From 362ecbd1cb5a4e7cd943ddc759d44cd2dba2bc6a Mon Sep 17 00:00:00 2001 From: Bronek Kozicki Date: Fri, 14 Nov 2025 17:30:56 +0000 Subject: [PATCH 001/105] fix: Apply object reserve for Vault pseudo-account (#5954) --- src/test/app/Vault_test.cpp | 18 ++++++++----- src/test/jtx/impl/vault.cpp | 1 - src/xrpld/app/tx/detail/VaultCreate.cpp | 12 +++------ src/xrpld/app/tx/detail/VaultCreate.h | 3 --- src/xrpld/app/tx/detail/VaultDelete.cpp | 34 +++++++++++++++++++++++-- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index 2ca525c036..4097b93786 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -1329,7 +1329,7 @@ class Vault_test : public beast::unit_test::suite Vault& vault) { auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); testcase("insufficient fee"); - env(tx, fee(env.current()->fees().base), ter(telINSUF_FEE_P)); + env(tx, fee(env.current()->fees().base - 1), ter(telINSUF_FEE_P)); }); testCase([this]( @@ -2074,6 +2074,10 @@ class Vault_test : public beast::unit_test::suite auto const sleMPT = env.le(mptoken); BEAST_EXPECT(sleMPT == nullptr); + // Use one reserve so the next transaction fails + env(ticket::create(owner, 1)); + env.close(); + // No reserve to create MPToken for asset in VaultWithdraw tx = vault.withdraw( {.depositor = owner, @@ -2091,7 +2095,7 @@ class Vault_test : public beast::unit_test::suite } }, {.requireAuth = false, - .initialXRP = acctReserve + incReserve * 4 - 1}); + .initialXRP = acctReserve + incReserve * 4 + 1}); testCase([this]( Env& env, @@ -2980,6 +2984,9 @@ class Vault_test : public beast::unit_test::suite env.le(keylet::line(owner, asset.raw().get())); BEAST_EXPECT(trustline == nullptr); + env(ticket::create(owner, 1)); + env.close(); + // Fail because not enough reserve to create trust line tx = vault.withdraw( {.depositor = owner, @@ -2995,7 +3002,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); }, - CaseArgs{.initialXRP = acctReserve + incReserve * 4 - 1}); + CaseArgs{.initialXRP = acctReserve + incReserve * 4 + 1}); testCase( [&, this]( @@ -3016,8 +3023,7 @@ class Vault_test : public beast::unit_test::suite env(pay(owner, charlie, asset(100))); env.close(); - // Use up some reserve on tickets - env(ticket::create(charlie, 2)); + env(ticket::create(charlie, 3)); env.close(); // Fail because not enough reserve to create MPToken for shares @@ -3035,7 +3041,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); }, - CaseArgs{.initialXRP = acctReserve + incReserve * 4 - 1}); + CaseArgs{.initialXRP = acctReserve + incReserve * 4 + 1}); testCase([&, this]( Env& env, diff --git a/src/test/jtx/impl/vault.cpp b/src/test/jtx/impl/vault.cpp index 8ec4422977..a1295ba887 100644 --- a/src/test/jtx/impl/vault.cpp +++ b/src/test/jtx/impl/vault.cpp @@ -19,7 +19,6 @@ Vault::create(CreateArgs const& args) jv[jss::TransactionType] = jss::VaultCreate; jv[jss::Account] = args.owner.human(); jv[jss::Asset] = to_json(args.asset); - jv[jss::Fee] = STAmount(env.current()->fees().increment).getJson(); if (args.flags) jv[jss::Flags] = *args.flags; return {jv, keylet}; diff --git a/src/xrpld/app/tx/detail/VaultCreate.cpp b/src/xrpld/app/tx/detail/VaultCreate.cpp index 8acb40ad41..393faa35f8 100644 --- a/src/xrpld/app/tx/detail/VaultCreate.cpp +++ b/src/xrpld/app/tx/detail/VaultCreate.cpp @@ -79,13 +79,6 @@ VaultCreate::preflight(PreflightContext const& ctx) return tesSUCCESS; } -XRPAmount -VaultCreate::calculateBaseFee(ReadView const& view, STTx const& tx) -{ - // One reserve increment is typically much greater than one base fee. - return calculateOwnerReserveFee(view, tx); -} - TER VaultCreate::preclaim(PreclaimContext const& ctx) { @@ -142,8 +135,9 @@ VaultCreate::doApply() if (auto ter = dirLink(view(), account_, vault)) return ter; - adjustOwnerCount(view(), owner, 1, j_); - auto ownerCount = owner->at(sfOwnerCount); + // We will create Vault and PseudoAccount, hence increase OwnerCount by 2 + adjustOwnerCount(view(), owner, 2, j_); + auto const ownerCount = owner->at(sfOwnerCount); if (mPriorBalance < view().fees().accountReserve(ownerCount)) return tecINSUFFICIENT_RESERVE; diff --git a/src/xrpld/app/tx/detail/VaultCreate.h b/src/xrpld/app/tx/detail/VaultCreate.h index b83dc190ac..987bbe7df4 100644 --- a/src/xrpld/app/tx/detail/VaultCreate.h +++ b/src/xrpld/app/tx/detail/VaultCreate.h @@ -23,9 +23,6 @@ public: static NotTEC preflight(PreflightContext const& ctx); - static XRPAmount - calculateBaseFee(ReadView const& view, STTx const& tx); - static TER preclaim(PreclaimContext const& ctx); diff --git a/src/xrpld/app/tx/detail/VaultDelete.cpp b/src/xrpld/app/tx/detail/VaultDelete.cpp index 93ab973e35..903b5a83a7 100644 --- a/src/xrpld/app/tx/detail/VaultDelete.cpp +++ b/src/xrpld/app/tx/detail/VaultDelete.cpp @@ -146,7 +146,35 @@ VaultDelete::doApply() return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE // Destroy the pseudo-account. - view().erase(view().peek(keylet::account(pseudoID))); + auto vaultPseudoSLE = view().peek(keylet::account(pseudoID)); + if (!vaultPseudoSLE || vaultPseudoSLE->at(~sfVaultID) != vault->key()) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + // Making the payment and removing the empty holding should have deleted any + // obligations associated with the vault or vault pseudo-account. + if (*vaultPseudoSLE->at(sfBalance)) + { + // LCOV_EXCL_START + JLOG(j_.error()) << "VaultDelete: pseudo-account has a balance"; + return tecHAS_OBLIGATIONS; + // LCOV_EXCL_STOP + } + if (vaultPseudoSLE->at(sfOwnerCount) != 0) + { + // LCOV_EXCL_START + JLOG(j_.error()) << "VaultDelete: pseudo-account still owns objects"; + return tecHAS_OBLIGATIONS; + // LCOV_EXCL_STOP + } + if (view().exists(keylet::ownerDir(pseudoID))) + { + // LCOV_EXCL_START + JLOG(j_.error()) << "VaultDelete: pseudo-account has a directory"; + return tecHAS_OBLIGATIONS; + // LCOV_EXCL_STOP + } + + view().erase(vaultPseudoSLE); // Remove the vault from its owner's directory. auto const ownerID = vault->at(sfOwner); @@ -170,7 +198,9 @@ VaultDelete::doApply() return tefBAD_LEDGER; // LCOV_EXCL_STOP } - adjustOwnerCount(view(), owner, -1, j_); + + // We are destroying Vault and PseudoAccount, hence decrease by 2 + adjustOwnerCount(view(), owner, -2, j_); // Destroy the vault. view().erase(vault); From 13a12c6402615c224e053764feaac7ed0286241a Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Fri, 14 Nov 2025 20:27:28 +0000 Subject: [PATCH 002/105] chore: Update nudb recipe to remove linker warnings (#6038) --- conan.lock | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/conan.lock b/conan.lock index 28bf67b1be..67c4dd8a10 100644 --- a/conan.lock +++ b/conan.lock @@ -6,18 +6,18 @@ "sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869", "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318", "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246", - "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1759820024.194", + "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1762797952.535", "re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976", "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614", "openssl/3.5.4#a1d5835cc6ed5c5b8f3cd5b9b5d24205%1760106486.594", - "nudb/2.0.9#c62cfd501e57055a7e0d8ee3d5e5427d%1756234237.107", + "nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1763150366.909", "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999", "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64", "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03", "libarchive/3.8.1#5cf685686322e906cb42706ab7e099a8%1756234256.696", "jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244", "grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958", - "doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1749889324.069", + "doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1762797941.757", "date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493", "c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915", "bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716", @@ -53,6 +53,9 @@ ], "lz4/[>=1.9.4 <2]": [ "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504" + ], + "sqlite3/3.44.2": [ + "sqlite3/3.49.1" ] }, "config_requires": [] From 2c187461cc892ff64b1693726ad73deb649987d3 Mon Sep 17 00:00:00 2001 From: Jingchen Date: Mon, 17 Nov 2025 14:02:10 +0000 Subject: [PATCH 003/105] refactor: Retire NegativeUNL amendment (#6033) Amendments activated for more than 2 years can be retired. This change retires the NegativeUNL amendment. --- include/xrpl/protocol/detail/features.macro | 2 +- src/test/consensus/NegativeUNL_test.cpp | 45 +-------------------- src/test/rpc/Feature_test.cpp | 3 +- src/xrpld/app/consensus/RCLConsensus.cpp | 7 +--- src/xrpld/app/ledger/detail/BuildLedger.cpp | 2 +- src/xrpld/app/misc/NetworkOPs.cpp | 3 +- src/xrpld/app/tx/detail/Change.cpp | 7 ---- 7 files changed, 9 insertions(+), 60 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 75b8db515d..dd66d8a34c 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -66,7 +66,6 @@ XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo XRPL_FEATURE(DisallowIncoming, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes) -XRPL_FEATURE(NegativeUNL, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes) @@ -130,6 +129,7 @@ XRPL_RETIRE_FEATURE(HardenedValidations) XRPL_RETIRE_FEATURE(ImmediateOfferKilled) XRPL_RETIRE_FEATURE(MultiSign) XRPL_RETIRE_FEATURE(MultiSignReserve) +XRPL_RETIRE_FEATURE(NegativeUNL) XRPL_RETIRE_FEATURE(NonFungibleTokensV1_1) XRPL_RETIRE_FEATURE(PayChan) XRPL_RETIRE_FEATURE(SortedDirectories) diff --git a/src/test/consensus/NegativeUNL_test.cpp b/src/test/consensus/NegativeUNL_test.cpp index 8457d0e2be..5b7eebed2f 100644 --- a/src/test/consensus/NegativeUNL_test.cpp +++ b/src/test/consensus/NegativeUNL_test.cpp @@ -15,7 +15,6 @@ namespace test { /* * This file implements the following negative UNL related tests: * -- test filling and applying ttUNL_MODIFY Tx and ledger update - * -- test ttUNL_MODIFY Tx failure without featureNegativeUNL amendment * -- test the NegativeUNLVote class. The test cases are split to multiple * test classes to allow parallel execution. * -- test the negativeUNLFilter function @@ -208,7 +207,7 @@ class NegativeUNL_test : public beast::unit_test::suite testcase("Create UNLModify Tx and apply to ledgers"); - jtx::Env env(*this, jtx::testable_amendments() | featureNegativeUNL); + jtx::Env env(*this, jtx::testable_amendments()); std::vector publicKeys = createPublicKeys(3); // genesis ledger auto l = std::make_shared( @@ -216,7 +215,6 @@ class NegativeUNL_test : public beast::unit_test::suite env.app().config(), std::vector{}, env.app().getNodeFamily()); - BEAST_EXPECT(l->rules().enabled(featureNegativeUNL)); // Record the public keys and ledger sequences of expected negative UNL // validators when we build the ledger history @@ -500,44 +498,6 @@ class NegativeUNL_test : public beast::unit_test::suite } }; -class NegativeUNLNoAmendment_test : public beast::unit_test::suite -{ - void - testNegativeUNLNoAmendment() - { - testcase("No negative UNL amendment"); - - jtx::Env env(*this, jtx::testable_amendments() - featureNegativeUNL); - std::vector publicKeys = createPublicKeys(1); - // genesis ledger - auto l = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); - BEAST_EXPECT(!l->rules().enabled(featureNegativeUNL)); - - // generate more ledgers - for (auto i = 0; i < 256 - 1; ++i) - { - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); - } - BEAST_EXPECT(l->seq() == 256); - auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]); - OpenView accum(&*l); - BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false)); - accum.apply(*l); - BEAST_EXPECT(negUnlSizeTest(l, 0, false, false)); - } - - void - run() override - { - testNegativeUNLNoAmendment(); - } -}; - /** * Utility class for creating validators and ledger history */ @@ -563,7 +523,7 @@ struct NetworkHistory }; NetworkHistory(beast::unit_test::suite& suite, Parameter const& p) - : env(suite, jtx::testable_amendments() | featureNegativeUNL) + : env(suite, jtx::testable_amendments()) , param(p) , validations(env.app().getValidations()) { @@ -1867,7 +1827,6 @@ class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite }; BEAST_DEFINE_TESTSUITE(NegativeUNL, consensus, ripple); -BEAST_DEFINE_TESTSUITE(NegativeUNLNoAmendment, consensus, ripple); BEAST_DEFINE_TESTSUITE(NegativeUNLVoteInternal, consensus, ripple); BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus, ripple); diff --git a/src/test/rpc/Feature_test.cpp b/src/test/rpc/Feature_test.cpp index 250c634007..10f82ac88d 100644 --- a/src/test/rpc/Feature_test.cpp +++ b/src/test/rpc/Feature_test.cpp @@ -124,7 +124,8 @@ class Feature_test : public beast::unit_test::suite featureToName(fixRemoveNFTokenAutoTrustLine) == "fixRemoveNFTokenAutoTrustLine"); BEAST_EXPECT(featureToName(featureFlow) == "Flow"); - BEAST_EXPECT(featureToName(featureNegativeUNL) == "NegativeUNL"); + BEAST_EXPECT( + featureToName(featureDeletableAccounts) == "DeletableAccounts"); BEAST_EXPECT( featureToName(fixIncludeKeyletFields) == "fixIncludeKeyletFields"); BEAST_EXPECT(featureToName(featureTokenEscrow) == "TokenEscrow"); diff --git a/src/xrpld/app/consensus/RCLConsensus.cpp b/src/xrpld/app/consensus/RCLConsensus.cpp index 7734ab790d..09584f2e77 100644 --- a/src/xrpld/app/consensus/RCLConsensus.cpp +++ b/src/xrpld/app/consensus/RCLConsensus.cpp @@ -346,9 +346,7 @@ RCLConsensus::Adaptor::onClose( prevLedger, validations, initialSet, j_); } } - else if ( - prevLedger->isVotingLedger() && - prevLedger->rules().enabled(featureNegativeUNL)) + else if (prevLedger->isVotingLedger()) { // previous ledger was a voting ledger, // so the current consensus session is for a flag ledger, @@ -1015,8 +1013,7 @@ RCLConsensus::Adaptor::preStartRound( inboundTransactions_.newRound(prevLgr.seq()); // Notify NegativeUNLVote that new validators are added - if (prevLgr.ledger_->rules().enabled(featureNegativeUNL) && - !nowTrusted.empty()) + if (!nowTrusted.empty()) nUnlVote_.newValidators(prevLgr.seq() + 1, nowTrusted); // propose only if we're in sync with the network (and validating) diff --git a/src/xrpld/app/ledger/detail/BuildLedger.cpp b/src/xrpld/app/ledger/detail/BuildLedger.cpp index 97824e3023..dd3593e1cf 100644 --- a/src/xrpld/app/ledger/detail/BuildLedger.cpp +++ b/src/xrpld/app/ledger/detail/BuildLedger.cpp @@ -28,7 +28,7 @@ buildLedgerImpl( { auto built = std::make_shared(*parent, closeTime); - if (built->isFlagLedger() && built->rules().enabled(featureNegativeUNL)) + if (built->isFlagLedger()) { built->updateNegativeUNL(); } diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index ebe539523b..963f3dc3ea 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -2063,8 +2063,7 @@ NetworkOPsImp::beginConsensus( "ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches " "hash"); - if (prevLedger->rules().enabled(featureNegativeUNL)) - app_.validators().setNegativeUNL(prevLedger->negativeUNL()); + app_.validators().setNegativeUNL(prevLedger->negativeUNL()); TrustChanges const changes = app_.validators().updateTrusted( app_.getValidations().getCurrentNodeIDs(), closingInfo.parentCloseTime, diff --git a/src/xrpld/app/tx/detail/Change.cpp b/src/xrpld/app/tx/detail/Change.cpp index 4832287c2e..43db9ae13c 100644 --- a/src/xrpld/app/tx/detail/Change.cpp +++ b/src/xrpld/app/tx/detail/Change.cpp @@ -51,13 +51,6 @@ Transactor::invokePreflight(PreflightContext const& ctx) return temBAD_SEQUENCE; } - if (ctx.tx.getTxnType() == ttUNL_MODIFY && - !ctx.rules.enabled(featureNegativeUNL)) - { - JLOG(ctx.j.warn()) << "Change: NegativeUNL not enabled"; - return temDISABLED; - } - return tesSUCCESS; } From 77b7cef5a74b9464e9bcbfd9180996647ad34e3b Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 17 Nov 2025 14:31:19 -0500 Subject: [PATCH 004/105] ci: Use new Debian Trixie images (#6034) This change uses the new Debian Trixie CI images added by XRPLF/ci#83. --- .github/scripts/strategy-matrix/generate.py | 4 +- .github/scripts/strategy-matrix/linux.json | 46 +++++++++++++++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/.github/scripts/strategy-matrix/generate.py b/.github/scripts/strategy-matrix/generate.py index c762d61ccd..d8f2509e33 100755 --- a/.github/scripts/strategy-matrix/generate.py +++ b/.github/scripts/strategy-matrix/generate.py @@ -130,8 +130,8 @@ def generate_strategy_matrix(all: bool, config: Config) -> list: if os['distro_name'] == 'rhel' and architecture['platform'] == 'linux/arm64': continue - # We skip all clang-20 on arm64 due to boost 1.86 build error - if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-20' and architecture['platform'] == 'linux/arm64': + # We skip all clang 20+ on arm64 due to Boost build error. + if f'{os['compiler_name']}' in ['clang-20', 'clang-21'] and architecture['platform'] == 'linux/arm64': continue # Enable code coverage for Debian Bookworm using GCC 15 in Debug and no diff --git a/.github/scripts/strategy-matrix/linux.json b/.github/scripts/strategy-matrix/linux.json index a8fe90e6ac..748ee031c9 100644 --- a/.github/scripts/strategy-matrix/linux.json +++ b/.github/scripts/strategy-matrix/linux.json @@ -15,63 +15,91 @@ "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "12", - "image_sha": "e1782cd" + "image_sha": "0525eae" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "13", - "image_sha": "e1782cd" + "image_sha": "0525eae" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "e1782cd" + "image_sha": "0525eae" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "15", - "image_sha": "e1782cd" + "image_sha": "0525eae" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "16", - "image_sha": "e1782cd" + "image_sha": "0525eae" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "17", - "image_sha": "e1782cd" + "image_sha": "0525eae" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "18", - "image_sha": "e1782cd" + "image_sha": "0525eae" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "19", - "image_sha": "e1782cd" + "image_sha": "0525eae" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "20", - "image_sha": "e1782cd" + "image_sha": "0525eae" + }, + { + "distro_name": "debian", + "distro_version": "trixie", + "compiler_name": "gcc", + "compiler_version": "14", + "image_sha": "0525eae" + }, + { + "distro_name": "debian", + "distro_version": "trixie", + "compiler_name": "gcc", + "compiler_version": "15", + "image_sha": "0525eae" + }, + { + "distro_name": "debian", + "distro_version": "trixie", + "compiler_name": "clang", + "compiler_version": "20", + "image_sha": "0525eae" + }, + { + "distro_name": "debian", + "distro_version": "trixie", + "compiler_name": "clang", + "compiler_version": "21", + "image_sha": "0525eae" }, { "distro_name": "rhel", From 3fb6acd29ea9e4c96c32883b2badab0566b2aeeb Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 17 Nov 2025 16:54:13 -0500 Subject: [PATCH 005/105] ci: Fix filtering out of Clang 20+ on ARM (#6046) This change fixes the strategy matrix check to filter out the Clang 20+ on ARM, which still fail due to problems with Boost. --- .github/scripts/strategy-matrix/generate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/strategy-matrix/generate.py b/.github/scripts/strategy-matrix/generate.py index d8f2509e33..230c18c2df 100755 --- a/.github/scripts/strategy-matrix/generate.py +++ b/.github/scripts/strategy-matrix/generate.py @@ -131,7 +131,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list: continue # We skip all clang 20+ on arm64 due to Boost build error. - if f'{os['compiler_name']}' in ['clang-20', 'clang-21'] and architecture['platform'] == 'linux/arm64': + if f'{os['compiler_name']}-{os['compiler_version']}' in ['clang-20', 'clang-21'] and architecture['platform'] == 'linux/arm64': continue # Enable code coverage for Debian Bookworm using GCC 15 in Debug and no From d9c27da529a6cd75f30de145069b32610564dc3d Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 19 Nov 2025 02:14:39 +0530 Subject: [PATCH 006/105] refactor: split up `RPCHelpers.h` into two (#6047) This PR splits `RPCHelpers.h` into two files, by moving out all the ledger-fetching-related functions into a separate file, `RPCLedgerHelpers.h`. It also moves `getAccountObjects` to `AccountObjects.h`, since it is only used in that one place. --- src/xrpld/app/rdb/RelationalDatabase.h | 2 +- src/xrpld/rpc/detail/RPCHelpers.cpp | 625 ------------------ src/xrpld/rpc/detail/RPCHelpers.h | 80 --- src/xrpld/rpc/detail/RPCLedgerHelpers.cpp | 458 +++++++++++++ src/xrpld/rpc/detail/RPCLedgerHelpers.h | 96 +++ src/xrpld/rpc/handlers/AMMInfo.cpp | 1 + src/xrpld/rpc/handlers/AccountChannels.cpp | 1 + .../rpc/handlers/AccountCurrenciesHandler.cpp | 2 +- src/xrpld/rpc/handlers/AccountInfo.cpp | 1 + src/xrpld/rpc/handlers/AccountLines.cpp | 1 + src/xrpld/rpc/handlers/AccountObjects.cpp | 195 +++++- src/xrpld/rpc/handlers/AccountOffers.cpp | 1 + src/xrpld/rpc/handlers/BookOffers.cpp | 1 + src/xrpld/rpc/handlers/DepositAuthorized.cpp | 2 +- src/xrpld/rpc/handlers/GatewayBalances.cpp | 2 +- src/xrpld/rpc/handlers/GetAggregatePrice.cpp | 2 +- src/xrpld/rpc/handlers/LedgerData.cpp | 1 + src/xrpld/rpc/handlers/LedgerDiff.cpp | 2 +- src/xrpld/rpc/handlers/LedgerEntry.cpp | 2 +- src/xrpld/rpc/handlers/LedgerHandler.cpp | 2 +- src/xrpld/rpc/handlers/LedgerHeader.cpp | 2 +- src/xrpld/rpc/handlers/LedgerRequest.cpp | 2 +- src/xrpld/rpc/handlers/NFTOffers.cpp | 1 + src/xrpld/rpc/handlers/NoRippleCheck.cpp | 1 + src/xrpld/rpc/handlers/RipplePathFind.cpp | 2 +- src/xrpld/rpc/handlers/TransactionEntry.cpp | 2 +- src/xrpld/rpc/handlers/VaultInfo.cpp | 2 +- 27 files changed, 770 insertions(+), 719 deletions(-) create mode 100644 src/xrpld/rpc/detail/RPCLedgerHelpers.cpp create mode 100644 src/xrpld/rpc/detail/RPCLedgerHelpers.h diff --git a/src/xrpld/app/rdb/RelationalDatabase.h b/src/xrpld/app/rdb/RelationalDatabase.h index 570bce2b95..18a5536cf6 100644 --- a/src/xrpld/app/rdb/RelationalDatabase.h +++ b/src/xrpld/app/rdb/RelationalDatabase.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include diff --git a/src/xrpld/rpc/detail/RPCHelpers.cpp b/src/xrpld/rpc/detail/RPCHelpers.cpp index d9f640d537..6d1314ff51 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCHelpers.cpp @@ -130,513 +130,6 @@ isRelatedToAccount( return false; } -bool -getAccountObjects( - ReadView const& ledger, - AccountID const& account, - std::optional> const& typeFilter, - uint256 dirIndex, - uint256 entryIndex, - std::uint32_t const limit, - Json::Value& jvResult) -{ - // check if dirIndex is valid - if (!dirIndex.isZero() && !ledger.read({ltDIR_NODE, dirIndex})) - return false; - - auto typeMatchesFilter = [](std::vector const& typeFilter, - LedgerEntryType ledgerType) { - auto it = std::find(typeFilter.begin(), typeFilter.end(), ledgerType); - return it != typeFilter.end(); - }; - - // if dirIndex != 0, then all NFTs have already been returned. only - // iterate NFT pages if the filter says so AND dirIndex == 0 - bool iterateNFTPages = - (!typeFilter.has_value() || - typeMatchesFilter(typeFilter.value(), ltNFTOKEN_PAGE)) && - dirIndex == beast::zero; - - Keylet const firstNFTPage = keylet::nftpage_min(account); - - // we need to check the marker to see if it is an NFTTokenPage index. - if (iterateNFTPages && entryIndex != beast::zero) - { - // if it is we will try to iterate the pages up to the limit - // and then change over to the owner directory - - if (firstNFTPage.key != (entryIndex & ~nft::pageMask)) - iterateNFTPages = false; - } - - auto& jvObjects = (jvResult[jss::account_objects] = Json::arrayValue); - - // this is a mutable version of limit, used to seamlessly switch - // to iterating directory entries when nftokenpages are exhausted - uint32_t mlimit = limit; - - // iterate NFTokenPages preferentially - if (iterateNFTPages) - { - Keylet const first = entryIndex == beast::zero - ? firstNFTPage - : Keylet{ltNFTOKEN_PAGE, entryIndex}; - - Keylet const last = keylet::nftpage_max(account); - - // current key - uint256 ck = ledger.succ(first.key, last.key.next()).value_or(last.key); - - // current page - auto cp = ledger.read(Keylet{ltNFTOKEN_PAGE, ck}); - - while (cp) - { - jvObjects.append(cp->getJson(JsonOptions::none)); - auto const npm = (*cp)[~sfNextPageMin]; - if (npm) - cp = ledger.read(Keylet(ltNFTOKEN_PAGE, *npm)); - else - cp = nullptr; - - if (--mlimit == 0) - { - if (cp) - { - jvResult[jss::limit] = limit; - jvResult[jss::marker] = std::string("0,") + to_string(ck); - return true; - } - } - - if (!npm) - break; - - ck = *npm; - } - - // if execution reaches here then we're about to transition - // to iterating the root directory (and the conventional - // behaviour of this RPC function.) Therefore we should - // zero entryIndex so as not to terribly confuse things. - entryIndex = beast::zero; - } - - auto const root = keylet::ownerDir(account); - auto found = false; - - if (dirIndex.isZero()) - { - dirIndex = root.key; - found = true; - } - - auto dir = ledger.read({ltDIR_NODE, dirIndex}); - if (!dir) - { - // it's possible the user had nftoken pages but no - // directory entries. If there's no nftoken page, we will - // give empty array for account_objects. - if (mlimit >= limit) - jvResult[jss::account_objects] = Json::arrayValue; - - // non-zero dirIndex validity was checked in the beginning of this - // function; by this point, it should be zero. This function returns - // true regardless of nftoken page presence; if absent, account_objects - // is already set as an empty array. Notice we will only return false in - // this function when entryIndex can not be found, indicating an invalid - // marker error. - return true; - } - - std::uint32_t i = 0; - for (;;) - { - auto const& entries = dir->getFieldV256(sfIndexes); - auto iter = entries.begin(); - - if (!found) - { - iter = std::find(iter, entries.end(), entryIndex); - if (iter == entries.end()) - return false; - - found = true; - } - - // it's possible that the returned NFTPages exactly filled the - // response. Check for that condition. - if (i == mlimit && mlimit < limit) - { - jvResult[jss::limit] = limit; - jvResult[jss::marker] = - to_string(dirIndex) + ',' + to_string(*iter); - return true; - } - - for (; iter != entries.end(); ++iter) - { - auto const sleNode = ledger.read(keylet::child(*iter)); - - if (!typeFilter.has_value() || - typeMatchesFilter(typeFilter.value(), sleNode->getType())) - { - jvObjects.append(sleNode->getJson(JsonOptions::none)); - } - - if (++i == mlimit) - { - if (++iter != entries.end()) - { - jvResult[jss::limit] = limit; - jvResult[jss::marker] = - to_string(dirIndex) + ',' + to_string(*iter); - return true; - } - - break; - } - } - - auto const nodeIndex = dir->getFieldU64(sfIndexNext); - if (nodeIndex == 0) - return true; - - dirIndex = keylet::page(root, nodeIndex).key; - dir = ledger.read({ltDIR_NODE, dirIndex}); - if (!dir) - return true; - - if (i == mlimit) - { - auto const& e = dir->getFieldV256(sfIndexes); - if (!e.empty()) - { - jvResult[jss::limit] = limit; - jvResult[jss::marker] = - to_string(dirIndex) + ',' + to_string(*e.begin()); - } - - return true; - } - } -} - -namespace { - -bool -isValidatedOld(LedgerMaster& ledgerMaster, bool standalone) -{ - if (standalone) - return false; - - return ledgerMaster.getValidatedLedgerAge() > Tuning::maxValidatedLedgerAge; -} - -template -Status -ledgerFromRequest(T& ledger, JsonContext& context) -{ - ledger.reset(); - - auto& params = context.params; - - auto indexValue = params[jss::ledger_index]; - auto hashValue = params[jss::ledger_hash]; - - // We need to support the legacy "ledger" field. - auto& legacyLedger = params[jss::ledger]; - if (legacyLedger) - { - if (legacyLedger.asString().size() > 12) - hashValue = legacyLedger; - else - indexValue = legacyLedger; - } - - if (!hashValue.isNull()) - { - if (!hashValue.isString()) - return {rpcINVALID_PARAMS, "ledgerHashNotString"}; - - uint256 ledgerHash; - if (!ledgerHash.parseHex(hashValue.asString())) - return {rpcINVALID_PARAMS, "ledgerHashMalformed"}; - return getLedger(ledger, ledgerHash, context); - } - - if (!indexValue.isConvertibleTo(Json::stringValue)) - return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; - - auto const index = indexValue.asString(); - - if (index == "current" || index.empty()) - return getLedger(ledger, LedgerShortcut::CURRENT, context); - - if (index == "validated") - return getLedger(ledger, LedgerShortcut::VALIDATED, context); - - if (index == "closed") - return getLedger(ledger, LedgerShortcut::CLOSED, context); - - std::uint32_t val; - if (!beast::lexicalCastChecked(val, index)) - return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; - - return getLedger(ledger, val, context); -} -} // namespace - -template -Status -ledgerFromRequest(T& ledger, GRPCContext& context) -{ - R& request = context.params; - return ledgerFromSpecifier(ledger, request.ledger(), context); -} - -// explicit instantiation of above function -template Status -ledgerFromRequest<>( - std::shared_ptr&, - GRPCContext&); - -// explicit instantiation of above function -template Status -ledgerFromRequest<>( - std::shared_ptr&, - GRPCContext&); - -// explicit instantiation of above function -template Status -ledgerFromRequest<>( - std::shared_ptr&, - GRPCContext&); - -template -Status -ledgerFromSpecifier( - T& ledger, - org::xrpl::rpc::v1::LedgerSpecifier const& specifier, - Context& context) -{ - ledger.reset(); - - using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase; - LedgerCase ledgerCase = specifier.ledger_case(); - switch (ledgerCase) - { - case LedgerCase::kHash: { - if (auto hash = uint256::fromVoidChecked(specifier.hash())) - { - return getLedger(ledger, *hash, context); - } - return {rpcINVALID_PARAMS, "ledgerHashMalformed"}; - } - case LedgerCase::kSequence: - return getLedger(ledger, specifier.sequence(), context); - case LedgerCase::kShortcut: - [[fallthrough]]; - case LedgerCase::LEDGER_NOT_SET: { - auto const shortcut = specifier.shortcut(); - if (shortcut == - org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED) - { - return getLedger(ledger, LedgerShortcut::VALIDATED, context); - } - else - { - if (shortcut == - org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT || - shortcut == - org::xrpl::rpc::v1::LedgerSpecifier:: - SHORTCUT_UNSPECIFIED) - { - return getLedger(ledger, LedgerShortcut::CURRENT, context); - } - else if ( - shortcut == - org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED) - { - return getLedger(ledger, LedgerShortcut::CLOSED, context); - } - } - } - } - - return Status::OK; -} - -template -Status -getLedger(T& ledger, uint256 const& ledgerHash, Context& context) -{ - ledger = context.ledgerMaster.getLedgerByHash(ledgerHash); - if (ledger == nullptr) - return {rpcLGR_NOT_FOUND, "ledgerNotFound"}; - return Status::OK; -} - -template -Status -getLedger(T& ledger, uint32_t ledgerIndex, Context& context) -{ - ledger = context.ledgerMaster.getLedgerBySeq(ledgerIndex); - if (ledger == nullptr) - { - auto cur = context.ledgerMaster.getCurrentLedger(); - if (cur->info().seq == ledgerIndex) - { - ledger = cur; - } - } - - if (ledger == nullptr) - return {rpcLGR_NOT_FOUND, "ledgerNotFound"}; - - if (ledger->info().seq > context.ledgerMaster.getValidLedgerIndex() && - isValidatedOld(context.ledgerMaster, context.app.config().standalone())) - { - ledger.reset(); - if (context.apiVersion == 1) - return {rpcNO_NETWORK, "InsufficientNetworkMode"}; - return {rpcNOT_SYNCED, "notSynced"}; - } - - return Status::OK; -} - -template -Status -getLedger(T& ledger, LedgerShortcut shortcut, Context& context) -{ - if (isValidatedOld(context.ledgerMaster, context.app.config().standalone())) - { - if (context.apiVersion == 1) - return {rpcNO_NETWORK, "InsufficientNetworkMode"}; - return {rpcNOT_SYNCED, "notSynced"}; - } - - if (shortcut == LedgerShortcut::VALIDATED) - { - ledger = context.ledgerMaster.getValidatedLedger(); - if (ledger == nullptr) - { - if (context.apiVersion == 1) - return {rpcNO_NETWORK, "InsufficientNetworkMode"}; - return {rpcNOT_SYNCED, "notSynced"}; - } - - XRPL_ASSERT( - !ledger->open(), "ripple::RPC::getLedger : validated is not open"); - } - else - { - if (shortcut == LedgerShortcut::CURRENT) - { - ledger = context.ledgerMaster.getCurrentLedger(); - XRPL_ASSERT( - ledger->open(), "ripple::RPC::getLedger : current is open"); - } - else if (shortcut == LedgerShortcut::CLOSED) - { - ledger = context.ledgerMaster.getClosedLedger(); - XRPL_ASSERT( - !ledger->open(), "ripple::RPC::getLedger : closed is not open"); - } - else - { - return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; - } - - if (ledger == nullptr) - { - if (context.apiVersion == 1) - return {rpcNO_NETWORK, "InsufficientNetworkMode"}; - return {rpcNOT_SYNCED, "notSynced"}; - } - - static auto const minSequenceGap = 10; - - if (ledger->info().seq + minSequenceGap < - context.ledgerMaster.getValidLedgerIndex()) - { - ledger.reset(); - if (context.apiVersion == 1) - return {rpcNO_NETWORK, "InsufficientNetworkMode"}; - return {rpcNOT_SYNCED, "notSynced"}; - } - } - return Status::OK; -} - -// Explicit instantiation of above three functions -template Status -getLedger<>(std::shared_ptr&, uint32_t, Context&); - -template Status -getLedger<>( - std::shared_ptr&, - LedgerShortcut shortcut, - Context&); - -template Status -getLedger<>(std::shared_ptr&, uint256 const&, Context&); - -// The previous version of the lookupLedger command would accept the -// "ledger_index" argument as a string and silently treat it as a request to -// return the current ledger which, while not strictly wrong, could cause a lot -// of confusion. -// -// The code now robustly validates the input and ensures that the only possible -// values for the "ledger_index" parameter are the index of a ledger passed as -// an integer or one of the strings "current", "closed" or "validated". -// Additionally, the code ensures that the value passed in "ledger_hash" is a -// string and a valid hash. Invalid values will return an appropriate error -// code. -// -// In the absence of the "ledger_hash" or "ledger_index" parameters, the code -// assumes that "ledger_index" has the value "current". -// -// Returns a Json::objectValue. If there was an error, it will be in that -// return value. Otherwise, the object contains the field "validated" and -// optionally the fields "ledger_hash", "ledger_index" and -// "ledger_current_index", if they are defined. -Status -lookupLedger( - std::shared_ptr& ledger, - JsonContext& context, - Json::Value& result) -{ - if (auto status = ledgerFromRequest(ledger, context)) - return status; - - auto& info = ledger->info(); - - if (!ledger->open()) - { - result[jss::ledger_hash] = to_string(info.hash); - result[jss::ledger_index] = info.seq; - } - else - { - result[jss::ledger_current_index] = info.seq; - } - - result[jss::validated] = context.ledgerMaster.isValidated(*ledger); - return Status::OK; -} - -Json::Value -lookupLedger(std::shared_ptr& ledger, JsonContext& context) -{ - Json::Value result; - if (auto status = lookupLedger(ledger, context, result)) - status.inject(result); - - return result; -} - hash_set parseAccountIds(Json::Value const& jvArray) { @@ -988,123 +481,5 @@ isAccountObjectsValidType(LedgerEntryType const& type) } } -std::variant, Json::Value> -getLedgerByContext(RPC::JsonContext& context) -{ - auto const hasHash = context.params.isMember(jss::ledger_hash); - auto const hasIndex = context.params.isMember(jss::ledger_index); - std::uint32_t ledgerIndex = 0; - - auto& ledgerMaster = context.app.getLedgerMaster(); - LedgerHash ledgerHash; - - if ((hasHash && hasIndex) || !(hasHash || hasIndex)) - { - return RPC::make_param_error( - "Exactly one of ledger_hash and ledger_index can be set."); - } - - context.loadType = Resource::feeHeavyBurdenRPC; - - if (hasHash) - { - auto const& jsonHash = context.params[jss::ledger_hash]; - if (!jsonHash.isString() || !ledgerHash.parseHex(jsonHash.asString())) - return RPC::invalid_field_error(jss::ledger_hash); - } - else - { - auto const& jsonIndex = context.params[jss::ledger_index]; - if (!jsonIndex.isInt()) - return RPC::invalid_field_error(jss::ledger_index); - - // We need a validated ledger to get the hash from the sequence - if (ledgerMaster.getValidatedLedgerAge() > - RPC::Tuning::maxValidatedLedgerAge) - { - if (context.apiVersion == 1) - return rpcError(rpcNO_CURRENT); - return rpcError(rpcNOT_SYNCED); - } - - ledgerIndex = jsonIndex.asInt(); - auto ledger = ledgerMaster.getValidatedLedger(); - - if (ledgerIndex >= ledger->info().seq) - return RPC::make_param_error("Ledger index too large"); - if (ledgerIndex <= 0) - return RPC::make_param_error("Ledger index too small"); - - auto const j = context.app.journal("RPCHandler"); - // Try to get the hash of the desired ledger from the validated - // ledger - auto neededHash = hashOfSeq(*ledger, ledgerIndex, j); - if (!neededHash) - { - // Find a ledger more likely to have the hash of the desired - // ledger - auto const refIndex = getCandidateLedger(ledgerIndex); - auto refHash = hashOfSeq(*ledger, refIndex, j); - XRPL_ASSERT( - refHash, - "ripple::RPC::getLedgerByContext : nonzero ledger hash"); - - ledger = ledgerMaster.getLedgerByHash(*refHash); - if (!ledger) - { - // We don't have the ledger we need to figure out which - // ledger they want. Try to get it. - - if (auto il = context.app.getInboundLedgers().acquire( - *refHash, refIndex, InboundLedger::Reason::GENERIC)) - { - Json::Value jvResult = RPC::make_error( - rpcLGR_NOT_FOUND, - "acquiring ledger containing requested index"); - jvResult[jss::acquiring] = - getJson(LedgerFill(*il, &context)); - return jvResult; - } - - if (auto il = context.app.getInboundLedgers().find(*refHash)) - { - Json::Value jvResult = RPC::make_error( - rpcLGR_NOT_FOUND, - "acquiring ledger containing requested index"); - jvResult[jss::acquiring] = il->getJson(0); - return jvResult; - } - - // Likely the app is shutting down - return Json::Value(); - } - - neededHash = hashOfSeq(*ledger, ledgerIndex, j); - } - XRPL_ASSERT( - neededHash, - "ripple::RPC::getLedgerByContext : nonzero needed hash"); - ledgerHash = neededHash ? *neededHash : beast::zero; // kludge - } - - // Try to get the desired ledger - // Verify all nodes even if we think we have it - auto ledger = context.app.getInboundLedgers().acquire( - ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC); - - // In standalone mode, accept the ledger from the ledger cache - if (!ledger && context.app.config().standalone()) - ledger = ledgerMaster.getLedgerByHash(ledgerHash); - - if (ledger) - return ledger; - - if (auto il = context.app.getInboundLedgers().find(ledgerHash)) - return il->getJson(0); - - return RPC::make_error( - rpcNOT_READY, "findCreate failed to return an inbound ledger"); -} - } // namespace RPC } // namespace ripple diff --git a/src/xrpld/rpc/detail/RPCHelpers.h b/src/xrpld/rpc/detail/RPCHelpers.h index 9ee4376411..808b975de3 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.h +++ b/src/xrpld/rpc/detail/RPCHelpers.h @@ -73,81 +73,6 @@ isRelatedToAccount( std::shared_ptr const& sle, AccountID const& accountID); -/** Gathers all objects for an account in a ledger. - @param ledger Ledger to search account objects. - @param account AccountID to find objects for. - @param typeFilter Gathers objects of these types. empty gathers all types. - @param dirIndex Begin gathering account objects from this directory. - @param entryIndex Begin gathering objects from this directory node. - @param limit Maximum number of objects to find. - @param jvResult A JSON result that holds the request objects. -*/ -bool -getAccountObjects( - ReadView const& ledger, - AccountID const& account, - std::optional> const& typeFilter, - uint256 dirIndex, - uint256 entryIndex, - std::uint32_t const limit, - Json::Value& jvResult); - -/** Get ledger by hash - If there is no error in the return value, the ledger pointer will have - been filled -*/ -template -Status -getLedger(T& ledger, uint256 const& ledgerHash, Context& context); - -/** Get ledger by sequence - If there is no error in the return value, the ledger pointer will have - been filled -*/ -template -Status -getLedger(T& ledger, uint32_t ledgerIndex, Context& context); - -enum LedgerShortcut { CURRENT, CLOSED, VALIDATED }; -/** Get ledger specified in shortcut. - If there is no error in the return value, the ledger pointer will have - been filled -*/ -template -Status -getLedger(T& ledger, LedgerShortcut shortcut, Context& context); - -/** Look up a ledger from a request and fill a Json::Result with either - an error, or data representing a ledger. - - If there is no error in the return value, then the ledger pointer will have - been filled. -*/ -Json::Value -lookupLedger(std::shared_ptr&, JsonContext&); - -/** Look up a ledger from a request and fill a Json::Result with the data - representing a ledger. - - If the returned Status is OK, the ledger pointer will have been filled. -*/ -Status -lookupLedger( - std::shared_ptr&, - JsonContext&, - Json::Value& result); - -template -Status -ledgerFromRequest(T& ledger, GRPCContext& context); - -template -Status -ledgerFromSpecifier( - T& ledger, - org::xrpl::rpc::v1::LedgerSpecifier const& specifier, - Context& context); - hash_set parseAccountIds(Json::Value const& jvArray); @@ -194,11 +119,6 @@ chooseLedgerEntryType(Json::Value const& params); bool isAccountObjectsValidType(LedgerEntryType const& type); -/** Return a ledger based on ledger_hash or ledger_index, - or an RPC error */ -std::variant, Json::Value> -getLedgerByContext(RPC::JsonContext& context); - std::optional> keypairForSignature( Json::Value const& params, diff --git a/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp b/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp new file mode 100644 index 0000000000..8ba7eeddcd --- /dev/null +++ b/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp @@ -0,0 +1,458 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace ripple { +namespace RPC { + +namespace { + +bool +isValidatedOld(LedgerMaster& ledgerMaster, bool standalone) +{ + if (standalone) + return false; + + return ledgerMaster.getValidatedLedgerAge() > Tuning::maxValidatedLedgerAge; +} + +template +Status +ledgerFromRequest(T& ledger, JsonContext& context) +{ + ledger.reset(); + + auto& params = context.params; + + auto indexValue = params[jss::ledger_index]; + auto hashValue = params[jss::ledger_hash]; + + // We need to support the legacy "ledger" field. + auto& legacyLedger = params[jss::ledger]; + if (legacyLedger) + { + if (legacyLedger.asString().size() > 12) + hashValue = legacyLedger; + else + indexValue = legacyLedger; + } + + if (!hashValue.isNull()) + { + if (!hashValue.isString()) + return {rpcINVALID_PARAMS, "ledgerHashNotString"}; + + uint256 ledgerHash; + if (!ledgerHash.parseHex(hashValue.asString())) + return {rpcINVALID_PARAMS, "ledgerHashMalformed"}; + return getLedger(ledger, ledgerHash, context); + } + + if (!indexValue.isConvertibleTo(Json::stringValue)) + return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; + + auto const index = indexValue.asString(); + + if (index == "current" || index.empty()) + return getLedger(ledger, LedgerShortcut::CURRENT, context); + + if (index == "validated") + return getLedger(ledger, LedgerShortcut::VALIDATED, context); + + if (index == "closed") + return getLedger(ledger, LedgerShortcut::CLOSED, context); + + std::uint32_t val; + if (!beast::lexicalCastChecked(val, index)) + return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; + + return getLedger(ledger, val, context); +} +} // namespace + +template +Status +ledgerFromRequest(T& ledger, GRPCContext& context) +{ + R& request = context.params; + return ledgerFromSpecifier(ledger, request.ledger(), context); +} + +// explicit instantiation of above function +template Status +ledgerFromRequest<>( + std::shared_ptr&, + GRPCContext&); + +// explicit instantiation of above function +template Status +ledgerFromRequest<>( + std::shared_ptr&, + GRPCContext&); + +// explicit instantiation of above function +template Status +ledgerFromRequest<>( + std::shared_ptr&, + GRPCContext&); + +template +Status +ledgerFromSpecifier( + T& ledger, + org::xrpl::rpc::v1::LedgerSpecifier const& specifier, + Context& context) +{ + ledger.reset(); + + using LedgerCase = org::xrpl::rpc::v1::LedgerSpecifier::LedgerCase; + LedgerCase ledgerCase = specifier.ledger_case(); + switch (ledgerCase) + { + case LedgerCase::kHash: { + if (auto hash = uint256::fromVoidChecked(specifier.hash())) + { + return getLedger(ledger, *hash, context); + } + return {rpcINVALID_PARAMS, "ledgerHashMalformed"}; + } + case LedgerCase::kSequence: + return getLedger(ledger, specifier.sequence(), context); + case LedgerCase::kShortcut: + [[fallthrough]]; + case LedgerCase::LEDGER_NOT_SET: { + auto const shortcut = specifier.shortcut(); + if (shortcut == + org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED) + { + return getLedger(ledger, LedgerShortcut::VALIDATED, context); + } + else + { + if (shortcut == + org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CURRENT || + shortcut == + org::xrpl::rpc::v1::LedgerSpecifier:: + SHORTCUT_UNSPECIFIED) + { + return getLedger(ledger, LedgerShortcut::CURRENT, context); + } + else if ( + shortcut == + org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED) + { + return getLedger(ledger, LedgerShortcut::CLOSED, context); + } + } + } + } + + return Status::OK; +} + +template +Status +getLedger(T& ledger, uint256 const& ledgerHash, Context& context) +{ + ledger = context.ledgerMaster.getLedgerByHash(ledgerHash); + if (ledger == nullptr) + return {rpcLGR_NOT_FOUND, "ledgerNotFound"}; + return Status::OK; +} + +template +Status +getLedger(T& ledger, uint32_t ledgerIndex, Context& context) +{ + ledger = context.ledgerMaster.getLedgerBySeq(ledgerIndex); + if (ledger == nullptr) + { + auto cur = context.ledgerMaster.getCurrentLedger(); + if (cur->info().seq == ledgerIndex) + { + ledger = cur; + } + } + + if (ledger == nullptr) + return {rpcLGR_NOT_FOUND, "ledgerNotFound"}; + + if (ledger->info().seq > context.ledgerMaster.getValidLedgerIndex() && + isValidatedOld(context.ledgerMaster, context.app.config().standalone())) + { + ledger.reset(); + if (context.apiVersion == 1) + return {rpcNO_NETWORK, "InsufficientNetworkMode"}; + return {rpcNOT_SYNCED, "notSynced"}; + } + + return Status::OK; +} + +template +Status +getLedger(T& ledger, LedgerShortcut shortcut, Context& context) +{ + if (isValidatedOld(context.ledgerMaster, context.app.config().standalone())) + { + if (context.apiVersion == 1) + return {rpcNO_NETWORK, "InsufficientNetworkMode"}; + return {rpcNOT_SYNCED, "notSynced"}; + } + + if (shortcut == LedgerShortcut::VALIDATED) + { + ledger = context.ledgerMaster.getValidatedLedger(); + if (ledger == nullptr) + { + if (context.apiVersion == 1) + return {rpcNO_NETWORK, "InsufficientNetworkMode"}; + return {rpcNOT_SYNCED, "notSynced"}; + } + + XRPL_ASSERT( + !ledger->open(), "ripple::RPC::getLedger : validated is not open"); + } + else + { + if (shortcut == LedgerShortcut::CURRENT) + { + ledger = context.ledgerMaster.getCurrentLedger(); + XRPL_ASSERT( + ledger->open(), "ripple::RPC::getLedger : current is open"); + } + else if (shortcut == LedgerShortcut::CLOSED) + { + ledger = context.ledgerMaster.getClosedLedger(); + XRPL_ASSERT( + !ledger->open(), "ripple::RPC::getLedger : closed is not open"); + } + else + { + return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; + } + + if (ledger == nullptr) + { + if (context.apiVersion == 1) + return {rpcNO_NETWORK, "InsufficientNetworkMode"}; + return {rpcNOT_SYNCED, "notSynced"}; + } + + static auto const minSequenceGap = 10; + + if (ledger->info().seq + minSequenceGap < + context.ledgerMaster.getValidLedgerIndex()) + { + ledger.reset(); + if (context.apiVersion == 1) + return {rpcNO_NETWORK, "InsufficientNetworkMode"}; + return {rpcNOT_SYNCED, "notSynced"}; + } + } + return Status::OK; +} + +// Explicit instantiation of above three functions +template Status +getLedger<>(std::shared_ptr&, uint32_t, Context&); + +template Status +getLedger<>( + std::shared_ptr&, + LedgerShortcut shortcut, + Context&); + +template Status +getLedger<>(std::shared_ptr&, uint256 const&, Context&); + +// The previous version of the lookupLedger command would accept the +// "ledger_index" argument as a string and silently treat it as a request to +// return the current ledger which, while not strictly wrong, could cause a lot +// of confusion. +// +// The code now robustly validates the input and ensures that the only possible +// values for the "ledger_index" parameter are the index of a ledger passed as +// an integer or one of the strings "current", "closed" or "validated". +// Additionally, the code ensures that the value passed in "ledger_hash" is a +// string and a valid hash. Invalid values will return an appropriate error +// code. +// +// In the absence of the "ledger_hash" or "ledger_index" parameters, the code +// assumes that "ledger_index" has the value "current". +// +// Returns a Json::objectValue. If there was an error, it will be in that +// return value. Otherwise, the object contains the field "validated" and +// optionally the fields "ledger_hash", "ledger_index" and +// "ledger_current_index", if they are defined. +Status +lookupLedger( + std::shared_ptr& ledger, + JsonContext& context, + Json::Value& result) +{ + if (auto status = ledgerFromRequest(ledger, context)) + return status; + + auto& info = ledger->info(); + + if (!ledger->open()) + { + result[jss::ledger_hash] = to_string(info.hash); + result[jss::ledger_index] = info.seq; + } + else + { + result[jss::ledger_current_index] = info.seq; + } + + result[jss::validated] = context.ledgerMaster.isValidated(*ledger); + return Status::OK; +} + +Json::Value +lookupLedger(std::shared_ptr& ledger, JsonContext& context) +{ + Json::Value result; + if (auto status = lookupLedger(ledger, context, result)) + status.inject(result); + + return result; +} + +std::variant, Json::Value> +getLedgerByContext(RPC::JsonContext& context) +{ + auto const hasHash = context.params.isMember(jss::ledger_hash); + auto const hasIndex = context.params.isMember(jss::ledger_index); + std::uint32_t ledgerIndex = 0; + + auto& ledgerMaster = context.app.getLedgerMaster(); + LedgerHash ledgerHash; + + if ((hasHash && hasIndex) || !(hasHash || hasIndex)) + { + return RPC::make_param_error( + "Exactly one of ledger_hash and ledger_index can be set."); + } + + context.loadType = Resource::feeHeavyBurdenRPC; + + if (hasHash) + { + auto const& jsonHash = context.params[jss::ledger_hash]; + if (!jsonHash.isString() || !ledgerHash.parseHex(jsonHash.asString())) + return RPC::invalid_field_error(jss::ledger_hash); + } + else + { + auto const& jsonIndex = context.params[jss::ledger_index]; + if (!jsonIndex.isInt()) + return RPC::invalid_field_error(jss::ledger_index); + + // We need a validated ledger to get the hash from the sequence + if (ledgerMaster.getValidatedLedgerAge() > + RPC::Tuning::maxValidatedLedgerAge) + { + if (context.apiVersion == 1) + return rpcError(rpcNO_CURRENT); + return rpcError(rpcNOT_SYNCED); + } + + ledgerIndex = jsonIndex.asInt(); + auto ledger = ledgerMaster.getValidatedLedger(); + + if (ledgerIndex >= ledger->info().seq) + return RPC::make_param_error("Ledger index too large"); + if (ledgerIndex <= 0) + return RPC::make_param_error("Ledger index too small"); + + auto const j = context.app.journal("RPCHandler"); + // Try to get the hash of the desired ledger from the validated + // ledger + auto neededHash = hashOfSeq(*ledger, ledgerIndex, j); + if (!neededHash) + { + // Find a ledger more likely to have the hash of the desired + // ledger + auto const refIndex = getCandidateLedger(ledgerIndex); + auto refHash = hashOfSeq(*ledger, refIndex, j); + XRPL_ASSERT( + refHash, + "ripple::RPC::getLedgerByContext : nonzero ledger hash"); + + ledger = ledgerMaster.getLedgerByHash(*refHash); + if (!ledger) + { + // We don't have the ledger we need to figure out which + // ledger they want. Try to get it. + + if (auto il = context.app.getInboundLedgers().acquire( + *refHash, refIndex, InboundLedger::Reason::GENERIC)) + { + Json::Value jvResult = RPC::make_error( + rpcLGR_NOT_FOUND, + "acquiring ledger containing requested index"); + jvResult[jss::acquiring] = + getJson(LedgerFill(*il, &context)); + return jvResult; + } + + if (auto il = context.app.getInboundLedgers().find(*refHash)) + { + Json::Value jvResult = RPC::make_error( + rpcLGR_NOT_FOUND, + "acquiring ledger containing requested index"); + jvResult[jss::acquiring] = il->getJson(0); + return jvResult; + } + + // Likely the app is shutting down + return Json::Value(); + } + + neededHash = hashOfSeq(*ledger, ledgerIndex, j); + } + XRPL_ASSERT( + neededHash, + "ripple::RPC::getLedgerByContext : nonzero needed hash"); + ledgerHash = neededHash ? *neededHash : beast::zero; // kludge + } + + // Try to get the desired ledger + // Verify all nodes even if we think we have it + auto ledger = context.app.getInboundLedgers().acquire( + ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC); + + // In standalone mode, accept the ledger from the ledger cache + if (!ledger && context.app.config().standalone()) + ledger = ledgerMaster.getLedgerByHash(ledgerHash); + + if (ledger) + return ledger; + + if (auto il = context.app.getInboundLedgers().find(ledgerHash)) + return il->getJson(0); + + return RPC::make_error( + rpcNOT_READY, "findCreate failed to return an inbound ledger"); +} + +} // namespace RPC +} // namespace ripple diff --git a/src/xrpld/rpc/detail/RPCLedgerHelpers.h b/src/xrpld/rpc/detail/RPCLedgerHelpers.h new file mode 100644 index 0000000000..17382d3c53 --- /dev/null +++ b/src/xrpld/rpc/detail/RPCLedgerHelpers.h @@ -0,0 +1,96 @@ +#ifndef XRPL_RPC_RPCLEDGERHELPERS_H_INCLUDED +#define XRPL_RPC_RPCLEDGERHELPERS_H_INCLUDED + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace Json { +class Value; +} + +namespace ripple { + +class ReadView; +class Transaction; + +namespace RPC { + +struct JsonContext; + +/** Get ledger by hash + If there is no error in the return value, the ledger pointer will have + been filled +*/ +template +Status +getLedger(T& ledger, uint256 const& ledgerHash, Context& context); + +/** Get ledger by sequence + If there is no error in the return value, the ledger pointer will have + been filled +*/ +template +Status +getLedger(T& ledger, uint32_t ledgerIndex, Context& context); + +enum LedgerShortcut { CURRENT, CLOSED, VALIDATED }; +/** Get ledger specified in shortcut. + If there is no error in the return value, the ledger pointer will have + been filled +*/ +template +Status +getLedger(T& ledger, LedgerShortcut shortcut, Context& context); + +/** Look up a ledger from a request and fill a Json::Result with either + an error, or data representing a ledger. + + If there is no error in the return value, then the ledger pointer will have + been filled. +*/ +Json::Value +lookupLedger(std::shared_ptr&, JsonContext&); + +/** Look up a ledger from a request and fill a Json::Result with the data + representing a ledger. + + If the returned Status is OK, the ledger pointer will have been filled. +*/ +Status +lookupLedger( + std::shared_ptr&, + JsonContext&, + Json::Value& result); + +template +Status +ledgerFromRequest(T& ledger, GRPCContext& context); + +template +Status +ledgerFromSpecifier( + T& ledger, + org::xrpl::rpc::v1::LedgerSpecifier const& specifier, + Context& context); + +/** Return a ledger based on ledger_hash or ledger_index, + or an RPC error */ +std::variant, Json::Value> +getLedgerByContext(RPC::JsonContext& context); + +} // namespace RPC + +} // namespace ripple + +#endif diff --git a/src/xrpld/rpc/handlers/AMMInfo.cpp b/src/xrpld/rpc/handlers/AMMInfo.cpp index 01e9f0cd16..dda30fcfa7 100644 --- a/src/xrpld/rpc/handlers/AMMInfo.cpp +++ b/src/xrpld/rpc/handlers/AMMInfo.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/AccountChannels.cpp b/src/xrpld/rpc/handlers/AccountChannels.cpp index e1f86630c5..281b0ec8c4 100644 --- a/src/xrpld/rpc/handlers/AccountChannels.cpp +++ b/src/xrpld/rpc/handlers/AccountChannels.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/AccountCurrenciesHandler.cpp b/src/xrpld/rpc/handlers/AccountCurrenciesHandler.cpp index ca165e7592..10f22ad654 100644 --- a/src/xrpld/rpc/handlers/AccountCurrenciesHandler.cpp +++ b/src/xrpld/rpc/handlers/AccountCurrenciesHandler.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index 8c07f20581..3caafc411b 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/AccountLines.cpp b/src/xrpld/rpc/handlers/AccountLines.cpp index 22ca1bc2f9..b28f4d7483 100644 --- a/src/xrpld/rpc/handlers/AccountLines.cpp +++ b/src/xrpld/rpc/handlers/AccountLines.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/AccountObjects.cpp b/src/xrpld/rpc/handlers/AccountObjects.cpp index f68ab5dfae..82ff1782e4 100644 --- a/src/xrpld/rpc/handlers/AccountObjects.cpp +++ b/src/xrpld/rpc/handlers/AccountObjects.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,198 @@ doAccountNFTs(RPC::JsonContext& context) return result; } +bool +getAccountObjects( + ReadView const& ledger, + AccountID const& account, + std::optional> const& typeFilter, + uint256 dirIndex, + uint256 entryIndex, + std::uint32_t const limit, + Json::Value& jvResult) +{ + // check if dirIndex is valid + if (!dirIndex.isZero() && !ledger.read({ltDIR_NODE, dirIndex})) + return false; + + auto typeMatchesFilter = [](std::vector const& typeFilter, + LedgerEntryType ledgerType) { + auto it = std::find(typeFilter.begin(), typeFilter.end(), ledgerType); + return it != typeFilter.end(); + }; + + // if dirIndex != 0, then all NFTs have already been returned. only + // iterate NFT pages if the filter says so AND dirIndex == 0 + bool iterateNFTPages = + (!typeFilter.has_value() || + typeMatchesFilter(typeFilter.value(), ltNFTOKEN_PAGE)) && + dirIndex == beast::zero; + + Keylet const firstNFTPage = keylet::nftpage_min(account); + + // we need to check the marker to see if it is an NFTTokenPage index. + if (iterateNFTPages && entryIndex != beast::zero) + { + // if it is we will try to iterate the pages up to the limit + // and then change over to the owner directory + + if (firstNFTPage.key != (entryIndex & ~nft::pageMask)) + iterateNFTPages = false; + } + + auto& jvObjects = (jvResult[jss::account_objects] = Json::arrayValue); + + // this is a mutable version of limit, used to seamlessly switch + // to iterating directory entries when nftokenpages are exhausted + uint32_t mlimit = limit; + + // iterate NFTokenPages preferentially + if (iterateNFTPages) + { + Keylet const first = entryIndex == beast::zero + ? firstNFTPage + : Keylet{ltNFTOKEN_PAGE, entryIndex}; + + Keylet const last = keylet::nftpage_max(account); + + // current key + uint256 ck = ledger.succ(first.key, last.key.next()).value_or(last.key); + + // current page + auto cp = ledger.read(Keylet{ltNFTOKEN_PAGE, ck}); + + while (cp) + { + jvObjects.append(cp->getJson(JsonOptions::none)); + auto const npm = (*cp)[~sfNextPageMin]; + if (npm) + cp = ledger.read(Keylet(ltNFTOKEN_PAGE, *npm)); + else + cp = nullptr; + + if (--mlimit == 0) + { + if (cp) + { + jvResult[jss::limit] = limit; + jvResult[jss::marker] = std::string("0,") + to_string(ck); + return true; + } + } + + if (!npm) + break; + + ck = *npm; + } + + // if execution reaches here then we're about to transition + // to iterating the root directory (and the conventional + // behaviour of this RPC function.) Therefore we should + // zero entryIndex so as not to terribly confuse things. + entryIndex = beast::zero; + } + + auto const root = keylet::ownerDir(account); + auto found = false; + + if (dirIndex.isZero()) + { + dirIndex = root.key; + found = true; + } + + auto dir = ledger.read({ltDIR_NODE, dirIndex}); + if (!dir) + { + // it's possible the user had nftoken pages but no + // directory entries. If there's no nftoken page, we will + // give empty array for account_objects. + if (mlimit >= limit) + jvResult[jss::account_objects] = Json::arrayValue; + + // non-zero dirIndex validity was checked in the beginning of this + // function; by this point, it should be zero. This function returns + // true regardless of nftoken page presence; if absent, account_objects + // is already set as an empty array. Notice we will only return false in + // this function when entryIndex can not be found, indicating an invalid + // marker error. + return true; + } + + std::uint32_t i = 0; + for (;;) + { + auto const& entries = dir->getFieldV256(sfIndexes); + auto iter = entries.begin(); + + if (!found) + { + iter = std::find(iter, entries.end(), entryIndex); + if (iter == entries.end()) + return false; + + found = true; + } + + // it's possible that the returned NFTPages exactly filled the + // response. Check for that condition. + if (i == mlimit && mlimit < limit) + { + jvResult[jss::limit] = limit; + jvResult[jss::marker] = + to_string(dirIndex) + ',' + to_string(*iter); + return true; + } + + for (; iter != entries.end(); ++iter) + { + auto const sleNode = ledger.read(keylet::child(*iter)); + + if (!typeFilter.has_value() || + typeMatchesFilter(typeFilter.value(), sleNode->getType())) + { + jvObjects.append(sleNode->getJson(JsonOptions::none)); + } + + if (++i == mlimit) + { + if (++iter != entries.end()) + { + jvResult[jss::limit] = limit; + jvResult[jss::marker] = + to_string(dirIndex) + ',' + to_string(*iter); + return true; + } + + break; + } + } + + auto const nodeIndex = dir->getFieldU64(sfIndexNext); + if (nodeIndex == 0) + return true; + + dirIndex = keylet::page(root, nodeIndex).key; + dir = ledger.read({ltDIR_NODE, dirIndex}); + if (!dir) + return true; + + if (i == mlimit) + { + auto const& e = dir->getFieldV256(sfIndexes); + if (!e.empty()) + { + jvResult[jss::limit] = limit; + jvResult[jss::marker] = + to_string(dirIndex) + ',' + to_string(*e.begin()); + } + + return true; + } + } +} + Json::Value doAccountObjects(RPC::JsonContext& context) { @@ -265,7 +458,7 @@ doAccountObjects(RPC::JsonContext& context) return RPC::invalid_field_error(jss::marker); } - if (!RPC::getAccountObjects( + if (!getAccountObjects( *ledger, accountID, typeFilter, diff --git a/src/xrpld/rpc/handlers/AccountOffers.cpp b/src/xrpld/rpc/handlers/AccountOffers.cpp index acba153554..e8bc2bcf79 100644 --- a/src/xrpld/rpc/handlers/AccountOffers.cpp +++ b/src/xrpld/rpc/handlers/AccountOffers.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/BookOffers.cpp b/src/xrpld/rpc/handlers/BookOffers.cpp index d0544460d1..e82b2fa345 100644 --- a/src/xrpld/rpc/handlers/BookOffers.cpp +++ b/src/xrpld/rpc/handlers/BookOffers.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/DepositAuthorized.cpp b/src/xrpld/rpc/handlers/DepositAuthorized.cpp index 7490dbea94..707db63e36 100644 --- a/src/xrpld/rpc/handlers/DepositAuthorized.cpp +++ b/src/xrpld/rpc/handlers/DepositAuthorized.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/GatewayBalances.cpp b/src/xrpld/rpc/handlers/GatewayBalances.cpp index 3e614c2a24..88411b020e 100644 --- a/src/xrpld/rpc/handlers/GatewayBalances.cpp +++ b/src/xrpld/rpc/handlers/GatewayBalances.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/GetAggregatePrice.cpp b/src/xrpld/rpc/handlers/GetAggregatePrice.cpp index a1121e260b..c74a4331fd 100644 --- a/src/xrpld/rpc/handlers/GetAggregatePrice.cpp +++ b/src/xrpld/rpc/handlers/GetAggregatePrice.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/LedgerData.cpp b/src/xrpld/rpc/handlers/LedgerData.cpp index d5f27a138e..c5e39f69b4 100644 --- a/src/xrpld/rpc/handlers/LedgerData.cpp +++ b/src/xrpld/rpc/handlers/LedgerData.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/LedgerDiff.cpp b/src/xrpld/rpc/handlers/LedgerDiff.cpp index d713f43bfd..3628138329 100644 --- a/src/xrpld/rpc/handlers/LedgerDiff.cpp +++ b/src/xrpld/rpc/handlers/LedgerDiff.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace ripple { std::pair diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index 78655f1c9f..992c5551c3 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/LedgerHandler.cpp b/src/xrpld/rpc/handlers/LedgerHandler.cpp index f282d0ddd3..4483838fa0 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.cpp +++ b/src/xrpld/rpc/handlers/LedgerHandler.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/LedgerHeader.cpp b/src/xrpld/rpc/handlers/LedgerHeader.cpp index 193ca355d3..ebbd6beb01 100644 --- a/src/xrpld/rpc/handlers/LedgerHeader.cpp +++ b/src/xrpld/rpc/handlers/LedgerHeader.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/LedgerRequest.cpp b/src/xrpld/rpc/handlers/LedgerRequest.cpp index ea3208605f..fd06ab30ba 100644 --- a/src/xrpld/rpc/handlers/LedgerRequest.cpp +++ b/src/xrpld/rpc/handlers/LedgerRequest.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/NFTOffers.cpp b/src/xrpld/rpc/handlers/NFTOffers.cpp index 6d11ff5b0a..51290a404c 100644 --- a/src/xrpld/rpc/handlers/NFTOffers.cpp +++ b/src/xrpld/rpc/handlers/NFTOffers.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/NoRippleCheck.cpp b/src/xrpld/rpc/handlers/NoRippleCheck.cpp index e5c1170969..9ff2757a40 100644 --- a/src/xrpld/rpc/handlers/NoRippleCheck.cpp +++ b/src/xrpld/rpc/handlers/NoRippleCheck.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include diff --git a/src/xrpld/rpc/handlers/RipplePathFind.cpp b/src/xrpld/rpc/handlers/RipplePathFind.cpp index 1cfea8dd5c..771c1cb95f 100644 --- a/src/xrpld/rpc/handlers/RipplePathFind.cpp +++ b/src/xrpld/rpc/handlers/RipplePathFind.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/TransactionEntry.cpp b/src/xrpld/rpc/handlers/TransactionEntry.cpp index 5dd8d685e1..9553c2d41e 100644 --- a/src/xrpld/rpc/handlers/TransactionEntry.cpp +++ b/src/xrpld/rpc/handlers/TransactionEntry.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/xrpld/rpc/handlers/VaultInfo.cpp b/src/xrpld/rpc/handlers/VaultInfo.cpp index 3e8226352a..7e040fef82 100644 --- a/src/xrpld/rpc/handlers/VaultInfo.cpp +++ b/src/xrpld/rpc/handlers/VaultInfo.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include From ad37461ab2e3057d1aa2bd8208027284f176a98b Mon Sep 17 00:00:00 2001 From: sunnyraindy Date: Wed, 19 Nov 2025 09:21:35 +0800 Subject: [PATCH 007/105] chore: Fix some typos in comments (#6040) --- external/secp256k1/include/secp256k1.h | 2 +- include/xrpl/basics/SlabAllocator.h | 2 +- include/xrpl/basics/base_uint.h | 2 +- include/xrpl/basics/comparators.h | 2 +- include/xrpl/beast/unit_test/runner.h | 2 +- src/test/app/PermissionedDEX_test.cpp | 4 ++-- src/test/app/ValidatorList_test.cpp | 2 +- src/test/app/tx/apply_test.cpp | 4 ++-- src/test/core/Config_test.cpp | 2 +- src/test/core/SociDB_test.cpp | 2 +- src/test/jtx/amount.h | 2 +- src/test/jtx/envconfig.h | 2 +- src/test/overlay/cluster_test.cpp | 2 +- src/xrpld/peerfinder/detail/SlotImp.h | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/external/secp256k1/include/secp256k1.h b/external/secp256k1/include/secp256k1.h index c6e9417f05..e562cd00e8 100644 --- a/external/secp256k1/include/secp256k1.h +++ b/external/secp256k1/include/secp256k1.h @@ -541,7 +541,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( /** Verify an ECDSA signature. * * Returns: 1: correct signature - * 0: incorrect or unparseable signature + * 0: incorrect or unparsable signature * Args: ctx: pointer to a context object * In: sig: the signature being verified. * msghash32: the 32-byte message hash being verified. diff --git a/include/xrpl/basics/SlabAllocator.h b/include/xrpl/basics/SlabAllocator.h index b85b2149ca..d27616ecdd 100644 --- a/include/xrpl/basics/SlabAllocator.h +++ b/include/xrpl/basics/SlabAllocator.h @@ -159,7 +159,7 @@ public: @param count the number of items the slab allocator can allocate; note that a count of 0 is valid and means that the allocator is, effectively, disabled. This can be very useful in some - contexts (e.g. when mimimal memory usage is needed) and + contexts (e.g. when minimal memory usage is needed) and allows for graceful failure. */ constexpr explicit SlabAllocator( diff --git a/include/xrpl/basics/base_uint.h b/include/xrpl/basics/base_uint.h index 48c8030f57..4be4b35af3 100644 --- a/include/xrpl/basics/base_uint.h +++ b/include/xrpl/basics/base_uint.h @@ -546,7 +546,7 @@ operator<=>(base_uint const& lhs, base_uint const& rhs) // This comparison might seem wrong on a casual inspection because it // compares data internally stored as std::uint32_t byte-by-byte. But // note that the underlying data is stored in big endian, even if the - // plaform is little endian. This makes the comparison correct. + // platform is little endian. This makes the comparison correct. // // FIXME: use std::lexicographical_compare_three_way once support is // added to MacOS. diff --git a/include/xrpl/basics/comparators.h b/include/xrpl/basics/comparators.h index 6b1d693e65..4858a0ad74 100644 --- a/include/xrpl/basics/comparators.h +++ b/include/xrpl/basics/comparators.h @@ -9,7 +9,7 @@ namespace ripple { /* * MSVC 2019 version 16.9.0 added [[nodiscard]] to the std comparison - * operator() functions. boost::bimap checks that the comparitor is a + * operator() functions. boost::bimap checks that the comparator is a * BinaryFunction, in part by calling the function and ignoring the value. * These two things don't play well together. These wrapper classes simply * strip [[nodiscard]] from operator() for use in boost::bimap. diff --git a/include/xrpl/beast/unit_test/runner.h b/include/xrpl/beast/unit_test/runner.h index f0742c7b01..f91cc92c91 100644 --- a/include/xrpl/beast/unit_test/runner.h +++ b/include/xrpl/beast/unit_test/runner.h @@ -39,7 +39,7 @@ public: The argument string is available to suites and allows for customization of the test. Each suite - defines its own syntax for the argumnet string. + defines its own syntax for the argument string. The same argument is passed to all suites. */ void diff --git a/src/test/app/PermissionedDEX_test.cpp b/src/test/app/PermissionedDEX_test.cpp index d202b39e09..25d94a968b 100644 --- a/src/test/app/PermissionedDEX_test.cpp +++ b/src/test/app/PermissionedDEX_test.cpp @@ -966,8 +966,8 @@ class PermissionedDEX_test : public beast::unit_test::suite { testcase("Remove unfunded offer"); - // checking that an unfunded offer will be implictly removed by a - // successfuly payment tx + // checking that an unfunded offer will be implicitly removed by a + // successful payment tx Env env(*this, features); auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); diff --git a/src/test/app/ValidatorList_test.cpp b/src/test/app/ValidatorList_test.cpp index 370f262075..2f88f0ea1e 100644 --- a/src/test/app/ValidatorList_test.cpp +++ b/src/test/app/ValidatorList_test.cpp @@ -1740,7 +1740,7 @@ private: // locals[0]: from 0 to maxKeys - 4 // locals[1]: from 1 to maxKeys - 2 // locals[2]: from 2 to maxKeys - // interesection of at least 2: same as locals[1] + // intersection of at least 2: same as locals[1] // intersection when 1 is dropped: from 2 to maxKeys - 4 constexpr static int publishers = 3; std::array< diff --git a/src/test/app/tx/apply_test.cpp b/src/test/app/tx/apply_test.cpp index fcfa1a8328..236905cefd 100644 --- a/src/test/app/tx/apply_test.cpp +++ b/src/test/app/tx/apply_test.cpp @@ -49,7 +49,7 @@ public: .first; if (valid != Validity::Valid) - fail("Non-Fully canoncial signature was not permitted"); + fail("Non-Fully canonical signature was not permitted"); } { @@ -63,7 +63,7 @@ public: fully_canonical.app().config()) .first; if (valid == Validity::Valid) - fail("Non-Fully canoncial signature was permitted"); + fail("Non-Fully canonical signature was permitted"); } pass(); diff --git a/src/test/core/Config_test.cpp b/src/test/core/Config_test.cpp index 34c4a553b4..6f11877202 100644 --- a/src/test/core/Config_test.cpp +++ b/src/test/core/Config_test.cpp @@ -1183,7 +1183,7 @@ r.ripple.com:51235 BEAST_EXPECT(cfg.IPS_FIXED[6] == "12.34.12.123 12345"); BEAST_EXPECT(cfg.IPS_FIXED[7] == "12.34.12.123 12345"); - // all ipv6 should be ignored by colon replacer, howsoever formated + // all ipv6 should be ignored by colon replacer, howsoever formatted BEAST_EXPECT(cfg.IPS_FIXED[8] == "::"); BEAST_EXPECT(cfg.IPS_FIXED[9] == "2001:db8::"); BEAST_EXPECT(cfg.IPS_FIXED[10] == "::1"); diff --git a/src/test/core/SociDB_test.cpp b/src/test/core/SociDB_test.cpp index e201f75dba..2d38ac4697 100644 --- a/src/test/core/SociDB_test.cpp +++ b/src/test/core/SociDB_test.cpp @@ -79,7 +79,7 @@ public: void testSQLiteFileNames() { - // confirm that files are given the correct exensions + // confirm that files are given the correct extensions testcase("sqliteFileNames"); BasicConfig c; setupSQLiteConfig(c, getDatabasePath()); diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index 4d32ef2d1a..a5a73c59e8 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -243,7 +243,7 @@ struct XRP_t } /** Returns an amount of XRP as PrettyAmount, - which is trivially convertable to STAmount + which is trivially convertible to STAmount @param v The number of XRP (not drops) */ diff --git a/src/test/jtx/envconfig.h b/src/test/jtx/envconfig.h index efc1c50901..4c8476d95f 100644 --- a/src/test/jtx/envconfig.h +++ b/src/test/jtx/envconfig.h @@ -6,7 +6,7 @@ namespace ripple { namespace test { -// frequently used macros defined here for convinience. +// frequently used macros defined here for convenience. #define PORT_WS "port_ws" #define PORT_RPC "port_rpc" #define PORT_PEER "port_peer" diff --git a/src/test/overlay/cluster_test.cpp b/src/test/overlay/cluster_test.cpp index e5fd20bc1b..d29e143cff 100644 --- a/src/test/overlay/cluster_test.cpp +++ b/src/test/overlay/cluster_test.cpp @@ -227,7 +227,7 @@ public: BEAST_EXPECT(!c->load(s4)); // Check if we properly terminate when we encounter - // a malformed or unparseable entry: + // a malformed or unparsable entry: auto const node1 = randomNode(); auto const node2 = randomNode(); diff --git a/src/xrpld/peerfinder/detail/SlotImp.h b/src/xrpld/peerfinder/detail/SlotImp.h index 2badd9a2ef..9898ca490d 100644 --- a/src/xrpld/peerfinder/detail/SlotImp.h +++ b/src/xrpld/peerfinder/detail/SlotImp.h @@ -176,7 +176,7 @@ public: // DEPRECATED public data members // Tells us if we checked the connection. Outbound connections - // are always considered checked since we successfuly connected. + // are always considered checked since we successfully connected. bool checked; // Set to indicate if the connection can receive incoming at the From 6ff495fd9b923c5a07e5aca159ea268d34ac0c9e Mon Sep 17 00:00:00 2001 From: Olek <115580134+oleks-rip@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:58:18 -0500 Subject: [PATCH 008/105] Fix: Perform array size check (#6030) The `ledger_entry` and `deposit_preauth` requests require an array of credentials. However, the array size is not checked before is gets processing. This fix adds checks and return errors in case array size is too big. --- src/test/rpc/LedgerEntry_test.cpp | 4 +-- src/xrpld/rpc/handlers/LedgerEntry.cpp | 34 ++++++++++++++++++-------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index fdd3838e89..a0fde0f457 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -1103,7 +1103,7 @@ class LedgerEntry_test : public beast::unit_test::suite checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", - "Invalid field 'authorized_credentials', not array."); + "Invalid field 'authorized_credentials', array empty."); } { @@ -1144,7 +1144,7 @@ class LedgerEntry_test : public beast::unit_test::suite checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", - "Invalid field 'authorized_credentials', not array."); + "Invalid field 'authorized_credentials', array too long."); } } diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index 992c5551c3..bf8a4a5b80 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -16,8 +16,6 @@ #include #include -#include - namespace ripple { static Expected @@ -178,18 +176,41 @@ static Expected parseAuthorizeCredentials(Json::Value const& jv) { if (!jv.isArray()) + { return LedgerEntryHelpers::invalidFieldError( "malformedAuthorizedCredentials", jss::authorized_credentials, "array"); - STArray arr(sfAuthorizeCredentials, jv.size()); + } + + std::uint32_t const n = jv.size(); + if (n > maxCredentialsArraySize) + { + return Unexpected(LedgerEntryHelpers::malformedError( + "malformedAuthorizedCredentials", + "Invalid field '" + std::string(jss::authorized_credentials) + + "', array too long.")); + } + + if (n == 0) + { + return Unexpected(LedgerEntryHelpers::malformedError( + "malformedAuthorizedCredentials", + "Invalid field '" + std::string(jss::authorized_credentials) + + "', array empty.")); + } + + STArray arr(sfAuthorizeCredentials, n); for (auto const& jo : jv) { if (!jo.isObject()) + { return LedgerEntryHelpers::invalidFieldError( "malformedAuthorizedCredentials", jss::authorized_credentials, "array"); + } + if (auto const value = LedgerEntryHelpers::hasRequired( jo, {jss::issuer, jss::credential_type}, @@ -260,13 +281,6 @@ parseDepositPreauth(Json::Value const& dp, Json::StaticString const fieldName) auto const arr = parseAuthorizeCredentials(ac); if (!arr.has_value()) return Unexpected(arr.error()); - if (arr->empty() || (arr->size() > maxCredentialsArraySize)) - { - return LedgerEntryHelpers::invalidFieldError( - "malformedAuthorizedCredentials", - jss::authorized_credentials, - "array"); - } auto const& sorted = credentials::makeSorted(arr.value()); if (sorted.empty()) From a3d4be4eafce09c8a26fa81489fd59d4fd4a4b97 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 20 Nov 2025 17:07:28 +0530 Subject: [PATCH 009/105] fix: Set correct index for limit in `book_offers` CLI (#6043) This change fixes an indexing typo in the `book_offers` CLI processing, and does not affect the HTTPS/WS RPC processing. --- src/test/rpc/RPCCall_test.cpp | 23 +++++++++++++---------- src/xrpld/rpc/detail/RPCCall.cpp | 26 +++++++++++++++++++++----- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/test/rpc/RPCCall_test.cpp b/src/test/rpc/RPCCall_test.cpp index 07129e4bae..7647dc5f65 100644 --- a/src/test/rpc/RPCCall_test.cpp +++ b/src/test/rpc/RPCCall_test.cpp @@ -1584,8 +1584,6 @@ static RPCCallTestData const rpcCallTestArray[] = { "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", - "junk", // Note: indexing bug in parseBookOffers() requires junk - // param. "200", }, RPCCallTestData::no_exception, @@ -1597,7 +1595,6 @@ static RPCCallTestData const rpcCallTestArray[] = { "issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ledger_hash" : "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", "limit" : 200, - "proof" : true, "taker_gets" : { "currency" : "EUR", "issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA" @@ -1617,8 +1614,8 @@ static RPCCallTestData const rpcCallTestArray[] = { "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", - "junk", // Note: indexing bug in parseBookOffers() requires junk param. "200", + "0", "MyMarker"}, RPCCallTestData::no_exception, R"({ @@ -1630,7 +1627,6 @@ static RPCCallTestData const rpcCallTestArray[] = { "ledger_hash" : "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", "limit" : 200, "marker" : "MyMarker", - "proof" : true, "taker_gets" : { "currency" : "EUR", "issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA" @@ -1665,8 +1661,8 @@ static RPCCallTestData const rpcCallTestArray[] = { "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", - "junk", // Note: indexing bug in parseBookOffers() requires junk param. "200", + "0", "MyMarker", "extra"}, RPCCallTestData::no_exception, @@ -1770,12 +1766,19 @@ static RPCCallTestData const rpcCallTestArray[] = { "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", - "junk", // Note: indexing bug in parseBookOffers() requires junk - // param. "not_a_number", }, - RPCCallTestData::bad_cast, - R"()"}, + RPCCallTestData::no_exception, + R"({ + "method" : "book_offers", + "params" : [ + { + "error" : "invalidParams", + "error_code" : 31, + "error_message" : "Invalid field 'limit'." + } + ] + })"}, // can_delete // ------------------------------------------------------------------ diff --git a/src/xrpld/rpc/detail/RPCCall.cpp b/src/xrpld/rpc/detail/RPCCall.cpp index 915f951749..185043302a 100644 --- a/src/xrpld/rpc/detail/RPCCall.cpp +++ b/src/xrpld/rpc/detail/RPCCall.cpp @@ -332,15 +332,31 @@ private: if (jvParams.size() >= 5) { - int iLimit = jvParams[5u].asInt(); + try + { + int iLimit = jvParams[4u].asInt(); - if (iLimit > 0) - jvRequest[jss::limit] = iLimit; + if (iLimit > 0) + jvRequest[jss::limit] = iLimit; + } + catch (std::exception const&) + { + return RPC::invalid_field_error(jss::limit); + } } - if (jvParams.size() >= 6 && jvParams[5u].asInt()) + if (jvParams.size() >= 6) { - jvRequest[jss::proof] = true; + try + { + int bProof = jvParams[5u].asInt(); + if (bProof) + jvRequest[jss::proof] = true; + } + catch (std::exception const&) + { + return RPC::invalid_field_error(jss::proof); + } } if (jvParams.size() == 7) From adbeb94c2bd3e90f415eee1776ad52cfa19d48ee Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Thu, 20 Nov 2025 18:09:03 +0000 Subject: [PATCH 010/105] ci: Only upload artifacts in XRPLF repo owner (#6060) This change prevents uploading too many artifacts in non-public repositories. --- .github/workflows/reusable-build-test-config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index 768897f665..8ce810aa2e 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -130,7 +130,7 @@ jobs: --target "${CMAKE_TARGET}" - name: Upload rippled artifact (Linux) - if: ${{ runner.os == 'Linux' }} + if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }} uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 env: BUILD_DIR: ${{ inputs.build_dir }} From 57f4b4eb7ff279d848262a0c5fcee56bd8820494 Mon Sep 17 00:00:00 2001 From: Jingchen Date: Fri, 21 Nov 2025 14:19:43 +0000 Subject: [PATCH 011/105] refactor: Retire Checks amendment (#6055) Amendments activated for more than 2 years can be retired. This change retires the Checks amendment. --- include/xrpl/protocol/detail/features.macro | 2 +- .../xrpl/protocol/detail/transactions.macro | 6 +++--- src/test/app/Check_test.cpp | 19 ------------------- src/test/app/Delegate_test.cpp | 3 --- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index dd66d8a34c..116da10ca3 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -68,7 +68,6 @@ XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYe XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes) -XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes) // The following amendments are obsolete, but must remain supported @@ -116,6 +115,7 @@ XRPL_RETIRE_FIX(STAmountCanonicalize) XRPL_RETIRE_FIX(TakerDryOfferRemoval) XRPL_RETIRE_FIX(TrustLinesToSelf) +XRPL_RETIRE_FEATURE(Checks) XRPL_RETIRE_FEATURE(CheckCashMakesTrustLine) XRPL_RETIRE_FEATURE(CryptoConditions) XRPL_RETIRE_FEATURE(DepositAuth) diff --git a/include/xrpl/protocol/detail/transactions.macro b/include/xrpl/protocol/detail/transactions.macro index 23049d2543..c3cc2cef76 100644 --- a/include/xrpl/protocol/detail/transactions.macro +++ b/include/xrpl/protocol/detail/transactions.macro @@ -226,7 +226,7 @@ TRANSACTION(ttPAYCHAN_CLAIM, 15, PaymentChannelClaim, #endif TRANSACTION(ttCHECK_CREATE, 16, CheckCreate, Delegation::delegatable, - featureChecks, + uint256{}, noPriv, ({ {sfDestination, soeREQUIRED}, @@ -242,7 +242,7 @@ TRANSACTION(ttCHECK_CREATE, 16, CheckCreate, #endif TRANSACTION(ttCHECK_CASH, 17, CheckCash, Delegation::delegatable, - featureChecks, + uint256{}, noPriv, ({ {sfCheckID, soeREQUIRED}, @@ -256,7 +256,7 @@ TRANSACTION(ttCHECK_CASH, 17, CheckCash, #endif TRANSACTION(ttCHECK_CANCEL, 18, CheckCancel, Delegation::delegatable, - featureChecks, + uint256{}, noPriv, ({ {sfCheckID, soeREQUIRED}, diff --git a/src/test/app/Check_test.cpp b/src/test/app/Check_test.cpp index 61e20a0098..eb234cea56 100644 --- a/src/test/app/Check_test.cpp +++ b/src/test/app/Check_test.cpp @@ -125,25 +125,6 @@ class Check_test : public beast::unit_test::suite using namespace test::jtx; Account const alice{"alice"}; - { - // If the Checks amendment is not enabled, you should not be able - // to create, cash, or cancel checks. - Env env{*this, features - featureChecks}; - - env.fund(XRP(1000), alice); - env.close(); - - uint256 const checkId{ - getCheckIndex(env.master, env.seq(env.master))}; - env(check::create(env.master, alice, XRP(100)), ter(temDISABLED)); - env.close(); - - env(check::cash(alice, checkId, XRP(100)), ter(temDISABLED)); - env.close(); - - env(check::cancel(alice, checkId), ter(temDISABLED)); - env.close(); - } { // If the Checks amendment is enabled all check-related // facilities should be available. diff --git a/src/test/app/Delegate_test.cpp b/src/test/app/Delegate_test.cpp index 9e1c777a91..e36ad9a550 100644 --- a/src/test/app/Delegate_test.cpp +++ b/src/test/app/Delegate_test.cpp @@ -1703,9 +1703,6 @@ class Delegate_test : public beast::unit_test::suite // NFTokenMint, NFTokenBurn, NFTokenCreateOffer, NFTokenCancelOffer, // NFTokenAcceptOffer are not included, they are tested separately. std::unordered_map txRequiredFeatures{ - {"CheckCreate", featureChecks}, - {"CheckCash", featureChecks}, - {"CheckCancel", featureChecks}, {"Clawback", featureClawback}, {"AMMClawback", featureAMMClawback}, {"AMMCreate", featureAMM}, From e4dccfd49b2a6415aecf968690c3676bd5f555f0 Mon Sep 17 00:00:00 2001 From: Pratik Mankawde Date: Fri, 21 Nov 2025 15:18:00 +0000 Subject: [PATCH 012/105] refactor: Retire DisallowIncoming amendment (#6045) Amendments activated for more than 2 years can be retired. This change retires the DisallowIncoming amendment. --- include/xrpl/protocol/detail/features.macro | 2 +- src/test/app/Check_test.cpp | 17 +------- src/test/app/NFToken_test.cpp | 20 ++------- src/test/app/PayChan_test.cpp | 17 +------- src/test/app/SetTrust_test.cpp | 22 ++-------- src/test/rpc/AccountInfo_test.cpp | 48 ++++++++------------- src/xrpld/app/tx/detail/CreateCheck.cpp | 3 +- src/xrpld/app/tx/detail/NFTokenUtils.cpp | 28 ++++-------- src/xrpld/app/tx/detail/PayChan.cpp | 3 +- src/xrpld/app/tx/detail/SetAccount.cpp | 36 +++++++--------- src/xrpld/app/tx/detail/SetTrust.cpp | 28 ++++++------ src/xrpld/rpc/handlers/AccountInfo.cpp | 7 +-- 12 files changed, 67 insertions(+), 164 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 116da10ca3..4180f1e7ff 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -63,7 +63,6 @@ XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo) -XRPL_FEATURE(DisallowIncoming, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes) @@ -120,6 +119,7 @@ XRPL_RETIRE_FEATURE(CheckCashMakesTrustLine) XRPL_RETIRE_FEATURE(CryptoConditions) XRPL_RETIRE_FEATURE(DepositAuth) XRPL_RETIRE_FEATURE(DepositPreauth) +XRPL_RETIRE_FEATURE(DisallowIncoming) XRPL_RETIRE_FEATURE(Escrow) XRPL_RETIRE_FEATURE(EnforceInvariants) XRPL_RETIRE_FEATURE(ExpandedSignerList) diff --git a/src/test/app/Check_test.cpp b/src/test/app/Check_test.cpp index eb234cea56..b7d158041b 100644 --- a/src/test/app/Check_test.cpp +++ b/src/test/app/Check_test.cpp @@ -67,8 +67,6 @@ public: class Check_test : public beast::unit_test::suite { - FeatureBitset const disallowIncoming{featureDisallowIncoming}; - static uint256 getCheckIndex(AccountID const& account, std::uint32_t uSequence) { @@ -258,24 +256,12 @@ class Check_test : public beast::unit_test::suite using namespace test::jtx; - // test flag doesn't set unless amendment enabled - { - Env env{*this, features - disallowIncoming}; - Account const alice{"alice"}; - env.fund(XRP(10000), alice); - env(fset(alice, asfDisallowIncomingCheck)); - env.close(); - auto const sle = env.le(alice); - uint32_t flags = sle->getFlags(); - BEAST_EXPECT(!(flags & lsfDisallowIncomingCheck)); - } - Account const gw{"gateway"}; Account const alice{"alice"}; Account const bob{"bob"}; IOU const USD{gw["USD"]}; - Env env{*this, features | disallowIncoming}; + Env env{*this, features}; STAmount const startBalance{XRP(1000).value()}; env.fund(startBalance, gw, alice, bob); @@ -2594,7 +2580,6 @@ public: { using namespace test::jtx; auto const sa = testable_amendments(); - testWithFeats(sa - disallowIncoming); testWithFeats(sa); testTrustLineCreation(sa); } diff --git a/src/test/app/NFToken_test.cpp b/src/test/app/NFToken_test.cpp index a11446df71..12ac309acb 100644 --- a/src/test/app/NFToken_test.cpp +++ b/src/test/app/NFToken_test.cpp @@ -12,8 +12,6 @@ namespace ripple { class NFTokenBaseUtil_test : public beast::unit_test::suite { - FeatureBitset const disallowIncoming{featureDisallowIncoming}; - // Helper function that returns the number of NFTs minted by an issuer. static std::uint32_t mintedCount(test::jtx::Env const& env, test::jtx::Account const& issuer) @@ -2960,19 +2958,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite using namespace test::jtx; - // test flag doesn't set unless amendment enabled - { - Env env{*this, features - disallowIncoming}; - Account const alice{"alice"}; - env.fund(XRP(10000), alice); - env(fset(alice, asfDisallowIncomingNFTokenOffer)); - env.close(); - auto const sle = env.le(alice); - uint32_t flags = sle->getFlags(); - BEAST_EXPECT(!(flags & lsfDisallowIncomingNFTokenOffer)); - } - - Env env{*this, features | disallowIncoming}; + Env env{*this, features}; Account const issuer{"issuer"}; Account const minter{"minter"}; @@ -7624,8 +7610,8 @@ class NFTokenDisallowIncoming_test : public NFTokenBaseUtil_test run() override { testWithFeats( - allFeatures - featureDisallowIncoming - fixNFTokenReserve - - featureNFTokenMintOffer - featureDynamicNFT); + allFeatures - fixNFTokenReserve - featureNFTokenMintOffer - + featureDynamicNFT); } }; diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index bee3167b29..59c404ae28 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -14,8 +14,6 @@ using namespace jtx::paychan; struct PayChan_test : public beast::unit_test::suite { - FeatureBitset const disallowIncoming{featureDisallowIncoming}; - static std::pair> channelKeyAndSle( ReadView const& view, @@ -242,20 +240,8 @@ struct PayChan_test : public beast::unit_test::suite testcase("Disallow Incoming Flag"); using namespace jtx; - // test flag doesn't set unless amendment enabled - { - Env env{*this, features - disallowIncoming}; - Account const alice{"alice"}; - env.fund(XRP(10000), alice); - env(fset(alice, asfDisallowIncomingPayChan)); - env.close(); - auto const sle = env.le(alice); - uint32_t flags = sle->getFlags(); - BEAST_EXPECT(!(flags & lsfDisallowIncomingPayChan)); - } - using namespace std::literals::chrono_literals; - Env env{*this, features | disallowIncoming}; + Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); auto const cho = Account("cho"); @@ -2127,7 +2113,6 @@ public: { using namespace test::jtx; FeatureBitset const all{testable_amendments()}; - testWithFeats(all - disallowIncoming); testWithFeats(all); testDepositAuthCreds(); testMetaAndOwnership(all - fixIncludeKeyletFields); diff --git a/src/test/app/SetTrust_test.cpp b/src/test/app/SetTrust_test.cpp index 88e359ab23..07573cf13f 100644 --- a/src/test/app/SetTrust_test.cpp +++ b/src/test/app/SetTrust_test.cpp @@ -9,8 +9,6 @@ namespace test { class SetTrust_test : public beast::unit_test::suite { - FeatureBitset const disallowIncoming{featureDisallowIncoming}; - public: void testTrustLineDelete() @@ -478,25 +476,12 @@ public: using namespace test::jtx; - // test flag doesn't set unless amendment enabled - { - Env env{*this, features - disallowIncoming}; - Account const alice{"alice"}; - env.fund(XRP(10000), alice); - env(fset(alice, asfDisallowIncomingTrustline)); - env.close(); - auto const sle = env.le(alice); - uint32_t flags = sle->getFlags(); - BEAST_EXPECT(!(flags & lsfDisallowIncomingTrustline)); - } - // fixDisallowIncomingV1 { for (bool const withFix : {true, false}) { - auto const amend = withFix - ? features | disallowIncoming - : (features | disallowIncoming) - fixDisallowIncomingV1; + auto const amend = + withFix ? features : features - fixDisallowIncomingV1; Env env{*this, amend}; auto const dist = Account("dist"); @@ -532,7 +517,7 @@ public: } } - Env env{*this, features | disallowIncoming}; + Env env{*this, features}; auto const gw = Account{"gateway"}; auto const alice = Account{"alice"}; @@ -630,7 +615,6 @@ public: { using namespace test::jtx; auto const sa = testable_amendments(); - testWithFeats(sa - disallowIncoming); testWithFeats(sa); } }; diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 86d0a4b4f6..5e2fc608b3 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -615,33 +615,23 @@ public: {"disallowIncomingTrustline", asfDisallowIncomingTrustline}}}; - if (features[featureDisallowIncoming]) + for (auto& asf : disallowIncomingFlags) { - for (auto& asf : disallowIncomingFlags) - { - // Clear a flag and check that account_info returns results - // as expected - env(fclear(alice, asf.second)); - env.close(); - auto const f1 = getAccountFlag(asf.first, alice); - BEAST_EXPECT(f1.has_value()); - BEAST_EXPECT(!f1.value()); + // Clear a flag and check that account_info returns results + // as expected + env(fclear(alice, asf.second)); + env.close(); + auto const f1 = getAccountFlag(asf.first, alice); + BEAST_EXPECT(f1.has_value()); + BEAST_EXPECT(!f1.value()); - // Set a flag and check that account_info returns results - // as expected - env(fset(alice, asf.second)); - env.close(); - auto const f2 = getAccountFlag(asf.first, alice); - BEAST_EXPECT(f2.has_value()); - BEAST_EXPECT(f2.value()); - } - } - else - { - for (auto& asf : disallowIncomingFlags) - { - BEAST_EXPECT(!getAccountFlag(asf.first, alice)); - } + // Set a flag and check that account_info returns results + // as expected + env(fset(alice, asf.second)); + env.close(); + auto const f2 = getAccountFlag(asf.first, alice); + BEAST_EXPECT(f2.has_value()); + BEAST_EXPECT(f2.value()); } static constexpr std::pair @@ -706,12 +696,8 @@ public: FeatureBitset const allFeatures{ ripple::test::jtx::testable_amendments()}; testAccountFlags(allFeatures); - testAccountFlags(allFeatures - featureDisallowIncoming); - testAccountFlags( - allFeatures - featureDisallowIncoming - featureClawback); - testAccountFlags( - allFeatures - featureDisallowIncoming - featureClawback - - featureTokenEscrow); + testAccountFlags(allFeatures - featureClawback); + testAccountFlags(allFeatures - featureClawback - featureTokenEscrow); } }; diff --git a/src/xrpld/app/tx/detail/CreateCheck.cpp b/src/xrpld/app/tx/detail/CreateCheck.cpp index f5a36e6ac5..df859c4364 100644 --- a/src/xrpld/app/tx/detail/CreateCheck.cpp +++ b/src/xrpld/app/tx/detail/CreateCheck.cpp @@ -61,8 +61,7 @@ CreateCheck::preclaim(PreclaimContext const& ctx) auto const flags = sleDst->getFlags(); // Check if the destination has disallowed incoming checks - if (ctx.view.rules().enabled(featureDisallowIncoming) && - (flags & lsfDisallowIncomingCheck)) + if (flags & lsfDisallowIncomingCheck) return tecNO_PERMISSION; // Pseudo-accounts cannot cash checks. Note, this is not amendment-gated diff --git a/src/xrpld/app/tx/detail/NFTokenUtils.cpp b/src/xrpld/app/tx/detail/NFTokenUtils.cpp index 67f3a0de5f..db2b00cb2c 100644 --- a/src/xrpld/app/tx/detail/NFTokenUtils.cpp +++ b/src/xrpld/app/tx/detail/NFTokenUtils.cpp @@ -919,31 +919,21 @@ tokenOfferCreatePreclaim( return tecNO_DST; // check if the destination has disallowed incoming offers - if (view.rules().enabled(featureDisallowIncoming)) - { - // flag cannot be set unless amendment is enabled but - // out of an abundance of caution check anyway - - if (sleDst->getFlags() & lsfDisallowIncomingNFTokenOffer) - return tecNO_PERMISSION; - } + if (sleDst->getFlags() & lsfDisallowIncomingNFTokenOffer) + return tecNO_PERMISSION; } if (owner) { - // Check if the owner (buy offer) has disallowed incoming offers - if (view.rules().enabled(featureDisallowIncoming)) - { - auto const sleOwner = view.read(keylet::account(*owner)); + auto const sleOwner = view.read(keylet::account(*owner)); - // defensively check - // it should not be possible to specify owner that doesn't exist - if (!sleOwner) - return tecNO_TARGET; + // defensively check + // it should not be possible to specify owner that doesn't exist + if (!sleOwner) + return tecNO_TARGET; - if (sleOwner->getFlags() & lsfDisallowIncomingNFTokenOffer) - return tecNO_PERMISSION; - } + if (sleOwner->getFlags() & lsfDisallowIncomingNFTokenOffer) + return tecNO_PERMISSION; } if (view.rules().enabled(fixEnforceNFTokenTrustlineV2) && !amount.native()) diff --git a/src/xrpld/app/tx/detail/PayChan.cpp b/src/xrpld/app/tx/detail/PayChan.cpp index c3dc99e7fb..b52ae78523 100644 --- a/src/xrpld/app/tx/detail/PayChan.cpp +++ b/src/xrpld/app/tx/detail/PayChan.cpp @@ -202,8 +202,7 @@ PayChanCreate::preclaim(PreclaimContext const& ctx) auto const flags = sled->getFlags(); // Check if they have disallowed incoming payment channels - if (ctx.view.rules().enabled(featureDisallowIncoming) && - (flags & lsfDisallowIncomingPayChan)) + if (flags & lsfDisallowIncomingPayChan) return tecNO_PERMISSION; if ((flags & lsfRequireDestTag) && !ctx.tx[~sfDestinationTag]) diff --git a/src/xrpld/app/tx/detail/SetAccount.cpp b/src/xrpld/app/tx/detail/SetAccount.cpp index db513d9f05..e860eca22d 100644 --- a/src/xrpld/app/tx/detail/SetAccount.cpp +++ b/src/xrpld/app/tx/detail/SetAccount.cpp @@ -595,29 +595,25 @@ SetAccount::doApply() sle->isFieldPresent(sfNFTokenMinter)) sle->makeFieldAbsent(sfNFTokenMinter); - // Set or clear flags for disallowing various incoming instruments - if (ctx_.view().rules().enabled(featureDisallowIncoming)) - { - if (uSetFlag == asfDisallowIncomingNFTokenOffer) - uFlagsOut |= lsfDisallowIncomingNFTokenOffer; - else if (uClearFlag == asfDisallowIncomingNFTokenOffer) - uFlagsOut &= ~lsfDisallowIncomingNFTokenOffer; + if (uSetFlag == asfDisallowIncomingNFTokenOffer) + uFlagsOut |= lsfDisallowIncomingNFTokenOffer; + else if (uClearFlag == asfDisallowIncomingNFTokenOffer) + uFlagsOut &= ~lsfDisallowIncomingNFTokenOffer; - if (uSetFlag == asfDisallowIncomingCheck) - uFlagsOut |= lsfDisallowIncomingCheck; - else if (uClearFlag == asfDisallowIncomingCheck) - uFlagsOut &= ~lsfDisallowIncomingCheck; + if (uSetFlag == asfDisallowIncomingCheck) + uFlagsOut |= lsfDisallowIncomingCheck; + else if (uClearFlag == asfDisallowIncomingCheck) + uFlagsOut &= ~lsfDisallowIncomingCheck; - if (uSetFlag == asfDisallowIncomingPayChan) - uFlagsOut |= lsfDisallowIncomingPayChan; - else if (uClearFlag == asfDisallowIncomingPayChan) - uFlagsOut &= ~lsfDisallowIncomingPayChan; + if (uSetFlag == asfDisallowIncomingPayChan) + uFlagsOut |= lsfDisallowIncomingPayChan; + else if (uClearFlag == asfDisallowIncomingPayChan) + uFlagsOut &= ~lsfDisallowIncomingPayChan; - if (uSetFlag == asfDisallowIncomingTrustline) - uFlagsOut |= lsfDisallowIncomingTrustline; - else if (uClearFlag == asfDisallowIncomingTrustline) - uFlagsOut &= ~lsfDisallowIncomingTrustline; - } + if (uSetFlag == asfDisallowIncomingTrustline) + uFlagsOut |= lsfDisallowIncomingTrustline; + else if (uClearFlag == asfDisallowIncomingTrustline) + uFlagsOut &= ~lsfDisallowIncomingTrustline; // Set or clear flags for disallowing escrow if (ctx_.view().rules().enabled(featureTokenEscrow)) diff --git a/src/xrpld/app/tx/detail/SetTrust.cpp b/src/xrpld/app/tx/detail/SetTrust.cpp index dcbdbc013f..37ecdf2386 100644 --- a/src/xrpld/app/tx/detail/SetTrust.cpp +++ b/src/xrpld/app/tx/detail/SetTrust.cpp @@ -200,31 +200,27 @@ SetTrust::preclaim(PreclaimContext const& ctx) // This might be nullptr auto const sleDst = ctx.view.read(keylet::account(uDstAccountID)); - if ((ctx.view.rules().enabled(featureDisallowIncoming) || - ammEnabled(ctx.view.rules()) || + if ((ammEnabled(ctx.view.rules()) || ctx.view.rules().enabled(featureSingleAssetVault)) && sleDst == nullptr) return tecNO_DST; // If the destination has opted to disallow incoming trustlines // then honour that flag - if (ctx.view.rules().enabled(featureDisallowIncoming)) + if (sleDst->getFlags() & lsfDisallowIncomingTrustline) { - if (sleDst->getFlags() & lsfDisallowIncomingTrustline) + // The original implementation of featureDisallowIncoming was + // too restrictive. If + // o fixDisallowIncomingV1 is enabled and + // o The trust line already exists + // Then allow the TrustSet. + if (ctx.view.rules().enabled(fixDisallowIncomingV1) && + ctx.view.exists(keylet::line(id, uDstAccountID, currency))) { - // The original implementation of featureDisallowIncoming was - // too restrictive. If - // o fixDisallowIncomingV1 is enabled and - // o The trust line already exists - // Then allow the TrustSet. - if (ctx.view.rules().enabled(fixDisallowIncomingV1) && - ctx.view.exists(keylet::line(id, uDstAccountID, currency))) - { - // pass - } - else - return tecNO_PERMISSION; + // pass } + else + return tecNO_PERMISSION; } // In general, trust lines to pseudo accounts are not permitted, unless diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index 3caafc411b..7365ccc6ef 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -116,11 +116,8 @@ doAccountInfo(RPC::JsonContext& context) for (auto const& lsf : lsFlags) acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); - if (ledger->rules().enabled(featureDisallowIncoming)) - { - for (auto const& lsf : disallowIncomingFlags) - acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); - } + for (auto const& lsf : disallowIncomingFlags) + acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); if (ledger->rules().enabled(featureClawback)) acctFlags[allowTrustLineClawbackFlag.first.data()] = From fb74dc28e1b7cb9f121d024dd896c82f95f538a3 Mon Sep 17 00:00:00 2001 From: Jingchen Date: Fri, 21 Nov 2025 17:11:00 +0000 Subject: [PATCH 013/105] chore: Clean up comment in NetworkOps_test.cpp (#6066) This change removes a copyright notice that was accidentally copied over from another file. --- .github/scripts/rename/copyright.sh | 3 --- src/test/app/NetworkOPs_test.cpp | 2 -- 2 files changed, 5 deletions(-) diff --git a/.github/scripts/rename/copyright.sh b/.github/scripts/rename/copyright.sh index c0f64de496..41dbdc1f94 100755 --- a/.github/scripts/rename/copyright.sh +++ b/.github/scripts/rename/copyright.sh @@ -70,9 +70,6 @@ fi if ! grep -q 'Dev Null' src/test/app/tx/apply_test.cpp; then echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/tx/apply_test.cpp)" > src/test/app/tx/apply_test.cpp fi -if ! grep -q 'Dev Null' src/test/app/NetworkOPs_test.cpp; then - echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/NetworkOPs_test.cpp)" > src/test/app/NetworkOPs_test.cpp -fi if ! grep -q 'Dev Null' src/test/rpc/ManifestRPC_test.cpp; then echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ManifestRPC_test.cpp)" > src/test/rpc/ManifestRPC_test.cpp fi diff --git a/src/test/app/NetworkOPs_test.cpp b/src/test/app/NetworkOPs_test.cpp index d9afe6d628..3965778221 100644 --- a/src/test/app/NetworkOPs_test.cpp +++ b/src/test/app/NetworkOPs_test.cpp @@ -1,5 +1,3 @@ -// Copyright (c) 2020 Dev Null Productions - #include #include #include From 58e03190ac360c53d120e69ab22e96899c824278 Mon Sep 17 00:00:00 2001 From: Vito Tumas <5780819+Tapanito@users.noreply.github.com> Date: Fri, 21 Nov 2025 22:59:12 +0100 Subject: [PATCH 014/105] docs: Improve `VaultWithdraw` documentation (#6068) --- src/xrpld/app/tx/detail/VaultWithdraw.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xrpld/app/tx/detail/VaultWithdraw.cpp b/src/xrpld/app/tx/detail/VaultWithdraw.cpp index 8cd3f5cd97..7777f2257f 100644 --- a/src/xrpld/app/tx/detail/VaultWithdraw.cpp +++ b/src/xrpld/app/tx/detail/VaultWithdraw.cpp @@ -121,6 +121,8 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx) if (auto const ret = checkFrozen(ctx.view, dstAcct, vaultAsset)) return ret; + // Cannot return shares to the vault, if the underlying asset was frozen for + // the submitter if (auto const ret = checkFrozen(ctx.view, account, vaultShare)) return ret; From 8449c6c3655c29c8ee9e3407aa6420f445069388 Mon Sep 17 00:00:00 2001 From: Olek <115580134+oleks-rip@users.noreply.github.com> Date: Fri, 21 Nov 2025 17:20:45 -0500 Subject: [PATCH 015/105] Fix: nullptr resolving without db config (#6029) If the config disables SQL db usage, such as a validator: ``` [ledger_tx_tables] use_tx_tables = 0 ``` then the pointer to DB engine is null, but it was still resolved during startup. Although it didn't crash in Release mode, possibly due to the compiler optimizing it away, it did crash in Debug mode. This change explicitly checks for the validity of the pointer and generates a runtime error if not set. --- src/xrpld/app/rdb/backend/detail/Node.cpp | 12 ++++++++++-- src/xrpld/app/rdb/backend/detail/Node.h | 2 +- src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp | 3 +-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/xrpld/app/rdb/backend/detail/Node.cpp b/src/xrpld/app/rdb/backend/detail/Node.cpp index ed8c5c06aa..04f328390d 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.cpp +++ b/src/xrpld/app/rdb/backend/detail/Node.cpp @@ -171,7 +171,7 @@ getRowsMinMax(soci::session& session, TableType type) bool saveValidatedLedger( DatabaseCon& ldgDB, - DatabaseCon& txnDB, + std::unique_ptr const& txnDB, Application& app, std::shared_ptr const& ledger, bool current) @@ -254,7 +254,15 @@ saveValidatedLedger( if (app.config().useTxTables()) { - auto db = txnDB.checkoutDb(); + if (!txnDB) + { + // LCOV_EXCL_START + JLOG(j.fatal()) << "TxTables db isn't available"; + Throw("TxTables db isn't available"); + // LCOV_EXCL_STOP + } + + auto db = txnDB->checkoutDb(); soci::transaction tr(*db); diff --git a/src/xrpld/app/rdb/backend/detail/Node.h b/src/xrpld/app/rdb/backend/detail/Node.h index 412631571e..2c0fd69445 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.h +++ b/src/xrpld/app/rdb/backend/detail/Node.h @@ -111,7 +111,7 @@ getRowsMinMax(soci::session& session, TableType type); bool saveValidatedLedger( DatabaseCon& ldgDB, - DatabaseCon& txnDB, + std::unique_ptr const& txnDB, Application& app, std::shared_ptr const& ledger, bool current); diff --git a/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp b/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp index 4934205bfd..944ed814f5 100644 --- a/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp +++ b/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp @@ -392,8 +392,7 @@ SQLiteDatabaseImp::saveValidatedLedger( { if (existsLedger()) { - if (!detail::saveValidatedLedger( - *lgrdb_, *txdb_, app_, ledger, current)) + if (!detail::saveValidatedLedger(*lgrdb_, txdb_, app_, ledger, current)) return false; } From 800a315383631e3460a51ee164c87d4032687e28 Mon Sep 17 00:00:00 2001 From: Jingchen Date: Mon, 24 Nov 2025 11:23:16 +0000 Subject: [PATCH 016/105] refactor: Retire CryptoConditionsSuite amendment (#6036) Amendments activated for more than 2 years can be retired. This change retires the CryptoConditionsSuite amendment. --- include/xrpl/protocol/detail/features.macro | 7 ++++--- src/test/rpc/Feature_test.cpp | 17 ++++++++++++++++- src/xrpld/app/tx/detail/Escrow.cpp | 6 ------ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 4180f1e7ff..d7a182faf0 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -79,9 +79,9 @@ XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYe // enabled (added to the ledger). // // If a feature remains obsolete for long enough that no clients are able -// to vote for it, the feature can be removed (entirely?) from the code. -XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete) - +// to vote for it, the feature can be removed entirely from the code. Until +// then the feature needs to be marked explicitly as obsolete, e.g. +// XRPL_FEATURE(Example, Supported::yes, VoteBehavior::Obsolete) // The following amendments have been active for at least two years. Their // pre-amendment code has been removed and the identifiers are deprecated. // All known amendments and amendments that may appear in a validated ledger @@ -117,6 +117,7 @@ XRPL_RETIRE_FIX(TrustLinesToSelf) XRPL_RETIRE_FEATURE(Checks) XRPL_RETIRE_FEATURE(CheckCashMakesTrustLine) XRPL_RETIRE_FEATURE(CryptoConditions) +XRPL_RETIRE_FEATURE(CryptoConditionsSuite) XRPL_RETIRE_FEATURE(DepositAuth) XRPL_RETIRE_FEATURE(DepositPreauth) XRPL_RETIRE_FEATURE(DisallowIncoming) diff --git a/src/test/rpc/Feature_test.cpp b/src/test/rpc/Feature_test.cpp index 10f82ac88d..2158524e3e 100644 --- a/src/test/rpc/Feature_test.cpp +++ b/src/test/rpc/Feature_test.cpp @@ -529,7 +529,22 @@ class Feature_test : public beast::unit_test::suite using namespace test::jtx; Env env{*this}; - constexpr char const* featureName = "CryptoConditionsSuite"; + + auto const& supportedAmendments = detail::supportedAmendments(); + auto obsoleteFeature = std::find_if( + std::begin(supportedAmendments), + std::end(supportedAmendments), + [](auto const& pair) { + return pair.second == VoteBehavior::Obsolete; + }); + + if (obsoleteFeature == std::end(supportedAmendments)) + { + pass(); + return; + } + + auto const featureName = obsoleteFeature->first; auto jrr = env.rpc("feature", featureName)[jss::result]; if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status")) diff --git a/src/xrpld/app/tx/detail/Escrow.cpp b/src/xrpld/app/tx/detail/Escrow.cpp index 5cf90809a2..c22b8145c6 100644 --- a/src/xrpld/app/tx/detail/Escrow.cpp +++ b/src/xrpld/app/tx/detail/Escrow.cpp @@ -153,12 +153,6 @@ EscrowCreate::preflight(PreflightContext const& ctx) << ec.message(); return temMALFORMED; } - - // Conditions other than PrefixSha256 require the - // "CryptoConditionsSuite" amendment: - if (condition->type != Type::preimageSha256 && - !ctx.rules.enabled(featureCryptoConditionsSuite)) - return temDISABLED; } return tesSUCCESS; From a791c03dc16085a7beb0f7683b1d7d3c6d1b8a6f Mon Sep 17 00:00:00 2001 From: Jingchen Date: Mon, 24 Nov 2025 11:52:08 +0000 Subject: [PATCH 017/105] refactor: Retire DeletableAccounts amendment (#6056) Amendments activated for more than 2 years can be retired. This change retires the DeletableAccounts amendment. --- include/xrpl/protocol/detail/features.macro | 2 +- .../xrpl/protocol/detail/transactions.macro | 2 +- src/libxrpl/ledger/View.cpp | 2 +- src/test/app/AccountDelete_test.cpp | 55 ------------------- src/test/app/NFToken_test.cpp | 7 --- src/test/app/TxQ_test.cpp | 2 +- src/test/rpc/Feature_test.cpp | 3 +- src/test/rpc/LedgerClosed_test.cpp | 2 +- src/test/rpc/LedgerRPC_test.cpp | 4 +- src/test/rpc/LedgerRequestRPC_test.cpp | 18 +++--- src/xrpld/app/tx/detail/DeleteAccount.cpp | 3 - src/xrpld/app/tx/detail/InvariantCheck.cpp | 7 +-- src/xrpld/app/tx/detail/Payment.cpp | 6 +- src/xrpld/app/tx/detail/XChainBridge.cpp | 5 +- 14 files changed, 20 insertions(+), 98 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index d7a182faf0..d06d3030f6 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -66,7 +66,6 @@ XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes) -XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes) // The following amendments are obsolete, but must remain supported @@ -118,6 +117,7 @@ XRPL_RETIRE_FEATURE(Checks) XRPL_RETIRE_FEATURE(CheckCashMakesTrustLine) XRPL_RETIRE_FEATURE(CryptoConditions) XRPL_RETIRE_FEATURE(CryptoConditionsSuite) +XRPL_RETIRE_FEATURE(DeletableAccounts) XRPL_RETIRE_FEATURE(DepositAuth) XRPL_RETIRE_FEATURE(DepositPreauth) XRPL_RETIRE_FEATURE(DisallowIncoming) diff --git a/include/xrpl/protocol/detail/transactions.macro b/include/xrpl/protocol/detail/transactions.macro index c3cc2cef76..e551c89e55 100644 --- a/include/xrpl/protocol/detail/transactions.macro +++ b/include/xrpl/protocol/detail/transactions.macro @@ -297,7 +297,7 @@ TRANSACTION(ttTRUST_SET, 20, TrustSet, #endif TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete, Delegation::notDelegatable, - featureDeletableAccounts, + uint256{}, mustDeleteAcct, ({ {sfDestination, soeREQUIRED}, diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 069bd3a4d8..6356dd1131 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -1863,7 +1863,7 @@ rippleSendIOU( // Direct send: redeeming IOUs and/or sending own IOUs. auto const ter = rippleCreditIOU(view, uSenderID, uReceiverID, saAmount, false, j); - if (view.rules().enabled(featureDeletableAccounts) && ter != tesSUCCESS) + if (ter != tesSUCCESS) return ter; saActual = saAmount; return tesSUCCESS; diff --git a/src/test/app/AccountDelete_test.cpp b/src/test/app/AccountDelete_test.cpp index 9d5d1cd877..f22f9c4165 100644 --- a/src/test/app/AccountDelete_test.cpp +++ b/src/test/app/AccountDelete_test.cpp @@ -418,60 +418,6 @@ public: env.close(); } - void - testAmendmentEnable() - { - // Start with the featureDeletableAccounts amendment disabled. - // Then enable the amendment and delete an account. - using namespace jtx; - - testcase("Amendment enable"); - - Env env{*this, testable_amendments() - featureDeletableAccounts}; - Account const alice("alice"); - Account const becky("becky"); - - env.fund(XRP(10000), alice, becky); - env.close(); - - // Close enough ledgers to be able to delete alice's account. - incLgrSeqForAccDel(env, alice); - - // Verify that alice's account root is present. - Keylet const aliceAcctKey{keylet::account(alice.id())}; - BEAST_EXPECT(env.closed()->exists(aliceAcctKey)); - - auto const alicePreDelBal{env.balance(alice)}; - auto const beckyPreDelBal{env.balance(becky)}; - - auto const acctDelFee{drops(env.current()->fees().increment)}; - env(acctdelete(alice, becky), fee(acctDelFee), ter(temDISABLED)); - env.close(); - - // Verify that alice's account root is still present and alice and - // becky both have their XRP. - BEAST_EXPECT(env.current()->exists(aliceAcctKey)); - BEAST_EXPECT(env.balance(alice) == alicePreDelBal); - BEAST_EXPECT(env.balance(becky) == beckyPreDelBal); - - // When the amendment is enabled the previous transaction is - // retried into the new open ledger and succeeds. - env.enableFeature(featureDeletableAccounts); - env.close(); - - // alice's account is still in the most recently closed ledger. - BEAST_EXPECT(env.closed()->exists(aliceAcctKey)); - - // Verify that alice's account root is gone from the current ledger - // and becky has alice's XRP. - BEAST_EXPECT(!env.current()->exists(aliceAcctKey)); - BEAST_EXPECT( - env.balance(becky) == alicePreDelBal + beckyPreDelBal - acctDelFee); - - env.close(); - BEAST_EXPECT(!env.closed()->exists(aliceAcctKey)); - } - void testTooManyOffers() { @@ -1148,7 +1094,6 @@ public: testBasics(); testDirectories(); testOwnedTypes(); - testAmendmentEnable(); testTooManyOffers(); testImplicitlyCreatedTrustline(); testBalanceTooSmallForFee(); diff --git a/src/test/app/NFToken_test.cpp b/src/test/app/NFToken_test.cpp index 12ac309acb..5f57322be1 100644 --- a/src/test/app/NFToken_test.cpp +++ b/src/test/app/NFToken_test.cpp @@ -5720,7 +5720,6 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Close the ledger until the ledger sequence is large enough to delete // the account (no longer within ) - // This is enforced by the featureDeletableAccounts amendment auto incLgrSeqForAcctDel = [&](Env& env, Account const& acct) { int const delta = [&]() -> int { if (env.seq(acct) + 255 > openLedgerSeq(env)) @@ -5839,8 +5838,6 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } env.close(); - // Increment ledger sequence to the number that is - // enforced by the featureDeletableAccounts amendment incLgrSeqForAcctDel(env, alice); // Verify that alice's account root is present. @@ -5943,8 +5940,6 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ticketCount(env, alice) == 0); - // Increment ledger sequence to the number that is - // enforced by the featureDeletableAccounts amendment incLgrSeqForAcctDel(env, alice); // Verify that alice's account root is present. @@ -6053,8 +6048,6 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ticketCount(env, minter) == 0); - // Increment ledger sequence to the number that is - // enforced by the featureDeletableAccounts amendment incLgrSeqForAcctDel(env, alice); // Verify that alice's account root is present. diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index 4b7f156738..8e78969397 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -4330,7 +4330,7 @@ public: Account const ellie("ellie"); Account const fiona("fiona"); - constexpr int ledgersInQueue = 10; + constexpr int ledgersInQueue = 20; auto cfg = makeConfig( {{"minimum_txn_in_ledger_standalone", "1"}, {"ledgers_in_queue", std::to_string(ledgersInQueue)}, diff --git a/src/test/rpc/Feature_test.cpp b/src/test/rpc/Feature_test.cpp index 2158524e3e..374e4735c8 100644 --- a/src/test/rpc/Feature_test.cpp +++ b/src/test/rpc/Feature_test.cpp @@ -124,8 +124,7 @@ class Feature_test : public beast::unit_test::suite featureToName(fixRemoveNFTokenAutoTrustLine) == "fixRemoveNFTokenAutoTrustLine"); BEAST_EXPECT(featureToName(featureFlow) == "Flow"); - BEAST_EXPECT( - featureToName(featureDeletableAccounts) == "DeletableAccounts"); + BEAST_EXPECT(featureToName(featureDID) == "DID"); BEAST_EXPECT( featureToName(fixIncludeKeyletFields) == "fixIncludeKeyletFields"); BEAST_EXPECT(featureToName(featureTokenEscrow) == "TokenEscrow"); diff --git a/src/test/rpc/LedgerClosed_test.cpp b/src/test/rpc/LedgerClosed_test.cpp index b3a5e60afd..ba25a115c3 100644 --- a/src/test/rpc/LedgerClosed_test.cpp +++ b/src/test/rpc/LedgerClosed_test.cpp @@ -38,7 +38,7 @@ public: lc_result = env.rpc("ledger_closed")[jss::result]; BEAST_EXPECT( lc_result[jss::ledger_hash] == - "E86DE7F3D7A4D9CE17EF7C8BA08A8F4D8F643B9552F0D895A31CDA78F541DE4E"); + "0F1A9E0C109ADEF6DA2BDE19217C12BBEC57174CBDBD212B0EBDC1CEDB853185"); BEAST_EXPECT(lc_result[jss::ledger_index] == 3); } diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 2d9daa5d9d..57a20527d0 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -307,8 +307,8 @@ class LedgerRPC_test : public beast::unit_test::suite { std::string const hash3{ - "E86DE7F3D7A4D9CE17EF7C8BA08A8F4D" - "8F643B9552F0D895A31CDA78F541DE4E"}; + "0F1A9E0C109ADEF6DA2BDE19217C12BBEC57174CBDBD212B0EBDC1CEDB8531" + "85"}; // access via the ledger_hash field Json::Value jvParams; jvParams[jss::ledger_hash] = hash3; diff --git a/src/test/rpc/LedgerRequestRPC_test.cpp b/src/test/rpc/LedgerRequestRPC_test.cpp index 5917dcedf2..0751b120aa 100644 --- a/src/test/rpc/LedgerRequestRPC_test.cpp +++ b/src/test/rpc/LedgerRequestRPC_test.cpp @@ -200,7 +200,7 @@ public: result = env.rpc("ledger_request", "3")[jss::result]; constexpr char const* hash3 = - "8D631B20BC989AF568FBA97375290544B0703A5ADC1CF9E9053580461690C9EE"; + "9FFD8AE09190D5002FE4252A1B29EABCF40DABBCE3B42619C6BD0BE381D51103"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "3"); BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "99999999999999980"); @@ -209,14 +209,14 @@ public: BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash2); BEAST_EXPECT( result[jss::ledger][jss::account_hash] == - "BC9EF2A16BFF80BCFABA6FA84688D858D33BD0FA0435CAA9DF6DA4105A39A29E"); + "35738B8517F37D08983AF6BC7DA483CCA9CF6B41B1FECB31A20028D78FE0BB22"); BEAST_EXPECT( result[jss::ledger][jss::transaction_hash] == - "0213EC486C058B3942FBE3DAC6839949A5C5B02B8B4244C8998EFDF04DBD8222"); + "CBD7F0948EBFA2241DE4EA627939A0FFEE6B80A90FE09C42C825DA546E9B73FF"); result = env.rpc("ledger_request", "4")[jss::result]; constexpr char const* hash4 = - "1A8E7098B23597E73094DADA58C9D62F3AB93A12C6F7666D56CA85A6CFDE530F"; + "7C9B614445517B8C6477E0AB10A35FFC1A23A34FEA41A91ECBDE884CC097C6E1"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "4"); BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "99999999999999960"); @@ -225,14 +225,14 @@ public: BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash3); BEAST_EXPECT( result[jss::ledger][jss::account_hash] == - "C690188F123C91355ADA8BDF4AC5B5C927076D3590C215096868A5255264C6DD"); + "1EE701DD2A150205173E1EDE8D474DF6803EC95253DAAEE965B9D896CFC32A04"); BEAST_EXPECT( result[jss::ledger][jss::transaction_hash] == - "3CBDB8F42E04333E1642166BFB93AC9A7E1C6C067092CD5D881D6F3AB3D67E76"); + "9BBDDBF926100DFFF364E16268F544B19F5B9BC6ECCBBC104F98D13FA9F3BC35"); result = env.rpc("ledger_request", "5")[jss::result]; constexpr char const* hash5 = - "C6A222D71AE65D7B4F240009EAD5DEB20D7EEDE5A4064F28BBDBFEEB6FBE48E5"; + "98885D02145CCE4AD2605F1809F17188DB2053B14ED399CAC985DD8E03DCA8C0"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "5"); BEAST_EXPECT( result[jss::ledger][jss::total_coins] == "99999999999999940"); @@ -241,10 +241,10 @@ public: BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash4); BEAST_EXPECT( result[jss::ledger][jss::account_hash] == - "EA81CD9D36740736F00CB747E0D0E32D3C10B695823D961F0FB9A1CE7133DD4D"); + "41D64D64796468DEA7AE2A7282C0BB525D6FD7ABC29453C5E5BC6406E947CBCE"); BEAST_EXPECT( result[jss::ledger][jss::transaction_hash] == - "C3D086CD6BDB9E97AD1D513B2C049EF2840BD21D0B3E22D84EBBB89B6D2EF59D"); + "8FE8592EF22FBC2E8C774C7A1ED76AA3FCE64BED17D748CBA9AFDF7072FE36C7"); result = env.rpc("ledger_request", "6")[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); diff --git a/src/xrpld/app/tx/detail/DeleteAccount.cpp b/src/xrpld/app/tx/detail/DeleteAccount.cpp index 0654c8dbce..c9fd0cc75e 100644 --- a/src/xrpld/app/tx/detail/DeleteAccount.cpp +++ b/src/xrpld/app/tx/detail/DeleteAccount.cpp @@ -22,9 +22,6 @@ namespace ripple { bool DeleteAccount::checkExtraFeatures(PreflightContext const& ctx) { - if (!ctx.rules.enabled(featureDeletableAccounts)) - return false; - if (ctx.tx.isFieldPresent(sfCredentialIDs) && !ctx.rules.enabled(featureCredentials)) return false; diff --git a/src/xrpld/app/tx/detail/InvariantCheck.cpp b/src/xrpld/app/tx/detail/InvariantCheck.cpp index c15f2b64a5..80c41f4d2b 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.cpp +++ b/src/xrpld/app/tx/detail/InvariantCheck.cpp @@ -1028,12 +1028,7 @@ ValidNewAccountRoot::finalize( return false; } - std::uint32_t const startingSeq = // - pseudoAccount // - ? 0 // - : view.rules().enabled(featureDeletableAccounts) // - ? view.seq() // - : 1; + std::uint32_t const startingSeq = pseudoAccount ? 0 : view.seq(); if (accountSeq_ != startingSeq) { diff --git a/src/xrpld/app/tx/detail/Payment.cpp b/src/xrpld/app/tx/detail/Payment.cpp index 3aff4db5e1..56aeb1b0aa 100644 --- a/src/xrpld/app/tx/detail/Payment.cpp +++ b/src/xrpld/app/tx/detail/Payment.cpp @@ -398,14 +398,10 @@ Payment::doApply() if (!sleDst) { - std::uint32_t const seqno{ - view().rules().enabled(featureDeletableAccounts) ? view().seq() - : 1}; - // Create the account. sleDst = std::make_shared(k); sleDst->setAccountID(sfAccount, dstAccountID); - sleDst->setFieldU32(sfSequence, seqno); + sleDst->setFieldU32(sfSequence, view().seq()); view().insert(sleDst); } diff --git a/src/xrpld/app/tx/detail/XChainBridge.cpp b/src/xrpld/app/tx/detail/XChainBridge.cpp index 554d4a8436..e555dca0a1 100644 --- a/src/xrpld/app/tx/detail/XChainBridge.cpp +++ b/src/xrpld/app/tx/detail/XChainBridge.cpp @@ -464,12 +464,9 @@ transferHelper( } // Create the account. - std::uint32_t const seqno{ - psb.rules().enabled(featureDeletableAccounts) ? psb.seq() : 1}; - sleDst = std::make_shared(dstK); sleDst->setAccountID(sfAccount, dst); - sleDst->setFieldU32(sfSequence, seqno); + sleDst->setFieldU32(sfSequence, psb.seq()); psb.insert(sleDst); } From 21c02232a54e0069a7a0e7c40e0d74259d46ecec Mon Sep 17 00:00:00 2001 From: Jingchen Date: Mon, 24 Nov 2025 13:58:37 +0000 Subject: [PATCH 018/105] refactor: Retire RequireFullyCanonicalSig amendment (#6035) Amendments activated for more than 2 years can be retired. This change retires the RequireFullyCanonicalSig amendment. --- include/xrpl/protocol/PublicKey.h | 6 +- include/xrpl/protocol/STTx.h | 36 ++-------- include/xrpl/protocol/detail/features.macro | 2 +- src/libxrpl/protocol/PublicKey.cpp | 9 +-- src/libxrpl/protocol/STTx.cpp | 76 ++++++--------------- src/test/app/tx/apply_test.cpp | 17 ----- src/test/ledger/View_test.cpp | 6 +- src/test/protocol/STTx_test.cpp | 3 +- src/test/protocol/SecretKey_test.cpp | 8 +-- src/test/rpc/Feature_test.cpp | 18 ++--- src/xrpld/app/tx/detail/Batch.cpp | 3 +- src/xrpld/app/tx/detail/PayChan.cpp | 2 +- src/xrpld/app/tx/detail/apply.cpp | 8 +-- src/xrpld/rpc/handlers/PayChanClaim.cpp | 3 +- 14 files changed, 51 insertions(+), 146 deletions(-) diff --git a/include/xrpl/protocol/PublicKey.h b/include/xrpl/protocol/PublicKey.h index 445e0e3b97..8d8062408b 100644 --- a/include/xrpl/protocol/PublicKey.h +++ b/include/xrpl/protocol/PublicKey.h @@ -231,11 +231,7 @@ verifyDigest( SHA512-Half, and the resulting digest is signed. */ [[nodiscard]] bool -verify( - PublicKey const& publicKey, - Slice const& m, - Slice const& sig, - bool mustBeFullyCanonical = true) noexcept; +verify(PublicKey const& publicKey, Slice const& m, Slice const& sig) noexcept; /** Calculate the 160-bit node ID from a node public key. */ NodeID diff --git a/include/xrpl/protocol/STTx.h b/include/xrpl/protocol/STTx.h index 716881d910..02f865e349 100644 --- a/include/xrpl/protocol/STTx.h +++ b/include/xrpl/protocol/STTx.h @@ -103,22 +103,15 @@ public: std::optional> signatureTarget = {}); - enum class RequireFullyCanonicalSig : bool { no, yes }; - /** Check the signature. - @param requireCanonicalSig If `true`, check that the signature is fully - canonical. If `false`, only check that the signature is valid. @param rules The current ledger rules. @return `true` if valid signature. If invalid, the error message string. */ Expected - checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const& rules) - const; + checkSign(Rules const& rules) const; Expected - checkBatchSign( - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules) const; + checkBatchSign(Rules const& rules) const; // SQL Functions with metadata. static std::string const& @@ -140,40 +133,25 @@ public: private: /** Check the signature. - @param requireCanonicalSig If `true`, check that the signature is fully - canonical. If `false`, only check that the signature is valid. @param rules The current ledger rules. @param sigObject Reference to object that contains the signature fields. Will be *this more often than not. @return `true` if valid signature. If invalid, the error message string. */ Expected - checkSign( - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules, - STObject const& sigObject) const; + checkSign(Rules const& rules, STObject const& sigObject) const; Expected - checkSingleSign( - RequireFullyCanonicalSig requireCanonicalSig, - STObject const& sigObject) const; + checkSingleSign(STObject const& sigObject) const; Expected - checkMultiSign( - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules, - STObject const& sigObject) const; + checkMultiSign(Rules const& rules, STObject const& sigObject) const; Expected - checkBatchSingleSign( - STObject const& batchSigner, - RequireFullyCanonicalSig requireCanonicalSig) const; + checkBatchSingleSign(STObject const& batchSigner) const; Expected - checkBatchMultiSign( - STObject const& batchSigner, - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules) const; + checkBatchMultiSign(STObject const& batchSigner, Rules const& rules) const; STBase* copy(std::size_t n, void* buf) const override; diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index d06d3030f6..054b9d0a03 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -65,7 +65,6 @@ XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes) -XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes) // The following amendments are obsolete, but must remain supported @@ -133,6 +132,7 @@ XRPL_RETIRE_FEATURE(MultiSignReserve) XRPL_RETIRE_FEATURE(NegativeUNL) XRPL_RETIRE_FEATURE(NonFungibleTokensV1_1) XRPL_RETIRE_FEATURE(PayChan) +XRPL_RETIRE_FEATURE(RequireFullyCanonicalSig) XRPL_RETIRE_FEATURE(SortedDirectories) XRPL_RETIRE_FEATURE(TicketBatch) XRPL_RETIRE_FEATURE(TickSize) diff --git a/src/libxrpl/protocol/PublicKey.cpp b/src/libxrpl/protocol/PublicKey.cpp index 0a29af7d32..f1794331ad 100644 --- a/src/libxrpl/protocol/PublicKey.cpp +++ b/src/libxrpl/protocol/PublicKey.cpp @@ -267,18 +267,13 @@ verifyDigest( } bool -verify( - PublicKey const& publicKey, - Slice const& m, - Slice const& sig, - bool mustBeFullyCanonical) noexcept +verify(PublicKey const& publicKey, Slice const& m, Slice const& sig) noexcept { if (auto const type = publicKeyType(publicKey)) { if (*type == KeyType::secp256k1) { - return verifyDigest( - publicKey, sha512Half(m), sig, mustBeFullyCanonical); + return verifyDigest(publicKey, sha512Half(m), sig); } else if (*type == KeyType::ed25519) { diff --git a/src/libxrpl/protocol/STTx.cpp b/src/libxrpl/protocol/STTx.cpp index dbcf1f304e..b89f337288 100644 --- a/src/libxrpl/protocol/STTx.cpp +++ b/src/libxrpl/protocol/STTx.cpp @@ -237,10 +237,7 @@ STTx::sign( } Expected -STTx::checkSign( - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules, - STObject const& sigObject) const +STTx::checkSign(Rules const& rules, STObject const& sigObject) const { try { @@ -249,9 +246,8 @@ STTx::checkSign( // multi-signing. Otherwise we're single-signing. Blob const& signingPubKey = sigObject.getFieldVL(sfSigningPubKey); - return signingPubKey.empty() - ? checkMultiSign(requireCanonicalSig, rules, sigObject) - : checkSingleSign(requireCanonicalSig, sigObject); + return signingPubKey.empty() ? checkMultiSign(rules, sigObject) + : checkSingleSign(sigObject); } catch (std::exception const&) { @@ -260,18 +256,16 @@ STTx::checkSign( } Expected -STTx::checkSign( - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules) const +STTx::checkSign(Rules const& rules) const { - if (auto const ret = checkSign(requireCanonicalSig, rules, *this); !ret) + if (auto const ret = checkSign(rules, *this); !ret) return ret; /* Placeholder for field that will be added by Lending Protocol if (isFieldPresent(sfCounterpartySignature)) { auto const counterSig = getFieldObject(sfCounterpartySignature); - if (auto const ret = checkSign(requireCanonicalSig, rules, counterSig); + if (auto const ret = checkSign(rules, counterSig); !ret) return Unexpected("Counterparty: " + ret.error()); } @@ -280,9 +274,7 @@ STTx::checkSign( } Expected -STTx::checkBatchSign( - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules) const +STTx::checkBatchSign(Rules const& rules) const { try { @@ -299,8 +291,8 @@ STTx::checkBatchSign( { Blob const& signingPubKey = signer.getFieldVL(sfSigningPubKey); auto const result = signingPubKey.empty() - ? checkBatchMultiSign(signer, requireCanonicalSig, rules) - : checkBatchSingleSign(signer, requireCanonicalSig); + ? checkBatchMultiSign(signer, rules) + : checkBatchSingleSign(signer); if (!result) return result; @@ -395,10 +387,7 @@ STTx::getMetaSQL( } static Expected -singleSignHelper( - STObject const& sigObject, - Slice const& data, - bool const fullyCanonical) +singleSignHelper(STObject const& sigObject, Slice const& data) { // We don't allow both a non-empty sfSigningPubKey and an sfSigners. // That would allow the transaction to be signed two ways. So if both @@ -413,11 +402,8 @@ singleSignHelper( if (publicKeyType(makeSlice(spk))) { Blob const signature = sigObject.getFieldVL(sfTxnSignature); - validSig = verify( - PublicKey(makeSlice(spk)), - data, - makeSlice(signature), - fullyCanonical); + validSig = + verify(PublicKey(makeSlice(spk)), data, makeSlice(signature)); } } catch (std::exception const&) @@ -432,33 +418,24 @@ singleSignHelper( } Expected -STTx::checkSingleSign( - RequireFullyCanonicalSig requireCanonicalSig, - STObject const& sigObject) const +STTx::checkSingleSign(STObject const& sigObject) const { auto const data = getSigningData(*this); - bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) || - (requireCanonicalSig == STTx::RequireFullyCanonicalSig::yes); - return singleSignHelper(sigObject, makeSlice(data), fullyCanonical); + return singleSignHelper(sigObject, makeSlice(data)); } Expected -STTx::checkBatchSingleSign( - STObject const& batchSigner, - RequireFullyCanonicalSig requireCanonicalSig) const +STTx::checkBatchSingleSign(STObject const& batchSigner) const { Serializer msg; serializeBatch(msg, getFlags(), getBatchTransactionIDs()); - bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) || - (requireCanonicalSig == STTx::RequireFullyCanonicalSig::yes); - return singleSignHelper(batchSigner, msg.slice(), fullyCanonical); + return singleSignHelper(batchSigner, msg.slice()); } Expected multiSignHelper( STObject const& sigObject, std::optional txnAccountID, - bool const fullyCanonical, std::function makeMsg, Rules const& rules) { @@ -515,8 +492,7 @@ multiSignHelper( validSig = verify( PublicKey(makeSlice(spk)), makeMsg(accountID).slice(), - makeSlice(signature), - fullyCanonical); + makeSlice(signature)); } } catch (std::exception const& e) @@ -535,14 +511,8 @@ multiSignHelper( } Expected -STTx::checkBatchMultiSign( - STObject const& batchSigner, - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules) const +STTx::checkBatchMultiSign(STObject const& batchSigner, Rules const& rules) const { - bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) || - (requireCanonicalSig == RequireFullyCanonicalSig::yes); - // We can ease the computational load inside the loop a bit by // pre-constructing part of the data that we hash. Fill a Serializer // with the stuff that stays constant from signature to signature. @@ -551,7 +521,6 @@ STTx::checkBatchMultiSign( return multiSignHelper( batchSigner, std::nullopt, - fullyCanonical, [&dataStart](AccountID const& accountID) -> Serializer { Serializer s = dataStart; finishMultiSigningData(accountID, s); @@ -561,14 +530,8 @@ STTx::checkBatchMultiSign( } Expected -STTx::checkMultiSign( - RequireFullyCanonicalSig requireCanonicalSig, - Rules const& rules, - STObject const& sigObject) const +STTx::checkMultiSign(Rules const& rules, STObject const& sigObject) const { - bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) || - (requireCanonicalSig == RequireFullyCanonicalSig::yes); - // Used inside the loop in multiSignHelper to enforce that // the account owner may not multisign for themselves. auto const txnAccountID = &sigObject != this @@ -582,7 +545,6 @@ STTx::checkMultiSign( return multiSignHelper( sigObject, txnAccountID, - fullyCanonical, [&dataStart](AccountID const& accountID) -> Serializer { Serializer s = dataStart; finishMultiSigningData(accountID, s); diff --git a/src/test/app/tx/apply_test.cpp b/src/test/app/tx/apply_test.cpp index 236905cefd..308ad3d3b8 100644 --- a/src/test/app/tx/apply_test.cpp +++ b/src/test/app/tx/apply_test.cpp @@ -35,23 +35,6 @@ public: SerialIter sitTrans(makeSlice(*ret)); STTx const tx = *std::make_shared(std::ref(sitTrans)); - { - test::jtx::Env no_fully_canonical( - *this, - test::jtx::testable_amendments() - - featureRequireFullyCanonicalSig); - - Validity valid = checkValidity( - no_fully_canonical.app().getHashRouter(), - tx, - no_fully_canonical.current()->rules(), - no_fully_canonical.app().config()) - .first; - - if (valid != Validity::Valid) - fail("Non-Fully canonical signature was not permitted"); - } - { test::jtx::Env fully_canonical( *this, test::jtx::testable_amendments()); diff --git a/src/test/ledger/View_test.cpp b/src/test/ledger/View_test.cpp index b7dbf4ec9e..ab978fda59 100644 --- a/src/test/ledger/View_test.cpp +++ b/src/test/ledger/View_test.cpp @@ -1114,10 +1114,10 @@ class GetAmendments_test : public beast::unit_test::suite break; } - // There should be at least 5 amendments. Don't do exact comparison + // There should be at least 3 amendments. Don't do exact comparison // to avoid maintenance as more amendments are added in the future. BEAST_EXPECT(i == 254); - BEAST_EXPECT(majorities.size() >= 5); + BEAST_EXPECT(majorities.size() >= 3); // None of the amendments should be enabled yet. auto enableds = getEnabledAmendments(*env.closed()); @@ -1135,7 +1135,7 @@ class GetAmendments_test : public beast::unit_test::suite break; } BEAST_EXPECT(i == 255); - BEAST_EXPECT(enableds.size() >= 5); + BEAST_EXPECT(enableds.size() >= 3); } void diff --git a/src/test/protocol/STTx_test.cpp b/src/test/protocol/STTx_test.cpp index 8a434486ea..50cd8c511f 100644 --- a/src/test/protocol/STTx_test.cpp +++ b/src/test/protocol/STTx_test.cpp @@ -1615,8 +1615,7 @@ public: BEAST_EXPECT(!defaultRules.enabled(featureAMM)); unexpected( - !j.checkSign(STTx::RequireFullyCanonicalSig::yes, defaultRules), - "Transaction fails signature test"); + !j.checkSign(defaultRules), "Transaction fails signature test"); Serializer rawTxn; j.add(rawTxn); diff --git a/src/test/protocol/SecretKey_test.cpp b/src/test/protocol/SecretKey_test.cpp index bd7e2ccfe4..803988e9d5 100644 --- a/src/test/protocol/SecretKey_test.cpp +++ b/src/test/protocol/SecretKey_test.cpp @@ -145,7 +145,7 @@ public: auto sig = sign(pk, sk, makeSlice(data)); BEAST_EXPECT(sig.size() != 0); - BEAST_EXPECT(verify(pk, makeSlice(data), sig, true)); + BEAST_EXPECT(verify(pk, makeSlice(data), sig)); // Construct wrong data: auto badData = data; @@ -156,17 +156,17 @@ public: std::max_element(badData.begin(), badData.end())); // Wrong data: should fail - BEAST_EXPECT(!verify(pk, makeSlice(badData), sig, true)); + BEAST_EXPECT(!verify(pk, makeSlice(badData), sig)); // Slightly change the signature: if (auto ptr = sig.data()) ptr[j % sig.size()]++; // Wrong signature: should fail - BEAST_EXPECT(!verify(pk, makeSlice(data), sig, true)); + BEAST_EXPECT(!verify(pk, makeSlice(data), sig)); // Wrong data and signature: should fail - BEAST_EXPECT(!verify(pk, makeSlice(badData), sig, true)); + BEAST_EXPECT(!verify(pk, makeSlice(badData), sig)); } } } diff --git a/src/test/rpc/Feature_test.cpp b/src/test/rpc/Feature_test.cpp index 374e4735c8..e01f7566ac 100644 --- a/src/test/rpc/Feature_test.cpp +++ b/src/test/rpc/Feature_test.cpp @@ -183,16 +183,16 @@ class Feature_test : public beast::unit_test::suite using namespace test::jtx; Env env{*this}; - auto jrr = env.rpc("feature", "RequireFullyCanonicalSig")[jss::result]; + auto jrr = env.rpc("feature", "Flow")[jss::result]; BEAST_EXPECTS(jrr[jss::status] == jss::success, "status"); jrr.removeMember(jss::status); BEAST_EXPECT(jrr.size() == 1); BEAST_EXPECT( - jrr.isMember("00C1FC4A53E60AB02C864641002B3172F38677E29C26C54066851" - "79B37E1EDAC")); + jrr.isMember("740352F2412A9909880C23A559FCECEDA3BE2126FED62FC7660D6" + "28A06927F11")); auto feature = *(jrr.begin()); - BEAST_EXPECTS(feature[jss::name] == "RequireFullyCanonicalSig", "name"); + BEAST_EXPECTS(feature[jss::name] == "Flow", "name"); BEAST_EXPECTS(!feature[jss::enabled].asBool(), "enabled"); BEAST_EXPECTS( feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(), @@ -200,7 +200,7 @@ class Feature_test : public beast::unit_test::suite BEAST_EXPECTS(feature[jss::supported].asBool(), "supported"); // feature names are case-sensitive - expect error here - jrr = env.rpc("feature", "requireFullyCanonicalSig")[jss::result]; + jrr = env.rpc("feature", "flow")[jss::result]; BEAST_EXPECT(jrr[jss::error] == "badFeature"); BEAST_EXPECT(jrr[jss::error_message] == "Feature unknown or invalid."); } @@ -419,9 +419,9 @@ class Feature_test : public beast::unit_test::suite break; } - // There should be at least 5 amendments. Don't do exact comparison + // There should be at least 3 amendments. Don't do exact comparison // to avoid maintenance as more amendments are added in the future. - BEAST_EXPECT(majorities.size() >= 5); + BEAST_EXPECT(majorities.size() >= 3); std::map const& votes = ripple::detail::supportedAmendments(); @@ -476,8 +476,8 @@ class Feature_test : public beast::unit_test::suite testcase("Veto"); using namespace test::jtx; - Env env{*this, FeatureBitset{featureRequireFullyCanonicalSig}}; - constexpr char const* featureName = "RequireFullyCanonicalSig"; + Env env{*this, FeatureBitset{featureFlow}}; + constexpr char const* featureName = "Flow"; auto jrr = env.rpc("feature", featureName)[jss::result]; if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status")) diff --git a/src/xrpld/app/tx/detail/Batch.cpp b/src/xrpld/app/tx/detail/Batch.cpp index a2c51d6c82..b233249170 100644 --- a/src/xrpld/app/tx/detail/Batch.cpp +++ b/src/xrpld/app/tx/detail/Batch.cpp @@ -451,8 +451,7 @@ Batch::preflightSigValidated(PreflightContext const& ctx) } // Check the batch signers signatures. - auto const sigResult = ctx.tx.checkBatchSign( - STTx::RequireFullyCanonicalSig::yes, ctx.rules); + auto const sigResult = ctx.tx.checkBatchSign(ctx.rules); if (!sigResult) { diff --git a/src/xrpld/app/tx/detail/PayChan.cpp b/src/xrpld/app/tx/detail/PayChan.cpp index b52ae78523..ae47036ab6 100644 --- a/src/xrpld/app/tx/detail/PayChan.cpp +++ b/src/xrpld/app/tx/detail/PayChan.cpp @@ -440,7 +440,7 @@ PayChanClaim::preflight(PreflightContext const& ctx) PublicKey const pk(ctx.tx[sfPublicKey]); Serializer msg; serializePayChanAuthorization(msg, k.key, authAmt); - if (!verify(pk, msg.slice(), *sig, /*canonical*/ true)) + if (!verify(pk, msg.slice(), *sig)) return temBAD_SIGNATURE; } diff --git a/src/xrpld/app/tx/detail/apply.cpp b/src/xrpld/app/tx/detail/apply.cpp index e9709c20f5..06be378c2b 100644 --- a/src/xrpld/app/tx/detail/apply.cpp +++ b/src/xrpld/app/tx/detail/apply.cpp @@ -58,13 +58,7 @@ checkValidity( if (!any(flags & SF_SIGGOOD)) { - // Don't know signature state. Check it. - auto const requireCanonicalSig = - rules.enabled(featureRequireFullyCanonicalSig) - ? STTx::RequireFullyCanonicalSig::yes - : STTx::RequireFullyCanonicalSig::no; - - auto const sigVerify = tx.checkSign(requireCanonicalSig, rules); + auto const sigVerify = tx.checkSign(rules); if (!sigVerify) { router.setFlags(id, SF_SIGBAD); diff --git a/src/xrpld/rpc/handlers/PayChanClaim.cpp b/src/xrpld/rpc/handlers/PayChanClaim.cpp index dd36a873f0..95c4ba5f3d 100644 --- a/src/xrpld/rpc/handlers/PayChanClaim.cpp +++ b/src/xrpld/rpc/handlers/PayChanClaim.cpp @@ -137,8 +137,7 @@ doChannelVerify(RPC::JsonContext& context) serializePayChanAuthorization(msg, channelId, XRPAmount(drops)); Json::Value result; - result[jss::signature_verified] = - verify(*pk, msg.slice(), makeSlice(*sig), /*canonical*/ true); + result[jss::signature_verified] = verify(*pk, msg.slice(), makeSlice(*sig)); return result; } From b550dc00edc62f2974f2eaee50d58cd1aecdca80 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 24 Nov 2025 21:43:39 -0500 Subject: [PATCH 019/105] ci: Remove missing commits check (#6077) This change removes the CI check for missing commits, as well as a stray path to the publish-docs workflow that isn't used in the on-trigger workflow. --- .github/workflows/on-trigger.yml | 6 -- .../reusable-check-missing-commits.yml | 62 ------------------- 2 files changed, 68 deletions(-) delete mode 100644 .github/workflows/reusable-check-missing-commits.yml diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml index 9df6417c07..b5a56fb671 100644 --- a/.github/workflows/on-trigger.yml +++ b/.github/workflows/on-trigger.yml @@ -14,9 +14,7 @@ on: - "master" paths: # These paths are unique to `on-trigger.yml`. - - ".github/workflows/reusable-check-missing-commits.yml" - ".github/workflows/on-trigger.yml" - - ".github/workflows/publish-docs.yml" # Keep the paths below in sync with those in `on-pr.yml`. - ".github/actions/build-deps/**" @@ -63,10 +61,6 @@ defaults: shell: bash jobs: - check-missing-commits: - if: ${{ github.event_name == 'push' && github.ref_type == 'branch' && contains(fromJSON('["develop", "release"]'), github.ref_name) }} - uses: ./.github/workflows/reusable-check-missing-commits.yml - build-test: uses: ./.github/workflows/reusable-build-test.yml strategy: diff --git a/.github/workflows/reusable-check-missing-commits.yml b/.github/workflows/reusable-check-missing-commits.yml deleted file mode 100644 index 07d29174d8..0000000000 --- a/.github/workflows/reusable-check-missing-commits.yml +++ /dev/null @@ -1,62 +0,0 @@ -# This workflow checks that all commits in the "master" branch are also in the -# "release" and "develop" branches, and that all commits in the "release" branch -# are also in the "develop" branch. -name: Check for missing commits - -# This workflow can only be triggered by other workflows. -on: workflow_call - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-missing-commits - cancel-in-progress: true - -defaults: - run: - shell: bash - -jobs: - check: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - fetch-depth: 0 - - name: Check for missing commits - env: - MESSAGE: | - - If you are reading this, then the commits indicated above are missing - from the "develop" and/or "release" branch. Do a reverse-merge as soon - as possible. See CONTRIBUTING.md for instructions. - run: | - set -o pipefail - # Branches are ordered by how "canonical" they are. Every commit in one - # branch should be in all the branches behind it. - order=(master release develop) - branches=() - for branch in "${order[@]}"; do - # Check that the branches exist so that this job will work on forked - # repos, which don't necessarily have master and release branches. - echo "Checking if ${branch} exists." - if git ls-remote --exit-code --heads origin \ - refs/heads/${branch} > /dev/null; then - branches+=(origin/${branch}) - fi - done - - prior=() - for branch in "${branches[@]}"; do - if [[ ${#prior[@]} -ne 0 ]]; then - echo "Checking ${prior[@]} for commits missing from ${branch}." - git log --oneline --no-merges "${prior[@]}" \ - ^$branch | tee -a "missing-commits.txt" - echo - fi - prior+=("${branch}") - done - - if [[ $(cat missing-commits.txt | wc -l) -ne 0 ]]; then - echo "${MESSAGE}" - exit 1 - fi From b124c9f7e3383d6a64a4d7623f5ea089dbef61d2 Mon Sep 17 00:00:00 2001 From: Jingchen Date: Tue, 25 Nov 2025 14:21:17 +0000 Subject: [PATCH 020/105] refactor: Retire Flow and FlowSortStrands amendments (#6054) Amendments activated for more than 2 years can be retired. This change retires the Flow and FlowSortStrands amendments. --- include/xrpl/protocol/detail/features.macro | 4 +- src/test/app/CrossingLimits_test.cpp | 39 ++++------------- src/test/app/TxQ_test.cpp | 4 +- src/test/jtx/Env_test.cpp | 20 ++++++--- src/test/ledger/View_test.cpp | 4 +- src/test/rpc/Feature_test.cpp | 20 ++++----- src/xrpld/app/paths/RippleCalc.cpp | 9 ---- src/xrpld/app/paths/detail/StrandFlow.h | 48 ++++----------------- 8 files changed, 47 insertions(+), 101 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 054b9d0a03..5f1eca7afe 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -64,8 +64,6 @@ XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes) -XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes) -XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes) // The following amendments are obsolete, but must remain supported // because they could potentially get enabled. @@ -124,7 +122,9 @@ XRPL_RETIRE_FEATURE(Escrow) XRPL_RETIRE_FEATURE(EnforceInvariants) XRPL_RETIRE_FEATURE(ExpandedSignerList) XRPL_RETIRE_FEATURE(FeeEscalation) +XRPL_RETIRE_FEATURE(Flow) XRPL_RETIRE_FEATURE(FlowCross) +XRPL_RETIRE_FEATURE(FlowSortStrands) XRPL_RETIRE_FEATURE(HardenedValidations) XRPL_RETIRE_FEATURE(ImmediateOfferKilled) XRPL_RETIRE_FEATURE(MultiSign) diff --git a/src/test/app/CrossingLimits_test.cpp b/src/test/app/CrossingLimits_test.cpp index 8f0483b590..13d7aef505 100644 --- a/src/test/app/CrossingLimits_test.cpp +++ b/src/test/app/CrossingLimits_test.cpp @@ -267,9 +267,8 @@ public: // strand dry until the liquidity is actually used) // The implementation allows any single step to consume at most 1000 - // offers. With the `FlowSortStrands` feature enabled, if the total - // number of offers consumed by all the steps combined exceeds 1500, the - // payment stops. + // offers.If the total number of offers consumed by all the steps + // combined exceeds 1500, the payment stops. { Env env(*this, features); @@ -457,16 +456,12 @@ public: // below the limit. However, if all the offers are consumed it would // create a tecOVERSIZE error. - // The featureFlowSortStrands introduces a way of tracking the total - // number of consumed offers; with this feature the transaction no - // longer fails with a tecOVERSIZE error. // The implementation allows any single step to consume at most 1000 - // offers. With the `FlowSortStrands` feature enabled, if the total - // number of offers consumed by all the steps combined exceeds 1500, the - // payment stops. Since the first set of offers consumes 998 offers, the - // second set will consume 998, which is not over the limit and the - // payment stops. So 2*998, or 1996 is the expected value when - // `FlowSortStrands` is enabled. + // offers. If the total number of offers consumed by all the steps + // combined exceeds 1500, the payment stops. Since the first set of + // offers consumes 998 offers, the second set will consume 998, which is + // not over the limit and the payment stops. So 2*998, or 1996 is the + // expected value. n_offers(env, 998, alice, XRP(1.00), USD(1)); n_offers(env, 998, alice, XRP(0.99), USD(1)); n_offers(env, 998, alice, XRP(0.98), USD(1)); @@ -474,24 +469,10 @@ public: n_offers(env, 998, alice, XRP(0.96), USD(1)); n_offers(env, 998, alice, XRP(0.95), USD(1)); - bool const withSortStrands = features[featureFlowSortStrands]; - - auto const expectedTER = [&]() -> TER { - if (!withSortStrands) - return TER{tecOVERSIZE}; - return tesSUCCESS; - }(); - - env(offer(bob, USD(8000), XRP(8000)), ter(expectedTER)); + env(offer(bob, USD(8000), XRP(8000)), ter(tesSUCCESS)); env.close(); - auto const expectedUSD = [&] { - if (!withSortStrands) - return USD(0); - return USD(1996); - }(); - - env.require(balance(bob, expectedUSD)); + env.require(balance(bob, USD(1996))); } void @@ -507,9 +488,7 @@ public: using namespace jtx; auto const sa = testable_amendments(); testAll(sa); - testAll(sa - featureFlowSortStrands); testAll(sa - featurePermissionedDEX); - testAll(sa - featureFlowSortStrands - featurePermissionedDEX); } }; diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index 8e78969397..e59cf7deff 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -1054,7 +1054,7 @@ public: // Charlie - queue a transaction, with a higher fee // than default env(noop(charlie), fee(15), queued); - checkMetrics(*this, env, 6, initQueueMax, 4, 3); + checkMetrics(*this, env, 6, initQueueMax, 4, 3, 257); BEAST_EXPECT(env.seq(alice) == aliceSeq); BEAST_EXPECT(env.seq(bob) == bobSeq); @@ -4330,7 +4330,7 @@ public: Account const ellie("ellie"); Account const fiona("fiona"); - constexpr int ledgersInQueue = 20; + constexpr int ledgersInQueue = 30; auto cfg = makeConfig( {{"minimum_txn_in_ledger_standalone", "1"}, {"ledgers_in_queue", std::to_string(ledgersInQueue)}, diff --git a/src/test/jtx/Env_test.cpp b/src/test/jtx/Env_test.cpp index 5e4f534b6a..fbc4bd37a2 100644 --- a/src/test/jtx/Env_test.cpp +++ b/src/test/jtx/Env_test.cpp @@ -798,16 +798,18 @@ public: { // a Env FeatureBitset has *only* those features - Env env{*this, FeatureBitset{featureDynamicMPT | featureFlow}}; + Env env{ + *this, FeatureBitset{featureDynamicMPT | featureTokenEscrow}}; BEAST_EXPECT(env.app().config().features.size() == 2); foreachFeature(supported, [&](uint256 const& f) { - bool const has = (f == featureDynamicMPT || f == featureFlow); + bool const has = + (f == featureDynamicMPT || f == featureTokenEscrow); this->BEAST_EXPECT(has == hasFeature(env, f)); }); } auto const missingSomeFeatures = - testable_amendments() - featureDynamicMPT - featureFlow; + testable_amendments() - featureDynamicMPT - featureTokenEscrow; BEAST_EXPECT(missingSomeFeatures.count() == (supported.count() - 2)); { // a Env supported_features_except is missing *only* those features @@ -815,7 +817,8 @@ public: BEAST_EXPECT( env.app().config().features.size() == (supported.count() - 2)); foreachFeature(supported, [&](uint256 const& f) { - bool hasnot = (f == featureDynamicMPT || f == featureFlow); + bool hasnot = + (f == featureDynamicMPT || f == featureTokenEscrow); this->BEAST_EXPECT(hasnot != hasFeature(env, f)); }); } @@ -828,7 +831,9 @@ public: Env env{ *this, FeatureBitset{ - featureDynamicMPT, featureFlow, *neverSupportedFeat}}; + featureDynamicMPT, + featureTokenEscrow, + *neverSupportedFeat}}; // this app will have just 2 supported amendments and // one additional never supported feature flag @@ -836,7 +841,7 @@ public: BEAST_EXPECT(hasFeature(env, *neverSupportedFeat)); foreachFeature(supported, [&](uint256 const& f) { - bool has = (f == featureDynamicMPT || f == featureFlow); + bool has = (f == featureDynamicMPT || f == featureTokenEscrow); this->BEAST_EXPECT(has == hasFeature(env, f)); }); } @@ -856,7 +861,8 @@ public: (supported.count() - 2 + 1)); BEAST_EXPECT(hasFeature(env, *neverSupportedFeat)); foreachFeature(supported, [&](uint256 const& f) { - bool hasnot = (f == featureDynamicMPT || f == featureFlow); + bool hasnot = + (f == featureDynamicMPT || f == featureTokenEscrow); this->BEAST_EXPECT(hasnot != hasFeature(env, f)); }); } diff --git a/src/test/ledger/View_test.cpp b/src/test/ledger/View_test.cpp index ab978fda59..9c7a5a286e 100644 --- a/src/test/ledger/View_test.cpp +++ b/src/test/ledger/View_test.cpp @@ -1117,7 +1117,7 @@ class GetAmendments_test : public beast::unit_test::suite // There should be at least 3 amendments. Don't do exact comparison // to avoid maintenance as more amendments are added in the future. BEAST_EXPECT(i == 254); - BEAST_EXPECT(majorities.size() >= 3); + BEAST_EXPECT(majorities.size() >= 2); // None of the amendments should be enabled yet. auto enableds = getEnabledAmendments(*env.closed()); @@ -1135,7 +1135,7 @@ class GetAmendments_test : public beast::unit_test::suite break; } BEAST_EXPECT(i == 255); - BEAST_EXPECT(enableds.size() >= 3); + BEAST_EXPECT(enableds.size() >= 2); } void diff --git a/src/test/rpc/Feature_test.cpp b/src/test/rpc/Feature_test.cpp index e01f7566ac..058b4a9572 100644 --- a/src/test/rpc/Feature_test.cpp +++ b/src/test/rpc/Feature_test.cpp @@ -123,7 +123,7 @@ class Feature_test : public beast::unit_test::suite BEAST_EXPECT( featureToName(fixRemoveNFTokenAutoTrustLine) == "fixRemoveNFTokenAutoTrustLine"); - BEAST_EXPECT(featureToName(featureFlow) == "Flow"); + BEAST_EXPECT(featureToName(featureBatch) == "Batch"); BEAST_EXPECT(featureToName(featureDID) == "DID"); BEAST_EXPECT( featureToName(fixIncludeKeyletFields) == "fixIncludeKeyletFields"); @@ -183,16 +183,16 @@ class Feature_test : public beast::unit_test::suite using namespace test::jtx; Env env{*this}; - auto jrr = env.rpc("feature", "Flow")[jss::result]; + auto jrr = env.rpc("feature", "fixAMMOverflowOffer")[jss::result]; BEAST_EXPECTS(jrr[jss::status] == jss::success, "status"); jrr.removeMember(jss::status); BEAST_EXPECT(jrr.size() == 1); BEAST_EXPECT( - jrr.isMember("740352F2412A9909880C23A559FCECEDA3BE2126FED62FC7660D6" - "28A06927F11")); + jrr.isMember("12523DF04B553A0B1AD74F42DDB741DE8DC06A03FC089A0EF197E" + "2A87F1D8107")); auto feature = *(jrr.begin()); - BEAST_EXPECTS(feature[jss::name] == "Flow", "name"); + BEAST_EXPECTS(feature[jss::name] == "fixAMMOverflowOffer", "name"); BEAST_EXPECTS(!feature[jss::enabled].asBool(), "enabled"); BEAST_EXPECTS( feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(), @@ -200,7 +200,7 @@ class Feature_test : public beast::unit_test::suite BEAST_EXPECTS(feature[jss::supported].asBool(), "supported"); // feature names are case-sensitive - expect error here - jrr = env.rpc("feature", "flow")[jss::result]; + jrr = env.rpc("feature", "fMM")[jss::result]; BEAST_EXPECT(jrr[jss::error] == "badFeature"); BEAST_EXPECT(jrr[jss::error_message] == "Feature unknown or invalid."); } @@ -419,9 +419,9 @@ class Feature_test : public beast::unit_test::suite break; } - // There should be at least 3 amendments. Don't do exact comparison + // There should be at least 2 amendments. Don't do exact comparison // to avoid maintenance as more amendments are added in the future. - BEAST_EXPECT(majorities.size() >= 3); + BEAST_EXPECT(majorities.size() >= 2); std::map const& votes = ripple::detail::supportedAmendments(); @@ -476,8 +476,8 @@ class Feature_test : public beast::unit_test::suite testcase("Veto"); using namespace test::jtx; - Env env{*this, FeatureBitset{featureFlow}}; - constexpr char const* featureName = "Flow"; + Env env{*this, FeatureBitset{featurePriceOracle}}; + constexpr char const* featureName = "fixAMMOverflowOffer"; auto jrr = env.rpc("feature", featureName)[jss::result]; if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status")) diff --git a/src/xrpld/app/paths/RippleCalc.cpp b/src/xrpld/app/paths/RippleCalc.cpp index ac30932f11..a6751169d7 100644 --- a/src/xrpld/app/paths/RippleCalc.cpp +++ b/src/xrpld/app/paths/RippleCalc.cpp @@ -43,15 +43,6 @@ RippleCalc::rippleCalculate( PaymentSandbox flowSB(&view); auto j = l.journal("Flow"); - if (!view.rules().enabled(featureFlow)) - { - // The new payment engine was enabled several years ago. New transaction - // should never use the old rules. Assume this is a replay - j.fatal() - << "Old payment rules are required for this transaction. Assuming " - "this is a replay and running with the new rules."; - } - { bool const defaultPaths = !pInputs ? true : pInputs->defaultPathsAllowed; diff --git a/src/xrpld/app/paths/detail/StrandFlow.h b/src/xrpld/app/paths/detail/StrandFlow.h index c9a4619717..fb93f3fdb7 100644 --- a/src/xrpld/app/paths/detail/StrandFlow.h +++ b/src/xrpld/app/paths/detail/StrandFlow.h @@ -433,7 +433,7 @@ public: // add the strands in `next_` to `cur_`, sorted by theoretical quality. // Best quality first. cur_.clear(); - if (v.rules().enabled(featureFlowSortStrands) && !next_.empty()) + if (!next_.empty()) { std::vector> strandQuals; strandQuals.reserve(next_.size()); @@ -719,46 +719,16 @@ flow( continue; } - if (baseView.rules().enabled(featureFlowSortStrands)) - { - XRPL_ASSERT(!best, "ripple::flow : best is unset"); - if (!f.inactive) - activeStrands.push(strand); - best.emplace(f.in, f.out, std::move(*f.sandbox), *strand, q); - activeStrands.pushRemainingCurToNext(strandIndex + 1); - break; - } - - activeStrands.push(strand); - - if (!best || best->quality < q || - (best->quality == q && best->out < f.out)) - { - // If this strand is inactive (because it consumed too many - // offers) and ends up having the best quality, remove it - // from the activeStrands. If it doesn't end up having the - // best quality, keep it active. - - if (f.inactive) - { - // This should be `nextSize`, not `size`. This issue is - // fixed in featureFlowSortStrands. - markInactiveOnUse = activeStrands.size() - 1; - } - else - { - markInactiveOnUse.reset(); - } - - best.emplace(f.in, f.out, std::move(*f.sandbox), *strand, q); - } + XRPL_ASSERT(!best, "ripple::flow : best is unset"); + if (!f.inactive) + activeStrands.push(strand); + best.emplace(f.in, f.out, std::move(*f.sandbox), *strand, q); + activeStrands.pushRemainingCurToNext(strandIndex + 1); + break; } - bool const shouldBreak = [&] { - if (baseView.rules().enabled(featureFlowSortStrands)) - return !best || offersConsidered >= maxOffersToConsider; - return !best; - }(); + bool const shouldBreak = + !best || offersConsidered >= maxOffersToConsider; if (best) { From 856470203a15d03a9960bdd6e8cc4379db17738e Mon Sep 17 00:00:00 2001 From: Bart Date: Tue, 25 Nov 2025 16:03:17 -0500 Subject: [PATCH 021/105] ci: Trigger clio pipeline on PRs targeting release branches (#6080) This change triggers the Clio pipeline on PRs that target any of the `release*` branches (in addition to the `master` branch), as opposed to only the `release` branch. --- .github/workflows/on-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 3f009f63bb..ff3d25812a 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -122,7 +122,7 @@ jobs: needs: - should-run - build-test - if: ${{ needs.should-run.outputs.go == 'true' && contains(fromJSON('["release", "master"]'), github.ref_name) }} + if: ${{ needs.should-run.outputs.go == 'true' && (startsWith(github.base_ref, 'release') || github.base_ref == 'master') }} uses: ./.github/workflows/reusable-notify-clio.yml secrets: clio_notify_token: ${{ secrets.CLIO_NOTIFY_TOKEN }} From a18b30b765c50f318f1a3928f19bd3ecb32b328f Mon Sep 17 00:00:00 2001 From: Bart Date: Wed, 26 Nov 2025 12:28:06 -0500 Subject: [PATCH 022/105] docs: Update instructions how to (re)generate conan.lock file (#6070) This change updates the instructions for how to generate a Conan lockfile that is compatible with Linux, macOS, and Windows. Whenever Conan dependencies change, the Conan lock file needs to be regenerated. However, different OSes have slightly different requirements, and thus require slightly different dependencies. Luckily a single `conan.lock` file can be used, as long as the union of dependencies is included. The current instructions in the `BUILD.md` file are insufficient to regenerate the lock file such that it is compatible with all OSes, which this change addresses. The three profiles contain the bare minimum needed to generate the lockfile; it does not particularly matter whether the build type is Debug or Release, for instance. --- BUILD.md | 34 ++++++--------------------- conan/lockfile/README.md | 42 ++++++++++++++++++++++++++++++++++ conan/lockfile/linux.profile | 8 +++++++ conan/lockfile/macos.profile | 8 +++++++ conan/lockfile/windows.profile | 9 ++++++++ 5 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 conan/lockfile/README.md create mode 100644 conan/lockfile/linux.profile create mode 100644 conan/lockfile/macos.profile create mode 100644 conan/lockfile/windows.profile diff --git a/BUILD.md b/BUILD.md index 39570edbd3..c4b9b93467 100644 --- a/BUILD.md +++ b/BUILD.md @@ -88,6 +88,13 @@ These instructions assume a basic familiarity with Conan and CMake. If you are unfamiliar with Conan, then please read [this crash course](./docs/build/conan.md) or the official [Getting Started][3] walkthrough. +#### Conan lockfile + +To achieve reproducible dependencies, we use a [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html), +which has to be updated every time dependencies change. + +Please see the [instructions on how to regenerate the lockfile](conan/lockfile/README.md). + #### Default profile We recommend that you import the provided `conan/profiles/default` profile: @@ -450,33 +457,6 @@ tools.build:cxxflags=['-DBOOST_ASIO_DISABLE_CONCEPTS'] The location of `rippled` binary in your build directory depends on your CMake generator. Pass `--help` to see the rest of the command line options. -#### Conan lockfile - -To achieve reproducible dependencies, we use [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html). - -The `conan.lock` file in the repository contains a "snapshot" of the current dependencies. -It is implicitly used when running `conan` commands, you don't need to specify it. - -You have to update this file every time you add a new dependency or change a revision or version of an existing dependency. - -> [!NOTE] -> Conan uses local cache by default when creating a lockfile. -> -> To ensure, that lockfile creation works the same way on all developer machines, you should clear the local cache before creating a new lockfile. - -To create a new lockfile, run the following commands in the repository root: - -```bash -conan remove '*' --confirm -rm conan.lock -# This ensure that xrplf remote is the first to be consulted -conan remote add --force --index 0 xrplf https://conan.ripplex.io -conan lock create . -o '&:jemalloc=True' -o '&:rocksdb=True' -``` - -> [!NOTE] -> If some dependencies are exclusive for some OS, you may need to run the last command for them adding `--profile:all `. - ## Coverage report The coverage report is intended for developers using compilers GCC diff --git a/conan/lockfile/README.md b/conan/lockfile/README.md new file mode 100644 index 0000000000..d7ebba1b30 --- /dev/null +++ b/conan/lockfile/README.md @@ -0,0 +1,42 @@ +# Conan lockfile + +To achieve reproducible dependencies, we use a [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html). + +The `conan.lock` file in the repository contains a "snapshot" of the current +dependencies. It is implicitly used when running `conan` commands, so you don't +need to specify it. + +You have to update this file every time you add a new dependency or change a +revision or version of an existing dependency. + +## Updating the lockfile + +To update a lockfile, run the following commands from the repository root: + +```bash +# Ensure that the xrplf remote is the first to be consulted, so any recipes we +# patched are used. We also add it there to not created huge diff when the +# official Conan Center Index is updated. +conan remote add --force --index 0 xrplf https://conan.ripplex.io + +# Remove all local packages to prevent the local cache from influencing the +# lockfile. +conan remove '*' --confirm + +# Create a new lockfile that is compatible with Linux, macOS, and Windows. The +# first create command will create a new lockfile, while the subsequent create +# commands will merge any additional dependencies into the created lockfile. +rm conan.lock +conan lock create . \ + --options '&:jemalloc=True' \ + --options '&:rocksdb=True' \ + --profile:all=conan/lockfile/linux.profile +conan lock create . \ + --options '&:jemalloc=True' \ + --options '&:rocksdb=True' \ + --profile:all=conan/lockfile/macos.profile +conan lock create . \ + --options '&:jemalloc=True' \ + --options '&:rocksdb=True' \ + --profile:all=conan/lockfile/windows.profile +``` diff --git a/conan/lockfile/linux.profile b/conan/lockfile/linux.profile new file mode 100644 index 0000000000..25ad5988c5 --- /dev/null +++ b/conan/lockfile/linux.profile @@ -0,0 +1,8 @@ +[settings] +arch=x86_64 +build_type=Release +compiler=gcc +compiler.cppstd=20 +compiler.libcxx=libstdc++11 +compiler.version=13 +os=Linux diff --git a/conan/lockfile/macos.profile b/conan/lockfile/macos.profile new file mode 100644 index 0000000000..332a0c143d --- /dev/null +++ b/conan/lockfile/macos.profile @@ -0,0 +1,8 @@ +[settings] +arch=armv8 +build_type=Release +compiler=apple-clang +compiler.cppstd=20 +compiler.libcxx=libc++ +compiler.version=17.0 +os=Macos diff --git a/conan/lockfile/windows.profile b/conan/lockfile/windows.profile new file mode 100644 index 0000000000..4bb266a62e --- /dev/null +++ b/conan/lockfile/windows.profile @@ -0,0 +1,9 @@ +[settings] +arch=x86_64 +build_type=Release +compiler=msvc +compiler.cppstd=20 +compiler.runtime=dynamic +compiler.runtime_type=Release +compiler.version=194 +os=Windows From 4e25dc9291ff4a0433e17a6d7a63782960a35f1c Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 26 Nov 2025 17:54:36 +0000 Subject: [PATCH 023/105] chore: Update lockfile (#6083) This change update recipes, to make sure we have the best compatibility with latest compilers and so on. --- conan.lock | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/conan.lock b/conan.lock index 67c4dd8a10..93e91a307a 100644 --- a/conan.lock +++ b/conan.lock @@ -7,31 +7,32 @@ "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318", "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246", "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1762797952.535", - "re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976", - "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614", + "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1764175362.029", + "protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456", "openssl/3.5.4#a1d5835cc6ed5c5b8f3cd5b9b5d24205%1760106486.594", "nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1763150366.909", "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999", "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64", "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03", - "libarchive/3.8.1#5cf685686322e906cb42706ab7e099a8%1756234256.696", + "libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1764175360.142", "jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244", "grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958", "doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1762797941.757", - "date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493", - "c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915", - "bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716", + "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1763584497.32", + "c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1764175359.429", + "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1764175359.429", "boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1756223752.326", - "abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1756234220.907" + "abseil/20230802.1#90ba607d4ee8fb5fb157c3db540671fc%1764175359.429" ], "build_requires": [ "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497", "strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1756234281.733", - "protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614", + "protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456", "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1756234232.901", "msys2/cci.latest#5b73b10144f73cc5bfe0572ed9be39e1%1751977009.857", - "m4/1.4.19#f119296e5c4772b3bb7ab060ae8f417b%1760707875.678", - "cmake/3.31.8#dde3bde00bb843687e55aea5afa0e220%1756234232.89", + "m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846", + "cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1764175359.44", + "cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1764175359.429", "b2/5.3.3#107c15377719889654eb9a162a673975%1756234226.28", "automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56", "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86" @@ -48,14 +49,11 @@ "boost/1.83.0": [ "boost/1.88.0" ], - "sqlite3/[>=3.44 <4]": [ + "sqlite3/3.44.2": [ "sqlite3/3.49.1" ], "lz4/[>=1.9.4 <2]": [ "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504" - ], - "sqlite3/3.44.2": [ - "sqlite3/3.49.1" ] }, "config_requires": [] From 2ed4047840bc89052aad6ab3bc5077c9d84c2a38 Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 26 Nov 2025 18:43:14 +0000 Subject: [PATCH 024/105] chore: Make conan lockfile generation commands into a script (#6085) This change moves the lockfile instructions into a script, and instead of removing packages it sets the Conan home directory to a temporary directory. There are several advantages, such as: * Not affecting the user's Conan home directory, so there is no need to remove packages. * Only the script needs to be run, rather than several commands. --- conan/lockfile/README.md | 32 +------------------------------- conan/lockfile/regenerate.sh | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 31 deletions(-) create mode 100755 conan/lockfile/regenerate.sh diff --git a/conan/lockfile/README.md b/conan/lockfile/README.md index d7ebba1b30..5e70de102d 100644 --- a/conan/lockfile/README.md +++ b/conan/lockfile/README.md @@ -9,34 +9,4 @@ need to specify it. You have to update this file every time you add a new dependency or change a revision or version of an existing dependency. -## Updating the lockfile - -To update a lockfile, run the following commands from the repository root: - -```bash -# Ensure that the xrplf remote is the first to be consulted, so any recipes we -# patched are used. We also add it there to not created huge diff when the -# official Conan Center Index is updated. -conan remote add --force --index 0 xrplf https://conan.ripplex.io - -# Remove all local packages to prevent the local cache from influencing the -# lockfile. -conan remove '*' --confirm - -# Create a new lockfile that is compatible with Linux, macOS, and Windows. The -# first create command will create a new lockfile, while the subsequent create -# commands will merge any additional dependencies into the created lockfile. -rm conan.lock -conan lock create . \ - --options '&:jemalloc=True' \ - --options '&:rocksdb=True' \ - --profile:all=conan/lockfile/linux.profile -conan lock create . \ - --options '&:jemalloc=True' \ - --options '&:rocksdb=True' \ - --profile:all=conan/lockfile/macos.profile -conan lock create . \ - --options '&:jemalloc=True' \ - --options '&:rocksdb=True' \ - --profile:all=conan/lockfile/windows.profile -``` +To update a lockfile, run from the repository root: `./conan/lockfile/regenerate.sh` diff --git a/conan/lockfile/regenerate.sh b/conan/lockfile/regenerate.sh new file mode 100755 index 0000000000..30d38dc2d7 --- /dev/null +++ b/conan/lockfile/regenerate.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -ex + +TEMP_DIR=$(mktemp -d) +trap "rm -rf $TEMP_DIR" EXIT + +echo "Using temporary CONAN_HOME: $TEMP_DIR" + +# We use a temporary Conan home to avoid polluting the user's existing Conan +# configuration and to not use local cache (which leads to non-reproducible lockfiles). +export CONAN_HOME="$TEMP_DIR" + +# Ensure that the xrplf remote is the first to be consulted, so any recipes we +# patched are used. We also add it there to not created huge diff when the +# official Conan Center Index is updated. +conan remote add --force --index 0 xrplf https://conan.ripplex.io + +# Delete any existing lockfile. +rm -f conan.lock + +# Create a new lockfile that is compatible with Linux, macOS, and Windows. The +# first create command will create a new lockfile, while the subsequent create +# commands will merge any additional dependencies into the created lockfile. +conan lock create . \ + --options '&:jemalloc=True' \ + --options '&:rocksdb=True' \ + --profile:all=conan/lockfile/linux.profile +conan lock create . \ + --options '&:jemalloc=True' \ + --options '&:rocksdb=True' \ + --profile:all=conan/lockfile/macos.profile +conan lock create . \ + --options '&:jemalloc=True' \ + --options '&:rocksdb=True' \ + --profile:all=conan/lockfile/windows.profile From f399749ee2612200d166a53fbd863cfcf8f6fa61 Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 26 Nov 2025 19:14:17 +0000 Subject: [PATCH 025/105] chore: Add black pre-commit hook (#6086) This change adds Black as a pre-commit hook to format Python files. --- .github/scripts/strategy-matrix/generate.py | 246 ++++++++++++----- .pre-commit-config.yaml | 5 + conanfile.py | 276 ++++++++++---------- tests/conan/conanfile.py | 19 +- 4 files changed, 332 insertions(+), 214 deletions(-) diff --git a/.github/scripts/strategy-matrix/generate.py b/.github/scripts/strategy-matrix/generate.py index 230c18c2df..79530a1d75 100755 --- a/.github/scripts/strategy-matrix/generate.py +++ b/.github/scripts/strategy-matrix/generate.py @@ -2,11 +2,12 @@ import argparse import itertools import json -from pathlib import Path from dataclasses import dataclass +from pathlib import Path THIS_DIR = Path(__file__).parent.resolve() + @dataclass class Config: architecture: list[dict] @@ -14,7 +15,8 @@ class Config: build_type: list[str] cmake_args: list[str] -''' + +""" Generate a strategy matrix for GitHub Actions CI. On each PR commit we will build a selection of Debian, RHEL, Ubuntu, MacOS, and @@ -27,19 +29,23 @@ We will further set additional CMake arguments as follows: - All release builds will have the `assert` option. - Certain Debian Bookworm configurations will change the reference fee, enable codecov, and enable voidstar in PRs. -''' +""" + + def generate_strategy_matrix(all: bool, config: Config) -> list: configurations = [] - for architecture, os, build_type, cmake_args in itertools.product(config.architecture, config.os, config.build_type, config.cmake_args): + for architecture, os, build_type, cmake_args in itertools.product( + config.architecture, config.os, config.build_type, config.cmake_args + ): # The default CMake target is 'all' for Linux and MacOS and 'install' # for Windows, but it can get overridden for certain configurations. - cmake_target = 'install' if os["distro_name"] == 'windows' else 'all' + cmake_target = "install" if os["distro_name"] == "windows" else "all" # We build and test all configurations by default, except for Windows in # Debug, because it is too slow, as well as when code coverage is # enabled as that mode already runs the tests. build_only = False - if os['distro_name'] == 'windows' and build_type == 'Debug': + if os["distro_name"] == "windows" and build_type == "Debug": build_only = True # Only generate a subset of configurations in PRs. @@ -54,21 +60,46 @@ def generate_strategy_matrix(all: bool, config: Config) -> list: # - Bookworm using Clang 17: Release and no Unity on linux/amd64, # set the reference fee to 1000. # - Bookworm using Clang 20: Debug and Unity on linux/amd64. - if os['distro_name'] == 'debian': + if os["distro_name"] == "debian": skip = True - if os['distro_version'] == 'bookworm': - if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-13' and build_type == 'Release' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/amd64': - cmake_args = f'-DUNIT_TEST_REFERENCE_FEE=500 {cmake_args}' + if os["distro_version"] == "bookworm": + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-13" + and build_type == "Release" + and "-Dunity=ON" in cmake_args + and architecture["platform"] == "linux/amd64" + ): + cmake_args = f"-DUNIT_TEST_REFERENCE_FEE=500 {cmake_args}" skip = False - if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-15' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/amd64': + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15" + and build_type == "Debug" + and "-Dunity=OFF" in cmake_args + and architecture["platform"] == "linux/amd64" + ): skip = False - if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-16' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/arm64': - cmake_args = f'-Dvoidstar=ON {cmake_args}' + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "clang-16" + and build_type == "Debug" + and "-Dunity=OFF" in cmake_args + and architecture["platform"] == "linux/arm64" + ): + cmake_args = f"-Dvoidstar=ON {cmake_args}" skip = False - if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-17' and build_type == 'Release' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/amd64': - cmake_args = f'-DUNIT_TEST_REFERENCE_FEE=1000 {cmake_args}' + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "clang-17" + and build_type == "Release" + and "-Dunity=ON" in cmake_args + and architecture["platform"] == "linux/amd64" + ): + cmake_args = f"-DUNIT_TEST_REFERENCE_FEE=1000 {cmake_args}" skip = False - if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-20' and build_type == 'Debug' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/amd64': + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "clang-20" + and build_type == "Debug" + and "-Dunity=ON" in cmake_args + and architecture["platform"] == "linux/amd64" + ): skip = False if skip: continue @@ -76,13 +107,23 @@ def generate_strategy_matrix(all: bool, config: Config) -> list: # RHEL: # - 9 using GCC 12: Debug and Unity on linux/amd64. # - 10 using Clang: Release and no Unity on linux/amd64. - if os['distro_name'] == 'rhel': + if os["distro_name"] == "rhel": skip = True - if os['distro_version'] == '9': - if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-12' and build_type == 'Debug' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/amd64': + if os["distro_version"] == "9": + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12" + and build_type == "Debug" + and "-Dunity=ON" in cmake_args + and architecture["platform"] == "linux/amd64" + ): skip = False - elif os['distro_version'] == '10': - if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-any' and build_type == 'Release' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/amd64': + elif os["distro_version"] == "10": + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "clang-any" + and build_type == "Release" + and "-Dunity=OFF" in cmake_args + and architecture["platform"] == "linux/amd64" + ): skip = False if skip: continue @@ -92,104 +133,169 @@ def generate_strategy_matrix(all: bool, config: Config) -> list: # - Noble using GCC 14: Release and Unity on linux/amd64. # - Noble using Clang 18: Debug and no Unity on linux/amd64. # - Noble using Clang 19: Release and Unity on linux/arm64. - if os['distro_name'] == 'ubuntu': + if os["distro_name"] == "ubuntu": skip = True - if os['distro_version'] == 'jammy': - if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-12' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/arm64': + if os["distro_version"] == "jammy": + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12" + and build_type == "Debug" + and "-Dunity=OFF" in cmake_args + and architecture["platform"] == "linux/arm64" + ): skip = False - elif os['distro_version'] == 'noble': - if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-14' and build_type == 'Release' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/amd64': + elif os["distro_version"] == "noble": + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-14" + and build_type == "Release" + and "-Dunity=ON" in cmake_args + and architecture["platform"] == "linux/amd64" + ): skip = False - if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-18' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/amd64': + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "clang-18" + and build_type == "Debug" + and "-Dunity=OFF" in cmake_args + and architecture["platform"] == "linux/amd64" + ): skip = False - if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-19' and build_type == 'Release' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/arm64': + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "clang-19" + and build_type == "Release" + and "-Dunity=ON" in cmake_args + and architecture["platform"] == "linux/arm64" + ): skip = False if skip: continue # MacOS: # - Debug and no Unity on macos/arm64. - if os['distro_name'] == 'macos' and not (build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'macos/arm64'): + if os["distro_name"] == "macos" and not ( + build_type == "Debug" + and "-Dunity=OFF" in cmake_args + and architecture["platform"] == "macos/arm64" + ): continue # Windows: # - Release and Unity on windows/amd64. - if os['distro_name'] == 'windows' and not (build_type == 'Release' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'windows/amd64'): + if os["distro_name"] == "windows" and not ( + build_type == "Release" + and "-Dunity=ON" in cmake_args + and architecture["platform"] == "windows/amd64" + ): continue - # Additional CMake arguments. - cmake_args = f'{cmake_args} -Dtests=ON -Dwerr=ON -Dxrpld=ON' - if not f'{os['compiler_name']}-{os['compiler_version']}' in ['gcc-12', 'clang-16']: - cmake_args = f'{cmake_args} -Dwextra=ON' - if build_type == 'Release': - cmake_args = f'{cmake_args} -Dassert=ON' + cmake_args = f"{cmake_args} -Dtests=ON -Dwerr=ON -Dxrpld=ON" + if not f"{os['compiler_name']}-{os['compiler_version']}" in [ + "gcc-12", + "clang-16", + ]: + cmake_args = f"{cmake_args} -Dwextra=ON" + if build_type == "Release": + cmake_args = f"{cmake_args} -Dassert=ON" # We skip all RHEL on arm64 due to a build failure that needs further # investigation. - if os['distro_name'] == 'rhel' and architecture['platform'] == 'linux/arm64': + if os["distro_name"] == "rhel" and architecture["platform"] == "linux/arm64": continue # We skip all clang 20+ on arm64 due to Boost build error. - if f'{os['compiler_name']}-{os['compiler_version']}' in ['clang-20', 'clang-21'] and architecture['platform'] == 'linux/arm64': + if ( + f"{os['compiler_name']}-{os['compiler_version']}" + in ["clang-20", "clang-21"] + and architecture["platform"] == "linux/arm64" + ): continue # Enable code coverage for Debian Bookworm using GCC 15 in Debug and no # Unity on linux/amd64 - if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-15' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/amd64': - cmake_args = f'-Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0 {cmake_args}' + if ( + f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15" + and build_type == "Debug" + and "-Dunity=OFF" in cmake_args + and architecture["platform"] == "linux/amd64" + ): + cmake_args = f"-Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0 {cmake_args}" # Generate a unique name for the configuration, e.g. macos-arm64-debug # or debian-bookworm-gcc-12-amd64-release-unity. - config_name = os['distro_name'] - if (n := os['distro_version']) != '': - config_name += f'-{n}' - if (n := os['compiler_name']) != '': - config_name += f'-{n}' - if (n := os['compiler_version']) != '': - config_name += f'-{n}' - config_name += f'-{architecture['platform'][architecture['platform'].find('/')+1:]}' - config_name += f'-{build_type.lower()}' - if '-Dunity=ON' in cmake_args: - config_name += '-unity' + config_name = os["distro_name"] + if (n := os["distro_version"]) != "": + config_name += f"-{n}" + if (n := os["compiler_name"]) != "": + config_name += f"-{n}" + if (n := os["compiler_version"]) != "": + config_name += f"-{n}" + config_name += ( + f"-{architecture['platform'][architecture['platform'].find('/') + 1 :]}" + ) + config_name += f"-{build_type.lower()}" + if "-Dunity=ON" in cmake_args: + config_name += "-unity" # Add the configuration to the list, with the most unique fields first, # so that they are easier to identify in the GitHub Actions UI, as long # names get truncated. - configurations.append({ - 'config_name': config_name, - 'cmake_args': cmake_args, - 'cmake_target': cmake_target, - 'build_only': build_only, - 'build_type': build_type, - 'os': os, - 'architecture': architecture, - }) + configurations.append( + { + "config_name": config_name, + "cmake_args": cmake_args, + "cmake_target": cmake_target, + "build_only": build_only, + "build_type": build_type, + "os": os, + "architecture": architecture, + } + ) return configurations def read_config(file: Path) -> Config: config = json.loads(file.read_text()) - if config['architecture'] is None or config['os'] is None or config['build_type'] is None or config['cmake_args'] is None: - raise Exception('Invalid configuration file.') + if ( + config["architecture"] is None + or config["os"] is None + or config["build_type"] is None + or config["cmake_args"] is None + ): + raise Exception("Invalid configuration file.") return Config(**config) -if __name__ == '__main__': +if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument('-a', '--all', help='Set to generate all configurations (generally used when merging a PR) or leave unset to generate a subset of configurations (generally used when committing to a PR).', action="store_true") - parser.add_argument('-c', '--config', help='Path to the JSON file containing the strategy matrix configurations.', required=False, type=Path) + parser.add_argument( + "-a", + "--all", + help="Set to generate all configurations (generally used when merging a PR) or leave unset to generate a subset of configurations (generally used when committing to a PR).", + action="store_true", + ) + parser.add_argument( + "-c", + "--config", + help="Path to the JSON file containing the strategy matrix configurations.", + required=False, + type=Path, + ) args = parser.parse_args() matrix = [] - if args.config is None or args.config == '': - matrix += generate_strategy_matrix(args.all, read_config(THIS_DIR / "linux.json")) - matrix += generate_strategy_matrix(args.all, read_config(THIS_DIR / "macos.json")) - matrix += generate_strategy_matrix(args.all, read_config(THIS_DIR / "windows.json")) + if args.config is None or args.config == "": + matrix += generate_strategy_matrix( + args.all, read_config(THIS_DIR / "linux.json") + ) + matrix += generate_strategy_matrix( + args.all, read_config(THIS_DIR / "macos.json") + ) + matrix += generate_strategy_matrix( + args.all, read_config(THIS_DIR / "windows.json") + ) else: matrix += generate_strategy_matrix(args.all, read_config(args.config)) # Generate the strategy matrix. - print(f'matrix={json.dumps({"include": matrix})}') + print(f"matrix={json.dumps({'include': matrix})}") diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a032fee75e..c85e0798f7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,6 +31,11 @@ repos: hooks: - id: prettier + - repo: https://github.com/psf/black-pre-commit-mirror + rev: 25.11.0 + hooks: + - id: black + exclude: | (?x)^( external/.*| diff --git a/conanfile.py b/conanfile.py index 41ec5d35f3..5a0a50a0e7 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,149 +1,155 @@ -from conan import ConanFile, __version__ as conan_version -from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout import re -class Xrpl(ConanFile): - name = 'xrpl' +from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout - license = 'ISC' - author = 'John Freeman ' - url = 'https://github.com/xrplf/rippled' - description = 'The XRP Ledger' - settings = 'os', 'compiler', 'build_type', 'arch' +from conan import ConanFile +from conan import __version__ as conan_version + + +class Xrpl(ConanFile): + name = "xrpl" + + license = "ISC" + author = "John Freeman " + url = "https://github.com/xrplf/rippled" + description = "The XRP Ledger" + settings = "os", "compiler", "build_type", "arch" options = { - 'assertions': [True, False], - 'coverage': [True, False], - 'fPIC': [True, False], - 'jemalloc': [True, False], - 'rocksdb': [True, False], - 'shared': [True, False], - 'static': [True, False], - 'tests': [True, False], - 'unity': [True, False], - 'xrpld': [True, False], + "assertions": [True, False], + "coverage": [True, False], + "fPIC": [True, False], + "jemalloc": [True, False], + "rocksdb": [True, False], + "shared": [True, False], + "static": [True, False], + "tests": [True, False], + "unity": [True, False], + "xrpld": [True, False], } requires = [ - 'grpc/1.50.1', - 'libarchive/3.8.1', - 'nudb/2.0.9', - 'openssl/3.5.4', - 'soci/4.0.3', - 'zlib/1.3.1', + "grpc/1.50.1", + "libarchive/3.8.1", + "nudb/2.0.9", + "openssl/3.5.4", + "soci/4.0.3", + "zlib/1.3.1", ] test_requires = [ - 'doctest/2.4.12', + "doctest/2.4.12", ] tool_requires = [ - 'protobuf/3.21.12', + "protobuf/3.21.12", ] default_options = { - 'assertions': False, - 'coverage': False, - 'fPIC': True, - 'jemalloc': False, - 'rocksdb': True, - 'shared': False, - 'static': True, - 'tests': False, - 'unity': False, - 'xrpld': False, - - 'date/*:header_only': True, - 'grpc/*:shared': False, - 'grpc/*:secure': True, - 'libarchive/*:shared': False, - 'libarchive/*:with_acl': False, - 'libarchive/*:with_bzip2': False, - 'libarchive/*:with_cng': False, - 'libarchive/*:with_expat': False, - 'libarchive/*:with_iconv': False, - 'libarchive/*:with_libxml2': False, - 'libarchive/*:with_lz4': True, - 'libarchive/*:with_lzma': False, - 'libarchive/*:with_lzo': False, - 'libarchive/*:with_nettle': False, - 'libarchive/*:with_openssl': False, - 'libarchive/*:with_pcreposix': False, - 'libarchive/*:with_xattr': False, - 'libarchive/*:with_zlib': False, - 'lz4/*:shared': False, - 'openssl/*:shared': False, - 'protobuf/*:shared': False, - 'protobuf/*:with_zlib': True, - 'rocksdb/*:enable_sse': False, - 'rocksdb/*:lite': False, - 'rocksdb/*:shared': False, - 'rocksdb/*:use_rtti': True, - 'rocksdb/*:with_jemalloc': False, - 'rocksdb/*:with_lz4': True, - 'rocksdb/*:with_snappy': True, - 'snappy/*:shared': False, - 'soci/*:shared': False, - 'soci/*:with_sqlite3': True, - 'soci/*:with_boost': True, - 'xxhash/*:shared': False, + "assertions": False, + "coverage": False, + "fPIC": True, + "jemalloc": False, + "rocksdb": True, + "shared": False, + "static": True, + "tests": False, + "unity": False, + "xrpld": False, + "date/*:header_only": True, + "grpc/*:shared": False, + "grpc/*:secure": True, + "libarchive/*:shared": False, + "libarchive/*:with_acl": False, + "libarchive/*:with_bzip2": False, + "libarchive/*:with_cng": False, + "libarchive/*:with_expat": False, + "libarchive/*:with_iconv": False, + "libarchive/*:with_libxml2": False, + "libarchive/*:with_lz4": True, + "libarchive/*:with_lzma": False, + "libarchive/*:with_lzo": False, + "libarchive/*:with_nettle": False, + "libarchive/*:with_openssl": False, + "libarchive/*:with_pcreposix": False, + "libarchive/*:with_xattr": False, + "libarchive/*:with_zlib": False, + "lz4/*:shared": False, + "openssl/*:shared": False, + "protobuf/*:shared": False, + "protobuf/*:with_zlib": True, + "rocksdb/*:enable_sse": False, + "rocksdb/*:lite": False, + "rocksdb/*:shared": False, + "rocksdb/*:use_rtti": True, + "rocksdb/*:with_jemalloc": False, + "rocksdb/*:with_lz4": True, + "rocksdb/*:with_snappy": True, + "snappy/*:shared": False, + "soci/*:shared": False, + "soci/*:with_sqlite3": True, + "soci/*:with_boost": True, + "xxhash/*:shared": False, } def set_version(self): if self.version is None: - path = f'{self.recipe_folder}/src/libxrpl/protocol/BuildInfo.cpp' - regex = r'versionString\s?=\s?\"(.*)\"' - with open(path, encoding='utf-8') as file: + path = f"{self.recipe_folder}/src/libxrpl/protocol/BuildInfo.cpp" + regex = r"versionString\s?=\s?\"(.*)\"" + with open(path, encoding="utf-8") as file: matches = (re.search(regex, line) for line in file) match = next(m for m in matches if m) self.version = match.group(1) def configure(self): - if self.settings.compiler == 'apple-clang': - self.options['boost'].visibility = 'global' - if self.settings.compiler in ['clang', 'gcc']: - self.options['boost'].without_cobalt = True + if self.settings.compiler == "apple-clang": + self.options["boost"].visibility = "global" + if self.settings.compiler in ["clang", "gcc"]: + self.options["boost"].without_cobalt = True def requirements(self): # Conan 2 requires transitive headers to be specified - transitive_headers_opt = {'transitive_headers': True} if conan_version.split('.')[0] == '2' else {} - self.requires('boost/1.88.0', force=True, **transitive_headers_opt) - self.requires('date/3.0.4', **transitive_headers_opt) - self.requires('lz4/1.10.0', force=True) - self.requires('protobuf/3.21.12', force=True) - self.requires('sqlite3/3.49.1', force=True) + transitive_headers_opt = ( + {"transitive_headers": True} if conan_version.split(".")[0] == "2" else {} + ) + self.requires("boost/1.88.0", force=True, **transitive_headers_opt) + self.requires("date/3.0.4", **transitive_headers_opt) + self.requires("lz4/1.10.0", force=True) + self.requires("protobuf/3.21.12", force=True) + self.requires("sqlite3/3.49.1", force=True) if self.options.jemalloc: - self.requires('jemalloc/5.3.0') + self.requires("jemalloc/5.3.0") if self.options.rocksdb: - self.requires('rocksdb/10.5.1') - self.requires('xxhash/0.8.3', **transitive_headers_opt) + self.requires("rocksdb/10.5.1") + self.requires("xxhash/0.8.3", **transitive_headers_opt) exports_sources = ( - 'CMakeLists.txt', - 'cfg/*', - 'cmake/*', - 'external/*', - 'include/*', - 'src/*', + "CMakeLists.txt", + "cfg/*", + "cmake/*", + "external/*", + "include/*", + "src/*", ) def layout(self): cmake_layout(self) # Fix this setting to follow the default introduced in Conan 1.48 # to align with our build instructions. - self.folders.generators = 'build/generators' + self.folders.generators = "build/generators" + + generators = "CMakeDeps" - generators = 'CMakeDeps' def generate(self): tc = CMakeToolchain(self) - tc.variables['tests'] = self.options.tests - tc.variables['assert'] = self.options.assertions - tc.variables['coverage'] = self.options.coverage - tc.variables['jemalloc'] = self.options.jemalloc - tc.variables['rocksdb'] = self.options.rocksdb - tc.variables['BUILD_SHARED_LIBS'] = self.options.shared - tc.variables['static'] = self.options.static - tc.variables['unity'] = self.options.unity - tc.variables['xrpld'] = self.options.xrpld + tc.variables["tests"] = self.options.tests + tc.variables["assert"] = self.options.assertions + tc.variables["coverage"] = self.options.coverage + tc.variables["jemalloc"] = self.options.jemalloc + tc.variables["rocksdb"] = self.options.rocksdb + tc.variables["BUILD_SHARED_LIBS"] = self.options.shared + tc.variables["static"] = self.options.static + tc.variables["unity"] = self.options.unity + tc.variables["xrpld"] = self.options.xrpld tc.generate() def build(self): @@ -158,40 +164,40 @@ class Xrpl(ConanFile): cmake.install() def package_info(self): - libxrpl = self.cpp_info.components['libxrpl'] + libxrpl = self.cpp_info.components["libxrpl"] libxrpl.libs = [ - 'xrpl', - 'xrpl.libpb', - 'ed25519', - 'secp256k1', + "xrpl", + "xrpl.libpb", + "ed25519", + "secp256k1", ] # TODO: Fix the protobufs to include each other relative to # `include/`, not `include/ripple/proto/`. - libxrpl.includedirs = ['include', 'include/ripple/proto'] + libxrpl.includedirs = ["include", "include/ripple/proto"] libxrpl.requires = [ - 'boost::headers', - 'boost::chrono', - 'boost::container', - 'boost::coroutine', - 'boost::date_time', - 'boost::filesystem', - 'boost::json', - 'boost::program_options', - 'boost::process', - 'boost::regex', - 'boost::system', - 'boost::thread', - 'date::date', - 'grpc::grpc++', - 'libarchive::libarchive', - 'lz4::lz4', - 'nudb::nudb', - 'openssl::crypto', - 'protobuf::libprotobuf', - 'soci::soci', - 'sqlite3::sqlite', - 'xxhash::xxhash', - 'zlib::zlib', + "boost::headers", + "boost::chrono", + "boost::container", + "boost::coroutine", + "boost::date_time", + "boost::filesystem", + "boost::json", + "boost::program_options", + "boost::process", + "boost::regex", + "boost::system", + "boost::thread", + "date::date", + "grpc::grpc++", + "libarchive::libarchive", + "lz4::lz4", + "nudb::nudb", + "openssl::crypto", + "protobuf::libprotobuf", + "soci::soci", + "sqlite3::sqlite", + "xxhash::xxhash", + "zlib::zlib", ] if self.options.rocksdb: - libxrpl.requires.append('rocksdb::librocksdb') + libxrpl.requires.append("rocksdb::librocksdb") diff --git a/tests/conan/conanfile.py b/tests/conan/conanfile.py index 1ea1b333fc..71e43ef25a 100644 --- a/tests/conan/conanfile.py +++ b/tests/conan/conanfile.py @@ -1,28 +1,29 @@ from pathlib import Path -from conan import ConanFile from conan.tools.build import can_run from conan.tools.cmake import CMake, cmake_layout +from conan import ConanFile + + class Example(ConanFile): + name = "example" + license = "ISC" + author = "John Freeman , Michael Legleux Date: Thu, 27 Nov 2025 11:51:32 -0500 Subject: [PATCH 026/105] refactor: Replaces ed25519-donna source by Conan package (#6088) This change substitutes the `ed25519-donna` source code copy by the Conan recipe added in https://github.com/XRPLF/conan-center-index/pull/23. --- BUILD.md | 7 +- CMakeLists.txt | 4 +- conan.lock | 1 + conanfile.py | 2 + external/README.md | 1 - external/ed25519-donna/CMakeLists.txt | 51 - external/ed25519-donna/README.md | 183 - .../ed25519-donna/curve25519-donna-32bit.h | 579 -- .../ed25519-donna/curve25519-donna-64bit.h | 413 -- .../ed25519-donna/curve25519-donna-helpers.h | 67 - .../ed25519-donna/curve25519-donna-sse2.h | 1112 ---- .../ed25519-donna/ed25519-donna-32bit-sse2.h | 513 -- .../ed25519-donna-32bit-tables.h | 61 - .../ed25519-donna/ed25519-donna-64bit-sse2.h | 436 -- .../ed25519-donna-64bit-tables.h | 53 - .../ed25519-donna-64bit-x86-32bit.h | 435 -- .../ed25519-donna/ed25519-donna-64bit-x86.h | 357 -- .../ed25519-donna-basepoint-table.h | 259 - .../ed25519-donna/ed25519-donna-batchverify.h | 275 - .../ed25519-donna/ed25519-donna-impl-base.h | 364 -- .../ed25519-donna/ed25519-donna-impl-sse2.h | 390 -- .../ed25519-donna-portable-identify.h | 103 - .../ed25519-donna/ed25519-donna-portable.h | 136 - external/ed25519-donna/ed25519-donna.h | 115 - external/ed25519-donna/ed25519-hash-custom.h | 11 - external/ed25519-donna/ed25519-hash.h | 219 - .../ed25519-randombytes-custom.h | 8 - external/ed25519-donna/ed25519-randombytes.h | 91 - external/ed25519-donna/ed25519.c | 150 - external/ed25519-donna/ed25519.h | 30 - external/ed25519-donna/fuzz/README.md | 173 - external/ed25519-donna/fuzz/build-nix.php | 134 - .../ed25519-donna/fuzz/curve25519-ref10.c | 1272 ----- .../ed25519-donna/fuzz/curve25519-ref10.h | 8 - .../ed25519-donna/fuzz/ed25519-donna-sse2.c | 3 - external/ed25519-donna/fuzz/ed25519-donna.c | 1 - external/ed25519-donna/fuzz/ed25519-donna.h | 34 - external/ed25519-donna/fuzz/ed25519-ref10.c | 4647 ----------------- external/ed25519-donna/fuzz/ed25519-ref10.h | 9 - external/ed25519-donna/fuzz/fuzz-curve25519.c | 172 - external/ed25519-donna/fuzz/fuzz-ed25519.c | 219 - external/ed25519-donna/modm-donna-32bit.h | 469 -- external/ed25519-donna/modm-donna-64bit.h | 361 -- external/ed25519-donna/regression.h | 1024 ---- external/ed25519-donna/test-internals.c | 176 - external/ed25519-donna/test-ticks.h | 50 - external/ed25519-donna/test.c | 260 - 47 files changed, 10 insertions(+), 15428 deletions(-) delete mode 100644 external/ed25519-donna/CMakeLists.txt delete mode 100644 external/ed25519-donna/README.md delete mode 100644 external/ed25519-donna/curve25519-donna-32bit.h delete mode 100644 external/ed25519-donna/curve25519-donna-64bit.h delete mode 100644 external/ed25519-donna/curve25519-donna-helpers.h delete mode 100644 external/ed25519-donna/curve25519-donna-sse2.h delete mode 100644 external/ed25519-donna/ed25519-donna-32bit-sse2.h delete mode 100644 external/ed25519-donna/ed25519-donna-32bit-tables.h delete mode 100644 external/ed25519-donna/ed25519-donna-64bit-sse2.h delete mode 100644 external/ed25519-donna/ed25519-donna-64bit-tables.h delete mode 100644 external/ed25519-donna/ed25519-donna-64bit-x86-32bit.h delete mode 100644 external/ed25519-donna/ed25519-donna-64bit-x86.h delete mode 100644 external/ed25519-donna/ed25519-donna-basepoint-table.h delete mode 100644 external/ed25519-donna/ed25519-donna-batchverify.h delete mode 100644 external/ed25519-donna/ed25519-donna-impl-base.h delete mode 100644 external/ed25519-donna/ed25519-donna-impl-sse2.h delete mode 100644 external/ed25519-donna/ed25519-donna-portable-identify.h delete mode 100644 external/ed25519-donna/ed25519-donna-portable.h delete mode 100644 external/ed25519-donna/ed25519-donna.h delete mode 100644 external/ed25519-donna/ed25519-hash-custom.h delete mode 100644 external/ed25519-donna/ed25519-hash.h delete mode 100644 external/ed25519-donna/ed25519-randombytes-custom.h delete mode 100644 external/ed25519-donna/ed25519-randombytes.h delete mode 100644 external/ed25519-donna/ed25519.c delete mode 100644 external/ed25519-donna/ed25519.h delete mode 100644 external/ed25519-donna/fuzz/README.md delete mode 100644 external/ed25519-donna/fuzz/build-nix.php delete mode 100644 external/ed25519-donna/fuzz/curve25519-ref10.c delete mode 100644 external/ed25519-donna/fuzz/curve25519-ref10.h delete mode 100644 external/ed25519-donna/fuzz/ed25519-donna-sse2.c delete mode 100644 external/ed25519-donna/fuzz/ed25519-donna.c delete mode 100644 external/ed25519-donna/fuzz/ed25519-donna.h delete mode 100644 external/ed25519-donna/fuzz/ed25519-ref10.c delete mode 100644 external/ed25519-donna/fuzz/ed25519-ref10.h delete mode 100644 external/ed25519-donna/fuzz/fuzz-curve25519.c delete mode 100644 external/ed25519-donna/fuzz/fuzz-ed25519.c delete mode 100644 external/ed25519-donna/modm-donna-32bit.h delete mode 100644 external/ed25519-donna/modm-donna-64bit.h delete mode 100644 external/ed25519-donna/regression.h delete mode 100644 external/ed25519-donna/test-internals.c delete mode 100644 external/ed25519-donna/test-ticks.h delete mode 100644 external/ed25519-donna/test.c diff --git a/BUILD.md b/BUILD.md index c4b9b93467..5d8eb9b064 100644 --- a/BUILD.md +++ b/BUILD.md @@ -145,10 +145,12 @@ cd external git init git remote add origin git@github.com:XRPLF/conan-center-index.git git sparse-checkout init -git sparse-checkout set recipes/snappy +git sparse-checkout set recipes/ed25519 +git sparse-checkout add recipes/snappy git sparse-checkout add recipes/soci git fetch origin master git checkout master +conan export --version 2015.03 recipes/ed25519/all conan export --version 1.1.10 recipes/snappy/all conan export --version 4.0.3 recipes/soci/all rm -rf .git @@ -162,7 +164,8 @@ the new recipe will be automatically pulled from the official Conan Center. > [!NOTE] > You might need to add `--lockfile=""` to your `conan install` command -> to avoid automatic use of the existing `conan.lock` file when you run `conan export` manually on your machine +> to avoid automatic use of the existing `conan.lock` file when you run +> `conan export` manually on your machine ### Conan profile tweaks diff --git a/CMakeLists.txt b/CMakeLists.txt index cedc41eae0..3cfd627afb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,6 @@ set(SECP256K1_BUILD_CTIME_TESTS FALSE) set(SECP256K1_BUILD_EXAMPLES FALSE) add_subdirectory(external/secp256k1) add_library(secp256k1::secp256k1 ALIAS secp256k1) -add_subdirectory(external/ed25519-donna) add_subdirectory(external/antithesis-sdk) find_package(gRPC REQUIRED) find_package(lz4 REQUIRED) @@ -117,8 +116,9 @@ if(rocksdb) target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb) endif() -find_package(nudb REQUIRED) find_package(date REQUIRED) +find_package(ed25519 REQUIRED) +find_package(nudb REQUIRED) find_package(xxHash REQUIRED) target_link_libraries(xrpl_libs INTERFACE diff --git a/conan.lock b/conan.lock index 93e91a307a..2d76558fd2 100644 --- a/conan.lock +++ b/conan.lock @@ -17,6 +17,7 @@ "libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1764175360.142", "jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244", "grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958", + "ed25519/2015.03#17c1f1910e769f368025267a53c23c13%1764259445.491", "doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1762797941.757", "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1763584497.32", "c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1764175359.429", diff --git a/conanfile.py b/conanfile.py index 5a0a50a0e7..ebc5af1446 100644 --- a/conanfile.py +++ b/conanfile.py @@ -28,6 +28,7 @@ class Xrpl(ConanFile): } requires = [ + "ed25519/2015.03", "grpc/1.50.1", "libarchive/3.8.1", "nudb/2.0.9", @@ -188,6 +189,7 @@ class Xrpl(ConanFile): "boost::system", "boost::thread", "date::date", + "ed25519::ed25519", "grpc::grpc++", "libarchive::libarchive", "lz4::lz4", diff --git a/external/README.md b/external/README.md index 7de1fd25a0..9d720faf74 100644 --- a/external/README.md +++ b/external/README.md @@ -5,5 +5,4 @@ The subdirectories in this directory contain external libraries used by rippled. | Folder | Upstream | Description | | :--------------- | :------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | | `antithesis-sdk` | [Project](https://github.com/antithesishq/antithesis-sdk-cpp/) | [Antithesis](https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html) SDK for C++ | -| `ed25519-donna` | [Project](https://github.com/floodyberry/ed25519-donna) | [Ed25519](http://ed25519.cr.yp.to/) digital signatures | | `secp256k1` | [Project](https://github.com/bitcoin-core/secp256k1) | ECDSA digital signatures using the **secp256k1** curve | diff --git a/external/ed25519-donna/CMakeLists.txt b/external/ed25519-donna/CMakeLists.txt deleted file mode 100644 index f060d530aa..0000000000 --- a/external/ed25519-donna/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -cmake_minimum_required(VERSION 3.11) - -project(ed25519 - LANGUAGES C -) - -if(PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/output/$/lib") -endif() - -if(NOT TARGET OpenSSL::SSL) - find_package(OpenSSL) -endif() - -add_library(ed25519 STATIC - ed25519.c -) -add_library(ed25519::ed25519 ALIAS ed25519) -target_link_libraries(ed25519 PUBLIC OpenSSL::SSL) -if(NOT MSVC) - target_compile_options(ed25519 PRIVATE -Wno-implicit-fallthrough) -endif() - -include(GNUInstallDirs) - -#[=========================================================[ - NOTE for macos: - https://github.com/floodyberry/ed25519-donna/issues/29 - our source for ed25519-donna-portable.h has been - patched to workaround this. -#]=========================================================] -target_include_directories(ed25519 PUBLIC - $ - $ -) - -install( - TARGETS ed25519 - EXPORT ${PROJECT_NAME}-exports - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" -) -install( - EXPORT ${PROJECT_NAME}-exports - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" - FILE ${PROJECT_NAME}-targets.cmake - NAMESPACE ${PROJECT_NAME}:: -) -install( - FILES ed25519.h - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" -) diff --git a/external/ed25519-donna/README.md b/external/ed25519-donna/README.md deleted file mode 100644 index e09fc27e31..0000000000 --- a/external/ed25519-donna/README.md +++ /dev/null @@ -1,183 +0,0 @@ -[ed25519](http://ed25519.cr.yp.to/) is an -[Elliptic Curve Digital Signature Algortithm](http://en.wikipedia.org/wiki/Elliptic_Curve_DSA), -developed by [Dan Bernstein](http://cr.yp.to/djb.html), -[Niels Duif](http://www.nielsduif.nl/), -[Tanja Lange](http://hyperelliptic.org/tanja), -[Peter Schwabe](http://www.cryptojedi.org/users/peter/), -and [Bo-Yin Yang](http://www.iis.sinica.edu.tw/pages/byyang/). - -This project provides performant, portable 32-bit & 64-bit implementations. All implementations are -of course constant time in regard to secret data. - -#### Performance - -SSE2 code and benches have not been updated yet. I will do those next. - -Compilers versions are gcc 4.6.3, icc 13.1.1, clang 3.4-1~exp1. - -Batch verification time (in parentheses) is the average time per 1 verification in a batch of 64 signatures. Counts are in thousands of cycles. - -Note that SSE2 performance may be less impressive on AMD & older CPUs with slower SSE ops! - -Visual Studio performance for `ge25519_scalarmult_base_niels` will lag behind a bit until optimized assembler versions of `ge25519_scalarmult_base_choose_niels` -are made. - -##### E5200 @ 2.5ghz, march=core2 - - - - - - - - - - - -
ImplementationSigngcciccclangVerifygcciccclang
ed25519-donna 64bit 100k110k137k327k (144k) 342k (163k) 422k (194k)
amd64-64-24k 102k 355k (158k)
ed25519-donna-sse2 64bit108k111k116k353k (155k) 345k (154k) 360k (161k)
amd64-51-32k 116k 380k (175k)
ed25519-donna-sse2 32bit147k147k156k380k (178k) 381k (173k) 430k (192k)
ed25519-donna 32bit 597k335k380k1693k (720k)1052k (453k)1141k (493k)
- -##### E3-1270 @ 3.4ghz, march=corei7-avx - - - - - - - - - - - -
ImplementationSigngcciccclangVerifygcciccclang
amd64-64-24k 68k 225k (104k)
ed25519-donna 64bit 71k 75k 90k226k (105k) 226k (112k) 277k (125k)
amd64-51-32k 72k 218k (107k)
ed25519-donna-sse2 64bit 79k 82k 92k252k (122k) 259k (124k) 282k (131k)
ed25519-donna-sse2 32bit 94k 95k103k296k (146k) 294k (137k) 306k (147k)
ed25519-donna 32bit 525k299k316k1502k (645k)959k (418k) 954k (416k)
- -#### Compilation - -No configuration is needed **if you are compiling against OpenSSL**. - -##### Hash Options - -If you are not compiling aginst OpenSSL, you will need a hash function. - -To use a simple/**slow** implementation of SHA-512, use `-DED25519_REFHASH` when compiling `ed25519.c`. -This should never be used except to verify the code works when OpenSSL is not available. - -To use a custom hash function, use `-DED25519_CUSTOMHASH` when compiling `ed25519.c` and put your -custom hash implementation in ed25519-hash-custom.h. The hash must have a 512bit digest and implement - - struct ed25519_hash_context; - - void ed25519_hash_init(ed25519_hash_context *ctx); - void ed25519_hash_update(ed25519_hash_context *ctx, const uint8_t *in, size_t inlen); - void ed25519_hash_final(ed25519_hash_context *ctx, uint8_t *hash); - void ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen); - -##### Random Options - -If you are not compiling aginst OpenSSL, you will need a random function for batch verification. - -To use a custom random function, use `-DED25519_CUSTOMRANDOM` when compiling `ed25519.c` and put your -custom hash implementation in ed25519-randombytes-custom.h. The random function must implement: - - void ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len); - -Use `-DED25519_TEST` when compiling `ed25519.c` to use a deterministically seeded, non-thread safe CSPRNG -variant of Bob Jenkins [ISAAC](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29) - -##### Minor options - -Use `-DED25519_INLINE_ASM` to disable the use of custom assembler routines and instead rely on portable C. - -Use `-DED25519_FORCE_32BIT` to force the use of 32 bit routines even when compiling for 64 bit. - -##### 32-bit - - gcc ed25519.c -m32 -O3 -c - -##### 64-bit - - gcc ed25519.c -m64 -O3 -c - -##### SSE2 - - gcc ed25519.c -m32 -O3 -c -DED25519_SSE2 -msse2 - gcc ed25519.c -m64 -O3 -c -DED25519_SSE2 - -clang and icc are also supported - - -#### Usage - -To use the code, link against `ed25519.o -mbits` and: - - #include "ed25519.h" - -Add `-lssl -lcrypto` when using OpenSSL (Some systems don't need -lcrypto? It might be trial and error). - -To generate a private key, simply generate 32 bytes from a secure -cryptographic source: - - ed25519_secret_key sk; - randombytes(sk, sizeof(ed25519_secret_key)); - -To generate a public key: - - ed25519_public_key pk; - ed25519_publickey(sk, pk); - -To sign a message: - - ed25519_signature sig; - ed25519_sign(message, message_len, sk, pk, signature); - -To verify a signature: - - int valid = ed25519_sign_open(message, message_len, pk, signature) == 0; - -To batch verify signatures: - - const unsigned char *mp[num] = {message1, message2..} - size_t ml[num] = {message_len1, message_len2..} - const unsigned char *pkp[num] = {pk1, pk2..} - const unsigned char *sigp[num] = {signature1, signature2..} - int valid[num] - - /* valid[i] will be set to 1 if the individual signature was valid, 0 otherwise */ - int all_valid = ed25519_sign_open_batch(mp, ml, pkp, sigp, num, valid) == 0; - -**Note**: Batch verification uses `ed25519_randombytes_unsafe`, implemented in -`ed25519-randombytes.h`, to generate random scalars for the verification code. -The default implementation now uses OpenSSLs `RAND_bytes`. - -Unlike the [SUPERCOP](http://bench.cr.yp.to/supercop.html) version, signatures are -not appended to messages, and there is no need for padding in front of messages. -Additionally, the secret key does not contain a copy of the public key, so it is -32 bytes instead of 64 bytes, and the public key must be provided to the signing -function. - -##### Curve25519 - -Curve25519 public keys can be generated thanks to -[Adam Langley](http://www.imperialviolet.org/2013/05/10/fastercurve25519.html) -leveraging Ed25519's precomputed basepoint scalar multiplication. - - curved25519_key sk, pk; - randombytes(sk, sizeof(curved25519_key)); - curved25519_scalarmult_basepoint(pk, sk); - -Note the name is curved25519, a combination of curve and ed25519, to prevent -name clashes. Performance is slightly faster than short message ed25519 -signing due to both using the same code for the scalar multiply. - -#### Testing - -Fuzzing against reference implemenations is now available. See [fuzz/README](fuzz/README.md). - -Building `ed25519.c` with `-DED25519_TEST` and linking with `test.c` will run basic sanity tests -and benchmark each function. `test-batch.c` has been incorporated in to `test.c`. - -`test-internals.c` is standalone and built the same way as `ed25519.c`. It tests the math primitives -with extreme values to ensure they function correctly. SSE2 is now supported. - -#### Papers - -[Available on the Ed25519 website](http://ed25519.cr.yp.to/papers.html) \ No newline at end of file diff --git a/external/ed25519-donna/curve25519-donna-32bit.h b/external/ed25519-donna/curve25519-donna-32bit.h deleted file mode 100644 index b0861acf03..0000000000 --- a/external/ed25519-donna/curve25519-donna-32bit.h +++ /dev/null @@ -1,579 +0,0 @@ -/* - Public domain by Andrew M. - See: https://github.com/floodyberry/curve25519-donna - - 32 bit integer curve25519 implementation -*/ - -typedef uint32_t bignum25519[10]; -typedef uint32_t bignum25519align16[12]; - -static const uint32_t reduce_mask_25 = (1 << 25) - 1; -static const uint32_t reduce_mask_26 = (1 << 26) - 1; - - -/* out = in */ -DONNA_INLINE static void -curve25519_copy(bignum25519 out, const bignum25519 in) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[4] = in[4]; - out[5] = in[5]; - out[6] = in[6]; - out[7] = in[7]; - out[8] = in[8]; - out[9] = in[9]; -} - -/* out = a + b */ -DONNA_INLINE static void -curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) { - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; - out[3] = a[3] + b[3]; - out[4] = a[4] + b[4]; - out[5] = a[5] + b[5]; - out[6] = a[6] + b[6]; - out[7] = a[7] + b[7]; - out[8] = a[8] + b[8]; - out[9] = a[9] + b[9]; -} - -DONNA_INLINE static void -curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { - uint32_t c; - out[0] = a[0] + b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; - out[1] = a[1] + b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; - out[2] = a[2] + b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; - out[3] = a[3] + b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; - out[4] = a[4] + b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; - out[5] = a[5] + b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; - out[6] = a[6] + b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; - out[7] = a[7] + b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; - out[8] = a[8] + b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; - out[9] = a[9] + b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; - out[0] += 19 * c; -} - -DONNA_INLINE static void -curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { - uint32_t c; - out[0] = a[0] + b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; - out[1] = a[1] + b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; - out[2] = a[2] + b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; - out[3] = a[3] + b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; - out[4] = a[4] + b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; - out[5] = a[5] + b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; - out[6] = a[6] + b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; - out[7] = a[7] + b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; - out[8] = a[8] + b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; - out[9] = a[9] + b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; - out[0] += 19 * c; -} - -/* multiples of p */ -static const uint32_t twoP0 = 0x07ffffda; -static const uint32_t twoP13579 = 0x03fffffe; -static const uint32_t twoP2468 = 0x07fffffe; -static const uint32_t fourP0 = 0x0fffffb4; -static const uint32_t fourP13579 = 0x07fffffc; -static const uint32_t fourP2468 = 0x0ffffffc; - -/* out = a - b */ -DONNA_INLINE static void -curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) { - uint32_t c; - out[0] = twoP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; - out[1] = twoP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; - out[2] = twoP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; - out[3] = twoP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; - out[4] = twoP2468 + a[4] - b[4] + c; - out[5] = twoP13579 + a[5] - b[5] ; - out[6] = twoP2468 + a[6] - b[6] ; - out[7] = twoP13579 + a[7] - b[7] ; - out[8] = twoP2468 + a[8] - b[8] ; - out[9] = twoP13579 + a[9] - b[9] ; -} - -/* out = a - b, where a is the result of a basic op (add,sub) */ -DONNA_INLINE static void -curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { - uint32_t c; - out[0] = fourP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; - out[1] = fourP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; - out[2] = fourP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; - out[3] = fourP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; - out[4] = fourP2468 + a[4] - b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; - out[5] = fourP13579 + a[5] - b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; - out[6] = fourP2468 + a[6] - b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; - out[7] = fourP13579 + a[7] - b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; - out[8] = fourP2468 + a[8] - b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; - out[9] = fourP13579 + a[9] - b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; - out[0] += 19 * c; -} - -DONNA_INLINE static void -curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { - uint32_t c; - out[0] = fourP0 + a[0] - b[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; - out[1] = fourP13579 + a[1] - b[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; - out[2] = fourP2468 + a[2] - b[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; - out[3] = fourP13579 + a[3] - b[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; - out[4] = fourP2468 + a[4] - b[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; - out[5] = fourP13579 + a[5] - b[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; - out[6] = fourP2468 + a[6] - b[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; - out[7] = fourP13579 + a[7] - b[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; - out[8] = fourP2468 + a[8] - b[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; - out[9] = fourP13579 + a[9] - b[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; - out[0] += 19 * c; -} - -/* out = -a */ -DONNA_INLINE static void -curve25519_neg(bignum25519 out, const bignum25519 a) { - uint32_t c; - out[0] = twoP0 - a[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26; - out[1] = twoP13579 - a[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25; - out[2] = twoP2468 - a[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26; - out[3] = twoP13579 - a[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25; - out[4] = twoP2468 - a[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26; - out[5] = twoP13579 - a[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25; - out[6] = twoP2468 - a[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26; - out[7] = twoP13579 - a[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25; - out[8] = twoP2468 - a[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26; - out[9] = twoP13579 - a[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25; - out[0] += 19 * c; -} - -/* out = a * b */ -#define curve25519_mul_noinline curve25519_mul -static void -curve25519_mul(bignum25519 out, const bignum25519 a, const bignum25519 b) { - uint32_t r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; - uint32_t s0,s1,s2,s3,s4,s5,s6,s7,s8,s9; - uint64_t m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; - uint32_t p; - - r0 = b[0]; - r1 = b[1]; - r2 = b[2]; - r3 = b[3]; - r4 = b[4]; - r5 = b[5]; - r6 = b[6]; - r7 = b[7]; - r8 = b[8]; - r9 = b[9]; - - s0 = a[0]; - s1 = a[1]; - s2 = a[2]; - s3 = a[3]; - s4 = a[4]; - s5 = a[5]; - s6 = a[6]; - s7 = a[7]; - s8 = a[8]; - s9 = a[9]; - - m1 = mul32x32_64(r0, s1) + mul32x32_64(r1, s0); - m3 = mul32x32_64(r0, s3) + mul32x32_64(r1, s2) + mul32x32_64(r2, s1) + mul32x32_64(r3, s0); - m5 = mul32x32_64(r0, s5) + mul32x32_64(r1, s4) + mul32x32_64(r2, s3) + mul32x32_64(r3, s2) + mul32x32_64(r4, s1) + mul32x32_64(r5, s0); - m7 = mul32x32_64(r0, s7) + mul32x32_64(r1, s6) + mul32x32_64(r2, s5) + mul32x32_64(r3, s4) + mul32x32_64(r4, s3) + mul32x32_64(r5, s2) + mul32x32_64(r6, s1) + mul32x32_64(r7, s0); - m9 = mul32x32_64(r0, s9) + mul32x32_64(r1, s8) + mul32x32_64(r2, s7) + mul32x32_64(r3, s6) + mul32x32_64(r4, s5) + mul32x32_64(r5, s4) + mul32x32_64(r6, s3) + mul32x32_64(r7, s2) + mul32x32_64(r8, s1) + mul32x32_64(r9, s0); - - r1 *= 2; - r3 *= 2; - r5 *= 2; - r7 *= 2; - - m0 = mul32x32_64(r0, s0); - m2 = mul32x32_64(r0, s2) + mul32x32_64(r1, s1) + mul32x32_64(r2, s0); - m4 = mul32x32_64(r0, s4) + mul32x32_64(r1, s3) + mul32x32_64(r2, s2) + mul32x32_64(r3, s1) + mul32x32_64(r4, s0); - m6 = mul32x32_64(r0, s6) + mul32x32_64(r1, s5) + mul32x32_64(r2, s4) + mul32x32_64(r3, s3) + mul32x32_64(r4, s2) + mul32x32_64(r5, s1) + mul32x32_64(r6, s0); - m8 = mul32x32_64(r0, s8) + mul32x32_64(r1, s7) + mul32x32_64(r2, s6) + mul32x32_64(r3, s5) + mul32x32_64(r4, s4) + mul32x32_64(r5, s3) + mul32x32_64(r6, s2) + mul32x32_64(r7, s1) + mul32x32_64(r8, s0); - - r1 *= 19; - r2 *= 19; - r3 = (r3 / 2) * 19; - r4 *= 19; - r5 = (r5 / 2) * 19; - r6 *= 19; - r7 = (r7 / 2) * 19; - r8 *= 19; - r9 *= 19; - - m1 += (mul32x32_64(r9, s2) + mul32x32_64(r8, s3) + mul32x32_64(r7, s4) + mul32x32_64(r6, s5) + mul32x32_64(r5, s6) + mul32x32_64(r4, s7) + mul32x32_64(r3, s8) + mul32x32_64(r2, s9)); - m3 += (mul32x32_64(r9, s4) + mul32x32_64(r8, s5) + mul32x32_64(r7, s6) + mul32x32_64(r6, s7) + mul32x32_64(r5, s8) + mul32x32_64(r4, s9)); - m5 += (mul32x32_64(r9, s6) + mul32x32_64(r8, s7) + mul32x32_64(r7, s8) + mul32x32_64(r6, s9)); - m7 += (mul32x32_64(r9, s8) + mul32x32_64(r8, s9)); - - r3 *= 2; - r5 *= 2; - r7 *= 2; - r9 *= 2; - - m0 += (mul32x32_64(r9, s1) + mul32x32_64(r8, s2) + mul32x32_64(r7, s3) + mul32x32_64(r6, s4) + mul32x32_64(r5, s5) + mul32x32_64(r4, s6) + mul32x32_64(r3, s7) + mul32x32_64(r2, s8) + mul32x32_64(r1, s9)); - m2 += (mul32x32_64(r9, s3) + mul32x32_64(r8, s4) + mul32x32_64(r7, s5) + mul32x32_64(r6, s6) + mul32x32_64(r5, s7) + mul32x32_64(r4, s8) + mul32x32_64(r3, s9)); - m4 += (mul32x32_64(r9, s5) + mul32x32_64(r8, s6) + mul32x32_64(r7, s7) + mul32x32_64(r6, s8) + mul32x32_64(r5, s9)); - m6 += (mul32x32_64(r9, s7) + mul32x32_64(r8, s8) + mul32x32_64(r7, s9)); - m8 += (mul32x32_64(r9, s9)); - - r0 = (uint32_t)m0 & reduce_mask_26; c = (m0 >> 26); - m1 += c; r1 = (uint32_t)m1 & reduce_mask_25; c = (m1 >> 25); - m2 += c; r2 = (uint32_t)m2 & reduce_mask_26; c = (m2 >> 26); - m3 += c; r3 = (uint32_t)m3 & reduce_mask_25; c = (m3 >> 25); - m4 += c; r4 = (uint32_t)m4 & reduce_mask_26; c = (m4 >> 26); - m5 += c; r5 = (uint32_t)m5 & reduce_mask_25; c = (m5 >> 25); - m6 += c; r6 = (uint32_t)m6 & reduce_mask_26; c = (m6 >> 26); - m7 += c; r7 = (uint32_t)m7 & reduce_mask_25; c = (m7 >> 25); - m8 += c; r8 = (uint32_t)m8 & reduce_mask_26; c = (m8 >> 26); - m9 += c; r9 = (uint32_t)m9 & reduce_mask_25; p = (uint32_t)(m9 >> 25); - m0 = r0 + mul32x32_64(p,19); r0 = (uint32_t)m0 & reduce_mask_26; p = (uint32_t)(m0 >> 26); - r1 += p; - - out[0] = r0; - out[1] = r1; - out[2] = r2; - out[3] = r3; - out[4] = r4; - out[5] = r5; - out[6] = r6; - out[7] = r7; - out[8] = r8; - out[9] = r9; -} - -/* out = in*in */ -static void -curve25519_square(bignum25519 out, const bignum25519 in) { - uint32_t r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; - uint32_t d6,d7,d8,d9; - uint64_t m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; - uint32_t p; - - r0 = in[0]; - r1 = in[1]; - r2 = in[2]; - r3 = in[3]; - r4 = in[4]; - r5 = in[5]; - r6 = in[6]; - r7 = in[7]; - r8 = in[8]; - r9 = in[9]; - - m0 = mul32x32_64(r0, r0); - r0 *= 2; - m1 = mul32x32_64(r0, r1); - m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2); - r1 *= 2; - m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2 ); - m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2); - r2 *= 2; - m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4 ) + mul32x32_64(r2, r3); - m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) + mul32x32_64(r3, r3 * 2); - r3 *= 2; - m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6 ) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4 ); - m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) + mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4 ); - m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8 ) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6 ) + mul32x32_64(r4, r5 * 2); - - d6 = r6 * 19; - d7 = r7 * 2 * 19; - d8 = r8 * 19; - d9 = r9 * 2 * 19; - - m0 += (mul32x32_64(d9, r1 ) + mul32x32_64(d8, r2 ) + mul32x32_64(d7, r3 ) + mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19)); - m1 += (mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3 ) + mul32x32_64(d7, r4 ) + mul32x32_64(d6, r5 * 2)); - m2 += (mul32x32_64(d9, r3 ) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) + mul32x32_64(d6, r6 )); - m3 += (mul32x32_64(d9, r4 ) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6 )); - m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7 )); - m5 += (mul32x32_64(d9, r6 ) + mul32x32_64(d8, r7 * 2)); - m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8 )); - m7 += (mul32x32_64(d9, r8 )); - m8 += (mul32x32_64(d9, r9 )); - - r0 = (uint32_t)m0 & reduce_mask_26; c = (m0 >> 26); - m1 += c; r1 = (uint32_t)m1 & reduce_mask_25; c = (m1 >> 25); - m2 += c; r2 = (uint32_t)m2 & reduce_mask_26; c = (m2 >> 26); - m3 += c; r3 = (uint32_t)m3 & reduce_mask_25; c = (m3 >> 25); - m4 += c; r4 = (uint32_t)m4 & reduce_mask_26; c = (m4 >> 26); - m5 += c; r5 = (uint32_t)m5 & reduce_mask_25; c = (m5 >> 25); - m6 += c; r6 = (uint32_t)m6 & reduce_mask_26; c = (m6 >> 26); - m7 += c; r7 = (uint32_t)m7 & reduce_mask_25; c = (m7 >> 25); - m8 += c; r8 = (uint32_t)m8 & reduce_mask_26; c = (m8 >> 26); - m9 += c; r9 = (uint32_t)m9 & reduce_mask_25; p = (uint32_t)(m9 >> 25); - m0 = r0 + mul32x32_64(p,19); r0 = (uint32_t)m0 & reduce_mask_26; p = (uint32_t)(m0 >> 26); - r1 += p; - - out[0] = r0; - out[1] = r1; - out[2] = r2; - out[3] = r3; - out[4] = r4; - out[5] = r5; - out[6] = r6; - out[7] = r7; - out[8] = r8; - out[9] = r9; -} - - -/* out = in ^ (2 * count) */ -static void -curve25519_square_times(bignum25519 out, const bignum25519 in, int count) { - uint32_t r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; - uint32_t d6,d7,d8,d9; - uint64_t m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,c; - uint32_t p; - - r0 = in[0]; - r1 = in[1]; - r2 = in[2]; - r3 = in[3]; - r4 = in[4]; - r5 = in[5]; - r6 = in[6]; - r7 = in[7]; - r8 = in[8]; - r9 = in[9]; - - do { - m0 = mul32x32_64(r0, r0); - r0 *= 2; - m1 = mul32x32_64(r0, r1); - m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2); - r1 *= 2; - m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2 ); - m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2); - r2 *= 2; - m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4 ) + mul32x32_64(r2, r3); - m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) + mul32x32_64(r3, r3 * 2); - r3 *= 2; - m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6 ) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4 ); - m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) + mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4 ); - m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8 ) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6 ) + mul32x32_64(r4, r5 * 2); - - d6 = r6 * 19; - d7 = r7 * 2 * 19; - d8 = r8 * 19; - d9 = r9 * 2 * 19; - - m0 += (mul32x32_64(d9, r1 ) + mul32x32_64(d8, r2 ) + mul32x32_64(d7, r3 ) + mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19)); - m1 += (mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3 ) + mul32x32_64(d7, r4 ) + mul32x32_64(d6, r5 * 2)); - m2 += (mul32x32_64(d9, r3 ) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) + mul32x32_64(d6, r6 )); - m3 += (mul32x32_64(d9, r4 ) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6 )); - m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7 )); - m5 += (mul32x32_64(d9, r6 ) + mul32x32_64(d8, r7 * 2)); - m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8 )); - m7 += (mul32x32_64(d9, r8 )); - m8 += (mul32x32_64(d9, r9 )); - - r0 = (uint32_t)m0 & reduce_mask_26; c = (m0 >> 26); - m1 += c; r1 = (uint32_t)m1 & reduce_mask_25; c = (m1 >> 25); - m2 += c; r2 = (uint32_t)m2 & reduce_mask_26; c = (m2 >> 26); - m3 += c; r3 = (uint32_t)m3 & reduce_mask_25; c = (m3 >> 25); - m4 += c; r4 = (uint32_t)m4 & reduce_mask_26; c = (m4 >> 26); - m5 += c; r5 = (uint32_t)m5 & reduce_mask_25; c = (m5 >> 25); - m6 += c; r6 = (uint32_t)m6 & reduce_mask_26; c = (m6 >> 26); - m7 += c; r7 = (uint32_t)m7 & reduce_mask_25; c = (m7 >> 25); - m8 += c; r8 = (uint32_t)m8 & reduce_mask_26; c = (m8 >> 26); - m9 += c; r9 = (uint32_t)m9 & reduce_mask_25; p = (uint32_t)(m9 >> 25); - m0 = r0 + mul32x32_64(p,19); r0 = (uint32_t)m0 & reduce_mask_26; p = (uint32_t)(m0 >> 26); - r1 += p; - } while (--count); - - out[0] = r0; - out[1] = r1; - out[2] = r2; - out[3] = r3; - out[4] = r4; - out[5] = r5; - out[6] = r6; - out[7] = r7; - out[8] = r8; - out[9] = r9; -} - -/* Take a little-endian, 32-byte number and expand it into polynomial form */ -static void -curve25519_expand(bignum25519 out, const unsigned char in[32]) { - static const union { uint8_t b[2]; uint16_t s; } endian_check = {{1,0}}; - uint32_t x0,x1,x2,x3,x4,x5,x6,x7; - - if (endian_check.s == 1) { - x0 = *(uint32_t *)(in + 0); - x1 = *(uint32_t *)(in + 4); - x2 = *(uint32_t *)(in + 8); - x3 = *(uint32_t *)(in + 12); - x4 = *(uint32_t *)(in + 16); - x5 = *(uint32_t *)(in + 20); - x6 = *(uint32_t *)(in + 24); - x7 = *(uint32_t *)(in + 28); - } else { - #define F(s) \ - ((((uint32_t)in[s + 0]) ) | \ - (((uint32_t)in[s + 1]) << 8) | \ - (((uint32_t)in[s + 2]) << 16) | \ - (((uint32_t)in[s + 3]) << 24)) - x0 = F(0); - x1 = F(4); - x2 = F(8); - x3 = F(12); - x4 = F(16); - x5 = F(20); - x6 = F(24); - x7 = F(28); - #undef F - } - - out[0] = ( x0 ) & 0x3ffffff; - out[1] = ((((uint64_t)x1 << 32) | x0) >> 26) & 0x1ffffff; - out[2] = ((((uint64_t)x2 << 32) | x1) >> 19) & 0x3ffffff; - out[3] = ((((uint64_t)x3 << 32) | x2) >> 13) & 0x1ffffff; - out[4] = (( x3) >> 6) & 0x3ffffff; - out[5] = ( x4 ) & 0x1ffffff; - out[6] = ((((uint64_t)x5 << 32) | x4) >> 25) & 0x3ffffff; - out[7] = ((((uint64_t)x6 << 32) | x5) >> 19) & 0x1ffffff; - out[8] = ((((uint64_t)x7 << 32) | x6) >> 12) & 0x3ffffff; - out[9] = (( x7) >> 6) & 0x1ffffff; -} - -/* Take a fully reduced polynomial form number and contract it into a - * little-endian, 32-byte array - */ -static void -curve25519_contract(unsigned char out[32], const bignum25519 in) { - bignum25519 f; - curve25519_copy(f, in); - - #define carry_pass() \ - f[1] += f[0] >> 26; f[0] &= reduce_mask_26; \ - f[2] += f[1] >> 25; f[1] &= reduce_mask_25; \ - f[3] += f[2] >> 26; f[2] &= reduce_mask_26; \ - f[4] += f[3] >> 25; f[3] &= reduce_mask_25; \ - f[5] += f[4] >> 26; f[4] &= reduce_mask_26; \ - f[6] += f[5] >> 25; f[5] &= reduce_mask_25; \ - f[7] += f[6] >> 26; f[6] &= reduce_mask_26; \ - f[8] += f[7] >> 25; f[7] &= reduce_mask_25; \ - f[9] += f[8] >> 26; f[8] &= reduce_mask_26; - - #define carry_pass_full() \ - carry_pass() \ - f[0] += 19 * (f[9] >> 25); f[9] &= reduce_mask_25; - - #define carry_pass_final() \ - carry_pass() \ - f[9] &= reduce_mask_25; - - carry_pass_full() - carry_pass_full() - - /* now t is between 0 and 2^255-1, properly carried. */ - /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ - f[0] += 19; - carry_pass_full() - - /* now between 19 and 2^255-1 in both cases, and offset by 19. */ - f[0] += (reduce_mask_26 + 1) - 19; - f[1] += (reduce_mask_25 + 1) - 1; - f[2] += (reduce_mask_26 + 1) - 1; - f[3] += (reduce_mask_25 + 1) - 1; - f[4] += (reduce_mask_26 + 1) - 1; - f[5] += (reduce_mask_25 + 1) - 1; - f[6] += (reduce_mask_26 + 1) - 1; - f[7] += (reduce_mask_25 + 1) - 1; - f[8] += (reduce_mask_26 + 1) - 1; - f[9] += (reduce_mask_25 + 1) - 1; - - /* now between 2^255 and 2^256-20, and offset by 2^255. */ - carry_pass_final() - - #undef carry_pass - #undef carry_full - #undef carry_final - - f[1] <<= 2; - f[2] <<= 3; - f[3] <<= 5; - f[4] <<= 6; - f[6] <<= 1; - f[7] <<= 3; - f[8] <<= 4; - f[9] <<= 6; - - #define F(i, s) \ - out[s+0] |= (unsigned char )(f[i] & 0xff); \ - out[s+1] = (unsigned char )((f[i] >> 8) & 0xff); \ - out[s+2] = (unsigned char )((f[i] >> 16) & 0xff); \ - out[s+3] = (unsigned char )((f[i] >> 24) & 0xff); - - out[0] = 0; - out[16] = 0; - F(0,0); - F(1,3); - F(2,6); - F(3,9); - F(4,12); - F(5,16); - F(6,19); - F(7,22); - F(8,25); - F(9,28); - #undef F -} - - -/* out = (flag) ? in : out */ -DONNA_INLINE static void -curve25519_move_conditional_bytes(uint8_t out[96], const uint8_t in[96], uint32_t flag) { - const uint32_t nb = flag - 1, b = ~nb; - const uint32_t *inl = (const uint32_t *)in; - uint32_t *outl = (uint32_t *)out; - outl[0] = (outl[0] & nb) | (inl[0] & b); - outl[1] = (outl[1] & nb) | (inl[1] & b); - outl[2] = (outl[2] & nb) | (inl[2] & b); - outl[3] = (outl[3] & nb) | (inl[3] & b); - outl[4] = (outl[4] & nb) | (inl[4] & b); - outl[5] = (outl[5] & nb) | (inl[5] & b); - outl[6] = (outl[6] & nb) | (inl[6] & b); - outl[7] = (outl[7] & nb) | (inl[7] & b); - outl[8] = (outl[8] & nb) | (inl[8] & b); - outl[9] = (outl[9] & nb) | (inl[9] & b); - outl[10] = (outl[10] & nb) | (inl[10] & b); - outl[11] = (outl[11] & nb) | (inl[11] & b); - outl[12] = (outl[12] & nb) | (inl[12] & b); - outl[13] = (outl[13] & nb) | (inl[13] & b); - outl[14] = (outl[14] & nb) | (inl[14] & b); - outl[15] = (outl[15] & nb) | (inl[15] & b); - outl[16] = (outl[16] & nb) | (inl[16] & b); - outl[17] = (outl[17] & nb) | (inl[17] & b); - outl[18] = (outl[18] & nb) | (inl[18] & b); - outl[19] = (outl[19] & nb) | (inl[19] & b); - outl[20] = (outl[20] & nb) | (inl[20] & b); - outl[21] = (outl[21] & nb) | (inl[21] & b); - outl[22] = (outl[22] & nb) | (inl[22] & b); - outl[23] = (outl[23] & nb) | (inl[23] & b); - -} - -/* if (iswap) swap(a, b) */ -DONNA_INLINE static void -curve25519_swap_conditional(bignum25519 a, bignum25519 b, uint32_t iswap) { - const uint32_t swap = (uint32_t)(-(int32_t)iswap); - uint32_t x0,x1,x2,x3,x4,x5,x6,x7,x8,x9; - - x0 = swap & (a[0] ^ b[0]); a[0] ^= x0; b[0] ^= x0; - x1 = swap & (a[1] ^ b[1]); a[1] ^= x1; b[1] ^= x1; - x2 = swap & (a[2] ^ b[2]); a[2] ^= x2; b[2] ^= x2; - x3 = swap & (a[3] ^ b[3]); a[3] ^= x3; b[3] ^= x3; - x4 = swap & (a[4] ^ b[4]); a[4] ^= x4; b[4] ^= x4; - x5 = swap & (a[5] ^ b[5]); a[5] ^= x5; b[5] ^= x5; - x6 = swap & (a[6] ^ b[6]); a[6] ^= x6; b[6] ^= x6; - x7 = swap & (a[7] ^ b[7]); a[7] ^= x7; b[7] ^= x7; - x8 = swap & (a[8] ^ b[8]); a[8] ^= x8; b[8] ^= x8; - x9 = swap & (a[9] ^ b[9]); a[9] ^= x9; b[9] ^= x9; -} diff --git a/external/ed25519-donna/curve25519-donna-64bit.h b/external/ed25519-donna/curve25519-donna-64bit.h deleted file mode 100644 index 2941d1bcdc..0000000000 --- a/external/ed25519-donna/curve25519-donna-64bit.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - Public domain by Adam Langley & - Andrew M. - See: https://github.com/floodyberry/curve25519-donna - - 64bit integer curve25519 implementation -*/ - -typedef uint64_t bignum25519[5]; - -static const uint64_t reduce_mask_40 = ((uint64_t)1 << 40) - 1; -static const uint64_t reduce_mask_51 = ((uint64_t)1 << 51) - 1; -static const uint64_t reduce_mask_56 = ((uint64_t)1 << 56) - 1; - -/* out = in */ -DONNA_INLINE static void -curve25519_copy(bignum25519 out, const bignum25519 in) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[4] = in[4]; -} - -/* out = a + b */ -DONNA_INLINE static void -curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) { - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; - out[3] = a[3] + b[3]; - out[4] = a[4] + b[4]; -} - -/* out = a + b, where a and/or b are the result of a basic op (add,sub) */ -DONNA_INLINE static void -curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; - out[3] = a[3] + b[3]; - out[4] = a[4] + b[4]; -} - -DONNA_INLINE static void -curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { - uint64_t c; - out[0] = a[0] + b[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51; - out[1] = a[1] + b[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51; - out[2] = a[2] + b[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51; - out[3] = a[3] + b[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51; - out[4] = a[4] + b[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51; - out[0] += c * 19; -} - -/* multiples of p */ -static const uint64_t twoP0 = 0x0fffffffffffda; -static const uint64_t twoP1234 = 0x0ffffffffffffe; -static const uint64_t fourP0 = 0x1fffffffffffb4; -static const uint64_t fourP1234 = 0x1ffffffffffffc; - -/* out = a - b */ -DONNA_INLINE static void -curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) { - out[0] = a[0] + twoP0 - b[0]; - out[1] = a[1] + twoP1234 - b[1]; - out[2] = a[2] + twoP1234 - b[2]; - out[3] = a[3] + twoP1234 - b[3]; - out[4] = a[4] + twoP1234 - b[4]; -} - -/* out = a - b, where a and/or b are the result of a basic op (add,sub) */ -DONNA_INLINE static void -curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { - out[0] = a[0] + fourP0 - b[0]; - out[1] = a[1] + fourP1234 - b[1]; - out[2] = a[2] + fourP1234 - b[2]; - out[3] = a[3] + fourP1234 - b[3]; - out[4] = a[4] + fourP1234 - b[4]; -} - -DONNA_INLINE static void -curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { - uint64_t c; - out[0] = a[0] + fourP0 - b[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51; - out[1] = a[1] + fourP1234 - b[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51; - out[2] = a[2] + fourP1234 - b[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51; - out[3] = a[3] + fourP1234 - b[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51; - out[4] = a[4] + fourP1234 - b[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51; - out[0] += c * 19; -} - -/* out = -a */ -DONNA_INLINE static void -curve25519_neg(bignum25519 out, const bignum25519 a) { - uint64_t c; - out[0] = twoP0 - a[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51; - out[1] = twoP1234 - a[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51; - out[2] = twoP1234 - a[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51; - out[3] = twoP1234 - a[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51; - out[4] = twoP1234 - a[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51; - out[0] += c * 19; -} - -/* out = a * b */ -DONNA_INLINE static void -curve25519_mul(bignum25519 out, const bignum25519 in2, const bignum25519 in) { -#if !defined(HAVE_NATIVE_UINT128) - uint128_t mul; -#endif - uint128_t t[5]; - uint64_t r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; - - r0 = in[0]; - r1 = in[1]; - r2 = in[2]; - r3 = in[3]; - r4 = in[4]; - - s0 = in2[0]; - s1 = in2[1]; - s2 = in2[2]; - s3 = in2[3]; - s4 = in2[4]; - -#if defined(HAVE_NATIVE_UINT128) - t[0] = ((uint128_t) r0) * s0; - t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0; - t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1; - t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1; - t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2; -#else - mul64x64_128(t[0], r0, s0) - mul64x64_128(t[1], r0, s1) mul64x64_128(mul, r1, s0) add128(t[1], mul) - mul64x64_128(t[2], r0, s2) mul64x64_128(mul, r2, s0) add128(t[2], mul) mul64x64_128(mul, r1, s1) add128(t[2], mul) - mul64x64_128(t[3], r0, s3) mul64x64_128(mul, r3, s0) add128(t[3], mul) mul64x64_128(mul, r1, s2) add128(t[3], mul) mul64x64_128(mul, r2, s1) add128(t[3], mul) - mul64x64_128(t[4], r0, s4) mul64x64_128(mul, r4, s0) add128(t[4], mul) mul64x64_128(mul, r3, s1) add128(t[4], mul) mul64x64_128(mul, r1, s3) add128(t[4], mul) mul64x64_128(mul, r2, s2) add128(t[4], mul) -#endif - - r1 *= 19; - r2 *= 19; - r3 *= 19; - r4 *= 19; - -#if defined(HAVE_NATIVE_UINT128) - t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2; - t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3; - t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4; - t[3] += ((uint128_t) r4) * s4; -#else - mul64x64_128(mul, r4, s1) add128(t[0], mul) mul64x64_128(mul, r1, s4) add128(t[0], mul) mul64x64_128(mul, r2, s3) add128(t[0], mul) mul64x64_128(mul, r3, s2) add128(t[0], mul) - mul64x64_128(mul, r4, s2) add128(t[1], mul) mul64x64_128(mul, r2, s4) add128(t[1], mul) mul64x64_128(mul, r3, s3) add128(t[1], mul) - mul64x64_128(mul, r4, s3) add128(t[2], mul) mul64x64_128(mul, r3, s4) add128(t[2], mul) - mul64x64_128(mul, r4, s4) add128(t[3], mul) -#endif - - - r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51); - add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51); - add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51); - add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51); - add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51); - r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51; - r1 += c; - - out[0] = r0; - out[1] = r1; - out[2] = r2; - out[3] = r3; - out[4] = r4; -} - -DONNA_NOINLINE static void -curve25519_mul_noinline(bignum25519 out, const bignum25519 in2, const bignum25519 in) { - curve25519_mul(out, in2, in); -} - -/* out = in^(2 * count) */ -DONNA_NOINLINE static void -curve25519_square_times(bignum25519 out, const bignum25519 in, uint64_t count) { -#if !defined(HAVE_NATIVE_UINT128) - uint128_t mul; -#endif - uint128_t t[5]; - uint64_t r0,r1,r2,r3,r4,c; - uint64_t d0,d1,d2,d4,d419; - - r0 = in[0]; - r1 = in[1]; - r2 = in[2]; - r3 = in[3]; - r4 = in[4]; - - do { - d0 = r0 * 2; - d1 = r1 * 2; - d2 = r2 * 2 * 19; - d419 = r4 * 19; - d4 = d419 * 2; - -#if defined(HAVE_NATIVE_UINT128) - t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 )); - t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19)); - t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 )); - t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 )); - t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 )); -#else - mul64x64_128(t[0], r0, r0) mul64x64_128(mul, d4, r1) add128(t[0], mul) mul64x64_128(mul, d2, r3) add128(t[0], mul) - mul64x64_128(t[1], d0, r1) mul64x64_128(mul, d4, r2) add128(t[1], mul) mul64x64_128(mul, r3, r3 * 19) add128(t[1], mul) - mul64x64_128(t[2], d0, r2) mul64x64_128(mul, r1, r1) add128(t[2], mul) mul64x64_128(mul, d4, r3) add128(t[2], mul) - mul64x64_128(t[3], d0, r3) mul64x64_128(mul, d1, r2) add128(t[3], mul) mul64x64_128(mul, r4, d419) add128(t[3], mul) - mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul) -#endif - - r0 = lo128(t[0]) & reduce_mask_51; - r1 = lo128(t[1]) & reduce_mask_51; shl128(c, t[0], 13); r1 += c; - r2 = lo128(t[2]) & reduce_mask_51; shl128(c, t[1], 13); r2 += c; - r3 = lo128(t[3]) & reduce_mask_51; shl128(c, t[2], 13); r3 += c; - r4 = lo128(t[4]) & reduce_mask_51; shl128(c, t[3], 13); r4 += c; - shl128(c, t[4], 13); r0 += c * 19; - c = r0 >> 51; r0 &= reduce_mask_51; - r1 += c ; c = r1 >> 51; r1 &= reduce_mask_51; - r2 += c ; c = r2 >> 51; r2 &= reduce_mask_51; - r3 += c ; c = r3 >> 51; r3 &= reduce_mask_51; - r4 += c ; c = r4 >> 51; r4 &= reduce_mask_51; - r0 += c * 19; - } while(--count); - - out[0] = r0; - out[1] = r1; - out[2] = r2; - out[3] = r3; - out[4] = r4; -} - -DONNA_INLINE static void -curve25519_square(bignum25519 out, const bignum25519 in) { -#if !defined(HAVE_NATIVE_UINT128) - uint128_t mul; -#endif - uint128_t t[5]; - uint64_t r0,r1,r2,r3,r4,c; - uint64_t d0,d1,d2,d4,d419; - - r0 = in[0]; - r1 = in[1]; - r2 = in[2]; - r3 = in[3]; - r4 = in[4]; - - d0 = r0 * 2; - d1 = r1 * 2; - d2 = r2 * 2 * 19; - d419 = r4 * 19; - d4 = d419 * 2; - -#if defined(HAVE_NATIVE_UINT128) - t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 )); - t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19)); - t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 )); - t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 )); - t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 )); -#else - mul64x64_128(t[0], r0, r0) mul64x64_128(mul, d4, r1) add128(t[0], mul) mul64x64_128(mul, d2, r3) add128(t[0], mul) - mul64x64_128(t[1], d0, r1) mul64x64_128(mul, d4, r2) add128(t[1], mul) mul64x64_128(mul, r3, r3 * 19) add128(t[1], mul) - mul64x64_128(t[2], d0, r2) mul64x64_128(mul, r1, r1) add128(t[2], mul) mul64x64_128(mul, d4, r3) add128(t[2], mul) - mul64x64_128(t[3], d0, r3) mul64x64_128(mul, d1, r2) add128(t[3], mul) mul64x64_128(mul, r4, d419) add128(t[3], mul) - mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul) -#endif - - r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51); - add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51); - add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51); - add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51); - add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51); - r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51; - r1 += c; - - out[0] = r0; - out[1] = r1; - out[2] = r2; - out[3] = r3; - out[4] = r4; -} - -/* Take a little-endian, 32-byte number and expand it into polynomial form */ -DONNA_INLINE static void -curve25519_expand(bignum25519 out, const unsigned char *in) { - static const union { uint8_t b[2]; uint16_t s; } endian_check = {{1,0}}; - uint64_t x0,x1,x2,x3; - - if (endian_check.s == 1) { - x0 = *(uint64_t *)(in + 0); - x1 = *(uint64_t *)(in + 8); - x2 = *(uint64_t *)(in + 16); - x3 = *(uint64_t *)(in + 24); - } else { - #define F(s) \ - ((((uint64_t)in[s + 0]) ) | \ - (((uint64_t)in[s + 1]) << 8) | \ - (((uint64_t)in[s + 2]) << 16) | \ - (((uint64_t)in[s + 3]) << 24) | \ - (((uint64_t)in[s + 4]) << 32) | \ - (((uint64_t)in[s + 5]) << 40) | \ - (((uint64_t)in[s + 6]) << 48) | \ - (((uint64_t)in[s + 7]) << 56)) - - x0 = F(0); - x1 = F(8); - x2 = F(16); - x3 = F(24); - } - - out[0] = x0 & reduce_mask_51; x0 = (x0 >> 51) | (x1 << 13); - out[1] = x0 & reduce_mask_51; x1 = (x1 >> 38) | (x2 << 26); - out[2] = x1 & reduce_mask_51; x2 = (x2 >> 25) | (x3 << 39); - out[3] = x2 & reduce_mask_51; x3 = (x3 >> 12); - out[4] = x3 & reduce_mask_51; -} - -/* Take a fully reduced polynomial form number and contract it into a - * little-endian, 32-byte array - */ -DONNA_INLINE static void -curve25519_contract(unsigned char *out, const bignum25519 input) { - uint64_t t[5]; - uint64_t f, i; - - t[0] = input[0]; - t[1] = input[1]; - t[2] = input[2]; - t[3] = input[3]; - t[4] = input[4]; - - #define curve25519_contract_carry() \ - t[1] += t[0] >> 51; t[0] &= reduce_mask_51; \ - t[2] += t[1] >> 51; t[1] &= reduce_mask_51; \ - t[3] += t[2] >> 51; t[2] &= reduce_mask_51; \ - t[4] += t[3] >> 51; t[3] &= reduce_mask_51; - - #define curve25519_contract_carry_full() curve25519_contract_carry() \ - t[0] += 19 * (t[4] >> 51); t[4] &= reduce_mask_51; - - #define curve25519_contract_carry_final() curve25519_contract_carry() \ - t[4] &= reduce_mask_51; - - curve25519_contract_carry_full() - curve25519_contract_carry_full() - - /* now t is between 0 and 2^255-1, properly carried. */ - /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ - t[0] += 19; - curve25519_contract_carry_full() - - /* now between 19 and 2^255-1 in both cases, and offset by 19. */ - t[0] += (reduce_mask_51 + 1) - 19; - t[1] += (reduce_mask_51 + 1) - 1; - t[2] += (reduce_mask_51 + 1) - 1; - t[3] += (reduce_mask_51 + 1) - 1; - t[4] += (reduce_mask_51 + 1) - 1; - - /* now between 2^255 and 2^256-20, and offset by 2^255. */ - curve25519_contract_carry_final() - - #define write51full(n,shift) \ - f = ((t[n] >> shift) | (t[n+1] << (51 - shift))); \ - for (i = 0; i < 8; i++, f >>= 8) *out++ = (unsigned char)f; - #define write51(n) write51full(n,13*n) - write51(0) - write51(1) - write51(2) - write51(3) -} - -#if !defined(ED25519_GCC_64BIT_CHOOSE) - -/* out = (flag) ? in : out */ -DONNA_INLINE static void -curve25519_move_conditional_bytes(uint8_t out[96], const uint8_t in[96], uint64_t flag) { - const uint64_t nb = flag - 1, b = ~nb; - const uint64_t *inq = (const uint64_t *)in; - uint64_t *outq = (uint64_t *)out; - outq[0] = (outq[0] & nb) | (inq[0] & b); - outq[1] = (outq[1] & nb) | (inq[1] & b); - outq[2] = (outq[2] & nb) | (inq[2] & b); - outq[3] = (outq[3] & nb) | (inq[3] & b); - outq[4] = (outq[4] & nb) | (inq[4] & b); - outq[5] = (outq[5] & nb) | (inq[5] & b); - outq[6] = (outq[6] & nb) | (inq[6] & b); - outq[7] = (outq[7] & nb) | (inq[7] & b); - outq[8] = (outq[8] & nb) | (inq[8] & b); - outq[9] = (outq[9] & nb) | (inq[9] & b); - outq[10] = (outq[10] & nb) | (inq[10] & b); - outq[11] = (outq[11] & nb) | (inq[11] & b); -} - -/* if (iswap) swap(a, b) */ -DONNA_INLINE static void -curve25519_swap_conditional(bignum25519 a, bignum25519 b, uint64_t iswap) { - const uint64_t swap = (uint64_t)(-(int64_t)iswap); - uint64_t x0,x1,x2,x3,x4; - - x0 = swap & (a[0] ^ b[0]); a[0] ^= x0; b[0] ^= x0; - x1 = swap & (a[1] ^ b[1]); a[1] ^= x1; b[1] ^= x1; - x2 = swap & (a[2] ^ b[2]); a[2] ^= x2; b[2] ^= x2; - x3 = swap & (a[3] ^ b[3]); a[3] ^= x3; b[3] ^= x3; - x4 = swap & (a[4] ^ b[4]); a[4] ^= x4; b[4] ^= x4; -} - -#endif /* ED25519_GCC_64BIT_CHOOSE */ - -#define ED25519_64BIT_TABLES - diff --git a/external/ed25519-donna/curve25519-donna-helpers.h b/external/ed25519-donna/curve25519-donna-helpers.h deleted file mode 100644 index e4058ff5ec..0000000000 --- a/external/ed25519-donna/curve25519-donna-helpers.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - Public domain by Andrew M. - See: https://github.com/floodyberry/curve25519-donna - - Curve25519 implementation agnostic helpers -*/ - -/* - * In: b = 2^5 - 2^0 - * Out: b = 2^250 - 2^0 - */ -static void -curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) { - bignum25519 ALIGN(16) t0,c; - - /* 2^5 - 2^0 */ /* b */ - /* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5); - /* 2^10 - 2^0 */ curve25519_mul_noinline(b, t0, b); - /* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10); - /* 2^20 - 2^0 */ curve25519_mul_noinline(c, t0, b); - /* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20); - /* 2^40 - 2^0 */ curve25519_mul_noinline(t0, t0, c); - /* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10); - /* 2^50 - 2^0 */ curve25519_mul_noinline(b, t0, b); - /* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50); - /* 2^100 - 2^0 */ curve25519_mul_noinline(c, t0, b); - /* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100); - /* 2^200 - 2^0 */ curve25519_mul_noinline(t0, t0, c); - /* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50); - /* 2^250 - 2^0 */ curve25519_mul_noinline(b, t0, b); -} - -/* - * z^(p - 2) = z(2^255 - 21) - */ -static void -curve25519_recip(bignum25519 out, const bignum25519 z) { - bignum25519 ALIGN(16) a,t0,b; - - /* 2 */ curve25519_square_times(a, z, 1); /* a = 2 */ - /* 8 */ curve25519_square_times(t0, a, 2); - /* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */ - /* 11 */ curve25519_mul_noinline(a, b, a); /* a = 11 */ - /* 22 */ curve25519_square_times(t0, a, 1); - /* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b); - /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); - /* 2^255 - 2^5 */ curve25519_square_times(b, b, 5); - /* 2^255 - 21 */ curve25519_mul_noinline(out, b, a); -} - -/* - * z^((p-5)/8) = z^(2^252 - 3) - */ -static void -curve25519_pow_two252m3(bignum25519 two252m3, const bignum25519 z) { - bignum25519 ALIGN(16) b,c,t0; - - /* 2 */ curve25519_square_times(c, z, 1); /* c = 2 */ - /* 8 */ curve25519_square_times(t0, c, 2); /* t0 = 8 */ - /* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */ - /* 11 */ curve25519_mul_noinline(c, b, c); /* c = 11 */ - /* 22 */ curve25519_square_times(t0, c, 1); - /* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b); - /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b); - /* 2^252 - 2^2 */ curve25519_square_times(b, b, 2); - /* 2^252 - 3 */ curve25519_mul_noinline(two252m3, b, z); -} diff --git a/external/ed25519-donna/curve25519-donna-sse2.h b/external/ed25519-donna/curve25519-donna-sse2.h deleted file mode 100644 index 1dbfd44d8b..0000000000 --- a/external/ed25519-donna/curve25519-donna-sse2.h +++ /dev/null @@ -1,1112 +0,0 @@ -/* - Public domain by Andrew M. - See: https://github.com/floodyberry/curve25519-donna - - SSE2 curve25519 implementation -*/ - -#include -typedef __m128i xmmi; - -typedef union packedelem8_t { - unsigned char u[16]; - xmmi v; -} packedelem8; - -typedef union packedelem32_t { - uint32_t u[4]; - xmmi v; -} packedelem32; - -typedef union packedelem64_t { - uint64_t u[2]; - xmmi v; -} packedelem64; - -/* 10 elements + an extra 2 to fit in 3 xmm registers */ -typedef uint32_t bignum25519[12]; -typedef packedelem32 packed32bignum25519[5]; -typedef packedelem64 packed64bignum25519[10]; - -static const packedelem32 bot32bitmask = {{0xffffffff, 0x00000000, 0xffffffff, 0x00000000}}; -static const packedelem32 top32bitmask = {{0x00000000, 0xffffffff, 0x00000000, 0xffffffff}}; -static const packedelem32 top64bitmask = {{0x00000000, 0x00000000, 0xffffffff, 0xffffffff}}; -static const packedelem32 bot64bitmask = {{0xffffffff, 0xffffffff, 0x00000000, 0x00000000}}; - -/* reduction masks */ -static const packedelem64 packedmask26 = {{0x03ffffff, 0x03ffffff}}; -static const packedelem64 packedmask25 = {{0x01ffffff, 0x01ffffff}}; -static const packedelem32 packedmask2625 = {{0x3ffffff,0,0x1ffffff,0}}; -static const packedelem32 packedmask26262626 = {{0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff}}; -static const packedelem32 packedmask25252525 = {{0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff}}; - -/* multipliers */ -static const packedelem64 packednineteen = {{19, 19}}; -static const packedelem64 packednineteenone = {{19, 1}}; -static const packedelem64 packedthirtyeight = {{38, 38}}; -static const packedelem64 packed3819 = {{19*2,19}}; -static const packedelem64 packed9638 = {{19*4,19*2}}; - -/* 121666,121665 */ -static const packedelem64 packed121666121665 = {{121666, 121665}}; - -/* 2*(2^255 - 19) = 0 mod p */ -static const packedelem32 packed2p0 = {{0x7ffffda,0x3fffffe,0x7fffffe,0x3fffffe}}; -static const packedelem32 packed2p1 = {{0x7fffffe,0x3fffffe,0x7fffffe,0x3fffffe}}; -static const packedelem32 packed2p2 = {{0x7fffffe,0x3fffffe,0x0000000,0x0000000}}; - -static const packedelem32 packed32packed2p0 = {{0x7ffffda,0x7ffffda,0x3fffffe,0x3fffffe}}; -static const packedelem32 packed32packed2p1 = {{0x7fffffe,0x7fffffe,0x3fffffe,0x3fffffe}}; - -/* 4*(2^255 - 19) = 0 mod p */ -static const packedelem32 packed4p0 = {{0xfffffb4,0x7fffffc,0xffffffc,0x7fffffc}}; -static const packedelem32 packed4p1 = {{0xffffffc,0x7fffffc,0xffffffc,0x7fffffc}}; -static const packedelem32 packed4p2 = {{0xffffffc,0x7fffffc,0x0000000,0x0000000}}; - -static const packedelem32 packed32packed4p0 = {{0xfffffb4,0xfffffb4,0x7fffffc,0x7fffffc}}; -static const packedelem32 packed32packed4p1 = {{0xffffffc,0xffffffc,0x7fffffc,0x7fffffc}}; - -/* out = in */ -DONNA_INLINE static void -curve25519_copy(bignum25519 out, const bignum25519 in) { - xmmi x0,x1,x2; - x0 = _mm_load_si128((xmmi*)in + 0); - x1 = _mm_load_si128((xmmi*)in + 1); - x2 = _mm_load_si128((xmmi*)in + 2); - _mm_store_si128((xmmi*)out + 0, x0); - _mm_store_si128((xmmi*)out + 1, x1); - _mm_store_si128((xmmi*)out + 2, x2); -} - -/* out = a + b */ -DONNA_INLINE static void -curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) { - xmmi a0,a1,a2,b0,b1,b2; - a0 = _mm_load_si128((xmmi*)a + 0); - a1 = _mm_load_si128((xmmi*)a + 1); - a2 = _mm_load_si128((xmmi*)a + 2); - b0 = _mm_load_si128((xmmi*)b + 0); - b1 = _mm_load_si128((xmmi*)b + 1); - b2 = _mm_load_si128((xmmi*)b + 2); - a0 = _mm_add_epi32(a0, b0); - a1 = _mm_add_epi32(a1, b1); - a2 = _mm_add_epi32(a2, b2); - _mm_store_si128((xmmi*)out + 0, a0); - _mm_store_si128((xmmi*)out + 1, a1); - _mm_store_si128((xmmi*)out + 2, a2); -} - -#define curve25519_add_after_basic curve25519_add_reduce -DONNA_INLINE static void -curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { - xmmi a0,a1,a2,b0,b1,b2; - xmmi c1,c2,c3; - xmmi r0,r1,r2,r3,r4,r5; - - a0 = _mm_load_si128((xmmi*)a + 0); - a1 = _mm_load_si128((xmmi*)a + 1); - a2 = _mm_load_si128((xmmi*)a + 2); - b0 = _mm_load_si128((xmmi*)b + 0); - b1 = _mm_load_si128((xmmi*)b + 1); - b2 = _mm_load_si128((xmmi*)b + 2); - a0 = _mm_add_epi32(a0, b0); - a1 = _mm_add_epi32(a1, b1); - a2 = _mm_add_epi32(a2, b2); - - r0 = _mm_and_si128(_mm_unpacklo_epi64(a0, a1), bot32bitmask.v); - r1 = _mm_srli_epi64(_mm_unpacklo_epi64(a0, a1), 32); - r2 = _mm_and_si128(_mm_unpackhi_epi64(a0, a1), bot32bitmask.v); - r3 = _mm_srli_epi64(_mm_unpackhi_epi64(a0, a1), 32); - r4 = _mm_and_si128(_mm_unpacklo_epi64(_mm_setzero_si128(), a2), bot32bitmask.v); - r5 = _mm_srli_epi64(_mm_unpacklo_epi64(_mm_setzero_si128(), a2), 32); - - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); - c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); - c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - - _mm_store_si128((xmmi*)out + 0, _mm_unpacklo_epi64(_mm_unpacklo_epi32(r0, r1), _mm_unpacklo_epi32(r2, r3))); - _mm_store_si128((xmmi*)out + 1, _mm_unpacklo_epi64(_mm_unpackhi_epi32(r0, r1), _mm_unpackhi_epi32(r2, r3))); - _mm_store_si128((xmmi*)out + 2, _mm_unpackhi_epi32(r4, r5)); -} - -DONNA_INLINE static void -curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) { - xmmi a0,a1,a2,b0,b1,b2; - xmmi c1,c2; - xmmi r0,r1; - - a0 = _mm_load_si128((xmmi*)a + 0); - a1 = _mm_load_si128((xmmi*)a + 1); - a2 = _mm_load_si128((xmmi*)a + 2); - a0 = _mm_add_epi32(a0, packed2p0.v); - a1 = _mm_add_epi32(a1, packed2p1.v); - a2 = _mm_add_epi32(a2, packed2p2.v); - b0 = _mm_load_si128((xmmi*)b + 0); - b1 = _mm_load_si128((xmmi*)b + 1); - b2 = _mm_load_si128((xmmi*)b + 2); - a0 = _mm_sub_epi32(a0, b0); - a1 = _mm_sub_epi32(a1, b1); - a2 = _mm_sub_epi32(a2, b2); - - r0 = _mm_and_si128(_mm_shuffle_epi32(a0, _MM_SHUFFLE(2,2,0,0)), bot32bitmask.v); - r1 = _mm_and_si128(_mm_shuffle_epi32(a0, _MM_SHUFFLE(3,3,1,1)), bot32bitmask.v); - - c1 = _mm_srli_epi32(r0, 26); - c2 = _mm_srli_epi32(r1, 25); - r0 = _mm_and_si128(r0, packedmask26.v); - r1 = _mm_and_si128(r1, packedmask25.v); - r0 = _mm_add_epi32(r0, _mm_slli_si128(c2, 8)); - r1 = _mm_add_epi32(r1, c1); - - a0 = _mm_unpacklo_epi64(_mm_unpacklo_epi32(r0, r1), _mm_unpackhi_epi32(r0, r1)); - a1 = _mm_add_epi32(a1, _mm_srli_si128(c2, 8)); - - _mm_store_si128((xmmi*)out + 0, a0); - _mm_store_si128((xmmi*)out + 1, a1); - _mm_store_si128((xmmi*)out + 2, a2); -} - -DONNA_INLINE static void -curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) { - xmmi a0,a1,a2,b0,b1,b2; - xmmi c1,c2,c3; - xmmi r0,r1,r2,r3,r4,r5; - - a0 = _mm_load_si128((xmmi*)a + 0); - a1 = _mm_load_si128((xmmi*)a + 1); - a2 = _mm_load_si128((xmmi*)a + 2); - a0 = _mm_add_epi32(a0, packed4p0.v); - a1 = _mm_add_epi32(a1, packed4p1.v); - a2 = _mm_add_epi32(a2, packed4p2.v); - b0 = _mm_load_si128((xmmi*)b + 0); - b1 = _mm_load_si128((xmmi*)b + 1); - b2 = _mm_load_si128((xmmi*)b + 2); - a0 = _mm_sub_epi32(a0, b0); - a1 = _mm_sub_epi32(a1, b1); - a2 = _mm_sub_epi32(a2, b2); - - r0 = _mm_and_si128(_mm_unpacklo_epi64(a0, a1), bot32bitmask.v); - r1 = _mm_srli_epi64(_mm_unpacklo_epi64(a0, a1), 32); - r2 = _mm_and_si128(_mm_unpackhi_epi64(a0, a1), bot32bitmask.v); - r3 = _mm_srli_epi64(_mm_unpackhi_epi64(a0, a1), 32); - r4 = _mm_and_si128(_mm_unpacklo_epi64(_mm_setzero_si128(), a2), bot32bitmask.v); - r5 = _mm_srli_epi64(_mm_unpacklo_epi64(_mm_setzero_si128(), a2), 32); - - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); - c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); - c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - - _mm_store_si128((xmmi*)out + 0, _mm_unpacklo_epi64(_mm_unpacklo_epi32(r0, r1), _mm_unpacklo_epi32(r2, r3))); - _mm_store_si128((xmmi*)out + 1, _mm_unpacklo_epi64(_mm_unpackhi_epi32(r0, r1), _mm_unpackhi_epi32(r2, r3))); - _mm_store_si128((xmmi*)out + 2, _mm_unpackhi_epi32(r4, r5)); -} - -DONNA_INLINE static void -curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) { - xmmi a0,a1,a2,b0,b1,b2; - xmmi c1,c2,c3; - xmmi r0,r1,r2,r3,r4,r5; - - a0 = _mm_load_si128((xmmi*)a + 0); - a1 = _mm_load_si128((xmmi*)a + 1); - a2 = _mm_load_si128((xmmi*)a + 2); - a0 = _mm_add_epi32(a0, packed2p0.v); - a1 = _mm_add_epi32(a1, packed2p1.v); - a2 = _mm_add_epi32(a2, packed2p2.v); - b0 = _mm_load_si128((xmmi*)b + 0); - b1 = _mm_load_si128((xmmi*)b + 1); - b2 = _mm_load_si128((xmmi*)b + 2); - a0 = _mm_sub_epi32(a0, b0); - a1 = _mm_sub_epi32(a1, b1); - a2 = _mm_sub_epi32(a2, b2); - - r0 = _mm_and_si128(_mm_unpacklo_epi64(a0, a1), bot32bitmask.v); - r1 = _mm_srli_epi64(_mm_unpacklo_epi64(a0, a1), 32); - r2 = _mm_and_si128(_mm_unpackhi_epi64(a0, a1), bot32bitmask.v); - r3 = _mm_srli_epi64(_mm_unpackhi_epi64(a0, a1), 32); - r4 = _mm_and_si128(_mm_unpacklo_epi64(_mm_setzero_si128(), a2), bot32bitmask.v); - r5 = _mm_srli_epi64(_mm_unpacklo_epi64(_mm_setzero_si128(), a2), 32); - - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); - c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); - c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - - _mm_store_si128((xmmi*)out + 0, _mm_unpacklo_epi64(_mm_unpacklo_epi32(r0, r1), _mm_unpacklo_epi32(r2, r3))); - _mm_store_si128((xmmi*)out + 1, _mm_unpacklo_epi64(_mm_unpackhi_epi32(r0, r1), _mm_unpackhi_epi32(r2, r3))); - _mm_store_si128((xmmi*)out + 2, _mm_unpackhi_epi32(r4, r5)); -} - - -DONNA_INLINE static void -curve25519_neg(bignum25519 out, const bignum25519 b) { - xmmi a0,a1,a2,b0,b1,b2; - xmmi c1,c2,c3; - xmmi r0,r1,r2,r3,r4,r5; - - a0 = packed2p0.v; - a1 = packed2p1.v; - a2 = packed2p2.v; - b0 = _mm_load_si128((xmmi*)b + 0); - b1 = _mm_load_si128((xmmi*)b + 1); - b2 = _mm_load_si128((xmmi*)b + 2); - a0 = _mm_sub_epi32(a0, b0); - a1 = _mm_sub_epi32(a1, b1); - a2 = _mm_sub_epi32(a2, b2); - - r0 = _mm_and_si128(_mm_unpacklo_epi64(a0, a1), bot32bitmask.v); - r1 = _mm_srli_epi64(_mm_unpacklo_epi64(a0, a1), 32); - r2 = _mm_and_si128(_mm_unpackhi_epi64(a0, a1), bot32bitmask.v); - r3 = _mm_srli_epi64(_mm_unpackhi_epi64(a0, a1), 32); - r4 = _mm_and_si128(_mm_unpacklo_epi64(_mm_setzero_si128(), a2), bot32bitmask.v); - r5 = _mm_srli_epi64(_mm_unpacklo_epi64(_mm_setzero_si128(), a2), 32); - - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); - c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); - c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - - _mm_store_si128((xmmi*)out + 0, _mm_unpacklo_epi64(_mm_unpacklo_epi32(r0, r1), _mm_unpacklo_epi32(r2, r3))); - _mm_store_si128((xmmi*)out + 1, _mm_unpacklo_epi64(_mm_unpackhi_epi32(r0, r1), _mm_unpackhi_epi32(r2, r3))); - _mm_store_si128((xmmi*)out + 2, _mm_unpackhi_epi32(r4, r5)); -} - - -/* Multiply two numbers: out = in2 * in */ -static void -curve25519_mul(bignum25519 out, const bignum25519 r, const bignum25519 s) { - xmmi m01,m23,m45,m67,m89; - xmmi m0123,m4567; - xmmi s0123,s4567; - xmmi s01,s23,s45,s67,s89; - xmmi s12,s34,s56,s78,s9; - xmmi r0,r2,r4,r6,r8; - xmmi r1,r3,r5,r7,r9; - xmmi r119,r219,r319,r419,r519,r619,r719,r819,r919; - xmmi c1,c2,c3; - - s0123 = _mm_load_si128((xmmi*)s + 0); - s01 = _mm_shuffle_epi32(s0123,_MM_SHUFFLE(3,1,2,0)); - s12 = _mm_shuffle_epi32(s0123, _MM_SHUFFLE(2,2,1,1)); - s23 = _mm_shuffle_epi32(s0123,_MM_SHUFFLE(3,3,2,2)); - s4567 = _mm_load_si128((xmmi*)s + 1); - s34 = _mm_unpacklo_epi64(_mm_srli_si128(s0123,12),s4567); - s45 = _mm_shuffle_epi32(s4567,_MM_SHUFFLE(3,1,2,0)); - s56 = _mm_shuffle_epi32(s4567, _MM_SHUFFLE(2,2,1,1)); - s67 = _mm_shuffle_epi32(s4567,_MM_SHUFFLE(3,3,2,2)); - s89 = _mm_load_si128((xmmi*)s + 2); - s78 = _mm_unpacklo_epi64(_mm_srli_si128(s4567,12),s89); - s89 = _mm_shuffle_epi32(s89,_MM_SHUFFLE(3,1,2,0)); - s9 = _mm_shuffle_epi32(s89, _MM_SHUFFLE(3,3,2,2)); - - r0 = _mm_load_si128((xmmi*)r + 0); - r1 = _mm_shuffle_epi32(r0, _MM_SHUFFLE(1,1,1,1)); - r1 = _mm_add_epi64(r1, _mm_and_si128(r1, top64bitmask.v)); - r2 = _mm_shuffle_epi32(r0, _MM_SHUFFLE(2,2,2,2)); - r3 = _mm_shuffle_epi32(r0, _MM_SHUFFLE(3,3,3,3)); - r3 = _mm_add_epi64(r3, _mm_and_si128(r3, top64bitmask.v)); - r0 = _mm_shuffle_epi32(r0, _MM_SHUFFLE(0,0,0,0)); - r4 = _mm_load_si128((xmmi*)r + 1); - r5 = _mm_shuffle_epi32(r4, _MM_SHUFFLE(1,1,1,1)); - r5 = _mm_add_epi64(r5, _mm_and_si128(r5, top64bitmask.v)); - r6 = _mm_shuffle_epi32(r4, _MM_SHUFFLE(2,2,2,2)); - r7 = _mm_shuffle_epi32(r4, _MM_SHUFFLE(3,3,3,3)); - r7 = _mm_add_epi64(r7, _mm_and_si128(r7, top64bitmask.v)); - r4 = _mm_shuffle_epi32(r4, _MM_SHUFFLE(0,0,0,0)); - r8 = _mm_load_si128((xmmi*)r + 2); - r9 = _mm_shuffle_epi32(r8, _MM_SHUFFLE(3,1,3,1)); - r9 = _mm_add_epi64(r9, _mm_and_si128(r9, top64bitmask.v)); - r8 = _mm_shuffle_epi32(r8, _MM_SHUFFLE(3,0,3,0)); - - m01 = _mm_mul_epu32(r1,s01); - m23 = _mm_mul_epu32(r1,s23); - m45 = _mm_mul_epu32(r1,s45); - m67 = _mm_mul_epu32(r1,s67); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r3,s01)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r3,s23)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r3,s45)); - m89 = _mm_mul_epu32(r1,s89); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r5,s01)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r5,s23)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r3,s67)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r7,s01)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r5,s45)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r7,s23)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r9,s01)); - - /* shift up */ - m89 = _mm_unpackhi_epi64(m67,_mm_slli_si128(m89,8)); - m67 = _mm_unpackhi_epi64(m45,_mm_slli_si128(m67,8)); - m45 = _mm_unpackhi_epi64(m23,_mm_slli_si128(m45,8)); - m23 = _mm_unpackhi_epi64(m01,_mm_slli_si128(m23,8)); - m01 = _mm_unpackhi_epi64(_mm_setzero_si128(),_mm_slli_si128(m01,8)); - - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r0,s01)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r0,s23)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r0,s45)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r0,s67)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r2,s01)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r2,s23)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r4,s23)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r0,s89)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r4,s01)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r2,s45)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r2,s67)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r6,s01)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r4,s45)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r6,s23)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r8,s01)); - - r219 = _mm_mul_epu32(r2, packednineteen.v); - r419 = _mm_mul_epu32(r4, packednineteen.v); - r619 = _mm_mul_epu32(r6, packednineteen.v); - r819 = _mm_mul_epu32(r8, packednineteen.v); - r119 = _mm_shuffle_epi32(r1,_MM_SHUFFLE(0,0,2,2)); r119 = _mm_mul_epu32(r119, packednineteen.v); - r319 = _mm_shuffle_epi32(r3,_MM_SHUFFLE(0,0,2,2)); r319 = _mm_mul_epu32(r319, packednineteen.v); - r519 = _mm_shuffle_epi32(r5,_MM_SHUFFLE(0,0,2,2)); r519 = _mm_mul_epu32(r519, packednineteen.v); - r719 = _mm_shuffle_epi32(r7,_MM_SHUFFLE(0,0,2,2)); r719 = _mm_mul_epu32(r719, packednineteen.v); - r919 = _mm_shuffle_epi32(r9,_MM_SHUFFLE(0,0,2,2)); r919 = _mm_mul_epu32(r919, packednineteen.v); - - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r919,s12)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r919,s34)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r919,s56)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r919,s78)); - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r719,s34)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r719,s56)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r719,s78)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r719,s9)); - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r519,s56)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r519,s78)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r519,s9)); - m67 = _mm_add_epi64(m67,_mm_mul_epu32(r819,s89)); - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r319,s78)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r319,s9)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r619,s89)); - m89 = _mm_add_epi64(m89,_mm_mul_epu32(r919,s9)); - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r819,s23)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r819,s45)); - m45 = _mm_add_epi64(m45,_mm_mul_epu32(r819,s67)); - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r619,s45)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r619,s67)); - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r419,s67)); - m23 = _mm_add_epi64(m23,_mm_mul_epu32(r419,s89)); - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r219,s89)); - m01 = _mm_add_epi64(m01,_mm_mul_epu32(r119,s9)); - - r0 = _mm_unpacklo_epi64(m01, m45); - r1 = _mm_unpackhi_epi64(m01, m45); - r2 = _mm_unpacklo_epi64(m23, m67); - r3 = _mm_unpackhi_epi64(m23, m67); - r4 = _mm_unpacklo_epi64(m89, m89); - r5 = _mm_unpackhi_epi64(m89, m89); - - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); - c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); - c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - - m0123 = _mm_unpacklo_epi32(r0, r1); - m4567 = _mm_unpackhi_epi32(r0, r1); - m0123 = _mm_unpacklo_epi64(m0123, _mm_unpacklo_epi32(r2, r3)); - m4567 = _mm_unpacklo_epi64(m4567, _mm_unpackhi_epi32(r2, r3)); - m89 = _mm_unpackhi_epi32(r4, r5); - - _mm_store_si128((xmmi*)out + 0, m0123); - _mm_store_si128((xmmi*)out + 1, m4567); - _mm_store_si128((xmmi*)out + 2, m89); -} - -DONNA_NOINLINE static void -curve25519_mul_noinline(bignum25519 out, const bignum25519 r, const bignum25519 s) { - curve25519_mul(out, r, s); -} - -#define curve25519_square(r, n) curve25519_square_times(r, n, 1) -static void -curve25519_square_times(bignum25519 r, const bignum25519 in, int count) { - xmmi m01,m23,m45,m67,m89; - xmmi r0,r1,r2,r3,r4,r5,r6,r7,r8,r9; - xmmi r0a,r1a,r2a,r3a,r7a,r9a; - xmmi r0123,r4567; - xmmi r01,r23,r45,r67,r6x,r89,r8x; - xmmi r12,r34,r56,r78,r9x; - xmmi r5619; - xmmi c1,c2,c3; - - r0123 = _mm_load_si128((xmmi*)in + 0); - r01 = _mm_shuffle_epi32(r0123,_MM_SHUFFLE(3,1,2,0)); - r23 = _mm_shuffle_epi32(r0123,_MM_SHUFFLE(3,3,2,2)); - r4567 = _mm_load_si128((xmmi*)in + 1); - r45 = _mm_shuffle_epi32(r4567,_MM_SHUFFLE(3,1,2,0)); - r67 = _mm_shuffle_epi32(r4567,_MM_SHUFFLE(3,3,2,2)); - r89 = _mm_load_si128((xmmi*)in + 2); - r89 = _mm_shuffle_epi32(r89,_MM_SHUFFLE(3,1,2,0)); - - do { - r12 = _mm_unpackhi_epi64(r01, _mm_slli_si128(r23, 8)); - r0 = _mm_shuffle_epi32(r01, _MM_SHUFFLE(0,0,0,0)); - r0 = _mm_add_epi64(r0, _mm_and_si128(r0, top64bitmask.v)); - r0a = _mm_shuffle_epi32(r0,_MM_SHUFFLE(3,2,1,2)); - r1 = _mm_shuffle_epi32(r01, _MM_SHUFFLE(2,2,2,2)); - r2 = _mm_shuffle_epi32(r23, _MM_SHUFFLE(0,0,0,0)); - r2 = _mm_add_epi64(r2, _mm_and_si128(r2, top64bitmask.v)); - r2a = _mm_shuffle_epi32(r2,_MM_SHUFFLE(3,2,1,2)); - r3 = _mm_shuffle_epi32(r23, _MM_SHUFFLE(2,2,2,2)); - r34 = _mm_unpackhi_epi64(r23, _mm_slli_si128(r45, 8)); - r4 = _mm_shuffle_epi32(r45, _MM_SHUFFLE(0,0,0,0)); - r4 = _mm_add_epi64(r4, _mm_and_si128(r4, top64bitmask.v)); - r56 = _mm_unpackhi_epi64(r45, _mm_slli_si128(r67, 8)); - r5619 = _mm_mul_epu32(r56, packednineteen.v); - r5 = _mm_shuffle_epi32(r5619, _MM_SHUFFLE(1,1,1,0)); - r6 = _mm_shuffle_epi32(r5619, _MM_SHUFFLE(3,2,3,2)); - r78 = _mm_unpackhi_epi64(r67, _mm_slli_si128(r89, 8)); - r6x = _mm_unpacklo_epi64(r67, _mm_setzero_si128()); - r7 = _mm_shuffle_epi32(r67, _MM_SHUFFLE(2,2,2,2)); - r7 = _mm_mul_epu32(r7, packed3819.v); - r7a = _mm_shuffle_epi32(r7, _MM_SHUFFLE(3,3,3,2)); - r8x = _mm_unpacklo_epi64(r89, _mm_setzero_si128()); - r8 = _mm_shuffle_epi32(r89, _MM_SHUFFLE(0,0,0,0)); - r8 = _mm_mul_epu32(r8, packednineteen.v); - r9 = _mm_shuffle_epi32(r89, _MM_SHUFFLE(2,2,2,2)); - r9x = _mm_slli_epi32(_mm_shuffle_epi32(r89, _MM_SHUFFLE(3,3,3,2)), 1); - r9 = _mm_mul_epu32(r9, packed3819.v); - r9a = _mm_shuffle_epi32(r9, _MM_SHUFFLE(2,2,2,2)); - - m01 = _mm_mul_epu32(r01, r0); - m23 = _mm_mul_epu32(r23, r0a); - m45 = _mm_mul_epu32(r45, r0a); - m45 = _mm_add_epi64(m45, _mm_mul_epu32(r23, r2)); - r23 = _mm_slli_epi32(r23, 1); - m67 = _mm_mul_epu32(r67, r0a); - m67 = _mm_add_epi64(m67, _mm_mul_epu32(r45, r2a)); - m89 = _mm_mul_epu32(r89, r0a); - m89 = _mm_add_epi64(m89, _mm_mul_epu32(r67, r2a)); - r67 = _mm_slli_epi32(r67, 1); - m89 = _mm_add_epi64(m89, _mm_mul_epu32(r45, r4)); - r45 = _mm_slli_epi32(r45, 1); - - r1 = _mm_slli_epi32(r1, 1); - r3 = _mm_slli_epi32(r3, 1); - r1a = _mm_add_epi64(r1, _mm_and_si128(r1, bot64bitmask.v)); - r3a = _mm_add_epi64(r3, _mm_and_si128(r3, bot64bitmask.v)); - - m23 = _mm_add_epi64(m23, _mm_mul_epu32(r12, r1)); - m45 = _mm_add_epi64(m45, _mm_mul_epu32(r34, r1a)); - m67 = _mm_add_epi64(m67, _mm_mul_epu32(r56, r1a)); - m67 = _mm_add_epi64(m67, _mm_mul_epu32(r34, r3)); - r34 = _mm_slli_epi32(r34, 1); - m89 = _mm_add_epi64(m89, _mm_mul_epu32(r78, r1a)); - r78 = _mm_slli_epi32(r78, 1); - m89 = _mm_add_epi64(m89, _mm_mul_epu32(r56, r3a)); - r56 = _mm_slli_epi32(r56, 1); - - m01 = _mm_add_epi64(m01, _mm_mul_epu32(_mm_slli_epi32(r12, 1), r9)); - m01 = _mm_add_epi64(m01, _mm_mul_epu32(r34, r7)); - m23 = _mm_add_epi64(m23, _mm_mul_epu32(r34, r9)); - m01 = _mm_add_epi64(m01, _mm_mul_epu32(r56, r5)); - m23 = _mm_add_epi64(m23, _mm_mul_epu32(r56, r7)); - m45 = _mm_add_epi64(m45, _mm_mul_epu32(r56, r9)); - m01 = _mm_add_epi64(m01, _mm_mul_epu32(r23, r8)); - m01 = _mm_add_epi64(m01, _mm_mul_epu32(r45, r6)); - m23 = _mm_add_epi64(m23, _mm_mul_epu32(r45, r8)); - m23 = _mm_add_epi64(m23, _mm_mul_epu32(r6x, r6)); - m45 = _mm_add_epi64(m45, _mm_mul_epu32(r78, r7a)); - m67 = _mm_add_epi64(m67, _mm_mul_epu32(r78, r9)); - m45 = _mm_add_epi64(m45, _mm_mul_epu32(r67, r8)); - m67 = _mm_add_epi64(m67, _mm_mul_epu32(r8x, r8)); - m89 = _mm_add_epi64(m89, _mm_mul_epu32(r9x, r9a)); - - r0 = _mm_unpacklo_epi64(m01, m45); - r1 = _mm_unpackhi_epi64(m01, m45); - r2 = _mm_unpacklo_epi64(m23, m67); - r3 = _mm_unpackhi_epi64(m23, m67); - r4 = _mm_unpacklo_epi64(m89, m89); - r5 = _mm_unpackhi_epi64(m89, m89); - - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - c1 = _mm_srli_epi64(r1, 25); c2 = _mm_srli_epi64(r3, 25); r1 = _mm_and_si128(r1, packedmask25.v); r3 = _mm_and_si128(r3, packedmask25.v); r2 = _mm_add_epi64(r2, c1); r4 = _mm_add_epi64(r4, c2); c3 = _mm_slli_si128(c2, 8); - c1 = _mm_srli_epi64(r4, 26); r4 = _mm_and_si128(r4, packedmask26.v); r5 = _mm_add_epi64(r5, c1); - c1 = _mm_srli_epi64(r5, 25); r5 = _mm_and_si128(r5, packedmask25.v); r0 = _mm_add_epi64(r0, _mm_unpackhi_epi64(_mm_mul_epu32(c1, packednineteen.v), c3)); - c1 = _mm_srli_epi64(r0, 26); c2 = _mm_srli_epi64(r2, 26); r0 = _mm_and_si128(r0, packedmask26.v); r2 = _mm_and_si128(r2, packedmask26.v); r1 = _mm_add_epi64(r1, c1); r3 = _mm_add_epi64(r3, c2); - - r01 = _mm_unpacklo_epi64(r0, r1); - r45 = _mm_unpackhi_epi64(r0, r1); - r23 = _mm_unpacklo_epi64(r2, r3); - r67 = _mm_unpackhi_epi64(r2, r3); - r89 = _mm_unpackhi_epi64(r4, r5); - } while (--count); - - r0123 = _mm_shuffle_epi32(r23, _MM_SHUFFLE(2,0,3,3)); - r4567 = _mm_shuffle_epi32(r67, _MM_SHUFFLE(2,0,3,3)); - r0123 = _mm_or_si128(r0123, _mm_shuffle_epi32(r01, _MM_SHUFFLE(3,3,2,0))); - r4567 = _mm_or_si128(r4567, _mm_shuffle_epi32(r45, _MM_SHUFFLE(3,3,2,0))); - r89 = _mm_shuffle_epi32(r89, _MM_SHUFFLE(3,3,2,0)); - - _mm_store_si128((xmmi*)r + 0, r0123); - _mm_store_si128((xmmi*)r + 1, r4567); - _mm_store_si128((xmmi*)r + 2, r89); -} - -DONNA_INLINE static void -curve25519_tangle32(packedelem32 *out, const bignum25519 x, const bignum25519 z) { - xmmi x0,x1,x2,z0,z1,z2; - - x0 = _mm_load_si128((xmmi *)(x + 0)); - x1 = _mm_load_si128((xmmi *)(x + 4)); - x2 = _mm_load_si128((xmmi *)(x + 8)); - z0 = _mm_load_si128((xmmi *)(z + 0)); - z1 = _mm_load_si128((xmmi *)(z + 4)); - z2 = _mm_load_si128((xmmi *)(z + 8)); - - out[0].v = _mm_unpacklo_epi32(x0, z0); - out[1].v = _mm_unpackhi_epi32(x0, z0); - out[2].v = _mm_unpacklo_epi32(x1, z1); - out[3].v = _mm_unpackhi_epi32(x1, z1); - out[4].v = _mm_unpacklo_epi32(x2, z2); -} - -DONNA_INLINE static void -curve25519_untangle32(bignum25519 x, bignum25519 z, const packedelem32 *in) { - xmmi t0,t1,t2,t3,t4,zero; - - t0 = _mm_shuffle_epi32(in[0].v, _MM_SHUFFLE(3,1,2,0)); - t1 = _mm_shuffle_epi32(in[1].v, _MM_SHUFFLE(3,1,2,0)); - t2 = _mm_shuffle_epi32(in[2].v, _MM_SHUFFLE(3,1,2,0)); - t3 = _mm_shuffle_epi32(in[3].v, _MM_SHUFFLE(3,1,2,0)); - t4 = _mm_shuffle_epi32(in[4].v, _MM_SHUFFLE(3,1,2,0)); - zero = _mm_setzero_si128(); - _mm_store_si128((xmmi *)x + 0, _mm_unpacklo_epi64(t0, t1)); - _mm_store_si128((xmmi *)x + 1, _mm_unpacklo_epi64(t2, t3)); - _mm_store_si128((xmmi *)x + 2, _mm_unpacklo_epi64(t4, zero)); - _mm_store_si128((xmmi *)z + 0, _mm_unpackhi_epi64(t0, t1)); - _mm_store_si128((xmmi *)z + 1, _mm_unpackhi_epi64(t2, t3)); - _mm_store_si128((xmmi *)z + 2, _mm_unpackhi_epi64(t4, zero)); -} - -DONNA_INLINE static void -curve25519_add_reduce_packed32(packedelem32 *out, const packedelem32 *r, const packedelem32 *s) { - xmmi r0,r1,r2,r3,r4; - xmmi s0,s1,s2,s3,s4,s5; - xmmi c1,c2; - - r0 = _mm_add_epi32(r[0].v, s[0].v); - r1 = _mm_add_epi32(r[1].v, s[1].v); - r2 = _mm_add_epi32(r[2].v, s[2].v); - r3 = _mm_add_epi32(r[3].v, s[3].v); - r4 = _mm_add_epi32(r[4].v, s[4].v); - - s0 = _mm_unpacklo_epi64(r0, r2); /* 00 44 */ - s1 = _mm_unpackhi_epi64(r0, r2); /* 11 55 */ - s2 = _mm_unpacklo_epi64(r1, r3); /* 22 66 */ - s3 = _mm_unpackhi_epi64(r1, r3); /* 33 77 */ - s4 = _mm_unpacklo_epi64(_mm_setzero_si128(), r4); /* 00 88 */ - s5 = _mm_unpackhi_epi64(_mm_setzero_si128(), r4); /* 00 99 */ - - c1 = _mm_srli_epi32(s0, 26); c2 = _mm_srli_epi32(s2, 26); s0 = _mm_and_si128(s0, packedmask26262626.v); s2 = _mm_and_si128(s2, packedmask26262626.v); s1 = _mm_add_epi32(s1, c1); s3 = _mm_add_epi32(s3, c2); - c1 = _mm_srli_epi32(s1, 25); c2 = _mm_srli_epi32(s3, 25); s1 = _mm_and_si128(s1, packedmask25252525.v); s3 = _mm_and_si128(s3, packedmask25252525.v); s2 = _mm_add_epi32(s2, c1); s4 = _mm_add_epi32(s4, _mm_unpackhi_epi64(_mm_setzero_si128(), c2)); s0 = _mm_add_epi32(s0, _mm_unpacklo_epi64(_mm_setzero_si128(), c2)); - c1 = _mm_srli_epi32(s2, 26); c2 = _mm_srli_epi32(s4, 26); s2 = _mm_and_si128(s2, packedmask26262626.v); s4 = _mm_and_si128(s4, packedmask26262626.v); s3 = _mm_add_epi32(s3, c1); s5 = _mm_add_epi32(s5, c2); - c1 = _mm_srli_epi32(s3, 25); c2 = _mm_srli_epi32(s5, 25); s3 = _mm_and_si128(s3, packedmask25252525.v); s5 = _mm_and_si128(s5, packedmask25252525.v); s4 = _mm_add_epi32(s4, c1); s0 = _mm_add_epi32(s0, _mm_or_si128(_mm_slli_si128(c1, 8), _mm_srli_si128(_mm_add_epi32(_mm_add_epi32(_mm_slli_epi32(c2, 4), _mm_slli_epi32(c2, 1)), c2), 8))); - c1 = _mm_srli_epi32(s0, 26); c2 = _mm_srli_epi32(s2, 26); s0 = _mm_and_si128(s0, packedmask26262626.v); s2 = _mm_and_si128(s2, packedmask26262626.v); s1 = _mm_add_epi32(s1, c1); s3 = _mm_add_epi32(s3, c2); - - out[0].v = _mm_unpacklo_epi64(s0, s1); /* 00 11 */ - out[1].v = _mm_unpacklo_epi64(s2, s3); /* 22 33 */ - out[2].v = _mm_unpackhi_epi64(s0, s1); /* 44 55 */ - out[3].v = _mm_unpackhi_epi64(s2, s3); /* 66 77 */ - out[4].v = _mm_unpackhi_epi64(s4, s5); /* 88 99 */ -} - -DONNA_INLINE static void -curve25519_add_packed32(packedelem32 *out, const packedelem32 *r, const packedelem32 *s) { - out[0].v = _mm_add_epi32(r[0].v, s[0].v); - out[1].v = _mm_add_epi32(r[1].v, s[1].v); - out[2].v = _mm_add_epi32(r[2].v, s[2].v); - out[3].v = _mm_add_epi32(r[3].v, s[3].v); - out[4].v = _mm_add_epi32(r[4].v, s[4].v); -} - -DONNA_INLINE static void -curve25519_sub_packed32(packedelem32 *out, const packedelem32 *r, const packedelem32 *s) { - xmmi r0,r1,r2,r3,r4; - xmmi s0,s1,s2,s3; - xmmi c1,c2; - - r0 = _mm_add_epi32(r[0].v, packed32packed2p0.v); - r1 = _mm_add_epi32(r[1].v, packed32packed2p1.v); - r2 = _mm_add_epi32(r[2].v, packed32packed2p1.v); - r3 = _mm_add_epi32(r[3].v, packed32packed2p1.v); - r4 = _mm_add_epi32(r[4].v, packed32packed2p1.v); - r0 = _mm_sub_epi32(r0, s[0].v); /* 00 11 */ - r1 = _mm_sub_epi32(r1, s[1].v); /* 22 33 */ - r2 = _mm_sub_epi32(r2, s[2].v); /* 44 55 */ - r3 = _mm_sub_epi32(r3, s[3].v); /* 66 77 */ - r4 = _mm_sub_epi32(r4, s[4].v); /* 88 99 */ - - s0 = _mm_unpacklo_epi64(r0, r2); /* 00 44 */ - s1 = _mm_unpackhi_epi64(r0, r2); /* 11 55 */ - s2 = _mm_unpacklo_epi64(r1, r3); /* 22 66 */ - s3 = _mm_unpackhi_epi64(r1, r3); /* 33 77 */ - - c1 = _mm_srli_epi32(s0, 26); c2 = _mm_srli_epi32(s2, 26); s0 = _mm_and_si128(s0, packedmask26262626.v); s2 = _mm_and_si128(s2, packedmask26262626.v); s1 = _mm_add_epi32(s1, c1); s3 = _mm_add_epi32(s3, c2); - c1 = _mm_srli_epi32(s1, 25); c2 = _mm_srli_epi32(s3, 25); s1 = _mm_and_si128(s1, packedmask25252525.v); s3 = _mm_and_si128(s3, packedmask25252525.v); s2 = _mm_add_epi32(s2, c1); r4 = _mm_add_epi32(r4, _mm_srli_si128(c2, 8)); s0 = _mm_add_epi32(s0, _mm_slli_si128(c2, 8)); - - out[0].v = _mm_unpacklo_epi64(s0, s1); /* 00 11 */ - out[1].v = _mm_unpacklo_epi64(s2, s3); /* 22 33 */ - out[2].v = _mm_unpackhi_epi64(s0, s1); /* 44 55 */ - out[3].v = _mm_unpackhi_epi64(s2, s3); /* 66 77 */ - out[4].v = r4; -} - -DONNA_INLINE static void -curve25519_sub_after_basic_packed32(packedelem32 *out, const packedelem32 *r, const packedelem32 *s) { - xmmi r0,r1,r2,r3,r4; - xmmi s0,s1,s2,s3,s4,s5; - xmmi c1,c2; - - r0 = _mm_add_epi32(r[0].v, packed32packed4p0.v); - r1 = _mm_add_epi32(r[1].v, packed32packed4p1.v); - r2 = _mm_add_epi32(r[2].v, packed32packed4p1.v); - r3 = _mm_add_epi32(r[3].v, packed32packed4p1.v); - r4 = _mm_add_epi32(r[4].v, packed32packed4p1.v); - r0 = _mm_sub_epi32(r0, s[0].v); /* 00 11 */ - r1 = _mm_sub_epi32(r1, s[1].v); /* 22 33 */ - r2 = _mm_sub_epi32(r2, s[2].v); /* 44 55 */ - r3 = _mm_sub_epi32(r3, s[3].v); /* 66 77 */ - r4 = _mm_sub_epi32(r4, s[4].v); /* 88 99 */ - - s0 = _mm_unpacklo_epi64(r0, r2); /* 00 44 */ - s1 = _mm_unpackhi_epi64(r0, r2); /* 11 55 */ - s2 = _mm_unpacklo_epi64(r1, r3); /* 22 66 */ - s3 = _mm_unpackhi_epi64(r1, r3); /* 33 77 */ - s4 = _mm_unpacklo_epi64(_mm_setzero_si128(), r4); /* 00 88 */ - s5 = _mm_unpackhi_epi64(_mm_setzero_si128(), r4); /* 00 99 */ - - c1 = _mm_srli_epi32(s0, 26); c2 = _mm_srli_epi32(s2, 26); s0 = _mm_and_si128(s0, packedmask26262626.v); s2 = _mm_and_si128(s2, packedmask26262626.v); s1 = _mm_add_epi32(s1, c1); s3 = _mm_add_epi32(s3, c2); - c1 = _mm_srli_epi32(s1, 25); c2 = _mm_srli_epi32(s3, 25); s1 = _mm_and_si128(s1, packedmask25252525.v); s3 = _mm_and_si128(s3, packedmask25252525.v); s2 = _mm_add_epi32(s2, c1); s4 = _mm_add_epi32(s4, _mm_unpackhi_epi64(_mm_setzero_si128(), c2)); s0 = _mm_add_epi32(s0, _mm_unpacklo_epi64(_mm_setzero_si128(), c2)); - c1 = _mm_srli_epi32(s2, 26); c2 = _mm_srli_epi32(s4, 26); s2 = _mm_and_si128(s2, packedmask26262626.v); s4 = _mm_and_si128(s4, packedmask26262626.v); s3 = _mm_add_epi32(s3, c1); s5 = _mm_add_epi32(s5, c2); - c1 = _mm_srli_epi32(s3, 25); c2 = _mm_srli_epi32(s5, 25); s3 = _mm_and_si128(s3, packedmask25252525.v); s5 = _mm_and_si128(s5, packedmask25252525.v); s4 = _mm_add_epi32(s4, c1); s0 = _mm_add_epi32(s0, _mm_or_si128(_mm_slli_si128(c1, 8), _mm_srli_si128(_mm_add_epi32(_mm_add_epi32(_mm_slli_epi32(c2, 4), _mm_slli_epi32(c2, 1)), c2), 8))); - c1 = _mm_srli_epi32(s0, 26); c2 = _mm_srli_epi32(s2, 26); s0 = _mm_and_si128(s0, packedmask26262626.v); s2 = _mm_and_si128(s2, packedmask26262626.v); s1 = _mm_add_epi32(s1, c1); s3 = _mm_add_epi32(s3, c2); - - out[0].v = _mm_unpacklo_epi64(s0, s1); /* 00 11 */ - out[1].v = _mm_unpacklo_epi64(s2, s3); /* 22 33 */ - out[2].v = _mm_unpackhi_epi64(s0, s1); /* 44 55 */ - out[3].v = _mm_unpackhi_epi64(s2, s3); /* 66 77 */ - out[4].v = _mm_unpackhi_epi64(s4, s5); /* 88 99 */ -} - -DONNA_INLINE static void -curve25519_tangle64_from32(packedelem64 *a, packedelem64 *b, const packedelem32 *c, const packedelem32 *d) { - xmmi c0,c1,c2,c3,c4,c5,t; - xmmi d0,d1,d2,d3,d4,d5; - xmmi t0,t1,t2,t3,t4,zero; - - t0 = _mm_shuffle_epi32(c[0].v, _MM_SHUFFLE(3,1,2,0)); - t1 = _mm_shuffle_epi32(c[1].v, _MM_SHUFFLE(3,1,2,0)); - t2 = _mm_shuffle_epi32(d[0].v, _MM_SHUFFLE(3,1,2,0)); - t3 = _mm_shuffle_epi32(d[1].v, _MM_SHUFFLE(3,1,2,0)); - c0 = _mm_unpacklo_epi64(t0, t1); - c3 = _mm_unpackhi_epi64(t0, t1); - d0 = _mm_unpacklo_epi64(t2, t3); - d3 = _mm_unpackhi_epi64(t2, t3); - t = _mm_unpacklo_epi64(c0, d0); a[0].v = t; a[1].v = _mm_srli_epi64(t, 32); - t = _mm_unpackhi_epi64(c0, d0); a[2].v = t; a[3].v = _mm_srli_epi64(t, 32); - t = _mm_unpacklo_epi64(c3, d3); b[0].v = t; b[1].v = _mm_srli_epi64(t, 32); - t = _mm_unpackhi_epi64(c3, d3); b[2].v = t; b[3].v = _mm_srli_epi64(t, 32); - - t0 = _mm_shuffle_epi32(c[2].v, _MM_SHUFFLE(3,1,2,0)); - t1 = _mm_shuffle_epi32(c[3].v, _MM_SHUFFLE(3,1,2,0)); - t2 = _mm_shuffle_epi32(d[2].v, _MM_SHUFFLE(3,1,2,0)); - t3 = _mm_shuffle_epi32(d[3].v, _MM_SHUFFLE(3,1,2,0)); - c1 = _mm_unpacklo_epi64(t0, t1); - c4 = _mm_unpackhi_epi64(t0, t1); - d1 = _mm_unpacklo_epi64(t2, t3); - d4 = _mm_unpackhi_epi64(t2, t3); - t = _mm_unpacklo_epi64(c1, d1); a[4].v = t; a[5].v = _mm_srli_epi64(t, 32); - t = _mm_unpackhi_epi64(c1, d1); a[6].v = t; a[7].v = _mm_srli_epi64(t, 32); - t = _mm_unpacklo_epi64(c4, d4); b[4].v = t; b[5].v = _mm_srli_epi64(t, 32); - t = _mm_unpackhi_epi64(c4, d4); b[6].v = t; b[7].v = _mm_srli_epi64(t, 32); - - t4 = _mm_shuffle_epi32(c[4].v, _MM_SHUFFLE(3,1,2,0)); - zero = _mm_setzero_si128(); - c2 = _mm_unpacklo_epi64(t4, zero); - c5 = _mm_unpackhi_epi64(t4, zero); - t4 = _mm_shuffle_epi32(d[4].v, _MM_SHUFFLE(3,1,2,0)); - d2 = _mm_unpacklo_epi64(t4, zero); - d5 = _mm_unpackhi_epi64(t4, zero); - t = _mm_unpacklo_epi64(c2, d2); a[8].v = t; a[9].v = _mm_srli_epi64(t, 32); - t = _mm_unpacklo_epi64(c5, d5); b[8].v = t; b[9].v = _mm_srli_epi64(t, 32); -} - -DONNA_INLINE static void -curve25519_tangle64(packedelem64 *out, const bignum25519 x, const bignum25519 z) { - xmmi x0,x1,x2,z0,z1,z2,t; - - x0 = _mm_load_si128((xmmi *)x + 0); - x1 = _mm_load_si128((xmmi *)x + 1); - x2 = _mm_load_si128((xmmi *)x + 2); - z0 = _mm_load_si128((xmmi *)z + 0); - z1 = _mm_load_si128((xmmi *)z + 1); - z2 = _mm_load_si128((xmmi *)z + 2); - - t = _mm_unpacklo_epi64(x0, z0); out[0].v = t; out[1].v = _mm_srli_epi64(t, 32); - t = _mm_unpackhi_epi64(x0, z0); out[2].v = t; out[3].v = _mm_srli_epi64(t, 32); - t = _mm_unpacklo_epi64(x1, z1); out[4].v = t; out[5].v = _mm_srli_epi64(t, 32); - t = _mm_unpackhi_epi64(x1, z1); out[6].v = t; out[7].v = _mm_srli_epi64(t, 32); - t = _mm_unpacklo_epi64(x2, z2); out[8].v = t; out[9].v = _mm_srli_epi64(t, 32); -} - -DONNA_INLINE static void -curve25519_tangleone64(packedelem64 *out, const bignum25519 x) { - xmmi x0,x1,x2; - - x0 = _mm_load_si128((xmmi *)(x + 0)); - x1 = _mm_load_si128((xmmi *)(x + 4)); - x2 = _mm_load_si128((xmmi *)(x + 8)); - - out[0].v = _mm_shuffle_epi32(x0, _MM_SHUFFLE(0,0,0,0)); - out[1].v = _mm_shuffle_epi32(x0, _MM_SHUFFLE(1,1,1,1)); - out[2].v = _mm_shuffle_epi32(x0, _MM_SHUFFLE(2,2,2,2)); - out[3].v = _mm_shuffle_epi32(x0, _MM_SHUFFLE(3,3,3,3)); - out[4].v = _mm_shuffle_epi32(x1, _MM_SHUFFLE(0,0,0,0)); - out[5].v = _mm_shuffle_epi32(x1, _MM_SHUFFLE(1,1,1,1)); - out[6].v = _mm_shuffle_epi32(x1, _MM_SHUFFLE(2,2,2,2)); - out[7].v = _mm_shuffle_epi32(x1, _MM_SHUFFLE(3,3,3,3)); - out[8].v = _mm_shuffle_epi32(x2, _MM_SHUFFLE(0,0,0,0)); - out[9].v = _mm_shuffle_epi32(x2, _MM_SHUFFLE(1,1,1,1)); -} - -DONNA_INLINE static void -curve25519_swap64(packedelem64 *out) { - out[0].v = _mm_shuffle_epi32(out[0].v, _MM_SHUFFLE(1,0,3,2)); - out[1].v = _mm_shuffle_epi32(out[1].v, _MM_SHUFFLE(1,0,3,2)); - out[2].v = _mm_shuffle_epi32(out[2].v, _MM_SHUFFLE(1,0,3,2)); - out[3].v = _mm_shuffle_epi32(out[3].v, _MM_SHUFFLE(1,0,3,2)); - out[4].v = _mm_shuffle_epi32(out[4].v, _MM_SHUFFLE(1,0,3,2)); - out[5].v = _mm_shuffle_epi32(out[5].v, _MM_SHUFFLE(1,0,3,2)); - out[6].v = _mm_shuffle_epi32(out[6].v, _MM_SHUFFLE(1,0,3,2)); - out[7].v = _mm_shuffle_epi32(out[7].v, _MM_SHUFFLE(1,0,3,2)); - out[8].v = _mm_shuffle_epi32(out[8].v, _MM_SHUFFLE(1,0,3,2)); - out[9].v = _mm_shuffle_epi32(out[9].v, _MM_SHUFFLE(1,0,3,2)); -} - -DONNA_INLINE static void -curve25519_untangle64(bignum25519 x, bignum25519 z, const packedelem64 *in) { - _mm_store_si128((xmmi *)(x + 0), _mm_unpacklo_epi64(_mm_unpacklo_epi32(in[0].v, in[1].v), _mm_unpacklo_epi32(in[2].v, in[3].v))); - _mm_store_si128((xmmi *)(x + 4), _mm_unpacklo_epi64(_mm_unpacklo_epi32(in[4].v, in[5].v), _mm_unpacklo_epi32(in[6].v, in[7].v))); - _mm_store_si128((xmmi *)(x + 8), _mm_unpacklo_epi32(in[8].v, in[9].v) ); - _mm_store_si128((xmmi *)(z + 0), _mm_unpacklo_epi64(_mm_unpackhi_epi32(in[0].v, in[1].v), _mm_unpackhi_epi32(in[2].v, in[3].v))); - _mm_store_si128((xmmi *)(z + 4), _mm_unpacklo_epi64(_mm_unpackhi_epi32(in[4].v, in[5].v), _mm_unpackhi_epi32(in[6].v, in[7].v))); - _mm_store_si128((xmmi *)(z + 8), _mm_unpackhi_epi32(in[8].v, in[9].v) ); -} - -DONNA_INLINE static void -curve25519_mul_packed64(packedelem64 *out, const packedelem64 *r, const packedelem64 *s) { - xmmi r1,r2,r3,r4,r5,r6,r7,r8,r9; - xmmi r1_2,r3_2,r5_2,r7_2,r9_2; - xmmi c1,c2; - - out[0].v = _mm_mul_epu32(r[0].v, s[0].v); - out[1].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[1].v), _mm_mul_epu32(r[1].v, s[0].v)); - r1_2 = _mm_slli_epi32(r[1].v, 1); - out[2].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r1_2 , s[1].v), _mm_mul_epu32(r[2].v, s[0].v))); - out[3].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[3].v), _mm_add_epi64(_mm_mul_epu32(r[1].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[1].v), _mm_mul_epu32(r[3].v, s[0].v)))); - r3_2 = _mm_slli_epi32(r[3].v, 1); - out[4].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r1_2 , s[3].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r3_2 , s[1].v), _mm_mul_epu32(r[4].v, s[0].v))))); - out[5].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[5].v), _mm_add_epi64(_mm_mul_epu32(r[1].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[3].v), _mm_add_epi64(_mm_mul_epu32(r[3].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[1].v), _mm_mul_epu32(r[5].v, s[0].v)))))); - r5_2 = _mm_slli_epi32(r[5].v, 1); - out[6].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[6].v), _mm_add_epi64(_mm_mul_epu32(r1_2 , s[5].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r3_2 , s[3].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r5_2 , s[1].v), _mm_mul_epu32(r[6].v, s[0].v))))))); - out[7].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[7].v), _mm_add_epi64(_mm_mul_epu32(r[1].v, s[6].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[5].v), _mm_add_epi64(_mm_mul_epu32(r[3].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[3].v), _mm_add_epi64(_mm_mul_epu32(r[5].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r[6].v, s[1].v), _mm_mul_epu32(r[7].v , s[0].v)))))))); - r7_2 = _mm_slli_epi32(r[7].v, 1); - out[8].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[8].v), _mm_add_epi64(_mm_mul_epu32(r1_2 , s[7].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[6].v), _mm_add_epi64(_mm_mul_epu32(r3_2 , s[5].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r5_2 , s[3].v), _mm_add_epi64(_mm_mul_epu32(r[6].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r7_2 , s[1].v), _mm_mul_epu32(r[8].v, s[0].v))))))))); - out[9].v = _mm_add_epi64(_mm_mul_epu32(r[0].v, s[9].v), _mm_add_epi64(_mm_mul_epu32(r[1].v, s[8].v), _mm_add_epi64(_mm_mul_epu32(r[2].v, s[7].v), _mm_add_epi64(_mm_mul_epu32(r[3].v, s[6].v), _mm_add_epi64(_mm_mul_epu32(r[4].v, s[5].v), _mm_add_epi64(_mm_mul_epu32(r[5].v, s[4].v), _mm_add_epi64(_mm_mul_epu32(r[6].v, s[3].v), _mm_add_epi64(_mm_mul_epu32(r[7].v, s[2].v), _mm_add_epi64(_mm_mul_epu32(r[8].v, s[1].v), _mm_mul_epu32(r[9].v, s[0].v)))))))))); - - r1 = _mm_mul_epu32(r[1].v, packednineteen.v); - r2 = _mm_mul_epu32(r[2].v, packednineteen.v); - r1_2 = _mm_slli_epi32(r1, 1); - r3 = _mm_mul_epu32(r[3].v, packednineteen.v); - r4 = _mm_mul_epu32(r[4].v, packednineteen.v); - r3_2 = _mm_slli_epi32(r3, 1); - r5 = _mm_mul_epu32(r[5].v, packednineteen.v); - r6 = _mm_mul_epu32(r[6].v, packednineteen.v); - r5_2 = _mm_slli_epi32(r5, 1); - r7 = _mm_mul_epu32(r[7].v, packednineteen.v); - r8 = _mm_mul_epu32(r[8].v, packednineteen.v); - r7_2 = _mm_slli_epi32(r7, 1); - r9 = _mm_mul_epu32(r[9].v, packednineteen.v); - r9_2 = _mm_slli_epi32(r9, 1); - - out[0].v = _mm_add_epi64(out[0].v, _mm_add_epi64(_mm_mul_epu32(r9_2, s[1].v), _mm_add_epi64(_mm_mul_epu32(r8, s[2].v), _mm_add_epi64(_mm_mul_epu32(r7_2, s[3].v), _mm_add_epi64(_mm_mul_epu32(r6, s[4].v), _mm_add_epi64(_mm_mul_epu32(r5_2, s[5].v), _mm_add_epi64(_mm_mul_epu32(r4, s[6].v), _mm_add_epi64(_mm_mul_epu32(r3_2, s[7].v), _mm_add_epi64(_mm_mul_epu32(r2, s[8].v), _mm_mul_epu32(r1_2, s[9].v)))))))))); - out[1].v = _mm_add_epi64(out[1].v, _mm_add_epi64(_mm_mul_epu32(r9 , s[2].v), _mm_add_epi64(_mm_mul_epu32(r8, s[3].v), _mm_add_epi64(_mm_mul_epu32(r7 , s[4].v), _mm_add_epi64(_mm_mul_epu32(r6, s[5].v), _mm_add_epi64(_mm_mul_epu32(r5 , s[6].v), _mm_add_epi64(_mm_mul_epu32(r4, s[7].v), _mm_add_epi64(_mm_mul_epu32(r3 , s[8].v), _mm_mul_epu32(r2, s[9].v))))))))); - out[2].v = _mm_add_epi64(out[2].v, _mm_add_epi64(_mm_mul_epu32(r9_2, s[3].v), _mm_add_epi64(_mm_mul_epu32(r8, s[4].v), _mm_add_epi64(_mm_mul_epu32(r7_2, s[5].v), _mm_add_epi64(_mm_mul_epu32(r6, s[6].v), _mm_add_epi64(_mm_mul_epu32(r5_2, s[7].v), _mm_add_epi64(_mm_mul_epu32(r4, s[8].v), _mm_mul_epu32(r3_2, s[9].v)))))))); - out[3].v = _mm_add_epi64(out[3].v, _mm_add_epi64(_mm_mul_epu32(r9 , s[4].v), _mm_add_epi64(_mm_mul_epu32(r8, s[5].v), _mm_add_epi64(_mm_mul_epu32(r7 , s[6].v), _mm_add_epi64(_mm_mul_epu32(r6, s[7].v), _mm_add_epi64(_mm_mul_epu32(r5 , s[8].v), _mm_mul_epu32(r4, s[9].v))))))); - out[4].v = _mm_add_epi64(out[4].v, _mm_add_epi64(_mm_mul_epu32(r9_2, s[5].v), _mm_add_epi64(_mm_mul_epu32(r8, s[6].v), _mm_add_epi64(_mm_mul_epu32(r7_2, s[7].v), _mm_add_epi64(_mm_mul_epu32(r6, s[8].v), _mm_mul_epu32(r5_2, s[9].v)))))); - out[5].v = _mm_add_epi64(out[5].v, _mm_add_epi64(_mm_mul_epu32(r9 , s[6].v), _mm_add_epi64(_mm_mul_epu32(r8, s[7].v), _mm_add_epi64(_mm_mul_epu32(r7 , s[8].v), _mm_mul_epu32(r6, s[9].v))))); - out[6].v = _mm_add_epi64(out[6].v, _mm_add_epi64(_mm_mul_epu32(r9_2, s[7].v), _mm_add_epi64(_mm_mul_epu32(r8, s[8].v), _mm_mul_epu32(r7_2, s[9].v)))); - out[7].v = _mm_add_epi64(out[7].v, _mm_add_epi64(_mm_mul_epu32(r9 , s[8].v), _mm_mul_epu32(r8, s[9].v))); - out[8].v = _mm_add_epi64(out[8].v, _mm_mul_epu32(r9_2, s[9].v)); - - c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); - c1 = _mm_srli_epi64(out[1].v, 25); c2 = _mm_srli_epi64(out[5].v, 25); out[1].v = _mm_and_si128(out[1].v, packedmask25.v); out[5].v = _mm_and_si128(out[5].v, packedmask25.v); out[2].v = _mm_add_epi64(out[2].v, c1); out[6].v = _mm_add_epi64(out[6].v, c2); - c1 = _mm_srli_epi64(out[2].v, 26); c2 = _mm_srli_epi64(out[6].v, 26); out[2].v = _mm_and_si128(out[2].v, packedmask26.v); out[6].v = _mm_and_si128(out[6].v, packedmask26.v); out[3].v = _mm_add_epi64(out[3].v, c1); out[7].v = _mm_add_epi64(out[7].v, c2); - c1 = _mm_srli_epi64(out[3].v, 25); c2 = _mm_srli_epi64(out[7].v, 25); out[3].v = _mm_and_si128(out[3].v, packedmask25.v); out[7].v = _mm_and_si128(out[7].v, packedmask25.v); out[4].v = _mm_add_epi64(out[4].v, c1); out[8].v = _mm_add_epi64(out[8].v, c2); - c2 = _mm_srli_epi64(out[8].v, 26); out[8].v = _mm_and_si128(out[8].v, packedmask26.v); out[9].v = _mm_add_epi64(out[9].v, c2); - c2 = _mm_srli_epi64(out[9].v, 25); out[9].v = _mm_and_si128(out[9].v, packedmask25.v); out[0].v = _mm_add_epi64(out[0].v, _mm_mul_epu32(c2, packednineteen.v)); - c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); -} - -DONNA_INLINE static void -curve25519_square_packed64(packedelem64 *out, const packedelem64 *r) { - xmmi r0,r1,r2,r3; - xmmi r1_2,r3_2,r4_2,r5_2,r6_2,r7_2; - xmmi d5,d6,d7,d8,d9; - xmmi c1,c2; - - r0 = r[0].v; - r1 = r[1].v; - r2 = r[2].v; - r3 = r[3].v; - - out[0].v = _mm_mul_epu32(r0, r0); - r0 = _mm_slli_epi32(r0, 1); - out[1].v = _mm_mul_epu32(r0, r1); - r1_2 = _mm_slli_epi32(r1, 1); - out[2].v = _mm_add_epi64(_mm_mul_epu32(r0, r2 ), _mm_mul_epu32(r1, r1_2)); - r1 = r1_2; - out[3].v = _mm_add_epi64(_mm_mul_epu32(r0, r3 ), _mm_mul_epu32(r1, r2 )); - r3_2 = _mm_slli_epi32(r3, 1); - out[4].v = _mm_add_epi64(_mm_mul_epu32(r0, r[4].v), _mm_add_epi64(_mm_mul_epu32(r1, r3_2 ), _mm_mul_epu32(r2, r2))); - r2 = _mm_slli_epi32(r2, 1); - out[5].v = _mm_add_epi64(_mm_mul_epu32(r0, r[5].v), _mm_add_epi64(_mm_mul_epu32(r1, r[4].v), _mm_mul_epu32(r2, r3))); - r5_2 = _mm_slli_epi32(r[5].v, 1); - out[6].v = _mm_add_epi64(_mm_mul_epu32(r0, r[6].v), _mm_add_epi64(_mm_mul_epu32(r1, r5_2 ), _mm_add_epi64(_mm_mul_epu32(r2, r[4].v), _mm_mul_epu32(r3, r3_2 )))); - r3 = r3_2; - out[7].v = _mm_add_epi64(_mm_mul_epu32(r0, r[7].v), _mm_add_epi64(_mm_mul_epu32(r1, r[6].v), _mm_add_epi64(_mm_mul_epu32(r2, r[5].v), _mm_mul_epu32(r3, r[4].v)))); - r7_2 = _mm_slli_epi32(r[7].v, 1); - out[8].v = _mm_add_epi64(_mm_mul_epu32(r0, r[8].v), _mm_add_epi64(_mm_mul_epu32(r1, r7_2 ), _mm_add_epi64(_mm_mul_epu32(r2, r[6].v), _mm_add_epi64(_mm_mul_epu32(r3, r5_2 ), _mm_mul_epu32(r[4].v, r[4].v))))); - out[9].v = _mm_add_epi64(_mm_mul_epu32(r0, r[9].v), _mm_add_epi64(_mm_mul_epu32(r1, r[8].v), _mm_add_epi64(_mm_mul_epu32(r2, r[7].v), _mm_add_epi64(_mm_mul_epu32(r3, r[6].v), _mm_mul_epu32(r[4].v, r5_2 ))))); - - d5 = _mm_mul_epu32(r[5].v, packedthirtyeight.v); - d6 = _mm_mul_epu32(r[6].v, packednineteen.v); - d7 = _mm_mul_epu32(r[7].v, packedthirtyeight.v); - d8 = _mm_mul_epu32(r[8].v, packednineteen.v); - d9 = _mm_mul_epu32(r[9].v, packedthirtyeight.v); - - r4_2 = _mm_slli_epi32(r[4].v, 1); - r6_2 = _mm_slli_epi32(r[6].v, 1); - out[0].v = _mm_add_epi64(out[0].v, _mm_add_epi64(_mm_mul_epu32(d9, r1 ), _mm_add_epi64(_mm_mul_epu32(d8, r2 ), _mm_add_epi64(_mm_mul_epu32(d7, r3 ), _mm_add_epi64(_mm_mul_epu32(d6, r4_2), _mm_mul_epu32(d5, r[5].v)))))); - out[1].v = _mm_add_epi64(out[1].v, _mm_add_epi64(_mm_mul_epu32(d9, _mm_srli_epi32(r2, 1)), _mm_add_epi64(_mm_mul_epu32(d8, r3 ), _mm_add_epi64(_mm_mul_epu32(d7, r[4].v), _mm_mul_epu32(d6, r5_2 ))))); - out[2].v = _mm_add_epi64(out[2].v, _mm_add_epi64(_mm_mul_epu32(d9, r3 ), _mm_add_epi64(_mm_mul_epu32(d8, r4_2), _mm_add_epi64(_mm_mul_epu32(d7, r5_2 ), _mm_mul_epu32(d6, r[6].v))))); - out[3].v = _mm_add_epi64(out[3].v, _mm_add_epi64(_mm_mul_epu32(d9, r[4].v ), _mm_add_epi64(_mm_mul_epu32(d8, r5_2), _mm_mul_epu32(d7, r[6].v)))); - out[4].v = _mm_add_epi64(out[4].v, _mm_add_epi64(_mm_mul_epu32(d9, r5_2 ), _mm_add_epi64(_mm_mul_epu32(d8, r6_2), _mm_mul_epu32(d7, r[7].v)))); - out[5].v = _mm_add_epi64(out[5].v, _mm_add_epi64(_mm_mul_epu32(d9, r[6].v ), _mm_mul_epu32(d8, r7_2 ))); - out[6].v = _mm_add_epi64(out[6].v, _mm_add_epi64(_mm_mul_epu32(d9, r7_2 ), _mm_mul_epu32(d8, r[8].v))); - out[7].v = _mm_add_epi64(out[7].v, _mm_mul_epu32(d9, r[8].v)); - out[8].v = _mm_add_epi64(out[8].v, _mm_mul_epu32(d9, r[9].v)); - - c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); - c1 = _mm_srli_epi64(out[1].v, 25); c2 = _mm_srli_epi64(out[5].v, 25); out[1].v = _mm_and_si128(out[1].v, packedmask25.v); out[5].v = _mm_and_si128(out[5].v, packedmask25.v); out[2].v = _mm_add_epi64(out[2].v, c1); out[6].v = _mm_add_epi64(out[6].v, c2); - c1 = _mm_srli_epi64(out[2].v, 26); c2 = _mm_srli_epi64(out[6].v, 26); out[2].v = _mm_and_si128(out[2].v, packedmask26.v); out[6].v = _mm_and_si128(out[6].v, packedmask26.v); out[3].v = _mm_add_epi64(out[3].v, c1); out[7].v = _mm_add_epi64(out[7].v, c2); - c1 = _mm_srli_epi64(out[3].v, 25); c2 = _mm_srli_epi64(out[7].v, 25); out[3].v = _mm_and_si128(out[3].v, packedmask25.v); out[7].v = _mm_and_si128(out[7].v, packedmask25.v); out[4].v = _mm_add_epi64(out[4].v, c1); out[8].v = _mm_add_epi64(out[8].v, c2); - c2 = _mm_srli_epi64(out[8].v, 26); out[8].v = _mm_and_si128(out[8].v, packedmask26.v); out[9].v = _mm_add_epi64(out[9].v, c2); - c2 = _mm_srli_epi64(out[9].v, 25); out[9].v = _mm_and_si128(out[9].v, packedmask25.v); out[0].v = _mm_add_epi64(out[0].v, _mm_mul_epu32(c2, packednineteen.v)); - c1 = _mm_srli_epi64(out[0].v, 26); c2 = _mm_srli_epi64(out[4].v, 26); out[0].v = _mm_and_si128(out[0].v, packedmask26.v); out[4].v = _mm_and_si128(out[4].v, packedmask26.v); out[1].v = _mm_add_epi64(out[1].v, c1); out[5].v = _mm_add_epi64(out[5].v, c2); -} - - -/* Take a little-endian, 32-byte number and expand it into polynomial form */ -static void -curve25519_expand(bignum25519 out, const unsigned char in[32]) { - uint32_t x0,x1,x2,x3,x4,x5,x6,x7; - - x0 = *(uint32_t *)(in + 0); - x1 = *(uint32_t *)(in + 4); - x2 = *(uint32_t *)(in + 8); - x3 = *(uint32_t *)(in + 12); - x4 = *(uint32_t *)(in + 16); - x5 = *(uint32_t *)(in + 20); - x6 = *(uint32_t *)(in + 24); - x7 = *(uint32_t *)(in + 28); - - out[0] = ( x0 ) & 0x3ffffff; - out[1] = ((((uint64_t)x1 << 32) | x0) >> 26) & 0x1ffffff; - out[2] = ((((uint64_t)x2 << 32) | x1) >> 19) & 0x3ffffff; - out[3] = ((((uint64_t)x3 << 32) | x2) >> 13) & 0x1ffffff; - out[4] = (( x3) >> 6) & 0x3ffffff; - out[5] = ( x4 ) & 0x1ffffff; - out[6] = ((((uint64_t)x5 << 32) | x4) >> 25) & 0x3ffffff; - out[7] = ((((uint64_t)x6 << 32) | x5) >> 19) & 0x1ffffff; - out[8] = ((((uint64_t)x7 << 32) | x6) >> 12) & 0x3ffffff; - out[9] = (( x7) >> 6) & 0x1ffffff; - out[10] = 0; - out[11] = 0; -} - -/* Take a fully reduced polynomial form number and contract it into a - * little-endian, 32-byte array - */ -static void -curve25519_contract(unsigned char out[32], const bignum25519 in) { - bignum25519 ALIGN(16) f; - curve25519_copy(f, in); - - #define carry_pass() \ - f[1] += f[0] >> 26; f[0] &= 0x3ffffff; \ - f[2] += f[1] >> 25; f[1] &= 0x1ffffff; \ - f[3] += f[2] >> 26; f[2] &= 0x3ffffff; \ - f[4] += f[3] >> 25; f[3] &= 0x1ffffff; \ - f[5] += f[4] >> 26; f[4] &= 0x3ffffff; \ - f[6] += f[5] >> 25; f[5] &= 0x1ffffff; \ - f[7] += f[6] >> 26; f[6] &= 0x3ffffff; \ - f[8] += f[7] >> 25; f[7] &= 0x1ffffff; \ - f[9] += f[8] >> 26; f[8] &= 0x3ffffff; - - #define carry_pass_full() \ - carry_pass() \ - f[0] += 19 * (f[9] >> 25); f[9] &= 0x1ffffff; - - #define carry_pass_final() \ - carry_pass() \ - f[9] &= 0x1ffffff; - - carry_pass_full() - carry_pass_full() - - /* now t is between 0 and 2^255-1, properly carried. */ - /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ - f[0] += 19; - carry_pass_full() - - /* now between 19 and 2^255-1 in both cases, and offset by 19. */ - f[0] += (1 << 26) - 19; - f[1] += (1 << 25) - 1; - f[2] += (1 << 26) - 1; - f[3] += (1 << 25) - 1; - f[4] += (1 << 26) - 1; - f[5] += (1 << 25) - 1; - f[6] += (1 << 26) - 1; - f[7] += (1 << 25) - 1; - f[8] += (1 << 26) - 1; - f[9] += (1 << 25) - 1; - - /* now between 2^255 and 2^256-20, and offset by 2^255. */ - carry_pass_final() - - #undef carry_pass - #undef carry_full - #undef carry_final - - f[1] <<= 2; - f[2] <<= 3; - f[3] <<= 5; - f[4] <<= 6; - f[6] <<= 1; - f[7] <<= 3; - f[8] <<= 4; - f[9] <<= 6; - - #define F(i, s) \ - out[s+0] |= (unsigned char )(f[i] & 0xff); \ - out[s+1] = (unsigned char )((f[i] >> 8) & 0xff); \ - out[s+2] = (unsigned char )((f[i] >> 16) & 0xff); \ - out[s+3] = (unsigned char )((f[i] >> 24) & 0xff); - - out[0] = 0; - out[16] = 0; - F(0,0); - F(1,3); - F(2,6); - F(3,9); - F(4,12); - F(5,16); - F(6,19); - F(7,22); - F(8,25); - F(9,28); - #undef F -} - -/* if (iswap) swap(a, b) */ -DONNA_INLINE static void -curve25519_swap_conditional(bignum25519 a, bignum25519 b, uint32_t iswap) { - const uint32_t swap = (uint32_t)(-(int32_t)iswap); - xmmi a0,a1,a2,b0,b1,b2,x0,x1,x2; - xmmi mask = _mm_cvtsi32_si128(swap); - mask = _mm_shuffle_epi32(mask, 0); - a0 = _mm_load_si128((xmmi *)a + 0); - a1 = _mm_load_si128((xmmi *)a + 1); - b0 = _mm_load_si128((xmmi *)b + 0); - b1 = _mm_load_si128((xmmi *)b + 1); - b0 = _mm_xor_si128(a0, b0); - b1 = _mm_xor_si128(a1, b1); - x0 = _mm_and_si128(b0, mask); - x1 = _mm_and_si128(b1, mask); - x0 = _mm_xor_si128(x0, a0); - x1 = _mm_xor_si128(x1, a1); - a0 = _mm_xor_si128(x0, b0); - a1 = _mm_xor_si128(x1, b1); - _mm_store_si128((xmmi *)a + 0, x0); - _mm_store_si128((xmmi *)a + 1, x1); - _mm_store_si128((xmmi *)b + 0, a0); - _mm_store_si128((xmmi *)b + 1, a1); - - a2 = _mm_load_si128((xmmi *)a + 2); - b2 = _mm_load_si128((xmmi *)b + 2); - b2 = _mm_xor_si128(a2, b2); - x2 = _mm_and_si128(b2, mask); - x2 = _mm_xor_si128(x2, a2); - a2 = _mm_xor_si128(x2, b2); - _mm_store_si128((xmmi *)b + 2, a2); - _mm_store_si128((xmmi *)a + 2, x2); -} - -/* out = (flag) ? out : in */ -DONNA_INLINE static void -curve25519_move_conditional_bytes(uint8_t out[96], const uint8_t in[96], uint32_t flag) { - xmmi a0,a1,a2,a3,a4,a5,b0,b1,b2,b3,b4,b5; - const uint32_t nb = flag - 1; - xmmi masknb = _mm_shuffle_epi32(_mm_cvtsi32_si128(nb),0); - a0 = _mm_load_si128((xmmi *)in + 0); - a1 = _mm_load_si128((xmmi *)in + 1); - a2 = _mm_load_si128((xmmi *)in + 2); - b0 = _mm_load_si128((xmmi *)out + 0); - b1 = _mm_load_si128((xmmi *)out + 1); - b2 = _mm_load_si128((xmmi *)out + 2); - a0 = _mm_andnot_si128(masknb, a0); - a1 = _mm_andnot_si128(masknb, a1); - a2 = _mm_andnot_si128(masknb, a2); - b0 = _mm_and_si128(masknb, b0); - b1 = _mm_and_si128(masknb, b1); - b2 = _mm_and_si128(masknb, b2); - a0 = _mm_or_si128(a0, b0); - a1 = _mm_or_si128(a1, b1); - a2 = _mm_or_si128(a2, b2); - _mm_store_si128((xmmi*)out + 0, a0); - _mm_store_si128((xmmi*)out + 1, a1); - _mm_store_si128((xmmi*)out + 2, a2); - - a3 = _mm_load_si128((xmmi *)in + 3); - a4 = _mm_load_si128((xmmi *)in + 4); - a5 = _mm_load_si128((xmmi *)in + 5); - b3 = _mm_load_si128((xmmi *)out + 3); - b4 = _mm_load_si128((xmmi *)out + 4); - b5 = _mm_load_si128((xmmi *)out + 5); - a3 = _mm_andnot_si128(masknb, a3); - a4 = _mm_andnot_si128(masknb, a4); - a5 = _mm_andnot_si128(masknb, a5); - b3 = _mm_and_si128(masknb, b3); - b4 = _mm_and_si128(masknb, b4); - b5 = _mm_and_si128(masknb, b5); - a3 = _mm_or_si128(a3, b3); - a4 = _mm_or_si128(a4, b4); - a5 = _mm_or_si128(a5, b5); - _mm_store_si128((xmmi*)out + 3, a3); - _mm_store_si128((xmmi*)out + 4, a4); - _mm_store_si128((xmmi*)out + 5, a5); -} - diff --git a/external/ed25519-donna/ed25519-donna-32bit-sse2.h b/external/ed25519-donna/ed25519-donna-32bit-sse2.h deleted file mode 100644 index db04a13d3f..0000000000 --- a/external/ed25519-donna/ed25519-donna-32bit-sse2.h +++ /dev/null @@ -1,513 +0,0 @@ -#if defined(ED25519_GCC_32BIT_SSE_CHOOSE) - -#define HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS - -DONNA_NOINLINE static void -ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) { - int32_t breg = (int32_t)b; - uint32_t sign = (uint32_t)breg >> 31; - uint32_t mask = ~(sign - 1); - uint32_t u = (breg + mask) ^ mask; - - __asm__ __volatile__ ( - /* ysubx+xaddy */ - "movl %0, %%eax ;\n" - "movd %%eax, %%xmm6 ;\n" - "pshufd $0x00, %%xmm6, %%xmm6 ;\n" - "pxor %%xmm0, %%xmm0 ;\n" - "pxor %%xmm1, %%xmm1 ;\n" - "pxor %%xmm2, %%xmm2 ;\n" - "pxor %%xmm3, %%xmm3 ;\n" - - /* 0 */ - "movl $0, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movl $1, %%ecx ;\n" - "movd %%ecx, %%xmm4 ;\n" - "pxor %%xmm5, %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* 1 */ - "movl $1, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 0(%1), %%xmm4 ;\n" - "movdqa 16(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "movdqa 32(%1), %%xmm4 ;\n" - "movdqa 48(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* 2 */ - "movl $2, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 96(%1), %%xmm4 ;\n" - "movdqa 112(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "movdqa 128(%1), %%xmm4 ;\n" - "movdqa 144(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* 3 */ - "movl $3, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 192(%1), %%xmm4 ;\n" - "movdqa 208(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "movdqa 224(%1), %%xmm4 ;\n" - "movdqa 240(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* 4 */ - "movl $4, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 288(%1), %%xmm4 ;\n" - "movdqa 304(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "movdqa 320(%1), %%xmm4 ;\n" - "movdqa 336(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* 5 */ - "movl $5, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 384(%1), %%xmm4 ;\n" - "movdqa 400(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "movdqa 416(%1), %%xmm4 ;\n" - "movdqa 432(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* 6 */ - "movl $6, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 480(%1), %%xmm4 ;\n" - "movdqa 496(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "movdqa 512(%1), %%xmm4 ;\n" - "movdqa 528(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* 7 */ - "movl $7, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 576(%1), %%xmm4 ;\n" - "movdqa 592(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "movdqa 608(%1), %%xmm4 ;\n" - "movdqa 624(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* 8 */ - "movl $8, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 672(%1), %%xmm4 ;\n" - "movdqa 688(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm0 ;\n" - "por %%xmm5, %%xmm1 ;\n" - "movdqa 704(%1), %%xmm4 ;\n" - "movdqa 720(%1), %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "por %%xmm4, %%xmm2 ;\n" - "por %%xmm5, %%xmm3 ;\n" - - /* conditional swap based on sign */ - "movl %3, %%ecx ;\n" - "movl %2, %%eax ;\n" - "xorl $1, %%ecx ;\n" - "movd %%ecx, %%xmm6 ;\n" - "pxor %%xmm7, %%xmm7 ;\n" - "pshufd $0x00, %%xmm6, %%xmm6 ;\n" - "pxor %%xmm0, %%xmm2 ;\n" - "pxor %%xmm1, %%xmm3 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa %%xmm2, %%xmm4 ;\n" - "movdqa %%xmm3, %%xmm5 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "pand %%xmm7, %%xmm5 ;\n" - "pxor %%xmm4, %%xmm0 ;\n" - "pxor %%xmm5, %%xmm1 ;\n" - "pxor %%xmm0, %%xmm2 ;\n" - "pxor %%xmm1, %%xmm3 ;\n" - - /* store ysubx */ - "movd %%xmm0, %%ecx ;\n" - "movl %%ecx, %%edx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 0(%%eax) ;\n" - "movd %%xmm0, %%ecx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "shrdl $26, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 4(%%eax) ;\n" - "movd %%xmm0, %%edx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "shrdl $19, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 8(%%eax) ;\n" - "movd %%xmm0, %%ecx ;\n" - "shrdl $13, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 12(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrl $6, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 16(%%eax) ;\n" - "movl %%edx, %%ecx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 20(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrdl $25, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 24(%%eax) ;\n" - "movd %%xmm1, %%ecx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrdl $19, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 28(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "shrdl $12, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 32(%%eax) ;\n" - "shrl $6, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "xorl %%ecx, %%ecx ;\n" - "movl %%edx, 36(%%eax) ;\n" - "movl %%ecx, 40(%%eax) ;\n" - "movl %%ecx, 44(%%eax) ;\n" - - /* store xaddy */ - "addl $48, %%eax ;\n" - "movdqa %%xmm2, %%xmm0 ;\n" - "movdqa %%xmm3, %%xmm1 ;\n" - "movd %%xmm0, %%ecx ;\n" - "movl %%ecx, %%edx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 0(%%eax) ;\n" - "movd %%xmm0, %%ecx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "shrdl $26, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 4(%%eax) ;\n" - "movd %%xmm0, %%edx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "shrdl $19, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 8(%%eax) ;\n" - "movd %%xmm0, %%ecx ;\n" - "shrdl $13, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 12(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrl $6, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 16(%%eax) ;\n" - "movl %%edx, %%ecx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 20(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrdl $25, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 24(%%eax) ;\n" - "movd %%xmm1, %%ecx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrdl $19, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 28(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "shrdl $12, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 32(%%eax) ;\n" - "shrl $6, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "xorl %%ecx, %%ecx ;\n" - "movl %%edx, 36(%%eax) ;\n" - "movl %%ecx, 40(%%eax) ;\n" - "movl %%ecx, 44(%%eax) ;\n" - - /* t2d */ - "movl %0, %%eax ;\n" - "movd %%eax, %%xmm6 ;\n" - "pshufd $0x00, %%xmm6, %%xmm6 ;\n" - "pxor %%xmm0, %%xmm0 ;\n" - "pxor %%xmm1, %%xmm1 ;\n" - - /* 0 */ - "movl $0, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "pxor %%xmm0, %%xmm0 ;\n" - "pxor %%xmm1, %%xmm1 ;\n" - - /* 1 */ - "movl $1, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 64(%1), %%xmm3 ;\n" - "movdqa 80(%1), %%xmm4 ;\n" - "pand %%xmm7, %%xmm3 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "por %%xmm3, %%xmm0 ;\n" - "por %%xmm4, %%xmm1 ;\n" - - /* 2 */ - "movl $2, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 160(%1), %%xmm3 ;\n" - "movdqa 176(%1), %%xmm4 ;\n" - "pand %%xmm7, %%xmm3 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "por %%xmm3, %%xmm0 ;\n" - "por %%xmm4, %%xmm1 ;\n" - - /* 3 */ - "movl $3, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 256(%1), %%xmm3 ;\n" - "movdqa 272(%1), %%xmm4 ;\n" - "pand %%xmm7, %%xmm3 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "por %%xmm3, %%xmm0 ;\n" - "por %%xmm4, %%xmm1 ;\n" - - /* 4 */ - "movl $4, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 352(%1), %%xmm3 ;\n" - "movdqa 368(%1), %%xmm4 ;\n" - "pand %%xmm7, %%xmm3 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "por %%xmm3, %%xmm0 ;\n" - "por %%xmm4, %%xmm1 ;\n" - - /* 5 */ - "movl $5, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 448(%1), %%xmm3 ;\n" - "movdqa 464(%1), %%xmm4 ;\n" - "pand %%xmm7, %%xmm3 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "por %%xmm3, %%xmm0 ;\n" - "por %%xmm4, %%xmm1 ;\n" - - /* 6 */ - "movl $6, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 544(%1), %%xmm3 ;\n" - "movdqa 560(%1), %%xmm4 ;\n" - "pand %%xmm7, %%xmm3 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "por %%xmm3, %%xmm0 ;\n" - "por %%xmm4, %%xmm1 ;\n" - - /* 7 */ - "movl $7, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 640(%1), %%xmm3 ;\n" - "movdqa 656(%1), %%xmm4 ;\n" - "pand %%xmm7, %%xmm3 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "por %%xmm3, %%xmm0 ;\n" - "por %%xmm4, %%xmm1 ;\n" - - /* 8 */ - "movl $8, %%eax ;\n" - "movd %%eax, %%xmm7 ;\n" - "pshufd $0x00, %%xmm7, %%xmm7 ;\n" - "pcmpeqd %%xmm6, %%xmm7 ;\n" - "movdqa 736(%1), %%xmm3 ;\n" - "movdqa 752(%1), %%xmm4 ;\n" - "pand %%xmm7, %%xmm3 ;\n" - "pand %%xmm7, %%xmm4 ;\n" - "por %%xmm3, %%xmm0 ;\n" - "por %%xmm4, %%xmm1 ;\n" - - /* store t2d */ - "movl %2, %%eax ;\n" - "addl $96, %%eax ;\n" - "movd %%xmm0, %%ecx ;\n" - "movl %%ecx, %%edx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 0(%%eax) ;\n" - "movd %%xmm0, %%ecx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "shrdl $26, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 4(%%eax) ;\n" - "movd %%xmm0, %%edx ;\n" - "pshufd $0x39, %%xmm0, %%xmm0 ;\n" - "shrdl $19, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 8(%%eax) ;\n" - "movd %%xmm0, %%ecx ;\n" - "shrdl $13, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 12(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrl $6, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 16(%%eax) ;\n" - "movl %%edx, %%ecx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 20(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrdl $25, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 24(%%eax) ;\n" - "movd %%xmm1, %%ecx ;\n" - "pshufd $0x39, %%xmm1, %%xmm1 ;\n" - "shrdl $19, %%ecx, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "movl %%edx, 28(%%eax) ;\n" - "movd %%xmm1, %%edx ;\n" - "movd %%xmm1, %%edx ;\n" - "shrdl $12, %%edx, %%ecx ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "movl %%ecx, 32(%%eax) ;\n" - "shrl $6, %%edx ;\n" - "andl $0x1ffffff, %%edx ;\n" - "xorl %%ecx, %%ecx ;\n" - "movl %%edx, 36(%%eax) ;\n" - "movl %%ecx, 40(%%eax) ;\n" - "movl %%ecx, 44(%%eax) ;\n" - "movdqa 0(%%eax), %%xmm0 ;\n" - "movdqa 16(%%eax), %%xmm1 ;\n" - "movdqa 32(%%eax), %%xmm2 ;\n" - - /* conditionally negate t2d */ - - /* set up 2p in to 3/4 */ - "movl $0x7ffffda, %%ecx ;\n" - "movl $0x3fffffe, %%edx ;\n" - "movd %%ecx, %%xmm3 ;\n" - "movd %%edx, %%xmm5 ;\n" - "movl $0x7fffffe, %%ecx ;\n" - "movd %%ecx, %%xmm4 ;\n" - "punpckldq %%xmm5, %%xmm3 ;\n" - "punpckldq %%xmm5, %%xmm4 ;\n" - "punpcklqdq %%xmm4, %%xmm3 ;\n" - "movdqa %%xmm4, %%xmm5 ;\n" - "punpcklqdq %%xmm4, %%xmm4 ;\n" - - /* subtract and conditionally move */ - "movl %3, %%ecx ;\n" - "sub $1, %%ecx ;\n" - "movd %%ecx, %%xmm6 ;\n" - "pshufd $0x00, %%xmm6, %%xmm6 ;\n" - "movdqa %%xmm6, %%xmm7 ;\n" - "psubd %%xmm0, %%xmm3 ;\n" - "psubd %%xmm1, %%xmm4 ;\n" - "psubd %%xmm2, %%xmm5 ;\n" - "pand %%xmm6, %%xmm0 ;\n" - "pand %%xmm6, %%xmm1 ;\n" - "pand %%xmm6, %%xmm2 ;\n" - "pandn %%xmm3, %%xmm6 ;\n" - "movdqa %%xmm7, %%xmm3 ;\n" - "pandn %%xmm4, %%xmm7 ;\n" - "pandn %%xmm5, %%xmm3 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm3, %%xmm2 ;\n" - - /* store */ - "movdqa %%xmm0, 0(%%eax) ;\n" - "movdqa %%xmm1, 16(%%eax) ;\n" - "movdqa %%xmm2, 32(%%eax) ;\n" - : - : "m"(u), "r"(&table[pos * 8]), "m"(t), "m"(sign) /* %0 = u, %1 = table, %2 = t, %3 = sign */ - : "%eax", "%ecx", "%edx", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" - ); -} - -#endif /* defined(ED25519_GCC_32BIT_SSE_CHOOSE) */ - diff --git a/external/ed25519-donna/ed25519-donna-32bit-tables.h b/external/ed25519-donna/ed25519-donna-32bit-tables.h deleted file mode 100644 index c977c26ebc..0000000000 --- a/external/ed25519-donna/ed25519-donna-32bit-tables.h +++ /dev/null @@ -1,61 +0,0 @@ -static const ge25519 ALIGN(16) ge25519_basepoint = { - {0x0325d51a,0x018b5823,0x00f6592a,0x0104a92d,0x01a4b31d,0x01d6dc5c,0x027118fe,0x007fd814,0x013cd6e5,0x0085a4db}, - {0x02666658,0x01999999,0x00cccccc,0x01333333,0x01999999,0x00666666,0x03333333,0x00cccccc,0x02666666,0x01999999}, - {0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}, - {0x01b7dda3,0x01a2ace9,0x025eadbb,0x0003ba8a,0x0083c27e,0x00abe37d,0x01274732,0x00ccacdd,0x00fd78b7,0x019e1d7c} -}; - -/* - d -*/ - -static const bignum25519 ALIGN(16) ge25519_ecd = { - 0x035978a3,0x00d37284,0x03156ebd,0x006a0a0e,0x0001c029,0x0179e898,0x03a03cbb,0x01ce7198,0x02e2b6ff,0x01480db3 -}; - -static const bignum25519 ALIGN(16) ge25519_ec2d = { - 0x02b2f159,0x01a6e509,0x022add7a,0x00d4141d,0x00038052,0x00f3d130,0x03407977,0x019ce331,0x01c56dff,0x00901b67 -}; - -/* - sqrt(-1) -*/ - -static const bignum25519 ALIGN(16) ge25519_sqrtneg1 = { - 0x020ea0b0,0x0186c9d2,0x008f189d,0x0035697f,0x00bd0c60,0x01fbd7a7,0x02804c9e,0x01e16569,0x0004fc1d,0x00ae0c92 -}; - -static const ge25519_niels ALIGN(16) ge25519_niels_sliding_multiples[32] = { - {{0x0340913e,0x000e4175,0x03d673a2,0x002e8a05,0x03f4e67c,0x008f8a09,0x00c21a34,0x004cf4b8,0x01298f81,0x0113f4be},{0x018c3b85,0x0124f1bd,0x01c325f7,0x0037dc60,0x033e4cb7,0x003d42c2,0x01a44c32,0x014ca4e1,0x03a33d4b,0x001f3e74},{0x037aaa68,0x00448161,0x0093d579,0x011e6556,0x009b67a0,0x0143598c,0x01bee5ee,0x00b50b43,0x0289f0c6,0x01bc45ed}}, - {{0x00fcd265,0x0047fa29,0x034faacc,0x01ef2e0d,0x00ef4d4f,0x014bd6bd,0x00f98d10,0x014c5026,0x007555bd,0x00aae456},{0x00ee9730,0x016c2a13,0x017155e4,0x01874432,0x00096a10,0x01016732,0x01a8014f,0x011e9823,0x01b9a80f,0x01e85938},{0x01d0d889,0x01a4cfc3,0x034c4295,0x0110e1ae,0x0162508c,0x00f2db4c,0x0072a2c6,0x0098da2e,0x02f12b9b,0x0168a09a}}, - {{0x0047d6ba,0x0060b0e9,0x0136eff2,0x008a5939,0x03540053,0x0064a087,0x02788e5c,0x00be7c67,0x033eb1b5,0x005529f9},{0x00a5bb33,0x00af1102,0x01a05442,0x001e3af7,0x02354123,0x00bfec44,0x01f5862d,0x00dd7ba3,0x03146e20,0x00a51733},{0x012a8285,0x00f6fc60,0x023f9797,0x003e85ee,0x009c3820,0x01bda72d,0x01b3858d,0x00d35683,0x0296b3bb,0x010eaaf9}}, - {{0x023221b1,0x01cb26aa,0x0074f74d,0x0099ddd1,0x01b28085,0x00192c3a,0x013b27c9,0x00fc13bd,0x01d2e531,0x0075bb75},{0x004ea3bf,0x00973425,0x001a4d63,0x01d59cee,0x01d1c0d4,0x00542e49,0x01294114,0x004fce36,0x029283c9,0x01186fa9},{0x01b8b3a2,0x00db7200,0x00935e30,0x003829f5,0x02cc0d7d,0x0077adf3,0x0220dd2c,0x0014ea53,0x01c6a0f9,0x01ea7eec}}, - {{0x039d8064,0x01885f80,0x00337e6d,0x01b7a902,0x02628206,0x015eb044,0x01e30473,0x0191f2d9,0x011fadc9,0x01270169},{0x02a8632f,0x0199e2a9,0x00d8b365,0x017a8de2,0x02994279,0x0086f5b5,0x0119e4e3,0x01eb39d6,0x0338add7,0x00d2e7b4},{0x0045af1b,0x013a2fe4,0x0245e0d6,0x014538ce,0x038bfe0f,0x01d4cf16,0x037e14c9,0x0160d55e,0x0021b008,0x01cf05c8}}, - {{0x01864348,0x01d6c092,0x0070262b,0x014bb844,0x00fb5acd,0x008deb95,0x003aaab5,0x00eff474,0x00029d5c,0x0062ad66},{0x02802ade,0x01c02122,0x01c4e5f7,0x00781181,0x039767fb,0x01703406,0x0342388b,0x01f5e227,0x022546d8,0x0109d6ab},{0x016089e9,0x00cb317f,0x00949b05,0x01099417,0x000c7ad2,0x011a8622,0x0088ccda,0x01290886,0x022b53df,0x00f71954}}, - {{0x027fbf93,0x01c04ecc,0x01ed6a0d,0x004cdbbb,0x02bbf3af,0x00ad5968,0x01591955,0x0094f3a2,0x02d17602,0x00099e20},{0x02007f6d,0x003088a8,0x03db77ee,0x00d5ade6,0x02fe12ce,0x0107ba07,0x0107097d,0x00482a6f,0x02ec346f,0x008d3f5f},{0x032ea378,0x0028465c,0x028e2a6c,0x018efc6e,0x0090df9a,0x01a7e533,0x039bfc48,0x010c745d,0x03daa097,0x0125ee9b}}, - {{0x028ccf0b,0x00f36191,0x021ac081,0x012154c8,0x034e0a6e,0x01b25192,0x00180403,0x01d7eea1,0x00218d05,0x010ed735},{0x03cfeaa0,0x01b300c4,0x008da499,0x0068c4e1,0x0219230a,0x01f2d4d0,0x02defd60,0x00e565b7,0x017f12de,0x018788a4},{0x03d0b516,0x009d8be6,0x03ddcbb3,0x0071b9fe,0x03ace2bd,0x01d64270,0x032d3ec9,0x01084065,0x0210ae4d,0x01447584}}, - {{0x0020de87,0x00e19211,0x01b68102,0x00b5ac97,0x022873c0,0x01942d25,0x01271394,0x0102073f,0x02fe2482,0x01c69ff9},{0x010e9d81,0x019dbbe5,0x0089f258,0x006e06b8,0x02951883,0x018f1248,0x019b3237,0x00bc7553,0x024ddb85,0x01b4c964},{0x01c8c854,0x0060ae29,0x01406d8e,0x01cff2f9,0x00cff451,0x01778d0c,0x03ac8c41,0x01552e59,0x036559ee,0x011d1b12}}, - {{0x00741147,0x0151b219,0x01092690,0x00e877e6,0x01f4d6bb,0x0072a332,0x01cd3b03,0x00dadff2,0x0097db5e,0x0086598d},{0x01c69a2b,0x01decf1b,0x02c2fa6e,0x013b7c4f,0x037beac8,0x013a16b5,0x028e7bda,0x01f6e8ac,0x01e34fe9,0x01726947},{0x01f10e67,0x003c73de,0x022b7ea2,0x010f32c2,0x03ff776a,0x00142277,0x01d38b88,0x00776138,0x03c60822,0x01201140}}, - {{0x0236d175,0x0008748e,0x03c6476d,0x013f4cdc,0x02eed02a,0x00838a47,0x032e7210,0x018bcbb3,0x00858de4,0x01dc7826},{0x00a37fc7,0x0127b40b,0x01957884,0x011d30ad,0x02816683,0x016e0e23,0x00b76be4,0x012db115,0x02516506,0x0154ce62},{0x00451edf,0x00bd749e,0x03997342,0x01cc2c4c,0x00eb6975,0x01a59508,0x03a516cf,0x00c228ef,0x0168ff5a,0x01697b47}}, - {{0x00527359,0x01783156,0x03afd75c,0x00ce56dc,0x00e4b970,0x001cabe9,0x029e0f6d,0x0188850c,0x0135fefd,0x00066d80},{0x02150e83,0x01448abf,0x02bb0232,0x012bf259,0x033c8268,0x00711e20,0x03fc148f,0x005e0e70,0x017d8bf9,0x0112b2e2},{0x02134b83,0x001a0517,0x0182c3cc,0x00792182,0x0313d799,0x001a3ed7,0x0344547e,0x01f24a0d,0x03de6ad2,0x00543127}}, - {{0x00dca868,0x00618f27,0x015a1709,0x00ddc38a,0x0320fd13,0x0036168d,0x0371ab06,0x01783fc7,0x0391e05f,0x01e29b5d},{0x01471138,0x00fca542,0x00ca31cf,0x01ca7bad,0x0175bfbc,0x01a708ad,0x03bce212,0x01244215,0x0075bb99,0x01acad68},{0x03a0b976,0x01dc12d1,0x011aab17,0x00aba0ba,0x029806cd,0x0142f590,0x018fd8ea,0x01a01545,0x03c4ad55,0x01c971ff}}, - {{0x00d098c0,0x000afdc7,0x006cd230,0x01276af3,0x03f905b2,0x0102994c,0x002eb8a4,0x015cfbeb,0x025f855f,0x01335518},{0x01cf99b2,0x0099c574,0x01a69c88,0x00881510,0x01cd4b54,0x0112109f,0x008abdc5,0x0074647a,0x0277cb1f,0x01e53324},{0x02ac5053,0x01b109b0,0x024b095e,0x016997b3,0x02f26bb6,0x00311021,0x00197885,0x01d0a55a,0x03b6fcc8,0x01c020d5}}, - {{0x02584a34,0x00e7eee0,0x03257a03,0x011e95a3,0x011ead91,0x00536202,0x00b1ce24,0x008516c6,0x03669d6d,0x004ea4a8},{0x00773f01,0x0019c9ce,0x019f6171,0x01d4afde,0x02e33323,0x01ad29b6,0x02ead1dc,0x01ed51a5,0x01851ad0,0x001bbdfa},{0x00577de5,0x00ddc730,0x038b9952,0x00f281ae,0x01d50390,0x0002e071,0x000780ec,0x010d448d,0x01f8a2af,0x00f0a5b7}}, - {{0x031f2541,0x00d34bae,0x0323ff9d,0x003a056d,0x02e25443,0x00a1ad05,0x00d1bee8,0x002f7f8e,0x03007477,0x002a24b1},{0x0114a713,0x01457e76,0x032255d5,0x01cc647f,0x02a4bdef,0x0153d730,0x00118bcf,0x00f755ff,0x013490c7,0x01ea674e},{0x02bda3e8,0x00bb490d,0x00f291ea,0x000abf40,0x01dea321,0x002f9ce0,0x00b2b193,0x00fa54b5,0x0128302f,0x00a19d8b}}, - {{0x022ef5bd,0x01638af3,0x038c6f8a,0x01a33a3d,0x039261b2,0x01bb89b8,0x010bcf9d,0x00cf42a9,0x023d6f17,0x01da1bca},{0x00e35b25,0x000d824f,0x0152e9cf,0x00ed935d,0x020b8460,0x01c7b83f,0x00c969e5,0x01a74198,0x0046a9d9,0x00cbc768},{0x01597c6a,0x0144a99b,0x00a57551,0x0018269c,0x023c464c,0x0009b022,0x00ee39e1,0x0114c7f2,0x038a9ad2,0x01584c17}}, - {{0x03b0c0d5,0x00b30a39,0x038a6ce4,0x01ded83a,0x01c277a6,0x01010a61,0x0346d3eb,0x018d995e,0x02f2c57c,0x000c286b},{0x0092aed1,0x0125e37b,0x027ca201,0x001a6b6b,0x03290f55,0x0047ba48,0x018d916c,0x01a59062,0x013e35d4,0x0002abb1},{0x003ad2aa,0x007ddcc0,0x00c10f76,0x0001590b,0x002cfca6,0x000ed23e,0x00ee4329,0x00900f04,0x01c24065,0x0082fa70}}, - {{0x02025e60,0x003912b8,0x0327041c,0x017e5ee5,0x02c0ecec,0x015a0d1c,0x02b1ce7c,0x0062220b,0x0145067e,0x01a5d931},{0x009673a6,0x00e1f609,0x00927c2a,0x016faa37,0x01650ef0,0x016f63b5,0x03cd40e1,0x003bc38f,0x0361f0ac,0x01d42acc},{0x02f81037,0x008ca0e8,0x017e23d1,0x011debfe,0x01bcbb68,0x002e2563,0x03e8add6,0x000816e5,0x03fb7075,0x0153e5ac}}, - {{0x02b11ecd,0x016bf185,0x008f22ef,0x00e7d2bb,0x0225d92e,0x00ece785,0x00508873,0x017e16f5,0x01fbe85d,0x01e39a0e},{0x01669279,0x017c810a,0x024941f5,0x0023ebeb,0x00eb7688,0x005760f1,0x02ca4146,0x0073cde7,0x0052bb75,0x00f5ffa7},{0x03b8856b,0x00cb7dcd,0x02f14e06,0x001820d0,0x01d74175,0x00e59e22,0x03fba550,0x00484641,0x03350088,0x01c3c9a3}}, - {{0x00dcf355,0x0104481c,0x0022e464,0x01f73fe7,0x00e03325,0x0152b698,0x02ef769a,0x00973663,0x00039b8c,0x0101395b},{0x01805f47,0x019160ec,0x03832cd0,0x008b06eb,0x03d4d717,0x004cb006,0x03a75b8f,0x013b3d30,0x01cfad88,0x01f034d1},{0x0078338a,0x01c7d2e3,0x02bc2b23,0x018b3f05,0x0280d9aa,0x005f3d44,0x0220a95a,0x00eeeb97,0x0362aaec,0x00835d51}}, - {{0x01b9f543,0x013fac4d,0x02ad93ae,0x018ef464,0x0212cdf7,0x01138ba9,0x011583ab,0x019c3d26,0x028790b4,0x00e2e2b6},{0x033bb758,0x01f0dbf1,0x03734bd1,0x0129b1e5,0x02b3950e,0x003bc922,0x01a53ec8,0x018c5532,0x006f3cee,0x00ae3c79},{0x0351f95d,0x0012a737,0x03d596b8,0x017658fe,0x00ace54a,0x008b66da,0x0036c599,0x012a63a2,0x032ceba1,0x00126bac}}, - {{0x03dcfe7e,0x019f4f18,0x01c81aee,0x0044bc2b,0x00827165,0x014f7c13,0x03b430f0,0x00bf96cc,0x020c8d62,0x01471997},{0x01fc7931,0x001f42dd,0x00ba754a,0x005bd339,0x003fbe49,0x016b3930,0x012a159c,0x009f83b0,0x03530f67,0x01e57b85},{0x02ecbd81,0x0096c294,0x01fce4a9,0x017701a5,0x0175047d,0x00ee4a31,0x012686e5,0x008efcd4,0x0349dc54,0x01b3466f}}, - {{0x02179ca3,0x01d86414,0x03f0afd0,0x00305964,0x015c7428,0x0099711e,0x015d5442,0x00c71014,0x01b40b2e,0x01d483cf},{0x01afc386,0x01984859,0x036203ff,0x0045c6a8,0x0020a8aa,0x00990baa,0x03313f10,0x007ceede,0x027429e4,0x017806ce},{0x039357a1,0x0142f8f4,0x0294a7b6,0x00eaccf4,0x0259edb3,0x01311e6e,0x004d326f,0x0130c346,0x01ccef3c,0x01c424b2}}, - {{0x0364918c,0x00148fc0,0x01638a7b,0x01a1fd5b,0x028ad013,0x0081e5a4,0x01a54f33,0x0174e101,0x003d0257,0x003a856c},{0x00051dcf,0x00f62b1d,0x0143d0ad,0x0042adbd,0x000fda90,0x01743ceb,0x0173e5e4,0x017bc749,0x03b7137a,0x0105ce96},{0x00f9218a,0x015b8c7c,0x00e102f8,0x0158d7e2,0x0169a5b8,0x00b2f176,0x018b347a,0x014cfef2,0x0214a4e3,0x017f1595}}, - {{0x006d7ae5,0x0195c371,0x0391e26d,0x0062a7c6,0x003f42ab,0x010dad86,0x024f8198,0x01542b2a,0x0014c454,0x0189c471},{0x0390988e,0x00b8799d,0x02e44912,0x0078e2e6,0x00075654,0x01923eed,0x0040cd72,0x00a37c76,0x0009d466,0x00c8531d},{0x02651770,0x00609d01,0x0286c265,0x0134513c,0x00ee9281,0x005d223c,0x035c760c,0x00679b36,0x0073ecb8,0x016faa50}}, - {{0x02c89be4,0x016fc244,0x02f38c83,0x018beb72,0x02b3ce2c,0x0097b065,0x034f017b,0x01dd957f,0x00148f61,0x00eab357},{0x0343d2f8,0x003398fc,0x011e368e,0x00782a1f,0x00019eea,0x00117b6f,0x0128d0d1,0x01a5e6bb,0x01944f1b,0x012b41e1},{0x03318301,0x018ecd30,0x0104d0b1,0x0038398b,0x03726701,0x019da88c,0x002d9769,0x00a7a681,0x031d9028,0x00ebfc32}}, - {{0x0220405e,0x0171face,0x02d930f8,0x017f6d6a,0x023b8c47,0x0129d5f9,0x02972456,0x00a3a524,0x006f4cd2,0x004439fa},{0x00c53505,0x0190c2fd,0x00507244,0x009930f9,0x01a39270,0x01d327c6,0x0399bc47,0x01cfe13d,0x0332bd99,0x00b33e7d},{0x0203f5e4,0x003627b5,0x00018af8,0x01478581,0x004a2218,0x002e3bb7,0x039384d0,0x0146ea62,0x020b9693,0x0017155f}}, - {{0x03c97e6f,0x00738c47,0x03b5db1f,0x01808fcf,0x01e8fc98,0x01ed25dd,0x01bf5045,0x00eb5c2b,0x0178fe98,0x01b85530},{0x01c20eb0,0x01aeec22,0x030b9eee,0x01b7d07e,0x0187e16f,0x014421fb,0x009fa731,0x0040b6d7,0x00841861,0x00a27fbc},{0x02d69abf,0x0058cdbf,0x0129f9ec,0x013c19ae,0x026c5b93,0x013a7fe7,0x004bb2ba,0x0063226f,0x002a95ca,0x01abefd9}}, - {{0x02f5d2c1,0x00378318,0x03734fb5,0x01258073,0x0263f0f6,0x01ad70e0,0x01b56d06,0x01188fbd,0x011b9503,0x0036d2e1},{0x0113a8cc,0x01541c3e,0x02ac2bbc,0x01d95867,0x01f47459,0x00ead489,0x00ab5b48,0x01db3b45,0x00edb801,0x004b024f},{0x00b8190f,0x011fe4c2,0x00621f82,0x010508d7,0x001a5a76,0x00c7d7fd,0x03aab96d,0x019cd9dc,0x019c6635,0x00ceaa1e}}, - {{0x01085cf2,0x01fd47af,0x03e3f5e1,0x004b3e99,0x01e3d46a,0x0060033c,0x015ff0a8,0x0150cdd8,0x029e8e21,0x008cf1bc},{0x00156cb1,0x003d623f,0x01a4f069,0x00d8d053,0x01b68aea,0x01ca5ab6,0x0316ae43,0x0134dc44,0x001c8d58,0x0084b343},{0x0318c781,0x0135441f,0x03a51a5e,0x019293f4,0x0048bb37,0x013d3341,0x0143151e,0x019c74e1,0x00911914,0x0076ddde}}, - {{0x006bc26f,0x00d48e5f,0x00227bbe,0x00629ea8,0x01ea5f8b,0x0179a330,0x027a1d5f,0x01bf8f8e,0x02d26e2a,0x00c6b65e},{0x01701ab6,0x0051da77,0x01b4b667,0x00a0ce7c,0x038ae37b,0x012ac852,0x03a0b0fe,0x0097c2bb,0x00a017d2,0x01eb8b2a},{0x0120b962,0x0005fb42,0x0353b6fd,0x0061f8ce,0x007a1463,0x01560a64,0x00e0a792,0x01907c92,0x013a6622,0x007b47f1}} -}; diff --git a/external/ed25519-donna/ed25519-donna-64bit-sse2.h b/external/ed25519-donna/ed25519-donna-64bit-sse2.h deleted file mode 100644 index ca08651d67..0000000000 --- a/external/ed25519-donna/ed25519-donna-64bit-sse2.h +++ /dev/null @@ -1,436 +0,0 @@ -#if defined(ED25519_GCC_64BIT_SSE_CHOOSE) - -#define HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS - -DONNA_NOINLINE static void -ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) { - int64_t breg = (int64_t)b; - uint64_t sign = (uint64_t)breg >> 63; - uint64_t mask = ~(sign - 1); - uint64_t u = (breg + mask) ^ mask; - - __asm__ __volatile__ ( - /* ysubx+xaddy+t2d */ - "movq %0, %%rax ;\n" - "movd %%rax, %%xmm14 ;\n" - "pshufd $0x00, %%xmm14, %%xmm14 ;\n" - "pxor %%xmm0, %%xmm0 ;\n" - "pxor %%xmm1, %%xmm1 ;\n" - "pxor %%xmm2, %%xmm2 ;\n" - "pxor %%xmm3, %%xmm3 ;\n" - "pxor %%xmm4, %%xmm4 ;\n" - "pxor %%xmm5, %%xmm5 ;\n" - - /* 0 */ - "movq $0, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movq $1, %%rax ;\n" - "movd %%rax, %%xmm6 ;\n" - "pxor %%xmm7, %%xmm7 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm6, %%xmm2 ;\n" - "por %%xmm7, %%xmm3 ;\n" - - /* 1 */ - "movq $1, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 0(%1), %%xmm6 ;\n" - "movdqa 16(%1), %%xmm7 ;\n" - "movdqa 32(%1), %%xmm8 ;\n" - "movdqa 48(%1), %%xmm9 ;\n" - "movdqa 64(%1), %%xmm10 ;\n" - "movdqa 80(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 2 */ - "movq $2, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 96(%1), %%xmm6 ;\n" - "movdqa 112(%1), %%xmm7 ;\n" - "movdqa 128(%1), %%xmm8 ;\n" - "movdqa 144(%1), %%xmm9 ;\n" - "movdqa 160(%1), %%xmm10 ;\n" - "movdqa 176(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 3 */ - "movq $3, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 192(%1), %%xmm6 ;\n" - "movdqa 208(%1), %%xmm7 ;\n" - "movdqa 224(%1), %%xmm8 ;\n" - "movdqa 240(%1), %%xmm9 ;\n" - "movdqa 256(%1), %%xmm10 ;\n" - "movdqa 272(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 4 */ - "movq $4, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 288(%1), %%xmm6 ;\n" - "movdqa 304(%1), %%xmm7 ;\n" - "movdqa 320(%1), %%xmm8 ;\n" - "movdqa 336(%1), %%xmm9 ;\n" - "movdqa 352(%1), %%xmm10 ;\n" - "movdqa 368(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 5 */ - "movq $5, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 384(%1), %%xmm6 ;\n" - "movdqa 400(%1), %%xmm7 ;\n" - "movdqa 416(%1), %%xmm8 ;\n" - "movdqa 432(%1), %%xmm9 ;\n" - "movdqa 448(%1), %%xmm10 ;\n" - "movdqa 464(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 6 */ - "movq $6, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 480(%1), %%xmm6 ;\n" - "movdqa 496(%1), %%xmm7 ;\n" - "movdqa 512(%1), %%xmm8 ;\n" - "movdqa 528(%1), %%xmm9 ;\n" - "movdqa 544(%1), %%xmm10 ;\n" - "movdqa 560(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 7 */ - "movq $7, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 576(%1), %%xmm6 ;\n" - "movdqa 592(%1), %%xmm7 ;\n" - "movdqa 608(%1), %%xmm8 ;\n" - "movdqa 624(%1), %%xmm9 ;\n" - "movdqa 640(%1), %%xmm10 ;\n" - "movdqa 656(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 8 */ - "movq $8, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 672(%1), %%xmm6 ;\n" - "movdqa 688(%1), %%xmm7 ;\n" - "movdqa 704(%1), %%xmm8 ;\n" - "movdqa 720(%1), %%xmm9 ;\n" - "movdqa 736(%1), %%xmm10 ;\n" - "movdqa 752(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* conditionally swap ysubx and xaddy */ - "movq %3, %%rax ;\n" - "xorq $1, %%rax ;\n" - "movd %%rax, %%xmm14 ;\n" - "pxor %%xmm15, %%xmm15 ;\n" - "pshufd $0x00, %%xmm14, %%xmm14 ;\n" - "pxor %%xmm0, %%xmm2 ;\n" - "pxor %%xmm1, %%xmm3 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa %%xmm2, %%xmm6 ;\n" - "movdqa %%xmm3, %%xmm7 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pxor %%xmm6, %%xmm0 ;\n" - "pxor %%xmm7, %%xmm1 ;\n" - "pxor %%xmm0, %%xmm2 ;\n" - "pxor %%xmm1, %%xmm3 ;\n" - - /* store ysubx */ - "xorq %%rax, %%rax ;\n" - "movd %%xmm0, %%rcx ;\n" - "movd %%xmm0, %%r8 ;\n" - "movd %%xmm1, %%rsi ;\n" - "pshufd $0xee, %%xmm0, %%xmm0 ;\n" - "pshufd $0xee, %%xmm1, %%xmm1 ;\n" - "movd %%xmm0, %%rdx ;\n" - "movd %%xmm1, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "movq %%rcx, %%r9 ;\n" - "movq %%r8, %%r10 ;\n" - "movq %%rdx, %%r11 ;\n" - "movq %%rsi, %%r12 ;\n" - "movq %%rdi, %%r13 ;\n" - "shrq $26, %%r9 ;\n" - "shrq $26, %%r10 ;\n" - "shrq $26, %%r11 ;\n" - "shrq $26, %%r12 ;\n" - "shrq $26, %%r13 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "andl $0x1ffffff, %%r9d ;\n" - "andl $0x3ffffff, %%r8d ;\n" - "andl $0x1ffffff, %%r10d ;\n" - "andl $0x3ffffff, %%edx ;\n" - "andl $0x1ffffff, %%r11d ;\n" - "andl $0x3ffffff, %%esi ;\n" - "andl $0x1ffffff, %%r12d ;\n" - "andl $0x3ffffff, %%edi ;\n" - "andl $0x1ffffff, %%r13d ;\n" - "movl %%ecx, 0(%2) ;\n" - "movl %%r9d, 4(%2) ;\n" - "movl %%r8d, 8(%2) ;\n" - "movl %%r10d, 12(%2) ;\n" - "movl %%edx, 16(%2) ;\n" - "movl %%r11d, 20(%2) ;\n" - "movl %%esi, 24(%2) ;\n" - "movl %%r12d, 28(%2) ;\n" - "movl %%edi, 32(%2) ;\n" - "movl %%r13d, 36(%2) ;\n" - "movq %%rax, 40(%2) ;\n" - - /* store xaddy */ - "movd %%xmm2, %%rcx ;\n" - "movd %%xmm2, %%r8 ;\n" - "movd %%xmm3, %%rsi ;\n" - "pshufd $0xee, %%xmm2, %%xmm2 ;\n" - "pshufd $0xee, %%xmm3, %%xmm3 ;\n" - "movd %%xmm2, %%rdx ;\n" - "movd %%xmm3, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "movq %%rcx, %%r9 ;\n" - "movq %%r8, %%r10 ;\n" - "movq %%rdx, %%r11 ;\n" - "movq %%rsi, %%r12 ;\n" - "movq %%rdi, %%r13 ;\n" - "shrq $26, %%r9 ;\n" - "shrq $26, %%r10 ;\n" - "shrq $26, %%r11 ;\n" - "shrq $26, %%r12 ;\n" - "shrq $26, %%r13 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "andl $0x1ffffff, %%r9d ;\n" - "andl $0x3ffffff, %%r8d ;\n" - "andl $0x1ffffff, %%r10d ;\n" - "andl $0x3ffffff, %%edx ;\n" - "andl $0x1ffffff, %%r11d ;\n" - "andl $0x3ffffff, %%esi ;\n" - "andl $0x1ffffff, %%r12d ;\n" - "andl $0x3ffffff, %%edi ;\n" - "andl $0x1ffffff, %%r13d ;\n" - "movl %%ecx, 48(%2) ;\n" - "movl %%r9d, 52(%2) ;\n" - "movl %%r8d, 56(%2) ;\n" - "movl %%r10d, 60(%2) ;\n" - "movl %%edx, 64(%2) ;\n" - "movl %%r11d, 68(%2) ;\n" - "movl %%esi, 72(%2) ;\n" - "movl %%r12d, 76(%2) ;\n" - "movl %%edi, 80(%2) ;\n" - "movl %%r13d, 84(%2) ;\n" - "movq %%rax, 88(%2) ;\n" - - /* extract t2d */ - "xorq %%rax, %%rax ;\n" - "movd %%xmm4, %%rcx ;\n" - "movd %%xmm4, %%r8 ;\n" - "movd %%xmm5, %%rsi ;\n" - "pshufd $0xee, %%xmm4, %%xmm4 ;\n" - "pshufd $0xee, %%xmm5, %%xmm5 ;\n" - "movd %%xmm4, %%rdx ;\n" - "movd %%xmm5, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "movq %%rcx, %%r9 ;\n" - "movq %%r8, %%r10 ;\n" - "movq %%rdx, %%r11 ;\n" - "movq %%rsi, %%r12 ;\n" - "movq %%rdi, %%r13 ;\n" - "shrq $26, %%r9 ;\n" - "shrq $26, %%r10 ;\n" - "shrq $26, %%r11 ;\n" - "shrq $26, %%r12 ;\n" - "shrq $26, %%r13 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "andl $0x1ffffff, %%r9d ;\n" - "andl $0x3ffffff, %%r8d ;\n" - "andl $0x1ffffff, %%r10d ;\n" - "andl $0x3ffffff, %%edx ;\n" - "andl $0x1ffffff, %%r11d ;\n" - "andl $0x3ffffff, %%esi ;\n" - "andl $0x1ffffff, %%r12d ;\n" - "andl $0x3ffffff, %%edi ;\n" - "andl $0x1ffffff, %%r13d ;\n" - "movd %%ecx, %%xmm0 ;\n" - "movd %%r9d, %%xmm4 ;\n" - "movd %%r8d, %%xmm8 ;\n" - "movd %%r10d, %%xmm3 ;\n" - "movd %%edx, %%xmm1 ;\n" - "movd %%r11d, %%xmm5 ;\n" - "movd %%esi, %%xmm6 ;\n" - "movd %%r12d, %%xmm7 ;\n" - "movd %%edi, %%xmm2 ;\n" - "movd %%r13d, %%xmm9 ;\n" - "punpckldq %%xmm4, %%xmm0 ;\n" - "punpckldq %%xmm3, %%xmm8 ;\n" - "punpckldq %%xmm5, %%xmm1 ;\n" - "punpckldq %%xmm7, %%xmm6 ;\n" - "punpckldq %%xmm9, %%xmm2 ;\n" - "punpcklqdq %%xmm8, %%xmm0 ;\n" - "punpcklqdq %%xmm6, %%xmm1 ;\n" - - /* set up 2p in to 3/4 */ - "movl $0x7ffffda, %%ecx ;\n" - "movl $0x3fffffe, %%edx ;\n" - "movl $0x7fffffe, %%eax ;\n" - "movd %%ecx, %%xmm3 ;\n" - "movd %%edx, %%xmm5 ;\n" - "movd %%eax, %%xmm4 ;\n" - "punpckldq %%xmm5, %%xmm3 ;\n" - "punpckldq %%xmm5, %%xmm4 ;\n" - "punpcklqdq %%xmm4, %%xmm3 ;\n" - "movdqa %%xmm4, %%xmm5 ;\n" - "punpcklqdq %%xmm4, %%xmm4 ;\n" - - /* subtract and conditionally move */ - "movl %3, %%ecx ;\n" - "sub $1, %%ecx ;\n" - "movd %%ecx, %%xmm6 ;\n" - "pshufd $0x00, %%xmm6, %%xmm6 ;\n" - "movdqa %%xmm6, %%xmm7 ;\n" - "psubd %%xmm0, %%xmm3 ;\n" - "psubd %%xmm1, %%xmm4 ;\n" - "psubd %%xmm2, %%xmm5 ;\n" - "pand %%xmm6, %%xmm0 ;\n" - "pand %%xmm6, %%xmm1 ;\n" - "pand %%xmm6, %%xmm2 ;\n" - "pandn %%xmm3, %%xmm6 ;\n" - "movdqa %%xmm7, %%xmm3 ;\n" - "pandn %%xmm4, %%xmm7 ;\n" - "pandn %%xmm5, %%xmm3 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm3, %%xmm2 ;\n" - - /* store t2d */ - "movdqa %%xmm0, 96(%2) ;\n" - "movdqa %%xmm1, 112(%2) ;\n" - "movdqa %%xmm2, 128(%2) ;\n" - : - : "m"(u), "r"(&table[pos * 8]), "r"(t), "m"(sign) /* %0 = u, %1 = table, %2 = t, %3 = sign */ - : - "%rax", "%rcx", "%rdx", "%rdi", "%rsi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", - "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm14", "%xmm14", - "cc", "memory" - ); -} - -#endif /* defined(ED25519_GCC_64BIT_SSE_CHOOSE) */ - diff --git a/external/ed25519-donna/ed25519-donna-64bit-tables.h b/external/ed25519-donna/ed25519-donna-64bit-tables.h deleted file mode 100644 index 4a6ff9edae..0000000000 --- a/external/ed25519-donna/ed25519-donna-64bit-tables.h +++ /dev/null @@ -1,53 +0,0 @@ -static const ge25519 ge25519_basepoint = { - {0x00062d608f25d51a,0x000412a4b4f6592a,0x00075b7171a4b31d,0x0001ff60527118fe,0x000216936d3cd6e5}, - {0x0006666666666658,0x0004cccccccccccc,0x0001999999999999,0x0003333333333333,0x0006666666666666}, - {0x0000000000000001,0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000}, - {0x00068ab3a5b7dda3,0x00000eea2a5eadbb,0x0002af8df483c27e,0x000332b375274732,0x00067875f0fd78b7} -}; - -static const bignum25519 ge25519_ecd = { - 0x00034dca135978a3,0x0001a8283b156ebd,0x0005e7a26001c029,0x000739c663a03cbb,0x00052036cee2b6ff -}; - -static const bignum25519 ge25519_ec2d = { - 0x00069b9426b2f159,0x00035050762add7a,0x0003cf44c0038052,0x0006738cc7407977,0x0002406d9dc56dff -}; - -static const bignum25519 ge25519_sqrtneg1 = { - 0x00061b274a0ea0b0,0x0000d5a5fc8f189d,0x0007ef5e9cbd0c60,0x00078595a6804c9e,0x0002b8324804fc1d -}; - -static const ge25519_niels ge25519_niels_sliding_multiples[32] = { - {{0x00003905d740913e,0x0000ba2817d673a2,0x00023e2827f4e67c,0x000133d2e0c21a34,0x00044fd2f9298f81},{0x000493c6f58c3b85,0x0000df7181c325f7,0x0000f50b0b3e4cb7,0x0005329385a44c32,0x00007cf9d3a33d4b},{0x00011205877aaa68,0x000479955893d579,0x00050d66309b67a0,0x0002d42d0dbee5ee,0x0006f117b689f0c6}}, - {{0x00011fe8a4fcd265,0x0007bcb8374faacc,0x00052f5af4ef4d4f,0x0005314098f98d10,0x0002ab91587555bd},{0x0005b0a84cee9730,0x00061d10c97155e4,0x0004059cc8096a10,0x00047a608da8014f,0x0007a164e1b9a80f},{0x0006933f0dd0d889,0x00044386bb4c4295,0x0003cb6d3162508c,0x00026368b872a2c6,0x0005a2826af12b9b}}, - {{0x000182c3a447d6ba,0x00022964e536eff2,0x000192821f540053,0x0002f9f19e788e5c,0x000154a7e73eb1b5},{0x0002bc4408a5bb33,0x000078ebdda05442,0x0002ffb112354123,0x000375ee8df5862d,0x0002945ccf146e20},{0x0003dbf1812a8285,0x0000fa17ba3f9797,0x0006f69cb49c3820,0x00034d5a0db3858d,0x00043aabe696b3bb}}, - {{0x00072c9aaa3221b1,0x000267774474f74d,0x000064b0e9b28085,0x0003f04ef53b27c9,0x0001d6edd5d2e531},{0x00025cd0944ea3bf,0x00075673b81a4d63,0x000150b925d1c0d4,0x00013f38d9294114,0x000461bea69283c9},{0x00036dc801b8b3a2,0x0000e0a7d4935e30,0x0001deb7cecc0d7d,0x000053a94e20dd2c,0x0007a9fbb1c6a0f9}}, - {{0x0006217e039d8064,0x0006dea408337e6d,0x00057ac112628206,0x000647cb65e30473,0x00049c05a51fadc9},{0x0006678aa6a8632f,0x0005ea3788d8b365,0x00021bd6d6994279,0x0007ace75919e4e3,0x00034b9ed338add7},{0x0004e8bf9045af1b,0x000514e33a45e0d6,0x0007533c5b8bfe0f,0x000583557b7e14c9,0x00073c172021b008}}, - {{0x00075b0249864348,0x00052ee11070262b,0x000237ae54fb5acd,0x0003bfd1d03aaab5,0x00018ab598029d5c},{0x000700848a802ade,0x0001e04605c4e5f7,0x0005c0d01b9767fb,0x0007d7889f42388b,0x0004275aae2546d8},{0x00032cc5fd6089e9,0x000426505c949b05,0x00046a18880c7ad2,0x0004a4221888ccda,0x0003dc65522b53df}}, - {{0x0007013b327fbf93,0x0001336eeded6a0d,0x0002b565a2bbf3af,0x000253ce89591955,0x0000267882d17602},{0x0000c222a2007f6d,0x000356b79bdb77ee,0x00041ee81efe12ce,0x000120a9bd07097d,0x000234fd7eec346f},{0x0000a119732ea378,0x00063bf1ba8e2a6c,0x00069f94cc90df9a,0x000431d1779bfc48,0x000497ba6fdaa097}}, - {{0x0003cd86468ccf0b,0x00048553221ac081,0x0006c9464b4e0a6e,0x00075fba84180403,0x00043b5cd4218d05},{0x0006cc0313cfeaa0,0x0001a313848da499,0x0007cb534219230a,0x00039596dedefd60,0x00061e22917f12de},{0x0002762f9bd0b516,0x0001c6e7fbddcbb3,0x00075909c3ace2bd,0x00042101972d3ec9,0x000511d61210ae4d}}, - {{0x000386484420de87,0x0002d6b25db68102,0x000650b4962873c0,0x0004081cfd271394,0x00071a7fe6fe2482},{0x000676ef950e9d81,0x0001b81ae089f258,0x00063c4922951883,0x0002f1d54d9b3237,0x0006d325924ddb85},{0x000182b8a5c8c854,0x00073fcbe5406d8e,0x0005de3430cff451,0x000554b967ac8c41,0x0004746c4b6559ee}}, - {{0x000546c864741147,0x0003a1df99092690,0x0001ca8cc9f4d6bb,0x00036b7fc9cd3b03,0x000219663497db5e},{0x00077b3c6dc69a2b,0x0004edf13ec2fa6e,0x0004e85ad77beac8,0x0007dba2b28e7bda,0x0005c9a51de34fe9},{0x0000f1cf79f10e67,0x00043ccb0a2b7ea2,0x00005089dfff776a,0x0001dd84e1d38b88,0x0004804503c60822}}, - {{0x000021d23a36d175,0x0004fd3373c6476d,0x00020e291eeed02a,0x00062f2ecf2e7210,0x000771e098858de4},{0x00049ed02ca37fc7,0x000474c2b5957884,0x0005b8388e816683,0x0004b6c454b76be4,0x000553398a516506},{0x0002f5d278451edf,0x000730b133997342,0x0006965420eb6975,0x000308a3bfa516cf,0x0005a5ed1d68ff5a}}, - {{0x0005e0c558527359,0x0003395b73afd75c,0x000072afa4e4b970,0x00062214329e0f6d,0x000019b60135fefd},{0x0005122afe150e83,0x0004afc966bb0232,0x0001c478833c8268,0x00017839c3fc148f,0x00044acb897d8bf9},{0x000068145e134b83,0x0001e4860982c3cc,0x000068fb5f13d799,0x0007c9283744547e,0x000150c49fde6ad2}}, - {{0x0001863c9cdca868,0x0003770e295a1709,0x0000d85a3720fd13,0x0005e0ff1f71ab06,0x00078a6d7791e05f},{0x0003f29509471138,0x000729eeb4ca31cf,0x00069c22b575bfbc,0x0004910857bce212,0x0006b2b5a075bb99},{0x0007704b47a0b976,0x0002ae82e91aab17,0x00050bd6429806cd,0x00068055158fd8ea,0x000725c7ffc4ad55}}, - {{0x00002bf71cd098c0,0x00049dabcc6cd230,0x00040a6533f905b2,0x000573efac2eb8a4,0x0004cd54625f855f},{0x00026715d1cf99b2,0x0002205441a69c88,0x000448427dcd4b54,0x0001d191e88abdc5,0x000794cc9277cb1f},{0x0006c426c2ac5053,0x0005a65ece4b095e,0x0000c44086f26bb6,0x0007429568197885,0x0007008357b6fcc8}}, - {{0x00039fbb82584a34,0x00047a568f257a03,0x00014d88091ead91,0x0002145b18b1ce24,0x00013a92a3669d6d},{0x0000672738773f01,0x000752bf799f6171,0x0006b4a6dae33323,0x0007b54696ead1dc,0x00006ef7e9851ad0},{0x0003771cc0577de5,0x0003ca06bb8b9952,0x00000b81c5d50390,0x00043512340780ec,0x0003c296ddf8a2af}}, - {{0x00034d2ebb1f2541,0x0000e815b723ff9d,0x000286b416e25443,0x0000bdfe38d1bee8,0x0000a892c7007477},{0x000515f9d914a713,0x00073191ff2255d5,0x00054f5cc2a4bdef,0x0003dd57fc118bcf,0x0007a99d393490c7},{0x0002ed2436bda3e8,0x00002afd00f291ea,0x0000be7381dea321,0x0003e952d4b2b193,0x000286762d28302f}}, - {{0x00058e2bce2ef5bd,0x00068ce8f78c6f8a,0x0006ee26e39261b2,0x00033d0aa50bcf9d,0x0007686f2a3d6f17},{0x000036093ce35b25,0x0003b64d7552e9cf,0x00071ee0fe0b8460,0x00069d0660c969e5,0x00032f1da046a9d9},{0x000512a66d597c6a,0x0000609a70a57551,0x000026c08a3c464c,0x0004531fc8ee39e1,0x000561305f8a9ad2}}, - {{0x0002cc28e7b0c0d5,0x00077b60eb8a6ce4,0x0004042985c277a6,0x000636657b46d3eb,0x000030a1aef2c57c},{0x0004978dec92aed1,0x000069adae7ca201,0x00011ee923290f55,0x00069641898d916c,0x00000aaec53e35d4},{0x0001f773003ad2aa,0x000005642cc10f76,0x00003b48f82cfca6,0x0002403c10ee4329,0x00020be9c1c24065}}, - {{0x0000e44ae2025e60,0x0005f97b9727041c,0x0005683472c0ecec,0x000188882eb1ce7c,0x00069764c545067e},{0x000387d8249673a6,0x0005bea8dc927c2a,0x0005bd8ed5650ef0,0x0000ef0e3fcd40e1,0x000750ab3361f0ac},{0x00023283a2f81037,0x000477aff97e23d1,0x0000b8958dbcbb68,0x0000205b97e8add6,0x00054f96b3fb7075}}, - {{0x0005afc616b11ecd,0x00039f4aec8f22ef,0x0003b39e1625d92e,0x0005f85bd4508873,0x00078e6839fbe85d},{0x0005f20429669279,0x00008fafae4941f5,0x00015d83c4eb7688,0x0001cf379eca4146,0x0003d7fe9c52bb75},{0x00032df737b8856b,0x0000608342f14e06,0x0003967889d74175,0x0001211907fba550,0x00070f268f350088}}, - {{0x0004112070dcf355,0x0007dcff9c22e464,0x00054ada60e03325,0x00025cd98eef769a,0x000404e56c039b8c},{0x00064583b1805f47,0x00022c1baf832cd0,0x000132c01bd4d717,0x0004ecf4c3a75b8f,0x0007c0d345cfad88},{0x00071f4b8c78338a,0x00062cfc16bc2b23,0x00017cf51280d9aa,0x0003bbae5e20a95a,0x00020d754762aaec}}, - {{0x0004feb135b9f543,0x00063bd192ad93ae,0x00044e2ea612cdf7,0x000670f4991583ab,0x00038b8ada8790b4},{0x0007c36fc73bb758,0x0004a6c797734bd1,0x0000ef248ab3950e,0x00063154c9a53ec8,0x0002b8f1e46f3cee},{0x00004a9cdf51f95d,0x0005d963fbd596b8,0x00022d9b68ace54a,0x0004a98e8836c599,0x000049aeb32ceba1}}, - {{0x00067d3c63dcfe7e,0x000112f0adc81aee,0x00053df04c827165,0x0002fe5b33b430f0,0x00051c665e0c8d62},{0x00007d0b75fc7931,0x00016f4ce4ba754a,0x0005ace4c03fbe49,0x00027e0ec12a159c,0x000795ee17530f67},{0x00025b0a52ecbd81,0x0005dc0695fce4a9,0x0003b928c575047d,0x00023bf3512686e5,0x0006cd19bf49dc54}}, - {{0x0007619052179ca3,0x0000c16593f0afd0,0x000265c4795c7428,0x00031c40515d5442,0x0007520f3db40b2e},{0x0006612165afc386,0x0001171aa36203ff,0x0002642ea820a8aa,0x0001f3bb7b313f10,0x0005e01b3a7429e4},{0x00050be3d39357a1,0x0003ab33d294a7b6,0x0004c479ba59edb3,0x0004c30d184d326f,0x00071092c9ccef3c}}, - {{0x0000523f0364918c,0x000687f56d638a7b,0x00020796928ad013,0x0005d38405a54f33,0x0000ea15b03d0257},{0x0003d8ac74051dcf,0x00010ab6f543d0ad,0x0005d0f3ac0fda90,0x0005ef1d2573e5e4,0x0004173a5bb7137a},{0x00056e31f0f9218a,0x0005635f88e102f8,0x0002cbc5d969a5b8,0x000533fbc98b347a,0x0005fc565614a4e3}}, - {{0x0006570dc46d7ae5,0x00018a9f1b91e26d,0x000436b6183f42ab,0x000550acaa4f8198,0x00062711c414c454},{0x0002e1e67790988e,0x0001e38b9ae44912,0x000648fbb4075654,0x00028df1d840cd72,0x0003214c7409d466},{0x0001827406651770,0x0004d144f286c265,0x00017488f0ee9281,0x00019e6cdb5c760c,0x0005bea94073ecb8}}, - {{0x0005bf0912c89be4,0x00062fadcaf38c83,0x00025ec196b3ce2c,0x00077655ff4f017b,0x0003aacd5c148f61},{0x0000ce63f343d2f8,0x0001e0a87d1e368e,0x000045edbc019eea,0x0006979aed28d0d1,0x0004ad0785944f1b},{0x00063b34c3318301,0x0000e0e62d04d0b1,0x000676a233726701,0x00029e9a042d9769,0x0003aff0cb1d9028}}, - {{0x0005c7eb3a20405e,0x0005fdb5aad930f8,0x0004a757e63b8c47,0x00028e9492972456,0x000110e7e86f4cd2},{0x0006430bf4c53505,0x000264c3e4507244,0x00074c9f19a39270,0x00073f84f799bc47,0x0002ccf9f732bd99},{0x0000d89ed603f5e4,0x00051e1604018af8,0x0000b8eedc4a2218,0x00051ba98b9384d0,0x00005c557e0b9693}}, - {{0x0001ce311fc97e6f,0x0006023f3fb5db1f,0x0007b49775e8fc98,0x0003ad70adbf5045,0x0006e154c178fe98},{0x0006bbb089c20eb0,0x0006df41fb0b9eee,0x00051087ed87e16f,0x000102db5c9fa731,0x000289fef0841861},{0x00016336fed69abf,0x0004f066b929f9ec,0x0004e9ff9e6c5b93,0x00018c89bc4bb2ba,0x0006afbf642a95ca}}, - {{0x0000de0c62f5d2c1,0x00049601cf734fb5,0x0006b5c38263f0f6,0x0004623ef5b56d06,0x0000db4b851b9503},{0x00055070f913a8cc,0x000765619eac2bbc,0x0003ab5225f47459,0x00076ced14ab5b48,0x00012c093cedb801},{0x00047f9308b8190f,0x000414235c621f82,0x00031f5ff41a5a76,0x0006736773aab96d,0x00033aa8799c6635}}, - {{0x0007f51ebd085cf2,0x00012cfa67e3f5e1,0x0001800cf1e3d46a,0x00054337615ff0a8,0x000233c6f29e8e21},{0x0000f588fc156cb1,0x000363414da4f069,0x0007296ad9b68aea,0x0004d3711316ae43,0x000212cd0c1c8d58},{0x0004d5107f18c781,0x00064a4fd3a51a5e,0x0004f4cd0448bb37,0x000671d38543151e,0x0001db7778911914}}, - {{0x000352397c6bc26f,0x00018a7aa0227bbe,0x0005e68cc1ea5f8b,0x0006fe3e3a7a1d5f,0x00031ad97ad26e2a},{0x00014769dd701ab6,0x00028339f1b4b667,0x0004ab214b8ae37b,0x00025f0aefa0b0fe,0x0007ae2ca8a017d2},{0x000017ed0920b962,0x000187e33b53b6fd,0x00055829907a1463,0x000641f248e0a792,0x0001ed1fc53a6622}} -}; diff --git a/external/ed25519-donna/ed25519-donna-64bit-x86-32bit.h b/external/ed25519-donna/ed25519-donna-64bit-x86-32bit.h deleted file mode 100644 index 1ce109c5b7..0000000000 --- a/external/ed25519-donna/ed25519-donna-64bit-x86-32bit.h +++ /dev/null @@ -1,435 +0,0 @@ -#if defined(ED25519_GCC_64BIT_32BIT_CHOOSE) - -#define HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS - -DONNA_NOINLINE static void -ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) { - int64_t breg = (int64_t)b; - uint64_t sign = (uint64_t)breg >> 63; - uint64_t mask = ~(sign - 1); - uint64_t u = (breg + mask) ^ mask; - - __asm__ __volatile__ ( - /* ysubx+xaddy+t2d */ - "movq %0, %%rax ;\n" - "movd %%rax, %%xmm14 ;\n" - "pshufd $0x00, %%xmm14, %%xmm14 ;\n" - "pxor %%xmm0, %%xmm0 ;\n" - "pxor %%xmm1, %%xmm1 ;\n" - "pxor %%xmm2, %%xmm2 ;\n" - "pxor %%xmm3, %%xmm3 ;\n" - "pxor %%xmm4, %%xmm4 ;\n" - "pxor %%xmm5, %%xmm5 ;\n" - - /* 0 */ - "movq $0, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movq $1, %%rax ;\n" - "movd %%rax, %%xmm6 ;\n" - "pxor %%xmm7, %%xmm7 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm6, %%xmm2 ;\n" - "por %%xmm7, %%xmm3 ;\n" - - /* 1 */ - "movq $1, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 0(%1), %%xmm6 ;\n" - "movdqa 16(%1), %%xmm7 ;\n" - "movdqa 32(%1), %%xmm8 ;\n" - "movdqa 48(%1), %%xmm9 ;\n" - "movdqa 64(%1), %%xmm10 ;\n" - "movdqa 80(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 2 */ - "movq $2, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 96(%1), %%xmm6 ;\n" - "movdqa 112(%1), %%xmm7 ;\n" - "movdqa 128(%1), %%xmm8 ;\n" - "movdqa 144(%1), %%xmm9 ;\n" - "movdqa 160(%1), %%xmm10 ;\n" - "movdqa 176(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 3 */ - "movq $3, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 192(%1), %%xmm6 ;\n" - "movdqa 208(%1), %%xmm7 ;\n" - "movdqa 224(%1), %%xmm8 ;\n" - "movdqa 240(%1), %%xmm9 ;\n" - "movdqa 256(%1), %%xmm10 ;\n" - "movdqa 272(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 4 */ - "movq $4, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 288(%1), %%xmm6 ;\n" - "movdqa 304(%1), %%xmm7 ;\n" - "movdqa 320(%1), %%xmm8 ;\n" - "movdqa 336(%1), %%xmm9 ;\n" - "movdqa 352(%1), %%xmm10 ;\n" - "movdqa 368(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 5 */ - "movq $5, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 384(%1), %%xmm6 ;\n" - "movdqa 400(%1), %%xmm7 ;\n" - "movdqa 416(%1), %%xmm8 ;\n" - "movdqa 432(%1), %%xmm9 ;\n" - "movdqa 448(%1), %%xmm10 ;\n" - "movdqa 464(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 6 */ - "movq $6, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 480(%1), %%xmm6 ;\n" - "movdqa 496(%1), %%xmm7 ;\n" - "movdqa 512(%1), %%xmm8 ;\n" - "movdqa 528(%1), %%xmm9 ;\n" - "movdqa 544(%1), %%xmm10 ;\n" - "movdqa 560(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 7 */ - "movq $7, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 576(%1), %%xmm6 ;\n" - "movdqa 592(%1), %%xmm7 ;\n" - "movdqa 608(%1), %%xmm8 ;\n" - "movdqa 624(%1), %%xmm9 ;\n" - "movdqa 640(%1), %%xmm10 ;\n" - "movdqa 656(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 8 */ - "movq $8, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 672(%1), %%xmm6 ;\n" - "movdqa 688(%1), %%xmm7 ;\n" - "movdqa 704(%1), %%xmm8 ;\n" - "movdqa 720(%1), %%xmm9 ;\n" - "movdqa 736(%1), %%xmm10 ;\n" - "movdqa 752(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* conditionally swap ysubx and xaddy */ - "movq %3, %%rax ;\n" - "xorq $1, %%rax ;\n" - "movd %%rax, %%xmm14 ;\n" - "pxor %%xmm15, %%xmm15 ;\n" - "pshufd $0x00, %%xmm14, %%xmm14 ;\n" - "pxor %%xmm0, %%xmm2 ;\n" - "pxor %%xmm1, %%xmm3 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa %%xmm2, %%xmm6 ;\n" - "movdqa %%xmm3, %%xmm7 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pxor %%xmm6, %%xmm0 ;\n" - "pxor %%xmm7, %%xmm1 ;\n" - "pxor %%xmm0, %%xmm2 ;\n" - "pxor %%xmm1, %%xmm3 ;\n" - - /* store ysubx */ - "xorq %%rax, %%rax ;\n" - "movd %%xmm0, %%rcx ;\n" - "movd %%xmm0, %%r8 ;\n" - "movd %%xmm1, %%rsi ;\n" - "pshufd $0xee, %%xmm0, %%xmm0 ;\n" - "pshufd $0xee, %%xmm1, %%xmm1 ;\n" - "movd %%xmm0, %%rdx ;\n" - "movd %%xmm1, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "movq %%rcx, %%r9 ;\n" - "movq %%r8, %%r10 ;\n" - "movq %%rdx, %%r11 ;\n" - "movq %%rsi, %%r12 ;\n" - "movq %%rdi, %%r13 ;\n" - "shrq $26, %%r9 ;\n" - "shrq $26, %%r10 ;\n" - "shrq $26, %%r11 ;\n" - "shrq $26, %%r12 ;\n" - "shrq $26, %%r13 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "andl $0x1ffffff, %%r9d ;\n" - "andl $0x3ffffff, %%r8d ;\n" - "andl $0x1ffffff, %%r10d ;\n" - "andl $0x3ffffff, %%edx ;\n" - "andl $0x1ffffff, %%r11d ;\n" - "andl $0x3ffffff, %%esi ;\n" - "andl $0x1ffffff, %%r12d ;\n" - "andl $0x3ffffff, %%edi ;\n" - "andl $0x1ffffff, %%r13d ;\n" - "movl %%ecx, 0(%2) ;\n" - "movl %%r9d, 4(%2) ;\n" - "movl %%r8d, 8(%2) ;\n" - "movl %%r10d, 12(%2) ;\n" - "movl %%edx, 16(%2) ;\n" - "movl %%r11d, 20(%2) ;\n" - "movl %%esi, 24(%2) ;\n" - "movl %%r12d, 28(%2) ;\n" - "movl %%edi, 32(%2) ;\n" - "movl %%r13d, 36(%2) ;\n" - - /* store xaddy */ - "movd %%xmm2, %%rcx ;\n" - "movd %%xmm2, %%r8 ;\n" - "movd %%xmm3, %%rsi ;\n" - "pshufd $0xee, %%xmm2, %%xmm2 ;\n" - "pshufd $0xee, %%xmm3, %%xmm3 ;\n" - "movd %%xmm2, %%rdx ;\n" - "movd %%xmm3, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "movq %%rcx, %%r9 ;\n" - "movq %%r8, %%r10 ;\n" - "movq %%rdx, %%r11 ;\n" - "movq %%rsi, %%r12 ;\n" - "movq %%rdi, %%r13 ;\n" - "shrq $26, %%r9 ;\n" - "shrq $26, %%r10 ;\n" - "shrq $26, %%r11 ;\n" - "shrq $26, %%r12 ;\n" - "shrq $26, %%r13 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "andl $0x1ffffff, %%r9d ;\n" - "andl $0x3ffffff, %%r8d ;\n" - "andl $0x1ffffff, %%r10d ;\n" - "andl $0x3ffffff, %%edx ;\n" - "andl $0x1ffffff, %%r11d ;\n" - "andl $0x3ffffff, %%esi ;\n" - "andl $0x1ffffff, %%r12d ;\n" - "andl $0x3ffffff, %%edi ;\n" - "andl $0x1ffffff, %%r13d ;\n" - "movl %%ecx, 40(%2) ;\n" - "movl %%r9d, 44(%2) ;\n" - "movl %%r8d, 48(%2) ;\n" - "movl %%r10d, 52(%2) ;\n" - "movl %%edx, 56(%2) ;\n" - "movl %%r11d, 60(%2) ;\n" - "movl %%esi, 64(%2) ;\n" - "movl %%r12d, 68(%2) ;\n" - "movl %%edi, 72(%2) ;\n" - "movl %%r13d, 76(%2) ;\n" - - /* extract t2d */ - "xorq %%rax, %%rax ;\n" - "movd %%xmm4, %%rcx ;\n" - "movd %%xmm4, %%r8 ;\n" - "movd %%xmm5, %%rsi ;\n" - "pshufd $0xee, %%xmm4, %%xmm4 ;\n" - "pshufd $0xee, %%xmm5, %%xmm5 ;\n" - "movd %%xmm4, %%rdx ;\n" - "movd %%xmm5, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "movq %%rcx, %%r9 ;\n" - "movq %%r8, %%r10 ;\n" - "movq %%rdx, %%r11 ;\n" - "movq %%rsi, %%r12 ;\n" - "movq %%rdi, %%r13 ;\n" - "shrq $26, %%r9 ;\n" - "shrq $26, %%r10 ;\n" - "shrq $26, %%r11 ;\n" - "shrq $26, %%r12 ;\n" - "shrq $26, %%r13 ;\n" - "andl $0x3ffffff, %%ecx ;\n" - "andl $0x1ffffff, %%r9d ;\n" - "andl $0x3ffffff, %%r8d ;\n" - "andl $0x1ffffff, %%r10d ;\n" - "andl $0x3ffffff, %%edx ;\n" - "andl $0x1ffffff, %%r11d ;\n" - "andl $0x3ffffff, %%esi ;\n" - "andl $0x1ffffff, %%r12d ;\n" - "andl $0x3ffffff, %%edi ;\n" - "andl $0x1ffffff, %%r13d ;\n" - "movd %%ecx, %%xmm0 ;\n" - "movd %%r9d, %%xmm4 ;\n" - "movd %%r8d, %%xmm8 ;\n" - "movd %%r10d, %%xmm3 ;\n" - "movd %%edx, %%xmm1 ;\n" - "movd %%r11d, %%xmm5 ;\n" - "movd %%esi, %%xmm6 ;\n" - "movd %%r12d, %%xmm7 ;\n" - "movd %%edi, %%xmm2 ;\n" - "movd %%r13d, %%xmm9 ;\n" - "punpckldq %%xmm4, %%xmm0 ;\n" - "punpckldq %%xmm3, %%xmm8 ;\n" - "punpckldq %%xmm5, %%xmm1 ;\n" - "punpckldq %%xmm7, %%xmm6 ;\n" - "punpckldq %%xmm9, %%xmm2 ;\n" - "punpcklqdq %%xmm8, %%xmm0 ;\n" - "punpcklqdq %%xmm6, %%xmm1 ;\n" - - /* set up 2p in to 3/4 */ - "movl $0x7ffffda, %%ecx ;\n" - "movl $0x3fffffe, %%edx ;\n" - "movl $0x7fffffe, %%eax ;\n" - "movd %%ecx, %%xmm3 ;\n" - "movd %%edx, %%xmm5 ;\n" - "movd %%eax, %%xmm4 ;\n" - "punpckldq %%xmm5, %%xmm3 ;\n" - "punpckldq %%xmm5, %%xmm4 ;\n" - "punpcklqdq %%xmm4, %%xmm3 ;\n" - "movdqa %%xmm4, %%xmm5 ;\n" - "punpcklqdq %%xmm4, %%xmm4 ;\n" - - /* subtract and conditionally move */ - "movl %3, %%ecx ;\n" - "sub $1, %%ecx ;\n" - "movd %%ecx, %%xmm6 ;\n" - "pshufd $0x00, %%xmm6, %%xmm6 ;\n" - "movdqa %%xmm6, %%xmm7 ;\n" - "psubd %%xmm0, %%xmm3 ;\n" - "psubd %%xmm1, %%xmm4 ;\n" - "psubd %%xmm2, %%xmm5 ;\n" - "pand %%xmm6, %%xmm0 ;\n" - "pand %%xmm6, %%xmm1 ;\n" - "pand %%xmm6, %%xmm2 ;\n" - "pandn %%xmm3, %%xmm6 ;\n" - "movdqa %%xmm7, %%xmm3 ;\n" - "pandn %%xmm4, %%xmm7 ;\n" - "pandn %%xmm5, %%xmm3 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm3, %%xmm2 ;\n" - - /* store t2d */ - "movdqa %%xmm0, 80(%2) ;\n" - "movdqa %%xmm1, 96(%2) ;\n" - "movd %%xmm2, %%rax ;\n" - "movq %%rax, 112(%2) ;\n" - : - : "m"(u), "r"(&table[pos * 8]), "r"(t), "m"(sign) /* %0 = u, %1 = table, %2 = t, %3 = sign */ - : - "%rax", "%rcx", "%rdx", "%rdi", "%rsi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", - "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm14", "%xmm14", - "cc", "memory" - ); -} - -#endif /* defined(ED25519_GCC_64BIT_32BIT_CHOOSE) */ - diff --git a/external/ed25519-donna/ed25519-donna-64bit-x86.h b/external/ed25519-donna/ed25519-donna-64bit-x86.h deleted file mode 100644 index 7c844ecda4..0000000000 --- a/external/ed25519-donna/ed25519-donna-64bit-x86.h +++ /dev/null @@ -1,357 +0,0 @@ -#if defined(ED25519_GCC_64BIT_X86_CHOOSE) - -#define HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS - -#if defined(__clang__) || defined (__GNUC__) -# define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) -#else -# define ATTRIBUTE_NO_SANITIZE_ADDRESS -#endif - -ATTRIBUTE_NO_SANITIZE_ADDRESS DONNA_NOINLINE static void -ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) { - int64_t breg = (int64_t)b; - uint64_t sign = (uint64_t)breg >> 63; - uint64_t mask = ~(sign - 1); - uint64_t u = (breg + mask) ^ mask; - - __asm__ __volatile__ ( - /* ysubx+xaddy+t2d */ - "movq %0, %%rax ;\n" - "movd %%rax, %%xmm14 ;\n" - "pshufd $0x00, %%xmm14, %%xmm14 ;\n" - "pxor %%xmm0, %%xmm0 ;\n" - "pxor %%xmm1, %%xmm1 ;\n" - "pxor %%xmm2, %%xmm2 ;\n" - "pxor %%xmm3, %%xmm3 ;\n" - "pxor %%xmm4, %%xmm4 ;\n" - "pxor %%xmm5, %%xmm5 ;\n" - - /* 0 */ - "movq $0, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movq $1, %%rax ;\n" - "movd %%rax, %%xmm6 ;\n" - "pxor %%xmm7, %%xmm7 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm6, %%xmm2 ;\n" - "por %%xmm7, %%xmm3 ;\n" - - /* 1 */ - "movq $1, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 0(%1), %%xmm6 ;\n" - "movdqa 16(%1), %%xmm7 ;\n" - "movdqa 32(%1), %%xmm8 ;\n" - "movdqa 48(%1), %%xmm9 ;\n" - "movdqa 64(%1), %%xmm10 ;\n" - "movdqa 80(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 2 */ - "movq $2, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 96(%1), %%xmm6 ;\n" - "movdqa 112(%1), %%xmm7 ;\n" - "movdqa 128(%1), %%xmm8 ;\n" - "movdqa 144(%1), %%xmm9 ;\n" - "movdqa 160(%1), %%xmm10 ;\n" - "movdqa 176(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 3 */ - "movq $3, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 192(%1), %%xmm6 ;\n" - "movdqa 208(%1), %%xmm7 ;\n" - "movdqa 224(%1), %%xmm8 ;\n" - "movdqa 240(%1), %%xmm9 ;\n" - "movdqa 256(%1), %%xmm10 ;\n" - "movdqa 272(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 4 */ - "movq $4, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 288(%1), %%xmm6 ;\n" - "movdqa 304(%1), %%xmm7 ;\n" - "movdqa 320(%1), %%xmm8 ;\n" - "movdqa 336(%1), %%xmm9 ;\n" - "movdqa 352(%1), %%xmm10 ;\n" - "movdqa 368(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 5 */ - "movq $5, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 384(%1), %%xmm6 ;\n" - "movdqa 400(%1), %%xmm7 ;\n" - "movdqa 416(%1), %%xmm8 ;\n" - "movdqa 432(%1), %%xmm9 ;\n" - "movdqa 448(%1), %%xmm10 ;\n" - "movdqa 464(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 6 */ - "movq $6, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 480(%1), %%xmm6 ;\n" - "movdqa 496(%1), %%xmm7 ;\n" - "movdqa 512(%1), %%xmm8 ;\n" - "movdqa 528(%1), %%xmm9 ;\n" - "movdqa 544(%1), %%xmm10 ;\n" - "movdqa 560(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 7 */ - "movq $7, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 576(%1), %%xmm6 ;\n" - "movdqa 592(%1), %%xmm7 ;\n" - "movdqa 608(%1), %%xmm8 ;\n" - "movdqa 624(%1), %%xmm9 ;\n" - "movdqa 640(%1), %%xmm10 ;\n" - "movdqa 656(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* 8 */ - "movq $8, %%rax ;\n" - "movd %%rax, %%xmm15 ;\n" - "pshufd $0x00, %%xmm15, %%xmm15 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa 672(%1), %%xmm6 ;\n" - "movdqa 688(%1), %%xmm7 ;\n" - "movdqa 704(%1), %%xmm8 ;\n" - "movdqa 720(%1), %%xmm9 ;\n" - "movdqa 736(%1), %%xmm10 ;\n" - "movdqa 752(%1), %%xmm11 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pand %%xmm15, %%xmm8 ;\n" - "pand %%xmm15, %%xmm9 ;\n" - "pand %%xmm15, %%xmm10 ;\n" - "pand %%xmm15, %%xmm11 ;\n" - "por %%xmm6, %%xmm0 ;\n" - "por %%xmm7, %%xmm1 ;\n" - "por %%xmm8, %%xmm2 ;\n" - "por %%xmm9, %%xmm3 ;\n" - "por %%xmm10, %%xmm4 ;\n" - "por %%xmm11, %%xmm5 ;\n" - - /* conditionally swap ysubx and xaddy */ - "movq %3, %%rax ;\n" - "xorq $1, %%rax ;\n" - "movd %%rax, %%xmm14 ;\n" - "pxor %%xmm15, %%xmm15 ;\n" - "pshufd $0x00, %%xmm14, %%xmm14 ;\n" - "pxor %%xmm0, %%xmm2 ;\n" - "pxor %%xmm1, %%xmm3 ;\n" - "pcmpeqd %%xmm14, %%xmm15 ;\n" - "movdqa %%xmm2, %%xmm6 ;\n" - "movdqa %%xmm3, %%xmm7 ;\n" - "pand %%xmm15, %%xmm6 ;\n" - "pand %%xmm15, %%xmm7 ;\n" - "pxor %%xmm6, %%xmm0 ;\n" - "pxor %%xmm7, %%xmm1 ;\n" - "pxor %%xmm0, %%xmm2 ;\n" - "pxor %%xmm1, %%xmm3 ;\n" - - /* store ysubx */ - "movq $0x7ffffffffffff, %%rax ;\n" - "movd %%xmm0, %%rcx ;\n" - "movd %%xmm0, %%r8 ;\n" - "movd %%xmm1, %%rsi ;\n" - "pshufd $0xee, %%xmm0, %%xmm0 ;\n" - "pshufd $0xee, %%xmm1, %%xmm1 ;\n" - "movd %%xmm0, %%rdx ;\n" - "movd %%xmm1, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "andq %%rax, %%rcx ;\n" - "andq %%rax, %%r8 ;\n" - "andq %%rax, %%rdx ;\n" - "andq %%rax, %%rsi ;\n" - "andq %%rax, %%rdi ;\n" - "movq %%rcx, 0(%2) ;\n" - "movq %%r8, 8(%2) ;\n" - "movq %%rdx, 16(%2) ;\n" - "movq %%rsi, 24(%2) ;\n" - "movq %%rdi, 32(%2) ;\n" - - /* store xaddy */ - "movq $0x7ffffffffffff, %%rax ;\n" - "movd %%xmm2, %%rcx ;\n" - "movd %%xmm2, %%r8 ;\n" - "movd %%xmm3, %%rsi ;\n" - "pshufd $0xee, %%xmm2, %%xmm2 ;\n" - "pshufd $0xee, %%xmm3, %%xmm3 ;\n" - "movd %%xmm2, %%rdx ;\n" - "movd %%xmm3, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "andq %%rax, %%rcx ;\n" - "andq %%rax, %%r8 ;\n" - "andq %%rax, %%rdx ;\n" - "andq %%rax, %%rsi ;\n" - "andq %%rax, %%rdi ;\n" - "movq %%rcx, 40(%2) ;\n" - "movq %%r8, 48(%2) ;\n" - "movq %%rdx, 56(%2) ;\n" - "movq %%rsi, 64(%2) ;\n" - "movq %%rdi, 72(%2) ;\n" - - /* extract t2d */ - "movq $0x7ffffffffffff, %%rax ;\n" - "movd %%xmm4, %%rcx ;\n" - "movd %%xmm4, %%r8 ;\n" - "movd %%xmm5, %%rsi ;\n" - "pshufd $0xee, %%xmm4, %%xmm4 ;\n" - "pshufd $0xee, %%xmm5, %%xmm5 ;\n" - "movd %%xmm4, %%rdx ;\n" - "movd %%xmm5, %%rdi ;\n" - "shrdq $51, %%rdx, %%r8 ;\n" - "shrdq $38, %%rsi, %%rdx ;\n" - "shrdq $25, %%rdi, %%rsi ;\n" - "shrq $12, %%rdi ;\n" - "andq %%rax, %%rcx ;\n" - "andq %%rax, %%r8 ;\n" - "andq %%rax, %%rdx ;\n" - "andq %%rax, %%rsi ;\n" - "andq %%rax, %%rdi ;\n" - - /* conditionally negate t2d */ - "movq %3, %%rax ;\n" - "movq $0xfffffffffffda, %%r9 ;\n" - "movq $0xffffffffffffe, %%r10 ;\n" - "movq %%r10, %%r11 ;\n" - "movq %%r10, %%r12 ;\n" - "movq %%r10, %%r13 ;\n" - "subq %%rcx, %%r9 ;\n" - "subq %%r8, %%r10 ;\n" - "subq %%rdx, %%r11 ;\n" - "subq %%rsi, %%r12 ;\n" - "subq %%rdi, %%r13 ;\n" - "cmpq $1, %%rax ;\n" - "cmove %%r9, %%rcx ;\n" - "cmove %%r10, %%r8 ;\n" - "cmove %%r11, %%rdx ;\n" - "cmove %%r12, %%rsi ;\n" - "cmove %%r13, %%rdi ;\n" - - /* store t2d */ - "movq %%rcx, 80(%2) ;\n" - "movq %%r8, 88(%2) ;\n" - "movq %%rdx, 96(%2) ;\n" - "movq %%rsi, 104(%2) ;\n" - "movq %%rdi, 112(%2) ;\n" - : - : "m"(u), "r"(&table[pos * 8]), "r"(t), "m"(sign) /* %0 = u, %1 = table, %2 = t, %3 = sign */ - : - "%rax", "%rcx", "%rdx", "%rdi", "%rsi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", - "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm14", "%xmm14", - "cc", "memory" - ); -} - -#endif /* defined(ED25519_GCC_64BIT_X86_CHOOSE) */ - diff --git a/external/ed25519-donna/ed25519-donna-basepoint-table.h b/external/ed25519-donna/ed25519-donna-basepoint-table.h deleted file mode 100644 index 41dcd526a2..0000000000 --- a/external/ed25519-donna/ed25519-donna-basepoint-table.h +++ /dev/null @@ -1,259 +0,0 @@ -/* multiples of the base point in packed {ysubx, xaddy, t2d} form */ -static const uint8_t ALIGN(16) ge25519_niels_base_multiples[256][96] = { - {0x3e,0x91,0x40,0xd7,0x05,0x39,0x10,0x9d,0xb3,0xbe,0x40,0xd1,0x05,0x9f,0x39,0xfd,0x09,0x8a,0x8f,0x68,0x34,0x84,0xc1,0xa5,0x67,0x12,0xf8,0x98,0x92,0x2f,0xfd,0x44,0x85,0x3b,0x8c,0xf5,0xc6,0x93,0xbc,0x2f,0x19,0x0e,0x8c,0xfb,0xc6,0x2d,0x93,0xcf,0xc2,0x42,0x3d,0x64,0x98,0x48,0x0b,0x27,0x65,0xba,0xd4,0x33,0x3a,0x9d,0xcf,0x07,0x59,0xbb,0x6f,0x4b,0x67,0x15,0xbd,0xdb,0xea,0xa5,0xa2,0xee,0x00,0x3f,0xe1,0x41,0xfa,0xc6,0x57,0xc9,0x1c,0x9d,0xd4,0xcd,0xca,0xec,0x16,0xaf,0x1f,0xbe,0x0e,0x4f}, - {0xa8,0xd5,0xb4,0x42,0x60,0xa5,0x99,0x8a,0xf6,0xac,0x60,0x4e,0x0c,0x81,0x2b,0x8f,0xaa,0x37,0x6e,0xb1,0x6b,0x23,0x9e,0xe0,0x55,0x25,0xc9,0x69,0xa6,0x95,0xb5,0x6b,0xd7,0x71,0x3c,0x93,0xfc,0xe7,0x24,0x92,0xb5,0xf5,0x0f,0x7a,0x96,0x9d,0x46,0x9f,0x02,0x07,0xd6,0xe1,0x65,0x9a,0xa6,0x5a,0x2e,0x2e,0x7d,0xa8,0x3f,0x06,0x0c,0x59,0x02,0x68,0xd3,0xda,0xaa,0x7e,0x34,0x6e,0x05,0x48,0xee,0x83,0x93,0x59,0xf3,0xba,0x26,0x68,0x07,0xe6,0x10,0xbe,0xca,0x3b,0xb8,0xd1,0x5e,0x16,0x0a,0x4f,0x31,0x49}, - {0x65,0xd2,0xfc,0xa4,0xe8,0x1f,0x61,0x56,0x7d,0xba,0xc1,0xe5,0xfd,0x53,0xd3,0x3b,0xbd,0xd6,0x4b,0x21,0x1a,0xf3,0x31,0x81,0x62,0xda,0x5b,0x55,0x87,0x15,0xb9,0x2a,0x30,0x97,0xee,0x4c,0xa8,0xb0,0x25,0xaf,0x8a,0x4b,0x86,0xe8,0x30,0x84,0x5a,0x02,0x32,0x67,0x01,0x9f,0x02,0x50,0x1b,0xc1,0xf4,0xf8,0x80,0x9a,0x1b,0x4e,0x16,0x7a,0x34,0x48,0x67,0xf1,0xf4,0x11,0xf2,0x9b,0x95,0xf8,0x2d,0xf6,0x17,0x6b,0x4e,0xb8,0x4e,0x2a,0x72,0x5b,0x07,0x6f,0xde,0xd7,0x21,0x2a,0xbb,0x63,0xb9,0x04,0x9a,0x54}, - {0xbf,0x18,0x68,0x05,0x0a,0x05,0xfe,0x95,0xa9,0xfa,0x60,0x56,0x71,0x89,0x7e,0x32,0x73,0x50,0xa0,0x06,0xcd,0xe3,0xe8,0xc3,0x9a,0xa4,0x45,0x74,0x4c,0x3f,0x93,0x27,0x9f,0x09,0xfc,0x8e,0xb9,0x51,0x73,0x28,0x38,0x25,0xfd,0x7d,0xf4,0xc6,0x65,0x67,0x65,0x92,0x0a,0xfb,0x3d,0x8d,0x34,0xca,0x27,0x87,0xe5,0x21,0x03,0x91,0x0e,0x68,0xb0,0x26,0x14,0xe5,0xec,0x45,0x1e,0xbf,0x94,0x0f,0xba,0x6d,0x3d,0xc6,0x2b,0xe3,0xc0,0x52,0xf8,0x8c,0xd5,0x74,0x29,0xe4,0x18,0x4c,0xe6,0xb0,0xb1,0x79,0xf0,0x44}, - {0xba,0xd6,0x47,0xa4,0xc3,0x82,0x91,0x7f,0xb7,0x29,0x27,0x4b,0xd1,0x14,0x00,0xd5,0x87,0xa0,0x64,0xb8,0x1c,0xf1,0x3c,0xe3,0xf3,0x55,0x1b,0xeb,0x73,0x7e,0x4a,0x15,0x33,0xbb,0xa5,0x08,0x44,0xbc,0x12,0xa2,0x02,0xed,0x5e,0xc7,0xc3,0x48,0x50,0x8d,0x44,0xec,0xbf,0x5a,0x0c,0xeb,0x1b,0xdd,0xeb,0x06,0xe2,0x46,0xf1,0xcc,0x45,0x29,0xb3,0x03,0xd0,0xe7,0x79,0xa1,0x32,0xc8,0x7e,0x4d,0x12,0x00,0x0a,0x9d,0x72,0x5f,0xf3,0x8f,0x6d,0x0e,0xa1,0xd4,0xc1,0x62,0x98,0x7a,0xb2,0x38,0x59,0xac,0xb8,0x68}, - {0xa4,0x8c,0x7d,0x7b,0xb6,0x06,0x98,0x49,0x39,0x27,0xd2,0x27,0x84,0xe2,0x5b,0x57,0xb9,0x53,0x45,0x20,0xe7,0x5c,0x08,0xbb,0x84,0x78,0x41,0xae,0x41,0x4c,0xb6,0x38,0x31,0x71,0x15,0x77,0xeb,0xee,0x0c,0x3a,0x88,0xaf,0xc8,0x00,0x89,0x15,0x27,0x9b,0x36,0xa7,0x59,0xda,0x68,0xb6,0x65,0x80,0xbd,0x38,0xcc,0xa2,0xb6,0x7b,0xe5,0x51,0xa4,0xe3,0x9d,0x68,0x91,0xad,0x9d,0x8f,0x37,0x91,0xfb,0xf8,0x28,0x24,0x5f,0x17,0x88,0xb9,0xcf,0x9f,0x32,0xb5,0x0a,0x05,0x9f,0xc0,0x54,0x13,0xa2,0xdf,0x65,0x78}, - {0xb1,0x21,0x32,0xaa,0x9a,0x2c,0x6f,0xba,0xa7,0x23,0xba,0x3b,0x53,0x21,0xa0,0x6c,0x3a,0x2c,0x19,0x92,0x4f,0x76,0xea,0x9d,0xe0,0x17,0x53,0x2e,0x5d,0xdd,0x6e,0x1d,0xbf,0xa3,0x4e,0x94,0xd0,0x5c,0x1a,0x6b,0xd2,0xc0,0x9d,0xb3,0x3a,0x35,0x70,0x74,0x49,0x2e,0x54,0x28,0x82,0x52,0xb2,0x71,0x7e,0x92,0x3c,0x28,0x69,0xea,0x1b,0x46,0x36,0xda,0x0f,0xab,0xac,0x8a,0x7a,0x21,0xc8,0x49,0x35,0x3d,0x54,0xc6,0x28,0xa5,0x68,0x75,0xab,0x13,0x8b,0x5b,0xd0,0x37,0x37,0xbc,0x2c,0x3a,0x62,0xef,0x3c,0x23}, - {0xd9,0x34,0x92,0xf3,0xed,0x5d,0xa7,0xe2,0xf9,0x58,0xb5,0xe1,0x80,0x76,0x3d,0x96,0xfb,0x23,0x3c,0x6e,0xac,0x41,0x27,0x2c,0xc3,0x01,0x0e,0x32,0xa1,0x24,0x90,0x3a,0x8f,0x3e,0xdd,0x04,0x66,0x59,0xb7,0x59,0x2c,0x70,0x88,0xe2,0x77,0x03,0xb3,0x6c,0x23,0xc3,0xd9,0x5e,0x66,0x9c,0x33,0xb1,0x2f,0xe5,0xbc,0x61,0x60,0xe7,0x15,0x09,0x7e,0xa3,0x34,0xa8,0x35,0xe8,0x7d,0xdf,0xea,0x57,0x98,0x68,0xda,0x9c,0xe1,0x8b,0x26,0xb3,0x67,0x71,0x36,0x85,0x11,0x2c,0xc2,0xd5,0xef,0xdb,0xd9,0xb3,0x9e,0x58}, - {0x5e,0x51,0xaa,0x49,0x54,0x63,0x5b,0xed,0x3a,0x82,0xc6,0x0b,0x9f,0xc4,0x65,0xa8,0xc4,0xd1,0x42,0x5b,0xe9,0x1f,0x0c,0x85,0xb9,0x15,0xd3,0x03,0x6f,0x6d,0xd7,0x30,0x1d,0x9c,0x2f,0x63,0x0e,0xdd,0xcc,0x2e,0x15,0x31,0x89,0x76,0x96,0xb6,0xd0,0x51,0x58,0x7a,0x63,0xa8,0x6b,0xb7,0xdf,0x52,0x39,0xef,0x0e,0xa0,0x49,0x7d,0xd3,0x6d,0xc7,0xe4,0x06,0x21,0x17,0x44,0x44,0x6c,0x69,0x7f,0x8d,0x92,0x80,0xd6,0x53,0xfb,0x26,0x3f,0x4d,0x69,0xa4,0x9e,0x73,0xb4,0xb0,0x4b,0x86,0x2e,0x11,0x97,0xc6,0x10}, - {0xde,0x5f,0xbe,0x7d,0x27,0xc4,0x93,0x64,0xa2,0x7e,0xad,0x19,0xad,0x4f,0x5d,0x26,0x90,0x45,0x30,0x46,0xc8,0xdf,0x00,0x0e,0x09,0xfe,0x66,0xed,0xab,0x1c,0xe6,0x25,0x05,0xc8,0x58,0x83,0xa0,0x2a,0xa6,0x0c,0x47,0x42,0x20,0x7a,0xe3,0x4a,0x3d,0x6a,0xdc,0xed,0x11,0x3b,0xa6,0xd3,0x64,0x74,0xef,0x06,0x08,0x55,0xaf,0x9b,0xbf,0x03,0x04,0x66,0x58,0xcc,0x28,0xe1,0x13,0x3f,0x7e,0x74,0x59,0xb4,0xec,0x73,0x58,0x6f,0xf5,0x68,0x12,0xcc,0xed,0x3d,0xb6,0xa0,0x2c,0xe2,0x86,0x45,0x63,0x78,0x6d,0x56}, - {0x34,0x08,0xc1,0x9c,0x9f,0xa4,0x37,0x16,0x51,0xc4,0x9b,0xa8,0xd5,0x56,0x8e,0xbc,0xdb,0xd2,0x7f,0x7f,0x0f,0xec,0xb5,0x1c,0xd9,0x35,0xcc,0x5e,0xca,0x5b,0x97,0x33,0xd0,0x2f,0x5a,0xc6,0x85,0x42,0x05,0xa1,0xc3,0x67,0x16,0xf3,0x2a,0x11,0x64,0x6c,0x58,0xee,0x1a,0x73,0x40,0xe2,0x0a,0x68,0x2a,0xb2,0x93,0x47,0xf3,0xa5,0xfb,0x14,0xd4,0xf7,0x85,0x69,0x16,0x46,0xd7,0x3c,0x57,0x00,0xc8,0xc9,0x84,0x5e,0x3e,0x59,0x1e,0x13,0x61,0x7b,0xb6,0xf2,0xc3,0x2f,0x6c,0x52,0xfc,0x83,0xea,0x9c,0x82,0x14}, - {0xc2,0x95,0xdd,0x97,0x84,0x7b,0x43,0xff,0xa7,0xb5,0x4e,0xaa,0x30,0x4e,0x74,0x6c,0x8b,0xe8,0x85,0x3c,0x61,0x5d,0x0c,0x9e,0x73,0x81,0x75,0x5f,0x1e,0xc7,0xd9,0x2f,0xb8,0xec,0x71,0x4e,0x2f,0x0b,0xe7,0x21,0xe3,0x77,0xa4,0x40,0xb9,0xdd,0x56,0xe6,0x80,0x4f,0x1d,0xce,0xce,0x56,0x65,0xbf,0x7e,0x7b,0x5d,0x53,0xc4,0x3b,0xfc,0x05,0xdd,0xde,0xaf,0x52,0xae,0xb3,0xb8,0x24,0xcf,0x30,0x3b,0xed,0x8c,0x63,0x95,0x34,0x95,0x81,0xbe,0xa9,0x83,0xbc,0xa4,0x33,0x04,0x1f,0x65,0x5c,0x47,0x67,0x37,0x37}, - {0xd9,0xad,0xd1,0x40,0xfd,0x99,0xba,0x2f,0x27,0xd0,0xf4,0x96,0x6f,0x16,0x07,0xb3,0xae,0x3b,0xf0,0x15,0x52,0xf0,0x63,0x43,0x99,0xf9,0x18,0x3b,0x6c,0xa5,0xbe,0x1f,0x90,0x65,0x24,0x14,0xcb,0x95,0x40,0x63,0x35,0x55,0xc1,0x16,0x40,0x14,0x12,0xef,0x60,0xbc,0x10,0x89,0x0c,0x14,0x38,0x9e,0x8c,0x7c,0x90,0x30,0x57,0x90,0xf5,0x6b,0x8a,0x5b,0x41,0xe1,0xf1,0x78,0xa7,0x0f,0x7e,0xa7,0xc3,0xba,0xf7,0x9f,0x40,0x06,0x50,0x9a,0xa2,0x9a,0xb8,0xd7,0x52,0x6f,0x56,0x5a,0x63,0x7a,0xf6,0x1c,0x52,0x02}, - {0x94,0x52,0x9d,0x0a,0x0b,0xee,0x3f,0x51,0x66,0x5a,0xdf,0x0f,0x5c,0xe7,0x98,0x8f,0xce,0x07,0xe1,0xbf,0x88,0x86,0x61,0xd4,0xed,0x2c,0x38,0x71,0x7e,0x0a,0xa0,0x3f,0xe4,0x5e,0x2f,0x77,0x20,0x67,0x14,0xb1,0xce,0x9a,0x07,0x96,0xb1,0x94,0xf8,0xe8,0x4a,0x82,0xac,0x00,0x4d,0x22,0xf8,0x4a,0xc4,0x6c,0xcd,0xf7,0xd9,0x53,0x17,0x00,0x34,0xdb,0x3d,0x96,0x2d,0x23,0x69,0x3c,0x58,0x38,0x97,0xb4,0xda,0x87,0xde,0x1d,0x85,0xf2,0x91,0xa0,0xf9,0xd1,0xd7,0xaa,0xb6,0xed,0x48,0xa0,0x2f,0xfe,0xb5,0x12}, - {0x4d,0xe3,0xfc,0x96,0xc4,0xfb,0xf0,0x71,0xed,0x5b,0xf3,0xad,0x6b,0x82,0xb9,0x73,0x61,0xc5,0x28,0xff,0x61,0x72,0x04,0xd2,0x6f,0x20,0xb1,0x6f,0xf9,0x76,0x9b,0x74,0x92,0x1e,0x6f,0xad,0x26,0x7c,0x2b,0xdf,0x13,0x89,0x4b,0x50,0x23,0xd3,0x66,0x4b,0xc3,0x8b,0x1c,0x75,0xc0,0x9d,0x40,0x8c,0xb8,0xc7,0x96,0x07,0xc2,0x93,0x7e,0x6f,0x05,0xae,0xa6,0xae,0x04,0xf6,0x5a,0x1f,0x99,0x9c,0xe4,0xbe,0xf1,0x51,0x23,0xc1,0x66,0x6b,0xff,0xee,0xb5,0x08,0xa8,0x61,0x51,0x21,0xe0,0x01,0x0f,0xc1,0xce,0x0f}, - {0x44,0x1e,0xfe,0x49,0xa6,0x58,0x4d,0x64,0x7e,0x77,0xad,0x31,0xa2,0xae,0xfc,0x21,0xd2,0xd0,0x7f,0x88,0x5a,0x1c,0x44,0x02,0xf3,0x11,0xc5,0x83,0x71,0xaa,0x01,0x49,0x45,0x4e,0x24,0xc4,0x9d,0xd2,0xf2,0x3d,0x0a,0xde,0xd8,0x93,0x74,0x0e,0x02,0x2b,0x4d,0x21,0x0c,0x82,0x7e,0x06,0xc8,0x6c,0x0a,0xb9,0xea,0x6f,0x16,0x79,0x37,0x41,0xf0,0xf8,0x1a,0x8c,0x54,0xb7,0xb1,0x08,0xb4,0x99,0x62,0x24,0x7c,0x7a,0x0f,0xce,0x39,0xd9,0x06,0x1e,0xf9,0xb0,0x60,0xf7,0x13,0x12,0x6d,0x72,0x7b,0x88,0xbb,0x41}, - {0xbe,0x46,0x43,0x74,0x44,0x7d,0xe8,0x40,0x25,0x2b,0xb5,0x15,0xd4,0xda,0x48,0x1d,0x3e,0x60,0x3b,0xa1,0x18,0x8a,0x3a,0x7c,0xf7,0xbd,0xcd,0x2f,0xc1,0x28,0xb7,0x4e,0xae,0x91,0x66,0x7c,0x59,0x4c,0x23,0x7e,0xc8,0xb4,0x85,0x0a,0x3d,0x9d,0x88,0x64,0xe7,0xfa,0x4a,0x35,0x0c,0xc9,0xe2,0xda,0x1d,0x9e,0x6a,0x0c,0x07,0x1e,0x87,0x0a,0x89,0x89,0xbc,0x4b,0x99,0xb5,0x01,0x33,0x60,0x42,0xdd,0x5b,0x3a,0xae,0x6b,0x73,0x3c,0x9e,0xd5,0x19,0xe2,0xad,0x61,0x0d,0x64,0xd4,0x85,0x26,0x0f,0x30,0xe7,0x3e}, - {0xb7,0xd6,0x7d,0x9e,0xe4,0x55,0xd2,0xf5,0xac,0x1e,0x0b,0x61,0x5c,0x11,0x16,0x80,0xca,0x87,0xe1,0x92,0x5d,0x97,0x99,0x3c,0xc2,0x25,0x91,0x97,0x62,0x57,0x81,0x13,0x18,0x75,0x1e,0x84,0x47,0x79,0xfa,0x43,0xd7,0x46,0x9c,0x63,0x59,0xfa,0xc6,0xe5,0x74,0x2b,0x05,0xe3,0x1d,0x5e,0x06,0xa1,0x30,0x90,0xb8,0xcf,0xa2,0xc6,0x47,0x7d,0xe0,0xd6,0xf0,0x8e,0x14,0xd0,0xda,0x3f,0x3c,0x6f,0x54,0x91,0x9a,0x74,0x3e,0x9d,0x57,0x81,0xbb,0x26,0x10,0x62,0xec,0x71,0x80,0xec,0xc9,0x34,0x8d,0xf5,0x8c,0x14}, - {0x27,0xf0,0x34,0x79,0xf6,0x92,0xa4,0x46,0xa9,0x0a,0x84,0xf6,0xbe,0x84,0x99,0x46,0x54,0x18,0x61,0x89,0x2a,0xbc,0xa1,0x5c,0xd4,0xbb,0x5d,0xbd,0x1e,0xfa,0xf2,0x3f,0x6d,0x75,0xe4,0x9a,0x7d,0x2f,0x57,0xe2,0x7f,0x48,0xf3,0x88,0xbb,0x45,0xc3,0x56,0x8d,0xa8,0x60,0x69,0x6d,0x0b,0xd1,0x9f,0xb9,0xa1,0xae,0x4e,0xad,0xeb,0x8f,0x27,0x66,0x39,0x93,0x8c,0x1f,0x68,0xaa,0xb1,0x98,0x0c,0x29,0x20,0x9c,0x94,0x21,0x8c,0x52,0x3c,0x9d,0x21,0x91,0x52,0x11,0x39,0x7b,0x67,0x9c,0xfe,0x02,0xdd,0x04,0x41}, - {0x2a,0x42,0x24,0x11,0x5e,0xbf,0xb2,0x72,0xb5,0x3a,0xa3,0x98,0x33,0x0c,0xfa,0xa1,0x66,0xb6,0x52,0xfa,0x01,0x61,0xcb,0x94,0xd5,0x53,0xaf,0xaf,0x00,0x3b,0x86,0x2c,0xb8,0x6a,0x09,0xdb,0x06,0x4e,0x21,0x81,0x35,0x4f,0xe4,0x0c,0xc9,0xb6,0xa8,0x21,0xf5,0x2a,0x9e,0x40,0x2a,0xc1,0x24,0x65,0x81,0xa4,0xfc,0x8e,0xa4,0xb5,0x65,0x01,0x76,0x6a,0x84,0xa0,0x74,0xa4,0x90,0xf1,0xc0,0x7c,0x2f,0xcd,0x84,0xf9,0xef,0x12,0x8f,0x2b,0xaa,0x58,0x06,0x29,0x5e,0x69,0xb8,0xc8,0xfe,0xbf,0xd9,0x67,0x1b,0x59}, - {0xfa,0x9b,0xb4,0x80,0x1c,0x0d,0x2f,0x31,0x8a,0xec,0xf3,0xab,0x5e,0x51,0x79,0x59,0x88,0x1c,0xf0,0x9e,0xc0,0x33,0x70,0x72,0xcb,0x7b,0x8f,0xca,0xc7,0x2e,0xe0,0x3d,0x5d,0xb5,0x18,0x9f,0x71,0xb3,0xb9,0x99,0x1e,0x64,0x8c,0xa1,0xfa,0xe5,0x65,0xe4,0xed,0x05,0x9f,0xc2,0x36,0x11,0x08,0x61,0x8b,0x12,0x30,0x70,0x86,0x4f,0x9b,0x48,0xef,0x92,0xeb,0x3a,0x2d,0x10,0x32,0xd2,0x61,0xa8,0x16,0x61,0xb4,0x53,0x62,0xe1,0x24,0xaa,0x0b,0x19,0xe7,0xab,0x7e,0x3d,0xbf,0xbe,0x6c,0x49,0xba,0xfb,0xf5,0x49}, - {0xd4,0xcf,0x5b,0x8a,0x10,0x9a,0x94,0x30,0xeb,0x73,0x64,0xbc,0x70,0xdd,0x40,0xdc,0x1c,0x0d,0x7c,0x30,0xc1,0x94,0xc2,0x92,0x74,0x6e,0xfa,0xcb,0x6d,0xa8,0x04,0x56,0x2e,0x57,0x9c,0x1e,0x8c,0x62,0x5d,0x15,0x41,0x47,0x88,0xc5,0xac,0x86,0x4d,0x8a,0xeb,0x63,0x57,0x51,0xf6,0x52,0xa3,0x91,0x5b,0x51,0x67,0x88,0xc2,0xa6,0xa1,0x06,0xb6,0x64,0x17,0x7c,0xd4,0xd1,0x88,0x72,0x51,0x8b,0x41,0xe0,0x40,0x11,0x54,0x72,0xd1,0xf6,0xac,0x18,0x60,0x1a,0x03,0x9f,0xc6,0x42,0x27,0xfe,0x89,0x9e,0x98,0x20}, - {0x7f,0xcc,0x2d,0x3a,0xfd,0x77,0x97,0x49,0x92,0xd8,0x4f,0xa5,0x2c,0x7c,0x85,0x32,0xa0,0xe3,0x07,0xd2,0x64,0xd8,0x79,0xa2,0x29,0x7e,0xa6,0x0c,0x1d,0xed,0x03,0x04,0x2e,0xec,0xea,0x85,0x8b,0x27,0x74,0x16,0xdf,0x2b,0xcb,0x7a,0x07,0xdc,0x21,0x56,0x5a,0xf4,0xcb,0x61,0x16,0x4c,0x0a,0x64,0xd3,0x95,0x05,0xf7,0x50,0x99,0x0b,0x73,0x52,0xc5,0x4e,0x87,0x35,0x2d,0x4b,0xc9,0x8d,0x6f,0x24,0x98,0xcf,0xc8,0xe6,0xc5,0xce,0x35,0xc0,0x16,0xfa,0x46,0xcb,0xf7,0xcc,0x3d,0x30,0x08,0x43,0x45,0xd7,0x5b}, - {0xc2,0x4c,0xb2,0x28,0x95,0xd1,0x9a,0x7f,0x81,0xc1,0x35,0x63,0x65,0x54,0x6b,0x7f,0x36,0x72,0xc0,0x4f,0x6e,0xb6,0xb8,0x66,0x83,0xad,0x80,0x73,0x00,0x78,0x3a,0x13,0x2a,0x79,0xe7,0x15,0x21,0x93,0xc4,0x85,0xc9,0xdd,0xcd,0xbd,0xa2,0x89,0x4c,0xc6,0x62,0xd7,0xa3,0xad,0xa8,0x3d,0x1e,0x9d,0x2c,0xf8,0x67,0x30,0x12,0xdb,0xb7,0x5b,0xbe,0x62,0xca,0xc6,0x67,0xf4,0x61,0x09,0xee,0x52,0x19,0x21,0xd6,0x21,0xec,0x04,0x70,0x47,0xd5,0x9b,0x77,0x60,0x23,0x18,0xd2,0xe0,0xf0,0x58,0x6d,0xca,0x0d,0x74}, - {0x4e,0xce,0xcf,0x52,0x07,0xee,0x48,0xdf,0xb7,0x08,0xec,0x06,0xf3,0xfa,0xff,0xc3,0xc4,0x59,0x54,0xb9,0x2a,0x0b,0x71,0x05,0x8d,0xa3,0x3e,0x96,0xfa,0x25,0x1d,0x16,0x3c,0x43,0x78,0x04,0x57,0x8c,0x1a,0x23,0x9d,0x43,0x81,0xc2,0x0e,0x27,0xb5,0xb7,0x9f,0x07,0xd9,0xe3,0xea,0x99,0xaa,0xdb,0xd9,0x03,0x2b,0x6c,0x25,0xf5,0x03,0x2c,0x7d,0xa4,0x53,0x7b,0x75,0x18,0x0f,0x79,0x79,0x58,0x0c,0xcf,0x30,0x01,0x7b,0x30,0xf9,0xf7,0x7e,0x25,0x77,0x3d,0x90,0x31,0xaf,0xbb,0x96,0xbd,0xbd,0x68,0x94,0x69}, - {0xcf,0xfe,0xda,0xf4,0x46,0x2f,0x1f,0xbd,0xf7,0xd6,0x7f,0xa4,0x14,0x01,0xef,0x7c,0x7f,0xb3,0x47,0x4a,0xda,0xfd,0x1f,0xd3,0x85,0x57,0x90,0x73,0xa4,0x19,0x52,0x52,0x48,0x19,0xa9,0x6a,0xe6,0x3d,0xdd,0xd8,0xcc,0xd2,0xc0,0x2f,0xc2,0x64,0x50,0x48,0x2f,0xea,0xfd,0x34,0x66,0x24,0x48,0x9b,0x3a,0x2e,0x4a,0x6c,0x4e,0x1c,0x3e,0x29,0xe1,0x12,0x51,0x92,0x4b,0x13,0x6e,0x37,0xa0,0x5d,0xa1,0xdc,0xb5,0x78,0x37,0x70,0x11,0x31,0x1c,0x46,0xaf,0x89,0x45,0xb0,0x23,0x28,0x03,0x7f,0x44,0x5c,0x60,0x5b}, - {0x89,0x7c,0xc4,0x20,0x59,0x80,0x65,0xb9,0xcc,0x8f,0x3b,0x92,0x0c,0x10,0xf0,0xe7,0x77,0xef,0xe2,0x02,0x65,0x25,0x01,0x00,0xee,0xb3,0xae,0xa8,0xce,0x6d,0xa7,0x24,0x4c,0xf0,0xe7,0xf0,0xc6,0xfe,0xe9,0x3b,0x62,0x49,0xe3,0x75,0x9e,0x57,0x6a,0x86,0x1a,0xe6,0x1d,0x1e,0x16,0xef,0x42,0x55,0xd5,0xbd,0x5a,0xcc,0xf4,0xfe,0x12,0x2f,0x40,0xc7,0xc0,0xdf,0xb2,0x22,0x45,0x0a,0x07,0xa4,0xc9,0x40,0x7f,0x6e,0xd0,0x10,0x68,0xf6,0xcf,0x78,0x41,0x14,0xcf,0xc6,0x90,0x37,0xa4,0x18,0x25,0x7b,0x60,0x5e}, - {0x18,0x18,0xdf,0x6c,0x8f,0x1d,0xb3,0x58,0xa2,0x58,0x62,0xc3,0x4f,0xa7,0xcf,0x35,0x6e,0x1d,0xe6,0x66,0x4f,0xff,0xb3,0xe1,0xf7,0xd5,0xcd,0x6c,0xab,0xac,0x67,0x50,0x14,0xcf,0x96,0xa5,0x1c,0x43,0x2c,0xa0,0x00,0xe4,0xd3,0xae,0x40,0x2d,0xc4,0xe3,0xdb,0x26,0x0f,0x2e,0x80,0x26,0x45,0xd2,0x68,0x70,0x45,0x9e,0x13,0x33,0x1f,0x20,0x51,0x9d,0x03,0x08,0x6b,0x7f,0x52,0xfd,0x06,0x00,0x7c,0x01,0x64,0x49,0xb1,0x18,0xa8,0xa4,0x25,0x2e,0xb0,0x0e,0x22,0xd5,0x75,0x03,0x46,0x62,0x88,0xba,0x7c,0x39}, - {0xb2,0x59,0x59,0xf0,0x93,0x30,0xc1,0x30,0x76,0x79,0xa9,0xe9,0x8d,0xa1,0x3a,0xe2,0x26,0x5e,0x1d,0x72,0x91,0xd4,0x2f,0x22,0x3a,0x6c,0x6e,0x76,0x20,0xd3,0x39,0x23,0xe7,0x79,0x13,0xc8,0xfb,0xc3,0x15,0x78,0xf1,0x2a,0xe1,0xdd,0x20,0x94,0x61,0xa6,0xd5,0xfd,0xa8,0x85,0xf8,0xc0,0xa9,0xff,0x52,0xc2,0xe1,0xc1,0x22,0x40,0x1b,0x77,0xa7,0x2f,0x3a,0x51,0x86,0xd9,0x7d,0xd8,0x08,0xcf,0xd4,0xf9,0x71,0x9b,0xac,0xf5,0xb3,0x83,0xa2,0x1e,0x1b,0xc3,0x6b,0xd0,0x76,0x1a,0x97,0x19,0x92,0x18,0x1a,0x33}, - {0xc6,0x80,0x4f,0xfb,0x45,0x6f,0x16,0xf5,0xcf,0x75,0xc7,0x61,0xde,0xc7,0x36,0x9c,0x1c,0xd9,0x41,0x90,0x1b,0xe8,0xd4,0xe3,0x21,0xfe,0xbd,0x83,0x6b,0x7c,0x16,0x31,0xaf,0x72,0x75,0x9d,0x3a,0x2f,0x51,0x26,0x9e,0x4a,0x07,0x68,0x88,0xe2,0xcb,0x5b,0xc4,0xf7,0x80,0x11,0xc1,0xc1,0xed,0x84,0x7b,0xa6,0x49,0xf6,0x9f,0x61,0xc9,0x1a,0x68,0x10,0x4b,0x52,0x42,0x38,0x2b,0xf2,0x87,0xe9,0x9c,0xee,0x3b,0x34,0x68,0x50,0xc8,0x50,0x62,0x4a,0x84,0x71,0x9d,0xfc,0x11,0xb1,0x08,0x1f,0x34,0x36,0x24,0x61}, - {0x8d,0x89,0x4e,0x87,0xdb,0x41,0x9d,0xd9,0x20,0xdc,0x07,0x6c,0xf1,0xa5,0xfe,0x09,0xbc,0x9b,0x0f,0xd0,0x67,0x2c,0x3d,0x79,0x40,0xff,0x5e,0x9e,0x30,0xe2,0xeb,0x46,0x38,0x26,0x2d,0x1a,0xe3,0x49,0x63,0x8b,0x35,0xfd,0xd3,0x9b,0x00,0xb7,0xdf,0x9d,0xa4,0x6b,0xa0,0xa3,0xb8,0xf1,0x8b,0x7f,0x45,0x04,0xd9,0x78,0x31,0xaa,0x22,0x15,0x38,0x49,0x61,0x69,0x53,0x2f,0x38,0x2c,0x10,0x6d,0x2d,0xb7,0x9a,0x40,0xfe,0xda,0x27,0xf2,0x46,0xb6,0x91,0x33,0xc8,0xe8,0x6c,0x30,0x24,0x05,0xf5,0x70,0xfe,0x45}, - {0x8c,0x0b,0x0c,0x96,0xa6,0x75,0x48,0xda,0x20,0x2f,0x0e,0xef,0x76,0xd0,0x68,0x5b,0xd4,0x8f,0x0b,0x3d,0xcf,0x51,0xfb,0x07,0xd4,0x92,0xe3,0xa0,0x23,0x16,0x8d,0x42,0x91,0x14,0x95,0xc8,0x20,0x49,0xf2,0x62,0xa2,0x0c,0x63,0x3f,0xc8,0x07,0xf0,0x05,0xb8,0xd4,0xc9,0xf5,0xd2,0x45,0xbb,0x6f,0x45,0x22,0x7a,0xb5,0x6d,0x9f,0x61,0x16,0xfd,0x08,0xa3,0x01,0x44,0x4a,0x4f,0x08,0xac,0xca,0xa5,0x76,0xc3,0x19,0x22,0xa8,0x7d,0xbc,0xd1,0x43,0x46,0xde,0xb8,0xde,0xc6,0x38,0xbd,0x60,0x2d,0x59,0x81,0x1d}, - {0x5f,0xac,0x0d,0xa6,0x56,0x87,0x36,0x61,0x57,0xdc,0xab,0xeb,0x6a,0x2f,0xe0,0x17,0x7d,0x0f,0xce,0x4c,0x2d,0x3f,0x19,0x7f,0xf0,0xdc,0xec,0x89,0x77,0x4a,0x23,0x20,0xe8,0xc5,0x85,0x7b,0x9f,0xb6,0x65,0x87,0xb2,0xba,0x68,0xd1,0x8b,0x67,0xf0,0x6f,0x9b,0x0f,0x33,0x1d,0x7c,0xe7,0x70,0x3a,0x7c,0x8e,0xaf,0xb0,0x51,0x6d,0x5f,0x3a,0x52,0xb2,0x78,0x71,0xb6,0x0d,0xd2,0x76,0x60,0xd1,0x1e,0xd5,0xf9,0x34,0x1c,0x07,0x70,0x11,0xe4,0xb3,0x20,0x4a,0x2a,0xf6,0x66,0xe3,0xff,0x3c,0x35,0x82,0xd6,0x7c}, - {0xb6,0xfa,0x87,0xd8,0x5b,0xa4,0xe1,0x0b,0x6e,0x3b,0x40,0xba,0x32,0x6a,0x84,0x2a,0x00,0x60,0x6e,0xe9,0x12,0x10,0x92,0xd9,0x43,0x09,0xdc,0x3b,0x86,0xc8,0x38,0x28,0xf3,0xf4,0xac,0x68,0x60,0xcd,0x65,0xa6,0xd3,0xe3,0xd7,0x3c,0x18,0x2d,0xd9,0x42,0xd9,0x25,0x60,0x33,0x9d,0x38,0x59,0x57,0xff,0xd8,0x2c,0x2b,0x3b,0x25,0xf0,0x3e,0x30,0x50,0x46,0x4a,0xcf,0xb0,0x6b,0xd1,0xab,0x77,0xc5,0x15,0x41,0x6b,0x49,0xfa,0x9d,0x41,0xab,0xf4,0x8a,0xae,0xcf,0x82,0x12,0x28,0xa8,0x06,0xa6,0xb8,0xdc,0x21}, - {0xc8,0x9f,0x9d,0x8c,0x46,0x04,0x60,0x5c,0xcb,0xa3,0x2a,0xd4,0x6e,0x09,0x40,0x25,0x9c,0x2f,0xee,0x12,0x4c,0x4d,0x5b,0x12,0xab,0x1d,0xa3,0x94,0x81,0xd0,0xc3,0x0b,0xba,0x31,0x77,0xbe,0xfa,0x00,0x8d,0x9a,0x89,0x18,0x9e,0x62,0x7e,0x60,0x03,0x82,0x7f,0xd9,0xf3,0x43,0x37,0x02,0xcc,0xb2,0x8b,0x67,0x6f,0x6c,0xbf,0x0d,0x84,0x5d,0x8b,0xe1,0x9f,0x30,0x0d,0x38,0x6e,0x70,0xc7,0x65,0xe1,0xb9,0xa6,0x2d,0xb0,0x6e,0xab,0x20,0xae,0x7d,0x99,0xba,0xbb,0x57,0xdd,0x96,0xc1,0x2a,0x23,0x76,0x42,0x3a}, - {0xfa,0x84,0x70,0x8a,0x2c,0x43,0x42,0x4b,0x45,0xe5,0xb9,0xdf,0xe3,0x19,0x8a,0x89,0x5d,0xe4,0x58,0x9c,0x21,0x00,0x9f,0xbe,0xd1,0xeb,0x6d,0xa1,0xce,0x77,0xf1,0x1f,0xcb,0x7e,0x44,0xdb,0x72,0xc1,0xf8,0x3b,0xbd,0x2d,0x28,0xc6,0x1f,0xc4,0xcf,0x5f,0xfe,0x15,0xaa,0x75,0xc0,0xff,0xac,0x80,0xf9,0xa9,0xe1,0x24,0xe8,0xc9,0x70,0x07,0xfd,0xb5,0xb5,0x45,0x9a,0xd9,0x61,0xcf,0x24,0x79,0x3a,0x1b,0xe9,0x84,0x09,0x86,0x89,0x3e,0x3e,0x30,0x19,0x09,0x30,0xe7,0x1e,0x0b,0x50,0x41,0xfd,0x64,0xf2,0x39}, - {0x9c,0xe2,0xe7,0xdb,0x17,0x34,0xad,0xa7,0x9c,0x13,0x9c,0x2b,0x6a,0x37,0x94,0xbd,0xa9,0x7b,0x59,0x93,0x8e,0x1b,0xe9,0xa0,0x40,0x98,0x88,0x68,0x34,0xd7,0x12,0x17,0xe1,0x7b,0x09,0xfe,0xab,0x4a,0x9b,0xd1,0x29,0x19,0xe0,0xdf,0xe1,0xfc,0x6d,0xa4,0xff,0xf1,0xa6,0x2c,0x94,0x08,0xc9,0xc3,0x4e,0xf1,0x35,0x2c,0x27,0x21,0xc6,0x65,0xdd,0x93,0x31,0xce,0xf8,0x89,0x2b,0xe7,0xbb,0xc0,0x25,0xa1,0x56,0x33,0x10,0x4d,0x83,0xfe,0x1c,0x2e,0x3d,0xa9,0x19,0x04,0x72,0xe2,0x9c,0xb1,0x0a,0x80,0xf9,0x22}, - {0xcb,0xf8,0x9e,0x3e,0x8a,0x36,0x5a,0x60,0x15,0x47,0x50,0xa5,0x22,0xc0,0xe9,0xe3,0x8f,0x24,0x24,0x5f,0xb0,0x48,0x3d,0x55,0xe5,0x26,0x76,0x64,0xcd,0x16,0xf4,0x13,0xac,0xfd,0x6e,0x9a,0xdd,0x9f,0x02,0x42,0x41,0x49,0xa5,0x34,0xbe,0xce,0x12,0xb9,0x7b,0xf3,0xbd,0x87,0xb9,0x64,0x0f,0x64,0xb4,0xca,0x98,0x85,0xd3,0xa4,0x71,0x41,0x8c,0x4c,0xc9,0x99,0xaa,0x58,0x27,0xfa,0x07,0xb8,0x00,0xb0,0x6f,0x6f,0x00,0x23,0x92,0x53,0xda,0xad,0xdd,0x91,0xd2,0xfb,0xab,0xd1,0x4b,0x57,0xfa,0x14,0x82,0x50}, - {0x4b,0xfe,0xd6,0x3e,0x15,0x69,0x02,0xc2,0xc4,0x77,0x1d,0x51,0x39,0x67,0x5a,0xa6,0x94,0xaf,0x14,0x2c,0x46,0x26,0xde,0xcb,0x4b,0xa7,0xab,0x6f,0xec,0x60,0xf9,0x22,0xd6,0x03,0xd0,0x53,0xbb,0x15,0x1a,0x46,0x65,0xc9,0xf3,0xbc,0x88,0x28,0x10,0xb2,0x5a,0x3a,0x68,0x6c,0x75,0x76,0xc5,0x27,0x47,0xb4,0x6c,0xc8,0xa4,0x58,0x77,0x3a,0x76,0x50,0xae,0x93,0xf6,0x11,0x81,0x54,0xa6,0x54,0xfd,0x1d,0xdf,0x21,0xae,0x1d,0x65,0x5e,0x11,0xf3,0x90,0x8c,0x24,0x12,0x94,0xf4,0xe7,0x8d,0x5f,0xd1,0x9f,0x5d}, - {0x7f,0x72,0x63,0x6d,0xd3,0x08,0x14,0x03,0x33,0xb5,0xc7,0xd7,0xef,0x9a,0x37,0x6a,0x4b,0xe2,0xae,0xcc,0xc5,0x8f,0xe1,0xa9,0xd3,0xbe,0x8f,0x4f,0x91,0x35,0x2f,0x33,0x1e,0x52,0xd7,0xee,0x2a,0x4d,0x24,0x3f,0x15,0x96,0x2e,0x43,0x28,0x90,0x3a,0x8e,0xd4,0x16,0x9c,0x2e,0x77,0xba,0x64,0xe1,0xd8,0x98,0xeb,0x47,0xfa,0x87,0xc1,0x3b,0x0c,0xc2,0x86,0xea,0x15,0x01,0x47,0x6d,0x25,0xd1,0x46,0x6c,0xcb,0xb7,0x8a,0x99,0x88,0x01,0x66,0x3a,0xb5,0x32,0x78,0xd7,0x03,0xba,0x6f,0x90,0xce,0x81,0x0d,0x45}, - {0x75,0x52,0x20,0xa6,0xa1,0xb6,0x7b,0x6e,0x83,0x8e,0x3c,0x41,0xd7,0x21,0x4f,0xaa,0xb2,0x5c,0x8f,0xe8,0x55,0xd1,0x56,0x6f,0xe1,0x5b,0x34,0xa6,0x4b,0x5d,0xe2,0x2d,0x3f,0x74,0xae,0x1c,0x96,0xd8,0x74,0xd0,0xed,0x63,0x1c,0xee,0xf5,0x18,0x6d,0xf8,0x29,0xed,0xf4,0xe7,0x5b,0xc5,0xbd,0x97,0x08,0xb1,0x3a,0x66,0x79,0xd2,0xba,0x4c,0xcd,0x1f,0xd7,0xa0,0x24,0x90,0xd1,0x80,0xf8,0x8a,0x28,0xfb,0x0a,0xc2,0x25,0xc5,0x19,0x64,0x3a,0x5f,0x4b,0x97,0xa3,0xb1,0x33,0x72,0x00,0xe2,0xef,0xbc,0x7f,0x7d}, - {0x01,0x28,0x6b,0x26,0x6a,0x1e,0xef,0xfa,0x16,0x9f,0x73,0xd5,0xc4,0x68,0x6c,0x86,0x2c,0x76,0x03,0x1b,0xbc,0x2f,0x8a,0xf6,0x8d,0x5a,0xb7,0x87,0x5e,0x43,0x75,0x59,0x94,0x90,0xc2,0xf3,0xc5,0x5d,0x7c,0xcd,0xab,0x05,0x91,0x2a,0x9a,0xa2,0x81,0xc7,0x58,0x30,0x1c,0x42,0x36,0x1d,0xc6,0x80,0xd7,0xd4,0xd8,0xdc,0x96,0xd1,0x9c,0x4f,0x68,0x37,0x7b,0x6a,0xd8,0x97,0x92,0x19,0x63,0x7a,0xd1,0x1a,0x24,0x58,0xd0,0xd0,0x17,0x0c,0x1c,0x5c,0xad,0x9c,0x02,0xba,0x07,0x03,0x7a,0x38,0x84,0xd0,0xcd,0x7c}, - {0x17,0x04,0x26,0x6d,0x2c,0x42,0xa6,0xdc,0xbd,0x40,0x82,0x94,0x50,0x3d,0x15,0xae,0x77,0xc6,0x68,0xfb,0xb4,0xc1,0xc0,0xa9,0x53,0xcf,0xd0,0x61,0xed,0xd0,0x8b,0x42,0x93,0xcc,0x60,0x67,0x18,0x84,0x0c,0x9b,0x99,0x2a,0xb3,0x1a,0x7a,0x00,0xae,0xcd,0x18,0xda,0x0b,0x62,0x86,0xec,0x8d,0xa8,0x44,0xca,0x90,0x81,0x84,0xca,0x93,0x35,0xa7,0x9a,0x84,0x5e,0x9a,0x18,0x13,0x92,0xcd,0xfa,0xd8,0x65,0x35,0xc3,0xd8,0xd4,0xd1,0xbb,0xfd,0x53,0x5b,0x54,0x52,0x8c,0xe6,0x63,0x2d,0xda,0x08,0x83,0x39,0x27}, - {0x13,0xd4,0x5e,0x43,0x28,0x8d,0xc3,0x42,0xc9,0xcc,0x78,0x32,0x60,0xf3,0x50,0xbd,0xef,0x03,0xda,0x79,0x1a,0xab,0x07,0xbb,0x55,0x33,0x8c,0xbe,0xae,0x97,0x95,0x26,0x53,0x24,0x70,0x0a,0x4c,0x0e,0xa1,0xb9,0xde,0x1b,0x7d,0xd5,0x66,0x58,0xa2,0x0f,0xf7,0xda,0x27,0xcd,0xb5,0xd9,0xb9,0xff,0xfd,0x33,0x2c,0x49,0x45,0x29,0x2c,0x57,0xbe,0x30,0xcd,0xd6,0x45,0xc7,0x7f,0xc7,0xfb,0xae,0xba,0xe3,0xd3,0xe8,0xdf,0xe4,0x0c,0xda,0x5d,0xaa,0x30,0x88,0x2c,0xa2,0x80,0xca,0x5b,0xc0,0x98,0x54,0x98,0x7f}, - {0x17,0xe1,0x0b,0x9f,0x88,0xce,0x49,0x38,0x88,0xa2,0x54,0x7b,0x1b,0xad,0x05,0x80,0x1c,0x92,0xfc,0x23,0x9f,0xc3,0xa3,0x3d,0x04,0xf3,0x31,0x0a,0x47,0xec,0xc2,0x76,0x63,0x63,0xbf,0x0f,0x52,0x15,0x56,0xd3,0xa6,0xfb,0x4d,0xcf,0x45,0x5a,0x04,0x08,0xc2,0xa0,0x3f,0x87,0xbc,0x4f,0xc2,0xee,0xe7,0x12,0x9b,0xd6,0x3c,0x65,0xf2,0x30,0x85,0x0c,0xc1,0xaa,0x38,0xc9,0x08,0x8a,0xcb,0x6b,0x27,0xdb,0x60,0x9b,0x17,0x46,0x70,0xac,0x6f,0x0e,0x1e,0xc0,0x20,0xa9,0xda,0x73,0x64,0x59,0xf1,0x73,0x12,0x2f}, - {0x11,0x1e,0xe0,0x8a,0x7c,0xfc,0x39,0x47,0x9f,0xab,0x6a,0x4a,0x90,0x74,0x52,0xfd,0x2e,0x8f,0x72,0x87,0x82,0x8a,0xd9,0x41,0xf2,0x69,0x5b,0xd8,0x2a,0x57,0x9e,0x5d,0xc0,0x0b,0xa7,0x55,0xd7,0x8b,0x48,0x30,0xe7,0x42,0xd4,0xf1,0xa4,0xb5,0xd6,0x06,0x62,0x61,0x59,0xbc,0x9e,0xa6,0xd1,0xea,0x84,0xf7,0xc5,0xed,0x97,0x19,0xac,0x38,0x3b,0xb1,0x51,0xa7,0x17,0xb5,0x66,0x06,0x8c,0x85,0x9b,0x7e,0x86,0x06,0x7d,0x74,0x49,0xde,0x4d,0x45,0x11,0xc0,0xac,0xac,0x9c,0xe6,0xe9,0xbf,0x9c,0xcd,0xdf,0x22}, - {0xd9,0x0c,0x0d,0xc3,0xe0,0xd2,0xdb,0x8d,0x33,0x43,0xbb,0xac,0x5f,0x66,0x8e,0xad,0x1f,0x96,0x2a,0x32,0x8c,0x25,0x6b,0x8f,0xc7,0xc1,0x48,0x54,0xc0,0x16,0x29,0x6b,0xa1,0xe0,0x3b,0x10,0xb4,0x59,0xec,0x56,0x69,0xf9,0x59,0xd2,0xec,0xba,0xe3,0x2e,0x32,0xcd,0xf5,0x13,0x94,0xb2,0x7c,0x79,0x72,0xe4,0xcd,0x24,0x78,0x87,0xe9,0x0f,0x3b,0x91,0xba,0x0a,0xd1,0x34,0xdb,0x7e,0x0e,0xac,0x6d,0x2e,0x82,0xcd,0xa3,0x4e,0x15,0xf8,0x78,0x65,0xff,0x3d,0x08,0x66,0x17,0x0a,0xf0,0x7f,0x30,0x3f,0x30,0x4c}, - {0x85,0x8c,0xb2,0x17,0xd6,0x3b,0x0a,0xd3,0xea,0x3b,0x77,0x39,0xb7,0x77,0xd3,0xc5,0xbf,0x5c,0x6a,0x1e,0x8c,0xe7,0xc6,0xc6,0xc4,0xb7,0x2a,0x8b,0xf7,0xb8,0x61,0x0d,0x00,0x45,0xd9,0x0d,0x58,0x03,0xfc,0x29,0x93,0xec,0xbb,0x6f,0xa4,0x7a,0xd2,0xec,0xf8,0xa7,0xe2,0xc2,0x5f,0x15,0x0a,0x13,0xd5,0xa1,0x06,0xb7,0x1a,0x15,0x6b,0x41,0xb0,0x36,0xc1,0xe9,0xef,0xd7,0xa8,0x56,0x20,0x4b,0xe4,0x58,0xcd,0xe5,0x07,0xbd,0xab,0xe0,0x57,0x1b,0xda,0x2f,0xe6,0xaf,0xd2,0xe8,0x77,0x42,0xf7,0x2a,0x1a,0x19}, - {0x31,0x14,0x3c,0xc5,0x4b,0xf7,0x16,0xce,0xde,0xed,0x72,0x20,0xce,0x25,0x97,0x2b,0xe7,0x3e,0xb2,0xb5,0x6f,0xc3,0xb9,0xb8,0x08,0xc9,0x5c,0x0b,0x45,0x0e,0x2e,0x7e,0xfb,0x0e,0x46,0x4f,0x43,0x2b,0xe6,0x9f,0xd6,0x07,0x36,0xa6,0xd4,0x03,0xd3,0xde,0x24,0xda,0xa0,0xb7,0x0e,0x21,0x52,0xf0,0x93,0x5b,0x54,0x00,0xbe,0x7d,0x7e,0x23,0x30,0xb4,0x01,0x67,0xed,0x75,0x35,0x01,0x10,0xfd,0x0b,0x9f,0xe6,0x94,0x10,0x23,0x22,0x7f,0xe4,0x83,0x15,0x0f,0x32,0x75,0xe3,0x55,0x11,0xb1,0x99,0xa6,0xaf,0x71}, - {0x1d,0xb6,0x53,0x39,0x9b,0x6f,0xce,0x65,0xe6,0x41,0xa1,0xaf,0xea,0x39,0x58,0xc6,0xfe,0x59,0xf7,0xa9,0xfd,0x5f,0x43,0x0f,0x8e,0xc2,0xb1,0xc2,0xe9,0x42,0x11,0x02,0xd6,0x50,0x3b,0x47,0x1c,0x3c,0x42,0xea,0x10,0xef,0x38,0x3b,0x1f,0x7a,0xe8,0x51,0x95,0xbe,0xc9,0xb2,0x5f,0xbf,0x84,0x9b,0x1c,0x9a,0xf8,0x78,0xbc,0x1f,0x73,0x00,0x80,0x18,0xf8,0x48,0x18,0xc7,0x30,0xe4,0x19,0xc1,0xce,0x5e,0x22,0x0c,0x96,0xbf,0xe3,0x15,0xba,0x6b,0x83,0xe0,0xda,0xb6,0x08,0x58,0xe1,0x47,0x33,0x6f,0x4d,0x4c}, - {0xc9,0x1f,0x7d,0xc1,0xcf,0xec,0xf7,0x18,0x14,0x3c,0x40,0x51,0xa6,0xf5,0x75,0x6c,0xdf,0x0c,0xee,0xf7,0x2b,0x71,0xde,0xdb,0x22,0x7a,0xe4,0xa7,0xaa,0xdd,0x3f,0x19,0x70,0x19,0x8f,0x98,0xfc,0xdd,0x0c,0x2f,0x1b,0xf5,0xb9,0xb0,0x27,0x62,0x91,0x6b,0xbe,0x76,0x91,0x77,0xc4,0xb6,0xc7,0x6e,0xa8,0x9f,0x8f,0xa8,0x00,0x95,0xbf,0x38,0x6f,0x87,0xe8,0x37,0x3c,0xc9,0xd2,0x1f,0x2c,0x46,0xd1,0x18,0x5a,0x1e,0xf6,0xa2,0x76,0x12,0x24,0x39,0x82,0xf5,0x80,0x50,0x69,0x49,0x0d,0xbf,0x9e,0xb9,0x6f,0x6a}, - {0xeb,0x55,0x08,0x56,0xbb,0xc1,0x46,0x6a,0x9d,0xf0,0x93,0xf8,0x38,0xbb,0x16,0x24,0xc1,0xac,0x71,0x8f,0x37,0x11,0x1d,0xd7,0xea,0x96,0x18,0xa3,0x14,0x69,0xf7,0x75,0xc6,0x23,0xe4,0xb6,0xb5,0x22,0xb1,0xee,0x8e,0xff,0x86,0xf2,0x10,0x70,0x9d,0x93,0x8c,0x5d,0xcf,0x1d,0x83,0x2a,0xa9,0x90,0x10,0xeb,0xc5,0x42,0x9f,0xda,0x6f,0x13,0xd1,0xbd,0x05,0xa3,0xb1,0xdf,0x4c,0xf9,0x08,0x2c,0xf8,0x9f,0x9d,0x4b,0x36,0x0f,0x8a,0x58,0xbb,0xc3,0xa5,0xd8,0x87,0x2a,0xba,0xdc,0xe8,0x0b,0x51,0x83,0x21,0x02}, - {0x14,0x2d,0xad,0x5e,0x38,0x66,0xf7,0x4a,0x30,0x58,0x7c,0xca,0x80,0xd8,0x8e,0xa0,0x3d,0x1e,0x21,0x10,0xe6,0xa6,0x13,0x0d,0x03,0x6c,0x80,0x7b,0xe1,0x1c,0x07,0x6a,0x7f,0x7a,0x30,0x43,0x01,0x71,0x5a,0x9d,0x5f,0xa4,0x7d,0xc4,0x9e,0xde,0x63,0xb0,0xd3,0x7a,0x92,0xbe,0x52,0xfe,0xbb,0x22,0x6c,0x42,0x40,0xfd,0x41,0xc4,0x87,0x13,0xf8,0x8a,0x97,0x87,0xd1,0xc3,0xd3,0xb5,0x13,0x44,0x0e,0x7f,0x3d,0x5a,0x2b,0x72,0xa0,0x7c,0x47,0xbb,0x48,0x48,0x7b,0x0d,0x92,0xdc,0x1e,0xaf,0x6a,0xb2,0x71,0x31}, - {0xa8,0x4c,0x56,0x97,0x90,0x31,0x2f,0xa9,0x19,0xe1,0x75,0x22,0x4c,0xb8,0x7b,0xff,0x50,0x51,0x87,0xa4,0x37,0xfe,0x55,0x4f,0x5a,0x83,0xf0,0x3c,0x87,0xd4,0x1f,0x22,0xd1,0x47,0x8a,0xb2,0xd8,0xb7,0x0d,0xa6,0xf1,0xa4,0x70,0x17,0xd6,0x14,0xbf,0xa6,0x58,0xbd,0xdd,0x53,0x93,0xf8,0xa1,0xd4,0xe9,0x43,0x42,0x34,0x63,0x4a,0x51,0x6c,0x41,0x63,0x15,0x3a,0x4f,0x20,0x22,0x23,0x2d,0x03,0x0a,0xba,0xe9,0xe0,0x73,0xfb,0x0e,0x03,0x0f,0x41,0x4c,0xdd,0xe0,0xfc,0xaa,0x4a,0x92,0xfb,0x96,0xa5,0xda,0x48}, - {0xc7,0x9c,0xa5,0x5c,0x66,0x8e,0xca,0x6e,0xa0,0xac,0x38,0x2e,0x4b,0x25,0x47,0xa8,0xce,0x17,0x1e,0xd2,0x08,0xc7,0xaf,0x31,0xf7,0x4a,0xd8,0xca,0xfc,0xd6,0x6d,0x67,0x93,0x97,0x4c,0xc8,0x5d,0x1d,0xf6,0x14,0x06,0x82,0x41,0xef,0xe3,0xf9,0x41,0x99,0xac,0x77,0x62,0x34,0x8f,0xb8,0xf5,0xcd,0xa9,0x79,0x8a,0x0e,0xfa,0x37,0xc8,0x58,0x58,0x90,0xfc,0x96,0x85,0x68,0xf9,0x0c,0x1b,0xa0,0x56,0x7b,0xf3,0xbb,0xdc,0x1d,0x6a,0xd6,0x35,0x49,0x7d,0xe7,0xc2,0xdc,0x0a,0x7f,0xa5,0xc6,0xf2,0x73,0x4f,0x1c}, - {0xbb,0xa0,0x5f,0x30,0xbd,0x4f,0x7a,0x0e,0xad,0x63,0xc6,0x54,0xe0,0x4c,0x9d,0x82,0x48,0x38,0xe3,0x2f,0x83,0xc3,0x21,0xf4,0x42,0x4c,0xf6,0x1b,0x0d,0xc8,0x5a,0x79,0x84,0x34,0x7c,0xfc,0x6e,0x70,0x6e,0xb3,0x61,0xcf,0xc1,0xc3,0xb4,0xc9,0xdf,0x73,0xe5,0xc7,0x1c,0x78,0xc9,0x79,0x1d,0xeb,0x5c,0x67,0xaf,0x7d,0xdb,0x9a,0x45,0x70,0xb3,0x2b,0xb4,0x91,0x49,0xdb,0x91,0x1b,0xca,0xdc,0x02,0x4b,0x23,0x96,0x26,0x57,0xdc,0x78,0x8c,0x1f,0xe5,0x9e,0xdf,0x9f,0xd3,0x1f,0xe2,0x8c,0x84,0x62,0xe1,0x5f}, - {0x1a,0x96,0x94,0xe1,0x4f,0x21,0x59,0x4e,0x4f,0xcd,0x71,0x0d,0xc7,0x7d,0xbe,0x49,0x2d,0xf2,0x50,0x3b,0xd2,0xcf,0x00,0x93,0x32,0x72,0x91,0xfc,0x46,0xd4,0x89,0x47,0x08,0xb2,0x7c,0x5d,0x2d,0x85,0x79,0x28,0xe7,0xf2,0x7d,0x68,0x70,0xdd,0xde,0xb8,0x91,0x78,0x68,0x21,0xab,0xff,0x0b,0xdc,0x35,0xaa,0x7d,0x67,0x43,0xc0,0x44,0x2b,0x8e,0xb7,0x4e,0x07,0xab,0x87,0x1c,0x1a,0x67,0xf4,0xda,0x99,0x8e,0xd1,0xc6,0xfa,0x67,0x90,0x4f,0x48,0xcd,0xbb,0xac,0x3e,0xe4,0xa4,0xb9,0x2b,0xef,0x2e,0xc5,0x60}, - {0xf1,0x8b,0xfd,0x3b,0xbc,0x89,0x5d,0x0b,0x1a,0x55,0xf3,0xc9,0x37,0x92,0x6b,0xb0,0xf5,0x28,0x30,0xd5,0xb0,0x16,0x4c,0x0e,0xab,0xca,0xcf,0x2c,0x31,0x9c,0xbc,0x10,0x11,0x6d,0xae,0x7c,0xc2,0xc5,0x2b,0x70,0xab,0x8c,0xa4,0x54,0x9b,0x69,0xc7,0x44,0xb2,0x2e,0x49,0xba,0x56,0x40,0xbc,0xef,0x6d,0x67,0xb6,0xd9,0x48,0x72,0xd7,0x70,0x5b,0xa0,0xc2,0x3e,0x4b,0xe8,0x8a,0xaa,0xe0,0x81,0x17,0xed,0xf4,0x9e,0x69,0x98,0xd1,0x85,0x8e,0x70,0xe4,0x13,0x45,0x79,0x13,0xf4,0x76,0xa9,0xd3,0x5b,0x75,0x63}, - {0x53,0x08,0xd1,0x2a,0x3e,0xa0,0x5f,0xb5,0x69,0x35,0xe6,0x9e,0x90,0x75,0x6f,0x35,0x90,0xb8,0x69,0xbe,0xfd,0xf1,0xf9,0x9f,0x84,0x6f,0xc1,0x8b,0xc4,0xc1,0x8c,0x0d,0xb7,0xac,0xf1,0x97,0x18,0x10,0xc7,0x3d,0xd8,0xbb,0x65,0xc1,0x5e,0x7d,0xda,0x5d,0x0f,0x02,0xa1,0x0f,0x9c,0x5b,0x8e,0x50,0x56,0x2a,0xc5,0x37,0x17,0x75,0x63,0x27,0xa9,0x19,0xb4,0x6e,0xd3,0x02,0x94,0x02,0xa5,0x60,0xb4,0x77,0x7e,0x4e,0xb4,0xf0,0x56,0x49,0x3c,0xd4,0x30,0x62,0xa8,0xcf,0xe7,0x66,0xd1,0x7a,0x8a,0xdd,0xc2,0x70}, - {0x0e,0xec,0x6f,0x9f,0x50,0x94,0x61,0x65,0x8d,0x51,0xc6,0x46,0xa9,0x7e,0x2e,0xee,0x5c,0x9b,0xe0,0x67,0xf3,0xc1,0x33,0x97,0x95,0x84,0x94,0x63,0x63,0xac,0x0f,0x2e,0x13,0x7e,0xed,0xb8,0x7d,0x96,0xd4,0x91,0x7a,0x81,0x76,0xd7,0x0a,0x2f,0x25,0x74,0x64,0x25,0x85,0x0d,0xe0,0x82,0x09,0xe4,0xe5,0x3c,0xa5,0x16,0x38,0x61,0xb8,0x32,0x64,0xcd,0x48,0xe4,0xbe,0xf7,0xe7,0x79,0xd0,0x86,0x78,0x08,0x67,0x3a,0xc8,0x6a,0x2e,0xdb,0xe4,0xa0,0xd9,0xd4,0x9f,0xf8,0x41,0x4f,0x5a,0x73,0x5c,0x21,0x79,0x41}, - {0x2a,0xed,0xdc,0xd7,0xe7,0x94,0x70,0x8c,0x70,0x9c,0xd3,0x47,0xc3,0x8a,0xfb,0x97,0x02,0xd9,0x06,0xa9,0x33,0xe0,0x3b,0xe1,0x76,0x9d,0xd9,0x0c,0xa3,0x44,0x03,0x70,0x34,0xcd,0x6b,0x28,0xb9,0x33,0xae,0xe4,0xdc,0xd6,0x9d,0x55,0xb6,0x7e,0xef,0xb7,0x1f,0x8e,0xd3,0xb3,0x1f,0x14,0x8b,0x27,0x86,0xc2,0x41,0x22,0x66,0x85,0xfa,0x31,0xf4,0x22,0x36,0x2e,0x42,0x6c,0x82,0xaf,0x2d,0x50,0x33,0x98,0x87,0x29,0x20,0xc1,0x23,0x91,0x38,0x2b,0xe1,0xb7,0xc1,0x9b,0x89,0x24,0x95,0xa9,0x12,0x23,0xbb,0x24}, - {0xc3,0x67,0xde,0x32,0x17,0xed,0xa8,0xb1,0x48,0x49,0x1b,0x46,0x18,0x94,0xb4,0x3c,0xd2,0xbc,0xcf,0x76,0x43,0x43,0xbd,0x8e,0x08,0x80,0x18,0x1e,0x87,0x3e,0xee,0x0f,0x6b,0x5c,0xf8,0xf5,0x2a,0x0c,0xf8,0x41,0x94,0x67,0xfa,0x04,0xc3,0x84,0x72,0x68,0xad,0x1b,0xba,0xa3,0x99,0xdf,0x45,0x89,0x16,0x5d,0xeb,0xff,0xf9,0x2a,0x1d,0x0d,0xdf,0x1e,0x62,0x32,0xa1,0x8a,0xda,0xa9,0x79,0x65,0x22,0x59,0xa1,0x22,0xb8,0x30,0x93,0xc1,0x9a,0xa7,0x7b,0x19,0x04,0x40,0x76,0x1d,0x53,0x18,0x97,0xd7,0xac,0x16}, - {0x3d,0x1d,0x9b,0x2d,0xaf,0x72,0xdf,0x72,0x5a,0x24,0x32,0xa4,0x36,0x2a,0x46,0x63,0x37,0x96,0xb3,0x16,0x79,0xa0,0xce,0x3e,0x09,0x23,0x30,0xb9,0xf6,0x0e,0x3e,0x12,0xad,0xb6,0x87,0x78,0xc5,0xc6,0x59,0xc9,0xba,0xfe,0x90,0x5f,0xad,0x9e,0xe1,0x94,0x04,0xf5,0x42,0xa3,0x62,0x4e,0xe2,0x16,0x00,0x17,0x16,0x18,0x4b,0xd3,0x4e,0x16,0x9a,0xe6,0x2f,0x19,0x4c,0xd9,0x7e,0x48,0x13,0x15,0x91,0x3a,0xea,0x2c,0xae,0x61,0x27,0xde,0xa4,0xb9,0xd3,0xf6,0x7b,0x87,0xeb,0xf3,0x73,0x10,0xc6,0x0f,0xda,0x78}, - {0x6a,0xc6,0x2b,0xe5,0x28,0x5d,0xf1,0x5b,0x8e,0x1a,0xf0,0x70,0x18,0xe3,0x47,0x2c,0xdd,0x8b,0xc2,0x06,0xbc,0xaf,0x19,0x24,0x3a,0x17,0x6b,0x25,0xeb,0xde,0x25,0x2d,0x94,0x3a,0x0c,0x68,0xf1,0x80,0x9f,0xa2,0xe6,0xe7,0xe9,0x1a,0x15,0x7e,0xf7,0x71,0x73,0x79,0x01,0x48,0x58,0xf1,0x00,0x11,0xdd,0x8d,0xb3,0x16,0xb3,0xa4,0x4a,0x05,0xb8,0x7c,0x26,0x19,0x8d,0x46,0xc8,0xdf,0xaf,0x4d,0xe5,0x66,0x9c,0x78,0x28,0x0b,0x17,0xec,0x6e,0x66,0x2a,0x1d,0xeb,0x2a,0x60,0xa7,0x7d,0xab,0xa6,0x10,0x46,0x13}, - {0xfe,0xb0,0xf6,0x8d,0xc7,0x8e,0x13,0x51,0x1b,0xf5,0x75,0xe5,0x89,0xda,0x97,0x53,0xb9,0xf1,0x7a,0x71,0x1d,0x7a,0x20,0x09,0x50,0xd6,0x20,0x2b,0xba,0xfd,0x02,0x21,0x15,0xf5,0xd1,0x77,0xe7,0x65,0x2a,0xcd,0xf1,0x60,0xaa,0x8f,0x87,0x91,0x89,0x54,0xe5,0x06,0xbc,0xda,0xbc,0x3b,0xb7,0xb1,0xfb,0xc9,0x7c,0xa9,0xcb,0x78,0x48,0x65,0xa1,0xe6,0x5c,0x05,0x05,0xe4,0x9e,0x96,0x29,0xad,0x51,0x12,0x68,0xa7,0xbc,0x36,0x15,0xa4,0x7d,0xaa,0x17,0xf5,0x1a,0x3a,0xba,0xb2,0xec,0x29,0xdb,0x25,0xd7,0x0a}, - {0x57,0x24,0x4e,0x83,0xb1,0x67,0x42,0xdc,0xc5,0x1b,0xce,0x70,0xb5,0x44,0x75,0xb6,0xd7,0x5e,0xd1,0xf7,0x0b,0x7a,0xf0,0x1a,0x50,0x36,0xa0,0x71,0xfb,0xcf,0xef,0x4a,0x85,0x6f,0x05,0x9b,0x0c,0xbc,0xc7,0xfe,0xd7,0xff,0xf5,0xe7,0x68,0x52,0x7d,0x53,0xfa,0xae,0x12,0x43,0x62,0xc6,0xaf,0x77,0xd9,0x9f,0x39,0x02,0x53,0x5f,0x67,0x4f,0x1e,0x17,0x15,0x04,0x36,0x36,0x2d,0xc3,0x3b,0x48,0x98,0x89,0x11,0xef,0x2b,0xcd,0x10,0x51,0x94,0xd0,0xad,0x6e,0x0a,0x87,0x61,0x65,0xa8,0xa2,0x72,0xbb,0xcc,0x0b}, - {0xc8,0xa9,0xb1,0xea,0x2f,0x96,0x5e,0x18,0xcd,0x7d,0x14,0x65,0x35,0xe6,0xe7,0x86,0xf2,0x6d,0x5b,0xbb,0x31,0xe0,0x92,0xb0,0x3e,0xb7,0xd6,0x59,0xab,0xf0,0x24,0x40,0x96,0x12,0xfe,0x50,0x4c,0x5e,0x6d,0x18,0x7e,0x9f,0xe8,0xfe,0x82,0x7b,0x39,0xe0,0xb0,0x31,0x70,0x50,0xc5,0xf6,0xc7,0x3b,0xc2,0x37,0x8f,0x10,0x69,0xfd,0x78,0x66,0xc2,0x63,0x68,0x63,0x31,0xfa,0x86,0x15,0xf2,0x33,0x2d,0x57,0x48,0x8c,0xf6,0x07,0xfc,0xae,0x9e,0x78,0x9f,0xcc,0x73,0x4f,0x01,0x47,0xad,0x8e,0x10,0xe2,0x42,0x2d}, - {0x9b,0xd2,0xdf,0x94,0x15,0x13,0xf5,0x97,0x6a,0x4c,0x3f,0x31,0x5d,0x98,0x55,0x61,0x10,0x50,0x45,0x08,0x07,0x3f,0xa1,0xeb,0x22,0xd3,0xd2,0xb8,0x08,0x26,0x6b,0x67,0x93,0x75,0x53,0x0f,0x0d,0x7b,0x71,0x21,0x4c,0x06,0x1e,0x13,0x0b,0x69,0x4e,0x91,0x9f,0xe0,0x2a,0x75,0xae,0x87,0xb6,0x1b,0x6e,0x3c,0x42,0x9b,0xa7,0xf3,0x0b,0x42,0x47,0x2b,0x5b,0x1c,0x65,0xba,0x38,0x81,0x80,0x1b,0x1b,0x31,0xec,0xb6,0x71,0x86,0xb0,0x35,0x31,0xbc,0xb1,0x0c,0xff,0x7b,0xe0,0xf1,0x0c,0x9c,0xfa,0x2f,0x5d,0x74}, - {0xbd,0xc8,0xc9,0x2b,0x1e,0x5a,0x52,0xbf,0x81,0x9d,0x47,0x26,0x08,0x26,0x5b,0xea,0xdb,0x55,0x01,0xdf,0x0e,0xc7,0x11,0xd5,0xd0,0xf5,0x0c,0x96,0xeb,0x3c,0xe2,0x1a,0x6a,0x4e,0xd3,0x21,0x57,0xdf,0x36,0x60,0xd0,0xb3,0x7b,0x99,0x27,0x88,0xdb,0xb1,0xfa,0x6a,0x75,0xc8,0xc3,0x09,0xc2,0xd3,0x39,0xc8,0x1d,0x4c,0xe5,0x5b,0xe1,0x06,0x4a,0x99,0x32,0x19,0x87,0x5d,0x72,0x5b,0xb0,0xda,0xb1,0xce,0xb5,0x1c,0x35,0x32,0x05,0xca,0xb7,0xda,0x49,0x15,0xc4,0x7d,0xf7,0xc1,0x8e,0x27,0x61,0xd8,0xde,0x58}, - {0x5c,0xc5,0x66,0xf2,0x93,0x37,0x17,0xd8,0x49,0x4e,0x45,0xcc,0xc5,0x76,0xc9,0xc8,0xa8,0xc3,0x26,0xbc,0xf8,0x82,0xe3,0x5c,0xf9,0xf6,0x85,0x54,0xe8,0x9d,0xf3,0x2f,0xa8,0xc9,0xc2,0xb6,0xa8,0x5b,0xfb,0x2d,0x8c,0x59,0x2c,0xf5,0x8e,0xef,0xee,0x48,0x73,0x15,0x2d,0xf1,0x07,0x91,0x80,0x33,0xd8,0x5b,0x1d,0x53,0x6b,0x69,0xba,0x08,0x7a,0xc5,0xef,0xc3,0xee,0x3e,0xed,0x77,0x11,0x48,0xff,0xd4,0x17,0x55,0xe0,0x04,0xcb,0x71,0xa6,0xf1,0x3f,0x7a,0x3d,0xea,0x54,0xfe,0x7c,0x94,0xb4,0x33,0x06,0x12}, - {0x42,0x00,0x61,0x91,0x78,0x98,0x94,0x0b,0xe8,0xfa,0xeb,0xec,0x3c,0xb1,0xe7,0x4e,0xc0,0xa4,0xf0,0x94,0x95,0x73,0xbe,0x70,0x85,0x91,0xd5,0xb4,0x99,0x0a,0xd3,0x35,0x0a,0x10,0x12,0x49,0x47,0x31,0xbd,0x82,0x06,0xbe,0x6f,0x7e,0x6d,0x7b,0x23,0xde,0xc6,0x79,0xea,0x11,0x19,0x76,0x1e,0xe1,0xde,0x3b,0x39,0xcb,0xe3,0x3b,0x43,0x07,0xf4,0x97,0xe9,0x5c,0xc0,0x44,0x79,0xff,0xa3,0x51,0x5c,0xb0,0xe4,0x3d,0x5d,0x57,0x7c,0x84,0x76,0x5a,0xfd,0x81,0x33,0x58,0x9f,0xda,0xf6,0x7a,0xde,0x3e,0x87,0x2d}, - {0x09,0x34,0x37,0x43,0x64,0x31,0x7a,0x15,0xd9,0x81,0xaa,0xf4,0xee,0xb7,0xb8,0xfa,0x06,0x48,0xa6,0xf5,0xe6,0xfe,0x93,0xb0,0xb6,0xa7,0x7f,0x70,0x54,0x36,0x77,0x2e,0x81,0xf9,0x5d,0x4e,0xe1,0x02,0x62,0xaa,0xf5,0xe1,0x15,0x50,0x17,0x59,0x0d,0xa2,0x6c,0x1d,0xe2,0xba,0xd3,0x75,0xa2,0x18,0x53,0x02,0x60,0x01,0x8a,0x61,0x43,0x05,0xc1,0x23,0x4c,0x97,0xf4,0xbd,0xea,0x0d,0x93,0x46,0xce,0x9d,0x25,0x0a,0x6f,0xaa,0x2c,0xba,0x9a,0xa2,0xb8,0x2c,0x20,0x04,0x0d,0x96,0x07,0x2d,0x36,0x43,0x14,0x4b}, - {0x7a,0x1f,0x6e,0xb6,0xc7,0xb7,0xc4,0xcc,0x7e,0x2f,0x0c,0xf5,0x25,0x7e,0x15,0x44,0x1c,0xaf,0x3e,0x71,0xfc,0x6d,0xf0,0x3e,0xf7,0x63,0xda,0x52,0x67,0x44,0x2f,0x58,0xcb,0x9c,0x52,0x1c,0xe9,0x54,0x7c,0x96,0xfb,0x35,0xc6,0x64,0x92,0x26,0xf6,0x30,0x65,0x19,0x12,0x78,0xf4,0xaf,0x47,0x27,0x5c,0x6f,0xf6,0xea,0x18,0x84,0x03,0x17,0xe4,0x4c,0x32,0x20,0xd3,0x7b,0x31,0xc6,0xc4,0x8b,0x48,0xa4,0xe8,0x42,0x10,0xa8,0x64,0x13,0x5a,0x4e,0x8b,0xf1,0x1e,0xb2,0xc9,0x8d,0xa2,0xcd,0x4b,0x1c,0x2a,0x0c}, - {0x47,0x04,0x1f,0x6f,0xd0,0xc7,0x4d,0xd2,0x59,0xc0,0x87,0xdb,0x3e,0x9e,0x26,0xb2,0x8f,0xd2,0xb2,0xfb,0x72,0x02,0x5b,0xd1,0x77,0x48,0xf6,0xc6,0xd1,0x8b,0x55,0x7c,0x45,0x69,0xbd,0x69,0x48,0x81,0xc4,0xed,0x22,0x8d,0x1c,0xbe,0x7d,0x90,0x6d,0x0d,0xab,0xc5,0x5c,0xd5,0x12,0xd2,0x3b,0xc6,0x83,0xdc,0x14,0xa3,0x30,0x9b,0x6a,0x5a,0x3d,0x46,0x96,0xd3,0x24,0x15,0xec,0xd0,0xf0,0x24,0x5a,0xc3,0x8a,0x62,0xbb,0x12,0xa4,0x5f,0xbc,0x1c,0x79,0x3a,0x0c,0xa5,0xc3,0xaf,0xfb,0x0a,0xca,0xa5,0x04,0x04}, - {0xd6,0x43,0xa7,0x0a,0x07,0x40,0x1f,0x8c,0xe8,0x5e,0x26,0x5b,0xcb,0xd0,0xba,0xcc,0xde,0xd2,0x8f,0x66,0x6b,0x04,0x4b,0x57,0x33,0x96,0xdd,0xca,0xfd,0x5b,0x39,0x46,0xd1,0x6f,0x41,0x2a,0x1b,0x9e,0xbc,0x62,0x8b,0x59,0x50,0xe3,0x28,0xf7,0xc6,0xb5,0x67,0x69,0x5d,0x3d,0xd8,0x3f,0x34,0x04,0x98,0xee,0xf8,0xe7,0x16,0x75,0x52,0x39,0x9c,0x9a,0x5d,0x1a,0x2d,0xdb,0x7f,0x11,0x2a,0x5c,0x00,0xd1,0xbc,0x45,0x77,0x9c,0xea,0x6f,0xd5,0x54,0xf1,0xbe,0xd4,0xef,0x16,0xd0,0x22,0xe8,0x29,0x9a,0x57,0x76}, - {0x17,0x2a,0xc0,0x49,0x7e,0x8e,0xb6,0x45,0x7f,0xa3,0xa9,0xbc,0xa2,0x51,0xcd,0x23,0x1b,0x4c,0x22,0xec,0x11,0x5f,0xd6,0x3e,0xb1,0xbd,0x05,0x9e,0xdc,0x84,0xa3,0x43,0xf2,0x34,0xb4,0x52,0x13,0xb5,0x3c,0x33,0xe1,0x80,0xde,0x93,0x49,0x28,0x32,0xd8,0xce,0x35,0x0d,0x75,0x87,0x28,0x51,0xb5,0xc1,0x77,0x27,0x2a,0xbb,0x14,0xc5,0x02,0x45,0xb6,0xf1,0x8b,0xda,0xd5,0x4b,0x68,0x53,0x4b,0xb5,0xf6,0x7e,0xd3,0x8b,0xfb,0x53,0xd2,0xb0,0xa9,0xd7,0x16,0x39,0x31,0x59,0x80,0x54,0x61,0x09,0x92,0x60,0x11}, - {0xaa,0xcf,0xda,0x29,0x69,0x16,0x4d,0xb4,0x8f,0x59,0x13,0x84,0x4c,0x9f,0x52,0xda,0x59,0x55,0x3d,0x45,0xca,0x63,0xef,0xe9,0x0b,0x8e,0x69,0xc5,0x5b,0x12,0x1e,0x35,0xcd,0x4d,0x9b,0x36,0x16,0x56,0x38,0x7a,0x63,0x35,0x5c,0x65,0xa7,0x2c,0xc0,0x75,0x21,0x80,0xf1,0xd4,0xf9,0x1b,0xc2,0x7d,0x42,0xe0,0xe6,0x91,0x74,0x7d,0x63,0x2f,0xbe,0x7b,0xf6,0x1a,0x46,0x9b,0xb4,0xd4,0x61,0x89,0xab,0xc8,0x7a,0x03,0x03,0xd6,0xfb,0x99,0xa6,0xf9,0x9f,0xe1,0xde,0x71,0x9a,0x2a,0xce,0xe7,0x06,0x2d,0x18,0x7f}, - {0xec,0x68,0x01,0xab,0x64,0x8e,0x7c,0x7a,0x43,0xc5,0xed,0x15,0x55,0x4a,0x5a,0xcb,0xda,0x0e,0xcd,0x47,0xd3,0x19,0x55,0x09,0xb0,0x93,0x3e,0x34,0x8c,0xac,0xd4,0x67,0x22,0x75,0x21,0x8e,0x72,0x4b,0x45,0x09,0xd8,0xb8,0x84,0xd4,0xf4,0xe8,0x58,0xaa,0x3c,0x90,0x46,0x7f,0x4d,0x25,0x58,0xd3,0x17,0x52,0x1c,0x24,0x43,0xc0,0xac,0x44,0x77,0x57,0x7a,0x4f,0xbb,0x6b,0x7d,0x1c,0xe1,0x13,0x83,0x91,0xd4,0xfe,0x35,0x8b,0x84,0x46,0x6b,0xc9,0xc6,0xa1,0xdc,0x4a,0xbd,0x71,0xad,0x12,0x83,0x1c,0x6d,0x55}, - {0x82,0x39,0x8d,0x0c,0xe3,0x40,0xef,0x17,0x34,0xfa,0xa3,0x15,0x3e,0x07,0xf7,0x31,0x6e,0x64,0x73,0x07,0xcb,0xf3,0x21,0x4f,0xff,0x4e,0x82,0x1d,0x6d,0x6c,0x6c,0x74,0x21,0xe8,0x1b,0xb1,0x56,0x67,0xf0,0x81,0xdd,0xf3,0xa3,0x10,0x23,0xf8,0xaf,0x0f,0x5d,0x46,0x99,0x6a,0x55,0xd0,0xb2,0xf8,0x05,0x7f,0x8c,0xcc,0x38,0xbe,0x7a,0x09,0xa4,0x2d,0xa5,0x7e,0x87,0xc9,0x49,0x0c,0x43,0x1d,0xdc,0x9b,0x55,0x69,0x43,0x4c,0xd2,0xeb,0xcc,0xf7,0x09,0x38,0x2c,0x02,0xbd,0x84,0xee,0x4b,0xa3,0x14,0x7e,0x57}, - {0x0a,0x3b,0xa7,0x61,0xac,0x68,0xe2,0xf0,0xf5,0xa5,0x91,0x37,0x10,0xfa,0xfa,0xf2,0xe9,0x00,0x6d,0x6b,0x82,0x3e,0xe1,0xc1,0x42,0x8f,0xd7,0x6f,0xe9,0x7e,0xfa,0x60,0x2b,0xd7,0x4d,0xbd,0xbe,0xce,0xfe,0x94,0x11,0x22,0x0f,0x06,0xda,0x4f,0x6a,0xf4,0xff,0xd1,0xc8,0xc0,0x77,0x59,0x4a,0x12,0x95,0x92,0x00,0xfb,0xb8,0x04,0x53,0x70,0xc6,0x6e,0x29,0x4d,0x35,0x1d,0x3d,0xb6,0xd8,0x31,0xad,0x5f,0x3e,0x05,0xc3,0xf3,0xec,0x42,0xbd,0xb4,0x8c,0x95,0x0b,0x67,0xfd,0x53,0x63,0xa1,0x0c,0x8e,0x39,0x21}, - {0xf3,0x33,0x2b,0x38,0x8a,0x05,0xf5,0x89,0xb4,0xc0,0x48,0xad,0x0b,0xba,0xe2,0x5a,0x6e,0xb3,0x3d,0xa5,0x03,0xb5,0x93,0x8f,0xe6,0x32,0xa2,0x95,0x9d,0xed,0xa3,0x5a,0x01,0x56,0xb7,0xb4,0xf9,0xaa,0x98,0x27,0x72,0xad,0x8d,0x5c,0x13,0x72,0xac,0x5e,0x23,0xa0,0xb7,0x61,0x61,0xaa,0xce,0xd2,0x4e,0x7d,0x8f,0xe9,0x84,0xb2,0xbf,0x1b,0x61,0x65,0xd9,0xc7,0xe9,0x77,0x67,0x65,0x36,0x80,0xc7,0x72,0x54,0x12,0x2b,0xcb,0xee,0x6e,0x50,0xd9,0x99,0x32,0x05,0x65,0xcc,0x57,0x89,0x5e,0x4e,0xe1,0x07,0x4a}, - {0x99,0xf9,0x0d,0x98,0xcb,0x12,0xe4,0x4e,0x71,0xc7,0x6e,0x3c,0x6f,0xd7,0x15,0xa3,0xfd,0x77,0x5c,0x92,0xde,0xed,0xa5,0xbb,0x02,0x34,0x31,0x1d,0x39,0xac,0x0b,0x3f,0x9b,0xa4,0x77,0xc4,0xcd,0x58,0x0b,0x24,0x17,0xf0,0x47,0x64,0xde,0xda,0x38,0xfd,0xad,0x6a,0xc8,0xa7,0x32,0x8d,0x92,0x19,0x81,0xa0,0xaf,0x84,0xed,0x7a,0xaf,0x50,0xe5,0x5b,0xf6,0x15,0x01,0xde,0x4f,0x6e,0xb2,0x09,0x61,0x21,0x21,0x26,0x98,0x29,0xd9,0xd6,0xad,0x0b,0x81,0x05,0x02,0x78,0x06,0xd0,0xeb,0xba,0x16,0xa3,0x21,0x19}, - {0xfc,0x70,0xb8,0xdf,0x7e,0x2f,0x42,0x89,0xbd,0xb3,0x76,0x4f,0xeb,0x6b,0x29,0x2c,0xf7,0x4d,0xc2,0x36,0xd4,0xf1,0x38,0x07,0xb0,0xae,0x73,0xe2,0x41,0xdf,0x58,0x64,0x8b,0xc1,0xf3,0xd9,0x9a,0xad,0x5a,0xd7,0x9c,0xc1,0xb1,0x60,0xef,0x0e,0x6a,0x56,0xd9,0x0e,0x5c,0x25,0xac,0x0b,0x9a,0x3e,0xf5,0xc7,0x62,0xa0,0xec,0x9d,0x04,0x7b,0x83,0x44,0x44,0x35,0x7a,0xe3,0xcb,0xdc,0x93,0xbe,0xed,0x0f,0x33,0x79,0x88,0x75,0x87,0xdd,0xc5,0x12,0xc3,0x04,0x60,0x78,0x64,0x0e,0x95,0xc2,0xcb,0xdc,0x93,0x60}, - {0x6d,0x70,0xe0,0x85,0x85,0x9a,0xf3,0x1f,0x33,0x39,0xe7,0xb3,0xd8,0xa5,0xd0,0x36,0x3b,0x45,0x8f,0x71,0xe1,0xf2,0xb9,0x43,0x7c,0xa9,0x27,0x48,0x08,0xea,0xd1,0x57,0x4b,0x03,0x84,0x60,0xbe,0xee,0xde,0x6b,0x54,0xb8,0x0f,0x78,0xb6,0xc2,0x99,0x31,0x95,0x06,0x2d,0xb6,0xab,0x76,0x33,0x97,0x90,0x7d,0x64,0x8b,0xc9,0x80,0x31,0x6e,0x71,0xb0,0x28,0xa1,0xe7,0xb6,0x7a,0xee,0xaa,0x8b,0xa8,0x93,0x6d,0x59,0xc1,0xa4,0x30,0x61,0x21,0xb2,0x82,0xde,0xb4,0xf7,0x18,0xbd,0x97,0xdd,0x9d,0x99,0x3e,0x36}, - {0xc4,0x1f,0xee,0x35,0xc1,0x43,0xa8,0x96,0xcf,0xc8,0xe4,0x08,0x55,0xb3,0x6e,0x97,0x30,0xd3,0x8c,0xb5,0x01,0x68,0x2f,0xb4,0x2b,0x05,0x3a,0x69,0x78,0x9b,0xee,0x48,0xc6,0xae,0x4b,0xe2,0xdc,0x48,0x18,0x2f,0x60,0xaf,0xbc,0xba,0x55,0x72,0x9b,0x76,0x31,0xe9,0xef,0x3c,0x6e,0x3c,0xcb,0x90,0x55,0xb3,0xf9,0xc6,0x9b,0x97,0x1f,0x23,0xc6,0xf3,0x2a,0xcc,0x4b,0xde,0x31,0x5c,0x1f,0x8d,0x20,0xfe,0x30,0xb0,0x4b,0xb0,0x66,0xb4,0x4f,0xc1,0x09,0x70,0x8d,0xb7,0x13,0x24,0x79,0x08,0x9b,0xfa,0x9b,0x07}, - {0xf4,0x0d,0x30,0xda,0x51,0x3a,0x90,0xe3,0xb0,0x5a,0xa9,0x3d,0x23,0x64,0x39,0x84,0x80,0x64,0x35,0x0b,0x2d,0xf1,0x3c,0xed,0x94,0x71,0x81,0x84,0xf6,0x77,0x8c,0x03,0x45,0x42,0xd5,0xa2,0x80,0xed,0xc9,0xf3,0x52,0x39,0xf6,0x77,0x78,0x8b,0xa0,0x0a,0x75,0x54,0x08,0xd1,0x63,0xac,0x6d,0xd7,0x6b,0x63,0x70,0x94,0x15,0xfb,0xf4,0x1e,0xec,0x7b,0x16,0x5b,0xe6,0x5e,0x4e,0x85,0xc2,0xcd,0xd0,0x96,0x42,0x0a,0x59,0x59,0x99,0x21,0x10,0x98,0x34,0xdf,0xb2,0x72,0x56,0xff,0x0b,0x4a,0x2a,0xe9,0x5e,0x57}, - {0xcf,0x2f,0x18,0x8a,0x90,0x80,0xc0,0xd4,0xbd,0x9d,0x48,0x99,0xc2,0x70,0xe1,0x30,0xde,0x33,0xf7,0x52,0x57,0xbd,0xba,0x05,0x00,0xfd,0xd3,0x2c,0x11,0xe7,0xd4,0x43,0x01,0xd8,0xa4,0x0a,0x45,0xbc,0x46,0x5d,0xd8,0xb9,0x33,0xa5,0x27,0x12,0xaf,0xc3,0xc2,0x06,0x89,0x2b,0x26,0x3b,0x9e,0x38,0x1b,0x58,0x2f,0x38,0x7e,0x1e,0x0a,0x20,0xc5,0x3a,0xf9,0xea,0x67,0xb9,0x8d,0x51,0xc0,0x52,0x66,0x05,0x9b,0x98,0xbc,0x71,0xf5,0x97,0x71,0x56,0xd9,0x85,0x2b,0xfe,0x38,0x4e,0x1e,0x65,0x52,0xca,0x0e,0x05}, - {0x9c,0x0c,0x3f,0x45,0xde,0x1a,0x43,0xc3,0x9b,0x3b,0x70,0xff,0x5e,0x04,0xf5,0xe9,0x3d,0x7b,0x84,0xed,0xc9,0x7a,0xd9,0xfc,0xc6,0xf4,0x58,0x1c,0xc2,0xe6,0x0e,0x4b,0xea,0x68,0xe6,0x60,0x76,0x39,0xac,0x97,0x97,0xb4,0x3a,0x15,0xfe,0xbb,0x19,0x9b,0x9f,0xa7,0xec,0x34,0xb5,0x79,0xb1,0x4c,0x57,0xae,0x31,0xa1,0x9f,0xc0,0x51,0x61,0x96,0x5d,0xf0,0xfd,0x0d,0x5c,0xf5,0x3a,0x7a,0xee,0xb4,0x2a,0xe0,0x2e,0x26,0xdd,0x09,0x17,0x17,0x12,0x87,0xbb,0xb2,0x11,0x0b,0x03,0x0f,0x80,0xfa,0x24,0xef,0x1f}, - {0x96,0x31,0xa7,0x1a,0xfb,0x53,0xd6,0x37,0x18,0x64,0xd7,0x3f,0x30,0x95,0x94,0x0f,0xb2,0x17,0x3a,0xfb,0x09,0x0b,0x20,0xad,0x3e,0x61,0xc8,0x2f,0x29,0x49,0x4d,0x54,0x86,0x6b,0x97,0x30,0xf5,0xaf,0xd2,0x22,0x04,0x46,0xd2,0xc2,0x06,0xb8,0x90,0x8d,0xe5,0xba,0xe5,0x4d,0x6c,0x89,0xa1,0xdc,0x17,0x0c,0x34,0xc8,0xe6,0x5f,0x00,0x28,0x88,0x86,0x52,0x34,0x9f,0xba,0xef,0x6a,0xa1,0x7d,0x10,0x25,0x94,0xff,0x1b,0x5c,0x36,0x4b,0xd9,0x66,0xcd,0xbb,0x5b,0xf7,0xfa,0x6d,0x31,0x0f,0x93,0x72,0xe4,0x72}, - {0x4f,0x08,0x81,0x97,0x8c,0x20,0x95,0x26,0xe1,0x0e,0x45,0x23,0x0b,0x2a,0x50,0xb1,0x02,0xde,0xef,0x03,0xa6,0xae,0x9d,0xfd,0x4c,0xa3,0x33,0x27,0x8c,0x2e,0x9d,0x5a,0x27,0x76,0x2a,0xd3,0x35,0xf6,0xf3,0x07,0xf0,0x66,0x65,0x5f,0x86,0x4d,0xaa,0x7a,0x50,0x44,0xd0,0x28,0x97,0xe7,0x85,0x3c,0x38,0x64,0xe0,0x0f,0x00,0x7f,0xee,0x1f,0xe5,0xf7,0xdb,0x03,0xda,0x05,0x53,0x76,0xbd,0xcd,0x34,0x14,0x49,0xf2,0xda,0xa4,0xec,0x88,0x4a,0xd2,0xcd,0xd5,0x4a,0x7b,0x43,0x05,0x04,0xee,0x51,0x40,0xf9,0x00}, - {0xb2,0x30,0xd3,0xc3,0x23,0x6b,0x35,0x8d,0x06,0x1b,0x47,0xb0,0x9b,0x8b,0x1c,0xf2,0x3c,0xb8,0x42,0x6e,0x6c,0x31,0x6c,0xb3,0x0d,0xb1,0xea,0x8b,0x7e,0x9c,0xd7,0x07,0x53,0x97,0xaf,0x07,0xbb,0x93,0xef,0xd7,0xa7,0x66,0xb7,0x3d,0xcf,0xd0,0x3e,0x58,0xc5,0x1e,0x0b,0x6e,0xbf,0x98,0x69,0xce,0x52,0x04,0xd4,0x5d,0xd2,0xff,0xb7,0x47,0x12,0xdd,0x08,0xbc,0x9c,0xfb,0xfb,0x87,0x9b,0xc2,0xee,0xe1,0x3a,0x6b,0x06,0x8a,0xbf,0xc1,0x1f,0xdb,0x2b,0x24,0x57,0x0d,0xb6,0x4b,0xa6,0x5e,0xa3,0x20,0x35,0x1c}, - {0x4a,0xa3,0xcb,0xbc,0xa6,0x53,0xd2,0x80,0x9b,0x21,0x38,0x38,0xa1,0xc3,0x61,0x3e,0x96,0xe3,0x82,0x98,0x01,0xb6,0xc3,0x90,0x6f,0xe6,0x0e,0x5d,0x77,0x05,0x3d,0x1c,0x59,0xc0,0x6b,0x21,0x40,0x6f,0xa8,0xcd,0x7e,0xd8,0xbc,0x12,0x1d,0x23,0xbb,0x1f,0x90,0x09,0xc7,0x17,0x9e,0x6a,0x95,0xb4,0x55,0x2e,0xd1,0x66,0x3b,0x0c,0x75,0x38,0x1a,0xe5,0x22,0x94,0x40,0xf1,0x2e,0x69,0x71,0xf6,0x5d,0x2b,0x3c,0xc7,0xc0,0xcb,0x29,0xe0,0x4c,0x74,0xe7,0x4f,0x01,0x21,0x7c,0x48,0x30,0xd3,0xc7,0xe2,0x21,0x06}, - {0x8d,0x83,0x59,0x82,0xcc,0x60,0x98,0xaf,0xdc,0x9a,0x9f,0xc6,0xc1,0x48,0xea,0x90,0x30,0x1e,0x58,0x65,0x37,0x48,0x26,0x65,0xbc,0xa5,0xd3,0x7b,0x09,0xd6,0x07,0x00,0xf3,0xf0,0xdb,0xb0,0x96,0x17,0xae,0xb7,0x96,0xe1,0x7c,0xe1,0xb9,0xaf,0xdf,0x54,0xb4,0xa3,0xaa,0xe9,0x71,0x30,0x92,0x25,0x9d,0x2e,0x00,0xa1,0x9c,0x58,0x8e,0x5d,0x4b,0xa9,0x42,0x08,0x95,0x1d,0xbf,0xc0,0x3e,0x2e,0x8f,0x58,0x63,0xc3,0xd3,0xb2,0xef,0xe2,0x51,0xbb,0x38,0x14,0x96,0x0a,0x86,0xbf,0x1c,0x3c,0x78,0xd7,0x83,0x15}, - {0xe1,0x7a,0xa2,0x5d,0xef,0xa2,0xee,0xec,0x74,0x01,0x67,0x55,0x14,0x3a,0x7c,0x59,0x7a,0x16,0x09,0x66,0x12,0x2a,0xa6,0xc9,0x70,0x8f,0xed,0x81,0x2e,0x5f,0x2a,0x25,0xc7,0x28,0x9d,0xcc,0x04,0x47,0x03,0x90,0x8f,0xc5,0x2c,0xf7,0x9e,0x67,0x1b,0x1d,0x26,0x87,0x5b,0xbe,0x5f,0x2b,0xe1,0x16,0x0a,0x58,0xc5,0x83,0x4e,0x06,0x58,0x49,0x0d,0xe8,0x66,0x50,0x26,0x94,0x28,0x0d,0x6b,0x8c,0x7c,0x30,0x85,0xf7,0xc3,0xfc,0xfd,0x12,0x11,0x0c,0x78,0xda,0x53,0x1b,0x88,0xb3,0x43,0xd8,0x0b,0x17,0x9c,0x07}, - {0xff,0x6f,0xfa,0x64,0xe4,0xec,0x06,0x05,0x23,0xe5,0x05,0x62,0x1e,0x43,0xe3,0xbe,0x42,0xea,0xb8,0x51,0x24,0x42,0x79,0x35,0x00,0xfb,0xc9,0x4a,0xe3,0x05,0xec,0x6d,0x56,0xd0,0xd5,0xc0,0x50,0xcd,0xd6,0xcd,0x3b,0x57,0x03,0xbb,0x6d,0x68,0xf7,0x9a,0x48,0xef,0xc3,0xf3,0x3f,0x72,0xa6,0x3c,0xcc,0x8a,0x7b,0x31,0xd7,0xc0,0x68,0x67,0xb3,0xc1,0x55,0xf1,0xe5,0x25,0xb6,0x94,0x91,0x7b,0x7b,0x99,0xa7,0xf3,0x7b,0x41,0x00,0x26,0x6b,0x6d,0xdc,0xbd,0x2c,0xc2,0xf4,0x52,0xcd,0xdd,0x14,0x5e,0x44,0x51}, - {0x51,0x49,0x14,0x3b,0x4b,0x2b,0x50,0x57,0xb3,0xbc,0x4b,0x44,0x6b,0xff,0x67,0x8e,0xdb,0x85,0x63,0x16,0x27,0x69,0xbd,0xb8,0xc8,0x95,0x92,0xe3,0x31,0x6f,0x18,0x13,0x55,0xa4,0xbe,0x2b,0xab,0x47,0x31,0x89,0x29,0x91,0x07,0x92,0x4f,0xa2,0x53,0x8c,0xa7,0xf7,0x30,0xbe,0x48,0xf9,0x49,0x4b,0x3d,0xd4,0x4f,0x6e,0x08,0x90,0xe9,0x12,0x2e,0xbb,0xdf,0x7f,0xb3,0x96,0x0c,0xf1,0xf9,0xea,0x1c,0x12,0x5e,0x93,0x9a,0x9f,0x3f,0x98,0x5b,0x3a,0xc4,0x36,0x11,0xdf,0xaf,0x99,0x3e,0x5d,0xf0,0xe3,0xb2,0x77}, - {0xde,0xc4,0x2e,0x9c,0xc5,0xa9,0x6f,0x29,0xcb,0xf3,0x84,0x4f,0xbf,0x61,0x8b,0xbc,0x08,0xf9,0xa8,0x17,0xd9,0x06,0x77,0x1c,0x5d,0x25,0xd3,0x7a,0xfc,0x95,0xb7,0x63,0xa4,0xb0,0xdd,0x12,0x9c,0x63,0x98,0xd5,0x6b,0x86,0x24,0xc0,0x30,0x9f,0xd1,0xa5,0x60,0xe4,0xfc,0x58,0x03,0x2f,0x7c,0xd1,0x8a,0x5e,0x09,0x2e,0x15,0x95,0xa1,0x07,0xc8,0x5f,0x9e,0x38,0x02,0x8f,0x36,0xa8,0x3b,0xe4,0x8d,0xcf,0x02,0x3b,0x43,0x90,0x43,0x26,0x41,0xc5,0x5d,0xfd,0xa1,0xaf,0x37,0x01,0x2f,0x03,0x3d,0xe8,0x8f,0x3e}, - {0x94,0xa2,0x70,0x05,0xb9,0x15,0x8b,0x2f,0x49,0x45,0x08,0x67,0x70,0x42,0xf2,0x94,0x84,0xfd,0xbb,0x61,0xe1,0x5a,0x1c,0xde,0x07,0x40,0xac,0x7f,0x79,0x3b,0xba,0x75,0x3c,0xd1,0xef,0xe8,0x8d,0x4c,0x70,0x08,0x31,0x37,0xe0,0x33,0x8e,0x1a,0xc5,0xdf,0xe3,0xcd,0x60,0x12,0xa5,0x5d,0x9d,0xa5,0x86,0x8c,0x25,0xa6,0x99,0x08,0xd6,0x22,0x96,0xd1,0xcd,0x70,0xc0,0xdb,0x39,0x62,0x9a,0x8a,0x7d,0x6c,0x8b,0x8a,0xfe,0x60,0x60,0x12,0x40,0xeb,0xbc,0x47,0x88,0xb3,0x5e,0x9e,0x77,0x87,0x7b,0xd0,0x04,0x09}, - {0x9c,0x91,0xba,0xdd,0xd4,0x1f,0xce,0xb4,0xaa,0x8d,0x4c,0xc7,0x3e,0xdb,0x31,0xcf,0x51,0xcc,0x86,0xad,0x63,0xcc,0x63,0x2c,0x07,0xde,0x1d,0xbc,0x3f,0x14,0xe2,0x43,0xb9,0x40,0xf9,0x48,0x66,0x2d,0x32,0xf4,0x39,0x0c,0x2d,0xbd,0x0c,0x2f,0x95,0x06,0x31,0xf9,0x81,0xa0,0xad,0x97,0x76,0x16,0x6c,0x2a,0xf7,0xba,0xce,0xaa,0x40,0x62,0xa0,0x95,0xa2,0x5b,0x9c,0x74,0x34,0xf8,0x5a,0xd2,0x37,0xca,0x5b,0x7c,0x94,0xd6,0x6a,0x31,0xc9,0xe7,0xa7,0x3b,0xf1,0x66,0xac,0x0c,0xb4,0x8d,0x23,0xaf,0xbd,0x56}, - {0xeb,0x33,0x35,0xf5,0xe3,0xb9,0x2a,0x36,0x40,0x3d,0xb9,0x6e,0xd5,0x68,0x85,0x33,0x72,0x55,0x5a,0x1d,0x52,0x14,0x0e,0x9e,0x18,0x13,0x74,0x83,0x6d,0xa8,0x24,0x1d,0xb2,0x3b,0x9d,0xc1,0x6c,0xd3,0x10,0x13,0xb9,0x86,0x23,0x62,0xb7,0x6b,0x2a,0x06,0x5c,0x4f,0xa1,0xd7,0x91,0x85,0x9b,0x7c,0x54,0x57,0x1e,0x7e,0x50,0x31,0xaa,0x03,0x1f,0xce,0xd4,0xff,0x48,0x76,0xec,0xf4,0x1c,0x8c,0xac,0x54,0xf0,0xea,0x45,0xe0,0x7c,0x35,0x09,0x1d,0x82,0x25,0xd2,0x88,0x59,0x48,0xeb,0x9a,0xdc,0x61,0xb2,0x43}, - {0xbb,0x79,0xbb,0x88,0x19,0x1e,0x5b,0xe5,0x9d,0x35,0x7a,0xc1,0x7d,0xd0,0x9e,0xa0,0x33,0xea,0x3d,0x60,0xe2,0x2e,0x2c,0xb0,0xc2,0x6b,0x27,0x5b,0xcf,0x55,0x60,0x32,0x64,0x13,0x95,0x6c,0x8b,0x3d,0x51,0x19,0x7b,0xf4,0x0b,0x00,0x26,0x71,0xfe,0x94,0x67,0x95,0x4f,0xd5,0xdd,0x10,0x8d,0x02,0x64,0x09,0x94,0x42,0xe2,0xd5,0xb4,0x02,0xf2,0x8d,0xd1,0x28,0xcb,0x55,0xa1,0xb4,0x08,0xe5,0x6c,0x18,0x46,0x46,0xcc,0xea,0x89,0x43,0x82,0x6c,0x93,0xf4,0x9c,0xc4,0x10,0x34,0x5d,0xae,0x09,0xc8,0xa6,0x27}, - {0x88,0xb1,0x0d,0x1f,0xcd,0xeb,0xa6,0x8b,0xe8,0x5b,0x5a,0x67,0x3a,0xd7,0xd3,0x37,0x5a,0x58,0xf5,0x15,0xa3,0xdf,0x2e,0xf2,0x7e,0xa1,0x60,0xff,0x74,0x71,0xb6,0x2c,0x54,0x69,0x3d,0xc4,0x0a,0x27,0x2c,0xcd,0xb2,0xca,0x66,0x6a,0x57,0x3e,0x4a,0xdd,0x6c,0x03,0xd7,0x69,0x24,0x59,0xfa,0x79,0x99,0x25,0x8c,0x3d,0x60,0x03,0x15,0x22,0xd0,0xe1,0x0b,0x39,0xf9,0xcd,0xee,0x59,0xf1,0xe3,0x8c,0x72,0x44,0x20,0x42,0xa9,0xf4,0xf0,0x94,0x7a,0x66,0x1c,0x89,0x82,0x36,0xf4,0x90,0x38,0xb7,0xf4,0x1d,0x7b}, - {0x24,0xa2,0xb2,0xb3,0xe0,0xf2,0x92,0xe4,0x60,0x11,0x55,0x2b,0x06,0x9e,0x6c,0x7c,0x0e,0x7b,0x7f,0x0d,0xe2,0x8f,0xeb,0x15,0x92,0x59,0xfc,0x58,0x26,0xef,0xfc,0x61,0x8c,0xf5,0xf8,0x07,0x18,0x22,0x2e,0x5f,0xd4,0x09,0x94,0xd4,0x9f,0x5c,0x55,0xe3,0x30,0xa6,0xb6,0x1f,0x8d,0xa8,0xaa,0xb2,0x3d,0xe0,0x52,0xd3,0x45,0x82,0x69,0x68,0x7a,0x18,0x18,0x2a,0x85,0x5d,0xb1,0xdb,0xd7,0xac,0xdd,0x86,0xd3,0xaa,0xe4,0xf3,0x82,0xc4,0xf6,0x0f,0x81,0xe2,0xba,0x44,0xcf,0x01,0xaf,0x3d,0x47,0x4c,0xcf,0x46}, - {0xf9,0xe5,0xc4,0x9e,0xed,0x25,0x65,0x42,0x03,0x33,0x90,0x16,0x01,0xda,0x5e,0x0e,0xdc,0xca,0xe5,0xcb,0xf2,0xa7,0xb1,0x72,0x40,0x5f,0xeb,0x14,0xcd,0x7b,0x38,0x29,0x40,0x81,0x49,0xf1,0xa7,0x6e,0x3c,0x21,0x54,0x48,0x2b,0x39,0xf8,0x7e,0x1e,0x7c,0xba,0xce,0x29,0x56,0x8c,0xc3,0x88,0x24,0xbb,0xc5,0x8c,0x0d,0xe5,0xaa,0x65,0x10,0x57,0x0d,0x20,0xdf,0x25,0x45,0x2c,0x1c,0x4a,0x67,0xca,0xbf,0xd6,0x2d,0x3b,0x5c,0x30,0x40,0x83,0xe1,0xb1,0xe7,0x07,0x0a,0x16,0xe7,0x1c,0x4f,0xe6,0x98,0xa1,0x69}, - {0xbc,0x78,0x1a,0xd9,0xe0,0xb2,0x62,0x90,0x67,0x96,0x50,0xc8,0x9c,0x88,0xc9,0x47,0xb8,0x70,0x50,0x40,0x66,0x4a,0xf5,0x9d,0xbf,0xa1,0x93,0x24,0xa9,0xe6,0x69,0x73,0xed,0xca,0xc5,0xdc,0x34,0x44,0x01,0xe1,0x33,0xfb,0x84,0x3c,0x96,0x5d,0xed,0x47,0xe7,0xa0,0x86,0xed,0x76,0x95,0x01,0x70,0xe4,0xf9,0x67,0xd2,0x7b,0x69,0xb2,0x25,0x64,0x68,0x98,0x13,0xfb,0x3f,0x67,0x9d,0xb8,0xc7,0x5d,0x41,0xd9,0xfb,0xa5,0x3c,0x5e,0x3b,0x27,0xdf,0x3b,0xcc,0x4e,0xe0,0xd2,0x4c,0x4e,0xb5,0x3d,0x68,0x20,0x14}, - {0x97,0xd1,0x9d,0x24,0x1e,0xbd,0x78,0xb4,0x02,0xc1,0x58,0x5e,0x00,0x35,0x0c,0x62,0x5c,0xac,0xba,0xcc,0x2f,0xd3,0x02,0xfb,0x2d,0xa7,0x08,0xf5,0xeb,0x3b,0xb6,0x60,0xd0,0x5a,0xcc,0xc1,0x6f,0xbb,0xee,0x34,0x8b,0xac,0x46,0x96,0xe9,0x0c,0x1b,0x6a,0x53,0xde,0x6b,0xa6,0x49,0xda,0xb0,0xd3,0xc1,0x81,0xd0,0x61,0x41,0x3b,0xe8,0x31,0x4f,0x2b,0x06,0x9e,0x12,0xc7,0xe8,0x97,0xd8,0x0a,0x32,0x29,0x4f,0x8f,0xe4,0x49,0x3f,0x68,0x18,0x6f,0x4b,0xe1,0xec,0x5b,0x17,0x03,0x55,0x2d,0xb6,0x1e,0xcf,0x55}, - {0x58,0x3d,0xc2,0x65,0x10,0x10,0x79,0x58,0x9c,0x81,0x94,0x50,0x6d,0x08,0x9d,0x8b,0xa7,0x5f,0xc5,0x12,0xa9,0x2f,0x40,0xe2,0xd4,0x91,0x08,0x57,0x64,0x65,0x9a,0x66,0x52,0x8c,0xf5,0x7d,0xe3,0xb5,0x76,0x30,0x36,0xcc,0x99,0xe7,0xdd,0xb9,0x3a,0xd7,0x20,0xee,0x13,0x49,0xe3,0x1c,0x83,0xbd,0x33,0x01,0xba,0x62,0xaa,0xfb,0x56,0x1a,0xec,0xc9,0x9d,0x5c,0x50,0x6b,0x3e,0x94,0x1a,0x37,0x7c,0xa7,0xbb,0x57,0x25,0x30,0x51,0x76,0x34,0x41,0x56,0xae,0x73,0x98,0x5c,0x8a,0xc5,0x99,0x67,0x83,0xc4,0x13}, - {0xb9,0xe1,0xb3,0x5a,0x46,0x5d,0x3a,0x42,0x61,0x3f,0xf1,0xc7,0x87,0xc1,0x13,0xfc,0xb6,0xb9,0xb5,0xec,0x64,0x36,0xf8,0x19,0x07,0xb6,0x37,0xa6,0x93,0x0c,0xf8,0x66,0x80,0xd0,0x8b,0x5d,0x6a,0xfb,0xdc,0xc4,0x42,0x48,0x1a,0x57,0xec,0xc4,0xeb,0xde,0x65,0x53,0xe5,0xb8,0x83,0xe8,0xb2,0xd4,0x27,0xb8,0xe5,0xc8,0x7d,0xc8,0xbd,0x50,0x11,0xe1,0xdf,0x6e,0x83,0x37,0x6d,0x60,0xd9,0xab,0x11,0xf0,0x15,0x3e,0x35,0x32,0x96,0x3b,0xb7,0x25,0xc3,0x3a,0xb0,0x64,0xae,0xd5,0x5f,0x72,0x44,0x64,0xd5,0x1d}, - {0x7d,0x12,0x62,0x33,0xf8,0x7f,0xa4,0x8f,0x15,0x7c,0xcd,0x71,0xc4,0x6a,0x9f,0xbc,0x8b,0x0c,0x22,0x49,0x43,0x45,0x71,0x6e,0x2e,0x73,0x9f,0x21,0x12,0x59,0x64,0x0e,0x9a,0xc8,0xba,0x08,0x00,0xe6,0x97,0xc2,0xe0,0xc3,0xe1,0xea,0x11,0xea,0x4c,0x7d,0x7c,0x97,0xe7,0x9f,0xe1,0x8b,0xe3,0xf3,0xcd,0x05,0xa3,0x63,0x0f,0x45,0x3a,0x3a,0x27,0x46,0x39,0xd8,0x31,0x2f,0x8f,0x07,0x10,0xa5,0x94,0xde,0x83,0x31,0x9d,0x38,0x80,0x6f,0x99,0x17,0x6d,0x6c,0xe3,0xd1,0x7b,0xa8,0xa9,0x93,0x93,0x8d,0x8c,0x31}, - {0x19,0xfe,0xff,0x2a,0x03,0x5d,0x74,0xf2,0x66,0xdb,0x24,0x7f,0x49,0x3c,0x9f,0x0c,0xef,0x98,0x85,0xba,0xe3,0xd3,0x98,0xbc,0x14,0x53,0x1d,0x9a,0x67,0x7c,0x4c,0x22,0x98,0xd3,0x1d,0xab,0x29,0x9e,0x66,0x5d,0x3b,0x9e,0x2d,0x34,0x58,0x16,0x92,0xfc,0xcd,0x73,0x59,0xf3,0xfd,0x1d,0x85,0x55,0xf6,0x0a,0x95,0x25,0xc3,0x41,0x9a,0x50,0xe9,0x25,0xf9,0xa6,0xdc,0x6e,0xc0,0xbd,0x33,0x1f,0x1b,0x64,0xf4,0xf3,0x3e,0x79,0x89,0x3e,0x83,0x9d,0x80,0x12,0xec,0x82,0x89,0x13,0xa1,0x28,0x23,0xf0,0xbf,0x05}, - {0x0b,0xe0,0xca,0x23,0x70,0x13,0x32,0x36,0x59,0xcf,0xac,0xd1,0x0a,0xcf,0x4a,0x54,0x88,0x1c,0x1a,0xd2,0x49,0x10,0x74,0x96,0xa7,0x44,0x2a,0xfa,0xc3,0x8c,0x0b,0x78,0xe4,0x12,0xc5,0x0d,0xdd,0xa0,0x81,0x68,0xfe,0xfa,0xa5,0x44,0xc8,0x0d,0xe7,0x4f,0x40,0x52,0x4a,0x8f,0x6b,0x8e,0x74,0x1f,0xea,0xa3,0x01,0xee,0xcd,0x77,0x62,0x57,0x5f,0x30,0x4f,0x23,0xbc,0x8a,0xf3,0x1e,0x08,0xde,0x05,0x14,0xbd,0x7f,0x57,0x9a,0x0d,0x2a,0xe6,0x34,0x14,0xa5,0x82,0x5e,0xa1,0xb7,0x71,0x62,0x72,0x18,0xf4,0x5f}, - {0x9d,0xdb,0x89,0x17,0x0c,0x08,0x8e,0x39,0xf5,0x78,0xe7,0xf3,0x25,0x20,0x60,0xa7,0x5d,0x03,0xbd,0x06,0x4c,0x89,0x98,0xfa,0xbe,0x66,0xa9,0x25,0xdc,0x03,0x6a,0x10,0x40,0x95,0xb6,0x13,0xe8,0x47,0xdb,0xe5,0xe1,0x10,0x26,0x43,0x3b,0x2a,0x5d,0xf3,0x76,0x12,0x78,0x38,0xe9,0x26,0x1f,0xac,0x69,0xcb,0xa0,0xa0,0x8c,0xdb,0xd4,0x29,0xd0,0x53,0x33,0x33,0xaf,0x0a,0xad,0xd9,0xe5,0x09,0xd3,0xac,0xa5,0x9d,0x66,0x38,0xf0,0xf7,0x88,0xc8,0x8a,0x65,0x57,0x3c,0xfa,0xbe,0x2c,0x05,0x51,0x8a,0xb3,0x4a}, - {0x93,0xd5,0x68,0x67,0x25,0x2b,0x7c,0xda,0x13,0xca,0x22,0x44,0x57,0xc0,0xc1,0x98,0x1d,0xce,0x0a,0xca,0xd5,0x0b,0xa8,0xf1,0x90,0xa6,0x88,0xc0,0xad,0xd1,0xcd,0x29,0x9c,0xc0,0xdd,0x5f,0xef,0xd1,0xcf,0xd6,0xce,0x5d,0x57,0xf7,0xfd,0x3e,0x2b,0xe8,0xc2,0x34,0x16,0x20,0x5d,0x6b,0xd5,0x25,0x9b,0x2b,0xed,0x04,0xbb,0xc6,0x41,0x30,0x48,0xe1,0x56,0xd9,0xf9,0xf2,0xf2,0x0f,0x2e,0x6b,0x35,0x9f,0x75,0x97,0xe7,0xad,0x5c,0x02,0x6c,0x5f,0xbb,0x98,0x46,0x1a,0x7b,0x9a,0x04,0x14,0x68,0xbd,0x4b,0x10}, - {0x67,0xed,0xf1,0x68,0x31,0xfd,0xf0,0x51,0xc2,0x3b,0x6f,0xd8,0xcd,0x1d,0x81,0x2c,0xde,0xf2,0xd2,0x04,0x43,0x5c,0xdc,0x44,0x49,0x71,0x2a,0x09,0x57,0xcc,0xe8,0x5b,0x63,0xf1,0x7f,0xd6,0x5f,0x9a,0x5d,0xa9,0x81,0x56,0xc7,0x4c,0x9d,0xe6,0x2b,0xe9,0x57,0xf2,0x20,0xde,0x4c,0x02,0xf8,0xb7,0xf5,0x2d,0x07,0xfb,0x20,0x2a,0x4f,0x20,0x79,0xb0,0xeb,0x30,0x3d,0x3b,0x14,0xc8,0x30,0x2e,0x65,0xbd,0x5a,0x15,0x89,0x75,0x31,0x5c,0x6d,0x8f,0x31,0x3c,0x3c,0x65,0x1f,0x16,0x79,0xc2,0x17,0xfb,0x70,0x25}, - {0x75,0x15,0xb6,0x2c,0x7f,0x36,0xfa,0x3e,0x6c,0x02,0xd6,0x1c,0x76,0x6f,0xf9,0xf5,0x62,0x25,0xb5,0x65,0x2a,0x14,0xc7,0xe8,0xcd,0x0a,0x03,0x53,0xea,0x65,0xcb,0x3d,0x5a,0x24,0xb8,0x0b,0x55,0xa9,0x2e,0x19,0xd1,0x50,0x90,0x8f,0xa8,0xfb,0xe6,0xc8,0x35,0xc9,0xa4,0x88,0x2d,0xea,0x86,0x79,0x68,0x86,0x01,0xde,0x91,0x5f,0x1c,0x24,0xaa,0x6c,0xde,0x40,0x29,0x17,0xd8,0x28,0x3a,0x73,0xd9,0x22,0xf0,0x2c,0xbf,0x8f,0xd1,0x01,0x5b,0x23,0xdd,0xfc,0xd7,0x16,0xe5,0xf0,0xcd,0x5f,0xdd,0x0e,0x42,0x08}, - {0x4a,0xfa,0x62,0x83,0xab,0x20,0xff,0xcd,0x6e,0x3e,0x1a,0xe2,0xd4,0x18,0xe1,0x57,0x2b,0xe6,0x39,0xfc,0x17,0x96,0x17,0xe3,0xfd,0x69,0x17,0xbc,0xef,0x53,0x9a,0x0d,0xce,0x10,0xf4,0x04,0x4e,0xc3,0x58,0x03,0x85,0x06,0x6e,0x27,0x5a,0x5b,0x13,0xb6,0x21,0x15,0xb9,0xeb,0xc7,0x70,0x96,0x5d,0x9c,0x88,0xdb,0x21,0xf3,0x54,0xd6,0x04,0xd5,0xb5,0xbd,0xdd,0x16,0xc1,0x7d,0x5e,0x2d,0xdd,0xa5,0x8d,0xb6,0xde,0x54,0x29,0x92,0xa2,0x34,0x33,0x17,0x08,0xb6,0x1c,0xd7,0x1a,0x99,0x18,0x26,0x4f,0x7a,0x4a}, - {0x95,0x5f,0xb1,0x5f,0x02,0x18,0xa7,0xf4,0x8f,0x1b,0x5c,0x6b,0x34,0x5f,0xf6,0x3d,0x12,0x11,0xe0,0x00,0x85,0xf0,0xfc,0xcd,0x48,0x18,0xd3,0xdd,0x4c,0x0c,0xb5,0x11,0x4b,0x2a,0x37,0xaf,0x91,0xb2,0xc3,0x24,0xf2,0x47,0x81,0x71,0x70,0x82,0xda,0x93,0xf2,0x9e,0x89,0x86,0x64,0x85,0x84,0xdd,0x33,0xee,0xe0,0x23,0x42,0x31,0x96,0x4a,0xd6,0xff,0xa4,0x08,0x44,0x27,0xe8,0xa6,0xd9,0x76,0x15,0x9c,0x7e,0x17,0x8e,0x73,0xf2,0xb3,0x02,0x3d,0xb6,0x48,0x33,0x77,0x51,0xcc,0x6b,0xce,0x4d,0xce,0x4b,0x4f}, - {0x84,0x25,0x24,0xe2,0x5a,0xce,0x1f,0xa7,0x9e,0x8a,0xf5,0x92,0x56,0x72,0xea,0x26,0xf4,0x3c,0xea,0x1c,0xd7,0x09,0x1a,0xd2,0xe6,0x01,0x1c,0xb7,0x14,0xdd,0xfc,0x73,0x6f,0x0b,0x9d,0xc4,0x6e,0x61,0xe2,0x30,0x17,0x23,0xec,0xca,0x8f,0x71,0x56,0xe4,0xa6,0x4f,0x6b,0xf2,0x9b,0x40,0xeb,0x48,0x37,0x5f,0x59,0x61,0xe5,0xce,0x42,0x30,0x41,0xac,0x9b,0x44,0x79,0x70,0x7e,0x42,0x0a,0x31,0xe2,0xbc,0x6d,0xe3,0x5a,0x85,0x7c,0x1a,0x84,0x5f,0x21,0x76,0xae,0x4c,0xd6,0xe1,0x9c,0x9a,0x0c,0x74,0x9e,0x38}, - {0xce,0xb9,0xdc,0x34,0xae,0xb3,0xfc,0x64,0xad,0xd0,0x48,0xe3,0x23,0x03,0x50,0x97,0x1b,0x38,0xc6,0x62,0x7d,0xf0,0xb3,0x45,0x88,0x67,0x5a,0x46,0x79,0x53,0x54,0x61,0x28,0xac,0x0e,0x57,0xf6,0x78,0xbd,0xc9,0xe1,0x9c,0x91,0x27,0x32,0x0b,0x5b,0xe5,0xed,0x91,0x9b,0xa1,0xab,0x3e,0xfc,0x65,0x90,0x36,0x26,0xd6,0xe5,0x25,0xc4,0x25,0x6e,0xde,0xd7,0xf1,0xa6,0x06,0x3e,0x3f,0x08,0x23,0x06,0x8e,0x27,0x76,0xf9,0x3e,0x77,0x6c,0x8a,0x4e,0x26,0xf6,0x14,0x8c,0x59,0x47,0x48,0x15,0x89,0xa0,0x39,0x65}, - {0x73,0xf7,0xd2,0xc3,0x74,0x1f,0xd2,0xe9,0x45,0x68,0xc4,0x25,0x41,0x54,0x50,0xc1,0x33,0x9e,0xb9,0xf9,0xe8,0x5c,0x4e,0x62,0x6c,0x18,0xcd,0xc5,0xaa,0xe4,0xc5,0x11,0x19,0x4a,0xbb,0x14,0xd4,0xdb,0xc4,0xdd,0x8e,0x4f,0x42,0x98,0x3c,0xbc,0xb2,0x19,0x69,0x71,0xca,0x36,0xd7,0x9f,0xa8,0x48,0x90,0xbd,0x19,0xf0,0x0e,0x32,0x65,0x0f,0xc6,0xe0,0xfd,0xca,0xb1,0xd1,0x86,0xd4,0x81,0x51,0x3b,0x16,0xe3,0xe6,0x3f,0x4f,0x9a,0x93,0xf2,0xfa,0x0d,0xaf,0xa8,0x59,0x2a,0x07,0x33,0xec,0xbd,0xc7,0xab,0x4c}, - {0x2e,0x0a,0x9c,0x08,0x24,0x96,0x9e,0x23,0x38,0x47,0xfe,0x3a,0xc0,0xc4,0x48,0xc7,0x2a,0xa1,0x4f,0x76,0x2a,0xed,0xdb,0x17,0x82,0x85,0x1c,0x32,0xf0,0x93,0x9b,0x63,0x89,0xd2,0x78,0x3f,0x8f,0x78,0x8f,0xc0,0x9f,0x4d,0x40,0xa1,0x2c,0xa7,0x30,0xfe,0x9d,0xcc,0x65,0xcf,0xfc,0x8b,0x77,0xf2,0x21,0x20,0xcb,0x5a,0x16,0x98,0xe4,0x7e,0xc3,0xa1,0x11,0x91,0xe3,0x08,0xd5,0x7b,0x89,0x74,0x90,0x80,0xd4,0x90,0x2b,0x2b,0x19,0xfd,0x72,0xae,0xc2,0xae,0xd2,0xe7,0xa6,0x02,0xb6,0x85,0x3c,0x49,0xdf,0x0e}, - {0x68,0x5a,0x9b,0x59,0x58,0x81,0xcc,0xae,0x0e,0xe2,0xad,0xeb,0x0f,0x4f,0x57,0xea,0x07,0x7f,0xb6,0x22,0x74,0x1d,0xe4,0x4f,0xb4,0x4f,0x9d,0x01,0xe3,0x92,0x3b,0x40,0x13,0x41,0x76,0x84,0xd2,0xc4,0x67,0x67,0x35,0xf8,0xf5,0xf7,0x3f,0x40,0x90,0xa0,0xde,0xbe,0xe6,0xca,0xfa,0xcf,0x8f,0x1c,0x69,0xa3,0xdf,0xd1,0x54,0x0c,0xc0,0x04,0xf8,0x5c,0x46,0x8b,0x81,0x2f,0xc2,0x4d,0xf8,0xef,0x80,0x14,0x5a,0xf3,0xa0,0x71,0x57,0xd6,0xc7,0x04,0xad,0xbf,0xe8,0xae,0xf4,0x76,0x61,0xb2,0x2a,0xb1,0x5b,0x35}, - {0xf4,0xbb,0x93,0x74,0xcc,0x64,0x1e,0xa7,0xc3,0xb0,0xa3,0xec,0xd9,0x84,0xbd,0xe5,0x85,0xe7,0x05,0xfa,0x0c,0xc5,0x6b,0x0a,0x12,0xc3,0x2e,0x18,0x32,0x81,0x9b,0x0f,0x18,0x73,0x8c,0x5a,0xc7,0xda,0x01,0xa3,0x11,0xaa,0xce,0xb3,0x9d,0x03,0x90,0xed,0x2d,0x3f,0xae,0x3b,0xbf,0x7c,0x07,0x6f,0x8e,0xad,0x52,0xe0,0xf8,0xea,0x18,0x75,0x32,0x6c,0x7f,0x1b,0xc4,0x59,0x88,0xa4,0x98,0x32,0x38,0xf4,0xbc,0x60,0x2d,0x0f,0xd9,0xd1,0xb1,0xc9,0x29,0xa9,0x15,0x18,0xc4,0x55,0x17,0xbb,0x1b,0x87,0xc3,0x47}, - {0x48,0x4f,0xec,0x71,0x97,0x53,0x44,0x51,0x6e,0x5d,0x8c,0xc9,0x7d,0xb1,0x05,0xf8,0x6b,0xc6,0xc3,0x47,0x1a,0xc1,0x62,0xf7,0xdc,0x99,0x46,0x76,0x85,0x9b,0xb8,0x00,0xb0,0x66,0x50,0xc8,0x50,0x5d,0xe6,0xfb,0xb0,0x99,0xa2,0xb3,0xb0,0xc4,0xec,0x62,0xe0,0xe8,0x1a,0x44,0xea,0x54,0x37,0xe5,0x5f,0x8d,0xd4,0xe8,0x2c,0xa0,0xfe,0x08,0xd0,0xea,0xde,0x68,0x76,0xdd,0x4d,0x82,0x23,0x5d,0x68,0x4b,0x20,0x45,0x64,0xc8,0x65,0xd6,0x89,0x5d,0xcd,0xcf,0x14,0xb5,0x37,0xd5,0x75,0x4f,0xa7,0x29,0x38,0x47}, - {0x18,0xc4,0x79,0x46,0x75,0xda,0xd2,0x82,0xf0,0x8d,0x61,0xb2,0xd8,0xd7,0x3b,0xe6,0x0a,0xeb,0x47,0xac,0x24,0xef,0x5e,0x35,0xb4,0xc6,0x33,0x48,0x4c,0x68,0x78,0x20,0xc9,0x02,0x39,0xad,0x3a,0x53,0xd9,0x23,0x8f,0x58,0x03,0xef,0xce,0xdd,0xc2,0x64,0xb4,0x2f,0xe1,0xcf,0x90,0x73,0x25,0x15,0x90,0xd3,0xe4,0x44,0x4d,0x8b,0x66,0x6c,0x0c,0x82,0x78,0x7a,0x21,0xcf,0x48,0x3b,0x97,0x3e,0x27,0x81,0xb2,0x0a,0x6a,0xf7,0x7b,0xed,0x8e,0x8c,0xa7,0x65,0x6c,0xa9,0x3f,0x43,0x8a,0x4f,0x05,0xa6,0x11,0x74}, - {0x6d,0xc8,0x9d,0xb9,0x32,0x9d,0x65,0x4d,0x15,0xf1,0x3a,0x60,0x75,0xdc,0x4c,0x04,0x88,0xe4,0xc2,0xdc,0x2c,0x71,0x4c,0xb3,0xff,0x34,0x81,0xfb,0x74,0x65,0x13,0x7c,0xb4,0x75,0xb1,0x18,0x3d,0xe5,0x9a,0x57,0x02,0xa1,0x92,0xf3,0x59,0x31,0x71,0x68,0xf5,0x35,0xef,0x1e,0xba,0xec,0x55,0x84,0x8f,0x39,0x8c,0x45,0x72,0xa8,0xc9,0x1e,0x9b,0x50,0xa2,0x00,0xd4,0xa4,0xe6,0xb8,0xb4,0x82,0xc8,0x0b,0x02,0xd7,0x81,0x9b,0x61,0x75,0x95,0xf1,0x9b,0xcc,0xe7,0x57,0x60,0x64,0xcd,0xc7,0xa5,0x88,0xdd,0x3a}, - {0xf2,0xdc,0x35,0xb6,0x70,0x57,0x89,0xab,0xbc,0x1f,0x6c,0xf6,0x6c,0xef,0xdf,0x02,0x87,0xd1,0xb6,0xbe,0x68,0x02,0x53,0x85,0x74,0x9e,0x87,0xcc,0xfc,0x29,0x99,0x24,0x46,0x30,0x39,0x59,0xd4,0x98,0xc2,0x85,0xec,0x59,0xf6,0x5f,0x98,0x35,0x7e,0x8f,0x3a,0x6e,0xf6,0xf2,0x2a,0xa2,0x2c,0x1d,0x20,0xa7,0x06,0xa4,0x31,0x11,0xba,0x61,0x29,0x90,0x95,0x16,0xf1,0xa0,0xd0,0xa3,0x89,0xbd,0x7e,0xba,0x6c,0x6b,0x3b,0x02,0x07,0x33,0x78,0x26,0x3e,0x5a,0xf1,0x7b,0xe7,0xec,0xd8,0xbb,0x0c,0x31,0x20,0x56}, - {0x43,0xd6,0x34,0x49,0x43,0x93,0x89,0x52,0xf5,0x22,0x12,0xa5,0x06,0xf8,0xdb,0xb9,0x22,0x1c,0xf4,0xc3,0x8f,0x87,0x6d,0x8f,0x30,0x97,0x9d,0x4d,0x2a,0x6a,0x67,0x37,0xd6,0x85,0xe2,0x77,0xf4,0xb5,0x46,0x66,0x93,0x61,0x8f,0x6c,0x67,0xff,0xe8,0x40,0xdd,0x94,0xb5,0xab,0x11,0x73,0xec,0xa6,0x4d,0xec,0x8c,0x65,0xf3,0x46,0xc8,0x7e,0xc7,0x2e,0xa2,0x1d,0x3f,0x8f,0x5e,0x9b,0x13,0xcd,0x01,0x6c,0x77,0x1d,0x0f,0x13,0xb8,0x9f,0x98,0xa2,0xcf,0x8f,0x4c,0x21,0xd5,0x9d,0x9b,0x39,0x23,0xf7,0xaa,0x6d}, - {0x47,0xbe,0x3d,0xeb,0x62,0x75,0x3a,0x5f,0xb8,0xa0,0xbd,0x8e,0x54,0x38,0xea,0xf7,0x99,0x72,0x74,0x45,0x31,0xe5,0xc3,0x00,0x51,0xd5,0x27,0x16,0xe7,0xe9,0x04,0x13,0xa2,0x8e,0xad,0xac,0xbf,0x04,0x3b,0x58,0x84,0xe8,0x8b,0x14,0xe8,0x43,0xb7,0x29,0xdb,0xc5,0x10,0x08,0x3b,0x58,0x1e,0x2b,0xaa,0xbb,0xb3,0x8e,0xe5,0x49,0x54,0x2b,0xfe,0x9c,0xdc,0x6a,0xd2,0x14,0x98,0x78,0x0b,0xdd,0x48,0x8b,0x3f,0xab,0x1b,0x3c,0x0a,0xc6,0x79,0xf9,0xff,0xe1,0x0f,0xda,0x93,0xd6,0x2d,0x7c,0x2d,0xde,0x68,0x44}, - {0x9e,0x46,0x19,0x94,0x5e,0x35,0xbb,0x51,0x54,0xc7,0xdd,0x23,0x4c,0xdc,0xe6,0x33,0x62,0x99,0x7f,0x44,0xd6,0xb6,0xa5,0x93,0x63,0xbd,0x44,0xfb,0x6f,0x7c,0xce,0x6c,0xce,0x07,0x63,0xf8,0xc6,0xd8,0x9a,0x4b,0x28,0x0c,0x5d,0x43,0x31,0x35,0x11,0x21,0x2c,0x77,0x7a,0x65,0xc5,0x66,0xa8,0xd4,0x52,0x73,0x24,0x63,0x7e,0x42,0xa6,0x5d,0xca,0x22,0xac,0xde,0x88,0xc6,0x94,0x1a,0xf8,0x1f,0xae,0xbb,0xf7,0x6e,0x06,0xb9,0x0f,0x58,0x59,0x8d,0x38,0x8c,0xad,0x88,0xa8,0x2c,0x9f,0xe7,0xbf,0x9a,0xf2,0x58}, - {0x68,0x3e,0xe7,0x8d,0xab,0xcf,0x0e,0xe9,0xa5,0x76,0x7e,0x37,0x9f,0x6f,0x03,0x54,0x82,0x59,0x01,0xbe,0x0b,0x5b,0x49,0xf0,0x36,0x1e,0xf4,0xa7,0xc4,0x29,0x76,0x57,0xf6,0xcd,0x0e,0x71,0xbf,0x64,0x5a,0x4b,0x3c,0x29,0x2c,0x46,0x38,0xe5,0x4c,0xb1,0xb9,0x3a,0x0b,0xd5,0x56,0xd0,0x43,0x36,0x70,0x48,0x5b,0x18,0x24,0x37,0xf9,0x6a,0x88,0xa8,0xc6,0x09,0x45,0x02,0x20,0x32,0x73,0x89,0x55,0x4b,0x13,0x36,0xe0,0xd2,0x9f,0x28,0x33,0x3c,0x23,0x36,0xe2,0x83,0x8f,0xc1,0xae,0x0c,0xbb,0x25,0x1f,0x70}, - {0xed,0x6c,0x61,0xe4,0xf8,0xb0,0xa8,0xc3,0x7d,0xa8,0x25,0x9e,0x0e,0x66,0x00,0xf7,0x9c,0xa5,0xbc,0xf4,0x1f,0x06,0xe3,0x61,0xe9,0x0b,0xc4,0xbd,0xbf,0x92,0x0c,0x2e,0x13,0xc1,0xbe,0x7c,0xd9,0xf6,0x18,0x9d,0xe4,0xdb,0xbf,0x74,0xe6,0x06,0x4a,0x84,0xd6,0x60,0x4e,0xac,0x22,0xb5,0xf5,0x20,0x51,0x5e,0x95,0x50,0xc0,0x5b,0x0a,0x72,0x35,0x5a,0x80,0x9b,0x43,0x09,0x3f,0x0c,0xfc,0xab,0x42,0x62,0x37,0x8b,0x4e,0xe8,0x46,0x93,0x22,0x5c,0xf3,0x17,0x14,0x69,0xec,0xf0,0x4e,0x14,0xbb,0x9c,0x9b,0x0e}, - {0xad,0x20,0x57,0xfb,0x8f,0xd4,0xba,0xfb,0x0e,0x0d,0xf9,0xdb,0x6b,0x91,0x81,0xee,0xbf,0x43,0x55,0x63,0x52,0x31,0x81,0xd4,0xd8,0x7b,0x33,0x3f,0xeb,0x04,0x11,0x22,0xee,0xbe,0xb1,0x5d,0xd5,0x9b,0xee,0x8d,0xb9,0x3f,0x72,0x0a,0x37,0xab,0xc3,0xc9,0x91,0xd7,0x68,0x1c,0xbf,0xf1,0xa8,0x44,0xde,0x3c,0xfd,0x1c,0x19,0x44,0x6d,0x36,0x14,0x8c,0xbc,0xf2,0x43,0x17,0x3c,0x9e,0x3b,0x6c,0x85,0xb5,0xfc,0x26,0xda,0x2e,0x97,0xfb,0xa7,0x68,0x0e,0x2f,0xb8,0xcc,0x44,0x32,0x59,0xbc,0xe6,0xa4,0x67,0x41}, - {0x00,0x27,0xf6,0x76,0x28,0x9d,0x3b,0x64,0xeb,0x68,0x76,0x0e,0x40,0x9d,0x1d,0x5d,0x84,0x06,0xfc,0x21,0x03,0x43,0x4b,0x1b,0x6a,0x24,0x55,0x22,0x7e,0xbb,0x38,0x79,0xee,0x8f,0xce,0xf8,0x65,0x26,0xbe,0xc2,0x2c,0xd6,0x80,0xe8,0x14,0xff,0x67,0xe9,0xee,0x4e,0x36,0x2f,0x7e,0x6e,0x2e,0xf1,0xf6,0xd2,0x7e,0xcb,0x70,0x33,0xb3,0x34,0xcc,0xd6,0x81,0x86,0xee,0x91,0xc5,0xcd,0x53,0xa7,0x85,0xed,0x9c,0x10,0x02,0xce,0x83,0x88,0x80,0x58,0xc1,0x85,0x74,0xed,0xe4,0x65,0xfe,0x2d,0x6e,0xfc,0x76,0x11}, - {0x9b,0x61,0x9c,0x5b,0xd0,0x6c,0xaf,0xb4,0x80,0x84,0xa5,0xb2,0xf4,0xc9,0xdf,0x2d,0xc4,0x4d,0xe9,0xeb,0x02,0xa5,0x4f,0x3d,0x34,0x5f,0x7d,0x67,0x4c,0x3a,0xfc,0x08,0xb8,0x0e,0x77,0x49,0x89,0xe2,0x90,0xdb,0xa3,0x40,0xf4,0xac,0x2a,0xcc,0xfb,0x98,0x9b,0x87,0xd7,0xde,0xfe,0x4f,0x35,0x21,0xb6,0x06,0x69,0xf2,0x54,0x3e,0x6a,0x1f,0xea,0x34,0x07,0xd3,0x99,0xc1,0xa4,0x60,0xd6,0x5c,0x16,0x31,0xb6,0x85,0xc0,0x40,0x95,0x82,0x59,0xf7,0x23,0x3e,0x33,0xe2,0xd1,0x00,0xb9,0x16,0x01,0xad,0x2f,0x4f}, - {0x54,0x4e,0xae,0x94,0x41,0xb2,0xbe,0x44,0x6c,0xef,0x57,0x18,0x51,0x1c,0x54,0x5f,0x98,0x04,0x8d,0x36,0x2d,0x6b,0x1e,0xa6,0xab,0xf7,0x2e,0x97,0xa4,0x84,0x54,0x44,0x38,0xb6,0x3b,0xb7,0x1d,0xd9,0x2c,0x96,0x08,0x9c,0x12,0xfc,0xaa,0x77,0x05,0xe6,0x89,0x16,0xb6,0xf3,0x39,0x9b,0x61,0x6f,0x81,0xee,0x44,0x29,0x5f,0x99,0x51,0x34,0x7c,0x7d,0xea,0x9f,0xd0,0xfc,0x52,0x91,0xf6,0x5c,0x93,0xb0,0x94,0x6c,0x81,0x4a,0x40,0x5c,0x28,0x47,0xaa,0x9a,0x8e,0x25,0xb7,0x93,0x28,0x04,0xa6,0x9c,0xb8,0x10}, - {0x9c,0x28,0x18,0x97,0x49,0x47,0x59,0x3d,0x26,0x3f,0x53,0x24,0xc5,0xf8,0xeb,0x12,0x15,0xef,0xc3,0x14,0xcb,0xbf,0x62,0x02,0x8e,0x51,0xb7,0x77,0xd5,0x78,0xb8,0x20,0x6e,0xf0,0x45,0x5a,0xbe,0x41,0x39,0x75,0x65,0x5f,0x9c,0x6d,0xed,0xae,0x7c,0xd0,0xb6,0x51,0xff,0x72,0x9c,0x6b,0x77,0x11,0xa9,0x4d,0x0d,0xef,0xd9,0xd1,0xd2,0x17,0x6a,0x3e,0x3f,0x07,0x18,0xaf,0xf2,0x27,0x69,0x10,0x52,0xd7,0x19,0xe5,0x3f,0xfd,0x22,0x00,0xa6,0x3c,0x2c,0xb7,0xe3,0x22,0xa7,0xc6,0x65,0xcc,0x63,0x4f,0x21,0x72}, - {0x93,0xa6,0x07,0x53,0x40,0x7f,0xe3,0xb4,0x95,0x67,0x33,0x2f,0xd7,0x14,0xa7,0xab,0x99,0x10,0x76,0x73,0xa7,0xd0,0xfb,0xd6,0xc9,0xcb,0x71,0x81,0xc5,0x48,0xdf,0x5f,0xc9,0x29,0x3b,0xf4,0xb9,0xb7,0x9d,0x1d,0x75,0x8f,0x51,0x4f,0x4a,0x82,0x05,0xd6,0xc4,0x9d,0x2f,0x31,0xbd,0x72,0xc0,0xf2,0xb0,0x45,0x15,0x5a,0x85,0xac,0x24,0x1f,0xaa,0x05,0x95,0x8e,0x32,0x08,0xd6,0x24,0xee,0x20,0x14,0x0c,0xd1,0xc1,0x48,0x47,0xa2,0x25,0xfb,0x06,0x5c,0xe4,0xff,0xc7,0xe6,0x95,0xe3,0x2a,0x9e,0x73,0xba,0x00}, - {0xd6,0x90,0x87,0x5c,0xde,0x98,0x2e,0x59,0xdf,0xa2,0xc2,0x45,0xd3,0xb7,0xbf,0xe5,0x22,0x99,0xb4,0xf9,0x60,0x3b,0x5a,0x11,0xf3,0x78,0xad,0x67,0x3e,0x3a,0x28,0x03,0x26,0xbb,0x88,0xea,0xf5,0x26,0x44,0xae,0xfb,0x3b,0x97,0x84,0xd9,0x79,0x06,0x36,0x50,0x4e,0x69,0x26,0x0c,0x03,0x9f,0x5c,0x26,0xd2,0x18,0xd5,0xe7,0x7d,0x29,0x72,0x39,0xb9,0x0c,0xbe,0xc7,0x1d,0x24,0x48,0x80,0x30,0x63,0x8b,0x4d,0x9b,0xf1,0x32,0x08,0x93,0x28,0x02,0x0d,0xc9,0xdf,0xd3,0x45,0x19,0x27,0x46,0x68,0x29,0xe1,0x05}, - {0x5a,0x49,0x9c,0x2d,0xb3,0xee,0x82,0xba,0x7c,0xb9,0x2b,0xf1,0xfc,0xc8,0xef,0xce,0xe0,0xd1,0xb5,0x93,0xae,0xab,0x2d,0xb0,0x9b,0x8d,0x69,0x13,0x9c,0x0c,0xc0,0x39,0x50,0x45,0x2c,0x24,0xc8,0xbb,0xbf,0xad,0xd9,0x81,0x30,0xd0,0xec,0x0c,0xc8,0xbc,0x92,0xdf,0xc8,0xf5,0xa6,0x66,0x35,0x84,0x4c,0xce,0x58,0x82,0xd3,0x25,0xcf,0x78,0x68,0x9d,0x48,0x31,0x8e,0x6b,0xae,0x15,0x87,0xf0,0x2b,0x9c,0xab,0x1c,0x85,0xaa,0x05,0xfa,0x4e,0xf0,0x97,0x5a,0xa7,0xc9,0x32,0xf8,0x3f,0x6b,0x07,0x52,0x6b,0x00}, - {0x1c,0x78,0x95,0x9d,0xe1,0xcf,0xe0,0x29,0xe2,0x10,0x63,0x96,0x18,0xdf,0x81,0xb6,0x39,0x6b,0x51,0x70,0xd3,0x39,0xdf,0x57,0x22,0x61,0xc7,0x3b,0x44,0xe3,0x57,0x4d,0x2d,0x08,0xce,0xb9,0x16,0x7e,0xcb,0xf5,0x29,0xbc,0x7a,0x41,0x4c,0xf1,0x07,0x34,0xab,0xa7,0xf4,0x2b,0xce,0x6b,0xb3,0xd4,0xce,0x75,0x9f,0x1a,0x56,0xe9,0xe2,0x7d,0xcb,0x5e,0xa5,0xb6,0xf4,0xd4,0x70,0xde,0x99,0xdb,0x85,0x5d,0x7f,0x52,0x01,0x48,0x81,0x9a,0xee,0xd3,0x40,0xc4,0xc9,0xdb,0xed,0x29,0x60,0x1a,0xaf,0x90,0x2a,0x6b}, - {0x97,0x1e,0xe6,0x9a,0xfc,0xf4,0x23,0x69,0xd1,0x5f,0x3f,0xe0,0x1d,0x28,0x35,0x57,0x2d,0xd1,0xed,0xe6,0x43,0xae,0x64,0xa7,0x4a,0x3e,0x2d,0xd1,0xe9,0xf4,0xd8,0x5f,0x0a,0xd8,0xb2,0x5b,0x24,0xf3,0xeb,0x77,0x9b,0x07,0xb9,0x2f,0x47,0x1b,0x30,0xd8,0x33,0x73,0xee,0x4c,0xf2,0xe6,0x47,0xc6,0x09,0x21,0x6c,0x27,0xc8,0x12,0x58,0x46,0xd9,0x62,0x10,0x2a,0xb2,0xbe,0x43,0x4d,0x16,0xdc,0x31,0x38,0x75,0xfb,0x65,0x70,0xd7,0x68,0x29,0xde,0x7b,0x4a,0x0d,0x18,0x90,0x67,0xb1,0x1c,0x2b,0x2c,0xb3,0x05}, - {0xfd,0xa8,0x4d,0xd2,0xcc,0x5e,0xc0,0xc8,0x83,0xef,0xdf,0x05,0xac,0x1a,0xcf,0xa1,0x61,0xcd,0xf9,0x7d,0xf2,0xef,0xbe,0xdb,0x99,0x1e,0x47,0x7b,0xa3,0x56,0x55,0x3b,0x95,0x81,0xd5,0x7a,0x2c,0xa4,0xfc,0xf7,0xcc,0xf3,0x33,0x43,0x6e,0x28,0x14,0x32,0x9d,0x97,0x0b,0x34,0x0d,0x9d,0xc2,0xb6,0xe1,0x07,0x73,0x56,0x48,0x1a,0x77,0x31,0x82,0xd4,0x4d,0xe1,0x24,0xc5,0xb0,0x32,0xb6,0xa4,0x2b,0x1a,0x54,0x51,0xb3,0xed,0xf3,0x5a,0x2b,0x28,0x48,0x60,0xd1,0xa3,0xeb,0x36,0x73,0x7a,0xd2,0x79,0xc0,0x4f}, - {0x7f,0x2f,0xbf,0x89,0xb0,0x38,0xc9,0x51,0xa7,0xe9,0xdf,0x02,0x65,0xbd,0x97,0x24,0x53,0xe4,0x80,0x78,0x9c,0xc0,0xff,0xff,0x92,0x8e,0xf9,0xca,0xce,0x67,0x45,0x12,0x0d,0xc5,0x86,0x0c,0x44,0x8b,0x34,0xdc,0x51,0xe6,0x94,0xcc,0xc9,0xcb,0x37,0x13,0xb9,0x3c,0x3e,0x64,0x4d,0xf7,0x22,0x64,0x08,0xcd,0xe3,0xba,0xc2,0x70,0x11,0x24,0xb4,0x73,0xc4,0x0a,0x86,0xab,0xf9,0x3f,0x35,0xe4,0x13,0x01,0xee,0x1d,0x91,0xf0,0xaf,0xc4,0xc6,0xeb,0x60,0x50,0xe7,0x4a,0x0d,0x00,0x87,0x6c,0x96,0x12,0x86,0x3f}, - {0xde,0x0d,0x2a,0x78,0xc9,0x0c,0x9a,0x55,0x85,0x83,0x71,0xea,0xb2,0xcd,0x1d,0x55,0x8c,0x23,0xef,0x31,0x5b,0x86,0x62,0x7f,0x3d,0x61,0x73,0x79,0x76,0xa7,0x4a,0x50,0x13,0x8d,0x04,0x36,0xfa,0xfc,0x18,0x9c,0xdd,0x9d,0x89,0x73,0xb3,0x9d,0x15,0x29,0xaa,0xd0,0x92,0x9f,0x0b,0x35,0x9f,0xdc,0xd4,0x19,0x8a,0x87,0xee,0x7e,0xf5,0x26,0xb1,0xef,0x87,0x56,0xd5,0x2c,0xab,0x0c,0x7b,0xf1,0x7a,0x24,0x62,0xd1,0x80,0x51,0x67,0x24,0x5a,0x4f,0x34,0x5a,0xc1,0x85,0x69,0x30,0xba,0x9d,0x3d,0x94,0x41,0x40}, - {0x96,0xcc,0xeb,0x43,0xba,0xee,0xc0,0xc3,0xaf,0x9c,0xea,0x26,0x9c,0x9c,0x74,0x8d,0xc6,0xcc,0x77,0x1c,0xee,0x95,0xfa,0xd9,0x0f,0x34,0x84,0x76,0xd9,0xa1,0x20,0x14,0xdd,0xaa,0x6c,0xa2,0x43,0x77,0x21,0x4b,0xce,0xb7,0x8a,0x64,0x24,0xb4,0xa6,0x47,0xe3,0xc9,0xfb,0x03,0x7a,0x4f,0x1d,0xcb,0x19,0xd0,0x00,0x98,0x42,0x31,0xd9,0x12,0x4f,0x59,0x37,0xd3,0x99,0x77,0xc6,0x00,0x7b,0xa4,0x3a,0xb2,0x40,0x51,0x3c,0x5e,0x95,0xf3,0x5f,0xe3,0x54,0x28,0x18,0x44,0x12,0xa0,0x59,0x43,0x31,0x92,0x4f,0x1b}, - {0x51,0x09,0x15,0x89,0x9d,0x10,0x5c,0x3e,0x6a,0x69,0xe9,0x2d,0x91,0xfa,0xce,0x39,0x20,0x30,0x5f,0x97,0x3f,0xe4,0xea,0x20,0xae,0x2d,0x13,0x7f,0x2a,0x57,0x9b,0x23,0xb1,0x66,0x98,0xa4,0x30,0x30,0xcf,0x33,0x59,0x48,0x5f,0x21,0xd2,0x73,0x1f,0x25,0xf6,0xf4,0xde,0x51,0x40,0xaa,0x82,0xab,0xf6,0x23,0x9a,0x6f,0xd5,0x91,0xf1,0x5f,0x68,0x90,0x2d,0xac,0x33,0xd4,0x9e,0x81,0x23,0x85,0xc9,0x5f,0x79,0xab,0x83,0x28,0x3d,0xeb,0x93,0x55,0x80,0x72,0x45,0xef,0xcb,0x36,0x8f,0x75,0x6a,0x52,0x0c,0x02}, - {0xbc,0xdb,0xd8,0x9e,0xf8,0x34,0x98,0x77,0x6c,0xa4,0x7c,0xdc,0xf9,0xaa,0xf2,0xc8,0x74,0xb0,0xe1,0xa3,0xdc,0x4c,0x52,0xa9,0x77,0x38,0x31,0x15,0x46,0xcc,0xaa,0x02,0x89,0xcc,0x42,0xf0,0x59,0xef,0x31,0xe9,0xb6,0x4b,0x12,0x8e,0x9d,0x9c,0x58,0x2c,0x97,0x59,0xc7,0xae,0x8a,0xe1,0xc8,0xad,0x0c,0xc5,0x02,0x56,0x0a,0xfe,0x2c,0x45,0xdf,0x77,0x78,0x64,0xa0,0xf7,0xa0,0x86,0x9f,0x7c,0x60,0x0e,0x27,0x64,0xc4,0xbb,0xc9,0x11,0xfb,0xf1,0x25,0xea,0x17,0xab,0x7b,0x87,0x4b,0x30,0x7b,0x7d,0xfb,0x4c}, - {0xfe,0x75,0x9b,0xb8,0x6c,0x3d,0xb4,0x72,0x80,0xdc,0x6a,0x9c,0xd9,0x94,0xc6,0x54,0x9f,0x4c,0xe3,0x3e,0x37,0xaa,0xc3,0xb8,0x64,0x53,0x07,0x39,0x2b,0x62,0xb4,0x14,0x12,0xef,0x89,0x97,0xc2,0x99,0x86,0xe2,0x0d,0x19,0x57,0xdf,0x71,0xcd,0x6e,0x2b,0xd0,0x70,0xc9,0xec,0x57,0xc8,0x43,0xc3,0xc5,0x3a,0x4d,0x43,0xbc,0x4c,0x1d,0x5b,0x26,0x9f,0x0a,0xcc,0x15,0x26,0xfb,0xb6,0xe5,0xcc,0x8d,0xb8,0x2b,0x0e,0x4f,0x3a,0x05,0xa7,0x69,0x33,0x8b,0x49,0x01,0x13,0xd1,0x2d,0x59,0x58,0x12,0xf7,0x98,0x2f}, - {0x56,0x9e,0x0f,0xb5,0x4c,0xa7,0x94,0x0c,0x20,0x13,0x8e,0x8e,0xa9,0xf4,0x1f,0x5b,0x67,0x0f,0x30,0x82,0x21,0xcc,0x2a,0x9a,0xf9,0xaa,0x06,0xd8,0x49,0xe2,0x6a,0x3a,0x01,0xa7,0x54,0x4f,0x44,0xae,0x12,0x2e,0xde,0xd7,0xcb,0xa9,0xf0,0x3e,0xfe,0xfc,0xe0,0x5d,0x83,0x75,0x0d,0x89,0xbf,0xce,0x54,0x45,0x61,0xe7,0xe9,0x62,0x80,0x1d,0x5a,0x7c,0x90,0xa9,0x85,0xda,0x7a,0x65,0x62,0x0f,0xb9,0x91,0xb5,0xa8,0x0e,0x1a,0xe9,0xb4,0x34,0xdf,0xfb,0x1d,0x0e,0x8d,0xf3,0x5f,0xf2,0xae,0xe8,0x8c,0x8b,0x29}, - {0xb2,0x0c,0xf7,0xef,0x53,0x79,0x92,0x2a,0x76,0x70,0x15,0x79,0x2a,0xc9,0x89,0x4b,0x6a,0xcf,0xa7,0x30,0x7a,0x45,0x18,0x94,0x85,0xe4,0x5c,0x4d,0x40,0xa8,0xb8,0x34,0xde,0x65,0x21,0x0a,0xea,0x72,0x7a,0x83,0xf6,0x79,0xcf,0x0b,0xb4,0x07,0xab,0x3f,0x70,0xae,0x38,0x77,0xc7,0x36,0x16,0x52,0xdc,0xd7,0xa7,0x03,0x18,0x27,0xa6,0x6b,0x35,0x33,0x69,0x83,0xb5,0xec,0x6e,0xc2,0xfd,0xfe,0xb5,0x63,0xdf,0x13,0xa8,0xd5,0x73,0x25,0xb2,0xa4,0x9a,0xaa,0x93,0xa2,0x6a,0x1c,0x5e,0x46,0xdd,0x2b,0xd6,0x71}, - {0x80,0xdf,0x78,0xd3,0x28,0xcc,0x33,0x65,0xb4,0xa4,0x0f,0x0a,0x79,0x43,0xdb,0xf6,0x5a,0xda,0x01,0xf7,0xf9,0x5f,0x64,0xe3,0xa4,0x2b,0x17,0xf3,0x17,0xf3,0xd5,0x74,0xf5,0x5e,0xf7,0xb1,0xda,0xb5,0x2d,0xcd,0xf5,0x65,0xb0,0x16,0xcf,0x95,0x7f,0xd7,0x85,0xf0,0x49,0x3f,0xea,0x1f,0x57,0x14,0x3d,0x2b,0x2b,0x26,0x21,0x36,0x33,0x1c,0x81,0xca,0xd9,0x67,0x54,0xe5,0x6f,0xa8,0x37,0x8c,0x29,0x2b,0x75,0x7c,0x8b,0x39,0x3b,0x62,0xac,0xe3,0x92,0x08,0x6d,0xda,0x8c,0xd9,0xe9,0x47,0x45,0xcc,0xeb,0x4a}, - {0xc9,0x01,0x6d,0x27,0x1b,0x07,0xf0,0x12,0x70,0x8c,0xc4,0x86,0xc5,0xba,0xb8,0xe7,0xa9,0xfb,0xd6,0x71,0x9b,0x12,0x08,0x53,0x92,0xb7,0x3d,0x5a,0xf9,0xfb,0x88,0x5d,0x10,0xb6,0x54,0x73,0x9e,0x8d,0x40,0x0b,0x6e,0x5b,0xa8,0x5b,0x53,0x32,0x6b,0x80,0x07,0xa2,0x58,0x4a,0x03,0x3a,0xe6,0xdb,0x2c,0xdf,0xa1,0xc9,0xdd,0xd9,0x3b,0x17,0xdf,0x72,0x58,0xfe,0x1e,0x0f,0x50,0x2b,0xc1,0x18,0x39,0xd4,0x2e,0x58,0xd6,0x58,0xe0,0x3a,0x67,0xc9,0x8e,0x27,0xed,0xe6,0x19,0xa3,0x9e,0xb1,0x13,0xcd,0xe1,0x06}, - {0x23,0x6f,0x16,0x6f,0x51,0xad,0xd0,0x40,0xbe,0x6a,0xab,0x1f,0x93,0x32,0x8e,0x11,0x8e,0x08,0x4d,0xa0,0x14,0x5e,0xe3,0x3f,0x66,0x62,0xe1,0x26,0x35,0x60,0x80,0x30,0x53,0x03,0x5b,0x9e,0x62,0xaf,0x2b,0x47,0x47,0x04,0x8d,0x27,0x90,0x0b,0xaa,0x3b,0x27,0xbf,0x43,0x96,0x46,0x5f,0x78,0x0c,0x13,0x7b,0x83,0x8d,0x1a,0x6a,0x3a,0x7f,0x0b,0x80,0x3d,0x5d,0x39,0x44,0xe6,0xf7,0xf6,0xed,0x01,0xc9,0x55,0xd5,0xa8,0x95,0x39,0x63,0x2c,0x59,0x30,0x78,0xcd,0x68,0x7e,0x30,0x51,0x2e,0xed,0xfd,0xd0,0x30}, - {0xb3,0x33,0x12,0xf2,0x1a,0x4d,0x59,0xe0,0x9c,0x4d,0xcc,0xf0,0x8e,0xe7,0xdb,0x1b,0x77,0x9a,0x49,0x8f,0x7f,0x18,0x65,0x69,0x68,0x98,0x09,0x2c,0x20,0x14,0x92,0x0a,0x50,0x47,0xb8,0x68,0x1e,0x97,0xb4,0x9c,0xcf,0xbb,0x64,0x66,0x29,0x72,0x95,0xa0,0x2b,0x41,0xfa,0x72,0x26,0xe7,0x8d,0x5c,0xd9,0x89,0xc5,0x51,0x43,0x08,0x15,0x46,0x2e,0xa0,0xb9,0xae,0xc0,0x19,0x90,0xbc,0xae,0x4c,0x03,0x16,0x0d,0x11,0xc7,0x55,0xec,0x32,0x99,0x65,0x01,0xf5,0x6d,0x0e,0xfe,0x5d,0xca,0x95,0x28,0x0d,0xca,0x3b}, - {0xa4,0x62,0x5d,0x3c,0xbc,0x31,0xf0,0x40,0x60,0x7a,0xf0,0xcf,0x3e,0x8b,0xfc,0x19,0x45,0xb5,0x0f,0x13,0xa2,0x3d,0x18,0x98,0xcd,0x13,0x8f,0xae,0xdd,0xde,0x31,0x56,0xbf,0x01,0xcc,0x9e,0xb6,0x8e,0x68,0x9c,0x6f,0x89,0x44,0xa6,0xad,0x83,0xbc,0xf0,0xe2,0x9f,0x7a,0x5f,0x5f,0x95,0x2d,0xca,0x41,0x82,0xf2,0x8d,0x03,0xb4,0xa8,0x4e,0x02,0xd2,0xca,0xf1,0x0a,0x46,0xed,0x2a,0x83,0xee,0x8c,0xa4,0x05,0x53,0x30,0x46,0x5f,0x1a,0xf1,0x49,0x45,0x77,0x21,0x91,0x63,0xa4,0x2c,0x54,0x30,0x09,0xce,0x24}, - {0x06,0xc1,0x06,0xfd,0xf5,0x90,0xe8,0x1f,0xf2,0x10,0x88,0x5d,0x35,0x68,0xc4,0xb5,0x3e,0xaf,0x8c,0x6e,0xfe,0x08,0x78,0x82,0x4b,0xd7,0x06,0x8a,0xc2,0xe3,0xd4,0x41,0x85,0x0b,0xf3,0xfd,0x55,0xa1,0xcf,0x3f,0xa4,0x2e,0x37,0x36,0x8e,0x16,0xf7,0xd2,0x44,0xf8,0x92,0x64,0xde,0x64,0xe0,0xb2,0x80,0x42,0x4f,0x32,0xa7,0x28,0x99,0x54,0x2e,0x1a,0xee,0x63,0xa7,0x32,0x6e,0xf2,0xea,0xfd,0x5f,0xd2,0xb7,0xe4,0x91,0xae,0x69,0x4d,0x7f,0xd1,0x3b,0xd3,0x3b,0xbc,0x6a,0xff,0xdc,0xc0,0xde,0x66,0x1b,0x49}, - {0xa7,0x32,0xea,0xc7,0x3d,0xb1,0xf5,0x98,0x98,0xdb,0x16,0x7e,0xcc,0xf8,0xd5,0xe3,0x47,0xd9,0xf8,0xcb,0x52,0xbf,0x0a,0xac,0xac,0xe4,0x5e,0xc8,0xd0,0x38,0xf3,0x08,0xa1,0x64,0xda,0xd0,0x8e,0x4a,0xf0,0x75,0x4b,0x28,0xe2,0x67,0xaf,0x2c,0x22,0xed,0xa4,0x7b,0x7b,0x1f,0x79,0xa3,0x34,0x82,0x67,0x8b,0x01,0xb7,0xb0,0xb8,0xf6,0x4c,0xbd,0x73,0x1a,0x99,0x21,0xa8,0x83,0xc3,0x7a,0x0c,0x32,0xdf,0x01,0xbc,0x27,0xab,0x63,0x70,0x77,0x84,0x1b,0x33,0x3d,0xc1,0x99,0x8a,0x07,0xeb,0x82,0x4a,0x0d,0x53}, - {0x25,0x48,0xf9,0xe1,0x30,0x36,0x4c,0x00,0x5a,0x53,0xab,0x8c,0x26,0x78,0x2d,0x7e,0x8b,0xff,0x84,0xcc,0x23,0x23,0x48,0xc7,0xb9,0x70,0x17,0x10,0x3f,0x75,0xea,0x65,0x9e,0xbf,0x9a,0x6c,0x45,0x73,0x69,0x6d,0x80,0xa8,0x00,0x49,0xfc,0xb2,0x7f,0x25,0x50,0xb8,0xcf,0xc8,0x12,0xf4,0xac,0x2b,0x5b,0xbd,0xbf,0x0c,0xe0,0xe7,0xb3,0x0d,0x63,0x63,0x09,0xe2,0x3e,0xfc,0x66,0x3d,0x6b,0xcb,0xb5,0x61,0x7f,0x2c,0xd6,0x81,0x1a,0x3b,0x44,0x13,0x42,0x04,0xbe,0x0f,0xdb,0xa1,0xe1,0x21,0x19,0xec,0xa4,0x02}, - {0xa2,0xb8,0x24,0x3b,0x9a,0x25,0xe6,0x5c,0xb8,0xa0,0xaf,0x45,0xcc,0x7a,0x57,0xb8,0x37,0x70,0xa0,0x8b,0xe8,0xe6,0xcb,0xcc,0xbf,0x09,0x78,0x12,0x51,0x3c,0x14,0x3d,0x5f,0x79,0xcf,0xf1,0x62,0x61,0xc8,0xf5,0xf2,0x57,0xee,0x26,0x19,0x86,0x8c,0x11,0x78,0x35,0x06,0x1c,0x85,0x24,0x21,0x17,0xcf,0x7f,0x06,0xec,0x5d,0x2b,0xd1,0x36,0x57,0x45,0x15,0x79,0x91,0x27,0x6d,0x12,0x0a,0x3a,0x78,0xfc,0x5c,0x8f,0xe4,0xd5,0xac,0x9b,0x17,0xdf,0xe8,0xb6,0xbd,0x36,0x59,0x28,0xa8,0x5b,0x88,0x17,0xf5,0x2e}, - {0xdc,0xae,0x58,0x8c,0x4e,0x97,0x37,0x46,0xa4,0x41,0xf0,0xab,0xfb,0x22,0xef,0xb9,0x8a,0x71,0x80,0xe9,0x56,0xd9,0x85,0xe1,0xa6,0xa8,0x43,0xb1,0xfa,0x78,0x1b,0x2f,0x51,0x2f,0x5b,0x30,0xfb,0xbf,0xee,0x96,0xb8,0x96,0x95,0x88,0xad,0x38,0xf9,0xd3,0x25,0xdd,0xd5,0x46,0xc7,0x2d,0xf5,0xf0,0x95,0x00,0x3a,0xbb,0x90,0x82,0x96,0x57,0x01,0xe1,0x20,0x0a,0x43,0xb8,0x1a,0xf7,0x47,0xec,0xf0,0x24,0x8d,0x65,0x93,0xf3,0xd1,0xee,0xe2,0x6e,0xa8,0x09,0x75,0xcf,0xe1,0xa3,0x2a,0xdc,0x35,0x3e,0xc4,0x7d}, - {0xc3,0xd9,0x7d,0x88,0x65,0x66,0x96,0x85,0x55,0x53,0xb0,0x4b,0x31,0x9b,0x0f,0xc9,0xb1,0x79,0x20,0xef,0xf8,0x8d,0xe0,0xc6,0x2f,0xc1,0x8c,0x75,0x16,0x20,0xf7,0x7e,0x18,0x97,0x3e,0x27,0x5c,0x2a,0x78,0x5a,0x94,0xfd,0x4e,0x5e,0x99,0xc6,0x76,0x35,0x3e,0x7d,0x23,0x1f,0x05,0xd8,0x2e,0x0f,0x99,0x0a,0xd5,0x82,0x1d,0xb8,0x4f,0x04,0xd9,0xe3,0x07,0xa9,0xc5,0x18,0xdf,0xc1,0x59,0x63,0x4c,0xce,0x1d,0x37,0xb3,0x57,0x49,0xbb,0x01,0xb2,0x34,0x45,0x70,0xca,0x2e,0xdd,0x30,0x9c,0x3f,0x82,0x79,0x7f}, - {0xe8,0x13,0xb5,0xa3,0x39,0xd2,0x34,0x83,0xd8,0xa8,0x1f,0xb9,0xd4,0x70,0x36,0xc1,0x33,0xbd,0x90,0xf5,0x36,0x41,0xb5,0x12,0xb4,0xd9,0x84,0xd7,0x73,0x03,0x4e,0x0a,0xba,0x87,0xf5,0x68,0xf0,0x1f,0x9c,0x6a,0xde,0xc8,0x50,0x00,0x4e,0x89,0x27,0x08,0xe7,0x5b,0xed,0x7d,0x55,0x99,0xbf,0x3c,0xf0,0xd6,0x06,0x1c,0x43,0xb0,0xa9,0x64,0x19,0x29,0x7d,0x5b,0xa1,0xd6,0xb3,0x2e,0x35,0x82,0x3a,0xd5,0xa0,0xf6,0xb4,0xb0,0x47,0x5d,0xa4,0x89,0x43,0xce,0x56,0x71,0x6c,0x34,0x18,0xce,0x0a,0x7d,0x1a,0x07}, - {0x0b,0xba,0x87,0xc8,0xaa,0x2d,0x07,0xd3,0xee,0x62,0xa5,0xbf,0x05,0x29,0x26,0x01,0x8b,0x76,0xef,0xc0,0x02,0x30,0x54,0xcf,0x9c,0x7e,0xea,0x46,0x71,0xcc,0x3b,0x2c,0x31,0x44,0xe1,0x20,0x52,0x35,0x0c,0xcc,0x41,0x51,0xb1,0x09,0x07,0x95,0x65,0x0d,0x36,0x5f,0x9d,0x20,0x1b,0x62,0xf5,0x9a,0xd3,0x55,0x77,0x61,0xf7,0xbc,0x69,0x7c,0x5f,0x29,0xe8,0x04,0xeb,0xd7,0xf0,0x07,0x7d,0xf3,0x50,0x2f,0x25,0x18,0xdb,0x10,0xd7,0x98,0x17,0x17,0xa3,0xa9,0x51,0xe9,0x1d,0xa5,0xac,0x22,0x73,0x9a,0x5a,0x6f}, - {0xc5,0xc6,0x41,0x2f,0x0c,0x00,0xa1,0x8b,0x9b,0xfb,0xfe,0x0c,0xc1,0x79,0x9f,0xc4,0x9f,0x1c,0xc5,0x3c,0x70,0x47,0xfa,0x4e,0xca,0xaf,0x47,0xe1,0xa2,0x21,0x4e,0x49,0xbe,0x44,0xd9,0xa3,0xeb,0xd4,0x29,0xe7,0x9e,0xaf,0x78,0x80,0x40,0x09,0x9e,0x8d,0x03,0x9c,0x86,0x47,0x7a,0x56,0x25,0x45,0x24,0x3b,0x8d,0xee,0x80,0x96,0xab,0x02,0x9a,0x0d,0xe5,0xdd,0x85,0x8a,0xa4,0xef,0x49,0xa2,0xb9,0x0f,0x4e,0x22,0x9a,0x21,0xd9,0xf6,0x1e,0xd9,0x1d,0x1f,0x09,0xfa,0x34,0xbb,0x46,0xea,0xcb,0x76,0x5d,0x6b}, - {0x94,0xd9,0x0c,0xec,0x6c,0x55,0x57,0x88,0xba,0x1d,0xd0,0x5c,0x6f,0xdc,0x72,0x64,0x77,0xb4,0x42,0x8f,0x14,0x69,0x01,0xaf,0x54,0x73,0x27,0x85,0xf6,0x33,0xe3,0x0a,0x22,0x25,0x78,0x1e,0x17,0x41,0xf9,0xe0,0xd3,0x36,0x69,0x03,0x74,0xae,0xe6,0xf1,0x46,0xc7,0xfc,0xd0,0xa2,0x3e,0x8b,0x40,0x3e,0x31,0xdd,0x03,0x9c,0x86,0xfb,0x16,0x62,0x09,0xb6,0x33,0x97,0x19,0x8e,0x28,0x33,0xe1,0xab,0xd8,0xb4,0x72,0xfc,0x24,0x3e,0xd0,0x91,0x09,0xed,0xf7,0x11,0x48,0x75,0xd0,0x70,0x8f,0x8b,0xe3,0x81,0x3f}, - {0xfe,0xaf,0xd9,0x7e,0xcc,0x0f,0x91,0x7f,0x4b,0x87,0x65,0x24,0xa1,0xb8,0x5c,0x54,0x04,0x47,0x0c,0x4b,0xd2,0x7e,0x39,0xa8,0x93,0x09,0xf5,0x04,0xc1,0x0f,0x51,0x50,0x24,0xc8,0x17,0x5f,0x35,0x7f,0xdb,0x0a,0xa4,0x99,0x42,0xd7,0xc3,0x23,0xb9,0x74,0xf7,0xea,0xf8,0xcb,0x8b,0x3e,0x7c,0xd5,0x3d,0xdc,0xde,0x4c,0xd3,0xe2,0xd3,0x0a,0x9d,0x24,0x6e,0x33,0xc5,0x0f,0x0c,0x6f,0xd9,0xcf,0x31,0xc3,0x19,0xde,0x5e,0x74,0x1c,0xfe,0xee,0x09,0x00,0xfd,0xd6,0xf2,0xbe,0x1e,0xfa,0xf0,0x8b,0x15,0x7c,0x12}, - {0xa2,0x79,0x98,0x2e,0x42,0x7c,0x19,0xf6,0x47,0x36,0xca,0x52,0xd4,0xdd,0x4a,0xa4,0xcb,0xac,0x4e,0x4b,0xc1,0x3f,0x41,0x9b,0x68,0x4f,0xef,0x07,0x7d,0xf8,0x4e,0x35,0x74,0xb9,0x51,0xae,0xc4,0x8f,0xa2,0xde,0x96,0xfe,0x4d,0x74,0xd3,0x73,0x99,0x1d,0xa8,0x48,0x38,0x87,0x0b,0x68,0x40,0x62,0x95,0xdf,0x67,0xd1,0x79,0x24,0xd8,0x4e,0x75,0xd9,0xc5,0x60,0x22,0xb5,0xe3,0xfe,0xb8,0xb0,0x41,0xeb,0xfc,0x2e,0x35,0x50,0x3c,0x65,0xf6,0xa9,0x30,0xac,0x08,0x88,0x6d,0x23,0x39,0x05,0xd2,0x92,0x2d,0x30}, - {0x3d,0x28,0xa4,0xbc,0xa2,0xc1,0x13,0x78,0xd9,0x3d,0x86,0xa1,0x91,0xf0,0x62,0xed,0x86,0xfa,0x68,0xc2,0xb8,0xbc,0xc7,0xae,0x4c,0xae,0x1c,0x6f,0xb7,0xd3,0xe5,0x10,0x77,0xf1,0xe0,0xe4,0xb6,0x6f,0xbc,0x2d,0x93,0x6a,0xbd,0xa4,0x29,0xbf,0xe1,0x04,0xe8,0xf6,0x7a,0x78,0xd4,0x66,0x19,0x5e,0x60,0xd0,0x26,0xb4,0x5e,0x5f,0xdc,0x0e,0x67,0x8e,0xda,0x53,0xd6,0xbf,0x53,0x54,0x41,0xf6,0xa9,0x24,0xec,0x1e,0xdc,0xe9,0x23,0x8a,0x57,0x03,0x3b,0x26,0x87,0xbf,0x72,0xba,0x1c,0x36,0x51,0x6c,0xb4,0x45}, - {0xa1,0x7f,0x4f,0x31,0xbf,0x2a,0x40,0xa9,0x50,0xf4,0x8c,0x8e,0xdc,0xf1,0x57,0xe2,0x84,0xbe,0xa8,0x23,0x4b,0xd5,0xbb,0x1d,0x3b,0x71,0xcb,0x6d,0xa3,0xbf,0x77,0x21,0xe4,0xe3,0x7f,0x8a,0xdd,0x4d,0x9d,0xce,0x30,0x0e,0x62,0x76,0x56,0x64,0x13,0xab,0x58,0x99,0x0e,0xb3,0x7b,0x4f,0x59,0x4b,0xdf,0x29,0x12,0x32,0xef,0x0a,0x1c,0x5c,0x8f,0xdb,0x79,0xfa,0xbc,0x1b,0x08,0x37,0xb3,0x59,0x5f,0xc2,0x1e,0x81,0x48,0x60,0x87,0x24,0x83,0x9c,0x65,0x76,0x7a,0x08,0xbb,0xb5,0x8a,0x7d,0x38,0x19,0xe6,0x4a}, - {0x2e,0xa3,0x44,0x53,0xaa,0xf6,0xdb,0x8d,0x78,0x40,0x1b,0xb4,0xb4,0xea,0x88,0x7d,0x60,0x0d,0x13,0x4a,0x97,0xeb,0xb0,0x5e,0x03,0x3e,0xbf,0x17,0x1b,0xd9,0x00,0x1a,0x83,0xfb,0x5b,0x98,0x44,0x7e,0x11,0x61,0x36,0x31,0x96,0x71,0x2a,0x46,0xe0,0xfc,0x4b,0x90,0x25,0xd4,0x48,0x34,0xac,0x83,0x64,0x3d,0xa4,0x5b,0xbe,0x5a,0x68,0x75,0xb2,0xf2,0x61,0xeb,0x33,0x09,0x96,0x6e,0x52,0x49,0xff,0xc9,0xa8,0x0f,0x3d,0x54,0x69,0x65,0xf6,0x7a,0x10,0x75,0x72,0xdf,0xaa,0xe6,0xb0,0x23,0xb6,0x29,0x55,0x13}, - {0x18,0xd5,0xd1,0xad,0xd7,0xdb,0xf0,0x18,0x11,0x1f,0xc1,0xcf,0x88,0x78,0x9f,0x97,0x9b,0x75,0x14,0x71,0xf0,0xe1,0x32,0x87,0x01,0x3a,0xca,0x65,0x1a,0xb8,0xb5,0x79,0xfe,0x83,0x2e,0xe2,0xbc,0x16,0xc7,0xf5,0xc1,0x85,0x09,0xe8,0x19,0xeb,0x2b,0xb4,0xae,0x4a,0x25,0x14,0x37,0xa6,0x9d,0xec,0x13,0xa6,0x90,0x15,0x05,0xea,0x72,0x59,0x11,0x78,0x8f,0xdc,0x20,0xac,0xd4,0x0f,0xa8,0x4f,0x4d,0xac,0x94,0xd2,0x9a,0x9a,0x34,0x04,0x36,0xb3,0x64,0x2d,0x1b,0xc0,0xdb,0x3b,0x5f,0x90,0x95,0x9c,0x7e,0x4f}, - {0x2e,0x30,0x81,0x57,0xbc,0x4b,0x67,0x62,0x0f,0xdc,0xad,0x89,0x39,0x0f,0x52,0xd8,0xc6,0xd9,0xfb,0x53,0xae,0x99,0x29,0x8c,0x4c,0x8e,0x63,0x2e,0xd9,0x3a,0x99,0x31,0xfe,0x99,0x52,0x35,0x3d,0x44,0xc8,0x71,0xd7,0xea,0xeb,0xdb,0x1c,0x3b,0xcd,0x8b,0x66,0x94,0xa4,0xf1,0x9e,0x49,0x92,0x80,0xc8,0xad,0x44,0xa1,0xc4,0xee,0x42,0x19,0x92,0x49,0x23,0xae,0x19,0x53,0xac,0x7d,0x92,0x3e,0xea,0x0c,0x91,0x3d,0x1b,0x2c,0x22,0x11,0x3c,0x25,0x94,0xe4,0x3c,0x55,0x75,0xca,0xf9,0x4e,0x31,0x65,0x0a,0x2a}, - {0xc2,0x27,0xf9,0xf7,0x7f,0x93,0xb7,0x2d,0x35,0xa6,0xd0,0x17,0x06,0x1f,0x74,0xdb,0x76,0xaf,0x55,0x11,0xa2,0xf3,0x82,0x59,0xed,0x2d,0x7c,0x64,0x18,0xe2,0xf6,0x4c,0x3a,0x79,0x1c,0x3c,0xcd,0x1a,0x36,0xcf,0x3b,0xbc,0x35,0x5a,0xac,0xbc,0x9e,0x2f,0xab,0xa6,0xcd,0xa8,0xe9,0x60,0xe8,0x60,0x13,0x1a,0xea,0x6d,0x9b,0xc3,0x5d,0x05,0xb6,0x5b,0x8d,0xc2,0x7c,0x22,0x19,0xb1,0xab,0xff,0x4d,0x77,0xbc,0x4e,0xe2,0x07,0x89,0x2c,0xa3,0xe4,0xce,0x78,0x3c,0xa8,0xb6,0x24,0xaa,0x10,0x77,0x30,0x1a,0x12}, - {0x97,0x4a,0x03,0x9f,0x5e,0x5d,0xdb,0xe4,0x2d,0xbc,0x34,0x30,0x09,0xfc,0x53,0xe1,0xb1,0xd3,0x51,0x95,0x91,0x46,0x05,0x46,0x2d,0xe5,0x40,0x7a,0x6c,0xc7,0x3f,0x33,0xc9,0x83,0x74,0xc7,0x3e,0x71,0x59,0xd6,0xaf,0x96,0x2b,0xb8,0x77,0xe0,0xbf,0x88,0xd3,0xbc,0x97,0x10,0x23,0x28,0x9e,0x28,0x9b,0x3a,0xed,0x6c,0x4a,0xb9,0x7b,0x52,0x2e,0x48,0x5b,0x99,0x2a,0x99,0x3d,0x56,0x01,0x38,0x38,0x6e,0x7c,0xd0,0x05,0x34,0xe5,0xd8,0x64,0x2f,0xde,0x35,0x50,0x48,0xf7,0xa9,0xa7,0x20,0x9b,0x06,0x89,0x6b}, - {0x0d,0x22,0x70,0x62,0x41,0xa0,0x2a,0x81,0x4e,0x5b,0x24,0xf9,0xfa,0x89,0x5a,0x99,0x05,0xef,0x72,0x50,0xce,0xc4,0xad,0xff,0x73,0xeb,0x73,0xaa,0x03,0x21,0xbc,0x23,0x77,0xdb,0xc7,0xb5,0x8c,0xfa,0x82,0x40,0x55,0xc1,0x34,0xc7,0xf8,0x86,0x86,0x06,0x7e,0xa5,0xe7,0xf6,0xd9,0xc8,0xe6,0x29,0xcf,0x9b,0x63,0xa7,0x08,0xd3,0x73,0x04,0x05,0x9e,0x58,0x03,0x26,0x79,0xee,0xca,0x92,0xc4,0xdc,0x46,0x12,0x42,0x4b,0x2b,0x4f,0xa9,0x01,0xe6,0x74,0xef,0xa1,0x02,0x1a,0x34,0x04,0xde,0xbf,0x73,0x2f,0x10}, - {0xc6,0x45,0x57,0x7f,0xab,0xb9,0x18,0xeb,0x90,0xc6,0x87,0x57,0xee,0x8a,0x3a,0x02,0xa9,0xaf,0xf7,0x2d,0xda,0x12,0x27,0xb7,0x3d,0x01,0x5c,0xea,0x25,0x7d,0x59,0x36,0x9a,0x1c,0x51,0xb5,0xe0,0xda,0xb4,0xa2,0x06,0xff,0xff,0x2b,0x29,0x60,0xc8,0x7a,0x34,0x42,0x50,0xf5,0x5d,0x37,0x1f,0x98,0x2d,0xa1,0x4e,0xda,0x25,0xd7,0x6b,0x3f,0xac,0x58,0x60,0x10,0x7b,0x8d,0x4d,0x73,0x5f,0x90,0xc6,0x6f,0x9e,0x57,0x40,0xd9,0x2d,0x93,0x02,0x92,0xf9,0xf8,0x66,0x64,0xd0,0xd6,0x60,0xda,0x19,0xcc,0x7e,0x7b}, - {0x0d,0x69,0x5c,0x69,0x3c,0x37,0xc2,0x78,0x6e,0x90,0x42,0x06,0x66,0x2e,0x25,0xdd,0xd2,0x2b,0xe1,0x4a,0x44,0x44,0x1d,0x95,0x56,0x39,0x74,0x01,0x76,0xad,0x35,0x42,0x9b,0xfa,0x7c,0xa7,0x51,0x4a,0xae,0x6d,0x50,0x86,0xa3,0xe7,0x54,0x36,0x26,0x82,0xdb,0x82,0x2d,0x8f,0xcd,0xff,0xbb,0x09,0xba,0xca,0xf5,0x1b,0x66,0xdc,0xbe,0x03,0xf5,0x75,0x89,0x07,0x0d,0xcb,0x58,0x62,0x98,0xf2,0x89,0x91,0x54,0x42,0x29,0x49,0xe4,0x6e,0xe3,0xe2,0x23,0xb4,0xca,0xa0,0xa1,0x66,0xf0,0xcd,0xb0,0xe2,0x7c,0x0e}, - {0xa3,0x85,0x8c,0xc4,0x3a,0x64,0x94,0xc4,0xad,0x39,0x61,0x3c,0xf4,0x1d,0x36,0xfd,0x48,0x4d,0xe9,0x3a,0xdd,0x17,0xdb,0x09,0x4a,0x67,0xb4,0x8f,0x5d,0x0a,0x6e,0x66,0xf9,0x70,0x4b,0xd9,0xdf,0xfe,0xa6,0xfe,0x2d,0xba,0xfc,0xc1,0x51,0xc0,0x30,0xf1,0x89,0xab,0x2f,0x7f,0x7e,0xd4,0x82,0x48,0xb5,0xee,0xec,0x8a,0x13,0x56,0x52,0x61,0x0d,0xcb,0x70,0x48,0x4e,0xf6,0xbb,0x2a,0x6b,0x8b,0x45,0xaa,0xf0,0xbc,0x65,0xcd,0x5d,0x98,0xe8,0x75,0xba,0x4e,0xbe,0x9a,0xe4,0xde,0x14,0xd5,0x10,0xc8,0x0b,0x7f}, - {0x6f,0x13,0xf4,0x26,0xa4,0x6b,0x00,0xb9,0x35,0x30,0xe0,0x57,0x9e,0x36,0x67,0x8d,0x28,0x3c,0x46,0x4f,0xd9,0xdf,0xc8,0xcb,0xf5,0xdb,0xee,0xf8,0xbc,0x8d,0x1f,0x0d,0xa0,0x13,0x72,0x73,0xad,0x9d,0xac,0x83,0x98,0x2e,0xf7,0x2e,0xba,0xf8,0xf6,0x9f,0x57,0x69,0xec,0x43,0xdd,0x2e,0x1e,0x31,0x75,0xab,0xc5,0xde,0x7d,0x90,0x3a,0x1d,0xdc,0x81,0xd0,0x3e,0x31,0x93,0x16,0xba,0x80,0x34,0x1b,0x85,0xad,0x9f,0x32,0x29,0xcb,0x21,0x03,0x03,0x3c,0x01,0x28,0x01,0xe3,0xfd,0x1b,0xa3,0x44,0x1b,0x01,0x00}, - {0x0c,0x6c,0xc6,0x3f,0x6c,0xa0,0xdf,0x3f,0xd2,0x0d,0xd6,0x4d,0x8e,0xe3,0x40,0x5d,0x71,0x4d,0x8e,0x26,0x38,0x8b,0xe3,0x7a,0xe1,0x57,0x83,0x6e,0x91,0x8d,0xc4,0x3a,0x5c,0xa7,0x0a,0x6a,0x69,0x1f,0x56,0x16,0x6a,0xbd,0x52,0x58,0x5c,0x72,0xbf,0xc1,0xad,0x66,0x79,0x9a,0x7f,0xdd,0xa8,0x11,0x26,0x10,0x85,0xd2,0xa2,0x88,0xd9,0x63,0x2e,0x23,0xbd,0xaf,0x53,0x07,0x12,0x00,0x83,0xf6,0xd8,0xfd,0xb8,0xce,0x2b,0xe9,0x91,0x2b,0xe7,0x84,0xb3,0x69,0x16,0xf8,0x66,0xa0,0x68,0x23,0x2b,0xd5,0xfa,0x33}, - {0x16,0x1e,0xe4,0xc5,0xc6,0x49,0x06,0x54,0x35,0x77,0x3f,0x33,0x30,0x64,0xf8,0x0a,0x46,0xe7,0x05,0xf3,0xd2,0xfc,0xac,0xb2,0xa7,0xdc,0x56,0xa2,0x29,0xf4,0xc0,0x16,0xe8,0xcf,0x22,0xc4,0xd0,0xc8,0x2c,0x8d,0xcb,0x3a,0xa1,0x05,0x7b,0x4f,0x2b,0x07,0x6f,0xa5,0xf6,0xec,0xe6,0xb6,0xfe,0xa3,0xe2,0x71,0x0a,0xb9,0xcc,0x55,0xc3,0x3c,0x31,0x91,0x3e,0x90,0x43,0x94,0xb6,0xe9,0xce,0x37,0x56,0x7a,0xcb,0x94,0xa4,0xb8,0x44,0x92,0xba,0xba,0xa4,0xd1,0x7c,0xc8,0x68,0x75,0xae,0x6b,0x42,0xaf,0x1e,0x63}, - {0x9f,0xfe,0x66,0xda,0x10,0x04,0xe9,0xb3,0xa6,0xe5,0x16,0x6c,0x52,0x4b,0xdd,0x85,0x83,0xbf,0xf9,0x1e,0x61,0x97,0x3d,0xbc,0xb5,0x19,0xa9,0x1e,0x8b,0x64,0x99,0x55,0xe8,0x0d,0x70,0xa3,0xb9,0x75,0xd9,0x47,0x52,0x05,0xf8,0xe2,0xfb,0xc5,0x80,0x72,0xe1,0x5d,0xe4,0x32,0x27,0x8f,0x65,0x53,0xb5,0x80,0x5f,0x66,0x7f,0x2c,0x1f,0x43,0x19,0x7b,0x8f,0x85,0x44,0x63,0x02,0xd6,0x4a,0x51,0xea,0xa1,0x2f,0x35,0xab,0x14,0xd7,0xa9,0x90,0x20,0x1a,0x44,0x00,0x89,0x26,0x3b,0x25,0x91,0x5f,0x71,0x04,0x7b}, - {0x43,0xae,0xf6,0xac,0x28,0xbd,0xed,0x83,0xb4,0x7a,0x5c,0x7d,0x8b,0x7c,0x35,0x86,0x44,0x2c,0xeb,0xb7,0x69,0x47,0x40,0xc0,0x3f,0x58,0xf6,0xc2,0xf5,0x7b,0xb3,0x59,0xc6,0xba,0xe6,0xc4,0x80,0xc2,0x76,0xb3,0x0b,0x9b,0x1d,0x6d,0xdd,0xd3,0x0e,0x97,0x44,0xf9,0x0b,0x45,0x58,0x95,0x9a,0xb0,0x23,0xe2,0xcd,0x57,0xfa,0xac,0xd0,0x48,0x71,0xe6,0xab,0x7d,0xe4,0x26,0x0f,0xb6,0x37,0x3a,0x2f,0x62,0x97,0xa1,0xd1,0xf1,0x94,0x03,0x96,0xe9,0x7e,0xce,0x08,0x42,0xdb,0x3b,0x6d,0x33,0x91,0x41,0x23,0x16}, - {0xf6,0x7f,0x26,0xf6,0xde,0x99,0xe4,0xb9,0x43,0x08,0x2c,0x74,0x7b,0xca,0x72,0x77,0xb1,0xf2,0xa4,0xe9,0x3f,0x15,0xa0,0x23,0x06,0x50,0xd0,0xd5,0xec,0xdf,0xdf,0x2c,0x40,0x86,0xf3,0x1f,0xd6,0x9c,0x49,0xdd,0xa0,0x25,0x36,0x06,0xc3,0x9b,0xcd,0x29,0xc3,0x3d,0xd7,0x3d,0x02,0xd8,0xe2,0x51,0x31,0x92,0x3b,0x20,0x7a,0x70,0x25,0x4a,0x6a,0xed,0xf6,0x53,0x8a,0x66,0xb7,0x2a,0xa1,0x70,0xd1,0x1d,0x58,0x42,0x42,0x30,0x61,0x01,0xe2,0x3a,0x4c,0x14,0x00,0x40,0xfc,0x49,0x8e,0x24,0x6d,0x89,0x21,0x57}, - {0xae,0x1b,0x18,0xfd,0x17,0x55,0x6e,0x0b,0xb4,0x63,0xb9,0x2b,0x9f,0x62,0x22,0x90,0x25,0x46,0x06,0x32,0xe9,0xbc,0x09,0x55,0xda,0x13,0x3c,0xf6,0x74,0xdd,0x8e,0x57,0x4e,0xda,0xd0,0xa1,0x91,0x50,0x5d,0x28,0x08,0x3e,0xfe,0xb5,0xa7,0x6f,0xaa,0x4b,0xb3,0x93,0x93,0xe1,0x7c,0x17,0xe5,0x63,0xfd,0x30,0xb0,0xc4,0xaf,0x35,0xc9,0x03,0x3d,0x0c,0x2b,0x49,0xc6,0x76,0x72,0x99,0xfc,0x05,0xe2,0xdf,0xc4,0xc2,0xcc,0x47,0x3c,0x3a,0x62,0xdd,0x84,0x9b,0xd2,0xdc,0xa2,0xc7,0x88,0x02,0x59,0xab,0xc2,0x3e}, - {0xb9,0x7b,0xd8,0xe4,0x7b,0xd2,0xa0,0xa1,0xed,0x1a,0x39,0x61,0xeb,0x4d,0x8b,0xa9,0x83,0x9b,0xcb,0x73,0xd0,0xdd,0xa0,0x99,0xce,0xca,0x0f,0x20,0x5a,0xc2,0xd5,0x2d,0xcb,0xd1,0x32,0xae,0x09,0x3a,0x21,0xa7,0xd5,0xc2,0xf5,0x40,0xdf,0x87,0x2b,0x0f,0x29,0xab,0x1e,0xe8,0xc6,0xa4,0xae,0x0b,0x5e,0xac,0xdb,0x6a,0x6c,0xf6,0x1b,0x0e,0x7e,0x88,0x2c,0x79,0xe9,0xd5,0xab,0xe2,0x5d,0x6d,0x92,0xcb,0x18,0x00,0x02,0x1a,0x1e,0x5f,0xae,0xba,0xcd,0x69,0xba,0xbf,0x5f,0x8f,0xe8,0x5a,0xb3,0x48,0x05,0x73}, - {0xee,0xb8,0xa8,0xcb,0xa3,0x51,0x35,0xc4,0x16,0x5f,0x11,0xb2,0x1d,0x6f,0xa2,0x65,0x50,0x38,0x8c,0xab,0x52,0x4f,0x0f,0x76,0xca,0xb8,0x1d,0x41,0x3b,0x44,0x43,0x30,0x34,0xe3,0xd6,0xa1,0x4b,0x09,0x5b,0x80,0x19,0x3f,0x35,0x09,0x77,0xf1,0x3e,0xbf,0x2b,0x70,0x22,0x06,0xcb,0x06,0x3f,0x42,0xdd,0x45,0x78,0xd8,0x77,0x22,0x5a,0x58,0x62,0x89,0xd4,0x33,0x82,0x5f,0x8a,0xa1,0x7f,0x25,0x78,0xec,0xb5,0xc4,0x98,0x66,0xff,0x41,0x3e,0x37,0xa5,0x6f,0x8e,0xa7,0x1f,0x98,0xef,0x50,0x89,0x27,0x56,0x76}, - {0xc0,0xc8,0x1f,0xd5,0x59,0xcf,0xc3,0x38,0xf2,0xb6,0x06,0x05,0xfd,0xd2,0xed,0x9b,0x8f,0x0e,0x57,0xab,0x9f,0x10,0xbf,0x26,0xa6,0x46,0xb8,0xc1,0xa8,0x60,0x41,0x3f,0x9d,0xcf,0x86,0xea,0xa3,0x73,0x70,0xe1,0xdc,0x5f,0x15,0x07,0xb7,0xfb,0x8c,0x3a,0x8e,0x8a,0x83,0x31,0xfc,0xe7,0x53,0x48,0x16,0xf6,0x13,0xb6,0x84,0xf4,0xbb,0x28,0x7c,0x6c,0x13,0x6f,0x5c,0x2f,0x61,0xf2,0xbe,0x11,0xdd,0xf6,0x07,0xd1,0xea,0xaf,0x33,0x6f,0xde,0x13,0xd2,0x9a,0x7e,0x52,0x5d,0xf7,0x88,0x81,0x35,0xcb,0x79,0x1e}, - {0xf1,0xe3,0xf7,0xee,0xc3,0x36,0x34,0x01,0xf8,0x10,0x9e,0xfe,0x7f,0x6a,0x8b,0x82,0xfc,0xde,0xf9,0xbc,0xe5,0x08,0xf9,0x7f,0x31,0x38,0x3b,0x3a,0x1b,0x95,0xd7,0x65,0x81,0x81,0xe0,0xf5,0xd8,0x53,0xe9,0x77,0xd9,0xde,0x9d,0x29,0x44,0x0c,0xa5,0x84,0xe5,0x25,0x45,0x86,0x0c,0x2d,0x6c,0xdc,0xf4,0xf2,0xd1,0x39,0x2d,0xb5,0x8a,0x47,0x59,0xd1,0x52,0x92,0xd3,0xa4,0xa6,0x66,0x07,0xc8,0x1a,0x87,0xbc,0xe1,0xdd,0xe5,0x6f,0xc9,0xc1,0xa6,0x40,0x6b,0x2c,0xb8,0x14,0x22,0x21,0x1a,0x41,0x7a,0xd8,0x16}, - {0x15,0x62,0x06,0x42,0x5a,0x7e,0xbd,0xb3,0xc1,0x24,0x5a,0x0c,0xcd,0xe3,0x9b,0x87,0xb7,0x94,0xf9,0xd6,0xb1,0x5d,0xc0,0x57,0xa6,0x8c,0xf3,0x65,0x81,0x7c,0xf8,0x28,0x83,0x05,0x4e,0xd5,0xe2,0xd5,0xa4,0xfb,0xfa,0x99,0xbd,0x2e,0xd7,0xaf,0x1f,0xe2,0x8f,0x77,0xe9,0x6e,0x73,0xc2,0x7a,0x49,0xde,0x6d,0x5a,0x7a,0x57,0x0b,0x99,0x1f,0xd6,0xf7,0xe8,0x1b,0xad,0x4e,0x34,0xa3,0x8f,0x79,0xea,0xac,0xeb,0x50,0x1e,0x7d,0x52,0xe0,0x0d,0x52,0x9e,0x56,0xc6,0x77,0x3e,0x6d,0x4d,0x53,0xe1,0x2f,0x88,0x45}, - {0xd6,0x83,0x79,0x75,0x5d,0x34,0x69,0x66,0xa6,0x11,0xaa,0x17,0x11,0xed,0xb6,0x62,0x8f,0x12,0x5e,0x98,0x57,0x18,0xdd,0x7d,0xdd,0xf6,0x26,0xf6,0xb8,0xe5,0x8f,0x68,0xe4,0x6f,0x3c,0x94,0x29,0x99,0xac,0xd8,0xa2,0x92,0x83,0xa3,0x61,0xf1,0xf9,0xb5,0xf3,0x9a,0xc8,0xbe,0x13,0xdb,0x99,0x26,0x74,0xf0,0x05,0xe4,0x3c,0x84,0xcf,0x7d,0xc0,0x32,0x47,0x4a,0x48,0xd6,0x90,0x6c,0x99,0x32,0x56,0xca,0xfd,0x43,0x21,0xd5,0xe1,0xc6,0x5d,0x91,0xc3,0x28,0xbe,0xb3,0x1b,0x19,0x27,0x73,0x7e,0x68,0x39,0x67}, - {0xa6,0x75,0x56,0x38,0x14,0x20,0x78,0xef,0xe8,0xa9,0xfd,0xaa,0x30,0x9f,0x64,0xa2,0xcb,0xa8,0xdf,0x5c,0x50,0xeb,0xd1,0x4c,0xb3,0xc0,0x4d,0x1d,0xba,0x5a,0x11,0x46,0xc0,0x1a,0x0c,0xc8,0x9d,0xcc,0x6d,0xa6,0x36,0xa4,0x38,0x1b,0xf4,0x5c,0xa0,0x97,0xc6,0xd7,0xdb,0x95,0xbe,0xf3,0xeb,0xa7,0xab,0x7d,0x7e,0x8d,0xf6,0xb8,0xa0,0x7d,0x76,0xda,0xb5,0xc3,0x53,0x19,0x0f,0xd4,0x9b,0x9e,0x11,0x21,0x73,0x6f,0xac,0x1d,0x60,0x59,0xb2,0xfe,0x21,0x60,0xcc,0x03,0x4b,0x4b,0x67,0x83,0x7e,0x88,0x5f,0x5a}, - {0x11,0x3d,0xa1,0x70,0xcf,0x01,0x63,0x8f,0xc4,0xd0,0x0d,0x35,0x15,0xb8,0xce,0xcf,0x7e,0xa4,0xbc,0xa4,0xd4,0x97,0x02,0xf7,0x34,0x14,0x4d,0xe4,0x56,0xb6,0x69,0x36,0xb9,0x43,0xa6,0xa0,0xd3,0x28,0x96,0x9e,0x64,0x20,0xc3,0xe6,0x00,0xcb,0xc3,0xb5,0x32,0xec,0x2d,0x7c,0x89,0x02,0x53,0x9b,0x0c,0xc7,0xd1,0xd5,0xe2,0x7a,0xe3,0x43,0x33,0xe1,0xa6,0xed,0x06,0x3f,0x7e,0x38,0xc0,0x3a,0xa1,0x99,0x51,0x1d,0x30,0x67,0x11,0x38,0x26,0x36,0xf8,0xd8,0x5a,0xbd,0xbe,0xe9,0xd5,0x4f,0xcd,0xe6,0x21,0x6a}, - {0x5f,0xe6,0x46,0x30,0x0a,0x17,0xc6,0xf1,0x24,0x35,0xd2,0x00,0x2a,0x2a,0x71,0x58,0x55,0xb7,0x82,0x8c,0x3c,0xbd,0xdb,0x69,0x57,0xff,0x95,0xa1,0xf1,0xf9,0x6b,0x58,0xe3,0xb2,0x99,0x66,0x12,0x29,0x41,0xef,0x01,0x13,0x8d,0x70,0x47,0x08,0xd3,0x71,0xbd,0xb0,0x82,0x11,0xd0,0x32,0x54,0x32,0x36,0x8b,0x1e,0x00,0x07,0x1b,0x37,0x45,0x0b,0x79,0xf8,0x5e,0x8d,0x08,0xdb,0xa6,0xe5,0x37,0x09,0x61,0xdc,0xf0,0x78,0x52,0xb8,0x6e,0xa1,0x61,0xd2,0x49,0x03,0xac,0x79,0x21,0xe5,0x90,0x37,0xb0,0xaf,0x0e}, - {0x2f,0x04,0x48,0x37,0xc1,0x55,0x05,0x96,0x11,0xaa,0x0b,0x82,0xe6,0x41,0x9a,0x21,0x0c,0x6d,0x48,0x73,0x38,0xf7,0x81,0x1c,0x61,0xc6,0x02,0x5a,0x67,0xcc,0x9a,0x30,0x1d,0xae,0x75,0x0f,0x5e,0x80,0x40,0x51,0x30,0xcc,0x62,0x26,0xe3,0xfb,0x02,0xec,0x6d,0x39,0x92,0xea,0x1e,0xdf,0xeb,0x2c,0xb3,0x5b,0x43,0xc5,0x44,0x33,0xae,0x44,0xee,0x43,0xa5,0xbb,0xb9,0x89,0xf2,0x9c,0x42,0x71,0xc9,0x5a,0x9d,0x0e,0x76,0xf3,0xaa,0x60,0x93,0x4f,0xc6,0xe5,0x82,0x1d,0x8f,0x67,0x94,0x7f,0x1b,0x22,0xd5,0x62}, - {0x6d,0x93,0xd0,0x18,0x9c,0x29,0x4c,0x52,0x0c,0x1a,0x0c,0x8a,0x6c,0xb5,0x6b,0xc8,0x31,0x86,0x4a,0xdb,0x2e,0x05,0x75,0xa3,0x62,0x45,0x75,0xbc,0xe4,0xfd,0x0e,0x5c,0x3c,0x7a,0xf7,0x3a,0x26,0xd4,0x85,0x75,0x4d,0x14,0xe9,0xfe,0x11,0x7b,0xae,0xdf,0x3d,0x19,0xf7,0x59,0x80,0x70,0x06,0xa5,0x37,0x20,0x92,0x83,0x53,0x9a,0xf2,0x14,0xf5,0xd7,0xb2,0x25,0xdc,0x7e,0x71,0xdf,0x40,0x30,0xb5,0x99,0xdb,0x70,0xf9,0x21,0x62,0x4c,0xed,0xc3,0xb7,0x34,0x92,0xda,0x3e,0x09,0xee,0x7b,0x5c,0x36,0x72,0x5e}, - {0x7f,0x21,0x71,0x45,0x07,0xfc,0x5b,0x57,0x5b,0xd9,0x94,0x06,0x5d,0x67,0x79,0x37,0x33,0x1e,0x19,0xf4,0xbb,0x37,0x0a,0x9a,0xbc,0xea,0xb4,0x47,0x4c,0x10,0xf1,0x77,0x3e,0xb3,0x08,0x2f,0x06,0x39,0x93,0x7d,0xbe,0x32,0x9f,0xdf,0xe5,0x59,0x96,0x5b,0xfd,0xbd,0x9e,0x1f,0xad,0x3d,0xff,0xac,0xb7,0x49,0x73,0xcb,0x55,0x05,0xb2,0x70,0x4c,0x2c,0x11,0x55,0xc5,0x13,0x51,0xbe,0xcd,0x1f,0x88,0x9a,0x3a,0x42,0x88,0x66,0x47,0x3b,0x50,0x5e,0x85,0x77,0x66,0x44,0x4a,0x40,0x06,0x4a,0x8f,0x39,0x34,0x0e}, - {0xe8,0xbd,0xce,0x3e,0xd9,0x22,0x7d,0xb6,0x07,0x2f,0x82,0x27,0x41,0xe8,0xb3,0x09,0x8d,0x6d,0x5b,0xb0,0x1f,0xa6,0x3f,0x74,0x72,0x23,0x36,0x8a,0x36,0x05,0x54,0x5e,0x28,0x19,0x4b,0x3e,0x09,0x0b,0x93,0x18,0x40,0xf6,0xf3,0x73,0x0e,0xe1,0xe3,0x7d,0x6f,0x5d,0x39,0x73,0xda,0x17,0x32,0xf4,0x3e,0x9c,0x37,0xca,0xd6,0xde,0x8a,0x6f,0x9a,0xb2,0xb7,0xfd,0x3d,0x12,0x40,0xe3,0x91,0xb2,0x1a,0xa2,0xe1,0x97,0x7b,0x48,0x9e,0x94,0xe6,0xfd,0x02,0x7d,0x96,0xf9,0x97,0xde,0xd3,0xc8,0x2e,0xe7,0x0d,0x78}, - {0xbc,0xe7,0x9a,0x08,0x45,0x85,0xe2,0x0a,0x06,0x4d,0x7f,0x1c,0xcf,0xde,0x8d,0x38,0xb8,0x11,0x48,0x0a,0x51,0x15,0xac,0x38,0xe4,0x8c,0x92,0x71,0xf6,0x8b,0xb2,0x0e,0x72,0x27,0xf4,0x00,0xf3,0xea,0x1f,0x67,0xaa,0x41,0x8c,0x2a,0x2a,0xeb,0x72,0x8f,0x92,0x32,0x37,0x97,0xd7,0x7f,0xa1,0x29,0xa6,0x87,0xb5,0x32,0xad,0xc6,0xef,0x1d,0xa7,0x95,0x51,0xef,0x1a,0xbe,0x5b,0xaf,0xed,0x15,0x7b,0x91,0x77,0x12,0x8c,0x14,0x2e,0xda,0xe5,0x7a,0xfb,0xf7,0x91,0x29,0x67,0x28,0xdd,0xf8,0x1b,0x20,0x7d,0x46}, - {0xad,0x4f,0xef,0x74,0x9a,0x91,0xfe,0x95,0xa2,0x08,0xa3,0xf6,0xec,0x7b,0x82,0x3a,0x01,0x7b,0xa4,0x09,0xd3,0x01,0x4e,0x96,0x97,0xc7,0xa3,0x5b,0x4f,0x3c,0xc4,0x71,0xa9,0xe7,0x7a,0x56,0xbd,0xf4,0x1e,0xbc,0xbd,0x98,0x44,0xd6,0xb2,0x4c,0x62,0x3f,0xc8,0x4e,0x1f,0x2c,0xd2,0x64,0x10,0xe4,0x01,0x40,0x38,0xba,0xa5,0xc5,0xf9,0x2e,0xcd,0x74,0x9e,0xfa,0xf6,0x6d,0xfd,0xb6,0x7a,0x26,0xaf,0xe4,0xbc,0x78,0x82,0xf1,0x0e,0x99,0xef,0xf1,0xd0,0xb3,0x55,0x82,0x93,0xf2,0xc5,0x90,0xa3,0x8c,0x75,0x5a}, - {0x95,0x24,0x46,0xd9,0x10,0x27,0xb7,0xa2,0x03,0x50,0x7d,0xd5,0xd2,0xc6,0xa8,0x3a,0xca,0x87,0xb4,0xa0,0xbf,0x00,0xd4,0xe3,0xec,0x72,0xeb,0xb3,0x44,0xe2,0xba,0x2d,0x94,0xdc,0x61,0x1d,0x8b,0x91,0xe0,0x8c,0x66,0x30,0x81,0x9a,0x46,0x36,0xed,0x8d,0xd3,0xaa,0xe8,0xaf,0x29,0xa8,0xe6,0xd4,0x3f,0xd4,0x39,0xf6,0x27,0x80,0x73,0x0a,0xcc,0xe1,0xff,0x57,0x2f,0x4a,0x0f,0x98,0x43,0x98,0x83,0xe1,0x0d,0x0d,0x67,0x00,0xfd,0x15,0xfb,0x49,0x4a,0x3f,0x5c,0x10,0x9c,0xa6,0x26,0x51,0x63,0xca,0x98,0x26}, - {0x78,0xba,0xb0,0x32,0x88,0x31,0x65,0xe7,0x8b,0xff,0x5c,0x92,0xf7,0x31,0x18,0x38,0xcc,0x1f,0x29,0xa0,0x91,0x1b,0xa8,0x08,0x07,0xeb,0xca,0x49,0xcc,0x3d,0xb4,0x1f,0x0e,0xd9,0x3d,0x5e,0x2f,0x70,0x3d,0x2e,0x86,0x53,0xd2,0xe4,0x18,0x09,0x3f,0x9e,0x6a,0xa9,0x4d,0x02,0xf6,0x3e,0x77,0x5e,0x32,0x33,0xfa,0x4a,0x0c,0x4b,0x00,0x3c,0x2b,0xb8,0xf4,0x06,0xac,0x46,0xa9,0x9a,0xf3,0xc4,0x06,0xa8,0xa5,0x84,0xa2,0x1c,0x87,0x47,0xcd,0xc6,0x5f,0x26,0xd3,0x3e,0x17,0xd2,0x1f,0xcd,0x01,0xfd,0x43,0x6b}, - {0x44,0xc5,0x97,0x46,0x4b,0x5d,0xa7,0xc7,0xbf,0xff,0x0f,0xdf,0x48,0xf8,0xfd,0x15,0x5a,0x78,0x46,0xaa,0xeb,0xb9,0x68,0x28,0x14,0xf7,0x52,0x5b,0x10,0xd7,0x68,0x5a,0xf3,0x0e,0x76,0x3e,0x58,0x42,0xc7,0xb5,0x90,0xb9,0x0a,0xee,0xb9,0x52,0xdc,0x75,0x3f,0x92,0x2b,0x07,0xc2,0x27,0x14,0xbf,0xf0,0xd9,0xf0,0x6f,0x2d,0x0b,0x42,0x73,0x06,0x1e,0x85,0x9e,0xcb,0xf6,0x2c,0xaf,0xc4,0x38,0x22,0xc6,0x13,0x39,0x59,0x8f,0x73,0xf3,0xfb,0x99,0x96,0xb8,0x8a,0xda,0x9e,0xbc,0x34,0xea,0x2f,0x63,0xb5,0x3d}, - {0xd8,0xd9,0x5d,0xf7,0x2b,0xee,0x6e,0xf4,0xa5,0x59,0x67,0x39,0xf6,0xb1,0x17,0x0d,0x73,0x72,0x9e,0x49,0x31,0xd1,0xf2,0x1b,0x13,0x5f,0xd7,0x49,0xdf,0x1a,0x32,0x04,0xd5,0x25,0x98,0x82,0xb1,0x90,0x49,0x2e,0x91,0x89,0x9a,0x3e,0x87,0xeb,0xea,0xed,0xf8,0x4a,0x70,0x4c,0x39,0x3d,0xf0,0xee,0x0e,0x2b,0xdf,0x95,0xa4,0x7e,0x19,0x59,0xae,0x5a,0xe5,0xe4,0x19,0x60,0xe1,0x04,0xe9,0x92,0x2f,0x7e,0x7a,0x43,0x7b,0xe7,0xa4,0x9a,0x15,0x6f,0xc1,0x2d,0xce,0xc7,0xc0,0x0c,0xd7,0xf4,0xc1,0xfd,0xea,0x45}, - {0x2b,0xd7,0x45,0x80,0x85,0x01,0x84,0x69,0x51,0x06,0x2f,0xcf,0xa2,0xfa,0x22,0x4c,0xc6,0x2d,0x22,0x6b,0x65,0x36,0x1a,0x94,0xde,0xda,0x62,0x03,0xc8,0xeb,0x5e,0x5a,0xed,0xb1,0xcc,0xcf,0x24,0x46,0x0e,0xb6,0x95,0x03,0x5c,0xbd,0x92,0xc2,0xdb,0x59,0xc9,0x81,0x04,0xdc,0x1d,0x9d,0xa0,0x31,0x40,0xd9,0x56,0x5d,0xea,0xce,0x73,0x3f,0xc6,0x8d,0x4e,0x0a,0xd1,0xbf,0xa7,0xb7,0x39,0xb3,0xc9,0x44,0x7e,0x00,0x57,0xbe,0xfa,0xae,0x57,0x15,0x7f,0x20,0xc1,0x60,0xdb,0x18,0x62,0x26,0x91,0x88,0x05,0x26}, - {0x04,0xff,0x60,0x83,0xa6,0x04,0xf7,0x59,0xf4,0xe6,0x61,0x76,0xde,0x3f,0xd9,0xc3,0x51,0x35,0x87,0x12,0x73,0x2a,0x1b,0x83,0x57,0x5d,0x61,0x4e,0x2e,0x0c,0xad,0x54,0x42,0xe5,0x76,0xc6,0x3c,0x8e,0x81,0x4c,0xad,0xcc,0xce,0x03,0x93,0x2c,0x42,0x5e,0x08,0x9f,0x12,0xb4,0xca,0xcc,0x07,0xec,0xb8,0x43,0x44,0xb2,0x10,0xfa,0xed,0x0d,0x2a,0x52,0x2b,0xb8,0xd5,0x67,0x3b,0xee,0xeb,0xc1,0xa5,0x9f,0x46,0x63,0xf1,0x36,0xd3,0x9f,0xc1,0x6e,0xf2,0xd2,0xb4,0xa5,0x08,0x94,0x7a,0xa7,0xba,0xb2,0xec,0x62}, - {0x3d,0x2b,0x15,0x61,0x52,0x79,0xed,0xe5,0xd1,0xd7,0xdd,0x0e,0x7d,0x35,0x62,0x49,0x71,0x4c,0x6b,0xb9,0xd0,0xc8,0x82,0x74,0xbe,0xd8,0x66,0xa9,0x19,0xf9,0x59,0x2e,0x74,0x28,0xb6,0xaf,0x36,0x28,0x07,0x92,0xa5,0x04,0xe1,0x79,0x85,0x5e,0xcd,0x5f,0x4a,0xa1,0x30,0xc6,0xad,0x01,0xad,0x5a,0x98,0x3f,0x66,0x75,0x50,0x3d,0x91,0x61,0xda,0x31,0x32,0x1a,0x36,0x2d,0xc6,0x0d,0x70,0x02,0x20,0x94,0x32,0x58,0x47,0xfa,0xce,0x94,0x95,0x3f,0x51,0x01,0xd8,0x02,0x5c,0x5d,0xc0,0x31,0xa1,0xc2,0xdb,0x3d}, - {0x4b,0xc5,0x5e,0xce,0xf9,0x0f,0xdc,0x9a,0x0d,0x13,0x2f,0x8c,0x6b,0x2a,0x9c,0x03,0x15,0x95,0xf8,0xf0,0xc7,0x07,0x80,0x02,0x6b,0xb3,0x04,0xac,0x14,0x83,0x96,0x78,0x14,0xbb,0x96,0x27,0xa2,0x57,0xaa,0xf3,0x21,0xda,0x07,0x9b,0xb7,0xba,0x3a,0x88,0x1c,0x39,0xa0,0x31,0x18,0xe2,0x4b,0xe5,0xf9,0x05,0x32,0xd8,0x38,0xfb,0xe7,0x5e,0x8e,0x6a,0x44,0x41,0xcb,0xfd,0x8d,0x53,0xf9,0x37,0x49,0x43,0xa9,0xfd,0xac,0xa5,0x78,0x8c,0x3c,0x26,0x8d,0x90,0xaf,0x46,0x09,0x0d,0xca,0x9b,0x3c,0x63,0xd0,0x61}, - {0x66,0x25,0xdb,0xff,0x35,0x49,0x74,0x63,0xbb,0x68,0x0b,0x78,0x89,0x6b,0xbd,0xc5,0x03,0xec,0x3e,0x55,0x80,0x32,0x1b,0x6f,0xf5,0xd7,0xae,0x47,0xd8,0x5f,0x96,0x6e,0xdf,0x73,0xfc,0xf8,0xbc,0x28,0xa3,0xad,0xfc,0x37,0xf0,0xa6,0x5d,0x69,0x84,0xee,0x09,0xa9,0xc2,0x38,0xdb,0xb4,0x7f,0x63,0xdc,0x7b,0x06,0xf8,0x2d,0xac,0x23,0x5b,0x7b,0x52,0x80,0xee,0x53,0xb9,0xd2,0x9a,0x8d,0x6d,0xde,0xfa,0xaa,0x19,0x8f,0xe8,0xcf,0x82,0x0e,0x15,0x04,0x17,0x71,0x0e,0xdc,0xde,0x95,0xdd,0xb9,0xbb,0xb9,0x79}, - {0xc2,0x26,0x31,0x6a,0x40,0x55,0xb3,0xeb,0x93,0xc3,0xc8,0x68,0xa8,0x83,0x63,0xd2,0x82,0x7a,0xb9,0xe5,0x29,0x64,0x0c,0x6c,0x47,0x21,0xfd,0xc9,0x58,0xf1,0x65,0x50,0x74,0x73,0x9f,0x8e,0xae,0x7d,0x99,0xd1,0x16,0x08,0xbb,0xcf,0xf8,0xa2,0x32,0xa0,0x0a,0x5f,0x44,0x6d,0x12,0xba,0x6c,0xcd,0x34,0xb8,0xcc,0x0a,0x46,0x11,0xa8,0x1b,0x54,0x99,0x42,0x0c,0xfb,0x69,0x81,0x70,0x67,0xcf,0x6e,0xd7,0xac,0x00,0x46,0xe1,0xba,0x45,0xe6,0x70,0x8a,0xb9,0xaa,0x2e,0xf2,0xfa,0xa4,0x58,0x9e,0xf3,0x81,0x39}, - {0x93,0x0a,0x23,0x59,0x75,0x8a,0xfb,0x18,0x5d,0xf4,0xe6,0x60,0x69,0x8f,0x16,0x1d,0xb5,0x3c,0xa9,0x14,0x45,0xa9,0x85,0x3a,0xfd,0xd0,0xac,0x05,0x37,0x08,0xdc,0x38,0xde,0x6f,0xe6,0x6d,0xa5,0xdf,0x45,0xc8,0x3a,0x48,0x40,0x2c,0x00,0xa5,0x52,0xe1,0x32,0xf6,0xb4,0xc7,0x63,0xe1,0xd2,0xe9,0x65,0x1b,0xbc,0xdc,0x2e,0x45,0xf4,0x30,0x40,0x97,0x75,0xc5,0x82,0x27,0x6d,0x85,0xcc,0xbe,0x9c,0xf9,0x69,0x45,0x13,0xfa,0x71,0x4e,0xea,0xc0,0x73,0xfc,0x44,0x88,0x69,0x24,0x3f,0x59,0x1a,0x9a,0x2d,0x63}, - {0xa6,0xcb,0x07,0xb8,0x15,0x6b,0xbb,0xf6,0xd7,0xf0,0x54,0xbc,0xdf,0xc7,0x23,0x18,0x0b,0x67,0x29,0x6e,0x03,0x97,0x1d,0xbb,0x57,0x4a,0xed,0x47,0x88,0xf4,0x24,0x0b,0xa7,0x84,0x0c,0xed,0x11,0xfd,0x09,0xbf,0x3a,0x69,0x9f,0x0d,0x81,0x71,0xf0,0x63,0x79,0x87,0xcf,0x57,0x2d,0x8c,0x90,0x21,0xa2,0x4b,0xf6,0x8a,0xf2,0x7d,0x5a,0x3a,0xc7,0xea,0x1b,0x51,0xbe,0xd4,0xda,0xdc,0xf2,0xcc,0x26,0xed,0x75,0x80,0x53,0xa4,0x65,0x9a,0x5f,0x00,0x9f,0xff,0x9c,0xe1,0x63,0x1f,0x48,0x75,0x44,0xf7,0xfc,0x34}, - {0xca,0x67,0x97,0x78,0x4c,0xe0,0x97,0xc1,0x7d,0x46,0xd9,0x38,0xcb,0x4d,0x71,0xb8,0xa8,0x5f,0xf9,0x83,0x82,0x88,0xde,0x55,0xf7,0x63,0xfa,0x4d,0x16,0xdc,0x3b,0x3d,0x98,0xaa,0xcf,0x78,0xab,0x1d,0xbb,0xa5,0xf2,0x72,0x0b,0x19,0x67,0xa2,0xed,0x5c,0x8e,0x60,0x92,0x0a,0x11,0xc9,0x09,0x93,0xb0,0x74,0xb3,0x2f,0x04,0xa3,0x19,0x01,0x7d,0x17,0xc2,0xe8,0x9c,0xd8,0xa2,0x67,0xc1,0xd0,0x95,0x68,0xf6,0xa5,0x9d,0x66,0xb0,0xa2,0x82,0xb2,0xe5,0x98,0x65,0xf5,0x73,0x0a,0xe2,0xed,0xf1,0x88,0xc0,0x56}, - {0x17,0x6e,0xa8,0x10,0x11,0x3d,0x6d,0x33,0xfa,0xb2,0x75,0x0b,0x32,0x88,0xf3,0xd7,0x88,0x29,0x07,0x25,0x76,0x33,0x15,0xf9,0x87,0x8b,0x10,0x99,0x6b,0x4c,0x67,0x09,0x02,0x8f,0xf3,0x24,0xac,0x5f,0x1b,0x58,0xbd,0x0c,0xe3,0xba,0xfe,0xe9,0x0b,0xa9,0xf0,0x92,0xcf,0x8a,0x02,0x69,0x21,0x9a,0x8f,0x03,0x59,0x83,0xa4,0x7e,0x8b,0x03,0xf8,0x6f,0x31,0x99,0x21,0xf8,0x4e,0x9f,0x4f,0x8d,0xa7,0xea,0x82,0xd2,0x49,0x2f,0x74,0x31,0xef,0x5a,0xab,0xa5,0x71,0x09,0x65,0xeb,0x69,0x59,0x02,0x31,0x5e,0x6e}, - {0xfb,0x93,0xe5,0x87,0xf5,0x62,0x6c,0xb1,0x71,0x3e,0x5d,0xca,0xde,0xed,0x99,0x49,0x6d,0x3e,0xcc,0x14,0xe0,0xc1,0x91,0xb4,0xa8,0xdb,0xa8,0x89,0x47,0x11,0xf5,0x08,0x22,0x62,0x06,0x63,0x0e,0xfb,0x04,0x33,0x3f,0xba,0xac,0x87,0x89,0x06,0x35,0xfb,0xa3,0x61,0x10,0x8c,0x77,0x24,0x19,0xbd,0x20,0x86,0x83,0xd1,0x43,0xad,0x58,0x30,0xd0,0x63,0x76,0xe5,0xfd,0x0f,0x3c,0x32,0x10,0xa6,0x2e,0xa2,0x38,0xdf,0xc3,0x05,0x9a,0x4f,0x99,0xac,0xbd,0x8a,0xc7,0xbd,0x99,0xdc,0xe3,0xef,0xa4,0x9f,0x54,0x26}, - {0xd6,0xf9,0x6b,0x1e,0x46,0x5a,0x1d,0x74,0x81,0xa5,0x77,0x77,0xfc,0xb3,0x05,0x23,0xd9,0xd3,0x74,0x64,0xa2,0x74,0x55,0xd4,0xff,0xe0,0x01,0x64,0xdc,0xe1,0x26,0x19,0x6e,0x66,0x3f,0xaf,0x49,0x85,0x46,0xdb,0xa5,0x0e,0x4a,0xf1,0x04,0xcf,0x7f,0xd7,0x47,0x0c,0xba,0xa4,0xf7,0x3f,0xf2,0x3d,0x85,0x3c,0xce,0x32,0xe1,0xdf,0x10,0x3a,0xa0,0xce,0x17,0xea,0x8a,0x4e,0x7f,0xe0,0xfd,0xc1,0x1f,0x3a,0x46,0x15,0xd5,0x2f,0xf1,0xc0,0xf2,0x31,0xfd,0x22,0x53,0x17,0x15,0x5d,0x1e,0x86,0x1d,0xd0,0xa1,0x1f}, - {0x32,0x98,0x59,0x7d,0x94,0x55,0x80,0xcc,0x20,0x55,0xf1,0x37,0xda,0x56,0x46,0x1e,0x20,0x93,0x05,0x4e,0x74,0xf7,0xf6,0x99,0x33,0xcf,0x75,0x6a,0xbc,0x63,0x35,0x77,0xab,0x94,0xdf,0xd1,0x00,0xac,0xdc,0x38,0xe9,0x0d,0x08,0xd1,0xdd,0x2b,0x71,0x2e,0x62,0xe2,0xd5,0xfd,0x3e,0xe9,0x13,0x7f,0xe5,0x01,0x9a,0xee,0x18,0xed,0xfc,0x73,0xb3,0x9c,0x13,0x63,0x08,0xe9,0xb1,0x06,0xcd,0x3e,0xa0,0xc5,0x67,0xda,0x93,0xa4,0x32,0x89,0x63,0xad,0xc8,0xce,0x77,0x8d,0x44,0x4f,0x86,0x1b,0x70,0x6b,0x42,0x1f}, - {0x01,0x1c,0x91,0x41,0x4c,0x26,0xc9,0xef,0x25,0x2c,0xa2,0x17,0xb8,0xb7,0xa3,0xf1,0x47,0x14,0x0f,0xf3,0x6b,0xda,0x75,0x58,0x90,0xb0,0x31,0x1d,0x27,0xf5,0x1a,0x4e,0x52,0x25,0xa1,0x91,0xc8,0x35,0x7e,0xf1,0x76,0x9c,0x5e,0x57,0x53,0x81,0x6b,0xb7,0x3e,0x72,0x9b,0x0d,0x6f,0x40,0x83,0xfa,0x38,0xe4,0xa7,0x3f,0x1b,0xbb,0x76,0x0b,0x9b,0x93,0x92,0x7f,0xf9,0xc1,0xb8,0x08,0x6e,0xab,0x44,0xd4,0xcb,0x71,0x67,0xbe,0x17,0x80,0xbb,0x99,0x63,0x64,0xe5,0x22,0x55,0xa9,0x72,0xb7,0x1e,0xd6,0x6d,0x7b}, - {0x92,0x3d,0xf3,0x50,0xe8,0xc1,0xad,0xb7,0xcf,0xd5,0x8c,0x60,0x4f,0xfa,0x98,0x79,0xdb,0x5b,0xfc,0x8d,0xbd,0x2d,0x96,0xad,0x4f,0x2f,0x1d,0xaf,0xce,0x9b,0x3e,0x70,0xc7,0xd2,0x01,0xab,0xf9,0xab,0x30,0x57,0x18,0x3b,0x14,0x40,0xdc,0x76,0xfb,0x16,0x81,0xb2,0xcb,0xa0,0x65,0xbe,0x6c,0x86,0xfe,0x6a,0xff,0x9b,0x65,0x9b,0xfa,0x53,0x55,0x54,0x88,0x94,0xe9,0xc8,0x14,0x6c,0xe5,0xd4,0xae,0x65,0x66,0x5d,0x3a,0x84,0xf1,0x5a,0xd6,0xbc,0x3e,0xb7,0x1b,0x18,0x50,0x1f,0xc6,0xc4,0xe5,0x93,0x8d,0x39}, - {0xf3,0x48,0xe2,0x33,0x67,0xd1,0x4b,0x1c,0x5f,0x0a,0xbf,0x15,0x87,0x12,0x9e,0xbd,0x76,0x03,0x0b,0xa1,0xf0,0x8c,0x3f,0xd4,0x13,0x1b,0x19,0xdf,0x5d,0x9b,0xb0,0x53,0xf2,0xe3,0xe7,0xd2,0x60,0x7c,0x87,0xc3,0xb1,0x8b,0x82,0x30,0xa0,0xaa,0x34,0x3b,0x38,0xf1,0x9e,0x73,0xe7,0x26,0x3e,0x28,0x77,0x05,0xc3,0x02,0x90,0x9c,0x9c,0x69,0xcc,0xf1,0x46,0x59,0x23,0xa7,0x06,0xf3,0x7d,0xd9,0xe5,0xcc,0xb5,0x18,0x17,0x92,0x75,0xe9,0xb4,0x81,0x47,0xd2,0xcd,0x28,0x07,0xd9,0xcd,0x6f,0x0c,0xf3,0xca,0x51}, - {0x0a,0xe0,0x74,0x76,0x42,0xa7,0x0b,0xa6,0xf3,0x7b,0x7a,0xa1,0x70,0x85,0x0e,0x63,0xcc,0x24,0x33,0xcf,0x3d,0x56,0x58,0x37,0xaa,0xfd,0x83,0x23,0x29,0xaa,0x04,0x55,0xc7,0x54,0xac,0x18,0x9a,0xf9,0x7a,0x73,0x0f,0xb3,0x1c,0xc5,0xdc,0x78,0x33,0x90,0xc7,0x0c,0xe1,0x4c,0x33,0xbc,0x89,0x2b,0x9a,0xe9,0xf8,0x89,0xc1,0x29,0xae,0x12,0xcf,0x01,0x0d,0x1f,0xcb,0xc0,0x9e,0xa9,0xae,0xf7,0x34,0x3a,0xcc,0xef,0xd1,0x0d,0x22,0x4e,0x9c,0xd0,0x21,0x75,0xca,0x55,0xea,0xa5,0xeb,0x58,0xe9,0x4f,0xd1,0x5f}, - {0x2c,0xab,0x45,0x28,0xdf,0x2d,0xdc,0xb5,0x93,0xe9,0x7f,0x0a,0xb1,0x91,0x94,0x06,0x46,0xe3,0x02,0x40,0xd6,0xf3,0xaa,0x4d,0xd1,0x74,0x64,0x58,0x6e,0xf2,0x3f,0x09,0x8e,0xcb,0x93,0xbf,0x5e,0xfe,0x42,0x3c,0x5f,0x56,0xd4,0x36,0x51,0xa8,0xdf,0xbe,0xe8,0x20,0x42,0x88,0x9e,0x85,0xf0,0xe0,0x28,0xd1,0x25,0x07,0x96,0x3f,0xd7,0x7d,0x29,0x98,0x05,0x68,0xfe,0x24,0x0d,0xb1,0xe5,0x23,0xaf,0xdb,0x72,0x06,0x73,0x75,0x29,0xac,0x57,0xb4,0x3a,0x25,0x67,0x13,0xa4,0x70,0xb4,0x86,0xbc,0xbc,0x59,0x2f}, - {0x5f,0x13,0x17,0x99,0x42,0x7d,0x84,0x83,0xd7,0x03,0x7d,0x56,0x1f,0x91,0x1b,0xad,0xd1,0xaa,0x77,0xbe,0xd9,0x48,0x77,0x7e,0x4a,0xaf,0x51,0x2e,0x2e,0xb4,0x58,0x54,0x01,0xc3,0x91,0xb6,0x60,0xd5,0x41,0x70,0x1e,0xe7,0xd7,0xad,0x3f,0x1b,0x20,0x85,0x85,0x55,0x33,0x11,0x63,0xe1,0xc2,0x16,0xb1,0x28,0x08,0x01,0x3d,0x5e,0xa5,0x2a,0x4f,0x44,0x07,0x0c,0xe6,0x92,0x51,0xed,0x10,0x1d,0x42,0x74,0x2d,0x4e,0xc5,0x42,0x64,0xc8,0xb5,0xfd,0x82,0x4c,0x2b,0x35,0x64,0x86,0x76,0x8a,0x4a,0x00,0xe9,0x13}, - {0xdb,0xce,0x2f,0x83,0x45,0x88,0x9d,0x73,0x63,0xf8,0x6b,0xae,0xc9,0xd6,0x38,0xfa,0xf7,0xfe,0x4f,0xb7,0xca,0x0d,0xbc,0x32,0x5e,0xe4,0xbc,0x14,0x88,0x7e,0x93,0x73,0x7f,0x87,0x3b,0x19,0xc9,0x00,0x2e,0xbb,0x6b,0x50,0xdc,0xe0,0x90,0xa8,0xe3,0xec,0x9f,0x64,0xde,0x36,0xc0,0xb7,0xf3,0xec,0x1a,0x9e,0xde,0x98,0x08,0x04,0x46,0x5f,0x8d,0xf4,0x7b,0x29,0x16,0x71,0x03,0xb9,0x34,0x68,0xf0,0xd4,0x22,0x3b,0xd1,0xa9,0xc6,0xbd,0x96,0x46,0x57,0x15,0x97,0xe1,0x35,0xe8,0xd5,0x91,0xe8,0xa4,0xf8,0x2c}, - {0x67,0x0f,0x11,0x07,0x87,0xfd,0x93,0x6d,0x49,0xb5,0x38,0x7c,0xd3,0x09,0x4c,0xdd,0x86,0x6a,0x73,0xc2,0x4c,0x6a,0xb1,0x7c,0x09,0x2a,0x25,0x58,0x6e,0xbd,0x49,0x20,0xa2,0x6b,0xd0,0x17,0x7e,0x48,0xb5,0x2c,0x6b,0x19,0x50,0x39,0x1c,0x38,0xd2,0x24,0x30,0x8a,0x97,0x85,0x81,0x9c,0x65,0xd7,0xf6,0xa4,0xd6,0x91,0x28,0x7f,0x6f,0x7a,0x49,0xef,0x9a,0x6a,0x8d,0xfd,0x09,0x7d,0x0b,0xb9,0x3d,0x5b,0xbe,0x60,0xee,0xf0,0xd4,0xbf,0x9e,0x51,0x2c,0xb5,0x21,0x4c,0x1d,0x94,0x45,0xc5,0xdf,0xaa,0x11,0x60}, - {0x3c,0xf8,0x95,0xcf,0x6d,0x92,0x67,0x5f,0x71,0x90,0x28,0x71,0x61,0x85,0x7e,0x7c,0x5b,0x7a,0x8f,0x99,0xf3,0xe7,0xa1,0xd6,0xe0,0xf9,0x62,0x0b,0x1b,0xcc,0xc5,0x6f,0x90,0xf8,0xcb,0x02,0xc8,0xd0,0xde,0x63,0xaa,0x6a,0xff,0x0d,0xca,0x98,0xd0,0xfb,0x99,0xed,0xb6,0xb9,0xfd,0x0a,0x4d,0x62,0x1e,0x0b,0x34,0x79,0xb7,0x18,0xce,0x69,0xcb,0x79,0x98,0xb2,0x28,0x55,0xef,0xd1,0x92,0x90,0x7e,0xd4,0x3c,0xae,0x1a,0xdd,0x52,0x23,0x9f,0x18,0x42,0x04,0x7e,0x12,0xf1,0x01,0x71,0xe5,0x3a,0x6b,0x59,0x15}, - {0xa2,0x79,0x91,0x3f,0xd2,0x39,0x27,0x46,0xcf,0xdd,0xd6,0x97,0x31,0x12,0x83,0xff,0x8a,0x14,0xf2,0x53,0xb5,0xde,0x07,0x13,0xda,0x4d,0x5f,0x7b,0x68,0x37,0x22,0x0d,0xca,0x24,0x51,0x7e,0x16,0x31,0xff,0x09,0xdf,0x45,0xc7,0xd9,0x8b,0x15,0xe4,0x0b,0xe5,0x56,0xf5,0x7e,0x22,0x7d,0x2b,0x29,0x38,0xd1,0xb6,0xaf,0x41,0xe2,0xa4,0x3a,0xf5,0x05,0x33,0x2a,0xbf,0x38,0xc1,0x2c,0xc3,0x26,0xe9,0xa2,0x8f,0x3f,0x58,0x48,0xeb,0xd2,0x49,0x55,0xa2,0xb1,0x3a,0x08,0x6c,0xa3,0x87,0x46,0x6e,0xaa,0xfc,0x32}, - {0xf5,0x9a,0x7d,0xc5,0x8d,0x6e,0xc5,0x7b,0xf2,0xbd,0xf0,0x9d,0xed,0xd2,0x0b,0x3e,0xa3,0xe4,0xef,0x22,0xde,0x14,0xc0,0xaa,0x5c,0x6a,0xbd,0xfe,0xce,0xe9,0x27,0x46,0xdf,0xcc,0x87,0x27,0x73,0xa4,0x07,0x32,0xf8,0xe3,0x13,0xf2,0x08,0x19,0xe3,0x17,0x4e,0x96,0x0d,0xf6,0xd7,0xec,0xb2,0xd5,0xe9,0x0b,0x60,0xc2,0x36,0x63,0x6f,0x74,0x1c,0x97,0x6c,0xab,0x45,0xf3,0x4a,0x3f,0x1f,0x73,0x43,0x99,0x72,0xeb,0x88,0xe2,0x6d,0x18,0x44,0x03,0x8a,0x6a,0x59,0x33,0x93,0x62,0xd6,0x7e,0x00,0x17,0x49,0x7b}, - {0x64,0xb0,0x84,0xab,0x5c,0xfb,0x85,0x2d,0x14,0xbc,0xf3,0x89,0xd2,0x10,0x78,0x49,0x0c,0xce,0x15,0x7b,0x44,0xdc,0x6a,0x47,0x7b,0xfd,0x44,0xf8,0x76,0xa3,0x2b,0x12,0xdd,0xa2,0x53,0xdd,0x28,0x1b,0x34,0x54,0x3f,0xfc,0x42,0xdf,0x5b,0x90,0x17,0xaa,0xf4,0xf8,0xd2,0x4d,0xd9,0x92,0xf5,0x0f,0x7d,0xd3,0x8c,0xe0,0x0f,0x62,0x03,0x1d,0x54,0xe5,0xb4,0xa2,0xcd,0x32,0x02,0xc2,0x7f,0x18,0x5d,0x11,0x42,0xfd,0xd0,0x9e,0xd9,0x79,0xd4,0x7d,0xbe,0xb4,0xab,0x2e,0x4c,0xec,0x68,0x2b,0xf5,0x0b,0xc7,0x02}, - {0xbb,0x2f,0x0b,0x5d,0x4b,0xec,0x87,0xa2,0xca,0x82,0x48,0x07,0x90,0x57,0x5c,0x41,0x5c,0x81,0xd0,0xc1,0x1e,0xa6,0x44,0xe0,0xe0,0xf5,0x9e,0x40,0x0a,0x4f,0x33,0x26,0xe1,0x72,0x8d,0x45,0xbf,0x32,0xe5,0xac,0xb5,0x3c,0xb7,0x7c,0xe0,0x68,0xe7,0x5b,0xe7,0xbd,0x8b,0xee,0x94,0x7d,0xcf,0x56,0x03,0x3a,0xb4,0xfe,0xe3,0x97,0x06,0x6b,0xc0,0xa3,0x62,0xdf,0x4a,0xf0,0xc8,0xb6,0x5d,0xa4,0x6d,0x07,0xef,0x00,0xf0,0x3e,0xa9,0xd2,0xf0,0x49,0x58,0xb9,0x9c,0x9c,0xae,0x2f,0x1b,0x44,0x43,0x7f,0xc3,0x1c}, - {0x4f,0x32,0xc7,0x5c,0x5a,0x56,0x8f,0x50,0x22,0xa9,0x06,0xe5,0xc0,0xc4,0x61,0xd0,0x19,0xac,0x45,0x5c,0xdb,0xab,0x18,0xfb,0x4a,0x31,0x80,0x03,0xc1,0x09,0x68,0x6c,0xb9,0xae,0xce,0xc9,0xf1,0x56,0x66,0xd7,0x6a,0x65,0xe5,0x18,0xf8,0x15,0x5b,0x1c,0x34,0x23,0x4c,0x84,0x32,0x28,0xe7,0x26,0x38,0x68,0x19,0x2f,0x77,0x6f,0x34,0x3a,0xc8,0x6a,0xda,0xe2,0x12,0x51,0xd5,0xd2,0xed,0x51,0xe8,0xb1,0x31,0x03,0xbd,0xe9,0x62,0x72,0xc6,0x8e,0xdd,0x46,0x07,0x96,0xd0,0xc5,0xf7,0x6e,0x9f,0x1b,0x91,0x05}, - {0xbb,0x0e,0xdf,0xf5,0x83,0x99,0x33,0xc1,0xac,0x4c,0x2c,0x51,0x8f,0x75,0xf3,0xc0,0xe1,0x98,0xb3,0x0b,0x0a,0x13,0xf1,0x2c,0x62,0x0c,0x27,0xaa,0xf9,0xec,0x3c,0x6b,0xef,0xea,0x2e,0x51,0xf3,0xac,0x49,0x53,0x49,0xcb,0xc1,0x1c,0xd3,0x41,0xc1,0x20,0x8d,0x68,0x9a,0xa9,0x07,0x0c,0x18,0x24,0x17,0x2d,0x4b,0xc6,0xd1,0xf9,0x5e,0x55,0x08,0xbd,0x73,0x3b,0xba,0x70,0xa7,0x36,0x0c,0xbf,0xaf,0xa3,0x08,0xef,0x4a,0x62,0xf2,0x46,0x09,0xb4,0x98,0xff,0x37,0x57,0x9d,0x74,0x81,0x33,0xe1,0x4d,0x5f,0x67}, - {0xfc,0x82,0x17,0x6b,0x03,0x52,0x2c,0x0e,0xb4,0x83,0xad,0x6c,0x81,0x6c,0x81,0x64,0x3e,0x07,0x64,0x69,0xd9,0xbd,0xdc,0xd0,0x20,0xc5,0x64,0x01,0xf7,0x9d,0xd9,0x13,0x1d,0xb3,0xda,0x3b,0xd9,0xf6,0x2f,0xa1,0xfe,0x2d,0x65,0x9d,0x0f,0xd8,0x25,0x07,0x87,0x94,0xbe,0x9a,0xf3,0x4f,0x9c,0x01,0x43,0x3c,0xcd,0x82,0xb8,0x50,0xf4,0x60,0xca,0xc0,0xe5,0x21,0xc3,0x5e,0x4b,0x01,0xa2,0xbf,0x19,0xd7,0xc9,0x69,0xcb,0x4f,0xa0,0x23,0x00,0x75,0x18,0x1c,0x5f,0x4e,0x80,0xac,0xed,0x55,0x9e,0xde,0x06,0x1c}, - {0xe2,0xc4,0x3e,0xa3,0xd6,0x7a,0x0f,0x99,0x8e,0xe0,0x2e,0xbe,0x38,0xf9,0x08,0x66,0x15,0x45,0x28,0x63,0xc5,0x43,0xa1,0x9c,0x0d,0xb6,0x2d,0xec,0x1f,0x8a,0xf3,0x4c,0xaa,0x69,0x6d,0xff,0x40,0x2b,0xd5,0xff,0xbb,0x49,0x40,0xdc,0x18,0x0b,0x53,0x34,0x97,0x98,0x4d,0xa3,0x2f,0x5c,0x4a,0x5e,0x2d,0xba,0x32,0x7d,0x8e,0x6f,0x09,0x78,0xe7,0x5c,0xfa,0x0d,0x65,0xaa,0xaa,0xa0,0x8c,0x47,0xb5,0x48,0x2a,0x9e,0xc4,0xf9,0x5b,0x72,0x03,0x70,0x7d,0xcc,0x09,0x4f,0xbe,0x1a,0x09,0x26,0x3a,0xad,0x3c,0x37}, - {0x7c,0xf5,0xc9,0x82,0x4d,0x63,0x94,0xb2,0x36,0x45,0x93,0x24,0xe1,0xfd,0xcb,0x1f,0x5a,0xdb,0x8c,0x41,0xb3,0x4d,0x9c,0x9e,0xfc,0x19,0x44,0x45,0xd9,0xf3,0x40,0x00,0xad,0xbb,0xdd,0x89,0xfb,0xa8,0xbe,0xf1,0xcb,0xae,0xae,0x61,0xbc,0x2c,0xcb,0x3b,0x9d,0x8d,0x9b,0x1f,0xbb,0xa7,0x58,0x8f,0x86,0xa6,0x12,0x51,0xda,0x7e,0x54,0x21,0xd3,0x86,0x59,0xfd,0x39,0xe9,0xfd,0xde,0x0c,0x38,0x0a,0x51,0x89,0x2c,0x27,0xf4,0xb9,0x19,0x31,0xbb,0x07,0xa4,0x2b,0xb7,0xf4,0x4d,0x25,0x4a,0x33,0x0a,0x55,0x63}, - {0x37,0xcf,0x69,0xb5,0xed,0xd6,0x07,0x65,0xe1,0x2e,0xa5,0x0c,0xb0,0x29,0x84,0x17,0x5d,0xd6,0x6b,0xeb,0x90,0x00,0x7c,0xea,0x51,0x8f,0xf7,0xda,0xc7,0x62,0xea,0x3e,0x49,0x7b,0x54,0x72,0x45,0x58,0xba,0x9b,0xe0,0x08,0xc4,0xe2,0xfa,0xc6,0x05,0xf3,0x8d,0xf1,0x34,0xc7,0x69,0xfa,0xe8,0x60,0x7a,0x76,0x7d,0xaa,0xaf,0x2b,0xa9,0x39,0x4e,0x27,0x93,0xe6,0x13,0xc7,0x24,0x9d,0x75,0xd3,0xdb,0x68,0x77,0x85,0x63,0x5f,0x9a,0xb3,0x8a,0xeb,0x60,0x55,0x52,0x70,0xcd,0xc4,0xc9,0x65,0x06,0x6a,0x43,0x68}, - {0x27,0x3f,0x2f,0x20,0xe8,0x35,0x02,0xbc,0xb0,0x75,0xf9,0x64,0xe2,0x00,0x5c,0xc7,0x16,0x24,0x8c,0xa3,0xd5,0xe9,0xa4,0x91,0xf9,0x89,0xb7,0x8a,0xf6,0xe7,0xb6,0x17,0x7c,0x10,0x20,0xe8,0x17,0xd3,0x56,0x1e,0x65,0xe9,0x0a,0x84,0x44,0x68,0x26,0xc5,0x7a,0xfc,0x0f,0x32,0xc6,0xa1,0xe0,0xc1,0x72,0x14,0x61,0x91,0x9c,0x66,0x73,0x53,0x57,0x52,0x0e,0x9a,0xab,0x14,0x28,0x5d,0xfc,0xb3,0xca,0xc9,0x84,0x20,0x8f,0x90,0xca,0x1e,0x2d,0x5b,0x88,0xf5,0xca,0xaf,0x11,0x7d,0xf8,0x78,0xa6,0xb5,0xb4,0x1c}, - {0x6c,0xfc,0x4a,0x39,0x6b,0xc0,0x64,0xb6,0xb1,0x5f,0xda,0x98,0x24,0xde,0x88,0x0c,0x34,0xd8,0xca,0x4b,0x16,0x03,0x8d,0x4f,0xa2,0x34,0x74,0xde,0x78,0xca,0x0b,0x33,0xe7,0x07,0xa0,0xa2,0x62,0xaa,0x74,0x6b,0xb1,0xc7,0x71,0xf0,0xb0,0xe0,0x11,0xf3,0x23,0xe2,0x0b,0x00,0x38,0xe4,0x07,0x57,0xac,0x6e,0xef,0x82,0x2d,0xfd,0xc0,0x2d,0x4e,0x74,0x19,0x11,0x84,0xff,0x2e,0x98,0x24,0x47,0x07,0x2b,0x96,0x5e,0x69,0xf9,0xfb,0x53,0xc9,0xbf,0x4f,0xc1,0x8a,0xc5,0xf5,0x1c,0x9f,0x36,0x1b,0xbe,0x31,0x3c}, - {0xee,0x8a,0x94,0x08,0x4d,0x86,0xf4,0xb0,0x6f,0x1c,0xba,0x91,0xee,0x19,0xdc,0x07,0x58,0xa1,0xac,0xa6,0xae,0xcd,0x75,0x79,0xbb,0xd4,0x62,0x42,0x13,0x61,0x0b,0x33,0x72,0x42,0xcb,0xf9,0x93,0xbc,0x68,0xc1,0x98,0xdb,0xce,0xc7,0x1f,0x71,0xb8,0xae,0x7a,0x8d,0xac,0x34,0xaa,0x52,0x0e,0x7f,0xbb,0x55,0x7d,0x7e,0x09,0xc1,0xce,0x41,0x8a,0x80,0x6d,0xa2,0xd7,0x19,0x96,0xf7,0x6d,0x15,0x9e,0x1d,0x9e,0xd4,0x1f,0xbb,0x27,0xdf,0xa1,0xdb,0x6c,0xc3,0xd7,0x73,0x7d,0x77,0x28,0x1f,0xd9,0x4c,0xb4,0x26}, - {0x75,0x74,0x38,0x8f,0x47,0x48,0xf0,0x51,0x3c,0xcb,0xbe,0x9c,0xf4,0xbc,0x5d,0xb2,0x55,0x20,0x9f,0xd9,0x44,0x12,0xab,0x9a,0xd6,0xa5,0x10,0x1c,0x6c,0x9e,0x70,0x2c,0x83,0x03,0x73,0x62,0x93,0xf2,0xb7,0xe1,0x2c,0x8a,0xca,0xeb,0xff,0x79,0x52,0x4b,0x14,0x13,0xd4,0xbf,0x8a,0x77,0xfc,0xda,0x0f,0x61,0x72,0x9c,0x14,0x10,0xeb,0x7d,0x7a,0xee,0x66,0x87,0x6a,0xaf,0x62,0xcb,0x0e,0xcd,0x53,0x55,0x04,0xec,0xcb,0x66,0xb5,0xe4,0x0b,0x0f,0x38,0x01,0x80,0x58,0xea,0xe2,0x2c,0xf6,0x9f,0x8e,0xe6,0x08}, - {0xad,0x30,0xc1,0x4b,0x0a,0x50,0xad,0x34,0x9c,0xd4,0x0b,0x3d,0x49,0xdb,0x38,0x8d,0xbe,0x89,0x0a,0x50,0x98,0x3d,0x5c,0xa2,0x09,0x3b,0xba,0xee,0x87,0x3f,0x1f,0x2f,0xf9,0xf2,0xb8,0x0a,0xd5,0x09,0x2d,0x2f,0xdf,0x23,0x59,0xc5,0x8d,0x21,0xb9,0xac,0xb9,0x6c,0x76,0x73,0x26,0x34,0x8f,0x4a,0xf5,0x19,0xf7,0x38,0xd7,0x3b,0xb1,0x4c,0x4a,0xb6,0x15,0xe5,0x75,0x8c,0x84,0xf7,0x38,0x90,0x4a,0xdb,0xba,0x01,0x95,0xa5,0x50,0x1b,0x75,0x3f,0x3f,0x31,0x0d,0xc2,0xe8,0x2e,0xae,0xc0,0x53,0xe3,0xa1,0x19}, - {0xc3,0x05,0xfa,0xba,0x60,0x75,0x1c,0x7d,0x61,0x5e,0xe5,0xc6,0xa0,0xa0,0xe1,0xb3,0x73,0x64,0xd6,0xc0,0x18,0x97,0x52,0xe3,0x86,0x34,0x0c,0xc2,0x11,0x6b,0x54,0x41,0xbd,0xbd,0x96,0xd5,0xcd,0x72,0x21,0xb4,0x40,0xfc,0xee,0x98,0x43,0x45,0xe0,0x93,0xb5,0x09,0x41,0xb4,0x47,0x53,0xb1,0x9f,0x34,0xae,0x66,0x02,0x99,0xd3,0x6b,0x73,0xb4,0xb3,0x34,0x93,0x50,0x2d,0x53,0x85,0x73,0x65,0x81,0x60,0x4b,0x11,0xfd,0x46,0x75,0x83,0x5c,0x42,0x30,0x5f,0x5f,0xcc,0x5c,0xab,0x7f,0xb8,0xa2,0x95,0x22,0x41}, - {0xe9,0xd6,0x7e,0xf5,0x88,0x9b,0xc9,0x19,0x25,0xc8,0xf8,0x6d,0x26,0xcb,0x93,0x53,0x73,0xd2,0x0a,0xb3,0x13,0x32,0xee,0x5c,0x34,0x2e,0x2d,0xb5,0xeb,0x53,0xe1,0x14,0xc6,0xea,0x93,0xe2,0x61,0x52,0x65,0x2e,0xdb,0xac,0x33,0x21,0x03,0x92,0x5a,0x84,0x6b,0x99,0x00,0x79,0xcb,0x75,0x09,0x46,0x80,0xdd,0x5a,0x19,0x8d,0xbb,0x60,0x07,0x8a,0x81,0xe6,0xcd,0x17,0x1a,0x3e,0x41,0x84,0xa0,0x69,0xed,0xa9,0x6d,0x15,0x57,0xb1,0xcc,0xca,0x46,0x8f,0x26,0xbf,0x2c,0xf2,0xc5,0x3a,0xc3,0x9b,0xbe,0x34,0x6b}, - {0xb2,0xc0,0x78,0x3a,0x64,0x2f,0xdf,0xf3,0x7c,0x02,0x2e,0xf2,0x1e,0x97,0x3e,0x4c,0xa3,0xb5,0xc1,0x49,0x5e,0x1c,0x7d,0xec,0x2d,0xdd,0x22,0x09,0x8f,0xc1,0x12,0x20,0xd3,0xf2,0x71,0x65,0x65,0x69,0xfc,0x11,0x7a,0x73,0x0e,0x53,0x45,0xe8,0xc9,0xc6,0x35,0x50,0xfe,0xd4,0xa2,0xe7,0x3a,0xe3,0x0b,0xd3,0x6d,0x2e,0xb6,0xc7,0xb9,0x01,0x29,0x9d,0xc8,0x5a,0xe5,0x55,0x0b,0x88,0x63,0xa7,0xa0,0x45,0x1f,0x24,0x83,0x14,0x1f,0x6c,0xe7,0xc2,0xdf,0xef,0x36,0x3d,0xe8,0xad,0x4b,0x4e,0x78,0x5b,0xaf,0x08}, - {0x33,0x25,0x1f,0x88,0xdc,0x99,0x34,0x28,0xb6,0x23,0x93,0x77,0xda,0x25,0x05,0x9d,0xf4,0x41,0x34,0x67,0xfb,0xdd,0x7a,0x89,0x8d,0x16,0x3a,0x16,0x71,0x9d,0xb7,0x32,0x4b,0x2c,0xcc,0x89,0xd2,0x14,0x73,0xe2,0x8d,0x17,0x87,0xa2,0x11,0xbd,0xe4,0x4b,0xce,0x64,0x33,0xfa,0xd6,0x28,0xd5,0x18,0x6e,0x82,0xd9,0xaf,0xd5,0xc1,0x23,0x64,0x6a,0xb3,0xfc,0xed,0xd9,0xf8,0x85,0xcc,0xf9,0xe5,0x46,0x37,0x8f,0xc2,0xbc,0x22,0xcd,0xd3,0xe5,0xf9,0x38,0xe3,0x9d,0xe4,0xcc,0x2d,0x3e,0xc1,0xfb,0x5e,0x0a,0x48}, - {0x71,0x20,0x62,0x01,0x0b,0xe7,0x51,0x0b,0xc5,0xaf,0x1d,0x8b,0xcf,0x05,0xb5,0x06,0xcd,0xab,0x5a,0xef,0x61,0xb0,0x6b,0x2c,0x31,0xbf,0xb7,0x0c,0x60,0x27,0xaa,0x47,0x1f,0x22,0xce,0x42,0xe4,0x4c,0x61,0xb6,0x28,0x39,0x05,0x4c,0xcc,0x9d,0x19,0x6e,0x03,0xbe,0x1c,0xdc,0xa4,0xb4,0x3f,0x66,0x06,0x8e,0x1c,0x69,0x47,0x1d,0xb3,0x24,0xc3,0xf8,0x15,0xc0,0xed,0x1e,0x54,0x2a,0x7c,0x3f,0x69,0x7c,0x7e,0xfe,0xa4,0x11,0xd6,0x78,0xa2,0x4e,0x13,0x66,0xaf,0xf0,0x94,0xa0,0xdd,0x14,0x5d,0x58,0x5b,0x54}, - {0x0f,0x3a,0xd4,0xa0,0x5e,0x27,0xbf,0x67,0xbe,0xee,0x9b,0x08,0x34,0x8e,0xe6,0xad,0x2e,0xe7,0x79,0xd4,0x4c,0x13,0x89,0x42,0x54,0x54,0xba,0x32,0xc3,0xf9,0x62,0x0f,0xe1,0x21,0xb3,0xe3,0xd0,0xe4,0x04,0x62,0x95,0x1e,0xff,0x28,0x7a,0x63,0xaa,0x3b,0x9e,0xbd,0x99,0x5b,0xfd,0xcf,0x0c,0x0b,0x71,0xd0,0xc8,0x64,0x3e,0xdc,0x22,0x4d,0x39,0x5f,0x3b,0xd6,0x89,0x65,0xb4,0xfc,0x61,0xcf,0xcb,0x57,0x3f,0x6a,0xae,0x5c,0x05,0xfa,0x3a,0x95,0xd2,0xc2,0xba,0xfe,0x36,0x14,0x37,0x36,0x1a,0xa0,0x0f,0x1c}, - {0xff,0x3d,0x94,0x22,0xb6,0x04,0xc6,0xd2,0xa0,0xb3,0xcf,0x44,0xce,0xbe,0x8c,0xbc,0x78,0x86,0x80,0x97,0xf3,0x4f,0x25,0x5d,0xbf,0xa6,0x1c,0x3b,0x4f,0x61,0xa3,0x0f,0x50,0x6a,0x93,0x8c,0x0e,0x2b,0x08,0x69,0xb6,0xc5,0xda,0xc1,0x35,0xa0,0xc9,0xf9,0x34,0xb6,0xdf,0xc4,0x54,0x3e,0xb7,0x6f,0x40,0xc1,0x2b,0x1d,0x9b,0x41,0x05,0x40,0xf0,0x82,0xbe,0xb9,0xbd,0xfe,0x03,0xa0,0x90,0xac,0x44,0x3a,0xaf,0xc1,0x89,0x20,0x8e,0xfa,0x54,0x19,0x91,0x9f,0x49,0xf8,0x42,0xab,0x40,0xef,0x8a,0x21,0xba,0x1f}, - {0x3e,0xf5,0xc8,0xfa,0x48,0x94,0x54,0xab,0x41,0x37,0xa6,0x7b,0x9a,0xe8,0xf6,0x81,0x01,0x5e,0x2b,0x6c,0x7d,0x6c,0xfd,0x74,0x42,0x6e,0xc8,0xa8,0xca,0x3a,0x2e,0x39,0x94,0x01,0x7b,0x3e,0x04,0x57,0x3e,0x4f,0x7f,0xaf,0xda,0x08,0xee,0x3e,0x1d,0xa8,0xf1,0xde,0xdc,0x99,0xab,0xc6,0x39,0xc8,0xd5,0x61,0x77,0xff,0x13,0x5d,0x53,0x6c,0xaf,0x35,0x8a,0x3e,0xe9,0x34,0xbd,0x4c,0x16,0xe8,0x87,0x58,0x44,0x81,0x07,0x2e,0xab,0xb0,0x9a,0xf2,0x76,0x9c,0x31,0x19,0x3b,0xc1,0x0a,0xd5,0xe4,0x7f,0xe1,0x25}, - {0x76,0xf6,0x04,0x1e,0xd7,0x9b,0x28,0x0a,0x95,0x0f,0x42,0xd6,0x52,0x1c,0x8e,0x20,0xab,0x1f,0x69,0x34,0xb0,0xd8,0x86,0x51,0x51,0xb3,0x9f,0x2a,0x44,0x51,0x57,0x25,0xa7,0x21,0xf1,0x76,0xf5,0x7f,0x5f,0x91,0xe3,0x87,0xcd,0x2f,0x27,0x32,0x4a,0xc3,0x26,0xe5,0x1b,0x4d,0xde,0x2f,0xba,0xcc,0x9b,0x89,0x69,0x89,0x8f,0x82,0xba,0x6b,0x01,0x39,0xfe,0x90,0x66,0xbc,0xd1,0xe2,0xd5,0x7a,0x99,0xa0,0x18,0x4a,0xb5,0x4c,0xd4,0x60,0x84,0xaf,0x14,0x69,0x1d,0x97,0xe4,0x7b,0x6b,0x7f,0x4f,0x50,0x9d,0x55}, - {0xd5,0x54,0xeb,0xb3,0x78,0x83,0x73,0xa7,0x7c,0x3c,0x55,0xa5,0x66,0xd3,0x69,0x1d,0xba,0x00,0x28,0xf9,0x62,0xcf,0x26,0x0a,0x17,0x32,0x7e,0x80,0xd5,0x12,0xab,0x01,0xfd,0x66,0xd2,0xf6,0xe7,0x91,0x48,0x9c,0x1b,0x78,0x07,0x03,0x9b,0xa1,0x44,0x07,0x3b,0xe2,0x61,0x60,0x1d,0x8f,0x38,0x88,0x0e,0xd5,0x4b,0x35,0xa3,0xa6,0x3e,0x12,0x96,0x2d,0xe3,0x41,0x90,0x18,0x8d,0x11,0x48,0x58,0x31,0xd8,0xc2,0xe3,0xed,0xb9,0xd9,0x45,0x32,0xd8,0x71,0x42,0xab,0x1e,0x54,0xa1,0x18,0xc9,0xe2,0x61,0x39,0x4a}, - {0xa0,0xbb,0xe6,0xf8,0xe0,0x3b,0xdc,0x71,0x0a,0xe3,0xff,0x7e,0x34,0xf8,0xce,0xd6,0x6a,0x47,0x3a,0xe1,0x5f,0x42,0x92,0xa9,0x63,0xb7,0x1d,0xfb,0xe3,0xbc,0xd6,0x2c,0x1e,0x3f,0x23,0xf3,0x44,0xd6,0x27,0x03,0x16,0xf0,0xfc,0x34,0x0e,0x26,0x9a,0x49,0x79,0xb9,0xda,0xf2,0x16,0xa7,0xb5,0x83,0x1f,0x11,0xd4,0x9b,0xad,0xee,0xac,0x68,0x10,0xc2,0xd7,0xf3,0x0e,0xc9,0xb4,0x38,0x0c,0x04,0xad,0xb7,0x24,0x6e,0x8e,0x30,0x23,0x3e,0xe7,0xb7,0xf1,0xd9,0x60,0x38,0x97,0xf5,0x08,0xb5,0xd5,0x60,0x57,0x59}, - {0x97,0x63,0xaa,0x04,0xe1,0xbf,0x29,0x61,0xcb,0xfc,0xa7,0xa4,0x08,0x00,0x96,0x8f,0x58,0x94,0x90,0x7d,0x89,0xc0,0x8b,0x3f,0xa9,0x91,0xb2,0xdc,0x3e,0xa4,0x9f,0x70,0x90,0x27,0x02,0xfd,0xeb,0xcb,0x2a,0x88,0x60,0x57,0x11,0xc4,0x05,0x33,0xaf,0x89,0xf4,0x73,0x34,0x7d,0xe3,0x92,0xf4,0x65,0x2b,0x5a,0x51,0x54,0xdf,0xc5,0xb2,0x2c,0xca,0x2a,0xfd,0x63,0x8c,0x5d,0x0a,0xeb,0xff,0x4e,0x69,0x2e,0x66,0xc1,0x2b,0xd2,0x3a,0xb0,0xcb,0xf8,0x6e,0xf3,0x23,0x27,0x1f,0x13,0xc8,0xf0,0xec,0x29,0xf0,0x70}, - {0x33,0x3e,0xed,0x2e,0xb3,0x07,0x13,0x46,0xe7,0x81,0x55,0xa4,0x33,0x2f,0x04,0xae,0x66,0x03,0x5f,0x19,0xd3,0x49,0x44,0xc9,0x58,0x48,0x31,0x6c,0x8a,0x5d,0x7d,0x0b,0xb9,0xb0,0x10,0x5e,0xaa,0xaf,0x6a,0x2a,0xa9,0x1a,0x04,0xef,0x70,0xa3,0xf0,0x78,0x1f,0xd6,0x3a,0xaa,0x77,0xfb,0x3e,0x77,0xe1,0xd9,0x4b,0xa7,0xa2,0xa5,0xec,0x44,0x43,0xd5,0x95,0x7b,0x32,0x48,0xd4,0x25,0x1d,0x0f,0x34,0xa3,0x00,0x83,0xd3,0x70,0x2b,0xc5,0xe1,0x60,0x1c,0x53,0x1c,0xde,0xe4,0xe9,0x7d,0x2c,0x51,0x24,0x22,0x27}, - {0x2e,0x34,0xc5,0x49,0xaf,0x92,0xbc,0x1a,0xd0,0xfa,0xe6,0xb2,0x11,0xd8,0xee,0xff,0x29,0x4e,0xc8,0xfc,0x8d,0x8c,0xa2,0xef,0x43,0xc5,0x4c,0xa4,0x18,0xdf,0xb5,0x11,0xfc,0x75,0xa9,0x42,0x8a,0xbb,0x7b,0xbf,0x58,0xa3,0xad,0x96,0x77,0x39,0x5c,0x8c,0x48,0xaa,0xed,0xcd,0x6f,0xc7,0x7f,0xe2,0xa6,0x20,0xbc,0xf6,0xd7,0x5f,0x73,0x19,0x66,0x42,0xc8,0x42,0xd0,0x90,0xab,0xe3,0x7e,0x54,0x19,0x7f,0x0f,0x8e,0x84,0xeb,0xb9,0x97,0xa4,0x65,0xd0,0xa1,0x03,0x25,0x5f,0x89,0xdf,0x91,0x11,0x91,0xef,0x0f} -}; diff --git a/external/ed25519-donna/ed25519-donna-batchverify.h b/external/ed25519-donna/ed25519-donna-batchverify.h deleted file mode 100644 index 43c4923b3e..0000000000 --- a/external/ed25519-donna/ed25519-donna-batchverify.h +++ /dev/null @@ -1,275 +0,0 @@ -/* - Ed25519 batch verification -*/ - -#define max_batch_size 64 -#define heap_batch_size ((max_batch_size * 2) + 1) - -/* which limb is the 128th bit in? */ -static const size_t limb128bits = (128 + bignum256modm_bits_per_limb - 1) / bignum256modm_bits_per_limb; - -typedef size_t heap_index_t; - -typedef struct batch_heap_t { - unsigned char r[heap_batch_size][16]; /* 128 bit random values */ - ge25519 points[heap_batch_size]; - bignum256modm scalars[heap_batch_size]; - heap_index_t heap[heap_batch_size]; - size_t size; -} batch_heap; - -/* swap two values in the heap */ -static void -heap_swap(heap_index_t *heap, size_t a, size_t b) { - heap_index_t temp; - temp = heap[a]; - heap[a] = heap[b]; - heap[b] = temp; -} - -/* add the scalar at the end of the list to the heap */ -static void -heap_insert_next(batch_heap *heap) { - size_t node = heap->size, parent; - heap_index_t *pheap = heap->heap; - bignum256modm *scalars = heap->scalars; - - /* insert at the bottom */ - pheap[node] = (heap_index_t)node; - - /* sift node up to its sorted spot */ - parent = (node - 1) / 2; - while (node && lt256_modm_batch(scalars[pheap[parent]], scalars[pheap[node]], bignum256modm_limb_size - 1)) { - heap_swap(pheap, parent, node); - node = parent; - parent = (node - 1) / 2; - } - heap->size++; -} - -/* update the heap when the root element is updated */ -static void -heap_updated_root(batch_heap *heap, size_t limbsize) { - size_t node, parent, childr, childl; - heap_index_t *pheap = heap->heap; - bignum256modm *scalars = heap->scalars; - - /* sift root to the bottom */ - parent = 0; - node = 1; - childl = 1; - childr = 2; - while ((childr < heap->size)) { - node = lt256_modm_batch(scalars[pheap[childl]], scalars[pheap[childr]], limbsize) ? childr : childl; - heap_swap(pheap, parent, node); - parent = node; - childl = (parent * 2) + 1; - childr = childl + 1; - } - - /* sift root back up to its sorted spot */ - parent = (node - 1) / 2; - while (node && lte256_modm_batch(scalars[pheap[parent]], scalars[pheap[node]], limbsize)) { - heap_swap(pheap, parent, node); - node = parent; - parent = (node - 1) / 2; - } -} - -/* build the heap with count elements, count must be >= 3 */ -static void -heap_build(batch_heap *heap, size_t count) { - heap->heap[0] = 0; - heap->size = 0; - while (heap->size < count) - heap_insert_next(heap); -} - -/* extend the heap to contain new_count elements */ -static void -heap_extend(batch_heap *heap, size_t new_count) { - while (heap->size < new_count) - heap_insert_next(heap); -} - -/* get the top 2 elements of the heap */ -static void -heap_get_top2(batch_heap *heap, heap_index_t *max1, heap_index_t *max2, size_t limbsize) { - heap_index_t h0 = heap->heap[0], h1 = heap->heap[1], h2 = heap->heap[2]; - if (lt256_modm_batch(heap->scalars[h1], heap->scalars[h2], limbsize)) - h1 = h2; - *max1 = h0; - *max2 = h1; -} - -/* */ -static void -ge25519_multi_scalarmult_vartime_final(ge25519 *r, ge25519 *point, bignum256modm scalar) { - const bignum256modm_element_t topbit = ((bignum256modm_element_t)1 << (bignum256modm_bits_per_limb - 1)); - size_t limb = limb128bits; - bignum256modm_element_t flag; - - if (isone256_modm_batch(scalar)) { - /* this will happen most of the time after bos-carter */ - *r = *point; - return; - } else if (iszero256_modm_batch(scalar)) { - /* this will only happen if all scalars == 0 */ - memset(r, 0, sizeof(*r)); - r->y[0] = 1; - r->z[0] = 1; - return; - } - - *r = *point; - - /* find the limb where first bit is set */ - while (!scalar[limb]) - limb--; - - /* find the first bit */ - flag = topbit; - while ((scalar[limb] & flag) == 0) - flag >>= 1; - - /* exponentiate */ - for (;;) { - ge25519_double(r, r); - if (scalar[limb] & flag) - ge25519_add(r, r, point); - - flag >>= 1; - if (!flag) { - if (!limb--) - break; - flag = topbit; - } - } -} - -/* count must be >= 5 */ -static void -ge25519_multi_scalarmult_vartime(ge25519 *r, batch_heap *heap, size_t count) { - heap_index_t max1, max2; - - /* start with the full limb size */ - size_t limbsize = bignum256modm_limb_size - 1; - - /* whether the heap has been extended to include the 128 bit scalars */ - int extended = 0; - - /* grab an odd number of scalars to build the heap, unknown limb sizes */ - heap_build(heap, ((count + 1) / 2) | 1); - - for (;;) { - heap_get_top2(heap, &max1, &max2, limbsize); - - /* only one scalar remaining, we're done */ - if (iszero256_modm_batch(heap->scalars[max2])) - break; - - /* exhausted another limb? */ - if (!heap->scalars[max1][limbsize]) - limbsize -= 1; - - /* can we extend to the 128 bit scalars? */ - if (!extended && isatmost128bits256_modm_batch(heap->scalars[max1])) { - heap_extend(heap, count); - heap_get_top2(heap, &max1, &max2, limbsize); - extended = 1; - } - - sub256_modm_batch(heap->scalars[max1], heap->scalars[max1], heap->scalars[max2], limbsize); - ge25519_add(&heap->points[max2], &heap->points[max2], &heap->points[max1]); - heap_updated_root(heap, limbsize); - } - - ge25519_multi_scalarmult_vartime_final(r, &heap->points[max1], heap->scalars[max1]); -} - -/* not actually used for anything other than testing */ -unsigned char batch_point_buffer[3][32]; - -static int -ge25519_is_neutral_vartime(const ge25519 *p) { - static const unsigned char zero[32] = {0}; - unsigned char point_buffer[3][32]; - curve25519_contract(point_buffer[0], p->x); - curve25519_contract(point_buffer[1], p->y); - curve25519_contract(point_buffer[2], p->z); - memcpy(batch_point_buffer[1], point_buffer[1], 32); - return (memcmp(point_buffer[0], zero, 32) == 0) && (memcmp(point_buffer[1], point_buffer[2], 32) == 0); -} - -int -ED25519_FN(ed25519_sign_open_batch) (const unsigned char **m, size_t *mlen, const unsigned char **pk, const unsigned char **RS, size_t num, int *valid) { - batch_heap ALIGN(16) batch; - ge25519 ALIGN(16) p; - bignum256modm *r_scalars; - size_t i, batchsize; - unsigned char hram[64]; - int ret = 0; - - for (i = 0; i < num; i++) - valid[i] = 1; - - while (num > 3) { - batchsize = (num > max_batch_size) ? max_batch_size : num; - - /* generate r (scalars[batchsize+1]..scalars[2*batchsize] */ - ED25519_FN(ed25519_randombytes_unsafe) (batch.r, batchsize * 16); - r_scalars = &batch.scalars[batchsize + 1]; - for (i = 0; i < batchsize; i++) - expand256_modm(r_scalars[i], batch.r[i], 16); - - /* compute scalars[0] = ((r1s1 + r2s2 + ...)) */ - for (i = 0; i < batchsize; i++) { - expand256_modm(batch.scalars[i], RS[i] + 32, 32); - mul256_modm(batch.scalars[i], batch.scalars[i], r_scalars[i]); - } - for (i = 1; i < batchsize; i++) - add256_modm(batch.scalars[0], batch.scalars[0], batch.scalars[i]); - - /* compute scalars[1]..scalars[batchsize] as r[i]*H(R[i],A[i],m[i]) */ - for (i = 0; i < batchsize; i++) { - ed25519_hram(hram, RS[i], pk[i], m[i], mlen[i]); - expand256_modm(batch.scalars[i+1], hram, 64); - mul256_modm(batch.scalars[i+1], batch.scalars[i+1], r_scalars[i]); - } - - /* compute points */ - batch.points[0] = ge25519_basepoint; - for (i = 0; i < batchsize; i++) - if (!ge25519_unpack_negative_vartime(&batch.points[i+1], pk[i])) - goto fallback; - for (i = 0; i < batchsize; i++) - if (!ge25519_unpack_negative_vartime(&batch.points[batchsize+i+1], RS[i])) - goto fallback; - - ge25519_multi_scalarmult_vartime(&p, &batch, (batchsize * 2) + 1); - if (!ge25519_is_neutral_vartime(&p)) { - ret |= 2; - - fallback: - for (i = 0; i < batchsize; i++) { - valid[i] = ED25519_FN(ed25519_sign_open) (m[i], mlen[i], pk[i], RS[i]) ? 0 : 1; - ret |= (valid[i] ^ 1); - } - } - - m += batchsize; - mlen += batchsize; - pk += batchsize; - RS += batchsize; - num -= batchsize; - valid += batchsize; - } - - for (i = 0; i < num; i++) { - valid[i] = ED25519_FN(ed25519_sign_open) (m[i], mlen[i], pk[i], RS[i]) ? 0 : 1; - ret |= (valid[i] ^ 1); - } - - return ret; -} - diff --git a/external/ed25519-donna/ed25519-donna-impl-base.h b/external/ed25519-donna/ed25519-donna-impl-base.h deleted file mode 100644 index 48913edcb4..0000000000 --- a/external/ed25519-donna/ed25519-donna-impl-base.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - conversions -*/ - -DONNA_INLINE static void -ge25519_p1p1_to_partial(ge25519 *r, const ge25519_p1p1 *p) { - curve25519_mul(r->x, p->x, p->t); - curve25519_mul(r->y, p->y, p->z); - curve25519_mul(r->z, p->z, p->t); -} - -DONNA_INLINE static void -ge25519_p1p1_to_full(ge25519 *r, const ge25519_p1p1 *p) { - curve25519_mul(r->x, p->x, p->t); - curve25519_mul(r->y, p->y, p->z); - curve25519_mul(r->z, p->z, p->t); - curve25519_mul(r->t, p->x, p->y); -} - -static void -ge25519_full_to_pniels(ge25519_pniels *p, const ge25519 *r) { - curve25519_sub(p->ysubx, r->y, r->x); - curve25519_add(p->xaddy, r->y, r->x); - curve25519_copy(p->z, r->z); - curve25519_mul(p->t2d, r->t, ge25519_ec2d); -} - -/* - adding & doubling -*/ - -static void -ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519 *q) { - bignum25519 a,b,c,d,t,u; - - curve25519_sub(a, p->y, p->x); - curve25519_add(b, p->y, p->x); - curve25519_sub(t, q->y, q->x); - curve25519_add(u, q->y, q->x); - curve25519_mul(a, a, t); - curve25519_mul(b, b, u); - curve25519_mul(c, p->t, q->t); - curve25519_mul(c, c, ge25519_ec2d); - curve25519_mul(d, p->z, q->z); - curve25519_add(d, d, d); - curve25519_sub(r->x, b, a); - curve25519_add(r->y, b, a); - curve25519_add_after_basic(r->z, d, c); - curve25519_sub_after_basic(r->t, d, c); -} - - -static void -ge25519_double_p1p1(ge25519_p1p1 *r, const ge25519 *p) { - bignum25519 a,b,c; - - curve25519_square(a, p->x); - curve25519_square(b, p->y); - curve25519_square(c, p->z); - curve25519_add_reduce(c, c, c); - curve25519_add(r->x, p->x, p->y); - curve25519_square(r->x, r->x); - curve25519_add(r->y, b, a); - curve25519_sub(r->z, b, a); - curve25519_sub_after_basic(r->x, r->x, r->y); - curve25519_sub_after_basic(r->t, c, r->z); -} - -static void -ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_niels *q, unsigned char signbit) { - const bignum25519 *qb = (const bignum25519 *)q; - bignum25519 *rb = (bignum25519 *)r; - bignum25519 a,b,c; - - curve25519_sub(a, p->y, p->x); - curve25519_add(b, p->y, p->x); - curve25519_mul(a, a, qb[signbit]); /* x for +, y for - */ - curve25519_mul(r->x, b, qb[signbit^1]); /* y for +, x for - */ - curve25519_add(r->y, r->x, a); - curve25519_sub(r->x, r->x, a); - curve25519_mul(c, p->t, q->t2d); - curve25519_add_reduce(r->t, p->z, p->z); - curve25519_copy(r->z, r->t); - curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */ - curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */ -} - -static void -ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, unsigned char signbit) { - const bignum25519 *qb = (const bignum25519 *)q; - bignum25519 *rb = (bignum25519 *)r; - bignum25519 a,b,c; - - curve25519_sub(a, p->y, p->x); - curve25519_add(b, p->y, p->x); - curve25519_mul(a, a, qb[signbit]); /* ysubx for +, xaddy for - */ - curve25519_mul(r->x, b, qb[signbit^1]); /* xaddy for +, ysubx for - */ - curve25519_add(r->y, r->x, a); - curve25519_sub(r->x, r->x, a); - curve25519_mul(c, p->t, q->t2d); - curve25519_mul(r->t, p->z, q->z); - curve25519_add_reduce(r->t, r->t, r->t); - curve25519_copy(r->z, r->t); - curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */ - curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */ -} - -static void -ge25519_double_partial(ge25519 *r, const ge25519 *p) { - ge25519_p1p1 t; - ge25519_double_p1p1(&t, p); - ge25519_p1p1_to_partial(r, &t); -} - -static void -ge25519_double(ge25519 *r, const ge25519 *p) { - ge25519_p1p1 t; - ge25519_double_p1p1(&t, p); - ge25519_p1p1_to_full(r, &t); -} - -static void -ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q) { - ge25519_p1p1 t; - ge25519_add_p1p1(&t, p, q); - ge25519_p1p1_to_full(r, &t); -} - -static void -ge25519_nielsadd2(ge25519 *r, const ge25519_niels *q) { - bignum25519 a,b,c,e,f,g,h; - - curve25519_sub(a, r->y, r->x); - curve25519_add(b, r->y, r->x); - curve25519_mul(a, a, q->ysubx); - curve25519_mul(e, b, q->xaddy); - curve25519_add(h, e, a); - curve25519_sub(e, e, a); - curve25519_mul(c, r->t, q->t2d); - curve25519_add(f, r->z, r->z); - curve25519_add_after_basic(g, f, c); - curve25519_sub_after_basic(f, f, c); - curve25519_mul(r->x, e, f); - curve25519_mul(r->y, h, g); - curve25519_mul(r->z, g, f); - curve25519_mul(r->t, e, h); -} - -static void -ge25519_pnielsadd(ge25519_pniels *r, const ge25519 *p, const ge25519_pniels *q) { - bignum25519 a,b,c,x,y,z,t; - - curve25519_sub(a, p->y, p->x); - curve25519_add(b, p->y, p->x); - curve25519_mul(a, a, q->ysubx); - curve25519_mul(x, b, q->xaddy); - curve25519_add(y, x, a); - curve25519_sub(x, x, a); - curve25519_mul(c, p->t, q->t2d); - curve25519_mul(t, p->z, q->z); - curve25519_add(t, t, t); - curve25519_add_after_basic(z, t, c); - curve25519_sub_after_basic(t, t, c); - curve25519_mul(r->xaddy, x, t); - curve25519_mul(r->ysubx, y, z); - curve25519_mul(r->z, z, t); - curve25519_mul(r->t2d, x, y); - curve25519_copy(y, r->ysubx); - curve25519_sub(r->ysubx, r->ysubx, r->xaddy); - curve25519_add(r->xaddy, r->xaddy, y); - curve25519_mul(r->t2d, r->t2d, ge25519_ec2d); -} - - -/* - pack & unpack -*/ - -static void -ge25519_pack(unsigned char r[32], const ge25519 *p) { - bignum25519 tx, ty, zi; - unsigned char parity[32]; - curve25519_recip(zi, p->z); - curve25519_mul(tx, p->x, zi); - curve25519_mul(ty, p->y, zi); - curve25519_contract(r, ty); - curve25519_contract(parity, tx); - r[31] ^= ((parity[0] & 1) << 7); -} - -static int -ge25519_unpack_negative_vartime(ge25519 *r, const unsigned char p[32]) { - static const unsigned char zero[32] = {0}; - static const bignum25519 one = {1}; - unsigned char parity = p[31] >> 7; - unsigned char check[32]; - bignum25519 t, root, num, den, d3; - - curve25519_expand(r->y, p); - curve25519_copy(r->z, one); - curve25519_square(num, r->y); /* x = y^2 */ - curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */ - curve25519_sub_reduce(num, num, r->z); /* x = y^1 - 1 */ - curve25519_add(den, den, r->z); /* den = dy^2 + 1 */ - - /* Computation of sqrt(num/den) */ - /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ - curve25519_square(t, den); - curve25519_mul(d3, t, den); - curve25519_square(r->x, d3); - curve25519_mul(r->x, r->x, den); - curve25519_mul(r->x, r->x, num); - curve25519_pow_two252m3(r->x, r->x); - - /* 2. computation of r->x = num * den^3 * (num*den^7)^((p-5)/8) */ - curve25519_mul(r->x, r->x, d3); - curve25519_mul(r->x, r->x, num); - - /* 3. Check if either of the roots works: */ - curve25519_square(t, r->x); - curve25519_mul(t, t, den); - curve25519_sub_reduce(root, t, num); - curve25519_contract(check, root); - if (!ed25519_verify(check, zero, 32)) { - curve25519_add_reduce(t, t, num); - curve25519_contract(check, t); - if (!ed25519_verify(check, zero, 32)) - return 0; - curve25519_mul(r->x, r->x, ge25519_sqrtneg1); - } - - curve25519_contract(check, r->x); - if ((check[0] & 1) == parity) { - curve25519_copy(t, r->x); - curve25519_neg(r->x, t); - } - curve25519_mul(r->t, r->x, r->y); - return 1; -} - - -/* - scalarmults -*/ - -#define S1_SWINDOWSIZE 5 -#define S1_TABLE_SIZE (1<<(S1_SWINDOWSIZE-2)) -#define S2_SWINDOWSIZE 7 -#define S2_TABLE_SIZE (1<<(S2_SWINDOWSIZE-2)) - -/* computes [s1]p1 + [s2]basepoint */ -static void -ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const bignum256modm s2) { - signed char slide1[256], slide2[256]; - ge25519_pniels pre1[S1_TABLE_SIZE]; - ge25519 d1; - ge25519_p1p1 t; - int32_t i; - - contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE); - contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE); - - ge25519_double(&d1, p1); - ge25519_full_to_pniels(pre1, p1); - for (i = 0; i < S1_TABLE_SIZE - 1; i++) - ge25519_pnielsadd(&pre1[i+1], &d1, &pre1[i]); - - /* set neutral */ - memset(r, 0, sizeof(ge25519)); - r->y[0] = 1; - r->z[0] = 1; - - i = 255; - while ((i >= 0) && !(slide1[i] | slide2[i])) - i--; - - for (; i >= 0; i--) { - ge25519_double_p1p1(&t, r); - - if (slide1[i]) { - ge25519_p1p1_to_full(r, &t); - ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7); - } - - if (slide2[i]) { - ge25519_p1p1_to_full(r, &t); - ge25519_nielsadd2_p1p1(&t, r, &ge25519_niels_sliding_multiples[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7); - } - - ge25519_p1p1_to_partial(r, &t); - } -} - - - -#if !defined(HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS) - -static uint32_t -ge25519_windowb_equal(uint32_t b, uint32_t c) { - return ((b ^ c) - 1) >> 31; -} - -static void -ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) { - bignum25519 neg; - uint32_t sign = (uint32_t)((unsigned char)b >> 7); - uint32_t mask = ~(sign - 1); - uint32_t u = (b + mask) ^ mask; - uint32_t i; - - /* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */ - uint8_t packed[96] = {0}; - packed[0] = 1; - packed[32] = 1; - - for (i = 0; i < 8; i++) - curve25519_move_conditional_bytes(packed, table[(pos * 8) + i], ge25519_windowb_equal(u, i + 1)); - - /* expand in to t */ - curve25519_expand(t->ysubx, packed + 0); - curve25519_expand(t->xaddy, packed + 32); - curve25519_expand(t->t2d , packed + 64); - - /* adjust for sign */ - curve25519_swap_conditional(t->ysubx, t->xaddy, sign); - curve25519_neg(neg, t->t2d); - curve25519_swap_conditional(t->t2d, neg, sign); -} - -#endif /* HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS */ - - -/* computes [s]basepoint */ -static void -ge25519_scalarmult_base_niels(ge25519 *r, const uint8_t basepoint_table[256][96], const bignum256modm s) { - signed char b[64]; - uint32_t i; - ge25519_niels t; - - contract256_window4_modm(b, s); - - ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[1]); - curve25519_sub_reduce(r->x, t.xaddy, t.ysubx); - curve25519_add_reduce(r->y, t.xaddy, t.ysubx); - memset(r->z, 0, sizeof(bignum25519)); - curve25519_copy(r->t, t.t2d); - r->z[0] = 2; - for (i = 3; i < 64; i += 2) { - ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]); - ge25519_nielsadd2(r, &t); - } - ge25519_double_partial(r, r); - ge25519_double_partial(r, r); - ge25519_double_partial(r, r); - ge25519_double(r, r); - ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[0]); - curve25519_mul(t.t2d, t.t2d, ge25519_ecd); - ge25519_nielsadd2(r, &t); - for(i = 2; i < 64; i += 2) { - ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]); - ge25519_nielsadd2(r, &t); - } -} - diff --git a/external/ed25519-donna/ed25519-donna-impl-sse2.h b/external/ed25519-donna/ed25519-donna-impl-sse2.h deleted file mode 100644 index 5fe3416381..0000000000 --- a/external/ed25519-donna/ed25519-donna-impl-sse2.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - conversions -*/ - -static void -ge25519_p1p1_to_partial(ge25519 *r, const ge25519_p1p1 *p) { - packed64bignum25519 ALIGN(16) xz, tt, xzout; - curve25519_mul(r->y, p->y, p->z); - curve25519_tangle64(xz, p->x, p->z); - curve25519_tangleone64(tt, p->t); - curve25519_mul_packed64(xzout, xz, tt); - curve25519_untangle64(r->x, r->z, xzout); -} - -static void -ge25519_p1p1_to_full(ge25519 *r, const ge25519_p1p1 *p) { - packed64bignum25519 ALIGN(16) zy, xt, xx, zz, ty; - curve25519_tangle64(ty, p->t, p->y); - curve25519_tangleone64(xx, p->x); - curve25519_mul_packed64(xt, xx, ty); - curve25519_untangle64(r->x, r->t, xt); - curve25519_tangleone64(zz, p->z); - curve25519_mul_packed64(zy, zz, ty); - curve25519_untangle64(r->z, r->y, zy); -} - -static void -ge25519_full_to_pniels(ge25519_pniels *p, const ge25519 *r) { - curve25519_sub(p->ysubx, r->y, r->x); - curve25519_add(p->xaddy, r->x, r->y); - curve25519_copy(p->z, r->z); - curve25519_mul(p->t2d, r->t, ge25519_ec2d); -} - -/* - adding & doubling -*/ - -static void -ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519 *q) { - bignum25519 ALIGN(16) a,b,c,d; - packed32bignum25519 ALIGN(16) xx, yy, yypxx, yymxx, bd, ac, bdmac, bdpac; - packed64bignum25519 ALIGN(16) at, bu, atbu, ptz, qtz, cd; - - curve25519_tangle32(yy, p->y, q->y); - curve25519_tangle32(xx, p->x, q->x); - curve25519_add_packed32(yypxx, yy, xx); - curve25519_sub_packed32(yymxx, yy, xx); - curve25519_tangle64_from32(at, bu, yymxx, yypxx); - curve25519_mul_packed64(atbu, at, bu); - curve25519_untangle64(a, b, atbu); - curve25519_tangle64(ptz, p->t, p->z); - curve25519_tangle64(qtz, q->t, q->z); - curve25519_mul_packed64(cd, ptz, qtz); - curve25519_untangle64(c, d, cd); - curve25519_mul(c, c, ge25519_ec2d); - curve25519_add_reduce(d, d, d); - /* reduce, so no after_basic is needed later */ - curve25519_tangle32(bd, b, d); - curve25519_tangle32(ac, a, c); - curve25519_sub_packed32(bdmac, bd, ac); - curve25519_add_packed32(bdpac, bd, ac); - curve25519_untangle32(r->x, r->t, bdmac); - curve25519_untangle32(r->y, r->z, bdpac); -} - - -static void -ge25519_double_p1p1(ge25519_p1p1 *r, const ge25519 *p) { - bignum25519 ALIGN(16) a,b,c,x; - packed64bignum25519 ALIGN(16) xy, zx, ab, cx; - packed32bignum25519 ALIGN(16) xc, yz, xt, yc, ac, bc; - - curve25519_add(x, p->x, p->y); - curve25519_tangle64(xy, p->x, p->y); - curve25519_square_packed64(ab, xy); - curve25519_untangle64(a, b, ab); - curve25519_tangle64(zx, p->z, x); - curve25519_square_packed64(cx, zx); - curve25519_untangle64(c, x, cx); - curve25519_tangle32(bc, b, c); - curve25519_tangle32(ac, a, c); - curve25519_add_reduce_packed32(yc, bc, ac); - curve25519_untangle32(r->y, c, yc); - curve25519_sub(r->z, b, a); - curve25519_tangle32(yz, r->y, r->z); - curve25519_tangle32(xc, x, c); - curve25519_sub_after_basic_packed32(xt, xc, yz); - curve25519_untangle32(r->x, r->t, xt); -} - -static void -ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_niels *q, unsigned char signbit) { - const bignum25519 *qb = (const bignum25519 *)q; - bignum25519 *rb = (bignum25519 *)r; - bignum25519 ALIGN(16) a,b,c; - packed64bignum25519 ALIGN(16) ab, yx, aybx; - packed32bignum25519 ALIGN(16) bd, ac, bdac; - - curve25519_sub(a, p->y, p->x); - curve25519_add(b, p->y, p->x); - curve25519_tangle64(ab, a, b); - curve25519_tangle64(yx, qb[signbit], qb[signbit^1]); - curve25519_mul_packed64(aybx, ab, yx); - curve25519_untangle64(a, b, aybx); - curve25519_add(r->y, b, a); - curve25519_add_reduce(r->t, p->z, p->z); - curve25519_mul(c, p->t, q->t2d); - curve25519_copy(r->z, r->t); - curve25519_add(rb[2+signbit], rb[2+signbit], c); - curve25519_tangle32(bd, b, rb[2+(signbit^1)]); - curve25519_tangle32(ac, a, c); - curve25519_sub_packed32(bdac, bd, ac); - curve25519_untangle32(r->x, rb[2+(signbit^1)], bdac); -} - -static void -ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, unsigned char signbit) { - const bignum25519 *qb = (const bignum25519 *)q; - bignum25519 *rb = (bignum25519 *)r; - bignum25519 ALIGN(16) a,b,c; - packed64bignum25519 ALIGN(16) ab, yx, aybx, zt, zt2d, tc; - packed32bignum25519 ALIGN(16) bd, ac, bdac; - - curve25519_sub(a, p->y, p->x); - curve25519_add(b, p->y, p->x); - curve25519_tangle64(ab, a, b); - curve25519_tangle64(yx, qb[signbit], qb[signbit^1]); - curve25519_mul_packed64(aybx, ab, yx); - curve25519_untangle64(a, b, aybx); - curve25519_add(r->y, b, a); - curve25519_tangle64(zt, p->z, p->t); - curve25519_tangle64(zt2d, q->z, q->t2d); - curve25519_mul_packed64(tc, zt, zt2d); - curve25519_untangle64(r->t, c, tc); - curve25519_add_reduce(r->t, r->t, r->t); - curve25519_copy(r->z, r->t); - curve25519_add(rb[2+signbit], rb[2+signbit], c); - curve25519_tangle32(bd, b, rb[2+(signbit^1)]); - curve25519_tangle32(ac, a, c); - curve25519_sub_packed32(bdac, bd, ac); - curve25519_untangle32(r->x, rb[2+(signbit^1)], bdac); -} - -static void -ge25519_double(ge25519 *r, const ge25519 *p) { - ge25519_p1p1 ALIGN(16) t; - ge25519_double_p1p1(&t, p); - ge25519_p1p1_to_full(r, &t); -} - -static void -ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q) { - ge25519_p1p1 ALIGN(16) t; - ge25519_add_p1p1(&t, p, q); - ge25519_p1p1_to_full(r, &t); -} - -static void -ge25519_double_partial(ge25519 *r, const ge25519 *p) { - ge25519_p1p1 ALIGN(16) t; - ge25519_double_p1p1(&t, p); - ge25519_p1p1_to_partial(r, &t); -} - -static void -ge25519_nielsadd2(ge25519 *r, const ge25519_niels *q) { - packed64bignum25519 ALIGN(16) ab, yx, aybx, eg, ff, hh, xz, ty; - packed32bignum25519 ALIGN(16) bd, ac, bdac; - bignum25519 ALIGN(16) a,b,c,d,e,f,g,h; - - curve25519_sub(a, r->y, r->x); - curve25519_add(b, r->y, r->x); - curve25519_tangle64(ab, a, b); - curve25519_tangle64(yx, q->ysubx, q->xaddy); - curve25519_mul_packed64(aybx, ab, yx); - curve25519_untangle64(a, b, aybx); - curve25519_add(h, b, a); - curve25519_add_reduce(d, r->z, r->z); - curve25519_mul(c, r->t, q->t2d); - curve25519_add(g, d, c); /* d is reduced, so no need for after_basic */ - curve25519_tangle32(bd, b, d); - curve25519_tangle32(ac, a, c); - curve25519_sub_packed32(bdac, bd, ac); /* d is reduced, so no need for after_basic */ - curve25519_untangle32(e, f, bdac); - curve25519_tangle64(eg, e, g); - curve25519_tangleone64(ff, f); - curve25519_mul_packed64(xz, eg, ff); - curve25519_untangle64(r->x, r->z, xz); - curve25519_tangleone64(hh, h); - curve25519_mul_packed64(ty, eg, hh); - curve25519_untangle64(r->t, r->y, ty); -} - -static void -ge25519_pnielsadd(ge25519_pniels *r, const ge25519 *p, const ge25519_pniels *q) { - ge25519_p1p1 ALIGN(16) t; - ge25519 ALIGN(16) f; - ge25519_pnielsadd_p1p1(&t, p, q, 0); - ge25519_p1p1_to_full(&f, &t); - ge25519_full_to_pniels(r, &f); -} - -/* - pack & unpack -*/ - -static void -ge25519_pack(unsigned char r[32], const ge25519 *p) { - bignum25519 ALIGN(16) tx, ty, zi; - unsigned char parity[32]; - curve25519_recip(zi, p->z); - curve25519_mul(tx, p->x, zi); - curve25519_mul(ty, p->y, zi); - curve25519_contract(r, ty); - curve25519_contract(parity, tx); - r[31] ^= ((parity[0] & 1) << 7); -} - - -static int -ge25519_unpack_negative_vartime(ge25519 *r, const unsigned char p[32]) { - static const bignum25519 ALIGN(16) one = {1}; - static const unsigned char zero[32] = {0}; - unsigned char parity = p[31] >> 7; - unsigned char check[32]; - bignum25519 ALIGN(16) t, root, num, den, d3; - - curve25519_expand(r->y, p); - curve25519_copy(r->z, one); - curve25519_square_times(num, r->y, 1); /* x = y^2 */ - curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */ - curve25519_sub_reduce(num, num, r->z); /* x = y^2 - 1 */ - curve25519_add(den, den, r->z); /* den = dy^2 + 1 */ - - /* Computation of sqrt(num/den) */ - /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ - curve25519_square_times(t, den, 1); - curve25519_mul(d3, t, den); - curve25519_square_times(r->x, d3, 1); - curve25519_mul(r->x, r->x, den); - curve25519_mul(r->x, r->x, num); - curve25519_pow_two252m3(r->x, r->x); - - /* 2. computation of r->x = t * num * den^3 */ - curve25519_mul(r->x, r->x, d3); - curve25519_mul(r->x, r->x, num); - - /* 3. Check if either of the roots works: */ - curve25519_square_times(t, r->x, 1); - curve25519_mul(t, t, den); - curve25519_copy(root, t); - curve25519_sub_reduce(root, root, num); - curve25519_contract(check, root); - if (!ed25519_verify(check, zero, 32)) { - curve25519_add_reduce(t, t, num); - curve25519_contract(check, t); - if (!ed25519_verify(check, zero, 32)) - return 0; - curve25519_mul(r->x, r->x, ge25519_sqrtneg1); - } - - curve25519_contract(check, r->x); - if ((check[0] & 1) == parity) { - curve25519_copy(t, r->x); - curve25519_neg(r->x, t); - } - curve25519_mul(r->t, r->x, r->y); - return 1; -} - - - -/* - scalarmults -*/ - -#define S1_SWINDOWSIZE 5 -#define S1_TABLE_SIZE (1<<(S1_SWINDOWSIZE-2)) -#define S2_SWINDOWSIZE 7 -#define S2_TABLE_SIZE (1<<(S2_SWINDOWSIZE-2)) - -static void -ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const bignum256modm s2) { - signed char slide1[256], slide2[256]; - ge25519_pniels ALIGN(16) pre1[S1_TABLE_SIZE]; - ge25519 ALIGN(16) d1; - ge25519_p1p1 ALIGN(16) t; - int32_t i; - - contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE); - contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE); - - ge25519_double(&d1, p1); - ge25519_full_to_pniels(pre1, p1); - for (i = 0; i < S1_TABLE_SIZE - 1; i++) - ge25519_pnielsadd(&pre1[i+1], &d1, &pre1[i]); - - /* set neutral */ - memset(r, 0, sizeof(ge25519)); - r->y[0] = 1; - r->z[0] = 1; - - i = 255; - while ((i >= 0) && !(slide1[i] | slide2[i])) - i--; - - for (; i >= 0; i--) { - ge25519_double_p1p1(&t, r); - - if (slide1[i]) { - ge25519_p1p1_to_full(r, &t); - ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7); - } - - if (slide2[i]) { - ge25519_p1p1_to_full(r, &t); - ge25519_nielsadd2_p1p1(&t, r, &ge25519_niels_sliding_multiples[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7); - } - - ge25519_p1p1_to_partial(r, &t); - } -} - -#if !defined(HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS) - -static uint32_t -ge25519_windowb_equal(uint32_t b, uint32_t c) { - return ((b ^ c) - 1) >> 31; -} - -static void -ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) { - bignum25519 ALIGN(16) neg; - uint32_t sign = (uint32_t)((unsigned char)b >> 7); - uint32_t mask = ~(sign - 1); - uint32_t u = (b + mask) ^ mask; - uint32_t i; - - /* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */ - uint8_t ALIGN(16) packed[96] = {0}; - packed[0] = 1; - packed[32] = 1; - - for (i = 0; i < 8; i++) - curve25519_move_conditional_bytes(packed, table[(pos * 8) + i], ge25519_windowb_equal(u, i + 1)); - - /* expand in to t */ - curve25519_expand(t->ysubx, packed + 0); - curve25519_expand(t->xaddy, packed + 32); - curve25519_expand(t->t2d , packed + 64); - - /* adjust for sign */ - curve25519_swap_conditional(t->ysubx, t->xaddy, sign); - curve25519_neg(neg, t->t2d); - curve25519_swap_conditional(t->t2d, neg, sign); -} - -#endif /* HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS */ - -static void -ge25519_scalarmult_base_niels(ge25519 *r, const uint8_t table[256][96], const bignum256modm s) { - signed char b[64]; - uint32_t i; - ge25519_niels ALIGN(16) t; - - contract256_window4_modm(b, s); - - ge25519_scalarmult_base_choose_niels(&t, table, 0, b[1]); - curve25519_sub_reduce(r->x, t.xaddy, t.ysubx); - curve25519_add_reduce(r->y, t.xaddy, t.ysubx); - memset(r->z, 0, sizeof(bignum25519)); - r->z[0] = 2; - curve25519_copy(r->t, t.t2d); - for (i = 3; i < 64; i += 2) { - ge25519_scalarmult_base_choose_niels(&t, table, i / 2, b[i]); - ge25519_nielsadd2(r, &t); - } - ge25519_double_partial(r, r); - ge25519_double_partial(r, r); - ge25519_double_partial(r, r); - ge25519_double(r, r); - ge25519_scalarmult_base_choose_niels(&t, table, 0, b[0]); - curve25519_mul(t.t2d, t.t2d, ge25519_ecd); - ge25519_nielsadd2(r, &t); - for(i = 2; i < 64; i += 2) { - ge25519_scalarmult_base_choose_niels(&t, table, i / 2, b[i]); - ge25519_nielsadd2(r, &t); - } -} diff --git a/external/ed25519-donna/ed25519-donna-portable-identify.h b/external/ed25519-donna/ed25519-donna-portable-identify.h deleted file mode 100644 index 26a264cf9e..0000000000 --- a/external/ed25519-donna/ed25519-donna-portable-identify.h +++ /dev/null @@ -1,103 +0,0 @@ -/* os */ -#if defined(_WIN32) || defined(_WIN64) || defined(__TOS_WIN__) || defined(__WINDOWS__) - #define OS_WINDOWS -#elif defined(sun) || defined(__sun) || defined(__SVR4) || defined(__svr4__) - #define OS_SOLARIS -#else - #include /* need this to define BSD */ - #define OS_NIX - #if defined(__linux__) - #define OS_LINUX - #elif defined(BSD) - #define OS_BSD - #if defined(MACOS_X) || (defined(__APPLE__) & defined(__MACH__)) - #define OS_OSX - #elif defined(macintosh) || defined(Macintosh) - #define OS_MAC - #elif defined(__OpenBSD__) - #define OS_OPENBSD - #endif - #endif -#endif - - -/* compiler */ -#if defined(_MSC_VER) - #define COMPILER_MSVC -#endif -#if defined(__ICC) - #define COMPILER_INTEL -#endif -#if defined(__GNUC__) - #if (__GNUC__ >= 3) - #define COMPILER_GCC ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + (__GNUC_PATCHLEVEL__)) - #else - #define COMPILER_GCC ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) ) - #endif -#endif -#if defined(__PATHCC__) - #define COMPILER_PATHCC -#endif -#if defined(__clang__) - #define COMPILER_CLANG ((__clang_major__ * 10000) + (__clang_minor__ * 100) + (__clang_patchlevel__)) -#endif - - - -/* cpu */ -#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__ ) || defined(_M_X64) - #define CPU_X86_64 -#elif defined(__i586__) || defined(__i686__) || (defined(_M_IX86) && (_M_IX86 >= 500)) - #define CPU_X86 500 -#elif defined(__i486__) || (defined(_M_IX86) && (_M_IX86 >= 400)) - #define CPU_X86 400 -#elif defined(__i386__) || (defined(_M_IX86) && (_M_IX86 >= 300)) || defined(__X86__) || defined(_X86_) || defined(__I86__) - #define CPU_X86 300 -#elif defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(_M_IA64) || defined(__ia64) - #define CPU_IA64 -#endif - -#if defined(__sparc__) || defined(__sparc) || defined(__sparcv9) - #define CPU_SPARC - #if defined(__sparcv9) - #define CPU_SPARC64 - #endif -#endif - -#if defined(powerpc) || defined(__PPC__) || defined(__ppc__) || defined(_ARCH_PPC) || defined(__powerpc__) || defined(__powerpc) || defined(POWERPC) || defined(_M_PPC) - #define CPU_PPC - #if defined(_ARCH_PWR7) - #define CPU_POWER7 - #elif defined(__64BIT__) - #define CPU_PPC64 - #else - #define CPU_PPC32 - #endif -#endif - -#if defined(__hppa__) || defined(__hppa) - #define CPU_HPPA -#endif - -#if defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) - #define CPU_ALPHA -#endif - -/* 64 bit cpu */ -#if defined(CPU_X86_64) || defined(CPU_IA64) || defined(CPU_SPARC64) || defined(__64BIT__) || defined(__LP64__) || defined(_LP64) || (defined(_MIPS_SZLONG) && (_MIPS_SZLONG == 64)) - #define CPU_64BITS -#endif - -#if defined(COMPILER_MSVC) - typedef signed char int8_t; - typedef unsigned char uint8_t; - typedef signed short int16_t; - typedef unsigned short uint16_t; - typedef signed int int32_t; - typedef unsigned int uint32_t; - typedef signed __int64 int64_t; - typedef unsigned __int64 uint64_t; -#else - #include -#endif - diff --git a/external/ed25519-donna/ed25519-donna-portable.h b/external/ed25519-donna/ed25519-donna-portable.h deleted file mode 100644 index aad1441a99..0000000000 --- a/external/ed25519-donna/ed25519-donna-portable.h +++ /dev/null @@ -1,136 +0,0 @@ -#include "ed25519-donna-portable-identify.h" - -#define mul32x32_64(a,b) (((uint64_t)(a))*(b)) - -/* platform */ -#if defined(COMPILER_MSVC) - #include - #if !defined(_DEBUG) - #undef mul32x32_64 - #define mul32x32_64(a,b) __emulu(a,b) - #endif - #undef inline - #define inline __forceinline - #define DONNA_INLINE __forceinline - #define DONNA_NOINLINE __declspec(noinline) - #define ALIGN(x) __declspec(align(x)) - #define ROTL32(a,b) _rotl(a,b) - #define ROTR32(a,b) _rotr(a,b) -#else - #include - #define DONNA_INLINE inline __attribute__((always_inline)) - #define DONNA_NOINLINE __attribute__((noinline)) - #undef ALIGN - #define ALIGN(x) __attribute__((aligned(x))) - #define ROTL32(a,b) (((a) << (b)) | ((a) >> (32 - b))) - #define ROTR32(a,b) (((a) >> (b)) | ((a) << (32 - b))) -#endif - -/* uint128_t */ -#if defined(CPU_64BITS) && !defined(ED25519_FORCE_32BIT) - #if defined(COMPILER_CLANG) && (COMPILER_CLANG >= 30100) - #define HAVE_NATIVE_UINT128 - typedef unsigned __int128 uint128_t; - #elif defined(COMPILER_MSVC) - #define HAVE_UINT128 - typedef struct uint128_t { - uint64_t lo, hi; - } uint128_t; - #define mul64x64_128(out,a,b) out.lo = _umul128(a,b,&out.hi); - #define shr128_pair(out,hi,lo,shift) out = __shiftright128(lo, hi, shift); - #define shl128_pair(out,hi,lo,shift) out = __shiftleft128(lo, hi, shift); - #define shr128(out,in,shift) shr128_pair(out, in.hi, in.lo, shift) - #define shl128(out,in,shift) shl128_pair(out, in.hi, in.lo, shift) - #define add128(a,b) { uint64_t p = a.lo; a.lo += b.lo; a.hi += b.hi + (a.lo < p); } - #define add128_64(a,b) { uint64_t p = a.lo; a.lo += b; a.hi += (a.lo < p); } - #define lo128(a) (a.lo) - #define hi128(a) (a.hi) - #elif defined(COMPILER_GCC) && !defined(HAVE_NATIVE_UINT128) - #if defined(__SIZEOF_INT128__) - #define HAVE_NATIVE_UINT128 - typedef unsigned __int128 uint128_t; - #elif (COMPILER_GCC >= 40400) - #define HAVE_NATIVE_UINT128 - typedef unsigned uint128_t __attribute__((mode(TI))); - #elif defined(CPU_X86_64) - #define HAVE_UINT128 - typedef struct uint128_t { - uint64_t lo, hi; - } uint128_t; - #define mul64x64_128(out,a,b) __asm__ ("mulq %3" : "=a" (out.lo), "=d" (out.hi) : "a" (a), "rm" (b)); - #define shr128_pair(out,hi,lo,shift) __asm__ ("shrdq %2,%1,%0" : "+r" (lo) : "r" (hi), "J" (shift)); out = lo; - #define shl128_pair(out,hi,lo,shift) __asm__ ("shldq %2,%1,%0" : "+r" (hi) : "r" (lo), "J" (shift)); out = hi; - #define shr128(out,in,shift) shr128_pair(out,in.hi, in.lo, shift) - #define shl128(out,in,shift) shl128_pair(out,in.hi, in.lo, shift) - #define add128(a,b) __asm__ ("addq %4,%2; adcq %5,%3" : "=r" (a.hi), "=r" (a.lo) : "1" (a.lo), "0" (a.hi), "rm" (b.lo), "rm" (b.hi) : "cc"); - #define add128_64(a,b) __asm__ ("addq %4,%2; adcq $0,%3" : "=r" (a.hi), "=r" (a.lo) : "1" (a.lo), "0" (a.hi), "rm" (b) : "cc"); - #define lo128(a) (a.lo) - #define hi128(a) (a.hi) - #endif - #endif - - #if defined(HAVE_NATIVE_UINT128) - #define HAVE_UINT128 - #define mul64x64_128(out,a,b) out = (uint128_t)a * b; - #define shr128_pair(out,hi,lo,shift) out = (uint64_t)((((uint128_t)hi << 64) | lo) >> (shift)); - #define shl128_pair(out,hi,lo,shift) out = (uint64_t)(((((uint128_t)hi << 64) | lo) << (shift)) >> 64); - #define shr128(out,in,shift) out = (uint64_t)(in >> (shift)); - #define shl128(out,in,shift) out = (uint64_t)((in << shift) >> 64); - #define add128(a,b) a += b; - #define add128_64(a,b) a += (uint64_t)b; - #define lo128(a) ((uint64_t)a) - #define hi128(a) ((uint64_t)(a >> 64)) - #endif - - #if !defined(HAVE_UINT128) - #error Need a uint128_t implementation! - #endif -#endif - -/* endian */ -#if !defined(ED25519_OPENSSLRNG) -static inline void U32TO8_LE(unsigned char *p, const uint32_t v) { - p[0] = (unsigned char)(v ); - p[1] = (unsigned char)(v >> 8); - p[2] = (unsigned char)(v >> 16); - p[3] = (unsigned char)(v >> 24); -} -#endif - -#if !defined(HAVE_UINT128) -static inline uint32_t U8TO32_LE(const unsigned char *p) { - return - (((uint32_t)(p[0]) ) | - ((uint32_t)(p[1]) << 8) | - ((uint32_t)(p[2]) << 16) | - ((uint32_t)(p[3]) << 24)); -} -#else -static inline uint64_t U8TO64_LE(const unsigned char *p) { - return - (((uint64_t)(p[0]) ) | - ((uint64_t)(p[1]) << 8) | - ((uint64_t)(p[2]) << 16) | - ((uint64_t)(p[3]) << 24) | - ((uint64_t)(p[4]) << 32) | - ((uint64_t)(p[5]) << 40) | - ((uint64_t)(p[6]) << 48) | - ((uint64_t)(p[7]) << 56)); -} - -static inline void U64TO8_LE(unsigned char *p, const uint64_t v) { - p[0] = (unsigned char)(v ); - p[1] = (unsigned char)(v >> 8); - p[2] = (unsigned char)(v >> 16); - p[3] = (unsigned char)(v >> 24); - p[4] = (unsigned char)(v >> 32); - p[5] = (unsigned char)(v >> 40); - p[6] = (unsigned char)(v >> 48); - p[7] = (unsigned char)(v >> 56); -} -#endif - -#include -#include - - diff --git a/external/ed25519-donna/ed25519-donna.h b/external/ed25519-donna/ed25519-donna.h deleted file mode 100644 index de1120f46f..0000000000 --- a/external/ed25519-donna/ed25519-donna.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - Public domain by Andrew M. - Modified from the amd64-51-30k implementation by - Daniel J. Bernstein - Niels Duif - Tanja Lange - Peter Schwabe - Bo-Yin Yang -*/ - - -#include "ed25519-donna-portable.h" - -#if defined(ED25519_SSE2) -#else - #if defined(HAVE_UINT128) && !defined(ED25519_FORCE_32BIT) - #define ED25519_64BIT - #else - #define ED25519_32BIT - #endif -#endif - -#if !defined(ED25519_NO_INLINE_ASM) - /* detect extra features first so un-needed functions can be disabled throughout */ - #if defined(ED25519_SSE2) - #if defined(COMPILER_GCC) && defined(CPU_X86) - #define ED25519_GCC_32BIT_SSE_CHOOSE - #elif defined(COMPILER_GCC) && defined(CPU_X86_64) - #define ED25519_GCC_64BIT_SSE_CHOOSE - #endif - #else - #if defined(CPU_X86_64) - #if defined(COMPILER_GCC) - #if defined(ED25519_64BIT) - #define ED25519_GCC_64BIT_X86_CHOOSE - #else - #define ED25519_GCC_64BIT_32BIT_CHOOSE - #endif - #endif - #endif - #endif -#endif - -#if defined(ED25519_SSE2) - #include "curve25519-donna-sse2.h" -#elif defined(ED25519_64BIT) - #include "curve25519-donna-64bit.h" -#else - #include "curve25519-donna-32bit.h" -#endif - -#include "curve25519-donna-helpers.h" - -/* separate uint128 check for 64 bit sse2 */ -#if defined(HAVE_UINT128) && !defined(ED25519_FORCE_32BIT) - #include "modm-donna-64bit.h" -#else - #include "modm-donna-32bit.h" -#endif - -typedef unsigned char hash_512bits[64]; - -/* - Timing safe memory compare -*/ -static int -ed25519_verify(const unsigned char *x, const unsigned char *y, size_t len) { - size_t differentbits = 0; - while (len--) - differentbits |= (*x++ ^ *y++); - return (int) (1 & ((differentbits - 1) >> 8)); -} - - -/* - * Arithmetic on the twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2 - * with d = -(121665/121666) = 37095705934669439343138083508754565189542113879843219016388785533085940283555 - * Base point: (15112221349535400772501151409588531511454012693041857206046113283949847762202,46316835694926478169428394003475163141307993866256225615783033603165251855960); - */ - -typedef struct ge25519_t { - bignum25519 x, y, z, t; -} ge25519; - -typedef struct ge25519_p1p1_t { - bignum25519 x, y, z, t; -} ge25519_p1p1; - -typedef struct ge25519_niels_t { - bignum25519 ysubx, xaddy, t2d; -} ge25519_niels; - -typedef struct ge25519_pniels_t { - bignum25519 ysubx, xaddy, z, t2d; -} ge25519_pniels; - -#include "ed25519-donna-basepoint-table.h" - -#if defined(ED25519_64BIT) - #include "ed25519-donna-64bit-tables.h" - #include "ed25519-donna-64bit-x86.h" -#else - #include "ed25519-donna-32bit-tables.h" - #include "ed25519-donna-64bit-x86-32bit.h" -#endif - - -#if defined(ED25519_SSE2) - #include "ed25519-donna-32bit-sse2.h" - #include "ed25519-donna-64bit-sse2.h" - #include "ed25519-donna-impl-sse2.h" -#else - #include "ed25519-donna-impl-base.h" -#endif - diff --git a/external/ed25519-donna/ed25519-hash-custom.h b/external/ed25519-donna/ed25519-hash-custom.h deleted file mode 100644 index 7dc249129d..0000000000 --- a/external/ed25519-donna/ed25519-hash-custom.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - a custom hash must have a 512bit digest and implement: - - struct ed25519_hash_context; - - void ed25519_hash_init(ed25519_hash_context *ctx); - void ed25519_hash_update(ed25519_hash_context *ctx, const uint8_t *in, size_t inlen); - void ed25519_hash_final(ed25519_hash_context *ctx, uint8_t *hash); - void ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen); -*/ - diff --git a/external/ed25519-donna/ed25519-hash.h b/external/ed25519-donna/ed25519-hash.h deleted file mode 100644 index 6ba8f52383..0000000000 --- a/external/ed25519-donna/ed25519-hash.h +++ /dev/null @@ -1,219 +0,0 @@ -#if defined(ED25519_REFHASH) - -/* reference/slow SHA-512. really, do not use this */ - -#define HASH_BLOCK_SIZE 128 -#define HASH_DIGEST_SIZE 64 - -typedef struct sha512_state_t { - uint64_t H[8]; - uint64_t T[2]; - uint32_t leftover; - uint8_t buffer[HASH_BLOCK_SIZE]; -} sha512_state; - -typedef sha512_state ed25519_hash_context; - -static const uint64_t sha512_constants[80] = { - 0x428a2f98d728ae22ull, 0x7137449123ef65cdull, 0xb5c0fbcfec4d3b2full, 0xe9b5dba58189dbbcull, - 0x3956c25bf348b538ull, 0x59f111f1b605d019ull, 0x923f82a4af194f9bull, 0xab1c5ed5da6d8118ull, - 0xd807aa98a3030242ull, 0x12835b0145706fbeull, 0x243185be4ee4b28cull, 0x550c7dc3d5ffb4e2ull, - 0x72be5d74f27b896full, 0x80deb1fe3b1696b1ull, 0x9bdc06a725c71235ull, 0xc19bf174cf692694ull, - 0xe49b69c19ef14ad2ull, 0xefbe4786384f25e3ull, 0x0fc19dc68b8cd5b5ull, 0x240ca1cc77ac9c65ull, - 0x2de92c6f592b0275ull, 0x4a7484aa6ea6e483ull, 0x5cb0a9dcbd41fbd4ull, 0x76f988da831153b5ull, - 0x983e5152ee66dfabull, 0xa831c66d2db43210ull, 0xb00327c898fb213full, 0xbf597fc7beef0ee4ull, - 0xc6e00bf33da88fc2ull, 0xd5a79147930aa725ull, 0x06ca6351e003826full, 0x142929670a0e6e70ull, - 0x27b70a8546d22ffcull, 0x2e1b21385c26c926ull, 0x4d2c6dfc5ac42aedull, 0x53380d139d95b3dfull, - 0x650a73548baf63deull, 0x766a0abb3c77b2a8ull, 0x81c2c92e47edaee6ull, 0x92722c851482353bull, - 0xa2bfe8a14cf10364ull, 0xa81a664bbc423001ull, 0xc24b8b70d0f89791ull, 0xc76c51a30654be30ull, - 0xd192e819d6ef5218ull, 0xd69906245565a910ull, 0xf40e35855771202aull, 0x106aa07032bbd1b8ull, - 0x19a4c116b8d2d0c8ull, 0x1e376c085141ab53ull, 0x2748774cdf8eeb99ull, 0x34b0bcb5e19b48a8ull, - 0x391c0cb3c5c95a63ull, 0x4ed8aa4ae3418acbull, 0x5b9cca4f7763e373ull, 0x682e6ff3d6b2b8a3ull, - 0x748f82ee5defb2fcull, 0x78a5636f43172f60ull, 0x84c87814a1f0ab72ull, 0x8cc702081a6439ecull, - 0x90befffa23631e28ull, 0xa4506cebde82bde9ull, 0xbef9a3f7b2c67915ull, 0xc67178f2e372532bull, - 0xca273eceea26619cull, 0xd186b8c721c0c207ull, 0xeada7dd6cde0eb1eull, 0xf57d4f7fee6ed178ull, - 0x06f067aa72176fbaull, 0x0a637dc5a2c898a6ull, 0x113f9804bef90daeull, 0x1b710b35131c471bull, - 0x28db77f523047d84ull, 0x32caab7b40c72493ull, 0x3c9ebe0a15c9bebcull, 0x431d67c49c100d4cull, - 0x4cc5d4becb3e42b6ull, 0x597f299cfc657e2aull, 0x5fcb6fab3ad6faecull, 0x6c44198c4a475817ull -}; - -static uint64_t -sha512_ROTR64(uint64_t x, int k) { - return (x >> k) | (x << (64 - k)); -} - -static uint64_t -sha512_LOAD64_BE(const uint8_t *p) { - return - ((uint64_t)p[0] << 56) | - ((uint64_t)p[1] << 48) | - ((uint64_t)p[2] << 40) | - ((uint64_t)p[3] << 32) | - ((uint64_t)p[4] << 24) | - ((uint64_t)p[5] << 16) | - ((uint64_t)p[6] << 8) | - ((uint64_t)p[7] ); -} - -static void -sha512_STORE64_BE(uint8_t *p, uint64_t v) { - p[0] = (uint8_t)(v >> 56); - p[1] = (uint8_t)(v >> 48); - p[2] = (uint8_t)(v >> 40); - p[3] = (uint8_t)(v >> 32); - p[4] = (uint8_t)(v >> 24); - p[5] = (uint8_t)(v >> 16); - p[6] = (uint8_t)(v >> 8); - p[7] = (uint8_t)(v ); -} - -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S0(x) (sha512_ROTR64(x, 28) ^ sha512_ROTR64(x, 34) ^ sha512_ROTR64(x, 39)) -#define S1(x) (sha512_ROTR64(x, 14) ^ sha512_ROTR64(x, 18) ^ sha512_ROTR64(x, 41)) -#define G0(x) (sha512_ROTR64(x, 1) ^ sha512_ROTR64(x, 8) ^ (x >> 7)) -#define G1(x) (sha512_ROTR64(x, 19) ^ sha512_ROTR64(x, 61) ^ (x >> 6)) -#define W0(in,i) (sha512_LOAD64_BE(&in[i * 8])) -#define W1(i) (G1(w[i - 2]) + w[i - 7] + G0(w[i - 15]) + w[i - 16]) -#define STEP(i) \ - t1 = S0(r[0]) + Maj(r[0], r[1], r[2]); \ - t0 = r[7] + S1(r[4]) + Ch(r[4], r[5], r[6]) + sha512_constants[i] + w[i]; \ - r[7] = r[6]; \ - r[6] = r[5]; \ - r[5] = r[4]; \ - r[4] = r[3] + t0; \ - r[3] = r[2]; \ - r[2] = r[1]; \ - r[1] = r[0]; \ - r[0] = t0 + t1; - -static void -sha512_blocks(sha512_state *S, const uint8_t *in, size_t blocks) { - uint64_t r[8], w[80], t0, t1; - size_t i; - - for (i = 0; i < 8; i++) r[i] = S->H[i]; - - while (blocks--) { - for (i = 0; i < 16; i++) { w[i] = W0(in, i); } - for (i = 16; i < 80; i++) { w[i] = W1(i); } - for (i = 0; i < 80; i++) { STEP(i); } - for (i = 0; i < 8; i++) { r[i] += S->H[i]; S->H[i] = r[i]; } - S->T[0] += HASH_BLOCK_SIZE * 8; - S->T[1] += (!S->T[0]) ? 1 : 0; - in += HASH_BLOCK_SIZE; - } -} - -static void -ed25519_hash_init(sha512_state *S) { - S->H[0] = 0x6a09e667f3bcc908ull; - S->H[1] = 0xbb67ae8584caa73bull; - S->H[2] = 0x3c6ef372fe94f82bull; - S->H[3] = 0xa54ff53a5f1d36f1ull; - S->H[4] = 0x510e527fade682d1ull; - S->H[5] = 0x9b05688c2b3e6c1full; - S->H[6] = 0x1f83d9abfb41bd6bull; - S->H[7] = 0x5be0cd19137e2179ull; - S->T[0] = 0; - S->T[1] = 0; - S->leftover = 0; -} - -static void -ed25519_hash_update(sha512_state *S, const uint8_t *in, size_t inlen) { - size_t blocks, want; - - /* handle the previous data */ - if (S->leftover) { - want = (HASH_BLOCK_SIZE - S->leftover); - want = (want < inlen) ? want : inlen; - memcpy(S->buffer + S->leftover, in, want); - S->leftover += (uint32_t)want; - if (S->leftover < HASH_BLOCK_SIZE) - return; - in += want; - inlen -= want; - sha512_blocks(S, S->buffer, 1); - } - - /* handle the current data */ - blocks = (inlen & ~(HASH_BLOCK_SIZE - 1)); - S->leftover = (uint32_t)(inlen - blocks); - if (blocks) { - sha512_blocks(S, in, blocks / HASH_BLOCK_SIZE); - in += blocks; - } - - /* handle leftover data */ - if (S->leftover) - memcpy(S->buffer, in, S->leftover); -} - -static void -ed25519_hash_final(sha512_state *S, uint8_t *hash) { - uint64_t t0 = S->T[0] + (S->leftover * 8), t1 = S->T[1]; - - S->buffer[S->leftover] = 0x80; - if (S->leftover <= 111) { - memset(S->buffer + S->leftover + 1, 0, 111 - S->leftover); - } else { - memset(S->buffer + S->leftover + 1, 0, 127 - S->leftover); - sha512_blocks(S, S->buffer, 1); - memset(S->buffer, 0, 112); - } - - sha512_STORE64_BE(S->buffer + 112, t1); - sha512_STORE64_BE(S->buffer + 120, t0); - sha512_blocks(S, S->buffer, 1); - - sha512_STORE64_BE(&hash[ 0], S->H[0]); - sha512_STORE64_BE(&hash[ 8], S->H[1]); - sha512_STORE64_BE(&hash[16], S->H[2]); - sha512_STORE64_BE(&hash[24], S->H[3]); - sha512_STORE64_BE(&hash[32], S->H[4]); - sha512_STORE64_BE(&hash[40], S->H[5]); - sha512_STORE64_BE(&hash[48], S->H[6]); - sha512_STORE64_BE(&hash[56], S->H[7]); -} - -static void -ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen) { - ed25519_hash_context ctx; - ed25519_hash_init(&ctx); - ed25519_hash_update(&ctx, in, inlen); - ed25519_hash_final(&ctx, hash); -} - -#elif defined(ED25519_CUSTOMHASH) - -#include "ed25519-hash-custom.h" - -#else - -#include - -typedef SHA512_CTX ed25519_hash_context; - -static void -ed25519_hash_init(ed25519_hash_context *ctx) { - SHA512_Init(ctx); -} - -static void -ed25519_hash_update(ed25519_hash_context *ctx, const uint8_t *in, size_t inlen) { - SHA512_Update(ctx, in, inlen); -} - -static void -ed25519_hash_final(ed25519_hash_context *ctx, uint8_t *hash) { - SHA512_Final(hash, ctx); -} - -static void -ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen) { - SHA512(in, inlen, hash); -} - -#endif - diff --git a/external/ed25519-donna/ed25519-randombytes-custom.h b/external/ed25519-donna/ed25519-randombytes-custom.h deleted file mode 100644 index 9f5106340c..0000000000 --- a/external/ed25519-donna/ed25519-randombytes-custom.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - a custom randombytes must implement: - - void ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len); - - ed25519_randombytes_unsafe is used by the batch verification function - to create random scalars -*/ diff --git a/external/ed25519-donna/ed25519-randombytes.h b/external/ed25519-donna/ed25519-randombytes.h deleted file mode 100644 index 53d1c3fe1e..0000000000 --- a/external/ed25519-donna/ed25519-randombytes.h +++ /dev/null @@ -1,91 +0,0 @@ -#if defined(ED25519_TEST) -/* - ISAAC+ "variant", the paper is not clear on operator precedence and other - things. This is the "first in, first out" option! - - Not threadsafe or securely initialized, only for deterministic testing -*/ -typedef struct isaacp_state_t { - uint32_t state[256]; - unsigned char buffer[1024]; - uint32_t a, b, c; - size_t left; -} isaacp_state; - -#define isaacp_step(offset, mix) \ - x = mm[i + offset]; \ - a = (a ^ (mix)) + (mm[(i + offset + 128) & 0xff]); \ - y = (a ^ b) + mm[(x >> 2) & 0xff]; \ - mm[i + offset] = y; \ - b = (x + a) ^ mm[(y >> 10) & 0xff]; \ - U32TO8_LE(out + (i + offset) * 4, b); - -static void -isaacp_mix(isaacp_state *st) { - uint32_t i, x, y; - uint32_t a = st->a, b = st->b, c = st->c; - uint32_t *mm = st->state; - unsigned char *out = st->buffer; - - c = c + 1; - b = b + c; - - for (i = 0; i < 256; i += 4) { - isaacp_step(0, ROTL32(a,13)) - isaacp_step(1, ROTR32(a, 6)) - isaacp_step(2, ROTL32(a, 2)) - isaacp_step(3, ROTR32(a,16)) - } - - st->a = a; - st->b = b; - st->c = c; - st->left = 1024; -} - -static void -isaacp_random(isaacp_state *st, void *p, size_t len) { - size_t use; - unsigned char *c = (unsigned char *)p; - while (len) { - use = (len > st->left) ? st->left : len; - memcpy(c, st->buffer + (sizeof(st->buffer) - st->left), use); - - st->left -= use; - c += use; - len -= use; - - if (!st->left) - isaacp_mix(st); - } -} - -void -ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len) { - static int initialized = 0; - static isaacp_state rng; - - if (!initialized) { - memset(&rng, 0, sizeof(rng)); - isaacp_mix(&rng); - isaacp_mix(&rng); - initialized = 1; - } - - isaacp_random(&rng, p, len); -} -#elif defined(ED25519_CUSTOMRNG) - -#include "ed25519-randombytes-custom.h" - -#else - -#include - -void -ED25519_FN(ed25519_randombytes_unsafe) (void *p, size_t len) { - - RAND_bytes(p, (int) len); - -} -#endif diff --git a/external/ed25519-donna/ed25519.c b/external/ed25519-donna/ed25519.c deleted file mode 100644 index 58a755b8d3..0000000000 --- a/external/ed25519-donna/ed25519.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - Public domain by Andrew M. - - Ed25519 reference implementation using Ed25519-donna -*/ - - -/* define ED25519_SUFFIX to have it appended to the end of each public function */ -#if !defined(ED25519_SUFFIX) -#define ED25519_SUFFIX -#endif - -#define ED25519_FN3(fn,suffix) fn##suffix -#define ED25519_FN2(fn,suffix) ED25519_FN3(fn,suffix) -#define ED25519_FN(fn) ED25519_FN2(fn,ED25519_SUFFIX) - -#include "ed25519-donna.h" -#include "ed25519.h" -#include "ed25519-randombytes.h" -#include "ed25519-hash.h" - -/* - Generates a (extsk[0..31]) and aExt (extsk[32..63]) -*/ - -DONNA_INLINE static void -ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) { - ed25519_hash(extsk, sk, 32); - extsk[0] &= 248; - extsk[31] &= 127; - extsk[31] |= 64; -} - -static void -ed25519_hram(hash_512bits hram, const ed25519_signature RS, const ed25519_public_key pk, const unsigned char *m, size_t mlen) { - ed25519_hash_context ctx; - ed25519_hash_init(&ctx); - ed25519_hash_update(&ctx, RS, 32); - ed25519_hash_update(&ctx, pk, 32); - ed25519_hash_update(&ctx, m, mlen); - ed25519_hash_final(&ctx, hram); -} - -void -ED25519_FN(ed25519_publickey) (const ed25519_secret_key sk, ed25519_public_key pk) { - bignum256modm a; - ge25519 ALIGN(16) A; - hash_512bits extsk; - - /* A = aB */ - ed25519_extsk(extsk, sk); - expand256_modm(a, extsk, 32); - ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a); - ge25519_pack(pk, &A); -} - - -void -ED25519_FN(ed25519_sign) (const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS) { - ed25519_hash_context ctx; - bignum256modm r, S, a; - ge25519 ALIGN(16) R; - hash_512bits extsk, hashr, hram; - - ed25519_extsk(extsk, sk); - - /* r = H(aExt[32..64], m) */ - ed25519_hash_init(&ctx); - ed25519_hash_update(&ctx, extsk + 32, 32); - ed25519_hash_update(&ctx, m, mlen); - ed25519_hash_final(&ctx, hashr); - expand256_modm(r, hashr, 64); - - /* R = rB */ - ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r); - ge25519_pack(RS, &R); - - /* S = H(R,A,m).. */ - ed25519_hram(hram, RS, pk, m, mlen); - expand256_modm(S, hram, 64); - - /* S = H(R,A,m)a */ - expand256_modm(a, extsk, 32); - mul256_modm(S, S, a); - - /* S = (r + H(R,A,m)a) */ - add256_modm(S, S, r); - - /* S = (r + H(R,A,m)a) mod L */ - contract256_modm(RS + 32, S); -} - -int -ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) { - ge25519 ALIGN(16) R, A; - hash_512bits hash; - bignum256modm hram, S; - unsigned char checkR[32]; - - if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) - return -1; - - /* hram = H(R,A,m) */ - ed25519_hram(hash, RS, pk, m, mlen); - expand256_modm(hram, hash, 64); - - /* S */ - expand256_modm(S, RS + 32, 32); - - /* SB - H(R,A,m)A */ - ge25519_double_scalarmult_vartime(&R, &A, hram, S); - ge25519_pack(checkR, &R); - - /* check that R = SB - H(R,A,m)A */ - return ed25519_verify(RS, checkR, 32) ? 0 : -1; -} - -#include "ed25519-donna-batchverify.h" - -/* - Fast Curve25519 basepoint scalar multiplication -*/ - -void -ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) { - curved25519_key ec; - bignum256modm s; - bignum25519 ALIGN(16) yplusz, zminusy; - ge25519 ALIGN(16) p; - size_t i; - - /* clamp */ - for (i = 0; i < 32; i++) ec[i] = e[i]; - ec[0] &= 248; - ec[31] &= 127; - ec[31] |= 64; - - expand_raw256_modm(s, ec); - - /* scalar * basepoint */ - ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s); - - /* u = (y + z) / (z - y) */ - curve25519_add(yplusz, p.y, p.z); - curve25519_sub(zminusy, p.z, p.y); - curve25519_recip(zminusy, zminusy); - curve25519_mul(yplusz, yplusz, zminusy); - curve25519_contract(pk, yplusz); -} - diff --git a/external/ed25519-donna/ed25519.h b/external/ed25519-donna/ed25519.h deleted file mode 100644 index dc86675cd1..0000000000 --- a/external/ed25519-donna/ed25519.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ED25519_H -#define ED25519_H - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -typedef unsigned char ed25519_signature[64]; -typedef unsigned char ed25519_public_key[32]; -typedef unsigned char ed25519_secret_key[32]; - -typedef unsigned char curved25519_key[32]; - -void ed25519_publickey(const ed25519_secret_key sk, ed25519_public_key pk); -int ed25519_sign_open(const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS); -void ed25519_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS); - -int ed25519_sign_open_batch(const unsigned char **m, size_t *mlen, const unsigned char **pk, const unsigned char **RS, size_t num, int *valid); - -void ed25519_randombytes_unsafe(void *out, size_t count); - -void curved25519_scalarmult_basepoint(curved25519_key pk, const curved25519_key e); - -#if defined(__cplusplus) -} -#endif - -#endif // ED25519_H diff --git a/external/ed25519-donna/fuzz/README.md b/external/ed25519-donna/fuzz/README.md deleted file mode 100644 index 306ddfe08c..0000000000 --- a/external/ed25519-donna/fuzz/README.md +++ /dev/null @@ -1,173 +0,0 @@ -This code fuzzes ed25519-donna (and optionally ed25519-donna-sse2) against the ref10 implementations of -[curve25519](https://github.com/floodyberry/supercop/tree/master/crypto_scalarmult/curve25519/ref10) and -[ed25519](https://github.com/floodyberry/supercop/tree/master/crypto_sign/ed25519/ref10). - -Curve25519 tests that generating a public key from a secret key - -# Building - -## *nix + PHP - -`php build-nix.php (required parameters) (optional parameters)` - -Required parameters: - -* `--function=[curve25519,ed25519]` -* `--bits=[32,64]` - -Optional parameters: - -* `--with-sse2` - - Also fuzz against ed25519-donna-sse2 -* `--with-openssl` - - Build with OpenSSL's SHA-512. - - Default: Reference SHA-512 implementation (slow!) - -* `--compiler=[gcc,clang,icc]` - - Default: gcc - -* `--no-asm` - - Do not use platform specific assembler - - -example: - - php build-nix.php --bits=64 --function=ed25519 --with-sse2 --compiler=icc - -## Windows - -Create a project with access to the ed25519 files. - -If you are not using OpenSSL, add the `ED25519_REFHASH` define to the projects -"Properties/Preprocessor/Preprocessor Definitions" option - -Add the following files to the project: - -* `fuzz/curve25519-ref10.c` -* `fuzz/ed25519-ref10.c` -* `fuzz/ed25519-donna.c` -* `fuzz/ed25519-donna-sse2.c` (optional) -* `fuzz-[curve25519/ed25519].c` (depending on which you want to fuzz) - -If you are also fuzzing against ed25519-donna-sse2, add the `ED25519_SSE2` define for `fuzz-[curve25519/ed25519].c` under -its "Properties/Preprocessor/Preprocessor Definitions" option. - -# Running - -If everything agrees, the program will only output occasional status dots (every 0x1000 passes) -and a 64bit progress count (every 0x20000 passes): - - fuzzing: ref10 curved25519 curved25519-sse2 - - ................................ [0000000000020000] - ................................ [0000000000040000] - ................................ [0000000000060000] - ................................ [0000000000080000] - ................................ [00000000000a0000] - ................................ [00000000000c0000] - -If any of the implementations do not agree with the ref10 implementation, the program will dump -the random data that was used, the data generated by the ref10 implementation, and diffs of the -ed25519-donna data against the ref10 data. - -## Example errors - -These are example error dumps (with intentionally introduced errors). - -### Ed25519 - -Random data: - -* sk, or Secret Key -* m, or Message - -Generated data: - -* pk, or Public Key -* sig, or Signature -* valid, or if the signature of the message is valid with the public key - -Dump: - - sk: - 0x3b,0xb7,0x17,0x7a,0x66,0xdc,0xb7,0x9a,0x90,0x25,0x07,0x99,0x96,0xf3,0x92,0xef, - 0x78,0xf8,0xad,0x6c,0x35,0x87,0x81,0x67,0x03,0xe6,0x95,0xba,0x06,0x18,0x7c,0x9c, - - m: - 0x7c,0x8d,0x3d,0xe1,0x92,0xee,0x7a,0xb8,0x4d,0xc9,0xfb,0x02,0x34,0x1e,0x5a,0x91, - 0xee,0x01,0xa6,0xb8,0xab,0x37,0x3f,0x3d,0x6d,0xa2,0x47,0xe3,0x27,0x93,0x7c,0xb7, - 0x77,0x07,0xb6,0x88,0x41,0x22,0xf3,0x3f,0xce,0xcb,0x6b,0x3e,0x2b,0x23,0x68,0x7f, - 0x5b,0xb9,0xda,0x04,0xbb,0xae,0x42,0x50,0xf5,0xe9,0xc5,0x11,0xbd,0x52,0x76,0x98, - 0xf1,0x87,0x09,0xb9,0x89,0x0a,0x52,0x69,0x01,0xce,0xe0,0x4a,0xa6,0x46,0x5a,0xe1, - 0x63,0x14,0xe0,0x81,0x52,0xec,0xcd,0xcf,0x70,0x54,0x7d,0xa3,0x49,0x8b,0xf0,0x89, - 0x70,0x07,0x12,0x2a,0xd9,0xaa,0x16,0x01,0xb2,0x16,0x3a,0xbb,0xfc,0xfa,0x13,0x5b, - 0x69,0x83,0x92,0x70,0x95,0x76,0xa0,0x8e,0x16,0x79,0xcc,0xaa,0xb5,0x7c,0xf8,0x7a, - - ref10: - pk: - 0x71,0xb0,0x5e,0x62,0x1b,0xe3,0xe7,0x36,0x91,0x8b,0xc0,0x13,0x36,0x0c,0xc9,0x04, - 0x16,0xf5,0xff,0x48,0x0c,0x83,0x6b,0x88,0x53,0xa2,0xc6,0x0f,0xf7,0xac,0x42,0x04, - - sig: - 0x3e,0x05,0xc5,0x37,0x16,0x0b,0x29,0x30,0x89,0xa3,0xe7,0x83,0x08,0x16,0xdd,0x96, - 0x02,0xfa,0x0d,0x44,0x2c,0x43,0xaa,0x80,0x93,0x04,0x58,0x22,0x09,0xbf,0x11,0xa5, - 0xcc,0xa5,0x3c,0x9f,0xa0,0xa4,0x64,0x5a,0x4a,0xdb,0x20,0xfb,0xc7,0x9b,0xfd,0x3f, - 0x08,0xae,0xc4,0x3c,0x1e,0xd8,0xb6,0xb4,0xd2,0x6d,0x80,0x92,0xcb,0x71,0xf3,0x02, - - valid: yes - - ed25519-donna: - pk diff: - ____,____,____,____,____,____,____,____,____,____,____,____,____,____,____,____, - ____,____,____,____,____,____,____,____,____,____,____,____,____,____,____,____, - - sig diff: - 0x2c,0xb9,0x25,0x14,0xd0,0x94,0xeb,0xfe,0x46,0x02,0xc2,0xe8,0xa3,0xeb,0xbf,0xb5, - 0x72,0x84,0xbf,0xc1,0x8a,0x32,0x30,0x99,0xf7,0x58,0xfe,0x06,0xa8,0xdc,0xdc,0xab, - 0xb5,0x57,0x03,0x33,0x87,0xce,0x54,0x55,0x6a,0x69,0x8a,0xc4,0xb7,0x2a,0xed,0x97, - 0xb4,0x68,0xe7,0x52,0x7a,0x07,0x55,0x3b,0xa2,0x94,0xd6,0x5e,0xa1,0x61,0x80,0x08, - - valid: no - -In this case, the generated public key matches, but the generated signature is completely -different and does not validate. - -### Curve25519 - -Random data: - -* sk, or Secret Key - -Generated data: - -* pk, or Public Key - -Dump: - - sk: - 0x44,0xec,0x0b,0x0e,0xa2,0x0e,0x9c,0x5b,0x8c,0xce,0x7b,0x1d,0x68,0xae,0x0f,0x9e, - 0x81,0xe2,0x04,0x76,0xda,0x87,0xa4,0x9e,0xc9,0x4f,0x3b,0xf9,0xc3,0x89,0x63,0x70, - - - ref10: - 0x24,0x55,0x55,0xc0,0xf9,0x80,0xaf,0x02,0x43,0xee,0x8c,0x7f,0xc1,0xad,0x90,0x95, - 0x57,0x91,0x14,0x2e,0xf2,0x14,0x22,0x80,0xdd,0x4e,0x3c,0x85,0x71,0x84,0x8c,0x62, - - - curved25519 diff: - 0x12,0xd1,0x61,0x2b,0x16,0xb3,0xd8,0x29,0xf8,0xa3,0xba,0x70,0x4e,0x49,0x4f,0x43, - 0xa1,0x3c,0x6b,0x42,0x11,0x61,0xcc,0x30,0x87,0x73,0x46,0xfb,0x85,0xc7,0x9a,0x35, - - - curved25519-sse2 diff: - ____,____,____,____,____,____,____,____,____,____,____,____,____,____,____,____, - ____,____,____,____,____,____,____,____,____,____,____,____,____,____,____,____, - - -In this case, curved25519 is totally wrong, while curved25519-sse2 matches the reference -implementation. \ No newline at end of file diff --git a/external/ed25519-donna/fuzz/build-nix.php b/external/ed25519-donna/fuzz/build-nix.php deleted file mode 100644 index c69144ebc9..0000000000 --- a/external/ed25519-donna/fuzz/build-nix.php +++ /dev/null @@ -1,134 +0,0 @@ -set = false; - - $map = array(); - foreach($legal_values as $value) - $map[$value] = true; - - for ($i = 1; $i < $argc; $i++) { - if (!preg_match("!--".$flag."=(.*)!", $argv[$i], $m)) - continue; - if (isset($map[$m[1]])) { - $this->value = $m[1]; - $this->set = true; - return; - } else { - usage("{$m[1]} is not a valid parameter to --{$flag}!"); - exit(1); - } - } - } - } - - class flag extends argument { - function flag($flag) { - global $argc, $argv; - - $this->set = false; - - $flag = "--{$flag}"; - for ($i = 1; $i < $argc; $i++) { - if ($argv[$i] !== $flag) - continue; - $this->value = true; - $this->set = true; - return; - } - } - } - - $bits = new multiargument("bits", array("32", "64")); - $function = new multiargument("function", array("curve25519", "ed25519")); - $compiler = new multiargument("compiler", array("gcc", "clang", "icc")); - $with_sse2 = new flag("with-sse2"); - $with_openssl = new flag("with-openssl"); - $no_asm = new flag("no-asm"); - - $err = ""; - if (!$bits->set) - $err .= "--bits not set\n"; - if (!$function->set) - $err .= "--function not set\n"; - - if ($err !== "") { - usage($err); - exit; - } - - $compile = ($compiler->set) ? $compiler->value : "gcc"; - $link = ""; - $flags = "-O3 -m{$bits->value}"; - $ret = 0; - - if ($with_openssl->set) $link .= " -lssl -lcrypto"; - if (!$with_openssl->set) $flags .= " -DED25519_REFHASH -DED25519_TEST"; - if ($no_asm->set) $flags .= " -DED25519_NO_INLINE_ASM"; - - if ($function->value === "curve25519") { - runcmd("building ref10..", "{$compile} {$flags} curve25519-ref10.c -c -o curve25519-ref10.o"); - runcmd("building ed25519..", "{$compile} {$flags} ed25519-donna.c -c -o ed25519.o"); - if ($with_sse2->set) { - runcmd("building ed25519-sse2..", "{$compile} {$flags} ed25519-donna-sse2.c -c -o ed25519-sse2.o -msse2"); - $flags .= " -DED25519_SSE2"; - $link .= " ed25519-sse2.o"; - } - runcmd("linking..", "{$compile} {$flags} {$link} fuzz-curve25519.c ed25519.o curve25519-ref10.o -o fuzz-curve25519"); - echoln("fuzz-curve25519 built."); - } else if ($function->value === "ed25519") { - runcmd("building ref10..", "{$compile} {$flags} ed25519-ref10.c -c -o ed25519-ref10.o"); - runcmd("building ed25519..", "{$compile} {$flags} ed25519-donna.c -c -o ed25519.o"); - if ($with_sse2->set) { - runcmd("building ed25519-sse2..", "{$compile} {$flags} ed25519-donna-sse2.c -c -o ed25519-sse2.o -msse2"); - $flags .= " -DED25519_SSE2"; - $link .= " ed25519-sse2.o"; - } - runcmd("linking..", "{$compile} {$flags} {$link} fuzz-ed25519.c ed25519.o ed25519-ref10.o -o fuzz-ed25519"); - echoln("fuzz-ed25519 built."); - } - - - cleanup(); -?> diff --git a/external/ed25519-donna/fuzz/curve25519-ref10.c b/external/ed25519-donna/fuzz/curve25519-ref10.c deleted file mode 100644 index efefce6fde..0000000000 --- a/external/ed25519-donna/fuzz/curve25519-ref10.c +++ /dev/null @@ -1,1272 +0,0 @@ -#include - -typedef int32_t crypto_int32; -typedef int64_t crypto_int64; -typedef uint64_t crypto_uint64; - -typedef crypto_int32 fe[10]; - -/* -h = 0 -*/ - -void fe_0(fe h) -{ - h[0] = 0; - h[1] = 0; - h[2] = 0; - h[3] = 0; - h[4] = 0; - h[5] = 0; - h[6] = 0; - h[7] = 0; - h[8] = 0; - h[9] = 0; -} - -/* -h = 1 -*/ - -void fe_1(fe h) -{ - h[0] = 1; - h[1] = 0; - h[2] = 0; - h[3] = 0; - h[4] = 0; - h[5] = 0; - h[6] = 0; - h[7] = 0; - h[8] = 0; - h[9] = 0; -} - -/* -h = f + g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Postconditions: - |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -void fe_add(fe h,fe f,fe g) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 g0 = g[0]; - crypto_int32 g1 = g[1]; - crypto_int32 g2 = g[2]; - crypto_int32 g3 = g[3]; - crypto_int32 g4 = g[4]; - crypto_int32 g5 = g[5]; - crypto_int32 g6 = g[6]; - crypto_int32 g7 = g[7]; - crypto_int32 g8 = g[8]; - crypto_int32 g9 = g[9]; - crypto_int32 h0 = f0 + g0; - crypto_int32 h1 = f1 + g1; - crypto_int32 h2 = f2 + g2; - crypto_int32 h3 = f3 + g3; - crypto_int32 h4 = f4 + g4; - crypto_int32 h5 = f5 + g5; - crypto_int32 h6 = f6 + g6; - crypto_int32 h7 = f7 + g7; - crypto_int32 h8 = f8 + g8; - crypto_int32 h9 = f9 + g9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -h = f -*/ - -void fe_copy(fe h,fe f) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - h[0] = f0; - h[1] = f1; - h[2] = f2; - h[3] = f3; - h[4] = f4; - h[5] = f5; - h[6] = f6; - h[7] = f7; - h[8] = f8; - h[9] = f9; -} - - -/* -Replace (f,g) with (g,f) if b == 1; -replace (f,g) with (f,g) if b == 0. - -Preconditions: b in {0,1}. -*/ - -void fe_cswap(fe f,fe g,unsigned int b) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 g0 = g[0]; - crypto_int32 g1 = g[1]; - crypto_int32 g2 = g[2]; - crypto_int32 g3 = g[3]; - crypto_int32 g4 = g[4]; - crypto_int32 g5 = g[5]; - crypto_int32 g6 = g[6]; - crypto_int32 g7 = g[7]; - crypto_int32 g8 = g[8]; - crypto_int32 g9 = g[9]; - crypto_int32 x0 = f0 ^ g0; - crypto_int32 x1 = f1 ^ g1; - crypto_int32 x2 = f2 ^ g2; - crypto_int32 x3 = f3 ^ g3; - crypto_int32 x4 = f4 ^ g4; - crypto_int32 x5 = f5 ^ g5; - crypto_int32 x6 = f6 ^ g6; - crypto_int32 x7 = f7 ^ g7; - crypto_int32 x8 = f8 ^ g8; - crypto_int32 x9 = f9 ^ g9; - b = -b; - x0 &= b; - x1 &= b; - x2 &= b; - x3 &= b; - x4 &= b; - x5 &= b; - x6 &= b; - x7 &= b; - x8 &= b; - x9 &= b; - f[0] = f0 ^ x0; - f[1] = f1 ^ x1; - f[2] = f2 ^ x2; - f[3] = f3 ^ x3; - f[4] = f4 ^ x4; - f[5] = f5 ^ x5; - f[6] = f6 ^ x6; - f[7] = f7 ^ x7; - f[8] = f8 ^ x8; - f[9] = f9 ^ x9; - g[0] = g0 ^ x0; - g[1] = g1 ^ x1; - g[2] = g2 ^ x2; - g[3] = g3 ^ x3; - g[4] = g4 ^ x4; - g[5] = g5 ^ x5; - g[6] = g6 ^ x6; - g[7] = g7 ^ x7; - g[8] = g8 ^ x8; - g[9] = g9 ^ x9; -} - -static crypto_uint64 load_3(const unsigned char *in) -{ - crypto_uint64 result; - result = (crypto_uint64) in[0]; - result |= ((crypto_uint64) in[1]) << 8; - result |= ((crypto_uint64) in[2]) << 16; - return result; -} - -static crypto_uint64 load_4(const unsigned char *in) -{ - crypto_uint64 result; - result = (crypto_uint64) in[0]; - result |= ((crypto_uint64) in[1]) << 8; - result |= ((crypto_uint64) in[2]) << 16; - result |= ((crypto_uint64) in[3]) << 24; - return result; -} - -void fe_frombytes(fe h,const unsigned char *s) -{ - crypto_int64 h0 = load_4(s); - crypto_int64 h1 = load_3(s + 4) << 6; - crypto_int64 h2 = load_3(s + 7) << 5; - crypto_int64 h3 = load_3(s + 10) << 3; - crypto_int64 h4 = load_3(s + 13) << 2; - crypto_int64 h5 = load_4(s + 16); - crypto_int64 h6 = load_3(s + 20) << 7; - crypto_int64 h7 = load_3(s + 23) << 5; - crypto_int64 h8 = load_3(s + 26) << 4; - crypto_int64 h9 = load_3(s + 29) << 2; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - - carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - - -/* -h = f * g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. - |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. - -Postconditions: - |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -*/ - -/* -Notes on implementation strategy: - -Using schoolbook multiplication. -Karatsuba would save a little in some cost models. - -Most multiplications by 2 and 19 are 32-bit precomputations; -cheaper than 64-bit postcomputations. - -There is one remaining multiplication by 19 in the carry chain; -one *19 precomputation can be merged into this, -but the resulting data flow is considerably less clean. - -There are 12 carries below. -10 of them are 2-way parallelizable and vectorizable. -Can get away with 11 carries, but then data flow is much deeper. - -With tighter constraints on inputs can squeeze carries into int32. -*/ - -void fe_mul(fe h,fe f,fe g) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 g0 = g[0]; - crypto_int32 g1 = g[1]; - crypto_int32 g2 = g[2]; - crypto_int32 g3 = g[3]; - crypto_int32 g4 = g[4]; - crypto_int32 g5 = g[5]; - crypto_int32 g6 = g[6]; - crypto_int32 g7 = g[7]; - crypto_int32 g8 = g[8]; - crypto_int32 g9 = g[9]; - crypto_int32 g1_19 = 19 * g1; /* 1.4*2^29 */ - crypto_int32 g2_19 = 19 * g2; /* 1.4*2^30; still ok */ - crypto_int32 g3_19 = 19 * g3; - crypto_int32 g4_19 = 19 * g4; - crypto_int32 g5_19 = 19 * g5; - crypto_int32 g6_19 = 19 * g6; - crypto_int32 g7_19 = 19 * g7; - crypto_int32 g8_19 = 19 * g8; - crypto_int32 g9_19 = 19 * g9; - crypto_int32 f1_2 = 2 * f1; - crypto_int32 f3_2 = 2 * f3; - crypto_int32 f5_2 = 2 * f5; - crypto_int32 f7_2 = 2 * f7; - crypto_int32 f9_2 = 2 * f9; - crypto_int64 f0g0 = f0 * (crypto_int64) g0; - crypto_int64 f0g1 = f0 * (crypto_int64) g1; - crypto_int64 f0g2 = f0 * (crypto_int64) g2; - crypto_int64 f0g3 = f0 * (crypto_int64) g3; - crypto_int64 f0g4 = f0 * (crypto_int64) g4; - crypto_int64 f0g5 = f0 * (crypto_int64) g5; - crypto_int64 f0g6 = f0 * (crypto_int64) g6; - crypto_int64 f0g7 = f0 * (crypto_int64) g7; - crypto_int64 f0g8 = f0 * (crypto_int64) g8; - crypto_int64 f0g9 = f0 * (crypto_int64) g9; - crypto_int64 f1g0 = f1 * (crypto_int64) g0; - crypto_int64 f1g1_2 = f1_2 * (crypto_int64) g1; - crypto_int64 f1g2 = f1 * (crypto_int64) g2; - crypto_int64 f1g3_2 = f1_2 * (crypto_int64) g3; - crypto_int64 f1g4 = f1 * (crypto_int64) g4; - crypto_int64 f1g5_2 = f1_2 * (crypto_int64) g5; - crypto_int64 f1g6 = f1 * (crypto_int64) g6; - crypto_int64 f1g7_2 = f1_2 * (crypto_int64) g7; - crypto_int64 f1g8 = f1 * (crypto_int64) g8; - crypto_int64 f1g9_38 = f1_2 * (crypto_int64) g9_19; - crypto_int64 f2g0 = f2 * (crypto_int64) g0; - crypto_int64 f2g1 = f2 * (crypto_int64) g1; - crypto_int64 f2g2 = f2 * (crypto_int64) g2; - crypto_int64 f2g3 = f2 * (crypto_int64) g3; - crypto_int64 f2g4 = f2 * (crypto_int64) g4; - crypto_int64 f2g5 = f2 * (crypto_int64) g5; - crypto_int64 f2g6 = f2 * (crypto_int64) g6; - crypto_int64 f2g7 = f2 * (crypto_int64) g7; - crypto_int64 f2g8_19 = f2 * (crypto_int64) g8_19; - crypto_int64 f2g9_19 = f2 * (crypto_int64) g9_19; - crypto_int64 f3g0 = f3 * (crypto_int64) g0; - crypto_int64 f3g1_2 = f3_2 * (crypto_int64) g1; - crypto_int64 f3g2 = f3 * (crypto_int64) g2; - crypto_int64 f3g3_2 = f3_2 * (crypto_int64) g3; - crypto_int64 f3g4 = f3 * (crypto_int64) g4; - crypto_int64 f3g5_2 = f3_2 * (crypto_int64) g5; - crypto_int64 f3g6 = f3 * (crypto_int64) g6; - crypto_int64 f3g7_38 = f3_2 * (crypto_int64) g7_19; - crypto_int64 f3g8_19 = f3 * (crypto_int64) g8_19; - crypto_int64 f3g9_38 = f3_2 * (crypto_int64) g9_19; - crypto_int64 f4g0 = f4 * (crypto_int64) g0; - crypto_int64 f4g1 = f4 * (crypto_int64) g1; - crypto_int64 f4g2 = f4 * (crypto_int64) g2; - crypto_int64 f4g3 = f4 * (crypto_int64) g3; - crypto_int64 f4g4 = f4 * (crypto_int64) g4; - crypto_int64 f4g5 = f4 * (crypto_int64) g5; - crypto_int64 f4g6_19 = f4 * (crypto_int64) g6_19; - crypto_int64 f4g7_19 = f4 * (crypto_int64) g7_19; - crypto_int64 f4g8_19 = f4 * (crypto_int64) g8_19; - crypto_int64 f4g9_19 = f4 * (crypto_int64) g9_19; - crypto_int64 f5g0 = f5 * (crypto_int64) g0; - crypto_int64 f5g1_2 = f5_2 * (crypto_int64) g1; - crypto_int64 f5g2 = f5 * (crypto_int64) g2; - crypto_int64 f5g3_2 = f5_2 * (crypto_int64) g3; - crypto_int64 f5g4 = f5 * (crypto_int64) g4; - crypto_int64 f5g5_38 = f5_2 * (crypto_int64) g5_19; - crypto_int64 f5g6_19 = f5 * (crypto_int64) g6_19; - crypto_int64 f5g7_38 = f5_2 * (crypto_int64) g7_19; - crypto_int64 f5g8_19 = f5 * (crypto_int64) g8_19; - crypto_int64 f5g9_38 = f5_2 * (crypto_int64) g9_19; - crypto_int64 f6g0 = f6 * (crypto_int64) g0; - crypto_int64 f6g1 = f6 * (crypto_int64) g1; - crypto_int64 f6g2 = f6 * (crypto_int64) g2; - crypto_int64 f6g3 = f6 * (crypto_int64) g3; - crypto_int64 f6g4_19 = f6 * (crypto_int64) g4_19; - crypto_int64 f6g5_19 = f6 * (crypto_int64) g5_19; - crypto_int64 f6g6_19 = f6 * (crypto_int64) g6_19; - crypto_int64 f6g7_19 = f6 * (crypto_int64) g7_19; - crypto_int64 f6g8_19 = f6 * (crypto_int64) g8_19; - crypto_int64 f6g9_19 = f6 * (crypto_int64) g9_19; - crypto_int64 f7g0 = f7 * (crypto_int64) g0; - crypto_int64 f7g1_2 = f7_2 * (crypto_int64) g1; - crypto_int64 f7g2 = f7 * (crypto_int64) g2; - crypto_int64 f7g3_38 = f7_2 * (crypto_int64) g3_19; - crypto_int64 f7g4_19 = f7 * (crypto_int64) g4_19; - crypto_int64 f7g5_38 = f7_2 * (crypto_int64) g5_19; - crypto_int64 f7g6_19 = f7 * (crypto_int64) g6_19; - crypto_int64 f7g7_38 = f7_2 * (crypto_int64) g7_19; - crypto_int64 f7g8_19 = f7 * (crypto_int64) g8_19; - crypto_int64 f7g9_38 = f7_2 * (crypto_int64) g9_19; - crypto_int64 f8g0 = f8 * (crypto_int64) g0; - crypto_int64 f8g1 = f8 * (crypto_int64) g1; - crypto_int64 f8g2_19 = f8 * (crypto_int64) g2_19; - crypto_int64 f8g3_19 = f8 * (crypto_int64) g3_19; - crypto_int64 f8g4_19 = f8 * (crypto_int64) g4_19; - crypto_int64 f8g5_19 = f8 * (crypto_int64) g5_19; - crypto_int64 f8g6_19 = f8 * (crypto_int64) g6_19; - crypto_int64 f8g7_19 = f8 * (crypto_int64) g7_19; - crypto_int64 f8g8_19 = f8 * (crypto_int64) g8_19; - crypto_int64 f8g9_19 = f8 * (crypto_int64) g9_19; - crypto_int64 f9g0 = f9 * (crypto_int64) g0; - crypto_int64 f9g1_38 = f9_2 * (crypto_int64) g1_19; - crypto_int64 f9g2_19 = f9 * (crypto_int64) g2_19; - crypto_int64 f9g3_38 = f9_2 * (crypto_int64) g3_19; - crypto_int64 f9g4_19 = f9 * (crypto_int64) g4_19; - crypto_int64 f9g5_38 = f9_2 * (crypto_int64) g5_19; - crypto_int64 f9g6_19 = f9 * (crypto_int64) g6_19; - crypto_int64 f9g7_38 = f9_2 * (crypto_int64) g7_19; - crypto_int64 f9g8_19 = f9 * (crypto_int64) g8_19; - crypto_int64 f9g9_38 = f9_2 * (crypto_int64) g9_19; - crypto_int64 h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38; - crypto_int64 h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19; - crypto_int64 h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38; - crypto_int64 h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19; - crypto_int64 h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38; - crypto_int64 h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19; - crypto_int64 h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38; - crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; - crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; - crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - - /* - |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) - i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8 - |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19)) - i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9 - */ - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - /* |h0| <= 2^25 */ - /* |h4| <= 2^25 */ - /* |h1| <= 1.51*2^58 */ - /* |h5| <= 1.51*2^58 */ - - carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - /* |h1| <= 2^24; from now on fits into int32 */ - /* |h5| <= 2^24; from now on fits into int32 */ - /* |h2| <= 1.21*2^59 */ - /* |h6| <= 1.21*2^59 */ - - carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - /* |h2| <= 2^25; from now on fits into int32 unchanged */ - /* |h6| <= 2^25; from now on fits into int32 unchanged */ - /* |h3| <= 1.51*2^58 */ - /* |h7| <= 1.51*2^58 */ - - carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - /* |h3| <= 2^24; from now on fits into int32 unchanged */ - /* |h7| <= 2^24; from now on fits into int32 unchanged */ - /* |h4| <= 1.52*2^33 */ - /* |h8| <= 1.52*2^33 */ - - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - /* |h4| <= 2^25; from now on fits into int32 unchanged */ - /* |h8| <= 2^25; from now on fits into int32 unchanged */ - /* |h5| <= 1.01*2^24 */ - /* |h9| <= 1.51*2^58 */ - - carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - /* |h9| <= 2^24; from now on fits into int32 unchanged */ - /* |h0| <= 1.8*2^37 */ - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - /* |h0| <= 2^25; from now on fits into int32 unchanged */ - /* |h1| <= 1.01*2^24 */ - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -h = f * 121666 -Can overlap h with f. - -Preconditions: - |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. - -Postconditions: - |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -*/ - -void fe_mul121666(fe h,fe f) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int64 h0 = f0 * (crypto_int64) 121666; - crypto_int64 h1 = f1 * (crypto_int64) 121666; - crypto_int64 h2 = f2 * (crypto_int64) 121666; - crypto_int64 h3 = f3 * (crypto_int64) 121666; - crypto_int64 h4 = f4 * (crypto_int64) 121666; - crypto_int64 h5 = f5 * (crypto_int64) 121666; - crypto_int64 h6 = f6 * (crypto_int64) 121666; - crypto_int64 h7 = f7 * (crypto_int64) 121666; - crypto_int64 h8 = f8 * (crypto_int64) 121666; - crypto_int64 h9 = f9 * (crypto_int64) 121666; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - - carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -h = f * f -Can overlap h with f. - -Preconditions: - |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. - -Postconditions: - |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -*/ - -/* -See fe_mul.c for discussion of implementation strategy. -*/ - -void fe_sq(fe h,fe f) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 f0_2 = 2 * f0; - crypto_int32 f1_2 = 2 * f1; - crypto_int32 f2_2 = 2 * f2; - crypto_int32 f3_2 = 2 * f3; - crypto_int32 f4_2 = 2 * f4; - crypto_int32 f5_2 = 2 * f5; - crypto_int32 f6_2 = 2 * f6; - crypto_int32 f7_2 = 2 * f7; - crypto_int32 f5_38 = 38 * f5; /* 1.31*2^30 */ - crypto_int32 f6_19 = 19 * f6; /* 1.31*2^30 */ - crypto_int32 f7_38 = 38 * f7; /* 1.31*2^30 */ - crypto_int32 f8_19 = 19 * f8; /* 1.31*2^30 */ - crypto_int32 f9_38 = 38 * f9; /* 1.31*2^30 */ - crypto_int64 f0f0 = f0 * (crypto_int64) f0; - crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1; - crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2; - crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3; - crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4; - crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5; - crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6; - crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7; - crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8; - crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9; - crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1; - crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2; - crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2; - crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4; - crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2; - crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6; - crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2; - crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8; - crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38; - crypto_int64 f2f2 = f2 * (crypto_int64) f2; - crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3; - crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4; - crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5; - crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6; - crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7; - crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19; - crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38; - crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3; - crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4; - crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2; - crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6; - crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38; - crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19; - crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38; - crypto_int64 f4f4 = f4 * (crypto_int64) f4; - crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5; - crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19; - crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38; - crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19; - crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38; - crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38; - crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19; - crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38; - crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19; - crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38; - crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19; - crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38; - crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19; - crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38; - crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38; - crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19; - crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38; - crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19; - crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38; - crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38; - crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; - crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; - crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; - crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; - crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; - crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; - crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; - crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; - crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; - crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - - carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - - carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - - carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -h = f - g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Postconditions: - |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -void fe_sub(fe h,fe f,fe g) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 g0 = g[0]; - crypto_int32 g1 = g[1]; - crypto_int32 g2 = g[2]; - crypto_int32 g3 = g[3]; - crypto_int32 g4 = g[4]; - crypto_int32 g5 = g[5]; - crypto_int32 g6 = g[6]; - crypto_int32 g7 = g[7]; - crypto_int32 g8 = g[8]; - crypto_int32 g9 = g[9]; - crypto_int32 h0 = f0 - g0; - crypto_int32 h1 = f1 - g1; - crypto_int32 h2 = f2 - g2; - crypto_int32 h3 = f3 - g3; - crypto_int32 h4 = f4 - g4; - crypto_int32 h5 = f5 - g5; - crypto_int32 h6 = f6 - g6; - crypto_int32 h7 = f7 - g7; - crypto_int32 h8 = f8 - g8; - crypto_int32 h9 = f9 - g9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -Preconditions: - |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Write p=2^255-19; q=floor(h/p). -Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). - -Proof: - Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. - Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4. - - Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). - Then 0> 25; - q = (h0 + q) >> 26; - q = (h1 + q) >> 25; - q = (h2 + q) >> 26; - q = (h3 + q) >> 25; - q = (h4 + q) >> 26; - q = (h5 + q) >> 25; - q = (h6 + q) >> 26; - q = (h7 + q) >> 25; - q = (h8 + q) >> 26; - q = (h9 + q) >> 25; - - /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ - h0 += 19 * q; - /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ - - carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; - carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; - carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; - carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; - carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; - carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; - carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; - carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; - carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; - carry9 = h9 >> 25; h9 -= carry9 << 25; - /* h10 = carry9 */ - - /* - Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - Have h0+...+2^230 h9 between 0 and 2^255-1; - evidently 2^255 h10-2^255 q = 0. - Goal: Output h0+...+2^230 h9. - */ - - s[0] = h0 >> 0; - s[1] = h0 >> 8; - s[2] = h0 >> 16; - s[3] = (h0 >> 24) | (h1 << 2); - s[4] = h1 >> 6; - s[5] = h1 >> 14; - s[6] = (h1 >> 22) | (h2 << 3); - s[7] = h2 >> 5; - s[8] = h2 >> 13; - s[9] = (h2 >> 21) | (h3 << 5); - s[10] = h3 >> 3; - s[11] = h3 >> 11; - s[12] = (h3 >> 19) | (h4 << 6); - s[13] = h4 >> 2; - s[14] = h4 >> 10; - s[15] = h4 >> 18; - s[16] = h5 >> 0; - s[17] = h5 >> 8; - s[18] = h5 >> 16; - s[19] = (h5 >> 24) | (h6 << 1); - s[20] = h6 >> 7; - s[21] = h6 >> 15; - s[22] = (h6 >> 23) | (h7 << 3); - s[23] = h7 >> 5; - s[24] = h7 >> 13; - s[25] = (h7 >> 21) | (h8 << 4); - s[26] = h8 >> 4; - s[27] = h8 >> 12; - s[28] = (h8 >> 20) | (h9 << 6); - s[29] = h9 >> 2; - s[30] = h9 >> 10; - s[31] = h9 >> 18; -} - -void fe_invert(fe out,fe z) -{ - fe t0; - fe t1; - fe t2; - fe t3; - int i; - - -/* qhasm: fe z1 */ - -/* qhasm: fe z2 */ - -/* qhasm: fe z8 */ - -/* qhasm: fe z9 */ - -/* qhasm: fe z11 */ - -/* qhasm: fe z22 */ - -/* qhasm: fe z_5_0 */ - -/* qhasm: fe z_10_5 */ - -/* qhasm: fe z_10_0 */ - -/* qhasm: fe z_20_10 */ - -/* qhasm: fe z_20_0 */ - -/* qhasm: fe z_40_20 */ - -/* qhasm: fe z_40_0 */ - -/* qhasm: fe z_50_10 */ - -/* qhasm: fe z_50_0 */ - -/* qhasm: fe z_100_50 */ - -/* qhasm: fe z_100_0 */ - -/* qhasm: fe z_200_100 */ - -/* qhasm: fe z_200_0 */ - -/* qhasm: fe z_250_50 */ - -/* qhasm: fe z_250_0 */ - -/* qhasm: fe z_255_5 */ - -/* qhasm: fe z_255_21 */ - -/* qhasm: enter pow225521 */ - -/* qhasm: z2 = z1^2^1 */ -/* asm 1: fe_sq(>z2=fe#1,z2=fe#1,>z2=fe#1); */ -/* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ -fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); - -/* qhasm: z8 = z2^2^2 */ -/* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ -/* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ -fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); - -/* qhasm: z9 = z1*z8 */ -/* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#3,z22=fe#3,>z22=fe#3); */ -/* asm 2: fe_sq(>z22=t2,z22=t2,>z22=t2); */ -fe_sq(t2,t0); for (i = 1;i < 1;++i) fe_sq(t2,t2); - -/* qhasm: z_5_0 = z9*z22 */ -/* asm 1: fe_mul(>z_5_0=fe#2,z_5_0=t1,z_10_5=fe#3,z_10_5=fe#3,>z_10_5=fe#3); */ -/* asm 2: fe_sq(>z_10_5=t2,z_10_5=t2,>z_10_5=t2); */ -fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2); - -/* qhasm: z_10_0 = z_10_5*z_5_0 */ -/* asm 1: fe_mul(>z_10_0=fe#2,z_10_0=t1,z_20_10=fe#3,z_20_10=fe#3,>z_20_10=fe#3); */ -/* asm 2: fe_sq(>z_20_10=t2,z_20_10=t2,>z_20_10=t2); */ -fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2); - -/* qhasm: z_20_0 = z_20_10*z_10_0 */ -/* asm 1: fe_mul(>z_20_0=fe#3,z_20_0=t2,z_40_20=fe#4,z_40_20=fe#4,>z_40_20=fe#4); */ -/* asm 2: fe_sq(>z_40_20=t3,z_40_20=t3,>z_40_20=t3); */ -fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3); - -/* qhasm: z_40_0 = z_40_20*z_20_0 */ -/* asm 1: fe_mul(>z_40_0=fe#3,z_40_0=t2,z_50_10=fe#3,z_50_10=fe#3,>z_50_10=fe#3); */ -/* asm 2: fe_sq(>z_50_10=t2,z_50_10=t2,>z_50_10=t2); */ -fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2); - -/* qhasm: z_50_0 = z_50_10*z_10_0 */ -/* asm 1: fe_mul(>z_50_0=fe#2,z_50_0=t1,z_100_50=fe#3,z_100_50=fe#3,>z_100_50=fe#3); */ -/* asm 2: fe_sq(>z_100_50=t2,z_100_50=t2,>z_100_50=t2); */ -fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2); - -/* qhasm: z_100_0 = z_100_50*z_50_0 */ -/* asm 1: fe_mul(>z_100_0=fe#3,z_100_0=t2,z_200_100=fe#4,z_200_100=fe#4,>z_200_100=fe#4); */ -/* asm 2: fe_sq(>z_200_100=t3,z_200_100=t3,>z_200_100=t3); */ -fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3); - -/* qhasm: z_200_0 = z_200_100*z_100_0 */ -/* asm 1: fe_mul(>z_200_0=fe#3,z_200_0=t2,z_250_50=fe#3,z_250_50=fe#3,>z_250_50=fe#3); */ -/* asm 2: fe_sq(>z_250_50=t2,z_250_50=t2,>z_250_50=t2); */ -fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2); - -/* qhasm: z_250_0 = z_250_50*z_50_0 */ -/* asm 1: fe_mul(>z_250_0=fe#2,z_250_0=t1,z_255_5=fe#2,z_255_5=fe#2,>z_255_5=fe#2); */ -/* asm 2: fe_sq(>z_255_5=t1,z_255_5=t1,>z_255_5=t1); */ -fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1); - -/* qhasm: z_255_21 = z_255_5*z11 */ -/* asm 1: fe_mul(>z_255_21=fe#12,z_255_21=out,= 0;--pos) { - b = e[pos / 8] >> (pos & 7); - b &= 1; - swap ^= b; - fe_cswap(x2,x3,swap); - fe_cswap(z2,z3,swap); - swap = b; -/* qhasm: fe X2 */ - -/* qhasm: fe Z2 */ - -/* qhasm: fe X3 */ - -/* qhasm: fe Z3 */ - -/* qhasm: fe X4 */ - -/* qhasm: fe Z4 */ - -/* qhasm: fe X5 */ - -/* qhasm: fe Z5 */ - -/* qhasm: fe A */ - -/* qhasm: fe B */ - -/* qhasm: fe C */ - -/* qhasm: fe D */ - -/* qhasm: fe E */ - -/* qhasm: fe AA */ - -/* qhasm: fe BB */ - -/* qhasm: fe DA */ - -/* qhasm: fe CB */ - -/* qhasm: fe t0 */ - -/* qhasm: fe t1 */ - -/* qhasm: fe t2 */ - -/* qhasm: fe t3 */ - -/* qhasm: fe t4 */ - -/* qhasm: enter ladder */ - -/* qhasm: D = X3-Z3 */ -/* asm 1: fe_sub(>D=fe#5,D=tmp0,B=fe#6,B=tmp1,A=fe#1,A=x2,C=fe#2,C=z2,DA=fe#4,DA=z3,CB=fe#2,CB=z2,BB=fe#5,BB=tmp0,AA=fe#6,AA=tmp1,t0=fe#3,t0=x3,t1=fe#2,t1=z2,X4=fe#1,X4=x2,E=fe#6,E=tmp1,t2=fe#2,t2=z2,t3=fe#4,t3=z3,X5=fe#3,X5=x3,t4=fe#5,t4=tmp0,Z5=fe#4,x1,Z5=z3,x1,Z4=fe#2,Z4=z2, - -typedef unsigned char ed25519_signature[64]; -typedef unsigned char ed25519_public_key[32]; -typedef unsigned char ed25519_secret_key[32]; - -typedef unsigned char curved25519_key[32]; - -void ed25519_publickey(const ed25519_secret_key sk, ed25519_public_key pk); -int ed25519_sign_open(const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS); -void ed25519_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS); - -int ed25519_sign_open_batch(const unsigned char **m, size_t *mlen, const unsigned char **pk, const unsigned char **RS, size_t num, int *valid); - -void ed25519_randombytes_unsafe(void *out, size_t count); - -void curved25519_scalarmult_basepoint(curved25519_key pk, const curved25519_key e); - -#if defined(ED25519_SSE2) -void ed25519_publickey_sse2(const ed25519_secret_key sk, ed25519_public_key pk); -int ed25519_sign_open_sse2(const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS); -void ed25519_sign_sse2(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS); - -int ed25519_sign_open_batch_sse2(const unsigned char **m, size_t *mlen, const unsigned char **pk, const unsigned char **RS, size_t num, int *valid); - -void ed25519_randombytes_unsafe_sse2(void *out, size_t count); - -void curved25519_scalarmult_basepoint_sse2(curved25519_key pk, const curved25519_key e); -#endif - -#endif // ED25519_H diff --git a/external/ed25519-donna/fuzz/ed25519-ref10.c b/external/ed25519-donna/fuzz/ed25519-ref10.c deleted file mode 100644 index a8e802df29..0000000000 --- a/external/ed25519-donna/fuzz/ed25519-ref10.c +++ /dev/null @@ -1,4647 +0,0 @@ -#include -#include -#include - -static int crypto_verify_32(const unsigned char *x,const unsigned char *y) -{ - unsigned int differentbits = 0; -#define F(i) differentbits |= x[i] ^ y[i]; - F(0) - F(1) - F(2) - F(3) - F(4) - F(5) - F(6) - F(7) - F(8) - F(9) - F(10) - F(11) - F(12) - F(13) - F(14) - F(15) - F(16) - F(17) - F(18) - F(19) - F(20) - F(21) - F(22) - F(23) - F(24) - F(25) - F(26) - F(27) - F(28) - F(29) - F(30) - F(31) - return (1 & ((differentbits - 1) >> 8)) - 1; -} - -#if defined(ED25519_REFHASH) - -/* reference/slow SHA-512. really, do not use this */ - -#define HASH_BLOCK_SIZE 128 -#define HASH_DIGEST_SIZE 64 - -typedef struct sha512_state_t { - uint64_t H[8]; - uint64_t T[2]; - uint32_t leftover; - uint8_t buffer[HASH_BLOCK_SIZE]; -} sha512_state; - -typedef sha512_state ed25519_hash_context; - -static const uint64_t sha512_constants[80] = { - 0x428a2f98d728ae22ull, 0x7137449123ef65cdull, 0xb5c0fbcfec4d3b2full, 0xe9b5dba58189dbbcull, - 0x3956c25bf348b538ull, 0x59f111f1b605d019ull, 0x923f82a4af194f9bull, 0xab1c5ed5da6d8118ull, - 0xd807aa98a3030242ull, 0x12835b0145706fbeull, 0x243185be4ee4b28cull, 0x550c7dc3d5ffb4e2ull, - 0x72be5d74f27b896full, 0x80deb1fe3b1696b1ull, 0x9bdc06a725c71235ull, 0xc19bf174cf692694ull, - 0xe49b69c19ef14ad2ull, 0xefbe4786384f25e3ull, 0x0fc19dc68b8cd5b5ull, 0x240ca1cc77ac9c65ull, - 0x2de92c6f592b0275ull, 0x4a7484aa6ea6e483ull, 0x5cb0a9dcbd41fbd4ull, 0x76f988da831153b5ull, - 0x983e5152ee66dfabull, 0xa831c66d2db43210ull, 0xb00327c898fb213full, 0xbf597fc7beef0ee4ull, - 0xc6e00bf33da88fc2ull, 0xd5a79147930aa725ull, 0x06ca6351e003826full, 0x142929670a0e6e70ull, - 0x27b70a8546d22ffcull, 0x2e1b21385c26c926ull, 0x4d2c6dfc5ac42aedull, 0x53380d139d95b3dfull, - 0x650a73548baf63deull, 0x766a0abb3c77b2a8ull, 0x81c2c92e47edaee6ull, 0x92722c851482353bull, - 0xa2bfe8a14cf10364ull, 0xa81a664bbc423001ull, 0xc24b8b70d0f89791ull, 0xc76c51a30654be30ull, - 0xd192e819d6ef5218ull, 0xd69906245565a910ull, 0xf40e35855771202aull, 0x106aa07032bbd1b8ull, - 0x19a4c116b8d2d0c8ull, 0x1e376c085141ab53ull, 0x2748774cdf8eeb99ull, 0x34b0bcb5e19b48a8ull, - 0x391c0cb3c5c95a63ull, 0x4ed8aa4ae3418acbull, 0x5b9cca4f7763e373ull, 0x682e6ff3d6b2b8a3ull, - 0x748f82ee5defb2fcull, 0x78a5636f43172f60ull, 0x84c87814a1f0ab72ull, 0x8cc702081a6439ecull, - 0x90befffa23631e28ull, 0xa4506cebde82bde9ull, 0xbef9a3f7b2c67915ull, 0xc67178f2e372532bull, - 0xca273eceea26619cull, 0xd186b8c721c0c207ull, 0xeada7dd6cde0eb1eull, 0xf57d4f7fee6ed178ull, - 0x06f067aa72176fbaull, 0x0a637dc5a2c898a6ull, 0x113f9804bef90daeull, 0x1b710b35131c471bull, - 0x28db77f523047d84ull, 0x32caab7b40c72493ull, 0x3c9ebe0a15c9bebcull, 0x431d67c49c100d4cull, - 0x4cc5d4becb3e42b6ull, 0x597f299cfc657e2aull, 0x5fcb6fab3ad6faecull, 0x6c44198c4a475817ull -}; - -static uint64_t -sha512_ROTR64(uint64_t x, int k) { - return (x >> k) | (x << (64 - k)); -} - -static uint64_t -sha512_LOAD64_BE(const uint8_t *p) { - return - ((uint64_t)p[0] << 56) | - ((uint64_t)p[1] << 48) | - ((uint64_t)p[2] << 40) | - ((uint64_t)p[3] << 32) | - ((uint64_t)p[4] << 24) | - ((uint64_t)p[5] << 16) | - ((uint64_t)p[6] << 8) | - ((uint64_t)p[7] ); -} - -static void -sha512_STORE64_BE(uint8_t *p, uint64_t v) { - p[0] = (uint8_t)(v >> 56); - p[1] = (uint8_t)(v >> 48); - p[2] = (uint8_t)(v >> 40); - p[3] = (uint8_t)(v >> 32); - p[4] = (uint8_t)(v >> 24); - p[5] = (uint8_t)(v >> 16); - p[6] = (uint8_t)(v >> 8); - p[7] = (uint8_t)(v ); -} - -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S0(x) (sha512_ROTR64(x, 28) ^ sha512_ROTR64(x, 34) ^ sha512_ROTR64(x, 39)) -#define S1(x) (sha512_ROTR64(x, 14) ^ sha512_ROTR64(x, 18) ^ sha512_ROTR64(x, 41)) -#define G0(x) (sha512_ROTR64(x, 1) ^ sha512_ROTR64(x, 8) ^ (x >> 7)) -#define G1(x) (sha512_ROTR64(x, 19) ^ sha512_ROTR64(x, 61) ^ (x >> 6)) -#define W0(in,i) (sha512_LOAD64_BE(&in[i * 8])) -#define W1(i) (G1(w[i - 2]) + w[i - 7] + G0(w[i - 15]) + w[i - 16]) -#define STEP(i) \ - t1 = S0(r[0]) + Maj(r[0], r[1], r[2]); \ - t0 = r[7] + S1(r[4]) + Ch(r[4], r[5], r[6]) + sha512_constants[i] + w[i]; \ - r[7] = r[6]; \ - r[6] = r[5]; \ - r[5] = r[4]; \ - r[4] = r[3] + t0; \ - r[3] = r[2]; \ - r[2] = r[1]; \ - r[1] = r[0]; \ - r[0] = t0 + t1; - -static void -sha512_blocks(sha512_state *S, const uint8_t *in, size_t blocks) { - uint64_t r[8], w[80], t0, t1; - size_t i; - - for (i = 0; i < 8; i++) r[i] = S->H[i]; - - while (blocks--) { - for (i = 0; i < 16; i++) { w[i] = W0(in, i); } - for (i = 16; i < 80; i++) { w[i] = W1(i); } - for (i = 0; i < 80; i++) { STEP(i); } - for (i = 0; i < 8; i++) { r[i] += S->H[i]; S->H[i] = r[i]; } - S->T[0] += HASH_BLOCK_SIZE * 8; - S->T[1] += (!S->T[0]) ? 1 : 0; - in += HASH_BLOCK_SIZE; - } -} - -static void -ed25519_hash_init(sha512_state *S) { - S->H[0] = 0x6a09e667f3bcc908ull; - S->H[1] = 0xbb67ae8584caa73bull; - S->H[2] = 0x3c6ef372fe94f82bull; - S->H[3] = 0xa54ff53a5f1d36f1ull; - S->H[4] = 0x510e527fade682d1ull; - S->H[5] = 0x9b05688c2b3e6c1full; - S->H[6] = 0x1f83d9abfb41bd6bull; - S->H[7] = 0x5be0cd19137e2179ull; - S->T[0] = 0; - S->T[1] = 0; - S->leftover = 0; -} - -static void -ed25519_hash_update(sha512_state *S, const uint8_t *in, size_t inlen) { - size_t blocks, want; - - /* handle the previous data */ - if (S->leftover) { - want = (HASH_BLOCK_SIZE - S->leftover); - want = (want < inlen) ? want : inlen; - memcpy(S->buffer + S->leftover, in, want); - S->leftover += (uint32_t)want; - if (S->leftover < HASH_BLOCK_SIZE) - return; - in += want; - inlen -= want; - sha512_blocks(S, S->buffer, 1); - } - - /* handle the current data */ - blocks = (inlen & ~(HASH_BLOCK_SIZE - 1)); - S->leftover = (uint32_t)(inlen - blocks); - if (blocks) { - sha512_blocks(S, in, blocks / HASH_BLOCK_SIZE); - in += blocks; - } - - /* handle leftover data */ - if (S->leftover) - memcpy(S->buffer, in, S->leftover); -} - -static void -ed25519_hash_final(sha512_state *S, uint8_t *hash) { - uint64_t t0 = S->T[0] + (S->leftover * 8), t1 = S->T[1]; - - S->buffer[S->leftover] = 0x80; - if (S->leftover <= 111) { - memset(S->buffer + S->leftover + 1, 0, 111 - S->leftover); - } else { - memset(S->buffer + S->leftover + 1, 0, 127 - S->leftover); - sha512_blocks(S, S->buffer, 1); - memset(S->buffer, 0, 112); - } - - sha512_STORE64_BE(S->buffer + 112, t1); - sha512_STORE64_BE(S->buffer + 120, t0); - sha512_blocks(S, S->buffer, 1); - - sha512_STORE64_BE(&hash[ 0], S->H[0]); - sha512_STORE64_BE(&hash[ 8], S->H[1]); - sha512_STORE64_BE(&hash[16], S->H[2]); - sha512_STORE64_BE(&hash[24], S->H[3]); - sha512_STORE64_BE(&hash[32], S->H[4]); - sha512_STORE64_BE(&hash[40], S->H[5]); - sha512_STORE64_BE(&hash[48], S->H[6]); - sha512_STORE64_BE(&hash[56], S->H[7]); -} - -static void -crypto_hash_sha512(unsigned char *hash, const unsigned char *in, size_t inlen) { - ed25519_hash_context ctx; - ed25519_hash_init(&ctx); - ed25519_hash_update(&ctx, in, inlen); - ed25519_hash_final(&ctx, hash); -} - -#else - -#include - -static void -crypto_hash_sha512(unsigned char *hash, const unsigned char *in, size_t inlen) { - SHA512(in, inlen, hash); -} - -#endif - - - - -typedef int32_t crypto_int32; -typedef uint32_t crypto_uint32; -typedef int64_t crypto_int64; -typedef uint64_t crypto_uint64; - -typedef crypto_int32 fe[10]; - -/* -h = 0 -*/ - -static void fe_0(fe h) -{ - h[0] = 0; - h[1] = 0; - h[2] = 0; - h[3] = 0; - h[4] = 0; - h[5] = 0; - h[6] = 0; - h[7] = 0; - h[8] = 0; - h[9] = 0; -} - -/* -h = 1 -*/ - -static void fe_1(fe h) -{ - h[0] = 1; - h[1] = 0; - h[2] = 0; - h[3] = 0; - h[4] = 0; - h[5] = 0; - h[6] = 0; - h[7] = 0; - h[8] = 0; - h[9] = 0; -} - -/* -h = f + g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Postconditions: - |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -static void fe_add(fe h,const fe f,const fe g) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 g0 = g[0]; - crypto_int32 g1 = g[1]; - crypto_int32 g2 = g[2]; - crypto_int32 g3 = g[3]; - crypto_int32 g4 = g[4]; - crypto_int32 g5 = g[5]; - crypto_int32 g6 = g[6]; - crypto_int32 g7 = g[7]; - crypto_int32 g8 = g[8]; - crypto_int32 g9 = g[9]; - crypto_int32 h0 = f0 + g0; - crypto_int32 h1 = f1 + g1; - crypto_int32 h2 = f2 + g2; - crypto_int32 h3 = f3 + g3; - crypto_int32 h4 = f4 + g4; - crypto_int32 h5 = f5 + g5; - crypto_int32 h6 = f6 + g6; - crypto_int32 h7 = f7 + g7; - crypto_int32 h8 = f8 + g8; - crypto_int32 h9 = f9 + g9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - - -/* -Replace (f,g) with (g,g) if b == 1; -replace (f,g) with (f,g) if b == 0. - -Preconditions: b in {0,1}. -*/ - -static void fe_cmov(fe f,const fe g,unsigned int b) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 g0 = g[0]; - crypto_int32 g1 = g[1]; - crypto_int32 g2 = g[2]; - crypto_int32 g3 = g[3]; - crypto_int32 g4 = g[4]; - crypto_int32 g5 = g[5]; - crypto_int32 g6 = g[6]; - crypto_int32 g7 = g[7]; - crypto_int32 g8 = g[8]; - crypto_int32 g9 = g[9]; - crypto_int32 x0 = f0 ^ g0; - crypto_int32 x1 = f1 ^ g1; - crypto_int32 x2 = f2 ^ g2; - crypto_int32 x3 = f3 ^ g3; - crypto_int32 x4 = f4 ^ g4; - crypto_int32 x5 = f5 ^ g5; - crypto_int32 x6 = f6 ^ g6; - crypto_int32 x7 = f7 ^ g7; - crypto_int32 x8 = f8 ^ g8; - crypto_int32 x9 = f9 ^ g9; - b = -b; - x0 &= b; - x1 &= b; - x2 &= b; - x3 &= b; - x4 &= b; - x5 &= b; - x6 &= b; - x7 &= b; - x8 &= b; - x9 &= b; - f[0] = f0 ^ x0; - f[1] = f1 ^ x1; - f[2] = f2 ^ x2; - f[3] = f3 ^ x3; - f[4] = f4 ^ x4; - f[5] = f5 ^ x5; - f[6] = f6 ^ x6; - f[7] = f7 ^ x7; - f[8] = f8 ^ x8; - f[9] = f9 ^ x9; -} - - -/* -h = f -*/ - -static void fe_copy(fe h,const fe f) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - h[0] = f0; - h[1] = f1; - h[2] = f2; - h[3] = f3; - h[4] = f4; - h[5] = f5; - h[6] = f6; - h[7] = f7; - h[8] = f8; - h[9] = f9; -} - - -static crypto_uint64 load_3(const unsigned char *in) -{ - crypto_uint64 result; - result = (crypto_uint64) in[0]; - result |= ((crypto_uint64) in[1]) << 8; - result |= ((crypto_uint64) in[2]) << 16; - return result; -} - -static crypto_uint64 load_4(const unsigned char *in) -{ - crypto_uint64 result; - result = (crypto_uint64) in[0]; - result |= ((crypto_uint64) in[1]) << 8; - result |= ((crypto_uint64) in[2]) << 16; - result |= ((crypto_uint64) in[3]) << 24; - return result; -} - -/* -Ignores top bit of h. -*/ - -static void fe_frombytes(fe h,const unsigned char *s) -{ - crypto_int64 h0 = load_4(s); - crypto_int64 h1 = load_3(s + 4) << 6; - crypto_int64 h2 = load_3(s + 7) << 5; - crypto_int64 h3 = load_3(s + 10) << 3; - crypto_int64 h4 = load_3(s + 13) << 2; - crypto_int64 h5 = load_4(s + 16); - crypto_int64 h6 = load_3(s + 20) << 7; - crypto_int64 h7 = load_3(s + 23) << 5; - crypto_int64 h8 = load_3(s + 26) << 4; - crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - - carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -Preconditions: - |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. - -Write p=2^255-19; q=floor(h/p). -Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). - -Proof: - Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. - Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. - - Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). - Then 0> 25; - q = (h0 + q) >> 26; - q = (h1 + q) >> 25; - q = (h2 + q) >> 26; - q = (h3 + q) >> 25; - q = (h4 + q) >> 26; - q = (h5 + q) >> 25; - q = (h6 + q) >> 26; - q = (h7 + q) >> 25; - q = (h8 + q) >> 26; - q = (h9 + q) >> 25; - - /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ - h0 += 19 * q; - /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ - - carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; - carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; - carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; - carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; - carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; - carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; - carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; - carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; - carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; - carry9 = h9 >> 25; h9 -= carry9 << 25; - /* h10 = carry9 */ - - /* - Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. - Have h0+...+2^230 h9 between 0 and 2^255-1; - evidently 2^255 h10-2^255 q = 0. - Goal: Output h0+...+2^230 h9. - */ - - s[0] = h0 >> 0; - s[1] = h0 >> 8; - s[2] = h0 >> 16; - s[3] = (h0 >> 24) | (h1 << 2); - s[4] = h1 >> 6; - s[5] = h1 >> 14; - s[6] = (h1 >> 22) | (h2 << 3); - s[7] = h2 >> 5; - s[8] = h2 >> 13; - s[9] = (h2 >> 21) | (h3 << 5); - s[10] = h3 >> 3; - s[11] = h3 >> 11; - s[12] = (h3 >> 19) | (h4 << 6); - s[13] = h4 >> 2; - s[14] = h4 >> 10; - s[15] = h4 >> 18; - s[16] = h5 >> 0; - s[17] = h5 >> 8; - s[18] = h5 >> 16; - s[19] = (h5 >> 24) | (h6 << 1); - s[20] = h6 >> 7; - s[21] = h6 >> 15; - s[22] = (h6 >> 23) | (h7 << 3); - s[23] = h7 >> 5; - s[24] = h7 >> 13; - s[25] = (h7 >> 21) | (h8 << 4); - s[26] = h8 >> 4; - s[27] = h8 >> 12; - s[28] = (h8 >> 20) | (h9 << 6); - s[29] = h9 >> 2; - s[30] = h9 >> 10; - s[31] = h9 >> 18; -} - - -/* -h = f - g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Postconditions: - |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -static void fe_sub(fe h,const fe f,const fe g) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 g0 = g[0]; - crypto_int32 g1 = g[1]; - crypto_int32 g2 = g[2]; - crypto_int32 g3 = g[3]; - crypto_int32 g4 = g[4]; - crypto_int32 g5 = g[5]; - crypto_int32 g6 = g[6]; - crypto_int32 g7 = g[7]; - crypto_int32 g8 = g[8]; - crypto_int32 g9 = g[9]; - crypto_int32 h0 = f0 - g0; - crypto_int32 h1 = f1 - g1; - crypto_int32 h2 = f2 - g2; - crypto_int32 h3 = f3 - g3; - crypto_int32 h4 = f4 - g4; - crypto_int32 h5 = f5 - g5; - crypto_int32 h6 = f6 - g6; - crypto_int32 h7 = f7 - g7; - crypto_int32 h8 = f8 - g8; - crypto_int32 h9 = f9 - g9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - - -/* -h = f * f -Can overlap h with f. - -Preconditions: - |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. - -Postconditions: - |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -*/ - -/* -See fe_mul.c for discussion of implementation strategy. -*/ - -static void fe_sq(fe h,const fe f) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 f0_2 = 2 * f0; - crypto_int32 f1_2 = 2 * f1; - crypto_int32 f2_2 = 2 * f2; - crypto_int32 f3_2 = 2 * f3; - crypto_int32 f4_2 = 2 * f4; - crypto_int32 f5_2 = 2 * f5; - crypto_int32 f6_2 = 2 * f6; - crypto_int32 f7_2 = 2 * f7; - crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */ - crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */ - crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */ - crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */ - crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */ - crypto_int64 f0f0 = f0 * (crypto_int64) f0; - crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1; - crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2; - crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3; - crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4; - crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5; - crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6; - crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7; - crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8; - crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9; - crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1; - crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2; - crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2; - crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4; - crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2; - crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6; - crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2; - crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8; - crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38; - crypto_int64 f2f2 = f2 * (crypto_int64) f2; - crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3; - crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4; - crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5; - crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6; - crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7; - crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19; - crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38; - crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3; - crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4; - crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2; - crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6; - crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38; - crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19; - crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38; - crypto_int64 f4f4 = f4 * (crypto_int64) f4; - crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5; - crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19; - crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38; - crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19; - crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38; - crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38; - crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19; - crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38; - crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19; - crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38; - crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19; - crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38; - crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19; - crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38; - crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38; - crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19; - crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38; - crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19; - crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38; - crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38; - crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; - crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; - crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; - crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; - crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; - crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; - crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; - crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; - crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; - crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - - carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - - carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - - carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -h = 2 * f * f -Can overlap h with f. - -Preconditions: - |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. - -Postconditions: - |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -*/ - -/* -See fe_mul.c for discussion of implementation strategy. -*/ - -static void fe_sq2(fe h,const fe f) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 f0_2 = 2 * f0; - crypto_int32 f1_2 = 2 * f1; - crypto_int32 f2_2 = 2 * f2; - crypto_int32 f3_2 = 2 * f3; - crypto_int32 f4_2 = 2 * f4; - crypto_int32 f5_2 = 2 * f5; - crypto_int32 f6_2 = 2 * f6; - crypto_int32 f7_2 = 2 * f7; - crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */ - crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */ - crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */ - crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */ - crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */ - crypto_int64 f0f0 = f0 * (crypto_int64) f0; - crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1; - crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2; - crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3; - crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4; - crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5; - crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6; - crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7; - crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8; - crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9; - crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1; - crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2; - crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2; - crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4; - crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2; - crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6; - crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2; - crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8; - crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38; - crypto_int64 f2f2 = f2 * (crypto_int64) f2; - crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3; - crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4; - crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5; - crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6; - crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7; - crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19; - crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38; - crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3; - crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4; - crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2; - crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6; - crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38; - crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19; - crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38; - crypto_int64 f4f4 = f4 * (crypto_int64) f4; - crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5; - crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19; - crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38; - crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19; - crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38; - crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38; - crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19; - crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38; - crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19; - crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38; - crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19; - crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38; - crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19; - crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38; - crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38; - crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19; - crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38; - crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19; - crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38; - crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38; - crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; - crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; - crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; - crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; - crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; - crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; - crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; - crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; - crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; - crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - - h0 += h0; - h1 += h1; - h2 += h2; - h3 += h3; - h4 += h4; - h5 += h5; - h6 += h6; - h7 += h7; - h8 += h8; - h9 += h9; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - - carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - - carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - - carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - - carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -/* -h = f * g -Can overlap h with f or g. - -Preconditions: - |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. - |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. - -Postconditions: - |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. -*/ - -/* -Notes on implementation strategy: - -Using schoolbook multiplication. -Karatsuba would save a little in some cost models. - -Most multiplications by 2 and 19 are 32-bit precomputations; -cheaper than 64-bit postcomputations. - -There is one remaining multiplication by 19 in the carry chain; -one *19 precomputation can be merged into this, -but the resulting data flow is considerably less clean. - -There are 12 carries below. -10 of them are 2-way parallelizable and vectorizable. -Can get away with 11 carries, but then data flow is much deeper. - -With tighter constraints on inputs can squeeze carries into int32. -*/ - -static void fe_mul(fe h,const fe f,const fe g) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 g0 = g[0]; - crypto_int32 g1 = g[1]; - crypto_int32 g2 = g[2]; - crypto_int32 g3 = g[3]; - crypto_int32 g4 = g[4]; - crypto_int32 g5 = g[5]; - crypto_int32 g6 = g[6]; - crypto_int32 g7 = g[7]; - crypto_int32 g8 = g[8]; - crypto_int32 g9 = g[9]; - crypto_int32 g1_19 = 19 * g1; /* 1.959375*2^29 */ - crypto_int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ - crypto_int32 g3_19 = 19 * g3; - crypto_int32 g4_19 = 19 * g4; - crypto_int32 g5_19 = 19 * g5; - crypto_int32 g6_19 = 19 * g6; - crypto_int32 g7_19 = 19 * g7; - crypto_int32 g8_19 = 19 * g8; - crypto_int32 g9_19 = 19 * g9; - crypto_int32 f1_2 = 2 * f1; - crypto_int32 f3_2 = 2 * f3; - crypto_int32 f5_2 = 2 * f5; - crypto_int32 f7_2 = 2 * f7; - crypto_int32 f9_2 = 2 * f9; - crypto_int64 f0g0 = f0 * (crypto_int64) g0; - crypto_int64 f0g1 = f0 * (crypto_int64) g1; - crypto_int64 f0g2 = f0 * (crypto_int64) g2; - crypto_int64 f0g3 = f0 * (crypto_int64) g3; - crypto_int64 f0g4 = f0 * (crypto_int64) g4; - crypto_int64 f0g5 = f0 * (crypto_int64) g5; - crypto_int64 f0g6 = f0 * (crypto_int64) g6; - crypto_int64 f0g7 = f0 * (crypto_int64) g7; - crypto_int64 f0g8 = f0 * (crypto_int64) g8; - crypto_int64 f0g9 = f0 * (crypto_int64) g9; - crypto_int64 f1g0 = f1 * (crypto_int64) g0; - crypto_int64 f1g1_2 = f1_2 * (crypto_int64) g1; - crypto_int64 f1g2 = f1 * (crypto_int64) g2; - crypto_int64 f1g3_2 = f1_2 * (crypto_int64) g3; - crypto_int64 f1g4 = f1 * (crypto_int64) g4; - crypto_int64 f1g5_2 = f1_2 * (crypto_int64) g5; - crypto_int64 f1g6 = f1 * (crypto_int64) g6; - crypto_int64 f1g7_2 = f1_2 * (crypto_int64) g7; - crypto_int64 f1g8 = f1 * (crypto_int64) g8; - crypto_int64 f1g9_38 = f1_2 * (crypto_int64) g9_19; - crypto_int64 f2g0 = f2 * (crypto_int64) g0; - crypto_int64 f2g1 = f2 * (crypto_int64) g1; - crypto_int64 f2g2 = f2 * (crypto_int64) g2; - crypto_int64 f2g3 = f2 * (crypto_int64) g3; - crypto_int64 f2g4 = f2 * (crypto_int64) g4; - crypto_int64 f2g5 = f2 * (crypto_int64) g5; - crypto_int64 f2g6 = f2 * (crypto_int64) g6; - crypto_int64 f2g7 = f2 * (crypto_int64) g7; - crypto_int64 f2g8_19 = f2 * (crypto_int64) g8_19; - crypto_int64 f2g9_19 = f2 * (crypto_int64) g9_19; - crypto_int64 f3g0 = f3 * (crypto_int64) g0; - crypto_int64 f3g1_2 = f3_2 * (crypto_int64) g1; - crypto_int64 f3g2 = f3 * (crypto_int64) g2; - crypto_int64 f3g3_2 = f3_2 * (crypto_int64) g3; - crypto_int64 f3g4 = f3 * (crypto_int64) g4; - crypto_int64 f3g5_2 = f3_2 * (crypto_int64) g5; - crypto_int64 f3g6 = f3 * (crypto_int64) g6; - crypto_int64 f3g7_38 = f3_2 * (crypto_int64) g7_19; - crypto_int64 f3g8_19 = f3 * (crypto_int64) g8_19; - crypto_int64 f3g9_38 = f3_2 * (crypto_int64) g9_19; - crypto_int64 f4g0 = f4 * (crypto_int64) g0; - crypto_int64 f4g1 = f4 * (crypto_int64) g1; - crypto_int64 f4g2 = f4 * (crypto_int64) g2; - crypto_int64 f4g3 = f4 * (crypto_int64) g3; - crypto_int64 f4g4 = f4 * (crypto_int64) g4; - crypto_int64 f4g5 = f4 * (crypto_int64) g5; - crypto_int64 f4g6_19 = f4 * (crypto_int64) g6_19; - crypto_int64 f4g7_19 = f4 * (crypto_int64) g7_19; - crypto_int64 f4g8_19 = f4 * (crypto_int64) g8_19; - crypto_int64 f4g9_19 = f4 * (crypto_int64) g9_19; - crypto_int64 f5g0 = f5 * (crypto_int64) g0; - crypto_int64 f5g1_2 = f5_2 * (crypto_int64) g1; - crypto_int64 f5g2 = f5 * (crypto_int64) g2; - crypto_int64 f5g3_2 = f5_2 * (crypto_int64) g3; - crypto_int64 f5g4 = f5 * (crypto_int64) g4; - crypto_int64 f5g5_38 = f5_2 * (crypto_int64) g5_19; - crypto_int64 f5g6_19 = f5 * (crypto_int64) g6_19; - crypto_int64 f5g7_38 = f5_2 * (crypto_int64) g7_19; - crypto_int64 f5g8_19 = f5 * (crypto_int64) g8_19; - crypto_int64 f5g9_38 = f5_2 * (crypto_int64) g9_19; - crypto_int64 f6g0 = f6 * (crypto_int64) g0; - crypto_int64 f6g1 = f6 * (crypto_int64) g1; - crypto_int64 f6g2 = f6 * (crypto_int64) g2; - crypto_int64 f6g3 = f6 * (crypto_int64) g3; - crypto_int64 f6g4_19 = f6 * (crypto_int64) g4_19; - crypto_int64 f6g5_19 = f6 * (crypto_int64) g5_19; - crypto_int64 f6g6_19 = f6 * (crypto_int64) g6_19; - crypto_int64 f6g7_19 = f6 * (crypto_int64) g7_19; - crypto_int64 f6g8_19 = f6 * (crypto_int64) g8_19; - crypto_int64 f6g9_19 = f6 * (crypto_int64) g9_19; - crypto_int64 f7g0 = f7 * (crypto_int64) g0; - crypto_int64 f7g1_2 = f7_2 * (crypto_int64) g1; - crypto_int64 f7g2 = f7 * (crypto_int64) g2; - crypto_int64 f7g3_38 = f7_2 * (crypto_int64) g3_19; - crypto_int64 f7g4_19 = f7 * (crypto_int64) g4_19; - crypto_int64 f7g5_38 = f7_2 * (crypto_int64) g5_19; - crypto_int64 f7g6_19 = f7 * (crypto_int64) g6_19; - crypto_int64 f7g7_38 = f7_2 * (crypto_int64) g7_19; - crypto_int64 f7g8_19 = f7 * (crypto_int64) g8_19; - crypto_int64 f7g9_38 = f7_2 * (crypto_int64) g9_19; - crypto_int64 f8g0 = f8 * (crypto_int64) g0; - crypto_int64 f8g1 = f8 * (crypto_int64) g1; - crypto_int64 f8g2_19 = f8 * (crypto_int64) g2_19; - crypto_int64 f8g3_19 = f8 * (crypto_int64) g3_19; - crypto_int64 f8g4_19 = f8 * (crypto_int64) g4_19; - crypto_int64 f8g5_19 = f8 * (crypto_int64) g5_19; - crypto_int64 f8g6_19 = f8 * (crypto_int64) g6_19; - crypto_int64 f8g7_19 = f8 * (crypto_int64) g7_19; - crypto_int64 f8g8_19 = f8 * (crypto_int64) g8_19; - crypto_int64 f8g9_19 = f8 * (crypto_int64) g9_19; - crypto_int64 f9g0 = f9 * (crypto_int64) g0; - crypto_int64 f9g1_38 = f9_2 * (crypto_int64) g1_19; - crypto_int64 f9g2_19 = f9 * (crypto_int64) g2_19; - crypto_int64 f9g3_38 = f9_2 * (crypto_int64) g3_19; - crypto_int64 f9g4_19 = f9 * (crypto_int64) g4_19; - crypto_int64 f9g5_38 = f9_2 * (crypto_int64) g5_19; - crypto_int64 f9g6_19 = f9 * (crypto_int64) g6_19; - crypto_int64 f9g7_38 = f9_2 * (crypto_int64) g7_19; - crypto_int64 f9g8_19 = f9 * (crypto_int64) g8_19; - crypto_int64 f9g9_38 = f9_2 * (crypto_int64) g9_19; - crypto_int64 h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38; - crypto_int64 h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19; - crypto_int64 h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38; - crypto_int64 h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19; - crypto_int64 h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38; - crypto_int64 h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19; - crypto_int64 h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38; - crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; - crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; - crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - - /* - |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) - i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 - |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) - i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 - */ - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - /* |h0| <= 2^25 */ - /* |h4| <= 2^25 */ - /* |h1| <= 1.71*2^59 */ - /* |h5| <= 1.71*2^59 */ - - carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - /* |h1| <= 2^24; from now on fits into int32 */ - /* |h5| <= 2^24; from now on fits into int32 */ - /* |h2| <= 1.41*2^60 */ - /* |h6| <= 1.41*2^60 */ - - carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - /* |h2| <= 2^25; from now on fits into int32 unchanged */ - /* |h6| <= 2^25; from now on fits into int32 unchanged */ - /* |h3| <= 1.71*2^59 */ - /* |h7| <= 1.71*2^59 */ - - carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - /* |h3| <= 2^24; from now on fits into int32 unchanged */ - /* |h7| <= 2^24; from now on fits into int32 unchanged */ - /* |h4| <= 1.72*2^34 */ - /* |h8| <= 1.41*2^60 */ - - carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - /* |h4| <= 2^25; from now on fits into int32 unchanged */ - /* |h8| <= 2^25; from now on fits into int32 unchanged */ - /* |h5| <= 1.01*2^24 */ - /* |h9| <= 1.71*2^59 */ - - carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - /* |h9| <= 2^24; from now on fits into int32 unchanged */ - /* |h0| <= 1.1*2^39 */ - - carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - /* |h0| <= 2^25; from now on fits into int32 unchanged */ - /* |h1| <= 1.01*2^24 */ - - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - - -/* -return 1 if f is in {1,3,5,...,q-2} -return 0 if f is in {0,2,4,...,q-1} - -Preconditions: - |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -static int fe_isnegative(const fe f) -{ - unsigned char s[32]; - fe_tobytes(s,f); - return s[0] & 1; -} - - -/* -return 1 if f == 0 -return 0 if f != 0 - -Preconditions: - |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. -*/ - -static const unsigned char zero[32] = {0}; - -static int fe_isnonzero(const fe f) -{ - unsigned char s[32]; - fe_tobytes(s,f); - return crypto_verify_32(s,zero); -} - -/* -h = -f - -Preconditions: - |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. - -Postconditions: - |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. -*/ - -static void fe_neg(fe h,const fe f) -{ - crypto_int32 f0 = f[0]; - crypto_int32 f1 = f[1]; - crypto_int32 f2 = f[2]; - crypto_int32 f3 = f[3]; - crypto_int32 f4 = f[4]; - crypto_int32 f5 = f[5]; - crypto_int32 f6 = f[6]; - crypto_int32 f7 = f[7]; - crypto_int32 f8 = f[8]; - crypto_int32 f9 = f[9]; - crypto_int32 h0 = -f0; - crypto_int32 h1 = -f1; - crypto_int32 h2 = -f2; - crypto_int32 h3 = -f3; - crypto_int32 h4 = -f4; - crypto_int32 h5 = -f5; - crypto_int32 h6 = -f6; - crypto_int32 h7 = -f7; - crypto_int32 h8 = -f8; - crypto_int32 h9 = -f9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; -} - -static void fe_invert(fe out,const fe z) -{ - fe t0; - fe t1; - fe t2; - fe t3; - int i; - - -/* qhasm: fe z1 */ - -/* qhasm: fe z2 */ - -/* qhasm: fe z8 */ - -/* qhasm: fe z9 */ - -/* qhasm: fe z11 */ - -/* qhasm: fe z22 */ - -/* qhasm: fe z_5_0 */ - -/* qhasm: fe z_10_5 */ - -/* qhasm: fe z_10_0 */ - -/* qhasm: fe z_20_10 */ - -/* qhasm: fe z_20_0 */ - -/* qhasm: fe z_40_20 */ - -/* qhasm: fe z_40_0 */ - -/* qhasm: fe z_50_10 */ - -/* qhasm: fe z_50_0 */ - -/* qhasm: fe z_100_50 */ - -/* qhasm: fe z_100_0 */ - -/* qhasm: fe z_200_100 */ - -/* qhasm: fe z_200_0 */ - -/* qhasm: fe z_250_50 */ - -/* qhasm: fe z_250_0 */ - -/* qhasm: fe z_255_5 */ - -/* qhasm: fe z_255_21 */ - -/* qhasm: enter pow225521 */ - -/* qhasm: z2 = z1^2^1 */ -/* asm 1: fe_sq(>z2=fe#1,z2=fe#1,>z2=fe#1); */ -/* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ -fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); - -/* qhasm: z8 = z2^2^2 */ -/* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ -/* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ -fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); - -/* qhasm: z9 = z1*z8 */ -/* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#3,z22=fe#3,>z22=fe#3); */ -/* asm 2: fe_sq(>z22=t2,z22=t2,>z22=t2); */ -fe_sq(t2,t0); for (i = 1;i < 1;++i) fe_sq(t2,t2); - -/* qhasm: z_5_0 = z9*z22 */ -/* asm 1: fe_mul(>z_5_0=fe#2,z_5_0=t1,z_10_5=fe#3,z_10_5=fe#3,>z_10_5=fe#3); */ -/* asm 2: fe_sq(>z_10_5=t2,z_10_5=t2,>z_10_5=t2); */ -fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2); - -/* qhasm: z_10_0 = z_10_5*z_5_0 */ -/* asm 1: fe_mul(>z_10_0=fe#2,z_10_0=t1,z_20_10=fe#3,z_20_10=fe#3,>z_20_10=fe#3); */ -/* asm 2: fe_sq(>z_20_10=t2,z_20_10=t2,>z_20_10=t2); */ -fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2); - -/* qhasm: z_20_0 = z_20_10*z_10_0 */ -/* asm 1: fe_mul(>z_20_0=fe#3,z_20_0=t2,z_40_20=fe#4,z_40_20=fe#4,>z_40_20=fe#4); */ -/* asm 2: fe_sq(>z_40_20=t3,z_40_20=t3,>z_40_20=t3); */ -fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3); - -/* qhasm: z_40_0 = z_40_20*z_20_0 */ -/* asm 1: fe_mul(>z_40_0=fe#3,z_40_0=t2,z_50_10=fe#3,z_50_10=fe#3,>z_50_10=fe#3); */ -/* asm 2: fe_sq(>z_50_10=t2,z_50_10=t2,>z_50_10=t2); */ -fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2); - -/* qhasm: z_50_0 = z_50_10*z_10_0 */ -/* asm 1: fe_mul(>z_50_0=fe#2,z_50_0=t1,z_100_50=fe#3,z_100_50=fe#3,>z_100_50=fe#3); */ -/* asm 2: fe_sq(>z_100_50=t2,z_100_50=t2,>z_100_50=t2); */ -fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2); - -/* qhasm: z_100_0 = z_100_50*z_50_0 */ -/* asm 1: fe_mul(>z_100_0=fe#3,z_100_0=t2,z_200_100=fe#4,z_200_100=fe#4,>z_200_100=fe#4); */ -/* asm 2: fe_sq(>z_200_100=t3,z_200_100=t3,>z_200_100=t3); */ -fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3); - -/* qhasm: z_200_0 = z_200_100*z_100_0 */ -/* asm 1: fe_mul(>z_200_0=fe#3,z_200_0=t2,z_250_50=fe#3,z_250_50=fe#3,>z_250_50=fe#3); */ -/* asm 2: fe_sq(>z_250_50=t2,z_250_50=t2,>z_250_50=t2); */ -fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2); - -/* qhasm: z_250_0 = z_250_50*z_50_0 */ -/* asm 1: fe_mul(>z_250_0=fe#2,z_250_0=t1,z_255_5=fe#2,z_255_5=fe#2,>z_255_5=fe#2); */ -/* asm 2: fe_sq(>z_255_5=t1,z_255_5=t1,>z_255_5=t1); */ -fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1); - -/* qhasm: z_255_21 = z_255_5*z11 */ -/* asm 1: fe_mul(>z_255_21=fe#12,z_255_21=out,z2=fe#1,z2=fe#1,>z2=fe#1); */ -/* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ -fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); - -/* qhasm: z8 = z2^2^2 */ -/* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ -/* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ -fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); - -/* qhasm: z9 = z1*z8 */ -/* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#1,z22=fe#1,>z22=fe#1); */ -/* asm 2: fe_sq(>z22=t0,z22=t0,>z22=t0); */ -fe_sq(t0,t0); for (i = 1;i < 1;++i) fe_sq(t0,t0); - -/* qhasm: z_5_0 = z9*z22 */ -/* asm 1: fe_mul(>z_5_0=fe#1,z_5_0=t0,z_10_5=fe#2,z_10_5=fe#2,>z_10_5=fe#2); */ -/* asm 2: fe_sq(>z_10_5=t1,z_10_5=t1,>z_10_5=t1); */ -fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1); - -/* qhasm: z_10_0 = z_10_5*z_5_0 */ -/* asm 1: fe_mul(>z_10_0=fe#1,z_10_0=t0,z_20_10=fe#2,z_20_10=fe#2,>z_20_10=fe#2); */ -/* asm 2: fe_sq(>z_20_10=t1,z_20_10=t1,>z_20_10=t1); */ -fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1); - -/* qhasm: z_20_0 = z_20_10*z_10_0 */ -/* asm 1: fe_mul(>z_20_0=fe#2,z_20_0=t1,z_40_20=fe#3,z_40_20=fe#3,>z_40_20=fe#3); */ -/* asm 2: fe_sq(>z_40_20=t2,z_40_20=t2,>z_40_20=t2); */ -fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2); - -/* qhasm: z_40_0 = z_40_20*z_20_0 */ -/* asm 1: fe_mul(>z_40_0=fe#2,z_40_0=t1,z_50_10=fe#2,z_50_10=fe#2,>z_50_10=fe#2); */ -/* asm 2: fe_sq(>z_50_10=t1,z_50_10=t1,>z_50_10=t1); */ -fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1); - -/* qhasm: z_50_0 = z_50_10*z_10_0 */ -/* asm 1: fe_mul(>z_50_0=fe#1,z_50_0=t0,z_100_50=fe#2,z_100_50=fe#2,>z_100_50=fe#2); */ -/* asm 2: fe_sq(>z_100_50=t1,z_100_50=t1,>z_100_50=t1); */ -fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1); - -/* qhasm: z_100_0 = z_100_50*z_50_0 */ -/* asm 1: fe_mul(>z_100_0=fe#2,z_100_0=t1,z_200_100=fe#3,z_200_100=fe#3,>z_200_100=fe#3); */ -/* asm 2: fe_sq(>z_200_100=t2,z_200_100=t2,>z_200_100=t2); */ -fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2); - -/* qhasm: z_200_0 = z_200_100*z_100_0 */ -/* asm 1: fe_mul(>z_200_0=fe#2,z_200_0=t1,z_250_50=fe#2,z_250_50=fe#2,>z_250_50=fe#2); */ -/* asm 2: fe_sq(>z_250_50=t1,z_250_50=t1,>z_250_50=t1); */ -fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1); - -/* qhasm: z_250_0 = z_250_50*z_50_0 */ -/* asm 1: fe_mul(>z_250_0=fe#1,z_250_0=t0,z_252_2=fe#1,z_252_2=fe#1,>z_252_2=fe#1); */ -/* asm 2: fe_sq(>z_252_2=t0,z_252_2=t0,>z_252_2=t0); */ -fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0); - -/* qhasm: z_252_3 = z_252_2*z1 */ -/* asm 1: fe_mul(>z_252_3=fe#12,z_252_3=out,X); - fe_1(h->Y); - fe_1(h->Z); -} - -static void ge_p3_0(ge_p3 *h) -{ - fe_0(h->X); - fe_1(h->Y); - fe_1(h->Z); - fe_0(h->T); -} - -static void ge_precomp_0(ge_precomp *h) -{ - fe_1(h->yplusx); - fe_1(h->yminusx); - fe_0(h->xy2d); -} - -/* -r = p -*/ - -static void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) -{ - fe_mul(r->X,p->X,p->T); - fe_mul(r->Y,p->Y,p->Z); - fe_mul(r->Z,p->Z,p->T); -} - -/* -r = p -*/ - -static void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) -{ - fe_mul(r->X,p->X,p->T); - fe_mul(r->Y,p->Y,p->Z); - fe_mul(r->Z,p->Z,p->T); - fe_mul(r->T,p->X,p->Y); -} - -/* -r = p -*/ - -static void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) -{ - fe_copy(r->X,p->X); - fe_copy(r->Y,p->Y); - fe_copy(r->Z,p->Z); -} - - -/* -r = 2 * p -*/ - -static void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) -{ - fe t0; -/* qhasm: enter ge_p2_dbl */ - -/* qhasm: fe X1 */ - -/* qhasm: fe Y1 */ - -/* qhasm: fe Z1 */ - -/* qhasm: fe A */ - -/* qhasm: fe AA */ - -/* qhasm: fe XX */ - -/* qhasm: fe YY */ - -/* qhasm: fe B */ - -/* qhasm: fe X3 */ - -/* qhasm: fe Y3 */ - -/* qhasm: fe Z3 */ - -/* qhasm: fe T3 */ - -/* qhasm: XX=X1^2 */ -/* asm 1: fe_sq(>XX=fe#1,XX=r->X,X); */ -fe_sq(r->X,p->X); - -/* qhasm: YY=Y1^2 */ -/* asm 1: fe_sq(>YY=fe#3,YY=r->Z,Y); */ -fe_sq(r->Z,p->Y); - -/* qhasm: B=2*Z1^2 */ -/* asm 1: fe_sq2(>B=fe#4,B=r->T,Z); */ -fe_sq2(r->T,p->Z); - -/* qhasm: A=X1+Y1 */ -/* asm 1: fe_add(>A=fe#2,A=r->Y,X,Y); */ -fe_add(r->Y,p->X,p->Y); - -/* qhasm: AA=A^2 */ -/* asm 1: fe_sq(>AA=fe#5,AA=t0,Y); */ -fe_sq(t0,r->Y); - -/* qhasm: Y3=YY+XX */ -/* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,X); */ -fe_add(r->Y,r->Z,r->X); - -/* qhasm: Z3=YY-XX */ -/* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,Z,X); */ -fe_sub(r->Z,r->Z,r->X); - -/* qhasm: X3=AA-Y3 */ -/* asm 1: fe_sub(>X3=fe#1,X3=r->X,Y); */ -fe_sub(r->X,t0,r->Y); - -/* qhasm: T3=B-Z3 */ -/* asm 1: fe_sub(>T3=fe#4,T3=r->T,T,Z); */ -fe_sub(r->T,r->T,r->Z); - -/* qhasm: return */ -} - - -/* -r = 2 * p -*/ - -static void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) -{ - ge_p2 q; - ge_p3_to_p2(&q,p); - ge_p2_dbl(r,&q); -} - - -/* -r = p -*/ - -static void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) -{ - fe_add(r->YplusX,p->Y,p->X); - fe_sub(r->YminusX,p->Y,p->X); - fe_copy(r->Z,p->Z); - fe_mul(r->T2d,p->T,d2); -} - -/* -r = p + q -*/ - -static void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) -{ - fe t0; -/* qhasm: enter ge_add */ - -/* qhasm: fe X1 */ - -/* qhasm: fe Y1 */ - -/* qhasm: fe Z1 */ - -/* qhasm: fe Z2 */ - -/* qhasm: fe T1 */ - -/* qhasm: fe ZZ */ - -/* qhasm: fe YpX2 */ - -/* qhasm: fe YmX2 */ - -/* qhasm: fe T2d2 */ - -/* qhasm: fe X3 */ - -/* qhasm: fe Y3 */ - -/* qhasm: fe Z3 */ - -/* qhasm: fe T3 */ - -/* qhasm: fe YpX1 */ - -/* qhasm: fe YmX1 */ - -/* qhasm: fe A */ - -/* qhasm: fe B */ - -/* qhasm: fe C */ - -/* qhasm: fe D */ - -/* qhasm: YpX1 = Y1+X1 */ -/* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ -fe_add(r->X,p->Y,p->X); - -/* qhasm: YmX1 = Y1-X1 */ -/* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ -fe_sub(r->Y,p->Y,p->X); - -/* qhasm: A = YpX1*YpX2 */ -/* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YplusX); */ -fe_mul(r->Z,r->X,q->YplusX); - -/* qhasm: B = YmX1*YmX2 */ -/* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YminusX); */ -fe_mul(r->Y,r->Y,q->YminusX); - -/* qhasm: C = T2d2*T1 */ -/* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */ -fe_mul(r->T,q->T2d,p->T); - -/* qhasm: ZZ = Z1*Z2 */ -/* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */ -fe_mul(r->X,p->Z,q->Z); - -/* qhasm: D = 2*ZZ */ -/* asm 1: fe_add(>D=fe#5,D=t0,X,X); */ -fe_add(t0,r->X,r->X); - -/* qhasm: X3 = A-B */ -/* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ -fe_sub(r->X,r->Z,r->Y); - -/* qhasm: Y3 = A+B */ -/* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ -fe_add(r->Y,r->Z,r->Y); - -/* qhasm: Z3 = D+C */ -/* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */ -fe_add(r->Z,t0,r->T); - -/* qhasm: T3 = D-C */ -/* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */ -fe_sub(r->T,t0,r->T); - -/* qhasm: return */ -} - - -/* -r = p - q -*/ - -static void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) -{ - fe t0; -/* qhasm: enter ge_sub */ - -/* qhasm: fe X1 */ - -/* qhasm: fe Y1 */ - -/* qhasm: fe Z1 */ - -/* qhasm: fe Z2 */ - -/* qhasm: fe T1 */ - -/* qhasm: fe ZZ */ - -/* qhasm: fe YpX2 */ - -/* qhasm: fe YmX2 */ - -/* qhasm: fe T2d2 */ - -/* qhasm: fe X3 */ - -/* qhasm: fe Y3 */ - -/* qhasm: fe Z3 */ - -/* qhasm: fe T3 */ - -/* qhasm: fe YpX1 */ - -/* qhasm: fe YmX1 */ - -/* qhasm: fe A */ - -/* qhasm: fe B */ - -/* qhasm: fe C */ - -/* qhasm: fe D */ - -/* qhasm: YpX1 = Y1+X1 */ -/* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ -fe_add(r->X,p->Y,p->X); - -/* qhasm: YmX1 = Y1-X1 */ -/* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ -fe_sub(r->Y,p->Y,p->X); - -/* qhasm: A = YpX1*YmX2 */ -/* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YminusX); */ -fe_mul(r->Z,r->X,q->YminusX); - -/* qhasm: B = YmX1*YpX2 */ -/* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YplusX); */ -fe_mul(r->Y,r->Y,q->YplusX); - -/* qhasm: C = T2d2*T1 */ -/* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */ -fe_mul(r->T,q->T2d,p->T); - -/* qhasm: ZZ = Z1*Z2 */ -/* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */ -fe_mul(r->X,p->Z,q->Z); - -/* qhasm: D = 2*ZZ */ -/* asm 1: fe_add(>D=fe#5,D=t0,X,X); */ -fe_add(t0,r->X,r->X); - -/* qhasm: X3 = A-B */ -/* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ -fe_sub(r->X,r->Z,r->Y); - -/* qhasm: Y3 = A+B */ -/* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ -fe_add(r->Y,r->Z,r->Y); - -/* qhasm: Z3 = D-C */ -/* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */ -fe_sub(r->Z,t0,r->T); - -/* qhasm: T3 = D+C */ -/* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */ -fe_add(r->T,t0,r->T); - -/* qhasm: return */ -} - - -/* -r = p + q -*/ - -static void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) -{ - fe t0; -/* qhasm: enter ge_madd */ - -/* qhasm: fe X1 */ - -/* qhasm: fe Y1 */ - -/* qhasm: fe Z1 */ - -/* qhasm: fe T1 */ - -/* qhasm: fe ypx2 */ - -/* qhasm: fe ymx2 */ - -/* qhasm: fe xy2d2 */ - -/* qhasm: fe X3 */ - -/* qhasm: fe Y3 */ - -/* qhasm: fe Z3 */ - -/* qhasm: fe T3 */ - -/* qhasm: fe YpX1 */ - -/* qhasm: fe YmX1 */ - -/* qhasm: fe A */ - -/* qhasm: fe B */ - -/* qhasm: fe C */ - -/* qhasm: fe D */ - -/* qhasm: YpX1 = Y1+X1 */ -/* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ -fe_add(r->X,p->Y,p->X); - -/* qhasm: YmX1 = Y1-X1 */ -/* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ -fe_sub(r->Y,p->Y,p->X); - -/* qhasm: A = YpX1*ypx2 */ -/* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yplusx); */ -fe_mul(r->Z,r->X,q->yplusx); - -/* qhasm: B = YmX1*ymx2 */ -/* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yminusx); */ -fe_mul(r->Y,r->Y,q->yminusx); - -/* qhasm: C = xy2d2*T1 */ -/* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */ -fe_mul(r->T,q->xy2d,p->T); - -/* qhasm: D = 2*Z1 */ -/* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */ -fe_add(t0,p->Z,p->Z); - -/* qhasm: X3 = A-B */ -/* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ -fe_sub(r->X,r->Z,r->Y); - -/* qhasm: Y3 = A+B */ -/* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ -fe_add(r->Y,r->Z,r->Y); - -/* qhasm: Z3 = D+C */ -/* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */ -fe_add(r->Z,t0,r->T); - -/* qhasm: T3 = D-C */ -/* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */ -fe_sub(r->T,t0,r->T); - -/* qhasm: return */ -} - - -/* -r = p - q -*/ - -static void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) -{ - fe t0; -/* qhasm: enter ge_msub */ - -/* qhasm: fe X1 */ - -/* qhasm: fe Y1 */ - -/* qhasm: fe Z1 */ - -/* qhasm: fe T1 */ - -/* qhasm: fe ypx2 */ - -/* qhasm: fe ymx2 */ - -/* qhasm: fe xy2d2 */ - -/* qhasm: fe X3 */ - -/* qhasm: fe Y3 */ - -/* qhasm: fe Z3 */ - -/* qhasm: fe T3 */ - -/* qhasm: fe YpX1 */ - -/* qhasm: fe YmX1 */ - -/* qhasm: fe A */ - -/* qhasm: fe B */ - -/* qhasm: fe C */ - -/* qhasm: fe D */ - -/* qhasm: YpX1 = Y1+X1 */ -/* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ -fe_add(r->X,p->Y,p->X); - -/* qhasm: YmX1 = Y1-X1 */ -/* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ -fe_sub(r->Y,p->Y,p->X); - -/* qhasm: A = YpX1*ymx2 */ -/* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yminusx); */ -fe_mul(r->Z,r->X,q->yminusx); - -/* qhasm: B = YmX1*ypx2 */ -/* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yplusx); */ -fe_mul(r->Y,r->Y,q->yplusx); - -/* qhasm: C = xy2d2*T1 */ -/* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */ -fe_mul(r->T,q->xy2d,p->T); - -/* qhasm: D = 2*Z1 */ -/* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */ -fe_add(t0,p->Z,p->Z); - -/* qhasm: X3 = A-B */ -/* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ -fe_sub(r->X,r->Z,r->Y); - -/* qhasm: Y3 = A+B */ -/* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ -fe_add(r->Y,r->Z,r->Y); - -/* qhasm: Z3 = D-C */ -/* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */ -fe_sub(r->Z,t0,r->T); - -/* qhasm: T3 = D+C */ -/* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */ -fe_add(r->T,t0,r->T); - -/* qhasm: return */ -} - - -static void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) -{ - fe recip; - fe x; - fe y; - - fe_invert(recip,h->Z); - fe_mul(x,h->X,recip); - fe_mul(y,h->Y,recip); - fe_tobytes(s,y); - s[31] ^= fe_isnegative(x) << 7; -} - -static void ge_tobytes(unsigned char *s,const ge_p2 *h) -{ - fe recip; - fe x; - fe y; - - fe_invert(recip,h->Z); - fe_mul(x,h->X,recip); - fe_mul(y,h->Y,recip); - fe_tobytes(s,y); - s[31] ^= fe_isnegative(x) << 7; -} - -static int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) -{ - fe u; - fe v; - fe v3; - fe vxx; - fe check; - - fe_frombytes(h->Y,s); - fe_1(h->Z); - fe_sq(u,h->Y); - fe_mul(v,u,d); - fe_sub(u,u,h->Z); /* u = y^2-1 */ - fe_add(v,v,h->Z); /* v = dy^2+1 */ - - fe_sq(v3,v); - fe_mul(v3,v3,v); /* v3 = v^3 */ - fe_sq(h->X,v3); - fe_mul(h->X,h->X,v); - fe_mul(h->X,h->X,u); /* x = uv^7 */ - - fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ - fe_mul(h->X,h->X,v3); - fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ - - fe_sq(vxx,h->X); - fe_mul(vxx,vxx,v); - fe_sub(check,vxx,u); /* vx^2-u */ - if (fe_isnonzero(check)) { - fe_add(check,vxx,u); /* vx^2+u */ - if (fe_isnonzero(check)) return -1; - fe_mul(h->X,h->X,sqrtm1); - } - - if (fe_isnegative(h->X) == (s[31] >> 7)) - fe_neg(h->X,h->X); - - fe_mul(h->T,h->X,h->Y); - return 0; -} - - -static void slide(signed char *r,const unsigned char *a) -{ - int i; - int b; - int k; - - for (i = 0;i < 256;++i) - r[i] = 1 & (a[i >> 3] >> (i & 7)); - - for (i = 0;i < 256;++i) - if (r[i]) { - for (b = 1;b <= 6 && i + b < 256;++b) { - if (r[i + b]) { - if (r[i] + (r[i + b] << b) <= 15) { - r[i] += r[i + b] << b; r[i + b] = 0; - } else if (r[i] - (r[i + b] << b) >= -15) { - r[i] -= r[i + b] << b; - for (k = i + b;k < 256;++k) { - if (!r[k]) { - r[k] = 1; - break; - } - r[k] = 0; - } - } else - break; - } - } - } - -} - - -/* -r = a * A + b * B -where a = a[0]+256*a[1]+...+256^31 a[31]. -and b = b[0]+256*b[1]+...+256^31 b[31]. -B is the Ed25519 base point (x,4/5) with x positive. -*/ - -static void ge_double_scalarmult_vartime(ge_p2 *r,const unsigned char *a,const ge_p3 *A,const unsigned char *b) -{ - signed char aslide[256]; - signed char bslide[256]; - ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ - ge_p1p1 t; - ge_p3 u; - ge_p3 A2; - int i; - - slide(aslide,a); - slide(bslide,b); - - ge_p3_to_cached(&Ai[0],A); - ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); - ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); - ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); - ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); - ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); - ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); - ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); - ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); - - ge_p2_0(r); - - for (i = 255;i >= 0;--i) { - if (aslide[i] || bslide[i]) break; - } - - for (;i >= 0;--i) { - ge_p2_dbl(&t,r); - - if (aslide[i] > 0) { - ge_p1p1_to_p3(&u,&t); - ge_add(&t,&u,&Ai[aslide[i]/2]); - } else if (aslide[i] < 0) { - ge_p1p1_to_p3(&u,&t); - ge_sub(&t,&u,&Ai[(-aslide[i])/2]); - } - - if (bslide[i] > 0) { - ge_p1p1_to_p3(&u,&t); - ge_madd(&t,&u,&Bi[bslide[i]/2]); - } else if (bslide[i] < 0) { - ge_p1p1_to_p3(&u,&t); - ge_msub(&t,&u,&Bi[(-bslide[i])/2]); - } - - ge_p1p1_to_p2(r,&t); - } -} - -static unsigned char equal(signed char b,signed char c) -{ - unsigned char ub = b; - unsigned char uc = c; - unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ - crypto_uint32 y = x; /* 0: yes; 1..255: no */ - y -= 1; /* 4294967295: yes; 0..254: no */ - y >>= 31; /* 1: yes; 0: no */ - return y; -} - -static unsigned char negative(signed char b) -{ - unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ - x >>= 63; /* 1: yes; 0: no */ - return x; -} - -static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b) -{ - fe_cmov(t->yplusx,u->yplusx,b); - fe_cmov(t->yminusx,u->yminusx,b); - fe_cmov(t->xy2d,u->xy2d,b); -} - - - -static void select(ge_precomp *t,int pos,signed char b) -{ - ge_precomp minust; - unsigned char bnegative = negative(b); - unsigned char babs = b - (((-bnegative) & b) << 1); - - ge_precomp_0(t); - cmov(t,&base[pos][0],equal(babs,1)); - cmov(t,&base[pos][1],equal(babs,2)); - cmov(t,&base[pos][2],equal(babs,3)); - cmov(t,&base[pos][3],equal(babs,4)); - cmov(t,&base[pos][4],equal(babs,5)); - cmov(t,&base[pos][5],equal(babs,6)); - cmov(t,&base[pos][6],equal(babs,7)); - cmov(t,&base[pos][7],equal(babs,8)); - fe_copy(minust.yplusx,t->yminusx); - fe_copy(minust.yminusx,t->yplusx); - fe_neg(minust.xy2d,t->xy2d); - cmov(t,&minust,bnegative); -} - -/* -h = a * B -where a = a[0]+256*a[1]+...+256^31 a[31] -B is the Ed25519 base point (x,4/5) with x positive. - -Preconditions: - a[31] <= 127 -*/ - -static void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) -{ - signed char e[64]; - signed char carry; - ge_p1p1 r; - ge_p2 s; - ge_precomp t; - int i; - - for (i = 0;i < 32;++i) { - e[2 * i + 0] = (a[i] >> 0) & 15; - e[2 * i + 1] = (a[i] >> 4) & 15; - } - /* each e[i] is between 0 and 15 */ - /* e[63] is between 0 and 7 */ - - carry = 0; - for (i = 0;i < 63;++i) { - e[i] += carry; - carry = e[i] + 8; - carry >>= 4; - e[i] -= carry << 4; - } - e[63] += carry; - /* each e[i] is between -8 and 8 */ - - ge_p3_0(h); - for (i = 1;i < 64;i += 2) { - select(&t,i / 2,e[i]); - ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); - } - - ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r); - ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); - ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); - ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r); - - for (i = 0;i < 64;i += 2) { - select(&t,i / 2,e[i]); - ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); - } -} - -/* -Input: - s[0]+256*s[1]+...+256^63*s[63] = s - -Output: - s[0]+256*s[1]+...+256^31*s[31] = s mod l - where l = 2^252 + 27742317777372353535851937790883648493. - Overwrites s in place. -*/ - -static void sc_reduce(unsigned char *s) -{ - crypto_int64 s0 = 2097151 & load_3(s); - crypto_int64 s1 = 2097151 & (load_4(s + 2) >> 5); - crypto_int64 s2 = 2097151 & (load_3(s + 5) >> 2); - crypto_int64 s3 = 2097151 & (load_4(s + 7) >> 7); - crypto_int64 s4 = 2097151 & (load_4(s + 10) >> 4); - crypto_int64 s5 = 2097151 & (load_3(s + 13) >> 1); - crypto_int64 s6 = 2097151 & (load_4(s + 15) >> 6); - crypto_int64 s7 = 2097151 & (load_3(s + 18) >> 3); - crypto_int64 s8 = 2097151 & load_3(s + 21); - crypto_int64 s9 = 2097151 & (load_4(s + 23) >> 5); - crypto_int64 s10 = 2097151 & (load_3(s + 26) >> 2); - crypto_int64 s11 = 2097151 & (load_4(s + 28) >> 7); - crypto_int64 s12 = 2097151 & (load_4(s + 31) >> 4); - crypto_int64 s13 = 2097151 & (load_3(s + 34) >> 1); - crypto_int64 s14 = 2097151 & (load_4(s + 36) >> 6); - crypto_int64 s15 = 2097151 & (load_3(s + 39) >> 3); - crypto_int64 s16 = 2097151 & load_3(s + 42); - crypto_int64 s17 = 2097151 & (load_4(s + 44) >> 5); - crypto_int64 s18 = 2097151 & (load_3(s + 47) >> 2); - crypto_int64 s19 = 2097151 & (load_4(s + 49) >> 7); - crypto_int64 s20 = 2097151 & (load_4(s + 52) >> 4); - crypto_int64 s21 = 2097151 & (load_3(s + 55) >> 1); - crypto_int64 s22 = 2097151 & (load_4(s + 57) >> 6); - crypto_int64 s23 = (load_4(s + 60) >> 3); - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - crypto_int64 carry10; - crypto_int64 carry11; - crypto_int64 carry12; - crypto_int64 carry13; - crypto_int64 carry14; - crypto_int64 carry15; - crypto_int64 carry16; - - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - s23 = 0; - - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - s22 = 0; - - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - s21 = 0; - - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - s20 = 0; - - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - s19 = 0; - - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - s18 = 0; - - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - s17 = 0; - - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - s16 = 0; - - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - s15 = 0; - - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - s14 = 0; - - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - s13 = 0; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -/* -Input: - a[0]+256*a[1]+...+256^31*a[31] = a - b[0]+256*b[1]+...+256^31*b[31] = b - c[0]+256*c[1]+...+256^31*c[31] = c - -Output: - s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l - where l = 2^252 + 27742317777372353535851937790883648493. -*/ - -static void sc_muladd(unsigned char *s,const unsigned char *a,const unsigned char *b,const unsigned char *c) -{ - crypto_int64 a0 = 2097151 & load_3(a); - crypto_int64 a1 = 2097151 & (load_4(a + 2) >> 5); - crypto_int64 a2 = 2097151 & (load_3(a + 5) >> 2); - crypto_int64 a3 = 2097151 & (load_4(a + 7) >> 7); - crypto_int64 a4 = 2097151 & (load_4(a + 10) >> 4); - crypto_int64 a5 = 2097151 & (load_3(a + 13) >> 1); - crypto_int64 a6 = 2097151 & (load_4(a + 15) >> 6); - crypto_int64 a7 = 2097151 & (load_3(a + 18) >> 3); - crypto_int64 a8 = 2097151 & load_3(a + 21); - crypto_int64 a9 = 2097151 & (load_4(a + 23) >> 5); - crypto_int64 a10 = 2097151 & (load_3(a + 26) >> 2); - crypto_int64 a11 = (load_4(a + 28) >> 7); - crypto_int64 b0 = 2097151 & load_3(b); - crypto_int64 b1 = 2097151 & (load_4(b + 2) >> 5); - crypto_int64 b2 = 2097151 & (load_3(b + 5) >> 2); - crypto_int64 b3 = 2097151 & (load_4(b + 7) >> 7); - crypto_int64 b4 = 2097151 & (load_4(b + 10) >> 4); - crypto_int64 b5 = 2097151 & (load_3(b + 13) >> 1); - crypto_int64 b6 = 2097151 & (load_4(b + 15) >> 6); - crypto_int64 b7 = 2097151 & (load_3(b + 18) >> 3); - crypto_int64 b8 = 2097151 & load_3(b + 21); - crypto_int64 b9 = 2097151 & (load_4(b + 23) >> 5); - crypto_int64 b10 = 2097151 & (load_3(b + 26) >> 2); - crypto_int64 b11 = (load_4(b + 28) >> 7); - crypto_int64 c0 = 2097151 & load_3(c); - crypto_int64 c1 = 2097151 & (load_4(c + 2) >> 5); - crypto_int64 c2 = 2097151 & (load_3(c + 5) >> 2); - crypto_int64 c3 = 2097151 & (load_4(c + 7) >> 7); - crypto_int64 c4 = 2097151 & (load_4(c + 10) >> 4); - crypto_int64 c5 = 2097151 & (load_3(c + 13) >> 1); - crypto_int64 c6 = 2097151 & (load_4(c + 15) >> 6); - crypto_int64 c7 = 2097151 & (load_3(c + 18) >> 3); - crypto_int64 c8 = 2097151 & load_3(c + 21); - crypto_int64 c9 = 2097151 & (load_4(c + 23) >> 5); - crypto_int64 c10 = 2097151 & (load_3(c + 26) >> 2); - crypto_int64 c11 = (load_4(c + 28) >> 7); - crypto_int64 s0; - crypto_int64 s1; - crypto_int64 s2; - crypto_int64 s3; - crypto_int64 s4; - crypto_int64 s5; - crypto_int64 s6; - crypto_int64 s7; - crypto_int64 s8; - crypto_int64 s9; - crypto_int64 s10; - crypto_int64 s11; - crypto_int64 s12; - crypto_int64 s13; - crypto_int64 s14; - crypto_int64 s15; - crypto_int64 s16; - crypto_int64 s17; - crypto_int64 s18; - crypto_int64 s19; - crypto_int64 s20; - crypto_int64 s21; - crypto_int64 s22; - crypto_int64 s23; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - crypto_int64 carry10; - crypto_int64 carry11; - crypto_int64 carry12; - crypto_int64 carry13; - crypto_int64 carry14; - crypto_int64 carry15; - crypto_int64 carry16; - crypto_int64 carry17; - crypto_int64 carry18; - crypto_int64 carry19; - crypto_int64 carry20; - crypto_int64 carry21; - crypto_int64 carry22; - - s0 = c0 + a0*b0; - s1 = c1 + a0*b1 + a1*b0; - s2 = c2 + a0*b2 + a1*b1 + a2*b0; - s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0; - s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0; - s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0; - s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0; - s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0; - s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0; - s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0; - s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0; - s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0; - s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1; - s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2; - s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3; - s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4; - s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5; - s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6; - s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7; - s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8; - s20 = a9*b11 + a10*b10 + a11*b9; - s21 = a10*b11 + a11*b10; - s22 = a11*b11; - s23 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21; - carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21; - carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21; - carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21; - carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21; - - s11 += s23 * 666643; - s12 += s23 * 470296; - s13 += s23 * 654183; - s14 -= s23 * 997805; - s15 += s23 * 136657; - s16 -= s23 * 683901; - s23 = 0; - - s10 += s22 * 666643; - s11 += s22 * 470296; - s12 += s22 * 654183; - s13 -= s22 * 997805; - s14 += s22 * 136657; - s15 -= s22 * 683901; - s22 = 0; - - s9 += s21 * 666643; - s10 += s21 * 470296; - s11 += s21 * 654183; - s12 -= s21 * 997805; - s13 += s21 * 136657; - s14 -= s21 * 683901; - s21 = 0; - - s8 += s20 * 666643; - s9 += s20 * 470296; - s10 += s20 * 654183; - s11 -= s20 * 997805; - s12 += s20 * 136657; - s13 -= s20 * 683901; - s20 = 0; - - s7 += s19 * 666643; - s8 += s19 * 470296; - s9 += s19 * 654183; - s10 -= s19 * 997805; - s11 += s19 * 136657; - s12 -= s19 * 683901; - s19 = 0; - - s6 += s18 * 666643; - s7 += s18 * 470296; - s8 += s18 * 654183; - s9 -= s18 * 997805; - s10 += s18 * 136657; - s11 -= s18 * 683901; - s18 = 0; - - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - - s5 += s17 * 666643; - s6 += s17 * 470296; - s7 += s17 * 654183; - s8 -= s17 * 997805; - s9 += s17 * 136657; - s10 -= s17 * 683901; - s17 = 0; - - s4 += s16 * 666643; - s5 += s16 * 470296; - s6 += s16 * 654183; - s7 -= s16 * 997805; - s8 += s16 * 136657; - s9 -= s16 * 683901; - s16 = 0; - - s3 += s15 * 666643; - s4 += s15 * 470296; - s5 += s15 * 654183; - s6 -= s15 * 997805; - s7 += s15 * 136657; - s8 -= s15 * 683901; - s15 = 0; - - s2 += s14 * 666643; - s3 += s14 * 470296; - s4 += s14 * 654183; - s5 -= s14 * 997805; - s6 += s14 * 136657; - s7 -= s14 * 683901; - s14 = 0; - - s1 += s13 * 666643; - s2 += s13 * 470296; - s3 += s13 * 654183; - s4 -= s13 * 997805; - s5 += s13 * 136657; - s6 -= s13 * 683901; - s13 = 0; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - - carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; - - s0 += s12 * 666643; - s1 += s12 * 470296; - s2 += s12 * 654183; - s3 -= s12 * 997805; - s4 += s12 * 136657; - s5 -= s12 * 683901; - s12 = 0; - - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; -} - -/* -int crypto_sign_keypair(unsigned char *pk,unsigned char *sk) -{ - unsigned char h[64]; - ge_p3 A; - int i; - - randombytes(sk,32); - crypto_hash_sha512(h,sk,32); - h[0] &= 248; - h[31] &= 63; - h[31] |= 64; - - ge_scalarmult_base(&A,h); - ge_p3_tobytes(pk,&A); - - for (i = 0;i < 32;++i) sk[32 + i] = pk[i]; - return 0; -} -*/ - -int crypto_sign_pk_ref10(unsigned char *pk,unsigned char *sk) -{ - unsigned char h[64]; - ge_p3 A; - int i; - - crypto_hash_sha512(h,sk,32); - h[0] &= 248; - h[31] &= 63; - h[31] |= 64; - - ge_scalarmult_base(&A,h); - ge_p3_tobytes(pk,&A); - - for (i = 0;i < 32;++i) sk[32 + i] = pk[i]; - return 0; -} - -int crypto_sign_ref10( - unsigned char *sm,unsigned long long *smlen, - const unsigned char *m,unsigned long long mlen, - const unsigned char *sk -) -{ - unsigned char az[64]; - unsigned char r[64]; - unsigned char hram[64]; - ge_p3 R; - unsigned long long i; - - crypto_hash_sha512(az,sk,32); - az[0] &= 248; - az[31] &= 63; - az[31] |= 64; - - *smlen = mlen + 64; - for (i = 0;i < mlen;++i) sm[64 + i] = m[i]; - for (i = 0;i < 32;++i) sm[32 + i] = az[32 + i]; - crypto_hash_sha512(r,sm + 32,mlen + 32); - for (i = 0;i < 32;++i) sm[32 + i] = sk[32 + i]; - - sc_reduce(r); - ge_scalarmult_base(&R,r); - ge_p3_tobytes(sm,&R); - - crypto_hash_sha512(hram,sm,mlen + 64); - sc_reduce(hram); - sc_muladd(sm + 32,hram,az,r); - - return 0; -} - -int crypto_sign_open_ref10( - unsigned char *m,unsigned long long *mlen, - const unsigned char *sm,unsigned long long smlen, - const unsigned char *pk -) -{ - unsigned char h[64]; - unsigned char checkr[32]; - ge_p3 A; - ge_p2 R; - unsigned long long i; - - *mlen = -1; - if (smlen < 64) return -1; - if (sm[63] & 224) return -1; - if (ge_frombytes_negate_vartime(&A,pk) != 0) return -1; - - for (i = 0;i < smlen;++i) m[i] = sm[i]; - for (i = 0;i < 32;++i) m[32 + i] = pk[i]; - crypto_hash_sha512(h,m,smlen); - sc_reduce(h); - - ge_double_scalarmult_vartime(&R,h,&A,sm + 32); - ge_tobytes(checkr,&R); - if (crypto_verify_32(checkr,sm) != 0) { - for (i = 0;i < smlen;++i) m[i] = 0; - return -1; - } - - for (i = 0;i < smlen - 64;++i) m[i] = sm[64 + i]; - for (i = smlen - 64;i < smlen;++i) m[i] = 0; - *mlen = smlen - 64; - return 0; -} - diff --git a/external/ed25519-donna/fuzz/ed25519-ref10.h b/external/ed25519-donna/fuzz/ed25519-ref10.h deleted file mode 100644 index c8a0f69b65..0000000000 --- a/external/ed25519-donna/fuzz/ed25519-ref10.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef ED25519_REF10_H -#define ED25519_REF10_H - -int crypto_sign_pk_ref10(unsigned char *pk,unsigned char *sk); -int crypto_sign_ref10(unsigned char *sm,unsigned long long *smlen,const unsigned char *m,unsigned long long mlen,const unsigned char *sk); -int crypto_sign_open_ref10(unsigned char *m,unsigned long long *mlen,const unsigned char *sm,unsigned long long smlen,const unsigned char *pk); - -#endif /* ED25519_REF10_H */ - diff --git a/external/ed25519-donna/fuzz/fuzz-curve25519.c b/external/ed25519-donna/fuzz/fuzz-curve25519.c deleted file mode 100644 index 43017014c2..0000000000 --- a/external/ed25519-donna/fuzz/fuzz-curve25519.c +++ /dev/null @@ -1,172 +0,0 @@ -#if defined(_WIN32) - #include - #include - typedef unsigned int uint32_t; - typedef unsigned __int64 uint64_t; -#else - #include -#endif - -#include -#include - -#include "ed25519-donna.h" -#include "curve25519-ref10.h" - -static void -print_diff(const char *desc, const unsigned char *a, const unsigned char *b, size_t len) { - size_t p = 0; - unsigned char diff; - printf("%s diff:\n", desc); - while (len--) { - diff = *a++ ^ *b++; - if (!diff) - printf("____,"); - else - printf("0x%02x,", diff); - if ((++p & 15) == 0) - printf("\n"); - } - printf("\n\n"); -} - -static void -print_bytes(const char *desc, const unsigned char *bytes, size_t len) { - size_t p = 0; - printf("%s:\n", desc); - while (len--) { - printf("0x%02x,", *bytes++); - if ((++p & 15) == 0) - printf("\n"); - } - printf("\n\n"); -} - - -/* chacha20/12 prng */ -void -prng(unsigned char *out, size_t bytes) { - static uint32_t state[16]; - static int init = 0; - uint32_t x[16], t; - size_t i; - - if (!init) { - #if defined(_WIN32) - HCRYPTPROV csp; - if (!CryptAcquireContext(&csp, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - printf("CryptAcquireContext failed\n"); - exit(1); - } - if (!CryptGenRandom(csp, (DWORD)sizeof(state), (BYTE*)state)) { - printf("CryptGenRandom failed\n"); - exit(1); - } - CryptReleaseContext(csp, 0); - #else - FILE *f = NULL; - f = fopen("/dev/urandom", "rb"); - if (!f) { - printf("failed to open /dev/urandom\n"); - exit(1); - } - if (fread(state, sizeof(state), 1, f) != 1) { - printf("read error on /dev/urandom\n"); - exit(1); - } - #endif - init = 1; - } - - while (bytes) { - for (i = 0; i < 16; i++) x[i] = state[i]; - - #define rotl32(x,k) ((x << k) | (x >> (32 - k))) - #define quarter(a,b,c,d) \ - x[a] += x[b]; t = x[d]^x[a]; x[d] = rotl32(t,16); \ - x[c] += x[d]; t = x[b]^x[c]; x[b] = rotl32(t,12); \ - x[a] += x[b]; t = x[d]^x[a]; x[d] = rotl32(t, 8); \ - x[c] += x[d]; t = x[b]^x[c]; x[b] = rotl32(t, 7); - - for (i = 0; i < 12; i += 2) { - quarter( 0, 4, 8,12) - quarter( 1, 5, 9,13) - quarter( 2, 6,10,14) - quarter( 3, 7,11,15) - quarter( 0, 5,10,15) - quarter( 1, 6,11,12) - quarter( 2, 7, 8,13) - quarter( 3, 4, 9,14) - }; - - if (bytes <= 64) { - memcpy(out, x, bytes); - bytes = 0; - } else { - memcpy(out, x, 64); - bytes -= 64; - out += 64; - } - - /* don't need a nonce, so last 4 words are the counter. 2^136 bytes can be generated */ - if (!++state[12]) if (!++state[13]) if (!++state[14]) ++state[15]; - } -} - - - -int main() { - const size_t skmax = 1024; - static unsigned char sk[1024][32]; - unsigned char pk[3][32]; - unsigned char *skp; - size_t ski, pki, i; - uint64_t ctr; - - printf("fuzzing: "); - printf(" ref10"); - printf(" curved25519"); -#if defined(ED25519_SSE2) - printf(" curved25519-sse2"); -#endif - printf("\n\n"); - - for (ctr = 0, ski = skmax;;ctr++) { - if (ski == skmax) { - prng((unsigned char *)sk, sizeof(sk)); - ski = 0; - } - skp = sk[ski++]; - - pki = 0; - crypto_scalarmult_base_ref10(pk[pki++], skp); - curved25519_scalarmult_basepoint(pk[pki++], skp); - #if defined(ED25519_SSE2) - curved25519_scalarmult_basepoint_sse2(pk[pki++], skp); - #endif - - for (i = 1; i < pki; i++) { - if (memcmp(pk[0], pk[i], 32) != 0) { - printf("\n\n"); - print_bytes("sk", skp, 32); - print_bytes("ref10", pk[0], 32); - print_diff("curved25519", pk[0], pk[1], 32); - #if defined(ED25519_SSE2) - print_diff("curved25519-sse2", pk[0], pk[2], 32); - #endif - exit(1); - } - } - - if (ctr && (ctr % 0x1000 == 0)) { - printf("."); - if ((ctr % 0x20000) == 0) { - printf(" ["); - for (i = 0; i < 8; i++) - printf("%02x", (unsigned char)(ctr >> ((7 - i) * 8))); - printf("]\n"); - } - } - } -} - diff --git a/external/ed25519-donna/fuzz/fuzz-ed25519.c b/external/ed25519-donna/fuzz/fuzz-ed25519.c deleted file mode 100644 index b242e8e5da..0000000000 --- a/external/ed25519-donna/fuzz/fuzz-ed25519.c +++ /dev/null @@ -1,219 +0,0 @@ -#if defined(_WIN32) - #include - #include - typedef unsigned int uint32_t; -#else - #include -#endif - -#include -#include - -#include "ed25519-donna.h" -#include "ed25519-ref10.h" - -static void -print_diff(const char *desc, const unsigned char *a, const unsigned char *b, size_t len) { - size_t p = 0; - unsigned char diff; - printf("%s diff:\n", desc); - while (len--) { - diff = *a++ ^ *b++; - if (!diff) - printf("____,"); - else - printf("0x%02x,", diff); - if ((++p & 15) == 0) - printf("\n"); - } - printf("\n"); -} - -static void -print_bytes(const char *desc, const unsigned char *bytes, size_t len) { - size_t p = 0; - printf("%s:\n", desc); - while (len--) { - printf("0x%02x,", *bytes++); - if ((++p & 15) == 0) - printf("\n"); - } - printf("\n"); -} - - -/* chacha20/12 prng */ -void -prng(unsigned char *out, size_t bytes) { - static uint32_t state[16]; - static int init = 0; - uint32_t x[16], t; - size_t i; - - if (!init) { - #if defined(_WIN32) - HCRYPTPROV csp = NULL; - if (!CryptAcquireContext(&csp, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - printf("CryptAcquireContext failed\n"); - exit(1); - } - if (!CryptGenRandom(csp, (DWORD)sizeof(state), (BYTE*)state)) { - printf("CryptGenRandom failed\n"); - exit(1); - } - CryptReleaseContext(csp, 0); - #else - FILE *f = NULL; - f = fopen("/dev/urandom", "rb"); - if (!f) { - printf("failed to open /dev/urandom\n"); - exit(1); - } - if (fread(state, sizeof(state), 1, f) != 1) { - printf("read error on /dev/urandom\n"); - exit(1); - } - #endif - init = 1; - } - - while (bytes) { - for (i = 0; i < 16; i++) x[i] = state[i]; - - #define rotl32(x,k) ((x << k) | (x >> (32 - k))) - #define quarter(a,b,c,d) \ - x[a] += x[b]; t = x[d]^x[a]; x[d] = rotl32(t,16); \ - x[c] += x[d]; t = x[b]^x[c]; x[b] = rotl32(t,12); \ - x[a] += x[b]; t = x[d]^x[a]; x[d] = rotl32(t, 8); \ - x[c] += x[d]; t = x[b]^x[c]; x[b] = rotl32(t, 7); - - for (i = 0; i < 12; i += 2) { - quarter( 0, 4, 8,12) - quarter( 1, 5, 9,13) - quarter( 2, 6,10,14) - quarter( 3, 7,11,15) - quarter( 0, 5,10,15) - quarter( 1, 6,11,12) - quarter( 2, 7, 8,13) - quarter( 3, 4, 9,14) - }; - - if (bytes <= 64) { - memcpy(out, x, bytes); - bytes = 0; - } else { - memcpy(out, x, 64); - bytes -= 64; - out += 64; - } - - /* don't need a nonce, so last 4 words are the counter. 2^136 bytes can be generated */ - if (!++state[12]) if (!++state[13]) if (!++state[14]) ++state[15]; - } -} - -typedef struct random_data_t { - unsigned char sk[32]; - unsigned char m[128]; -} random_data; - -typedef struct generated_data_t { - unsigned char pk[32]; - unsigned char sig[64]; - int valid; -} generated_data; - -static void -print_generated(const char *desc, generated_data *g) { - printf("%s:\n", desc); - print_bytes("pk", g->pk, 32); - print_bytes("sig", g->sig, 64); - printf("valid: %s\n\n", g->valid ? "no" : "yes"); -} - -static void -print_generated_diff(const char *desc, const generated_data *base, generated_data *g) { - printf("%s:\n", desc); - print_diff("pk", base->pk, g->pk, 32); - print_diff("sig", base->sig, g->sig, 64); - printf("valid: %s\n\n", (base->valid == g->valid) ? "___" : (g->valid ? "no" : "yes")); -} - -int main() { - const size_t rndmax = 128; - static random_data rnd[128]; - static generated_data gen[3]; - random_data *r; - generated_data *g; - unsigned long long dummylen; - unsigned char dummysk[64]; - unsigned char dummymsg[2][128+64]; - size_t rndi, geni, i, j; - uint64_t ctr; - - printf("fuzzing: "); - printf(" ref10"); - printf(" ed25519-donna"); -#if defined(ED25519_SSE2) - printf(" ed25519-donna-sse2"); -#endif - printf("\n\n"); - - for (ctr = 0, rndi = rndmax;;ctr++) { - if (rndi == rndmax) { - prng((unsigned char *)rnd, sizeof(rnd)); - rndi = 0; - } - r = &rnd[rndi++]; - - /* ref10, lots of horrible gymnastics to work around the wonky api */ - geni = 0; - g = &gen[geni++]; - memcpy(dummysk, r->sk, 32); /* pk is appended to the sk, need to copy the sk to a larger buffer */ - crypto_sign_pk_ref10(dummysk + 32, dummysk); - memcpy(g->pk, dummysk + 32, 32); - crypto_sign_ref10(dummymsg[0], &dummylen, r->m, 128, dummysk); - memcpy(g->sig, dummymsg[0], 64); /* sig is placed in front of the signed message */ - g->valid = crypto_sign_open_ref10(dummymsg[1], &dummylen, dummymsg[0], 128 + 64, g->pk); - - /* ed25519-donna */ - g = &gen[geni++]; - ed25519_publickey(r->sk, g->pk); - ed25519_sign(r->m, 128, r->sk, g->pk, g->sig); - g->valid = ed25519_sign_open(r->m, 128, g->pk, g->sig); - - #if defined(ED25519_SSE2) - /* ed25519-donna-sse2 */ - g = &gen[geni++]; - ed25519_publickey_sse2(r->sk, g->pk); - ed25519_sign_sse2(r->m, 128, r->sk, g->pk, g->sig); - g->valid = ed25519_sign_open_sse2(r->m, 128, g->pk, g->sig); - #endif - - /* compare implementations 1..geni against the reference */ - for (i = 1; i < geni; i++) { - if (memcmp(&gen[0], &gen[i], sizeof(generated_data)) != 0) { - printf("\n\n"); - print_bytes("sk", r->sk, 32); - print_bytes("m", r->m, 128); - print_generated("ref10", &gen[0]); - print_generated_diff("ed25519-donna", &gen[0], &gen[1]); - #if defined(ED25519_SSE2) - print_generated_diff("ed25519-donna-sse2", &gen[0], &gen[2]); - #endif - exit(1); - } - } - - /* print out status */ - if (ctr && (ctr % 0x1000 == 0)) { - printf("."); - if ((ctr % 0x20000) == 0) { - printf(" ["); - for (i = 0; i < 8; i++) - printf("%02x", (unsigned char)(ctr >> ((7 - i) * 8))); - printf("]\n"); - } - } - } -} \ No newline at end of file diff --git a/external/ed25519-donna/modm-donna-32bit.h b/external/ed25519-donna/modm-donna-32bit.h deleted file mode 100644 index dfd76be668..0000000000 --- a/external/ed25519-donna/modm-donna-32bit.h +++ /dev/null @@ -1,469 +0,0 @@ -/* - Public domain by Andrew M. -*/ - - -/* - Arithmetic modulo the group order n = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989 - - k = 32 - b = 1 << 8 = 256 - m = 2^252 + 27742317777372353535851937790883648493 = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed - mu = floor( b^(k*2) / m ) = 0xfffffffffffffffffffffffffffffffeb2106215d086329a7ed9ce5a30a2c131b -*/ - -#define bignum256modm_bits_per_limb 30 -#define bignum256modm_limb_size 9 - -typedef uint32_t bignum256modm_element_t; -typedef bignum256modm_element_t bignum256modm[9]; - -static const bignum256modm modm_m = { - 0x1cf5d3ed, 0x20498c69, 0x2f79cd65, 0x37be77a8, - 0x00000014, 0x00000000, 0x00000000, 0x00000000, - 0x00001000 -}; - -static const bignum256modm modm_mu = { - 0x0a2c131b, 0x3673968c, 0x06329a7e, 0x01885742, - 0x3fffeb21, 0x3fffffff, 0x3fffffff, 0x3fffffff, - 0x000fffff -}; - -static bignum256modm_element_t -lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) { - return (a - b) >> 31; -} - -/* see HAC, Alg. 14.42 Step 4 */ -static void -reduce256_modm(bignum256modm r) { - bignum256modm t; - bignum256modm_element_t b = 0, pb, mask; - - /* t = r - m */ - pb = 0; - pb += modm_m[0]; b = lt_modm(r[0], pb); t[0] = (r[0] - pb + (b << 30)); pb = b; - pb += modm_m[1]; b = lt_modm(r[1], pb); t[1] = (r[1] - pb + (b << 30)); pb = b; - pb += modm_m[2]; b = lt_modm(r[2], pb); t[2] = (r[2] - pb + (b << 30)); pb = b; - pb += modm_m[3]; b = lt_modm(r[3], pb); t[3] = (r[3] - pb + (b << 30)); pb = b; - pb += modm_m[4]; b = lt_modm(r[4], pb); t[4] = (r[4] - pb + (b << 30)); pb = b; - pb += modm_m[5]; b = lt_modm(r[5], pb); t[5] = (r[5] - pb + (b << 30)); pb = b; - pb += modm_m[6]; b = lt_modm(r[6], pb); t[6] = (r[6] - pb + (b << 30)); pb = b; - pb += modm_m[7]; b = lt_modm(r[7], pb); t[7] = (r[7] - pb + (b << 30)); pb = b; - pb += modm_m[8]; b = lt_modm(r[8], pb); t[8] = (r[8] - pb + (b << 16)); - - /* keep r if r was smaller than m */ - mask = b - 1; - r[0] ^= mask & (r[0] ^ t[0]); - r[1] ^= mask & (r[1] ^ t[1]); - r[2] ^= mask & (r[2] ^ t[2]); - r[3] ^= mask & (r[3] ^ t[3]); - r[4] ^= mask & (r[4] ^ t[4]); - r[5] ^= mask & (r[5] ^ t[5]); - r[6] ^= mask & (r[6] ^ t[6]); - r[7] ^= mask & (r[7] ^ t[7]); - r[8] ^= mask & (r[8] ^ t[8]); -} - -/* - Barrett reduction, see HAC, Alg. 14.42 - - Instead of passing in x, pre-process in to q1 and r1 for efficiency -*/ -static void -barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256modm r1) { - bignum256modm q3, r2; - uint64_t c; - bignum256modm_element_t f, b, pb; - - /* q1 = x >> 248 = 264 bits = 9 30 bit elements - q2 = mu * q1 - q3 = (q2 / 256(32+1)) = q2 / (2^8)^(32+1) = q2 >> 264 */ - c = mul32x32_64(modm_mu[0], q1[7]) + mul32x32_64(modm_mu[1], q1[6]) + mul32x32_64(modm_mu[2], q1[5]) + mul32x32_64(modm_mu[3], q1[4]) + mul32x32_64(modm_mu[4], q1[3]) + mul32x32_64(modm_mu[5], q1[2]) + mul32x32_64(modm_mu[6], q1[1]) + mul32x32_64(modm_mu[7], q1[0]); - c >>= 30; - c += mul32x32_64(modm_mu[0], q1[8]) + mul32x32_64(modm_mu[1], q1[7]) + mul32x32_64(modm_mu[2], q1[6]) + mul32x32_64(modm_mu[3], q1[5]) + mul32x32_64(modm_mu[4], q1[4]) + mul32x32_64(modm_mu[5], q1[3]) + mul32x32_64(modm_mu[6], q1[2]) + mul32x32_64(modm_mu[7], q1[1]) + mul32x32_64(modm_mu[8], q1[0]); - f = (bignum256modm_element_t)c; q3[0] = (f >> 24) & 0x3f; c >>= 30; - c += mul32x32_64(modm_mu[1], q1[8]) + mul32x32_64(modm_mu[2], q1[7]) + mul32x32_64(modm_mu[3], q1[6]) + mul32x32_64(modm_mu[4], q1[5]) + mul32x32_64(modm_mu[5], q1[4]) + mul32x32_64(modm_mu[6], q1[3]) + mul32x32_64(modm_mu[7], q1[2]) + mul32x32_64(modm_mu[8], q1[1]); - f = (bignum256modm_element_t)c; q3[0] |= (f << 6) & 0x3fffffff; q3[1] = (f >> 24) & 0x3f; c >>= 30; - c += mul32x32_64(modm_mu[2], q1[8]) + mul32x32_64(modm_mu[3], q1[7]) + mul32x32_64(modm_mu[4], q1[6]) + mul32x32_64(modm_mu[5], q1[5]) + mul32x32_64(modm_mu[6], q1[4]) + mul32x32_64(modm_mu[7], q1[3]) + mul32x32_64(modm_mu[8], q1[2]); - f = (bignum256modm_element_t)c; q3[1] |= (f << 6) & 0x3fffffff; q3[2] = (f >> 24) & 0x3f; c >>= 30; - c += mul32x32_64(modm_mu[3], q1[8]) + mul32x32_64(modm_mu[4], q1[7]) + mul32x32_64(modm_mu[5], q1[6]) + mul32x32_64(modm_mu[6], q1[5]) + mul32x32_64(modm_mu[7], q1[4]) + mul32x32_64(modm_mu[8], q1[3]); - f = (bignum256modm_element_t)c; q3[2] |= (f << 6) & 0x3fffffff; q3[3] = (f >> 24) & 0x3f; c >>= 30; - c += mul32x32_64(modm_mu[4], q1[8]) + mul32x32_64(modm_mu[5], q1[7]) + mul32x32_64(modm_mu[6], q1[6]) + mul32x32_64(modm_mu[7], q1[5]) + mul32x32_64(modm_mu[8], q1[4]); - f = (bignum256modm_element_t)c; q3[3] |= (f << 6) & 0x3fffffff; q3[4] = (f >> 24) & 0x3f; c >>= 30; - c += mul32x32_64(modm_mu[5], q1[8]) + mul32x32_64(modm_mu[6], q1[7]) + mul32x32_64(modm_mu[7], q1[6]) + mul32x32_64(modm_mu[8], q1[5]); - f = (bignum256modm_element_t)c; q3[4] |= (f << 6) & 0x3fffffff; q3[5] = (f >> 24) & 0x3f; c >>= 30; - c += mul32x32_64(modm_mu[6], q1[8]) + mul32x32_64(modm_mu[7], q1[7]) + mul32x32_64(modm_mu[8], q1[6]); - f = (bignum256modm_element_t)c; q3[5] |= (f << 6) & 0x3fffffff; q3[6] = (f >> 24) & 0x3f; c >>= 30; - c += mul32x32_64(modm_mu[7], q1[8]) + mul32x32_64(modm_mu[8], q1[7]); - f = (bignum256modm_element_t)c; q3[6] |= (f << 6) & 0x3fffffff; q3[7] = (f >> 24) & 0x3f; c >>= 30; - c += mul32x32_64(modm_mu[8], q1[8]); - f = (bignum256modm_element_t)c; q3[7] |= (f << 6) & 0x3fffffff; q3[8] = (bignum256modm_element_t)(c >> 24); - - /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) - r2 = (q3 * m) mod (256^(32+1)) = (q3 * m) & ((1 << 264) - 1) */ - c = mul32x32_64(modm_m[0], q3[0]); - r2[0] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; - c += mul32x32_64(modm_m[0], q3[1]) + mul32x32_64(modm_m[1], q3[0]); - r2[1] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; - c += mul32x32_64(modm_m[0], q3[2]) + mul32x32_64(modm_m[1], q3[1]) + mul32x32_64(modm_m[2], q3[0]); - r2[2] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; - c += mul32x32_64(modm_m[0], q3[3]) + mul32x32_64(modm_m[1], q3[2]) + mul32x32_64(modm_m[2], q3[1]) + mul32x32_64(modm_m[3], q3[0]); - r2[3] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; - c += mul32x32_64(modm_m[0], q3[4]) + mul32x32_64(modm_m[1], q3[3]) + mul32x32_64(modm_m[2], q3[2]) + mul32x32_64(modm_m[3], q3[1]) + mul32x32_64(modm_m[4], q3[0]); - r2[4] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; - c += mul32x32_64(modm_m[0], q3[5]) + mul32x32_64(modm_m[1], q3[4]) + mul32x32_64(modm_m[2], q3[3]) + mul32x32_64(modm_m[3], q3[2]) + mul32x32_64(modm_m[4], q3[1]) + mul32x32_64(modm_m[5], q3[0]); - r2[5] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; - c += mul32x32_64(modm_m[0], q3[6]) + mul32x32_64(modm_m[1], q3[5]) + mul32x32_64(modm_m[2], q3[4]) + mul32x32_64(modm_m[3], q3[3]) + mul32x32_64(modm_m[4], q3[2]) + mul32x32_64(modm_m[5], q3[1]) + mul32x32_64(modm_m[6], q3[0]); - r2[6] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; - c += mul32x32_64(modm_m[0], q3[7]) + mul32x32_64(modm_m[1], q3[6]) + mul32x32_64(modm_m[2], q3[5]) + mul32x32_64(modm_m[3], q3[4]) + mul32x32_64(modm_m[4], q3[3]) + mul32x32_64(modm_m[5], q3[2]) + mul32x32_64(modm_m[6], q3[1]) + mul32x32_64(modm_m[7], q3[0]); - r2[7] = (bignum256modm_element_t)(c & 0x3fffffff); c >>= 30; - c += mul32x32_64(modm_m[0], q3[8]) + mul32x32_64(modm_m[1], q3[7]) + mul32x32_64(modm_m[2], q3[6]) + mul32x32_64(modm_m[3], q3[5]) + mul32x32_64(modm_m[4], q3[4]) + mul32x32_64(modm_m[5], q3[3]) + mul32x32_64(modm_m[6], q3[2]) + mul32x32_64(modm_m[7], q3[1]) + mul32x32_64(modm_m[8], q3[0]); - r2[8] = (bignum256modm_element_t)(c & 0xffffff); - - /* r = r1 - r2 - if (r < 0) r += (1 << 264) */ - pb = 0; - pb += r2[0]; b = lt_modm(r1[0], pb); r[0] = (r1[0] - pb + (b << 30)); pb = b; - pb += r2[1]; b = lt_modm(r1[1], pb); r[1] = (r1[1] - pb + (b << 30)); pb = b; - pb += r2[2]; b = lt_modm(r1[2], pb); r[2] = (r1[2] - pb + (b << 30)); pb = b; - pb += r2[3]; b = lt_modm(r1[3], pb); r[3] = (r1[3] - pb + (b << 30)); pb = b; - pb += r2[4]; b = lt_modm(r1[4], pb); r[4] = (r1[4] - pb + (b << 30)); pb = b; - pb += r2[5]; b = lt_modm(r1[5], pb); r[5] = (r1[5] - pb + (b << 30)); pb = b; - pb += r2[6]; b = lt_modm(r1[6], pb); r[6] = (r1[6] - pb + (b << 30)); pb = b; - pb += r2[7]; b = lt_modm(r1[7], pb); r[7] = (r1[7] - pb + (b << 30)); pb = b; - pb += r2[8]; b = lt_modm(r1[8], pb); r[8] = (r1[8] - pb + (b << 24)); - - reduce256_modm(r); - reduce256_modm(r); -} - -/* addition modulo m */ -static void -add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { - bignum256modm_element_t c; - - c = x[0] + y[0]; r[0] = c & 0x3fffffff; c >>= 30; - c += x[1] + y[1]; r[1] = c & 0x3fffffff; c >>= 30; - c += x[2] + y[2]; r[2] = c & 0x3fffffff; c >>= 30; - c += x[3] + y[3]; r[3] = c & 0x3fffffff; c >>= 30; - c += x[4] + y[4]; r[4] = c & 0x3fffffff; c >>= 30; - c += x[5] + y[5]; r[5] = c & 0x3fffffff; c >>= 30; - c += x[6] + y[6]; r[6] = c & 0x3fffffff; c >>= 30; - c += x[7] + y[7]; r[7] = c & 0x3fffffff; c >>= 30; - c += x[8] + y[8]; r[8] = c; - - reduce256_modm(r); -} - -/* multiplication modulo m */ -static void -mul256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { - bignum256modm r1, q1; - uint64_t c; - bignum256modm_element_t f; - - /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) - q1 = x >> 248 = 264 bits = 9 30 bit elements */ - c = mul32x32_64(x[0], y[0]); - f = (bignum256modm_element_t)c; r1[0] = (f & 0x3fffffff); c >>= 30; - c += mul32x32_64(x[0], y[1]) + mul32x32_64(x[1], y[0]); - f = (bignum256modm_element_t)c; r1[1] = (f & 0x3fffffff); c >>= 30; - c += mul32x32_64(x[0], y[2]) + mul32x32_64(x[1], y[1]) + mul32x32_64(x[2], y[0]); - f = (bignum256modm_element_t)c; r1[2] = (f & 0x3fffffff); c >>= 30; - c += mul32x32_64(x[0], y[3]) + mul32x32_64(x[1], y[2]) + mul32x32_64(x[2], y[1]) + mul32x32_64(x[3], y[0]); - f = (bignum256modm_element_t)c; r1[3] = (f & 0x3fffffff); c >>= 30; - c += mul32x32_64(x[0], y[4]) + mul32x32_64(x[1], y[3]) + mul32x32_64(x[2], y[2]) + mul32x32_64(x[3], y[1]) + mul32x32_64(x[4], y[0]); - f = (bignum256modm_element_t)c; r1[4] = (f & 0x3fffffff); c >>= 30; - c += mul32x32_64(x[0], y[5]) + mul32x32_64(x[1], y[4]) + mul32x32_64(x[2], y[3]) + mul32x32_64(x[3], y[2]) + mul32x32_64(x[4], y[1]) + mul32x32_64(x[5], y[0]); - f = (bignum256modm_element_t)c; r1[5] = (f & 0x3fffffff); c >>= 30; - c += mul32x32_64(x[0], y[6]) + mul32x32_64(x[1], y[5]) + mul32x32_64(x[2], y[4]) + mul32x32_64(x[3], y[3]) + mul32x32_64(x[4], y[2]) + mul32x32_64(x[5], y[1]) + mul32x32_64(x[6], y[0]); - f = (bignum256modm_element_t)c; r1[6] = (f & 0x3fffffff); c >>= 30; - c += mul32x32_64(x[0], y[7]) + mul32x32_64(x[1], y[6]) + mul32x32_64(x[2], y[5]) + mul32x32_64(x[3], y[4]) + mul32x32_64(x[4], y[3]) + mul32x32_64(x[5], y[2]) + mul32x32_64(x[6], y[1]) + mul32x32_64(x[7], y[0]); - f = (bignum256modm_element_t)c; r1[7] = (f & 0x3fffffff); c >>= 30; - c += mul32x32_64(x[0], y[8]) + mul32x32_64(x[1], y[7]) + mul32x32_64(x[2], y[6]) + mul32x32_64(x[3], y[5]) + mul32x32_64(x[4], y[4]) + mul32x32_64(x[5], y[3]) + mul32x32_64(x[6], y[2]) + mul32x32_64(x[7], y[1]) + mul32x32_64(x[8], y[0]); - f = (bignum256modm_element_t)c; r1[8] = (f & 0x00ffffff); q1[0] = (f >> 8) & 0x3fffff; c >>= 30; - c += mul32x32_64(x[1], y[8]) + mul32x32_64(x[2], y[7]) + mul32x32_64(x[3], y[6]) + mul32x32_64(x[4], y[5]) + mul32x32_64(x[5], y[4]) + mul32x32_64(x[6], y[3]) + mul32x32_64(x[7], y[2]) + mul32x32_64(x[8], y[1]); - f = (bignum256modm_element_t)c; q1[0] = (q1[0] | (f << 22)) & 0x3fffffff; q1[1] = (f >> 8) & 0x3fffff; c >>= 30; - c += mul32x32_64(x[2], y[8]) + mul32x32_64(x[3], y[7]) + mul32x32_64(x[4], y[6]) + mul32x32_64(x[5], y[5]) + mul32x32_64(x[6], y[4]) + mul32x32_64(x[7], y[3]) + mul32x32_64(x[8], y[2]); - f = (bignum256modm_element_t)c; q1[1] = (q1[1] | (f << 22)) & 0x3fffffff; q1[2] = (f >> 8) & 0x3fffff; c >>= 30; - c += mul32x32_64(x[3], y[8]) + mul32x32_64(x[4], y[7]) + mul32x32_64(x[5], y[6]) + mul32x32_64(x[6], y[5]) + mul32x32_64(x[7], y[4]) + mul32x32_64(x[8], y[3]); - f = (bignum256modm_element_t)c; q1[2] = (q1[2] | (f << 22)) & 0x3fffffff; q1[3] = (f >> 8) & 0x3fffff; c >>= 30; - c += mul32x32_64(x[4], y[8]) + mul32x32_64(x[5], y[7]) + mul32x32_64(x[6], y[6]) + mul32x32_64(x[7], y[5]) + mul32x32_64(x[8], y[4]); - f = (bignum256modm_element_t)c; q1[3] = (q1[3] | (f << 22)) & 0x3fffffff; q1[4] = (f >> 8) & 0x3fffff; c >>= 30; - c += mul32x32_64(x[5], y[8]) + mul32x32_64(x[6], y[7]) + mul32x32_64(x[7], y[6]) + mul32x32_64(x[8], y[5]); - f = (bignum256modm_element_t)c; q1[4] = (q1[4] | (f << 22)) & 0x3fffffff; q1[5] = (f >> 8) & 0x3fffff; c >>= 30; - c += mul32x32_64(x[6], y[8]) + mul32x32_64(x[7], y[7]) + mul32x32_64(x[8], y[6]); - f = (bignum256modm_element_t)c; q1[5] = (q1[5] | (f << 22)) & 0x3fffffff; q1[6] = (f >> 8) & 0x3fffff; c >>= 30; - c += mul32x32_64(x[7], y[8]) + mul32x32_64(x[8], y[7]); - f = (bignum256modm_element_t)c; q1[6] = (q1[6] | (f << 22)) & 0x3fffffff; q1[7] = (f >> 8) & 0x3fffff; c >>= 30; - c += mul32x32_64(x[8], y[8]); - f = (bignum256modm_element_t)c; q1[7] = (q1[7] | (f << 22)) & 0x3fffffff; q1[8] = (f >> 8) & 0x3fffff; - - barrett_reduce256_modm(r, q1, r1); -} - -static void -expand256_modm(bignum256modm out, const unsigned char *in, size_t len) { - unsigned char work[64] = {0}; - bignum256modm_element_t x[16]; - bignum256modm q1; - - memcpy(work, in, len); - x[0] = U8TO32_LE(work + 0); - x[1] = U8TO32_LE(work + 4); - x[2] = U8TO32_LE(work + 8); - x[3] = U8TO32_LE(work + 12); - x[4] = U8TO32_LE(work + 16); - x[5] = U8TO32_LE(work + 20); - x[6] = U8TO32_LE(work + 24); - x[7] = U8TO32_LE(work + 28); - x[8] = U8TO32_LE(work + 32); - x[9] = U8TO32_LE(work + 36); - x[10] = U8TO32_LE(work + 40); - x[11] = U8TO32_LE(work + 44); - x[12] = U8TO32_LE(work + 48); - x[13] = U8TO32_LE(work + 52); - x[14] = U8TO32_LE(work + 56); - x[15] = U8TO32_LE(work + 60); - - /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) */ - out[0] = ( x[0]) & 0x3fffffff; - out[1] = ((x[ 0] >> 30) | (x[ 1] << 2)) & 0x3fffffff; - out[2] = ((x[ 1] >> 28) | (x[ 2] << 4)) & 0x3fffffff; - out[3] = ((x[ 2] >> 26) | (x[ 3] << 6)) & 0x3fffffff; - out[4] = ((x[ 3] >> 24) | (x[ 4] << 8)) & 0x3fffffff; - out[5] = ((x[ 4] >> 22) | (x[ 5] << 10)) & 0x3fffffff; - out[6] = ((x[ 5] >> 20) | (x[ 6] << 12)) & 0x3fffffff; - out[7] = ((x[ 6] >> 18) | (x[ 7] << 14)) & 0x3fffffff; - out[8] = ((x[ 7] >> 16) | (x[ 8] << 16)) & 0x00ffffff; - - /* 8*31 = 248 bits, no need to reduce */ - if (len < 32) - return; - - /* q1 = x >> 248 = 264 bits = 9 30 bit elements */ - q1[0] = ((x[ 7] >> 24) | (x[ 8] << 8)) & 0x3fffffff; - q1[1] = ((x[ 8] >> 22) | (x[ 9] << 10)) & 0x3fffffff; - q1[2] = ((x[ 9] >> 20) | (x[10] << 12)) & 0x3fffffff; - q1[3] = ((x[10] >> 18) | (x[11] << 14)) & 0x3fffffff; - q1[4] = ((x[11] >> 16) | (x[12] << 16)) & 0x3fffffff; - q1[5] = ((x[12] >> 14) | (x[13] << 18)) & 0x3fffffff; - q1[6] = ((x[13] >> 12) | (x[14] << 20)) & 0x3fffffff; - q1[7] = ((x[14] >> 10) | (x[15] << 22)) & 0x3fffffff; - q1[8] = ((x[15] >> 8) ); - - barrett_reduce256_modm(out, q1, out); -} - -static void -expand_raw256_modm(bignum256modm out, const unsigned char in[32]) { - bignum256modm_element_t x[8]; - - x[0] = U8TO32_LE(in + 0); - x[1] = U8TO32_LE(in + 4); - x[2] = U8TO32_LE(in + 8); - x[3] = U8TO32_LE(in + 12); - x[4] = U8TO32_LE(in + 16); - x[5] = U8TO32_LE(in + 20); - x[6] = U8TO32_LE(in + 24); - x[7] = U8TO32_LE(in + 28); - - out[0] = ( x[0]) & 0x3fffffff; - out[1] = ((x[ 0] >> 30) | (x[ 1] << 2)) & 0x3fffffff; - out[2] = ((x[ 1] >> 28) | (x[ 2] << 4)) & 0x3fffffff; - out[3] = ((x[ 2] >> 26) | (x[ 3] << 6)) & 0x3fffffff; - out[4] = ((x[ 3] >> 24) | (x[ 4] << 8)) & 0x3fffffff; - out[5] = ((x[ 4] >> 22) | (x[ 5] << 10)) & 0x3fffffff; - out[6] = ((x[ 5] >> 20) | (x[ 6] << 12)) & 0x3fffffff; - out[7] = ((x[ 6] >> 18) | (x[ 7] << 14)) & 0x3fffffff; - out[8] = ((x[ 7] >> 16) ) & 0x0000ffff; -} - -static void -contract256_modm(unsigned char out[32], const bignum256modm in) { - U32TO8_LE(out + 0, (in[0] ) | (in[1] << 30)); - U32TO8_LE(out + 4, (in[1] >> 2) | (in[2] << 28)); - U32TO8_LE(out + 8, (in[2] >> 4) | (in[3] << 26)); - U32TO8_LE(out + 12, (in[3] >> 6) | (in[4] << 24)); - U32TO8_LE(out + 16, (in[4] >> 8) | (in[5] << 22)); - U32TO8_LE(out + 20, (in[5] >> 10) | (in[6] << 20)); - U32TO8_LE(out + 24, (in[6] >> 12) | (in[7] << 18)); - U32TO8_LE(out + 28, (in[7] >> 14) | (in[8] << 16)); -} - - - -static void -contract256_window4_modm(signed char r[64], const bignum256modm in) { - char carry; - signed char *quads = r; - bignum256modm_element_t i, j, v; - - for (i = 0; i < 8; i += 2) { - v = in[i]; - for (j = 0; j < 7; j++) { - *quads++ = (v & 15); - v >>= 4; - } - v |= (in[i+1] << 2); - for (j = 0; j < 8; j++) { - *quads++ = (v & 15); - v >>= 4; - } - } - v = in[8]; - *quads++ = (v & 15); v >>= 4; - *quads++ = (v & 15); v >>= 4; - *quads++ = (v & 15); v >>= 4; - *quads++ = (v & 15); v >>= 4; - - /* making it signed */ - carry = 0; - for(i = 0; i < 63; i++) { - r[i] += carry; - r[i+1] += (r[i] >> 4); - r[i] &= 15; - carry = (r[i] >> 3); - r[i] -= (carry << 4); - } - r[63] += carry; -} - -static void -contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize) { - int i,j,k,b; - int m = (1 << (windowsize - 1)) - 1, soplen = 256; - signed char *bits = r; - bignum256modm_element_t v; - - /* first put the binary expansion into r */ - for (i = 0; i < 8; i++) { - v = s[i]; - for (j = 0; j < 30; j++, v >>= 1) - *bits++ = (v & 1); - } - v = s[8]; - for (j = 0; j < 16; j++, v >>= 1) - *bits++ = (v & 1); - - /* Making it sliding window */ - for (j = 0; j < soplen; j++) { - if (!r[j]) - continue; - - for (b = 1; (b < (soplen - j)) && (b <= 6); b++) { - if ((r[j] + (r[j + b] << b)) <= m) { - r[j] += r[j + b] << b; - r[j + b] = 0; - } else if ((r[j] - (r[j + b] << b)) >= -m) { - r[j] -= r[j + b] << b; - for (k = j + b; k < soplen; k++) { - if (!r[k]) { - r[k] = 1; - break; - } - r[k] = 0; - } - } else if (r[j + b]) { - break; - } - } - } -} - - -/* - helpers for batch verifcation, are allowed to be vartime -*/ - -/* out = a - b, a must be larger than b */ -static void -sub256_modm_batch(bignum256modm out, const bignum256modm a, const bignum256modm b, size_t limbsize) { - size_t i = 0; - bignum256modm_element_t carry = 0; - switch (limbsize) { - case 8: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; - case 7: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; - case 6: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; - case 5: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; - case 4: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; - case 3: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; - case 2: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; - case 1: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 31); out[i] &= 0x3fffffff; i++; - case 0: - default: out[i] = (a[i] - b[i]) - carry; - } -} - - -/* is a < b */ -static int -lt256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) { - switch (limbsize) { - case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1; - case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1; - case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1; - case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1; - case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1; - case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1; - case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1; - case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1; - case 0: if (a[0] > b[0]) return 0; if (a[0] < b[0]) return 1; - } - return 0; -} - -/* is a <= b */ -static int -lte256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) { - switch (limbsize) { - case 8: if (a[8] > b[8]) return 0; if (a[8] < b[8]) return 1; - case 7: if (a[7] > b[7]) return 0; if (a[7] < b[7]) return 1; - case 6: if (a[6] > b[6]) return 0; if (a[6] < b[6]) return 1; - case 5: if (a[5] > b[5]) return 0; if (a[5] < b[5]) return 1; - case 4: if (a[4] > b[4]) return 0; if (a[4] < b[4]) return 1; - case 3: if (a[3] > b[3]) return 0; if (a[3] < b[3]) return 1; - case 2: if (a[2] > b[2]) return 0; if (a[2] < b[2]) return 1; - case 1: if (a[1] > b[1]) return 0; if (a[1] < b[1]) return 1; - case 0: if (a[0] > b[0]) return 0; if (a[0] < b[0]) return 1; - } - return 1; -} - - -/* is a == 0 */ -static int -iszero256_modm_batch(const bignum256modm a) { - size_t i; - for (i = 0; i < 9; i++) - if (a[i]) - return 0; - return 1; -} - -/* is a == 1 */ -static int -isone256_modm_batch(const bignum256modm a) { - size_t i; - if (a[0] != 1) - return 0; - for (i = 1; i < 9; i++) - if (a[i]) - return 0; - return 1; -} - -/* can a fit in to (at most) 128 bits */ -static int -isatmost128bits256_modm_batch(const bignum256modm a) { - uint32_t mask = - ((a[8] ) | /* 16 */ - (a[7] ) | /* 46 */ - (a[6] ) | /* 76 */ - (a[5] ) | /* 106 */ - (a[4] & 0x3fffff00)); /* 128 */ - - return (mask == 0); -} diff --git a/external/ed25519-donna/modm-donna-64bit.h b/external/ed25519-donna/modm-donna-64bit.h deleted file mode 100644 index a47a38a42d..0000000000 --- a/external/ed25519-donna/modm-donna-64bit.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - Public domain by Andrew M. -*/ - - -/* - Arithmetic modulo the group order n = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989 - - k = 32 - b = 1 << 8 = 256 - m = 2^252 + 27742317777372353535851937790883648493 = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed - mu = floor( b^(k*2) / m ) = 0xfffffffffffffffffffffffffffffffeb2106215d086329a7ed9ce5a30a2c131b -*/ - -#define bignum256modm_bits_per_limb 56 -#define bignum256modm_limb_size 5 - -typedef uint64_t bignum256modm_element_t; -typedef bignum256modm_element_t bignum256modm[5]; - -static const bignum256modm modm_m = { - 0x12631a5cf5d3ed, - 0xf9dea2f79cd658, - 0x000000000014de, - 0x00000000000000, - 0x00000010000000 -}; - -static const bignum256modm modm_mu = { - 0x9ce5a30a2c131b, - 0x215d086329a7ed, - 0xffffffffeb2106, - 0xffffffffffffff, - 0x00000fffffffff -}; - -static bignum256modm_element_t -lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) { - return (a - b) >> 63; -} - -static void -reduce256_modm(bignum256modm r) { - bignum256modm t; - bignum256modm_element_t b = 0, pb, mask; - - /* t = r - m */ - pb = 0; - pb += modm_m[0]; b = lt_modm(r[0], pb); t[0] = (r[0] - pb + (b << 56)); pb = b; - pb += modm_m[1]; b = lt_modm(r[1], pb); t[1] = (r[1] - pb + (b << 56)); pb = b; - pb += modm_m[2]; b = lt_modm(r[2], pb); t[2] = (r[2] - pb + (b << 56)); pb = b; - pb += modm_m[3]; b = lt_modm(r[3], pb); t[3] = (r[3] - pb + (b << 56)); pb = b; - pb += modm_m[4]; b = lt_modm(r[4], pb); t[4] = (r[4] - pb + (b << 32)); - - /* keep r if r was smaller than m */ - mask = b - 1; - - r[0] ^= mask & (r[0] ^ t[0]); - r[1] ^= mask & (r[1] ^ t[1]); - r[2] ^= mask & (r[2] ^ t[2]); - r[3] ^= mask & (r[3] ^ t[3]); - r[4] ^= mask & (r[4] ^ t[4]); -} - -static void -barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256modm r1) { - bignum256modm q3, r2; - uint128_t c, mul; - bignum256modm_element_t f, b, pb; - - /* q1 = x >> 248 = 264 bits = 5 56 bit elements - q2 = mu * q1 - q3 = (q2 / 256(32+1)) = q2 / (2^8)^(32+1) = q2 >> 264 */ - mul64x64_128(c, modm_mu[0], q1[3]) mul64x64_128(mul, modm_mu[3], q1[0]) add128(c, mul) mul64x64_128(mul, modm_mu[1], q1[2]) add128(c, mul) mul64x64_128(mul, modm_mu[2], q1[1]) add128(c, mul) shr128(f, c, 56); - mul64x64_128(c, modm_mu[0], q1[4]) add128_64(c, f) mul64x64_128(mul, modm_mu[4], q1[0]) add128(c, mul) mul64x64_128(mul, modm_mu[3], q1[1]) add128(c, mul) mul64x64_128(mul, modm_mu[1], q1[3]) add128(c, mul) mul64x64_128(mul, modm_mu[2], q1[2]) add128(c, mul) - f = lo128(c); q3[0] = (f >> 40) & 0xffff; shr128(f, c, 56); - mul64x64_128(c, modm_mu[4], q1[1]) add128_64(c, f) mul64x64_128(mul, modm_mu[1], q1[4]) add128(c, mul) mul64x64_128(mul, modm_mu[2], q1[3]) add128(c, mul) mul64x64_128(mul, modm_mu[3], q1[2]) add128(c, mul) - f = lo128(c); q3[0] |= (f << 16) & 0xffffffffffffff; q3[1] = (f >> 40) & 0xffff; shr128(f, c, 56); - mul64x64_128(c, modm_mu[4], q1[2]) add128_64(c, f) mul64x64_128(mul, modm_mu[2], q1[4]) add128(c, mul) mul64x64_128(mul, modm_mu[3], q1[3]) add128(c, mul) - f = lo128(c); q3[1] |= (f << 16) & 0xffffffffffffff; q3[2] = (f >> 40) & 0xffff; shr128(f, c, 56); - mul64x64_128(c, modm_mu[4], q1[3]) add128_64(c, f) mul64x64_128(mul, modm_mu[3], q1[4]) add128(c, mul) - f = lo128(c); q3[2] |= (f << 16) & 0xffffffffffffff; q3[3] = (f >> 40) & 0xffff; shr128(f, c, 56); - mul64x64_128(c, modm_mu[4], q1[4]) add128_64(c, f) - f = lo128(c); q3[3] |= (f << 16) & 0xffffffffffffff; q3[4] = (f >> 40) & 0xffff; shr128(f, c, 56); - q3[4] |= (f << 16); - - mul64x64_128(c, modm_m[0], q3[0]) - r2[0] = lo128(c) & 0xffffffffffffff; shr128(f, c, 56); - mul64x64_128(c, modm_m[0], q3[1]) add128_64(c, f) mul64x64_128(mul, modm_m[1], q3[0]) add128(c, mul) - r2[1] = lo128(c) & 0xffffffffffffff; shr128(f, c, 56); - mul64x64_128(c, modm_m[0], q3[2]) add128_64(c, f) mul64x64_128(mul, modm_m[2], q3[0]) add128(c, mul) mul64x64_128(mul, modm_m[1], q3[1]) add128(c, mul) - r2[2] = lo128(c) & 0xffffffffffffff; shr128(f, c, 56); - mul64x64_128(c, modm_m[0], q3[3]) add128_64(c, f) mul64x64_128(mul, modm_m[3], q3[0]) add128(c, mul) mul64x64_128(mul, modm_m[1], q3[2]) add128(c, mul) mul64x64_128(mul, modm_m[2], q3[1]) add128(c, mul) - r2[3] = lo128(c) & 0xffffffffffffff; shr128(f, c, 56); - mul64x64_128(c, modm_m[0], q3[4]) add128_64(c, f) mul64x64_128(mul, modm_m[4], q3[0]) add128(c, mul) mul64x64_128(mul, modm_m[3], q3[1]) add128(c, mul) mul64x64_128(mul, modm_m[1], q3[3]) add128(c, mul) mul64x64_128(mul, modm_m[2], q3[2]) add128(c, mul) - r2[4] = lo128(c) & 0x0000ffffffffff; - - pb = 0; - pb += r2[0]; b = lt_modm(r1[0], pb); r[0] = (r1[0] - pb + (b << 56)); pb = b; - pb += r2[1]; b = lt_modm(r1[1], pb); r[1] = (r1[1] - pb + (b << 56)); pb = b; - pb += r2[2]; b = lt_modm(r1[2], pb); r[2] = (r1[2] - pb + (b << 56)); pb = b; - pb += r2[3]; b = lt_modm(r1[3], pb); r[3] = (r1[3] - pb + (b << 56)); pb = b; - pb += r2[4]; b = lt_modm(r1[4], pb); r[4] = (r1[4] - pb + (b << 40)); - - reduce256_modm(r); - reduce256_modm(r); -} - - -static void -add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { - bignum256modm_element_t c; - - c = x[0] + y[0]; r[0] = c & 0xffffffffffffff; c >>= 56; - c += x[1] + y[1]; r[1] = c & 0xffffffffffffff; c >>= 56; - c += x[2] + y[2]; r[2] = c & 0xffffffffffffff; c >>= 56; - c += x[3] + y[3]; r[3] = c & 0xffffffffffffff; c >>= 56; - c += x[4] + y[4]; r[4] = c; - - reduce256_modm(r); -} - -static void -mul256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) { - bignum256modm q1, r1; - uint128_t c, mul; - bignum256modm_element_t f; - - mul64x64_128(c, x[0], y[0]) - f = lo128(c); r1[0] = f & 0xffffffffffffff; shr128(f, c, 56); - mul64x64_128(c, x[0], y[1]) add128_64(c, f) mul64x64_128(mul, x[1], y[0]) add128(c, mul) - f = lo128(c); r1[1] = f & 0xffffffffffffff; shr128(f, c, 56); - mul64x64_128(c, x[0], y[2]) add128_64(c, f) mul64x64_128(mul, x[2], y[0]) add128(c, mul) mul64x64_128(mul, x[1], y[1]) add128(c, mul) - f = lo128(c); r1[2] = f & 0xffffffffffffff; shr128(f, c, 56); - mul64x64_128(c, x[0], y[3]) add128_64(c, f) mul64x64_128(mul, x[3], y[0]) add128(c, mul) mul64x64_128(mul, x[1], y[2]) add128(c, mul) mul64x64_128(mul, x[2], y[1]) add128(c, mul) - f = lo128(c); r1[3] = f & 0xffffffffffffff; shr128(f, c, 56); - mul64x64_128(c, x[0], y[4]) add128_64(c, f) mul64x64_128(mul, x[4], y[0]) add128(c, mul) mul64x64_128(mul, x[3], y[1]) add128(c, mul) mul64x64_128(mul, x[1], y[3]) add128(c, mul) mul64x64_128(mul, x[2], y[2]) add128(c, mul) - f = lo128(c); r1[4] = f & 0x0000ffffffffff; q1[0] = (f >> 24) & 0xffffffff; shr128(f, c, 56); - mul64x64_128(c, x[4], y[1]) add128_64(c, f) mul64x64_128(mul, x[1], y[4]) add128(c, mul) mul64x64_128(mul, x[2], y[3]) add128(c, mul) mul64x64_128(mul, x[3], y[2]) add128(c, mul) - f = lo128(c); q1[0] |= (f << 32) & 0xffffffffffffff; q1[1] = (f >> 24) & 0xffffffff; shr128(f, c, 56); - mul64x64_128(c, x[4], y[2]) add128_64(c, f) mul64x64_128(mul, x[2], y[4]) add128(c, mul) mul64x64_128(mul, x[3], y[3]) add128(c, mul) - f = lo128(c); q1[1] |= (f << 32) & 0xffffffffffffff; q1[2] = (f >> 24) & 0xffffffff; shr128(f, c, 56); - mul64x64_128(c, x[4], y[3]) add128_64(c, f) mul64x64_128(mul, x[3], y[4]) add128(c, mul) - f = lo128(c); q1[2] |= (f << 32) & 0xffffffffffffff; q1[3] = (f >> 24) & 0xffffffff; shr128(f, c, 56); - mul64x64_128(c, x[4], y[4]) add128_64(c, f) - f = lo128(c); q1[3] |= (f << 32) & 0xffffffffffffff; q1[4] = (f >> 24) & 0xffffffff; shr128(f, c, 56); - q1[4] |= (f << 32); - - barrett_reduce256_modm(r, q1, r1); -} - -static void -expand256_modm(bignum256modm out, const unsigned char *in, size_t len) { - unsigned char work[64] = {0}; - bignum256modm_element_t x[16]; - bignum256modm q1; - - memcpy(work, in, len); - x[0] = U8TO64_LE(work + 0); - x[1] = U8TO64_LE(work + 8); - x[2] = U8TO64_LE(work + 16); - x[3] = U8TO64_LE(work + 24); - x[4] = U8TO64_LE(work + 32); - x[5] = U8TO64_LE(work + 40); - x[6] = U8TO64_LE(work + 48); - x[7] = U8TO64_LE(work + 56); - - /* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) */ - out[0] = ( x[0]) & 0xffffffffffffff; - out[1] = ((x[ 0] >> 56) | (x[ 1] << 8)) & 0xffffffffffffff; - out[2] = ((x[ 1] >> 48) | (x[ 2] << 16)) & 0xffffffffffffff; - out[3] = ((x[ 2] >> 40) | (x[ 3] << 24)) & 0xffffffffffffff; - out[4] = ((x[ 3] >> 32) | (x[ 4] << 32)) & 0x0000ffffffffff; - - /* under 252 bits, no need to reduce */ - if (len < 32) - return; - - /* q1 = x >> 248 = 264 bits */ - q1[0] = ((x[ 3] >> 56) | (x[ 4] << 8)) & 0xffffffffffffff; - q1[1] = ((x[ 4] >> 48) | (x[ 5] << 16)) & 0xffffffffffffff; - q1[2] = ((x[ 5] >> 40) | (x[ 6] << 24)) & 0xffffffffffffff; - q1[3] = ((x[ 6] >> 32) | (x[ 7] << 32)) & 0xffffffffffffff; - q1[4] = ((x[ 7] >> 24) ); - - barrett_reduce256_modm(out, q1, out); -} - -static void -expand_raw256_modm(bignum256modm out, const unsigned char in[32]) { - bignum256modm_element_t x[4]; - - x[0] = U8TO64_LE(in + 0); - x[1] = U8TO64_LE(in + 8); - x[2] = U8TO64_LE(in + 16); - x[3] = U8TO64_LE(in + 24); - - out[0] = ( x[0]) & 0xffffffffffffff; - out[1] = ((x[ 0] >> 56) | (x[ 1] << 8)) & 0xffffffffffffff; - out[2] = ((x[ 1] >> 48) | (x[ 2] << 16)) & 0xffffffffffffff; - out[3] = ((x[ 2] >> 40) | (x[ 3] << 24)) & 0xffffffffffffff; - out[4] = ((x[ 3] >> 32) ) & 0x000000ffffffff; -} - -static void -contract256_modm(unsigned char out[32], const bignum256modm in) { - U64TO8_LE(out + 0, (in[0] ) | (in[1] << 56)); - U64TO8_LE(out + 8, (in[1] >> 8) | (in[2] << 48)); - U64TO8_LE(out + 16, (in[2] >> 16) | (in[3] << 40)); - U64TO8_LE(out + 24, (in[3] >> 24) | (in[4] << 32)); -} - -static void -contract256_window4_modm(signed char r[64], const bignum256modm in) { - char carry; - signed char *quads = r; - bignum256modm_element_t i, j, v, m; - - for (i = 0; i < 5; i++) { - v = in[i]; - m = (i == 4) ? 8 : 14; - for (j = 0; j < m; j++) { - *quads++ = (v & 15); - v >>= 4; - } - } - - /* making it signed */ - carry = 0; - for(i = 0; i < 63; i++) { - r[i] += carry; - r[i+1] += (r[i] >> 4); - r[i] &= 15; - carry = (r[i] >> 3); - r[i] -= (carry << 4); - } - r[63] += carry; -} - -static void -contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize) { - int i,j,k,b; - int m = (1 << (windowsize - 1)) - 1, soplen = 256; - signed char *bits = r; - bignum256modm_element_t v; - - /* first put the binary expansion into r */ - for (i = 0; i < 4; i++) { - v = s[i]; - for (j = 0; j < 56; j++, v >>= 1) - *bits++ = (v & 1); - } - v = s[4]; - for (j = 0; j < 32; j++, v >>= 1) - *bits++ = (v & 1); - - /* Making it sliding window */ - for (j = 0; j < soplen; j++) { - if (!r[j]) - continue; - - for (b = 1; (b < (soplen - j)) && (b <= 6); b++) { - if ((r[j] + (r[j + b] << b)) <= m) { - r[j] += r[j + b] << b; - r[j + b] = 0; - } else if ((r[j] - (r[j + b] << b)) >= -m) { - r[j] -= r[j + b] << b; - for (k = j + b; k < soplen; k++) { - if (!r[k]) { - r[k] = 1; - break; - } - r[k] = 0; - } - } else if (r[j + b]) { - break; - } - } - } -} - -/* - helpers for batch verifcation, are allowed to be vartime -*/ - -/* out = a - b, a must be larger than b */ -static void -sub256_modm_batch(bignum256modm out, const bignum256modm a, const bignum256modm b, size_t limbsize) { - size_t i = 0; - bignum256modm_element_t carry = 0; - switch (limbsize) { - case 4: out[i] = (a[i] - b[i]) ; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; - case 3: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; - case 2: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; - case 1: out[i] = (a[i] - b[i]) - carry; carry = (out[i] >> 63); out[i] &= 0xffffffffffffff; i++; - case 0: - default: out[i] = (a[i] - b[i]) - carry; - } -} - - -/* is a < b */ -static int -lt256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) { - size_t i = 0; - bignum256modm_element_t t, carry = 0; - switch (limbsize) { - case 4: t = (a[i] - b[i]) ; carry = (t >> 63); i++; - case 3: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; - case 2: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; - case 1: t = (a[i] - b[i]) - carry; carry = (t >> 63); i++; - case 0: t = (a[i] - b[i]) - carry; carry = (t >> 63); - } - return (int)carry; -} - -/* is a <= b */ -static int -lte256_modm_batch(const bignum256modm a, const bignum256modm b, size_t limbsize) { - size_t i = 0; - bignum256modm_element_t t, carry = 0; - switch (limbsize) { - case 4: t = (b[i] - a[i]) ; carry = (t >> 63); i++; - case 3: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; - case 2: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; - case 1: t = (b[i] - a[i]) - carry; carry = (t >> 63); i++; - case 0: t = (b[i] - a[i]) - carry; carry = (t >> 63); - } - return (int)!carry; -} - -/* is a == 0 */ -static int -iszero256_modm_batch(const bignum256modm a) { - size_t i; - for (i = 0; i < 5; i++) - if (a[i]) - return 0; - return 1; -} - -/* is a == 1 */ -static int -isone256_modm_batch(const bignum256modm a) { - size_t i; - for (i = 0; i < 5; i++) - if (a[i] != ((i) ? 0 : 1)) - return 0; - return 1; -} - -/* can a fit in to (at most) 128 bits */ -static int -isatmost128bits256_modm_batch(const bignum256modm a) { - uint64_t mask = - ((a[4] ) | /* 32 */ - (a[3] ) | /* 88 */ - (a[2] & 0xffffffffff0000)); - - return (mask == 0); -} diff --git a/external/ed25519-donna/regression.h b/external/ed25519-donna/regression.h deleted file mode 100644 index b4c2e62c0a..0000000000 --- a/external/ed25519-donna/regression.h +++ /dev/null @@ -1,1024 +0,0 @@ -{{0x9d,0x61,0xb1,0x9d,0xef,0xfd,0x5a,0x60,0xba,0x84,0x4a,0xf4,0x92,0xec,0x2c,0xc4,0x44,0x49,0xc5,0x69,0x7b,0x32,0x69,0x19,0x70,0x3b,0xac,0x03,0x1c,0xae,0x7f,0x60,},{0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7,0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a,0x0e,0xe1,0x72,0xf3,0xda,0xa6,0x23,0x25,0xaf,0x02,0x1a,0x68,0xf7,0x07,0x51,0x1a,},{0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72,0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a,0x84,0x87,0x7f,0x1e,0xb8,0xe5,0xd9,0x74,0xd8,0x73,0xe0,0x65,0x22,0x49,0x01,0x55,0x5f,0xb8,0x82,0x15,0x90,0xa3,0x3b,0xac,0xc6,0x1e,0x39,0x70,0x1c,0xf9,0xb4,0x6b,0xd2,0x5b,0xf5,0xf0,0x59,0x5b,0xbe,0x24,0x65,0x51,0x41,0x43,0x8e,0x7a,0x10,0x0b,},""}, -{{0x4c,0xcd,0x08,0x9b,0x28,0xff,0x96,0xda,0x9d,0xb6,0xc3,0x46,0xec,0x11,0x4e,0x0f,0x5b,0x8a,0x31,0x9f,0x35,0xab,0xa6,0x24,0xda,0x8c,0xf6,0xed,0x4f,0xb8,0xa6,0xfb,},{0x3d,0x40,0x17,0xc3,0xe8,0x43,0x89,0x5a,0x92,0xb7,0x0a,0xa7,0x4d,0x1b,0x7e,0xbc,0x9c,0x98,0x2c,0xcf,0x2e,0xc4,0x96,0x8c,0xc0,0xcd,0x55,0xf1,0x2a,0xf4,0x66,0x0c,},{0x92,0xa0,0x09,0xa9,0xf0,0xd4,0xca,0xb8,0x72,0x0e,0x82,0x0b,0x5f,0x64,0x25,0x40,0xa2,0xb2,0x7b,0x54,0x16,0x50,0x3f,0x8f,0xb3,0x76,0x22,0x23,0xeb,0xdb,0x69,0xda,0x08,0x5a,0xc1,0xe4,0x3e,0x15,0x99,0x6e,0x45,0x8f,0x36,0x13,0xd0,0xf1,0x1d,0x8c,0x38,0x7b,0x2e,0xae,0xb4,0x30,0x2a,0xee,0xb0,0x0d,0x29,0x16,0x12,0xbb,0x0c,0x00,},"\x72"}, -{{0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b,0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1,0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b,0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7,},{0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3,0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58,0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac,0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25,},{0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02,0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3,0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44,0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac,0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90,0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59,0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a,},"\xaf\x82"}, -{{0x0d,0x4a,0x05,0xb0,0x73,0x52,0xa5,0x43,0x6e,0x18,0x03,0x56,0xda,0x0a,0xe6,0xef,0xa0,0x34,0x5f,0xf7,0xfb,0x15,0x72,0x57,0x57,0x72,0xe8,0x00,0x5e,0xd9,0x78,0xe9,},{0xe6,0x1a,0x18,0x5b,0xce,0xf2,0x61,0x3a,0x6c,0x7c,0xb7,0x97,0x63,0xce,0x94,0x5d,0x3b,0x24,0x5d,0x76,0x11,0x4d,0xd4,0x40,0xbc,0xf5,0xf2,0xdc,0x1a,0xa5,0x70,0x57,},{0xd9,0x86,0x8d,0x52,0xc2,0xbe,0xbc,0xe5,0xf3,0xfa,0x5a,0x79,0x89,0x19,0x70,0xf3,0x09,0xcb,0x65,0x91,0xe3,0xe1,0x70,0x2a,0x70,0x27,0x6f,0xa9,0x7c,0x24,0xb3,0xa8,0xe5,0x86,0x06,0xc3,0x8c,0x97,0x58,0x52,0x9d,0xa5,0x0e,0xe3,0x1b,0x82,0x19,0xcb,0xa4,0x52,0x71,0xc6,0x89,0xaf,0xa6,0x0b,0x0e,0xa2,0x6c,0x99,0xdb,0x19,0xb0,0x0c,},"\xcb\xc7\x7b"}, -{{0x6d,0xf9,0x34,0x0c,0x13,0x8c,0xc1,0x88,0xb5,0xfe,0x44,0x64,0xeb,0xaa,0x3f,0x7f,0xc2,0x06,0xa2,0xd5,0x5c,0x34,0x34,0x70,0x7e,0x74,0xc9,0xfc,0x04,0xe2,0x0e,0xbb,},{0xc0,0xda,0xc1,0x02,0xc4,0x53,0x31,0x86,0xe2,0x5d,0xc4,0x31,0x28,0x47,0x23,0x53,0xea,0xab,0xdb,0x87,0x8b,0x15,0x2a,0xeb,0x8e,0x00,0x1f,0x92,0xd9,0x02,0x33,0xa7,},{0x12,0x4f,0x6f,0xc6,0xb0,0xd1,0x00,0x84,0x27,0x69,0xe7,0x1b,0xd5,0x30,0x66,0x4d,0x88,0x8d,0xf8,0x50,0x7d,0xf6,0xc5,0x6d,0xed,0xfd,0xb5,0x09,0xae,0xb9,0x34,0x16,0xe2,0x6b,0x91,0x8d,0x38,0xaa,0x06,0x30,0x5d,0xf3,0x09,0x56,0x97,0xc1,0x8b,0x2a,0xa8,0x32,0xea,0xa5,0x2e,0xdc,0x0a,0xe4,0x9f,0xba,0xe5,0xa8,0x5e,0x15,0x0c,0x07,},"\x5f\x4c\x89\x89"}, -{{0xb7,0x80,0x38,0x1a,0x65,0xed,0xf8,0xb7,0x8f,0x69,0x45,0xe8,0xdb,0xec,0x79,0x41,0xac,0x04,0x9f,0xd4,0xc6,0x10,0x40,0xcf,0x0c,0x32,0x43,0x57,0x97,0x5a,0x29,0x3c,},{0xe2,0x53,0xaf,0x07,0x66,0x80,0x4b,0x86,0x9b,0xb1,0x59,0x5b,0xe9,0x76,0x5b,0x53,0x48,0x86,0xbb,0xaa,0xb8,0x30,0x5b,0xf5,0x0d,0xbc,0x7f,0x89,0x9b,0xfb,0x5f,0x01,},{0xb2,0xfc,0x46,0xad,0x47,0xaf,0x46,0x44,0x78,0xc1,0x99,0xe1,0xf8,0xbe,0x16,0x9f,0x1b,0xe6,0x32,0x7c,0x7f,0x9a,0x0a,0x66,0x89,0x37,0x1c,0xa9,0x4c,0xaf,0x04,0x06,0x4a,0x01,0xb2,0x2a,0xff,0x15,0x20,0xab,0xd5,0x89,0x51,0x34,0x16,0x03,0xfa,0xed,0x76,0x8c,0xf7,0x8c,0xe9,0x7a,0xe7,0xb0,0x38,0xab,0xfe,0x45,0x6a,0xa1,0x7c,0x09,},"\x18\xb6\xbe\xc0\x97"}, -{{0x78,0xae,0x9e,0xff,0xe6,0xf2,0x45,0xe9,0x24,0xa7,0xbe,0x63,0x04,0x11,0x46,0xeb,0xc6,0x70,0xdb,0xd3,0x06,0x0c,0xba,0x67,0xfb,0xc6,0x21,0x6f,0xeb,0xc4,0x45,0x46,},{0xfb,0xcf,0xbf,0xa4,0x05,0x05,0xd7,0xf2,0xbe,0x44,0x4a,0x33,0xd1,0x85,0xcc,0x54,0xe1,0x6d,0x61,0x52,0x60,0xe1,0x64,0x0b,0x2b,0x50,0x87,0xb8,0x3e,0xe3,0x64,0x3d,},{0x6e,0xd6,0x29,0xfc,0x1d,0x9c,0xe9,0xe1,0x46,0x87,0x55,0xff,0x63,0x6d,0x5a,0x3f,0x40,0xa5,0xd9,0xc9,0x1a,0xfd,0x93,0xb7,0x9d,0x24,0x18,0x30,0xf7,0xe5,0xfa,0x29,0x85,0x4b,0x8f,0x20,0xcc,0x6e,0xec,0xbb,0x24,0x8d,0xbd,0x8d,0x16,0xd1,0x4e,0x99,0x75,0x21,0x94,0xe4,0x90,0x4d,0x09,0xc7,0x4d,0x63,0x95,0x18,0x83,0x9d,0x23,0x00,},"\x89\x01\x0d\x85\x59\x72"}, -{{0x69,0x18,0x65,0xbf,0xc8,0x2a,0x1e,0x4b,0x57,0x4e,0xec,0xde,0x4c,0x75,0x19,0x09,0x3f,0xaf,0x0c,0xf8,0x67,0x38,0x02,0x34,0xe3,0x66,0x46,0x45,0xc6,0x1c,0x5f,0x79,},{0x98,0xa5,0xe3,0xa3,0x6e,0x67,0xaa,0xba,0x89,0x88,0x8b,0xf0,0x93,0xde,0x1a,0xd9,0x63,0xe7,0x74,0x01,0x3b,0x39,0x02,0xbf,0xab,0x35,0x6d,0x8b,0x90,0x17,0x8a,0x63,},{0x6e,0x0a,0xf2,0xfe,0x55,0xae,0x37,0x7a,0x6b,0x7a,0x72,0x78,0xed,0xfb,0x41,0x9b,0xd3,0x21,0xe0,0x6d,0x0d,0xf5,0xe2,0x70,0x37,0xdb,0x88,0x12,0xe7,0xe3,0x52,0x98,0x10,0xfa,0x55,0x52,0xf6,0xc0,0x02,0x09,0x85,0xca,0x17,0xa0,0xe0,0x2e,0x03,0x6d,0x7b,0x22,0x2a,0x24,0xf9,0x9b,0x77,0xb7,0x5f,0xdd,0x16,0xcb,0x05,0x56,0x81,0x07,},"\xb4\xa8\xf3\x81\xe7\x0e\x7a"}, -{{0x3b,0x26,0x51,0x6f,0xb3,0xdc,0x88,0xeb,0x18,0x1b,0x9e,0xd7,0x3f,0x0b,0xcd,0x52,0xbc,0xd6,0xb4,0xc7,0x88,0xe4,0xbc,0xaf,0x46,0x05,0x7f,0xd0,0x78,0xbe,0xe0,0x73,},{0xf8,0x1f,0xb5,0x4a,0x82,0x5f,0xce,0xd9,0x5e,0xb0,0x33,0xaf,0xcd,0x64,0x31,0x40,0x75,0xab,0xfb,0x0a,0xbd,0x20,0xa9,0x70,0x89,0x25,0x03,0x43,0x6f,0x34,0xb8,0x63,},{0xd6,0xad,0xde,0xc5,0xaf,0xb0,0x52,0x8a,0xc1,0x7b,0xb1,0x78,0xd3,0xe7,0xf2,0x88,0x7f,0x9a,0xdb,0xb1,0xad,0x16,0xe1,0x10,0x54,0x5e,0xf3,0xbc,0x57,0xf9,0xde,0x23,0x14,0xa5,0xc8,0x38,0x8f,0x72,0x3b,0x89,0x07,0xbe,0x0f,0x3a,0xc9,0x0c,0x62,0x59,0xbb,0xe8,0x85,0xec,0xc1,0x76,0x45,0xdf,0x3d,0xb7,0xd4,0x88,0xf8,0x05,0xfa,0x08,},"\x42\x84\xab\xc5\x1b\xb6\x72\x35"}, -{{0xed,0xc6,0xf5,0xfb,0xdd,0x1c,0xee,0x4d,0x10,0x1c,0x06,0x35,0x30,0xa3,0x04,0x90,0xb2,0x21,0xbe,0x68,0xc0,0x36,0xf5,0xb0,0x7d,0x0f,0x95,0x3b,0x74,0x5d,0xf1,0x92,},{0xc1,0xa4,0x9c,0x66,0xe6,0x17,0xf9,0xef,0x5e,0xc6,0x6b,0xc4,0xc6,0x56,0x4c,0xa3,0x3d,0xe2,0xa5,0xfb,0x5e,0x14,0x64,0x06,0x2e,0x6d,0x6c,0x62,0x19,0x15,0x5e,0xfd,},{0x2c,0x76,0xa0,0x4a,0xf2,0x39,0x1c,0x14,0x70,0x82,0xe3,0x3f,0xaa,0xcd,0xbe,0x56,0x64,0x2a,0x1e,0x13,0x4b,0xd3,0x88,0x62,0x0b,0x85,0x2b,0x90,0x1a,0x6b,0xc1,0x6f,0xf6,0xc9,0xcc,0x94,0x04,0xc4,0x1d,0xea,0x12,0xed,0x28,0x1d,0xa0,0x67,0xa1,0x51,0x38,0x66,0xf9,0xd9,0x64,0xf8,0xbd,0xd2,0x49,0x53,0x85,0x6c,0x50,0x04,0x29,0x01,},"\x67\x2b\xf8\x96\x5d\x04\xbc\x51\x46"}, -{{0x4e,0x7d,0x21,0xfb,0x3b,0x18,0x97,0x57,0x1a,0x44,0x58,0x33,0xbe,0x0f,0x9f,0xd4,0x1c,0xd6,0x2b,0xe3,0xaa,0x04,0x04,0x0f,0x89,0x34,0xe1,0xfc,0xbd,0xca,0xcd,0x45,},{0x31,0xb2,0x52,0x4b,0x83,0x48,0xf7,0xab,0x1d,0xfa,0xfa,0x67,0x5c,0xc5,0x38,0xe9,0xa8,0x4e,0x3f,0xe5,0x81,0x9e,0x27,0xc1,0x2a,0xd8,0xbb,0xc1,0xa3,0x6e,0x4d,0xff,},{0x28,0xe4,0x59,0x8c,0x41,0x5a,0xe9,0xde,0x01,0xf0,0x3f,0x9f,0x3f,0xab,0x4e,0x91,0x9e,0x8b,0xf5,0x37,0xdd,0x2b,0x0c,0xdf,0x6e,0x79,0xb9,0xe6,0x55,0x9c,0x94,0x09,0xd9,0x15,0x1a,0x4c,0x40,0xf0,0x83,0x19,0x39,0x37,0x62,0x7c,0x36,0x94,0x88,0x25,0x9e,0x99,0xda,0x5a,0x9f,0x0a,0x87,0x49,0x7f,0xa6,0x69,0x6a,0x5d,0xd6,0xce,0x08,},"\x33\xd7\xa7\x86\xad\xed\x8c\x1b\xf6\x91"}, -{{0xa9,0x80,0xf8,0x92,0xdb,0x13,0xc9,0x9a,0x3e,0x89,0x71,0xe9,0x65,0xb2,0xff,0x3d,0x41,0xea,0xfd,0x54,0x09,0x3b,0xc9,0xf3,0x4d,0x1f,0xd2,0x2d,0x84,0x11,0x5b,0xb6,},{0x44,0xb5,0x7e,0xe3,0x0c,0xdb,0x55,0x82,0x9d,0x0a,0x5d,0x4f,0x04,0x6b,0xae,0xf0,0x78,0xf1,0xe9,0x7a,0x7f,0x21,0xb6,0x2d,0x75,0xf8,0xe9,0x6e,0xa1,0x39,0xc3,0x5f,},{0x77,0xd3,0x89,0xe5,0x99,0x63,0x0d,0x93,0x40,0x76,0x32,0x95,0x83,0xcd,0x41,0x05,0xa6,0x49,0xa9,0x29,0x2a,0xbc,0x44,0xcd,0x28,0xc4,0x00,0x00,0xc8,0xe2,0xf5,0xac,0x76,0x60,0xa8,0x1c,0x85,0xb7,0x2a,0xf8,0x45,0x2d,0x7d,0x25,0xc0,0x70,0x86,0x1d,0xae,0x91,0x60,0x1c,0x78,0x03,0xd6,0x56,0x53,0x16,0x50,0xdd,0x4e,0x5c,0x41,0x00,},"\x34\x86\xf6\x88\x48\xa6\x5a\x0e\xb5\x50\x7d"}, -{{0x5b,0x5a,0x61,0x9f,0x8c,0xe1,0xc6,0x6d,0x7c,0xe2,0x6e,0x5a,0x2a,0xe7,0xb0,0xc0,0x4f,0xeb,0xcd,0x34,0x6d,0x28,0x6c,0x92,0x9e,0x19,0xd0,0xd5,0x97,0x3b,0xfe,0xf9,},{0x6f,0xe8,0x36,0x93,0xd0,0x11,0xd1,0x11,0x13,0x1c,0x4f,0x3f,0xba,0xaa,0x40,0xa9,0xd3,0xd7,0x6b,0x30,0x01,0x2f,0xf7,0x3b,0xb0,0xe3,0x9e,0xc2,0x7a,0xb1,0x82,0x57,},{0x0f,0x9a,0xd9,0x79,0x30,0x33,0xa2,0xfa,0x06,0x61,0x4b,0x27,0x7d,0x37,0x38,0x1e,0x6d,0x94,0xf6,0x5a,0xc2,0xa5,0xa9,0x45,0x58,0xd0,0x9e,0xd6,0xce,0x92,0x22,0x58,0xc1,0xa5,0x67,0x95,0x2e,0x86,0x3a,0xc9,0x42,0x97,0xae,0xc3,0xc0,0xd0,0xc8,0xdd,0xf7,0x10,0x84,0xe5,0x04,0x86,0x0b,0xb6,0xba,0x27,0x44,0x9b,0x55,0xad,0xc4,0x0e,},"\x5a\x8d\x9d\x0a\x22\x35\x7e\x66\x55\xf9\xc7\x85"}, -{{0x94,0x0c,0x89,0xfe,0x40,0xa8,0x1d,0xaf,0xbd,0xb2,0x41,0x6d,0x14,0xae,0x46,0x91,0x19,0x86,0x97,0x44,0x41,0x0c,0x33,0x03,0xbf,0xaa,0x02,0x41,0xda,0xc5,0x78,0x00,},{0xa2,0xeb,0x8c,0x05,0x01,0xe3,0x0b,0xae,0x0c,0xf8,0x42,0xd2,0xbd,0xe8,0xde,0xc7,0x38,0x6f,0x6b,0x7f,0xc3,0x98,0x1b,0x8c,0x57,0xc9,0x79,0x2b,0xb9,0x4c,0xf2,0xdd,},{0xd8,0xbb,0x64,0xaa,0xd8,0xc9,0x95,0x5a,0x11,0x5a,0x79,0x3a,0xdd,0xd2,0x4f,0x7f,0x2b,0x07,0x76,0x48,0x71,0x4f,0x49,0xc4,0x69,0x4e,0xc9,0x95,0xb3,0x30,0xd0,0x9d,0x64,0x0d,0xf3,0x10,0xf4,0x47,0xfd,0x7b,0x6c,0xb5,0xc1,0x4f,0x9f,0xe9,0xf4,0x90,0xbc,0xf8,0xcf,0xad,0xbf,0xd2,0x16,0x9c,0x8a,0xc2,0x0d,0x3b,0x8a,0xf4,0x9a,0x0c,},"\xb8\x7d\x38\x13\xe0\x3f\x58\xcf\x19\xfd\x0b\x63\x95"}, -{{0x9a,0xca,0xd9,0x59,0xd2,0x16,0x21,0x2d,0x78,0x9a,0x11,0x92,0x52,0xeb,0xfe,0x0c,0x96,0x51,0x2a,0x23,0xc7,0x3b,0xd9,0xf3,0xb2,0x02,0x29,0x2d,0x69,0x16,0xa7,0x38,},{0xcf,0x3a,0xf8,0x98,0x46,0x7a,0x5b,0x7a,0x52,0xd3,0x3d,0x53,0xbc,0x03,0x7e,0x26,0x42,0xa8,0xda,0x99,0x69,0x03,0xfc,0x25,0x22,0x17,0xe9,0xc0,0x33,0xe2,0xf2,0x91,},{0x6e,0xe3,0xfe,0x81,0xe2,0x3c,0x60,0xeb,0x23,0x12,0xb2,0x00,0x6b,0x3b,0x25,0xe6,0x83,0x8e,0x02,0x10,0x66,0x23,0xf8,0x44,0xc4,0x4e,0xdb,0x8d,0xaf,0xd6,0x6a,0xb0,0x67,0x10,0x87,0xfd,0x19,0x5d,0xf5,0xb8,0xf5,0x8a,0x1d,0x6e,0x52,0xaf,0x42,0x90,0x80,0x53,0xd5,0x5c,0x73,0x21,0x01,0x00,0x92,0x74,0x87,0x95,0xef,0x94,0xcf,0x06,},"\x55\xc7\xfa\x43\x4f\x5e\xd8\xcd\xec\x2b\x7a\xea\xc1\x73"}, -{{0xd5,0xae,0xee,0x41,0xee,0xb0,0xe9,0xd1,0xbf,0x83,0x37,0xf9,0x39,0x58,0x7e,0xbe,0x29,0x61,0x61,0xe6,0xbf,0x52,0x09,0xf5,0x91,0xec,0x93,0x9e,0x14,0x40,0xc3,0x00,},{0xfd,0x2a,0x56,0x57,0x23,0x16,0x3e,0x29,0xf5,0x3c,0x9d,0xe3,0xd5,0xe8,0xfb,0xe3,0x6a,0x7a,0xb6,0x6e,0x14,0x39,0xec,0x4e,0xae,0x9c,0x0a,0x60,0x4a,0xf2,0x91,0xa5,},{0xf6,0x8d,0x04,0x84,0x7e,0x5b,0x24,0x97,0x37,0x89,0x9c,0x01,0x4d,0x31,0xc8,0x05,0xc5,0x00,0x7a,0x62,0xc0,0xa1,0x0d,0x50,0xbb,0x15,0x38,0xc5,0xf3,0x55,0x03,0x95,0x1f,0xbc,0x1e,0x08,0x68,0x2f,0x2c,0xc0,0xc9,0x2e,0xfe,0x8f,0x49,0x85,0xde,0xc6,0x1d,0xcb,0xd5,0x4d,0x4b,0x94,0xa2,0x25,0x47,0xd2,0x44,0x51,0x27,0x1c,0x8b,0x00,},"\x0a\x68\x8e\x79\xbe\x24\xf8\x66\x28\x6d\x46\x46\xb5\xd8\x1c"}, -{{0x0a,0x47,0xd1,0x04,0x52,0xae,0x2f,0xeb,0xec,0x51,0x8a,0x1c,0x7c,0x36,0x28,0x90,0xc3,0xfc,0x1a,0x49,0xd3,0x4b,0x03,0xb6,0x46,0x7d,0x35,0xc9,0x04,0xa8,0x36,0x2d,},{0x34,0xe5,0xa8,0x50,0x8c,0x47,0x43,0x74,0x69,0x62,0xc0,0x66,0xe4,0xba,0xde,0xa2,0x20,0x1b,0x8a,0xb4,0x84,0xde,0x5c,0x4f,0x94,0x47,0x6c,0xcd,0x21,0x43,0x95,0x5b,},{0x2a,0x3d,0x27,0xdc,0x40,0xd0,0xa8,0x12,0x79,0x49,0xa3,0xb7,0xf9,0x08,0xb3,0x68,0x8f,0x63,0xb7,0xf1,0x4f,0x65,0x1a,0xac,0xd7,0x15,0x94,0x0b,0xdb,0xe2,0x7a,0x08,0x09,0xaa,0xc1,0x42,0xf4,0x7a,0xb0,0xe1,0xe4,0x4f,0xa4,0x90,0xba,0x87,0xce,0x53,0x92,0xf3,0x3a,0x89,0x15,0x39,0xca,0xf1,0xef,0x4c,0x36,0x7c,0xae,0x54,0x50,0x0c,},"\xc9\x42\xfa\x7a\xc6\xb2\x3a\xb7\xff\x61\x2f\xdc\x8e\x68\xef\x39"}, -{{0xf8,0x14,0x8f,0x75,0x06,0xb7,0x75,0xef,0x46,0xfd,0xc8,0xe8,0xc7,0x56,0x51,0x68,0x12,0xd4,0x7d,0x6c,0xfb,0xfa,0x31,0x8c,0x27,0xc9,0xa2,0x26,0x41,0xe5,0x6f,0x17,},{0x04,0x45,0xe4,0x56,0xda,0xcc,0x7d,0x5b,0x0b,0xbe,0xd2,0x3c,0x82,0x00,0xcd,0xb7,0x4b,0xdc,0xb0,0x3e,0x4c,0x7b,0x73,0xf0,0xa2,0xb9,0xb4,0x6e,0xac,0x5d,0x43,0x72,},{0x36,0x53,0xcc,0xb2,0x12,0x19,0x20,0x2b,0x84,0x36,0xfb,0x41,0xa3,0x2b,0xa2,0x61,0x8c,0x4a,0x13,0x34,0x31,0xe6,0xe6,0x34,0x63,0xce,0xb3,0xb6,0x10,0x6c,0x4d,0x56,0xe1,0xd2,0xba,0x16,0x5b,0xa7,0x6e,0xaa,0xd3,0xdc,0x39,0xbf,0xfb,0x13,0x0f,0x1d,0xe3,0xd8,0xe6,0x42,0x7d,0xb5,0xb7,0x19,0x38,0xdb,0x4e,0x27,0x2b,0xc3,0xe2,0x0b,},"\x73\x68\x72\x4a\x5b\x0e\xfb\x57\xd2\x8d\x97\x62\x2d\xbd\xe7\x25\xaf"}, -{{0x77,0xf8,0x86,0x91,0xc4,0xef,0xf2,0x3e,0xbb,0x73,0x64,0x94,0x70,0x92,0x95,0x1a,0x5f,0xf3,0xf1,0x07,0x85,0xb4,0x17,0xe9,0x18,0x82,0x3a,0x55,0x2d,0xab,0x7c,0x75,},{0x74,0xd2,0x91,0x27,0xf1,0x99,0xd8,0x6a,0x86,0x76,0xae,0xc3,0x3b,0x4c,0xe3,0xf2,0x25,0xcc,0xb1,0x91,0xf5,0x2c,0x19,0x1c,0xcd,0x1e,0x8c,0xca,0x65,0x21,0x3a,0x6b,},{0xfb,0xe9,0x29,0xd7,0x43,0xa0,0x3c,0x17,0x91,0x05,0x75,0x49,0x2f,0x30,0x92,0xee,0x2a,0x2b,0xf1,0x4a,0x60,0xa3,0xfc,0xac,0xec,0x74,0xa5,0x8c,0x73,0x34,0x51,0x0f,0xc2,0x62,0xdb,0x58,0x27,0x91,0x32,0x2d,0x6c,0x8c,0x41,0xf1,0x70,0x0a,0xdb,0x80,0x02,0x7e,0xca,0xbc,0x14,0x27,0x0b,0x70,0x34,0x44,0xae,0x3e,0xe7,0x62,0x3e,0x0a,},"\xbd\x8e\x05\x03\x3f\x3a\x8b\xcd\xcb\xf4\xbe\xce\xb7\x09\x01\xc8\x2e\x31"}, -{{0xab,0x6f,0x7a,0xee,0x6a,0x08,0x37,0xb3,0x34,0xba,0x5e,0xb1,0xb2,0xad,0x7f,0xce,0xcf,0xab,0x7e,0x32,0x3c,0xab,0x18,0x7f,0xe2,0xe0,0xa9,0x5d,0x80,0xef,0xf1,0x32,},{0x5b,0x96,0xdc,0xa4,0x97,0x87,0x5b,0xf9,0x66,0x4c,0x5e,0x75,0xfa,0xcf,0x3f,0x9b,0xc5,0x4b,0xae,0x91,0x3d,0x66,0xca,0x15,0xee,0x85,0xf1,0x49,0x1c,0xa2,0x4d,0x2c,},{0x73,0xbc,0xa6,0x4e,0x9d,0xd0,0xdb,0x88,0x13,0x8e,0xed,0xfa,0xfc,0xea,0x8f,0x54,0x36,0xcf,0xb7,0x4b,0xfb,0x0e,0x77,0x33,0xcf,0x34,0x9b,0xaa,0x0c,0x49,0x77,0x5c,0x56,0xd5,0x93,0x4e,0x1d,0x38,0xe3,0x6f,0x39,0xb7,0xc5,0xbe,0xb0,0xa8,0x36,0x51,0x0c,0x45,0x12,0x6f,0x8e,0xc4,0xb6,0x81,0x05,0x19,0x90,0x5b,0x0c,0xa0,0x7c,0x09,},"\x81\x71\x45\x6f\x8b\x90\x71\x89\xb1\xd7\x79\xe2\x6b\xc5\xaf\xbb\x08\xc6\x7a"}, -{{0x8d,0x13,0x5d,0xe7,0xc8,0x41,0x1b,0xbd,0xbd,0x1b,0x31,0xe5,0xdc,0x67,0x8f,0x2a,0xc7,0x10,0x9e,0x79,0x2b,0x60,0xf3,0x8c,0xd2,0x49,0x36,0xe8,0xa8,0x98,0xc3,0x2d,},{0x1c,0xa2,0x81,0x93,0x85,0x29,0x89,0x65,0x35,0xa7,0x71,0x4e,0x35,0x84,0x08,0x5b,0x86,0xef,0x9f,0xec,0x72,0x3f,0x42,0x81,0x9f,0xc8,0xdd,0x5d,0x8c,0x00,0x81,0x7f,},{0xa1,0xad,0xc2,0xbc,0x6a,0x2d,0x98,0x06,0x62,0x67,0x7e,0x7f,0xdf,0xf6,0x42,0x4d,0xe7,0xdb,0xa5,0x0f,0x57,0x95,0xca,0x90,0xfd,0xf3,0xe9,0x6e,0x25,0x6f,0x32,0x85,0xca,0xc7,0x1d,0x33,0x60,0x48,0x2e,0x99,0x3d,0x02,0x94,0xba,0x4e,0xc7,0x44,0x0c,0x61,0xaf,0xfd,0xf3,0x5f,0xe8,0x3e,0x6e,0x04,0x26,0x39,0x37,0xdb,0x93,0xf1,0x05,},"\x8b\xa6\xa4\xc9\xa1\x5a\x24\x4a\x9c\x26\xbb\x2a\x59\xb1\x02\x6f\x21\x34\x8b\x49"}, -{{0x0e,0x76,0x5d,0x72,0x0e,0x70,0x5f,0x93,0x66,0xc1,0xab,0x8c,0x3f,0xa8,0x4c,0x9a,0x44,0x37,0x0c,0x06,0x96,0x9f,0x80,0x32,0x96,0x88,0x4b,0x28,0x46,0xa6,0x52,0xa4,},{0x7f,0xae,0x45,0xdd,0x0a,0x05,0x97,0x10,0x26,0xd4,0x10,0xbc,0x49,0x7a,0xf5,0xbe,0x7d,0x08,0x27,0xa8,0x2a,0x14,0x5c,0x20,0x3f,0x62,0x5d,0xfc,0xb8,0xb0,0x3b,0xa8,},{0xbb,0x61,0xcf,0x84,0xde,0x61,0x86,0x22,0x07,0xc6,0xa4,0x55,0x25,0x8b,0xc4,0xdb,0x4e,0x15,0xee,0xa0,0x31,0x7f,0xf8,0x87,0x18,0xb8,0x82,0xa0,0x6b,0x5c,0xf6,0xec,0x6f,0xd2,0x0c,0x5a,0x26,0x9e,0x5d,0x5c,0x80,0x5b,0xaf,0xbc,0xc5,0x79,0xe2,0x59,0x0a,0xf4,0x14,0xc7,0xc2,0x27,0x27,0x3c,0x10,0x2a,0x10,0x07,0x0c,0xdf,0xe8,0x0f,},"\x1d\x56\x6a\x62\x32\xbb\xaa\xb3\xe6\xd8\x80\x4b\xb5\x18\xa4\x98\xed\x0f\x90\x49\x86"}, -{{0xdb,0x36,0xe3,0x26,0xd6,0x76,0xc2,0xd1,0x9c,0xc8,0xfe,0x0c,0x14,0xb7,0x09,0x20,0x2e,0xcf,0xc7,0x61,0xd2,0x70,0x89,0xeb,0x6e,0xa4,0xb1,0xbb,0x02,0x1e,0xcf,0xa7,},{0x48,0x35,0x9b,0x85,0x0d,0x23,0xf0,0x71,0x5d,0x94,0xbb,0x8b,0xb7,0x5e,0x7e,0x14,0x32,0x2e,0xaf,0x14,0xf0,0x6f,0x28,0xa8,0x05,0x40,0x3f,0xbd,0xa0,0x02,0xfc,0x85,},{0xb6,0xdc,0xd0,0x99,0x89,0xdf,0xba,0xc5,0x43,0x22,0xa3,0xce,0x87,0x87,0x6e,0x1d,0x62,0x13,0x4d,0xa9,0x98,0xc7,0x9d,0x24,0xb5,0x0b,0xd7,0xa6,0xa7,0x97,0xd8,0x6a,0x0e,0x14,0xdc,0x9d,0x74,0x91,0xd6,0xc1,0x4a,0x67,0x3c,0x65,0x2c,0xfb,0xec,0x9f,0x96,0x2a,0x38,0xc9,0x45,0xda,0x3b,0x2f,0x08,0x79,0xd0,0xb6,0x8a,0x92,0x13,0x00,},"\x1b\x0a\xfb\x0a\xc4\xba\x9a\xb7\xb7\x17\x2c\xdd\xc9\xeb\x42\xbb\xa1\xa6\x4b\xce\x47\xd4"}, -{{0xc8,0x99,0x55,0xe0,0xf7,0x74,0x1d,0x90,0x5d,0xf0,0x73,0x0b,0x3d,0xc2,0xb0,0xce,0x1a,0x13,0x13,0x4e,0x44,0xfe,0xf3,0xd4,0x0d,0x60,0xc0,0x20,0xef,0x19,0xdf,0x77,},{0xfd,0xb3,0x06,0x73,0x40,0x2f,0xaf,0x1c,0x80,0x33,0x71,0x4f,0x35,0x17,0xe4,0x7c,0xc0,0xf9,0x1f,0xe7,0x0c,0xf3,0x83,0x6d,0x6c,0x23,0x63,0x6e,0x3f,0xd2,0x28,0x7c,},{0x7e,0xf6,0x6e,0x5e,0x86,0xf2,0x36,0x08,0x48,0xe0,0x01,0x4e,0x94,0x88,0x0a,0xe2,0x92,0x0a,0xd8,0xa3,0x18,0x5a,0x46,0xb3,0x5d,0x1e,0x07,0xde,0xa8,0xfa,0x8a,0xe4,0xf6,0xb8,0x43,0xba,0x17,0x4d,0x99,0xfa,0x79,0x86,0x65,0x4a,0x08,0x91,0xc1,0x2a,0x79,0x44,0x55,0x66,0x93,0x75,0xbf,0x92,0xaf,0x4c,0xc2,0x77,0x0b,0x57,0x9e,0x0c,},"\x50\x7c\x94\xc8\x82\x0d\x2a\x57\x93\xcb\xf3\x44\x2b\x3d\x71\x93\x6f\x35\xfe\x3a\xfe\xf3\x16"}, -{{0x4e,0x62,0x62,0x7f,0xc2,0x21,0x14,0x24,0x78,0xae,0xe7,0xf0,0x07,0x81,0xf8,0x17,0xf6,0x62,0xe3,0xb7,0x5d,0xb2,0x9b,0xb1,0x4a,0xb4,0x7c,0xf8,0xe8,0x41,0x04,0xd6,},{0xb1,0xd3,0x98,0x01,0x89,0x20,0x27,0xd5,0x8a,0x8c,0x64,0x33,0x51,0x63,0x19,0x58,0x93,0xbf,0xc1,0xb6,0x1d,0xbe,0xca,0x32,0x60,0x49,0x7e,0x1f,0x30,0x37,0x11,0x07,},{0x83,0x6a,0xfa,0x76,0x4d,0x9c,0x48,0xaa,0x47,0x70,0xa4,0x38,0x8b,0x65,0x4e,0x97,0xb3,0xc1,0x6f,0x08,0x29,0x67,0xfe,0xbc,0xa2,0x7f,0x2f,0xc4,0x7d,0xdf,0xd9,0x24,0x4b,0x03,0xcf,0xc7,0x29,0x69,0x8a,0xcf,0x51,0x09,0x70,0x43,0x46,0xb6,0x0b,0x23,0x0f,0x25,0x54,0x30,0x08,0x9d,0xdc,0x56,0x91,0x23,0x99,0xd1,0x12,0x2d,0xe7,0x0a,},"\xd3\xd6\x15\xa8\x47\x2d\x99\x62\xbb\x70\xc5\xb5\x46\x6a\x3d\x98\x3a\x48\x11\x04\x6e\x2a\x0e\xf5"}, -{{0x6b,0x83,0xd7,0xda,0x89,0x08,0xc3,0xe7,0x20,0x5b,0x39,0x86,0x4b,0x56,0xe5,0xf3,0xe1,0x71,0x96,0xa3,0xfc,0x9c,0x2f,0x58,0x05,0xaa,0xd0,0xf5,0x55,0x4c,0x14,0x2d,},{0xd0,0xc8,0x46,0xf9,0x7f,0xe2,0x85,0x85,0xc0,0xee,0x15,0x90,0x15,0xd6,0x4c,0x56,0x31,0x1c,0x88,0x6e,0xdd,0xcc,0x18,0x5d,0x29,0x6d,0xbb,0x16,0x5d,0x26,0x25,0xd6,},{0x16,0xe4,0x62,0xa2,0x9a,0x6d,0xd4,0x98,0x68,0x5a,0x37,0x18,0xb3,0xee,0xd0,0x0c,0xc1,0x59,0x86,0x01,0xee,0x47,0x82,0x04,0x86,0x03,0x2d,0x6b,0x9a,0xcc,0x9b,0xf8,0x9f,0x57,0x68,0x4e,0x08,0xd8,0xc0,0xf0,0x55,0x89,0xcd,0xa2,0x88,0x2a,0x05,0xdc,0x4c,0x63,0xf9,0xd0,0x43,0x1d,0x65,0x52,0x71,0x08,0x12,0x43,0x30,0x03,0xbc,0x08,},"\x6a\xda\x80\xb6\xfa\x84\xf7\x03\x49\x20\x78\x9e\x85\x36\xb8\x2d\x5e\x46\x78\x05\x9a\xed\x27\xf7\x1c"}, -{{0x19,0xa9,0x1f,0xe2,0x3a,0x4e,0x9e,0x33,0xec,0xc4,0x74,0x87,0x8f,0x57,0xc6,0x4c,0xf1,0x54,0xb3,0x94,0x20,0x34,0x87,0xa7,0x03,0x5e,0x1a,0xd9,0xcd,0x69,0x7b,0x0d,},{0x2b,0xf3,0x2b,0xa1,0x42,0xba,0x46,0x22,0xd8,0xf3,0xe2,0x9e,0xcd,0x85,0xee,0xa0,0x7b,0x9c,0x47,0xbe,0x9d,0x64,0x41,0x2c,0x9b,0x51,0x0b,0x27,0xdd,0x21,0x8b,0x23,},{0x88,0x1f,0x5b,0x8c,0x5a,0x03,0x0d,0xf0,0xf7,0x5b,0x66,0x34,0xb0,0x70,0xdd,0x27,0xbd,0x1e,0xe3,0xc0,0x87,0x38,0xae,0x34,0x93,0x38,0xb3,0xee,0x64,0x69,0xbb,0xf9,0x76,0x0b,0x13,0x57,0x8a,0x23,0x7d,0x51,0x82,0x53,0x5e,0xde,0x12,0x12,0x83,0x02,0x7a,0x90,0xb5,0xf8,0x65,0xd6,0x3a,0x65,0x37,0xdc,0xa0,0x7b,0x44,0x04,0x9a,0x0f,},"\x82\xcb\x53\xc4\xd5\xa0\x13\xba\xe5\x07\x07\x59\xec\x06\xc3\xc6\x95\x5a\xb7\xa4\x05\x09\x58\xec\x32\x8c"}, -{{0x1d,0x5b,0x8c,0xb6,0x21,0x5c,0x18,0x14,0x16,0x66,0xba,0xee,0xfc,0xf5,0xd6,0x9d,0xad,0x5b,0xea,0x9a,0x34,0x93,0xdd,0xda,0xa3,0x57,0xa4,0x39,0x7a,0x13,0xd4,0xde,},{0x94,0xd2,0x3d,0x97,0x7c,0x33,0xe4,0x9e,0x5e,0x49,0x92,0xc6,0x8f,0x25,0xec,0x99,0xa2,0x7c,0x41,0xce,0x6b,0x91,0xf2,0xbf,0xa0,0xcd,0x82,0x92,0xfe,0x96,0x28,0x35,},{0x3a,0xcd,0x39,0xbe,0xc8,0xc3,0xcd,0x2b,0x44,0x29,0x97,0x22,0xb5,0x85,0x0a,0x04,0x00,0xc1,0x44,0x35,0x90,0xfd,0x48,0x61,0xd5,0x9a,0xae,0x74,0x96,0xac,0xb3,0xdf,0x73,0xfc,0x3f,0xdf,0x79,0x69,0xae,0x5f,0x50,0xba,0x47,0xdd,0xdc,0x43,0x52,0x46,0xe5,0xfd,0x37,0x6f,0x6b,0x89,0x1c,0xd4,0xc2,0xca,0xf5,0xd6,0x14,0xb6,0x17,0x0c,},"\xa9\xa8\xcb\xb0\xad\x58\x51\x24\xe5\x22\xab\xbf\xb4\x05\x33\xbd\xd6\xf4\x93\x47\xb5\x5b\x18\xe8\x55\x8c\xb0"}, -{{0x6a,0x91,0xb3,0x22,0x7c,0x47,0x22,0x99,0x08,0x9b,0xdc,0xe9,0x35,0x6e,0x72,0x6a,0x40,0xef,0xd8,0x40,0xf1,0x10,0x02,0x70,0x8b,0x7e,0xe5,0x5b,0x64,0x10,0x5a,0xc2,},{0x9d,0x08,0x4a,0xa8,0xb9,0x7a,0x6b,0x9b,0xaf,0xa4,0x96,0xdb,0xc6,0xf7,0x6f,0x33,0x06,0xa1,0x16,0xc9,0xd9,0x17,0xe6,0x81,0x52,0x0a,0x0f,0x91,0x43,0x69,0x42,0x7e,},{0xf5,0x87,0x54,0x23,0x78,0x1b,0x66,0x21,0x6c,0xb5,0xe8,0x99,0x8d,0xe5,0xd9,0xff,0xc2,0x9d,0x1d,0x67,0x10,0x70,0x54,0xac,0xe3,0x37,0x45,0x03,0xa9,0xc3,0xef,0x81,0x15,0x77,0xf2,0x69,0xde,0x81,0x29,0x67,0x44,0xbd,0x70,0x6f,0x1a,0xc4,0x78,0xca,0xf0,0x9b,0x54,0xcd,0xf8,0x71,0xb3,0xf8,0x02,0xbd,0x57,0xf9,0xa6,0xcb,0x91,0x01,},"\x5c\xb6\xf9\xaa\x59\xb8\x0e\xca\x14\xf6\xa6\x8f\xb4\x0c\xf0\x7b\x79\x4e\x75\x17\x1f\xba\x96\x26\x2c\x1c\x6a\xdc"}, -{{0x93,0xea,0xa8,0x54,0xd7,0x91,0xf0,0x53,0x72,0xce,0x72,0xb9,0x4f,0xc6,0x50,0x3b,0x2f,0xf8,0xae,0x68,0x19,0xe6,0xa2,0x1a,0xfe,0x82,0x5e,0x27,0xad,0xa9,0xe4,0xfb,},{0x16,0xce,0xe8,0xa3,0xf2,0x63,0x18,0x34,0xc8,0x8b,0x67,0x08,0x97,0xff,0x0b,0x08,0xce,0x90,0xcc,0x14,0x7b,0x45,0x93,0xb3,0xf1,0xf4,0x03,0x72,0x7f,0x7e,0x7a,0xd5,},{0xd8,0x34,0x19,0x7c,0x1a,0x30,0x80,0x61,0x4e,0x0a,0x5f,0xa0,0xaa,0xaa,0x80,0x88,0x24,0xf2,0x1c,0x38,0xd6,0x92,0xe6,0xff,0xbd,0x20,0x0f,0x7d,0xfb,0x3c,0x8f,0x44,0x40,0x2a,0x73,0x82,0x18,0x0b,0x98,0xad,0x0a,0xfc,0x8e,0xec,0x1a,0x02,0xac,0xec,0xf3,0xcb,0x7f,0xde,0x62,0x7b,0x9f,0x18,0x11,0x1f,0x26,0x0a,0xb1,0xdb,0x9a,0x07,},"\x32\xfe\x27\x99\x41\x24\x20\x21\x53\xb5\xc7\x0d\x38\x13\xfd\xee\x9c\x2a\xa6\xe7\xdc\x74\x3d\x4d\x53\x5f\x18\x40\xa5"}, -{{0x94,0x1c,0xac,0x69,0xfb,0x7b,0x18,0x15,0xc5,0x7b,0xb9,0x87,0xc4,0xd6,0xc2,0xad,0x2c,0x35,0xd5,0xf9,0xa3,0x18,0x2a,0x79,0xd4,0xba,0x13,0xea,0xb2,0x53,0xa8,0xad,},{0x23,0xbe,0x32,0x3c,0x56,0x2d,0xfd,0x71,0xce,0x65,0xf5,0xbb,0xa5,0x6a,0x74,0xa3,0xa6,0xdf,0xc3,0x6b,0x57,0x3d,0x2f,0x94,0xf6,0x35,0xc7,0xf9,0xb4,0xfd,0x5a,0x5b,},{0x0f,0x8f,0xad,0x1e,0x6b,0xde,0x77,0x1b,0x4f,0x54,0x20,0xea,0xc7,0x5c,0x37,0x8b,0xae,0x6d,0xb5,0xac,0x66,0x50,0xcd,0x2b,0xc2,0x10,0xc1,0x82,0x3b,0x43,0x2b,0x48,0xe0,0x16,0xb1,0x05,0x95,0x45,0x8f,0xfa,0xb9,0x2f,0x7a,0x89,0x89,0xb2,0x93,0xce,0xb8,0xdf,0xed,0x6c,0x24,0x3a,0x20,0x38,0xfc,0x06,0x65,0x2a,0xaa,0xf1,0x6f,0x02,},"\xbb\x31\x72\x79\x57\x10\xfe\x00\x05\x4d\x3b\x5d\xfe\xf8\xa1\x16\x23\x58\x2d\xa6\x8b\xf8\xe4\x6d\x72\xd2\x7c\xec\xe2\xaa"}, -{{0x1a,0xcd,0xbb,0x79,0x3b,0x03,0x84,0x93,0x46,0x27,0x47,0x0d,0x79,0x5c,0x3d,0x1d,0xd4,0xd7,0x9c,0xea,0x59,0xef,0x98,0x3f,0x29,0x5b,0x9b,0x59,0x17,0x9c,0xbb,0x28,},{0x3f,0x60,0xc7,0x54,0x1a,0xfa,0x76,0xc0,0x19,0xcf,0x5a,0xa8,0x2d,0xcd,0xb0,0x88,0xed,0x9e,0x4e,0xd9,0x78,0x05,0x14,0xae,0xfb,0x37,0x9d,0xab,0xc8,0x44,0xf3,0x1a,},{0xbe,0x71,0xef,0x48,0x06,0xcb,0x04,0x1d,0x88,0x5e,0xff,0xd9,0xe6,0xb0,0xfb,0xb7,0x3d,0x65,0xd7,0xcd,0xec,0x47,0xa8,0x9c,0x8a,0x99,0x48,0x92,0xf4,0xe5,0x5a,0x56,0x8c,0x4c,0xc7,0x8d,0x61,0xf9,0x01,0xe8,0x0d,0xbb,0x62,0x8b,0x86,0xa2,0x3c,0xcd,0x59,0x4e,0x71,0x2b,0x57,0xfa,0x94,0xc2,0xd6,0x7e,0xc2,0x66,0x34,0x87,0x85,0x07,},"\x7c\xf3\x4f\x75\xc3\xda\xc9\xa8\x04\xd0\xfc\xd0\x9e\xba\x9b\x29\xc9\x48\x4e\x8a\x01\x8f\xa9\xe0\x73\x04\x2d\xf8\x8e\x3c\x56"}, -{{0x8e,0xd7,0xa7,0x97,0xb9,0xce,0xa8,0xa8,0x37,0x0d,0x41,0x91,0x36,0xbc,0xdf,0x68,0x3b,0x75,0x9d,0x2e,0x3c,0x69,0x47,0xf1,0x7e,0x13,0xe2,0x48,0x5a,0xa9,0xd4,0x20,},{0xb4,0x9f,0x3a,0x78,0xb1,0xc6,0xa7,0xfc,0xa8,0xf3,0x46,0x6f,0x33,0xbc,0x0e,0x92,0x9f,0x01,0xfb,0xa0,0x43,0x06,0xc2,0xa7,0x46,0x5f,0x46,0xc3,0x75,0x93,0x16,0xd9,},{0x04,0x26,0x6c,0x03,0x3b,0x91,0xc1,0x32,0x2c,0xeb,0x34,0x46,0xc9,0x01,0xff,0xcf,0x3c,0xc4,0x0c,0x40,0x34,0xe8,0x87,0xc9,0x59,0x7c,0xa1,0x89,0x3b,0xa7,0x33,0x0b,0xec,0xbb,0xd8,0xb4,0x81,0x42,0xef,0x35,0xc0,0x12,0xc6,0xba,0x51,0xa6,0x6d,0xf9,0x30,0x8c,0xb6,0x26,0x8a,0xd6,0xb1,0xe4,0xb0,0x3e,0x70,0x10,0x24,0x95,0x79,0x0b,},"\xa7\x50\xc2\x32\x93\x3d\xc1\x4b\x11\x84\xd8\x6d\x8b\x4c\xe7\x2e\x16\xd6\x97\x44\xba\x69\x81\x8b\x6a\xc3\x3b\x1d\x82\x3b\xb2\xc3"}, -{{0xf2,0xab,0x39,0x6f,0xe8,0x90,0x6e,0x3e,0x56,0x33,0xe9,0x9c,0xab,0xcd,0x5b,0x09,0xdf,0x08,0x59,0xb5,0x16,0x23,0x0b,0x1e,0x04,0x50,0xb5,0x80,0xb6,0x5f,0x61,0x6c,},{0x8e,0xa0,0x74,0x24,0x51,0x59,0xa1,0x16,0xaa,0x71,0x22,0xa2,0x5e,0xc1,0x6b,0x89,0x1d,0x62,0x5a,0x68,0xf3,0x36,0x60,0x42,0x39,0x08,0xf6,0xbd,0xc4,0x4f,0x8c,0x1b,},{0xa0,0x6a,0x23,0xd9,0x82,0xd8,0x1a,0xb8,0x83,0xaa,0xe2,0x30,0xad,0xbc,0x36,0x8a,0x6a,0x99,0x77,0xf0,0x03,0xce,0xbb,0x00,0xd4,0xc2,0xe4,0x01,0x84,0x90,0x19,0x1a,0x84,0xd3,0xa2,0x82,0xfd,0xbf,0xb2,0xfc,0x88,0x04,0x6e,0x62,0xde,0x43,0xe1,0x5f,0xb5,0x75,0x33,0x6b,0x3c,0x8b,0x77,0xd1,0x9c,0xe6,0xa0,0x09,0xce,0x51,0xf5,0x0c,},"\x5a\x44\xe3\x4b\x74\x6c\x5f\xd1\x89\x8d\x55\x2a\xb3\x54\xd2\x8f\xb4\x71\x38\x56\xd7\x69\x7d\xd6\x3e\xb9\xbd\x6b\x99\xc2\x80\xe1\x87"}, -{{0x55,0x0a,0x41,0xc0,0x13,0xf7,0x9b,0xab,0x8f,0x06,0xe4,0x3a,0xd1,0x83,0x6d,0x51,0x31,0x27,0x36,0xa9,0x71,0x38,0x06,0xfa,0xfe,0x66,0x45,0x21,0x9e,0xaa,0x1f,0x9d,},{0xaf,0x6b,0x71,0x45,0x47,0x4d,0xc9,0x95,0x4b,0x9a,0xf9,0x3a,0x9c,0xdb,0x34,0x44,0x9d,0x5b,0x7c,0x65,0x1c,0x82,0x4d,0x24,0xe2,0x30,0xb9,0x00,0x33,0xce,0x59,0xc0,},{0x16,0xdc,0x1e,0x2b,0x9f,0xa9,0x09,0xee,0xfd,0xc2,0x77,0xba,0x16,0xeb,0xe2,0x07,0xb8,0xda,0x5e,0x91,0x14,0x3c,0xde,0x78,0xc5,0x04,0x7a,0x89,0xf6,0x81,0xc3,0x3c,0x4e,0x4e,0x34,0x28,0xd5,0xc9,0x28,0x09,0x59,0x03,0xa8,0x11,0xec,0x00,0x2d,0x52,0xa3,0x9e,0xd7,0xf8,0xb3,0xfe,0x19,0x27,0x20,0x0c,0x6d,0xd0,0xb9,0xab,0x3e,0x04,},"\x8b\xc4\x18\x5e\x50\xe5\x7d\x5f\x87\xf4\x75\x15\xfe\x2b\x18\x37\xd5\x85\xf0\xaa\xe9\xe1\xca\x38\x3b\x3e\xc9\x08\x88\x4b\xb9\x00\xff\x27"}, -{{0x19,0xac,0x3e,0x27,0x24,0x38,0xc7,0x2d,0xdf,0x7b,0x88,0x19,0x64,0x86,0x7c,0xb3,0xb3,0x1f,0xf4,0xc7,0x93,0xbb,0x7e,0xa1,0x54,0x61,0x3c,0x1d,0xb0,0x68,0xcb,0x7e,},{0xf8,0x5b,0x80,0xe0,0x50,0xa1,0xb9,0x62,0x0d,0xb1,0x38,0xbf,0xc9,0xe1,0x00,0x32,0x7e,0x25,0xc2,0x57,0xc5,0x92,0x17,0xb6,0x01,0xf1,0xf6,0xac,0x9a,0x41,0x3d,0x3f,},{0xea,0x85,0x5d,0x78,0x1c,0xbe,0xa4,0x68,0x2e,0x35,0x01,0x73,0xcb,0x89,0xe8,0x61,0x9c,0xcf,0xdd,0xb9,0x7c,0xdc,0xe1,0x6f,0x9a,0x2f,0x6f,0x68,0x92,0xf4,0x6d,0xbe,0x68,0xe0,0x4b,0x12,0xb8,0xd8,0x86,0x89,0xa7,0xa3,0x16,0x70,0xcd,0xff,0x40,0x9a,0xf9,0x8a,0x93,0xb4,0x9a,0x34,0x53,0x7b,0x6a,0xa0,0x09,0xd2,0xeb,0x8b,0x47,0x01,},"\x95\x87\x2d\x5f\x78\x9f\x95\x48\x4e\x30\xcb\xb0\xe1\x14\x02\x89\x53\xb1\x6f\x5c\x6a\x8d\x9f\x65\xc0\x03\xa8\x35\x43\xbe\xaa\x46\xb3\x86\x45"}, -{{0xca,0x26,0x7d,0xe9,0x6c,0x93,0xc2,0x38,0xfa,0xfb,0x12,0x79,0x81,0x20,0x59,0xab,0x93,0xac,0x03,0x05,0x96,0x57,0xfd,0x99,0x4f,0x8f,0xa5,0xa0,0x92,0x39,0xc8,0x21,},{0x01,0x73,0x70,0xc8,0x79,0x09,0x0a,0x81,0xc7,0xf2,0x72,0xc2,0xfc,0x80,0xe3,0xaa,0xc2,0xbc,0x60,0x3f,0xcb,0x37,0x9a,0xfc,0x98,0x69,0x11,0x60,0xab,0x74,0x5b,0x26,},{0xac,0x95,0x7f,0x82,0x33,0x5a,0xa7,0x14,0x1e,0x96,0xb5,0x9d,0x63,0xe3,0xcc,0xee,0x95,0xc3,0xa2,0xc4,0x7d,0x02,0x65,0x40,0xc2,0xaf,0x42,0xdc,0x95,0x33,0xd5,0xfd,0x81,0x82,0x7d,0x16,0x79,0xad,0x18,0x7a,0xea,0xf3,0x78,0x34,0x91,0x5e,0x75,0xb1,0x47,0xa9,0x28,0x68,0x06,0xc8,0x01,0x75,0x16,0xba,0x43,0xdd,0x05,0x1a,0x5e,0x0c,},"\xe0\x5f\x71\xe4\xe4\x9a\x72\xec\x55\x0c\x44\xa3\xb8\x5a\xca\x8f\x20\xff\x26\xc3\xee\x94\xa8\x0f\x1b\x43\x1c\x7d\x15\x4e\xc9\x60\x3e\xe0\x25\x31"}, -{{0x3d,0xff,0x5e,0x89,0x94,0x75,0xe7,0xe9,0x1d,0xd2,0x61,0x32,0x2f,0xab,0x09,0x98,0x0c,0x52,0x97,0x0d,0xe1,0xda,0x6e,0x2e,0x20,0x16,0x60,0xcc,0x4f,0xce,0x70,0x32,},{0xf3,0x01,0x62,0xba,0xc9,0x84,0x47,0xc4,0x04,0x2f,0xac,0x05,0xda,0x44,0x80,0x34,0x62,0x9b,0xe2,0xc6,0xa5,0x8d,0x30,0xdf,0xd5,0x78,0xba,0x9f,0xb5,0xe3,0x93,0x0b,},{0x5e,0xfe,0x7a,0x92,0xff,0x96,0x23,0x08,0x9b,0x3e,0x3b,0x78,0xf3,0x52,0x11,0x53,0x66,0xe2,0x6b,0xa3,0xfb,0x1a,0x41,0x62,0x09,0xbc,0x02,0x9e,0x9c,0xad,0xcc,0xd9,0xf4,0xaf,0xfa,0x33,0x35,0x55,0xa8,0xf3,0xa3,0x5a,0x9d,0x0f,0x7c,0x34,0xb2,0x92,0xca,0xe7,0x7e,0xc9,0x6f,0xa3,0xad,0xfc,0xaa,0xde,0xe2,0xd9,0xce,0xd8,0xf8,0x05,},"\x93\x8f\x0e\x77\x62\x1b\xf3\xea\x52\xc7\xc4\x91\x1c\x51\x57\xc2\xd8\xa2\xa8\x58\x09\x3e\xf1\x6a\xa9\xb1\x07\xe6\x9d\x98\x03\x7b\xa1\x39\xa3\xc3\x82"}, -{{0x9a,0x6b,0x84,0x78,0x64,0xe7,0x0c,0xfe,0x8b,0xa6,0xab,0x22,0xfa,0x0c,0xa3,0x08,0xc0,0xcc,0x8b,0xec,0x71,0x41,0xfb,0xca,0xa3,0xb8,0x1f,0x5d,0x1e,0x1c,0xfc,0xfc,},{0x34,0xad,0x0f,0xbd,0xb2,0x56,0x65,0x07,0xa8,0x1c,0x2b,0x1f,0x8a,0xa8,0xf5,0x3d,0xcc,0xaa,0x64,0xcc,0x87,0xad,0xa9,0x1b,0x90,0x3e,0x90,0x0d,0x07,0xee,0xe9,0x30,},{0x2a,0xb2,0x55,0x16,0x9c,0x48,0x9c,0x54,0xc7,0x32,0x23,0x2e,0x37,0xc8,0x73,0x49,0xd4,0x86,0xb1,0xeb,0xa2,0x05,0x09,0xdb,0xab,0xe7,0xfe,0xd3,0x29,0xef,0x08,0xfd,0x75,0xba,0x1c,0xd1,0x45,0xe6,0x7b,0x2e,0xa2,0x6c,0xb5,0xcc,0x51,0xca,0xb3,0x43,0xee,0xb0,0x85,0xfe,0x1f,0xd7,0xb0,0xec,0x4c,0x6a,0xfc,0xd9,0xb9,0x79,0xf9,0x05,},"\x83\x83\x67\x47\x11\x83\xc7\x1f\x7e\x71\x77\x24\xf8\x9d\x40\x1c\x3a\xd9\x86\x3f\xd9\xcc\x7a\xa3\xcf\x33\xd3\xc5\x29\x86\x0c\xb5\x81\xf3\x09\x3d\x87\xda"}, -{{0x57,0x5b,0xe0,0x7a,0xfc,0xa5,0xd0,0x63,0xc2,0x38,0xcd,0x9b,0x80,0x28,0x77,0x2c,0xc4,0x9c,0xda,0x34,0x47,0x14,0x32,0xa2,0xe1,0x66,0xe0,0x96,0xe2,0x21,0x9e,0xfc,},{0x94,0xe5,0xeb,0x4d,0x50,0x24,0xf4,0x9d,0x7e,0xbf,0x79,0x81,0x7c,0x8d,0xe1,0x14,0x97,0xdc,0x2b,0x55,0x62,0x2a,0x51,0xae,0x12,0x3f,0xfc,0x74,0x9d,0xbb,0x16,0xe0,},{0x58,0x27,0x1d,0x44,0x23,0x6f,0x3b,0x98,0xc5,0x8f,0xd7,0xae,0x0d,0x2f,0x49,0xef,0x2b,0x6e,0x3a,0xff,0xdb,0x22,0x5a,0xa3,0xba,0x55,0x5f,0x0e,0x11,0xcc,0x53,0xc2,0x3a,0xd1,0x9b,0xaf,0x24,0x34,0x65,0x90,0xd0,0x5d,0x7d,0x53,0x90,0x58,0x20,0x82,0xcf,0x94,0xd3,0x9c,0xad,0x65,0x30,0xab,0x93,0xd1,0x3e,0xfb,0x39,0x27,0x95,0x06,},"\x33\xe5\x91\x8b\x66\xd3\x3d\x55\xfe\x71\x7c\xa3\x43\x83\xea\xe7\x8f\x0a\xf8\x28\x89\xca\xf6\x69\x6e\x1a\xc9\xd9\x5d\x1f\xfb\x32\xcb\xa7\x55\xf9\xe3\x50\x3e"}, -{{0x15,0xff,0xb4,0x55,0x14,0xd4,0x34,0x44,0xd6,0x1f,0xcb,0x10,0x5e,0x30,0xe1,0x35,0xfd,0x26,0x85,0x23,0xdd,0xa2,0x0b,0x82,0x75,0x8b,0x17,0x94,0x23,0x11,0x04,0x41,},{0x17,0x72,0xc5,0xab,0xc2,0xd2,0x3f,0xd2,0xf9,0xd1,0xc3,0x25,0x7b,0xe7,0xbc,0x3c,0x1c,0xd7,0x9c,0xee,0x40,0x84,0x4b,0x74,0x9b,0x3a,0x77,0x43,0xd2,0xf9,0x64,0xb8,},{0x68,0x28,0xcd,0x76,0x24,0xe7,0x93,0xb8,0xa4,0xce,0xb9,0x6d,0x3c,0x2a,0x97,0x5b,0xf7,0x73,0xe5,0xff,0x66,0x45,0xf3,0x53,0x61,0x40,0x58,0x62,0x1e,0x58,0x83,0x52,0x89,0xe7,0xf3,0x1f,0x42,0xdf,0xe6,0xaf,0x6d,0x73,0x6f,0x26,0x44,0x51,0x1e,0x32,0x0c,0x0f,0xa6,0x98,0x58,0x2a,0x79,0x77,0x8d,0x18,0x73,0x0e,0xd3,0xe8,0xcb,0x08,},"\xda\x9c\x55\x59\xd0\xea\x51\xd2\x55\xb6\xbd\x9d\x76\x38\xb8\x76\x47\x2f\x94\x2b\x33\x0f\xc0\xe2\xb3\x0a\xea\x68\xd7\x73\x68\xfc\xe4\x94\x82\x72\x99\x1d\x25\x7e"}, -{{0xfe,0x05,0x68,0x64,0x29,0x43,0xb2,0xe1,0xaf,0xbf,0xd1,0xf1,0x0f,0xe8,0xdf,0x87,0xa4,0x23,0x6b,0xea,0x40,0xdc,0xe7,0x42,0x07,0x2c,0xb2,0x18,0x86,0xee,0xc1,0xfa,},{0x29,0x9e,0xbd,0x1f,0x13,0x17,0x7d,0xbd,0xb6,0x6a,0x91,0x2b,0xbf,0x71,0x20,0x38,0xfd,0xf7,0x3b,0x06,0xc3,0xac,0x02,0x0c,0x7b,0x19,0x12,0x67,0x55,0xd4,0x7f,0x61,},{0xd5,0x9e,0x6d,0xfc,0xc6,0xd7,0xe3,0xe2,0xc5,0x8d,0xec,0x81,0xe9,0x85,0xd2,0x45,0xe6,0x81,0xac,0xf6,0x59,0x4a,0x23,0xc5,0x92,0x14,0xf7,0xbe,0xd8,0x01,0x5d,0x81,0x3c,0x76,0x82,0xb6,0x0b,0x35,0x83,0x44,0x03,0x11,0xe7,0x2a,0x86,0x65,0xba,0x2c,0x96,0xde,0xc2,0x3c,0xe8,0x26,0xe1,0x60,0x12,0x7e,0x18,0x13,0x2b,0x03,0x04,0x04,},"\xc5\x9d\x08\x62\xec\x1c\x97\x46\xab\xcc\x3c\xf8\x3c\x9e\xeb\xa2\xc7\x08\x2a\x03\x6a\x8c\xb5\x7c\xe4\x87\xe7\x63\x49\x27\x96\xd4\x7e\x6e\x06\x3a\x0c\x1f\xec\xcc\x2d"}, -{{0x5e,0xcb,0x16,0xc2,0xdf,0x27,0xc8,0xcf,0x58,0xe4,0x36,0xa9,0xd3,0xaf,0xfb,0xd5,0x8e,0x95,0x38,0xa9,0x26,0x59,0xa0,0xf9,0x7c,0x4c,0x4f,0x99,0x46,0x35,0xa8,0xca,},{0xda,0x76,0x8b,0x20,0xc4,0x37,0xdd,0x3a,0xa5,0xf8,0x4b,0xb6,0xa0,0x77,0xff,0xa3,0x4a,0xb6,0x85,0x01,0xc5,0x35,0x2b,0x5c,0xc3,0xfd,0xce,0x7f,0xe6,0xc2,0x39,0x8d,},{0x1c,0x72,0x3a,0x20,0xc6,0x77,0x24,0x26,0xa6,0x70,0xe4,0xd5,0xc4,0xa9,0x7c,0x6e,0xbe,0x91,0x47,0xf7,0x1b,0xb0,0xa4,0x15,0x63,0x1e,0x44,0x40,0x6e,0x29,0x03,0x22,0xe4,0xca,0x97,0x7d,0x34,0x8f,0xe7,0x85,0x6a,0x8e,0xdc,0x23,0x5d,0x0f,0xe9,0x5f,0x7e,0xd9,0x1a,0xef,0xdd,0xf2,0x8a,0x77,0xe2,0xc7,0xdb,0xfd,0x8f,0x55,0x2f,0x0a,},"\x56\xf1\x32\x9d\x9a\x6b\xe2\x5a\x61\x59\xc7\x2f\x12\x68\x8d\xc8\x31\x4e\x85\xdd\x9e\x7e\x4d\xc0\x5b\xbe\xcb\x77\x29\xe0\x23\xc8\x6f\x8e\x09\x37\x35\x3f\x27\xc7\xed\xe9"}, -{{0xd5,0x99,0xd6,0x37,0xb3,0xc3,0x0a,0x82,0xa9,0x98,0x4e,0x2f,0x75,0x84,0x97,0xd1,0x44,0xde,0x6f,0x06,0xb9,0xfb,0xa0,0x4d,0xd4,0x0f,0xd9,0x49,0x03,0x9d,0x7c,0x84,},{0x67,0x91,0xd8,0xce,0x50,0xa4,0x46,0x89,0xfc,0x17,0x87,0x27,0xc5,0xc3,0xa1,0xc9,0x59,0xfb,0xee,0xd7,0x4e,0xf7,0xd8,0xe7,0xbd,0x3c,0x1a,0xb4,0xda,0x31,0xc5,0x1f,},{0xeb,0xf1,0x0d,0x9a,0xc7,0xc9,0x61,0x08,0x14,0x0e,0x7d,0xef,0x6f,0xe9,0x53,0x3d,0x72,0x76,0x46,0xff,0x5b,0x3a,0xf2,0x73,0xc1,0xdf,0x95,0x76,0x2a,0x66,0xf3,0x2b,0x65,0xa0,0x96,0x34,0xd0,0x13,0xf5,0x4b,0x5d,0xd6,0x01,0x1f,0x91,0xbc,0x33,0x6c,0xa8,0xb3,0x55,0xce,0x33,0xf8,0xcf,0xbe,0xc2,0x53,0x5a,0x4c,0x42,0x7f,0x82,0x05,},"\xa7\xc0\x4e\x8b\xa7\x5d\x0a\x03\xd8\xb1\x66\xad\x7a\x1d\x77\xe1\xb9\x1c\x7a\xaf\x7b\xef\xdd\x99\x31\x1f\xc3\xc5\x4a\x68\x4d\xdd\x97\x1d\x5b\x32\x11\xc3\xee\xaf\xf1\xe5\x4e"}, -{{0x30,0xab,0x82,0x32,0xfa,0x70,0x18,0xf0,0xce,0x6c,0x39,0xbd,0x8f,0x78,0x2f,0xe2,0xe1,0x59,0x75,0x8b,0xb0,0xf2,0xf4,0x38,0x6c,0x7f,0x28,0xcf,0xd2,0xc8,0x58,0x98,},{0xec,0xfb,0x6a,0x2b,0xd4,0x2f,0x31,0xb6,0x12,0x50,0xba,0x5d,0xe7,0xe4,0x6b,0x47,0x19,0xaf,0xdf,0xbc,0x66,0x0d,0xb7,0x1a,0x7b,0xd1,0xdf,0x7b,0x0a,0x3a,0xbe,0x37,},{0x9a,0xf8,0x85,0x34,0x4c,0xc7,0x23,0x94,0x98,0xf7,0x12,0xdf,0x80,0xbc,0x01,0xb8,0x06,0x38,0x29,0x1e,0xd4,0xa1,0xd2,0x8b,0xaa,0x55,0x45,0x01,0x7a,0x72,0xe2,0xf6,0x56,0x49,0xcc,0xf9,0x60,0x3d,0xa6,0xeb,0x5b,0xfa,0xb9,0xf5,0x54,0x3a,0x6c,0xa4,0xa7,0xaf,0x38,0x66,0x15,0x3c,0x76,0xbf,0x66,0xbf,0x95,0xde,0xf6,0x15,0xb0,0x0c,},"\x63\xb8\x0b\x79\x56\xac\xbe\xcf\x0c\x35\xe9\xab\x06\xb9\x14\xb0\xc7\x01\x4f\xe1\xa4\xbb\xc0\x21\x72\x40\xc1\xa3\x30\x95\xd7\x07\x95\x3e\xd7\x7b\x15\xd2\x11\xad\xaf\x9b\x97\xdc"}, -{{0x0d,0xdc,0xdc,0x87,0x2c,0x7b,0x74,0x8d,0x40,0xef,0xe9,0x6c,0x28,0x81,0xae,0x18,0x9d,0x87,0xf5,0x61,0x48,0xed,0x8a,0xf3,0xeb,0xbb,0xc8,0x03,0x24,0xe3,0x8b,0xdd,},{0x58,0x8d,0xda,0xdc,0xbc,0xed,0xf4,0x0d,0xf0,0xe9,0x69,0x7d,0x8b,0xb2,0x77,0xc7,0xbb,0x14,0x98,0xfa,0x1d,0x26,0xce,0x0a,0x83,0x5a,0x76,0x0b,0x92,0xca,0x7c,0x85,},{0xc1,0x79,0xc0,0x94,0x56,0xe2,0x35,0xfe,0x24,0x10,0x5a,0xfa,0x6e,0x8e,0xc0,0x46,0x37,0xf8,0xf9,0x43,0x81,0x7c,0xd0,0x98,0xba,0x95,0x38,0x7f,0x96,0x53,0xb2,0xad,0xd1,0x81,0xa3,0x14,0x47,0xd9,0x2d,0x1a,0x1d,0xdf,0x1c,0xeb,0x0d,0xb6,0x21,0x18,0xde,0x9d,0xff,0xb7,0xdc,0xd2,0x42,0x40,0x57,0xcb,0xdf,0xf5,0xd4,0x1d,0x04,0x03,},"\x65\x64\x1c\xd4\x02\xad\xd8\xbf\x3d\x1d\x67\xdb\xeb\x6d\x41\xde\xbf\xbe\xf6\x7e\x43\x17\xc3\x5b\x0a\x6d\x5b\xbb\xae\x0e\x03\x4d\xe7\xd6\x70\xba\x14\x13\xd0\x56\xf2\xd6\xf1\xde\x12"}, -{{0x89,0xf0,0xd6,0x82,0x99,0xba,0x0a,0x5a,0x83,0xf2,0x48,0xae,0x0c,0x16,0x9f,0x8e,0x38,0x49,0xa9,0xb4,0x7b,0xd4,0x54,0x98,0x84,0x30,0x5c,0x99,0x12,0xb4,0x66,0x03,},{0xab,0xa3,0xe7,0x95,0xaa,0xb2,0x01,0x2a,0xcc,0xea,0xdd,0x7b,0x3b,0xd9,0xda,0xee,0xed,0x6f,0xf5,0x25,0x8b,0xdc,0xd7,0xc9,0x36,0x99,0xc2,0xa3,0x83,0x6e,0x38,0x32,},{0x2c,0x69,0x1f,0xa8,0xd4,0x87,0xce,0x20,0xd5,0xd2,0xfa,0x41,0x55,0x91,0x16,0xe0,0xbb,0xf4,0x39,0x7c,0xf5,0x24,0x0e,0x15,0x25,0x56,0x18,0x35,0x41,0xd6,0x6c,0xf7,0x53,0x58,0x24,0x01,0xa4,0x38,0x8d,0x39,0x03,0x39,0xdb,0xef,0x4d,0x38,0x47,0x43,0xca,0xa3,0x46,0xf5,0x5f,0x8d,0xab,0xa6,0x8b,0xa7,0xb9,0x13,0x1a,0x8a,0x6e,0x0b,},"\x4f\x18\x46\xdd\x7a\xd5\x0e\x54\x5d\x4c\xfb\xff\xbb\x1d\xc2\xff\x14\x5d\xc1\x23\x75\x4d\x08\xaf\x4e\x44\xec\xc0\xbc\x8c\x91\x41\x13\x88\xbc\x76\x53\xe2\xd8\x93\xd1\xea\xc2\x10\x7d\x05"}, -{{0x0a,0x3c,0x18,0x44,0xe2,0xdb,0x07,0x0f,0xb2,0x4e,0x3c,0x95,0xcb,0x1c,0xc6,0x71,0x4e,0xf8,0x4e,0x2c,0xcd,0x2b,0x9d,0xd2,0xf1,0x46,0x0e,0xbf,0x7e,0xcf,0x13,0xb1,},{0x72,0xe4,0x09,0x93,0x7e,0x06,0x10,0xeb,0x5c,0x20,0xb3,0x26,0xdc,0x6e,0xa1,0xbb,0xbc,0x04,0x06,0x70,0x1c,0x5c,0xd6,0x7d,0x1f,0xbd,0xe0,0x91,0x92,0xb0,0x7c,0x01,},{0x87,0xf7,0xfd,0xf4,0x60,0x95,0x20,0x1e,0x87,0x7a,0x58,0x8f,0xe3,0xe5,0xaa,0xf4,0x76,0xbd,0x63,0x13,0x8d,0x8a,0x87,0x8b,0x89,0xd6,0xac,0x60,0x63,0x1b,0x34,0x58,0xb9,0xd4,0x1a,0x3c,0x61,0xa5,0x88,0xe1,0xdb,0x8d,0x29,0xa5,0x96,0x89,0x81,0xb0,0x18,0x77,0x6c,0x58,0x87,0x80,0x92,0x2f,0x5a,0xa7,0x32,0xba,0x63,0x79,0xdd,0x05,},"\x4c\x82\x74\xd0\xed\x1f\x74\xe2\xc8\x6c\x08\xd9\x55\xbd\xe5\x5b\x2d\x54\x32\x7e\x82\x06\x2a\x1f\x71\xf7\x0d\x53\x6f\xdc\x87\x22\xcd\xea\xd7\xd2\x2a\xae\xad\x2b\xfa\xa1\xad\x00\xb8\x29\x57"}, -{{0xc8,0xd7,0xa8,0x81,0x8b,0x98,0xdf,0xdb,0x20,0x83,0x9c,0x87,0x1c,0xb5,0xc4,0x8e,0x9e,0x94,0x70,0xca,0x3a,0xd3,0x5b,0xa2,0x61,0x3a,0x5d,0x31,0x99,0xc8,0xab,0x23,},{0x90,0xd2,0xef,0xbb,0xa4,0xd4,0x3e,0x6b,0x2b,0x99,0x2c,0xa1,0x60,0x83,0xdb,0xcf,0xa2,0xb3,0x22,0x38,0x39,0x07,0xb0,0xee,0x75,0xf3,0xe9,0x58,0x45,0xd3,0xc4,0x7f,},{0xfa,0x2e,0x99,0x44,0x21,0xae,0xf1,0xd5,0x85,0x66,0x74,0x81,0x3d,0x05,0xcb,0xd2,0xcf,0x84,0xef,0x5e,0xb4,0x24,0xaf,0x6e,0xcd,0x0d,0xc6,0xfd,0xbd,0xc2,0xfe,0x60,0x5f,0xe9,0x85,0x88,0x33,0x12,0xec,0xf3,0x4f,0x59,0xbf,0xb2,0xf1,0xc9,0x14,0x9e,0x5b,0x9c,0xc9,0xec,0xda,0x05,0xb2,0x73,0x11,0x30,0xf3,0xed,0x28,0xdd,0xae,0x0b,},"\x78\x3e\x33\xc3\xac\xbd\xbb\x36\xe8\x19\xf5\x44\xa7\x78\x1d\x83\xfc\x28\x3d\x33\x09\xf5\xd3\xd1\x2c\x8d\xcd\x6b\x0b\x3d\x0e\x89\xe3\x8c\xfd\x3b\x4d\x08\x85\x66\x1c\xa5\x47\xfb\x97\x64\xab\xff"}, -{{0xb4,0x82,0x70,0x36,0x12,0xd0,0xc5,0x86,0xf7,0x6c,0xfc,0xb2,0x1c,0xfd,0x21,0x03,0xc9,0x57,0x25,0x15,0x04,0xa8,0xc0,0xac,0x4c,0x86,0xc9,0xc6,0xf3,0xe4,0x29,0xff,},{0xfd,0x71,0x1d,0xc7,0xdd,0x3b,0x1d,0xfb,0x9d,0xf9,0x70,0x4b,0xe3,0xe6,0xb2,0x6f,0x58,0x7f,0xe7,0xdd,0x7b,0xa4,0x56,0xa9,0x1b,0xa4,0x3f,0xe5,0x1a,0xec,0x09,0xad,},{0x58,0x83,0x2b,0xde,0xb2,0x6f,0xea,0xfc,0x31,0xb4,0x62,0x77,0xcf,0x3f,0xb5,0xd7,0xa1,0x7d,0xfb,0x7c,0xcd,0x9b,0x1f,0x58,0xec,0xbe,0x6f,0xeb,0x97,0x96,0x66,0x82,0x8f,0x23,0x9b,0xa4,0xd7,0x52,0x19,0x26,0x0e,0xca,0xc0,0xac,0xf4,0x0f,0x0e,0x5e,0x25,0x90,0xf4,0xca,0xa1,0x6b,0xbb,0xcd,0x8a,0x15,0x5d,0x34,0x79,0x67,0xa6,0x07,},"\x29\xd7\x7a\xcf\xd9\x9c\x7a\x00\x70\xa8\x8f\xeb\x62\x47\xa2\xbc\xe9\x98\x4f\xe3\xe6\xfb\xf1\x9d\x40\x45\x04\x2a\x21\xab\x26\xcb\xd7\x71\xe1\x84\xa9\xa7\x5f\x31\x6b\x64\x8c\x69\x20\xdb\x92\xb8\x7b"}, -{{0x84,0xe5,0x0d,0xd9,0xa0,0xf1,0x97,0xe3,0x89,0x3c,0x38,0xdb,0xd9,0x1f,0xaf,0xc3,0x44,0xc1,0x77,0x6d,0x3a,0x40,0x0e,0x2f,0x0f,0x0e,0xe7,0xaa,0x82,0x9e,0xb8,0xa2,},{0x2c,0x50,0xf8,0x70,0xee,0x48,0xb3,0x6b,0x0a,0xc2,0xf8,0xa5,0xf3,0x36,0xfb,0x09,0x0b,0x11,0x30,0x50,0xdb,0xcc,0x25,0xe0,0x78,0x20,0x0a,0x6e,0x16,0x15,0x3e,0xea,},{0x69,0xe6,0xa4,0x49,0x1a,0x63,0x83,0x73,0x16,0xe8,0x6a,0x5f,0x4b,0xa7,0xcd,0x0d,0x73,0x1e,0xcc,0x58,0xf1,0xd0,0xa2,0x64,0xc6,0x7c,0x89,0xbe,0xfd,0xd8,0xd3,0x82,0x9d,0x8d,0xe1,0x3b,0x33,0xcc,0x0b,0xf5,0x13,0x93,0x17,0x15,0xc7,0x80,0x96,0x57,0xe2,0xbf,0xb9,0x60,0xe5,0xc7,0x64,0xc9,0x71,0xd7,0x33,0x74,0x60,0x93,0xe5,0x00,},"\xf3\x99\x2c\xde\x64\x93\xe6\x71\xf1\xe1\x29\xdd\xca\x80\x38\xb0\xab\xdb\x77\xbb\x90\x35\xf9\xf8\xbe\x54\xbd\x5d\x68\xc1\xae\xff\x72\x4f\xf4\x7d\x29\x34\x43\x91\xdc\x53\x61\x66\xb8\x67\x1c\xbb\xf1\x23"}, -{{0xb3,0x22,0xd4,0x65,0x77,0xa2,0xa9,0x91,0xa4,0xd1,0x69,0x82,0x87,0x83,0x2a,0x39,0xc4,0x87,0xef,0x77,0x6b,0x4b,0xff,0x03,0x7a,0x05,0xc7,0xf1,0x81,0x2b,0xde,0xec,},{0xeb,0x2b,0xca,0xdf,0xd3,0xee,0xc2,0x98,0x6b,0xaf,0xf3,0x2b,0x98,0xe7,0xc4,0xdb,0xf0,0x3f,0xf9,0x5d,0x8a,0xd5,0xff,0x9a,0xa9,0x50,0x6e,0x54,0x72,0xff,0x84,0x5f,},{0xc7,0xb5,0x51,0x37,0x31,0x7c,0xa2,0x1e,0x33,0x48,0x9f,0xf6,0xa9,0xbf,0xab,0x97,0xc8,0x55,0xdc,0x6f,0x85,0x68,0x4a,0x70,0xa9,0x12,0x5a,0x26,0x1b,0x56,0xd5,0xe6,0xf1,0x49,0xc5,0x77,0x4d,0x73,0x4f,0x2d,0x8d,0xeb,0xfc,0x77,0xb7,0x21,0x89,0x6a,0x82,0x67,0xc2,0x37,0x68,0xe9,0xba,0xdb,0x91,0x0e,0xef,0x83,0xec,0x25,0x88,0x02,},"\x19\xf1\xbf\x5d\xcf\x17\x50\xc6\x11\xf1\xc4\xa2\x86\x52\x00\x50\x4d\x82\x29\x8e\xdd\x72\x67\x1f\x62\xa7\xb1\x47\x1a\xc3\xd4\xa3\x0f\x7d\xe9\xe5\xda\x41\x08\xc5\x2a\x4c\xe7\x0a\x3e\x11\x4a\x52\xa3\xb3\xc5"}, -{{0x96,0x0c,0xab,0x50,0x34,0xb9,0x83,0x8d,0x09,0x8d,0x2d,0xcb,0xf4,0x36,0x4b,0xec,0x16,0xd3,0x88,0xf6,0x37,0x6d,0x73,0xa6,0x27,0x3b,0x70,0xf8,0x2b,0xbc,0x98,0xc0,},{0x5e,0x3c,0x19,0xf2,0x41,0x5a,0xcf,0x72,0x9f,0x82,0x9a,0x4e,0xbd,0x5c,0x40,0xe1,0xa6,0xbc,0x9f,0xbc,0xa9,0x57,0x03,0xa9,0x37,0x60,0x87,0xed,0x09,0x37,0xe5,0x1a,},{0x27,0xd4,0xc3,0xa1,0x81,0x1e,0xf9,0xd4,0x36,0x0b,0x3b,0xdd,0x13,0x3c,0x2c,0xcc,0x30,0xd0,0x2c,0x2f,0x24,0x82,0x15,0x77,0x6c,0xb0,0x7e,0xe4,0x17,0x7f,0x9b,0x13,0xfc,0x42,0xdd,0x70,0xa6,0xc2,0xfe,0xd8,0xf2,0x25,0xc7,0x66,0x3c,0x7f,0x18,0x2e,0x7e,0xe8,0xec,0xcf,0xf2,0x0d,0xc7,0xb0,0xe1,0xd5,0x83,0x4e,0xc5,0xb1,0xea,0x01,},"\xf8\xb2\x19\x62\x44\x7b\x0a\x8f\x2e\x42\x79\xde\x41\x1b\xea\x12\x8e\x0b\xe4\x4b\x69\x15\xe6\xcd\xa8\x83\x41\xa6\x8a\x0d\x81\x83\x57\xdb\x93\x8e\xac\x73\xe0\xaf\x6d\x31\x20\x6b\x39\x48\xf8\xc4\x8a\x44\x73\x08"}, -{{0xeb,0x77,0xb2,0x63,0x8f,0x23,0xee,0xbc,0x82,0xef,0xe4,0x5e,0xe9,0xe5,0xa0,0x32,0x66,0x37,0x40,0x1e,0x66,0x3e,0xd0,0x29,0x69,0x9b,0x21,0xe6,0x44,0x3f,0xb4,0x8e,},{0x9e,0xf2,0x76,0x08,0x96,0x1a,0xc7,0x11,0xde,0x71,0xa6,0xe2,0xd4,0xd4,0x66,0x3e,0xa3,0xec,0xd4,0x2f,0xb7,0xe4,0xe8,0x62,0x7c,0x39,0x62,0x2d,0xf4,0xaf,0x0b,0xbc,},{0x18,0xdc,0x56,0xd7,0xbd,0x9a,0xcd,0x4f,0x4d,0xaa,0x78,0x54,0x0b,0x4a,0xc8,0xff,0x7a,0xa9,0x81,0x5f,0x45,0xa0,0xbb,0xa3,0x70,0x73,0x1a,0x14,0xea,0xab,0xe9,0x6d,0xf8,0xb5,0xf3,0x7d,0xbf,0x8e,0xae,0x4c,0xb1,0x5a,0x64,0xb2,0x44,0x65,0x1e,0x59,0xd6,0xa3,0xd6,0x76,0x1d,0x9e,0x3c,0x50,0xf2,0xd0,0xcb,0xb0,0x9c,0x05,0xec,0x06,},"\x99\xe3\xd0\x09\x34\x00\x3e\xba\xfc\x3e\x9f\xdb\x68\x7b\x0f\x5f\xf9\xd5\x78\x2a\x4b\x1f\x56\xb9\x70\x00\x46\xc0\x77\x91\x56\x02\xc3\x13\x4e\x22\xfc\x90\xed\x7e\x69\x0f\xdd\xd4\x43\x3e\x20\x34\xdc\xb2\xdc\x99\xab"}, -{{0xb6,0x25,0xaa,0x89,0xd3,0xf7,0x30,0x87,0x15,0x42,0x7b,0x6c,0x39,0xbb,0xac,0x58,0xef,0xfd,0x3a,0x0f,0xb7,0x31,0x6f,0x7a,0x22,0xb9,0x9e,0xe5,0x92,0x2f,0x2d,0xc9,},{0x65,0xa9,0x9c,0x3e,0x16,0xfe,0xa8,0x94,0xec,0x33,0xc6,0xb2,0x0d,0x91,0x05,0xe2,0xa0,0x4e,0x27,0x64,0xa4,0x76,0x9d,0x9b,0xbd,0x4d,0x8b,0xac,0xfe,0xab,0x4a,0x2e,},{0x01,0xbb,0x90,0x1d,0x83,0xb8,0xb6,0x82,0xd3,0x61,0x4a,0xf4,0x6a,0x80,0x7b,0xa2,0x69,0x13,0x58,0xfe,0xb7,0x75,0x32,0x5d,0x34,0x23,0xf5,0x49,0xff,0x0a,0xa5,0x75,0x7e,0x4e,0x1a,0x74,0xe9,0xc7,0x0f,0x97,0x21,0xd8,0xf3,0x54,0xb3,0x19,0xd4,0xf4,0xa1,0xd9,0x14,0x45,0xc8,0x70,0xfd,0x0f,0xfb,0x94,0xfe,0xd6,0x46,0x64,0x73,0x0d,},"\xe0\x72\x41\xdb\xd3\xad\xbe\x61\x0b\xbe\x4d\x00\x5d\xd4\x67\x32\xa4\xc2\x50\x86\xec\xb8\xec\x29\xcd\x7b\xca\x11\x6e\x1b\xf9\xf5\x3b\xfb\xf3\xe1\x1f\xa4\x90\x18\xd3\x9f\xf1\x15\x4a\x06\x66\x8e\xf7\xdf\x5c\x67\x8e\x6a"}, -{{0xb1,0xc9,0xf8,0xbd,0x03,0xfe,0x82,0xe7,0x8f,0x5c,0x0f,0xb0,0x64,0x50,0xf2,0x7d,0xac,0xdf,0x71,0x64,0x34,0xdb,0x26,0x82,0x75,0xdf,0x3e,0x1d,0xc1,0x77,0xaf,0x42,},{0x7f,0xc8,0x8b,0x1f,0x7b,0x3f,0x11,0xc6,0x29,0xbe,0x67,0x1c,0x21,0x62,0x1f,0x5c,0x10,0x67,0x2f,0xaf,0xc8,0x49,0x2d,0xa8,0x85,0x74,0x20,0x59,0xee,0x67,0x74,0xcf,},{0x4b,0x22,0x99,0x51,0xef,0x26,0x2f,0x16,0x97,0x8f,0x79,0x14,0xbc,0x67,0x2e,0x72,0x26,0xc5,0xf8,0x37,0x9d,0x27,0x78,0xc5,0xa2,0xdc,0x0a,0x26,0x50,0x86,0x9f,0x7a,0xcf,0xbd,0x0b,0xcd,0x30,0xfd,0xb0,0x61,0x9b,0xb4,0x4f,0xc1,0xae,0x59,0x39,0xb8,0x7c,0xc3,0x18,0x13,0x30,0x09,0xc2,0x03,0x95,0xb6,0xc7,0xeb,0x98,0x10,0x77,0x01,},"\x33\x1d\xa7\xa9\xc1\xf8\x7b\x2a\xc9\x1e\xe3\xb8\x6d\x06\xc2\x91\x63\xc0\x5e\xd6\xf8\xd8\xa9\x72\x5b\x47\x1b\x7d\xb0\xd6\xac\xec\x7f\x0f\x70\x24\x87\x16\x3f\x5e\xda\x02\x0c\xa5\xb4\x93\xf3\x99\xe1\xc8\xd3\x08\xc3\xc0\xc2"}, -{{0x6d,0x8c,0xdb,0x2e,0x07,0x5f,0x3a,0x2f,0x86,0x13,0x72,0x14,0xcb,0x23,0x6c,0xeb,0x89,0xa6,0x72,0x8b,0xb4,0xa2,0x00,0x80,0x6b,0xf3,0x55,0x7f,0xb7,0x8f,0xac,0x69,},{0x57,0xa0,0x4c,0x7a,0x51,0x13,0xcd,0xdf,0xe4,0x9a,0x4c,0x12,0x46,0x91,0xd4,0x6c,0x1f,0x9c,0xdc,0x8f,0x34,0x3f,0x9d,0xcb,0x72,0xa1,0x33,0x0a,0xec,0xa7,0x1f,0xda,},{0xa6,0xcb,0xc9,0x47,0xf9,0xc8,0x7d,0x14,0x55,0xcf,0x1a,0x70,0x85,0x28,0xc0,0x90,0xf1,0x1e,0xce,0xe4,0x85,0x5d,0x1d,0xba,0xad,0xf4,0x74,0x54,0xa4,0xde,0x55,0xfa,0x4c,0xe8,0x4b,0x36,0xd7,0x3a,0x5b,0x5f,0x8f,0x59,0x29,0x8c,0xcf,0x21,0x99,0x2d,0xf4,0x92,0xef,0x34,0x16,0x3d,0x87,0x75,0x3b,0x7e,0x9d,0x32,0xf2,0xc3,0x66,0x0b,},"\x7f\x31\x8d\xbd\x12\x1c\x08\xbf\xdd\xfe\xff\x4f\x6a\xff\x4e\x45\x79\x32\x51\xf8\xab\xf6\x58\x40\x33\x58\x23\x89\x84\x36\x00\x54\xf2\xa8\x62\xc5\xbb\x83\xed\x89\x02\x5d\x20\x14\xa7\xa0\xce\xe5\x0d\xa3\xcb\x0e\x76\xbb\xb6\xbf"}, -{{0x47,0xad,0xc6,0xd6,0xbf,0x57,0x1e,0xe9,0x57,0x0c,0xa0,0xf7,0x5b,0x60,0x4a,0xc4,0x3e,0x30,0x3e,0x4a,0xb3,0x39,0xca,0x9b,0x53,0xca,0xcc,0x5b,0xe4,0x5b,0x2c,0xcb,},{0xa3,0xf5,0x27,0xa1,0xc1,0xf1,0x7d,0xfe,0xed,0x92,0x27,0x73,0x47,0xc9,0xf9,0x8a,0xb4,0x75,0xde,0x17,0x55,0xb0,0xab,0x54,0x6b,0x8a,0x15,0xd0,0x1b,0x9b,0xd0,0xbe,},{0x4e,0x8c,0x31,0x83,0x43,0xc3,0x06,0xad,0xbb,0xa6,0x0c,0x92,0xb7,0x5c,0xb0,0x56,0x9b,0x92,0x19,0xd8,0xa8,0x6e,0x5d,0x57,0x75,0x2e,0xd2,0x35,0xfc,0x10,0x9a,0x43,0xc2,0xcf,0x4e,0x94,0x2c,0xac,0xf2,0x97,0x27,0x9f,0xbb,0x28,0x67,0x53,0x47,0xe0,0x80,0x27,0x72,0x2a,0x4e,0xb7,0x39,0x5e,0x00,0xa1,0x74,0x95,0xd3,0x2e,0xdf,0x0b,},"\xce\x49\x7c\x5f\xf5\xa7\x79\x90\xb7\xd8\xf8\x69\x9e\xb1\xf5\xd8\xc0\x58\x2f\x70\xcb\x7a\xc5\xc5\x4d\x9d\x92\x49\x13\x27\x8b\xc6\x54\xd3\x7e\xa2\x27\x59\x0e\x15\x20\x22\x17\xfc\x98\xda\xc4\xc0\xf3\xbe\x21\x83\xd1\x33\x31\x57\x39"}, -{{0x3c,0x19,0xb5,0x0b,0x0f,0xe4,0x79,0x61,0x71,0x9c,0x38,0x1d,0x0d,0x8d,0xa9,0xb9,0x86,0x9d,0x31,0x2f,0x13,0xe3,0x29,0x8b,0x97,0xfb,0x22,0xf0,0xaf,0x29,0xcb,0xbe,},{0x0f,0x7e,0xda,0x09,0x14,0x99,0x62,0x5e,0x2b,0xae,0x85,0x36,0xea,0x35,0xcd,0xa5,0x48,0x3b,0xd1,0x6a,0x9c,0x7e,0x41,0x6b,0x34,0x1d,0x6f,0x2c,0x83,0x34,0x36,0x12,},{0xef,0xbd,0x41,0xf2,0x6a,0x5d,0x62,0x68,0x55,0x16,0xf8,0x82,0xb6,0xec,0x74,0xe0,0xd5,0xa7,0x18,0x30,0xd2,0x03,0xc2,0x31,0x24,0x8f,0x26,0xe9,0x9a,0x9c,0x65,0x78,0xec,0x90,0x0d,0x68,0xcd,0xb8,0xfa,0x72,0x16,0xad,0x0d,0x24,0xf9,0xec,0xbc,0x9f,0xfa,0x65,0x53,0x51,0x66,0x65,0x82,0xf6,0x26,0x64,0x53,0x95,0xa3,0x1f,0xa7,0x04,},"\x8d\xdc\xd6\x30\x43\xf5\x5e\xc3\xbf\xc8\x3d\xce\xae\x69\xd8\xf8\xb3\x2f\x4c\xdb\x6e\x2a\xeb\xd9\x4b\x43\x14\xf8\xfe\x72\x87\xdc\xb6\x27\x32\xc9\x05\x2e\x75\x57\xfe\x63\x53\x43\x38\xef\xb5\xb6\x25\x4c\x5d\x41\xd2\x69\x0c\xf5\x14\x4f"}, -{{0x34,0xe1,0xe9,0xd5,0x39,0x10,0x7e,0xb8,0x6b,0x39,0x3a,0x5c,0xce,0xa1,0x49,0x6d,0x35,0xbc,0x7d,0x5e,0x9a,0x8c,0x51,0x59,0xd9,0x57,0xe4,0xe5,0x85,0x2b,0x3e,0xb0,},{0x0e,0xcb,0x26,0x01,0xd5,0xf7,0x04,0x74,0x28,0xe9,0xf9,0x09,0x88,0x3a,0x12,0x42,0x00,0x85,0xf0,0x4e,0xe2,0xa8,0x8b,0x6d,0x95,0xd3,0xd7,0xf2,0xc9,0x32,0xbd,0x76,},{0x32,0xd2,0x29,0x04,0xd3,0xe7,0x01,0x2d,0x6f,0x5a,0x44,0x1b,0x0b,0x42,0x28,0x06,0x4a,0x5c,0xf9,0x5b,0x72,0x3a,0x66,0xb0,0x48,0xa0,0x87,0xec,0xd5,0x59,0x20,0xc3,0x1c,0x20,0x4c,0x3f,0x20,0x06,0x89,0x1a,0x85,0xdd,0x19,0x32,0xe3,0xf1,0xd6,0x14,0xcf,0xd6,0x33,0xb5,0xe6,0x32,0x91,0xc6,0xd8,0x16,0x6f,0x30,0x11,0x43,0x1e,0x09,},"\xa6\xd4\xd0\x54\x2c\xfe\x0d\x24\x0a\x90\x50\x7d\xeb\xac\xab\xce\x7c\xbb\xd4\x87\x32\x35\x3f\x4f\xad\x82\xc7\xbb\x7d\xbd\x9d\xf8\xe7\xd9\xa1\x69\x80\xa4\x51\x86\xd8\x78\x6c\x5e\xf6\x54\x45\xbc\xc5\xb2\xad\x5f\x66\x0f\xfc\x7c\x8e\xaa\xc0"}, -{{0x49,0xdd,0x47,0x3e,0xde,0x6a,0xa3,0xc8,0x66,0x82,0x4a,0x40,0xad,0xa4,0x99,0x6c,0x23,0x9a,0x20,0xd8,0x4c,0x93,0x65,0xe4,0xf0,0xa4,0x55,0x4f,0x80,0x31,0xb9,0xcf,},{0x78,0x8d,0xe5,0x40,0x54,0x4d,0x3f,0xeb,0x0c,0x91,0x92,0x40,0xb3,0x90,0x72,0x9b,0xe4,0x87,0xe9,0x4b,0x64,0xad,0x97,0x3e,0xb6,0x5b,0x46,0x69,0xec,0xf2,0x35,0x01,},{0xd2,0xfd,0xe0,0x27,0x91,0xe7,0x20,0x85,0x25,0x07,0xfa,0xa7,0xc3,0x78,0x90,0x40,0xd9,0xef,0x86,0x64,0x63,0x21,0xf3,0x13,0xac,0x55,0x7f,0x40,0x02,0x49,0x15,0x42,0xdd,0x67,0xd0,0x5c,0x69,0x90,0xcd,0xb0,0xd4,0x95,0x50,0x1f,0xbc,0x5d,0x51,0x88,0xbf,0xbb,0x84,0xdc,0x1b,0xf6,0x09,0x8b,0xee,0x06,0x03,0xa4,0x7f,0xc2,0x69,0x0f,},"\x3a\x53\x59\x4f\x3f\xba\x03\x02\x93\x18\xf5\x12\xb0\x84\xa0\x71\xeb\xd6\x0b\xae\xc7\xf5\x5b\x02\x8d\xc7\x3b\xfc\x9c\x74\xe0\xca\x49\x6b\xf8\x19\xdd\x92\xab\x61\xcd\x8b\x74\xbe\x3c\x0d\x6d\xcd\x12\x8e\xfc\x5e\xd3\x34\x2c\xba\x12\x4f\x72\x6c"}, -{{0x33,0x1c,0x64,0xda,0x48,0x2b,0x6b,0x55,0x13,0x73,0xc3,0x64,0x81,0xa0,0x2d,0x81,0x36,0xec,0xad,0xbb,0x01,0xab,0x11,0x4b,0x44,0x70,0xbf,0x41,0x60,0x7a,0xc5,0x71,},{0x52,0xa0,0x0d,0x96,0xa3,0x14,0x8b,0x47,0x26,0x69,0x2d,0x9e,0xff,0x89,0x16,0x0e,0xa9,0xf9,0x9a,0x5c,0xc4,0x38,0x9f,0x36,0x1f,0xed,0x0b,0xb1,0x6a,0x42,0xd5,0x21,},{0x22,0xc9,0x9a,0xa9,0x46,0xea,0xd3,0x9a,0xc7,0x99,0x75,0x62,0x81,0x0c,0x01,0xc2,0x0b,0x46,0xbd,0x61,0x06,0x45,0xbd,0x2d,0x56,0xdc,0xdc,0xba,0xac,0xc5,0x45,0x2c,0x74,0xfb,0xf4,0xb8,0xb1,0x81,0x3b,0x0e,0x94,0xc3,0x0d,0x80,0x8c,0xe5,0x49,0x8e,0x61,0xd4,0xf7,0xcc,0xbb,0x4c,0xc5,0xf0,0x4d,0xfc,0x61,0x40,0x82,0x5a,0x96,0x00,},"\x20\xe1\xd0\x5a\x0d\x5b\x32\xcc\x81\x50\xb8\x11\x6c\xef\x39\x65\x9d\xd5\xfb\x44\x3a\xb1\x56\x00\xf7\x8e\x5b\x49\xc4\x53\x26\xd9\x32\x3f\x28\x50\xa6\x3c\x38\x08\x85\x94\x95\xae\x27\x3f\x58\xa5\x1e\x9d\xe9\xa1\x45\xd7\x74\xb4\x0b\xa9\xd7\x53\xd3"}, -{{0x5c,0x0b,0x96,0xf2,0xaf,0x87,0x12,0x12,0x2c,0xf7,0x43,0xc8,0xf8,0xdc,0x77,0xb6,0xcd,0x55,0x70,0xa7,0xde,0x13,0x29,0x7b,0xb3,0xdd,0xe1,0x88,0x62,0x13,0xcc,0xe2,},{0x05,0x10,0xea,0xf5,0x7d,0x73,0x01,0xb0,0xe1,0xd5,0x27,0x03,0x9b,0xf4,0xc6,0xe2,0x92,0x30,0x0a,0x3a,0x61,0xb4,0x76,0x54,0x34,0xf3,0x20,0x3c,0x10,0x03,0x51,0xb1,},{0x06,0xe5,0xd8,0x43,0x6a,0xc7,0x70,0x5b,0x3a,0x90,0xf1,0x63,0x1c,0xdd,0x38,0xec,0x1a,0x3f,0xa4,0x97,0x78,0xa9,0xb9,0xf2,0xfa,0x5e,0xbe,0xa4,0xe7,0xd5,0x60,0xad,0xa7,0xdd,0x26,0xff,0x42,0xfa,0xfa,0x8b,0xa4,0x20,0x32,0x37,0x42,0x76,0x1a,0xca,0x69,0x04,0x94,0x0d,0xc2,0x1b,0xbe,0xf6,0x3f,0xf7,0x2d,0xaa,0xb4,0x5d,0x43,0x0b,},"\x54\xe0\xca\xa8\xe6\x39\x19\xca\x61\x4b\x2b\xfd\x30\x8c\xcf\xe5\x0c\x9e\xa8\x88\xe1\xee\x44\x46\xd6\x82\xcb\x50\x34\x62\x7f\x97\xb0\x53\x92\xc0\x4e\x83\x55\x56\xc3\x1c\x52\x81\x6a\x48\xe4\xfb\x19\x66\x93\x20\x6b\x8a\xfb\x44\x08\x66\x2b\x3c\xb5\x75"}, -{{0xde,0x84,0xf2,0x43,0x5f,0x78,0xde,0xdb,0x87,0xda,0x18,0x19,0x4f,0xf6,0xa3,0x36,0xf0,0x81,0x11,0x15,0x0d,0xef,0x90,0x1c,0x1a,0xc4,0x18,0x14,0x6e,0xb7,0xb5,0x4a,},{0xd3,0xa9,0x2b,0xba,0xa4,0xd6,0x3a,0xf7,0x9c,0x22,0x26,0xa7,0x23,0x6e,0x64,0x27,0x42,0x8d,0xf8,0xb3,0x62,0x42,0x7f,0x87,0x30,0x23,0xb2,0x2d,0x2f,0x5e,0x03,0xf2,},{0x47,0x1e,0xbc,0x97,0x3c,0xfd,0xac,0xee,0xc0,0x72,0x79,0x30,0x73,0x68,0xb7,0x3b,0xe3,0x5b,0xc6,0xf8,0xd8,0x31,0x2b,0x70,0x15,0x05,0x67,0x36,0x90,0x96,0x70,0x6d,0xc4,0x71,0x12,0x6c,0x35,0x76,0xf9,0xf0,0xeb,0x55,0x0d,0xf5,0xac,0x6a,0x52,0x51,0x81,0x11,0x00,0x29,0xdd,0x1f,0xc1,0x11,0x74,0xd1,0xaa,0xce,0xd4,0x8d,0x63,0x0f,},"\x20\x51\x35\xec\x7f\x41\x7c\x85\x80\x72\xd5\x23\x3f\xb3\x64\x82\xd4\x90\x6a\xbd\x60\xa7\x4a\x49\x8c\x34\x7f\xf2\x48\xdf\xa2\x72\x2c\xa7\x4e\x87\x9d\xe3\x31\x69\xfa\xdc\x7c\xd4\x4d\x6c\x94\xa1\x7d\x16\xe1\xe6\x30\x82\x4b\xa3\xe0\xdf\x22\xed\x68\xea\xab"}, -{{0xba,0x4d,0x6e,0x67,0xb2,0xce,0x67,0xa1,0xe4,0x43,0x26,0x49,0x40,0x44,0xf3,0x7a,0x44,0x2f,0x3b,0x81,0x72,0x5b,0xc1,0xf9,0x34,0x14,0x62,0x71,0x8b,0x55,0xee,0x20,},{0xf7,0x3f,0xa0,0x76,0xf8,0x4b,0x6d,0xb6,0x75,0xa5,0xfd,0xa5,0xad,0x67,0xe3,0x51,0xa4,0x1e,0x8e,0x7f,0x29,0xad,0xd1,0x68,0x09,0xca,0x01,0x03,0x87,0xe9,0xc6,0xcc,},{0x57,0xb9,0xd2,0xa7,0x11,0x20,0x7f,0x83,0x74,0x21,0xba,0xe7,0xdd,0x48,0xea,0xa1,0x8e,0xab,0x1a,0x9a,0x70,0xa0,0xf1,0x30,0x58,0x06,0xfe,0xe1,0x7b,0x45,0x8f,0x3a,0x09,0x64,0xb3,0x02,0xd1,0x83,0x4d,0x3e,0x0a,0xc9,0xe8,0x49,0x6f,0x00,0x0b,0x77,0xf0,0x08,0x3b,0x41,0xf8,0xa9,0x57,0xe6,0x32,0xfb,0xc7,0x84,0x0e,0xee,0x6a,0x06,},"\x4b\xaf\xda\xc9\x09\x9d\x40\x57\xed\x6d\xd0\x8b\xca\xee\x87\x56\xe9\xa4\x0f\x2c\xb9\x59\x80\x20\xeb\x95\x01\x95\x28\x40\x9b\xbe\xa3\x8b\x38\x4a\x59\xf1\x19\xf5\x72\x97\xbf\xb2\xfa\x14\x2f\xc7\xbb\x1d\x90\xdb\xdd\xde\x77\x2b\xcd\xe4\x8c\x56\x70\xd5\xfa\x13"}, -{{0x0d,0x13,0x1c,0x45,0xae,0xa6,0xf3,0xa4,0xe1,0xb9,0xa2,0xcf,0x60,0xc5,0x51,0x04,0x58,0x7e,0xfa,0xa8,0x46,0xb2,0x22,0xbf,0x0a,0x7b,0x74,0xce,0x7a,0x3f,0x63,0xb6,},{0x3c,0x67,0x29,0xdb,0xe9,0x3b,0x49,0x9c,0x4e,0x61,0x4a,0x2f,0x21,0xbe,0xb7,0x29,0x43,0x8d,0x49,0x8e,0x1a,0xc8,0xd1,0x4c,0xba,0xd9,0x71,0x7a,0x5d,0xbd,0x97,0xcd,},{0xa9,0xc5,0xee,0x86,0xfb,0x06,0xd9,0xe4,0x6b,0x37,0x9c,0x32,0xdd,0xa7,0xc9,0x2c,0x9c,0x13,0xdb,0x27,0x4d,0xc2,0x41,0x16,0xfb,0xdd,0x87,0x86,0x96,0x04,0x54,0x88,0xcc,0x75,0xa5,0x2f,0xff,0x67,0xd1,0xa5,0x11,0x3d,0x06,0xe3,0x33,0xac,0x67,0xff,0x66,0x4b,0x3f,0x2a,0x40,0x5f,0xa1,0xd1,0x4d,0xd5,0xbb,0xb9,0x74,0x09,0xb6,0x06,},"\xb4\x29\x1d\x08\xb8\x8f\xb2\xf7\xb8\xf9\x9d\x0d\xce\x40\x07\x9f\xcb\xab\x71\x8b\xbd\x8f\x4e\x8e\xab\xc3\xc1\x42\x8b\x6a\x07\x1f\xb2\xa3\xc8\xeb\xa1\xca\xcc\xcf\xa8\x71\xb3\x65\xc7\x08\xbe\xf2\x68\x5b\xc1\x3e\x6b\x80\xbc\x14\xa5\xf2\x49\x17\x0f\xfc\x56\xd0\x14"}, -{{0xa7,0x5e,0x3b,0x6b,0x41,0x70,0xe4,0x44,0x78,0x1b,0xe4,0xee,0xac,0x3e,0x0f,0xda,0xa4,0xb4,0x35,0x6f,0x70,0x54,0x86,0xbc,0xb0,0x71,0xa3,0x25,0xae,0x07,0x1f,0xba,},{0x99,0x3d,0x38,0xa7,0xd7,0x2f,0x0a,0xee,0x15,0xff,0x6f,0x4f,0xdc,0x37,0xca,0x77,0x24,0xfd,0x13,0x73,0xa3,0x76,0x6b,0x27,0x5d,0xbc,0x77,0xe6,0x47,0x98,0x0e,0x0a,},{0xa5,0xdb,0x4d,0x3d,0x33,0x29,0xab,0xe3,0x69,0x79,0x59,0xe6,0xb5,0x94,0x7e,0xa8,0x60,0x1b,0x03,0xef,0x8e,0x1d,0x6f,0xe2,0x02,0x14,0x49,0x31,0x27,0x2c,0xa0,0xa0,0x9b,0x5e,0xb0,0xf3,0x90,0x57,0x2e,0xa7,0xef,0x03,0xc6,0x13,0x1e,0x9d,0xe5,0xf1,0x6b,0xf0,0xb0,0x34,0x24,0x4f,0x7e,0x10,0x4f,0xf5,0x31,0x1b,0xbf,0x66,0x3a,0x0d,},"\x40\x37\x86\x6f\x65\x48\xb0\x1c\xc6\xbc\xf3\xa9\x40\xe3\x94\x5a\xa2\xd1\x88\xb4\xb7\xf1\x82\xaa\x77\xec\x4d\x6b\x04\x28\xab\x5b\x84\xd8\x5d\xf1\x92\xa5\xa3\x8a\xda\x08\x9d\x76\xfa\x26\xbf\x67\x73\x6a\x70\x41\xa5\xeb\x8f\x0c\x57\x19\xeb\x39\x66\x93\xc4\x51\x60\xf8"}, -{{0xbc,0xbc,0xf5,0x61,0xec,0xc0,0x5a,0x41,0xc7,0xd7,0xe5,0x5e,0x69,0x6d,0x32,0xce,0x39,0xb4,0xd0,0x3c,0x1f,0x5f,0x3f,0x3a,0x89,0x27,0xfe,0x5e,0x62,0xe8,0x44,0xb2,},{0x4d,0xdf,0x53,0xfa,0xd6,0xa7,0xa9,0xed,0x30,0xf3,0xaf,0xec,0xca,0x13,0x6f,0xd7,0x84,0x3b,0x72,0xc2,0x43,0x09,0x08,0x91,0xae,0x40,0x21,0xa3,0x2c,0xad,0xff,0x1a,},{0x9f,0xf1,0x51,0x15,0xf6,0x66,0x1f,0x32,0x11,0xd7,0xa4,0x07,0x64,0x96,0x76,0x29,0xba,0x6a,0x52,0x63,0x95,0x1b,0xdc,0x3c,0x6a,0x4c,0x90,0xd0,0x70,0xf7,0xbe,0x00,0x02,0x4b,0x80,0xd8,0x3b,0x6b,0xc2,0x75,0x87,0xfc,0xff,0x5f,0x5c,0xcc,0x0e,0xb3,0xcd,0xe1,0x49,0x7c,0xf5,0x68,0x95,0x14,0x7a,0x06,0x3f,0x61,0xf0,0x8a,0xdf,0x0b,},"\x6f\x67\x16\xb6\x78\x47\x40\x98\x0a\xeb\xc3\x24\x88\x07\xe3\x1c\x12\x86\xac\x7b\x68\x1c\x00\xb6\x6c\x88\xff\x7a\x33\x6d\x44\x1f\xa5\xc3\xeb\x25\x6d\x20\xcf\x6d\x1a\xc9\x2c\xcf\xe4\xbe\x6d\xcc\x41\xb1\xaf\xf8\x46\xd3\x60\xc2\x43\x00\x1c\xab\xdf\xbf\x1a\x9b\x24\x04\x55"}, -{{0x21,0x05,0x32,0x80,0x5f,0xa9,0xcc,0x9b,0xe9,0x16,0xd2,0x13,0xca,0xc3,0x74,0xe3,0xcd,0x6f,0xc2,0x60,0x2a,0x54,0x4d,0x0c,0x1c,0xe2,0x9d,0x30,0x10,0x5d,0x69,0xab,},{0x10,0x69,0x9e,0x49,0x9b,0xe9,0x9e,0x2b,0x11,0xb9,0x8f,0x6f,0x86,0xb6,0x7c,0xdc,0x4c,0xcf,0x69,0xf3,0xc5,0x3c,0xe0,0x94,0x87,0x56,0x47,0xd2,0xd0,0xd0,0xec,0xc5,},{0x4c,0x2d,0x31,0xd5,0xbb,0xc4,0x2e,0x02,0x6d,0xc1,0xe0,0x79,0xec,0xc4,0xdd,0x07,0x2c,0x5d,0x2c,0xce,0x65,0xe3,0xdb,0x8d,0x8a,0x1d,0xd9,0x05,0x7f,0xaa,0x03,0x71,0x72,0x7f,0x72,0x72,0x31,0xa0,0xf0,0x60,0xfa,0x27,0x09,0x75,0x33,0xb6,0xdb,0x3b,0x8f,0x62,0x52,0xf2,0x79,0x3d,0x75,0x66,0x2c,0xaa,0xdf,0x5f,0x0f,0xcc,0x71,0x0e,},"\x9f\xc4\xd2\x8c\xfd\x25\xe6\xc0\xc5\xe7\x24\xe1\x9c\xa3\x9d\x71\xe5\x3b\xf4\xaa\x27\x96\xc5\x4c\x33\x51\xf1\x08\xfc\x70\xf2\x61\x1a\x62\xe0\xab\x90\xaf\x6a\xde\x52\x16\x78\x8e\x9e\xb2\xa8\x73\x05\x9b\x1e\x79\xd7\xd5\x9d\xeb\xd6\x8f\x2d\x4d\x80\xff\xe3\x1b\xf7\x4b\x92\x8c"}, -{{0x18,0x5d,0x64,0xb6,0x94,0x79,0xe0,0xba,0x0a,0x58,0x44,0xa1,0x0a,0xd8,0x41,0x25,0xba,0x11,0xc4,0xb4,0x0d,0x63,0xed,0xa2,0xc5,0x7a,0xfc,0x7e,0x01,0x9c,0x8e,0x0c,},{0xa5,0x76,0x4f,0x63,0x98,0xa5,0xae,0x22,0x66,0xa3,0x8f,0x97,0x14,0x53,0x3c,0x4b,0xbd,0x8d,0x07,0x82,0x6f,0x63,0xe2,0x04,0xcb,0xac,0x37,0x4b,0x0a,0xce,0xf1,0xbd,},{0x43,0xe0,0x38,0x7d,0xa5,0xba,0x09,0xa1,0x90,0xf6,0xe7,0xb2,0x68,0x05,0x78,0xd8,0x89,0x76,0x9b,0xcc,0x44,0x5e,0x5e,0xf5,0x71,0xb4,0x92,0x87,0x1c,0x15,0x5c,0x5b,0x9f,0x62,0x0b,0xfa,0xcf,0xbf,0x2d,0xf1,0xfd,0x87,0x44,0x46,0x04,0xb7,0x1b,0x2e,0x23,0x7b,0xaa,0xa7,0xee,0x20,0x93,0xed,0xe4,0xa6,0x01,0xed,0xf8,0x83,0xe3,0x07,},"\x4a\x08\x24\xfe\x70\xd4\x31\x54\x13\xd0\xa0\xca\xfb\xf4\xf5\xfe\x11\x7d\x5e\x07\xe1\xc3\xa4\xef\xfb\x9d\x0a\xe9\x14\x90\x23\x48\x78\xcc\xf6\x79\x2a\x91\xf6\x8c\x6a\x52\x0d\xe1\x60\x71\xf0\x8a\xbe\x35\xdc\x5e\xa4\x28\xf1\x95\x7b\x66\x33\x71\xce\x24\xc6\x09\xdd\x55\xb8\xf4\x93"}, -{{0xcf,0xa9,0xd9,0x16,0x4b,0x3c,0x4f,0x6f,0x72,0x26,0x35,0xd2,0x06,0x6c,0xd7,0xea,0x5e,0x55,0x33,0xd2,0xc7,0x4f,0x8a,0xdd,0x66,0x9c,0x37,0x1f,0xaa,0x47,0x64,0x26,},{0x41,0x16,0x9a,0x66,0xf9,0xa6,0x3f,0x28,0x57,0x82,0xa6,0xc2,0xdb,0x81,0xcc,0x3f,0x70,0xb3,0xad,0xa2,0x1a,0x68,0xc8,0x47,0x45,0xc8,0x8a,0x74,0xc3,0xb0,0xa2,0xde,},{0x01,0xd7,0xc9,0xb5,0x70,0x1a,0xf7,0x1e,0x2f,0x48,0x77,0xff,0xc9,0xb7,0xb5,0x30,0x5f,0x52,0x81,0x6d,0x44,0x58,0xe3,0x7e,0x41,0xc7,0x71,0x9f,0xac,0x1d,0x76,0xa0,0x1f,0xff,0x3f,0x50,0xfe,0x1a,0x58,0x75,0xcc,0xc3,0xfb,0x70,0x00,0x1c,0x94,0x7a,0x33,0xfc,0x8b,0x20,0x7d,0xe1,0x35,0x72,0xcc,0xdb,0x8b,0xa9,0x89,0x33,0xab,0x01,},"\x75\x76\x21\xb1\x67\x5d\xb7\xca\xce\xf7\xf2\x78\x25\x87\xff\x3a\xf5\x1a\x3e\xf2\xf4\xbc\xf9\x27\x9c\x4c\xe9\x40\x02\xe1\xf0\x04\x24\xbf\x0e\xb6\x21\x98\x2c\xc8\x5c\xb4\xd1\x71\xe5\x64\xa0\xc2\xf6\xe3\x56\x7a\x1a\xae\x2c\xdd\xb7\xe9\xb2\x5f\x47\xdc\x20\xa5\x10\x50\x54\x29\x69\xca"}, -{{0x1a,0xcb,0x4a,0x25,0x6c,0x2f,0x89,0x93,0xca,0x24,0xde,0x1e,0x00,0x14,0x60,0x6d,0x66,0x8b,0x5e,0x75,0x60,0x32,0xd2,0x69,0xf1,0xd2,0x4d,0x35,0x1c,0x8e,0xea,0x4a,},{0xcb,0xbd,0xcd,0x8c,0xbc,0x88,0x5a,0xb4,0x3a,0x05,0x7e,0x5f,0x95,0x79,0xf1,0x16,0x19,0x54,0x15,0x9e,0x7b,0x56,0x2e,0xa2,0x6c,0xd9,0xa4,0x3c,0x88,0xd3,0xf9,0x6d,},{0x05,0xaa,0x76,0xf7,0xfe,0x51,0x89,0x23,0x03,0xd7,0x89,0x14,0x71,0x59,0x95,0xe7,0xd7,0x68,0xff,0x77,0x14,0xce,0x27,0x0f,0x17,0x5e,0x56,0xaf,0x17,0xae,0x01,0x8d,0x3f,0xa9,0x39,0xf5,0xf6,0x20,0xde,0x82,0xbc,0xd1,0x54,0x96,0x87,0xb2,0x05,0xc7,0x87,0x12,0x03,0xe6,0x24,0x23,0x8c,0x4e,0x30,0x9f,0xab,0x7f,0x92,0xfb,0xaa,0x05,},"\xc4\x6a\x6d\x61\xaa\x0a\xed\x1c\x1d\x85\x47\xa7\x0b\x89\xb7\x19\x64\x75\xd5\xa4\x87\x08\x81\xb1\xec\xd0\xf0\xcb\x9c\x74\x5f\x8a\x2a\xdc\x80\x24\xe2\xdc\x55\xb5\x3a\xa5\xd3\x83\xa8\x1a\xab\xc1\xa4\x7e\x8d\x07\xd0\x0b\x7f\x0b\x56\xce\xdd\xbf\xb1\xf4\x24\xbb\x5c\x02\x18\x46\x78\xa6\x66"}, -{{0xac,0xe3,0xc4,0x64,0x24,0x82,0x36,0x22,0x97,0x9f,0xc3,0xa8,0x4a,0x7d,0xa6,0x9c,0x1d,0x52,0x7d,0x83,0x12,0xe8,0xfb,0x01,0x83,0x75,0xbd,0x3a,0x96,0xc2,0x9c,0x18,},{0x93,0x7c,0xf3,0x41,0x36,0xd9,0xe1,0xcc,0xe0,0xde,0x11,0xb1,0x2c,0x70,0xcb,0xfb,0x74,0x55,0x44,0x84,0x21,0xe9,0x2c,0x82,0xe7,0xc4,0x09,0x34,0xbf,0xf8,0xc6,0x76,},{0xfe,0xb8,0x89,0x6d,0xd3,0xfe,0x60,0x01,0xff,0xea,0x17,0x1b,0x37,0xb7,0x88,0xa6,0x9f,0x7f,0x85,0x01,0x93,0xa6,0x34,0x06,0xf5,0x63,0x76,0xdd,0x26,0x3d,0x09,0x9a,0xef,0x80,0xec,0xe6,0x7e,0x2c,0x43,0xf4,0x0e,0xca,0x46,0x2c,0x6b,0x71,0xe7,0x94,0x06,0xb1,0x8d,0xb7,0x4a,0xe5,0xd4,0x98,0x44,0xe3,0xb1,0x32,0xbc,0x2a,0x13,0x07,},"\xa9\xf1\x37\xbc\x90\x21\xbf\x10\x5a\xee\x25\xbe\x21\xcd\x9e\xe5\xb3\x54\x7c\xf1\x0c\xc5\xf9\x84\x76\xfb\x58\x8b\xd7\x0e\x2d\x6d\x6b\x08\x34\xe8\x42\xe4\xee\x94\x30\x3c\xf9\x6b\x09\xc1\x71\x53\x81\xb3\x6e\x14\xa4\x91\xb8\x0f\x89\x5e\xa4\x21\xb8\xec\x2b\x1d\x3c\x18\x7e\x02\x93\x5c\x55\x26"}, -{{0x88,0xf6,0x81,0x93,0x4e,0x33,0xc3,0x5c,0x07,0xdc,0x6e,0x5a,0x83,0x29,0x42,0xae,0x3d,0x59,0x90,0x3c,0xcd,0xe2,0xf7,0x6c,0xcb,0x75,0x87,0xce,0xa7,0xec,0x41,0xb6,},{0x6a,0x4e,0x8a,0xa5,0xad,0xb6,0x3d,0x22,0xfd,0x7b,0x14,0xa2,0x6f,0xdb,0x03,0xb7,0xc8,0xaa,0x6c,0xcd,0x5a,0x19,0x6f,0x2c,0x54,0xb0,0x46,0x5a,0xdb,0x50,0x92,0xe1,},{0x45,0xb2,0x7b,0xf1,0xb9,0xea,0xc0,0x6b,0x62,0xb6,0x86,0xf6,0xd5,0x46,0x56,0x3b,0x2d,0xfe,0x5b,0x17,0x5d,0xbe,0xf3,0x2b,0xf7,0x8c,0x35,0xa1,0x6c,0x95,0x8a,0x9d,0x4f,0x26,0xd2,0x91,0xde,0x9b,0xb2,0x06,0x6c,0x0a,0x28,0x61,0x13,0xcc,0x09,0x17,0x2d,0x40,0xa3,0x6d,0x4c,0xbd,0x95,0x17,0x08,0x86,0x02,0x26,0xeb,0x30,0xcd,0x05,},"\x6e\x8b\xac\x1f\x85\x3b\x81\xfe\xf9\x47\x07\xe1\x8c\xc6\x1c\x6f\x0a\x9c\xbc\x2a\x41\xd0\x78\xdc\xc8\x3f\xc0\x22\x9c\x7f\x8d\xbe\x6d\xbd\xd9\x08\x54\xb1\xf1\xae\x2b\x9f\x2b\x12\x0b\x86\xa8\x78\x6b\x4e\x78\xce\x23\xab\x86\xba\xaf\x88\x75\x4a\xf0\xf3\xd8\x88\x81\xda\xe0\xbc\x52\x61\xbf\xd0\x38"}, -{{0x48,0x05,0x0a,0x6e,0x01,0x58,0xf6,0xad,0x25,0x34,0x12,0xe4,0x49,0x7c,0xff,0x62,0xd5,0xee,0x55,0x5e,0xdf,0xfe,0x59,0xe4,0xdc,0x40,0x15,0x22,0x81,0x32,0x95,0xce,},{0x97,0x5e,0x01,0x0a,0xbb,0x9a,0x3e,0x56,0x65,0x91,0x37,0xb0,0x50,0x60,0x57,0xf2,0x83,0x98,0x2f,0x88,0x6c,0xa1,0x72,0xc7,0xbc,0x2c,0x50,0x0e,0xd9,0xbd,0x26,0xc1,},{0x72,0x16,0xab,0x60,0xc3,0x51,0x68,0x18,0x7d,0x0f,0xce,0x47,0x53,0xc8,0x6e,0x80,0x05,0x8d,0x54,0x0b,0x76,0xbf,0x95,0x84,0x3a,0x58,0x98,0x84,0x10,0x60,0xa9,0x9a,0x44,0xde,0x6f,0x43,0x96,0x25,0xa3,0xf6,0x36,0x5f,0x59,0xc3,0x77,0xbf,0x45,0x90,0x9b,0xbf,0xef,0x5c,0x50,0xb2,0x5f,0x31,0x94,0xe5,0xfb,0xd3,0x4e,0xa5,0xe7,0x06,},"\xed\x6e\xec\x29\xfb\x70\x49\xdf\xf7\x07\xf0\xa4\x42\x6e\xbc\x8f\x5b\x35\x0e\x95\x87\x0b\x9d\x61\x98\xc8\x13\x9e\x9c\x3e\x1e\x40\x99\x37\xd1\xa8\x58\xa0\xde\xa4\x82\xa5\xcb\x1a\x85\x4e\xd3\xb5\xa9\x39\x7a\xcb\x63\xbf\xf6\xb6\x40\x39\xef\x2e\xb1\x15\x9e\x99\x85\x83\x10\xbb\xbd\x86\x12\x5c\x3e\x0e"}, -{{0x18,0xd1,0x3d,0x0c,0x00,0xe8,0xe3,0x38,0x6a,0x5c,0xfb,0x30,0xa9,0xe7,0x9f,0xe8,0x8b,0x18,0x61,0xed,0x2d,0x12,0x01,0xeb,0x17,0x00,0x38,0xe1,0x94,0x77,0x04,0x03,},{0xa4,0xaf,0xc8,0x33,0x40,0x18,0x76,0x09,0x0d,0x9b,0x88,0x0c,0x41,0x26,0x7d,0x68,0xcb,0xbe,0xea,0xa3,0x8a,0xfb,0x20,0x88,0x4e,0x27,0x32,0x8f,0x3b,0x7f,0x53,0x5e,},{0x03,0x39,0x88,0x15,0x4c,0x5d,0x79,0xd2,0x51,0x0b,0xe8,0x3e,0x77,0x80,0x15,0xdf,0xe2,0xfb,0x85,0xb8,0x11,0x1f,0x7e,0xc1,0x39,0x91,0x8b,0x54,0x00,0xe3,0xd6,0x56,0xee,0x80,0xa9,0xf5,0xc9,0x07,0x2b,0x5b,0x46,0x7a,0x5c,0xc5,0xa5,0x7c,0xc8,0xad,0x10,0x62,0xb5,0xbf,0xf1,0x08,0x62,0xd9,0xd3,0x69,0xdd,0xe2,0xcc,0x96,0x67,0x01,},"\x91\x0f\x6c\x27\x2d\xd9\x79\x31\xac\x47\x31\x0d\x24\x4c\xad\xb4\x32\x51\x36\x5e\x02\xba\x9f\x6a\x5b\x3c\x32\x26\xbe\x9d\x7d\x3a\x74\xa2\xba\x49\x06\xe8\xe7\x1a\x4b\xf3\xd3\x55\x6e\xbd\xfc\x66\x6c\xd6\xb1\x2f\x20\xc4\xa0\x08\x34\xb8\x8f\xbb\x24\x45\x75\x19\x92\x86\xb0\xb9\x34\x4c\xf3\x34\xaf\xf0\x07"}, -{{0x4a,0xdc,0x8c,0x28,0x64,0x6a,0x93,0xa8,0x17,0x29,0x3a,0x14,0xd2,0x9b,0x48,0xe2,0xc6,0xd7,0x12,0xa6,0x89,0x93,0x54,0x7a,0x5c,0x5e,0x4d,0x14,0x52,0xac,0xbc,0x3a,},{0x7f,0x40,0x47,0x36,0x28,0xf2,0x3f,0xc0,0xdf,0xf0,0x02,0x1a,0xfd,0x48,0x77,0x40,0xd4,0x91,0x6a,0x91,0x22,0xe6,0xc9,0x7d,0x36,0x43,0x3e,0x5e,0xbf,0x04,0xf8,0x8c,},{0x6d,0x3b,0x4e,0x90,0xec,0x40,0x83,0x11,0xf9,0xb1,0x5b,0x92,0x53,0xd3,0xd9,0x5c,0x5d,0x15,0x26,0x20,0xc2,0x60,0xd5,0x63,0x02,0x55,0x5a,0x88,0x04,0xa5,0x10,0x4b,0xa5,0xe8,0xd2,0x9e,0xe1,0x08,0xe7,0x64,0xa6,0x42,0x19,0x29,0x72,0x98,0xab,0x76,0x74,0xbb,0xca,0x78,0x4d,0xee,0x28,0x77,0x3b,0x34,0xe1,0x85,0xa3,0x86,0xc2,0x08,},"\x09\xfb\x55\x01\xf1\x68\x8f\x80\xa0\xab\x9e\x22\xd7\x78\xae\x13\x0a\xca\xf7\x4d\x7f\x51\x85\xb4\xda\x19\x8c\x6b\x9e\xda\xc4\x30\x2e\x2b\x75\x3e\x57\x87\x66\xe1\x7d\x40\x56\xdc\x40\xd9\x5c\xf4\xca\x8b\xcc\x65\x65\x79\x5e\x97\xd6\x8b\xcd\xa7\x9f\xa7\x7c\x49\x33\x97\x71\x63\x56\x16\x4c\xaa\xb5\xd1\x9c\xfd"}, -{{0xf2,0x6e,0x1c,0x84,0x69,0x7a,0x49,0x08,0x15,0x1b,0x44,0x7d,0xcf,0x6c,0x7c,0x7a,0x38,0xb0,0x40,0x81,0xdb,0x9e,0x7c,0x77,0x38,0xe6,0xfe,0xc9,0x00,0xbe,0xd0,0xc1,},{0xa8,0x6e,0x14,0x22,0xc1,0x23,0x5f,0xf8,0xe1,0xaa,0x08,0x34,0x70,0xd5,0xe4,0x22,0x88,0xcb,0x00,0x7a,0xb5,0x0e,0x79,0x5d,0xd0,0xb4,0xff,0x87,0x39,0x49,0x66,0xc4,},{0x44,0xf3,0x34,0x4b,0x95,0x66,0xc9,0xdf,0xd2,0x2d,0x61,0x98,0xe1,0xcb,0xf9,0x5d,0x9e,0x28,0xf2,0x98,0x2f,0xc7,0xf1,0x66,0xab,0x25,0xdd,0xa3,0x0c,0x46,0xf7,0x68,0xc5,0x58,0xe0,0x39,0x4f,0xb9,0xab,0x3e,0x1d,0x4d,0xb4,0xcf,0x48,0x7c,0x17,0x64,0x1a,0x13,0xf3,0xf4,0x89,0x39,0xe0,0xc6,0x48,0x27,0xa7,0x51,0x03,0xc5,0x74,0x06,},"\x54\xed\x47\x60\x6a\x14\x87\xc2\xf9\x00\xce\xfb\x6e\x89\x9d\xba\xf6\xc3\x1c\xc8\x8e\xbe\x35\x58\xb8\x3b\x93\xf6\xd4\x22\xc3\x1e\x88\x8e\x48\xe5\x20\xee\xae\xdd\x7e\x55\x4a\x9c\xd4\x0c\x2c\x51\x9d\x53\x3b\x61\x44\xce\xe4\x84\xc3\x89\xe9\x76\xb1\xe4\x02\x2b\x50\xe7\xdb\xb8\x7e\xad\x7e\x54\x1a\x20\x04\xda\xf7"}, -{{0xcc,0x0c,0x33,0xf3,0xa8,0x6f,0x5a,0x17,0xd3,0x0c,0x18,0x6c,0xe0,0xf3,0xb7,0x40,0xba,0xfa,0x5f,0xe3,0xc7,0x09,0x0f,0x14,0x35,0x41,0xe2,0xb2,0xc1,0xe5,0x34,0xbc,},{0x96,0x7a,0x71,0xc7,0xcf,0x9b,0x82,0xcc,0x78,0xcb,0xe1,0x09,0x10,0x4d,0x8b,0x43,0x8a,0x8d,0x1f,0xd7,0x1d,0x26,0x0d,0x02,0x90,0x46,0xa9,0xa4,0x52,0x68,0x66,0xff,},{0xe2,0x77,0xb3,0xdd,0x65,0x5c,0x33,0xff,0x75,0xfa,0x92,0x0a,0xf1,0xfc,0xc8,0x59,0x40,0x1e,0x6c,0x7a,0x6e,0xf4,0xc6,0xbf,0xbf,0xac,0x50,0x69,0x63,0x8f,0x19,0xca,0x11,0x5b,0xaf,0x13,0xc0,0x9c,0x82,0xaf,0x79,0x3f,0xac,0xb6,0xab,0xd0,0xcd,0x58,0xe8,0x48,0x1b,0x08,0xc1,0xb6,0x8a,0xd7,0xa2,0x66,0x5c,0x4a,0x61,0x4a,0x28,0x06,},"\x19\x44\xe5\xe1\x55\xd7\x5e\x0d\x0b\xe9\x2e\x1b\xe1\x4c\xec\x37\x0a\xd1\x37\x91\xf2\xbf\xd4\x0f\x27\x12\x14\xe9\x4f\xcf\x21\x3c\x71\xbc\x20\xd7\xce\x0c\x75\x84\x42\x1a\xc4\xef\xc4\x51\x88\x3c\xc3\xf4\x95\x6f\x21\xf7\x3a\x42\x16\x72\x04\x38\xbc\x38\xff\x2c\xfd\xf3\x70\x99\x05\xa5\x0a\x9d\x94\xb1\xd9\xe7\x93\x2b"}, -{{0xf0,0xbc,0x97,0x93,0x75,0xa7,0x07,0x30,0x68,0xdb,0xa7,0xf6,0xc0,0x94,0xdb,0x65,0x98,0xb4,0xe4,0x5d,0xf7,0xd5,0x49,0x58,0x3c,0x22,0xfd,0xed,0x80,0x48,0xfa,0x2e,},{0xb4,0x2b,0x6c,0x57,0xa7,0x8f,0x1d,0x90,0x09,0x0a,0x71,0x81,0xab,0x2a,0xe0,0x9f,0x42,0x6c,0xbc,0x2b,0xe9,0x6e,0xb2,0xcf,0x27,0xab,0xc7,0x0d,0x7d,0x32,0xa4,0xb3,},{0x19,0xdb,0xc3,0x02,0x7f,0x9f,0xae,0x70,0x7d,0xeb,0x76,0xf5,0x88,0xf9,0xfd,0x07,0xaa,0x8e,0xae,0x29,0xbd,0x4e,0x1d,0x04,0xc2,0xc9,0x84,0x38,0x82,0x86,0xb3,0xb1,0x22,0x24,0x8a,0x6c,0x03,0xed,0x67,0xec,0xa3,0x5d,0xf4,0xdb,0x3d,0xc1,0xe4,0x23,0x7f,0x26,0x78,0x92,0x51,0x84,0x97,0xd9,0x55,0x2a,0x21,0xde,0x19,0xb5,0x14,0x0f,},"\x27\xab\x30\x49\xb5\xc6\x35\x1f\x6c\xfe\x38\xb1\x3a\x05\x9f\x50\x37\x25\x7e\xe3\xd6\x5d\x60\x79\x65\x68\x56\xed\xc8\x76\xea\x08\x1f\xd8\xa9\x48\x04\x66\xf8\x83\x94\x78\x08\x84\x66\xf5\x1e\xcb\xfa\xf2\xd6\x5d\xef\x25\xf0\xc4\xdd\x8d\x08\x58\x82\x02\x81\x22\x32\xf5\x79\x45\xdf\x8a\x6f\xa1\x61\xed\x8c\x03\x43\xb5\x83"}, -{{0x30,0x22,0x97,0x5f,0x29,0x8c,0x0a,0xd5,0xdd,0xbe,0x90,0x95,0x4f,0x20,0xe6,0x3a,0xe0,0xc0,0xd2,0x70,0x4c,0xf1,0x3c,0x22,0x1f,0x5b,0x37,0x20,0xaf,0x4d,0xba,0x32,},{0xb8,0x45,0xbc,0xe3,0x8e,0x26,0xab,0x02,0x7b,0x82,0x47,0x46,0x3d,0x43,0x7a,0x71,0xbb,0xdd,0xca,0x2a,0x23,0x81,0xd8,0x1f,0xad,0x4c,0x29,0x7d,0xf9,0x14,0x0b,0xd5,},{0xae,0x14,0xa8,0x60,0xfa,0xd0,0x05,0x1b,0x3e,0xb7,0x2b,0x37,0x21,0xa8,0x2f,0x7b,0x95,0x46,0xb2,0x86,0x72,0x61,0xe2,0xb7,0xb6,0x38,0x97,0x9e,0x25,0x61,0xbd,0xeb,0x89,0xb6,0x00,0x76,0x8f,0x82,0x45,0x0a,0x66,0xc8,0xb0,0x48,0x12,0x83,0xfa,0x21,0xcb,0x6c,0x53,0xbd,0xe3,0x50,0xef,0xfb,0x68,0xa7,0xd1,0x11,0x4b,0xfd,0xb2,0x03,},"\x9a\xa1\x9a\x59\x5d\x98\x93\x78\xcd\xc0\x68\x91\x88\x7e\xf5\xf9\xc2\x46\xe5\xf8\x3c\x0b\x65\x87\x10\x67\x3e\x4e\x7d\xb7\x60\xc7\x63\x54\xc4\xf5\xd1\xe9\x0d\xb0\x4a\x23\xb4\xfb\x43\x4c\x69\x38\x45\x93\xd0\x10\xe3\x12\xb1\x1d\x29\x9c\x9f\x97\x48\x2d\xe8\x87\xce\xcf\xe8\x2e\xa7\x23\xbc\xa7\x9a\x1b\xd6\x4d\x03\xef\x19\xee"}, -{{0x0f,0x71,0x0b,0x6c,0x48,0x1f,0x71,0x44,0x95,0x89,0x75,0x33,0x12,0xef,0x64,0x93,0x2b,0x46,0x52,0xeb,0xe0,0xe0,0x75,0x97,0xf7,0xda,0x1c,0x4f,0x3d,0xcf,0xfb,0x80,},{0x69,0x73,0xff,0x29,0x32,0xcc,0xdd,0xfc,0x1d,0x16,0xc4,0xc0,0xda,0x50,0xc8,0xb2,0x9f,0xe6,0x45,0x2d,0x1e,0xe8,0x4d,0x52,0x06,0x4e,0xbf,0x3d,0x62,0x8d,0x40,0x3e,},{0x02,0xa8,0xd2,0x6a,0xee,0x11,0x42,0x0f,0xb4,0xf0,0x9d,0x11,0x63,0xe1,0x4b,0x86,0x7d,0xf7,0xc6,0xf6,0xc8,0xf8,0xdc,0x7a,0x78,0x03,0x46,0x59,0xf0,0x40,0x1c,0xad,0x0a,0xa9,0x03,0x97,0xef,0xdd,0x07,0x04,0xb7,0x98,0xdb,0x19,0x36,0x50,0x30,0x26,0xe2,0xa1,0xad,0xc2,0x97,0xe2,0x79,0x74,0xd4,0xbe,0x31,0x2a,0x37,0x53,0xf8,0x04,},"\x85\xd8\x57\x44\xad\x55\xe9\xef\x9a\x65\xca\x91\xe8\x5c\x8a\x4f\x80\xe4\xc5\x8f\x8e\x4e\x93\x54\xe8\x33\x98\x60\x98\xb7\xd9\xfe\x9f\xdc\x0d\xed\xb0\xd7\x5d\x25\x39\xfb\xa0\x00\x34\xfc\x0c\x2e\x84\x34\x4d\x1e\xda\xa0\x9d\x4f\x63\xd5\x54\x6d\x67\x80\x3d\xd6\xb5\x4d\xdc\xc0\xb1\xd3\xf2\x58\x2d\xd7\x52\x89\xe3\x1d\xe4\x2e\x69"}, -{{0x7a,0x05,0xf1,0x21,0xf6,0x01,0x12,0xdd,0x16,0xfe,0xe8,0xc9,0x1b,0xc2,0xa1,0x14,0x79,0xf4,0xb6,0x7e,0xe3,0x34,0x56,0x04,0x2c,0x8d,0xe1,0x67,0xfc,0x58,0x80,0x17,},{0xb3,0xb0,0x5b,0xe9,0x89,0xce,0xa7,0x19,0x75,0x05,0xd4,0xb5,0x43,0x35,0xe5,0xe1,0xd7,0x7a,0x4b,0x52,0xba,0x72,0x82,0x60,0x4b,0xbc,0x1c,0xf6,0xc4,0xe8,0x7a,0x6c,},{0xd3,0x0c,0xe8,0xa3,0x22,0xb4,0x50,0xa2,0xfb,0x1a,0xfd,0x32,0x9c,0xec,0x85,0x59,0xcc,0xf1,0x12,0xbd,0x83,0x96,0x5f,0x9e,0xc4,0x73,0x62,0x70,0xa0,0x91,0x4e,0x06,0x11,0x96,0xbf,0x52,0x09,0x77,0x8c,0x9f,0x8c,0xcf,0x39,0xc4,0x66,0x8b,0xbf,0x0e,0x13,0x63,0xf8,0x1a,0xfe,0x45,0xdd,0x74,0xe8,0x0d,0x58,0x75,0xdd,0xbf,0x6f,0x01,},"\xd9\xc5\x9e\x8c\xc4\xed\xe5\x37\xbe\x21\x22\xab\x49\x2a\x5b\x91\x5a\x9b\x0a\x11\x4b\x2a\xde\x35\x6f\xc0\x45\x7e\xf9\x87\x22\xd5\xf5\x67\xb8\x62\x11\xe2\x83\x69\xd1\x41\x68\xec\x4a\x3c\x80\x40\x76\xe1\x54\xad\xc7\x0a\x66\x8c\xf6\x4a\x20\xd1\x3c\xf1\x90\xd1\x15\xcd\x68\x8d\x03\x6e\x46\x93\x82\x51\xdf\x49\x64\xdc\x35\x17\xb1\x0c"}, -{{0xbf,0x38,0x1f,0x8d,0xfb,0x5d,0x0c,0x6d,0x64,0xe4,0x16,0xac,0x23,0xe0,0xd0,0xfc,0xb8,0x6e,0xbb,0x89,0x9b,0x1d,0x14,0x6a,0xbd,0x91,0x1b,0x92,0xa7,0x80,0x8e,0xb6,},{0x86,0x3f,0xad,0x8d,0x1f,0x1b,0xc6,0x30,0xa1,0x5f,0x6f,0xe8,0xec,0xef,0xe6,0xb4,0x49,0x7b,0x60,0xb2,0x1a,0xe8,0x83,0x0d,0xa4,0x67,0x42,0x04,0x5f,0xef,0x15,0x6f,},{0x99,0xb7,0x53,0x78,0x73,0x8f,0xca,0xc8,0x06,0x76,0x69,0xe8,0x50,0x9b,0x5d,0x26,0x07,0xe1,0xef,0x76,0xaf,0x90,0x04,0xe1,0x3f,0xe5,0xd3,0x93,0x2d,0xf6,0x0b,0x16,0x82,0x16,0xf5,0x85,0x65,0x34,0x0f,0xa4,0xd6,0x38,0x05,0x5a,0x89,0x04,0x4e,0xe7,0xd4,0x5e,0x2b,0xd0,0x82,0xa5,0x33,0x82,0x28,0x9a,0x34,0x70,0x06,0x48,0x98,0x0e,},"\x86\x54\xf2\xf5\xc6\xdc\xd2\xcf\xcb\xb6\xed\x8d\x2b\xc5\xfb\x5f\xec\x53\xe3\xef\xfb\x0d\xe6\x5a\xac\x50\x7f\xa5\x6c\x89\x77\x32\x39\x5a\xa0\x99\x46\xd3\xb6\x58\x6a\x92\xed\xd6\xdc\x99\x31\x5e\x1b\xa7\x4c\x6a\x02\x47\xc4\xba\x77\x60\xb9\x48\xeb\x3c\x09\x32\xd9\xfe\x1f\x0e\x9f\xea\x6e\xb6\x1a\x54\x8a\x9a\xb4\x8f\xfd\xf1\x54\x73\x29"}, -{{0x36,0x98,0x32,0x41,0xa0,0xa8,0xe6,0x0c,0xe0,0x2a,0x61,0xb3,0xfa,0xfa,0xb1,0x5a,0x73,0x13,0xa5,0xa2,0x70,0xd0,0x15,0xb9,0xc9,0xec,0x07,0x0d,0xc4,0x2d,0xee,0xda,},{0x66,0x47,0x98,0x4d,0x42,0xb9,0xa5,0xb3,0xb1,0xaf,0xa3,0xb7,0xf8,0xf4,0x9d,0x4c,0x2b,0x05,0xe3,0x89,0x84,0xe9,0x9c,0xea,0x8f,0xd6,0x82,0x35,0xd2,0xae,0x46,0x27,},{0xee,0x37,0xdf,0x8a,0xf4,0x22,0xf9,0x1f,0x85,0xdf,0xe4,0x3e,0xfe,0x79,0xf6,0x23,0x78,0x06,0x8c,0xcd,0xba,0xf3,0x91,0x6e,0xec,0xbc,0x3a,0xdf,0xed,0x05,0x08,0xbd,0xeb,0xaf,0x5c,0xe0,0x6b,0x3b,0xc2,0x79,0xf7,0x80,0x87,0xf0,0xdb,0x8d,0xb3,0xc6,0x82,0x3e,0xdf,0xb3,0x2c,0x12,0x21,0x78,0x30,0xbe,0x72,0x3d,0x88,0x72,0xb3,0x0c,},"\xce\xbb\x9e\x40\x44\x51\x81\x82\x53\xc0\x39\x2a\x45\x54\xee\x73\x23\xc5\xd5\xb8\xb2\x26\x77\x57\x00\xb8\x06\xed\x5b\x91\x33\x79\x16\xea\x7e\xcb\xc3\xd4\x10\x3f\xc6\x5e\x53\x72\xae\x7e\x5f\x9b\xa2\xd8\xf5\xae\xe2\x4c\xcf\x6e\x63\x1a\xe2\x0c\x4a\xf9\xb5\xf7\x28\xcd\xf8\x9e\x81\x89\xde\xf1\xa5\xb3\xd3\x53\x47\xaa\x20\x35\x25\xea\x1d\x2e"}, -{{0xd0,0x68,0x99,0xf9,0x3a,0x40,0x8d,0xac,0xb4,0x1c,0x96,0x97,0x18,0x34,0x6f,0x1e,0x28,0x9b,0xb5,0xea,0x65,0xe2,0x83,0xff,0x79,0xc7,0x05,0xa0,0x74,0x51,0x7c,0x35,},{0x46,0xbf,0x2a,0x08,0xa0,0x76,0xc4,0x7d,0x7f,0x11,0xb7,0x33,0xf8,0x14,0x1c,0x35,0x53,0x63,0xed,0x85,0xd7,0xde,0xf2,0x6b,0xa6,0xa0,0xce,0x15,0xac,0x5f,0x2b,0xe8,},{0x6f,0x89,0xde,0x92,0xa6,0x6b,0xc5,0xf4,0x14,0x43,0x39,0x12,0x49,0x50,0xbd,0xf5,0x88,0x14,0x4c,0xb3,0x72,0xf6,0x73,0x62,0x45,0x35,0x1c,0x94,0x76,0xbe,0xcc,0x59,0xa2,0x58,0xf9,0xa9,0x33,0xff,0xff,0x2b,0xef,0x4b,0x46,0xcd,0x10,0x57,0x39,0x52,0x25,0x79,0x9f,0xd0,0x9d,0xed,0xe6,0x82,0x3d,0xb0,0xe3,0x25,0xdb,0xc8,0x14,0x0d,},"\x08\x64\xc3\x9a\xc4\xfd\xa8\xeb\x90\x48\x59\x7b\xd4\x0b\xe0\x40\x10\x21\xfd\x2d\xd3\xa3\x39\x0a\x8f\xac\xce\x98\x4b\x26\x0a\x13\xfa\x2c\x7c\xfc\x00\xd1\x92\xfa\xdf\x13\x4a\x0a\xd5\xa1\x81\xee\x89\xef\xf0\xc7\x95\xea\xa0\xfb\xfe\x2f\x3b\x26\x11\x5d\x07\x16\x8d\xb4\x2e\xd2\x1a\x51\x30\x3b\x19\x58\xe4\xa4\x2d\xc0\x65\xb2\x2c\xe4\x8f\x17\xa6"}, -{{0xee,0xbc,0xa7,0x96,0x69,0x70,0xee,0x9f,0x2c,0xc4,0xd7,0x4c,0x6f,0x1d,0x8e,0x0e,0xbf,0xf7,0xc4,0x5a,0xeb,0xad,0x34,0x9f,0xb9,0xf8,0x6d,0xf6,0x28,0xdf,0xff,0x0e,},{0x89,0x10,0x1e,0x03,0x09,0xf7,0x67,0xe6,0x4a,0xe9,0xc9,0x8c,0x4a,0x5d,0x8d,0x23,0x28,0xfb,0x3e,0xf2,0x62,0xd0,0x82,0xf4,0x9b,0x64,0xca,0x20,0x9e,0x19,0x90,0xf6,},{0x7d,0x44,0x7e,0xe5,0x32,0x8c,0x9f,0xe7,0xf1,0x19,0x36,0xcc,0x42,0x99,0x87,0x54,0xa5,0x6c,0xd1,0xd2,0xa6,0x95,0x1a,0xf4,0xfe,0xe7,0xc4,0xa8,0xeb,0x31,0x9d,0x49,0x23,0x70,0x7c,0x79,0x3c,0x55,0xd7,0x90,0x67,0xf8,0x22,0xd5,0xb1,0x6b,0xb5,0x77,0x6e,0x38,0xdf,0xfa,0xbc,0x67,0x23,0x7a,0x91,0x6a,0x81,0xa6,0x33,0x39,0xb0,0x03,},"\x0f\xac\x79\x0a\xdb\x9f\x59\xe5\xcb\x0d\xdc\xb2\xb6\x67\x17\x2f\x2a\x21\x03\x4d\x93\xbc\xad\xdf\x18\x86\x06\xfa\x9e\x77\x6d\xb3\x3a\x8f\xcc\x6b\xd7\xf5\x56\x78\x83\xfc\x0d\xe3\x51\xaa\x9a\xfa\xa3\x6d\x20\x75\xb1\xba\x85\x3b\xad\xa8\x49\xb8\x66\x1d\x5c\x81\x54\xe7\xb0\xaf\xea\x65\x6d\xd1\x5e\x01\xa9\xc5\xba\x21\x58\x9b\x02\xf8\xfc\x54\x81\xc2"}, -{{0x38,0x20,0xb6,0xb1,0x59,0x39,0xd0,0xaf,0xe1,0x8c,0x9c,0xb3,0xd9,0xa2,0xa0,0x8f,0x16,0x7d,0xd4,0x58,0xeb,0x6c,0x7e,0x3f,0x15,0x58,0xb0,0xc6,0xdb,0x4c,0x68,0x90,},{0x80,0xb8,0x5c,0x65,0x59,0xfe,0xa8,0xb4,0x00,0xe1,0x99,0x9c,0xc5,0xbf,0xed,0x50,0x7a,0xd7,0xfc,0x29,0x4c,0xd9,0xba,0x0c,0xe2,0xdd,0x25,0x84,0xa9,0x10,0x89,0xb0,},{0x82,0x3e,0xe2,0xc0,0xc8,0xd8,0x7f,0xaa,0x0e,0xc0,0x14,0x1e,0x9c,0xe0,0x8b,0x51,0xe5,0x7c,0x83,0x97,0x92,0xd1,0xfb,0xd9,0x7a,0x96,0x72,0x07,0xfd,0x41,0x58,0x49,0xeb,0xfb,0x5d,0xad,0xb5,0xa1,0xdc,0x2c,0x0a,0x8b,0x7f,0xc6,0x3f,0xc3,0x54,0x85,0x7b,0x8c,0x90,0xc4,0x47,0x20,0xe1,0x3f,0x45,0xcd,0x01,0xe7,0xaa,0x23,0x14,0x0c,},"\x3e\x5a\xd9\x2d\x44\xb4\x0e\x86\x14\xd8\x08\x7c\x9c\x74\x3d\xe0\xc0\x86\x1a\x07\xf1\xf5\x14\x6d\x71\xca\xc2\xf3\x74\x00\x24\xe8\x41\xcc\x2d\x46\x02\x7c\xf5\xd2\x61\xd3\xee\x7c\x18\x75\xb3\x95\x51\x01\x7b\x5f\xb1\x46\x81\x14\xfc\x3e\x09\x8a\x89\x9c\xdb\xd5\x58\xb3\x9f\x09\x8e\x15\x6b\x6e\x98\x01\xeb\xcd\xd6\x5f\xed\x56\xdb\xfc\xaf\x2c\x8c\x78\x7b"}, -{{0x0d,0x20,0xfa,0x4a,0x37,0xff,0x30,0xc4,0xdc,0xc3,0xe4,0x4e,0xa7,0xac,0x50,0x11,0x37,0xe5,0x80,0x7e,0x97,0x81,0x33,0x0a,0xc3,0x10,0x98,0x2c,0xc3,0xd3,0x9d,0xbd,},{0x67,0xbb,0x0a,0x01,0xbc,0x86,0x17,0xb4,0x91,0xef,0xf1,0xa3,0x26,0xc1,0xc7,0x0f,0x7d,0x0c,0x5b,0x95,0xa5,0xad,0x48,0x24,0x1a,0xed,0xce,0x1c,0x6f,0x08,0x83,0xcf,},{0xde,0xab,0x12,0xed,0x82,0xba,0x94,0xb4,0x69,0xca,0x98,0xb6,0x6f,0xa2,0x04,0x44,0xb4,0xb7,0x88,0x1c,0x4f,0x0f,0x85,0x34,0x09,0xc9,0xa1,0x50,0x4a,0x5b,0x2b,0x6d,0x78,0x60,0xf2,0x6a,0xda,0x6b,0xf7,0x34,0x59,0xb9,0xcd,0xb5,0x73,0xc8,0x01,0x71,0x21,0x33,0x8e,0xfa,0x60,0xf4,0x14,0x80,0x86,0xd7,0xa3,0xa8,0xed,0x59,0xbb,0x07,},"\x35\xe0\xf4\xb4\xa5\x17\xf9\xc7\xaa\x45\x14\xf0\x3e\x6d\x65\xf1\x9b\x27\xc6\x2c\xc0\x69\xf6\xbf\x07\xdd\x63\x78\xbd\x6a\xfe\x2b\x76\x65\x60\x00\x6c\xbd\x57\x30\xa0\x09\x19\xed\x11\x19\x1f\xb0\xc8\xda\xc5\x6e\x15\x3f\xc1\xce\xa4\xbd\xce\x50\x46\xcc\xcb\x71\x77\x59\xa4\x08\x3e\x1c\x16\xf7\x40\x76\x32\x64\xcc\x80\x4d\xe0\xd0\xe1\xa4\xb5\xa2\x30\x67\xaf"}, -{{0xbe,0xe1,0x61,0x88,0x1d,0x81,0x9b,0x37,0x0d,0x24,0x0d,0x50,0x9b,0xa4,0x6b,0x06,0xfb,0x82,0x8e,0x20,0x31,0x0d,0x9f,0x6b,0x30,0x97,0x80,0x70,0x3e,0x98,0x92,0x7b,},{0x10,0x85,0x43,0x80,0xde,0x89,0x16,0x2b,0xfb,0x9f,0x78,0x35,0xa2,0x71,0x6a,0x3a,0x6e,0x02,0x65,0x67,0x1b,0x25,0x0b,0x38,0x9d,0x01,0xc3,0xbc,0xc0,0x37,0x36,0xb8,},{0xb0,0x7d,0x07,0x2e,0xb3,0x83,0x1f,0xae,0x8a,0x06,0xef,0xfa,0x92,0x01,0x79,0x74,0x96,0xdc,0xe1,0x26,0xb8,0xe1,0x1f,0xef,0x2f,0xa0,0x7f,0x66,0x4d,0xc5,0xcf,0x3d,0x4b,0xf9,0xc3,0x8a,0x8b,0x3c,0x09,0xfb,0x5f,0x14,0xfa,0x2d,0xeb,0x21,0x9e,0x7d,0x85,0x2f,0xdd,0x27,0xc7,0xba,0x32,0xd3,0x09,0x94,0x2f,0x27,0x46,0xdf,0xe4,0x04,},"\x5a\x6f\xe5\x99\xb6\xb0\x9b\x05\xc0\xba\x6a\x62\x2d\xf3\xa9\x2b\x3d\x37\x6d\x24\xd0\x4e\xa8\x5e\xbe\x76\x7b\xc2\xec\x4d\x14\xe8\x3e\x69\x37\xdc\x0b\x91\x4b\x48\x09\xfd\xb6\x07\x90\x68\x41\xa6\xfd\x1d\xcd\xf6\x1a\xae\xa8\xf9\xbb\x81\xb2\xcc\xaa\x32\xdf\x41\x29\x89\xae\x53\x64\x66\x80\xa7\x1a\x21\x1c\x84\x40\xea\xb0\xf1\xae\xc5\xe4\xfc\x00\xe6\xa2\xc9\x6d"}, -{{0x70,0x15,0x0e,0x95,0x16,0x16,0x4a,0x3d,0x7b,0x7e,0x8b,0x6f,0x25,0x5b,0x65,0xca,0xc9,0xf0,0x74,0x59,0xb3,0x2d,0x11,0xbb,0x94,0xb3,0xd2,0x77,0x20,0x8a,0xbc,0x99,},{0x23,0x28,0xbe,0xc8,0xe4,0x03,0x51,0x04,0x78,0x82,0xe8,0xb4,0x3b,0xc1,0xab,0x08,0x53,0x86,0xfa,0x47,0x98,0x7e,0x46,0xea,0x87,0x60,0x88,0x14,0xc5,0xda,0x71,0x3c,},{0xed,0xa3,0xf5,0x03,0x3e,0xa7,0x95,0x3a,0x0d,0x58,0x3c,0x64,0x57,0x52,0x2e,0x84,0xad,0x78,0x44,0x53,0x04,0xd4,0x8e,0x57,0x7d,0x4d,0x69,0xe8,0x64,0x1f,0xeb,0xe1,0x52,0x48,0xd8,0xd9,0x0c,0xe0,0x94,0x4a,0x8f,0x80,0x1d,0x39,0x09,0x9b,0xc7,0x74,0x94,0xba,0xc4,0xce,0x2a,0x20,0xb3,0x83,0x69,0xc6,0xad,0xfb,0x71,0xe0,0x3d,0x0f,},"\x77\xbe\x8e\xce\xaa\xb4\x31\xa1\x3c\x2a\x28\xd0\xd1\x55\x64\x89\xd8\xc3\x92\xfd\x7a\xe4\x11\x57\xf7\xca\xf0\x82\xcb\x54\xe4\x5f\x08\x62\x6b\xe0\x07\x6b\xe8\x44\xd3\x8f\xde\x90\x1a\x5e\xab\x0e\x88\x32\xd6\x9d\xac\x22\xfb\x85\x07\xfb\x8e\xc4\xfa\xf7\xc8\x8f\xd2\x6d\xa3\x08\x46\x1a\xfe\x38\x59\x87\x97\x2b\x5e\x76\x0a\x34\xa5\xe1\x8b\x9a\x82\xb4\xaa\xa5\x29\xb7"}, -{{0x3f,0x87,0xfc,0xfd,0xb4,0x21,0x42,0x2a,0x9c,0x5f,0xb9,0x82,0x68,0x31,0x3c,0x15,0x12,0x8c,0x78,0x84,0x4e,0xf9,0xeb,0x3b,0x37,0x13,0xfa,0x77,0xb6,0x71,0x89,0x03,},{0x53,0x3e,0xc5,0x92,0x28,0x37,0x4b,0xd0,0x3a,0x46,0x99,0xe3,0xa8,0x89,0x6b,0x86,0x18,0x2f,0xcf,0x8f,0xc3,0x08,0x5f,0xdb,0x8f,0x5c,0x46,0x71,0x52,0x4d,0x6f,0xe0,},{0xf6,0x51,0x9d,0x7e,0xdb,0x61,0x34,0x11,0x19,0x74,0x03,0x3f,0x03,0xb8,0xd8,0x9e,0x9c,0x76,0xca,0xec,0x89,0x65,0xa8,0xe1,0x7c,0xd4,0x5f,0xff,0x19,0xde,0x26,0x15,0xd7,0x3e,0xcc,0xdb,0x4a,0x66,0x64,0xa8,0xf0,0xe2,0x3a,0xdf,0x98,0x98,0x8e,0x96,0x25,0x1b,0xf2,0x6e,0xb7,0xa4,0xcc,0xaa,0xc1,0x07,0x9f,0x0a,0x77,0x2f,0x9b,0x05,},"\xc0\x0f\xed\x2d\x68\x94\x68\xbc\xba\xcc\xcd\x44\x6e\x8d\x8f\x29\x9e\x2a\x86\x92\x5e\x62\xe5\x97\x09\xaf\xaf\x48\x57\x46\x9f\xf1\xe0\x06\xd0\x0f\xa3\xe1\x8a\x36\x15\xf8\xf0\x6b\x6e\xbd\xff\x78\x5d\xde\x58\x85\x1d\x2c\x23\x90\x38\xa0\xc3\x44\xdc\xe9\x85\xbd\x1f\xc8\xde\xb4\x77\x9a\xe5\xf8\x93\x2e\x2f\x9e\xd5\x99\x0b\x64\x72\xdb\xe4\xe6\xfe\xf6\x91\x76\x57\xe0\xb5"}, -{{0x44,0xce,0xef,0x04,0x4f,0xf9,0x98,0xd4,0xab,0xea,0xaf,0x37,0x4e,0xb4,0x1d,0x08,0x67,0x18,0xb6,0x30,0x97,0xb1,0xe3,0x5f,0x89,0x63,0x4c,0x14,0x89,0x71,0x32,0xea,},{0xe8,0x3c,0x86,0x67,0x7d,0x03,0xed,0x3a,0x5e,0x8c,0x95,0xf4,0x1f,0x0b,0x32,0x5f,0xf4,0x33,0x37,0x02,0xf2,0xff,0x69,0x36,0xf5,0x7f,0xf3,0x0a,0xa3,0x14,0x85,0xc7,},{0x55,0x45,0x52,0xd6,0xb7,0x90,0xd4,0x21,0xd0,0x6b,0x0a,0x67,0xf8,0xe0,0x02,0xad,0x7a,0x1e,0xd0,0x1c,0x06,0xcf,0x00,0xcb,0xea,0xec,0x2a,0x26,0x8b,0xda,0x29,0xf1,0x18,0x3f,0x0c,0xea,0xfc,0x62,0x5f,0xa5,0xfd,0xb8,0x47,0xdc,0x86,0xfa,0xe1,0xa2,0x04,0x06,0xe4,0x59,0xd4,0xa0,0x17,0x7c,0xb5,0x15,0x22,0x0a,0x56,0x8e,0x08,0x00,},"\x8d\x3e\x2d\xec\x46\x44\xc7\xb5\x16\x33\xb1\x3e\x63\x75\xca\x42\xff\x91\x38\x46\x5f\x43\xd7\x80\x0c\x73\x13\x19\x9f\x67\xc9\xcf\x1b\x52\x0b\x18\x20\xbd\x63\x0e\xcf\x1c\x99\x2e\x27\x67\xb3\x8e\xb5\xbb\xc4\x41\xa4\xab\x8d\x31\x7d\xb4\x41\xdb\x35\xa0\xfe\x3a\xbe\x7a\x9e\x45\x41\x88\x1c\x2d\x7b\x1a\x26\x12\x30\x69\x59\x81\x5d\x1d\xa4\x12\x67\xd9\x64\x9d\xd4\x49\x4a\xce"}, -{{0x98,0xef,0x2a,0x44,0xd4,0xc8,0x47,0x6d,0xff,0x05,0xaa,0x78,0xdc,0xf9,0xc6,0xdc,0x08,0x6c,0xb2,0xf6,0x22,0xa0,0x67,0x45,0xd6,0x0c,0xbf,0x22,0x3f,0xaa,0xba,0x66,},{0x42,0xfd,0xb1,0xda,0xa3,0x9f,0x01,0x59,0x11,0x9b,0xee,0xc1,0xbe,0xdf,0x6f,0x03,0x94,0xb2,0x6a,0x2a,0x29,0xbd,0x1f,0xde,0x08,0x1e,0xcc,0xda,0xde,0xcc,0x22,0x6a,},{0xab,0x5e,0x87,0x24,0xa3,0xe6,0xff,0x76,0x05,0x8c,0xfb,0x21,0x4d,0x57,0x4e,0x04,0xd0,0x55,0x74,0xec,0xdd,0x4f,0xfe,0x8c,0x07,0xc7,0xaf,0x39,0x6e,0x88,0x26,0x87,0xc5,0xd7,0x9e,0xf1,0xe6,0x2f,0xbb,0x4c,0x5f,0x1b,0xd0,0x6b,0x9b,0xd8,0x97,0x82,0x6e,0xdd,0xe0,0xd1,0x11,0xd9,0x18,0xe8,0xef,0x96,0x1f,0xf2,0xa0,0x0d,0x77,0x00,},"\xc8\xb5\xfc\xfc\x3c\x18\xc7\xd9\x59\x57\xb6\x68\xe9\x1c\x73\x1d\x50\xc7\xfc\xea\x4f\x95\x75\xbb\xf7\x84\x62\x58\x70\xe2\x38\xdf\x54\x6e\x2c\xb1\xa1\x9d\x28\x08\xdd\x5b\x23\x0d\x38\x71\xfd\xec\x16\x10\x0e\xe1\xfb\xf9\xb7\x22\xfa\x37\x44\xa7\x50\xa3\xb3\x96\xb0\x5f\x9c\x21\xb8\xc0\xf6\x1e\xad\x57\xa7\x8c\x5e\xcf\x72\xb5\x79\xcf\xe8\x8a\x3f\x40\x4c\x8a\xcf\x52\x4f\x9a\xb9"}, -{{0x93,0xa8,0xc7,0x92,0xa2,0x39,0xc9,0x31,0x91,0x7c,0x11,0x48,0x24,0xa0,0x17,0x4f,0x8b,0xc4,0xeb,0xbf,0x98,0xaf,0x8c,0x7e,0x32,0x1e,0x0f,0x5b,0xea,0x40,0x15,0xec,},{0x9b,0x2e,0xaa,0x8a,0x9c,0x2c,0x25,0xff,0x4f,0x6e,0x13,0xbb,0x12,0xba,0xe5,0xd0,0x6f,0xda,0x0e,0xb1,0x10,0x5f,0xaf,0xae,0x58,0x80,0xff,0x16,0x87,0x40,0xbb,0x74,},{0xcf,0xe3,0x2c,0x44,0x35,0xd9,0x11,0xd7,0x72,0xdc,0x07,0x27,0xe7,0x8d,0x68,0x9d,0x01,0x64,0xc5,0x06,0x95,0x97,0xcb,0x44,0x1b,0x22,0xc1,0xd2,0x62,0x36,0x47,0x9f,0x1a,0xfd,0x70,0x89,0x12,0x1b,0x9a,0xb4,0xf6,0x1b,0xbb,0x1f,0xae,0x1a,0xb4,0x2f,0x76,0x35,0xa9,0x2a,0x53,0x78,0x4d,0x71,0x70,0x91,0x6b,0x70,0x3a,0xa5,0xcc,0x09,},"\x90\x1b\xf4\xe0\x41\xca\xf1\x6e\x04\xf2\xff\xde\x8d\x6f\xe9\x7e\x93\xd0\x90\x0f\x6b\xc0\xfc\x09\xa9\xa0\x17\x9d\x13\x7b\x4b\x77\x88\xe5\x7e\xb9\x27\x66\xa9\xc6\x34\xf3\x5a\xdb\x5c\x29\x88\xaf\x1e\x86\x20\x8f\x46\x19\x98\xf5\x9c\xfe\xc9\x92\x04\xb4\x84\xfb\xca\xd3\x95\x1e\x7e\xe4\x40\x55\x23\x70\x5d\x97\x39\xb4\x43\x07\xdb\x03\xf7\x13\xfd\xa7\x8d\xb4\x21\xef\x31\x21\xb3\xba"}, -{{0x70,0x01,0xfa,0x0c,0x44,0x04,0xc2,0x8a,0xa5,0xb5,0xfc,0xff,0x30,0xa9,0x61,0xf2,0x1a,0x22,0xf5,0xb8,0x5a,0x9e,0x38,0x2e,0x07,0xae,0xa8,0xa8,0x92,0x4d,0x0e,0xc1,},{0xda,0xeb,0xb6,0x3c,0x4d,0x8f,0x40,0xce,0xba,0x8e,0xc3,0x5e,0x3d,0xd9,0x46,0xa6,0xb7,0x5b,0xc7,0x4f,0xcb,0x29,0xad,0xe7,0xb5,0x5e,0xee,0x3c,0xc3,0xae,0xa5,0xca,},{0x64,0xea,0xc9,0xce,0x87,0x46,0x06,0x18,0x63,0x6b,0x41,0xfd,0x2d,0xec,0xc1,0x67,0x3b,0xfc,0x48,0xc5,0xf4,0x79,0xdf,0xac,0xb5,0x1e,0x86,0x68,0x64,0x07,0x37,0x4b,0x1d,0x10,0xbf,0x65,0xd6,0xd7,0x47,0x42,0x14,0xd7,0x77,0x0c,0x9e,0x5c,0x7f,0x80,0x6c,0x80,0xd5,0x3d,0x48,0xb7,0x20,0x87,0x0e,0x5e,0x78,0xf3,0x2e,0x3a,0x7e,0x05,},"\x44\xf4\x8c\xfb\x02\xf0\x87\x77\xa5\x78\x73\x85\x5f\x96\xbe\x4c\x02\x91\x32\x3f\x27\x39\xb2\x75\xd9\x07\x57\xa1\x54\x72\xe5\x75\x04\x36\xe0\x10\x74\x08\xfe\x30\x26\xc0\x06\x25\x68\x99\x83\xf9\x90\xeb\xa9\xbe\xcb\xfc\xe4\x03\xcc\xd5\x63\x56\xad\x27\x41\xfd\x21\x44\x5d\xfb\x23\xd7\x61\x12\xe5\x78\xb3\x39\x5c\xf9\xd9\x60\x95\x5f\x1d\xa8\xf3\x99\xca\x28\x6f\x21\x39\x0e\x25\xa5\x9a"}, -{{0x3a,0xdc,0xe3,0xa3,0xd3,0xfb,0xc9,0x77,0xdd,0x4b,0x30,0x0a,0x74,0x74,0x9f,0x13,0xa3,0xb0,0x4a,0x5d,0x73,0xa2,0xcd,0x75,0xa9,0x94,0xe3,0x19,0x5e,0xfe,0xbd,0xac,},{0x6f,0xf1,0x9b,0x1f,0x18,0xd6,0x48,0x51,0xd5,0xc7,0x48,0x45,0xc6,0x40,0x7f,0x0b,0xf5,0x96,0xa5,0x2e,0x38,0x5e,0x02,0x01,0x27,0xe8,0x3e,0x54,0xcf,0xf5,0xac,0x19,},{0x7d,0xda,0x89,0xf8,0x5b,0x40,0x53,0x9f,0x5a,0xd8,0xc6,0xde,0x49,0x53,0xf7,0x09,0x4a,0x71,0x5b,0x63,0xdd,0xa3,0x0e,0xc7,0xcf,0x65,0xa7,0x85,0xce,0xae,0x5f,0xc6,0x88,0x70,0x7e,0xe0,0x0b,0xe6,0x82,0xce,0xcb,0xe7,0xee,0x37,0xd8,0xfc,0x39,0xee,0x6d,0x83,0xc6,0x44,0x09,0x68,0x17,0x08,0xa0,0x89,0x8a,0x18,0x3b,0x28,0x8a,0x06,},"\xfe\x6c\x1a\x31\x06\x8e\x33\x2d\x12\xaa\xb3\x7d\x99\x40\x65\x68\xde\xaa\x36\xbd\xb2\x77\xce\xe5\x53\x04\x63\x3b\xd0\xa2\x67\xa8\x50\xe2\x03\xbb\x3f\xab\xe5\x11\x0b\xcc\x1c\xa4\x31\x66\x98\xab\x1c\xf0\x0f\x0b\x0f\x1d\x97\xef\x21\x80\x88\x7f\x0e\xc0\x99\x1e\x8c\x11\x11\xf0\xc0\xe1\xd2\xb7\x12\x43\x3a\xd2\xb3\x07\x1b\xd6\x6e\x1d\x81\xf7\xfa\x47\xbb\x4b\xb3\x1a\xc0\xf0\x59\xbb\x3c\xb8"}, -{{0x14,0x80,0x3c,0x1f,0x23,0xa4,0x7f,0xcd,0xd3,0x5e,0x5d,0x14,0x6e,0x20,0xca,0x63,0x0c,0xd7,0x12,0xc0,0x47,0xd5,0x33,0x0b,0x65,0x2e,0x31,0x85,0x7a,0xcb,0xc9,0xe8,},{0x36,0xf2,0xd5,0xbd,0x6d,0x83,0x24,0xfa,0x6e,0x9d,0xb7,0xf7,0xd8,0x54,0xeb,0xe4,0x8c,0x0e,0x62,0x99,0x99,0x81,0x22,0xe9,0xd4,0x4b,0x8a,0xdb,0xef,0x54,0xf0,0x93,},{0x07,0xa7,0xde,0x6c,0xe9,0x76,0x64,0xb3,0xea,0x09,0x28,0xe1,0x38,0x5c,0x33,0x09,0xbe,0x08,0xa4,0x7c,0xbf,0x4d,0xaa,0x91,0x86,0xa1,0xb9,0x48,0xc8,0x6f,0xbb,0xa3,0x9c,0x4e,0xfc,0xfc,0xb7,0xa0,0xa3,0x86,0x6b,0xc9,0x4c,0x67,0x88,0xff,0xe6,0xbe,0x0d,0x49,0x72,0xe5,0x6d,0x0c,0x32,0x92,0xd1,0xcc,0x6e,0x25,0x44,0x7b,0x99,0x04,},"\x55\x59\x83\x67\x9d\x02\x6e\x53\x54\xb4\xcc\x05\x5a\xe1\xbc\x14\x65\x3c\x72\x81\xec\x72\x23\x72\xf3\xfe\xb7\x78\xe8\x41\xda\x82\x1b\x3d\x0b\x8e\xe7\xa9\xa9\x12\x9e\xa0\x68\x24\xbe\x83\x79\xfb\xbd\xcb\x07\x48\xf4\x23\x72\x1c\xcb\x17\x2a\x1b\xaf\xa1\xd5\xae\x9f\xc1\xc5\x1e\x93\xd4\x1d\xd5\x51\xc3\x08\x60\x79\xb6\x20\x28\x6c\x1c\x40\xc1\x22\x3b\xbc\xbb\x76\x72\x2e\x92\xca\x21\xd8\x41\x0a"}, -{{0x1a,0x61,0x15,0x4d,0x34,0x72,0xcd,0x96,0xb3,0x28,0xee,0x67,0x4b,0xeb,0x4f,0xc8,0x67,0x63,0xa9,0x69,0xfb,0x41,0x04,0x94,0xe0,0x67,0x84,0x14,0xe3,0x1a,0x46,0xa6,},{0x75,0x76,0xd9,0x3a,0xc8,0x5d,0x0f,0xc6,0x1f,0x25,0x8c,0x55,0xcf,0x90,0xbd,0x87,0xa6,0x35,0x09,0x9c,0x0e,0x81,0x0e,0xd0,0xb9,0x37,0x25,0x8d,0x13,0xb4,0x25,0x59,},{0xad,0xa1,0x66,0x6c,0x9c,0x3b,0x82,0x84,0xb8,0xa2,0x1c,0x4f,0x26,0x18,0xef,0x08,0x08,0xa6,0x46,0xf3,0xf1,0x09,0x41,0xe4,0x70,0xf7,0x38,0xe1,0x78,0x5e,0x2d,0xe9,0xfd,0xd9,0xc8,0xcb,0x52,0x6f,0x94,0x5c,0x7a,0x8c,0x69,0x94,0xf1,0x51,0xb7,0xd0,0x66,0x58,0x1b,0x1d,0x75,0x53,0x07,0x94,0x7c,0x62,0xbe,0xfc,0x8a,0xb7,0x07,0x0f,},"\x64\xc5\x65\xef\xbc\xb8\xb9\x52\x8e\xd4\x72\x53\xf3\xc6\xa4\x03\x5d\xb7\x81\xd6\xf0\x97\x6b\x5e\x5b\xa8\x44\x7d\x4e\xd5\x4b\x04\x10\x52\x93\xef\x4c\x00\x0d\x8b\x2e\x1b\x5b\x75\xe7\x27\xe5\xd2\xa0\x77\x74\x3b\x50\xd1\x83\xb4\x91\x76\x48\x01\xa2\x50\x4d\x16\xee\x6d\x7d\x8a\xc4\xfe\x40\xe6\xbf\xc2\xa8\x12\x9c\x72\x85\xa5\xac\x69\x1c\x35\xe6\x42\xed\x16\x2c\xf7\xfb\xc6\x45\x16\x73\x3a\x23\xb3"}, -{{0xf2,0x15,0xd3,0x4f,0xe2,0xd7,0x57,0xcf,0xf9,0xcf,0x5c,0x05,0x43,0x09,0x94,0xde,0x58,0x79,0x87,0xce,0x45,0xcb,0x04,0x59,0xf6,0x1e,0xc6,0xc8,0x25,0xc6,0x22,0x59,},{0x1e,0xd5,0x06,0x48,0x5b,0x09,0xa6,0x45,0x0b,0xe7,0xc9,0x33,0x7d,0x9f,0xe8,0x7e,0xf9,0x9c,0x96,0xf8,0xbd,0x11,0xcd,0x63,0x1c,0xa1,0x60,0xd0,0xfd,0x73,0x06,0x7e,},{0xcb,0xef,0x65,0xb6,0xf3,0xfd,0x58,0x09,0x69,0xfc,0x33,0x40,0xcf,0xae,0x4f,0x7c,0x99,0xdf,0x13,0x40,0xcc,0xe5,0x46,0x26,0x18,0x31,0x44,0xef,0x46,0x88,0x71,0x63,0x4b,0x0a,0x5c,0x00,0x33,0x53,0x41,0x08,0xe1,0xc6,0x7c,0x0d,0xc9,0x9d,0x30,0x14,0xf0,0x10,0x84,0xe9,0x8c,0x95,0xe1,0x01,0x4b,0x30,0x9b,0x1d,0xbb,0x2e,0x67,0x04,},"\xfb\xed\x2a\x7d\xf4\x18\xec\x0e\x80\x36\x31\x2e\xc2\x39\xfc\xee\x6e\xf9\x7d\xc8\xc2\xdf\x1f\x2e\x14\xad\xee\x28\x78\x08\xb7\x88\xa6\x07\x21\x43\xb8\x51\xd9\x75\xc8\xe8\xa0\x29\x9d\xf8\x46\xb1\x91\x13\xe3\x8c\xee\x83\xda\x71\xea\x8e\x9b\xd6\xf5\x7b\xdc\xd3\x55\x75\x23\xf4\xfe\xb6\x16\xca\xa5\x95\xae\xa0\x1e\xb0\xb3\xd4\x90\xb9\x9b\x52\x5e\xa4\xfb\xb9\x25\x8b\xc7\xfb\xb0\xde\xea\x8f\x56\x8c\xb2"}, -{{0x8c,0x9f,0x95,0x08,0x30,0x75,0xa4,0x3f,0xe4,0x26,0xd1,0x9f,0x1e,0x87,0x71,0x9b,0x40,0x04,0x3d,0xe8,0x8e,0xb0,0xee,0x97,0x1f,0x70,0xe1,0x0c,0x76,0x94,0xce,0x4e,},{0xe9,0x1d,0x16,0x7a,0xa3,0xeb,0xc2,0x3e,0x70,0xaa,0xb4,0x5d,0xab,0xe9,0x05,0xe4,0x16,0x26,0x2f,0x91,0x0e,0x2a,0x95,0x5d,0xd8,0x61,0x9e,0xfc,0x74,0xc2,0x4e,0x85,},{0xca,0xc5,0x55,0x22,0x2d,0xaf,0xec,0x76,0xa0,0xb4,0x7b,0x9d,0x2c,0x58,0x6b,0x3b,0x3b,0x9b,0x3b,0x9c,0x83,0x64,0xbe,0xb3,0xca,0xe1,0xe8,0xdd,0x7f,0x1a,0xe9,0xdd,0x74,0xf2,0x2b,0x8d,0xd4,0xad,0x2b,0x29,0x0f,0x81,0x35,0x1a,0x41,0x5a,0x99,0xf0,0x30,0xf1,0x07,0x78,0xbe,0x4c,0xda,0x85,0xd1,0xd3,0x53,0x33,0x1e,0x70,0xf1,0x09,},"\xb6\x9d\x70\xe8\x60\xf5\x5c\x42\x7e\xf2\xa7\x1d\xf3\x6e\x05\xbb\xc4\x3b\xb2\xe0\x64\x63\xaa\x5d\xe3\x44\x19\xc6\xa6\x14\xee\xa6\x69\x53\x35\xa8\x75\x26\xc1\x22\x64\x88\xd8\x42\x89\x1d\x05\x74\xdf\x34\x3c\x9c\x1e\x17\xae\xd6\x95\x8e\xce\xe8\x74\x74\x22\x1e\xb7\x7a\x59\x9e\xcb\x05\x93\x44\xc0\xd0\x52\xc0\x00\x2a\x66\xe5\xa6\x01\x31\x85\xaf\x69\xa0\x1b\xa5\xdb\xc6\x60\xd3\x6c\xae\x23\x5f\x67\xfe\x0e"}, -{{0xd7,0xeb,0x1f,0xba,0x42,0x4f,0xee,0xd1,0x00,0x77,0x7e,0xed,0xb4,0x87,0x4b,0xf2,0x08,0x10,0xad,0x68,0x6b,0x67,0xe3,0x1d,0x27,0xec,0xf6,0x10,0x60,0x9a,0x33,0xf5,},{0xa2,0x5a,0xcb,0x11,0xa6,0xc8,0x25,0x71,0x3a,0x08,0x5f,0xa7,0x54,0x69,0x28,0x86,0xa8,0x7d,0x07,0xfb,0x9b,0xe1,0xa5,0x3e,0xb9,0x61,0x72,0x8b,0xb6,0x6c,0x90,0x60,},{0x2b,0xf7,0x19,0x68,0x2b,0x07,0xcc,0x5e,0xcc,0x04,0x80,0xf3,0x7e,0x9d,0x12,0x3f,0xf6,0xf4,0x4c,0x26,0xe6,0x95,0x8e,0x59,0xf0,0x80,0x46,0x6f,0x9c,0xd3,0x73,0xa1,0x65,0x00,0xda,0xf1,0x23,0xdc,0x3f,0x13,0x34,0x77,0x4b,0xfc,0x9f,0xa8,0x45,0x03,0xb1,0x6d,0xbf,0x21,0xa8,0x15,0xc1,0xad,0xa6,0xeb,0xef,0x49,0x20,0x46,0x17,0x02,},"\xa1\xd0\xf8\x1e\x3d\x59\x08\x9c\xc2\xb1\x9e\x07\xd2\xfc\xe4\x3d\xb4\xcf\x17\x1f\xaa\x64\x2f\x3b\x0b\xbd\xe7\x7a\xe3\xd5\x3a\xf5\xc0\x2b\xf8\xfc\x12\xff\xb4\xe5\x7f\x7c\x8a\x01\x5d\x6c\x2d\x17\x89\x44\xfa\xe9\xf7\xc8\xfc\x96\x9d\x4b\x77\xbe\xa5\x18\x76\xae\x99\xd5\x9e\x94\xad\x24\x56\xe0\xed\x72\xc5\x2c\xf4\xe5\x34\x0d\xa1\x7c\x44\xdb\xff\x86\x45\x7a\x51\x9b\x6f\xff\xe2\x69\x06\x62\x90\xd6\x29\xfe\x69"}, -{{0x4f,0x6a,0xeb,0x35,0xfc,0xe1,0x4f,0xbc,0xbb,0x9a,0xa8,0xa4,0xf6,0x45,0x1b,0xf9,0x5b,0x98,0xdf,0x04,0x7f,0xa8,0xc4,0x3f,0x1e,0xad,0x3b,0x40,0x4d,0x3f,0x92,0x8f,},{0xbf,0x66,0xa9,0xed,0xd0,0x94,0x81,0xdb,0x84,0x44,0xa1,0x76,0xc8,0xce,0x05,0x78,0xd2,0x93,0x4f,0x0c,0xdc,0x97,0x34,0xe8,0x6f,0xca,0xac,0x05,0xbf,0x33,0x30,0xf1,},{0x6a,0xdb,0x07,0xe3,0x64,0xf2,0xa4,0x55,0xcb,0x05,0x86,0x7a,0xbc,0x51,0x1a,0xcd,0x9d,0x65,0x89,0x77,0xf0,0xca,0xca,0xfc,0x92,0x82,0x8e,0x7b,0x72,0x4f,0x6b,0xbf,0x98,0xbf,0x0b,0xfb,0x29,0xf4,0xe5,0xe6,0xc7,0x47,0x38,0xd4,0xfd,0xd8,0x16,0xd9,0x25,0x24,0x07,0xae,0x4f,0x3a,0xfc,0x57,0x4c,0x4f,0x00,0x61,0x48,0x24,0xe2,0x03,},"\x2d\xfb\xb3\xf5\x9e\x19\xea\x17\xd4\x4a\x5b\xde\x4a\xd2\x27\xa1\xa3\x51\xdd\xa1\x7a\xf8\x40\xee\x0a\x75\xda\x21\xa5\xcc\xa8\x9b\x6d\x1c\x56\x7c\x33\x3e\x9c\xc9\x10\xe2\x15\x7e\x05\xe8\x6a\xd5\xd9\x31\x14\x50\x64\x59\x4c\x47\xba\xee\xa8\x66\x3a\x34\x64\x9c\x43\xe9\x0e\xb9\x5c\xa1\x0f\x7d\x51\x59\x7b\x37\x8a\x72\x2f\x1f\x70\x4a\xdf\x9f\x22\xe9\xf8\x85\xb8\x9d\x1f\x93\x80\x06\xa2\xef\xcd\xb4\x2a\xaf\xf5\xe3"}, -{{0xef,0x4a,0x67,0x62,0xb4,0x00,0x97,0x52,0x04,0xcc,0xc1,0x3a,0xbb,0x47,0x34,0x40,0x15,0x45,0x49,0x06,0x85,0x0f,0xf1,0x49,0x40,0xcb,0xb8,0x3a,0xa2,0x24,0x14,0xae,},{0xea,0xca,0x45,0x09,0x96,0xf5,0x0c,0xfa,0xf2,0xbd,0x7f,0x9d,0x7f,0xa7,0x08,0x7f,0x09,0xad,0x49,0x66,0x42,0x06,0xa8,0x0b,0xc2,0xe5,0xbb,0xbb,0x85,0xbb,0x66,0x8e,},{0x02,0x69,0x7d,0x44,0xca,0xd8,0x62,0xf1,0xda,0xf5,0x70,0x82,0x05,0xf4,0x50,0xd4,0x08,0x52,0x5b,0x10,0xc0,0x1f,0xfd,0x06,0xcf,0xee,0x80,0x37,0x4f,0x3d,0xb1,0x6f,0xa9,0xa4,0x9c,0x19,0xa9,0x84,0x4b,0x34,0x5f,0x2f,0x95,0x59,0xea,0x74,0xaa,0xb1,0x73,0xba,0xa0,0x78,0xc5,0x43,0x70,0xa5,0x16,0x67,0x00,0xc6,0xda,0xfb,0x78,0x0a,},"\xa4\xb6\x3e\xae\xd5\xa6\x4a\x94\xf2\xca\xd2\x12\xce\x2a\xe7\x10\x92\xfd\x3e\xa7\x44\xf5\xbd\x89\x56\x2b\x2f\xc2\xa6\xc9\xe4\xd7\xaa\x27\xad\xd5\x62\x64\xa5\xa5\x50\x16\x61\x0b\xe6\xc1\x9f\xf7\xd4\x98\x9e\x95\x04\x74\x08\x53\x01\x27\x15\xa7\x9e\xce\x9e\x12\xc3\x01\xb3\x31\x7c\x7d\x9b\x67\x30\xdb\x86\x2a\x4a\x1d\x28\x05\x8e\x0f\x8b\x5d\xdd\x97\x38\xc7\xc6\x2e\xa5\x72\xcf\xe5\x9e\xae\x08\xe2\xb8\xb6\x59\x3b\x58"}, -{{0x55,0x01,0x7e,0x5f,0x61,0xf0,0xc5,0xba,0xfb,0xcd,0xe6,0xf8,0x49,0xf4,0x2a,0x31,0xe5,0xe7,0xa8,0x78,0xc1,0xd3,0xf9,0x12,0x6f,0xc5,0x69,0xfd,0x41,0x7e,0xa9,0xf2,},{0x66,0x91,0x4f,0x74,0xed,0x93,0x2f,0xc8,0x81,0xff,0x01,0x66,0x68,0x3f,0x67,0x5a,0x7c,0x28,0xa9,0x26,0xfd,0xdd,0x64,0x69,0xcd,0xb3,0xf2,0x8e,0x6d,0xec,0x42,0xcc,},{0xb1,0xa5,0xe7,0xc4,0x9b,0x8f,0xc6,0xb4,0x33,0x1e,0x04,0x16,0xce,0x7e,0x4e,0xd5,0x9e,0xdd,0x56,0x30,0x0b,0x80,0x2e,0x0d,0x72,0xab,0xca,0x4a,0x6f,0xcb,0x87,0x6c,0x03,0xbf,0x33,0x15,0x79,0x12,0x4a,0xe0,0xd3,0xfe,0x43,0xf7,0x89,0x8b,0xc8,0x7e,0x93,0xfc,0x2d,0xa3,0x97,0x0f,0xc8,0x63,0x89,0x57,0xd1,0x8c,0x66,0x13,0xc8,0x08,},"\x2f\xc8\x4a\x09\x98\xfa\x6e\x16\x8a\x86\x64\x10\xbb\x68\x10\x5d\xf2\x49\xa2\x8c\xfc\x76\x60\x4b\xe9\x4f\xd7\xdf\xff\xf2\xfc\x1d\xed\xd2\x20\x19\x94\x65\x57\x5e\x8d\xf8\x60\x19\x0f\x16\xac\xa4\x08\x41\x69\xbe\x16\xc6\xba\x32\xeb\x67\x04\x2f\xfd\x4f\x23\x03\x16\xa2\x6b\x26\x24\xa4\x2f\x8f\x90\xad\x57\xf6\x91\x64\x86\xfa\x91\xfd\x94\xed\x68\xad\xed\x4e\x63\x24\x30\xef\x71\x94\x46\x97\x9b\xfa\xf3\x45\x40\x9c\x38\x7f"}, -{{0x05,0x53,0xfb,0xa8,0x66,0x94,0x23,0x41,0x21,0x7c,0xf2,0x78,0xac,0x57,0xcb,0x21,0xac,0xd0,0x9d,0x99,0x16,0xcc,0x6a,0xf0,0xac,0x46,0x94,0x1e,0xa1,0x39,0xd5,0x45,},{0x84,0x0c,0x66,0xe5,0x7c,0x2d,0x4f,0x52,0xa4,0xa2,0x79,0x6d,0x2a,0x53,0xc5,0x70,0x9b,0x96,0xa6,0x28,0xc2,0xe0,0x63,0xfe,0x6e,0xfd,0x47,0xf2,0x83,0xef,0x5e,0x82,},{0xbc,0x33,0x64,0xc1,0x52,0xee,0x5c,0x80,0x8a,0xc3,0x40,0xf4,0x9e,0xa2,0xcc,0x40,0x4e,0x93,0x51,0x71,0x21,0x22,0x0c,0xce,0x6f,0x7c,0x30,0xa2,0x25,0x00,0xe4,0x1b,0xcd,0xb6,0xe8,0x20,0x48,0x0f,0x8f,0xcc,0xdd,0x22,0xff,0x9a,0xd9,0x6d,0xa5,0x32,0x80,0x2f,0x43,0x1e,0x94,0x24,0x0f,0xb8,0x3d,0x4b,0xce,0xaa,0x09,0xb9,0x2b,0x0d,},"\xc1\xfa\xe6\x26\x2a\x0e\x98\xa6\xb1\x23\x5f\xcb\x62\x28\x3b\x7f\x0a\x09\x7f\x9d\x00\x24\x16\xd3\x18\xfe\xfc\x60\xc5\xa1\x58\x4f\x90\x0a\xd0\xab\x26\xcc\xfa\xe0\xd6\xd8\x4a\xa9\xaa\x2d\xf1\x6d\x4c\x11\x7e\xa2\x72\x46\x76\xcb\x86\x6d\x48\x70\xa8\x72\xfc\x82\x9a\x7c\x2a\x5d\x21\xba\x83\x34\x0a\xdb\x33\x9a\x34\xc5\x18\x4c\x7f\x5e\xad\x0f\x07\x72\x89\xb3\x36\x77\xed\x6a\x1b\xa3\x4b\xe1\x99\x4e\x25\x76\x3b\xd1\xd9\xfa\xec"}, -{{0x7a,0x5a,0xc6,0x02,0xde,0x19,0xf3,0xc2,0x10,0x40,0xbc,0xdd,0xbf,0xf4,0x2f,0x6a,0xee,0x6f,0x95,0xc1,0xb0,0x93,0x86,0x8f,0x48,0xe5,0x04,0x82,0xdb,0xf4,0xf9,0xc7,},{0xfb,0xb6,0xc7,0x53,0x1c,0xda,0x21,0xe7,0xd1,0x7e,0xa9,0x03,0xc4,0xd1,0x4b,0xe6,0xc6,0x8b,0x4c,0xa8,0x03,0xa1,0x6b,0xd8,0x71,0x20,0xf5,0xaa,0xf7,0xdc,0xe1,0xd4,},{0x84,0x10,0x1d,0xd4,0xb5,0xe8,0xca,0x3e,0xd9,0x8c,0x1e,0x8a,0x06,0xe1,0x1d,0x7e,0x42,0x4b,0x0d,0x12,0xca,0x71,0x4e,0xe7,0x37,0x4b,0x64,0xc2,0x9d,0x51,0xa2,0x02,0x1c,0xc7,0x7a,0xc7,0x53,0x89,0xd9,0xb0,0xa6,0x46,0xa4,0x47,0x62,0x3d,0x7d,0x04,0xd1,0x24,0x18,0x66,0xb0,0xca,0x6e,0xdd,0x1b,0x7a,0xc0,0x15,0x66,0x6b,0x70,0x0d,},"\xbd\x16\x85\x41\x92\x79\xeb\x81\xe4\xcf\x3c\x90\x90\x31\xf0\xf0\x9c\x5f\xfa\xe7\xe2\xce\x6b\xa9\xd9\x6c\x2b\xce\x87\xb8\xba\x0d\xd7\x63\x23\x10\x01\xe5\x32\xc7\xdd\xd6\x21\x03\xab\xf7\x01\x28\x8e\x19\xdd\x8f\x53\x02\xe8\xf5\xd3\x1b\x64\xcc\x33\x9b\xd8\xb7\xa9\x55\x50\xc8\xa1\x16\xfd\x48\x69\x48\x77\x2b\xd5\xaf\x8d\xfd\x46\x00\x1c\x59\x76\x7b\x0d\x6b\xdc\xe3\x83\xa7\x07\x89\x92\xd1\x02\x2f\xbc\xaf\x90\x71\x06\x87\xb9\xaa"}, -{{0x50,0x41,0x4c,0xf5,0x49,0xbc,0xc5,0x5b,0x5b,0x6b,0x75,0xea,0x37,0x82,0xb2,0xea,0x7c,0x08,0x7b,0x6a,0x01,0x06,0x17,0x5e,0x46,0x9c,0xa2,0xcc,0x76,0x4a,0xeb,0x01,},{0xd0,0xf3,0x0c,0x12,0xe9,0x97,0xf9,0x6e,0x7a,0xee,0xcd,0x1b,0xff,0x6a,0x01,0x2e,0xc3,0x88,0xeb,0xf8,0xf3,0xf4,0xaf,0x66,0x48,0x04,0xd1,0x63,0x8e,0x4c,0x34,0x6a,},{0xb3,0x09,0x80,0x01,0x60,0xde,0x43,0xa6,0x3a,0x89,0xa0,0xac,0xb8,0xa6,0x05,0x00,0x59,0x58,0x9b,0x3e,0xae,0xca,0xc2,0x0b,0x25,0x6f,0xec,0xe4,0x38,0x04,0x2f,0x69,0x41,0x5d,0x8a,0x56,0x88,0x3e,0xe3,0x83,0x6d,0x31,0x34,0xa7,0xfc,0x1d,0xe6,0x4f,0xa8,0xc8,0xce,0xcc,0x3c,0xe2,0x75,0x89,0xf6,0x06,0x05,0x88,0x20,0x85,0x7a,0x0c,},"\x75\xad\x77\xe8\xc5\x4b\x0b\x05\xfb\x2d\x16\x2e\x7c\xad\xb8\xa7\x52\x80\x81\xb8\x63\xf7\x6a\x44\x1b\x37\x44\x69\x41\x3e\x57\x14\xed\xf5\x4f\x80\x04\x96\xaf\x01\x57\xc1\x7e\x42\x55\x83\x41\x4d\x43\x61\xf2\x13\x41\x71\xc0\xb8\x7c\x22\xce\x68\x20\xa4\x85\x0a\xb4\x9d\x99\xa9\xba\xdc\xe9\xe3\x61\x10\xe7\xf3\x06\x01\x18\xb3\x59\x0f\x82\xb4\x37\x71\xe9\xfb\xb0\x81\xaf\xe6\x22\x27\xe0\x24\xd9\x8d\xe6\xcd\xec\x02\x8d\x7c\x49\x49\x0d"}, -{{0x93,0xcb,0x00,0xd8,0xfe,0x9c,0x97,0x77,0xa6,0x83,0x63,0x1f,0x39,0xba,0x0f,0x48,0x76,0x14,0x82,0xcf,0x1c,0x36,0x6b,0xd8,0x63,0xcf,0x71,0x51,0x01,0x53,0x25,0x55,},{0x87,0xe9,0x4a,0x1e,0xa5,0x25,0x8d,0x61,0x18,0x0c,0xb8,0x28,0x59,0x0f,0xf1,0x41,0x8a,0x87,0xd0,0x1e,0x70,0x26,0x86,0xba,0x8a,0xbc,0x26,0x92,0xc8,0xdc,0x3c,0x91,},{0x09,0x82,0x4f,0xa2,0xdf,0xbc,0x4d,0x6e,0xf7,0x6a,0x9e,0x41,0x45,0x96,0x11,0x16,0x76,0x91,0x30,0x55,0x3b,0x3e,0xdf,0xfa,0x50,0xd0,0x4f,0x39,0xb8,0xb7,0x9f,0xac,0xbd,0x23,0x7a,0xcf,0x71,0x35,0x4a,0x53,0xa6,0xe5,0xfe,0xe7,0x54,0xe8,0x23,0xb0,0xb2,0x90,0xf9,0x61,0x93,0x20,0xa1,0x3d,0x56,0x12,0x69,0xa2,0x21,0x63,0x9f,0x03,},"\x88\xd8\x53\x8d\x31\x86\x78\x13\xd8\x8f\xef\x72\x28\xd4\x9a\x7e\x95\x0d\x73\x83\x96\xf1\x16\xdd\xa1\x02\x5f\x79\x13\x54\x7c\x5d\x1d\xc5\x67\x7a\x6d\xe4\xb4\xa5\x88\x05\x07\xb3\x61\x78\x0b\x61\xb4\x3f\x77\x95\x26\x3d\xb2\x2f\xf3\x41\x64\x5f\x2f\x59\x14\xfd\x60\x88\xc2\x81\x12\x11\xed\x47\x56\xac\x01\x9a\x60\x35\xd6\x6e\x31\x70\xc1\xd8\x2b\xfa\xa3\x05\x96\xb3\x96\xb3\x26\x0c\xc1\xd1\x0d\x41\x3d\xd4\x7e\xbe\x6d\xaa\x0c\x30\xdc\x42"}, -{{0x2b,0x4c,0xae,0x38,0x0e,0x95,0xce,0x69,0x4c,0x26,0xac,0x79,0x57,0x44,0x73,0x47,0xf9,0x8e,0x31,0xb4,0xbf,0x02,0xd7,0x44,0xe1,0x31,0x52,0x90,0x71,0xe2,0x30,0x1d,},{0xe6,0xfc,0x70,0x5a,0x79,0xc9,0x8e,0x11,0x5b,0x4e,0x28,0xd3,0xaa,0x15,0x06,0xb7,0x4e,0xe7,0x42,0x76,0xc5,0xfc,0x11,0x09,0xa7,0xf4,0xd8,0x9c,0x6f,0xaf,0xb8,0x89,},{0x55,0x5e,0x45,0x65,0x6b,0xa9,0xcf,0xbf,0x51,0x55,0xd0,0xe5,0x25,0x76,0xe5,0x19,0x7a,0xbb,0xbc,0x9d,0xd2,0x33,0x99,0x3e,0xec,0x2a,0x1e,0xe7,0xf6,0xa8,0x64,0x09,0xc0,0xb7,0x1b,0x0a,0x66,0x19,0x78,0xff,0x5e,0x0a,0xcd,0xc9,0x46,0x3d,0xc4,0x49,0x90,0x6f,0x47,0x4f,0x8e,0x79,0xbb,0x86,0x16,0x8b,0xf7,0x07,0x41,0xe3,0x4b,0x02,},"\xe0\xb8\x25\x0e\x27\xb7\xc0\x29\x1d\xbc\x47\xa6\xda\x6f\x12\x68\x98\x7a\xfd\xf0\xa1\xe9\x0b\xe6\x9b\xcb\xc4\x37\x08\x65\x21\x78\x30\xd5\x20\x86\x93\xbe\x7b\x70\x45\x09\x9a\x22\xea\x27\xf9\x52\xeb\x3f\x79\xa9\xa0\xf1\xb5\xa8\x7b\x19\x36\x77\x90\x78\x8d\x34\xc2\x19\xc2\xe2\xa6\xb8\x34\x02\x0f\xb4\xfd\x14\x9d\xc5\x6b\x54\x4f\xdd\xbb\x42\x07\x1a\x16\x2f\xc7\xcb\x33\xc1\x46\xca\xc0\x5a\x31\xb1\x83\xe9\xda\xad\xc6\x16\xf3\xaf\x44\x9b\x17"}, -{{0xb5,0x64,0x91,0xe5,0x49,0x99,0xbb,0x5a,0x17,0x15,0xeb,0xfa,0x2f,0xeb,0x14,0xa5,0x45,0xa3,0xa4,0x3c,0x2f,0xdf,0xd4,0xbe,0x0c,0x95,0xfc,0x11,0x81,0x9a,0xd6,0x95,},{0xcd,0x42,0xbf,0x41,0x4f,0x9b,0xfc,0x72,0xec,0x06,0x98,0x82,0xa8,0x00,0x55,0x7c,0xdf,0x31,0xbc,0x34,0x64,0xfb,0x10,0x2c,0x31,0x0e,0x6d,0xbd,0x3a,0xe2,0x08,0x63,},{0xe3,0xbe,0x3e,0x71,0xa8,0x98,0x52,0xdf,0x3c,0xff,0xd7,0x2d,0x68,0x20,0x78,0x69,0xdd,0x3e,0xce,0xb4,0x9b,0x1f,0x02,0x94,0x93,0xec,0xcb,0xb9,0x32,0x44,0x4e,0xbe,0x8c,0x8c,0x6d,0xb5,0xf0,0xa5,0xa6,0x7e,0x21,0x94,0x40,0x8d,0xf9,0x84,0x19,0x13,0xa5,0xac,0x1a,0x60,0x68,0x96,0x41,0x9a,0x66,0x8f,0x4f,0x47,0xc5,0x6c,0x2b,0x08,},"\xeb\x44\x18\xba\x30\x68\x3e\xc7\x95\x9b\xdb\x1e\xc7\xb2\x63\xf8\x3e\x81\xf0\x54\xdd\xcd\xbe\x0a\x67\x38\xca\x77\x63\xe2\x46\x93\x5b\xac\x41\x90\x26\xc2\x2b\xfb\xdd\x12\x36\x33\x6c\xc1\x61\x07\xc5\x35\x13\xe3\xdd\xf3\x4e\x12\x08\x46\x96\x2c\x3b\xdd\x54\xf5\xad\x57\x49\x59\x72\x08\xf1\x5a\x8b\xb5\x66\x67\xba\xa8\x95\xf0\x83\x40\xdb\x89\xb8\x5c\x43\x5e\x77\x09\x31\x92\x8d\x8a\xbc\x99\x26\x2f\x83\x9a\xed\xd9\xbe\x2a\xa1\x38\xc9\x25\x9a\xdf"}, -{{0x65,0x79,0xc2,0x47,0xdd,0x2c,0xd0,0x2b,0xa2,0xf7,0xd7,0xa9,0x50,0xa3,0x30,0x75,0x26,0x81,0xe9,0x2c,0x0d,0xc6,0x29,0x84,0xbb,0xea,0x27,0x9e,0xa5,0x21,0xc3,0x81,},{0x0b,0x08,0x7b,0xea,0x1a,0x1b,0x3d,0x15,0x80,0x5c,0xb6,0x04,0xf4,0xbb,0x8d,0x68,0xed,0xde,0x27,0x4f,0xaf,0x52,0x1f,0xe6,0xdf,0x50,0xc5,0x5f,0x8a,0xd4,0xa7,0x0d,},{0xec,0xca,0xf8,0x01,0xae,0x0a,0x91,0x2e,0x21,0xc6,0xb8,0x3a,0x5f,0x0e,0x4e,0x88,0xd4,0xb2,0x71,0x34,0x59,0xff,0x93,0x44,0x9f,0xc0,0xb2,0x1a,0x9f,0x41,0x60,0x50,0x11,0x3c,0xba,0xe4,0xe8,0x14,0xd2,0x0c,0x0a,0x79,0x8f,0x76,0xd2,0xf9,0xd3,0x26,0xed,0x83,0x95,0x9e,0xa0,0x2a,0xbd,0xc1,0xab,0x35,0x0a,0x46,0x71,0x23,0xf7,0x09,},"\xdf\x7c\x55\x2f\xfc\x89\x37\x4b\x95\x71\xa6\x02\x4a\x8d\x04\x71\xd7\xeb\x6b\xe8\xdf\xca\x6f\x41\x66\xb5\x81\xb6\x54\x79\x01\x5a\x05\x68\x12\x90\x74\xcc\x04\xd6\x34\x2c\x75\x8c\xa1\x8f\x79\x87\xde\xc5\x36\xb7\x03\x3d\x5f\x96\x81\x50\x43\x40\xe2\x09\x86\xf0\x27\xb8\xcf\x1f\x26\x3b\xe7\x6d\xb3\x52\x5d\x17\x34\x22\x95\x0e\xa8\xdc\xed\xdc\x58\x56\x40\x91\x8a\xa9\xd2\x5c\xa8\x9c\xba\x70\x1c\x20\x20\x15\x38\x73\xf4\x61\x08\xc7\x72\xcb\x38\x8d\x55"}, -{{0x18,0xfb,0xa6,0x0c,0x50,0x26,0xf3,0xc9,0xdd,0x7a,0xed,0xc0,0x42,0x09,0xd5,0x26,0x03,0x61,0xde,0x40,0x0e,0x19,0x0a,0xeb,0x60,0x16,0x9e,0x05,0xa3,0x36,0x7c,0x9f,},{0xdf,0xff,0x34,0x7f,0x3d,0xd2,0x55,0x53,0x0b,0xf7,0xfb,0x34,0xd0,0x2b,0xa4,0x86,0xd1,0x12,0xbb,0x46,0xe9,0x50,0xe2,0xef,0x80,0xe5,0x17,0x01,0x4c,0xc9,0x57,0x34,},{0x4b,0xc0,0x11,0xe4,0x0f,0x0f,0x59,0xc6,0x18,0xf6,0xbb,0xe2,0x30,0xb6,0xf7,0xbc,0x2f,0x50,0xe3,0x61,0x7c,0x7f,0xaa,0xb7,0xf4,0xc2,0x1c,0xb8,0x4f,0x77,0xeb,0xa9,0x94,0xcb,0x7c,0x2a,0x1b,0xf1,0x0b,0x01,0xbb,0x20,0x08,0x44,0x97,0xfd,0xf0,0xa6,0xab,0x5d,0x9b,0xcd,0x22,0xc4,0xa2,0xc5,0xa7,0x8f,0x79,0x92,0x68,0x25,0x94,0x0f,},"\x34\xf0\x8a\x80\x4d\x78\x29\xcc\x39\x14\xf0\x00\xce\x1a\x32\x88\xac\xce\x21\x49\xc8\xa0\x20\x86\xb9\xf6\x7a\xfc\xcd\x83\xa1\x78\xb0\xbc\xfd\x49\x70\xc0\x56\x99\x7d\xa7\xdc\x3d\x47\x56\x2f\x16\x66\x3c\xed\xc5\x2f\x82\xd7\x10\x85\x0c\xf4\x05\x03\x79\xef\xda\xc2\x3b\xee\x17\xc3\x30\xa3\x83\xad\x13\x7f\x78\x84\x73\xb2\xb0\x72\x36\x03\xb6\xde\xb1\xfd\xbf\x6c\x52\x3f\xc9\x48\xa0\xcc\xc4\xff\x10\x0f\xb9\x46\xd8\x74\xc1\xf9\x90\x43\x6a\xe8\xc4\xf3\xb2"}, -{{0x07,0x3c,0xc1,0x5b,0x05,0x36,0x28,0x59,0x33,0xb2,0xbe,0x39,0x25,0x3c,0xf4,0xfd,0x69,0x6b,0x81,0x61,0x0f,0x5d,0xd3,0xad,0xac,0x2e,0x9c,0xbf,0x33,0x8e,0xf2,0xf6,},{0x00,0xb5,0x51,0xd3,0x71,0x54,0x43,0x75,0xda,0xc5,0xc4,0xe9,0x6c,0xd1,0xf0,0x21,0x52,0x07,0xe8,0xe1,0x66,0xa1,0xfe,0x49,0xd5,0xb0,0xa5,0x1a,0xc1,0x84,0x43,0xec,},{0x3a,0xa5,0x2a,0x83,0x06,0x2a,0x8f,0x28,0xa5,0xd6,0xb7,0x60,0x7f,0x48,0x4b,0x66,0xcc,0x37,0x48,0x96,0xb7,0x66,0x12,0x31,0x26,0x33,0x3c,0x57,0x95,0x81,0x31,0x6c,0x74,0x28,0x06,0xf6,0x27,0xb5,0xbc,0x55,0xca,0xd7,0x05,0xcc,0x1d,0x47,0x82,0xb0,0x44,0x08,0x0c,0x8a,0xc8,0x40,0xf3,0x8c,0x0c,0x50,0xd3,0x5e,0x34,0x5c,0x78,0x03,},"\xc2\x85\x36\x2b\xc8\xef\x62\x8f\x7a\xed\xf6\x54\x23\x1e\xe5\x1a\xcd\xf2\xcf\x69\xa8\x86\xb9\x42\xbb\x9b\xfe\xd8\x15\x51\x05\xd9\x20\x9d\xed\x2a\xf2\x4f\x16\x9a\xd5\xfc\xd4\x51\x37\x0f\x58\x27\xa8\x51\x11\xc7\xa5\x2e\x03\x2c\x50\x38\x61\x7c\x0c\x01\x70\xe2\xa6\xc2\x31\xdc\x40\x1d\x12\x06\x2e\xdb\x18\x60\x36\x11\x4e\x38\x79\x3b\x79\x08\x90\x77\x58\x1b\x97\x83\xf4\x00\x07\x10\x3e\xf1\x74\x72\x49\x1c\x00\xe7\x13\x8a\xec\xc5\x08\x4d\x3c\x85\x01\x04\x70"}, -{{0xfd,0x89,0x4a,0x1e,0x82,0x32,0x20,0x3b,0x28,0x95,0x05,0xd5,0xc6,0x8c,0x68,0x79,0x1f,0xfc,0x0e,0x54,0xf2,0xa8,0x75,0x30,0xfb,0xba,0x5b,0x3a,0x3f,0x2c,0xaf,0x00,},{0xe9,0x5a,0xb5,0x65,0x94,0x5c,0x7a,0xe5,0xd5,0x33,0xdf,0x5d,0x0c,0xcc,0xc7,0xe9,0xab,0xbc,0x83,0x8e,0x20,0xa0,0xb6,0x1c,0x93,0x0f,0x5d,0x41,0xd8,0x1a,0x6f,0xe7,},{0xf5,0x11,0x02,0x21,0x9e,0x88,0x04,0xbe,0x71,0x3e,0x55,0x6d,0xf4,0xe4,0xaf,0xa2,0xf8,0x86,0x6f,0xe8,0x65,0x41,0xa1,0xc2,0xa0,0x93,0x4d,0x24,0xc3,0xc9,0xbe,0xb2,0x80,0xa7,0x0d,0xd8,0xd5,0x27,0xfe,0x8b,0x7e,0x0b,0x94,0x82,0x14,0xd5,0xf2,0xf9,0x63,0x86,0x19,0x91,0x4b,0x72,0xd5,0x5d,0xc1,0x98,0xb0,0x22,0x9a,0x84,0x87,0x08,},"\x26\x69\x62\x4a\x94\xf2\xc4\x4a\x05\xb7\xdc\x3e\xbf\x93\xe5\x8a\x4b\xf3\xa0\x1c\x27\x36\x57\xe7\xe7\x87\x89\x76\xf6\xb6\xea\x73\x7f\xa3\xf2\x2c\xc8\x36\x5b\x8b\x22\x0c\x00\x7d\x5b\x64\x27\x26\xa4\x08\xfe\x2f\xab\x69\xeb\xb3\xbd\x07\x2b\x34\x9f\x4d\xc3\x37\x7e\xe7\xcc\x75\x29\x34\x25\x42\x15\xd2\x39\x89\xbd\x3c\xd0\x2c\xe9\x99\xad\xec\x97\x84\x99\x3f\x4c\x19\x94\x08\x15\xf3\x9c\x9e\x22\x92\x47\xf5\x20\x5c\x36\xcb\xa4\x4e\x71\x42\x66\x36\x92\x89\xb4\xa7"}, -{{0x18,0xef,0x46,0x4e,0x28,0xf8,0x7f,0xfc,0xfa,0x4d,0x3a,0x9c,0x09,0xa2,0x29,0x10,0x95,0x1b,0x8c,0x71,0x9f,0xda,0xcd,0xb5,0x6d,0xe6,0x2c,0x4b,0x40,0x6d,0xf0,0x0c,},{0xc5,0x06,0x4c,0x9d,0x43,0xee,0x2d,0xa7,0x5b,0x06,0xbb,0x09,0xc7,0x72,0x67,0xdb,0xd0,0xd3,0x91,0x28,0xf1,0xcd,0xc6,0xbf,0xa4,0x51,0xa0,0x3e,0x93,0xaf,0x4a,0x70,},{0xd1,0xe7,0xf1,0x6e,0x8e,0x59,0x7d,0x42,0x8a,0xde,0xa6,0x55,0x91,0xd5,0x51,0xb5,0x4b,0x66,0x7a,0xff,0x20,0x20,0xc4,0x64,0xf7,0xf4,0xe5,0x3c,0x47,0x73,0xf7,0x04,0x33,0x24,0x9a,0x3c,0x71,0xb4,0xd1,0x1c,0x89,0xc3,0xfa,0xa8,0x92,0x80,0x92,0x27,0xb9,0xf2,0x9e,0xf4,0xf7,0xf5,0xd0,0x20,0xd4,0x67,0x4d,0x40,0x21,0x35,0x94,0x05,},"\x9c\x82\x57\x07\xd9\x35\x83\x65\xab\x9d\x38\xf7\xe7\x28\xd6\x28\xaa\x72\x2a\x4f\x1a\x20\xa3\x8e\x47\xc9\x99\xff\xf8\xfc\x32\x41\x7f\xbe\x07\x2f\x96\xeb\x6a\x0e\x11\xe4\xda\x9b\x6d\xe9\x61\x54\x45\x28\x0e\x93\xc7\x7a\x36\x34\xd3\xd2\xc6\x87\x98\x56\xc2\x48\xf9\x80\x0f\x60\xa0\xd3\x8d\xc1\xce\xa8\xb7\xf3\x1f\x28\x6c\xb0\x37\x48\x27\xb4\xc6\xba\x14\x4a\x66\x94\xf2\xb9\x08\xea\xd6\x8d\x18\x34\x01\x24\xcb\x59\xcf\x17\x01\x86\x3b\xd4\xf3\xef\xc7\x09\xf3\x62\x7a"}, -{{0xc9,0x11,0xbd,0xf2,0xf9,0xe7,0xcc,0x5f,0xff,0x35,0xc9,0x6e,0x15,0xcc,0x12,0xea,0xfd,0x05,0xab,0x0d,0xb3,0x1f,0x64,0x9f,0x74,0x08,0xac,0xd0,0xca,0xda,0x76,0xe0,},{0xde,0x44,0x69,0x6c,0xd6,0xbd,0x2c,0xbe,0x9b,0x11,0xa0,0xef,0x18,0xb8,0x81,0x64,0x80,0x1a,0x96,0x9d,0x5e,0x06,0xed,0x45,0x3e,0xb4,0x00,0x8c,0xce,0x9a,0x57,0x25,},{0xd5,0x84,0xb5,0xda,0x37,0x1a,0xe4,0xf5,0xc9,0x85,0x9b,0x25,0xf7,0x0d,0xc5,0x6c,0x1b,0x7b,0x4e,0x02,0xd1,0xae,0x66,0x36,0x28,0x3b,0x1b,0x7b,0x11,0x21,0x7a,0xfd,0xcd,0xf6,0x5d,0x1b,0x49,0xca,0x2c,0x8e,0xf1,0x79,0x66,0xe9,0xbc,0x65,0xf1,0x0c,0x31,0x0b,0x77,0xbb,0x5d,0xf7,0xaf,0xf5,0xec,0x1b,0x37,0x9a,0x2c,0xe5,0x5d,0x0d,},"\x76\xc4\x71\x24\x1d\x17\x19\x29\x84\xb0\x03\x62\x69\x6e\x4d\x9d\x4d\x2b\x7f\x83\x9c\x20\x64\x11\x7e\x50\xa1\x59\x8f\x3a\x11\x72\xb1\x6c\x55\xe5\x39\x68\x66\x08\x47\x52\x02\x4f\x3a\x7e\xb6\x8b\xb3\xff\xdb\x80\x97\x9a\x0a\xf6\xd0\xf6\xaf\x26\xb6\xf0\xbc\x0c\x03\x84\x43\x3b\xcf\xd4\x4c\x75\xeb\x65\x4a\x8a\x82\x25\xcb\x9c\x4a\x7f\xb3\xc8\x24\xc3\xaf\x61\x25\xfd\x46\xdb\x28\x7e\x70\x49\x2d\x15\x46\x32\xcb\x8f\x62\x43\x26\x59\xd9\x58\xd6\x28\x1d\x04\xa5\x4f\x5f\x5f"}, -{{0xd3,0x70,0x32,0x99,0xc4,0x1d,0xb3,0x6d,0x77,0xdd,0x3a,0x49,0x54,0x1f,0x3f,0xb2,0x1d,0x0b,0x2b,0xad,0x1f,0x6e,0x07,0x4a,0xff,0xd9,0x6f,0x1c,0x40,0xd0,0xf9,0x27,},{0x86,0x2c,0x5e,0xf6,0x16,0xa5,0xf0,0x66,0xfd,0x87,0x75,0x8a,0x56,0xab,0x45,0x05,0x6f,0xea,0x4b,0xd3,0x3f,0x00,0x8b,0xe2,0x4f,0x7b,0x54,0x0e,0x09,0x5e,0x14,0x8e,},{0xdf,0x28,0x27,0x71,0x21,0xea,0xc4,0x46,0x30,0x08,0x4c,0xce,0x75,0x91,0x7a,0xe9,0xf6,0xbe,0xc6,0x5a,0xf5,0x57,0x2d,0xc3,0x07,0x19,0xbd,0xe6,0x61,0xcf,0x69,0x6b,0x85,0xb8,0x67,0x2d,0xd4,0x98,0x3c,0xab,0x30,0xbd,0x05,0xcc,0x3a,0x11,0x9d,0x7d,0xb9,0xba,0xbd,0x52,0x2d,0x7b,0x3a,0x6b,0xcf,0x38,0x86,0xec,0xd2,0x5e,0x08,0x0f,},"\xac\x92\xed\xbe\x22\x25\x7b\xb0\x6d\x94\xaa\x95\x0e\x62\xd1\x8c\xa2\xac\x0a\x8f\xc1\x06\x00\x0d\x22\x31\xf8\xa1\x3b\x8d\x7a\x20\x9c\xcd\x8c\xc4\x9a\x6c\xd6\x8a\x7f\x36\xc0\x2f\xb8\xf7\x28\xd1\x55\x95\x16\x7f\x0b\xa8\xcf\xe9\x5c\x8a\x1e\x43\x5f\x32\x75\x13\x01\x4a\xc4\x28\xb7\x5d\x4f\x72\xe7\xc8\x34\xdd\x70\xe1\xa4\x48\xf1\x84\x7d\x34\x98\x47\x5f\x74\xe3\xd9\x33\x4d\xc7\xdc\xc4\xfe\xd7\x2b\xf6\xc7\xfe\x3b\x1d\x4f\x53\xd4\x29\x61\x6f\x1d\xf4\x4f\x19\x73\x31\x58\xb6"}, -{{0xd4,0x11,0xcd,0x33,0x57,0x6d,0x0e,0xfe,0x9e,0xc4,0x13,0xcc,0xda,0xab,0xd4,0xfc,0xba,0xfe,0xc0,0x1a,0x3a,0xf4,0xb3,0xcb,0xe3,0x4f,0x8b,0x05,0xef,0x8b,0x59,0xba,},{0xe8,0x70,0x34,0x4d,0xf9,0x8d,0xd3,0xa8,0x70,0x2c,0x45,0x19,0xbf,0x9e,0x8b,0x35,0xa9,0xd1,0x89,0xe7,0x46,0xf7,0x20,0x3d,0xbb,0xf9,0xbb,0xfa,0xb2,0x2d,0x6f,0x63,},{0x83,0x46,0x0d,0x15,0x46,0x1d,0x67,0x17,0x71,0x0b,0xaf,0xd6,0xa4,0x7a,0x1e,0xaa,0x90,0x0a,0x80,0xf2,0xbf,0x8b,0x8a,0xae,0x24,0x68,0x77,0x36,0x14,0xee,0x84,0xbd,0x62,0x8c,0x97,0x17,0x47,0x63,0x68,0xef,0x36,0x40,0xcf,0x76,0x0a,0xca,0xc8,0x3a,0xd6,0x02,0x32,0xa7,0x69,0x63,0xb7,0xd5,0x25,0x88,0xb1,0x1d,0xc0,0x04,0xd7,0x0d,},"\x11\xd2\xc2\xa7\xf0\x19\x09\x88\x12\x66\x96\x43\x1b\x4b\xbc\xd9\x0a\xb7\xb5\x6a\x32\xda\x64\x04\xae\x44\x6a\xa7\x62\xa4\xdd\xc6\x60\x94\x97\x15\x38\xee\xb8\x5b\xde\x04\x70\xa5\x10\xbe\x0d\x6d\x85\x78\x0e\xe7\x30\xa9\x85\x41\x38\x72\x8a\xe6\x81\x61\x62\x26\x8d\xa8\x52\x85\x8e\xae\xd4\xec\x74\xc7\xac\x62\xe6\xe7\x09\x6d\xc0\x02\xdf\x0b\xdf\x5f\xa4\x0d\xa5\x65\xb4\x1d\x18\x1a\x3f\x0a\xd0\xc5\xe0\xb9\x76\x74\x3e\x31\x5d\x9d\xb8\xed\x41\x60\xab\xe6\x9c\x13\xa2\xb3\xf0\x9a"}, -{{0xe1,0x0a,0x2f,0x13,0x80,0xc3,0xe4,0x72,0x0e,0x8a,0x87,0x07,0xa9,0xbc,0xb2,0x5a,0x0f,0x58,0x27,0x0d,0x70,0x59,0xcd,0x76,0x26,0xc7,0x15,0x34,0x47,0xed,0xfb,0x87,},{0xa3,0xc7,0x17,0xac,0xab,0x36,0x6a,0x40,0xb5,0x11,0x87,0xbb,0xf3,0x5b,0x2d,0x15,0xe9,0x7c,0xfe,0xac,0xd7,0x34,0x9c,0x06,0xef,0x1c,0x91,0xac,0x93,0xe9,0x06,0x56,},{0x09,0x4b,0xf6,0xf9,0x53,0xca,0x0e,0xb7,0x7d,0xf4,0x51,0x29,0xb7,0xbf,0x10,0xd1,0x92,0xcf,0x6d,0xde,0xae,0x94,0xad,0x62,0x02,0xb8,0xea,0xcf,0xbe,0xc1,0x19,0xe5,0x29,0x15,0x78,0xfe,0x64,0xa0,0x84,0xae,0x60,0x0f,0xe0,0x7e,0xfd,0xb8,0xa7,0x82,0x61,0x0d,0xbd,0xb0,0xb4,0x9e,0xb5,0xf2,0xa4,0x6c,0x43,0x23,0x55,0x55,0x2f,0x01,},"\x13\x52\x12\xa9\xcf\x00\xd0\xa0\x52\x20\xbe\x73\x23\xbf\xa4\xa5\xba\x7f\xc5\x46\x55\x14\x00\x77\x02\x12\x1a\x9c\x92\xe4\x6b\xd4\x73\x06\x2f\x00\x84\x1a\xf8\x3c\xb7\xbc\x4b\x2c\xd5\x8d\xc4\xd5\xb1\x51\x24\x4c\xc8\x29\x3e\x79\x57\x96\x83\x5e\xd3\x68\x22\xc6\xe0\x98\x93\xec\x99\x1b\x38\xad\xa4\xb2\x1a\x06\xe6\x91\xaf\xa8\x87\xdb\x4e\x9d\x7b\x1d\x2a\xfc\x65\xba\x8d\x2f\x5e\x69\x26\xff\x53\xd2\xd4\x4d\x55\xfa\x09\x5f\x3f\xad\x62\x54\x5c\x71\x4f\x0f\x3f\x59\xe4\xbf\xe9\x1a\xf8"}, -{{0xb2,0xe6,0x97,0xb3,0xd3,0xef,0xec,0x97,0x6e,0xf3,0x36,0x95,0x30,0xc7,0x92,0x71,0x7b,0xdb,0xb4,0x28,0xd9,0xed,0x0c,0x11,0xec,0x0e,0xa9,0xb2,0xe5,0xf3,0x9f,0x82,},{0xc4,0xd2,0xe4,0xb3,0xc2,0x36,0xd6,0xc9,0xb8,0xc7,0x4f,0xa3,0x84,0x61,0x2c,0x47,0x10,0xd8,0x3a,0xa1,0x6a,0xd7,0xef,0x01,0xfb,0xb7,0x42,0x1d,0x4f,0xb3,0xf0,0xf6,},{0x50,0x47,0xfa,0x38,0x19,0x7b,0x83,0x28,0xe7,0x8d,0xd8,0xa1,0x0e,0x96,0x6a,0xfb,0x7b,0xd3,0xd4,0x36,0x08,0x28,0x0f,0x1c,0x25,0x7d,0x25,0xca,0x43,0xbc,0x1c,0x06,0xe9,0x4a,0x57,0x47,0xab,0x62,0x15,0xec,0xe5,0x4c,0xde,0xff,0x8c,0x56,0x56,0x7d,0x70,0xd2,0xf9,0x1f,0x9e,0xc8,0xc2,0x60,0xaa,0x10,0x80,0xa6,0xab,0x5a,0x7a,0x02,},"\x7b\x43\x62\x32\xac\x21\x11\xa8\x40\x59\x51\x0c\x48\x36\x25\x88\xfc\xb7\x38\x34\x26\xbe\x5e\x6f\x62\xf3\x72\xe4\xf7\xcc\xa8\x3c\x81\xc2\x35\x7f\x9b\x54\xf4\xa1\x52\x91\x06\x5b\x6d\x41\xaa\xd1\xea\x93\xcf\xfa\x77\x6b\x9a\xca\xa5\x8a\xfe\x2b\x51\x64\x4b\x97\xaf\x9a\x3e\x53\xf8\x4e\x40\xaa\x6d\x86\x05\x1e\x69\x14\xcd\x03\x9d\x41\x70\xa9\xa5\x26\xdd\x69\x95\x5f\xf5\x07\xc3\x3f\x74\xe2\x17\x65\x91\xfb\x0b\x3c\xd7\xf0\x0e\xe4\x18\xf2\xc2\x58\xa9\x98\x1c\xcc\xee\x72\xf0\x1c\x84\x30"}, -{{0x19,0xa6,0x79,0xa7,0xa9,0x05,0xa1,0xe2,0xb3,0x03,0x8e,0x6e,0x41,0x8b,0x3d,0xa9,0x7c,0x30,0x89,0xc7,0xcd,0x35,0x1e,0xa0,0x7b,0xc8,0xd1,0xaf,0x64,0xea,0xcc,0x46,},{0x19,0xf0,0x83,0x61,0xf4,0x69,0xb4,0xae,0x1e,0x0c,0xeb,0x94,0xf4,0x7a,0x7d,0xe7,0x31,0x74,0x10,0xa9,0x2d,0xd0,0x13,0xb1,0x6a,0xe0,0xd0,0x53,0x2f,0xa4,0xb3,0xef,},{0x43,0x47,0xb7,0xb4,0xf7,0xc3,0xc4,0xdd,0x31,0x5b,0x83,0x84,0xa0,0xb0,0xca,0xee,0xd8,0x4b,0xda,0xbe,0x24,0xb2,0x91,0x5f,0x12,0x51,0x2d,0xfd,0x04,0x77,0x0f,0xc9,0x96,0xa1,0xbf,0xb7,0x29,0xaf,0xef,0x9e,0xdd,0x61,0x14,0x47,0x08,0x1a,0x53,0x30,0x61,0x7e,0xae,0xa1,0xc1,0xda,0xb1,0xbf,0x13,0xce,0xa8,0x99,0x72,0x04,0x91,0x0c,},"\x98\x0c\x7b\x4d\x29\x39\x06\x1a\xc7\xb9\xba\x44\x11\x17\xa1\x94\x85\x66\x17\x81\xa4\x08\x30\x67\xc5\x5a\xcf\x93\x02\x6c\x08\x2a\x93\xcc\x12\x4f\x09\x5e\x1b\x4f\x2c\x3f\x6c\x13\x54\x12\xa5\x09\x62\x28\xe8\xa0\x71\xe8\xb4\xb6\x68\xba\x9d\x96\x44\xea\x9f\x4d\xab\xfc\x54\xa9\x85\x6c\x3e\x96\x5e\x63\x63\x39\x5a\xb7\x09\x03\x7d\xda\x22\x9b\xaf\x92\x7c\xd0\x1f\x9a\xf5\xe0\x39\xaf\xc4\x2f\x3c\xec\x63\x4f\x5d\x83\x2d\x2a\xb7\xc7\xca\xd3\xad\x7b\x8c\xf2\x7e\xbd\xac\x69\x84\x31\xad\x82\x36"}, -{{0xf0,0x3b,0x83,0x63,0xee,0x5b,0x0e,0xef,0x70,0x18,0xa4,0x9b,0xc0,0x2a,0xdf,0x73,0x1d,0xa5,0x4e,0xe5,0x0a,0x7f,0x03,0xb8,0x8a,0x29,0xa2,0x08,0x2b,0x18,0x9c,0x43,},{0x31,0x28,0x7e,0xf5,0xa2,0xe6,0x41,0x04,0xab,0x77,0x90,0xb3,0x12,0xf3,0x5c,0x7a,0xd4,0xaf,0x6b,0xeb,0x0d,0x7c,0xeb,0x8a,0x58,0xf3,0x6a,0x54,0xce,0x27,0x2c,0x3e,},{0xe8,0xfa,0x96,0x7e,0x6a,0xfa,0xdf,0x6a,0x87,0x7d,0x87,0xe5,0xf5,0xc5,0x2b,0xb6,0x34,0xb7,0x5a,0x78,0x04,0x19,0x9a,0x2b,0xc9,0xd0,0x27,0xb6,0x3a,0x35,0x65,0x4d,0x9d,0xdd,0x06,0x83,0x04,0x55,0x64,0x1d,0xbf,0xb4,0x9e,0xdc,0xe4,0x2e,0x20,0xe7,0xd4,0x10,0x4a,0x07,0x1c,0x2c,0xbb,0xec,0x23,0x01,0x8c,0x29,0x7c,0xed,0x99,0x08,},"\x24\x19\x1b\x54\x64\xb3\x5a\xc7\xbc\xf4\xa3\x75\xf0\x33\xef\xba\x89\x43\xb0\x9b\x9f\xf0\xfc\x40\x3c\xa7\xaa\xe7\x02\xa3\xcb\xf3\x96\xc5\x13\x1b\xc0\x08\x13\x2c\xf5\xf1\x29\x10\xd5\x86\xdc\x1d\xb9\xc0\x84\x57\x4a\x96\xba\xbe\xe9\x56\x42\xf9\x22\x37\x1c\x03\x82\xec\x04\x02\xa2\x6f\xeb\x14\x2e\x41\x46\xbb\xd3\x36\x0c\x2b\x36\x83\x4f\xe4\x5a\xf5\xe2\x86\x8d\x4d\x56\xfd\xd5\x04\xce\xbf\x0c\x2d\x7f\x57\x91\xb4\x42\x94\x17\xc8\xb6\x5a\x98\xe0\xb1\x5c\x46\x6c\x13\x7f\x41\x05\x24\xfc\xe7\x37"}, -{{0x11,0x08,0x6b,0x0d,0x11,0xe4,0x15,0xab,0x1c,0xe0,0x2a,0xaf,0x8f,0x06,0x21,0xb5,0x44,0x30,0xf6,0xfb,0x13,0x5c,0x74,0xf4,0x0d,0x38,0xe8,0xc6,0x47,0x37,0x06,0x4b,},{0x71,0x66,0xdf,0xbc,0x69,0x1e,0xb8,0xc2,0x01,0x11,0x4b,0xa0,0xd1,0xa2,0xc7,0xb8,0x7f,0x7a,0x1f,0xd8,0xd0,0xb3,0x60,0x58,0xb0,0xd7,0xdc,0xab,0xe1,0xae,0x30,0xda,},{0xe9,0x07,0x45,0x9d,0x5a,0xdc,0xd0,0xd0,0xc3,0x64,0x18,0x58,0x1f,0x19,0xd0,0xee,0xbd,0xa7,0x13,0x8e,0xbd,0x9f,0xaa,0x0b,0x26,0x22,0x01,0xf4,0x58,0xc8,0x56,0x31,0x0b,0xb7,0x7f,0x4c,0x7d,0xe9,0x22,0x49,0x5d,0xcf,0xe8,0xb2,0x48,0xed,0xa2,0xad,0x0d,0xf6,0xa7,0x3f,0x47,0xbb,0xfb,0x89,0x4b,0xaa,0x7d,0x88,0x69,0x87,0x58,0x02,},"\x4b\x5b\x29\x36\xc5\xe3\x60\xa3\x84\x55\x50\x37\x21\x07\x8f\x8a\xdb\x40\x4a\x7e\xe7\xec\xc1\x48\x01\xdc\x87\xa6\x7a\x15\x2b\x76\x95\x69\xfb\xea\xc0\xaf\xa2\x5a\x20\x70\xa1\x68\x6b\x90\x0a\xc1\x63\x3d\x49\x98\x08\xcd\xb2\xe8\x1c\xe3\x91\x6d\x5a\x3c\x04\xd1\x9c\x5b\xb2\x69\x9a\x66\x2b\x8a\xba\x4a\xf9\x4d\x39\x0b\xac\x7c\xcc\x8e\xc9\x10\xed\x2a\xcd\xf8\x6e\xbb\x71\xad\xb6\x01\x87\x78\x85\xee\xf3\xc9\x16\x62\xfc\x30\x73\x8e\x35\x2c\xc7\x43\x53\xcc\xf8\xd8\xed\xee\xfa\xcc\x04\x2c\x10\xa0\xe5"}, -{{0xef,0xce,0x76,0x67,0xa8,0xef,0x91,0x22,0x8c,0xae,0xd1,0x4e,0xb4,0x77,0xa3,0x45,0xe5,0xe8,0x23,0x92,0x34,0x08,0x08,0x48,0x76,0x0e,0xd0,0x97,0x07,0x13,0xfa,0x86,},{0x91,0x93,0x05,0x5a,0x84,0xdf,0x1e,0xac,0xca,0x28,0xce,0x2a,0x08,0xc2,0xa0,0x7a,0x50,0xf0,0x4c,0x02,0x4e,0xcf,0x1f,0xe4,0xa4,0x7d,0x2e,0xfb,0xaf,0x63,0xed,0x58,},{0xe5,0xa6,0x31,0x24,0xdb,0x16,0x96,0xb6,0x41,0x40,0xb6,0xe9,0x61,0x2f,0xa9,0x58,0x7b,0x3e,0xef,0x71,0x01,0x09,0x39,0x8d,0x44,0xba,0x0c,0xa6,0x3c,0x0e,0xba,0xd0,0x6f,0x0a,0x6c,0x89,0x94,0xea,0x34,0xb3,0xa2,0xaf,0x91,0xa8,0x9b,0xf4,0x1a,0xe6,0x14,0xd7,0x72,0x7d,0x71,0x6f,0xd4,0x2f,0x8b,0x92,0xe1,0xac,0x64,0xfd,0xbf,0x03,},"\xaa\x1b\xc8\x0d\x7b\xcc\x1d\x94\xa2\x3a\x57\xce\xdf\x50\x27\x48\x24\x77\xdc\x46\xb8\x68\x90\xbc\x0e\x5a\xc2\x9a\xe6\xc9\x1b\xbc\x43\x13\x03\x48\x79\x73\x05\xf7\x55\x43\x58\x0a\x8a\x06\x9b\x34\x8a\x7b\xd8\xfc\x3e\x01\x52\x30\xb7\xc1\x94\x0c\x7f\x80\xa8\x2b\x12\x90\x09\x10\xdb\xcf\x06\x30\xda\x03\xf0\x81\xd4\x4c\x7f\x95\x5d\x4a\x11\x72\xf5\x6e\xcc\x7c\x5a\xc6\x46\x69\x6b\xff\xdf\x4e\xb6\xd8\x8b\xdd\x9c\xc3\x84\x35\x28\xb7\x25\x83\xab\xb3\xba\xd0\x2e\x56\xef\x76\x46\xee\xd5\x13\x95\x51\xcd\xeb"}, -{{0x88,0xfc,0xca,0xa9,0x6a,0xd8,0x84,0xd1,0x16,0x5b,0xe7,0x1d,0xd0,0xc4,0xf5,0xf8,0xf4,0x42,0x1c,0x60,0xfb,0xfa,0x49,0x8b,0xfe,0xe9,0xb9,0x67,0x46,0x24,0x43,0xbd,},{0xc7,0x5c,0xb0,0xe0,0x23,0x7b,0x45,0xb8,0x65,0x6e,0xea,0x9f,0x3d,0x1a,0x9d,0x4a,0xcd,0x01,0xa1,0x03,0xaa,0x26,0x9b,0xb2,0x4f,0xd5,0x41,0x22,0xfd,0x81,0xf2,0xac,},{0x27,0xd3,0xa1,0x97,0xcc,0x99,0x94,0x21,0x20,0x63,0xbc,0xe8,0xd7,0x99,0xe7,0x7b,0x68,0x53,0xb7,0x35,0x5e,0xbe,0x36,0x9b,0xcf,0x18,0x89,0xa4,0x18,0xa8,0x2c,0xaa,0x3a,0x79,0x87,0xa6,0x63,0xf6,0x21,0xde,0xfe,0x86,0xb3,0xac,0x4a,0xd4,0x4f,0xae,0xed,0x16,0xc9,0x11,0x6a,0xce,0x28,0xfc,0xcf,0x91,0x55,0x57,0xfa,0x77,0x99,0x03,},"\x9d\x0e\xac\x98\x55\x6b\xfa\x86\x72\xc3\x57\x05\xd1\xd6\x1a\xc4\xd0\xfc\xa1\x9d\xc0\xd9\x93\x01\x58\x77\x85\x7d\x27\xfd\x80\xf7\x4a\xca\xce\x66\x6c\x56\x34\x85\xd8\x1e\x53\x60\x3a\x6a\xef\x40\x87\x5f\xa5\x51\xcc\x10\x5f\x2c\xc1\x0b\x39\x69\x46\x79\xcd\xf4\xa6\xb0\x73\xbc\x88\x64\x5f\xc5\x1a\x36\xda\x17\x9d\x3d\x1e\x3c\x77\x22\x45\x4c\x5e\x73\x57\x7c\x61\xaa\x7d\x14\x8c\x4b\xa5\x0e\xa4\x6c\x56\xa1\xc3\xb3\xb3\xc4\x70\xf9\x31\x00\x49\x4e\x08\xbc\x55\x14\xac\x76\x3a\x85\x48\x3c\x42\xc7\xcd\xc2\x7c"}, -{{0x67,0x0b,0x30,0x62,0x6f,0xe3,0x67,0xd8,0xb4,0x5f,0x43,0x73,0x3d,0x6f,0x25,0xb3,0x7e,0xcc,0xbc,0xb5,0x51,0x96,0x3f,0x0a,0xc8,0xb6,0x66,0xb4,0x80,0x41,0xc7,0x2d,},{0x65,0xaa,0x4c,0x6d,0x4b,0xa0,0xab,0x34,0xbc,0x75,0xb3,0x9f,0x09,0x52,0x7c,0xa6,0xf2,0x42,0x5f,0x52,0x41,0x5c,0xdf,0xfd,0xf2,0xdf,0xf2,0x73,0xf8,0xea,0x61,0x2c,},{0x1b,0x6b,0x43,0x77,0xd2,0xb9,0x8e,0x0f,0x9d,0x24,0xae,0x8d,0xfe,0x30,0xe2,0x39,0x6e,0x20,0x04,0x38,0x0d,0x34,0x31,0x48,0x8e,0x58,0x43,0xcf,0x8d,0x2d,0x7a,0x00,0x70,0xab,0x21,0xf8,0xa3,0xb5,0x1c,0xe8,0x4d,0x2f,0x4b,0xa2,0x09,0xf7,0x39,0xf9,0x22,0xbe,0xbf,0x79,0x80,0x96,0x69,0x3f,0x56,0x22,0x87,0x3d,0x79,0xae,0x6f,0x04,},"\xd0\x0b\xcc\xa7\xe1\x84\xd1\x0e\x1f\x1f\xe4\x20\xb5\x06\x39\xe1\xd5\xde\xba\x52\xa7\x51\x23\x6e\x68\xc5\x9b\xb4\xbf\xf9\x80\x2f\x5f\xc1\x65\xed\x42\xfd\x6d\x53\x46\x70\xa7\xc6\xfb\x60\xe4\x30\x7d\x94\x79\x15\xa2\x48\xbf\x2f\x93\x46\x5c\x2c\xb4\x4d\x8f\x45\x3d\x2c\x01\x5a\xfb\xc8\xed\x58\x81\x8e\xa5\x17\x26\xa2\x51\x77\x93\x0e\x9e\xa1\x92\xef\x45\x14\xf4\xbb\x0e\xb4\xe0\xf5\xd4\xae\x3c\x46\xe3\x57\xc8\x11\x87\xf7\xed\x17\x47\x33\xff\xf9\x59\xc3\xf9\xfa\xe6\x48\x6c\xfa\x13\x56\xa9\x56\x99\x21\x1d\xe5"}, -{{0x81,0x3c,0x4d,0xae,0xd6,0x7a,0x19,0x0d,0x68,0xbb,0x63,0x5d,0x73,0xaf,0x6d,0xa7,0x4f,0x32,0xfd,0xf7,0xc4,0x8c,0xca,0x6e,0x59,0x26,0x29,0x46,0xb8,0xe8,0xc7,0x1f,},{0xa2,0x09,0x54,0x57,0xd7,0x69,0x70,0x20,0xe2,0xb8,0x84,0xd9,0x5a,0x96,0x57,0x8c,0x2a,0x90,0x0a,0x76,0x66,0xac,0x0d,0xc7,0xbd,0x38,0xf1,0x93,0x1d,0x79,0x45,0xd8,},{0xb4,0x46,0x57,0x4f,0xf6,0xa4,0xbd,0x2b,0x57,0x2e,0x48,0x7c,0x4a,0xb4,0x43,0xca,0x64,0x10,0x75,0x16,0x8a,0xa4,0xe1,0x09,0x2f,0x71,0xf3,0x0b,0xdb,0x06,0x8c,0xe4,0x6a,0x39,0x5e,0xfe,0xe1,0xee,0x66,0x0b,0x9f,0xac,0x26,0xd5,0x41,0x09,0x72,0x2c,0x15,0xcd,0xb7,0x91,0xbf,0xb8,0x7f,0xff,0x63,0xc6,0x59,0x6a,0xd4,0xf2,0x27,0x0c,},"\xce\x54\xcb\x04\x50\xe6\x89\xa0\xdb\xef\x78\x53\x08\xb3\x17\x74\x72\xfc\xd6\xd3\x82\x03\xe5\x8a\x05\x90\xb3\x1f\xa2\x53\xf9\xea\x59\x0b\xe5\x36\x8a\x92\x2d\xe8\x8b\x63\x45\x01\x02\x68\x44\x43\xfb\x81\x89\xe6\x01\x28\x20\x03\x32\x3b\x89\xc8\x1e\x92\xea\xef\x2b\x5d\xdc\x4a\x55\xc5\x3f\xa3\xcf\xad\x41\x60\x24\x8b\x3c\x28\x6f\xf8\x0d\x31\xd1\x61\xb7\xb8\xde\xe7\x13\x55\x2b\x56\xf1\x50\x7f\xb7\x2e\xad\xfa\x89\x05\x4e\x9d\x16\x00\xac\x87\x4c\x4b\x0a\x96\x10\x04\xeb\x6d\x0d\x4b\xfd\x2e\xcb\x9c\x73\x4f\x00\xba"}, -{{0x84,0x00,0x96,0x2b,0xb7,0x69,0xf6,0x38,0x68,0xca,0xe5,0xa3,0xfe,0xc8,0xdb,0x6a,0x9c,0x8d,0x3f,0x1c,0x84,0x6c,0x8d,0xce,0xeb,0x64,0x2b,0x69,0x46,0xef,0xa8,0xe3,},{0x98,0xbe,0x21,0x00,0x19,0x93,0xa7,0xeb,0x1a,0x12,0x77,0xff,0x74,0xc1,0x55,0x04,0x18,0x3d,0x25,0xfd,0xfc,0xc0,0x5f,0x0d,0x4d,0xea,0x89,0x2f,0x6e,0x30,0x18,0x90,},{0x0a,0xd7,0x1b,0x00,0x25,0xf3,0xd9,0xa5,0x0d,0xb3,0x38,0x41,0x4d,0x6d,0x67,0x0e,0x77,0x99,0xb7,0x27,0x0a,0x84,0x44,0xf6,0xae,0x7f,0x12,0xae,0x7e,0xb7,0x1b,0xd0,0x3f,0xfd,0x3c,0x4f,0x36,0x63,0x1f,0x69,0xfd,0xcc,0x40,0x61,0x46,0x8f,0xf5,0x82,0xed,0xe4,0x95,0x24,0x3e,0xf1,0x36,0x1a,0x3b,0x32,0x95,0xfa,0x81,0x3b,0xa2,0x05,},"\xf7\xe6\x7d\x98\x2a\x2f\xf9\x3e\xcd\xa4\x08\x71\x52\xb4\x86\x4c\x94\x3b\x1b\xa7\x02\x1f\x54\x07\x04\x3c\xcb\x42\x53\xd3\x48\xc2\x7b\x92\x83\xac\xb2\x6c\x19\x4f\xd1\xcb\xb7\x9e\x6a\xfc\x32\xff\x68\x6b\x55\xb0\xb3\x61\x72\x18\xdc\xf3\x93\x16\xb4\xb6\x6b\x3c\x8c\x0d\x67\x26\x7a\x86\xdb\x8a\xdf\x37\x50\x80\x1b\xcf\x93\x27\xd4\xc2\x54\x41\xb9\x61\x97\x83\x2b\x4c\xde\x0e\xac\x3f\xf2\x28\x92\xa2\xf0\xbc\x17\xc2\xc2\x13\xc0\x23\x77\xa3\x33\xe3\x08\xed\x27\x16\x58\x04\x93\x83\xb7\xe2\xe5\x7b\x6b\x8b\x12\x55\x12\xe0"}, -{{0x62,0x88,0x72,0x20,0x35,0xd1,0xea,0x69,0x9b,0xc7,0xcf,0xdf,0x18,0xd8,0x96,0x25,0x42,0x31,0x80,0xb6,0x83,0xfa,0x74,0x63,0x9f,0x4f,0x30,0xf1,0x53,0x59,0xcc,0x85,},{0xe1,0x7f,0xaa,0x01,0x95,0x72,0x86,0x1a,0x06,0x4e,0x1b,0xc5,0x71,0x25,0x6d,0xea,0x14,0x68,0xf3,0xa4,0x85,0x90,0xa8,0x91,0x38,0xaa,0xa8,0x59,0x25,0x08,0x0c,0xd7,},{0x9d,0xec,0x92,0xb6,0xe8,0x9a,0xdb,0xe8,0xf4,0xe1,0xb5,0xe9,0x3a,0xc4,0xfc,0xf9,0x57,0xde,0x7d,0x19,0x70,0xa2,0x26,0x77,0x0e,0xc4,0xed,0xa6,0x47,0xc8,0xe3,0xb3,0xdf,0xfb,0x27,0x31,0xa3,0x9e,0x16,0xe4,0xa0,0x11,0x9d,0x36,0x62,0xa9,0x37,0xe5,0x60,0x52,0x24,0x91,0xec,0x7a,0x16,0x96,0xbe,0x04,0xc0,0x76,0xb1,0x2e,0x35,0x01,},"\x8b\x6c\xaa\xca\xc5\x1d\x89\x49\xfb\x86\xac\xbc\xb1\xb9\x9d\x85\x9f\xf6\x7c\x64\x14\x7b\xc1\x21\x69\x09\xdc\xab\x07\xee\x6e\xf0\x9f\x40\x38\x63\x32\x73\x94\x68\x9d\xc3\x4a\xbc\x77\x8f\xcb\x5c\x1f\x50\x91\xac\xf5\xa0\x8f\x9d\x84\x22\x11\xd1\xae\x2e\xb4\x0b\xe9\xbb\x8d\x66\x79\x07\x74\x71\x54\x7a\x6c\x71\xff\x77\xb5\x19\xd4\xb7\x10\x8e\x32\xbc\x46\x25\x1c\x60\xde\xe8\xe3\x32\xb6\x22\x93\x16\xe6\xd5\x7c\x22\xab\x82\x6f\xf1\xbc\x33\xf2\xb0\x21\x38\x07\xc1\x92\x80\xaf\x11\x0f\xd2\x6e\xe2\x74\x68\x20\x1c\xff\x49\xcb"}, -{{0x13,0x03,0x8a,0x3a,0x65,0xef,0x32,0x75,0x9a,0x9c,0xd9,0x03,0xac,0xb5,0x54,0xb2,0x52,0xde,0x00,0xe7,0xcd,0xb7,0x7b,0xbe,0xd1,0x97,0x0b,0x20,0x68,0x0e,0xe1,0x7b,},{0xb6,0xa3,0x08,0xe6,0x7f,0x9b,0x46,0xc6,0x64,0x99,0x45,0x6a,0xb5,0xcd,0x13,0x5c,0xb2,0xfe,0x84,0xa3,0x2e,0xb0,0x45,0x35,0x86,0x26,0x60,0x4d,0xa4,0x12,0x2c,0x8f,},{0x52,0x61,0x55,0x8e,0xcc,0x3c,0x98,0xff,0x36,0x35,0x1f,0x42,0xf5,0x04,0xca,0xd4,0xa3,0x2f,0xfd,0xa5,0xa7,0x44,0x56,0x09,0x60,0xb4,0xc1,0x06,0xe4,0x49,0x2f,0x02,0xe2,0x04,0x78,0x88,0x7a,0xfe,0xe4,0xf7,0x70,0xf0,0x55,0x97,0xa7,0xe3,0x88,0xca,0xce,0xae,0x80,0x5a,0xe3,0x51,0xe0,0xe4,0x5e,0x8e,0x57,0x8e,0x6a,0x6f,0xf2,0x0c,},"\xdd\xf0\x0b\x40\x33\xa2\xa0\x88\x02\x2d\xab\xe9\x33\x56\x43\x2f\x50\xdd\xc6\xc6\xe1\xa6\x59\xdc\x1a\x93\x12\x4a\x4c\x2f\xff\xfd\x18\x27\x65\xa2\xf5\x6c\x43\xea\x0b\xfd\x8d\xe8\x01\x50\x60\x88\x9a\xe6\x94\x1c\x3f\x3e\x25\x5d\x44\x21\xa1\xc3\x62\x01\xbe\x84\x6a\x27\x38\xa7\x1f\x12\x0c\xad\x59\x8c\xa8\x52\x7d\x70\xff\x8d\x5a\x09\x93\xb5\x5c\xb5\x15\x35\x17\x11\x0a\x41\x96\x2d\xaf\xf4\x22\x50\x15\x8f\x20\x96\xd1\xdd\xaf\x71\x86\xe5\x02\x98\xcb\xe5\x1f\xcb\x42\x9c\xbe\xa4\x11\x29\x3f\x8a\x7b\xd9\xcf\x06\x9f\xa2\x37\xe4"}, -{{0xb9,0xde,0x5b,0x06,0x3d,0x3c,0xa3,0xa7,0x73,0xf1,0x14,0x94,0x1b,0x2e,0x42,0x27,0xc0,0x75,0x11,0xc0,0xf5,0xc0,0x60,0x17,0xb9,0xc8,0x84,0x50,0x18,0xf2,0x34,0x32,},{0x52,0x95,0x24,0x3c,0x86,0x46,0xe0,0x96,0x67,0x4d,0xda,0x15,0x97,0x9b,0x32,0x2b,0x9d,0xd0,0xfa,0xf2,0x7d,0x02,0x4a,0x0e,0xd5,0x77,0x13,0x34,0xe1,0x17,0x9e,0xd2,},{0x92,0xba,0x76,0x0d,0x14,0xd1,0x41,0x5c,0xfa,0xf2,0x18,0xca,0x84,0x70,0x14,0x08,0x8a,0xe5,0x1a,0xd8,0x21,0x11,0x3a,0x6f,0x86,0x30,0x35,0x6f,0x7b,0xa8,0x5c,0x00,0x5e,0x23,0x30,0xf1,0x06,0x6d,0x0d,0xf4,0x64,0x80,0x60,0x52,0xa4,0x17,0x46,0x10,0x05,0x04,0x62,0xf3,0xe0,0x13,0xd7,0x02,0xe7,0xc7,0x71,0x85,0xa0,0x32,0x58,0x0b,},"\x94\x93\xcc\x23\x89\x6b\x84\x09\x60\x46\xae\x10\x53\xaf\xe3\x94\x99\xe9\x42\x42\x54\xb3\x66\xfe\x14\x3f\x4d\xa3\x21\xe2\xdc\x9e\x47\x84\x20\x8e\x12\xa5\x42\xd8\x99\x82\x8d\xde\x7e\xff\x62\x5a\x7f\x12\x41\x69\x90\xc2\x84\x1f\xfb\x09\x5b\xf9\x4c\x0c\x61\x0e\x5a\x66\x39\x18\xb6\x89\x03\x1c\xcd\x6b\x51\x93\x49\xd0\x4d\xe1\xc2\x12\xca\x2a\x9d\x7a\xbf\x52\xe1\xb4\xfd\x46\x7b\xb6\x65\xb6\x91\x9e\xf8\xf9\x16\x17\xe2\x05\x56\x5b\xf5\x66\x47\xe5\xf8\xd5\x08\xea\x20\x0a\x84\x46\x7f\x8f\xa1\x22\xe7\x4b\xc3\xb9\x97\x9f\x11\x74\xe5"}, -{{0x8f,0xf0,0x29,0x7c,0xc0,0x88,0x42,0xb5,0xe6,0x75,0x52,0xec,0x28,0x43,0xe0,0x43,0x53,0xa3,0x4d,0x74,0xef,0x89,0xb8,0x56,0x5d,0x97,0x20,0x5b,0x74,0xca,0x13,0x3a,},{0x0f,0x7e,0xf9,0x8c,0x5b,0xa4,0xaf,0x98,0x4d,0xfb,0x77,0xbc,0x4e,0x53,0x7b,0x2b,0x39,0xe6,0x27,0x3b,0xb3,0xe7,0xb9,0x5f,0xe1,0xb7,0xe6,0x78,0x19,0x52,0xbd,0x4a,},{0x07,0x83,0x73,0x7f,0x70,0x6e,0x6f,0xf3,0x66,0x14,0xf8,0x50,0x07,0x4f,0xca,0x1f,0x48,0x5f,0x24,0xfc,0xde,0x2a,0x28,0xaf,0x54,0x4f,0x37,0xab,0xd6,0x9b,0x7a,0x58,0x1d,0xef,0xd8,0xc7,0x71,0xb0,0x31,0xe1,0x08,0xd1,0x9d,0x78,0x8c,0x74,0xc5,0xf2,0x0b,0xb3,0xf1,0xc2,0x1c,0xd9,0x2b,0xe3,0x17,0xba,0xcd,0x8f,0x65,0x0b,0x49,0x05,},"\x2b\xdc\x3a\x48\x6c\x5e\x4e\xa6\x2d\xcf\xec\x8a\x9d\x4f\xcf\x9e\xa9\x49\x0d\xbc\xc7\x15\x61\x5d\x58\x49\x0a\x72\xce\x83\x3f\xa2\x23\x87\xca\x50\xa0\x05\x25\x08\xcf\x0a\xff\x1c\xa7\x27\xf0\xfe\xd4\x6f\xfa\x7d\x3c\x8e\x23\xc5\xbb\x01\xd4\x7e\x90\xff\x06\xd3\x85\x8a\x55\x7d\x99\x26\x48\x15\x79\xda\xf4\x38\x4a\xea\x50\xe9\x6e\xc6\x15\xd2\xa3\xbf\x3c\x11\x22\xf1\xf2\x4d\xd6\xed\x98\xa5\xde\x42\x18\x83\x58\x9c\x21\x39\x98\xca\x54\x32\x37\x3e\x68\xbb\xbe\x89\x42\x8c\xa9\x88\x5d\x05\x93\xd5\xe6\x21\x51\x16\xb8\x26\x63\x86\x45\x2b"}, -{{0x05,0x0d,0x55,0x3d,0x28,0x2d,0xca,0x32,0x69,0xc8,0x3c,0x18,0x17,0x68,0xec,0x06,0x7b,0x81,0xc9,0xfe,0x0c,0x94,0xf2,0xa0,0xeb,0xbb,0x0c,0x94,0x2d,0x0f,0xcd,0x7c,},{0x63,0xe2,0x30,0xb0,0x03,0xc5,0x3a,0x56,0x72,0xe8,0x32,0xff,0x7f,0x24,0x43,0x0b,0xe2,0x23,0xe4,0x97,0xde,0x84,0x02,0x33,0xf5,0x95,0xa3,0xe2,0x00,0xc7,0x12,0x7e,},{0x3f,0x0e,0x83,0x76,0x5b,0x31,0xbb,0xe8,0xe1,0xfb,0x92,0xe9,0x67,0x8d,0x6c,0xde,0x57,0x1a,0x03,0xba,0x7f,0x1d,0xcc,0x11,0x28,0x46,0x1f,0x70,0x85,0x25,0x45,0x7f,0x4e,0x0e,0x23,0x53,0xaa,0x2b,0x59,0x8c,0x06,0x3f,0xf1,0xbf,0xfd,0xac,0x91,0x6b,0x5a,0x22,0x00,0x65,0x51,0x56,0x90,0x4b,0x05,0x85,0x57,0x7a,0x16,0x28,0x56,0x0d,},"\x15\xe1\x3b\x8c\x01\x00\x4f\x6a\xa5\xb2\x36\xdb\xb2\x81\x67\x7f\x74\x6d\x81\xe5\x48\xe0\xaa\x80\xf0\xe4\x14\x52\x15\x21\xd8\x56\xcd\x69\x4e\x7c\x91\x52\xbb\x5e\x43\x77\x6b\x60\xf6\xb5\x60\xed\x1a\xd3\xe4\xb3\x90\xdb\xf3\xe4\x6e\xf9\x25\x74\x43\xf3\x9c\x14\x9e\x02\x40\xa0\x2d\x02\x1e\x1e\x3d\x7d\x04\x6b\x26\xfd\x00\x4e\xee\x7c\xa1\x6a\x80\x59\xe1\x26\xc7\x4c\xb3\xf2\x19\x4d\xb4\x7b\xf6\x04\x65\xec\xef\x5c\x70\x4d\x2e\x2c\x75\xe2\xe5\x00\x60\xea\x2a\x31\xcb\x72\xb7\xb3\xc6\xb1\xb5\xec\x72\xab\x38\x00\x40\x85\x28\x1a\x22\xfe\x86"}, -{{0x69,0x49,0x7c,0xd7,0xb4,0xe8,0x68,0xcf,0xa0,0x32,0x8d,0x92,0xbd,0x60,0x52,0xd7,0x72,0xb2,0x76,0x73,0x95,0xc1,0x45,0x95,0xb2,0x79,0x85,0x1a,0x9c,0xdd,0x31,0xaa,},{0x5d,0x27,0x6d,0x62,0x6e,0x23,0x0d,0x18,0xe7,0xbc,0xd6,0x11,0x41,0xcb,0x93,0xc9,0x0e,0xf0,0xf7,0x9e,0x01,0x32,0x12,0x12,0xd8,0x38,0xec,0x71,0x45,0x7b,0x1a,0xac,},{0xbe,0xaf,0xa5,0x83,0x40,0x96,0x09,0x08,0xe8,0xd8,0x6e,0x40,0x32,0x9e,0x3a,0x45,0x23,0xfc,0x7b,0xe7,0x70,0xad,0xdb,0x86,0xe3,0x4c,0x37,0x72,0xf8,0x4c,0xd9,0xfb,0x33,0x8d,0x1f,0x3b,0x65,0xbf,0xcd,0xb0,0x9f,0x35,0xc6,0xda,0x36,0xd1,0xa3,0xad,0xf8,0xf9,0x1f,0x1f,0xfd,0x57,0x82,0xcc,0x83,0x02,0x06,0x43,0x3a,0x08,0x41,0x0d,},"\x53\xcd\x08\x0a\x0c\x61\xf1\xa0\x93\xd3\xb3\xa7\x45\x71\xc2\x96\x30\x3f\x36\x3b\x41\x07\xed\xbe\x88\x0b\x7a\xa9\xdf\xe4\x4a\xb5\xd5\xdc\x5f\x74\xbe\x9c\x8d\x87\x6f\x04\xd7\x54\x65\x34\x91\xab\x51\xb1\x35\xfc\x95\x3f\x71\x28\x7b\x62\xff\x41\xb6\x7c\x74\x2b\xd3\x44\x56\x71\xa9\xd4\xf2\xdc\x17\x4c\xa1\xb0\x33\x5f\x78\x62\x7a\x0d\xd4\xb3\x06\x50\x50\x41\x78\x03\x9e\x73\x93\x63\x85\x10\xff\xe8\x40\x91\xb5\x72\x98\xd3\xac\x90\x01\xc3\x67\xc1\x45\x2f\xbc\xb3\x3d\xc5\x4a\x5d\xc3\x16\xfb\x2a\x52\x70\x76\x4a\x2a\xc8\x20\xa0\xb6\x3f\xbd\xc6"}, -{{0x21,0x65,0xa4,0x86,0xb6,0x12,0xbb,0xff,0x52,0x9c,0xd0,0x03,0x46,0x96,0x4a,0x3c,0xb8,0xcd,0xcf,0xfa,0x51,0xdc,0x3d,0x52,0x4d,0xd5,0xad,0xc5,0xac,0x93,0x6d,0x68,},{0x7e,0xbc,0x83,0x9a,0x46,0x5e,0x14,0xf5,0x89,0x24,0x76,0xe4,0xa1,0x3b,0x39,0x88,0xf8,0x3b,0x3c,0xd2,0x7e,0xf7,0x9e,0x19,0x3f,0x86,0xfa,0x16,0xf3,0x4a,0x1c,0xe1,},{0x7e,0xc6,0xfb,0xa5,0x6b,0xa5,0x24,0x60,0xa1,0xb4,0xf2,0x73,0x86,0x89,0xc1,0x88,0x3d,0xda,0x9a,0xaf,0xfc,0x8b,0xde,0x17,0xcb,0x60,0x29,0xbd,0xce,0x3a,0x0e,0xbe,0x2f,0xff,0xda,0x55,0x93,0x9b,0x70,0xbb,0xd0,0x7f,0xdb,0xf6,0xfc,0x5c,0xda,0x87,0xfe,0xd8,0xba,0x58,0x57,0x5f,0x89,0x4a,0x36,0x6e,0x45,0xe5,0x70,0x5e,0xea,0x09,},"\xb7\x28\xda\x7a\x36\x16\x7c\x60\x85\xbd\x2d\x96\x2c\xf6\x39\x59\xfa\xcd\x95\xc9\xad\x45\x42\x02\x8a\xfb\xa9\x0e\xc9\xc6\xc0\x76\x0b\xda\xe9\x35\x42\x9c\x3f\xeb\x39\x33\xe2\xf0\x00\x42\xc6\x72\xad\x2c\xd7\x34\x8d\x92\xbc\x33\xf8\x17\x51\xe2\x94\xae\x91\x71\xb9\x45\xb1\x93\x14\x4e\xf8\xac\xb9\xa1\xbd\x9a\xbf\x04\x75\xce\x0d\x0a\xc7\x89\xb2\x00\xc3\x2e\x9c\x9a\x27\x36\xb1\x68\x36\x9c\xe5\xf9\x7b\x1e\x8d\x2e\x79\x00\xe1\xa7\x59\x17\x84\x41\xf1\xfc\x43\x05\x64\xae\x12\x9b\xae\x78\x57\x74\x05\x11\xa6\x68\xf3\x2c\x0a\x3b\x07\x7a\x9d\x8b\x19"}, -{{0x1c,0x64,0xad,0x63,0xdd,0x14,0x70,0x34,0x59,0x8e,0x12,0x8f,0x74,0x06,0xec,0x05,0x30,0x74,0x6e,0xa1,0xc5,0xb7,0x2e,0xcf,0x79,0xe8,0x88,0x06,0x54,0x86,0xfa,0x1b,},{0xba,0xa6,0xbc,0xc1,0xc3,0xd8,0xd3,0xb1,0x1f,0xfc,0x15,0x87,0xad,0xdd,0xc5,0x8b,0xfd,0x96,0xc2,0xb9,0x92,0xb6,0xc6,0xf5,0x9f,0xcc,0x50,0xcc,0xbc,0xdd,0x0e,0xb9,},{0x74,0x77,0xe5,0x41,0x58,0xf1,0x3b,0x71,0x28,0xc0,0xa1,0x10,0xca,0x6b,0x65,0xf4,0x25,0x14,0xfb,0x70,0xcd,0x5c,0xf2,0x8a,0x8b,0x1c,0xc6,0x11,0x0e,0xa0,0x6f,0xcf,0x94,0x29,0x0d,0xa1,0x3f,0x85,0xa1,0x1c,0x23,0x51,0xd3,0xbb,0xcc,0xbb,0x4c,0x64,0xe0,0x21,0x5d,0x6d,0x0f,0x00,0x99,0xe7,0xf2,0x7b,0xc9,0x4e,0x94,0x9b,0x15,0x0b,},"\x9e\xbd\x8e\x33\x78\x93\xbb\x05\x3e\xf2\xb9\xe3\x26\x9d\xf5\x48\x48\x49\x4f\x03\xcd\x63\x57\x6b\x33\xe6\x4b\x10\x80\xbe\x4b\xe0\x15\x26\x4a\x40\x3f\xb9\x60\x2b\xbf\x90\xca\x19\xb2\x41\xa9\xb6\x68\x63\x90\x9b\x90\x08\xce\x1b\x2f\xfc\xf2\x36\xef\xa4\xc2\x66\x8f\x0f\x47\xdb\x9f\xf5\xfa\x15\x7d\x9c\xb6\x05\x41\x2b\xe7\xdd\x8b\x07\xea\x87\x8c\xcc\xae\x6b\xf5\x0f\x93\x5b\x86\xd1\x9e\x1b\x64\x8b\x69\xe5\x28\x55\x3a\x56\xd8\xaf\xb7\x82\x21\xad\x53\x30\x7b\x7a\x4e\xc8\xd2\xfd\x48\x61\xb5\x5d\xc5\xda\xe8\xe9\x3e\xf3\x87\xfb\xbe\x0b\x4c\xe7\xf7\x88"}, -{{0x55,0xab,0xbc,0x5d,0xac,0x41,0x28,0x13,0x4d,0xc8,0xc6,0x01,0x8a,0x21,0x3e,0xd4,0xb6,0x0f,0xcc,0x8e,0x90,0xcb,0xd4,0x1d,0xb2,0xd2,0x1e,0xda,0x53,0x73,0xe9,0x36,},{0x25,0x1a,0xfa,0xa2,0x64,0x69,0x26,0xb2,0xa3,0x71,0xf2,0xa0,0x9d,0x58,0x65,0xb9,0x8c,0x9a,0x5e,0xb6,0xca,0x04,0x7c,0xd0,0xd8,0xee,0x36,0xe5,0xe0,0x41,0x69,0x74,},{0xf6,0xa6,0x1c,0x2e,0x66,0x1a,0x9e,0xb7,0xbd,0xe1,0x82,0xe3,0x8e,0xc9,0x9a,0xf9,0x85,0xf6,0x16,0x98,0xa5,0xd7,0xfa,0x43,0x0d,0x16,0xe3,0xf1,0xa9,0x37,0x09,0xb7,0x55,0x22,0x32,0x0d,0xe4,0x8a,0xfc,0xc5,0x95,0xab,0x20,0x91,0x22,0xae,0x0c,0xe1,0x32,0xcd,0xf4,0xb0,0x39,0x17,0x46,0xe7,0xff,0x34,0x11,0x77,0x57,0x0c,0x81,0x08,},"\x47\x01\x0e\x13\x98\xad\x55\xfa\xbe\x37\x1d\xd8\x64\x8f\x76\x8d\x90\xdf\x4b\x96\x5a\x3b\x39\x61\x00\xb3\x03\xb4\x0a\x17\x51\x8b\xed\x6d\x86\xb0\x9f\x73\x4a\xb7\xc1\x0b\x5f\x3a\x01\xb5\x3d\xee\xc5\xf8\x53\x4b\x70\xc7\x9f\x3f\x29\xb2\x84\xfd\xec\x48\x6f\x22\xf4\x4c\x22\xcc\xd5\xc6\x46\x35\x94\x41\x52\x67\xba\xa6\x11\xf7\x0b\x1b\x31\x6c\xaa\x1b\x68\xb5\xe0\xe9\x9b\x31\xc5\xbb\x0c\xe1\x36\x79\xa2\x3c\x31\xa6\x39\x99\x69\x81\x64\xcb\xf3\x7d\x10\x3b\xa9\x24\x90\x18\x8b\xe5\x99\x37\xf1\x23\x04\x3e\xc7\x86\xef\xe3\xd4\x11\xf9\xb0\x62\x3a\x6a\xd9\x72"}, -{{0xf2,0xdc,0xf4,0xa1,0xa0,0xd4,0x6d,0xdb,0x2d,0x72,0xf8,0xfd,0xd8,0x0b,0xbe,0xc5,0xb7,0xde,0xa5,0x91,0x3d,0xa4,0x96,0x6c,0x2f,0x4d,0x12,0xc2,0x61,0xf0,0xbf,0x98,},{0xd3,0x95,0x70,0xa2,0x5c,0xa5,0x9f,0x22,0x57,0xf9,0x3f,0x96,0x60,0x0d,0xf4,0xf6,0x3e,0x68,0x4b,0xf6,0x3a,0xe8,0xdf,0xfd,0x91,0x4e,0x46,0x29,0xc3,0xd5,0x09,0x5f,},{0x42,0x88,0x2a,0x81,0x1d,0xad,0x2d,0x85,0x18,0x85,0xe4,0xcb,0xe9,0x04,0x47,0x08,0xd9,0x1a,0x86,0xf1,0x5d,0xfa,0x1d,0x66,0xc3,0xeb,0x30,0x43,0x14,0x53,0x1f,0x30,0x15,0x20,0x8c,0x71,0x1b,0x9b,0xdb,0xc5,0xfb,0x23,0x39,0x51,0xe5,0x69,0xb5,0x9d,0x34,0xe4,0x15,0xee,0xc4,0xb3,0x7f,0xfd,0x37,0x4d,0x41,0x2c,0x9a,0x36,0x0d,0x0c,},"\x3b\x00\xe8\x08\xfc\xa4\xc1\x16\x51\xd8\x53\xd6\xb9\x0f\x95\x2c\xcf\x56\x47\xe1\x02\xd4\xee\x0a\xd7\xa5\xd1\x81\xd5\xb4\x25\x8c\x52\x3c\xd3\x9e\x3d\x98\x25\x29\x8d\x84\xc8\xcb\xa0\x9f\x43\xdb\xba\x11\x99\x88\x22\x2c\x76\x05\x9c\xaf\x17\xb4\xbf\x99\x31\xc4\x5e\x61\x74\x48\xae\xad\xe1\x51\x18\x14\x97\xb2\x45\x52\x36\x7e\x52\xbc\x45\xac\x79\x08\x88\x06\xd3\x36\x82\x07\xaa\xfe\xfd\x30\x57\x84\x5d\xce\x81\x9d\x5a\xaa\xa7\x7b\x21\x8e\x2a\xed\x3d\xa7\x6d\x40\xc1\xf0\x76\x99\xf8\x17\x2e\x4a\x5c\x80\x3f\x7a\x2a\xce\xb9\xa4\x7a\x89\x52\xe1\xb2\xf0\x53\xf2"}, -{{0x22,0x46,0xbf,0xb0,0x61,0x55,0x85,0x9e,0x10,0xa7,0x48,0xff,0x8f,0x59,0x19,0xad,0x5d,0x1d,0xaa,0xb7,0x56,0xf0,0x10,0x57,0xb7,0x90,0xd0,0x74,0x74,0x77,0x5f,0x4f,},{0xfa,0x63,0x49,0xb6,0x2d,0xc8,0xc6,0xa2,0xfe,0xee,0xf6,0xff,0xc3,0x3a,0xe0,0x85,0xc6,0x49,0x79,0x5c,0x1c,0x9d,0x98,0x98,0xe7,0x5c,0x13,0xae,0x16,0x25,0xdb,0x34,},{0x2b,0xe4,0x91,0x5a,0x35,0x2f,0x77,0x85,0x48,0x30,0x46,0xd8,0xae,0x96,0x25,0xb8,0xb6,0x32,0x57,0xaf,0x57,0xc0,0x73,0x69,0x12,0x56,0xee,0x07,0x6d,0x6e,0x1b,0x97,0x2a,0x10,0x1f,0x55,0x1c,0x70,0x5d,0x3f,0x96,0x15,0x7c,0x33,0xb5,0x6e,0xa0,0x49,0xbe,0x4a,0xf4,0xdc,0x56,0x1c,0xbe,0x3c,0x1e,0xc5,0x07,0x2d,0x7f,0x13,0x4e,0x07,},"\x63\xee\x1c\x7b\xbb\x15\xce\xbe\x1c\x22\x53\x2d\x48\x16\x82\x75\x4b\xda\xf5\x8b\x8b\xc9\x97\xae\x30\xa3\x4c\x9d\x23\xc3\x3f\x16\x90\xc3\x46\xab\x0a\x73\x65\xff\x62\x45\x74\x24\xb6\x10\x5f\x84\x21\xec\xa0\xce\x3c\x63\x0a\xcf\xeb\x9a\x1c\xc4\x16\x39\x0e\xdf\x49\x20\xe2\x2b\x23\x67\xe9\xfb\x5d\x2a\xb2\x5b\xee\x56\xda\x03\xea\x55\xe3\xf5\x78\x82\xd4\x8b\x89\x22\x93\x14\xd7\x34\xcb\x83\xc7\x9f\x4e\x17\xee\x64\xba\xe6\xf7\xad\xdb\xe9\xb5\x25\xfc\xd0\x3a\x91\x40\x9a\x2d\xde\x90\x77\x51\xdb\x8c\xc9\x7e\x08\xd0\xea\x89\xc4\xd1\x87\x18\xd2\x6d\x0b\x89\x7b\x64"}, -{{0xc0,0x88,0xa3,0xdd,0x2c,0xb8,0xbd,0x5d,0x68,0x4d,0xb8,0x53,0x8d,0xc2,0x24,0x73,0xb6,0xf0,0x14,0xf6,0x4f,0xe8,0x6a,0xf1,0x68,0xb4,0xbb,0x01,0xb9,0x0a,0x1d,0xd0,},{0xaa,0xd6,0x15,0xa9,0xc2,0x87,0x59,0xf0,0x3d,0x37,0x3a,0xbe,0x66,0x66,0x91,0xde,0xad,0x8b,0x84,0xf9,0xb8,0xb5,0x0a,0x67,0xf8,0xf0,0xaa,0x4a,0x70,0x15,0x80,0xd1,},{0x3b,0xb4,0x59,0xd1,0xac,0x57,0x5a,0x18,0x0c,0x17,0x28,0xd8,0xb8,0x92,0x49,0x70,0x49,0x2a,0x0c,0x8d,0x2a,0x37,0x8c,0x29,0xd1,0xd4,0x17,0x85,0xc8,0x37,0x9a,0x58,0xe2,0xba,0x36,0x06,0x78,0x5e,0x1c,0x5d,0xa2,0x9e,0x55,0x27,0x55,0x2b,0xc6,0xdc,0x89,0xa2,0xb6,0x9c,0x27,0xfe,0x51,0xed,0x25,0x3a,0x9f,0x3b,0x56,0x5b,0x27,0x00,},"\x74\x90\x6a\xe0\x5a\x5a\xf8\xe9\x96\x8b\x6f\xeb\x49\x85\x69\xd6\x34\x5a\x24\xf9\x71\x1b\xef\xb1\x36\xe6\xc3\xb5\xed\x49\x33\x9e\x59\xa7\x93\x8b\x4b\xa1\xa1\x18\xf1\x69\xb9\xac\xe0\xf7\x84\x2a\x26\xa6\x45\xf1\x4c\x0a\xd2\x2e\xbb\xcd\xa9\x3e\x67\xe4\xc3\x48\xef\xc3\xd9\xec\xbb\x14\x19\xe6\x26\x2d\x04\x36\xa5\x8e\xa8\x2c\x22\x02\x38\x90\x65\xcc\xf6\x7c\x4f\x55\x0e\x45\xb5\xf6\xa1\x2a\x6c\x01\x1b\x2e\x0a\x30\x10\x1d\x5c\x62\x32\x8b\xbf\x99\xc8\xc9\x55\x63\xa6\xe3\x3b\xdd\x9c\xce\x72\xb1\xf7\x20\x13\x9c\x2f\xd3\xe0\x49\x13\x14\x6a\xe5\xba\xc5\x28\x8e\x0e\x3e"}, -{{0x45,0x66,0x7d,0x1e,0x7b,0x59,0x10,0x97,0x9c,0x4a,0x32,0x83,0x17,0x96,0x83,0x71,0xc8,0x64,0xd5,0x64,0xa6,0x61,0xc5,0xcc,0xe5,0x57,0xc9,0xec,0xc6,0x1b,0xab,0x9e,},{0xed,0xcd,0xf5,0xe1,0xa1,0x70,0xe0,0x0c,0x8c,0x68,0x7e,0x7e,0x9c,0x18,0xf9,0x89,0x3b,0x5f,0xe4,0x95,0xcd,0x29,0x77,0xce,0xb7,0xf4,0x46,0xc0,0x14,0x9a,0xa9,0xd3,},{0x6d,0xe6,0x68,0xf1,0xca,0x6f,0x29,0x28,0x14,0x62,0x52,0x89,0xa0,0x80,0x80,0x20,0xc8,0x7c,0x89,0xac,0x94,0xf5,0xb0,0x50,0x8e,0x55,0x7b,0xdf,0x80,0x00,0xa5,0xca,0x80,0x8f,0x02,0x1c,0x96,0x79,0xb5,0x0e,0xe2,0xf3,0x20,0x06,0x4c,0x95,0xa4,0x64,0xa8,0x43,0x93,0x79,0x82,0x8c,0x3b,0x76,0xcf,0xa7,0x66,0x45,0x5e,0x12,0x8c,0x0b,},"\xcd\x66\xce\xc4\x76\xc8\x7c\x8d\xbf\x47\xec\x91\xda\xc4\x8f\xb5\xb4\x2d\xb1\x28\x2a\x57\x3e\x0a\x5c\xf0\xb9\x17\x68\x98\x66\x08\xe1\xd7\xeb\xd0\x5f\x52\x51\xbc\xf8\xb4\x7a\x17\x09\x32\x29\xac\xef\xbd\x44\xbe\xb2\x1c\x0c\x0c\x92\x8d\xd3\xcd\x3f\x89\x66\xec\xce\x69\x10\x33\x1c\x50\x8e\xa7\x6b\xaf\x90\x4d\x8c\x21\xf6\xc1\x7c\x2c\x58\xd0\x0a\xfd\x32\x59\xb8\xbf\x79\x4c\x14\x6b\x12\xb9\x95\xcd\xdd\x1c\x42\x89\xc5\xbe\x31\x68\xeb\xd6\x16\xb3\x84\xc2\x81\xce\x1b\x38\xa1\x0e\x18\x07\x80\x88\x53\xc6\x81\xa6\x40\xa0\x09\xb4\xd2\xac\xd7\x93\x4f\x8c\x6d\x07\x57\x81\x61"}, -{{0x24,0x89,0x74,0x28,0xae,0x65,0x46,0xd8,0x5b,0x31,0x90,0xeb,0xe3,0xf1,0xf7,0xbf,0x7c,0x71,0x25,0x28,0xac,0x85,0x1a,0x58,0x8b,0x07,0xd5,0xc8,0xf9,0x4e,0xec,0xd1,},{0x5f,0x34,0x8f,0xe3,0xea,0x5b,0x2c,0x02,0x3d,0x0a,0xf7,0xed,0xe6,0x0e,0x55,0xf9,0x1a,0xa5,0x51,0x99,0x69,0x9d,0xa1,0x5a,0x11,0xc3,0x79,0x1d,0x68,0xd7,0x10,0xbd,},{0x1b,0x5e,0x75,0xde,0xf4,0x9f,0x51,0xd6,0xb2,0xde,0x00,0x8c,0x71,0xfc,0x1a,0x90,0x9b,0xd4,0x2c,0xa8,0x13,0x29,0x8d,0xce,0x4e,0xee,0xf7,0x17,0x81,0x5d,0x7a,0x6c,0x07,0x8c,0x2f,0x3d,0x9a,0x3f,0xce,0x1a,0xb5,0xb3,0xad,0x8e,0xf8,0xd4,0x5c,0xdf,0x2e,0xb4,0x90,0x1c,0x32,0xee,0xa2,0xd5,0xe0,0x18,0xdc,0xf2,0x83,0x3c,0xad,0x0c,},"\x52\x01\xd9\x72\x5f\x1d\xff\xa1\x86\x3f\xa4\xd8\x4c\x30\x18\x61\x14\x1a\xcd\xfb\x64\xbe\x1f\xbf\xdd\x5b\x93\x86\xdb\x20\xef\x39\x40\x99\xee\xbc\xfd\xfe\xcc\x62\xc6\x26\x86\x07\xa8\x4d\x55\xc5\x5c\xd0\xef\xdc\x37\x2e\xcf\x30\x67\x34\x3e\x7b\x07\x31\xc2\x68\x54\x61\xe2\x4b\x95\x3f\x99\x94\x9e\x59\xba\x3e\x67\xed\x0f\x08\x48\x31\x37\x93\x96\x2a\x29\x2c\x45\x98\x14\xc5\xe2\x86\x90\xec\x1f\x45\x17\x1f\x1a\xba\xb8\x6f\xdd\x14\x56\x8b\x00\xca\xf4\x85\x81\x11\x5e\xe5\xea\x83\xb0\x00\x28\x2f\xbb\xf0\xc0\xb2\xa1\x11\x60\x39\xa3\x5c\xfa\x3f\x20\x14\x22\x20\x7a\x3d\x49\x48"}, -{{0x7b,0x04,0xac,0xa7,0xcf,0x92,0x62,0x16,0xcb,0x96,0x0a,0x38,0x90,0x78,0x63,0x39,0xd0,0xa6,0x15,0x96,0x76,0x80,0x19,0x01,0x23,0xfd,0xa3,0xb6,0x0c,0x6a,0xeb,0x11,},{0xcd,0xbc,0x3e,0x70,0xe4,0xe8,0xfd,0x13,0xd0,0xcc,0xe2,0x85,0x2a,0x3b,0x93,0x72,0xc3,0xa6,0x16,0x0c,0xd6,0xde,0xab,0xa9,0x0f,0x9b,0x30,0x22,0xf7,0x0c,0x91,0xf9,},{0x25,0xd2,0xd3,0x61,0x75,0x1d,0x52,0xb4,0xfe,0x66,0xea,0x18,0xe4,0xb9,0x86,0x6b,0xde,0x3d,0x12,0x1a,0x73,0x12,0xfd,0x9e,0x28,0xa1,0xe2,0x95,0xe0,0x87,0xe3,0x17,0x6c,0x94,0xc8,0x74,0xa2,0xe8,0x16,0x00,0xf2,0x4c,0x46,0x54,0xf4,0x3d,0x1b,0x67,0xd4,0x7b,0x64,0x82,0x26,0x48,0x59,0x0c,0xe5,0xce,0x44,0xf3,0xb5,0xdd,0xc5,0x02,},"\x1c\xb0\x96\x24\xb1\xf1\x4a\x02\x60\xc7\xf5\x6d\x8c\x60\xb5\xfe\x45\x83\x71\x14\x23\x25\x51\xef\x59\x66\x38\x6e\x0c\x2b\x44\x1b\x75\xcf\xdb\x8d\xf2\x18\x57\x85\xd2\x2c\xf5\x26\xfa\x9d\xf7\xfd\x45\xd9\xd8\x38\x81\xb6\x6c\x1f\xee\xe0\x91\x3e\x23\x81\x21\xee\xdb\xb7\xab\x50\x4d\xa0\xbe\xe8\x99\x80\x16\x68\x45\x35\x03\x19\x91\xf1\x1b\xfc\xd9\xb9\x56\x90\xaa\xd2\xd1\x9b\xd6\xa9\xde\x18\x44\xed\x13\x62\x30\x2d\xf4\x21\x72\x30\xb2\x5c\x05\x52\xce\x27\x75\x34\xc6\x50\xca\xe5\x26\x57\x7f\x25\xd8\xb1\xfe\x9f\x9f\xeb\xca\x2c\x81\x46\x70\xd4\x80\x5b\x21\xad\xef\x85\x2d\xaf\x94"}, -{{0xea,0x73,0xbf,0x64,0xa1,0xa9,0x78,0x77,0xc3,0xc3,0xe7,0xca,0x46,0x44,0xb7,0x1a,0xaa,0x66,0x31,0x4c,0x8f,0x1b,0x66,0xba,0xfa,0xeb,0xd5,0xed,0xfb,0x88,0x8b,0xcd,},{0xca,0xac,0x93,0x90,0x2e,0x57,0x64,0xad,0xe4,0x72,0x94,0xed,0xd5,0x1f,0xaa,0x14,0x62,0x09,0x40,0xc6,0x68,0xb5,0xc1,0xc3,0x92,0xa6,0x92,0x83,0x25,0xd4,0xc3,0xfd,},{0xbd,0x86,0xcb,0x9c,0x70,0xa0,0x55,0x27,0x9a,0x86,0xa9,0xe6,0x48,0x70,0x98,0x8b,0x8a,0x73,0x45,0xc3,0xcd,0x29,0x48,0xa0,0xfa,0xbc,0xfb,0x38,0xab,0xce,0x3c,0x42,0x0b,0x4d,0x55,0x21,0x61,0x8e,0x11,0xd2,0xde,0x82,0x7d,0x9d,0xe5,0x69,0xf6,0xbc,0x3b,0xe6,0x6a,0xad,0x40,0x63,0x6c,0xda,0xa6,0x47,0x60,0xde,0xd3,0xb7,0xc2,0x09,},"\x36\x2e\xec\x68\xb9\x12\x85\x27\x86\xbb\x4f\x9a\xff\xf9\xec\xf7\xcb\x28\xc9\xde\x6b\x18\x42\x2a\x8c\xa9\x40\xb0\xd7\xe6\xdc\xb8\x3a\xa4\x4b\xe0\xaf\xb5\xf1\x80\x6d\x43\xf0\xe3\x1d\x71\xf9\x22\xf8\x53\x61\x5a\x26\xe2\x87\xa2\x7f\x08\xa0\x4f\xbc\xe3\xd4\x5a\x0c\x6c\x31\x1d\x4b\x7c\xb1\x7e\x42\x5b\xbe\xb0\xa6\xb4\x10\xb5\xd6\xdb\xb7\xac\x11\xdf\x98\x50\xa1\x31\xa6\x91\xe3\xb6\x0b\x0b\x21\x4e\xbe\x04\x41\x06\xe9\x82\x43\x32\x87\x59\x52\x67\xb0\x31\xb5\xd4\xa0\x92\x62\xde\xd8\x93\x4f\xdf\xdf\x96\x4d\x86\x8e\xf9\xa2\xc8\x42\xf8\x04\xea\xfd\xde\xfc\xb7\x1d\x9f\x16\xa5\x9b\xf8"}, -{{0xb8,0x12,0x3c,0x11,0x6b,0x33,0xba,0xd0,0xdc,0xbc,0x2c,0x4d,0xc0,0x6a,0x3d,0x66,0x85,0x0d,0xab,0x36,0x0c,0xdb,0x5a,0x03,0x3c,0x14,0x89,0x5c,0x4e,0xe3,0x1b,0xfb,},{0xbd,0xca,0x15,0x1b,0xa3,0x2c,0x6b,0xb3,0x15,0x31,0xb0,0x5f,0xdf,0x86,0xc6,0xd7,0x8c,0x8c,0xd1,0x93,0x56,0x11,0xd5,0xff,0x11,0x1a,0x0f,0x00,0x63,0x5b,0x18,0x85,},{0x9c,0xf1,0x3e,0xba,0x3d,0xcc,0x37,0xb8,0xfc,0x70,0xcc,0xb2,0x32,0x74,0x36,0xb9,0xf0,0x88,0x55,0xe7,0x26,0xaa,0x7e,0xd8,0x2b,0xd5,0xcb,0x7d,0xf4,0x5f,0xdf,0x9e,0xc1,0xf9,0x6a,0xfa,0xd1,0x93,0xf4,0x75,0x72,0xd7,0x70,0x44,0x4b,0x65,0xb7,0x4a,0x37,0xcc,0x03,0x4f,0xc5,0x14,0xcb,0x3f,0x91,0xb2,0xd8,0xad,0xa5,0xb0,0x20,0x06,},"\x79\x70\xf6\x66\x66\x34\x54\x8c\x84\x8b\xb5\x23\x38\x81\x7b\x26\xa4\xd0\xca\x68\xdf\x3d\x28\xaf\xff\x20\x7c\x2d\x02\x80\x67\xa1\x8e\x4c\x95\x43\x02\x5f\x5b\x02\x28\xaa\x69\x1e\x50\x88\x51\x31\x51\xa9\x44\x94\xe1\x5d\x1f\x54\x21\x03\x28\xe0\xdf\x15\x9b\x35\x2c\x30\xaa\xa7\xa8\x44\xf1\x8a\x9f\x4c\x39\x5d\xcb\xb3\xfb\x9f\xcf\xbe\xd1\x10\x3e\x07\x06\xfb\xf9\xc3\x5f\xe2\x66\x68\x48\xfa\x35\xdc\x2c\xf5\x22\x7e\xbe\xe8\x9e\x7d\x3b\xcf\xae\x27\x21\xb2\x5f\xde\xc3\xd3\x17\x4e\xa7\xce\x26\x7a\x55\xdd\x61\xd5\x82\x01\xe9\x6b\xda\x30\x3c\xf4\x18\xed\xf6\xe3\x2f\xb9\x2f\x5d\xc1\xa0\xb1"}, -{{0xb1,0x8e,0x1d,0x00,0x45,0x99,0x5e,0xc3,0xd0,0x10,0xc3,0x87,0xcc,0xfe,0xb9,0x84,0xd7,0x83,0xaf,0x8f,0xbb,0x0f,0x40,0xfa,0x7d,0xb1,0x26,0xd8,0x89,0xf6,0xda,0xdd,},{0x77,0xf4,0x8b,0x59,0xca,0xed,0xa7,0x77,0x51,0xed,0x13,0x8b,0x0e,0xc6,0x67,0xff,0x50,0xf8,0x76,0x8c,0x25,0xd4,0x83,0x09,0xa8,0xf3,0x86,0xa2,0xba,0xd1,0x87,0xfb,},{0x6b,0xd7,0x10,0xa3,0x68,0xc1,0x24,0x99,0x23,0xfc,0x7a,0x16,0x10,0x74,0x74,0x03,0x04,0x0f,0x0c,0xc3,0x08,0x15,0xa0,0x0f,0x9f,0xf5,0x48,0xa8,0x96,0xbb,0xda,0x0b,0x4e,0xb2,0xca,0x19,0xeb,0xcf,0x91,0x7f,0x0f,0x34,0x20,0x0a,0x9e,0xdb,0xad,0x39,0x01,0xb6,0x4a,0xb0,0x9c,0xc5,0xef,0x7b,0x9b,0xcc,0x3c,0x40,0xc0,0xff,0x75,0x09,},"\x91\x6c\x7d\x1d\x26\x8f\xc0\xe7\x7c\x1b\xef\x23\x84\x32\x57\x3c\x39\xbe\x57\x7b\xbe\xa0\x99\x89\x36\xad\xd2\xb5\x0a\x65\x31\x71\xce\x18\xa5\x42\xb0\xb7\xf9\x6c\x16\x91\xa3\xbe\x60\x31\x52\x28\x94\xa8\x63\x41\x83\xed\xa3\x87\x98\xa0\xc5\xd5\xd7\x9f\xbd\x01\xdd\x04\xa8\x64\x6d\x71\x87\x3b\x77\xb2\x21\x99\x8a\x81\x92\x2d\x81\x05\xf8\x92\x31\x63\x69\xd5\x22\x4c\x99\x83\x37\x2d\x23\x13\xc6\xb1\xf4\x55\x6e\xa2\x6b\xa4\x9d\x46\xe8\xb5\x61\xe0\xfc\x76\x63\x3a\xc9\x76\x6e\x68\xe2\x1f\xba\x7e\xdc\xa9\x3c\x4c\x74\x60\x37\x6d\x7f\x3a\xc2\x2f\xf3\x72\xc1\x8f\x61\x3f\x2a\xe2\xe8\x56\xaf\x40"}, -{{0x93,0x64,0x9c,0x63,0x91,0x0b,0x35,0x71,0x8e,0x48,0xc5,0x90,0xd2,0x61,0xc4,0x8e,0x4e,0xf8,0x33,0x66,0x13,0xf6,0xaa,0x07,0x7b,0x46,0x26,0x76,0xb3,0xba,0x88,0x29,},{0x06,0xa6,0x85,0x89,0x8b,0x85,0x52,0x12,0xeb,0xc2,0x89,0x91,0x5d,0x10,0x5a,0x43,0x20,0xd6,0x20,0xd8,0x57,0x71,0xb8,0xc6,0xb1,0x5b,0xf1,0x0a,0x1b,0xe6,0xe9,0xb8,},{0x62,0x74,0xf2,0xd4,0xf4,0x31,0xd5,0xaf,0xfe,0xfa,0x35,0xe7,0xcf,0x58,0x4a,0x59,0x90,0x17,0x19,0x3d,0xa9,0x90,0x94,0xca,0x90,0x8b,0x75,0xac,0xb6,0x08,0xd1,0xbf,0x98,0x18,0x57,0xbe,0x93,0xa7,0xda,0xfb,0x0f,0xad,0xb3,0xff,0x09,0x06,0xf4,0x8a,0x5e,0xe9,0x50,0x45,0x6f,0x78,0x2c,0x2d,0x60,0x5b,0x14,0x09,0x5b,0xa0,0xff,0x0f,},"\x2c\xd1\xa9\x51\x05\x6c\x9e\xba\xe1\x39\x9b\x6b\xd2\xd8\x2c\x0a\xe2\x77\x85\x62\x90\xd0\x69\x20\xac\x56\xca\xc8\xfb\x42\x43\x51\x01\xc7\x2a\xa9\xc0\x8d\xd2\xd1\x24\x26\x32\x55\x62\xc2\xf0\xa4\x9c\xd8\x21\xb1\x1b\x93\x9a\xaf\xa5\x93\xb4\x09\x5c\x02\x1b\xcb\x48\x27\xb1\x07\xb9\x66\x4d\x68\x28\x28\x88\xbc\x4a\x44\xaf\x3e\x3b\xdc\x86\x1b\xe6\xaf\x30\x90\x44\xc3\xda\xab\x57\xb7\x70\x23\xdc\x90\x2d\x47\xeb\xc3\x26\xf9\xbd\xd0\x2d\xbc\x02\xcd\x54\x0f\xf8\x1b\x2d\xdf\x7c\xf6\x79\xa4\x11\x93\xdf\xe5\xf8\xc8\xca\x1a\xae\xfc\x41\xef\x74\x02\x80\xd9\x82\x3e\x30\xa3\x54\x71\x7c\x84\x31\xf5\xd8"}, -{{0x1c,0x15,0xcb,0xeb,0x89,0x36,0x2d,0x69,0x47,0x6a,0x2a,0xa4,0xa5,0xf3,0xef,0x20,0x89,0xcf,0x87,0x28,0x63,0x49,0xe0,0xdf,0xe0,0xe7,0x2d,0x9e,0x3e,0x5a,0x66,0xc7,},{0x13,0xa8,0x82,0xa1,0x06,0x41,0x82,0x58,0x2c,0x21,0x18,0x47,0xe1,0x9b,0x4d,0xac,0x59,0x72,0x2c,0x9f,0xfd,0x34,0x82,0x6d,0x96,0xf3,0x31,0x13,0x40,0x0f,0xac,0x7a,},{0x59,0x98,0xb2,0x80,0x8a,0xdf,0xde,0xea,0xeb,0xe2,0xc3,0xea,0xc0,0x26,0xd3,0xf8,0x25,0xf9,0xc7,0xf2,0xaf,0x97,0xca,0x32,0x4f,0xbd,0x57,0xaa,0xc1,0xbe,0xdf,0xf7,0x8a,0x8e,0xe6,0x21,0xd0,0x37,0xee,0x3a,0xd2,0xa7,0x12,0xe9,0xa0,0x09,0xc5,0x8e,0xa3,0xe6,0xf2,0xa8,0x28,0xf7,0x4b,0x86,0xda,0x27,0x5a,0x44,0xa4,0xb1,0xe5,0x0b,},"\x09\x1c\x9b\x9b\x11\x6a\xe8\x3d\x23\xd0\x1a\x62\x95\x21\x17\x85\xd4\x46\xb6\x22\x8d\xd6\x87\xdd\xf7\x9b\xd0\xd5\xa4\xda\xa8\xc7\x9d\x2c\xbf\xc3\x73\x65\xf1\xf2\x85\xe3\x61\x73\x81\x23\xe3\x4e\x2b\xcb\xfc\x66\x4c\xe1\x25\x3a\x11\xd9\xe4\xa7\x98\x2e\x58\xcf\x94\x68\xe1\x01\x7e\xa1\x4d\x2c\xc6\xd0\x86\x5d\x40\xfd\xe8\xcb\x56\x02\x41\xe9\x6a\xc1\x61\x7c\x79\x1f\x0c\xa7\xc6\x41\x0c\xad\xf3\x28\x61\x1b\x18\xae\xf3\x33\xd8\x35\x0a\xc4\x97\xf0\xa4\xae\x2d\x03\xfd\xf0\xe2\x3e\x42\x6d\x34\xf4\x51\x47\x80\xd1\x47\x4e\x11\x35\x83\x54\x1f\x3c\x04\x36\x72\x05\x71\x72\x61\x8c\xb2\x05\x9e\xaa\xed\x56"}, -{{0x11,0x24,0x1f,0xfd,0xf3,0x4a,0xe8,0xab,0x87,0x54,0x75,0xe9,0x4c,0x6c,0xc3,0x29,0x1f,0x0b,0x88,0x20,0xdc,0x85,0xe2,0x0f,0x32,0xfc,0x53,0xb2,0x4a,0xe6,0x89,0x78,},{0x09,0xc0,0x45,0xe4,0xbd,0x51,0x37,0x31,0x4c,0x0e,0xc1,0xd0,0x31,0xfa,0xf9,0x14,0x91,0x0c,0x45,0xa4,0x67,0x6f,0x5a,0x3c,0xd8,0xf5,0x81,0xbc,0xcc,0xb0,0x3c,0x97,},{0x72,0xce,0x9f,0x91,0xbe,0x2e,0x66,0xcf,0xc9,0x0f,0x95,0x25,0x95,0x94,0x6f,0xfc,0x90,0xbf,0xce,0x53,0x08,0x7d,0x49,0xe5,0xdd,0x7c,0x08,0x7f,0x3f,0xaa,0x8f,0x18,0xf2,0x35,0x6d,0xe9,0x71,0xe4,0x42,0x9d,0x98,0x5a,0x99,0x19,0x4b,0x4f,0x92,0xce,0xd3,0xef,0x47,0xcd,0x71,0x14,0x37,0x9e,0x0b,0x32,0x67,0xa9,0xf8,0xb1,0xe7,0x06,},"\x3b\x89\xde\xcc\xb7\x02\x3e\x4b\x2b\x7a\xff\x2c\x39\x51\x87\x0a\xf4\x13\xa9\xb0\x4d\xd8\x6a\xc7\x8b\x7c\x8f\xd8\x87\x49\x2d\x8d\xde\x49\xd8\xfd\xa1\x49\xed\xd5\x47\x81\xae\x2b\x50\x80\x30\xd1\x44\x16\xa9\xa3\x8b\xed\x2b\x9a\xeb\xbb\xb2\x02\x50\xb3\xc9\x31\xac\xd4\xe3\x2f\xbe\xee\xc5\xa2\x65\x01\xbe\xab\x72\x68\xd1\x44\xfc\xe8\x95\x1a\x10\x1c\x4b\x51\x78\x16\x6f\xbb\x59\x27\xb1\xdf\xb1\xe1\xce\x90\xd1\xd1\x23\x06\x8e\x3f\x47\x2c\x88\x8f\xdb\x01\xfd\xf7\x0e\x7f\x8d\xe9\xb0\xad\xb2\x84\xb7\x11\x9f\x55\x35\x43\x16\xf8\x4e\xd0\x90\x03\x0f\x9c\x26\x62\x06\x1c\xa4\x84\x47\xcc\x0a\xef\x96\x41\x26"}, -{{0x3b,0xdb,0x16,0x24,0x65,0xea,0xce,0xff,0x98,0xd6,0x9c,0x86,0xf7,0x00,0x39,0xc5,0x17,0xd1,0x68,0xae,0xfe,0x6b,0xb1,0x01,0xb4,0xf7,0x69,0xa8,0x6b,0x17,0xc9,0x72,},{0xd7,0x6c,0xb7,0xbe,0x74,0x32,0x82,0x89,0xfd,0x1c,0x64,0xbe,0x74,0x7c,0xca,0x5b,0xb3,0x02,0x95,0xdf,0xac,0xcd,0x0f,0x2e,0x43,0xf5,0x17,0x03,0xfd,0x5d,0x36,0x83,},{0x6f,0x13,0x62,0xa4,0x02,0x06,0x37,0x91,0xf9,0x50,0x98,0x4f,0x54,0x49,0x28,0xe6,0x16,0xa4,0xef,0x79,0xbb,0xeb,0x68,0x54,0xe9,0x61,0x5a,0xab,0x9c,0xdb,0xae,0xc4,0x83,0xfb,0x9a,0x04,0xbf,0x22,0xde,0x5d,0x97,0xa1,0x5b,0xda,0x2d,0x39,0x04,0x83,0xc7,0xf6,0x1d,0xbe,0xe0,0x7b,0xb5,0x14,0x1f,0xc1,0x73,0xb1,0xaa,0x47,0x65,0x0d,},"\xfb\xf3\x68\xfe\xae\xba\x87\x91\x8b\x1b\x8c\x7b\x8a\x26\x83\x2b\xe6\xe7\xfc\x1c\xbd\xb8\x90\x25\x19\x28\x1a\x06\x54\xec\x73\xde\x0b\xb0\x71\x01\xa9\xd6\x03\xf7\x45\xd4\xec\x23\x57\xae\xe9\x87\x0c\xb1\x9a\x56\xcb\x44\xfb\xd9\xc9\x1f\xc3\x47\x52\x61\x2f\xbd\x83\xd6\xfc\x1a\x16\xbf\x8a\x85\xa2\x15\xd0\x14\x8e\x4a\xf3\x7d\x29\x84\x67\xe5\xcc\x48\x6b\x13\x13\x52\xce\x09\x21\x82\xce\x82\x84\x15\x9a\x38\x12\xb3\x0b\xac\xbf\xf5\x95\x86\x38\x11\xbf\x9a\x30\xa9\xda\x49\x45\x65\xc3\xac\x18\x14\x43\x00\x18\xea\x0e\xee\xd3\x9c\xdb\xca\x27\xf9\x31\x40\xe4\x69\x49\xdb\x57\x0b\xfa\x2e\xd4\xf4\x07\x3f\x88\x33"}, -{{0xd5,0xef,0xe5,0x1d,0x5c,0xd8,0xe1,0x08,0xbd,0x92,0x2f,0xc0,0xea,0x12,0x61,0x90,0xa9,0x46,0x28,0xff,0xa5,0x3c,0x43,0x3a,0x51,0x80,0x22,0x79,0x2d,0xdc,0x78,0xef,},{0x42,0x6b,0x01,0xcc,0x61,0xff,0x5e,0x0e,0x72,0x4d,0xa1,0xd3,0xb2,0x97,0xf5,0x32,0x5c,0x18,0xc6,0x2f,0x64,0xd5,0xeb,0x48,0xd4,0xa5,0x21,0x6a,0x8e,0x9a,0x40,0x73,},{0x23,0x06,0xf5,0x8f,0xcd,0x4c,0xff,0x22,0x22,0xd8,0x1b,0x05,0xa4,0x75,0x53,0x2b,0x8b,0x19,0xdc,0x67,0xe6,0xd7,0x8d,0xdb,0x42,0x05,0xa3,0xb7,0x62,0x1c,0xc5,0xae,0xf0,0xb3,0x93,0xd5,0xd2,0x4d,0xd9,0x6c,0x88,0xcc,0xbc,0x53,0xa3,0x20,0x8d,0xa3,0x23,0xbe,0x45,0x87,0xd5,0xec,0x06,0x7c,0x82,0x0f,0x07,0x23,0xaa,0x44,0xe9,0x0e,},"\x9d\x17\xbc\xfe\x2d\xfc\x74\x2f\x41\x1c\xb5\x3a\x94\xf3\x59\xc0\x01\xab\xf0\x96\xc7\x41\xf3\x4a\xf4\x86\x79\xf2\x81\xe7\xce\x6b\xbd\x9e\x87\x70\x9f\xc0\x72\x8a\x56\x3d\xb2\xb9\xcf\x8e\xa4\xfb\xdc\xc3\x44\xc1\x84\x8e\x65\x3c\xe9\x70\xc6\xce\x29\xde\x2c\xcd\x52\x03\x00\x64\x9a\xdc\xdd\xfc\x75\x39\x71\xf8\x46\xaa\xc1\xba\x42\xae\x45\x28\x95\x2d\x94\x98\x0a\xa7\xc6\xcf\xa2\x14\x29\x07\x64\x7f\x89\x4a\xe9\x74\xa7\x4d\x59\x03\x5a\x73\xef\x56\xa1\x0b\x66\x12\x62\x48\x09\x52\x01\x90\xac\xe6\x61\xc3\xa4\x70\x95\xe0\x32\x2e\xfd\x78\x1d\x50\xd1\x16\x35\x98\xf2\xda\x32\xf3\x1b\xc9\xc4\xf9\x13\xd1\xb1\x48\x61"}, -{{0x18,0xaf,0x89,0x02,0x5e,0xbf,0xa7,0x6b,0xd5,0x57,0xcf,0xb2,0xdf,0xf1,0x48,0x24,0x52,0x14,0x64,0x1f,0xd5,0xbd,0xa1,0x59,0xf7,0x3d,0xa0,0x4b,0x08,0xe8,0x7c,0x88,},{0x0c,0x58,0x44,0x59,0xb9,0xeb,0xcc,0xca,0xd5,0x87,0xb2,0x72,0x16,0x0b,0xc6,0x0b,0x27,0xf4,0xf7,0x72,0xb4,0x32,0x1d,0xe7,0x72,0x3a,0xfe,0xf5,0x77,0xed,0xc7,0xb4,},{0x26,0xbb,0x08,0x82,0x29,0x7c,0x2c,0x08,0xa7,0x52,0xd3,0x98,0x11,0x45,0xdc,0xde,0x55,0x89,0x3a,0x11,0xdf,0x77,0xf8,0xaa,0x4c,0x19,0xd0,0xb9,0xed,0x6e,0x52,0x20,0xed,0x12,0xe9,0xfa,0xc3,0xaf,0x13,0xd0,0xf0,0xc7,0x15,0x68,0xf4,0xa5,0x47,0xd3,0x01,0x14,0xa6,0x59,0x9a,0x23,0x68,0x06,0xc4,0xbe,0xee,0x67,0x65,0x28,0x44,0x08,},"\xe8\x2f\x46\x65\x2a\xb9\x14\xaf\x53\x5d\x8f\xb7\x20\xb5\x57\xac\x95\x01\x8d\x9f\x2a\x3f\xcc\xe8\x57\x71\xbb\x40\xab\x14\xcb\x9a\x98\x6e\x09\x6f\x3a\xfe\x5b\xee\x82\x9d\xfd\x8b\x97\x33\x5c\x53\x6a\xc9\x71\xa2\x16\x55\xaf\x16\xa2\xf8\xfd\xba\x18\x3a\x4e\x18\x56\x4c\x21\x49\x29\x56\x53\x7a\x41\x9a\xbb\xbb\xb0\x2a\x4b\xbd\xc0\x14\x81\xf5\xc6\xe6\x58\xec\xf3\xc3\x4f\x01\x1a\xd8\x46\xf5\xed\xcd\x49\x39\x19\x5d\xf8\x5e\x41\x30\x3f\xb9\xa8\x8f\xdf\xbd\x70\x43\x96\xf7\x55\x9a\x32\x73\x18\xb9\x52\xb3\xe6\x0c\xe8\xdd\xde\x56\x37\x85\x79\x23\x2f\xaf\x95\x0c\x78\xe7\xf0\xb1\x7c\x3b\x8d\xec\xe3\x6b\x78\x8a\x84\x73"}, -{{0x0c,0x93,0xd9,0x98,0x15,0xff,0xf8,0xfe,0x22,0xb9,0xe4,0x5a,0xa0,0x2b,0x3e,0x64,0x45,0xce,0x1d,0x6b,0xf5,0xa6,0x5d,0xce,0x3d,0xa1,0x07,0xaa,0x10,0x55,0x94,0x0e,},{0x4d,0x27,0xa4,0x7b,0x0f,0xc8,0x08,0x00,0xd8,0x4d,0x24,0x4e,0xeb,0xb1,0xde,0xb4,0x43,0x6d,0x97,0x63,0x3a,0x83,0xe6,0x71,0x25,0xad,0x52,0xea,0x01,0x68,0x50,0x57,},{0x7d,0xc4,0x46,0x7a,0xbc,0xf6,0x43,0x1a,0xdb,0x7c,0xcf,0xe8,0x68,0xea,0xc8,0xcd,0x8a,0x61,0x5a,0x0f,0xf6,0x5f,0x6a,0x9e,0x33,0x83,0x75,0xb1,0xaa,0xe3,0xc4,0x9a,0x12,0x6c,0x9e,0xba,0x79,0x42,0x6d,0x16,0x41,0xc6,0xb9,0x7c,0x3e,0x92,0xc1,0x94,0xe5,0xee,0x44,0x31,0xef,0xa2,0x43,0x9f,0xd4,0x50,0xf2,0xcd,0x01,0x8c,0x87,0x00,},"\x11\xe8\x77\xde\x58\xc1\x34\xea\xf4\xc9\xf1\xb5\x3c\x3d\xc4\x51\xd3\xc0\x55\xf1\x6b\x09\x62\x27\x25\xb2\x79\x76\x85\x12\xfe\x10\xa7\xad\xb0\x76\x5b\x68\x9e\xc2\x1d\x5b\x6e\xfa\xa1\x9f\x1b\x9d\x36\x25\x4d\xf0\xa9\x36\x7f\x44\x1b\x26\xbd\xb9\x0b\x28\xcb\xc4\x03\xe5\x07\x40\x82\xfa\x1f\xed\x58\xe1\x40\xda\xc9\x7a\xea\xf4\x83\xe2\xc1\x3f\x3c\xc5\x60\xab\xff\xab\xa0\x5b\x76\x3f\xee\xdb\x51\xe6\x06\x98\x15\x1c\xf5\x6e\xfd\xf1\xd3\x7d\x6c\xe0\x56\x44\x86\x21\x0f\x05\x2e\x93\x7f\x2e\xa2\x6f\x63\xef\xa5\xd2\x47\xff\x18\x83\x29\xbb\x1a\xa8\x3c\xe3\xf4\xf3\x5a\x3d\x7d\xec\x14\x59\x9e\x5f\xeb\x7b\x6d\x5f\xe4\x29\x6a"}, -{{0x98,0x9e,0x99,0x94,0x56,0x35,0x19,0x2c,0x02,0x3c,0xc5,0x18,0x6f,0xc2,0x5b,0xba,0xef,0x47,0x24,0x07,0x75,0xd1,0x5a,0x56,0x19,0x5d,0x88,0xcd,0x07,0xc3,0x74,0x8e,},{0xca,0x0b,0xea,0xfd,0xf7,0x31,0xd8,0x93,0x01,0xf7,0x72,0x3c,0x5b,0xb7,0xe5,0xa1,0xc3,0xff,0x3e,0xab,0x27,0xc9,0x7d,0x71,0x1b,0xcd,0x76,0xe4,0x20,0x54,0xbe,0xe4,},{0xae,0xf7,0x56,0xbf,0xb8,0xa7,0x26,0x6e,0x17,0xd1,0x5f,0x3f,0x11,0xee,0x50,0xed,0x25,0xbe,0x42,0x0e,0x95,0xa0,0x74,0x22,0x71,0xeb,0xd1,0x22,0x94,0xe2,0xcb,0x96,0xea,0xd0,0x83,0xb8,0xff,0x0b,0x82,0x9d,0x2e,0xde,0xb1,0x4d,0xa8,0x6e,0x40,0x2e,0xf2,0x5e,0x6d,0x4a,0x5a,0x79,0x58,0xc1,0x84,0xed,0x10,0xc1,0x76,0xcb,0x57,0x0b,},"\xc4\x84\x14\xf5\xc7\x57\xd0\x3c\x52\x3e\xf3\xf3\xb8\x51\x07\x71\xb0\xff\x3b\x4b\x97\xde\x27\x96\x25\xd3\x49\xec\x18\x5a\x29\x92\x7a\x66\xb9\x59\x3b\xa1\x93\x38\xc2\xf5\xe4\x13\x1f\x1a\xc0\x7e\xa4\x6d\x2c\x1b\x6e\x4a\xb5\x22\x92\x80\xb2\xe2\xbb\x9d\x14\x0d\x1e\xf7\xaf\x7b\x16\x92\xbf\x2d\x09\x7b\x80\xf8\x11\xad\xcf\xa9\x5d\x5c\xbf\x9e\xee\x92\xa1\x64\x1c\x55\x2b\x4b\xe4\xa0\xd7\x34\xf0\xaf\xd4\x70\xb9\xd7\xf4\xe4\x57\x78\x95\x1e\x21\xfc\x53\x4f\x20\x0a\x12\x8b\x96\xad\xb8\x37\x3f\x10\xce\xce\xc2\xda\xc2\x99\x6a\x06\x2f\xb3\xc2\x94\x31\x59\x65\xa9\xd5\xd7\xb0\x77\xc4\xb0\x13\xc6\x4a\x38\x42\x97\x69\xd2\x3e\xab"}, -{{0x6b,0xdb,0xbe,0x06,0xd9,0xf4,0x21,0x9e,0xea,0x64,0x03,0xa3,0x57,0xb2,0x5e,0x56,0x19,0x92,0xfa,0xe0,0xf0,0xf6,0x14,0x56,0x1d,0xd8,0x6d,0x23,0xde,0x41,0x5a,0x43,},{0xed,0x52,0xdd,0x1c,0xce,0x32,0xd9,0xb4,0x85,0xe0,0x94,0x07,0x46,0x42,0x1d,0x36,0xb9,0xfd,0xe6,0xcd,0xf0,0x21,0x15,0x45,0xb6,0x34,0x04,0x4d,0x4b,0x3c,0xb8,0xf1,},{0x95,0x02,0x06,0x60,0x5b,0x0f,0x41,0x7c,0x90,0x84,0x3e,0x2c,0x8d,0x8e,0x66,0xc8,0x28,0xbb,0x10,0xb9,0x9b,0x36,0xee,0xee,0xe8,0xca,0xf2,0xe0,0xe5,0x48,0x4d,0x93,0xfe,0x02,0xbf,0x53,0x34,0x05,0xf4,0xbb,0x74,0xa5,0x0e,0x55,0x85,0xfa,0x0d,0xae,0xf4,0x82,0x1f,0x03,0x01,0xd0,0x1b,0x46,0x32,0x1b,0xaa,0x31,0xe1,0xf0,0x8d,0x03,},"\x58\x2a\xda\x13\xd6\x92\x93\xe4\x9b\xbd\x46\x10\x32\xdf\xea\x1c\xa2\x02\x5b\x52\xe0\x13\xa3\x3a\x03\x87\xfc\xfc\x5f\x7c\x0b\x8e\xc9\x55\x98\x26\x07\xfc\x90\x1e\x1b\x7f\x63\x6a\x9d\x37\x1e\x1f\x91\xfe\x47\x6b\xdd\x44\x85\x6e\x27\x5d\x67\xef\xa1\x42\x38\x16\x43\x54\xc2\x31\x12\x4c\x84\xde\x8f\x5b\x89\xd5\xa5\x8e\xa6\x74\x4b\x4d\x3b\x3d\x79\x06\x90\x52\x33\xcc\xe6\x94\xa6\x4d\x69\x6f\x5a\x70\x24\xfc\x90\x33\xb1\xce\x39\x08\x99\xa3\xb4\x41\xa4\x8e\x53\xc7\xc9\xb3\x0b\xa1\x2e\x7d\x61\xf3\x5f\x15\xe6\x58\xc7\xcc\x44\x07\xe2\xf6\x89\xea\x8a\x55\xd0\x1b\xf5\xdb\xac\xb1\x19\x54\x75\x4f\x92\x0f\x09\xdb\xd4\x84\x09\xbb\xb5"}, -{{0xd7,0x61,0xc8,0xc5,0xa9,0x60,0x1b,0x91,0x45,0xb7,0xd0,0x51,0x24,0x9b,0x00,0x41,0x07,0xe4,0x52,0xe5,0x63,0x10,0x0c,0x6c,0x78,0x80,0x38,0xc9,0xee,0x8a,0xda,0xd7,},{0xe6,0x48,0x87,0x75,0xd6,0x40,0x7e,0xfc,0x7b,0x2b,0xca,0x89,0x0a,0x7f,0xc6,0x22,0x66,0xfc,0x54,0xcd,0xac,0x89,0x33,0x43,0xb4,0xf5,0x9a,0x19,0x6d,0x94,0x88,0x98,},{0x7a,0xb7,0x8b,0x64,0xe6,0xdb,0x35,0x9a,0x2d,0xc8,0x30,0x2e,0x10,0x92,0xed,0x66,0xfa,0x73,0x6b,0x53,0x62,0x53,0xa1,0xcd,0x90,0xfd,0xb8,0xc1,0x0e,0xfd,0x78,0x30,0x02,0x25,0xe1,0x91,0x96,0x35,0x99,0xba,0x54,0x9c,0xc8,0x59,0x20,0x9d,0xf0,0xff,0x61,0xcd,0x06,0x9b,0x03,0xd2,0x54,0xe6,0xe7,0xd7,0x6c,0x79,0x84,0x40,0xf9,0x07,},"\x84\xea\xd5\xea\xbd\x2f\xd4\xb7\xc7\x9a\x9a\x92\x8a\xb8\xee\x0a\x16\xa5\xfd\x66\x7a\x05\x7f\x8a\x25\x46\x63\xd5\x6d\xaa\xe1\x56\xd1\xa4\x9a\xff\xb2\x99\x61\x37\xb9\xd8\xb3\x40\xe6\x35\x73\x2f\x9d\x2b\x4c\x60\x21\x84\x42\x54\x1e\x72\xd2\xb0\x0e\x1e\xe7\xa7\x3c\x3f\x67\xca\xa4\x99\xfa\x9d\x07\x0b\x57\xd0\x76\xdc\xde\x96\xb0\x76\x47\x23\xc3\xc6\x59\xc7\xa0\x0c\x1b\x78\xb1\x5c\xcc\x22\x23\x89\x0b\x51\x06\x7f\xc8\x1e\x23\xe9\x45\x8a\xb0\x68\x3b\xa6\x26\xa5\x3d\x0c\x37\x93\xa5\x8a\x98\x57\xbb\x44\xb3\xbd\x85\xbb\x6c\xe5\x3a\x85\x69\x4e\x7f\x53\xcc\x1b\xd4\x6d\x50\xed\xa3\x7d\x81\xf5\x38\x1b\x51\x3d\x1f\x38\x33\x9d\x29\x1b"}, -{{0xc5,0xe0,0xc7,0xa7,0xbb,0x8b,0x7c,0xa0,0x7b,0xf0,0xa0,0x5e,0xa6,0x7e,0xff,0x6d,0xee,0xbf,0xe3,0x71,0x4e,0xe3,0xe1,0xa2,0x27,0xf4,0xdc,0x8e,0x24,0x2a,0x2f,0xa0,},{0x51,0x35,0xef,0xcd,0x90,0x52,0xbe,0xc5,0x7a,0x44,0x31,0xca,0xab,0xe8,0x26,0x80,0xee,0xc0,0xa3,0x3a,0xfd,0x59,0xb3,0x02,0x03,0xb2,0x80,0xba,0x12,0xbe,0x48,0x5c,},{0x2e,0x7f,0xde,0xb3,0x48,0x4d,0x0a,0x5e,0x8d,0xce,0x94,0x44,0x89,0x79,0x49,0x6b,0x06,0x42,0xca,0xbc,0x37,0x33,0xa5,0x1f,0x8c,0x3c,0x5c,0x51,0xc1,0x9a,0xe3,0x19,0x01,0x8d,0xa9,0x10,0x91,0xc2,0x38,0x5f,0x2f,0x4e,0x9a,0x59,0xed,0xbc,0xa2,0xab,0xd0,0xd0,0x85,0xee,0x40,0xd3,0xf0,0xd4,0x20,0x61,0xa5,0xa9,0x83,0x2a,0x37,0x0c,},"\x37\x70\xa6\x78\x66\x52\xc4\xb7\x8a\x04\x3e\xdc\xe0\x7f\x3e\x20\x4d\x81\x99\x7c\x42\xaf\xc2\x23\x31\xf7\x5a\x54\x94\xa8\x26\xd7\xcb\x69\xab\x43\x14\xa4\x73\x72\x10\x58\xa1\x83\x99\x81\xd5\xb7\x02\x2d\x0c\xd8\x67\x03\x77\xda\xf3\x32\x04\x76\xd2\x5b\x9f\x55\x95\x61\xd6\x6e\xe0\xa7\x09\xfe\x17\x36\x1e\x2a\x52\x89\x8f\x57\x53\xc4\xfb\x43\xbd\x0c\x98\xb3\x68\xf5\x12\xad\xc0\x9c\xd9\x27\xc6\x62\x26\x76\x92\x6d\x8c\x2d\x91\xa1\x4a\xca\x32\xf2\x26\xf7\x00\x36\xc1\xc8\x58\xbc\xff\xc2\xb5\x9f\x54\xc1\xc3\x7b\xf8\x1e\xb5\x2e\xcb\x3f\x00\xda\x60\x2c\x94\x36\x1b\x52\xa5\xaf\xdd\xbf\xd7\xe0\x50\x36\xe3\x77\x50\x30\x50\x33\x3b\xe5\x12"}, -{{0x11,0xbb,0x47,0x48,0xd2,0x54,0x7e,0x61,0x96,0xbe,0x82,0x3c,0x9b,0xe7,0xaa,0x18,0x15,0x0c,0x20,0x4b,0x12,0xca,0x8d,0x73,0xc1,0xbd,0x46,0xb1,0x1a,0x54,0xb4,0x75,},{0xef,0xeb,0x42,0xda,0x28,0xd7,0x64,0x96,0x64,0x03,0xdd,0x30,0x0d,0x9f,0x94,0x51,0xb2,0x58,0xab,0x1c,0x80,0xdf,0x06,0xfe,0x59,0x43,0x15,0x3f,0x53,0x01,0xcc,0xcb,},{0x44,0xc5,0x8d,0xa4,0x9d,0x23,0x65,0xd2,0x70,0x29,0xd1,0xee,0xbb,0x3b,0xeb,0xf7,0xc0,0x32,0xd8,0x58,0xaa,0x07,0xe0,0x75,0x6b,0x1c,0x26,0xa5,0x41,0x2d,0x22,0x69,0x11,0x76,0x03,0x13,0x41,0xad,0x37,0xd7,0xbb,0x78,0x43,0x28,0x9e,0xb3,0x9d,0xb4,0x91,0x58,0x4c,0x1b,0x2a,0x1d,0xa2,0xe4,0xa2,0x64,0x9c,0x22,0x93,0x82,0x66,0x06,},"\xf4\xb7\x65\xb2\x58\xba\x35\xb4\x27\x52\x5c\x7f\x10\xa4\x6f\x0b\xcc\xd3\x57\xec\x1a\xd5\x2a\x5b\x13\x94\x17\xa9\xd3\x89\x4c\x51\x2d\x89\xeb\x88\xe6\x81\xb1\xf3\x0a\xac\x4c\x11\x5c\xcf\x36\x54\x5e\x83\xf3\x78\x34\xc8\x2e\x83\x00\xcc\x1e\xb2\x89\xaf\x43\x75\x96\x8c\x29\xc0\xff\xef\xb4\x0e\x15\x6c\x20\xc0\x43\x26\x69\xac\x8d\xc0\xa8\x3c\x13\xb1\xe8\x55\xa8\x4a\xd0\x13\x3c\x40\xc8\x2c\x87\xee\x1e\x7d\xd4\x08\x4d\x74\x1c\x80\xde\x8a\x7a\x9f\x77\x59\xe8\x43\xa5\x62\x09\x9c\x4d\x7d\xf8\x75\x35\x20\x39\xff\x4d\x38\x24\x65\x13\x86\xc9\x77\x59\xff\x7d\xba\x52\x06\x4e\x6d\x31\x12\xe0\x80\x81\x9a\xee\x8c\xe7\x23\xa1\xa2\xaa\x46\x4d\x8a"}, -{{0x74,0x52,0xa0,0x01,0x56,0xd7,0x94,0xed,0xeb,0xff,0x4a,0xdb,0x1f,0x7a,0x7e,0xec,0x26,0x21,0x7f,0xef,0x67,0xc3,0xd2,0x68,0x35,0x2b,0x2b,0x54,0x60,0xa7,0xdc,0x25,},{0x5f,0x4d,0xc3,0x38,0xcf,0xbd,0x38,0x4b,0x5f,0x1c,0x14,0xc2,0x26,0x70,0x14,0x46,0xb5,0x2b,0x1e,0x3e,0x2a,0x3c,0xba,0x1a,0x40,0xee,0x28,0x25,0x08,0x0d,0x1d,0xe6,},{0xa8,0xf9,0xfa,0x24,0xa3,0xde,0xa1,0x02,0x2e,0x73,0xf0,0xd8,0x8b,0x1c,0x37,0xd0,0x6d,0x0f,0x0b,0x20,0xbb,0xff,0x0e,0xcd,0xb4,0xa4,0x0c,0x86,0xd7,0xe4,0x75,0x61,0x7c,0x03,0x57,0x0a,0x74,0x19,0xd7,0x4b,0xa0,0xf1,0x32,0x70,0x96,0xbf,0x19,0xf0,0xd0,0xcf,0x9f,0x51,0xd4,0x83,0x11,0x2f,0x26,0x92,0x23,0x78,0x68,0x2f,0x48,0x07,},"\x8c\x4e\xe2\x86\x76\x56\xe3\x3f\x52\x69\x41\x4d\x77\xb4\x2d\x8e\x47\x50\xdb\xa9\x3c\x41\x8b\xac\xca\x10\x93\x8c\xc3\xb5\x70\xc6\x60\x3d\x52\xc2\x34\x44\x88\x60\x7b\x2f\x93\x4f\x6d\x26\x9f\xcb\x2a\xd9\x66\x21\x9b\x1a\xb1\x14\x72\xf4\x2c\x67\x2c\xe2\x05\x92\x49\x0e\xc5\xba\xf6\xa2\xd2\xfc\x8a\x3e\xe3\x53\x74\xb1\x90\x2f\xde\xfc\x78\x70\xb1\xb6\x26\xfa\x46\xb1\x2b\x6c\xee\x24\x1f\x60\x1a\x9b\x3f\xe4\xc5\x08\x12\xe5\x73\xe6\x75\x2c\xe2\xc7\x64\x4e\x33\x67\xa6\xa6\xb7\x77\x58\xd8\xe4\x93\x4b\x58\xaf\x23\xab\xae\x8f\xec\xac\x25\xed\xd7\x34\x03\x0e\xe7\xcf\x39\x90\x7e\x3e\xed\x81\x86\xa1\x9a\x80\x71\x03\xa9\xfc\x49\xd3\x8f\x4c\x84\x60"}, -{{0x88,0x0e,0xf1,0x06,0x73,0x3f,0x04,0xe7,0x61,0x95,0xeb,0xa2,0x80,0xb3,0xfa,0xdd,0xa0,0xf2,0x5d,0xcf,0x96,0xa6,0xa9,0x9c,0x8c,0xcf,0x84,0x2c,0x68,0xaf,0xda,0xe5,},{0x70,0xce,0xe3,0x3d,0x41,0xc7,0x28,0xce,0x7b,0x14,0x19,0x31,0xe6,0xe8,0x52,0x45,0x67,0xd7,0x60,0x1e,0xb7,0x9f,0x67,0xfd,0xcd,0x07,0xb9,0xd6,0x82,0xc6,0x50,0xf0,},{0xff,0x6c,0xae,0xdd,0x8a,0x46,0x8a,0xa0,0x7d,0x4c,0x6e,0x71,0x31,0xbb,0xda,0x76,0x18,0x2b,0xa9,0x58,0x64,0x93,0x76,0xe7,0x11,0xf4,0x4c,0x7b,0xba,0xcb,0xa6,0x07,0x7b,0xea,0x87,0x8b,0xa5,0x94,0x9c,0xde,0xee,0xf0,0x5c,0xfd,0x49,0x83,0xb0,0x05,0x7d,0x27,0x5e,0xa3,0xe1,0x8c,0x32,0x65,0x94,0x68,0xc3,0x0c,0x47,0xac,0x8f,0x0b,},"\xf4\xf3\x8d\x07\x7f\x2b\x03\xda\x82\x1b\xd3\x6f\xde\x67\x3d\x66\x6e\x52\xf4\x83\x2e\x1c\x0d\xcf\xee\xf0\x49\x32\x8a\xcb\x7b\xd7\x1a\xd2\xbf\xc4\x9c\x12\x35\x16\xe1\x96\xc4\x70\xdf\x08\x47\xb3\x84\x8a\x45\xa2\xc6\x9b\xea\x03\xe2\xaf\xa7\xe5\x82\x05\xb6\x3b\x52\x38\x14\xfc\x8e\x24\x2f\x05\x9c\x69\xff\x7e\x40\xf9\x7b\xe8\x12\x5b\x70\xa5\x4f\xda\xf3\x5a\xea\xfa\xc7\x91\x14\xa7\xb4\x19\xe6\xbb\x9e\x70\xbf\x07\xad\xb5\x59\x81\x96\x00\xdc\x25\xe5\x1b\x4b\x70\x0d\x27\xca\x54\x72\xa0\xe7\xcb\xbf\xd1\x4e\x09\x9f\xaa\x3a\x72\x00\x2d\xa5\x38\xcb\xe4\x5d\x62\x1e\xf0\xd5\x25\x2b\xa2\x9d\x83\xf8\xb3\xec\x83\x89\xc9\xce\xb6\xc6\xb2\xe8\xd8\xa2\x0f"}, -{{0xa2,0xd8,0x8f,0x37,0xec,0xc2,0xb2,0xc0,0x5d,0xd6,0xcb,0x31,0x59,0x96,0x2c,0x5f,0x64,0x6a,0x98,0x15,0xb2,0xfb,0x37,0x79,0x1f,0xc7,0xb6,0x06,0xe2,0x91,0x3e,0xd5,},{0x58,0xdd,0x67,0xd7,0xa1,0x5d,0x4c,0xa0,0x34,0x1a,0x4c,0x86,0x95,0x66,0xca,0xd8,0xc4,0xee,0x16,0xe5,0x83,0xa1,0x0b,0x48,0x24,0x17,0x3b,0x08,0x29,0x0d,0x92,0xd1,},{0xcc,0xf2,0x40,0x0c,0xd6,0x73,0xe1,0xef,0xfd,0x20,0x16,0x1d,0x7b,0x68,0xa5,0xfb,0x87,0xc1,0xe9,0x9d,0x36,0x35,0xd7,0x8c,0x2d,0xa1,0xb5,0x09,0xfa,0xc3,0x33,0x46,0xc0,0x69,0x16,0x3a,0x6c,0x46,0xc7,0x82,0x6a,0x48,0xbb,0xbd,0x03,0xb0,0x5e,0x6e,0x23,0x51,0xfa,0x62,0xbf,0x89,0xbf,0x7c,0xcf,0x9a,0x90,0x24,0xbd,0x15,0x7d,0x07,},"\xd1\xb8\x7e\x9e\x88\x6d\xfb\xbd\xc8\xca\x8a\xb9\x01\x0e\xcf\x9b\xba\xf2\x3f\x72\xab\x3c\xbe\x76\x9d\xb1\xd4\x3c\x2a\x47\x4a\x81\x65\x1c\x46\x4e\x9f\xb9\x27\x34\x63\x46\x41\xc9\x48\x5a\x02\x39\xb3\x11\x07\x71\xe7\xf7\x5e\x05\x25\x2e\x4d\x8f\x4c\x0a\xa1\xba\x08\x62\x6d\x7e\x96\x31\x7c\x20\xac\xde\x2a\xd9\x9b\x23\xbd\xad\xfd\x6f\x17\x46\x8e\xb4\x02\xec\x5e\xef\xa5\x7b\x47\xca\xf9\x72\xb3\xdd\x21\xd8\x9f\x0e\x29\x89\xff\x87\xd5\x1e\xd2\xe2\xd6\x39\xc1\x64\x4e\x69\x8c\xbe\x02\x21\xb8\xe1\x79\xf3\xcf\xb0\x4a\x20\xcb\x24\x70\x21\x6a\x68\x82\xfb\x4f\xf7\x99\xe1\x15\x36\xcf\x64\x21\x9f\x0c\x07\x51\x76\xbc\x7c\xf0\xf6\xc5\xb7\x92\x5f\xcd\x61\x55"}, -{{0x42,0xaa,0xfd,0x0a,0xe2,0x6d,0xf1,0xe7,0xaa,0x02,0x76,0x86,0x0d,0x75,0x27,0x83,0xaf,0x97,0x28,0x04,0x39,0xbb,0x23,0xea,0xe4,0x6e,0x3f,0x84,0xca,0xac,0x78,0xde,},{0xda,0xa2,0x35,0x0a,0xdb,0x55,0xdb,0xa9,0xdf,0x7d,0x7a,0xf5,0x10,0x19,0x98,0xfe,0x51,0x5d,0x31,0x1c,0x3c,0xba,0x3e,0xea,0xb9,0x13,0x82,0x33,0x19,0x0c,0x3b,0x4e,},{0x11,0x61,0x43,0x65,0x0b,0x6c,0x13,0x3d,0x61,0x78,0x59,0xdb,0x24,0x29,0xc2,0x91,0x35,0x79,0x79,0x0b,0x21,0x97,0xd7,0xb7,0xb1,0xb4,0x96,0x2b,0x32,0x87,0x21,0x03,0x2c,0xee,0xca,0x58,0xb2,0xd5,0x64,0x39,0xe2,0x33,0xbb,0x84,0xdc,0x52,0x5e,0x28,0x4f,0xf8,0xdf,0x2b,0xde,0x1d,0xb4,0x98,0x6f,0xaf,0xd2,0x1b,0x3d,0x7d,0x6a,0x0a,},"\x72\x13\x1b\x80\xad\x59\x9b\x6f\x5f\xf6\x98\x54\x7d\x16\xe7\x49\x9d\x71\x27\x5e\x4e\x9b\x30\x52\x6a\x5a\xac\x0b\x0c\x8b\x14\xfa\x4a\x54\x0c\xfb\x11\x45\xfc\x00\x44\x18\xbc\xd3\x18\xc1\xa7\x0e\x62\x69\xa3\xfb\x69\xba\xed\x86\xf3\x63\xf5\xb8\xf9\x7f\x56\x9c\x20\xd4\xf4\x99\x0e\x7b\xb4\xd0\xc3\x99\x21\x26\x8d\x63\x6e\xd0\x55\x4b\xd6\x2a\xcf\xca\xcd\x3b\x8e\x03\x02\x17\xaa\xfa\xc3\x04\x4c\x03\x7e\x0f\x94\xda\x18\xc6\xb9\xa0\x93\x2c\x3c\x58\x75\xd3\xa9\x3f\xbd\xad\xcf\x67\x96\x4e\xec\x9e\xc2\xbe\x69\xb4\x8f\x02\x0f\x6c\x98\x74\xde\x5f\x8a\x51\x67\xb5\xee\x02\x4a\x2c\x2e\xfd\x0c\xdc\xd2\xac\xd8\xc1\xf7\x87\x81\x41\x41\xe3\x0b\x38\xb1\x63\x17\x5b"}, -{{0xb6,0x9c,0x33,0xb1,0x1b,0xa6,0x78,0x41,0xc3,0xd4,0xe6,0xf9,0x23,0x4e,0x35,0x37,0x0a,0x28,0xb4,0x76,0x62,0xac,0x56,0x0b,0x27,0xc0,0x78,0xb6,0x6a,0xb1,0xb0,0x21,},{0x9d,0xf6,0x8e,0x9a,0xcf,0x67,0x37,0x92,0x61,0x74,0x4d,0xb5,0xd1,0xe3,0x77,0x89,0x2f,0x2b,0x69,0x2e,0xd5,0xa3,0x8b,0x37,0x07,0x3c,0x04,0xde,0x5d,0x22,0x67,0x37,},{0x24,0x36,0x8f,0xee,0x5b,0xd8,0x48,0xb4,0xc6,0x61,0xa3,0xbe,0x4f,0x31,0x0c,0xfc,0x43,0x6e,0x79,0xec,0x4a,0x78,0x50,0x1b,0x81,0x09,0x5f,0xe5,0x16,0x14,0x23,0x1b,0x6c,0xa1,0xab,0x12,0x69,0x99,0x6a,0xd2,0xe9,0x8e,0x29,0x97,0x81,0xaf,0x8e,0x29,0x80,0x4b,0x24,0xfe,0x56,0x79,0xca,0x3b,0xa6,0x50,0xc5,0xc4,0xcc,0x58,0xce,0x01,},"\xf9\xea\x12\x6d\x3a\xb2\x19\x61\xaa\x24\x33\x90\x0a\x39\x82\xb8\x3e\x0e\xf8\x6d\x52\xd1\x34\x40\xaf\xa4\x81\x7f\x9b\x82\x2f\xb5\x82\xcc\x39\x32\xbf\x45\x0d\x46\x77\xc9\x18\x81\x81\xfe\x75\x26\xad\x6f\xe5\xab\xc6\x1d\x0a\xe7\x59\xf2\x15\x01\x3c\x0b\x2b\x41\x06\x4c\xb6\x27\x8b\xa7\xe3\x9e\x2f\x4c\x10\xd6\xcc\x96\x05\xb3\x86\x9e\x16\x9d\x7d\xa4\x2e\x88\xeb\x85\x78\x70\xfe\x61\x18\xbb\x02\xbc\x08\xc8\x05\x5f\x0c\x18\x9b\x62\xf7\x9f\xb1\x46\xb4\xc5\x43\xaa\x30\xcc\x0c\xd5\x7f\x03\x7e\x9e\xf7\xa6\x37\x11\xf6\x6e\x6f\x28\x78\x93\x17\x02\x20\x27\x02\x61\x42\x77\xd5\x13\xf0\x85\x0b\x75\x85\x49\x33\x6b\x30\xcf\x40\xab\x8b\xd4\x60\xe6\x0e\x12\xde\xed\x04"}, -{{0x7b,0x63,0x61,0x3f,0x6d,0xae,0x01,0xcd,0xcd,0x5e,0x6b,0x37,0x68,0x69,0x71,0xcd,0x8d,0x8a,0x99,0x54,0x2f,0x63,0x29,0xa1,0x28,0x54,0xa9,0xd8,0xff,0x81,0x05,0xac,},{0x72,0xec,0x43,0xfa,0xf3,0x4d,0x87,0x30,0x17,0x7d,0x1f,0x07,0x43,0xc7,0x4c,0x20,0xbf,0x72,0xc2,0x39,0x4b,0x8a,0x7d,0x47,0x1f,0xfe,0x2a,0x04,0xab,0x00,0x81,0x1c,},{0x76,0xf5,0x0b,0x2b,0x9c,0x2a,0xd9,0x7b,0xfb,0x94,0x99,0xee,0x41,0x92,0x8a,0xc0,0x72,0xda,0x5e,0x8b,0xc7,0x1d,0x02,0x12,0x55,0x09,0x42,0x33,0x2b,0x62,0xe7,0x0c,0x8b,0xfe,0x1c,0x72,0x25,0x42,0x39,0x46,0x88,0xde,0xcd,0x91,0x7a,0xec,0x8f,0x95,0x35,0x3e,0x1d,0x72,0x62,0x4b,0x70,0xeb,0xed,0x5d,0x17,0xf6,0xc5,0x49,0x77,0x02,},"\x18\x16\x48\x8f\x1f\xc8\x3e\x1e\xd5\x91\x16\x37\xdd\x42\xba\x20\x77\x65\x7d\xfe\x1a\xe4\x22\xad\x0a\xee\x59\xdf\x9d\xd5\x6a\x27\x63\xc2\xdd\x0e\xf6\x1a\x12\xbb\x82\x5b\x0d\xac\x1e\xda\x5f\xbb\x69\x1c\x5e\xd5\x8f\x3f\xb3\x25\x05\x0b\x45\x63\xa4\x04\x20\x99\x98\x2f\xff\xa5\xd6\xed\x74\x2d\x95\x82\x3d\xa8\xe1\x78\x7c\xf7\x46\xef\x63\xb3\xfb\xb0\xe8\x8a\x6c\x0b\xea\xe4\xf7\x31\x83\x66\x93\x6b\x49\x17\xf5\x07\x33\x60\x68\xb1\x94\x68\x09\x00\xa7\xbf\x4a\x6f\xb6\x9a\x5c\x38\x7b\x97\xe3\x1b\xc7\xf9\xbe\x53\xc2\xa8\x9e\x36\x51\xce\x1d\xe4\x1b\x10\xe9\x21\xb2\x06\xeb\xf3\x2e\x56\x21\xef\x80\x81\x61\x6d\xcd\x7a\x20\x59\x43\x7e\xfa\xd0\x14\xbb\x8e\x2c\x82\x21"}, -{{0x35,0x58,0xd3,0xa7,0x43,0x95,0xbd,0xcb,0xa5,0x60,0xe2,0xc4,0x5a,0x91,0x96,0x0c,0xec,0x6c,0xb3,0xed,0xbc,0xd3,0x0e,0x72,0x2f,0x7f,0x05,0x52,0x10,0xf3,0x7b,0x51,},{0x53,0x4f,0x43,0xeb,0xa4,0x03,0xa8,0x4f,0x25,0x96,0x7c,0x15,0x2d,0x93,0xa0,0x17,0x5e,0xc8,0x29,0x3e,0x6f,0x43,0x75,0x31,0x9e,0xad,0xf9,0x57,0x40,0x1f,0xbb,0xd2,},{0xb3,0x65,0xb5,0x56,0x1a,0x13,0xa5,0x45,0x17,0xcf,0x90,0xd8,0x8b,0x35,0xeb,0x09,0x67,0xd6,0xd5,0x84,0x14,0xb8,0xc1,0x54,0x7e,0x69,0x31,0x59,0xe0,0x13,0x78,0x56,0x36,0x54,0xc5,0x0f,0xb4,0x23,0x23,0xf0,0x9d,0xd7,0x8f,0xfe,0x28,0x05,0x6d,0xdf,0xa5,0x4f,0xeb,0xf4,0x48,0x91,0xe8,0xa7,0x41,0xb6,0xa1,0x68,0x7d,0x72,0x86,0x05,},"\xbe\x75\x44\x4f\x9c\xe6\xbe\x1d\x83\xaf\x62\x2a\x8c\x47\x8d\x51\x01\x27\xdb\x56\xf1\xde\x6e\xb8\xa5\x12\x65\x22\xb0\x9f\xdc\x6c\xa0\x86\x2c\xec\x0b\x8b\x2a\xaf\xa3\x1c\x17\xa2\xcc\x47\x7d\xa5\x33\xd2\x76\xa1\xae\x4f\x8e\x07\x59\xd6\xaf\xa0\xb1\x74\x11\xb5\x17\x0b\x52\xf2\x05\x47\xc7\x2f\x3e\x88\xd4\x8c\xb4\x56\xfe\x62\x5b\x62\xfe\xb0\xf8\x13\x17\xed\xf1\xec\x09\xec\xe5\x34\xb9\xf5\x00\xd4\xe1\xb1\xbd\xa2\xdb\x21\x98\x2a\xa9\x50\x94\x22\x6e\xe9\xf5\xb0\xa6\x5d\xa8\x3f\x91\x12\x1c\x96\xb3\xb4\x01\x0a\xe7\x82\x6c\x9e\x80\x63\x6c\xba\x00\xf7\x0c\x3c\x8a\x27\x9b\x01\xb9\x52\x94\xcb\x85\x0f\x91\x70\x9f\x43\x76\x66\x2a\x58\x0b\x15\xac\x29\x81\xaf\xe9\xf8\x54"}, -{{0xa3,0x5b,0x92,0xf2,0x44,0x06,0x3a,0x19,0xbb,0x5e,0x3e,0xd4,0xd6,0x99,0xed,0x20,0x69,0x60,0x71,0x16,0xd2,0xbd,0x08,0x11,0x3f,0x0d,0x83,0x73,0x61,0x3f,0x35,0xb7,},{0x7e,0xc9,0x36,0x01,0x86,0x4e,0xe4,0x99,0x5a,0x4f,0x7a,0xbc,0xd3,0xdf,0xc1,0x01,0xe9,0xe7,0xf3,0x69,0xe6,0x3d,0xe1,0xae,0x68,0xa0,0x7a,0xa7,0xf0,0x75,0xb3,0x29,},{0xa2,0x3d,0xbe,0x37,0x57,0xe4,0x78,0xdb,0xc8,0x4d,0x3d,0xb3,0xa9,0x33,0xb0,0x42,0x8c,0xed,0xb6,0xb0,0x1b,0x86,0xd8,0xd7,0x3f,0x39,0x59,0x87,0x8d,0xae,0x6f,0x05,0x88,0xf5,0x05,0xcd,0x4d,0x39,0xf2,0xab,0x46,0x77,0xb6,0x48,0x05,0xd6,0x29,0x65,0x2a,0x22,0x52,0x98,0x25,0xc3,0xa9,0x1d,0x04,0x37,0x49,0xfc,0x71,0xf0,0x37,0x06,},"\x65\xcd\x36\xda\xe0\x16\x8d\x69\x97\x4f\x95\xf0\x9d\xd9\xa5\x9d\xb7\x99\xf9\x11\xe1\xa1\x5b\x85\xa0\x08\x93\xb8\xc9\xa3\xd4\x8a\x2f\x58\xac\x12\x6b\xfa\xa0\xa6\x06\xc0\x5d\x94\x70\x1d\x27\x3a\xbf\x7d\x68\x81\x7f\x2c\x71\xb1\xc5\x41\x79\x5c\x4f\x60\x95\xe2\x6c\x9d\xff\x80\x3f\x03\x2f\x75\x66\x3f\xd1\x69\x8e\xdd\x97\xff\x3a\x0e\x72\xe1\xb7\xc9\x94\x8b\x08\xba\xcb\x5f\x7d\xe5\x02\xb2\xfe\xa6\x7c\xa2\xfe\xf1\x90\xd6\x0e\xae\x92\xd1\x51\x58\xda\x44\x4a\x49\xd2\xe9\xd5\xa5\x73\xe8\xe1\x77\xe8\xbb\xf7\xe6\xc4\x9f\x90\x71\x36\xe7\x1d\x2a\x66\xcb\x07\x63\x6d\x48\x76\x8f\xf4\x17\xc8\xbe\xcc\xf4\x32\x31\x81\xfe\xfb\x31\x24\xe4\x34\x04\x9e\xa4\x5d\xd5\x01\x9e\x40\xb4"}, -{{0x72,0xd4,0xa5,0x64,0xca,0x15,0x49,0x9b,0x5e,0x4e,0x75,0xd8,0xac,0x0f,0x28,0x21,0x7d,0x32,0x11,0x4a,0x0c,0x64,0x9a,0x7c,0x8e,0xaa,0xdd,0x0c,0xc7,0x8c,0x52,0x0b,},{0xc7,0x66,0xbd,0x73,0x83,0x7c,0x4f,0xaa,0x52,0x15,0x50,0x2f,0x1e,0xfc,0x90,0xc0,0x03,0xf7,0x11,0xbb,0xef,0x55,0x17,0x00,0x91,0x02,0x8a,0x34,0x49,0x34,0x08,0xa9,},{0x8f,0xc4,0xf1,0x79,0x33,0x0b,0x64,0x2d,0xd8,0x6c,0xa9,0x36,0x26,0x51,0xb8,0x3b,0x00,0x6d,0x83,0x75,0xcc,0xef,0x81,0x1d,0x3c,0x67,0x06,0xf9,0x15,0x94,0x65,0x1d,0xf2,0x76,0x99,0x53,0x72,0x30,0x46,0xcc,0xb9,0xbf,0xe6,0x6a,0x66,0x7e,0x0d,0x11,0xfc,0x3e,0xa2,0xd8,0x22,0x62,0x34,0xfd,0xd5,0x16,0x47,0x65,0x26,0x0f,0x7b,0x05,},"\x6c\x7e\x7b\x62\xeb\x24\x4a\x45\xd7\x84\x36\xe2\x97\x0d\xcd\x6c\x0f\x7d\xb8\x22\x97\xa8\x61\x40\xea\x58\xdd\x22\xc2\x19\x5a\xdb\xc9\x56\xd4\xc4\xec\x05\x35\x4b\x21\xef\xe2\x4c\xfc\xfe\x10\xe1\x76\x22\x36\x88\x48\x18\x0d\x2c\x46\x80\xcc\x21\x5e\x8c\xee\xa6\xcc\xe2\x22\x16\x1f\x1e\x09\x22\x39\x25\x3b\x97\x46\xf7\x88\x7d\xf2\x42\x5a\xb5\xa8\x80\xbd\xba\x98\x15\x3b\xe7\x86\xdc\x83\x8c\xbe\xca\x01\x6b\x1d\x06\x52\x4b\xd6\xbf\xba\x80\x9a\x8b\xb3\x7a\xda\xb1\x5d\x42\x41\x5f\x86\xec\x03\x58\x36\x5e\xa8\x7b\x81\x50\xb0\x54\x41\xd9\xd4\x98\x46\x87\x14\x85\xca\xae\x6d\xe3\x59\x73\x6c\x27\x18\x97\x36\xd8\xf1\x76\x5f\x3e\x5c\x5f\x6b\x92\x16\x83\x96\x39\x0b\xee\x94\xcf\xbd"}, -{{0x2e,0x5a,0xaa,0xb2,0x98,0xe6,0x6c,0x2d,0xc1,0xd7,0x7e,0xa7,0x42,0x1f,0xf8,0x95,0x25,0x5f,0x9d,0x90,0x0d,0xb0,0x45,0x0d,0x63,0xf9,0xf7,0x9c,0x1a,0x70,0x13,0xcf,},{0x03,0x81,0xf3,0xf1,0x90,0x45,0x71,0x9b,0x9e,0x8c,0xeb,0x56,0x2f,0x0e,0x96,0x5d,0xc0,0x7b,0x09,0xf3,0x71,0xa9,0x63,0xa2,0x81,0xc7,0x49,0xc2,0x53,0x2f,0x65,0x4a,},{0x7c,0x74,0x30,0x30,0x5b,0x36,0x1a,0x9e,0x35,0xb2,0x78,0x0c,0x4d,0x44,0x08,0x07,0x1b,0x21,0x30,0x93,0x1d,0x39,0x83,0x0e,0xc8,0xd3,0x13,0xaa,0xfb,0xc8,0x3a,0x65,0xda,0xe1,0x9c,0xb7,0x47,0xd9,0xd1,0xc4,0xce,0x3f,0x35,0x9c,0xc8,0x24,0xea,0x8c,0x92,0xf6,0x6a,0x42,0xb8,0x61,0x4e,0x78,0x48,0xb8,0x84,0xac,0x8a,0xa4,0xae,0x02,},"\x3d\xf0\xe5\x4c\x71\x1e\x31\x32\xd7\xae\x95\x3d\xeb\x7b\x66\x86\x9e\xe5\x31\xee\x40\xb6\x3c\xe6\x93\x20\x6c\xdb\x2f\x4b\xda\x0a\x25\x69\xe9\x13\xac\x3e\x65\x32\xc5\xd9\x64\x8e\xfd\x46\x27\x78\x0f\xb8\xa3\x1d\x10\x7e\x03\x3f\x05\x4d\x19\xed\x8b\x7c\x49\xdc\x40\x7d\x2e\x94\x9d\xe2\x5f\x99\x30\x72\x21\xd3\x58\x43\xf6\xd5\xeb\x7d\xe5\xcd\xf4\x1b\x91\xdb\xbf\x34\xcb\x6c\x9c\x53\x00\x21\x01\x4b\x56\xab\xc4\x4a\xc2\x30\x03\x13\x61\x56\x08\xa7\xb4\xa2\x35\xe9\x9c\x14\xce\xf8\x05\x08\x87\x03\x22\x09\x48\x8b\x9e\xae\xaa\x82\xc0\x94\x05\xfc\x75\xbe\xc9\x4d\xd4\x2d\x6f\xf1\xb5\x99\xa6\x3e\xe5\x74\x2f\x33\x64\x09\x3a\xc9\x2c\xab\xab\x30\x35\x82\x2a\xa8\x67\xae\x56\xdc\xc9\x9d"}, -{{0xb6,0x36,0xa0,0x24,0x48,0x00,0x35,0x43,0xdb,0x86,0x4b,0x40,0xb5,0xd8,0xd6,0xdd,0x9a,0xd6,0x11,0x62,0x4c,0x9b,0x0f,0xc6,0x89,0x0c,0x51,0xea,0x55,0x92,0xc7,0x90,},{0x1e,0xf3,0x60,0x49,0x59,0x68,0xe5,0x6e,0x6d,0x3f,0xe7,0x40,0xb1,0xc8,0x4c,0x4e,0x44,0x90,0xed,0x68,0x2d,0xeb,0x43,0x05,0xaf,0xd5,0x96,0xef,0xb2,0x80,0x22,0x3b,},{0xd4,0xba,0x80,0x30,0x0d,0x5c,0xb5,0x13,0x53,0xc0,0x3f,0x28,0xc4,0x4f,0xd0,0xa4,0x24,0xff,0xe1,0xe4,0x0d,0x78,0xed,0x7b,0xb1,0x13,0x3e,0x8f,0xe4,0xe1,0x87,0x50,0x52,0x93,0xb2,0x0a,0x39,0x1d,0xa9,0x62,0xc6,0xa8,0xac,0x0a,0xce,0xc9,0xc6,0x72,0x26,0xaf,0x3b,0x61,0x95,0xda,0xbe,0x39,0xb3,0x66,0x22,0x94,0xda,0x3e,0x0e,0x09,},"\x4a\xa8\x5a\xac\x25\x03\x4f\x61\x4e\xd4\x4f\x7a\xdc\xdb\xee\xec\x25\xfc\xc2\xa9\xee\xa3\x2a\xb6\xa8\x69\x95\x06\xf7\xa1\xca\xd3\xbc\x89\x2e\x9d\xce\x93\x4e\x75\xb0\xa8\xcd\x14\x64\x2b\x77\x85\x99\x28\x6c\xfd\x8f\x50\xa9\xe4\xf2\xed\xf9\xf9\xd6\x29\x1a\x2e\x29\x79\xcf\x18\x06\xb9\x3e\xd8\xc9\xa7\x8f\xae\x19\x9b\x28\x54\xa0\x3e\xc4\x06\xab\x3f\x72\x08\x35\xee\x26\x3f\xbb\xc9\x1c\xb4\xef\x07\x58\xd7\x75\xfc\x78\x4c\x7d\x5b\x25\x1a\xc8\x93\x79\x19\xa9\xe6\x7b\xe8\x8c\x9e\x44\xcf\x2e\xc7\xf5\x60\x26\x9a\xa0\xf1\x11\x3d\x91\xb8\x44\x01\xdb\x15\xa3\xc4\x8c\x7d\xac\xff\x49\x39\xee\x01\xba\xbb\x98\x2f\xb9\x56\x25\xc6\xc3\xad\x78\x74\x90\x60\x55\x1b\xfd\xe8\xcc\xe4\xfb\x8a\x29"}, -{{0x5c,0xa0,0x54,0x3c,0x71,0xf5,0x68,0xa0,0x0e,0xed,0xf5,0x0a,0x95,0x20,0xf4,0xc1,0x5b,0x52,0x6e,0x3f,0xb0,0xda,0x81,0x6c,0x29,0xea,0x3d,0x50,0xb2,0xf6,0x2a,0x12,},{0xd4,0xa2,0x93,0x3c,0xe1,0x94,0x54,0xe3,0x31,0xb5,0x28,0x01,0x00,0x20,0x9a,0x6c,0xe8,0xe5,0x69,0xf9,0x93,0xc2,0xac,0xab,0x51,0xdb,0xe8,0x64,0xc5,0xcb,0x25,0x63,},{0x43,0x68,0x23,0xee,0xff,0x3e,0xdc,0xe5,0xd8,0x58,0x7d,0x68,0xe5,0x47,0x3e,0xf3,0xd8,0xdc,0x94,0x65,0xb5,0x58,0xb6,0xe8,0xe7,0xcd,0x31,0x37,0xec,0xcc,0x80,0xb4,0xc4,0xe8,0x06,0xed,0xf1,0x36,0x19,0xd8,0xe7,0x17,0xe6,0x9f,0x48,0xd7,0x06,0x1b,0x68,0xde,0x02,0xc8,0x20,0x9b,0xe1,0xf7,0xac,0x26,0xba,0x8e,0xdf,0x60,0x6d,0x02,},"\x4e\xf8\x49\x69\x78\xd2\x8c\x10\xab\xd5\x4a\x26\x35\x6e\xe5\x59\x21\xce\xb3\x50\xdd\x4b\x74\x2c\x41\x61\xfb\xeb\xa8\xa1\x60\x1f\x8a\xd0\x48\x4b\x21\xa8\xcf\x5a\x29\x4f\xac\x00\xec\x8a\x6f\x59\xe3\x36\x2e\x47\xbf\xae\x1e\x28\xa2\xe6\xd0\x17\xc5\xca\xa7\x5f\xb0\xf4\x84\x82\x80\x80\x37\xca\x21\x47\x69\x54\xd7\x78\xff\x1a\x05\x86\xda\x3e\xf6\x9d\x6c\xef\x6d\x2d\x8d\xf4\xae\x7a\x85\x44\x2a\x1e\x46\xc9\x98\xcf\x40\x7a\x6a\xd4\xc5\x46\x3a\x43\xc2\x48\xf3\xb6\x93\x7f\xdb\xc8\x45\xb6\x0c\x6d\x85\xe0\x56\x3c\xc1\x6b\xa9\x67\x5d\x36\x4f\x52\x5f\x66\x9a\xaa\xc9\x5f\x42\x8b\xb5\x82\x05\x09\x9f\x9e\x4a\x6d\xbb\xd0\x15\x1f\xb6\x5b\xab\xe1\x23\xe5\x39\x3a\xd6\x40\x26\x93\x5c\xb4\x88\xaa"}, -{{0x5f,0x87,0x11,0x7d,0xa9,0xbb,0xb6,0x09,0x1c,0x94,0xda,0x6b,0x23,0x0b,0x7d,0x8f,0x6d,0xe0,0xed,0x2a,0x07,0x64,0x13,0xb9,0x2e,0xac,0xdc,0x43,0xab,0xbc,0x68,0x97,},{0xaa,0x78,0x6a,0x14,0x62,0x26,0x83,0x2a,0xa7,0x3c,0x43,0x4b,0x0e,0xdc,0x2d,0x41,0xd2,0x55,0x8f,0x82,0x0a,0xb8,0xf8,0x7e,0x09,0xe6,0xcd,0xa9,0x10,0x72,0xb9,0xb6,},{0x0f,0x19,0xe6,0xea,0x0c,0x05,0xf3,0x81,0x85,0xc0,0x1c,0x2d,0x64,0x77,0x99,0x5d,0xaf,0x50,0x65,0xba,0x9d,0x80,0x17,0x3f,0xa6,0xbb,0x23,0xa7,0x74,0xdc,0x88,0xb3,0xaa,0xe8,0x79,0xd8,0xa6,0x24,0x71,0xd2,0xd3,0x04,0xcc,0x3d,0xc6,0x62,0x78,0xa7,0xab,0xcb,0x0b,0xb0,0x77,0x1c,0xd2,0x78,0xe1,0x1e,0x7b,0x93,0x2e,0x9f,0x9b,0x0f,},"\x22\x97\xc4\x0a\x2e\x83\x65\xba\xe4\xc5\xf0\x63\x0c\x50\xb1\x3b\xdd\x9a\xd9\x77\x0a\x5d\x9a\x94\x51\xd0\x08\x74\xb0\x23\xd2\x5e\xcd\x46\x8b\x96\x57\x1b\x2f\x16\xdc\xb1\xb0\xd3\xd7\x56\xc1\xf0\x44\xfc\xdd\xd1\xc5\x1f\x27\x72\x7a\x03\x69\xc9\xcf\x25\xbd\x6a\xa5\x95\x51\xb5\xb0\x7c\xf8\xf8\x07\xd9\x2b\x15\x91\x98\x63\x97\x04\x74\x0f\xe6\xed\xa0\xf2\x6d\xba\x7e\x75\xd4\x53\x0b\x28\x00\xf0\x3f\xb6\xaa\x67\x7d\x84\xdf\x75\xd6\x8d\x4f\xbb\x64\xad\x21\x00\x1e\x3f\xc8\x7b\x60\x9b\x9c\x25\x1e\x8c\xcb\x12\xbb\xca\x92\x74\x47\xe2\x05\x4e\x07\x68\x8e\xb8\xa2\x05\x21\xa5\x22\x49\xe7\xb9\x43\xbe\xd6\x0e\x6a\x93\xc0\x1e\x3e\xb6\x21\xf0\x46\x0c\x18\xa6\x90\xb6\xf6\xb6\x6e\xdc\x6e\x87\x43\xa6"}, -{{0xb5,0x3a,0x64,0x4c,0x92,0xba,0x2d,0xc7,0x10,0x8b,0x16,0x83,0x3f,0x09,0xad,0x59,0x17,0x84,0x64,0x37,0x22,0x5a,0x77,0x3d,0x32,0xd7,0x9c,0x97,0x73,0x3c,0x0a,0x58,},{0x51,0x58,0x18,0xc6,0x9c,0x0e,0x0a,0x17,0x06,0xb0,0x41,0x43,0x84,0x2f,0x3e,0x9e,0x27,0x14,0x48,0xfb,0xaf,0x3a,0x89,0x91,0x19,0xc3,0x2f,0x42,0x56,0x6f,0xfd,0x33,},{0x13,0xd2,0xcb,0xac,0x79,0x76,0xad,0x27,0xf0,0xbf,0x66,0x9a,0xd5,0x88,0xef,0xb2,0xc9,0x1b,0xab,0x85,0x07,0xd5,0x7f,0xb1,0x6b,0xfe,0xa9,0xca,0xff,0x2b,0x09,0x64,0xe7,0x56,0x25,0xc4,0xd8,0x08,0xd7,0xbb,0xb7,0x8c,0x5b,0x46,0x4e,0xdf,0xfe,0x49,0x49,0xec,0xfb,0xc8,0xb9,0x5f,0xf6,0xfd,0xb1,0xbd,0xca,0x27,0x42,0x06,0x81,0x00,},"\x13\x03\x6d\xaa\xee\x45\xfc\xfd\xe0\xc5\x3e\x06\xd0\x5a\xa9\xc0\x1e\xa9\x4a\x67\xe8\x6c\x6c\x53\x8c\xcb\x28\x3b\x36\x8d\xaf\x70\x78\xd3\xfb\xab\x58\x0c\x76\xec\xf8\x2b\x4e\x96\x60\xf0\x68\xdc\xbb\x50\x0b\x80\x59\x50\x17\xc5\xbe\x3c\x44\x8f\xbd\x8a\x17\xd9\x7c\x56\x43\x19\x78\x90\xe1\x67\xb3\x53\x45\xbf\x65\xe7\x5b\x82\xc8\xd6\x52\x29\xf2\xf6\x0a\xae\x27\x72\x58\x1b\xc9\x9c\x49\xd4\x16\xbc\x3d\x78\x74\x6e\xf8\x30\xf1\xaf\x94\x4f\x4a\x67\x15\xab\x4f\xfb\x01\x59\x1b\xac\x28\x57\xf1\xa9\xc9\xd1\x70\x08\x88\x78\x00\x06\xa3\x16\x07\x33\x8f\x7a\xf7\xbe\xdf\x6e\xfe\x0b\x57\x29\x9a\xc9\x15\x52\x6f\xe5\xe1\xe1\x01\x29\x87\x08\xc6\xe6\x1b\x84\x22\x0a\xfe\x95\xb5\x3f\x89\x59\x87\x45\x61\x52"}, -{{0xd2,0x7c,0x9e,0xaf,0xcf,0x88,0x15,0x19,0x90,0xbb,0x5b,0x2f,0xa8,0x44,0x3e,0x70,0x9b,0x5f,0xd8,0xd7,0x8d,0x23,0x38,0x03,0x32,0x2d,0xc8,0x6d,0x93,0xd9,0x32,0x95,},{0x08,0xe0,0xef,0xf5,0x29,0x77,0x67,0x14,0x68,0x61,0x96,0xd8,0x17,0xfd,0xf7,0x1e,0xb5,0xb6,0xe8,0x32,0x65,0x16,0xef,0x48,0x9b,0xfe,0x18,0x6a,0xc5,0xc5,0xbf,0x6d,},{0xc2,0x54,0xe3,0x71,0x44,0x56,0x33,0x13,0x74,0x42,0xee,0xfe,0x40,0xad,0x4a,0x82,0xe6,0x9b,0x1e,0xbf,0x48,0xa6,0x85,0xa2,0xbc,0x6f,0xfb,0xac,0x12,0x6d,0x22,0x84,0x87,0xb2,0xe3,0x53,0x7c,0x97,0xef,0x74,0x10,0x34,0x20,0x91,0x96,0x2e,0x50,0xc0,0xcb,0x85,0xde,0x7b,0x39,0xce,0xb4,0x1a,0xc4,0x07,0x8d,0x40,0xf3,0x40,0x71,0x06,},"\x77\xc3\x5b\xda\x32\xa5\x96\x7d\x8b\x30\x2f\xa7\xa4\x75\x83\xce\xab\x89\xc9\xa6\x09\xa6\x67\xb7\x53\x15\x5f\xa6\x99\x6f\x86\x31\xd0\xeb\xed\xfe\x0a\xc3\x64\xc7\x7e\x85\xba\x37\x31\x1f\x0d\xe5\x7a\x0d\xc2\xc1\xe9\xe4\x00\xd5\x8b\x42\x4a\x32\x2e\x1d\x57\x71\xe0\xa9\xfd\x95\x02\xad\x02\x32\xce\x54\x4f\x07\xd8\xc6\x6e\x7c\x31\x47\xf8\x60\x7a\xc6\x18\x9b\xb6\x90\x66\xf2\xfa\xd6\x31\x18\x5f\x45\x7f\x46\x7e\xba\x33\x22\x8e\xcc\x40\xe8\x94\xa7\x7b\x57\x16\x98\xa9\xbf\xac\x84\x1a\x54\xea\xc5\x21\x9d\xa9\x9c\x6a\x91\x25\xc4\x69\xa2\x2f\xe8\x1f\x3b\x95\x14\x33\x89\x6f\x19\xce\x39\xb3\x73\xfd\x7e\x5c\x7b\x65\x0a\x5e\xf2\x36\x5a\xe7\x51\x0b\x0d\xa5\xe4\x9d\x7c\x07\x07\x3c\xf1\x66\xa9\x83\x87\xe8"}, -{{0x70,0x21,0x3d,0x3a,0x79,0xc6,0x5d,0x6d,0xbb,0xa5,0x42,0xa3,0x67,0x96,0x35,0x00,0x3a,0x68,0x2a,0xf5,0xfa,0x58,0xde,0x6b,0x0d,0x65,0xbf,0xa2,0x41,0x84,0x90,0x1c,},{0x44,0x02,0xfb,0x92,0xcc,0x12,0x49,0xdd,0x1a,0xe1,0x69,0x0f,0x03,0xb3,0xec,0x4f,0x1e,0x9b,0xda,0xb0,0xde,0x5b,0xfd,0x28,0x9f,0x10,0x29,0x68,0x30,0xfd,0x40,0x3e,},{0x5b,0x6c,0xe2,0x77,0x4d,0x40,0x0e,0xce,0xa8,0xa8,0x08,0xf5,0xfd,0x0a,0x79,0x7f,0xfc,0x61,0x16,0x75,0x23,0x76,0xcd,0x7b,0xfa,0x3b,0x2c,0xca,0x3a,0x84,0xd5,0x59,0x3f,0x5c,0x03,0xad,0x3e,0xec,0x1d,0x89,0x53,0x22,0x75,0xc4,0x7b,0x7c,0xe2,0xa0,0xe9,0xc5,0x9c,0xc4,0x02,0x8a,0x8a,0x65,0xe5,0xbb,0x90,0x97,0xea,0x71,0xc2,0x08,},"\xcd\x6e\x1c\xd9\xc9\x0f\x56\x6d\xe0\x43\xd7\x5d\x72\x44\xec\xfd\xb3\x8e\x8b\xde\x2f\x9a\x6c\xd5\xa4\xfd\xac\x72\xb5\xed\xe6\xaf\x62\xd9\x81\x91\x8c\x5e\x61\x0a\x38\x78\x92\x74\xfa\x10\xe5\x27\xf8\x5f\xad\x20\x9b\x76\xca\x1c\x28\x1a\xd5\x89\x0f\x9c\x96\xd3\x5d\xe5\x22\xf1\xdd\xcc\xb5\x39\xb8\x79\x8a\x00\x67\xac\xdd\x45\xb6\xe3\x44\xa5\xd9\xa9\x77\x31\xf5\x45\xff\xa4\xb1\x7b\x87\x5c\x67\xb4\x8e\x9d\x4c\x4b\xa7\x2c\x98\xa4\x50\x55\x83\xfd\xbf\x1e\x12\xf2\x2b\x5a\x7a\x49\x47\x46\xcc\x9b\x6c\x1b\x57\x19\x06\xc6\x7f\xcc\x88\x3a\x9c\x15\xa3\x80\x68\x75\xb6\x59\xe5\x81\x6b\x42\x76\xc3\x19\x0e\x25\xcc\x1a\xc3\xde\x47\xbf\x99\xc4\x99\x65\x38\x8f\x54\xf3\xef\x8e\xb5\x69\x90\x6c\x60\x08\xe5\xfb\xbd"}, -{{0x5d,0x54,0x0b,0x3b,0x14,0xf0,0xc0,0x17,0x5c,0x04,0x7e,0xaf,0x02,0x6c,0x90,0x70,0x65,0x9e,0xf1,0x3e,0x9d,0x28,0xe0,0xc5,0xc5,0x16,0xa4,0x28,0x26,0x9b,0x14,0xeb,},{0x1d,0x2d,0x4d,0x55,0x1a,0x57,0xc6,0xfb,0x2b,0x04,0x18,0x10,0x49,0xd4,0x03,0x9d,0x57,0x5c,0xf8,0x0c,0x0b,0xc6,0xec,0x70,0x33,0x06,0x7f,0x27,0x30,0x93,0x44,0xde,},{0x32,0x52,0x7d,0xa7,0x55,0x31,0x28,0x89,0x93,0x5d,0xd5,0xee,0x91,0xb1,0xbb,0x11,0x7a,0x5d,0x37,0x7d,0xd2,0x3e,0xf5,0xb7,0xe1,0x5b,0xaf,0xfa,0xe9,0xa5,0x43,0x91,0xa3,0xfd,0x23,0x4b,0xdc,0xe0,0x73,0xe0,0x98,0xc5,0x8d,0x05,0xbf,0x19,0x5b,0x4c,0x3c,0xc6,0x39,0x72,0x38,0x3b,0xa4,0xb5,0x10,0x72,0x97,0x1a,0xeb,0xcb,0x62,0x0d,},"\xe4\xc9\xe8\x70\x68\x98\xca\xd4\xac\x68\xd7\x3c\x13\x0e\xfa\x04\xa5\x4f\x8c\xa2\x59\x19\xea\x6b\xfa\xa5\x4c\x8c\x72\x0c\xed\x85\x4c\x5e\x95\x09\x10\x2c\x7b\x88\x5a\xed\xdf\xfb\xd1\xb7\xf2\xc5\x92\x25\x83\x67\x7a\xc9\xee\xa9\xa1\x08\xc7\xe8\x3e\x88\x71\xae\xd5\xa0\x84\xf5\x44\x0b\x0f\x39\x1a\xd7\xff\xc6\xba\xb4\x57\x4a\xf1\xb9\x67\x70\xf4\x37\x0e\x8e\x98\x8e\x85\xec\xb1\xa8\xd6\x03\x4f\xc3\xd7\xf4\x9f\x74\x22\x02\x3b\x9d\xab\x5d\x0c\x16\xbe\xab\x5f\x5d\x37\xb0\xa4\xd7\xde\x19\x7a\xd8\x7c\xd4\xff\x8c\xe7\x8e\xb1\x2e\x1d\xaf\x73\x9d\x8b\x47\xab\x38\x0a\xbe\x90\x93\x35\x6d\xb5\xb5\x97\x17\x75\x1a\x49\xe1\x94\x84\x72\xfd\xac\xc2\x59\xff\xff\xc8\xc1\xdb\xae\x59\x26\x07\xd4\xec\x71\xcc\x6a\x8f\x6b"}, -{{0xca,0x41,0x76,0x9c,0xaf,0x17,0x17,0xb4,0xe4,0x5c,0x93,0xc1,0x21,0xdc,0x82,0xa5,0x34,0xfb,0xc6,0xec,0x09,0x86,0x66,0x2c,0x32,0x22,0xd7,0x14,0x92,0xbd,0x11,0x76,},{0xaf,0x3f,0x89,0xf6,0x18,0x7d,0xbc,0xf9,0x21,0x77,0x50,0xc6,0x7e,0xf8,0x9e,0xd4,0x7b,0x03,0x9f,0x9e,0xb0,0x62,0xff,0xec,0x9d,0xf6,0x4a,0xb5,0x2b,0x0b,0x45,0xcb,},{0x5c,0xda,0x87,0x2f,0x7e,0xd6,0xd7,0xc9,0x02,0x18,0xac,0x10,0xbe,0xe8,0xe2,0x14,0xf3,0xb3,0x4d,0x15,0xd2,0x5c,0x39,0x25,0x5e,0xc9,0xe6,0xb0,0x17,0x7a,0xa3,0xcb,0x73,0x68,0xd1,0x1c,0xb8,0xed,0x6f,0xf5,0xcf,0x0c,0x04,0x28,0x1d,0x06,0xbc,0x42,0x72,0xb8,0xbc,0x09,0xc2,0x3f,0x6f,0x4c,0xd5,0xa8,0x10,0xdd,0xc7,0xb9,0xc1,0x03,},"\x9d\xe8\x47\x6c\x58\x13\x84\x8a\xb1\x45\x15\x37\x84\x1c\xc1\x78\x00\x21\x81\xa2\x18\x2a\xf3\x05\xb1\x2e\x5f\x7c\x3b\x1d\x56\xb2\x2c\xf4\x6a\xe6\x27\x6d\x18\x26\xec\x0a\x8c\x9a\x7d\x9f\x68\x08\x3b\x72\x25\xbb\xfa\xef\xce\x82\xb3\xb6\x45\x94\x05\x2a\x77\x00\xf3\x09\x23\x3a\x79\xff\xfd\xfc\xcc\x5c\x21\x40\x0c\x91\xcc\x0e\x41\x8d\x51\x41\xd4\x86\xb5\x21\x99\x01\xd6\xdd\x24\x47\xc1\xf7\xb7\xcf\x5a\x08\x79\xe7\x0e\x1d\xd6\x58\xd0\xf2\xec\xf3\x1e\xbe\xee\x11\xa5\xc7\x44\x40\xc6\x3b\x9d\x8b\x45\x31\x8c\x34\x65\xd7\xff\x03\x36\x5e\xdd\x03\x85\xed\xf8\x0d\x4f\xde\xd5\x1f\x0f\x75\x33\xee\x40\x99\xf1\x9e\x93\xbc\x9d\x08\xda\xdc\xd1\x34\x85\xdb\x23\x95\x22\xff\xc8\x1e\x2c\x05\x1f\x87\x96\xd6\x2e\x97\x9f\xcf"}, -{{0xfe,0xdd,0x63,0xff,0xd4,0xcf,0xbf,0x61,0x88,0x94,0x96,0x2e,0x12,0x1a,0x90,0x25,0xee,0xa3,0x18,0xa8,0x0a,0x1a,0xdf,0x16,0x9d,0x64,0x90,0x44,0x5d,0x2e,0x02,0xa0,},{0x54,0x2f,0x22,0x44,0xbd,0xb7,0xd8,0x4b,0x87,0xe6,0x28,0xa8,0xe6,0xa1,0x2f,0x17,0xbf,0x74,0xa9,0xa6,0xd0,0xea,0x46,0xc5,0x95,0xdb,0xfd,0xc6,0x80,0xc0,0x4b,0x26,},{0xed,0x59,0xd9,0xe2,0x3d,0xec,0x34,0x94,0xb0,0xfb,0xc5,0xd1,0x0c,0xd0,0x2b,0xab,0x86,0xb3,0xeb,0x35,0xab,0xbf,0x9e,0x4d,0x4a,0x92,0x64,0x79,0xf1,0x34,0x58,0x3a,0x44,0xce,0x72,0xdc,0x41,0x22,0xac,0xa3,0x77,0xa4,0x07,0x2b,0x71,0x56,0x46,0x2b,0x74,0xe8,0xdf,0x46,0xb6,0x86,0x69,0x86,0x36,0x83,0x6e,0xf2,0x03,0x17,0x9c,0x07,},"\x2e\x2a\xe5\x84\x64\x1b\xe0\x3d\xd4\x8f\x9c\x61\x80\x77\xae\xaa\x18\x21\x2a\x42\x41\xf0\xc0\x19\x4e\xd2\x3e\x37\x0d\x74\x1a\x3a\xe1\x1a\x5f\xec\x3b\x04\x0c\x16\xea\xfa\x4a\xc8\xd1\x8a\xba\xa7\xce\x8f\x28\x69\x67\x33\x71\x89\xf0\x49\x5f\xfd\xd6\x19\x95\xcd\xe3\x1d\xd8\xdf\xc3\xdf\x57\x00\xb5\x7a\x7a\x29\x98\x0e\x9c\x82\x3f\xee\x85\xd6\x14\x51\x17\x67\x29\xe7\x27\x87\xc6\x10\x9b\x47\x35\x9b\x93\xdf\xd6\x2e\x1e\x5a\x2d\x64\x2c\x05\x72\x42\xda\xe5\x00\xa9\x4c\xa1\xa9\x3b\xc5\x7b\xe1\xad\xe7\x6f\xe4\x50\x1c\x0f\x63\x77\xed\x0e\x92\x46\x17\x9a\xec\xdd\x99\x46\xb6\x71\xe8\x19\x0e\x1e\xd2\x3f\x96\x6e\x96\x40\x9b\x94\x82\x22\xd8\xea\x58\x39\xde\x90\x4f\xc5\x13\x48\x07\x3b\x8f\x40\xed\xbd\x9b\x4a\x4b\x22\x75"}, -{{0x38,0xf2,0x18,0x4e,0xaa,0x55,0x36,0x56,0xee,0x29,0x02,0x70,0x6b,0xce,0xc4,0xac,0xb5,0xaf,0x25,0x15,0x7c,0xa0,0xf6,0xa2,0xd4,0x8d,0xe8,0x52,0x85,0xfa,0x3b,0xc0,},{0x7f,0xf0,0x3f,0xb4,0xc8,0x2e,0x9c,0x15,0xd6,0x59,0xdf,0x42,0x4b,0x3e,0x73,0xed,0x1d,0x78,0x00,0x6f,0x3e,0x0b,0x79,0xeb,0x64,0xd9,0x8c,0x13,0xae,0xc6,0xba,0x37,},{0x4a,0x64,0x13,0xc2,0xc8,0x7f,0x2b,0x38,0x56,0xa8,0xde,0xcb,0xce,0x49,0x3a,0xde,0xae,0x0c,0x69,0xc9,0x41,0x34,0x70,0x7f,0xb0,0xf1,0x8f,0x30,0x49,0xfd,0x3e,0x3d,0x05,0x1a,0xbd,0xb9,0xd4,0xbe,0xe2,0x53,0xc6,0x10,0x7c,0x02,0xd5,0x7a,0xd7,0xcc,0x9f,0x31,0x01,0xdb,0x66,0x0a,0xfa,0xc2,0xb7,0x98,0x19,0x38,0xe9,0x56,0x4f,0x01,},"\xc2\xdf\x77\xc9\xe4\x79\xf6\x19\x83\xb6\xc7\x48\x3e\xf9\x3f\xb8\x5a\x10\x3b\x21\x39\x23\x92\x65\x23\x06\x5e\xbf\xf2\x25\x7e\x85\x42\x7e\x05\xcd\xc2\x75\x82\xef\x6c\x16\xbe\x35\x3a\x3b\x25\x03\x72\xd6\x37\x0e\xec\xb6\xc8\x96\x29\x17\xeb\x65\x6f\x26\x41\x69\x01\x89\xd1\x72\xa1\x11\x05\x15\x57\xab\xc2\x49\x4e\x32\xca\xb6\x5e\xd0\x63\x3a\xff\xe9\x24\x08\xb5\x5c\x4e\xd8\xaf\x65\xe2\xc5\xe7\xaa\xb8\x87\xa3\xcc\x8d\x28\xc5\x2e\x9e\x13\x36\xd0\xb7\xbb\x3f\xe2\xcd\x84\x3e\x7f\xa1\x68\x03\x42\xf8\xa4\xaa\xfa\x02\xc4\xab\x25\x2f\x08\xc3\xd4\x6d\x5f\x00\xfd\x01\x48\x42\x63\xee\x63\x52\x84\xf6\xdb\x26\xd6\x29\x8d\xe5\xb0\xdd\x23\x8d\xa4\x0a\x8d\x2a\x93\x37\x6d\xa0\x30\x27\x83\xa0\xe3\xbe\x23\xd9\xe7\xf9\x90\xd2\x5b"}, -{{0x8b,0xfc,0xa4,0x84,0x62,0xd2,0x53,0x6f,0x74,0xb8,0x4f,0x6a,0xf5,0x9f,0x5d,0x85,0x82,0xff,0x8f,0x7e,0xc2,0x87,0x45,0xd6,0x72,0xe7,0x2e,0xb7,0x2e,0x79,0xd3,0xe9,},{0x9d,0x10,0xd2,0x75,0xc3,0xd3,0xfe,0x45,0x9f,0x7f,0xe2,0x90,0x1b,0xce,0x38,0x91,0x91,0xcc,0x84,0x83,0xc0,0xf5,0x11,0x40,0xd9,0xc6,0x2b,0x08,0xfa,0xde,0x81,0xbb,},{0x44,0xd7,0x7e,0x43,0x9e,0xf6,0xca,0x5e,0xb9,0x40,0xc6,0x0f,0xf8,0x73,0x2d,0xdc,0x16,0x26,0x9e,0xa0,0x23,0xbb,0x26,0x13,0xbd,0x44,0x7e,0xba,0x7f,0xd6,0x98,0x51,0x22,0x6c,0x48,0x19,0xce,0x8d,0x44,0x98,0x5a,0x49,0xf3,0xf4,0x1a,0xc7,0xaf,0x33,0xc4,0x7f,0xfe,0x5f,0x89,0x30,0x4a,0x32,0x56,0xe4,0x45,0xf8,0xd6,0x86,0xe3,0x07,},"\x81\xee\x4c\xb9\xc4\x5d\xa6\x91\xda\xcd\x7d\xd0\x9a\xff\x59\x73\x72\x67\xbb\x55\xc3\xad\xe1\xba\x32\xc1\x7b\x7d\x0d\x2d\x0c\x60\x79\xc3\x9d\x5f\xd5\xb2\x9b\xa5\xf9\xc1\x76\x20\x97\x70\x98\x43\xee\xe5\x61\x2b\xd2\x0b\xc8\x18\x5b\xf6\x4d\x5c\x93\x41\x84\xe1\x36\x24\xe6\xf8\x77\xa2\xa5\xdd\xa1\x5c\x0d\xf6\x2a\xfb\xb9\x70\x57\xcc\x91\xca\xc9\xa1\x84\x06\xa0\xe0\x10\x9c\xc3\x9b\x2e\x3f\x81\x2e\x22\x7a\x40\x62\xd5\xef\x81\xc9\x2c\x22\xa7\xdc\x79\x7c\x84\x5d\x71\xeb\x6e\xa9\xe4\x2e\xc8\x41\x7f\xba\x90\xa9\x6d\x2b\xb1\x43\x94\x18\x33\x0b\x4b\xb2\xf9\x9c\x6d\x63\xd3\x04\xa0\xe5\x06\xdc\xa9\x65\x3e\x5d\xe0\xdd\x56\xe3\x09\xdb\x1a\x76\xa0\xfa\xab\xab\x16\x37\x74\xf0\x00\x08\x8c\xef\x3d\x1b\x7a\x6c\xf6\x61\xd2\xe1\xd9"}, -{{0xd7,0x48,0x0d,0x42,0x72,0xbc,0xb1,0x55,0x7b,0x1b,0xbe,0xe0,0x49,0x15,0xc1,0x26,0xa5,0x2c,0xa6,0xd6,0xa8,0xbb,0x53,0x14,0xa0,0xe1,0xa5,0x2b,0x59,0xbf,0xc9,0x9c,},{0x99,0xc8,0x39,0xd3,0x6d,0x8f,0x5b,0x86,0x52,0x61,0x8e,0xd7,0xb0,0xfe,0x9e,0xc3,0xd9,0x4e,0xff,0xf4,0xc4,0x53,0xc5,0x40,0x63,0x14,0x76,0xa5,0x97,0x9b,0xbb,0xe0,},{0xe0,0x4d,0xc8,0x44,0x2d,0x35,0x21,0x73,0xe9,0x31,0x81,0x8e,0x29,0x08,0x58,0xde,0x85,0x68,0x8a,0x46,0x49,0xea,0x3e,0x3c,0x3a,0xe7,0x4e,0xda,0xa5,0x4a,0xd0,0x1b,0x64,0x62,0x2a,0xd8,0xa0,0x90,0xb6,0xad,0x60,0xad,0xfd,0x01,0x88,0x18,0x82,0x82,0x8d,0x39,0x07,0x8b,0xb5,0xb2,0x71,0x4f,0xd3,0xea,0x83,0x97,0xa3,0x42,0xfd,0x04,},"\x61\x5c\xc1\x9f\x94\x20\x17\x36\x5b\xa8\xbf\xa2\x56\xce\xcc\xc8\x5e\xe2\x89\xa1\xc3\x4b\xb1\x44\x2a\xcc\x07\x16\xc7\xfc\x2c\xae\xb7\x6a\x9d\xe1\x9a\xde\xc1\x06\x37\x1e\x47\xa3\x0d\x2e\x12\x39\xce\x1f\x7d\xca\x25\x52\x6d\x60\x4b\xdd\x64\x76\x59\xd9\x42\xbc\xba\xc3\x68\x91\x13\x49\xc3\xb9\x46\xa9\x7d\xa1\x0a\x42\xdb\xcf\x3c\x73\x41\x6d\x2e\x6b\xa2\x2b\xd2\x9d\x9f\x70\x56\x72\xe9\xe3\x38\x94\x4c\xef\x01\xad\x21\xf0\x09\x74\x2e\x07\xbc\xd8\x88\xca\x31\xe1\xee\x95\x3e\x8c\x1b\x1f\xd9\x54\xb7\xdc\xf1\xa0\xb1\xd5\xa0\x69\x06\x5a\x66\xcb\x72\x1a\xdc\x02\x0f\x4e\xfe\x1a\xbd\xd1\x67\x42\x74\x69\x39\x28\x57\x80\xd7\x53\x13\x7a\xe0\x14\x0b\xb4\x10\xfb\x6c\xe3\x36\x76\xc2\x7a\xee\xc5\x93\xa8\x8c\xbc\x73\xaf\xd9\xf4\x05\x11"}, -{{0x3c,0x2d,0x36,0x50,0x73,0x5b,0x41,0xef,0x90,0x06,0xbb,0x45,0xe4,0xbe,0x2e,0x0a,0xa5,0xcd,0xe8,0x51,0xae,0xac,0x42,0x1e,0xe9,0xc1,0xb4,0x92,0xd8,0x7a,0xa1,0x8a,},{0x3e,0x46,0xdd,0xce,0x29,0x88,0x44,0xfc,0xaf,0xa0,0x0a,0x1b,0x47,0xea,0xf3,0xde,0x70,0x59,0x6d,0xf1,0xbb,0xee,0x3c,0x80,0x9d,0x1b,0xe7,0xdd,0x94,0x08,0x0e,0x34,},{0x3f,0x2a,0xf0,0x1a,0xd5,0x37,0x7a,0xc3,0x90,0x40,0xd4,0x1a,0x41,0xe3,0x6e,0x7b,0x93,0xfa,0x72,0x35,0xb8,0x41,0x79,0x1f,0x43,0x2e,0xcd,0x7f,0x91,0xa3,0xb2,0x1a,0xb7,0x19,0x6c,0x88,0x3a,0xd5,0xa7,0xdb,0x44,0x6f,0x6c,0x06,0x67,0x24,0x60,0xf3,0xf6,0x3e,0xf8,0x63,0xd9,0x43,0x2b,0xe9,0xca,0xea,0xbb,0x79,0xe8,0x7e,0x22,0x08,},"\x14\x25\xd8\xd2\x18\xda\x1a\x10\xa8\x0b\x6a\x9c\x3c\x27\x50\xef\xe4\x16\x57\x98\x4a\xbd\x51\x00\xf4\x51\xba\x94\x9d\xb0\x10\x46\xb7\x12\x6b\xe8\x40\x23\x34\xed\x57\x52\x8b\xac\x05\x62\x25\x53\xa8\x6b\x72\x67\x22\x69\x5a\x8f\xb3\x31\xd8\x56\x54\x17\xc4\xff\x0f\x25\x1a\x32\x0a\xd0\x6d\xed\xbb\x75\x0d\xef\x35\xd5\x21\xc3\xc4\xcd\x57\x1a\x45\xad\xa8\x45\x06\x53\xd5\xe8\x1f\xe0\xbe\xb5\x3a\xaa\xe7\x87\xb3\xeb\x65\x3c\x23\x81\xed\x55\xaa\xf2\x59\x0e\xe5\xed\x8b\x66\x26\xf1\xc4\xb0\x43\x0a\x54\xf3\x96\x58\x62\x4e\x66\x35\xfe\xfc\x98\xfe\xe8\xfc\x3e\x1c\xc7\xff\x3d\xd4\x20\xde\x9d\xa1\x1a\x62\xfc\xae\x0e\x0c\xb4\x54\xfc\x6f\x7d\xf0\x39\x54\x29\x1d\x26\x20\x2f\x1b\x18\x8b\x65\x7b\x3b\xae\x07\x38\x94\x49\xb7\x5e\x67\x42\x2f"}, -{{0x74,0x96,0x59,0x96,0x26,0x8c,0xdc,0x4c,0x09,0x22,0x0b,0xd3,0x1c,0xe0,0x7b,0x21,0x7a,0x03,0x82,0x6e,0xe9,0x81,0xfa,0x89,0xf3,0xa2,0x35,0x9c,0xed,0x09,0x5e,0xf1,},{0x40,0x96,0xd0,0x27,0xc1,0xc5,0xee,0x4c,0xbf,0xc0,0x4b,0x9d,0x53,0x41,0x74,0x02,0x9f,0xdb,0x50,0xcf,0x56,0x10,0xd3,0x02,0x1e,0xf9,0x33,0xb4,0xca,0xf3,0x39,0x85,},{0x8c,0x66,0x28,0x34,0x43,0x17,0xa6,0x3a,0xca,0x6f,0x78,0xcf,0xae,0xa9,0x65,0xb3,0xaa,0x55,0x22,0xce,0x91,0x41,0x95,0x14,0x1c,0x08,0x87,0x0a,0x1b,0x8d,0xac,0xf3,0x4b,0x79,0xc7,0xab,0xc6,0x93,0xcd,0x9e,0x5e,0xbe,0x1a,0x2e,0x86,0xf0,0x33,0x2d,0x20,0x48,0xdb,0x3c,0xbd,0xef,0x01,0x68,0x79,0x62,0xd6,0xdf,0x24,0x9e,0x38,0x00,},"\x45\xb2\xf0\x64\x61\x5b\xf7\x74\xfc\xe9\x7f\x51\xc4\x64\x68\x5d\x7b\x3e\x4f\xef\xff\x92\x31\x24\x0a\x71\x9b\x3b\x06\x21\xcd\x4a\xd8\x33\x05\x67\x5c\xd6\xea\xae\xbf\xf7\x91\x00\x0b\x0b\x1f\xa3\x1d\x82\xd8\x18\x1b\x7f\xe5\x7c\x5e\x00\xce\xc5\x6f\xf9\x02\x2e\x9c\xe8\xdb\x66\x35\x6e\x40\x8e\x3e\xe2\x62\xfe\x62\x77\x89\xe6\x55\x35\xef\x1a\x63\xe8\xfe\xc9\x33\xbe\x3d\xee\x34\xd2\xfa\xcd\xb8\x92\x8c\xc4\x56\xab\xf2\xf3\xe8\xca\xb4\x7e\xff\x1c\xa4\x2e\x8b\x0e\x48\xd2\xc7\x3e\x7b\xcc\x5d\xe3\xf1\x05\x6f\xc5\x23\xdf\xef\x6b\x00\x23\xf3\x28\x89\xed\x39\x4e\xed\xa0\x32\xab\xf6\xbc\xaa\xda\xa7\xf3\xee\x74\x11\x87\x60\xab\x6d\x91\xdf\x52\x8b\xdc\x58\x07\x97\x2c\x85\xfa\x7c\xb5\x6e\x38\x7d\x73\x32\xe7\x79\xe5\x2d\x0d\xd7\xdb\x0c\xfb"}, -{{0x0a,0xbf,0x06,0x9c,0x08,0xb2,0x69,0x1c,0x3a,0x26,0xf7,0x9d,0xc8,0xed,0x05,0xcb,0x71,0xd2,0x20,0xff,0x78,0xf3,0xa5,0xc5,0x78,0x0a,0xe9,0xda,0x18,0xe4,0x56,0x43,},{0x9e,0xf3,0xb5,0xcc,0x01,0x6c,0xc8,0x2d,0xbd,0xda,0x70,0x57,0x66,0xaa,0x44,0x8b,0xd6,0x1f,0xa1,0xaa,0xf1,0x17,0x0e,0xfe,0x91,0x49,0xda,0xa9,0xfe,0x64,0xa1,0xae,},{0xc7,0x56,0x6f,0xb3,0xb4,0xd8,0xde,0xf6,0x67,0xe0,0x40,0xf2,0x76,0xd3,0xed,0x98,0xd3,0x6d,0xff,0x46,0x01,0x26,0xa7,0x5b,0x4c,0xc2,0x10,0x03,0x86,0xbb,0x01,0xc6,0x42,0xf6,0xd8,0xde,0x7e,0x64,0x9b,0xe6,0xe0,0x81,0x8b,0x08,0xd7,0x7c,0xe6,0x0f,0x4e,0xe5,0xe7,0x71,0x7a,0x50,0x88,0x4b,0xde,0xe0,0x20,0x34,0xec,0xf1,0xcd,0x0c,},"\x0d\x05\x52\x91\xb2\xe8\x61\xea\xe1\x9e\xa0\xfb\x20\x69\xd8\xc9\xee\xf4\xf1\x34\x7f\x35\x76\xd7\x84\x11\xae\x7c\x0b\x1c\x1c\xaf\x31\xfd\xe7\x36\xdc\x8a\xcc\xac\xb6\x62\xdf\x76\xb6\x20\xb6\x2c\xe9\x0b\x9f\x92\xc8\x33\x09\x12\x86\x21\xd0\x57\xcf\x84\x58\x05\x94\x90\x88\xe9\x38\xdd\xbc\x3d\x41\xc5\xe5\x54\x1f\xec\x82\x98\x68\x7a\xd2\xf7\x9a\xcd\xa0\x1a\xa2\x15\xd2\x58\x21\x43\x6e\xac\x9d\x26\x87\x16\xd4\xcd\x60\x50\x26\x0c\xb4\xef\x6a\xad\xa4\x83\x5e\x07\x3a\x84\x58\x21\xff\x21\x1a\xe2\xba\xad\xce\xb6\xe5\x7f\x06\xf8\x83\x45\xed\xbf\x93\xbf\xdf\x54\xfb\x74\x12\x3b\x57\xc0\xfb\x4a\x79\x60\x8d\x8d\xb6\x74\x08\x89\xe1\x57\x33\x50\x77\x99\xf7\xa1\xfd\x30\x17\xbc\xd7\x7b\x28\xa2\xbb\x6c\x91\xec\xd1\x54\xe9\xc5\xa5\xff\xa0\xeb\x62"}, -{{0xf3,0xfd,0x5e,0xc5,0xe2,0x30,0xb6,0xda,0xd1,0xac,0x3d,0x3a,0xeb,0xad,0xc7,0x86,0x3f,0xf8,0x9d,0xe2,0xa1,0x31,0x7f,0x42,0x4d,0x15,0x98,0x9a,0x3e,0xfb,0x0a,0xfd,},{0xf9,0x9e,0x5d,0x5e,0xee,0xae,0xd1,0x20,0x5c,0xfb,0x5c,0x2c,0xc4,0xe5,0xe9,0xf6,0xb4,0xe7,0xf6,0x41,0x29,0xf8,0x60,0x10,0x4c,0xa6,0x24,0x4e,0xb9,0xfe,0xb5,0x64,},{0x44,0xb0,0x12,0x46,0x63,0xad,0xb0,0xc7,0x3a,0xed,0x49,0xf7,0x34,0x03,0x46,0x1f,0xcb,0x19,0x11,0x1b,0x0b,0xa1,0x7a,0xa9,0x96,0x56,0x6f,0x47,0x7e,0x37,0xd5,0x24,0xb0,0xe1,0xf1,0x07,0x61,0x2f,0xc5,0x2a,0x7c,0x76,0x7b,0x18,0x1f,0xbf,0x4d,0x62,0x9b,0xdd,0xc0,0x8f,0x30,0x58,0x4d,0xec,0x61,0x24,0xc5,0xd3,0x9d,0x42,0x31,0x02,},"\x71\xf2\x89\x73\xed\x3d\xf0\x59\x45\xfa\x0b\xdb\x23\xe9\xbe\xca\x65\x1d\x3e\xe6\xbf\x9f\xa4\x5f\xfd\xc6\x06\x1e\x42\xfa\x2e\x8d\x76\x23\x5f\x0e\x9e\x2d\xaa\x65\xe5\x26\x31\xfc\x3b\xea\xd3\x3d\xa0\x55\xbb\x49\x2e\x47\x58\xe5\x98\xa0\x30\xa3\x3b\x3c\x40\xb3\x43\x71\x45\x9b\x23\x3c\xcc\x04\x3c\xcc\xc3\xa3\xcb\xce\x54\x9e\x20\xe0\xb2\xb4\x33\x05\xb6\x4a\xec\x66\x1a\xad\xba\x65\x56\xb1\x7d\x76\xe3\xbb\xed\x62\xc4\xa4\xea\xc4\xf8\x86\x03\x99\x67\x52\xd2\x36\x3c\x8d\x4a\x27\x89\xd1\x28\xf6\xe9\x59\x94\x5c\x68\xc3\x01\x46\xd1\x94\xcc\xb6\x83\x9e\xc6\x53\x44\x60\x16\x52\xc1\x8b\x00\x74\xe2\xbc\x76\x68\x31\x16\x97\xd9\x60\xc7\x06\x65\x97\x92\x4d\x70\x4d\x02\xa0\x19\x3f\xaf\xbf\xdf\x57\x1e\xe0\xdf\xe4\x14\xdc\x2f\x52\x89\x69\x12\xbc\x32"}, -{{0x73,0x8f,0x13,0x10,0xa4,0xe0,0x8f,0x91,0x7a,0x0a,0x5c,0x1f,0xba,0xf4,0xef,0x72,0xf9,0x5e,0xe6,0x2f,0xcd,0xed,0x50,0x86,0x8a,0x3d,0xaf,0x98,0x85,0x6a,0x44,0x8d,},{0x42,0x27,0x2c,0x2c,0x8b,0x08,0x47,0x0e,0xe5,0xdd,0x8a,0xf8,0x84,0x9c,0x01,0xb7,0x50,0x8d,0x3a,0x3c,0x65,0xb0,0x33,0x0e,0x69,0x5c,0x84,0x1d,0x5d,0xcc,0xb2,0xf5,},{0xce,0x1e,0x35,0x77,0xb6,0xa2,0x10,0x16,0xb9,0xdd,0x0b,0x51,0x7b,0xaa,0x0c,0xcb,0x10,0x7b,0xc1,0x99,0xb8,0xbb,0xae,0xf6,0x8f,0x95,0x0c,0x8e,0xd5,0x80,0x13,0xc8,0x53,0xb4,0xd3,0x38,0xee,0xdc,0x67,0x50,0x79,0xab,0x13,0x90,0x46,0x2f,0xfe,0xfa,0x6a,0x95,0x9b,0x04,0x3f,0x8b,0x56,0x51,0xc6,0xca,0x37,0x5c,0xe0,0xb4,0xa4,0x03,},"\xf0\xe7\xef\x67\x82\xd0\x4c\x69\x43\xb1\x9e\xb6\x6f\xf6\x22\x6b\x73\x6e\x3b\x09\x40\xc0\x9b\xb1\x26\xbf\xc4\xc4\xca\x7a\x5e\x70\x16\xc2\x86\xb7\xbf\xd7\x3a\xa6\xa7\x9a\x96\x03\x1b\xc8\x1c\xb5\xda\x68\xce\xc7\x1a\x6a\x0d\x39\x78\x0c\xbe\x6a\x0c\xd4\x77\x4d\x3a\xa0\x6a\x88\x16\x10\x44\x4a\x8c\x9d\x19\x10\x22\x94\xe5\xf6\x35\x18\x7a\xa6\xf4\x8d\x11\x91\x2c\x70\x94\xb3\x88\x33\x02\x8d\x57\x0c\xb1\x10\xdb\x60\x62\x5b\xb1\xbd\xc3\x7a\xff\xa2\x5e\xa3\xc8\xf8\xdb\xfc\x25\x14\xf4\x36\x5c\x62\xb2\x98\x9a\x66\xd2\x7c\x80\x38\x4e\x74\xae\x5f\xba\x8c\x1c\x2a\xf9\xc7\x2c\x49\x71\xe6\x4f\xa6\xa1\xdc\x25\x17\xb3\x1e\xa5\x7c\xcb\x08\x15\xa7\xfe\x2d\xa0\xf1\x46\xca\xa0\x84\x31\xd2\x5d\x15\x16\x62\xd9\xd2\x6e\x95\x22\x9d\x0c\x62\x82\x36\x64\x12\x3c"}, -{{0x88,0x41,0xd2,0x2a,0xde,0xd6,0x9c,0x13,0x1e,0xf5,0xee,0x0a,0x10,0xab,0x0a,0x9b,0x77,0xcb,0x75,0x4e,0xde,0x8d,0x25,0x7a,0x53,0x72,0x72,0x6e,0x2b,0x49,0x9c,0x6e,},{0x71,0x5e,0xcc,0xa6,0x36,0x81,0xbc,0x6e,0x9e,0x31,0xd1,0x88,0x48,0x90,0x2f,0x4d,0x96,0xfe,0xaf,0x43,0xb9,0x5d,0x00,0x86,0x42,0x90,0x3b,0x17,0x63,0xbc,0x9f,0xb8,},{0xbb,0x2b,0xab,0x70,0x03,0xf1,0x31,0x1b,0xe9,0xb8,0xc8,0x83,0xfc,0x4f,0xd5,0x28,0xad,0xfd,0x51,0xa9,0xc9,0x9d,0xb3,0xdc,0xa8,0xda,0x0f,0xca,0x95,0x8d,0xa1,0x9a,0x10,0xeb,0x22,0x33,0x26,0x67,0xb1,0xa0,0x06,0x5d,0x3d,0xbc,0x0d,0x06,0x26,0x9a,0x12,0x59,0xb6,0xa8,0x90,0x48,0x4a,0xa2,0x14,0x3a,0x52,0x69,0x5f,0x14,0x5b,0x0a,},"\x08\x7c\xa6\xbe\x2a\x95\x0c\x02\x4b\x3e\x74\x67\xfe\x00\xa7\xd3\x64\x55\x5d\x5d\xc6\x77\x0f\x5e\xbd\x26\x06\x42\x52\x5b\xd3\xc0\xf9\x65\xdb\x36\xd7\xb2\x29\xa5\x74\x21\xee\xc6\x4e\x4d\x99\x1c\xdd\xe5\x91\x23\x03\x44\x70\x55\x3f\x4e\xb0\xbe\x81\xad\x29\x36\xc8\xca\x26\xbc\xab\x4e\x5d\x79\x04\x0e\x29\x79\x87\x28\x60\x16\x84\xa4\x68\x32\x3c\xf3\xba\xae\x4d\x94\x8d\x0a\x1f\xd9\x05\xef\xfe\x16\xdc\x44\x64\x20\x88\xdf\x53\xf6\x38\x8b\xc4\x80\xed\xf4\xaa\x20\x7d\x0e\xd1\x61\xed\xa3\x45\x71\x2b\x4c\x00\xcb\x05\xfc\xf6\x35\xec\x25\x88\x78\x5b\xfb\x8a\x27\xcd\xc2\x89\x96\xa1\xdb\x3e\x67\x87\x02\x33\x93\xc0\x75\xd8\x3c\x90\x38\xfe\xd7\x89\x9c\x55\xfe\xc3\x07\xde\x32\x49\xc1\x4b\xda\x49\xe8\xb8\x95\x86\x09\x42\xc3\x6d\x64\x0b\xb8\x93\x77\x91\x42"}, -{{0xc0,0x21,0x35,0xe7,0xb6,0x5a,0xac,0x72,0xf6,0x3c,0x32,0xbf,0x5b,0xef,0x5b,0x68,0xc7,0xf3,0xb8,0xed,0x56,0x20,0x8e,0x59,0xe4,0x75,0x20,0x70,0xe9,0xd0,0x70,0x95,},{0xdc,0xf6,0x00,0xf2,0x44,0x03,0x7a,0x75,0x20,0x3a,0xe1,0x1a,0xc3,0x16,0xe8,0xdb,0xe9,0x98,0x6f,0x0d,0xce,0x23,0x47,0x39,0x39,0x33,0x4b,0xf5,0xce,0xa4,0x8b,0x0d,},{0xdd,0x5c,0xba,0xe4,0x79,0xeb,0x5e,0x22,0x95,0x74,0xc2,0x1e,0xc3,0xbe,0xd9,0x11,0x11,0x3a,0x57,0xa1,0x91,0x6d,0x33,0x13,0x45,0x75,0x15,0xd5,0x5c,0xc5,0xb6,0xe6,0xeb,0xc5,0x2c,0x93,0xf8,0x21,0xd1,0x39,0x88,0xdb,0xba,0x8d,0xf5,0x09,0x6d,0x55,0xff,0x9c,0x39,0xe7,0xf9,0xd5,0x61,0xcb,0x58,0x93,0x0c,0x96,0xa7,0xa5,0xd6,0x0b,},"\x86\xd9\x49\x13\x50\xd2\x56\x6e\x70\x8e\xd3\x56\x18\x5d\x61\x0c\x73\x46\x5b\x2a\x5c\x70\x12\x91\x99\x58\xaf\x2c\xf7\x6a\xf9\x95\x23\x0d\x36\x0d\xe4\x00\xb7\x13\x71\x70\xdd\x08\x35\xf1\x0f\xcb\xec\x22\x4e\xe4\xe4\x2c\x7d\x1c\xeb\xb7\xf5\x80\xfe\xa8\xed\x62\x23\x16\x3b\xac\xdd\x19\x23\xa5\x72\xcb\xb6\xdc\x26\xca\x8b\x17\xad\xe6\x8c\x6d\x28\x08\xc4\xca\x1e\xca\x28\xea\xe9\xa1\x45\xf6\x8d\x40\x79\xd8\xd5\x9d\x14\x0e\x95\x82\x28\xe7\xe9\x95\x20\xe3\x42\xdb\xd7\x45\x7a\x91\x59\x74\x0f\x48\xbd\xc2\x7b\x93\xbd\xab\xeb\xa4\x65\xcb\xf0\xc8\xdf\x5e\xf2\xc0\xf9\x38\x6e\xeb\xe6\x56\xf5\xd7\x49\xd5\xf9\x14\x7f\x52\x52\x66\x91\x0d\x7b\x80\x39\x6a\x90\xbe\x5c\xc1\x88\xa9\xa9\x45\xf9\x3e\x75\x3f\xc9\x9b\xaf\xa1\x8e\xe0\xa6\xdf\xf7\x9b\xf8\x48\x48\x98\xef"}, -{{0x15,0x4a,0x47,0xeb,0xa1,0xb8,0xc3,0x83,0x62,0xea,0x61,0xfa,0xeb,0x0c,0x0a,0xd7,0xe6,0x1e,0x41,0x2a,0x3c,0xba,0x46,0x88,0xaf,0x0d,0xb2,0xa4,0x87,0x20,0x8b,0x1c,},{0x16,0xde,0x2c,0x89,0x4a,0x50,0xcb,0xd4,0xca,0x90,0x41,0x9a,0x4c,0xa6,0x49,0x42,0xcb,0x14,0xbd,0x33,0x5c,0x5d,0x3f,0x4a,0x53,0xe2,0x39,0xc2,0x80,0xbd,0xa7,0x25,},{0xf4,0xb6,0xeb,0x1a,0x8d,0x95,0x0e,0x88,0x7f,0xd2,0xf3,0x0f,0x70,0xa2,0x3b,0x41,0x87,0x14,0x95,0xbf,0xa5,0xb8,0xa4,0xad,0x39,0x96,0xcd,0x9b,0xf5,0x1e,0xb7,0x42,0xe0,0x7f,0x4c,0x4d,0x2d,0xa4,0xb0,0x1a,0xb0,0x87,0x36,0x7a,0x50,0xe2,0xb6,0x5b,0x3c,0xef,0x51,0x4e,0x40,0xd8,0x37,0x54,0x0b,0x8c,0x89,0x96,0x64,0x85,0x91,0x0f,},"\xbf\x60\x7e\x8b\x6e\x14\xd9\xc8\xac\xd9\x68\x15\xaf\x0c\x03\x5a\xc7\x3c\x41\x04\xc9\x37\x86\xcc\xc1\xc9\xf8\x59\x39\x5d\xd7\x81\x90\x03\x20\xeb\xf3\x56\xaa\x99\x1c\xdc\x9f\x50\x3f\xce\xe9\xf8\x36\x75\x88\x8a\x7d\x59\x20\x02\xd2\xa5\x4a\x57\x3a\x96\x99\x4b\x3f\xa8\x65\x53\x8c\x61\x7e\xd8\xad\x1f\xf6\x20\x18\x28\x8a\x67\x4f\x44\x9b\xe0\xaa\xb5\x22\x2f\x74\xc4\xfd\x47\x5e\xd6\xa8\xdf\xb2\x7f\x45\x28\x7b\x22\xb2\xb6\xc3\xbd\x15\x17\x9f\x26\x7d\x15\x7d\x7d\x8a\x41\x59\x67\x9b\xe8\x5b\x25\xc2\xbb\x2b\xa8\x50\xaa\xed\x9a\xe3\xae\x57\x1b\xe4\xf7\x58\x36\x32\x9c\xf3\x6f\x41\x2c\x1c\x80\xf1\x41\x3b\x76\x61\xea\xb4\xa8\xe1\x1b\x60\x24\x24\x4f\xc6\x23\x23\xff\x02\xe3\x8a\xce\xb1\x73\x7b\xd4\x74\xbf\x1e\x98\x01\x5d\xbc\x78\x8b\x02\x7b\xbe\x21\x7c\xf4\xe7"}, -{{0xd3,0x02,0x84,0x31,0xce,0x2e,0xef,0x73,0xbd,0x94,0x0a,0xb8,0x4c,0xa2,0x9f,0x13,0xfb,0x26,0x43,0x6a,0xa2,0x5e,0x1b,0x7b,0xf2,0x6c,0xb3,0x3f,0x17,0xfd,0xf8,0x17,},{0x63,0xdf,0x20,0x3e,0x28,0x60,0xba,0xc4,0xd3,0x52,0xe7,0x22,0xc1,0xc9,0x1f,0xe3,0x77,0x6e,0x1c,0xbc,0xae,0x85,0x53,0xa4,0xf1,0x98,0x90,0x26,0x0b,0xf0,0xe4,0x57,},{0xce,0x97,0x29,0xa9,0x6c,0x3e,0xd2,0x89,0x43,0xb2,0x78,0x39,0xc7,0x33,0x82,0xec,0xd5,0x72,0x96,0x0c,0x1f,0x9e,0x90,0xc5,0xef,0xf9,0xdd,0x49,0x9f,0xf4,0x8f,0x17,0xd2,0x5e,0xdd,0x12,0x68,0xef,0xfe,0x41,0xee,0x6a,0x81,0xce,0x48,0xd8,0x4d,0xe5,0x13,0xdf,0x9c,0x41,0x44,0x26,0x21,0xb2,0xf5,0x49,0x1e,0x34,0x6b,0xe1,0x8c,0x04,},"\x08\x63\x35\xd6\x12\x75\xd1\x68\xea\xac\x05\x40\x47\x7f\x50\xd4\xb1\x5f\x9e\x50\xb9\xbe\x69\x39\x21\xed\x54\xa9\x94\x1b\xc4\x06\x43\xcd\xa6\x2e\x1d\x80\x5d\x02\x50\xa8\x11\x46\xbd\x5f\xe2\xd3\x9e\x81\x44\x4d\x21\xe2\xb2\x1b\x03\x1c\x11\x13\x06\xca\xcb\xf5\x27\x17\xf6\xfb\x4c\xd3\x41\x6f\x12\x15\xf8\xdd\xdc\xed\xd2\xf0\x09\x6b\x0f\xcf\xa0\xa6\xcc\x2c\xde\x7a\x2b\xab\x7f\x1e\x32\x79\x0b\x53\x61\xdf\x36\x71\x42\x4c\xc7\x22\xf2\x31\xbf\x71\x89\x5b\xcd\xcb\x7b\x22\xee\x07\x4e\x8f\xb4\xa9\x67\x85\x04\xe7\x35\x36\x6c\x17\x2f\x07\x63\x7b\x7a\x93\x14\x9b\xb2\x1f\x38\x88\x33\x78\xa1\xdb\x27\x3f\xc2\x32\x39\xe3\x53\x37\xf9\xce\x56\x6d\x8d\xdf\x3b\x31\x33\xca\xd7\xf2\xce\x81\xed\xb5\x03\xce\x1d\x27\xc5\xa6\x57\x16\x0b\x78\xdc\xa9\xae\xae\xa3\x79\xbe\x9c\x85"}, -{{0xee,0x89,0x85,0xdc,0x27,0x50,0x44,0x40,0xa8,0x75,0x8d,0x4c,0x53,0xe4,0x22,0x52,0x15,0x79,0x7a,0x00,0xcd,0x86,0x31,0xd5,0x9b,0xd9,0x3b,0xc6,0x6f,0x37,0x3d,0x5e,},{0xcd,0x64,0x7b,0xb0,0x65,0x69,0x3d,0x48,0x65,0x89,0x15,0x6a,0x9f,0xa2,0x61,0x43,0x75,0x34,0xdc,0x86,0xf4,0x6f,0x72,0xd0,0xa8,0x00,0x39,0x9a,0x7a,0xf0,0x10,0xf7,},{0x5b,0xd6,0x0a,0xd5,0xe9,0xba,0xd9,0x93,0x2c,0xa9,0xc7,0x5f,0x23,0x1a,0x76,0x88,0x9a,0xe7,0xa8,0xb8,0x64,0xb9,0x1d,0x1f,0xcb,0xa5,0xc5,0xd4,0xbf,0xa1,0xd9,0x28,0x38,0xad,0xb9,0x74,0x84,0x2a,0x07,0x10,0x77,0x9b,0x3e,0x30,0x94,0x04,0x49,0x09,0xe9,0x2c,0x7c,0xf0,0x46,0xce,0x51,0x9f,0x4c,0x68,0xe8,0xf1,0x9e,0xc0,0x3c,0x02,},"\xf2\x22\x04\x85\xad\xdf\xeb\xce\x02\xa8\x33\xac\xa3\x33\x81\xd1\xdf\x91\x7e\xd6\x09\x95\x0e\xd2\x4f\x85\xe3\xb0\x2b\x2b\x99\x4b\x4d\x93\x97\x84\xe3\x32\xf4\x10\x64\xc8\xb4\xa2\x63\x0a\xb3\x69\x61\x74\x2a\xa1\xcf\xfd\xcb\x08\xc1\x44\xee\xae\xde\xaf\xd4\x8b\x5d\xbe\x96\xbf\x24\x35\x0e\x14\xfd\x68\x28\x6b\xc0\x8e\xea\xef\x8b\xc6\xad\x9e\x19\x5d\x14\x84\xaf\xcd\x30\xaf\xa8\xce\xd4\x84\x81\x26\xd5\x6c\x81\xb4\x3c\x27\xa5\xdb\xbd\xec\x1a\x50\xc1\x10\x62\xce\x21\xc6\x1d\x86\x0c\x25\xa8\x62\xfb\xb7\x5c\x3b\xd5\x1c\x8d\xc0\x76\x36\x66\x86\x69\xbb\xf7\x51\xea\xca\xcc\xb3\xb5\x1d\x2c\x0d\x41\x40\x31\x6c\xfc\xe2\xeb\x18\xd2\x90\x8c\xec\xd5\xa1\x88\x67\x9b\xc5\xf5\xde\x29\x0f\x54\x8e\x7e\xbc\x57\xd4\x1b\x58\x9a\x24\xce\x88\xee\x48\xd9\x7e\x8d\x0c\x7c\x76\x99\x60"}, -{{0x80,0xdf,0xe2,0xbf,0x73,0x87,0xba,0xd4,0x65,0x4e,0xb0,0x76,0xf8,0xda,0xe9,0x59,0x51,0x63,0xe4,0x01,0x27,0xf5,0xdf,0x49,0x2d,0xad,0x7d,0xf0,0x4c,0x72,0x21,0xc4,},{0xd1,0x78,0x3c,0xee,0xb9,0xcf,0x8e,0x4d,0x07,0x76,0x4c,0x47,0x3f,0xa4,0x06,0x1b,0x82,0x74,0x39,0x71,0x03,0xf2,0x07,0x6d,0x70,0x32,0x49,0xd7,0x58,0xb8,0xfb,0xd5,},{0x27,0x27,0x9e,0x3c,0xdc,0xb0,0x3e,0xf5,0x57,0xa5,0xde,0xfc,0x2f,0x6c,0x58,0x12,0x8a,0x6d,0xc3,0xf8,0xb0,0x38,0x59,0x58,0x01,0x4e,0x70,0x9c,0x1f,0x61,0xb0,0xae,0x6b,0x40,0x35,0x76,0xf0,0xe4,0x54,0xd5,0xe4,0xc6,0x4c,0x17,0x31,0x38,0xee,0x4b,0xbd,0x5f,0xe7,0xb6,0x0d,0x06,0xc5,0xab,0xe2,0x3f,0xe9,0x9e,0xe3,0xb4,0x6a,0x00,},"\xaa\x09\xd7\x84\xbb\x09\xdc\x99\x99\x31\xeb\xb4\xc0\x0e\x42\x4c\xef\xec\xa1\x04\x81\x8d\x8e\xaf\x06\x61\xf0\x97\x28\xad\x02\x5e\xf4\x73\x93\x21\x05\x71\xf1\x74\x04\xe9\xaa\x6d\x8c\xbd\x5f\xd8\x8c\xd7\xdf\xb8\xe2\xe8\xa1\x08\xc0\x5d\xe2\x06\xf3\x40\x82\x34\xa3\xb4\x63\xdb\xe7\x1a\x07\xd0\x55\x87\x32\x45\x24\xb7\x32\x6e\xe7\x9d\x33\x48\xdd\xbe\xd7\x87\x1b\x86\xfc\xb4\x88\x03\x1d\xc9\xea\x93\xf6\xb8\xd7\xfd\xa6\x23\x93\x48\xa5\x62\x44\x4f\xaf\x1e\x72\xd3\x1a\xf3\x54\x43\xe9\xdf\x53\xe7\x62\xf3\xe5\x6b\x48\x66\x8f\x97\x84\xb3\x36\x8a\xb2\x78\xa4\x8e\xf4\x54\x6a\x26\xcf\xad\x0d\x0a\x51\x61\x69\x8f\x26\xee\x8d\x34\xfc\x2b\x3d\x6d\xfb\x93\xb0\x09\xac\x29\x6f\x6a\xfe\x48\x7e\xe3\x35\xea\xc9\xf0\x2c\xfc\xae\x5f\xcb\xd1\xa1\x6b\xa4\xe7\x1b\xe1\xb1\x12\x56\x2f\xc2"}, -{{0xda,0x1f,0x86,0x85,0x42,0xcd,0x7c,0xce,0x7a,0x5c,0xa3,0xfa,0x3c,0x24,0x08,0x1b,0x4d,0x23,0x44,0xb2,0x1a,0x15,0x7f,0x02,0x64,0xa3,0x47,0x13,0x2d,0x19,0x65,0x9d,},{0xcb,0x3a,0x25,0xa5,0x3f,0x27,0x2e,0xa8,0x13,0x80,0x44,0x68,0xd6,0x50,0x0e,0x96,0xa1,0xea,0xf8,0x22,0x70,0x5b,0x77,0x90,0xa8,0xac,0x3e,0x98,0xcc,0x4e,0x52,0x4b,},{0x75,0xc5,0x17,0xad,0xe4,0xf0,0x8d,0x77,0x46,0x30,0x57,0x43,0xd1,0xa7,0x76,0xc3,0xc5,0x5e,0xb5,0xee,0xdf,0xdf,0xcb,0x5e,0xb1,0xd5,0x63,0x4a,0x1b,0xda,0xf7,0xa4,0xb8,0xd2,0x41,0x87,0xd6,0xc8,0x85,0x0e,0x3c,0xed,0x65,0x67,0xa0,0x3c,0x4c,0x59,0x38,0x9a,0x4c,0xf4,0x71,0x14,0xce,0x54,0x73,0x16,0x0f,0x23,0x05,0x46,0xe6,0x0d,},"\xc6\x98\x7e\xf3\x80\xd5\xd0\xe7\x41\x96\x44\x3a\xaa\x3a\x32\x35\x6c\xbc\x02\x63\x6c\x5a\x4b\x6d\x62\xa8\x11\x4b\x21\x11\xbc\x1a\xbd\xdd\x9e\x44\xb3\x67\x2c\x18\xb5\x8d\x4e\xf5\x91\xaf\x45\x62\xe0\x20\x04\x9f\x8e\x12\x74\x68\x8e\x1f\x8e\x52\x96\xd2\xf9\x25\x2e\x7f\xc8\x4c\xd1\xd0\xc5\x8e\x98\xf0\xf1\x60\x53\x0a\xa2\x2c\x87\x1e\xef\x65\x2e\x71\x97\x4c\xe9\x1b\x4a\x65\xfc\x25\xfd\x09\xfa\x1b\x6c\x32\x08\x6e\x98\xec\x70\x8d\x9a\xbc\xb1\xd9\xcc\x8e\x1a\x08\x9e\xd8\xdb\x22\x06\xee\x95\x70\x23\x6a\xd6\x9b\x3d\xe6\x82\x18\x62\xfd\x2c\x70\xcd\x83\xa3\x2a\x68\xb0\x48\x62\x29\x55\x3d\x92\x8d\xe4\x8d\x03\xa1\x04\xe8\x73\x81\x96\x4a\xbe\xa7\x66\x83\x97\x6d\x52\x7c\x84\x16\x3a\x12\xee\xe0\xa5\x59\x86\xcf\x14\x31\xe9\xc8\x6c\xba\x81\x82\xca\x94\x68\x9b\xac\xd1\x65\xfb\xce"}, -{{0xf1,0x3d,0xae,0xc0,0xef,0x33,0xdd,0xd1,0x33,0xc7,0xd2,0x44,0xd1,0x0f,0xd2,0x7d,0xdb,0x23,0x70,0x52,0x80,0xff,0x5f,0x18,0x15,0xf0,0xf6,0x56,0xd8,0x36,0xfe,0x84,},{0x2d,0xc7,0xf1,0x36,0x7d,0xe6,0x72,0xc5,0x1e,0x00,0x5c,0x74,0xf8,0x76,0xf9,0x82,0x59,0x39,0x96,0x87,0x3a,0xcb,0xa0,0x79,0x29,0x27,0x34,0xc2,0x09,0xc2,0xb1,0x11,},{0xdb,0x77,0x18,0x33,0xf7,0xfd,0xba,0xcd,0xab,0x2b,0x5c,0xc8,0x0e,0xed,0x50,0xaf,0xdf,0x13,0x78,0x3b,0x7f,0xe5,0xe9,0x03,0xd5,0xdb,0xb4,0xc2,0xe5,0x35,0x31,0x6a,0x6e,0xef,0x4c,0x34,0xf0,0x04,0xd2,0xb9,0xa4,0xe2,0x70,0x0b,0xd6,0xe2,0xac,0xdd,0x56,0x4c,0x3c,0x80,0xcc,0x68,0xa3,0x03,0xf5,0xfb,0x09,0x1c,0xb4,0x34,0x0f,0x0a,},"\xec\x02\xff\x18\x04\xb2\xb3\x09\xaf\x31\x58\xb6\x62\x72\xa1\x4a\x3a\xad\x83\xc4\x1a\x71\x98\x46\xf7\x08\x8c\xa9\x79\x2a\xf5\x75\xc7\x89\x13\xc4\x32\x75\x9f\x0b\x9a\x74\x8b\xdc\x55\x68\x49\x6e\x41\x65\x8c\xc1\xcd\xb8\xda\x6c\x91\xd0\x7c\x3e\xc2\xf4\xaf\x50\x42\x49\xb9\x96\xaa\x00\xc0\x07\x1c\xdf\xa7\x93\xf8\x2d\x0e\xc5\xd2\x67\x26\x2f\x51\x8f\xc0\x29\xb8\x8e\x20\xb6\x20\x1f\xb9\xe0\x5a\xbd\x3f\x95\x24\xc5\xda\x2f\xa8\x97\x8f\xf2\xef\xd4\x81\x20\xcf\x00\x82\x2d\x1b\xee\x90\xdf\x81\x61\x25\xd8\xed\xc0\xcf\xb5\xde\x66\xd1\x6b\xe6\x38\x96\xa4\x12\xa6\x2b\x03\x1b\x71\x18\xac\x13\xfe\x2c\x9f\xaa\x6b\x1a\x33\x42\xf9\xcc\xf7\x88\x41\x66\xcf\x48\x9a\x84\xde\x26\xb5\xce\x5b\x21\x85\x6a\x3a\xf2\x89\xbc\x66\x22\xc0\xaa\xb9\xf2\x14\x2d\x39\x3f\x5d\x4b\x23\x67\x79\xdb\xb0\x66"}, -{{0x42,0xdc,0x16,0xc5,0x7f,0xb6,0xf1,0x28,0x94,0x5f,0xa1,0x01,0xe0,0x5b,0xbf,0x54,0x8e,0xf7,0xd9,0x77,0x26,0xb6,0x92,0xfe,0x40,0x40,0x69,0xcc,0x57,0xcc,0xef,0xa0,},{0x0a,0x1b,0xa5,0xdf,0x52,0x39,0x96,0xf9,0x54,0xb3,0x4d,0xdc,0xfa,0xba,0xd3,0xf3,0xde,0xe2,0x1a,0x5f,0xa7,0xa4,0xce,0x32,0x2d,0x21,0x6b,0xd8,0xcc,0xaf,0x43,0x8c,},{0xc7,0x59,0x77,0xe8,0x3b,0xcf,0xe9,0xdf,0x72,0x92,0xa8,0x60,0xed,0x97,0x25,0x55,0xb5,0xc2,0x44,0x16,0xfd,0x4b,0x7e,0xe3,0x28,0x53,0x88,0xfa,0x5b,0x14,0x47,0x60,0x8e,0x4a,0x34,0x78,0x13,0xcf,0xe0,0x93,0x51,0x2a,0x76,0x51,0xe4,0x22,0xe9,0x86,0x7d,0xb7,0xb9,0x7c,0x0b,0x08,0x67,0xf0,0xb8,0xc7,0xb7,0xf4,0xf0,0x2c,0x31,0x0d,},"\xf2\x71\x4c\x23\xa3\xa6\xfc\x11\xad\x15\xc9\x80\xb7\x35\x0f\xc8\x42\x17\x87\x76\x61\x18\x80\x55\xff\x75\x0d\x82\xc4\x9c\x5f\xef\x7b\xc8\xe6\xaa\xc5\x74\xa1\xb7\x9a\x3f\x26\xd1\x69\x69\xc0\xf4\x06\xee\xab\x3e\x9e\x12\x85\x0a\x55\x70\x97\x45\xe3\x0d\xff\xa6\x2a\x69\xdf\xb2\xb6\x4b\x3c\x1b\xd2\xbc\x35\x86\xe2\x6d\x4e\xea\x71\x4d\x2a\x7b\x71\xcf\x79\xfb\x8f\xfb\xf2\xaa\xad\x00\xca\x3e\x4f\x2b\x6f\x50\x3c\xc1\xfe\xf2\xea\xb3\x65\x6f\xb4\x4f\x8d\x62\xa8\xdb\x8a\xb5\x8f\x39\x46\x93\x94\x9e\xea\x57\xfa\xfe\xcf\x00\x5f\x6e\xbf\x12\x87\xdb\xa4\xd2\xd6\x23\xc0\x2e\xa1\x71\xf5\x67\xe5\x26\xad\xd2\x07\x09\xeb\xca\xb9\x62\xf8\x3d\x98\xef\x66\x8e\xbd\x01\xef\x20\x48\x8b\x36\x65\xe3\xa4\x46\xfb\xfb\x13\xd3\x40\x50\x94\x2c\x74\x9b\xb2\xdf\xfc\x76\x63\x67\xfd\x45\x2e\x68\xe5\xb0\xc6"}, -{{0x90,0xb4,0x55,0xc6,0xbb,0x9c,0xec,0x83,0xe1,0x37,0x35,0x70,0x65,0x33,0x9d,0x03,0x05,0x25,0xd0,0xea,0x7f,0x5b,0x92,0x3a,0x2d,0x59,0x72,0xc3,0xc1,0x2a,0xa3,0x7b,},{0x5c,0xef,0x03,0x8c,0x16,0xbf,0xa4,0xb4,0xc9,0x23,0xa0,0xfe,0x70,0xcd,0x7f,0x25,0xc8,0xbc,0x83,0x7f,0xdf,0x5a,0x7e,0xfb,0x9d,0x95,0xf2,0x1b,0x96,0xbe,0x92,0x5a,},{0xc9,0x34,0x5e,0xec,0x2c,0x4a,0x0a,0xec,0x73,0x23,0x86,0x49,0x4a,0x69,0xa3,0xfc,0xe8,0xb8,0xa1,0xbe,0x36,0x6b,0xbe,0xd1,0x65,0x9f,0x13,0x1f,0xe9,0x7c,0xc0,0x37,0xfb,0x1b,0x7c,0x1b,0x68,0xb0,0xf3,0x02,0x39,0x45,0xd2,0x00,0x90,0xa0,0xcd,0x2c,0x15,0x53,0xa4,0x7f,0xae,0xc4,0xd6,0x6f,0xd8,0x16,0xce,0x12,0x11,0x68,0xf3,0x09,},"\xc6\x2c\xfd\xb9\xd2\x1e\xee\x6b\xe4\x7f\x30\x72\x7a\xae\xe5\x1f\x07\x03\x78\x9a\x43\x1d\x32\x22\x85\x33\x35\x02\x17\xa9\x3a\x18\x90\x06\x69\xc9\x59\x56\xf3\xf2\xae\x90\xdc\x74\x5a\x71\xe1\x83\x40\xd0\x58\xd1\x6b\x4c\x6f\xe3\x3b\x64\xaf\x8d\xad\x97\x3f\xe5\xdc\x02\xe8\x52\x07\x05\xc7\xa8\xbb\x3c\xcb\xe1\x83\x8c\x6c\x24\x93\x37\xf9\xb6\xa4\xc0\xe1\xf8\xa4\xe5\xd1\x03\x19\x6f\xa7\x99\x98\x92\x3d\x04\x22\xe9\xd0\x79\xa7\x2c\xc2\xa8\xf8\x6d\x65\x90\x31\xa6\x07\xd4\xcc\xa0\xb9\x47\xb3\xab\xee\xee\xf6\x4c\x28\xda\x42\x0d\x05\xde\x66\x5a\x55\x10\xfe\x55\xf7\x75\x98\xec\xad\x7f\xaa\x0a\xc2\x84\x80\x0b\x53\x82\x93\x94\xc4\xae\x90\xbe\x66\x67\x8f\xf0\x4a\xb4\x6d\xa2\x65\xae\x06\x40\x2d\x8c\x83\xca\xd8\x4d\x61\xa0\x51\xde\x02\x60\x55\x98\x88\xe7\x79\xf7\x4b\x72\xa5\xd7\x1c\x13\x2f"}, -{{0xdc,0x18,0x5c,0x2b,0xa0,0xb3,0x78,0xdf,0xe5,0xdd,0xa5,0x10,0xc3,0x2f,0xef,0xf5,0x35,0xca,0x2e,0x8a,0x02,0x43,0x4b,0x32,0x6e,0x01,0x58,0xbc,0x87,0x8e,0x88,0x48,},{0x33,0xd6,0xcc,0x05,0xa4,0x34,0xe4,0x19,0x28,0x0d,0x58,0x64,0xa1,0xaf,0x20,0x9a,0x2c,0x67,0x68,0x14,0xb7,0x0f,0x72,0xf8,0x14,0x1a,0xc7,0xe0,0x57,0x3e,0xe6,0x3e,},{0xf1,0xe4,0x45,0x14,0xd2,0xec,0xbc,0xc8,0xd1,0xa7,0xe8,0x4b,0xf5,0x84,0xce,0x73,0x18,0x35,0xe9,0x89,0x4f,0x88,0x97,0x4f,0x09,0x8d,0x45,0x6b,0x60,0x71,0x8f,0x57,0x5e,0xf4,0xd8,0x06,0x2f,0x21,0x82,0x50,0x42,0x50,0xcf,0x83,0xbb,0x2a,0xf2,0xa7,0x9b,0x1f,0x58,0xa6,0xa9,0x7b,0xd9,0x8d,0xa4,0x67,0x13,0x2d,0x7b,0xec,0x2f,0x05,},"\xe2\x76\xb1\x19\x12\xcc\xa5\xa8\x4b\xba\x65\x0c\x17\x2a\xef\x3a\x4d\x5f\x91\xac\x72\x29\x13\xbb\x89\x1a\x3a\xb0\x42\x4a\xb0\x7e\xa7\x09\xcb\x8b\xba\x3a\x3d\x11\xf8\x2f\x51\xc2\xaf\x01\x62\xa8\x2f\x72\x19\xce\x27\xb3\x5a\x30\x50\x7d\x53\x6a\x93\x08\x17\xe4\x0f\x85\xa2\x2a\x5a\x43\x2b\x94\xd1\x92\xc3\xc8\x91\x17\x77\xcf\xdb\x7f\xe9\x37\xa6\x75\x02\x77\x0d\x6d\x75\x75\x3d\x3a\xe8\x82\x29\xe0\x8f\x1e\xd2\x3b\x43\x28\xd8\x62\xac\x61\x86\x3c\x06\x3e\xa9\x84\x8f\x8a\xb9\x6a\x02\x13\xd7\xb9\x36\xc4\x8f\xe7\x54\x83\x6c\x98\x48\x78\x59\xd1\x99\xb3\xd9\x40\x39\x27\x16\xa1\xd5\x69\xe6\xc0\xcb\x1b\xa9\x18\x93\x2c\xf8\x85\x25\xe2\x56\xc8\xab\xb1\x1a\xaf\x0b\x45\x46\x55\xd5\xdb\x55\x71\x3c\xeb\xba\x28\x7a\xe2\x02\x65\x1a\xc8\x72\xbf\xc8\x0f\xea\xa7\xe0\x0d\x47\xc0\xbe\x38\xe6\x58\xf7\xc5"}, -{{0x90,0x72,0x1c,0x43,0xbc,0x36,0x6f,0x24,0xbf,0x4e,0x8c,0x99,0x3e,0x13,0x80,0x24,0x68,0x2f,0x10,0x29,0xdb,0xa3,0x5a,0xbe,0xb0,0xd6,0x0c,0x7f,0xa7,0x10,0x02,0x1c,},{0x7c,0x63,0xa2,0xf1,0x3b,0x7b,0x22,0x0a,0x0b,0xb7,0x52,0xe3,0x80,0x07,0x53,0xb8,0xb6,0xb3,0x26,0x69,0x37,0x8c,0xe1,0x31,0xbb,0x77,0xa9,0xa8,0xd2,0x30,0xe9,0xae,},{0xd2,0x06,0x4a,0x6d,0x6c,0x99,0xc6,0xc3,0xf1,0x52,0xd2,0xd4,0x35,0xf2,0x4e,0x34,0xb5,0x45,0x9b,0x08,0x2e,0xf1,0x1e,0x94,0x4a,0x77,0xff,0x54,0xdd,0xf9,0x86,0x27,0x37,0xec,0xb2,0xac,0x8d,0x54,0x20,0x7d,0x36,0xc5,0x1a,0xd4,0x1f,0x36,0x49,0x0a,0x11,0x1b,0xa8,0x0e,0x12,0x6b,0xfe,0xcb,0x09,0xde,0xf6,0xac,0xcb,0xdf,0x88,0x0e,},"\x65\x1c\x96\x17\xca\xc9\x58\xc7\xed\xd4\xa5\xf3\xfe\xdf\xb8\x3d\xc9\x71\xab\xfb\xb6\x9a\x31\xe8\x98\xcc\xa8\x47\x2e\xf0\x68\x03\x4a\x6d\x23\x76\xee\x0e\x72\xd0\xa9\xbf\xee\x27\x57\x96\xc3\x79\x5a\xda\xc8\xeb\xe1\xd1\x2b\x66\xec\x26\x8f\x6b\x75\xfa\x39\x41\x15\x4f\x99\xe2\x23\xfa\xf2\xcb\xab\x5b\x92\xe2\xb3\xba\x7b\x79\xbe\x77\x00\xef\x9d\xba\x69\x25\x3c\xce\x53\x56\xb0\xc4\xe7\x47\x03\xcf\xca\xfd\xb5\x54\x68\x50\xb4\x62\x32\x67\x5c\x90\xc0\x2d\x5e\x42\x6d\x33\xd6\x0c\xeb\xf0\xc7\x93\x01\x82\x37\x9d\xbb\x00\x7f\x53\x61\x63\xc8\xdd\xbb\xd3\x15\x7b\xb2\xda\x62\x34\x01\x33\xf0\x0a\xe2\x68\x2e\xc6\xba\xa6\x41\x6b\x5a\x01\x52\x1c\xc1\x0e\x04\x69\x52\x95\xf2\xe5\xb9\x4c\x05\xf0\x03\x83\xff\xe9\x54\x83\x07\x97\xf6\xdf\x82\x31\x72\x53\x2f\x98\x16\x5f\xe3\x14\xab\x32\x59\x29\xaf\x83\x85"}, -{{0x9c,0xec,0x24,0x67,0x58,0xe4,0x12,0xe7,0x37,0x8b,0x45,0x79,0xea,0xfe,0x9f,0xac,0x5a,0x25,0xd5,0x40,0x5f,0x92,0x70,0xb5,0xd7,0xe5,0x43,0x41,0x4e,0xc3,0xd5,0xda,},{0x97,0x5a,0x9e,0x6a,0x15,0x2c,0xae,0xbb,0x2f,0x9d,0xd0,0xde,0xb7,0x6d,0xd9,0x22,0xb6,0xdc,0x77,0x05,0x5d,0xda,0x03,0xfb,0xae,0x9e,0x7c,0x68,0x5d,0x07,0x3a,0xa1,},{0x9b,0xad,0x1e,0x3b,0x12,0x79,0xef,0x65,0x8f,0x4d,0x07,0x16,0x44,0xc6,0x3a,0xe2,0xb7,0xa7,0x80,0x35,0x7e,0x9d,0xc4,0x26,0xf1,0x65,0x0e,0xc0,0x63,0x4d,0xfc,0x52,0x0f,0x8e,0xda,0x9d,0xc8,0xf1,0x0a,0xa7,0x32,0x4c,0x59,0x42,0xd2,0x34,0x7f,0xf8,0x80,0x2b,0xd9,0x0e,0x95,0xfc,0xec,0x31,0x33,0x52,0xcd,0xae,0x64,0xf3,0x2a,0x04,},"\x17\xec\x9b\xd4\x7a\xdd\x6c\xcf\xbd\x78\x7a\xf0\xd9\x01\x3e\x9c\xc9\x79\xaa\xf8\x50\xe0\x94\x26\xd3\xb2\x8e\xdf\xd7\x12\x96\xeb\x31\xff\x8b\x21\xc5\xfe\x7b\xe0\x50\xf5\x36\x32\x4c\x3e\xc4\x88\x50\xe0\xb5\x08\xa3\x6b\xb4\xcb\x7e\x75\x4b\x32\x71\x83\xa1\xb3\x94\xd8\x8a\x79\x41\xd1\xce\x8d\xac\x62\xa5\xd8\x29\x18\x74\xd7\x84\x85\xe5\x1f\x29\xed\x05\x86\x5a\x20\x6e\x52\xec\xb1\x2c\x5d\x10\x7d\x4f\xf9\x6f\x25\xd3\xc5\xd1\x81\xd2\xc4\xba\x64\x63\x60\x0d\xb1\xcc\xa3\x28\x57\xfc\xf5\x97\xcb\xdf\xb2\xfd\xa2\x70\x8a\x8a\xba\x28\x1b\x43\xc3\xd2\x8c\x4a\x4e\x79\x83\x36\x15\x09\xf6\x1a\x10\x74\xe6\xf0\xad\x61\x01\xc7\xb5\x67\xee\x40\x78\xe9\x83\x9c\x47\xf4\x65\x31\xb7\x29\xff\x0e\xfe\xef\x7c\x9d\x1a\x8d\x83\x3d\x9c\x0f\x42\x81\x2a\x34\x18\x7c\x3a\x77\x8c\x16\x5c\x09\xd6\x45\x9c\x9c\x7c\xea\xa2"}, -{{0xd1,0x40,0x3f,0x63,0x20,0x2e,0x08,0x05,0x25,0x84,0x3b,0xde,0x25,0x5e,0xeb,0x6b,0x67,0x83,0xc1,0xca,0xae,0x9d,0x6e,0xd0,0x0b,0xa6,0x08,0x05,0xbe,0xd1,0x94,0x1f,},{0x23,0x8a,0xea,0x3a,0xd6,0xd6,0xf2,0x77,0x83,0xe7,0x05,0x16,0xbb,0xfc,0xca,0x47,0x70,0x36,0x6b,0x50,0xed,0x0f,0xe6,0xa4,0xe9,0x66,0xb5,0x3a,0xf1,0x21,0xa7,0x21,},{0x8e,0x60,0xe7,0x3c,0x06,0x38,0x16,0x79,0x5e,0x29,0xf5,0xd6,0x4e,0xce,0x11,0x59,0xf1,0xb5,0xd5,0x02,0x1a,0x6f,0x8f,0x65,0x5e,0x26,0x1a,0x4d,0x00,0x26,0xf5,0xb9,0x4f,0xf2,0x92,0x32,0x50,0x49,0x9d,0x99,0x52,0x98,0x48,0x05,0x12,0xe4,0x12,0x62,0x76,0xaa,0x4a,0x22,0x6d,0x01,0x5a,0x95,0x82,0x7b,0x3c,0xe6,0x92,0xe2,0x33,0x02,},"\xc4\xf1\x7d\x44\x2f\xba\x4c\xa0\xdf\x8d\xc1\xd0\x62\x8d\x7d\x7f\x36\xb6\x0b\x57\x58\xd7\xc1\x3b\x80\xb8\xf9\x7a\x62\x12\x4d\x96\xa2\x3b\x27\x95\x65\x49\x5a\x8a\xcc\xab\x59\x97\x11\x5b\x13\xa4\xba\x22\x0a\x73\x95\x7e\xb7\x93\x05\x20\xac\xbb\xfb\x6f\x54\xcf\x68\x72\x6b\x64\x50\xc6\xff\xa9\x47\x0b\x05\x5e\xa2\x62\x91\x4e\x2b\xc6\x12\x63\x3f\x1a\xc3\xd0\x61\x8a\x23\xdf\xf1\x88\xa7\x33\xd7\x6b\xcb\xcc\x46\x0f\x52\xab\x61\xe1\x99\x38\xf9\xc8\xca\xaa\x79\x2c\x20\x8d\x1f\x6c\x75\x47\x28\x90\x5f\xda\x51\xd8\x81\xa3\x47\xa5\x3d\xa7\x44\xd3\xba\xad\xc0\xa7\x6c\x47\x4c\x55\x86\x80\x26\x90\x95\xf9\x08\x4a\x74\x47\x1d\x5c\x09\xff\xc2\x91\x41\xb5\xbf\xaf\x49\x54\xdf\xac\xbc\xa6\x63\xd0\x37\xb1\x7e\xbf\x95\x59\x88\x22\x33\xe5\xca\x5a\x8b\xf7\x5c\xca\x4f\xc9\xc5\xa4\x10\x9f\x32\xe1\x45\xf3\x85\x3b\x17"}, -{{0xbd,0xf6,0xbd,0xc3,0x1a,0xb0,0xb5,0x31,0x37,0x84,0x48,0x3a,0xbe,0xca,0x6e,0xa5,0xe9,0xcd,0xc6,0x8f,0x81,0xb2,0x1f,0x35,0x0d,0x09,0xc3,0x90,0x7b,0xb9,0xb6,0xa1,},{0x03,0x62,0x77,0x12,0xb7,0x55,0xe5,0x06,0x9f,0xb9,0xab,0x8f,0x9e,0x89,0x97,0x24,0x02,0x9a,0x7f,0x26,0x8a,0xf9,0x39,0x88,0x21,0xee,0xec,0x93,0x60,0xc9,0x28,0x5b,},{0x38,0xfa,0xc6,0x03,0xed,0x24,0x6f,0x83,0x3f,0x1c,0x0f,0xd4,0x58,0x56,0x98,0xb0,0xa7,0x13,0x05,0xef,0xf0,0xd1,0x4a,0x00,0x49,0xb3,0xce,0xf0,0x73,0xbd,0x03,0x6d,0xd4,0x51,0xb3,0xda,0xba,0xda,0xae,0xae,0xa2,0xae,0xaf,0x83,0xd3,0x95,0x74,0x6f,0x4e,0x86,0x86,0x6a,0xda,0x97,0x1c,0xbe,0x48,0x2e,0xdb,0x04,0x19,0x33,0x2f,0x0e,},"\x90\xa6\x6a\xaf\xa5\x64\x2a\x98\xe7\x9f\x0d\x88\x14\x70\x80\x16\x7b\x11\xe4\x46\x65\x18\xf1\x95\xcd\xdd\x89\x40\xd1\x2e\xe4\x91\x8d\x31\xa6\xd4\xcb\x77\xd0\xbf\x5a\xf2\x99\x83\xbb\xe5\x08\x56\x10\xa7\x9d\xaf\x0c\x75\xa7\x8c\xcb\xcf\xfb\xbd\xab\x21\x89\xc3\x94\xae\x24\xe2\x65\xbd\x8c\x55\xfd\x3f\x40\x98\xe1\xb1\x75\x57\x75\x49\x51\x8e\x7a\x4d\xcf\x74\x52\x08\x6d\xd1\x27\x8d\xd5\x8e\xa4\xc0\xaa\x69\x0e\x91\x79\x51\xef\x39\xfc\xff\x60\xcb\xfa\x1e\x90\x91\x0b\xab\x53\x74\x92\x8d\x47\x22\xf7\x02\xbf\x5a\xd6\x02\x8f\xfd\xa6\x54\x1f\xa5\xba\x1a\x37\x79\xec\x78\xb0\xa9\x5f\xe3\x85\x0c\x74\x8b\x6c\x8f\x42\xf3\x30\xec\x79\x54\x1a\x52\xa1\xcf\x57\xdb\x72\xdf\x4f\x92\xce\x7f\x74\x8a\xee\xf1\xaf\x33\xbc\x5a\xe0\xa8\x2c\x89\xdf\xf2\x16\xf2\x3a\xec\x16\x8a\x7d\xbb\x51\x0a\xa6\x32\xda\xab\xcc\x97\x1b\x3f"}, -{{0x57,0xb3,0xb1,0x4a,0xce,0x1c,0xd0,0xcd,0x60,0x3e,0x63,0x28,0xbd,0x21,0x9e,0xe7,0xd9,0xd0,0x94,0x48,0x7f,0xa6,0x68,0xf2,0x8a,0xee,0xc0,0x2b,0x43,0xc9,0x09,0xa7,},{0x24,0xe6,0xb6,0x39,0x5f,0x97,0xea,0x0e,0x23,0x71,0x86,0xd4,0x69,0xb7,0x19,0x23,0xd2,0x11,0x3a,0xdf,0x40,0x3b,0xee,0xeb,0x4a,0x2d,0x27,0x90,0x9a,0xaf,0x3e,0xda,},{0xfc,0x79,0xfd,0xc6,0xd0,0x90,0x88,0x7a,0x61,0xe4,0x3c,0x6b,0x91,0x87,0xb6,0x57,0xd2,0xe4,0xd9,0xcb,0xaf,0xd6,0xe7,0xca,0xeb,0x7e,0xbd,0xea,0x84,0x28,0x25,0xb7,0x8f,0xb9,0x49,0xd2,0xc4,0x9a,0x0c,0xf3,0x8b,0x6c,0x73,0x29,0x6d,0x82,0xc8,0xdd,0xeb,0x1f,0xe2,0xd4,0x0a,0xad,0xdd,0x79,0x64,0xda,0x68,0xac,0xf8,0xc6,0x6f,0x0e,},"\xb2\xe0\xde\xdd\x80\x2e\xed\x99\x6d\xbd\x58\x36\xbf\x86\x88\xb0\xd1\x20\x1b\xf5\x44\x2f\xf9\xbb\xd3\x51\xae\xef\xe1\xa0\xc2\x1f\xea\x2b\x5c\x9f\xe5\xed\xee\x47\xe9\x21\x09\x9b\x05\xae\xda\xa8\x03\x67\xc1\xce\x08\x82\x1d\x78\x3a\x5b\x64\xcf\x05\x9c\x0f\x43\x35\x08\x39\x86\xa5\xa6\xec\xff\x8c\x84\xfd\x40\xe0\xba\x5d\xd5\xe5\xd2\xf0\x11\x12\xa8\x4c\xe5\xcf\x8e\x0d\xb7\x8b\xeb\x18\x2d\x91\x39\xc0\xb0\xf3\xe0\x06\x0a\x3f\xa7\x38\x69\xe9\x64\x23\xf1\x70\xdf\x9a\xf1\xcb\x9c\x35\x56\x6d\x87\xdf\xf5\x42\x22\x3f\x6d\x43\x9b\xdb\x54\x72\x9d\x36\x6a\xff\x63\x7b\x0f\x36\xa5\xd1\x4b\x15\xd6\x12\xbd\x03\x07\x6c\xc4\xd0\x4c\x1f\x25\xb3\xba\x84\xe0\xd1\xfe\x47\x4e\x57\x18\xd1\xa1\x7d\x5a\x48\x84\x65\x66\x2e\xe4\xc3\xf6\x64\xb4\xc9\x27\x4b\x64\x9d\x78\xce\xa4\xe8\x52\x43\xf3\x71\x32\x39\x04\x8a\x90\x8c\xe3\xe1"}, -{{0x01,0x8a,0x2c,0x3d,0xee,0xa5,0x0a,0xb5,0x06,0x75,0x1f,0x9c,0x2a,0xda,0xad,0xfd,0x9e,0x21,0x92,0x12,0x16,0x09,0x93,0x16,0x84,0xeb,0x26,0x5e,0x19,0x3e,0x7f,0x89,},{0xaf,0x41,0x0b,0xdd,0xde,0xfc,0x64,0x4e,0xf1,0x2c,0x98,0x99,0xff,0x71,0xb9,0xe1,0xd0,0xdf,0xa3,0xd6,0x9d,0x8c,0x2c,0xd6,0x76,0xc1,0x91,0x6b,0x34,0x59,0x1c,0xfd,},{0x7a,0x44,0xe6,0xa3,0x19,0x32,0xde,0xe6,0xdc,0x2d,0x83,0x94,0xe2,0x9a,0x65,0x51,0xd1,0x3e,0x6c,0x6f,0xfd,0xfa,0x21,0x8f,0xa5,0xb9,0x98,0x66,0x8d,0x84,0x39,0xdb,0x5e,0x05,0x37,0x9f,0xbf,0xa0,0xda,0x5b,0x56,0x3e,0xd9,0x66,0x43,0x5a,0xe2,0xc5,0x4e,0x3a,0xd1,0x6e,0x1a,0x9f,0xca,0x1f,0x5a,0x15,0x7a,0x08,0x07,0x04,0xab,0x03,},"\xcf\x78\x13\xef\xac\x12\xad\x1c\x7c\x73\x22\xcc\xbe\x54\xaa\x0e\x9a\x8b\xa4\xfd\x43\x45\xb0\x6e\x4c\xe7\xa3\x5c\x8b\x1c\xd5\xe3\xf7\xf0\x68\x85\x33\x84\x9b\xa2\xcf\x4c\x75\xb6\xf2\x09\x26\xa1\x19\x4a\x72\xdf\x0e\x1b\x1b\x34\x45\x6a\x21\x33\x11\x2d\x00\x67\x22\xfe\x81\x1d\x5e\x40\xc4\x12\x11\x59\xde\xd8\x89\x90\xc0\xac\x2b\xfd\x34\xf3\x5a\xf4\xf0\x7c\xc4\x02\xe9\xa3\x81\xa6\x75\xd0\x3f\xec\x7e\xc4\x38\xc4\xad\x9d\x92\x9a\xec\x8f\x24\x2d\xef\x02\x3c\x99\x3c\x9e\x8b\xa1\x8c\x74\x28\xe8\x8f\xde\x68\xa4\x71\x1e\x50\x6d\x79\x69\xf6\x3c\x8e\x0b\xc8\x3f\xf0\xde\x4e\x13\x36\x10\x6c\x05\xe0\x9d\x59\x22\x40\x0e\x8a\x81\xbf\x54\x88\x56\x67\x89\x97\x85\x88\x2b\x70\xf2\x0d\xd8\xfb\x1e\x75\xf5\x85\x5b\x76\x5a\x25\x6d\xa4\x34\x1b\xf2\x3e\xa0\xff\xa1\x8a\xad\xda\x38\x18\x16\x94\x60\x01\x04\x56\x69\xc8\xd0\x4d\xf0"}, -{{0xbe,0xa4,0x45,0xe9,0xb6,0xd3,0xf2,0x12,0x35,0x91,0x2c,0xd6,0xc4,0x2e,0xc0,0x57,0x72,0x97,0xca,0x20,0xa1,0x03,0x57,0x88,0x0c,0x2b,0x84,0x6d,0xd8,0xe2,0xcc,0x77,},{0x02,0x41,0x74,0x96,0x62,0x21,0x69,0x9e,0xa4,0xb0,0xa3,0x7e,0x51,0x7f,0xf9,0xb1,0x65,0x98,0xae,0x4d,0x4e,0x83,0xbf,0xa3,0xca,0x50,0xbc,0x61,0x68,0x41,0xf5,0x95,},{0x69,0x64,0xb9,0xc5,0x90,0x3e,0x74,0xe9,0x93,0x28,0xac,0xef,0x03,0x65,0x58,0xee,0xcd,0x33,0x69,0x15,0x0a,0x52,0xe2,0xcb,0xad,0x4b,0xbb,0x97,0xd4,0x61,0xb3,0xdf,0xc6,0xb3,0xe8,0x45,0x58,0x13,0xa4,0xf4,0xbd,0xca,0x46,0x30,0x2e,0x02,0xe6,0x83,0xec,0xea,0x18,0x20,0x17,0x1c,0x53,0x8e,0x54,0xc3,0xde,0x6c,0x95,0x4a,0xa4,0x07,},"\x47\x43\xc7\xc0\x99\xab\x81\x59\x27\xb3\x67\x4d\x00\x54\xb6\xde\x59\xaf\x28\x11\xab\xc2\xcf\x7f\xde\x08\xf6\x29\x29\x18\x5a\xdc\x23\x8f\xad\xd5\xe7\x5a\xe3\xba\x00\x36\xff\x56\x5a\x79\x40\x5b\x42\x4f\x65\x52\x33\x1e\x27\x89\xd9\x70\x9a\xc1\xec\xbd\x83\x9a\xa1\xe9\x1c\x85\x48\x17\x59\x79\x58\xcc\x4b\xd9\x1d\x07\x37\x75\x07\xc2\xc8\xd3\xc0\x06\xcf\xeb\x6c\x0a\x6c\x5a\x50\xee\xe1\x15\xe2\x11\x53\xdd\x19\x8e\xa0\xa3\xaf\xf6\x2b\x70\x75\xd5\xa4\x61\x78\x87\x83\xf0\x50\xe6\x59\xc5\x72\x96\x3d\x7a\x59\xe5\xaf\xaa\x2b\x9c\x50\x1f\x43\xc6\xac\x08\xab\x47\x97\xc4\x56\x6d\x22\xb9\x3c\xdf\x65\xa9\x9a\x2a\x1d\x63\x8e\x79\xf7\x2b\x5f\x46\x31\xfe\x5e\x9e\x5f\x96\x8f\x6d\xb7\xa1\x88\x0d\xf5\x1d\x8f\xeb\xc1\x49\x42\x67\x2f\x8e\xa6\xfc\x3a\x72\x81\x4a\x44\xd6\x6d\x14\x84\x20\xa6\x90\x00\xf6\x8c\x33\x0d\xe5\xb8\x0f\xc6"}, -{{0x64,0x47,0x54,0x0e,0xd7,0xbe,0x0a,0x11,0xc2,0xa8,0xde,0x79,0x3d,0x83,0xc6,0xe2,0x44,0x98,0x3d,0xb1,0x8d,0x78,0xec,0x9d,0x75,0xf1,0x72,0x9c,0x92,0xe0,0xfd,0xf1,},{0x39,0x12,0x12,0xc8,0xed,0xc4,0xd3,0x34,0xa5,0xbe,0xc8,0x60,0xef,0x0f,0x5e,0xbb,0x5e,0xc4,0x4e,0x8b,0xb5,0x1c,0x0f,0x67,0x41,0x99,0x89,0x59,0xb2,0xb3,0x79,0xfc,},{0x3a,0xb5,0xf8,0x8e,0x2f,0x72,0x76,0xb5,0xb6,0x58,0x3d,0xff,0xba,0x56,0x39,0x99,0x3a,0x90,0x5d,0xbf,0x9b,0x88,0xce,0xea,0xaa,0xae,0x33,0x35,0x80,0x0e,0x4a,0x5f,0x10,0xf8,0x3d,0xa6,0xd6,0x22,0x5a,0x8d,0xbe,0x99,0xae,0x80,0x07,0x50,0x09,0xdd,0x50,0x87,0x86,0xb3,0x97,0x51,0x13,0xdb,0x47,0x8e,0x14,0xba,0x10,0x1b,0xee,0x0f,},"\xa4\x38\x1c\x76\x38\xc4\x87\x99\xe9\xb5\xc4\x3f\x67\xfc\x3a\xa3\xcb\xb5\xec\x42\x34\xf3\x7e\x70\xcc\xcc\xce\xd1\x62\x7a\x57\x68\x3d\x1e\x53\xf4\xe0\x88\x3d\x8b\x46\x2b\xf8\x3f\x13\x08\x63\x03\x68\xc8\x9b\x49\x15\x33\xdd\xb8\xc9\xa5\xb9\xe8\x15\x50\x02\xfd\xd5\x81\xa9\xa5\xbe\x0e\x43\x0b\x90\x86\xa6\xbe\xac\x47\x20\x21\x0f\x87\xb1\x4e\x86\x2d\x97\xe5\xcc\x69\x28\x67\x86\xa7\x58\x67\x23\xf2\x31\xef\x0e\x3e\x1b\x93\x2d\xbb\xa3\xa1\x8a\x0c\xb2\x21\xcb\x07\xf8\x0e\x6a\x8e\x13\x00\x05\x6c\x13\xe7\x02\xb2\x3b\xfb\x32\x50\xec\x7c\xc8\x64\xd5\xc7\xec\x57\x86\x24\x07\x09\xc5\x60\x24\xea\x6b\xe5\xf7\xb1\x5a\x4f\xa5\x55\x5e\x39\xa7\x44\xa1\xdc\x55\x7d\xf5\xb9\x48\xdb\x22\x0b\x3d\x57\x45\x74\x66\x91\xda\xcb\x44\x21\x64\x1c\xdc\xc1\x2e\x7e\xc0\x45\x02\x93\xf1\x9e\xc5\x7b\x09\xcf\xf1\x35\x84\x7a\xab\xe4\x46\xa6\x13\x32"}, -{{0x0c,0x58,0x7a,0x81,0x1a,0xdd,0x88,0xb9,0x94,0x45,0x8c,0x3c,0x80,0x8a,0xc4,0xe3,0xa8,0x3a,0xfa,0xb2,0x6d,0x4c,0xff,0x5c,0x96,0x1b,0x9d,0xf0,0xb5,0xc8,0x33,0x44,},{0x06,0x78,0x3b,0x0c,0xdc,0xc5,0x02,0x8c,0x56,0x38,0xbd,0x74,0x8f,0x0b,0xc7,0x6f,0x7e,0x94,0xd1,0xaa,0x20,0x15,0xca,0x94,0x87,0x38,0xa3,0x50,0x04,0x60,0xac,0xa0,},{0x33,0xb4,0xf4,0x27,0x4f,0x20,0x00,0x8a,0x72,0x1d,0x1e,0x8d,0x05,0x4a,0x2b,0x4e,0x95,0x32,0x7e,0x38,0xbb,0x07,0xb3,0x3c,0x4b,0xee,0x7e,0x1c,0xe0,0x20,0xa4,0x42,0xfb,0x26,0x27,0xed,0xa3,0xb7,0xac,0x93,0xcd,0x3a,0xb0,0xb1,0x2b,0x99,0x93,0x5a,0x1a,0x92,0x33,0x11,0x16,0x04,0xda,0x4a,0xcf,0xfb,0x53,0x15,0xb9,0x07,0x12,0x0b,},"\xf5\x6d\xc6\xb7\x60\x76\x32\x5b\x21\x26\xed\x11\xd1\xf0\x9d\xec\xef\x9d\x15\xc3\x1d\x0e\x90\xcd\xb1\xa2\x7e\x08\x9c\xc5\x63\x29\xf6\xec\x3f\x66\x5e\xb6\x73\x9e\xc5\x67\x8b\x3f\x37\xee\x1f\xb3\x7d\xeb\x9e\x24\x00\x92\xb7\xa8\x8f\xd2\x55\x25\xac\xd5\x5e\x29\x4e\xb1\x04\x6f\x9b\x1b\x69\xa8\x47\xeb\x9c\xeb\x7b\x15\x93\xb9\xf6\x97\x8e\xf6\x18\xc1\x5d\xe4\xe0\x59\xec\xc3\xbf\xda\x32\x97\xa1\x9c\x2d\xf2\x02\xad\xf7\x21\x55\xcf\x21\xea\xbd\x03\x94\x8d\xf1\x51\x98\xe8\xa6\x8b\x08\x84\xf9\x3a\xd5\xe3\x6e\xb0\x98\x3c\xca\x30\xe4\x5a\x8b\x4b\x5f\xb8\x13\x6f\xde\xa8\xa3\x34\x1d\xd7\x87\x75\x40\xa5\x57\xde\xbf\x75\x30\xcc\x33\xae\xee\xf6\x27\x1c\x3f\x0a\xf6\xd0\x97\x87\xe8\x15\xf2\xf1\xdd\x25\xce\x4d\x2f\xd0\x9f\xfa\x9f\x53\x08\x1b\x46\x9c\x50\x0d\xa4\xd4\x41\x80\xc0\x4e\xb1\x86\x93\x29\xcb\xf2\xd8\x23\x18\x7e\x83\x1c\x24"}, -{{0x66,0xcf,0x40,0x1a,0x21,0x42,0xfc,0xf4,0xa8,0x01,0x80,0x46,0xcf,0x41,0x40,0xbc,0xa1,0x8d,0x76,0xef,0x62,0x66,0xe7,0xa0,0x24,0x75,0x7d,0xf1,0x72,0xa5,0xd6,0x53,},{0x67,0xd4,0x8d,0xfd,0x23,0x74,0x3c,0xc2,0xca,0x40,0xe4,0xdf,0xd6,0xb8,0xcc,0x5d,0x84,0xbe,0x82,0xdd,0x2b,0x11,0x20,0xcc,0x47,0x6e,0x6a,0xf6,0xf2,0x5e,0xcc,0x98,},{0xd6,0xb0,0xe8,0x0e,0x60,0xbc,0x1b,0x29,0xab,0x8f,0x74,0x80,0x8f,0xc4,0x60,0x84,0x77,0x95,0xcc,0xb8,0x87,0xba,0xc0,0xec,0xaa,0x8e,0x13,0x52,0x97,0xa8,0x50,0x97,0x71,0x2b,0x24,0xb0,0xa1,0xfb,0xaf,0x7a,0x67,0xc5,0xd5,0x30,0xa4,0x7d,0x06,0x43,0xfc,0x87,0x02,0xc0,0x59,0xd2,0x15,0xfb,0x11,0x2d,0xbe,0x47,0x5e,0x5b,0xca,0x0d,},"\xda\xa8\xef\xb3\xfd\x41\xf1\x2f\xbc\x55\xbd\x60\x46\x41\x57\xa2\x6d\x71\x86\x32\xd8\x82\xae\xdb\x6b\xf9\x8e\x47\xdd\x23\x37\x87\x9e\x0b\x46\x45\x2e\x06\x2e\x6d\xfb\xff\x3e\x7b\xca\x72\x89\xe4\xef\x6b\x3f\x41\xd4\xb0\x3b\xdc\x2c\x84\x2a\xfe\x97\xf3\x02\x98\x83\xed\x45\xf6\x05\x4d\xde\x96\x90\x64\x9a\xbb\x2b\x8d\xc2\x8f\x5f\xe8\xce\xcf\x80\xfc\x1e\xa4\x11\xbf\xc4\x0b\xbf\x4f\xd2\x0b\x21\x8c\xf4\x7e\xa8\xee\x11\x8d\x4d\x5a\xef\xa5\xc1\xbf\xa0\x8a\x8f\xb1\xb3\x0d\x6d\xe0\x97\x7c\xd1\x5e\x50\x29\x2c\x50\x1f\x2e\x71\xce\x27\x40\xff\x82\x8b\x84\x32\xda\x5a\x59\x4b\xab\x52\x23\x76\x0b\x64\x79\x2e\xd3\xa6\x9d\xd7\x5e\x28\x29\x23\x49\x43\x65\x65\x13\xdf\x1a\x17\xa2\xa0\x67\xa9\xa8\xea\xa6\x4e\x19\x56\x9f\x46\x93\x9d\x34\xb9\x92\x71\xae\x50\xa4\x7d\x7d\xbc\xa3\x62\x0c\x81\x25\x5b\x0e\x1f\xd1\xf3\xce\xc8\x51\xf1\xb1\x1b\x35"}, -{{0x5d,0xbf,0x88,0x5a,0xa5,0x98,0xe8,0x95,0x57,0x1f,0x5f,0x65,0x09,0x0b,0x72,0x32,0x3e,0x9d,0x70,0xb0,0xf5,0x81,0x10,0x68,0x7a,0xfb,0xbc,0x38,0x3a,0xfe,0xdc,0xac,},{0xfa,0x17,0xeb,0xa7,0x6e,0x3b,0xc3,0xea,0x6d,0xab,0x3a,0x5b,0x12,0x0d,0xc5,0xec,0xb9,0xae,0x6f,0x00,0x13,0x8f,0x7d,0x36,0xdd,0xa9,0x26,0x8b,0xc4,0x72,0x21,0x74,},{0xe1,0x42,0x9d,0xab,0x2e,0x42,0xcd,0x03,0x5b,0x7f,0xc6,0x02,0xef,0xd6,0xba,0xf9,0x47,0x06,0xf1,0x6e,0xaf,0x2f,0x8b,0x5f,0xed,0x32,0x92,0x39,0xe8,0x75,0x60,0x5f,0xb1,0x72,0xf5,0xdd,0x9a,0xe2,0xbc,0x2e,0xb4,0x2e,0xb4,0x74,0x56,0x7e,0x29,0x2f,0x52,0x06,0xe8,0x2e,0x69,0x4b,0xca,0x0d,0x6d,0x43,0x3b,0x86,0x76,0x34,0xcb,0x0d,},"\x1e\x0b\x6c\xf1\x5c\xe0\x33\x37\x17\x9c\x02\xd6\x54\x08\xdf\x5b\xe9\x20\x0c\x37\x82\xb6\x00\x4a\xf9\x4e\xa4\xde\xcb\x25\x79\x99\xd6\xfd\xff\x30\x1d\x11\xd0\x0c\x98\xc3\x72\xfa\xc0\xd0\x26\xcb\x56\xdf\xef\xe3\xde\xf7\xeb\x99\xac\x68\xd6\x96\x8e\x17\x12\x4d\x84\x46\xf5\x3e\x8d\x2d\x3d\xd8\x90\xd3\x7a\x23\xc7\xe0\xb8\x3a\x48\x4b\x3c\x93\xbd\xdf\x6c\x11\x8e\x02\x81\x95\x9d\x27\xbd\x87\xd3\x7e\x84\x3d\x57\x85\xf4\xa4\x07\x71\x39\x84\x94\xe6\xc4\x32\x2f\xbb\x67\x5c\x1d\x47\x93\x21\x03\x21\x48\xf7\xfe\x52\x56\x4d\xdf\x7a\xe7\xac\x26\x9d\x0c\xd2\xe5\x52\xfe\xc5\x89\xae\xae\x0f\xb9\x3f\xe3\xee\xae\xf0\x85\x60\x96\xcf\x4f\x6b\x34\x97\xe7\x23\x5c\xc8\x49\x4d\x81\x0a\x0b\x46\xc5\xea\xc8\x7f\x18\x7e\x50\x5b\xb7\x76\x4f\x80\x45\xc9\x54\x19\x83\xf7\xb0\x25\x69\x80\x09\xa2\x3d\x9d\xf0\xbd\x1a\x47\x3c\xbe\xe4\xcf\x5e\x94\x88\xec\xbc"}, -{{0x84,0xb3,0xae,0xdd,0x47,0x97,0xa5,0x65,0xc3,0x51,0xde,0x7d,0xfa,0x07,0x00,0xb9,0xff,0x7c,0x4d,0x72,0x91,0xc8,0x80,0x8d,0x8a,0x8a,0xe5,0x05,0xcd,0xd2,0x25,0x90,},{0xd7,0xad,0x72,0xca,0xa7,0xc2,0x22,0x09,0xec,0x46,0x78,0xd1,0x1d,0x55,0x90,0xa6,0xcb,0x28,0xa0,0x71,0x17,0xfe,0x5a,0xef,0x57,0xb5,0x07,0x51,0x58,0x32,0x01,0xa5,},{0x92,0x20,0xf0,0xed,0xaa,0xae,0xe1,0xb8,0x76,0x35,0x0d,0xbe,0x92,0x66,0x06,0x17,0x67,0xb8,0x62,0x96,0xc3,0x51,0xd4,0xca,0xc9,0x9d,0x07,0xcd,0x61,0x2c,0x6e,0xfb,0x24,0xf8,0xf9,0xb0,0xb9,0x75,0xf9,0x5c,0x42,0xc5,0xb6,0xaf,0xed,0xc8,0x92,0xf8,0x7e,0xfe,0xdd,0x39,0xd5,0x16,0x02,0x94,0xc2,0x76,0x58,0xbd,0xcf,0x42,0x85,0x0b,},"\x53\x25\x67\xff\xa5\x3b\x5c\x0f\xcd\x29\xc3\x94\x99\xd2\xe7\x8e\xcd\x20\xe6\x31\x23\x49\x92\x40\xe7\x75\x08\x8b\x39\x4d\xc6\x5c\x8b\xaa\xa0\xfe\x8f\x6a\xa7\xe7\x01\x81\xf9\xe1\x0a\xdd\x8b\x4a\x8b\xeb\x0b\x2e\xc3\x8a\x43\x30\x9f\x10\x0c\xd4\xbe\x91\xc6\xf4\x8e\x79\xdc\x0a\xee\x93\xa1\x5c\x94\x03\x77\x3b\x35\x4a\x8d\x42\xed\x48\xd8\xf2\x76\x23\x0f\xa6\xde\x5a\xda\x50\x1e\xe0\xa6\x53\xb4\x45\x8f\x0e\xcf\x6d\x5b\x3c\x33\xe2\x14\x1c\x66\x2f\x6e\xa0\x55\xf7\x41\xe5\x45\x86\x91\x7d\x2e\x0c\x4e\xb2\xb5\x66\x21\xf9\x66\x5f\xef\x32\x46\xf0\xbd\x80\x0b\x53\x3e\x3b\xc6\x15\xc4\x02\x1f\x8d\x0e\x2a\xd2\x33\xa1\x1e\x77\x36\xc4\x93\xac\xc3\x1f\xae\xe7\x6a\x09\x7d\xc4\x0d\xb9\xef\xc2\x24\x46\xea\xcf\x1c\xc1\x8f\x51\xfd\x10\x23\x6a\x2f\x94\x2d\x0a\x53\xc3\xce\x20\x91\x08\xb5\x93\x8c\x0a\x9e\x53\x6b\x89\xef\x0a\xd6\xb4\x05\xa1\x0f\x22\xc3"}, -{{0x69,0x50,0xbf,0xcf,0x48,0x0b,0x98,0xea,0x18,0xa2,0xd5,0xae,0x5b,0xa6,0xe7,0x66,0x8f,0x4c,0x28,0x3f,0xf2,0x71,0x13,0x57,0x74,0x0f,0xfe,0x32,0xcf,0x25,0x81,0x9a,},{0x8e,0x4c,0x6f,0x23,0x3f,0x7b,0x86,0x32,0x1c,0x9d,0x67,0x99,0xba,0xc2,0x8a,0xaf,0xcd,0x25,0x03,0xd7,0xaa,0x0a,0x7b,0xde,0xd8,0x72,0x27,0x27,0xfb,0xbc,0xae,0xb8,},{0x94,0xde,0x5d,0xf7,0xa2,0x5e,0xcd,0x70,0x20,0x5d,0x40,0xbc,0x94,0x99,0xfc,0x7c,0xd7,0x13,0x65,0x68,0x06,0x0a,0x41,0x9a,0x93,0xbe,0x6e,0x31,0x86,0x64,0xbb,0x6d,0xfc,0xe6,0x0e,0x2d,0x4e,0x63,0x3f,0x7e,0xc1,0x48,0xfe,0x4f,0x83,0x4e,0xd2,0x77,0xc1,0xfe,0xc4,0xc4,0xe2,0xa8,0x6f,0x44,0xc4,0x58,0x9c,0x81,0x78,0x88,0xdb,0x00,},"\xa4\x01\xb9\x22\xab\xa5\x7e\xe0\xc6\xac\x1c\x8f\x1b\x48\x29\x6a\x85\x62\xee\xf1\x37\x52\x68\x93\x88\x6a\x08\x30\x6e\x22\x03\x66\x77\x88\x61\x8b\x93\x98\x64\x46\x7a\x31\xf1\x6e\xdc\xe1\x52\xa4\x2c\x25\x54\x6b\x64\x0e\xa8\xbe\xd1\x89\xa4\xf8\x98\x86\xa3\x7f\x10\x69\x11\xea\xe1\xf5\x00\x81\xbf\x79\x5e\x70\xc6\x50\x44\x37\xd2\xa8\x0c\xb8\x39\x47\x9e\xcb\xb8\x7c\x12\x9b\xcc\x5f\xe3\x1d\x71\x6e\xf9\x78\xc2\x06\xd7\xf0\x8a\x79\x34\x66\x59\x4f\x4d\x75\xe2\x15\xbb\x63\x74\x59\x6f\x8e\x7d\x00\xee\xa7\x24\x78\x09\x43\xe8\x9b\xd3\x86\x3c\x95\x1b\xbd\x24\xef\xee\x23\xc9\x7c\x2c\x79\x7c\x7f\xaf\xbf\x8f\x2c\x8b\x43\xf3\x7a\x5f\x88\x11\x29\xa0\x95\x73\xfa\x7a\x03\x4a\x28\x5e\x80\xdc\x4b\xa4\xbc\x95\x64\xa4\xdc\xed\xeb\x33\x16\x7e\x0b\x30\xc5\xa0\x0b\x9a\x10\x9a\x22\x31\xcf\xa0\x01\x2b\x29\xb2\xb3\x45\x0b\x89\x2e\xcc\xef\x08\x08\xe5\x03\xf8"}, -{{0x61,0xb2,0x60,0xf5,0xb8,0x48,0xb2,0x71,0xef,0x48,0xe5,0xa5,0x6d,0x29,0x74,0x32,0xd8,0x9f,0x2a,0xb8,0x5b,0xd5,0x38,0xfa,0x66,0x88,0x70,0xd0,0x56,0x02,0x20,0xe5,},{0x60,0x86,0xfe,0x87,0x35,0xf3,0x99,0xf1,0xaf,0x2e,0x39,0x5e,0x0f,0xdf,0xb5,0x62,0x9e,0xbc,0xb0,0x4b,0x6e,0xd4,0xa5,0x4a,0x9e,0x47,0x05,0x2c,0x6e,0x81,0x91,0xd4,},{0x98,0x28,0xfe,0xc8,0xff,0x5c,0xf8,0x5a,0x98,0xf4,0x50,0x77,0x0b,0x5b,0xdb,0x4b,0x80,0xda,0xca,0x44,0x37,0x9d,0x8f,0x53,0xc9,0x1c,0x34,0x8e,0x22,0xdf,0x64,0xac,0x48,0xf2,0xb6,0xe2,0xa7,0xb3,0xb6,0x42,0xbc,0x81,0x93,0xa1,0x94,0x31,0x62,0x29,0xe6,0x94,0x47,0xed,0x24,0x1c,0xd4,0x23,0xd8,0x3b,0x6f,0xe7,0xb2,0xd4,0x4b,0x00,},"\x28\x26\x29\x5d\x79\x94\x5f\x67\x54\x76\xbc\x4d\x45\xef\x80\x0d\x80\xb1\xf0\x39\x8e\x4b\xe6\x0e\x3d\xe4\x57\x1e\xd1\x08\xdf\x98\x9f\x03\x2d\xe6\xc2\x34\x5d\x99\x48\xd6\x77\x92\x7e\xa0\xb8\xcf\x1a\x5c\xa3\x6f\xd5\xf2\x3c\x25\xdc\x0d\x2a\xb5\xbd\x56\x5a\x54\xaf\x46\xfd\x97\xd3\x38\xd7\x70\xe3\xa7\xb4\x7e\xfb\x54\xc0\x7a\x16\x64\x70\x77\x71\xeb\x4e\x37\xd9\xd7\x0b\xa7\x79\x25\x1d\xcd\xcd\x3b\xf6\xd1\x24\x8a\xde\xc5\x3f\x78\x72\x59\xc4\xd5\x94\xd5\xfd\x4c\xed\x8e\x3d\xb7\x62\x1d\x49\x65\xd4\x82\x98\x17\x81\x24\x93\x1a\x3d\x0c\xd2\x69\xb2\xd5\x3b\x7c\xd2\x61\xb9\x6d\x37\x0c\x5d\x96\x93\xc8\xad\x13\x3e\xd5\x89\x45\xee\x35\x40\xe1\x06\x25\xd9\x24\xae\xba\x9b\xda\xfc\x65\x61\x00\xaa\xb2\x76\xfa\x99\x6b\x1d\xb4\x77\xbf\x85\xea\x55\x90\x81\xd5\xb4\xc7\x30\x7d\xc1\x59\x56\x54\xac\xa8\x2f\x7b\x6d\x2d\xda\xf7\x35\x7c\x15\xa4\xd7\xd8\xb9\x08"}, -{{0x93,0x6d,0xc1,0xce,0xf6,0xa3,0x10,0x74,0x7f,0x35,0x00,0x88,0x05,0x5a,0x39,0xaa,0x76,0x2d,0x9a,0x4b,0x52,0xc8,0xc8,0xe4,0xc6,0x82,0x79,0x43,0x80,0xc2,0x72,0x5c,},{0x03,0xb3,0x18,0x00,0x41,0x2d,0xf4,0xd5,0x6f,0x15,0x32,0xc0,0x58,0x28,0xc0,0xb7,0x25,0x28,0xa6,0x7a,0x78,0x1b,0xef,0x4c,0x06,0xc1,0xfb,0x6f,0xf2,0xce,0x32,0x4b,},{0x3f,0x99,0x4b,0x8e,0xf5,0x28,0xf6,0x42,0x1c,0x6a,0x6a,0x22,0xe9,0x77,0xad,0xe5,0xce,0xe8,0x87,0x26,0x3d,0xe3,0x8b,0x71,0x9a,0xcd,0x12,0xd4,0x69,0xbf,0xd8,0xc3,0xf6,0x8e,0x7a,0xc0,0x7d,0x2f,0xae,0x80,0xa2,0x09,0x27,0x78,0xdf,0x0b,0x46,0x35,0x37,0xad,0x3a,0x05,0x51,0x99,0x7a,0x3d,0x5b,0x51,0xf8,0x32,0xd9,0xc8,0x23,0x0b,},"\xeb\x58\xfe\x86\xc4\xef\x34\x9c\x29\xae\x6f\xb0\x4f\x10\x85\x0e\x38\xc6\x82\x3d\xbe\x64\xa0\x9a\x5b\xf1\xe0\xce\x60\x0d\x39\x4e\xfa\x6f\xb9\x6e\xd6\xa8\xf2\xc9\xd4\xbe\xc0\x5e\x6a\x5e\xbd\x5a\x1b\xf4\xd0\xc5\x1d\xb9\x34\xe5\x7b\x79\xe5\xc6\xa8\x79\xd9\x75\x19\x7d\xbb\x10\x47\x5f\x65\xc7\xf8\xa8\xc6\xa7\x7a\x42\x03\x84\xb5\x06\x2a\x27\x40\xf1\x40\x17\x40\xee\x0f\x5e\x04\x3a\xad\x7a\x2a\x2b\x42\x60\xc5\xd9\x07\xf7\x05\xed\xaf\x65\xb0\xe3\x75\xdf\xc7\xb0\x0b\xd6\x60\xdb\x61\x47\xf2\xeb\xe8\x70\xa0\xee\x18\xdc\x2b\xa3\xc9\x2b\x0b\x76\xfa\xe2\xb9\x09\x32\xcd\xb6\xc1\x49\xe4\x6f\x3f\xee\xcf\x4c\x26\xf0\x44\x1f\x3a\x9e\x00\x66\x78\xae\xcf\xf8\xcc\xae\xca\xed\xa7\x3a\x18\xa6\x8a\xc9\x88\xb6\x2e\x83\xa9\xbb\x51\x88\xae\xde\x38\xdf\x77\xa9\xa1\x64\xab\xbd\xd9\xd5\x8e\x52\xa6\xca\xf7\x22\x23\x89\xf1\x98\xe8\x5f\xbf\x96\x62\x36\xdc\xdb\xd4\xc1"}, -{{0xf8,0x9e,0xed,0x09,0xde,0xc5,0x51,0x36,0x1f,0xa4,0x6f,0x37,0x59,0x73,0xd4,0xfb,0xfa,0x5c,0x5c,0x12,0xf1,0xb5,0xe5,0xab,0xf4,0x5c,0xfa,0x05,0xff,0x31,0xa3,0x40,},{0x3e,0x0e,0xfd,0xca,0x39,0x19,0xfa,0x10,0xd4,0xa8,0x49,0xce,0xf1,0xde,0x42,0x88,0x51,0xbd,0x08,0xef,0xd2,0x48,0x59,0x4f,0xd8,0x9c,0xde,0xb9,0xde,0xee,0x43,0xb0,},{0x89,0x7e,0x6f,0x27,0x97,0xc3,0xf3,0x26,0xd2,0xcd,0xb1,0xd2,0x67,0x3d,0x36,0x06,0x31,0xf0,0x63,0x30,0x45,0x80,0xff,0x5b,0x4e,0xb4,0x3d,0x39,0xad,0x68,0x51,0x83,0x4c,0x9c,0xf8,0x91,0xd9,0xf0,0x90,0x5b,0xf8,0xde,0x07,0x5f,0x76,0x35,0xdf,0xca,0x60,0x1a,0xdc,0x0f,0x14,0xe7,0xb2,0xc7,0x6f,0x75,0x71,0xbf,0xa4,0x68,0xed,0x0c,},"\x4c\xf9\x77\x3d\xa0\x5f\xd3\x22\xfc\x14\x7b\xe9\x00\xef\x5c\xf2\x56\xc8\x8a\xfd\xad\x4b\x08\xc2\x30\xdf\xc8\x98\x1f\xb6\x9f\x47\x6f\x7d\x45\xef\x7c\x90\x06\xbc\x10\x03\x2b\xa5\x34\x36\xac\x22\x84\x3e\x0d\x76\x28\x9c\xf6\x8f\x98\x18\xfa\x64\x03\x1d\x4b\x40\x95\x50\x59\xaa\x69\x11\x09\x15\x88\x9f\x5e\x22\x73\x2a\x13\x43\x91\x25\x81\xab\x3b\x11\xa3\xba\xe7\xa4\x71\x35\x95\x08\x59\x65\x75\xf8\x88\x16\x0b\xee\xf9\x66\xe5\x70\x8f\x0e\x31\x47\xea\xcf\xce\xc1\xca\xa3\xef\x24\x0c\x5e\x0a\x14\xc1\x86\x54\x6c\x8e\xeb\x64\x65\x83\x50\xb1\xaf\xfc\x0c\xfd\x2a\xc2\x13\xaf\x67\x0a\xfc\xa7\xbb\xc9\xdd\xdd\x28\xa4\x65\xb5\x86\xe6\x9c\x38\x8c\xd7\x34\x78\xd6\x8e\xfb\x32\x2b\xdf\x86\xd9\x21\x30\x11\xe7\x11\xb2\xb9\x5f\xef\xa7\xbb\x9b\x59\x39\x76\x17\x06\xaa\x71\x21\x02\x49\x06\x42\x0b\xdd\xf1\xd8\x80\x0a\x43\x38\xd9\x38\xfa\x13\x7c\xf2\x7e\x9f\xfc\x51\xc6"}, -{{0x40,0x07,0x96,0xef,0x60,0xc5,0xcf,0x40,0x84,0xde,0xe1,0x80,0x1c,0x4a,0x19,0x75,0xe4,0x82,0xe7,0x0a,0xef,0x96,0x1c,0xd4,0x2e,0x2f,0xd5,0xa3,0xfa,0x1a,0x0f,0xbe,},{0xf4,0x7d,0xa3,0x81,0x28,0xf2,0xd0,0x12,0xcc,0x57,0x97,0x57,0x1d,0x47,0x9c,0x83,0xe7,0xd8,0xa3,0x40,0x98,0x02,0xf9,0xa7,0xd9,0x76,0xc2,0x70,0x67,0xcb,0xbe,0x43,},{0x84,0xd3,0xaa,0x3f,0x36,0x18,0x44,0x39,0x67,0x54,0xd8,0x0d,0x9f,0xa0,0x5b,0x8b,0x2f,0xa4,0xab,0xf3,0xa0,0xf3,0x6b,0x63,0x9b,0xee,0x9c,0xfb,0x5c,0x85,0x30,0xa3,0xa9,0xcc,0x34,0x67,0x7f,0x92,0xa9,0x13,0xc4,0x1e,0x80,0x0f,0x2e,0x80,0x41,0xf7,0x66,0x6d,0x07,0xed,0x85,0xf1,0x6a,0x57,0xd8,0x17,0xb1,0x24,0x1f,0xc5,0xee,0x04,},"\xc4\x73\x32\x5e\x78\x5b\x27\xdf\x44\x71\xee\xfb\x9e\xbe\xbd\x64\x61\xd5\x70\x80\x01\x81\x10\x0f\xf3\x6c\xaf\x3c\x38\xf6\x7c\x19\x21\xb1\x57\xec\x8e\x61\x26\xf9\x55\xae\xbd\x90\xea\x3f\xe5\x38\x5f\x80\x42\xcd\x70\x4b\x27\xcc\x1d\x69\x78\xc0\xe2\xa2\x96\x69\x5f\x5e\xf9\x7b\x7c\x2e\x16\xae\x4f\xf4\xd0\x63\xc6\x88\xd7\xf4\x6e\x96\x4e\x1f\x0a\x00\x50\x3f\x35\x73\x45\x97\x76\x83\xd6\xe4\xc3\x42\x3d\x56\xbd\xb6\xce\x86\x4b\x69\x87\xe0\x85\xe8\x3e\x70\xc7\xc1\xa1\x4e\x0e\x41\x3f\x59\x2a\x72\xa7\x1e\x01\x7d\x50\x5b\x64\xc2\x4f\x1a\x1a\x6b\x81\x3e\x06\x4e\x6e\x0c\xf8\xbd\x45\x71\xd0\xff\x2f\x26\x7a\x6a\x13\xe0\xcd\x43\x04\x63\xb6\xca\x3b\x88\xf0\xcd\x40\xb0\xfb\x83\xd5\xbe\xdf\x6f\x7d\x47\xe1\x70\xe8\x7d\x0a\x75\x00\x93\x69\x3e\xda\x23\x2a\x6d\xaf\x98\x12\x57\x27\xb9\x58\x8e\xcb\x89\x4a\xe3\x73\xba\xe3\xa4\x45\xa1\x06\x30\x64\x69\xa4\xc2\xcd\x77\xff"}, -{{0x67,0x03,0xa6,0x23,0x2c,0x5e,0x2e,0x65,0xe0,0xab,0x3b,0x92,0xe2,0xaa,0xf9,0xf5,0xfb,0xd3,0x3f,0xb4,0x69,0x88,0x04,0x7d,0x6f,0x4d,0x0f,0xf5,0x38,0x7f,0xa0,0x29,},{0x04,0x7c,0xff,0xca,0x8b,0x7b,0x11,0xac,0x6e,0xac,0xc0,0xea,0xa0,0xc5,0xb7,0x3c,0x75,0xb9,0xc6,0x37,0x95,0x69,0x73,0xaf,0x9d,0x97,0xb2,0xdd,0x5b,0x60,0x5d,0x6f,},{0xca,0xe9,0x68,0x79,0xe5,0xb6,0x03,0xbe,0x86,0x66,0x09,0xd4,0xa0,0x53,0xbf,0xa1,0x2a,0x51,0x37,0x8e,0x99,0xb2,0xa2,0x81,0x2e,0x47,0x89,0x26,0x7d,0x8f,0x32,0xf4,0x73,0x24,0x3f,0x8a,0xf7,0x4b,0x9b,0xe7,0x3f,0x47,0xde,0xa5,0x0f,0x0d,0x16,0x5e,0xbf,0x49,0x45,0x8b,0x73,0xe5,0x3d,0x88,0x58,0x0c,0x19,0x1a,0x18,0x2d,0x19,0x04,},"\xa2\x6b\x30\xa7\x69\x19\x79\x32\xa3\xa6\x28\x54\x96\x8d\x76\x01\x51\x61\x23\x66\x77\x8d\xc9\x94\x57\x6a\x2e\x0e\x03\x55\x49\x6b\x46\x20\x0e\x50\x69\x48\xa0\xd1\x02\xb6\x65\x1b\x2e\x73\x34\xca\x6c\x6e\xae\xf8\xbc\xa4\x4b\x42\x59\x70\xa0\xb3\x7d\x6b\xde\x0d\xa9\xd3\xc1\xb9\xf5\x1c\xbb\x25\xbc\x33\x5c\xd6\xfa\x92\x8a\x74\xf2\xc0\xdc\x2c\x6e\x99\xd3\x7a\x12\x86\x3a\x47\x4d\x4d\xf4\x3a\xad\x35\x41\x5f\xfc\xaa\x24\xd8\xc2\x9f\x91\x45\x72\xab\x2a\xbe\xc3\x89\x2d\xb4\x9e\x67\x9c\x5e\xa2\x20\xc2\xf5\x19\xa7\xd0\x33\xac\x1a\x2c\x5a\x46\x78\x69\xe3\x0e\xda\x3d\x26\x35\xca\x86\x34\x31\x47\x3f\x95\x8d\x55\x2b\xdc\x55\x82\x35\x2c\x29\x0d\x0c\xe4\xfa\x9c\xfd\x0a\xd4\x27\x99\xc2\x27\xec\x90\xb7\xc9\xe5\xdb\x9f\x5a\x7b\x6d\x56\x92\x12\xee\xd9\x4d\x32\x33\x26\x80\x5f\x2b\x3a\x00\x10\xd6\xc1\x1e\xb4\x10\x7c\x82\x83\x03\x76\x52\xf5\x0d\xc0\x67\xb6\xdc\x81\xf4\xdb"}, -{{0xe0,0xe7,0x2f,0x8f,0x17,0x86,0x33,0x62,0x67,0x33,0xbc,0xbd,0xa2,0xad,0x2a,0x50,0xe6,0x53,0x89,0x0f,0x15,0x35,0x9b,0x6c,0x22,0xfc,0x73,0x45,0xad,0x33,0x31,0x09,},{0xd1,0x3c,0xee,0x54,0x0d,0x84,0xb5,0x66,0x7d,0x51,0x6f,0xe7,0xec,0x72,0x39,0xbf,0x8d,0xa9,0x15,0x46,0xee,0x79,0x1f,0x84,0xed,0xd8,0xff,0xcf,0x3a,0x08,0x3e,0x76,},{0x14,0x55,0x21,0x71,0xb9,0x52,0x45,0xac,0x0f,0x0e,0x5a,0x6e,0x7a,0x2f,0x54,0x17,0x21,0x06,0x8d,0xb6,0x50,0xc6,0xda,0xda,0x04,0xc2,0x8c,0xab,0x7c,0x49,0x19,0x5f,0x64,0x36,0x71,0x21,0x44,0xcb,0x31,0x91,0x3c,0x56,0x2e,0x30,0xc3,0x9d,0x8a,0x85,0x49,0xfb,0x64,0xff,0xea,0x81,0xc7,0x44,0x51,0x43,0xb5,0xf2,0x32,0x86,0xda,0x05,},"\x79\x1f\xd6\x13\xc1\x09\x52\x92\xc8\xa4\xa2\xc8\x6b\x47\xae\x02\x61\x55\xb8\x46\x5b\x60\x7d\xbb\x41\x64\x77\xef\x79\xa2\x97\xc9\xd7\x75\x8c\xe3\x4a\xf9\xdc\xbf\x1c\x68\x47\x4f\x30\x90\x9f\xbe\x74\xb7\xba\x42\x96\x32\xf2\x40\x3a\xad\x83\x2b\x48\x6b\x72\xc2\x30\x54\xad\x42\xf7\x65\x3a\x9d\xdb\x45\x6c\xc7\x91\xf3\x48\x88\x6a\x7a\xe5\xdc\xec\x7c\x0b\xa8\x15\xf7\xa9\x3a\x10\xfe\x33\x1e\x90\x3b\x97\x0f\x7b\x50\x28\xbe\x49\xd1\x4b\xc5\x62\x0d\x63\x79\x26\x72\xb9\x8b\x94\x88\xc6\x7a\xe1\x66\x46\x69\x3e\x11\x20\x47\xf0\xac\x89\x21\xff\x56\x1c\x92\xdd\x05\x96\xd3\x2d\xf0\xa6\xe5\x07\xac\x1b\x07\xde\x51\x6c\x98\x42\x8d\x57\x0a\x37\xdb\x9b\xcd\x7c\x7e\x61\xc6\x94\x8a\xb3\xfe\x91\x25\x0d\xd1\xd5\xbd\x67\x12\x75\xdf\x9a\x97\x2f\x22\xc2\xba\x36\x80\x47\x47\xae\xc1\xea\x24\x16\xc1\xf4\x1a\xb8\x7b\xef\xde\x31\x62\x9b\x2d\x43\x31\x7c\xe4\x1c\xda\x03\x62\x62\x86\xc0"}, -{{0x54,0x4d,0xaf,0xd9,0x96,0x0d,0x82,0x97,0x56,0xc6,0xd4,0xb3,0xea,0xdd,0x44,0x37,0x5f,0xe7,0x80,0x51,0x87,0x6b,0xf9,0x78,0xa3,0x81,0xb0,0xde,0xca,0xaa,0x80,0x96,},{0xae,0x4f,0x64,0x25,0xc1,0xb6,0x7c,0xcb,0x77,0xf9,0xaa,0xcf,0xea,0x28,0xea,0xef,0x76,0x9c,0x8c,0xac,0xee,0x03,0x52,0x05,0xcd,0xcd,0x78,0x7e,0x8d,0x07,0x62,0x9d,},{0xa2,0xae,0x11,0x7c,0x8d,0xe4,0xca,0x6d,0x6f,0xe7,0x5e,0x46,0x60,0x23,0xbd,0x55,0x0c,0x26,0xfe,0xdd,0x3e,0x74,0xca,0x13,0xad,0xb6,0x25,0xf2,0x72,0xe1,0x75,0xf1,0x4d,0x5d,0xf5,0x50,0xac,0xe7,0xd8,0x22,0x88,0xef,0xef,0xab,0xf9,0x63,0x11,0xa1,0x23,0xbe,0xe2,0x38,0x89,0xad,0x37,0x11,0xbf,0xf2,0xb8,0x08,0x79,0x46,0xbf,0x0e,},"\x44\x7f\xe7\x34\x4c\xad\x1f\xae\x09\xd6\xa7\xd0\x5f\x09\xd5\x03\xc1\xb3\xd3\xd5\xdf\xa5\x84\x81\x0c\x35\xbc\x41\xe4\x95\x56\x93\x70\x61\x54\xe2\xd7\x51\xb2\xf1\xb5\x25\xe1\xa1\x45\x47\xba\x7f\x8b\x23\x20\x88\xa6\xfc\x92\x27\x02\xd9\x3a\x11\xcd\x82\x94\x9c\x27\xbe\xd6\x45\xdc\x35\x1f\xb4\xc1\x24\x2c\xf4\x1d\x01\x57\x54\x12\xe7\x92\xae\xd2\x14\x53\x1d\x94\xfd\x66\xe0\x3d\xd3\x2e\x97\x2f\xd7\x7f\x69\x47\xa3\x53\xe1\xae\x5e\x00\xf5\xa6\xca\x77\x99\x24\x72\xf0\x96\xb6\xe7\x47\x5f\xe5\x34\xe9\x13\xa7\x7b\xcb\x0d\x68\x1f\xdf\xb3\xa7\xa0\xdc\xb5\x6d\x27\x4d\xf4\xaa\x10\x9d\x4a\x8a\x37\x79\x4a\x92\x76\xf5\x00\x06\x69\x6f\xf1\x2c\xa4\xd0\x25\x40\x39\xdf\x0f\xb3\xf7\x2a\x96\x0d\xa0\x5c\x98\x72\xf2\xe3\x3e\xe8\x1d\x1c\xf7\xa6\xf4\x8b\xbc\xe0\xaa\x18\xc7\xc0\xf0\x6b\xa5\x5e\x67\x68\x9e\x0a\xf5\x87\xb5\x00\xea\xb7\x9c\xc7\xf9\x64\x0b\xca\x10\x4b\x7f\xbf\x31\xf0\x8e"}, -{{0xbf,0xbc,0xd8,0x67,0x02,0x7a,0x19,0x99,0x78,0xd5,0x3e,0x35,0x9d,0x70,0x31,0x8f,0xc7,0x8c,0x7c,0xc7,0xbb,0x5c,0x79,0x96,0xba,0x79,0x7c,0x85,0x54,0xf3,0xf0,0xf0,},{0x7c,0x5a,0xe3,0xba,0xb9,0x20,0x11,0x99,0xdf,0xbe,0x74,0xb7,0xd1,0xec,0x15,0x71,0x25,0xbd,0xba,0xa4,0x52,0x0f,0x50,0x1d,0xa3,0xf2,0x48,0x57,0x9d,0xc6,0xc2,0x2d,},{0xe4,0x86,0x15,0xb6,0x56,0x33,0xe6,0x19,0x93,0xb0,0xaa,0xa1,0xfa,0xfb,0x74,0xb9,0x62,0x9c,0x38,0x4f,0xd5,0x92,0xbd,0x73,0x5f,0xa1,0xf6,0x2c,0x5c,0xad,0x11,0x29,0x1f,0xcd,0x8c,0x2e,0x91,0xa5,0x0b,0xfe,0x0b,0x03,0xb4,0x35,0x02,0xff,0xf3,0xa5,0xc3,0x82,0xb9,0xc2,0x82,0x19,0x07,0xef,0xc3,0x4d,0xa5,0xba,0x05,0x4a,0xf0,0x0e,},"\x11\x7f\xae\x13\xe7\x87\x77\xb6\x21\x9f\x02\x02\x14\xc1\xb8\x7c\x57\x04\x6d\x1c\x09\xce\x82\xee\x2b\x56\x29\x89\x8d\x9b\x0d\xe7\x4a\x15\xcf\xe9\x9f\x80\x54\x8b\xa9\x13\xd7\x03\x6c\x56\x28\x5a\x4c\xba\x49\x3b\x52\xd2\xcb\x70\xd6\x36\x5a\xce\x3d\xa1\x2b\x1f\x34\xa2\x77\x8a\xf3\x6e\xf5\x2a\xb8\x2e\xde\x04\xca\xca\xf2\x79\x3f\x5f\x89\x83\x1e\x3b\x20\x5a\x9e\xe4\xc1\xd6\xfb\xda\xb4\xba\x4d\x9f\xae\x65\xdd\x79\xa5\xfe\x76\xb4\xb3\x9a\x30\x92\xcc\x71\x48\xd2\x11\xe8\x5e\xe8\x2a\xb4\x63\xd3\x4d\xce\xe9\x06\x1d\x9c\x21\xde\xd2\x05\x1b\xbd\x50\xb4\x13\xf0\xe2\x1a\x0e\x48\xd1\xff\xa8\xdc\xae\x24\x0b\x34\x95\xbe\x25\xd9\x31\x51\xb5\x7a\xa2\x71\xab\x99\xaa\x70\x8c\xa2\x80\x80\xca\xb4\x80\x4f\xce\xfa\x92\x9f\x5f\x1e\xf3\xf4\xc6\xc0\xfb\xfb\x40\xbe\xf7\xea\x1b\x50\x9b\x36\xba\x12\x60\x32\x35\x12\x37\x9d\x7b\xc3\xfd\xbb\x5d\x3f\xaa\xc9\xb0\x0e\x21\xf1\x2e\xa1\xca\x2e\x29"}, -{{0xdf,0x2d,0xf8,0xa9,0xd6,0x6d,0x56,0x38,0xcd,0xee,0x09,0x32,0x4e,0x7b,0x10,0xf8,0xed,0x29,0xab,0x91,0x38,0x7e,0x31,0x47,0xb7,0xdc,0x03,0xf7,0xcd,0x80,0x05,0x08,},{0x5c,0x04,0x2e,0x15,0x7f,0xb7,0xfb,0x12,0xd4,0xd4,0xfe,0xf2,0x84,0x71,0x41,0xec,0xfb,0x57,0xc1,0x25,0x3e,0x14,0xea,0xf3,0x00,0x4d,0x65,0x13,0xf5,0x2f,0xe6,0x25,},{0x9a,0x10,0x74,0x53,0x1e,0xd4,0x3d,0x07,0xbf,0xfc,0x7f,0x2b,0x6c,0x13,0xb8,0x83,0x8f,0xc7,0x5c,0xba,0x02,0xc7,0xd1,0xec,0x7b,0xa3,0x8b,0xca,0x3c,0xef,0x20,0xdc,0x9b,0xad,0xf3,0xa3,0x06,0x4a,0x2c,0x93,0xb1,0x84,0x24,0x41,0x42,0x0b,0x6a,0x8d,0x42,0x1a,0x96,0x0d,0x70,0xdf,0xb7,0xc7,0x0e,0xec,0x29,0x5f,0x21,0xf8,0x3f,0x0a,},"\x21\x57\x66\x15\xc9\x34\x6a\x63\xdc\xcf\x0c\x50\xec\xbd\x7c\x6d\x72\xad\x45\x2c\xfe\xd4\x3e\xa7\x32\x02\xcc\x7a\x98\x57\x60\x56\xb9\x66\x4b\x54\x62\x29\x05\xa1\xe7\x22\x17\x20\x73\x0a\xc6\x85\xd3\xbd\x39\x77\xec\x39\x59\xd4\x46\xbf\xa9\x41\xe7\x25\xb6\xfe\x16\xaf\xe5\x43\x2c\x4b\x4b\xde\xe7\xaa\x0f\xd8\x03\x09\x48\xed\x6f\xcb\xa7\xc0\xbd\xb4\x0c\x2e\x51\x7d\xa9\x74\x56\xe7\x4e\x1f\x93\xd5\xed\x67\x6d\xe0\xf4\xa8\xb0\xae\xa4\x49\x40\x4b\xd1\x5b\x6d\xa7\x9d\xc1\xb8\x13\x96\x5f\xe5\x57\x24\x10\xd7\x6f\x5b\x5e\xac\x66\x30\x50\x57\x03\x11\xdc\x98\x42\xb6\xfb\xf8\x80\x6a\xec\x03\x15\x17\x15\xca\xcf\x7f\x21\x80\x2e\x8b\xf5\xe9\x8a\x89\xc0\xd7\xd0\xd0\x98\xb7\x3c\x6e\xfc\x09\x96\x2e\x36\xb4\xe0\x30\xc1\xa6\x4b\x5d\x34\x9f\x5f\x20\x42\xc7\x44\x28\x67\x1e\x4a\x2c\x7f\xea\x0c\xae\xe2\x42\x2d\x85\xc4\xfc\xdd\xfe\xd3\x22\x13\x85\x9a\x69\x95\x5d\x4e\x3e\xbb\x7e\x1b\x20\x22"}, -{{0xe8,0xee,0x06,0x5f,0x99,0x07,0xf1,0xef,0xa2,0xda,0xec,0xb2,0x3a,0x04,0x25,0xf3,0x53,0x09,0x4d,0xa0,0x2b,0xc2,0xc9,0x31,0xf0,0xa5,0x87,0xef,0xc0,0xd1,0x3d,0xe1,},{0xc7,0x26,0x51,0xb7,0xfb,0x7a,0xc0,0x33,0x7a,0x17,0x29,0x77,0x49,0x6f,0xd7,0xf2,0xa7,0x2a,0xea,0x88,0x93,0x85,0x83,0x5e,0x56,0x3c,0x6b,0x60,0x53,0xa3,0x2d,0xc1,},{0xa5,0x10,0xdf,0xf4,0x2d,0x45,0x59,0xa1,0x9a,0x7b,0xf0,0xfe,0x0b,0xea,0x53,0xd3,0xe1,0xf2,0x2d,0xfa,0x6b,0xe5,0x50,0x39,0x89,0x5e,0x12,0xa5,0xd0,0x7d,0xa5,0xf2,0xe3,0x77,0x13,0xcc,0xb2,0xeb,0x21,0x60,0x11,0x62,0x8f,0x69,0x83,0xf8,0x71,0xfe,0xe2,0x86,0xe6,0x6f,0xff,0x4b,0xe7,0x58,0x2c,0x96,0x1a,0x1e,0xd7,0x56,0x84,0x04,},"\xa2\xf0\xc1\x37\x34\x73\xa3\x05\xd8\xf1\xd9\x91\x38\xb0\x6b\x9a\x96\x94\xff\xaa\x8a\x88\x22\x2d\xe9\xf7\x29\xbe\xe1\x30\x51\x75\xdf\xb1\x70\x01\xcc\x77\xf6\x7b\x6d\x40\xc9\x0c\x1a\x28\xfb\x22\x6c\x11\x28\x6d\xb4\xa1\x3e\x45\xe6\x92\x11\x24\x2b\xcd\xd0\x1c\xb6\xe2\xc4\x54\xe7\x6c\x0c\xab\x88\x1b\x4d\x2d\x9d\x3a\xb1\x00\xa5\xd6\x1d\x17\x25\xd8\x66\xe4\xfd\xb6\x6d\x93\xd7\x7f\x5b\x30\x86\x93\xb9\xb5\xa3\x33\xe5\x7f\xa2\x5d\x1e\x5d\x2e\x38\xdf\x6e\x4e\x9e\xc8\x41\x59\xbb\xee\x1f\xfe\xa9\x26\x83\x6a\x01\x01\xc9\x14\x83\xbd\x5b\xc8\x8a\x6f\x1c\xc4\xd4\xe7\xf0\x08\xad\x08\x45\x3a\x01\x23\x42\x9d\xd3\x35\x78\x1c\x7c\xbf\x8d\x68\x5a\x89\x99\xed\x11\x77\x60\x70\x04\xa1\x3c\x4c\xb5\xea\x49\x08\xc5\x42\x60\x7d\x3f\x2c\xd6\x69\x0c\xf1\xf2\xa7\x45\x5b\xbd\x38\xf5\x38\xf0\x7a\x10\x39\x64\x31\x7e\xfb\xce\xe3\x7e\xb4\x69\x31\xc0\x27\xcf\x15\x3e\xf8\x6e\x43\xd7\x82\x81\xeb\xd7\x10"}, -{{0xc7,0x2e,0x67,0xd8,0xc3,0xfe,0xc0,0x04,0xff,0x61,0x87,0x18,0xa9,0x09,0x9e,0xb8,0xad,0x7b,0x06,0xff,0x3b,0x8c,0x54,0x2a,0x7e,0x8b,0x98,0x47,0x31,0x34,0x75,0xe1,},{0x4e,0xb0,0x02,0xd3,0xcc,0xeb,0x18,0x8c,0x66,0x58,0xfe,0xc5,0x1c,0xb4,0x79,0xa6,0x52,0x64,0xac,0x55,0x5c,0x75,0xcd,0xc2,0x24,0x9c,0xf1,0xce,0x3d,0xef,0xc1,0x6d,},{0x2d,0x7b,0xab,0x8e,0xbd,0xa7,0xfc,0xa5,0xbb,0x3c,0x25,0xf5,0x1d,0xc5,0x1b,0x73,0xe6,0xff,0x6a,0x3b,0xb1,0xb5,0x2a,0xcc,0x78,0x11,0xa7,0xd2,0x59,0x5c,0xd6,0xfd,0xaf,0x73,0x04,0x94,0x41,0x8e,0x2f,0x57,0xef,0xdc,0x56,0x17,0xb0,0x66,0xfd,0x7b,0x62,0x07,0x68,0x0d,0x94,0xfb,0x8c,0x43,0xd3,0xd4,0x74,0x0b,0x41,0xcb,0x69,0x01,},"\xa8\xf3\x41\x35\xc0\x13\x2e\xc9\x5b\x64\xb0\xcb\xf5\x1d\x66\x90\x01\x43\x37\x04\x06\x79\x1f\xbb\x55\xf2\xb8\xca\x95\x3c\xc7\x4a\x46\xe0\x8b\x00\x2f\xa2\xda\x21\xb9\x51\xb8\x87\x1f\x7a\x29\xbc\x6d\x38\x79\x0a\xfc\x66\xa3\x29\xc3\x97\xd9\xf9\x25\x0b\xae\x0e\x30\xae\x34\x26\xe0\x8d\x8e\xad\x01\x79\xa3\xb3\x13\xc9\x08\x83\x91\x92\xf2\x89\xa3\xf3\xb6\xe9\x60\xb4\xc5\xce\xbe\xf0\xa0\x9d\xaa\x9c\x7a\x15\xc1\x9d\x4e\xbc\x6f\xc2\xac\x3c\xd0\x22\x32\xe8\x32\xb2\x34\xed\xd7\x96\x5d\x68\x7b\xfe\xb7\x58\xf7\x0f\xa7\x96\x38\x41\xb7\x85\x9b\xb9\x7c\x97\x1b\xd5\x57\xbc\x87\x69\x52\x4a\xc4\xc6\xee\xb3\x57\x97\x93\x33\x4b\x52\x2d\x17\x6b\xc6\x2f\x86\xb4\xd5\xc0\xd4\x01\x70\x36\xd2\xb6\xbd\x4e\x43\x84\x41\x6e\xf8\x26\x31\x39\x69\x1a\x86\x06\x17\x0d\x73\xc9\x3d\x64\x17\xdc\xc1\xa0\x8a\x53\x7c\x9e\xd4\x40\x04\x71\xa4\x6f\x52\x90\x7b\x46\xb1\x0a\x8b\x68\x89\xdb\xb4\x64\x7a\x8b\xbc\x71\x49"}, -{{0x69,0x64,0x50,0xb5,0x57,0xec,0x3c,0x94,0xcf,0x1a,0xf1,0x32,0x64,0x75,0x63,0x4a,0xa8,0x1d,0xef,0x38,0x14,0xff,0x30,0xa0,0x2b,0xa7,0xf2,0x04,0x4b,0x59,0xc0,0xfe,},{0x85,0x84,0x77,0x3c,0x56,0x6b,0x0e,0xed,0x3f,0x43,0x28,0x17,0x05,0xb5,0x75,0xa4,0x34,0xe4,0x7d,0x6c,0xf6,0xb2,0x51,0xb8,0x98,0x03,0xfe,0xf5,0x35,0x34,0xcb,0x29,},{0xce,0x8b,0x0a,0x57,0x79,0xf4,0xf5,0xf4,0x01,0xe8,0x4d,0x65,0x92,0x7a,0x0c,0x28,0xdf,0x82,0x9e,0x95,0xd0,0x9b,0xfa,0x97,0x11,0x1b,0x87,0x00,0x07,0x8f,0xf8,0x94,0xcf,0x72,0x77,0xe3,0x4a,0x71,0x61,0x44,0xd5,0x53,0x06,0xfc,0x9e,0x2f,0x64,0xcd,0x28,0x75,0x83,0xcc,0x80,0x03,0xbe,0x0e,0x8f,0xaf,0x26,0xaf,0x76,0x40,0x14,0x0e,},"\xcc\x25\x78\x29\xf3\x0a\x5f\x90\xdf\xdb\xc2\x47\xd4\x2e\x38\x87\x38\xb7\x6c\x41\xef\x8a\x82\xa5\xe0\x22\x5d\xdf\x1e\x38\x6d\x77\x08\x0b\x3b\x9d\xf8\x6c\x54\xb8\x5c\xdf\x2c\x32\xf3\x67\xab\xa0\xc3\xb6\xbf\x88\x8a\x5a\x69\x03\x52\x9b\x6a\xeb\x4d\x54\x07\xa1\x01\x80\x14\x91\x14\x13\x02\x28\xfc\x43\x56\xcc\xf3\x66\xb7\x7b\xe8\x97\x96\xa9\xe7\x1a\x0c\x69\x3f\x31\xe5\x84\xa4\xf1\x43\x09\x7b\xa3\x70\x36\x3b\x67\xb2\xf2\xe2\xfd\x8d\x6f\xe8\xb4\xe8\xdb\xf0\xd7\xdc\xc1\xa8\x36\x00\x41\x15\x8a\xa2\xaf\xf7\xe2\xa3\x25\xb8\xe5\x18\xf1\x93\xa2\x8b\xae\x05\xe3\xd5\x2b\x26\x62\x1a\xf4\x02\x02\x6d\x7f\x25\x0e\x86\xdc\xee\x30\x1a\x58\xb6\x31\xea\xdf\x45\x27\xe9\x58\xf0\x2a\x61\x58\x7f\x0b\xb5\x16\xce\xfa\xc0\x09\xfe\x51\x05\x2f\xff\x53\x33\x6d\xbd\x94\xe7\x26\x6d\x3b\x43\xca\xba\x8a\x1b\x38\xe5\xd8\x71\xc2\xa2\x4a\x4c\x41\x2f\xff\x3f\x7a\x9a\x52\xa8\xab\x23\xba\xc9\x79\x1b\x2b\x5a\x66\x9a"}, -{{0xa8,0xdd,0x35,0xf0,0x54,0xfb,0x6f,0xf6,0xf0,0xab,0x09,0x4a,0x0d,0x3d,0x1c,0x26,0x28,0x32,0x18,0x1d,0xf3,0x5c,0xcd,0x51,0x92,0x54,0x5e,0xbd,0x6a,0x9c,0xf5,0x29,},{0xca,0x41,0x23,0x38,0xd3,0x81,0x4b,0x88,0x6d,0x96,0x4b,0x71,0x92,0x5e,0x1a,0xab,0xb3,0xff,0xd0,0x78,0x34,0xdb,0xe7,0xdc,0x51,0x25,0x68,0x88,0x2b,0x53,0xe4,0xa3,},{0xfa,0x70,0x9f,0xbc,0x83,0x82,0xaf,0x83,0xd1,0x18,0x12,0x61,0x8d,0xfa,0xca,0x45,0x2e,0xab,0x83,0xe4,0xc5,0x3f,0xe9,0xe5,0x85,0x84,0x67,0xd0,0x7b,0x67,0x67,0xe1,0x79,0x75,0xc1,0xe0,0x63,0x93,0xd6,0xdd,0xe1,0x5a,0x34,0xd9,0x47,0x3d,0x1c,0xf4,0xd6,0xd8,0xc2,0xd5,0x73,0x94,0x52,0x00,0x80,0xfa,0xc4,0xe4,0x34,0x48,0xbe,0x07,},"\x55\xa7\xad\x91\x32\xd6\x3a\xc1\x61\xe7\xad\xb1\x32\xb9\x18\x9f\xdd\x84\xc3\x61\xc1\xe4\xf5\x41\x9a\x6d\xf7\x3d\xf4\xd7\xae\xb2\x9a\x8d\xc4\xbf\x01\x49\x0d\x4f\x48\x4e\x2d\x12\x07\x75\x17\xf5\xfc\x7a\xd0\xbd\xed\xa2\x0a\x6c\xb0\x22\x79\x42\x29\x0b\x08\xc3\xfe\x33\xab\x9b\x21\x35\xbc\x38\xa6\x57\x9a\x54\xbd\x98\x2f\x7d\x14\x17\xce\x86\x71\x17\xae\xa9\x18\xdb\xd3\xdd\x47\x6e\x7e\xb5\xb5\xd3\xc3\xe4\x8a\x86\x4a\x2f\x94\x2a\x31\x50\x1a\xa2\xb2\x9b\x53\xb8\x05\x13\xc9\x5d\x6a\x41\x18\x44\xf0\xde\xdf\x16\xa2\x9a\xc2\x67\xd3\x31\xe5\x3b\xdc\x25\x39\xbf\xcf\x32\xdc\x9b\x5d\x64\x0f\x12\x31\xe2\xca\xfb\x0a\xe9\x4b\xb5\x18\x94\x26\x86\x33\x64\x26\x2e\xfb\x47\xb5\xb5\xcc\xdb\xbc\x93\x32\x42\x16\xa7\x99\xb6\xf5\x0d\x37\x04\xf1\x5e\xd5\x9a\xf6\xcc\x7d\x91\x0c\xf0\x62\xd1\xbe\x63\x2d\xca\x5d\xf2\x13\xd4\x87\xd8\x56\x4f\x2b\x2b\xd7\xd8\x18\xbb\xa2\x7c\x36\x40\x13\xd9\x2d\x7f\x72\x62\x54\x62"}, -{{0xae,0x1d,0x2c,0x6b,0x17,0x1b,0xe2,0x4c,0x2e,0x41,0x3d,0x36,0x4d,0xcd,0xa9,0x7f,0xa4,0x76,0xaa,0xf9,0x12,0x3d,0x33,0x66,0xb0,0xbe,0x03,0xa1,0x42,0xfe,0x6e,0x7d,},{0xd4,0x37,0xf5,0x75,0x42,0xc6,0x81,0xdd,0x54,0x34,0x87,0x40,0x8e,0xc7,0xa4,0x4b,0xd4,0x2a,0x5f,0xd5,0x45,0xce,0x2f,0x4c,0x82,0x97,0xd6,0x7b,0xb0,0xb3,0xaa,0x7b,},{0x90,0x90,0x08,0xf3,0xfc,0xff,0xf4,0x39,0x88,0xae,0xe1,0x31,0x4b,0x15,0xb1,0x82,0x2c,0xaa,0xa8,0xda,0xb1,0x20,0xbd,0x45,0x2a,0xf4,0x94,0xe0,0x83,0x35,0xb4,0x4a,0x94,0xc3,0x13,0xc4,0xb1,0x45,0xea,0xdd,0x51,0x66,0xea,0xac,0x03,0x4e,0x29,0xb7,0xe6,0xac,0x79,0x41,0xd5,0x96,0x1f,0xc4,0x9d,0x26,0x0e,0x1c,0x48,0x20,0xb0,0x0e,},"\x9e\x6c\x2f\xc7\x6e\x30\xf1\x7c\xd8\xb4\x98\x84\x5d\xa4\x4f\x22\xd5\x5b\xec\x15\x0c\x61\x30\xb4\x11\xc6\x33\x9d\x14\xb3\x99\x69\xab\x10\x33\xbe\x68\x75\x69\xa9\x91\xa0\x6f\x70\xb2\xa8\xa6\x93\x1a\x77\x7b\x0e\x4b\xe6\x72\x3c\xd7\x5e\x5a\xa7\x53\x28\x13\xef\x50\xb3\xd3\x72\x71\x64\x0f\xa2\xfb\x28\x7c\x03\x55\x25\x76\x41\xea\x93\x5c\x85\x1c\x0b\x6a\xc6\x8b\xe7\x2c\x88\xdf\xc5\x85\x6f\xb5\x35\x43\xfb\x37\x7b\x0d\xbf\x64\x80\x8a\xfc\xc4\x27\x4a\xa4\x56\x85\x5a\xd2\x8f\x61\x26\x7a\x41\x9b\xc7\x21\x66\xb9\xca\x73\xcd\x3b\xb7\x9b\xf7\xdd\x25\x9b\xaa\x75\x91\x14\x40\x97\x4b\x68\xe8\xba\x95\xa7\x8c\xbb\xe1\xcb\x6a\xd8\x07\xa3\x3a\x1c\xce\x2f\x40\x6f\xf7\xbc\xbd\x05\x8b\x44\xa3\x11\xb3\x8a\xb4\xd4\xe6\x14\x16\xc4\xa7\x4d\x88\x3d\x6a\x6a\x79\x4a\xbd\x9c\xf1\xc0\x39\x02\x8b\xf1\xb2\x0e\x3d\x49\x90\xaa\xe8\x6f\x32\xbf\x06\xcd\x83\x49\xa7\xa8\x84\xcc\xe0\x16\x5e\x36\xa0\x64\x0e\x98\x7b\x9d\x51"}, -{{0x02,0x65,0xa7,0x94,0x4b,0xac,0xcf,0xeb,0xf4,0x17,0xb8,0x7a,0xe1,0xe6,0xdf,0x2f,0xf2,0xa5,0x44,0xff,0xb5,0x82,0x25,0xa0,0x8e,0x09,0x2b,0xe0,0x3f,0x02,0x60,0x97,},{0x63,0xd3,0x27,0x61,0x5e,0xa0,0x13,0x9b,0xe0,0x74,0x0b,0x61,0x8a,0xff,0x1a,0xcf,0xa8,0x18,0xd4,0xb0,0xc2,0xcf,0xea,0xf0,0xda,0x93,0xcd,0xd5,0x24,0x5f,0xb5,0xa9,},{0xb6,0xc4,0x45,0xb7,0xed,0xdc,0xa5,0x93,0x5c,0x61,0x70,0x8d,0x44,0xea,0x59,0x06,0xbd,0x19,0xcc,0x54,0x22,0x4e,0xae,0x3c,0x8e,0x46,0xce,0x99,0xf5,0xcb,0xbd,0x34,0x1f,0x26,0x62,0x39,0x38,0xf5,0xfe,0x04,0x07,0x0b,0x1b,0x02,0xe7,0x1f,0xbb,0x7c,0x78,0xa9,0x0c,0x0d,0xda,0x66,0xcb,0x14,0x3f,0xab,0x02,0xe6,0xa0,0xba,0xe3,0x06,},"\x87\x4e\xd7\x12\xa2\xc4\x1c\x26\xa2\xd9\x52\x7c\x55\x23\x3f\xde\x0a\x4f\xfb\x86\xaf\x8e\x8a\x1d\xd0\xa8\x20\x50\x2c\x5a\x26\x93\x2b\xf8\x7e\xe0\xde\x72\xa8\x87\x4e\xf2\xee\xbf\x83\x38\x4d\x44\x3f\x7a\x5f\x46\xa1\x23\x3b\x4f\xb5\x14\xa2\x46\x99\x81\x82\x48\x94\xf3\x25\xbf\x86\xaa\x0f\xe1\x21\x71\x53\xd4\x0f\x35\x56\xc4\x3a\x8e\xa9\x26\x94\x44\xe1\x49\xfb\x70\xe9\x41\x5a\xe0\x76\x6c\x56\x5d\x93\xd1\xd6\x36\x8f\x9a\x23\xa0\xad\x76\xf9\xa0\x9d\xbf\x79\x63\x4a\xa9\x71\x78\x67\x77\x34\xd0\x4e\xf1\xa5\xb3\xf8\x7c\xe1\xee\x9f\xc5\xa9\xac\x4e\x7a\x72\xc9\xd7\xd3\x1e\xc8\x9e\x28\xa8\x45\xd2\xe1\x10\x3c\x15\xd6\x41\x0c\xe3\xc7\x23\xb0\xcc\x22\x09\xf6\x98\xaa\x9f\xa2\x88\xbb\xbe\xcf\xd9\xe5\xf8\x9c\xdc\xb0\x9d\x3c\x21\x5f\xeb\x47\xa5\x8b\x71\xea\x70\xe2\xab\xea\xd6\x7f\x1b\x08\xea\x6f\x56\x1f\xb9\x3e\xf0\x52\x32\xee\xda\xbf\xc1\xc7\x70\x2a\xb0\x39\xbc\x46\x5c\xf5\x7e\x20\x7f\x10\x93\xfc\x82\x08"}, -{{0x6b,0xce,0x4d,0xfd,0x53,0xbf,0xa5,0x50,0x6f,0x2f,0x55,0x4d,0x2d,0x99,0x4a,0x0d,0xc4,0x0c,0xaf,0xcd,0xec,0x7e,0x1b,0xe0,0x50,0x00,0x6e,0x5c,0x5a,0x4b,0x38,0xa1,},{0xc8,0x90,0x02,0x37,0x28,0xd8,0x39,0x70,0x70,0x29,0x17,0x71,0xe6,0x5e,0x03,0x4d,0x34,0xd4,0xaa,0xe5,0xe2,0x47,0x65,0x3e,0x4f,0xf4,0xc0,0x74,0x59,0x1d,0xa7,0x02,},{0x99,0xae,0x67,0x82,0xff,0x27,0x64,0x6c,0x27,0xf6,0x1e,0x23,0x63,0x6a,0xe1,0x88,0x15,0x21,0xcf,0xa5,0xed,0x25,0x6f,0x70,0xbc,0xe7,0xce,0x00,0xb6,0x82,0x80,0xce,0x8e,0x0c,0x82,0xaa,0x76,0x5a,0xfb,0x8b,0x5a,0x1f,0xf2,0xfe,0x42,0xc5,0x74,0x41,0xe4,0x58,0xe4,0x43,0xdc,0x8b,0x12,0x34,0x77,0xae,0x33,0xd8,0x84,0x88,0x8c,0x0b,},"\x32\x39\x19\x07\x47\xee\x33\xd4\x0b\xf8\x70\xac\x9a\xd4\x9d\x88\xee\x32\x0f\x63\xc0\x52\x57\xe8\xab\x2c\x60\x30\x65\x97\xce\x76\xd1\xf1\xe7\x92\xab\x6a\x65\xca\xa5\x44\xfb\xec\x20\x89\x2f\xd4\x96\x05\x94\xf3\x1b\x37\x63\xef\x07\xd4\x98\x2e\xae\x4a\x2d\xbf\x33\x77\xdc\xc1\xe3\xf9\x5e\x46\xed\x39\xb7\xf0\x22\x2f\x04\xbb\x5c\x3b\x43\x4c\x8f\x9f\x31\x0d\xe9\xf1\x22\xa2\x9f\x82\x41\xe8\x1e\x20\x65\x49\xae\x62\x8d\x2b\x8a\xd7\x68\x97\x2c\x98\x84\x7c\x11\x88\xad\x04\xc8\x35\x35\x63\x78\xbe\xf7\x9c\xd1\x26\x86\x94\x05\xb1\x29\xfd\xbd\xc3\xbc\x48\x9c\xbd\x13\x99\x50\x5d\xad\xef\x76\x17\xb5\xbe\x5d\xa1\x73\xd3\xe8\x0e\x58\x38\xc9\x9e\x34\x92\x76\x24\x27\x29\xe0\x21\x9b\xd7\x47\x6a\xe5\xc4\xf8\x1a\x12\x87\x8f\xb4\x83\xa6\xc0\xe9\xb0\xdf\x29\x62\xeb\x0b\xf0\x01\x57\x78\x2c\xf7\x68\xa1\xb7\x1c\x01\x01\x69\xee\x85\x22\xde\xf0\x02\x4a\xd7\xe4\x57\x75\xa2\x90\x63\x9c\x53\xaa\xf4\x81\x98\xc4\x2d\xe7\x5c"}, -{{0x17,0x86,0x1a,0x8d,0x41,0x54,0xac,0xd4,0xfa,0x9c,0x8f,0xc9,0x47,0xc1,0x88,0x6c,0x11,0x29,0x0b,0xe2,0x22,0x87,0x2f,0xf4,0xf8,0xcd,0x25,0x93,0x9e,0x4d,0x13,0x61,},{0x43,0x77,0x3f,0x44,0x49,0x06,0x5e,0xae,0xba,0xf8,0x93,0x7b,0xaf,0x75,0x85,0x60,0xb0,0xc4,0xd2,0xde,0x46,0x97,0x78,0x39,0xb3,0xb8,0x73,0xd5,0xd7,0xd5,0xfd,0x8f,},{0xa5,0xee,0x02,0x4c,0xcd,0xbd,0xd4,0xc2,0x1a,0x24,0x70,0x9e,0xc5,0x3d,0xcc,0xb7,0xee,0x17,0x62,0x6d,0xd0,0x0a,0x09,0x3d,0x08,0x84,0xf5,0xb4,0x5c,0x4c,0x9d,0x16,0x91,0x84,0x01,0x51,0xc3,0x3c,0x8a,0xa0,0x7b,0x69,0xb3,0x4e,0x16,0xf6,0x16,0x47,0xeb,0xe7,0x93,0xae,0x4d,0xaa,0x70,0xcf,0xf4,0x8e,0x6a,0xb4,0x2f,0xfd,0xbc,0x00,},"\x18\x4d\xf5\xea\x32\x15\xeb\xe1\x80\x39\x0b\x0f\xf0\x42\xba\x23\x81\x15\x5a\x03\x8d\xc7\x32\xf7\x6a\x01\xc7\xe7\x0f\x82\xd1\xcc\xc9\xde\x9a\x05\x96\xb3\xfe\xe4\x47\x20\x9c\x99\x26\x84\xf6\x43\xdf\x21\xf4\xcf\x9d\x17\x92\x62\x79\x0e\x86\x23\xe4\x24\x72\xdc\x35\x19\x97\xe6\xda\x18\x9c\x07\xe1\xe8\x88\x2c\x07\xf8\x6c\x63\x37\xec\x01\x13\x91\x2c\xf9\x22\x15\xc8\xde\x19\x82\xb8\xfc\x57\xbf\xab\xc5\x5a\x3e\x87\x36\xf7\x36\x10\x42\x9d\x97\xfe\xb5\x1d\x79\x4f\x50\x5d\x0c\x5a\x0b\x3a\xbd\x48\xef\x7f\x55\xa6\x28\xf9\x0b\x85\x67\xa1\xc1\x5e\xa9\xd1\x90\xd7\xbf\x4e\xc2\xbc\x93\x34\xad\xa6\xcb\x92\x80\x8d\xfc\x20\x64\x83\x6f\xcf\xa4\x6b\x96\xfd\x7a\x5d\x6f\x4b\x05\x4d\xab\x09\xb7\x35\x95\xfe\xb8\x9e\xd0\x05\xb9\xec\x9d\x31\x88\x12\x1d\xe6\x96\x96\xd6\x4e\x7c\x7b\xbd\xfc\x1c\x46\x9f\xaf\x14\x8c\x38\xa7\x78\x59\x70\xaf\xe1\xac\xd0\x6a\x92\xc9\x94\x78\xfe\x44\x97\x4e\x3b\xb2\x09\x5e\x44\x67\xe9\xb2\xe9\x96"}, -{{0x0a,0x84,0xba,0xa5,0x4f,0x11,0xcf,0x17,0x09,0x0f,0xec,0x61,0xf3,0xf9,0x40,0x15,0x08,0xa3,0xa0,0x38,0x87,0xac,0xa1,0xa7,0x93,0x93,0x94,0xb1,0xee,0x40,0xa9,0x25,},{0x30,0x9a,0x73,0xc6,0x2d,0x23,0xd7,0x40,0xf2,0xe9,0x3c,0x18,0x58,0x7a,0xc1,0x5e,0x7e,0xc4,0x80,0xd2,0x5a,0xc0,0x79,0x4e,0x10,0xf8,0xcd,0x46,0x1c,0xc2,0xb1,0x30,},{0x4d,0x87,0x0b,0xd5,0x3a,0xf8,0xf1,0x3f,0x21,0x4d,0x99,0x34,0xec,0x90,0x3a,0xc4,0x82,0x84,0x09,0x2c,0xd9,0xb1,0x62,0xa4,0x4c,0xce,0xc8,0x51,0xfa,0x94,0x2d,0xe7,0x15,0xcc,0xda,0x07,0xb7,0x99,0x1d,0x71,0x27,0x23,0xe7,0xa4,0xd5,0xb4,0xf0,0x37,0x4a,0xb8,0x5a,0xc3,0x86,0x7e,0x0b,0x53,0xeb,0xc4,0x6b,0x53,0x0f,0x9f,0xed,0x05,},"\xfe\x70\x01\x7b\x14\x67\x8b\x0d\x3a\xd0\x3e\x18\x3d\x6f\x53\x31\x43\x78\x37\x9a\xb3\xda\x65\xb3\x51\x12\x57\xb3\xd5\x40\x86\xe8\x6f\x20\x31\x13\x90\x21\x39\x1a\xf9\xd7\x20\x85\xff\x7c\x3d\xc8\xc1\xe2\xd9\x1e\x53\x33\x38\x55\x42\x3d\x0f\x78\x5e\x2c\xc5\xf8\xb7\x79\x9f\xcf\x1b\x70\xe6\xbe\xcb\x78\x8e\x53\xe9\x02\x0f\x29\x95\xdd\xb0\xc3\x83\xa1\xf8\x10\x38\xfc\x3d\x54\x3c\xe0\xa3\x8c\x9c\x28\x8a\x9b\xc4\x07\x7f\x42\x77\xdc\xc6\xc5\x64\x22\x63\xfc\xfe\x19\x68\x80\x05\xa6\x03\xf5\x76\x75\xd2\x43\x4f\x3e\xd1\xf4\x6d\x32\xf1\x4e\xae\xb0\x73\xe8\x3e\xe7\x08\x6d\xa2\xfb\x67\x65\x9d\x3f\xb6\x8c\x62\x32\x0b\x77\x27\xb3\xb8\xea\x00\x65\x76\xbc\x2c\x7e\x6b\x5f\x1e\xce\xfa\x8b\x92\xe7\x0c\x92\xc8\x89\x51\xd0\xc1\x2d\x91\xde\x80\x1c\x38\xb7\xca\x5a\x0a\x04\xb4\xc3\x42\x9a\xba\x86\x38\x6e\x96\xe0\x6a\xfd\x20\xd4\xc5\xc2\xfe\x2b\x9b\x42\x73\xeb\x05\x20\x1a\x79\x27\x3a\xbd\xbe\xb3\x7e\xd1\x83\x0d\x22\x6b\x6b\xdb"}, -{{0x38,0x37,0x94,0x23,0xda,0xfd,0xbf,0x25,0xe1,0x9d,0x72,0x31,0xbd,0xdd,0x80,0xb4,0xce,0xfc,0xfe,0x2a,0xed,0x93,0x25,0x84,0xdf,0xa0,0xcc,0x3c,0x9f,0x92,0x32,0xde,},{0x59,0x7e,0x81,0xdc,0xee,0x94,0x48,0xb7,0x7d,0xe6,0x82,0x9e,0x79,0x21,0xc8,0xa3,0x90,0x53,0x5d,0x89,0xa0,0x84,0x94,0x30,0xae,0xd6,0x63,0x64,0xee,0x14,0x0d,0x8b,},{0xd8,0xb5,0x0a,0x88,0xae,0xd6,0xf2,0xa9,0x6d,0x08,0x22,0x13,0xad,0xf8,0xb2,0x51,0x9f,0x6a,0x0b,0xbd,0x30,0xdd,0x3c,0xb0,0xf3,0xfd,0x3c,0xe1,0xc6,0x43,0xfc,0x02,0x99,0x46,0xcd,0x43,0x46,0x2e,0xd2,0x25,0x13,0xf1,0xd6,0x5f,0xca,0x24,0xbd,0xe3,0x81,0x81,0x66,0xba,0xa8,0x6d,0xaa,0x79,0x87,0x92,0xaf,0xaf,0xe0,0xc1,0xa1,0x0a,},"\x36\x12\x5c\xa6\x66\x68\x80\x29\x06\x23\x7e\x63\xa2\xfe\x5a\xe6\x10\xf1\x1a\x7c\xf9\x25\x20\xd1\x9e\x66\x90\xa3\xad\xfa\xfd\x5d\x07\xa7\x84\xbc\x1a\x0e\x18\x52\x73\xd1\x1d\x34\x0d\x5e\xff\x90\x15\x97\xde\xdf\x45\x0c\x46\x99\xd4\x3f\x3f\xb1\x68\xd5\x57\xf6\xc9\xc0\x30\x77\xc3\xcd\xc3\x70\xd3\x48\x32\xcc\xdf\x2a\x8e\x3d\x75\x79\x64\x90\xed\x02\x42\x89\x9d\x25\xdd\xf4\x4b\xfc\x66\xf3\x29\xcf\x4c\x45\x16\x87\x03\xc3\x1b\xc9\x20\x2d\x89\x0f\x39\x69\xff\xd3\xac\x35\xa1\x28\x18\xdc\xa7\x51\xce\xb8\x80\x8f\xe8\x1e\xfa\x26\xa5\xe0\xd2\x00\xc5\xec\x1d\x94\xa5\x09\x7e\xa7\x4b\x64\x98\xfe\x28\x8f\x30\xc4\x8d\x72\x7e\x9d\x3d\x35\xc8\xe1\x2d\x85\x42\x07\x02\x55\x6f\x28\x61\x48\x4f\xfd\x09\xb4\xf1\x22\x65\xcc\x9a\xba\xfe\xb8\x2c\xf5\x90\x02\x88\x95\xa7\xd0\x50\xff\x57\xcc\xf5\xf2\x80\x22\xd0\x16\xab\x40\x94\xb0\x62\xe4\x8b\x66\xfd\x36\xd1\xe1\x96\x26\xe5\x21\x5e\xfa\x40\xfb\x7e\x3b\x70\x62\xf8\x1e\x95\x48\x30\xc9"}, -{{0xf9,0x25,0xd2,0x74,0xaa,0xf1,0xfe,0x1a,0x21,0x65,0x62,0x37,0x38,0x5e,0x97,0xf7,0x78,0x3e,0x78,0x09,0x0c,0x5d,0x42,0x17,0xfe,0xce,0x70,0x57,0xc8,0x0f,0x42,0x6d,},{0x3b,0x0f,0xc3,0x70,0xbe,0x3a,0x4b,0x19,0xa8,0x8a,0xb9,0x98,0xc5,0x95,0x04,0xff,0xb5,0x9a,0x87,0x60,0x63,0x38,0xe6,0x73,0xdf,0x5b,0x3f,0xab,0x4d,0x9b,0xfb,0x8d,},{0x79,0x54,0x9a,0x31,0x7d,0x10,0xa0,0xbe,0x32,0x2a,0x94,0xa1,0x51,0xad,0x11,0xe7,0x7e,0xfc,0x48,0x36,0xcc,0x80,0x06,0xa8,0x50,0x81,0x27,0x3d,0x76,0x02,0xa6,0x38,0x96,0x3a,0x9c,0xaf,0x19,0xc3,0xed,0xf1,0xe2,0x5f,0xad,0x1e,0x9d,0x68,0x70,0x1a,0x71,0xde,0xa7,0x27,0xda,0x6a,0x5c,0x5b,0xca,0xc9,0x33,0x95,0x89,0x22,0x4b,0x05,},"\x14\x3c\xaa\xfa\x5f\x62\xb1\x3e\x43\xdf\xfa\x49\xd4\x20\xfa\x99\xf7\x71\xb1\x92\x6d\x40\xd6\xcb\x2b\xbb\x42\x7f\x27\xb6\xc2\x66\xeb\x3d\xeb\x2d\x8b\xbb\xd4\x7b\x82\x14\xad\x40\x25\x1c\xb1\x90\x7a\xd6\x5e\xb9\x41\x93\xe5\x4a\xd8\x5c\x67\x00\xb4\x18\x9e\x80\xf1\xcc\x01\x54\xc6\x3e\xd1\x51\xa8\xbb\xbd\x30\xe0\x16\x37\xca\x58\xe7\x0a\xa3\xee\x52\xef\x75\xd0\x87\x30\x78\xa4\x05\x01\x4f\x78\x6e\xb2\xd7\x7b\x7f\x44\x22\xf9\x27\x82\x3e\x47\x5e\x05\xb2\x42\x45\xf9\x06\x8a\x67\xf1\x4f\x4f\x3c\xfb\x1e\xb3\x0b\xfe\xde\x7b\x32\x62\x23\x0c\xed\x9e\x31\x36\x1d\xb1\x96\x36\xb2\xc1\x2f\xdf\x1b\x9c\x14\x51\x0a\xcd\x5b\xc1\x8c\x0d\xdf\x76\x35\xe0\x03\x50\x3e\x6f\x71\xe1\xc3\x65\xcd\xfb\x4c\x65\xee\x75\xb4\xde\x06\x94\xaf\x87\x07\x63\x74\xd6\x31\xe6\xc4\xb8\xe2\x40\xfa\x51\xda\xb5\xe1\xf8\x0c\xa2\xa0\x6c\x49\xf4\x2e\xa0\x9e\x04\x75\xde\xfb\x18\x4d\x9c\xde\x9f\x58\xf9\x59\xe6\x40\x92\xaa\xc8\xf2\x02\x7e\x46\x81\x26\xf2\xfb"}, -{{0x97,0x1f,0x80,0x6b,0xe6,0xf0,0x7d,0x41,0xbe,0x88,0x30,0xff,0x8d,0xae,0x70,0x4b,0x08,0x63,0x8a,0xd6,0xcf,0xf7,0x22,0xd8,0x43,0x25,0x38,0x12,0x7b,0x76,0x96,0x25,},{0xaf,0x6a,0xc9,0x8d,0xce,0x20,0x78,0xa6,0xc7,0x3f,0x60,0x97,0xba,0xb6,0x3f,0x20,0x5c,0xaf,0x69,0x53,0xaf,0xa2,0x84,0xd0,0x42,0xbd,0x50,0xa4,0xfc,0xe9,0x6c,0xb4,},{0x20,0x37,0xa0,0xa7,0x67,0x4b,0x84,0xff,0x27,0xd0,0xb2,0x2f,0x62,0xb4,0xba,0xc6,0x5e,0x2d,0xc0,0xf5,0xfd,0xc8,0x99,0xfe,0xb7,0x80,0x0f,0x25,0xc2,0x99,0x81,0xde,0xe6,0x41,0xc5,0xa5,0x0f,0x8b,0x94,0x10,0x97,0x0b,0x49,0xd2,0xd5,0x36,0x58,0xc8,0x9e,0xe1,0x69,0x61,0xdc,0xcf,0x53,0x91,0xa6,0x91,0x8f,0x2a,0x84,0xea,0xda,0x0b,},"\x01\x34\x55\xd0\x49\xaa\x54\xed\x99\x5f\xbd\x94\xe6\x36\x99\x55\x49\x53\x95\xe4\x43\x88\x22\x25\x9b\x10\x60\xe9\xa3\x47\x79\x04\x2a\x1a\x69\x21\x1f\x6e\xa2\x07\x73\x99\xdd\x23\x48\x06\xba\x0b\x35\x3c\xd7\x9a\x57\xe1\xc4\x9b\x25\x0a\xb2\x71\x06\xdc\xde\x57\x6e\xcf\xa1\x15\xea\xe4\x61\xfe\xbb\x12\xd2\xda\x25\xff\xcf\x17\xb7\x15\xf8\xd9\x5c\x2f\x0c\x42\x5d\x5a\x81\xf7\x00\x11\x5b\x70\xd4\x9e\x1c\xfe\x49\xfc\xaa\x14\xfa\x20\x5e\x28\xec\x85\x24\x7f\x1a\x6e\x71\x28\xbf\x3b\xb3\x06\x0d\xc0\x84\x64\xbd\xa6\x53\x85\x40\xd0\xac\x47\x20\x93\xe5\xa0\x72\x0f\xde\x2f\x3d\xc4\x78\x8e\x0e\x9b\x0d\xbf\xe2\xa2\xb5\xf1\xa0\xf3\xf8\x0d\xe9\x84\x02\x5b\x15\xc6\x5a\xf7\x7f\x67\x1e\x1c\x5e\x28\x40\x44\x4d\xe5\xc7\xed\xa0\x25\xe6\xdc\x1a\x3f\xf1\x6e\x26\xcc\x54\xcd\xee\xd5\x6b\xe7\x3f\x9b\x01\xab\x2b\x1b\xc1\x6c\x8e\xf5\x8a\x5b\x76\xdd\x47\x28\x78\x07\xe5\xc5\x0f\x0d\x7c\x0a\x5b\x81\x20\xdf\xde\x64\x5a\x01\x2c\x5c\xf1\x14\x91\xbc"}, -{{0x2b,0xb0,0x65,0x2f,0x8f,0xff,0x69,0x01,0x99,0x11,0x48,0xc6,0x8a,0x32,0x67,0x87,0x72,0x71,0x00,0x6a,0xe9,0x58,0x91,0x49,0xbb,0x20,0x68,0x50,0xcd,0xf5,0x2f,0xb0,},{0xc0,0x3b,0x77,0xbe,0x98,0x3e,0x74,0xa2,0x34,0xc1,0x98,0x64,0x96,0xb2,0x92,0xe1,0x39,0x99,0x2e,0xb7,0x52,0x9e,0x70,0xb3,0xaf,0xad,0x7a,0xe4,0xfd,0xcf,0x8a,0x66,},{0x4e,0x15,0x8d,0xea,0xae,0xc3,0xd8,0x89,0x41,0x29,0x6a,0xf2,0xd2,0x73,0x41,0x01,0x2b,0x02,0x41,0xd4,0xe0,0xf4,0x6e,0x43,0x5e,0x37,0x5c,0x98,0x75,0xe8,0x9f,0x5e,0x32,0xc0,0x57,0xb5,0x27,0xbc,0x34,0x11,0xaf,0x09,0x6a,0x77,0xbf,0xce,0xb4,0x5b,0x98,0x3e,0xfe,0x45,0x5e,0x3f,0x03,0x15,0x5d,0x6b,0xc7,0xb0,0xac,0xc8,0xe6,0x0c,},"\xb9\x23\xca\x67\xe3\x96\xd8\x65\x6f\xa3\xdb\xce\x82\x89\xa3\x8b\xd3\xc1\x28\xce\xfb\x30\xef\xc1\x86\x2b\xb9\x44\xb4\x50\x78\x05\x41\x98\x24\xce\x2b\x83\xd6\x90\xef\x4c\xf1\x07\x49\x28\x17\x14\x3b\xf6\x4c\x02\x49\x89\xaf\x1a\x7d\x2e\x1f\x5a\xc9\x78\x74\xf8\x6b\xb0\xd3\x77\x3f\xf8\x40\xf5\x14\xd9\xa1\x39\x4a\x39\x59\xb0\x11\xd3\xa6\xb8\x16\xa3\xfa\xe5\xde\x17\xb2\xa9\xff\x34\x98\x63\xd2\x7f\xbb\xb5\x0c\xca\x73\x41\x08\x75\x10\x00\xd6\x35\x8c\xa0\x64\x7a\x93\xeb\x49\xe2\xe7\xaf\x06\x28\x7d\x48\xf2\xc0\x9d\x5c\x1c\x73\xe4\xd8\xf7\x7e\xa2\xbc\xaa\x73\x56\x79\x5b\x26\x72\x87\x19\xbe\xd5\xff\xdb\x82\x15\x78\xbd\x5d\x66\xbf\x92\xed\xaf\x8b\x23\x8b\x2b\xbd\x7d\x1e\x2c\x30\xa7\x87\xf9\x01\xa3\x3d\x0a\x76\x66\x9a\x9c\x3c\x7f\x2b\x55\x2c\xcb\x83\x49\xc7\xde\xd5\xe1\xa4\x61\x70\xcf\x28\xe3\x59\xe2\xfd\xd5\x4b\x05\xa5\x62\xf5\x28\xc6\x8a\x56\x97\x4d\xf8\x2d\x46\x66\x37\xc8\xe5\x32\x46\xa7\x21\x7e\x43\x86\x80\x1e\x0e\x32\x66"}, -{{0xdb,0x9b,0x81,0x2c,0xb3,0xc7,0xc0,0x3b,0x97,0x7f,0x48,0x7d,0x3d,0x65,0xcc,0xd9,0xcd,0x2f,0x3d,0xee,0x11,0x60,0x20,0x67,0xdb,0xfb,0x72,0xb5,0x89,0xff,0x3f,0x79,},{0xff,0xa0,0x38,0xad,0x8c,0x3b,0x37,0x8c,0xe7,0x5d,0x65,0x84,0x4d,0x08,0xe3,0xd6,0xa9,0x2d,0x19,0x4a,0x1b,0x78,0x62,0xe9,0xd9,0x72,0x0d,0x20,0x67,0x9b,0x29,0x44,},{0xa6,0x28,0xa7,0x74,0x21,0xb2,0xab,0xab,0x57,0x6e,0xed,0x35,0xd2,0xee,0x3d,0x14,0x56,0x1b,0x21,0xfa,0x14,0xa6,0xe2,0xfa,0xc2,0x63,0xc3,0xea,0xdd,0x79,0xf2,0xfc,0x06,0x69,0xf9,0x42,0x9b,0x91,0x0b,0x84,0x22,0xb4,0xb2,0x9a,0xc0,0x26,0xa4,0x2e,0x98,0xd1,0x81,0xbe,0x35,0x07,0xc5,0xed,0x7c,0x74,0x8a,0x1f,0xdc,0xf1,0xd8,0x07,},"\xa7\x00\x92\xc7\x69\x7c\xd4\xa2\x09\x56\x7c\x38\xba\x7f\xb7\x1a\xa8\xf1\x5e\x58\x27\xa2\x08\x76\x92\x39\x43\xfd\x6a\xdc\x65\x9c\x98\x67\xac\x6f\x58\xa6\x1d\xc7\xce\xc3\xd3\x62\x41\x16\x82\x00\x0c\x1a\x9a\xd1\x29\x5e\xb8\xb7\x0f\x24\x2d\x86\xb5\x86\x5e\xb7\x6b\x87\xe3\xf2\xc6\x94\x1d\x26\x12\xee\x3b\xcd\xe8\xf1\x97\x65\x56\x67\x33\x15\x2e\xf5\x4e\x95\x69\x09\x43\x28\x5f\x78\xb3\x75\xf4\x03\x65\x85\xd4\x73\x9d\xee\xde\xef\x6d\x94\x6d\xb6\x1c\xa4\x58\xef\x4f\x65\x0d\xa9\x63\xc3\x85\xe2\x9d\xfd\xee\x41\x5f\xe4\x95\x84\x5f\x55\x19\x7a\x87\x0f\x8c\xde\xb5\xa0\x10\xba\x6b\xbb\x32\xbf\x1a\x58\x8c\xc7\x74\xd4\x89\x01\x84\xc4\xb2\x92\x4a\x5b\x80\x73\x31\x3b\xce\x22\x65\x85\xf1\xad\xfc\x22\x9c\x90\xbc\x6c\xc9\xd2\x12\xe6\x2f\x05\xd3\x3b\xed\xac\x96\x1d\x77\xcf\x8c\x26\x20\xe4\x51\xde\x81\x7f\x8c\x1b\xb1\x6a\x2c\x59\xff\x80\x4b\x63\x5a\x73\xa8\xcf\x8c\x18\x1b\x3f\x94\x01\xc3\xb6\x43\xd1\x8a\x2f\x70\x6e\xa9\xca\xe4\x70\x71\xa6"}, -{{0xce,0x37,0x9b,0xbe,0x2f,0xa8,0xab,0xcb,0xa5,0x1c,0x7a,0x75,0x43,0xde,0x5b,0x71,0x80,0x77,0x1b,0x3c,0x44,0xbc,0x6b,0x41,0x89,0x2e,0x7b,0x88,0x97,0x9b,0xab,0x90,},{0x7f,0x3c,0xff,0x89,0xf4,0x1b,0xab,0xf4,0xfa,0x64,0xcb,0xa3,0x3a,0x5b,0xb1,0x7f,0x41,0x3b,0xbf,0x2a,0x1e,0x11,0x2b,0x50,0xa8,0xe9,0xb1,0xf8,0x21,0xd8,0x49,0xbf,},{0xda,0x98,0xdf,0xb1,0x89,0x38,0x5b,0x2c,0x85,0x3b,0x6c,0xf3,0x75,0x73,0x80,0x46,0xa8,0xf2,0x7e,0xf2,0x79,0x74,0xab,0xce,0xce,0xa1,0xdb,0x02,0x98,0x9b,0x95,0x1f,0xe4,0x33,0xa6,0xce,0x1e,0x22,0x5b,0x3f,0xa8,0x20,0x32,0xfe,0x06,0x0a,0x7d,0x3f,0x6c,0x18,0x3f,0xd1,0x15,0x7f,0x79,0x1a,0x06,0x4b,0x40,0x76,0x50,0x57,0x16,0x00,},"\x00\x1a\x74\xf0\x95\xc8\x14\xd3\xbe\xed\x67\xa8\xd1\x5f\xc1\x8e\xfe\x23\x5d\xc3\xf6\x45\x78\x12\xa4\x03\x9b\x7a\x46\xfe\x9a\x0e\x9d\xe8\x1a\x7a\x4e\x5f\xba\xb5\xeb\xe9\xe1\xe4\x80\x1b\xd1\x1b\x45\xc9\xf7\xad\x06\x36\xa0\x9b\xff\x42\x16\x4b\xe5\x74\x9a\x04\xc0\x2f\x0a\xb6\x1f\x0e\xcf\xdf\xef\x79\x9b\x82\x7d\xa6\xa2\x74\xc8\xd3\xb3\x9f\x2e\x38\x05\xa6\x79\x12\x87\xee\xdb\x23\x14\xd3\xf8\x42\xb5\x58\xb9\xb4\x89\xaf\xe1\xed\x37\xbb\xbc\xfc\x5e\x60\xa4\x31\xd5\xac\x60\xb3\x9e\x94\x6d\x90\x3d\x6b\xf6\xb1\x40\xe1\x2c\x7e\x07\xf9\xed\x7a\xc4\x6a\x39\x99\xc6\x24\x5c\x8a\xb1\xbd\xb2\x18\x79\xa3\x17\xa3\xdc\xd2\x57\xa5\xc4\xf3\x49\xb7\xf5\x9e\x4e\x43\xd6\x2d\x9f\x1c\xd1\x6f\x51\x8f\x1c\xa6\xca\xd3\x7e\x2c\xb2\x0f\x25\x98\xc4\x13\x42\x91\xc6\xb8\xa9\x8a\xae\x52\x47\xe2\x6e\xef\xb7\x6a\xa3\x8c\x9c\x82\x31\xc1\x7e\x9d\xbf\x27\x1c\xec\x80\xfb\xa5\xb4\xa8\x34\xbd\x9b\xe8\x1e\xa8\x41\x63\x7a\xa9\xcd\xd4\xc4\xbf\x26\xd7\xad\x24\xca\x3c"}, -{{0x2b,0x2e,0xe8,0x09,0xd6,0x47,0x02,0x3e,0x7b,0x77,0xfc,0x54,0x1f,0x44,0x87,0x5a,0x35,0xfa,0x94,0x1d,0x37,0xf7,0xc5,0xb2,0x1f,0xd3,0x49,0x34,0xd2,0x39,0x19,0x35,},{0x2c,0x29,0xd5,0x3e,0x1b,0xf2,0xc7,0x87,0x9d,0x73,0xd2,0x0b,0xa8,0x8c,0xa0,0x7a,0x0b,0x21,0x6d,0x7f,0x6d,0x05,0xd9,0x36,0x63,0xa6,0x5c,0x3d,0x9e,0x10,0x63,0x3a,},{0x12,0xd9,0x06,0x85,0x77,0x55,0x72,0xc9,0xea,0xbc,0x9b,0xe2,0x57,0x4c,0xa9,0xae,0x66,0xf0,0xe6,0x52,0xe5,0x78,0xb2,0x17,0x36,0xcd,0x6e,0x65,0x4f,0x7c,0x6b,0x15,0x45,0x88,0x3d,0x56,0xbf,0x76,0x0c,0xcf,0xc3,0xcf,0x87,0x54,0x4e,0x00,0x04,0xc7,0x98,0x06,0x12,0x57,0xe1,0x30,0x03,0x0c,0xb9,0x97,0xa7,0x88,0x36,0x9a,0x9a,0x05,},"\xc4\x14\x7d\x64\xeb\xfd\xa4\x1a\x1b\xe5\x97\x72\x62\x95\x81\x04\xe9\x40\xc3\x87\x6b\xcd\x5b\x69\x56\xac\xfd\xec\x32\xc6\x60\x91\x4d\x62\x62\x3c\x21\x06\x63\xcb\x2c\xbe\x62\x49\xd7\xf5\x27\x49\x91\xc6\x0e\x95\x0e\x8e\x28\x09\x04\x99\x53\xc6\x95\x81\xd2\x46\x9f\x4f\xe9\x82\xc7\x43\x4f\xed\xd9\xd4\xe0\x0a\xe0\x88\x96\xd6\x2c\xc1\xfb\x98\x4d\xd2\x33\x15\x0c\xc2\x48\x3e\x15\x9c\xff\x40\x97\xdf\x8c\x03\x6b\xb6\x33\x00\x3a\xbb\xfb\xe1\x8c\x8f\xa7\x9b\x5a\x22\x27\x08\x38\x12\x3f\xc9\xbe\x39\xb8\x89\x2c\x80\x38\x4a\x38\x50\x28\xc1\xa8\x1e\xc5\x8c\x8f\x21\x06\x0e\x78\xaf\xd2\xc0\x4b\xfd\x2d\x30\xca\x39\x77\xc6\xed\xad\x51\x8c\xc1\xe2\x00\x4c\xdc\x14\xbf\x3d\x15\xf5\xf5\x28\xe5\xaf\x27\x7f\xa1\x82\x27\x58\x70\xe5\xc0\x12\xf5\xf8\x2f\xb1\xaf\xd0\x4e\xdd\xe4\x57\x8d\xdd\x21\x60\xa1\xa3\xdb\xc0\x50\xe8\x0b\xdd\x81\x1b\xc8\x8e\xad\x79\xbf\x93\xf0\x10\xcd\x0f\xd4\x43\x3d\x0b\xc3\x48\xda\xcf\xd0\x94\x7c\xce\xda\x62\xbf\xa4\x97\x11\xd0\x13"}, -{{0x4e,0xa1,0x8d,0x6b,0x4a,0xf8,0x05,0x3b,0x88,0x5e,0xc1,0x88,0xbe,0x48,0xde,0xb8,0x6f,0xfb,0x2a,0x69,0xa4,0xce,0xc8,0x66,0x37,0xbb,0xd7,0xb4,0x1b,0x80,0x7c,0x46,},{0xe5,0x98,0x60,0x59,0x97,0x62,0x33,0xed,0x77,0x38,0x2c,0x3d,0x99,0x59,0xf3,0x4e,0x31,0x79,0x62,0x69,0x65,0x53,0xe8,0x6e,0xd1,0xe5,0x90,0x2c,0x4b,0xed,0xd1,0x67,},{0x27,0x57,0x0c,0x00,0x2a,0x48,0x7d,0x00,0x0c,0xa3,0x92,0x8b,0x83,0xcb,0x43,0x19,0x72,0x2c,0x46,0xdf,0xb4,0xcc,0xa2,0x60,0xde,0x79,0x0e,0xc0,0xe3,0xc1,0x93,0x26,0x88,0xf8,0x73,0x62,0x95,0x28,0x18,0xb5,0x4f,0x51,0xbc,0x7a,0xee,0xb2,0x63,0xf9,0x60,0xbc,0x0d,0xa8,0x96,0x4b,0xf3,0x12,0xef,0x93,0xe8,0x1f,0x06,0xc8,0x0b,0x04,},"\xe9\xc8\x9a\x1a\x11\x19\x37\x32\x06\xce\x40\xed\xe3\xb8\x9a\x82\xf8\x94\x62\xa1\xde\xe9\xe7\x89\xe9\x84\x5e\xec\x21\xf5\x71\xc0\xfa\xef\xd4\x30\xad\x33\x8e\x4a\x72\xc0\x47\xa3\x9a\x42\x59\x58\x03\x87\xfb\x9a\xac\xad\xdc\x36\xa2\xb5\x1e\x7b\x60\xa8\x7c\xa1\x32\x1f\xf8\x06\x79\x4c\xd6\xdd\x45\x49\xa4\xdf\x45\xc2\xda\xe3\xe5\x39\xc4\xd7\xd0\x6b\x6e\x6e\x9f\x46\x6f\xfc\xa2\xfa\x49\x78\xce\x3d\xc7\x92\xe4\x4a\x62\x83\x88\x0c\xd1\x38\xa7\x5a\x22\x6f\x98\x5d\xa4\x1f\xfd\xc0\xe3\x2a\x5a\x85\xc8\x5f\xe9\xa4\x3a\xe7\x8f\xcf\xe5\x7f\x4d\xd7\x54\x0a\x6d\xd3\x92\x4a\x49\xab\x39\xeb\x69\x95\x0d\x42\x11\x51\xd9\x6b\x1e\x4f\xd3\x93\x58\x90\xf6\x34\xcd\x52\xa7\x3a\x75\x5f\x5c\x2f\xb7\x2f\x9c\xd5\xa2\xe6\x7e\xa9\x30\x91\x5e\x13\x3b\x47\xcf\x6b\x7c\x10\xa9\xd8\x89\xc6\xaf\x6b\x5f\x1f\x4f\x51\x09\x4d\x27\xfb\xba\x22\x8a\xc2\x26\x8b\x34\x40\x27\xfd\x49\xe4\x26\x34\x3c\xc0\x13\x43\x99\xb4\xb5\x10\xaa\xea\x50\x23\x4d\xf4\x2c\x37\xfa\x1c\x4f\x4d\x0e"}, -{{0xfc,0x1b,0x75,0xd1,0x7d,0x38,0x07,0x21,0x73,0x51,0xd2,0xaa,0x40,0xd9,0xb0,0x4f,0x52,0x5b,0x89,0xed,0x3f,0x5f,0xcd,0xb3,0x11,0xbe,0xc2,0xae,0xc5,0xcb,0x7e,0xce,},{0x55,0xe4,0x84,0xe7,0x74,0xa4,0x39,0x2a,0x9d,0x6e,0xef,0xf8,0x35,0xa8,0xfb,0xb2,0x32,0xcf,0x62,0x76,0xa8,0x9c,0x74,0xfc,0x0d,0x1b,0xb2,0x04,0x5a,0x8b,0x21,0xbe,},{0x9a,0x68,0xd1,0x51,0xfe,0xa3,0x90,0x98,0x93,0x35,0x9e,0x60,0xb9,0x6b,0x68,0xb2,0xa3,0xe2,0x94,0x6f,0x2b,0x47,0xb8,0x75,0x39,0x8a,0x1e,0x39,0xeb,0x01,0x46,0x3d,0x35,0xea,0xe7,0xd9,0x76,0xf8,0x33,0xa7,0x62,0xb5,0x1f,0x27,0x26,0xee,0x0d,0xcc,0xad,0x5c,0xe3,0x60,0x05,0x64,0xfd,0x9d,0xd5,0x8c,0x23,0x80,0x7f,0xdf,0xfd,0x05,},"\xd0\x31\xbd\x11\xda\x30\x80\x97\xe3\xbe\xb6\xff\xdb\x26\x00\xee\x6a\x19\x3c\xa6\xd8\x32\x45\x01\xc9\x72\xb1\xa2\x51\x66\xfa\x7a\x36\x9f\x5b\xc8\x82\xea\x45\x61\x2c\xf0\x25\x80\x25\x4d\x21\xb4\x0b\x03\x63\x23\x7e\x83\x5d\xae\x26\x56\xc1\xb7\xf4\x73\x6e\x88\xbe\x53\xd6\xb1\x19\xc0\x7f\x57\x29\xbb\xd8\x2f\x67\xde\x03\x58\x83\x22\x87\x92\x43\xc5\x99\x0a\x7e\x61\xf5\x69\x07\xb2\x41\x71\xa5\x7c\xbb\x0b\xbe\xfb\xa2\x31\x62\x77\xaf\x93\x26\xf9\xcb\xf3\x53\x8b\xcb\xf6\x78\x0b\xe4\x18\x25\xa2\xca\x77\x4b\x41\xbd\xb1\xcd\x5c\x60\x88\x51\xec\x23\x39\xeb\x2f\x4f\xee\xdd\xaa\x89\x1a\x63\x26\xb2\x9d\x97\xd7\xfb\xf3\x11\xe3\xbb\x74\x9c\x5d\x4c\x05\x8d\xcc\x14\xf4\x52\xf9\x33\x49\x91\xe2\x71\xc1\x6d\x65\x08\xc8\x18\x63\x39\x27\xf4\x29\x80\x4c\xa7\xa3\x81\x70\xf1\xb9\xf6\xbd\x73\xed\x67\x5e\x11\xe8\xc0\xd3\x21\xfa\xc9\x12\x73\x0b\x4b\xa2\xf7\xc4\x28\x53\x4a\xdc\xaa\x4d\xad\x31\x4c\x55\x80\x7e\x6c\x64\x2d\x49\x4c\x6b\x2f\x0e\x8c\xd1\x29\x77\x5c\xc0"}, -{{0x0d,0x0b,0xf4,0xd4,0x2e,0xf8,0x10,0xb1,0x79,0xeb,0x84,0x17,0x71,0xde,0x6d,0xbd,0xe7,0x63,0x61,0xca,0xf8,0x94,0xe4,0x2a,0x14,0xb1,0xe0,0x97,0x87,0xea,0x3e,0x06,},{0x71,0x71,0x51,0x0b,0x43,0xfc,0x17,0xef,0xa8,0x0b,0x15,0xe3,0x20,0xb1,0xb0,0xa4,0x08,0x33,0x25,0x42,0xe0,0xd3,0x6e,0x4a,0xb9,0xa6,0x49,0xcd,0x94,0x1b,0x5a,0xed,},{0x24,0x44,0x6b,0xdf,0x03,0x41,0x6a,0x4d,0x08,0x61,0x44,0x66,0xfb,0x85,0x1d,0xb5,0x0e,0x91,0xa6,0x23,0xca,0xcd,0x1b,0x0b,0x35,0x66,0x0f,0x3c,0xf9,0x33,0x20,0x0e,0x15,0x30,0x87,0x08,0xda,0x34,0x99,0xa5,0xad,0x25,0xf0,0xf0,0x30,0x6b,0x79,0x42,0x76,0x2e,0x20,0xa7,0x65,0xb7,0xca,0x9b,0x90,0x1c,0x75,0x0b,0x3a,0x95,0x32,0x0a,},"\x8e\x21\x79\x97\x5d\x0a\x8e\x5a\x69\xfe\x87\x5a\x3c\xb1\xe7\x9a\xec\x49\xc3\x85\x3e\x30\xdd\x03\x20\xfe\x3e\xbf\xb6\x38\xb8\x2f\x89\xad\x16\x43\x03\x6b\x37\xe5\x6e\x0b\x55\xe0\xa9\xe2\x2a\x4e\x28\x3d\x7a\x27\x48\x5c\xe9\x10\x2d\xb6\x78\x7d\x66\x28\xb7\x79\x13\xe1\x08\x96\x77\x4e\x49\x5c\x26\xe8\xba\xb2\x6e\x7f\x9a\x94\xd2\x9a\xaa\x36\xae\xc9\xc2\x6a\xd3\xf5\x0e\x5d\x8c\x0b\x76\x98\xbb\x5f\x01\xb8\x76\xd0\xd6\x5f\xcf\x5e\x9e\x32\xcd\x7b\x89\x82\x9e\xd0\x5b\x0b\x8f\x63\xa9\x38\x58\x98\x5b\xc9\x56\x9f\xce\x42\x9f\xd3\x7a\x21\x1a\xbe\xd6\x50\xf5\x85\xc3\xb5\x59\x00\x44\x3b\x6c\x5d\x6e\x8a\x48\xba\x67\xde\xee\xd0\x7b\x76\xe9\x69\xfc\x88\x43\x0f\xce\x27\x09\xc0\xbb\x5c\xe9\x26\xab\x7f\x44\xe0\xcd\x79\xf4\xec\x35\x9e\xf7\x67\x48\x88\x3f\xcc\x3d\x02\x6e\xdd\x06\xc8\xb9\xcb\xa5\x4b\x99\x0d\x30\xaa\x41\xf1\x44\x8a\x10\x89\x3f\xb0\x53\x92\x80\xc5\x99\xd4\x23\x61\x43\x3a\x34\xcd\xaf\xd8\xeb\xdd\x92\xef\xb9\xc3\x8a\x36\xda\xf4\xc7\x40\x60\xc6\x96"}, -{{0x57,0xb5,0x19,0x4d,0x26,0xab,0xe4,0xab,0x21,0x16,0xc0,0xf0,0x3d,0x23,0xdb,0xe1,0x16,0xd4,0x88,0x25,0xa2,0x5e,0x77,0xd6,0x46,0x48,0xb4,0x36,0x92,0xae,0x25,0xbf,},{0x49,0x9c,0x02,0xdb,0xad,0x2a,0x4e,0xab,0x3b,0x6f,0xf1,0xab,0xa3,0x94,0x4b,0x91,0xc3,0xf2,0x73,0xa3,0x82,0xc5,0x48,0xa6,0xf3,0xa1,0x9c,0x83,0xf0,0xa8,0x67,0x24,},{0x4c,0x73,0x45,0x96,0x0c,0x8f,0xd4,0x8a,0x7d,0xea,0xd7,0x1d,0xbd,0x61,0x90,0x84,0x68,0xef,0xa8,0x65,0xa1,0x35,0x56,0x8c,0x8f,0x9c,0xa0,0x05,0x54,0x83,0x46,0x86,0x17,0xa7,0xe3,0x35,0x84,0x0f,0x57,0xc6,0xcd,0x8f,0x2c,0x98,0x05,0xcd,0x47,0xa9,0xd7,0xcd,0xfd,0xe5,0x3d,0xa8,0xef,0x4f,0x1a,0xdb,0xb6,0xf6,0x98,0xaa,0xf1,0x00,},"\xb4\x81\x3c\x9d\x13\x21\x5f\xe9\xf6\x3a\x78\xff\x7a\xc9\x51\x73\xeb\x81\x0b\x46\x13\xf0\xf4\x8d\x68\x76\xb2\xbd\x3b\x2c\x72\xbc\x7d\x98\xcb\x1a\xc3\x2b\xc4\x1c\xa4\x7f\x09\x89\x6f\x79\x20\x4e\xcf\xb8\x26\x4c\xe8\xf3\xc3\xe7\x6d\xc1\x24\xda\x8d\xdc\x6e\x0d\xfc\x1e\x13\xb5\xa5\x29\xf2\x0c\x82\x61\x3f\xb9\xa8\x2e\x5f\x5d\x77\x32\x6a\x86\x1f\xae\xda\xbc\x73\x25\xc5\x9a\xf3\x3d\xae\x67\x44\x02\x5e\x64\x97\x74\xfc\x4f\x79\x13\x4b\xf9\xf6\xe3\xd5\x87\x5d\xd9\x1b\xc8\xa1\x4c\xc3\x6a\x66\x28\x3d\x01\xd8\xd1\x08\xc1\x33\x27\xec\xa5\x30\x57\xba\x50\xbf\x21\x0c\x19\xf1\x39\xde\x64\x94\x98\x26\x46\x19\x8a\x12\x46\xc2\x71\xb0\xa3\x68\xc1\x0a\xab\x95\xcd\x89\x61\x23\x5d\x74\x2d\xf4\x54\x5b\xe6\x8b\xd0\x10\xdc\x0d\xb2\x3b\x67\x3e\x62\x36\x09\xe4\x20\xee\x76\xb1\x05\x6c\x52\x0f\x9c\xe8\xfb\xe8\xee\x18\x63\xdf\x97\xd1\x7b\x71\x74\x63\x6c\x3a\x2b\x61\x22\x95\x09\x19\x48\x81\x0d\x1d\x4b\x8a\x58\x43\x76\x0a\x28\x87\xdc\x55\xef\x51\x2a\xf0\x41\xec\x54\xfa\xd3"}, -{{0x06,0x8d,0x27,0xb2,0x1e,0x2a,0xcf,0xcc,0x19,0xc3,0xe9,0x67,0x3d,0xd4,0x41,0x42,0xd9,0x8a,0xac,0xae,0x89,0x49,0x30,0xe2,0x0c,0xa0,0x67,0x43,0x9e,0x74,0x9a,0x79,},{0xe2,0x2d,0xdd,0x39,0x6f,0x95,0x5b,0xb9,0x0e,0x28,0x47,0x76,0xaa,0x76,0xe9,0x21,0xe5,0x06,0x99,0xd0,0xca,0x89,0x14,0xa9,0xb7,0xb8,0x41,0xeb,0x5f,0xf4,0x7d,0x6d,},{0x0c,0x17,0x3c,0x48,0x8a,0xd0,0x01,0xcb,0xb9,0xc4,0x3d,0x7b,0x30,0xa7,0xc0,0x71,0xa2,0xfd,0xb0,0x8c,0xf7,0xf3,0x7d,0xaf,0x71,0xd7,0xae,0x71,0x28,0xdc,0x0d,0x43,0xf0,0xf0,0x95,0xb2,0x92,0x9c,0x54,0xb7,0x73,0xed,0x4a,0x1f,0x0b,0xf0,0xdc,0x4f,0x36,0x4f,0x06,0x01,0xe8,0xd5,0xae,0x06,0x2f,0x5b,0x78,0xc0,0x5b,0xfb,0xc7,0x02,},"\x1c\x68\x15\x42\x3d\x1a\x2c\x5e\xbe\x88\x28\xd1\x64\x65\x27\xc1\x7b\x20\x06\xe5\x47\xf0\x16\xb5\x35\x0f\x01\x0d\x79\xb1\x3d\xf4\xfb\x8c\x6e\xd5\x7b\xa9\xc2\x6c\x3c\xb0\xe0\xa6\x41\x78\xb6\x50\xa3\xea\x54\x44\xa4\xfa\xd5\xb2\x0a\x3e\xb8\xca\xa7\x02\x63\x40\x11\xcf\x78\x92\xa0\x72\x7b\x6e\x81\x50\xb0\x77\x04\x29\xa3\x7a\x8a\x0b\xb3\xa7\xed\xb8\x91\xa7\xc9\x02\x40\xbc\x03\x60\xb1\x4e\x6d\xd7\x70\xa9\x90\xb3\x1b\x31\xf3\x3d\xdb\xf6\x53\x98\x8f\x82\x74\x2e\x5e\xec\x31\xb2\x73\x68\xeb\x0e\x4f\x1e\xcf\x4d\x67\x6f\x49\x21\x4a\x52\x0d\x1e\x5b\x2b\xbb\x59\xac\x2e\x13\x26\x7e\x07\xa0\xcb\xac\xbe\xd9\xf9\x4d\x74\x73\xed\x69\x78\x28\xb0\x92\x8f\xcc\x61\x6e\xe0\x2e\x51\xfc\xd8\xdb\x4d\x8f\x75\x33\xb7\xb1\x39\xa0\x5e\x06\xf9\xe0\xea\xe3\x29\x93\xe3\x02\x5a\xef\x05\x90\xb3\xfb\xb4\x29\x2a\x3a\xc4\x07\x65\xe8\x58\x4e\xad\x00\x26\x6a\xcd\xcb\xdd\xe1\x45\x7a\x03\xb7\xd5\x7b\xd5\xc9\xe6\x4f\xb0\x6b\x64\xa5\x0f\x35\xf0\xa1\xec\x34\xb6\xdd\xbd\xe7\x67\xb9\x6f\xfd"}, -{{0xa3,0x4d,0x52,0x56,0x31,0x59,0xe0,0x72,0x3e,0x9f,0x3f,0xd1,0x33,0xbd,0x96,0xe2,0x0a,0xda,0xe6,0x23,0xf8,0xc7,0x98,0x01,0x3b,0xc3,0x6b,0x44,0x14,0x89,0xbd,0xc2,},{0x1f,0xb6,0x58,0xe6,0x45,0xde,0x6d,0x3e,0xfd,0xb0,0x83,0xa7,0x3f,0xbd,0x59,0x2f,0xcd,0x4b,0x80,0x0e,0x03,0xc7,0xbd,0x68,0x1a,0xea,0xe6,0x57,0x6b,0xfb,0xbe,0x2f,},{0x5f,0xab,0x5a,0x71,0x40,0xd4,0x78,0x73,0x68,0x43,0x05,0xaa,0x63,0x53,0xd3,0x86,0x2f,0x5f,0xc1,0x3e,0x54,0xa4,0x0c,0x95,0x63,0xcc,0xea,0xc8,0xf7,0x40,0x08,0xc6,0xc4,0x45,0x63,0x1f,0xa8,0x64,0xe0,0xf1,0xc3,0x45,0xb5,0x95,0x4f,0x80,0x05,0x6a,0xeb,0xa2,0x56,0x62,0xb7,0x88,0x27,0xb5,0xe8,0xe3,0xa9,0x43,0x78,0x13,0x72,0x0f,},"\x1d\x21\x5f\x85\xc0\x89\xf3\x5f\x30\x7a\x74\x6c\x66\xc7\xc1\xe4\x1d\x6b\xa3\x77\x30\xd7\x59\xe6\xe5\x62\x2d\x6c\x6a\x19\x8e\x40\xf6\x3d\x37\x87\x3b\x71\x5d\xf7\x51\x8b\x3c\x6b\xb5\xe9\x5a\x46\x77\x26\xb9\x7c\x9a\x0f\x8f\x5d\xfc\xdb\xfd\x1e\x0d\xe3\x57\x66\x1d\xde\xab\x55\x50\x42\xb9\x45\xfd\x89\x9f\xad\x6d\x38\x2d\x79\x17\xda\x9e\x12\xdf\xbd\xa0\xd6\x99\x00\xb3\x97\x51\x65\xa7\x3d\x0a\xc9\xde\x01\xfd\x30\x48\xb8\xfe\x5f\x0b\x90\xbe\x67\xe0\x3d\xc2\x2f\x65\x3a\x0a\x13\xeb\x4b\x0b\x75\x3f\x3f\x3b\xbf\x78\x73\x69\xeb\xd8\xbf\x5e\x00\xeb\x78\xbf\x0b\x35\x15\xa9\x1e\x68\xb1\xd5\xfc\x69\x20\xbf\x4f\x42\x59\xf8\xa7\x30\xef\xc7\xf1\x01\x6d\x50\x1e\xf6\xfb\x7c\xb8\x36\x6f\xc8\xe7\x16\xcf\xa5\x0e\xa8\xb2\x03\xcc\xa1\xa3\x16\x70\x7e\x0b\x0f\xc5\x7e\xaf\xce\x82\xd6\x2f\x7f\xf3\xae\x04\xac\x8f\xd0\x41\xb5\x5b\x19\xa3\x52\xa6\x9e\x6d\x4b\x79\xd0\xe6\x50\x17\x51\x68\xe3\x4f\xa3\x35\x8e\xac\x81\x6c\xec\xf2\xc8\xdd\x1b\xf2\xa5\x89\x11\x3e\x91\xbb\x81\x8f\x91\xf8"}, -{{0x58,0xdf,0xe7,0x68,0xbf,0x52,0x11,0x84,0x94,0xb2,0x99,0x75,0x15,0x4c,0xf4,0x52,0xbd,0x97,0x46,0xdc,0x7d,0xe1,0xd6,0xbc,0xd1,0x8e,0xe6,0xa0,0x5a,0xcf,0xd8,0x58,},{0x0f,0x14,0x76,0xc6,0xcc,0x2a,0x1b,0x47,0x64,0xaf,0x75,0x80,0x5e,0x77,0x34,0x1f,0x14,0xa0,0xd8,0xb0,0x9c,0x6a,0x5b,0x2e,0xa2,0x87,0xfd,0x51,0x7c,0x3f,0xa6,0xb9,},{0x97,0x71,0x37,0xa3,0x8a,0xf4,0x4f,0x4b,0x26,0x2a,0xbf,0xf7,0xe0,0x72,0x82,0x43,0x3c,0x58,0x92,0x6d,0x56,0x2f,0xbc,0x61,0x80,0xbd,0xe6,0xcd,0x94,0x97,0x86,0x1f,0xb6,0xd9,0x55,0xcf,0x38,0x3d,0x99,0x9f,0xa1,0x03,0x7b,0x8b,0x17,0x54,0xce,0x88,0x8c,0x9f,0xfc,0x15,0x60,0xa4,0x51,0xd0,0xe9,0xdb,0x8d,0x74,0xd2,0x94,0x06,0x04,},"\x60\x97\x94\x20\x1c\x4f\x6f\xaf\x48\x87\x90\xd6\x1d\xbf\xf3\xf4\x1b\x32\x8c\x5b\x06\x95\xcb\xe9\xaa\x8a\x13\x6d\x72\xb4\x97\x7b\x21\xb5\x00\xf2\x16\xe9\xf3\x21\x68\xad\xa8\xc1\x3b\xff\x25\x32\x76\x47\xe3\x0d\x8a\x24\x4d\x74\xd8\x83\x03\xab\xc9\x0b\x7f\x71\xaa\x07\xca\x04\xd1\x7b\xc8\xa0\x16\x7d\x6e\x63\xfb\x88\xba\xa1\xda\xb8\x1d\x50\xf1\xe9\x1f\x46\xf5\xaf\x77\xf2\xe8\x40\x8b\x82\x63\x36\xa3\x50\x52\xef\xff\xdf\x4a\xf7\x95\x96\xaf\x1b\xb2\x25\x9f\x83\xc1\xbc\x10\x9c\xfd\xc3\xdd\x50\xfd\x96\xd3\x10\xf2\x7e\xa4\xc6\xc7\x69\x0f\x21\x81\x5e\xa9\x2b\xd7\x93\x89\x68\x0c\xfe\x3e\xd4\x0c\x80\x18\x11\x90\x68\x8d\x24\x22\x2d\x9a\x1e\xd5\x2c\xe6\xa1\x6b\x41\xdb\xd9\x10\x7e\xb6\xd2\xe3\x59\x4e\x44\x94\xd7\x5d\xd7\xc0\x89\xe3\xb2\x6f\xfd\x00\xd1\x00\x3c\x92\xc4\xc3\x9a\xe5\x38\x2e\xf9\x29\x14\x91\xa8\x80\xca\x4e\xc3\xac\x2b\x86\xe6\x67\x19\xb9\x2b\x6f\x7c\xea\x2c\xb0\xbb\xb1\xcf\x62\x4d\x0d\x1a\xbe\xae\x55\x6e\x5f\x73\x90\x9d\xd5\x46\x27\x70\x37\xec\x97\x2f\xd4"}, -{{0x5a,0x63,0xef,0x9b,0xd7,0xdb,0xf0,0xe8,0x9f,0xef,0x15,0x59,0x83,0x65,0x9e,0x8a,0x0a,0x6c,0xa0,0x02,0xbc,0x42,0xfa,0xd5,0xa4,0x5a,0xf8,0xe0,0x28,0x19,0x23,0xf4,},{0xe6,0x32,0xf4,0xdc,0x99,0x42,0x31,0xcc,0x17,0x90,0xc2,0x1a,0xfa,0xda,0xa9,0x77,0xa5,0x89,0xb0,0xeb,0x0d,0xa1,0x9f,0xcb,0x27,0x92,0x91,0x1b,0x15,0xec,0xf8,0xaf,},{0x75,0x46,0x1f,0x99,0x65,0x0c,0x03,0x68,0x05,0x81,0x13,0xa1,0x5b,0xa1,0x6b,0xd2,0x33,0x7b,0x2e,0x63,0x3d,0xa3,0x81,0x12,0x87,0x8c,0x48,0x34,0xfa,0xc9,0xba,0x2e,0x30,0x7c,0x86,0x6c,0x02,0xaf,0x79,0xbe,0xa3,0x36,0x59,0x61,0x4c,0xbb,0x44,0x65,0xc5,0x7e,0xc3,0xef,0xfd,0x4c,0x47,0x8a,0xe3,0x8a,0x34,0xa0,0x5c,0xf1,0xed,0x07,},"\x79\x6b\xc8\x36\x1c\x6e\x8e\xec\x39\x83\x8b\x24\xf5\x39\x71\xe8\x20\xf8\x23\x61\xe0\x51\x0e\xb4\xde\xf1\xdb\x25\x12\x38\x7d\x6b\xf3\x5b\xbd\xfa\x31\x88\x79\x20\x94\x35\xd6\x88\x7b\x14\x10\xb3\xeb\xc1\x45\x5f\x91\xf9\x85\xe0\xfa\xb1\xce\x1c\x50\x5c\x45\x55\x76\xbc\xa0\x35\x39\xd0\x48\xad\x3a\x0e\xd1\xf1\x1c\x73\xba\xc6\x80\x9e\x2e\xa1\x47\x97\x5b\xee\x27\xc6\x52\x61\xac\xa1\x17\xdf\x0f\xae\x70\x08\xe2\xc3\xc1\x30\xbe\xc5\x53\x3a\xb8\x93\x51\xc2\x14\x0c\x9d\x1a\x62\xbd\xf6\x88\x62\x97\x87\xf9\x54\xe1\xc6\x10\xcb\xb7\x5e\xdb\x86\x20\x9d\x7c\x35\x7c\xd0\x6e\xf4\x19\x31\xdd\x5d\xfd\x1c\x7d\x40\x7f\xa4\xee\x1e\xf2\x93\x93\xbe\xab\x57\x13\x17\x38\x02\xcc\xe2\xd5\x62\x29\xcf\xa7\x6b\x60\x16\x62\xc4\xd9\xa8\x4a\x49\x36\xc5\x2a\xbb\x19\x81\x37\x8b\x71\x7e\xb5\x5c\xb6\x04\xa6\x8d\x34\xf0\x3b\x21\x9f\x32\x22\x6c\xa0\xe6\x69\x34\x8a\x2d\x8d\x24\x53\x93\x0e\xb6\xe9\xc2\xbf\x66\xfa\x4e\x92\xc7\x51\x36\xe1\x48\xcd\xb0\x34\x13\x0d\x3f\x64\x63\x82\xe1\xc7\x15\x79\xac\x70"}, -{{0x8b,0x2f,0x06,0x14,0x1e,0x40,0x11,0x63,0xf9,0x0f,0x67,0x4b,0x04,0xdc,0x90,0xdc,0xb6,0xdd,0x33,0x86,0x41,0x93,0x39,0x66,0x2e,0xcb,0x0d,0xff,0xad,0xf2,0x50,0x0b,},{0x54,0xda,0x93,0x4a,0x65,0x91,0x19,0x19,0x85,0x53,0xfd,0x45,0x66,0xb6,0x60,0xd8,0xd6,0x10,0xad,0xc3,0x29,0x0c,0xb8,0x48,0x29,0xc8,0x94,0x14,0x8c,0xf3,0xf6,0x7e,},{0xd6,0x8e,0x37,0x50,0xdc,0x56,0x43,0x23,0x97,0x40,0x1c,0x98,0xff,0x15,0x29,0xdb,0x9e,0xd4,0x8f,0xea,0x24,0x6d,0xd4,0xed,0x38,0x3e,0xc7,0x4c,0x1a,0x46,0x3a,0xeb,0x78,0x4c,0x87,0xb1,0xfd,0xa8,0xbb,0xce,0x97,0x0f,0xc9,0x7a,0xa9,0x80,0x7d,0xdb,0xe9,0x5d,0x41,0xfb,0x02,0x2e,0xa6,0x8c,0x1e,0x31,0x16,0x54,0xfa,0x1d,0xa2,0x07,},"\x1d\xeb\x25\xd4\x34\x58\x69\x03\x23\xa7\xd2\x6a\x26\x69\x50\x90\x99\x34\x74\xf4\x67\xc6\xfd\xe5\xdd\xb3\x4d\xa9\x45\xbe\x3c\xea\x2f\x6b\x75\x65\x2a\xe2\x1c\xbc\x4f\xd2\x27\x63\xa1\xb4\x55\x83\xe1\xc3\xe8\x8b\xbb\x5f\xea\x20\x49\xb7\x33\x6c\x91\x15\x99\x88\xc0\x15\x26\x82\x4c\xa3\xbe\xf1\x6b\x36\x2b\x92\x02\xb8\xb9\x75\x41\x85\xbd\x61\xbe\xa8\xf5\x39\xaa\xdf\x4a\x1a\xb1\x35\xfb\xc3\x1d\x2a\x8e\x33\x17\x80\x73\x10\x6c\xbb\xc0\x2d\x4c\xd0\xd3\xc8\xfe\xaa\x8e\xb7\x33\x08\x43\x56\x25\x17\x95\xaf\xbd\x78\xac\x3c\x4f\x8a\x3b\xa1\x9a\xed\x75\x5c\x64\x6f\x35\x56\x9c\x7a\x6c\x67\x5b\x6d\x69\x18\xe8\x34\x96\x9a\xca\x03\xf7\x1a\x2e\x72\xcc\xb1\x70\x03\xbb\x75\xb6\x2e\x85\x2a\xaf\x58\xb3\xba\xea\x89\xbc\xd6\x4a\x32\xeb\x14\xa6\xb9\xe1\x0d\xe4\x89\x71\xe5\x3d\x0e\x9a\xc9\x9a\x78\xf4\x2d\xe0\x38\x2e\xf0\xe8\x0e\xd3\xcf\xa3\x43\xf3\x5e\x4a\x99\x83\xb9\xae\xed\x98\x6d\x3a\x57\xf4\x7e\x5e\x46\xd4\x0e\x9d\x67\x73\x02\x80\x9a\x2d\x37\xe4\xec\x01\x1f\x05\x1b\x4d\x03\x1e\xd6\x00"}, -{{0xdc,0x64,0x9f,0xbb,0x1b,0xee,0x0a,0x44,0x81,0x4d,0x6d,0x9e,0x90,0x80,0xd5,0xd9,0x0c,0x1f,0xc1,0x73,0xab,0x5f,0xef,0xed,0x82,0x6a,0x74,0x72,0x3a,0x77,0x4e,0x0a,},{0x02,0x14,0xc8,0x9f,0x38,0x67,0xad,0x2e,0x88,0x70,0xe5,0x0f,0x8c,0x2a,0x62,0x54,0x98,0x6d,0x9c,0x22,0x0e,0x33,0x38,0x41,0x13,0x00,0xcd,0x9c,0x64,0x04,0xd4,0xb1,},{0x0e,0x0c,0x5e,0x4e,0x18,0x43,0x75,0xda,0x4e,0xf7,0xe2,0xa2,0xe4,0x88,0x80,0x50,0xcd,0x84,0xe2,0xfe,0x21,0xd0,0x8e,0x84,0xa8,0x52,0xdb,0x2b,0xe3,0xfb,0xc3,0x72,0xc4,0x72,0xde,0x09,0x54,0xdc,0xd1,0xdc,0x11,0xae,0xc4,0x93,0xc5,0x69,0xf4,0x0f,0xc6,0xf7,0x7f,0x03,0xee,0x52,0x4f,0xb0,0x6e,0xc4,0x0f,0xaa,0x1d,0x6c,0xc1,0x0f,},"\x32\x87\x00\xa8\xae\x58\x1c\x1e\xdc\x4e\x2c\x00\xc7\x8b\xf4\x60\x60\x97\xf9\xbd\x75\xaa\xde\x20\x5a\x24\x3c\x5f\xd7\x43\x4d\x62\x22\xda\x93\x7e\x28\x81\xa2\xe3\xc5\x74\x35\x6d\x4d\x56\x79\x30\x1d\xa9\x9e\x11\xcf\x74\x9c\x27\x92\x1c\x8c\xaa\x2a\xb2\xa5\x64\xd8\x7c\x5d\xf8\xec\xf1\xa7\x2b\x68\x01\x84\x82\x4f\x69\x86\x02\x2e\x3f\xc9\x8b\xd2\xa2\x1c\x34\x55\xab\xf1\x15\x49\x54\xfb\x30\xc8\x98\x82\x94\x7b\x02\xf3\x5a\xf7\xb1\xbf\xad\x05\x23\x7d\x24\x2e\x2b\x74\x83\x2f\xc5\x36\x19\x6f\x2e\x59\xd1\xac\xd0\xc1\xdb\x6f\x19\x43\xd0\xf6\x04\x3b\xbd\x6a\x76\x90\x83\xed\x66\xba\x0e\x05\xa5\x0f\xeb\x0a\xcf\x72\xb6\xc1\x6b\xa9\xaf\x03\x9a\xfb\x7f\xe2\xa4\xaa\xeb\x4d\x06\x18\x1c\x5a\x18\x78\x68\x9e\x67\xa3\xf5\xd0\xad\x39\xe7\x94\xd6\x23\x9a\x7e\x0a\x12\xce\x82\x0c\x5b\xe6\x0f\xd5\xf1\xdd\x79\x70\x2f\x49\xd0\x2b\x79\x75\x5f\xe8\x73\xf5\x78\x5c\x72\xf7\x46\x25\xcd\x7e\x24\x28\x26\x25\x97\xd3\x14\x82\xc2\xc0\x50\x88\x01\xfd\x96\x31\x9d\x61\xb9\x1b\xa2\x53\xa5\xe7\x22\xf4\x14\xcf"}, -{{0x39,0xb8,0x06,0x2d,0xa4,0x3e,0x64,0xe1,0x67,0x67,0x65,0xd6,0x2c,0x7f,0xb8,0xe0,0xa9,0x9c,0x4f,0xd4,0x17,0xd6,0xf7,0xe3,0x31,0x9b,0xb1,0x30,0x44,0x20,0x5f,0x3b,},{0x62,0x27,0xce,0xfe,0x88,0xea,0x4f,0xb2,0x7b,0x37,0xb5,0xf7,0x97,0x77,0x8b,0xd7,0x2f,0xda,0xfe,0xad,0xcc,0xd9,0xae,0xb6,0x7a,0xd4,0x37,0xce,0x08,0xfb,0xa6,0xa8,},{0xc5,0xf6,0x26,0x49,0x0c,0x0e,0xf4,0xe1,0xef,0xc3,0xed,0xeb,0x0c,0xbc,0x3f,0x7d,0xe2,0x67,0x05,0x7f,0xb7,0xb6,0xeb,0x8f,0x0c,0x81,0x35,0x84,0x96,0x5b,0xc5,0xc4,0x21,0xfe,0xed,0xf5,0x42,0x41,0xca,0xe0,0x01,0xec,0x6d,0x5e,0x25,0xc9,0xb1,0xfb,0xa0,0x38,0x5e,0x5d,0xbd,0x95,0xa0,0x6e,0xc1,0xd8,0xae,0x51,0x91,0x44,0x96,0x0d,},"\x74\x0a\xf6\x79\xe3\x06\x9f\xad\x05\x9f\xa4\x82\x5f\xa4\x1c\x59\xfb\xd4\x84\xaa\x64\x93\x03\xc2\x7c\x4f\x7a\x94\x71\x1c\x5b\x71\x3b\x2a\x6b\x89\x87\x85\x9e\x22\x71\xa6\xa7\x1e\xb0\xb4\xa1\x5a\xbd\xe4\xf5\x16\x8f\x6c\xb9\xdb\xdc\x6a\x27\xa2\xa1\x3d\x52\xc9\x72\x08\x96\xa1\xf4\xce\x3a\x53\x45\xee\x79\x3b\x6c\xc3\xad\x80\xd7\xd5\x81\x63\xd5\x45\x5b\x9c\xbd\x07\x3e\x2b\x7a\xdb\xff\x95\x59\x0c\x71\x72\x27\x1b\xd9\x1f\xef\xdb\xd0\x16\x57\xee\x17\x50\x65\x10\x36\xcd\xc3\x56\x0b\x44\x4c\xa2\x18\x4b\xf4\xf3\xea\x89\xfc\x97\x3a\xab\x6f\xb4\xa8\xee\x57\x04\xbb\xe5\xa7\x1c\x99\xfa\x3b\x5e\xf0\xd0\x39\x62\x49\x75\x82\x97\x69\x9a\xe2\x02\xb8\x19\x69\x0d\xc7\xac\x46\x92\x77\x03\x46\x90\x78\x45\xe2\x21\x0d\x53\x63\xad\xee\xc0\x3f\x0f\xc7\x76\x1b\x7e\x0e\xc0\xfe\xa1\xbc\xf6\xb0\x4f\xc5\x4b\x3e\x4c\x40\xd1\x9b\x8f\xa6\x49\xac\x84\x79\xe8\xf8\x07\x30\xc0\xc9\x4e\x9f\x4a\x1a\xd5\x06\xf2\xbc\xab\x0c\x49\x54\x0f\x6d\xec\xaa\x77\xb3\xd6\x57\xdc\x38\xa0\x2b\x28\xa9\x77\xec\xe4\x82\x54\x5a"}, -{{0x52,0xf4,0x67,0x5d,0x8c,0xcd,0x0e,0xb9,0x09,0xdf,0x0a,0x51,0x66,0x48,0xdb,0x26,0xfa,0x03,0x3b,0xa4,0x1d,0x43,0xfc,0x38,0x45,0x89,0x6d,0x45,0x6e,0x14,0x26,0x5f,},{0xf3,0x9e,0x7d,0xaf,0xc9,0x7b,0x0a,0x84,0xdc,0xbf,0x7f,0xa1,0x4a,0x94,0x03,0xee,0x1f,0xa9,0x2b,0x85,0xe5,0xa7,0xe5,0xd0,0x5f,0x03,0x1b,0x44,0xdd,0xf1,0xf7,0x94,},{0x4b,0xf6,0x68,0x82,0x7a,0x72,0x0a,0xf6,0x88,0x98,0xa0,0x6e,0xa7,0xb4,0x45,0x45,0xa3,0x4c,0xa8,0x96,0xec,0xf3,0x11,0xfe,0xea,0x47,0xe0,0x68,0x6d,0x91,0x1f,0xad,0xaa,0x03,0x11,0x89,0x97,0x15,0x3c,0x65,0x36,0x1f,0xea,0x15,0xde,0x9b,0xb8,0x91,0xb8,0x90,0x98,0x72,0x04,0x55,0x08,0xff,0xad,0x0c,0xd9,0xea,0xb2,0x1a,0x97,0x02,},"\x74\x42\x71\x10\x85\x7c\xb4\xaf\x0a\x33\x42\xc2\xb5\x29\x97\xbc\xe1\xa0\xdb\x64\x05\xc7\x4e\x96\x51\xc5\xb8\x59\x79\xac\xb0\x71\xe5\x67\xfe\x70\x41\x2c\x4e\x0d\x8c\x9f\xa4\x21\x91\x4f\x6a\x62\xf2\xae\x42\x0b\x7b\x2f\x4c\xf8\x0c\x90\x57\x42\x21\x22\x22\x88\xb6\x58\x67\xea\xa6\x6e\x7e\x0a\x05\x57\xa2\x6c\x54\x9f\x9a\x7a\x4e\x70\x83\x8b\xa4\x07\x4b\x4c\xd7\xa9\xd7\x58\xb3\x78\xb8\x8d\xd4\x94\x41\xdf\x80\x2a\x44\x4d\xcb\xc3\x06\x24\x93\x3b\x59\x92\x2f\x33\xc2\x0f\x01\x9f\xe7\x8e\xe2\x4b\x8f\xba\x79\xa6\x82\xf3\x88\x50\x5a\xc9\xc9\x7f\x4e\xb8\x7c\x61\x18\x80\x02\x6b\x4c\x23\x30\x6b\x86\x51\x73\xf5\xd7\x16\xab\xc6\xcd\x9a\x99\x06\xdb\x34\x30\x13\x6f\x75\x41\x29\xc4\x43\xb2\x0c\x42\xbe\x2f\xbc\xbc\xd4\x40\x34\xd7\x14\xf5\x8a\x4b\xa8\xe7\x56\x60\x7a\x02\xb6\x08\xef\x49\x64\x8f\x2a\xd0\xce\xa9\x9e\x7a\xb3\x0a\x8d\xd7\x81\x40\x04\xf7\x25\xf4\x93\x01\xd7\xb3\x04\xdc\xda\x62\x5c\x29\x6d\x92\x8c\xb5\x81\x73\x6a\xb7\x39\xc8\x6b\x46\x92\x41\xa8\x25\x93\x51\xfd\x37\xb4\x78\x0a\x99\x93"}, -{{0xba,0xd7,0x3c,0x9f,0xda,0x4c,0xeb,0x9d,0xa6,0xc7,0x01,0xc2,0xa6,0xe2,0xef,0xc0,0x46,0x7a,0xfa,0x0a,0x74,0xf8,0x75,0x0c,0x52,0xcf,0x1f,0xd4,0xc8,0xe7,0x48,0x9a,},{0xbb,0x0f,0x02,0x7a,0x90,0x35,0x37,0x6e,0x1a,0xa3,0x20,0x6c,0x3d,0x77,0x44,0x75,0xe3,0x51,0xf5,0x76,0x7e,0xf8,0x6e,0xf4,0x8a,0x72,0xc0,0x37,0xc2,0x4c,0xce,0x62,},{0x19,0x7d,0x6b,0x6c,0xc8,0x8a,0x98,0xc0,0x6d,0xfc,0xa0,0xc0,0x12,0x25,0xed,0xfe,0x38,0xa0,0xb2,0x28,0x9f,0x29,0xf8,0xa4,0x4e,0xc0,0x81,0x6a,0x95,0x2d,0x58,0x5e,0x2d,0x59,0xb5,0xb0,0x8d,0xe1,0x00,0xc0,0x60,0x62,0x96,0xcc,0xf5,0xe9,0x2a,0x99,0xe0,0x93,0x62,0x31,0x44,0xb8,0xb2,0x2d,0xb8,0x7d,0x92,0x92,0x25,0x54,0x60,0x05,},"\x74\xb9\x66\xcb\x78\x07\x71\xae\xe6\x3d\x73\x4d\xf3\x75\x67\x02\xd1\xd5\xfd\xed\xdf\x32\x13\x6c\x63\x58\xb8\x36\x31\x8a\x4f\x98\x4f\xe7\x1e\x77\x16\xad\xdd\xbd\x64\x9e\xba\x44\xcd\x42\x82\xe0\x05\x5d\x8c\x1e\xd2\xd3\x51\x23\xd6\x6e\x5a\x98\xf1\xc0\x83\x8d\xed\x56\x3b\x9a\x20\xeb\x80\x07\x53\x8f\xc7\xb0\x71\x3e\x7e\x48\x5e\x3c\x28\xf6\xeb\xc4\x21\xa2\x9d\xce\x25\x24\xdb\x7f\x29\x20\x57\x61\x03\x6a\xda\x62\xe5\xb0\xb7\xd5\xb7\xf2\x94\xff\x17\xf3\x38\x23\x2f\xa5\xfd\x42\xb6\xf7\x25\x33\x04\x09\x2d\x84\x8f\x50\x73\x52\x48\x59\x5d\xa0\xf7\xef\x28\xe5\x68\xe9\x91\x6b\xfc\x56\xd7\xed\x0d\x81\x1b\x59\xd5\xd8\x91\xae\x43\xe1\xb1\x98\x07\x13\x06\xbf\x52\x5c\x67\x8c\x63\x43\x99\x80\x05\xfb\xb7\x86\x9d\x1c\x40\xf8\xca\xc8\x07\xfe\x2e\xf0\x3f\x3d\x5b\x93\x3f\x58\x97\x8e\xf2\x90\x6f\xcc\xf7\x44\x4a\x29\x36\xe6\x3d\x92\x8c\x69\x09\x26\xc9\xc9\x94\xed\x3d\x66\x62\x63\xe9\x56\xfd\xfe\xa2\x77\x64\xbc\x5f\x74\x12\x5b\xc4\x6b\xc1\x02\xdd\x3e\x5f\xf9\x3b\x5e\x12\x3e\x4b\x38\xbd\xef\x69\x7e\x15"}, -{{0x70,0x73,0x27,0xa4,0x31,0xdb,0xa7,0x76,0x39,0xb3,0x96,0x6b,0x2b,0xc0,0x95,0xf8,0xee,0xdf,0x57,0xf7,0xa2,0x00,0xe3,0xb0,0x07,0x7c,0xe4,0x20,0x38,0x9c,0x92,0xfe,},{0xee,0x24,0x96,0x91,0x08,0x64,0x18,0x9f,0xda,0xa3,0xc7,0x75,0x7e,0xb3,0xcd,0xa9,0xab,0x1e,0x70,0xfc,0x9e,0x7f,0x71,0xa3,0x8a,0x0b,0xfc,0x84,0x59,0x31,0xc9,0x5a,},{0xfb,0x99,0x02,0x9f,0xec,0xa3,0x87,0xa5,0xd7,0x65,0x96,0x1e,0x36,0x1d,0x71,0x72,0xb9,0x8b,0x7e,0x0f,0x11,0x29,0x0b,0xb1,0xe5,0xb5,0x7b,0x51,0xbc,0x21,0x23,0xd0,0xbc,0xe2,0x90,0x20,0x39,0x2a,0x4f,0xec,0x9a,0xe6,0xa7,0x2c,0x4c,0x38,0x6c,0xea,0x18,0x57,0xcb,0x8f,0x9c,0x50,0xaa,0x9a,0x76,0xd7,0xf1,0x68,0x7f,0xcf,0x29,0x00,},"\x32\xef\x31\xb6\x4e\xee\x70\x0f\xca\x2a\xb2\x1a\x26\x7f\x8d\x9d\x3b\xdc\x68\x9c\x75\x38\xfe\x95\x9b\xf7\x13\xfa\x99\x5d\xb2\xc0\xad\x36\xdd\xe4\x30\xa8\x41\x7d\x43\x7b\x72\xc7\x4e\x26\xdb\xe3\x1d\x93\x70\x1d\x46\x17\xfe\x51\x82\x5c\xff\x7a\x54\x4f\xc9\xf4\x4e\x43\x45\xe1\x4b\x4b\x11\xe1\x5f\x26\xff\xc2\xaf\x80\x35\xf3\xf9\x70\xe4\xdd\xa4\x4c\x0e\xbc\x03\x63\xc2\xb5\x6f\xde\x21\x86\x63\xbf\x78\x83\x90\x92\x53\x8f\xc2\xf3\x91\x53\xd4\xeb\x29\xda\x0c\x1a\x08\xaa\x96\x66\x01\xcc\x68\xca\x96\xe9\x93\xb0\x1b\x17\x3a\x26\x1b\x2e\xf3\x27\x65\x03\x82\xf5\x68\xfe\x94\x48\x55\xb0\xf4\xfd\x9d\x15\xe7\x52\xac\x74\xdc\xfd\x37\xb3\x78\x6f\xff\xce\xf2\x33\x39\xc2\x1e\x92\x70\xdc\xe8\x89\x1d\xd5\xee\xeb\xa9\x60\x8f\xdc\x7b\x6f\xbc\xc9\x9f\xa1\xb5\x90\x3d\xaa\x09\x68\xe1\xb6\x91\xd1\x9d\x06\xf2\x15\xde\xd0\x47\xef\x9d\x76\x61\x0f\x5d\xe2\x20\xf5\x04\x1b\x31\x3f\xaf\x9e\x96\xc9\xfd\x7d\xb5\x4b\x52\x25\x72\x6a\xf4\x35\xf9\xcb\xd9\xfd\x87\xab\x40\xce\x8f\x2c\x69\x40\xb5\x5f\x0f\xaa\xe8\x78\x50\xca"}, -{{0x6a,0xa5,0xc9,0xf0,0x08,0xf9,0x90,0x47,0x3b,0xa4,0xa6,0x28,0x6a,0x41,0x66,0x14,0x02,0x66,0x61,0xf1,0x1e,0x1a,0x24,0xef,0xa8,0x1a,0xc3,0x58,0x52,0xd1,0xd0,0x70,},{0x60,0x5a,0xc9,0xb4,0xdb,0xdd,0x50,0x33,0xd6,0xc8,0x28,0xbf,0xaf,0xa9,0x3c,0x00,0x39,0x44,0x0a,0xa1,0x1c,0xa7,0x24,0xae,0x83,0x40,0x43,0xe0,0x7b,0xd0,0x32,0xd5,},{0x97,0x56,0x30,0x3b,0x90,0x65,0x5e,0x93,0x52,0x51,0x03,0x2a,0xb1,0x9c,0xfc,0x95,0xca,0x1c,0x2a,0x2c,0x3e,0xa2,0x8b,0x03,0x3b,0xd4,0x70,0x66,0xcb,0xd4,0xc7,0xd8,0x98,0x2a,0x8b,0x98,0x86,0xf1,0xb9,0xcd,0x02,0xe8,0x8a,0x65,0x56,0x4d,0xa8,0xdc,0xc3,0x4f,0x30,0x8b,0xa9,0xf1,0x01,0x44,0xba,0x46,0x9c,0x2e,0xfa,0x49,0xe0,0x04,},"\xb5\x16\x5d\x39\x63\xf6\xe6\xf9\xea\x56\x57\xe9\xf0\x7f\xf3\xa3\x21\xeb\x33\x8f\x9a\x8c\x3d\x3c\x42\x30\x6b\x2b\x27\x89\x78\xb3\x1c\x62\x3a\x63\x1b\xe3\xb0\x4c\x41\xed\xfd\xed\xdf\x53\x8e\x1b\x76\x5b\xc8\x78\x54\x01\xc1\xaf\x29\xd0\x46\x7a\x64\x41\x1c\x49\x73\x95\xd7\x55\xdc\xa0\x3a\xe3\x27\x2f\x4b\xc1\xfb\x19\x18\xdc\xc1\xed\x6f\x04\xd6\x49\x84\x04\xa8\xce\x14\x09\xd4\x47\xf5\x70\xa4\x35\x95\x22\xcc\x54\x62\x92\x02\xeb\xe5\x07\xab\x69\x38\x43\x14\x1b\xd5\xea\x05\x73\xb2\x0f\x32\x1a\x48\x3f\xf3\x83\xa4\x68\x97\xf5\x92\x6f\xe0\xb8\xaf\xc2\x55\x72\x70\x7b\x63\xee\xed\x28\x35\x32\x92\x8a\x41\x44\x19\x64\x97\x94\x2c\x57\x2a\xc5\x47\x60\x51\x39\x25\x6b\x0a\xa0\xea\xf0\x4d\xb1\xa2\x56\x01\x2e\xd4\x53\xb1\x73\xee\x19\xad\x6e\x9b\x1a\xf3\xf4\x5f\xf3\x04\x4a\x64\x1f\x8c\x8e\xb0\xac\x7b\xb4\x5a\xbb\xde\xd4\x72\x86\xb2\xa0\x69\xd3\x90\x86\x94\xee\x06\xf2\xfb\xd0\xef\x60\x5a\x79\x11\x02\x6e\xa9\xea\x3c\x49\x13\xf3\x8c\x04\xd8\xb6\x95\x65\xa7\x02\x78\x67\xab\x30\x92\xd0\x5f\x4c\xfb\x18\xfc\x7c"}, -{{0x8e,0xfb,0x8b,0x79,0x74,0x2b,0xe2,0x1e,0x6d,0x31,0xde,0x67,0x8b,0xc8,0x14,0x50,0xba,0x86,0x21,0x08,0x2c,0xd6,0xf0,0x00,0x3e,0x22,0x86,0x1e,0x22,0x91,0xc4,0x81,},{0x33,0x38,0x1e,0x35,0x6c,0x4f,0xd3,0x86,0xa3,0xf7,0xb9,0x69,0xaf,0xd9,0xf5,0xc0,0x0d,0x20,0x67,0xb6,0x98,0xb3,0xf1,0xf0,0x0f,0x37,0x84,0x20,0x2d,0x30,0x84,0xcf,},{0x92,0x30,0x05,0xcb,0x48,0x48,0x40,0x2a,0xa8,0xf9,0xd5,0xda,0x74,0x03,0x0b,0x00,0x94,0x44,0x92,0x4c,0x21,0x4a,0xd6,0x00,0xdd,0xba,0xb4,0xc1,0x53,0xa6,0xff,0x02,0x2b,0x53,0xcf,0x63,0x64,0xcd,0x7e,0xe9,0x9b,0xef,0x34,0xfe,0x14,0x4d,0xa9,0x64,0xed,0xfc,0x38,0xa0,0xba,0x63,0x33,0x12,0x65,0x0e,0xbf,0x0e,0x55,0xa0,0x60,0x09,},"\x6b\x75\x03\x25\xd3\xa0\xf0\x8a\x14\x77\x00\xb5\x1a\x9b\x37\x25\x57\x10\x94\x81\x8e\xd6\x9d\x1f\x76\x10\x13\xeb\x86\xf3\x23\xf7\x3c\x49\xf5\xe4\x39\x87\x7c\x27\x83\xb3\x36\xd1\xf1\xa6\x74\xef\x3e\x43\x1f\xc1\xae\x01\x80\x08\x2d\xf5\xfc\xa6\x9f\x84\x81\x39\xfe\x6a\xb6\x73\x9a\x05\x92\xeb\xd6\xd4\x70\x5c\x7f\x01\x36\xb2\x21\x89\xa1\x1d\x60\xd4\xd3\xc9\xbc\x80\xfe\x7d\x7c\x00\x95\x2d\x57\x42\xf9\xc0\xc2\x12\x1f\xe7\x92\xdf\x13\x3f\x22\x1d\xb9\x91\xfc\x96\x0e\xe6\x4b\x9d\x32\xe0\x17\x8e\x54\x2b\xce\x8e\xfa\x8d\x03\xac\x80\x26\xcd\x77\xba\x8b\xf0\xb2\x42\x15\xb9\xfa\xed\x2e\xae\xc9\x20\xe9\x25\xd5\xec\x46\xff\xf6\xbd\xe7\x25\xe9\x1c\x82\x80\xe4\xad\xa2\x32\xa5\x43\x3a\xe9\x68\x0e\xbb\x53\xeb\x55\x55\x31\x47\xc9\x33\x70\x57\x48\x54\x89\x61\x54\x51\x42\x99\xc0\x93\x21\x9a\x11\x1d\xca\x4e\x63\x7a\xd5\x00\x13\x38\xc6\xd4\xd5\xee\x90\x98\xc6\x58\x32\xf7\xaf\x83\x5b\xcb\x62\x21\x28\x42\x30\x36\xc7\x9a\x57\x37\x73\x8a\x75\x39\xf8\xd4\xa6\xb8\xb2\x21\xb5\x6d\x14\x01\xae\xb7\x4d\x45\x71\xbc\x00\x9d"}, -{{0xed,0x04,0x6d,0x68,0x8b,0x2b,0x0a,0x1b,0xc3,0xda,0xf2,0x11,0x9d,0xd3,0x21,0xa6,0x07,0xb1,0x6d,0x2a,0x2d,0x1d,0x96,0x3a,0xdd,0x12,0x09,0xc6,0x65,0xb5,0xcc,0xba,},{0x87,0x34,0xf1,0xff,0xcb,0xd7,0x1c,0xfd,0xe2,0x90,0x01,0x7e,0xa6,0x25,0x3e,0x58,0x0d,0x59,0xe6,0x5b,0x54,0x1b,0x46,0x52,0x1f,0x5e,0x5e,0xc1,0x45,0x1e,0xae,0xc6,},{0x72,0x1b,0xfd,0x47,0x76,0xcf,0xba,0x13,0x33,0x0f,0xd3,0x72,0x69,0xe9,0x79,0xc1,0xd7,0xb6,0xce,0x54,0xa5,0x1b,0x82,0xf4,0x56,0xe1,0x37,0x37,0x8e,0x58,0x2f,0x19,0x2a,0x12,0x08,0x9d,0xa5,0xab,0xa7,0x6a,0x7b,0x16,0x18,0x13,0xdc,0xe5,0x6b,0x72,0x89,0x2a,0x35,0x33,0x0c,0x94,0xf7,0xff,0x21,0xd0,0x9c,0xf0,0x9e,0x55,0x35,0x04,},"\xb9\xcc\x90\xfd\x8d\xe2\xa1\x41\xf9\x51\x16\xdb\x3b\x04\xbe\x83\xe9\x85\x22\x59\x7e\xc2\x17\x49\x64\x24\x51\x80\xb9\xa4\x73\x76\x7d\x6d\x47\x0a\x21\x7d\xb5\xff\x5a\x1a\xb7\x77\xe1\xe2\x8a\x0b\x16\x97\x5e\x2b\xac\xb8\x73\x02\x04\x44\xb4\x7e\xd8\x32\x64\x21\xb9\x0e\xbb\x50\x36\x88\xf0\x90\xc1\x1b\x3b\x13\x61\x7c\x5c\x50\x52\xc2\x97\xa4\x1e\x28\x93\x77\x5e\x34\xd5\x9a\xda\x49\xd9\x94\xc0\xe4\xa9\xf5\x22\x0e\x9f\x03\x15\xa6\x77\x05\xa3\xec\x08\xaf\x0d\xc7\x24\xb5\xcf\x67\xff\x34\xfa\xda\x8b\xa7\x10\x9e\xd2\xb5\xa8\x90\x7b\xb4\x03\xfb\x1a\x83\x8b\x4b\x05\x9f\x18\xc7\x92\xd7\xbf\xec\x05\xde\xe0\xc9\xcb\xbf\x17\x53\x40\x9d\x7d\xb3\xac\xea\xf4\x7b\x4c\x61\x39\x84\x97\xb0\xec\xa6\xc1\xf8\xac\x08\xa7\xea\x1e\xb9\xc4\x0b\xc4\xe9\x2e\x88\x82\x12\xf7\xd9\xee\x14\xfd\xb7\x31\x58\x16\x09\x44\xff\x9b\xcd\xfe\xf1\xa7\x46\x9c\xc7\x0f\x94\x74\xe5\xf2\x4d\xff\xfe\xa5\x85\xf0\x9e\xaa\xab\x4b\xe2\xaf\xeb\xbe\x8e\x6c\xf8\x6d\x35\x68\x0d\xc5\xd1\xb9\x29\x13\xe8\x48\x25\x6e\xc7\x36\x31\x6f\xd0\xa2\x14\x20\x63\xb0"}, -{{0x76,0xac,0x8e,0x57,0x0a,0x39,0xb3,0xa0,0x23,0x2c,0x45,0x49,0x75,0x37,0xfb,0x21,0x55,0xac,0xec,0x36,0x17,0x86,0x5e,0xd1,0xdf,0x21,0x0f,0x00,0xb4,0x9d,0x1b,0x8d,},{0x31,0x2a,0x3a,0xd8,0x99,0xae,0x6a,0x25,0x50,0x7a,0xe6,0xe4,0x52,0x4e,0x10,0xb6,0x3a,0x6e,0x7a,0xe5,0x3d,0x9c,0xff,0xd3,0x9c,0xf2,0x85,0x21,0xd9,0x35,0x33,0xd6,},{0xcf,0x03,0xf5,0x25,0x91,0x3c,0x44,0x30,0x3b,0x2f,0x80,0x07,0x93,0x93,0xc2,0x1c,0x11,0x58,0x14,0x6e,0xcf,0x99,0x63,0x6f,0x5d,0x97,0xad,0xfd,0xd9,0xf3,0x58,0x39,0x80,0x4c,0x23,0x80,0x4c,0xbf,0x1e,0x55,0x3c,0xfd,0x4b,0x73,0xf6,0x89,0xa9,0x14,0x3a,0xec,0x29,0x8f,0x82,0x76,0xe1,0xe4,0xee,0x08,0x91,0xf1,0xba,0x75,0xde,0x04,},"\x53\xce\xd9\xdb\x2b\x47\x9e\x59\xd3\xed\x64\x3f\x7c\xc3\x78\x4c\x24\xb8\xbd\x4c\x63\x20\x6c\x72\xe2\x3f\xa8\x50\x02\x88\x99\xa4\x1c\xe1\xa8\xbd\xc0\x03\xf1\x2b\x7c\x29\x97\x2c\x9a\x08\xbc\xd2\x31\xfe\x0e\x1a\x0f\xef\x0b\xaf\xbf\xa4\xe0\xe0\x27\xd7\x20\x04\x07\x5b\xa3\x7d\x49\x0e\xb9\x96\x4e\x78\x3b\xb9\x8f\x9e\x50\x3e\x9c\x1f\xd3\xd2\x3f\xb0\x01\x7c\xc7\xc7\xa9\xf8\x6d\x17\x1f\x04\x1e\x23\x55\xd8\xc5\xe6\x22\x9d\x34\xc7\xee\xac\xb6\x35\x8c\xf3\x06\x0d\x5d\x26\x5b\xae\x20\x04\xa5\x58\x87\x86\x59\xa3\x0d\xfe\xd5\xf2\xec\x78\x8b\x4e\x14\x39\x7b\x5d\x00\xc2\x9d\xb5\xd4\xeb\xf1\x66\x39\xa8\xdf\x29\x2a\x3d\x24\xf6\x98\x3c\xbc\xa7\x60\xd9\x03\xe9\x76\xf5\xb6\x98\x64\x2b\xa1\xfe\xd4\x9e\x79\xc3\x8f\x4b\xb3\x94\x6e\xfc\xcc\x9d\x6a\xef\xad\x33\x6d\x55\x8f\x78\xe4\xf2\x05\x42\x2e\x10\x38\x4a\x4e\x53\x1e\x75\x80\x7e\xfb\x38\x9d\x2a\xf4\xca\xb4\x38\x25\xfb\x87\xf1\x96\xa9\x08\x07\x69\xfe\x75\x85\x78\x29\x70\xa6\x91\x8a\xff\xe1\x0d\x20\xd6\x29\xb7\x05\x84\x55\x97\x41\x8d\x69\x9d\xe3\xf1\xde\x85\x4f\x94\xbd"}, -{{0xf6,0x4a,0x66,0xba,0x0f,0x08,0x19,0xf3,0x00,0x14,0x16,0xc2,0x20,0xbf,0x52,0xd8,0x60,0x13,0x0a,0x19,0x76,0x4a,0xa8,0xab,0x38,0xd1,0x5b,0x2a,0xa7,0x5a,0xc0,0x22,},{0x81,0x25,0x25,0x3c,0xd3,0x37,0xe0,0x0d,0x45,0xb4,0x50,0x79,0xb5,0x85,0x34,0x95,0x61,0xe5,0xf5,0x42,0xa8,0x1f,0x6d,0x2f,0xcf,0xd9,0x85,0xc1,0x0f,0xea,0xb2,0xaf,},{0x4d,0xe6,0xf5,0x25,0x08,0x22,0xd7,0xc9,0xd5,0xbb,0x98,0x58,0x25,0x00,0xb5,0xc0,0x85,0xf5,0x41,0xeb,0xdc,0x45,0x0e,0xd1,0xac,0xaf,0x83,0x68,0x48,0x27,0xed,0x1d,0xc7,0x71,0x47,0xaa,0xe4,0xb1,0x9e,0x14,0xa7,0xdc,0x5b,0xbe,0x1f,0x1e,0x4f,0x57,0x71,0xd8,0xa6,0xe4,0xf2,0x35,0x17,0x39,0xaf,0xb0,0x8c,0x80,0x6d,0x55,0x87,0x01,},"\x80\x72\x86\x2e\xd0\xab\x35\x92\x1d\xb5\xec\x2c\xba\x8e\x6a\xed\xb0\x44\x1f\xdf\x47\x49\x10\x06\xc0\x1e\x64\x56\xad\x70\xfa\xe3\xc4\x15\x2d\xcf\xbf\xdb\xb8\xf0\xfd\xde\xc5\xe9\x6b\x12\xbf\x67\x98\x9b\xa9\x67\x93\xf4\x86\x1a\x11\xb6\x39\x09\xce\x8d\x19\xb8\xca\x64\xa5\x44\xb3\x1c\xe0\x51\xfb\xc8\x8e\x06\x28\x06\xd9\x96\x5c\xbd\x29\x67\xb0\x16\x14\xe8\x6b\x53\x2f\xbf\x59\x84\x32\x18\xdc\x9c\x19\xc8\x03\x15\xf0\x44\x73\x17\x19\x37\x10\x92\xa3\xda\x38\x87\x8b\xc4\xcf\x77\xde\x97\x2e\x86\x04\x66\xb8\xfc\x45\xe4\x65\xdc\x3d\x0e\xbf\x94\xbd\xea\x60\xef\x0b\x98\x91\xce\xd4\x1b\x99\x7b\x11\xb3\x1e\xe4\x16\x7d\xb6\x0c\x9c\xfc\x8b\x85\xbe\xac\xfe\x22\x3c\xc1\x82\x92\x13\x77\x40\x85\xd7\xc0\x6d\x2b\x2e\x63\x2c\xc2\x1c\xd9\x66\x0d\xf4\x7c\x4f\xa9\x18\xbd\xd5\x96\xdd\xf6\x22\xdc\xb6\x52\x64\x2b\x67\x52\x7b\xa8\xed\x15\xa8\x19\xa8\xe2\x1f\x48\xd7\xee\x70\x24\x7f\x52\x00\xe3\x7c\x25\x9d\xff\xd1\x7e\xec\x8c\x23\x2f\x97\x0c\xb0\x31\x82\xfe\x39\x64\x13\x29\x93\xf6\xec\xb7\xc4\xdb\x18\xcc\xef\x39\x0c\x9e\xb3\x63\x9e"}, -{{0x84,0x39,0xb1,0xd6,0x0a,0xa4,0x84,0x60,0x13,0x5e,0xb1,0x00,0x2c,0xc1,0x12,0x79,0x29,0x95,0x07,0x9a,0x77,0xe6,0xe8,0xab,0x02,0x0b,0x9a,0xba,0xca,0x89,0x20,0xb4,},{0xea,0xdc,0x3e,0x0c,0x5b,0xdd,0xbc,0x30,0x52,0xc3,0xb2,0xf8,0xb0,0xa9,0x45,0x66,0xc2,0xb2,0xc8,0x79,0xed,0x17,0x03,0x4a,0xc0,0xe6,0xa4,0x5f,0x2b,0x3e,0x32,0xd2,},{0x62,0xda,0x81,0xe1,0x64,0x40,0x82,0x1b,0x59,0x3b,0x6e,0xe6,0x54,0x0e,0x15,0xd1,0xae,0xa7,0x5d,0x23,0xe0,0xa1,0xbb,0xfe,0xdc,0x80,0x8c,0x95,0x48,0xf8,0x7e,0x8b,0xbf,0x36,0x91,0x5a,0x39,0xa7,0x47,0x16,0xf6,0x45,0xcc,0xa5,0x71,0x4d,0x17,0x0a,0xf9,0x07,0x57,0x6d,0x4f,0x37,0x05,0xe5,0x43,0xd2,0xad,0xdd,0xc5,0xff,0x23,0x03,},"\x54\x19\xf6\xd2\x4e\xb4\x66\x35\xd4\xa7\xf8\xea\xb8\x03\xcf\xd0\xd0\x4d\xe0\x92\xaf\xbd\x86\xf2\xa6\x96\x1a\x8d\x1e\xb8\xc0\xd1\x97\xba\x55\xee\x08\xc9\x91\x82\x2a\x5a\xa7\x02\xba\xe0\x33\x7a\xbd\x5c\xa7\xfa\xa1\x5e\x1f\x1a\xe3\x69\x94\x6e\x9b\x81\x21\x6c\x0f\x5f\xc2\x2b\xbd\x44\x33\xc3\xde\x93\xc5\xca\xa2\x74\x16\x83\xbb\xd0\xe1\xa7\x8d\xf2\x8d\xda\x19\x17\x41\x01\x87\x63\x34\xd4\x03\x39\x65\x9f\x02\x1a\xe7\x66\x16\x2c\x6c\xc5\x42\x1b\x79\xcf\x9d\x5c\x09\x0e\xd4\xaf\x07\xec\x84\x49\x30\x35\xbd\x0b\x24\x21\xb5\x33\x68\x42\x95\xbb\xe7\x6a\x70\xfe\xc5\x96\xef\x8c\x89\xc5\xc9\xdd\xa3\xc3\x3b\x77\x35\xd2\xd2\xf2\x0b\x28\xf1\xa5\x40\x2e\x72\xd0\x4b\xa2\x91\xdd\x59\xf1\x4a\xf0\x8a\xdf\x56\xee\xb0\x86\xd7\x69\xc6\xbe\xc3\x45\x18\x91\x37\x23\x45\xfd\x6b\xd0\x2d\xcf\x95\xe8\x03\xaf\x03\x53\x15\x0e\x18\x2e\x32\x3a\xaf\x68\x3e\x03\x6d\x9a\x13\x5d\x2e\x6f\x98\xcb\x4d\x32\x7e\x2c\xe7\xd5\x42\x47\xf3\x59\x2e\xd0\x67\xb4\xce\x76\x27\x17\x4f\x99\x6f\x28\x16\x5c\x9c\x11\xf0\x7e\x5e\xe9\xce\xe6\x38\x51\xc6\xb6\x8e\xa2"}, -{{0x3a,0x04,0x63,0x97,0xf0,0xaf,0xc0,0x72,0xbc,0x7f,0x90,0x7c,0x74,0xd3,0x8f,0xd1,0xb9,0xaf,0xdf,0x27,0xe1,0x4a,0x35,0x34,0x76,0x8b,0x0d,0xd2,0xdf,0x3a,0x1c,0x22,},{0x99,0xcd,0x70,0xef,0x3b,0xe3,0x42,0x49,0x33,0x93,0x87,0x2f,0x54,0xc4,0x7d,0xea,0xa0,0x81,0x02,0x18,0x92,0xd1,0x1a,0x32,0x68,0xf3,0x14,0x5e,0xd4,0xf3,0xab,0xe5,},{0x50,0x24,0xce,0x60,0x25,0x79,0x65,0x68,0x70,0x80,0xc5,0xb1,0xfc,0x7d,0x13,0x01,0xc3,0x2a,0xa6,0xfc,0xc8,0x35,0x49,0x7d,0x9c,0xb2,0x3a,0x74,0xa6,0xca,0x27,0x24,0xf5,0x53,0x53,0xc1,0xb7,0x57,0x82,0x7c,0xa5,0x44,0x0c,0x9e,0xf8,0xf8,0xc1,0x05,0x09,0x13,0xe2,0x0a,0xab,0xec,0x35,0xc4,0x97,0xb5,0x60,0x41,0xb5,0xde,0xb2,0x09,},"\xf0\x8d\xde\xf4\x6c\xc6\xc3\x41\x79\x82\x0c\x98\x61\x37\x51\x72\xfd\xdf\x77\x4f\x8d\xc3\xf7\xd6\x4a\xa4\x32\xda\x8e\x5f\xae\x64\x4c\x0a\x8a\x9e\x69\x08\x51\x7d\x50\x5d\xeb\xd6\x12\x86\x8a\xc6\xda\xf9\x5c\xd7\xe1\x69\x97\x50\x02\x2c\xcd\x4b\x88\xdb\xae\x2b\xbf\x73\x54\x6e\xe4\xb8\x35\xd3\x19\xa8\x42\xda\xe8\xb9\xed\x68\x33\x23\xf3\x1e\x5c\xc5\x79\x19\xbc\x9d\xbe\x3b\xcf\xff\xb2\xad\xa4\x80\x72\x69\x7f\xf4\xa7\xd3\x10\xc9\x1a\xdb\xca\x81\xfa\xf2\x6a\x0e\xb7\xbb\x0c\x40\x4a\xc9\xd8\xdf\xec\x63\xe9\xc6\x4e\x2f\x42\x0c\x07\xd3\x23\xb7\xc0\xdc\x3b\x73\x50\x72\x83\xae\xb1\xce\xe5\x1d\xb4\xe1\xa8\x3a\x69\x2c\x7c\x1e\xa3\x98\xf6\xf3\x09\x40\xfa\xb8\x5e\x21\x38\xd4\xb8\x5a\xa4\xe2\x31\xe5\x42\x4f\x5b\x06\x4e\xd0\x26\xf0\xcc\xb9\x9d\x1c\x85\xa9\xeb\x15\xf5\x93\x4a\x11\x35\x9d\x41\x1c\xf9\x4a\xe8\xff\xa3\x36\x1a\x22\x4f\x46\xba\xb8\x52\xd1\x84\xa2\x48\xb4\xc3\x1f\xe3\xa7\xe7\xf5\x13\x4c\x05\x10\x31\xa9\xf3\x28\xa7\xbe\x4a\x7c\xbb\xb1\xd8\xd8\x63\xa4\x00\xfd\x2d\x58\xda\xa4\x4f\x1b\x9d\x8e\x9d\xdf\x96\x1c\xe6\x32\x2f"}, -{{0x12,0x4f,0x74,0x16,0xa8,0x04,0x53,0xe4,0xcf,0x1c,0xd7,0xb5,0xe0,0x50,0xa9,0x76,0x14,0x18,0x25,0x8b,0xf7,0xd2,0x7b,0xeb,0x7f,0x23,0x23,0x8c,0x45,0x40,0xbe,0x2d,},{0x0d,0xa3,0x4a,0xb1,0x73,0x99,0x01,0x50,0xdf,0x73,0x99,0xb6,0xbc,0xdd,0xba,0x93,0xc6,0xdb,0xcb,0xf4,0xd1,0x76,0x94,0x1c,0xb5,0x07,0x1e,0x87,0x34,0xc5,0xdc,0x92,},{0xb0,0x57,0x21,0x04,0xaa,0x69,0xe5,0x29,0xe3,0x46,0x5a,0x6f,0xd2,0x8f,0x40,0x4a,0x4e,0xc2,0x02,0x76,0xa9,0x93,0xb1,0x72,0x5e,0xb8,0xc5,0xf6,0x50,0xb4,0xa2,0x16,0xf1,0x87,0x1b,0x24,0xe3,0x68,0xcc,0x46,0xcd,0x1e,0xe0,0x17,0x4c,0xda,0x1b,0x5e,0x4a,0xe2,0x20,0x0a,0xa9,0xfc,0x44,0x52,0x2d,0x97,0x5a,0x9c,0x51,0x81,0x49,0x08,},"\x9d\xcb\x98\x73\xff\x05\x4d\xb1\x1d\x0a\x9b\x19\xde\x68\x85\xff\xba\x7f\x0e\x68\x1c\xf7\xfb\x8f\x6c\xd9\x50\xc4\x83\x28\xd1\xf9\x19\xca\x46\x05\x4e\xee\xe6\xc9\xe5\x78\x43\xeb\xdd\xa7\xb2\x4b\xc3\x50\x3c\x4d\x61\x2a\xbb\x1a\x31\x4f\x39\xf5\x82\x21\xd2\xb5\x4d\xc7\x55\xac\xca\x79\x69\x74\x0e\x7f\xa8\xb1\xa9\x52\x3b\x8c\x73\x79\xfd\x39\x52\x53\xf4\xe6\xcd\x05\x4e\xe2\x4b\x75\x61\x3c\x35\x81\xd4\x9e\x19\x24\x6a\x7b\x3b\xe1\xce\xcb\x33\x4b\xe4\x4f\x3d\x62\x6f\xe3\xb7\xb2\x69\xe6\x28\xd4\x45\x80\xc2\x06\x36\xeb\xa2\x64\x2f\x27\x44\xb9\x59\xe6\x57\x57\xd0\xee\x60\x18\x43\xf1\x88\xe9\x5d\x17\x25\x3f\xef\x56\x70\x68\xa5\x40\x5a\x3a\x9e\x67\x7f\xea\x3d\x7d\x55\xf7\xea\xd1\x9a\x3f\x30\xc5\xf9\x85\x67\x1b\x55\xfa\x12\x0c\xb9\xd0\x5f\x47\x1b\x6e\x1e\x8d\x77\x9a\x2c\x80\x3a\x19\xe6\xd0\xd7\xcd\x50\x78\x87\xed\x64\x7c\x2a\x95\x48\x3f\x93\x39\x91\xed\x45\xae\x30\x1a\x2b\x0e\x95\x4a\x57\x03\xd2\x48\xc7\x88\x10\xaa\x0b\x19\x9c\xc2\xbe\xbb\x2f\x1d\x71\xcc\x40\x48\x7d\xbd\x42\xee\xe0\xf7\x45\xf7\xd2\x85\x68\x5b\x1f\xb3\x1b\x15"}, -{{0x25,0xd1,0x3b,0x38,0x37,0x60,0x1b,0x07,0xa9,0x75,0x69,0x3e,0x5a,0x33,0xd5,0x33,0x7c,0x34,0xc1,0x12,0x7f,0xe4,0xc2,0x74,0x90,0x61,0x2a,0xaf,0x7f,0x64,0x2e,0x9a,},{0x3a,0x07,0xcd,0x68,0xee,0x26,0x92,0xd5,0x1c,0xfa,0xd1,0xa8,0x0e,0x77,0x63,0xb1,0x8a,0x04,0x3c,0x74,0xf4,0xe1,0xb0,0x1e,0xdc,0x55,0xba,0x9a,0x9e,0x07,0x79,0x5a,},{0x20,0xcb,0xf0,0x83,0x92,0xfe,0xa6,0xa9,0x9c,0xf4,0x46,0xa9,0x5c,0x19,0x9c,0xaa,0x0c,0x0f,0x98,0x13,0xcc,0x21,0x7b,0x8d,0x22,0x8e,0x2e,0xd9,0x0b,0xab,0x95,0xea,0x92,0xcd,0x73,0xac,0x95,0x83,0x47,0x64,0xd3,0x3e,0x42,0x24,0x3c,0x80,0xa7,0x60,0x34,0x91,0xc8,0xd3,0xe4,0x9a,0xc7,0x15,0xfd,0x8a,0x5b,0x9e,0x47,0x89,0xbb,0x03,},"\x11\x5b\x32\x20\xb4\x5c\xa8\xf3\x6c\x7f\xf5\xb5\x38\x87\xd4\x7e\x66\x9b\x78\xda\xc1\x3b\x98\xcc\x7a\xac\xa5\xc2\xe1\x9f\xce\x81\xec\x86\x17\xca\x41\x0e\x11\xc9\xa9\x11\x8a\x66\x84\x53\xb3\x29\xff\xb7\x18\xea\xec\x73\x91\x72\xf0\xa8\x49\xa0\x84\x81\x92\xa5\xbd\xea\x18\xab\x4f\x60\xd8\xd1\xa0\xd3\x38\x95\x2d\x77\xb2\xcc\x13\xef\xe8\x3c\x76\xe8\xdd\x58\x80\x3b\x1d\x8b\x3c\x97\x29\xef\x10\x2b\x20\x83\x5b\x7d\xe8\x72\xbe\xf3\x01\x0f\x15\xa4\xca\xdd\xf0\x7c\xf7\xbd\xd2\x22\xd8\x4b\x17\x4b\xc2\x15\x27\xcf\xfb\x1b\x7f\xfd\xe8\x1e\x28\x1d\x30\xcb\x7b\xce\x25\xea\x3d\xff\xb6\xea\x1f\xbb\x06\xcb\x70\x56\x9a\x95\xed\x1a\x07\xe9\x7c\xa4\x2d\xe7\x0a\xa2\x18\x15\x9e\xfd\x60\x8f\xa9\xb0\x89\x6e\x0b\x58\x51\x8a\x32\x2f\x25\x1d\x13\x3e\x58\xc8\xfc\x14\x28\xab\x0a\x17\x0e\xd8\x45\xc7\x5f\xb4\x03\xf1\xff\xb9\x7d\x2d\x2a\x6d\x4f\x27\x79\x11\xd3\x26\xc1\xca\xbb\xb8\x51\x6c\xbc\x17\x90\x8a\xb8\x1f\xf8\xd7\x9a\xf4\x46\x11\xea\x1d\x05\x87\x9c\x1e\xc8\x1d\x06\x93\x6e\x0f\x4a\x0a\xef\x6d\x57\x48\xe1\x81\xd3\x0e\xc2\x52\x36\x59\x7a\x97\x3d"}, -{{0x7b,0x3a,0x76,0xde,0xca,0xea,0x60,0xc4,0x1e,0x95,0xb0,0x58,0x77,0xa7,0xda,0x82,0x06,0x4c,0x27,0x27,0x8c,0x8d,0x7d,0xf5,0xf0,0xbb,0x95,0xf0,0xad,0x2d,0x04,0x35,},{0xf8,0x0d,0xb5,0xc2,0x87,0x21,0xb1,0xc6,0x11,0xbd,0x87,0xeb,0x14,0x5a,0x98,0xbb,0xf3,0x83,0xb0,0x68,0x04,0x5d,0xf2,0x45,0x8d,0x1a,0x6f,0xda,0x09,0x9f,0x7f,0xc2,},{0x2c,0xd2,0x6f,0xb3,0xc4,0xf7,0x44,0x0a,0x72,0xaf,0xfe,0x93,0x56,0x4f,0x6f,0x65,0x59,0xad,0xb1,0x5c,0xc7,0xa2,0xba,0x10,0x87,0x9f,0xb7,0xd6,0x7e,0x47,0xd4,0xeb,0xd0,0x2f,0xe4,0x82,0x36,0x98,0xa5,0xfb,0xd4,0xa9,0x07,0xfd,0x69,0x18,0x4c,0x25,0x5a,0x17,0x0e,0x5f,0x17,0x47,0xfc,0xe9,0x68,0x10,0x2d,0xc2,0x19,0xb5,0x0d,0x02,},"\x37\x5f\xad\xae\xdd\x9c\xac\x49\xb6\x4e\x15\x74\x02\x80\x46\x06\x9f\x4c\x83\x65\x4c\x8a\x70\x11\xab\xdb\x64\xdb\x16\xb4\x7f\xa3\x11\x79\x81\x72\xf9\x07\x22\x17\xb0\xa6\xa4\x3e\x5d\xf6\xff\xcc\x11\x54\xbc\xec\x1c\x68\xe1\xd3\x5e\xc0\x58\x80\xd0\x12\xce\x76\xe4\xce\xbf\x30\x1b\xb2\xec\x98\x3d\x00\xb4\xa0\x54\x0c\x93\x7f\xf1\xc6\xdf\x94\x41\xc6\x1b\xdb\x3b\xe8\xe0\xc7\xc1\x1a\x35\xd4\x9b\x6f\x55\xc3\x81\x26\x9a\x0e\x76\x8e\xfb\xd4\x53\x44\x7f\xe4\x8b\x75\xac\x39\x64\x6c\xa8\x2e\xca\x7d\x14\x93\x04\x42\x34\x91\x87\x1c\x10\xdb\xcf\xc5\x97\x3a\x57\xfa\xb8\x37\x1c\x30\xcb\xc4\xe9\x0b\xec\xc0\xb6\x71\x52\x22\x6e\xe1\x77\xb4\xff\x36\x8e\xc8\x79\xb3\x91\xeb\x95\xe3\x6d\xcb\xb0\x7b\x2c\x16\xba\x39\x55\x45\xd4\x52\x9f\x72\x7b\x1a\x11\xef\x65\xd1\x20\x97\x6b\x7c\xcc\x86\xaf\x4b\xd2\x04\xcb\x94\x89\xc9\x21\xe4\x3b\xa5\xe8\x50\xcf\xe5\x98\x99\xf1\xc1\xec\x4a\xa5\xc9\x2b\x6d\xac\x69\x14\xb1\x95\x2b\x53\xdc\xb5\x40\xb4\x09\x23\x13\x81\x56\x89\x87\xbb\x22\x36\xbc\x40\x89\x5d\xf3\xf1\x7e\xab\x7c\x02\x74\xf2\x24\x4f\x95\x86\x12\xe8\x8e"}, -{{0x5f,0xf8,0xd4,0x05,0x26,0x08,0xeb,0x03,0x3a,0x5e,0x94,0xb6,0x03,0xce,0x38,0x4d,0x84,0x52,0xf6,0x0a,0x26,0x49,0x8b,0x91,0x12,0x56,0x7f,0x34,0x10,0xc1,0x86,0x66,},{0xc4,0x90,0x0d,0xe2,0x4d,0x9a,0xf2,0x48,0x27,0x63,0x10,0x99,0x26,0xaf,0x7c,0x48,0x13,0x80,0xfa,0xbc,0xda,0x94,0x40,0xc1,0xa5,0x3e,0xa1,0xcd,0xc2,0x7e,0x65,0x68,},{0xb7,0x37,0xd4,0xe5,0xbe,0x27,0xde,0xb6,0xd8,0x77,0x29,0xc6,0x36,0xdf,0xf7,0xa4,0x06,0xc0,0x13,0xf3,0x13,0xc3,0x8c,0xf6,0x83,0xfe,0x14,0xf7,0x5a,0x3b,0x30,0x05,0xd9,0x53,0x5d,0x7e,0x58,0x15,0xc8,0xf8,0xb3,0x7c,0x51,0xd6,0x92,0x71,0x11,0xc9,0x79,0xf7,0xd9,0xd8,0x1a,0x34,0x7a,0xa9,0xcc,0x09,0xed,0x4e,0x6c,0x18,0xe9,0x0f,},"\x13\x8c\x60\x55\x7c\x2e\x90\x08\xaf\xc0\x3d\x45\xbe\xc7\x1f\x96\x11\x49\xa0\x83\x59\x26\x75\x1c\x8f\xf3\x93\x5c\x7d\x65\x2d\x83\xe1\xb0\xb1\xda\x7d\x5b\xbe\x0b\x8e\x17\x1a\x4e\x49\xaa\xe0\x6f\xd8\xa9\xde\xff\x78\xdc\xde\x4d\x25\xb1\xaa\x89\x99\x98\xa0\xf9\x9e\x1d\xf6\xf9\x33\x7a\x3e\xa2\xf2\x4b\x76\xc3\x17\xa7\x01\x4d\xb4\xe5\x28\x31\x91\x79\x5a\x70\xd8\x82\x1d\x21\x78\x46\x49\x0f\x95\x87\x01\xd3\x9d\xc2\xc8\xce\x47\xd9\x28\x93\x88\x74\xd8\x7b\x35\x58\x98\x9b\xc7\x7a\xf8\x20\x97\x9a\x35\x1e\xef\x95\x94\xaa\x5b\x94\xf3\x34\x1e\xde\xd4\xea\x20\xb0\x8c\x3e\x7c\x56\x10\xd4\x32\x67\x81\x8d\xfa\xc0\xa8\x7d\xdf\x52\x7f\xbc\xe8\x51\x2b\xbf\x85\xb6\x6c\x9b\xb5\xd6\x2f\x0f\xe8\x40\x48\xf2\x3b\x19\x60\x4a\x5c\x8d\x82\xb1\xf2\x5a\x8d\xa0\x27\x31\xfe\xb2\xec\xae\x48\x9b\x84\x75\xf7\xbd\x32\x6d\xdf\x1a\x08\x18\x9e\x46\xc0\x8c\xf5\x05\x38\xc2\xa3\x63\xe2\xf4\xeb\x2c\x01\xa2\x04\xc7\xff\xbc\x0b\x98\x1a\xdc\x0f\xd9\x97\xaa\xfd\xf2\xa2\x22\xee\x84\xc3\x09\xf6\xe9\x5e\xc7\xde\x4f\xa8\x5d\x47\x68\xd5\xc0\x03\x16\x50\x28\x22\x5e\x22\xe0\x9e"}, -{{0xee,0xde,0xfc,0x17,0x57,0xe3,0xa7,0xe5,0xed,0x39,0x46,0xdb,0xed,0xc3,0x96,0xa3,0x62,0xf6,0x83,0xd2,0xc5,0x1b,0x0b,0x9f,0x60,0x76,0x5d,0x4b,0xfc,0x51,0x34,0xde,},{0xa9,0x87,0x2b,0xc2,0x19,0x2f,0xc0,0x2b,0x18,0x9c,0xee,0xd4,0x03,0xab,0x9f,0x27,0x0a,0x03,0x2a,0x83,0x5f,0xde,0xbf,0xaf,0x1c,0x9d,0x69,0x34,0xed,0x83,0x04,0xbc,},{0xd5,0xbe,0xa8,0xea,0x9a,0x5f,0xe9,0xed,0x6d,0x2b,0xf8,0x39,0x93,0x0c,0x0c,0x6c,0xd5,0x03,0x9e,0x98,0x8f,0x55,0x1f,0xde,0xdb,0x54,0x37,0xe1,0xc1,0xaf,0x0e,0xd7,0xb3,0x89,0x7c,0x03,0x57,0x11,0xc3,0xc5,0x19,0x26,0xbe,0x8d,0x1b,0x32,0x02,0x4d,0x5c,0xd5,0x82,0xf5,0xf8,0x36,0x9a,0xd8,0x4d,0x18,0xb1,0x25,0x02,0x65,0x2f,0x07,},"\xb1\x94\xdb\x73\xf9\x94\xcb\xdc\x3c\xbe\x63\x0b\xa7\x2c\x47\xc2\x24\x9b\xc0\x59\x2a\xb5\x47\x94\x2b\x1d\x1b\x88\x2b\x44\xf5\xb3\x85\x5e\x56\x8b\xdd\xdf\x92\xef\x05\x02\x2d\x88\xfc\xfc\x29\x4e\x76\xb6\x4a\x00\xe9\xc7\x43\x55\x37\x37\x63\xe4\x9a\x4e\xbc\x47\x24\x3d\x48\xa9\xad\x58\x89\x94\xa5\x18\xf8\x0f\x86\x15\xc2\xb3\x1d\xa5\x87\xa5\x3e\x52\x9d\x43\x5a\x86\x97\x35\x0d\xfc\xde\x02\xd2\x0c\xce\x7d\x5e\xee\xfe\x3f\x5a\xb2\xaa\xc6\x01\x25\x9c\xda\x38\x53\x8a\x1b\x83\x01\xf9\x83\x2e\x75\xab\x90\xf8\xa9\x32\xf2\x67\xea\xc1\x81\x00\x39\x65\xd5\x26\x6f\x20\x61\x80\xc6\xc3\x80\xec\xe8\x03\x57\x7c\xcb\x46\x17\x6b\xf6\x07\x15\x94\x86\xf2\x42\x59\x74\x7e\x2c\xa6\xfb\x19\x12\xdb\x7b\x78\xa9\x73\xb2\x84\x63\x87\xc1\x20\x80\x30\xee\x1f\x40\x0d\x0c\x5b\x5e\x8b\xde\x96\x35\xae\x55\x63\x8b\xa1\x7c\x73\x4d\xe8\x63\x8b\xb8\x5d\xfc\xd7\x66\x29\xa7\xf9\xf4\x0d\x6a\xb9\x54\xd5\x5b\xf8\x57\x5f\xc9\xc9\xa5\x95\x09\x7e\x08\x93\xdb\x5a\x7b\x8a\x6c\x45\x5e\xcb\xd3\xd2\x2d\x72\x5e\x19\xde\x29\x41\xf4\x67\xf9\xeb\x93\xd6\x6a\x0e\x2b\xbd\xbf\x92\xed\x1c"}, -{{0x09,0xd2,0x2b,0xba,0xa5,0x95,0x6c,0xfa,0xcb,0xbf,0x9f,0xd5,0x51,0x09,0x75,0x12,0x86,0x86,0xc4,0x0c,0x6e,0xa9,0x6b,0x89,0xef,0x4c,0x0f,0x0c,0x64,0x9b,0xcd,0x7f,},{0xe5,0x59,0xea,0x8a,0xcb,0xdc,0x61,0xb6,0x70,0x9a,0x7d,0x83,0xae,0x15,0x84,0x9a,0x6c,0x78,0xb2,0x03,0x92,0x3d,0xd0,0xa2,0x99,0x23,0x9e,0xe4,0x88,0x69,0x30,0xba,},{0xe6,0x52,0x75,0xc4,0x32,0x8a,0x70,0xad,0x62,0x40,0x8e,0xd7,0xfb,0x17,0x28,0xbe,0x87,0xa7,0x3a,0x81,0x4f,0xee,0x8e,0xbd,0x94,0xf2,0x66,0x5c,0x71,0xbc,0x66,0xab,0x0c,0x1b,0x07,0xa6,0x00,0xb3,0x0b,0xc0,0x81,0xa7,0x4c,0x53,0x68,0x57,0xc2,0x06,0x10,0x38,0x4b,0xe2,0x68,0xd9,0xaf,0x3e,0x3e,0xcd,0xdd,0x3e,0xb0,0xc1,0x4c,0x0c,},"\x1c\x26\xa0\xf3\xa1\xa5\xb2\xd7\xd5\xb2\x97\xaf\x8a\x6a\x68\x9d\x7c\x62\xa2\x52\x67\xe1\x97\xd2\x3b\xec\xd2\xf2\xb8\x16\xc4\xde\x92\xfb\xda\xff\xb9\x41\xc3\xfc\x8d\xb7\xa8\x43\x35\xa8\x4c\xfb\xc9\x2c\xb3\xac\x80\x6e\xd5\x8d\xf1\x6b\x6b\x8e\x11\x9a\x48\xdf\x4f\x27\xc7\x1e\x93\x1a\x59\x38\xe7\xd0\x02\x73\x48\x85\xe1\x3a\x25\x8a\x15\xb6\xe1\x13\x6e\xfb\xa7\x2f\x1d\x09\x6b\x68\x9f\x76\x18\xf4\x9c\x96\x80\x63\xe8\xf9\x91\xfa\x0b\x55\x60\x1e\x43\x0e\xee\x13\x49\x2a\x1b\x09\x41\x3e\xb2\x38\x13\x59\x1a\x7a\x9f\x07\x0c\xc3\x96\xca\x9d\x1f\xac\xdd\x4f\x4c\xe3\x7c\x40\xf7\x24\x5f\x55\x03\x5e\x10\xfa\xd6\xb8\x5b\x5f\x01\xa1\xda\xac\xc0\xdf\x94\x06\x9f\x7d\xe8\xf6\x46\x7f\x96\xd1\xfb\x98\x64\x8e\x8a\x05\x20\xa8\xcd\x72\x3c\x98\xe9\xdc\x2d\xd4\xb2\x93\x4d\x82\x28\xf0\xae\x1a\x41\x5b\xd3\xa7\xcd\xa3\x8d\x7a\x99\x83\xce\x1a\xf6\xf8\xc9\x70\xa2\xa5\x91\x63\x5f\xe1\x2b\x91\x75\x36\xef\x81\x5e\xaf\x1a\x31\x38\xd7\x0c\xe7\x0a\x79\x42\x64\xd7\xc9\x86\xd9\xee\x32\x90\x44\x5f\x15\xa9\x24\x8f\x27\x65\x27\x1e\x5a\x99\x21\x96\xae\x33\x1a\xbd\x41\x64\xbf"}, -{{0x77,0x82,0x6e,0xd3,0x51,0xa3,0xf0,0x92,0x54,0xae,0x56,0x92,0x88,0x5d,0x77,0x4c,0xb3,0xf2,0x44,0x10,0xa4,0x80,0x9f,0xd9,0x0f,0x8a,0x00,0xda,0x9a,0xee,0x99,0x03,},{0x3e,0xac,0x8f,0x41,0xee,0x73,0xe6,0xef,0x13,0x68,0x21,0xf7,0x95,0x7a,0x1c,0x27,0xe1,0x56,0x38,0xd0,0xe3,0x91,0x6e,0x6c,0xaa,0xc6,0xfb,0x7b,0xeb,0x7b,0xcf,0xb0,},{0x97,0x7a,0xdc,0xcd,0xb8,0x29,0xb4,0x0b,0xbd,0x8e,0x53,0x85,0x6a,0x78,0x3d,0xb3,0x46,0xa3,0x9d,0xff,0x62,0x04,0x1a,0x29,0x72,0xd2,0x90,0x09,0xf1,0xc9,0xff,0x81,0xb8,0xad,0x54,0xcb,0x90,0x1e,0x49,0x7c,0x1d,0x30,0x21,0xb5,0x0b,0x6c,0x69,0xee,0x73,0x55,0x8f,0xd7,0xbe,0x05,0xd6,0x25,0xf5,0x72,0x7f,0x9a,0xf2,0xce,0x87,0x02,},"\x1f\xf0\x6c\x0b\x39\x99\xce\xcb\x19\x00\xa4\x7d\x26\x7b\xea\xfb\xb3\x5d\x93\xd1\x4c\xb2\xc8\x92\x5e\x3e\x3f\xe5\xd9\x67\x58\x69\x25\xee\x4b\xaa\x41\x99\x8e\xdd\x01\x03\x20\x58\x10\xaa\xd5\xc0\xbb\xdc\x77\x87\x44\x76\x81\x02\x46\xd1\x30\x89\xa6\x4d\xb5\x76\x42\x4f\xae\x0b\xed\x96\x64\xa4\x2a\x49\x11\x47\xd1\xee\x3b\x9c\x3b\x1b\xa4\x87\x5b\xe1\x54\x62\x39\x25\x40\xf9\x97\x8d\x9a\x46\x30\xba\x4c\x52\x54\x99\x75\x1a\x45\xef\xc2\x99\xec\x7d\x73\xb1\x7f\x9a\xd2\x75\xee\x71\xa6\x87\xe7\x26\x90\xd7\x32\x02\x42\xd2\xdc\x2b\xd4\xd5\xc5\xcf\x0f\x17\xa4\x65\x18\x5d\xcf\x60\xf8\xef\xff\x53\x90\x3f\x20\xb0\xc2\xab\x21\x92\xd4\x43\x68\xf2\xf2\xfb\x36\x04\x8a\xf0\x71\xf7\xaa\x85\x7b\x14\xad\x1d\x11\x46\x12\x05\xbe\xbe\x17\xe0\x2b\xe2\xe3\xcc\xb6\x09\x28\x21\x88\x5c\x4e\x0d\x48\x11\xbe\x3f\x45\xb1\xfe\xa0\x88\x45\x3e\x02\x24\x32\xf5\x62\x56\x2b\x43\xa3\x55\xcb\x56\x27\x0c\xed\xb6\xc2\xc4\x2d\xbf\x9b\xe8\x50\xe7\x71\x92\xfd\xc6\x5c\xfd\x36\x83\x4b\xe9\x88\xdb\xe9\xa9\x3e\x25\x18\xc1\x38\xb0\x90\xfb\x9d\xa8\x27\xcb\x1c\x91\xc8\xfe\x52\xfe\x7c\x57\xf7"}, -{{0x99,0xa9,0x95,0x31,0xc3,0xcd,0x6e,0x3e,0x9c,0x90,0x0a,0x9e,0xeb,0x26,0x26,0x7e,0x72,0xf0,0x9d,0x11,0xb6,0x51,0xa8,0x97,0xeb,0xb7,0x9b,0xe0,0x16,0xf6,0x4c,0x6e,},{0x9b,0xf9,0xf8,0xb4,0x8a,0x27,0x28,0xe0,0x26,0x08,0xfc,0x19,0x89,0x9d,0x21,0x96,0x56,0x83,0x9d,0x1c,0xc1,0xe9,0xa8,0x98,0x4d,0xf6,0x74,0xec,0x26,0x66,0x2f,0x41,},{0x0e,0x89,0xda,0x5d,0x94,0x9c,0xf2,0xbf,0x40,0xc7,0xe1,0x7c,0x2d,0x0f,0x9c,0xea,0xbc,0x88,0xa0,0x92,0xeb,0x4d,0x49,0xcf,0xbf,0xea,0xb7,0xc8,0xbf,0xf4,0x32,0x45,0xc6,0x7b,0x9e,0x2e,0x92,0xf9,0xbc,0xb9,0xb3,0x4b,0x3f,0xcf,0x8b,0x01,0xfa,0x2e,0xa7,0xa9,0x64,0x9f,0x81,0x4c,0x3a,0xa9,0x8b,0x3d,0xd0,0x45,0x40,0xc3,0x1d,0x09,},"\x7a\x89\xc0\xc1\x95\x2f\xdc\x42\x98\xdc\xae\xa8\x54\xef\xc1\x34\x65\x6b\xe1\x47\xe9\xe8\xe8\x2f\xc9\xa4\x49\x05\x9d\x80\x57\x0f\x75\x67\x6b\x81\xc4\xa9\x4f\x76\xa9\x68\x20\x0c\xde\xb0\x98\x8c\x73\xf5\x9a\xfc\x72\xad\x4c\x31\x03\xe1\x9f\xe6\x3b\x7e\x95\xe1\x40\xb5\xcb\x2e\xfc\x7b\x97\xa6\xff\xbb\x6c\x29\x8d\xda\xce\x3b\xe6\xd2\xed\x3d\x59\x8b\x8b\xdf\x0c\x2f\xe6\xc9\x76\x02\x14\x2a\x76\xe9\x78\x51\x4c\x19\x6c\x1b\x9a\x88\xef\xdc\x19\x25\xfc\x50\x61\x55\xcf\xf9\xa2\xf2\x1a\xb6\x34\xe2\xb9\x3e\x96\x92\x8a\x5d\x8f\x7c\xe4\xcb\x73\x26\xd9\x68\x94\x69\x24\x2b\xa9\xc6\xa0\x1b\x77\x49\x6b\xad\xef\x87\x57\x8f\x5a\x17\x28\x4e\x90\x0a\x72\xdf\x14\x1c\x61\x99\xb0\xe7\x1a\xb5\xda\x43\x75\x03\x76\x17\xec\x61\x96\xd4\xf4\xe2\x3a\xe2\x91\x6a\x72\xd0\xfc\xe7\x96\x02\x23\x05\xac\x9f\xbb\xbb\xe4\x70\x5b\x34\x0e\x42\xb7\x8e\x1c\x02\xbb\x10\x01\x86\x0c\xdc\xaf\x71\xed\x89\x25\x5d\xd5\x6c\xc0\xb3\x1c\x59\xd4\x59\x6d\xce\xf8\x4e\x22\x23\x4b\xe5\x62\xbd\x80\x1e\x94\x11\x1d\x83\xa7\x80\x64\xc9\x0f\x9d\x82\xfc\xe9\x1f\x68\xab\xb0\x3c\x73\xb6\xbd\x8d\x7e\x02\xd4"}, -{{0xaa,0x58,0x40,0x3e,0x76,0x3b,0xac,0x40,0x5d,0xb0,0x65,0xeb,0x11,0xeb,0x6b,0xe3,0xe3,0xb6,0xcf,0x00,0xec,0x4a,0x22,0x2b,0x52,0xbf,0xf4,0xb6,0xe3,0xd1,0x56,0xac,},{0x16,0x7f,0x9b,0x9a,0x46,0x65,0xf9,0x3f,0x5d,0x7d,0x30,0x16,0xac,0xe6,0xfb,0xd1,0x34,0x20,0xb2,0xe5,0x1e,0x72,0xbd,0xe5,0x9e,0xed,0xf2,0x69,0x93,0xb6,0x6c,0xae,},{0x64,0xb5,0x98,0xca,0x5b,0x8f,0x9a,0xe7,0x42,0xe4,0x6e,0xe0,0xd8,0xc1,0xaa,0xf3,0x14,0x58,0xb5,0x0c,0x25,0xd2,0x67,0xa6,0x77,0xe4,0x4b,0xe5,0xb7,0x55,0xf1,0x4d,0x51,0x80,0x1a,0x30,0x39,0x9b,0xfc,0xc3,0x8d,0x14,0x07,0x1a,0xa0,0xae,0x93,0xda,0x82,0x5a,0x58,0x1a,0xb6,0xc2,0x07,0x25,0xa0,0xa9,0x10,0xb4,0x73,0x5d,0xfa,0x0b,},"\x3b\xaa\x09\x98\xff\x02\xb3\x2b\x90\xb5\x1f\x9a\x84\x0c\x7b\x5c\x58\x70\xcf\xb1\x81\x0a\x9b\x0f\x77\xb5\x59\x09\xd4\x7a\xd3\x35\x14\x7a\x99\x1c\x29\xfb\xeb\xfc\x59\x2e\x93\x07\x17\x5c\x19\x64\x12\x9a\x2d\x5e\xfc\x62\x15\x80\x74\x53\xbc\xd7\x26\x96\x97\x81\x22\x2b\xca\xd1\xc9\x9a\x49\x74\x8b\x9e\xe6\x67\xc4\xd0\xc8\x28\x89\xe2\xf5\x00\x64\xc1\x15\xdb\xd8\xfb\x48\x3d\x72\xab\x0c\xca\xdf\x76\xbd\xdb\x2d\xc7\x27\xdb\xc3\xfa\x5c\x46\x24\xc2\x83\xd8\x92\x1c\x8a\xa4\x42\x51\x10\xdc\xdd\x69\xc0\x5e\x5e\xd5\x9b\x35\x96\x25\xee\xaa\xec\x1e\x27\xea\xfe\x9d\x9a\x5c\xe7\x36\xc3\xf9\xc5\x27\xea\x54\x78\x18\xb9\xbc\xa6\x81\x1b\xe4\xcc\x15\x05\x8a\x6f\x5b\x68\x33\x03\xb8\x0c\x90\xc9\x4a\x83\xb8\xb1\x58\x69\x71\x3a\x66\xb1\xe0\xf6\x56\x33\x1b\x28\x6d\x1e\xf7\x69\x88\x34\xab\x3e\x13\x84\x17\xaa\xd6\xbb\x3a\xb3\xbd\x9f\xc7\x87\x61\xa4\x82\xdf\xc6\x54\xf3\xf8\x62\x8c\x8d\x9f\xc1\x60\x18\x89\x8f\x16\x41\xe8\x62\x2b\xd2\x72\xe3\x8d\x41\x70\x6c\xb9\xce\xbe\x6e\xe5\xe1\x73\x57\x6b\xf6\x1b\xb1\x18\x8c\xf2\xf3\x9c\x62\x22\x0b\xba\x88\xfc\xb4\xde\x48\x98\xb2\x5b\x04"}, -{{0x10,0x44,0xee,0x37,0x08,0xc0,0xb0,0xe9,0x09,0xa8,0xcb,0x2b,0xa2,0xcd,0x0a,0xf8,0xd2,0x8a,0x5d,0xe0,0x1d,0x96,0x2e,0x82,0x60,0x87,0xfb,0x23,0x2d,0xf7,0xb2,0xd2,},{0x46,0xd2,0x41,0xea,0x0c,0x70,0x2c,0x18,0x89,0xd4,0x46,0x55,0x82,0x46,0x29,0xb6,0x72,0x84,0xd4,0xe6,0x44,0xa4,0x8f,0xa4,0x54,0x55,0xd2,0x7a,0xc5,0xf6,0x25,0x29,},{0x7d,0x6b,0xed,0x7f,0x87,0xd0,0x90,0xab,0xe0,0x13,0xc3,0x1e,0x12,0x03,0x90,0x3b,0xac,0x9c,0x93,0x44,0x5d,0x06,0xc7,0xb5,0x3d,0x31,0xd1,0x5f,0x97,0x0d,0x88,0x64,0x7a,0x7e,0xd2,0xc3,0xa6,0x30,0x50,0xba,0x19,0xd6,0x80,0x43,0xaa,0xdd,0x18,0xbd,0x86,0x1d,0xe1,0xac,0x47,0x15,0xb8,0xe8,0x28,0xb2,0xb1,0x6f,0x8a,0x92,0xb0,0x01,},"\xb8\xa4\x45\x45\x5f\xb6\x6e\x17\xe3\x14\x3d\x35\x20\x4c\x9e\xa9\x34\x74\xee\xbe\xef\x93\x96\x3e\xe5\xc1\xd3\x77\xca\x21\x7a\xcd\x4c\xa6\x3e\x57\x55\xda\x08\xfb\xff\xdb\xd4\x35\x2b\xf1\x65\x19\x38\x96\xc8\xd6\xf7\x6b\xb4\xcd\x3b\xc2\xd3\xa4\x76\xa4\xe3\x20\x82\x4a\x12\x10\xce\x74\xd0\x01\x4d\x74\x7f\x11\x1e\xec\x31\x0c\x5c\x89\xed\x4d\x08\x50\xe8\x11\xf8\x0a\x8b\xb2\x8d\xca\xf6\xf4\x11\xdf\x83\xe2\xc1\xdf\xd9\x0c\x4a\xd2\x35\x61\x45\x4e\xb5\xd7\x56\xb6\x3b\x4e\xa7\xf3\x7d\xc5\xd4\x66\xc1\x6e\xf7\x0d\x11\x19\x0c\x4f\x53\x16\xfe\x2a\xa8\x59\x74\x40\xe8\x8b\xbe\xba\xeb\x35\xea\x5f\x04\xf0\x7b\x03\x39\x26\x41\x58\xef\x90\x9a\xd5\x16\x3b\xfc\x24\x8c\xd7\x24\x13\x3e\x27\x4f\x81\x26\x95\xf2\x90\xe5\x71\x76\xa9\x6b\x93\x93\xd0\x7b\xb3\x10\x29\x9f\x5d\x2a\x6b\x6d\xd1\xda\xbc\xb5\x1b\xf2\x9c\x5a\xfa\x7e\xbb\x07\x01\xc6\xc8\x47\x67\xac\x13\x77\x93\x09\x1f\xe0\xed\x6e\x47\xd7\x80\x62\x8a\x32\xc8\x4f\x83\xe0\x0e\x9c\x16\x74\x2a\x52\x3e\xcb\x63\xc2\x4f\x4a\x33\x8e\xd2\x99\xa0\x61\x94\x92\x4f\x44\xc5\xa5\xd3\xc9\x37\xff\x9b\x09\x45\x98\x2a\xd2\x4a\x2d\x1c\x79"}, -{{0x95,0xdd,0x1a,0x5e,0x65,0x8f,0xa6,0xc8,0xd4,0x25,0x07,0xb3,0xe5,0xb8,0xed,0xb5,0xba,0xec,0xa6,0x2d,0xeb,0x00,0xfc,0x5d,0x4d,0xca,0x8e,0x1a,0xb5,0x83,0x5e,0x59,},{0x3a,0x53,0x23,0xdd,0x1e,0x07,0xf3,0x23,0xbb,0x6d,0x83,0xe9,0xc2,0xdb,0x92,0xa2,0x9f,0x62,0xe2,0xe0,0x03,0xee,0x0d,0xea,0xcd,0x7e,0x2e,0x4e,0x03,0x0d,0x8d,0x27,},{0xd0,0x2a,0x75,0x23,0xdc,0xbd,0x29,0x57,0x6b,0xa8,0x09,0xb5,0x31,0x03,0x77,0x74,0xdf,0x41,0x73,0x4a,0x41,0x17,0x58,0x13,0x11,0x9c,0x6a,0x6a,0x78,0x8c,0xd9,0xb8,0xad,0x78,0x08,0x65,0x67,0x86,0x67,0x69,0x9a,0xe6,0x6d,0x01,0x09,0x19,0xa9,0x66,0xa0,0x51,0xc0,0x81,0x63,0xdf,0x67,0xa9,0x77,0xee,0x6e,0x22,0x0d,0x0d,0xc3,0x0f,},"\x9b\x7a\xfd\x48\xc4\x74\x60\x4c\x26\x36\x75\x31\x55\x68\x40\xc3\x88\x66\x8b\x0f\x38\x40\x06\x3d\xfc\x98\x69\xad\x5b\x90\x12\x74\xb9\x31\x29\x3d\x04\xf3\xc8\xe8\xf7\xf8\xea\xb8\x15\xa6\x41\xd7\xc3\x51\x28\x4e\x8b\xb0\x43\x7a\xc5\x51\xbb\x29\x43\x89\x64\xe6\xa7\xc7\xba\x77\x23\x44\xb3\x33\xf9\xed\xa5\xa7\x75\x68\xc8\x93\x1d\xdc\xaf\x21\xe3\x2e\x07\xb1\x0b\xf4\x82\x0f\xb8\x59\xbc\xf8\x7b\x81\xc4\xbf\xf4\x26\xf2\x4a\x4d\x46\x8f\x2e\x9a\xed\xa8\xf1\x7d\x93\x97\x09\x97\x0d\xb1\x1d\xf7\x62\x47\xe9\x8a\x39\xeb\x8b\x38\xf5\x94\x9f\x34\x9f\x2a\xe0\x5a\xb4\x8c\x01\x85\x17\xc4\x8f\xa0\x20\x5d\xc7\xf1\x56\x64\x53\xe1\x05\xe4\x8c\x52\xeb\x45\x5c\x0c\x40\x80\x2f\x79\x7b\x3e\xef\xb1\xe2\xf3\xb1\xf8\x43\x15\xae\xd5\xb0\x71\x1c\x64\x99\xa6\x91\xb7\x4b\x91\xf1\x2e\xf7\x0f\x76\xc4\xc0\x5c\x1a\xa1\xa9\x93\xe2\xf3\xe5\x28\xab\x34\x3d\xd2\x36\x81\x62\xf4\x03\x6a\x61\xa1\x3a\x88\x04\x5d\xcd\xef\xa8\x5d\x68\x53\x22\x75\xbc\xf5\xb8\xf5\xf0\x0e\xfd\xea\x99\x9a\x95\x78\x31\x75\xd9\xee\x95\xa9\x25\xd4\x8a\x54\x49\x34\xd8\xc6\xb2\x62\x22\x5b\x6e\xbe\xa3\x54\x15\xdd\x44\xdf\x1f"}, -{{0x1a,0xbc,0x0b,0x9a,0xa0,0x1d,0xc5,0x7c,0xa5,0x3e,0xfe,0x73,0x80,0x96,0x2b,0x1a,0x88,0xd5,0x0a,0x96,0x4f,0x5c,0xd9,0x86,0x40,0x98,0x2c,0x74,0x39,0x3f,0x29,0x26,},{0x8d,0x4f,0xd1,0x43,0x94,0xd7,0xc1,0x40,0x57,0x00,0x30,0x69,0x83,0xfb,0xf7,0x6e,0xa9,0xf1,0x71,0xb1,0x5a,0x6b,0x56,0x61,0x2a,0x1f,0xeb,0x1c,0xbd,0xae,0x5d,0xd5,},{0xf7,0x38,0xaf,0x2d,0x3e,0x29,0x0b,0x3d,0x23,0xd9,0xaf,0xf7,0x41,0x4b,0xfc,0x5f,0xfa,0x47,0x23,0x5d,0xc0,0x53,0x68,0x7a,0x8b,0xa5,0xc8,0x54,0x1b,0x85,0x11,0xf7,0x81,0x56,0x6c,0xda,0xa1,0x30,0xe0,0x67,0x7d,0xb5,0x5f,0xa8,0xbe,0x9d,0x81,0xa0,0x92,0xcb,0x58,0x92,0x3a,0x86,0x28,0x49,0x4d,0x2f,0x62,0xd9,0x5c,0x16,0x71,0x00,},"\xda\x2d\xd9\x40\xd5\xe1\xdb\x6e\x80\xbf\x7e\x2b\x78\x2e\x7e\x74\x5c\xd4\xfd\x25\x2e\x98\x15\x17\x97\x58\x87\xdd\x05\xac\x77\xed\x83\x7d\x08\x29\x61\x57\x5e\xfe\xdf\x30\x1f\xdf\x24\xb7\x07\x18\xb9\x91\xb8\xd9\x2b\xdd\x2e\x6b\xee\x17\xc8\xaa\x4b\xc6\x94\xa7\x27\xbc\xfc\x78\xfd\x85\x19\x5c\x42\xca\xf8\x83\xa2\xc3\x8d\x16\x1c\xad\xd7\x9c\xfd\xa9\xa3\x91\x10\xe1\x26\x4d\x30\xbd\x4c\x5c\x4a\x58\x76\x77\x7f\x23\x3b\x07\x1b\x1b\x0b\x40\x89\x35\xf0\x46\x89\x54\xcc\x74\x4a\xf8\x06\x3b\x00\x4e\xde\x56\xcd\x98\x1c\x4d\xd5\x60\x8a\xbf\xfe\xae\xc9\xe5\x8f\x3f\xaf\xaa\x67\x14\x67\x80\x4b\x7f\xa2\x55\x8f\x4f\x95\x17\x42\x01\xf1\x83\xd8\x0a\x59\x14\x06\x5f\xed\x53\x11\x5b\x41\xeb\xc3\x38\xf7\x8d\xf0\x50\x05\x3b\x8a\x4e\x75\xea\x7c\x6f\xdc\x35\x4d\xad\x27\xbf\xd8\xa2\xe6\x6f\xcd\x7a\xe2\xf5\x87\xd2\x4b\xe0\xd4\xa3\x3d\xa3\x0a\x22\x0e\x51\xbc\x05\xfa\x4e\x41\x2b\x95\x9f\xd9\x5d\x89\xea\x6e\xc0\x16\x25\x16\xc0\x96\xa9\x43\x3a\x9e\x7c\xf5\x99\xc9\x28\xbd\x53\x05\xc2\x17\x3b\xf7\x49\x3e\xd0\xc1\xc6\x03\xcd\x03\xf0\x82\xcc\xe4\x42\x37\xa7\x9f\xfd\x8b\xe9\xa6\x72\xc2\xeb\xaa"}, -{{0xcb,0xff,0xce,0x2c,0x9b,0xd3,0xe2,0x3e,0x40,0x6e,0x5f,0x66,0xe6,0x32,0xdc,0xfa,0x72,0x66,0x54,0xd2,0x9a,0x95,0x5c,0xec,0x98,0x31,0x73,0x23,0x5f,0xa3,0x59,0xd0,},{0x49,0x65,0x3e,0xdd,0x64,0xa5,0x5f,0x7c,0xd4,0x0e,0xaf,0x3f,0x8e,0x72,0xeb,0x96,0xdb,0xcd,0xee,0x39,0x8f,0x34,0x81,0x7f,0x2c,0x95,0x86,0x79,0x49,0x71,0x0b,0x14,},{0xe7,0xce,0xd4,0xfa,0x2a,0x7d,0xff,0x73,0xf1,0x06,0x8b,0xba,0xd0,0xec,0x9a,0x11,0x09,0x04,0x3c,0x97,0xa6,0x2e,0xff,0xa1,0x48,0x87,0x6f,0x09,0x69,0xed,0x4d,0xc6,0x08,0xe2,0x8b,0xce,0x79,0x7a,0xf3,0xb8,0x25,0x32,0xc9,0x4d,0xec,0x4d,0x68,0x11,0xb7,0xf5,0x63,0x67,0x91,0x29,0xfa,0xcf,0x17,0xbb,0x73,0xd6,0x93,0x75,0xeb,0x05,},"\x1f\xfd\xe6\x82\x6e\x4f\x0c\x24\xa7\x96\x1f\x19\x1e\x74\xcc\x0b\xbc\x92\x8e\x3f\x1a\xec\x3e\xfa\xb3\x27\x65\xc2\x50\x1c\xbc\x16\x20\xe7\xee\x6f\x61\xfc\xcf\xb0\x0c\xfc\xa9\xfb\x98\x14\x3b\x52\x9b\xcc\x8c\x3d\x0f\xdf\x89\xee\x7c\x34\x2f\x10\x18\x15\xfa\xbf\x7d\xea\xf9\xf3\x02\xa2\x88\xfe\x17\x58\x26\xd5\x90\xd9\x9e\xe6\xfd\x92\xda\x74\xf9\x59\x6b\x78\x3c\x0e\x7d\x47\xd7\x11\xa3\x2f\x39\xea\x41\x65\xe5\x21\x24\x31\x44\x1b\x49\x8c\x6b\x70\xdb\x3b\x09\xd1\xf4\xe4\xa1\x4a\x6b\xae\x39\xda\x50\x88\xbb\x85\xb3\x28\x5c\xe9\xdf\x2f\x90\x68\x1a\xf2\xc7\x4d\xec\xe4\x39\xae\xb9\x1e\x1c\x1b\x07\x12\xed\xdb\xee\x8d\x72\x56\x98\x28\xf3\x7c\xb7\x20\xc5\x09\xd0\x2a\xec\x47\x60\x70\x48\x4e\x9b\x16\xec\x71\x79\x94\x7a\xc9\x6c\xaf\x0e\x1b\xe8\xb6\xb7\x4f\x37\x2d\x72\x35\xfe\x6e\x39\x99\xdf\x73\x3b\xcc\xd4\x82\xdf\xe2\xe6\x31\xf5\x6b\x58\x26\x67\xdc\xe5\xe3\x12\x17\x63\xad\xfa\xcf\x3b\x18\xcf\x20\x95\xf7\x39\x4d\xee\x49\x27\xfc\x2b\xea\x6b\x58\x24\xd9\x0c\xd5\x9e\x85\x4e\xc5\x87\x2b\x45\x51\xb0\x2e\xfa\xba\x5a\xd5\x4a\x9b\x7a\x8f\x6d\xe5\xd7\xcd\xa5\x82\x5b\x32\x5b\x07\x6d\xed"}, -{{0x9f,0x91,0x23,0x14,0x97,0x48,0x4c,0xab,0x39,0xb9,0xe2,0x0f,0x86,0x11,0x81,0xd3,0x97,0x90,0x85,0x77,0xbb,0xb2,0x96,0x82,0x42,0xd0,0x71,0xbc,0xa4,0x81,0x3f,0xfb,},{0x88,0x24,0xbc,0x6c,0xd6,0xa6,0xf1,0x5a,0x5f,0x41,0x66,0x8f,0x2b,0x3b,0xae,0x8f,0xc4,0x96,0x73,0x83,0x07,0x8d,0x08,0xb5,0x1d,0x6d,0x1b,0x2b,0x93,0xa1,0x07,0x1f,},{0x0a,0x1c,0x70,0x6d,0xd8,0xa1,0x30,0x77,0xab,0x18,0x38,0x6c,0x65,0xfa,0x97,0xcf,0x9d,0xfc,0x43,0x54,0x2d,0x18,0x46,0xec,0xbd,0xde,0xb7,0xb3,0xc9,0x3f,0x3c,0x66,0xf3,0xcc,0xd0,0x44,0x7a,0xac,0xdd,0x4d,0xad,0x8f,0xbf,0x73,0x6c,0x4f,0xf9,0xdb,0xdb,0x62,0xbf,0xc1,0x4d,0x88,0x83,0xe3,0x85,0xbc,0xe9,0xba,0xc5,0x6a,0x35,0x0c,},"\x21\xd4\xfb\xc9\x81\x63\xc3\xfb\x6e\x09\xf7\x75\xc2\xab\x7b\x18\xb1\x87\x92\x34\x0b\xaf\xed\xac\xb4\x96\x05\x62\x2e\x3c\x08\xaa\x3b\x2b\x8d\x0e\x09\x02\xf3\x61\xaa\x1c\x0f\x65\x2e\x27\x32\xb1\x0a\x0c\x5c\x6a\x05\x09\x89\x96\xb5\x88\x26\x7c\xc8\x95\x1a\x78\xb5\xd4\x31\xe7\x22\x2b\xbb\x50\x8e\xee\xf1\xb5\xe8\xb8\xd0\x1d\x39\x91\xe1\x8d\xdd\xc6\xca\x8d\x22\x2e\xf1\x77\xce\x62\x93\x8d\x18\x10\xee\xcf\x06\xf4\x73\x8b\x28\xf4\x40\x94\x6c\xca\xd2\xa1\x2e\x39\xd3\x86\x11\xbe\xd3\xa3\x9f\x93\x41\x9a\x17\x9e\xc2\xb1\xb5\x2d\x5f\xe5\xc8\x0c\x23\xb8\x4d\x88\x03\x75\x5f\x51\x46\x09\x2c\xc1\x99\xb4\xbd\xce\xa5\xbc\xf2\x03\x7b\xd5\x3f\xf6\x34\x66\x94\x15\x5f\x02\x7d\x8c\xe2\xba\xff\xe3\x0a\x56\x66\x59\x6c\x00\x78\x3a\xae\xad\xe9\xc7\x7f\xc8\x63\x79\x42\xec\xe0\x17\xd6\x48\x4c\x28\x99\xb1\x91\x8d\x3a\x48\x0b\xd5\x15\x76\x78\xd4\x77\x2d\x27\x1f\x9b\x99\x76\x8e\xe1\xbc\xc4\x6b\x24\x89\xae\x87\xcd\x03\x0f\x47\xd1\x33\x3c\x76\x72\xcb\x90\x2c\xb4\xf5\xfe\x74\x6e\x85\x3d\xe5\x79\x40\xba\x22\x64\xd3\xe6\x29\x64\x4d\x65\x3a\x5b\x7a\xf7\x8c\xe6\x4a\x99\x3f\x36\x25\x0f\x8c\xb7\xcb\x45"}, -{{0x1e,0x2b,0xd5,0x48,0x7c,0x5f,0x5c,0xed,0x46,0x1f,0x60,0x4d,0xcc,0xb4,0xe7,0x8e,0xb9,0x16,0x08,0xf0,0xb8,0x21,0xf5,0xaf,0xc4,0xe3,0xe5,0x34,0xf7,0x96,0x03,0x92,},{0xef,0x82,0x54,0x75,0xcf,0x20,0x51,0xa2,0x01,0x7a,0xe5,0x32,0xf0,0x77,0xd9,0x67,0x74,0x34,0x7d,0x27,0x67,0xea,0x7b,0x45,0xf9,0xc1,0xb8,0x60,0xab,0x99,0x35,0x06,},{0x4d,0x33,0xc9,0x6a,0x2e,0x3a,0x5d,0xb7,0x39,0x1a,0xdf,0x65,0xc1,0xcc,0x35,0x65,0xfe,0x76,0xee,0xaf,0xd0,0xb5,0xc7,0xab,0xb0,0xb4,0x92,0xa0,0xb5,0x1e,0x1f,0xa3,0x36,0x39,0x94,0x6a,0x24,0x3b,0x2d,0xde,0xf3,0x57,0x55,0x22,0x98,0xce,0x0a,0xa9,0x5e,0xac,0x6f,0xbf,0xe6,0x60,0x98,0x82,0x71,0x87,0x7e,0xb2,0xa7,0xda,0x18,0x06,},"\x1d\xbb\xbb\x13\xcd\xad\x88\x85\x4b\x80\x9c\xed\xed\x27\x33\x43\xd3\x06\xa8\xde\xab\xf3\xff\x02\xc9\xce\xc6\xf0\x02\xb8\xe9\xe1\x0e\xf5\xd1\xb0\xf5\x71\x1f\x33\x26\x7a\xa9\x1c\x17\x1b\x61\xe9\x60\xf7\x40\x45\x7b\x81\xd7\x51\xa4\x73\xf4\x4f\x75\x0a\x08\x0c\xab\x80\xaf\x7c\xcc\xa7\xdf\xfc\xfa\xc9\xee\x4c\x39\xdc\x85\xcb\xdf\x51\x25\x9c\xcd\x34\x70\xd9\xba\xd3\xad\x30\xf4\xee\x5d\xbd\x4f\xac\x6b\xd5\xc6\xc4\xdf\x73\x11\xa4\x70\x04\x46\x95\xa7\xe1\xa7\xe1\x85\x72\x20\x75\x88\xaf\xa5\x7e\xeb\xcd\x4d\x57\x5b\x6d\x42\x44\x57\xee\x92\x46\x5c\xe1\x86\x3e\x3c\x67\x7c\xf8\x75\xfd\xb9\x8d\x40\x78\xeb\xe7\x14\x42\x60\x80\x70\x52\x57\x71\x44\xcb\x8e\x03\x59\xaa\x42\xad\x15\x5d\x79\xda\xe3\xde\xb9\x9c\x46\x32\xc1\x91\xc7\x99\xcb\xfe\x58\x7d\x95\x47\x87\x06\x8d\x66\x3b\xdf\xc0\xfa\xb1\x33\x4f\x18\x76\xbf\x49\x8c\x4d\xb5\xc5\x3d\xb7\xb0\x20\x4e\xd5\xa5\x21\xc6\x2f\x09\xea\xca\x8d\x01\x89\xf3\xb3\x94\x14\x3f\x29\xc4\x21\xcb\x5c\x8d\x07\xbd\x75\x1b\xaf\x4c\xbe\x3b\xf4\xbe\x17\x01\xdf\x4b\x22\x07\xdf\xb2\x90\x4d\x84\xf4\xdb\xda\x51\xcb\xa5\x76\xd5\xa5\xbb\x16\xef\xe6\x98\xed\xd6\x08"}, -{{0xf7,0x8d,0xb1,0x4d,0x6d,0x1a,0x64,0x3d,0xd7,0x73,0x5b,0xaf,0x26,0x35,0x32,0x12,0x44,0xe7,0xec,0x8c,0xa7,0x2c,0x5c,0x38,0xc9,0x8c,0x80,0x9d,0xb9,0xcb,0x5a,0x55,},{0x54,0x14,0xf7,0x5f,0x52,0xf3,0x86,0x4a,0xfb,0x0c,0x79,0xc2,0xc5,0xc1,0xd0,0x6b,0x4b,0xce,0x40,0x0f,0xbd,0xdf,0x17,0xfe,0x9c,0xfb,0x2a,0x8b,0xac,0x47,0xa0,0xdd,},{0xd7,0xcb,0xd4,0x18,0x1f,0x67,0x71,0x20,0x07,0xb7,0xf0,0xe1,0x84,0x52,0xe0,0xa0,0x24,0x46,0x4d,0x9d,0xc9,0xb5,0xff,0x9c,0xf6,0x69,0xd1,0xb9,0x11,0x69,0xd7,0x57,0x32,0x62,0xf8,0x33,0x36,0xb9,0x7c,0x86,0x1b,0xfa,0xb3,0xfc,0xf6,0x69,0x22,0x3c,0xe8,0xca,0xf3,0x19,0xf2,0x1d,0x23,0xf1,0xfa,0x33,0x1a,0x2d,0x89,0xb6,0xca,0x0b,},"\x05\xca\xf1\xb8\xed\xc3\xb1\x73\xfb\xc1\xed\x29\xb9\x5e\x2b\xf0\x6d\x81\x4b\xa2\x40\x7d\x4b\x31\xc7\x28\xd0\x4e\xc2\x73\xd2\x53\x94\x42\x3a\xc7\xd4\xff\xf2\xca\x36\xee\x90\x27\x30\x93\xc7\x56\xe2\xbd\x13\xc9\x6d\x4a\x3d\xc7\xf5\xbe\x17\x59\xfc\xd3\x28\xeb\x66\xc5\x88\x2b\x58\xfa\x45\x88\xe5\xb2\xa3\x71\x3a\x41\x54\xa2\x34\x0d\x0b\x06\xad\x01\x96\x01\xb0\xe0\x28\xe4\x97\xf8\x98\x25\x6b\x02\x8a\xf9\x5c\xd8\x16\x8d\xf5\xe5\x8a\x57\xcd\x1e\xbf\xc0\xa0\xc9\x1c\xed\x61\xdb\xb4\x80\xac\xa7\xdf\x8d\xca\x91\xeb\x16\xe9\x80\x07\xcd\x2c\xd1\xa2\x04\x5b\x0e\x44\x77\xd1\x2d\x5a\x40\x72\xf3\x65\x42\x65\x67\xc9\xd6\x15\x77\xf3\x48\x5c\x8f\x46\x60\x5e\x7f\x47\x5e\xf0\x4a\x39\x48\xf6\x0d\xba\x8c\x55\x08\xd1\x4b\xfd\xdb\x9b\x11\xdd\x04\x4e\xf2\xd8\x4c\x16\xb9\xa9\x03\x8d\x8e\x78\xed\xa4\x3b\x91\x29\x7d\xf3\x5f\x43\x61\xa3\x83\xb4\x1d\x49\x67\x7a\x68\x7d\x5b\x34\x4a\xd1\xab\x0f\xc7\x30\x17\xb3\xbe\xbf\x32\x30\x6f\xb3\xfd\x7b\x3d\x50\x71\xf3\xab\x5f\x6e\x49\xaa\x15\x54\x0c\xad\x65\x03\xbe\xa7\x78\x4c\xf9\x42\x18\x01\xce\x13\x85\x83\x98\x93\x36\x2a\x97\xfa\xe1\x21\x30\x0d\x67\x83\xaf\x0f"}, -{{0x7d,0xfa,0x32,0x8e,0x90,0xa1,0xb8,0x49,0xc2,0x19,0xe3,0xda,0x83,0x2d,0xf9,0xed,0x77,0x44,0x82,0x34,0xf0,0xd8,0x9e,0xa5,0xd1,0x7a,0x3d,0x64,0xe7,0x88,0x3d,0xaf,},{0xe3,0x0c,0xe6,0xfd,0x5f,0x58,0x00,0x38,0x9a,0x70,0xcd,0x11,0x73,0x64,0xf5,0x99,0x45,0xaf,0xb1,0x80,0xf2,0x29,0x92,0x73,0x60,0xb0,0x6b,0x48,0x35,0xf8,0xdc,0x91,},{0x1c,0x61,0xd5,0x3b,0x87,0x2f,0x8c,0xde,0x59,0x86,0x09,0x68,0x2c,0x79,0xf6,0xc5,0xdf,0x00,0x7c,0x51,0x3a,0x71,0xcf,0xb3,0xa0,0x6d,0xcb,0x82,0xd8,0x5c,0x4b,0x00,0xcc,0xc4,0x0b,0x00,0xe5,0x9f,0x59,0x53,0x93,0x08,0x8b,0x4c,0xd0,0x43,0x28,0x55,0xc6,0x7a,0x20,0x7d,0xa7,0x1f,0x87,0xe7,0x2c,0x40,0x9b,0x3e,0x50,0x27,0x95,0x07,},"\xe5\xe4\x95\xd6\x63\xf4\x72\x36\x71\x45\x32\x68\x7a\x24\x30\x8f\x94\x2c\xa9\xc3\x3e\x08\x8f\x7f\x10\x6a\x5a\x72\x35\x18\xca\xcb\xbe\xf4\xa6\x8c\x93\x9a\x69\x50\xb2\xdc\x25\x89\xf8\x2d\x35\x4e\x57\x52\x72\xd4\x2b\x13\x83\xd3\x15\xab\x8a\x20\xaa\x0c\xdc\x9d\x4d\xf6\x78\xab\x3b\x26\x61\x2b\x5d\xca\x66\xe7\x1f\x9f\x3f\xa7\xd9\xe7\x31\xdc\x48\x1e\x2b\xc7\x12\x7c\xea\x3b\x62\x03\xca\x6c\xd8\x16\x2e\x90\x88\x6a\x73\xdc\x46\xc8\x3d\xde\xfc\x4b\x9e\x2d\x53\xd2\x9d\xd3\x87\xc6\x24\xe0\x8b\xd8\xd5\x3b\xe9\x28\xa4\x0a\x9a\xa8\xae\x8b\x1c\x8d\x0f\xb6\xa7\xbd\x6d\xce\x5f\x62\x31\x5b\x7a\x21\x81\xf6\x27\xf2\x56\xbb\xe7\xe2\xa9\x5b\xf4\x64\xe6\x13\x22\x04\xc1\x74\x20\x96\x29\x84\x02\x35\xb2\xc3\x99\x13\x30\x1a\x4b\x40\x32\x5d\x11\x8d\x38\x4b\xc7\xac\x02\x8c\xd4\xf1\x27\x02\xe1\x61\x19\x1b\x14\x9e\x42\x09\x05\x8a\x55\x12\x2b\xbb\x8b\x22\xb2\x46\x83\xba\x4f\x8e\x2e\x6c\xcf\xc0\x8d\xc8\xc8\xb1\xbc\xfb\x6d\x60\xbd\x8f\x06\x21\x96\x93\x3d\xf3\x19\xab\x16\x90\x6d\x08\x57\x30\xeb\xa1\x72\x0d\x4b\x02\xc6\x7d\xaf\x38\xcc\xe6\xab\xa3\x8e\x25\xd6\x8e\xf9\x5b\x2f\x52\x19\x13\xa1\xd7\x7d\x5e\xb6\x50"}, -{{0x6c,0xe1,0x3d,0x3c,0x2e,0xc7,0x1f,0xed,0x83,0x13,0x1a,0x69,0xd5,0xd0,0x30,0x31,0x4a,0xb4,0x9e,0x65,0x65,0xef,0x68,0x16,0x3f,0xff,0x09,0xac,0x5d,0x9b,0x47,0xe7,},{0x9c,0x7b,0x11,0x18,0xfa,0xb9,0x1e,0x0e,0x7b,0x19,0x2a,0x23,0xd9,0x5f,0xb8,0x77,0xcb,0x79,0x36,0xcc,0x6c,0x8a,0x33,0x05,0x92,0xf4,0x8e,0x67,0x84,0xed,0xc2,0x92,},{0x60,0x8b,0x2b,0xf6,0xf6,0xda,0x05,0xc2,0xac,0x5b,0xbf,0xd7,0x95,0xa2,0xac,0x32,0xc7,0x9c,0x74,0x15,0x3f,0x94,0x31,0xde,0xa5,0x97,0x68,0xff,0x4c,0x22,0x5e,0x3b,0x69,0x3b,0x64,0x5a,0x50,0x67,0x66,0xb8,0x60,0x85,0x0e,0xe9,0x7e,0xa4,0x30,0x32,0xb0,0x5b,0x69,0xe5,0x67,0x67,0xe8,0xeb,0x9d,0x19,0x18,0xdf,0x9a,0xfb,0xa8,0x05,},"\x10\xbb\xc3\x11\xeb\x2a\x76\x5e\x01\x67\xff\x37\x61\x8f\xf7\x0e\x13\xf0\x2d\x7b\x06\x17\xae\x4a\xc0\x6b\xef\xbb\xe1\x49\xc9\x72\xa9\x94\xf6\x80\xca\x4d\xc9\xa9\x2e\xc7\xef\xa5\x39\x97\xfa\xd3\x56\xb9\xff\x4e\xbd\xee\x62\x95\x41\xd1\xf4\xde\xa6\x2e\xd0\xd2\x49\x4f\x9c\xcf\xdf\x07\xa9\x31\x04\x91\xf6\x1c\x4b\x3e\x27\x00\xb4\xa3\xc6\x68\xd6\x78\x32\x9a\x38\xc2\xef\xf9\xd8\xcb\xa4\x31\xfb\x95\x9e\x7f\x76\x55\xbd\x0f\xbd\x77\xd5\x3b\xbb\xc2\xeb\x8d\xc5\x1d\xd7\x18\xed\x98\x72\x8a\x18\x16\x86\xbe\x12\x2b\x84\x4d\x3d\xa3\x31\xe3\x29\xd3\x95\x9b\x59\x23\xf7\x73\x43\x25\xa0\x21\x02\x6e\x27\x54\xe1\x7a\x15\x10\x8b\xe8\x01\x46\x5a\xd9\x58\xdb\xcf\x21\xdf\x89\x0c\xfe\x5d\x5b\x88\x3c\xa4\x3c\x61\xce\xdc\xcb\xdb\x58\xb8\x49\xea\x75\x37\x4f\x1e\x91\x8e\x80\x3e\x57\x7a\x5d\xc7\xa1\xc1\x79\x36\xec\xcf\xcd\x34\x81\xbd\x2b\x1e\xb0\x75\xb8\x32\x37\xca\x6f\x3c\x07\xc1\x9e\x9a\xf9\x73\x12\x67\xbe\x82\xd4\x89\x8e\xee\x96\xeb\xc9\x00\xd4\x8b\x05\x9d\x51\xb0\xdd\x41\x5b\x1c\x89\x06\x60\xa8\x8d\x25\xf5\xc5\xf3\x5d\x8e\x45\xe5\x23\xe0\xce\x33\x36\x92\x3a\xb4\x36\x70\xe3\x5c\x50\x57\xd5\x6c\x75\x88\x76"}, -{{0xd4,0x5e,0xe6,0x9a,0x5f,0x1a,0x7c,0xfd,0xd0,0x34,0x3f,0x87,0x70,0xd1,0xc6,0xbc,0x02,0x6f,0x06,0x7a,0x70,0xdb,0xe8,0x39,0xa8,0x6f,0x2a,0xa0,0x68,0xc3,0x3f,0x81,},{0xfc,0x8d,0x9f,0xb0,0xe4,0xf3,0x47,0x93,0x09,0x07,0x55,0xe0,0x32,0x80,0x96,0xe0,0x1e,0x28,0x1e,0xa3,0x51,0xb8,0xd9,0x5c,0xd9,0x11,0x6e,0x13,0x1a,0x5c,0xa5,0x4e,},{0x15,0x6c,0x51,0xc5,0xf9,0x15,0xd8,0x9b,0x8d,0x14,0x00,0x35,0x0f,0x8f,0x21,0x7a,0x5c,0x02,0xe2,0x62,0x9e,0xde,0x9f,0x4a,0x30,0xb6,0xe7,0x1d,0x1e,0xa7,0xa9,0x53,0xcc,0x6d,0xb3,0x1b,0xa5,0xc7,0x78,0xc2,0x69,0x92,0x0b,0x64,0x9f,0xb4,0x22,0x1c,0x6d,0x38,0xcf,0x2c,0xea,0x2a,0x7d,0xe3,0xad,0x42,0x3e,0x04,0xfa,0xaa,0x06,0x07,},"\xeb\x5e\xd8\xab\x79\xcb\xfe\x61\xc2\x59\x81\xb9\xd1\xd6\xb7\x0f\x10\xb6\x01\x94\xb4\x16\x1f\xe1\x7d\x11\xaf\xf1\x76\x79\x94\xaa\x08\x13\xe9\xec\xe2\xf4\xc5\xd5\x31\xb9\x9e\x8a\xdf\x18\x88\xc3\x0a\x63\x89\x3e\xb4\x51\xaa\xf5\x5a\xcd\x5a\x52\xad\x8c\x40\x1f\xaa\x88\xd6\xea\xcf\x3e\x49\x47\x05\x66\x11\x4f\xd0\xc6\xa2\x74\xe9\x54\x48\x46\xb0\xae\x9b\xfa\x12\x4d\x79\x51\xeb\x26\x71\x5e\x19\x25\x3f\xf7\xed\xc8\xa7\x09\x65\x77\x6f\x23\xce\x46\x03\x1e\x03\x4a\x20\x07\x23\xba\x3d\x11\xe1\x1d\x35\x3d\x7e\x7c\xd8\x4a\xed\xe2\x67\xff\x64\xbe\xd4\x18\xcb\x9f\x28\xc6\x1c\xd0\xf6\x3b\x6c\xe2\xec\xae\x14\xb2\x0b\xc6\xbd\xae\xd8\xc4\x28\xba\xd1\x8b\xe4\xb7\xd6\x63\x38\x36\x4a\xcd\x80\x42\xa8\x25\x6f\x25\x8a\x69\x96\x9b\x8d\x3c\xa2\xea\xb3\xae\xa3\x70\x6e\x5f\x21\xc3\xb1\xef\xcc\x25\x4a\x82\x4b\xb4\xe7\xea\x7a\xba\x88\x27\xc8\xeb\x82\x78\x6c\x66\x5a\xa9\x73\x82\x19\x31\xff\x99\x0a\x63\xfd\x34\xa7\x4a\x6d\x8c\x22\xa8\x82\xb0\xb9\x35\x15\x2c\xcb\x36\xfc\xc7\x6f\x4e\xca\x65\xd6\x7c\x86\x80\x94\x2f\x75\xdf\xad\x07\x34\x39\xc0\x91\x60\x65\xe8\x38\x77\xf7\xba\x20\x93\x03\xf3\x35\x48\xd9\xe4\x0d\x4a\x6b"}, -{{0x8a,0x76,0xea,0xab,0x3a,0x21,0xec,0x5a,0x97,0x5c,0x8b,0x9e,0x19,0x7a,0x98,0x9e,0x8e,0x03,0x08,0x99,0xeb,0x45,0xd7,0x89,0x68,0xd0,0xfb,0x69,0x7b,0x92,0xe4,0x6d,},{0x2d,0x9c,0x81,0x3d,0x2d,0x81,0xe2,0x73,0x0b,0x0d,0x17,0xd8,0x51,0x2b,0xb8,0xb5,0xd3,0x3f,0x43,0x6c,0xab,0xaa,0x13,0xe1,0x41,0xca,0x1c,0xb7,0x85,0x01,0x43,0x44,},{0xfc,0xee,0xcc,0xa4,0xb0,0x14,0xfe,0xcd,0x90,0xb9,0x21,0xb0,0xfa,0x3b,0x15,0xae,0xaa,0x4e,0x62,0xca,0xa1,0xfb,0x22,0x72,0x9c,0x70,0x26,0x92,0x32,0xc3,0x3c,0xef,0x0d,0x0a,0xee,0xa6,0x64,0x32,0xc1,0x28,0xaf,0xb9,0xa3,0x64,0x6b,0xc7,0xf0,0x3a,0x12,0x77,0x4d,0xa8,0x75,0x83,0x98,0xc2,0xa0,0xdc,0xce,0x0b,0xbb,0xf6,0x74,0x0a,},"\xc6\xc7\x8f\x2e\x20\x80\x46\x1a\xed\x9f\x12\xb4\xf7\x7c\x98\x9b\x19\x71\x67\x80\xfa\xb6\x0e\x6e\xcb\x97\x93\xb4\xbc\x7e\xd6\x9e\x5f\x70\xfa\x6b\xdb\xa1\x6e\x9b\xd3\x19\x49\x69\xee\xa6\x66\x5a\xbf\xd6\x30\xde\xee\xfa\x3d\x71\x7b\x6d\x25\x4d\xd2\x4b\xc9\x7d\xde\x21\xf0\xf2\x9f\x9e\xd3\x4b\x8b\xd7\xa0\x13\x38\x0f\x4f\x82\xc9\x84\xfd\xbd\x95\xaf\x98\x05\xb7\x44\xbc\xd9\x52\xc5\xa7\x1f\xbb\x57\xd1\x1f\x41\x1c\x18\xcc\x30\xbc\x35\x94\xf7\xad\x82\x28\xcb\x60\x99\x39\x4a\x1b\x6b\x0a\x81\x85\x81\xbd\xf9\x3c\xce\x58\xf3\xa4\xa2\x3e\x55\xdb\x3e\x69\xca\x9d\x60\xcf\xb3\xa9\x07\xfb\x68\x32\x9e\x2f\xfb\x6c\x65\xf1\xe8\x28\xd2\x81\x27\x10\x9c\x9e\x9f\xb7\x01\x60\xf2\xef\x82\xa2\xee\x9f\x9b\xd1\x70\xc5\x1e\x13\xfd\x3f\xc1\x86\x6b\x22\xc7\x9f\xe6\xd5\x10\x12\x17\x97\x9d\xbe\x27\x24\xdc\xad\x8a\x9b\xc6\x9a\xcc\x42\xc1\x12\xdc\x69\x7b\xd2\x71\xee\xa5\x50\xe9\xe5\x04\x06\xbf\xd2\x82\x45\xb8\x3b\x8f\x01\x2d\x34\xdb\x6d\xbd\xd5\x5a\xe6\xe5\x75\x74\x5c\x15\x3d\x6e\x75\x34\x90\x10\x27\xea\xdc\x2f\xcc\x33\xa5\x28\x7d\xdb\xca\x6d\x3a\xea\xb8\x97\x22\x94\xdc\x6c\x71\x2b\x99\x42\x54\x72\x77\x34\x0e\x7a\xd1\x9e"}, -{{0x18,0xa8,0xf9,0x36,0x48,0xcd,0xcf,0x47,0x13,0x36,0x30,0xaf,0x1e,0x11,0xc0,0xce,0xea,0x3d,0xe0,0x73,0x27,0x31,0x4c,0x96,0x58,0x0d,0xf7,0x75,0x59,0x7d,0x7a,0x9c,},{0x29,0x12,0xf4,0x1a,0xb4,0xc8,0x7e,0x39,0x37,0xa0,0x33,0x31,0x80,0x2c,0xba,0x87,0x71,0x6b,0x4e,0xea,0x14,0xb9,0xfb,0xa6,0xf5,0x46,0xd0,0xac,0x2c,0x09,0x73,0xdf,},{0x3b,0x77,0x39,0x4c,0xd6,0x9f,0x8b,0x45,0xd0,0x0c,0xfe,0x3a,0x79,0xa7,0x90,0x06,0x28,0xa5,0x65,0x18,0xb3,0x79,0xed,0x8a,0x11,0x58,0x1f,0xc3,0xa3,0x76,0xe5,0xd6,0x68,0x07,0xdf,0x11,0xe7,0x09,0x04,0xf6,0x96,0xc7,0x41,0xd2,0x1d,0x13,0x93,0x10,0xfa,0x1b,0x89,0xa9,0x3b,0xdc,0x4d,0x2c,0x39,0x97,0x99,0x1f,0x52,0x20,0xee,0x00,},"\x59\x20\x93\xac\x7c\xd6\x71\xd6\x07\x0b\x00\x27\xed\xac\x1f\xb0\x15\xcc\x20\x5d\x78\xbb\x60\x3f\x37\x8e\xb9\xf8\xaa\x38\x8c\xa8\x30\xdb\x3c\xb2\x34\x20\xc7\xe8\x52\xdb\x0b\x55\x24\x1e\xb8\x8a\x02\xcc\x62\x7a\xa9\x41\x43\xbe\x43\x9a\xab\x4b\xf2\x63\x47\x57\x47\x04\x06\xe8\x42\xf2\x0e\xb1\x0f\x07\x00\xe3\xc2\xda\x36\x4f\x58\x8a\x80\x00\xf2\x38\x50\xc1\x2c\xe9\x76\xf3\x26\xd2\xdf\x1b\xac\x13\xe9\x50\x20\xb4\x12\xb1\x75\xbf\x74\xbd\x7e\xbb\xac\xf3\xae\x55\xc0\xda\xeb\xb5\xc0\x10\xbf\x80\x4f\xee\xe1\xd7\xd4\x9f\xae\x05\x0b\xea\x55\x99\x6f\x53\xcf\xe1\xf1\x5a\x0c\xf2\x07\x27\xdb\x4e\xe3\x11\xc2\x60\xba\xd9\x68\x2d\x7b\x96\x5e\x27\xa9\x49\x1f\x47\x1d\x4a\x47\x3a\xff\x64\x6c\x7d\x42\x4d\x5a\x0b\xdc\xbb\x8a\x02\x33\xf4\xb3\x06\x0d\xd0\x4c\x98\xec\x98\xdf\xd0\x5e\xc7\x24\x78\x84\xe2\xd8\xe1\x52\xd4\xae\x52\xb3\xd5\x86\x5d\x9e\xfd\x67\x06\xa6\x0e\x08\x8e\x1e\x7c\x9f\x62\x45\x10\xab\xc7\xa2\x04\x5a\x2c\x7a\x75\x88\xe2\x53\x5e\x73\x19\x1d\xd5\xcf\x05\x42\x15\x63\xf5\x56\xa1\x3e\x82\x36\x67\x03\x43\xcd\x5b\xa4\xd4\x66\xe2\x45\xc4\xee\x3b\x5a\x41\xe7\x0c\x9a\x0f\x5e\x6e\xa2\xc5\x59\xeb\xe6\x1b\xa8\x1e"}, -{{0x20,0x6c,0xd2,0xb8,0x11,0x4a,0xae,0x18,0x8d,0x81,0x86,0x2c,0xce,0xc4,0xcb,0x92,0xc4,0xef,0x5f,0xc7,0x8c,0x24,0x43,0x5a,0x19,0xf9,0xed,0x9b,0x8a,0x22,0xf4,0x7e,},{0x97,0xa6,0x7a,0xc2,0x81,0x1f,0x52,0x94,0x56,0xdf,0x53,0x27,0x37,0xd7,0x6b,0xed,0x7e,0x38,0x7d,0xa8,0x3b,0xd5,0x54,0x59,0x37,0x2f,0xdf,0xb2,0x7f,0xfa,0xcf,0xf3,},{0x73,0xa4,0x0d,0x9d,0xa0,0x8f,0xb9,0x8e,0xa2,0x5b,0x67,0xe7,0x21,0x55,0x7a,0x1a,0x51,0x22,0x52,0x94,0xd3,0x16,0xb5,0x31,0x49,0xaf,0x89,0x5f,0xa4,0xd6,0x3c,0xb4,0xa3,0xf5,0x6f,0x68,0x85,0x66,0xef,0x6d,0xa4,0x2f,0xd2,0x94,0x1d,0xff,0xa0,0x6d,0x49,0x7a,0xa9,0x02,0x16,0x5d,0x50,0x21,0x3a,0x62,0x14,0x11,0x62,0x99,0xa9,0x0c,},"\x48\x0c\x48\x00\xf6\x8c\x79\xf5\xdf\xc0\xc3\x66\x6c\x0a\xc4\x29\xb3\x0f\xe0\xc5\xfe\x84\x87\x50\xdb\x21\x71\x38\x0b\x80\xc8\xe9\xfe\xc0\xa0\x54\xb1\x6d\x08\x67\x4c\xef\xe2\xf6\x4e\xc2\x8b\xb6\xb0\x59\x6b\x35\x23\x55\x75\xf1\x89\xbe\xe2\x59\xac\xa7\x66\xc2\x22\xac\x0a\x46\xcf\x2a\xf7\x57\x74\xda\x4e\x34\xa0\xb5\x4f\xc2\xac\x49\xec\x8b\xed\xf4\x88\x7c\xd9\xb7\xbe\x4f\xdb\x7f\x68\x69\x02\xdd\xfa\xb0\x46\x27\xe2\x6e\xa2\xdc\x3d\x97\xd6\x2a\x4b\x15\x46\x18\x02\x18\xed\x8f\xa1\x13\x33\x48\x19\xb5\x27\x5c\xc5\x4a\xfd\xee\x44\x30\x90\x08\x59\x65\x07\x97\x16\x75\xe6\xd8\xb8\xa8\xed\xec\x47\x18\xf2\xd4\xbd\x73\x52\x13\xcb\xbd\x18\x79\x1f\xaa\x80\x54\x17\x49\x07\xa7\xac\x17\xd7\x14\x3a\x47\x57\xe4\x93\xbe\xee\xc4\x84\x9d\x0b\x83\x6f\x18\xbb\x2b\x3c\x90\x16\xf2\x5a\xf4\x7f\xb9\x61\x99\x25\x17\x20\x54\x9f\x15\xd1\x49\x50\x3d\x41\x09\x5e\x25\xf2\x62\x09\xda\xac\x39\x15\x44\x85\xc3\xde\xd7\xcb\x1a\x8c\x3e\x83\xa5\x2f\x5a\x06\xec\x09\xcf\x83\xdf\x00\x72\x6b\x79\x68\xf6\x4c\x0c\xba\xe2\x99\x51\x2f\xb4\x38\x56\x0f\x04\xb3\xb6\x44\x34\x6f\x93\x8a\xc8\xe9\x04\x86\x61\x4c\xd8\x44\xb5\x4e\xae\x07\x8b\xf6\x78\xb3"}, -{{0x59,0xb1,0x44,0xa7,0x08,0xab,0xec,0x97,0x27,0x29,0xa0,0x4a,0x6c,0x13,0xf0,0xea,0x02,0x0b,0x4e,0xd4,0xa4,0x82,0x98,0x02,0x3a,0x56,0x89,0x58,0xc2,0x12,0x15,0xec,},{0xc4,0xf4,0x72,0x00,0x92,0xed,0x61,0x79,0xa0,0x82,0xae,0x4d,0x61,0x45,0xdf,0x37,0x71,0x78,0x6e,0xfc,0xa9,0xbd,0x9b,0xb7,0x9c,0x9f,0x66,0x67,0xd2,0xcb,0x56,0xb3,},{0x1a,0x80,0x85,0x0f,0xcb,0xd6,0xe6,0x43,0xc6,0xba,0x8e,0xb6,0x84,0xdb,0xef,0x7d,0xf0,0x15,0x15,0x92,0x28,0xda,0xed,0xcf,0x06,0x04,0x70,0x91,0x86,0x05,0x4d,0xb1,0x85,0xaa,0x7b,0xaa,0xcb,0x09,0xd6,0xca,0xad,0x01,0x63,0x8e,0xff,0x8e,0x46,0x87,0x35,0xa6,0x01,0x24,0xde,0x0c,0x53,0x76,0xe9,0x43,0x40,0xe5,0x41,0xa9,0x80,0x07,},"\x38\x57\xbd\x26\x0b\x8a\xad\x9d\x07\x3f\x06\x76\x5d\x37\xfe\x89\x3a\x3f\x53\xe2\x3d\xe8\x66\xdd\xac\x33\x49\x5a\x39\xad\x33\xee\x9e\x9d\x5c\x22\x50\x2b\xc1\xc4\xb5\x47\x0d\x0e\x3f\x3a\x58\x52\x23\xfe\x4c\xb9\x3c\xc4\xad\x2b\x5b\xa6\xd7\x88\x26\xa5\x3f\xc0\x25\x3d\xc5\x80\xa2\x01\x8c\xc9\xff\x1c\xfe\xdb\xd3\xac\x0b\x53\x29\x2d\xee\xfb\xc1\x4e\x58\x9a\xcf\x49\x6c\xb5\xf7\x67\x01\x30\xfd\xbb\x6c\xf3\x8d\x20\x89\x53\xc0\x15\xa0\x47\x46\x75\xb7\x24\xbd\x10\x9f\x7c\xb8\x9c\x33\x01\x67\x51\xfe\x7a\xa7\x85\xd0\x99\xd0\x9a\xb2\x0d\xd5\x25\x8c\xd7\x64\xac\x8d\xaf\x34\x3c\xe4\x79\x0e\xad\x08\x63\xaf\x43\x12\x1a\xa5\x27\xa3\x7a\x11\x62\x8f\x47\x86\x96\x68\xf8\xea\xc0\x0d\x80\xb6\xbf\x99\x06\x66\x3d\x7a\x28\x99\xc1\xcb\x67\x8c\xd7\xb3\xeb\x3b\xc8\x02\x26\xb8\xb1\x3b\x6e\x46\x87\x7f\x38\xf0\x7c\x3d\x9c\x86\xd3\x36\x8b\xaa\xc4\xa6\xf6\xb9\x3c\xce\xbc\xec\x98\x11\x47\x4b\x6a\x6a\x4d\xa5\xc3\xa5\x96\x65\x71\xee\xd0\x5e\xdc\xc0\xe3\xfe\x7c\xd1\x59\x15\xc9\x1f\x44\xee\xe8\xc1\x49\xae\x45\x1f\x37\x55\x18\xa7\x9f\xb6\x00\xa9\x71\xa3\x9b\x94\x33\xdf\xa1\x9f\x91\x93\x1b\x19\x32\x27\x57\x47\xc2\x62\xee\xdc\xbd\x27\xf1"}, -{{0x8d,0x16,0x21,0xee,0xab,0x83,0x27,0x0d,0xe8,0x57,0x33,0x5c,0x66,0x5b,0xbf,0x57,0x26,0xe3,0x72,0x22,0x25,0xfd,0x01,0x6e,0x23,0xbf,0x90,0xab,0x47,0xae,0xec,0x3d,},{0xbe,0xcd,0xbc,0x02,0x4d,0xae,0x6a,0x94,0xed,0x4e,0x29,0xc8,0x0f,0x2a,0xff,0x79,0x6a,0xed,0x8f,0xeb,0x2c,0x1b,0x37,0x90,0xa8,0xc7,0x2d,0x7b,0x04,0x8a,0x2c,0x61,},{0xe0,0x8d,0x6c,0xaa,0x5f,0x39,0x32,0x7d,0x6e,0x66,0x52,0xed,0x74,0xdd,0x1a,0x37,0x84,0x4b,0x97,0x9f,0x5c,0xce,0x74,0x7a,0x60,0x6f,0x56,0x79,0xf4,0x89,0x8b,0xbb,0x76,0x43,0xdf,0x7e,0x93,0x1b,0x54,0xa2,0xb4,0x0e,0xbd,0xef,0xe8,0x30,0x03,0xf6,0x1c,0xa0,0xf1,0x11,0x12,0xf0,0x23,0xc6,0xa3,0xe8,0xcc,0x18,0xca,0xfe,0x5f,0x0d,},"\x97\xfa\xcd\xdc\x82\xcc\xcc\xcf\x78\x8c\x31\xb3\x30\x5e\x93\xeb\xa9\x56\xf8\x96\x13\xe6\xe5\x35\x42\xb0\x43\x26\x7f\xee\x54\x4c\x2b\x0a\x8a\xe8\x88\x6a\x31\xb9\xd3\x21\xa6\x3c\x27\x62\x3b\xae\xfe\xa8\x40\xb2\xa8\xaf\x5b\x23\x30\x19\x3f\xfb\x5b\xaf\x87\x3c\x33\x55\x28\xaf\xea\xe2\x16\x01\x63\xc8\x51\xc5\xa2\xe5\x81\x54\xa1\xb0\x56\x9c\x2d\x13\x66\xc0\x71\x04\x37\x62\x3b\x0e\x08\xc6\x86\xe5\x4f\xc2\x79\xed\x4c\x45\xf3\xe8\x56\x86\x83\x75\xf7\x82\x24\xc7\x77\xb1\x3d\x75\xde\x10\xd7\x91\x73\x55\x24\x25\xd1\x5a\x56\x19\x04\x15\x5f\x21\x17\xb2\xf1\x47\x13\xeb\x0b\x04\x64\x8a\x3b\xde\xb3\x30\x21\x67\xd1\x97\x3e\x78\x8a\x06\xcb\x00\xd4\x8c\xcb\x26\x9f\xa7\x1a\xf8\xba\x68\xea\xe5\x5d\xbb\xfd\x95\x94\xd5\xc2\xb4\xdc\x13\xae\x03\x21\x71\x85\x61\xac\xdf\x67\xdc\x8c\xfc\xc2\x5b\xc4\x6b\xb6\x6e\x09\x6a\x19\x41\xd9\x33\x52\x07\xd3\xf7\xd1\x1e\x89\x04\x90\x4f\xab\xe3\xa5\x0a\x38\x83\xe7\x07\x80\x47\xdf\x25\x2f\x38\xb6\x7c\xd2\x8a\x6a\xc4\x5c\x7d\x7a\x1d\x2a\x1d\xe8\xd4\x57\x47\xcf\x09\x30\x1e\x01\xcd\xaf\xd0\xcd\x99\xa6\xe9\x1b\x70\x4d\x50\x9f\xce\x69\x2f\xbd\xef\x2f\x71\xa5\xce\x0b\x35\xbc\x15\xc6\x5f\x87\x68\x24"}, -{{0xf2,0x73,0x5d,0x50,0xee,0x3a,0x9a,0x65,0xb5,0x8c,0x8a,0xcf,0x55,0x16,0x63,0xe9,0x88,0x09,0xec,0x40,0x6f,0x73,0xe3,0xe7,0xf4,0xe7,0x3b,0xc4,0xea,0x92,0x38,0x74,},{0xdf,0x48,0xa5,0xb9,0x4a,0x07,0xaf,0x3c,0x2c,0x99,0xb8,0x38,0x87,0x62,0x24,0x32,0x33,0xc8,0x50,0xdc,0x17,0x53,0x17,0xd6,0x02,0x63,0x8e,0x5b,0x86,0xab,0x49,0xed,},{0x69,0x42,0xa7,0x69,0x64,0x17,0xef,0xaa,0x59,0x1b,0x95,0xe1,0x1f,0x02,0xd7,0x63,0xbe,0xf5,0x27,0x9b,0x93,0x2a,0x8e,0x2a,0x7c,0xbb,0x9f,0x58,0x36,0x95,0xc1,0x4c,0xe5,0xcc,0x55,0x6b,0xec,0x66,0x79,0x9b,0x33,0xcb,0x59,0x2d,0xa4,0xdf,0x27,0x35,0xf9,0xee,0xf2,0xc3,0xce,0xca,0x43,0x62,0x16,0x4b,0x6c,0xc9,0x3d,0xa4,0xe1,0x05,},"\xae\x31\xe9\x4e\x71\x97\xe4\xe4\xd0\x23\x93\x48\x02\x5e\xd6\x68\x1e\x51\x3c\xe1\xa6\xe0\xaa\x0e\x5b\x97\x93\x73\x91\x21\x50\xef\x11\x3e\x50\xef\x05\x69\xc4\x83\xf7\x56\x8c\x4b\xbc\x47\x03\xc5\xda\xca\xa8\x0a\x0d\xe4\xe7\x38\x38\x3f\xa1\xf1\x0d\x6d\x40\x71\xa3\x1b\x99\xe6\x48\x51\x43\x97\x23\x16\xc8\x65\x22\xe3\x7c\x68\x87\xa1\xc3\x07\xb2\x9b\x0d\xd6\xf9\xf1\xb4\x38\x31\x0a\xf9\xd8\xd7\x34\x6f\xb4\x1f\x9b\x2d\xd2\xe8\x0b\x14\xc4\x5e\xb8\x7d\x4e\xd4\x8e\x37\xa5\x26\x0b\x52\x25\x7b\x3e\x99\x78\x7a\x13\xc5\x53\x92\xba\x93\x0c\x08\xe0\x24\x0e\x96\x0d\xef\x0c\x29\xb8\x55\x07\x45\xcf\x14\x9d\xee\x53\xa5\xd1\x74\xec\x06\x5d\x2d\x66\x77\xde\xe1\xfc\x42\x05\x70\x62\xc3\x4e\x27\xea\x5d\xbc\xdb\x86\x1b\x9f\x67\x0c\x60\x32\xc7\x84\x6c\xec\x8e\x87\xa7\xc9\x52\x0e\x27\x96\x7b\x01\x86\xee\x71\xb7\x7e\xd6\xd0\x29\xbb\xdd\x70\x94\x9c\xec\x4a\x70\x93\x29\xfa\x37\xfe\xe0\x02\x49\x0c\xc1\xbc\x4c\x2d\xf6\xf7\x63\xf9\x85\x8f\x33\xd7\x50\xc5\xb5\x05\xa6\x7e\x23\x70\x63\xc0\x48\x6f\x94\x56\xd3\xc6\x20\xd9\xac\x7c\x98\xf1\x38\x1d\xe0\xef\xfe\x41\xc1\x82\x59\x50\x4a\x15\x0d\x68\xa6\xa2\x8b\x0a\x3e\xea\x80\x3b\x85\x53\x15\xc9\xe0"}, -{{0xca,0xd9,0xd2,0x1a,0x01,0xc7,0xe1,0xd1,0x5d,0xf2,0xfb,0xd7,0x9c,0x51,0x6e,0xb8,0xc3,0x40,0x1e,0x9f,0xe2,0x84,0x67,0xcc,0x7b,0x21,0x67,0x9d,0x4e,0x33,0x1a,0x3d,},{0xa7,0xb5,0x5c,0x15,0xd6,0x79,0x0b,0x40,0x53,0x6f,0xca,0xe5,0xad,0x28,0x92,0xcd,0x66,0xb1,0x86,0x89,0xf4,0x99,0xc1,0xfd,0xee,0xa6,0x6d,0x4a,0x7d,0xf3,0x94,0x24,},{0x31,0x92,0x7d,0x01,0xdb,0x9f,0x24,0x72,0xf4,0xdf,0x6f,0x63,0xc1,0x8e,0xbd,0x83,0xc2,0xb1,0xaa,0xf8,0x8d,0x58,0x0e,0x84,0x88,0x54,0xdf,0x8c,0xba,0x63,0x95,0xd3,0xda,0x7b,0xd6,0xbb,0x9e,0xdc,0x1f,0xce,0x1c,0x7d,0x7e,0x13,0x60,0x55,0x8f,0xcd,0xdf,0xa9,0x39,0x15,0xbe,0x07,0x6e,0xfb,0x8e,0xa2,0xdc,0x5e,0xa7,0xb2,0x0d,0x0a,},"\x70\x70\x2b\xf1\x9c\x91\x9f\x98\x36\xde\xfd\x7b\x84\x6f\xd9\x99\x2d\x8b\x7e\xb2\xe1\x06\xae\xb7\x1e\x60\xa3\x1b\x4e\xa2\x5a\x41\xb2\x12\xdc\x7d\xe7\xc9\x1c\xbd\x61\x3d\x58\xd0\x59\x5d\xb8\x33\xcf\xe7\xe5\x05\x84\xf2\x55\x69\x60\x2c\x77\x44\xfa\x67\x5d\x15\x6d\x0f\x63\xcd\x2b\x7c\x08\x9c\x8a\x00\x68\x6a\x43\x71\x69\x82\x6a\x12\xdc\x48\x5b\x38\xc0\x68\xa8\x00\x71\x42\xe5\x16\x37\x47\x01\x1a\x07\xa4\x15\x68\x36\x22\xab\x1e\x23\xce\x57\x7c\x73\x2b\xa1\x4f\x40\x1f\xbc\x30\x43\xe0\x69\x3a\x92\x05\xc1\x9a\x92\x29\x8a\x3d\x9b\x08\xfb\x7a\xfa\xfa\xe0\xa9\xf0\x16\xbc\x75\x0e\xe6\x31\xa5\xf5\xda\x5d\xb6\xf9\xba\x26\x92\xc7\x4c\xaa\xae\xb4\xd0\x97\xe9\x0e\x3c\x02\xd2\xe3\xa7\xfb\x3a\xa0\x00\x04\x0b\x7c\x17\xb7\x45\x64\xe6\x46\xbe\xa1\x6b\xad\x61\x1e\xbc\x08\x59\xa3\x82\x88\x04\xab\x4f\x5c\xfb\xa4\x17\xd2\x54\x51\x5c\xa3\x62\x0a\x3a\xd6\x83\xc4\x6c\xa6\x26\x7b\xb4\x95\x39\xbb\x30\xe3\x69\x08\x7e\x67\x43\x8e\x94\x89\x56\x27\x50\xdc\xcb\xa3\xaa\x0b\x1b\x0a\x6c\x26\x70\x32\xd2\x0c\x2a\xdb\x75\xe6\x8d\xf1\x12\x3b\x52\x59\xbf\xe4\xea\xc6\xca\xdc\xa6\x77\x81\x38\xa3\x73\x18\xad\xb3\x0e\x8d\x66\x9f\x3b\xc9\x69\x2c\xc7\x4b\x68"}, -{{0xd9,0xbe,0x84,0x22,0x55,0xe9,0xa1,0x6b,0x0a,0x51,0xa8,0x67,0x42,0x18,0xce,0xe7,0xcd,0x9a,0x8b,0xdf,0x34,0x35,0x08,0x39,0x7f,0x4d,0xdb,0x05,0xf3,0xfa,0x00,0x82,},{0x79,0x31,0xbc,0x6d,0xfa,0x33,0x24,0x94,0x3a,0xab,0x18,0x3d,0x12,0x85,0x51,0x59,0x19,0x39,0x9f,0xfe,0x0b,0x71,0x06,0x77,0xf0,0x91,0x5d,0x3a,0x5b,0xe5,0x1e,0x92,},{0xc9,0x38,0x45,0x65,0x8c,0x95,0x60,0xd2,0xc0,0xe2,0x8f,0x28,0x2a,0xdb,0xd4,0x65,0x2b,0xaf,0xd3,0xbb,0x2e,0xde,0xc1,0x7c,0x94,0x87,0x8f,0x7b,0x94,0xd3,0xc7,0x7a,0xfe,0xc9,0x06,0xed,0x29,0x2a,0x8d,0xfb,0xf5,0xf8,0xe7,0xc1,0x18,0xe8,0xf2,0xca,0x33,0xdd,0xa7,0x90,0x9d,0x9b,0x69,0x5b,0x8f,0xf5,0xa1,0xc0,0xe9,0x7a,0xc8,0x07,},"\xac\x6c\x55\xb1\x34\x66\x3e\x41\xf0\x2a\x6d\xcb\x85\x49\xea\xa1\xc0\x13\xf5\x96\x58\xd8\x1d\x81\x2f\x95\xb7\x40\x09\x51\x37\x23\x67\x19\x45\xe1\x32\x4f\x90\xf8\xa3\xf9\x71\x36\x91\x81\xb5\x87\xba\xb4\x56\x65\xf7\x88\xd6\x63\xab\x78\x14\x0c\x5a\x22\xc1\xc1\x8d\x4a\xfe\xdc\x74\x48\xa7\x48\xaf\xe5\xbf\x23\x87\x00\x3c\x1d\x65\xab\x18\x48\x2e\xf9\x89\x22\xb4\x70\xda\x80\xad\x14\xc9\x44\x95\x1c\xe4\xae\xd3\x73\x90\xcc\xe7\x9a\x8e\x01\xb2\x4c\x7d\xfc\x11\x41\xc0\xec\xa2\xc7\xf7\x73\xed\x4b\x11\x80\x6a\x34\x61\x55\x13\x48\x6e\x4e\xe1\x1a\xf0\x80\x78\xa1\xb4\x05\x4c\xf9\x88\x02\x98\x60\x8d\xd9\xb3\xfa\xa1\xa2\x42\xa4\x52\xfe\x51\x16\x04\xb3\x10\x2c\x31\x3d\x14\xcc\x27\xc6\xf0\xf8\x47\x1d\x94\x55\x53\x17\xea\xa2\x64\xcd\xf5\x2c\x69\xe1\x8f\x46\x1e\x47\x90\x3d\x21\x29\x87\x16\xb1\x72\xee\x9c\xb1\x78\xf0\x8f\xf2\xd3\xc9\xc1\x62\x12\x1c\x2e\xd2\x1d\x87\x34\xb2\xf0\x63\x0d\x39\x91\x46\xcb\xf7\x6e\x02\x8a\x14\x3f\x2b\xf7\xbb\x50\xaf\x0f\x57\xb9\xba\x80\x21\xd2\x64\xb0\x0c\x66\x62\xf8\x4c\x86\xcb\x6d\x59\x52\xb3\xd2\x41\xf7\xdc\x3e\x70\x0c\x96\x61\x6c\xbc\xfb\x0d\x0e\x75\x3f\xfd\x5d\x21\xee\x32\x0e\x65\xe9\x7e\x25\xcb\x86\x09"}, -{{0xcf,0xc4,0x8c,0xc6,0xf6,0x58,0x11,0xfe,0x7d,0x7b,0xba,0x85,0xd1,0xcd,0x84,0x85,0x8f,0xd6,0xf7,0xed,0xd6,0x38,0xf4,0xf5,0x52,0x36,0x3e,0xe7,0x68,0x5f,0x69,0xca,},{0xd2,0x9c,0x10,0x69,0x4c,0x5e,0x8e,0x3f,0x34,0x47,0xed,0x78,0xd3,0x4d,0xbd,0x74,0xa2,0xb3,0x01,0x37,0x3b,0xa8,0x71,0xb5,0x85,0x0c,0x33,0x3d,0xff,0x7b,0xf8,0xd0,},{0x80,0xc5,0xd5,0x1e,0x96,0xd1,0xca,0xc8,0xef,0xd3,0x45,0x98,0x25,0xe7,0x9c,0x1e,0x9f,0x65,0xaf,0x70,0x1d,0x1d,0x29,0xe1,0xf9,0x5b,0x03,0x67,0x07,0x11,0x3b,0x77,0x98,0x4b,0x7b,0x33,0x50,0xf0,0x40,0x77,0x33,0x3c,0x95,0x7f,0x8f,0xbc,0x7d,0x9b,0x04,0x0c,0x36,0x26,0x51,0x41,0x7b,0x98,0x99,0x02,0x7c,0xd3,0x3e,0xdb,0x11,0x03,},"\x8e\x7d\xef\xb9\xd1\x6d\x03\x6b\xd6\x42\xcf\x22\x6e\x32\x77\x3e\x60\x53\x61\xc5\xec\x4b\x95\x12\x55\x78\x8d\xb0\xa0\x42\xc6\x3e\x5a\x43\x67\xd6\x15\x24\xf1\x0e\x62\x58\x99\x13\x25\xa3\x9a\xb6\xb0\x36\x12\x26\x0c\x3f\xe3\xdf\x20\xb3\x42\x02\xd3\x43\x95\xbd\x4e\xd4\x0b\xd6\x13\x73\xdf\x78\x1a\x4c\x8b\xcf\xbd\x15\x30\x10\x60\xf0\x74\x37\x73\x23\x33\xd8\xe4\x97\x36\x32\x2d\xee\x6b\x22\x43\x8e\x78\x7d\x88\x56\xb7\x0c\x26\xec\x57\xd6\xda\xde\x9c\x3c\x28\xe2\x72\x20\xc5\x67\x0e\x39\x35\x44\xed\x09\x59\x37\x29\x8d\xc3\xad\xc7\x38\x65\xf7\x77\xe9\x00\x37\xbd\xef\x83\x47\x16\x47\x6d\x78\xf4\xe6\xcb\x49\x61\xa4\xc6\x8a\x8a\x83\x63\x38\xa9\xf5\xda\x17\x9c\x4d\x5e\x93\xc3\xf7\x0d\xd3\x5e\xec\x70\x96\x53\xdd\x8d\xe3\x79\x96\xb1\x20\x56\xd4\xee\xfc\xb4\xb6\xb3\xc1\x3b\xa9\x84\xd8\x32\x27\x5c\x43\x86\xeb\xf4\xa8\xff\x7f\x07\x8b\xe3\xd4\x28\xc1\xe0\xd9\xb1\x62\x38\x1f\x06\xa5\xb7\xbb\x12\x70\x40\x03\xd9\x1f\x25\xd1\xd8\xfd\x43\x62\x6c\xe7\x0f\xff\x59\xd2\x92\x77\x68\xa7\x6b\xf7\xf9\xef\x76\xff\x95\x48\x9f\x38\xed\xcd\x1c\x9e\x9b\x8a\x8b\x0e\xf6\x6c\x32\x80\x57\x76\xd5\xae\x9f\xbd\x84\xa7\xaf\x4f\xa6\x56\x3e\xc7\x0a\xc5\x73\x3a\x44"}, -{{0x15,0xc9,0xf7,0xc4,0xd8,0x4a,0x5a,0x47,0x90,0x41,0x95,0x2e,0x6a,0x8c,0xac,0x24,0xe7,0x6f,0xd2,0xd2,0x75,0xc1,0x97,0xe6,0xb5,0x21,0x92,0x9b,0x43,0xba,0x6c,0x5d,},{0x86,0x33,0xc1,0x82,0x9d,0x29,0x09,0x1d,0xf7,0x1f,0xd5,0xc0,0xef,0x64,0x05,0x72,0xe4,0xb6,0x49,0x74,0xcd,0x09,0x7d,0xbe,0xbb,0xcd,0xde,0xba,0x04,0x16,0x47,0xc0,},{0x1e,0x36,0xbe,0xa5,0xa5,0x83,0x76,0x7e,0xbd,0x80,0x30,0x6c,0xab,0x23,0x31,0x55,0xb7,0xb4,0x28,0x14,0xb4,0x34,0x73,0xcf,0x45,0xcd,0xc5,0x03,0x9c,0x93,0x97,0x44,0xa9,0x69,0x4b,0x87,0x22,0x0d,0xaf,0x4c,0xcd,0x29,0xf2,0x5c,0xea,0x40,0x5e,0x7c,0x08,0xdb,0x2e,0xf1,0x7f,0x3f,0x03,0x4d,0xbb,0x49,0xcf,0xf6,0x02,0x83,0xe3,0x06,},"\x11\x73\x0d\xd4\x5d\xda\x80\xd8\x4d\x08\x0d\x92\xe9\xbd\xda\xee\xa6\x87\x8e\x4a\x0b\x3b\x51\x2d\x9e\xa7\x33\x80\x8e\x1c\xef\x51\xd4\x90\x48\xd6\xc7\x81\x16\xa4\xbd\xe3\xc6\x4a\xce\xaa\x52\xbe\xca\x86\xb3\x31\xab\x59\xe9\x18\x5c\x70\x28\x6a\x02\xbb\x5d\xd0\x4f\x5c\x7f\x4e\x9c\x7e\x44\x5e\x77\x45\x85\x65\xf1\x59\xc7\x83\xdf\xd4\xd9\x76\xa9\x10\xe9\x37\x78\x9d\x21\x41\xd4\x16\xed\x3a\x7f\x60\x8d\x26\x73\x7a\x86\xb2\x0b\x62\x4e\x3c\x36\xaf\x18\xd2\x5c\x7d\x59\xb8\xd7\x42\x7e\xc6\xc4\xd3\xd4\x38\xd7\xae\x09\x49\xdd\x7d\x74\x8c\x1f\xfd\x6f\x28\xe8\x28\x5d\x44\x04\x22\xd2\x2a\x37\x61\x20\x2e\x95\x84\xf5\xcd\xb3\x50\x45\x47\xaa\x4b\x68\x57\x30\xc9\x82\xcb\xa2\x13\xde\x08\x02\x0a\x5e\x4e\x46\xa9\x5f\xac\x4b\x48\x1b\xea\x0b\x63\x0a\xbd\x03\x0d\xdd\x33\x5a\x20\xfe\x2c\xf7\x09\x4a\xef\x48\x13\x95\x69\x91\x91\x3c\x68\x21\xf4\xb5\x41\x0d\xf4\xf1\x33\xfe\x63\xe2\x2c\x08\x09\x2a\x0a\x65\x97\x27\x22\xa2\x7a\xe4\x20\x11\xa8\x07\xc3\x27\xb4\x17\x23\x7c\x54\x01\x14\xee\xcb\x9f\x0e\x96\xcd\xa5\xdc\xf0\x24\x6f\x1d\x27\x17\xf4\x9b\x9c\xea\x9d\xc6\xa3\xda\x9b\x39\x6f\x02\x70\x52\x92\x26\xf5\xdc\xba\x64\x99\x91\x8a\x6c\x28\x9f\xe0\x55\xfe\xc8"}, -{{0x6d,0x2d,0x0d,0x82,0x3f,0x29,0x47,0x46,0xb9,0xa5,0x51,0x2e,0x14,0xe7,0x3c,0x1d,0x85,0x5b,0x5e,0x4b,0xca,0x65,0xfe,0x81,0x77,0x29,0x81,0x0c,0xc5,0xef,0x84,0x0d,},{0x1b,0x64,0x80,0xa6,0xa9,0x0d,0xfb,0x47,0x29,0x84,0x85,0x5c,0xef,0x6f,0x1a,0xb3,0x1e,0xb7,0xb3,0xf1,0x3c,0x8a,0xc0,0x0f,0xa5,0x56,0xd2,0x0b,0x53,0xe5,0xae,0x17,},{0xb5,0x15,0xf4,0x9e,0xb3,0x2a,0xd4,0x78,0x69,0x2d,0xf8,0x8f,0x07,0xb7,0x80,0x2c,0x6e,0x0e,0x53,0x27,0xaa,0x08,0xa6,0x36,0x6e,0x4c,0xb1,0xd1,0xe2,0x6f,0x9e,0x65,0xfc,0x81,0xab,0xeb,0xe2,0x21,0x5d,0x64,0x91,0x00,0xf2,0x75,0x98,0x27,0x3a,0x41,0x2b,0x62,0x4e,0x84,0x2d,0x81,0x30,0x40,0x37,0x97,0xe5,0x7d,0xec,0x97,0x5a,0x0a,},"\x87\x72\x72\x1f\x72\xea\xf7\xf7\x30\x40\xc0\x68\xa7\xc3\x75\x3b\xff\xca\x7d\xc2\xd0\x93\x0c\x65\x25\xf4\x25\xe6\x00\x5c\x25\xcd\x4c\x0f\xf5\x09\x5c\x9c\x61\xa5\xd8\xa1\x96\x7b\x8c\x86\x01\x0c\x88\x4e\x50\x9e\x6b\x16\x70\xf7\x90\x46\xe2\x29\x79\xeb\xd3\x54\x73\x40\x90\xd3\xad\xa2\x14\x35\xc1\xf8\x25\x4f\x7b\x52\x22\xcd\x55\x64\xf0\x64\xe9\x77\x64\x03\x66\x44\x9f\x4e\x50\x08\xf8\x70\xf9\xc4\x84\x05\x65\xbf\x4f\xb5\xf5\x74\xc9\x77\x4b\xa2\x56\x8e\x71\xa9\xcc\xd8\x2f\xfc\x59\xb6\x94\xf2\x6e\x7d\xe4\xce\x2e\x3f\xd8\x80\xa0\xee\xf3\x87\x93\x13\x33\xed\xe0\x0d\xcb\x06\x5e\x6d\x0f\x79\x59\x1a\x2a\xa9\x56\xdf\x19\x48\xa2\x65\xcb\x95\x75\x0d\x8a\x23\x3b\x15\xc2\x88\xa0\x54\x87\xc5\x15\x66\x3f\x93\xe7\x40\xfb\x15\x70\xfb\xe4\xbd\x80\xc6\x8e\x8d\x92\x97\x34\x5a\x8a\x01\xcd\xbd\x88\xf4\xa3\x9b\xed\x9c\x5e\xf0\x9f\x14\x4b\xce\x5d\xe5\x68\xbf\x37\x33\xbc\x53\xb2\x03\x9a\x29\xcb\x3e\x19\x45\x01\xad\xc1\xc1\x0e\x86\x38\x3a\xac\x8b\x0f\x85\xc6\x7a\x66\x89\xbb\xe1\x47\x0a\x39\x24\x76\x31\x34\x39\xca\x88\xd9\x8c\x02\x1c\x0e\xae\xc2\x5f\xb2\xf9\xa1\x60\xce\x5c\x78\x61\x70\xbe\x02\x38\xfb\x87\x85\xdd\x33\xbf\xa9\x05\x9a\x6c\x37\x02\xd0\xde\x05"}, -{{0xc0,0xcf,0x79,0x9a,0xf7,0x39,0x5b,0xf2,0x7b,0xaf,0xa3,0x6c,0xab,0x43,0x70,0x45,0xe3,0x9c,0x90,0x3b,0xf8,0x07,0x54,0x83,0x19,0xce,0x44,0xf2,0x87,0x49,0x4f,0xbb,},{0xaf,0xbf,0x55,0x0c,0xa2,0x90,0xc9,0x05,0xbd,0xd9,0x2f,0xc8,0x83,0x1e,0xbe,0x3d,0xfe,0xb6,0xda,0xae,0x4f,0x56,0x00,0x52,0x53,0xcc,0x50,0x95,0x1e,0x50,0xed,0xc2,},{0x5b,0xba,0x01,0xa4,0xc7,0xb2,0x55,0x42,0xd0,0x69,0x12,0xde,0x70,0xaa,0x1e,0x22,0x04,0x23,0xfd,0xf8,0x33,0x8a,0x9e,0x69,0x33,0x95,0xcb,0x6f,0x0d,0xc1,0xfb,0xfd,0x01,0x8e,0x3c,0x77,0xe5,0x0a,0xef,0x90,0xa9,0x08,0x0f,0x30,0xf1,0xf5,0x79,0x2b,0x24,0x31,0x07,0x8f,0xe6,0xe3,0xe0,0x04,0x64,0x24,0x5e,0x17,0xcd,0x8d,0xc1,0x07,},"\xdb\xe6\x57\x80\xe9\x68\xde\x9e\x40\xff\xb5\x7c\xf5\x9a\x60\xfd\x93\xb3\xf9\xa5\xe7\xd8\xed\x51\x80\xad\xbc\x57\x8c\xa1\xbc\x48\xbd\x9f\xb6\x0a\x13\x24\xc9\xc2\xc1\x14\x14\x79\xa0\xdc\xf0\xf1\xd0\x7e\x84\x93\x65\x26\xdf\x42\x33\x3c\x0d\x77\x3e\x3f\xed\x9e\x40\x38\xde\x5b\x95\xad\x90\x5c\x92\xcb\xe0\x40\x48\x7b\xf5\x5e\x10\xe1\xed\xb4\x29\xa0\xec\xc4\xe0\xe8\xd0\x0a\x98\x8a\x9c\xd5\x3e\x2e\xb3\x72\xf4\xfc\x4c\xd9\x53\x7b\x26\x9b\xa3\xa2\x3c\xef\xbc\x8d\xf6\x47\x6e\x75\x43\x4b\x81\xd9\x3e\x88\x91\xbf\x41\x7c\x82\xe3\x63\xf3\xe4\xab\xf8\x0a\x4f\x73\xac\xa8\x4a\xc7\xdf\x63\x37\xf5\x36\xd6\x3d\x93\x9d\x92\xcb\xa6\x4b\xe7\x42\x22\x11\x16\x06\x9e\xf2\x51\xab\xba\x0b\x00\xaf\x01\x71\x8b\xb5\x80\xdd\xbe\xb7\x99\x73\xef\x10\xa6\x8b\x4d\x0f\xa0\x23\xd6\xeb\xd3\x07\x9d\x6b\x32\xa1\xaa\x20\xa2\x1e\x92\x02\xf2\x75\x90\xc3\xf0\xc0\xcc\x25\x30\x73\xc3\xf8\x22\xaa\xc4\x59\xd3\x9f\x50\x75\x8b\x70\xc0\x07\x10\xa3\xc9\x84\x38\x41\x65\x08\x52\x2e\x51\x2a\xda\xa0\xaf\xd5\x03\xa7\xce\xb0\x4f\xb9\x4a\x4a\x93\x2c\xe8\x0c\xd5\xa7\xf1\x1b\xb8\x61\x26\x3f\x58\xe5\x74\x9d\x54\x2a\x11\x0d\xe7\xc7\x68\x9d\xfc\xb0\xc5\x1a\xfa\x9d\x54\xa5\x8f\xf8\x9f\x3f\x67"}, -{{0xcd,0xaa,0x50,0xe8,0x52,0x7d,0xc7,0xa5,0x0f,0xb3,0x7e,0x28,0xfa,0x8b,0x95,0x68,0xc3,0x7e,0x85,0x67,0xe0,0xb4,0x99,0x99,0x7b,0x9a,0xed,0x67,0x61,0x80,0xc3,0xb0,},{0x7c,0x56,0xe1,0x64,0x51,0x02,0x68,0xc1,0x82,0xb4,0x23,0x74,0x79,0x04,0xf1,0xd3,0xa5,0x80,0x93,0x30,0xf6,0xe1,0xb2,0x92,0x66,0xec,0x46,0xe7,0x3b,0xe1,0x55,0x0f,},{0x13,0x7b,0xd1,0x0a,0x50,0xef,0x60,0x93,0x84,0xfe,0x66,0x87,0x68,0xfb,0x87,0x1d,0xe7,0x41,0xca,0x0f,0x53,0xff,0x84,0x77,0xd7,0xeb,0xfa,0x90,0xaa,0xfd,0x5e,0x26,0x81,0xfd,0xf1,0xb8,0x92,0x50,0x46,0x3c,0x15,0xdb,0x8e,0x17,0xa5,0x88,0x25,0xfe,0x94,0x27,0xde,0x08,0x9c,0x34,0xde,0x13,0xcd,0x07,0xbb,0xa1,0x8d,0x4a,0xa4,0x0d,},"\x94\xfc\xfb\xaa\xa3\x03\xde\xce\x7b\x90\x8f\x87\x4c\xc5\xf0\x95\x06\x1f\x17\x54\xbb\x35\x78\x0d\xb6\x66\xb6\x3a\xb8\x29\x08\x11\xbf\x1c\x52\x1a\x7f\x8f\x78\x5e\xa2\x70\xdf\xb3\x9d\x0d\x6e\xd9\x5a\xb7\x19\x55\xa1\x1f\xfa\xea\xa2\x68\xe0\x81\xff\x3e\x4f\x24\x25\xb4\x18\x80\xa9\x87\x15\x1e\x67\x8e\x89\x11\x13\x50\x94\x2d\x82\x0c\x3e\xec\x36\x21\x24\x26\x66\x3b\xe1\x75\xe5\x28\x6b\x4a\xd1\xcc\x80\x4e\x3e\x3a\x03\xb9\xfa\x3e\x82\x83\x8e\xbb\xc2\x61\x5a\x64\x5f\x2c\xa1\x46\x8a\xc4\xa1\xcd\xbe\x52\x37\x61\xe8\x3f\x43\x81\xb0\xc8\x55\x0a\xe5\xe8\xc8\xcd\x1f\xda\x57\x19\x14\x36\xe2\x7c\xb8\x83\xbc\x64\xbe\x86\xa9\xdc\x61\x10\xef\x34\x01\xd8\x8a\x7d\xeb\xd1\xb7\x01\xd9\xc2\x57\xa6\x82\x6c\xf0\x1e\x9e\x29\x22\xe3\xae\x57\x7f\x28\x34\x27\x5f\xb0\xec\xda\x80\xed\x8c\xf1\x80\x1e\x0b\xc5\xe0\x1e\x26\xa7\x7c\x48\xbd\xf4\x6a\x5c\x48\x94\xd2\x2a\xb5\x3e\x74\x18\x27\xe2\x4b\xed\x5f\x07\x50\xff\xad\x05\xe5\x3f\x1d\x5e\x61\xdf\xd3\x16\xb1\x91\xd9\x79\x7e\xf7\x13\x13\x1a\x8b\x43\x0a\xbe\x3f\xac\x5f\x3c\x4a\x2c\xa0\x21\x87\x8b\x15\xad\xc8\xc5\xf5\x42\x11\x42\x60\xe6\x87\xa9\xd1\x99\xd2\x30\xc4\xe0\xd3\xfc\x69\x69\x93\xb5\x9c\xcf\xa3\xff\xa9\xd8\xd2\xfb"}, -{{0x0f,0xde,0xa9,0xbe,0xe6,0x28,0x8f,0x94,0x7e,0x0a,0xdb,0xdd,0xa4,0xdf,0xb2,0xba,0xa0,0x38,0x91,0xaf,0x25,0x02,0x4a,0x5e,0x13,0x8a,0xc7,0x79,0x84,0xd0,0x05,0x07,},{0x70,0xab,0xd8,0x64,0x30,0xd7,0xe8,0xd6,0x32,0x09,0xc8,0xb3,0x73,0xec,0x4e,0x4b,0x79,0xe9,0x89,0xe6,0x72,0x5f,0xac,0xef,0xba,0xde,0x3c,0x75,0x74,0xd2,0x3c,0xd0,},{0x80,0xc4,0x2d,0xd5,0xdf,0x03,0xb2,0x85,0xa8,0x6a,0xc9,0x5c,0xe6,0x66,0x9f,0x78,0x6a,0x97,0x8a,0x81,0x3a,0x9d,0x7b,0x8c,0x6a,0x23,0xde,0x76,0xfb,0xd0,0x9b,0xdb,0x66,0xc5,0xdd,0x1c,0xc9,0xf1,0xa1,0x76,0xcb,0xa3,0x88,0xd5,0x05,0x17,0x64,0xa3,0x2f,0xa2,0x7f,0x00,0x28,0xba,0x48,0x98,0x06,0x8b,0xd0,0x1a,0x3e,0xe1,0x72,0x08,},"\xcf\x72\xc1\xa1\x80\xa2\xbc\x37\xd8\x47\x8d\x9a\x7a\x39\xac\xf0\x3b\xf2\xa5\x07\x90\xf7\x90\x2f\x81\x12\x12\x22\xd3\x1d\x3e\xc9\x16\xf4\xf2\x4c\xef\x9d\x7c\x41\xdc\x02\x1b\x0e\x84\x87\xbb\x89\x2e\x47\x30\x5e\x54\x52\x03\x03\xe8\x9b\x30\xb2\x63\xda\xc4\xa9\xba\x37\x5d\x46\xc4\x0f\xcf\x40\x05\x35\xc9\x59\xd2\xb7\x46\xa7\xfc\x97\x0c\xf6\x5b\x47\x2e\x84\xb5\xf1\xd0\xeb\xad\xcf\xa1\xae\xd6\xfc\x47\xfa\xcc\xe1\x6a\x36\x6a\x3b\x1d\x6e\x51\x68\x13\xc1\x96\x09\x75\xf8\xf2\xb4\x30\x42\xfb\x4e\xea\xab\xe6\x3c\x6f\x65\xdb\x45\xdd\xb7\xdb\x88\x8a\x19\xa9\xd7\xba\x6c\xa4\x79\xfc\xd7\x0c\x5d\x1e\x97\x0f\x12\xc1\x4f\x4d\x24\xfb\x7e\x2f\x35\x7b\xd3\xa9\x4a\xa1\xb8\x68\xcc\xc0\x84\x7f\x2e\xef\x21\x85\x3e\x25\x3b\xaf\xbf\x07\xc4\xe6\x17\x6a\x1e\xf0\x77\x16\x78\x41\xeb\xbe\x56\x29\x33\x71\x57\xf3\x9f\x75\xc7\x1d\x21\xe7\xe9\x6c\x51\xa1\xb1\x6f\xa8\xdc\x60\xf0\xb1\x27\x9f\xcd\xa2\x64\x1f\xc8\x59\x1e\x3c\x49\x2f\x15\xbf\x83\xca\xf1\xd9\x5b\x2c\xd9\x13\x32\xf1\xb4\x20\x2f\xe7\x28\x62\xca\x2e\xa2\xef\x92\xc1\x1d\xb8\x31\xd8\x2f\x8f\xc3\xd4\x1f\xe2\x9a\x76\xc2\x11\xa7\x58\xe2\xf7\x1b\xd8\x9d\x2c\x66\x10\xf2\x01\x42\x9f\x34\x8d\x56\xe1\x0e\x3b\x7a\xf5\x3e\x27"}, -{{0x03,0xd5,0xe4,0x66,0xf8,0x29,0x8a,0xb5,0x43,0x8a,0x30,0x97,0x6d,0x13,0x22,0xa7,0x21,0x5a,0x64,0x2d,0xd5,0xfb,0x4c,0x3f,0x85,0x19,0x40,0x9a,0x75,0x22,0xf0,0x92,},{0x4b,0x3e,0xd4,0xdb,0x08,0x0e,0x2a,0x45,0x2e,0x16,0x91,0x2c,0x14,0x50,0x44,0x24,0x92,0x0a,0x60,0x97,0x56,0x04,0xe4,0xf3,0x79,0x25,0x8d,0x1c,0x8b,0x19,0x3d,0x6f,},{0x6d,0x7e,0x46,0x58,0xf2,0x6f,0x33,0x7c,0x98,0xe0,0x3f,0x13,0x54,0x2e,0x2f,0x39,0x44,0x0f,0xf7,0xbf,0x8d,0x88,0xf3,0xf6,0xdf,0xa4,0xd6,0x49,0x48,0xcd,0x96,0xb7,0x90,0x51,0x49,0x2f,0xc2,0x8f,0x65,0xf2,0xcc,0x0d,0x23,0xa0,0xc4,0xd5,0xe2,0x30,0x7b,0xb1,0xc4,0x7e,0x11,0xe5,0x3b,0x37,0x1f,0x09,0x1b,0x69,0xf8,0x0d,0xbd,0x05,},"\x1b\x47\xb7\x00\x13\xcb\x53\xe1\xf8\xf4\x97\x1e\x0f\x39\x56\x3c\xe8\x7e\xdb\xc2\xce\xdd\x99\xe5\xa3\x55\x85\xdf\x8b\x00\xa8\x52\xf7\xb9\xc9\x7c\x7e\x4a\x54\x65\xfc\x56\x05\xae\x8c\x5c\x36\x57\x0a\x99\x20\x1a\x7a\xd6\x03\x12\x87\xef\x0c\x7b\x2b\xa6\xe5\x7b\x05\x6d\x0f\xc8\xd6\xca\x43\xbf\x6c\xbd\xab\x09\x89\x34\xb4\x03\x19\x7b\x52\x5d\x22\xd4\x5e\x6b\x29\xc7\x8f\x8d\x61\x83\xe4\x1f\xfe\x19\x7d\xae\x25\xba\x22\xb0\x66\x69\xae\x05\xba\xdd\x7e\x1d\xa6\x93\x2a\x7d\x05\x4c\xba\xb3\xf5\x4e\x51\x46\x22\x3a\xd8\x67\x12\x31\xbc\x16\xfe\x62\x67\x9b\xd2\x81\x7a\x6b\x80\xe6\x53\x99\x8c\x49\x49\xf8\x1f\xf5\x3b\x61\x73\x16\x3e\x11\xda\x3e\x6d\x3c\x76\xd8\x4c\x71\x32\x25\xb4\x17\x3d\x6b\xf0\x6a\x85\xb6\x98\x8a\x48\xbe\x43\x59\xcb\x51\x55\x03\xca\x56\x3f\x43\x53\xf8\xe7\xd4\x5e\x4d\x94\x46\x2c\x89\xa0\x4a\x00\xf1\xb3\xb0\xca\x64\x22\xd5\xdb\x02\x9c\x50\x7d\x46\x48\x34\xa2\x0c\x78\xa7\x13\x66\x1d\x84\xed\xff\xc4\x96\xd6\x92\x82\x61\x98\x94\x43\x7b\x44\x87\x95\x4c\xbe\xa2\xaa\x72\x61\xe6\xa6\x2b\x68\x51\x15\x4a\x5d\x25\xfb\x6b\x4f\x09\xc5\x94\x73\xd3\x85\xce\x03\xe9\x1b\xa8\x65\xea\xb6\x6c\x58\xc0\xab\xb0\xb7\xa7\x8e\x4b\xe9\x27\xe5\x54\x60\xcc\xd7\x0d\x82"}, -{{0x76,0xcc,0x18,0xa1,0xda,0xff,0xfa,0x10,0x05,0x86,0xc0,0x6a,0x7b,0x40,0xf7,0x9c,0x35,0xfe,0x55,0x8c,0x33,0x9c,0x29,0x99,0xa5,0xf4,0x38,0x75,0xcf,0xad,0xe0,0x3e,},{0x4b,0x9d,0xa8,0xd2,0xf1,0x37,0xdc,0x6c,0x85,0x7a,0x99,0xa5,0x99,0x8d,0xd8,0x9d,0xd5,0xf0,0x59,0x71,0xa2,0x1e,0x8c,0x77,0x66,0x70,0xeb,0x47,0xbc,0x12,0x70,0xa5,},{0xdb,0x74,0x75,0x1c,0x66,0xe6,0xb1,0x86,0x60,0x44,0xdd,0x9a,0xe9,0x9f,0x19,0xe6,0x33,0x4f,0x17,0x9e,0x79,0xd8,0xb8,0xe0,0xc8,0xcd,0x71,0xd2,0x2c,0xef,0xb9,0xea,0xb7,0xe3,0xe7,0xa9,0xc2,0xda,0x22,0x5f,0x2a,0x9d,0x93,0xa3,0x13,0xd1,0xcb,0xf1,0xb7,0xfe,0x25,0x97,0xb8,0xd7,0x02,0xbf,0x30,0x17,0xa6,0xa6,0xbc,0x7b,0x7b,0x06,},"\x45\x22\xb1\xd8\x23\x73\xf7\xa3\x18\x22\x1e\x7e\x57\x61\x75\x03\xdd\xf4\x4f\xd5\x39\x97\x52\x2a\x1d\x96\x3c\x85\xb7\x08\xd0\xb2\x45\xde\x37\x2a\xd5\x2e\xc7\xf5\x4f\x62\x13\xd2\x71\xf7\xc9\x1d\x5a\x1d\x36\xd1\x34\xdb\x38\x9d\xf0\xb0\x81\xa0\x6b\xc0\xc7\xa4\x87\x5f\x72\x40\x92\x79\x31\x72\xc9\x11\x56\x41\xc6\xd0\x54\xf1\xd9\x92\xe0\xfa\xe4\xdf\x58\x69\x5f\x0e\xa3\x44\x9d\x7a\x4b\x3a\x88\x57\xe1\x98\x03\xfe\x49\xb6\xd5\x2c\x9f\xf3\x74\x6a\x57\x4a\x27\x56\x95\x65\x79\xf9\xfb\x80\x9a\x0e\xde\xc9\x2c\x55\xe9\x5f\xfe\xfa\x3d\x05\xf1\x65\x82\x2f\x46\x4a\x21\x99\x9f\x29\x69\x1f\x67\x44\xac\x5a\x3e\xe4\x90\x17\x88\x06\x45\xe8\x37\xed\xeb\xfd\x2e\x0f\x24\x99\x7f\x04\x11\x45\xa7\x2e\x23\x76\xad\xa2\x83\x18\x6c\xa2\xb8\x36\x36\x29\x77\x19\x5b\xae\xe3\x0a\x3a\xcc\x81\xb2\x43\xf3\xee\x37\x6a\x2c\x47\x64\xc7\x83\x66\x7a\x4b\x11\x77\xe7\x95\x1d\x3e\x3c\x7b\xe4\xf1\xbd\x7a\xe8\xc6\x0f\xd5\xfb\x0f\xd9\x1f\x0c\x1c\x14\xd0\xd2\x32\x7e\x8f\x20\xd9\x2c\x0d\xfc\xc5\x38\x70\xe9\xd9\x9f\xdb\xf9\xdd\x9a\x17\xe8\x82\x50\x9a\xe7\xba\xa8\x65\x3e\x39\xed\xc8\xee\x56\x90\x00\xd6\x24\xcb\x93\xa0\x75\x4a\x79\x8d\x1f\x81\x1f\x6a\x0e\xf5\x50\x1a\x17\xbc\xf2\x5f\xd0\xf9\x16\x26"}, -{{0x71,0xad,0x98,0x0d,0x58,0xad,0x8e,0x7d,0x33,0x30,0x66,0x89,0x35,0x89,0x36,0xa3,0x72,0xd5,0x19,0x0b,0x24,0xec,0x7f,0x9b,0xde,0x74,0x9c,0xb8,0x11,0x50,0xef,0xda,},{0xfd,0x35,0xa7,0x5f,0xe5,0xab,0xc2,0x01,0x04,0x69,0x1a,0x24,0xa4,0x65,0x94,0x40,0xb5,0x5a,0xea,0xea,0x90,0x2a,0xc3,0xbe,0x27,0x4a,0xf2,0x7a,0xa8,0x31,0x28,0x69,},{0x81,0x67,0x0b,0x10,0x29,0xe4,0x81,0xe9,0xff,0x3c,0x17,0x1f,0x05,0xc1,0x68,0x61,0xc8,0x46,0xee,0x79,0xcd,0xf2,0xe2,0x1e,0x3b,0xf9,0x52,0xbc,0xfa,0xc9,0x75,0x65,0xf2,0xb1,0xdc,0xed,0xf6,0x9d,0x2e,0x7e,0xb3,0x5c,0xaf,0x56,0x62,0xe8,0xbc,0x67,0x1f,0xbb,0x96,0x75,0x6a,0x63,0xa5,0x96,0x26,0x4d,0x1b,0x7f,0x4a,0xf9,0x7e,0x06,},"\xe8\x7a\xe0\x73\xff\x5d\xcc\x54\x85\xa1\x99\x40\xe4\xe3\xff\x26\x3a\x06\x18\xa9\x02\x5a\xd4\x03\x2d\xfb\x36\xd1\x71\xce\x88\x1f\x71\xc1\x8a\x49\x21\x0e\xb4\x58\x19\x80\x61\x42\xe2\xf0\x0d\xb3\x04\x18\x35\xbf\x2c\x3b\xcc\xf1\xdb\xa0\x2b\x8b\x5a\x5b\xda\xf8\xfe\xa3\x16\xc0\x62\x3d\xd4\x8a\x56\x4e\xc1\x66\xf0\x37\xd5\x87\xc8\xc0\x16\x84\xe5\xe5\xc0\xba\x9d\xba\x4d\x23\xb4\x9a\x03\x09\x24\x4e\x28\x2a\x51\x40\x86\x22\xed\xb0\x57\x04\x74\x7e\x0c\xde\xec\x97\x68\x93\x77\x70\x71\x09\x89\x72\xc1\x13\xa8\xab\x63\x9c\x31\xf1\x61\x32\x33\xee\x46\x0e\xea\x8a\x8c\x10\xe1\xe6\xe1\x52\x21\x45\x29\x87\x8c\xf1\xad\xae\xaf\x78\xcf\x19\xba\xc7\x13\x61\x81\x5b\xf5\x79\x55\x49\x8f\xab\x4f\x0f\x2b\x75\x86\xc8\x6f\x9f\x4c\x2d\xdf\x89\x72\xf9\xb9\xe0\xeb\x63\x6d\x84\xbc\xc1\x43\x85\xb2\xd0\x38\xbe\x55\xa9\x63\x70\x2e\xfe\x22\x5a\x50\xbd\xd0\xc4\xda\x92\xa2\xa6\xa0\x91\x00\xea\x04\xa2\x11\xd3\x96\x45\x8d\xce\xb4\x48\x71\x16\x83\x7d\x13\x9e\xb0\xf1\x22\x53\x8e\xd3\x98\x6a\xd0\xaf\x4d\xa2\xdf\xfc\x89\xf3\x26\x9c\xa8\x85\x38\x08\x6e\x69\x1e\x5b\xea\xe9\x58\x1e\x7c\x63\xd8\xe6\x12\xda\x2c\x47\xf7\x4d\xde\x1d\x94\x95\x1e\xad\xb0\xdf\x60\xc3\x89\x7d\x2a\x30\x95\xc5\x06\x09\x3b"}, -{{0x61,0x59,0x4e,0x24,0xe7,0x5f,0x99,0x6b,0x4f,0xb6,0xb3,0xe5,0x63,0xf6,0xa4,0xf9,0x91,0x5c,0xfa,0x65,0xdd,0xb1,0x99,0xb0,0x1f,0xed,0x7f,0x8e,0xd7,0x82,0x4e,0xcb,},{0x86,0x27,0xd2,0x14,0x15,0x79,0xcd,0x25,0x21,0xaa,0x07,0x68,0x00,0xac,0x35,0x4b,0x9e,0x3a,0x47,0xd7,0x1c,0xed,0xc8,0x54,0x74,0x34,0x26,0x82,0x25,0xe3,0x30,0x05,},{0x63,0x02,0xb3,0xff,0x27,0x10,0xbe,0x30,0x6c,0x92,0xb9,0xaa,0xe3,0x0d,0x23,0xc3,0xd4,0xbe,0xff,0x39,0x4e,0x63,0x20,0x1e,0x6a,0xd1,0x17,0x13,0x34,0x5c,0x4f,0xcb,0x5c,0xc8,0xd3,0xdd,0x10,0xad,0xfb,0x82,0xbb,0x11,0xa1,0x89,0xce,0x7e,0xc3,0xe4,0x22,0x27,0x27,0x62,0x4f,0xc1,0x78,0x81,0xc1,0x47,0x88,0xd2,0x71,0x0e,0x16,0x08,},"\xbc\x01\xb0\x8c\x7c\xaa\x23\x61\x00\xa0\x12\xa7\x26\x47\x7d\x0e\xc3\x89\xdb\xfa\xda\xc7\x3d\x51\x06\x42\x4c\x5d\x1f\x3d\x1c\xef\x16\x95\xcf\xd9\x3a\x70\x62\xec\x8b\xf1\x06\x70\x47\x85\x49\x20\x16\x2f\x65\x13\x57\xbe\xdf\x1c\xd5\xa9\x2e\xc2\x9b\xdb\x5d\xff\x71\x6e\x8f\x60\x25\x51\x5a\x95\x49\xba\x36\xcd\xc3\x5c\xed\x7c\x5c\x0c\x36\x8e\x6c\xd9\x2f\x2f\x10\xae\x14\x6a\x20\x72\x8c\x37\x4b\xba\x50\x96\x41\xce\x88\xcb\x42\xff\xf0\xce\xdf\xd9\xfd\x67\xf3\x10\xf9\xd0\x1a\x3f\x36\x90\xeb\x21\xdb\x17\xbc\xe6\x7a\xe3\x5c\x4c\xd2\x4c\x20\x9f\x09\xf0\x44\x75\x9d\x8d\x5a\x7d\x24\x8e\x2b\xd9\x66\x52\x4b\xa8\xc0\xc2\x89\x74\x72\x6b\x43\xbd\x05\xde\x84\x34\x33\xcc\x40\x05\x98\x92\x29\x74\x62\x3d\x9a\xcb\xfd\xc7\x61\xc4\xc0\x43\x75\xa9\x52\xce\x54\xca\xff\xaa\x96\xac\xff\x6d\x9d\xc2\x78\x74\x2a\xf4\x76\xe1\x86\x5c\xb8\xc2\x0d\x13\xd1\xc1\x90\x08\x63\xbc\xa2\x31\xe4\x4c\x6b\x0d\x47\xcb\x41\xd5\x10\xf7\x95\x8f\x48\xf3\x04\xd0\x3d\xa0\x33\x48\x4a\x3e\x1f\x27\x3f\xaf\x69\x83\x37\x5b\x7d\x3b\xe0\x3d\x8a\x0a\x00\x2d\xef\x63\x65\xbe\xb2\xfa\x8c\xcf\x1a\x94\x98\x7a\xdc\xd3\x3d\x0d\xa1\x17\x7f\xc5\x15\x9b\x6e\x56\xd0\x04\x30\x1e\x92\x1d\xbc\x12\xec\x0a\x73\xf4\x13\xcf\x2c\x48"}, -{{0x54,0xe6,0xbb,0xfb,0xf8,0xc0,0x6f,0xf2,0xc0,0x66,0x31,0x8c,0x2e,0xbf,0x03,0xd5,0x06,0x54,0x7b,0xf4,0x3c,0x2d,0x7a,0x5d,0x4d,0xf3,0x05,0xa3,0x03,0x2b,0x71,0x38,},{0x3b,0x71,0xaa,0x1d,0xef,0x66,0x6d,0x91,0x88,0xf4,0x03,0xf8,0x2e,0xd3,0x04,0x54,0xab,0xa5,0xbc,0x9f,0x47,0x0f,0x6e,0xb9,0x88,0xda,0x18,0x7c,0x92,0x52,0x32,0x84,},{0x3d,0xf4,0xd0,0x90,0x79,0xf8,0x30,0xe3,0xf9,0x82,0x28,0x36,0x81,0xba,0x37,0xb5,0x0f,0x3c,0x73,0xde,0x2c,0x5d,0x22,0xa2,0x91,0x35,0x8e,0xbb,0x1f,0xb8,0x54,0xe5,0x10,0xf6,0x3f,0x9a,0x48,0xe9,0xff,0xf7,0xfd,0x83,0x11,0x30,0x2e,0xa3,0xe9,0x69,0x39,0x4e,0x6d,0x49,0xc9,0xe3,0x18,0x20,0x54,0x94,0x2f,0x6a,0x74,0x4c,0xee,0x03,},"\x03\x18\xd7\xcb\x48\x05\xaf\x98\x21\xdd\x3f\x91\x4b\x0e\x07\x6f\xea\x04\xa7\xd2\xdb\x3a\x59\xa0\x0a\xff\xea\xd3\x32\x5a\x2b\xe4\x0c\x1f\x87\xf5\x32\x76\xa8\x55\x26\x04\xf2\x28\xb9\x76\xe2\x88\xb9\xbe\x90\x6a\x7b\xd2\x5b\x2f\xfa\xb8\xa8\xaf\x5d\x0f\x6e\x08\x78\x6f\xd0\x34\xe2\xfe\x1e\xb7\xee\x03\x39\x79\x86\x0d\xd1\xe5\x32\x72\x87\xe9\xe6\x15\xf5\xdc\x5a\x96\x0f\x17\x02\x6b\x56\x84\x2f\xc8\xd4\x4c\xad\x00\x2e\xdc\x85\x01\xcf\xb9\x56\x00\x15\x02\xe4\xdd\xc8\x1a\x77\x00\xd9\xc0\xbe\x88\xeb\x4a\xaa\x64\xa6\xcb\xc3\x9d\xe8\x2f\x13\xc1\x10\x86\xde\x1a\x42\x70\xd3\xaf\x97\x28\x4b\xac\x1c\xae\xf1\xd3\xed\xaa\x10\x71\x66\x6b\xd8\x3b\x2e\xde\x39\x62\xd9\x8b\x9d\x93\x49\x7d\xdf\xd8\xe9\x7d\xab\x30\x89\x95\x0c\xf3\x0e\xd1\x1d\xb7\x7a\xd1\x43\x7a\x0a\xf5\x88\x9d\x8e\xfc\x44\xe6\x12\x42\x0e\x39\x07\x26\x7d\xf3\xac\xff\x4b\xd3\xfb\x6e\x8c\xa5\xba\xdf\x8e\x72\xf9\xde\x39\x52\x86\x53\x05\x85\x24\x45\x6a\x81\xda\x5f\x84\x98\x2a\xfa\xc3\x4b\xef\x5f\x71\xe9\x1f\x8f\x90\x93\x8a\x6f\x5f\x1f\x28\x77\x16\xde\x56\xa0\x94\x6d\x26\x1e\x87\xbc\x77\x5c\xe1\x89\xe4\x1a\x77\xba\xed\xe7\x32\x0a\x3c\x60\x8f\xc9\x71\xe5\x5d\x0a\x77\x3c\x4d\x84\x8d\x42\x86\x37\xf1\x1b\x4e\x44\x60\x39\x0c"}, -{{0x68,0x62,0x06,0x1b,0xe0,0xde,0x9d,0xfd,0x99,0x81,0x18,0x20,0x4b,0x2b,0x98,0xdb,0x3c,0xe7,0xd7,0xe8,0x19,0xdb,0xc1,0x07,0x94,0xaf,0x0a,0xb2,0xb0,0x6e,0x84,0x34,},{0x9c,0x5f,0x7c,0x22,0x65,0xdd,0xe1,0xb2,0x5e,0x4f,0x27,0xec,0x71,0x58,0x0d,0x52,0xdc,0x89,0xf2,0xc3,0xa7,0x12,0xbc,0x1a,0xd5,0xd6,0xd6,0x9e,0x71,0x1e,0x08,0xd4,},{0x96,0x5e,0xdb,0x34,0xe8,0xab,0x8b,0xc3,0x20,0x4a,0x32,0x01,0xd2,0x21,0x86,0x37,0x2d,0xe4,0x24,0x26,0x00,0x29,0x7c,0xfd,0xb5,0x7a,0xa1,0xdf,0x07,0x4e,0xc5,0x0d,0xdf,0x10,0x10,0x5e,0x9d,0x4c,0x89,0xa2,0x66,0xc3,0x4d,0xb7,0x77,0x2a,0xa9,0x4c,0xba,0x94,0x64,0x29,0xe6,0x8b,0xa6,0x2b,0xf9,0xa0,0xac,0x90,0xf5,0xf0,0x5b,0x02,},"\x17\x40\xdd\xe8\x43\x4a\x0d\x68\x99\x25\x67\x9b\x0c\x18\x03\x00\xcd\xbd\x0c\xf6\xa8\x9a\xd8\xfd\xe3\x46\x53\x31\x6c\xee\x4c\x57\x1a\x41\x05\xc9\xe9\xe0\x28\x42\x38\xfe\xf2\xc3\x8a\x09\x15\x7c\x5d\xb9\x43\x40\x57\x1b\x39\x0a\xdf\xb6\x9f\xf4\xc0\xdc\x50\x53\x25\x3a\x67\x9d\x42\xcc\x1f\x1b\xf1\xff\x42\x92\x29\xea\x0a\x50\x44\xc6\xf7\x95\x64\xe0\xdd\x28\x7f\x53\xf0\x15\xb8\x31\x87\xd9\xad\x27\xd9\x10\x39\xaf\x06\x2c\x43\x7b\x15\x75\xa0\xea\xb6\xae\xb8\xaa\x0d\x27\xb2\x76\x65\xd6\xde\xa9\x04\x1f\xf9\x96\x3a\x31\x18\xb3\x29\x8a\x85\x44\xe3\xfd\x69\xac\x68\x77\xe3\xe4\x05\x2f\xe4\x42\x2b\xf0\x35\x60\xb2\xc5\x7e\xc5\x31\xee\x8b\x5f\xf5\x3c\x28\xdb\xde\x35\xbb\x45\xc3\x50\x77\x63\x6e\x6f\x84\x1b\x59\xd7\xeb\x77\xbc\x77\x91\xb6\x09\x38\x58\xa3\xa8\x0a\x3a\xa6\xd7\x78\xdb\xf5\x3d\xb9\xd0\x61\x19\xc5\x0b\x71\xc7\x91\xc0\x49\x5c\x57\x6d\x1b\x59\xd3\x96\x87\x3e\xd8\x71\x48\x53\x52\xc8\x29\x9a\x35\x9d\xa5\xee\x9d\x7f\x36\xed\x14\x55\xf8\x98\x51\xa3\x08\x51\xbe\xa7\x19\x68\x5a\xec\xd0\x8f\x25\x56\x26\x09\xdd\x10\x66\x30\x73\x52\x77\xe1\xd6\x51\x9b\xb1\x68\x7d\xe8\xb8\xc6\x8b\x96\x71\x45\x2e\xdb\xb3\x49\x1d\xa2\x64\xcd\xfa\x00\x17\xc5\x12\xd2\x76\x97\x59\xcb\x92\x5f\xb6\x64"}, -{{0xb2,0x25,0x0b,0xbc,0xb2,0x68,0xd2,0x47,0x7c,0x83,0x12,0xb1,0x90,0x0f,0xd9,0x99,0x82,0xba,0xa2,0x9a,0x68,0x97,0x4f,0xbf,0x87,0x78,0xa1,0x22,0x8d,0xc9,0x75,0x50,},{0x44,0xaa,0x8d,0xf1,0x18,0x16,0x74,0xb0,0x5a,0xde,0x98,0x0f,0x7e,0xdd,0xba,0xf3,0xbd,0x74,0x22,0xa9,0x20,0x28,0x7c,0xb2,0xd2,0xdb,0x59,0xa0,0x63,0xee,0xbf,0x74,},{0xf2,0xb8,0xd9,0x2e,0xd5,0x1e,0xbd,0x10,0x00,0xbf,0x9d,0xd3,0x41,0x1a,0x9f,0xa9,0xe7,0xae,0xe5,0x4c,0x4c,0x86,0xe2,0x4a,0xd0,0xf9,0xad,0x5c,0x55,0x64,0x3a,0x12,0xd6,0x80,0x01,0x9c,0xa0,0x3f,0x21,0x6b,0xd4,0xbd,0x32,0xc9,0xce,0x1c,0xd8,0xa5,0x28,0xc3,0xff,0xaa,0x5d,0x5b,0x1d,0xc9,0x1a,0x4b,0xe5,0x6f,0x0e,0x2c,0x5e,0x06,},"\x7e\xf0\xae\x13\x36\xa6\xfa\xb3\x7f\x99\xda\x5f\xa7\xd0\xde\xc7\x40\x9c\x07\x26\x23\xea\xd8\x4f\x24\x1d\x53\xd0\x59\x6b\x46\x17\x05\xfb\x1b\x3c\x53\x7d\x36\xb8\x9e\x89\x60\xfe\xbb\x4c\xdc\x0d\x42\x7c\xe2\xfc\x1b\xe5\x8d\xbb\xce\x15\x1e\x35\xac\xd8\xb6\xac\xe4\x0a\x19\x82\x29\x14\xa4\xbd\x8c\x4a\xf6\x32\xf1\x36\x41\x8a\xc4\x9b\x18\x4d\x55\x19\x3e\xbc\xc3\x2d\x0d\x79\x87\x09\xb1\xa8\xfe\x29\x4f\xba\x8a\x1f\xe7\x2d\x97\x6b\x44\x00\xd4\xa3\x93\x24\x23\x11\xb0\xf8\xcc\x99\x4e\x89\x47\x5b\x00\x38\xae\x5d\x89\x14\x93\x8e\x8f\x6e\x87\xc6\xf5\x0b\x9d\x65\x6c\x45\xd7\xb1\x42\x31\xef\xed\x97\xf3\xc9\x06\x68\x91\x36\x70\xbf\x5b\xe2\xef\xd5\xc2\x70\xc7\xcb\xaf\x01\xe8\x57\x2e\x98\x00\x97\x8d\xfe\x2e\x10\xa2\xfc\x04\x40\xb8\x55\x62\x9b\xf9\xcd\x40\x9e\xa9\x41\xcb\x69\x22\x6c\xac\x77\x1b\x15\xea\x77\xc0\x32\x68\x48\x80\x6f\xf8\xd2\xe2\x01\xe6\xe2\x6c\xd5\xf4\x54\x30\xda\xdc\xff\x8f\x59\xc3\x21\xc1\xc9\xc6\xa2\x9b\x94\x88\x29\x35\x44\x7d\x3e\x6c\x2e\x88\x04\xb1\x16\x15\x76\xbd\xf0\x32\x0f\xe5\x3c\x30\x7d\x9c\xde\x42\x60\x77\xa7\x67\x7c\xde\x3c\x1b\xc8\x3e\x18\xe6\x0a\x0c\x4e\xe6\xdc\xcd\x87\x7c\x21\x3a\x8e\x4c\xca\x64\x0e\xe0\x49\x29\x80\x45\x70\xae\x1f\x96\x15\x7c\x04\x35\x7a"}, -{{0xb8,0x09,0x36,0x1f,0x55,0xcf,0xe8,0x13,0x7f,0xbd,0xa8,0x80,0xfc,0x62,0xcb,0xe4,0x4c,0x21,0x6e,0x14,0x18,0x93,0x34,0x63,0x02,0xb3,0x36,0x04,0x5d,0xe2,0x18,0x78,},{0xfd,0x23,0xe4,0x2f,0xf0,0x66,0x44,0xea,0xd3,0x47,0xab,0xcc,0x1b,0x3e,0x03,0xb0,0xe8,0x85,0x93,0xb6,0x12,0x54,0x98,0x1d,0xd8,0xae,0x59,0x45,0x4e,0x61,0xb3,0xe0,},{0xb5,0xb5,0x95,0x0d,0x37,0x72,0xd2,0xee,0xf8,0x8e,0x1b,0x0f,0x5d,0xf5,0xff,0xae,0x2f,0x21,0x03,0x88,0x5e,0x71,0x44,0x6d,0x34,0x6f,0xbb,0x5d,0xae,0xf9,0x49,0x67,0xa6,0xb7,0xb6,0xe4,0xbe,0x88,0x51,0x10,0x06,0x58,0x76,0xc6,0x65,0xb7,0x81,0x2d,0xe4,0x6a,0xd3,0x1e,0xc3,0xbf,0xcb,0xea,0xee,0x13,0xed,0x0c,0x1e,0x0b,0x30,0x0e,},"\x17\xac\xe1\x97\xd0\x83\xaa\xf1\x72\x6f\x53\xe5\xef\x81\xb5\xa8\xc0\x92\x22\xf2\x60\xee\x5f\x1f\x54\x04\xab\x78\xd9\x00\xd4\x89\x68\x84\x49\xb8\x43\xba\xd3\xc4\x98\xaa\xc6\xd8\x0b\x46\x39\xb7\x6e\x6e\x81\xc5\x52\x76\xa6\xf9\xc7\xce\xcd\x70\xb7\x1a\xaa\xf2\x01\x8e\xf7\x6c\x0e\x30\x15\x4a\xae\x86\xa5\xc8\x6d\x4e\x8d\x0e\x4e\xc6\x8c\xc4\x27\x06\x0b\xd5\x65\x14\xf7\x23\x80\x86\xbb\xef\x5b\xfc\xa1\xf5\x67\x1b\x18\x04\x18\x38\xfd\x01\x35\x72\x44\x3d\xba\x48\xfb\xdd\x95\xca\x74\x0b\x0d\xaa\x43\x27\x16\x4a\x1e\x34\x67\x72\x49\x70\x8f\x77\xbd\x79\x3e\x7c\xaa\x66\x38\xb5\xdc\x9f\xbe\x6f\x0d\xfd\x41\x20\x20\x90\x97\x20\x9c\x93\xce\xdf\xaf\x21\xb6\xbf\x59\xca\x6e\x99\xe6\x20\x96\x39\x44\x4f\x0e\x82\x7b\xbc\xc0\xa6\x1c\x3a\x23\x7c\xa2\x2a\x28\x32\x13\x22\x3a\xb6\x58\xe7\x12\xc7\x55\x62\x38\xd3\xa5\xfe\x31\x72\x2d\x65\xf5\x70\x6e\xf6\xd6\x4d\x73\x23\x2d\x30\x43\x22\x0f\x14\xe5\xcf\xd3\xc2\xc8\x3a\x83\xd6\x8e\x20\x27\x4b\x6f\x96\xb2\x9d\xe0\x40\xce\xc8\x47\x50\x30\xb6\xa8\xa8\x7d\x29\x80\x8d\xd3\x81\x79\x5c\x3d\x22\xac\xf5\xdc\x19\x3b\x72\x0d\x95\xa7\x52\xd9\xf1\x23\xc2\x09\xff\xba\x00\x4e\x48\xdd\x06\xdd\x8c\x9e\x17\x2b\xc9\xe0\x87\xd8\x0b\xc5\x21\x6c\x0b\x0b\x6e\x77\x03\x12\x41"}, -{{0xee,0xef,0x80,0x74,0xc2,0xeb,0x9a,0x1c,0xee,0x2f,0x2d,0x3b,0xb0,0x53,0x25,0x54,0x6a,0x9f,0xb7,0xcb,0xe4,0x4b,0x59,0x94,0x61,0xfc,0x58,0x85,0xf5,0xfd,0x9c,0xac,},{0x9b,0x89,0x29,0x41,0xa0,0x57,0x3b,0x7a,0x16,0x73,0xef,0x48,0x0f,0x08,0x11,0x68,0xd9,0xb7,0x49,0x6a,0x81,0xf9,0x17,0x7d,0xc4,0x27,0xca,0x1f,0x84,0xcb,0xbf,0x7d,},{0x6f,0x71,0x01,0x98,0x4f,0xd6,0x89,0x2e,0x21,0x44,0xb7,0xd4,0x56,0x19,0x83,0x0c,0xae,0xb6,0x71,0x3b,0xfa,0xb4,0xee,0xbb,0xe2,0x17,0xc5,0xbe,0xcd,0x24,0x9b,0xd9,0xd7,0x52,0xeb,0x76,0xe9,0xfa,0x99,0x5e,0x7c,0x71,0xff,0x7d,0xf8,0x6b,0xb2,0x60,0xcd,0xda,0x17,0x3f,0xf5,0xde,0xec,0x6a,0xf2,0x04,0xb7,0xdd,0xe0,0x11,0xde,0x09,},"\x9a\xe3\x9f\xea\xde\x90\x5a\xff\xcb\xed\xd2\xe7\x2a\x6f\x24\x29\xb3\xd1\x10\x8e\x5b\xc1\xa9\xdb\xaf\x49\x0a\x62\x99\xbc\xcd\x94\xac\xc4\x13\xad\xac\xc9\x18\xb1\x4a\xfa\x85\xc7\x8b\xc1\x68\xcc\x00\x74\x0c\x3d\xa0\xe0\x81\x83\x91\x5f\x79\xb7\xfe\x38\x68\xce\x2a\x7e\x88\x6b\x32\xad\x45\x00\x98\x05\xbf\xb8\x1b\x8c\x07\xb3\xb1\x02\x24\x20\xc0\xf0\x09\xb8\x89\xd7\xfc\x22\xfd\x19\x97\xae\x34\x19\x84\x38\xca\x94\x77\x85\x75\x12\x2f\xca\xaf\x96\xe6\x50\x2c\x33\xa7\x5a\x12\x9a\x2d\x0d\xbb\x07\x3d\x93\x82\x0d\x9c\x96\x68\x3d\xb3\x18\x99\x0b\xe3\xfe\xf4\xca\xfc\x89\x0a\xfb\xd9\xb1\x50\x4c\x74\x39\xa0\x8a\x06\x5e\x78\x14\xee\x4f\x9b\x6f\x57\xee\x16\xba\xed\x3f\x0e\x3a\xa3\x5d\xd2\x3d\x35\x28\xa4\x58\x91\x9a\xd7\x70\x48\xb4\xe2\xe6\x17\x23\x46\xbe\x24\x9a\x50\xaf\x02\xbc\x6c\x85\x33\x04\xc2\x08\xae\x0b\xa0\x27\x71\x26\x2a\x0d\x8a\x46\x5f\x71\xfa\x06\x35\xe5\x3e\xb2\xef\x0a\x84\x7d\x56\xa0\xbc\xd7\xdd\x3f\xe0\x77\xc9\x2b\xcd\xca\x30\x69\xa4\xa6\x82\xa2\x85\x99\x28\x31\x5c\xe3\xeb\x44\x5c\x60\x72\xa7\x14\x92\xee\x82\xe1\x72\xa2\x0b\xe0\xb6\x48\xb7\x56\xe6\xc7\x75\x37\x6f\x0c\x7c\x3d\xf8\xe6\x42\x88\x08\x9c\x2f\x81\xce\x95\x93\xc6\xe0\x8b\xb1\xcc\x1b\x27\xfc\xbd\x39\x2f\xc7\x95\x2c\x55"}, -{{0x61,0xfa,0xeb,0x15,0xf8,0x57,0xf6,0x55,0x78,0x62,0xc8,0xb8,0xc7,0xef,0x41,0xf8,0x05,0x45,0x52,0x09,0x96,0xfc,0xc1,0x12,0x7b,0x8c,0x24,0x91,0x82,0x22,0x01,0xae,},{0x60,0xa2,0x90,0xc0,0xfc,0x42,0x5a,0x08,0x74,0x67,0x3d,0x94,0xf9,0xbb,0x14,0x00,0xf9,0xda,0xcd,0xe9,0x95,0x4f,0x9f,0x5b,0x05,0xdd,0x48,0xab,0x74,0x7a,0x39,0x50,},{0x31,0xf9,0x0f,0x50,0xb2,0xdc,0x70,0x5f,0x1d,0x92,0xf1,0x2c,0xa9,0x97,0x5d,0x76,0xf1,0xb2,0x82,0x6a,0xda,0x3c,0xc1,0x85,0xb0,0xed,0x6c,0x83,0x86,0x07,0x77,0xbd,0x8c,0x48,0x9b,0x59,0x85,0x5a,0x91,0xf6,0x48,0x39,0xd4,0x9b,0xa4,0x67,0x98,0x5a,0xbb,0x37,0x6c,0x47,0xa4,0x90,0x8b,0x27,0x1b,0x8f,0x77,0xc5,0x8d,0x01,0xfd,0x04,},"\x25\x3b\x56\x6e\xcc\xb5\x63\xbd\x6e\x48\x0c\x69\x73\x9b\x8e\x37\x25\x19\xa3\x43\x72\x54\xe0\xe5\x02\x9c\xac\x86\xc7\x16\x38\xf2\xdf\x2a\x6c\xf9\xe5\x6d\xb2\x56\x99\x34\xde\xba\x90\xdb\x75\x54\x7e\x36\x71\x74\x7d\xf6\x4d\x6f\x2a\xaf\x3c\x11\x0f\xa6\x7a\x70\x94\xcc\xbe\x4c\xc5\x35\x5f\x0d\x43\x23\x51\x36\xee\x26\xdb\xe3\x7f\x42\x25\xd3\xbb\xfe\x24\x55\x95\x28\x05\x85\xfb\x54\x8f\x89\x4e\x86\xc5\x16\x10\x25\x80\x29\x1f\xa7\xa0\x28\x59\x55\x7f\xb9\x8e\xb5\x88\x87\x08\x28\xb0\x99\x0a\xe9\xd7\x4f\x38\x31\xda\x58\x94\x6b\xc7\xa5\xce\x1b\xa4\x98\xb4\xe8\xbe\x89\x89\xa3\xb5\x0d\x7e\x87\x89\xf5\x6b\x8b\x4f\xec\xbc\x2a\x33\xbf\xa3\xef\x59\x1a\x0f\xbc\xd9\x32\xfa\x93\xe1\x9f\x3a\x81\x2a\xe5\xe4\xe3\xb4\xb2\x42\xbe\x77\x05\xa5\x87\x4a\xf7\x3b\xe3\x10\xb0\x05\x82\x66\xa3\x78\xf2\x3c\x13\x48\x52\x47\x15\xb0\xcc\xc1\x8d\x66\x34\xb2\x36\x36\xc3\x16\xba\x6a\x1d\xd2\xfd\x50\x92\xc0\x67\x16\xa7\x17\xb5\x4d\x0e\xb9\xfc\x7f\x63\x6f\x85\xbb\xf2\x25\xa2\xcf\x03\x5b\x4b\x7c\xfd\xdd\x75\x35\x16\x82\xc0\x57\x6c\x6b\x3b\xa5\xa1\xc0\xb2\x5e\xc5\x94\xe7\x70\x9d\xd0\x9a\x00\x79\x77\x2f\xf3\xac\xc6\x7f\xb6\xc1\xb3\x7b\xb3\x74\x2b\x72\x6e\x77\xe8\x05\x61\xd9\xab\x73\x16\x0b\x73\x36\x25\x81\xda\x5b\x9c\x7f"}, -{{0xe6,0xb9,0xcd,0x4d,0xa0,0x7c,0xb3,0x4f,0x30,0x39,0x1c,0xf6,0x8f,0x0d,0x87,0xc7,0xcf,0xcf,0x68,0xf8,0x10,0xff,0xa4,0x0f,0x97,0x39,0xc9,0x5d,0xeb,0x03,0x7f,0x71,},{0x56,0x9e,0xde,0x0f,0x04,0x63,0x0b,0x43,0xa0,0x4c,0x5a,0x66,0xb6,0xa5,0x63,0x6b,0x76,0x6c,0x75,0x96,0x59,0x84,0xa7,0x47,0x7e,0x15,0x49,0x19,0x60,0xfd,0xd8,0x64,},{0x1e,0x37,0x5c,0x94,0xbd,0x80,0x9c,0xa0,0xcd,0xd0,0x2f,0x89,0xec,0xec,0x4e,0x43,0x77,0x32,0xdd,0x20,0xa0,0xa8,0x4b,0x25,0x4e,0xae,0x88,0x9d,0x80,0x70,0xe6,0x82,0xd1,0x13,0xb0,0xbe,0x22,0xe4,0x1e,0x6c,0xdc,0x3b,0xe8,0x77,0x68,0x0e,0x7e,0xeb,0x7f,0x09,0x95,0xe6,0x62,0x2d,0xc0,0xb4,0x34,0xfb,0x09,0x49,0xdd,0x99,0x4b,0x0c,},"\x69\xde\xf0\x52\x3a\xfd\xa6\x96\xf8\x44\x8f\x9c\x11\x43\xab\xc2\x65\x33\xe6\x86\x95\xa0\x90\xdf\x0d\x9e\x43\xd0\xc0\xef\xf4\x35\x83\xe6\xf7\x09\xd2\x04\x3c\x81\x5f\xbb\x3f\x96\xba\x2b\x0d\xc3\xbe\x6f\xec\xad\x5d\xd3\x81\x48\x78\x8e\x4a\x03\x85\xa9\xfe\x7a\x92\x1f\xcb\x8c\xce\xe0\xe4\xd3\xae\xd4\xbc\x3d\x21\x6d\x84\xb4\x14\xf9\x58\x0b\x02\x82\x0c\x03\xd9\x2e\x67\x5e\x68\x5c\x4b\x58\x51\xf3\x63\xbb\x4d\xf9\x7b\x41\x7c\x3f\xd9\x00\x22\xee\xaf\xa2\x0d\xfb\xe8\x29\x64\xf2\xff\x07\x3d\x25\x57\x58\xfb\xe5\x67\xc7\x6b\x2c\x35\xe2\xb0\x9f\x8a\x8d\x7a\xfa\x32\xc6\xf5\xad\x01\xbc\x3e\xbf\x6e\x21\x06\x06\xdb\x03\x8e\xcb\x68\x20\xce\x1e\xa4\xdd\x52\x9f\xc1\xad\xfb\xc2\xa1\x38\x56\x5a\xc6\xd0\xf4\xa4\x10\x9b\xdd\x47\xb8\xaa\x6e\xf4\xb8\xbe\xde\x45\x46\x80\xd1\xdb\xdb\x75\xfe\x1e\xb2\xe5\x48\xd5\xde\x7c\xb6\xd7\x92\xfe\xf3\xaa\x0d\x84\x80\xa6\x03\x0b\x30\xf1\x04\xd7\xe7\x6b\x58\xe9\xf4\x76\xeb\xf2\xcc\x83\x29\x23\xb5\x0c\x50\xc1\x11\xc3\x51\x5f\xc5\x18\x85\x23\x23\x42\x6c\xa7\x78\xa5\x96\xd3\x19\x5d\xa8\x58\x5d\x8c\x3a\xa9\x20\x83\x31\x3a\x6e\x65\x85\xb7\x0c\x98\xb1\x85\xb4\x72\x79\x8a\x61\xcd\xe7\x7e\x62\xec\x27\x2f\x14\xb0\xd9\xeb\x4f\x22\xf9\xc7\xc0\x58\x17\xda\x6f\xde\xfe\x78\x79\xa5\x84"}, -{{0x4d,0x90,0x44,0xf1,0x7b,0x5a,0x09,0x77,0xdc,0x5a,0xa9,0x91,0x6a,0x92,0x43,0x00,0xa2,0x44,0xa1,0xef,0x7f,0x06,0x02,0x77,0xad,0x49,0x78,0x35,0x1e,0xa6,0x42,0x91,},{0xab,0x9c,0x06,0x92,0xa6,0x06,0xb2,0x56,0x7c,0x19,0xc3,0x0f,0x9f,0xaa,0x3b,0x4c,0xfe,0x72,0xfb,0x23,0x70,0x77,0x76,0x7b,0x76,0xd3,0xb2,0xae,0x14,0x90,0xa6,0xd4,},{0x6f,0xa4,0x8a,0xea,0x4d,0x5b,0x9a,0xf6,0x5a,0xf9,0x64,0xcd,0xb7,0x09,0x44,0x3a,0x11,0xfa,0x84,0xf7,0xd4,0x4a,0xcd,0xda,0xb1,0x6e,0x04,0xa6,0xfc,0xef,0xb2,0x7a,0xe3,0x3c,0x05,0xb3,0x6d,0xa1,0x3c,0x23,0xde,0x51,0x7d,0x6e,0x6a,0xc5,0x74,0xa0,0x3e,0xa6,0x30,0xba,0x4f,0xbb,0x95,0x81,0x31,0x12,0x9a,0xa7,0xf1,0x35,0x4c,0x01,},"\x7c\x8c\x71\x89\xaf\x67\x32\x7a\xf1\xc6\xdd\x2c\x30\xe9\x75\xf1\x90\xe3\xb3\x8d\x00\x8b\x45\x85\x16\x7e\x0d\x45\x07\x40\xd4\x67\x34\x58\x7f\x6d\x20\x87\x84\x24\x5c\xc5\xcb\x06\x2a\x2a\x27\x7f\x17\xeb\xb2\x74\x6f\x9b\xdf\x4a\x82\x37\xca\x47\x9a\xb0\xa4\x30\x17\x7e\x19\xed\x7d\xd3\x62\x25\x76\xb1\x4c\xdc\x08\x28\x22\x14\xfe\x5e\xe4\xd7\x6b\x43\xc1\x6a\xc9\x08\x64\xc5\x1b\xe8\xae\xd4\x5d\x7b\x98\x0d\xf7\x91\x7f\x29\x0f\xdf\x79\x58\x46\x46\x5f\x27\xfc\xb7\xe5\x73\x06\x37\x94\x4f\x05\x77\xc9\x2f\x32\x37\x5e\x99\x5b\xc0\xcd\xa9\xd7\x19\x6f\x2c\x0c\x1a\xc8\xb8\x0d\x12\xa0\x43\x99\x63\xeb\xd2\x25\x4c\x34\x77\x03\x57\x58\x16\xe7\x96\x4c\x13\xd4\x4d\x62\x92\x80\xc3\x12\xea\x26\x53\x44\xde\x38\xf3\xb1\x8d\x91\x50\xf8\xf9\x24\xaf\xb4\x4b\x6b\xfb\x9e\xda\x51\x3d\x59\xe6\x5e\x2e\xf1\x86\x66\xe6\xc2\xa2\x1c\x40\x18\x66\x5b\xef\xe9\x2c\xae\x58\x1d\x3c\xb1\x4e\x23\xe9\x7d\x83\x00\x02\xcb\x90\x93\x1a\xe0\x21\x00\x68\xaf\x39\x4e\xbe\x35\x1b\xe5\xb8\x17\xf3\x67\x4b\xfb\xf4\x00\x49\x03\x0e\x4f\xe5\x05\xd3\x4a\x1d\x50\x2a\x2c\x50\xd8\xe6\x38\xe9\x26\xc2\x30\x67\x6b\x7e\xde\xfb\x6b\xec\x77\xb1\xc0\xce\x60\x93\x25\x28\x7b\xa5\xfd\xd7\xa9\x97\x69\x87\xbd\x07\xfc\x6a\x43\x44\x95\x6e\xbf\x81\x8f\x08\x58\x6c"}, -{{0x75,0xad,0x76,0xbb,0x4c,0x0c,0x22,0x9a,0x5a,0xdc,0x79,0xe4,0x44,0xb1,0x3f,0x88,0xa9,0x64,0x59,0x86,0x2c,0x8c,0xf0,0xba,0x49,0x8d,0x0c,0x99,0x6a,0xf9,0x4a,0x7a,},{0xf0,0x74,0xdd,0x2b,0x9c,0x1c,0x30,0x91,0x05,0xec,0x95,0x1b,0xb5,0x81,0x2a,0x91,0xdd,0xb5,0x40,0x23,0xb3,0x80,0x9a,0xb3,0x79,0xc5,0x6a,0xf0,0x46,0x1a,0xf6,0x17,},{0x0c,0x46,0x43,0xa8,0xbe,0x6d,0xc2,0x2f,0x4b,0xeb,0x6b,0xcc,0x70,0xc6,0x17,0x2e,0xc7,0x60,0x83,0x78,0x65,0x3c,0xb4,0xe9,0x9f,0x3a,0xe7,0x95,0xea,0xdf,0x4e,0x98,0x2a,0x29,0x76,0x09,0xca,0x79,0x38,0xf5,0xdf,0x63,0x2b,0x09,0x56,0x28,0xcb,0x75,0x06,0x2d,0x3d,0x51,0xfc,0x0f,0x33,0x23,0xbf,0xa7,0xb2,0x2e,0xc4,0xd4,0x72,0x05,},"\x0c\xa8\xc1\xc7\x41\x28\xd7\x4e\x9d\x0a\x7b\xf8\x96\x42\x91\xd0\x74\x91\x7f\x2f\x99\x20\xef\xb9\x11\x52\x05\x67\x64\x2a\x50\xa6\x15\xab\xcb\xd0\x0a\xed\x4a\xbb\xfe\xf1\xa9\x83\xcc\xe3\x33\xe1\xd0\xdf\x3e\x64\x04\xfb\x90\x43\xc6\x80\x39\x14\xcd\x5f\xff\xbc\x66\xa0\x79\x0c\x78\x78\xa2\x40\x89\xa5\x71\xf8\x95\x66\x2a\x1d\x18\xbe\x3f\x01\xff\x97\xfb\x33\x23\x33\x4b\x6f\x5b\xaf\x96\x55\x14\x48\xe4\x09\x0d\x03\x3c\x46\x42\x94\xd0\x91\x33\xb1\x51\xd5\xb5\xc6\x32\x1b\x50\xe2\x24\x1d\xe0\xef\x6f\x88\x28\x89\xcc\xf4\xad\x35\x40\xd5\xa1\xe3\xf7\x54\x8f\xb1\x3b\xe7\x1c\x16\x51\x66\x06\xe7\x9d\x04\x49\xc2\xa0\x8e\x5d\xc2\x31\x48\x84\x3c\x84\xe9\x7e\xd2\x40\x69\x16\x1c\x8e\x75\x20\x8f\x33\xe9\x5b\x3e\x10\xd1\xd4\x9a\x2f\xae\xf9\xd9\x86\xab\x62\x80\x9f\x62\xad\x39\xc7\xcc\x87\x1f\x37\x5a\x4f\x5a\x6f\xaf\x10\x4d\x7e\x11\xb8\x90\xcf\xb0\x58\x99\x02\x68\x52\x16\xec\x07\xcb\x8e\x8e\x9e\x7a\x7c\x43\x63\x5e\x23\x21\x2b\x69\xca\x3b\x7e\xd5\x4f\x0b\x97\x94\x9e\x3d\x9a\x66\x62\xf8\xe4\xb3\xab\x09\xcd\x49\x52\x94\xc3\x31\xc0\x47\xd8\x6e\xe7\x85\xff\x65\x8b\xcd\x7f\xcf\x9c\x48\x06\x05\xce\x05\xe8\x10\x06\x8d\x60\xfc\x9b\x26\xb5\xf0\x63\xeb\x90\x00\xd2\x65\x7a\x50\x94\x28\x4a\xc8\x0f\x13\x75\xd0\xb6\x6d\x6f\x5f"}, -{{0xad,0xc6,0xe9,0xb2,0xe1,0x03,0xb6,0x2c,0x24,0xad,0x43,0x46,0x41,0x0e,0x83,0xa1,0xa0,0xbd,0x25,0x3e,0x4a,0xbf,0x77,0x91,0x18,0x50,0xc6,0xd9,0x66,0x6e,0x09,0xf9,},{0xfc,0xe3,0x16,0xe3,0x3c,0x91,0x08,0x21,0xbe,0xed,0xdd,0x63,0x4b,0xed,0xc5,0x8e,0xe5,0x79,0x99,0xa7,0x6e,0xce,0x38,0x46,0x05,0x28,0x3b,0x99,0xb5,0x43,0xb7,0x8b,},{0xcb,0x01,0x7d,0x6d,0x26,0x82,0xc9,0x85,0x43,0x66,0x25,0x9a,0xa3,0x5f,0x30,0xd4,0x91,0xcf,0xaa,0x93,0x09,0x98,0xc2,0x97,0xdb,0xdd,0xc6,0xad,0xed,0x5b,0x3d,0x40,0x1c,0xf7,0x6d,0x80,0xd8,0xa2,0x76,0x4d,0xe1,0x31,0x71,0x8b,0x6e,0x0c,0x48,0x1d,0x71,0x96,0xbc,0x72,0x57,0x97,0x16,0xb0,0xc0,0xf6,0xff,0x05,0x3e,0x68,0xc5,0x0c,},"\x8c\xcc\xd9\x8e\xbb\xf2\x43\x9f\xfd\xfa\xc4\x16\x87\x63\x8f\xaa\x44\x4e\x1c\xa4\xb6\x3d\x13\xe8\x98\xea\xa8\x35\x54\x92\xf2\x88\x13\xab\x81\x3f\xd0\x15\x10\xe1\x12\xbe\x10\x6b\x20\x45\xd3\x0f\x63\x33\x5d\x24\x89\x04\xd5\x21\xde\x18\x1a\xba\xc0\x3e\x3d\x2c\xb2\xd1\x6c\x44\xb3\xb0\x12\xa0\xc5\x1f\x99\x01\xae\xf9\x05\x6c\x72\x4d\x7a\x2c\x6b\x2a\xcb\x0a\x07\x55\x59\x40\xe4\xc6\xe2\x11\x54\x89\x06\x11\xad\xeb\x64\x89\xf4\x61\xd3\xe5\xec\xd1\xaf\x5a\x4d\x2b\x0a\xda\xf4\x17\x47\x43\x6e\xb4\x14\x75\x7a\x8f\xe4\x77\x56\x74\xe3\xc6\xe5\xde\x45\x69\xd6\xfc\x6c\x78\x8e\x10\x90\x5e\xba\x32\xc2\x70\xa3\x93\xe6\xf7\x21\xa7\x65\x29\x4e\x2a\xc9\x9a\x9b\x6e\x53\x4d\x3d\xf0\x8d\x1d\xb9\x7d\x60\x2a\xc3\x19\x5c\xb0\xb7\x7f\x5b\xd4\xac\xaf\x73\x7f\xad\xd6\x99\x1f\x06\x88\xab\xc7\x49\x18\x04\x75\x74\xea\xc2\x82\x89\x73\x9a\x66\x4e\x0e\x0e\x20\x57\x4a\x2c\x25\xfd\xe4\x9d\x14\x53\x9d\xb1\xce\xdd\x4a\x92\x04\xa7\x0a\xcf\xf0\xa6\x2c\x8f\x25\xcd\x76\x8f\xfa\xb1\x5c\x4d\xb3\x16\x84\x0a\x4d\x1b\xc9\x2e\x21\x26\x70\xbe\x07\xc5\xbd\xcf\x53\x75\x90\x60\x7d\xfb\xbb\xb4\xd9\xf9\x8b\x89\xda\x0b\x4d\xf7\xd8\x8f\x3e\xca\x48\x14\xd1\x6b\xfa\x20\xc8\xd2\xfa\x94\xf9\xf2\x59\xf2\xee\x2d\x3a\x83\xc9\xe4\x17\x1b\x1a\x26\x2c\x4b\x99"}, -{{0x37,0xfc,0x1b,0xed,0xa4,0x06,0x0b,0x6c,0x57,0x88,0x3d,0xdb,0xa0,0x77,0x6c,0x2b,0xcf,0x5a,0xc2,0x8a,0x65,0x13,0x26,0x02,0x1c,0xca,0x97,0x72,0x37,0x30,0xfb,0xb0,},{0x7b,0xd7,0xbf,0x1c,0x99,0xdc,0x82,0xe0,0x6f,0x08,0xbb,0x45,0x4d,0x8f,0xb2,0x88,0xa5,0x79,0x27,0xe0,0x7f,0xf1,0xb1,0x2a,0xf1,0x5e,0xe2,0xc1,0x2f,0xbb,0x6b,0x3d,},{0xa0,0x1d,0xd6,0x5f,0xad,0xa2,0x70,0x39,0xf1,0x68,0xb1,0x23,0x41,0x9d,0x8a,0xbf,0xbd,0xa4,0x8c,0x57,0x2e,0xce,0x24,0xfd,0xa0,0x6e,0x1a,0x5e,0xc3,0x1e,0x08,0x4f,0x4e,0xe1,0xcb,0xf9,0x96,0x1e,0x88,0xed,0x51,0xe1,0x89,0xfc,0xb7,0xf5,0xf2,0x35,0xde,0x1e,0x5b,0x28,0xd0,0x8f,0x2b,0xfc,0xa1,0x90,0xb0,0xf0,0x19,0xec,0xc2,0x07,},"\x3d\xfc\xac\x02\x65\xa0\x24\xa8\x3c\xb9\x32\x67\x44\x89\xa1\x63\xaa\xc3\x14\xbf\x3d\x96\x9f\x27\x59\x6e\x45\x17\x33\xb9\x9d\xeb\xa5\xee\xb7\x79\x21\x0b\xaf\x95\xbf\x54\x5a\x1a\xe6\xb8\xa9\x15\x86\x06\x93\xee\x89\x0f\x93\x93\x20\xe0\x6a\x84\x44\x83\xd1\x8c\x6a\x1b\xcd\x03\xc6\x38\xbb\x7d\x1f\xe2\xa8\x2e\xb4\x48\xa3\x11\xb1\x30\x2e\xa6\x42\x8f\x54\xa3\x9f\x45\xa4\xd5\x60\xbe\x15\x57\xa2\xb2\x54\xc4\x5c\x13\x7f\x45\xcc\x68\x35\x68\x36\xe2\x1b\xed\x0b\x7f\x73\xa5\x18\xce\x09\xdb\x0b\xe3\x93\x92\x7c\x33\x9b\xf2\xa4\xb5\x98\x75\x39\x40\x4c\xe6\x50\x28\x4d\xe1\x2e\x3b\x55\x3b\x26\x2e\xfe\x23\x84\x83\x32\xcc\xfd\xc3\x5e\x79\x1a\x0a\xb4\x3f\x13\x9c\x71\xed\x0f\xcb\x2d\x17\x3b\xb3\x77\xee\x46\xb1\xa9\xdc\xa9\x27\x7e\x77\xdf\x85\x5f\x28\x30\x25\x1e\x31\xe2\x6a\xcd\x86\x76\x3c\x8d\x7e\xac\x22\xc8\x82\xfc\x17\x4f\x2b\x5e\x75\xca\x6a\xd1\xad\xe0\x3f\x94\x2b\xb2\xa1\x3b\xf5\x41\x90\x61\x59\x15\x8c\x68\x36\x3c\x74\x80\xc5\xb2\x7a\x99\x32\x0f\x82\x83\xa2\x69\x9d\x43\x69\xc0\x71\xc5\x0d\xbd\x90\xb7\x79\x2e\x47\x72\xef\xbc\x0b\x19\x5b\xce\x84\xcc\x4d\xcf\xff\x70\x72\xa4\x89\x68\xdb\x69\xf9\xfe\xdd\xd0\xf9\xce\xd6\x59\xeb\x5d\xb7\x16\x7f\x35\xf9\x88\xce\xc1\x14\x88\x7d\xcb\xfd\xf2\x7d\x02\xd3\x00\xb3\xe1\xab\xec"}, -{{0x8d,0x42,0xf4,0xdd,0xd2,0xbb,0xd2,0xb8,0x27,0xb0,0xa0,0xd3,0x1d,0x8f,0x75,0x8e,0xbd,0x13,0xa1,0xb9,0xb3,0x71,0x22,0x28,0x94,0x8c,0xa6,0x10,0xbb,0x88,0x58,0xe5,},{0xb7,0x35,0x48,0x98,0x79,0x4f,0x9d,0xb0,0xa8,0xaf,0x6e,0xea,0xfc,0xdb,0xdf,0x01,0x1d,0x3f,0xbe,0xf0,0x21,0x2a,0xd9,0x38,0xa4,0xa4,0xad,0x27,0xab,0x16,0xeb,0xbf,},{0x70,0x76,0x4b,0xe3,0x9c,0x6d,0xca,0x0f,0x06,0x7a,0xbe,0x1e,0xca,0x49,0x0f,0xda,0x95,0x1f,0xd4,0xe9,0x49,0x96,0x95,0x26,0x6e,0x27,0x0b,0x9b,0x05,0xea,0xe7,0x06,0xca,0x8d,0x1c,0xa6,0xa9,0x2d,0x7c,0x48,0x8e,0xc6,0xad,0x8b,0xa1,0x14,0x57,0xa4,0x2a,0x5e,0x31,0x70,0x2a,0x9c,0x2b,0xce,0x89,0x2d,0xc4,0x05,0x35,0xc0,0x9f,0x01,},"\xe3\xa2\xbe\xbc\x04\x96\xd8\x97\x4a\x8f\x40\x61\x88\x03\x69\x31\x4e\xd9\xe4\x40\xc1\xb7\x7e\x26\xfe\x50\x71\xce\x69\x4f\xfd\x21\x36\xdb\x0c\x4d\x5e\x88\x0e\x60\x00\x08\x3a\x75\xc9\x0d\x3c\xf7\x2b\x9c\xf5\xa2\xb1\xa9\x00\x2c\x27\x01\xa2\xff\x59\xb0\x69\x9a\x8f\x42\xd7\x9d\xd8\xa5\xfb\x71\xa8\x12\x54\x53\xd9\x1f\xb8\x00\x80\xa3\xf0\xa1\x65\x84\x28\x2f\x17\xec\x7d\xfd\xc2\xe5\xc6\x9c\x4d\x9b\xdf\x48\x4d\x55\x94\x4d\xae\x27\x3f\x21\x1c\xfb\x76\xad\x37\xda\x45\x87\x13\x65\x43\x9a\xf3\x5e\xea\x1f\xbe\xcd\x4c\xa6\x79\xb5\x9b\x5e\x01\xba\xcf\x49\xc7\xf4\xe5\xef\xaa\x40\x6b\xa1\xda\xeb\x08\x54\x82\xaf\x5d\xed\x89\xdc\x68\x85\xff\xbe\x3d\x14\xd2\x93\x1b\x83\x89\x7e\x28\xad\x06\xe5\x56\x4e\x27\x89\xba\xea\x81\xbd\x93\x2a\xa2\x79\xfe\x8e\x32\x4b\x9a\x8e\xf1\x11\xc2\xab\xe2\xf1\x37\xd4\xbb\x50\xd8\xab\x76\xce\xbc\x0b\xd9\x82\xa2\x39\x19\x75\x1a\xd4\xd4\x9e\x88\xeb\x14\x17\x3d\x33\x10\x28\x9a\x87\x23\x17\xe4\xa4\x51\xe8\x8d\x54\x32\x08\x91\x87\x0f\x15\xb2\xd5\x33\x24\x43\x08\x77\xa9\xfb\x5b\x49\xbb\x92\x9f\x21\x1c\x5b\x89\x76\x4d\xd9\xc3\xa5\x95\xa1\x45\x1e\x9f\x85\xa2\x38\x54\x00\x02\x56\x6e\x53\xa9\x9e\xd1\xe6\xdd\xc9\xb4\x85\x3f\x45\x5e\xdb\x4c\xf1\x98\x0d\x56\xbb\xdc\x13\x13\xa3\x6e\x76\xea\x9c\xbb\x04\x8a"}, -{{0xb6,0x2d,0xe5,0xa1,0xac,0xfe,0x4c,0xa2,0xd1,0xf0,0xc1,0x32,0xaf,0xcb,0xda,0xe6,0x6f,0xb2,0x9a,0x02,0xf2,0x97,0xfb,0xc2,0x40,0x7f,0xad,0xbb,0xf2,0x45,0x42,0x00,},{0xb6,0x3b,0x2d,0x0b,0xf3,0x55,0xf7,0xb6,0xd0,0xba,0xc0,0x74,0x03,0x41,0x1c,0x40,0xaf,0xbb,0xb2,0xf7,0x07,0x50,0x3b,0x3f,0xc2,0xce,0xe8,0xa1,0xc7,0xd0,0xa8,0x38,},{0x5c,0xdb,0x00,0xe9,0x8d,0xe7,0x3e,0xab,0x48,0x0b,0xe4,0x2f,0x8a,0x8a,0x61,0x63,0x80,0x9a,0x0d,0x37,0x10,0x1b,0x6a,0x5a,0x4e,0xed,0x6a,0x0c,0x92,0x03,0x0d,0x09,0xa5,0x56,0x2c,0x72,0x90,0x80,0xce,0x6f,0x65,0x94,0xc8,0xfa,0xfb,0x1f,0x59,0x47,0x72,0xdb,0x7a,0x90,0xa9,0xe7,0xda,0x15,0x89,0x6e,0x82,0xf7,0x05,0x69,0x39,0x0d,},"\xe6\x59\xe5\x1d\x7b\x19\x3c\x4b\x8e\x2b\x3e\xd7\x3a\x9d\x75\x57\xed\x2b\xab\x61\x53\x88\x3a\xb7\x23\x59\x2f\x73\x0a\x91\x45\x67\x14\x2b\x3f\xa4\x35\xdb\x32\x19\xf8\x3a\x54\x2d\xc7\xa4\xbd\x80\x5a\xf6\x66\xea\x86\x5b\x85\x31\x46\xf8\xe3\xa9\xfe\x87\x07\x11\xf9\x0d\x12\xb0\x69\x34\x92\xaf\x2a\x1e\xdf\x99\xa1\x64\x58\xf7\x81\xf1\x26\x6e\xc4\x37\xa5\x29\x6a\x82\x2c\xa9\xd6\x9c\xe8\x44\xb5\xc5\x90\x97\xa2\xa5\x6f\x3e\xb8\xfd\x27\x3a\x63\x61\x16\xdb\x77\x43\x00\x92\x2d\x45\xb7\x44\x65\x7a\x69\x2f\x5e\x8b\xfb\xcb\x06\xd2\x42\x28\x18\xae\xb5\x1e\x7c\xda\x68\xac\xfb\xed\xa1\x6e\x7c\x79\x58\x0d\xcc\xcd\xe2\x4e\x8e\x3d\x60\x1b\x16\xe0\x63\xb4\x3a\x6d\x0d\x14\x07\x55\x2f\x75\x04\xf5\xbe\x19\x88\x2e\x4f\xfe\x32\x34\x4f\x5f\x47\x3e\x73\xa8\xf6\xed\x37\xb0\xd8\xd9\xe5\xe0\xa0\xdc\x98\x28\x39\x5b\xcb\xd8\xf3\xa4\xe3\x12\x48\x69\x24\x9d\x05\x8b\xe0\xe0\x45\xde\x0b\x1e\x12\xb1\xc8\x3b\xa0\xaa\x22\x7c\x95\xb8\x2b\xf7\x42\xc3\xea\xc0\x15\x2b\x33\xe6\xd1\x9b\xe8\xb3\x3a\x35\xbf\x70\x5d\xaa\xb1\x06\x22\xa9\x0a\xed\x02\x2e\xa6\xe4\x39\xed\x50\xa9\x30\x84\x37\x92\x99\x24\xba\x3a\xb1\x11\xad\x0c\xaa\x6f\xeb\x0a\x6e\xb1\x65\x82\x4e\xbd\xb0\x86\x65\x71\xef\xc0\x7e\x52\x22\xed\x86\x86\xb1\x4d\x92\x70\xbf\x76\xb9\x45\xd5\x20\x14"}, -{{0x97,0x32,0x05,0x9d,0x7b,0xf0,0x20,0x0f,0x5f,0x30,0x41,0x24,0x30,0x33,0x6b,0xe4,0xef,0x1e,0x3c,0xae,0x62,0x93,0x8a,0xd0,0x87,0x29,0xce,0x3b,0xa7,0x14,0xcf,0xd4,},{0x0d,0xe8,0x42,0x5f,0x5e,0x30,0xb2,0xb8,0xae,0xbb,0x80,0x72,0x00,0x9a,0x30,0xcf,0x04,0x11,0xc3,0xc8,0x23,0x8f,0x4e,0x42,0x08,0x76,0x0c,0x56,0xc3,0x3e,0x43,0x4f,},{0xfb,0xa1,0x74,0x9b,0x64,0x1d,0xd4,0xdf,0x34,0x66,0x4b,0xc4,0x3c,0x00,0x46,0x8c,0x7d,0x75,0xe8,0x4a,0xfa,0xd7,0x2d,0xe4,0x73,0xfd,0x1e,0x9c,0x87,0xda,0x15,0xea,0x60,0x4f,0xc2,0x54,0x9a,0x1a,0x86,0x7f,0xa8,0x08,0x50,0xe9,0xc2,0xa5,0x9c,0xd9,0x90,0x53,0x88,0x67,0x60,0xa8,0xd9,0x76,0x4b,0x84,0xdd,0x67,0x26,0x76,0x72,0x0d,},"\x1a\x13\xe7\xab\x60\x3b\x48\xeb\x89\x6f\xe1\x71\x73\xfb\x31\x95\x0b\x0d\xcd\x5a\x35\xff\xdb\xe1\x37\x1c\x7a\x5b\xfb\xa5\x93\x31\x75\x89\xd9\x65\x2d\x88\x79\x77\x29\x18\x0b\x8d\x0e\x51\x5a\xbf\xe6\x54\x8f\x16\x04\x21\xe5\x37\xd5\xc9\x4a\xef\x2b\x34\xc7\xeb\xb0\x97\x42\x00\x03\xbc\x0f\x36\x1b\x42\x3e\x7e\x14\x63\x0a\x80\x3c\x11\x82\x02\x54\x00\x49\xf6\x8c\x9c\xf4\x6f\xae\x03\x68\xd1\x62\xe4\x00\xd7\x7b\xb4\x52\x3c\xf6\xc7\x53\xb9\x75\xc2\x45\xbc\x99\xed\x2f\x41\x3a\x9d\x06\xc2\xda\x6c\xe0\xcc\x09\x87\xb6\x40\x6b\x80\x9e\x8e\xb3\x19\x03\x3d\x2d\xe9\x13\x1d\xee\x3b\x1b\x7b\x5c\x95\xd6\x53\xce\xd8\xfc\xcf\x99\x8d\xa1\x76\x85\x11\xec\xa4\xd3\xc5\xf7\x35\xad\xab\x96\x50\x3b\x35\x51\x80\x3e\x49\x22\x63\x50\x95\xef\x81\x1b\xe4\xc0\x8a\x6c\xba\xc9\x17\xcb\xe6\xcd\x91\xa4\xae\x5a\x33\x0c\xce\xc0\xe8\xe8\x15\x37\x12\x17\xa3\xde\x62\xf2\xd2\xd6\x14\x66\x21\x98\x33\xf3\x34\x47\x13\x2f\x4d\x43\x35\x0c\x58\xcb\xaf\x42\x24\x75\xed\xb1\x28\xc5\x6d\x80\xa4\x95\x72\x6b\x1f\xdb\xc5\x65\x51\xeb\x72\xd0\xf4\xfe\xc2\x6b\xa8\xbf\xf5\xee\xd6\x77\x4b\x85\x03\x9a\x52\x92\x83\x4b\x5d\x1c\xc1\xb0\x9b\xa0\xa3\x95\x4d\x29\x32\x36\x73\xf5\xe7\x12\x76\xa1\x2a\xc4\xc5\x79\x35\x5b\xf1\xec\xca\x48\xe6\xa7\x16\xb9\xfc\xec\xdc\x56\x5c\x51\xb9"}, -{{0x9c,0x7f,0x6f,0x37,0x9e,0x38,0x57,0x00,0x7e,0x2a,0xc6,0x32,0x4c,0xbb,0xce,0xd5,0x7a,0xc9,0xee,0xe4,0x47,0x78,0x13,0xf8,0x3a,0x81,0xfc,0x8c,0xef,0xa9,0x64,0xd5,},{0xa5,0x4b,0xa3,0x96,0xd6,0x87,0x63,0x4d,0x3e,0xcc,0xf4,0x1c,0x57,0x82,0x49,0x4f,0x5f,0x10,0xa5,0x21,0xa1,0xe5,0xd3,0x88,0x52,0x3d,0x80,0xee,0xba,0x5b,0x0b,0x2b,},{0x65,0x68,0x5f,0x9c,0xa5,0x98,0x2e,0x15,0xa2,0x2b,0xa3,0xc8,0x3a,0x03,0x48,0x34,0x84,0x82,0xdf,0xae,0x57,0xce,0xa1,0x78,0xf0,0x78,0x0c,0x05,0x7b,0xae,0xbe,0x4a,0xf6,0x32,0xf9,0x84,0x54,0x0a,0x26,0x01,0x9a,0x7f,0xb3,0x42,0x53,0xc9,0xec,0xe7,0xff,0x30,0x8a,0xda,0x23,0x3c,0xe0,0x68,0x63,0x47,0xab,0x5b,0x21,0xce,0x57,0x0b,},"\x3f\x2d\x30\x72\xfe\x73\x83\xe5\x41\x55\x1e\xa9\xab\xdb\xae\xae\x6a\x46\x4a\xe6\xb9\xf0\xba\x78\x6a\x44\x1b\x2d\x08\xda\x5b\xca\xda\x3c\x54\x24\xdc\x69\x31\xd6\xb3\x95\x23\xe2\xde\x0a\x0c\x2e\x4e\x6b\x5b\x8c\xda\x92\x5e\x5e\xac\x93\x84\x16\xa2\xc5\x1b\xf1\x3d\x49\x53\x1d\x7e\xc7\x11\x4b\x1c\x82\xfe\xaf\x90\xf3\xf8\x75\x91\xe3\x97\xd0\x27\x02\xf8\xec\x1b\x30\xd9\x9f\x5b\xe7\xd2\x20\x3e\x4f\xe4\xdb\x2e\xa4\x7e\x7b\x45\x89\xd8\xac\x50\x62\x48\xd7\x34\x74\x66\xed\xbc\x96\xea\x32\xbf\x3a\x6e\xa7\x50\x2d\xd6\x0c\x9e\x84\x90\x27\x15\xab\x2c\x6c\xa6\x8f\x5b\x00\xe1\xd9\x09\xd8\x3a\xa6\xab\x66\x2d\x8a\xea\x87\x0e\xcd\x86\x1f\xec\x69\xf2\xee\xc0\xae\x67\x7d\x29\x95\xb0\xed\x68\x8f\xaa\x8e\xf7\x82\x44\xe0\xd1\x19\x56\x97\xb0\x71\x22\xce\xaa\x11\xf5\xa6\xea\x58\xfb\xdf\xa2\xe2\xec\x2d\xf9\xd1\x86\x93\xae\x96\xd4\x71\x27\x55\x6e\x91\xf0\x86\x49\x82\xc1\x34\x19\xb0\x4a\x63\xf2\x08\xe7\x30\xd2\x69\x51\x88\x2a\xef\xe0\x01\xbc\xa3\x40\x8b\xd9\x86\x27\x48\xc6\xcc\x87\x6c\x28\xca\xc3\xbb\x2e\xb3\x39\x58\x18\xc2\x09\x1e\x0f\xbd\x7a\x0b\x44\x68\xc6\xb0\xd0\x0c\xd0\x08\xc1\x1c\x3c\x3a\xd0\x10\x80\xa1\xf5\xa4\x0a\xe2\xe4\xb0\xc3\xa0\x71\xef\xc8\xe1\xd1\xba\x6a\xce\x6d\x4d\xf0\xff\x19\x82\x9b\x0c\x68\x0b\x3a\xeb\x75\x91\x77\xed\x34"}, -{{0xa4,0x78,0xf3,0x5a,0xbb,0x73,0x72,0x7b,0x6b,0xe6,0xee,0x5e,0x56,0xee,0xc3,0x23,0xc9,0x51,0x78,0x82,0xfd,0x69,0x19,0x36,0x0e,0xbb,0xbf,0x5d,0x5c,0xb8,0xb8,0x3a,},{0x7a,0x6e,0x26,0x6a,0x54,0xd1,0x35,0xdd,0xa0,0x00,0x9c,0xcd,0xa8,0xa9,0x4a,0x47,0x12,0xae,0x5c,0xb1,0x47,0x61,0xe8,0x43,0x6e,0x97,0xc4,0xb7,0x81,0x4d,0x8e,0x8c,},{0x9d,0x16,0xfd,0x40,0xb9,0xf8,0xdd,0x9b,0x4a,0x1a,0x8c,0x6d,0x70,0x3b,0x9f,0xcc,0xbb,0x94,0x0b,0x1e,0x0a,0xe7,0x7a,0x59,0x70,0x37,0x4a,0xf0,0xcf,0x72,0x6f,0x44,0x79,0xfd,0x30,0xd7,0xdf,0xf5,0xcf,0x53,0x49,0x4d,0x9a,0x29,0x6a,0xb6,0xb9,0xe4,0x6e,0xa6,0xc1,0x36,0xb4,0xdb,0x2c,0x71,0xc2,0x1b,0x97,0xc1,0xc8,0x25,0x4d,0x0a,},"\x01\x73\xa3\x40\x50\xb4\x37\x48\x06\x1f\xf8\xf5\xa3\xd7\xc4\x3b\x63\x60\x84\x77\x86\xe8\xbb\x75\xe5\x36\xfb\x47\xb6\x45\xb2\x14\xf2\x21\xba\x24\xd8\x3d\x28\xbc\x02\x50\x24\x66\x3e\x53\x4f\x90\xf6\xe8\x3a\x93\xd8\xbd\xde\xda\x2c\xd8\x80\x81\x55\x65\x2a\x90\x8c\x43\x7c\x2d\xb6\xf3\xed\x49\x12\xf5\x7c\xa5\xb9\x79\x28\xa7\x3b\xe9\x64\xaf\x59\xdf\x44\x39\x85\x4b\xb0\x06\xfc\x29\x5a\x87\xb7\xb7\x22\x39\xc7\xfa\xdf\xec\x40\x71\x55\x09\xd9\x85\x79\xda\xad\xfb\x8d\x52\x4b\x4c\xec\x66\x20\x70\x5e\xfd\x41\x04\xc2\x97\x14\x4a\xea\x72\x29\x74\xe1\x2c\x5e\xce\xe5\x39\x1e\xf2\xd9\x3a\xc2\xb1\x24\xe4\xac\x49\x61\x47\xc8\xb7\x03\x63\x58\x5d\x70\x78\xcc\xc5\x3e\x2a\xe5\x93\x35\x0b\xc2\x55\x48\xa0\x54\x25\x26\xab\x00\xaf\xe4\x77\xa0\xf4\xb2\x73\x97\xc7\x2b\xc7\x4a\x8a\x8a\xb1\x56\xe6\x2b\x8b\xb4\x7c\x3f\xbb\x4b\x34\x91\x3e\x45\x96\x87\x47\x6b\xf3\x31\x42\xc6\x14\x70\x21\x07\xff\xe2\xcc\x01\xe2\x5f\xa3\x02\x75\xe1\xe2\xe6\x3c\xea\x91\x68\xe4\xa4\x7c\x02\xde\x09\x7d\x4d\x85\x3b\x27\x67\x5c\x5b\xb3\x30\xb9\x4a\x97\x4e\xad\x85\xe2\xbd\xee\x8e\xe1\x7c\xbb\x56\x53\x34\x66\x58\xdf\x2f\x91\xf6\xbd\x73\x94\x91\xdd\x71\x98\x8b\x3a\x97\x6a\x3e\x2e\x7a\x9d\x13\x74\x10\xf4\xac\xba\x9f\xeb\x5f\x11\x79\x8c\x9a\x43\xb6\xad\xce\x14\x36\x5a\x7c\x6d"}, -{{0xff,0xe8,0x25,0x14,0x8c,0x09,0x59,0xb3,0xa6,0x8d,0xe8,0x6a,0xd8,0xe8,0xaf,0x7f,0xa5,0xe0,0x78,0xf3,0x63,0xdc,0x12,0x42,0x13,0xc9,0x00,0x20,0xda,0x0c,0x90,0x89,},{0x13,0x91,0x52,0xa0,0xbd,0x22,0x96,0x2d,0xd9,0x19,0xae,0x3e,0x0b,0x16,0x20,0xe0,0x3c,0x03,0x3c,0x2a,0xd0,0xa3,0x97,0x9e,0xc6,0xbc,0xd1,0x70,0x5e,0x23,0xd5,0x98,},{0xfe,0x4e,0x89,0xee,0x31,0x78,0x6c,0x0a,0x3d,0x3d,0xe3,0x64,0x9b,0xb9,0x3f,0x0b,0x8a,0xef,0x1c,0xaf,0x5a,0x83,0x2e,0xc5,0xe4,0x06,0x78,0x10,0x70,0x5a,0xdd,0xdf,0x53,0x9b,0x8f,0x4e,0x05,0xad,0x08,0xcf,0x34,0x79,0xe4,0x5b,0x42,0xc9,0x65,0x28,0xf6,0xd5,0x9a,0x46,0x25,0x70,0x3d,0xdb,0xf1,0x5b,0x63,0x09,0x39,0x65,0xd8,0x0d,},"\xf1\x25\x78\x0d\x0c\xd0\x88\x53\x0f\x0c\x87\xb7\x0b\xd4\x2e\xba\xb5\x6a\xdb\x5a\xd4\x34\x5f\x92\x9a\xe5\xde\xae\x07\xfb\x55\x32\x21\x53\xa8\xf0\x23\xd3\x88\x43\xbf\x5d\x6a\x93\xfe\x99\x3e\xee\x71\xbc\x2e\xe5\x63\xb2\x5a\x50\x91\x8f\x03\xef\xdb\x5d\xbf\x72\x69\xad\xd6\x9d\xed\x3e\x66\x95\x38\x95\x62\x0d\x9b\x6c\xf4\x6b\xa2\x34\x8f\x8d\x66\xd7\xf0\x92\x23\x5e\x37\x8c\x1e\x3e\xdf\xeb\xeb\x78\x08\x4b\xc8\xde\xa0\x13\xf9\x93\x3a\xae\x14\xa0\x41\x94\x82\x76\xd0\x1f\x1c\xb5\x83\x4b\x0e\x59\x0e\x13\xd9\x31\xd1\x92\x92\xbb\x1d\x80\x41\xff\x2f\xe2\xe1\x17\x1a\x2e\x0b\x9a\x05\x98\x21\xd0\x92\x4d\xde\x7f\x3b\x1b\xb5\x98\x13\xf5\xe3\xc6\x35\x20\xaa\xfb\x88\x01\xba\x62\xc7\x09\x7d\x4d\x8c\xf4\x37\xa5\x68\xa7\xf0\x08\x7c\x6e\xa0\xfc\xe6\xe5\x68\xc4\x88\x3f\x1c\xd1\x2c\x74\x9d\x06\xa6\xfe\xb2\x78\xf1\x08\x6a\x8b\x04\x76\x99\x21\xf7\x8a\x99\x59\x06\x2a\xb0\x6f\x98\xee\x80\xc2\xc7\x85\x4f\xfa\x76\x0f\x86\xa8\x9e\xe1\xa5\x12\x66\x05\x3d\x19\x5e\x61\xbb\x1d\xbd\x18\xdd\x89\xff\x39\x4e\x40\x8a\xce\x0f\x64\x1a\x39\x5d\x56\x11\x8e\xa7\x2b\x7d\x8a\xdf\x78\xb1\x65\x5e\xce\xce\x7e\x82\x50\xe8\xa3\xa9\x1c\xb8\xfc\xa0\xd9\xce\x0b\xaf\x89\x80\xa3\x87\xc5\xed\x43\x18\x66\x32\x80\xe5\xb4\x53\x1f\x31\x87\xc4\x7e\xae\xa7\xc3\x29\x72\x8d\xdd\x0e\x40"}, -{{0x49,0xaf,0xf4,0x21,0xa7,0xcd,0x12,0x72,0x2a,0xa8,0x4c,0x48,0xc1,0xfb,0x1c,0x5f,0x8d,0x9e,0x27,0x7d,0x0a,0x99,0xec,0xbc,0x93,0x48,0xc3,0xaa,0xa7,0x4b,0xe4,0x22,},{0x88,0xd2,0xc2,0x62,0x66,0xf4,0x93,0xbc,0x67,0x57,0x8c,0xa0,0xb1,0xf5,0x11,0x60,0xcf,0x0f,0xdb,0x6a,0x09,0xa9,0x06,0xdb,0x9f,0xaa,0x68,0x6f,0x11,0xf8,0x20,0x8d,},{0x74,0x91,0x81,0x28,0x4d,0xf0,0x5d,0xbe,0x59,0x74,0xb9,0x17,0x82,0xa1,0xa7,0x6e,0xa0,0x86,0x42,0xcb,0x0f,0x0c,0x98,0xdb,0x58,0x6c,0x57,0x5c,0x21,0x0c,0xdc,0x8b,0x65,0x1b,0xd3,0x4b,0x75,0x7a,0xe3,0x8e,0x4b,0x6b,0xe9,0x46,0x52,0x35,0xbd,0x0e,0xca,0x43,0x0e,0x26,0xc3,0xee,0xde,0x56,0x1c,0x6e,0x82,0x4d,0xfa,0x20,0x0e,0x0a,},"\x70\xa1\xac\x14\x4b\x75\xfd\xa7\x55\x86\xa7\x9c\x36\xfd\x39\xcc\xe5\xf5\xca\xe2\xe6\x37\x58\x52\xd3\xb6\x2a\x96\x30\x33\x6a\x29\x3e\xa6\xd2\xac\x6e\x5b\x57\xda\x21\xef\x36\x4a\x59\x5b\xb0\x75\x0f\x5b\xf4\xd2\xb3\x20\x67\x64\x23\x87\x0e\x4b\x8e\x08\x69\x60\x1f\x16\x68\x06\x19\x04\x8c\x4e\xde\x27\x6d\xa6\x9f\x20\x5a\x70\x17\x6e\x25\xea\x04\xbd\x08\x97\x63\xe7\x09\xba\x34\x3f\xc8\x83\x1e\x52\x04\x4e\xab\xf9\x44\x1e\x69\x97\xf8\xba\x1a\xeb\x9e\xf0\xf4\x91\x17\x06\x67\xa7\xf5\xfc\x96\x27\xcb\xd0\x55\x1b\x76\xbe\x27\x28\x3a\x4b\x0c\x5f\x66\x78\x46\x68\x82\x26\xa1\x15\xee\x80\x20\xdf\x08\x04\x2b\x19\xb5\x9f\xe5\x51\x31\x6a\x6c\xb6\x91\x68\x60\xb9\xec\xd7\x41\x54\xb4\x05\x10\x38\xa1\x73\x52\x37\x2e\xc1\x4d\x3c\x95\x7d\x2e\xf5\x0f\xf7\x86\x18\x9a\x8a\xeb\x9c\x08\xf4\x5e\xeb\x5e\xb8\xb0\x40\x33\x99\x74\xaa\x97\x98\xc4\x25\xd7\xbe\xcb\x22\x8c\x44\x7a\x6d\x0b\x3c\xef\x27\x18\x93\xe0\xf7\x07\x6e\x22\x3a\x7e\x87\xc6\xa3\xd2\x70\xa0\x33\xbc\x97\xa4\x56\x5e\xdc\xe0\xaa\x91\xff\xc3\xf7\x80\x17\x75\xa6\xf2\x9b\x23\x02\x45\xbd\x71\xfa\x03\x43\x53\xde\x37\x23\x95\xd1\xbf\xcb\xde\xbb\xa0\x81\x33\x0f\x7c\x07\x6b\xe9\x9c\x2c\xf4\x86\x7f\x15\xb7\x8d\x52\xf4\x6f\xc7\x39\x1c\x9c\xb9\x5e\x5d\x64\x64\x3b\xaf\xfe\x72\xa8\xe3\xa6\x50\x66\x7f\xbb\x3e"}, -{{0x70,0x3a,0x6e,0x2b,0x62,0xd0,0x09,0x0c,0x61,0xd8,0x65,0x9b,0x6a,0x96,0x3e,0x03,0xc9,0xd6,0x2c,0x1b,0x38,0xf7,0xd7,0x0e,0x5f,0x9f,0xf0,0x55,0x90,0xcd,0x03,0x60,},{0x37,0x0c,0x21,0xde,0x6e,0xf2,0xfa,0xb5,0x34,0xad,0xa9,0x99,0x86,0x9c,0x90,0xbc,0x9b,0x92,0xcc,0xbf,0x24,0x9b,0x79,0xd3,0x9d,0x95,0x44,0x1d,0x1e,0xde,0x21,0x0a,},{0xe5,0xfd,0x64,0xda,0x02,0x88,0x00,0xc6,0xce,0xed,0x06,0x8a,0x5e,0x59,0x6f,0x16,0x21,0xc7,0x0a,0x8c,0xb1,0x38,0xb3,0x1b,0x32,0x64,0x7e,0xb4,0xb0,0x7b,0xd2,0xec,0xc5,0x94,0x2c,0x18,0x84,0x4f,0x36,0x70,0x33,0xf6,0x73,0x98,0xe3,0x14,0xba,0x2c,0x7c,0xcf,0x29,0x9c,0x06,0x97,0x87,0x77,0x70,0x25,0xd8,0x45,0xf2,0xaa,0xd6,0x0e,},"\xd4\x2a\x17\x56\xe8\x4d\xf4\xb4\xe9\x77\x3f\x86\xf7\x67\x4a\x2c\xd7\x8e\x71\xe4\x0a\xa8\xf6\x44\xe6\x70\x2d\xfb\xc2\xc2\xc5\xca\x90\xfc\x24\x2e\x9c\xb0\x09\x9c\xc8\xf2\xc2\xd3\x13\x6b\xaa\xfc\x0f\xf6\x95\x48\x2f\xda\xcd\xef\x9f\x56\x56\x10\xb6\xe1\x90\x07\x22\xf4\x35\xc6\x38\x5b\x35\xe9\xf6\xc4\x36\xca\x03\x7e\x03\xf6\x4e\x22\x33\xdf\xfa\x58\xdb\x3b\x91\xcc\x1d\xaa\x0b\xb0\xc5\x4c\x8a\x43\xe4\x69\xd2\xcf\xf7\xfa\x2b\xf8\xf5\xd1\xd8\x77\x93\x10\x89\xc8\x2e\xd8\x9a\xba\x42\xf2\xee\x2b\x86\xe4\x45\xcf\xd0\x9f\x4c\xd7\x8b\x35\x19\x1b\xf4\x67\xe7\x84\xee\xf7\x5d\xc9\x87\xe0\x46\xd3\x7d\x4d\x4e\x8e\x9b\xbe\x14\xaf\x80\xd0\x3a\x1f\x40\x89\x83\x84\xb9\xd3\x27\x9f\xac\x9c\x57\xfd\x9c\x7e\xec\xbe\x19\xa5\xac\xc1\x50\x33\xb8\x4e\x07\xfd\x0e\x40\x9b\xdb\xd5\xa5\x7f\x65\x64\x11\x83\xa6\xc0\xa8\xec\x42\x6d\x1f\x1d\x22\x31\x66\xff\x0a\x19\x00\xb2\xe9\x2b\x7d\x85\x83\x5d\x01\x9d\x17\x77\x5e\x50\x93\xcc\xd1\x26\xf9\x0f\x63\xcb\x7d\x15\xcb\xeb\x53\x13\x24\x21\x9c\xd6\x4d\xed\x67\x14\xb2\x1a\x65\x37\x1a\xf0\x72\x10\xdf\xdf\x0e\x4e\x58\xdd\xc7\xd5\x9f\x4c\xfa\x65\xc4\x21\xd8\x14\xee\x2c\x9b\xf6\xdb\xf6\x48\x73\xd5\x79\xb0\x9e\xe5\xdc\xed\xd7\x33\x06\x3e\x03\x9a\xc9\xa5\xf9\xca\x4c\x25\x25\xa4\xcc\x8e\x98\x4d\xa7\x18\x5e\x2d\x64\xfa\xd8\x1c\x8a"}, -{{0x76,0x84,0x9c,0x18,0x8e,0x3e,0xdd,0x0f,0xf5,0xf8,0xfb,0x87,0x4d,0xc0,0x45,0x66,0x45,0x51,0x84,0x45,0xe4,0x1a,0x7d,0x68,0x33,0xe6,0x16,0xc3,0xc4,0x8c,0x98,0x68,},{0xd6,0x70,0xe2,0xea,0x07,0xdb,0x60,0xc2,0x2a,0xb7,0x9a,0x93,0xeb,0xf4,0x9d,0x22,0xa6,0x24,0x5e,0xe3,0xaf,0x07,0xb3,0xbe,0x58,0x4e,0xda,0x69,0x4c,0x37,0x72,0x9e,},{0x71,0x41,0x39,0x9d,0x51,0xda,0xa6,0xeb,0x45,0x19,0xbf,0x3f,0x01,0xb2,0x33,0x92,0x0f,0xa9,0x08,0xfe,0xfa,0x61,0x2f,0x0c,0xd7,0xd5,0xaf,0x8a,0x9a,0x3c,0x44,0x19,0x0e,0x3f,0x63,0x84,0xa8,0xd1,0x4d,0x37,0xc9,0x70,0x30,0xef,0x50,0x18,0xcf,0x8a,0xee,0x8a,0xeb,0x15,0x69,0xa7,0x3d,0x84,0x86,0x2a,0x59,0xb7,0xdf,0x72,0xfe,0x09,},"\x1e\xcc\xb0\xbc\x8e\xca\x3a\xb5\xbe\xe6\x8c\x5f\x8c\xaa\x34\x53\x67\x66\xc7\x05\xf5\x08\x27\xdb\x7a\xc3\x75\xd4\xfe\x30\xb5\x8f\xfb\x7e\x2f\xe4\x90\xcc\x71\xa8\xff\x86\xc0\x06\xd6\x17\x4d\x05\x79\x3a\xb8\xa5\x5d\xd5\x1b\x06\xde\x41\x7b\xc0\xac\x45\x2c\xdc\x7c\xfb\x0b\xb0\x03\x62\xb6\x76\x5d\x20\xdb\x23\xeb\x18\x48\x02\x70\x64\xa1\xd9\x09\x1d\x3b\x10\xed\x77\x6f\x28\xb7\x67\x68\xbd\xfc\x08\xf0\xbc\x51\x1f\x76\xfa\xeb\xa7\x6c\xfc\x4c\xb5\xc8\x3d\xc9\xeb\xe8\xa8\xd7\x9e\xdc\xa9\x23\xec\xcd\x52\x40\x09\xca\xfe\xdc\x90\xe3\xad\x87\xd1\x39\x2e\x1f\xcc\xf4\xe6\x0c\xca\xb9\x5d\xc0\xab\x54\xbf\x44\x24\x5a\x00\x7a\x96\xd4\x66\x34\xb1\xb2\x96\x5b\x82\x9c\x3d\x7d\xaa\x76\x59\x72\xb5\x4a\x7b\x36\x5b\x6f\x34\xd7\x7d\x71\x76\xac\xd8\xd8\x94\xf6\xb4\x17\x09\x1b\x6c\x00\xed\xb7\xa4\xe8\x13\x79\x98\x8b\xfc\xec\xb6\x92\xe9\xc3\xc4\x31\x0a\x7e\x24\x0e\x5c\x10\x63\xcd\xe1\x13\xf2\x2a\x68\x4a\x50\xa1\x12\xff\x47\xd3\x89\x88\x12\xef\xb9\x26\x37\x07\x2b\x86\x16\x3a\xd8\x93\x16\xd2\x21\x19\x5a\xcb\xfa\xd0\xa0\x3a\x1f\xbc\x2d\x96\x7f\xe8\x3f\x84\xc8\x45\x9f\xcc\xd4\x90\xb9\xc5\xb3\xe5\x5d\x27\xe9\x48\x4e\x94\x3c\x41\x7f\x21\x28\xd7\x37\x01\xda\x28\xf4\x9f\xd3\x68\x3f\x33\xa3\x9c\xde\xe2\x34\xbd\x30\x5b\x94\x91\xe2\xf3\xeb\x62\x1b\xe3\xdd\x1d\xbb\xb3\x1b"}, -{{0x83,0xae,0x48,0xad,0x70,0xda,0x0b,0xb3,0xcd,0xf8,0x74,0x81,0xee,0x2c,0x0c,0x85,0x71,0xc2,0xca,0x98,0x67,0x12,0xf8,0xbc,0x23,0x29,0xe9,0xa3,0xe3,0x33,0x83,0xc5,},{0xb7,0x85,0x30,0x90,0x00,0xdf,0x95,0xf5,0xa0,0x4f,0x7d,0x89,0xc4,0x11,0x33,0x01,0x05,0x7a,0xda,0xee,0xb2,0x9b,0xcd,0x28,0xd9,0x93,0x71,0xb5,0x37,0xbb,0xa2,0xf6,},{0x43,0x33,0x23,0x51,0xd3,0xfb,0x7b,0x45,0xfc,0xf3,0x7c,0x60,0x7d,0x44,0x2e,0xa8,0x0d,0xbd,0xa2,0xcb,0x69,0xc2,0x88,0x4f,0x42,0x4e,0x65,0xea,0x3a,0x33,0x1e,0xd8,0x47,0x2d,0x43,0x68,0x40,0x5c,0xb7,0x36,0xb2,0xd6,0x68,0x5a,0xd7,0x82,0xe2,0x39,0xfe,0x83,0x3e,0xd7,0x89,0xa2,0x92,0x31,0x85,0x16,0x6f,0x60,0x83,0x42,0xee,0x05,},"\xb7\x52\x1d\x3f\x71\xc6\x79\xfa\x70\x37\xfe\x74\x88\xa6\x41\xf6\xb9\x7c\x49\x45\x4a\xcc\x8e\x36\xb9\x03\xd8\xf9\xeb\xb5\x4d\x89\xcb\x56\xef\xd1\x9e\x04\xba\x6a\x7c\x8f\x48\xa7\xd3\xec\x9d\xec\xd3\xf1\xcd\x0f\xaf\x6e\x97\x81\x18\xe6\xad\xce\x9c\x6c\x6b\xe6\x3c\x6a\x6a\x1a\xe2\x16\x51\x82\x84\x79\xa4\x6b\xc9\xa0\xf7\x94\x30\x40\xf9\x40\xa0\xd4\x70\xc8\xe5\x77\xc5\xd5\x75\xcb\x53\xc1\xbf\x3a\xb1\xfe\xb0\x50\xdc\xb6\xfe\xf0\xba\x44\x47\xf2\x99\xfd\xb9\xf2\x7e\xcb\x07\x14\xec\xfe\xfd\x74\xba\xd7\xb1\x22\xa4\x62\xc2\x4a\x20\x98\x48\xa0\x33\x89\x07\x45\x78\xc5\xbd\xc3\x63\x96\xd8\x09\xb0\xf1\x40\x18\xda\x64\x91\x7e\x6b\xf8\x7e\xf4\x05\xc8\xf3\xe3\x33\xff\x9c\x3b\xaf\x63\x39\x66\x76\x20\x79\x4b\xb4\x74\x3f\x05\x14\xb5\xde\x7d\x7f\xdd\x94\x7a\x7e\x35\x01\xee\x88\xef\xad\x15\x9e\x33\xa1\x07\x2f\xbb\x99\xc7\xc7\x1e\x9d\x13\xa5\x02\xd5\xa0\x7c\x4f\x81\x7e\xeb\x7f\x0c\x53\x19\xaa\x41\xa9\x6d\x5f\xf4\xf1\x5a\x73\xc2\x9b\x57\x1f\xe2\x11\x09\x0e\x17\x2c\x8d\xb5\x18\x62\x46\x12\xa5\xc3\x71\xa9\xd7\xce\xf6\xde\x35\xeb\xef\x96\xe8\x8e\x1a\x78\xaf\x3b\xd5\xdd\x35\x25\x1a\xb5\x4d\x73\x71\x8f\x3e\x70\xd2\xd5\x90\x21\x53\x1d\xc7\x31\x84\xf0\xfc\x69\xc2\xe9\x29\x65\x84\x4e\xc2\x7c\x1c\x02\xaf\x5e\x9a\x34\x69\xde\x35\x5d\xb2\x25\x6e\x0e\xc2\xa4\xeb\xa3\x0a"}, -{{0x39,0xe5,0x6a,0x65,0x62,0x3a,0x0a,0xeb,0xad,0xe0,0xda,0x12,0xce,0x1d,0xf3,0x78,0xbc,0x92,0x40,0x73,0xf7,0x3a,0x54,0x9e,0xff,0xae,0xbc,0x46,0x5d,0x1a,0x78,0xe2,},{0x83,0xda,0x8a,0xd5,0x0b,0xad,0x09,0xeb,0x3e,0x94,0xc7,0x25,0xdf,0x3c,0xc3,0xa1,0x19,0x73,0x6a,0xdc,0x85,0x9c,0xa1,0xa1,0x05,0x03,0xf4,0x8f,0xf2,0xfe,0xc5,0x96,},{0x39,0x8e,0x82,0x60,0x01,0x1f,0x57,0xd8,0xac,0x8c,0x58,0xd5,0x45,0x7b,0xc6,0x52,0xc7,0x41,0x4a,0xaf,0x6f,0xb2,0xf4,0x26,0xb7,0x89,0x90,0x56,0x60,0x5c,0x0a,0xfc,0x28,0x39,0x24,0x23,0xb2,0xb5,0x71,0xf5,0xe6,0xc3,0xc7,0xf6,0xd6,0x02,0x45,0xe5,0x3e,0xbd,0x03,0xbd,0xc5,0xad,0x3c,0x1a,0xd8,0x73,0x8c,0xb3,0x22,0x14,0xd0,0x0f,},"\xa9\x6d\xc2\xea\x3f\xa1\x35\x14\x92\xa4\x61\x9d\x91\x94\x68\x1f\x8e\xc4\x00\xa9\x71\x58\x24\x44\x82\x65\x38\x38\xcc\xb7\xe1\x56\xa8\x2d\x56\x43\x68\xf8\x3a\x6e\xe1\xbe\x46\xbc\x34\xb8\x17\x20\x0e\x84\x64\xc3\xd1\x2b\x5e\xf2\xc5\x0b\x19\x56\x5b\x88\x1c\x4c\x3d\x45\x63\xfb\x94\x7e\xb4\x7c\x3e\xe9\xc1\xee\x78\x53\x26\x98\x74\x45\x5b\xfa\xcb\xa3\x05\xf3\x07\xd1\xac\x53\x09\xee\xae\x5c\x07\xfa\x5c\x4d\x42\x8e\xdb\xc8\xb9\x52\x8c\x44\x15\x24\x3a\x9e\xf5\x80\xaf\xf8\xfc\xfb\x12\x00\x0a\x71\xfc\xee\xe8\x9d\xe9\x7f\x90\x27\x95\x29\xbc\xc8\x22\xed\x3c\xb3\x4c\x82\xba\x5f\xec\x15\xf4\x94\x56\x63\x63\x6d\x67\xb5\xfe\xce\xac\xc3\x1d\x25\xf9\x8a\xea\x07\xf7\x80\x0d\x5a\x10\x34\x25\x1c\xb9\x1d\xd0\x96\x3e\xc2\xc1\xa5\x47\x73\xa4\xd9\x6c\x18\x35\x7f\x8d\x10\x1d\xe5\x8e\x93\x2f\x8c\x6c\xdd\xe8\xe3\xcf\xce\xf5\xa7\x44\x3f\xdb\xa7\xb7\x83\x20\x40\x3c\x01\x96\x84\x47\x24\xa6\x12\x18\x3e\x34\xbd\xd8\x08\xce\x7b\x95\x88\x61\xca\x37\x11\x57\x30\xea\xed\xe1\xfd\x0b\xaa\xbe\x97\x6e\xfe\xfd\x03\x65\xfd\xf9\x26\x77\x6c\x53\x6f\x47\xff\x80\xde\x5c\x18\x29\x1b\xb7\xe9\xf1\xb9\x13\xff\xd1\xd9\x44\x68\xb7\x89\x75\x2f\xae\x6c\xa8\x97\xc0\xcc\xa5\x3e\xf1\xe7\x31\xd0\x0c\x8b\xdb\xe8\x92\x9e\xa6\xb1\xdc\xe1\xf3\x1a\x20\x68\x8d\x37\xb0\xf3\xa2\xb4\x15\x3b\x30\x6b\xdb\xa1"}, -{{0x4b,0x99,0x21,0x85,0x2f,0x40,0x9a,0x32,0x3a,0xe3,0x81,0x75,0xe8,0xd7,0x6a,0x21,0x1f,0xc4,0xd9,0xc6,0x54,0x17,0x8e,0xea,0x3b,0xaa,0x7a,0x76,0x7a,0x6f,0xda,0x06,},{0x4c,0x72,0x3e,0x43,0x6b,0x6b,0xd9,0x7f,0x44,0xaf,0x52,0x50,0x3b,0x21,0xcc,0x50,0xd5,0xf6,0xad,0x6c,0xfc,0x82,0x88,0x34,0x5d,0xde,0x80,0x54,0xe9,0x95,0x58,0x2e,},{0xcb,0xf1,0xf1,0x64,0x2d,0xf9,0x50,0xeb,0x71,0xfd,0x09,0x59,0x0d,0x34,0xc2,0x65,0x92,0x2c,0x58,0xbd,0x80,0x26,0xbb,0xa3,0xfc,0x0e,0x59,0x4a,0x6b,0xb1,0xf2,0xb9,0x0d,0xa3,0xdc,0x1d,0x5f,0x6b,0x6d,0x5b,0x40,0x5a,0x89,0x6d,0x1d,0xbb,0x71,0xb8,0x68,0x5c,0x4d,0xfc,0x44,0x4a,0xca,0xff,0xe6,0x5a,0xb8,0x33,0x17,0x89,0xf5,0x07,},"\x3f\x33\xd8\xfb\x83\xe6\x87\x41\x09\x0a\x37\xbe\xdd\x74\x5c\xf1\x41\xaa\xae\xd8\xc9\x2f\xfa\x74\x2a\x52\x56\x17\x77\x88\x58\x05\xac\xe1\x42\x46\xab\x98\xa8\xcb\x59\x8c\x9c\xe3\xde\x9b\x29\xba\xe5\xfa\x04\xb1\xcf\x82\x8d\xe1\x1a\xff\x80\xa7\xef\x8a\x3a\x38\xae\xde\x4f\x3c\x35\x63\xa2\x5d\x04\x9b\xad\xca\xd5\xed\x7e\x47\xfd\xbb\xa6\xe1\x11\x30\x7e\xeb\xe9\xef\x49\x06\xbc\x98\x97\x28\xb7\x6e\x84\xaf\xe8\x08\xe6\x65\x3b\x27\x1e\x21\x10\x4a\xa6\x65\xf1\x89\x8d\xd2\xaa\xb2\x30\x90\xe2\x2b\x4e\x34\x4a\x26\x16\xfb\xd8\xee\x4a\xd8\xed\x81\x08\x39\x5e\xba\x81\x7f\xbd\x14\xfe\xc5\xc1\x7d\xcf\x56\xb8\x22\x08\x56\xb2\xb8\x33\xe0\x91\x40\x7d\x50\x89\xb3\x5d\xdf\x34\xb8\x6f\xf7\xdc\x9f\xde\x52\xb2\x1e\xf1\x21\x76\xef\x33\x70\xb7\xf3\xa0\xa8\xcb\x1b\x05\x8a\x51\xae\xff\xf3\xd2\x79\xd8\x0f\x51\xa6\x8b\xfb\x59\x25\x87\xb4\x5c\x5c\x63\xa7\xe4\xd6\x25\xb8\x87\xde\x48\x6a\x11\x83\x16\xc3\xb6\xa2\x38\x57\x5f\x92\xac\x5b\x1c\x94\xc3\xf5\xdb\xbd\x96\x68\x60\x00\xd6\xd3\x9c\xcc\xd5\x58\xd4\x20\xe4\xd4\x47\xa8\xcb\xc4\xbc\x7b\x8c\x6a\x03\xaf\x0f\x00\x34\xfb\x35\x18\xd9\x38\x00\xf0\xf7\x13\xe4\xb1\x37\x32\xe1\x6a\xda\x51\x80\x1d\x7e\x55\x9c\xf8\x39\xd1\x05\x8f\x64\x95\x56\x98\x31\x13\x99\x34\x54\x16\x85\x0d\xdd\xcc\x56\x01\xa6\x84\xfd\x09\xe6\xaf\xd3\x94\x4f\x5e\x19"}, -{{0x1b,0xff,0x65,0x2a,0x2c,0x83,0x09,0xa3,0x93,0xac,0x11,0xda,0x3a,0xa9,0x7f,0xb0,0x78,0xbb,0x28,0x4e,0xd5,0xe1,0xb8,0xcc,0xc9,0x83,0x65,0x2e,0xf8,0x55,0x6c,0xd0,},{0xaa,0xab,0xdc,0x09,0x1f,0xc3,0x68,0x23,0x54,0x20,0x17,0x44,0xe9,0xb7,0x3f,0xd2,0xa6,0xcf,0xb2,0x81,0x91,0x4b,0xf2,0xc7,0x0e,0xc3,0xdc,0x1d,0xec,0x72,0x16,0xb0,},{0x93,0xc9,0xc3,0x34,0x93,0xfc,0x64,0x17,0x2d,0x51,0xe1,0x6a,0x0a,0x1c,0xd7,0x29,0xa0,0xd9,0x9e,0x3c,0xb8,0x64,0xe8,0x9a,0x42,0x98,0x7f,0x39,0xdd,0x8c,0xd2,0x65,0x45,0xfd,0xfe,0x37,0x58,0x19,0x11,0xe8,0x03,0x67,0x7d,0xa4,0xc5,0x5b,0x0a,0x68,0x3d,0xdf,0x62,0xb7,0x28,0xf8,0xf3,0x06,0x85,0xae,0x58,0xf6,0x28,0xeb,0xe6,0x09,},"\x48\xd0\x26\x98\xa9\x7b\xdc\xb3\xef\x07\x8d\xcf\xcf\x57\x50\x00\x5f\x17\x02\xd3\x00\xe7\xe8\x9b\xc4\x36\xe3\x81\x11\x34\x01\xf8\x52\xb8\xb4\xac\xff\x60\xff\xbd\x4a\xb4\x6d\x20\x21\x68\xd9\x8b\x87\x35\xe7\x9c\xb3\x50\xe3\x5b\x07\x0f\xf6\xbd\xca\xfd\x95\x4b\x55\x19\x69\xb6\xb1\xa7\x0c\x91\x31\xeb\xd4\x0d\x96\x14\x02\x91\xd8\xd2\xb0\x91\x54\x0a\x8b\x18\xd8\xe5\x46\x59\x15\xc2\x5d\xbc\x6b\x5c\x9a\x68\x79\x42\x53\x3c\x37\x2c\x8b\x4e\x95\xa9\x53\x67\x71\x69\xb9\x50\xed\xd3\x46\x43\x75\xcd\x43\x13\x2f\xf9\xbd\x54\x1e\xe2\x2b\xd4\x18\xce\x23\x19\x5f\x65\xd8\xb2\x89\xf6\x33\xec\x8d\x71\xe1\xa8\x01\xb0\x6c\x3c\x82\x7f\x62\x7e\x72\x3d\x21\x99\x10\x0c\xe7\x3e\x8e\x4a\x44\x40\xe7\x78\x31\x7a\x47\x49\x10\x79\x3b\x47\xb1\x0f\xfb\x55\xdb\x7f\x28\x1c\x7d\x7a\x03\x3b\xd8\x00\x48\xb8\x26\x73\xb8\x7c\xf9\x5e\x99\x42\x2b\xa6\x28\x68\x8f\x3c\x97\x18\x90\xca\x15\xd1\x2f\x57\x2f\xa1\x97\x7a\x17\x30\x70\x69\xda\x30\x4e\xad\x30\x26\xeb\x01\x04\x26\x68\x89\x0d\x17\x00\x8c\xd1\xe9\x2c\x46\xcb\xe9\xc8\x57\xe7\x19\x3d\xe3\xab\xa3\x91\x1e\x4f\x86\xfe\x0a\x16\x98\xab\x7c\xdb\x92\x51\xa8\x42\x4b\x28\x48\xb9\x6a\xd8\x1e\xa2\x39\xd3\x65\xfd\xea\x92\xea\x5c\x04\x73\xd0\xa6\xbb\x1e\x37\x13\x56\xbd\xfa\xd2\xd0\x35\x03\x36\xd3\xe1\x94\x7c\x93\x6f\xd0\xc2\x51\x95\x44\x50\x11\x73\x1b"}, -{{0x00,0x2f,0xdd,0x1f,0x76,0x41,0x79,0x3a,0xb0,0x64,0xbb,0x7a,0xa8,0x48,0xf7,0x62,0xe7,0xec,0x6e,0x33,0x2f,0xfc,0x26,0xee,0xac,0xda,0x14,0x1a,0xe3,0x3b,0x17,0x83,},{0x77,0xd1,0xd8,0xeb,0xac,0xd1,0x3f,0x4e,0x2f,0x8a,0x40,0xe2,0x8c,0x4a,0x63,0xbc,0x9c,0xe3,0xbf,0xb6,0x97,0x16,0x33,0x4b,0xcb,0x28,0xa3,0x3e,0xb1,0x34,0x08,0x6c,},{0x0d,0xf3,0xaa,0x0d,0x09,0x99,0xad,0x3d,0xc5,0x80,0x37,0x8f,0x52,0xd1,0x52,0x70,0x0d,0x5b,0x3b,0x05,0x7f,0x56,0xa6,0x6f,0x92,0x11,0x2e,0x44,0x1e,0x1c,0xb9,0x12,0x3c,0x66,0xf1,0x87,0x12,0xc8,0x7e,0xfe,0x22,0xd2,0x57,0x37,0x77,0x29,0x62,0x41,0x21,0x69,0x04,0xd7,0xcd,0xd7,0xd5,0xea,0x43,0x39,0x28,0xbd,0x28,0x72,0xfa,0x0c,},"\x5a\xc1\xdf\xc3\x24\xf4\x3e\x6c\xb7\x9a\x87\xab\x04\x70\xfa\x85\x7b\x51\xfb\x94\x49\x82\xe1\x90\x74\xca\x44\xb1\xe4\x00\x82\xc1\xd0\x7b\x92\xef\xa7\xea\x55\xad\x42\xb7\xc0\x27\xe0\xb9\xe3\x37\x56\xd9\x5a\x2c\x17\x96\xa7\xc2\x06\x68\x11\xdc\x41\x85\x83\x77\xd4\xb8\x35\xc1\x68\x8d\x63\x88\x84\xcd\x2a\xd8\x97\x0b\x74\xc1\xa5\x4a\xad\xd2\x70\x64\x16\x39\x28\xa7\x79\x88\xb2\x44\x03\xaa\x85\xaf\x82\xce\xab\x6b\x72\x8e\x55\x47\x61\xaf\x71\x75\xae\xb9\x92\x15\xb7\x42\x1e\x44\x74\xc0\x4d\x21\x3e\x01\xff\x03\xe3\x52\x9b\x11\x07\x7c\xdf\x28\x96\x4b\x8c\x49\xc5\x64\x9e\x3a\x46\xfa\x0a\x09\xdc\xd5\x9d\xca\xd5\x8b\x9b\x92\x2a\x83\x21\x0a\xcd\x5e\x65\x06\x55\x31\x40\x02\x34\xf5\xe4\x0c\xdd\xcf\x98\x04\x96\x8e\x3e\x9a\xc6\xf5\xc4\x4a\xf6\x50\x01\xe1\x58\x06\x7f\xc3\xa6\x60\x50\x2d\x13\xfa\x88\x74\xfa\x93\x33\x21\x38\xd9\x60\x6b\xc4\x1b\x4c\xee\x7e\xdc\x39\xd7\x53\xda\xe1\x2a\x87\x39\x41\xbb\x35\x7f\x7e\x92\xa4\x49\x88\x47\xd6\x60\x54\x56\xcb\x8c\x0b\x42\x5a\x47\xd7\xd3\xca\x37\xe5\x4e\x90\x3a\x41\xe6\x45\x0a\x35\xeb\xe5\x23\x7c\x6f\x0c\x1b\xbb\xc1\xfd\x71\xfb\x7c\xd8\x93\xd1\x89\x85\x02\x95\xc1\x99\xb7\xd8\x8a\xf2\x6b\xc8\x54\x89\x75\xfd\xa1\x09\x9f\xfe\xfe\xe4\x2a\x52\xf3\x42\x8d\xdf\xf3\x5e\x01\x73\xd3\x33\x95\x62\x50\x7a\xc5\xd2\xc4\x5b\xbd\x2c\x19\xcf\xe8\x9b"}, -{{0x25,0xb0,0xf0,0xbb,0x3d,0xcb,0x42,0x2a,0x6f,0x3c,0x6c,0x22,0x0e,0xaa,0xdb,0x11,0xdb,0xfe,0x48,0x9c,0x2d,0x45,0x5b,0x27,0x6c,0xef,0xe8,0xcb,0xa0,0x57,0xf9,0xf3,},{0xfe,0x03,0xc9,0xc4,0x39,0x4a,0xdc,0x74,0xb1,0x3f,0x47,0x65,0x4b,0xea,0xd8,0xbc,0x85,0x59,0x58,0xb4,0x19,0x4f,0xda,0xb2,0x09,0x7a,0xc1,0xb1,0x57,0x93,0x3c,0x05,},{0xda,0x50,0xd5,0x24,0x2b,0xf5,0x1c,0x39,0x51,0x78,0x0c,0xaf,0xd9,0x26,0xd6,0x7b,0xdf,0x56,0x40,0xd5,0xd3,0xbb,0x08,0x43,0x38,0x31,0xd5,0x6e,0x48,0xe2,0x59,0x2a,0x1c,0x37,0x59,0x68,0xbb,0x4d,0x2f,0xbe,0xa5,0x61,0x45,0xab,0xf2,0xd8,0x29,0x91,0x36,0x3b,0x15,0x65,0xfa,0x1e,0xff,0xe2,0x14,0x01,0x1a,0x68,0x6e,0x39,0x95,0x0e,},"\x54\xd9\x9f\x96\x9e\xfa\x88\x70\xfc\x20\xfa\x9a\x96\x2b\xb3\x72\x61\x9c\x32\x44\x39\x72\x8a\xf3\x13\x9c\x2a\x07\xe8\xc1\xb2\x9c\x1e\x4e\xed\xc2\xd4\x0b\xa7\x22\xf6\x3c\xe3\x76\x70\x36\x2a\xf6\xf5\x20\x2a\xdd\x66\x8c\x4f\xb4\xd6\x2f\xa8\xba\xcb\xc7\xd0\x7f\xf3\xbd\x38\xc1\x5a\x01\x06\x42\x59\xcc\x34\x13\x48\x61\x63\x29\x67\x46\x05\x41\xa9\x9b\x8d\x51\x82\xbf\x59\x34\x7b\x5a\x59\x87\x9a\xa3\xb0\x91\xa1\xf3\xe0\x41\x35\xbd\x63\x01\xbe\x52\x26\xd4\x89\x5e\x5e\x9c\x2b\x15\xe4\x8e\x5e\xcd\xf4\x41\x29\xe6\x12\x28\x53\xa6\x06\xfc\x11\x84\x66\xfa\x72\x0b\x5a\xb1\x65\x63\x5c\x3b\xde\x04\xd7\x42\x89\x27\x4f\xa0\x35\x47\xac\xcb\xde\x78\x0e\x1f\xa0\xbf\x2c\x56\xf8\x43\x6a\x53\xe7\x38\x78\xa4\x24\xa2\x9a\xa9\xde\x38\x5d\xba\x41\x9a\xe6\xa5\xd1\x2e\x00\x42\x76\x15\x2b\x58\xd3\x25\xb3\x02\x40\x0a\x55\x33\x3c\x38\xcd\xe4\x90\x8a\xe1\xd0\x12\x1c\xbe\xca\x95\x08\x09\xc5\x43\x31\x42\x77\xc1\x48\x5e\x68\xd9\xf9\xc0\xa9\x62\xd1\xb1\xe0\xdd\xa1\xd4\xa5\x2b\x56\xf8\x30\x8a\x80\xb9\x2a\xcc\x9f\x4e\xbc\x3e\xd4\x5d\x91\xa1\x29\xda\x86\x75\x62\x1a\xf6\x76\x70\x3d\xef\x3b\x84\x11\x31\x83\xb2\xe3\xa8\xc5\x61\x57\xf2\x43\xf1\x39\x80\xf3\xd1\x75\x6f\xea\x76\x68\xc9\x15\x03\xd3\x5c\x83\x9a\x21\x20\xc7\x9e\xc9\x54\xfb\x54\x6d\x7b\x54\x2f\x98\x72\x89\x53\x4f\xfd\xef\x62\xd4\x7f\xd5\xec"}, -{{0xbf,0x5b,0xa5,0xd6,0xa4,0x9d,0xd5,0xef,0x7b,0x4d,0x5d,0x7d,0x3e,0x4e,0xcc,0x50,0x5c,0x01,0xf6,0xcc,0xee,0x4c,0x54,0xb5,0xef,0x7b,0x40,0xaf,0x6a,0x45,0x41,0x40,},{0x1b,0xe0,0x34,0xf8,0x13,0x01,0x7b,0x90,0x0d,0x89,0x90,0xaf,0x45,0xfa,0xd5,0xb5,0x21,0x4b,0x57,0x3b,0xd3,0x03,0xef,0x7a,0x75,0xef,0x4b,0x8c,0x5c,0x5b,0x98,0x42,},{0x27,0x9c,0xac,0xe6,0xfd,0xaf,0x39,0x45,0xe3,0x83,0x7d,0xf4,0x74,0xb2,0x86,0x46,0x14,0x37,0x47,0x63,0x2b,0xed,0xe9,0x3e,0x7a,0x66,0xf5,0xca,0x29,0x1d,0x2c,0x24,0x97,0x85,0x12,0xca,0x0c,0xb8,0x82,0x7c,0x8c,0x32,0x26,0x85,0xbd,0x60,0x55,0x03,0xa5,0xec,0x94,0xdb,0xae,0x61,0xbb,0xdc,0xae,0x1e,0x49,0x65,0x06,0x02,0xbc,0x07,},"\x16\x15\x2c\x2e\x03\x7b\x1c\x0d\x32\x19\xce\xd8\xe0\x67\x4a\xee\x6b\x57\x83\x4b\x55\x10\x6c\x53\x44\x62\x53\x22\xda\x63\x8e\xce\xa2\xfc\x9a\x42\x4a\x05\xee\x95\x12\xd4\x8f\xcf\x75\xdd\x8b\xd4\x69\x1b\x3c\x10\xc2\x8e\xc9\x8e\xe1\xaf\xa5\xb8\x63\xd1\xc3\x67\x95\xed\x18\x10\x5d\xb3\xa9\xaa\xbd\x9d\x2b\x4c\x17\x47\xad\xba\xf1\xa5\x6f\xfc\xc0\xc5\x33\xc1\xc0\xfa\xef\x33\x1c\xdb\x79\xd9\x61\xfa\x39\xf8\x80\xa1\xb8\xb1\x16\x47\x41\x82\x2e\xfb\x15\xa7\x25\x9a\x46\x5b\xef\x21\x28\x55\x75\x1f\xab\x66\xa8\x97\xbf\xa2\x11\xab\xe0\xea\x2f\x2e\x1c\xd8\xa1\x1d\x80\xe1\x42\xcd\xe1\x26\x3e\xec\x26\x7a\x31\x38\xae\x1f\xcf\x40\x99\xdb\x0a\xb5\x3d\x64\xf3\x36\xf4\xbc\xd7\xa3\x63\xf6\xdb\x11\x2c\x0a\x24\x53\x05\x1a\x00\x06\xf8\x13\xaa\xf4\xae\x94\x8a\x20\x90\x61\x93\x74\xfa\x58\x05\x24\x09\xc2\x8e\xf7\x62\x25\x68\x7d\xf3\xcb\x2d\x1b\x0b\xfb\x43\xb0\x9f\x47\xf1\x23\x2f\x79\x0e\x6d\x8d\xea\x75\x9e\x57\x94\x20\x99\xf4\xc4\xbd\x33\x90\xf2\x8a\xfc\x20\x98\x24\x49\x61\x46\x5c\x64\x3f\xc8\xb2\x97\x66\xaf\x2b\xcb\xc5\x44\x0b\x86\xe8\x36\x08\xcf\xc9\x37\xbe\x98\xbb\x48\x27\xfd\x5e\x6b\x68\x9a\xdc\x2e\x26\x51\x3d\xb5\x31\x07\x6a\x65\x64\x39\x62\x55\xa0\x99\x75\xb7\x03\x4d\xac\x06\x46\x1b\x25\x56\x42\xe3\xa7\xed\x75\xfa\x9f\xc2\x65\x01\x1f\x5f\x62\x50\x38\x2a\x84\xac\x26\x8d\x63\xba\x64"}, -{{0x65,0xde,0x29,0x7b,0x70,0xcb,0xe8,0x09,0x80,0x50,0x0a,0xf0,0x56,0x1a,0x24,0xdb,0x50,0x00,0x10,0x00,0x12,0x5f,0x44,0x90,0x36,0x6d,0x83,0x00,0xd3,0x12,0x85,0x92,},{0xba,0x8e,0x2a,0xd9,0x29,0xbd,0xce,0xa5,0x38,0x74,0x10,0x42,0xb5,0x7f,0x20,0x67,0xd3,0x15,0x37,0x07,0xa4,0x53,0x77,0x0d,0xb9,0xf3,0xc4,0xca,0x75,0x50,0x4d,0x24,},{0x7a,0x9b,0x73,0x6b,0x01,0xcc,0x92,0xa3,0x34,0x9f,0x1a,0x3c,0x32,0xdb,0xd9,0x19,0x59,0x82,0x53,0x94,0xff,0x44,0x3c,0x56,0x74,0x05,0xe8,0x99,0xc8,0x18,0x5c,0xe8,0xfa,0xd9,0x50,0x0e,0x1f,0xce,0x89,0xd9,0x5a,0x62,0x53,0xc0,0x04,0x77,0x43,0x5a,0xcf,0x04,0xbf,0xf9,0x93,0xde,0x1b,0x00,0x49,0x5d,0xef,0x08,0x34,0xee,0x1f,0x07,},"\x13\x1d\x8f\x4c\x2c\x94\xb1\x53\x56\x5b\x86\x59\x2e\x77\x0c\x98\x7a\x44\x34\x61\xb3\x9a\xa2\x40\x8b\x29\xe2\x13\xab\x05\x7a\xff\xc5\x98\xb5\x83\x73\x9d\x66\x03\xa8\x3f\xef\x0a\xfc\x51\x47\x21\xdb\x0e\x76\xf9\xbd\x1b\x72\xb9\x8c\x56\x5c\xc8\x88\x1a\xf5\x74\x7c\x0b\xa6\xf5\x8c\x53\xdd\x23\x77\xda\x6c\x0d\x3a\xa8\x05\x62\x0c\xc4\xe7\x5d\x52\xaa\xbc\xba\x1f\x9b\x28\x49\xe0\x8b\xd1\xb6\xb9\x2e\x6f\x06\x61\x5b\x81\x45\x19\x60\x6a\x02\xdc\x65\xa8\x60\x9f\x5b\x29\xe9\xc2\xaf\x5a\x89\x4f\x71\x16\xef\x28\xcf\xd1\xe7\xb7\x6b\x64\x06\x17\x32\xf7\xa5\xa3\xf8\xaa\x4c\x2e\x56\x9e\x62\x7a\x3f\x97\x49\xaa\x59\x7b\xe4\x9d\x6b\x94\x43\x6c\x35\x2d\xd5\xfa\x7b\x83\xc9\x2d\x26\x10\xfa\xa3\x20\x95\xca\x30\x21\x52\xd9\x1a\x3c\x97\x76\x75\x0e\x75\x8e\xe8\xe9\xe4\x02\xc6\xf5\x38\x5e\xaa\x5d\xf2\x38\x50\xe5\x4b\xeb\x1b\xe4\x37\xa4\x16\xc7\x11\x5e\xd6\xaa\x6d\xe1\x3b\x55\x48\x25\x32\x78\x7e\x0b\xee\x34\xb8\x3f\x30\x84\x40\x67\x65\x63\x54\x97\xc9\x31\xb6\x2a\x05\x18\xf1\xfb\xc2\xb8\x91\xdc\x72\x62\xc7\xc6\xb6\x7e\xda\x59\x4f\xa5\x30\xd7\x4c\x93\x29\xba\xd5\xbe\x94\xc2\x87\xfb\xcd\xe5\x3a\xa8\x02\x72\xb8\x33\x22\x61\x3d\x93\x68\xe5\x90\x40\x76\xfd\xbc\xc8\x8b\x2c\x0e\x59\xc1\x0b\x02\xc4\x48\xe0\x0d\x1b\x3e\x7a\x9c\x96\x40\xfe\xff\xb9\x52\x3a\x8a\x60\xe1\xd8\x3f\x04\xa4\xb8\xdf\x69\x15\x3b"}, -{{0x08,0x26,0xe7,0x33,0x33,0x24,0xe7,0xec,0x8c,0x76,0x42,0x92,0xf6,0x01,0x5d,0x46,0x70,0xe9,0xb8,0xd7,0xc4,0xa8,0x9e,0x8d,0x90,0x9e,0x8e,0xf4,0x35,0xd1,0x8d,0x15,},{0xff,0xb2,0x34,0x8c,0xa8,0xa0,0x18,0x05,0x8b,0xe7,0x1d,0x15,0x12,0xf3,0x76,0xf9,0x1e,0x8b,0x0d,0x55,0x25,0x81,0x25,0x4e,0x10,0x76,0x02,0x21,0x73,0x95,0xe6,0x62,},{0x4b,0xac,0x7f,0xab,0xec,0x87,0x24,0xd8,0x1a,0xb0,0x9a,0xe1,0x30,0x87,0x4d,0x70,0xb5,0x21,0x34,0x92,0x10,0x43,0x72,0xf6,0x01,0xae,0x5a,0xbb,0x10,0x53,0x27,0x99,0x37,0x3c,0x4d,0xad,0x21,0x58,0x76,0x44,0x1f,0x47,0x4e,0x2c,0x00,0x6b,0xe3,0x7c,0x3c,0x8f,0x5f,0x6f,0x01,0x7d,0x08,0x70,0x41,0x4f,0xd2,0x76,0xa8,0xf4,0x28,0x08,},"\x7f\x9e\x3e\x2f\x03\xc9\xdf\x3d\x21\xb9\x90\xf5\xa4\xaf\x82\x95\x73\x4a\xfe\x78\x3a\xcc\xc3\x4f\xb1\xe9\xb8\xe9\x5a\x0f\xd8\x37\xaf\x7e\x05\xc1\x3c\xda\x0d\xe8\xfa\xda\xc9\x20\x52\x65\xa0\x79\x2b\x52\x56\x3b\xdc\x2f\xee\x76\x63\x48\xbe\xfc\xc5\x6b\x88\xbb\xb9\x5f\x15\x44\x14\xfb\x18\x6e\xc4\x36\xaa\x62\xea\x6f\xca\xbb\x11\xc0\x17\xa9\xd2\xd1\x5f\x67\xe5\x95\x98\x0e\x04\xc9\x31\x3b\xc9\x4f\xbc\x8c\x11\x34\xc2\xf4\x03\x32\xbc\x7e\x31\x1a\xc1\xce\x11\xb5\x05\xf8\x57\x2a\xda\x7f\xbe\x19\x6f\xba\x82\x2d\x9a\x91\x44\x92\xfa\x71\x85\xe9\xf3\xbe\xa4\x68\x72\x00\xa5\x24\xc6\x73\xa1\xcd\xf8\x7e\xb3\xa1\x40\xdc\xdb\x6a\x88\x75\x61\x34\x88\xa2\xb0\x0a\xdf\x71\x75\x34\x1c\x1c\x25\x76\x35\xfa\x1a\x53\xa3\xe2\x1d\x60\xc2\x28\x39\x9e\xea\x09\x91\xf1\x12\xc6\x0f\x65\x3d\x71\x48\xe2\xc5\xce\xb9\x8f\x94\x08\x31\xf0\x70\xdb\x10\x84\xd7\x91\x56\xcc\x82\xc4\x6b\xc9\xb8\xe8\x84\xf3\xfa\x81\xbe\x2d\xa4\xcd\xda\x46\xbc\xaa\x24\xcc\x46\x1f\x76\xee\x64\x7b\xb0\xf0\xf8\xc1\x5a\xc5\xda\xa7\x95\xb9\x45\xe6\xf8\x5b\xb3\x10\x36\x2e\x48\xd8\x09\x5c\x78\x2c\x61\xc5\x2b\x48\x1b\x4b\x00\x2a\xd0\x6e\xa7\x4b\x8d\x30\x6e\xff\x71\xab\xf2\x1d\xb7\x10\xa8\x91\x3c\xbe\x48\x33\x2b\xe0\xa0\xb3\xf3\x1e\x0c\x7a\x6e\xba\x85\xce\x33\xf3\x57\xc7\xae\xcc\xd3\x0b\xfb\x1a\x65\x74\x40\x8b\x66\xfe\x40\x4d\x31\xc3\xc5"}, -{{0x00,0xad,0x62,0x27,0x97,0x7b,0x5f,0x38,0xcc,0xda,0x99,0x4d,0x92,0x8b,0xba,0x90,0x86,0xd2,0xda,0xeb,0x01,0x3f,0x86,0x90,0xdb,0x98,0x66,0x48,0xb9,0x0c,0x1d,0x45,},{0x91,0xa4,0xea,0x00,0x57,0x52,0xb9,0x2c,0xbe,0xbf,0x99,0xa8,0xa5,0xcb,0xec,0xd2,0x40,0xae,0x3f,0x01,0x6c,0x44,0xad,0x14,0x1b,0x2e,0x57,0xdd,0xc7,0x73,0xdc,0x8e,},{0xdc,0x50,0x1d,0xb7,0x9f,0xd7,0x82,0xbc,0x88,0xca,0xe7,0x92,0x55,0x7d,0x5d,0x27,0x3f,0x9b,0xa5,0x60,0xc7,0xd9,0x00,0x37,0xfe,0x84,0xac,0x87,0x9d,0x68,0x4f,0x61,0x2a,0x77,0x45,0x2c,0x44,0x43,0xe9,0x5c,0x07,0xb8,0xbe,0x19,0x2c,0x35,0x76,0x9b,0x17,0xbb,0xdf,0xca,0x42,0x28,0x0d,0xe7,0x96,0xd9,0x21,0x19,0xd8,0x33,0x67,0x0d,},"\xcb\x5b\xc5\xb9\x8b\x2e\xfc\xe4\x35\x43\xe9\x1d\xf0\x41\xe0\xdb\xb5\x3e\xd8\xf6\x7b\xf0\xf1\x97\xc5\x2b\x22\x11\xe7\xa4\x5e\x2e\x1e\xc8\x18\xc1\xa8\x0e\x10\xab\xf6\xa4\x35\x35\xf5\xb7\x9d\x97\x4d\x8a\xe2\x8a\x22\x95\xc0\xa6\x52\x17\x63\xb6\x07\xd5\x10\x3c\x6a\xef\x3b\x27\x86\xbd\x5a\xfd\x75\x63\x69\x56\x60\x68\x43\x37\xbc\x30\x90\x73\x9f\xb1\xcd\x53\xa9\xd6\x44\x13\x9b\x6d\x4c\xae\xc7\x5b\xda\x7f\x25\x21\xfb\xfe\x67\x6a\xb4\x5b\x98\xcb\x31\x7a\xa7\xca\x79\xfc\x54\xa3\xd7\xc5\x78\x46\x6a\x6a\xa6\x4e\x43\x4e\x92\x34\x65\xa7\xf2\x11\xaa\x0c\x61\x68\x1b\xb8\x48\x6e\x90\x20\x6a\x25\x25\x0d\x3f\xda\xe6\xfb\x03\x29\x97\x21\xe9\x9e\x2a\x91\x49\x10\xd9\x17\x60\x08\x9b\x5d\x28\x1e\x13\x1e\x6c\x83\x6b\xc2\xde\x08\xf7\xe0\x2c\x48\xd3\x23\xc6\x47\xe9\x53\x6c\x00\xec\x10\x39\x20\x1c\x03\x62\x61\x8c\x7d\x47\xaa\x8e\x7b\x97\x15\xff\xc4\x39\x98\x7a\xe1\xd3\x11\x54\xa6\x19\x8c\x5a\xa1\x1c\x12\x8f\x40\x82\xf5\x56\xc9\x9b\xaf\x10\x3e\xca\xdc\x3b\x2f\x3b\x2e\xc5\xb4\x69\x62\x3b\xc0\x3a\x53\xca\xf3\x81\x4b\x16\x30\x0a\xed\xbd\xa5\x38\xd6\x76\xd1\xf6\x07\x10\x26\x39\xdb\x2a\x62\xc4\x46\x70\x7c\xe6\x46\x9b\xd8\x73\xa0\x46\x82\x25\xbe\x88\xb0\xae\xf5\xd4\x02\x04\x59\xb9\x4b\x32\xfe\x2b\x01\x33\xe9\x2e\x7b\xa5\x4d\xd2\xa5\x39\x7e\xd8\x5f\x96\x6a\xb3\x9e\xd0\x73\x0c\xca\x8e\x7d\xac\xb8\xa3\x36"}, -{{0x15,0x21,0xc6,0xdb,0xd6,0xf7,0x24,0xde,0x73,0xea,0xf7,0xb5,0x62,0x64,0xf0,0x10,0x35,0xc0,0x4e,0x01,0xc1,0xf3,0xeb,0x3c,0xbe,0x83,0xef,0xd2,0x6c,0x43,0x9a,0xda,},{0x2f,0x61,0xa2,0x6f,0xfb,0x68,0xba,0x4f,0x6e,0x14,0x15,0x29,0xdc,0x26,0x17,0xe8,0x53,0x1c,0x71,0x51,0x40,0x48,0x08,0x09,0x3b,0x4f,0xa7,0xfe,0xda,0xea,0x25,0x5d,},{0xa8,0x17,0xed,0x23,0xec,0x39,0x8a,0x12,0x86,0x01,0xc1,0x83,0x2d,0xc6,0xaf,0x76,0x43,0xbf,0x3a,0x5f,0x51,0x7b,0xcc,0x57,0x94,0x50,0xfd,0xb4,0x75,0x90,0x28,0xf4,0x96,0x61,0x64,0x12,0x5f,0x6e,0xbd,0x0d,0x6b,0xf8,0x6f,0xf2,0x98,0xa3,0x9c,0x76,0x6d,0x0c,0x21,0xfd,0xb0,0xcb,0xfd,0xf8,0x1c,0xd0,0xeb,0x1f,0x03,0xcd,0x8a,0x08,},"\x3e\x3c\x7c\x49\x07\x88\xe4\xb1\xd4\x2f\x5c\xbc\xae\x3a\x99\x30\xbf\x61\x7e\xbd\xff\x44\x7f\x7b\xe2\xac\x2b\xa7\xcd\x5b\xcf\xc0\x15\x76\x09\x63\xe6\xfe\x5b\x95\x6f\xb7\xcd\xb3\x5b\xd5\xa1\x7f\x54\x29\xca\x66\x4f\x43\x7f\x08\x75\x3a\x74\x1c\x2b\xc8\x69\x2b\x71\xa9\x11\x5c\x58\x2a\x25\xb2\xf7\x4d\x32\x98\x54\xd6\x0b\x78\x17\xc0\x79\xb3\x52\x3a\xaf\xf8\x79\x3c\x2f\x72\xff\xf8\xcd\x10\x59\x2c\x54\xe7\x38\xdf\x1d\x64\x52\xfb\x72\xda\x13\x1c\x67\x31\xea\x5c\x95\x3c\x62\xea\x17\x7a\xc1\xf4\x73\x5e\x51\x54\x47\x73\x87\x10\x9a\xfa\xe1\x5f\x3e\xd6\xee\xb0\x86\x06\xe2\x8c\x81\xd4\x38\x6f\x03\xb9\x37\x69\x24\xb6\xef\x8d\x22\x1e\xe2\x95\x47\xf8\x2a\x7e\xde\x48\xe1\xdc\x17\x72\x3e\x3d\x42\x17\x1e\xea\xf9\x6a\xc8\x4b\xed\xc2\xa0\x1d\xd8\x6f\x4d\x08\x57\x34\xfd\x69\xf9\x1b\x52\x63\xe4\x39\x08\x3f\xf0\x31\x85\x36\xad\xff\x41\x47\x30\x8e\x3a\xaf\xd1\xb5\x8b\xb7\x4f\x6f\xb0\x21\x4a\x46\xfd\xcd\x35\x24\xf1\x8d\xf5\xa7\x19\xce\x57\x31\x9e\x79\x1b\x4e\xa6\x06\xb4\x99\xbf\xa5\x7a\x60\xe7\x07\xf9\x4e\x18\xf1\xfe\xd2\x2f\x91\xbc\x79\xe6\x36\x4a\x84\x3f\x9c\xbf\x93\x82\x5c\x46\x5e\x9c\xae\x90\x72\xbc\x9d\x3e\xc4\x47\x1f\x21\xab\x2f\x7e\x99\xa6\x33\xf5\x87\xaa\xc3\xdb\x78\xae\x96\x66\xa8\x9a\x18\x00\x8d\xd6\x1d\x60\x21\x85\x54\x41\x1a\x65\x74\x0f\xfd\x1a\xe3\xad\xc0\x65\x95\xe3\xb7\x87\x64\x07\xb6"}, -{{0x17,0xe5,0xf0,0xa8,0xf3,0x47,0x51,0xba,0xbc,0x5c,0x72,0x3e,0xcf,0x33,0x93,0x06,0x99,0x2f,0x39,0xea,0x06,0x5a,0xc1,0x40,0xfc,0xbc,0x39,0x7d,0x2d,0xd3,0x2c,0x4b,},{0x4f,0x1e,0x23,0xcc,0x0f,0x2f,0x69,0xc8,0x8e,0xf9,0x16,0x2a,0xb5,0xf8,0xc5,0x9f,0xb3,0xb8,0xab,0x20,0x96,0xb7,0x7e,0x78,0x2c,0x63,0xc0,0x7c,0x8c,0x4f,0x2b,0x60,},{0xef,0xe2,0xcb,0x63,0xfe,0x7b,0x4f,0xc9,0x89,0x46,0xdc,0x82,0xfb,0x69,0x98,0xe7,0x41,0xed,0x9c,0xe6,0xb9,0xc1,0xa9,0x3b,0xb4,0x5b,0xc0,0xa7,0xd8,0x39,0x6d,0x74,0x05,0x28,0x2b,0x43,0xfe,0x36,0x3b,0xa5,0xb2,0x35,0x89,0xf8,0xe1,0xfa,0xe1,0x30,0xe1,0x57,0xce,0x88,0x8c,0xd7,0x2d,0x05,0x3d,0x0c,0xc1,0x9d,0x25,0x7a,0x43,0x00,},"\xc0\xfa\xd7\x90\x02\x40\x19\xbd\x6f\xc0\x8a\x7a\x92\xf5\xf2\xac\x35\xcf\x64\x32\xe2\xea\xa5\x3d\x48\x2f\x6e\x12\x04\x93\x53\x36\xcb\x3a\xe6\x5a\x63\xc2\x4d\x0e\xc6\x53\x9a\x10\xee\x18\x76\x0f\x2f\x52\x05\x37\x77\x4c\xde\xc6\xe9\x6b\x55\x53\x60\x11\xda\xa8\xf8\xbc\xb9\xcd\xaf\x6d\xf5\xb3\x46\x48\x44\x8a\xc7\xd7\xcb\x7c\x6b\xd8\x0d\x67\xfb\xf3\x30\xf8\x76\x52\x97\x76\x60\x46\xa9\x25\xab\x52\x41\x1d\x16\x04\xc3\xed\x6a\x85\x17\x30\x40\x12\x56\x58\xa3\x2c\xf4\xc8\x54\xef\x28\x13\xdf\x2b\xe6\xf3\x83\x0e\x5e\xee\x5a\x61\x63\xa8\x3c\xa8\x84\x9f\x61\x29\x91\xa3\x1e\x9f\x88\x02\x8e\x50\xbf\x85\x35\xe1\x17\x55\xfa\xd0\x29\xd9\x4c\xf2\x59\x59\xf6\x69\x5d\x09\xc1\xba\x43\x15\xd4\x0f\x7c\xf5\x1b\x3f\x81\x66\xd0\x2f\xab\xa7\x51\x1e\xcd\x8b\x1d\xde\xd5\xf1\x0c\xd6\x84\x34\x55\xcf\xf7\x07\xed\x22\x53\x96\xc6\x1d\x08\x20\xd2\x0a\xda\x70\xd0\xc3\x61\x9f\xf6\x79\x42\x20\x61\xc9\xf7\xc7\x6e\x97\xd5\xa3\x7a\xf6\x1f\xd6\x22\x12\xd2\xda\xfc\x64\x7e\xbb\xb9\x79\xe6\x1d\x90\x70\xec\x03\x60\x9a\x07\xf5\xfc\x57\xd1\x19\xae\x64\xb7\xa6\xef\x92\xa5\xaf\xae\x66\x0a\x30\xed\x48\xd7\x02\xcc\x31\x28\xc6\x33\xb4\xf1\x90\x60\xa0\x57\x81\x01\x72\x9e\xe9\x79\xf7\x90\xf4\x5b\xdb\xb5\xfe\x1a\x8a\x62\xf0\x1a\x61\xa3\x1d\x61\xaf\x07\x03\x04\x50\xfa\x04\x17\x32\x3e\x94\x07\xbc\x76\xe7\x31\x30\xe7\xc6\x9d\x62\xe6\xa7"}, -{{0x0c,0xd7,0xaa,0x7d,0x60,0x5e,0x44,0xd5,0xff,0xb9,0x79,0x66,0xb2,0xcb,0x93,0xc1,0x89,0xe4,0xc5,0xa8,0x5d,0xb8,0x7f,0xad,0x7a,0xb8,0xd6,0x24,0x63,0xc5,0x9b,0x59,},{0x48,0x89,0x85,0x5f,0xe4,0x11,0x6b,0x49,0x13,0x92,0x7f,0x47,0xf2,0x27,0x3b,0xf5,0x59,0xc3,0xb3,0x94,0xa9,0x83,0x63,0x1a,0x25,0xae,0x59,0x70,0x33,0x18,0x5e,0x46,},{0xbf,0x91,0x15,0xfd,0x3d,0x02,0x70,0x6e,0x39,0x8d,0x4b,0xf3,0xb0,0x2a,0x82,0x67,0x4f,0xf3,0x04,0x15,0x08,0xfd,0x39,0xd2,0x9f,0x86,0x7e,0x50,0x16,0x34,0xb9,0x26,0x1f,0x51,0x6a,0x79,0x4f,0x98,0x73,0x8d,0x7c,0x70,0x13,0xa3,0xf2,0xf8,0x58,0xff,0xdd,0x08,0x04,0x7f,0xb6,0xbf,0x3d,0xdd,0xfb,0x4b,0x4f,0x4c,0xbe,0xef,0x30,0x03,},"\x28\xa5\x5d\xda\x6c\xd0\x84\x4b\x65\x77\xc9\xd6\xda\x07\x3a\x4d\xc3\x5c\xbc\x98\xac\x15\x8a\xb5\x4c\xf8\x8f\xd2\x0c\xc8\x7e\x83\xc4\xbb\xa2\xd7\x4d\x82\xce\x0f\x48\x54\xec\x4d\xb5\x13\xde\x40\x04\x65\xaa\xa5\xee\xe7\x90\xbc\x84\xf1\x63\x37\x07\x2d\x3a\x91\xcd\xe4\x0d\x6e\x0d\xf1\xba\x0c\xc0\x64\x5f\x5d\x5c\xbb\xb6\x42\x38\x1d\x7b\x9e\x21\x1d\x25\x26\x7a\x8a\xcf\x77\xd1\xed\xb6\x9c\x3a\x63\x0f\x5b\x13\x3d\x24\xf0\x46\xa8\x1b\xf2\x2f\xf0\x3b\x31\xd8\x44\x7e\x12\xc3\xf7\xb7\x71\x14\xa7\x0c\xbd\x20\xbb\xd0\x8b\x0b\x38\x27\xa6\xbb\xcf\x90\x40\x9e\x34\x44\x47\xa7\xfb\xc5\x9b\xdd\x97\xd7\x29\x07\x1f\x8d\x71\xdc\xc3\x3e\x6e\xf2\xcb\xab\x1d\x41\x1e\xdf\x13\x73\x4d\xb1\xdd\x97\x03\x27\x6f\x5e\xb2\xd6\xaa\x2c\xb8\x95\x2d\xd6\x71\x2b\xfa\xe8\x09\xce\x08\xc3\xaa\x50\x2b\x81\x35\x71\x3f\xac\x0a\x9c\x25\xb1\xd4\x5b\x6a\x58\x31\xe0\x24\x21\xbb\xa6\x5b\x81\xa5\x96\xef\xa2\x4b\x05\x76\xbd\x1d\xc7\xfd\xfb\x49\xbe\x76\x28\x75\xe8\x1b\xd5\x40\x72\x2b\xc0\x61\x40\xb9\xaa\x2e\xf7\xb8\x4a\x80\x1e\x41\xde\xd6\x8d\x45\x46\xac\x48\x73\xd9\xe7\xce\xd6\x49\xb6\x4f\xad\xaf\x0b\x5c\x4b\x6e\xb8\xd0\x36\x31\x52\x33\xf4\x32\x6c\xa0\x1e\x03\x39\x30\x50\xcd\x02\x7c\x24\xf6\x73\x03\xfb\x84\x6b\xd2\xc6\xb3\xdb\xa0\x6b\xed\x0d\x59\xa3\x62\x89\xd2\x4b\xd6\x48\xf7\xdb\x0b\x3a\x81\x34\x66\x12\x59\x3e\x3d\xdd\x18\xc5\x57"}, -{{0x33,0x37,0x1d,0x9e,0x89,0x2f,0x98,0x75,0x05,0x2a,0xc8,0xe3,0x25,0xba,0x50,0x5e,0x74,0x77,0xc1,0xac,0xe2,0x4b,0xa7,0x82,0x26,0x43,0xd4,0x3d,0x0a,0xce,0xf3,0xde,},{0x35,0x92,0x9b,0xde,0xd2,0x7c,0x24,0x9c,0x87,0xd8,0xb8,0xd8,0x2f,0x59,0x26,0x0a,0x57,0x53,0x27,0xb5,0x46,0xc3,0xa1,0x67,0xc6,0x9f,0x59,0x92,0xd5,0xb8,0xe0,0x06,},{0x98,0x5c,0xa4,0x46,0xdd,0xc0,0x07,0x82,0x7c,0xc8,0xf2,0x85,0x2c,0xbd,0x81,0x15,0xef,0x8c,0x59,0x75,0xe9,0xd7,0xce,0x96,0xd7,0x4d,0xfe,0xd8,0x59,0xaa,0x14,0xa4,0xc1,0x52,0x54,0x00,0x6b,0xea,0x5e,0x08,0x35,0x9e,0xfe,0x26,0x25,0xd7,0x15,0xe0,0x89,0x7e,0xe5,0xa1,0x6f,0x15,0x12,0x03,0xbe,0x50,0x10,0x41,0x86,0x37,0xde,0x05,},"\x27\xa3\x2e\xfb\xa2\x82\x04\xbe\x59\xb7\xff\x5f\xe4\x88\xca\x15\x8a\x91\xd5\x98\x60\x91\xec\xc4\x45\x8b\x49\xe0\x90\xdd\x37\xcb\xfe\xde\x7c\x0f\x46\x18\x6f\xab\xcb\xdf\xf7\x8d\x28\x44\x15\x58\x08\xef\xff\xd8\x73\xed\x9c\x92\x61\x52\x6e\x04\xe4\xf7\x05\x0b\x8d\x7b\xd2\x67\xa0\xfe\x3d\x5a\x44\x93\x78\xd5\x4a\x4f\xeb\xbd\x2f\x26\x82\x43\x38\xe2\xaa\xaf\x35\xa3\x2f\xf0\xf6\x25\x04\xbd\xa5\xc2\xe4\x4a\xbc\x63\x15\x9f\x33\x6c\xf2\x5e\x6b\xb4\x0d\xdb\x7d\x88\x25\xdf\xf1\x8f\xd5\x1f\xc0\x19\x51\xea\xed\xcd\x33\x70\x70\x07\xe1\x20\x3c\xa5\x8b\x4f\x7d\x24\x2f\x81\x66\xa9\x07\xe0\x99\x93\x2c\x00\x1b\xfb\x1e\xc9\xa6\x1e\x0e\xf2\xda\x4e\x84\x46\xaf\x20\x82\x01\x31\x5d\x69\x68\x17\x10\xd4\x25\xd2\x40\x0c\x38\x7d\x7b\x9d\xf3\x21\xa4\xae\xc6\x02\xb9\xc6\x56\xc3\xe2\x31\x0b\xff\x87\x56\xd1\x8b\x80\x21\x34\xb1\x56\x04\xf4\xed\xc1\x11\x14\x9a\x98\x79\xe3\x12\x41\xdd\x34\xf7\x02\xf4\xc3\x49\x61\x7b\x13\x52\x97\x69\xa7\x72\xf5\xe5\x2a\x89\xc0\x98\xe0\xdc\xa5\x92\x06\x67\x89\x3a\x25\x00\x61\xb1\x79\x91\x62\x6e\xb9\x31\x92\x98\x68\x5b\xe4\x6b\x6a\x8b\x68\x42\x24\x44\xfa\x5a\x36\xbc\xf3\xa6\x87\xe2\xec\xcb\x93\x22\xc8\x7d\xc8\x01\x65\xda\x89\x89\x30\x85\x0b\x98\xfc\x86\x3c\xad\xa1\xaa\x99\xc6\xd6\x1c\x45\x1b\x9c\xcf\x48\x74\xc7\xf0\xe7\x5b\x0a\x0c\x60\x2f\x04\x48\x12\xc7\x17\x65\xad\xaf\x02\x02\x53\x95\xb0"}, -{{0xbe,0xed,0xb8,0x07,0x3d,0xf5,0x8f,0x8c,0x1b,0xff,0xbd,0xbd,0x77,0xec,0x7d,0xec,0xb2,0xc8,0x2a,0x9b,0xab,0xec,0xef,0xc0,0x33,0x15,0x07,0xbd,0xc2,0xc2,0xa7,0xe7,},{0xb2,0x7e,0x90,0x8b,0x80,0x5e,0x29,0x6f,0xc3,0x0d,0x2e,0x47,0x4b,0x06,0x0c,0xd5,0x0c,0x0f,0x6f,0x52,0x0b,0x36,0x71,0x71,0x21,0x83,0xbd,0x89,0xd4,0xe7,0x33,0xe9,},{0x8c,0x89,0x0c,0xcc,0xad,0xc7,0x76,0x0e,0x1e,0x82,0xe4,0x3c,0x44,0xb3,0xdc,0x0b,0x68,0x5a,0x48,0xb4,0x79,0xae,0x13,0xcc,0x0a,0x6b,0x05,0x57,0xd0,0xfb,0x1c,0xba,0xbb,0xa6,0x3d,0x2a,0x96,0x84,0x34,0x12,0xea,0x8d,0x36,0xc5,0x0a,0xcb,0xf5,0x2b,0x92,0xcf,0xb2,0xdc,0xe4,0x9d,0xc4,0x8a,0xf6,0xdd,0xcf,0x8e,0xe4,0x7a,0x86,0x08,},"\x35\xca\x57\xf0\xf9\x15\xe5\x20\x9d\x54\xea\x4b\x87\x1f\xfb\x58\x53\x54\xdf\x1b\x4a\x4a\x17\x96\xfb\xe4\xd6\x22\x7d\x3e\x1a\xba\x51\x71\xed\x03\x91\xa7\x9e\x83\xe2\x4d\x82\xfd\xaf\xd1\x5c\x17\xb2\x8b\xf6\xc9\x4d\x61\x8c\x74\xd6\x52\x64\xe5\x8f\xaa\xac\xd2\x90\x28\x72\xfd\xd0\xef\xa2\x2e\x8d\x2d\x7c\xe8\xe3\xb8\x19\x7f\x0c\x36\x15\xb0\xa3\x85\x23\x5f\xa9\xfd\x8e\x45\x64\xee\x6e\x6b\x16\x50\xb4\xcf\xb9\x4d\x87\x2c\x80\x5c\x32\xd4\xf3\xa1\x8f\x96\x64\x61\xd3\xad\xbb\x60\x5f\xa5\x25\x88\x4f\x8e\xb1\x97\x62\x73\x96\xba\x4d\x99\x5d\x78\xac\x02\x94\x8a\x0e\xaa\xbb\x58\x51\x9b\x9a\x8e\x2e\x79\x85\xcd\x1d\xe2\xc7\x1d\x89\x18\xd9\x6a\x01\x68\x66\x0c\xe1\x7c\xdd\xf3\x64\xe3\xec\x0d\x4b\xd9\x0f\x21\x04\x75\x1a\x19\x27\xee\x1d\x23\xf3\xe7\xa6\x98\x40\xed\x04\x0b\x00\xe5\xf6\xe4\x86\x6e\xc5\x88\x13\x14\x9c\xc3\x82\xae\xbf\x61\x62\x60\x8c\x79\x57\x4d\x55\x3f\x47\x23\x0e\x92\x4a\x0e\xf1\xeb\xf5\x5d\x8e\x1a\x52\xab\xb6\x2a\x2d\x7a\xc8\x60\x27\xc7\xc0\x3c\xc8\x3f\xa1\x94\x9d\xa2\x9e\x2f\x30\x37\xab\x98\x6f\xd2\xff\xfe\x65\x0e\x31\x49\xba\xba\xe5\xa5\x0b\x1e\xe9\x69\x6f\x3b\xab\xec\x72\xe2\x96\x97\xc8\x24\x22\x81\x4d\x27\x20\x85\x50\x0f\xd8\x37\xfe\x3c\x7a\x97\x3e\xf4\xc1\x69\xaf\x12\xdd\x7f\x02\x70\x06\x20\xbb\x04\x5b\xdb\xf8\x46\x23\xf3\x26\x35\x05\x70\xb3\xca\xdb\xc9\xae\xa4\x20\x0b\x28\x28\x7e\x17\xab"}, -{{0x91,0x84,0xef,0x61,0x88,0x16,0x83,0x25,0x92,0xbc,0x8e,0xb3,0x5f,0x4f,0xfd,0x4f,0xf9,0x8d,0xfb,0xf7,0x77,0x6c,0x90,0xf2,0xaa,0xd2,0x12,0xce,0x7e,0x03,0x35,0x1e,},{0x68,0x7b,0x77,0x26,0x01,0x0d,0x9b,0xde,0x2c,0x90,0xe5,0x73,0xcd,0x2a,0x2a,0x70,0x2f,0xf2,0x8c,0x4a,0x2a,0xf7,0x0a,0xfc,0x73,0x15,0xc9,0x4d,0x57,0x56,0x01,0xe5,},{0xb3,0xc2,0x4e,0x75,0x13,0x2c,0x56,0x34,0x75,0x42,0x2d,0x5e,0xa4,0x12,0xb5,0xc1,0xe8,0xe6,0xe5,0xea,0x1c,0x08,0xea,0xd1,0x39,0x3c,0x41,0x2d,0xa1,0x34,0xc9,0xa1,0x63,0x82,0x84,0xea,0x7e,0x2c,0xa0,0x32,0xfe,0x3d,0x3e,0x32,0xa9,0x06,0x6a,0x8c,0x88,0x39,0x90,0x3f,0x6e,0xf4,0x6e,0x96,0x6b,0xb5,0xe4,0x92,0xd8,0xc2,0xaa,0x00,},"\x72\x9e\xb7\xe5\x4a\x9d\x00\xc5\x86\x17\xaf\x18\xc3\x45\xb8\xdc\x6e\x5b\x4e\x0f\x57\xde\x2f\x3c\x02\xe5\x4a\x2e\xc8\xf1\x42\x5e\xc2\xe2\x40\x77\x5b\x5a\xb0\xc1\x0f\x84\xac\x8b\xaf\xda\x45\x84\xf7\xe2\x1c\x65\x5f\xae\xcd\x80\x30\xa9\x89\x06\xbd\x68\x39\x8f\x26\xb5\xd5\x8d\x92\xb6\xcf\x04\x5e\x9b\xd9\x74\x3c\x74\xc9\xa3\x42\xec\x61\xce\x57\xf3\x7b\x98\x1e\xac\x4d\x8b\xf0\x34\x60\x88\x66\xe9\x85\xbb\x68\x68\x6a\x68\xb4\xa2\xaf\x88\xb9\x92\xa2\xa6\xd2\xdc\x8c\xe8\x8b\xfb\x0a\x36\xcf\x28\xbb\xab\x70\x24\xab\xfa\x2b\xea\x53\x31\x3b\x66\xc9\x06\xf4\xf7\xcf\x66\x97\x0f\x54\x00\x95\xbd\x01\x04\xaa\x49\x24\xdd\x82\xe1\x54\x13\xc2\x26\x79\xf8\x47\xe4\x8c\xd0\xc7\xec\x1f\x67\x7e\x00\x5f\xec\x01\x77\xfb\xd5\xc5\x59\xfc\x39\xad\xd6\x13\x99\x1f\xba\xea\xe4\xd2\x4d\x39\xd3\x09\xef\x74\x64\x7f\x81\x92\xcc\x4c\x62\xd0\x64\x20\x28\xc7\x6a\x1b\x95\x1f\x6b\xc9\x63\x9d\xeb\x91\xec\xc0\x8b\xe6\x04\x3f\x21\x09\x70\x5a\x42\xc7\xea\xe7\x12\x64\x9d\x91\xd9\x6c\xcb\xbf\xb6\x3d\x8d\x0d\xd6\xdd\x11\x21\x60\xf6\x13\x61\xec\xdc\x67\x93\x92\x9c\xa9\xae\xf9\xab\x56\x94\x4a\x6f\xa4\xa7\xdf\x1e\x27\x9e\xaf\x58\xce\x83\x23\xa9\xcf\x62\xc9\x42\x79\xff\xf7\x44\x0f\xbc\x93\x6b\xaa\x61\x48\x9c\x99\x93\x30\xba\xdc\xb9\xfc\x0e\x18\x4b\xc5\x09\x3f\x33\x0c\xbb\x24\x2f\x71\xfb\x37\x87\x38\xfe\xa1\x05\x11\xdd\x43\x83\x64\xd7\xf7\x6b\xcc"}, -{{0x35,0x4e,0x13,0x15,0x2e,0xe1,0xfe,0x74,0x8a,0x12,0x52,0x20,0x4c,0x65,0x27,0xbd,0xc1,0xb1,0xeb,0x2e,0xb5,0x36,0x78,0x15,0x0e,0x63,0x59,0x92,0x47,0x08,0xd8,0x12,},{0xd4,0x5f,0xf6,0xc5,0xfb,0x83,0xe7,0xbb,0x96,0x69,0xaa,0x89,0x60,0xde,0xb7,0xdb,0xc6,0x65,0xc9,0x88,0x43,0x9b,0x6c,0x9e,0xf6,0x72,0xc6,0x81,0x1d,0xc8,0xbc,0xf6,},{0xde,0x2b,0x46,0xe6,0x5f,0x3d,0xec,0xef,0x34,0x33,0x2e,0x50,0x0f,0x2e,0x11,0x30,0x6f,0xbd,0xcf,0x1b,0xe8,0x5a,0x1c,0x1e,0xe6,0x8b,0xa3,0x04,0x5d,0xce,0xc2,0xc7,0xbe,0x60,0x8d,0x22,0x92,0x7d,0xa1,0xf4,0x4c,0x0e,0x20,0x83,0xae,0x62,0x2c,0xf3,0xc2,0x9d,0x89,0x38,0x87,0x99,0x4e,0xfc,0xfa,0x2c,0xa5,0x94,0xf5,0x05,0x1f,0x03,},"\x8e\x5f\xcc\xf6\x6b\x1b\xa6\x16\x9c\xb6\x85\x73\x3d\x9d\x0e\x01\x90\x36\x1c\x90\xbc\xab\x95\xc1\x63\x28\x5a\x97\xfe\x35\x6d\x2b\xdc\xde\x3c\x93\x80\x26\x88\x05\xa3\x84\xd0\x63\xda\x09\xcc\xd9\x96\x9c\xc3\xff\x74\x31\xe6\x0a\x8e\x9f\x86\x9c\xd6\x2f\xaa\x0e\x35\x61\x51\xb2\x80\xbc\x52\x6e\x57\x7c\x2c\x53\x8c\x9a\x72\x4d\xc4\x8b\xf8\x8b\x70\x32\x1d\x7e\x1e\xee\xdb\x3c\x4a\xf7\x06\x74\x8c\x94\x2e\x67\xbd\xab\xdb\x41\xbe\xc2\x97\x7b\x15\x23\x06\x9e\x31\xe2\x9b\x76\x30\x02\x88\xf8\x8a\x51\xb3\x84\xb8\x0c\xc2\x52\x6f\x16\x79\x34\x0d\xde\xc3\x88\x1f\x5c\xd2\x8b\x03\x78\xd9\xcd\x0a\x81\x2b\x68\xdd\x3f\x68\xf7\xa2\x3e\x1b\x54\xbe\xe7\x46\x6a\xc7\x65\xcf\x38\xdf\x04\xd6\x74\x41\xdf\xa4\x98\xc4\xbf\xfc\x52\x04\x5f\xa6\xd2\xdb\xcd\xbf\xa3\x3d\xfa\xa7\x76\x44\xff\xcc\xef\x0d\xec\xdb\x67\x90\xc7\x0a\x0d\x73\x4e\xc2\x87\xcc\x33\x8c\xb5\xa9\x09\xc0\x05\x51\x89\x30\x11\x69\xc4\xf7\x70\x2c\x05\xc0\x91\x1a\x27\xb1\x6e\xf9\xed\x93\x4f\xa6\xa0\xca\x7b\x13\xe4\x13\x52\x34\x22\x53\x56\x47\x96\x80\x30\xed\xc4\x0c\xd7\x3e\x7d\x6b\x34\x5b\x75\x81\xf4\x38\x31\x6d\x68\xe3\xcd\x29\x2b\x84\x6d\x3f\x4f\x7c\x48\x62\xbc\x7e\x6b\x3f\xb8\x9a\x27\xf6\xf6\x0c\xd7\xdb\x2e\x34\xec\x9a\xae\x10\x13\xfe\x37\xac\xff\x8a\xd8\x88\xcb\x9a\x59\x3e\xf5\xe6\x21\xea\xe5\x18\x6c\x58\xb3\x1d\xcf\xde\x22\x87\x0e\x33\x6d\x33\xf4\x40\xf6\xb8\xd4\x9a"}, -{{0x7f,0xf6,0x2d,0x4b,0x3c,0x4d,0x99,0xd3,0x42,0xd4,0xbb,0x40,0x1d,0x72,0x6b,0x21,0xe9,0x9f,0x4e,0xf5,0x92,0x14,0x9f,0xc3,0x11,0xb6,0x87,0x61,0xf5,0x56,0x7f,0xf6,},{0x7f,0xdf,0xdb,0x9e,0xca,0x29,0xd3,0xf0,0x1d,0x94,0x86,0xd7,0xe1,0x12,0xce,0x03,0xaa,0x37,0xb9,0x13,0x26,0xa4,0x28,0x3b,0x9c,0x03,0x99,0x9c,0x5e,0xda,0x09,0x9a,},{0x05,0x8f,0x79,0x92,0x7f,0xbf,0x61,0x78,0x72,0x48,0x15,0xc7,0xb1,0x1c,0x63,0xba,0xaa,0x90,0xbc,0xc1,0x5d,0x72,0x72,0xbe,0x08,0x2f,0x8a,0x91,0x41,0x86,0x1c,0x81,0x64,0x33,0x05,0x5f,0x6c,0xf6,0x49,0x14,0x24,0x85,0x3f,0x9e,0xc7,0x8b,0xb9,0x1a,0xce,0x91,0x3a,0x93,0x41,0x1b,0x4e,0x5e,0xd5,0x8b,0xc4,0xba,0x57,0x15,0xc6,0x0a,},"\x99\xc4\x4c\x79\x65\x72\xa4\x82\x3f\xc6\xc3\x80\x77\x30\x83\x91\x73\x77\x4c\x05\xdb\xfc\x14\x92\xed\x0d\x00\x50\x9a\x95\xa1\xde\x37\x27\x4b\x31\x35\xed\x04\x56\xa1\x71\x8e\x57\x65\x97\xdc\x13\xf2\xa2\xab\x37\xa4\x5c\x06\xcb\xb4\xa2\xd2\x2a\xfa\xd4\xd5\xf3\xd9\x0a\xb3\xd8\xda\x4d\xcd\xaa\x06\xd4\x4f\x22\x19\x08\x84\x01\xc5\xdc\xee\xe2\x60\x55\xc4\x78\x2f\x78\xd7\xd6\x3a\x38\x06\x08\xe1\xbe\xf8\x9e\xee\xf3\x38\xc2\xf0\x89\x7d\xa1\x06\xfa\xfc\xe2\xfb\x2e\xbc\x5d\xb6\x69\xc7\xc1\x72\xc9\xcf\xe7\x7d\x31\x09\xd2\x39\xfe\x5d\x00\x5c\x8e\xe7\x51\x51\x1b\x5a\x88\x31\x7c\x72\x9b\x0d\x8b\x70\xb5\x2f\x6b\xd3\xcd\xa2\xfe\x86\x5c\x77\xf3\x6e\x4f\x1b\x63\x5f\x33\x6e\x03\x6b\xd7\x18\xbe\xc9\x0e\xe7\x8a\x80\x28\x11\x51\x0c\x40\x58\xc1\xba\x36\x40\x17\x25\x3a\xa8\x42\x92\x2e\x1d\xd7\xd7\xa0\xf0\xfc\x9c\x69\xe4\x3f\xc4\xea\xef\xfa\xaf\x1a\xe5\xfa\x5d\x2d\x73\xb4\x30\x79\x61\x7b\xab\xa0\x30\x92\x3f\xe5\xb1\x3d\x2c\x1c\x4f\xe6\xfa\xc3\xf2\xdb\x74\xe2\x02\x0a\x73\x4b\x61\x21\xa0\x30\x2f\xce\x82\x0b\xa0\x58\x0c\xe6\x13\x53\x48\xfd\xf0\x63\x2e\x00\x08\xdf\x03\xee\x11\x21\x68\xf5\xcf\xa0\x03\x7a\x26\xa1\xf6\x9b\x1f\x13\x17\xed\xf2\xa3\xab\x36\x74\x55\xa7\x7e\x00\x69\x12\x15\xd7\xaa\x31\x33\xc2\x15\x9d\x3d\xa2\xb1\x34\xcf\x04\xf0\xde\xfb\xf0\x7a\x60\x64\x01\x1e\x64\xdd\x14\xd4\xf8\xf0\x64\x35\x66\x55\x42\x88\x04\xc2\x77\x1a"}, -{{0x6c,0xab,0xad,0xd0,0x3f,0x8a,0x2e,0x6e,0xba,0xb9,0x6a,0x74,0xf8,0x0e,0x18,0x16,0x4e,0x4d,0x1b,0x6b,0xaa,0x67,0x8f,0x5a,0x82,0xe2,0x56,0x04,0xaf,0x98,0x9a,0xaf,},{0x2a,0x4a,0x31,0x79,0x56,0x41,0x94,0xe0,0x01,0x00,0xc1,0x8b,0xc3,0x53,0x51,0xd8,0xb1,0x35,0xbb,0xae,0x5b,0x32,0xb2,0x8f,0xce,0x1d,0x7b,0x67,0x66,0xca,0x4b,0x32,},{0x4e,0x65,0xc6,0xc1,0xd4,0x93,0x04,0x5e,0x8a,0x92,0x50,0xe3,0x97,0xc1,0xd1,0xd3,0x0f,0xfe,0xd2,0x4d,0xb6,0x6a,0x89,0x61,0xaa,0x45,0x8f,0x8f,0x0f,0xcb,0x76,0x0c,0x39,0xfe,0x86,0x57,0xd7,0xab,0x8f,0x84,0x00,0x0b,0x96,0xd5,0x19,0x71,0x7c,0xff,0x71,0xf9,0x26,0x52,0x2c,0x1e,0xfe,0xc7,0xf8,0xb2,0x62,0x4e,0xae,0x55,0xf6,0x0c,},"\x27\x9f\x78\xcf\x3b\x9c\xcf\xc6\xe1\xb0\x1e\x1a\x82\xf5\x0e\xd1\x72\xe9\xa8\xe1\xe7\x02\xbb\x15\x66\x1d\xd7\xdc\x3a\x45\x6f\xf7\xa7\xa7\xfd\xfb\x08\x1d\xb3\x86\x70\x79\x63\x0c\x7f\x70\xfd\x75\x32\x92\xec\x60\xec\xbf\x50\x63\x2e\x9a\xa4\x5b\x99\x65\x05\xc6\x6e\x6d\xc3\xc6\xae\x89\x2e\x21\xb6\xa8\x70\x5e\x4b\xba\xe8\xf1\x6a\x33\x78\x55\x4b\x31\xfd\xb0\x13\x9d\xcd\x15\xc9\x6a\x8a\x7e\x4b\x88\x75\x6a\x86\xd1\x8d\xb5\xdc\x74\xfd\x76\x91\x19\x7d\xd8\x8e\x2c\x7d\x5d\xf5\x2b\x04\x93\x44\xcd\xc4\x77\xc9\xcd\x7e\x89\xed\xa9\x9c\xcf\xb1\xd0\x08\x14\xd0\x15\x2b\x96\x54\xdf\x32\x79\x37\x2c\xa5\xf1\x8b\x1c\x94\x6f\x28\x94\xa7\x6b\x07\x9d\xdb\x1c\x3c\xd6\x1f\xbb\x96\x9a\xee\xc9\x19\x3a\x6b\x88\xfb\x7d\x13\x6c\x07\xf9\x82\x1e\x5c\x10\x74\xb4\xe9\x3b\xca\xf6\xfa\x14\xd0\xd1\xd7\xe1\x70\x75\x89\xd7\x7e\xc1\x33\x72\x06\xe5\x3a\x1f\x06\xcc\x26\x67\x2f\xf9\x5c\x13\xd5\xff\x44\x47\x66\x93\x1b\xa3\x0a\x0a\xfd\xcd\xad\xd2\x09\x8e\x9c\x41\xfd\x87\xa3\xf2\x3c\xd1\x6d\xbb\x0e\xfb\xf8\x09\x2c\xe3\x3e\x32\x7f\x42\x61\x09\x90\xe1\xce\xe6\xcb\x8e\x54\x95\x1a\xa0\x81\xe6\x97\x65\xae\x40\x09\xae\xed\x75\x8e\x76\x8d\xe5\x0c\x23\xd9\xa2\x2b\x4a\x06\xdc\x4d\x19\xfc\x8c\xbd\x0c\xde\xf4\xc9\x83\x46\x17\x55\xd0\xa3\xb5\xd6\xa9\xc1\x22\x53\xe0\x95\x68\x33\x9f\xf7\xe5\xf7\x8c\x5f\xdf\x7e\xc8\x9f\x91\x86\xa6\x21\xa8\xc0\xee\xd1\x1b\x67\x02\x2e"}, -{{0x0f,0xa0,0xc3,0x2c,0x3a,0xe3,0x4b,0xe5,0x1b,0x92,0xf9,0x19,0x45,0x40,0x59,0x81,0xa8,0xe2,0x02,0x48,0x85,0x58,0xa8,0xe2,0x20,0xc2,0x88,0xc7,0xd6,0xa5,0x53,0x2d,},{0xd6,0xae,0xe6,0x2b,0xd9,0x1f,0xc9,0x45,0x36,0x35,0xff,0xcc,0x02,0xb2,0xf3,0x8d,0xca,0xb1,0x32,0x85,0x14,0x03,0x80,0x58,0x0c,0xcd,0xff,0x08,0x65,0xdf,0x04,0x92,},{0x7e,0x9a,0xb8,0x5e,0xe9,0x4f,0xe4,0xb3,0x5d,0xcb,0x54,0x53,0x29,0xa0,0xef,0x25,0x92,0x3d,0xe5,0xc9,0xdc,0x23,0xe7,0xdf,0x1a,0x7e,0x77,0xab,0x0d,0xcf,0xb8,0x9e,0x03,0xf4,0xe7,0x85,0xca,0x64,0x29,0xcb,0x2b,0x0d,0xf5,0x0d,0xa6,0x23,0x0f,0x73,0x3f,0x00,0xf3,0x3a,0x45,0xc4,0xe5,0x76,0xcd,0x40,0xbd,0xb8,0x4f,0x1a,0xe0,0x01,},"\x53\xf4\x4b\xe0\xe5\x99\x7f\xf0\x72\x64\xcb\x64\xba\x13\x59\xe2\x80\x1d\xef\x87\x55\xe6\x4a\x23\x62\xbd\xda\xf5\x97\xe6\x72\xd0\x21\xd3\x4f\xfa\xce\x6d\x97\xe0\xf2\xb1\xf6\xae\x62\x5f\xd3\x3d\x3c\x4f\x6e\x9f\xf7\xd0\xc7\x3f\x1d\xa8\xde\xfb\x23\xf3\x24\x97\x5e\x92\x1b\xb2\x47\x32\x58\x17\x7a\x16\x61\x25\x67\xed\xf7\xd5\x76\x0f\x3f\x3e\x3a\x6d\x26\xaa\xab\xc5\xfd\xe4\xe2\x04\x3f\x73\xfa\x70\xf1\x28\x02\x09\x33\xb1\xba\x3b\x6b\xd6\x94\x98\xe9\x50\x3e\xa6\x70\xf1\xed\x88\x0d\x36\x51\xf2\xe4\xc5\x9e\x79\xca\xbc\x86\xe9\xb7\x03\x39\x42\x94\x11\x2d\x5d\x8e\x21\x3c\x31\x74\x23\xb5\x25\xa6\xdf\x70\x10\x6a\x9d\x65\x8a\x26\x20\x28\xb5\xf4\x51\x00\xcb\x77\xd1\x15\x0d\x8f\xe4\x61\xee\xd4\x34\xf2\x41\x01\x5f\x32\x76\xad\x7b\x09\xa2\x91\xb4\xa7\xf3\x5e\x3c\x30\x05\x1c\xbf\x13\xb1\xd4\xa7\xfa\x0c\x81\xa5\x0f\x93\x9e\x7c\x49\x67\x3a\xfd\xc8\x78\x83\xc9\xe3\xe6\x1f\x5a\x1d\xf0\x37\x55\x47\x0f\xda\x74\xbf\x23\xea\x88\x67\x6b\x25\x8a\x97\xa2\x80\xd5\xf9\x0b\x52\xb7\x14\xb5\x96\x03\x5b\xae\x08\xc8\xd0\xfe\x6d\x94\xf8\x94\x95\x59\xb1\xf2\x7d\x71\x16\xcf\x59\xdd\x3c\xfb\xf1\x82\x02\xa0\x9c\x13\xf5\xc4\xfb\xc8\xd9\x72\x25\x49\x28\x87\xd3\x28\x70\xc2\x29\x7e\x34\xde\xbd\x98\x76\xd6\xd0\x1a\xc2\x7a\x16\xb0\x88\xb0\x79\x07\x9f\x2b\x20\xfe\xb0\x25\x37\xcd\xa3\x14\xc4\x3c\xb2\xdc\xa3\x71\xb9\xdf\x37\xed\x11\xec\x97\xe1\xa7\xa6\x99\x3a"}, -{{0x7b,0x06,0xf8,0x80,0x26,0xfa,0x86,0xf3,0x9f,0xce,0x24,0x26,0xf6,0x7c,0xc5,0x99,0x6b,0xed,0xd0,0xcf,0xc4,0xb5,0xeb,0xb1,0xb5,0xe3,0xed,0xbb,0x47,0xe0,0x80,0xaa,},{0x3f,0x14,0x69,0xee,0x6a,0x2e,0x78,0x67,0xe2,0xe9,0x01,0x2d,0x40,0x2c,0xf5,0xa4,0x86,0x14,0x97,0xc0,0x1d,0xf8,0x79,0xa1,0xde,0xb1,0xc5,0x39,0x83,0x0b,0x58,0xde,},{0x42,0xf1,0x33,0xe3,0x4e,0x3e,0xb7,0x03,0x2a,0x13,0x3e,0xd7,0x81,0x53,0x7e,0xc6,0x2e,0x44,0xa5,0xce,0x83,0x81,0xe5,0xe0,0xbf,0x9e,0x13,0xa9,0x14,0xa4,0xb2,0xc7,0x57,0x81,0x1d,0x6d,0x3b,0x1e,0x86,0x67,0x24,0x24,0xea,0x42,0x30,0xd1,0x0f,0x7c,0x61,0x0a,0xbb,0x70,0x69,0xe6,0x1e,0x31,0x9b,0x40,0x66,0xa2,0xbd,0x7b,0xc9,0x00,},"\x71\x17\x5d\x4e\x21\x72\x12\x97\xd9\x17\x6d\x81\x7f\x4e\x78\x5d\x96\x00\xd9\x23\xf9\x87\xfe\x0b\x26\xfd\x79\xd3\x3a\x5e\xa5\xd1\xe8\x18\xb7\x1f\x0f\x92\xb8\xc7\x3a\xfd\xda\xbd\xcc\x27\xf6\xd1\x6e\x26\xaa\xfa\x87\x4c\xfd\x77\xa0\x0e\x06\xc3\x6b\x04\x14\x87\x58\x2b\xb9\x33\x76\x0f\x88\xb4\x19\x12\x73\x45\x77\x6e\xa4\x18\xf8\x35\x22\x25\x4f\xed\x33\x81\x9b\xc5\xc9\x5f\x8f\x84\x04\xcc\x14\x4e\xbf\x14\x86\xc8\x85\x15\x40\x9d\x34\x33\xaa\xf5\x19\xd9\x92\x0f\x52\x56\xe6\x29\x41\x9e\x9a\x95\x58\x0a\x35\xb0\x69\xb8\xd2\x55\x33\xdf\xcb\xc9\x8a\xd3\x64\x04\xa9\x51\x80\x8e\x01\x37\x8c\x03\x26\x63\x26\xd1\x20\x04\x69\x75\xfd\xe0\x7d\xae\xf3\x26\x6c\xaa\xcd\x82\x1c\x14\x03\x49\x9d\x7f\xdf\x17\xc0\x33\xc8\xd8\xc3\xf2\x8f\x16\x2b\x5f\x09\xdf\xda\xca\x06\x28\x5f\x00\xc6\xcb\x98\x6d\xfd\xf5\x15\x1a\xa6\x63\x96\x08\xb5\xb1\x3e\x78\xd6\x5a\x43\x68\x58\x5b\x16\x13\x87\x54\xfb\xd1\x13\x83\x5a\x68\x6c\xd0\x66\xc2\xb8\x9b\xb0\x95\x3c\x24\xd5\x0e\x77\xbf\x0f\xc4\x57\xc1\xe0\xfc\xf5\xd4\x4d\xa8\xdb\x9a\x88\xf0\x62\xbe\x3b\x68\x8d\x5c\xdc\xff\x1d\x1c\x00\xe8\x1e\xc9\xd4\x13\x88\x22\x95\xb3\x41\xfe\xe8\xfa\x42\x7d\xc1\x09\xad\xeb\x5f\x28\x4e\xec\x20\x2f\x1b\xef\x11\x5b\xf9\x6b\x17\x82\xd3\xcc\xde\xb6\x82\xb6\x9b\xf9\x2d\x17\x0c\x00\x7d\x5d\xf8\x0e\x1e\xd9\x62\xf6\x77\xdc\x24\xa1\x45\xa1\xe4\xe8\x29\xe8\xde\xc0\x10\x4e\x5f\x78\x36\x59\x44"}, -{{0xc3,0xf5,0xe1,0x49,0x96,0x8a,0x24,0xf4,0xde,0x91,0x19,0x53,0x19,0x75,0xf4,0x43,0x01,0x5c,0xcc,0xa3,0x05,0xd7,0x11,0x9e,0xd4,0x74,0x9e,0x8b,0xf6,0xd9,0x4f,0xc7,},{0x39,0xaa,0xcc,0xdb,0x94,0x8a,0x40,0x38,0x53,0x8a,0x45,0x88,0x32,0x2f,0x80,0x6b,0xb1,0x29,0xb5,0x87,0x6c,0x4b,0xec,0x51,0x27,0x1a,0xfe,0x4f,0x49,0x69,0x00,0x45,},{0x5f,0xa2,0xb5,0x31,0x67,0x7b,0x00,0xb8,0x5b,0x0a,0x31,0x3c,0xbd,0x47,0x9f,0x55,0xf4,0xab,0x3e,0xc5,0xcf,0xce,0x5e,0x45,0x4d,0x2b,0x74,0x17,0x6c,0xcc,0x33,0x99,0xc8,0x99,0xf9,0xd6,0xb5,0x1e,0xd4,0xc1,0xe7,0x61,0x85,0xac,0x9f,0xe7,0x30,0xc4,0xb4,0x01,0x40,0x44,0xf7,0x04,0x11,0x85,0xbc,0x3c,0x85,0x72,0x2e,0xb2,0xea,0x02,},"\xc4\x63\x70\xe3\x7f\x2e\x0c\xad\xcf\x93\x40\x2f\x1f\x0c\xb0\x48\xf5\x28\x81\xba\x75\x0b\x7a\x43\xf5\x6a\xb1\x1c\xe3\x48\x73\x2f\xb5\x7e\x7f\x9a\xaf\x8d\xfc\xbe\x45\x5e\x14\xe9\x83\xc2\x48\xd0\x26\xa2\x7e\x7f\x14\x8d\x5d\xb5\xa5\x3f\x94\x63\x57\x02\xb8\x95\x12\x77\x71\x04\x7a\x87\x6d\x14\x10\x73\x86\xc5\xe0\xff\x89\x33\x34\x5b\xbd\x7a\x93\x6d\x99\x0d\x33\xef\xa2\x8c\x2e\xc4\xe4\x86\x4f\xfd\x2f\xf5\x76\xf7\xc8\x8f\x95\x4c\xfc\x1c\x45\x9e\x88\x3b\xb7\x12\xda\xe3\xcd\xf6\x63\x20\x66\xf1\xf4\xd1\x3a\x50\x96\x15\xb3\x36\x0c\xad\xc5\xa3\x07\xf2\x3e\x52\xa5\x1b\x40\xa6\xfe\xeb\xe0\xb1\x8d\x0e\x9e\xe4\xe3\x48\xf3\x3c\xd8\x1a\x8d\xef\x22\x2f\x6a\x59\xb1\x28\x61\xd3\x35\xbd\x9a\xf8\x5c\xc0\x04\xbe\x46\xf1\xd3\xa4\x24\xf4\x87\x0a\xe9\xdc\x58\x7e\x5a\x4a\xde\x13\x6b\x93\x70\x64\x93\x48\xc3\x3a\xc3\xbf\x1f\xeb\xee\xbf\xfe\xa3\x70\x85\xed\x59\xca\xc9\xd9\xe6\x96\x47\x0b\x23\x46\x09\xe9\xa1\x0a\x9d\x43\x1f\xf9\x1e\x69\xcb\x51\x35\xfd\x11\x7f\xf5\x8a\x36\x53\x97\x44\xeb\xe7\x0c\xea\x69\x73\xc0\x0c\x7a\x4d\x57\xb6\x2f\x4a\x71\x36\xd7\x31\xb8\xe4\x6f\xf1\x8e\xc0\xed\x69\x07\x00\x31\x90\x50\x75\xd8\x54\x1d\x56\x8c\xfc\xe6\xee\xb7\x62\x42\xb7\x81\x9a\x7b\x6a\x93\x55\x21\x11\xbb\x88\xf1\x65\x52\x7c\xfa\x69\x66\xd3\x9f\xcb\xe0\xa7\xde\xa0\x08\xe3\x9c\x7a\x3e\x57\x7a\xb3\x07\xcd\x1d\x0e\xa3\x26\x83\x3d\x52\x65\x4e\x17\x29\x55\xf3\xfc\xd4"}, -{{0x42,0x30,0x5c,0x93,0x02,0xf4,0x5e,0xa6,0xf8,0x7e,0x26,0xe2,0x20,0x8f,0xd9,0x4b,0x3c,0x4a,0xd0,0x37,0xb1,0xb6,0xc8,0x3c,0xf6,0x67,0x7a,0xa1,0x09,0x6a,0x01,0x3c,},{0x3b,0x97,0xb1,0xf1,0x1c,0xe4,0x5b,0xa4,0x6f,0xfb,0xb2,0x5b,0x76,0xbf,0xc5,0xad,0x7b,0x77,0xf9,0x0c,0xc6,0x9e,0xd7,0x61,0x15,0xde,0xa4,0x02,0x94,0x69,0xd5,0x87,},{0x18,0xd0,0x5e,0x5d,0x01,0x66,0x8e,0x83,0xf4,0x0f,0xa3,0xbb,0xee,0x28,0xb3,0x88,0xac,0xf3,0x18,0xd1,0xb0,0xb5,0xad,0x66,0x8c,0x67,0x2f,0x34,0x5c,0x8e,0xda,0x14,0xc2,0xf8,0x84,0xcd,0x2a,0x90,0x39,0x45,0x9c,0xe0,0x81,0x0b,0xc5,0xb5,0x80,0xfe,0x70,0xd3,0x96,0x4a,0x43,0xed,0xb4,0x9e,0x73,0xa6,0xff,0x91,0x4b,0xbf,0x04,0x0c,},"\xd1\x10\x82\x8d\x44\x91\x98\xd6\x75\xe7\x4e\x8e\x39\x43\x9f\xd1\x5e\x75\xbf\x2c\xc1\xf4\x30\xab\xfb\x24\x58\x36\x88\x5b\xaf\xc4\x20\xf7\x54\xb8\x9d\x2f\xbb\xf6\xdd\x34\x90\x79\x2e\x7a\x4f\x76\x60\x73\xcf\xe3\xb3\x02\xd0\x89\x83\x1a\xce\x86\x9e\x27\x30\xfd\xe4\x5c\x21\x21\xec\x3e\xf2\x17\xaa\x9c\x43\xfa\x7c\xc7\xe9\xed\x0a\x01\xad\x9f\x1d\x2f\xc3\x61\x36\x38\xca\x9f\xc1\x93\xc9\x8b\x37\x45\x5b\xf5\xdb\xf8\xf3\x8b\x64\x70\x8d\xfd\xca\x6c\x21\xf0\x97\x5f\x10\x17\xc5\xda\x5f\x64\x34\xbd\xa9\xf0\x33\xce\xc2\xa6\x31\xab\x50\x31\x8e\x01\x7b\x17\x0b\x24\x0b\xf0\x1e\xb8\xb3\x6c\x7e\x1c\xb5\x9e\x77\x36\xac\x34\x44\x42\x08\x13\x2a\x8f\x59\xe4\xf3\x13\xd6\x5d\x84\x9c\x6a\x4f\xdf\x13\xe2\x0e\xca\xee\x38\x23\xe5\x89\xa1\x71\xb3\x9b\x24\x89\x49\x7b\x06\xe6\xff\x58\xc2\xc9\xf1\xdc\x5d\x3a\xa3\xbd\x10\xe6\x44\x3e\x22\xd4\x2d\x07\xb7\x83\xf7\x9f\xd4\x3a\x46\xe1\xcd\xe3\x14\xb6\x63\xa9\x5f\x72\x46\xde\xa1\x31\xfc\xd4\x6d\x1d\xc3\x33\xc5\x45\x4f\x86\xb2\xc4\xe2\xe4\x24\xde\xa4\x05\xcc\x22\x30\xd4\xdc\xd3\x9a\x2e\xab\x2f\x92\x84\x5c\xf6\xa7\x99\x41\x92\x06\x3f\x12\x02\x74\x9e\xf5\x2d\xcb\x96\xf2\xb7\x9e\xd6\xa9\x81\x18\xca\x0b\x99\xba\x22\x85\x49\x08\x60\xeb\x4c\x61\xab\x78\xb9\xdd\xc6\xac\xc7\xad\x88\x3f\xa5\xe9\x6f\x9d\x02\x91\x71\x22\x3a\xbf\x75\x73\xe3\x62\x30\xe0\xa8\x1f\x6c\x13\x11\x15\x14\x73\xee\x26\x4f\x4b\x84\x2e\x92\x3d\xcb\x3b"}, -{{0xc5,0x7a,0x43,0xdc,0xd7,0xba,0xb8,0x51,0x60,0x09,0x54,0x69,0x18,0xd7,0x1a,0xd4,0x59,0xb7,0x34,0x5e,0xfd,0xca,0x8d,0x4f,0x19,0x92,0x98,0x75,0xc8,0x39,0xd7,0x22,},{0x20,0x83,0xb4,0x44,0x23,0x6b,0x9a,0xb3,0x1d,0x4e,0x00,0xc8,0x9d,0x55,0xc6,0x26,0x0f,0xee,0x71,0xac,0x1a,0x47,0xc4,0xb5,0xba,0x22,0x74,0x04,0xd3,0x82,0xb8,0x2d,},{0x1e,0xde,0xf9,0xbc,0x03,0x69,0x71,0xf1,0xfa,0x88,0xed,0xf4,0x53,0x93,0xc8,0x02,0xe6,0xc1,0xa1,0x63,0x1c,0x8a,0x06,0x87,0x1a,0x09,0xa3,0x20,0x82,0x1d,0xce,0x40,0xbe,0xca,0x97,0xe5,0x3a,0x03,0x61,0xa9,0x55,0xa4,0xc6,0xd6,0x0b,0x8c,0xa8,0xe4,0x00,0xc8,0x13,0x40,0x91,0x1c,0xcb,0x4f,0x56,0x28,0x40,0x41,0xcd,0xbb,0x18,0x04,},"\xa4\xf6\xd9\xc2\x81\xcf\x81\xa2\x8a\x0b\x9e\x77\x49\x9a\xa2\x4b\xde\x96\xcc\x12\x64\x37\x44\x91\xc0\x08\x29\x4e\xe0\xaf\x6f\x6e\x4b\xbb\x68\x63\x96\xf5\x90\x68\xd3\x58\xe3\x0f\xe9\x99\x2d\xb0\xc6\xf1\x66\x80\xa1\xc7\x1e\x27\xa4\xa9\x07\xac\x60\x7d\x39\xbd\xc3\x25\x8c\x79\x56\x48\x2f\xb3\x79\x96\xf4\xbe\xb3\xe5\x05\x1b\x81\x48\x01\x9a\x1c\x25\x6e\x2e\xe9\x99\xeb\xc8\xce\x64\xc5\x4e\x07\xfe\xdb\x4f\xbd\x89\x53\xeb\xd9\x3b\x7d\x69\xce\x5a\x00\x82\xed\xd6\x20\x9d\x12\xd3\x61\x9b\x4f\xd2\xea\xe9\x16\x46\x1f\x72\xa4\xce\x72\x71\x57\x25\x1a\x19\x20\x9b\xbf\xf9\xfb\xdb\xd2\x89\x43\x6f\x3f\xca\xcc\x6b\x4e\x13\x18\x52\x1a\x47\x83\x9c\xba\x4b\x14\xf7\xd7\xa2\x1e\x7b\x5d\x6b\x6a\x75\x3d\x58\x04\xaf\xcd\x2b\x1e\xb7\x77\x9b\x92\xab\xab\x8a\xfa\x8a\xa4\xfa\x51\xca\xec\x0b\x85\xdc\xd0\xfc\x2a\x06\x76\x03\x6d\x3f\x56\x63\x0a\x83\x1f\xfe\xb5\x02\x86\x1d\xd8\x91\x61\xc7\x08\xa9\xc0\x06\xc7\x3c\x93\x0c\xe5\xb9\x47\x56\x42\x6f\xf1\x8a\xa1\x12\xfb\x4e\xb9\xa6\x85\x00\xb4\x8d\x4e\xed\xbd\x41\x67\xb6\xff\xd0\xa1\x1d\x49\x44\x3a\x17\x3c\xe9\xd9\x49\x43\x67\x48\xfc\x06\x34\xf0\x6b\xb0\x8b\x8f\x34\x23\xf4\x46\x3d\xba\x7b\x4d\x19\x9b\x64\xdf\x57\x81\x17\xf0\xa2\x64\x5f\x0b\x2a\x1e\x2a\xda\x27\xd2\x86\xf7\x67\x33\xf2\x5b\x82\xed\x1d\x48\xa5\xc3\x89\x8d\x4a\xd6\x21\xe5\x0e\xd9\x06\x0d\xaa\xd4\x0a\x39\x53\x2e\x4d\x1b\xf1\x62\xce\x36\x80\x4d\x5d\x4e\x2d"}, -{{0x2d,0xdd,0xb6,0xb8,0xfd,0x04,0xfa,0x90,0xec,0xe1,0xa7,0x09,0xf8,0x41,0x8f,0x2e,0x5d,0x0c,0x9c,0x43,0xaf,0xe7,0xcf,0xce,0x19,0xe6,0xad,0x15,0xa7,0x34,0x76,0xf7,},{0x80,0x59,0xde,0x6a,0x7c,0x47,0x76,0x48,0x9e,0xcc,0x2e,0x7d,0x70,0x7f,0xfc,0xe3,0x02,0x85,0xbf,0x30,0xa2,0x3f,0x78,0xd7,0x2d,0xb4,0x9c,0xfd,0x6e,0xd0,0xd4,0x92,},{0xc6,0x34,0xea,0x7b,0xf7,0x2e,0x89,0x5a,0x2e,0x79,0x6e,0x28,0x34,0x20,0x14,0x15,0xb8,0xb4,0x5e,0x05,0xe0,0x45,0x55,0x92,0x84,0xeb,0x90,0x52,0xc0,0xe8,0x4f,0x62,0xa5,0xa9,0xf0,0xc9,0x76,0x4f,0x75,0x76,0x78,0x8c,0x72,0x28,0xb1,0x9e,0xf5,0x17,0xc1,0x95,0x49,0x73,0x25,0xa4,0x8a,0x93,0x44,0xb1,0x47,0xc1,0x2f,0xd7,0x55,0x09,},"\x47\x4b\xaa\x59\x0a\x4c\xd7\x2d\x54\x24\xe5\x1d\x82\x57\xb3\xd4\x43\x25\xbc\x4c\x50\x63\xa0\x03\x3c\x86\xeb\xbe\x99\xed\x72\x12\x18\x4c\x19\x94\x4d\x08\x2a\x11\x53\x79\xdd\x4c\xec\xe9\x73\xfa\xa0\xbc\xa6\x48\x5b\xd2\x5f\x37\x44\xa7\x19\xe7\x0a\xa0\x29\x1e\x1b\x5a\x96\xe6\x37\xc1\x40\x61\x6a\x98\x26\x33\x57\xc7\x6b\x6e\xb0\x08\x3f\xe5\x14\x14\xe3\x86\x87\x0d\x0f\xdc\x7d\xd9\xab\xe4\xff\x6f\xb5\xbb\xf1\xe7\xb1\x5d\xac\x3e\x08\xe2\x61\x5f\x65\x5c\x31\x04\xce\xb3\x2a\x4c\xc2\xc9\xe9\xc4\x3c\xf2\x82\xd3\x46\xac\x25\x3c\xcc\x46\xb6\x35\xae\x04\x09\x73\xb4\x97\x35\x72\x0f\xfb\x89\x04\x69\xa5\x67\xc5\x82\x4e\x0c\x00\xd7\xcc\xd5\x50\x9a\x71\x80\x92\xa9\x06\x46\x1c\x4d\x61\x63\xea\xf4\x22\x41\x8f\x5f\xc6\xe0\x09\xfc\x3f\x52\x9a\xc6\x1a\x2f\x89\xbb\x8e\x0e\xd4\x5d\x94\x0c\x4c\x23\x31\xff\x8d\x8e\x1d\x6d\x58\xd4\x17\xd8\xfc\x26\x56\xa0\x2e\x87\x01\xae\xe7\x5a\xed\x91\x87\x24\xee\xbe\x4a\x2c\xf4\x74\x4c\x5c\x40\x1e\x21\x70\x23\xdf\x68\xa6\xf6\xa0\x22\x8b\xd0\x5a\x67\x9a\x69\x7d\x8d\xe7\x03\x6b\x9e\xd2\x69\x09\x0d\x3c\x65\x48\x6a\xfb\x91\xe2\x79\x54\xeb\x15\xb9\x64\x66\x5e\xde\x7a\xd0\x08\xf1\x2f\xb3\xa9\xd0\xe6\x9c\x13\xb4\x25\x4f\x43\x81\x9e\x08\x18\xa4\x19\x5f\x68\xb8\xa3\x8a\xe8\x1f\x3f\xcb\x18\x79\xc9\x5a\xb4\xcd\x0f\xfc\x38\xe3\x81\x08\x92\x60\xcc\xa9\x67\xac\xe5\xa0\x85\xb4\x57\xab\x5e\xb3\x63\x85\x21\x01\x37\x75\x70\xf9\xac\x9e\x38"}, -{{0x55,0x47,0xf1,0x00,0x4b,0xae,0xdf,0xce,0x5c,0xfc,0x08,0x50,0xb0,0x53,0x02,0x37,0x4a,0xad,0x24,0xf6,0x16,0x39,0x94,0xec,0xd7,0x51,0xdf,0x3a,0xf3,0xc1,0x06,0x20,},{0x7c,0xe6,0x20,0x78,0x73,0x85,0xee,0x19,0x51,0xac,0x49,0xa7,0x73,0x52,0xee,0x0d,0x6f,0x8c,0x5c,0xd4,0x7d,0xf7,0x4e,0x9e,0x32,0x16,0xa6,0x32,0x4f,0xc7,0xcf,0x7f,},{0x29,0xdf,0x3a,0xd5,0x89,0x00,0x9c,0x66,0x7b,0xaa,0x5e,0x72,0xda,0xbb,0x4e,0x53,0xcb,0x78,0x76,0xde,0x4e,0x7e,0xfe,0x5c,0xc2,0x1e,0xad,0x7f,0xa8,0x78,0xdb,0x57,0xf9,0x7c,0x11,0x03,0xdd,0xb3,0x9a,0x86,0x1e,0xb8,0x86,0x53,0xc1,0xd4,0xec,0x3b,0x43,0x06,0xe4,0x58,0x4b,0x47,0xb8,0xbc,0x90,0x42,0x31,0x19,0xe7,0xe4,0xaf,0x00,},"\xa6\xc1\x7e\xeb\x5b\x80\x66\xc2\xcd\x9a\x89\x66\x73\x17\xa9\x45\xa0\xc7\xc9\x69\x96\xe7\x7a\xe8\x54\xc5\x09\xc6\xcd\x06\x31\xe9\x22\xad\x04\x50\x3a\xf8\x7a\x3c\x46\x28\xad\xaf\xed\x76\x00\xd0\x71\xc0\x78\xa2\x2e\x7f\x64\xbd\xa0\x8a\x36\x2b\x38\xb2\x6c\xa1\x50\x06\xd3\x8a\xcf\x53\x2d\x0d\xed\xea\x41\x77\xa2\xd3\x3f\x06\x95\x6d\x80\xe9\x63\x84\x8e\xc7\x91\xb2\x76\x2f\xa9\x94\x49\xb4\xf1\xa1\xed\x9b\x3f\x25\x80\xbe\x3a\xc7\xd7\xf5\x2f\xb1\x44\x21\xd6\x22\x2b\xa7\x6f\x80\x77\x50\xc6\xcb\xb0\xb1\x6f\x08\x95\xfc\x73\xd9\xdf\xc5\x87\xe1\xa9\xe5\xd1\xe5\x83\x75\xfb\xab\x70\x5b\x8f\x0c\x1f\xd7\xdf\x8b\x3a\xd4\x46\xf2\xf0\x84\x59\xe7\xed\x1a\xf5\x95\x56\xfb\xc9\x66\xdc\x24\x9c\x1c\xf6\x04\xf3\xe6\x77\xc8\xa0\x9d\x43\x63\x60\x87\x74\xbf\x38\x11\xbe\xf0\x64\x27\x48\xc5\x5c\x51\x6c\x7a\x58\x0f\xa3\x49\x90\x50\xac\xb3\x0e\xed\x87\x0d\x0d\x91\x17\x4c\xb6\x23\xe9\x8c\x3a\xd1\x21\xcf\x81\xf0\x4e\x57\xd4\x9b\x00\x84\x24\xa9\x8a\x31\xee\xaa\xf5\xf3\x8e\x00\x0f\x90\x3d\x48\xd2\x15\xed\x52\xf8\x62\xd6\x36\xa5\xa7\x36\x07\xde\x85\x76\x01\x67\x26\x7e\xfe\x30\xf8\xa2\x6e\xbc\x5a\xa0\xc0\x9f\x5b\x25\x8d\x33\x61\xca\x69\xd1\xd7\xee\x07\xb5\x96\x48\x17\x9a\xb2\x17\x0e\xc5\x0c\x07\xf6\x61\x6f\x21\x68\x72\x52\x94\x21\xa6\x33\x4a\x4a\x1e\xd3\xd2\x67\x1e\xf4\x7b\xc9\xa9\x2a\xfb\x58\x31\x4e\x83\x2d\xb8\xa9\x00\x34\x08\xa0\x48\x75\x03\xfe\x4f\x67\x77\x0d\xd4\xb6"}, -{{0x3d,0xd7,0x20,0x3c,0x23,0x7a,0xef,0xe9,0xe3,0x8a,0x20,0x1f,0xf3,0x41,0x49,0x01,0x79,0x90,0x5f,0x9f,0x10,0x08,0x28,0xda,0x18,0xfc,0xbe,0x58,0x76,0x8b,0x57,0x60,},{0xf0,0x67,0xd7,0xb2,0xff,0x3a,0x95,0x7e,0x83,0x73,0xa7,0xd4,0x2e,0xf0,0x83,0x2b,0xcd,0xa8,0x4e,0xbf,0x28,0x72,0x49,0xa1,0x84,0xa2,0x12,0xa9,0x4c,0x99,0xea,0x5b,},{0x4c,0x03,0x69,0x35,0xa9,0x6a,0xbc,0x0d,0x05,0x0d,0x90,0x7b,0xed,0xbe,0x99,0x46,0xfb,0x97,0x43,0x9f,0x03,0x9c,0x74,0x2e,0x05,0x1c,0xcf,0x09,0xad,0xd7,0xdf,0x44,0xd1,0x7d,0xa9,0x8c,0x2c,0xa0,0x1b,0xdc,0x24,0x24,0xda,0x1e,0x4d,0xeb,0xf3,0x47,0xf8,0xff,0xf4,0x8a,0xc8,0x03,0x0d,0x2c,0xc0,0x7f,0x95,0x75,0xc0,0x44,0xbe,0x04,},"\xdb\x28\xed\x31\xac\x04\xb0\xc2\xde\xce\xe7\xa6\xb2\x4f\xc9\xa0\x82\xcc\x26\x2c\xa7\xcc\xf2\xa2\x47\xd6\x37\x2e\xc3\xe9\x12\x0e\xce\xdb\x45\x42\xea\x59\x3f\xea\x30\x33\x5c\x5a\xb9\xdd\x31\x8a\x3b\x4f\xd5\x83\x42\x99\xcf\x3f\x53\xd9\xef\x46\x13\x7b\x27\x3c\x39\x0e\xc3\xc2\x6a\x0b\x44\x70\xd0\xd9\x4b\x77\xd8\x2c\xae\x4b\x24\x58\x78\x37\xb1\x67\xbb\x7f\x81\x66\x71\x0b\xae\xb3\xee\x70\xaf\x79\x73\x16\xcb\x7d\x05\xfa\x57\xe4\x68\xae\x3f\x0b\xd4\x49\x40\x4d\x85\x28\x80\x8b\x41\xfc\xca\x62\xf5\xe0\xa2\xaa\x5d\x8f\x3a\xca\xb0\x08\xcc\x5f\x6e\x5a\xb0\x27\x77\xbd\xcd\xe8\x7f\x0a\x10\xef\x06\xa4\xbb\x37\xfe\x02\xc9\x48\x15\xcf\x76\xbf\xb8\xf5\xcd\xd8\x65\xcc\x26\xdc\xb5\xcf\x49\x2e\xdf\xd5\x47\xb5\x35\xe2\xe6\xa6\xd8\x54\x09\x56\xdc\xba\x62\xcf\xea\x19\xa9\x47\x44\x06\xe9\x34\x33\x7e\x45\x42\x70\xe0\x10\x36\xac\x45\x79\x3b\x6b\x8a\xce\xda\x18\x7a\x08\xd5\x6a\x2c\xe4\xe9\x8f\x42\xea\x37\x5b\x10\x1a\x6b\x9f\xcb\x42\x31\xd1\x71\xaa\x46\x3e\xeb\x43\x58\x6a\x4b\x82\xa3\x87\xbc\xdd\xaf\x71\xa8\x0f\xd5\xc1\xf7\x29\x2e\xfc\x2b\xd8\xe7\x0c\x11\xea\xa8\x17\x10\x60\x61\xb6\xc4\x61\xc4\x88\x3d\x61\x3c\xc0\x6c\x7e\x2a\x03\xf7\x3d\x90\xfc\x55\xcd\xc0\x72\x65\xee\xfd\x36\xbe\x72\x27\x03\x83\xd6\xc6\x76\xca\xe3\x7c\x93\x69\x1f\x1a\xe3\xd9\x27\xb3\xa1\xcd\x96\x3e\x42\x29\x75\x7a\xe5\x23\x1e\xea\x73\xa9\xf7\x15\x15\x62\x83\x05\x41\x0a\xc2\x59\x3b\x32\x5c\xc6\x31"}, -{{0x28,0x27,0x75,0xdf,0x9e,0xbb,0xd7,0xc5,0xa6,0x5f,0x3a,0x2b,0x09,0x6e,0x36,0xee,0x64,0xa8,0xf8,0xea,0x71,0x9d,0xa7,0x77,0x58,0x73,0x9e,0x4e,0x74,0x76,0x11,0x1d,},{0xa2,0xb4,0x96,0x46,0x03,0x3a,0x13,0x93,0x7c,0xad,0x6b,0x0e,0x91,0x4e,0x3c,0xec,0x54,0x98,0x9c,0x25,0x2c,0xa5,0x64,0x3d,0x07,0x65,0x55,0xd8,0xc5,0x5e,0x56,0xe0,},{0x15,0x76,0x39,0x73,0x85,0x94,0x02,0x90,0x7d,0x8d,0xcb,0x86,0xad,0xc2,0x4a,0x2a,0x16,0x8b,0xa3,0xab,0xf2,0x24,0x61,0x73,0xd6,0x34,0x8a,0xfe,0xd5,0x1e,0xf6,0x0b,0x0c,0x0e,0xde,0xff,0x4e,0x10,0xbc,0xef,0x4c,0x6e,0x57,0x78,0xc8,0xbc,0x1f,0x5e,0x9e,0xe0,0x23,0x73,0x73,0x44,0x5b,0x45,0x51,0x55,0xd2,0x3d,0xe1,0x27,0xa2,0x02,},"\x14\xcc\x50\xc2\x97\x3e\xa9\xd0\x18\x7a\x73\xf7\x1c\xb9\xf1\xce\x07\xe7\x39\xe0\x49\xec\x2b\x27\xe6\x61\x3c\x10\xc2\x6b\x73\xa2\xa9\x66\xe0\x1a\xc3\xbe\x8b\x50\x5a\xea\xad\x14\x85\xc1\xc2\xa3\xc6\xc2\xb0\x0f\x81\xb9\xe5\xf9\x27\xb7\x3b\xfd\x49\x86\x01\xa7\x62\x2e\x85\x44\x83\x7a\xad\x02\xe7\x2b\xf7\x21\x96\xdc\x24\x69\x02\xe5\x8a\xf2\x53\xad\x7e\x02\x5e\x36\x66\xd3\xbf\xc4\x6b\x5b\x02\xf0\xeb\x4a\x37\xc9\x55\x49\x92\xab\xc8\x65\x1d\xe1\x2f\xd8\x13\x17\x73\x79\xbb\x0c\xe1\x72\xcd\x8a\xaf\x93\x7f\x97\x96\x42\xbc\x2e\xd7\xc7\xa4\x30\xcb\x14\xc3\xcd\x31\x01\xb9\xf6\xb9\x1e\xe3\xf5\x42\xac\xdf\x01\x7f\x8c\x21\x16\x29\x7f\x45\x64\x76\x8f\x4d\xb9\x5d\xad\x8a\x9b\xcd\xc8\xda\x4d\x8f\xb1\x3e\xf6\xe2\xda\x0b\x13\x16\xd3\xc8\xc2\xf3\xed\x83\x6b\x35\xfe\x2f\xd3\x3e\xff\xb4\x09\xe3\xbc\x1b\x0f\x85\x22\x5d\x2a\x1d\xe3\xbf\xc2\xd2\x05\x63\x94\x64\x75\xc4\xd7\xca\x9f\xdd\xba\xf5\x9a\xd8\xf8\x96\x1d\x28\x7a\xe7\xdd\x80\x3e\x7a\xf1\xfa\x61\x23\x29\xb1\xbd\xc0\x4e\x22\x56\x00\xae\x73\x1b\xc0\x1a\xe0\x92\x5a\xed\x62\xac\x50\xd4\x60\x86\xf3\x64\x6c\xf4\x7b\x07\x2f\x0d\x3b\x04\x4b\x36\xf8\x5c\xec\x72\x9a\x8b\xb2\xb9\x28\x83\xca\x4d\xfb\x34\xa8\xee\x8a\x02\x73\xb3\x1a\xf5\x09\x82\xbb\x61\x31\xbf\xa1\x1d\x55\x50\x4b\x1f\x6f\x1a\x0a\x00\x43\x8c\xa2\x6d\x8a\xb4\xf4\x8b\xcd\xdc\x9d\x5a\x38\x85\x1a\xbe\xde\x41\x51\xd5\xb7\x0d\x72\x07\x32\xa0\x0a\xbe\xa2\xc8\xb9\x79"}, -{{0x47,0x30,0xa5,0xcf,0x97,0x72,0xd7,0xd6,0x66,0x5b,0xa7,0x87,0xbe,0xa4,0xc9,0x52,0x52,0xe6,0xec,0xd6,0x3e,0xc6,0x23,0x90,0x54,0x7b,0xf1,0x00,0xc0,0xa4,0x63,0x75,},{0xf9,0xf0,0x94,0xf7,0xcc,0x1d,0x40,0xf1,0x92,0x6b,0x5b,0x22,0xdc,0xe4,0x65,0x78,0x44,0x68,0xb2,0x0a,0xb3,0x49,0xbc,0x6d,0x4f,0xdf,0x78,0xd0,0x04,0x2b,0xbc,0x5b,},{0x55,0x2c,0x73,0x47,0xbd,0xfe,0x13,0x16,0x46,0xce,0x09,0x32,0xd8,0x2a,0x36,0xd2,0xc1,0xb7,0x6d,0x7c,0x30,0xee,0x89,0x0e,0x05,0x92,0xe1,0x9f,0x9d,0x18,0xb9,0xa5,0x6f,0x48,0xd7,0xa9,0xb6,0x8c,0x01,0x7d,0xa6,0xb5,0x50,0xc9,0x43,0xaf,0x4a,0x90,0x7b,0xaf,0x31,0x7e,0x41,0x9f,0xbb,0xc9,0x6f,0x6c,0xf4,0xbf,0xad,0x42,0xde,0x00,},"\xe7\x47\x6d\x2e\x66\x84\x20\xe1\xb0\xfa\xdf\xba\xa5\x42\x86\xfa\x7f\xa8\x90\xa8\x7b\x82\x80\xe2\x60\x78\x15\x22\x95\xe1\xe6\xe5\x5d\x12\x41\x43\x5c\xc4\x30\xa8\x69\x3b\xb1\x0c\xde\x46\x43\xf5\x9c\xbf\xcc\x25\x6f\x45\xf5\x09\x0c\x90\x9a\x14\xc7\xfc\x49\xd3\x7b\xfc\x25\xaf\x11\xe8\xf4\xc8\x3f\x4c\x32\xd4\xaa\xbf\x43\xb2\x0f\xa3\x82\xbb\x66\x22\xa1\x84\x8f\x8f\xfc\x4d\xff\x34\x08\xbb\x4e\xc7\xc6\x7a\x35\xb4\xcd\xae\xe5\xe2\x79\xc0\xfc\x0a\x66\x09\x3a\x9f\x36\xa6\x0f\xdd\x65\xe6\x33\x4a\x80\x4e\x84\x5c\x85\x30\xb6\xfd\xa3\x63\xb5\x64\x03\x37\xd0\x27\x24\x3c\xcf\xb3\xc1\x77\xf4\x3e\x71\x78\x96\xe4\x6e\xad\x7f\x72\xca\x06\xaa\x0f\xf1\xe7\x72\x47\x12\x1b\xaf\x48\xbe\x9a\x44\x5f\x72\x9c\xa1\x39\x0f\xc4\x61\x51\xcb\xd3\x3f\xcb\xd7\x37\x3f\x27\xa6\xba\x55\xc9\x2c\xbf\x69\x45\xb0\x9b\x44\xb9\xa4\xe5\x80\x0d\x40\x30\x70\xae\x66\x04\x89\x97\xb2\x19\x7f\x02\x18\x1a\x09\x7e\x56\x3f\x9b\x9a\xcc\x84\x11\x39\x25\x8a\x25\x8b\xc6\x10\xd3\xbd\x89\x16\x37\x35\x6b\x2e\xdc\x8c\x18\x4c\x35\xc6\x5a\xf9\x1a\xaf\x7b\x1c\x16\xd7\x4a\x5f\x5f\x86\x25\x48\x13\x92\x54\xec\xf5\x50\x63\x1d\x5f\x88\x49\xaf\xdb\x5b\x64\xcf\x36\x6f\xf2\x63\x3a\x93\xf3\xa1\x8c\x39\xb5\x15\x02\x45\xfb\x5f\x33\xc9\xe4\xe2\xd9\x4a\xf6\x96\x3a\x70\xb8\x8f\x9e\x7e\x51\x9f\x8f\xa2\xa0\xf2\xe3\x74\x9d\xe8\x83\xd0\xe6\xf0\x52\xa9\x49\xd0\xfc\x71\x53\xa8\x69\x3f\x6d\x80\x1d\x73\x52\xeb\x2f\x7a\x46\x5c\x0e"}, -{{0x27,0x70,0xaa,0xdd,0x1d,0x12,0x3e,0x95,0x47,0x83,0x2d,0xfb,0x2a,0x83,0x7e,0xba,0x08,0x91,0x79,0xef,0x4f,0x23,0xab,0xc4,0xa5,0x3f,0x2a,0x71,0x4e,0x42,0x3e,0xe2,},{0x3c,0x5f,0xbb,0x07,0x53,0x0d,0xd3,0xa2,0x0f,0xf3,0x5a,0x50,0x0e,0x37,0x08,0x92,0x63,0x10,0xfe,0xd8,0xa8,0x99,0x69,0x02,0x32,0xb4,0x2c,0x15,0xbd,0x86,0xe5,0xdc,},{0xf2,0x67,0x71,0x5e,0x9a,0x84,0xc7,0x31,0x4f,0x2d,0x58,0x69,0xef,0x4a,0xb8,0xd2,0x14,0x9a,0x13,0xf7,0xe8,0xe1,0xc7,0x28,0xc4,0x23,0x90,0x62,0x93,0xb4,0x9c,0xe6,0x28,0x34,0x54,0xdd,0x1c,0x7b,0x04,0x74,0x1d,0xf2,0xea,0xbe,0xdc,0x4d,0x6a,0xb1,0x39,0x7d,0xc9,0x5a,0x67,0x9d,0xf0,0x4d,0x2c,0x17,0xd6,0x6c,0x79,0xbb,0x76,0x01,},"\xa5\xcc\x20\x55\xeb\xa3\xcf\x6f\x0c\x63\x32\xc1\xf2\xab\x58\x54\x87\x09\x13\xb0\x3f\xf7\x09\x3b\xc9\x4f\x33\x5a\xdd\x44\x33\x22\x31\xd9\x86\x9f\x02\x7d\x82\xef\xd5\xf1\x22\x71\x44\xab\x56\xe3\x22\x2d\xc3\xdd\xcc\xf0\x62\xd9\xc1\xb0\xc1\x02\x4d\x9b\x41\x6d\xfa\x3e\xe8\xa7\x02\x79\x23\x00\x34\x65\xe0\xff\xae\xfb\x75\xb9\xf2\x9d\xc6\xbc\xf2\x13\xad\xc5\xe3\x18\xfd\x8b\xa9\x3a\x7a\xa5\xbf\xb4\x95\xde\x9d\x7c\x5e\x1a\x19\x6c\xd3\xa2\xd7\x72\x1f\x8b\xa7\x85\xaa\x90\x52\xa1\x81\x1c\x7f\xcc\x8f\x93\x93\x27\x65\x05\x9c\xab\x9c\x9b\x71\x89\x45\x89\x5e\xf2\x6f\x3a\xc0\x48\xd4\xca\xbf\x91\xa9\xe6\xaa\x83\xac\x14\xd4\x31\x56\x82\x78\x37\x91\x4e\xb7\x63\xa2\x3c\xba\x53\xf6\x0f\x15\x0f\x4b\x70\x20\x3e\xc1\x83\x3f\xf1\x05\x84\x94\x57\xa8\xda\x73\x27\x66\x1f\xb2\x3a\x55\x41\x64\xe0\x5f\xcf\x01\x46\xb1\x06\x74\x96\x4b\xe6\xf6\xaa\x0a\xcc\x94\xc4\x1a\xd5\x71\x80\xe5\x18\x0d\x19\x9b\xd9\x10\x2f\x55\xd7\x40\xe8\x17\x89\xb1\x56\x71\xbb\xd0\x67\x0e\x6d\xe5\xd9\x7e\x1a\xe6\x26\xd8\xa0\xeb\xc3\x2c\x8f\xd9\xd2\x47\x37\x27\x4e\x47\xd2\xdd\x59\x41\xa2\x72\xe7\x2a\x59\x89\x28\xad\x10\x9c\xde\x93\x7b\xf2\x48\xd5\x7f\x5d\x29\x42\x98\x3c\x51\xe2\xa8\x9f\x8f\x05\x4d\x5c\x48\xdf\xad\x8f\xcf\x1f\xfa\x97\xf7\xde\x6a\x3a\x43\xca\x15\xfc\x67\x20\xef\xae\xc6\x9f\x08\x36\xd8\x42\x23\xf9\x77\x6d\x11\x1e\xc2\xbb\xc6\x9b\x2d\xfd\x58\xbe\x8c\xa1\x2c\x07\x21\x64\xb7\x18\xcd\x7c\x24\x6d\x64"}, -{{0x4f,0xda,0xb7,0xc1,0x60,0x0e,0x70,0x11,0x4b,0x11,0xf5,0x33,0x24,0x23,0x76,0xaf,0x76,0x14,0xb4,0xd5,0xda,0x04,0x6a,0xc4,0xbe,0xde,0xa2,0x1d,0x8a,0x36,0x15,0x98,},{0xa2,0x5c,0x9a,0x94,0xd6,0xe4,0xec,0xd9,0x5a,0x4b,0xd6,0x80,0x5f,0x76,0x2e,0xb1,0xc4,0x57,0xa8,0xd4,0x5d,0x24,0x32,0x38,0xb1,0x83,0x9c,0xbb,0xa8,0xf4,0x41,0xcc,},{0x50,0x75,0xc0,0x90,0xcf,0xbe,0xb6,0xb0,0x18,0x02,0xaf,0x7f,0x4d,0xa5,0xaa,0x4f,0x43,0x4d,0x5e,0xe2,0xf3,0x53,0x0e,0xeb,0xb7,0x5c,0x85,0xe0,0x86,0x21,0xf8,0x3e,0xdc,0x08,0xaa,0x96,0x69,0x38,0x94,0xa4,0x27,0x76,0x33,0xba,0x81,0xe1,0x9e,0x9e,0x55,0xaf,0x5c,0x49,0x5d,0xaa,0x5e,0x1a,0x6f,0x8c,0xbb,0x79,0xc0,0x1c,0x72,0x07,},"\xda\x40\x58\x90\xd1\x1a\x87\x2c\x11\x9d\xab\x5e\xfc\xbf\xf6\x1e\x93\x1f\x38\xec\xcc\xa4\x57\xed\xc6\x26\xd3\xea\x29\xed\x4f\xe3\x15\x4f\xaf\xec\x14\x44\xda\x74\x34\x3c\x06\xad\x90\xac\x9d\x17\xb5\x11\xbc\xb7\x3b\xb4\x9d\x90\xba\xfb\x7c\x7e\xa8\x00\xbd\x58\x41\x1d\xf1\x27\x5c\x3c\xae\x71\xb7\x00\xa5\xda\xb4\x91\xa4\x26\x16\x78\x58\x79\x56\xaa\x4a\x21\x9e\x1a\xc6\xdd\x3f\xb2\xcb\x8c\x46\x19\x72\x18\xe7\x26\xdc\x7e\xd2\x34\x52\x6a\x6b\x01\xc0\xd7\x2c\xb9\x3a\xb3\xf4\xf3\x8a\x08\xe5\x94\x0b\x3f\x61\xa7\x2a\xd2\x78\x9a\x05\x32\x00\x0f\xac\x1d\x2d\x2e\x3a\xd6\x32\xac\x8b\x62\xbb\x3f\xf5\xb9\x9d\x53\x59\x7b\xf4\xd4\x4b\x19\x67\x49\x24\xdf\x9b\x3d\xb3\xd0\x25\x3f\x74\x62\x7c\xca\xb3\x00\x31\xc8\x5e\x29\x1c\x58\xb5\xfa\x91\x67\x52\x2a\x46\x74\x6f\xc3\x07\x03\x67\x45\xd4\xf9\x81\x77\x86\xe5\xd3\x00\xe6\xc5\xd5\x03\x12\x5f\xea\x01\xde\xc3\xe3\xfe\xdb\xf3\x86\x1c\xa2\x62\x7a\x05\x18\xfb\x2b\x24\xe5\xa7\xa0\x14\x17\x87\x19\xe9\xb3\x45\xf7\xb2\x49\xce\x3a\x41\x32\x80\xc8\xde\xb6\x74\xf5\x9a\x25\xbe\x92\xa8\xab\x64\x00\xc7\xc5\x2b\x07\x28\xae\x34\xe2\x2b\x2e\xc2\x00\xc1\xcb\xab\xa2\xcc\xd8\xaf\x29\x24\x9d\x17\xaf\x60\xc3\x60\x07\xa7\x22\xfc\x80\x25\x8a\x7b\xeb\xab\x1c\xda\xad\x74\x62\xa8\xb7\x58\x8c\x2f\x7e\x27\xc6\xd0\x7a\xfc\xf6\x01\x17\xfe\xd1\x1b\xd6\x85\x9e\x75\xe3\xb4\xfc\xee\x39\x81\x88\x1e\x95\xdd\x11\x68\x27\xdd\x4b\x36\x9a\xf0\x69\xd3\xc8\xf2\x67\x6f\x8a"}, -{{0x26,0x45,0x04,0x60,0x4e,0x70,0xd7,0x2d,0xc4,0x47,0x4d,0xbb,0x34,0x91,0x3e,0x9c,0x0f,0x80,0x6d,0xfe,0x18,0xc7,0x87,0x9a,0x41,0x76,0x2a,0x9e,0x43,0x90,0xec,0x61,},{0xeb,0x2b,0x51,0x8c,0xe7,0xdc,0x71,0xc9,0x1f,0x36,0x65,0x58,0x16,0x51,0xfd,0x03,0xaf,0x84,0xc4,0x6b,0xf1,0xfe,0xd2,0x43,0x32,0x22,0x35,0x3b,0xc7,0xec,0x51,0x1d,},{0xee,0xa4,0x39,0xa0,0x0f,0x7e,0x45,0x9b,0x40,0x2b,0x83,0x51,0x50,0xa7,0x79,0xee,0xd1,0x71,0xab,0x97,0x1b,0xd1,0xb5,0x8d,0xcc,0x7f,0x93,0x86,0xda,0xdd,0x58,0x3d,0xe8,0xdc,0x69,0xe2,0x67,0x12,0x1d,0xde,0x41,0xf0,0xf9,0x49,0x3d,0x45,0x0b,0x16,0x21,0x9c,0xdf,0x3c,0x22,0xf0,0x94,0x82,0xce,0x40,0x2f,0xe1,0x7c,0xa4,0x9e,0x08,},"\x90\x1d\x70\xe6\x7e\xd2\x42\xf2\xec\x1d\xda\x81\x3d\x4c\x05\x2c\xfb\x31\xfd\x00\xcf\xe5\x44\x6b\xf3\xb9\x3f\xdb\x95\x0f\x95\x2d\x94\xef\x9c\x99\xd1\xc2\x64\xa6\xb1\x3c\x35\x54\xa2\x64\xbe\xb9\x7e\xd2\x0e\x6b\x5d\x66\xad\x84\xdb\x5d\x8f\x1d\xe3\x5c\x49\x6f\x94\x7a\x23\x27\x09\x54\x05\x1f\x8e\x4d\xbe\x0d\x3e\xf9\xab\x30\x03\xdd\x47\xb8\x59\x35\x6c\xec\xb8\x1c\x50\xaf\xfa\x68\xc1\x5d\xad\xb5\xf8\x64\xd5\xe1\xbb\x4d\x3b\xad\xa6\xf3\xab\xa1\xc8\x3c\x43\x8d\x79\xa9\x4b\xfb\x50\xb4\x38\x79\xe9\xce\xf0\x8a\x2b\xfb\x22\xfa\xd9\x43\xdb\xf7\x68\x37\x79\x74\x6e\x31\xc4\x86\xf0\x1f\xd6\x44\x90\x50\x48\xb1\x12\xee\x25\x80\x42\x15\x3f\x46\xd1\xc7\x77\x2a\x06\x24\xbc\xd6\x94\x1e\x90\x62\xcf\xda\x75\xdc\x87\x12\x53\x3f\x40\x57\x33\x5c\x29\x80\x38\xcb\xca\x29\xeb\xdb\x56\x0a\x29\x5a\x88\x33\x96\x92\x80\x8e\xb3\x48\x1f\xd9\x73\x5e\xa4\x14\xf6\x20\xc1\x43\xb2\x13\x3f\x57\xbb\x64\xe4\x47\x78\xa8\xca\x70\x91\x82\x02\xd1\x57\x42\x61\x02\xe1\xdf\xc0\xa8\xf7\xb1\xae\x48\x7b\x74\xf0\x27\x92\x63\x31\x54\xdf\xe7\x4c\xaa\x1b\x70\x88\xfd\xa2\x2f\xa8\xb9\xbc\x35\x4c\x58\x5f\x15\x67\x70\x6e\x29\x55\x49\x38\x70\xf5\x41\x69\xe0\xd7\x69\x11\x59\xdf\x43\x89\x79\x61\xd2\x4a\x85\x2e\xa9\x70\xc5\x14\x94\x8f\x3b\x48\xf7\x1e\xe5\x86\xe7\x2e\xc7\x8d\xb8\x20\xf2\x53\xe0\x8d\xb8\x4f\x6f\x31\x2c\x43\x33\xbd\x0b\x73\x2f\xe7\x58\x83\x50\x77\x83\xe9\xa1\xfd\x4f\xba\xb8\xe5\x87\x0f\x9b\xf7\xad\x58\xaa"}, -{{0x2c,0xa7,0x44,0x7a,0x36,0x68,0xb7,0x48,0xb1,0xfd,0x3d,0x52,0xd2,0x08,0x0d,0x30,0xe3,0x4d,0x39,0x7b,0xb2,0x84,0x6c,0xaf,0x8f,0x65,0x9a,0xc1,0x68,0x78,0x8c,0xa5,},{0xab,0x33,0x1c,0xd4,0x0a,0x31,0xd0,0x17,0x3c,0x0c,0x8c,0x1c,0x17,0x00,0x25,0x32,0x80,0x7b,0xf8,0x9e,0x3e,0xdb,0x6d,0x34,0xc2,0xdd,0x82,0x94,0x63,0x2b,0x9f,0xbc,},{0xf9,0x3a,0xda,0x15,0xae,0x9c,0xd2,0xb5,0x4f,0x26,0xf8,0x6f,0x0c,0x28,0x39,0x2a,0xed,0x5e,0xb6,0xb6,0xb4,0x4d,0x01,0xa4,0xe3,0x3a,0x54,0xe7,0xda,0x37,0xc3,0x8e,0x8d,0x53,0x36,0x6f,0x73,0xfd,0x85,0xbe,0x64,0x2e,0x4e,0xc8,0x12,0x36,0xd1,0x63,0xf0,0xd0,0x25,0xe7,0x6c,0x8b,0xbd,0xd6,0x5d,0x43,0xdf,0x49,0xf0,0x9c,0x1f,0x01,},"\xa8\x2b\xcd\x94\x24\xbf\xfd\xa0\xf2\xf5\xe9\xea\xe1\x78\x35\xdb\xe4\x68\xf6\x1b\x78\x5a\xab\x82\x93\x47\x37\xa9\x1c\x5f\x60\x2c\xb7\xc6\x17\xcd\xff\xe8\x7c\xad\x72\x6a\x49\x72\xe1\x5a\x7b\x8e\xe1\x47\xf0\x62\xd2\xa5\xa4\xd8\x97\x06\xb5\x71\xfa\x8a\xa2\xb9\x59\x81\xc7\x8a\xbe\xaa\xae\x86\x20\x3f\xa2\xc0\xe0\x72\x97\x40\x6e\xa8\xc2\x71\x11\xa8\x6d\xbe\x1d\x5a\x7c\x3b\x7a\xe9\x30\x90\x4d\x98\x90\xf6\xd4\xab\xeb\xd1\x41\x2a\x73\xad\x5f\xee\xa6\x4a\xcf\x06\x5d\x3e\x63\xb5\xcb\xe2\x0c\xf2\x0b\xbd\x2d\x8b\x94\xf9\x05\x3e\xd5\xf6\x66\x33\x48\x25\x30\x12\x44\x46\x60\x59\x18\xde\x66\x45\x5e\x8c\xf4\xb1\x01\xa1\x27\x23\x3c\x4e\x27\xd5\xd5\x5b\xf9\x5b\xd3\x19\x5d\x03\x40\xd4\x35\x31\xfc\x75\xfa\xf8\xdd\xed\x52\x75\xbf\x89\x75\x0d\xe8\x38\xfd\x10\xc3\x17\x45\xbe\x4c\xa4\x1f\xa8\x71\xcb\x0f\x9b\x01\x67\x06\xa1\xa7\xe3\xc4\x4b\xb9\x0a\xc7\xa8\xad\x51\xe2\x72\x38\x92\x92\xfd\x6c\x98\xad\x7a\x06\x9e\x76\xe3\xf5\xf3\xe0\xcc\x77\x0b\x9e\x9b\x35\xa7\x65\xd0\xd9\x37\x12\xd7\xcd\xab\xd1\x7e\x5d\x01\xdd\x81\x83\xaf\x4a\xd9\x36\x5d\xb0\xa0\xfa\x41\x38\x1f\xce\x60\xa0\x81\xdf\x1c\x5a\xb0\xf8\xc1\x8f\x95\xa7\xa8\xb5\x82\xdf\xff\x7f\x14\x9e\xa5\x79\xdf\x06\x23\xb3\x3b\x75\x08\xf0\xc6\x63\xf0\x1e\x3a\x2d\xcd\x9d\xfb\xee\x51\xcc\x61\x52\x20\xfd\xaf\xfd\xab\x51\xbd\xae\x42\xcb\x9f\x7f\xa9\xe3\xb7\xc6\x9c\xc8\xad\xa5\xcc\xd6\x42\x52\x9b\xa5\x14\xfd\xc5\x4f\xcf\x27\x20\xb8\xf5\xd0\x8b\x95"}, -{{0x49,0x4e,0xa9,0xbc,0xce,0x26,0x88,0x5b,0x7d,0x17,0xd1,0xfc,0x11,0x44,0x48,0xf2,0x39,0xf0,0xce,0x46,0xe5,0xf2,0x47,0xb4,0xc9,0x99,0xfa,0x86,0x29,0x69,0x24,0x72,},{0x69,0x01,0xe5,0xef,0xae,0x57,0x53,0x6b,0xa5,0xfd,0xd9,0x6b,0x59,0x65,0x73,0x59,0x06,0x5f,0x25,0xd3,0x91,0xa1,0xaa,0x8c,0xdc,0x0d,0x38,0xbb,0x5d,0x53,0xc1,0x39,},{0x54,0x8a,0x09,0x3a,0x68,0x03,0x61,0xb7,0xdc,0x56,0xf1,0x45,0x03,0xb5,0x5e,0xee,0xc3,0xb3,0xf4,0xfd,0x4c,0xa9,0x9d,0x6a,0xed,0xce,0x08,0x30,0xf7,0xf4,0xae,0x2f,0x73,0x28,0x53,0x9b,0x34,0xc4,0x8f,0xc9,0x76,0x09,0x22,0x33,0x3d,0xae,0x9c,0x7c,0x01,0x7e,0x7d,0xb7,0x3b,0x8f,0xaa,0x6c,0x06,0xbe,0x05,0xe3,0x47,0x99,0x2b,0x06,},"\x3b\xad\xbf\xa5\xf5\xa8\xaa\x2c\xce\x0a\x60\xe6\x86\xcd\xce\x65\x4d\x24\x45\x2f\x98\xfd\x54\x87\x2e\x73\x95\xb3\x94\x64\x38\x0a\x0e\x18\x55\x57\xea\x13\x4d\x09\x57\x30\x86\x4f\x42\x54\xd3\xdd\x94\x69\x70\xc1\x0c\x80\x4f\xcc\x08\x99\xdf\xa0\x24\x20\x5b\xe0\xf8\x0b\x1c\x75\x44\x95\x23\x32\x4f\xe6\xa0\x75\x1e\x47\xb4\xff\x48\x22\xb8\xc3\x3e\x9e\xaf\x1d\x1d\x96\xe0\xde\x3d\x4a\xcd\x89\x69\x6b\x7f\xcc\x03\xd4\x9f\x92\xf8\x2b\x97\x25\x70\x0b\x35\x0d\xb1\xa8\x76\x15\x36\x95\x45\x56\x1b\x85\x99\xf5\xea\x92\x0a\x31\x0a\x8b\xaf\xc0\xe8\xd7\x46\x8c\xbf\x6f\x38\x20\xe9\x43\x59\x4a\xfd\xd5\x16\x6e\x4e\x33\x09\xdd\xdd\x76\x94\xef\x67\xe6\x94\xf3\x4f\xc6\x27\x24\xff\x96\xac\x33\x64\x17\x6f\x34\xe8\xa0\x2b\x4c\xf5\x69\xdb\x5b\x8f\x77\xd5\x85\x12\xae\xda\xbf\x0b\xcd\x1c\x2d\xf1\x2d\xb3\xa9\x47\x3f\x94\x8c\x5c\x32\x43\x30\x9a\xae\x46\xc4\x9e\xfd\x08\x8b\x60\xf3\x1a\x8a\x72\xad\x7e\x5a\x35\xac\xc5\xd8\x9f\xa6\x68\x07\xeb\x5d\x3b\xa9\xcd\xf0\x8d\x47\x53\xcb\x85\x08\x9e\xe3\x6f\x5c\x96\xb4\x32\xb6\x92\x83\x52\xaf\xad\x58\x01\x22\x25\xd6\x15\x7f\x9e\x36\x11\x42\x6d\xf9\x21\xb6\xd1\xd8\x37\x46\x28\xa6\x30\x31\xe9\xff\xb9\x0e\x42\xff\xbb\xa0\x21\xf1\x74\xf6\x85\x03\x15\x54\x30\x15\x2c\x91\x55\xdc\x98\xff\xa2\x6c\x4f\xab\x06\x5e\x1f\x8e\x46\x22\xc2\xf2\x8a\x8c\xb0\x43\x11\x0b\x61\x74\x41\x14\x0f\x8e\x20\xad\xc1\x6f\x79\x9d\x1d\x50\x96\xb1\xf5\x05\x32\xbe\x50\x42\xd2\x1b\x81\xea\x46\xc7"}, -{{0x00,0xd7,0x35,0xeb,0xae,0xe7,0x5d,0xd5,0x79,0xa4,0x0d,0xfd,0x82,0x50,0x82,0x74,0xd0,0x1a,0x15,0x72,0xdf,0x99,0xb8,0x11,0xd5,0xb0,0x11,0x90,0xd8,0x21,0x92,0xe4,},{0xba,0x02,0x51,0x7c,0x0f,0xdd,0x3e,0x26,0x14,0xb3,0xf7,0xbf,0x99,0xed,0x9b,0x49,0x2b,0x80,0xed,0xf0,0x49,0x5d,0x23,0x0f,0x88,0x17,0x30,0xea,0x45,0xbc,0x17,0xc4,},{0xdc,0xdc,0x54,0x61,0x19,0x37,0xd2,0xbd,0x06,0xca,0xcd,0x98,0x18,0xb3,0xbe,0x15,0xce,0x74,0x25,0x42,0x7a,0x75,0xf5,0x0d,0x19,0x7a,0x33,0x7a,0x3b,0x8b,0xa6,0x71,0x4e,0xf4,0x88,0x66,0xf2,0x43,0xbd,0x5a,0xc7,0x41,0x5e,0x91,0x45,0x17,0xa2,0xc1,0xc5,0xa9,0x53,0xf4,0x32,0xb9,0x9d,0xb0,0xe6,0x20,0xd6,0x4f,0x74,0xeb,0x85,0x05,},"\x59\xc0\xb6\x9a\xf9\x5d\x07\x4c\x88\xfd\xc8\xf0\x63\xbf\xdc\x31\xb5\xf4\xa9\xbc\x9c\xec\xdf\xfa\x81\x28\xe0\x1e\x7c\x19\x37\xdd\xe5\xeb\x05\x70\xb5\x1b\x7b\x5d\x0a\x67\xa3\x55\x5b\x4c\xdc\xe2\xbc\xa7\xa3\x1a\x4f\xe8\xe1\xd0\x3a\xb3\x2b\x40\x35\xe6\xda\xdb\xf1\x53\x20\x59\xee\x01\xd3\xd9\xa7\x63\x3a\x0e\x70\x6a\x11\x54\xca\xb2\x2a\x07\xcd\x74\xc0\x6a\x3c\xb6\x01\x24\x4c\xf3\xcf\x35\xa3\x5c\x31\x00\xba\x47\xf3\x13\x72\xa2\xda\x65\xdc\xff\x0d\x7a\x80\xa1\x05\x5d\x8a\xa9\x92\x12\xe8\x99\xaa\xd7\xf0\x2e\x94\x9e\x6f\xee\x4d\x3c\x9c\xef\xa8\x50\x69\xea\xff\x1f\x6a\xd0\x6f\xc3\x00\xc8\x71\xab\x82\xb2\xbe\xdb\x93\x4d\x20\x87\x5c\x2a\x26\x32\x42\xcd\xb7\xf9\xbe\x19\x2a\x87\x10\xb2\x4c\x7e\xa9\x8d\x43\xda\xec\x8b\xaa\x55\x53\xc6\x78\xa3\x8f\x0e\x0a\xdf\x7d\x3f\xf2\xdc\xc7\x99\xa1\xdb\xad\x6e\xab\x1c\x3d\x94\x58\xa9\xdb\x92\x2f\x02\xe7\x5c\xfa\xb9\xd6\x5c\x73\x36\xda\xe7\x18\x95\xd5\xbb\x15\xca\xc2\x03\xf2\xb3\x8b\x99\x96\xc4\x10\xf8\x65\x5a\xd2\x2d\x3c\x09\x1c\x20\xb7\xf9\x26\xd4\x5e\x78\x01\x28\xf1\x97\x47\x46\x2a\xbc\x5c\x58\x93\x2f\xbb\x9e\x0b\xc6\x2d\x53\x86\x88\x02\xf1\xb0\x83\xf1\x83\xb8\xa1\xf9\x43\x49\x86\xd5\xcf\x97\xc0\x4e\x2f\x3e\x14\x57\x30\xcb\xa9\x87\x79\xc7\xfe\xd0\xca\xb1\xc0\x5d\x5e\x46\x53\xc6\xc3\xf6\x73\x62\x60\xbc\x78\xee\x43\x72\x86\x2f\xfe\x9e\x90\x37\x1d\x76\x2c\x74\x32\x78\x1f\x35\xce\xd8\x84\xa4\xba\xca\x05\x65\x3e\xf2\x5f\x25\xa6\xf3\xd5\x62\x83\x08"}, -{{0x8c,0x34,0xb9,0x05,0x44,0x0b,0x61,0x91,0x1d,0x1d,0x81,0x37,0xc5,0x3d,0x46,0xa1,0xa7,0x6d,0x46,0x09,0xaf,0x97,0x3e,0x18,0xeb,0x4c,0x57,0x09,0x29,0x56,0x27,0xbb,},{0xb6,0x9a,0x8b,0x2f,0xdf,0x5c,0x20,0xe7,0x34,0xc2,0xff,0xb2,0x94,0xbc,0x8a,0xe1,0x01,0x1d,0x66,0x4f,0x11,0xaf,0xe7,0xfb,0xc4,0x71,0x92,0x5c,0xf7,0x2f,0xa9,0x9d,},{0x3e,0x0b,0x72,0x07,0x3d,0xc9,0x37,0x5e,0xed,0xcc,0xa6,0xc4,0xfc,0x1c,0xd3,0x15,0x93,0x8a,0x05,0x0c,0x92,0x71,0x6b,0xd2,0x28,0x4f,0x46,0x29,0xa9,0x62,0xbe,0xec,0x0b,0x7d,0x7c,0xf1,0x6a,0xb9,0x23,0xd5,0x8f,0x5b,0x90,0xd3,0x90,0x1a,0x8e,0x5c,0x75,0xc8,0xf1,0x7d,0xab,0x99,0x98,0xe0,0x07,0xd8,0xc4,0x95,0x11,0x97,0x3d,0x0e,},"\x30\xb5\x7a\x38\x9b\x48\xa0\xbe\xb1\xa4\x84\x32\xbf\xf6\xb3\x14\xbd\xed\x79\xc4\xa1\x76\x3a\x5a\xcb\x57\xce\xa1\xbf\xb4\xc6\xd0\x16\xcf\x09\x0f\x5b\xd0\x5b\xbd\x11\x4e\x33\xae\x7c\x17\x78\x2d\xfa\x26\x4f\x46\xc4\x5f\x8c\x59\x9c\x60\x30\x16\xfe\x9f\xf0\x5b\x6b\x5a\x99\xe9\x2f\xe7\x13\xa4\xcd\x5c\x41\xb2\x92\xed\x2b\xb2\xe9\xcf\x33\xa4\x40\x54\x2e\x82\x1e\xc8\x2c\xbf\x66\x5c\x3f\x02\xe3\xdc\x33\x7d\x7f\xdb\x58\xe3\x1b\x27\xcb\x29\x54\x54\x14\x68\x81\x46\x98\x51\x0d\xf1\x8c\x85\xc8\x1f\xad\x12\xdb\x11\xec\x6b\x96\x6f\x49\x30\xda\x56\x46\xb9\x91\xdb\x97\x44\x50\x97\xda\x30\xda\xb6\x1c\xda\x53\xa4\x10\x83\xcb\x96\xad\xd1\x9d\xe6\xc5\xee\xc3\x23\xbc\xa9\xd3\x53\x0e\x38\xc0\x0b\x35\xaf\x73\x60\x07\x76\x01\xbe\x6a\xc9\x7f\x30\x30\xf9\x30\xa2\x7b\x90\xfe\x8b\x69\x11\xba\xe3\x89\x06\x5a\xdc\x15\xe1\x88\x23\x00\xe2\xa0\x03\x27\x4d\x23\x18\x2d\x5e\xfd\x5b\xa4\xb9\x13\x0c\x07\xbd\x5c\x65\xfe\xcb\x8b\x5c\xb7\xeb\x38\x83\x6b\x31\x8b\xef\xdf\xd7\x7d\xe4\xd6\xca\x01\x81\xf7\x7a\xe5\x74\x08\x91\x68\x32\x25\xf5\x49\xdd\x84\x26\x14\x5c\x97\xc5\x81\x8c\x31\x9f\x7a\xb2\xd8\x68\xe1\xa4\x1c\xea\xb6\x4c\x08\x51\x16\x06\x98\x97\xbf\x2c\xa3\x66\x76\x52\x40\x61\x55\xed\x06\x46\x43\x1b\x6d\xe1\xcc\xc0\x3b\x42\x79\xae\x4d\x32\x66\x79\x26\x5d\xce\x82\x04\x8e\x72\x98\xe1\xf8\x7f\xce\xc0\x76\x8a\xc0\xf5\xd8\xff\x84\xf7\x21\x0b\xe5\x4d\x41\x1a\xf8\xed\xea\x72\x17\xf4\xe5\x94\x13\x12\x1e\x14\x8c\x60\xda"}, -{{0x77,0xa8,0x3e,0x18,0xc9,0xf0,0x00,0xee,0xff,0x7d,0xee,0xac,0x95,0x9e,0xcb,0xa2,0x20,0x6c,0x0a,0xa3,0x9d,0x2f,0x0e,0x2a,0xed,0x57,0x29,0x48,0x2a,0x7a,0x02,0x29,},{0x62,0xb1,0xb3,0x16,0x13,0x55,0x96,0xbf,0xbc,0xa6,0x03,0x7e,0xd8,0x47,0xc6,0x1f,0xb7,0xf0,0x9f,0xa3,0x6c,0xe9,0x0a,0xbb,0x77,0x89,0xb8,0x6f,0x76,0x8b,0x59,0xdd,},{0x1e,0xaa,0xd8,0x42,0x0a,0xc1,0x2c,0x99,0xac,0x1f,0xf4,0x47,0x66,0x78,0xe3,0xcb,0xbe,0x94,0xda,0x6a,0x79,0x7f,0x17,0x46,0x64,0xd5,0xee,0x0f,0x64,0x14,0x33,0xfb,0x1e,0x7c,0xb2,0xf5,0x61,0x3e,0x10,0x80,0x5d,0xf8,0x65,0x4c,0xd8,0xe0,0xd4,0x5d,0x96,0x23,0x09,0x32,0xbc,0x7f,0x20,0xb0,0x4e,0xae,0x83,0x64,0x35,0x13,0x43,0x09,},"\xf3\xd5\xfa\x2a\xca\xef\xd8\x58\xf1\xdf\x26\xe0\x30\x59\xcd\xcb\xc2\x46\x8a\xd7\x4a\xfc\x99\x3d\x0d\xb9\xc4\xcd\xe4\x11\x3f\x8d\x55\xc7\xda\x71\xd3\x8b\xa0\x65\x20\x53\x1c\x61\xfd\xdb\x5f\x33\xd5\xf0\x35\x3b\xe2\x37\x6e\x58\x07\x11\xbe\x45\xc0\xa3\x0b\x1f\xa0\x1b\x55\xe2\x28\xc6\xfa\x35\xe3\xf9\x5b\x67\x90\x9f\xc7\xdf\x3f\xd4\x64\xd9\x3d\x66\x1a\x92\x6f\x9d\x11\xf7\x55\x0c\x17\xfb\xcc\x34\x96\x52\x6e\x8f\x10\xe0\xc8\x91\x66\x77\xb2\xbe\x5b\x31\x9b\x68\x8f\x21\xe8\x1a\xaa\x94\x82\xe5\xc9\x3e\x64\xce\x8c\x43\x7b\x9c\x1e\x14\xfe\xfe\xd7\x0a\x3f\xee\x56\x88\x11\xdc\x31\xca\xda\xb3\xd5\xb2\x20\x25\x44\x65\x33\x6d\xc4\xd9\x7a\x3b\xd0\x96\xb5\xe0\x65\xe0\xcf\xbe\x82\x84\x9e\x2c\x19\x05\xac\xa4\x86\x53\x3f\x0d\xa7\xa6\x1f\x1e\x9a\x55\xb8\xe2\xa8\x32\x62\xde\xeb\x59\xf2\xb1\x3d\x3a\x8a\xef\x57\x00\x84\x5b\x83\xb2\x5a\xe2\x18\x3c\x0d\xda\xc0\xce\x42\xf8\xd2\x56\x74\xcb\x0d\x0d\x22\x0a\x6d\xe7\xc1\x85\x8b\xb0\x7d\x59\xa3\x37\x23\x44\xd9\x44\x60\x2a\xa4\x51\xd2\xb9\x37\xdb\x0f\xe6\xfe\xca\x0b\xeb\xa8\x17\x21\xfc\x36\x1e\xa7\x50\x9e\x2b\x6d\x39\x7e\x1c\x19\x1b\x56\xf5\x4a\xb4\x36\xd0\xd2\x7a\xb4\xc0\x61\xbd\x66\x1a\xd1\xa4\x45\x23\x87\xe8\x73\x57\x54\xd0\x7f\xa7\xef\x4d\x45\x48\xb1\x72\x58\x24\x25\xb2\x99\x04\x6e\x63\x01\xb5\xba\x6b\x91\x44\x18\xf1\x49\xcf\x72\x2e\x10\xbd\xe2\xe0\xd4\x17\x00\xf1\x2c\x84\x29\xfc\x89\x7b\x78\x19\xda\x92\x29\x22\x40\xcd\x45\x56\x54\x58\xc9\xa7\xb2\x9c\x12"}, -{{0x73,0xb0,0x33,0x73,0xef,0x1f,0xd8,0x49,0x00,0x5e,0xcd,0x62,0x70,0xdd,0x99,0x06,0xf1,0x9f,0x44,0x39,0xe4,0x03,0x76,0xcd,0xbc,0x52,0x09,0x02,0xbc,0x97,0x68,0x12,},{0x66,0x37,0x19,0xe0,0x8b,0xa3,0xba,0x16,0x66,0xf6,0x06,0x9a,0x3f,0x54,0x99,0x18,0x66,0xb1,0x8c,0xc6,0xbe,0x41,0x99,0x1b,0x02,0xeb,0x30,0x26,0xff,0x9e,0x15,0x5f,},{0xa4,0x0a,0xbe,0x98,0xfc,0x69,0xda,0x8a,0x1f,0xf9,0xff,0x5c,0x2c,0xca,0x93,0x63,0x2e,0x97,0x59,0x80,0xee,0x8b,0x82,0xc3,0xc3,0x76,0x02,0x2d,0x65,0x24,0xab,0x73,0x6d,0x01,0xb0,0x72,0xf2,0xb6,0x81,0xb5,0xf1,0xcd,0x3e,0xa0,0x67,0x01,0x2e,0xd6,0xd0,0x74,0xe9,0x49,0xc4,0x23,0x27,0xa3,0x66,0xca,0xa9,0xe4,0x75,0x0a,0x3c,0x08,},"\xd5\xc2\xde\xab\xa7\x95\xc3\x0a\xba\x32\x1b\xc7\xde\x69\x96\xf0\xd9\x0e\x4d\x05\xc7\x47\xfb\x4d\xae\x8f\x34\x51\x89\x5d\xef\x6e\x16\xe7\x2f\x38\xea\xce\x75\x6f\x36\x63\x5f\x8f\xb0\xb7\x2a\x3a\x0c\x1f\x54\x66\x38\x17\xa9\x4d\x4f\xd3\x46\xf8\x35\xab\x0e\x65\x7f\x00\x1a\x6f\x2c\xec\xb8\x6d\x08\x25\xbd\x02\x63\x92\x54\xf7\xf7\xf3\x8c\xa9\x9d\xbb\x86\xc6\x4a\x63\x3f\x73\xba\xf9\x33\xaa\xe3\x56\x32\x81\xf4\x00\x5e\x2d\x0e\x7c\xec\x9f\xbd\xe8\xe5\x88\xa9\x57\xe2\x11\x06\x8b\xe6\x5b\x3d\x3d\x35\xbf\x4e\x8d\x5b\xb3\x47\x83\x33\xdf\x9c\xed\x9b\x2a\xba\xf4\x86\x97\x99\x4a\x14\x5e\x93\x21\x49\x9f\xc5\xee\x56\x0f\x4f\xbb\x68\x49\xe1\xae\x8e\xb3\xd1\xde\x00\x83\xa2\x1a\x03\xf6\xa6\xb2\x81\x76\xf0\x13\x0d\x38\x95\xe5\x0e\x75\xe3\xd7\xd0\x94\x7a\x7b\xc2\xc5\xb9\xff\x69\x89\x5d\x27\x79\x14\x42\xba\x8d\x0f\x21\x80\x71\x2b\x56\x7f\x71\x2e\xa9\x12\xf3\xb0\xd9\x2c\x19\x34\x2e\x01\x06\xff\x1d\x87\xb4\x6a\xd3\x3a\xf3\x00\xb9\x08\x55\xba\x97\x69\xd3\x66\xe7\x94\x25\xd9\x8e\x4d\xe1\x99\x05\xa0\x45\x77\x70\x7c\xbe\x62\x5b\x84\x69\x17\x81\xcd\x26\xbf\x62\x26\x0b\x4a\x8b\xd6\x05\xf7\x7a\xf6\xf9\x70\xe1\xb3\xa1\x12\xe8\x91\x83\x44\xbd\x0d\x8d\x2e\x41\xdf\xd2\xce\x98\x95\xb0\x24\x6e\x50\x88\x7a\xa3\xa5\x77\xff\x73\xbe\x4b\x6a\xe6\x0f\xeb\x0c\xa3\x6f\x6a\x5f\x81\x71\xed\x20\x9e\x5c\x56\x65\x29\xc0\x94\x0d\x9b\x4b\xd7\x44\xcc\xee\x56\xe5\x4a\x9a\x0c\x6e\x4d\xa5\x20\xdd\x31\x5c\x28\x72\xb0\x2d\xb5\x63\x70\x3e"}, -{{0xea,0xb1,0x79,0xe4,0x1e,0xd5,0xc8,0x89,0xff,0xe6,0xaa,0xbd,0xc0,0x54,0xfa,0xf1,0x30,0x7c,0x39,0x5e,0x46,0xe3,0x13,0xe1,0x7a,0x14,0xfe,0x01,0x02,0x3f,0xfa,0x30,},{0x86,0xf3,0x47,0x46,0xd3,0xf7,0xa0,0x1d,0xdb,0xe3,0x22,0xf1,0xac,0xa5,0x6d,0x22,0x85,0x6d,0x38,0x73,0x3a,0x3a,0x69,0x00,0xbb,0x08,0xe7,0x76,0x45,0x0e,0xc8,0x03,},{0x14,0x3c,0xb2,0x80,0x27,0xc2,0xf8,0x2e,0x37,0x5e,0x5f,0x34,0x0e,0x7f,0xe6,0xe6,0x0c,0xe7,0xbd,0x51,0x00,0x0b,0x49,0xc7,0x41,0x68,0xaf,0x85,0xe2,0x6e,0xd2,0xed,0x63,0x0e,0xd2,0x67,0x20,0x90,0x16,0x4c,0xc5,0x4b,0x05,0x2d,0xa6,0x94,0xeb,0xdd,0x21,0xa2,0x1b,0x30,0x53,0xf4,0xdc,0xfd,0x78,0x95,0xea,0x5f,0x6c,0x8a,0xa8,0x0d,},"\x97\x10\x95\xce\xbe\x50\x31\x53\x02\x24\x38\x7c\x5c\x31\x96\x6e\x38\x9b\x85\x66\x39\x00\x54\xcf\x45\x26\x4b\x44\xe1\x89\x64\xb7\xbe\x52\xc3\x3c\x4f\xfb\x25\x9a\xf1\x62\x83\x43\x8f\xa1\x5d\xd6\x6b\xc7\x79\x1b\x75\x33\xef\x10\xcb\x0b\xea\xb5\x24\xa6\x43\x76\x26\xf4\xcc\x74\x51\x28\x51\xad\xcc\x2f\xb1\x29\x05\x5a\x48\x2c\x61\x10\x73\x83\xfb\x7c\x52\x41\x83\x1d\x55\x51\x63\x4e\xef\x0d\xc0\xb8\xf9\x05\x3a\x00\x97\x1a\xa8\xfa\x1a\xe0\x89\x8e\x4b\x48\x1b\x67\x07\xe9\x7c\x0f\x94\x20\x40\xb3\x39\xd9\x2f\xc1\x7b\xba\xde\x74\x67\x5a\xf2\x43\xd8\xb2\xda\xfb\x15\xb1\xdb\x55\xd1\x24\x15\xb8\x5f\x30\x37\x29\x19\x30\xab\x61\x60\x0b\xa3\x43\x1f\x8e\xb4\x25\xbe\x44\x91\x61\x47\x28\xaf\x10\x1e\x81\xc0\x91\xf3\x48\xbc\x5f\xfd\x1b\xde\x6a\xe6\xca\xd5\xc1\x5b\x3a\xa7\x35\x80\x78\xcc\x4e\xff\xb5\x4a\x86\xe7\xf0\xe0\xc5\x5e\x4c\xfe\x0a\x54\x60\x5e\xd4\x43\xfd\xf2\xaa\xba\x01\x65\x85\xda\x61\x7e\x77\x34\x1d\x52\x88\x9d\x75\xdd\x54\x0d\x39\xfe\x8b\x79\x93\xed\x70\x5c\xfd\xde\xa0\xcb\x0d\x5a\x73\x1d\x6b\xfc\xdb\x81\x6a\xfa\xff\x47\xe9\x63\xee\xde\xbd\xf2\x41\xaf\x55\x93\x35\x3d\x6d\x40\x1a\x34\xf0\x29\xa8\xcd\xeb\x19\x04\xcc\x2c\xaa\x4f\x96\x35\xcc\x2b\xa6\xb7\xb1\xa2\x9d\xa6\x25\xff\xc3\x83\xbe\x2f\x5a\x8f\x1f\xa4\xf3\x9b\x2d\x4b\x4f\x4c\x2d\x88\x38\xce\x25\x8a\x04\xd4\xa1\x20\x49\x3f\xdf\x07\xf6\x8c\x0f\xfd\x1c\x16\xb7\x68\xa3\x5c\x55\xfe\xa2\xca\xc6\x96\xb5\xc2\x0e\xfc\x10\x86\x5c\xde\x8a\x64\x62\x7d\xcd"}, -{{0xfb,0xf1,0x46,0xeb,0xd5,0x10,0x75,0x57,0x0e,0xc5,0x1a,0xc4,0x10,0xae,0x9f,0x39,0x1d,0xb7,0x5b,0x61,0x0a,0xda,0x63,0x62,0xb4,0xdb,0xd9,0x49,0x65,0x6c,0xfb,0x66,},{0xbe,0x7c,0x2f,0x5b,0x21,0xd7,0x46,0xc8,0xea,0x32,0x45,0xce,0x6f,0x26,0x8e,0x9d,0xa7,0x4e,0x00,0xfa,0x85,0xc9,0xc4,0x75,0x26,0x0c,0x68,0xfa,0x1a,0xf6,0x36,0x1f,},{0x67,0x68,0x00,0x6f,0xe0,0xf2,0x01,0xb2,0x17,0xdd,0x10,0xeb,0x05,0xd4,0xb8,0x2a,0xdc,0xfe,0xb2,0xec,0xfc,0x83,0x73,0xc3,0x30,0x8f,0x41,0x50,0x39,0x48,0x11,0xeb,0x60,0x49,0x18,0x81,0xa2,0xe5,0x3d,0x12,0x89,0xd9,0x64,0x78,0xe1,0x8a,0x64,0xc3,0x4b,0x2a,0x19,0x83,0x2c,0xdc,0xcf,0xd9,0x6a,0x2e,0x4a,0x0c,0x46,0x9f,0xdc,0x0b,},"\xcd\x7a\xd4\xf1\x7f\xcf\xf7\x3a\xcc\x40\x2d\xc1\x02\xd0\x90\x79\xb2\x9a\xaf\x2a\x0f\x4b\x27\xcf\x6b\xee\xb1\xe2\xb2\x3d\x19\xab\x47\xde\xb3\xae\x1b\xec\xd6\x88\x61\xea\x27\x9c\x46\x69\x17\x38\xf4\xff\xf4\x7c\x43\x04\x7c\x4f\x8b\x56\xb6\xbb\xcc\x3f\xde\x07\x23\xd4\x41\x20\xdc\xd3\x07\xa6\x31\x0d\xc4\xf3\x66\xb8\xf3\xcd\x52\xdb\x19\xb8\x26\x6a\x48\x7f\x78\x72\x39\x1c\x45\xfe\x0d\x32\x48\xa7\xab\xf2\xc2\x00\x22\xd3\x76\x95\x47\xf6\x83\x06\x7d\xcc\x36\x3c\xd2\x2f\xd7\xcd\xa3\xca\xdc\x15\x80\x40\x56\xf0\xe2\xaa\x2b\x79\x50\x08\xc5\x98\xbe\x7a\x96\x18\x05\xe6\xdf\x29\x1b\xa3\x04\x1c\x47\xff\x56\x40\x27\x5f\x46\xe6\xae\x82\x09\x2d\x21\xab\xcb\xcf\xba\x11\xe7\x30\x21\x60\x08\x82\x2d\xe3\xce\x46\x24\x00\x59\x6d\xa7\x9f\x7a\xe5\xd1\xdf\x83\x89\x11\x2a\xd9\x88\x68\xfa\x94\xfb\x05\x46\xbf\xe6\xa6\x7a\xa8\xd2\x8c\x4d\x32\x07\x2d\x2e\xad\xd6\x25\x62\x55\xf1\x8c\x23\x82\xe6\x62\xdf\xa9\x22\xa6\x80\xe0\x6a\x43\x62\x2c\x48\x71\xd2\x7d\x18\x07\xf7\xb2\x70\x30\x70\xc8\x3d\xb8\xdd\x92\x9c\x06\x03\x8b\x21\x83\xcb\x8e\x2b\x9e\xc4\xc7\x78\xd7\xec\xf9\xe9\xff\xac\x77\xfa\x77\x37\xb0\x55\xfe\xac\x2e\x79\x82\xae\xee\xc0\xb7\x2f\x1b\xbc\xa2\x42\x4e\x1a\x84\x4b\xba\xc7\x9c\xb2\xe7\x40\x0f\x81\xdc\x44\x9d\x05\x60\xb5\x21\xa7\xc1\x6b\xb4\x16\x7e\x66\x96\x58\x60\x58\xa9\xb8\xed\x2e\x51\x16\x69\x0b\x77\xf2\xa1\x7e\x5c\x0b\x16\xa8\x3d\xcb\xd2\xe2\x45\x52\x29\x3e\x25\x8b\x32\xba\x7f\x84\x49\x44\x37\x93\x42\x69\x86\x27"}, -{{0xdf,0xf0,0xeb,0x6b,0x42,0x6d,0xea,0x2f,0xd3,0x3c,0x1d,0x3f,0xc2,0x4d,0xf9,0xb3,0x1b,0x48,0x6f,0xac,0xb7,0xed,0xb8,0x50,0x29,0x54,0xa3,0xe8,0xda,0x99,0xd9,0xfd,},{0xc2,0x45,0x08,0x5e,0xce,0x69,0xfb,0x9a,0xa5,0x60,0xd0,0xc2,0x7f,0xdb,0x63,0x4f,0x7a,0x84,0x0d,0x41,0xd8,0x46,0x36,0x60,0xfb,0xe8,0x24,0x83,0xb0,0xf3,0xcc,0x3a,},{0x6b,0x48,0xb1,0x0f,0x54,0x5d,0xdb,0x7a,0x89,0xcd,0x58,0x29,0xf4,0xe5,0xb2,0x01,0x46,0xcf,0x6b,0xc9,0x6e,0x55,0x0d,0x06,0xf6,0x5d,0xe8,0xbd,0xae,0x7c,0xcd,0xde,0xd2,0x6c,0xd6,0x30,0xf8,0x6c,0x92,0x66,0xbc,0xcf,0x88,0xe9,0x24,0x03,0x3e,0x04,0xf8,0x3a,0x54,0xf8,0x29,0x0d,0x7f,0x73,0x4c,0xf8,0x67,0x3c,0xca,0x8f,0x97,0x03,},"\xe7\xc9\xe3\x13\xd8\x61\x60\xf4\xc7\x4a\xa0\xae\x07\x36\x9e\xe2\x2b\x27\xf8\x1b\x3f\x69\x09\x7a\xff\xae\x28\xda\xe4\x84\x83\xfb\x52\xa5\xc0\x62\x30\x6b\x59\x61\x0f\x5c\xdb\xff\x63\x32\xb1\x96\x0c\xd6\xf2\xb8\xf7\xb4\x15\x78\xc2\x0f\x0b\xc9\x63\x7a\x0f\xdf\xc7\x39\xd6\x1f\x69\x9a\x57\x3f\x1c\x1a\x0b\x49\x29\x45\x06\xcf\x44\x87\x96\x5e\x5b\xb0\x7b\xbf\x81\x80\x3c\xb3\xd5\xcb\x38\x29\xc6\x6c\x4b\xee\x7f\xc8\x00\xed\xe2\x16\x15\x09\x34\xd2\x77\xde\xa5\x0e\xdb\x09\x7b\x99\x2f\x11\xbb\x66\x9f\xdf\x14\x0b\xf6\xae\x9f\xec\x46\xc3\xea\x32\xf8\x88\xfd\xe9\xd1\x54\xea\x84\xf0\x1c\x51\x26\x5a\x7d\x3f\xef\x6e\xef\xc1\xcc\xdb\xff\xd1\xe2\xc8\x97\xf0\x55\x46\xa3\xb1\xca\x11\xd9\x51\x7c\xd6\x67\xc6\x60\xec\x39\x60\xf7\xa8\xe5\xe8\x02\x02\xa7\x8d\x3a\x38\x8b\x92\xf5\xc1\xde\xe1\x4a\xe6\xac\xf8\xe1\x7c\x84\x1c\x95\x57\xc3\x5a\x2e\xec\xed\x6e\x6a\xf6\x37\x21\x48\xe4\x83\xcc\xd0\x6c\x8f\xe3\x44\x92\x4e\x10\x19\xfb\x91\xcb\xf7\x94\x1b\x9a\x17\x6a\x07\x34\x15\x86\x72\x10\x67\x04\x10\xc5\xdb\xd0\xac\x4a\x50\xe6\xc0\xa5\x09\xdd\xfd\xc5\x55\xf6\x0d\x69\x6d\x41\xc7\x7d\xb8\xe6\xc8\x4d\x51\x81\xf8\x72\x75\x5e\x64\xa7\x21\xb0\x61\xfc\xd6\x8c\x46\x3d\xb4\xd3\x2c\x9e\x01\xea\x50\x12\x67\xde\x22\x87\x9d\x7f\xc1\x2c\x8c\xa0\x37\x9e\xdb\x45\xab\xaa\x6e\x64\xdd\xa2\xaf\x6d\x40\xcc\xf2\x4f\xbe\xba\xd7\xb5\xa8\xd3\xe5\x20\x07\x94\x5e\xcd\x3d\xdc\x1e\x3e\xfe\xb5\x22\x58\x1a\xc8\x0e\x98\xc8\x63\xba\x0c\x59\x0a\x3e\xd9\x5c\xd1"}, -{{0x9f,0x32,0x95,0x8c,0x76,0x79,0xb9,0x0f,0xd5,0x03,0x60,0x56,0xa7,0x5e,0xc2,0xeb,0x2f,0x56,0xec,0x1e,0xff,0xc7,0xc0,0x12,0x46,0x1d,0xc8,0x9a,0x3a,0x16,0x74,0x20,},{0x1d,0x72,0x69,0xdc,0xb6,0xd1,0xf5,0x84,0xe6,0x62,0xd4,0xce,0x25,0x1d,0xe0,0xab,0xa2,0x90,0xef,0x78,0xb9,0x7d,0x44,0x8a,0xfb,0x1e,0x53,0x33,0xf1,0x97,0x6d,0x26,},{0x98,0x81,0xa5,0x76,0x3b,0xdb,0x25,0x9a,0x3f,0xef,0xbb,0xa3,0xd9,0x57,0x16,0x2d,0x6c,0x70,0xb8,0x04,0xfa,0x94,0xab,0x61,0x34,0x06,0xa6,0xec,0x42,0x50,0x5b,0x87,0x89,0x46,0x5c,0xa1,0xa9,0xa3,0x3e,0x18,0x95,0x98,0x88,0x42,0x27,0x0c,0x55,0xe5,0xbd,0xd5,0x48,0x3f,0x6b,0x17,0xb3,0x17,0x81,0xb5,0x93,0x50,0x7a,0x6c,0x18,0x08,},"\xa5\x6b\xa8\x6c\x71\x36\x05\x04\x08\x7e\x74\x5c\x41\x62\x70\x92\xad\x6b\x49\xa7\x1e\x9d\xaa\x56\x40\xe1\x04\x4b\xf0\x4d\x4f\x07\x1a\xd7\x28\x77\x9e\x95\xd1\xe2\x46\x05\x84\xe6\xf0\x77\x35\x45\xda\x82\xd4\x81\x4c\x91\x89\xa1\x20\xf1\x2f\x3e\x38\x19\x81\x3e\x5b\x24\x0d\x0f\x26\x43\x6f\x70\xee\x35\x3b\x4d\x20\xce\xa5\x4a\x14\x60\xb5\xb8\xf1\x00\x8d\x6f\x95\xf3\xaa\x2d\x8f\x1e\x90\x8f\xce\xd5\x0d\x62\x4e\x3a\x09\x69\x38\xb9\x35\x38\x54\xb9\x6d\xa4\x63\xa2\x79\x8a\x5a\x31\x2e\xc7\x90\x84\x2c\x10\xc4\x46\xe3\x35\x0c\x76\x4b\xf5\xc9\x72\x59\x3b\x99\x87\xbf\x23\x25\x6d\xaa\x88\x94\xd4\x7f\x22\xe8\x5b\x97\x60\x7e\x66\xfc\x08\xa1\x2c\x78\x9c\x47\x46\x08\x03\x68\xd3\x21\xbb\x90\x15\xa1\x15\x5b\x65\x52\x3a\xd8\xe9\x9b\xb9\x89\xb4\x4e\xac\x75\x6b\x07\x34\xac\xd7\xc6\x35\x7c\x70\xb5\x97\x43\x24\x6d\x16\x52\xd9\x1b\x0f\x98\x96\x96\x51\x41\x34\x5b\x99\x45\xcf\x34\x98\x04\x52\xf3\x50\x29\x74\xed\xb7\x6b\x9c\x78\x5f\xb0\xf4\x39\x52\x66\xb0\x55\xf3\xb5\xdb\x8a\xab\x68\xe9\xd7\x10\x2a\x1c\xd9\xee\x3d\x14\x25\x04\xf0\xe8\x8b\x28\x2e\x60\x3a\x73\x8e\x05\x1d\x98\xde\x05\xd1\xfc\xc6\x5b\x5f\x7e\x99\xc4\x11\x1c\xc0\xae\xc4\x89\xab\xd0\xec\xad\x31\x1b\xfc\x13\xe7\xd1\x65\x3b\x9c\x31\xe8\x1c\x99\x80\x37\xf9\x59\xd5\xcd\x98\x08\x35\xaa\x0e\x0b\x09\xbc\xbe\xd6\x34\x39\x11\x51\xda\x02\xbc\x01\xa3\x6c\x9a\x58\x00\xaf\xb9\x84\x16\x3a\x7b\xb8\x15\xed\xbc\x02\x26\xed\xa0\x59\x5c\x72\x4c\xa9\xb3\xf8\xa7\x11\x78\xf0\xd2\x0a\x5a"}, -{{0xf8,0x6d,0x6f,0x76,0x6f,0x88,0xb0,0x07,0x17,0xb7,0xd6,0x32,0x7e,0xb2,0x6c,0xf3,0xce,0xeb,0xa5,0x38,0x51,0x84,0x42,0x6f,0x9c,0xfd,0x82,0x95,0xe2,0x42,0x1f,0xf2,},{0xcb,0x1d,0x25,0x05,0x04,0x75,0x41,0x83,0x70,0x4d,0xbe,0x21,0xc3,0x23,0xd6,0x6f,0x9f,0x90,0x11,0x75,0x8f,0x6d,0x8d,0xab,0x6f,0x59,0x7b,0x19,0x96,0x62,0x14,0x5b,},{0xec,0x61,0xc0,0xb2,0x92,0x20,0x3a,0x8f,0x1d,0x87,0x23,0x5e,0xde,0x92,0xb7,0x47,0x23,0xc8,0xd2,0x34,0x08,0x42,0x37,0x73,0xae,0x50,0xb1,0xe9,0xbc,0x44,0x64,0xe0,0x3e,0x44,0x6d,0xa9,0xdc,0xe4,0xc3,0x9f,0x6d,0xd1,0x59,0xbe,0xa2,0x6c,0x00,0x9e,0xd0,0x01,0x20,0xbc,0x36,0xd4,0xa2,0x47,0xdc,0x0d,0x24,0xbc,0xef,0xcc,0x11,0x0c,},"\xda\x84\x23\xa6\xb7\xa1\x8f\x20\xaa\x1f\x90\xed\x23\x31\xb1\x7b\x24\x06\x7c\x40\x17\x5b\xc2\x5d\x81\x09\xe2\x1d\x87\xac\x00\x52\x8e\xb3\xb2\xf6\x6a\x2b\x52\xdc\x7e\xf2\xf8\xce\xcb\x75\xc7\x60\x99\xcf\xa2\x3d\xb8\xda\x89\x70\x43\xba\x1c\xce\x31\xe2\xdf\xea\x46\x07\x5f\x5e\x07\x32\x03\xea\xeb\x3d\x62\xc8\x4c\x10\x7b\x6d\xab\x33\xa1\x4e\xaf\x14\x9a\xa6\x18\x50\xc1\x5f\x5a\x58\xd8\x8a\x15\xab\xa9\x19\x6f\x9e\x49\x5e\x8d\xbe\xcb\xcf\x7e\x84\x44\xf5\xdd\x72\xa0\x8a\x09\x9d\x7f\x62\x09\x99\x0b\x56\x29\x74\xea\x82\x9e\xf1\x1d\x29\xa9\x20\xe3\xa7\x99\xd0\xd9\x2c\xb5\x0d\x50\xf8\x17\x63\x1a\xb0\x9d\xe9\x7c\x31\xe9\xa0\x5f\x4d\x78\xd6\x49\xfc\xd9\x3a\x83\x75\x20\x78\xab\x3b\xb0\xe1\x6c\x56\x4d\x4f\xb0\x7c\xa9\x23\xc0\x37\x4b\xa5\xbf\x1e\xea\x7e\x73\x66\x8e\x13\x50\x31\xfe\xaf\xcb\xb4\x7c\xbc\x2a\xe3\x0e\xc1\x6a\x39\xb9\xc3\x37\xe0\xa6\x2e\xec\xdd\x80\xc0\xb7\xa0\x49\x24\xac\x39\x72\xda\x4f\xa9\x29\x9c\x14\xb5\xa5\x3d\x37\xb0\x8b\xf0\x22\x68\xb3\xba\xc9\xea\x93\x55\x09\x0e\xeb\x04\xad\x87\xbe\xe0\x59\x3b\xa4\xe4\x44\x3d\xda\x38\xa9\x7a\xfb\xf2\xdb\x99\x52\xdf\x63\xf1\x78\xf3\xb4\xc5\x2b\xcc\x13\x2b\xe8\xd9\xe2\x68\x81\x21\x3a\xbd\xeb\x7e\x1c\x44\xc4\x06\x15\x48\x90\x9f\x05\x20\xf0\xdd\x75\x20\xfc\x40\x8e\xa2\x8c\x2c\xeb\xc0\xf5\x30\x63\xa2\xd3\x05\x70\xe0\x53\x50\xe5\x2b\x39\x0d\xd9\xb6\x76\x62\x98\x48\x47\xbe\x9a\xd9\xb4\xcd\x50\xb0\x69\xff\xd2\x9d\xd9\xc6\x2e\xf1\x47\x01\xf8\xd0\x12\xa4\xa7\x0c\x84\x31\xcc"}, -{{0xa5,0xb3,0x4c,0xef,0xab,0x94,0x79,0xdf,0x83,0x89,0xd7,0xe6,0xf6,0xc1,0x46,0xaa,0x8a,0xff,0xb0,0xbe,0xc8,0x37,0xf7,0x8a,0xf6,0x46,0x24,0xa1,0x45,0xcc,0x34,0x4e,},{0x7b,0x0f,0x4f,0x24,0xd9,0x97,0x2b,0xc6,0xfe,0x83,0x82,0x6c,0x52,0x71,0x6a,0xd1,0xe0,0xd7,0xd1,0x9f,0x12,0x38,0x58,0xcb,0x3e,0x99,0xfa,0x63,0x6a,0xc9,0x63,0x1a,},{0x2f,0xbd,0x89,0x9d,0x72,0xb6,0xd3,0x9e,0x4f,0x45,0xb8,0xb6,0x2c,0xbb,0xd5,0xf3,0xc0,0xac,0xb1,0xad,0x85,0x40,0x91,0x3f,0xa5,0x85,0x87,0x7e,0x91,0xcc,0xfe,0xf7,0xbe,0xe5,0x0a,0x4b,0x0f,0x9f,0xed,0xf5,0xcc,0x1e,0x0d,0x19,0x53,0xad,0x39,0x9c,0x83,0x89,0xa9,0x33,0x91,0xe1,0xb7,0xc9,0x29,0xaf,0x6d,0x6f,0x3b,0x79,0x6c,0x08,},"\xe2\x1e\x98\xaf\x6c\x2b\xac\x70\x55\x7e\xb0\xe8\x64\xda\x2c\x2b\x4d\x6c\x0a\x39\xa0\x59\xd3\x47\x72\x51\xf6\x17\x8a\x39\x67\x6f\x47\x49\xe7\xfb\xea\x62\x3f\x14\x8a\x43\xa8\xb0\xfe\x06\x10\x50\x6f\xa6\x58\xab\xd2\xf5\xfa\x39\x19\x8f\x26\x36\xb7\x24\xdb\x22\xd1\xae\xbc\x2a\xb0\x7b\x2b\x6d\xbf\xfd\xee\x8c\xec\xe8\x1e\x1a\xf1\x49\x3e\xc1\x96\x4e\x16\xbf\x86\xab\x25\x8c\xa0\xfe\xb7\x7e\x3c\x87\x17\xe4\x40\x38\xab\xe1\x52\xc1\x4b\xe1\x56\x60\xbf\x93\xb2\xd4\x8d\x92\xc4\xed\x70\x74\xd2\x49\x42\x10\x62\x1b\xcf\x20\x4f\xba\x88\xc6\x54\xd5\xff\xe0\x1e\x1a\x53\xd0\x8f\x70\xbb\x23\x70\x89\xdc\x80\x72\x16\xff\x6a\x85\xdb\xec\x31\x02\x23\x7d\x42\x59\x07\x78\xac\xf6\xc1\xdc\x56\x6d\x5a\x2b\xb9\xa6\x3b\xc2\x1c\x32\x9c\x27\x2e\x59\x65\xba\xee\xb0\xfe\x89\x1d\xe3\xcc\x8c\xbf\xa8\xe5\x41\xa8\x88\x1d\xf6\x89\x42\xe7\xff\x8d\xc6\x56\xbd\x08\x57\x5f\x6a\xaf\x92\x4a\x17\x6d\x66\x3b\x1a\x1f\x43\x57\x4d\x11\x76\x8c\x70\x1b\x26\x95\x61\xe5\x54\x38\xdb\xeb\xfd\x44\x3d\x21\x15\xcb\x93\x3d\x1c\xde\x4a\x91\x5b\x54\xc3\x25\xc2\x7f\x49\x9e\xf0\x2b\xd0\x12\xff\x1f\x9a\x36\x39\x09\x22\x88\x76\x00\xfe\x71\x2b\xcd\xc2\x3e\xb5\x97\x4a\x30\x53\x72\xad\x52\x95\x1f\x83\xf0\xe5\x8c\xc4\x9e\x28\x98\x41\x62\x19\x17\xf1\xfc\xb0\x23\x51\x47\x24\x0d\xae\x4c\xf3\xb9\x9b\x6a\xc6\xd8\xde\x94\xef\xe7\xc4\x43\x67\x14\x50\x8b\xcd\x01\x14\xc5\x60\x68\xff\x1b\x7c\x16\xd5\x1b\xd9\x06\x43\x78\x74\xd6\x54\x9a\xb5\xd8\x08\x78\x96\x87\x2e\xc8\xa0\x9d\x74\x12"}, -{{0xad,0x75,0xc9,0xce,0x29,0x9c,0x4d,0x59,0x39,0x33,0x67,0xd7,0x7a,0x4c,0x9f,0x8d,0xf8,0xdc,0xec,0x76,0x5c,0x6d,0xbd,0x25,0xb5,0x27,0xfb,0x76,0x69,0x91,0x36,0x04,},{0xb9,0x91,0x05,0x48,0xfe,0x63,0x12,0xa1,0x19,0xc9,0x99,0x3e,0xeb,0xcf,0xb9,0xdc,0x90,0x03,0x0f,0xfb,0x0e,0x4d,0xe2,0xb7,0xcc,0xd2,0x3c,0xbe,0xb4,0xfe,0xf7,0x1b,},{0x6b,0x7e,0xf2,0x7b,0xcf,0xbf,0x2b,0x71,0x49,0x85,0x03,0x37,0x64,0xfc,0xcf,0xf5,0x55,0xe3,0xf5,0xbc,0x44,0x61,0x0d,0x6c,0x8c,0x62,0x11,0x7c,0xb3,0x83,0x1a,0x07,0xf4,0xa8,0xbd,0xdb,0x0e,0xae,0xd1,0xd4,0x6b,0x02,0x89,0xb1,0x5d,0xe1,0xaa,0x4d,0xcc,0x17,0xd7,0x1b,0xe9,0x6a,0x09,0xe6,0x6b,0xa4,0xdc,0x46,0x27,0xc7,0x87,0x05,},"\x62\xfc\x5a\xb6\x7d\xeb\x1f\xee\x9a\xb6\xcc\xa3\xb8\x8a\x1d\xf1\xe5\x89\xf0\xfd\x4a\x88\xf4\xaa\x77\x38\x94\x87\x61\xfe\x84\x37\x2c\x5b\x18\xe4\x65\x52\x20\xc1\xd8\x4d\x52\xac\xad\x32\xe2\x29\xa5\xc7\x56\xc2\x0f\xc6\x2f\xe4\xb4\xb4\xe5\xfd\x70\x77\xae\x4e\xd5\x39\x7a\xa7\x96\xf2\x30\x7c\xee\xdb\x65\x05\xb3\x92\x97\x85\x6f\x4a\xeb\x5e\x70\x93\x8e\x36\xee\x24\xa0\xac\x7d\x98\x68\x30\x6f\x6b\x53\x91\x06\x23\xb7\xdc\x89\xa6\x67\x2a\xd7\x38\x57\x6e\xd5\xd8\x88\x31\xdd\x33\x83\x21\xc8\x90\x2b\xc2\x06\x1f\x65\xe9\x4d\x45\x2f\xdf\xa0\xdc\x66\x5c\xef\xb9\x23\x08\xe5\x23\x01\xbd\x46\x27\x00\x6b\x36\x3d\x06\xb7\x75\xa3\x95\x91\x4d\x8c\x86\x3e\x95\xa0\x0d\x68\x93\xf3\x37\x61\x34\xc4\x29\xf5\x64\x78\x14\x5e\x44\x56\xf7\xa1\x2d\x65\xbb\x2b\x89\x65\xd7\x28\xcb\x2d\xdb\xb7\x08\xf7\x12\x5c\x23\x70\x95\xa9\x21\x95\xd9\x2f\xa7\x27\xa3\x72\xf3\x54\x5a\xe7\x01\xf3\x80\x8f\xee\x80\x2c\x89\x67\xa7\x6e\x8a\x94\x0e\x55\xfb\x2d\x81\x0b\xfb\x47\xad\xa1\x56\xf0\xed\xa1\x82\x9b\x15\x9c\xf0\x5c\x7f\x36\xcf\x38\x47\xd7\xb2\x1d\xe8\x4c\x3d\xc0\xfe\x65\x83\x47\xf7\x93\x96\xa0\x11\x39\xa5\x08\xb6\x00\x22\xdb\x1c\x0e\x5a\xee\xf4\x7e\x44\x5e\x66\xf7\x83\xe6\x2c\x96\x59\x7b\xdb\x16\xf2\x09\xc0\x8a\x91\x32\xc7\x57\x31\x36\x17\x0e\xe3\xeb\xf2\x42\x61\x26\x5a\x89\xfb\x4f\x10\x33\x33\x75\xe2\x0b\x33\xab\x74\x03\x46\x4f\x52\x49\x46\x1c\x68\x53\xc5\xfd\xdb\x9f\x58\xaf\x81\x68\x92\x91\x03\x93\xa7\x07\x7b\x79\x9f\xdc\x34\x89\x72\x09\x98\xfe\xea\x86"}, -{{0x1c,0xed,0x57,0x45,0x29,0xb9,0xb4,0x16,0x97,0x7e,0x92,0xeb,0x39,0x44,0x8a,0x87,0x17,0xca,0xc2,0x93,0x4a,0x24,0x3a,0x5c,0x44,0xfb,0x44,0xb7,0x3c,0xcc,0x16,0xda,},{0x85,0xe1,0x67,0xd5,0xf0,0x62,0xfe,0xe8,0x20,0x14,0xf3,0xc8,0xb1,0xbe,0xae,0xd8,0xee,0xfb,0x2c,0x22,0xd8,0x64,0x9c,0x42,0x4b,0x86,0xb2,0x1b,0x11,0xeb,0x8b,0xda,},{0xe0,0x30,0x3a,0xef,0xe0,0x8a,0x77,0x73,0x8d,0xcc,0x65,0x7a,0xfb,0xb9,0xb8,0x35,0xed,0x27,0x96,0x13,0xa5,0x3c,0x73,0xfd,0xc5,0xdd,0xbf,0xb3,0x50,0xe5,0xcf,0xf4,0xd6,0xc9,0xbb,0x43,0xdc,0x07,0xc9,0x5b,0xf4,0xe2,0x3b,0x64,0xc4,0x0f,0x88,0x04,0xc7,0x16,0x99,0x52,0xe3,0xc8,0xd5,0x9a,0x71,0x97,0x24,0x1b,0xfe,0xd0,0x74,0x0f,},"\x1b\x3b\x95\x3c\xce\x6d\x15\x30\x3c\x61\xca\x70\x76\x09\xf7\x0e\x72\x50\xf6\xc0\xde\xba\x56\xa8\xce\x52\x2b\x59\x86\x68\x96\x51\xcd\xb8\x48\xb8\x42\xb2\x22\x96\x61\xb8\xee\xab\xfb\x85\x70\x74\x9e\xd6\xc2\xb1\x0a\x8f\xbf\x51\x50\x53\xb5\xea\x7d\x7a\x92\x28\x34\x9e\x46\x46\xf9\x50\x5e\x19\x80\x29\xfe\xc9\xce\x0f\x38\xe4\xe0\xca\x73\x62\x58\x42\xd6\x4c\xaf\x8c\xed\x07\x0a\x6e\x29\xc7\x43\x58\x6a\xa3\xdb\x6d\x82\x99\x3a\xc7\x1f\xd3\x8b\x78\x31\x62\xd8\xfe\x04\xff\xd0\xfa\x5c\xbc\x38\x1d\x0e\x21\x9c\x91\x93\x7d\xf6\xc9\x73\x91\x2f\xc0\x2f\xda\x53\x77\x31\x24\x68\x27\x4c\x4b\xee\x6d\xca\x7f\x79\xc8\xb5\x44\x86\x1e\xd5\xba\xbc\xf5\xc5\x0e\x14\x73\x49\x1b\xe0\x17\x08\xac\x7c\x9f\xf5\x8f\x1e\x40\xf8\x55\x49\x7c\xe9\xd7\xcc\x47\xb9\x41\x0f\x2e\xdd\x00\xf6\x49\x67\x40\x24\x3b\x8d\x03\xb2\xf5\xfa\x74\x2b\x9c\x63\x08\x67\xf7\x7a\xc4\x2f\x2b\x62\xc1\x4e\x5e\xbd\xdc\x7b\x64\x7a\x05\xff\xf4\x36\x70\x74\x5f\x28\x51\xef\xf4\x90\x9f\x5d\x27\xd5\x7a\xe8\x7f\x61\xe9\x65\xee\x60\xfd\xf9\x77\x24\xc5\x92\x67\xf2\x61\x0b\x7a\xd5\xde\x91\x98\x56\xd6\x4d\x7c\x21\x26\x59\xce\x86\x56\x14\x9b\x6a\x6d\x29\xd8\xf9\x2b\x31\x2b\xe5\x0b\x6e\x2a\x43\x1d\x36\xae\x02\x2b\x00\xa6\xfe\x36\x0e\x3a\xf6\x54\x32\x89\x9c\x43\xbe\x04\x27\xe3\x6d\x21\xcf\xec\x81\xf2\x1a\xa5\x3b\x33\xdb\x5e\xd2\xc3\x7d\xa8\xf9\x6a\xc3\xe7\xdc\x67\xa1\xde\x37\x54\x6c\xf7\xde\x10\x08\xc7\xe1\xad\xbe\x0f\x34\xfa\x7e\xb2\x43\x4d\x94\xe6\xa1\x3f\x4c\xf8\x6a\x98\xd4\x97\x62\x2f"}, -{{0xf0,0x79,0x0d,0x93,0xe2,0xd3,0xb8,0x4f,0x61,0xef,0x4c,0x80,0x71,0x47,0xab,0xa4,0x10,0xe4,0x15,0xe7,0x2b,0x71,0xb0,0xd6,0x1d,0x01,0x02,0x6f,0xed,0x99,0xda,0x3d,},{0xef,0xdf,0x64,0x9f,0xb0,0x33,0xcf,0x32,0x8e,0x0b,0x28,0x77,0x96,0xf8,0xa2,0x5e,0x9c,0x6e,0x2e,0x87,0x1b,0x33,0xc2,0xc2,0x1a,0x40,0x28,0xa8,0xa2,0x5a,0x4b,0x28,},{0x08,0x77,0x3a,0x6a,0x78,0x76,0x2c,0xbb,0x1e,0x25,0xfc,0xbb,0x29,0x13,0x99,0x41,0xbd,0xf1,0x6f,0x4e,0x09,0xa1,0xfa,0x08,0xfc,0x70,0x1f,0x32,0xf9,0x33,0xed,0xd7,0x4c,0x0a,0xe9,0x83,0xc1,0x2a,0x0a,0x5b,0x02,0x0b,0x6b,0xcf,0x44,0xbb,0x71,0x9d,0xde,0x8e,0xd0,0x78,0x1a,0x82,0x98,0x26,0x56,0x40,0xe1,0x60,0x8c,0x98,0xb3,0x01,},"\x79\x73\xe9\xf3\x2d\x74\x80\x59\x92\xeb\x65\xda\x0d\x63\x73\x35\xe5\x0e\xff\x0c\xe6\x8e\xa2\xd1\xf3\xa0\x2d\xe7\x04\x49\x2b\x9c\xfb\xe7\xe7\xba\x96\xfd\xb4\x2b\xb8\x21\xa5\x13\xd7\x3f\xc6\x04\x02\xe9\x2c\x85\x5d\xea\xed\x73\xff\xea\xf7\x09\x52\x02\x90\x62\xc8\x33\xe1\x4e\xc1\xb1\x4f\x14\x4e\x22\x07\xf6\xa0\xe7\x27\xe5\xa7\xe3\xcb\xab\x27\xd5\x97\x29\x70\xf6\x95\x18\xa1\x5b\x09\x3e\x74\x0c\xc0\xce\x11\xbf\x52\x48\xf0\x82\x6b\x8a\x98\xbd\xe8\xbf\x2c\x70\x82\xc9\x7a\xff\x15\x8d\x08\x37\x11\x18\xc8\x90\x21\xcc\x39\x74\xae\x8f\x76\xd8\x66\x73\xc3\xf8\x24\xb6\x2c\x79\xc4\xb4\x1f\x40\xea\xa8\x94\x37\x38\xf0\x33\x00\xf6\x8c\xbe\x17\x54\x68\xeb\x23\x5a\x9f\xf0\xe6\x53\x7f\x87\x14\xe9\x7e\x8f\x08\xca\x44\x4e\x41\x19\x10\x63\xb5\xfa\xbd\x15\x6e\x85\xdc\xf6\x66\x06\xb8\x1d\xad\x4a\x95\x06\x55\x84\xb3\xe0\x65\x8c\x20\xa7\x06\xea\xf4\xa0\x77\x7d\xa4\xd2\xe0\xcd\x2a\x0f\xca\x60\x10\x9c\x2b\x44\x03\xdb\x3f\x03\xcd\x47\x81\xc1\xfb\xb0\x27\x22\x02\xbc\xb1\x16\x87\x80\x8c\x50\xcb\x98\xf6\x4b\x7f\x3f\xd3\xd4\x33\x33\xbb\x5a\x06\x1b\x9e\x37\x70\x90\xab\xb1\xe0\xa8\x85\xcb\x26\xb7\x3c\x16\x3e\x63\xff\x64\x51\xff\x2f\x4e\xc8\x24\x9c\x7e\x15\x2b\xd0\x39\x73\xa1\xe9\x64\xe2\xb5\xb2\x35\x28\x1a\x93\x83\x99\xa1\x12\xa2\x45\x29\xe3\x83\xa5\x60\xdc\x50\xbb\x1b\x62\x2a\xd7\x4e\xf3\x56\x58\xdc\xb1\x0f\xfe\x02\x25\x68\xac\x3f\xfa\xe5\xb4\x65\xa8\xed\x76\x43\xe8\x56\x1b\x35\x2e\xe9\x94\x4a\x35\xd8\x82\xc7\x12\xb1\x87\x78\x8a\x0a\xba\xe5\xa2\x2f"}, -{{0x4c,0xb9,0xdf,0x7c,0xe6,0xfa,0xe9,0xd6,0x2b,0xa0,0x9e,0x8e,0xb7,0x0e,0x4c,0x96,0x9b,0xde,0xaf,0xcb,0x5e,0xc7,0xd7,0x02,0x43,0x26,0xe6,0x60,0x3b,0x06,0x21,0xbf,},{0x01,0x80,0x69,0xdd,0x0e,0xb4,0x40,0x55,0xa3,0x5c,0xd8,0xc7,0x7c,0x37,0xca,0x9f,0xb1,0xad,0x24,0x17,0x27,0x13,0x85,0xe1,0x34,0xb2,0xf4,0xe8,0x1f,0x52,0x03,0x3c,},{0xe3,0x3c,0x07,0x83,0x6c,0x53,0x7d,0x6b,0xfb,0xd0,0xf4,0x59,0x2d,0x6e,0x35,0xb1,0x63,0x49,0x9b,0xa7,0x8d,0xc7,0xff,0xce,0xc5,0x65,0xd0,0x4f,0x9a,0x7d,0xb7,0x81,0x94,0x3e,0x29,0xe6,0xce,0x76,0x76,0x3e,0x9b,0xad,0xdf,0x57,0x43,0x7f,0xd9,0xc6,0xb0,0x32,0x39,0xa6,0xe6,0x85,0x0e,0x45,0x02,0xa3,0x56,0xc2,0xe1,0x2c,0x37,0x05,},"\x14\x62\x7d\x6e\xa0\xe7\x89\x54\x60\x75\x94\x76\xdc\x74\xc4\x28\x00\xce\xef\x99\x43\x27\x51\x81\x51\x49\x0d\x9d\xf2\x30\x67\x91\x4e\x44\x78\x8a\x12\x76\x8c\xcb\x25\x47\x1b\x9c\x3b\xa9\xd1\x4f\xb4\x36\xdc\xba\x38\x42\x9b\x3a\x04\x56\x87\x77\x63\xc4\x91\x75\xd0\xe0\x82\x68\x3e\x07\xa9\x05\x8f\x36\x85\xc6\x27\x93\x07\xb2\x30\x3d\x12\x21\xb9\xc2\x97\x93\xd8\xa4\x87\x7f\x6d\xf5\x15\x87\x38\x4d\xad\xf7\x51\xc5\xf7\xbf\xbd\x20\x7d\x51\x96\x22\xc3\x7b\x51\xce\xee\xe2\xc2\x0d\x82\x69\xf8\xcb\x88\xd3\xfe\x43\xd6\xd4\x34\xd5\xbb\xd0\xe2\x03\xc1\x53\x2d\x97\xba\x55\x21\x47\x22\x74\x96\xc8\x7f\x67\xb5\x0b\xb7\x61\x93\xad\xd0\x14\x4d\xf1\xc1\x76\x65\x75\x85\x40\x83\x62\xca\x2e\xd0\x4a\xd6\x2a\xcf\x1c\x25\xe3\x41\xdf\xd1\x49\x8d\x85\xb4\xb1\x34\x9a\x8b\x0b\x9b\x02\xc4\x35\x23\xc5\x58\x53\x41\x9b\xfe\xd3\x7d\x5a\x2c\xdf\x17\xdf\xbf\x1a\x3b\xd7\x75\x9d\x6a\xe1\x80\xf9\xd2\x7d\xcd\x9a\x89\x33\xe2\x9a\x7c\x0a\x30\x77\x1e\xea\x7c\x2e\x0f\xa2\x42\x92\x5d\x23\x36\xdc\xe5\x85\x62\x90\x57\xd8\x44\x32\x39\x64\xf6\xd3\xd1\x1f\xf0\xb3\xf8\x29\xa3\xbe\x8c\x9f\x04\x68\xa6\x82\x3d\x8e\x70\xab\x5a\x2d\xa2\x1e\x15\xfa\x8b\x04\x1a\x29\x81\x22\x22\xe9\xc3\x0b\x2b\xd9\xa1\x2d\x1f\xde\xe6\xf8\x78\x76\xe8\xce\x81\x00\x96\x37\xa8\xbb\x22\x36\x12\x9a\x47\xca\x74\x28\x9e\xe4\xaa\xd4\x29\xff\xe2\x9f\x47\x43\x02\x41\xca\x8c\xc3\x84\x8b\x72\x00\xfd\x6e\x14\x70\x65\x1a\x9a\x0a\x6f\x72\xc9\x03\x3e\x83\x1d\xf0\x51\x40\x8a\x62\x60\xf6\x5c\xba\xf6\xe0\x12\xb1\x8e"}, -{{0xa1,0x36,0xe0,0x09,0xd5,0x3e,0x5e,0xf5,0x9d,0x09,0x46,0xbc,0x17,0x56,0x63,0xa8,0x6b,0xc0,0xfc,0xd2,0x9e,0xad,0xd9,0x5c,0xfc,0x9d,0x26,0x60,0x37,0xb1,0xe4,0xfb,},{0x9c,0x18,0x06,0xec,0x04,0x54,0xf5,0x83,0x14,0xeb,0x83,0x97,0xd6,0x42,0x87,0xde,0xe3,0x86,0x64,0x0d,0x84,0x91,0xab,0xa3,0x64,0x60,0x76,0x88,0x84,0x17,0x15,0xa0,},{0xbc,0x09,0x4b,0xa9,0x1c,0x11,0x5d,0xee,0x15,0xd7,0x53,0x36,0x1a,0x75,0xf3,0xf0,0x3d,0x6a,0xf4,0x5c,0x92,0x15,0x7e,0x95,0xdb,0xe8,0xd3,0x21,0x94,0xb6,0xc5,0xce,0x72,0xb9,0xdc,0x66,0xf7,0x3d,0xf1,0x2d,0xca,0x0b,0x63,0x9f,0x3e,0x79,0x1d,0x47,0x86,0x16,0xa1,0xf8,0xd7,0x35,0x9a,0x42,0xc8,0xea,0xe0,0xdd,0xa1,0x6b,0x16,0x06,},"\xa4\x9d\x1c\x3d\x49\xe1\x3c\x2e\xda\x56\x86\x8a\x88\x24\xaa\x9f\x8d\x2b\xf7\x2f\x21\x95\x5e\xba\xfd\x07\xb3\xbd\xc8\xe9\x24\xde\x20\x93\x6c\xee\x51\x3d\x8a\x64\xa4\x71\x73\xa3\xbd\x65\x9e\xff\x1a\xcc\xff\x82\x44\xb2\x6a\xae\x1a\x0c\x27\xfa\x89\x1b\xf4\xd8\x5e\x8f\xb1\xb7\x6a\x6c\xab\x1e\x7f\x74\xc8\x9e\xe0\x7b\xb4\x0d\x71\x43\x26\xf0\x9b\x3f\xd4\x06\x32\xfa\xd2\x08\xea\x81\x6f\x90\x72\x02\x8c\x14\xb5\xb5\x4e\xcc\x1c\x5b\x7f\xc8\x09\xe7\xe0\x78\x6e\x2f\x11\x49\x5e\x76\x01\x7e\xb6\x2a\xa4\x56\x3f\x3d\x00\xee\x84\x34\x8d\x98\x38\xcd\x17\x64\x9f\x69\x29\xa6\xd2\x06\xf6\x0e\x6f\xc8\x2e\x0c\x34\x64\xb2\x7e\x0e\x6a\xbd\x22\xf4\x46\x9b\xdf\xd4\xcb\x54\xf7\x7e\x32\x9b\x80\xf7\x1b\xf4\x21\x29\xec\x13\xc9\xdf\xe1\x92\xad\xfa\xa4\x2e\xe3\xdd\xee\xda\x38\x58\x16\xfb\xad\x5f\x41\x19\x38\xc6\x3b\x56\x0f\x4e\xcd\x94\x53\x4b\xe7\xd9\x87\x25\xcd\x94\xc9\x9c\xe4\x92\xf0\xf0\x69\xba\x0e\xc0\x8f\x87\x7a\x78\x12\xef\x27\xae\x19\xd7\xa7\x7b\xe6\x3f\x66\xbc\xf8\xd6\xcf\x3a\x1a\x61\xfc\x9c\xfe\xf1\x04\xc7\x46\x2a\x21\xca\x7f\x03\xaf\xb5\xbb\x1a\xc8\xc7\x51\x24\xb5\x54\xe8\xd0\x44\xb8\x10\xd9\x5f\xf8\xc9\xdd\x09\xa3\x44\x84\xd8\xc4\xb6\xc9\x5f\x95\xc3\xc2\x28\x23\xf5\x2c\xe8\x44\x29\x37\x24\xd5\x25\x91\x91\xf1\xba\x09\x29\xe2\xac\xdb\xb8\xb9\xa7\xa8\xad\xf0\xc5\x2e\x78\xac\xdf\xdf\x05\x7b\x09\x85\x88\x1a\xfb\xed\x4d\xbe\xbd\xeb\xbd\xae\x0a\x2b\x63\xbd\x4e\x90\xf9\x6a\xfd\xcb\xbd\x78\xf5\x06\x30\x9f\x9b\xdb\x65\x00\x13\xcb\x73\xfa\xed\x73\x90\x4e"}, -{{0xff,0x0f,0x1c,0x57,0xdd,0x88,0x4f,0xbe,0xea,0x6e,0x29,0x17,0x28,0x2b,0x79,0xba,0x67,0xf8,0xa6,0x85,0x12,0x67,0xb9,0xf4,0x63,0x6d,0xaf,0xda,0x33,0xbd,0x2b,0x5b,},{0xfe,0xf6,0x37,0x8a,0xd1,0x2a,0x7c,0x25,0x2f,0xa6,0xeb,0x74,0x2b,0x05,0x06,0x4b,0x41,0x53,0x0f,0xf0,0x19,0xdc,0x68,0x0a,0xb5,0x44,0xc0,0x27,0xea,0x28,0x36,0xe7,},{0xd5,0x00,0x84,0x86,0x72,0x6c,0xce,0x33,0x0a,0x29,0xdd,0x7e,0x4d,0x74,0x74,0xd7,0x35,0x79,0x82,0x01,0xaf,0xd1,0x20,0x6f,0xeb,0x86,0x9a,0x11,0x2e,0x5b,0x43,0x52,0x3c,0x06,0x97,0x67,0x61,0xbe,0x3c,0xf9,0xb2,0x71,0x63,0x78,0x27,0x3c,0x94,0xf9,0x35,0x72,0xa7,0xd2,0xb8,0x98,0x26,0x34,0xe0,0x75,0x5c,0x63,0x2b,0x44,0x90,0x08,},"\x52\x2a\x5e\x5e\xff\x5b\x5e\x98\xfa\xd6\x87\x8a\x9d\x72\xdf\x6e\xb3\x18\x62\x26\x10\xa1\xe1\xa4\x81\x83\xf5\x59\x0e\xce\xf5\xa6\xdf\x67\x1b\x28\xbe\x91\xc8\x8c\xdf\x7a\xe2\x88\x11\x47\xfe\x6c\x37\xc2\x8b\x43\xf6\x4c\xf9\x81\xc4\x55\xc5\x9e\x76\x5c\xe9\x4e\x1b\x64\x91\x63\x1d\xea\xee\xf6\xd1\xda\x9e\xbc\xa8\x86\x43\xc7\x7f\x83\xea\xe2\xcf\xdd\x2d\x97\xf6\x04\xfe\x45\x08\x1d\x1b\xe5\xc4\xae\x2d\x87\x59\x96\xb8\xb6\xfe\xcd\x70\x7d\x3f\xa2\x19\xa9\x3b\xa0\x48\x8e\x55\x24\x7b\x40\x5e\x33\x0c\xfb\x97\xd3\x1a\x13\x61\xc9\xb2\x08\x4b\xdb\x13\xfb\x0c\x05\x89\x25\xdb\x8c\x3c\x64\x9c\x9a\x3e\x93\x7b\x53\x3c\xc6\x31\x0f\xa3\xb1\x61\x26\xfb\x3c\xc9\xbb\x2b\x35\xc5\xc8\x30\x00\x15\x48\x8a\x30\xfa\xdc\xa3\xc8\x87\x1f\xa7\x0d\xfd\xc7\x05\x5b\xf8\xe6\x31\xf2\x0c\x9b\x25\x28\x31\x1e\x32\x4a\x7c\x4e\xdd\x54\x62\x07\x9f\x34\x41\xc9\xec\xf5\x5f\xa9\x99\xe7\x31\x37\x23\x44\xfd\xc0\xd4\x13\xe4\x17\xaa\xa0\x01\xa1\xb2\xd3\xd9\xbc\x00\x0f\xec\x1b\x02\xbd\x7a\x88\xa8\x12\xd9\xd8\xa6\x6f\x94\x64\x76\x4c\x07\x0c\x93\x04\x1e\xef\xb1\x7c\xe7\x4e\xff\x6d\x4a\xff\x75\xf0\xcb\xf6\xa7\x89\xa9\xec\xde\x74\xab\xe3\x31\x30\xfc\xa0\xda\x85\x3a\xa7\xc3\x31\x3a\xda\x3f\x0a\xe2\xf5\x95\xc6\x79\x6a\x93\x68\x5e\x72\x9d\xd1\x8a\x66\x9d\x63\x81\x82\x5a\xb3\xf3\x6a\x39\x1e\x75\x25\xb2\xa8\x07\xa5\x2f\xa5\xec\x2a\x03\x0a\x8c\xf3\xb7\x73\x37\xac\x41\xfc\xeb\x58\x0e\x84\x5e\xed\x65\x5a\x48\xb5\x47\x23\x8c\x2e\x81\x37\xc9\x2f\x8c\x27\xe5\x85\xca\xad\x31\x06\xee\xe3\x81\x4a"}, -{{0x0b,0xc6,0xaf,0x64,0xde,0x57,0x09,0xd3,0xdb,0xc2,0x8f,0x7e,0xf6,0xd3,0xfe,0x28,0xb6,0xde,0x52,0x9f,0x08,0xf5,0x85,0x7c,0xcb,0x91,0x06,0x95,0xde,0x45,0x4f,0x56,},{0xfb,0x49,0x1f,0xc9,0x00,0x23,0x7b,0xdc,0x7e,0x9a,0x11,0x9f,0x27,0x15,0x0c,0xd9,0x11,0x93,0x5c,0xd3,0x62,0x87,0x49,0xff,0x40,0xef,0x41,0xf3,0x95,0x5b,0xc8,0xac,},{0xdb,0xc7,0x13,0x4d,0x1c,0xd6,0xb0,0x81,0x3b,0x53,0x35,0x27,0x14,0xb6,0xdf,0x93,0x94,0x98,0xe9,0x1c,0xf3,0x7c,0x32,0x43,0x37,0xd9,0xc0,0x88,0xa1,0xb9,0x98,0x34,0x7d,0x26,0x18,0x5b,0x43,0x09,0x00,0x41,0x29,0x29,0xe4,0xf6,0x3e,0x91,0x03,0x79,0xfc,0x42,0xe3,0x55,0xa4,0xe9,0x8f,0x6f,0xee,0x27,0xda,0xfa,0xd1,0x95,0x72,0x06,},"\xac\x78\x86\xe4\xf4\x17\x2a\x22\xc9\x5e\x8e\xea\x37\x43\x7b\x37\x5d\x72\xac\xce\xdc\xee\x6c\xc6\xe8\x16\x76\x33\x01\xa2\xd8\xef\x4d\x6f\x31\xa2\xc1\xd6\x35\x81\x8b\x70\x26\xa3\x95\xce\x0d\xaf\xd7\x1c\x51\x80\x89\x3a\xf7\x6b\x7e\xa0\x56\xc9\x72\xd6\x80\xec\xa0\x1d\xcb\xdb\xae\x6b\x26\xf1\xc5\xf3\x3f\xc9\x88\xb8\x24\xfb\xbe\x00\xca\xcc\x31\x64\x69\xa3\xba\xe0\x7a\xa7\xc8\x88\x5a\xf7\xf6\x5f\x42\xe7\x5c\xef\x94\xdb\xb9\xaa\xb4\x82\x51\x43\xc8\x50\x70\xe7\x71\x6b\x76\x12\xf6\x4e\xf0\xb0\x16\x60\x11\xd2\x3e\xb5\x65\x4a\xa0\x98\xb0\x2d\x8d\x71\xe5\x7c\x8f\xa1\x7b\xff\x2f\xe9\x7d\xc8\x19\x31\x77\xea\xdc\x09\xfb\x19\x2d\x80\xaa\x92\xaf\xa9\x87\x20\xd4\x61\x48\x17\xff\x3c\x39\xd3\xac\xce\x18\x90\x6f\xa3\xde\x09\x61\x89\x31\xd0\xd7\xa6\x0c\x44\x29\xcb\xfa\x20\xcf\x16\x5c\x94\x79\x29\xac\x29\x3a\xe6\xc0\x6e\x7e\x8f\x25\xf1\x26\x42\x91\xe3\xe1\xc9\x8f\x5d\x93\xe6\xec\xc2\x38\x9b\xc6\x0d\xbb\xf4\xa6\x21\xb1\x32\xc5\x52\xa9\x9c\x95\xd2\x6d\x8d\x1a\xf6\x11\x38\xb5\x70\xa0\xde\x4b\x49\x7e\xbe\x80\x51\xc7\x27\x3a\x98\xe6\xe7\x87\x6d\x0b\x32\x75\x03\xaf\x3c\xb2\xcc\x40\x91\xce\x19\x25\xcb\x2f\x29\x57\xf4\xec\x56\xee\x90\xf8\xa0\x9d\xd5\x7d\x6e\x83\x06\x7a\x35\x6a\x4c\xfe\x65\xb1\xb7\xa4\x46\x5d\xa2\xab\x13\x3b\x0e\xfb\x5e\x7d\x4d\xbb\x81\x1b\xcb\xbd\xe7\x12\xaf\xbf\x0f\x7d\xd3\xf3\x26\x22\x22\x84\xb8\xc7\x4e\xac\x7a\xd6\x25\x7f\xa8\xc6\x32\xb7\xda\x25\x59\xa6\x26\x6e\x91\xe0\xef\x90\xdb\xb0\xaa\x96\x8f\x75\x37\x6b\x69\x3f\xca\xa5\xda\x34\x22\x21"}, -{{0x2f,0x5e,0x83,0xbd,0x5b,0x41,0x2e,0x71,0xae,0x3e,0x90,0x84,0xcd,0x36,0x9e,0xfc,0xc7,0x9b,0xf6,0x03,0x7c,0x4b,0x17,0x4d,0xfd,0x6a,0x11,0xfb,0x0f,0x5d,0xa2,0x18,},{0xa2,0x2a,0x6d,0xa2,0x9a,0x5e,0xf6,0x24,0x0c,0x49,0xd8,0x89,0x6e,0x3a,0x0f,0x1a,0x42,0x81,0xa2,0x66,0xc7,0x7d,0x38,0x3e,0xe6,0xf9,0xd2,0x5f,0xfa,0xcb,0xb8,0x72,},{0x9f,0x80,0x92,0x2b,0xc8,0xdb,0x32,0xd0,0xcc,0x43,0xf9,0x93,0x6a,0xff,0xeb,0xe7,0xb2,0xbc,0x35,0xa5,0xd8,0x22,0x77,0xcd,0x18,0x7b,0x5d,0x50,0xdc,0x7f,0xc4,0xc4,0x83,0x2f,0xff,0xa3,0x4e,0x95,0x43,0x80,0x6b,0x48,0x5c,0x04,0x54,0x8e,0x7c,0x75,0x42,0x94,0x25,0xe1,0x4d,0x55,0xd9,0x1f,0xc1,0x05,0x2e,0xfd,0x86,0x67,0x43,0x0b,},"\xb7\x66\x27\x3f\x06\x0e\xf3\xb2\xae\x33\x40\x45\x4a\x39\x1b\x42\x6b\xc2\xe9\x72\x64\xf8\x67\x45\x53\xeb\x00\xdd\x6e\xcf\xdd\x59\xb6\x11\xd8\xd6\x62\x92\x9f\xec\x71\x0d\x0e\x46\x20\x20\xe1\x2c\xdb\xf9\xc1\xec\x88\x58\xe8\x56\x71\xac\xf8\xb7\xb1\x44\x24\xce\x92\x07\x9d\x7d\x80\x1e\x2a\xd9\xac\xac\x03\x6b\xc8\xd2\xdf\xaa\x72\xaa\x83\x9b\xff\x30\xc0\xaa\x7e\x41\x4a\x88\x2c\x00\xb6\x45\xff\x9d\x31\xbc\xf5\xa5\x43\x82\xde\xf4\xd0\x14\x2e\xfa\x4f\x06\xe8\x23\x25\x7f\xf1\x32\xee\x96\x8c\xdc\x67\x38\xc5\x3f\x53\xb8\x4c\x8d\xf7\x6e\x9f\x78\xdd\x50\x56\xcf\x3d\x4d\x5a\x80\xa8\xf8\x4e\x3e\xde\xc4\x85\x20\xf2\xcb\x45\x83\xe7\x08\x53\x93\x55\xef\x7a\xa8\x6f\xb5\xa0\xe8\x7a\x94\xdc\xf1\x4f\x30\xa2\xcc\xa5\x68\xf1\x39\xd9\xce\x59\xea\xf4\x59\xa5\xc5\x91\x6c\xc8\xf2\x0b\x26\xaa\xf6\xc7\xc0\x29\x37\x9a\xed\xb0\x5a\x07\xfe\x58\x5c\xca\xc6\x03\x07\xc1\xf5\x8c\xa9\xf8\x59\x15\x7d\x06\xd0\x6b\xaa\x39\x4a\xac\xe7\x9d\x51\xb8\xcb\x38\xcf\xa2\x59\x81\x41\xe2\x45\x62\x4e\x5a\xb9\xb9\xd6\x87\x31\x17\x33\x48\x90\x53\x15\xbf\x1a\x5a\xd6\x1d\x1e\x8a\xda\xeb\x81\x0e\x4e\x8a\x86\xd7\xc1\x35\x37\xb0\xbe\x86\x0a\xb2\xed\x35\xb7\x33\x99\xb8\x80\x8a\xa9\x1d\x75\x0f\x77\x94\x3f\x8a\x8b\x7e\x89\xfd\xb5\x07\x28\xaa\x3d\xbb\xd8\xa4\x1a\x6e\x00\x75\x6f\x43\x8c\x9b\x9e\x9d\x55\x87\x2d\xf5\xa9\x06\x8a\xdd\x8a\x97\x2b\x7e\x43\xed\xad\x9c\xed\x22\x37\xca\x13\x67\xbe\x4b\x7c\xdb\x66\xa5\x4e\xa1\x2e\xef\x12\x94\x71\x15\x86\x10\xea\xf2\x8f\x99\xf7\xf6\x86\x55\x7d\xcd\xf6\x44\xea"}, -{{0x72,0x2a,0x2d,0xa5,0x0e,0x42,0xc1,0x1a,0x61,0xc9,0xaf,0xac,0x7b,0xe1,0xa2,0xfe,0xd2,0x26,0x7d,0x65,0x0f,0x8f,0x7d,0x8e,0x5b,0xc7,0x06,0xb8,0x07,0xc1,0xb9,0x1d,},{0xfd,0x0b,0x96,0x45,0x62,0xf8,0x23,0x72,0x1e,0x64,0x9c,0x3f,0xed,0xb4,0x32,0xa7,0x6f,0x91,0xe0,0xae,0xad,0x7c,0x61,0xd3,0x5f,0x95,0xed,0x77,0x26,0xd7,0x85,0x89,},{0xc2,0x69,0x5a,0x57,0x17,0x2a,0xaa,0x31,0xbd,0x08,0x90,0xf2,0x31,0xca,0x8e,0xee,0xc0,0x28,0x7a,0x87,0x17,0x26,0x69,0xa8,0x99,0xad,0x08,0x91,0xce,0xa4,0xc4,0x75,0x79,0xb5,0x04,0x20,0xe7,0x91,0xcd,0xec,0x8c,0x18,0x2c,0x8a,0x0e,0x8d,0xde,0x21,0xb2,0x48,0x0b,0x0c,0xfd,0x81,0x11,0xe2,0x8e,0x56,0x03,0x34,0x7a,0x35,0x2d,0x04,},"\x17\x3e\x8b\xb8\x85\xe1\xf9\x08\x14\x04\xac\xac\x99\x90\x41\xd2\xec\xfc\xb7\x3f\x94\x5e\x0d\xb3\x6e\x63\x1d\x7c\xd1\xab\x99\x9e\xb7\x17\xf3\x4b\xf0\x78\x74\xbf\x3d\x34\xe2\x53\x0e\xb6\x08\x5f\x4a\x9f\x88\xae\x1b\x0f\x7d\x80\xf2\x21\x45\x6a\x8e\x9a\x88\x90\xb9\x1a\x50\x19\x2d\xea\xaa\xcc\x0a\x1a\x61\x5a\x87\x84\x1e\x2c\x5a\x9e\x05\x79\x57\xaf\x6e\x48\xe7\x8c\xc8\x61\x98\xe3\x2e\x7a\xa2\x4d\xcf\x6c\xff\xa3\x29\xbc\x72\x60\x6d\x65\xb1\x16\x82\xc8\xba\x73\x6c\xce\x22\xa0\x57\x85\xdf\x11\x46\x33\x1e\x41\x60\x9c\xf9\xca\x71\x1c\xf4\x64\x95\x82\x97\x13\x8b\x58\xa9\x07\x3f\x3b\xbf\x06\xad\x8a\x85\xd1\x35\xde\x66\x65\x21\x04\xd8\x8b\x49\xd2\x7a\xd4\x1e\x59\xbc\xc4\x4c\x7f\xab\x68\xf5\x3f\x05\x02\xe2\x93\xff\xca\xba\xaf\x75\x59\x27\xdf\xdf\xfb\xfd\xe3\xb3\x5c\x08\x0b\x5d\xe4\xc8\xb7\x85\xf4\xda\x64\xef\x35\x7b\xc0\xd1\x46\x6a\x6a\x96\x56\x0c\x3c\x4f\x3e\x3c\x0b\x56\x3a\x00\x3f\x5f\x95\xf2\x37\x17\x1b\xce\x1a\x00\x17\x71\xa0\x4e\xde\x7c\xdd\x9b\x8c\xa7\x70\xfd\x36\xef\x90\xe9\xfe\x00\x00\xa8\xd7\x68\x5f\xd1\x53\xcc\x72\x82\xde\x95\x92\x0a\x8f\x8f\x08\x98\xd0\x0b\xf0\xc6\xc9\x33\xfe\x5b\xb9\x65\x3f\xf1\x46\xc4\xe2\xac\xd1\xa2\xe0\xc2\x3c\x12\x44\x84\x4d\xac\xf8\x65\x27\x16\x30\x2c\x20\x32\xf9\xc1\x14\x67\x9e\xd2\x6b\x3e\xe3\xab\x4a\x7b\x18\xbc\x4e\x30\x71\xf0\x97\x7d\xb5\x7c\xd0\xac\x68\xc0\x72\x7a\x09\xb4\xf1\x25\xfb\x64\xaf\x28\x50\xb2\x6c\x8a\x48\x42\x63\x33\x4e\x2d\xa9\x02\xd7\x44\x73\x70\x44\xe7\x9a\xb1\xcf\x5b\x2f\x93\xa0\x22\xb6\x3d\x40\xcd"}, -{{0x5f,0xe9,0xc3,0x96,0x0e,0xd5,0xbd,0x37,0x4c,0xc9,0x4d,0x42,0x35,0x7e,0x6a,0x24,0xdc,0x7e,0x30,0x60,0x78,0x8f,0x72,0x63,0x65,0xde,0xfa,0xcf,0x13,0xcd,0x12,0xda,},{0x0c,0xe7,0xb1,0x55,0xc8,0xb2,0x0e,0xbd,0xaa,0xcd,0xc2,0xaa,0x23,0x62,0x7e,0x34,0xb1,0xf9,0xac,0xe9,0x80,0x65,0x0a,0x25,0x30,0xc7,0x60,0x7d,0x04,0x81,0x4e,0xb4,},{0x37,0x9f,0x9c,0x54,0xc4,0x13,0xaf,0x0d,0x19,0x2e,0x9b,0xc7,0x36,0xb2,0x9d,0xa9,0xd5,0x21,0xe7,0xba,0x78,0x41,0xd3,0x09,0xf9,0xbc,0xc1,0xe7,0x42,0xec,0x43,0x08,0xfe,0x9f,0x7b,0xa5,0x1e,0x0b,0x22,0xae,0xd4,0x87,0xcb,0x4a,0xa3,0x91,0x3b,0x9b,0xeb,0xfb,0x3a,0xac,0xd3,0x8f,0x40,0x39,0xf9,0xbb,0xbe,0xbe,0x1a,0xd8,0x00,0x02,},"\xc9\x49\x0d\x83\xd9\xc3\xa9\x37\x0f\x06\xc9\x1a\xf0\x01\x68\x5a\x02\xfe\x49\xb5\xca\x66\x77\x33\xff\xf1\x89\xee\xe8\x53\xec\x16\x67\xa6\xc1\xb6\xc7\x87\xe9\x24\x48\x12\xd2\xd5\x32\x86\x6a\xb7\x4d\xfc\x87\x0d\x6f\x14\x03\x3b\x6b\xcd\x39\x85\x2a\x39\x00\xf8\xf0\x8c\xd9\x5a\x74\xcb\x8c\xbe\x02\xb8\xb8\xb5\x1e\x99\x3a\x06\xad\xfe\xbd\x7f\xc9\x85\x4a\xe5\xd2\x9f\x4d\xf9\x64\x28\x71\xd0\xc5\xe4\x70\xd9\x03\xcf\xbc\xbd\x5a\xdb\x32\x75\x62\x8f\x28\xa8\x0b\xf8\xc0\xf0\x37\x66\x87\xda\xe6\x73\xbf\x7a\x85\x47\xe8\x0d\x4a\x98\x55\xae\x25\x72\xfc\x2b\x20\x5d\xc8\xa1\x98\x01\x6d\xdc\x9b\x50\x99\x5f\x5b\x39\xf3\x68\xf5\x40\x50\x4a\x55\x18\x03\xd6\xdd\x5f\x87\x48\x28\xe5\x54\x1d\xed\x05\x28\x94\xd9\xe2\xdc\x5e\x6a\xa3\x51\x08\x7e\x79\x0c\x0d\xd5\xd9\xc4\xde\xcb\x21\x7e\x4d\xb8\x1c\x98\xa1\x84\xb2\x64\xe6\xda\xea\xc0\xf1\x1e\x07\x4c\xae\x2b\xfc\x89\x9f\x54\xb4\x19\xc6\x5d\xcc\x22\x66\x4a\x91\x5f\xbf\xff\xac\x35\xce\xe0\xf2\x86\xeb\x7b\x14\x49\x33\xdb\x93\x3e\x16\xc4\xbc\xb6\x50\xd5\x37\x72\x24\x89\xde\x23\x63\x73\xfd\x8d\x65\xfc\x86\x11\x8b\x6d\xef\x37\xca\x46\x08\xbc\x6c\xe9\x27\xb6\x54\x36\xff\xda\x7f\x02\xbf\xbf\x88\xb0\x45\xae\x7d\x2c\x2b\x45\xa0\xb3\x0c\x8f\x2a\x04\xdf\x95\x32\x21\x08\x8c\x55\x5f\xe9\xa5\xdf\x26\x09\x82\xa3\xd6\x4d\xf1\x94\xee\x95\x2f\xa9\xa9\x8c\x31\xb9\x64\x93\xdb\x61\x80\xd1\x3d\x67\xc3\x67\x16\xf9\x5f\x8c\x0b\xd7\xa0\x39\xad\x99\x06\x67\xca\x34\xa8\x3a\xc1\xa1\x8c\x37\xdd\x7c\x77\x36\xaa\x6b\x9b\x6f\xc2\xb1\xac\x0c\xe1\x19\xef\x77"}, -{{0xec,0x2f,0xa5,0x41,0xac,0x14,0xb4,0x14,0x14,0x9c,0x38,0x25,0xea,0xa7,0x00,0x1b,0x79,0x5a,0xa1,0x95,0x7d,0x40,0x40,0xdd,0xa9,0x25,0x73,0x90,0x4a,0xfa,0x7e,0xe4,},{0x71,0xb3,0x63,0xb2,0x40,0x84,0x04,0xd7,0xbe,0xec,0xde,0xf1,0xe1,0xf5,0x11,0xbb,0x60,0x84,0x65,0x8b,0x53,0x2f,0x7e,0xa6,0x3d,0x4e,0x3f,0x5f,0x01,0xc6,0x1d,0x31,},{0x84,0xd1,0x8d,0x56,0xf9,0x64,0xe3,0x77,0x67,0x59,0xbb,0xa9,0x2c,0x51,0x0c,0x2b,0x6d,0x57,0x45,0x55,0xc3,0xcd,0xda,0xde,0x21,0x2d,0xa9,0x03,0x74,0x55,0x49,0x91,0xe7,0xd7,0x7e,0x27,0x8d,0x63,0xe3,0x46,0x93,0xe1,0x95,0x80,0x78,0xcc,0x36,0x85,0xf8,0xc4,0x1c,0x1f,0x53,0x42,0xe3,0x51,0x89,0x96,0x38,0xef,0x61,0x21,0x14,0x01,},"\x27\x49\xfc\x7c\x4a\x72\x9e\x0e\x0a\xd7\x1b\x5b\x74\xeb\x9f\x9c\x53\x4e\xbd\x02\xff\xc9\xdf\x43\x74\xd8\x13\xbd\xd1\xae\x4e\xb8\x7f\x13\x50\xd5\xfd\xc5\x63\x93\x45\x15\x77\x17\x63\xe6\xc3\x3b\x50\xe6\x4e\x0c\xd1\x14\x57\x30\x31\xd2\x18\x6b\x6e\xca\x4f\xc8\x02\xcd\xdc\x7c\xc5\x1d\x92\xa6\x13\x45\xa1\x7f\x6a\xc3\x8c\xc7\x4d\x84\x70\x7a\x51\x56\xbe\x92\x02\xde\xe3\x44\x46\x52\xe7\x9b\xae\x7f\x0d\x31\xbd\x17\x56\x79\x61\xf6\x5d\xd0\x1a\x8e\x4b\xee\x38\x33\x19\x38\xce\x4b\x2b\x55\x06\x91\xb9\x9a\x4b\xc3\xc0\x72\xd1\x86\xdf\x4b\x33\x44\xa5\xc8\xfb\xfb\xb9\xfd\x2f\x35\x5f\x61\x07\xe4\x10\xc3\xd0\xc7\x98\xb6\x8d\x3f\xb9\xc6\xf7\xab\x5f\xe2\x7e\x70\x87\x1e\x86\x76\x76\x98\xfe\x35\xb7\x7e\xad\x4e\x43\x5a\x94\x02\xcc\x9e\xd6\xa2\x65\x7b\x05\x9b\xe0\xa2\x10\x03\xc0\x48\xbb\xf5\xe0\xeb\xd9\x3c\xbb\x2e\x71\xe9\x23\xcf\x5c\x72\x8d\x17\x58\xcd\x81\x7a\xd7\x4b\x45\x4a\x88\x71\x26\xd6\x53\xb9\x5a\x7f\x25\xe5\x29\x3b\x76\x8c\x9f\xc5\xa9\xc3\x5a\x23\x72\xe3\x74\x1b\xc9\x0f\xd6\x63\x01\x42\x7b\x10\x82\x4b\xb4\xb1\xe9\x11\x0b\xfb\xa8\x4c\x21\xa4\x0e\xb8\xfe\xd4\x49\x7e\x91\xdc\x3f\xfd\x04\x38\xc5\x14\xc0\xa8\xcb\x4c\xac\x6a\xd0\x25\x6b\xf1\x1d\x5a\xa7\xa9\xc7\xc0\x0b\x66\x9b\x01\x5b\x0b\xf8\x14\x25\xa2\x14\x13\xe2\xff\xb6\xed\xc0\xbd\x78\xe3\x85\xc4\x4f\xd7\x45\x58\xe5\x11\xc2\xc2\x5f\xee\x1f\xec\x18\xd3\x99\x0b\x86\x90\x30\x0f\xa7\x11\xe9\x3d\x98\x54\x66\x8f\x01\x87\x06\x5e\x76\xe7\x11\x3a\xe7\x63\xc3\x0d\xdd\x86\x72\x0b\x55\x46\xa6\xc3\xc6\xf1\xc4\x3b\xc6\x7b\x14"}, -{{0x61,0x32,0x69,0x2a,0x5e,0xf2,0x7b,0xf4,0x76,0xb1,0xe9,0x91,0xe6,0xc4,0x31,0xa8,0xc7,0x64,0xf1,0xae,0xbd,0x47,0x02,0x82,0xdb,0x33,0x21,0xbb,0x7c,0xb0,0x9c,0x20,},{0x7a,0x2d,0x16,0x61,0x84,0xf9,0xe5,0xf7,0x3b,0xea,0x45,0x44,0x86,0xb0,0x41,0xce,0xb5,0xfc,0x23,0x14,0xa7,0xbd,0x59,0xcb,0x71,0x8e,0x79,0xf0,0xec,0x98,0x9d,0x84,},{0xeb,0x67,0x7f,0x33,0x47,0xe1,0xa1,0xea,0x92,0x9e,0xfd,0xf6,0x2b,0xf9,0x10,0x5a,0x6c,0x8f,0x49,0x93,0x03,0x3b,0x4f,0x6d,0x03,0xcb,0x0d,0xbf,0x9c,0x74,0x2b,0x27,0x07,0x04,0xe3,0x83,0xab,0x7c,0x06,0x76,0xbd,0xb1,0xad,0x0c,0xe9,0xb1,0x66,0x73,0x08,0x3c,0x96,0x02,0xec,0x10,0xae,0x1d,0xd9,0x8e,0x87,0x48,0xb3,0x36,0x44,0x0b,},"\xa9\xc0\x86\x16\x65\xd8\xc2\xde\x06\xf9\x30\x1d\xa7\x0a\xfb\x27\xb3\x02\x4b\x74\x4c\x6b\x38\xb2\x42\x59\x29\x4c\x97\xb1\xd1\xcb\x4f\x0d\xcf\x75\x75\xa8\xed\x45\x4e\x2f\x09\x80\xf5\x03\x13\xa7\x73\x63\x41\x51\x83\xfe\x96\x77\xa9\xeb\x1e\x06\xcb\x6d\x34\xa4\x67\xcb\x7b\x07\x58\xd6\xf5\x5c\x56\x4b\x5b\xa1\x56\x03\xe2\x02\xb1\x88\x56\xd8\x9e\x72\xa2\x3a\xb0\x7d\x88\x53\xff\x77\xda\x7a\xff\x1c\xae\xbd\x79\x59\xf2\xc7\x10\xef\x31\xf5\x07\x8a\x9f\x2c\xda\xe9\x26\x41\xa1\xcc\x5f\x74\xd0\xc1\x43\xec\x42\xaf\xba\xa5\xf3\x78\xa9\xe1\x0d\x5b\xf7\x45\x87\xfa\x5f\x49\xc1\x56\x23\x32\x47\xda\xfd\x39\x29\xac\xde\x88\x8d\xc6\x84\x33\x7e\x40\xcd\xc5\x93\x2e\x7e\xb7\x3f\xfc\xc9\x0b\x85\xc0\xad\x46\x04\x16\x69\x1a\xef\xbd\x7e\xfd\x07\xb6\x57\xc3\x50\x94\x6a\x0e\x36\x6b\x37\xa6\xc8\x08\x9a\xba\x5c\x5f\xe3\xbb\xca\x06\x4a\xfb\xe9\xd4\x7f\xbc\x83\x91\x4a\xf1\xcb\x43\xc2\xb2\xef\xa9\x8e\x0a\x43\xbe\x32\xba\x82\x32\x02\x00\x1d\xef\x36\x81\x72\x51\xb6\x5f\x9b\x05\x06\xce\xf6\x68\x36\x42\xa4\x6e\xd6\x12\xf8\xca\x81\xee\x97\xbb\x04\xd3\x17\xb5\x17\x34\x3a\xde\x2b\x77\x12\x6d\x1f\x02\xa8\x7b\x76\x04\xc8\x65\x3b\x67\x48\xcf\x54\x88\xfa\x6d\x43\xdf\x80\x9f\xaa\x19\xe6\x92\x92\xd3\x8c\x5d\x39\x7d\xd8\xe2\x0c\x7a\xf7\xc5\x33\x4e\xc9\x77\xf5\x01\x0a\x0f\x7c\xb5\xb8\x94\x79\xca\x06\xdb\x4d\x12\x62\x7f\x06\x7d\x6c\x42\x18\x6a\x6b\x1f\x87\x42\xf3\x6a\xe7\x09\xba\x72\x0e\x3c\xd8\x98\x11\x66\x66\xd8\x1b\x19\x0b\x9b\x9d\x2a\x72\x20\x2c\xb6\x90\xa0\x3f\x33\x10\x42\x9a\x71\xdc\x04\x8c\xde"}, -{{0xf2,0x19,0xb2,0x10,0x11,0x64,0xaa,0x97,0x23,0xbd,0xe3,0xa7,0x34,0x6f,0x68,0xa3,0x50,0x61,0xc0,0x1f,0x97,0x82,0x07,0x25,0x80,0xba,0x32,0xdf,0x90,0x3b,0xa8,0x91,},{0xf6,0x6b,0x92,0x0d,0x5a,0xa1,0xa6,0x08,0x54,0x95,0xa1,0x48,0x05,0x39,0xbe,0xba,0x01,0xff,0xe6,0x0e,0x6a,0x63,0x88,0xd1,0xb2,0xe8,0xed,0xa2,0x33,0x55,0x81,0x0e,},{0x17,0xf0,0x12,0x7c,0xa3,0xba,0xfa,0x5f,0x4e,0xe9,0x59,0xcd,0x60,0xf7,0x72,0xbe,0x87,0xa0,0x03,0x49,0x61,0x51,0x7e,0x39,0xa0,0xa1,0xd0,0xf4,0xb9,0xe2,0x6d,0xb1,0x33,0x6e,0x60,0xc8,0x2b,0x35,0x2c,0x4c,0xba,0xcd,0xbb,0xd1,0x17,0x71,0xc3,0x77,0x4f,0x8c,0xc5,0xa1,0xa7,0x95,0xd6,0xe4,0xf4,0xeb,0xd5,0x1d,0xef,0x36,0x77,0x0b,},"\x01\x55\x77\xd3\xe4\xa0\xec\x1a\xb2\x59\x30\x10\x63\x43\xff\x35\xab\x4f\x1e\x0a\x8a\x2d\x84\x4a\xad\xbb\x70\xe5\xfc\x53\x48\xcc\xb6\x79\xc2\x29\x5c\x51\xd7\x02\xaa\xae\x7f\x62\x73\xce\x70\x29\x7b\x26\xcb\x7a\x25\x3a\x3d\xb9\x43\x32\xe8\x6a\x15\xb4\xa6\x44\x91\x23\x27\x91\xf7\xa8\xb0\x82\xee\x28\x34\xaf\x30\x40\x0e\x80\x46\x47\xa5\x32\xe9\xc4\x54\xd2\xa0\xa7\x32\x01\x30\xab\x6d\x4d\x86\x00\x73\xa3\x46\x67\xac\x25\xb7\xe5\xe2\x74\x7b\xa9\xf5\xc9\x45\x94\xfb\x68\x37\x7a\xe2\x60\x36\x9c\x40\x71\x3b\x4e\x32\xf2\x31\x95\xbf\x91\xd3\xd7\xf1\xa2\x71\x9b\xf4\x08\xaa\xd8\xd8\xa3\x47\xb1\x12\xe8\x4b\x11\x88\x17\xcb\x06\x51\x33\x44\x02\x17\x63\x03\x52\x72\xa7\xdb\x72\x8a\x0c\xcd\xaa\x94\x9c\x61\x71\x5d\x07\x64\x14\x0b\x3e\x8c\x01\xd2\x0f\xf1\x59\x3c\x7f\x2d\x55\xc4\xe8\x2a\x1c\x0c\xb1\xea\x58\x44\x2b\xf8\x0a\x74\x1b\xca\x91\xf5\x8a\xb0\x58\x1b\x49\x8e\xe9\xfe\x3c\x92\xca\x65\x41\x48\xef\x75\x31\x35\x43\xd1\xaf\xf3\x82\xbe\xfe\x1a\x93\xb0\x21\x90\xce\x01\x02\x17\x51\x58\xe2\x07\x1d\x02\xba\xca\xd8\xdb\xe9\xfb\x94\x0f\xcb\x61\x0c\x10\x5a\xd5\x2c\x80\xfe\xb1\xec\x4e\x52\x4f\x4c\x0e\xc7\x98\x3e\x9c\xe6\x96\xfa\x4f\xcf\x4b\xf0\x51\x4b\x8f\x04\x32\xb1\x7d\x54\x48\xfc\x42\x6f\xea\x2b\x01\xac\x7b\x26\xc2\xae\xd7\x69\x92\x75\x34\xda\x22\x57\x6f\xc1\xbb\xa7\x26\xe9\xd6\x5b\xe0\x1b\x59\xf6\x0a\x64\x8a\xce\x2f\xc3\xe5\xe2\x75\x78\x9f\xa6\x37\xcb\xbd\x84\xbe\x3d\x6a\xc2\x44\x57\xa6\x29\x2c\xd6\x56\xc7\xb5\x69\xa5\x2f\xfe\xa7\x91\x6b\x8d\x04\xb4\xf4\xa7\x5b\xe7\xac\x95\x14\x2f"}, -{{0xfc,0x18,0x00,0x35,0xae,0xc0,0xf5,0xed,0xe7,0xbd,0xa9,0x3b,0xf7,0x7a,0xde,0x7a,0x81,0xed,0x06,0xde,0x07,0xee,0x2e,0x3a,0xa8,0x57,0x6b,0xe8,0x16,0x08,0x61,0x0a,},{0x4f,0x21,0x5e,0x94,0x8c,0xae,0x24,0x3e,0xe3,0x14,0x3b,0x80,0x28,0x2a,0xd7,0x92,0xc7,0x80,0xd2,0xa6,0xb7,0x50,0x60,0xca,0x1d,0x29,0x0c,0xa1,0xa8,0xe3,0x15,0x1f,},{0xa4,0x3a,0x71,0xc3,0xa1,0x9c,0x35,0x66,0x0d,0xae,0x6f,0x31,0xa2,0x54,0xb8,0xc0,0xea,0x35,0x93,0xfc,0x8f,0xca,0x74,0xd1,0x36,0x40,0x01,0x2b,0x9e,0x94,0x73,0xd4,0xaf,0xe0,0x70,0xdb,0x01,0xe7,0xfb,0x39,0x9b,0xf4,0xca,0x60,0x70,0xe0,0x62,0x18,0x00,0x11,0x28,0x5a,0x67,0xdd,0x68,0x58,0xb7,0x61,0xe4,0x6c,0x6b,0xd3,0x20,0x04,},"\xb5\xe8\xb0\x16\x25\x66\x4b\x22\x23\x39\xe0\xf0\x5f\x93\xa9\x90\xba\x48\xb5\x6a\xe6\x54\x39\xa1\x75\x20\x93\x2d\xf0\x11\x72\x1e\x28\x4d\xbe\x36\xf9\x86\x31\xc0\x66\x51\x00\x98\xa6\x8d\x7b\x69\x2a\x38\x63\xe9\x9d\x58\xdb\x76\xca\x56\x67\xc8\x04\x3c\xb1\x0b\xd7\xab\xba\xf5\x06\x52\x9f\xbb\x23\xa5\x16\x6b\xe0\x38\xaf\xfd\xb9\xa2\x34\xc4\xf4\xfc\xf4\x3b\xdd\xd6\xb8\xd2\xce\x77\x2d\xd6\x53\xed\x11\x5c\x09\x5e\x23\x2b\x26\x9d\xd4\x88\x8d\x23\x68\xcb\x1c\x66\xbe\x29\xdd\x38\x3f\xca\x67\xf6\x67\x65\xb2\x96\x56\x4e\x37\x55\x5f\x0c\x0e\x48\x45\x04\xc5\x91\xf0\x06\xea\x85\x33\xa1\x25\x83\xad\x2e\x48\x31\x8f\xf6\xf3\x24\xec\xaf\x80\x4b\x1b\xae\x04\xaa\x89\x67\x43\xe6\x7e\xf6\x1c\xa3\x83\xd5\x8e\x42\xac\xfc\x64\x10\xde\x30\x77\x6e\x3b\xa2\x62\x37\x3b\x9e\x14\x41\x94\x39\x55\x10\x1a\x4e\x76\x82\x31\xad\x9c\x65\x29\xef\xf6\x11\x8d\xde\x5d\xf0\x2f\x94\xb8\xd6\xdf\x2d\x99\xf2\x78\x63\xb5\x17\x24\x3a\x57\x9e\x7a\xaf\xf3\x11\xea\x3a\x02\x82\xe4\x7c\xa8\x76\xfa\xbc\x22\x80\xfc\xe7\xad\xc9\x84\xdd\x0b\x30\x88\x5b\x16\x50\xf1\x47\x1d\xfc\xb0\x52\x2d\x49\xfe\xc7\xd0\x42\xf3\x2a\x93\xbc\x36\x8f\x07\x60\x06\xea\x01\xec\x1c\x74\x12\xbf\x66\xf6\x2d\xc8\x8d\xe2\xc0\xb7\x47\x01\xa5\x61\x4e\x85\x5e\x9f\xa7\x28\xfb\x1f\x11\x71\x38\x5f\x96\xaf\xbd\xe7\x0d\xea\x02\xe9\xaa\x94\xdc\x21\x84\x8c\x26\x30\x2b\x50\xae\x91\xf9\x69\x3a\x18\x64\xe4\xe0\x95\xae\x03\xcd\xc2\x2a\xd2\x8a\x0e\xb7\xdb\x59\x67\x79\x24\x67\x12\xfa\xb5\xf5\xda\x32\x7e\xfe\xc3\xe7\x96\x12\xde\x0a\x6c\xca\xa5\x36\x75\x9b\x8e"}, -{{0xa2,0x83,0x6a,0x65,0x42,0x79,0x12,0x12,0x2d,0x25,0xdc,0xdf,0xc9,0x9d,0x70,0x46,0xfe,0x9b,0x53,0xd5,0xc1,0xbb,0x23,0x61,0x7f,0x11,0x89,0x0e,0x94,0xca,0x93,0xed,},{0x8c,0x12,0xbd,0xa2,0x14,0xc8,0xab,0xb2,0x28,0x6a,0xcf,0xfb,0xf8,0x11,0x24,0x25,0x04,0x0a,0xab,0x9f,0x4d,0x8b,0xb7,0x87,0x0b,0x98,0xda,0x01,0x59,0xe8,0x82,0xf1,},{0xe6,0xa9,0xa6,0xb4,0x36,0x55,0x9a,0x43,0x20,0xc4,0x5c,0x0c,0x2c,0x4a,0x2a,0xed,0xec,0xb9,0x0d,0x41,0x6d,0x52,0xc8,0x26,0x80,0xac,0x73,0x30,0xd0,0x62,0xae,0xbe,0xf3,0xe9,0xac,0x9f,0x2c,0x5f,0xfa,0x45,0x5c,0x9b,0xe1,0x13,0x01,0x3a,0x2b,0x28,0x2e,0x56,0x00,0xfd,0x30,0x64,0x35,0xad,0xa8,0x3b,0x1e,0x48,0xba,0x2a,0x36,0x05,},"\x81\x3d\x60\x61\xc5\x6e\xae\x0f\xf5\x30\x41\xc0\x24\x4a\xa5\xe2\x9e\x13\xec\x0f\x3f\xb4\x28\xd4\xbe\xb8\xa9\x9e\x04\xbc\xa8\xc4\x1b\xdd\xb0\xdb\x94\x5f\x48\x7e\xfe\x38\xf2\xfc\x14\xa6\x28\xfa\xfa\x24\x62\xf8\x60\xe4\xe3\x42\x50\xeb\x4e\x93\xf1\x39\xab\x1b\x74\xa2\x61\x45\x19\xe4\x1e\xe2\x40\x3b\xe4\x27\x93\x0a\xb8\xbc\x82\xec\x89\xce\xaf\xb6\x09\x05\xbd\x4d\xdb\xbd\x13\xbd\xb1\x96\x54\x31\x4f\xc9\x23\x73\x14\x0b\x96\x2e\x22\x58\xe0\x38\xd7\x1b\x9e\xc6\x6b\x84\xef\x83\x19\xe0\x35\x51\xcb\x70\x7e\x74\x7f\x6c\x40\xad\x47\x6f\xbe\xfd\xce\x71\xf3\xa7\xb6\x7a\x1a\xf1\x86\x9b\xc6\x44\x06\x86\xe7\xe0\x85\x5e\x4f\x36\x9d\x1d\x88\xb8\x09\x9f\xba\x54\x71\x46\x78\x62\x7b\xba\x1a\xff\x41\xe7\x70\x7b\xc9\x7e\xdd\xf8\x90\xb0\xc0\x8d\xce\x3e\x98\x00\xd2\x4c\x6f\x61\x09\x2c\xe2\x8d\x48\x1b\x5d\xea\x5c\x09\x6c\x55\xd7\x2f\x89\x46\x00\x91\x31\xfb\x96\x8e\x2b\xc8\xa0\x54\xd8\x25\xad\xab\x76\x74\x0d\xcf\x0d\x75\x8c\x8b\xf5\x4f\xf3\x86\x59\xe7\x1b\x32\xbf\xe2\xe6\x15\xaa\xab\xb0\xf5\x29\x30\x85\x64\x9c\xf6\x0b\x98\x47\xbc\x62\x01\x1c\xe3\x87\x8a\xf6\x28\x98\x4a\x58\x40\xa4\xad\x5d\xae\x37\x02\xdb\x36\x7d\xa0\xf8\xa1\x65\xfe\xd0\x51\x7e\xb5\xc4\x42\xb0\x14\x53\x30\x24\x1b\x97\xee\xca\x73\x3b\xa6\x68\x8b\x9c\x12\x9a\x61\xcd\x12\x36\xaf\xf0\xe2\x7b\xcf\x98\xc2\x8b\x0f\xbe\xea\x55\xa3\xd7\xc7\x19\x3d\x64\x4b\x27\x49\xf9\x86\xbd\x46\xaf\x89\x38\xe8\xfa\xae\xaf\xbd\x9c\xec\x36\x12\xab\x00\x5b\xd7\xc3\xee\xaf\xe9\xa3\x12\x79\xca\x61\x02\x56\x06\x66\xba\x16\x13\x6f\xf1\x45\x2f\x85\x0a\xdb"}, -{{0xf0,0x51,0xaf,0x42,0x6d,0x0c,0x32,0x82,0xfa,0xfc,0x8b,0xf9,0x12,0xad,0xe1,0xc2,0x42,0x11,0xa9,0x5a,0xd2,0x00,0xe1,0xee,0xf5,0x49,0x32,0x0e,0x1c,0xb1,0xa2,0x52,},{0xfa,0x87,0x95,0x5e,0x0e,0xa1,0x3d,0xde,0x49,0xd8,0x3d,0xc2,0x2e,0x63,0xa2,0xbd,0xf1,0x07,0x67,0x25,0xc2,0xcc,0x7f,0x93,0xc7,0x65,0x11,0xf2,0x8e,0x79,0x44,0xf2,},{0xb8,0xf7,0x13,0x57,0x8a,0x64,0x46,0x67,0x19,0xac,0xeb,0x43,0x2f,0xce,0x30,0x2a,0x87,0xcf,0x06,0x6b,0xf3,0xe1,0x02,0xa3,0x50,0x61,0x69,0x21,0xa8,0x40,0x96,0x4b,0xfc,0x7e,0x68,0x5d,0x8f,0xd1,0x74,0x55,0xac,0x3e,0xb4,0x86,0x1e,0xdc,0xb8,0x97,0x9d,0x35,0xe3,0xa4,0xbd,0x82,0xa0,0x78,0xcd,0x70,0x77,0x21,0xd7,0x33,0x40,0x0e,},"\xb4\x8d\x9f\x84\x76\x2b\x3b\xcc\x66\xe9\x6d\x76\xa6\x16\xfa\x8f\xe8\xe0\x16\x95\x25\x1f\x47\xcf\xc1\xb7\xb1\x7d\x60\xdc\x9f\x90\xd5\x76\xef\x64\xee\x7d\x38\x85\x04\xe2\xc9\x07\x96\x38\x16\x5a\x88\x96\x96\x47\x1c\x98\x9a\x87\x6f\x8f\x13\xb6\x3b\x58\xd5\x31\xfe\xa4\xdd\x12\x29\xfc\x63\x16\x68\xa0\x47\xbf\xae\x2d\xa2\x81\xfe\xae\x1b\x6d\xe3\xeb\xe2\x80\xab\xe0\xa8\x2e\xe0\x0f\xbf\xdc\x22\xce\x2d\x10\xe0\x6a\x04\x92\xff\x14\x04\xdf\xc0\x94\xc4\x0b\x20\x3b\xf5\x57\x21\xdd\x78\x7e\xd4\xe9\x1d\x55\x17\xaa\xf5\x8d\x3b\xdd\x35\xd4\x4a\x65\xae\x6b\xa7\x56\x19\xb3\x39\xb6\x50\x51\x8c\xef\xcc\x17\x49\x3d\xe2\x7a\x3b\x5d\x41\x78\x8f\x87\xed\xbd\xe7\x26\x10\xf1\x81\xbf\x06\xe2\x08\xe0\xeb\x7c\xdf\xe8\x81\xd9\x1a\x2d\x6c\xc7\x7a\xa1\x9c\x0f\xcf\x33\x0f\xed\xb4\x46\x75\xd8\x00\xeb\x8c\xff\x95\x05\xd8\x88\x75\x44\xa5\x03\xcb\xe3\x73\xc4\x84\x7b\x19\xe8\xf3\x99\x57\x26\xef\xd6\x64\x98\x58\x59\x5c\x57\xcc\xaf\x0c\xbc\x9e\xb2\x5d\xe8\x3b\xa0\x46\xbc\x9f\x18\x38\xac\x7b\x89\x53\xdd\x81\xb8\x1a\xc0\xf6\x8d\x0e\x93\x38\xcb\x55\x40\x25\x52\xaf\xb6\xbc\x16\x94\x93\x51\xb9\x26\xd1\x51\xa8\x2e\xfc\x69\x5e\x8d\x7d\xa0\xdd\x55\x09\x93\x66\x78\x97\x18\xcc\xbf\x36\x03\x0b\xd2\xc3\xc1\x09\x39\x9b\xe2\x6c\xdb\x8b\x9e\x2a\x15\x5f\x3b\x2c\xb1\xbf\xa7\x1a\xb6\x9a\x23\x62\x5a\x4a\xc1\x18\xfe\x91\xcb\x2c\x19\x78\x8c\xf5\x2a\x71\xd7\x30\xd5\x76\xb4\x21\xd9\x69\x82\xa5\x1a\x29\x91\xda\xec\x44\x0c\xda\x7e\x6c\xc3\x28\x2b\x83\x12\x71\x42\x78\xb8\x19\xbf\xe2\x38\x7e\xb9\x6a\xa9\x1d\x40\x17\x30\x34\xf4\x28"}, -{{0xa1,0x03,0xe9,0x26,0x72,0xc6,0x5f,0x81,0xea,0x5d,0xa1,0xff,0xf1,0xa4,0x03,0x87,0x88,0x47,0x9e,0x94,0x1d,0x50,0x3a,0x75,0x6f,0x4a,0x75,0x52,0x01,0xa5,0x7c,0x1d,},{0xee,0x63,0xa5,0xb6,0x96,0x41,0x21,0x7a,0xcb,0xaf,0x33,0x39,0xda,0x82,0x9e,0xc0,0x71,0xb9,0x93,0x1e,0x59,0x87,0x15,0x35,0x14,0xd3,0x01,0x40,0x83,0x7a,0x7a,0xf4,},{0x2a,0xa2,0x03,0x5c,0x2c,0xe5,0xb5,0xe6,0xae,0x16,0x1e,0x16,0x8f,0x3a,0xd0,0xd6,0x59,0x2b,0xcf,0x2c,0x4a,0x04,0x9d,0x3e,0xd3,0x42,0xfc,0xeb,0x56,0xbe,0x9c,0x7c,0xb3,0x72,0x02,0x75,0x73,0xae,0x01,0x78,0xe8,0x87,0x8e,0xbe,0xfc,0xa7,0xb0,0x30,0x32,0x7b,0x8a,0xad,0x41,0x85,0x7d,0xe5,0x8c,0xb7,0x8e,0x1a,0x00,0xcb,0xac,0x05,},"\xb1\x98\x4e\x9e\xec\x08\x5d\x52\x4c\x1e\xb3\xb9\x5c\x89\xc8\x4a\xe0\x85\xbe\x5d\xc6\x5c\x32\x6e\x19\x02\x5e\x12\x10\xa1\xd5\x0e\xdb\xbb\xa5\xd1\x37\x0c\xf1\x5d\x68\xd6\x87\xeb\x11\x32\x33\xe0\xfb\xa5\x0f\x94\x33\xc7\xd3\x58\x77\x39\x50\xc6\x79\x31\xdb\x82\x96\xbb\xcb\xec\xec\x88\x8e\x87\xe7\x1a\x2f\x75\x79\xfa\xd2\xfa\x16\x2b\x85\xfb\x97\x47\x3c\x45\x6b\x9a\x5c\xe2\x95\x66\x76\x96\x9c\x7b\xf4\xc4\x56\x79\x08\x5b\x62\xf2\xc2\x24\xfc\x7f\x45\x87\x94\x27\x3f\x6d\x12\xc5\xf3\xe0\xd0\x69\x51\x82\x4d\x1c\xca\x3e\x2f\x90\x45\x59\xed\x28\xe2\x86\x8b\x36\x6d\x79\xd9\x4d\xc9\x86\x67\xb9\xb5\x92\x42\x68\xf3\xe3\x9b\x12\x91\xe5\xab\xe4\xa7\x58\xf7\x70\x19\xda\xcb\xb2\x2b\xd8\x19\x6e\x0a\x83\xa5\x67\x76\x58\x83\x6e\x96\xca\x56\x35\x05\x5a\x1e\x63\xd6\x5d\x03\x6a\x68\xd8\x7a\xc2\xfd\x28\x3f\xdd\xa3\x90\x31\x99\x09\xc5\xcc\x76\x80\x36\x88\x48\x87\x3d\x59\x7f\x29\x8e\x0c\x61\x72\x30\x80\x30\xff\xd4\x52\xbb\x13\x63\x61\x7b\x31\x6e\xd7\xcd\x94\x9a\x16\x5d\xc8\xab\xb5\x3f\x99\x1a\xef\x3f\x3e\x95\x02\xc5\xdf\xe4\x75\x6b\x7c\x6b\xfd\xfe\x89\xf5\xe0\x0f\xeb\xdd\x6a\xfb\x04\x02\x81\x8f\x11\xcf\x8d\x1d\x58\x64\xfe\x9d\xa1\xb8\x6e\x39\xaa\x93\x58\x31\x50\x6c\xf2\x40\x0e\xa7\xed\x75\xbd\x95\x33\xb2\x3e\x20\x2f\xe8\x75\xd7\xd9\x63\x8c\x89\xd1\x1c\xb2\xd6\xe6\x02\x1a\xe6\xbd\x27\xc7\x75\x48\x10\xd3\x5c\xd3\xa6\x14\x94\xf2\x7b\x16\xfc\x79\x4e\x2c\xd2\xf0\xd3\x45\x3a\xda\x93\x38\x65\xdb\x78\xc5\x79\x57\x1f\x8f\xc5\xc5\xc6\xbe\x8e\xaf\xfc\xe6\xa8\x52\xe5\xb3\xb1\xc5\x24\xc4\x93\x13\xd4\x27\xab\xcb"}, -{{0xd4,0x7c,0x1b,0x4b,0x9e,0x50,0xcb,0xb7,0x1f,0xd0,0x7d,0x09,0x6d,0x91,0xd8,0x72,0x13,0xd4,0x4b,0x02,0x43,0x73,0x04,0x47,0x61,0xc4,0x82,0x2f,0x9d,0x9d,0xf8,0x80,},{0xf4,0xe1,0xcb,0x86,0xc8,0xca,0x2c,0xfe,0xe4,0x3e,0x58,0x59,0x4a,0x87,0x78,0x43,0x6d,0x3e,0xa5,0x19,0x70,0x4e,0x00,0xc1,0xbb,0xe4,0x8b,0xbb,0x1c,0x94,0x54,0xf8,},{0x62,0x7e,0x7c,0xa7,0xe3,0x4e,0xd6,0x33,0x1d,0x62,0xb9,0x54,0x1c,0x1e,0xa9,0xa9,0x29,0x2b,0xe7,0xb0,0xa6,0x5d,0x80,0x5e,0x26,0x6b,0x51,0x22,0x27,0x2a,0x82,0xdb,0x7d,0x76,0x5a,0xcc,0x7e,0x2a,0x29,0x0d,0x68,0x58,0x04,0x92,0x2f,0x91,0xed,0x04,0xa3,0xc3,0x82,0xc0,0x3f,0xf2,0x1a,0x17,0x68,0xf5,0x84,0x41,0x3c,0x4e,0x5f,0x00,},"\x88\xd7\x00\x9d\x51\xde\x3d\x33\x7e\xef\x0f\x21\x5e\xa6\x6a\xb8\x30\xec\x5a\x9e\x68\x23\x76\x1c\x3b\x92\xad\x93\xea\x34\x1d\xb9\x2e\xce\x67\xf4\xef\x4c\xeb\x84\x19\x4a\xe6\x92\x6c\x3d\x01\x4b\x2d\x59\x78\x1f\x02\xe0\xb3\x2f\x9a\x61\x12\x22\xcb\x9a\x58\x50\xc6\x95\x7c\xb8\x07\x9a\xe6\x4e\x08\x32\xa1\xf0\x5e\x5d\x1a\x3c\x57\x2f\x9d\x08\xf1\x43\x7f\x76\xbb\x3b\x83\xb5\x29\x67\xc3\xd4\x8c\x35\x76\x84\x88\x91\xc9\x65\x8d\x49\x59\xeb\x80\x65\x6d\x26\xcd\xba\x08\x10\x03\x7c\x8a\x18\x31\x8f\xf1\x22\xf8\xaa\x89\x85\xc7\x73\xcb\x31\x7e\xfa\x2f\x55\x7f\x1c\x38\x96\xbc\xb1\x62\xdf\x5d\x87\x68\x1b\xb7\x87\xe7\x81\x3a\xa2\xde\xa3\xb0\xc5\x64\xd6\x46\xa9\x28\x61\xf4\x44\xca\x14\x07\xef\xba\xc3\xd1\x24\x32\xcb\xb7\x0a\x1d\x0e\xaf\xfb\x11\x74\x1d\x37\x18\xfe\xde\xe2\xb8\x30\x36\x18\x9a\x6f\xc4\x5a\x52\xf7\x4f\xa4\x87\xc1\x8f\xd2\x64\xa7\x94\x5f\x6c\x9e\x44\xb0\x11\xf5\xd8\x66\x13\xf1\x93\x9b\x19\xf4\xf4\xfd\xf5\x32\x34\x05\x7b\xe3\xf0\x05\xad\x64\xee\xbf\x3c\x8f\xfb\x58\xcb\x40\x95\x6c\x43\x36\xdf\x01\xd4\x42\x4b\x70\x6a\x0e\x56\x1d\x60\x17\x08\xd1\x24\x85\xe2\x1b\xcb\x6d\x79\x9d\x8d\x1d\x04\x4b\x40\x00\x64\xec\x09\x44\x50\x14\x06\xe7\x02\x53\x94\x70\x06\xca\xbb\xdb\x2d\xd6\xbd\x8c\xee\x44\x97\x65\x3d\x91\x13\xa4\x4d\x4d\xe9\xb6\x8d\x4c\x52\x6f\xca\x0b\x9b\x0c\x18\xfe\x50\xfb\x91\x7f\xdd\x9a\x91\x4f\xb8\x16\x10\x8a\x73\xa6\xb3\xff\xf9\xe6\x54\xe6\x9c\x9c\xfe\x02\xb0\x5c\x6c\x1b\x9d\x15\xc4\xe6\x5c\xf3\x10\x18\xb8\x10\x0d\x78\x46\x33\xee\x18\x88\xee\xe3\x57\x2a\xaf\xa6\xf1\x89\xea\x22\xd0"}, -{{0xfc,0x0c,0x32,0xc5,0xeb,0x6c,0x71,0xea,0x08,0xdc,0x2b,0x30,0x0c,0xbc,0xef,0x18,0xfd,0xde,0x3e,0xa2,0x0f,0x68,0xf2,0x17,0x33,0x23,0x7b,0x4d,0xda,0xab,0x90,0x0e,},{0x47,0xc3,0x7d,0x8a,0x08,0x08,0x57,0xeb,0x87,0x77,0xa6,0xc0,0xa9,0xa5,0xc9,0x27,0x30,0x3f,0xaf,0x5c,0x32,0x09,0x53,0xb5,0xde,0x48,0xe4,0x62,0xe1,0x2d,0x00,0x62,},{0x68,0x87,0xc6,0xe2,0xb9,0x8a,0x82,0xaf,0x5e,0xe3,0xdf,0xa7,0xca,0x2c,0xb2,0x5d,0x9c,0x10,0x74,0x56,0x20,0xa8,0x29,0x56,0xac,0xba,0x85,0xcb,0x57,0xc8,0xec,0x24,0x27,0x9f,0xa4,0x2f,0x09,0x23,0x59,0xa1,0xb6,0xbb,0xea,0xfb,0xa0,0x50,0xf1,0x4b,0x62,0x88,0x20,0x9e,0x6e,0xf7,0xbc,0x1e,0x0a,0x2b,0x87,0x2c,0x11,0x38,0xf3,0x05,},"\xa7\xb1\xe2\xdb\x6b\xdd\x96\xb3\xd5\x14\x75\x60\x35\x37\xa7\x6b\x42\xb0\x4d\x7e\xbd\x24\xfe\x51\x5a\x88\x76\x58\xe4\xa3\x52\xe2\x21\x09\x33\x56\x39\xa5\x9e\x25\x34\x81\x1f\x47\x53\xb7\x02\x09\xd0\xe4\x69\x8e\x9d\x92\x60\x88\x82\x6c\x14\x68\x96\x81\xea\x00\xfa\x3a\x2f\xca\xa0\x04\x7c\xed\x3e\xf2\x87\xe6\x17\x25\x02\xb2\x15\xe5\x64\x97\x61\x4d\x86\xb4\xcb\x26\xbc\xd7\x7a\x2e\x17\x25\x09\x36\x0e\xe5\x88\x93\xd0\x1c\x0d\x0f\xb4\xd4\xab\xfe\x4d\xbd\x8d\x2a\x2f\x54\x19\x0f\xa2\xf7\x31\xc1\xce\xac\x68\x29\xc3\xdd\xc9\xbf\xb2\xff\xd7\x0c\x57\xba\x0c\x2b\x22\xd2\x32\x6f\xbf\xe7\x39\x0d\xb8\x80\x9f\x73\x54\x7f\xf4\x7b\x86\xc3\x6f\x2b\xf7\x45\x4e\x67\x8c\x4f\x1c\x0f\xa8\x70\xbd\x0e\x30\xbb\xf3\x27\x8e\xc8\xd0\xc5\xe9\xb6\x4a\xff\x0a\xf6\x4b\xab\xc1\x9b\x70\xf4\xcf\x9a\x41\xcb\x8f\x95\xd3\xcd\xe2\x4f\x45\x6b\xa3\x57\x1c\x8f\x02\x1d\x38\xe5\x91\xde\xc0\x5c\xb5\xd1\xca\x7b\x48\xf9\xda\x4b\xd7\x34\xb0\x69\xa9\xfd\x10\x65\x00\xc1\xf4\x08\xab\x7f\xe8\xe4\xa6\xe6\xf3\xed\x64\xda\x0e\xd2\x4b\x01\xe3\x3d\xf8\x47\x5f\x95\xfa\x9e\xd7\x1d\x04\xdd\x30\xb3\xcd\x82\x37\x55\xa3\x40\x1b\xf5\xaf\xae\x10\xee\x7e\x18\xec\x6f\xe6\x37\xc3\x79\x3f\xd4\x34\xb4\x8d\x71\x45\x13\x04\x47\xe0\x02\x99\x10\x10\x52\x55\x8b\x50\x65\x54\xec\x9c\x39\x9f\x62\x94\x1c\x3f\x41\x4c\xbc\x35\x2c\xaa\x34\x5b\x93\x0a\xde\xcf\xad\xda\xc9\x1e\xe5\x3d\x14\x51\xa6\x5e\x06\x20\x10\x26\x32\x5d\xe0\x7c\x93\x1f\x69\xbb\xa8\x68\xa7\xc8\x7e\xe2\x3c\x60\x4e\xc6\x79\x43\x32\x91\x7d\xfe\x2c\x5b\x69\x66\x9b\x65\x97\x06\x91\x7f\x71\xed\xdf\x96"}, -{{0xa8,0xd7,0x3d,0x63,0x9a,0x23,0xcc,0x6a,0x96,0x7e,0xf3,0x1b,0xca,0xbb,0x5d,0x06,0x3e,0x53,0xe1,0xea,0xb8,0xfc,0xc7,0xca,0xb9,0xbc,0x3a,0x17,0xfd,0xe9,0xc2,0xf8,},{0x8d,0xaa,0x9f,0x4c,0x8b,0x1a,0x44,0x69,0x1b,0xf4,0x45,0x21,0xf2,0xf7,0xca,0x45,0xdc,0x7f,0xc6,0x1f,0x6a,0x4c,0xe6,0xf9,0x8f,0xaa,0x41,0xc2,0xa7,0x49,0x77,0xd1,},{0xc4,0xdc,0xef,0x1a,0x24,0x53,0x93,0x9b,0x36,0x4b,0x34,0x02,0x50,0xc3,0x12,0x94,0x31,0x43,0x1d,0x5b,0xa3,0xf4,0x76,0x70,0xab,0x07,0xce,0x68,0x0c,0x69,0xbf,0x28,0xb6,0x78,0x62,0x7c,0x76,0xa6,0x36,0x0f,0xc4,0x0d,0xc1,0x09,0xaa,0x7d,0xea,0x37,0x1b,0x82,0x5e,0x46,0x13,0x4f,0x62,0x45,0x72,0x18,0x2a,0xcf,0x39,0x57,0xe7,0x0f,},"\xfd\x1f\xac\x3d\x53\x31\x3b\x11\xac\xd2\x9f\x5a\x83\xac\x11\x89\x6d\xab\x25\x30\xfa\x47\x86\x5b\x22\x95\xc0\xd9\x9d\xd6\x7c\x36\xed\x8e\x5f\xa5\x49\x15\x0c\x79\x4c\x55\x49\xef\xb5\xc1\xd6\x91\x14\xd5\xd6\x07\xb2\x32\x85\xb7\x21\x2a\xfa\xab\x57\x84\x6a\x54\xae\x67\xb9\xe8\x80\xe0\x7b\x65\x86\x60\x7c\xec\xf6\xd4\xee\xd5\x16\xa3\xa7\x55\x11\xfe\x36\x7d\x88\xeb\x87\x1e\x6d\x71\xb7\xd6\xaa\x13\x67\xa0\x14\x21\xb1\x08\x8f\xc2\xd7\x5e\x44\x95\x4b\x73\x62\x5c\x52\xda\x8a\x3a\x18\x3c\x60\xbe\x9d\xa6\x05\x0f\x59\xa4\x53\xca\xa5\x35\x20\x59\x36\x71\x72\x8d\x43\x18\x77\xbf\xaa\xc9\x13\xa7\x65\xfb\x6a\x56\xb7\x52\x90\xb2\xa8\xaa\xac\x34\xaf\xb9\x21\x7b\xa1\xb0\xd5\x85\x0b\xa0\xfd\xab\xf8\x09\x69\xde\xf0\xfe\xee\x79\x4c\xeb\x60\x61\x4e\x33\x68\xe6\x3e\xf2\x0e\x4c\x32\xd3\x41\xec\x9b\x03\x28\xea\x9f\xe1\x39\x20\x7e\xd7\xa6\x26\xff\x08\x94\x3b\x41\x52\x33\xdb\x7c\xfc\xc8\x45\xc9\xb6\x31\x21\xd4\xed\x52\xec\x37\x48\xab\x6a\x1f\x36\xb2\x10\x3c\x7d\xc7\xe9\x30\x3a\xce\xa4\xba\x8a\xf7\xa3\xe0\x71\x84\xfb\x49\x1e\x89\x1e\xde\x84\xf0\xdc\x41\xca\xdc\x39\x73\x02\x8e\x87\x9a\xcd\x20\x31\xaf\xc2\x9a\x16\x09\x28\x68\xe2\xc7\xf5\x39\xfc\x1b\x79\x2e\xda\xb1\x95\xa2\x5a\xb9\x83\x06\x61\x34\x6b\x39\xef\x53\x91\x5d\xe4\xaf\x52\xc4\x21\xea\xf1\x72\xe9\xda\x76\xa0\x8c\x28\x3a\x52\xdf\x90\x7f\x70\x5d\x7e\x85\x99\xc5\xba\xae\x0c\x2a\xf3\x80\xc1\xbb\x46\xf9\x34\x84\xa0\x3f\x28\x37\x43\x24\xb2\x78\x99\x2b\x50\xb7\xaf\xa0\x25\x52\xca\xfa\x50\x3f\x03\x4f\x8d\x86\x6e\x9b\x72\x02\x71\xdd\x68\xcc\xb6\x85\xa8\x5f\xff\xd1"}, -{{0x79,0xc7,0xdc,0xb7,0xd5,0x9a,0x8d,0xf6,0xb2,0xb2,0xba,0x04,0x13,0x05,0x9d,0x89,0x68,0x09,0x95,0xc2,0x0e,0x91,0x6d,0xa0,0x1b,0x8f,0x06,0x7d,0xc6,0x0c,0xde,0xb4,},{0x29,0x87,0x43,0xc7,0x39,0x18,0xbd,0x55,0x6b,0x28,0xf8,0xd4,0x82,0x4a,0x09,0xb8,0x14,0x75,0x2a,0x7a,0xea,0xe7,0xee,0x04,0x87,0x5c,0x53,0xf4,0xd6,0xb1,0x08,0xd9,},{0x7b,0x7c,0xbe,0x44,0xc7,0x71,0xe4,0x37,0x1b,0xae,0x13,0xb0,0x72,0x2b,0xab,0xcc,0x10,0x64,0x15,0x57,0x32,0x96,0x2f,0x40,0x7c,0xba,0x2a,0xcd,0x35,0x38,0x1d,0x42,0x21,0x0b,0xec,0xe8,0x22,0xf4,0x68,0x11,0x21,0xfd,0x4d,0xab,0x74,0x5a,0x1f,0x30,0x77,0x92,0x2f,0xba,0x1a,0x78,0x04,0x5b,0x71,0x29,0x02,0xba,0xcc,0xac,0x66,0x0e,},"\x5f\xe2\x02\xf5\xb3\x3b\x77\x88\x81\x0d\x25\x08\xa1\x3b\x31\x14\xd6\x9b\x85\x96\xe6\xea\xcd\xa0\x5a\x04\xa2\xeb\x59\x7f\xa3\x27\x9c\x20\x8b\x5a\x5b\x65\xda\xac\xb6\x99\xf1\x44\xe1\xd6\x60\xe7\x8e\x13\x9b\x57\x83\x31\xab\xec\x5c\x3c\x35\x33\x44\x54\xf0\x3e\x83\x2c\x8d\x6e\x29\x84\xdf\x5d\x45\x0e\xcb\x5d\x33\x58\x2a\x78\x80\x8a\x9c\x78\xf2\x6e\xbc\xd1\x24\x4e\xf5\x2e\x3f\xa6\xdc\xa1\x15\xc1\xf0\xcb\x56\xe3\x8e\xae\x0e\x5b\x39\xf5\xfd\x86\x3d\xff\xd0\xb2\xfb\x5b\x95\x8f\x2d\x73\x9d\xb3\x12\xfc\x66\x7a\x17\xb0\x31\xc4\xc9\xf8\xc5\xa2\xad\x57\x79\x84\xcc\x41\x46\xc4\x37\x58\x0e\xfd\x21\x52\x17\x3f\xe0\xd5\x78\x2c\xc2\xae\x98\x31\xa8\xd9\xa0\x41\x77\x25\x60\x18\xff\x76\x31\xe0\xb0\xd8\xa9\x9c\xb2\x8f\x00\x8b\x32\x04\x21\xe2\x7a\x74\xc3\x13\x59\x18\x86\x63\x45\x6d\x85\xe0\x98\xc1\xeb\xd2\x81\x70\x10\x97\xb6\xae\x5a\x87\x1e\x5c\xcc\x02\x05\x8a\x50\x14\x16\xcb\x91\xc1\x2c\xef\x5b\xe6\xf1\x91\x43\x70\xe5\x63\xf1\xa1\xb2\xaa\x41\xf4\xb8\xee\x84\xcd\x32\xa1\xd5\x09\xe5\x29\x78\x7d\x14\xa4\x45\x43\x8d\x80\x7e\xcd\x62\x0e\x2f\xa2\x6d\xe0\xda\x64\x26\x86\x47\x84\xd4\xa2\x8f\x54\x10\x3e\x60\x92\x83\xb9\x9e\xe9\xb2\xb6\x99\xc9\x80\xbb\xb7\x88\x2c\x3e\xa6\x8d\xdc\x90\x80\x2a\xc2\x32\xf2\xc8\xe8\x42\x91\x98\x7b\xf3\xc5\x24\x09\x21\xb5\x9c\xfa\x21\x49\x69\x31\x76\x73\xd0\xbe\x7f\x34\xb1\xca\x0e\x15\xea\x73\xc7\x17\x54\x01\xce\x55\x0b\xe1\x06\xb4\x9e\x62\xf8\xdb\x68\x69\x5e\x74\x0e\x0f\x3a\x35\x56\xa1\x9f\x3c\x8e\x6b\x91\xac\x1c\xc2\x3e\x86\x3f\xcd\x0f\x0d\x9e\xb7\x04\x7a\xa6\x31\xe0\xd2\xeb\x9b\xcc\x6b"}, -{{0xb9,0xce,0xd0,0x41,0x25,0x93,0xfe,0xfe,0xd9,0x5e,0x94,0xac,0x96,0x5e,0x5b,0x23,0xff,0x9d,0x4b,0x0e,0x79,0x7d,0xb0,0x2b,0xf4,0x97,0x99,0x4d,0x3b,0x79,0x3e,0x60,},{0xc1,0x62,0x9a,0x72,0x31,0x89,0x95,0x93,0x37,0xf5,0x53,0x52,0x01,0xe5,0xd3,0x95,0xba,0x0a,0x03,0xea,0x8c,0x17,0x66,0x0d,0x0f,0x8b,0x6f,0x6e,0x64,0x04,0xbb,0x12,},{0xf1,0xb7,0x97,0xde,0xd8,0xa6,0x94,0x2b,0x12,0x62,0x68,0x48,0x34,0x0f,0xb7,0x19,0xfc,0xdd,0xaf,0xd9,0x8f,0x33,0xe2,0x99,0x2d,0x35,0x7b,0xfd,0xd3,0x59,0x33,0xc7,0xac,0x56,0x1e,0x5b,0x2f,0x93,0x94,0x64,0x33,0x8c,0x56,0x66,0x85,0x4c,0xa8,0x85,0xc4,0xd0,0x46,0xeb,0x2c,0x54,0xe4,0x8a,0x1b,0x5e,0xd2,0x66,0xad,0x34,0xde,0x05,},"\x55\x5b\xb3\x9c\x18\x99\xd5\x7c\xab\xe4\x28\x06\x4c\x2d\x92\x5f\x5f\xc4\xcf\x70\x59\xb9\x5f\xb8\x9a\x8e\x9e\x3a\x7e\x42\x6c\x6c\x92\x2d\x9e\x4d\x76\x98\x4e\xa2\x38\x3c\xab\xb4\xf2\xbe\xfd\x89\xc1\xf2\x0e\xaa\x8a\x00\xdb\xe7\x87\xcf\xa7\x0a\xe2\xae\x6a\xa9\x03\x31\xcb\xbe\x58\x0f\xa5\xa0\x21\x84\xed\x05\xe6\xc8\xe8\x9d\x57\x6a\xf2\x8a\xee\xaf\x7c\x4e\x25\x00\xf3\x58\xa0\x09\x71\xa0\xa7\x59\x20\xe8\x54\x84\x9b\xf3\x32\x14\x29\x75\x40\x4f\x59\x8c\x32\xe9\x69\x82\x04\x3d\x99\x2b\xcd\x1a\x4f\xe8\x19\xbb\x56\x34\xad\x03\x46\x7a\xfc\x4c\xe0\x50\x73\xf8\x8b\xa1\xba\x4a\xe8\x65\x3a\x04\x66\x5c\xf3\xf7\x16\x90\xfe\x13\x34\x38\x85\xbc\x5e\xbc\x0e\x5e\x62\xd8\x82\xf4\x3b\x7c\x68\x90\x0a\xc9\x43\x8b\xf4\xa8\x1c\xe9\x01\x69\xec\x12\x9e\xe6\x3e\x2c\x67\x5a\x1a\x5a\x67\xe2\x7c\xc7\x98\xc4\x8c\xc2\x3f\x51\x07\x8f\x46\x3b\x3b\x7c\xc1\x4e\x3b\xcf\xd2\xe9\xb8\x2c\x75\x24\x09\x34\xcb\xdc\x50\xc4\x30\x8f\x28\x2f\x19\x31\x22\x99\x56\x06\xf4\x01\x35\x10\x0a\x29\x1c\x55\xaf\xdf\x89\x34\xeb\x8b\x61\xd8\x14\x21\x67\x41\x24\xde\xc3\xb8\x8f\x9a\x73\x11\x0a\x9e\x61\x6f\x5b\x82\x6b\x9d\x34\x3f\x3a\xc0\xe9\xd7\xbd\xf4\xfd\x8b\x64\x8b\x40\xf0\x09\x8b\x38\x97\xa3\xa1\xcd\x65\xa6\x45\x70\x05\x9b\x8b\xc5\xc6\x74\x38\x83\x07\x4c\x88\x62\x3c\x1f\x5a\x88\xc5\x89\x69\xe2\x1c\x69\x2a\xca\x23\x68\x33\xd3\x47\x0b\x3e\xb0\x98\x15\xe1\x13\x8e\x9d\x06\x50\xc3\x90\xee\xe9\x77\x42\x21\x93\xb0\x09\x18\xbe\x8a\x97\xcc\x61\x99\xb4\x51\xb0\x5b\x57\x30\xd1\xd1\x33\x58\xcf\x74\x61\x06\x78\xf7\xac\x7f\x78\x95\xcc\x2e\xfc\x45\x6e\x03\x87\x3b"}, -{{0x81,0xda,0x16,0x8f,0x02,0xd4,0x6b,0xb8,0x7c,0xda,0x84,0x5d,0xa4,0x3f,0x8a,0x6c,0xba,0x2c,0x01,0x68,0x78,0xd6,0xf4,0x9c,0x6f,0x06,0x1a,0x60,0xf1,0x55,0xa0,0x4a,},{0xaf,0xf8,0x6e,0x98,0x09,0x3c,0xa4,0xc7,0x1b,0x1b,0x80,0x4c,0x5f,0xe4,0x51,0xcf,0xdf,0x86,0x82,0x50,0xde,0xa3,0x03,0x45,0xfa,0x4b,0x89,0xbb,0x09,0xb6,0xa5,0x3b,},{0x4a,0xac,0xa9,0x47,0xe3,0xf2,0x2c,0xc8,0xb8,0x58,0x8e,0xe0,0x30,0xac,0xe8,0xf6,0xb5,0xf5,0x71,0x1c,0x29,0x74,0xf2,0x0c,0xc1,0x8c,0x3b,0x65,0x5b,0x07,0xa5,0xbc,0x13,0x66,0xb5,0x9a,0x17,0x08,0x03,0x2d,0x12,0xca,0xe0,0x1a,0xb7,0x94,0xf8,0xcb,0xcc,0x1a,0x33,0x08,0x74,0xa7,0x50,0x35,0xdb,0x1d,0x69,0x42,0x2d,0x2f,0xc0,0x0c,},"\x6b\xc6\x72\x6a\x34\xa6\x4a\xae\x76\xab\x08\xc9\x2b\x17\x9e\x54\xff\x5d\x2e\x65\xeb\x2c\x6c\x65\x9a\xe8\x70\x3c\xc2\x45\xcb\xc2\xcf\x45\xa1\x2b\x22\xc4\x68\xae\x61\xfd\x9a\x66\x27\xad\x06\x26\xc9\xb1\xe5\xaf\x41\x2c\xb4\x83\xea\xee\x1d\xb1\x1b\x29\xf0\xa5\x10\xc1\x3e\x38\x02\x0e\x09\xae\x0e\xee\x76\x25\x37\xa3\xe9\xd1\xa0\xc7\xb0\x33\xd0\x97\xfd\xc1\xf4\xf8\x26\x29\xa9\xde\x9e\xf3\x8d\xa1\xcf\x96\xa9\x40\x35\x7d\x5f\x2e\x0e\x7e\x8d\xbc\x29\xdb\x72\x8a\x1e\x6a\xad\x87\x6e\x5e\x05\x31\x13\xd0\x64\x20\x27\x2b\x87\xcf\x0c\x40\xdf\xe0\x3a\x54\x4d\xe9\x6c\x7a\xea\x13\xba\x00\x29\xb5\x7b\x48\xd9\x9d\xcc\x6a\x65\x04\x92\xd7\x8c\x4c\xdd\x1b\x28\xe1\xa1\x15\xa7\xe3\xe7\xa7\xcb\x21\x33\x3d\x4f\xf8\x08\x58\xdf\xb6\x77\x82\xc1\x63\x54\xb8\x71\x65\x96\x56\x0d\x7d\x8e\x38\x9e\xb1\x5a\x05\x2a\x0b\xf5\xd1\x6e\xb5\x4f\xb3\xe4\x97\x3a\xd4\x98\x4e\x72\xa1\x87\xf5\x34\x7d\x5b\x26\x2c\x32\xb1\x64\x7e\x42\xb6\xa5\x38\x37\x09\x6c\xc7\x8c\x2a\x05\xce\x1c\x6e\x12\x49\x3a\x03\xf1\xa6\x67\x58\x4c\xb9\x7f\x4f\xcd\x57\xee\x94\x4c\x65\xb7\xee\xd2\x5f\x7a\xe0\xf3\xf6\xce\xde\x17\x3f\xdf\xac\xf5\xaf\x1d\xb1\x43\x73\x0d\x18\x09\x66\x64\x91\x4b\xa4\xcf\xc6\x96\x6f\x39\x20\x22\x78\x1c\x66\xa9\x41\x7c\xa2\x68\x0b\x51\xf6\x3e\x4f\xba\x42\x4e\xcf\xdb\xc6\xa2\xf0\x17\x87\xd0\xe7\x48\x4f\x8a\x8a\xb3\x90\xae\xaa\x6d\x1f\x7e\xd3\x25\xd8\x2f\xea\xa1\x69\x2a\x49\x84\xfa\xe4\x3d\xa8\x73\x29\xb0\x45\xda\x8f\x0a\x4f\x56\xb6\x95\xaa\x93\x5d\xe1\x52\xce\x03\x85\x15\x37\x20\x97\x9a\x2b\x70\x06\xd4\x05\xfc\xb0\xfb\xa0\x9e\x23\xb8\x5f\xd1\x9b"}, -{{0xaf,0x2e,0x60,0xda,0x0f,0x29,0xbb,0x16,0x14,0xfc,0x3f,0x19,0x3c,0xc3,0x53,0x33,0x19,0x86,0xb7,0x3f,0x3f,0x9a,0x0a,0xec,0x94,0x21,0xb9,0x47,0x3d,0x6a,0x4b,0x6a,},{0xc8,0xbf,0xe2,0x83,0x58,0x22,0x19,0x9c,0x61,0x27,0xb8,0x06,0xfa,0xbe,0xef,0x0c,0xb9,0xff,0x59,0xf3,0xc8,0x1f,0xf0,0xcb,0x89,0xc5,0x56,0xf5,0x51,0x06,0xaf,0x6a,},{0x50,0xf9,0xf9,0x41,0xa8,0xda,0x9f,0x62,0x40,0xf7,0x6d,0x2f,0xa3,0xb0,0x6d,0xd6,0xb2,0x29,0x2e,0xd3,0x2d,0x1c,0x05,0x21,0x80,0x97,0xd3,0x4d,0x8a,0x19,0xdf,0xe5,0x53,0xf7,0x6a,0xe3,0xc6,0xb4,0xa2,0xed,0x20,0x85,0x21,0x28,0x46,0x15,0x40,0xde,0xcf,0x41,0x8f,0x52,0xd3,0x8e,0x64,0x03,0x7e,0xec,0x77,0x71,0xbd,0x1a,0xfe,0x00,},"\x7d\xbb\x77\xb8\x8b\xda\x94\xf3\x44\x41\x6a\x06\xb0\x96\x56\x6c\x6e\x8b\x39\x39\x31\xa8\x24\x3a\x6c\xab\x75\xc3\x61\xfd\xe7\xdc\x53\x6a\xec\x40\xcd\xed\x83\x29\x6a\x89\xe8\xc3\xbe\xf7\xd7\x87\xcf\xc4\x94\x01\xa7\xb9\x18\x3f\x13\x8d\x50\x00\x61\x9f\xf0\x73\xc0\x5e\x2f\x84\x1d\x60\x08\x35\x8f\x10\xa2\xda\x7d\xcf\xac\x3d\x4d\x70\xc2\x0d\x2e\xc3\x4c\x7b\x6d\x5c\xd1\xa7\x34\xd6\xbb\xb1\x1c\x5f\xd8\xd2\xbc\xe3\x2a\xc8\x10\xef\x82\xb4\x18\x8a\xa8\xea\x3c\xfc\x30\x32\x23\x3d\xc0\xe2\x60\x0e\x9d\xb6\xe1\x8b\xc2\x2b\x10\x04\x4a\x31\xc1\x5b\xac\xea\xf5\x55\x4d\xe8\x9d\x2a\x34\x66\x80\x7f\x24\x44\x14\xd0\x80\xff\x29\x63\x95\x6c\x6e\x83\xc8\xe1\x44\xed\x00\x66\x08\x8b\x47\x6d\xdc\xb5\x64\x40\x34\x47\xd9\x15\x9f\x90\x89\xab\xa2\xb4\xd5\x57\x5c\x4d\x8a\xe6\x6f\xc8\x69\x0e\x73\x49\xed\x40\x83\x2e\x63\x69\xc0\x24\x56\x3e\xc4\x93\xbf\xcc\x0f\xc9\xac\x78\x7a\xc8\x41\x39\x7f\xe1\x33\x16\x72\x83\xd8\x0c\x42\xf0\x06\xa9\x9d\x39\xe8\x29\x79\xda\x3f\xa9\x33\x4b\xd9\xed\xe0\xd1\x4b\x41\xb7\x46\x6b\xce\xbb\xe8\x17\x1b\xc8\x04\xa6\x45\xd3\x72\x32\x74\xa1\xb9\x2b\xf8\x2f\xd9\x93\x35\x87\x44\xde\x92\x44\x19\x03\xd4\x36\xfd\x47\xf2\x3d\x40\x05\x2a\x38\x29\x36\x7f\x20\x2f\x05\x53\xb5\xe4\x9b\x76\xc5\xe0\x3f\xa6\xce\x7c\x3c\xf5\xee\xb2\x1d\xe9\x67\xbe\xc4\xdd\x35\x59\x25\x38\x4e\xbf\x96\x69\x7e\x82\x37\x62\xba\xc4\xd4\x3a\x76\x7c\x24\x1a\x4c\xef\x72\x4a\x97\x0d\x00\xff\x3a\x8a\xb3\xb8\x3e\xed\x84\x00\x75\xc7\x4e\x90\xf3\x06\xe3\x30\x01\x32\x60\x96\x21\x61\xe9\xd0\x91\x0d\xe1\x83\x62\x2c\xe9\xa6\xb8\xd5\x14\x42\x80\x55\x0f\xc7"}, -{{0x60,0x5f,0x90,0xb5,0x3d,0x8e,0x4a,0x3b,0x48,0xb9,0x7d,0x74,0x54,0x39,0xf2,0xa0,0x80,0x7d,0x83,0xb8,0x50,0x2e,0x8e,0x29,0x79,0xf0,0x3e,0x8d,0x37,0x6a,0xc9,0xfe,},{0xaa,0x3f,0xae,0x4c,0xfa,0x6f,0x6b,0xfd,0x14,0xba,0x0a,0xfa,0x36,0xdc,0xb1,0xa2,0x65,0x6f,0x36,0x54,0x1a,0xd6,0xb3,0xe6,0x7f,0x17,0x94,0xb0,0x63,0x60,0xa6,0x2f,},{0xdd,0x02,0x12,0xe6,0x32,0x88,0xcb,0xe1,0x4a,0x45,0x69,0xb4,0xd8,0x91,0xda,0x3c,0x7f,0x92,0x72,0x7c,0x5e,0x7f,0x9a,0x80,0x1c,0xf9,0xd6,0x82,0x70,0x85,0xe7,0x09,0x5b,0x66,0x9d,0x7d,0x45,0xf8,0x82,0xca,0x5f,0x07,0x45,0xdc,0xcd,0x24,0xd8,0x7a,0x57,0x18,0x13,0x20,0x19,0x1e,0x5b,0x7a,0x47,0xc3,0xf7,0xf2,0xdc,0xcb,0xd7,0x07,},"\x3b\xcd\xca\xc2\x92\xac\x95\x19\x02\x4a\xae\xce\xe2\xb3\xe9\x99\xff\x5d\x34\x45\xe9\xf1\xeb\x60\x94\x0f\x06\xb9\x12\x75\xb6\xc5\xdb\x27\x22\xed\x4d\x82\xfe\x89\x60\x52\x26\x53\x0f\x3e\x6b\x07\x37\xb3\x08\xcd\xe8\x95\x61\x84\x94\x4f\x38\x8a\x80\x04\x2f\x6c\xba\x27\x4c\x0f\x7d\x11\x92\xa0\xa9\x6b\x0d\xa6\xe2\xd6\xa6\x1b\x76\x51\x8f\xbe\xe5\x55\x77\x3a\x41\x45\x90\xa9\x28\xb4\xcd\x54\x5f\xcc\xf5\x81\x72\xf3\x58\x57\x12\x0e\xb9\x6e\x75\xc5\xc8\xac\x9a\xe3\xad\xd3\x67\xd5\x1d\x34\xac\x40\x34\x46\x36\x0e\xc1\x0f\x55\x3e\xa9\xf1\x4f\xb2\xb8\xb7\x8c\xba\x18\xc3\xe5\x06\xb2\xf0\x40\x97\x06\x3a\x43\xb2\xd3\x64\x31\xcc\xe0\x2c\xaf\x11\xc5\xa4\xdb\x8c\x82\x17\x52\xe5\x29\x85\xd5\xaf\x1b\xfb\xf4\xc6\x15\x72\xe3\xfa\xda\xe3\xad\x42\x4a\xcd\x81\x66\x2e\xa5\x83\x7a\x11\x43\xb9\x66\x93\x91\xd7\xb9\xcf\xe2\x30\xcf\xfb\x3a\x7b\xb0\x3f\x65\x91\xc2\x5a\x4f\x01\xc0\xd2\xd4\xac\xa3\xe7\x4d\xb1\x99\x7d\x37\x39\xc8\x51\xf0\x32\x7d\xb9\x19\xff\x6e\x77\xf6\xc8\xa2\x0f\xdd\x3e\x15\x94\xe9\x2d\x01\x90\x1a\xb9\xae\xf1\x94\xfc\x89\x3e\x70\xd7\x8c\x8a\xe0\xf4\x80\x00\x1a\x51\x5d\x4f\x99\x23\xae\x62\x78\xe8\x92\x72\x37\xd0\x5d\xb2\x3e\x98\x4c\x92\xa6\x83\x88\x2f\x57\xb1\xf1\x88\x2a\x74\xa1\x93\xab\x69\x12\xff\x24\x1b\x9f\xfa\x66\x2a\x0d\x47\xf2\x92\x05\xf0\x84\xdb\xde\x84\x5b\xaa\xeb\x5d\xd3\x6a\xe6\x43\x9a\x43\x76\x42\xfa\x76\x3b\x57\xe8\xdb\xe8\x4e\x55\x81\x3f\x01\x51\xe9\x7e\x5b\x9d\xe7\x68\xb2\x34\xb8\xdb\x15\xc4\x96\xd4\xbf\xcf\xa1\x38\x87\x88\x97\x2b\xb5\x0c\xe0\x30\xbc\x6e\x0c\xcf\x4f\xa7\xd0\x0d\x34\x37\x82\xf6\xba\x8d\xe0"}, -{{0x9e,0x2c,0x3d,0x18,0x98,0x38,0xf4,0xdd,0x52,0xef,0x08,0x32,0x88,0x68,0x74,0xc5,0xca,0x49,0x39,0x83,0xdd,0xad,0xc0,0x7c,0xbc,0x57,0x0a,0xf2,0xee,0x9d,0x62,0x09,},{0xf6,0x8d,0x3b,0x81,0xe7,0x35,0x57,0xee,0x1f,0x08,0xbd,0x2d,0x3f,0x46,0xa4,0x71,0x82,0x56,0xa0,0xf3,0xcd,0x8d,0x2e,0x03,0xeb,0x8f,0xe8,0x82,0xaa,0xb6,0x5c,0x69,},{0x38,0xa3,0x1b,0x6b,0x46,0x50,0x84,0x73,0x82,0x62,0xa2,0x6c,0x06,0x5f,0xe5,0xd9,0xe2,0x88,0x6b,0xf9,0xdd,0x35,0xcd,0xe0,0x5d,0xf9,0xba,0xd0,0xcc,0x7d,0xb4,0x01,0xc7,0x50,0xaa,0x19,0xe6,0x60,0x90,0xbc,0xe2,0x5a,0x3c,0x72,0x12,0x01,0xe6,0x05,0x02,0xc8,0xc1,0x04,0x54,0x34,0x66,0x48,0xaf,0x06,0x5e,0xab,0x0e,0xe7,0xd8,0x0f,},"\x19\x48\x5f\x52\x38\xba\x82\xea\xdf\x5e\xff\x14\xca\x75\xcd\x42\xe5\xd5\x6f\xea\x69\xd5\x71\x8c\xfb\x5b\x1d\x40\xd7\x60\x89\x9b\x45\x0e\x66\x88\x45\x58\xf3\xf2\x5b\x7c\x3d\xe9\xaf\xc4\x73\x8d\x7a\xc0\x9d\xa5\xdd\x46\x89\xbb\xfa\xc0\x78\x36\xf5\xe0\xbe\x43\x2b\x1d\xdc\xf1\xb1\xa0\x75\xbc\x98\x15\xd0\xde\xbc\x86\x5d\x90\xbd\x5a\x0c\x5f\x56\x04\xd9\xb4\x6a\xce\x81\x6c\x57\x69\x4e\xcc\x3d\x40\xd8\xf8\x4d\xf0\xed\xe2\xbc\x4d\x57\x77\x75\xa0\x27\xf7\x25\xde\x08\x16\xf5\x63\xfa\x88\xf8\x8e\x07\x77\x20\xeb\xb6\xac\x02\x57\x46\x04\x81\x98\x24\xdb\x74\x74\xd4\xd0\xb2\x2c\xd1\xbc\x05\x76\x8e\x0f\xb8\x67\xca\x1c\x1a\x7b\x90\xb3\x4a\xb7\xa4\x1a\xfc\x66\x95\x72\x66\xac\x0c\x91\x59\x34\xaa\xf3\x1c\x0c\xf6\x92\x7a\x4f\x03\xf2\x32\x85\xe6\xf2\x4a\xfd\x58\x13\x84\x9b\xb0\x8c\x20\x3a\xc2\xd0\x33\x6d\xcb\xf8\x0d\x77\xf6\xcf\x71\x20\xed\xfb\xcd\xf1\x81\xdb\x10\x7e\xc8\xe0\x0f\x32\x44\x9c\x1d\x3f\x5c\x04\x9a\x92\x69\x4b\x4e\xa2\xc6\xeb\xe5\xe2\xb0\xf6\x4b\x5a\xe5\x0a\xd3\x37\x4d\x24\x6b\x32\x70\x05\x7e\x72\x4a\x27\xcf\x26\x3b\x63\x3a\xb6\x5e\xcb\x7f\x5c\x26\x6b\x80\x07\x61\x8b\x10\xac\x9a\xc8\x3d\xb0\xfe\xbc\x04\xfd\x86\x3d\x96\x61\xab\x6e\x58\x49\x47\x66\xf7\x1b\x9a\x86\x7c\x5a\x7a\x45\x55\xf6\x67\xc1\xaf\x2e\x54\x58\x8f\x16\x2a\x41\xce\x75\x64\x07\xcc\x41\x61\xd6\x07\xb6\xe0\x68\x29\x80\x93\x4c\xaa\x1b\xef\x03\x6f\x73\x30\xd9\xee\xf0\x1e\xcc\x55\x35\x83\xfe\xe5\x99\x4e\x53\x3a\x46\xca\x91\x6f\x60\xf8\xb9\x61\xae\x01\xd2\x0f\x7a\xbf\x0d\xf6\x14\x1b\x60\x4d\xe7\x33\xc6\x36\xb4\x20\x18\xcd\x5f\x1d\x1e\xf4\xf8\x4c\xee\x40\xfc"}, -{{0x31,0x01,0x0d,0x1d,0x67,0xeb,0x61,0x63,0x48,0xe8,0x47,0x92,0xb9,0x2d,0x5d,0xc1,0x28,0x55,0x3c,0xb5,0x2f,0x63,0x68,0x15,0x9f,0xe7,0xb8,0x16,0xcd,0x0e,0x7c,0x37,},{0x26,0x65,0x43,0xd9,0x67,0x87,0xca,0x90,0x1f,0xcf,0xf0,0x6e,0x6e,0x43,0x44,0x91,0xae,0x09,0x70,0x88,0x0a,0x5a,0x18,0x7d,0x53,0x5e,0xdb,0x19,0xdb,0x5c,0xab,0xeb,},{0x7b,0x1e,0xb6,0x77,0xc3,0xe5,0xe6,0xa8,0xb4,0xba,0x69,0xfc,0xb7,0xf6,0xb1,0x87,0x0e,0x42,0xa8,0xd5,0x89,0x58,0xa3,0x5c,0x67,0x4e,0x2d,0xb8,0x21,0x07,0x48,0x1c,0x4c,0x7b,0x37,0xf0,0xf6,0x89,0xd3,0x9d,0x9f,0x51,0xe1,0x81,0xb1,0x7b,0x11,0x08,0xc1,0x5a,0x3e,0x27,0xb2,0x9d,0xf3,0xa4,0x31,0x5d,0xcc,0x4f,0xaf,0x12,0x22,0x05,},"\x39\xf8\x9a\x5e\x7a\xa5\x30\xb5\x46\x3d\x49\x8f\x80\x35\xb9\x90\x9d\x55\xda\x52\x7c\xdb\xd4\xde\x6d\x22\x83\x79\xf0\x89\xe6\x08\xa9\x20\x7a\x2c\x5b\x9c\x42\x05\x1a\x60\xc8\xca\x3f\xb9\x7a\x1c\x06\xcd\x74\x7d\x9d\x07\x39\x97\x0c\xeb\x88\xce\x52\x6f\x97\x11\x40\xea\x2e\xc2\x1f\x09\x0b\xa0\x75\xbf\x89\x75\xfa\xa5\x08\xb1\xcc\x10\xef\xa4\x94\xdc\x17\x2e\x6d\x3d\x3f\x3f\x75\xdc\x8e\x0e\x96\xf0\x5c\x0c\xcc\xb2\xf9\x6e\x91\x1c\xfa\x7a\x2c\x82\xc9\x84\x50\x18\xbb\x1f\x9d\x75\xf8\x2e\x3d\xfe\x11\x39\x34\x7b\x2a\xc0\x58\xb0\x14\xac\x93\x76\x0c\x90\xf5\x56\x7a\xb5\xc4\xeb\xa0\x4b\x49\xfb\x09\xdd\xad\xd3\x05\xbe\x51\x1d\xfe\x05\xc9\x6e\xbc\x86\xfd\x67\xb5\xd0\xab\x57\xd8\x5f\x4f\xe5\xe2\xf0\xfa\x9d\x88\xa6\x8f\x0f\x6b\x6b\xc8\xbb\x94\x4e\xb3\xc0\xb1\x75\x57\xe5\x5d\x5e\xa1\x87\xd9\x22\xa4\x28\x13\xe6\x90\x57\xc9\xb6\xa7\xf7\x5e\x49\x92\x1b\x70\x79\xe5\x8f\x8a\x63\x71\x9e\xe3\xe1\xad\x10\xcf\x0e\x8a\x70\xc4\xf1\x54\x02\x18\xb7\x04\x94\xbd\x02\x9e\xe0\x2f\xf9\x72\x7a\x7d\x85\xd3\x77\x91\x9e\xc4\x05\x14\x79\xb7\x0f\x7c\xd6\x76\x77\x23\xfe\x42\xc1\xc7\x89\x9c\x2b\x7c\x1f\x70\x2d\xd6\xb4\xd1\x3b\x67\x2d\x48\x8f\x34\xa0\xe9\x69\xdb\x79\xcc\x2c\xb2\x52\x4a\x94\x8a\x8d\xe4\xc5\xb6\x23\xec\xd9\x0d\x6e\x82\xd9\x70\x33\xc1\x25\x63\x7d\x1c\xd8\xc8\x48\x03\xd8\xfb\xc0\x12\x84\x6f\xfe\x48\x4f\x6c\x02\x14\x92\x58\xf9\x46\x2f\xa1\xe9\x9c\x30\x7d\xd0\x06\x2f\xe0\xb6\xf1\x1e\xee\x40\xc2\x62\x9e\xf7\xc0\xf6\xa5\x10\x72\x59\xea\x5b\x9f\xfb\x6f\x29\xf1\x2c\x32\xf7\xb5\x22\x8c\xab\xc9\x86\xab\x66\x45\x0a\xf9\xdc\xc3\xda\x09\xd0\xe0\xb9\xa4"}, -{{0x8f,0xf2,0x39,0x8c,0xd5,0x1f,0x51,0xd4,0xc2,0xc5,0x78,0x69,0xa2,0x21,0x8b,0x84,0x86,0x82,0x20,0x31,0xf4,0x00,0x72,0x9f,0x4a,0xc4,0xd5,0x90,0x9c,0x48,0xba,0xfe,},{0xa5,0xa8,0x87,0x04,0xb6,0x86,0x77,0xbe,0x3d,0x16,0xc3,0xdc,0x00,0x52,0xcf,0xee,0x6e,0x2b,0x30,0xe0,0x86,0x09,0x05,0x9d,0x4c,0xba,0x52,0xc6,0xd9,0x60,0x61,0xfb,},{0x41,0x7a,0x64,0x78,0x29,0xc9,0x28,0x98,0xe5,0x20,0xff,0x53,0x11,0xda,0xa0,0xa1,0x39,0xcd,0x8f,0xff,0xcb,0x25,0xa1,0x8e,0x6d,0x9b,0x50,0xcb,0x52,0xcb,0xc3,0x54,0x24,0xc3,0x9e,0xbb,0xb5,0xd5,0xac,0x6a,0x6d,0x63,0xf1,0xf5,0x3c,0x4d,0xf2,0x12,0xf7,0x02,0x5a,0x8a,0xae,0xf8,0xe3,0x64,0x93,0xc8,0x74,0xc3,0xce,0x34,0x1a,0x0e,},"\x99\x39\x53\xe4\x7a\x34\x11\x88\xbc\x59\x29\x42\xe1\x55\x7a\xf2\x95\x46\xe4\xe9\x36\x8e\x2f\x1a\x5e\xe9\x80\x6e\x2b\xaf\x66\xb6\x19\x01\x91\xfc\x5d\x2b\x7e\x47\xde\x37\xff\x05\x4f\xb2\xbb\xb1\xf0\x31\x68\x4a\xda\x5d\x60\x7a\xdd\xa3\xd6\x54\x33\x12\x2f\xa9\x04\xe0\x45\x6f\xaa\x84\x10\x9b\xbc\x51\x7f\x8a\xd3\x96\x60\x87\x63\x82\xad\xcf\xed\x0f\x76\x20\xcf\x11\x64\x62\x2e\xac\xd9\x1e\xb3\x7a\x85\x96\x46\x2e\xbe\x9e\xbe\x26\xbd\xc1\xe3\x2c\xc3\x4a\xd4\x6f\xb1\xce\xa4\x20\xe7\x3c\x31\x21\x54\x08\xe6\xd3\x54\x25\xf4\x4a\x82\x9b\x13\x2f\x63\x1a\x3f\x6d\xd4\xb8\x73\xa0\x00\x66\x7e\x19\xeb\x22\xff\xfd\x59\x03\xaa\xa7\xd4\xc8\xfd\xf2\x19\x53\xc3\xc6\x17\x8f\x5f\x8c\xb2\xaa\x6b\xff\x92\x89\x4e\xad\x83\x58\x88\xdf\x06\x0a\x3c\x90\x43\x02\x6e\x0e\x2c\xef\x27\x54\x97\xe7\xd1\x05\xdf\x3b\x64\x4a\x98\xf2\x6b\xf0\x01\x05\xc9\x94\x13\xee\x0a\xf8\x85\x19\x54\xd6\x5c\xeb\x8d\x79\xad\x30\x71\xb8\xbb\x87\xf0\xb1\x97\x43\xd2\x55\x6f\xfd\x98\x19\x83\x0b\x6e\xeb\xf7\xec\xc7\xe0\x45\x66\x1f\x43\x57\x0c\xe9\xfd\xbb\xe2\xd2\x52\x40\x6f\xa9\x0d\x04\x23\x6f\x22\x2c\x42\x9e\xc1\x6b\x12\x87\x22\x4a\xda\x1a\x53\x21\x61\xae\x8b\x48\x1b\xca\xb8\xd4\x7a\xfb\x3e\xd0\x44\x5b\x30\x60\xfd\x67\x59\x17\x98\x56\xf4\x08\x5c\x1e\x58\x5f\xd7\xc1\x40\x97\x99\xaf\x69\x3c\xf4\x27\xbd\x1d\x3d\xc1\x0b\x5a\xe3\x44\x7a\x8d\x2a\x18\xdc\x3a\x12\xa6\x86\x0b\x22\x17\x5d\xd5\xeb\x53\xa0\x95\x04\x32\xe2\xd7\xae\xfe\xce\x8a\xf0\xad\xe3\xd8\x56\x77\x43\xde\x43\x69\x0f\x2d\x25\x37\x23\xc5\xd7\xe4\x8b\xd3\x0d\x29\x37\x59\x37\x01\xce\xcd\xe9\x15\x4b\x76\x65\xcb\x61\x1d\x7d"}, -{{0xef,0x81,0x6c,0x8f,0x5e,0xc3,0x4e,0xf4,0x1f,0x68,0x83,0x1d,0x90,0xcd,0x29,0xe5,0x2d,0xe8,0x97,0x37,0x82,0xd0,0x03,0xee,0x4e,0xda,0xda,0x2a,0xda,0x26,0x91,0xd6,},{0x47,0xf9,0xb3,0x63,0xa8,0x8a,0x45,0x05,0x3a,0x05,0xbb,0x72,0x16,0x08,0x52,0xbf,0xe8,0xf7,0xdf,0xef,0xc2,0xf3,0x72,0x83,0xde,0x34,0x67,0x52,0xca,0xf0,0x92,0xcc,},{0x65,0xc5,0xd1,0x0e,0xa7,0xbf,0xdb,0xb3,0x8d,0x55,0x36,0x4a,0x99,0x68,0xf8,0x2b,0x54,0x82,0x24,0xdf,0xf3,0x36,0x3b,0x2d,0xdc,0xf5,0x85,0x16,0x3d,0xea,0x27,0xdc,0x63,0xb0,0x56,0x3e,0xb1,0xa8,0xdf,0xbe,0xe9,0x51,0xd3,0xc9,0xb3,0x3f,0xcd,0x6b,0xbf,0x09,0x21,0xc3,0xab,0xb2,0x17,0x86,0xb2,0x29,0x06,0x9b,0xd9,0xca,0x00,0x0a,},"\x95\x93\xc3\x5c\xde\xc5\x35\xbe\xbb\x69\x65\xda\x68\xea\xb0\xb6\x46\xbf\xfc\xfb\xd0\x48\x83\xbc\x4c\xef\x90\xd5\xd0\x1f\x01\x8c\x63\xc9\xb0\xdd\xfb\x3c\xef\x5e\x78\x62\x84\xd5\x21\x8c\xaa\xaf\x06\x0e\x92\x88\x95\x2f\x16\x30\x1e\xd8\xa4\xc1\xbc\xee\x25\x63\x56\xa0\xc8\xbd\xa3\x59\xfb\xaa\x27\x82\xb1\x0c\x86\xd1\x8e\x20\xf7\xa0\xec\x99\xb2\x7a\x0b\x4d\xbe\xfc\x0a\x26\x2a\x3b\xf6\x8f\xe8\x14\x44\xdc\xae\x5f\x69\x3e\xb0\xf1\x6e\x6e\xe0\x3f\x8f\xcb\xf3\xa3\x39\x81\x46\xd2\x0e\xc4\xd2\x65\x77\x61\xfd\x03\x20\xfe\xe7\xea\x70\x3c\x49\xa6\xa5\x43\xbc\x9b\xba\x91\x1e\x79\x25\x03\x87\x10\xe8\xc3\x65\x52\xd4\x76\xd6\x02\x7f\x58\xb2\xc5\x2b\xa5\x1a\xd6\x5e\xa4\xf0\x39\xc7\x8f\x96\xb8\x89\x10\x2b\xb4\xbd\xd6\x9b\x68\xe9\xc3\xd4\x5b\x51\x76\xa2\xd8\x2b\x0b\x95\xdc\x32\x10\x16\x37\x0d\xae\x30\xc3\x93\x65\x15\xdb\x04\x64\xc4\x17\x74\x30\x1c\x74\xe4\x2d\x89\xb8\xbf\x4b\x9c\x19\xed\x55\x4b\x12\xfe\xba\xc0\xf6\x0d\xdb\x32\x19\xcc\xc5\x60\x35\x31\xdb\xf2\xeb\x5f\x29\x34\x25\xd7\x2c\xce\xfa\x0c\x7f\x14\x4a\xba\x89\x34\x7b\x29\x6b\xe8\x7f\xf1\x89\x94\xb4\xa0\xc7\x0c\x93\x0f\x05\x93\x03\xb5\xdd\x4c\x8f\xe1\xe6\xbb\xc3\xcd\x68\xc6\xc0\xd8\x42\x46\xdc\x6e\x61\x40\xa2\xab\xd1\x78\x0b\x13\xf1\x59\x4a\x60\x19\xd1\x77\x8b\x7c\xbb\x3a\x3e\x3a\x34\xbf\xae\x72\x97\xf0\xb3\xed\xc3\x76\x94\x1c\x32\x35\x2a\x4b\xe3\x14\xb8\x4a\x9d\x8d\x6d\x7f\x1f\x38\xa0\xad\x37\x98\x02\x0a\xa2\xa3\x31\xa4\x02\xbe\x9c\x70\x44\x84\x74\x4a\x73\x0c\xbd\xed\xcb\x90\x4b\x6f\xde\x70\x8f\xbd\x14\xbf\xdc\x29\xef\xd4\x61\xd1\xd0\xb5\x82\x5d\xe0\xbc\x79\x42\x2b\x69\xa2\x72\x2f"}, -{{0x45,0xeb,0x0c,0x4d,0xfa,0xfa,0x2a,0x76,0x90,0xef,0x57,0x9c,0x09,0x54,0x56,0xce,0xed,0xcd,0x32,0xf0,0xb6,0x14,0x4d,0x0c,0x38,0x0f,0x87,0xfb,0x74,0x4a,0x0b,0x1f,},{0xfc,0x85,0x63,0x2c,0x98,0x38,0x4b,0x5f,0x96,0x82,0xae,0xd9,0xcd,0x66,0x4c,0xf1,0xf4,0x8e,0x58,0x8b,0xe2,0xd5,0x68,0xe5,0xc7,0x34,0x49,0x4d,0xf4,0xc7,0x12,0xb8,},{0x55,0x85,0x1d,0xe8,0xe1,0x09,0x2f,0x78,0x94,0x4f,0x6c,0x6d,0xd9,0x5b,0xf0,0x7e,0x2d,0xbc,0x8d,0xf7,0xf5,0x7a,0xd5,0x76,0x82,0x9b,0x97,0x8e,0x3a,0xf5,0x8a,0x7a,0x8e,0x94,0xed,0x4d,0xcc,0xbc,0x01,0x82,0x46,0x7e,0xdf,0x0b,0xad,0x4b,0xae,0x7c,0xa8,0x4a,0xa9,0xa0,0xc1,0x7c,0x61,0xa9,0xe0,0xdd,0xff,0x1d,0x75,0x25,0xd7,0x04,},"\x6f\x66\xd8\x47\x40\x5a\x03\xd7\xbd\x6f\x8d\x28\x97\xdb\xdf\x04\xe7\x6d\x7d\xf2\xd9\x47\x0a\x49\x96\xb7\xdd\x6d\xb8\x85\x00\xf8\xf4\xf8\x3e\x96\x0e\x21\x9a\x24\x86\xe2\x45\x45\xad\xd1\x36\x14\x55\x04\x14\xd8\x27\xc4\x1a\x9b\x08\x31\x8d\xaf\x01\xb1\x52\x14\xc6\x4a\x42\x66\xcb\xf8\xa5\x71\x7a\xda\x3e\x62\xc2\x67\x29\x07\x3e\x16\xdd\xbd\x66\xf2\xd5\x20\xe1\xe0\x99\x35\xde\x05\xe4\xdb\x11\xc3\x96\xd4\x77\x01\x0a\xec\x66\xaa\xfb\x76\x2e\x69\x23\x8d\x0b\x9e\x76\xb4\x52\x45\x4b\xf9\xe4\x51\xe7\x6a\xc7\x9e\x69\x90\xd4\x1b\x93\x2b\xc3\x29\x17\x09\x37\x83\xc9\x1b\xc9\xcf\x0b\xbe\x3b\x51\x40\x70\xa1\xe6\x92\xff\x34\xfd\x06\xb6\x6e\xa1\x1f\x39\xe1\x0a\xf9\x33\xee\x96\xd8\xe9\xb6\x77\xcb\x03\x73\x7e\x79\x64\xee\xaa\x72\x5f\x12\x12\x07\xf9\xc1\xb2\x6a\x96\xc6\x16\xdf\x7c\xb7\xca\xef\x47\xbd\xa9\x01\x36\x8f\xf2\xea\x58\x6e\x42\x2e\x65\xbf\x21\xa6\x91\xbd\xd2\xc1\x3e\x67\xff\xf5\x8c\xfb\xfe\xd8\x17\x82\x04\x9d\xaf\xa0\xf7\x27\xdf\x88\x62\x3f\x2f\x7e\x8f\x26\x2d\xaf\x93\x95\x42\xa1\x87\xb8\x72\x0a\x9b\x6b\x2b\x09\x89\x0e\x54\x87\x6b\x28\xa4\x38\x74\xab\xbe\x3b\xfa\x98\x1f\x81\x38\xb7\x72\xc5\xd5\x17\x36\x88\x5f\x86\xac\xac\x22\x15\xa0\xb0\x10\xdf\xc2\xc6\xb1\x50\x84\x5d\x4f\x82\x96\x25\x25\x86\xa3\xe1\x15\xf3\x03\xc3\xd8\xa5\x82\xe2\x0f\xd2\xd4\x3f\x6c\x44\x6e\x5d\x00\x28\x0e\xc1\x79\x82\x3b\x7f\xb4\xc1\xb0\xfe\xb9\x4e\xb4\xef\x17\x07\xf5\x18\x4e\x3b\x52\x46\x1a\x75\x62\xd1\xf3\x07\xcb\x75\x1c\xdb\xbf\x6e\xae\x49\xff\xae\x91\x86\x23\x58\xe7\x4e\x95\x48\x82\x2b\x8a\x04\x9f\xec\x6b\xf4\xc7\xa9\x9c\xab\xbe\x09\x20\x65\x77\xb6\x57\xe3\x1f"}, -{{0x70,0x9d,0x2e,0x19,0x90,0x06,0xf5,0x36,0x9a,0x7a,0x0b,0xdd,0x34,0xe7,0x4d,0xc7,0x84,0xbe,0x33,0x88,0x0e,0xa3,0xc5,0xdd,0x10,0xed,0x5c,0x94,0x45,0x1e,0x79,0x72,},{0x06,0xf9,0x89,0x20,0x2b,0xa2,0xcb,0xc9,0xc1,0x50,0xbe,0x61,0x12,0x62,0xac,0xa0,0x0c,0x45,0xf0,0x12,0xf8,0x9f,0xba,0xf8,0x9f,0x8c,0xec,0xcb,0xa0,0xb1,0x93,0x4a,},{0x62,0x9b,0xf9,0x7b,0x0c,0x78,0xee,0x6a,0x9c,0x87,0x59,0xfb,0xea,0x28,0x22,0x4e,0x27,0xab,0xbb,0x6c,0xbe,0x4d,0xea,0x5b,0xb7,0x97,0xe6,0xe0,0xfe,0x80,0xc9,0x13,0xf9,0x53,0xe3,0xa9,0xb6,0x23,0x35,0x2d,0x13,0xac,0xf4,0xce,0x62,0x50,0xfb,0x02,0x9a,0x1e,0x19,0x8d,0x72,0xbd,0x5e,0x74,0x02,0xe6,0x0e,0x9e,0x48,0xca,0x35,0x01,},"\x62\xf0\x03\x14\x0f\xa0\x9e\x03\x87\xd1\x87\xa0\xff\x96\xc4\x56\x3d\xf9\xf4\xe2\x8c\x22\x82\xc0\x18\x3a\xc3\xee\xde\x13\x12\x35\x49\x21\xf7\x80\xfc\xa5\x36\x1d\x30\x68\xd2\x99\x49\x63\x0b\x75\x30\xcd\x59\x14\xac\xe0\x46\x8d\x01\x4b\x6f\x53\xd8\x39\xb8\x2e\x38\x81\x7d\xbf\x2d\x83\x92\xc3\xce\x34\x24\xea\xb8\x6a\x24\xd8\x04\xc7\xac\xb1\xce\x7a\xcf\xe0\xa1\xcd\xa4\x39\x39\x24\x28\x31\x05\xda\x4a\x77\x41\x19\x6e\x02\x75\x50\x04\x7f\x85\xb7\xa0\xa0\x1d\x45\x41\x24\xef\xc0\xe2\x99\xf0\xef\x9a\xd1\x43\x50\x54\x30\x53\x48\x22\x61\x52\x8b\xaa\x56\xe6\x59\x99\xac\x80\x2c\x00\xa3\x36\x26\x7c\x63\x51\x06\xb2\x64\x03\xc1\x9f\x39\x1d\x53\xbd\x82\x86\x1d\x6d\x48\xa4\x38\x0b\x30\x43\xaa\x91\xd6\x49\x53\x68\x81\x20\x4e\xcc\xb0\xde\x20\xd4\x3e\x5a\x37\x55\xb7\xf6\x00\x91\x6e\xcc\xae\x42\xa0\xc9\x05\x3b\x46\x2d\x94\x17\xa1\x3d\x67\xd7\x78\x26\x4a\x89\x6e\x8e\xaf\x90\xba\xf6\x6d\x29\xe5\x43\x8a\x71\x67\x81\x12\x3a\x89\xfa\x9b\x8b\xee\xf9\x1d\x96\x5a\xf2\xf4\xa1\xa5\xbd\x5d\x2e\x2a\xaf\x46\xd5\xc9\x4b\x77\x09\xcd\xd3\x8d\x05\xfe\xee\x4b\xfb\x76\xa3\x59\x07\x7c\x16\xbc\x4b\xe9\x11\x6e\x69\x00\x12\x71\xcd\xa5\x65\xbc\x19\xbf\x47\xd4\xf9\x86\xbd\x9c\x0d\x18\x4c\xd8\xa3\x52\x0c\xa1\xbd\xb4\xb5\x05\xaa\xf7\xcb\x4e\xc9\xf9\x47\x89\x77\x9d\x30\x71\x4e\x79\x11\x6d\xd5\x01\x9d\x59\xb2\x8b\x17\xda\xd9\x6f\x4e\x21\x55\xad\x9c\x61\x27\x4a\xdd\xc6\xb6\x38\x10\x95\x04\xe9\xed\x19\xf4\xed\xa5\x37\x77\x62\x64\x8c\x40\x98\x22\x4e\x33\x91\x04\x3e\x4c\x2a\xd5\x91\x65\x4c\x9e\x7f\x97\x4e\xfd\xf0\xb0\x50\x4b\x6f\xa5\xf6\x46\xce\xcf\x44\xcd\x37\x24\x12\x37\x25\x05"}, -{{0x51,0x51,0x61,0x74,0x21,0xaa,0xdc,0x9c,0x95,0xa4,0x42,0xb4,0x5e,0x7f,0xf6,0xde,0x06,0xa2,0xc7,0x33,0xb8,0x5b,0xd7,0x89,0xfb,0xad,0x41,0x4e,0xe3,0xc9,0x1a,0xdd,},{0x14,0x94,0x1d,0x55,0x97,0x61,0xb3,0x0a,0xb0,0xa8,0x6d,0x47,0xe0,0xf7,0xd1,0x89,0x6b,0x33,0x78,0x45,0x27,0xc8,0x0a,0xf4,0x1c,0xb8,0x48,0x10,0xcb,0xff,0x9d,0xbf,},{0xfa,0xe4,0x77,0x3b,0x33,0x44,0x60,0xc7,0x7b,0xf0,0x1e,0xc6,0x36,0x6c,0x4f,0xe6,0x1c,0x0c,0xab,0x57,0xd8,0xa4,0xb0,0x39,0x09,0xc6,0x19,0xe1,0x1e,0xe3,0x46,0x1c,0x13,0xfa,0x21,0x57,0x6f,0x63,0x87,0x0e,0x42,0x3d,0xd0,0x41,0x81,0xe4,0xa7,0x01,0x3a,0x75,0x24,0xf2,0x46,0xfe,0x33,0x85,0x3c,0x67,0x41,0x62,0xa7,0x81,0x51,0x04,},"\x21\x6e\x9d\x40\xbc\xdc\x3b\x26\x50\x18\x8d\x12\x1c\x9f\x8e\xf2\x9e\x91\x4f\xac\xd0\x22\xfe\x01\xb9\x0e\xd1\x12\x25\xf2\xeb\x93\x53\x8e\x5f\xce\xe5\xab\x80\x45\xe9\x19\x9a\xa7\x6a\x16\xbd\xd0\x61\x68\x05\x66\x0e\x24\x7f\xec\xd7\xe2\x28\x21\xb6\x9b\x1f\x8e\x8a\x58\xac\x3f\xb8\x56\x91\xd7\x5d\x59\x57\xa1\xda\xf5\x3f\xf9\xee\x64\x76\xd7\xc4\xbc\x54\x1e\x6a\xd3\x8e\x3a\x34\xea\x90\xfc\x52\xa4\x8b\x93\x99\xf9\x2d\x17\xc9\xbb\x0d\x7f\xc3\x10\x4c\x55\xd0\xef\xb4\xea\x5b\x83\x1f\xf9\x49\x0b\x3f\x79\xf4\xd9\xd6\x99\x59\x4b\x74\x15\x66\xf2\xb5\x0a\x8f\xc7\x8c\xc4\x03\xfa\x40\xf5\xab\xb6\x63\x8a\x32\xf4\x49\xa8\xb3\xef\x02\x9c\x40\x2f\x46\x93\x1a\xd2\xbd\x3e\x8e\x68\x31\x08\x71\x4c\x98\x9a\xe2\x16\x89\xe9\xc4\x44\xb9\xf5\x5b\x81\x11\x9b\xb5\x03\x5b\xcf\x73\xe9\x7c\xe4\x3a\x22\x18\xc7\xbc\x3e\x43\x0d\x1e\x81\x4f\x34\xde\xe0\x57\x26\x5d\x31\x94\xb9\xf4\x38\x75\xd8\x38\x1f\x52\x5f\x78\x57\x6e\x64\xce\x69\x25\x84\xfa\xa3\x0f\xb7\x43\xa1\x2d\x1b\x77\x61\x4d\x2e\x10\xa6\xb8\x56\xb5\x2b\xe2\x7c\xdb\x63\x0b\xa1\xf0\xd3\xa6\xf8\xea\x98\x44\x54\x2e\x58\x4e\xa0\xa2\x77\x75\x27\xd0\xc5\x2a\xca\x94\x9a\xac\xda\x45\xad\x83\xd1\x6d\x5c\x83\xd6\x63\xad\xb7\x9c\xad\x6f\x3e\x39\xe9\x90\xfe\x28\x2a\x14\xc3\x53\xaa\x23\x79\xd7\xf0\x6a\xda\xb7\x4c\xea\x02\x1b\x89\x83\xa5\x7f\x1d\x0c\xf7\x03\x29\x2e\xb0\x5e\xce\x89\xc5\x3f\x3a\x12\x65\x61\x0e\x0c\x1e\xa8\xdd\xd4\x44\xd1\xff\xd6\xbc\x3d\x03\xf0\xa6\xe4\xd0\xdf\x5c\x5b\x8d\xc1\xf9\x5d\x9f\x55\x58\xb1\x18\xaf\xe6\xbe\xa0\xf6\xc2\x93\x13\x63\xf0\x3a\xb3\x4e\x75\x7d\x49\x36\x41\x74\xf6\x58\xef\xbb\xf3\x8d\xc1\x77"}, -{{0x38,0xbe,0xd4,0x45,0x55,0x6d,0xe7,0x44,0x82,0xbf,0x5f,0xec,0x05,0x06,0xf9,0xaf,0x33,0x0b,0x15,0x1e,0x50,0xd4,0x77,0x4d,0xfe,0x85,0x91,0xd7,0xb7,0xe0,0x27,0x6b,},{0x4c,0x0f,0x9c,0x49,0xa4,0x2f,0x40,0x47,0xbf,0xe6,0x88,0x55,0x51,0xc5,0xe4,0xb8,0x56,0xcf,0x77,0x1a,0x67,0xaf,0x3f,0x89,0xdb,0xf6,0x02,0xf9,0xdb,0x92,0x20,0xf3,},{0xf7,0x02,0xd0,0xd4,0x63,0x28,0x2f,0xc7,0xfd,0x5f,0x8f,0x90,0x29,0xb8,0x9c,0x62,0x6c,0xaf,0xd8,0x34,0x50,0xc3,0xbb,0x9d,0xd8,0xf6,0x58,0x9f,0x0c,0x4b,0x4b,0x71,0xf6,0x49,0xea,0x21,0x2e,0x5e,0x33,0x48,0x7c,0x59,0xc1,0x68,0xea,0x3a,0xd8,0x31,0x50,0xf1,0xfc,0xdf,0xe8,0xc5,0x3e,0xba,0x65,0xad,0xc2,0x02,0x3c,0x25,0x83,0x0f,},"\x0f\xf0\x03\x1d\xf0\xbe\xef\xf3\x71\x0c\x6b\x76\x3f\x9b\x8e\xc8\x17\x19\xbf\xa1\x52\x8c\xe4\x65\x19\xad\xf3\xd3\x41\x2d\x93\xfb\x18\x8f\xd4\x97\xd5\xd1\x70\x91\xc0\xf0\x34\x59\x60\xdd\x0e\xb0\xc0\x9f\xc4\x00\x51\x73\x66\x5d\x4d\x97\xf9\x5c\x13\x82\x8b\xc7\x6b\x34\x92\xb8\x7a\x4b\x64\x25\x3c\x8b\x5f\xa4\x7a\xa7\x5f\xa3\xb8\x6d\x5a\xbe\xea\x8d\xe5\x95\x9a\x60\x22\x89\x13\x6f\x60\xa6\x9b\x30\x9e\x77\x3b\x22\x55\xcd\xe1\x9e\xd2\xa2\xe1\x99\xc3\x3d\xb1\x1c\x16\xad\xe0\x8a\x31\x97\x50\xb8\x51\xd9\x2c\x69\x29\x24\xfc\x98\x59\xbe\x52\x34\x31\xcb\xe7\x8e\xc0\x92\xdb\x11\x29\x21\x0e\xbb\xea\xa7\xc2\xa2\xc0\x00\xee\xb1\x05\xca\x03\x01\xa4\x8f\x3e\x45\xfd\xfb\x15\xb2\x75\xcb\xab\x83\xca\x5c\x99\xd7\x37\xa5\x85\x32\x0e\x9e\x3b\x31\x71\x79\xbd\x86\x46\x7f\xa9\x69\x4f\xcd\xb2\xac\x6a\xd3\x6e\xd7\x14\x48\x43\xdb\xc3\x4e\x42\x3d\x35\xaf\xd7\xd8\x97\x2a\x1c\x43\xc1\x99\xa1\x91\xab\xd6\xce\xba\x49\x36\xd3\x95\xc9\x95\xa3\xeb\x13\xcb\x05\x7f\x88\xa9\xdc\x94\x90\xfe\x98\x84\x5e\xe5\xd2\x6a\x89\xfb\x64\x2a\x2a\x51\x6d\xc3\x05\x6c\x54\xd3\x63\x72\x13\x36\x3a\x86\x28\xa4\x2a\x39\x5d\x94\x2b\x95\x4a\x89\xe8\xef\x7a\x74\x4d\x8a\xe5\xad\xac\x88\xc6\x16\xef\xaa\x90\xe2\x07\x72\x05\xa6\x0b\xaf\xfe\xde\x5c\x87\xbb\x14\xde\xad\x30\x62\x29\x49\x5f\x69\x8f\x3e\x49\x06\x16\x96\x6b\x16\x36\x38\x7d\x0d\x86\x18\x3f\x94\x5b\x24\xa9\xdc\xfc\xcf\x4d\x36\x72\x2c\xd1\x2e\xbb\x6b\xd8\xe7\x83\x25\x75\x2a\xfa\x2b\x1a\xbd\x13\xc4\xbd\xbc\xad\xd1\x70\x86\x91\x36\x82\x62\x42\xac\xfb\x72\x1d\xe5\xff\x27\xba\x8a\xa0\xc0\x18\xb2\x25\xed\x34\x04\x80\x3c\xe9\xfa\x2d\x50\x8d\x89\x44"}, -{{0x05,0x54,0x60,0xb3,0x2d,0xd0,0x4d,0x7f,0x4b,0x23,0x11,0xa8,0x98,0x07,0xe0,0x73,0xfd,0x55,0x65,0x65,0xa4,0x77,0x18,0x57,0xd8,0x82,0x79,0x41,0x30,0xa2,0xfe,0x5d,},{0x26,0x0f,0x8f,0xed,0x4b,0xba,0x30,0xb9,0xe1,0x2a,0xd8,0x52,0x3f,0xbb,0x6f,0x57,0xf0,0xa7,0xa8,0x82,0x55,0x00,0x61,0xf1,0xda,0x46,0xfb,0xd8,0xea,0x44,0x22,0x21,},{0x23,0xf4,0xf1,0x62,0x7f,0xba,0xbd,0x78,0x91,0xd7,0xd8,0x48,0x96,0x31,0xc7,0x23,0x1d,0x22,0xde,0x71,0x86,0x4e,0x26,0x2a,0xb4,0xda,0x84,0xea,0x8a,0x13,0xa6,0x0f,0xea,0xc4,0xdc,0xfb,0x18,0x12,0xf1,0x20,0x04,0x44,0xb7,0x75,0xf1,0x21,0xd7,0x26,0x6d,0x75,0x5c,0xe9,0xb6,0xa9,0xad,0x79,0x65,0x59,0xc0,0xa2,0x6b,0x51,0x6d,0x02,},"\x74\x07\xf9\x6e\xe3\xe7\x9c\x69\xd3\x6c\xe1\xf6\x4e\x4f\x18\x86\x55\xea\x68\xb9\x47\xe7\xe2\xbe\x97\xb0\x5e\xbc\x6d\x44\x39\xe9\x50\x27\x6e\xf3\xf0\xe6\xa0\x3d\xd4\x8b\x24\xf6\x69\x29\xb4\x9c\x15\x80\xeb\x46\x88\x07\xe1\xe7\xa2\x5e\xb9\xb9\x4d\xa3\x40\xc5\x3f\x98\x4f\x8b\x81\x60\x3e\xfb\x61\x04\x7b\xf3\xf1\x4b\x68\x6d\x97\x98\x00\x3d\x2f\x68\x58\x9a\x79\xeb\xfa\xd5\x44\x09\xc7\x1c\x90\xff\x67\xc1\x1f\xbd\x76\xcc\x72\xc2\xd1\x45\xf4\x58\xe4\x2f\x88\xb7\x5d\x25\x0e\xad\xca\xfe\x66\xbf\x37\xff\xc8\x37\xb6\x2f\xf0\x06\x68\x5b\x7f\x85\xa9\xd8\x75\xfc\x07\x8c\x82\xe6\x1f\xe3\x5d\x19\x22\x52\x7a\x55\x1d\xab\x62\xf9\xe4\x77\x49\x91\x46\xba\xd9\x12\x20\x3e\x66\x4c\x41\x7c\x36\x79\xc0\x2d\x87\x2a\xba\xc0\x03\x2f\x8c\xc7\x7f\x77\xbf\xe5\x4d\x33\x26\xfd\xee\x92\x76\xa4\x8e\xa4\xeb\x25\x13\x50\x40\x68\x82\xd0\x8c\x83\x0e\x76\x49\xfe\x68\x54\x55\x8a\x75\x13\xab\x2d\x8d\x2a\xc3\xe5\xce\xd8\xa8\x08\xd2\xae\xe4\x54\x77\x9e\xda\xbd\x1a\xa6\x3b\xb1\x9f\x71\x8f\x47\x0b\xdc\x84\x51\xcd\x9b\x29\x49\x41\xe3\x49\x70\x63\xb1\xe3\x9b\x6c\xa1\x84\x56\x2f\xe8\x38\xcb\xfe\xee\x92\x2d\xe2\x4d\xdf\xcf\x98\x82\xc5\xe6\x15\xb1\x1b\xf9\x04\x81\x7f\xbd\x64\x71\x39\xdb\x80\xb4\xe8\xfe\xb3\x7f\x11\xe1\x85\x2d\x7e\x87\x6d\xb9\xcb\x63\xc9\x4d\x7e\xe3\x41\x92\xf7\x20\x0b\x5b\xc7\x7a\x03\x11\xae\x43\xb8\x06\xeb\xd4\xc2\x89\x6c\x53\xf5\x8f\x7e\xbc\x16\x25\xcb\x20\xd7\x10\x7e\xf9\xdb\x0d\xa2\x87\x88\x52\x3d\xe9\x91\xef\x6c\x58\x66\xb1\x8d\x8d\xe8\x3a\x95\x4d\x32\x81\xe0\x6d\xbf\x27\xc4\xf2\x38\x2e\x08\xcd\x0e\x0f\x6e\xba\xe3\xf9\x61\xb7\x7f\xce\x5a\x95\xa9\xb0\x62\x1b\x75\x6f"}, -{{0xe9,0xf6,0xd3,0x1b,0x93,0x69,0x42,0xc5,0x26,0xe0,0xf9,0xec,0x4f,0x5a,0x7a,0xc2,0x5f,0xa7,0x89,0xe0,0xc4,0x34,0xbc,0xd9,0x19,0x9d,0x72,0x0c,0x74,0x3c,0x84,0xc4,},{0x32,0x12,0x6d,0x26,0xe2,0x82,0x31,0xc5,0xb5,0x85,0xb1,0x3f,0x43,0xa0,0x1c,0x6f,0xe5,0x42,0x94,0x6b,0x07,0xd3,0xa9,0x1e,0x57,0xd2,0x81,0x52,0x3f,0x5c,0xb4,0x5c,},{0x7e,0x3b,0x1c,0x4c,0x71,0x6c,0x80,0x8e,0x90,0xb9,0x74,0x45,0x89,0x15,0xf3,0xb2,0x23,0x9c,0x42,0x07,0x71,0x19,0xfe,0x27,0x07,0x88,0xfa,0xe5,0x20,0x57,0x8b,0xd7,0xda,0x64,0x88,0x04,0x41,0x32,0xe1,0xbe,0xf2,0x3e,0x3b,0x23,0xc3,0x4d,0x9c,0x18,0x62,0x74,0x4f,0x28,0xfc,0xae,0xcd,0xa6,0xca,0xc0,0xfd,0x72,0xb9,0x3b,0x6a,0x0f,},"\xe8\x81\x33\xf3\xd1\x76\x42\xd5\xc2\x27\x79\xa8\x53\x16\xba\x0d\xf3\x4c\x79\x2b\x4e\xfe\xe4\x9e\xd7\xdd\x93\xca\x33\x22\xef\x47\xc7\x2e\x5b\x2e\x45\x95\xc7\x78\x00\x43\x4b\x60\x71\x9a\xdf\x54\xe4\xc1\xa3\x4c\x89\xfa\x1e\x27\xee\x8d\x35\xa0\x92\x1f\x97\x55\xac\x4a\x77\xa6\xc1\x68\x4e\xa0\xf5\xc8\xee\x5f\x75\x9c\xe5\x9b\xfe\x83\x15\x80\x0a\x67\xaa\x6c\x64\xdd\xfa\xac\x92\xea\xbe\x6c\x2c\x61\x37\x79\x78\x4b\x3a\xff\xaf\xcc\x62\x0f\x2a\x6d\xc5\xcb\x8d\x8d\xc7\xd7\x4a\xa4\xd7\x94\x94\x67\x84\x94\xe5\xe6\x39\x4c\x43\x3c\x14\x80\x9f\xf4\x0c\x9a\x59\x2d\x0d\x69\x4a\x81\x10\x3b\x44\x53\x1e\x1f\x48\xbc\x13\x96\x5d\x15\xaf\x8b\xf3\x34\x04\x88\xf8\xcd\x58\xf0\x9a\xe1\xa6\x61\x6b\xf8\x5a\xc9\xde\x7e\x0c\x66\x96\xaa\x2f\x1b\xec\x15\xe1\x7a\x44\xda\x4a\x84\xed\xb4\xec\x6d\x77\x24\x77\x88\xba\x0d\xe3\xae\x12\xa1\x55\xcb\xed\xc0\xda\x2f\x56\x8e\xef\x0b\x75\xa8\x77\xea\x5b\x0c\x2c\x0d\x4b\xf2\xc6\x1d\x46\x8a\x46\xfa\xad\xfa\xec\xe3\x5f\xc2\x63\xa9\xbe\x99\x87\xf4\xf7\xf7\x8f\x05\xc7\x07\x78\x43\x78\xc7\xb8\xf7\xda\xf9\xac\x3a\x12\x2a\xad\x39\xa1\x67\x79\x66\xda\x9e\xf2\x86\xc9\xe0\x62\xc4\xf4\x39\xad\x0b\xdd\xea\x26\xe5\x4b\x2f\x73\x88\xe2\x38\xb2\xa6\x49\x28\x45\x0d\x34\x56\x4c\x5a\x44\x7e\x7a\xfb\xbe\xdd\x10\x85\xf1\xf2\x4c\x11\xae\x08\x43\x22\xd1\xa3\x2c\xf8\xaa\x47\x39\x41\xf0\x0d\x56\xb1\x61\x82\x13\xca\xb3\x90\x0a\xa6\x06\x46\x3d\x9f\x80\x0e\x92\x6f\x9f\x42\xd4\xb0\x82\xd8\xc5\xec\x3a\x4a\x02\x5b\x45\xf9\xaa\xdc\x8b\xcb\xd1\x70\x91\xb3\xda\x49\xe9\x45\x3d\xc5\x5e\x89\xb5\xb5\xfe\x6b\x31\xf5\xed\xda\xd1\x0b\x66\x01\x57\x25\x68\xd8\xe2\x05\xd3\x25\x1a"}, -{{0x6b,0xf4,0xca,0xaa,0xbb,0x96,0x85,0x4a,0x38,0xa5,0x72,0xf4,0xce,0x6c,0x78,0x38,0xf7,0xe7,0x50,0x11,0x8c,0x73,0xf2,0x72,0x35,0x82,0x61,0x8e,0x23,0x07,0xf8,0x38,},{0x08,0x12,0x63,0x73,0xd0,0x56,0xf0,0x0e,0x54,0xb8,0xd4,0x3d,0x77,0xc3,0x5f,0x5f,0x91,0x98,0x33,0xe9,0x0d,0x8a,0xaf,0xd6,0xc8,0x24,0x6d,0x27,0x91,0x7a,0xd0,0x91,},{0xd2,0x11,0x3f,0x80,0xd6,0xcf,0x92,0x84,0x86,0xa2,0x50,0xa6,0x79,0xd6,0xe7,0x4b,0x35,0xea,0x9d,0x26,0x06,0x1f,0xa9,0x4d,0x76,0x9e,0x1a,0x8f,0xbf,0xa0,0xa7,0x34,0x22,0x7f,0x55,0x53,0x7e,0x4e,0xbf,0xf5,0x93,0x36,0xdb,0x14,0x1c,0xf5,0xd6,0xd4,0x82,0xa0,0x71,0x1f,0x1e,0x9f,0xc7,0x2f,0xf7,0x09,0x56,0xa1,0x1b,0x4f,0xb9,0x09,},"\x47\x76\xe9\xd6\x00\x85\x48\x1f\xa5\x37\xbf\x29\x5b\xda\xbd\x8b\x1c\xf6\x32\xa8\xcd\x40\xbc\xe6\xbd\x32\x5c\x12\x9f\x97\x70\x00\xe8\x84\x68\xeb\xf2\xdc\x15\x8a\xc0\xf2\x07\x21\x2d\xb0\x0f\xb6\x0b\x8e\xc8\xba\xe2\x29\x37\x2e\x9a\x6b\x01\x53\x0a\x7e\xd1\xbc\x9d\x38\x9e\xc8\x91\x3f\x59\x03\x0d\x5b\x54\xaf\x56\xae\x1c\xcc\x28\xf3\x7c\xc9\x6a\x8e\x53\x20\x4e\x92\xa6\x77\x76\x6a\xdf\xaa\xda\x99\xb0\x28\x1f\x86\x7f\x61\xac\x9f\xf7\xd9\x72\xee\x3e\xd4\x27\xd7\x2f\xaa\xe7\x5d\x4a\xec\x01\xb5\xff\xc3\x70\x61\xb6\xf0\xf7\xe5\x71\x4c\x4c\xf3\x0d\x5b\x73\x1b\x07\x46\x06\x5f\x19\xe4\xc8\x92\x2d\xde\x64\x2f\x80\xfe\x24\xa3\xc8\xdc\xb2\xe5\xf1\xc2\x66\xe2\xaf\x6c\x37\xde\xcf\x55\xa2\xba\xa5\x4f\x0d\x5c\xf0\x83\x93\x70\xc3\xe0\xb4\xe7\x7a\x4f\x36\xbb\xb3\x16\x20\x14\x93\x3a\x4a\x4e\xbc\xae\x8c\x60\x96\x1a\xc6\xdc\xf1\x34\xf3\x08\x28\xd3\x14\x02\xae\x74\xe7\xe8\x51\x3c\x9d\x2a\xd8\xee\x46\xb7\xa9\xd5\x3a\x1f\x87\xeb\xfc\xe0\x4f\x46\x1b\xde\xd1\x74\x9b\x6f\xc4\xc4\xf2\x57\x93\x52\x56\x92\xd7\xa0\xe4\x26\xc8\x4e\x06\x08\x2c\xc3\xe6\xab\xb5\x13\x68\x37\x0c\xbb\x10\x6c\x7a\x08\x97\xf6\x6d\x92\xc9\x73\x9c\xff\x9f\x27\x06\xd6\xa2\x98\x0e\xce\xa3\xac\x49\x45\xf0\xf4\x7e\x65\x6b\xd9\x63\x77\x77\xe8\x53\xd2\xa8\x39\x10\x43\x27\xdc\x04\x9e\xbc\x34\xf0\x49\xd6\xc2\xf8\x0e\xca\x99\xdb\x7b\x41\x84\x24\xac\xef\x75\x22\x60\xd2\xd4\x27\x94\x93\x23\x99\x7c\xd9\x61\x7e\xdf\x50\xd4\x41\xd0\x08\x8b\x1d\x47\x91\x2e\x35\xcf\x54\x23\x15\x26\x58\x29\xf3\x83\xf4\x58\x60\xd3\xb4\x5e\x73\x5b\xb2\xf8\x58\x6d\xcf\x58\xdb\x4f\x2a\xcf\xb4\xa6\x88\x53\xa9\x6e\xed\x7b\x89\x76\x9d\x36\x56\x13"}, -{{0x5d,0x95,0x85,0x73,0x6a,0xb2,0x09,0xb0,0xab,0xe8,0xbf,0x74,0xac,0xa4,0xee,0xa4,0xf6,0xd1,0x65,0x0b,0x53,0x25,0x50,0xa2,0x23,0xe0,0x44,0x58,0x0f,0x8e,0x20,0xde,},{0xe7,0x77,0x29,0xed,0xfd,0x21,0x44,0xb2,0xb1,0x20,0x78,0x76,0x54,0x17,0xfa,0x21,0xf1,0x59,0x4f,0x09,0xb2,0x69,0xe9,0xb6,0x70,0x68,0x02,0xb4,0xf3,0xbd,0xfe,0x85,},{0xe7,0xb0,0x8e,0x1d,0x58,0x09,0xfd,0xd8,0x52,0x94,0x43,0xd6,0x5a,0xda,0x5d,0xd6,0x55,0xea,0x55,0xb5,0x41,0x5a,0x01,0x13,0x93,0xbe,0x70,0x71,0x67,0x64,0x86,0xd3,0x58,0xe8,0xd2,0xa4,0x60,0xeb,0xe0,0x75,0xb0,0xe7,0x01,0xb2,0x4c,0x9e,0x3a,0xb5,0xf2,0xb0,0x33,0x59,0x2d,0x4d,0xe3,0xb7,0xf3,0x7f,0xd5,0x41,0xf6,0x92,0x09,0x09,},"\x08\x69\x35\x91\xe6\xc5\x8a\x5e\xad\x9c\x85\xfe\x8e\xc5\x85\x08\xf8\x1a\x34\x67\x63\x6c\x2d\x34\xfc\xc1\xf4\x66\xe5\xc6\xda\xfd\xc3\x7c\x35\xcb\xee\x35\x58\x9c\x69\x97\xe2\xb1\x54\x48\x13\x27\x44\xe5\xa1\xe1\x31\xbb\x49\xbf\x5c\x25\x63\xf8\x7e\xad\x3e\xfe\x01\xe8\x8c\xbf\x24\xcc\x17\x69\xc7\x8c\xdf\xc1\x67\xe3\x78\x21\x5b\x15\x85\x9c\x7a\x28\xec\xe7\x0e\x18\x8f\xa3\x30\x26\x7d\x3f\xc5\x7b\x4a\xce\x6c\x15\x20\xec\x67\x87\x50\x67\xfd\x33\xbe\x86\xf4\xa1\x96\x7a\xfb\x3e\xb1\x64\xc7\x97\xcf\x28\xd8\x07\x2a\xa6\x9d\x82\xaf\xa3\x83\x74\xf8\xe5\x79\x7c\x4c\x28\x47\x1b\x7d\x69\xf5\xb9\xc7\xb4\xac\xdb\xc1\x9f\x3c\x5c\x5d\x40\x08\x08\xa9\x82\xa4\x78\x37\xae\xd1\xb3\x84\x1d\x69\x89\x0e\xeb\x31\x49\x4e\x10\xe3\xe5\x13\xd1\x2d\x0c\xa6\x86\xc7\xce\x65\x17\x78\x09\x27\x03\xfe\xf0\xdc\xc0\x21\x40\x77\xdf\xb3\x61\x25\x1b\xde\xa4\x36\x4d\xd4\x1b\x97\xbc\xeb\x0f\xb1\x47\x5a\x50\xe4\x70\x8f\x47\xf7\x87\x8c\x74\x40\x1e\x97\x71\xcc\x3f\xce\xac\xe8\x91\x69\x98\x1a\xa7\x72\x50\x85\x00\x90\xd1\x81\xd8\x35\x8e\xbb\xa6\x5e\x29\x0a\xcb\x03\x52\xbe\xce\x8c\x57\x98\x32\xa6\x01\x55\x18\x16\xd1\xc0\x56\x21\xcc\xbb\xee\x0f\xbe\x39\xea\x2f\x19\x53\x93\x19\x9e\x69\xc2\x34\xc2\xfb\x1c\x37\xe4\x74\x84\x08\x60\xce\x60\x91\x61\xfc\xfc\xe2\x86\x95\x74\xbe\x0d\x38\xf9\x5e\x20\xf4\xf8\x72\x52\x47\xb9\x62\x7b\x46\xe8\x34\x90\x51\x01\xac\x12\xb9\x34\xcb\xf8\x7c\xb2\xd1\x90\xd2\xf5\x14\x90\xa8\x2c\x4e\x81\x0e\xdd\xb8\x1f\x95\x6a\x9f\x36\xbd\xa4\x97\xbc\xa5\x06\xa4\x9e\xe9\xcd\x47\xfd\xa5\xb7\xf2\xb8\x84\xa3\x64\x8c\xad\xd1\x2a\xb6\x18\x98\xad\xa4\x6e\xcc\x97\x0f\x81\xdc\x9f\x87\x68\x45\xdb"}, -{{0x60,0xb1,0x42,0xf1,0x65,0x11,0x41,0x43,0xca,0x30,0xa6,0x04,0xfe,0xf5,0x1c,0x68,0x64,0x36,0xaa,0x1b,0x9a,0xfd,0xb2,0x66,0xb3,0xe3,0x98,0xcc,0xb3,0xc4,0xd8,0x55,},{0xea,0xf6,0xc5,0xa7,0x6c,0xa9,0x9b,0xf7,0x30,0x64,0x98,0x88,0x8c,0x3b,0x7a,0x1f,0xea,0xe9,0x8b,0xf8,0x98,0x8d,0x7f,0x2e,0x15,0x47,0xf8,0xf5,0x3a,0x45,0x28,0xaa,},{0xa6,0x21,0xf0,0x84,0xea,0x1a,0x36,0xef,0x81,0x2a,0x97,0x55,0xc9,0xaf,0xbb,0x53,0xda,0xda,0xae,0x6b,0x3a,0x53,0xfa,0x83,0x44,0xca,0x40,0xd3,0x61,0x2a,0x26,0x8a,0x35,0xfe,0xd0,0xfd,0x39,0x8a,0xb7,0x5b,0xcd,0x63,0x9c,0x54,0x79,0x37,0xc9,0x41,0x55,0xab,0x1a,0x7a,0x34,0x67,0xdd,0x4b,0xfd,0xdf,0xac,0xab,0x16,0x55,0xe9,0x08,},"\x18\x15\xde\xe1\x17\x3b\x78\x26\x47\x20\xd3\x5b\x7c\xc2\x45\x4a\x00\x0a\x65\xff\xf2\x14\xe2\x47\x3e\x20\xbc\x83\xf3\xec\xde\x9c\x04\xc1\xe0\x69\x6c\xe6\xe5\x55\x19\xdd\x2a\x75\xce\x04\x64\xbf\x60\x1a\xdc\x38\x1e\x79\x3e\xcb\x9f\x8c\xe7\xab\x87\xb6\xca\x2a\x3e\x41\x0f\x63\x90\x69\x45\x19\x78\xd1\x48\x73\xd3\x39\x0f\xab\x86\x23\x96\x97\x13\xc3\xdf\xcd\x58\xd8\x6d\x12\x40\x73\x76\x1e\xe0\x9a\x65\x2a\x48\x76\x7f\x96\x46\xcb\x72\x6a\xc4\x54\xac\x9a\x1b\xc5\xfa\xed\x30\x26\xb7\x03\x98\x2b\xc2\xb1\xe0\x75\x82\x10\xe1\xd6\x25\x19\x23\x0e\xb2\xb2\xf4\xa4\x86\xbc\x55\x16\x85\x60\xc4\x36\x3d\xf5\xff\x5a\xdf\xda\x11\xac\x7e\xf5\x1b\x18\x19\x6c\x94\x33\x7c\x07\xae\xf1\x17\x99\x0f\x77\x0c\x0f\x1e\x8c\x0f\x88\xeb\x6f\xfc\x40\xe8\xed\x7c\x3a\x80\xa6\x32\xdb\x1e\x7f\x63\xb6\x30\x96\xe2\xac\x49\xe5\x77\x92\xb3\x11\x43\xe2\xf4\xfa\xab\xce\xae\x66\xb2\x74\x71\x68\x1c\x36\xfc\x11\x39\x00\x7f\x9b\x54\x8c\xdc\x6e\x3b\x8f\xbb\xda\xba\x7a\x8a\xdb\x84\x34\x31\x23\x8b\xb4\x61\xba\x24\xf6\xe0\x9f\x62\xc7\x2d\x63\x77\xb4\x04\x8c\xb0\x13\x4c\x25\xa5\x41\x1a\x20\xbf\xcf\xc1\x3e\x48\xd8\x0e\x36\xbf\xb0\xda\x7e\x01\x85\xd3\x3f\x19\x28\x63\x6e\x15\xde\xe0\xe5\xdf\x89\x92\xa1\x65\x72\xb1\x3e\xa8\xf7\xcf\x85\xca\xe3\x2d\x52\x9f\x66\xe8\xf6\xd2\xfb\x2a\xd0\xbb\xfe\x71\x99\x16\x9b\x25\x67\xba\x00\xc7\x81\xb2\x0a\x48\xe1\xd7\x0d\xf9\xfa\x31\x19\xcd\x7e\x5b\xbe\x58\x88\x4b\x0b\x51\x21\x89\x40\xfa\x81\x5f\x85\x62\x5f\xa2\x03\x47\x1c\xee\x80\x84\x78\x0e\xb0\xb9\x35\x6f\x9f\x3d\x4f\x6d\xf7\x40\x30\x1d\x70\x7e\xf1\xff\xb3\x51\x9e\x3f\x90\xb8\x06\x4b\x98\xe7\x0f\x37\x5d\x07\x14\x26\x88\x17\x18"}, -{{0x73,0x4b,0xa4,0x70,0x33,0xc6,0x14,0x02,0x32,0xdd,0x4a,0x7a,0x14,0xf1,0xa7,0x74,0x3e,0xef,0xe9,0x07,0x0b,0xad,0x96,0x62,0x49,0x16,0x30,0xcc,0x9d,0x28,0xc1,0xf3,},{0x2f,0xa5,0xdf,0x30,0x26,0xd6,0x07,0x42,0xe2,0xaf,0xf6,0xb5,0x78,0x42,0xc7,0x12,0x68,0x46,0xc8,0xa7,0xbb,0xe9,0x26,0x6e,0xfa,0x7b,0x3f,0x23,0x98,0xc3,0x57,0xea,},{0x9b,0xd0,0x74,0xd1,0xd0,0xbd,0x28,0x00,0x1b,0xaf,0x7d,0x2d,0x4e,0x82,0x43,0x5d,0xf0,0x8c,0x42,0x64,0xd8,0xcb,0xb1,0xc3,0x81,0x18,0x3c,0x2f,0x01,0x22,0x3f,0x79,0xf9,0x49,0x23,0xca,0x17,0x8c,0xac,0x75,0x56,0x4e,0x16,0xc7,0xf5,0x60,0x79,0x08,0x8f,0x7e,0xd8,0x85,0xde,0x4d,0x50,0x9f,0xbc,0x78,0xf4,0x38,0xfb,0xa3,0xf6,0x07,},"\x5d\x3c\x65\x98\x10\xc3\xfe\xa5\x2a\x6d\xf3\x86\x1e\x5c\xdc\x5b\x70\x3c\xc1\xce\xf4\x85\x58\xc6\x1d\x8c\x51\xd0\xed\xea\x5a\x14\x79\xcf\xe5\x06\x3d\x82\xde\xd9\xca\x68\x1e\x57\x48\x88\x7c\x40\xec\xfb\x9e\x1a\x9a\x8b\x7f\x85\x09\xd1\x07\x76\x46\x1c\x39\x23\x39\x96\x93\xa7\x81\x89\x08\x91\x78\xd5\xaa\xbd\x15\xf8\xc8\x46\x64\x2b\xe4\x7d\x6d\x4c\xaf\x13\x82\x4e\xdc\xef\xb8\x09\x86\x8f\xa7\x2d\xdf\x03\x5c\x4d\xe8\xef\x0a\x9c\x83\x22\x64\xf6\x6f\x01\x27\x61\xce\x69\x55\xbc\x3c\x41\x6e\x93\xe2\x91\x88\x02\x5e\xbb\xb1\x3a\x55\x32\x58\xc1\xd7\xc4\x99\xc9\xa4\xae\xb1\x0b\xb3\x6f\x61\xd1\xbb\x4c\xec\x5a\xe5\x5d\x17\x57\x22\xb9\xa9\x69\x6d\xf8\x81\x95\x1e\x35\x20\x0b\x96\x53\xcf\x6e\xd4\xb3\xd1\x5d\xe0\x87\xa9\xd1\xc3\x19\xfc\xe8\x58\x21\x56\xbe\xbf\x3f\xc9\x1e\x0e\x61\x0f\xf7\xa1\x53\x08\xfd\x1d\x2c\x60\x69\xfb\xbb\x29\x47\xd3\x11\x07\x31\xd2\x45\xae\x29\x63\x01\x4b\xd7\x6d\xea\x42\xdb\x12\x5c\xec\xc4\x93\xc8\xe9\x09\x1a\x76\x64\x65\x77\x72\x9a\xed\x49\x66\xfc\xe9\x69\x9f\xe1\x2e\x36\x7d\x66\x5d\xf9\xe9\x5a\x91\x93\xe1\x13\x3e\x14\x3a\xf9\x2f\x82\xb6\x6a\xc7\x76\x4e\x50\x33\x17\x86\x90\x52\x18\x09\xa7\x10\x7d\x8a\xe9\xb8\x8e\x0e\xd1\xf3\x5b\x17\x19\x90\x1b\x93\x0a\xd0\xe1\xcb\xce\x7f\xb3\x02\x67\xb1\x15\x52\x04\xf6\x05\xf5\x25\xe4\x9d\xe2\x98\x8e\xa7\xf7\x4b\xe8\x81\x51\x77\xfd\x97\x6a\x1b\xcc\x12\x6d\x9c\x9c\x13\x5c\x5b\x42\x76\xd3\x80\x19\xc3\x4a\xef\xb7\xa0\x22\x0f\x7f\x5a\xef\xf3\x80\xae\xd6\x27\xb0\x70\xc2\xc9\xe2\x15\x33\xbb\x35\xc0\x8e\x39\x4c\x85\xae\x25\xe6\x86\x29\x42\x59\x9c\x65\xdb\xae\x59\x77\xa5\x84\xa8\x81\x80\xe0\xc8\xc7\x1e\x5a\x84\x09\xe0\x4e\xf7"}, -{{0x45,0xe3,0x4d,0x0e,0xf4,0xc1,0x96,0xfa,0x6d,0x57,0x2b,0x6b,0x17,0x74,0xb5,0x21,0x8f,0x7c,0x32,0x91,0x30,0x4c,0x13,0x50,0x0d,0xf7,0x07,0x0d,0x90,0xe8,0x03,0x9e,},{0x13,0xa7,0x30,0x4d,0xff,0x42,0x33,0x59,0x17,0x7a,0xba,0xfa,0x5e,0x65,0x08,0xd2,0x67,0x69,0xca,0x99,0xcf,0x8a,0xf4,0x5c,0x38,0x3f,0x3f,0xf6,0x34,0x40,0x60,0x03,},{0xb4,0x2c,0x1f,0x92,0x5f,0x4b,0xac,0xcd,0x12,0x9e,0xfb,0x10,0x9d,0xb3,0x54,0xac,0xa3,0x1c,0x68,0x98,0xf4,0xf4,0x51,0x29,0x47,0x49,0xa2,0x6a,0x6d,0xa1,0x67,0x7b,0xd3,0xa5,0xc0,0x41,0x19,0xe3,0x5f,0x47,0x31,0x9f,0x20,0xcf,0xdf,0xc0,0x8b,0xb4,0x52,0x8b,0x21,0x00,0x9e,0x00,0xbd,0x41,0xeb,0xc0,0xf4,0x68,0x63,0xbe,0xd1,0x0b,},"\x3d\x9e\xd5\xc6\x4b\x75\xe1\x35\xdf\x2f\x5e\x85\x30\x0d\x90\xf2\x1b\x36\x39\x35\xe2\x81\x75\x56\xfc\x93\x11\x75\x1b\xa7\x53\x54\x77\xde\xc8\x35\x6e\xc3\x85\xef\xb8\x2b\x41\x40\x62\xf3\x5b\xb6\xd3\xed\xea\xfd\xe3\x05\xf9\x90\x0a\x25\xe9\x81\x3c\x9e\xe0\x23\x7d\x46\x40\x96\x50\xcd\xcd\xb5\xdf\xa2\x30\x1a\x8e\x26\x47\xf8\xd3\x81\x9d\x86\xf7\xb7\xe3\x07\x0d\x33\x44\x0f\x82\xc4\x05\x4b\x1a\xb5\xed\xeb\xeb\x27\xf9\x5b\x3c\x4c\x6f\xdd\x46\x8f\x21\x60\x0f\x03\xb3\x49\x4d\xa2\x00\xba\xb9\x29\x3c\x38\xd0\x2f\xc4\x40\x48\xe5\x2f\xf5\xfd\x0f\x72\x17\xa0\x4d\x4c\xe9\x12\xa1\x80\xd1\x62\x8f\x36\x82\x80\xb6\x89\x26\x72\xe8\xff\x98\xd4\x62\x9a\xc2\x8b\x60\xc0\x2a\x30\x1e\x6c\x60\x26\xc1\xb9\xe9\xef\x21\xcf\x03\x92\xdf\x22\x50\x08\xd5\xa0\xe0\x28\x4b\x28\x26\x31\xad\x17\x10\xf8\x11\x61\x56\x97\x06\x6c\x98\x29\x65\x19\x94\x8a\x7c\xfe\xd5\xae\xeb\x45\x4e\xe7\xa6\x1c\xc2\x71\xbd\x3d\x49\x9b\xe1\x7d\xf0\x9d\x3a\x0e\x79\x0e\xe6\xb9\xbd\x99\xe1\xb9\x19\xbe\xd4\xa0\x63\xb8\xd1\xa3\x4f\x1a\xfd\x2e\x95\x2b\x9d\xfe\xfd\x77\x09\x69\xc8\xb2\xfc\x37\x97\x7a\xbb\x0f\xee\x63\x17\x25\x3a\x23\xec\xc9\x75\x78\x16\x89\x73\x33\x4c\x8f\x91\x76\x3a\xb9\x7f\x29\xc4\x9b\xae\xee\x7b\x35\xf3\xae\x7f\x5c\xd3\xa4\xa6\xe6\x97\xef\x25\x5a\x3c\x2e\xc0\xc7\x52\xa3\x39\x6f\x69\xf6\x63\xca\x1f\xc2\xb3\x32\xdf\xe6\xc0\xfa\xf7\x8a\xfe\x9c\x68\xd9\x95\x71\xe8\xe8\x96\xc5\x09\x30\x85\xe9\x86\x3a\x27\x64\x8a\x9e\x58\xf3\xa9\xa8\x4c\xbb\xfe\x2b\x41\xca\x36\x33\xdd\x5c\xf6\xe8\x2c\xb7\x7c\xec\xac\xad\x8d\x78\xb3\x53\xf4\x8d\xb4\x2d\x99\xc3\x6b\xca\xd1\x70\xea\x9e\x98\xab\xb2\x78\x8c\x33\xa3\xc7\x06\x26\x8f\x36\x31"}, -{{0x88,0x8c,0xe2,0xec,0xce,0xda,0x9c,0xa2,0xb9,0x48,0xac,0x14,0x43,0xc2,0xae,0xdd,0x75,0x95,0xaa,0xcf,0x36,0xed,0xaf,0x27,0x25,0x5b,0xde,0x7a,0x69,0x91,0xdc,0xc0,},{0x01,0x6e,0x57,0x2b,0x4f,0x98,0x41,0x7c,0x6e,0xe2,0x97,0xab,0xd7,0x84,0xea,0x48,0x22,0x6f,0xf4,0xfb,0xf0,0x05,0x0a,0x5a,0xde,0x88,0x06,0xe7,0x04,0x6d,0x3b,0xa3,},{0x99,0xd8,0x3f,0x14,0x8a,0x23,0x6e,0xbb,0xef,0x1c,0xad,0x88,0xcb,0x3c,0x76,0x94,0xf4,0x98,0x6c,0x92,0x50,0xe2,0x1c,0x36,0x03,0xa0,0xd9,0x41,0xbf,0xf1,0x99,0xcf,0x77,0xd6,0xce,0x99,0xef,0xdb,0x20,0x53,0x31,0x88,0xd6,0x8a,0xd1,0x33,0xde,0x03,0x3a,0x1f,0xb3,0x46,0x8a,0xbb,0x70,0x6d,0x2b,0x8b,0x4f,0xba,0xc0,0x8d,0xfe,0x03,},"\x5c\x80\x1a\x8e\x66\x4e\x76\x60\x76\x0a\x25\xa5\xe1\x43\x1a\x62\x15\x9f\xc3\xf3\xaa\x71\x37\x80\xae\x7c\xbc\xe2\x3b\x85\x64\x78\x27\x99\xbf\x2b\xe4\x81\x7e\xe2\x92\x19\x65\xba\xb7\xe1\xd4\x48\x33\x82\x4c\x16\x28\xd4\x2d\xce\xe3\xe4\x6a\xe4\x2b\x28\x16\xd0\xa4\x32\xa1\xab\x0b\xd2\x1f\xcf\x30\xad\xb6\x3d\x8d\xd7\x65\x69\x54\x43\x43\xd0\x03\x5c\x76\x05\x22\xca\x68\xbe\xa7\x2c\x40\x4e\xdd\xa1\xe9\x09\x5e\xc9\x0f\x33\x25\x68\x1c\x6d\xe0\xf4\xc1\x2d\x1a\xfb\xcb\xa2\xc7\x87\x1a\x1b\x1e\x1f\x19\xc3\x5b\x0b\xed\x9e\xc2\xa8\x7c\x04\x3d\x36\xd8\x19\x39\x6b\xd5\xd0\x99\xe1\xaa\x09\x03\x91\x29\x7c\x73\x3f\x65\xa8\xc5\xd2\x12\x0c\x67\x63\x53\x16\xfa\xb2\x5b\x4d\x48\x47\xa4\x5f\xc3\xf7\x6f\x2e\x24\x26\xdb\xee\x46\x29\x97\x50\x62\xfc\xe1\x4e\x21\x89\xdb\xa2\x7f\xb1\xde\xd2\x45\x3f\x00\x1d\xeb\xfa\xa8\x99\xc1\x16\x60\x61\x2d\x2c\xe2\xad\x2f\x76\x2e\xa5\xde\xe7\xe7\x1e\x58\xad\xcd\xce\xfa\x79\xe8\xe8\xb2\x7f\xc4\xcc\xf8\x9a\xab\xf1\x76\xb5\xd3\x4f\x82\xdd\x15\xd8\x89\xf9\xf0\x87\xdc\x9a\xe8\xa4\x2a\x72\xf3\xb8\x35\x83\x61\x6e\x17\x06\x37\xcd\x1a\xdf\x38\xaa\x65\x51\xcb\xac\xca\x36\x02\xbd\xc7\xae\x21\x0c\x4a\x44\x6b\x3a\xf8\xdb\x27\x20\xe5\x49\xbb\xed\xb8\xbe\xd2\x15\xae\x00\xf1\x9d\xa2\x9d\x8f\xb0\xb6\x42\xd2\x7b\x2d\x88\x57\x5f\x0e\xe8\x4f\x3d\x12\x9e\xb7\x74\xd2\x0f\x53\x7a\x1c\x0f\xdc\xf7\x17\xbd\xeb\xcf\xe4\x7f\x83\x31\xa3\x41\x86\x43\x46\xfa\x6a\x1c\x6b\xbf\xd1\x78\x81\x9e\x38\x7a\x0d\x54\x99\xa6\x8e\x81\xcc\x9f\x82\xad\x39\xe3\x1e\x4d\xfe\x71\x95\x2d\x5e\xa5\xcc\x80\x52\xa3\xce\xed\x17\x51\xf5\x9d\xc7\xec\xc9\x74\x2f\xad\x14\x4e\x18\xdd\xa8\xd0\x58\x2e\x74\xe3\x9c\xa8\xc4"}, -{{0x61,0x73,0x90,0x85,0x7d,0xc1,0x0c,0xdf,0x82,0xb5,0xc9,0x42,0x61,0xf5,0x8c,0xe2,0xd4,0x4a,0xa2,0xf5,0x7d,0x29,0x8f,0x08,0xa2,0xd6,0xc7,0x4d,0x28,0x14,0x7d,0xaf,},{0x89,0xe0,0xc3,0xe0,0xa0,0xf1,0x30,0xd1,0x91,0x6e,0x0e,0x38,0x49,0xb7,0x28,0x6f,0xa2,0xe3,0xac,0x4c,0x17,0xbd,0x1f,0x71,0x6e,0xe5,0xa7,0x2f,0x02,0x57,0xfb,0x8d,},{0x63,0xe9,0x0a,0x6a,0xfb,0xbb,0xb0,0xee,0x69,0x6b,0xfb,0x56,0xef,0xd6,0x79,0xd6,0x8a,0x98,0x51,0xa8,0x94,0x76,0x40,0xa9,0x7f,0x41,0xf6,0x8e,0xdf,0xea,0xdd,0x21,0x6e,0xd8,0x69,0x8e,0x2e,0x43,0xc8,0x20,0xc9,0x04,0x4c,0xaa,0x7a,0xda,0xab,0x5b,0x76,0x76,0x2b,0x68,0x18,0x31,0xa9,0xf7,0x60,0x47,0x6a,0x84,0x43,0xc4,0x3c,0x06,},"\x1f\xd9\xe7\x45\x3e\xaf\xfd\x7c\x9b\x54\x05\x56\x22\xdd\xe1\x70\xdd\x58\xb7\x1c\xb9\x45\xde\x75\x35\x1d\x5f\xce\xb1\xf5\x36\xbd\xe2\x51\x58\xf0\x37\x86\x15\x5f\x95\x3d\xc2\x07\xa1\x70\x8f\x90\xd9\x5b\x15\xac\xa0\xae\xe3\x09\x7f\xdc\xaa\xe8\x5e\x4a\xb1\xc2\xcd\xb7\x05\xc5\x3e\x6c\x2e\xd2\x1a\x99\x4b\x30\x4a\x75\xca\xf2\xce\x4f\xc7\xd6\x1f\x56\x1e\x74\xe2\x97\x39\x7e\x2c\xde\x5c\xc6\x90\x56\x94\x03\x43\xaa\x81\x37\x5d\x0a\xf1\x8d\x17\xd2\xf3\x4c\x0a\x71\xdc\xf1\xde\x3c\x4f\xc4\x88\xa1\x4c\x5f\xa6\xb3\x33\x7a\x31\x74\xb1\xda\x79\x58\xfb\x00\xbd\x59\x55\x14\x82\x21\x42\x7c\x60\xdb\xa0\x41\x17\xc8\x0d\x24\x88\x65\x6d\xbd\x53\x43\xde\x89\x12\x87\xb5\x0e\xf4\xdf\x98\x25\xed\xa7\x6b\x49\x77\xf3\xac\xd4\xab\x6d\x31\x02\xfa\x56\x87\x83\x06\xcd\x76\x56\x14\x91\xbc\xfd\xaa\x1d\xa5\x67\xe6\x77\xf7\xf0\x3b\xae\x5d\xbf\x44\x26\xc3\xc4\xa6\xc3\xd0\x82\xf9\x17\x8b\x2e\xfd\xd2\xbd\x49\xee\xe9\x7e\xf4\xdc\xf3\xf0\xf5\x1b\xbd\xef\xfe\x5a\xe6\x60\x1e\x28\x01\x95\x18\xf8\x27\xf0\x2e\x51\xf6\x67\x9b\x87\x15\x97\x8b\xec\x3e\x69\xd5\x77\x15\x6d\xd7\x19\x95\x93\x71\xba\xf0\x34\x21\x9f\xbb\xd1\x7a\x23\x69\xa8\x54\x14\x90\xf6\xa0\x20\x13\xe3\x3e\x74\xf4\x76\x9b\xe3\x7a\xef\xa4\xde\xfb\x6b\xfb\x3f\x35\x1c\x2a\x26\x14\x82\xc2\xfb\xec\x49\xf8\x5f\x84\x45\x45\x6e\x8f\x5a\x47\x40\x30\xcd\x72\xd0\x95\xef\x6a\x62\x20\x30\xe1\xe4\x3a\x0c\x5d\xeb\xb0\x34\x73\x1d\x2f\x5e\x8e\x4b\xa3\x99\x0f\x07\x7d\x0c\x16\x26\x49\xd1\xfa\x3e\xa4\xfe\x1e\x81\xd7\x4a\xa8\x49\xe2\x1b\x05\x9d\x96\x6c\xba\xd4\xc4\x93\xca\x10\xba\xfe\x7a\x69\x24\x3e\x3c\x0a\x6e\xbf\xd1\x3d\x69\x79\x06\x30\x33\x92\xba\x65\xd4\xfe\x06\xb6\xa5"}, -{{0x87,0x7d,0x01,0x74,0x36,0x36,0x9e,0xc2,0x45,0x3f,0xed,0x46,0xe9,0x77,0xd6,0xac,0xc3,0xa7,0xbe,0x60,0xd3,0x13,0x95,0xad,0x6e,0x7e,0xa9,0xe0,0x74,0x80,0xe4,0xc9,},{0x4e,0x65,0x42,0x2f,0xed,0x33,0x4a,0x55,0xe8,0xb6,0x73,0x89,0x3e,0xba,0x7c,0x18,0x1d,0xd7,0x24,0xdd,0xa0,0x02,0x81,0x7b,0x0b,0xae,0x28,0xac,0xdc,0x3f,0x7f,0xc0,},{0x76,0x88,0xf3,0xf2,0x40,0x1e,0xac,0xaf,0x2d,0xd8,0x8e,0x17,0x0f,0xf1,0xc4,0xd7,0xe9,0x48,0x22,0xa7,0x7f,0x6b,0x55,0x0b,0x56,0x9e,0x82,0x15,0x2b,0xbb,0xb4,0x34,0x05,0x7e,0x01,0x23,0x0b,0x05,0xce,0x58,0xee,0x1d,0xee,0x52,0x26,0xb5,0xc7,0xcd,0xbe,0x5a,0x8a,0xde,0x3b,0x94,0x65,0xf5,0x9a,0xed,0x74,0x14,0x5d,0x14,0x33,0x0c,},"\x4e\xd3\xf5\xbd\xbd\x41\xd0\xe3\xb0\xa8\xa7\xfc\x37\x52\xee\xa4\x96\xd6\x14\x16\x78\xcb\xfe\x06\x75\x7f\x61\xe1\xa1\x68\xd7\x61\xb6\xda\x83\x05\x2f\x79\x94\x95\x0d\x24\x62\x6f\x00\x4f\xbe\x9b\x8c\x95\x62\xe0\xc9\x55\xfb\x3b\x5c\x08\xfd\x2d\x3d\x25\x83\x93\xa3\x49\x03\x0c\x8e\x15\x62\x05\xb4\x04\x83\x03\x8b\xe1\x95\x9f\x1c\xba\x49\x0a\x87\xfe\x13\x89\x9e\x4f\x37\x52\x06\x3b\x68\xfe\x3e\x1c\x50\x71\xf7\xdb\x00\x02\xf0\x14\x94\xb4\xa3\xee\x2e\x07\x99\x2b\xdd\x20\x0d\xb4\x31\x66\x29\xee\x8a\x95\xca\x34\x7f\x0b\x28\xd6\x40\x2a\x6d\xa8\xb5\x3e\x6b\x32\x58\x1c\x36\x91\xe1\x1a\xe9\xb6\xe0\xf0\x49\x48\x94\xe6\x49\xa9\x2d\x03\xeb\x49\xc4\xd6\x83\x3f\xa1\xf5\x4f\x8d\xcd\x91\xd0\x69\x36\xa6\xe6\x2d\x49\x1e\x2c\xea\x46\xdd\x07\xd9\xf0\x2d\x32\x54\xb8\x50\xbc\x97\x49\xf2\x58\xa6\x1a\xd3\xb9\xcc\x24\xb0\x32\x87\x33\x1b\x85\xa2\x41\x43\xaa\xf8\xfc\xcc\xac\x5f\x18\xbf\xc7\x2d\xec\x75\xc0\x23\x35\x16\xaa\x6e\x45\x89\xc7\x8c\x66\x5a\x18\x6e\xd9\x02\x09\x1d\xf9\x7b\x0d\x04\xe8\x3a\x2d\x74\xd7\x89\x89\x1a\xea\x2c\xac\xf8\x13\xff\xfb\x5e\xfa\xf7\x8d\xbc\xd7\xaf\x54\xef\x55\xc7\x7b\x1c\x4c\x8a\xce\x9e\x92\x78\xad\xc2\x3d\x76\xc7\x79\xd6\x4b\x3b\xbb\xd1\xfb\x33\xb0\x98\x36\xea\x64\xa7\x1e\x47\x11\xe8\x9e\x8d\xa0\xf7\x09\x21\x33\x42\x17\x6a\xe2\x2c\x6e\x78\x52\xc3\x97\x3b\x60\xd9\xf9\x88\x89\xb4\x42\xaa\x48\xd7\xbf\xdf\xde\xf6\x4c\x36\xc5\x86\xc4\xfb\x2a\xd2\xe2\x7e\xbe\x47\x9f\x6d\x72\x2f\x06\x9f\xd6\x10\x6b\x0d\x08\x97\x5d\x5f\x72\x15\x47\xc3\xb9\xc5\x2f\x9f\xc5\xf4\x5b\xb4\x5b\x5b\x63\x21\x88\xe8\x06\x26\x51\x8a\x79\x05\x6b\xdc\x4e\xe1\xd2\xbe\x6c\x65\x42\xa2\x1f\xad\xea\x92\xc6\xdf\xb7\x76"}, -{{0x4f,0x0b,0x36,0x07,0xd7,0x0b,0x0f,0x26,0x98,0x32,0x7e,0xf4,0xf1,0x98,0x2c,0x5b,0x4b,0x94,0xbe,0x78,0xf5,0x0c,0x76,0xf4,0x3b,0xd6,0x42,0xf1,0xf0,0xed,0xe3,0x9b,},{0x94,0x2b,0x43,0x08,0x9f,0xd0,0x31,0xce,0xc0,0xf9,0x9e,0x5e,0x55,0x0d,0x65,0x30,0x7f,0xb6,0xc3,0xe7,0x93,0x44,0x9f,0xb3,0x90,0xff,0x73,0x0f,0xff,0xd7,0xc7,0x4b,},{0xf3,0x96,0xa1,0x1f,0x2f,0x03,0xc6,0x14,0x39,0x68,0x4f,0x79,0x00,0x1b,0xd4,0xf3,0x46,0xa3,0x48,0xdc,0xf1,0xd3,0xbe,0xb2,0xd3,0xbf,0xe3,0x3e,0xa7,0x3a,0x5a,0xd4,0xeb,0x97,0x50,0x6a,0xcf,0xbf,0xfb,0x78,0x4e,0x77,0x54,0x81,0x89,0xcd,0x59,0x9f,0x8c,0xcf,0x17,0x35,0x5d,0xde,0x80,0xe7,0x50,0x24,0xef,0x2a,0x78,0xd5,0xfa,0x03,},"\x9f\x70\x0a\x1d\x25\x60\xf6\x9d\x9b\xc1\x05\xbc\x83\xbf\xf5\x39\xe4\x25\x8c\x02\x48\x60\x20\x13\xa9\x59\xb9\x78\xa1\x9c\xc2\x73\x28\x0d\x90\xc0\x17\x80\x89\x57\x8b\x50\x51\x8e\x06\xad\x1e\xab\x79\x0f\xfe\x71\x0c\x63\xd7\x88\x87\xa9\x55\x69\x14\x4f\x3e\x58\xa8\x83\x7f\x93\xdd\x51\x6f\xcd\xdd\x22\xbc\x97\xa7\xf1\x44\x11\xd4\x24\xb2\xe8\xe9\xaa\x7c\x28\x01\x19\xad\x94\xce\x92\x53\x3f\xc7\xfe\xa6\xc6\x62\x48\x64\x4a\xc3\xe1\xbe\xef\x25\x53\xa6\xf6\x1e\x91\xb9\x37\x9b\x0f\xe0\xc6\x8b\x40\x68\x14\x55\xb3\x11\xf4\x0d\xf0\xc9\x7f\x53\xfc\x95\x42\x42\xc3\x75\xe7\x70\x8d\x61\xba\xd9\xf5\x12\x96\x24\x72\x74\xfa\x01\xa7\x32\x8f\xa5\x00\x9d\x99\x95\xf5\x01\xae\x86\x83\x55\x2b\x11\xa4\x9d\x26\x38\x11\x67\x23\xb1\x31\x94\x50\xa9\x01\x38\xd2\x78\xcd\x95\x12\xb8\x0c\xa5\x79\x2e\xd1\x6c\x68\x3b\xef\x92\xec\x87\x88\x4c\x9f\x07\xf1\x37\xdc\x47\xa1\x31\x46\xe5\x11\x06\x5c\x2e\x1b\x4b\x80\xef\xde\x88\xae\x12\xe2\x94\x31\xbe\xb7\xae\xe3\x65\xc1\x6d\x80\x50\x6b\x99\xaf\xa6\xa1\x40\x6e\xdb\x06\x17\x66\x87\x58\x32\xdb\xa4\x73\xe5\x19\xdd\x70\x18\xf4\x02\xeb\x1b\xb3\x01\x4b\x7c\xee\x4f\x02\xe9\x80\xb1\xb1\x71\x27\xe7\xd2\x5d\xfe\x0c\x16\x8c\x53\x44\xf1\xc9\x00\x44\xf8\x27\x70\x7d\xca\x03\x07\x0e\x4c\x43\xcc\x46\x00\x47\xff\x62\x87\x0f\x07\x5f\x34\x59\x18\x16\xe4\xd0\x7e\xe3\x02\xe7\xb2\xc2\xca\x92\x55\xa3\x5e\x8a\xde\xc0\x35\x30\xe8\x6a\x13\xb1\xbd\xfa\x14\x98\x81\x30\x98\xf9\xba\x59\xf8\x18\x7a\xbc\xaf\xe2\x1b\xa0\x9d\x7c\x4a\xaa\x1a\xd1\x0a\x2f\x28\x33\x4a\xb5\x39\x96\x14\x7c\x24\x59\xc0\x1b\x6a\x10\x83\x9e\x03\x01\x12\x3d\x91\xa3\x5c\xed\x7a\xf8\x9a\xfb\xac\x7d\x9c\xf8\xac\x9a\x38\xce\xeb\xef\x83"}, -{{0xb8,0xa0,0x01,0x0c,0x78,0x4d,0x8d,0x00,0x2a,0x31,0xda,0x11,0xd0,0x22,0xd3,0x01,0x88,0xa4,0x19,0x7a,0x1d,0x5f,0x14,0xea,0x4c,0x0d,0xab,0x29,0xa2,0xe4,0x06,0x68,},{0x8b,0xdc,0x63,0xe5,0x0b,0xed,0xe1,0x3c,0x91,0xa4,0x1e,0x4b,0x4b,0x78,0x57,0xb9,0xe5,0x53,0xf4,0x84,0xe3,0xc1,0xec,0x16,0x7d,0xc0,0x4c,0x28,0x1e,0xa8,0x66,0x22,},{0xb3,0xf6,0xcf,0x4c,0x0e,0x0f,0x90,0x74,0xff,0x2c,0x2c,0x47,0xe1,0x63,0x20,0x2f,0x1e,0x9d,0x6e,0xe1,0x17,0xcf,0x75,0x76,0x33,0xe4,0xab,0xe7,0x44,0x23,0xaa,0x70,0x00,0x8a,0xda,0x15,0x09,0xec,0x1d,0xc1,0x17,0xc1,0xc2,0x30,0xe9,0xb2,0x37,0x86,0xf3,0xd0,0xf2,0x9b,0x73,0xaa,0x28,0x45,0x36,0xe9,0x58,0x01,0x06,0xa8,0xa7,0x0c,},"\x5c\x6c\xcb\x29\x8b\xe2\x16\x80\x8b\x81\x1e\x56\xd9\x72\xf4\x56\xb6\x9a\xd3\x95\x94\xee\xe3\x54\x70\x1c\xa6\xb3\xe3\x8d\x1f\x41\xa3\x59\xe5\x51\x2a\xf9\x8a\x3a\x08\x73\x26\x5f\xe5\x19\x1f\x4f\x2e\xca\xf6\x6b\xee\x75\xa3\xac\x0b\x71\xa4\xdd\xf2\xa7\x59\xeb\xdd\xdb\xd8\x8a\x6a\x1c\x6f\xd0\xfc\xf7\xd7\xcb\x92\xa8\x4e\x33\x07\xb4\xa4\xf9\x8c\x71\x0a\xbf\x4f\x55\x3d\xee\x74\xf6\x52\xd2\xac\x64\xbc\x30\xf7\x2b\xf4\x35\x4e\xf7\xe8\x06\xa1\x90\x71\xa0\x51\xbc\xfc\xfb\x27\xe3\x7f\xdd\xd4\x1e\xce\xae\xc1\x75\x8e\x94\x69\x5c\x67\x0e\xf4\xc5\xa5\x90\x21\x78\x32\x9d\xb9\x58\x5c\x65\xef\x0f\xa3\xcd\x62\x44\x9b\xb2\x0b\x1f\x13\xae\xcf\xdd\x1c\x6c\xf7\x8c\x51\xf5\x68\xce\x9f\xb8\x52\x59\xaa\xd0\x5b\x38\xc6\xb4\x85\xf6\xb8\x60\x76\x92\x8d\xdb\x4e\x20\x36\xf4\x5e\x7b\x9c\x6a\x7f\xf2\x4a\xe1\x77\x60\x30\xe2\x57\x68\x25\x01\x9a\xb4\x63\xeb\xf7\x10\x3a\x33\x07\x20\x33\xea\xcb\xb5\xb5\x03\xf5\x32\x66\xaf\xb8\x2f\x9b\x24\x54\xb8\xdc\x05\x7d\x84\xf3\x0d\x9d\x2c\xb7\xc3\xa3\x1a\x7d\xbd\xfb\xa5\xb8\xe4\x92\x31\xc2\x31\x39\x6c\x47\xca\x04\x2c\x8e\x48\xa1\xa5\xe3\xec\x9a\xfe\x40\x20\x59\x53\x90\xf9\x99\x0d\xfb\x87\x4e\x08\x25\xae\x9a\xe5\xe7\x52\xaf\x63\xaf\x6f\xd3\xe7\x87\xe7\x5e\x8d\x8d\xc4\xc6\x63\x02\x27\x7a\xc0\x1b\x30\xa1\x8a\x56\xcb\x82\xc8\xa7\xeb\xdc\x91\x5b\x71\x53\x25\x5a\x1f\xed\xc4\x92\xe4\x96\x60\x26\x2b\xb2\x49\x78\x0d\x17\x3e\x1f\xd2\x0d\x18\xc4\xf6\xb0\xb6\x9a\xa2\xec\xa0\x24\xbf\x3c\x80\xd7\xd5\x96\x2c\xc4\xa1\x29\xa7\x94\x3b\x27\xf3\x3c\xc7\x99\xa3\x60\x45\x54\x12\x75\xa2\xcd\xb9\x2a\x40\xe4\x85\xba\x8b\x73\x7a\x04\xb4\x3d\x29\xc3\xe2\x5f\x76\xcb\x3d\x93\xa6\xb9\x44\x61\xf8\x8f\x56\x96"}, -{{0xef,0xc8,0x6c,0xbe,0x40,0x36,0x3a,0xbf,0xbb,0x2a,0x4b,0x1f,0xcc,0xe5,0xfd,0x60,0x84,0xda,0x96,0xe7,0xe8,0x14,0xde,0x71,0xaa,0xdf,0x9a,0x61,0x8f,0x30,0x36,0x25,},{0x22,0xf2,0x95,0xce,0xe7,0x27,0xd2,0x8d,0x2b,0x93,0x17,0x15,0x3e,0x7d,0x94,0x12,0xda,0x10,0x65,0xc1,0xb1,0x6a,0xe2,0xa2,0x51,0xdd,0x1f,0xb4,0x31,0xc6,0x2b,0x01,},{0xf8,0x81,0x83,0x10,0x22,0x8c,0xa7,0x61,0x11,0x52,0x4c,0xe9,0x4b,0xfc,0xb0,0x24,0x6e,0xa6,0x35,0x08,0xce,0xe9,0x30,0x65,0x92,0xb2,0xf7,0x75,0x48,0xed,0xef,0xcf,0x76,0xbd,0x14,0x54,0x50,0x8e,0xa7,0x15,0x04,0x2c,0xec,0x16,0x9c,0xea,0x51,0x15,0xab,0x54,0x23,0x5c,0xb1,0x09,0x7b,0x10,0x70,0x2a,0xa3,0x83,0x78,0x02,0x8e,0x0c,},"\x9e\x4f\xa4\x5d\xc0\x26\x71\x0f\x6b\xef\x4e\xd0\xf0\x7c\x54\x4b\x0b\xb0\xd8\x8f\xa7\x9e\x71\x77\xd8\x44\x8b\xc2\x09\xd7\x1c\xfe\x97\x43\xc1\x0a\xf0\xc9\x93\x7d\x72\xe1\x81\x9e\x5b\x53\x1d\x66\x1c\x58\xc6\x31\x41\xce\x86\x62\xc8\x83\x9e\x66\x4d\xb7\x9e\x16\xc5\x4d\x11\x3a\xbb\x02\xa7\x5b\xdf\x11\xb3\x45\x3d\x07\x18\x25\xbc\x41\x57\x41\xe9\x94\x83\x54\x6b\x8e\x1e\x68\x19\xde\x53\x01\x70\x92\xe4\xef\x87\x1f\x1c\xa0\xd3\x50\x8f\x93\x78\x28\xa4\x66\x7d\xb1\x1f\xff\xf9\x41\x6e\xeb\xb9\x4b\xf9\xb8\x4d\x65\x46\x03\x09\x48\x34\xa9\x9c\xa7\x0b\x90\xf5\x62\xa8\x68\x23\x62\x4d\xfe\x9c\xb2\xf9\xe8\x8c\x17\x3f\x13\x46\x4d\x4c\xe2\x55\xf2\x22\xdb\x50\xdd\x63\xab\x42\x46\x57\x34\xe7\x52\x95\xc0\x64\xb6\x4c\xc3\xf1\x5e\x62\x37\xe3\x7f\x33\xd6\x15\xf7\xc2\x43\xe4\xba\x30\x89\x60\xcf\xd4\x39\x34\x02\x52\x55\x00\xbb\x79\x02\x97\x0b\x39\x31\xd4\x8b\x35\x66\x6a\x2d\x4d\x2a\xb0\x8f\xa1\x2a\xf3\x66\xa0\x04\x34\x6c\x9d\xd9\x3d\x39\xfb\x1b\x73\x40\xf1\x04\xe5\x1f\xed\xbb\x53\x36\x05\xb5\xff\x39\xcf\x6d\x59\x51\x3f\x12\x85\x6d\xcf\xa1\x98\xd7\x93\xb0\xfc\x87\x5c\xde\xa0\x74\x1f\x14\x55\x74\x6d\x8a\x19\xc3\xe9\xd9\x28\xf0\x02\x1b\x01\xc2\x51\x31\x81\x1e\x48\xc3\xc7\x5c\x6f\x41\x42\x2a\x88\x10\xc6\xc8\x1f\x35\xb4\x54\xee\xae\x8c\xd1\x7c\xf3\xf2\xe6\xf0\xbc\xd9\xf2\x90\x98\x4f\x49\x65\x78\x62\x3a\xb8\xe2\x73\x8d\x2d\x10\x84\x0e\xb9\x1d\x10\x1c\xb4\xa2\x37\x22\xb7\x2e\x3d\xd1\x85\x44\x0c\x3b\x9f\x44\xd4\x6a\x39\x3a\x34\xc1\x87\xa2\x0d\x61\x0b\xb6\x98\xc5\x05\x31\x74\x1e\xfe\x96\x32\x35\x12\x32\x98\x00\x77\x2a\x40\x80\x65\xa7\xef\x8e\x4e\x41\x05\xeb\x1f\x5b\xf6\xd3\xfd\x6b\x21\x7f\xd8\x36\xd8\x9f\x53\xb9\x6f\x45"}, -{{0x33,0x55,0x6c,0x60,0xde,0x2f,0x2c,0x9a,0x93,0x03,0xb9,0x9a,0xdd,0x37,0x85,0x92,0x06,0x05,0x05,0xf8,0xe4,0x98,0x61,0x08,0x5a,0x4b,0x15,0xf0,0x72,0xa7,0xef,0x28,},{0x23,0x1e,0xc8,0xcd,0x84,0x58,0x59,0xf6,0x99,0x61,0x27,0x51,0x19,0xdb,0xe4,0xf7,0x15,0xe5,0xec,0x5a,0xa9,0x8b,0xb8,0x74,0x16,0x75,0xb3,0xc2,0xd0,0xc8,0x9f,0xee,},{0xe0,0x6a,0x7a,0x41,0x44,0x57,0xbb,0xbe,0xf2,0xba,0xc3,0x77,0x5c,0xca,0xd0,0x87,0xda,0xcb,0x1f,0xa4,0xbf,0x93,0x88,0x94,0xe8,0xc9,0x29,0x11,0x8e,0x09,0xe6,0x78,0xdd,0x19,0x93,0x8b,0xc8,0x8f,0x43,0xed,0x0f,0x7d,0x31,0xcc,0x6a,0x0e,0x60,0x2c,0x4e,0x4d,0x1f,0xee,0x33,0xd4,0x1e,0x74,0xa1,0x19,0xfa,0x2d,0x1e,0x4e,0x34,0x0f,},"\x96\xaf\x54\x0e\xa2\xb1\x92\x3f\x5f\xd0\xaa\xd3\x21\xac\x03\x20\x70\xc2\xd6\x5b\xa1\x3d\x16\x4e\x75\xc3\x46\x97\x58\xfc\xf3\x1b\xb3\x16\x55\xcb\x3a\x72\x1f\x9c\xb3\x4b\xe2\xc9\x0c\x77\xeb\x65\xbe\x37\xf6\x06\xd3\x2a\x91\x7a\x4c\xb9\xa7\x09\xac\x07\x05\x22\x99\x30\xef\x6e\xb6\xfd\xb0\xfa\x3c\x0f\xd3\xa9\x0c\xe1\x71\x67\x4e\xe3\xed\x06\x35\x4b\xaf\xc3\xc7\x07\x54\x67\xa5\x74\x45\xb8\x03\x85\x64\x04\x47\x90\x2b\xe3\x92\x62\x89\x4b\x1f\x64\xfe\xa5\x82\x87\xdc\x32\x2d\x19\x87\x59\x72\xa7\xc8\xbe\x91\xd3\x1f\x02\x1c\x70\xeb\x68\x2f\xdf\x11\xa1\x0f\x8f\x58\x2a\x12\x6e\x06\x47\x94\x83\x8c\x69\xfd\xf6\x4f\x5b\x6e\x8b\xa5\x9d\x48\xb4\x38\x4f\x8e\x9f\xb5\xc0\x87\xcc\x77\x38\x29\x5c\xd3\x23\x44\xba\x3b\x69\x7e\xe6\xb6\xa8\xb7\x8e\xe7\xa9\x57\x5c\x97\x97\x2a\x4d\x1b\xb1\x84\x86\xf9\x03\x7a\x0f\x3c\x6f\x47\x1a\x90\xf8\x64\x98\xdb\xc0\xdf\x52\x32\xc0\x7e\x8c\x01\xb6\x90\xbe\xe7\x53\x02\x99\x2a\x7a\x36\xfb\x44\x37\xc2\x5a\x8b\xf5\xe3\x4c\xf7\xd5\xb5\x55\x72\xc7\x00\xa0\x79\x84\x8d\x38\x13\x64\xf9\x94\x6a\x91\xeb\x16\x03\xff\x3d\xe5\xeb\xdd\x52\x3b\xd9\x25\x64\x81\x8e\x23\x7a\x53\xe8\xf5\x22\xde\xaa\x2c\x29\xb8\x97\xe9\x61\x58\x6e\x10\x0e\xd0\xfc\x0a\xd7\x0d\x16\x09\x34\xe6\x94\x02\x7e\x5c\x95\x79\x20\xbc\x05\x46\xe9\x01\xbe\x39\xa8\x45\x35\x59\x7e\x1f\x28\x0c\x22\x22\x67\xab\xe9\x7f\x41\x20\x5d\x81\x71\x82\x0d\xd2\xfa\xaf\xc0\x69\x94\x19\x32\x1a\x91\x60\xf6\x9b\x99\xfd\x41\x18\x09\x45\xb6\x2d\x2d\xd1\x05\xcc\x7b\xbe\x82\x1d\x28\x60\x5e\x09\x8e\xdf\xa8\xb2\x30\x9a\xeb\x05\x34\xe7\x56\x37\x7f\x59\x93\x7c\x67\x46\x3f\xd8\x7c\x8b\x92\xab\x58\x11\x9c\xf4\xce\x6c\x66\x5a\xf5\x72\xfb\xae\x1d\xe4\xa2\xcc\x71"}, -{{0x7a,0x5c,0x74,0x31,0x4e,0x11,0x83,0x33,0x4a,0x4b,0x62,0x26,0xb9,0xa8,0x2d,0x70,0xfc,0x2a,0x12,0x4e,0x3f,0x87,0xdb,0x6a,0x22,0x83,0xee,0x05,0xb6,0x8e,0x34,0xe0,},{0xbe,0xae,0x7d,0x3d,0xd9,0x7c,0x67,0xf6,0x27,0x3b,0xfa,0xa0,0x66,0x13,0x1f,0xed,0x8a,0xce,0x7f,0x53,0x5f,0xe6,0x46,0x4e,0x65,0x79,0x1c,0x7e,0x53,0x98,0x57,0x6c,},{0xc2,0xab,0x1f,0x6f,0x51,0x14,0xa8,0x4f,0x21,0x85,0x02,0x58,0x2c,0x56,0x7b,0x37,0xa8,0xbd,0xbc,0xdf,0x63,0x40,0xfa,0x46,0x22,0x87,0x3b,0xe8,0x91,0x06,0xf0,0xa9,0x0b,0x48,0x29,0x50,0x5f,0x72,0x12,0x9d,0xf0,0xab,0x3d,0x85,0x13,0x26,0x87,0x74,0xa3,0x4d,0xf3,0xad,0x21,0xce,0x25,0x4b,0x46,0x44,0x88,0xad,0xdd,0x6c,0x9b,0x04,},"\x98\xba\xc6\x72\x47\x55\x91\x29\x92\xad\xc2\xa4\x8b\x54\x42\x37\x6f\x2d\x92\x79\x97\xa0\x40\xfb\x98\xef\xe5\x44\xeb\x0c\x8e\x18\x66\xb9\x61\x6e\x29\x8d\x33\x60\x31\x6e\xd9\x76\xbd\x94\x6a\x41\x1f\xdd\x3a\x6b\x62\x5c\x0c\x1a\x37\xaf\x0f\x41\xcf\x65\x69\xa7\x88\x4a\xb8\x46\x74\x91\xa9\x87\xdf\x3e\xa7\xa0\xb7\xeb\xc4\x69\x25\x69\xa3\x4c\xe3\xa2\xea\x35\x03\x49\x5b\x2c\x02\xd4\x9d\x7d\x7d\xb5\x79\xd1\x3a\x82\xcf\x0c\xf7\xa9\x54\x7a\x6e\xae\xbe\x68\xe7\x26\x7d\x45\xa6\x0b\x8d\x47\x72\x45\x52\x28\xcc\xa4\x03\x6e\x28\x2e\x1a\x12\x16\xf3\x4c\xef\x7e\xa6\x8f\x93\x82\x70\xbd\xb0\x42\x93\xc8\x85\xd0\x05\xf9\xf7\xe6\x38\xa8\xb4\xea\xd2\x62\x6c\x09\x45\x17\x4f\xf2\xa3\xe2\xd6\xe1\x5a\x4c\x03\x38\xc0\x9e\x12\x60\xf0\x92\x8c\xa9\xd3\x49\x98\x24\xf3\xfe\xdc\x47\x85\xda\x49\xc5\xc3\x4a\x56\x85\x5e\x24\x1f\xac\xc6\x34\x7a\x39\x9d\xdc\xac\x43\x99\xa8\xb1\x58\x19\x8c\x15\x14\x61\xa3\xb1\x89\xe5\x8e\xc1\xf7\xef\xcf\x2a\xb2\x03\x1f\xb1\x7b\x6f\x03\x5b\xa1\xf0\x92\xe9\xee\xe2\xe9\x2c\x2d\x6c\xc2\x03\x22\x87\xf8\x54\xb4\x1e\x70\xfc\x61\xc8\xd1\x1a\x2e\x4f\x07\x08\xf0\x2e\xeb\xd0\x2e\x8c\x7e\x8c\x7b\x38\xa5\x7b\xfa\x1a\x74\x5f\x3a\x86\xc2\x39\x09\xf6\xf8\x9a\xb1\x6c\xe7\xe1\x81\x3c\x1d\x20\x14\x7f\x31\xb4\xcf\x2a\xd0\xb6\x06\xfb\x17\xe5\xac\x1a\xb5\x1e\xf4\xa7\xd8\x09\x3c\xee\x9a\x65\x5f\x47\x1d\xc5\xb1\x46\xbd\x1b\x93\xe5\x40\xa3\xd3\xd3\xe2\xde\x81\x05\x91\x1c\x10\xd6\xab\x5f\xf7\x9c\x2d\x06\x02\x7f\x7a\x54\x56\x1f\x20\x71\x41\x4b\xd3\x30\xa8\x78\x54\x42\x25\x1c\x81\x0e\x23\x2f\x83\xc3\x67\xf0\xbe\x77\x99\xa9\x3f\x52\x38\xf7\xf1\x7b\x5b\xe8\x29\xfd\x89\x12\x3c\x04\x83\x3a\xf8\xb7\x7e\x5a\x43\x63\x04\x7c\xec\xa7"}, -{{0xda,0x80,0x06,0xad,0xc4,0x92,0xca,0x5d,0xc8,0x6c,0x29,0x59,0x43,0x7a,0x75,0xde,0xb6,0x12,0x0f,0xf7,0x87,0xd2,0xec,0xb9,0xc2,0x0c,0x30,0xb5,0x2c,0x26,0xbc,0x41,},{0xff,0x11,0x3b,0xf0,0xaa,0x58,0xd5,0x46,0xf2,0x38,0x5d,0x44,0x4e,0xcb,0x78,0x88,0xf8,0xca,0xba,0x43,0xa1,0x74,0xa8,0x9f,0xd6,0x06,0x5f,0x2b,0x7d,0xc1,0x7b,0xf0,},{0x1f,0x53,0x75,0xdc,0xb3,0xad,0x2b,0xaa,0xff,0x95,0x6d,0x85,0x54,0xec,0xb4,0x24,0x17,0x6b,0xe9,0xa6,0xeb,0x9e,0xa5,0x4e,0x81,0x4e,0x0a,0x73,0xdf,0x2a,0x5d,0x84,0x8a,0xda,0x26,0xba,0x8e,0x18,0x05,0xcd,0x51,0xc5,0xe1,0x69,0x50,0xc1,0xff,0x7d,0x4d,0x27,0x64,0xda,0xa6,0xf4,0xc7,0x50,0x2f,0xb8,0x65,0xcb,0xe5,0x5a,0xaf,0x0b,},"\x3e\xb4\x32\x4d\xbc\x01\x49\xd2\xe7\xd6\xdf\x63\x2b\xb0\xcb\xe9\xa9\xf6\xdf\xa8\x3e\x22\x7f\xc0\x7b\xde\x1b\x57\x7b\x36\x11\xfb\x92\x1c\x9f\x83\x13\xf0\x68\xe6\x29\x5d\x49\x13\xa8\x19\x6b\xe5\x30\xf6\xa0\x1f\x57\xc0\x9c\x02\x84\x91\x44\x4b\x78\x47\x20\xe9\x09\xea\x1f\xb6\x9c\x1c\x1d\xd6\x30\x44\x00\x32\x7b\x77\x31\xb3\x3c\xc4\x6d\xeb\x04\x6c\xda\xb6\xad\x1b\x53\xf1\x74\x9a\x0c\x65\xcb\x9a\x7e\x37\x6f\xfa\x02\x23\x0f\x53\x65\x84\xae\xa2\x43\xc6\x39\x10\x3a\xdb\xba\x76\x43\x21\x64\x9d\x7e\x01\x26\xf8\x2e\x0b\x4f\xd9\xdc\xb8\x6c\x73\x1c\xbc\xc5\x17\xf2\x01\x68\x41\xe9\x16\xbc\xd5\xfd\xe8\x71\xdc\x09\x8c\xd9\x13\xdc\x54\x62\x84\xd1\xb2\x16\x5c\x63\xe8\x8f\x32\xa2\x78\x9a\x50\x08\x56\x37\x1b\x50\xd2\x2f\xb8\xc8\x7d\x1a\x3c\xae\xdc\xdf\xd0\x1e\xe5\xf8\x70\xa5\x3c\x28\x41\x81\xd6\x32\xec\x66\xd4\x8b\x6b\xdd\x56\x46\xac\x39\xc9\xe7\x53\x38\xa5\x20\x21\x20\x62\xbc\x34\x66\xef\x5c\x58\x76\x55\x70\xb9\x05\xf6\x3a\x93\xd0\x7f\x8f\x1b\xaa\xc3\x52\x6b\x01\x6d\xa7\x99\xf3\xe9\xe0\x3a\x4f\x7f\x81\x35\x5e\x0f\x7a\x76\xf3\x0a\x42\xb8\x07\x32\x20\x51\xb7\x1c\x62\x6a\x7a\x29\x6d\x75\xb9\xd9\xd1\xa2\x3b\xcb\x13\xc9\xef\x48\xa9\x12\xdc\x05\x73\x25\xd3\xbc\xfb\x3f\x9f\xad\xaf\x0c\x24\x9b\x10\x2a\xeb\x85\x4a\xa3\x63\x1e\x34\xf6\x9a\xd9\x0c\x2a\xb2\xed\x33\xba\xcc\x40\xb9\xed\x10\x37\xfa\xe6\x7c\xdf\x79\x9d\x5a\x9b\x43\x78\x59\x61\x12\x7d\x62\xf8\xe0\xbc\x15\x89\xfd\x1a\x06\xfc\xa2\xae\xa7\xcf\xc0\x12\xcb\xf7\xb5\xb2\x07\xdd\xc4\xe6\x77\xd8\xae\x4a\xec\x10\x00\x45\xce\x36\xc0\x0b\x74\xd1\xd2\x82\x50\x79\x12\x36\xdc\x5d\xcc\x1e\xd3\x13\xc8\xc2\x46\x17\x26\x66\xf7\x52\x17\x43\x7c\x60\x34\xac\xd6\x41\x98\xcd\x96\xdf\x2a"}, -{{0xa2,0x84,0xe2,0x6b,0x97,0xe5,0x38,0x83,0x9c,0x80,0x8d,0x45,0xbd,0xe6,0xf0,0x12,0xa3,0x54,0x45,0x4a,0xef,0x81,0xca,0xa8,0xc5,0x59,0x14,0x62,0x4f,0x2b,0x7d,0x66,},{0x5a,0xe4,0x6e,0x34,0x69,0x5e,0xfa,0xf4,0x63,0xa4,0x20,0x8f,0xc4,0xe3,0x5b,0x81,0xf2,0xc6,0x35,0x93,0x23,0x8a,0x56,0xf2,0x44,0x4b,0x85,0x0f,0x05,0x8c,0x3c,0x5c,},{0xbf,0x11,0x0e,0x2e,0x9c,0xec,0xbc,0x31,0xfa,0x3e,0x0c,0x24,0x38,0xcd,0x1f,0x43,0x21,0xf9,0x2c,0xd2,0x87,0x00,0x5a,0x48,0x52,0x8a,0xdd,0xf7,0x6c,0xad,0x8d,0x88,0xbb,0x22,0x71,0x9e,0xf9,0x1b,0x13,0x95,0x62,0xa1,0x51,0x18,0x38,0x68,0x26,0x74,0xfa,0xa9,0xff,0x7e,0x7a,0xde,0x6c,0x9d,0x57,0x3f,0x84,0x50,0x36,0xd1,0x89,0x05,},"\x9e\xbf\xe9\x10\xb5\x0a\x5c\xb7\x19\xd9\x5b\x96\x1e\x59\x05\xf0\x0e\xc7\x94\x3b\x55\x46\x8a\xb5\x95\x66\x92\x01\x76\x45\xb3\x66\x07\x1f\x8f\xbb\x77\xeb\x49\xec\x73\xea\x7d\x64\x51\x14\x05\xb9\x0d\xe2\x2d\xb9\x8c\x3e\xae\x39\xc4\x03\x9c\x7a\x13\x34\x30\xe8\x01\x0b\xdd\x39\xa0\x0f\xd1\xa5\x28\xb1\x13\xda\xe1\x49\xcf\xad\x3a\xe3\x40\xda\x27\xdc\xc5\x07\x78\x2e\xcd\x89\x29\x23\x75\x17\xaf\xe7\x46\x3e\xca\x24\x73\xc7\xac\xf6\xf7\xaa\x04\xef\xc9\xf2\x66\xae\x7b\x6d\x63\xbb\x8c\xc2\xa4\x38\xb3\x44\x82\x7f\x07\x13\xd1\xf1\x73\x6f\x0c\xbb\x65\xb9\x93\x53\xf2\x03\x55\xfa\x02\x30\xd4\xfa\x70\x73\x28\xa8\x66\x26\x54\xe8\x3a\xd0\x53\x0a\x10\xf9\xa6\x9e\x17\xc0\x99\xe1\xe2\xb5\xdb\x18\xe5\xf6\xf1\xdc\xed\xa5\x88\x3e\x8c\xab\x79\x70\x1a\x5e\x90\x89\x56\x2e\xd1\x53\xad\x08\xc6\x74\xf0\x97\xc2\x8e\x4d\x16\x63\x3e\x09\x29\x69\xa8\xf0\xbd\xac\x54\x52\x7c\x0e\xe0\x3b\xc2\x00\xe5\xbe\x61\x2e\x3d\x1e\xab\xd8\x70\x91\x10\x1b\x49\x62\xaf\xa0\x7b\x31\x08\x06\x99\x2f\x37\x30\x76\xd7\x6a\x58\x18\x51\x18\x13\x7c\x9d\x26\xee\x2c\xd4\xc6\x18\xc1\x82\x83\xdd\x19\xf0\xe7\xa0\x89\xee\x37\x30\x5b\x6b\x95\x18\xa7\x8d\x80\x98\x43\x6e\xf6\x2b\xe7\xd6\x99\x80\x8a\xce\xcf\x67\x93\x9d\x61\xb3\xe0\x29\x37\xcd\x8c\x5f\x1e\x74\x6d\x42\x74\x33\x4b\xc9\xc3\x7f\xdc\xba\x23\x4c\x16\x6f\xd7\x12\x89\x3f\x3a\x04\x08\x32\xec\x54\x25\xe5\x7d\x80\xf1\x1e\xf9\xca\x5f\xbc\xd6\xc1\x47\xfb\xbf\x5e\x2f\xae\x74\x6e\x0d\xdb\x60\x58\x67\xe3\xbd\x05\x04\x83\xc3\xcd\x13\x29\xab\xe5\x7a\x60\xbf\x88\x89\x8d\xc7\xe8\x0e\xde\x0f\x45\x17\xde\x8f\xc8\x07\xe8\x88\xb6\x21\xa0\x0f\x66\x30\x84\xff\x94\xb9\x99\x96\x62\x8f\x3b\x11\x69\x0a\x60\xf0\x91\x8c\xb5\xc9\xa7\xef"}, -{{0xcc,0x97,0xa9,0x63,0x01,0xce,0xed,0x0f,0x92,0x27,0x31,0xb6,0x85,0xba,0xd8,0xad,0x4f,0x06,0x20,0x7b,0xe3,0x40,0xf5,0xa4,0x4f,0xd1,0x87,0xf2,0x99,0x03,0xec,0x20,},{0xeb,0x56,0x3a,0x7b,0xce,0x12,0xdb,0x97,0xf1,0x89,0x1d,0x0f,0x61,0x0b,0xeb,0xd5,0x51,0x01,0xa3,0x12,0x5c,0xa8,0xdb,0xb5,0x0b,0x25,0xa6,0xb5,0x05,0x0d,0x37,0x84,},{0xff,0xbd,0xd3,0x24,0x41,0x81,0xcd,0xf6,0x03,0x4f,0x4a,0x45,0x0f,0xdd,0x95,0xde,0xe4,0x97,0x1a,0x93,0x3f,0x8b,0xe0,0x22,0xbb,0x0a,0x41,0x06,0xae,0xf3,0x9a,0xf3,0x05,0x5b,0x72,0x18,0x81,0xc9,0xb5,0x4d,0x1e,0x99,0xb9,0x40,0x90,0x96,0xfb,0xe6,0xdc,0x2c,0x99,0x66,0xe3,0x67,0x99,0x64,0xbd,0x7e,0xf4,0xc8,0x08,0xca,0xbf,0x01,},"\xb9\xea\x3b\x3d\xf7\x18\x7e\xa4\x15\xa3\xc3\x35\xe0\x83\x4e\x10\xf4\x40\x91\x5b\x2a\xd4\x1c\x71\xf2\x55\xd6\x95\x0a\x4e\x91\x20\xe4\xd4\x94\xfd\x9e\x67\x2c\xe5\x32\x06\xfd\xc4\x17\xd8\x65\x89\x7b\x47\xac\x10\x54\xe1\xca\x10\x68\x19\x52\x32\xd4\x29\x74\x35\xe4\x4e\x12\x24\xe6\x6a\x91\x2d\x9d\x7d\x18\x29\x46\xff\x5a\x9f\x08\x5b\xb8\xba\x19\xc5\x4d\x16\xb5\x86\xa9\xb3\x04\x61\xb6\x77\x3b\x93\x95\x03\x11\xe1\x61\x98\x86\xf5\xa5\xb3\xf1\x11\xaa\xad\x09\x4b\xae\x31\xc4\x8f\x19\x41\x08\x09\x68\xbd\x02\x77\xbb\x6f\xa9\x2e\xeb\xf3\x24\xb1\x92\xdf\x5c\xc9\x69\x51\x6c\x78\xc7\xb2\xd1\x21\x59\xb4\xd1\xc8\xeb\x03\x16\x0c\x4c\xd1\x90\x7f\x62\xed\x4b\x85\x4c\x56\x9e\xcc\x48\x1c\x08\xe6\x36\xf4\x4e\xd7\xc3\x90\xe5\x8b\x59\x37\xd2\x90\x6b\x28\x17\xbc\x37\x69\xda\xd9\xda\x1b\x0f\x79\x39\x1b\x55\x94\x20\x63\x05\x5d\xa0\xd6\xf2\x49\xa3\xe4\x52\xba\xdd\xaa\x03\x29\x98\xd7\xf7\x33\x98\xcc\xd0\x15\x1b\xfc\x92\xc5\xe2\xfd\xfa\x9b\x14\x85\x5e\x6b\x0d\x37\x46\xdc\xe2\x48\xe2\x19\x67\x29\x87\x25\x2e\xc7\x47\xdf\x27\x47\xfd\x3f\xbd\x8b\x71\x4c\x88\x2d\x70\x7e\xe3\x02\xa9\x04\x95\x0c\x34\x75\x4f\x85\x35\x0e\x1a\xa3\xf8\xea\x62\x93\xcf\x01\xf7\x17\xce\xfb\x6b\x83\xa2\x21\x26\xdf\x5c\x4f\x56\x98\xaa\xfd\x06\xa2\x24\x4a\xd7\xd0\x1f\x34\x01\x7c\xa0\xec\xe6\xf2\x10\x40\x04\x8a\xba\x6c\xa4\xae\xb0\x43\x25\xb9\x40\x2b\xcd\x43\xab\x13\x0a\x10\x57\x88\xac\x3d\x7b\x7d\xa0\x1e\xa9\x42\x6d\xd0\xea\x19\x33\xa8\x18\x99\x33\xa6\xc0\xc6\xcd\x64\x8e\xa3\x16\xa7\x46\x9a\x5f\xdc\x6e\x7c\x93\x4d\x91\x86\x58\x60\x97\xb5\x5d\xd5\x1a\xc4\x87\xbb\x80\xed\x11\xd4\xdf\x8d\x33\x62\x6b\xbc\xe9\x5e\x4f\x13\xbd\x49\x92\x2f\x00\xc9\x20\x22\x3f\x4c\xbf\x93\xcb"}, -{{0x67,0x9e,0x3e,0x34,0x77,0x3a,0xbe,0x4a,0xe2,0x5c,0xae,0x7d,0x07,0xcc,0xd0,0xeb,0x3b,0x0e,0xc0,0xa3,0x5d,0x57,0x02,0x57,0xd6,0x25,0x70,0xde,0x58,0xea,0x25,0x16,},{0x18,0xac,0xff,0xce,0x25,0x3b,0x27,0x25,0x95,0x79,0xed,0x99,0x24,0xf4,0x79,0xca,0xe3,0x12,0x16,0x7b,0xcd,0x87,0x6e,0xdb,0xa8,0x8b,0x5d,0x1d,0x73,0xc4,0x3d,0xbe,},{0x1a,0x51,0x02,0x26,0x28,0xcc,0xbb,0x88,0xea,0xe9,0xb2,0x17,0x73,0xc3,0xf8,0x30,0xb7,0xb6,0xe5,0xbc,0x36,0xc9,0x90,0x3c,0xe7,0x0f,0xbc,0xf4,0x59,0xd6,0xa1,0xed,0x8a,0x1d,0xce,0xff,0x5b,0x19,0x26,0x9e,0xbf,0x5a,0x6f,0xd3,0xd8,0x95,0x88,0x60,0xf5,0x54,0x46,0x1f,0x0e,0x9f,0xc0,0xe2,0x9a,0xf9,0xb1,0xfb,0x17,0x44,0xa8,0x0b,},"\xfb\x2b\x64\x8e\xbb\x16\x68\x82\x44\xf7\x8b\x2e\xe9\xa2\x73\x59\x9d\x56\xb6\x19\x89\x00\xd4\x38\xa9\xe9\x9c\x19\x14\x25\xc7\x2b\xec\x4f\x23\x58\x47\xe1\x8e\x47\xf5\x7c\x3c\xb3\x96\x65\x5f\x77\x89\x21\xf9\x08\x58\x0e\x8e\x83\xc9\x6c\x10\x8b\x20\xdd\x41\x66\x78\x02\x1b\xca\x25\x9b\x98\x51\x8f\xab\xb2\xd3\x53\x2e\x48\x51\xd9\xd5\x2a\xdd\x25\x42\xc0\xcb\x3e\xfa\x38\x57\xa1\x7e\x51\x24\x38\xbc\x0e\xc4\x76\x2e\x2f\x9b\xab\xa4\x29\xc0\x3e\x99\xbe\xc4\x03\x8e\x6b\x0c\xa4\x2b\xff\x5b\x23\x3b\x24\xc3\x33\xb4\xca\xea\xd2\xde\x37\x4a\x87\xb2\xab\x5d\x80\xd6\xe4\x9e\x44\x56\x32\x9d\x51\xae\x97\x3b\xc8\x3d\x78\x62\xf3\xd3\x15\xe5\x14\x48\x1b\x12\x85\x4a\x9d\xfc\x09\xe7\xd1\x4f\x0d\x02\x2c\x0b\xa3\x02\x25\x78\xeb\xa8\xf8\x74\xde\xba\x4a\xa8\xc8\x33\xf2\xb1\x32\x86\x1d\x4d\x51\xe5\x0f\xe9\xaa\x4b\x78\x7b\xd2\xf0\x51\xaa\xc5\x0c\x37\x53\x90\xcb\xbc\xfb\xa2\x00\x2b\x80\xad\x00\xcd\xc1\x29\x80\xf8\xba\x8b\xcb\x70\x64\xaf\xc0\x4d\x5c\x46\x82\xc1\x02\x9b\x10\xa6\xd4\x5f\xe6\xec\xd7\x04\x24\x5f\xaf\x59\x8c\x46\x59\x59\x7c\x5d\x68\xa1\x92\xcc\x1c\xd4\xfa\x45\xe8\x4b\x54\x9e\x8e\x5e\x67\xda\xa8\x79\xae\x5a\x52\x0a\x6b\x55\x50\x51\x98\x76\xa5\x62\xac\x49\xc6\xdb\x0a\xa7\x6e\xc6\x9b\xb6\x4d\xd6\xb5\xe1\xa3\xaf\x2e\x13\x1e\x72\x2e\x7c\xdd\x05\xbe\x34\xb5\xfc\xc6\x25\x9a\xa1\x24\xcc\xf8\x14\xcf\x5b\x50\x0d\x17\x6b\xe2\x8e\xbc\x40\xbb\x21\xf0\x3e\x24\xcc\xc1\x31\xe0\xf4\x1d\xaa\x1c\xa0\x2e\x6b\x00\xc9\xc5\x3f\xad\x12\x48\x61\x4e\x94\x0d\x4b\x23\x77\x60\xab\x75\x69\xa7\x67\xb7\x51\x5d\xd2\xd6\x23\xe5\x7a\x28\x41\xb7\xd2\x44\x1c\xf4\x30\x49\xe4\x69\x8d\x2f\x9c\x9e\xae\x7b\x29\x10\xf6\xad\x65\xed\xf9\xcb\x2b\xdb\xd9\xb2\x9f\x60\x6e\x0d"}, -{{0x9b,0xfa,0x60,0x92,0x3a,0x43,0xed,0x0c,0x24,0xe2,0xf1,0x2f,0x5b,0x86,0xa0,0x71,0x63,0x29,0xf9,0x3d,0x4d,0x8d,0x3e,0x06,0x23,0x80,0x02,0x89,0x32,0x78,0xc1,0x9a,},{0xfb,0x1c,0x00,0x68,0x77,0x81,0xb5,0x5b,0x89,0x3d,0x6b,0x2f,0x4f,0x49,0xcf,0x5f,0x73,0xd2,0x90,0x3c,0x31,0x6d,0x1e,0xee,0x75,0x99,0x1d,0x98,0x3a,0x18,0x68,0xc0,},{0x55,0xf2,0x02,0xef,0xb2,0xa5,0x7b,0xe8,0xb4,0xe4,0xfd,0x89,0x4d,0xcc,0x11,0xa4,0xfc,0x5f,0x82,0x76,0x61,0x8e,0xf5,0xcd,0x34,0xa4,0x49,0x5a,0xdb,0x01,0x6a,0x29,0x8e,0x64,0x80,0xa3,0x5c,0xfc,0x53,0xed,0xb2,0x5f,0xf1,0x49,0x9f,0xc5,0x32,0xa3,0x30,0x61,0xcc,0x01,0xa2,0x50,0x45,0x8a,0xa5,0xe4,0xf7,0xf1,0x6f,0x51,0x44,0x0d,},"\xa9\x90\x28\xb0\xf4\xa3\xaa\x5e\x79\xab\xef\x6c\x0d\xf4\xa7\x83\xef\x47\x0f\x1a\x29\xba\x51\xeb\xa0\x0f\x62\x14\xe8\x40\xfe\x19\xe5\xb6\xdc\x60\x21\xab\x59\x9b\xb2\xee\x36\x99\x57\x60\x15\xd7\x9a\x79\x39\xaf\x82\x35\x35\xb6\x30\xe3\x93\x8c\x72\x3f\x6e\x0b\x92\x29\xd4\x6b\xb3\x37\x9a\xcd\xba\x58\x7c\x23\x85\x67\xe3\xd8\x9b\xc3\xbd\x35\x19\xb7\x27\xfc\x69\x4f\xff\x11\x18\xbf\x22\xc8\xbc\x8b\xc8\x2c\x4d\xf7\xf5\xad\x38\xde\x05\xfe\x9f\x76\x29\x99\xec\xaa\x79\x5f\x3a\xe6\x30\xa9\xa3\x16\xd2\x6d\xce\x9f\x15\x68\xff\xa3\xf2\x2b\x02\x95\x21\x40\x20\xb3\xd3\xf5\x33\x7c\x14\x95\x68\x19\x22\x18\x13\x2a\x90\x70\x92\x79\xc0\x1d\x23\xba\xef\xa6\x69\xe1\xc4\xe4\x20\x38\x17\x3f\x13\x19\xc2\x12\xda\x14\x4f\x1c\x4e\xa4\xc5\x2c\x00\x5c\xbc\x0b\x5b\xc2\x83\xe7\x44\x83\xa0\xdc\xa6\x92\x79\xde\xb1\x7a\xe5\xb2\x9c\xfa\xfa\x7d\x00\x63\xf4\xe1\xbc\x93\x53\x7e\xfd\x93\x7e\x58\xa8\xac\xa7\x37\x22\x8f\x93\x7f\xf2\xa7\x41\x89\x0e\x96\xc5\x72\x5d\xa1\x1b\x45\xc4\x13\xa9\xbb\xb4\x18\x0a\x41\x99\x87\xbb\xf0\x46\xbf\xd3\x46\x29\x5d\x62\xf0\x81\xc7\x6d\xaf\x2b\x0e\x1e\xb4\xf6\x71\x2f\xee\xbe\x6f\x0a\x92\xe3\x58\xe7\xdd\xb8\x58\x96\x50\x7c\x34\x0a\x01\xf6\x8d\x1b\x0f\x08\x57\x78\xb7\xc4\x4b\x01\x4a\xa6\x67\x3e\x50\x17\x96\x95\x9a\x17\xa6\x88\xdb\x09\x59\x05\x84\x88\xa7\x11\x25\x72\xf2\x3c\xf9\xcd\xb5\x3b\x5e\xb4\xb4\x5f\x59\x53\xba\x0c\x0c\x69\x0f\x86\xbd\x75\xe8\x9a\x04\x7b\xeb\xaf\x84\x7c\x1d\xfc\x34\x5a\x4f\x3c\x7d\x3b\xee\xc9\x8b\x84\xb0\x21\x90\x03\xe8\x19\xf5\xc2\xad\xb4\x5f\x87\x17\x90\x3d\x1f\x5b\xd5\xd7\x19\x14\xc5\x6f\xca\xbc\x7a\x29\x0f\x9c\x41\x69\x9c\x95\x58\x4d\x6a\x3a\x16\x34\x0c\xb1\x7b\xaa\x1f\xc5\xe5\x46\x7a\xf7\xac\x32\x21"}, -{{0x6e,0x3a,0xf4,0x5e,0x66,0xe2,0x28,0x90,0xc3,0xf3,0xc9,0x34,0xf5,0x23,0xa4,0xd6,0x94,0x27,0x97,0x6e,0x6e,0x52,0x62,0x5f,0x8b,0xad,0x55,0x89,0x93,0x96,0x32,0x19,},{0xe0,0x97,0x36,0x4e,0x76,0xff,0x9f,0x2e,0x1d,0x16,0x7f,0x6b,0x20,0xc1,0xbc,0x58,0x30,0x08,0x5e,0x7e,0xc9,0x93,0xc1,0x38,0xf8,0xb1,0xb2,0x17,0x56,0x37,0xe7,0x41,},{0x26,0xba,0x56,0x2e,0x8a,0x40,0x65,0x70,0x82,0x07,0xc2,0x5e,0x23,0x9b,0x78,0x0a,0xee,0x38,0x79,0x4c,0xf9,0x83,0xa3,0x7a,0xcb,0xb9,0xd5,0x57,0xa6,0x5c,0xee,0xd3,0xc0,0xda,0x47,0xd1,0x7f,0x3e,0x8b,0x8f,0x4e,0xeb,0x1b,0x65,0xa2,0xc1,0x82,0xea,0x6f,0x29,0x62,0x3b,0x63,0xbb,0x0f,0x1c,0x72,0x59,0x26,0x83,0xb1,0x26,0xb9,0x01,},"\x5c\xfc\x2f\x4b\x55\x9f\x82\x05\xb3\x91\x02\x08\x76\x17\xf4\xd8\x6c\x7c\xe6\xcb\x25\x1e\x5f\x89\x60\x1d\xfc\x88\xed\x28\xe8\xd7\xa6\x70\xec\x00\x87\xd2\xea\x5d\x89\x30\x21\xc7\x04\x4d\xa2\x89\x9a\x22\xd7\x76\xfe\x90\x17\x0e\x51\xc2\x03\x25\x06\x90\xd3\x7a\x29\x45\x55\xe7\x4a\xf9\x23\x4c\xbf\x1a\xd8\xf2\x2c\xee\x89\x74\x82\x8a\x0d\x09\xe9\x55\x4b\x71\xee\x3b\xcf\x88\x0a\xb9\x83\x25\xf7\x06\x27\x21\x94\xeb\x2e\x80\xc7\x01\xd4\x41\xb5\xf8\x66\x85\x61\xb8\x88\x49\xf8\x27\xaf\x70\x3a\xb0\x95\x41\x05\xfd\x3c\x54\xb3\xf6\xec\x54\x93\x59\x6d\x0e\x3b\xc6\x78\x18\x04\x83\x10\xc4\xa3\xe0\xc5\x56\xbc\x80\x67\x5f\x20\x1f\x9b\xb9\xc6\x53\x8a\x41\xd9\x9a\xa4\x0c\x88\x6f\xc4\x31\x46\x72\x18\xd8\x19\xc2\x3e\x78\x49\x8a\xed\x06\x13\xfa\x6f\x97\x3e\x22\x11\xdf\x9f\xb8\x7f\x44\x11\x6f\x3f\xe4\xc2\x6d\x6c\xb2\xfa\x33\x4c\x87\xf7\x8c\x08\xca\x8c\x9b\x90\x41\xd8\x3a\x12\x30\x67\x7e\x0a\xf7\x88\x59\x8a\x42\xe4\x4c\xfd\xf6\x96\x4a\x4e\xe8\x0e\x38\x40\x2b\xa6\x7c\x73\xa5\x81\xe5\x52\xba\xa2\x28\x24\x25\xcb\x2c\xa1\x7c\xa9\x2e\xdf\xbf\x98\x29\x91\x02\xfb\xa7\x61\xb9\xb7\x1a\x54\x52\x14\x1b\xb9\xc1\x8d\xd9\x5f\xeb\xc2\xa7\x82\xde\x9c\xee\xc0\x8b\xd2\xee\x3f\x7f\x0c\x1b\xd8\x94\x6d\xba\x99\xcf\x9e\xa0\x86\xab\xaf\xd3\x7c\x9c\xa6\x02\x13\xf0\xde\x17\xc6\x1f\xf9\xc3\x91\xc9\x81\x8e\xd5\xcd\x85\x71\x77\x8b\x7d\xcc\x13\x22\x49\x62\x38\x6f\xb8\xca\x14\xf8\x61\xe9\x9f\x3b\x18\xed\xac\x8a\x5f\x13\x0f\x7b\xfc\xd4\x5d\x04\x5d\x0f\xf3\x4c\x81\x57\x2a\x51\x23\x63\xd6\x53\x0f\x93\x81\x3e\x5f\xb1\x0e\x9c\xb8\x33\x8a\x7f\x93\x80\x04\x91\x00\x6f\x44\x63\xe8\x9f\x0e\xd4\x53\x0e\x5f\x12\xdf\x67\x4f\x59\x89\x04\x78\x0a\xd0\x81\x2b\x1e\x35\x21\xfc\xd0\xf8\x3e"}, -{{0x5f,0x1f,0x27,0x18,0x44,0xd9,0xed,0x5a,0x6a,0x6f,0x20,0x9a,0x21,0x40,0x8d,0xae,0xa4,0x70,0xf6,0xfd,0x53,0xba,0x64,0x79,0xd7,0x40,0x71,0x05,0xb7,0xde,0x4d,0x65,},{0x60,0x85,0xd7,0xfb,0x5a,0x9b,0x2e,0xd8,0x06,0xc1,0xfd,0x30,0xa2,0xaf,0xde,0x76,0x09,0x61,0xf7,0xa3,0x6b,0x48,0xf4,0x87,0x52,0x46,0xe6,0x15,0xa2,0xbd,0x99,0x28,},{0x31,0x9b,0xb4,0xde,0xb2,0x17,0x81,0x12,0x24,0x1b,0x3f,0xb8,0xf4,0x6e,0x10,0x5c,0x3b,0x8e,0x4e,0xf7,0x21,0xeb,0x20,0x0d,0x76,0x2e,0xf3,0x63,0xe2,0x71,0x6f,0x2a,0x89,0xf8,0x0b,0x5b,0x9e,0x89,0x97,0x08,0x90,0xa0,0x98,0x92,0xad,0x6a,0x58,0x80,0x8b,0x47,0x7e,0x94,0x3b,0x3c,0xfa,0x77,0x77,0x4a,0x36,0x45,0xbc,0x74,0x5f,0x03,},"\xee\xd6\xb4\x47\x5d\xc2\x63\xbd\x22\x07\xfe\x9d\x41\xd4\x82\x82\xb7\x13\xf6\x80\xf2\xe0\x37\x38\x4f\x18\xb4\xbf\x22\x43\x47\xf5\xe4\xc4\xb0\x60\xb8\x08\xd4\x12\xea\xab\xcf\x73\x3d\xc3\x9a\x40\xc6\xbd\xa0\x50\x5c\xe7\x1f\xa8\x23\xbd\x1b\x17\x94\x84\x76\x78\xdc\x03\x4e\x79\x99\xc1\x63\x69\x34\x0b\xc6\x0c\x64\xd0\x9b\xb9\x18\x7b\x2e\x32\x60\x55\xa0\x53\xf8\xe5\x05\xea\x41\x96\x86\x14\x71\x62\x2d\xb0\xe4\x6f\x0f\x89\x54\xd8\xa1\xf0\x73\x32\xda\x4d\x8a\xc5\x57\x12\x62\x60\x09\x91\x2f\x8a\x15\xa9\xcd\x63\xa7\x4a\x03\xc9\x2f\x24\x6c\xb6\x3c\xc7\x3f\x92\xe5\x1d\xad\x1b\xc9\x71\x5b\x1e\xd3\xfe\x5f\x2e\x1b\x29\x59\xb9\xb7\x1e\x0e\x37\x36\x0e\xb2\x95\x36\xcf\x79\x71\x47\xfa\xb1\x08\x64\xd6\x14\x6c\x36\xb8\x23\x35\xa0\xce\x93\x14\x08\x47\x9c\x7e\xde\x48\x4f\xf7\x3e\x2d\xbf\xff\xc6\xc9\x22\x7e\x16\xd7\xa2\x3f\x4d\x90\xf1\x55\x84\x51\x4c\x39\x59\x4e\x17\xbf\xbb\x29\x5d\xe9\xd6\x2a\xda\xdb\x58\x9d\xbb\xe0\xb0\x6d\xc8\xda\xc5\xb3\xbf\x51\x7b\x24\xc1\x83\x7b\x39\x47\x2a\x6d\xd3\x89\x31\xff\xbb\xff\x5b\x76\x36\x38\x80\x5b\x4e\x22\x32\x1f\x7a\xfe\x92\xcd\xf5\x02\xfb\x63\xd1\x09\xdd\xcd\x9e\x40\x51\xad\x6f\x45\x59\x85\x32\xbe\x17\x95\x23\x71\x08\x51\xd3\x93\x1e\x88\x7d\x02\xc3\x45\xc7\x9c\x48\x9f\xc1\x06\xa4\xae\x16\x2f\x7d\xf7\x1a\xb9\x0b\x75\x1d\xa7\x03\x8a\x6d\xf7\x61\x6c\xfc\x11\x88\x7e\x21\x06\x8f\xb9\xe3\x3b\xe5\x66\x40\x2b\xe5\x04\xf3\xfc\x27\x42\xb8\x81\x50\x9b\xd4\xfe\x6a\x0f\xc7\x22\x64\x98\x83\xf8\xcb\x65\x55\x98\xa1\x5a\x1d\x4c\x22\x9d\xd8\x6b\x5c\xae\xb7\x11\xa0\x28\xde\xfd\x43\x11\x54\xbb\xa4\x6b\x48\x17\x2a\x4d\x8c\xbd\x45\xbc\x90\xaa\xf8\x74\xb6\x08\x5f\xa2\x84\xf5\xfe\xd6\x55\xad\x6f\xa1\x7d\x67\xb3\xb9\xa7\x96\xfa\x3e"}, -{{0x04,0x8a,0xc9,0xec,0x3e,0xcb,0x30,0xa3,0xb1,0xbf,0xda,0x9b,0x3b,0x79,0xa4,0x8c,0x07,0x93,0xb4,0x90,0x87,0x9e,0x3c,0x8a,0x5e,0x23,0xee,0x2b,0xab,0xcd,0x9b,0x7c,},{0x94,0x6c,0x18,0x6f,0xea,0xfc,0x35,0x80,0xa5,0x8d,0xdd,0x52,0x6f,0xf2,0x29,0xc0,0x47,0x20,0x25,0x0f,0x4c,0xf6,0xbd,0xe0,0x27,0x1e,0xef,0x9b,0x12,0xb1,0xc3,0xf3,},{0x2e,0xcf,0x5b,0x8a,0x59,0xa8,0xe2,0x7d,0x25,0x89,0x0a,0x2a,0xa3,0x2f,0x4a,0x06,0x73,0x27,0x5d,0x53,0x9b,0x17,0x4a,0xfa,0x7b,0x2c,0xeb,0xf2,0xe7,0x62,0x80,0xdf,0xfc,0x33,0x8e,0xde,0x85,0xac,0x8f,0x61,0x40,0x39,0x56,0x0e,0x28,0x06,0xd9,0xe1,0xe3,0xcf,0x9c,0xce,0x2c,0xeb,0x78,0x74,0xff,0xe1,0xa7,0xe8,0x0c,0xde,0xf4,0x0b,},"\xd6\x8b\xe8\xef\x7b\x4c\x7a\x42\x89\xf2\xb1\x8b\x16\xad\xe9\x7f\x4e\x4f\xa1\x64\x52\x97\x6a\xfb\x58\x16\x93\x38\x0c\xc5\x4d\xe3\x8a\x07\x58\x7f\x32\xe2\xd4\x54\x9f\x26\x59\x5f\xee\x23\x93\xbd\x06\x2e\x9b\x00\xba\xe7\x24\x98\xe4\x14\x8c\x8b\x88\x2a\x88\x40\xe1\x5b\x58\x5c\x82\xb5\xc0\xde\xfb\x23\x35\x18\x40\x99\x16\x61\x5d\xeb\x3a\x55\xa5\xf8\x4e\x6b\x3a\xab\x93\x84\x4d\xe3\xb1\xe4\xd8\x6e\x09\xf8\x89\xac\x71\xc3\x24\xeb\x12\xd0\xfb\xd8\x61\xcc\x31\x22\x95\x40\xe8\x43\xa3\x4f\x8d\x5b\xe4\x7c\x0e\xc0\xd2\x3d\xf4\x3e\x06\x81\x3f\xca\x30\x94\x39\x90\x4c\x16\x7d\x10\x43\xc0\xdc\xd4\x44\xb0\x04\xbe\x1f\xf2\x7b\x78\x62\xb0\x0e\xba\x94\x33\xb9\x4b\x0f\xcd\xc6\x75\x21\xda\x0c\x1d\x53\x58\x63\x6c\x78\xf5\x30\x43\x11\x64\xdd\xe2\x0a\x1c\xf1\x64\xf5\x1e\x29\xb8\xe6\x3e\xac\xde\xcc\x86\x9b\x41\x39\x2c\x66\x76\x64\xd9\x16\x80\xd9\xac\x51\x6a\xf5\x48\xf0\x9e\x60\x56\x4e\x81\x4e\x36\xe0\xb5\x63\xdb\xae\x55\xc6\x27\xff\xc1\x41\x58\xa5\x6d\x8e\xb3\x60\x9e\x17\x43\x81\xb2\x1d\xe4\xba\x82\x34\x44\x66\xdd\x57\x7f\x4d\x11\x03\xc4\x3c\x27\xfb\x83\xcb\x83\x3d\x87\xaf\xdf\x74\x12\xb4\x09\x09\x09\xb1\xdd\xe2\x64\xda\xdd\xce\x96\x7f\x49\x6b\xf6\xf1\x71\x12\xbf\x35\x1e\x41\x7d\xb5\x95\x3b\x13\xb8\xf0\xfc\xcc\xbf\x30\xf5\xbc\xf3\x76\x86\x1c\x12\xef\x20\xee\xc8\x9e\xd2\x3c\xf3\x84\xee\x78\xdc\x6e\xb4\x0f\xd5\x81\x1a\x7b\x23\x92\x7c\x13\xe7\xdc\x5d\xa3\xa9\x21\xb8\x83\xa9\xb2\xb1\x15\x59\x70\xfb\x0d\xa7\xd2\x99\x3d\xcd\xfd\x43\x43\x64\x2a\x9d\x5a\x63\x47\xe4\x3c\x19\x3b\x57\x93\xe4\x45\x3a\xc1\x53\x7a\xa3\xd0\x4d\xc9\xf7\x74\xe8\x40\x93\x48\x81\xd7\x8a\x39\xba\x25\x04\x38\xc5\x07\x25\x0e\xed\x2f\x6e\x07\xcc\x95\x3f\x78\x3d\x6b\x72\xb1\xcc\x61\x99\x81"}, -{{0x2f,0x05,0x7d,0x20,0xb1,0x67,0x85,0x31,0x61,0x1f,0x48,0xf0,0x03,0xb7,0xd2,0x2e,0xba,0x5d,0xbb,0xd7,0xe2,0xdd,0x41,0xb7,0xc7,0x9d,0x09,0x07,0x1f,0x85,0xe9,0x93,},{0x62,0x0f,0xc4,0xea,0xa3,0x4d,0x78,0x7d,0xf6,0x75,0xcc,0xbf,0x7e,0x89,0x32,0x04,0x82,0x8d,0xb9,0x2e,0xad,0x17,0xa1,0x16,0x5a,0xc7,0xfa,0x1a,0xb4,0x27,0x19,0xd8,},{0x30,0xdf,0x7b,0x0b,0x1c,0x04,0xfb,0x1e,0xfa,0x35,0x17,0xe9,0x28,0xd6,0xd5,0x7c,0x2c,0xa0,0xd0,0x7f,0x4e,0x04,0xff,0xb1,0xf0,0x8b,0x47,0x92,0xc5,0x93,0x7d,0xd2,0x71,0xcc,0xab,0xdc,0x00,0xdc,0xe8,0x50,0xaf,0xe5,0x0a,0xf5,0x99,0x0f,0x22,0x4e,0x84,0x20,0xa6,0x81,0xd9,0x5f,0x9f,0x7f,0x51,0x5a,0xfe,0xc1,0x02,0xef,0xd1,0x0e,},"\x6e\x35\xf6\xea\xa2\xbf\xee\x06\xea\x6f\x2b\x2f\x7a\xb1\x5f\xa9\x7c\x51\x80\x95\x8a\xf2\xe9\x0a\xf9\x18\xad\xfb\x3d\xb8\x32\x3f\x44\x7c\x7b\xf2\x6d\xc5\x34\x99\x7c\x38\xb7\xfc\x97\x7f\x64\x2d\xe2\x88\xcd\xf2\x53\x07\x1c\xac\xf3\x56\x4e\x3b\x8e\xd6\xdc\xe5\x7d\xdf\xba\x9f\xf7\x83\xba\xd2\xe7\x6d\xf1\x24\x82\x8f\xc1\x03\x1a\xcf\xad\xf0\x1a\x44\xd4\x1b\x42\x16\x1a\xd9\x06\x03\x01\xc1\xaf\x19\x28\xb9\xe5\xb7\x3b\x9b\xd2\x1c\xac\x60\xa8\x42\xb5\x04\xdc\x3c\xc3\x11\xc5\x22\xe3\xbb\x04\x8b\xf2\x21\x44\x4f\x53\xce\xb0\x8e\x77\xe9\x48\x59\x0e\x94\xed\x98\xf1\xb6\x04\xcb\x9e\xad\xc9\x3b\xbe\x74\x31\xc1\x14\x9b\x23\x19\x3f\xf9\x3e\x85\x69\xf1\x13\xe1\x68\x4d\x89\x76\xec\xae\x6f\x09\xe0\x10\x36\x14\xbe\x41\x8a\x47\x2e\xf5\x5b\xb8\x89\x0d\x72\xb3\x41\xcd\xd7\x50\x5b\x50\xa4\x55\x22\xab\x63\xed\x79\x1c\xe8\xf8\x2f\xed\xdd\x7a\x62\x0a\x4f\x6f\xb1\xd2\xfb\x0e\xd0\xc4\x56\x0d\x78\x44\x6d\x83\xb3\xd1\xb1\xbb\x56\xb3\x66\xd1\x96\x02\x0d\x06\x24\xb1\xfb\xdb\x75\xce\x73\x5d\xd4\x3e\x8e\x8d\xf1\x63\xc4\x4e\x23\x69\x93\xdc\xa3\x41\xf5\x13\x2d\x82\x5d\x0a\x4e\x39\x3a\x19\xd3\x8f\x61\xe1\x1e\x0c\xf3\x92\xcb\x9b\x64\x6e\xa2\x3c\x58\x09\x98\x24\xdd\x8d\x9f\xbe\x26\xa4\x9e\x33\xb2\x3d\xf8\x06\x07\xab\xf1\x97\x15\x79\x9c\x19\xac\xc7\x22\xed\x9b\xcf\x94\xa0\xc2\x9a\xd2\x4b\x78\xb0\xb0\x35\xb3\x24\x1c\x64\xcd\x86\xed\xea\xc8\x10\xe6\x67\x45\x69\x4b\x5e\xb1\x62\x50\x60\xed\xf2\xd9\x49\xde\x0d\x34\xf5\x22\xdf\x2d\xc6\x0a\xe6\x94\xa1\x93\xf3\xb8\x2c\x1d\x6f\x83\xa0\xcb\xb8\x40\xf4\x6c\x49\xa3\xd7\xd1\xcf\x06\xde\xaf\x96\xc6\x4f\x8f\x9e\x17\xbd\x9a\xd5\x12\xae\x63\x09\xc4\x86\xd9\xe2\xa7\x8d\xce\xec\xa4\x73\xa0\x42\x1d\xd1\xb6\x43\xc7\x87\x54\x27\x1b\x53\xce"}, -{{0x3a,0x3d,0x27,0x97,0x0f,0xe2,0xac,0xb6,0x95,0x1e,0xdd,0x5c,0xa9,0x0d,0xda,0x0f,0xc6,0xdd,0x22,0x9c,0x0a,0x56,0xdf,0x6e,0xb1,0x1a,0x9c,0x54,0xd2,0x42,0xdb,0xbf,},{0x56,0x4f,0x0d,0xc3,0xdc,0x47,0x20,0xe6,0x8e,0x44,0xdd,0x16,0x71,0x1e,0x04,0x9e,0x61,0x12,0x00,0x00,0x98,0xfa,0x62,0xa1,0xb9,0x8c,0x28,0x80,0x42,0xf7,0xc3,0xbd,},{0x22,0xeb,0x8e,0xa0,0x50,0x73,0x49,0xb6,0xa0,0xac,0xe2,0x5c,0xf9,0x18,0x0c,0xb0,0x8e,0x03,0x57,0xb0,0x45,0x02,0x90,0x5f,0xbe,0x69,0xb4,0xe2,0x1b,0x2b,0xd9,0x4e,0x22,0xcf,0xbd,0xb8,0x51,0xae,0x71,0x6a,0x5c,0x25,0x3c,0x70,0xd5,0xe2,0xb2,0x4e,0xa7,0x8f,0x35,0xbc,0x21,0x32,0x92,0x54,0x3d,0x94,0xe1,0x41,0x10,0xb2,0x41,0x06,},"\x43\x74\xf6\x1c\x2c\xd8\x8a\x3b\x89\x72\x24\x9b\xfa\x79\xb3\x6a\xb6\x9e\x3e\xd4\x84\xcc\x60\xe5\xd9\x54\x1f\xa7\x68\x6c\xf4\xee\xd1\x21\x0c\x5d\x0d\xcf\x42\xdd\x25\x97\x25\x01\x90\x91\x93\xca\x76\xae\x6e\xb7\xf4\x71\xd8\xbd\x0d\x5f\xb5\xa6\xb4\x31\xbc\x3d\xe0\xe0\x31\x8d\x50\x51\x45\x24\xde\x87\xc4\xb8\x30\x05\xdf\xb4\x12\x45\xfb\x1a\xf7\x9b\x84\xa9\x7b\x83\xd3\xca\xc7\xad\x7a\x53\x36\x4e\x2e\x9b\x21\xc9\x7b\x76\x9b\xdc\x57\xf0\x70\x31\x16\x16\x83\x80\xf3\xcc\x88\x36\x89\xeb\x4a\x7f\xa3\xb2\x6d\xbe\x12\xbc\x28\xf8\xc4\x03\x81\xaf\x64\xdf\x4b\x53\x61\xd1\x74\xcf\x75\xac\xbd\x46\x42\x87\x40\xb0\xd1\x32\x2d\x32\xbb\xe9\x48\x45\x21\x59\x66\xae\x58\x87\x77\xa8\xc0\x53\x36\xe3\x52\x30\x6d\x49\x27\x8d\x32\x8e\x49\x6d\xb6\x5e\x9e\xcf\x6c\xe6\x40\x5e\xd1\xc8\x93\x49\x0b\xc4\x8c\x13\xa1\x34\xe1\xfb\x6e\x80\xde\xbe\x6d\x32\xfc\xe6\xef\x74\x78\x3c\x8d\x77\x98\x0a\x44\x1a\x26\xae\xb4\xfd\x83\xcc\x85\x53\x52\xce\xdc\x18\x8f\x52\x79\xce\x21\x1f\x74\x4a\x40\xb2\x3c\xe7\xff\x24\x43\x7a\x1d\xd3\x37\x3e\xc5\xb2\x90\xda\x1f\x94\xf4\x3a\x07\xa3\xff\xea\x5b\x5f\x67\xb5\x2c\x19\x61\x85\xbc\xe9\xe9\xa8\x58\x25\x7f\xcd\x7a\x8e\xba\xf9\x04\x0e\xd0\x91\xfa\xce\x5a\x15\x5a\xa4\x47\xfa\x15\xe1\x21\x22\xd2\x5e\x8f\xc3\x6e\xae\xe2\x13\x7c\x7b\x3a\xa3\x0b\x7e\x3f\xf6\xcc\x86\xb6\xdc\xb9\xea\xf4\x9c\x95\x76\xf0\xf4\x62\x00\x84\x39\xcb\x1a\x3a\xba\x01\x3e\x89\x7a\x0f\xaf\x99\x4c\xb7\xd5\x9e\xde\x57\x74\xbb\x14\x47\x74\xf7\x3c\xa3\x0e\x64\x14\xa7\xcc\x7c\x74\xb2\x0c\x51\xa1\x40\x4d\xdc\x41\x9e\xf7\x62\x45\x93\xe9\xbc\xfb\x37\xc0\xa7\x62\xea\xb6\x8f\xac\xa5\x86\x34\x43\xe1\x6e\xdb\x75\x9d\xbc\x87\x88\x73\x2b\x9e\x4f\x59\xc1\x11\x92\xc3\xfc\xc8\x72\xaf\x55\xf3\x2d"}, -{{0x06,0xd4,0x98,0x31,0x8d,0xa4,0x56,0x24,0x2b,0x9c,0x3b,0x9a,0xb6,0xd5,0x32,0xa1,0x28,0xfc,0xe0,0x44,0xf5,0x38,0x82,0x68,0x2e,0x92,0x62,0x14,0x9c,0x16,0x52,0x88,},{0x41,0x35,0x17,0xaa,0x63,0x20,0x0a,0x17,0x17,0x32,0x09,0xa4,0xb3,0xe7,0x8a,0xb9,0x38,0x3c,0xb4,0xe3,0x9e,0xfd,0x67,0x94,0xc4,0x6a,0x2d,0x13,0xfa,0xfa,0x99,0xc0,},{0x82,0x50,0xf7,0x6d,0xc5,0x99,0xc5,0x12,0x87,0x87,0xe4,0xf6,0xd3,0xda,0x23,0x17,0x33,0x30,0xce,0x33,0x20,0xdb,0xa9,0x59,0xbd,0x71,0x4c,0xc8,0xcc,0x07,0xc6,0x79,0x45,0xd6,0x3e,0x75,0x66,0x2c,0x07,0x5e,0x26,0x74,0x60,0xab,0x7b,0xf5,0x61,0xf2,0x4f,0xaa,0xe3,0xb4,0x1d,0xbf,0x67,0x68,0x99,0x19,0x1e,0x3b,0x02,0xb5,0xaf,0x0a,},"\x3f\xe3\x0e\xcd\x55\x07\x7a\x6e\x50\xdf\x54\xbb\x1b\xf1\x24\x8b\xea\x40\x63\xe3\xfa\x75\x5f\x65\xfc\xd1\x15\x9e\xe0\x46\xef\xd0\xeb\x5f\x2f\xbb\x38\xb5\xc0\x09\x47\xc9\x7d\xc8\x79\xb3\x6b\x9e\x53\x61\x92\x28\x60\x86\xd0\xdc\x12\x05\x36\x10\x38\x61\x74\xa7\xc5\x6f\x22\xa8\x5b\x73\xff\x20\x8c\x59\x44\xf3\x93\x23\x6c\x32\x41\x58\x09\xda\x03\x6e\x73\xca\xd8\xfc\x3c\x30\x37\x80\x64\xa7\x6a\xfa\x93\x0a\x3b\xaa\xe9\xaa\x35\x70\x61\xa8\xc5\xe8\xe7\x56\xa9\xce\xcf\x94\xb7\x2d\xf4\x3f\xac\xd8\x8f\xa4\x9c\xb4\x94\x8c\x63\x68\x31\x8a\x6b\x1e\x5c\xff\x52\xe5\x87\xec\xdf\xae\xfd\xb6\x90\x81\xf2\x8c\x2d\x13\xbf\x8e\xab\x81\xdb\xaa\x5e\x37\x28\xc4\x31\x7f\xb7\x93\xdd\x19\x6b\xca\x0f\xe5\x4a\x6c\x24\x2c\xf2\x6e\x2d\x12\x9b\xa0\xd8\x2a\x2c\x3a\x45\xbc\x8d\x1d\xfd\x6f\x54\xf8\xda\x4f\x51\x89\xc9\x1a\xc2\x14\xfd\xab\xf4\xc5\x97\x38\x1b\x2e\x5c\x40\xcc\x71\xfa\x70\x51\xcf\x2e\xa9\x39\x06\xa3\x7d\x57\xdf\x12\xd5\xc7\xe5\xcd\x77\xc9\x07\xe4\x42\x56\x63\x15\xba\xe5\x1a\x22\x22\xd6\x2e\x3f\x42\xd1\x76\x78\x82\x63\x7d\x66\xa1\xd5\x30\x5a\xb4\x01\x0a\x0e\x49\xc5\x7d\xef\x69\xdc\xea\x83\x9e\x1b\x76\xa4\x11\x35\xba\x95\x2c\xc4\x24\x95\x0e\x8d\x3a\xac\x19\xe1\xd9\x3d\xe7\x75\x7c\x15\xff\x99\x97\xb3\xd2\xa8\x61\x3c\xd9\xa1\x64\x78\x1d\x1b\xe3\x31\x79\x9f\xa6\x10\x9c\xef\x61\x43\x05\xa1\x95\x8f\x62\x90\x3c\x8c\x9e\xa0\xb2\x3b\xa7\x06\xd4\x9c\x54\xba\xcc\xc1\xe6\x3c\xb4\xbf\x14\x78\x5f\xc7\xb0\x62\xa9\x80\x03\x49\xbd\xb0\xbb\x92\x72\x60\xb6\x77\xb6\x0f\x10\xe6\x2c\x87\x80\xf3\xeb\xb5\xeb\x6f\xf0\x36\x02\x63\xd4\x57\xab\x52\xfd\x11\x25\xc9\xce\x04\x6a\x95\xd8\x9d\x28\x73\x50\xc8\x04\xcf\xd4\xff\x2b\x2d\xdd\x18\xa9\xe1\x35\x19\xf2\x0b\x4d\x1e\x05\x1a\xf6\x24\x64\x0f"}, -{{0x8e,0x8e,0x1d,0xb5,0xb1,0x10,0x2e,0x22,0xa9,0x5c,0x47,0xaf,0x36,0x61,0x46,0x9f,0x00,0x0a,0x33,0xf1,0x3b,0x8b,0x87,0xb1,0x15,0xd2,0x45,0x2a,0x41,0x1f,0x6f,0x39,},{0x56,0xd7,0xb3,0x16,0x9a,0x95,0xc2,0x29,0x98,0xec,0x93,0x79,0x25,0xbd,0x7c,0xad,0x13,0xcc,0x65,0x80,0x8c,0xd5,0xd3,0x4a,0x6c,0x4d,0xa8,0x70,0xea,0xf3,0x23,0x64,},{0xf6,0xee,0x5e,0x13,0xcf,0xaa,0x36,0x2c,0x89,0x71,0xd5,0xa4,0xa8,0x79,0xa7,0xe3,0x69,0x66,0x52,0x5c,0xcd,0x86,0xc5,0xa4,0x8c,0xba,0x08,0xd9,0x13,0xec,0xe1,0xa7,0x9c,0x4c,0xd1,0x46,0xb8,0xe9,0xc6,0x51,0x25,0xfb,0xad,0xf1,0x7b,0xac,0x1c,0xab,0xcd,0xe8,0xfd,0x17,0xcf,0xd6,0x8f,0xa1,0xf9,0xc4,0x4e,0xa6,0x1c,0x08,0xa4,0x05,},"\xb2\x46\x34\xfb\xdd\x1b\x76\x61\x31\x5d\x9d\xc1\x53\xba\x90\xd6\x6a\x88\x62\x2a\x41\x58\xf8\xbc\xff\x25\xba\x9c\x29\xe6\x5f\x29\x7f\x8e\x60\x31\x18\x00\xb7\x33\x1b\x69\xfc\x20\xc9\xf8\x5b\xb7\xc1\x84\xbd\x40\x86\xb3\xa9\xf9\xa2\x71\x02\xb6\x23\x62\xbd\xb4\xfa\x5b\x20\x15\x94\x25\x0f\xc6\x28\xfd\x2e\x0e\x0d\x1b\xe0\x3d\xcf\x81\x8c\x60\x94\xc4\xc2\x91\x21\xcb\x2b\xf6\xd9\x08\xed\x8a\xab\x42\x7c\x37\x71\xc0\xc9\x5f\x0a\xc1\x46\x9a\x08\x10\xb6\x03\xa4\x70\x28\x2e\x59\x80\xa6\x07\x29\x19\x7f\xe6\xc2\x0e\xf6\x81\xcd\x1b\x96\x93\x2d\x20\x58\xf8\x96\xea\x74\x16\x42\x2a\x7e\x54\x1f\x22\x4a\x5f\x04\x25\x30\x80\x74\x1c\x5d\x4e\x3e\xb0\x39\xdb\x6b\xa0\x51\xb4\xca\x54\x17\xce\x8a\xfd\xc7\x02\x14\xba\x4d\xcc\x85\xb6\x23\xd1\x1e\x68\x1c\x60\x09\xae\xe4\xe6\x13\x0a\x83\xed\xd0\xd2\xc9\x9f\xb0\x64\x7e\x11\xed\xe7\x30\x1a\xe5\x6b\x59\x90\x4e\xf7\x02\x57\x32\xcd\xe0\x38\x80\x1e\xc7\xe8\xd9\x0a\x9a\x1b\xba\x04\x7f\xe6\x28\x35\x1b\x3b\x89\xd0\xbc\x5a\xe6\x65\xa7\x00\x89\x1f\x09\xeb\xee\xc0\x55\x91\x84\x2a\xdf\xcc\x25\xad\xc3\xc7\x1c\x1e\xbc\x4a\x31\x2e\x54\x71\xbe\x67\x25\x3b\x0e\x94\x28\xb0\xca\xe3\x76\x45\xa0\xf7\xec\xb8\x9d\xd7\x9f\xbd\x9b\xe2\x87\x54\x33\x66\x7a\xe0\x7d\x74\xa7\x98\x3c\x4c\xea\x60\x1e\x72\xe9\x75\xc2\x1d\xf9\x93\xe7\xfa\x22\xa9\xfa\xbd\x45\x45\x5d\x45\xe3\x70\x31\x55\x8e\x13\xa7\xa4\xf5\xf4\x97\xea\x78\xfb\x73\x99\xf8\x83\x8c\x0f\xd5\xde\x4e\xbb\x66\xdb\x29\x0f\x43\xa4\x86\x7d\x50\x53\x09\xf1\xc1\xbc\x27\xe9\xfa\xbc\xbb\xa7\x13\x02\xfc\x12\x04\x71\x5c\xe3\xfc\xb0\x90\x5b\xfa\x41\x1c\x9d\x1c\x9a\xb4\xa3\x99\x54\xe5\x0b\x8e\x0c\xf7\x36\xc1\x02\x89\x56\x3b\xdf\xa9\x67\x55\x3c\x36\xcd\x9e\x55\x5b\xc8\xcc\x56\xbe\x59\x48\x47\xde\x9f\x26\xf9"}, -{{0x38,0x84,0xb8,0xb7,0x9a,0xbf,0xd3,0xbe,0x6c,0x13,0x98,0x5e,0xb8,0x59,0xab,0x74,0x3f,0x15,0x7c,0xd9,0xde,0xb8,0x1b,0x2f,0xe9,0x7e,0xa4,0xd6,0x17,0x3e,0x46,0xf5,},{0xbd,0x7f,0xd9,0xa8,0xde,0xf1,0x3a,0x54,0x2e,0xd2,0xf2,0xfb,0x04,0x88,0x86,0x88,0x5b,0xa9,0xb5,0xce,0x59,0xcb,0x70,0x19,0xfb,0x54,0x66,0x79,0x86,0xee,0xbc,0x26,},{0xf4,0x20,0x6f,0xcd,0x34,0x50,0x24,0x41,0xd5,0x4a,0x73,0x32,0x3f,0x33,0xa5,0xdb,0xb4,0xc9,0x85,0x57,0x31,0x9f,0x21,0x24,0x6f,0x26,0x0f,0xfb,0xbe,0x58,0x44,0x88,0x6d,0xb5,0x67,0xf4,0xb6,0x3c,0x47,0x94,0x3d,0xbb,0x78,0xfc,0x35,0x65,0x7d,0x7c,0x04,0xd4,0xfe,0xb0,0x42,0xff,0x85,0x36,0xf6,0x72,0x92,0x5c,0x31,0x9e,0xfb,0x09,},"\x12\xad\xaf\xe3\x0e\xaf\x2b\x9c\x72\x03\xca\x5d\x44\xb9\x7f\xfe\xd4\xbf\x65\x17\xa4\x99\x88\xe4\xe6\x76\xc8\xe3\x14\xad\xbd\xbe\x23\xd8\xf2\xd3\xe2\xb0\x81\xa7\x02\x4f\xa5\x25\xab\x5a\xae\x26\xe6\x00\x57\xc1\x01\xe8\xf3\x68\xd3\xad\xdb\x93\x76\xc4\x68\x2c\x1f\x42\x24\xd7\xf1\x49\xa8\x47\x4b\xb9\xa8\xf6\x63\xef\x21\x0e\x95\x72\xce\x82\x9d\xa3\x88\xd8\xaa\xe7\x2a\x46\x71\x41\xad\xc1\x53\x47\x3b\xe3\x65\x3b\xaa\xa6\x4b\x5b\x1e\x2e\x30\x68\x3f\x6f\x06\xda\xc2\x78\x4d\x5b\xbf\x0d\x08\x2a\xab\x47\x30\x5e\xd8\xa8\xef\xd0\x88\x6c\xe6\x3a\x17\x93\x15\x22\x5d\x1e\x4d\x4f\xfc\xf1\xf2\x4a\xc2\xf4\x64\xcf\x5e\xd3\xa8\xb6\xd3\x99\x84\x54\xf1\xc0\x2c\xdb\xf0\xa4\x44\xee\x2b\x59\xdd\xbe\x0a\x17\x4a\x0d\x93\x7f\xa6\x28\x65\x08\x8a\xc6\x47\x49\x99\x57\xd2\x81\xc6\x94\x98\x03\xa5\xfb\xdf\xdd\x0d\xd9\xe9\x1b\x69\x76\x86\x1f\x3c\x5f\x21\x26\xf3\x9a\xac\x93\x5b\xe0\x9f\x4b\x97\x15\xbd\x4f\x0d\x5c\x55\xdf\x73\xa6\xb9\xf2\xc0\xad\x26\xce\x49\xd8\x22\xbf\x85\xbf\xa2\x34\x6f\x31\x65\xb0\x38\x59\xa7\x1c\x3d\x2a\x7b\x86\xdb\x6e\x9f\x2e\x5d\x7b\x16\x9a\x91\x0e\xeb\x7e\xf3\x8f\xbd\xfb\xbe\xc4\x3a\x9a\x25\xf0\x4b\xc3\xac\xfd\x3b\x06\x91\x54\x2a\xb6\xde\x9d\xb6\xf0\x30\x58\xf9\x58\x40\x24\xf9\x91\x8e\xde\xcd\x90\xfb\xb8\x57\x35\xd6\xdc\xec\x5b\xd5\x93\xae\x63\xe2\xcc\x96\x55\x35\x99\xa3\x10\xf8\xf2\x00\x9b\xa9\x53\x71\x19\x6b\x4d\x5b\x80\xe7\x55\x96\x37\xf2\x29\x26\x77\x8b\xe5\xe1\xcc\xef\x51\x26\xe2\x44\x3f\xa9\x39\xc2\xa5\x3d\xdd\xb0\x49\x61\xee\xfd\x34\xe5\x38\xcd\x8d\x7f\x0b\xec\x2b\xff\x1e\xf0\xd3\xa4\xbd\xd3\x58\x31\x76\x37\xf4\x2d\x59\x55\x38\xc1\x12\x22\x51\xa9\x4e\x96\x3d\x1f\x81\xe7\xb9\xae\xb1\x64\xf9\x5d\xa9\xa4\xed\x75\x29\xb8\x45\xeb\xc9\x61\xb2\x7b\x5c\x19"}, -{{0xec,0xd5,0x19,0xf2,0x87,0xad,0x39,0x50,0x52,0xb0,0xb3,0x0d,0xea,0xc3,0x41,0xd2,0xa9,0xdf,0x13,0xd6,0x56,0x7c,0x89,0x1c,0x81,0x3a,0x0c,0x9c,0xa5,0x2e,0x87,0x1e,},{0x8e,0xe9,0x4c,0x58,0x8e,0x0b,0x34,0x35,0x85,0xfc,0x67,0x48,0xfd,0x1b,0x54,0xb5,0x77,0x0c,0x64,0xe9,0x93,0x7a,0x56,0x35,0x7a,0x48,0xd4,0x4a,0xe2,0xf5,0x18,0x24,},{0xe8,0xf5,0x1b,0xe7,0x3f,0xc4,0xe0,0x23,0x5a,0xa1,0x53,0xa2,0xe1,0xb3,0x54,0xe9,0xc5,0xd2,0xd3,0x3a,0x11,0xae,0x0e,0x33,0x34,0x78,0xde,0x1d,0x8e,0x6c,0x44,0x56,0xd2,0xe2,0x50,0x82,0x4c,0x32,0x46,0xca,0x0e,0x8d,0x6a,0xe3,0xe1,0x66,0x77,0xa9,0x73,0x44,0x14,0x41,0x08,0xc1,0x3b,0x95,0x9e,0x1d,0xaf,0x51,0xcf,0x0f,0xe5,0x01,},"\xaa\x71\xbe\x5f\x55\x7e\x10\xc9\xfb\x5f\x09\x1a\x3a\x27\x44\x53\x94\x7c\x07\xa0\xe2\x5b\x26\xf9\x50\x92\x24\x54\x1d\xff\x76\xf4\xd9\x6e\xff\xd0\xd5\xa4\x1d\x31\x9b\xc9\x32\x1a\x86\x66\x7d\x55\xcf\x49\x43\x2f\xb5\xc3\xe7\x15\x38\x8f\x3f\x10\x6c\x91\x74\xb1\x61\x0c\x8f\x30\x75\xd5\x93\x1c\x29\x00\x99\x38\x5c\xe9\x24\x9e\x23\x51\x28\xe9\x07\xc5\x33\x90\x03\x6f\xbf\x5d\xa9\x68\xf8\xd0\x12\x33\x69\x58\xde\x90\xc5\xe8\xe6\xb1\x01\x6a\xd4\x3f\xb5\x7c\x8e\x28\x8d\xaf\xe1\x4e\x90\xe6\x4b\x63\x79\x1e\x5c\xbe\x55\x7e\x02\xdf\x8a\xc9\x37\x06\x42\xa7\x1f\xaf\x85\x10\x75\xe5\x56\x5f\x6f\x9a\x26\x7f\x4f\x6b\x45\x4c\xe4\xc5\x47\x48\x10\xb8\x04\x84\x4d\xda\x38\x39\x29\x39\x71\x97\x93\x24\x6a\xa4\x74\x54\xb9\xb0\xe8\x2e\x98\x03\xc0\x99\x35\xd0\x02\x7f\x39\x95\xcc\xa9\x71\x30\x69\xbb\x31\x02\x7f\x7b\x2a\xf1\x2f\xe5\xfe\xec\x7e\xeb\x06\x84\x3d\x82\x96\xec\x56\x82\x26\x2a\x07\xda\xe7\x47\xed\x7b\xc8\x21\xec\x17\x01\x8d\x89\x9f\xd1\x67\xb3\x6a\x7e\x37\x73\xb4\x27\x49\x9d\x99\xdc\x58\x3b\xbe\x4b\x42\x9a\xfa\x6a\x26\x59\x39\x53\xf9\x43\xe4\x67\x3b\xdd\x0d\x2a\x84\x42\x56\x13\x16\x03\xcd\x09\x03\x25\x6f\x33\x4d\x4f\x8e\xc8\x2d\xe1\x15\xb6\xca\x53\x38\xc7\x5c\x8b\xaa\x44\xb4\xba\x96\x3c\x7c\x78\x51\x0d\x8d\xe9\xb2\xa5\x85\x2f\x42\xf3\x46\x3c\x68\x5f\xb3\xa6\xda\x61\xa8\xe0\x89\x26\x62\xd6\xa2\x50\xfc\xaa\x6f\xef\x74\xd4\x50\xfc\x45\x7b\x98\x71\xd0\x8b\xb5\xbe\x30\x11\x29\x4a\xc8\x88\xfc\xe2\x15\xd5\x35\xc3\xb1\xa4\x3b\xb4\x7e\xfe\x3a\xd2\x5d\xa1\x59\x19\x1a\xed\x55\x19\x54\x69\xc5\x90\x93\xff\xb2\x4f\x65\xd6\x0c\x40\x20\xbf\xbe\x64\x7f\xf5\xdb\x7a\xb8\xa0\x1d\x5e\x48\x7b\x0b\x1b\x64\xef\x25\xda\x15\x6d\xb1\x42\xe6\xad\x87\x2a\x4d\xc1\xee\x9b\xa6\x68\x46\x52\x65\x37\x9e"}, -{{0x19,0x3f,0x3c,0x63,0x0f,0x0c,0x85,0x5b,0x52,0x9f,0x34,0xa4,0x4e,0x94,0x49,0x70,0xf4,0xa6,0x97,0x2e,0x6c,0x38,0x59,0x35,0x9c,0x2e,0x0c,0x87,0x62,0xba,0x9e,0xaf,},{0x32,0x56,0xf2,0xc8,0x2e,0x7c,0x80,0x12,0x01,0x21,0x01,0x40,0x56,0x9f,0xaf,0x18,0x50,0x7e,0x60,0x33,0x8c,0x2c,0xc4,0x11,0x8b,0xb1,0xce,0x60,0x5b,0x0e,0xbe,0x61,},{0xb1,0x25,0x10,0xac,0x5f,0x2f,0x6d,0x33,0x36,0x0c,0xdd,0xc6,0x72,0x91,0xd6,0xc2,0x70,0xfd,0x9e,0xe6,0x2d,0xc0,0x86,0xb3,0x8d,0x93,0x2d,0x26,0x47,0x3f,0xe9,0xa2,0x4e,0xfb,0xd4,0x24,0x88,0x67,0xea,0x7e,0x91,0x5a,0x30,0xc5,0xbf,0xb3,0xb8,0xb1,0x9a,0xa0,0x1a,0xa2,0xfe,0xbf,0x0d,0xac,0x6c,0xfd,0x66,0x38,0xa2,0xba,0x7e,0x0c,},"\x98\x62\x3f\x65\x16\x98\x08\x5b\xde\x02\x76\x2e\x8c\x33\x21\xf1\x4d\xa1\x61\x9b\x5c\x3f\x7c\x1a\x56\x8e\x8c\x26\xff\x0c\x62\xfd\xcc\x41\x24\x75\x91\x2e\xb8\xe8\xc4\xb0\xd3\x09\x18\xb8\xff\xee\xf3\x50\x93\x15\xe5\x8d\xa3\x59\xcd\xc2\xf2\x6b\xeb\xfb\x57\x03\x95\x3b\xe1\x6b\x8f\x3b\xeb\x1e\x54\xa1\xab\xee\x0a\xeb\xe2\x4e\x64\xdb\xe8\x73\x40\x2e\x15\x6f\x37\xdf\xc1\x68\xea\xf8\xa1\x14\xce\x08\xa6\x79\x5d\x3f\x64\xf5\x15\x1e\x9a\x8b\x82\x75\xcc\x7b\x49\xa6\xb8\xd8\xa6\x6b\x6d\x4b\x76\x32\xef\x80\x74\x0d\xc1\xc1\xb0\xa3\x8d\x1a\x28\xf7\xc1\xb2\x9f\xa4\x45\x41\xc1\xaa\xd3\x54\xd4\x59\x0c\x23\x1d\xae\x68\x7a\x2a\x8f\xed\x09\xe8\xc1\xeb\xbf\xcc\x38\xf3\x47\xbf\x06\xd9\x45\x77\xe4\x9a\xd1\x39\xf7\x10\xed\x8b\xb1\xfd\x07\x66\x3c\x03\x20\x84\x6f\xbb\x45\x5a\xb8\x37\xef\x96\x4a\xe7\xd4\xec\xee\xa4\x5f\xd7\xbd\x8d\x50\x9f\x82\x1e\x6e\xb0\x27\x49\x4e\xfd\x8d\xd8\xe9\x92\xb8\x86\x98\xee\xc2\xeb\xc5\xe0\x30\x25\xbe\x78\x9c\x18\x01\x3f\x20\x1f\x77\xaa\x2d\x34\xf5\x68\x64\x60\xe4\x3f\xb4\x89\xe0\x87\x76\xf9\x8b\xcd\xe2\xce\xeb\x9d\x4f\xaf\xdf\xfe\x03\x75\x60\x43\x71\xec\x32\xf4\x6b\x81\xfe\xc4\x74\x38\x29\x08\xe9\xd2\x50\xa0\xba\x27\x80\xa7\xd6\xdf\x40\x7b\xd2\xb1\xeb\x12\x67\x48\xd7\x25\x11\xb9\xb0\x69\xeb\x1c\xd4\x42\x70\xf2\x9f\xe8\x4b\x9a\x71\x77\x51\x83\x1d\x04\xc2\x81\x8e\x40\x8f\x22\x78\x93\x76\xc6\x1c\x2c\xa4\x5e\x32\xe7\x88\xea\xd3\xa7\x53\x6b\xf0\x9d\xa8\xaf\x47\x03\x90\x2f\x55\x16\xa0\x20\xd8\x92\x63\xe9\x37\x01\xa2\x56\x5e\xef\x12\x70\x41\x89\x25\xf3\x5a\x28\x8e\x32\x7b\xab\x62\x8a\xc2\xf0\x24\x8c\xfb\xca\x34\x82\xe2\x65\xd1\x62\x1c\xc3\x43\xc3\x1f\x65\x49\x3f\x06\x4b\xad\x0d\x76\x02\x46\x07\x15\xfa\x48\x6f\x29\x42\x63\x46\xaf\x53\xe3\x33\xb7\x5f\x59\x05"}, -{{0xa8,0x8a,0xd0,0x04,0x8d,0x38,0xc4,0x4c,0xeb,0xe7,0x35,0xea,0x38,0x02,0xca,0x57,0x6e,0x37,0x12,0x1c,0x7d,0x4d,0x76,0x0d,0xfd,0x88,0xde,0x16,0x63,0x06,0x4a,0xbb,},{0x14,0xdd,0x8b,0xb3,0x06,0x80,0x3e,0x5a,0x75,0x8e,0xd6,0x8a,0xd2,0x1d,0x07,0xd8,0x81,0x61,0xd5,0x0f,0x1c,0x74,0x71,0x37,0x77,0xda,0x12,0x09,0xaf,0xba,0xea,0x0b,},{0x13,0x41,0xa1,0x48,0xda,0x45,0x93,0xc8,0x8e,0xbc,0x5a,0x58,0x82,0x1e,0xef,0x77,0xf9,0x21,0x86,0x39,0x0f,0xf6,0x33,0xe7,0x62,0x07,0x08,0x4e,0x78,0x74,0xcc,0xf0,0xeb,0x1f,0x9e,0xc7,0x0a,0x3a,0x3f,0x96,0xb5,0x89,0x34,0xbc,0xb0,0x61,0xff,0x92,0x01,0x24,0xf7,0xe5,0x80,0xfa,0x2b,0x0b,0x27,0x95,0x83,0xad,0xf9,0x23,0x2d,0x0c,},"\x2c\xe8\xbc\xa2\x61\x78\x91\x3b\x16\x76\xe9\x0f\xfe\xfd\x94\x5b\xc5\x61\x98\x26\x60\xe2\xa7\x5d\x48\x2f\xf3\x0a\xab\xa1\xba\x43\xf8\x2d\x2e\x6b\x90\x9e\xc1\x0f\xc0\x97\x89\xff\x5c\xf3\x2a\x51\x80\xb6\x01\xea\x80\xfa\xde\xce\x6d\x7e\x7b\xae\xef\x48\x1d\xc6\x97\x9e\x2f\x65\x8a\xe0\xf6\xd8\xe4\x16\xb9\x32\x98\xf7\xd3\x40\x31\xbb\x76\xf7\x16\xed\x99\x1a\x16\xd0\x9a\x58\x2e\x58\xba\x40\x03\xac\x17\xbe\x8b\x44\x69\xe1\xa8\x89\xb2\xfb\xb2\x28\x9e\x98\xaf\x1c\x6d\x5b\xbe\xe7\x77\x56\x71\x3c\x07\x78\xb0\xdc\x44\x6a\x1f\x6c\x48\xc4\xd4\x08\x18\xec\x79\x99\x05\xf0\x69\xbc\x95\x34\x16\x57\xca\x5d\x02\xb7\xa5\x39\xa1\x3a\x02\xcd\x03\x76\xa5\x0e\x83\x43\xc0\xdc\x20\x34\x6d\xe5\x27\x5b\x1d\xcd\x4a\xd7\xaf\x72\x51\x31\xac\x75\xe9\x54\x82\x5d\x30\xea\xa5\x7a\x68\xbb\x98\xdf\xc4\x1c\xaf\xe5\x71\x05\x56\x64\x7b\x38\x7d\x9b\x7f\xd4\xe4\x76\x51\xe5\x13\x80\x50\x79\x8f\x6d\x40\xf4\xee\x71\x20\xb5\x8f\x74\xda\x94\xd7\x3c\xac\xbf\xd3\x93\xd1\x34\x73\x88\xee\x00\xb7\x9b\x8d\xbf\xeb\x57\x81\x41\x21\xbd\xda\x60\xc6\x27\xdc\xe1\x47\xd4\xd5\x68\xd7\x90\x52\xe9\x7b\x9a\x5f\x3e\xb5\x40\x7c\xc4\x64\x61\xa5\x5e\x18\xa9\x60\xd8\x09\x4a\x5f\xea\x48\xb6\x93\x75\x29\xcc\x4e\xc9\x19\xcd\xbe\xdf\x91\x85\x45\x6d\xc0\x0e\x8d\x98\xad\x15\x37\xee\x10\xa0\x57\xf4\xee\xc4\xb8\x1d\xc6\x03\x92\xfc\x91\x88\xd3\xe5\x61\x78\x59\x65\x09\x2e\x44\x31\x7f\x2a\x48\xe3\x66\x05\xfc\x58\x3f\xc1\x73\xb0\x5d\xb9\xdc\xbc\x75\x57\xd0\x64\x87\x39\x0f\xbb\xba\x77\xaf\x3a\x01\x4e\x1a\xc3\x51\x39\xca\xa1\xc5\x3a\x8d\x17\x34\x7f\x17\x8e\x1c\x54\xd0\xf5\x2b\x40\xe9\x10\x42\xc9\x3e\x7e\x48\x1d\x79\x2e\x28\x8f\xc2\x7e\x4c\x2f\xcf\x11\x1f\xe9\x7d\x9e\x23\x37\xd2\xfc\x1c\x30\x98\xf0\x66\x84\xa3\x1d\x55\xeb\xf3\x62\xc0\x27"}, -{{0x3f,0x59,0xd6,0xa0,0x18,0xf5,0x0a,0x82,0x21,0x17,0xe5,0xb4,0x73,0x60,0x9e,0x30,0xcd,0x64,0x92,0x0c,0xa1,0xc2,0x75,0x0d,0xcb,0x09,0xea,0xab,0x80,0x7a,0x3e,0xac,},{0x45,0x7d,0x0e,0x59,0xc1,0x1f,0x34,0x8f,0x3b,0xfb,0xdd,0x3f,0x32,0x7d,0xe7,0x8c,0x0a,0x75,0x77,0xc0,0xae,0xef,0x42,0xd4,0xc1,0xe5,0x67,0x00,0xd1,0x08,0x80,0x8b,},{0xd7,0x42,0x5e,0xa1,0x94,0xa6,0x71,0x5c,0x45,0x2e,0xc4,0xf6,0xd6,0xc7,0x6e,0x6d,0xd3,0x74,0xd3,0xca,0x7a,0xe7,0xa1,0x19,0x95,0xd0,0x2b,0x94,0x2d,0x4a,0x31,0x87,0x0d,0xd7,0x34,0xc1,0x2f,0xca,0x89,0xa8,0xeb,0x02,0x13,0xeb,0x13,0x9c,0x14,0xa8,0x7a,0x6a,0x33,0xe8,0x18,0x60,0x3b,0x2e,0x31,0x30,0x23,0xfa,0x58,0x73,0x7d,0x0e,},"\x7d\x10\x3a\x6c\x6b\xa2\xd0\x90\x87\xee\xf2\x25\x4c\x1c\x90\x3f\x06\x76\x95\xa5\x4c\x45\x15\xe4\xd1\x3b\xc1\xfb\xfb\x54\xd6\xe7\xa1\x67\x34\x9c\x14\x80\x99\x76\xda\x04\xa7\xe5\x8d\x96\xb4\x0a\xac\x3b\x2b\xdd\x14\xb9\xb5\x03\x22\xbb\x11\x64\x5f\x05\xe5\xe9\x78\xbc\x7f\xbd\x02\x49\x2e\xf8\x8f\x87\xd6\x68\x28\x0f\xd7\x08\x37\x32\x07\xff\x67\x0f\xcd\xa9\x7d\xf8\x48\x5d\x5e\x46\xdc\x3b\xd0\x43\x47\xf4\xd7\x52\x7e\xab\x27\x18\xf7\xd9\x3d\x13\x2b\xa7\x75\x82\x18\x89\x4e\x75\xa7\xde\xab\xe6\x93\x33\x5b\xa0\xdc\x73\xbf\x26\xc2\x88\xbf\xe9\xbe\x8a\x73\x6d\x75\xe5\xe0\xea\xa7\xbb\xe8\xd0\xb7\x7a\xbd\xd5\x14\x6e\x0f\xc9\xb3\x0d\xb9\xf0\x7c\xf4\xbf\x36\x26\x0a\x1f\x41\x41\x03\x31\xf8\xb4\x7c\x6b\x38\x33\x8c\x6d\xc9\xe8\x01\xff\xe1\xd5\x85\xf9\xb7\xfc\x31\xe9\x77\x8b\xca\x30\x27\xc2\x32\xc0\x74\xcb\x18\xe5\xb7\x29\x97\x00\x5f\xfe\xee\x4b\xf3\x7c\x8f\x87\x4b\x1b\x24\x6a\x63\x45\x41\x5d\xac\xac\xa7\x07\x5a\x60\x44\x3a\xc3\x31\x92\x36\xe2\x3c\xf6\xb7\x54\x47\x40\x80\x70\x52\x11\x49\x84\xb8\xd8\xf7\xe8\x57\xdc\xc6\xfa\xec\x88\x69\xcf\x96\xb9\x97\xdf\xa9\xaf\x91\x84\xad\x62\x3f\x1d\x90\xb8\xca\x75\x9b\x44\x8e\xab\xfc\xe1\x8c\x17\xcf\xdf\x9a\x3e\x33\x12\xe6\x3e\x5f\x08\x4c\xea\x90\x4c\x1c\x90\x99\x13\xcc\x4b\x19\xd0\x44\xa3\x72\x00\x34\x97\x3c\x73\x84\x94\x9b\xd6\xf9\xba\x92\x56\xf9\x8c\xd3\x94\xc5\x66\xda\x83\xc3\x11\x80\x10\x9f\x16\xd1\x03\x47\xb7\xe3\xe9\xdd\x6b\xe3\xbd\x3c\x77\xff\x1a\x79\x96\xa0\x78\xdc\xf8\x9d\xcd\xce\x2d\x1b\x61\x56\x95\xf4\xcc\x9f\x8f\x4f\x2a\x08\x80\x46\x41\xbc\xa8\x26\x62\xce\x88\xfa\xa5\x31\x45\xb6\xa4\x59\x55\xae\xc8\xcc\x2a\xf8\x1c\xcc\xb5\xd7\xc6\x4f\x9e\xce\x1c\x99\x83\x32\x64\x84\xa1\xe5\xec\xe4\xce\x36\x54\x4d\x63\x73\x5f\x77\x76\xf2\x1a\x20"}, -{{0xa1,0x21,0x2b,0x34,0xdb,0xca,0x63,0xb7,0x09,0x36,0x12,0xd0,0x5d,0xab,0x7b,0x4c,0xc8,0xf7,0xb6,0x76,0xa9,0x34,0xad,0x01,0xf6,0x59,0x85,0x1b,0x3b,0xb4,0x4e,0x4e,},{0xba,0x2f,0xcc,0xea,0x9a,0x08,0x05,0x91,0xbe,0x71,0x26,0x8d,0x7e,0x95,0x1f,0x25,0x0d,0xed,0xc0,0x04,0x16,0xe5,0xf3,0xf9,0x08,0xdb,0x6c,0xc5,0x71,0x25,0x49,0x25,},{0xfa,0x93,0xed,0x65,0x95,0xbc,0x95,0x8d,0xc0,0x42,0xce,0x16,0x45,0x16,0x7b,0x79,0xe8,0xf6,0x73,0x4c,0x46,0xf8,0x0f,0x63,0x1f,0xd5,0x48,0x49,0x08,0xf5,0xe5,0x1a,0x22,0x42,0x7e,0xe6,0x86,0xf5,0x64,0xff,0x98,0x2f,0x6e,0xf4,0xd2,0xca,0x1f,0x0c,0xa5,0x62,0x49,0x10,0xcd,0xd6,0x3c,0x11,0xa3,0xc2,0xb1,0x6d,0x40,0x97,0x3c,0x07,},"\x07\xc3\x7c\x46\xbe\x3c\x68\xd0\x56\x89\x57\x7a\xa6\x4a\x93\x2b\x90\x64\x46\xb2\x9b\xaf\x12\xf6\x17\x4a\x6b\x42\xbb\xae\xfd\x1f\x1f\x37\x3e\x0b\xcc\xc4\x73\xdd\xfc\xee\x1a\x7f\x21\xb9\x6a\x62\x60\xef\x0a\xa1\xf2\xd8\xb2\x95\x9e\x71\xd1\x2c\x95\x33\x58\xa2\x77\x4c\xc5\xe6\xf3\x79\xa3\x13\xe4\x35\xed\x69\xdf\xd6\xd4\xa5\x9a\xde\xe3\xcc\x7e\xc4\xba\xcb\xdb\xb3\xfe\xe5\x43\x0b\x73\xf6\x05\x1a\x60\x96\xc6\x0e\x9b\xc9\x2c\xc8\xfa\x05\x9f\xac\x2a\x93\xef\x70\x07\xd6\x4f\xbe\x50\x06\x49\x64\xd5\xa0\xad\x60\x11\x75\xcd\x9c\xab\xa4\x53\xf9\x10\x3b\x25\x48\x55\x45\xd3\x01\xf0\x3c\x5f\x9f\x94\x78\xbd\xf9\xd4\x14\xbf\x1d\xca\x3b\x1c\x1d\x9d\xaa\x99\x71\xf9\xe6\x17\xfb\xfa\xf5\xb0\x2a\x7f\xbd\x5d\x4f\xb8\x94\xc0\x97\x5c\x54\x59\x2b\x49\xa0\xfc\x85\xdd\x08\x53\xf3\x0c\x51\x50\x2d\x98\xfc\x1a\xb8\x5a\x17\xcc\x58\x96\x1a\xae\x97\x64\x57\x0b\xa5\xcb\xdb\xc9\x6d\xfc\xeb\x8d\x11\xda\x53\x36\x4b\x40\x25\xfe\x0b\x8b\xa8\xa3\x53\xad\x23\x68\x67\x20\x16\x9f\xe9\x73\x43\x2f\xfe\x29\x1a\x4b\x11\xde\xdd\xa0\xaa\xc7\x9a\x5e\x42\x62\x0a\x64\x58\x7d\x20\x59\xe7\x87\x01\x3b\x40\xce\xec\x59\x92\x08\xf6\x6e\xd0\xca\x6e\x1b\xe9\x09\x2e\xc2\x7d\xb2\x16\xee\x6d\xad\xfe\xbc\x21\x70\x5b\xc4\xa8\x5a\xee\x57\x7e\x57\xd2\x39\xaf\x58\x6e\xfe\xec\x22\xcf\x38\xd1\xcf\xb3\xcd\x74\xdd\x0d\x9a\x33\x81\xaa\x81\xe6\xa2\x97\xe3\x9b\x81\x91\x37\xad\x27\xd4\x75\xe2\xbf\x54\xaa\x42\x6d\xc2\x9c\x4c\xa8\x17\x6d\xf3\x43\x13\x7a\x2d\x79\xd1\x2e\xf9\xaa\x7b\xe1\xcf\x67\x75\xe5\xd8\xa4\x43\x0a\x85\xc3\x3d\xb6\x1c\xd2\xf3\x51\x87\xb4\xf6\xea\x9e\xbd\xd7\x53\xd1\xc4\xef\x72\x47\x11\x59\xff\x07\xb7\x78\x70\x90\x64\x96\x24\x9d\x42\x78\xe3\xf3\xca\x6b\xcb\xf3\x7a\x26\x5b\x89\x65\x39\x19\x0f\x9a\x31\xf1\xe7\xb4\xb6\x5c\xd1"}, -{{0xd9,0x68,0x20,0x86,0xfe,0x7d,0xda,0x30,0xb8,0x71,0x11,0x06,0x01,0x93,0xd8,0x47,0x56,0x6a,0xb9,0x4c,0xfd,0x9c,0x97,0xab,0x6b,0x43,0xe7,0xa8,0xd3,0xf7,0x93,0x82,},{0x8b,0x0b,0x13,0x72,0xd8,0x87,0x33,0xef,0x72,0x33,0xf6,0x37,0x97,0x90,0xd1,0xe4,0x6e,0x1e,0x07,0xe9,0xd3,0xfb,0x8b,0x0b,0xe2,0x52,0xed,0x04,0xc5,0xfa,0x16,0x3d,},{0x17,0x93,0xe4,0x97,0xeb,0x52,0x1c,0xa7,0x4e,0x35,0xd1,0x4a,0x63,0x86,0x8c,0xbe,0x94,0x99,0xda,0x2f,0x21,0xb4,0xeb,0x52,0x60,0x34,0x0f,0xca,0x3c,0x1f,0xec,0xa7,0x8d,0xbe,0x5b,0x14,0xac,0x10,0xf3,0xfa,0x76,0xfa,0x2e,0x71,0xe4,0xc9,0x14,0x61,0xaa,0x75,0x97,0x7e,0x5e,0x70,0x79,0x26,0x70,0xef,0x7f,0xf0,0xe6,0xa2,0x87,0x08,},"\xe8\x81\x4b\xe1\x24\xbe\x3c\x63\xcc\x9a\xdb\x03\xaf\x49\x3d\x44\x2f\xf2\x0d\x8b\x20\x0b\x20\xcd\x24\x93\x67\xf4\x17\xf9\xa9\xd8\x93\xfb\xbb\xe8\x5a\x64\x2b\xe2\x70\x1d\x1d\x1b\x3c\xd4\x8a\x85\xcf\x58\xf1\x59\xa1\x97\x27\x31\x43\xa5\x78\xf4\x2e\x8b\xcc\x8b\x62\x40\xf9\x32\x71\x90\x05\x38\xff\xc1\x87\xc0\xaf\xc8\xdb\xcc\x49\x2b\xcd\x67\x9b\xaa\xef\x3a\xf5\x08\x84\x34\xa9\x45\x86\xf9\x4b\x49\x97\x0b\xba\x18\xf5\xea\x0e\xbf\x0d\x27\xee\x48\x2a\xa8\x3a\xd0\xdd\x0e\xe6\x09\xdf\x59\xd3\x7f\x81\x8b\x2c\x8d\x7c\x15\xf0\xf6\xf5\x44\xdd\x4c\x7e\x7c\xb3\xa1\x67\x24\x32\x4f\x77\xd5\x89\x48\xf8\x47\x5a\x60\xd5\x3e\x5b\xd5\x10\xc1\x71\x37\xc9\x9e\x1c\xfa\x51\x5a\xf9\xbc\x85\x56\x9d\x21\x2a\x21\x19\x07\x29\xf2\x81\x7d\xe8\xc4\x69\x15\xe0\x21\xdf\x70\xff\x6d\x60\x21\x5f\x61\x4f\xc2\x11\x39\x90\x4d\xf3\xb2\x92\xb7\x49\xdc\x4d\xea\x02\x51\x8b\x62\xd1\x58\x62\xc9\x2d\x2a\x4c\x99\x67\x01\xcd\xec\xae\xd8\x4a\xb6\x28\xee\x98\x4f\xc1\x11\xee\xcb\x59\xe4\x84\x44\xef\xc0\xd4\x56\xe2\xc8\x52\x51\x84\x41\xc3\xdb\x76\x30\xdd\xd5\x15\x62\x49\xa2\x87\x30\x98\x38\x38\xae\x59\xac\x4c\xc7\x11\x0f\xd6\xde\x68\x10\x1e\xa5\xb2\xff\x69\xfd\x36\x4e\x3c\x94\x48\xde\xfe\xfe\x17\x5b\xcb\xe1\x17\xcc\x11\xb4\xff\x75\x49\xc3\x3e\x10\x25\xb6\xb5\x92\x04\x8a\x8e\x31\x96\x9e\x81\x8d\xcc\x18\x8b\xb1\x9d\x7a\x24\x40\xa3\xba\xba\x4e\xb1\xb8\x1c\x45\x67\x9d\xb4\x6b\x31\xbc\xde\x77\x76\x75\x7d\x99\x31\xec\x20\x63\xfc\x6f\x1f\xcd\x76\x1e\xcc\x57\xa7\xd0\x30\xa8\x5e\xa2\x73\xef\x18\x25\xb0\x50\x92\xab\x96\x45\x35\x9a\x44\x4f\xf7\xd1\x66\xb5\x75\xfa\xc2\x98\x30\x8d\x9f\xaa\x68\x46\x3d\x1d\x0f\x7b\x7d\xf8\xa5\x1c\x68\x15\xd3\x71\x59\xad\xc0\xb5\x93\x22\x4a\x81\x83\x21\xd7\x21\x9f\x09\x68\x6c\xfc\x95\x22\x59\x71\x8d\xfc"}, -{{0xb5,0x2b,0x24,0x9a,0x7a,0xea,0xe0,0xfb,0xd9,0x4f,0xfc,0xf9,0xa9,0xfd,0xe1,0x0d,0xe6,0x1c,0x3f,0x4c,0xbd,0xa1,0x4b,0x28,0x9f,0xe0,0x1f,0x82,0x70,0x73,0x34,0xca,},{0x73,0x51,0x63,0xbf,0xcf,0xd5,0x4f,0x9d,0x35,0x2e,0x1c,0x2f,0x3c,0x01,0x70,0xc9,0x5c,0x18,0x42,0xcc,0xc7,0x42,0x16,0x23,0xae,0x04,0x96,0x98,0x0c,0xee,0x79,0x1c,},{0x6f,0x48,0xa9,0xf7,0xf0,0xfa,0x19,0x2b,0x66,0xd1,0x21,0x75,0xa3,0x33,0x61,0x23,0x03,0xe1,0x80,0xb9,0xfa,0xb1,0x8e,0xda,0xbe,0xbc,0xdf,0x66,0x74,0xfd,0xfc,0xc5,0x36,0x07,0x08,0x9b,0xf9,0x80,0xce,0x35,0x89,0x4c,0x2f,0x9b,0xab,0xdc,0x44,0x38,0x66,0x7a,0xb3,0x29,0x7a,0x62,0x48,0xec,0x02,0x69,0xfa,0xa9,0x9c,0x72,0x48,0x07,},"\x1d\x44\x5e\x8e\xe3\x6f\x6e\x10\x64\xee\x12\x81\xe6\xb4\xa4\xce\xc5\x0a\x91\xc2\xb6\x67\xc8\x30\x5d\x1e\x9a\x5f\x7b\x73\xa3\x44\x58\x82\x58\x1f\xb0\xc1\x1e\x64\xf6\xee\x92\xe8\x11\xf9\xf2\xd6\xc5\x9c\x63\x44\xbe\x76\x91\xd1\x16\xdd\xa4\x93\xca\xde\x51\xc0\xce\x77\x37\x2b\x61\xa7\xc4\xfb\xb6\x33\x40\x13\x33\xcb\xf7\x13\x72\xad\x2f\x04\x4e\x99\x2a\xc0\x35\xf5\x87\x9c\x05\x30\x04\xf8\x22\x3f\x23\x7a\x24\xa4\x09\xb7\x89\x4f\x6a\xd5\x18\xe0\x46\xb8\xa8\x4c\x3f\x4c\x62\x60\xe6\x16\x9f\xd9\x44\xd5\x7f\xbc\xf9\xba\x27\x75\xf2\xd6\x0e\xd7\x72\xc4\x6c\xcd\x63\xc8\x50\xb8\x0d\x58\x7c\x52\x08\xdf\xb1\xa2\x58\x78\xc0\x2d\xec\xe3\xe6\x02\xe9\x63\x2f\xc3\xc2\xc7\x9b\x25\xab\x41\x03\x4c\x6e\x26\xb8\x69\x25\x53\x57\xa6\x86\x78\x1d\xfe\x6e\x64\x4b\xeb\xa9\xb6\x27\xda\x1f\xcb\x5e\xc0\xbe\x49\x7c\xf1\x88\xe1\xef\x1a\xf0\x60\x1b\xf1\x6b\x29\x11\xfd\x9f\xf3\x4f\x0e\x97\xac\x95\xa7\xfe\x2c\xf9\x0e\xa6\xce\xd3\x3c\xcb\x0e\xd1\xef\x2d\x41\x60\xef\xb0\x7c\x59\x1a\x5c\xb1\x6c\x70\xca\x16\x94\xfb\x36\xf2\xca\x19\xeb\xa5\x2b\xe3\xd4\xad\x89\x5a\xbc\xad\xa4\xb3\x6f\x02\x61\xd6\x5f\x59\xe0\xcf\xd2\xa6\x14\x8a\x88\x92\xdd\xbb\x45\x81\x0d\xb3\xbf\x4a\x9e\x26\xe9\x2c\x15\xea\x26\x18\xcf\xee\xb4\x62\xd8\x62\x8f\x25\x4f\x54\xd2\xaf\x27\x11\x3b\xab\x4f\x9a\x7d\x06\x79\x18\x11\x94\x2b\xdc\x32\xf8\x45\x92\x2d\x7b\x2d\xdb\xa9\x59\x14\x09\x28\xf8\xc2\x8d\x98\xb4\x4e\x1d\x19\xb9\x7f\xd3\x9c\xc0\xf9\xa5\x23\x6d\x34\x9f\xc8\x35\xac\x49\x21\x92\x46\x2e\x40\xac\x62\x9b\xeb\xff\xd2\xeb\xa7\x2d\x27\x88\xb2\x44\xbb\x77\x7a\xd0\xf7\xb7\xf9\x6f\x23\x41\x23\x99\xfc\x1d\x87\xa1\xd0\x87\xba\x08\x90\x27\xea\xbb\xc0\x5e\xda\xfe\xe4\x33\x79\xe8\x93\x29\x13\x31\xb4\x60\xbf\xa7\x33\x2e\x08\x42\xec\x25\x73\x39\x3d\xe9\x53\x06"}, -{{0x78,0x2a,0x93,0xef,0xe0,0xef,0x06,0xcb,0x25,0x34,0x33,0x0e,0xfd,0x0e,0x96,0x84,0xe9,0x96,0x9b,0x52,0x58,0x12,0x3e,0x49,0x02,0x39,0xbf,0x24,0xbf,0x9f,0x65,0x23,},{0x94,0x2f,0xa1,0x40,0x6e,0xe2,0x68,0x3e,0x29,0x37,0x7e,0x49,0xf7,0xba,0x75,0x7c,0xf5,0x0e,0xf0,0x72,0x37,0x07,0xd4,0x40,0x3d,0x28,0x62,0x25,0x70,0x45,0xde,0x87,},{0x93,0xe7,0x40,0x5a,0x40,0x44,0x51,0x01,0x66,0xc8,0xac,0x26,0x4c,0xe3,0xb5,0xba,0x66,0x65,0xd6,0x8b,0xad,0x45,0x87,0x12,0xdc,0x93,0xc2,0xc3,0x90,0x56,0x8d,0x74,0x02,0xef,0x7d,0x57,0xf5,0x49,0xb8,0xa1,0x04,0x2f,0x7f,0x69,0xa6,0x79,0xaa,0x85,0x5f,0x34,0xf8,0x01,0xd5,0x7d,0x79,0x89,0x5d,0xeb,0x8d,0xea,0xdb,0x35,0x23,0x08,},"\x46\xa4\xe3\x19\xa6\x70\xac\x99\x39\x94\xa5\x33\x00\xc3\xf7\x91\x44\xc2\xf7\xfe\xc1\x11\x6e\xee\xb3\x62\x1c\x76\xac\x35\xda\x79\xdb\xff\x6e\x18\x9c\xa9\xdb\xfc\x9a\xbb\xda\x05\x48\x47\xb2\x97\x1b\x02\xfa\xce\xbb\xe9\x26\xd4\x69\xeb\x0a\x86\x03\x89\xac\x74\x41\x62\xbf\x6f\xb1\x3b\x42\xcb\x9b\xb8\xc9\xd7\x26\x07\x13\x8e\x78\x00\x12\x1e\xe0\xcd\x63\x3e\xd5\x35\xc7\xae\x5f\x40\x60\xbb\xdd\x27\x1c\x9d\x11\x0a\xbf\xf5\xe0\x60\xea\x6e\xe8\x38\x90\xb1\xe9\x2a\x92\x56\xd7\xb2\xba\x98\x2a\x31\x14\xbb\x6d\xef\xfe\xe2\x69\x6f\x0a\x2f\x9c\x21\xaa\xa5\xb2\xde\xfa\x11\xaa\xb7\x07\x6d\xe6\xe5\x7e\x86\xf2\x84\xbb\x67\xf5\xa4\x9e\xe6\x85\x92\x10\x32\xc9\x5b\x74\xe7\xe3\xea\xc7\x23\xf1\x75\xaf\x08\x2c\x85\x8e\x0d\xfa\x01\x72\x8c\x38\xfb\xbb\x4c\x83\x58\x1f\x81\xac\xe6\xc6\x3c\x6b\xda\xac\x56\x20\xeb\x9a\x56\x8e\x7e\xbb\x7b\x72\xb3\xd1\xa1\x64\xef\x52\x4e\x7b\x9f\x00\x79\x9a\xb0\x86\x71\x59\x76\xc1\x4d\x0d\xf6\x5f\x7b\x96\xbf\x9e\xbc\xda\x7f\xee\xef\x11\x34\x22\x00\x1a\x03\xa7\x63\x3d\xf5\xe4\x99\x39\xa1\x21\xdb\x89\x9d\x9b\x8a\xc2\xdb\x4f\xad\x0c\x30\xcf\x0b\x8b\xdb\xc9\xe9\x80\x2a\x79\x7c\x82\x38\xe4\x65\x11\xff\x24\x06\x8c\xad\xcf\xf2\x44\x8c\xc0\xbf\xf9\x27\x69\x22\x33\x48\xd4\x5d\x6b\x6f\x2c\x8f\x15\x93\x38\x8c\x0b\xbb\xf4\x4b\x6d\xdb\x50\xb9\x8c\xd7\xf0\x9c\x73\x0f\x7d\xe4\xd0\x08\x15\x6c\xb3\xcd\xe0\xca\xb3\xad\x0a\x58\xa8\x39\x54\xe2\x34\xa0\xa8\xa0\x4b\x57\x3c\x9a\x8e\x9b\x92\x9e\xd3\x8b\x8b\x22\x8b\xf5\x5a\x3c\x6e\x2c\x6b\x51\xf6\x82\x65\x2f\xbb\x70\x8e\x74\x64\x0e\x33\x13\xe1\x7b\x46\x94\xd7\xfd\xf0\x11\x1f\x90\x60\x8c\x1b\x5a\xf4\x22\xdc\xde\xca\xd9\xdd\xb7\xf5\x0d\x1b\xf5\xbc\x63\x78\xcc\xaf\xfc\x32\x01\xe6\xc7\x87\xb4\x8c\x44\x3b\xa2\x40\xd9\xd5\x0f\xf6\xc0\xe9\xdf\x7f\x1a\x5b"}, -{{0x6f,0xe7,0xbc,0xf7,0xa6,0x84,0x42,0x3d,0xe1,0x07,0x6f,0xd7,0x6d,0xa7,0x83,0x42,0x33,0x73,0xb3,0x81,0x32,0x9e,0xfd,0x61,0x57,0x42,0x4e,0xc4,0xb2,0x65,0x5a,0x94,},{0x77,0x40,0xe9,0x1a,0xfe,0x45,0x32,0x4f,0x8b,0xb9,0x90,0xca,0x2a,0x34,0x12,0x79,0xdd,0xaf,0x23,0x2c,0x3b,0xb4,0x15,0xf1,0x78,0xb6,0x09,0x2f,0xba,0x19,0x5f,0xec,},{0x99,0x14,0xcc,0x50,0xfe,0xf0,0x93,0x5e,0xfb,0x89,0xb3,0xd6,0x4e,0x3c,0x1c,0x34,0x12,0xae,0xd6,0x59,0xb9,0x01,0x66,0x22,0x2c,0x0d,0x13,0xec,0x1c,0xe3,0xa6,0x8a,0xe6,0x28,0x1b,0x7e,0xfd,0x9d,0x4e,0xc6,0x4b,0x82,0xe7,0x3e,0x14,0x47,0x9f,0x03,0xfb,0xac,0x8f,0xa3,0xab,0xdb,0x41,0xea,0x42,0x15,0xc4,0xa4,0xd4,0x94,0x9d,0x09,},"\x0b\xaf\x0a\xd4\x40\x61\x2b\x4c\x5a\x13\x6c\x3a\x42\xbe\x1c\xa2\xb7\xc3\x19\x86\x2a\x44\xa9\xfd\x50\xc4\xee\x73\x54\x1c\x5e\x64\x57\xef\xa8\x18\x25\xb6\xdd\x4a\x72\x19\x4a\x29\x68\x68\x8b\xd4\x9e\x5a\x8f\x4c\x04\xdb\xaf\xc2\xe7\x88\x4c\x0c\x70\xc2\x08\xd4\xe9\x54\xcd\x16\x75\xda\x8e\x74\xc6\x5c\x49\x7c\xf9\xdc\x69\x42\x49\x65\xbd\xcb\xa5\xde\x52\x93\x6f\x92\x5f\x62\xe2\x01\xf9\x95\x05\xd3\x77\x7b\xeb\x3c\x2e\x08\xb2\xec\x9a\x87\x3e\x5a\x9c\x21\xfb\x4a\x2f\x3e\x86\x1f\x3c\xf4\xd6\xb5\xdc\xd1\xc8\x8b\xcd\x91\x63\x53\x9a\xc6\x2c\xd0\x65\x9f\x4e\xf2\x32\xc2\xce\x57\xfc\x77\xf9\x02\x85\xeb\x35\x01\x69\xed\xc6\xa8\x06\xff\x50\xf6\x1c\x7e\x0b\xee\xeb\xec\xec\x63\xbf\xc9\xd3\x98\x3f\x5b\xb4\xb2\x61\xc7\x46\x47\x1f\xcb\xf2\x89\x2c\x61\x08\x97\x0b\x68\xdb\x5e\x43\xc4\x50\x4d\xda\xe2\xd0\xff\xff\xa2\x8b\x67\x59\xae\x11\x28\xe1\x6f\x66\xd4\x92\xad\x61\xe3\x72\x2c\x96\x0f\x88\x69\x2b\xe8\x1a\x9f\x41\x28\x90\xff\xa3\x46\xe7\x02\xc8\x67\xdf\xa2\x59\x70\x3b\x73\xf5\x25\x07\x4f\x32\x27\xc4\x9c\xec\x1b\x64\x5a\x10\x3b\xd4\x47\x1f\x33\xf9\xf1\xba\xc3\x27\xd7\x91\x78\x61\xd0\xad\x91\xab\xee\x60\x22\x2e\xa2\xa3\xc8\xca\xc0\x52\xae\x9a\x2c\xbd\x90\x85\x5d\x73\x3d\x53\x19\x13\x3f\x95\x41\xbd\x0b\x61\xf0\x99\x52\x68\x35\x1e\x28\x63\xc1\xca\x2c\xa5\x1e\x3c\x97\x63\x83\xf5\xc4\xc1\x1f\xf4\x10\x03\x6f\xd5\x1d\x5a\xc5\x6b\x02\x3c\xe9\x02\x9c\x62\x0f\x22\x55\x70\x19\xad\x9b\x42\x64\xed\x4d\x71\xb4\x34\xf4\xa4\xd1\x7a\x7d\x57\x69\xfa\x1e\x14\xa6\x9f\x7a\xe4\x19\xcc\xf5\x94\x7f\x8c\x76\x82\x69\x71\x16\xc2\x40\x5f\x5a\x19\x59\xc5\x4b\x48\xf0\x87\x2f\x59\x6e\xd4\x59\x64\x48\x8d\xde\xc1\x2b\xdb\x63\x6d\x0b\x34\x9e\x74\x9e\xb6\x60\x92\xff\x45\x11\xfb\xa5\x9b\x59\x62\xcb\x93\xcc\x85\x51\x5c\xc8\x6a\xb0\xc6\xb2"}, -{{0xdd,0xa4,0x8a,0x0d,0x15,0xa2,0x9e,0xba,0x9a,0x76,0x30,0x5d,0x36,0x0e,0x46,0x6e,0x72,0xd8,0x04,0x0e,0xfe,0x2e,0x89,0xc0,0x4b,0x64,0x61,0x31,0x5a,0x9b,0x8b,0xf4,},{0x4f,0x5c,0xc3,0x6a,0x80,0x94,0x16,0xb5,0x8e,0x15,0xd2,0x4c,0xc5,0x79,0x68,0xcb,0x57,0x3b,0x76,0xad,0x90,0x88,0x7a,0x8e,0xf3,0x6c,0xde,0x7e,0xca,0x40,0x0f,0xcc,},{0xce,0x71,0xbc,0x82,0xd5,0x31,0xd0,0xf9,0x3b,0x57,0xbf,0xdc,0x2f,0x73,0x16,0xcf,0x40,0x4e,0xe0,0x9a,0xf8,0x8f,0x33,0xbf,0x80,0x6c,0x7c,0xad,0x6b,0x8f,0xfa,0x36,0x62,0x36,0xba,0x74,0xe7,0x5c,0x15,0x09,0x6d,0xda,0xa6,0xe3,0xa6,0x2a,0x8f,0x5e,0xb1,0xc8,0xc3,0xf6,0xb6,0xc9,0x4a,0x6a,0x34,0x9f,0xc7,0xc0,0xcb,0xfb,0x19,0x0d,},"\xf5\xac\x19\xb8\x1f\x21\x11\xa0\xdb\x0a\xe3\x0d\x15\x13\xed\x34\x3e\x7f\x57\xf7\xf7\x7d\x65\xb8\xac\x7c\xe3\xa6\x01\x17\x4b\xae\xd9\xbf\xa1\x36\x03\x59\x76\xf5\x16\xd5\xa8\x70\xf4\x5d\xb1\x91\x9f\x1e\xb1\xcb\xec\xbe\x88\xec\x32\xd1\x91\xe9\x24\x88\x21\xa7\xe7\x68\x1f\xe3\xab\xec\x11\x58\x4b\xdb\x33\xde\x1b\x4c\xa9\x48\x91\xeb\x66\xdc\xb8\x53\x9a\xc4\x11\x63\x73\x6c\xcf\xd6\x9a\xbb\x83\x81\x4d\xd3\x8c\xd6\x03\x81\x31\x87\x28\x05\x2a\x25\xcb\x66\x54\x71\x05\x86\x50\xcc\xc7\x57\x56\xdb\xee\x68\x8a\xb8\x26\xec\xad\x4a\xd5\xa7\xdb\x57\xe8\xf6\x5f\x1b\x64\xab\xff\x82\xdd\x53\x33\x4b\x79\x7a\xc4\x02\x28\xdd\x81\x7f\x23\x9d\x3e\xe8\x04\xa1\x9a\xea\xc8\xcf\xe3\x3e\xb6\x57\xec\x9c\xe9\x23\xd6\xb3\x88\x91\x4c\xfb\xa2\xe7\x2b\xfc\x2b\xc3\xd6\xf9\x85\xc0\xd9\x75\x34\xdb\x95\x8e\xed\xe5\x7b\x16\x49\x1f\xfb\x75\x5c\x1a\x58\xd7\x8a\xb3\x77\xfa\xec\x0d\x31\x18\x18\xe8\x99\x26\x0e\x3e\xbd\x1c\xcd\x29\x24\x6f\xa8\x2d\x0b\x76\x62\x2b\x2c\x4b\xc5\x2f\x54\x9f\xee\x72\xa3\x0f\x55\x4f\x33\x1f\x36\xd2\xa7\x4d\x99\x9e\xc1\x0a\x08\x29\x4f\x00\x2b\x43\x61\xe5\x90\x27\x9c\x2f\xb1\xbd\xa4\x31\x2c\xcb\x24\xd7\x52\x82\xce\x7c\x06\x1a\x0c\xa5\x52\x0c\x74\xf6\xf6\x33\x3b\x18\xc4\xb5\x41\xcb\x6c\x51\xe0\x15\x75\xba\x80\x51\x2f\xfa\x7c\xe0\xac\xcd\x22\xd1\x40\x27\xc5\x3a\xba\x1f\x74\x37\x83\x5f\x11\x14\xd6\x8e\x3a\xcf\x3f\xf8\xde\x94\xc8\xe4\xef\x6d\x3a\xb3\x12\xc9\x1d\x02\x97\x01\x57\x50\x8f\x54\xa5\x81\x6f\x46\x7a\x21\x4e\x9b\x12\x84\x30\x02\x89\xe6\x5f\x36\x5a\x61\x0a\x8e\xa2\x84\x66\x6c\xfe\x55\x18\xe4\x35\xbc\xcd\x21\x62\x75\x01\xc7\x25\xf0\xb8\xeb\x57\x25\xe0\xe0\x6e\x0c\xef\x5d\xb2\x01\xb4\x8e\xc9\x1e\xbf\x87\x8d\xd5\x7c\xe8\xda\xc7\x33\x48\x48\xa1\xbc\x82\xc1\x8b\x06\x59\x55\xe4\xf5\x9b\xe3\x39\x85\x94\xdc"}, -{{0xec,0x57,0xb9,0x41,0xad,0xf3,0xca,0x13,0xe7,0x7a,0x78,0x05,0x77,0xcf,0xd0,0xdf,0x5b,0x49,0xed,0xc8,0x53,0x51,0x05,0x2d,0xa3,0x4e,0x99,0xf8,0xa9,0xbf,0x32,0x08,},{0x28,0x59,0xc0,0x71,0x97,0x8a,0x04,0xb7,0xf5,0x40,0x7b,0x6d,0x22,0x40,0x1a,0x78,0xef,0xd0,0x39,0x4b,0xb9,0x66,0xb9,0xa0,0x4d,0xa6,0xb5,0xef,0x81,0x9d,0xe3,0xfa,},{0x11,0x8e,0x14,0x62,0x12,0x6b,0x45,0xb8,0xc6,0x80,0x35,0x23,0x75,0x5c,0x56,0xdf,0xc4,0xe1,0x23,0xe4,0xac,0xbb,0x66,0xba,0x0b,0xa6,0xfe,0x3e,0x05,0x3d,0xa4,0x11,0x9f,0x57,0x19,0x29,0x5e,0x0c,0x82,0xac,0x64,0xd7,0xc5,0xcb,0x1a,0xc8,0x98,0xdf,0x26,0x3d,0xdf,0xd3,0x60,0xf3,0x00,0x8d,0x91,0x01,0x8b,0x26,0xf6,0xa1,0x73,0x0a,},"\xd2\xbc\xbd\x1b\xc3\x61\xab\x32\xc6\x6d\x72\xfd\x48\xa8\xe2\x27\xdc\x6b\x8d\x6b\x15\x08\x48\xba\x71\x5f\xf4\x7d\xd3\x5c\x8e\x49\x38\x1b\xb4\xe2\x93\x3f\x42\xcd\x26\xb7\x5b\x14\xd9\xc0\x03\x92\x82\xb6\x2b\x85\x56\xaa\xa1\x1c\xd6\x91\xe8\x28\x38\x2b\xe3\x06\x88\x9f\xc9\x20\x51\x37\xb1\x69\xd3\xbf\x17\xb7\xf3\x76\x93\xfc\xe2\x86\x03\x9f\x03\x80\x9d\x7d\x9d\x98\xc8\xfd\xe4\x6f\x11\x01\x94\x2a\x27\x9c\x51\x67\x06\xf5\x01\x91\xa9\x11\x2f\x6a\x24\x63\x0e\x1a\x26\xc3\x21\xe4\x6c\x9c\xcc\x85\xb6\xef\x94\x2f\x35\x3a\x64\x2b\x9e\x7e\xf9\x98\xc0\xfc\xe2\xd3\xa7\x5b\x99\x9e\xeb\x77\xf3\x1f\x9b\x08\x13\xa9\x7e\x30\x14\xc3\xa8\x6e\x25\x58\x73\x46\x21\xa3\x06\x6d\xae\x35\x84\x50\x31\xe3\x56\x65\xf1\x92\x29\x07\xdb\xb7\x39\x78\x6a\x8b\x76\x58\xab\x60\x27\x6f\x2d\x92\x1d\x1a\x51\x23\x0f\xc7\x4d\x19\xe8\x01\x84\xa4\xf1\x0e\x9e\x83\x4a\xbc\x9a\x36\xc4\x29\x72\x6b\xc0\x55\xdc\x8c\x06\x3f\x0e\xca\x9c\x61\xa8\xa9\x70\xbd\x4b\xb5\xf4\x24\xee\x4d\x04\xbf\xc2\x95\xe3\xbb\x1f\x34\xbe\xcb\xd9\x92\x0f\xe2\xe7\x7f\xcf\x36\x76\x3f\x32\xfc\x9c\xfd\x5e\x46\x59\x79\xc1\x67\xca\xbf\x5a\x12\x44\xb4\x91\xfc\x06\xb8\x94\x64\x19\x04\x6b\xa5\x16\xc5\xb2\x33\xc4\x14\xdd\xef\xb6\xda\x04\xf2\xe1\x3d\xaf\xf7\xa9\xa0\xc0\x2a\x51\x8e\xde\x57\xad\x95\x21\xde\x64\xed\xdf\x6f\x49\xa9\x67\x0f\x63\x2d\x3f\x7d\x42\x42\x52\x07\xd0\x53\x60\x4f\xe3\x9d\x13\xb9\xf5\x2c\x8b\xc2\x92\xb0\x07\x6e\xa4\x2a\x56\x00\x56\xdf\x25\xde\x51\xad\x35\x88\x1d\x08\x54\x32\x24\xd7\xfa\x5d\x70\xb8\x60\x3e\xf2\x3c\xe0\x63\x39\xd6\xcd\x09\xe2\x2a\x95\x74\x9e\x50\xdf\xbd\x3b\x8a\xd6\x9f\xd3\x04\x96\xb9\x84\xd1\xc0\xa1\x99\xc8\x59\x48\x05\xf3\x8b\xa4\x46\x31\xa2\xc5\x9e\xad\xc6\x55\x4d\x19\xf9\xbc\x98\x36\x6d\xfd\xec\x2a\x12\x1d\x0e\x48\x14\xd2\xcd\x3f\x58\x71"}, -{{0xcb,0xfd,0x91,0xd7,0x69,0x5c,0x1f,0x27,0x0f,0x69,0x24,0x6a,0xb3,0xdf,0x90,0xed,0xb2,0x14,0x01,0x10,0x1c,0xa7,0xf8,0xf2,0x6c,0x6d,0x00,0xf4,0xdc,0xb7,0x23,0x3e,},{0x51,0x38,0x79,0xcf,0x79,0xd2,0xf4,0x6d,0xf4,0xb8,0x5a,0x5c,0x09,0x49,0xeb,0x21,0x16,0xab,0xf9,0x81,0x73,0x5a,0x30,0x31,0x64,0xcb,0xd8,0x5a,0xdf,0x20,0xb7,0x52,},{0xf3,0x36,0x13,0x7d,0xfe,0x6f,0x42,0xa6,0x66,0x9b,0x55,0xf7,0x4b,0x80,0xb3,0x03,0x5a,0x04,0x03,0x67,0xf9,0x06,0x56,0xfc,0xef,0x0a,0x64,0x4c,0x52,0x27,0x2d,0xdc,0x39,0x27,0x3c,0xd7,0x72,0x60,0x10,0xeb,0xcd,0x8a,0x30,0xa0,0x52,0x01,0xab,0x70,0xb8,0xff,0x97,0xd0,0x28,0x8a,0x2c,0xb9,0x4c,0xbc,0x49,0x02,0x06,0x47,0x39,0x0b,},"\x26\x4a\x93\x3f\x7d\x0a\xec\xba\xc1\x3e\xef\x64\x4b\x0b\x53\xdd\x53\xa1\x28\x09\x04\x10\x0d\xbc\x1a\xb8\x7b\x51\x14\x89\x98\xf9\xda\x0b\x3a\x0a\x63\x37\xf5\xe3\x48\x6c\x2b\x7e\x54\x8d\x21\x12\x59\x39\x7a\xaa\x19\x4e\xe4\x69\x5b\xf9\x8c\x2d\x5f\x44\x87\x69\x9f\x73\x97\xe5\xd3\xa7\xe6\xd5\xf6\x28\xfb\xd0\x54\x97\xc5\x56\xa5\x0a\x4d\x05\xe2\xb7\x12\xcd\xbc\x35\x10\x68\xe4\x2a\xf1\x95\x38\x90\x1b\x88\x25\x31\x0e\x34\x3e\x1a\x17\xa1\x86\x7d\xde\x0e\xb4\x7d\xda\xb4\x56\xd3\x16\xf3\x52\x15\x54\x93\x7b\xf8\x08\xae\x4e\x4b\xc1\xc3\xc5\xb4\x75\x6e\x4a\x16\x5a\xd9\xe8\x82\x7f\x53\x16\xf7\x48\xca\xc6\x99\x8e\xd2\xd2\x10\x4f\x26\x84\x07\xc1\x35\xe6\x2f\x26\xa9\x22\x46\x0e\xab\x6d\x85\x16\x39\xa0\x0e\x5f\x08\xb3\x47\x65\xea\x02\x44\xf4\x75\xbb\xfe\xac\x18\x3e\x3b\x5b\xd1\xaa\xb7\x98\x52\x27\x98\xa0\x8e\xc6\xbf\x22\x57\xd4\x69\x2f\x5b\x03\xcd\xd0\xa2\x13\x3d\xe9\x70\x60\x3e\x32\x51\x47\x5a\xad\x8d\x93\x4a\xf6\xb2\xbf\xc7\xa6\x50\xb9\x1b\xde\xc1\x43\xf8\xad\x25\x4c\xfa\x50\x6b\xbf\xf2\x8a\x03\xbe\xb6\x59\xef\x5e\x5d\xdf\xfe\x76\xe2\x32\x30\xc4\xcc\xd4\x63\x10\xb3\x7d\xd9\x1f\xa6\xaa\x68\x16\x7f\x62\xa5\x5c\x8a\x69\xf9\xed\x1e\xc6\xcd\xb1\x44\xdd\x81\xab\x0b\xcb\xd6\x26\x43\x42\x0b\xca\xe6\x78\x69\xf6\x4c\x0b\x16\x9f\x3c\xdf\x3c\x90\x58\x95\xb7\xd3\x5b\x6f\xaf\xda\x25\xcc\xf2\x3c\x3d\x10\xde\x32\xe7\xf2\x71\xe3\x00\xd3\x95\x97\xda\x8f\x84\x37\x22\xef\x08\x36\x4a\x5f\x7a\x10\x5b\x96\x55\x17\x2d\xf7\xc8\x2d\x73\x74\xf9\x82\x64\xc9\xcd\xcc\xb4\x96\xf2\xe1\x0f\xd8\x26\x2f\xb1\xa9\xa9\x96\x5b\x0b\x84\x1a\xc0\xd0\xe9\xc1\xa3\xd9\x49\x3e\xa7\xaa\x60\x02\x05\xb8\xf9\x00\xbe\x0d\x7a\xbb\x4d\x98\xa0\x65\x83\xd2\x29\x5c\x27\x63\x18\xbe\x28\xd4\x21\x98\x2d\xed\xd5\xbf\xc3\x3b\x88\x65\xd9\x4e\xf7\x47\xd6\x26\xaf\x99"}, -{{0x51,0xa4,0x19,0x7a,0xb7,0x68,0x6f,0x82,0xf6,0x00,0x3a,0x0c,0x32,0xf3,0x9d,0x0f,0x2e,0x47,0x55,0x5f,0x4e,0x9f,0x8d,0xee,0xe7,0x5b,0xcb,0x1b,0xd1,0xef,0x69,0xe5,},{0x06,0x38,0x6d,0xf8,0x6b,0x61,0xf1,0xf8,0xf4,0xdc,0x45,0xb7,0x3e,0xda,0xa8,0x41,0x92,0x09,0x68,0xbb,0xd1,0x31,0xcc,0x5c,0xa1,0xc5,0x29,0x4e,0xee,0xd5,0xc8,0xba,},{0x2c,0x07,0x29,0x69,0xff,0x47,0x19,0x21,0x2a,0x12,0x19,0x38,0xb5,0x06,0xc6,0x02,0x99,0x5b,0x4d,0x02,0xa2,0x2e,0x61,0x98,0xd6,0xe8,0x7d,0xd6,0xae,0x07,0x62,0x25,0xac,0x70,0xbb,0x25,0xef,0x8c,0x0e,0xe8,0x1e,0xb6,0xfe,0x95,0x3d,0xf6,0xb1,0x81,0x59,0x49,0xe8,0xed,0x05,0x06,0xcb,0x01,0x2e,0x87,0x3c,0xd3,0x6c,0xd0,0x9b,0x0a,},"\x2a\xed\xb7\xe8\x2f\x1f\xe4\xce\x46\x9a\xda\x48\x34\x5d\x00\x6d\x1b\x3b\xff\x40\xeb\x21\x86\x7f\x51\xfc\xe9\x65\x64\x0c\x40\x9e\xc1\x3a\xd4\xd5\x2f\x89\x1b\xd7\x90\x66\xd6\xb4\xd9\x44\xca\x86\x8d\x89\x86\xd2\x42\xb5\x7e\xcc\xc4\xc4\xa4\x88\x29\x1b\x15\x9c\x8d\xe4\x39\x2b\xe4\xb8\x6f\xeb\xaa\x75\xea\xc5\xd2\x2d\x3c\x4f\x8d\x6b\xef\x79\xad\xb9\xb9\x2b\x49\x14\xd5\xea\x07\xc7\xf0\x21\xe2\xc2\x9f\x58\xd0\x7b\xe8\xa0\x84\x10\x0b\xc1\x52\xd5\x1c\xa8\x97\xd7\xc1\x31\x64\x4d\x08\x95\x32\x2e\x94\x40\xa8\x33\x9e\x1a\xa3\x90\xa7\xf4\xfc\xb5\x1d\xdf\xb6\xdf\x48\xaa\xf5\x67\x63\x37\xd8\x7d\xdd\x85\xb1\xd9\x25\xe1\xa9\xc2\x9f\xe0\x81\x8f\x51\x4e\xf7\x2f\x74\x7a\x67\x49\x46\x47\x69\x07\xa7\xca\x99\xe9\xdb\x8d\x20\x96\x41\x05\x7a\x7f\x44\xa3\x17\xb9\x09\x74\xbc\x86\xf9\x61\x7a\x96\x8a\x76\xa6\xb8\x38\x7c\xf5\x85\x3e\x60\x81\x90\xc1\xa7\x9f\x1e\x1d\x68\x6e\x0d\xe2\x2d\xb6\xcd\x9a\xeb\x85\x32\xc5\xc8\x5c\xc9\x0b\x5a\x01\x85\x79\xf2\x8e\x50\x2a\x77\x0a\x4e\xc6\x75\x26\x3d\x0d\xd7\x81\xb4\xfa\x53\xc9\xdb\xf8\x09\x8d\x57\xb3\x3a\xe2\xaf\xba\xeb\x3e\x68\x26\x6a\xd9\xaa\xb7\x17\x4b\xa6\x8c\x64\x79\x88\x39\x92\x67\x0c\xcf\x3e\x5a\xc6\xa1\x7e\x65\xe3\x1e\x1f\xdc\x85\xe2\x69\xc8\x09\x35\xef\x57\x4f\x20\xd2\x39\x56\x84\x86\xe7\xd9\x4a\x4f\x72\x4a\xb7\x00\x60\x98\xb2\x4f\x3f\x61\x58\x76\x91\x43\x5c\x7f\x29\xce\x4e\x5c\xa7\x1b\x2b\x18\x74\x55\x64\x33\xa3\x58\xc8\xc5\xef\x3c\x88\x08\x43\x03\x0c\x2d\x13\xd5\x1b\x78\xc9\xbf\x1a\x88\x24\xe6\x2e\x11\x18\x44\x39\x6f\x5a\xf2\xe2\x5c\x31\x26\xef\x36\x26\xe2\x6e\xfa\xfa\xcf\x99\x83\x0a\xa4\x12\x12\x33\x2f\x37\x8a\x16\x72\x33\xa0\xb4\x22\x13\xaf\xe3\x6d\x83\xdc\x45\x82\xa7\x96\x93\xb9\xd5\x71\xa5\x77\x12\xa0\x8b\x85\x66\xd3\x61\xac\x90\x26\x47\xaf\xc8\x86\x60\x3e\x24\x28\x3e\xfb"}, -{{0xb1,0x11,0x9c,0x36,0x11,0x8b,0x7a,0x06,0x5a,0x19,0x5b,0xfb,0x8b,0x79,0xa5,0xc2,0x87,0xe0,0x9b,0xd2,0x87,0xc2,0xda,0xac,0x5e,0x6b,0x01,0x16,0x4c,0x5d,0x73,0x7f,},{0x88,0xf2,0x18,0xec,0xba,0x99,0xe7,0x70,0xed,0x21,0x4a,0x8d,0x01,0xa9,0x2a,0x10,0x40,0x0a,0xca,0xf1,0xf6,0xee,0xd4,0x20,0x06,0x7e,0x13,0x6e,0xe2,0xc0,0xc6,0x70,},{0x24,0xec,0x1e,0x54,0xfc,0x7e,0x72,0x2d,0x37,0x55,0x1d,0x02,0xcf,0x13,0x5d,0x33,0xf5,0xd3,0xff,0x53,0x57,0x73,0xe0,0x29,0x91,0xee,0x85,0xff,0xd3,0xaa,0x29,0x99,0x7f,0x9c,0x46,0x44,0x70,0x19,0x7f,0xee,0x81,0xdc,0xe1,0x10,0x60,0x9f,0x87,0x0b,0x27,0xc1,0x8d,0xfb,0xcf,0xd9,0x32,0x05,0x48,0x52,0x5e,0x93,0x14,0x8e,0x22,0x05,},"\x88\x16\xb1\xeb\x20\x6d\x5f\x6d\xcc\x2e\x4c\xc3\x91\xd2\x32\x09\x00\x6d\xe9\x35\xe3\x18\x15\x2e\x93\xfc\x8c\x2c\xf0\x8e\x26\x43\x2b\xad\x9a\xdb\x32\x03\xd8\x98\xdf\x0a\x2e\x7f\x1f\x83\xdc\x2f\x3e\xd3\x20\x5b\xec\x8e\xfc\xfd\x31\xad\xc1\xac\xa5\x75\x5d\xb9\xbd\x4e\xfe\x54\xcc\x17\x07\x30\x77\xde\x4a\x3f\xdd\x11\x99\x6e\x84\xb6\xa0\x52\xf0\x34\xb4\x10\x99\x22\x6c\x9c\x27\x2e\xae\x12\x52\x8f\x16\x58\x1b\x91\xb8\x12\x85\x0c\x20\x71\x44\xdb\xff\x3e\x85\x0c\xca\x84\x8e\xc2\xb1\xdd\x16\x47\x44\xd7\xb5\x93\x37\xd7\xe3\xef\xef\x00\x81\x62\xe6\x80\xbd\x4a\x08\x99\xce\xd6\x0b\x17\x1f\x8c\xbe\xb4\x8c\x51\x58\xdf\x6c\xbf\xdb\x26\x24\x08\x81\xbd\x58\xeb\xb8\xb6\xa0\x79\x58\x72\x79\x67\x9c\xb5\xad\x82\xf3\x71\xb5\x3c\x80\x13\x80\x4c\x35\x59\x6c\x88\x7e\x43\x6d\x23\x92\x6f\x99\x4e\x09\xd9\x8f\xbb\x8c\xe2\x70\x41\x74\xef\x38\xb6\x82\x62\xa7\xf1\xa7\x12\xda\x0e\xf0\xde\xc6\x39\x60\x68\x14\xb3\xbd\xca\xf2\x53\xff\x31\xc4\x8e\x8a\x75\x2c\x11\x1b\xd7\x10\x10\x31\xcc\x3d\x38\xef\xb0\xc9\xc7\xf1\x9c\x59\x08\x15\x84\xa0\xe0\x15\xee\x7c\x75\xb1\x0a\x4c\x51\xff\x54\x3a\x30\xe5\x2d\x5f\x94\xd8\x18\x8c\x6b\x08\xe9\xdf\x1e\x84\xa4\xe2\xc8\x07\x17\x0a\xc1\x24\xa7\x71\xb9\x94\x65\xa0\xd3\x8b\x1f\x1c\x63\x30\x40\x3c\x82\x54\x35\x82\xc5\xbb\x61\xb2\x20\xde\x1b\x9e\x0e\xf6\x9b\xda\xe2\x60\x23\x18\x1b\xa4\xcc\x07\x7a\x5f\x0d\x42\x57\x32\xac\xe1\x32\xae\x0c\x6f\xf0\xbb\x18\xba\xea\x83\xe8\x87\x7a\xfb\xe6\x50\xfe\x0b\xd0\x20\x93\xf0\x0a\x7b\x53\x65\x72\x8d\xcb\x66\xfb\xb8\x81\xf5\x92\x94\x50\x58\xa5\xb3\x50\x66\x5a\xf9\x1c\x55\x7a\x54\x72\x50\xad\x29\x5e\x68\xb4\xfb\x72\x45\x7c\xfb\x9d\x5e\xa1\xa7\xb2\xa3\x9c\x9a\xb7\xd7\xac\xe0\xaf\x5d\x51\x66\x9c\xb6\xc2\xc4\xc0\x7b\x22\x56\xd1\x0e\x5f\xfc\x6b\x97\xc6\x60\x00\x63\x13\xc4\xeb\x8d"}, -{{0xcb,0xb5,0x87,0x51,0x4e,0x0a,0x34,0xff,0xc3,0x4c,0xbc,0x04,0xf2,0x8c,0x9b,0x4f,0x64,0x65,0xf1,0xeb,0x22,0x5c,0xca,0x19,0xb8,0x64,0x87,0x6d,0xae,0xf3,0x7d,0x7f,},{0x6b,0x70,0x5d,0x46,0x77,0xd2,0xd8,0x49,0xb6,0x74,0x4b,0x1e,0xbe,0xd1,0x67,0xdb,0xcb,0xf6,0x45,0x92,0x4b,0x1f,0xf2,0xe6,0x36,0x07,0x94,0xbd,0xd0,0xe0,0x97,0x88,},{0x12,0x74,0xd6,0xf3,0x56,0xeb,0x64,0x14,0x72,0xb6,0xb9,0xe5,0xb3,0xce,0x65,0xd2,0x65,0x4e,0x6c,0xb8,0x7d,0x3a,0x83,0xfb,0x49,0xd0,0xf7,0xda,0x9c,0x44,0xbe,0x2b,0x53,0x26,0x04,0x46,0x5f,0x60,0x89,0xd6,0x80,0xd2,0xd9,0x4b,0x0e,0xdd,0x2b,0x6b,0x2b,0x80,0x5c,0x5e,0x84,0xc3,0x79,0xef,0xc0,0x59,0x67,0x3d,0x31,0x00,0x7a,0x09,},"\xbd\xf7\xd1\x7c\x70\x67\x96\xef\xd3\x48\x95\x59\xb5\x27\xb1\xc0\x58\x4b\x90\x22\xc9\xcb\xda\x3a\xac\x51\x46\xda\x34\x0d\x9c\xea\x69\xf9\x16\x03\x7c\xd2\x1b\x3e\xb1\x10\x43\x48\x88\x0f\xd5\xc5\xb7\xc6\x5f\xf8\x20\xf7\x49\x93\x46\x01\x69\x51\xcb\x71\x5d\x8d\xf2\xb4\x1c\x88\xcd\x3c\x66\x10\x54\x58\xb7\xb5\x90\xc2\x1c\x1a\xe2\xf6\xea\x9d\xde\xa7\x47\x0f\x25\xe0\x20\x27\xd1\x71\xe0\xe5\x74\xa2\xbb\x21\x64\x2f\x8f\x9d\xa5\x08\xe2\x1d\x8e\x73\x35\xb5\xac\xe5\x93\x52\x99\x40\x7b\xd1\xb0\x1b\xdd\x14\x23\x13\x3e\xf0\x45\x23\x4e\x70\x1f\x55\x54\x94\x34\xad\xe9\x4a\x60\xbe\x1e\x14\x06\xca\x5c\x75\x8c\x36\x79\x9c\xe1\x70\x30\x84\x47\x6e\x48\x4f\xb1\x74\x05\x30\xae\xe8\x42\x66\xd0\x7a\xdf\xb4\xcc\x68\x9f\x32\x65\x13\x3a\x59\xcd\xf9\x92\xfb\xb9\xa4\xb1\x2d\xef\xbe\x24\x1d\xdb\xf6\x5d\x12\xb2\xfb\xdd\xfc\x05\xaf\x0f\xb8\xde\x42\x08\x07\x75\xba\xd2\x9c\x6b\x04\x59\x84\x1c\xbb\x64\x8a\x9a\x95\xe4\x8d\x6e\x36\xac\x51\x44\x80\xa3\xde\xb4\xb3\x65\x54\xd8\xda\x62\x08\x08\xae\x9d\x47\x32\x97\x10\xd2\x0a\xaa\x6e\x5d\x7f\x54\x7d\x81\xad\x30\xf8\x4c\x0e\x3d\x23\x9c\xde\x5b\x16\x9d\x9d\xdf\x29\x48\x32\xd6\x7a\x80\x60\xba\x32\x9c\x4e\xf3\x9b\xe9\x4a\xc4\x64\x34\xdd\x21\x85\x93\x1d\x12\x31\xf9\xb6\xdf\x87\x8a\x5a\xf0\x83\x1e\x0e\x9d\x8a\x08\xd0\x80\x69\xde\xd6\xa9\x61\xef\x7f\x39\xfa\xd5\x01\xff\xd1\x7d\x6d\x9b\x7c\x65\x46\x53\xc1\xf5\x8f\xce\xe1\xa6\xcd\x80\x3d\x2a\xef\x16\x6c\x78\xef\x55\x14\xa3\x27\x6d\x69\x98\xdc\x7c\x09\xa3\xfa\x98\x2e\x42\x7c\x78\x5a\xa6\xa9\xe2\x56\xf7\xba\x72\xd5\xa6\xba\x33\xeb\x46\xf1\xf9\xfe\x9b\xe2\xbf\xc1\x41\x09\xf6\x47\x73\xc0\x0c\x06\x3b\x4d\x5c\xb4\xf4\xf8\xa0\xbe\xca\x92\xa9\xa0\x16\xc4\xf5\x40\xfe\xea\x9c\x3a\x31\xe3\x13\xbb\xcb\xc2\xff\x5e\xca\x99\x67\x85\x7f\x5f\x8a\x90\x9a\x29\xd7\xf2\x0d"}, -{{0x8b,0xde,0x3f,0xf6,0x1a,0x16,0x99,0x5a,0xb9,0xd5,0x39,0xf6,0x05,0x32,0x19,0x08,0x1b,0xca,0xea,0x1d,0x45,0x8e,0xc3,0x36,0x84,0xfc,0x1c,0x01,0xfb,0x56,0x5b,0xfa,},{0xcd,0x9d,0x78,0x2a,0x35,0x6e,0x84,0x7b,0x7a,0x04,0xc8,0x85,0xa9,0xb0,0x90,0x7c,0xc3,0x3b,0xa9,0x7a,0xd5,0x39,0x0d,0x4e,0xa5,0xfe,0xe5,0xeb,0x19,0x8d,0x08,0xb3,},{0x74,0x64,0xdf,0x0b,0x67,0xeb,0x90,0xb4,0xb7,0x3f,0xf0,0x82,0xad,0x0d,0x60,0xeb,0xfe,0x06,0x60,0xda,0xe9,0x70,0x69,0xb5,0x2c,0x37,0x27,0x22,0x3b,0xf7,0x0e,0x29,0xe4,0x87,0x11,0xa2,0xbb,0xb4,0x38,0xf5,0xf8,0xd8,0xa3,0x3b,0xb9,0xc4,0x8f,0xe7,0xb6,0x28,0xfa,0x8a,0x54,0x2f,0xf0,0xb5,0xae,0x36,0x26,0x9d,0x40,0x07,0xa5,0x05,},"\xa1\xf4\x0e\xc5\x80\x7e\x7a\x27\x06\x9a\x43\xb1\xae\xbf\xf5\x83\xef\x03\x70\x28\xc0\x2c\x85\x95\x25\xeb\x8f\xa4\xc3\xba\x95\xa9\x01\xff\x3a\xed\x78\xc4\xf8\x77\x52\xfb\x79\x55\x22\xf5\xbf\x71\x5b\xe7\xe3\xde\xfa\xc1\x0f\xcf\x17\xe3\xfa\x5c\x54\xb2\x00\x89\xa4\x72\x33\x33\x27\x25\x2e\xc9\x45\x71\x8f\xb4\x55\xe3\xf2\x7c\xcf\xde\xf8\x23\xd1\x2d\x40\x6e\x62\xa4\xae\xba\x3c\xb9\xd1\xc6\x1b\x2b\x17\xe4\x9e\x20\x0a\x84\x18\xf9\x35\xf2\x6e\xeb\x57\x60\x2c\x7a\xa3\xb3\xa2\x4f\x7e\x62\x38\xd3\xe0\x8d\x2d\x60\x9f\x2e\xad\xa0\x33\x2b\xc8\xcb\x12\x91\x6c\xb0\x3b\x0d\x4f\x9c\xd6\x02\x00\x25\x86\xd3\xe4\xcc\x7e\x0e\x03\x81\xc0\x45\xad\x2e\x1e\xe2\x82\x98\xae\x7f\xcf\x0c\x10\xf2\x12\x80\x85\x65\x29\x6f\x15\x8d\x2c\x32\xe8\xcb\x28\x15\x65\x81\xaf\x52\xbf\xc3\x47\x0c\x3c\x95\x82\x13\x8d\x22\x55\xe8\x42\x6d\x64\x8c\xa2\x37\xd7\xaa\xd2\x85\x6f\x17\x16\x38\x55\x82\x41\xd8\xae\x3f\x62\xba\x92\xdb\x59\x65\x68\xed\xee\x3e\xc0\xef\x37\x0f\x83\x62\x6a\xa0\x44\x5a\xf0\x8f\x96\x78\x63\x66\x0e\x8f\xba\x5a\x41\xc8\xe8\xed\xe1\xc9\x60\x51\x4a\x14\x68\x7a\x4a\x81\xe7\x76\xae\x0e\x8e\x77\x7f\xb0\xf2\x50\xd5\x1a\x83\xb5\x5f\x8c\x1f\xfd\xd7\x8d\xf3\xbd\xc9\x7f\xf1\x77\xaf\xec\xa0\x46\xc7\x2d\x72\xaf\x92\x4a\xd0\xd0\xab\x2b\xfc\x11\xb7\xf4\xab\xde\xd5\x1c\x39\x87\xa8\xbb\x94\xd6\x40\xc8\x71\x0e\x5f\xc9\xa4\x19\x0e\x8a\x00\x83\x63\xd7\x41\x9c\xea\x17\xc4\x0d\xea\x20\xea\x51\x56\x02\x9f\x3d\xeb\xf0\x52\x41\x91\x8f\x54\xaf\x50\x39\xe2\xc4\xcf\x2c\xa2\xe1\x39\xf6\x0e\x45\xcc\x65\x59\x5c\xdf\x54\xa6\x7d\x92\xb6\xac\x66\xfc\x0c\x5a\x29\x04\x95\xca\x57\xb0\x7e\xf5\x75\x0d\x05\xf5\x7d\x87\xd0\xc2\x28\xf7\xe4\xe1\x5a\xd0\xba\x01\x78\x73\x0f\x95\x1c\x69\x75\x83\x48\x1c\x66\xcb\xfc\xd4\x80\x32\x54\x4a\xa8\xd5\x09\x08\x30\x4b\xd8\x19\x40\x30\x87\x06"}, -{{0xda,0x59,0xbb,0xc5,0x23,0x40,0x4f,0x07,0x64,0x6a,0xdd,0x79,0x08,0x29,0x49,0x77,0xe4,0x66,0x45,0xbc,0x8a,0x38,0xba,0xd2,0x80,0x96,0x41,0xa2,0x3d,0xe3,0xb1,0x5a,},{0xb2,0x2c,0x0f,0x21,0xaa,0x1c,0x2d,0x45,0xf4,0xb2,0xe5,0x6c,0xc9,0xb5,0xe0,0x2f,0x9e,0x31,0xa2,0xea,0xa3,0x67,0xec,0xb4,0x82,0xf8,0x74,0xcb,0xd8,0xe9,0xfe,0x34,},{0x14,0x72,0x45,0x9c,0xbb,0xae,0x2c,0xf2,0x1c,0xe4,0x4a,0x15,0xba,0xe9,0xfc,0x85,0xdc,0xa4,0x0b,0x81,0x82,0xda,0x7d,0x52,0xcb,0xf5,0x6e,0xd5,0x38,0xd1,0x8e,0x03,0x47,0x7c,0x14,0x0a,0x3d,0xdd,0x0e,0xfb,0xa4,0x3c,0x96,0xaa,0x92,0xf5,0xf9,0xbc,0xdf,0x34,0x81,0x28,0x6c,0xe7,0x62,0xa7,0xe2,0xbd,0x1e,0x77,0x9b,0xa9,0x9b,0x0d,},"\x09\x71\x06\xc3\x62\x4d\x77\x4d\xde\x25\x51\xe0\xc2\x7e\x19\x50\x4e\x65\x18\xcc\x86\x36\x9a\xb2\x6f\xf8\x10\x96\x9e\x7d\xe2\x4a\xbc\x68\xb4\xb5\x3f\x11\xd9\x45\xd4\x9e\xf0\x78\xeb\x4f\x6b\xa6\xbf\x25\x7f\xf7\xb6\x08\xaf\xdc\xb3\x0a\x5c\x59\xa7\x56\xfd\x77\xa6\xc1\x24\x7f\x6f\x2a\x41\x10\x0d\x99\xfc\x52\x06\xaf\x3b\xcc\x6d\xe1\xd3\xe4\x96\x8e\x28\xfb\xa0\x12\x3f\x60\x45\xa1\xb5\x4d\x69\x3a\x42\xbd\xfa\x07\x1b\x2b\x91\x4b\x3c\x3c\x0c\x29\xb2\x59\x3d\x07\xe8\xbd\xc8\x6c\xa4\x2a\xc5\x55\xb7\xdc\xd9\x43\x9d\xf9\xfb\xd4\xbb\xec\x73\x0d\x63\x27\xbf\xae\x4f\xc4\x1e\xd4\x98\xb4\xf0\x4a\x0e\xb1\x4c\xee\x60\x82\x83\xaa\xa6\xe6\xaa\x46\x67\x6b\xc8\x8a\xed\x5d\x99\x39\x03\x7a\xad\x49\x15\x66\x1a\xf9\x4b\xb5\xf6\xe6\x53\xa2\xca\xc1\x23\x28\x70\x73\x27\x0e\x0b\x13\xfd\xa1\xdd\x48\x71\xaf\x6a\x92\xf9\x92\xf5\x39\xdf\x88\x17\x12\xfe\xfb\x03\x85\x40\xd4\x11\x91\x12\x3b\x6b\x3b\x4b\x6f\xf8\x7f\xfc\x92\x9a\x6b\xe5\x3c\x6c\xef\x02\xf4\x8f\x2f\x0c\xf2\xfe\x64\xa4\x5f\xd6\x60\x25\xcc\x2d\x7e\xe5\x5e\xbe\x23\x16\xc0\x00\x85\x56\x61\x16\x5e\x2a\x5b\xa4\x1a\xfc\x20\x97\x95\x7b\x6f\xe4\xc5\x52\x21\x20\x4b\x6f\xc1\xf3\x17\xdd\x3b\xa1\x3c\xac\x39\x92\x40\x26\xbd\xb6\x6b\xe4\x54\x22\x68\x87\x56\x31\xd2\x77\xf2\x10\x10\x7a\x33\x76\x7f\x6d\x95\x96\xe2\x57\x42\xd7\xa9\x0e\xa7\x91\xea\x4b\xc9\xee\x84\xa6\x7f\xd3\x28\xb8\x0f\x79\x1e\xde\x96\xd8\x96\x63\xe9\x37\xf0\xb7\x55\xba\xa9\xd5\x2b\xda\x21\x0c\xee\x1d\xb3\x39\xff\x1d\x3c\x4b\x00\x0b\x65\x3b\x9b\xde\x33\x80\x49\xaf\x84\x36\x4e\x21\x77\xf8\x0d\xd5\x1e\x2a\x16\x72\xee\x55\x5d\x63\x17\x58\x9f\x6f\x1d\x5a\xbe\x6c\x28\x77\x35\x8b\xf9\x4b\x0b\x80\x8f\xf8\x57\x36\x3f\xbf\xbe\x32\xe9\x73\x37\xe4\xb8\xa8\xc2\x21\xa9\xe7\x59\x62\xa8\xdc\x9b\x5a\x3d\x7c\xa5\xf9\xc9\xb6\x1c\x73\xc1\x46\x9a\x72\xbd"}, -{{0x40,0xea,0x82,0xda,0x41,0xfd,0x15,0xb0,0x6f,0xfe,0xb9,0x9c,0xd6,0x16,0xdc,0x6b,0xc8,0xc1,0xb2,0x14,0x77,0xea,0x23,0x94,0x66,0x08,0x8e,0x28,0x49,0xbf,0x10,0x16,},{0x59,0x10,0xe5,0x80,0xbf,0x41,0x2c,0x31,0xa8,0x74,0x51,0xd9,0xdd,0xf3,0x2b,0x3a,0xb7,0x13,0xf9,0xe4,0xa2,0x2c,0x59,0x0c,0x64,0x1c,0x14,0xa5,0xdf,0xbb,0xe0,0xd7,},{0xd2,0x98,0xfc,0xc9,0xa8,0xec,0xb7,0x6a,0x98,0xd4,0xa7,0x1d,0xfb,0x01,0xd2,0x76,0xab,0x2d,0x96,0x70,0xa9,0x5b,0xab,0x34,0xcf,0x1d,0x83,0x64,0x51,0x6d,0x1e,0xbd,0xb2,0x39,0x03,0x46,0x02,0x15,0x30,0x71,0x25,0xaf,0xd0,0x9c,0x75,0x8e,0x98,0x1a,0x45,0x2d,0xa9,0x5c,0x0a,0xc2,0xc0,0xb9,0x58,0xc6,0x91,0x7e,0x68,0x74,0x19,0x0d,},"\xa0\x6c\x4e\x02\xb8\x3a\xb7\xe1\x91\xad\x81\x8c\xb8\x18\x7b\x52\xa8\xda\x00\x4f\xe8\x38\xdb\x33\x3c\x4e\x02\x54\x8d\xb6\xbd\xf7\x91\x44\x46\x42\xe5\x7f\xdb\xc8\x59\x4e\x59\xd7\x02\x32\x80\xbb\xae\x82\x98\x6f\x39\x98\x05\x43\x4b\xb0\x72\xc8\xa2\x7a\x2d\xcd\x5a\xa6\x2f\x06\x5b\xc5\x8b\x06\x21\xfc\xd3\x65\xf6\xcd\xbf\x4d\x57\xd5\x77\xd9\x11\x50\x30\x1f\xa4\x8f\x18\x2f\x87\xe8\xdc\xa7\xce\x45\xa7\xd6\x48\x45\xff\x43\x4d\x1b\xab\x05\x34\xcc\xc8\x3a\xa0\x97\x4e\x88\xb3\x8f\xc2\x50\x8c\xef\xcb\xbc\x82\x13\x5b\x73\xb3\x84\xc8\x0e\xcc\xb8\xa0\x9e\x28\x73\xcc\x07\x12\x90\x21\xd8\x1c\xe1\x29\xa9\xdf\x65\xe6\x13\x41\x0a\xf9\x50\x19\x7d\xbf\x9a\xfc\x28\xed\xc4\xe6\x5c\x3e\x84\xda\x40\xd2\xef\x84\x1b\x88\x6b\xc4\x47\x19\xa5\xd5\x9d\xb2\xc6\xdc\x77\x64\x01\xc8\x95\xe2\xb3\xc8\x37\x83\xd7\x81\x7b\xba\x68\xba\xff\x59\x47\x0d\x60\x15\xbb\xa8\xd9\x75\xf0\xeb\x71\x2f\x3b\x89\x02\x91\x28\x05\x52\x3a\xa7\x1c\x90\x49\x9d\xe6\x89\xd3\x1a\xe4\x4e\x21\x0b\x84\x46\xf2\x48\x47\x27\xcc\x49\x1b\x92\xa8\xe8\xb1\x99\xd6\x28\xe1\xdf\x79\xa2\x8c\x56\x1e\x5a\x7d\x88\x2e\x30\x78\x7d\x08\xfb\x2d\x51\x96\xba\x61\x19\x63\x09\xb3\xbf\x0c\x58\x24\xa3\x54\x8c\x70\x00\x03\xfe\x99\x13\xbe\xfe\x12\x22\x31\x50\x01\x26\x85\xe9\x07\x20\xe9\xec\x6b\xc4\xdb\x60\x74\x25\xae\xc5\x31\xc4\xfa\x36\x08\x6d\x3b\x9b\xe3\x91\xa3\xf0\x46\x35\xa8\x07\x7a\x44\x7a\x16\xa6\xfd\x89\xaf\xbb\x9a\x72\xd0\xd3\x55\xcb\x0b\x22\xd5\x62\xf4\x3f\x59\xd4\xe3\x71\x28\xb3\xe2\xd9\x06\xc8\xae\x23\xd0\xaa\x59\x9c\x70\xd3\x77\x8a\x07\x6c\x1a\x39\x72\x8f\x1d\x69\x37\xbd\x48\xb9\x78\x74\x08\x50\x56\x61\x38\xd3\x48\x52\xb6\x30\x75\xe8\x9a\x8e\x22\x80\xed\xba\x6f\x4e\xe8\xf6\x15\x11\xe9\xb7\x68\xe9\x5c\x78\xd1\x97\xb6\x93\xb1\x09\xe8\x88\x18\xb4\x86\xa9\xdf\xdb\x74\xb4\xc5\x55\x0a\xcd\xfb\xd5"}, -{{0x28,0xbb,0x81,0xa1,0x7d,0x45,0x84,0x75,0x4d,0x52,0x81,0x8c,0xd0,0xf1,0xf2,0x1b,0xaa,0x77,0x7e,0x69,0x58,0x44,0xa1,0x51,0x22,0xac,0x05,0x34,0x4d,0xdd,0xc0,0x27,},{0xd5,0xf6,0x1d,0x51,0x99,0x44,0xd1,0x3b,0x84,0xbf,0xa7,0xcd,0x67,0xcb,0x0b,0xea,0x4e,0xf2,0x28,0x1e,0xfa,0x46,0x1f,0x22,0xad,0xe4,0xba,0x88,0x2d,0x11,0xb2,0x52,},{0x9c,0xe4,0x5a,0x07,0xdb,0xd2,0x8d,0x3f,0x6f,0x1b,0x35,0x63,0x0a,0x3f,0xd5,0x6f,0x1d,0x54,0x8f,0x84,0xff,0xb1,0xc6,0xae,0x64,0xb2,0x14,0x98,0xae,0x38,0xe5,0x96,0x91,0x6e,0x77,0xf7,0x99,0x05,0xe6,0x09,0xfb,0x1a,0xe0,0xda,0x36,0x13,0x8a,0x80,0xf2,0x42,0x12,0x21,0x67,0x06,0x80,0x92,0xcc,0x60,0x57,0x96,0xc5,0x66,0x9e,0x06,},"\x92\xe8\x4c\x7a\x55\xb0\xbe\xa0\x3e\x17\xcf\xb6\x5f\x70\x85\xce\x3f\x44\x5b\x15\x42\xba\xe9\x97\xde\x5f\x09\x2a\x24\xff\x24\x33\x80\x28\x6d\x13\x70\x91\xa5\x98\xf3\x5e\x6d\xae\x1a\x1c\x64\x8f\x5a\x49\x4c\x81\x9d\xfb\x24\x06\x52\xff\x90\x83\x81\xf3\x2d\x70\xbc\x51\x31\x00\xac\xa1\x6f\xe7\x22\x02\x95\xb1\xc7\x18\x35\xf1\x6d\x93\x10\xa9\xd2\x7a\x04\xa9\x80\xac\xe2\x97\xd5\xaf\x3f\x7c\xb7\xc7\x8b\x24\x99\x7c\xcb\x41\xf5\x4e\xcb\xab\x50\x7e\xb7\x3e\xa6\xa3\xed\x47\x0e\x49\x59\x05\x09\xf5\xd1\xe6\x03\x2a\x26\x05\xdb\x87\xf4\xa9\xb9\xec\x91\x60\x25\x83\xf1\x4e\x2f\xe1\xbd\xb9\x00\xec\xb8\x97\x11\x96\xb5\x5c\x0d\x43\x34\x89\xf2\x6b\xe9\xca\x15\x7c\xbd\x56\x57\x28\x87\xba\x85\x9f\x39\x67\x4a\x8e\x0c\xa0\x8f\x2d\xbb\x0f\x27\x07\x35\x51\xd0\xb1\x99\x06\x85\x17\x8b\x1a\xe9\xe7\x88\x54\x99\x14\x3d\x9d\x72\xc8\x57\x1d\x11\xe0\xd8\x5b\xf5\x8d\xf9\x4e\x2a\x74\xd9\xb6\x84\x65\x57\xf9\x12\x5c\xa0\x94\x4c\xe5\x71\x8d\x2c\xba\xe1\x67\x2b\xa0\x2b\x84\x7c\x17\xa6\xf6\xb4\x45\x63\x4d\x2f\x01\x75\xa7\x5c\xf6\x88\x3c\x62\xe5\xb5\x21\xc5\x71\x41\xf2\x18\xb2\xfb\x09\x94\xb3\x72\xa7\x16\xc4\xa2\x17\x43\x4b\xea\xb7\x57\x40\xb8\xe9\x1c\x62\x21\x87\xd0\x3c\x85\xda\x00\x1e\x00\x24\x73\x12\xa4\x65\x22\x5f\x5d\x6a\xf2\x32\x06\x4a\x42\x7d\x30\x18\x70\x0d\xed\x77\x4b\x90\x26\x77\x7a\x52\x75\xfc\x04\x75\x46\x06\xc8\x66\x00\x29\x7b\xf7\xb7\x1a\xaf\xf8\xb9\xa7\x46\x67\x7a\x36\x62\xf3\x75\x0e\x81\xb5\x01\x66\xf6\x23\x70\x00\x05\x1f\xfa\x15\x86\x8d\xef\xdf\x09\x00\x57\x72\x2a\xe2\x29\x96\x4a\x4e\xa0\x85\xe0\xdb\xc0\x4c\xe1\x99\x77\x22\xc5\xbb\x65\xd2\xb4\x7e\xcb\x74\x6f\xd8\x3a\x9f\x6a\x69\xc8\x15\x45\xa9\xb5\x02\xf5\xe7\x6d\x31\x30\xc5\xaf\xcb\x1c\x9a\xf9\x9d\x91\x87\x40\x83\x7c\xe8\x9d\x7c\xd2\x13\xfe\xf2\xfd\x06\x2c\xe8\x85\x0f\x69\x65\x9e\x4a\xd3\x27"}, -{{0x24,0xbf,0xd4,0xfc,0x45,0xd5,0x09,0x35,0x85,0x67,0x81,0x01,0xcf,0x56,0x3a,0xb8,0x01,0x1f,0xd6,0x43,0x0d,0xe1,0x55,0xf2,0xa4,0x25,0xf0,0x63,0x3e,0xe3,0xb7,0xcd,},{0x9c,0xf5,0xc5,0xfc,0x0c,0xcf,0xae,0xb2,0x8a,0x08,0xba,0x67,0x70,0x7b,0x18,0xdc,0x84,0xea,0x06,0x98,0xff,0xbd,0xbc,0x16,0x9a,0x09,0xc2,0x81,0x23,0xe6,0xc2,0xac,},{0xdc,0x93,0x5b,0x60,0xfd,0xe4,0x43,0x59,0xaf,0x8f,0x50,0xed,0x7f,0x91,0x9f,0x48,0x3c,0xe3,0xf2,0x4e,0x23,0x20,0xc5,0x5b,0xa9,0x2f,0x3e,0x76,0x17,0xc1,0x9b,0xfb,0x54,0x70,0x19,0x03,0xff,0x18,0x3b,0x42,0xcb,0xed,0xfe,0xf0,0x87,0x5f,0x42,0xb1,0x28,0x75,0xd3,0x6a,0x0a,0xee,0xc7,0x3f,0xfd,0x09,0x50,0x9d,0x92,0xb2,0x8b,0x0d,},"\xba\x54\x12\x8f\x45\xbe\x20\x01\xdb\xb0\x60\xd5\xdc\xc4\x71\x44\x99\x74\x15\xd4\x29\x4f\x6e\xba\x8d\xce\xba\x4f\x6c\xf2\x23\x46\x83\xc4\x26\x5f\x88\x03\x22\x05\x29\x6e\x9b\x27\xd6\x85\x06\x23\x2d\x57\xb6\x88\x40\x76\x48\xf8\x7c\xeb\x34\x20\x52\xbd\xe9\xd0\x06\x55\x42\xff\x17\x15\xc9\x42\x02\x7e\x67\x48\x2a\xf4\xbc\x27\x8f\xf7\x19\x66\xfb\x3f\x62\xa2\xa5\x32\x3c\xb1\xb4\xba\xe1\xe7\xb8\xfe\xdc\xbc\x73\xea\x05\xb4\x07\x64\x21\xb0\xb4\xfa\xe8\xbc\x33\x37\x41\x6a\x17\xfe\x12\x4e\x7e\xe4\x65\xeb\xb3\x8d\x87\x92\x30\x64\x29\xd8\x27\x9a\x1b\xd5\x4c\x37\xbe\xe8\xf9\xc8\x5e\xeb\xe3\xaf\xd1\xf6\x44\x89\xd4\xe5\x3a\xc5\xf5\x06\x57\xbb\x6f\xfb\x97\x12\x07\x44\xb7\x5d\x47\xc6\x22\x6d\x5a\x9c\x9c\x26\x4e\xe3\xe6\xa6\xde\xd0\x50\x62\xca\x10\x06\x66\x91\x18\x45\x45\x50\x01\x09\x19\xc2\x63\x3c\xf0\x86\x95\x03\x45\xe5\x14\xaf\x38\x43\x14\x8e\x5c\x64\x35\x2e\x69\x03\x7d\xfe\x60\xd4\xa8\xea\xb3\xeb\x8c\xb5\x4b\xd3\x9a\xf2\xf3\x53\xd5\xde\xd2\xe2\xbc\x8b\x11\xc0\x9f\x61\x2e\x12\x8c\x6e\xfa\x41\xf6\xeb\x2c\x95\x80\x87\xbe\x34\xc6\x33\x5a\x43\x00\x5d\x11\xa9\xd3\xb5\xa5\x29\xc2\xd1\xb0\x64\x2f\x77\xaf\xdd\x8c\x6b\x1d\x6f\xb2\xa9\xdc\xb6\x5f\x42\xf4\xec\xa8\xea\x9a\x05\x40\x58\xbe\x86\x13\x66\x76\x10\xe3\xee\xd8\xd1\xdf\x07\x39\xec\xa1\x71\x95\x41\x17\x98\x9d\x1b\x12\x18\x9a\xb5\x79\x04\xaa\x96\x0b\x0c\xa8\x55\x41\x74\x63\x85\xef\xa9\x85\xbe\x9d\x97\xb5\xa9\x02\x99\x89\xa9\xc7\x14\x98\xdf\xab\xdb\x81\x36\x81\xf5\x7e\x27\x6b\x64\xdb\x49\x1b\x8f\x08\x2a\x88\x51\x45\x46\x9a\x53\x1b\x7f\x9f\x04\xca\x0a\x2c\x2f\x8d\xff\x20\xcc\xb9\x9c\x28\x61\xf5\x4e\x5e\xaf\xa9\x62\xcc\x53\xea\xf1\x8d\x3d\x5e\x50\xd3\x37\xaf\x48\x5f\x19\x97\x5f\x05\x93\x07\x00\xa8\xa7\x25\x3f\x11\xf1\x84\x13\x0d\x0a\xee\x70\x96\x9d\x96\xfe\x08\xf2\x16\x95\x1d\x9d\xce\xd5\x23\x88"}, -{{0x2f,0xc2,0xf9,0xb2,0x05,0x0a,0xd7,0xd1,0x39,0x27,0x3e,0x93,0xe2,0xa0,0x45,0x1c,0x7b,0x5c,0xce,0x57,0x59,0x9a,0xa6,0xb0,0x8d,0x3e,0xdc,0x5b,0xb0,0x75,0x90,0xc8,},{0xff,0xe5,0xa1,0x78,0x80,0xd7,0x18,0xcc,0x79,0x88,0xc2,0xfd,0x98,0x25,0xb0,0x3b,0x93,0x45,0x0a,0xc1,0xde,0xb8,0xfb,0xd1,0xf1,0xbf,0x3b,0x8f,0x87,0x80,0x59,0x54,},{0x7a,0xff,0x16,0x2a,0x3c,0x0d,0x28,0xdf,0xf4,0x17,0x15,0xa9,0x74,0xaf,0x07,0xec,0xac,0x21,0x32,0xfc,0x18,0xbc,0x43,0xa1,0x98,0xfe,0x66,0x46,0x59,0x05,0x0d,0xa1,0x9a,0xe2,0x27,0x58,0xd5,0x2c,0x9c,0xbb,0x94,0xf1,0x35,0x8b,0xb0,0x26,0x10,0xa8,0xa3,0x51,0xc2,0x11,0x62,0x79,0xe7,0x24,0x5a,0xdf,0x69,0x67,0x5d,0xfd,0x36,0x0a,},"\xdc\x12\x97\x99\x0c\xc0\x27\xd5\x6d\x1f\xee\x26\x5c\x09\xbc\xf2\x07\xa9\x58\x3e\x6b\xab\x8d\x32\x47\x82\x28\xe0\xbc\x30\x5b\x98\x18\x15\x4c\x33\x8c\xee\xc3\x4b\x04\xc4\xad\xe7\xac\x61\xdc\xb0\x9b\xfa\xc8\xad\xe0\x0d\x1f\x29\xde\x31\x70\x60\xb8\xa4\xda\xf1\x98\x7d\xe4\x09\xca\x2c\x3f\xe4\x38\x00\x88\x07\x3c\xcf\x48\x5e\x9a\x69\x51\x6b\x5b\xbb\x41\x30\xf2\x0b\xe6\x9b\x2d\xd6\xa9\xb4\x65\x15\x9c\xca\x1a\xc8\x8b\x32\x8b\x80\xc5\x1b\x66\xaf\x7f\x4c\x50\xf6\x22\x87\x72\xf2\x87\x34\x69\x3c\xe4\x80\x5a\x41\x63\xdf\xf1\x4b\x4d\x03\x98\x11\xee\x3f\xce\x65\x93\x54\x44\xa6\xea\x9a\x72\xd7\x8b\x91\x5c\x9c\x3b\x76\x6c\x60\xb7\xe0\x32\x9e\x43\xc9\xc5\x7e\xde\x94\xb9\x15\x25\xce\x5a\x07\x5a\x72\x97\x21\x97\x72\xef\x3c\x02\x96\x49\xb5\x86\xa9\x5a\x73\xbb\xdf\x16\xd8\xfc\x20\x36\x8d\xe4\xba\x44\xde\x10\x64\xbe\x58\x26\xb3\x76\xbe\x31\xa8\x6c\xa4\x78\xa5\x2e\xfb\x98\xf1\xfa\x33\x31\x57\x71\x9b\xd6\xe0\xda\x80\xed\x68\xd0\xef\xea\xfe\xe5\xa1\x3b\xcc\x3b\x45\x75\x25\x25\x8f\x1f\x7e\x03\x1f\x7b\x40\x3a\x46\x15\x06\x92\x7b\x1e\x6c\x7d\x4a\x0c\x8d\x84\xb5\xf3\xdd\x0e\xb8\xbd\xb1\x3e\xdc\x2b\x51\x4a\x81\xd0\x88\xeb\x07\x7a\x52\xc8\xa8\x31\x86\x1f\xee\xe8\x11\x0e\x41\xa3\x25\xdc\xe2\x06\xb2\xd6\x7d\x25\xf9\x0e\xf5\x7e\x0f\xde\x70\x9f\x3e\x5a\x39\xc0\x4e\xed\x31\xe5\x7c\x19\x3b\x28\x3e\x2d\xa7\x27\x9e\xe3\xf1\xee\xd4\x82\xb3\xbb\xcd\x37\x39\x02\xc1\xdf\x81\x1a\xc3\x3e\x1d\xe0\x64\x29\xe8\xf8\x44\x3f\x60\x20\x19\x65\x0b\xdc\x2e\xe8\xd7\xf6\x50\x03\x6a\x7a\x22\xb8\xfd\x88\x51\x75\x11\x22\x9c\x72\x9a\x32\x69\xb3\xa3\xe8\xfc\x72\xb0\x1b\x5a\x4b\x3e\x33\xf5\x27\x2f\x3a\xd2\x16\x29\xd0\x8b\x1f\x71\x79\x35\xe9\xe1\x04\xad\xd2\xf0\xf2\x03\x34\x32\xbe\xc8\x2e\x21\x21\xd9\x8c\x9c\x1a\x58\xe0\xda\xba\x25\x53\x6a\x1b\xe8\xe5\x08\x83\x47\xf4\xa1\x4e\x48\xd8\xe3"}, -{{0x8a,0xfe,0x33,0xa0,0xc0,0x8a,0xa3,0x48,0x7a,0x97,0xdf,0x9f,0x01,0xf0,0x5b,0x23,0x27,0x7d,0xf0,0xbb,0x7e,0x4c,0xe3,0x95,0x22,0xae,0xc3,0xd1,0x78,0x16,0xe4,0x67,},{0xd0,0x04,0x37,0x0e,0x6e,0xdc,0x34,0xb3,0xe8,0x81,0x86,0x67,0x21,0x6f,0x5b,0x22,0x6b,0x0f,0xf7,0x5a,0x58,0x48,0x4c,0x86,0x16,0xe1,0xa8,0x66,0x44,0x4c,0xab,0x57,},{0x63,0xa8,0xae,0xac,0x02,0x5f,0x2d,0xde,0x9a,0x73,0x28,0x6e,0x56,0xc2,0xd6,0x2d,0xcb,0x79,0xa2,0x41,0xba,0x0b,0x2e,0x2d,0xba,0xca,0x87,0x52,0xed,0x2f,0xc8,0xcc,0x7a,0xb8,0xe6,0x60,0x0b,0x67,0x64,0x5f,0xb5,0xe8,0x18,0xa4,0xe8,0x2c,0x29,0x18,0x0a,0x6b,0x2c,0x3f,0x58,0xd0,0x99,0xcb,0x63,0x5c,0xe5,0x2b,0xdc,0x15,0x70,0x04,},"\x86\xfb\x74\x1f\x1b\x97\x08\x92\x91\x95\x03\x1a\xa1\x64\x5f\xb7\x09\xa8\xae\x32\x3f\xff\x85\xe5\x47\x01\x94\x45\x2e\x11\xb7\xb1\x27\x91\x94\xb5\xe2\x42\x7c\xe2\x3e\x1d\x74\x9c\x3d\xdf\x91\x0b\x01\x7e\x4f\x2d\xff\x86\xdb\xe4\x82\xc9\x1b\xd9\x94\xe8\x49\x3f\x2e\x68\x24\xbb\xa3\xbc\x7d\x7a\x84\x5f\x21\x7a\xe9\x76\x0b\x3c\xd0\x02\x26\xd9\xff\x26\x16\xd4\x52\x75\x1a\x90\xc3\xd0\xd3\xc3\x6d\x4a\xb4\xb2\x52\x0f\x67\x28\x81\x71\xbd\x3a\x34\xb2\xea\xca\xe8\xd4\x4c\x1e\x15\x3d\xda\x1f\x90\xbc\xd3\x59\x5d\xad\x37\x71\x3b\x8d\x34\x01\x56\xea\x90\xa4\xe1\x35\x95\x1b\xa7\x16\x9a\xc1\x75\x57\x8b\x81\xe9\x7a\x54\x1a\xb9\xbf\xb7\x63\x28\x79\x8d\x7d\x63\x1c\x14\xdf\x2a\xd6\x13\xe9\xc6\xe1\x14\x7a\x0e\x84\x06\x2d\xdb\xa0\x35\x85\x9d\x46\xba\xde\x5f\xad\xd9\xb3\x2b\x43\xda\xd4\x83\xc6\xb8\x02\x3b\x32\x39\x1e\x51\xef\x15\x20\xc6\x8c\x61\x91\x32\x6c\x49\x44\x23\x08\x0c\x62\x3d\xc4\xad\x0a\xa0\x74\x74\x8d\x82\x6c\x29\x64\x4c\x38\x98\x6a\x77\x00\x2f\x0c\xab\x90\x68\xe6\xc9\xec\x73\xcc\x2e\x0c\x58\x4b\x80\xe0\xbc\x37\x57\x21\xf7\xa8\xfc\x35\x31\x7a\x5e\x24\x0e\x8c\x66\x09\x2f\xb6\x30\x5b\x01\x2c\x70\xe1\x7a\xea\xff\x13\x38\x6d\x5e\x28\xd0\x64\x30\xca\x58\x5b\x0c\x85\xb2\x74\xe7\xfc\xbb\x63\xe3\x42\x3a\x98\x25\x79\xe5\xa6\x4a\x02\x62\xc4\x19\x08\xe5\x5d\xbe\x43\xda\xc1\xe5\xcc\x1b\xb7\x29\x8b\xe4\x28\x72\x0a\x12\xe3\xb0\x72\x55\x9e\xc2\x67\x5d\x45\x7a\xaf\x8f\x13\x25\x2e\x28\xaa\xd6\x3c\x15\x13\xf5\xf2\x39\x56\x4d\x36\x3c\x85\x05\xff\xa4\xe5\x0f\x66\x48\xc1\xcb\x82\xbb\xa8\x52\xbf\xf0\xac\xb0\x30\xcb\xe7\x3f\x05\x9d\xd8\x7b\xbd\x73\x18\xc5\x58\x6e\x70\x86\x18\xa4\xf4\xc9\xf3\xbe\xc3\xf4\xf0\x7c\x60\x9e\xeb\xb2\x4b\xa8\x78\xc6\xbf\x1e\x4f\x2d\x0f\xd1\x45\x0a\xb9\x4e\x31\x75\x52\x17\x78\x6f\xb1\x51\x82\x76\x0f\xfb\xe5\xa2\x67\xcb\xe9\x98\xa4\xff\x90\xa2"}, -{{0x6d,0xc7,0xcc,0xf3,0x29,0x37,0x8e,0x81,0x31,0xb6,0xde,0xfc,0xd8,0x93,0x70,0x30,0x10,0x68,0x94,0x63,0x36,0xb0,0xb7,0x62,0xac,0x5e,0xa5,0x14,0x87,0xdb,0xd3,0x9e,},{0x04,0xe9,0x0d,0x27,0x5e,0x79,0xdf,0x5f,0x2b,0x6e,0xf4,0xa3,0x15,0x05,0xaa,0xc0,0x5a,0x69,0x45,0x9b,0xaf,0x2c,0x58,0x1b,0x3c,0xe3,0xdb,0x29,0xf0,0xf1,0xfc,0x14,},{0x04,0x50,0x9d,0xb0,0x03,0xa1,0xa6,0xed,0x3f,0xbc,0xec,0x21,0xac,0x44,0xec,0x10,0xcc,0x06,0xd7,0x9f,0x27,0x14,0x96,0x08,0x82,0x17,0x03,0x16,0x27,0x5d,0xf8,0x04,0x23,0xa1,0xc1,0xa1,0x12,0xd8,0x81,0xfc,0x24,0xd2,0x81,0x25,0x26,0x07,0x90,0x58,0xaa,0x8b,0x60,0x8b,0xfc,0x6b,0x5e,0x57,0x63,0x22,0x40,0xc6,0x36,0xd6,0xeb,0x00,},"\x20\xce\xbb\xe9\x84\x01\xac\x89\x34\xc3\xe6\x5a\x57\x38\xcb\x0e\xc0\xcd\xc7\x5f\xdb\x09\xdc\x96\x31\x28\x94\xb1\x87\xc0\xa4\x6d\x2c\x38\xf4\x85\x5b\xe3\xee\xcc\xdc\xdc\xc5\x6d\x92\x6a\x8c\x08\xce\x6e\x74\x8e\x2a\x85\x8f\x53\x53\x2e\x7e\x5f\xc5\xf7\x01\x4c\x8c\x6f\x86\x31\x0c\xc2\x6e\xfe\xf3\x0a\xe5\x25\xa5\x15\x79\x40\xab\x53\x5e\xd8\xe4\x03\x11\x2b\x08\xe3\x5e\x2b\xb3\xdd\x91\xa9\xae\x8f\x77\x2d\x2a\xff\x37\xd8\xc4\x0d\x2b\x5c\xc8\x87\xa6\xf1\x50\x50\xa0\xf5\xbc\xf0\x36\x0c\x3a\x9d\x12\xd5\x91\x86\x55\xed\xc3\xc1\x3c\x86\xba\x6f\x4a\x2f\xa3\xbf\xcd\x40\x5e\xd3\x8f\x87\x1c\xf7\xdf\xf0\xf7\x5d\xaf\x2c\x32\x10\x84\xee\x9f\xa8\x12\x11\xad\xb1\x05\xb2\x5c\x22\x88\xf0\xf2\xf7\xf9\x3e\xf6\x56\xb2\xde\x19\x01\x22\xe7\xa4\xbf\xd4\xa1\xbd\x98\x93\xa8\x48\x5b\x50\x9f\xf0\xbc\x46\xcc\x96\x10\x51\xc1\xdb\x5a\x12\x49\x0c\x7e\x74\x19\x22\xcc\xc0\xa6\x65\x49\x64\x70\x27\x6f\x69\xc7\xb7\x70\x98\xc1\xe6\x70\xaf\x6b\x9f\x85\x12\x52\x99\x68\x75\xeb\x80\x35\xa8\x17\xfa\x9b\xe0\x7f\x2b\xe0\xbb\xb1\x20\x25\xe0\x56\x54\x14\xc8\x17\xe9\x42\x1a\xc7\x00\x37\x38\x93\x86\x2f\x24\xcb\x16\x5f\x9a\x27\x1a\x64\xfd\x23\x05\xc6\x67\x2c\x46\x76\x7f\x8f\x07\x5b\xe5\xd2\xd4\x07\x9b\xfa\xdc\x39\x56\x28\x8b\x02\x15\x60\x53\x11\xb5\xbf\x32\xf0\x03\x7b\x7c\x5a\xd5\x02\x01\x3e\x82\xae\x34\x19\xd9\xd8\xf3\x9c\x54\x5b\x58\x88\xf4\x71\x06\xc9\x4d\x5f\xd6\x08\x4d\x26\x03\x4a\x99\xf5\xdc\xbf\x26\xa8\x4e\xb4\xee\x14\x9c\x62\xa0\x41\x0d\x8c\x70\x7b\x1a\x9b\x07\x1f\x74\xed\x23\x93\x25\x85\x07\x2c\xe6\xcb\xd3\x3d\x4d\x54\xee\x91\x79\x16\xf5\xdf\xc6\x4d\x26\xa4\x98\x01\x84\x38\xb4\x55\x73\x93\x45\xdd\x60\xae\x0f\x47\x50\x62\x59\x15\xcc\x82\x9a\xb6\x82\x2d\x6f\x05\xf6\xd2\xbd\xa0\xa7\xbf\x56\x01\xe9\xa2\xed\x6d\xe9\x60\x37\x1d\x17\xe6\xf4\x37\x09\xc9\x67\x8c\xa7\x43\xad\xfb\xdb\x45"}, -{{0xcc,0xae,0x07,0xd2,0xa0,0x21,0xfe,0x3e,0x6e,0xe2,0x38,0x36,0xa7,0x11,0xb9,0x7b,0x04,0xe0,0xa4,0x41,0xf1,0x69,0x60,0x75,0x72,0x73,0x1c,0xb0,0x8c,0x26,0x94,0x88,},{0xa3,0x22,0x65,0xe5,0x32,0x8a,0x4f,0x49,0xcf,0x06,0xb4,0x67,0xa9,0x8b,0x9f,0x9d,0x5b,0x99,0x7b,0x85,0xdf,0xb7,0x52,0x3c,0xa6,0xa0,0xa1,0xd6,0x27,0xd3,0x28,0x91,},{0x0e,0xec,0x75,0x41,0x05,0x44,0x7f,0x97,0xd4,0xa9,0xcd,0x24,0x6c,0x7e,0xed,0xe3,0xfd,0x06,0x90,0x18,0xf0,0xd0,0x1a,0x41,0xdf,0xab,0xca,0x3e,0x90,0xa7,0x41,0x83,0x5e,0xa4,0xa9,0xd6,0x82,0x34,0x22,0x67,0xb2,0x50,0xfc,0x1c,0x8c,0x54,0x7c,0x89,0x63,0x2d,0x9f,0x68,0x9a,0xf5,0x36,0xc7,0x92,0x90,0x04,0xde,0xd0,0xd9,0x6f,0x09,},"\xa4\xbf\x82\x97\xd0\xdc\x5e\x4c\x92\xbd\x00\xad\x5b\x9c\x09\xb1\x23\x8b\x50\x3d\x61\x91\x16\xef\x74\x26\x03\x78\x34\x9a\x92\x82\xb4\x1f\x3f\x46\x76\xa6\x21\x5e\x3c\xe6\xd0\x22\x38\x48\x0a\x96\x04\x3b\x29\x42\xb3\xfe\xed\x12\x62\x0b\x1f\xa9\x7f\x77\x03\xb3\xeb\x68\x3c\x16\x01\xbd\x2f\x51\x82\x5c\x45\x0d\xf4\xfd\x1f\x33\xb0\xbf\x9c\x23\xc0\x32\x23\x78\x9e\x06\xe2\x4c\xf1\x36\xd3\xb5\x57\x40\x3a\x66\x98\x1f\x4b\x77\x7d\xcf\xe8\x90\xd2\xba\x96\xda\x4a\x47\x42\xae\xed\xdd\x6a\x61\x1d\x05\xfc\x21\x56\x94\xa5\xd8\x9a\x5d\xe6\x76\x0b\x1d\x94\x15\x15\x50\x44\xc0\x49\xcb\x02\x29\x1a\x15\x14\xfa\xa2\xe7\x7d\x2a\xe3\x3d\x44\x58\x5b\xda\xc6\x36\x5b\xf4\x81\xd9\xc9\x78\x33\x93\x7e\xab\x63\x6e\xd6\x57\x42\xa0\xd5\x97\x3b\x24\xd5\x40\x89\xb2\xda\xf0\x84\xd5\x41\x47\x65\x10\x5e\x4e\xca\x14\xaa\xad\xd1\x05\x33\x38\xa8\x47\x05\x05\x23\x2e\x4a\xc6\x33\x34\x5c\x5c\xde\xe1\xe4\x65\x3d\x1d\x93\x58\x3a\xf1\x18\x54\xb1\xd9\xb6\x5f\xc2\x02\x81\x83\x8c\x56\xdf\x11\x48\xf3\x5c\xcf\x9b\xfe\x2f\x3f\x80\xab\x73\xf5\xb7\x91\xcb\xed\x2d\x92\x06\x44\xcf\x03\x16\xf0\xcb\x5d\x36\x62\xb9\x12\x06\x47\xda\x56\xaf\xbe\xb4\x7a\x95\x29\x53\xbc\x1a\x37\xde\x85\x7e\x4b\x39\xfd\x92\xb6\x32\xb8\x51\x59\xf4\x6c\xd0\x5b\x6a\xbc\x23\x38\xd4\x63\x2d\x48\xe9\xa1\x78\x86\x0d\xe8\xf6\x5d\x9b\xc2\x3f\x24\x50\x7b\x7c\x56\x29\xe0\xbd\xaa\xc0\x67\xc4\x76\xc9\xc3\x94\x1d\x86\xf7\x88\x94\x4d\x74\x48\x52\xa6\x1d\xa7\x16\xf9\x5f\x3b\x04\xf0\x78\x3a\x56\x29\x41\xbc\xdd\xa4\x39\x59\x0f\xd1\x86\xb2\xa8\xeb\xf1\x9a\x5a\x7e\x4f\x4a\x3a\xaa\xb7\xa8\x7a\x43\x45\x24\xfb\xc9\x79\x9c\x99\x31\xeb\x8c\xe4\xe3\x4e\x99\xb6\x08\xca\xc9\x4a\xb7\xe7\x44\x95\x66\x8d\xf1\x36\x18\x5f\x48\x7d\x9f\xbc\xb6\x60\x5a\xd7\x25\x34\x54\x03\xec\x57\xf3\xf6\xdb\x36\x4a\x87\xf3\x8f\xea\x4b\x4c\x27\x15\x52\xe9\xf2\xe4\xa1\xbe"}, -{{0xdb,0x5d,0x5f,0x41,0xfd,0xdd,0x67,0x68,0x70,0x97,0x47,0xab,0x82,0x39,0xbb,0x4f,0x42,0xa3,0x1d,0x34,0xb4,0xfa,0x88,0x82,0x4d,0x94,0xbf,0x78,0xd3,0x14,0x92,0x64,},{0x03,0x85,0x8c,0xe6,0xb2,0xd2,0x40,0x79,0xee,0xad,0x66,0xca,0x0d,0xfe,0x77,0x2e,0xcd,0xa9,0xaf,0x4d,0x46,0xbc,0x9b,0x5e,0xdf,0xdc,0x28,0x6b,0x95,0xfe,0x97,0x16,},{0x5b,0x3d,0x0d,0xa7,0x10,0x23,0x55,0x48,0x6b,0xe4,0xd6,0x9c,0xfd,0x65,0x88,0x6c,0x9d,0x9c,0x87,0x38,0xb2,0x93,0xca,0xfb,0x23,0xb2,0x10,0x4b,0xfd,0xac,0x8d,0x7d,0x01,0x29,0x8e,0xeb,0x18,0xfd,0xe3,0xde,0xd6,0x49,0x1d,0x41,0xb4,0x19,0xcc,0x66,0x37,0x52,0xc4,0xe6,0x7d,0xbe,0x89,0x86,0x83,0x3d,0x20,0xe4,0xef,0x34,0x18,0x0b,},"\x67\xee\x03\xde\x45\xc3\xe7\x03\x0d\xb5\x24\x6e\xe5\xb5\x1b\xf2\x98\xbb\xa3\xe4\xd0\x93\x49\x37\xfc\x12\xd9\xa6\x29\x60\x4c\x53\xc0\x70\xe3\x0d\x61\x19\x99\xa9\xcd\xda\xf2\xd9\xac\xda\x6a\x9f\x67\x20\x2b\x35\x23\x69\xd4\x82\x60\xee\xbc\xe0\xe7\x8e\x4d\x5a\xe5\x4f\x67\x75\x21\xf8\x4a\x7b\xe0\x01\x7f\xab\x27\x8b\x2b\x57\x27\x5e\xfc\x5f\xa5\x7c\x61\x71\x86\xfc\x1b\xa4\x9e\xdf\xbd\x33\x08\x63\x48\x78\xd8\x64\xf2\xda\x15\x83\xca\x8d\x56\xce\x9f\xae\x77\xc4\x62\x03\x9a\xbc\x32\xd0\x53\x9c\x0a\x60\xb7\xbb\xba\x50\x29\xe9\x32\x9d\x27\x56\x83\xd9\xc4\xce\x77\xd0\xb9\x08\xad\xe9\x8b\x0e\x32\xb4\x42\x0d\x9a\xee\x2c\xc1\x0e\x4b\xe9\x22\xf9\x57\x25\x82\xdd\x89\x67\x14\x1c\x1d\x40\x2e\x21\x5f\x20\xae\xe0\xa8\x90\xe2\x36\x8e\x40\x6d\xea\x11\xbd\x11\x17\x7f\x2e\x03\x8a\xa2\xf1\xa0\xdf\xf5\x1a\x12\x8d\x95\x5d\x5e\x5f\x8d\x5d\x00\x09\xaa\xa8\x24\x40\xa9\x68\x64\xd6\xc6\x97\xf9\x10\xd1\xdf\x23\x0f\x46\x7f\x0e\x02\xa2\xe0\x2b\xf9\xe4\x5d\xa9\x5f\x25\x54\x10\xcc\x5a\xab\x8d\x85\xf4\x49\xa5\xde\x99\xaa\xbd\x44\xfd\x76\x3e\xc1\x46\x29\xf3\xdb\xab\x1a\x24\x7b\xff\xb7\x17\x46\x48\xe4\x3b\x9f\xb1\xeb\x0d\xf5\xe4\x10\x9b\x7a\x88\xe0\x55\x12\xb2\x08\x65\xba\xd3\x9f\x9e\xa7\x9d\x52\xf5\x18\x8e\x7c\xa5\x19\x44\x05\xbf\xb1\xa0\x97\x27\x61\x7f\x3f\x6c\x88\x19\x20\x08\xed\xbc\x0c\x65\x85\xdb\xf2\x61\xf1\x49\xdf\xfb\x59\x3d\x42\x71\x6e\x5a\x57\x77\xf5\x46\x2b\xee\xb1\xe9\xa5\x6a\x2c\x76\xe6\xcb\x73\x51\x17\xcc\x11\x83\xa3\x8d\x1e\x00\xb3\x03\xd1\x74\xaa\x9c\xf5\xc7\x31\xb2\xc7\x0e\xdd\x79\xcc\x5d\xc9\x6f\x40\x18\xf1\xd7\x1d\x71\x98\xbb\xb7\xd1\x34\xcd\x2f\xf8\xc1\x5f\x9a\x04\x28\x0d\xb2\x6a\x8f\xa9\x99\x7e\xb8\x6b\x13\x3c\x02\x2e\xda\x15\xd8\xad\x5e\x77\xcc\x9f\x62\x61\x59\x60\xba\xc2\xf9\xbb\xc3\xeb\xbd\x19\x8f\x72\xc5\x72\xb9\x71\x56\xfa\x7f\xa2\x29\xa9\x80\x14\xe1\x70"}, -{{0x7f,0x04,0x8d,0xfc,0xc2,0x65,0x0c,0xda,0x59,0x49,0x1d,0x4c,0xe2,0xb2,0x53,0x3a,0xec,0xc8,0x9c,0xc4,0xb3,0x36,0x88,0x51,0x94,0xb7,0xad,0x91,0x7d,0xb5,0xcd,0x14,},{0x08,0x00,0x1b,0x5d,0x40,0x95,0x8b,0xcb,0x27,0x0b,0xee,0xa9,0xba,0xba,0x33,0x87,0xe3,0xa4,0xb9,0x00,0xfc,0x42,0x27,0x56,0x57,0xc6,0xc6,0x91,0xa2,0xe2,0x64,0xf2,},{0x58,0x33,0x70,0x97,0x1d,0x24,0x65,0x2a,0xd2,0x13,0xc4,0x26,0x15,0x91,0x19,0x38,0xfa,0x9a,0xa3,0xd9,0xb7,0x19,0x69,0x40,0xe6,0xeb,0x08,0x15,0x12,0x00,0xc7,0xb6,0x72,0x9d,0x1e,0xff,0x8f,0x4f,0x09,0x04,0x07,0x4d,0xab,0x3d,0xdd,0xa6,0xaf,0x1e,0x4e,0x56,0x2b,0x7d,0x62,0x20,0xc1,0xa5,0x62,0x68,0x3b,0xea,0xb2,0x68,0xf8,0x0e,},"\x91\x75\x19\xcd\xb3\x35\x19\x68\x0b\xca\xe0\x4f\xaa\x79\x07\x71\xce\x7d\x13\x97\xc3\x45\xf1\xb0\x3d\xd7\x62\x57\x76\xf3\xf1\x95\x80\x99\x32\x61\x8b\x1c\x64\xac\xd9\x3a\xd0\x00\xea\xd0\x96\x54\xa3\x3d\x14\xf7\x48\xb4\x6b\x67\xaa\xe0\xff\x12\xdf\x3c\xc1\x63\x28\x0f\x47\xce\xdc\x16\xa8\x57\x90\x34\xe4\x98\x84\x29\x67\x72\xec\xbd\xbb\x71\xca\x29\xc1\x66\x23\x35\x33\xc8\xde\x54\x01\x2b\x41\x2c\xa1\x3c\xc2\x58\xf7\xc5\x46\x5d\x83\x42\x2f\x52\x4e\x4c\x05\xf8\x06\x31\x34\x78\x31\x9f\xd1\x43\xcf\x50\x88\xe6\x98\x37\x69\x7d\x36\x15\xd8\x0a\x7f\xa7\xe7\x44\x3f\xca\x65\xe7\x53\xac\x1b\x11\xd8\xef\xf3\x47\x66\x36\xae\x02\xd7\xa2\x0f\x4b\x23\x88\xda\xd6\x84\x00\x2f\x5c\xe9\x57\xca\xdd\xd2\x05\x3d\x0e\xd5\x33\x13\x2a\x81\xca\x19\xbb\x08\x0b\xd4\x3b\xe9\x32\x02\x8c\xb5\xf6\xb9\x64\xf0\x08\xb5\xb1\xc1\xc5\x99\x3b\xc9\xb5\x48\x5b\x22\xbb\xef\x70\x1f\x0a\x26\xa3\xe6\x75\xea\x31\x12\x2b\xba\xe9\x1d\x86\x4b\x54\xd8\x95\xaf\xdc\x79\xca\x58\xd4\xfe\x44\x92\x13\x35\x3b\x14\x9f\x31\x43\xb5\x14\x4d\x74\x7c\x5b\x46\x97\x47\x9a\xe6\x85\x28\x48\x53\x84\x04\x4a\xa2\xc9\x9b\xa4\xb1\x7b\x18\x4e\x94\x98\x22\x69\xbd\xe2\xde\x0b\x17\x70\x5d\x0b\xfc\x46\xd6\x90\x6a\x90\xed\xef\xe8\x91\x95\xde\x6b\xb8\xf3\xfb\x6a\x37\x41\x86\xc7\xcd\x08\x6d\x13\xd1\xb3\x52\x5a\x39\x94\xdc\x80\x20\xe1\xa0\x05\x54\xac\x8a\x82\xd6\x04\x7c\x5b\xff\x5e\x7f\x12\x45\x0f\x48\x65\xda\x16\x1e\x1a\x02\x1f\xd9\xbe\x8b\xd3\x3a\x32\xbb\x54\xa4\xdd\xf8\x74\x51\x2e\x74\xb5\xcf\xd3\xfc\x3c\xd9\xac\x11\xed\xd8\x78\x43\x36\x68\xe3\xfc\xc7\x82\xb9\x7b\x6d\x90\x5a\xdb\x0e\xbe\xc4\x2c\x92\x54\xac\x90\xf3\x58\x22\xc0\x0f\x97\xff\x3f\x0c\x7c\x39\xed\x3c\x7c\xb3\x92\x0f\x56\x08\xbb\x45\x83\x8b\xb2\x42\xa5\x2a\x86\x37\xd7\xce\xcd\xcf\x48\x9f\xa1\x83\xb4\x54\x51\xc6\xc9\xfc\xbb\xbf\x91\x4f\x5f\x7e\x6b\x22\x3b\xcb\x46\x75"}, -{{0x9f,0xeb,0x3d,0xf8,0x8c,0x49,0x4a,0x99,0x84,0x9c,0x6f,0xca,0x19,0x42,0x01,0x47,0x7a,0x2f,0xa7,0x56,0x4e,0x29,0xfb,0x06,0xcb,0x44,0xc1,0x15,0x4e,0x8c,0xea,0x3a,},{0xc3,0x56,0x28,0xca,0x6e,0xe2,0x8e,0xc1,0xc2,0x39,0xdd,0xc5,0xbb,0xa2,0xa9,0xe0,0x9e,0x48,0x46,0x81,0x6b,0x14,0x3c,0x74,0xdf,0xa2,0xae,0xc1,0xf6,0x25,0x51,0xb6,},{0xa1,0xc2,0x60,0x78,0x35,0xbe,0xc1,0xa1,0xd8,0x78,0x72,0xfd,0x8e,0xe4,0x88,0xd0,0xae,0x9e,0xd2,0x3d,0x49,0xfd,0x67,0x86,0xfc,0x49,0x96,0x72,0x5e,0x49,0xb3,0x26,0x21,0x18,0xba,0xbb,0x48,0x34,0x87,0x7c,0x7f,0x78,0xfb,0xea,0xc0,0x2d,0xf4,0x0a,0xb0,0x91,0xb8,0xb4,0x20,0xdc,0x99,0x51,0x38,0x1e,0x3b,0xcd,0xa0,0x67,0x05,0x02,},"\x95\xfb\x75\x81\xbd\x25\xff\xd4\x42\xc3\xae\x38\xa1\x9b\xea\x73\x49\xc7\xb7\x68\x3b\xa6\x76\x7e\x14\x8f\x0a\xfc\x15\x37\x3f\x67\xc1\x6d\x47\x17\x81\x20\x2e\x6d\xa8\x05\x4e\xd7\xfb\x9e\xe2\x04\xcc\x0f\x63\xc2\x10\xa6\x70\xa5\xf9\xce\xd4\x29\x45\x88\x19\x63\x30\xd3\x1b\x8e\x83\x92\xbe\xf6\xb4\x8f\xe3\xc9\x20\x78\xfa\xe1\x12\x84\xb4\xc3\xba\x20\xd9\x37\xe2\x71\x9d\xe7\xbf\x67\xc0\x06\x69\xad\x23\xe6\x13\x84\xeb\xdf\x8c\x6e\x60\x73\x54\x28\xc0\x84\xfe\x21\x7f\xdb\x47\x09\xcc\xb6\x08\x3f\xc0\xae\x4a\x05\x27\x3e\xef\x73\x90\x23\xd3\x4b\xb7\x3f\x66\x2d\xac\xdf\x11\x0b\x6d\xbd\x3e\x74\xfc\x14\x91\xe8\xc9\x65\x96\x07\x5f\xae\x5c\x36\xaa\xbe\x2a\x0a\x53\x05\x2b\xf7\x7c\x44\x62\x43\x80\x63\xaa\x7b\xc0\xc5\x0a\xb9\x20\xc9\xeb\x28\x86\x71\x56\x0c\xa5\xba\x7a\xf4\x4a\x53\xdb\x2e\x2f\xf4\x3c\xa5\x60\x69\xea\x55\x17\xcb\x21\x4e\x76\xfa\xa5\x3d\xbd\xa1\x00\x00\x3c\x4f\x61\x75\x41\x40\x41\xbe\x74\xde\x22\xce\x15\x5d\x22\x81\xb6\xf4\x03\x5b\xe3\x98\x41\xaf\xdb\x96\xdd\x89\xaa\x80\x8e\x68\x65\xba\xe6\x2d\x6b\xed\xd9\x19\xd3\xe8\x65\x10\xb9\xfa\x5f\xed\xd1\x97\x7c\x41\x31\xb2\xb8\x6e\x0f\x48\xd7\x21\x5e\xb1\x3d\x54\x98\xca\x5d\x23\x68\xf8\x18\x95\xed\x85\x5a\x52\x71\x24\x65\x7e\xc9\x53\x9e\xfe\x3b\x24\x99\xa3\xb0\xb3\x38\x26\x2f\x26\x34\x0e\x22\x55\x4c\x79\xf4\xfa\xd2\xb4\xe4\x19\xc7\x0b\xc1\xa2\x10\x7d\x20\x64\x56\xb6\x36\x87\x81\xbe\x4b\x5e\x2c\x54\xda\x42\xd3\x36\x04\x0f\xb7\xba\x49\xc3\x2d\x75\x23\x21\xad\xcd\x92\x98\x6e\x78\xbe\xdb\x22\x6c\xea\xc5\x02\x92\x08\x9b\xb5\x79\x02\x7f\x70\x22\x17\x74\x5a\xfe\x06\xa5\xbe\x13\x6b\x39\x98\xa3\x60\x4c\x9f\xf2\xac\xd6\xfa\x3f\x3f\x71\x63\x3d\x31\x02\xfb\xf0\x30\x47\xc5\x48\x6f\x84\xc4\xdc\x24\x47\xd8\x63\x79\x63\x83\xd5\x5f\x08\xc9\x81\xfd\x4d\xd7\xdc\x1c\xb7\x2b\x8b\xa4\x43\x5a\xf6\xab\xdd\x74\xe6\xf6\xe6\x79\x8f\x1a\xe2"}, -{{0xbf,0xf6,0x89,0x55,0xdd,0x6a,0xe0,0xe8,0xba,0x85,0xab,0x0d,0x0c,0xda,0xf0,0x4a,0x9f,0x5b,0xef,0xd5,0xef,0x60,0x14,0xf4,0x99,0x94,0xa7,0x83,0x63,0xdc,0x17,0xf7,},{0x0a,0xd9,0x49,0x3a,0xf8,0x0b,0x15,0xf0,0x7a,0x52,0x1c,0xcd,0x67,0x4f,0xe9,0xe5,0x21,0x2a,0x4a,0x28,0xc1,0x7c,0x74,0xf6,0x60,0x5f,0xfe,0xf7,0x8a,0x4a,0xed,0x72,},{0x93,0x19,0xee,0xf7,0x40,0x63,0x3a,0xda,0x1a,0xf0,0xe1,0x37,0x64,0x4c,0x61,0xfb,0x3e,0x11,0xba,0x4b,0x01,0xd3,0xc6,0xf2,0x53,0x92,0xdc,0x93,0x67,0x87,0x2a,0x23,0xbe,0x56,0x31,0x0d,0x31,0x2e,0xfc,0xb9,0x1b,0xdb,0xab,0x78,0xa7,0x5e,0x57,0x6e,0xbe,0x90,0x81,0x97,0x24,0x15,0xf5,0x62,0xdb,0x41,0xba,0xf5,0xe2,0x33,0x8b,0x07,},"\xd8\xf5\x65\x0a\xa3\x58\x1c\x4d\x39\xbd\x1b\x8a\xfc\x96\xc1\xad\x7c\x4b\xf7\x23\x42\x6f\x9d\x7f\xab\xd1\xa5\xc8\xac\x1d\x2f\xe5\x4a\x97\x1f\xac\x76\x5e\x05\xaf\x6e\x40\x7d\x72\x69\xba\xb6\x61\xb3\x43\x22\x92\xa4\x84\xf9\x52\xc1\x10\x95\xbb\xd2\x0a\x15\xd7\x7c\x41\xf8\xf3\x73\x1a\x50\x4d\x51\x8e\xe1\x0c\xd0\x06\xc9\x6e\xe5\x73\x72\xde\x5b\xea\x34\x8e\xc8\xba\x15\x91\x62\x17\x0c\x63\xe9\x70\xf1\xc7\xa3\x46\x5a\x3d\x59\x2e\x1d\x56\xc6\x54\x0f\xbd\xb6\x02\x28\xe3\x40\x90\x96\x46\x32\x0c\x95\xf2\x56\x98\xcd\x48\x96\xbd\xff\x58\xe2\x56\x1e\x3b\x3d\x9a\x73\xb8\x97\x47\x91\x2a\x1c\xf4\x67\xd6\x3e\x41\x45\x5f\xda\x77\x47\x7f\x46\xfe\x69\x37\xbb\x0e\x79\xd9\x2c\xcd\x52\xe8\x2d\xba\x90\x8a\x05\xa5\x7c\x7e\xcf\x49\x55\x4a\xb4\x4c\x0b\x71\x8e\x3b\xdd\x5f\xc0\xbf\x70\x70\xd9\xc5\x8f\x86\x05\x91\xc1\x8b\xca\x8b\x3a\x9a\x14\x8a\x06\x54\x8e\x0f\x01\x60\x2b\x1e\x6f\x68\x60\x37\xc9\x4f\xf7\x32\xe1\x55\xd5\x2d\x5b\x0b\x44\x70\x3b\x3d\x11\x16\x3e\x3f\x56\xe3\xb9\xc1\xb8\x64\x76\xe4\xdc\xbf\xc5\x3f\xa0\x59\x84\xe8\xc7\x5d\xd2\x18\x43\xcf\x96\xf9\xe4\x94\xab\xba\xe7\x18\x4a\xa4\x27\x36\x63\x3e\x38\x11\xae\xff\x40\x2b\x2f\xcb\x7d\x7f\x70\x2e\x44\x72\x41\xe2\x2a\x58\x84\x2f\xd6\xd0\xc0\x3d\x33\xff\x5b\x8c\x79\x22\x00\xe1\x73\xda\xa7\xb2\x17\xe4\xb2\xf4\x43\x3e\x6c\x02\x0a\xcc\xe5\x01\xb9\x32\x3a\xa0\x24\x11\x44\x43\x4b\x08\xe9\xd2\x46\x91\x39\xff\x67\x34\x22\x08\x90\x05\x46\x20\x0f\xd9\x71\xa6\x5d\xbd\x6d\xb6\xc2\x1e\x3e\xf9\x17\x2a\xbb\xa1\xea\x9e\xa2\xa2\x49\xad\xdf\x1a\x1e\xaa\x3c\xe1\x19\x38\xb1\x3e\x30\x91\x3c\xd0\xda\xd4\x91\xfc\xbb\x32\x85\xea\x37\x8b\x8e\xf9\x22\x7f\x3f\xa8\x0b\x58\x6e\xcf\xea\xe1\x37\x06\x6f\x84\x48\xac\xdf\xb7\x8d\x6d\x3e\x9e\xf4\xa6\xb3\x62\xdf\x42\x41\xad\x9a\xe2\x53\xb8\xe1\x59\x7d\x65\x6e\x00\x0c\xea\x44\x7a\x02\xfa\x49\x33\x32\x86\x09\xbb\xa0"}, -{{0x1b,0xa9,0x19,0xc0,0x66,0xbb,0x56,0xe6,0x40,0xc3,0x33,0x59,0x68,0xe1,0xd1,0xb5,0xbc,0xc0,0x93,0x38,0x3e,0x2d,0x7c,0xf8,0xb5,0xff,0xf5,0xc6,0x1e,0xc4,0x7a,0x77,},{0x80,0x4c,0x90,0xbd,0xc2,0xb3,0x61,0x8b,0x01,0xf0,0x75,0xe0,0x41,0xfa,0x97,0x1b,0x83,0xc5,0xb6,0xcf,0xa3,0xb6,0xb3,0x97,0x4f,0x3f,0xa4,0x35,0x99,0xbe,0xac,0xab,},{0x50,0x3e,0xb7,0xed,0x6d,0xe1,0xb7,0x76,0xc9,0x52,0xf2,0x55,0xbb,0xd4,0xbc,0xfb,0x0e,0x48,0xbc,0x70,0xc2,0xcc,0x2f,0x1f,0x72,0xbf,0x68,0x81,0x47,0x90,0x40,0xc4,0x75,0x24,0xec,0x54,0x2a,0xe1,0x3f,0x60,0x05,0xca,0x50,0x16,0xb5,0x8b,0x73,0x6a,0x50,0x89,0x8d,0xd0,0x56,0x9d,0x4d,0x38,0xad,0x29,0x86,0x30,0xd6,0x8a,0xdb,0x0b,},"\x87\xc5\xc7\x5d\x8a\xd0\x7d\x52\xac\xd7\x81\xd1\xbb\x95\xf7\x8c\x70\xe2\x1c\x2d\xd6\x6f\x7a\xa4\x42\x34\x15\x2f\x98\x23\x4d\x12\x83\x58\xa8\xae\xe9\x8e\xa9\x03\xa7\x7b\x44\x1d\xb1\x44\x7a\xe6\xff\x34\x32\xdd\xd4\x57\x0f\x7f\x58\x03\x61\x22\xc1\xfd\xcc\x93\xcb\x21\x57\x37\x39\xc1\x9c\xca\xa4\x11\x50\x8e\x08\xde\x26\x06\xf3\xd8\xf2\xdb\x89\xdf\x6a\x44\xa4\x61\x33\xd5\x70\x18\x46\x26\x27\xe2\x2f\x57\xef\x36\xd1\xde\x02\x4d\xe3\xd4\xae\x41\xb7\x52\xdf\x48\x21\x15\x59\x34\xb4\x47\xb2\xef\xfe\x51\x24\x87\x52\x1b\xe0\x35\x68\x32\xa7\x4c\xe0\xe2\xd8\x30\x1b\x79\xf9\x31\x75\xe8\xb6\xb9\x61\xb1\xdf\x63\x7d\x8a\xca\xdc\x88\x45\x43\xc6\x86\x4f\x80\x25\xec\xec\xec\x7c\x6e\x4f\xe0\xfe\xcf\xc4\x0d\xcd\x95\xe8\xd6\xab\x93\xce\x25\x59\x53\x84\x43\x6b\x59\x8b\x73\xc7\x4b\x03\xd4\x9e\xd5\x00\x2c\x0f\x85\x8c\xfd\x9d\x0d\xf6\x1e\xde\x93\x7c\xc4\x16\x59\xd6\x70\x8b\x96\xfc\x5a\xaa\xde\xe1\x09\xe2\xa6\x88\x46\xba\xf2\xc2\x46\xdf\xcf\x3d\x27\xc2\x8b\xd1\x37\x1e\x35\xfc\x94\x12\x63\x14\x42\xee\x75\xf3\x8c\x6e\x49\x58\x07\x0a\x74\xf6\xe6\xa2\x20\xf7\x5c\x72\x80\xea\xb4\x73\x7d\x97\xe3\x78\x82\xf3\x62\x48\x11\x67\x5f\x16\xca\xf6\x0c\xb9\x44\xbc\xe9\x2e\x75\x88\x4c\x56\x48\x3c\x61\xf2\x6b\x63\x71\xb1\xb5\x12\x37\x62\x1a\x06\x54\x3e\xb4\xab\xea\x7b\xec\xc4\xfc\x31\xdb\xb5\x47\x5b\x3d\xeb\x9b\xb3\xc8\x99\x23\x87\x10\x48\x30\xc6\x07\x2a\xfe\x1a\xf2\x44\xbf\x68\x1a\x40\x32\x9c\x9b\x37\x77\x2b\x09\xc5\xe8\x8e\x78\xf7\xdf\xfb\xc0\x45\x49\xff\xa1\x3b\x41\x44\xdd\xfa\x53\x8f\xc4\xb3\x30\x05\x40\xad\x83\x02\x15\xe2\x5f\x11\x44\x6d\x28\x9f\x33\x12\x2c\x2c\x88\x0d\xe3\xda\x71\xc4\x53\xd7\xe8\x8f\x7c\xa4\xea\x3d\x12\x55\xe8\x2f\x4b\xc9\xe5\x53\x3d\xc4\x01\xc3\x30\x40\xe1\x69\x40\xb2\xcf\x9c\xf2\x1f\xea\xca\x1c\x2c\x6c\x33\x33\x7c\xf7\x5e\x18\x84\xb4\x83\xbf\x80\x15\x36\xd3\x04\x08\x91\x15\xa0"}, -{{0x9b,0x36,0x24,0x7c,0x17,0x71,0x0e,0x95,0x26,0x1a,0x7d,0x70,0x2f,0x57,0xfe,0x81,0xf2,0x97,0x11,0x17,0xa5,0x0c,0x87,0x92,0x01,0x93,0xb3,0x86,0xd4,0x94,0xca,0x97,},{0x29,0xae,0x39,0xf2,0x73,0xe3,0x5f,0xb3,0xf6,0x11,0xda,0x09,0x16,0x00,0x65,0x0e,0xfb,0xc4,0xfc,0x4d,0x1e,0x7b,0x4c,0x76,0xac,0xed,0x5a,0x83,0xf8,0x26,0x34,0xf3,},{0x03,0x59,0x70,0xa6,0x72,0xe9,0x3f,0x87,0xeb,0x42,0xcc,0x39,0x6f,0x6e,0xa7,0xe1,0xb3,0xdd,0x5c,0x59,0x51,0x57,0x28,0x26,0xd1,0x07,0x5a,0x15,0xc2,0xd7,0xe4,0x54,0xdf,0x19,0x5b,0x51,0xaa,0xe8,0xdc,0x61,0xef,0x7a,0xb8,0x95,0x48,0x5f,0x64,0xe5,0x98,0x95,0x73,0xd9,0x8a,0x06,0x2e,0x67,0xae,0x73,0x56,0xfe,0x5c,0x9e,0x3b,0x0f,},"\xe8\xd9\xd5\x3b\xa2\x7e\x98\xed\xd5\x5d\xf3\xc6\xb2\x45\xea\xcd\xdc\x8a\x40\xe3\xef\xb0\x07\xbc\x91\x8e\xc5\xa8\x69\x17\x8a\x17\x0b\xb4\xa6\x35\xb7\xf8\xf7\x42\xe3\x7a\xd4\x5d\x14\xa7\x43\x44\xa6\xb5\x22\x83\x0a\x52\x21\x06\xeb\x96\x0d\xaf\x19\x2d\xc1\xe0\xfd\x70\xf1\x61\x60\xe1\x22\x51\x68\x92\xd0\xe2\xab\xd0\xd4\xae\x0f\x0d\x2e\x5a\xdc\xc9\x9a\xd5\x53\x02\xe2\x51\xb3\xe7\xa4\xd0\xcb\x33\x77\x4a\x49\x70\x49\x90\x5c\x33\xde\x1f\xbb\xc1\xad\x2b\x6c\x64\x52\x95\xfe\x41\x6b\x4d\x12\xb2\x32\xef\xe0\xa3\x3c\xd2\xad\x87\x32\xeb\xa1\xc3\xcb\x0e\xae\xb0\xb2\xa5\x7f\xa0\x3e\xc5\x67\xca\x29\x21\x0b\xf6\xff\x95\x42\xa7\x66\xf4\x96\xfe\x68\x05\x8a\xa9\x83\x80\x6c\xbe\x7a\xb1\x0a\x47\x92\x0b\xac\x82\x48\x81\x8e\x54\xa4\x15\x51\xc9\xa0\x95\x9e\x89\x94\xca\xc6\x0f\xc8\x68\xad\x48\xb5\xa2\x4d\x5f\x24\xa7\xa5\xa3\xfd\x90\xb8\x47\xe8\x17\xad\x3d\xd5\xd0\xd6\xf8\xde\x2d\x20\x4f\x64\x24\x83\xbd\x53\x58\x5a\x92\xef\x92\x54\x15\xa9\xb3\x8f\xbb\xf0\x7f\xc0\xf3\x5e\x70\x75\x69\xcf\x48\x8b\x20\x54\x53\xce\x54\x33\xeb\xa6\xfd\xe8\x78\x1a\xf7\x2b\x52\xbf\xbc\xab\x85\xea\xd3\x85\xd9\xd3\x17\x5e\x21\xad\x33\x73\xad\x53\x5c\xf0\xe3\x57\xed\x6b\x53\x83\xef\x38\x29\xa9\xd5\x09\x5b\x87\xdc\x9a\xad\xbe\x0c\xa7\xab\xad\xf3\x3e\xc3\xb6\xff\xd6\xeb\x94\xaf\xdc\xc1\x2e\x8d\x66\xa6\xfc\x05\xac\xf9\x73\x68\xdb\x0f\x69\x56\x5d\xcd\x8f\xef\x4d\x1e\x49\xd7\xdd\x4a\xc0\x53\xc2\x18\xf5\x24\x0c\x81\x2d\x4e\xbb\xa4\x40\xdc\x54\xca\xcd\xdb\x1c\x39\x32\x9e\x5b\xd0\xc3\xc8\x0d\xc3\x25\x9a\x80\xf0\x59\xf9\x46\x79\xaa\x07\x94\xca\x01\x15\xcc\x62\xaf\x25\xe1\x24\xcb\x8a\x9d\x41\x60\xea\xce\x6d\x22\xc7\xb1\xc4\x45\x44\xf8\x11\x42\xa1\x9e\xbb\x02\xa9\xbd\xa6\x42\x9c\x50\xe7\x83\xdb\x4a\x07\xf0\x21\x9e\x85\x7c\x8d\x3c\x56\x55\xa5\x82\x83\x1c\x8e\xab\xc3\xf1\x9b\x59\xad\x8d\x2c\x71\x4a\xde\xaf\x40\x39\xd5\xcf\x70"}, -{{0x6f,0xed,0xe7,0x39,0x6c,0x46,0x20,0x33,0x18,0x9a,0xcd,0x23,0xd2,0xf9,0xd0,0x2b,0x68,0x89,0x8d,0x35,0xf3,0xa0,0x1a,0x79,0x8f,0xc2,0x4d,0x48,0x8d,0xe9,0x3a,0x78,},{0xb3,0x40,0x62,0x06,0x0b,0x2c,0x20,0x07,0x6a,0x98,0xfe,0xa9,0x39,0xb3,0xb3,0xa5,0x04,0x51,0xa5,0xf4,0x9f,0x83,0x51,0xc0,0xad,0x75,0x91,0xdb,0xbe,0xbb,0x13,0x0f,},{0x88,0xa8,0x3e,0x20,0x12,0xd2,0x09,0xca,0x03,0xb8,0xeb,0xf6,0xde,0x5b,0xb7,0xef,0x4c,0xcb,0x5e,0x3d,0xf5,0xca,0xc7,0x89,0x54,0xaa,0x69,0x49,0x30,0xe4,0xde,0x82,0x54,0x4e,0xf5,0x08,0x3c,0x48,0x92,0xdb,0x9f,0x05,0xd7,0x7b,0xf6,0x3f,0x4f,0xdf,0xce,0x15,0xa4,0xd1,0xc3,0xf8,0x5b,0xae,0x80,0x77,0x06,0x2b,0xec,0x0e,0x7b,0x07,},"\x5a\xbc\xc1\x4b\x9d\x85\x78\xde\x08\x32\x1d\xe0\xd4\x15\xe3\xd4\x0e\x9d\xe3\x1e\x18\x88\x13\x74\x75\xce\x62\xbc\x6f\xbe\xe8\xfd\xd0\x3b\x9d\x47\xc7\xb8\x8b\xbc\xeb\x80\x44\x44\x49\x0b\xf6\xa3\xcc\xb7\xa2\x73\x26\x1e\x24\x00\x4e\xa6\x7c\xef\xa3\xd5\xd1\x73\x57\x6d\x01\xe3\x8f\x76\xc1\xe0\xe5\x15\x08\x3c\x97\xe7\x99\x14\xac\xf2\xbe\x41\x60\xef\x93\x60\xbb\xe9\x86\xb3\x6e\x9f\xf9\x33\x46\xb0\xe7\x06\x91\xd9\x34\xe4\x7f\x8a\x50\x3f\xa9\x33\xab\x2a\x50\x42\x69\x47\xcd\xa8\xe8\x10\xc9\xeb\xe3\xb3\x69\x82\xf0\x9a\xee\x60\x92\x73\x9f\xa2\x35\x8b\x61\x3c\x7f\x12\x9d\xb0\xdc\xbe\x36\x8b\xee\x52\xf2\xf7\xf1\xdf\xe3\xd2\x43\x46\x05\xb5\xaf\xcf\x25\x60\x71\x71\x7d\x92\x4f\xd0\x80\x3b\xbd\x0d\xd1\xf9\x55\x5c\xe8\x34\xda\xc7\x81\xdf\x4c\xc7\xaa\x19\xe7\xf1\x1d\xa9\xfb\x99\xcb\x9e\x6b\x9e\x1e\x6f\xb4\xf7\xe8\xdc\xb2\x23\x6c\x28\xae\xb6\xcb\xc5\x5a\x13\x0e\x03\xc1\xb1\x7a\x99\x1c\xca\x1b\x79\x4e\x6c\x13\x73\x2d\x5b\x0a\x66\xf6\xeb\xa8\x60\xec\xb9\x85\x55\xaa\x4c\x21\x8d\x11\x2b\x11\x6b\xce\x23\x82\x95\xde\x14\x27\x41\xf6\x87\xbe\x0b\x24\x87\xf5\x8f\xfc\x5c\x12\xa0\xa5\x19\xf1\xe2\x37\x93\x24\x2e\xf8\x57\xed\x39\x8a\x20\x69\x9d\x43\x51\x45\x3f\xc2\xf0\x92\x76\x2a\xbd\xe3\x4f\x4d\xa2\xdb\xe0\xce\x2a\xab\xaf\x6b\xc4\xc0\x15\x9f\x3f\xe1\xae\xa1\x6a\x03\x6f\x7e\xae\xcd\x62\x95\x38\xf3\xe0\xee\xd8\x3c\x9a\x4d\xc1\xab\xc2\x38\xf9\x0d\xaa\xf4\x89\xfd\x61\xb3\x4d\x93\x7b\x6f\x46\x07\xa7\x88\xba\xa8\x20\x61\x94\x3d\xba\xb2\x6c\x1d\x38\x4d\x8d\x49\xf9\x93\x48\x80\x0b\xf3\x61\xf8\x71\xf5\xd6\xcd\xa1\x8f\x68\x99\x18\xce\xc3\x1a\xd1\x58\xf1\x86\x3d\x13\xff\xac\x54\x05\xc1\x62\xc3\x2d\xe0\x6e\x32\x99\x4c\xc4\x10\x6f\x95\xbb\x4f\xff\xdb\xef\xe7\xd6\x29\xec\x77\x97\x39\x46\x09\xfd\xbf\xea\xdb\x46\x92\x73\x70\xa1\x1f\xb3\x84\x71\x54\x0f\x95\x1b\x93\xc6\xeb\x23\x86\x68\xdc\x00\x6c\x21\x66\x0b\xa2"}, -{{0xd5,0x59,0x58,0x01,0x34,0xab,0x05,0x0a,0xca,0x44,0x6e,0xa7,0x75,0x0e,0xf6,0xb3,0x71,0xd9,0x2d,0x76,0x45,0xec,0x76,0x35,0xfe,0x78,0x51,0x10,0x0b,0xc4,0xe5,0x1e,},{0xde,0x50,0x20,0xcd,0x21,0xa8,0xb3,0x23,0x39,0xde,0xcb,0xed,0xff,0x24,0x66,0x4d,0x95,0x80,0x32,0x63,0x27,0xae,0xdf,0x09,0xc5,0xec,0x6b,0x3f,0xe5,0x40,0x52,0x26,},{0x6f,0xcb,0x1a,0xc9,0x29,0x0a,0xb7,0x67,0xd5,0x9b,0x59,0x8c,0x9a,0x24,0xec,0xdb,0x6c,0x05,0xbb,0x02,0x3e,0xc3,0x60,0x14,0xa4,0x0d,0x90,0x8e,0xf0,0xdc,0x37,0x8a,0x45,0x28,0xb3,0x76,0x0d,0x88,0x9a,0x79,0x17,0x4e,0x21,0xca,0xe3,0x5d,0xf4,0x5d,0x42,0x7b,0xa6,0xea,0x81,0x2b,0xdd,0xca,0x16,0xe3,0x5a,0x69,0xb5,0xe7,0x9f,0x0a,},"\x68\x42\xe3\x19\x0a\x11\x0e\xee\x96\xc5\x07\xd4\xbc\xb4\xc5\x48\xc3\xa0\xed\x7b\x1a\x8e\xd7\x7d\xd9\x3b\x38\x61\x3b\x23\xc7\x3e\x83\x0b\x20\x5e\x62\x65\x19\x21\xad\x82\x96\xb0\x8d\x1e\x10\x08\xad\x78\xf2\x99\x6e\x3c\x7f\x38\x03\x2e\x46\x7c\xff\xec\xd7\x7b\x85\x25\xe2\x43\xce\xc0\x21\xf8\x52\x96\xaf\xd5\x45\xd7\xbe\x1a\x62\x56\x8b\xb0\xcf\xcd\xb9\x0d\x61\x4e\xd7\x98\xbf\xb7\xef\xc6\x55\x32\x68\x16\xa6\x10\x82\x25\x1d\xf0\x16\x13\xaa\xc8\x8e\xfc\xea\x1e\x0e\xa2\x96\x1b\x8f\x92\x1e\xbe\x15\x58\xde\xe8\x33\x74\xa0\x11\x3a\x78\xc5\x58\x57\xce\x20\x55\xbb\x2c\x48\xba\xdb\xd3\xd8\xf4\xcb\x19\x73\x4d\x00\xd0\x60\x4b\x61\x90\x73\x02\x0d\x72\xa9\x9a\x19\x23\xe6\x16\x0a\x09\x94\x65\x67\xfd\x4b\xda\x66\x44\x2e\xf5\xa7\x36\x07\x86\xd1\x78\xda\xe4\x49\x22\xf3\x50\xce\x2e\xdc\x6a\xf7\x3d\x1b\xd8\x0d\xc0\x3e\xc3\xca\x70\x05\xf4\x10\x9d\x10\xc6\xd4\xf7\xd8\xfa\x61\x73\x51\x10\xf8\xdb\xae\xdf\x91\xa0\xba\xd7\xd7\xfb\x5c\x04\xd7\x06\x37\x3c\x15\xc6\x45\x06\x3f\xf4\xb4\xfb\xd2\xd5\x59\xb0\xaf\xad\x43\x2d\x4c\x49\x6c\xd8\xab\xfe\xa2\x86\xfa\x67\x5d\xc0\x76\x72\x6e\xc5\x22\xb3\xa3\xc2\xf4\x7a\xec\xc5\x39\xf4\x8a\x79\x21\x69\xc4\xcc\x8c\xd4\x1c\xd2\xcb\x6b\x63\xdd\xbc\x19\x37\x3a\xc9\x69\x1c\x2b\xc2\xf7\x8f\x22\x60\x3d\x55\x13\x71\x5a\x16\xd4\x57\x4e\x7a\xcc\x4b\xea\x6d\xcd\x8c\xa7\xf1\x98\x65\xa4\x9d\x36\x64\xa2\x10\xdf\xad\x29\x07\x74\xb1\x0b\x71\x88\xf2\x55\xb3\xbe\x4d\xc8\xfa\x86\xf8\xda\x3f\x73\xa4\xe7\xc9\x29\x95\x1d\xf3\x0f\xe6\x6a\x17\xc8\xce\xe2\x3e\x4f\x2e\xd2\x06\x3f\x0b\x02\xab\x40\x37\x2c\xbe\x54\xb9\xa7\x08\xdf\x7c\x48\xa0\x65\x66\xd3\x9b\x19\x43\x4c\x6c\x76\x69\x87\xb3\xeb\xb0\x06\x75\xf4\x4c\x4b\x3c\x1e\x9f\x45\x04\xe7\xa9\x27\x05\x89\xc0\xd0\xf4\xcb\x73\x42\x35\xa5\x8e\xf0\x74\xcf\x9d\xec\xf3\x60\x1a\xee\xca\x9f\x1d\x8e\x35\x6c\xb2\xdb\x5f\xce\x79\xcb\xc3\x61\x43\xf3\x4b"}, -{{0x9d,0x4c,0xe9,0x75,0x54,0x78,0x76,0x63,0x6f,0xea,0x25,0x43,0x7c,0x28,0x80,0xc9,0xaa,0x8e,0xe6,0xb2,0x70,0xd1,0xb2,0xda,0x19,0x7c,0x8d,0x7f,0x95,0xe7,0xdc,0xcc,},{0xbd,0xe4,0x99,0x3c,0x03,0x04,0x77,0xc3,0x58,0x90,0xaa,0xe8,0x2b,0xb5,0x08,0x7e,0x91,0x4e,0x64,0xb9,0x4f,0xfc,0x64,0xe2,0xd7,0xa5,0xa7,0xc9,0x19,0xe2,0xd9,0x02,},{0xbe,0x17,0x44,0x4c,0xd4,0x65,0xa8,0x7a,0x97,0x1d,0xf8,0x4e,0xb1,0x02,0xf9,0xc7,0xa6,0x26,0xa7,0xc4,0xff,0x7a,0xea,0x51,0xd3,0x2c,0x81,0x35,0x3d,0x5d,0xbc,0x07,0x39,0x3c,0xa0,0x3d,0xb8,0x97,0xd1,0xff,0x09,0x94,0x5c,0x4d,0x91,0xd9,0x8c,0x9d,0x91,0xac,0xbd,0xc7,0xcc,0x7f,0x34,0x14,0x4d,0x4d,0x69,0xeb,0x04,0xd8,0x1f,0x0c,},"\xea\x0f\xa3\x2a\x4a\x28\x88\x11\x30\x1b\x9e\xe5\x33\xfa\x35\x1f\xdf\xbf\x6b\xc1\xd0\x55\x5a\x74\x02\x76\x7a\x3a\x91\x98\x55\x8f\x74\xbb\xa7\x03\x18\x57\x99\x5b\x9f\x32\x62\x26\xf1\xdd\x5d\xf1\x07\xb0\x63\x42\x20\x3e\xb8\xd4\x0c\x5f\x1d\xc9\x5b\x4f\x3f\x88\x97\x5a\xa2\x4a\xf8\x76\x9e\x26\x70\xc4\x66\x71\xbe\xbb\x7a\x0f\x1b\x75\x68\x72\x9a\xee\x47\x7e\x89\x88\xaf\x9c\x74\x9f\x32\x02\x70\x81\x71\xfd\x94\xb3\x37\xae\x67\xed\x21\xa6\xc4\x41\x74\x01\x4b\x0b\x0e\xb5\xba\x71\xc2\x77\x97\x8d\x48\x8c\x24\xc4\xa7\x84\x13\x09\x84\x6b\x4e\x30\xa4\xfb\xbc\xfc\x45\x07\x8d\x7e\x14\x01\x41\x14\xb1\xac\x64\xf7\xc3\x3c\x9a\xc2\x5e\xa5\x62\x6c\x2c\x81\x9f\xba\xa2\xa4\xde\x8a\x2b\xf5\xf1\x36\x5d\x6b\x70\x40\x7e\x80\x94\xf9\x91\x97\xce\x1f\x0c\x35\xe1\x1a\x98\xfb\xe3\x72\x41\x4e\xa2\x06\x4a\x3a\x12\xd1\xcd\x5c\x8d\xf8\xfc\x0e\x79\xf5\xb7\x70\xb5\x8f\x47\x7f\x91\x97\x6c\xa0\x13\x98\x95\x12\x0e\x24\x6b\xaa\xb5\xa0\x26\xf2\xd3\x9c\x68\x7d\xc0\x78\x83\x34\xb5\xc6\x26\xd5\x2c\xde\xbe\x05\xea\xf3\x08\x64\xb4\x13\xee\xbd\xc5\x58\x1e\xf0\x0d\x43\x92\x76\xe5\x2f\x47\x9c\x9c\x05\xb1\x16\x39\x58\x26\xb6\x04\x90\xb3\xce\x70\x0c\xc0\x02\x7f\x61\xe4\x6c\xa2\xf6\xfb\xc2\xc9\xde\x2e\x80\x08\x06\x55\x0a\xfb\x06\xd4\xa0\x8e\xac\x7a\x75\x8e\x24\x58\x2a\x4d\x6d\x42\x8b\x43\x3d\x36\x5f\xc3\x1d\x44\x44\x60\x7a\xfb\x64\xf1\x5e\x37\x07\x94\x00\x5a\x3a\x22\x44\xe6\x66\xd5\xd4\xc3\x8a\xd2\x00\x9c\x76\x9a\x51\xcd\xbf\x73\x8d\x23\x59\x42\xf4\x12\xd0\x7f\xee\xb7\x3b\x36\x57\xd0\xb0\xc9\x1c\xb5\x94\x0b\xad\x6a\x70\x6e\x14\xed\xcd\xc3\x42\x25\xb1\xc1\xf3\x8b\x1a\xbe\xcb\x2a\xdc\xaf\x81\x91\x55\xa9\x4f\xe1\x90\xfd\x55\x68\x22\xd5\x59\xd9\xc4\x70\x85\x4d\x3a\x43\xbf\xb8\x68\xda\xdd\x6e\x44\x3d\x98\xee\x87\xe4\xd8\x28\x4f\x5c\xf3\xa6\xda\xfa\xf2\x95\xb9\x02\x83\x6c\x64\x05\x11\xe6\x10\xae\x7d\x0c\xb1\xb1\xd3\xd6\x07\x9f\xe6"}, -{{0x02,0x73,0x86,0x82,0x32,0xf5,0xbe,0x48,0x59,0x2c,0xfa,0x05,0x13,0x4e,0x8d,0x55,0x54,0xed,0x1f,0x9a,0x57,0xbc,0x7e,0x39,0x82,0xa3,0x30,0xc5,0x7e,0x5a,0x7f,0x3a,},{0xf1,0x72,0x20,0x87,0x82,0xdb,0x66,0xd4,0x66,0xcb,0xe4,0xf4,0x41,0x7f,0x6f,0xc4,0x77,0xb7,0x34,0x9f,0x2a,0x98,0xdb,0x56,0xc0,0x3a,0x47,0x22,0x75,0x46,0xbc,0x5a,},{0x15,0xe8,0xd8,0xdc,0x7d,0x5d,0x25,0x35,0x9d,0x6a,0x10,0xd0,0x4e,0xe4,0x19,0x18,0xa9,0xc9,0xdf,0x4c,0x87,0xbe,0x26,0x9f,0xa8,0x32,0x43,0x4d,0x53,0x01,0xdb,0x02,0x24,0x81,0xbf,0xa3,0x95,0xa3,0xe3,0x46,0x6f,0x95,0x54,0xce,0xee,0x05,0x32,0xa8,0x18,0x3a,0x0d,0x05,0x50,0xe7,0xd1,0xab,0xe9,0x9f,0xc6,0x94,0xc6,0xff,0x93,0x01,},"\xf7\xa1\xd4\x61\x4c\xc6\x4a\x3b\xc4\x8f\x00\xc6\x27\x63\x04\xf3\x4d\x4d\xfd\x15\xe0\x61\x7b\x93\xcc\xef\x12\x6c\x5c\x63\x8c\x9d\x99\x53\xaa\xbb\x7d\xf4\x2d\xf4\xe0\xaa\xa7\xea\xc9\x6a\x4b\x38\xc7\xba\x75\x8d\x86\x0c\x90\xd0\x5e\x3d\x14\xe4\x79\xe5\x45\xf3\x19\xb0\xe5\xa8\x5a\xd8\xf0\x99\x1b\x43\xd6\xe4\x9c\x24\xfa\x06\x0e\x3e\x5d\xf9\x5c\x98\xd9\x45\x1a\xb8\x33\xe1\x2a\xa9\x7f\x40\x46\x11\xbb\xa3\x59\x49\x62\x65\xa6\xdb\x11\x91\x7d\x0d\xa5\xc6\xa7\x02\xd0\xb1\x02\xde\x36\xdd\x0c\x98\xdf\x5b\x54\x80\x6c\xe6\x26\xbb\x96\x37\x44\x75\xf6\x8a\x60\x60\xeb\x35\x0a\x7d\x2a\xae\x32\x04\xb3\xdf\xdf\x9f\x1e\x31\xbe\x81\xf7\x17\x0f\x8a\x1b\x93\x85\x41\x3f\xf8\xf6\x88\x1e\x10\xc1\xe8\xda\x4c\x88\xaf\xb5\x06\x39\xab\x44\x88\x7a\xca\x2a\xbe\xec\xed\xf1\x10\xd2\x95\x8c\x13\xfd\x33\x90\xd1\xb9\x6a\x76\x2d\x16\xce\x19\x69\x20\xce\x85\xf6\xc4\x15\xbe\xd5\x45\xb1\x44\x53\x02\xa6\xf0\x01\xeb\x8d\x00\xe9\x7c\x75\x18\x87\x86\x8d\x48\x1a\x0b\x1e\x4d\xfa\x04\xb6\xf7\x61\x08\x6e\xe8\xe6\x97\xb0\x19\xe0\x17\x10\x4b\xaf\xb9\x8f\xca\x24\x2e\x33\x4c\x6f\x18\xf1\xdb\x5b\x6f\x29\x5f\x05\xc5\x59\x36\x1c\x68\x31\xda\xbc\x42\xc2\x11\x07\x03\xf9\xd1\xf6\x4e\x12\xdd\xf2\x6a\x86\x79\x85\x4e\x9f\x8e\xf8\x47\x9e\x1f\x12\xc3\x54\x47\xaa\xc0\x2e\xa7\xf2\x42\xe5\x86\x32\xcf\x2f\xd0\x63\xfe\x66\x50\x70\x44\x5b\x80\xf3\xdc\x6a\x33\x03\xbb\xa9\x6e\x05\xfa\x88\xee\xc2\x01\xc5\xc2\xd0\x0c\xa8\x1b\x8d\xa6\x96\x9d\x0a\x4d\xd0\x48\x3b\x34\x77\xd3\x25\xa7\x1f\xac\xd6\xfa\x22\x09\xb4\x8c\xb4\xf6\x52\x5d\xa7\x3c\x9c\x05\xb2\xd9\x78\x9b\x01\x44\x8e\x15\x27\xe5\x6a\x09\xa9\xbc\x61\x36\xd9\x83\x72\x43\xc2\x07\x7b\x92\x5b\xbb\x93\x3f\x8f\xb1\xda\xac\x96\x33\x98\xc5\x80\x2a\xed\xa3\xbb\xca\x8a\xe3\xb8\xf4\xa9\xa8\x71\xf7\xea\x8e\x2c\x0c\xe8\x98\xc5\x66\x21\x7b\x5c\x06\xff\x55\xff\x9f\x4f\xe7\x83\x98\xae\x79\x73\x64\x1e\xaf\xb5\x21"}, -{{0x33,0x6a,0x83,0xb5,0x5a,0xbf,0x4c,0x02,0xe2,0x5e,0x54,0x03,0x29,0xb5,0x27,0x58,0x43,0xc2,0xec,0xb8,0xdf,0x69,0x39,0x5b,0x5a,0x5e,0x24,0x1b,0xd0,0xd8,0xc1,0x0d,},{0xdd,0x60,0x56,0x98,0x44,0x57,0x0c,0x9f,0x0a,0x82,0x64,0x3f,0x44,0x64,0x78,0xb5,0xac,0x6f,0xc5,0x42,0x21,0x42,0x31,0xa7,0xca,0x65,0x6a,0x92,0xb5,0xfd,0xaa,0x54,},{0xd2,0x63,0xf5,0x6d,0x59,0xcb,0x9b,0x28,0x96,0xa9,0x47,0x26,0x7c,0x2e,0xd7,0x8a,0x94,0x5b,0xac,0x5a,0xbd,0xbf,0x3c,0x14,0xdc,0x3a,0xd0,0x92,0xb2,0x30,0x8c,0xb9,0x31,0x5c,0x46,0x49,0x42,0xa0,0xa2,0x0b,0x20,0x24,0x51,0x1d,0x76,0x6e,0x85,0xc9,0x36,0x49,0x9a,0x14,0x9c,0xd0,0xbb,0xb2,0x09,0x15,0x0a,0x16,0x43,0x26,0x52,0x00,},"\x9a\xfe\xe8\xab\x48\x20\x10\xe2\x92\x64\xb4\x06\xd9\xb4\x94\x53\xd1\xce\x6d\x55\x09\x39\x07\x21\x82\x86\x3e\x46\x65\x28\x4a\xb0\x5d\x86\x25\x8e\x06\x23\xb1\x87\x54\xc4\x78\x52\x38\xf6\x97\xf0\x75\xad\xfb\x9e\x1d\x31\xa4\x2e\x85\x93\x4e\xc0\x71\xdd\xdd\xec\xc2\xe6\xc2\xf6\x13\x34\xa7\x95\x26\x78\x8b\x49\x52\x19\x07\x16\x90\x6d\xde\x17\xfb\xa5\x56\xee\xa4\xc8\xb5\x97\x27\x51\x4f\x6f\x56\x15\xa1\x9c\xa3\x6d\xa3\x58\xfa\xe6\xa6\xc5\x4f\x7f\x4b\x7a\x92\x9e\x31\xba\x7c\xc7\x1b\xde\x78\x82\xfa\x9f\xfd\x87\x30\x01\x36\x40\x9c\xaf\x3c\xa6\x4e\xef\xea\x61\x6a\xed\x58\xda\x5d\xfb\xf2\x8b\x66\x8e\xc1\xcc\xcf\xfc\xef\x6e\x2e\x14\xf8\x10\x9e\x9c\xbf\x76\xcf\xa4\x14\xf9\x1a\xc0\x0f\x48\xe9\x3e\xad\xa3\x85\xdd\x3d\x5c\x16\xe1\xa3\x9e\xa3\xdd\x55\xc7\x61\xfc\xa3\x61\xb4\x28\xf5\x16\xc0\x5e\x69\x4f\xe5\xc3\xc3\x45\xcd\x94\x45\x71\x87\xa8\xe6\x04\xb2\x00\xa1\xa0\xf9\x37\xae\x89\xf4\xd6\xb5\x42\x1d\xff\xcf\x7c\xa1\x5f\x2e\x2c\x25\x37\x8a\x41\x13\x23\x3f\x76\x13\xf4\x57\x0a\xa4\xb9\x09\xa9\x13\x5e\xae\x4c\x7b\x9e\xad\x45\x80\x07\xae\x17\x12\x6a\x11\xd1\x45\x25\x8a\xf9\x56\x3d\xb2\xf7\xe8\x92\x54\x31\x87\x8b\x0e\xec\xa8\xaf\xfc\x01\xac\x59\x13\xbf\x5b\xac\x4f\xa3\xa8\x57\xc5\x4c\xc8\x90\x6d\x6a\xf7\x7d\xe6\xb9\x32\x6b\x65\x06\x15\x10\x99\xe8\x7e\x99\xb1\xe8\x19\xc6\xfb\xe0\x82\x68\x8f\x34\xb8\x03\xd5\x88\xe4\x16\xd8\x53\x16\x97\x65\xd6\x2f\x7e\x0b\xdf\x72\xc5\xcd\x66\x66\x9a\x03\x35\x56\x23\x36\x73\x5e\x7e\xfb\x73\x4a\x2f\xad\xa3\x27\xf8\x58\xbe\xc6\x02\xd0\xda\x08\xeb\xa4\x47\x9e\x7f\x6d\xc4\xde\xf6\xe4\xeb\xdb\xb7\x30\xee\x91\xa3\x34\x45\xca\xdc\x9d\xf5\x2c\x82\x5a\xd3\x61\x49\xce\xfb\xc5\x1a\xb1\x02\x03\x35\x30\x81\x4b\xaf\xa7\xe8\x79\x61\xb0\x63\x67\xff\x89\x6f\x08\xae\x33\x4a\x9b\x1a\xad\x70\x3d\xa6\x86\x70\x6c\x11\xa0\x49\x43\xea\x75\xe1\x29\x92\xdc\xf6\x10\x6e\x37\x20\x77\xcd\x03\x11\x02\x9f"}, -{{0x88,0x40,0x91,0x72,0x61,0x8b,0x49,0x03,0x93,0xdb,0x27,0xd9,0x60,0x17,0x1c,0xbc,0x18,0x7e,0xaf,0x4d,0xd8,0xb3,0x20,0xb3,0xd2,0xf8,0x24,0x98,0x00,0x43,0x71,0x8f,},{0xce,0x2e,0x7c,0x58,0x39,0xef,0x56,0x32,0xa1,0x23,0xdc,0x37,0x3d,0xc1,0x4b,0x1f,0x05,0x05,0x76,0x6e,0x96,0x75,0x40,0x76,0x04,0xca,0x7c,0xf5,0x4e,0x8d,0x44,0xb2,},{0x93,0xb6,0xe2,0x9d,0x63,0x94,0x5d,0x5c,0x42,0x73,0x87,0xd0,0x06,0xc7,0xf0,0xb0,0x19,0x56,0xa9,0x5f,0xc0,0x43,0x6e,0xd4,0x2b,0x46,0xd0,0xf1,0x7b,0x5b,0xb1,0x93,0xea,0x8c,0x0e,0xbb,0xf3,0xd6,0xd1,0x3b,0xb5,0x39,0xe3,0x5c,0x91,0xf3,0xf0,0xf9,0xfa,0x34,0x14,0xa0,0x22,0x3c,0x90,0x60,0xba,0xc8,0x36,0x53,0xc6,0xfc,0xd9,0x06,},"\xfb\x3e\x82\xf1\x1b\xc2\x86\x26\x7e\x12\x38\x17\xad\x88\x64\xe0\x77\xd9\xf7\xa8\xe7\xa1\x63\xac\x7e\xea\xf9\x3d\x55\xdd\x11\x1d\xe8\x08\x3b\x66\xb5\x3c\xe7\xbc\x77\x1f\xc5\x07\x1a\x2d\x7a\xc2\xf8\x5d\x6f\xc6\xad\xcf\xce\xc4\x46\xe1\x6a\xa1\x04\x6d\xf3\x72\x09\xad\x7a\x29\xcf\x96\x65\xb4\x39\xa5\x4d\x6f\x8d\x94\x2f\x89\xbd\xaa\x56\xf2\xf1\x12\x60\xcc\x95\x99\x30\x38\xb0\xe8\xfb\xdb\x32\x14\xf1\x42\xe6\xc9\x0b\x61\xa1\xd2\xb1\x42\x07\x62\x06\xaf\x30\xac\x35\x78\x4a\x6d\xc1\x5a\x1e\x79\x25\x1a\x8c\x77\x31\xa1\xc5\x39\x78\x03\x8f\x8d\x76\xd7\x0c\x6c\x1c\xdf\x52\x9f\xbd\xb8\x4d\x15\x07\xdc\xff\xdd\x42\x87\x3d\xfa\x6a\x8f\xe6\xbd\x6f\x7f\xd2\x9c\x80\xe4\xb2\xf9\x33\xd2\xb6\xc9\xe6\x2c\x94\x57\xe6\x65\x47\x26\x55\x05\x9b\x63\xb6\x18\xe2\xa9\xa8\xe5\xb9\xe4\x1c\x36\x46\x17\x3a\x89\x2b\x8e\x6d\x4b\xca\xd6\xa6\x2a\x6f\xcc\xd3\x45\x58\x90\xb5\x8e\xc2\x68\x1a\x95\xcc\x97\x76\xa9\xfc\xe8\x3c\x54\xa9\xef\x31\x2a\x33\x19\x59\xc7\xef\x3f\x79\xee\x57\x6e\xb7\xb7\x94\x69\xc9\x23\x4b\x1e\xae\xf6\x09\x88\x47\x08\xfe\x4b\xb0\xef\xac\x66\x2d\xa8\x71\xba\x61\xdd\xab\xb3\xfc\xbd\xeb\x8f\x63\x56\x57\xdd\x9a\x5d\x73\x11\xe6\x39\xa8\x24\x85\x8b\x9a\x98\x68\xd3\xf9\x38\x4d\xa6\x12\xc7\xf2\xe7\x71\xa4\x6b\xd2\x62\x4c\x99\xea\x2b\x6c\xcb\xca\x99\x6c\x1d\x9c\x37\x55\x54\xf2\xa5\x51\x61\x9c\xe6\xd5\xe6\xe4\xd6\xb8\x44\xa4\xdb\xea\x83\xba\x73\x23\x31\xfc\xf4\x65\x72\xc1\xfb\x0e\x25\x7c\xe1\x04\x1b\x26\x5d\xf0\x2e\x69\x0a\x92\x81\x4b\xbf\x3b\x5e\xca\xc6\x9e\xe9\x98\x76\x6a\x02\xb0\xd2\xf9\x08\xb3\xc1\x5f\x95\x26\x99\x61\x6f\x2c\x07\xd5\x89\x19\x89\x89\xe6\x05\x6c\x16\x31\x9a\xab\x6c\xf8\x77\x19\x02\xc0\x78\x04\x6a\x88\xb2\x57\x0c\x13\xbc\x5e\xde\xba\x2e\xd1\xe3\xba\x13\x1d\xaf\x94\xe6\x89\x18\x62\xbb\x3d\xe7\xd1\x06\x3f\xe4\x05\x30\x7a\x5c\xd9\x75\x69\x3e\x9d\x58\xe1\x7c\x69\x0e\xee\xf4\xa2\x60\x3c\xaf\xc6\x8c\x2b"}, -{{0xe5,0x71,0x18,0x9b,0x5c,0xd9,0xe7,0x88,0x30,0x2d,0xe3,0x91,0x9d,0x85,0x0c,0x22,0x7d,0xcb,0xb6,0x15,0x02,0x2e,0x56,0x8b,0xda,0xeb,0x37,0xac,0x5b,0x29,0x39,0xc5,},{0xed,0xda,0x89,0x0f,0x42,0xdd,0x5f,0xbc,0x73,0x16,0xa5,0xfa,0xdf,0xbe,0xc3,0x85,0x56,0xf2,0x3f,0x51,0xb8,0xef,0xd2,0x62,0x54,0x37,0xf6,0xb5,0x06,0x9f,0x1e,0xe5,},{0x7f,0x79,0x7a,0x31,0x71,0x5d,0x7c,0x35,0x6f,0x8f,0x1f,0x78,0x37,0x00,0xaa,0x99,0x74,0xbb,0x93,0x6d,0x66,0x16,0x61,0xad,0x96,0x8c,0x7c,0xde,0x1a,0xc9,0xe7,0x67,0xbe,0x56,0xa2,0xdd,0x49,0xb9,0x23,0x0e,0x90,0x11,0x0c,0x67,0xc0,0xed,0x18,0x7c,0xb7,0xe7,0x5c,0x30,0x53,0xec,0xe8,0x44,0x98,0x4d,0x29,0x6f,0x0d,0x85,0xcb,0x07,},"\xb6\x2c\x86\x7a\xd6\x22\x74\x35\xbf\xa6\xda\xb8\x30\x68\x4e\x38\xd1\x96\xe1\xf8\x61\xaa\xde\x0f\xd6\xa7\x69\x9b\x6d\x60\x90\x1f\xef\xb2\xd7\x99\xc3\x5c\x6f\x3d\x8b\xb9\x4d\xee\xe8\x34\x40\x39\x81\x86\x6b\xab\x84\x94\x6a\xe9\x47\x6c\x75\xe9\xf1\xd3\x60\x2b\x42\xcb\x2d\xb4\x37\xbf\xf3\x3a\x77\x58\x22\xf0\xd6\xa2\x57\xd4\xb7\x54\x00\xeb\xa5\xb8\xab\xb3\x14\xb7\x1f\xc6\xb4\x6f\x8a\x34\xe8\x61\xa9\xa6\x2a\xbf\x33\xde\x84\x82\xf6\x3f\x9d\x71\x69\xe7\x73\xa2\xdc\xeb\xee\x03\x70\x5d\xac\x11\x7f\xd1\x49\x9b\x68\xe7\x41\x4f\x51\xff\x94\x37\xf2\x53\xa1\xd9\x90\x1e\xc3\xb0\xbb\xa8\x69\x65\xa1\x93\x83\x65\x54\x87\xb5\x80\x10\xf8\x04\x90\x9d\xe1\xff\xb2\x21\x2c\x02\x52\xdd\xd9\xbf\x2a\x56\xac\x46\xbd\x59\xc0\xc3\x4d\xd5\x9e\x46\x59\x8b\x6b\xab\xd4\xe5\xf3\xff\xfd\xe5\x5e\x48\xda\xb0\x39\x8c\x22\xaf\x9e\x26\xba\xdd\xf7\x72\x75\xe5\xf0\x17\xb3\x5a\x9b\x8f\x84\x35\xf9\x63\x19\x36\xb3\x91\xcb\x95\xd7\xad\xf3\x5d\x1d\x85\x45\xa0\xfd\x06\x64\x12\xd5\x08\x96\x7b\xbe\x9a\x20\x24\x5a\x26\x9e\x3b\xe2\x77\x71\x17\xe7\x5f\xba\xc1\x70\xdb\xa3\x52\xbe\x69\xb2\x54\xd3\x53\xb3\xb2\xcb\x3b\x7e\x21\xb7\x21\xaa\x9f\xe0\x44\xf8\x91\x6b\x4b\x2a\x6f\x8c\x28\xf8\xab\xe6\x6a\xc9\x2b\x91\x32\x3a\xc7\x3a\xfd\x93\xdf\xbe\xea\xee\xf2\x6d\x19\xbd\x9f\x67\xe9\x9d\x48\xcd\x2a\xd2\xd3\xe5\x5e\x45\xd2\x4d\x54\xb5\x0f\x44\xa3\x9b\x90\xe2\x42\xeb\xe9\xb4\x2b\xeb\xdb\x23\x0c\x47\x0b\xdf\xde\x1b\xc7\x72\x1c\x31\x20\x00\x84\x77\x39\x3d\xcc\x2e\x15\xfd\x22\xb2\x51\xfe\xb0\xe1\x8b\x02\x88\x3c\x07\x8a\xee\x4f\xb7\x60\x65\x5a\x67\x1d\xc7\xb8\xaa\xdb\x9a\x56\x24\x20\xa3\xc2\xef\xa2\xd3\x42\xe1\xe0\x09\x9d\x95\x1b\x42\x24\x29\x84\xf5\x94\xe6\x91\x4f\xe2\x82\xb1\xee\x12\x87\x35\x98\x4e\xf9\x3a\x66\x9e\x6e\xcb\xa2\x6c\x9f\xcb\x9f\x09\xf0\x92\x56\x64\x56\x17\xf1\x39\x2d\x35\x90\x89\x17\xcb\x8d\x29\xe0\x89\x7c\x75\x03\xcd\xdd\x5d\xe1\x95\x96\x86"}, -{{0x37,0x17,0x44,0xab,0x63,0xc1,0x15,0x61,0x39,0x29,0xa3,0x43,0x70,0x9b,0xb0,0x19,0xb7,0x35,0x7d,0xff,0x72,0xd2,0xa1,0x49,0xf1,0xd0,0xf7,0x1d,0x3a,0x20,0x1e,0xfe,},{0xe5,0x8a,0xbf,0xad,0x4a,0x13,0x85,0x9f,0x0a,0xcb,0x05,0xd0,0xe4,0x7d,0x59,0x63,0x8f,0x7b,0x1b,0x49,0x36,0x10,0x0b,0x98,0x8d,0x61,0xe6,0xe7,0x0e,0x22,0x66,0x7d,},{0x5e,0xae,0x4a,0xc7,0x2a,0xf0,0x17,0x4a,0xb2,0x56,0x52,0x7b,0x7c,0xd3,0x37,0xa0,0xe5,0x48,0x2e,0x61,0x5a,0xf0,0x68,0xdb,0x21,0xda,0xe3,0x5a,0x64,0x64,0x07,0x42,0x60,0x4d,0xf7,0x3f,0xd4,0xca,0x02,0xed,0x95,0x15,0xa5,0x60,0x8d,0x73,0x19,0x52,0x30,0xfa,0xdc,0xa7,0xb4,0x26,0xf0,0x2a,0x2f,0xbf,0xd0,0x20,0x61,0xaf,0x36,0x00,},"\xc2\x19\xde\x1e\x8d\x7a\xd8\xdf\x08\xc4\x93\x77\x39\x6f\xe7\xc1\xf2\xd5\x7b\xd2\x17\x06\x33\xa0\x0d\x70\x8f\xaa\xde\xe1\x80\xce\xba\x92\x84\x9a\x77\x78\x50\x6c\xbb\x36\x68\x75\xbf\x91\x24\x70\x18\x94\xce\xcd\xb3\x38\x51\x47\xd0\x67\x18\x43\x92\x2a\x64\x9a\xff\x7c\x43\x5e\xb5\xa9\xc7\x49\x27\x50\x30\x72\xd0\x06\x79\x78\x71\x6d\xc8\x0b\xe1\x54\x5a\x2d\xbf\x5a\x1c\x38\x53\x6e\x12\xbd\x77\x20\xc1\x96\x5d\x38\x03\xa4\xe8\xaa\x55\x76\x51\x92\xa1\x3b\x70\x5c\xa1\x05\x9d\xed\x0e\x80\x63\x62\xfc\x5b\xbe\x6c\x76\xa1\xc9\x67\x4b\xb8\x53\x79\x0f\x7e\x90\xaf\x00\x75\x3e\x00\x43\x6d\xa4\x8c\xd0\x82\xea\xd6\x4f\xdd\xb6\x89\x89\x01\x62\x08\x2f\x84\x82\x92\x4f\x33\xac\xd6\x04\x64\x0f\x69\x92\x73\x52\xb4\x3f\x64\x40\x2d\x27\xa8\x83\xfa\x6b\x72\xaa\x70\xd2\x41\xdf\xfa\xa1\x70\x1a\x25\xcf\x10\x79\x35\x82\x60\x79\x38\x75\xf7\x6a\x29\x78\xe9\xf9\xf9\xd6\x86\x34\xeb\x3f\x5f\x01\xbd\xe1\xce\x49\xe5\x92\x12\x52\xf9\x49\xf0\x82\x79\x5e\x4e\xaf\xed\x7b\xe5\xb4\x9a\x9f\x95\xed\xbb\x4a\x13\x53\x2e\x3f\x3b\x3b\xe6\x2e\x26\x52\x23\x12\x53\xa2\x0c\x1d\x54\x77\xe8\xf4\xbc\x57\xed\x76\xfa\x19\xea\xf0\x3a\x11\xbb\xa4\x29\xb6\x49\x6c\xe7\x62\x46\x17\x0e\x04\x3b\xc1\x4f\x2d\x2f\x70\x3d\x96\x8f\x1d\xeb\x09\x38\x87\x15\xc3\x7c\xb4\x75\x2d\xa8\xd4\x64\xe3\x48\xe0\x31\x3c\x89\x93\xe2\x41\x33\xa7\xc5\x45\x28\x4e\x3c\x9c\x90\x7d\x01\xb2\x60\xc4\x88\x3f\x9c\xb3\xe3\xdc\x5b\x6f\x7f\xb6\xd7\x55\x36\x36\x5f\x21\x32\xea\xed\xda\xb5\x70\xe7\x27\x3a\xfa\xc0\xbf\xf5\xc9\xfc\x0b\x82\x0f\x20\x78\xe0\x33\x60\x52\xe1\xfe\x7b\xde\xc8\x66\x74\xd0\x99\x8e\xc7\x8d\xa1\xc3\xf3\x47\x51\xf8\x86\x72\x76\x95\xf3\x5e\xca\x13\x04\xb1\x47\x34\x76\x6a\xb0\x5c\x11\x86\x30\x6d\xed\x9d\xb3\xee\xf6\x5d\x3c\x04\x56\xcd\xae\x81\x81\xaf\xee\x04\xb2\x96\xc6\x72\x2a\x88\xc7\xef\x30\x88\xd2\x6f\x7f\xe7\x4b\xc8\x9c\xf5\x28\x5c\x68\x8f\x02\x7b\x7e\x68\x60\x04\x86\xaf"}, -{{0x49,0x8b,0x6e,0xe6,0x49,0x2d,0x53,0x23,0x1b,0x35,0x32,0xd1,0x93,0x57,0x8b,0xa7,0x5d,0x6a,0x89,0x4e,0x2e,0x53,0x00,0x34,0xe2,0x1a,0xb8,0xad,0x8d,0x2c,0x0d,0x1f,},{0xd1,0x24,0x66,0x5b,0x28,0xfa,0xcd,0x2d,0x17,0x94,0x6a,0x04,0xdf,0xe3,0xd1,0x29,0xa4,0x56,0x1a,0x2b,0x24,0xeb,0x32,0x6d,0x84,0xb6,0x2b,0x42,0x2e,0x44,0xdb,0xcf,},{0x11,0x2f,0x5c,0x6d,0x3b,0xcb,0x3d,0xd9,0x93,0x46,0xd3,0x2a,0xd6,0x9c,0xbf,0xac,0x3e,0x65,0x3b,0xef,0x29,0xc6,0x8a,0x33,0xf4,0x32,0x31,0xf6,0x6c,0xea,0x1d,0x0a,0x19,0x54,0x27,0xd6,0xe1,0x0c,0x0e,0x77,0xc5,0xd5,0x5f,0xe2,0x79,0x42,0x87,0xee,0x32,0xe5,0xe2,0x2b,0xaf,0xbb,0xd8,0x05,0x2a,0xd3,0x60,0x6b,0x90,0xf9,0x45,0x05,},"\x04\x98\xa5\x9b\x87\xcd\xae\x28\x69\x55\x47\xe1\x08\x63\xbc\xe8\x04\xd9\x7d\xe0\xac\x80\x08\xf3\xd5\xfb\x65\x2c\x17\x57\x41\x9f\xdc\x9e\x0f\x97\x36\xf4\xc5\x9a\x34\xf2\x1c\xfc\x74\x59\x9f\xa7\x88\xfc\xc1\x0c\x67\x30\xc7\xdf\x8c\x3d\x2c\x1b\x6a\x78\x6d\x12\x30\xb6\x55\x85\x71\x9d\x1c\xb5\xc4\x90\x35\x9b\x94\x43\x5d\x6d\xd6\x71\xf5\x4d\x6e\x9a\x19\xb9\xb5\xaa\xad\x7e\x0f\x23\x3f\x87\x97\xdf\x99\x78\x28\xd8\x8c\xd9\x2e\xf0\x89\xef\x7d\xbf\x1e\x95\x27\x78\x94\xa2\xf7\xc2\xfd\x0c\x8e\x4d\xfd\xfa\x6d\x3d\x14\x58\x9f\xf0\x19\x16\xdb\xf9\xdd\xd8\x11\xc2\xf5\xe0\x1e\x94\x29\x89\x90\xa1\x45\xa6\xcf\xc2\x68\x95\x61\x4c\x7c\x96\x3f\xef\x30\x8a\x4e\x38\x56\xc3\x2d\xd3\xe3\x59\xbc\x56\xd2\xcc\xa4\x96\xad\x19\x9f\xf1\xa5\x68\xd6\x43\x0a\xc5\xcd\x20\x8e\x0e\x2d\x07\x80\x3c\xa5\x23\xe0\xd8\x13\xad\x37\x33\xab\x50\xbd\xca\xdc\xb9\x88\xae\xe7\x58\xea\x50\x43\x9b\xf3\x8e\xe6\x49\x99\x76\x04\xf1\x51\xc6\x02\xc8\x29\x00\xa8\x20\x5d\x8f\x6f\x67\x0c\x86\x84\xbf\x5a\xbb\x5f\x75\xff\x29\xa3\x7e\xb9\xbf\x81\x05\x19\x9f\xbb\xfb\x47\x07\xe1\x62\xe6\x4c\x71\x52\x70\xf8\x53\xe6\x48\xb0\xaa\x26\xfe\xa0\xf6\xdb\x56\x28\x96\xbf\x42\x4a\x9f\xfc\xb2\x92\xfa\xe8\x5b\x76\xce\xfb\x8b\xd5\xa4\xb3\xce\x1f\xb3\x9b\xd2\xa5\x0d\x0c\x9e\x6d\x93\x3e\x16\x7f\xf6\x29\xb8\xa4\x94\xf2\xa9\xb7\x74\xeb\x30\x3c\x78\x1e\xa0\x2a\xff\x1a\x8a\xfa\xdc\x24\x65\xcc\x61\x69\x68\x01\x5e\xd6\xa5\xa3\x3c\x31\x20\xb9\x45\xed\x53\x51\x98\x1e\x32\xfb\x9f\xb9\x6b\x22\x12\xdc\xf8\xfe\x9a\xc5\x6e\x3c\xf4\x1d\xc5\x24\xf8\x00\x63\x10\x20\xb0\x25\x91\x91\x78\xce\x07\x4e\xef\x07\x8d\x68\x42\x01\x2a\x27\x6e\xfa\x62\x8d\xb5\x40\x58\xd1\xeb\x5b\x5b\x70\x5f\x1e\x18\x18\xd2\xdf\x51\x64\xba\xab\xb0\xc6\x19\x56\xec\xdb\x8c\x70\x6e\x56\x2f\xc4\xfd\x64\x05\x28\x70\x53\x0a\xe4\x25\xb2\x21\xf8\x9d\xd6\xf9\x0d\xab\x88\x2e\x76\x3e\x7a\x7f\xfa\x14\x1b\xba\xa8\xbf\x7a\x3f\x21\xb0"}, -{{0xce,0xfc,0xfc,0xd1,0xcf,0xf4,0xd8,0x91,0x07,0x49,0x27,0x91,0x31,0x83,0x0b,0x1d,0xa1,0x9d,0xfc,0x52,0x45,0xf7,0x8c,0xa6,0x8b,0x8c,0x3c,0x1b,0x62,0x2b,0x45,0x51,},{0x1d,0x39,0x4a,0xbd,0x1b,0x4e,0xd1,0xae,0xdf,0x96,0x6a,0x60,0xef,0xd3,0xff,0x88,0x21,0x40,0xa7,0xe5,0x6b,0x42,0x83,0x74,0xec,0xb4,0x43,0x28,0x9a,0x9c,0x7f,0x00,},{0x7d,0x83,0xff,0x66,0xec,0x79,0x30,0x7b,0x1c,0x0c,0x09,0x3f,0xda,0x39,0x68,0xa9,0x6c,0xf6,0x04,0x4f,0x5c,0x80,0x28,0x88,0x58,0x40,0x18,0x84,0x5e,0x7c,0xaf,0x2a,0x13,0x5a,0xc6,0xf1,0x67,0x7e,0x84,0xd2,0x2e,0x45,0x8e,0x22,0x7e,0x4f,0x93,0x02,0x09,0x91,0x9b,0xc1,0x1b,0x12,0xf7,0xaa,0xf2,0xb8,0xc9,0x43,0x02,0xd6,0x42,0x00,},"\x5e\xc9\x4e\xd0\x6f\xc1\x25\x7a\xe9\xc1\x83\xce\x56\x27\x12\x07\xac\xa3\x7a\x23\xfd\xb4\xb0\xe7\x4a\xc9\x30\x7a\x1b\xb1\x12\xe0\x5e\xd5\xa5\xd0\x47\xc9\x31\x09\xe2\xe5\x94\x77\xb0\x33\x78\x34\x64\x22\xde\x36\x71\x4c\x29\x61\xbb\x97\x36\xa5\x13\xca\x36\x71\xc6\x03\xa6\x8c\x2b\xe7\x31\x7b\x1b\x52\xa0\x76\xda\xe2\xaf\xf7\xbc\x88\xcd\x5e\xea\x0a\xa2\x68\xfa\xaa\xda\xe5\x39\xc9\x38\xbb\x4f\xd4\xb6\x06\x9b\x19\x45\xeb\x6a\xf0\xc9\xe6\xc8\xaa\x5e\xe4\xa4\xaf\x37\xe9\x0c\x67\xe2\x48\xe8\xd2\x7b\xd7\xf9\x58\x9c\x4d\x30\xe9\x05\x65\x1b\xaf\x45\x36\x4f\xa0\x49\x95\x7e\xa5\xd9\xb7\x14\x6c\xa6\x82\x04\xe5\xe9\x73\xd0\xf1\xc9\x1a\x1c\x4b\xde\xd6\x61\x15\x02\x8a\x71\x11\x4f\x0f\x4f\x85\x1b\xd1\x15\xfa\xeb\x95\x4e\x3f\x71\xa0\x14\x70\xb2\x48\x1a\x00\x98\xd9\x9f\x9d\x74\x89\x8c\x8b\xa0\x28\x7c\xc7\x83\x41\x55\x21\x41\x73\xd1\xfc\xba\xfc\xfe\x9b\x08\x25\x03\x84\x43\x94\x76\x05\x58\x83\x83\x38\x16\xc9\x52\x4c\xfd\x57\x44\xaa\xa2\x59\xdb\x7e\xbd\x3a\x6a\xa2\x0b\x5a\x65\x46\xda\xde\xfd\x14\x06\x68\xeb\x0e\xcc\xb5\xf6\x68\xdb\x9f\xc6\x29\x83\xdf\x98\x08\x50\xc9\xd1\x98\x82\xa1\x75\x50\xd5\xdc\xa3\x54\x2c\xd3\x60\x03\xa0\xd0\x3c\xff\xb0\x45\x75\xa3\xe8\xe1\xd0\x70\x15\xc7\xb3\x0e\xca\x91\x15\xcd\x2b\x72\xe4\x6d\xfd\xdf\x6a\x4d\xda\x1f\xaa\x2d\xbd\xc8\x90\x00\xd4\x33\xf6\xec\x9a\xdc\x46\x14\x6d\x93\x9f\x32\x12\x1b\x99\xb2\x89\x83\xd9\x8b\x9d\xde\x8c\x3f\x6e\x57\x79\xf2\xb0\x70\x0c\xb0\x23\xdb\x13\xde\x65\x6e\x0a\xed\x1d\xa2\xd5\xc6\xba\x26\x52\x34\x36\x48\xad\x42\x0f\x6a\xb9\xe5\x5a\x97\x48\x2a\x1a\x22\xb3\xbc\x2e\xe5\x98\x62\x9a\xba\xd9\x54\x7e\xdb\x5f\xf7\x90\x99\x05\x64\xbd\x87\x1f\x81\xb2\x4b\x12\xf2\xbf\x8d\xbd\xfe\x7a\x88\x37\x5f\xad\x9c\xcb\xd9\xfc\x0b\xa1\xd3\xbb\xa5\xe3\xc4\x81\x3c\x18\xa0\x34\x8a\xad\x83\xfb\x1b\x82\x68\x90\x54\xd9\x9b\x46\x00\xdd\x17\x60\xd0\xdc\xce\x44\x75\x74\x67\xbe\xc1\x94\x64\x06\xd5\x30"}, -{{0xd1,0x07,0xcf,0x26,0xf5,0x27,0xdb,0x71,0xa2,0x06,0xe4,0x1d,0x17,0x95,0x53,0x21,0x01,0x32,0x25,0xbb,0x20,0xf9,0x3e,0x12,0xdf,0x3d,0xc7,0x39,0x9e,0x72,0x0c,0xa3,},{0x18,0x6b,0xf4,0x53,0xc9,0x5d,0xc0,0xa2,0xfd,0x58,0x9a,0x78,0xe2,0xc8,0x00,0x40,0xb3,0xf6,0xdd,0xf9,0xa6,0xf8,0x68,0x1d,0x14,0x60,0x36,0xcf,0x21,0x46,0xe8,0xfc,},{0x80,0x71,0xd9,0x7f,0x32,0x4f,0x10,0x35,0x8f,0x13,0xac,0x8c,0x61,0xd4,0x24,0xb4,0xf3,0x00,0xdd,0x04,0x19,0x57,0x1c,0x39,0xe4,0x0d,0x99,0xae,0xa5,0xf0,0x31,0x40,0xe6,0x2a,0xb4,0xc9,0x71,0x27,0xab,0x33,0xe9,0x82,0x69,0x96,0x6a,0xe1,0xd4,0x55,0x7e,0x45,0x9b,0xf7,0xf5,0x97,0xb3,0x13,0xf3,0x51,0xa2,0x01,0x22,0xf0,0x66,0x0e,},"\x78\xeb\x9e\x13\x78\x99\x28\xa7\x4f\x36\x01\x41\x72\x8e\xde\x98\x38\x96\x85\xc8\x36\xb9\x1f\xaf\xbf\x1a\x7e\x8c\x19\xcf\xbe\x21\xbd\x3c\x3d\x6c\x6e\xd8\x3c\x40\x9e\xf6\x93\xf1\xd7\x35\xda\x3f\xa4\x66\x49\x7e\x19\xf3\x8e\x30\xfb\xa2\xa1\x02\x37\x85\x45\x90\x70\xe6\xe9\x2c\x1c\xb7\xc9\xbd\x0c\x9b\xa6\x12\x20\x15\x78\x66\xc3\xbe\xd2\xb0\x1e\x6e\x6b\x9b\x8d\xd3\xf0\xc4\x7c\x02\xf1\x81\x34\x6a\x0a\x9b\x9b\x5d\x3d\x7e\x18\xa9\x4d\x69\x56\x85\x5e\x16\xe8\xea\xaa\xab\x71\xb1\x03\x02\xf3\x5b\xd8\xfb\x1f\x9b\x58\x47\x30\x41\x60\x32\x49\x26\x64\x5b\x05\x82\xc2\xf2\xf1\x53\x3a\x24\x28\x14\x61\x51\x42\x41\xdb\x28\x50\xef\x31\xc5\x76\x3b\x2e\x3d\x4f\xb1\x8f\xc6\xd8\xc1\xd7\xe5\x2f\x7c\x13\x39\x2c\x17\xe2\x70\x19\xff\x60\x00\x8e\x43\x1f\x17\x14\x37\x0b\xc0\xef\xd9\x45\x2a\x61\xf5\xc5\x64\x88\xd9\x1a\x18\x50\x37\xf1\xf6\x47\xf7\x2f\xa7\x85\x01\x0d\x5d\x78\xf0\xa1\x15\x87\xcc\xf6\x6b\x80\x88\xe0\xe6\x35\xff\xf3\x77\x41\x93\xb2\xed\xef\xfd\x92\xd6\xe8\xa0\x32\x11\x28\xae\x64\xcd\xb8\x62\xe6\x31\xe2\xee\x5b\xa0\xda\x44\xbb\xd5\x89\xdc\x39\x2b\x5a\x11\x3b\x86\xa7\x27\xa8\xdd\xb6\x98\xa3\x34\xcc\x66\x8b\x39\xb1\xcd\xe1\x99\xb8\x88\x37\xca\x5f\x00\xf5\x53\xf8\x9c\x62\x28\x34\x27\x36\x41\xd3\x9b\xc1\x0c\x6a\x24\xe1\xeb\x42\x58\x75\x42\xf0\x3f\xc1\x62\x75\x24\xed\x6b\x74\x93\x91\xf1\x10\x28\x70\x6c\x42\x36\x44\x25\xb2\xca\xf2\x01\x80\xe1\xb8\x02\xc7\x44\xb4\x9b\x7b\xcd\x9b\xf7\xb1\x5c\x23\xa0\xbf\x1c\x69\x65\x96\x0d\x34\x15\x54\xe1\x96\x6b\x6e\xf8\x2f\xcf\xbb\xe4\x1d\x1e\x09\xd7\x41\xe3\x09\x25\x44\x46\x77\x7f\x13\xc2\x9a\x67\xb8\xbd\xeb\xc5\xf7\xf0\x4d\x16\x0d\x60\xe3\x32\xe3\xd0\x44\x1a\x0f\x2f\x7b\x19\x2c\x3e\x2b\xdf\x6d\xad\xec\x2a\x42\x4f\x88\x66\x98\x06\x23\x6e\xe0\x4d\xea\x69\x2b\xd8\xbb\x6f\x91\xca\x06\x82\xec\xe3\x49\x14\x25\x75\x35\x8b\x9b\x7b\xe7\x06\x00\xb3\xcb\x81\xe1\x45\x6b\xa0\x79\x9f\xdc\x01\xff\xd6\x86\x23"}, -{{0xaf,0x7e,0xa8,0xe4,0x1c,0x89,0x37,0xa4,0xec,0x47,0x5a,0xd8,0x13,0x71,0xa1,0x71,0xd3,0xd0,0xf9,0xfd,0x75,0x19,0xa0,0x4c,0x75,0x1e,0xd4,0xad,0x8f,0xf8,0xfe,0xf9,},{0x15,0xdf,0xc7,0x15,0x85,0xba,0xc7,0x1e,0xf2,0x0f,0x37,0x49,0x87,0xc5,0x55,0xa3,0xf2,0xf0,0x7d,0x6b,0x9c,0x78,0x70,0x66,0xc1,0x0d,0x63,0xcf,0x06,0xe0,0x2a,0xb0,},{0xc0,0xf1,0x73,0x91,0x67,0x27,0x4b,0xf9,0x18,0x31,0xc7,0x4b,0xeb,0x64,0x5a,0xf7,0x90,0x45,0x9b,0x28,0xbb,0x3f,0x21,0x32,0x53,0x65,0x13,0x0f,0x40,0x9a,0xcb,0x66,0xdf,0x1d,0x22,0x37,0x59,0xa9,0x75,0x8e,0x08,0xfd,0x72,0x53,0x73,0x74,0x84,0xe2,0x85,0xa6,0xfb,0x47,0x40,0x4a,0xbe,0x2e,0xba,0x5e,0xf2,0x49,0xfd,0x02,0x5c,0x0a,},"\x05\xf2\x26\x3f\x02\x45\xec\xb9\xfa\xeb\x14\xe5\x7a\xca\x43\x66\x68\x30\x8c\x81\x25\xdf\x31\x16\xc4\xee\x20\x50\x1d\x0c\xde\x70\x1b\x36\x6e\x2b\x50\xa1\xc5\xed\xf4\x84\x14\x4c\xe1\x6b\xfb\x1f\x7d\x26\xdc\x42\x75\xea\x97\x32\xe2\x64\xba\x4d\x4a\x36\x2b\x40\x27\x5b\xa4\x73\x77\xdb\xc3\x32\xcb\x65\xe2\xf4\xc8\x85\x38\x94\xaa\x87\x8a\x4c\x17\x5d\xc5\xb3\xb2\xa7\x57\xff\x3c\x8d\x7d\xe6\x60\x97\x3b\x89\xda\xdf\x07\x6e\x2e\x4f\xc7\x62\x39\xb7\xbc\x75\x2a\x22\x9d\x44\xe0\x00\xce\xb6\x67\x10\x4c\xb0\x74\x6b\xfc\xf5\x9d\x69\x60\x3a\xe7\xfc\x1b\xcf\x11\xd2\xe3\x3f\x61\xdc\x49\x7e\xc1\xb0\xbd\x5e\x4f\x1d\xbe\xf4\x35\xf2\xf2\x91\xf3\x0b\x00\xa8\x5e\x83\x39\x46\xc8\xb1\x04\x84\xe4\xab\xd7\xd6\x0b\xdb\xb1\xfe\x6d\xff\x58\x07\xa5\x3b\xb8\x93\x82\x15\x30\x13\xb7\x0c\xa0\x8e\xfc\x91\xb7\xe9\xfc\x5b\x5d\xbb\xb6\xaf\x12\x3b\x57\xbe\x2e\x14\x0f\xc4\x71\xa4\x5d\x89\xfa\x82\x84\xcc\x27\xe0\xa1\xfe\x77\x1f\x55\x59\x8b\xbd\xcf\x06\x8d\x50\x6d\xad\x0a\x59\x21\x79\xce\xca\x39\xee\x95\x26\xf9\xe4\xfe\x47\xbf\x2b\xb1\x4f\xb1\x48\x6a\x67\x7d\x4d\x7b\x99\xa5\x20\x54\x56\x76\xa0\xf1\xfa\x80\x90\x49\xaa\x24\x14\xae\x7b\x81\x7d\x9a\x03\x6e\x5c\x15\x78\x86\xe8\x34\x1d\x4e\x81\x9c\x09\x2a\x3b\x48\xb3\x60\x6b\x03\xac\xb7\x27\xc6\xc2\x21\x7d\x0a\xf3\x01\x21\x54\x6a\x94\xaf\x6b\x49\xca\xa2\xa8\xc9\xb1\x78\x6f\xa0\xc2\xa5\x24\xec\x7a\x02\x3e\x92\x4b\x5f\x8a\x89\xa5\x37\x80\xc7\xf8\x78\x1c\x5b\x8e\x86\x94\x30\xca\xa0\xe6\xd0\x43\x79\x67\xe3\xae\xd4\x4f\x45\xc9\x01\xcb\xcf\x10\x26\xfb\xbd\x4e\x3d\xd9\xa0\x91\xec\xf8\xb3\x4f\x7d\xd5\x03\x8e\x54\x3d\xc7\xeb\x6a\xd5\x49\x4e\xfb\x14\x5c\xf6\x3e\xc0\xd3\x55\xbb\x8e\x17\x2f\x45\x5d\x8a\x6b\x13\xda\xca\xad\xdb\xc5\x6e\x47\xde\x3c\xf7\x62\xa1\xa7\x38\xef\x09\x2f\x14\x36\x68\x04\x67\xb5\xcd\x82\xe9\xe3\x6e\x2d\x2b\x68\x42\xb3\xbd\x5d\xce\x77\x18\x0d\xda\xf0\xb6\x43\x37\x8e\x69\x85\x99\xdd\x47\xf5\xcd\xbb"}, -{{0x0c,0x57,0xcb,0xfc,0xeb,0xde,0x10,0xed,0xe0,0x2d,0x1c,0xb0,0x1d,0xf3,0x60,0xd4,0x1f,0x2e,0x66,0xa5,0x04,0x43,0xd5,0x8b,0x5d,0x4f,0x08,0x28,0xc9,0xa1,0x8b,0xb7,},{0xc4,0xd7,0x61,0xba,0x18,0x99,0x71,0xb9,0x46,0x2c,0x61,0xbf,0x46,0xa7,0x65,0xf8,0x8e,0x2e,0xca,0xa5,0xbf,0x22,0x11,0x22,0x0a,0xfb,0x00,0xac,0x65,0x7f,0x7c,0xe5,},{0x8a,0xf7,0xbb,0xe0,0x1b,0x8a,0xb9,0x39,0x51,0xd1,0x6f,0xca,0x05,0xa9,0xc9,0x67,0xd1,0xc5,0x2c,0x97,0x4b,0xea,0x15,0x1e,0xa7,0x2e,0x4c,0xeb,0xaa,0x20,0xcc,0x78,0x3b,0xb6,0x1d,0x8d,0x69,0x38,0x5c,0xac,0x5b,0xc6,0xd7,0x2d,0xbd,0x16,0x2b,0xee,0xf1,0xfc,0xb5,0xdd,0x0e,0x0a,0x08,0xb4,0x8c,0xa0,0xb9,0xf6,0xd9,0xa9,0x88,0x0c,},"\x33\x77\x03\x24\x3a\xb5\xb4\xe4\xd3\x48\x1e\xe8\xdd\x1f\x44\x94\x50\x71\x74\x41\x26\x58\xa9\x39\x88\xb5\xc3\x04\x03\xa7\xb7\xed\x85\x22\xce\xb4\x6f\xa1\xee\x02\x75\x3a\x87\x4e\xf0\x67\x5d\x39\x7c\x57\x5d\xa0\xb0\x8c\xaa\x8c\xee\x33\x93\x78\x4d\x0f\x0d\xb8\x45\x98\x37\xaf\x90\xb9\x05\x6d\xf4\xe3\x8e\x41\x7f\x3a\xd2\xeb\x1a\x10\x0e\xf2\x07\xce\x2c\xa6\xc6\x10\x01\x80\x21\x66\x1e\x30\x70\x99\xf2\xb7\xc4\xae\x87\x59\x91\x14\x0b\xdd\x3f\x0f\x99\xad\x2c\x5d\x55\xaa\xcb\x84\xcc\x1c\xdc\xd5\x79\xe0\x80\x72\xb6\x95\x1f\xd4\x5e\xd2\x89\xac\x9f\xf7\xf0\x98\x6a\xc8\x8a\x4f\xbb\x9d\xc9\x20\x3d\x9b\xaf\x18\x0c\x90\xed\xf9\x37\x25\x8c\x9d\x0a\x6d\x48\xe2\x20\xf7\x2d\x25\x0c\x7f\x2c\x77\x7e\xaa\x7f\xb9\xfa\x11\xd5\x0a\x57\x98\x77\x2f\x9f\xd9\x76\xb0\x05\x99\xf1\xf0\x27\x6f\x3a\x2e\x4d\x98\x8a\xe9\x21\x25\x46\x7a\x8d\xed\xb7\xa1\x6f\x9e\x3a\x56\xe8\xd0\x06\x62\xb3\xeb\x67\xa3\x5b\x9b\x60\xe7\x3b\xd9\x35\x07\x7e\xe2\x38\xdf\x8f\x6e\x83\x3b\x9a\x55\x23\x38\x68\x26\xc1\xf2\x91\x7b\x1c\x3e\xc9\x8e\x0a\x5f\xde\x89\xc4\x8b\x1d\x44\x6d\xa5\xd0\xc8\x85\xfe\xf0\xe3\x74\xbf\xf3\x0a\x99\x7c\x7b\xaf\xd5\xe7\x43\xc8\x5d\x0c\x6a\xaa\x6e\xf1\x0a\x06\x12\x11\xa2\x32\x7c\x6d\x84\xeb\x74\x7a\x56\xe9\xbf\x60\xfc\xd5\xb5\x53\xb7\x98\x83\x4d\x0c\x5c\xca\xdb\x9d\x4b\x54\xe7\x23\x7d\x12\xc6\x79\xc1\x93\xa2\x87\xbb\x2f\x51\x1c\xd4\xee\x2a\x2d\x85\x49\xb4\x4b\x21\xc1\x1f\xbe\x57\x23\x38\x1c\x6c\x5f\x78\x46\x87\xfd\x90\xce\xbc\x5b\x49\x5a\xf9\xe4\x14\xf2\x96\x1b\x06\xa1\xc8\x43\x3b\x9a\xa3\x29\x2b\xcf\xf4\x24\x1c\x22\x71\x67\xf8\xd1\xde\x05\x4b\xa3\x3a\xd8\x1d\xa3\xeb\x3e\xc6\xe4\x0a\x6e\x26\x85\x4a\xf3\x49\x54\x01\x71\xb7\x5d\x75\xfb\x9a\x8d\x12\x93\x78\x27\xfd\x59\x4d\x31\x7b\x7a\x8d\x9f\x1c\x2f\xca\xbd\xa5\x63\x75\x56\x8c\x3e\x9e\x51\x4c\x2e\xff\xfc\x38\x78\x36\x3d\xcf\xad\x9f\xd9\x54\x36\xb0\x22\xe8\x77\x2a\x88\xcb\x71\xe8\x03\xbf\x90\x38\x19\x62"}, -{{0xfe,0x71,0x72,0x27,0x83,0x64,0x19,0x4b,0xcf,0xef,0xb4,0x78,0x31,0x42,0xb7,0x9f,0x59,0xd5,0xfd,0x97,0x8b,0x1e,0x47,0xc3,0x14,0xd7,0x8d,0x4c,0xb3,0xf6,0x1c,0x8a,},{0x2e,0x82,0xcc,0xe4,0x79,0x10,0xc7,0xe2,0xa7,0x9b,0xc1,0xf4,0x19,0xdc,0x3c,0x3d,0xf5,0x4f,0x23,0x29,0x1f,0xc8,0x19,0x3e,0x82,0x58,0xcc,0xd2,0xfd,0x38,0xd5,0x48,},{0xf6,0xc2,0xa4,0x29,0x6b,0x9a,0x34,0x07,0xc6,0xd7,0xa5,0x67,0x9d,0xae,0x86,0x66,0xb5,0x03,0xd1,0xa1,0x7e,0xac,0xf7,0x1d,0xf4,0x93,0x79,0x1b,0x8f,0xf0,0xc0,0xaa,0x8e,0xed,0x36,0xb3,0x27,0xa2,0x9a,0xb7,0x82,0x8f,0x46,0xf2,0x2d,0xe8,0x68,0xb6,0x28,0xb1,0xcf,0xd5,0x01,0xe8,0x59,0x9f,0xa3,0x16,0x93,0xb1,0x5f,0x61,0x08,0x0f,},"\x23\x50\x94\x51\xa0\x59\x96\x9f\x2b\x4b\xdf\xce\xe5\x38\x89\x57\xe9\x45\x6d\x1f\xc0\xcd\x85\x7e\x4f\x4d\x3c\x25\xa4\x15\x5d\x5e\xe9\x1c\x20\x53\xd5\x58\x06\x2e\xea\x68\x27\x95\x0d\xe8\x63\xbc\x9c\x3d\xf9\x67\x2c\xde\x8b\xa7\x41\x74\x4e\xbb\xdd\xb4\x5e\xc1\xf4\x28\x45\x70\xfd\x0a\xac\xd0\x7e\xa5\x8c\x58\x1b\xe2\xaf\xc9\x5a\xe4\x44\xe6\x78\xed\xc2\xa0\x24\x39\xf3\x87\xce\xc9\x82\xea\x3a\x44\x81\x4a\x8a\x30\x2b\xb3\xbf\xe8\x22\x8d\x58\xde\x03\x9d\xeb\xdf\x7c\x2a\x7e\xdd\xb4\xe7\x1c\xa4\x74\xf9\x4f\x7e\x2b\xd8\x9d\xc6\x5b\x16\x10\x73\x3c\x91\xff\xf8\x9b\xd4\x99\xf4\x01\x54\xa6\x19\x8f\xdf\x5e\xc7\xad\x37\x22\xd9\x25\xb2\x92\x19\x6c\x42\x94\x99\x07\x5b\xe0\xc5\xb6\xda\x9c\x09\x0c\x07\x91\xa7\x01\x9e\xb5\xe7\x36\x6b\xe6\xce\x58\xab\x2f\x04\xfe\xcd\x91\x27\xc4\x27\x18\x04\x7b\xf4\x70\x30\x69\x15\x21\x31\x2c\x08\x77\xaa\x3f\x36\xcc\x5f\xbc\x9c\xaa\xe0\xfd\xe3\x94\x5d\x2a\x86\x8e\xe2\x50\x2a\x38\x33\x20\x8e\xb8\x50\xa1\x63\xcf\xcb\xf6\xda\x9e\xe6\xad\x9f\xe0\x67\xfe\x24\x19\x86\xfe\x44\x36\xd6\xae\x4e\xdc\x61\x56\x19\x38\xe2\xa3\x3f\x4a\x33\xdb\x63\xf6\x9d\x3f\x1a\x88\x50\xed\x40\x02\x88\x69\x16\x41\x03\x48\x8f\xb7\x95\xcd\x82\xca\x06\x7f\xe1\xb4\x89\x7c\xaa\x49\xa7\xca\x9a\x80\xf3\xa8\x15\x1f\xd1\x3b\xbb\x7f\xf3\x50\xe8\x57\x9f\x56\x5d\xc1\xc4\xa9\xca\x93\x8d\x27\xb1\x5b\x3f\x85\x8e\xf4\x5d\x3d\xd7\x8b\x2c\x35\x86\x35\x35\x63\x15\xf5\x5a\x97\x52\x8e\xcf\xec\x5d\x11\xa5\xb7\x21\x50\x31\x07\xfa\xa4\x06\xc1\x70\x34\xe6\x01\x47\x4b\x3b\x60\xcf\x48\x69\x2e\x26\x92\x61\x15\x8f\xc3\x53\xd4\xdf\x42\x74\x38\x13\x57\x79\x0b\x77\x56\x08\x7b\x00\xcc\x79\xe3\xb9\xd2\x8a\x3f\x24\x39\xfe\xbf\x19\x9e\x64\xa8\xb3\x7c\x91\xb5\xa4\x33\x4e\x33\x54\xe8\xfa\xf3\xa3\x61\xe8\x56\xc5\x4b\xda\xa4\x3b\xfd\xcd\x6e\xe6\xc9\xf9\x67\x95\x88\xf6\x06\x99\x50\x83\x23\x48\xaa\xcb\xa2\xbf\xee\xba\xca\xa2\x07\x1d\xdc\x7d\x77\x89\x8e\xf0\xf6\x87\x93\xcd\x25"}, -{{0xa9,0x51,0xe4,0xe6,0xba,0x9f,0x1f,0x0b,0x35,0x48,0x31,0xc9,0x86,0x94,0x24,0x48,0xfa,0xed,0xe3,0x7e,0x11,0xb0,0xf2,0x47,0xda,0x27,0x06,0xdc,0xee,0xf7,0x3a,0xc7,},{0x30,0x36,0x20,0x14,0x97,0x4b,0xf7,0x5c,0x84,0x95,0xc2,0xe2,0x71,0xe7,0x13,0xd5,0x73,0x84,0x38,0x4d,0x0a,0x5d,0xa8,0x8e,0xde,0xea,0x79,0x27,0x9c,0x0c,0x58,0xec,},{0x02,0x78,0xc8,0x6a,0x15,0x20,0x8d,0x9b,0xe5,0xb1,0xe1,0x57,0x47,0x61,0x86,0x1b,0x8a,0xf7,0x2a,0xe0,0x8d,0x40,0xcd,0xcb,0xec,0x35,0x4e,0x65,0xa9,0xc3,0xd0,0xa0,0x6b,0x5f,0xcb,0xb2,0x97,0xd0,0x9b,0xef,0x39,0x74,0x62,0x39,0x59,0x86,0xc3,0x09,0x3e,0xeb,0x22,0x64,0x4c,0x00,0x3c,0x30,0x78,0x17,0x8c,0xdf,0x67,0x4e,0x99,0x0a,},"\x20\x57\x7d\xca\xc8\x91\x74\x88\x5e\xed\xb0\x62\x48\x9c\xd5\x12\xfa\x72\x86\x3e\xc5\x43\x8e\x31\xe9\x58\x78\xb7\x5c\xe2\x77\x2a\xee\x62\x90\xa0\xba\x3c\x8f\x64\x2c\x1d\x0e\xf5\x5d\xa8\xd5\xbc\x14\x84\xf8\x3b\xb9\x87\x6c\x7a\x8c\x0b\x6b\x60\x9b\x94\xd1\x12\xa0\x6f\xc8\x3c\xe8\xd2\xc1\xe0\x8e\xd6\xc7\x35\xe5\x7b\x24\x4a\xad\x6e\xcf\x70\x75\x36\x3d\x56\x5b\xa4\x78\x65\x69\x5c\x84\x23\x51\x09\x09\xe0\xa3\xdb\x4b\x61\xed\x7a\xa6\x7a\x74\x71\x33\x1e\x83\xa0\xc5\x8b\x82\x20\xa6\x24\x5f\x65\x66\x15\x49\xc1\xa1\x2d\x4c\x0d\x50\xc3\x26\xfb\x94\x91\x7c\xbd\x07\xbe\x51\xe8\x3f\xe8\xbb\x3e\x46\xca\x01\xb0\xa2\x60\xda\xaf\x1d\x6a\xbe\x37\x03\xd6\xa9\x25\x11\x3b\xb4\xd5\x7e\xa1\xa4\x8b\x4c\x7d\xbd\xaa\x03\xee\xa8\x14\xa4\xb5\xf0\x2e\x1d\xfb\x54\x5c\xc6\x23\xfe\x17\xa3\xbb\x18\xe4\x37\x3f\x5f\x7e\xc2\xfb\x52\x17\xd2\x3e\x4f\xed\x54\xa7\x72\xe1\x13\x23\xe7\x30\xaa\xd7\xef\xca\x8c\x46\x44\x00\xe7\x67\x90\x55\xfc\xc1\x25\xa8\x76\xef\x7b\x8b\x9d\xe1\x86\xe2\x29\xa7\xab\xf1\x91\xd0\xc5\x6d\x91\x81\x5f\x67\x87\x2e\x95\x7b\xfb\xc7\x63\x4a\xac\x40\x35\x76\xa5\x8f\x42\x7b\xdb\xb3\x0e\x8c\x4b\x6f\xc6\xc4\x47\x74\x10\x24\xeb\xb5\x03\xa5\xa9\x02\x51\x24\xa4\x88\x7f\x82\x5a\x43\xee\x94\x0f\x21\x0a\x1b\xd5\xae\x4f\x67\x32\xd6\x0f\x95\xf2\xb8\x32\x01\xc4\xc6\xdf\xe2\x79\x41\x2d\x75\x02\xa5\x21\x1f\x8f\x48\xf8\x00\xdb\x30\xfc\x37\x76\xc4\xed\x3a\x38\xbb\x46\x34\x82\x2c\x98\xa6\xd6\xdd\x32\x33\xbe\x60\xe4\x2c\xca\x45\xa3\x16\x3c\xc8\x4e\x9e\x8d\xa6\x47\xc0\x71\x1b\xc4\xc6\xcc\xd6\x5a\xa1\xe9\x72\xc0\x74\x04\xd1\x03\xe7\x4b\xcc\x31\xa7\xe2\xc3\xee\xa5\xac\x92\x57\xab\x42\x89\x47\xab\x3d\xd3\xfb\x15\x3d\x90\x69\x4a\x40\x73\x37\x3c\x4d\xd9\xce\xb1\x31\x15\x4f\xe8\x77\x47\x3f\xd9\x96\xf4\x24\xf3\x3e\x31\x6e\x4e\xb0\x2b\x8c\x75\x13\xbe\x69\x98\xe5\x16\xcb\xba\x54\xd9\x4c\xd0\xa4\x35\xe0\xff\xcc\x2c\x0a\x8e\xf7\x2b\x63\x0e\xc2\x47\x81\x06\x6a\xa5\xef\xb9"}, -{{0x38,0xa9,0xb2,0xd4,0x9b,0xa8,0xb8,0x2f,0x30,0x1a,0x57,0x72,0xce,0xa0,0xef,0xc2,0x21,0x84,0x55,0xc8,0xb2,0x18,0xb2,0x2c,0xba,0xa2,0xaa,0xd2,0xd7,0xad,0x3b,0x35,},{0x9d,0xf5,0xea,0x1f,0x78,0xf8,0x10,0xa5,0x21,0x77,0x46,0x02,0xbb,0xba,0x49,0x42,0xf0,0x45,0x92,0x38,0x96,0x6c,0x8b,0xcd,0x21,0x90,0x0a,0xfb,0xf3,0xd8,0x42,0x93,},{0xe1,0x9e,0x62,0xac,0x53,0x9a,0x9c,0xa2,0x51,0xd1,0x2d,0x4c,0x71,0x05,0x5b,0x0a,0x3f,0x58,0x1d,0x19,0xf2,0x68,0x2e,0x67,0x24,0x04,0xc7,0x8a,0xc1,0xf1,0x2b,0xbe,0xfc,0x91,0x51,0x92,0x76,0xa5,0xcb,0xe1,0x6f,0x52,0x0c,0xf7,0xa7,0xf6,0x87,0xa2,0x40,0xf0,0x32,0x91,0x57,0xc5,0x9f,0x50,0x02,0x6a,0x58,0xdc,0xdc,0x50,0xfc,0x08,},"\x17\x78\x16\x7c\x49\xb3\xa4\x4d\x4a\x5b\xa8\x38\xb7\x38\x85\x53\xb1\xe1\x3d\x36\xea\x4f\x86\xd3\x02\x42\xe1\xa8\x22\xa3\xbb\xaf\xf5\xce\xa6\x3e\x2a\xe2\xa4\x63\x5b\xe2\x36\xfe\xf2\xb8\x13\x5d\x14\xfb\x62\x1c\x0b\xb7\x73\xc9\xc1\x77\x53\xf8\x09\x26\xeb\x55\xd0\xf1\x15\xbd\x09\xa8\x85\xd8\x44\xb8\x18\xc9\xf0\x44\x89\xa3\x31\xbb\x5e\x03\x2b\x8e\x58\xcd\xa3\x69\x49\xc5\xa8\xd0\x8b\x55\xbb\x8d\xe9\x65\xe1\xf9\x0d\x3b\x9c\xfe\xec\xfc\x6a\xd9\xa4\xee\x5c\xb4\x04\x7e\x94\x50\xac\xdc\x64\x64\x01\x66\xa8\xc0\x69\xea\x84\x9a\xeb\xdd\xac\x1a\xe4\xaf\xec\x91\xdd\xd1\x7f\xa5\x55\x3f\xa8\x7c\x56\xf7\xe5\x1e\xc1\xcd\x6b\x5c\xc2\x33\x51\xd0\x57\xa4\xce\x4a\x89\x23\xc8\xae\x6a\xc7\xa8\xaf\xdc\xc0\x88\x1c\x0e\x74\xeb\xb0\x24\xef\x72\x96\x16\x2c\xb9\x3c\x68\xe5\x0b\xbb\x07\x4e\x65\x1a\xc8\x7d\xac\x9e\xa5\x9d\x4c\x3f\xbf\x0f\xe3\x79\xf3\xe9\x7a\x24\x56\x6e\xca\xe5\x43\x03\xbc\xfb\x6f\x0c\xc9\xf1\x5f\x66\x39\x43\x0e\x66\xb1\x9a\x42\x78\x49\xfd\xff\xf8\x33\xdf\x02\x68\x9e\x9d\xe4\x40\x06\xc9\x03\xc5\x59\x18\x34\x59\xb9\xf4\xa9\x7f\x54\xa0\xf2\xa2\x8d\xf7\xb0\xe9\xde\xed\xa8\x23\x9d\x7b\x51\x69\x77\xf5\xe7\xd6\x97\x1b\x45\x02\xe9\x88\x5f\x75\x0a\xf8\xd1\xa6\x66\x9e\x25\xe7\x7d\x5f\x32\x7c\x77\xc8\x7a\x86\xe0\xa1\x87\x2b\xc9\x6a\x76\x06\x0f\x5f\x8a\x0c\x40\xcc\x97\x3b\xfc\x7f\xe6\xed\x9b\xca\x78\xf8\x84\xe6\xa2\x82\x8b\x94\xd4\x89\xd3\x2a\x0f\xd3\x37\xe6\x9d\xb8\x3f\xb8\x78\x9a\xfd\x4e\x8e\xf5\x4c\x22\xa7\x8c\x25\x87\x46\x8b\x9a\xe0\x71\xba\xe3\xb2\x02\xd3\x18\x3a\xd5\xf0\xf8\xe8\x42\xe5\xa8\xde\x85\xbf\xff\x49\xe0\x3c\x83\x81\xbc\xa7\xfd\x42\x78\xdd\xcc\xaf\x01\x34\xfb\x55\x93\xa3\x95\xa7\x7a\x5c\xbd\x43\x45\x93\xbc\x4a\xd0\xff\x4b\x84\x00\xec\x67\x4c\x4e\xca\xf1\xd5\x77\x54\xbe\x0c\xb2\xfa\x9a\x64\x41\xa9\xab\xad\x7b\x42\x19\x7a\xd8\x2e\x50\x82\x7e\x4a\x42\x45\x57\x3a\x8f\x0e\xf8\x7f\x58\x22\x8a\x28\x67\xf4\xb3\xb8\x34\xb6\x63\x50\x37\x94\x0a"}, -{{0x9a,0x17,0x17,0x87,0x36,0x89,0xa0,0x3c,0x11,0x2d,0xd6,0xb4,0xd7,0x6a,0xe7,0x3b,0x89,0xb4,0x16,0xa5,0x98,0xce,0xec,0x20,0x9e,0x27,0x96,0x1e,0x7b,0xb1,0xee,0x8a,},{0xee,0xca,0xd1,0xe0,0xe4,0xb8,0x63,0x29,0x18,0x81,0xa8,0xc2,0x41,0xdb,0x9c,0xcf,0xff,0xe4,0xe5,0x5d,0x8b,0x5a,0x42,0xf3,0x07,0xb4,0x43,0x6a,0xcd,0x06,0x49,0xa6,},{0x1a,0xf8,0xbe,0x09,0x55,0x38,0x96,0x58,0x00,0xd8,0xef,0xf6,0xd7,0x23,0xd0,0x28,0xd6,0x5d,0x0e,0x9c,0x6e,0xb5,0xe9,0xd1,0x25,0xbb,0x3b,0x17,0x83,0xf1,0x1e,0xf7,0x07,0x9a,0x49,0xa8,0x07,0xe2,0x7e,0xf1,0x26,0x0b,0xe2,0x6a,0x3b,0x23,0x1d,0x03,0xb2,0xae,0x15,0x1e,0x49,0xf6,0xf1,0x89,0xf1,0x5b,0x1c,0x83,0xea,0xb0,0x1c,0x02,},"\xe2\x65\x80\x47\x09\x01\xa0\x7a\xb0\x93\x1a\xa2\x38\x29\x80\x2c\xe0\x4d\xa5\x9f\xdc\x2f\x77\x3b\xc5\x67\xf1\xe6\x5b\x4f\x2e\x2d\x4a\x1a\x6a\xec\x1f\x54\x15\x8a\xdf\xce\x9b\x09\x97\x90\xb5\x03\xa1\x3d\x22\x09\x7a\xe2\x3e\xbc\xcf\x92\x3f\x3b\xb1\x98\x6d\x6e\x49\x11\x1a\x8c\xf0\xd4\xeb\x82\x36\xbf\xe0\xd7\xc9\xe9\x3a\x5e\xfc\x7f\xeb\x8e\x6a\x9c\xd1\xb8\xd9\x21\xef\xa2\x1e\x44\x9f\xf4\x9e\x06\xc1\xcc\xfe\xa3\x1f\x93\xe0\x33\xc3\xc2\xa5\x4d\xdb\x0f\x65\x3a\x09\xfb\xd1\x8a\x70\xb5\x63\x15\xf1\x93\xe7\xbe\x56\xe5\x16\x8f\x59\x56\x38\x21\xd4\xbc\x3b\xbb\x0e\xaa\x20\x48\x28\x6b\xbe\xee\x5a\xa3\xf3\xe7\x53\x6c\xf2\xb7\x50\xfd\x32\x26\x02\xbb\x38\x47\xce\xca\x39\xb7\x54\x74\x32\x2d\x76\xb1\xde\x80\xfa\x2e\xad\xba\x15\x2d\x6f\x8f\x02\x0d\x4d\x93\x1c\x53\xf0\xa2\x80\x12\x24\xd3\x5d\xeb\x6e\xc1\x3b\x01\x48\x73\xe6\x89\x90\x36\x07\xde\x96\xd9\xb7\xa7\x43\xa8\x87\xd2\xf4\x8d\xaf\x2e\xd2\xee\xfb\x20\x2a\xbf\x60\x82\x79\x69\x81\x12\x3b\x96\x6e\x93\x6d\xcf\x34\x83\xe2\xd2\x4d\x69\x4e\xcb\x86\x5f\xbe\xb6\x96\x9f\x34\x70\x27\xfb\x8b\x17\x5d\x24\xa4\xc0\x45\xc0\xbb\x4a\xb5\xe0\x2d\xdc\xbe\x77\xd4\x75\x6c\x46\xd1\x37\xb0\x94\x47\x3a\x02\x30\x7a\x10\x83\x40\xac\xad\x9d\x03\xba\xe8\x40\x3a\xf1\x99\xcb\x75\xca\xe3\x16\x2f\x38\x15\x81\x3c\xc6\x8b\xf2\xa5\xe4\x99\xe5\x94\x92\x11\x49\xf3\xbb\xd2\x14\xda\x51\x37\xe7\x56\x52\x15\x59\xdc\x80\xd9\xa4\xb7\x4a\x0f\x49\x43\x02\x2c\x7c\xd5\xfc\xa4\x23\x15\xe0\xbc\xee\xae\x90\x69\x61\x5c\xe6\x7a\x04\x38\x24\x12\x31\x3a\x31\xd6\x7b\x34\x6c\x32\x9a\xd8\x2e\x74\x2c\x0a\x6c\xe0\xa6\xa0\x24\x54\xc1\x13\xe5\x20\x22\xf3\xcc\x03\xfd\xa6\x91\xeb\xdf\xe1\x4c\x53\xc8\xce\x5c\xa9\xb9\x32\xca\x1a\x38\x6e\x3e\xb4\xe9\x0a\x4d\xc6\xe8\xad\x85\x33\xb5\xaf\x1a\xae\xf5\x00\x31\x28\x65\x5c\xa6\x4f\x67\xfc\xd9\x7c\x6a\xc8\x03\x00\x24\x04\x90\x0b\xc0\xfa\xe9\x84\x63\xbc\xc3\x14\x09\xf9\x98\x17\x48\x78\x9a\xde\x2d\x07\x78\x3b\xc3\x2b"}, -{{0x43,0xbd,0x92,0x4d,0xb8,0x15,0x60,0x08,0xc6,0xb3,0x99,0x4a,0x81,0x30,0xd4,0x27,0xd5,0x14,0xdb,0x8a,0x61,0x3b,0x84,0xdf,0xb0,0xb8,0xe0,0xde,0x6a,0xc3,0x06,0x76,},{0x1b,0x34,0x61,0xc2,0x69,0xd5,0xb0,0x06,0x2d,0x5d,0xf6,0xfa,0x65,0x4a,0x25,0x86,0xf6,0x47,0xa0,0x68,0x42,0x18,0xa0,0x6e,0x5e,0x2f,0x7b,0xad,0xfb,0x39,0x41,0x31,},{0xd2,0xa0,0x5d,0x88,0xd9,0xd5,0x43,0xd9,0x4d,0x57,0xec,0x88,0xae,0x55,0x68,0x17,0x50,0xf2,0x0b,0x9b,0xe9,0xc1,0xe9,0x18,0xcd,0xaf,0x45,0x77,0x67,0xf2,0x94,0x8d,0xd6,0x29,0xe9,0x4f,0x06,0x8e,0xdc,0xf3,0xd9,0x92,0x7e,0x33,0x02,0x34,0xba,0xdc,0x3a,0x02,0xfa,0x5a,0xd3,0xd9,0xd8,0x5e,0x94,0x8c,0xb0,0xb0,0xcb,0x3c,0xd7,0x0a,},"\x61\x84\xe6\x48\x0c\x42\xe9\x6c\xc8\x77\x26\x9b\x16\x37\x15\x45\xff\x95\x23\xc4\x5e\xa8\x8e\x76\xa1\x34\x8c\x68\xae\x7f\x31\x8b\x08\x8f\xe4\x61\x09\x28\x23\x91\x85\xb6\xb5\x5b\xfa\x0f\x43\x64\x4c\x4a\x4c\x97\xc5\x6e\xd7\x7d\x08\xb1\xf4\xaa\xd2\xf4\xaa\x06\x99\x94\xab\xec\xa9\x6b\x7b\xf8\x1b\x80\x64\xea\x43\x50\xd8\xa8\xb0\x22\x97\xa5\x13\x08\xb6\x1c\x57\xc8\xf1\x87\x3c\x6f\x97\x00\x7a\xca\x31\x80\x42\x9e\x73\x0a\x66\x43\xf2\x87\x33\x54\x7b\xcf\x7b\x9a\xdf\xe3\x27\xe8\x57\x36\xbd\x04\xaf\x7f\x1d\x9f\x4f\xb8\x4a\x7f\x3a\xff\xdf\x4e\x22\xb5\x74\xec\xb4\xbc\x88\x36\xb1\x0b\x84\x53\xae\xaa\x5c\x1b\xf1\x32\x24\x8b\x82\x6c\xc5\x23\x0f\x75\xe0\x75\xfa\xc9\xf0\x37\x56\x11\x36\xe0\x06\x43\xd0\x82\x53\xe7\xad\x65\x2f\x70\x2c\x0d\x15\xb6\xd7\xd4\x8a\xa6\xf8\xe9\xb5\xf5\xcc\x14\x6e\x3f\x15\x6f\xb2\x52\x27\x51\xc3\x71\x00\x41\xbd\x92\x2f\x37\xa5\x03\x77\xe0\x28\xb0\xc4\xe4\xbc\x34\x65\xd7\xc8\x4a\xf6\xa5\xfb\x42\x7a\xcb\x3b\x41\x37\x8b\x10\x2b\xda\x46\xd8\xf6\xf2\x03\xa5\xff\xcf\x39\x5d\x43\x5e\x93\x45\x8a\x0b\x0a\x4c\x2e\x77\x82\xfa\xfe\x11\x9f\x76\x9f\x67\x05\x8c\x66\x77\xf6\xd1\x0d\x9c\xf5\xcb\x87\x48\xe1\x80\x57\x98\xed\x23\x3f\x6f\x93\x0e\xee\x0e\x50\x75\xbc\x58\xb9\x7a\xf9\x17\x7f\xda\x75\xd5\x37\x08\xbe\xb0\x4d\xc4\xf1\x9a\x43\xe7\x68\x07\x46\x09\xf1\x40\x65\xf4\x8f\xda\xd5\x07\x7c\xe1\x09\xba\xcc\x35\x71\x74\xa6\xb7\x95\x6f\x6e\x7f\x32\xe3\x84\x15\xbe\x52\x63\x70\xfa\x58\xc3\xc0\xb3\x1f\x51\xe6\xcd\x4b\x2c\xf2\x7f\x8b\xcb\xc2\x12\x59\xd9\xe5\xc3\xb5\xc2\x94\x6a\x9f\xc1\xb0\x0d\x9d\x15\xc3\xb7\xd8\x0b\xfd\x9d\x05\xdb\x91\xd2\x49\xd3\xe4\x2d\x89\x56\x68\x20\x44\x54\x8d\x83\xbd\xa8\xd5\xcc\x92\x12\x44\x2f\x30\xb4\x5c\xf4\xae\xad\x80\xcc\xe9\xb3\x51\x2c\x39\xc5\xc7\x37\xd3\xf8\xd7\x47\xaf\xba\xb2\x65\xaf\x5e\xee\xf8\xca\x93\x62\xec\x76\xe9\x43\xb0\xa0\xd7\xa3\x9f\x3d\xb1\x1e\xca\x14\x45\x8a\x7b\x59\x2e\x5e\x4f\xf2\x27\x5d\xd4\x8b\x28\x53"}, -{{0x8f,0xb0,0x86,0x20,0x6d,0xd9,0x5a,0x26,0x21,0xf5,0x98,0x56,0x0c,0xcb,0x28,0x1f,0x82,0x73,0xc8,0xfc,0x72,0xe2,0x36,0x11,0x08,0x9b,0xaa,0xc8,0x9d,0x3c,0x3c,0x78,},{0x20,0x27,0x6e,0xf4,0x79,0xf4,0xd4,0x52,0x3a,0xb7,0x74,0x20,0xd4,0x24,0xe8,0x81,0x9c,0x33,0xc8,0x37,0x79,0xed,0x80,0xc7,0xf6,0x66,0xe8,0xf4,0x40,0x3f,0x94,0xd7,},{0xa9,0x30,0x5e,0x00,0x16,0x00,0xd5,0x97,0xd0,0x5e,0xf6,0x71,0x69,0x9b,0xf0,0x9f,0x0d,0xcc,0x0c,0x44,0x47,0x5d,0x3c,0xa3,0x1e,0x7f,0xf1,0xbf,0xfe,0xdc,0x0c,0x67,0xda,0xa1,0xf3,0xb7,0x6a,0x03,0x59,0x48,0xc5,0x9c,0xd8,0x7f,0x82,0x45,0x3a,0x40,0x95,0x0a,0x1c,0x97,0x03,0xc2,0xe7,0xd9,0x28,0x0e,0x73,0x03,0x96,0x6d,0xa3,0x01,},"\xf0\x29\x03\xed\x42\x66\xe8\x49\xa4\x48\x52\x05\x95\x4f\xff\xa8\xa1\x08\xc3\x23\xb7\xe3\xf8\x43\x31\x04\x35\x14\xe4\x85\x56\xab\x01\x94\x97\x23\x3a\x5a\x12\x7b\xff\x3c\xd7\xc9\x70\x86\xbe\xce\xf5\x38\xb3\xf3\x39\xd7\xd0\x6e\x53\x2d\xc7\x32\x5e\x59\x7a\xe3\x57\xf8\x16\xde\xa4\x2a\x6a\x22\xc7\x9d\x22\x07\x4a\x2e\x1a\xd8\x02\x3c\x42\x4b\x7e\x09\x6e\x5a\xd8\x89\x7b\x05\xef\x7d\x00\xd3\x0a\x04\xaa\xf2\x98\x1e\xdd\xff\x2b\x34\x7f\x1e\x27\xe2\x0a\xab\xbe\x7e\x7a\x95\x44\x97\x8e\x09\x2b\x00\xcc\xe4\x20\xab\xa0\x61\x87\x37\x4f\xfb\xb3\x7b\x4c\x22\xd7\x5f\x04\xe5\x75\x90\xf6\x10\xa2\x73\x47\x28\x6c\x29\x83\x12\xa6\xc9\xb1\xbd\xf2\x4f\xbd\xa8\x51\x3c\x4f\x83\x56\xcc\xf7\x57\x06\x8f\xfc\x11\xbc\x65\x11\x37\x83\xa5\xdd\xe7\x72\x2f\xaf\x4c\xeb\x19\xfb\xb6\x2f\x40\x70\x2e\x2c\x6e\x6a\x8b\xb4\x9e\xf4\x04\x46\x45\x0c\x4c\x59\xa2\x99\x09\x44\xda\x47\x44\xf6\xee\x77\x0b\x93\x0c\x24\x66\x69\x81\x3c\xe5\xa9\xf5\xa4\x7d\xd8\x03\x88\x98\x1b\xfc\xc3\xa5\x6b\x5b\xe2\xc4\xc7\xe6\x59\xa2\xe9\x18\x2d\xec\x0a\xaa\xfe\x90\x31\xaa\x39\x54\xd4\xfe\x7c\x43\x11\x96\xa5\x61\xa5\xb7\x8e\xab\xa6\x4f\x3d\xb1\xb5\x86\xc5\x3b\x16\xf6\x79\xa8\x49\x21\xa6\x42\xc2\x60\xe4\x65\x3a\x61\xde\x10\x8e\xbd\xe6\xf7\x05\x3a\xfa\x2c\xb3\xf3\x66\x8e\xde\x12\x10\x20\xdd\x1b\xac\xe8\x41\x8a\xeb\xac\x3a\x5b\xd5\x14\x2f\x10\x5a\xc2\x6f\xe4\x9e\x5f\xb1\x40\xc1\x9b\x22\xd5\x4a\x62\x91\xdf\xc9\x54\x67\x02\x47\x88\x16\x46\x87\x4d\xef\xad\x81\x49\x95\x51\x9f\x62\x60\xe9\x77\x4a\x8d\x18\x5c\x37\x88\x1b\x4f\x25\x43\xc4\xb6\x3f\xbf\x19\x85\x01\x6a\xb4\x1c\x4d\x72\x8c\xbc\x90\xb3\xab\x87\x62\x67\xbe\xd4\x1d\x0c\x09\x02\xf6\xb5\x0e\x8f\xa9\x06\xfc\x47\x88\xf7\xb8\x20\x46\x73\x06\xe0\xfe\x9e\x03\x6a\x0a\x00\xf8\x04\xf9\x1c\x3c\xa7\x18\xb9\x5f\xf6\xd9\xe2\x20\x4b\xc3\x16\x1b\xf7\x0f\xcc\x17\xb2\x96\x4b\x56\xbc\x61\x2e\x29\x40\x2d\x96\xf5\x09\x86\x51\x4b\xc7\xd8\x31\xd5\x8e\x42\x79\x37\x86\xd5\x80\x6f"}, -{{0xaf,0xa1,0xb8,0x46,0xc2,0x10,0xb5,0x23,0x00,0xe9,0x76,0x96,0xf8,0x1b,0x8e,0xa7,0x74,0xd1,0xdf,0x12,0xe6,0x12,0x52,0x7c,0x55,0x74,0x7f,0x29,0xc1,0x93,0x73,0x96,},{0xb6,0x09,0x56,0x6b,0xbd,0x19,0x47,0xbd,0x7a,0xfa,0xce,0xb1,0x43,0x89,0xe8,0x36,0x22,0x71,0x69,0x21,0x5f,0xab,0x66,0x85,0x1a,0xa5,0xd7,0x0d,0x6e,0x2e,0x3b,0x89,},{0x98,0xb0,0xc6,0x31,0x3c,0xec,0xaf,0x7c,0x82,0xcb,0xde,0xb3,0xd0,0x28,0x06,0x41,0xc6,0x1a,0x06,0x0f,0x65,0xe5,0x63,0xaa,0x93,0xce,0x18,0x30,0x0a,0x9b,0x58,0x27,0x2d,0xc8,0x68,0x0b,0x48,0x5e,0x8c,0xd1,0x1c,0xf8,0x0f,0xdc,0xa8,0x68,0xfa,0xb3,0x65,0x37,0x83,0x84,0xa1,0x42,0x72,0x7f,0x2f,0x84,0x4f,0x87,0xcf,0xdf,0x19,0x05,},"\x4c\xac\x1b\x1f\x4b\xd4\x82\x84\xdc\xc9\xaf\xc8\xb5\x95\x5b\x64\xb4\x36\xdb\x70\x4b\x03\x35\xd9\x75\x5c\xc1\xf9\x74\x77\xf8\xd3\x23\xcb\x64\x10\xef\x14\x6a\xb8\xa9\xef\xb9\x52\x6d\x8b\x62\xe3\xbb\xad\x1f\x72\x95\xf4\x7b\xa9\xf0\xde\x95\x8f\x8e\xc9\xb7\x7a\xb4\x22\x32\x43\x7e\xd9\x74\x85\x64\x44\xcd\x22\xe2\x0b\xe3\x5e\x91\x81\x3b\xff\x4b\x01\x6f\x81\x0d\x0f\x61\xd8\x9f\x6b\x61\x4d\xb3\x3f\x34\xbd\x09\x98\x5b\x59\x3f\xe3\xe0\x6e\x06\x5b\x7b\xc6\xcd\x39\xd5\x5c\x2c\xfb\xec\x7b\x6d\x59\xc0\xb3\x7d\xd1\xd0\xd3\x51\x35\xab\x1d\x1b\x04\xf2\xf3\x0c\x2f\x04\xf4\xba\x2b\x36\x58\x27\x38\x08\x1c\xf5\x91\x90\xf5\x28\x36\x3d\xb9\x44\xed\x61\x29\x31\xd1\xd5\x14\xc6\x21\x4f\x9a\xb9\x2a\xbb\x18\x33\x92\x61\x83\xac\x52\xfb\xa2\xa4\x55\x1e\x20\xe4\xc0\xac\x95\x9a\x49\xdd\xb1\x67\xa3\x81\xe0\x24\x1d\x40\xc0\x86\xe9\x0e\x52\xac\xa0\x17\x25\x89\x75\xdb\xab\x2b\xa4\x51\xee\x53\x9a\x71\x8f\x07\x6a\x58\x70\x9c\x66\x97\x41\x8d\x9c\x6f\x13\xe4\xd3\x91\x36\x8b\xf0\xe8\xbd\x8f\x29\x32\xdd\x95\xce\xaf\x7a\xac\xa1\x24\x11\x47\xd3\x41\xa3\xac\xd0\x8d\xc3\x29\x05\x48\x35\x72\xb8\x9a\x80\xcc\x47\x23\x14\x68\xab\x8d\xe3\x59\xdd\x52\x5a\x62\x57\xcf\x19\x6c\x2e\xcb\x82\xfa\x8a\x78\xaa\x3a\x85\x1c\x7c\x96\xca\x25\xbf\x7c\xa3\xdc\xf3\xca\x21\x45\x3d\x0d\xfd\x33\x23\xd5\xa4\x22\xde\xc8\x43\x16\x10\x2f\x68\x4c\x35\x9f\x22\x6b\xb5\x37\x79\xc0\xb9\x95\x09\x39\x28\x1e\xf7\x9a\x58\xc0\x11\x99\x3e\xac\xe0\x85\x49\x7a\xfa\x4d\xaf\x64\xc9\x68\x7b\x0a\x11\xaa\x11\x6c\xfa\x7b\x03\x93\x62\x41\xa5\x56\x7b\x64\x6e\x7e\x42\xe9\xfb\x59\x24\x05\xb8\xfa\x3c\x0a\x82\x1f\xc3\x12\x1b\x45\xb1\x75\x3c\xec\x9a\x83\x94\x7d\x21\x1a\x45\x49\x9b\xd6\x37\x90\xb8\x7f\x01\x47\x2f\xe5\x66\xd8\x76\x96\xef\xed\xbb\x74\xed\x00\x04\x8c\x38\x4b\xa7\xf0\x27\xb3\xaa\x42\x98\xdc\x41\x10\x34\x9f\xed\xf5\x2a\x96\xcd\x05\xd0\x8b\xd6\x35\x77\x1e\xd4\x51\x07\x38\xd8\xf0\x7a\x60\x21\x24\x4d\x19\x03\x57\x9a\x3e\xa7\x39"}, -{{0xc8,0x59,0x13,0xa6,0x87,0x78,0x77,0x13,0x10,0x01,0x62,0x3c,0xcd,0xa9,0xcd,0xc1,0x2b,0x9d,0x40,0x43,0xb8,0xa8,0x37,0x93,0xc4,0x46,0x96,0x63,0x2c,0xd6,0x42,0x1c,},{0x9c,0xc6,0x7c,0x69,0x48,0xf7,0xbf,0x6e,0x55,0x6d,0x08,0x49,0xd3,0xb8,0xd2,0x03,0x45,0x7a,0x7b,0x61,0x54,0x9b,0x36,0x68,0x1d,0x75,0x4f,0x1d,0xc0,0x84,0x1e,0x96,},{0x01,0xfc,0xcf,0xdb,0x1f,0xb6,0x88,0x8b,0x03,0x10,0xa9,0x13,0x17,0x0f,0x7e,0x36,0x68,0x16,0xda,0xeb,0xe7,0x65,0x0d,0x72,0x51,0x3d,0x95,0x06,0xe6,0x6f,0x7d,0x62,0x20,0x8a,0x49,0xec,0xe0,0xaf,0x18,0x71,0x49,0x7f,0x45,0x41,0xef,0x60,0x5b,0xde,0x71,0x1c,0x9e,0x0a,0x12,0x05,0xef,0x48,0xf2,0x6c,0x03,0xdc,0x1a,0xd4,0xaf,0x03,},"\x91\xb5\x00\x9e\x83\xd0\xf6\x10\x33\x99\xc2\xd3\xfe\xec\x00\x84\x97\x3a\x30\x5b\xf4\x17\x6e\xc7\x82\x53\x75\x60\x47\x2d\xb1\x87\xa1\x1b\x4d\xcb\x4b\x2f\xfb\x7f\x06\x44\xfe\xb3\x94\xb2\x8e\x5b\xfe\x97\x24\x7c\x4a\x4a\x23\x1c\xf6\xe9\x16\xbf\x99\x34\x4c\xcd\xa8\x8a\x7f\x5d\x83\x1d\x6d\xe3\xd5\x63\xdd\x10\x2e\xae\xb1\x08\xc5\xbd\xce\x44\xe0\x63\x2d\x17\xe6\xfa\x55\xb1\x80\x67\xdf\x2f\xa8\xd2\x00\xa9\x86\x9f\x6a\xff\x92\x0c\x51\xd4\x6a\x1c\xed\x2d\x90\x3b\x1d\x9b\x6b\x07\x5f\xac\xbf\x91\xcd\x05\xeb\x41\xad\x81\x1a\x8e\xf4\x0d\x91\x18\x26\x10\x12\xc7\x2b\x89\x79\xf1\x51\x53\xdb\xb8\x56\x12\x93\xda\x9f\x8b\x77\xc8\xff\x14\xf7\x53\x87\x53\x6f\x00\x36\xd1\x71\x3a\x72\xce\x8c\x35\xb1\x06\x2f\x2c\x67\x32\xae\xbf\x32\x93\x67\x99\xb5\x1c\x2c\xbc\xd6\x57\x24\x13\xe7\xdf\xaa\xb8\x64\x1a\x02\xc1\x50\x23\x73\x81\xcf\x7a\x14\xe2\x2c\x74\xc6\xc2\x00\x09\xde\x7d\x3b\x7e\x69\xcd\x1b\x45\x84\xac\x2c\x01\xba\xba\xf9\x73\xc5\x6b\x38\x14\xbb\x00\x89\x72\x0e\x41\x96\x81\x06\xcf\x26\x50\x9d\x4a\xa5\x46\xfc\xad\x55\x34\xaf\x30\x3f\xfc\xa4\x2b\x16\xae\x6c\x93\xee\x06\xbc\x3c\xac\xe1\x2e\x4e\xc7\x18\x84\x4b\xd3\x0d\x22\x24\xcc\x48\x6d\x10\x6d\x1c\x45\x6b\xfa\x16\x5e\xa0\x12\x0f\xab\x3d\xf2\xc5\xab\x3a\x52\x3b\xbf\xa7\x89\xde\xed\x44\x03\x2a\xb0\xbe\x86\xeb\x7c\xc0\x9c\xdb\x7c\x07\xaa\x94\x8d\xd5\x27\x7c\x3d\xf1\xd9\xd1\x84\x35\x67\xde\xc8\x4f\x92\x88\xe0\x85\xb0\x5a\xe4\xb8\xaf\x2c\xea\x5d\x9a\x18\x4d\x50\xbe\xf8\x55\x50\xc8\x36\x61\x3d\x5d\x3a\xf5\xf9\xc2\x92\x8e\x6a\x89\x66\x0f\xa6\x27\x19\xeb\xff\x77\x3e\x46\xb7\x7e\x34\xbc\x04\x70\xda\x4d\x2c\xdb\xc7\x07\x1d\xa7\x58\xc4\xd3\x9f\xe6\x52\x01\xc8\x8a\xaa\x8e\x66\x03\xd0\xbb\xe7\xc3\xe9\xb2\xd9\xe4\x1b\x63\x46\x82\x09\x2f\x14\x73\x41\xad\x6d\x66\x7f\x20\xc6\x4e\x81\xa6\x8d\x62\x94\x67\xa5\x4d\xd8\x6e\x1c\xe1\x2c\x56\x0a\x6f\x9b\x64\x51\x2d\x6f\x38\x86\xcb\xb9\xf3\x7c\x37\xeb\x39\x85\xc8\xac\x38\xdd\x66\x82\xf4\x8f\xe1"}, -{{0xfa,0x1e,0x11,0xdc,0x83,0x64,0x20,0x8d,0x8e,0x1c,0xb6,0x6a,0x36,0x1b,0xe7,0xe8,0x4c,0x5e,0x36,0x81,0x66,0x58,0x7d,0x4f,0xdb,0x06,0xac,0xed,0x7f,0x62,0xe1,0x7c,},{0x4d,0x8e,0x6f,0x4b,0x34,0x15,0xdf,0x6c,0xed,0xab,0xfb,0x29,0x5c,0x19,0x84,0xfd,0x41,0x99,0x23,0xc6,0xac,0x41,0x76,0x4e,0x32,0xd2,0x2d,0xaf,0x37,0x2c,0x50,0xfc,},{0xe8,0x57,0xdb,0x08,0x7e,0x28,0xd6,0x75,0x0b,0xf5,0x4e,0x53,0x79,0x72,0x51,0xd8,0x43,0x99,0x89,0x57,0x6c,0x12,0xda,0x2d,0x9c,0x81,0x1a,0x14,0x87,0x7c,0x3b,0xd4,0x6c,0x4e,0xfa,0xb8,0x61,0xa1,0x0e,0xeb,0xe7,0xda,0x04,0xc0,0xb0,0xb4,0x45,0xc7,0xa3,0x90,0xa5,0x0c,0x13,0xde,0x36,0xf3,0xa3,0xc7,0xae,0x01,0x57,0x02,0x2c,0x0e,},"\x29\x4e\x63\xba\xcc\xcb\x80\x1b\xbf\x04\xc1\xf1\x9d\x0a\xee\x16\xf5\x65\x0a\x6e\x8e\xea\x6f\xe4\x11\x10\x66\x3e\xc0\x15\x32\xbd\x49\x60\xa5\x27\xf1\x5e\xca\x4a\xf2\xf4\xe6\xb7\xb0\xfc\x34\x0c\xf9\x7a\xa2\x34\xe9\x2c\xf7\xd6\x9d\x50\xe4\x00\x9c\x24\x96\xe3\xed\x4d\x9a\xff\x00\x0f\x9e\x18\x52\x75\xb8\x17\xd2\x6a\x0b\xab\x69\xb7\xf7\xee\x1e\xa3\x0d\xae\xc8\xbc\xee\x38\x7a\xe4\x6b\x4b\x29\x9c\x27\xbd\xc0\x6e\xea\x63\xf2\x4d\xbe\xe9\x55\xa6\xc0\x96\x90\x37\xee\xf9\x1c\x34\x32\x1e\x3c\x5c\x97\x2f\xde\x99\x31\x83\xb7\xd2\x3f\x6e\x01\x9c\x3e\x0c\xac\x75\x89\xae\x4a\x15\x21\xaf\x87\xea\x42\xdf\x8c\x22\xc2\x27\x0e\xc2\x3d\x6d\x14\x0f\x9c\xf6\xd4\xd5\x2f\xac\x1b\x9d\x6c\x89\x39\xef\x81\x31\xcb\x62\xa0\x35\xc5\x26\x15\x38\xbc\xdf\xd6\xdb\x41\x9a\x55\xef\x9f\xe5\xd7\xa5\xac\x44\x57\x9d\xe7\x00\x85\x8d\x74\xa3\x43\x48\x44\xf2\x83\x42\xc5\x65\x89\x27\x22\xe2\x7f\x40\x7d\x7f\x17\xb7\x4a\x59\x34\xbe\x91\x5b\x20\xc2\x40\x06\x43\x23\x5f\x8a\xb5\x79\x5f\x32\x4e\x33\xc5\x06\x44\xa0\x40\x33\x54\x2c\xb3\x81\x6d\x77\x0f\xa8\x99\xe7\x31\x1c\x14\x30\x1c\x1b\xd0\xf5\xaa\x60\xa2\xeb\x31\x65\x68\x0c\x72\x0e\x1e\xfa\x80\x96\xfc\x25\xd2\x77\x92\x75\xf1\x84\x2b\x2d\xb5\x3b\x4d\xa0\xad\x3e\x59\xc0\x75\x40\xc2\x84\x60\xce\xc1\xfd\xd3\xcd\xb7\xa3\x47\x8b\x91\xa9\xca\xf9\xac\x89\x1c\xdf\x3a\xea\xee\xca\x9a\x96\x56\xac\x13\x07\x25\x99\x22\xfc\xa7\x4c\x5c\xc6\x9f\x7e\x25\xc6\xbf\x58\x79\x73\xa4\xb7\xd3\xe3\xac\x06\x35\xb0\xdb\x22\xa0\x09\x3a\x79\x07\x68\x81\xc7\x17\x36\xee\x1d\x4d\x45\xf8\xed\x2d\x29\xa0\x67\x1a\x64\xe6\xca\x2f\x7a\x5e\xf4\x04\xb1\xed\xeb\x84\x20\x34\xf5\x71\xb6\x99\xbc\x59\xe5\xa3\x7d\xf0\x20\x54\xe8\x48\x2b\xf1\xe7\xb7\x7d\x8e\x83\x97\xda\x15\xd8\x9d\x73\x55\xa5\xdc\xe8\x6b\x16\x83\xa9\xac\x4e\x40\x6c\x08\xa9\x4a\x6e\xb0\x0e\x5a\xe1\x6d\x96\x72\x29\x72\xe5\xc5\x0c\x7b\xee\x4a\x84\xd0\x69\x7b\xbe\x67\xce\xb7\xef\x29\x5f\x06\xaa\xea\x5a\xbb\xa4\x44\x66\xbe\x0f\x67"}, -{{0x24,0xa9,0x14,0xce,0xb4,0x99,0xe3,0x75,0xe5,0xc6,0x67,0x77,0xc1,0xed,0x20,0x43,0xbe,0x56,0x54,0x9d,0x5e,0x50,0x2a,0x84,0x47,0x10,0x36,0x40,0x42,0xba,0x9a,0xcb,},{0x20,0xd2,0x1e,0xe7,0x64,0xb1,0xf3,0x5f,0x94,0x56,0x82,0x00,0xd6,0x3b,0xd5,0x82,0x8a,0xca,0x8c,0x5d,0x3e,0x90,0x47,0xd2,0x3f,0x47,0x8b,0x92,0x52,0x95,0xfa,0x2e,},{0x3a,0xe0,0xcc,0x7b,0xca,0x8d,0x73,0xbe,0x83,0xa9,0xb8,0x09,0xb1,0x33,0x38,0xc1,0x27,0x06,0xaa,0xef,0x75,0xc4,0xd1,0xa4,0x78,0x17,0x8f,0x9d,0xc5,0x65,0x51,0x4c,0x75,0x29,0xe2,0x98,0x04,0x3e,0xa7,0x8d,0x21,0xa5,0xa0,0x9d,0xd0,0x4f,0x10,0xae,0x87,0x44,0x1e,0x56,0x86,0xa9,0x33,0xc9,0x2c,0x75,0x54,0x84,0x27,0xad,0x3a,0x03,},"\x3f\xf9\xf6\x6f\xa2\x64\x6e\xc6\x6a\x1b\xf9\x33\xc2\xb4\xcc\x0f\xbf\x91\x2b\x4d\x6d\xb5\x05\x34\x25\x7f\x97\xd0\x1e\x69\x8d\x05\x48\x57\x47\xde\x25\x44\xe9\xf5\xa4\xa4\xa0\x75\x38\x8c\xf4\x40\x0a\xb8\x9b\x03\x53\xce\x86\x19\x82\x02\xdb\x3a\x90\x37\x67\xb8\x79\xa2\xaf\x9d\xaa\x15\x58\x43\x11\x1a\xf1\x5a\x2b\xc3\x5e\xfe\x41\xbc\xc9\x2c\x82\x07\xe0\x01\x13\xb0\x4f\x13\x03\x00\x79\x49\xff\xb6\xce\x8d\xf4\xb0\xb3\x42\x48\xfe\xdf\x5d\x9c\xb2\xce\xe9\x4b\x81\x2e\xd5\x8e\xce\x2a\x0c\xe0\x45\x4c\xf1\x4c\x20\xe4\x9e\x09\xfe\x66\x4d\x6e\x25\x76\x2e\x87\x89\x59\x32\xcd\x5c\xd3\x2e\xb6\xa3\xab\xb3\x8e\xe1\x63\x07\x8c\x13\x3e\x93\x58\x87\x91\xdb\xf6\xaf\x49\x9a\x31\xea\x44\x53\xbb\xcc\x7a\x85\xe4\x06\xc9\x84\x8a\x66\x40\x52\xf1\x11\x13\xfb\xb4\xff\xa7\x60\xde\xe4\xc2\x61\xe3\x96\x94\x24\x91\x11\x9d\xa2\x9a\x33\x58\x2f\x82\x1d\x41\x25\xe0\xb4\x16\x2f\x28\xbe\xb0\x66\x03\x1a\x65\x2d\x05\x74\x9a\xa7\x24\x4d\xd4\xf3\xd3\xbb\x15\xd2\x68\x32\x8d\x6a\x02\xfc\xe2\x50\x18\x15\x25\x7f\x8a\xd5\xaf\x4e\xcb\xe7\xcb\x8a\xe9\x66\x1e\x34\x4f\x90\x72\x31\x87\x91\xf3\xe8\x59\x09\x11\x21\xe0\x8a\xef\xca\x89\x82\xea\xaf\x66\x25\x9d\x9d\xe4\xf4\x6a\x31\xe7\x16\xdc\x03\x3d\x0f\x95\xd1\xfa\x93\x6b\x6c\x60\x79\xb1\x37\xdd\x11\x58\xd1\xde\xf1\x13\x01\x8c\x73\xf8\xeb\xb9\x80\x7e\x0f\x74\x15\x40\x4e\xa9\xc7\x85\x44\xac\xe7\xce\x46\x3c\xd1\xd1\xc5\x7e\x31\xf4\x09\x1b\xc0\x91\x80\x4c\xbc\xdd\xad\x0e\x15\xa4\x0c\xa9\x1a\xcb\xe1\xc6\x22\x4e\xd1\x3c\xaf\xb4\xdf\x2c\x84\xac\x9f\x0c\x3c\x9b\x54\x60\x07\xd9\xdd\x6e\x52\x4c\x46\x70\x72\x56\x3d\x4a\xc0\xd7\x00\xcc\x1b\xf3\x0f\xeb\xb3\x34\x31\x3d\xae\x57\x61\x74\x5e\xc0\xa5\xe9\xe8\x81\x50\x25\x95\x8f\x00\xfa\x2e\x58\x06\x0d\x7e\x9a\x5f\x2b\x72\x7f\x48\x69\x9f\x92\x9c\x84\x59\x93\x08\x92\x57\x3f\x78\x4f\xef\x56\x92\x51\x8b\x5c\xa2\x68\xe2\xa7\x3e\xbe\xad\x6e\xbd\xeb\x7e\xc2\x4e\xac\x92\xaa\x7d\xcb\x41\xb5\x98\xbd\x6e\xff\x36\x32\xd0\x69\x72\x62\x91"}, -{{0x55,0x32,0xe0,0x9b,0x93,0x7f,0xfd,0x3d,0x5f,0x4c,0x1d,0x9f,0x1f,0xfc,0xde,0xd2,0x6e,0xe7,0x4d,0x4d,0xa0,0x75,0x26,0x48,0x44,0x69,0x0b,0xd9,0xc8,0x61,0x39,0x94,},{0x50,0x93,0x96,0x9f,0x37,0x7b,0xec,0x3e,0x35,0xf5,0x9e,0xfd,0xa0,0x1a,0xb4,0x18,0x6c,0x5d,0x2a,0x36,0x74,0x0c,0xf0,0x22,0x67,0x5e,0x01,0x09,0x6b,0x1a,0x3f,0x0a,},{0xd5,0x27,0xff,0x0d,0x4a,0x21,0x9d,0x61,0xf4,0x18,0x12,0x12,0x06,0xa5,0x4a,0xe4,0x98,0x58,0x54,0xa3,0x10,0x48,0x27,0x44,0x48,0x6e,0x4d,0x13,0x0a,0x7d,0xe9,0x7c,0x31,0x9d,0xf8,0x37,0x2c,0x82,0x82,0x8c,0x93,0x6e,0x6a,0x8a,0xfd,0x9c,0x5d,0xe1,0x82,0x85,0x73,0xd8,0x26,0x1a,0xe9,0x36,0x5b,0x8f,0x23,0x76,0x76,0x18,0x24,0x02,},"\xad\xd4\xd7\xa9\xce\x3f\x63\xd1\xf9\x46\xe8\x67\x90\x65\x54\x5d\x8c\x7b\xf0\xa2\xcc\x3a\x4c\x00\xb8\xf1\x42\xf0\x94\x5a\xe3\x62\xc4\xc9\x46\x2a\x75\x76\xa4\x05\x9d\x57\x86\x16\x62\x88\x4b\xd8\x0b\x96\xd9\x0d\x27\x9a\x95\x2e\xda\x95\x2d\x37\xd4\xf9\x5c\xf0\xd7\x0d\xa9\x8f\x4f\xba\xca\x39\xe1\x69\xf9\xd9\x45\xd4\x1f\x87\x23\x97\xbb\xdd\x57\x01\x45\x43\x03\xd7\x7d\x31\xe8\x63\x48\x27\x1d\xa4\x0a\x1b\x8f\x1e\x57\xc3\x6f\xcd\x80\x3e\x14\xfa\x17\x71\x6c\x56\x31\xef\xa0\x1d\x3a\x79\x5d\xc2\x0b\x2b\xde\x36\xab\x73\xff\x6a\x2d\x53\x3b\xc1\x5c\xce\x22\x32\x87\x13\xc3\xc9\xcc\xd0\x72\xc3\xe4\x50\xd7\xf2\x2c\x0c\x9f\x94\x91\x97\x52\xcb\xfe\x45\xee\x65\x5d\x1b\x53\x67\x65\x93\xcd\xb4\x48\x70\x41\x02\x63\x1c\xaa\xa9\x76\x95\x2e\xaa\x1f\x6c\x2e\x87\x65\x64\xe4\x20\xf0\xc6\x46\xa0\xf8\x83\x65\xf7\x64\x15\xb4\x08\x5f\x60\xa3\x38\xb2\x9c\x51\x63\x3e\x54\x0f\x0b\xf3\x2d\x40\x87\xe7\xd0\xfb\x68\x5b\xe8\x8c\x75\x95\xdc\x53\x1c\x99\xb4\x89\x58\x45\x60\xad\x82\x34\xb1\x8e\x39\xa1\x07\xcf\x5d\x84\x2d\xab\xd4\x21\xe7\x7d\x26\xea\x5e\x0f\x14\x05\xce\x35\xfe\x79\x27\x14\xeb\x4e\xe1\xa8\x01\x76\x48\xac\x1a\xe7\x39\xa3\x3d\x7b\x1e\x08\x91\x05\xd1\xe5\xad\xd2\x7a\x62\xce\x64\x15\x45\x70\x34\x0a\xf9\xeb\x14\xe7\xfd\xfc\x2f\x9a\x2c\x2f\xcf\xcd\xac\x3c\xc4\x22\x77\x63\xf4\xd6\x29\x49\x74\x79\xf8\x49\x21\x6e\x5d\x90\xec\x16\xdf\xa3\x6b\x72\x51\x7f\x7b\x54\x86\xba\xee\x7f\xda\x44\x50\xc3\x52\xcf\xfb\xba\xe7\x39\x26\xc8\x43\x22\x4f\x8c\xe4\x4b\x38\xda\xe5\x3f\x3e\xad\x21\x89\x0b\x52\xa7\x80\x10\x75\x29\x16\x84\xfd\x59\x10\xed\x86\xad\x33\xe8\xa0\x07\xf6\xc3\xf8\x5c\x16\xb2\x09\x29\x37\x40\x18\x4f\x58\x90\x87\x4d\x43\x1c\xd4\xe0\xea\x40\x87\xc4\x9c\x34\x71\xd7\x89\xc8\x13\xc6\xdc\x9a\x78\x69\x93\x63\xa1\xd8\x71\x97\xd3\xb9\x2c\x02\x86\x68\x93\x11\x82\x3f\x4d\xf2\x2c\xe8\x03\x5e\x75\x73\x2c\xde\xa7\xf5\x62\x1f\x67\xdb\x0e\x2a\x4c\xa6\x61\x61\x93\x22\x1c\x0a\xa3\xd6\xde\x50\xd8\x52\x82\xee"}, -{{0xeb,0x36,0x51,0x10,0x09,0xd3,0x7a,0x9c,0x46,0xc4,0xd1,0x37,0x4d,0x0b,0xbd,0x0d,0x99,0x81,0xe7,0x8c,0xee,0x7d,0x18,0x8c,0x5a,0xab,0x98,0x3e,0xc2,0x39,0xe1,0x0c,},{0xb1,0xcc,0x21,0x2b,0x45,0x21,0xbb,0xe7,0xb1,0x9a,0x76,0x93,0x87,0x8a,0x55,0x84,0x40,0xee,0xc3,0x62,0x05,0xd8,0x43,0x9d,0x04,0x0a,0x46,0xa9,0x90,0x2f,0xbf,0x55,},{0x9f,0x58,0x37,0x24,0xde,0x55,0x2e,0xae,0x82,0xf2,0x54,0xac,0x6e,0x2e,0xd4,0x83,0xec,0x1a,0x07,0x34,0x62,0x66,0x73,0x5c,0x49,0x09,0x20,0x69,0x0c,0x1e,0x3f,0xb2,0xa9,0xe9,0xa3,0x41,0x94,0xed,0x64,0x73,0x73,0x3b,0x30,0x0d,0x4f,0x23,0xc9,0xae,0xc0,0xda,0x5a,0x20,0x22,0x05,0x4c,0xa4,0x38,0x85,0xa1,0x5a,0x29,0x84,0x32,0x0e,},"\xba\x24\x66\xe5\x6c\x1d\xf7\x7f\x22\xb6\xf0\x24\x1f\xc7\x95\x2a\xe9\xbc\x24\x75\x64\x19\xa9\x44\x6d\xd2\xb4\x9e\x2c\xb9\xdf\x59\x4e\x5b\x6c\x77\xa9\x5a\xa5\xfb\xd9\xdc\x57\xfe\xc8\x39\x62\xc7\x75\x1e\xeb\xb4\xba\x21\x82\x53\xf9\x16\xa9\x22\xa5\x13\x96\x63\xe3\x20\x3e\x3b\xe4\x82\xbe\x37\x9c\xa1\x51\xc4\x63\xd9\xad\xa2\x14\x46\x13\x5f\x35\x69\x94\xfa\x54\x49\xf0\x84\x47\x8f\x5b\xb4\xf5\xba\x61\x45\xc5\x15\x8e\xb7\xb1\xc4\x3c\x32\xeb\xea\x25\xe0\x9c\x90\x0f\x01\xef\x91\xe9\x2f\x88\xc0\x3c\x76\x50\x4a\xce\x96\x46\x01\x6f\xfc\x27\x89\x55\x9d\x0f\x3c\xc9\xd0\x0f\xb6\x1b\xdc\x6a\xf7\xd3\x94\x0f\x30\x2e\x58\x8e\x04\xf7\x9f\x7b\x3d\x4b\x91\xa5\xd1\x93\xa4\xf8\x22\x2b\xfe\xb6\x9b\xf0\x34\x7d\x98\xad\x81\xef\x99\xd1\x30\xeb\xc7\xb3\x6b\x07\x83\x39\x4e\xea\x92\xa3\x8d\xdd\x5e\x74\x80\xd2\xad\xd4\xe4\xde\xf5\x3e\xb9\x9c\x44\x9b\xff\x94\xe4\x71\x8b\x09\xf2\xea\x9b\x1f\x2b\x88\x65\x94\xa9\x5c\x33\xa6\x9e\x03\x33\x15\x4e\x44\x0a\xb3\x4b\x7b\x6c\x11\x34\xd8\x17\x9b\x6f\x0c\x56\x25\x1a\x9a\xd8\xe1\xb6\xb0\xf9\xb8\xa5\xc9\x70\x81\xa7\xf8\xfd\x05\xd0\xb0\xaf\xfc\x82\xdb\xdd\xc8\xb0\xc0\xab\x7e\x83\x3f\x30\x06\x26\xd4\xb9\x73\xb3\xf6\x0f\xea\xc5\x55\x71\xe8\x9c\xda\x0f\x2b\x44\x1e\xd2\xfa\xa6\x69\xa7\x0d\x55\x6c\xb4\x8f\x9b\x1d\x1c\xbc\xe3\x2e\xde\x5d\x16\x6b\x11\x43\xe2\x64\xb1\x1e\xa3\x27\x68\x1c\xb5\x59\xed\xd1\x3c\x36\x4b\xd2\xba\xf1\xfd\x54\xbb\x78\x18\x07\xbd\x59\xc8\x68\xb0\xe4\x79\x5a\x77\x9e\x67\xf0\xbd\x0d\x14\xb5\xa6\xb9\xe4\x40\xb5\x7a\x58\x23\x32\x8b\x59\xaf\xfb\xd0\x27\xed\xa7\xdd\x78\x50\x79\xc5\xf0\x2b\x5e\x32\x89\x0b\x03\x87\x30\x98\x6a\x39\xa5\xa9\x83\x4a\x3f\xed\x86\x8b\x6f\x45\xcb\xdd\x28\xac\xb2\x70\x9a\xff\x55\x62\x63\x86\x4f\x9a\xe1\xe7\x57\xb3\x27\x8c\x28\x8d\xbe\x29\x32\x82\x57\x12\x77\x3e\x43\x1f\x7c\x29\x32\x98\x57\xfd\xae\xa7\x98\xed\x93\x92\x08\x93\x63\x14\x02\xe6\xb1\x3b\xab\x62\xb4\x85\x54\x61\xed\xb9\x46\x20\xf2\xd1\x75\x18\x65\xf4\x45\xc4\x66"}, -{{0x7d,0xbc,0x81,0x90,0x2e,0x4e,0xaa,0xb3,0x07,0x75,0x40,0xf5,0x59,0x99,0x5c,0x38,0x74,0x03,0xca,0xc3,0x06,0xd4,0x86,0xe9,0x59,0xc5,0xeb,0x59,0xe4,0x31,0xc0,0xa8,},{0xe0,0x30,0x66,0x13,0x90,0x82,0xf6,0x13,0x44,0x8b,0xdb,0xc2,0x7f,0xe5,0x3a,0xa3,0xf8,0x89,0x94,0xc3,0x1d,0xdc,0xe0,0x02,0xe3,0x6b,0xbb,0x29,0x63,0xdf,0x3e,0xc8,},{0x5b,0x7f,0x65,0x2f,0x08,0xf2,0x29,0xfd,0xa1,0xb0,0xbd,0x75,0x93,0x77,0xb3,0xfb,0x72,0x6c,0x1b,0x9c,0x9a,0x10,0xef,0x63,0x42,0x6d,0x35,0x2d,0xd0,0x86,0x9b,0xd5,0x4d,0x87,0x6c,0x30,0x92,0xf1,0xcd,0x41,0x1c,0x37,0x57,0xd3,0xc6,0xb6,0xea,0x94,0x2a,0xa7,0x0c,0x3a,0xae,0xb4,0x21,0x7a,0x4c,0x73,0x64,0xd1,0x8e,0x76,0xe5,0x0f,},"\xdf\xf7\x98\xb1\x55\x7b\x17\x08\x5a\x06\x34\x37\x1d\xed\x5d\xdf\x7a\x5a\xcb\x99\x6e\xf9\x03\x54\x75\xe6\x82\x63\x36\xf6\x4a\xd8\xb8\x4b\x88\x2e\x30\xba\xde\xc2\xb4\xa7\x11\x99\x87\x52\xf4\xa1\x57\x4b\xc1\xf8\x9d\x43\x25\xcf\x2b\x39\x86\x10\x44\xdd\x03\x69\x1e\x71\xd0\x77\x68\xb5\x93\x3a\x30\x52\xcc\x7c\x81\xd5\x71\xa9\xde\x06\x1d\xc1\x90\x26\xc2\xf1\xe7\x01\xf2\xdc\xf2\x6a\x88\xd3\x40\x1b\xc9\x9f\xb8\x15\x59\xdc\xa7\x6d\x8a\x31\xa9\x20\x44\xa2\x73\x58\x7d\x62\x2a\x08\xd1\xcc\xe6\x1c\x8f\x94\x8a\x34\xde\xd1\xac\xb3\x18\x88\x1c\x9b\x49\xf6\xf3\x7c\x30\xa6\x5d\x49\x5b\x02\xd5\x42\x9e\x7a\xb4\x04\x0d\x8b\xeb\xeb\x78\x79\x4f\xf7\x36\xd1\x51\x10\x31\xa6\xd6\x7a\x22\xcd\xf3\x41\xb9\x80\x81\x1c\x9d\x77\x5f\xb1\x9c\x64\x78\xf0\x5e\xd9\x84\x30\x10\x3e\xa2\x4c\x0f\x41\x4d\x4c\xc0\x7d\x86\x0b\x72\xdc\x54\x2f\xf2\x2d\x83\x84\x5a\x42\xf8\xba\x45\xca\x7f\xf3\xaa\xb0\xb1\xe7\xde\x2b\x10\x94\xde\xac\x08\xd1\x6e\xee\x01\x96\x9f\x91\xbc\x16\xfe\xc2\x9c\xcc\x06\x1c\x54\xdb\x53\x45\xba\x64\x84\x2d\xac\xc9\x9e\xe7\x72\x94\x68\xd8\x0a\x3f\x09\x55\x83\xd8\xe8\x01\x24\x08\x51\x9d\x58\x2c\xc3\xff\x9a\x2e\xb7\xae\xba\xa2\x2d\xb8\x1f\xfc\x78\xee\x90\xef\x4e\xc5\x89\xdc\xce\x87\x11\x8d\xab\x31\xa6\x32\x8e\x40\x9a\xd5\x05\x9a\x51\x32\xc8\x2d\xf3\xce\xfe\x2e\x40\x14\xe4\x76\xf0\x4c\x3a\x70\x18\xe4\x52\x67\xec\x50\x18\xec\xd7\xbf\xf1\xdd\xa9\x26\x7e\x90\x66\x6b\x6b\x14\x17\xe8\x9d\xda\xcb\x50\x85\x94\x3b\xef\xc7\xad\x2f\x4d\xf5\xf1\xee\x0a\xf9\x43\x1a\xee\xb6\xb2\x4a\x55\x15\xb9\x3d\xbc\xf6\x86\x40\xf7\xda\xf8\xc9\x61\xe5\x67\xd7\x53\x49\x00\x20\x5c\x3d\xf2\x18\x4b\x6a\xc2\xda\x96\x1c\x4c\x1d\x2b\xc4\x9b\x4e\xa9\x6b\x81\x54\xff\xd4\xef\xff\xdc\x5e\x55\xa7\x11\x9c\xb8\xaf\x42\x9e\x85\x10\x5d\xff\xd4\x1f\xe4\xa2\xeb\xba\x48\x16\x8a\xa0\x5f\xa7\xdf\x27\xc4\x29\x87\x35\xff\x86\x8f\x14\x96\xbe\xb4\xb2\xed\x0b\x89\x80\xc7\x5f\xfd\x93\x9d\xdd\x1a\x17\xe4\x4a\x44\xfe\x3b\x02\x79\x53\x39\xb0\x8c\x8d"}, -{{0x91,0xb0,0x95,0xc8,0xa9,0x99,0xe0,0x3f,0x3e,0xd7,0x49,0xcd,0x9f,0x2f,0xaa,0xcc,0x00,0x76,0xc3,0xb4,0x77,0xa8,0x7a,0xb5,0xcc,0xd6,0x63,0x17,0x38,0x76,0x74,0x46,},{0xda,0xd1,0x74,0xd3,0x59,0xda,0xec,0xca,0x9c,0x6b,0x38,0x9b,0xa0,0x96,0x45,0x2a,0xb5,0xca,0x91,0xe6,0x38,0x3c,0x6d,0x04,0x2a,0x28,0x4e,0xce,0x16,0xba,0x97,0xb6,},{0x64,0xee,0x9e,0xfd,0xb0,0xc2,0x60,0x1a,0x83,0x5f,0x41,0x85,0x20,0x64,0x1e,0x43,0x6c,0x7d,0xd4,0x7c,0x33,0x3d,0x9f,0xc3,0x0c,0xfb,0xb9,0xe3,0x90,0xfe,0x76,0x45,0x30,0x65,0x47,0x08,0xb4,0x0b,0x03,0x58,0x18,0x99,0xa9,0xac,0x87,0x0e,0xfd,0x76,0x6f,0xfb,0xb4,0x63,0x71,0x52,0xf8,0xff,0x27,0x79,0x64,0xfe,0x35,0x42,0x52,0x09,},"\x9b\x0d\x8b\x00\x29\x98\x52\xd6\x8b\xbf\x49\x7f\xe6\x03\x96\x1a\x48\x54\x66\xa9\x9a\x54\x84\x00\x5d\xb7\x3d\x4e\x4b\xad\x81\x4e\x85\x74\xef\xd5\x4d\x64\x8b\xd5\xc9\x1a\xe8\x48\x3c\x54\xb2\xf9\x98\xb0\x2e\x1a\xbd\x6f\x40\x1a\x25\x52\x68\x43\xa5\xf2\xa2\x3a\x97\xbd\x58\x9d\x1f\x7e\x1a\xb1\x49\x15\xb1\xe3\x59\xa3\x96\xd3\x52\xc3\x60\xae\x65\x84\x32\x5a\xe4\xbb\x7d\x62\x4f\x61\x25\x5c\x5c\x7b\xf0\xa6\x7a\xca\xb4\x6c\x3b\x57\xb3\x45\x34\xc0\xee\x84\x31\xd2\x60\x57\x66\x06\xcb\xd8\x4d\x8d\x18\x39\xe7\x3d\xa6\xfe\x4b\x0b\x8b\x78\xf0\xf9\x58\x82\x7c\x2f\x1d\x93\xba\x7a\x34\x6d\xcc\x75\xcb\x56\x3d\xff\xde\x26\xf9\x97\x59\x8e\x8b\x5c\x2f\x16\x17\xc6\xfe\xfc\x9b\xe4\xb2\x8b\x54\x01\xb0\x00\x64\x13\xa2\x51\x69\x0d\x12\x03\xaa\xae\x4f\x6d\x8a\x3f\xb2\x1f\x24\x00\x9a\xb3\xbf\xf1\x37\x37\xa8\xa7\xe6\x64\x6c\x02\x73\x2d\x9e\xc5\xa4\xa5\x10\x46\x9e\x2d\x29\x9e\x4c\xc1\xad\x64\x80\xa4\x82\xaa\x95\x6f\x89\xdd\xcc\xcc\x64\xa1\x36\xfb\x15\xb8\x76\xb6\xec\xd8\x8c\x7c\x86\xa4\xdf\xc6\x0e\x66\x62\x07\xc6\x04\x16\x7d\x16\x34\x40\xca\x9a\xb9\xcf\x87\xa5\xe0\xf7\xbb\xc5\x51\x7d\xe4\xde\xe8\x76\xc0\x37\xf8\xcc\x9d\x95\x9c\x8f\xf5\xdb\xe9\x44\xff\x54\xcd\x91\xa7\x71\xe2\x92\x31\xf8\xb5\xf1\x7d\x61\xde\x90\x4c\x95\x5f\xe2\x02\x5d\xc5\x2e\xd4\x80\xfb\x3c\xc9\x0f\x23\x24\x59\xc6\x07\xef\x7e\x2a\xdb\x52\xc7\x48\x2b\xec\xd6\x7a\xd2\x14\x9a\x41\x28\xf9\x84\x03\x8b\x58\xaa\x90\x17\x67\x82\x39\x36\x04\xaa\xc7\x4c\x18\x20\x9a\x3d\x6a\x78\x63\x0c\x01\x95\x5a\x7c\xec\xe5\xda\x83\x84\xda\x3b\xaf\x63\xaa\x2d\xdf\x59\x63\xfa\xe0\x5b\xa3\xb8\x1c\x6a\x03\xd8\x6a\x00\xef\x78\xed\xb4\x18\x4f\xdc\x89\xb1\xd6\xbf\xeb\x31\x0f\xd1\xb5\xfc\xce\x1e\x21\x95\x24\xa3\xcf\xb2\xe9\x72\x57\x7f\x06\xb1\xdd\xde\xba\x00\x86\x5d\xae\x49\x79\x00\x0c\x00\x8a\xd9\x9f\x3b\x63\x8c\xce\xb8\xe8\xc7\xa0\xf9\x98\xd3\x4d\x92\x14\x3d\x81\xc0\xe1\xc0\x96\xa9\x25\xce\xba\x65\xc4\x30\x03\xee\x18\xd4\x94\xd0\x03\xe9\xc6\x1f\x77\xd6\x57\x59"}, -{{0x8c,0x56,0x8b,0x31,0x0a,0xce,0x7d,0x1f,0x0e,0xde,0xce,0xfd,0x60,0x3a,0x88,0x40,0x00,0x54,0x4c,0x79,0x25,0x65,0xd4,0x81,0xc3,0xd3,0xe0,0x6e,0x2d,0x82,0xca,0x96,},{0x5f,0xa6,0xe2,0x67,0xc7,0x66,0x73,0x68,0x41,0x41,0x10,0x72,0xd1,0x98,0x3d,0x19,0x00,0xac,0xf0,0x1d,0x48,0xc3,0xce,0x11,0x77,0x0b,0x26,0xf7,0x8d,0xa9,0x79,0xf7,},{0xde,0xbd,0xd8,0xe5,0xd3,0x11,0x2f,0xd7,0x7b,0x39,0x4a,0xa0,0xe3,0x6e,0x94,0x26,0xba,0xc9,0x1d,0xf1,0x26,0xfa,0x9c,0x31,0x7c,0xea,0x7c,0x9d,0x45,0x95,0x7c,0xdd,0x96,0xa4,0x5a,0xe3,0xad,0x76,0x04,0x13,0xee,0x12,0x05,0xaf,0xd7,0x1a,0x29,0xf9,0xc3,0xcb,0x58,0x6c,0xd2,0xd7,0xcd,0x1e,0x93,0xbc,0x16,0x52,0xfc,0x34,0xdc,0x04,},"\xb5\x9f\x5f\xe9\xbb\x4e\xcf\xf9\x28\x95\x94\x72\x1f\x26\x47\x04\x7b\x0d\xa5\xe0\xe4\x94\x1b\xbe\x57\xc5\xb7\x22\xb4\x76\x72\x3f\x0a\xc5\x97\x0b\x41\x11\xf8\x93\xbc\xaa\x41\x1f\x28\xfc\xeb\x4f\x58\x5a\x2a\x71\x87\x01\x8a\x90\x4b\x70\xef\x8f\xe1\xf6\x56\x9a\x54\xd0\x0a\xda\x37\xb6\x9c\xb5\xe9\xc9\xd2\x6c\x16\xa9\x03\x51\x81\x48\xe0\x4a\x1b\x93\x6a\x32\x32\x9c\x94\xee\x1a\x8f\xb6\xb5\x91\x89\x2c\x3a\xff\x00\xbf\x6e\x44\xdd\x0a\x76\x2b\xab\xe8\x9d\x70\x60\xc1\x7b\x90\x39\x0d\x23\xbf\x9d\x36\x0a\x29\x3b\x83\x08\x38\x30\x86\x91\x6e\x11\x82\xb1\xba\x43\x36\xf0\x01\xb8\xd2\x0d\xea\xe9\xa0\x29\xf7\xe8\x53\x97\xa9\xae\x5c\xf3\xca\x10\xc7\xf3\x87\x55\x88\xb8\xff\xab\xb0\x63\xc0\x0c\xa2\x6f\x58\x0f\x69\xed\xc5\x27\xa1\xac\xcf\x4f\x41\x39\x7b\x33\x76\x6b\xcf\x6d\x55\xeb\x8d\xe0\x81\xa4\x8c\x98\x1d\x05\xc0\x66\x61\x7b\x80\xd8\xf6\xf5\xe6\x0e\x59\xdd\x9b\x93\x0b\xc4\xd0\x45\x86\x40\x3b\xb8\x68\xdf\x75\x93\x3b\xdd\x86\x23\x0e\x44\x70\x36\xc1\x75\xa1\x0d\xe9\xbb\x39\x95\x3d\xcb\x19\x66\xa1\xf1\x19\x12\x07\x8e\x35\x8f\x48\xc5\xb2\x09\xa6\x36\xc7\xf7\x83\xf4\xd3\x6a\x93\xad\x2c\xc2\xe3\x24\x45\x19\x07\x8e\x99\xde\x1d\x51\x58\xb3\x96\x1e\x0f\xc5\xa4\xf2\x60\xc2\x5f\x45\xf5\xe8\x58\x5e\x60\x1d\xb0\x8b\xa0\x58\xd2\x90\x9a\x1b\xf4\x99\x5f\x48\x13\x46\x0d\x36\x95\x03\xc6\x87\x36\x85\xeb\xcd\x33\x30\xa1\x30\xb7\x5f\x23\x65\xfb\x2a\x5a\x34\xea\x63\xd9\x58\xa2\xa8\x67\xe9\x05\x52\xd2\xce\xc8\xc3\x90\x08\x4b\xe0\xc1\x08\xb0\xfd\x2d\x83\xcb\x92\x84\xdb\x5b\x84\x2c\xbb\x5d\x0c\x3f\x6f\x1e\x26\x03\xc9\xc3\x0c\x0f\x6a\x9b\x11\x8e\x1a\x14\x3a\x15\xe3\x19\xfd\x1b\x60\x71\x52\xb7\xcc\x05\x47\x49\x79\x54\xc1\xf7\x29\x19\x9d\x0b\x23\xe5\x38\x65\x40\x3b\x0a\xd6\x80\xe9\xb4\x53\x69\xa6\xaa\x38\xd6\x68\x5a\xbd\x39\x7f\x07\xfb\xca\x40\x62\x7e\xca\xf8\xd8\xd3\x01\x33\xa6\xd9\xd5\xaf\x00\x91\x92\x75\x1c\x9c\x45\xf7\x7c\x0b\xc0\x11\x26\x88\x00\xbf\x55\x25\x12\x73\x0e\x69\x97\x3c\x5b\xf3\x62\xab\x16\x48\x94\xbf"}, -{{0x3d,0x09,0xaf,0xce,0xe3,0xc4,0x32,0xfd,0xfb,0x6b,0xdc,0xea,0xd5,0x4e,0x3d,0xa5,0xb1,0xb4,0x16,0x5c,0x50,0xd6,0xd3,0x10,0xb7,0xfa,0xd7,0x87,0xb4,0x44,0xd6,0x80,},{0xb0,0xd9,0x02,0x8c,0x4d,0x14,0x87,0xd2,0x93,0xed,0x58,0x5a,0x76,0xbc,0x94,0xff,0xfb,0xaf,0xe2,0xc6,0x5d,0x98,0x0c,0x49,0x4e,0x14,0x1e,0x48,0x10,0xa3,0x5c,0xb9,},{0x89,0x73,0x9f,0xe4,0x41,0xca,0x0c,0xed,0x08,0xa6,0xeb,0x57,0x96,0xe9,0xbd,0xda,0x0e,0x74,0xfb,0x47,0x35,0x28,0xfd,0x49,0x07,0xed,0xb6,0x59,0xaa,0xb4,0x4d,0x33,0x43,0x22,0x90,0x46,0x71,0x63,0x68,0xfa,0xf8,0x8e,0x85,0xc1,0x64,0x4a,0xf6,0x6f,0xf2,0xdc,0xaf,0x0b,0x17,0xac,0x93,0xca,0x13,0x81,0x9f,0x3f,0x24,0x1d,0xd3,0x00,},"\x76\x71\x65\xca\xae\x0e\x57\x8f\x16\x53\x7e\x17\x50\xbe\x7d\xe8\x7a\x78\x9a\x51\xff\x2d\xe1\x18\x38\xf5\x64\xe2\x58\x0b\x23\x91\x36\x2d\x28\x68\xa5\xa4\x70\x8a\xf1\x5d\x2e\x2d\xb7\xb9\xbe\x39\xc1\x6a\xdc\xc1\x20\x0b\x34\xe6\xb4\xd4\x02\x7d\xdf\xfc\x1a\x2a\x35\x95\xe2\x9e\x85\x5e\xc5\x26\x1b\x20\xbd\x55\xc4\x28\xb0\x13\x09\xba\xdb\x59\xe2\xca\x3e\xdb\x96\x7f\xc2\xf4\xba\xc0\x72\x9d\xdf\x54\xfb\x6c\x20\x05\x7b\xdd\xa9\xe7\xaf\x7c\xbf\xc0\x92\xfb\xa8\x65\xfd\x32\x75\xb9\xd3\xbc\xb0\xc3\x46\xb9\x51\xd1\x70\xac\x9a\xa6\x50\xa8\x6d\xf4\x98\x55\xd4\x8a\x1b\x37\xce\x56\xc9\xf2\x73\x89\xf5\xc8\xb1\x5f\x5c\x2c\x90\x0c\x4f\x10\x7c\x06\x4f\x60\x3e\x4f\x86\x7e\xf2\xe9\xc1\x0a\x1b\x74\x21\x0e\x6b\x89\xbb\x01\x17\x93\xaa\x85\xde\xd4\x3b\x51\xb7\x49\xba\x7f\x70\x28\x7b\x6b\xc1\xb8\x94\x34\xdb\x8b\x8c\x8b\x5d\x73\xb2\x14\xb4\x1e\x36\xb5\x28\x00\x5b\xfb\xfe\x00\x2e\x21\xb1\x00\x6f\xb9\xd2\x4b\xab\xd7\x21\x06\xd0\x93\xe3\xc7\x09\x3b\x31\x38\xae\xa7\x19\xd6\x94\x79\x08\x46\x47\x49\x8c\xd6\xc9\xbb\xb7\x44\x50\x9c\xd7\xda\x8d\xd6\x1a\x62\x71\x00\xf0\x3c\x21\xe7\x50\xac\xb3\xfc\xf4\x63\x1d\x7c\x0f\x61\x81\x54\xd2\xe5\xfa\x66\x56\xfb\x76\xf7\x4c\x24\x79\x50\x47\xbb\xce\x45\x79\xeb\x11\x06\x43\xfa\x98\xe1\xf7\x76\xca\x76\xd7\xa2\xb7\xb7\xb8\x67\x81\x73\xc7\x73\xf4\xbe\x7e\x18\x2f\xd2\x4d\xd7\x62\x91\xac\x67\xd9\xf2\x6a\x28\xc5\xe3\xcb\x02\x5c\x68\x13\xa3\x78\xb3\x83\x22\x46\x42\xb4\xae\xfa\xd0\xc7\x6a\x65\x79\x51\x7b\x8f\x36\x07\x97\xdd\x22\x61\x3e\xe6\x82\xb1\x79\x38\x19\x50\xfb\x71\x60\x9a\x5f\xb5\x49\x4d\x2d\x57\xdc\xb0\x0f\x26\xd1\xe7\x29\x56\xf4\xd6\x67\x28\x30\xe0\x5c\x01\xb3\x77\x96\x77\xc0\x7e\xa0\x09\x53\xc6\xb8\xf0\xdc\x20\x4c\x8d\xbd\xcc\xb3\x81\xbc\x01\xb8\x9c\x5c\x26\x1d\xb1\x89\xab\x1f\x54\xe4\x6b\xc3\xed\xc4\xde\x5a\xd4\xf0\xeb\x29\xc0\xa1\x20\xe4\x37\xcd\x8f\x37\xac\x67\xd4\x8c\x7f\x0e\x73\x02\x78\x70\x8f\x02\xb5\x4a\xee\x62\xb7\x29\x52\xbc\x1c\x0e\xb4\x37\xca\x8b\xd5\x65\x54\x37"}, -{{0x41,0xc1,0xa2,0xdf,0x93,0x69,0xcd,0xc9,0x27,0x16,0x4a,0xa5,0xad,0xf7,0x75,0x71,0x36,0xab,0xe5,0x13,0x95,0x60,0x42,0x66,0x33,0x4c,0xc5,0x46,0x0a,0xd5,0x68,0x3e,},{0x40,0x55,0x78,0x34,0xcc,0xe8,0xe0,0x43,0x58,0x0a,0x42,0x72,0xa8,0x80,0x4d,0x4f,0x92,0x6e,0x88,0xcb,0x10,0xd1,0xdf,0x0c,0x5e,0x28,0xb9,0xb6,0x7e,0x1b,0x63,0xda,},{0xb8,0xb2,0x75,0x2a,0x09,0x71,0x96,0xc2,0x89,0x84,0x9d,0x78,0xf8,0x11,0xd9,0xa6,0x2f,0xc7,0x67,0x27,0x8f,0x0c,0x46,0x62,0x8b,0x52,0x1f,0x62,0xed,0x27,0x59,0xd7,0x44,0x62,0xa1,0x75,0xda,0x22,0x40,0x3f,0x15,0x02,0x04,0x45,0xca,0xe0,0x6d,0xa3,0xed,0x61,0xcc,0xa6,0x20,0x3b,0x70,0x06,0x36,0x2a,0x0e,0x19,0x89,0x63,0xd2,0x0e,},"\xb6\x4b\x14\xba\x77\xd2\x39\xe6\xf8\x1a\xbe\x06\x0a\xcc\xef\x85\xf0\x44\x2b\x65\x0c\x44\x01\x5e\xfc\x43\xa0\xaa\x2b\xa1\x0b\xf4\x8d\x30\x18\xb1\x95\x3d\xdf\xff\xbc\xda\x5b\xf3\xbb\xe0\xb6\xb3\xe4\xb0\xd9\xa3\x2c\x6b\x72\x5b\xbb\x23\x1e\x0a\x27\x04\x47\x1e\xe8\xbc\x1d\x59\x4f\x5c\x54\x22\x6f\x5d\xd9\xdf\xa1\x63\xcf\xc1\x45\x2c\x61\xf9\x3e\x4f\x81\x39\xab\x4c\xe4\x47\x6f\x07\xec\x93\x36\x61\xea\xe9\x1b\x6d\x50\x0b\xf5\x08\xac\x63\xe4\xba\xaf\x1f\xfc\x8f\x00\x07\xd8\x02\xe0\x05\xf1\xb4\xfc\x1c\x88\xbe\xe4\xd5\xe9\xe7\x63\x84\xf5\xa7\x04\x3b\xd6\x60\xcc\xe7\x1f\x3b\x67\xf0\x1f\x6a\xb8\x44\x29\x85\x31\xaa\xc7\x3a\x39\xd0\x45\x37\x00\x88\x85\x50\x05\xa0\x9c\x6d\x04\x23\x8e\xa4\x78\xdf\xac\xad\x1e\x6b\x22\xb2\xbe\x4c\x46\xb0\xd5\x9b\x1e\xba\x1f\x06\x0b\xf7\xda\x5d\x15\x66\xcf\x1f\xdb\x5c\x54\x3a\x33\x92\x6a\xf6\x3f\x01\xa0\xdb\x86\xe1\xa6\x71\x1c\x47\x3d\xc7\x95\xab\x28\x3c\x8d\x93\xfa\xcf\xb5\x70\x1f\xa2\xf2\xf6\xbb\x99\xf9\xb7\xe3\x74\x9b\x07\x1d\x58\x60\x7b\xe4\x4a\x70\x89\xbc\xb5\x03\xec\x14\x95\xb5\xfe\xed\xb3\x99\x96\x1f\xd3\x67\x7d\x74\x93\xea\xa3\xb3\xe9\xcc\x5e\x36\x42\xf4\x0d\x47\xde\x9b\xfe\xe7\xc2\x0b\x0e\x51\x9c\x4e\xb4\xa4\x0f\x4d\xa4\x46\xed\x6a\xc7\xaa\xca\x05\x3e\x75\x9c\x97\xda\xbe\x0a\x8e\xc2\xf5\x8e\x7f\x2f\x9b\x20\x72\x76\x2f\x9f\x79\x4a\x6a\x4e\x36\x06\x0b\x88\x72\xbd\x2c\x18\xd0\x6a\x85\xc2\xc1\x41\xa7\x82\x93\x77\x3e\xe8\xcf\xbf\x15\x4b\x99\x30\xcd\x39\xda\x31\xb4\x97\xe7\x37\xa7\x75\x0c\x90\xa1\x3f\x5a\xaa\x14\x7c\xd0\xdc\x43\x11\xf2\xe3\x49\x41\x25\x2e\xf1\x98\xb0\xc1\xf5\x08\x27\xe5\x6c\x9f\x16\xf5\x95\xac\xed\x6d\x2a\x69\x34\x65\x31\x49\x5a\x64\x99\x77\x4d\x36\x07\x66\xca\x9b\xe5\xed\x88\x81\xc0\xdb\x26\xed\x7c\x5e\x6f\xf3\xa4\xf9\xb7\x3c\xd8\xb6\x54\x64\x0d\xc9\x6b\xf4\x3b\xd4\x26\xa0\xf2\x8c\x9b\x25\xfa\x70\x4d\x62\xff\x02\x88\xfc\xce\xff\xaa\xeb\xd3\xea\x30\x97\xbc\xbb\xd7\x78\x42\x0e\xbc\x52\x0a\x41\x77\x30\xa1\xb5\xb3\xb8\xc9\x6c\xda\x9f\x4e\x17\x7d"}, -{{0xa0,0x06,0x11,0x48,0x94,0x67,0x12,0x2c,0x4c,0x16,0x4b,0xfb,0x6a,0x61,0x6e,0x6a,0x61,0x9b,0x9f,0x83,0xc4,0x36,0x72,0x06,0xb8,0x5d,0x3f,0xbe,0xc3,0x8c,0xd6,0x2c,},{0x57,0xab,0x58,0xba,0xbb,0x41,0xdc,0x0d,0xa0,0xbc,0xd5,0x06,0x05,0x9a,0xac,0x9f,0x46,0xec,0xa9,0x1c,0xd3,0x5a,0x61,0xf1,0xba,0x04,0x9a,0x9a,0xc2,0x27,0xf3,0xd9,},{0xc7,0x71,0xba,0x0a,0x3d,0x3c,0x4a,0x7b,0x06,0x4b,0xd5,0x1a,0xd0,0x5c,0x9f,0xf2,0x7f,0xd3,0x26,0x61,0x0f,0xbf,0xa0,0x91,0x83,0x03,0x9e,0x5e,0xdf,0x35,0x47,0x2d,0xde,0xd8,0xfc,0x22,0x75,0xbb,0xcc,0x5d,0xf1,0xbf,0x12,0x98,0x60,0xc0,0x1a,0x2c,0x13,0x11,0xda,0x60,0x2f,0xba,0xff,0xc8,0xb7,0x9c,0x24,0x9c,0x9c,0xc9,0x55,0x02,},"\x34\xdb\x02\xed\x75\x12\xbf\x8c\x67\xd3\x59\xe7\x20\x3a\x2e\xa4\x41\xe2\x0e\x72\x97\x66\xc1\x5a\xa0\x0f\xa2\x49\xa3\x51\x8f\xc2\x9e\xf8\x90\x5a\xa5\xb4\x67\x09\x58\xc6\xa4\x60\xd7\x7b\x3a\x80\xef\xcb\x47\x38\x59\xbb\xaf\xf8\x62\x22\x3e\xee\x52\xfe\x58\xac\xfd\x33\x15\xf1\x50\xf3\xc6\xc2\x7f\xf4\x8f\xca\x76\x55\x2f\x98\xf6\x58\x5b\x5e\x79\x33\x08\xbf\x59\x76\xba\xd6\xee\x32\x7b\x4a\x7a\x31\x32\x14\xb9\xae\x04\xb9\x65\x1b\x63\xcd\x8d\x9f\x5b\x3b\xec\x68\x9e\x0f\xd0\x00\xdd\x50\x17\x70\xdd\x0e\x99\xb8\xf9\x9e\xaf\xa0\x9c\x39\x6a\x24\x5a\x4a\x96\xe5\x68\x96\xa2\x9b\x24\x19\x0b\x1e\xf1\x10\x63\xf3\x9b\x63\xee\x3a\x58\x6b\x07\x62\x7d\xd3\x50\x0c\x4e\x17\x0b\x83\x5d\xc0\xec\x23\x6f\xa5\xa3\x5c\x44\x18\x47\x07\x56\x5c\x4a\x50\x66\x2d\x8d\xbc\xcf\xff\x7f\x9a\x7a\x68\xd0\x21\xb4\xaf\x64\xd5\x32\xb7\xc3\xd2\x74\x74\x18\xc2\xd7\x17\xbb\x6a\xca\x6b\x58\x74\x7a\xe4\xdd\x56\x41\xd8\x26\xf7\x9a\x8a\x31\x5c\x38\x21\x1a\x53\x8a\x92\x9e\x5b\x45\x1f\x62\x3f\x4f\xcb\xbc\xac\xdb\x86\xc8\x75\x2e\xa1\x3a\x61\x7a\xb4\x14\xab\x65\x3e\xb2\xe6\x8d\x54\x20\xdf\x7c\x6d\xf9\x24\x38\x16\x8d\xcf\x9c\x06\x65\x81\xdf\xe7\xb2\xc4\x68\x19\x4a\x23\x70\x7d\xe4\x65\x9b\xd6\x7e\xb6\x34\xff\x02\x47\x41\xc5\xfc\x86\x98\xfd\x4d\xc4\x1f\xe5\xdf\xc6\x29\x9b\x7a\x08\xe6\xff\xca\x37\x10\x9c\x02\x10\xc8\xf9\x4e\xa2\xd3\xdd\xc9\x77\xff\xc0\xb3\x79\x4f\xe6\xba\x43\x37\xc7\xaa\xb4\x34\xa6\x8a\xc6\x65\x48\x4e\xa8\x24\x3a\x84\xb7\x9a\xa1\x81\xee\x6a\xb5\xaa\x37\xa3\x2d\x87\x97\x25\xed\xc0\x18\xf8\x55\x21\x81\x81\x6d\x7d\x27\x2c\xa8\x81\x8a\x7b\x92\xe6\xee\x44\x54\xd1\xf7\x82\x8d\xd8\xaf\xba\x1a\x79\x03\x64\xb4\xff\x28\xd8\x4e\x02\x85\x97\x35\x3e\xbb\xef\x24\x83\x7b\xc3\x19\xe1\xae\x8f\x2b\x0b\x6a\x85\x1b\x48\x9c\x3e\x17\x0e\xef\x53\xe0\x65\xf7\x03\x26\x53\xcd\x6b\x46\xd8\xe5\x7e\x4e\x11\x1b\x78\x9b\xa9\x50\xc4\x23\x0a\xba\x35\xe5\x69\xe0\x66\x15\x40\x34\x07\xbc\xe0\x36\x9a\xaa\xb4\xea\xfa\xef\x0c\xae\x10\x9a\xc4\xcb\x83\x8f\xb6\xc1"}, -{{0xde,0x16,0x34,0xf3,0x46,0x0e,0x02,0x89,0x8d,0xb5,0x32,0x98,0xd6,0xd3,0x82,0x1c,0x60,0x85,0x3a,0xde,0xe2,0xd7,0xf3,0xe8,0xed,0xd8,0xb0,0x23,0x9a,0x48,0xcf,0xaf,},{0x9d,0xc1,0x46,0x5b,0x33,0x83,0xf3,0x7d,0xe0,0x0e,0xa2,0xd3,0xc7,0x0f,0x2c,0x8f,0xac,0x81,0x5f,0x01,0x72,0x02,0x9c,0x3f,0x57,0x95,0x79,0xc9,0x84,0xa5,0x89,0x5e,},{0xd2,0x05,0x06,0xeb,0x84,0x69,0x23,0xa0,0xb1,0x6f,0xf8,0x2f,0xb2,0xc3,0x92,0x3b,0x00,0xc1,0xb3,0xbc,0xc6,0xe2,0xf6,0x48,0x2f,0xba,0x24,0x80,0x75,0x21,0xe8,0xe0,0x22,0x3f,0x69,0x2e,0x62,0xea,0xc9,0x93,0xf4,0x98,0xf6,0x71,0x02,0xa0,0x4f,0xd1,0xac,0xf9,0xc7,0xe3,0x88,0x8d,0x85,0x7c,0x9a,0x08,0x0b,0x8a,0xf6,0x36,0x10,0x06,},"\xd1\x0c\x3e\x4d\xe7\xfa\x29\x89\xdb\xa8\x75\x37\xe0\x05\x93\xd0\xee\xd4\xd7\x5e\xe6\x58\x46\xda\xb1\x49\x8b\x47\x49\xd6\x4f\x40\xe3\x4b\x59\x11\xc5\xce\x3b\x53\xa7\xe3\x7d\x2d\x02\xbb\x0d\xae\x38\xed\x96\x2a\x4e\xdc\x86\xc0\x02\x07\xbe\xe9\xa8\xe4\x56\xec\xca\xe8\xbd\xf4\xd8\x7a\x76\x74\x60\x14\x20\x1a\xf6\xca\xff\xe1\x05\x66\xf0\x8d\x10\xda\xaf\x07\x71\x60\xf0\x11\xfe\xac\xa2\x5b\x9c\x1f\x6e\xca\x9f\xc5\x33\x14\xa8\x05\x47\x95\x17\x54\x35\x55\x25\x25\x7d\x09\xa7\xfd\xad\x5b\xc3\x21\xb7\x2a\xa2\x8d\x1e\x02\xd8\x69\x6d\x4f\x9e\xb0\xad\x3b\x21\x96\xf8\xbc\xfa\xeb\x1d\x61\x48\x28\x7a\x3f\xae\xfe\xf9\x1a\x7a\x3e\x06\x09\xc2\x8c\xe5\x9d\x0c\xa1\x4d\x0b\x30\x50\xdd\x4f\x09\x6b\x7b\xc2\x51\x39\x88\xba\x21\x21\x28\xd5\x02\x6d\xaa\xa7\x18\x88\x46\xdb\x21\xc5\xc1\xd1\x79\xab\x94\x87\xc1\xa5\xbd\x34\x65\x88\x12\x7c\x20\x39\x8d\x36\x2d\x4c\x75\x9c\xfa\xb2\xa6\x77\x75\x0b\x9e\x45\x67\x6a\x1e\x7e\x09\x2e\xf0\x2e\xdb\xf2\x78\xfb\x19\xa5\x8e\x9b\xf6\xc9\xe9\x96\xe2\x4e\xda\xd7\x3f\x3c\xe3\x1f\xa0\x4b\x6d\x85\x33\x43\x6b\xf8\x0b\x4b\x2f\x80\x5e\xd9\x1e\x7f\xcd\xa3\xbc\x2b\xab\x3b\x2b\xb1\x57\x15\x8a\xf0\xea\x8e\x3f\x07\x31\xdf\xad\x45\x9d\x2e\x79\xb6\xd3\x71\x5f\xe7\xbf\x1e\xaf\xc5\x39\x75\x93\x20\x88\x57\xe5\x7b\x7f\xeb\x2f\x73\x87\x94\x3a\x8e\x09\x13\x47\x0c\x16\x1a\xef\x4f\xe2\x05\xd3\x63\x7f\x23\x17\x7f\xf2\x63\x04\xa4\xf6\x4e\xba\x3f\xe6\xf7\xf2\x72\xd2\x34\xa6\x72\x06\xa3\x88\xdd\xd0\x36\x6e\x89\x4e\xaa\x4b\xb0\x5d\x73\xa4\x75\xf1\xb3\x4c\xa2\x22\xbb\xce\x16\x85\xb1\xb5\x6e\x03\x4e\x43\xb3\xc4\x0e\x81\xff\xf7\x96\x82\xc1\x9f\x32\xaa\x3f\x2a\x89\x5c\x07\x09\xf9\xf7\x4a\x4d\x59\xd3\xa4\x90\x29\xec\xfc\xb2\x83\x08\x2b\x06\x7f\x1a\x0d\x95\x05\x75\x0f\xd8\x67\x32\x19\x99\x48\x42\x49\xef\xa7\x25\xf5\x2c\x94\xc7\x59\x62\x06\xa9\x11\xf3\xf5\x05\xd6\x3f\x03\x13\x25\x4b\xd4\x45\xf0\x5b\xe3\x99\x6b\x58\xfe\x18\x19\xaf\x87\x35\x2e\x7f\x0a\x2c\xa3\x20\xd9\xcc\x00\xa5\xfe\x77\xad\x41\x64\x0d\x50\xbe\x84\x36"}, -{{0xc7,0x38,0xef,0x5f,0x09,0x35,0x28,0x1b,0xa6,0x25,0xfa,0x40,0x14,0xd4,0xa4,0xd0,0xbe,0x7e,0x28,0xfe,0xd7,0x79,0xa9,0xcf,0x65,0x8e,0x21,0xdb,0xa4,0x3c,0xeb,0xc1,},{0x95,0x79,0x9f,0xaf,0x70,0x6d,0x19,0x5e,0x54,0x4c,0x76,0xca,0xfd,0xdf,0x09,0xd0,0x2d,0x1b,0xea,0xfc,0x42,0xc9,0xd6,0xc9,0xea,0xd4,0xc1,0x84,0x55,0x87,0xd3,0x9e,},{0xf4,0x43,0x71,0xe6,0xc3,0x39,0x16,0x39,0xd4,0x57,0xed,0x14,0x64,0x81,0x84,0x80,0x94,0x11,0xe8,0x0a,0x32,0x01,0xf8,0x81,0x16,0x70,0xe5,0x00,0xfc,0xad,0x92,0xf3,0x00,0xaa,0xbf,0x7f,0xc6,0x8e,0x44,0x01,0x91,0xe8,0x81,0xd6,0xc3,0x47,0x4e,0xfd,0x6d,0x28,0xf0,0x9d,0xc4,0x43,0x12,0xfc,0xfc,0xb8,0x27,0x01,0xba,0x3c,0x29,0x0a,},"\x16\x8d\x0b\xc5\x59\x8b\xe0\x2f\x54\x43\xbf\xe7\xdf\xb8\x82\x99\x85\xca\x5d\x28\x2a\xf9\xcf\x1b\x14\x82\x60\x2f\x24\x3d\x48\x6b\xd8\x2b\xa0\x39\xa0\x75\x09\x09\xe9\xb3\xc7\xd4\xd5\xf8\xb8\xba\xf4\x57\x18\xaf\x03\x11\x85\x4f\x4d\x1c\x78\x37\xf3\x1d\x8e\xe6\x8d\x35\x58\xe7\xe5\x1e\x0c\x64\x6a\x4a\x63\x75\x96\xee\x90\x05\x7b\x01\xed\x0a\x17\xda\xa3\x95\x0b\x81\xab\x47\xae\x8b\x94\xc1\x7d\x40\x74\x69\x13\xc4\x6b\xa1\x47\x8b\xfc\xa5\x1b\x16\x76\x28\xfc\x3e\xe1\xe2\x2f\x2f\x19\xd6\xd8\xda\xf9\x3d\xf6\x54\x0c\xed\xb7\xa8\x59\xd1\xa2\xba\x59\x11\xba\x71\x76\x6e\x8b\x7f\xce\x0c\x0e\x86\x63\x61\x6d\x01\x80\x69\x7d\x78\xce\x30\x40\xd4\x38\x13\x19\x82\xf3\xf8\x11\x2a\xcc\xa2\x9a\xe5\x3e\x53\x9f\xf8\xc9\xec\x41\x06\xd1\x32\xf4\x02\x01\x85\x18\x30\x84\x85\xf2\xaa\x6c\x9e\x8d\x1e\x62\xfe\xd6\x0c\xb2\x49\x45\x7d\xb3\x3c\x6f\xd1\xfe\x07\x44\x53\x61\xf0\x81\x94\xa2\xb5\xa0\x57\xcb\x03\xcc\x75\x4e\x5c\x7d\x4a\x7e\xea\x53\xa7\xf7\xd2\x07\xca\xcc\xa5\xe6\x8c\xaf\xa9\x69\xa3\x52\x1d\xbb\x81\x03\x99\xa1\x7f\x32\x8e\xe7\x67\xcf\x55\x92\x6b\x2b\xd5\xf0\x29\x54\x9d\x3b\x46\x45\x79\xc4\x26\x55\x26\x53\x98\x47\x2e\x1c\x77\xcc\x8d\xd9\xaf\xf1\x87\xf7\xac\x34\xdd\x45\x6a\xce\x99\x9a\x73\x6e\xcc\xa6\xd4\x05\xd4\x92\x2c\x77\x9c\x60\x0c\x47\xb8\x4c\x9c\x1d\xf5\xe5\xf8\xed\x3b\x28\x11\xd3\x51\x33\x91\x13\xf8\x45\x3c\xca\x4c\x44\x11\x68\x8c\xb0\x38\x82\x58\xeb\xbd\x18\x72\xb8\x36\x10\x04\x22\x49\x49\x4e\xd5\x60\xd4\xcd\xa6\xa6\x84\x55\xd9\x57\xe8\x06\xdd\x0b\xdd\x83\x00\x4c\x4c\xa8\x07\x74\xb8\xa0\xa1\x66\x58\x66\xf1\x70\x85\x01\x4e\xad\xb3\xea\xe7\x38\x2f\xa8\x70\xde\xb2\x9d\xd8\xc9\x31\xb5\x30\x19\x62\x57\x40\xe2\x83\x92\xf3\x85\x75\xc0\xe2\xa9\xe5\x04\xfc\x35\xbd\x95\xdf\x56\x43\x9a\x89\x82\x30\xa2\x39\x8c\xd2\x22\x5c\x76\x6e\xf3\x6f\x12\xae\x7e\x49\xb3\x0a\x9c\x0a\xad\x46\x9d\x58\x95\xbb\xf7\x21\xcc\x0f\xf5\x1d\x84\x0c\x80\x2d\x4a\x7e\xef\xba\x84\xfe\x52\x05\xa2\xc2\xf1\x40\x11\x92\x2d\xde\x56\x14\x56\xf7\x9e\x61\x61"}, -{{0x5f,0xea,0x38,0x73,0x9c,0x61,0xca,0x83,0xbf,0x7b,0x4a,0xd1,0x75,0xa2,0x11,0x76,0x27,0xb9,0x71,0xa6,0x34,0xa3,0x05,0xa8,0x4f,0xa5,0x7f,0xec,0xb8,0x03,0x56,0x24,},{0xdd,0xd1,0x4b,0x0f,0xc0,0x67,0x68,0xd5,0x10,0x4c,0x50,0x76,0x4b,0xfd,0x3b,0x95,0x23,0x52,0xa3,0x40,0x07,0xc5,0x0d,0x5d,0xdd,0x22,0x4f,0xf5,0x1a,0xfc,0xdf,0x9c,},{0xf4,0xe2,0x74,0x82,0x3f,0x2c,0x39,0x6f,0x3a,0x32,0x94,0x86,0xaa,0x64,0x10,0xc5,0xff,0x19,0x26,0x6f,0x07,0x70,0xfd,0x04,0xfb,0x14,0xa7,0x60,0x2d,0x2b,0x69,0xa4,0xa2,0xb0,0x09,0x28,0xe9,0xe1,0xd9,0x23,0x89,0xf8,0x03,0x33,0x59,0xed,0x6f,0xb2,0x14,0x64,0x67,0xaa,0x15,0x4c,0xba,0x59,0x7d,0xec,0x6a,0x84,0x17,0x3f,0x8d,0x07,},"\x10\x13\xc6\x0a\x73\x95\x35\x49\xe5\xed\x10\x5b\xde\xa1\x50\xb9\x1e\x60\xec\x39\x20\x0d\x43\x72\x13\x04\xbf\xc8\xec\x43\x9d\x39\x60\x96\x13\xc2\xd8\x78\x04\x4a\x9d\xa0\x1b\x26\xd8\x6d\x6d\x65\xdb\x93\xd9\x1a\x13\x7e\x9c\x48\x08\xa9\x7d\x4e\xf2\x86\xa9\x03\xf3\xf1\x38\x2c\xc6\xd1\x29\x42\x16\xb9\xfa\xfc\x01\x3c\x86\xb9\xff\x68\xb5\x5a\x50\xea\x37\x66\xe6\x1d\xc1\xce\x38\x34\x8e\x91\xd6\x2c\xe7\x32\xc1\x52\xd7\x66\xb9\x33\x5c\x68\xd6\xca\xd7\x7b\xe2\xb4\xa0\xcd\x50\xb9\xa1\xec\x63\x2b\xa5\x56\x48\xa6\xe7\xe1\x1a\x14\xc0\x68\x53\xc0\x2a\xec\x48\x09\xbd\x14\x7a\x5d\xdd\x9f\xbc\x3b\xe9\xf0\xc8\x15\x8d\x84\xab\x67\x95\xd7\x71\xb4\x2b\x18\x14\xa1\x7a\x3c\x7a\x6c\xa0\xf4\xa8\xf7\xb3\xa0\xdb\x1c\x73\xba\x13\xb1\x64\x00\xdf\xec\xbd\x03\xd2\x16\x65\x0e\x4d\x69\x70\x4a\x70\x72\x46\x44\x4d\x57\x91\xfa\x27\x37\x52\xf5\x9c\xb5\xae\x9f\xd4\x16\xa5\x18\x66\x13\xd6\x6a\xfd\xbd\x1c\xe6\x91\xa8\x7b\xd7\xd8\xb6\x71\x90\xe9\xac\x68\x70\x62\xa0\x80\xd2\xec\x39\xfe\x76\xed\x83\x35\x05\x82\x51\x87\x28\x39\xe8\x5e\xb6\x2f\x18\xec\xe1\x87\xca\xba\x55\xb5\xf7\xd5\xed\xca\xde\x01\xcd\xc5\x43\xcc\x67\x7e\x50\x23\x8b\x89\xc5\x63\x5a\xd5\xc8\xfc\x22\x0f\x5e\x0b\xe1\xbc\x66\x7d\x20\x98\x97\x53\xa6\xd6\x16\xfa\x69\xf8\xb1\x29\x40\xb8\xca\x9e\x2c\x48\x57\x71\x32\xd8\x69\x1b\x05\x37\x79\xa1\x52\xcb\xac\xff\x3b\x8b\x1b\xd7\xaf\x69\x2e\x56\xc7\x3b\xba\xe4\x63\x47\x76\xcf\xc2\x13\xc9\x9b\x9a\xe4\x58\xdf\x1b\xef\xc8\xc8\x77\x74\x26\x64\xb0\xa0\xbb\x1f\x69\x15\xc8\xda\xe3\xb3\xf5\x5d\xd7\x5a\xba\x6a\x3b\xcc\x41\x76\xb4\xe3\xba\x03\xd0\xc1\xc0\x4c\x3c\x64\x08\x77\x8b\x2b\x8e\x5a\x8a\x3e\xb5\x2e\xd3\x2a\x74\x28\xc0\x0a\x98\xa5\x89\xd8\xca\x93\x90\xa2\x10\xf4\xa7\xac\x00\x4f\xa1\xfe\x4c\x6d\xa6\x94\xf1\x22\x76\xe3\x20\xb4\x1b\x0b\x59\xf7\x5d\x26\x4a\x39\x6d\x45\x0b\x63\x1a\xb3\x53\xf1\x61\x27\x09\xe7\xa2\xe6\xa5\x0d\x01\xcb\x11\x0e\x53\x04\x05\x46\xdd\x3b\x1e\x11\xd2\x57\x32\x81\x3a\xa7\x6b\xe5\xe8\x1f\xcf\x7a\x57\x73\xf6\x81\x5b\xbd"}, -{{0x60,0xf9,0xa1,0x4c,0xce,0x5d,0x43,0xfd,0x9a,0xab,0x4e,0xe8,0xcc,0x83,0x79,0xd5,0x75,0x94,0x91,0x52,0x69,0x3b,0xf2,0x9a,0x67,0x90,0xb0,0x35,0xe4,0x2a,0x44,0xde,},{0xbd,0x4a,0x70,0x74,0x0d,0x5a,0xca,0xbe,0x49,0xf9,0xa2,0x15,0x20,0x82,0xfa,0x20,0x25,0x33,0x0e,0x64,0x40,0x43,0x7f,0x1d,0x04,0x7f,0x31,0x3d,0xe4,0x90,0xdc,0xa5,},{0x72,0xf5,0x4b,0xb8,0xbd,0xd1,0x7e,0x9e,0x42,0x2c,0xd3,0x39,0x63,0x1d,0xd3,0x9f,0x57,0x35,0x50,0x15,0xd4,0xcb,0xd1,0x5a,0xca,0xb7,0x54,0x2e,0xfd,0x78,0x4a,0x32,0x1c,0x1f,0x61,0x25,0x76,0x4c,0x0d,0x15,0x40,0x45,0xb3,0x2e,0x70,0xdc,0x2e,0x03,0xfb,0xfe,0x11,0x17,0x46,0x8a,0xc3,0xe7,0x31,0x27,0xb5,0xfa,0xc8,0xd4,0x21,0x02,},"\xdd\x7f\x44\xf9\xeb\x72\x8a\xb4\x8d\xe5\x4e\xcd\xe6\xb6\x18\x4b\xd5\xdd\xd8\x70\x75\x45\xa0\x12\x9f\x2e\x90\x59\x05\xb5\x5d\x3e\x7f\xd5\x7e\x28\x48\x5d\x25\x81\x48\xf6\x60\x5e\x23\x77\xd5\xb2\x67\xd2\xea\xf4\xcd\x4b\x46\xe4\x54\x96\x22\x19\x86\x82\x32\xb6\xf4\x1f\x88\xa7\x97\xf9\xcd\xd5\xc3\x9a\xda\x51\xa6\x41\x21\x4f\xb9\xdb\x2c\x2a\x9b\x5a\x5b\x16\xe3\x03\x57\x53\x18\xb6\x25\xcc\xa9\x70\xb7\x43\x48\x72\x79\x02\xa1\xcf\x26\x8b\xd1\x6e\x10\x71\x13\x16\x1c\x8c\xbc\x99\x30\x3c\x2b\x9f\x23\x55\x41\xa7\xb3\x1e\x43\x31\x20\xfe\xba\x14\xfe\xbe\x4b\xcb\x0f\x5b\x93\x6c\x7e\xdd\xdd\x0e\xcf\xc7\x2c\x8d\x38\xf6\x4c\xdb\x6c\xfc\x29\x10\xbc\x29\xa5\x21\xc5\x0a\x51\xab\xcb\xc2\xaa\xbf\x78\x9d\xe8\x22\xcb\x04\xf5\x72\x8f\xee\x15\x3d\xd5\x50\x1b\x2d\xb5\x9c\x59\xf5\x0c\xab\x17\xc2\x92\x16\xd6\x69\x51\x01\x9e\x14\x5b\x36\xfd\x7e\x84\x1b\xfb\xb0\xa3\x28\x55\x4b\x44\xdd\x7e\xf5\x14\x68\xc3\xd5\xb7\xd3\xa1\xf7\xb9\xde\xf5\x8d\x8c\xf9\xd9\xbc\xaf\xe9\x2c\x86\xcf\x6d\x61\x19\xe9\x8d\xba\x6f\x38\xea\x57\xe3\x22\xdd\xc9\xc2\x19\x8d\x4b\xbc\x3b\x94\xea\x13\x29\xdb\x0d\x45\x8e\x01\xc7\x08\x1b\x33\x92\x5a\x3e\x28\x7f\x59\x9a\x85\x8c\x50\xc3\xa8\xf1\x8c\xc2\xaa\x63\x4d\xf6\x3e\x7f\x10\xe4\x03\xad\xea\xb2\xf4\x1d\xb5\x57\x87\x90\xc3\xb4\xf0\x41\xa8\xb7\xa4\xf6\x9c\xd6\xe0\x62\x15\xdf\x82\x01\xae\x5b\x3e\x1d\x1d\x25\xa0\xa3\x9b\xfc\x3d\x04\x1a\x2f\x98\x21\x3e\xf4\x14\x12\x45\x79\x2a\x76\xf0\x6d\x4d\xe2\x5f\x64\x67\xa0\xe5\x6f\x2f\x5c\xf6\x94\x00\xd2\x21\x17\xde\x7b\x46\x14\x95\x54\xb7\x0c\x75\xb9\xf9\x94\x84\xa4\xf6\xf0\x35\xad\x3f\x10\xe3\x75\x3c\xb1\x4f\x4f\x39\x8d\xcf\x6a\x64\xd1\x0c\xf6\xc4\xfa\xc0\x7c\x91\x19\x3c\xc0\xf5\x4f\x0d\xe5\x8c\x63\x43\xe9\xca\xaa\x6b\x4f\x47\x5e\xf9\x1a\x59\xe0\x83\xf9\xf2\x11\xf5\xbc\x8e\x7e\x45\x16\xb4\x5c\xf0\x6b\xf5\x0b\xeb\x8f\xc4\xab\x57\x9d\x86\xd4\xa4\x19\x0e\xea\xc7\x48\xd0\x6e\x08\x52\xc4\xb9\xba\x8c\xfc\x50\xdd\x0a\x03\x7a\x7b\xad\x7f\xad\x55\xaf\x30\x9a\x5f\x13\xd4\xc9\x1e\xd3\xe0"}, -{{0xa3,0x90,0x53,0xc5,0xc5,0x8b,0xf3,0x1d,0x46,0x2b,0x27,0xa6,0x20,0xb0,0xb3,0x7b,0x80,0x52,0xc6,0xb1,0xc4,0x10,0x2b,0x61,0x45,0x66,0x3a,0xa1,0x5e,0x97,0x87,0x18,},{0x36,0x42,0xac,0x2a,0x32,0x80,0xdc,0xe5,0x2a,0xd8,0xdf,0xcf,0xd3,0x70,0x94,0x36,0xed,0xc4,0xe7,0xe4,0xae,0x1b,0x45,0x2d,0x9b,0x22,0x07,0x80,0xb0,0x86,0x79,0xfa,},{0xf7,0x38,0x3e,0x96,0x6c,0xb2,0x30,0x9d,0xee,0xdf,0x86,0x01,0x00,0x18,0x3a,0xae,0xfa,0xc6,0x72,0xca,0x16,0xd5,0x41,0x9c,0xd6,0x42,0x2c,0xa7,0x0e,0x16,0xb3,0x97,0x6f,0x5f,0x16,0x5a,0xfc,0x27,0x86,0x11,0x7c,0x86,0x82,0x34,0xba,0x11,0x09,0xed,0xe0,0x31,0xf8,0x97,0x9b,0x50,0xe5,0x67,0x35,0x8b,0xd4,0xf8,0xbd,0x95,0x82,0x02,},"\xf6\x55\x40\xd3\xab\xeb\x1e\xe5\xea\x98\x70\x62\xc1\xb5\x79\x51\x6d\x3c\x29\xc3\x9c\xbc\x6b\x09\xd6\x0e\x18\xfe\x27\x4c\x2b\xef\xe0\xf5\xfe\x7d\xbd\x57\xc2\xd5\x83\x52\x29\xbb\x75\x4e\xc4\x34\x13\x94\x76\x57\x76\xd6\xa9\x17\x8c\x4e\x6a\x31\x2c\xd7\x4b\xdb\xac\xa0\xe8\x82\x70\x62\x8c\xd8\x41\x00\xf4\x72\xb0\x75\xf9\x36\x92\x83\x01\x22\xf0\x0f\x9b\xd9\x1a\xc5\x82\x83\x6c\x8b\xfa\x71\x4a\xa4\x8e\x97\x70\x03\x55\x6e\x1b\x69\x6d\xf3\x28\xef\x58\x4f\x41\x3f\x8a\xb6\x14\x76\x06\x99\xc4\xd1\x47\xc3\xee\xa1\xda\x04\x35\x83\x5c\x9b\xf7\xad\x54\x60\x6f\x02\x13\xeb\x74\xa1\xb4\x76\x14\x15\x06\xae\x2c\xd1\x24\xcd\x51\xd6\x6e\x7e\x7e\x57\x95\x60\x57\x63\x05\xc5\xfb\xe8\x43\x0b\xe3\xeb\xeb\xaa\xcb\xa3\xf9\x98\x9d\xd7\xd1\x99\xf5\xa4\x55\xa5\x0c\xdb\x37\x55\x03\x7e\x1a\x70\x67\x4a\x4f\xef\x40\xb4\xa3\xaa\xf7\xbd\x3c\x95\xb1\xab\x41\xbb\x20\x62\x11\xc3\xa1\x27\x6d\x3e\x37\xd8\xa3\xa5\xc3\xd5\xd0\xf3\x6e\xf5\xb4\xf3\xde\x26\xb7\xf2\x0f\x6b\x29\x00\x71\x6d\xcc\x22\xab\x73\x4e\xba\xf1\xe8\xd0\x00\x20\xe5\xf0\x19\x55\x16\x53\xb9\xc2\xf7\x0a\x40\x38\xdf\xb2\xf1\x2d\x25\xd6\xd8\x4e\x79\x07\x3a\x65\x48\xfe\x15\xe4\x82\x8f\xe5\xde\x83\xac\x3d\x8d\x98\xb7\xda\xf9\x27\x10\x48\x2c\x37\xf7\xbd\x24\x31\xa8\x11\x4c\x61\x37\x65\x7b\xb1\x77\x88\x2d\x8a\x3c\x76\xba\xbf\x1c\x67\x1a\x70\x55\x36\x5f\xe9\x08\x66\x16\x7a\x2d\x1d\xbc\x87\x0b\xe8\x3b\x36\x01\xf0\x9d\x4a\x31\x7a\xe2\x54\xca\xc9\xf9\x8d\xcc\x7a\xea\xd9\x22\x4c\xd9\xc9\xd8\xa2\x00\xab\xc8\x0a\x2d\xd1\x08\xaf\x28\xfd\x46\xad\x70\x80\xae\x74\x1b\x50\x05\x4b\x9b\x9a\x92\x01\xef\xb7\x83\x8b\xc4\xc5\xc2\xcc\x3d\x76\xba\x0f\xcc\x49\xc4\x6e\x79\x2c\x26\x29\x2b\x7d\x03\x12\xaf\xf9\x55\xa9\xf8\xed\xf0\xc6\x96\xa7\x0a\x61\x4f\x35\x53\xad\x38\x69\xbf\xde\x48\xd2\x6a\x4d\x36\x7b\x6c\xec\x05\x7e\x62\xa4\xe5\x48\x55\x4b\x48\xb5\x3e\xcd\xa7\x90\xba\x7a\x0a\xb2\xe3\xde\x58\x7b\xdc\x22\xb0\x2f\x59\x47\x63\x4d\x73\x09\x9f\x54\x7d\xb2\x2e\xc1\xbb\xf8\x23\x43\xf9\xa2\xca\x38\xbc\xe4\xeb\x59\xbe"}, -{{0xe0,0xc2,0x9d,0xf4,0xde,0x45,0xc4,0x75,0x39,0xe0,0x89,0x6b,0x3a,0x59,0xbc,0x3d,0xe6,0xb8,0x02,0xfd,0x14,0xdb,0xdc,0x9f,0x25,0xe7,0x17,0xac,0x82,0xc3,0x28,0xf3,},{0xa6,0x90,0x02,0xb0,0xf5,0xef,0x35,0x4c,0xe3,0xb2,0xd6,0xb8,0xd8,0xba,0x70,0xab,0x77,0x84,0x32,0xb2,0x2f,0x14,0x4d,0xc9,0xc2,0xeb,0x92,0xd9,0x9d,0x99,0xdd,0x2a,},{0xbb,0x3b,0x8c,0x5c,0x27,0x59,0x1f,0xd8,0xb9,0xc5,0xba,0x48,0x9d,0x6b,0x6e,0xe5,0xb0,0xfb,0x4a,0x7b,0x0d,0xe5,0x1f,0x16,0x39,0xaf,0xc6,0x73,0xd0,0xe5,0xf7,0x5e,0x31,0x3a,0xa7,0xe1,0xd0,0x00,0x90,0x81,0xdb,0xca,0x74,0x35,0xb6,0x87,0xcc,0xd1,0x2f,0x64,0xf7,0x4a,0x38,0x6e,0x77,0x2b,0x9e,0x24,0x78,0x1b,0x92,0x5c,0x8c,0x0c,},"\x6a\x37\xcb\x4c\x74\x9c\x58\x35\x90\xc8\xd8\x49\xbc\xe3\xfa\x65\x7f\x10\x00\x91\x90\xca\xd9\xbe\x41\xed\xe1\x9b\xf2\xfd\xb3\xc5\x62\xa6\x10\x1f\x27\xbd\x37\xf2\x23\xca\xb1\x3c\xed\x24\x5a\x1c\xed\xf8\x52\xf5\x51\xf8\x57\xaa\xd9\x72\x7f\x62\xc9\x67\xc0\xa9\x21\xdf\x11\x6f\x48\xa8\x0a\x60\x40\xb3\xc7\x23\xab\x5c\xb5\x94\xc4\x50\x7a\x3d\x20\xcd\x60\x51\x4e\x22\x16\x4a\x82\xb7\x4f\x19\xdc\xfd\xd8\x3c\x57\xbc\x36\x52\x37\x55\x17\x41\x4a\xf5\xd1\x8e\x0a\x64\xcc\xab\x36\x69\x97\x68\xd0\x7c\xf4\x0b\x70\x63\xa8\x3e\x43\xd5\xf6\x07\x96\x4b\x1b\xf0\x84\x0a\x45\xad\x50\xab\xf8\x3d\xbc\x84\x9f\x40\xe5\xb4\xcf\xb6\xa3\x34\x7b\x29\xfe\xc5\x07\x74\x04\x6a\x4b\x50\x04\x10\x32\xaa\x4d\x56\x7e\x85\x64\xb3\xee\xd1\x64\x20\x40\x68\x2d\xd8\xae\x7d\x71\x79\x28\x6c\xf6\xe1\x85\x3d\xc8\x7d\x27\xc3\xe9\xe6\x0f\xa4\x7c\xf8\xcb\x2d\xa0\x18\x1d\x53\xee\xc4\x06\x14\xb0\x73\x31\xa4\xfb\x70\x28\x08\x6d\x0b\x1c\xe2\xe1\x11\x5b\x73\xa1\x62\xc5\x27\xbd\xd7\xca\xb5\x33\x5b\x86\x3d\x10\x8b\xe0\x47\xbd\xbc\xa1\x12\xcc\x6e\x77\x6b\xb4\x53\xc3\x17\x31\x43\x88\xbb\x96\x53\xef\xb4\x44\x4b\xf5\xcf\x1e\xc8\xda\x23\xb7\x11\xba\x71\x79\x6c\x0a\xe0\x2b\xa1\xdc\xc8\x38\x45\x50\x78\xc3\x89\x7f\x07\xe9\xe1\x3b\x76\xe4\x92\x74\xc2\xe2\x07\x50\x6b\x00\xa0\xb5\x58\x88\x3a\xa1\x22\xb6\x67\xdb\x9d\x67\x05\x08\x60\x6a\x3f\x54\x32\x06\x36\xcd\x19\xf9\x73\x91\x7f\xb1\x87\x5f\x43\x63\xe2\x20\xf1\xe1\x23\x98\xcc\x6a\xfd\x79\x09\x47\x43\x33\x84\x56\x81\x3a\x58\x26\xad\x3f\x1a\xba\x7c\xd7\xbe\xab\x1f\xe1\x83\x85\x9c\x0c\xc9\xef\x40\xa5\xea\xb9\x12\xca\xf5\x15\xa8\xd4\xc3\xb9\x3d\x64\x1b\x7a\xb3\xe7\x6b\x16\xc1\x29\x71\xac\xe8\x8f\xf3\x3e\x5a\x1e\xd9\xb4\x4e\x45\xdb\x8f\x30\x85\xdb\xf0\x70\xb2\x56\xb0\xd7\x51\x2e\xe1\x06\x94\x32\x60\x3d\x73\x09\x5d\xb8\x74\x9c\xa5\x47\x96\x3b\xd7\x1a\x8a\x68\x4a\xb8\x51\x6b\x14\x6c\x41\x87\x17\x63\x86\xaf\xdf\x6c\xb1\x36\x8a\x3d\xd8\xfc\xb2\xcf\xff\x77\x05\x6a\xaf\x78\x23\xf8\x00\xb2\x66\xac\xce\x72\xbf\x64\x3c\x6d\x0c\x28\xf0\xab"}, -{{0x19,0x8b,0x5f,0xd1,0xc0,0x38,0x27,0xe0,0x99,0x4a,0xd5,0xbf,0xee,0x9b,0x5b,0x7b,0xe9,0x96,0x6c,0x9c,0x3a,0x26,0x7e,0x4d,0x74,0x30,0x34,0x37,0x67,0x40,0x3c,0x67,},{0x66,0x82,0xc6,0xf1,0xa8,0x66,0xb4,0x9b,0x2f,0x8e,0xe9,0x7f,0x2e,0x53,0x2f,0xa9,0x16,0x66,0xbf,0x38,0xda,0x1b,0x4d,0xd6,0x55,0x43,0xa1,0x77,0x77,0x94,0xcb,0xee,},{0xf4,0x54,0xf3,0x5b,0x18,0x53,0x8f,0x87,0x7e,0x5d,0x61,0x4a,0x76,0xb5,0x27,0x6a,0x27,0xfc,0x0b,0x43,0x3f,0x21,0x5d,0xc4,0xe9,0x63,0xb3,0xf0,0x47,0x69,0x4c,0x78,0x0c,0x51,0x5c,0x6e,0xf6,0xfe,0x2d,0xb4,0xb0,0x09,0x00,0x9b,0xc2,0x73,0x3a,0xec,0x4f,0xd4,0x6e,0x61,0x53,0x57,0xcc,0x0b,0xcc,0x9f,0x1f,0x7f,0xc2,0x1e,0x3c,0x02,},"\x3f\xda\xa1\x5c\x46\xf2\x51\x43\xdb\x97\x20\x79\xd7\x01\x3c\x7f\x69\xa1\x36\xf4\x5f\x3f\x6b\xa2\xce\xd8\xb8\x28\x46\x8e\xb3\xda\xa6\xb5\x0b\x4f\x8d\x33\x80\xfe\xc6\x4a\x03\x43\xbe\x11\x6f\x6f\x83\xb6\xee\x64\xcc\x4c\x1b\x1d\x08\xd5\x4f\xd4\x20\x29\xe4\x28\x5c\xfc\x6c\x6d\xd5\xcd\x18\x1a\xb5\x33\xff\xcd\x41\x1f\x23\xa1\x00\x3d\xa9\x4e\xc9\x34\x0e\x2e\xc7\x11\x99\xd6\x78\x54\x0d\x51\x82\xe1\x39\xff\xcb\xc5\x05\xa1\x70\xb8\xf0\x7f\x4a\x7e\x69\x4c\xa9\x2f\x58\x32\x0c\x0a\x07\x85\x64\xce\x9d\xe9\x9b\x0f\xa8\xe6\x6b\x0d\x82\x2e\x46\x7a\x5a\xeb\x83\x56\x79\x96\xa4\x8b\x89\xdb\x25\xca\xde\x64\x57\x79\x4e\x54\x14\xd6\x7e\x9d\x4a\xb7\xcd\x6c\xc2\x05\x8b\xb7\xa5\x13\xab\xd7\x09\xf4\xca\xf2\x4b\xb6\x7c\xe1\xc0\x3a\xb6\x2d\xbd\xfe\x30\x9e\xc7\xdb\x0f\xa3\xea\x7a\xae\x82\x36\xf2\x59\xb9\x22\xd4\x53\x61\x15\xa6\x3b\xc8\x9a\xcb\x20\x51\xd0\x9e\x73\x1c\xbb\x0d\xf1\x57\xd9\xd3\x45\xbd\x91\x09\x97\x3c\x2b\x59\x4f\x14\x8e\xfc\x6f\x33\x77\xde\x51\x63\xb7\xf6\x98\x69\xff\xef\x85\x3e\xae\xfe\xb4\x02\xe2\x35\x29\x59\x4f\xbd\x65\xca\x05\xfe\x40\x62\xc5\x29\xd8\xe3\x21\xab\xc0\x52\x00\xca\xc1\xe8\x39\xe8\x7b\x1f\xd3\xfd\xf0\x21\xd6\x8c\xbb\x3a\x41\x42\xb6\x9c\xc3\xaf\x6f\x63\x2e\xdd\x65\xb8\x3f\x5a\xa4\xcb\x17\xda\x5b\x6b\xa3\xfc\x03\xed\xb1\x7c\x2a\x3c\xb5\xb0\x48\x36\xe7\x66\x0e\x63\xc8\xa0\x48\x3e\x24\x39\x83\x37\x1d\xfa\x98\x39\xf9\x16\x4a\xd4\xda\x0d\x59\x53\x65\x5e\x3a\x95\x18\xe1\x36\xda\x74\x57\x37\xc7\x92\x43\xc3\x55\xfc\x12\x5c\xbd\xcc\x76\xae\xc9\x22\x16\x84\x6c\x45\x74\xf4\xf7\xf2\x98\xbc\xde\x54\xfd\x24\x44\xad\x30\x25\x95\x5c\x10\x03\x15\xde\x5a\x4e\x27\xc3\x33\xa0\x02\x84\xb2\xf7\x02\xfd\xd3\xde\x22\xac\x6c\x24\x0d\xbc\x14\xbf\x71\xe6\x2d\x13\x1b\x62\xf2\xdb\x99\x24\x73\xf2\xf9\x13\xf6\x0c\x91\x6e\xcf\x57\xdf\x5f\x3f\x02\x1f\xb3\x30\x83\x43\x95\xb7\x94\x72\xca\xff\x19\xfc\xfa\x0a\x27\x17\x95\xc7\x6d\x69\xb4\xdb\x3f\x85\xb8\xd2\xe5\xc3\x44\x19\x65\x48\x4d\xcc\x39\xab\xa5\x9b\x70\x12\x74\xf7\xfc\x42\x52\x46\x85\x60\x69"}, -{{0x43,0x92,0xf7,0xd4,0xfb,0xd6,0x8f,0xe1,0x54,0xe4,0xba,0x38,0xad,0x52,0x07,0x61,0x2a,0x06,0x48,0x55,0x60,0x56,0xc3,0x9a,0xc1,0x16,0xad,0x46,0x8f,0x89,0xbd,0x2d,},{0xcb,0xea,0xef,0x41,0xac,0xac,0x02,0xbf,0x1f,0x78,0x0c,0xe9,0x34,0xaa,0xbd,0x63,0x13,0x64,0xb3,0x69,0x56,0x7b,0xe1,0xbe,0x28,0xe3,0x90,0x6f,0x9d,0xb1,0x20,0xfa,},{0x86,0xe7,0xcc,0xf0,0x6e,0x79,0x36,0x2d,0x40,0xcd,0xb7,0xfb,0x75,0xa9,0x89,0x78,0xbb,0xd3,0x34,0xa1,0xdb,0x75,0x90,0x36,0x7d,0x60,0x84,0x9b,0xd5,0x3e,0x2f,0xb1,0xa4,0xbd,0xae,0x59,0x0d,0x1f,0x47,0xb5,0x49,0x0d,0x87,0x02,0xe7,0xc1,0xa8,0x72,0x68,0xb8,0xee,0x9d,0xb6,0x12,0xde,0x7b,0xdc,0x2e,0x38,0xfa,0x6d,0xeb,0x7e,0x05,},"\xcf\x17\x09\xdc\x9a\x08\x67\xee\x90\x87\x21\xb1\x36\xcb\x93\xa8\x42\x29\xe8\x3b\x46\x20\x47\x77\xca\x81\x94\xd0\x8b\x7a\x3c\xa9\xc9\x12\xeb\x24\x3e\x5b\xda\xbf\xee\xd3\x52\x34\x9d\x20\xbe\x80\x1b\x72\x2a\xf0\x89\x22\x38\xe7\x2e\xdf\x19\x0e\x63\x61\xf5\x75\x72\x78\x1a\xd3\xc2\x59\x0b\x19\x73\x57\x64\x1c\x80\x53\x83\xba\xa1\xd4\x97\x2f\x76\xc6\x54\x48\x53\x2c\x11\x08\x34\xa0\xba\xa8\xf4\x88\x63\xe1\x66\xb7\x06\x65\x37\x08\xcd\x40\x57\xd3\xa4\xf9\xfc\xb2\xce\xb4\x12\x00\x01\x27\x7d\x38\xc4\x38\x47\xd8\x22\x82\x2b\x77\x7c\x2b\xb4\xda\x40\x15\xa1\xc2\x4d\x41\x6d\x50\x62\xa8\x71\x84\x91\xd8\x55\xaa\xa5\xdb\xf5\x57\x9c\x16\x4d\x8e\x52\x4a\x9f\x2f\xa3\xf2\x2e\xb0\x98\x61\xff\xe6\xad\x65\x9f\xe3\x6e\xb4\x04\x31\x22\x2c\x22\xd7\x13\x7a\x6c\xab\xca\x8d\xb7\x86\xe3\x9d\x81\xf6\x61\xaf\xde\x4e\x39\x58\x9b\x4d\xb4\xd3\xc5\x1c\xa5\x35\x90\xa1\x4e\x11\x5d\x0a\xfc\x3a\x87\x7b\x83\x9a\x96\x38\xbe\xce\x80\xc3\x2c\x19\xe5\x1b\x75\x32\x02\x48\x45\xf7\x6c\xfe\x9b\xfb\x2a\xc0\x51\x30\xf6\x75\x8b\xf7\xfe\x99\x3a\xa9\x3a\xa2\x72\xe4\xe6\xbd\x0c\x75\xc1\x40\x99\xd4\x3e\x65\x2a\x22\x3e\x5b\xcd\x64\xc3\x62\xd4\xb8\xf4\xb9\x5e\x01\x6f\x93\x50\xc7\xfa\x74\xe6\x53\x52\x5d\x08\x01\x15\x58\xb2\xc6\xe9\xbf\x4f\xdf\x9d\xbd\x5e\xf9\xb0\x9b\xbc\x84\x6a\xfc\x2b\xcb\xc8\x6c\x4c\xcc\x31\x5f\x6d\x1c\xcd\x48\x9b\x0c\xf8\xed\x0d\x93\xf2\xf5\x32\xa4\x26\x26\x5c\x59\x0b\xa3\xa5\x90\x23\x34\x7d\x81\x9d\x9b\x28\x1e\xf8\x53\x10\xb0\x53\x16\xd4\x6c\x8a\x8c\x03\x65\xd0\x68\xa8\x70\x86\x64\xea\x4d\x77\xac\x0c\xd1\x50\xa6\x5a\x56\x58\x6b\xab\xd3\x4b\x74\x36\x5b\xb8\xfe\x3e\x61\x87\x26\x22\x84\xd6\x44\x32\xe4\xc8\x1e\xa4\xc0\xe5\x7c\x1d\x71\xae\x98\x0c\x7f\x4d\x1d\x87\x10\x32\xe1\x88\xbb\xf9\xd1\x75\x8c\xdc\x1d\xff\x98\x9f\x2d\x12\x88\xfe\xf4\xe2\x05\xe9\x9e\x7c\xbf\x2c\xc3\x24\xb8\xc9\x30\x46\xf4\x76\xc5\x9d\x3d\x0a\x59\xdb\x6f\xe3\x73\x82\xdc\x79\xc5\xec\x16\x05\x6a\xb3\x93\x4a\x52\xf7\xd2\x88\x0d\x04\x71\xa3\x77\xb6\xa8\xae\x84\xd5\x6a\xc2\x2d\x1d\x54\x55\x1c"}, -{{0x0b,0xea,0x98,0xab,0xe7,0xd6,0x3f,0x15,0x83,0x90,0xee,0x66,0x8a,0xa0,0x50,0xe8,0x4a,0x25,0xd2,0x89,0x3e,0x49,0xfc,0x83,0xf0,0x79,0xf9,0xbb,0xa6,0xa5,0x5a,0x75,},{0x22,0x19,0x2e,0xc0,0xd3,0x2e,0xf9,0x83,0x56,0x65,0xa6,0x1b,0xc8,0x8b,0xcf,0x4e,0x16,0x04,0x63,0x79,0x21,0x15,0x2c,0x11,0x6a,0xf5,0x03,0x36,0x5b,0xf6,0xbe,0x42,},{0x7e,0xb3,0x13,0x9b,0x88,0x0f,0xdf,0x66,0x37,0x6a,0x20,0x90,0x81,0x88,0x40,0x04,0x97,0x67,0xc8,0x37,0xf3,0xad,0x00,0x36,0xb1,0x41,0x66,0x70,0x52,0xb3,0x36,0x09,0x81,0x7c,0xa5,0xe2,0x40,0xed,0x8c,0xdf,0x3c,0xcf,0x3a,0xee,0x29,0x27,0x45,0x34,0x59,0x4d,0xb0,0xb4,0xcc,0xc5,0xc6,0xe5,0xbb,0xa3,0x28,0x0b,0x87,0x3f,0x29,0x01,},"\xc1\x78\xe3\x8d\x4e\x83\xed\x2b\xe5\x7c\xe1\xc3\xab\x64\x25\x3a\x81\x71\xe6\x10\x00\x81\x81\xfb\xfc\x6d\x75\x22\x69\xf7\xf1\xc5\xa9\xec\x62\xcb\x27\xf1\x9a\xd9\x9c\xe1\xf5\x11\x6a\x36\x3d\x96\xfd\xc5\xa4\x2f\x35\x8b\x6d\xbe\x7c\xab\xdf\xc9\xf6\x07\x18\xe4\x01\x2c\x1b\xb1\xf8\x42\xc5\x56\x08\x11\xba\x83\x74\xa0\x63\x77\x47\xff\x92\xea\xc2\x1c\xa6\x5d\xde\xaf\x43\xe9\x98\x9b\x7d\xe2\xd4\x32\x52\x0a\xfe\xe3\x64\xec\xfb\xa4\xda\x66\x9a\xd4\x89\x3d\x0b\xf6\x9f\x9f\x81\xe7\xdf\x69\x65\x7b\xe2\x2b\x92\x06\x97\x45\xf2\x16\xc2\x42\xcc\xd4\x6d\x02\xd3\x56\x16\xe1\x6c\x75\x5e\x0e\x37\xf9\x61\xa6\xf3\x63\x77\x52\x53\x4f\x6d\xfa\xb8\x80\x5a\xb7\x59\xa0\x32\xa4\xe7\xe4\xc8\x19\x53\x32\x5a\x2f\x68\x6b\xb6\x9a\x02\x9c\xe4\xe0\x3b\xec\xb3\x60\x56\x37\xc5\xa6\x5b\x52\xe3\x31\xc2\x6c\x92\x6e\xd4\x71\x1a\x50\x4d\x37\x33\xbb\x53\xc9\x7b\x80\xea\xfe\x4e\x75\xdd\xd9\xf4\x15\x36\x28\x88\xc3\xd4\xd3\x7b\xae\x0e\x63\xfa\x11\xbf\x75\x56\x66\x43\x7d\x72\xf5\x8c\x91\xd7\xa2\xf8\xcb\x61\x9b\x76\x20\xa0\x70\xb2\x6b\x18\xb4\xd5\x01\x84\xc5\x81\x87\x12\x11\x0e\x36\xd3\xe2\x83\x0f\x6a\x85\x76\xba\x57\xf9\xcc\xcb\x8f\xff\x40\x28\xbf\x8e\xf9\xcb\x81\x48\x25\xbb\xca\x82\x7d\x64\x95\x47\xbf\x6f\x2b\xef\x93\x17\x04\xca\x7f\x6d\xf1\x5f\x78\x01\x55\xed\x46\xea\xa7\xca\x7d\x72\xe2\x24\x34\xca\x04\x83\xbf\xb2\xf7\x90\x2d\xc7\x87\xf6\x17\xeb\x9b\xd4\x1e\xd4\x52\x0a\xdf\xd4\x30\x94\x8c\x71\x08\x05\xa7\x3c\x1b\xa5\x49\x2e\x96\x48\x4c\x4b\xaa\x7d\xa2\x4c\x74\x35\xc4\x6a\x05\x2b\xf3\x51\x5d\x33\xe4\x2d\xce\xf5\x17\xca\xa4\x5f\x36\xc8\x79\x12\x10\x78\xc6\x88\xdd\x10\xd7\x66\x56\xa1\x19\x76\x2b\x6a\x83\x41\x36\xfa\x1f\x8a\x64\x32\x24\xb9\x22\x4c\x54\x3c\xf0\x47\x0b\x3f\x8e\xe0\x17\xd6\x20\xdb\xdc\xc8\x4d\x98\x51\x54\xe9\xd1\xae\x80\xe5\xf1\x43\x87\xb8\x8a\x0f\x6a\x5c\x35\x90\x5a\xa5\x7f\xb3\xab\xeb\x0e\xa6\xec\xcd\xdb\x00\x44\x74\x63\x3c\xc4\x83\xb5\x6b\x8a\x8e\x20\xe8\xf2\xe0\x9e\x97\x9a\xa0\x98\x93\x08\x78\x75\xc6\xb1\x17\xb5\xf1\x38\x47\xad\x8f\xc0\x56\x04\xc4"}, -{{0xc2,0x58,0x78,0xb0,0xd1,0xe0,0x92,0x5c,0x8f,0x5f,0x04,0xa1,0xe5,0x79,0x90,0x80,0x96,0x3c,0x41,0x3a,0x13,0x99,0xc1,0x18,0xaf,0xb1,0x68,0x7c,0x79,0x7f,0x48,0x39,},{0x13,0xac,0x2c,0xad,0x41,0x90,0x8c,0x25,0x5f,0x67,0x1f,0x93,0x93,0x4a,0xe5,0xd7,0xbe,0x32,0x53,0x46,0x72,0x5c,0x8b,0x40,0xdc,0x39,0xea,0x80,0xd7,0x0d,0xdf,0x34,},{0x06,0xf5,0x51,0x98,0xb4,0x19,0x19,0x14,0xb7,0x43,0x06,0xf3,0x8e,0x38,0x13,0x16,0xea,0xc4,0x0b,0x5b,0x5a,0xdb,0x8a,0x31,0x24,0x64,0xf6,0x71,0x75,0xec,0xf6,0x12,0xe0,0x14,0x7b,0x1c,0xef,0x46,0xc2,0x51,0x87,0x50,0xa5,0x60,0x6b,0xb0,0x3b,0xc6,0x46,0x7b,0xb9,0x32,0x15,0x14,0xf6,0x9d,0xcb,0xeb,0xce,0x8f,0x69,0x05,0x80,0x02,},"\x68\x56\xcc\x71\x44\xb6\xbd\xdc\xc4\xb5\x89\x54\xd1\xa2\xe7\x10\x1d\x65\x84\xb5\xd5\xe7\x19\xa0\xae\xa0\xfb\xbd\xf2\x21\xc2\xa2\xaa\xcb\xac\xdc\x40\x20\xc5\xc8\xce\x68\x1f\xf7\x38\x1a\xcd\x60\x7b\x0f\x52\x39\x69\x23\x35\x70\x06\x55\xbe\x2d\x94\xc5\x3d\x7b\x51\x48\xe9\x2a\x2b\xc1\x63\x38\xc2\xf4\xc1\xa7\xd1\xc5\x95\xaf\x62\x2c\x24\x0c\xe5\x79\xa5\xe0\xf5\xb6\x51\xbf\x56\x25\x18\xce\xc8\xaa\x2c\xe4\xb4\xaa\xdb\x1f\x2f\xda\x6c\xf6\x29\x5b\xc3\x78\x03\xb5\x37\x7d\xab\x65\xc9\xb9\xa2\x94\x9f\xdd\x49\xbf\x9d\xdc\x8f\x96\xd2\x60\xff\x95\x1b\xf8\xe8\xcc\xf9\x82\x7e\x68\x69\xc4\x4b\xfd\x97\x33\x58\xce\xfd\xb0\x10\xdb\x5e\x1f\xe5\xdb\xd9\xf5\xd2\xb2\xca\x39\x3c\x17\xd4\x46\xf6\x37\x05\x9e\x69\x2d\x7a\x91\xaa\xdc\xc7\x68\x9f\x5f\x9e\x1b\x30\x52\x17\x5d\x9b\x6b\x20\x8f\x90\x26\x78\x7f\xdb\x66\x78\x3f\x45\x37\x2a\x24\x94\x6b\x1b\xd1\x68\x7b\xf0\xcf\xcc\x81\x74\xeb\xe4\xd3\x2e\x43\x28\x4f\xc7\x8d\x78\x44\xde\x0f\xa2\x2e\x20\x65\xe0\x75\x28\xba\xab\xaf\x01\x5c\xb3\x4d\x62\x9c\x35\x96\xad\x04\x0d\xe3\x1c\x56\x20\xeb\x26\x6d\xef\xa7\x53\x3a\xc0\x40\x19\x98\xe5\x67\x3a\x75\x43\x65\x04\x7d\xeb\xfc\xf7\xe1\x37\xa2\x0d\x16\xcd\xd6\xa5\x52\x19\x82\xf4\x44\xcf\xc3\x42\x93\x97\xc6\x41\xbd\x7e\x74\xa7\x70\xbb\x11\xfc\xb2\x94\x83\xe3\x37\xba\xe5\x16\x9e\xe8\x2d\xa9\xa9\x1a\xdf\x3a\xf6\x7c\xd8\x14\xc2\x82\x5d\x29\x01\x8e\xf0\x35\xea\x86\xf8\xde\x4c\x75\x63\xaa\xf6\x6e\x0c\x75\xd1\x7c\xa6\x8f\x49\xf0\x75\x8e\xc2\xd9\xc5\x17\x9d\x01\xaa\xed\x7d\x45\x15\xe9\x1a\x22\x2b\x0b\x06\xfb\xde\x4f\x07\xa7\xd9\xdf\x2d\xe3\xbc\xae\x37\xca\x2c\x84\x60\xc2\xa6\xb3\x74\x9e\x9b\xda\x36\xd0\x8e\x66\xbc\xc3\x56\xb3\x90\x43\x4b\x4a\x18\xcf\xa4\x5a\xf5\x57\xdc\xa3\xd8\x57\xff\x3a\xd3\x47\xcf\xb0\x7e\x23\x58\xc2\xac\xfd\x5c\xd5\x3b\x3b\x0e\xa2\xa4\x1e\xe5\xc0\x80\x2f\xd4\x73\xdb\x5f\x30\x52\x63\x34\xda\x41\xeb\x4b\xc7\x51\x83\x83\x89\x8a\x0b\x75\x07\xad\x4c\xa2\x89\xd6\x6c\x5e\x2e\xb7\x5c\xf2\x55\xdf\xf3\x12\xcb\x1e\x04\xee\xbe\xb4\x7f\x29\x30\xb9\x0d\x5e\x00\x2e\xb0"}, -{{0x0b,0x2e,0xc6,0x27,0x63,0xf6,0x87,0x59,0x31,0x35,0xda,0x19,0x61,0xef,0x29,0xa2,0x88,0x08,0x96,0x96,0xd9,0x44,0xb2,0x65,0xa5,0xf9,0x68,0x93,0xcd,0x2d,0x82,0x25,},{0xc1,0xe2,0x34,0xfa,0x8b,0xc9,0x6d,0x26,0x8e,0x7a,0xad,0x02,0x8b,0x03,0xf0,0xa9,0x11,0xb6,0x97,0x71,0x5d,0xb3,0xa2,0x1c,0x2f,0xc7,0xdf,0x48,0xec,0xda,0x88,0x75,},{0xff,0x70,0x1f,0x34,0xb3,0x59,0x4d,0xe3,0xb8,0x00,0x45,0xf4,0x29,0xe5,0xe3,0x2d,0xd8,0x8d,0x60,0x51,0xd4,0x19,0x5f,0x16,0x85,0xbe,0x78,0x37,0x66,0xe8,0x01,0x19,0x36,0x8f,0x56,0xb3,0x74,0x97,0x25,0xb9,0x13,0xf1,0x22,0x3f,0x87,0xfb,0x0f,0xb2,0x4d,0x9d,0xfa,0x08,0x41,0xd6,0xa0,0xe2,0xeb,0x1f,0xdd,0xf7,0x75,0xc2,0xd2,0x05,},"\xa8\x34\x34\xc6\x86\x93\xd5\xfc\xed\x91\xbd\xa1\x02\x13\xfc\xd5\x0c\x48\x92\x0b\x90\xce\xe9\xb7\x3a\x9c\x61\x08\x1a\x09\x74\x93\x3f\x4f\xdb\x0a\x67\xe6\x71\xf8\x35\x1b\x0e\xd5\xec\x0f\xe7\xb5\xfb\x0c\x87\x58\x6f\xe5\x82\xff\xb1\xbf\xa2\xdb\x5f\xce\xdd\x33\x02\x42\x82\x34\xb2\xbb\x0e\x72\x6d\xed\xf4\x5b\x13\xa7\x0c\xd3\x5a\xb3\xe2\x99\xd1\x3f\x34\x50\x35\x08\x27\x8c\x44\x58\xee\xa5\xb7\x35\x1b\x05\x83\x6b\xda\xd5\xb0\x5f\x60\xe4\x45\xfc\x65\x73\x7a\xe2\x7d\x2e\x52\xdf\x9c\x39\xe5\xda\x02\x86\x39\x2d\x08\xff\xf7\xec\xb7\x06\x68\x20\xfc\x90\xfc\x8a\x44\xd5\x61\x65\x61\xc5\x0b\x52\x71\x47\x02\x30\x2b\xca\x58\x74\xde\x85\xdb\xa0\x45\x04\x5f\x9f\x0e\x60\x4e\xb8\x6d\x6d\x7f\xbd\x77\x5f\x72\xea\x49\x3b\x2c\x4e\xf7\xc3\xbe\x16\xdb\x2c\xa7\xe4\xd8\xbd\x79\xeb\x20\xcf\xb5\xf0\xf6\xf0\x53\x36\xb7\x5c\xc8\x6d\x21\x9f\x3b\x8f\x2e\x91\xba\x7d\x52\xb6\x4f\xdd\x6a\x66\x64\xf0\x4f\x2f\xba\xb7\x58\xcd\xf9\x84\x16\x86\x91\xc3\x2f\x53\xe8\x61\x6b\x49\xf7\x6a\xb7\xb1\x92\xb9\x00\x90\x30\x82\xcc\x89\x65\x6a\x97\x05\x80\x4c\xc9\xb9\x28\x8a\x3e\x42\x17\x09\x84\xf8\xdc\x45\x4e\x08\x64\xb9\x34\x16\x72\x68\x6a\x17\x8c\x06\x00\x50\x17\x8a\x36\xc6\xd9\x06\xb2\xce\x07\x0d\x8f\xaa\xac\xd9\xa5\x8c\x79\x4a\x5e\xa4\x10\x8b\x4a\x48\x5c\x65\x81\x1c\x2d\xca\x2e\xe7\xbb\x10\xbf\xff\xf7\x5d\x45\x86\xb9\x90\xf4\x37\x63\xa1\x6f\xbc\x0b\x48\xae\x1f\xaf\xb0\x8a\x9a\x36\xfa\x43\x26\x84\x5d\xba\x5b\xa2\xfb\xd3\x2b\xbf\x66\x50\x5c\x5e\x86\x57\xed\x01\x07\xe3\xe1\x61\x44\xef\x31\xfa\x6a\xae\x72\xe7\x74\x09\x74\x83\xf5\x48\x0a\xa4\x55\x40\x56\x8f\xd0\x8c\xba\x0d\x57\x77\x68\x00\x4f\x58\xae\x9b\x95\xbe\x37\x4e\xd7\xf0\x29\x9f\xe7\x21\x27\x5e\x47\x6e\x0b\x9a\xb7\x2d\xc0\x6e\xa3\x28\x38\x4e\x39\xbf\x3a\xc3\x31\xc6\x25\x48\x43\x12\xcd\x9b\x06\xb1\x5a\x29\x54\xd3\x3e\x7a\xab\xa6\xbe\x22\x61\x88\x6c\xa8\x11\xdb\x96\xb1\x14\x3d\x06\xdd\x6e\x0f\x3c\xba\x7a\x1a\xe9\xb9\x4e\xaf\x67\x77\x1b\xb2\xd2\x4e\x2f\x94\xde\x9c\x47\x0f\xcd\xe7\xbf\xdb\x32\xf4\x10\x19\x8b\x5a\xa9\x69\x8e\x32"}, -{{0x89,0x60,0xd7,0xbe,0xe8,0xc6,0xb3,0x9c,0xa5,0x93,0x4d,0x7c,0xdd,0xd1,0x6f,0x16,0xb3,0x66,0x3e,0x6e,0x03,0xe8,0x33,0xc0,0x57,0xe2,0x18,0x1e,0x45,0x97,0xcb,0x68,},{0x43,0x40,0x90,0x95,0xd4,0xf5,0x0f,0x5e,0xdd,0xbd,0x5c,0xd4,0xd2,0x01,0x22,0x98,0xcb,0x41,0xa4,0x0e,0x99,0x49,0x2d,0x5a,0x2d,0xb0,0x8b,0xe5,0x37,0x7e,0xa1,0x83,},{0x72,0x13,0xdd,0x4a,0x79,0xfd,0x54,0xde,0xc0,0xc5,0x48,0xef,0x42,0xe6,0xca,0xe0,0x15,0xbe,0x77,0x80,0x2b,0xf5,0x15,0xcd,0x25,0x82,0x76,0x8f,0x72,0xf5,0x63,0xeb,0xb2,0xda,0x36,0xaf,0x4a,0xae,0xac,0x56,0xbb,0xff,0xc9,0x93,0x2c,0x2e,0x24,0xec,0x95,0xda,0xff,0x00,0xa5,0xf7,0xa0,0xac,0xab,0x9c,0x8b,0xd3,0xc2,0x3b,0xb4,0x0c,},"\x30\x8d\x84\xc7\xa5\xf7\x86\xe5\x63\xe5\xc1\xea\x57\xaa\xb5\xe5\x55\xc0\x09\x97\x74\x9d\x15\xae\xe3\x54\x39\xef\xa6\x45\xda\x2c\x39\x67\x70\x31\x15\xc6\xc6\x3e\xd7\xf9\x47\x85\xc5\x47\x8f\x38\x46\x7b\x86\xe7\x62\x6e\x8f\xff\xa4\xd5\x1a\x2d\xc4\x5e\x6d\xf2\xa3\x5c\xec\x99\x55\x5e\xab\xc9\xf7\xa9\x3e\x2e\x2b\x68\x94\x59\xb4\xe0\xc9\x2b\x35\x15\x62\xc4\x17\xb1\x99\x71\x13\x75\x4e\xa5\x9e\x4a\x91\x51\x07\x28\xff\x30\x71\xa2\xbb\xd1\xf4\x65\xa6\x87\xf6\x7d\xae\x95\x56\x15\x03\x1a\x8a\xd5\x51\xfe\x73\x8a\x26\x0b\xbc\x44\x6b\x48\xdc\xa1\xd9\x79\x05\x1a\xb5\x84\x08\x32\xe1\x9d\x47\x3b\x66\x62\x17\xa9\x18\x39\x80\xd6\xb2\x7e\x3d\x3c\x76\xd9\x36\x65\xba\x23\x93\xe6\xab\x1a\x42\xc3\x90\x4d\x40\x25\x93\x2d\x60\x1a\x20\x2a\x59\xa4\xc4\x9f\xdb\x77\xf0\xe0\x28\x68\x24\x7d\xe5\xaf\xdf\xaa\x1b\x89\x42\x08\xac\x00\xd7\x7c\x6b\xb5\x4c\x6b\x2a\x73\xa4\x76\x57\xe4\x4c\x85\x13\x79\x63\xb5\x75\x21\xaf\x20\x97\x62\x48\xeb\x26\x14\x82\x14\x7c\xdf\x7a\x14\x5c\x36\x43\xe2\x9e\x05\x88\xbf\xda\xe6\xa0\x82\x90\x48\x53\xce\x5a\x10\xd2\x49\x70\xeb\xdf\xb7\xf5\x9d\x5e\xfd\xd6\xa5\xe7\xe0\xd2\x87\x97\x1c\x84\x6a\xcd\x54\xd8\x4d\xd4\x54\x68\xa4\x11\x0b\xab\x6e\xf8\xd9\xa5\xb4\xb2\x42\x67\x88\x90\x0b\x7e\x1a\xdf\xe0\x62\x43\x44\xf9\x8f\xe5\x9e\xf8\xa1\xe6\xc4\x05\xb3\x44\xeb\x97\xbb\x20\x47\x73\x74\x4b\x6a\x2d\x8c\x6e\x65\xd1\x7c\xea\x07\xde\x03\xb7\xf0\xfe\x49\xf1\xa5\x5c\x33\xd5\xf1\x5c\xe5\x5d\xf7\xc9\x56\x1b\x25\x1c\x6a\xc8\x07\xa9\x25\x53\xe1\xce\x91\x70\x12\xdc\xcf\xd6\x9e\x7d\xbd\x03\x8c\x7e\xee\xca\xe9\x86\x23\xf1\x8f\xbb\x65\x0e\x22\x18\xa0\xbc\x0f\xff\x43\xa7\x5a\x11\x64\x48\xbb\x73\x62\xf5\x27\xee\x6b\xc8\xe1\x07\x61\xcc\xcf\x9b\xcf\xc0\xd0\x00\xf2\x12\x7b\x4c\xc1\x92\x11\xd0\x95\xa0\xbd\xaa\x4e\x4b\xe4\x51\x9e\x6c\x84\x45\xea\xb9\xb3\x14\x4a\x45\xca\xb9\x99\x61\x35\xbf\x7f\x75\xa7\x8d\x22\x27\x59\x00\xf4\xce\x1f\x0a\x9e\xac\x13\x63\x64\x10\x30\x62\x89\x3d\xad\x43\x90\x42\x2b\x77\xe5\xf5\xd1\xd9\x4d\x70\x29\xc6\x09\x7b\x35\xca\x64\xa7\xa4\x76\xfc\xc7"}, -{{0xef,0x6b,0x9b,0x51,0xfd,0x4f,0x85,0x86,0xca,0x62,0x65,0x8e,0x04,0x2f,0xc0,0x9a,0x83,0xb9,0x43,0x03,0x35,0x26,0xff,0xc3,0x26,0xc6,0x5e,0xb3,0xa5,0xfb,0x59,0x4b,},{0x1d,0x6e,0xec,0xe8,0x05,0xe0,0x88,0x78,0x21,0x87,0x6b,0x7e,0xd6,0xed,0x5b,0x07,0x14,0xd6,0x46,0xfb,0xec,0xda,0x38,0x76,0x4f,0x94,0xc8,0x15,0x5e,0x61,0xd0,0x04,},{0x71,0xd1,0x71,0x07,0x1c,0xd0,0xfe,0xa1,0xc6,0xa9,0xcf,0xad,0x1f,0x7f,0xd8,0x35,0xe8,0x5f,0xf9,0x06,0x77,0x8b,0xc6,0x34,0x5a,0x4d,0xec,0x43,0x13,0xec,0xc2,0xbf,0xf7,0x55,0xa7,0x17,0xeb,0xd9,0x12,0xa5,0xe0,0x28,0x40,0xac,0x07,0x38,0x42,0xf9,0xbf,0xca,0xa5,0x89,0x13,0xe2,0x60,0xe3,0xc7,0x33,0x93,0xd3,0x66,0x85,0xc7,0x0e,},"\xa8\xf3\xf1\x96\x65\xde\x23\x90\xd5\xcc\x52\xb0\x64\xb4\x85\x12\x73\x67\x74\x86\xd8\xf5\x56\x3b\xb7\xc9\x5f\xa9\x4d\xb3\x35\x61\x61\xee\x62\x22\x21\xf1\x0c\xbb\x1f\xa1\x95\xaa\xc7\x23\x1e\xa7\x16\xd7\x4b\x46\xb3\x7b\xc8\x5a\x70\xdb\xa3\xdf\xaa\x16\x75\x21\x7b\x35\x11\x99\xe7\x4a\x97\x10\x28\xf7\x29\xb7\xae\x2b\x74\xae\x8c\x6b\x3a\x06\x79\xc3\xe3\x29\x68\x02\x84\x4a\xd5\xbb\xa3\x43\xf6\xf9\xf7\xc4\x66\x1b\x4a\x29\xb4\x4f\x17\xe8\x9e\x11\x4f\xb2\x20\xe9\x84\xcd\x98\x0e\x94\xc3\xd2\xbf\x98\x73\xe0\x60\x5c\x92\x30\x17\x44\xa3\x03\x5e\xf0\x46\xba\xd2\x66\x6b\x5c\x63\xeb\xec\xf9\x3c\xc1\x40\x29\x19\x46\xc0\xfa\x17\x03\x40\xce\x39\x50\x92\xde\xed\x79\x84\x13\x52\xfb\xfe\xe0\x3a\x92\x7e\xb4\x58\xf2\xa6\x33\xed\x32\x71\x65\x2f\x5b\x0f\x99\x60\xcd\xf9\x01\x5d\x56\xfd\xab\xd8\x9e\xe7\x1e\x25\x9a\xf6\xeb\x51\x4b\x4c\x1b\xd4\xa6\x66\xf5\xb5\xa3\x5c\x90\xf3\x5b\x14\x94\x57\xaf\x29\x44\xdd\x0a\xa8\xd9\xb5\x42\x28\x3a\x7e\x54\x12\xb7\x75\xe4\x21\xd2\x12\x6f\x89\xbe\xbc\x3c\xa3\x7f\x73\x07\x16\x21\xf1\x32\x1e\xee\x52\xe9\x69\x04\x86\xa3\x3c\xd7\xff\x9c\x99\x67\xfb\x65\xee\x4e\x90\x7b\x6b\x85\x22\x11\x47\x3d\x21\xe9\xd9\x1a\x93\x36\x2a\xc7\x61\x76\x0e\x8c\x7b\xbe\xa4\x86\xc3\xd6\x05\xf9\xe1\x1b\x86\x13\x68\x19\xa7\xab\x3f\x32\xf1\x3f\xfc\xa1\x68\x17\xfe\xd1\x97\xff\x88\x0b\x4d\x6d\x9a\x80\x8f\x7f\x87\x87\x63\xa0\x45\x72\x8d\xf7\x2f\xaa\xa9\x63\xe4\xcb\x1c\x09\xcc\x2b\x2d\xa9\x20\x28\x0c\x83\x66\xb7\xd1\x8b\xf8\x97\x2d\xf1\x6c\xc2\x34\x48\xfb\xe6\xb2\xe6\xe1\x6c\xbb\xf0\x74\x51\x29\x85\x40\x53\x18\x96\x37\xce\x11\x5d\x23\x98\x43\x3c\x15\xd6\xf1\x16\xa2\x05\x33\x48\x24\xaf\x28\x2f\xa7\x58\x49\x4c\x47\x86\x8e\xa8\xf4\xdf\xad\xc7\x05\xe8\x61\xaa\xd2\xeb\x8e\xf3\xdb\xbe\xd2\xa4\x56\x9e\x15\x83\x4a\x76\x0c\xce\x0c\xbb\xc8\x4b\x28\x9e\x77\x9b\x98\x83\x46\xb9\x06\x9c\x74\x4c\x97\xab\x2b\xf4\x2b\x08\x6d\x2f\xb0\xa4\x11\xf5\xce\x99\xf0\x81\x9a\x30\x86\xb4\xfe\x9d\x96\xc7\xc9\x90\x8d\xce\x28\xdf\x1d\xdd\x30\xf3\x50\x1d\xda\xf7\x81\x10\x73\x4f\x9d\xcd\xfe\xc3"}, -{{0xba,0xd4,0x7c,0xd4,0xbd,0x89,0x84,0x90,0x67,0xcc,0xe1,0xe6,0x3c,0x3d,0x91,0xe9,0xb7,0x87,0xae,0xa8,0x58,0x4e,0xdb,0x07,0xf3,0x45,0x1e,0xf6,0x7e,0x7b,0xd7,0x9b,},{0xab,0x0c,0xe9,0xba,0x1d,0x29,0xbd,0xfb,0x85,0xa0,0xe6,0x6b,0x76,0xb5,0xe2,0xe0,0x5f,0xf7,0x32,0x56,0x9e,0x43,0x75,0xcc,0xd7,0x50,0x98,0xe9,0xe7,0x1d,0x17,0xbf,},{0xe5,0x72,0x4a,0x1d,0xd4,0x63,0xa9,0x7d,0x12,0x22,0xc5,0x18,0xc4,0x92,0x5d,0x32,0x22,0x02,0xd1,0x0f,0x04,0xcd,0x07,0x8e,0x77,0x1e,0x0f,0xb3,0x95,0x1d,0xbc,0x14,0x93,0xa2,0x34,0x46,0x07,0x54,0xc3,0xaa,0xe3,0xdf,0x93,0x00,0x8d,0xbb,0xfb,0x31,0x0c,0x99,0x59,0x2b,0xed,0xe7,0x35,0xa4,0xae,0xab,0x03,0x23,0xa1,0x21,0x0d,0x0e,},"\xb5\xa6\x1e\x19\xe4\x86\x3e\x0b\xb5\xf3\xfa\xb6\xc4\x97\x0d\x87\x85\x96\x89\x55\x21\xfa\x1e\x7f\x67\x8c\xaf\xa2\xde\x53\x32\x2f\xd4\x58\xa9\x8a\xa6\xe3\x58\x05\x42\x9f\x65\x12\x91\xb9\x5b\xd9\x95\x0e\x15\x5f\x3a\xda\x0b\x60\x91\x59\xa4\xab\xda\x59\x90\xc0\x4b\xc2\xe7\x64\x42\x2f\xb4\x9e\xf4\x2f\x12\x52\x9f\xf6\xf6\xa8\x20\x29\xff\x01\x85\x66\x2e\x65\x8f\x83\xc5\x46\xee\xd0\x9f\x06\xb5\xa6\x8e\x85\x7c\xda\xd0\xeb\x9e\xc4\xee\xcb\xfd\x88\xf3\x4b\xc8\x09\x90\xf8\x64\x4a\x9b\xfd\xde\x1d\x9f\x3a\x90\xd5\x57\xa8\xb8\x28\xd5\xce\x06\xa6\x4e\x3b\x23\x85\x82\xbb\x4c\xbe\xba\x30\xed\xc4\x9e\x81\x22\xc5\x5e\x95\xba\xdc\xf5\x02\xcc\x56\x78\x69\xc0\x9e\x9f\x46\xc6\xff\x3f\x68\x78\x98\x6b\x1d\xe0\x0b\x72\xa1\x85\x80\x46\xfc\xd3\xa6\xe9\xcd\xaf\x5b\x07\x3c\x56\xf2\x02\x50\x63\xa2\xd1\x78\xbd\x4c\x1e\x8c\xbc\x1e\x6e\x67\x1a\xa9\x7f\xb2\xcb\x4c\xc8\xa6\x2c\x20\xbe\x41\xc7\x76\x37\x2c\x8e\x7b\xe6\x3b\x48\x2e\x6c\x63\xfa\x85\xd7\xcf\xfb\xc1\xb2\x82\x0b\xae\x1f\xc1\x28\x34\x3a\x1e\x20\xfc\xf1\xbc\x35\x02\xee\xe8\x13\x58\xcc\x9a\x74\xc7\x2a\xf6\x35\x30\xf9\x6a\x25\xa6\x04\x64\x8f\xf5\x70\xdf\x1e\xb8\x9d\x1f\xdd\xba\xb2\x86\x79\xba\x2e\x9b\x41\x97\x7e\x9a\x9c\x1c\xae\xcd\xbf\xc3\x61\xa1\xdd\x05\x5e\xc5\x16\x20\xa9\xbb\xdb\xba\xf7\x18\xc9\xcc\x13\x6d\x20\x07\x71\x03\x99\x53\x6d\x13\x33\x24\x85\xec\x38\x87\x97\x85\xe0\xc9\xce\x99\x15\xa8\x02\x51\x37\x39\x90\xa5\x9b\xce\x44\x03\x26\x03\x1a\xb1\xb4\x58\xbf\xa5\xb8\xa4\x79\x3d\xa4\xee\x11\xab\x7a\xf2\x0d\xe2\xa1\x18\xc9\xae\x52\x1a\x41\x7b\x68\x20\x7f\xc8\x85\xe1\x09\xd8\x46\x3e\x9f\x02\x27\x87\xcc\x73\x0d\xb0\xb1\xfa\xae\xd2\x57\xbe\xd9\x01\x71\x08\x85\xb7\x4e\x99\x4f\x54\xf6\xf2\xae\xb6\x4f\x0f\x60\xb5\x9e\xfb\xf2\xe3\xbb\x65\x15\x42\x46\x03\xa1\x13\xc0\xb8\xa3\x1b\xa3\xc1\xe9\xa9\xb8\x11\x8c\x87\xec\x69\x49\xb7\x5f\x49\x62\x7e\xa7\xb1\x32\x88\x89\x39\x11\x04\xd4\xf4\xa3\x89\x2c\xf0\x0f\x26\xa7\x3c\xda\x2a\x40\xf9\xb7\x15\x7a\xfc\x40\x66\x7f\x4a\x04\xf6\x47\xdb\xf9\x39\x06\xb8\x4c\x9a\x35\x16\x4e\x1b\xc9\x02"}, -{{0xca,0xba,0x8e,0x05,0x33,0x11,0x3a,0x4b,0xe1,0x73,0x40,0x8b,0xa8,0x3c,0x0d,0xb7,0x42,0x60,0x80,0x2f,0x91,0x86,0xc3,0x91,0x40,0x26,0x55,0xac,0xde,0x60,0x15,0xcb,},{0x2d,0x7b,0xef,0x61,0x64,0xc2,0x79,0xfa,0x10,0x28,0xa9,0x78,0x8e,0x3e,0x8e,0xe8,0xac,0x15,0xed,0xcf,0x92,0xa5,0x85,0x50,0x62,0x95,0x23,0x10,0xb4,0x68,0x45,0x47,},{0xec,0x35,0xec,0x32,0xc8,0xa4,0x00,0x88,0x27,0xe1,0x78,0x49,0x2b,0x3b,0x8b,0xee,0x22,0xa4,0x95,0x4f,0xc6,0xb2,0x5f,0x4f,0x22,0x5d,0xd7,0xed,0x23,0x69,0x89,0x00,0xde,0x81,0x56,0x75,0x6a,0x8e,0xdc,0x35,0xc5,0x1d,0x10,0xf8,0x2b,0x83,0x0a,0x2a,0x65,0x96,0x76,0xea,0xc9,0x11,0xf9,0x60,0x24,0x47,0x66,0xe0,0xc3,0xc6,0x07,0x05,},"\x24\x13\xa3\x2b\xca\x5c\xe6\xe2\x30\xe5\x65\xeb\x85\x84\x93\xd5\xd0\x4e\x6d\x2e\x2a\x7a\xb1\xf8\x9a\x3b\x42\x33\x11\x67\x6b\xfa\x93\xc6\x7d\xaa\xfd\x1c\xfc\x71\x09\xe0\x40\xba\xc5\x2c\xbf\xe0\x7c\x28\x28\x0b\xb6\xac\xf6\xe3\xa3\x10\x73\xda\xb2\x96\x53\x78\xdd\x77\xf6\x1f\xe9\x24\x71\x35\xc1\xa6\x31\xb7\x9a\xd6\x68\xc9\xea\x1c\xd4\x11\x2d\x8d\x3a\x06\x4c\xc2\x1d\xf3\x2a\xea\xc7\xdd\x71\x8b\x09\x1f\xb6\x91\x5b\x8b\xc0\x63\xbb\x58\x15\xc3\x76\xe0\x14\x76\x31\x2a\x2e\x54\x33\x41\x7a\x7a\x93\x15\xd6\x59\x99\xb0\x2f\xf4\x64\xa4\x74\xa5\x97\xe5\x39\x88\x77\x36\x70\xec\xa4\x6a\x6e\x26\xcf\x96\xe9\x48\x8e\x9e\x63\x44\xbc\x78\x3d\xdf\xb5\x35\xe7\x6b\xb3\xb9\xa6\x03\xff\x4c\x59\xc7\xdb\xe2\xd8\xb6\x19\x8d\x5b\x24\x49\x0b\x4e\xa9\x6c\x95\x95\x9f\xfb\xf3\xd8\x21\x8e\x76\x0d\xaf\x20\xe0\x1e\x2f\x36\xc8\x4b\xb0\x97\x11\x5a\xbd\xde\xe9\x2b\xed\x82\xd1\x6b\x15\xa9\xe1\x92\xe9\x89\x3a\xc6\x38\x46\x1d\xf5\x07\x20\x7b\x0c\xf5\x95\x88\x4d\x8a\x99\xfb\x9c\x70\x45\xf9\xbf\xf7\xb7\x3f\x00\xca\x3f\xd5\x95\xa5\xce\xc2\x92\xad\xb4\x58\xbd\x94\x63\xbe\x12\x04\xd0\x16\x78\xd2\xf4\x38\x9b\x87\x20\x11\x5f\xa5\x97\xc4\x02\xb4\xff\x69\x4b\x71\xce\x4f\x3d\x33\x0d\x5e\x2f\x3c\x3a\xd6\xd9\x6a\x9b\x34\x39\x23\x0f\xc5\x3a\x44\x79\x4c\xda\x59\x55\x57\xc4\x06\xca\x15\x89\xbc\x7b\xe8\x1e\x2d\x79\x63\x60\x33\x25\x3f\xa7\xbd\xd6\x00\xc6\x7f\xc5\x59\x36\xbd\x96\xce\x04\x28\xc3\xeb\x97\xba\xd1\xde\x0a\x5f\xbb\x9b\x67\x51\x57\xde\x5f\x18\xbc\x62\xa7\xc2\x2c\x94\x83\xe2\x80\x2e\x67\x9b\x5b\x8f\x89\xdb\x0f\xc3\x7f\x7c\x71\x50\xad\x5a\xc8\x72\x2c\xeb\x99\x9b\x24\x35\xe6\x99\x72\x17\x09\x23\x36\xef\x1c\x8a\x22\x92\xda\xb9\xa4\x6f\xf8\xa9\xe1\x0d\x33\x55\x76\x5c\xac\x9d\x65\x98\x77\x0f\x4f\x01\xea\x63\x91\x25\xfd\x03\x16\x09\xdd\x1a\x50\x7d\x96\x28\x0c\x7d\x01\xa3\xee\x98\x7e\x9b\x21\x0e\xc8\x74\x4c\xd4\x8c\x74\xf8\xaf\xee\x96\x1e\x8e\xf2\x21\xf8\x26\xa1\xfe\x6e\x7d\xf0\xcb\x15\xad\x7c\x7e\xf4\xa9\x1f\x9d\x0f\x4c\x2e\x1b\xde\xa6\x35\xd2\x75\xfa\xc8\xc4\xbc\x06\x01\xf4\x90\xdb\xdb\xc7\x34"}, -{{0x9b,0xf3,0xfb,0xc7,0x30,0x8b,0x46,0xf6,0x03,0x6b,0xad,0xe0,0xc3,0xca,0x19,0x9f,0xac,0x66,0x2b,0x07,0xf1,0x03,0xbf,0x75,0x18,0x1d,0x52,0xba,0x6a,0x58,0xbe,0x05,},{0x2f,0x6a,0xc6,0xfc,0x33,0xbc,0x06,0x0c,0x1d,0xc3,0xcb,0x9d,0x1a,0x2b,0x91,0x15,0x84,0x5a,0xdd,0xb1,0x6c,0x4b,0x84,0xbe,0x37,0xed,0x33,0xad,0xb3,0xb3,0xd3,0xa8,},{0x0c,0x31,0x36,0xe0,0x1f,0x9b,0xcd,0x99,0xe1,0x0d,0x3d,0x12,0x4b,0x0c,0xdb,0x07,0x72,0xbe,0xc1,0x8a,0x86,0x4b,0xe8,0x1b,0xd1,0xda,0xa4,0x4d,0x81,0x8c,0x3d,0x47,0x0d,0xfa,0xa8,0xab,0x6e,0x9a,0x76,0x1c,0xf0,0x3f,0x93,0xef,0x9c,0xc7,0x82,0x91,0x09,0x6e,0xd6,0xd1,0x0c,0x08,0xfa,0x2f,0xba,0x3b,0xac,0x04,0xdd,0xe2,0x0f,0x0c,},"\xd6\x5e\x36\xa6\xa3\x81\x95\xec\xb9\x1d\xe3\xc8\x48\xb5\x1f\x63\x92\x45\xfa\x2b\xab\xa8\xa6\xf8\x59\x47\x15\x9d\xec\x0e\xd3\xfa\xe8\x0c\x5a\x0f\x8c\x66\xff\x24\x79\x3c\x89\xc0\xc6\x87\x54\x3b\xc6\x33\x54\x7a\x1f\x37\xf7\x30\xd9\x70\x12\xeb\xbd\xc7\xac\x33\x9c\x48\x90\xc0\x85\x6b\xbf\xe2\xba\x29\xb2\x5a\x7a\xa6\xb0\x89\xc0\x33\xfe\xcb\x76\xdb\x62\xdd\x3c\x00\xf6\x42\x1b\x9e\x76\xdd\x0e\xa3\x66\xeb\x2d\x4a\x05\x2e\xe6\xcc\x73\x6e\x38\x19\x19\x1d\x5a\xd7\xa6\x6d\x2b\xe0\x42\xcc\x65\x39\xe5\xf3\x56\x52\xb1\x55\xa7\x27\xf3\x88\x8d\x93\xf9\x3a\x91\x02\x59\x8f\x75\x38\xa9\xab\x7c\x77\x7e\xec\x79\x42\x6a\x60\x75\xd6\xf3\x8d\x64\xc4\x85\x52\x0f\x64\x13\xff\x4d\x35\x8a\x8a\x9c\xbd\xab\x01\xad\xf4\xdb\x02\xad\xae\xa2\x64\x94\xd1\xf5\xd6\x17\x63\x7f\x27\x7f\x8b\x0e\x6e\x7e\x61\xe2\xee\xcc\xdd\x33\x7d\xe2\xba\xf0\xca\x26\x4c\x14\xc8\xcb\x83\x68\x00\x0b\x9c\x71\x43\x85\xf4\x13\x73\x7d\x68\x16\xe2\x12\xca\xe2\xae\xcf\xff\xc3\x2f\xd1\x6d\x46\xc3\xec\xee\x6a\xb0\x74\xc0\xd7\x68\xbd\xfe\x99\xb8\x6c\xbb\xc8\xdf\x9c\x47\xcd\x58\x6d\x46\x58\x71\x26\x8d\x4a\x9d\x1c\x87\x72\x36\xab\x78\xf8\x85\x9c\x11\x4e\x25\x1c\xab\xc4\xbe\x0f\x8b\xc2\x5d\x14\x8c\x5f\x54\x3e\x29\x07\x45\xd1\x18\x03\xe4\x9f\x5b\x53\x19\x3f\xe3\x99\x69\xc0\x39\xb3\xf2\x49\xb3\x2f\x2b\x85\x98\xb6\xac\xf4\xed\x64\xd5\x75\x2b\xb7\x72\xff\x4e\xe0\x0c\xe0\xf8\x5e\xcb\xb4\xcf\xc4\xce\x07\xda\xf2\x80\x98\x68\xc2\x90\x3b\x78\x1e\x12\xa2\x74\x10\x5f\x06\x18\x10\x29\xe4\x7f\x2b\xfb\x21\xf4\x94\x80\xaa\x1e\x44\x47\x15\xc0\xb9\xff\x07\xea\xd8\x89\x75\xd9\x35\x85\xd2\xff\x42\x48\x32\xa9\x78\x3d\x94\x90\x6a\x60\xf8\x77\xae\x1c\x85\xff\x15\x31\x7b\xad\xca\x1e\x61\x31\x74\x33\xc7\xce\x96\x27\x9b\x67\x8e\xc9\xd1\x74\xdd\x08\x70\x08\x0b\x23\x41\x54\xf6\x26\xa5\x34\x62\xcf\xd5\x47\x84\x2e\xab\x87\x05\x60\x5b\x8e\xe8\x85\x72\x9e\xe7\x8d\x18\x33\xaa\x43\xf5\x5a\xc2\x27\x31\x98\x9f\xde\xda\x7d\xc5\xfa\x9c\x01\x98\x5f\x26\x61\xe6\xc7\x32\x6d\x34\x6e\x6d\xb2\x7e\x6f\x92\x1f\xae\x7c\x93\xa2\x17\x0e\x10\xdd\x0c\x46\x0b\xdc"}, -{{0x64,0xe8,0x93,0x04,0xa3,0x35,0xe9,0x03,0xcb,0x36,0xc0,0xbd,0xf1,0xa6,0x41,0x2e,0xf3,0x68,0x46,0x80,0x06,0xb7,0x3d,0x3d,0x2d,0x61,0xcb,0x03,0x0c,0xc5,0xf8,0xd1,},{0xa1,0x80,0xef,0x3a,0x66,0x1c,0x3c,0x47,0x9d,0x5f,0x69,0x80,0x7c,0x90,0x27,0x48,0xe3,0x5e,0x7f,0x72,0x51,0x21,0xe3,0x7a,0x5d,0x91,0xb8,0xbe,0xc8,0x8d,0x83,0xa6,},{0x92,0xeb,0x44,0x54,0x81,0x40,0x01,0xec,0xfc,0x18,0x02,0x5d,0x64,0x21,0xf6,0x46,0x45,0xa5,0xbc,0xbb,0x5c,0xb8,0xfd,0x85,0xc1,0x4d,0x77,0x26,0x17,0xc5,0x03,0xe8,0xbe,0x7d,0x3b,0xcf,0x11,0x7f,0x5e,0x68,0x01,0xd1,0xc3,0xb9,0x6f,0x90,0x90,0xa6,0x6d,0xdc,0x67,0xf8,0xcf,0x8f,0xf0,0xf1,0xc1,0x25,0xb1,0x6b,0x15,0xe2,0xce,0x07,},"\x2f\x51\x07\x4d\x98\x1b\xda\xfa\xfb\x02\xa4\x0f\xe8\x26\xc4\x5f\x31\x71\xc1\xb3\x18\x4d\x8c\x26\x0b\x82\xb8\x41\x1f\xc6\x25\xcb\x02\xcc\xfe\x75\x5d\xc2\x9d\xc7\x89\x5b\xf7\x59\xe6\x1b\x24\x50\xda\x1a\x65\x6a\x38\xd4\xf7\x0d\x2e\xe7\x48\xc5\x18\xc6\x42\x03\x06\xe5\xf0\x1e\xc7\xa0\xff\xe0\xe9\xdc\xeb\x93\xf6\xc0\x77\xb1\x26\x62\x88\x15\x84\xf9\x8c\xe6\xab\x94\x5f\x87\xfc\x6d\x12\x3c\x45\xd6\xcd\xfd\x82\x37\xa1\xce\x36\x35\xb6\x23\xa7\x9d\x02\x0d\xf4\x4c\x74\xb8\x9a\xc1\x4a\x32\x1f\xbf\x33\xa8\xc0\xa2\x55\x9f\xea\x1c\x2b\x15\x60\x76\xb8\x13\x90\x8f\x84\x2e\xbe\x4c\x2b\x94\x90\x89\xe5\x2b\x1a\xe4\x0d\xc6\xe4\xb2\xab\xbc\x43\x9a\x0b\xf7\x23\x69\x67\x9a\xab\x6f\x4c\x00\x01\x8b\xe1\x47\xf7\xc0\xa6\x7b\x96\x79\xee\x88\xa5\x38\x19\xc4\x9f\x7b\x67\x5e\x30\xa8\xb5\xaf\x39\x66\x1e\xe8\xdb\x21\x01\x04\x11\x29\x49\x68\xf8\x8e\x5d\x60\x4d\x0d\x88\xd7\x6a\x7e\x48\x64\xfa\xd3\xa5\x6f\x5f\x62\x4b\xa1\xb3\x4e\xa9\xcb\x72\x08\x50\xaa\xd3\xbd\x4f\x0a\x88\x2a\x7d\x25\xfb\xec\x2b\xb7\xca\x86\xda\x61\x6d\xa9\x6c\x15\x62\xc6\xd6\xa1\xab\xcc\x64\x1e\x1b\x58\xb2\xc1\x78\xe1\xc3\xbc\x8a\x3b\x36\xec\x9e\x14\x4d\xd2\xe7\x5b\x0b\xc8\xc0\x8c\xcb\x0d\x6e\x34\x27\xb0\x32\x2b\x3d\x6a\xb9\x3f\x3f\x60\xb9\xcc\x5b\x61\xda\xd0\x23\x85\xa1\x49\x49\xf9\xb8\x7a\x8e\x3a\xf1\xe0\xe0\xfa\xb7\xa9\xa9\x28\xc7\x53\xfc\x61\x10\x44\x4a\xf7\xcc\xaf\x80\x27\xed\x64\x1b\x9e\xd8\x7f\xa5\xd8\xe1\xf7\x6c\xae\x46\x5d\x57\xa7\x0d\xad\x9e\xbf\xdd\x3c\xe7\x57\x6a\xc4\xde\x89\xd9\x8f\x42\xe2\x82\xad\x87\xad\x6a\x50\x42\x57\x7c\xbb\xbc\x4d\x95\x1e\x2a\x86\x76\xfe\xdc\x8c\xb1\xb1\xbd\xf7\x6c\x3a\x38\x84\x63\x85\xa8\x5a\xa2\x47\x06\xc2\x0a\x8b\x38\x46\x5f\xe2\xae\x0e\x41\xf7\x8e\x61\x4b\x8e\x96\x42\xfe\x24\x71\xa9\x01\x57\x47\xdb\x97\x6e\x0c\x78\x48\xc2\x3f\xf3\xf4\x17\xcb\x05\xa8\xd5\xef\x40\x13\x0a\xdf\x85\x5c\x99\x8a\x62\x10\x4d\x7e\x2f\xb7\xc0\xf9\xaa\x2a\x49\x60\x75\x62\x3c\xed\x2c\x0f\x7e\xec\x10\x14\x7f\xf9\x60\x8a\x8a\x04\x2e\xf9\x81\x17\x45\x9b\x93\x83\x7f\xd1\xb8\xd5\xef\x03\x97\x8e\xad\xa7\x4c\xac"}, -{{0x6f,0x63,0x43,0x87,0xca,0x2c,0x0c,0xb1,0x67,0xa7,0x40,0xd6,0xaf,0xd8,0x9e,0x2a,0x28,0xf5,0x30,0x71,0x84,0xe8,0x1c,0xba,0x3c,0x03,0x70,0x46,0xa5,0xed,0xe2,0x3c,},{0x01,0x1f,0x2a,0x9a,0x11,0x1c,0x38,0xf3,0x49,0x0c,0xad,0x16,0x85,0xbe,0x78,0xec,0xee,0xdc,0x6f,0xac,0x4a,0x32,0x21,0x30,0x1c,0x69,0xc8,0x4b,0x1e,0xc7,0xb3,0xa7,},{0xfd,0x17,0xc6,0x18,0xcd,0xbb,0x5d,0x45,0x9e,0xa2,0xac,0xa8,0x86,0xf0,0x51,0x2c,0x62,0x32,0x51,0x28,0x4a,0xae,0x3a,0x83,0xeb,0x5d,0x7f,0x60,0xda,0x1d,0x9b,0x2b,0xa0,0x83,0xc4,0x55,0xa5,0xe2,0x58,0x3a,0x3c,0xba,0x73,0x6e,0x7b,0x96,0x1b,0xa1,0x9c,0x1c,0xc8,0xdd,0x90,0x74,0x5d,0xa8,0x2a,0x15,0xdf,0xc6,0x62,0xe8,0xe1,0x0d,},"\x86\x5c\x20\xa9\x4a\xc3\xf2\xe3\xbd\x5c\xb8\x5b\xec\x9d\x33\x72\x66\x71\xfe\x01\xf9\xc5\x37\x01\x7d\x59\xc8\xd5\x10\x6e\x43\x36\x0b\xf7\x6f\xc0\x61\x86\x70\x59\x80\xc8\xa8\x7b\xa3\x63\x3a\x4a\x17\x04\x26\xec\xc0\xde\xfb\x6d\xb2\x67\x0f\x5f\x59\x25\x33\x77\x4c\xda\x50\x05\x2a\xe5\x97\xd4\x8d\xea\xcc\x26\x37\x06\x3b\xfd\x51\x9f\x2e\x79\xba\xc8\x17\x75\xbe\xcc\xb1\xab\x2f\x5b\x39\x71\x2e\x2e\x82\x94\x69\xb7\x5a\x2d\x2d\xbd\x08\xaa\x6d\x24\x72\x34\x04\xb2\x5e\xb9\x48\xa4\x83\x4c\x55\x24\x6c\x80\x79\xa8\x2e\xc6\x43\x54\xe8\xc2\x38\x8f\x8c\x5a\x61\x6b\x3c\xdc\x37\x1e\x62\x63\xfa\xbc\x9f\x60\x99\x21\x9e\x86\x15\x85\xfe\x82\xa6\x7d\x61\x0d\xd1\xeb\x5c\x81\xc9\x6b\x5c\xb3\x54\xa6\x89\xfd\x8a\xac\x8d\xb7\x6c\x43\x3f\x0c\xb0\xb3\x1c\xf1\xd8\x55\xb6\xa3\x0a\x3d\x2a\x21\x2e\x9b\x4f\x7d\x7a\xfe\x61\x99\x51\xf9\x8d\x2f\x1b\xa2\xc1\x01\x08\x5b\xa8\x1f\x49\xb3\x60\x37\xcd\x64\x57\xa7\xea\xa8\xf4\xf3\xbe\xdf\x68\xd0\x9f\xc9\xfa\x25\xa9\xd7\x54\xdb\x65\x36\x02\x85\x41\x2d\x1a\x6d\xa5\x37\x88\x90\x5f\xcf\x4e\xfa\x8a\x80\xcd\x86\xca\x48\xb8\x45\x63\x3d\x8c\x31\xc2\xae\x06\xf1\x6c\x4c\x6b\xbb\xe9\xcd\x1a\xfb\x59\xe1\x01\xbe\x50\xe0\x35\x35\xdd\x8a\x65\xe4\x5b\xba\x46\xd4\x5c\xb1\x4b\xad\xfc\x8e\x93\xab\x52\x67\xf4\xe4\x92\xab\x1f\x9a\x95\xe6\x1f\xca\xb8\x1c\xbf\x2b\xd8\x67\xa3\xec\x7b\x4b\xaa\x18\x9a\x0f\x08\x56\x70\x75\x59\x61\x29\xdc\xf9\xff\x1c\x50\x2d\x32\x79\xe8\xaa\x6c\xe5\x6e\xaf\x13\x45\x82\xa9\xe4\x30\xa5\xaa\x8c\xa1\x0c\x3d\xa8\xbc\x79\x3d\x02\x56\xad\x19\xae\xa7\x14\x9f\x0e\xa7\xea\x95\xfa\xcf\xac\x1c\x5c\xfd\x29\xd7\xa3\xfe\x1a\x41\x79\x75\x73\x9e\x14\xda\x8e\xdc\x81\x99\x00\x47\x2c\xa8\xc6\x97\x16\x32\x8e\x8a\x29\x9f\x97\x4e\xdf\xf7\x41\xaa\xbc\x1c\x07\x4a\x76\x1b\x3e\xc8\x76\x1d\xda\x2e\x7e\xed\x7a\xf3\x3e\xf0\x04\x09\x84\x9d\x41\x54\x97\xc5\xed\x5d\xfa\xa2\x25\x9a\x31\xd0\x76\x39\x81\x70\xb2\xd9\xd2\x10\x20\x8b\x4a\x4c\x7d\xb8\xc6\x26\xd1\xc5\x33\x56\x2a\x1f\x95\x48\x9f\x98\x19\xe4\x98\x5f\xc4\xe1\xd1\xa7\x07\xbe\x5e\x82\xb0\x05\x48\x1d\x86\x37\x7f\x42\x4e"}, -{{0x4b,0x2e,0x1a,0xe6,0x0f,0xa5,0xd3,0x83,0xba,0xba,0x54,0xed,0xc1,0x68,0xb9,0xb0,0x5e,0x0d,0x05,0xee,0x9c,0x18,0x13,0x21,0xdb,0xfd,0xdd,0x19,0x83,0x95,0x91,0x54,},{0x36,0xc0,0x20,0xb1,0x85,0x52,0x34,0x56,0x19,0xef,0x88,0x37,0xeb,0x8d,0x54,0x94,0x84,0x0e,0x85,0xf4,0x68,0x09,0x34,0x3b,0x4d,0x6f,0x40,0x61,0x25,0xda,0x55,0x7d,},{0x22,0x20,0x11,0x9e,0x83,0xd6,0x9a,0x6a,0x3e,0xed,0x95,0xfa,0x16,0x6d,0x1d,0x11,0x28,0xa3,0xf2,0x32,0xca,0x1b,0x78,0xbc,0x94,0xb4,0xd4,0x76,0xc4,0x77,0x94,0x43,0x61,0x4b,0x87,0x72,0xaa,0x22,0x32,0xcb,0x07,0x20,0xa0,0x55,0xeb,0x71,0xd8,0x40,0x7f,0x3a,0xb1,0x9b,0xaa,0x1d,0x96,0x2c,0x05,0x2c,0x84,0xc0,0xbd,0x58,0x96,0x08,},"\xfa\xb9\x8b\x2b\xbf\x86\xae\xb0\x50\x86\x81\x2a\x4b\x00\x49\xa1\x04\x2a\xbb\x76\xdf\x9c\xd2\x90\x87\x55\x70\x63\x03\xef\xed\xb1\xad\x21\xe8\xbc\x8d\x75\x62\x34\x9e\x1e\x98\xce\x0d\x75\x2f\x4b\x3d\x99\xe6\x77\x36\x8b\xd0\x8c\x78\xfe\x74\x25\xec\x3b\x56\x0e\x38\x3b\xd4\x2a\xf6\x49\x98\x86\xc3\x5a\xdd\x80\xa5\x82\x8b\x61\xd6\x64\x4d\x7d\xc4\x43\xba\x2c\x06\xf9\xba\xd2\xec\xcb\x98\x3d\x24\x45\x8f\x6a\xda\x1b\x10\xbb\x5b\x77\x17\x2c\x5c\xdd\x56\xd2\x73\xd1\xe4\x10\x10\xb2\x5c\xf4\x8a\x7d\x58\xd7\x25\x57\x02\xac\x12\xf2\xa6\xfe\x29\x18\x46\x63\x95\xf4\x60\xd1\x52\x36\xd0\x35\xae\x94\x10\xca\x86\xc4\x60\x51\x28\x29\x9f\xaa\xf0\x90\x15\xf1\xad\xee\x77\x68\xee\x1a\x8f\x8c\xa0\x6d\x10\xdd\x7f\x95\xc4\x6f\xa1\x02\x53\x06\x5f\x9d\x6f\x90\x29\x59\x08\x80\x9f\xd7\x79\x57\x1b\xe2\x9e\x0a\xe6\x6e\x0b\xcb\xde\xb7\x91\x3d\x2b\xbb\x76\xac\x30\x2f\x34\x52\xc5\x5e\xf1\x99\xa4\x8e\xce\xb0\xe3\x59\x6c\x7b\x4c\x03\x86\xda\xe7\x10\x1e\xa2\x44\xa3\x3c\x4c\xdc\x83\x06\x72\xdf\x83\x65\x5b\x35\x33\x80\x52\x30\x7b\x94\xd2\x23\xca\xb1\xaf\x69\xe0\x7f\x78\xe5\x8c\xbb\x0c\xb3\xc5\x35\x1e\x3a\x6b\x0c\x4a\x92\x7f\x75\x62\xc5\x98\xd2\xd3\xdf\x90\x56\x9f\x61\xdb\x1a\x3c\xb0\x14\x0b\x56\xea\x02\xcf\x77\x45\xfb\xee\xc2\x02\x86\x73\xd6\x7f\x1e\xc5\xf7\xda\xf9\x71\x5f\x75\x4a\x9d\x8e\xd4\x6a\x7a\x63\xef\x72\x2e\xe0\xd5\x89\x93\x31\xb6\x3c\x97\x4f\xa8\x80\x42\x94\x35\x76\x7f\x96\x25\x4e\xf4\x6c\x99\x68\xf3\xfe\xda\xaf\xea\xf3\xe8\xf4\x56\x34\xb5\x4f\x5e\x0a\x5f\xc2\xd2\x37\x3a\xb9\xe9\x8d\x9a\xcf\xe3\x69\x7e\x64\x2a\x18\xe0\xdf\xd9\xfb\xc2\xf0\x94\x86\x6d\x40\x1f\x0a\x4c\xa2\xa4\x56\xed\xf6\xa1\xa7\x7b\x9c\x29\x6c\x39\x22\x06\x7e\xb3\xd5\xa5\xca\x0a\x77\xf4\x30\xe4\xc8\x61\x1d\x8f\x05\xa1\xba\xac\x16\x35\xef\x7b\xa8\x3d\xfc\x69\xd3\x01\x94\x98\x56\xbe\x4d\x2c\x8a\xb6\x1d\xe2\x9c\xf3\x92\x50\xc5\x79\x4c\xbf\x57\x50\xcd\xa9\x5d\x04\x68\xaf\xa2\xb7\xf2\x3d\xba\x4e\xf5\xf5\x29\x5a\x3b\xf4\x14\x00\x18\xb7\xed\x06\x18\x84\x44\x4f\x5b\xb1\xb7\xd2\x39\x31\x2d\xd7\x39\x99\x95\x36\xc6\x84\x45\x6e\xa0\x6b"}, -{{0xb2,0x16,0xce,0xbf,0x87,0x80,0x24,0xc2,0x0d,0xfc,0x86,0xce,0x4b,0x37,0xbd,0xc4,0x7a,0xa2,0x8f,0x29,0x20,0x3b,0x5b,0x44,0x92,0x50,0x65,0xd9,0x93,0xa2,0x59,0xfe,},{0xc3,0x6e,0xdb,0xb6,0x25,0x4a,0x91,0x3f,0x08,0xfe,0x25,0x9e,0x23,0x87,0x80,0x63,0x8f,0x72,0xec,0x0b,0x30,0x07,0x26,0x4b,0xcc,0x60,0xa9,0xe8,0x1e,0xe9,0x29,0x8f,},{0xb7,0x38,0x9e,0xe7,0x8d,0xd9,0x76,0x3f,0x9d,0x28,0x92,0x91,0x2e,0xdc,0xbe,0x3e,0x8a,0x23,0x6b,0x8b,0xdc,0x25,0xf4,0x4b,0x9c,0xfd,0xc8,0xc4,0x7c,0xd5,0x81,0x68,0xab,0x56,0xeb,0x04,0x02,0xa5,0xbd,0x75,0x2a,0xc8,0xf4,0x97,0x8d,0x2e,0xa2,0xb6,0x5d,0x2f,0xa8,0x52,0x65,0x96,0x6b,0x9f,0x57,0x22,0x7e,0xf4,0xa5,0x9a,0xe0,0x09,},"\x9c\x87\x17\xcc\x86\xfe\x02\x48\x0b\xfd\x9e\x92\x2b\xd7\x6b\xff\xee\x21\x70\xc4\xcb\x1b\x13\xdf\x83\x4a\xc0\x1d\x45\x00\x60\x86\x29\x7f\x1b\x8a\x26\xf2\xba\x67\x4d\x33\xe1\xd1\x62\xf1\x93\x67\xfe\xba\x97\x35\x2b\x7d\xf2\xe7\x5b\x30\x9d\x4b\x6f\x8b\x07\xcc\x0e\xb6\x77\x7e\x81\xe2\x68\xe0\x2d\x07\xf2\xa0\x8f\x8f\x39\xd5\xa8\x32\x0b\xfc\x01\xfc\x8c\x92\x27\xd2\xcf\x05\xe1\x28\x91\xff\x4d\xe8\x85\xa1\xc9\x33\x71\xa0\x91\x0b\xa5\x33\x92\xaf\xf9\xba\x2e\xed\x9a\x20\x55\x97\x7e\xc4\x15\x7b\xd6\x5b\x34\xdf\x79\x37\x2f\x4d\x50\xed\xbc\x48\x92\x43\x53\xcf\xa1\x69\x23\x19\xd8\x8a\x7a\x5b\xb7\x26\x25\x4c\x20\x92\x91\xe9\xb1\xd2\xc1\xa6\xc8\x23\x63\x98\x10\x9c\x59\xed\x42\xa0\xac\x9e\x76\x33\xc5\x20\x73\x4e\xcc\xfe\xa4\xfe\xa9\x5a\x47\xa8\xf0\xa0\x68\xb4\x27\x50\x00\x43\x9c\xc9\x7c\x57\x87\x1e\x10\x5c\xc0\x79\x0e\x9d\xcc\x9c\x25\xd5\xaf\x70\x63\xff\xd0\x5c\x4f\x37\x80\xe7\xbc\xa4\xc4\x56\xd0\x17\x0d\xa7\x09\xfc\x6c\xb3\xfa\xa7\x2b\xdc\xf5\x62\x90\x8a\xe9\x34\x0a\xef\x4d\x0c\x8b\x91\xf0\xfb\xcc\xbc\xf1\xcd\x89\x8b\x1c\x71\x6f\x4f\x14\x74\xc3\xaa\x31\x62\x42\xab\xdf\x63\x68\xe5\x7a\x24\x7f\xf2\xfd\x5c\xe2\x3d\x18\x7f\x69\x4f\x11\xe3\x8d\xfb\xfb\xc3\xd9\xdb\x20\x90\x3b\x4e\xbb\x44\x9b\x90\x49\xee\x02\x0f\x6e\x2f\x50\x8e\x8b\x2b\x16\x5b\xad\x74\x64\xdb\xdd\x17\x8c\xbd\x42\x32\x33\x76\x5d\x37\x1e\x7a\xe1\xc3\xe8\x78\xcd\xb5\xb8\x24\xb2\x0c\xb3\x09\x86\x7c\x0e\x47\x3c\x06\x7e\x67\x44\x00\x85\x27\xb6\xbc\x07\x6d\x07\x7f\x48\x67\x62\x2a\xee\xd1\xc2\x53\xdb\xde\x7c\x6a\x76\xc7\x01\x59\x62\xfb\x73\x39\x16\x98\x60\x0b\xb3\x18\xff\xa7\xb0\x13\x6e\xe4\xcc\xb0\x7d\xaa\xf0\x1f\x40\xff\x9c\x19\x4f\x98\x68\x1f\x9f\xae\xf8\xb6\xf9\xe9\x9f\x95\xdf\x00\x80\xda\x89\x66\xa8\xba\x7a\x94\x74\xc5\x37\xb9\x2d\xf9\x79\x9e\x2f\xd1\x6f\x78\x8d\xad\x7a\x7b\xcc\x74\x52\x26\xe1\xe6\x37\x1f\x52\xeb\xcd\xbd\x14\x40\x44\xdd\xfe\x63\x2d\xfc\x0a\x43\xd3\xa4\x50\x92\x31\x70\xeb\xc7\xae\x21\x9e\x50\xe0\x78\xa5\x11\xbc\x12\xef\x14\xcd\x14\xb5\x30\x9f\x38\xab\xd6\x5d\xb2\xb2\xa7\xaf\x22\x43\xb2\x29\xc9\xfd\x2e"}, -{{0xaf,0xce,0xce,0xa9,0x24,0x39,0xe4,0x4a,0x43,0xed,0x61,0xb6,0x73,0x04,0x3d,0xcb,0xc4,0xe3,0x60,0xf2,0xf3,0x0c,0xd0,0x78,0x96,0xcd,0xa2,0x0c,0xb9,0x88,0xd4,0xe3,},{0xd2,0x31,0xf6,0x92,0x35,0xa2,0xe3,0xa1,0xdd,0x5f,0x6c,0x2a,0x9a,0xaf,0x20,0xc0,0x34,0x54,0xb9,0xa2,0x9f,0x4e,0x3a,0x29,0xab,0x94,0x68,0x9d,0x0d,0x72,0x3e,0x50,},{0xa6,0x55,0x45,0xcf,0x3d,0xf4,0x56,0xb2,0x8d,0x83,0xa6,0xd9,0x4c,0x03,0x6a,0x19,0xd0,0xd2,0x9f,0xb0,0x65,0xed,0xc2,0x7e,0x5e,0x93,0xa1,0xf4,0x02,0x79,0x89,0x7e,0x1c,0x6f,0x25,0x95,0x9a,0x72,0x5a,0xba,0xbc,0x87,0xcf,0x2a,0xe7,0x27,0xf3,0x46,0x7b,0x79,0x57,0x0e,0x90,0x27,0x11,0x91,0x71,0x91,0xd9,0xcb,0x0d,0x2d,0x66,0x0c,},"\x0b\x05\xf8\x9e\xbb\x33\x97\x94\x76\x87\xaf\xbe\xf0\xed\xe8\x7c\xf3\x81\x06\x76\x27\x70\x37\x52\x1d\x95\x2a\x3b\xbb\xbd\xc8\x56\x59\x88\xa0\x95\xd8\xd4\xf6\xf5\x9b\xe5\x72\xd3\xd8\x21\xdd\x78\x99\x77\xef\x77\xa2\xfd\x71\x10\xce\xee\xd9\xf3\x75\x6e\xd8\xe1\x88\x26\x7b\x97\xa3\x0e\xf8\x95\x7c\x78\xae\xa3\xa2\x96\x3d\xec\xa6\x18\x60\x54\x5e\x0c\x40\x82\x48\x81\xeb\xb1\xdb\x10\xf6\x07\xe1\x0d\xdb\xdd\xce\x40\x0e\xa2\x36\xba\x47\x45\xaa\x99\xa0\x56\x41\x97\x67\x66\x78\x9e\xd0\xda\x7d\xb5\x5f\xda\xb4\x59\xeb\xd4\xb4\x41\xa6\x28\x2f\x7c\xfd\x5a\x20\xea\x06\xef\xfa\x33\x59\x55\xe5\xfd\x29\x18\x16\x71\xbc\x92\xc0\x00\x52\xf7\xf7\x5c\x39\x27\x7c\x9a\x43\xb7\x87\xac\x9f\xb1\x51\x6e\x99\x62\x32\xa5\x09\x77\x4d\x1d\xc2\x1d\x8c\x05\x13\xf7\x84\x4b\x0a\x5b\x5f\x18\x95\x75\x81\xf9\x90\x44\xa1\x42\x23\xcc\xda\x8a\x28\x4d\xe1\x2f\xd4\x24\x26\x5f\xe5\x7b\x27\x02\x15\xf8\xfa\x9f\xf2\xbe\xa5\x17\x93\x4e\x48\x00\xa4\x7d\x34\x6f\xb6\xc3\x61\xcf\xba\xbe\xff\xab\xd9\xc4\x16\x4f\x45\x15\x6e\x24\x5c\x97\x7e\xdb\x47\x36\x42\xc3\x94\x0b\xe5\xad\x6f\xd1\xa7\x11\x9a\x7b\x18\xe9\x8d\x6d\xc8\x43\xe0\xd2\x54\xc9\x3d\x01\x46\xd1\x8e\x5c\x62\xed\xe1\x49\x0f\x89\xa6\x05\xeb\x45\x4f\x97\x47\x78\xcf\xae\x20\x93\x2e\x95\x47\x7b\xd0\x3b\xcd\xb9\x7d\x5b\xcb\x76\x33\x59\x42\xe9\x2e\xe6\x68\xf2\x31\xe6\x9c\x57\x0a\xc5\x44\x6d\x0f\x77\x40\x66\x73\x7f\xdf\x49\xf1\x0c\xeb\x1b\x52\xd6\xd8\xa4\x63\x98\x46\xa3\x37\x3a\x7c\x6f\x3b\x4b\x31\x59\xfe\x2e\x7a\xf7\xee\xe2\xf0\xdf\x17\x2d\x94\xd2\x55\xd0\x17\x65\x1d\xa3\x00\x90\x05\xe5\xea\xc3\x17\x6c\x09\x38\x9e\xe4\x0d\x70\x38\x3b\xd3\x71\x17\xec\xa0\x83\x59\x8a\x18\x01\xf5\x92\xd0\x57\x18\x6e\x56\x8e\x24\x7c\x25\x2b\xe4\xb1\x4f\x72\x3a\xb7\xdd\xb9\x7a\xe9\x76\x8c\x26\x82\xfd\x63\xac\xc3\x00\x77\x9f\xe0\x4e\x2b\x88\x87\x47\x51\x34\x6c\x9e\x0f\x97\xa2\xa2\x16\x77\x2f\xf9\x62\x5c\x33\xbd\x7e\x29\xfe\xd8\x00\x3a\x08\xdb\xd3\x3b\x5d\x17\x89\x9c\x94\x3c\x25\xe9\x5a\xd7\x54\xfb\x63\x2e\x04\x7c\x11\x2a\xf7\xf7\xce\xba\x72\x36\x2e\x1a\x3d\xdd\x29\x35\xaa\xf7\xf8\x18\xa2\x7c"}, -{{0xb8,0x34,0xc6,0xe0,0xfa,0xcb,0xff,0x58,0x0d,0xd3,0xb2,0x37,0x53,0x95,0x9a,0x4c,0x21,0x54,0xc2,0x19,0x52,0x1b,0x3d,0x27,0x03,0x5d,0x07,0x1f,0x65,0x99,0xbd,0x02,},{0xd1,0xc3,0x84,0x71,0x5e,0x3b,0x3d,0x02,0xc1,0x3e,0x09,0x06,0x05,0x53,0x4c,0x7d,0xb7,0x40,0xda,0x2a,0xa5,0x60,0xf5,0x32,0x00,0xa3,0xce,0xd8,0xbe,0xae,0x8c,0xf8,},{0x0f,0x19,0xb7,0x06,0x6d,0x57,0x92,0x32,0x8a,0x98,0x00,0xd9,0xd4,0xf8,0xf6,0x7d,0x5b,0x08,0x9b,0x54,0x12,0x26,0xa1,0x67,0xda,0xcd,0x43,0x9f,0xa4,0x85,0xb0,0x02,0x5a,0x5d,0xc7,0xf2,0xc7,0xe2,0x3f,0xc4,0xa5,0xc6,0x86,0x9e,0x76,0x19,0xd3,0x56,0x39,0x97,0x00,0xc9,0x36,0x50,0xe8,0x9c,0xd2,0x5b,0x90,0xfb,0x99,0x25,0xe3,0x04,},"\x6c\xf1\x47\xb1\x60\x55\x28\xa3\x6b\xe7\x57\x16\xa1\x4b\x42\x0b\xcf\x06\x7c\x03\xf1\xcf\xe9\xc4\x40\x2f\x14\x98\x7f\xbf\xc9\xd3\xec\xc3\xcc\xf4\xf8\xd2\xd0\x3a\x55\x90\x0b\x8d\xc7\x9a\xf3\xb6\xe7\x74\x36\xf6\x9b\x14\x17\xad\x4b\x68\xfd\x44\xe5\xe3\x33\xed\x90\xea\x79\x43\xfb\xd1\x12\x26\x09\xec\x8f\xf6\xbb\x25\xe4\x2e\x99\x14\xf5\x92\x0f\xc7\x2c\x4d\x01\x3b\x6a\x96\x85\xc9\x96\xfb\xd8\x35\x2a\xaf\xb1\x84\xc2\x2d\x9e\x47\x87\x1a\x52\x80\xe4\xab\x7d\xd6\xa5\xcf\xd1\x0a\x59\x94\xa2\x00\xf6\x70\xe0\xb6\x22\xa9\x39\x4d\x47\x93\xd0\xa4\x20\xe7\xd8\x80\x6c\xb1\x27\xc7\xac\x69\x0d\x45\xa2\xe9\x41\x66\xce\xa6\x72\xbc\xd9\x82\xb0\xe9\xba\xad\x56\x31\x2d\x25\x70\xdd\xde\x7e\x0b\x9e\x7f\x47\x13\x6f\x04\x81\xd0\x0f\x66\xa2\xaa\xca\x4d\x1b\x09\xd7\xce\x6c\x5a\x98\xa7\x6b\x68\xcd\x97\xd5\x79\x39\x68\xd6\x67\x07\x3f\x82\x17\xf9\x05\x47\x35\x34\x0f\x9b\x14\x9c\x0d\xce\x84\x5b\x09\x9e\x88\xd0\x70\x96\x80\xf0\xf7\x76\x03\xff\x0a\x23\x31\xc5\x58\xfc\x36\xd5\xf2\x4d\xa9\xa6\x2d\x69\xaf\x51\x90\xd2\x1b\x5c\x85\x7a\x1e\x08\xf0\x14\xc6\xd4\x56\x46\x86\x65\xa7\xf8\x45\xc6\x6f\x91\x11\xf9\xc0\x98\xc6\x89\x40\xef\xcd\x87\xb6\x57\x07\x0c\xb9\x16\x4b\xc9\x74\x3a\xce\xb7\x43\x9a\x0d\x01\xc0\x06\x2a\x11\xaf\x2e\x11\x34\x93\x97\xf5\xd1\x52\x87\x2b\x13\xc5\xab\x32\xf5\x1c\xc5\x8f\x14\x75\xec\x82\xac\x67\x15\x61\xdc\xbd\x34\x3c\xfb\x3c\x5f\x78\xd0\xfc\x73\x05\x3c\x60\x04\xb0\xa4\xca\x3f\x20\x43\xff\x4b\x0c\x54\x27\x5c\x4f\xcb\x9c\xad\xc6\xba\xab\xe5\x7b\x1d\x5a\xcd\x53\x1e\x97\x2e\xf9\x33\x51\x36\xcd\x1d\x65\x51\x2b\xa1\xf5\xb6\xcc\xc4\xb6\x6b\x42\x50\xaa\xfa\x29\x67\xdd\x42\x11\xa2\x74\x2e\x0f\x17\x7d\x8f\x40\x63\x89\x9f\x61\x81\x5c\xbe\x6d\x8f\xbf\xcd\xf7\x48\x12\xbd\x40\xcc\x10\x08\x4e\x46\xa9\x9a\xc1\x28\x05\x8e\xaf\x16\xa4\x9a\x24\xb6\xae\x22\x8e\xcf\x01\x09\xc5\x2d\xfc\x06\xe3\x7d\x6a\x33\x3b\xcb\x24\xab\xa3\x12\x16\x4c\x6c\x02\x90\x48\x5d\x25\x12\x80\x53\x8c\xe9\x54\x1c\x09\x16\x64\x0e\x36\xd6\x92\x9d\xcd\x95\x88\xeb\x99\x57\x7f\x5f\x6d\x82\xbc\xbb\x19\x88\x26\x26\x7e\x49\xf5\xda\xff\x2c\x0d"}, -{{0x22,0x69,0xa5,0xd8,0xf7,0xac,0x2c,0xd9,0x04,0x8f,0x5f,0x49,0xe3,0x49,0xe5,0xc4,0x35,0xa1,0x59,0xb3,0x19,0xfe,0x3b,0x30,0xbf,0xac,0x8d,0x0d,0x50,0x59,0x43,0xf4,},{0x1c,0x81,0x79,0x43,0xdc,0x39,0xc2,0x4b,0x01,0xda,0x38,0xa4,0x87,0xb1,0x75,0x48,0x24,0x60,0xc6,0x09,0xe4,0x72,0x63,0x49,0xa9,0xaa,0x7a,0xea,0x9b,0xc0,0xfb,0x34,},{0xbe,0x0f,0xb3,0x30,0x8a,0x07,0x6a,0x61,0xa4,0xa9,0x2a,0x97,0xf6,0xac,0x55,0x32,0x71,0x90,0xe1,0x34,0x1d,0x6d,0xd4,0x10,0xd8,0x6b,0x41,0xbd,0xaf,0x2d,0x33,0x74,0x09,0x3e,0xf7,0x20,0xbd,0xb7,0x7f,0xeb,0x70,0x14,0xe0,0xf7,0x7d,0x3b,0x80,0x96,0x23,0xc7,0xca,0x53,0xe2,0xae,0x4b,0x09,0x71,0x13,0xe9,0x6d,0xb7,0x7a,0x2d,0x08,},"\x71\x53\xd4\xd9\xe6\x41\xaa\x61\x92\x0d\xb0\xff\x4b\xd5\x37\xa6\xd6\x13\x0a\x39\x65\x54\xcc\x94\x53\x76\x98\xf9\xca\xd1\x6b\x99\xee\xbe\xfa\x5f\x27\x76\xf2\xfe\xaf\xf6\xbd\x9a\x69\x04\x12\x0c\x67\xe0\x88\x3f\x6b\x96\xbb\xbb\x19\x5e\x95\xae\xc7\x53\xb6\x99\xba\xb3\xd0\x39\x44\xc1\x3c\x72\xfc\x84\xe3\xf2\xcb\xf6\x29\x6f\x64\x55\x49\x11\x1c\x93\xfa\xe1\xa7\x59\xbf\xcd\x16\xfc\x09\xe6\x0b\xb9\x78\x55\x35\xad\x27\xda\x24\x4e\xf2\xf8\x57\xf2\xde\x99\xa6\xe9\x21\x88\x89\x0e\x45\x2c\x7f\x5b\x9e\x3a\x4b\x96\x8e\x11\x74\x3b\x6f\xc7\xfa\xf1\x27\x5e\x53\x60\xa5\x46\x89\x41\x79\x78\x94\xd7\x70\xfa\x7d\xa3\x64\xa3\x37\x30\x22\x39\xfe\x83\xae\x0b\x0d\x08\x4a\xa1\x2a\xcd\xc6\x34\x62\x52\x4e\x0e\xb1\x0f\xef\xe8\x1b\xa9\x6f\x71\xf2\x75\xf3\x44\x9a\x3f\x8d\xb2\x1d\x58\x74\x9a\x38\x85\x3d\x39\xb0\xad\x8e\x69\x89\x1b\xd2\x04\xdf\xca\x8f\x6c\x23\x9d\xc9\xa0\xac\x27\xf5\x4d\xb4\x23\x8d\x47\x06\xdf\x11\xd6\x07\x36\x9d\xc7\xf7\x04\xda\x1d\x39\xf2\xe8\x2a\xf8\xc2\x83\xd2\x20\xc1\x24\x31\xf5\x6d\x80\x30\x69\xb4\xac\xb7\x70\x81\xc0\x31\xae\x33\x19\xfc\x77\xfc\xa7\x84\x50\x97\xfd\x72\x7a\xd0\xd0\x80\x89\x5b\xba\x23\xe8\x73\xd2\xde\xf8\xcd\xc2\x16\xc3\xee\xd6\x1b\x08\x76\x1b\xb9\xeb\xce\x02\x82\xcf\x50\x2a\xaf\x6c\xe7\xe8\xc0\x58\x63\x79\x58\xc3\xea\x1b\x72\xfe\x6e\x8d\xf8\xd3\x7a\xc0\x55\xdb\x69\x92\x58\x7f\xab\xbd\xc4\x67\xf5\x24\x75\x64\x4f\x91\x88\x63\xaf\x62\x04\x92\xf3\x46\x80\xf2\x05\x6c\xbc\xab\x75\xe2\x32\x36\x26\xc0\x94\x75\x9c\x0e\x0e\x99\xef\x19\x75\x95\x27\x25\x06\x46\xad\x76\x01\x20\xba\x38\x66\x99\xd5\x39\x34\xf9\x56\xb8\xbb\xc7\x39\x5b\xb4\x96\xce\xb2\xdd\x22\x3c\x7b\x50\x1b\x92\xd3\x6a\x95\xf8\xf0\xa0\x2e\xb5\xba\x4d\xdd\xf1\x66\xb9\xb9\x5b\x4a\x59\xe7\x2a\x30\xc6\x3c\xf2\x1e\x60\x85\x75\x19\x23\xd5\x4b\x30\x28\x1e\x52\xa0\x96\x18\xe6\xf0\x23\xba\x0a\x21\x67\x5e\x7f\x98\x9b\x89\x91\x58\x8c\x96\xc2\xb5\x6a\x78\xf5\xd2\x94\x5a\x7b\xae\xb6\xa0\xc1\xbb\xd5\xd9\x5a\xf3\xee\x83\x0f\x58\x09\xc7\x94\xa1\x5a\xb4\xb5\xf8\x9d\xd2\xbe\x2d\xfd\xcd\x8f\xe0\x52\x0f\xda\x2b\x3f\x02\xa1\xac\x01\x55"}, -{{0xe9,0x65,0xb3,0xf2,0x57,0x35,0x66,0x85,0xc9,0x8b,0x42,0xb9,0x64,0xa2,0x53,0xfc,0x49,0x53,0x99,0xcc,0x94,0xb0,0x99,0xc2,0x44,0x5f,0xc8,0x1c,0x75,0x9c,0x68,0xe5,},{0x68,0x9f,0x54,0x10,0xc8,0xe0,0xf4,0xd3,0x7b,0xc0,0x7c,0x85,0xd7,0xcc,0xe6,0xc9,0xb6,0x36,0x01,0xf9,0xbd,0xaf,0xec,0xaa,0x44,0x8a,0x5e,0xed,0x64,0xaf,0xc8,0xc6,},{0x8d,0x2b,0xc4,0xe1,0xcd,0x25,0x6a,0xad,0x8a,0x15,0x1d,0xec,0x01,0x0d,0xc9,0x3a,0x5e,0x5c,0xca,0x58,0x29,0x8d,0xec,0x49,0xcb,0xc9,0xc4,0x71,0x7b,0x5c,0xfb,0x54,0x60,0xd4,0x30,0xbe,0x72,0x6b,0x0f,0x30,0x2c,0xbd,0x92,0x6b,0xee,0xa1,0x9a,0xa3,0xc9,0x3a,0xeb,0x45,0x2a,0x44,0xf6,0x00,0x7a,0xf4,0x9a,0xdf,0x2f,0x05,0xbb,0x04,},"\x6f\x20\xa9\xad\x27\xe3\x0d\xac\x76\xb3\x0d\x4c\x19\xa5\xbd\x6d\xfd\x6d\x04\x92\x13\xf4\xbe\xcd\xd9\x63\xd7\x2b\x8b\x2d\xad\x68\x7b\x00\x38\x08\x20\x1d\x50\xf7\xdd\x6e\x59\x9e\xf5\x8c\xeb\x60\x68\xc5\x45\xed\x99\xb9\xe7\x63\xf9\xb0\xec\x1d\xb5\xfc\xbd\x7d\x49\x0a\x12\x1e\xce\xc6\xbb\xa1\xeb\x5e\xdb\xd6\xde\x85\x36\x47\x07\xc5\x5e\x30\x0c\x8b\x16\xbb\x25\x30\xf7\x08\x98\x13\x66\x89\xc9\x88\x59\x1d\x53\x91\xd9\xcc\x34\x7d\x79\x31\x06\x1a\x9b\x76\x96\xe2\xc9\xf3\x5b\xc0\xd3\x04\xa8\x1c\x2c\xf9\x54\xd9\xc3\xa8\x8a\x22\xe1\xd6\x7b\xbe\x0a\x85\x30\x84\x77\xf6\x29\x18\xc2\x5d\xb5\x04\xe4\x76\x2f\x0e\x3b\x42\x46\x00\x79\x08\xac\x70\x17\x79\x00\x6b\x77\xd7\x25\x10\xed\xc6\x9e\x17\xd0\xf6\x39\x4c\x77\xe5\x55\x18\x75\xa4\x46\xf8\x12\x33\x41\x5d\x0a\x91\xa0\x46\x0b\x51\xc4\x13\xd6\x44\xe8\x50\xf8\x55\x72\x81\xc4\x66\x99\xe5\x3b\x22\xa7\xc7\x3b\x06\x8e\xa3\x86\x52\xcf\xf3\xb0\xa7\xb8\xba\x30\x97\x1e\xab\x18\xfd\xbb\xd8\x73\x9e\xe1\xee\x0c\xd5\xcb\xfb\x7d\x5d\x41\x75\x7b\x63\x31\x27\x1f\xb7\x80\x97\x51\xe2\x03\x51\x3c\x99\x70\xf6\x6d\x91\xbc\x0c\xe0\x62\xf4\xfc\xb2\x8b\xe0\xa6\x99\x86\x7b\x79\x59\x4c\x64\x58\xa0\xd3\x07\xac\xac\x91\xf4\x13\xc4\x61\x58\x77\xdc\x53\xe1\xb0\x18\xda\x5c\xfc\xe1\xb6\x3f\x40\xbe\x1e\x55\x27\x4c\x43\x74\xcd\xfc\x21\x52\x44\x99\xa6\x83\xa2\x31\xad\xef\x77\x9d\x19\x21\x44\x0e\x5d\x3f\xdb\xd5\x03\x3d\xc9\x83\xcf\xc9\x31\xab\xe6\x38\xc3\x5d\x5a\x95\x86\x9e\x9f\xe3\xd9\x3e\xb9\x0b\xd1\x86\x1f\x85\x5c\xe1\xf6\x08\xb7\xbc\xad\x6b\x5e\x1b\xd9\x7e\xdc\x95\xed\x5d\xdc\xbc\xb7\x15\xd9\x19\xf5\xff\x77\xdf\x2d\xa4\x38\xf7\xa3\xa9\x82\x86\xdb\xd5\xb6\xe0\x43\xfc\x73\x72\xf6\x97\x04\xf0\x9d\x86\x55\x30\xf4\xf0\xed\xd3\x30\x0f\x18\x5b\x6d\x73\xd8\x71\x6d\x32\xd3\x2b\x1c\x9a\xc2\xdd\xf4\xf9\x02\xd3\xf2\x16\xd3\x5a\x33\xf3\x68\x09\x5d\xed\x10\xbe\x94\xbb\x53\xd6\xf2\x56\x56\x0f\xac\x2f\x4a\xf0\xed\xf5\xc5\xc7\x02\x14\x37\x77\x12\x6e\x7d\xe3\x2d\x07\x49\x39\x32\x66\x21\x29\xba\x0e\x7f\xc7\xcf\xb3\x6f\xd2\xca\x53\x16\x46\xe8\xcd\x22\x11\x85\x4f\xc5\x10\xaf\x3b\x1e\x8c\xaf\xde\x7a"}, -{{0xbc,0x3b,0x1e,0x0b,0xf8,0xd6,0x9e,0xa5,0xb4,0xcb,0xbf,0x10,0xbb,0x33,0xfc,0x95,0x5a,0xdc,0xbe,0x13,0xfc,0x20,0xaf,0x8a,0x10,0x87,0x2c,0xe9,0xdf,0x39,0xd6,0xbd,},{0xac,0xcd,0x26,0x28,0x15,0x59,0x19,0xbb,0xc7,0xf9,0xd8,0x6f,0x91,0xda,0xfe,0xc3,0x5c,0x71,0x1a,0x78,0xc7,0x9a,0xd3,0x60,0xed,0xdb,0x88,0xfa,0x8a,0x18,0x0b,0x2d,},{0x6e,0xf7,0xf0,0xe9,0x1f,0x2c,0xc6,0x71,0x5f,0x8e,0x5a,0x98,0x57,0x4b,0x44,0x00,0xc2,0x61,0xa6,0x43,0xe0,0x54,0x5f,0xf2,0x67,0x47,0xf8,0xe1,0x73,0x98,0x99,0xd7,0x66,0x40,0xb6,0x45,0x1c,0x43,0xc1,0xd0,0x3a,0x47,0x75,0xb5,0x4f,0xcf,0x9b,0xce,0x18,0xed,0x3f,0xcc,0xad,0x33,0x8b,0x77,0x64,0x02,0x4f,0xdf,0xa2,0xde,0x82,0x01,},"\x4c\x73\xe0\x4a\xbe\x08\x19\xde\x1f\x84\xd7\x05\x41\xeb\x1b\xb6\x1c\x4f\x42\x92\x0e\x1f\x2d\x1d\x9e\x62\x81\xa8\xa2\xe8\xb3\xeb\x45\x53\x7d\x83\x96\x90\x27\xf9\x9e\xf0\xea\x27\xca\x08\x5b\x13\xf9\xdb\x48\x0f\x00\xc0\x2f\x3f\xd7\x42\x9d\xd5\x67\x70\x89\x53\xbb\xf3\xb9\xe8\xe2\xc6\xac\x4d\x32\x1f\xf8\xf9\xe4\xa3\x15\x47\x23\x08\x5a\x54\xe9\xc9\x57\x3c\xc7\x35\x0c\x09\xf8\x97\x3f\x94\x8b\x08\x73\x03\x73\x59\x7a\x5f\xd0\x34\x98\x21\xae\x0a\x3c\xd6\xc8\x49\x92\xb1\x89\x12\x8f\x34\x90\x98\x7e\x1e\x9a\xd4\xf6\x57\x4c\xa5\x38\xfd\xfd\x83\x28\x4c\x1e\xb0\x95\x3f\x24\xc0\x8f\x74\x93\x2d\x43\x64\xdb\xbe\xf9\x22\x54\x24\x40\xda\xe8\x04\x24\xa9\x2e\xae\xf2\x7c\x18\x89\xbd\x08\xc4\x4f\x9d\xf0\x3a\x3a\xf3\x0d\xff\xb4\x8f\xae\x44\x5e\x62\x5f\x4d\x92\x65\xcf\x38\x7a\x1d\xa3\x5f\xe4\xc2\x31\x50\x45\x35\xdb\x72\xea\x81\xa1\x86\x80\x5f\x85\x6e\xbe\x6a\x6a\x65\x24\x14\x32\x53\x0f\xe6\xc9\x60\xc5\xf9\xbe\x6c\x22\x95\x70\x60\x30\x4e\x9d\xd8\xef\xbc\x1e\x48\x2e\x7d\xdb\xd8\xaf\x03\xbf\x23\x82\x89\x9c\x98\x6d\x91\x66\x11\xe4\xf2\x7a\xe5\x2f\x81\x7e\xf0\x1b\x6a\x14\x1f\xe4\xf6\x85\xd9\x4d\xc8\xcd\x52\x83\x00\x43\x93\x45\x87\x70\x4c\x1e\x64\x2e\x8f\xe5\x6b\xe6\xd6\xb8\x5b\xf4\xa6\xfe\xb2\xb6\x85\x8f\x1f\x00\x7f\x99\xd3\x9e\xa0\x4c\x9f\xe5\xfa\x7e\xf1\xb9\x1f\x49\x5e\xd0\xe7\xfa\x42\x13\xdd\x68\xce\xa4\x2b\x67\x29\xf9\x50\x31\x90\x7e\x27\xc4\x40\x98\x09\x43\x86\xfa\xbf\xb0\x4a\xb9\xb4\xde\x3d\x68\x61\xde\x46\x23\x12\xc5\x9b\x27\xc7\x6f\x7b\x6a\x4f\xc7\x1e\xa0\xd5\xda\xf6\xb7\x32\x05\x21\xa6\x7e\x5c\xb3\x75\x04\x97\x6a\xd7\x3d\xae\x2d\x64\x9f\xeb\x75\xe2\xea\xdd\x34\x01\xa7\xf2\xf3\x6e\x16\xdf\xbf\xbd\xb2\xaf\x57\x16\xcb\xa1\xbc\xe2\x0c\xd4\x7c\xe1\xc1\xd7\xbe\x00\x69\x70\x01\xfb\xbe\xb4\x91\x5a\xa6\xe5\x39\x3b\x5a\xb2\x0e\x0f\x31\xf5\x11\x91\x49\xa2\xcb\x4c\x4d\x45\x2c\x81\x56\x11\x3a\xc7\x82\x4f\x84\xf0\x9a\xeb\x81\x20\x2e\x8d\xd3\xda\xc0\xaa\x89\x39\x9b\x5a\x38\xb1\xe2\x18\x30\x19\x60\xa3\x7d\x52\x63\x2e\xea\xef\xe3\x68\x74\x55\x46\x42\x88\xeb\x17\xd9\xe1\x9a\x3a\x72\xed\x9d\xe3\x2c\x17\xbe\x79\xa3\xb9"}, -{{0x10,0x71,0x8f,0xa6,0xe2,0xd7,0xf6,0xed,0x38,0xfd,0x66,0xcb,0x6d,0xbf,0xa0,0x87,0xe8,0xf1,0xe8,0xa8,0xa2,0x4f,0xab,0x58,0xd7,0x9d,0x79,0x54,0xb8,0x72,0x0c,0x3e,},{0x87,0x0d,0x4f,0x66,0x6d,0x06,0xfd,0xa9,0xf9,0x51,0x1b,0x58,0x60,0x2e,0xec,0x05,0x0d,0x75,0x4e,0xa6,0xd8,0xe7,0x9c,0xdd,0x19,0xf6,0x01,0xc4,0x77,0xdf,0x1a,0xa0,},{0xe1,0x65,0x91,0x86,0xf1,0xf7,0x6f,0xe4,0x3a,0xc8,0xa1,0x17,0x03,0x36,0x0f,0xbe,0xff,0x53,0xb5,0xe5,0x7b,0x59,0x74,0xaa,0xa0,0x8e,0x25,0x75,0x57,0x9c,0x27,0x08,0x4c,0xf6,0x80,0x2e,0x7c,0x20,0x63,0x47,0x31,0x44,0x75,0xb6,0x03,0x19,0x74,0x94,0xe7,0xd6,0x1f,0xe4,0xb1,0xee,0x7b,0x78,0xe1,0x8d,0x94,0x46,0x93,0x52,0xdf,0x0c,},"\x41\x25\x9b\x6e\xef\x13\xd6\xff\xe3\x3c\xdd\xe7\x99\xb9\x95\xc4\x0b\xe7\x82\xcf\x97\x84\x40\xb6\x6b\xe5\x1c\x44\x05\x82\xab\xd4\x2f\x52\x66\x96\xbb\x3c\xb9\x22\x65\xb1\xed\x0e\x4b\xba\x76\x4c\xae\x28\x39\x83\x0a\x25\x26\x35\xdc\x80\xce\x5f\x73\xd5\x21\xb3\xd6\xff\x03\xac\x30\xe1\x98\xad\x20\x56\x7e\x75\xa3\x4f\xa8\x25\xeb\xf9\x84\x15\x08\xda\x84\xcd\x67\x42\x36\xca\x7b\x43\xde\x35\x64\xc9\x4a\xb0\x79\x40\x8f\xd9\x41\x37\xce\x3f\x90\xa5\xdd\x5d\x3a\xc3\x9a\x05\xec\x86\x71\x5a\x8f\x02\x5e\x45\x39\xa7\x64\x0a\xb8\x88\x36\xf4\xef\xba\xbd\x5e\x16\x52\xc4\x9e\xa2\x16\x13\xac\xfe\x34\x3a\x88\x0e\xe5\xa4\x2f\x2f\x91\x34\xef\x4e\x37\x16\xb1\x6d\x13\x4a\x9c\x4c\x71\xc3\x9b\x3c\x1a\x85\x7d\x3c\x89\x43\x97\x83\xee\xf1\xed\xd7\x1b\xf4\x49\x2d\x05\xfd\x18\x67\x3a\x52\x42\xff\x41\x87\xb9\xde\x47\xad\x49\x68\xda\x49\xdb\xa5\xa6\x09\x2e\x95\xea\x27\xdd\xfc\x74\x48\xdc\xf5\x97\x2d\x9d\x22\x8d\x63\xe5\x29\x1b\xa6\xe6\xfb\xd0\x7e\x32\x41\xf9\x36\x6c\xa4\x97\x6b\xb0\x4b\x22\xd0\x1f\x0d\xba\xe7\x94\xfa\x9c\x1d\x90\x29\xf8\x8a\x83\x60\x2b\x0e\x0e\xc5\x5e\x22\xc3\x7b\x20\x11\x25\xca\xdb\x53\x41\xef\x73\xf6\xda\x1a\xbb\xe2\xb1\xc4\x75\xf0\x75\x03\x45\xb1\xbe\x42\x59\xd8\xc2\x85\x31\xff\xe7\x78\x86\x67\xc4\x10\xda\xc3\x39\x91\x8c\x86\x9b\x00\xab\x80\xf2\x0b\xf7\x99\x0d\x36\x6f\x9b\x3d\x5e\x8e\xb2\xf4\x8d\x7e\xd0\xe6\x4b\x85\xdc\x9f\xe3\xbb\x99\x8b\x1e\xec\xd1\x23\x1e\x90\x2d\x2d\x15\x2e\x09\xda\x2d\x25\x92\xbd\xb3\x2c\x8c\xd2\xe2\xc4\x89\x49\x6b\x29\x80\xc0\x3d\xbb\x09\xec\x7f\x8a\x4e\xa2\xc7\x02\x0f\x2a\x0f\xaa\x65\x7c\xd6\xce\xd4\x8d\x6d\xa2\x78\x64\xcf\x5e\x97\xee\xa9\xb3\xc2\xf0\xf3\x4a\xbf\x8d\x87\xbd\x2a\xde\xb6\x0c\x72\x72\xfc\x43\x06\xd9\x55\xbd\xc8\x02\x3d\x7d\x3d\xc2\xf3\xda\xfe\x9e\xbe\x8a\x8d\x13\x89\x65\xa7\xf6\xce\x93\x51\x7c\xd2\x09\x96\x63\xf6\x7c\x34\x55\x21\x76\xdd\xb5\x95\xac\x6e\xa5\x60\x9f\xeb\xcf\x24\xc7\xd6\x9d\x41\x27\x09\xe5\x78\x67\x0a\x21\xac\x8a\xfc\xcb\x8b\xf2\xb1\x8f\xf3\xaf\x7d\xe2\x1d\xc7\x1d\x50\xd6\x0d\x37\xb6\xed\x72\x9d\xb0\x4b\xef\xf7\xd3\x4b\x29\x20\xd8\x75\x51\xce\x15"}, -{{0xc1,0xd4,0x72,0x4c,0x6c,0xb1,0xbc,0x67,0x23,0xb2,0xb4,0x30,0x34,0x27,0x8b,0x3c,0x5b,0x48,0xfe,0xd7,0xf8,0xa3,0xcc,0x23,0x18,0x03,0x3e,0x75,0x52,0x04,0x73,0x51,},{0xc2,0x7e,0x39,0x2e,0x7c,0x36,0x64,0xb9,0x06,0x1e,0xa7,0x6d,0x25,0x75,0xdd,0x7c,0x41,0xea,0xf1,0xda,0x3a,0x65,0xf3,0xa9,0x86,0xe0,0xa5,0x7f,0x6c,0x40,0xc1,0x7e,},{0xd3,0x7a,0x6e,0xc8,0x2e,0xd4,0x5c,0xa9,0xb4,0x85,0x5d,0xe9,0xcb,0x94,0x25,0x64,0xe8,0x83,0xff,0x70,0xa7,0x9b,0x8e,0x71,0x2d,0x5f,0x60,0x4e,0xc8,0x97,0x4d,0xe5,0x36,0x3a,0xc8,0x49,0xcb,0xab,0x28,0xe7,0xae,0xef,0xf2,0x8e,0xd3,0xf2,0xd1,0x4b,0x60,0x8b,0x31,0x46,0xc2,0xef,0xe0,0x73,0x5a,0xd8,0x15,0xc7,0xd7,0x5a,0x1a,0x01,},"\xde\xee\x99\xd7\xa7\x7d\x43\x00\xc1\x7a\xec\x1a\xb3\x23\xc5\x71\xc6\xe9\xe7\x3a\x43\x49\x1a\x3c\x78\x88\xb7\x6f\xc0\x3e\xc4\x3d\x07\xaf\x42\xa0\x5a\x2a\xa3\x22\xd0\x0c\x85\x60\xac\xef\x31\x41\x06\xb1\x0b\x9b\xd1\x26\x54\x35\x7f\xfa\x26\xf2\x39\x00\x50\xda\x63\xd6\x68\xc9\xe2\xdf\x54\x8f\x87\x63\x9e\x09\x6a\x35\x85\x3f\x82\xe7\x61\xfd\x71\x1d\x2a\x26\x54\x38\xf5\xd4\xdb\x5e\x32\x77\x57\x08\x15\x0d\xa6\xcb\x68\x6a\x2b\x4c\xa2\x11\xd7\xf0\x0d\xc0\xab\xcb\x2c\xa1\x50\xe7\x91\x11\x6a\x10\xa5\xef\xcf\xf3\x51\x4d\xab\x8e\xd8\x0a\x70\x92\xc3\xa0\x15\x15\x2c\xb2\x5d\x9f\x86\xec\x0d\x1c\xa6\x7d\xda\xb4\x4d\x64\xee\xb1\xf9\x31\xbf\xab\x2a\xb1\x88\x95\x6c\x74\x3d\xb4\x81\x48\x08\xc5\xcd\xe1\xb0\x74\x5b\x3e\xdd\x34\x0e\xb0\x3f\xfc\xc8\x0a\x78\xf3\xdb\x31\x0f\x4f\x5c\x20\x00\x9f\xc0\x27\x9c\x2c\x1b\xcb\x3c\xed\xf9\x90\xbd\x0e\x20\xc6\xf9\xfb\x75\x15\xad\x6e\x93\x3b\x07\xe9\x9d\xa6\xac\x32\xb9\x71\x41\x18\x7e\xf6\x3b\xdb\x10\x62\xe3\x72\x20\xa4\xdc\xd4\x19\xd6\x24\x4c\xdc\xc3\x4e\xa4\x1d\x0b\xcb\xc3\x13\x8b\x1d\x54\xae\xfc\x01\x90\xe3\x0b\x18\x7d\xb0\x73\xaa\x7d\x6c\xfe\x04\xbd\x3f\xd2\xac\x00\x31\x3e\x3d\xdd\x64\xa1\x81\x93\x5c\xa4\xb8\xb2\xa8\x5d\x36\xbc\x27\xd9\x7b\x76\x26\x76\x7b\x93\xee\x38\xde\xf8\xb6\xb2\xc8\xda\x9b\x00\x26\x36\x14\x34\x2f\xaa\x9d\x3e\x73\x8d\x27\x13\xc4\x5f\xfb\xee\xf8\xc8\x4b\xcd\xbc\x8d\xa4\x30\x9c\x84\x45\x53\x0f\x5c\x61\x7d\xc8\x66\x25\x1f\x54\x89\x50\xa1\x4f\x07\x5a\xa3\x11\x7f\x96\xe4\x1f\x89\x9d\xbe\x73\x40\xb1\xd9\x0a\x13\x52\xd3\xb8\xfb\x41\xb7\x9f\x16\xa8\x2b\xc2\xe4\xa1\x93\xb8\xa7\x23\x24\x00\x99\x6b\x73\xb1\xfc\x00\xb2\xec\x1c\x66\x75\x77\xf8\x28\x24\xd3\x9f\xb7\xf6\xe7\x69\x2d\xcd\x97\xb1\xd8\xce\x94\x08\x3c\xa1\x97\xe9\xa5\xd4\x0f\xad\xff\x0b\x9a\xc5\x7e\x9d\xe7\x61\xc1\x56\xe6\xd3\x1d\x52\xc3\x32\xd5\x13\xe9\xf5\x86\x97\xdc\xbd\xd8\x0a\x5e\x42\xc5\x51\x70\x2c\x3d\xe7\xbe\xcc\xc3\xdb\x84\x5b\x1a\x04\xc8\xcb\xd4\x16\x95\xea\x74\x28\xab\xba\x89\xe0\xdc\xe3\xe3\xd9\xe7\x02\x30\xae\x91\x47\xc2\xb8\x85\x59\xdc\x69\x5d\x68\x09\xa5\x1c\xcb\xc1\xdd\x9e\x08\x9c\x58\x5f"}, -{{0x37,0xc0,0x70,0xd4,0xa5,0x3b,0x13,0xbe,0x76,0x06,0x35,0x11,0x0d,0x1b,0xd4,0xf0,0x19,0x20,0x22,0x5a,0xfa,0xbe,0xc5,0x76,0xfa,0xae,0xc9,0x10,0xf2,0x92,0x6d,0x1a,},{0x0a,0xa8,0x5f,0x2a,0xb1,0xdf,0xf8,0x95,0xd1,0xfa,0xd0,0xc1,0x19,0xf2,0xbf,0x57,0x12,0x6a,0xab,0x60,0x1c,0x52,0x8d,0x37,0x69,0x8e,0x97,0x70,0x2d,0x35,0xf5,0x25,},{0x9d,0xa6,0x0c,0xc4,0xa6,0x4d,0x07,0xde,0xe1,0x34,0x6b,0xd3,0xd3,0x01,0x09,0x95,0xce,0x27,0x38,0x20,0x8a,0xb3,0x5b,0x34,0xc2,0xa8,0xfd,0x17,0x87,0xae,0x3a,0x1e,0x20,0x7f,0xe7,0x84,0x52,0x51,0x54,0xfa,0xe4,0xf5,0x79,0x4c,0xd8,0x50,0x30,0x45,0xfe,0xa8,0x5c,0xf7,0x7f,0xd9,0x2f,0x6a,0x70,0xcd,0x0c,0x5a,0x52,0xc0,0x81,0x0e,},"\x10\xc6\x46\x44\x7f\x81\xad\x94\xd0\x15\xd8\x6d\x0d\x98\xb2\x45\x2d\xca\x60\xa4\x7a\xb3\x52\x64\x03\x5e\x33\xa0\x94\x2b\x95\x4e\x3e\x23\xb9\x1d\x81\x23\xb8\x59\x3c\x6a\xf7\xc8\xd3\xec\xd2\x90\xe0\xe5\xee\x36\xfd\x4e\x53\xb7\xbe\x63\x3a\x6c\xf0\x27\xa5\xac\x3f\x0f\x67\x9e\xb1\xbd\xd2\x10\xa3\x8e\xa6\xe4\x8b\x05\x58\xe3\x03\x01\x0a\xf4\x74\xe7\xf6\xdf\x2a\x4e\x45\x76\x99\xfc\x38\xe3\x69\x38\xb0\x5f\xfc\xaa\x1b\x69\x4e\x32\xf3\xd1\xb2\xcc\x5d\x00\xcf\x25\x6f\x12\x18\x4c\x87\x3e\x51\x90\x89\xec\x1d\xf1\x5b\x0d\xc7\x6e\x7b\xfe\x90\x78\x0d\xf5\x81\x36\xfe\x59\x7f\xce\x89\x4c\xa5\x63\xe0\x8e\xfa\x0f\x2d\x4d\x20\x8b\xed\xe9\xa8\x74\x88\x28\x73\xd2\x51\xba\xf0\x19\xfe\x46\xd1\xd6\x50\x4b\x3b\xcd\x24\x3b\x79\x53\x51\xf3\x4d\x2e\x76\x06\xaa\x97\x55\x28\xee\x50\xd5\x9e\xfb\x6e\xe6\x99\x2a\x89\xb2\x42\x69\x56\xc2\xca\x42\x47\xe0\xdf\x01\x29\x85\x29\x83\xe9\x76\x7a\x8e\xed\x1b\xc7\x33\x5f\xfc\xa8\xd0\x28\x9f\x04\x80\x7f\x67\xca\x7d\xa9\x71\xf5\x8d\xb8\xb9\xbc\x9f\xdb\xe4\xf8\x3c\xfe\x9a\x00\xf1\xca\x58\x47\x98\xbc\x71\xd8\x51\xff\x7c\xd6\xc5\x1b\x89\x90\xaa\xba\x4d\x38\xb4\x16\xb9\x22\x40\xdf\xb7\x0e\xe3\xc1\x2b\x5e\x73\x10\x57\x76\x2e\xf9\x08\x23\xfb\xf6\x83\xca\x06\xd0\x5c\x20\xd3\xae\x2b\x97\xa8\x3e\xbe\x70\xae\x17\xaf\xff\x9d\x16\x60\x9d\x54\x6d\x8d\x3c\x74\xbc\x28\x18\x84\x89\x4f\x3d\x49\xe0\x83\xf1\x0a\xe7\xc1\x1c\x1d\xca\x0e\xff\xef\xcf\xa6\xe0\xf1\x53\x50\x81\xfa\xc3\xa2\x81\x9f\xd2\xe3\x26\x55\x27\x18\x2a\xe9\xd3\x91\xb2\x32\xbb\x75\x42\xe6\x84\x55\xcd\x26\x77\x60\xdb\x65\x2d\x19\xe2\x2f\xb2\xed\x11\xcd\x13\x05\xba\x8d\x98\xc1\xeb\xf2\xd1\x96\x9b\x24\xd6\x4f\x3e\x31\x9a\xf7\x4e\x09\x20\x06\xd2\xa3\xff\x74\x48\x72\xa2\x0e\xbf\x18\xd1\x77\x48\xab\x71\x10\x80\x50\x96\xea\x13\x6b\xce\x2f\x96\x8b\x20\x5e\x65\x0b\x80\x3c\x53\x1d\x06\x77\x5a\xe5\xce\xea\x28\xbb\x92\xe9\xa0\xed\xec\x89\x51\xce\x20\x09\xa8\x8e\xe1\xb6\x4d\x9b\x9e\x89\xf6\x90\x51\x20\x33\x84\x21\x0a\x10\x2a\x44\xd2\xd6\x70\x31\x73\xb6\x85\x07\xdc\xea\xdd\x3b\xf6\x51\x0d\xf2\xa5\xce\xfd\x9c\x80\xe4\xf3\x85\xb2\xf9\xe6\x21\x58\x13\xed\x32"}, -{{0x11,0x26,0x49,0x6a,0x58,0x2c,0xe5,0x8d,0x3d,0x61,0x8d,0xd8,0xa3,0x93,0x35,0x47,0xaa,0x7a,0x8a,0x30,0xfb,0x54,0x06,0x3b,0x8d,0xfd,0xd3,0x16,0x71,0xc6,0xc7,0x3d,},{0xe1,0x02,0x29,0xc6,0x23,0xfa,0x8a,0xd8,0x98,0x2c,0x3e,0x4c,0x36,0xff,0x52,0xdf,0x0f,0x21,0x9b,0x57,0x91,0x5b,0x6e,0x98,0x0e,0x5f,0xe7,0x2e,0xa0,0x96,0x2e,0x22,},{0xb3,0x0e,0xb5,0x6c,0xa9,0xb1,0x20,0xbf,0x84,0x9a,0x3a,0x9d,0x56,0xaf,0x03,0x3d,0xe8,0xa5,0x90,0xc9,0xe1,0x24,0x0c,0x1e,0x36,0xdb,0xc6,0xcf,0x0a,0x71,0xb7,0x8a,0x11,0xec,0x14,0x3f,0xb9,0x95,0x9a,0x8f,0x25,0xb5,0x77,0x11,0xd6,0xa9,0x0a,0x67,0xe0,0x1b,0xe3,0xa4,0xda,0x2b,0x69,0x39,0x48,0x69,0xbb,0x8d,0x64,0xb8,0x7e,0x0f,},"\x6a\x4b\x52\xd7\x30\xdd\xab\x82\x9b\x2a\x17\x95\x90\xcb\xd4\xc3\x72\x49\x8e\x9f\x43\x99\x77\xc0\xa1\x0d\xc1\x3c\x0a\xe1\x73\x6e\xaa\xff\x06\x33\x71\x43\x4f\xd0\xda\x80\x36\x0e\xc5\x89\x06\x07\xd2\xfa\xe1\xc9\xa2\xe1\xab\x0b\x7f\x3d\x66\x7f\x5b\x1b\x9c\x41\x8f\x18\xb1\x0c\x9e\x6f\xd6\x69\xd3\xeb\xec\x16\x8e\xfe\xf4\x41\x63\xe5\x77\xa2\xeb\xd0\xf2\xcb\x76\x8f\x80\xc2\x31\x88\xe8\x60\x69\xe4\xd1\x0f\x41\x03\x06\xce\xdd\x7a\x34\x1a\x61\xe0\xf4\xf3\xbc\x25\x04\x1b\xc2\xf9\x22\xed\x07\x3e\x1e\x2f\x1b\x70\x9c\x57\x9d\x10\x63\x0f\x33\x07\x17\x54\xd7\x07\x89\x4a\x1c\x62\x19\x0d\xe1\x88\x82\xc5\x64\xdc\x4c\x01\xdc\x54\x5d\xd8\x96\x64\x04\xed\x78\xfa\x32\x67\xa9\x46\x9f\x63\xb6\x12\x0a\xbb\x65\xf9\xb3\xba\x3e\xee\x28\xd7\x9c\x2e\xb4\xe7\x02\x0c\xc6\x98\x7d\xfc\x5c\x29\x67\x2f\x8c\x0f\xa3\xe6\x90\xd5\x84\xfe\x00\x0c\x64\xf3\x52\x61\x01\x79\x62\x1b\xfd\x5f\xf3\xeb\x30\xd1\x8f\x1a\x02\x50\x41\x6d\xb9\x3b\x1c\x1e\x93\xcf\x8a\x36\x46\x51\x75\x60\xd1\xcc\x8f\xff\x82\x2b\x51\xef\x27\xb2\x00\xe9\x87\xb5\x92\x39\x07\x53\x45\x3e\xf1\x38\xbd\x3d\x29\xdb\x7c\xb1\xb5\xf4\x5e\x47\x95\xb8\x9c\x53\xf4\x97\x04\x19\x27\x52\x23\x7c\x6a\xb2\x74\x84\x9f\x95\x94\xee\x97\x77\xf6\xef\xe7\x04\x83\x12\x9d\x06\x7f\x97\x19\x9d\x9a\xe3\x60\x90\x70\x38\x64\xf7\xca\x47\x50\xa6\xf3\xb6\xff\x83\x82\x4c\x91\x04\x84\x39\x4d\x1e\x2e\xce\xba\x18\x44\x6f\xe4\xe9\x94\xce\x07\x43\x3a\x74\x0d\xdd\x05\xf0\xe3\x96\xd4\x82\x89\x4e\x6f\x14\xac\xf7\xb9\x7b\xae\x6c\x7e\xb8\x87\x03\x03\x9f\xa7\x85\xd6\x0a\x3a\xf7\x8b\x13\x24\x3a\x4f\x88\xdd\xe1\xd9\x98\x61\x7f\x2e\x3f\xa7\xea\xfc\x2f\x43\x5d\xd4\xac\x1e\xa9\xc2\x38\x40\x7a\xa0\x9b\x4e\xea\x8e\xd4\x34\x92\x7b\x40\x66\x74\xac\x27\x04\x58\xcf\xb3\xbf\x29\xc3\x47\xf9\x45\x59\x61\x31\x79\xb9\x50\x21\x92\x32\x1b\x88\xe9\xaf\x0a\x90\xe9\xa4\xab\x9e\xdd\xaa\xe3\x82\xe3\x73\x4d\x14\x15\xeb\xe3\x24\x99\xc3\x4e\x6f\xde\xaf\x15\xb0\xd9\x78\x79\x85\xe0\x8d\xfe\x49\x54\x60\xc5\x4f\x67\x43\xd8\x1f\xf1\x68\x81\xe5\xe3\x0c\x51\xf4\xb0\x92\x37\x37\x83\xf1\x24\x23\xc3\xe1\xae\x85\x91\x13\x0a\x26\x99\x80\xca\xa1\xcb\x5c"}, -{{0x9c,0x16,0x7a,0xff,0x3b,0x1b,0x78,0x8f,0x13,0x3d,0x42,0x2d,0xe8,0xca,0x9a,0x64,0x31,0x64,0x09,0xf9,0xe3,0x5b,0xfe,0x22,0x03,0x2e,0xc4,0x17,0xae,0x9a,0xbc,0x6d,},{0xef,0xb5,0x34,0xf0,0xd4,0x7c,0x06,0x8e,0x77,0xb2,0x8a,0x90,0x6d,0x95,0xad,0x8d,0x21,0x3a,0x4d,0x4f,0xc1,0xc7,0x05,0x42,0xf0,0x1e,0x59,0x6d,0x57,0xb5,0xf0,0x19,},{0xc9,0xae,0x67,0xfd,0x64,0x15,0xdc,0xba,0xb2,0x92,0xfa,0xb3,0x94,0xca,0x6c,0x3b,0x7d,0x90,0xca,0x24,0x4d,0xc6,0xa7,0x76,0x4e,0x74,0xfd,0x20,0x2b,0xf4,0xb2,0x90,0x5b,0xd2,0x03,0x0e,0x6b,0xeb,0x91,0x4c,0x3c,0x23,0x8d,0xb3,0x71,0xb1,0xcb,0xa6,0xd9,0x26,0x1a,0xa3,0x92,0xec,0x87,0x1a,0x4b,0x8b,0x12,0xfe,0x9c,0x1c,0x97,0x0e,},"\x68\xac\x0f\xc2\xb6\x07\xba\x38\xe3\x77\xfa\xe8\x45\xc8\x08\xc8\xf9\xfa\x61\x4e\xb1\xf3\x11\x58\xa9\x62\x0a\x93\x7d\x3e\x30\x1e\x85\xac\xaa\x69\x14\x4b\xc3\x49\xa3\x9d\xfb\x58\x20\x41\xc4\xa1\x97\xae\x99\xb4\xd4\xd5\x9b\x7a\x2c\xa3\xd1\x62\x28\xb5\x59\x1c\xbf\x57\xc1\x8a\x78\x1e\xfd\x19\x19\x3c\x47\xb1\x6c\x60\x23\xa3\xa8\xba\x3d\x66\x8f\x05\xa3\x7f\x1e\x83\xb0\xd7\xfe\xbd\xd1\x0f\x63\xe4\x8e\xf7\xa2\x0e\x01\x5b\x1c\x67\x25\xd4\xc3\x00\xa9\x86\xc6\x0e\x3a\x11\x54\x69\xc8\xe5\x2b\xa0\x5b\x51\xc0\x5d\x0a\xf4\x0d\x89\xfd\x9e\xd7\x6f\x36\x95\x0a\xee\x3c\x78\x19\x89\x8a\x90\x3c\xfe\x03\x61\xa9\x1c\x69\x10\x0b\x49\x51\x41\xe8\x6e\xe7\x9d\x63\xd1\x74\x03\xfb\x1a\x16\x29\xef\x63\xcb\x7e\x9d\x27\x20\xcb\xff\xf0\x00\x2b\x19\x0b\xcd\xc2\x67\x94\x12\x4d\xd3\x8d\x42\xbc\xaa\x71\x75\x40\x5e\xb0\xbb\xcf\x8e\x37\xd6\x5d\x05\xa3\x71\x95\xb4\x79\x37\x1f\xa2\xbb\xbb\x16\x7d\x91\xce\xe8\x82\x35\xdd\x72\xea\x88\xfc\x73\xce\x3c\xe4\x3d\x33\xb7\x15\xf2\x5f\x19\x2e\xc2\x15\xda\xc1\x24\x89\x9c\x5e\x75\x86\xe8\x63\x40\xd8\xcb\xe5\x37\x35\xde\xfb\xe0\x2e\x4c\xc9\xfd\xe6\x9f\xb9\x79\x4d\x1d\xb7\x2b\x98\xc0\xf1\x97\x66\xee\x51\x38\xbb\xfa\x78\x90\x9a\xa2\x99\xb4\x91\x3c\x49\x9d\xea\xf5\x4b\x48\x41\xd5\x04\x48\x29\x98\x49\x36\x70\x0d\xcf\x92\xf3\x65\x42\xb2\xfc\x7e\x86\x44\x1b\x99\x25\xf5\xd0\xb7\x8c\x17\xa8\x5c\xfc\xfc\xb2\x0b\x0f\xd7\x51\x34\x9c\x27\x46\x3a\xbd\xe4\xd2\x7d\xf7\x42\x65\x28\x87\x13\xf9\x6d\xea\x01\x3b\x94\x55\x21\x80\x8b\x49\x96\xb1\xb2\xdc\x03\x38\xb6\xd2\x36\xef\xd6\xd2\xb2\x7d\xaf\xda\x46\xec\x5f\xa3\x2b\x96\x5e\x8b\xb5\xe8\xbb\x61\xbd\x96\x6e\xde\xb7\x74\x68\x1e\x0e\xa8\xc1\x7b\x8c\x99\xfa\x7d\x66\x0f\x0f\x66\xc9\xbc\x6d\x95\xcb\xd7\xdc\x09\x47\x24\x09\x8e\xb0\x51\x91\xb5\x3a\x3d\xf6\x56\x6b\x9c\x90\xe0\xd7\xdf\xf2\x94\x38\x48\xb6\x1a\x20\xd4\x8c\x22\xb6\xd3\xc9\x58\xe2\x93\xd7\x09\xc8\xf4\x81\x10\x23\x0f\xf5\x19\x18\x56\x28\x77\xda\xf6\xd9\x20\xc8\x5a\x82\xe0\x7c\x45\x1f\xe7\xae\x97\x59\xc0\xa7\x7e\x97\xbb\x29\x8b\x5d\x05\x92\xa4\x1d\x08\xf6\x7a\x4e\xd5\xa1\xbb\x41\xe9\x37\xb6\xa6\x8a\xeb\x38\xfd\x5b\xe9"}, -{{0xe9,0x94,0x88,0x05,0xeb,0x34,0x1b,0x28,0x67,0x47,0x9c,0x66,0x8f,0xd3,0x53,0x2c,0x30,0x99,0x41,0xc0,0xad,0x4c,0xb2,0xe5,0x42,0x31,0x75,0x6e,0x6a,0x1b,0xde,0xcb,},{0x54,0x47,0xa8,0xe3,0x4d,0x6a,0x64,0x00,0x02,0xd8,0xd6,0x0b,0xcf,0x1d,0xdc,0x71,0x1e,0x4c,0x46,0x5c,0x94,0xc3,0x4b,0x50,0xbd,0xef,0x35,0x89,0x60,0xff,0x81,0xf1,},{0xd3,0xdc,0x62,0xd6,0xce,0x9c,0x76,0x6f,0x2a,0xba,0xf9,0xa7,0xfb,0xe0,0x9d,0x6b,0xdb,0x07,0xa4,0x74,0x7b,0x56,0x08,0x0d,0xb0,0x9b,0xeb,0x4a,0x4e,0x80,0x4a,0x70,0xd7,0xdd,0xf4,0x11,0x94,0x75,0xc7,0xbe,0x83,0x4f,0x31,0x95,0x6f,0x4a,0x71,0xda,0xd0,0x29,0xcd,0xf2,0x36,0x3d,0xd0,0x36,0x5c,0xe2,0x2d,0xc2,0x7f,0x07,0x80,0x03,},"\x91\xcf\xfd\x7e\xb1\xcf\x6b\xd4\x75\x6b\xce\x6a\x30\xaf\x9d\xfb\xa2\x6d\xdd\x1c\xce\x03\x94\xc1\x94\xa3\xe3\x9c\xc3\xd1\xcb\xc2\x21\xb7\xeb\x70\xbe\xa1\x8d\x29\xc2\x67\x45\x71\x76\xa3\xc9\xe5\x3c\x18\xe4\x7d\x10\xa6\x7c\x46\x45\x05\x19\x77\x02\xe6\xb2\x47\x0d\x38\x86\x9d\xb5\x17\x4b\x15\x8f\x99\x92\xe4\x43\x5d\x02\x24\x6f\x54\x02\x58\xde\xdd\x3c\xe3\x3d\xf5\x82\x55\x5a\x68\x1f\xb7\x6e\xca\xcc\xb1\xc2\x98\x9b\x17\x7e\x3b\x7e\x45\x4a\xaa\x52\x9d\xe5\x9b\xf5\xa0\x31\x23\xd5\x71\xdf\x2e\x7f\x7c\xb8\x30\x80\x5c\x58\xb7\x4a\x65\x3b\xac\x0e\x5a\x88\x8e\x08\xdc\x22\x36\xd6\xcd\x49\x6a\xa0\x6d\x0d\x67\xcf\x3b\x33\x5e\x21\x8c\x49\xde\xda\xd8\x2f\xc1\xbe\x9e\xf2\x0c\xac\x61\x90\x5c\x30\xeb\x13\x2d\x73\x9b\x16\xca\x8a\x8c\x90\x66\x19\xc0\xe0\xd8\xb3\x39\x85\x32\x7e\x36\xf3\xd4\xb8\xfd\xa3\x87\xc1\x86\xcc\x50\x44\x31\x04\xdb\x76\x1f\x7f\xf9\x30\x12\x70\x20\x4a\x71\x3e\x58\x90\x21\x01\xfa\xd0\x00\xce\x93\x16\x47\xc5\x77\xfd\xec\x14\x8d\xca\x95\xcd\xc0\x89\x18\xeb\xed\x03\x7c\x60\x33\x2f\xad\xf0\x88\xf0\x36\x08\x3e\xbc\x92\xe1\x73\xb7\xdd\xcc\x30\xc4\x93\xf2\x7e\x69\xcd\x17\xa2\x0d\x30\xb7\x8f\x83\xa7\x2e\x4f\x5a\x74\x7d\x86\xd9\x6c\x5e\x1b\xb7\xa4\x38\x16\x62\x04\x01\x3e\x21\x64\xd6\xaa\xbc\x0d\x56\x2f\x54\x01\x5c\x36\x5c\x80\x44\x56\x07\x14\x5e\x56\x92\xee\x34\xf6\x35\x30\x77\xfa\xb7\x45\x2d\x88\xce\x3e\xb0\x1d\x2b\x37\x97\xdc\x91\xb3\x41\xa3\xa7\x26\x30\x15\x16\xba\xae\x18\xe8\x51\xf7\x4d\xfb\xdf\x08\x66\xbb\x23\x76\x86\x7d\xe5\x52\x31\xe3\x62\xc4\x72\xc5\x21\x16\x54\x4c\xd4\xf8\x1e\x93\x57\x1c\x4e\xc8\x20\xe7\xe6\x53\xf4\xe2\x1b\xe0\xa9\x42\x57\x6c\x9d\xe9\x1e\x7d\x12\x51\x68\x3d\x85\x9d\xe4\x48\xf8\x22\xdc\xf3\xd2\xcf\x55\xed\xe2\xf9\xc7\x1b\x60\x63\xd1\x37\x30\x61\xf8\xf5\x93\x6b\x69\x8d\x13\x84\xe6\x54\x59\xea\x2b\xc2\x6e\xc9\x67\x75\xef\x42\x52\x07\x43\x2d\xda\x0a\xc1\xfe\x28\x52\x6c\x5e\x45\x59\x34\x9c\x3d\x8d\xf9\x91\x82\x30\xf4\x04\x46\x83\xcc\x2c\x1b\x85\x8d\x14\x1a\xb8\xd0\x80\x5b\xb9\x33\x60\x67\x52\x2a\xa8\x9c\x81\x0f\x3e\xaa\x7a\xc2\xd8\xdd\x28\xc3\x75\x12\x25\xa1\x9e\xce\xc8\xbc\xca\x52\x43\x99\x46"}, -{{0xb0,0x17,0x53,0xef,0xa7,0x3b,0xb3,0xde,0x7a,0xa7,0x78,0xbe,0x7a,0xfc,0xbf,0xf6,0x6a,0x5d,0x3e,0x2c,0x2f,0x8b,0x5a,0xa2,0xb0,0x48,0x84,0x40,0x50,0x99,0x69,0x65,},{0xd0,0xcc,0x6c,0xf1,0x09,0xc9,0x99,0xfb,0xf6,0xd1,0x6f,0x47,0x1f,0xaf,0xd0,0x23,0x2b,0x0a,0x68,0xd4,0xc4,0x64,0x06,0xec,0x75,0x45,0xdb,0xab,0xa8,0x19,0x41,0x58,},{0x16,0xb7,0x42,0x12,0x27,0xae,0x09,0x13,0x06,0x85,0xcb,0xb1,0xa0,0xc6,0x0a,0xa5,0x7a,0x5e,0x1a,0xfe,0x1b,0xbe,0x6b,0xac,0xea,0x0c,0x28,0x1b,0xcc,0x89,0x98,0xe6,0x82,0x4a,0x77,0x2c,0x32,0x08,0xa6,0xb6,0xb4,0xd2,0x36,0x69,0x55,0x05,0xc9,0xbe,0x82,0x70,0x0c,0xf9,0x3a,0x78,0x39,0x85,0xa3,0x9e,0x16,0xe3,0x77,0xa7,0x41,0x0e,},"\x68\x4e\x61\x2f\x27\xee\xad\x0d\x34\x84\x4c\xc8\x1b\xa9\x11\xc2\x8a\xaf\x6d\x66\xe7\x12\x29\xe8\xcc\x34\x62\xf7\xc7\xa0\x50\xda\xa3\x0c\xb7\x44\x71\x15\x0f\x07\xda\xd4\x59\xb5\xa9\x13\x58\x47\x6c\x05\x98\x25\x5d\x8a\x64\x2d\xd7\xc0\x80\x28\x11\xbd\x88\xe4\xca\xc5\x97\xef\xe4\x1e\xbd\x96\xcd\x0f\x3b\x5c\xe7\x2d\xb4\xbe\x1a\x3d\xbd\x6b\x84\xf5\x44\x6e\x3d\xa6\x00\xd3\xb1\xd2\xb4\x60\xa0\x09\xbd\x31\xca\xcd\x98\xa9\x15\x18\xce\x33\xe9\xa7\x03\xd4\x04\x28\x87\x36\xcc\xc4\x31\x03\xfc\x69\xe6\x79\x74\xf3\x16\x52\xfa\x3d\xad\xef\x33\x37\xf6\xc8\x97\xa3\xd2\x01\x30\x3c\x8f\x03\x59\x7b\x4a\x87\xc9\x8f\x29\x1c\xcd\x58\xa3\xf1\xe8\x98\x33\x2a\xa5\x99\x3b\x47\xfc\xb5\xdd\xaa\x1c\x08\x68\xb6\x43\x74\x2d\x0e\x4a\x4b\x9c\xd4\x27\x03\x8b\x3b\x74\x99\x9b\xc8\x9a\xc3\x48\x4c\x0c\xa1\x3f\x25\xaa\xe8\xe7\x8a\xe1\xcc\xee\x62\x18\xac\xca\xb8\x1a\x4f\x69\x4f\x53\x24\xa3\x47\x62\x9d\x49\xb5\x5e\x40\x37\x50\x4a\x9a\xcc\x8d\xf5\x8c\x68\x41\xdd\xdc\xd4\xfc\x43\x47\xf7\xb6\xf1\xfd\x9d\xe0\x56\x45\x77\xe6\xf3\x29\xed\x95\x1a\x0a\x6b\x91\x24\xff\x63\xe2\x2e\xb3\x6d\x3a\x88\x63\xbc\x1b\xf6\x9c\xea\x24\xc6\x05\x96\x7e\x7d\x89\x48\x95\x3f\x27\xd5\xc4\xc7\x5f\x08\x49\xf8\x72\xa3\xe3\xd1\x6d\x42\x2f\xa5\xa1\x1e\x1b\x9a\x74\xdf\x6f\x38\xb9\x0f\x27\x7d\x81\xfc\xe8\x43\x7a\x14\xd9\x9d\x2b\xef\x18\x9d\x7c\xac\x83\xdd\xc6\x13\x77\xed\x34\x8b\x3c\x4f\xc0\x9e\xc2\xb9\x00\x59\x25\xd0\x4a\x71\xe2\x6d\x64\x16\x67\xbd\xf5\x49\x29\x43\x31\xc6\xea\x01\xcd\x5c\x0b\xd1\xb6\xa7\xec\xfd\xa2\x0b\x0f\x19\x29\x58\x2b\x74\x69\x7c\xb2\x62\xc3\x92\x7d\x6b\x22\x3f\x4b\x5f\x30\x43\xaa\x6e\xb4\x57\x1a\x78\xe9\xda\x11\xc2\xb3\x6f\x64\x55\x25\x80\xca\xa7\xb5\xfa\x6b\x90\xf9\x29\xe0\x16\x2e\x60\x8d\x12\x40\xd7\x24\x2c\xd2\xf4\x70\x25\xc0\x3d\xeb\xe0\x59\xb1\xdc\x94\x77\x02\x32\xbc\x67\x65\x14\x84\x80\xbb\x1d\x9f\x50\xda\x1e\xe6\x44\x8c\xf9\xc8\x8b\x19\xdd\x45\x99\x32\xc0\x6e\xd8\x11\xc4\xa6\x4a\x12\xd5\x93\x8b\xd1\xc7\x57\xbc\xfa\xea\xee\x89\x33\xfe\x5f\xff\x21\x76\x3d\xe7\x40\x48\x2b\xcf\x1b\xa5\x9a\xfd\xc8\xfc\xf8\x73\xc3\xd5\x07\xbb\x39\x4e\x32\xe4\x5f\x73\x65\x19"}, -{{0x4f,0x4b,0x20,0xd8,0x99,0x36,0x6f,0x2f,0x23,0xee,0x62,0x8f,0x22,0x9b,0x23,0x6c,0xf8,0x0f,0x43,0xba,0x18,0x31,0x77,0xc9,0x7e,0xe3,0x48,0x29,0x54,0x6f,0x17,0x42,},{0xc9,0x45,0x76,0x64,0x1f,0x4a,0x89,0x3c,0xdf,0xce,0xe7,0xb3,0x9f,0xc2,0x19,0x29,0xb8,0x6b,0x34,0x99,0x76,0xd7,0xb0,0xa4,0x6d,0x39,0xa5,0x88,0xbc,0xfe,0x43,0x57,},{0x0f,0x80,0xff,0x5d,0x17,0x48,0x8f,0xe2,0x6f,0x93,0xc5,0x43,0xb0,0x4e,0xd9,0x59,0xb5,0xf0,0x64,0x3f,0xc6,0x1c,0x7f,0x2c,0x3b,0xc6,0x01,0x32,0xba,0x9c,0x62,0x10,0xc8,0xb2,0x50,0xea,0x5e,0x84,0xd0,0x7b,0x01,0xde,0x68,0xbc,0x17,0x44,0x14,0xee,0xeb,0x31,0xfd,0xc2,0xba,0x68,0x23,0xe2,0x31,0xe3,0x12,0xa9,0x1e,0xde,0xdd,0x02,},"\xdb\x8e\xf0\x2e\x30\x33\xe6\xb9\x6a\x56\xca\xb0\x50\x82\xfb\x46\x95\xf4\xa1\xc9\x16\x25\x0d\xd7\x51\x73\xf4\x30\xa1\x0c\x94\x68\x81\x77\x09\xd3\x76\x23\x34\x6a\xe8\x24\x5b\x42\xbd\xa0\xda\x6b\x60\x46\x2c\xcf\xdf\xc7\x5a\x9a\xb9\x94\xe6\x6c\x9a\xb9\xfe\xcd\xd8\x59\x96\x10\x91\x0a\xff\xe4\xf1\x02\x15\xcb\x28\x0b\xf8\xf9\xf2\x70\x0a\x44\x47\x96\xda\xe9\x3e\x06\xc6\xbe\xa7\xd8\xb4\xfe\x13\x01\xba\xa7\x9c\xce\xc7\x69\x36\x8f\xeb\x24\x42\xc7\xde\x84\xf0\x95\xe6\xb3\xbf\xf6\x3d\x38\x8c\xba\xfb\x2b\x98\x09\xdc\x38\xe9\xb1\x2e\xbd\x03\x9c\x0a\x57\xf4\xd5\x22\xe9\x1e\xc8\xd1\xf2\xb8\xd2\x3a\x4a\x0a\xe0\x59\xaf\x85\x39\x3b\xb0\xa1\x5f\x74\x91\x10\xf6\x77\x4a\x1f\xd7\x31\xa6\xec\x21\x3e\x4f\xf4\x35\xda\xab\x54\x6d\x31\xed\x9e\xc3\xb6\xd8\xcc\x2e\xda\xce\xbf\x4f\xac\xc5\x56\x65\x56\xee\xa9\x2e\x5b\x3f\x25\x42\x23\x9b\x25\xe2\x80\x12\xdd\x4e\xf4\x00\x72\xee\xbf\x83\xed\x2a\x25\x51\x81\xf3\xa4\x42\x18\x9d\x68\xc6\xc6\x09\xf4\xdf\xdf\x3d\xb7\xd6\x7d\x08\x7a\x2f\xcd\x6d\x2d\xc5\x0b\xbf\xed\x8b\xfb\xbf\xcb\x74\xd3\xc4\x1f\x02\xa8\x78\x65\xb1\x3b\x8e\xfc\xf5\xc3\x58\x12\x57\xbe\x0a\xa9\x13\xf6\x0c\x37\x05\x27\xbd\xe1\x1a\x47\x5c\x13\x6a\x17\xc5\xee\xfe\xb0\x3f\x5b\xff\x28\x69\x3e\xd8\x41\xe8\xed\x1f\x7c\x29\x10\x2f\x55\x99\xdd\x44\x40\x09\xbc\xea\x6a\x92\xd5\x57\x41\x52\x45\x8e\x0c\xaf\x8a\x36\xaa\x72\xb5\xdc\x49\x08\xa6\x46\x1c\x9b\x74\x14\x53\x00\x5c\x8f\xbc\xc6\x81\x13\xae\x18\x42\x08\xee\x14\xb8\x35\x48\x0c\x6e\xfa\xfe\xd1\x8a\x76\x00\x0b\x38\xe5\x85\x82\x90\xf4\xd5\x1f\x52\xf0\x96\xcb\xe4\x90\xe1\xeb\x5c\xac\xb2\x26\xec\x49\x5a\x55\xa7\xfa\x45\x78\x43\xd5\x7f\xab\x67\xf8\xbe\x7e\x20\x93\x34\x78\x5b\xdd\x66\x5d\x7b\x63\xe4\xda\xf5\x7b\x6e\x78\x92\x8b\x60\x3c\x8c\x0f\x9b\xc8\x54\x64\x73\x3b\x61\x27\x3e\xf9\xe2\xb8\xa0\xcd\x7c\x3b\xf8\xee\x0a\x68\x72\xe3\x4d\x5a\x27\xa6\x25\xe3\x5e\xaf\x7f\xf5\x44\x0b\x8b\x14\x1a\xf7\x04\xdf\x70\xc9\xc1\x86\x23\xbd\x11\x20\x95\x13\x19\x25\x05\x10\x5c\xd7\xbc\xfa\x5f\x0d\x91\x9d\xa7\x06\x94\x8f\xbe\x1f\x76\x1f\x31\x58\x46\xaa\x3b\x48\x13\xdd\x9b\xa3\xd8\x1b\x92\x04\xe5\x40\x9c\x03\x82\xb6\xeb"}, -{{0xd2,0xe0,0x1d,0x25,0x78,0xb6,0x25,0xa7,0x06,0x0a,0xab,0xc2,0x57,0x65,0xf1,0x68,0xc6,0x80,0xce,0xf7,0x67,0xaa,0x97,0xca,0x0e,0x5e,0xb3,0xd6,0x67,0x47,0x4b,0x2a,},{0x19,0x1a,0xc2,0x23,0x57,0x54,0x24,0xaa,0x35,0x4b,0x25,0x5b,0x81,0x2d,0xd3,0x02,0x5d,0x70,0xed,0x82,0x9e,0x08,0x26,0xc0,0x16,0x29,0xf9,0xdf,0x35,0x45,0x08,0x2b,},{0x87,0xa0,0x10,0x39,0x4a,0x9f,0x2c,0x90,0x4e,0xff,0xef,0xca,0x9f,0xb4,0xd5,0xce,0x13,0x79,0x33,0x01,0xa4,0x92,0x5b,0xa5,0x1d,0xb1,0x19,0x12,0x3a,0x4d,0x73,0x0a,0xbf,0x76,0x4c,0xe0,0x65,0xe4,0x8d,0x90,0xa7,0x9d,0x90,0x7d,0x72,0x54,0xc4,0x0c,0xc3,0x58,0x98,0x7a,0x46,0x94,0x9e,0x92,0x8b,0xbb,0x3c,0xd0,0x85,0xdf,0xab,0x06,},"\x20\xd5\xdd\x69\x9b\x28\x53\x30\x2a\x68\x17\x09\x4d\x5e\xa5\x12\xbd\xf8\x53\x45\x04\xcb\x28\x9c\x60\x24\x67\x41\x07\x40\xec\x7e\xb8\xea\x64\x42\xc8\x0f\x14\x59\x35\x06\x8f\x91\x22\xfd\xf4\xa3\x9f\x20\x10\xf3\x3d\xb5\x5b\x81\x4d\x97\xbf\x2e\x58\x72\x32\x9f\x11\x26\xd4\xeb\x95\xb8\x06\xca\x19\x73\x11\x31\x65\xb1\x16\xbe\x87\x16\x37\x1f\x81\x33\x17\x79\xdc\x79\xa5\xcb\x39\x42\x08\x1a\xb5\xf2\x07\xf6\xb5\x3d\xb0\xe0\x03\x81\x07\xd6\x3c\xa9\x77\x08\x18\x19\x82\xdc\xb5\xf3\xb9\x30\x10\xec\x6e\xdf\xb2\xcf\xd3\x1c\xab\x00\x09\x0b\x3c\x38\x51\x5f\x97\x81\x76\x96\x86\xcb\x17\xab\x81\xd5\x4a\x8b\x77\x57\x54\xd4\x2f\xba\xd0\x86\xb8\x0b\x28\xd6\x36\xf7\x8b\x7e\xb7\x7e\xd9\xca\x35\xb6\x84\x3a\x51\x0f\x0a\xd0\xac\x1b\x20\x26\x7a\x00\x03\x01\xb3\xc7\x07\xa2\x0f\x02\x14\xd5\x9b\x5b\x81\x99\xc2\xf9\xee\x25\xd3\x20\x60\xac\xe3\xe0\xf2\x59\x46\x50\x41\x6a\x00\x71\x6c\xd3\xf9\x86\x04\xa5\xe1\x04\xb3\x33\x10\xfd\xae\x94\xc3\x14\x01\x3c\xdc\xa5\xba\x24\x14\x40\x9e\xb7\xf1\x90\x13\x94\xf0\x07\xd6\xfa\x0a\x29\xdb\xe8\xec\x3d\xf9\x8c\x39\x3c\x8d\x72\x69\x58\x77\xcc\x9b\xaf\x49\x1e\xf3\x0e\xf7\xdb\x33\x71\x60\x8c\xa9\x7c\xc6\x21\x56\x25\x20\xee\x58\x1d\x5d\x1c\xdb\xc7\x82\x32\xd6\xc7\xe4\x39\x37\xb2\xcc\x85\x49\xe6\xf1\xe0\x8d\xf5\xf2\xea\xc8\x44\xfe\x0f\x82\x2b\x24\x83\xad\x0a\x5d\xe3\x3b\xe6\x40\x89\x49\x0e\x77\xd6\x98\x00\xfa\xe2\x58\x9e\xe5\x87\x12\xac\x15\xa3\xf1\x9e\x6f\xfd\xbc\xa4\x2f\xe1\x89\x4e\x88\x9b\x94\xc0\x4b\x04\x24\x0d\xaf\xb0\xb2\x73\x0c\x23\x6b\x8c\xce\xb2\xcb\x97\xaf\xd1\xd5\x15\xdc\x19\xd1\x06\x7f\xd4\xab\xa8\xce\x29\x7f\xd6\xd1\x10\xb3\x5a\x21\xbd\x3c\x07\x5c\x57\x7d\x93\xfe\x1d\xf7\x7d\x64\x8f\x71\x19\x49\x20\x99\xb0\x17\xaf\x44\xeb\xa0\x9c\x80\x7f\x11\xa4\xc3\xf4\xa1\x1a\x2f\xff\x30\x6a\x72\x8b\xa7\x89\x83\x32\x3c\x92\xa2\xfd\x5f\xcc\x80\xc1\x8d\x42\x34\x26\xf8\x23\xa7\x3f\xe0\x40\x94\x95\x52\x84\x29\x3f\x5f\x6b\x3c\xa4\xff\x10\x80\xdb\xb1\xe4\xc6\xf7\x4c\x1d\x93\x5e\xd2\x1e\x30\x09\x4c\x7d\xe3\x36\xb8\x2d\xd8\x20\x0b\x0d\x65\x95\x83\xc5\xbf\xd5\x47\x0f\x9d\xb3\x42\xe7\x0e\xc4\x00\x07\x42\xc5\x64\x0a\x21\x4e\x3c\x2e"}, -{{0x7c,0xd7,0xec,0x99,0xdd,0x03,0xae,0xde,0x1f,0xf1,0x07,0x3e,0xc2,0xca,0x70,0x10,0x27,0x6e,0x94,0x7e,0x2a,0xa9,0xb0,0xe6,0x5f,0x87,0x7e,0x4c,0xcf,0x1b,0x3a,0x14,},{0xe4,0xc3,0x9d,0xbe,0x94,0x93,0x17,0x6b,0x82,0x13,0xf1,0x42,0x2a,0x9d,0xe7,0xc7,0x4f,0xb6,0xa5,0x91,0x90,0xfc,0xdb,0xf6,0x37,0xc7,0xad,0x5e,0xe1,0x65,0xc0,0x4f,},{0x6f,0x99,0x20,0x27,0x70,0x96,0x45,0x35,0xe4,0x83,0xa0,0xee,0x01,0xa5,0x29,0x44,0x2e,0xb3,0x21,0x30,0x3f,0xa8,0x05,0xd4,0x75,0x60,0x4d,0x7f,0xc7,0x28,0xa9,0x10,0x3f,0xb7,0xb5,0x58,0xb9,0x55,0xf4,0xd0,0x37,0x19,0xee,0xfa,0xa3,0xb7,0xed,0x5b,0x0d,0xa7,0x57,0x10,0xbb,0x98,0x78,0x7f,0x5c,0x22,0x82,0xed,0x66,0xe9,0xf6,0x0c,},"\xa6\x03\x4a\xa3\xc2\x48\x49\x23\xe8\x0e\x90\xe5\xa8\xe1\x74\x83\x50\xb4\xf2\xc3\xc8\x31\x9f\xaf\x1a\x2e\x32\x95\x15\x0a\x68\xe1\xee\xca\x1b\xc8\x49\x54\xcc\x89\xd4\x73\x1a\x7f\x65\x12\xaf\x01\x46\x4f\xdb\xce\x5d\xf6\x8e\xe8\x06\x6a\xd9\xa2\xfd\x21\xc0\x83\x5a\x76\x55\x9c\xa1\xc7\x44\x9a\x93\x3b\xcb\x15\xaf\x90\x22\x3d\x92\x5f\xf6\x1c\xd8\x3e\xb9\x35\x69\x83\x47\xa5\x70\x72\x70\x9a\x86\xb4\xe5\xa7\xa6\x26\xe0\x7a\x3f\x2e\x7e\x34\x1c\x77\x83\xa5\x40\xf8\x4a\xa7\x3e\x91\x7e\x86\x7b\xb8\x0b\xac\xe6\x25\x47\x05\xa9\xd1\xa1\x18\x5d\xe5\x6e\x1a\x4e\x78\xaa\xf5\x39\xe7\x49\xb8\xf7\x65\xbd\x05\x2c\x4c\xd1\x5b\x63\x8b\xf8\xec\xf8\x7d\x98\x14\x60\x6f\xed\x5a\x69\xf4\xda\xe9\xda\x47\xf3\x80\x6d\xd9\x0b\xe6\x4f\xcc\xd3\x36\x5c\xbe\x9e\x01\xc5\x88\xfe\x65\xd6\xb6\x03\x28\x07\x40\x96\x2a\xa8\xdd\xb9\x5a\x3f\x4f\x67\x4c\x03\xbc\x40\x43\x09\x2c\x54\x45\x95\x56\x82\x70\xa2\xc2\xa8\xaa\x06\xe3\xf6\x7c\x31\x99\x8c\x50\xb9\xa5\x8a\xca\xd0\x06\x90\xd3\x84\x81\x14\xcb\x19\x32\x93\xc8\xac\x21\x01\x6f\xd9\x96\xf5\xc6\x42\x14\x06\x4f\x82\x16\x7b\x2c\x92\x0c\xd8\xa8\x39\x75\x58\x52\xac\x77\xc3\xd9\x05\x26\xdd\x3a\xdb\x96\x83\x7c\xf4\xe7\x26\xf3\x4b\xd0\x29\x55\xcb\xac\x5b\x82\xc9\x2c\xf4\xaa\x8b\x54\xbb\x6e\x43\x6d\xae\x9b\xf8\x93\xef\x05\x0c\x6f\x13\x5a\x7e\x62\xfc\xd8\x34\xda\xc1\xd2\xbe\x8b\x8e\x59\xd6\x96\x13\x18\x11\x70\x1c\x43\x18\xbb\x6e\x9b\x5a\x20\xbe\xc6\x56\xfd\x2b\xa1\x92\xe2\x73\x2f\x42\x29\x63\xbe\xd4\xa4\xfd\x1e\xc9\x32\x63\x98\xdc\xe2\x90\xe0\x84\x8c\x70\xea\x23\x6c\x04\xc7\xdb\xb3\xb6\x79\x21\x44\x0c\x98\xd7\x27\x53\xf6\xa3\x32\xea\xad\x59\xfd\x0f\x57\x74\x29\x23\xfb\x62\x5f\xef\x07\x0f\x34\x22\x5e\xa0\x6c\x23\x63\xd1\x23\x66\x6b\x99\xac\x7d\x5e\x55\x0d\xa1\xe4\x04\xe5\x26\xb5\xb2\x29\xcb\x13\x0b\x84\xb1\x90\x3e\x43\x1c\xdb\x15\xb3\x37\x70\xf5\x81\x1d\x49\xfb\xd5\x0d\x60\xa3\x47\x4c\x0c\x35\xfc\x02\x1d\x86\x81\x81\x9e\xc7\x94\xcc\x32\xa6\x34\xbc\x46\xa9\x55\xaa\x02\x46\xb4\xff\x11\x24\x62\x3c\xba\xfb\x3c\xb9\xd3\xb9\x2a\x90\xfd\xe6\x48\xe4\x14\x63\x61\x92\x95\x2a\x92\x29\x1e\x5f\x86\xef\xdd\xb8\x9c\xa0\x78\xae\xa7\x71\x7f\xc7"}, -{{0xe3,0xca,0x37,0x13,0xa2,0xfd,0x41,0x2a,0xd5,0x33,0x6b,0xc3,0x56,0xb7,0x7b,0xe0,0x27,0xd5,0xb7,0x08,0x15,0xb3,0xac,0x2a,0xec,0xd8,0x34,0x0e,0xf5,0xf8,0x89,0xb1,},{0x1d,0x51,0x6c,0xb8,0xbe,0xf1,0x16,0xa0,0xc1,0xb6,0x92,0x90,0x09,0x93,0x3f,0x6e,0xb6,0x2c,0x23,0x05,0x07,0x45,0xfe,0x7e,0x8d,0x3c,0x63,0x16,0x23,0x77,0x81,0x11,},{0xb3,0x85,0x7e,0xa6,0x1b,0xaa,0x9e,0x62,0x83,0x8c,0x4e,0x3a,0x99,0x65,0x02,0xd3,0x36,0x4f,0xe1,0xec,0x59,0x42,0x58,0x35,0x50,0x73,0xdd,0x10,0xe4,0x97,0xc6,0x00,0xbe,0xfb,0x1f,0x8f,0x23,0x3f,0xd6,0xe3,0xb2,0xc8,0x7f,0x10,0xdc,0xb7,0x26,0x1a,0xaf,0x34,0x81,0xbf,0xd0,0x90,0x26,0x05,0xac,0xcc,0x90,0x0f,0xef,0x84,0xd4,0x07,},"\xdd\x99\xba\xf2\x95\xe0\x13\xee\xd1\x07\xba\x8a\xf8\x11\x21\xaa\xf1\x83\x5a\x3c\xca\x24\xf8\xe4\x64\xb4\xcf\xca\xa3\xc7\xbf\xfe\x6f\x95\x36\x01\x6d\x1c\x8c\xf3\x75\x03\x8c\x93\x27\xe8\xe2\x1b\x00\x40\x66\xf5\xea\xc0\xf7\x6a\x3e\x8e\xdf\xb0\x7b\xe8\xbd\x2f\x6b\xc7\x9c\x3b\x45\x6d\xe8\x25\x95\xe2\xc2\x10\x5b\xb1\xb0\xaa\xba\x5e\xee\xe1\xad\xef\x75\x21\x67\xd6\x33\xb3\x22\xeb\xf8\xf7\xcd\x5f\xbf\x59\x50\x8f\xdb\xdb\xec\xf2\x5e\x65\x7a\x9c\x70\x50\xaf\x26\xa8\x0a\x08\x5b\x08\x17\xc6\x21\x7e\x39\xac\xd5\x4c\xb9\xfa\x09\x54\x0f\xc7\xbd\xc5\x22\x6d\x6a\x27\x6d\x49\x2c\xc8\xa3\xdf\xfc\x2a\xbc\x6d\x0b\x9f\xb0\x8c\xbc\xcd\xd9\x43\x2e\x44\x98\x21\xa5\xdc\x98\xcf\xb3\xa4\x18\xe5\x39\xc8\x90\xfe\x5a\x04\x46\xb9\xf8\x1d\x30\x67\x00\x92\x7a\xde\x61\xcf\xdc\xc0\x62\x4f\x13\xb5\x84\x07\x48\x77\x46\x04\x80\x57\x31\xd9\x2e\x77\xd5\xde\xf6\x6b\xe4\x4c\xc8\x17\x94\x6f\x1c\xd7\x58\x19\x6c\xf4\x80\xf9\x9e\x71\x17\x83\x5c\x4c\x87\xcb\xd6\x40\x77\xa5\x62\xa8\x0c\xf1\x1d\x8c\xa6\x5b\xe7\xa9\x4d\x92\xb9\xdd\xae\xa9\x97\xe9\x3f\x14\x48\x57\x7e\xd6\xd8\x43\x6b\x2f\x31\x44\x69\x2c\x1f\xd7\xd2\x8a\x03\xe9\x27\x4b\xc9\xe8\x66\x9d\x85\x75\xf5\xde\x20\xcf\xbd\xbc\xb0\x4e\x9f\x39\xf3\x45\x1d\x70\x48\x37\x5e\x26\x98\xe7\x22\x84\x6c\xb4\xf2\xd1\x9a\x81\x0c\x53\xd4\xc1\xa6\xc3\xb7\x70\xfb\x40\x2d\xf0\x53\x0e\x7b\x29\x07\x22\x3f\xd0\x89\x9e\x00\xcb\x18\x8c\xa8\x0c\x15\x31\xb4\xe3\x7f\xba\x17\x6c\x17\xa2\xb8\xf5\xa3\xdd\xc7\xa9\x18\x8d\x48\xff\xc2\xb2\x72\xc3\xda\x9c\x9b\x89\xdf\xe5\x3f\x2f\xe7\xe3\x67\x2f\x91\xd1\x18\x18\x49\x1a\xce\x14\x0a\xdc\xae\x98\x50\x2e\x11\x4f\x4b\x35\x2b\x90\xe2\xe7\xfb\xd3\x33\xb2\x45\x9e\x7f\x15\xdd\x07\x64\xc9\xc3\x4e\x4c\xb7\xcc\x09\x55\x00\xcd\xa0\x35\xe8\xe2\xe4\xe3\xc8\xfd\x5d\xf5\xf3\xaa\x57\x9a\x73\x5d\xd8\xa9\xf1\x9e\xf3\x36\xfa\x97\x11\x14\xe4\x66\x18\x73\x4a\x4c\x13\xd3\x0c\x81\x12\x8c\xa2\x1d\xef\x47\x33\x01\x03\xd2\x3d\x80\xff\xe6\x74\x21\xa6\xcc\xf9\xf3\x6a\x93\xf0\x56\x03\xc5\x99\xee\x10\xb0\x34\x51\xf3\x6b\x21\x33\xc1\x87\xa7\x9a\xd9\xe6\xfd\xfb\xb1\x25\x95\xab\x73\xbb\x3e\x2e\x2e\x43\x03\x0f\xd3\x7e\x59\x1c\xf5\x5d"}, -{{0x29,0xa6,0x3d,0xcd,0x48,0xa3,0x51,0x77,0x14,0x11,0xfd,0xdc,0xab,0x46,0xbb,0x07,0x1e,0x91,0x49,0x85,0x76,0xe8,0xd0,0x2f,0x8b,0x60,0x44,0xf5,0xbd,0xd3,0xed,0x90,},{0x39,0x23,0xfd,0xcc,0x2a,0x9f,0xe5,0xca,0xbf,0x6e,0x99,0x32,0xe4,0x6d,0xbd,0x2b,0x7f,0x36,0x32,0x50,0x0f,0x9d,0x95,0x55,0x2d,0xb2,0xb0,0x45,0xbc,0x41,0x16,0x6f,},{0x12,0xbf,0x62,0x95,0x93,0xe2,0xca,0xad,0xc9,0x10,0xec,0x40,0xbf,0xe2,0xb7,0xa6,0x25,0x14,0x12,0x6b,0x16,0xba,0x3a,0x43,0x8d,0x88,0xe2,0xd2,0x1f,0x59,0x5a,0xae,0xe8,0xab,0xfa,0x4a,0xf2,0xec,0x87,0x03,0x61,0xd0,0xea,0x04,0xdf,0xc8,0xc6,0xa3,0x30,0xfb,0x28,0x41,0xc2,0xd8,0x21,0x1a,0x64,0xfa,0x1e,0x7e,0x7d,0x27,0x38,0x00,},"\xff\x18\xca\x0c\x20\x4c\x83\x86\xa4\xaa\x74\xec\x45\x73\xc7\xb6\x92\x16\xb3\x14\x70\xda\xed\xd9\x6a\x4f\x23\x02\x11\x6c\x79\x55\xd7\x2d\xac\xc8\x8e\x37\x14\x55\x0c\x09\xe6\xf7\xb9\xa8\x58\x62\x60\xdc\x7e\x63\xda\x4c\x63\x3b\xae\x01\x62\xe1\x16\xe5\xc1\x79\x7b\x78\xd8\x7d\x47\xff\xee\xa3\xd7\x81\x9d\xf9\xc8\x52\xf0\xff\x30\x93\x6a\x10\x5d\x3a\xf5\x53\x1a\x8f\x89\x54\x97\x11\xc1\x4c\x2d\x3e\xe1\x15\x64\xe7\xc8\x52\x5b\xd5\x88\x64\x00\x97\x62\xa0\x55\x41\xd8\xe0\x7a\xd8\x41\xa5\x5a\x6a\x9a\x00\x7e\xf2\x09\xcc\xec\x4b\x56\x40\xba\xbe\x35\x65\x1b\x61\xdf\x42\xde\x4d\x91\x0e\xe7\x3a\x93\x3c\x0b\x74\xe9\x95\x75\x7e\x84\xa9\x9e\xb0\x34\xf4\x18\x07\x18\x3c\x90\xca\x4e\xa8\xd8\x4c\xdb\xa4\x78\x61\x3c\x8e\x58\x7c\xb5\xf8\xfb\x6a\x05\x50\x81\xda\x6e\x90\x22\x0d\x5d\x86\xe3\x4e\x5f\x91\xe4\x88\xbd\x12\xc7\xa1\xa6\xb3\xc9\xfc\xe5\x30\x5e\x85\x34\x66\x58\xef\xfa\x81\x0d\x0e\x8a\x2a\x03\x9d\xb4\xa4\xc9\x49\x65\xbe\x40\x11\xf9\xd5\xe5\xda\x26\x62\x33\xe6\xc4\xe1\x8e\xd4\xf8\xa2\x5a\x57\xe4\x0a\x59\x1c\x7e\xd5\x90\xc0\xf8\xb1\xa1\x19\xc7\xc9\x74\x7f\x69\x1b\x02\x19\x6c\xd1\x8e\x69\x45\x21\x3f\x1d\x4c\x8c\x95\x79\xc6\xe0\xa2\xac\x45\x92\x41\x28\xd6\xd9\x2c\x8e\x4c\x66\x06\x53\x20\x35\x3d\x48\xd1\xd5\xe1\x31\x94\xd9\x05\xf8\x37\x07\x8f\x8d\xac\x0b\x68\xcf\x96\xae\x9e\x70\x55\x4c\x14\xb2\xfa\x29\xb1\x96\x30\xe4\xb0\xf5\xd2\xa7\x67\xe1\x90\xef\xbc\x59\x92\xc7\x09\xdc\xc9\x9a\xa0\xb5\xaa\xf4\xc4\x9d\x55\x13\xe1\x74\xfd\x60\x42\x36\xb0\x5b\x48\xfc\xfb\x55\xc9\xaf\x10\x59\x69\x27\xbc\xfa\xd3\x0b\xac\xc9\x9b\x2e\x02\x61\xf9\x7c\xf2\x97\xc1\x77\xf1\x92\x9d\xa1\xf6\x8d\xb9\xf9\x9a\xc6\x2f\xf2\xde\x3b\xb4\x0b\x18\x6a\xa7\xe8\xc5\xd6\x12\x39\x80\xd7\x59\x92\x7a\x3a\x07\xaa\x20\x8b\xee\xb7\x36\x79\x5a\xe5\xb8\x49\xd5\xda\xe5\xe3\x57\x37\x10\xaa\xa2\x4e\x96\xd5\x79\x1e\x27\x30\xd0\x27\x0f\x5b\x0a\x27\x05\xba\x51\x5d\x14\xaa\x7e\x6f\xa6\x62\x23\x75\x37\x7f\x9a\xba\x64\xd0\x25\x69\xa2\x09\xd3\x3d\xe6\x86\xe0\x89\xec\x60\x11\x8e\x48\x14\xff\xc6\xc0\x77\x8c\x64\x27\xbc\xe2\xb6\xb8\x44\xcf\xcd\x5a\x7c\xed\x0e\x35\x30\x3f\x50\xa0\xdf\xe5\xdf\x5d\xde\x1a\x2f\x23"}, -{{0xc7,0x18,0x8f,0xdd,0x80,0xf4,0xcd,0x31,0x83,0x9e,0xc9,0x58,0x67,0x1e,0x6d,0xd0,0x8b,0x21,0xf9,0xd7,0x52,0x8c,0x91,0x59,0x14,0x37,0x34,0xf9,0x4b,0x16,0x98,0x83,},{0x01,0x97,0x52,0xff,0x82,0x9b,0x68,0x59,0xb9,0x05,0x8d,0x00,0xc2,0x79,0x5e,0x83,0x56,0x55,0x44,0x06,0x75,0x75,0x3f,0x37,0xe8,0x5e,0xb7,0xbc,0x58,0x39,0xc4,0xca,},{0x35,0xc1,0x70,0xdd,0x0c,0x6d,0xc2,0x92,0x0a,0x59,0x57,0x75,0xd8,0xe2,0xdd,0x65,0x24,0x3e,0x9c,0x1b,0xf9,0x6e,0xf4,0x27,0x79,0x00,0x1e,0xd4,0x5f,0x01,0xb7,0xdf,0xeb,0xd6,0xf6,0xa7,0xdc,0x2d,0x38,0x6e,0xf4,0xd2,0xa5,0x67,0x79,0xeb,0xe7,0x7f,0x54,0xe5,0xae,0xcf,0xda,0x2d,0x54,0xa0,0x68,0x47,0x6b,0x24,0xdb,0xd7,0x8b,0x0c,},"\x4a\xf5\xdf\xe3\xfe\xaa\xbe\x7f\x8f\xcd\x38\x30\x8e\x0b\xd3\x85\xca\xd3\x81\x1c\xbd\xc7\x9c\x94\x4e\xbf\xe3\xcd\x67\x5c\xf3\xaf\xbe\xf4\x54\x2f\x54\x29\x75\xc2\xe2\xa6\xe6\x6e\x26\xb3\x2a\xc3\xd7\xe1\x9e\xf7\x4c\x39\xfa\x2a\x61\xc5\x68\x41\xc2\xd8\x21\x2e\x2b\xd7\xfb\x49\xcf\xb2\x5c\xc3\x60\x9a\x69\x3a\x6f\x2b\x9d\x4e\x22\xe2\x09\x9f\x80\xb7\x77\xd3\xd0\x5f\x33\xba\x7d\xb3\xc5\xab\x55\x76\x6c\xeb\x1a\x13\x22\xaf\x72\x6c\x56\x55\x16\xce\x56\x63\x29\xb9\x8f\xc5\xdc\x4c\xbd\x93\xce\xfb\x62\x76\x88\xc9\x77\xaf\x93\x67\xb5\xc6\x96\x59\xe4\x3c\xb7\xee\x75\x47\x11\xd6\x65\xc0\x03\x2a\xe2\x29\x34\xf4\x4c\x71\xd3\x11\x78\xef\x3d\x98\x10\x91\x28\x74\xb6\x2f\xa5\xe4\x02\x0e\x6d\x5d\x64\x58\x18\x37\x32\xc1\x9e\x2e\x89\x68\x5e\x04\x64\xe9\x1a\x9b\x1c\x8d\x52\x51\xe2\x4e\x5f\x91\x81\x3f\x50\x19\xa7\x40\xa0\x4b\x5d\x91\xcb\xb8\x30\x9e\x51\x61\xbb\xa7\x9d\xca\xb3\x82\x39\xa0\x91\xf5\x0e\x09\x9f\xf8\x19\xe3\xa7\xb5\x20\x5f\xe9\x07\xcd\xfe\x9c\x0d\xc3\xee\x85\xe3\x2d\x7b\xcd\x3c\xe0\x26\x35\xe2\x05\x83\x88\x03\x1e\x31\x7f\xbf\x22\xab\x9f\x39\xf7\xf7\xe3\xcd\x1a\x11\xa9\xc1\xf4\x5f\x4e\x1e\x42\xd2\x53\x6c\x12\x2c\x59\x18\x37\x91\x18\x47\x10\x8c\xea\xfd\x99\x08\x13\xc2\xb6\x34\x4c\xff\xc3\x4b\xe3\x71\x61\xdd\x81\x56\x26\x90\x0e\x8f\xcb\x85\xc2\x1a\xfb\x4f\x6b\xe8\xad\x01\x51\x6a\x31\xc2\xa6\x58\x03\x15\x85\x7c\x6a\x21\x67\x35\xca\x99\x10\x09\xdb\xc2\xea\x50\x34\x16\x07\x47\xa8\x69\xd5\xca\xdb\x0b\x47\xff\xbd\x5d\x3a\xc9\x7f\xdd\x05\x26\xca\xe6\xea\xa3\x5c\xff\x7a\x16\xea\xf4\xfb\x95\x0c\xa3\x15\x11\x34\x6f\xea\x61\x41\x99\x9a\x3f\x75\x4e\x62\x81\xcf\xba\x15\xe8\xa8\x26\x93\x2c\x58\x9c\x5d\x24\x7c\x90\x9d\x94\xb4\xea\xb7\xeb\xcb\x09\x07\x76\x48\xaf\x06\x5c\x2d\x86\x61\x1e\xb5\x88\x45\x3e\xd7\xc2\x47\x80\xd7\x3c\x68\x9c\x87\x44\xaf\xd5\x33\xa8\x6d\x9e\xe9\xe3\x36\x57\x32\xcb\xd0\xc3\x51\xe4\x36\xf8\x98\xb7\x04\x32\x92\x09\x7e\x03\xe6\x08\x1a\x23\xac\x86\x5e\x19\xdc\x88\x58\x96\x9b\x99\x9d\x01\xfa\x65\xef\x20\x0c\x3f\x26\x9c\x81\x8e\x30\xb9\x36\x5e\xcc\x68\x3b\xcf\xe6\x9c\x20\x3b\x4e\x0a\xb6\xfe\x0b\xb8\x71\xe8\xec\xaa\xae\x82\xd3\xac\xd3\x5d\x5b\x50"}, -{{0x38,0xba,0x06,0x21,0x70,0x4d,0x21,0x55,0xfc,0x2f,0x78,0x55,0x51,0x96,0x57,0x5d,0xe0,0x6d,0x80,0x25,0x5c,0x35,0xe9,0xdc,0x96,0x5b,0x6f,0xe9,0x6a,0x4d,0x53,0x89,},{0x43,0x88,0xf7,0xf6,0x8a,0x9e,0xff,0xbc,0x36,0x6e,0x42,0xd9,0x07,0x01,0x56,0x04,0xda,0xce,0xd1,0x72,0x7c,0xd1,0xd8,0x9d,0x74,0xad,0xcc,0x78,0x9f,0xd7,0xe6,0xe1,},{0x42,0xbe,0xd6,0xa9,0x87,0x86,0xf6,0x64,0x71,0x5f,0x39,0xbb,0x64,0x3c,0x40,0x5a,0xe1,0x75,0x00,0x56,0x46,0x0e,0x70,0x04,0x69,0xc8,0x10,0x38,0x95,0x04,0xc5,0x1c,0xff,0xd9,0xe1,0xa9,0x4c,0x38,0xf6,0x92,0xfb,0x31,0x62,0x65,0x31,0x6d,0x8f,0x4d,0xc3,0xad,0x1c,0xdd,0x8a,0x6d,0x59,0x91,0xef,0x01,0x0c,0xd1,0x48,0x9d,0x7c,0x09,},"\xed\x4c\x26\x83\xd6\x44\xb0\x5b\x39\xb0\x48\xef\x1f\x8b\x70\x25\xf2\x80\xca\x7e\x8f\xf7\x2c\xb7\xed\xa9\x93\x29\xfb\x79\x54\xb7\x00\x40\x07\x05\x27\x5f\x20\xb8\x58\xcf\x7e\x34\x9a\x35\x10\x66\x5b\x63\x06\x09\xc5\xe2\xe6\x20\x69\x26\x3a\xb9\xc5\x5e\x41\x23\xa5\x64\xdc\xa6\x34\x8c\x8a\x01\x33\x20\x75\xe7\xa5\xbe\xc9\xc2\x0a\x03\x80\x79\x57\xfe\xfa\x91\x0e\x60\xc3\x5a\xe5\x79\x77\x8c\xe2\xce\x42\xe6\xa6\x9a\x1b\x64\x76\x81\xe4\x3e\xc4\xb6\x3b\xd5\xfb\xef\xab\xb3\x17\x12\xcb\x3d\x64\x19\xea\xd7\x8d\xd4\x1c\x8a\x92\xaa\xce\xb6\x3c\xbf\xa8\x9d\x2a\xf3\x96\x06\xde\x01\x0a\x39\x7e\x30\x20\x53\xa6\x15\xc1\x6e\x5e\x95\xad\x99\x35\xc0\x79\xa0\xb8\x10\x31\x25\x78\x94\x71\xa1\xe3\x57\x4f\x42\x9b\x29\xe4\xd2\x25\xc7\x72\x3f\xbb\x3c\xf8\x8c\xbd\x73\x82\x3d\x9f\x0b\x6c\x7d\x05\xd0\x0b\xde\xb0\xfb\x0a\xd3\xd7\x13\x20\x33\x18\x3e\x21\xf6\xc1\xe8\xd8\xe4\xc0\xa3\xe4\xf5\x2f\x50\x01\xda\x68\x71\x71\x34\x5c\x6d\xc8\xb4\x2c\x42\xa6\x0d\x1f\x1f\xfa\x8f\xe3\xe7\xbc\xec\xe5\x9a\x03\x58\x78\xf9\xd4\xd8\x11\x27\xe2\x24\x96\xa4\x9b\xfc\xf6\xbf\x8b\x46\xa8\x0b\xd5\x62\xe6\x52\x55\x07\x1f\x9d\x11\xa9\xeb\x04\x81\xf4\x62\x6d\x4d\x71\xff\xc3\x8a\xfe\x6e\x35\x8a\x4b\x28\x91\x79\xcb\xce\x97\x64\xd8\x6b\x57\xac\x0a\x0c\x82\x7e\x8f\xf0\x78\x81\x33\x06\xa1\xd5\xfa\xdd\x32\xb4\x6a\x1f\xbc\xd7\x89\xff\x87\x54\x06\x3e\xec\xfe\x45\x31\x3b\xeb\x66\x01\xc3\xa3\x01\x0e\x8e\xb9\x7c\x8e\xff\xbd\x14\x0f\x1e\x68\x83\x11\x09\x2d\x27\x3c\x4d\xef\xca\x47\xda\x6f\x1f\x08\x25\x74\x46\x76\xf9\xa2\x80\xb6\xc2\xa8\x14\xfa\x47\xfa\xbc\x19\x80\xd0\xb3\x7f\x08\x7a\x53\xca\x87\x78\xf3\x9f\xfb\x47\x4f\xf5\xf1\x17\x1b\x44\x2c\x76\xdd\x00\x8d\x92\x18\x2f\x64\x4a\x71\x4a\x0f\x01\x1e\x21\x5a\x78\xb9\x7a\xf3\x7b\x33\x52\x0e\xbf\x43\x37\x2a\x5a\xb0\xcf\x70\xdc\xc1\xdc\x2f\x99\xd9\xe4\x43\x66\x58\xf8\xe0\x7c\xdf\x0b\x9e\xa4\xdd\x62\x24\xc2\x09\xe7\x52\x1b\x98\x1e\xe3\x51\xc3\xc2\xdf\x3a\x50\x04\x05\x27\xfc\xd7\x28\x04\x17\x60\x46\x40\x5d\xb7\xf6\x73\x4e\x85\xc5\xd3\x90\xf5\x20\xb0\xc0\x8d\xcb\xfa\x98\xb8\x74\x24\x80\xd5\xe4\x6f\x9b\xe8\x93\xf6\xd6\x61\x43\x40\xf8\x16\x16\x11\xd5\x05\x3d\xf4\x1c\xe4"}, -{{0xae,0x33,0x1f,0xc2,0xa1,0x47,0x59,0xb7,0x3f,0x1c,0xd9,0x65,0xe4,0x85,0x14,0xe1,0x2b,0x29,0xf6,0x3b,0x06,0xcc,0xfc,0x0a,0xd4,0x9f,0x36,0x82,0x0e,0x57,0xec,0x72,},{0x08,0x80,0x3d,0x48,0x23,0x8e,0xda,0x3f,0x9c,0xeb,0xb6,0x28,0x53,0x01,0x21,0xde,0x00,0xf0,0xf0,0x46,0x8c,0x20,0x2d,0x88,0x52,0x8b,0x8b,0xce,0xc6,0x87,0xa9,0x03,},{0x75,0xf7,0x39,0x08,0x88,0x77,0xe0,0x6d,0xc5,0x6d,0xae,0xc8,0xf1,0xe4,0xd2,0x11,0xb7,0x54,0xe3,0xc3,0xed,0xbf,0xa7,0xed,0xa4,0x44,0xf1,0x8c,0x49,0xb6,0x9c,0x5a,0x14,0x2d,0xb4,0x5a,0x0a,0x76,0x50,0xe4,0x7d,0x10,0x55,0x0b,0xa6,0x81,0xff,0x45,0xdd,0x44,0x63,0xc4,0xac,0x48,0xbf,0x44,0xb7,0x30,0x34,0xbd,0x56,0x59,0x22,0x0e,},"\x57\x16\x00\x33\x90\xe4\xf5\x21\x65\x98\xa0\x3d\x7c\x43\x0d\xbf\x49\x5e\xe3\xa7\x55\x7b\x58\x06\x32\xba\x59\xf1\x51\x98\xb6\x18\x0a\x42\x46\x9c\x23\x7d\xb5\xbc\x81\xf2\x9c\xfa\xab\x0a\xff\x3c\x99\x66\x30\x9a\xb0\x69\x58\xc9\xd7\x12\x6a\xdd\x78\xe3\xb3\x24\x59\xff\x8a\x0e\x0b\xde\xf8\x74\xb5\x8e\x60\x83\x66\x8f\x38\xad\x7d\x63\xaa\xe1\xf1\x2e\x26\xa6\x13\x34\x8f\x9f\x03\xea\x5d\x20\x5f\x04\x5d\x78\xcc\x89\x02\xd4\x7f\x81\xe8\xb5\x22\x93\xe7\x0e\x86\xc9\x80\x3d\x4d\xac\xea\x86\xc3\xb6\x74\x58\xae\x35\x79\xbc\x11\x11\x3b\x54\x90\xbc\xf3\xe1\xcd\x4e\x79\x79\xc2\x64\xd8\x35\x16\x1f\xd5\x5e\xfe\x95\x3b\x4c\x26\x39\x5d\xd9\x2c\xa4\x93\x09\x20\xe9\x04\xfa\xdc\x08\x89\xbb\x78\x22\xb1\xdf\xc4\x45\x26\x04\x84\x0d\xf0\x24\xdb\x08\x21\xd2\xd5\xe9\x67\x85\xa5\xc3\x7d\xbf\xd2\xc3\x75\x98\x32\x83\xe9\xb5\xb4\x3a\x32\x07\xa6\xa9\xb8\x33\x94\x83\x29\xd5\xde\x41\xe4\x50\x08\xbc\xba\xd4\x93\xde\x57\x54\xdd\x83\xde\xcc\x44\x0e\x51\x66\xed\xaa\xe0\x20\x8f\x00\x0c\x5f\x6d\x9c\x37\x21\x53\x20\x9e\x5b\x75\x78\x11\x6f\x89\xcf\x2f\x8b\x10\x04\xd1\x30\x7e\xa7\x9e\xd3\x74\x80\xf3\x19\x4a\x7e\x17\x98\x3a\x23\x04\x65\xcc\xc3\x0f\xcc\x1a\x62\xd2\x80\xfb\xba\xcc\xf0\x06\xdc\x4d\xee\x0e\xa7\x96\xb8\x1a\xcc\xc6\x1a\x06\x3e\x2c\x08\x3d\xae\xc0\x39\xbd\x9a\x64\xa7\x70\x24\xaf\x82\xec\x1b\x08\x98\xa3\x15\x43\x29\xfd\xf6\x16\x73\xc3\x6e\x4c\xc8\x1f\x7a\x41\x26\xe5\x62\x90\xe4\xb4\x56\x81\x9b\xde\xbf\x48\xcb\x5a\x40\x95\x5b\xab\x29\x7c\x2b\xbc\xb0\x18\xad\xbf\x24\x82\x86\x60\xa5\xd1\x2a\x06\x13\xbf\x3c\xcb\x5e\xeb\x9a\x17\xfb\x0a\x05\x47\xdb\x8d\xa2\x4d\x2e\xfb\x87\xba\x1b\x84\x31\x42\xa7\x5e\x4c\xa0\xb0\xa3\x33\xe4\xa1\x4f\xab\x35\xa6\x26\x69\x32\x9c\xa8\x75\x3f\x01\x6a\xc7\x0c\xd9\x97\xe8\xbc\x19\xee\x44\x8a\xea\xf0\xf4\xbf\x3c\xe5\x23\x05\x50\x57\x8a\xb6\x4c\x19\x01\x94\x46\xce\x2d\x9c\x01\xa0\x3d\x88\x9a\x99\x09\x86\x0a\xef\x76\xf0\x67\xc5\x0b\x61\xc3\xd0\xf1\x2c\xc8\x68\x6f\x5c\x31\xbf\x03\x2a\x84\x10\x15\xcf\xef\xf1\xcf\xda\xe9\x4f\x6b\x21\xda\xe9\x41\xb3\x35\xdc\x82\x1f\x32\x84\xce\x31\x50\x8f\x5d\xb5\xc4\x48\xff\xaa\x37\x73\xe9\xbe\x1a\x4c\x85\xa1\xc5\x8b\x00\x9f\xa3"}, -{{0x82,0x43,0x5f,0x39,0x79,0x01,0x06,0xb3,0xaf,0x72,0xf9,0x1f,0x14,0xc9,0x28,0xd2,0x46,0x5f,0x98,0xcd,0xd1,0x00,0x84,0xc4,0xa4,0x4d,0x19,0xaf,0x71,0xa1,0x92,0x7c,},{0xc5,0x2a,0x92,0x64,0x6f,0x5a,0xdb,0x21,0xc6,0xdd,0xe0,0xde,0x58,0x78,0x68,0x37,0xf8,0xa3,0x41,0x4c,0x09,0xae,0xdf,0xc2,0x7c,0x81,0x22,0x18,0xa7,0xe7,0x23,0x9e,},{0x1d,0xaa,0x44,0xef,0x06,0xd4,0xc1,0x0d,0xdb,0x48,0x67,0x84,0x23,0xc5,0xf1,0x03,0xa1,0xb5,0x68,0xd4,0x2b,0x20,0xcc,0x64,0xaf,0x11,0x0f,0xce,0x9d,0x76,0x79,0xa2,0xde,0xe4,0x12,0xb4,0x98,0x05,0x85,0xc2,0x6c,0x32,0x0d,0xba,0xa6,0x01,0xc4,0x72,0xde,0xfc,0x3c,0x85,0x41,0x5d,0xae,0xcd,0xd6,0xd2,0xd9,0xea,0xca,0xc8,0x5e,0x07,},"\xf3\xd6\xc4\x6a\xc5\x24\x8d\x53\x86\xb6\xb6\x84\x62\x59\x7d\x64\x70\x39\xf5\x44\xbb\x01\xac\x2d\x10\x67\xda\xaa\xa3\x97\xd2\xdb\xaf\x12\x5a\x1c\xf8\xfd\xf2\x80\xa6\xaf\xec\x32\x4d\x53\x11\xf5\x43\x68\x8a\x15\x6c\x84\x98\x19\xbb\x04\x6b\x91\x1c\x42\xea\x3c\xa0\x1b\x99\x80\x8c\x4d\x1f\x3b\x8b\x15\xda\x3e\xfe\x2f\x32\x52\x3e\xc3\xb0\x9c\x84\xb4\x8c\xff\xd1\x3c\x17\xc9\xe2\x6c\x91\x2d\x9c\x3e\x93\x46\xdf\xae\x3f\xd0\xc5\x6c\x88\x58\x78\x07\x82\xf6\x1a\x4c\x4d\xbf\xff\x1e\x9c\xb4\xb3\x62\xcd\x80\x01\xf9\xcd\xfe\xb1\xa7\x20\x82\xdc\xe9\xc9\xad\xe5\x2e\xff\xc9\x74\x46\x88\xac\x0b\x86\xc8\x82\x66\xb5\x3d\x89\x5c\x17\xea\xd9\xe8\x9e\xd8\xd2\x4d\x40\x64\x2f\x3a\xd3\xb9\xbf\x9b\xbc\x4d\xda\x79\x66\xef\x83\x28\x28\x9f\xb3\x1e\x17\xc8\x1f\xd0\x28\xef\x1b\xd9\xa1\xd4\xc7\x92\xe8\x6e\xc2\xdb\xdc\xe3\xf9\x37\xee\xcc\x3e\xeb\x51\x88\xd3\x25\x94\x19\x19\xbb\xf7\x5b\x43\x88\xe2\x39\x95\x07\xa3\xd7\xfb\x38\x75\x02\xa9\x5f\x42\x1c\x85\x82\x6c\x1c\x91\x76\xc9\x23\xe3\x16\x31\x0a\x4b\xa4\x5c\x8a\x5e\xf7\x55\x7c\xf8\x7b\x77\x02\x0b\x24\xf5\xba\x2b\xfd\x12\x28\x10\x95\x66\x30\x7f\xea\x65\xec\x01\x50\x19\x69\x12\x17\xbc\xe6\x9a\xee\x16\xf7\x62\x49\xc5\x8b\xb3\xe5\x21\x71\xcf\xef\xd5\x25\x4e\x5e\x0f\x39\x71\x69\x18\x6d\xc7\xcd\x9c\x1a\x85\xc8\x10\x34\xe0\x37\x18\x3d\x6e\xa2\x2a\xee\x8b\xb7\x47\x20\xd3\x4a\xc7\xa5\xaf\x1e\x92\xfb\x81\x85\xac\xe0\x1d\x9b\xf0\xf0\xf9\x00\x61\x01\xfc\xfa\xc8\xbb\xad\x17\x1b\x43\x70\x36\xef\x16\xcd\xae\x18\x81\xfc\x32\x55\xca\x35\x9b\xba\x1e\x94\xf7\x9f\x64\x55\x55\x95\x0c\x47\x83\xba\xb0\xa9\x44\xf7\xde\x8d\xf6\x92\x58\xb6\xaf\xe2\xb5\x93\x22\x17\x19\x5d\xa2\x45\xfe\xe1\x2a\xc3\x43\x82\x4a\x0b\x64\x03\xdf\xe4\x62\xd4\x3d\x28\x8d\xb3\x1f\x99\x09\x7e\xc3\xed\xc6\xe7\x65\x47\xa3\x74\x2f\x03\xc7\x77\xef\xb1\x58\xf5\x8d\x40\x53\xfa\x6c\xc8\xd6\x8b\x19\x6a\xf4\xf9\xde\x51\x6f\xd9\xfb\x7a\x6d\x5d\x9e\xe4\xa8\x9f\x9b\x9b\xce\x1e\x4d\xee\x35\x7a\x1e\x52\xc0\x54\x4c\xfb\x35\xb7\x09\x2d\x1a\xa5\xa6\xf7\xf4\xc7\x60\x26\x10\xe9\xc0\x0e\xf5\xb8\x76\x1b\xc7\x22\x79\xba\x22\x8a\x18\xb8\x40\x0b\xd7\x6d\x5b\x2b\xfd\x7c\x3c\x04\xaa\xc4\x43\x6d\xae\x2e\x98"}, -{{0x1b,0xea,0x77,0x26,0xd9,0x12,0xc5,0x5e,0xc7,0x8b,0x0c,0x16,0x1a,0x1a,0xd3,0xc9,0xdd,0x7b,0xc3,0x29,0xf8,0x5d,0x26,0xf6,0x2b,0x92,0xe3,0x1d,0x16,0xd8,0x3b,0x48,},{0xc9,0xdd,0xb4,0x21,0x06,0xcc,0xef,0x4e,0x0e,0xf4,0x79,0x45,0x51,0xd2,0x1d,0xf9,0x4a,0x63,0x06,0x87,0x2f,0x23,0x16,0x63,0xe4,0x7e,0x24,0x1f,0x77,0xcc,0x3e,0x82,},{0xf9,0xb0,0x45,0x17,0xbd,0x4f,0xd8,0xef,0x90,0xf2,0x14,0x0f,0xc9,0x5d,0xc1,0x66,0x20,0xd1,0x60,0x2a,0xb3,0x6c,0x9b,0x16,0x5f,0xff,0x3a,0xba,0x97,0x8d,0x59,0x76,0x71,0x10,0xbb,0x4e,0x07,0xa4,0x8f,0x45,0x12,0x14,0x47,0xac,0x0c,0x1a,0xba,0xc5,0x85,0xd3,0x91,0xd4,0x04,0x20,0x41,0x89,0x86,0x28,0xa2,0xd2,0xdc,0xc2,0x51,0x0d,},"\xb1\x12\x83\xb1\xf0\xce\x54\x9e\x58\x04\x73\x0a\xc3\x20\x7a\xc0\x03\x32\xd2\xaa\xcf\x9c\x31\x0d\x38\x32\xd8\x79\xf9\x63\x4b\xd8\xa5\x8a\xdf\x19\x9e\x4b\x86\x3b\xb1\x74\x81\xd2\x8a\xcb\x2d\xa0\xe1\x55\x7b\x83\x36\xa4\x00\xf6\x29\x56\x25\x03\x1d\x09\xe4\xdf\x4d\x31\x9b\xbc\x1e\x8f\x6e\x92\x32\xd2\x30\x53\xbb\x3f\xfa\xc4\xfe\x2c\x70\xce\x30\x77\xfc\x00\x60\xa5\xcb\x46\x92\xa1\xcf\x0b\x3e\x62\xfe\x45\x48\x02\xae\x10\xb8\x3d\xed\x61\xb6\xbf\x45\x4c\xa7\x5e\x4c\xda\xd5\x53\x2f\x20\xb7\x06\x54\xf1\x2b\xa9\x06\xf0\x03\xa8\xb9\xe9\x86\xf1\x5a\x39\x41\x9d\xeb\x2e\xa1\xea\xd7\x59\x82\x90\xee\xeb\xf9\x25\x2b\x0c\x27\x60\x5a\x7a\x73\xa6\xab\xeb\xb4\x22\x71\xd7\x1a\x3c\x19\x7a\x46\xbc\xc8\xdb\x11\xd9\x24\x28\x42\xf3\x78\x36\x4a\x37\xee\xca\xa3\x4e\x98\x21\x35\xbe\x34\x18\x2c\x69\xca\x8e\x6e\x3c\x8c\x90\xe1\xb4\xb2\xb4\x75\x81\x5a\x17\x83\x77\xae\x01\x65\xa7\x64\xc8\xba\x28\x89\xb5\xab\x29\x09\x49\xd8\x48\x7a\x88\xe0\xd3\xd2\xbc\x7e\x25\x20\x17\x6a\xa6\xff\x9f\xf0\xc4\x09\xff\x80\x51\x5f\x4f\x0b\x83\xc5\xe8\x2c\x23\xfd\x33\x26\xcd\xd6\xb7\x62\x52\xe7\xfd\xdc\xd6\xe4\x77\x09\x78\xcd\x50\x3e\xd2\xd6\xb4\x80\x10\x11\x67\xd3\xf1\x91\xfe\xd8\xd6\xd7\x4d\x74\xa2\x00\x7d\xb1\x09\x2e\x46\xa2\x3d\xde\xcd\xdc\xdb\x98\x46\x64\x04\x7b\x8d\xd7\xcc\x8a\x57\x6e\x1a\x80\x6f\x52\xcb\x02\x7a\x94\x80\xa9\x5c\xc4\x4b\x1e\x6f\x2e\x28\x6e\x9b\x7a\x6b\xf7\xb3\x96\xfa\x54\x96\xb7\xa5\xb1\xc0\x3d\x9c\x5c\x27\xda\x1a\x42\x99\x0d\x10\xb1\x2f\xb8\x64\x0e\x15\x96\xf2\x6b\x36\x6d\x27\x0b\xa6\x4f\x99\xaf\xff\xe3\xfe\xce\x05\xa9\xb0\x25\x4b\x20\x8c\x79\x97\xcd\xb5\x12\xfc\x77\x52\x79\x54\xa1\xcb\x50\xfd\xab\x1c\xc9\xa4\x51\x62\x74\x1f\xd6\xf9\xd3\xfd\x5f\x2e\x38\x28\x53\xd7\x33\x5d\xba\x1e\x6b\x29\x59\xdd\x86\xe1\x25\xe6\x7b\x53\xdc\x8e\x45\x3c\x81\x0b\xc0\x1b\xf2\x0b\xce\x7b\x61\x8d\xd5\xd1\xed\x78\x41\x06\xee\x06\xa3\xec\xaf\x6b\x3b\xee\x0b\x56\x83\x3b\x0b\x81\x31\x39\xc5\xa6\x96\x00\x0a\x44\x9c\x97\x90\x6a\x2f\xbd\xdc\x2d\x9d\xe9\x40\x6e\xa2\x82\xac\x4e\xe5\xef\x8b\xf3\x85\x4c\x74\xa6\xb7\x17\x3d\xd2\xf7\x9c\x7a\x12\x6f\x3c\x7b\x04\x33\xfd\x4e\xa2\x6e\x87\x7a\x14\x83\x1d\xd4\x15\xa1\x9d"}, -{{0xd0,0x1a,0x0e,0xad,0x9d,0x69,0x48,0x33,0x28,0x3b,0x9c,0xd7,0x29,0x9a,0x7b,0xd7,0x5f,0xa9,0x0b,0x1d,0x2d,0x78,0x84,0xe4,0x55,0x7b,0x33,0xc9,0x98,0x77,0x2a,0x68,},{0xa0,0xf7,0x57,0x47,0x9b,0xa6,0x27,0xef,0xef,0x95,0xd6,0xec,0x7a,0x93,0x1d,0xfa,0xc4,0x37,0x3d,0xf3,0x3d,0xaa,0xf4,0xdd,0xc4,0xec,0x68,0x94,0xc8,0x26,0x1e,0xd7,},{0x9a,0x0f,0xf7,0xf3,0x51,0x74,0xec,0x3f,0x66,0xd2,0x2a,0x6f,0x06,0xdf,0x60,0xe0,0x9c,0x8f,0x62,0x3a,0x5a,0xca,0x81,0x0e,0x23,0xa8,0x8d,0x0e,0x6a,0x31,0xcb,0x6f,0x1c,0xe1,0xc1,0xf9,0xdc,0xcc,0x9e,0x14,0x84,0xb6,0x8d,0xd0,0x04,0xac,0x53,0x59,0x7e,0x29,0xad,0x6a,0xb7,0x2e,0x8c,0xe2,0xb7,0x5a,0xd5,0xb8,0x0e,0xb8,0x48,0x03,},"\x76\x27\x53\x4e\x9a\x83\xd1\xe4\x06\xab\x94\x8d\x30\xd1\xda\x9c\x6a\x5d\xb0\x8e\x0f\xeb\x7f\xc5\xba\x5c\xbf\x76\x84\x9e\xe8\xad\xd4\x84\x7e\xf5\xca\x5a\x0d\xae\x41\x1a\xca\x09\x74\x51\xcb\x4c\x2b\x49\x8c\x94\x70\x97\x40\x70\x07\x64\x0d\xc1\x9e\xd9\x38\xe3\xb9\x1b\xf5\x1c\x95\x81\x16\x8d\xf8\x60\xbd\x94\x75\x16\x68\xda\xbd\x72\x1d\xc7\x39\x98\x40\x0b\xe2\x0c\x9a\x56\x3d\x50\x51\xef\x70\xe3\x54\x6f\xee\x67\x33\x12\xb5\x2a\x27\x40\x41\x05\x7e\x70\x84\x8e\xb7\xc5\xa2\x16\x44\xc9\x7e\x44\x8a\xbd\x76\x40\x20\x7d\x7c\xda\xfc\xf4\x5d\xa6\xdf\x34\x94\xd3\x58\x5b\x0e\x18\xac\x5a\xc9\x08\x1c\xb7\xa4\x07\xa3\x9a\x87\x77\x05\xcb\xaf\x79\xa0\x1b\x91\x5f\x73\x6e\xb0\x25\xc5\x8b\x4b\x5d\x80\x7f\xb7\xb7\x56\x6c\x59\x69\x78\x7c\x1d\x6c\xa4\xeb\xa9\x7d\x50\x9e\xf7\xfb\x35\x50\xd2\x1d\x37\x7e\xce\xff\xcf\x0e\xb6\x68\x18\x95\xad\xbd\x24\x6e\xe7\xbf\x3c\x93\x5a\x00\x64\x78\xb8\x32\xec\xe4\x6d\xe6\x11\x8b\x17\xe4\x66\xa2\x7f\xc2\xa4\x4a\x89\x6b\xaa\xe2\x72\xf9\xec\xf0\x18\xc6\x5c\xb5\x0c\xfb\xfc\x8d\x26\x09\x94\xa1\x8a\x83\x2d\x97\x19\x28\xc4\x49\x67\x57\x24\x58\x51\x31\xc8\x71\x53\x3c\x98\x97\xd8\xf8\x0f\x9c\x04\x16\xb7\x18\x78\x6b\x10\xfe\xa8\xeb\x5b\xd8\x13\xa2\x69\xa1\xb6\x77\xb7\xa2\x50\x7a\x44\xb7\x13\xd7\x05\x08\x65\x30\x99\x5e\x59\x33\x5d\xdc\x28\x55\xe8\x47\xe4\xf4\xdb\x06\xc9\x1f\x1d\x54\x02\x3d\x8a\x10\xf6\x9f\x9e\x61\xbd\xce\x4b\x68\x6f\xb6\x17\xbd\x50\x30\xe7\x55\xca\xdb\x1f\x64\x4e\x1d\xdd\x91\x61\x9b\x96\xec\xd6\x05\xb0\x01\x98\xb9\xa6\xed\xdb\x5a\x84\xeb\xd3\x69\x2b\x66\x59\x79\x76\x66\x37\xc6\x77\x37\x8c\x1c\x77\x04\x1f\xd4\xa6\xb3\x55\x5c\x1d\xc8\xa8\x3f\xe9\x01\x3b\xb6\x10\x6c\xc1\x8a\x2b\x03\x7c\x93\x77\xb7\xa1\xa5\xa5\xd0\xdc\xc5\x49\x18\xea\xad\x7e\x32\xc8\x80\x76\x7b\x26\xfd\x2e\xa2\xd6\x8b\x04\x05\xf5\xe0\x74\xf5\x5a\x19\xd8\xa3\x9f\xfb\xb7\xdc\x32\xfa\xee\x6a\x7f\x95\x32\xae\xc8\xa0\x77\x6c\x3f\xf8\x3a\xe3\xa4\x62\x77\x38\x49\x6a\x37\x1e\xb9\xe0\x90\xb7\x4e\x0e\xdd\xec\xfc\xd4\x1b\xed\x0c\x0c\xe5\x81\x27\x52\x43\x47\x2d\x26\xda\x8c\x99\x8e\x4b\x6d\x6b\x44\xfc\x88\xba\x2a\xb5\x46\x42\x22\x54\x17\x12\x02\x94\x41\x78\x05\x74\x2b\xdb\x33\xb7\xb1\x22"}, -{{0xdf,0x64,0x89,0x40,0xb5,0x78,0xbc,0x31,0xd2,0xa6,0x52,0x96,0x5f,0x30,0x39,0x1c,0xaf,0x06,0xd5,0xf2,0x51,0x59,0x9a,0x73,0x7c,0xe1,0x0b,0xe5,0x5f,0x4a,0x9d,0x0d,},{0x27,0xde,0x92,0x04,0x19,0xc1,0x86,0xb0,0x1b,0xe5,0x42,0x79,0xfb,0x8f,0x9b,0xe4,0xbb,0x4b,0x2c,0xad,0x75,0xca,0x7e,0x8f,0x79,0x2b,0xfa,0x7b,0xb9,0x7c,0x7f,0x41,},{0x62,0xbc,0x99,0x1c,0x45,0xba,0x9b,0x26,0xbf,0x44,0x01,0x16,0x26,0x41,0x62,0xc3,0x4c,0x88,0x59,0x78,0x85,0xe9,0x60,0x50,0x83,0xc6,0x04,0xb5,0xf5,0xd8,0xfa,0x6f,0x66,0x2b,0xa2,0x14,0xf7,0x6e,0x6c,0xf8,0x4e,0x5e,0xc0,0x4d,0xf1,0xbe,0xef,0xc5,0xf2,0x5d,0x3a,0x3b,0x72,0xf9,0x8b,0x50,0x69,0x83,0x19,0x16,0xa6,0x32,0x96,0x01,},"\x1a\xe5\x20\xbe\xeb\x4a\xd0\x72\x2b\x43\x06\x7f\xa7\xcd\x28\x74\xab\xcf\x34\xdd\x92\x37\xb4\x47\x8e\xae\x97\x72\xae\xa2\x97\xa6\x7f\xb7\x9b\x33\x07\x02\x04\xba\xee\x44\x0b\x9c\x87\xe2\xfb\xcb\xeb\x76\x80\x1d\xdd\xea\x5e\x45\x30\xd8\x9e\x11\x58\x31\x79\x93\x9a\x00\xa3\x2f\x81\x13\x32\xc5\x22\x91\xcc\x7a\xc9\x1e\x5a\x97\x0c\xd5\xaa\x70\x8b\x1d\xa2\x6b\xe9\xfe\x43\x2a\x9b\xbd\xa1\x31\x9e\x31\xe4\xbc\xc9\xf1\x66\x6a\x05\xb5\xc0\x5b\x87\x6b\xfd\x1f\x76\x66\x87\xcc\xea\x4e\x44\x82\xe9\x24\x32\x9a\xfa\xce\x5e\xe5\x2e\x98\x79\xfd\x69\xb7\x6e\x0f\x7e\x45\x2e\xc4\x71\x3b\xff\x21\x6d\x00\xc8\x25\x99\xd2\x7c\xa4\x81\xf7\x3a\xae\x13\x6f\x08\x75\xc8\x8a\x66\xb1\xb6\xf3\x4c\x50\x52\x3a\xb6\x02\xe9\xd4\xeb\xb7\xee\xb9\xe0\x43\xa6\x5e\x41\x89\x9d\x79\x75\x2a\x27\x9d\x2e\xd4\x69\x93\x92\x6f\x36\x21\xe7\xc3\x2c\x9a\x9b\x3b\x59\xd8\xdd\x57\xbe\xca\x39\x28\x54\x34\xde\x99\x1c\xbd\x2d\xfc\xbc\x5c\xa6\x2a\x77\x79\xf4\x75\xd0\xce\xf2\xf3\xe5\x62\xf2\x9a\xcd\x47\x4f\x3c\x99\xec\x5b\xd8\xde\x01\x10\x1b\xed\x2e\x0c\x9b\x60\xe2\xd7\x0f\xd4\x32\xc8\x92\xfc\x66\xf8\xd4\x61\x9a\x91\x1b\x56\x25\x16\x3e\x9a\x42\xbf\x9e\xa3\x85\x86\xd8\xe7\x64\x00\x15\x64\xd3\x35\x41\x12\x25\xfc\xb0\xa0\x6d\xc2\xa8\x2d\xa0\x77\x9a\x3c\x44\x4e\xb7\x86\x42\x01\xb4\x3e\xbb\x72\xb9\x21\xf3\x4d\x3c\x13\x08\x9d\xf2\xf4\xfa\xc3\x66\xff\x1e\x3c\x0b\x96\xf9\x3d\x2b\x4d\x72\x6a\x5c\xe4\xd6\x91\x6d\x82\xc7\x8b\xe3\x54\xa1\x23\x0c\x2c\xf0\x41\x8c\x78\xa1\x91\x3e\x45\x4f\x64\x8c\xc9\x2c\x8d\xd0\xe1\x84\x64\x5f\xe3\x78\x1d\x26\x3c\xff\x69\xf5\xc6\x0b\x1e\xbb\x52\x00\x5a\x8b\x78\xa5\x15\xc7\xe8\x88\x6f\xfe\x05\x4d\xab\x42\x8e\x2e\x22\x1d\x9d\x76\xaf\xf4\x26\x54\x16\x8d\x83\x3b\x88\x17\x82\x93\xe1\xfe\xdd\x15\xd4\x6c\xd6\x09\x48\x31\x29\xc4\xd2\xd8\x44\x32\xa9\x9d\x31\xff\xe9\xbd\xb5\x66\xf8\xc7\x5c\xe6\x5e\x18\x28\x8e\x4d\xf8\xc1\x67\x31\xa0\xf3\xfd\xde\x1c\xca\x6d\x8e\xde\x04\x35\xff\x74\x36\xca\x17\xd0\xae\xb8\x8e\x98\xe8\x06\x5c\xbc\xbf\xd0\xff\x83\x04\x3a\x35\x7c\xd1\xb0\x82\xd1\x70\x3d\x46\x18\x81\x87\x2c\xdf\x74\x1e\x4f\x99\xbd\x14\x67\x45\xba\x70\x39\x74\xbe\x40\xf5\x79\xbf\x5c\x4d\xba\x5b\xdb\x8c\x94\x1b\xce"}, -{{0xc8,0xac,0x23,0x45,0x58,0xaa,0x69,0x81,0x6b,0x36,0x8b,0x77,0xb7,0xcc,0xcb,0x5c,0x8d,0x2a,0x33,0xec,0x53,0xae,0xef,0x2c,0xe2,0x28,0x71,0x43,0xbd,0x98,0xc1,0x75,},{0x53,0x64,0xba,0xf1,0xfd,0xb2,0xc6,0x38,0x40,0xb3,0x0d,0x40,0x31,0xcf,0x83,0xa2,0xe1,0x8e,0x62,0x07,0x93,0xba,0xe5,0x9d,0x10,0x35,0xc0,0xed,0xe5,0x5e,0x52,0x8b,},{0x32,0x25,0x03,0x61,0xdf,0x6e,0xd2,0x83,0x48,0x5f,0x95,0xf3,0xd3,0x57,0xa4,0xf1,0xc3,0x3a,0x8c,0xf9,0x16,0x58,0x32,0x7c,0xd4,0x53,0xd4,0x9c,0x95,0x36,0x65,0x51,0x08,0x70,0xaa,0x45,0x4c,0xfa,0x3b,0x83,0x24,0x52,0x20,0xa8,0x27,0xd0,0xec,0x74,0x77,0xf9,0xec,0xeb,0x79,0xc4,0xa2,0x9f,0x30,0x1f,0x95,0x3c,0xc8,0xca,0xac,0x07,},"\xce\x48\x8d\x26\x97\x5c\x1c\x93\x28\xb4\x7f\xa9\x2e\x19\x56\x13\x30\x04\x1b\x23\xa0\xe5\x7a\x4b\x8b\xca\x89\xeb\x5f\x61\x5e\x73\xdd\x7f\xae\x69\xc2\x38\x0e\x32\x12\xf9\xb7\x33\x41\xc3\x56\xdb\x75\xa6\x25\x6d\x7a\x20\xa9\x7f\x75\x9d\x4c\xba\x71\x97\x17\x8e\xa7\x24\xdd\x93\x29\x49\x36\x0e\x96\xc5\x0a\x4b\x3b\xa5\x5a\x95\x33\x72\xc3\x97\xb0\x96\x9c\x2b\x14\xd3\x60\x9e\x0a\x85\x2d\x48\x4d\xf7\x0e\xaa\xb1\x12\x49\xeb\xeb\x32\x37\x92\x1f\x0a\x39\xa5\x5d\x7d\xcc\xfe\xf2\x05\xd9\x4e\xc8\x0d\x9e\x1f\xd6\xa2\xc1\xef\xd2\x98\x44\x10\x1d\xfe\x2c\x5f\x66\x8a\xdb\x79\x75\x91\x5d\xed\xd0\x86\x50\x0c\xee\x2c\x1e\x23\x3e\x8e\x48\x85\x5c\xc1\xa6\xf2\x87\xd6\x3d\xce\x10\xad\xdd\x13\xca\xc7\xb7\xa1\x87\xef\xe4\x7e\x12\xd1\xc3\x5b\xb3\x97\x40\x52\xb2\x3a\x73\x66\x8d\x3e\x4c\x87\xdb\x48\x41\xaf\x84\x6e\x80\x86\x72\xc4\x3d\x0a\x15\x22\xe2\x96\x5f\x08\x39\x51\xb2\xb2\xb0\xc4\x09\x54\x8e\xe6\x18\x2f\x0c\x98\x50\x51\x4c\x9e\x6c\x10\x2f\x54\xba\x41\x24\xc9\x2a\x90\x27\x4f\x40\x58\x91\xe6\x62\xf5\xeb\xb3\x77\x1b\x85\x78\x31\x56\xe9\xe5\x83\x67\x34\xd0\x9d\x1b\xaf\x5b\x21\x34\xc9\x31\x62\xee\xc4\xbe\x03\xbd\x12\xf6\x03\xcd\x27\xbe\x8b\x76\xac\xcc\x6e\x8b\x8b\xac\x02\x0c\xba\x34\x79\x65\x1c\x9f\xfa\x53\xce\x4e\xb7\x7a\x77\x31\x3b\xc1\x26\x5d\xda\xb8\x03\xef\x7a\x65\x63\xba\x6f\x79\x9d\x1e\xf3\x0e\xf5\xa0\xb4\x12\x96\x5f\xda\xc0\xb9\xda\xb8\x42\xc7\x8e\xe2\xcc\x62\x8e\x3d\x7d\x40\x61\xe3\x4e\xde\x37\x97\xe1\x54\xb0\x6e\x8c\x66\xce\xbd\xf2\xde\xd0\xf8\x1b\x60\xf9\xf5\xcd\xda\x67\x5a\x43\x52\x77\xba\x15\x24\x55\x7e\x67\xf5\xce\xfa\xfc\xe9\x29\x29\x1d\xce\x89\xec\xb0\x8a\x17\xb6\x7a\x60\xc5\x82\xb4\x87\xbf\x2f\x61\x69\x62\x66\x15\xf3\xc2\xfe\x3b\x67\x38\x8b\x71\x3d\x35\xb9\x06\x66\x69\x96\x0d\xe4\xdb\x41\x3c\xd8\x52\x8e\xe5\x6e\xd1\x73\xe9\x76\xa3\xc9\x74\xac\x63\x3a\x71\x34\xcc\xe3\x83\x19\x73\x5f\x85\x7b\x7d\x71\xba\x07\xf4\x77\xef\x85\x84\x8a\xa8\xf3\x9e\x11\x81\x18\x77\x9e\xd8\x7b\x4f\x42\xaa\x35\x8a\x89\xf7\xec\x84\x4a\x45\x1e\x7e\x8f\xc0\xaf\x41\x8b\x85\xbc\x9b\xf2\xf2\x6d\x1e\xa1\x37\xd3\x35\xec\x7e\xe7\x57\xb7\x0a\xe2\xfd\xd9\xcc\x13\x49\x32\xf0\xe5\x42\x5b\xf3\x7f\xb9\x15\xe7\x9e"}, -{{0x2c,0x47,0xf2,0xb8,0xb9,0xd2,0xce,0xe9,0xe6,0xf6,0x54,0xbc,0x24,0x65,0x8f,0x9e,0xaf,0x43,0x9c,0x23,0xbe,0xaa,0x0a,0x79,0xbf,0x35,0xcc,0x8c,0xd2,0xde,0xba,0xf4,},{0x44,0x4a,0xf2,0xf3,0x4f,0xd3,0x2e,0x5a,0x19,0xf6,0x1f,0x87,0xd0,0x3e,0x10,0x76,0x27,0xa3,0xee,0xb8,0xbd,0x94,0xd2,0xfa,0xea,0xa3,0x48,0xb0,0x5d,0xea,0x19,0x80,},{0x85,0x54,0xb0,0x1d,0x09,0xed,0x86,0xe6,0x13,0x95,0xb9,0x1a,0x2b,0x1e,0xe1,0x87,0x15,0xc4,0x2f,0x9c,0x7e,0x7f,0x07,0x00,0xd7,0x9f,0xf9,0xfb,0x57,0x81,0x29,0x3d,0x61,0xc5,0x58,0xdd,0x5b,0x43,0x1c,0x93,0x71,0x8d,0xcc,0x0f,0x98,0xfb,0x65,0x2b,0x59,0x6f,0x18,0xc3,0x0f,0x82,0x21,0x5e,0x8e,0x63,0xe4,0xf6,0x56,0x8c,0x88,0x00,},"\x04\x4c\x8f\xaa\x8c\x8a\xaf\x9f\x2b\x81\x86\xa6\xb9\xb3\x38\x47\xec\x7b\x45\x24\x23\xb2\x2a\x91\x74\x3d\x2e\x59\x7e\xcc\x1e\x1e\x22\xae\x60\x05\x3e\x9e\xe6\x23\x3b\x04\x4e\x77\x59\x20\xe4\xe3\xd6\x67\x19\x90\x13\x25\xcf\xdd\x39\xbb\x53\x2f\x8a\xa4\x69\xaa\xb4\x2e\x96\x08\xc2\x12\x60\xc0\x4c\x27\x41\x3a\x7a\x94\xe4\x66\xf6\x3c\x49\x52\xe9\x0e\xf9\x0c\x12\x81\x4b\x34\x51\xb1\xca\xd7\xda\x91\x47\xf8\x40\x92\x20\xf6\x49\x8c\xc0\xa6\x7f\xef\x4b\xc0\x4f\xc0\x6e\x1d\x89\x8a\x55\x15\x59\x1e\x8b\xe0\xc4\x3d\x75\xa6\xfe\x42\x5b\x7c\xbe\xfb\x1b\x91\xb1\xbd\x78\xb5\xbe\xc7\x82\x90\x56\x98\x2e\xfd\xc5\xbe\x24\xaf\x66\x78\x00\x6a\xdc\x6f\x04\x46\x20\x2e\x7e\xc3\xa2\xd6\x97\x9c\xb0\xdf\x7e\x25\xd7\x42\x33\x91\x4d\x9c\x58\xb8\x1c\xf5\x5b\xe0\x69\x67\xd3\xa5\x95\xc1\xb9\x67\x28\x69\x99\x4c\xfb\xa6\x71\x62\x83\x3a\x21\x43\xaa\x91\xcc\x93\xac\xda\xfa\x5b\x45\x20\x8d\xf3\xe8\x8c\xcc\x01\xa2\xa4\xd2\x20\xe3\x60\x09\x8d\x91\x54\xd2\x25\xa7\xca\x5f\x2f\x1e\x52\xb1\x00\x3d\x10\x66\x50\xa7\x7b\x28\x3b\x95\xe4\xba\xf1\xe7\x33\x6f\xa9\xa7\x47\xa2\xb3\x82\x3d\x36\x09\x10\x41\x2e\x76\xdb\x72\x5c\xe1\xab\x1e\x1d\x18\x9d\x0d\x3a\xbe\xf8\x2d\x76\x66\xbc\xf1\xb7\x66\x69\xe0\x64\x3b\x44\xf7\x4e\x90\xce\xaf\xa0\xc8\x37\x1b\x57\xc5\x8f\x3b\x37\x0a\x54\x7c\x60\x95\x8f\x0f\xcf\x46\x1b\x31\x50\xf8\x48\xc4\x70\xfa\x07\xe2\x9b\xf5\xf0\xd4\xb5\x9e\xfa\x5a\xb0\xd0\x34\x1e\x04\x51\xd0\xab\xb2\x9d\x74\x14\xcd\xdc\x46\xcc\x6d\x74\xcf\x3d\xc2\x33\xd0\xd1\x70\x73\x87\xbd\x8c\x77\x80\xff\x78\xe5\x46\xfb\x77\x29\x4d\x58\xa5\xdd\xa5\xf0\x5c\x12\x97\xe3\xd1\x77\x11\x56\xd2\x85\x63\x5b\xf7\xec\xed\xb3\x8a\x9e\x5e\x77\x44\x98\x04\xf3\x89\x9e\xa4\x6a\x50\x26\x6b\x25\x5a\xeb\x52\xd1\x8e\x0f\xa1\x36\xe5\x35\xcc\x90\x26\xf6\x78\x55\x2f\xa3\xee\x21\x46\x08\x1d\x99\x96\x85\xe2\x4b\xf7\x80\x7c\xc4\x7c\x13\x04\x36\xc5\x44\xd3\x5b\x4b\x87\x5b\xd8\xaf\xa3\x12\xce\x3a\xe1\x7c\xf1\xc7\xf5\xea\x1e\xce\xcb\x50\xf9\x53\x44\x72\x0c\xec\xf0\x88\x43\x4f\xf8\xe0\xba\x04\x4e\xc1\x9c\x98\xad\xa7\x78\x21\x16\x30\x4c\xbe\xac\x1c\x3e\x35\xf5\xa4\xf4\x43\x13\x35\x4d\xc9\xa4\x0e\xce\x5a\x0f\x9a\xd3\xa2\x02\x5a\xce\xf2\x62\xc5\x67\x9d\x64"}, -{{0x88,0x7f,0xdb,0x48,0x70,0x68,0x1d,0x4f,0xb0,0x6a,0x93,0x62,0x59,0xf7,0x5c,0xae,0x05,0x17,0xf5,0x01,0xaf,0x64,0x6b,0xc0,0x7a,0x4d,0x72,0xbe,0xe7,0xfb,0x1c,0x73,},{0xc7,0x62,0xeb,0xd4,0x8b,0x2c,0xe0,0x2d,0x06,0x38,0x4e,0x38,0x55,0x4b,0x82,0x5a,0xd3,0x22,0xeb,0xea,0x74,0xd2,0x59,0xdf,0x15,0x47,0xa4,0xd5,0x47,0xce,0x00,0x24,},{0x41,0x0a,0x5a,0xf3,0xc5,0x9b,0x7c,0x6b,0xdb,0x21,0x4b,0x16,0x6c,0xb7,0x9d,0x96,0xf8,0x30,0xcf,0x98,0xbf,0x52,0xda,0xd7,0xb6,0xff,0x29,0x79,0xc9,0x7f,0xea,0x4f,0xed,0x5e,0xf7,0xd3,0xd4,0x9f,0x03,0x09,0x72,0x79,0xb9,0xa0,0x99,0x22,0x6e,0x2a,0x08,0xdd,0x30,0xc6,0x07,0x86,0x25,0x4e,0x2d,0xa8,0xde,0xe2,0x40,0xbf,0xc3,0x08,},"\xc5\xdc\x77\x9f\x3f\x3f\xac\x06\xdd\x28\xe5\xa6\x7e\x0e\x52\x4a\xf5\xb5\xdc\x3b\x34\x40\x96\x57\xb6\x3d\xfa\xce\x94\x71\xe9\xa4\x1e\x11\x32\x17\x5a\x0b\x56\x9c\x8f\xea\x9d\x2e\xef\x2c\xf5\xd5\x96\x2c\x7e\x0b\x61\x45\xa9\xe7\xa0\xc1\xaa\x33\x77\x20\x44\xf9\xc3\x99\x8c\x5a\x8c\x48\x86\x45\x8b\x4e\x58\x6f\x93\x07\x60\x83\x61\xf5\x11\xe7\xab\x50\x92\xac\x41\xec\x76\xe0\x58\x6e\xf5\xb9\xc2\x36\xfc\xf5\xca\x2f\xc8\xdd\x6a\xae\xb7\x89\x36\x7f\x2e\x7c\x99\x09\x32\x55\x5d\xc5\x22\x61\xe4\x4e\x49\x42\x34\x98\xb5\x24\x41\x91\x83\xb6\xc1\xf1\xd4\x2c\x45\x46\x4e\xcc\xb0\xc2\xf7\xe2\x51\x77\xfe\x5c\xd4\x63\x50\x2b\x40\x3e\x06\xd5\x11\xfc\xf9\xdc\xb6\x40\x12\xe0\xf2\x0b\x34\xc2\xea\x7c\x00\x4d\x9e\x48\x4a\x7e\xd8\x1f\x32\x60\xc4\x1c\x8b\x19\x53\x52\x9f\x47\xf7\x1e\x86\x78\x43\xcc\x3c\x33\x2a\xd0\x36\x6a\x63\x81\x7e\xd1\x2d\xd4\x73\x0d\x3d\xfd\xbd\x75\x72\xb9\xff\x79\x80\x45\x94\x0d\xd1\x9f\xad\x0c\x8a\xea\x0b\x4a\xb6\x1c\x40\x16\xde\x32\x79\x9c\x73\xaa\x2b\x92\xd2\xc2\x5e\xe9\xb7\x2d\x46\xfe\x8f\x06\x93\xc5\x87\x75\xef\xb0\x5e\x9e\x17\xa5\xc3\x46\xa8\x12\x65\xd3\x5b\xe6\x9a\x22\xd0\x95\xde\x18\x60\x66\xa5\xc6\xd8\xc0\x7a\x3d\x38\xd0\x02\xa1\x0e\x5e\xfd\xb8\x66\xda\x4a\x9b\xdd\x54\xf5\x09\x26\x61\xb6\xc2\xd7\x43\xf5\xae\xaa\x4c\x6c\x31\x8f\xb5\x93\x23\x90\x30\x57\xe4\x9c\x23\x7b\x45\xf6\x75\x42\xa4\xf2\x7c\xaf\x65\xb5\x7c\xfc\xf8\x8b\x71\x20\x3d\x43\xd7\xf9\x53\x22\x16\x0f\x95\xc2\x32\xdd\x10\xab\xb1\x13\xb7\x21\xdd\xba\x22\x26\xb0\x63\x22\x9b\xb4\x41\x02\x33\x6b\x10\xbf\x16\x56\x55\x11\x61\x24\x97\x86\xd4\x54\xf4\xe0\x90\x9d\x50\x00\x17\xf6\xc7\x56\x4f\x73\x3c\x83\x1a\xf4\xe5\xec\x94\xdf\xd3\xbf\x8f\xf5\xf3\x02\x1b\x70\xa5\xca\x5d\x28\xc6\xdf\xb8\xa2\xc1\x8a\x1a\x66\x2a\x33\x35\x9f\x26\x4d\x16\x96\x98\xc1\xab\x55\x78\x3f\xac\xa7\x3b\xd6\x8c\x0f\x79\xd1\xd0\x4a\xe0\xec\xdb\x52\xae\x76\x18\x92\xc0\x24\x93\xff\x35\xf3\xd8\x4f\x66\xe2\x36\xfc\x58\x13\x4a\xd6\xa7\x7d\x92\x25\x49\x05\xd7\x73\x90\x0d\x9d\xdf\x26\x54\xc7\x0b\x46\xf3\x41\xda\xcb\x47\x93\xca\x51\xee\xde\x45\x53\x3e\xae\xeb\x6e\x33\x23\xbc\x3e\x6c\x85\xa7\x94\x06\x51\xc4\xf6\xf9\x81\x91\xc6\x18\xc8\x91\xea\x4e\x22\x0e\xa4"}, -{{0x88,0xb3,0xb4,0x63,0xdf,0xc3,0x0d,0x01,0x5e,0xef,0xbb,0xbd,0xd5,0x0e,0x24,0xa1,0xf7,0x27,0x77,0x75,0xbc,0xef,0x14,0xa6,0xbe,0x6b,0x73,0xc8,0xc5,0xc7,0x30,0x3e,},{0xf2,0xb6,0x28,0x4c,0x93,0x0d,0x4a,0xd3,0x2d,0x0a,0xc7,0x19,0x04,0x0e,0xe7,0x88,0x6b,0x34,0x72,0x2e,0xdf,0x53,0xda,0x80,0x1a,0xcb,0x5f,0x93,0x19,0x69,0xe1,0x19,},{0x82,0x5a,0xff,0x71,0xf7,0x93,0x03,0xbf,0x45,0x92,0xbd,0x8d,0xa4,0xd7,0xd9,0x43,0x7f,0xf2,0x67,0x97,0x6f,0x74,0x64,0x37,0x65,0x59,0x88,0xdd,0xcf,0x29,0x37,0x94,0x65,0xa3,0xb4,0x8c,0x9f,0xb0,0xf3,0x1c,0xef,0x03,0xe6,0x36,0x88,0x61,0xc3,0x69,0xb4,0x36,0x4f,0xb8,0xe4,0xb0,0xc7,0x2e,0x26,0xa9,0xa9,0xdd,0xed,0x1c,0x25,0x04,},"\x17\xc3\x17\xfa\x6b\xc9\x0c\x55\x32\x32\x8f\x02\xcc\xfb\x6c\x09\x9e\x6f\xe1\x00\x01\x74\xf2\xaf\x3a\x3a\x93\x09\x42\x85\x06\x71\x7c\x5c\x43\x35\xbd\xd7\xc3\x67\xff\x4e\x44\x8a\x9c\x04\x75\x03\xaf\xba\x68\xfd\x8f\x79\x87\x23\x7b\xe7\xf7\xfb\xdc\x6d\x73\xf2\x4c\x64\x21\xca\xb4\x22\xb3\xfb\x25\xf6\x7b\x2d\x71\x04\x2e\x71\x57\x0d\xf2\xaf\x37\xbf\xe5\xc1\x14\x21\x1f\xd5\x52\x4b\x6c\x1c\x6c\xc5\x2f\xab\xc3\xcd\x7f\xb4\x64\xcd\x58\x0b\xb7\x40\x71\xcb\x30\x0f\x8c\x9f\x8a\x46\x20\x8e\x5a\xa5\xdd\xfe\xa5\xfe\x90\x69\x7a\xa2\xf1\x4c\x60\x79\x50\xc9\x8f\x23\x12\xa9\xe1\x6e\xf6\x34\x6a\x8f\xd1\x29\x23\x27\x33\x82\x7e\x15\x01\xa6\x60\xc7\x7c\x29\xc5\x6d\x2f\xdd\x1c\x55\x97\xf8\xbc\x89\xaa\xef\xe3\x71\x37\x34\xfe\x82\x85\x82\x01\x89\x1a\x11\x47\xef\xaf\x1d\x78\xa4\x71\xf9\x20\xde\xfc\x88\x03\x44\x55\x3e\xb7\x16\xcc\xe3\x26\x0e\x86\xa1\xbc\x0b\xe2\x83\x73\xa6\xa0\x66\x11\x6e\x8e\xcb\x10\xa0\xc4\xa7\x0c\xa2\xb5\x36\x4e\x11\x9f\x84\xae\xc6\x0d\xec\xed\x3a\x4e\xff\x1f\xe6\x88\xc5\xe3\xe2\x51\x47\x0a\xb5\x16\xfa\x96\x4a\x4b\x6f\x28\x36\x8d\xd1\xe2\x83\x59\x79\x34\x06\x4d\xc0\xc5\xb5\x69\x10\x62\xcb\x2e\x26\x7b\xd1\x5f\xd4\x22\xbc\xfe\xfb\x83\xcc\xef\x7a\xa9\xa2\x27\x5e\xf5\x7e\x47\x31\x49\x98\x8c\x15\x78\xfd\x18\x70\x8d\x2f\xf6\x9f\x8e\x59\x80\xaa\x82\x6a\x82\xca\xb7\xd8\xb9\x2b\xb5\x3b\xdd\x46\xdb\x04\x6e\xcd\xfc\x8c\xd7\xae\x5c\xe4\x4f\x3c\x5b\x8c\x05\x65\xb5\xd3\xc0\x72\xc7\x6b\x95\xce\x90\x0a\xc3\xee\x55\x10\xdb\x0e\x75\xd3\xa4\x15\x0a\x98\xf3\xcc\xcc\xc6\x9e\x93\x0c\x6b\xa7\x41\xdb\xb0\xeb\x9f\xb3\x19\x68\x71\xba\x20\x6a\x58\xe0\xda\xe3\x9c\x8d\x6b\xb7\x2a\x82\x39\x9c\x4b\x7b\x9d\xa3\x85\x77\xac\x17\xff\x15\x24\xd6\x53\xc0\xbf\x33\x67\x93\x23\xca\x7e\xef\x4e\x92\x28\x72\x90\x31\x56\x0e\xd8\xf2\xe5\x19\x3c\x64\x0b\x2f\x5e\x60\x80\x75\xa2\xed\x61\x42\x8d\xfc\xcd\xc0\x00\x50\xba\x4b\x99\xed\x6d\x15\x36\xd5\xac\x1e\x93\x96\x74\xb4\x1d\x16\x31\x2a\xe5\xb0\x7d\xef\x1b\xf5\x35\x89\xbe\xd4\x40\x06\x02\xee\x11\xb8\x50\x33\x0f\x38\xaa\xd3\x3e\xf0\x41\x70\xa3\x90\x5c\x28\xb5\x0e\xcc\x57\xdc\xcf\x4f\x29\xd0\xc0\x0f\x71\x3d\x32\xff\xc8\x57\x95\x65\x88\xa6\x32\x6b\x95\x49\xed\xb0\xe4\xfe\x61\x85"}, -{{0x42,0x7d,0x6e,0x42,0x39,0x17,0x89,0x68,0x31,0x60,0x1b,0x8f,0x4e,0x21,0x56,0x1d,0xb6,0x10,0x85,0x71,0xbe,0x00,0x9e,0x29,0xdc,0xa4,0x9a,0x59,0x60,0xff,0x31,0x4b,},{0x8d,0x9e,0x63,0x60,0xfd,0xef,0x24,0x99,0x75,0xdf,0x27,0xb3,0x10,0x6a,0x71,0x12,0x05,0x87,0x72,0x2d,0xf3,0x27,0x0a,0x85,0xa1,0x3a,0x8c,0x3b,0xb8,0xc9,0x80,0x9e,},{0xd1,0xc9,0xa0,0x1c,0x56,0xe3,0x39,0x60,0xf4,0x9d,0xf3,0x7e,0xab,0x96,0x3b,0xc5,0xa9,0x9f,0x25,0xc6,0x00,0x44,0x6c,0xe2,0xca,0x48,0xd9,0x13,0x9d,0xa5,0x73,0x3b,0x71,0x8f,0xbf,0x1a,0x98,0x73,0x93,0xf6,0xe5,0x82,0x3c,0x2d,0x13,0x0c,0x7c,0xe6,0x0e,0xa3,0xdb,0x35,0x43,0xc8,0x85,0x4e,0xf1,0x2b,0x98,0xd3,0x3a,0xdd,0xe7,0x05,},"\x9c\x2c\xc7\xf2\x46\x2e\x09\xc4\xc5\x8c\x27\x09\xab\x42\x59\x88\x5a\x4e\x88\x7d\x9f\xa5\x31\x88\x15\x05\xaa\xf2\x03\xc1\x63\xfb\x3a\x0d\xc0\x28\xf4\xad\xa6\x06\x70\x63\x8d\x4a\x97\x27\xa3\x90\x83\xbe\xdb\xac\xed\x58\xed\xb7\x79\xe1\xce\x6c\xcd\xfb\x42\x8c\x36\x2b\xb1\xdb\x0c\x10\x53\x00\x6b\xd8\xf4\xbe\xf8\x9a\x1a\x9d\xe0\x1c\x77\x4e\x35\x7f\x91\x0e\x5c\x39\xb2\x24\x77\x55\x5e\x5f\x7c\x04\x98\xb5\xb2\x8f\x36\x9e\x5d\x3f\xa4\x2a\xb3\x60\xe4\xf4\x51\xc6\x9f\x81\xba\x0f\x3c\xce\xd4\x3a\x55\x9d\xb6\x00\x10\x42\x78\xf8\x68\x79\x6b\x2c\x91\x1b\x3b\x03\x2b\x72\x9f\x4b\x22\xac\x14\x9d\xc4\x67\xa0\xca\xe4\x8d\x19\xe9\xd9\x85\xb4\x2b\x62\x54\x9d\xe1\x71\xff\x56\x6e\x1d\x1e\x9b\xb8\xe5\x6c\xfd\x1a\xe8\xf7\xbd\xdc\xfd\x8a\x23\x41\x82\x7d\xbe\x89\xc8\x82\xab\x3e\x49\x83\x39\xff\x68\x1c\x7d\xc1\x10\x4d\xe7\x38\xb4\x80\x31\x69\x43\x10\x9f\x70\x3d\x47\x1a\xb8\x6e\x4c\xa4\x28\x7e\x4c\xd7\x4c\x31\x2f\xf7\xd0\x37\x39\x56\x06\xfb\x25\xf8\x71\xe7\x27\x70\x78\xa7\x87\xd0\x2f\x31\xcc\x9e\x81\x5b\xe8\x60\x0a\x7c\x47\xc6\xfd\xd8\x23\x31\xae\x9c\x49\x6a\x54\x7b\xdb\x23\x5b\x8a\x56\xd5\x32\x59\xe6\x29\x61\x24\xa3\x2c\x3b\x62\x5d\x20\x24\x19\xd0\x64\xb9\xa4\xe8\x3e\xfa\x87\xf1\x35\x37\xb4\xf5\x13\xb9\x16\xa8\x4f\xc8\x66\xd8\xa8\x99\x80\x4c\x78\x33\xea\xa0\x19\xe0\xd7\xe0\xe8\x07\x5b\xd6\xb5\xcb\x6f\xfc\x76\x64\x79\xf3\xf6\xe2\x0e\x48\x1e\x6a\xb2\x7b\xd8\x08\xad\x90\x6c\xdc\xc7\x82\x74\x30\xe3\x12\xf7\x40\xf2\x75\xdd\xf5\x1d\xd8\x32\x48\xfa\x05\x7c\x43\xc9\xcb\x77\x55\x7b\x2f\xd9\xc2\xd5\x28\x24\xff\x9e\x14\x6d\xea\xc1\xe6\x69\x1d\x45\x02\x13\xbc\x59\x0a\x49\xbe\xc7\x2d\x52\xe3\x8f\x6b\x4d\xc6\xcc\xa9\x51\xee\xf2\x18\x4d\x24\x25\x03\x1a\xd5\x9b\x24\x2e\xff\xa6\x8b\x6c\x72\xc5\x4c\x9d\xfd\xb4\x19\xc0\x2e\xb4\x3e\xf3\xf3\x4d\x33\x8d\x2a\x9d\xd0\x3a\x78\xcf\xdd\x01\x40\x98\xe2\x49\x25\x9e\x77\x28\x2e\x0c\x3f\xc1\x01\x0b\x02\xa6\x7f\xf8\x51\xe9\xcf\xd9\x74\x9c\x1c\xd8\xf0\x6c\xf4\x62\xe6\xad\xe9\x95\xac\x46\x6f\xab\x5c\x79\x5e\x9e\xff\x13\xe5\x5b\x43\x50\xb9\x4c\x73\x16\xaa\x49\x8d\xf9\xfd\xee\x99\x58\x04\x77\x93\xe3\xbb\xb8\x9f\xb8\x1d\xa8\x5f\x4b\x9d\x43\xe4\xb0\xd4\x3b\x38\x1b\x94\xcd\xc9\xa9\x9d\x06"}, -{{0xbe,0x93,0x52,0x09,0xf6,0x2d,0xea,0x60,0x12,0xec,0xda,0x6a,0x61,0x56,0xcd,0x16,0x6a,0x4d,0x76,0x11,0x50,0xde,0xed,0x45,0x68,0x16,0xea,0xf0,0xce,0x78,0xa7,0xf6,},{0xd3,0x9a,0x89,0xaf,0x72,0x29,0x39,0x48,0xb1,0x34,0x21,0xfb,0x88,0x3b,0xbe,0x37,0x2a,0xf9,0x08,0x9c,0x22,0x4d,0x42,0xb9,0x01,0x97,0x9f,0x7e,0x28,0x04,0xe1,0xc0,},{0x08,0xe0,0x98,0xa7,0x49,0xfc,0xe6,0xd1,0x23,0x54,0x39,0x58,0x78,0xa8,0xbe,0x35,0xfe,0x9e,0xdf,0x72,0x68,0x4d,0xd8,0x28,0x12,0x24,0x89,0x9b,0x1c,0xae,0xa4,0xed,0x68,0x77,0x85,0xdf,0xf5,0x5a,0x19,0x98,0x9e,0x03,0x63,0x6e,0x16,0x66,0x38,0x6f,0x22,0xc3,0xf4,0x43,0xec,0xf6,0xfd,0x34,0xd5,0x99,0xff,0x3e,0xc2,0xfa,0xf1,0x01,},"\x11\x7f\x42\x7c\xb6\x81\x50\xca\xfc\xfa\x46\x2c\x42\x20\x61\x41\x42\x7c\x4d\xce\xa1\xc8\xea\xcc\x2d\x30\xbe\xd1\xe9\x02\x07\xd5\xae\x30\x5e\x1f\xc1\x6c\x54\xe4\xc5\x4c\xc6\x87\x8c\xdb\xed\xc9\xf5\x1f\xe1\x84\x61\xec\x37\xc5\x57\xb1\x15\xd1\x3c\x86\x82\xc4\xe1\x5f\x50\x52\x96\xa1\x76\x0e\x1e\x75\xf5\xab\x27\xa5\xc1\x5a\x13\x57\xd2\xc8\xc4\x0d\xd5\x35\x5f\x7c\x82\xfe\xa5\xd2\x7e\x28\x87\x63\x58\xc1\x2e\x91\x13\xee\x29\x83\xea\x6f\x09\xc6\x4e\x06\xe2\x97\xdd\x96\xb3\x4d\x9b\x5e\xd4\x9f\xc4\x7a\x88\x39\x54\x9c\x66\xb0\x02\xfe\x94\x5e\x8f\x94\xe7\xd2\x31\x5c\x50\xca\x4d\xc0\x98\xbe\x4b\x32\x89\x81\x2f\xbe\xa9\x6b\x47\xce\x60\x45\x40\xbd\xe0\xe5\xab\x0b\x1b\xc0\x36\xbe\x9b\x6a\x95\xe0\x9c\x81\xe8\x98\x64\x0c\x8f\x05\xd6\x0a\xd9\x42\x18\xd0\xe6\x6c\xeb\x85\xa2\x6b\x78\x29\x22\x20\xbf\xd0\x61\xdd\x07\x35\x12\x92\x3b\x90\xc7\x9d\xcf\x5a\x19\x35\xfa\xfe\x8e\x01\xef\x8b\xf8\x1b\x4d\x37\xc5\xa5\x71\xb5\x0c\x42\x1f\x9b\xd2\x19\x4b\xef\x35\x86\xfc\xb8\x58\x48\x77\xbb\x7e\x04\x81\x65\x5b\x05\xc7\xb6\x43\xb1\xe4\x5b\x04\x03\x62\x72\x84\x18\x52\xe3\x19\x40\xef\x8f\x3b\x6d\x4f\xeb\x5d\xf0\x79\xd1\x76\xf9\x79\xc1\x8a\x11\xa6\x6d\x12\x14\xe5\x2f\x68\x7e\x90\x63\xc1\xc2\xb7\x27\x7b\x68\x5d\x5c\x72\xad\x56\x9f\x78\x73\x83\x8f\x91\x02\x57\xa0\x53\x13\x1c\x83\xeb\xce\x86\xe6\x9d\x73\x63\x62\xbe\xbc\x96\xbb\xfa\x35\xfc\xba\x1c\xb5\x27\xe7\x48\xe5\xf5\x79\x92\x9f\xd4\x0c\x56\xb1\xa5\x1a\x22\x2e\x86\x33\x02\x70\x5c\x86\xf7\xb5\x4e\xbf\xbb\x94\x82\xf7\xe2\x80\xf7\xbe\xc8\xca\xf3\xa6\xb5\x67\x1a\xc3\x0c\xd1\xbe\x52\x92\x88\x79\x7c\x01\x3c\xe5\x6b\xd1\x86\xde\x7d\xfc\x18\x28\x69\x14\x25\xc1\x47\xc5\x17\x4a\x29\x0d\x80\xcb\xd5\x9c\x19\xda\x7a\xdf\x77\x91\x88\x82\xa7\xb2\xa9\xa6\x4e\x6d\x76\xb4\x8b\x92\xf2\xa2\x66\xee\xe6\xe2\x51\xd2\xe8\x17\x65\x2b\x88\xb5\x02\xde\x73\x99\x78\x2d\x75\x29\xa8\x1d\x0a\x36\x39\x96\xb9\xdf\x68\xb1\x5a\x76\x30\x90\x4c\x8c\x24\x60\x81\xfa\x4f\x09\x29\x9f\x15\x75\x79\x58\xe0\x89\xa9\x01\xc3\x56\x46\x15\xc0\xf7\xcf\x27\x52\xb8\xb9\xe5\x21\x33\x8d\x83\x6e\x3d\xae\x4c\xe2\x37\x46\x42\x25\x3c\x4c\x98\x31\x97\x4e\x5d\x8c\x28\x42\xf4\x90\x07\xb7\x17\x75\x09\x3d\xfe\x57\xf4\x44\x92\xf0"}, -{{0x68,0x18,0xc6,0x0b,0xb6,0x43,0x9a,0xc2,0xee,0xe2,0xd4,0xe1,0x28,0xe9,0xd8,0x69,0x1d,0x4a,0xd5,0xd3,0x63,0xfe,0xd7,0xd6,0x57,0x7a,0x62,0xb6,0x56,0x99,0x94,0xa4,},{0x73,0x45,0xec,0x11,0xbc,0xcc,0x05,0x6f,0xc4,0xef,0xfa,0x3e,0x4e,0xf6,0x70,0x99,0x6a,0xa2,0x6a,0x1b,0xb1,0xb8,0x33,0x91,0xba,0xbc,0x39,0xa1,0xa5,0x96,0x01,0xf9,},{0x15,0x05,0x96,0x7a,0x27,0xb9,0xf8,0x6e,0x92,0x42,0x44,0x40,0x02,0xa1,0xe3,0x19,0x7d,0x74,0xdd,0xcd,0x89,0x65,0x9e,0xc5,0x14,0x02,0x02,0xaa,0xc7,0x94,0xb8,0xad,0xc1,0x93,0xe7,0xd3,0x0f,0x33,0x82,0x64,0x29,0x90,0xf6,0xfe,0xd7,0xa9,0x99,0xca,0xc8,0xc6,0x1e,0xaa,0x39,0xb7,0xd9,0x08,0x16,0xf1,0xd7,0x38,0x74,0x4b,0xe1,0x01,},"\xb2\xae\x65\x8b\x3c\x13\xc3\xcd\xeb\x1d\xc9\x93\xb0\xf4\x5d\x63\xa2\xea\x9a\xbd\x0b\x7a\x04\xf1\xf5\xce\x59\x32\x80\x6c\x2c\xa9\xb7\xa2\x04\xfb\xf8\xd0\x66\xb7\xf0\xfe\x6a\xe0\xd1\xda\x68\xc8\x85\xee\x11\xf6\xf6\xdb\x7e\x83\x20\xa2\xea\x65\x0b\x53\x38\x51\xcd\xd9\x9d\x90\x3a\xa0\xb3\xfa\xa3\xc9\x50\xf7\x02\xf0\x4e\x86\xb4\xee\xb3\xa1\xc7\xbc\x85\x4b\x25\x14\xfa\x5b\x47\x66\xd3\x75\xb4\xf1\xad\x61\x07\x53\x78\xdd\x92\xfd\x62\x6c\x2b\x47\xe0\x13\x83\xea\x72\x98\x79\x59\x26\x2c\x56\x28\x62\xb4\x5b\x75\x57\x67\x14\x13\xb6\x66\x14\xbc\xc9\xf7\xbd\xb9\xee\x46\xcb\xed\x89\x65\xbf\xa5\x05\x31\x50\x90\xc7\x20\x4b\xea\x89\x17\x5b\xe5\xf2\x08\x02\xe3\xde\xdd\xcb\xd8\xdd\x64\xcf\xef\x7e\xe6\xa6\xe3\x86\x0c\xe1\xe5\x79\x9d\xf5\xd8\x10\xd5\xec\xf3\x2e\x61\x5d\x16\xdf\xf8\x7a\xbd\x4a\x63\x6e\xa1\x7a\xa4\xec\xe5\xb6\xb2\xc0\x46\xb6\x5b\x5a\xf7\x49\x86\x2b\x45\x79\x0c\x39\x17\x68\x20\xb3\x69\x01\xbe\x64\x9c\xf4\x16\x9d\xf7\xe9\x23\x95\x6d\x96\x06\x49\x50\xc5\x55\xf4\x5a\xcb\x94\x50\x7c\xfd\x0c\x3b\x33\xb0\x80\x78\x5e\x35\xc0\xd2\xb0\xad\xdc\x4c\x0a\xd3\xfb\x21\x6a\xc2\xe6\x01\xc9\xc7\xe6\x17\xda\xbd\xa3\x33\xda\xe6\x03\xcc\x9d\xb1\xfc\x62\xae\x4e\x0e\x45\xe3\xcc\xdd\x16\x6a\x67\x81\xe2\x43\xb7\xda\xa1\x38\x80\x66\x32\xf5\x38\x84\x4e\xe3\xd1\x40\xb7\xa8\xbb\x2b\x54\x01\x00\x77\x8c\x45\x8e\x06\x61\x70\x70\x5e\x5f\xb2\xc8\x80\x29\x09\x8b\x99\x2c\x39\xbc\x9f\xf6\x33\x0b\xfc\xfe\x77\x52\x32\x0e\x6e\xa0\x94\x9d\x2c\x87\x1a\xed\xc1\x87\xbe\x27\xfe\xf7\xdb\x5f\x72\xa6\xa7\x73\xed\xde\x0d\xc5\x2a\xe2\xed\x93\x1c\xb2\x68\x17\xb8\x5b\x15\x45\x89\x4d\x92\x29\x8a\xaf\x87\xcc\xbc\x78\x3e\x8d\xd6\xd1\x64\x93\xf5\x6e\xad\x2b\xa8\x52\xee\x9c\x7d\x10\x07\x44\x06\x44\x0d\x2a\x27\x9a\xbc\x87\x4f\x15\x46\x8d\xd6\x6a\x71\x7b\xac\xe3\x7b\xe7\xb7\x05\x5d\xd9\x68\x1f\x8b\xe8\x13\x29\xee\x7a\xf9\x7e\x3a\xbc\x43\x4a\xc1\xc9\x3a\xec\x58\x2f\x23\xfd\x1e\xc0\xfa\x5a\xaf\xcf\x7b\xfb\xda\x00\xff\xa9\x7a\xe3\x17\xae\x91\x8d\x34\x9d\x21\xa7\xf4\x61\x91\x42\xba\x23\xda\xce\xf7\xb3\x90\xae\x26\xa1\x7e\x2e\x29\x62\xae\x27\x00\x53\x76\xb7\x2d\x4d\xa9\xe2\x97\x96\x53\xa6\x63\x25\xa1\x46\x17\x63\x8d\xbe\x1a\x55\x40\xb6\x83\xac\x00\x17"}, -{{0x6d,0x1d,0xa5,0xb4,0x83,0xe6,0x4b,0x03,0x65,0x99,0x0f,0xf0,0x93,0x81,0xfb,0x17,0x02,0xfd,0x8e,0xc3,0xa1,0xa3,0x69,0xcd,0x52,0xe4,0xc5,0x67,0x13,0xa3,0x14,0xa5,},{0x08,0x05,0x5c,0x26,0x1f,0x26,0xe0,0x2a,0x65,0x8f,0x66,0xd9,0xba,0x01,0xfc,0xde,0x53,0xe9,0xad,0xe3,0xed,0xc6,0xbf,0x81,0x5e,0x4a,0x68,0x02,0xe1,0x67,0x7a,0xb3,},{0xa5,0xb8,0xb4,0x4a,0x91,0x44,0x4c,0x64,0x37,0x4b,0x52,0x3c,0xb4,0xdc,0xb0,0xce,0xf4,0xce,0x52,0x40,0x8b,0x98,0x12,0x6d,0x7e,0x1a,0xe8,0xbd,0xc2,0x8c,0xf5,0x14,0x70,0xce,0x4e,0x25,0x3e,0x0b,0xe6,0x2b,0xd6,0x8e,0xbf,0x5f,0xa6,0xbc,0xe1,0x58,0x5e,0xcc,0xfa,0x92,0x56,0xc0,0x73,0xee,0x03,0xe5,0x4c,0x52,0x5b,0xbe,0x2d,0x0a,},"\x79\xa2\xc3\x70\x55\xf1\x89\xf3\x24\x7f\x1f\x8c\xea\x19\xb2\xea\x40\xd8\x58\xdb\x1f\x5d\x13\x92\xee\x6d\x41\x1c\x78\x02\xee\x23\xde\x52\xad\x02\x81\x17\x25\xa9\x4d\x76\x67\x5d\xa8\x9a\x96\xb5\xd0\x7a\xbc\xee\x23\x3a\x1a\x2e\x1f\xa3\x24\xff\xf9\xe7\x8a\x4c\x19\x61\x47\xf8\x57\x0b\x0b\x13\x71\x3d\x96\xaa\x5d\x75\x0a\x15\xd7\xcd\x16\x2e\x7b\xa2\xe7\x53\x33\x60\x7d\xd6\x98\xeb\x47\x73\xc7\xe9\x1f\x76\x68\xff\x8b\x62\xf0\x46\x40\xeb\x12\xec\xf1\x22\xfc\xe6\xb8\x32\xe0\xd0\xdf\x92\x8e\xef\xd2\xc2\x00\x23\x64\xaf\x6b\xb5\x52\x91\xd3\xf5\x49\x29\x08\x5b\xe3\x38\x34\x2f\x09\xda\x73\xe2\x79\xc8\x7c\x83\x24\x55\x58\x19\xed\x57\xe7\x8d\x7a\xc4\x09\x51\xd3\x3f\x65\xb9\x4a\xa1\xe5\x55\xe9\x2a\x06\x3d\x11\xf1\xff\x7b\x12\x69\x43\x41\xe3\xfe\x44\x49\x33\xd0\x1a\xa3\x67\x53\xed\x3c\xdd\xa8\x90\xbd\xf9\x5a\x82\x05\xb5\xd8\x93\x22\x19\x91\xc7\x95\xad\x0a\x4a\x94\x6f\x58\xd4\x0a\x45\x34\x51\xaf\x21\x4f\xd4\x65\xe2\x8d\x3e\x2f\x0a\x56\xaa\x56\xde\xf8\xdc\x04\xaa\xd3\x57\x13\xab\xfc\x8b\xd7\x85\x6d\x5a\x9d\xc3\xf6\x0a\x3f\x2b\xd3\xe6\x36\x6f\x1f\x24\x4e\x94\x1d\x6a\xea\x89\x2f\x6a\x88\x93\x1f\xe1\xc3\x13\xe0\x90\x78\xe9\x0b\xc6\x39\x2d\x49\x05\x33\xc9\xea\x3f\xf6\xde\xaf\x3a\xad\xfa\x8d\xfd\xc4\xe9\x0f\x64\xaf\x47\x58\x9e\xa6\x5a\x87\xac\xd2\x19\x96\x02\x35\x1d\x3a\xfc\x21\x03\x19\x6e\x03\x94\xed\x52\x3a\xa7\x99\xd3\x1e\x11\xd3\x4f\xff\x54\x6d\x44\xf4\x36\xb3\x48\x59\xf9\xcf\xbc\x9c\xe4\x03\xde\x5a\x98\x30\xec\x3d\x45\x3f\x0d\x45\x97\x0f\x57\x2c\x14\x4f\x19\x1b\x2f\xbb\x2d\x0e\xa6\xcc\x9c\x8e\x24\xd9\xc0\xb2\x18\x3b\x27\x80\x72\xeb\xb0\xbe\x2d\x70\xd0\x37\xfd\x2e\x8e\xc1\x8d\xc4\xc9\xb2\x1a\xbd\xc6\xa4\xce\x8d\x46\x68\xa2\x20\xee\xbd\x69\x34\xf0\x4b\xaf\x0e\x88\xa4\x88\xd2\xdf\xc7\x35\xa7\xc5\xa7\x0d\xbb\x01\x66\xa2\x1a\xe0\x11\xfc\x6e\x7d\xa1\x0f\xc3\x20\x33\x62\x71\xd9\xee\xad\x51\x0a\x6f\x70\x32\xf2\x29\x66\x92\xbe\x50\x80\x21\xbc\x98\xc1\x70\xbe\x42\x35\xf7\xce\x31\xf2\xbc\xd6\x34\x11\x63\x68\x33\x76\xae\x2c\x56\x62\xcb\x47\x70\xc9\x6e\x01\x8e\xf1\xbf\x47\x91\x33\x19\xc9\xa0\x9b\x9e\x96\x5a\xb5\xc3\xe9\x7b\xbc\x75\x6a\x56\x66\xb4\x56\x7f\x2c\xff\x2d\x0c\x3a\x6a\x40\x26\x15\x8c\xb9\xf9\x0f\x95\x00\x56"}, -{{0x51,0x46,0xf5,0xb7,0xf1,0xba,0xa1,0x9f,0xc8,0xcd,0x78,0x5c,0x89,0x6e,0x0f,0x90,0xf9,0xf6,0x59,0xb7,0x7b,0x1b,0x9b,0xb4,0xad,0xca,0xb5,0xa6,0x26,0x72,0x05,0xe4,},{0x68,0x8a,0x8d,0xe6,0x4e,0xff,0x33,0xba,0x6b,0xbe,0x36,0xcd,0xd6,0xa3,0x84,0xbb,0x67,0xb3,0xf4,0x26,0x36,0xdb,0x23,0x4f,0xf5,0xef,0xe0,0xb3,0x17,0x43,0xc7,0xe6,},{0x4b,0xdb,0xd7,0xc6,0x4f,0x13,0xe2,0x78,0xc2,0x39,0x69,0xe7,0xeb,0x38,0x6b,0xbe,0x49,0x9d,0xbd,0xef,0xc3,0xff,0x4e,0x30,0xcf,0xac,0x5c,0xf8,0x6f,0x21,0x6c,0x24,0xc9,0xe6,0xcd,0xe2,0x0e,0x52,0x9d,0x14,0x7f,0xb7,0xea,0x08,0xf2,0x59,0x3a,0xd5,0x09,0x03,0xb5,0xed,0xbf,0x86,0xb4,0xd2,0x8f,0x2e,0xb3,0x2e,0xf1,0x37,0xf0,0x0c,},"\x97\xbd\x99\xf5\x18\xee\x07\x88\xd5\x76\xd9\x9c\x04\x3b\x44\x9d\xfc\x24\x2a\xc5\xee\xae\xc3\x44\xa1\x94\x32\xb3\x45\x96\x2e\xc4\x12\xce\x55\x36\x2b\x3b\x85\x1d\x98\x11\x9f\xce\xb9\x32\x83\x47\xf6\xfc\xc6\x8d\xbf\x56\xa2\x81\x4d\xb0\x9e\x93\x85\x84\x3a\x93\x11\x89\xea\x3e\x72\xda\x9d\x79\xa4\x56\x93\x05\x3c\x03\x57\x01\xdc\x55\x51\x24\x0f\x95\xb3\x03\xfb\xa1\x6f\x89\xaa\x53\xa4\x38\x82\xb0\xf1\x38\x12\x02\xc7\x8f\x9c\x74\x19\x89\x9f\x23\x51\xec\xa9\x5e\x20\xbf\xee\x76\x35\x1c\x48\xd0\x04\x99\xf5\x91\xda\x56\xa9\x95\x24\xbb\x74\xfe\x1c\x83\x4e\xe9\x10\x77\x13\x9f\x1e\xdf\x67\x31\x5c\x07\xa3\xfd\x97\xf8\x0b\x7c\x27\x6b\x6c\xf6\xb5\xcc\x36\xbe\x36\x3b\x73\x12\x17\xf6\x31\x9f\x51\x29\xba\x7b\x14\xd0\x54\xc8\xd8\x1d\x8e\x3a\x3f\x3b\xe6\x2a\xc3\x1f\xf6\x2d\xf6\xa3\xb2\xee\x25\x96\x96\x9b\x99\x17\x04\xb3\x1c\x68\x99\x97\xab\x46\x28\xbc\x26\x60\xc6\x78\x72\x13\x2e\x85\xda\x0c\x4f\xcf\x56\x79\x65\xf1\x25\x4a\x8f\x43\x26\x92\xa1\x7b\xb8\x6c\xb3\xc1\xdc\xba\xac\x93\x95\x52\xf0\x9e\x50\xec\x5b\x0d\xe2\xef\x85\xe0\xac\x25\x3a\x41\x65\x65\x5d\xb5\xb5\xc4\x98\x03\x82\x1d\x85\x9c\x60\x96\x1e\x06\x1d\x58\x27\x8b\x82\x7d\xd4\xd3\xbc\x47\xf1\xc2\x2d\xe0\x94\x90\x6b\xdb\xbf\x3b\xad\xbd\xde\x22\xba\x24\x25\x58\x55\xeb\x86\xd1\xd7\xf3\x70\x82\x05\x93\x11\xdc\x07\x28\xeb\xea\xf2\x6c\x44\x73\xba\xd1\xfa\x9e\x61\x4b\x53\x3b\x81\x1b\x6b\xcb\x06\x50\xc0\x6d\x87\x9a\x52\x45\x78\x8f\x34\x01\xb4\x61\x97\x30\x07\x74\xa9\xaa\x73\xcd\x97\x8c\x05\x30\xc8\x1a\x53\xbd\xb3\xfc\x93\x24\x14\xb3\xe3\x04\x40\xdc\x12\x74\x41\xef\xf1\x60\x5e\x7f\xd9\xac\x8c\x63\x2e\x82\xbf\x1b\x45\x3d\x4f\x33\xa5\x7e\x4b\x67\xb0\xb6\xfc\xf6\xed\x55\x55\xb5\xf5\xa3\x00\xa1\x4a\x00\xd0\x38\x5a\x33\x75\x05\x25\xb0\x0e\xdb\x31\x2c\x6b\xfd\xd6\x4e\xdd\x3b\x53\x16\xd1\x9f\x95\x8c\x51\x76\x34\xf0\x13\xb0\x08\x93\x6d\x34\xe9\xb5\xe1\xe9\x28\x3a\x5f\x0f\xd7\x78\x33\x77\xc0\xe5\x09\x06\x41\xbb\x9d\x33\x8c\xf3\x13\x3a\xcd\x0b\x97\x1e\x53\x79\x04\xf1\x7a\xf9\x29\x11\xaf\xad\x72\xee\x97\xf9\xa8\x28\x3a\x16\xa7\xe2\x6a\xb4\x28\x41\x6c\x10\x17\xda\xe9\xb1\xa9\x9c\x4c\x33\x20\xad\x16\x3b\xdc\xfc\x32\x8b\xfa\xf9\xb8\xd5\xd7\xd2\x6d\x41\xd1\xef\x21\xa5\x20\x8f\x01"}, -{{0x5e,0x6f,0xda,0xc9,0x35,0x1a,0x63,0x7b,0x99,0xf3,0x3a,0x26,0x4e,0x12,0x87,0x69,0x7e,0x2a,0xba,0xb0,0xcc,0xa1,0x66,0x21,0x79,0x24,0x84,0xf5,0x60,0x6f,0x44,0xc1,},{0x57,0xe5,0xf8,0x8a,0xcd,0xdc,0x8c,0xde,0x7d,0xd0,0x7a,0x31,0x46,0xfb,0x1d,0x4f,0x7a,0x9b,0x63,0x83,0xa8,0xf6,0xb2,0xb8,0xd9,0xb0,0x7e,0xbc,0x3f,0xc4,0xdd,0x20,},{0x98,0x7e,0x32,0xe0,0x0a,0x8a,0x16,0x32,0xf4,0x7b,0x50,0x31,0x94,0x35,0x5c,0x98,0x0c,0xb2,0x2a,0xde,0xb3,0x26,0xb4,0xe3,0x11,0x5e,0xca,0xb0,0x4b,0x70,0x4d,0x18,0x6c,0xd9,0x2e,0x3c,0x3a,0xc7,0xb4,0xe2,0x93,0x6c,0xbd,0x07,0xcb,0x79,0x4e,0xc0,0xcf,0xe9,0x1a,0x97,0x87,0x2f,0xf2,0xb4,0x13,0x76,0xf5,0xf1,0x8f,0x55,0xb8,0x05,},"\x4d\x6c\xd3\xbc\x2f\x86\x26\x6b\x8b\xb1\xb6\x1d\x0e\x1c\xaa\x9b\xd2\xd4\xa1\x80\x36\x1a\xef\x3a\x18\xd3\x90\xb1\x0f\x7e\x86\x0f\x69\x7e\x24\x7e\xb6\xc3\xe5\x1d\x3b\x97\x6b\xf0\xca\x18\x3d\x01\xa6\x98\x80\xf1\x5c\x94\xb8\x75\x66\x8c\xa3\x0d\xad\xa0\x89\x5b\xed\xd4\xd7\x05\xa0\xe0\x33\x04\xd0\x63\xde\xa8\x7c\x7f\xde\xc9\x8b\x89\xc0\x6f\x13\x0d\xd5\xbd\x58\x6b\x54\xd9\xba\x73\x78\x26\xbb\x40\x5c\xd8\xac\x8b\xbc\x95\x00\xac\xda\x3c\x07\x46\x1d\x00\x94\x40\xaf\x0b\x25\x31\xe7\x2f\x3f\xf5\x01\x6a\xe2\xd8\x6d\x69\xb8\x7f\xb2\x73\xd1\xe8\xdd\x5f\x6a\x26\x4b\xee\xbb\x2f\x88\x59\x96\x74\x1f\xfd\xa2\x77\xa0\xfb\xf8\xef\x08\xf8\x1f\x22\xee\x59\x61\xd9\xd3\xfc\x93\x83\x62\xe1\xca\x12\x00\x4a\x91\xd9\xb5\xf7\xa6\x83\x3a\x6c\x22\x95\x5a\xc0\xcd\xa3\x39\x06\x71\x91\x0c\xbd\x51\xe6\x85\xfe\x09\x59\x73\xe4\x15\xfc\x2d\xb8\xad\xf1\x0b\x14\x7e\xc7\x08\x0c\x3b\x8e\xbd\x07\xd2\x1b\xb9\x55\x6d\xa8\x54\x30\xa2\x68\xee\xd8\x48\x6b\x1e\x31\xc9\x43\x13\xb0\x16\x49\xfe\x91\xb2\x22\xf8\x5a\xde\xe1\x5e\xb7\x77\x07\xd7\x8f\xfc\xb6\x60\x92\x65\x44\xd3\x3b\xe9\x99\x4a\x29\x76\x20\xdc\x7a\xed\x97\xf3\x92\x63\x90\x53\xf3\x88\xb0\xb3\xaa\x3b\xd0\xac\x5b\x03\x3c\xb4\x14\xbe\x52\x0b\x43\xdf\x68\x26\xb9\x76\x89\x0d\x0c\x53\xb9\x7b\x6c\x92\xe7\xd1\xa1\x57\x3d\x0c\x74\x94\xd7\x47\xe0\xca\xd9\xbd\x8e\xa5\x38\xd6\x2a\xd5\x98\x01\xad\x07\x16\xf1\x70\x19\x3e\x30\x09\xd9\x95\x9c\x55\xd2\xff\x64\x79\x9b\xd9\x59\x35\x9a\xbb\x94\xca\x97\x23\xb5\xff\xc2\x4c\x95\x07\xf8\xc5\xfd\x6e\x88\xea\xae\x7a\x70\xad\xd8\x4d\x74\x4c\xcf\x8b\x98\x36\x37\x88\xf0\xbf\xb1\xa0\x25\x22\x02\x57\x51\xe5\x34\x71\x0d\x40\xa2\xd3\x8a\x79\x11\x94\xeb\xa2\x93\xfd\x20\x46\xcc\x14\xdd\x38\x76\xd1\x68\xfc\x6e\x23\x6c\xbe\x14\x6d\x63\x69\xd2\x25\xbf\xa6\x7e\x53\x97\x98\x65\xf7\x88\x73\xa9\xfc\xf0\x3c\x18\x6f\xa8\x52\x1f\x0a\x55\x45\xac\xce\xe8\x0d\x1e\x55\x10\x72\x21\xe2\x1f\x0f\x22\x91\xc1\x43\xde\x02\x3e\x88\xd7\x33\x0c\xc8\x7d\x4c\x51\xff\x29\xa3\x09\x06\x05\xe9\x73\x94\x90\xc1\xdc\xee\x71\x34\x95\xf2\x31\xc2\xa3\x6b\x11\xab\x23\x55\x47\xfb\x63\x28\xf7\x47\x33\x6d\x9b\x1e\xf2\x5a\x8a\xb9\x9c\xed\xa9\x57\xb2\xdc\xce\xe4\x07\x5b\x0d\x03\x38\x1b\x94\xae\x18\xd0\x41\xea"}, -{{0xfc,0xff,0xf0,0x93,0x2d,0xc8,0x6e,0xa5,0x90,0x2a,0x8d,0x33,0x07,0x33,0x29,0x96,0x0c,0xd8,0x18,0x8a,0x07,0x5d,0xd0,0xbc,0xdf,0xa8,0x38,0x2c,0x20,0xb0,0xe7,0x8f,},{0x0c,0x92,0x05,0xa9,0x0b,0xbe,0x7f,0x2d,0x50,0x5e,0x17,0xfa,0x3d,0x08,0x0b,0x52,0x2a,0x1d,0x7a,0x15,0x2c,0xad,0x2d,0x85,0xd3,0x1b,0x34,0xa0,0x47,0x1c,0x0d,0x4c,},{0x37,0xdd,0xd8,0x3f,0x98,0xb0,0x57,0xb7,0xcb,0x32,0x08,0xa8,0x32,0xc5,0x8a,0xa9,0x06,0x94,0x56,0x3c,0x23,0x54,0x8d,0x43,0x22,0x91,0x38,0x0b,0x73,0x59,0x13,0x01,0xf2,0x74,0xb0,0x4c,0xee,0x2e,0xf7,0x8c,0x06,0xd9,0x6c,0x3d,0x9b,0x7c,0x17,0x52,0x1a,0xae,0x1a,0x8c,0xa5,0x0d,0x34,0x7c,0x09,0xc3,0xcf,0x70,0x3b,0xc8,0x83,0x0b,},"\x3d\x4b\x76\x12\x23\x73\xe2\x12\xa3\x46\xd1\x9a\x66\xbb\xfc\x4b\x62\x32\x92\x64\x9b\xd0\xce\x5c\xf6\xbb\x13\x56\x48\xbd\x01\xdb\x74\x03\xb3\xd0\xbd\xd1\x69\x7f\xf4\xe6\xe9\x08\x90\x41\x16\x75\x4d\x37\x0c\x40\xd7\x00\xcd\xb6\x64\xc4\x6a\x91\xdd\x84\xa3\x58\xb9\xd2\x38\x14\x43\xe6\x0f\x2c\x3f\x56\x40\x26\x1b\x6b\x85\x8b\xa8\xf8\x28\xb0\x97\x1f\x41\x22\xb2\x02\x88\xa2\x6b\xa2\x09\x0b\xa1\x4f\xd2\x76\x36\x0c\xc6\x86\x79\xcd\x84\x19\xae\x19\xc6\xd4\xdc\x7b\x66\x14\xc0\x6d\xf5\xe5\xc0\x51\x0e\x2c\xb6\x86\xde\x0e\xbd\x75\xe5\x21\x0a\x21\x55\x62\x58\x9b\x28\xc9\xcc\xc7\xd2\x72\xb9\x8b\xd4\xbf\x93\x49\x5e\xfe\x4f\xc5\xb7\x8d\xef\xec\xfb\xca\xa9\xfe\x12\x6b\xad\x30\xe8\x9b\x3a\x38\x9b\x42\x56\xf6\xa4\x8a\x76\xc3\x45\xde\x5a\x36\xa1\x44\x9f\x08\x34\x5b\x9a\x5e\x6a\x00\x1d\xa1\xff\x9c\xd4\x33\x70\x93\x48\xe9\xae\xfb\xc7\x8b\xa5\x2d\x3a\xb3\xb4\x69\x86\x93\x5e\xba\x8e\xcf\x81\xed\xc4\x3c\x5b\x2e\x3b\x5e\xb3\x8d\x9a\x16\x5e\x9e\x7f\x72\xf6\x17\x60\x54\x63\xbe\xdb\xa9\x73\xeb\xfd\xcd\xf2\xb0\x88\x9c\x71\x41\x2f\x8f\x85\x0c\x7a\x3b\x55\x18\xec\xd8\x9d\x2e\x25\xc0\xc1\xc3\x0f\x08\x5a\x0f\xfe\x54\x0e\xf9\xc0\xe8\x8f\xc7\xec\x4a\xf1\x94\x8a\x4e\x6f\x7a\x6e\x25\x6b\x30\x7a\x11\x27\xb7\x1b\xa6\x86\xef\xea\xdc\xa0\xe4\x86\x09\x47\xcf\x67\x4f\xce\xd6\xca\xf7\x31\x0c\xcb\xaa\x8d\x90\x47\xda\xed\x30\xfd\x55\x85\xd4\x1d\xde\xae\x4d\xf2\xfe\xd4\xb6\x22\x80\x32\xc3\xe4\xae\x23\x80\xe8\x7e\xc6\xcd\x72\xe4\xd7\x4b\x8b\x4c\x38\x13\xfb\x04\x33\x89\x39\x1e\x9c\x13\xf7\xd3\x3c\x3a\xab\x5a\x78\xfc\x4c\x6a\x63\x4c\x61\xa7\x0f\x02\xa9\x40\x54\x8d\xa1\x77\xc6\x5d\xf6\xab\x17\xcd\x96\x83\xf3\x7e\xa8\x21\xc7\x40\x88\x9d\x82\xe8\x8c\x83\x4e\x7d\x5d\xc1\x16\x62\xea\x78\xb1\x3c\x6a\x4b\x62\x18\xd3\x17\x84\x21\x9a\x47\x67\x59\x5b\x1a\x56\x21\x65\x25\xcd\x68\x93\x8b\x22\xbd\xb1\xf8\xc5\xa7\xf1\x70\x1a\xfe\xb9\x61\x88\x8e\x2e\x0e\xc0\xc8\x38\xcd\x62\x0c\xb7\xdd\x8a\x14\x93\xa0\x2c\xd5\x6b\x54\x51\x25\xe4\x70\x0c\x08\x89\xfa\x26\x44\xe6\x44\xa3\xaf\x53\x1d\x1c\xd6\xbc\x95\xe5\xdf\x91\x75\xf1\x37\xf2\x84\x08\xcb\x69\x9c\x7a\xe6\x6f\x65\xd1\xd2\x93\x0f\xac\x57\xca\x8a\x60\xe6\x31\x1a\x40\x78\x48\x8c\x9e\xa4\x04\x94\x8a\x9d\xeb\xeb\x9d\x5e\x10"}, -{{0xa1,0xe4,0xfc,0xfd,0xe0,0x44,0xf1,0xbb,0x0e,0x7b,0xbc,0x63,0x1a,0x83,0x1a,0x8d,0x07,0xe9,0x0a,0xe0,0x8a,0x96,0x6a,0xd6,0x27,0xb6,0x20,0xb1,0xe2,0x8c,0x42,0xcf,},{0x25,0x56,0x0f,0x31,0x16,0x8b,0xd4,0xb7,0x25,0x52,0xed,0xed,0xd0,0x8b,0xb6,0xbf,0x79,0xa9,0x40,0x63,0xc1,0xf1,0xe1,0xd3,0x04,0x86,0x9d,0xd1,0xce,0x04,0x9b,0x95,},{0xc8,0x00,0x15,0x27,0xbd,0x90,0x2c,0x15,0xc3,0xdd,0x5a,0xe1,0x81,0x80,0x52,0x5b,0x5e,0x82,0x02,0xbe,0x66,0x71,0x1f,0x82,0x88,0x5c,0x82,0x22,0xa1,0x5f,0x06,0x00,0x92,0xa2,0xa6,0xe2,0xf7,0xd7,0xe9,0x80,0x31,0x12,0x09,0x19,0x1b,0x32,0xb8,0xad,0xe4,0x8d,0x3e,0xa9,0x8c,0xf2,0x45,0xf0,0xfa,0xd6,0x2c,0x00,0x9c,0x5a,0x71,0x08,},"\x8c\x14\x54\xd4\xe0\x8a\x14\x01\x64\x6b\xf7\xa8\x85\x9e\x8a\x14\x5e\x85\xee\xeb\x40\xdb\x38\xff\x01\x69\x70\x96\x41\x21\x2c\x81\xb6\x73\x90\x74\x9c\x01\xa7\x98\x07\xf3\xcc\xad\xbb\xd2\x25\x6f\x36\xff\xc1\x80\xcf\x9b\xa4\x4b\xf4\xa7\x61\x2d\x44\x1c\x23\xb2\xe2\x5d\x33\xc4\x8a\x73\xe1\x6c\xe3\x57\x56\x27\x58\xad\xb0\x05\x53\xc3\x14\x2f\xb8\x17\x6b\x6a\xe8\xfb\x61\x0a\x60\xf9\x23\xb0\x91\x18\x14\xb1\x0f\x56\x79\x93\x6c\x36\x77\xb7\x0e\x84\x6e\x21\x8f\x58\x75\x67\xf2\x01\x9c\x7d\x28\x2a\x10\x7f\x3c\xc8\x47\x63\xad\xae\xc8\x89\x93\xc0\xcc\x50\x03\xe7\x7a\xf6\x0d\x67\xdb\x53\xf8\xcb\x72\x7a\xa6\x67\x2d\xe0\x04\x49\x8c\x3b\x3e\x22\x2a\xa7\x08\x2d\x91\xf9\x8a\x1a\x06\x83\x74\xc5\x10\xff\x53\xa5\xe5\x59\xcb\xe2\xd6\xc7\xc3\x44\x2d\x72\x38\x90\x7c\x81\x1d\x58\xaa\x7f\x5a\x46\xb8\x31\x12\x44\xf0\xdb\xe1\xb9\xc0\xe9\x44\xdd\xa1\xd8\x01\x08\x64\x94\x9c\x59\x39\x6c\x6b\x34\x6a\x11\xf3\xaa\x86\x6d\x6b\xce\xad\xfc\x90\x90\x38\xd2\x2e\xfb\xc8\xf1\xda\xc8\x10\xa9\xf2\xfa\xfc\xce\x7c\x03\x89\xeb\x0a\x56\xc0\xf6\x8c\xae\x24\xae\x3d\xdb\xdf\xf7\x11\x6d\x2f\xad\xeb\x9b\x0e\x75\x09\x53\x6f\xdc\x3b\x83\xe7\x13\x54\xda\x6a\x1a\xed\x16\x88\x74\x90\xdc\x2f\x4d\xf5\x7b\xba\xa7\x24\x45\x28\xfa\x30\x94\xb9\x9e\x86\x75\x81\xac\xef\x90\x62\x70\xb2\xcf\x4d\xed\xa6\xb8\xfd\x9d\xbb\x79\xad\xd7\xbe\xa8\xf8\x6f\xcb\x1f\x64\xdf\xd5\x0e\x38\x5b\x42\x09\xec\x0b\x1a\x9f\x6d\x2e\x51\x90\x68\x29\x7a\x2b\x5c\x40\x5c\x21\x6b\x4a\x2e\xd9\x83\xff\x69\xc5\x9b\x53\x0e\xff\xa6\x0c\x03\x67\x05\x12\x67\xdd\x2b\xbd\x1e\x86\xa9\xab\x5a\x11\x4d\xd4\xf6\x9b\x54\x0b\xfa\xbf\xe9\x7c\x04\x03\xb8\xfc\xbb\x27\x62\x57\x61\xed\xa3\xe2\xad\x8e\x62\x5c\xfe\x4b\x61\x5b\x70\x25\x53\x1a\x49\x89\x18\xc2\x4e\x02\xa0\x0e\x79\x7b\xba\xfd\x14\xf9\xd3\xf6\x82\x7e\x39\x00\x63\xc4\x36\x08\x06\x88\xd0\x37\xa6\xe2\x99\x3c\x56\xd3\xa8\xe9\x5f\x37\x5c\x10\x04\x0b\xf0\x4f\x03\x0c\x97\x26\x23\xd9\xe3\x80\x1c\x13\xb4\xec\x8d\x01\xcf\x18\x38\x55\xf5\x93\x5f\x10\xdd\xb2\xc5\x4c\x51\xc8\x0c\xbe\xd0\xc2\x4d\xb5\x6e\x1e\xd1\x48\x93\x1d\x89\x16\x1c\x5e\xa3\x7c\x2f\x97\x87\xf8\x8e\xf7\x33\x0e\x5d\xcd\x0e\x43\xd8\x1b\xfc\x8b\xf2\x3d\xdf\x79\x83\xcc\x1d\x73\x38\x43\xa3\x3c\xcb\x39\x5d\xfc"}, -{{0xbe,0xd1,0xbb,0xca,0xe1,0x86,0x43,0xd6,0xf6,0xaa,0xc3,0x4f,0x3d,0x9b,0x6a,0x14,0x78,0x39,0x4d,0x02,0xb9,0x31,0xcf,0xf0,0x06,0xd8,0x5f,0x21,0xb7,0xdb,0xc7,0x47,},{0x4f,0x52,0x8b,0x38,0x18,0x5a,0x42,0x4c,0x6f,0xde,0xce,0x46,0x51,0x1a,0x0c,0x29,0xb7,0xc0,0x4b,0x32,0xeb,0x04,0x83,0xab,0xb5,0x2d,0x5f,0x8e,0xb6,0xb3,0x52,0xeb,},{0x0f,0xc9,0x9d,0xd3,0xb9,0xa0,0xe8,0xb1,0xfc,0x6e,0x63,0x5a,0xf5,0xc6,0x40,0x06,0xb6,0x72,0x00,0xfe,0x95,0x8f,0x53,0xcc,0xe1,0xb9,0xb0,0x91,0xa4,0xe7,0x06,0x69,0xb5,0x93,0xf1,0x55,0x94,0xbc,0x08,0x42,0xe5,0x57,0x62,0x59,0xf9,0xa6,0x85,0x9a,0x0d,0xb2,0x2d,0x74,0x0f,0x9f,0x80,0x24,0xb5,0xba,0xf1,0xef,0x6f,0x95,0x8c,0x05,},"\xff\x7c\x64\x13\xe6\x18\xa0\x56\xde\x40\x1e\xe1\x0c\x40\xad\xe3\xd7\xc0\xe6\x86\x14\x95\xd9\x7c\x26\x89\xec\x6a\xbb\x69\xdd\x2a\xe7\x01\xfd\xca\xc8\xf0\x83\x31\xea\x5c\x5f\x5d\x80\x5b\x57\x89\xee\x5e\x24\x1f\xf4\xac\x8b\x96\x0f\x4f\x2b\x9f\xef\x6a\x72\x7f\xad\x86\xdc\xd4\x32\xde\x9f\xad\x6b\xa4\x5e\x00\xaa\x36\x87\xb0\xce\xeb\x2c\x0d\x43\x0b\x7d\x5f\xde\x63\xb4\xf6\xb9\x82\xc4\xf9\xe0\x3c\x43\x0a\xba\xd9\x04\x4d\x06\xdc\x49\xe8\x9d\xf4\x81\x40\x5d\x8f\xeb\xbb\x06\x53\xe9\x68\x69\x48\xaa\xd2\xd9\x07\x25\x44\xdf\x94\x24\xfd\x48\x7f\x4e\x24\xba\x7f\x24\x55\xdd\xec\x41\x05\x82\x8c\x39\x81\xbd\xdb\xb1\xb7\xfb\xdb\xac\x15\x59\x03\xe9\x60\xfc\xd9\x4c\x07\x16\xe7\x36\xf5\x19\x86\x7f\xbc\x52\xc5\x12\x60\xf5\x71\xd7\xed\xcb\x08\x1a\x23\x55\x0a\xd8\xc7\x0b\xb2\x68\x86\x4a\xb2\x76\xaa\x2c\xc2\xdb\xf6\x23\x83\xbb\x66\x03\x0e\xbe\x94\x35\x41\x74\xcc\xec\x2d\x2a\x90\x75\x78\x55\x64\x44\x50\x7c\xbf\x84\x88\xbb\x23\xc6\x24\x23\xa3\xa9\x8d\xa7\xcc\x96\x8f\x59\x9d\x3d\xc8\x4d\xca\x3a\xfa\xd7\xf1\x4e\xc3\x06\xe1\xdb\x53\x41\x43\x21\x6a\xa2\x2a\xd1\x80\x74\xc7\x19\x57\x08\x05\xea\x46\xbc\x86\xb7\x1a\x8f\xf5\x8e\x41\xe7\x3c\xb2\x9a\xd5\x75\x0f\xcf\xc9\xa1\xc5\x42\x92\xb6\x4b\x47\xec\x95\x38\xf5\x38\x16\xe3\x6e\xd0\xd0\xc1\xae\x5e\xad\x06\xd4\x77\xaa\x97\x5e\xce\xba\xf6\x2d\x90\x23\xb7\x7e\x50\xe7\xb6\xd4\xab\xda\xa4\x85\xea\x34\xec\x76\x6b\xeb\x1d\x9b\xa0\x3c\x9c\x06\x71\x86\xe2\xe3\x82\x66\xc6\xe2\x53\x1e\x97\x48\x02\x14\x63\x8a\x2b\xb3\x14\x31\xac\x20\x86\x79\x71\x55\xfc\x77\x5b\x3a\xad\x8d\x5a\x0b\x90\x4c\x38\x1e\xdd\x0c\x6b\xc2\x3c\x66\xa1\x90\x49\x55\xed\x45\x0a\x9c\xbd\x16\x45\x9c\x32\xf5\xca\x35\x4b\xbc\x2d\xa7\xb1\xa4\xd8\x14\xf1\xb8\x71\x0a\xad\xb2\xcc\xc4\xf3\x97\x75\x8b\x7e\x9d\x91\xf3\xa9\x1e\x58\x25\xab\x86\x82\xff\x5e\x41\x70\x2e\x07\x84\x1a\xc7\x69\x8c\x3d\xa9\xf5\x58\xed\xd0\x1f\x86\xce\x2c\x50\x6b\xf4\xc2\x14\x9a\xc9\xc1\x95\xa5\x9c\x7d\xd7\xd4\xec\xf9\x3c\x90\xb4\x42\x3b\x43\x50\x58\x8d\x41\x67\x2c\xed\xc8\x51\x0a\x7a\xd5\x3b\x4b\x7e\xdc\xaf\x23\xe4\x3e\x05\x66\x9d\x27\xa1\xfe\x97\xb7\x87\x30\xd3\xfc\x06\x0b\xd4\xed\xd9\x87\x2c\xff\xb9\x62\x85\x35\x1b\xef\x14\x8e\xf7\x83\xab\x39\x21\x16\xbd\x7b\x90\x7b\xad"}, -{{0xc7,0x18,0x82,0x3f,0x43,0xdb,0x22,0x17,0xc6,0x6a,0xb2,0x89,0x97,0x04,0x16,0x5d,0x20,0x85,0x73,0xde,0x60,0xf3,0x3b,0xc0,0xb9,0x33,0x8d,0x88,0x0f,0x19,0x3f,0xb5,},{0x29,0x40,0xb8,0x79,0xb6,0x3f,0x2c,0xb1,0xf6,0xe3,0xef,0x9c,0x9d,0x33,0x3b,0xa9,0x17,0x70,0xfe,0x18,0xcc,0x5a,0x34,0x7f,0xdf,0x12,0xb0,0xef,0xc5,0xca,0x2e,0xc9,},{0x4c,0x9c,0xdb,0x1a,0xd4,0x65,0x09,0x56,0x0d,0x87,0x1d,0x30,0x89,0xaf,0xb8,0x73,0x46,0x48,0x20,0x1b,0x10,0xac,0xc9,0x53,0xe8,0xb6,0x1f,0x2c,0xce,0x2d,0xba,0xe0,0xfb,0x9b,0x86,0x8a,0xc9,0x57,0x43,0x2b,0x72,0x22,0xdb,0xf7,0xe4,0xcf,0x0b,0xc7,0x53,0x09,0xbe,0xa3,0x60,0xb2,0x63,0xab,0xbd,0xe1,0x88,0x53,0x2d,0xda,0x25,0x04,},"\x05\x0e\x68\x77\xf6\x5e\xc7\x26\xee\xc7\x01\x86\x3f\xab\x14\x0b\x99\x4a\xa1\xe9\x2a\x48\x7d\xb1\xa1\x87\x01\x31\x20\x57\xdb\x44\xbf\xde\x70\x91\x1e\xc2\x6e\xaa\x28\x63\x2d\x03\x79\x4d\x54\x5d\xfc\xb2\xae\xd4\x34\x0c\xab\x7d\x09\x25\x95\xcd\x59\xed\x23\x99\x40\x43\xf5\x0b\xa6\x96\xe9\x80\x2b\xd6\x49\x90\x12\x13\x97\x28\x64\x57\xae\x69\xd7\x6c\xb8\xe3\x4d\x7c\x1a\xb2\x45\xcb\x07\xb1\xb4\x08\xf2\xbb\xbf\xdf\x33\xa1\xbd\xd5\x59\x63\x67\x02\xc9\x18\xf9\x82\xc2\xac\x02\x21\xf7\xf9\x4d\xb9\x1e\xde\xfc\xe2\x81\x18\x25\x9f\x89\xd9\x94\xda\xd5\xbb\x01\x3c\x67\x8c\x1c\x33\x8b\x65\x39\x6b\x15\xe8\x89\x9c\x16\x99\x21\xf2\x78\x85\x9c\xe0\xc8\x56\xd8\x89\xb8\xc6\x34\x18\xeb\xc5\x73\xd2\xd6\x25\xd5\xb5\x93\x88\x39\xf2\xb1\x69\xb6\x91\x6d\x8e\x40\xdd\xe7\x0d\x3b\x72\x88\x7a\xd2\x47\x8e\xf6\xfb\x12\x84\xfa\x0e\x4f\xc5\x24\xe3\xc6\xfa\x1d\xd2\x2b\xa6\xb8\x1d\xef\x82\x79\xf3\x82\xbc\xb4\x50\x48\x85\x1b\x17\xcd\x65\x9d\x59\x40\x9f\x57\x1f\xa8\xa9\x20\xa2\x09\x34\xd9\xdb\xe1\x02\x2d\x63\x58\x40\x96\x54\x00\x24\x0f\x87\x0a\xce\xff\xd5\xdb\x7c\x7d\xf0\x8a\xf8\x9e\x47\xe1\xb9\xe2\x0b\xb9\x9f\x96\xab\x07\x3e\xdf\x53\x69\x4c\x74\x82\x89\x0e\x36\x31\x34\x02\x17\xe6\x87\xab\x27\xc9\x84\xb6\x08\x25\x16\x94\x57\xd4\x35\xa5\x40\x9a\xd8\xe4\x2d\xa0\xaa\x63\xe2\x0c\x2b\xc6\x7b\xd8\xb9\xa2\x67\xf3\x96\x73\xa7\x7f\x7f\x31\x36\xdc\x5c\xb2\xd2\x49\x48\xdb\xe7\xbc\xd7\x12\x93\x18\xc6\x8c\x6f\xe9\x5d\xd4\xdd\x4f\xe9\x42\x28\x68\x31\xea\x53\x35\x2f\xbb\x25\x2a\x12\x88\xbc\xd8\x38\x92\x13\x56\x78\x5d\x07\x21\x34\xcb\x82\x0f\x62\x79\xcc\x71\x46\x1f\x43\x1b\xe9\xd3\x01\x47\x24\x32\x1c\x92\xfd\xc5\x76\x32\x01\x37\x70\x5c\xff\xb2\xc2\x36\x64\xb7\x05\xe9\xbe\x60\xae\x1a\x19\x0f\x3e\x34\x84\xf7\x00\x58\xe7\x02\x40\x7b\x05\x6d\x7f\xe5\xd3\x1c\xee\x9c\x2a\x6a\xc6\xea\xda\x35\x16\xab\xc5\x51\x72\x56\xdf\x12\x43\x78\x0a\x03\xbb\x00\xba\x00\xce\x24\x80\x76\xee\xca\x6f\xee\x91\xd5\xef\x9e\xb9\x07\xb8\x01\xaf\x09\x7f\x3e\x9e\xb2\x56\xbd\xcd\xe8\x1e\xfe\x4b\xaf\x81\x89\xb0\x39\x9e\x36\xf1\xea\xa3\xab\x62\x66\x17\xcf\x3b\x47\xdd\x89\xca\xf6\x9c\x64\xc5\xb8\xf6\x8b\xd9\x17\xfe\x03\xe4\x66\x85\x38\x46\x0a\x1b\xe8\x8d\x9a\x84\x6c\xef\x39\x93\x46\x27\xd4\x74\x73\x4f"}, -{{0x25,0x43,0xd1,0x66,0xc9,0xf5,0xf7,0x42,0x7f,0xf3,0x03,0x4f,0xfa,0x81,0x03,0xcb,0x11,0x7b,0xf4,0x72,0x33,0x1a,0x73,0xd9,0xa2,0xf1,0xbc,0x0a,0x02,0xa6,0xff,0x1b,},{0x42,0x67,0x8c,0xf3,0x85,0x70,0x21,0xaa,0x55,0x67,0x70,0x6d,0xb0,0x31,0xe7,0x92,0x71,0x5c,0xca,0xf8,0xab,0xb0,0x2a,0x04,0x2b,0xad,0x17,0xdb,0x3d,0x5f,0xa1,0x03,},{0x20,0xea,0x93,0x68,0xa2,0xcc,0xd0,0x8b,0xf9,0xcb,0xf4,0x8d,0x4a,0x2f,0x7d,0x03,0xf0,0xdb,0x08,0xa5,0x4b,0x87,0x67,0x9c,0xda,0x03,0xe2,0x96,0xaf,0x9e,0xf3,0x78,0xbe,0x9b,0x8f,0x04,0xb4,0x06,0x5b,0x00,0x9d,0xa6,0xdb,0x01,0x6f,0x3d,0xf9,0xdb,0x64,0x82,0x58,0x73,0xe2,0xfb,0x4d,0xe3,0x04,0x49,0x91,0x5c,0xd7,0x3c,0x46,0x09,},"\x74\x6d\x7a\xbf\x0b\xfb\x26\x62\xc2\x5a\xb5\xc5\xe4\x61\x2c\x30\x6f\x16\xd1\x3e\x44\xd0\xdb\x39\x4a\x00\x15\x67\x6c\xe6\x09\x78\x4f\x03\x23\xda\x1d\xfa\x94\xd2\xb2\xf1\xf6\xe0\x24\x44\xa9\x36\xd0\x19\xb1\x43\x02\x1f\x73\xc7\x9d\xf9\x30\x9e\x7b\xdf\xf3\x9d\xae\xec\x4c\xac\xa0\x0c\xba\x4e\xf3\x1c\x83\x10\xc1\xa0\x8e\xf4\xb3\x6f\x81\xc3\x77\x84\x6b\x5b\x90\xac\xd4\x11\xaa\x67\x1e\xd7\xaf\x27\x8a\x24\x22\x9b\x78\x93\xc1\xb4\x15\xd7\x98\x88\xd7\x63\x7f\x5c\xb5\xc9\xc6\xc6\x31\xae\x5f\xfa\x29\xf1\x34\x0e\x44\x40\x96\xab\x53\x36\x17\xfd\xcb\x80\xff\x81\xda\x0a\x7c\x6c\x14\x2e\xe0\xfe\x5e\xa8\x2f\x68\xcc\x3e\xa3\x8b\x56\xf2\x72\xb0\xd8\x0f\xd5\xf4\xf5\x5c\xa9\x34\x8c\x16\x18\x81\x43\x58\x13\xc3\xfa\x9f\xff\x66\xa2\xee\x6d\x5b\xd3\xed\xba\x0d\x2f\x9a\xa7\x4b\x1c\x44\xbf\xd0\xe6\x46\x78\xd3\x71\x51\x24\x96\x3a\xc5\x75\xff\xb0\x9e\xe1\x64\x37\xda\x48\x4b\x3b\xa5\x8e\x5a\xeb\x8e\xd8\xc5\xc0\xf4\x7b\x59\x90\x8f\xe5\x80\xf3\x7e\xc1\xde\x26\x6b\x29\x5d\x6b\xe8\x5e\x62\x35\x8e\x9b\xbd\xc7\x89\x64\xfb\x83\x7e\xea\x29\xfd\xb7\xde\x86\xcc\x56\xf4\x8b\xd9\xa3\xe6\xe2\xbe\x51\xd8\xa1\xdc\xff\x3c\xa4\xd5\x6e\xa9\x34\xc6\x82\x77\x2b\xca\xfb\x51\x49\x7b\xe5\xd0\xf2\xa2\x3d\xd4\x97\x0c\x02\xc4\x4c\x09\xad\x89\x7b\x42\x41\xac\xd7\xd6\xab\x12\xd8\xf0\x0c\x9a\xad\xc3\x34\xb4\x31\xfe\xc5\xbb\x69\xa2\x85\xb7\x55\x0a\x63\x9e\xce\x96\x95\x26\x82\xb7\x33\x4b\x68\xc6\x51\x52\xe8\x93\xb1\xc8\x10\x0c\x69\x4d\x8c\x5c\xfe\x26\xac\x03\xc1\xf3\x91\x4e\x65\xc8\x4f\x0e\x77\x72\x90\xc7\x6f\x6a\xcc\xe3\x40\xbf\xf6\x6d\xa7\x22\x0f\x73\x17\x5e\x94\xaf\x52\xf9\xf1\x9e\x61\xf8\x0d\xc1\xf3\x57\x16\xb3\xf4\x8d\xfa\x50\x25\xc9\xeb\xef\x73\x82\xe0\x55\x83\x0f\x5b\xbf\x15\xc6\xf6\xa9\x50\x32\x90\x9c\x89\x2c\x0f\x89\xc8\xc1\x5f\xc3\xea\x40\xa2\x0e\xe1\xa4\x52\x9b\x52\x19\x51\xdf\x44\xd9\xd7\x9d\x74\xe0\xc4\xc2\xe0\xfe\xd8\x49\xb8\x78\x52\x06\xdb\xe6\x2b\xfa\x2c\xa2\x10\x87\xa9\x12\xe9\xb1\x84\x55\x16\x59\xcd\x8a\x58\x7e\x95\xb0\x43\x17\x19\x25\x96\xbb\x0b\x7f\xc9\xf7\xbb\xb6\xee\x04\x9c\x8b\x02\xfd\xd7\x58\xb4\xe7\x98\x82\x07\x3b\x71\xea\xab\x18\xaa\x29\x37\x01\xc1\x7d\x55\xf9\xec\x46\xc5\x2d\xe1\xe8\x86\xb6\x75\x0f\xb0\xfb\xcd\x64\xf4\x56\x8a\x21\x0a\xe4\x51\xe9"}, -{{0x85,0xe0,0xa8,0x0f,0x3b,0x30,0xc2,0x01,0x99,0xd9,0xc1,0xec,0x66,0x2e,0x39,0x2f,0xdf,0x15,0x46,0x37,0x73,0x43,0xf1,0x24,0x71,0xdb,0x2a,0x03,0x10,0xa7,0x05,0xbd,},{0x54,0x0a,0x3a,0x1d,0x83,0x67,0x2e,0x49,0x50,0x34,0xcf,0xf4,0x08,0xe1,0xfb,0xe8,0x2e,0x53,0x8f,0x09,0x17,0xe8,0xa1,0xc7,0xd1,0x7a,0xab,0x58,0xe0,0x43,0xd3,0xc6,},{0x18,0x5e,0xf2,0x24,0x6a,0xba,0x2b,0x1a,0x56,0x80,0x32,0xc7,0xdf,0x93,0xc6,0x67,0x79,0x9b,0x8a,0x52,0x1a,0x6f,0x97,0x32,0x1e,0xad,0x58,0x66,0xb4,0xcb,0x9c,0x65,0xb6,0x4a,0x1c,0x40,0xb9,0xb6,0xa9,0x10,0xe7,0x42,0xdc,0x32,0xa7,0xe6,0x6d,0x11,0xea,0x45,0xdb,0xea,0xac,0xae,0x9f,0x09,0x51,0x1b,0x81,0x01,0xf8,0xaf,0x0c,0x0c,},"\xd2\x80\x2f\x15\x96\xf8\x38\x3b\x64\xed\xbd\xc5\x94\x06\x0b\xff\x0e\x70\x13\xd5\xb7\xc8\x5d\x83\x0f\xae\x11\xae\xb3\x4d\xd5\x94\x95\x9d\xa6\x24\xe0\x44\x47\x4c\x54\x09\xc0\x05\x96\x73\xbd\xc6\x1a\x67\x1e\xf5\xb0\xb8\xa2\x6f\x30\x10\x0b\x3b\x73\x96\x8d\x8e\x4d\x83\xa7\x2f\x25\xb5\x13\x44\x8d\x2f\x6b\x6a\x44\x75\xfd\xf8\x9e\x31\xca\x92\x68\xa3\x07\x05\xaf\x3f\x64\x9e\x3f\xe0\x1d\xde\x0c\xf4\xb2\x9e\xc2\xda\x54\x36\x44\x4a\xf0\x91\xd6\x27\x30\xac\xd4\xca\xb6\x08\xf0\xdf\x26\xf0\x88\xc6\xb9\xb9\x67\x37\x94\xf0\x74\x7d\xab\x2c\xe1\x90\xf9\x05\x92\x00\x9f\xdc\xe5\x46\x4b\x36\x61\xb7\xe8\x62\x0b\xad\x65\x50\x9a\x6c\x75\x2b\x72\x7a\x8d\xc8\xd3\xef\xa5\x84\xfd\xe0\x27\x2c\x45\x1d\x65\xa9\x3b\xec\xe4\xf5\x9d\x87\xdc\x6f\xbe\xb4\x51\x40\x1e\x3e\x2e\x00\x3c\x6a\xca\x7b\x3d\x3f\x92\x71\x91\x50\xc6\x77\x8f\x01\x5a\xff\x2a\x59\xbf\xbf\x2e\x91\xb2\x1b\x0a\xd6\x87\x75\x36\xeb\x54\x56\x70\x59\xf5\x87\xf5\x4d\x4e\x2a\x6f\xe1\xfd\xcd\xd6\xa7\xfd\xcb\x85\x15\x57\x5b\xcc\x37\x05\xd7\x78\x59\x35\x2f\xa0\xb0\x44\x16\x6e\x3c\x31\x88\x46\xa5\xdf\x33\x56\x30\x03\xcb\x20\xbc\x94\x2d\x30\x39\x10\x93\xe8\xd5\x83\xe8\xe6\x4d\xec\x57\x0e\xe1\xc4\x13\x87\x62\xf6\x48\x38\x98\xd3\x2e\x20\x32\xbd\xe9\xbb\xe0\x7e\xc2\xc3\xeb\x47\xd9\x68\x76\xf0\xfc\x0f\x02\x4d\x75\x3c\xeb\x34\xff\x84\x80\xb4\xcf\x57\x62\x30\xbb\x82\x63\xdd\x80\xee\xac\x66\x2e\xba\x31\xd8\xa6\x1f\x30\x9e\x17\x5f\x4c\x01\x43\xe2\x8a\x85\x2b\x1c\x30\x61\xce\x78\xef\xbd\x16\xa2\x87\x3d\xd2\x81\x98\xa4\x6e\xc0\xa8\x00\xb3\x0d\xc8\xa9\x3b\x8d\xbb\x81\xa7\x30\xde\x45\x0b\x86\x4d\xea\x76\x80\xe5\x09\xd8\x00\xe8\x23\x29\xc2\x61\xb0\x7e\x72\xaa\x80\xee\x16\xec\x37\x5d\xdb\xbb\x6f\xe3\xd8\xd4\x7b\x0e\x3c\x5a\x9f\x23\xc4\xd2\x0b\x72\x4c\x1d\xf5\x98\x35\xd8\x30\xdd\x22\xd1\x04\x03\xd8\xf1\x5c\x10\x2c\x4b\x37\x69\xc4\x16\x66\xc3\xab\x8c\x7e\x80\xb9\x40\xd0\xbb\xb5\x86\x52\xd1\x0a\x3f\xfe\x8d\x44\xdf\x10\x12\xa3\xdd\xc4\xe1\xc5\x18\xd4\x90\x19\xf7\xc5\xd3\xd9\xf9\x5e\xd9\x3a\x31\x97\x46\xd1\xe5\x43\xff\xa6\x9e\xdb\x49\xbb\x34\x39\xf8\xa3\x25\xac\x6a\x0c\xb4\xed\xd6\x5b\xa6\x00\x80\xa0\x44\x7c\x67\x4f\xaa\x72\xd8\xae\xbd\xb5\xd2\x54\x4f\x2f\x2d\x84\x7c\x72\xc2\xdf\xa6\x05\x7a\x69\x0a\xdc\x5c\x44\x1a"}, -{{0x82,0xa2,0xc6,0x49,0x3f,0x11,0xba,0x80,0xe4,0xb8,0xb3,0xb4,0x38,0x41,0xbe,0x97,0x0e,0x2a,0x10,0xa9,0x4d,0x22,0x49,0xd8,0xac,0x6f,0x54,0x14,0xcf,0x5a,0x3c,0xb5,},{0x4c,0x2e,0xe0,0x1c,0xde,0xa0,0x7d,0xb3,0x63,0x5f,0x5d,0x4c,0x10,0x82,0xb9,0x2f,0x29,0x8d,0xeb,0x17,0xd0,0xf9,0x05,0xdf,0x71,0xb6,0x6f,0xb2,0x27,0x4e,0xae,0x99,},{0x68,0xa9,0x1d,0x4f,0x8d,0x24,0x1c,0x1d,0xef,0xbd,0x5c,0xa9,0xe9,0xe1,0xed,0x82,0x74,0x41,0x95,0x06,0x75,0x1c,0x96,0x79,0x47,0xb1,0x0d,0x50,0x11,0x8b,0xbf,0xab,0xc7,0x65,0xff,0xd7,0xb3,0x1a,0x01,0x67,0xc4,0xfd,0x8b,0x11,0x75,0x33,0x24,0x12,0xdf,0x19,0xd8,0xaa,0x1a,0x90,0x95,0x90,0x86,0x13,0x20,0x92,0x3d,0xbc,0xb2,0x04,},"\x09\x85\x4d\x13\x68\x49\x50\x41\x9e\x0b\xb1\x64\x64\xe0\x99\x88\x90\x5c\x02\x17\x18\x3a\xa1\xe4\x8a\xdb\x14\x7b\xfc\xc2\xeb\x57\xc2\x30\x0b\x0d\xfc\x39\xd4\x89\x66\x55\xa5\x7a\xe2\x04\x15\x40\x8b\xb5\xf2\xc2\x38\x01\x39\x55\xf0\xa4\xfc\x78\x2e\x0c\x99\x3f\xe4\x2c\xb0\x8c\xd8\xcf\x41\x5c\xcb\xd6\xcf\x1c\xee\x2e\x80\x97\xf0\x4e\x8f\x09\xae\x5d\xa5\xf4\x15\xb1\x6c\x2c\xb3\x0c\xb2\xab\x66\x52\xba\x50\xeb\xbc\xae\x4a\x59\xe3\x1f\xe1\x1e\x7e\xf3\x69\x9c\xa9\x0a\xaf\xa5\x86\xbb\x24\x2c\x89\xcd\x2e\x33\x2b\x2b\xfa\x2f\x81\x42\xac\xca\xf4\x36\xf8\x9b\x64\x53\xbb\x48\x05\xa1\xe7\xf3\xab\x62\x70\xf0\xda\xf8\x93\x89\xe7\x17\xd1\xb7\x01\x75\xec\x57\x07\xc8\xf5\x12\xc4\x0a\xb9\x24\xc4\x57\xe9\xf0\x91\x47\x91\x75\x0d\xc2\x92\xbb\x27\xd6\xf6\x3b\xa8\xcc\xf5\x4b\x90\xd3\xeb\xa7\xf1\x9e\xb3\x00\xd9\xeb\x8f\x3b\x72\x03\x2b\xa9\x30\x37\xf5\x52\xb4\x09\xb5\x80\xa5\xf6\x51\x16\xfa\xff\xe0\xfd\xfd\xc6\xdb\x38\x81\x38\x6c\x3c\xbc\x16\xb6\x7e\xb2\x57\x63\xd7\xae\x3a\xac\x0b\x85\xaa\x1e\x9a\xa2\x2e\x49\x59\x60\x9d\x43\x81\xe4\xb6\xd7\x15\x9f\xf3\xe3\xb2\xd3\x7b\x64\x0f\x88\xcf\xbe\x4f\x8a\x77\xf8\x01\x64\x57\x22\x8b\xa6\xd3\xaf\x5c\x4e\x33\x12\x5d\x48\xbc\xfc\xf3\x67\x8c\x16\x3b\x69\x8e\x52\xe8\x56\x17\xab\x1a\x75\xff\x20\xc6\x90\xab\x07\x15\x5e\xe7\x57\x59\x85\x78\x07\x2d\x4a\x09\xdf\xc6\xc6\xc0\x94\xec\x04\x85\x67\xd5\x13\xce\x2b\x18\x34\xe1\x63\xdf\x15\x45\x31\x9d\x80\x61\xe0\xe5\x7f\x58\xef\x04\x1b\x7b\xff\xc4\x96\x6a\xc1\x66\x03\x31\xb9\x7a\xbb\xc9\x7b\xe2\x1a\xe2\xbc\x58\xc6\xc3\x27\x4a\x8a\xda\xd5\xfd\x2c\x3b\xc1\x6b\x92\xe1\xf8\xde\x87\x7b\x6a\x26\xf0\xc6\xab\x71\x62\xe8\xaa\xb9\x3a\xf8\xd8\x59\x18\xc1\x3d\x3e\x23\x5a\x27\x37\x48\xc6\x2f\x0d\x22\xcb\x1c\x93\xe1\x34\xa4\x95\xb1\xb5\xef\x8f\x1a\x11\x34\x51\x2d\x53\xb7\xa2\x11\x26\x31\x77\xf7\xa6\x0b\xdf\x47\x46\x91\xf2\x24\xa3\xb5\xba\xc4\x00\x6d\xb3\x45\xca\x67\x25\xf5\xee\x70\x3e\xca\x0d\xea\x10\xd7\x12\x67\x6f\x63\xef\x3e\x53\x7e\x63\xab\xd2\x60\x8c\xb4\xfb\xe2\x00\xe1\x5f\x18\x20\x91\x53\x49\x60\x72\x90\x80\x44\xc9\x5a\x4e\x9c\x53\x56\xaa\xe8\xed\x5f\x09\x59\xea\xc0\x91\xe2\x27\xa0\xb8\x1f\x58\x03\x27\x6b\x3b\x3b\xf4\xb6\x86\x5a\x55\xfc\x67\x82\xf6\x2e\xa6\xd6\x39\x90\xf9\xbe\xfe\x01"}, -{{0xe5,0x5b,0x34,0x3a,0x0f,0xa1,0xfb,0x74,0x71,0x89,0xcb,0x00,0xdb,0xc3,0xa6,0xaa,0x2d,0xcf,0x5b,0x86,0xe5,0x7d,0x76,0x93,0xf3,0x07,0x42,0x03,0x89,0x76,0x11,0x53,},{0x23,0xa1,0x44,0x60,0xea,0x98,0x3c,0xf9,0x97,0xc7,0x82,0xeb,0x45,0x82,0xab,0x3c,0x8a,0xa6,0xdd,0xe5,0x33,0x25,0xb9,0x77,0xb7,0x8e,0x33,0xd2,0xdc,0x5f,0x27,0xaa,},{0x07,0x26,0x6c,0x18,0x65,0x0e,0xcf,0x06,0x32,0xe2,0x25,0x62,0x4e,0xc4,0xc9,0x7f,0xc3,0x87,0xdc,0x37,0x46,0x87,0xa6,0x19,0x56,0xdc,0xcc,0xe7,0x28,0x94,0xee,0x13,0x8a,0xab,0xc8,0x0c,0xfc,0x90,0xc9,0xee,0xa6,0xdd,0x4c,0x59,0xaf,0x45,0x02,0xee,0x29,0x63,0x5a,0x92,0x88,0x07,0x86,0x67,0x8b,0x14,0xa3,0x93,0x1a,0x69,0xf9,0x07,},"\x36\x28\x9b\x5e\xaf\xf2\xa8\x5a\x7c\x6d\x57\x5b\xd1\x5e\xa5\x94\xb2\xfd\x85\x10\x87\x4a\x46\x9b\x52\x10\x91\x63\x69\x6d\x85\xb6\x8c\x5b\x21\x1d\x29\x64\xef\xdc\x66\xe6\x25\xab\xe8\xaa\xfe\x4c\xd9\x22\x0c\xdb\x34\x11\x07\xff\xa8\x27\x6e\xd4\xb3\x70\xfe\x37\x6c\x14\x82\x68\x71\x67\xdb\xc8\xf7\xb2\x05\xa3\xf3\x30\x1a\x16\x64\xd9\x07\x28\x77\xd9\xf9\x8b\x8f\x69\x83\x13\x01\xdf\x99\x94\x71\x7f\xc8\x89\x69\x24\x23\x91\xd9\xb0\x51\x7d\x6e\xfb\x27\x17\x01\xea\xb3\xf4\xa9\xb1\x20\x42\x13\xe8\xcd\x13\xf9\xd0\x99\x04\x8b\x82\x07\x56\x2f\x2e\x4e\xbc\x65\x3c\xc6\x5e\x9d\x55\x12\xd6\x5b\x41\x02\x2c\x79\xb4\xeb\x37\x29\x87\x69\xae\xaa\x6e\xfe\xd6\x9e\x9a\x8c\xb4\x45\xc7\x01\x22\x74\xde\x62\xf5\x09\xf4\xe4\x81\x4a\xdc\xbf\x44\x53\xb4\xfa\xb8\x5d\x7c\x8f\xd8\x45\xe0\x08\x30\xef\x5b\x7b\x1e\x63\xc6\x76\x13\x98\x4c\xae\xfe\x91\x5a\x54\x8e\x18\xe5\x05\x62\x2c\xb2\xb3\x92\x99\xf4\x27\xf4\xd8\x39\x83\xba\x2a\xa0\x0d\x53\xbe\xe1\xf5\x9a\xec\x83\x18\xc5\xea\x34\x5d\x29\x42\x52\x36\x97\x92\x76\x2a\xdd\x3e\x56\xfc\xfa\x6e\x77\x97\xf0\x28\xc7\x99\x47\x90\x45\xed\xb2\xe2\x05\xeb\x6d\xd6\xca\x04\xee\xe5\x6f\x94\x96\xd2\xbf\x26\x09\x93\x57\xc9\x73\x83\x5b\x99\x36\x02\x49\x11\xe4\x65\x5d\x3e\x22\xc8\x11\xc8\xd4\xdb\xd1\xb0\x4f\x78\x97\x3f\x07\x75\x23\xa3\x89\xb6\xf2\x8f\x6f\x54\x21\x61\x42\xcb\x93\xe3\x3d\x72\xb4\xa5\x05\x2d\x27\xe4\x91\x1e\x41\xe6\xce\xc7\xbe\xbe\x1b\x0a\x51\x13\xe6\xb7\x0b\x47\x9d\x2a\xbe\xed\xf6\x9b\x75\x64\xe5\xa5\x73\xb3\x52\xd1\x6c\xec\x89\x07\x01\xbb\x38\x3d\x3f\x66\x56\xed\xa0\x89\x2f\x8c\xcc\x70\x94\x0f\x62\xdb\xe5\x28\xa6\x5e\x31\xac\x53\x88\x26\xc1\x38\xac\x66\x52\x4e\x33\x16\x37\xba\x2d\x37\x73\x03\x58\xe6\xc7\x32\xcf\xf8\xfe\xe9\x40\xaf\xd2\x2c\x39\xae\x38\x1e\x5d\x88\x26\x73\x9b\x23\xfd\xc1\xb8\x0a\xea\x5a\x62\xa2\xcf\x0f\xf1\x52\x5e\x44\x6c\xf3\x10\x46\x19\x50\x51\xd5\x85\x03\xee\xd1\xbe\xfd\x79\x3e\xea\xe1\xd5\xd1\xb6\x2a\x5c\x98\x45\x15\x7a\x09\x5c\xdc\x08\xa1\xd7\x7b\xa4\x7e\x84\xa5\xa7\x39\x98\x0f\x0f\x5b\xe7\xaa\xec\x9a\x21\x5b\x20\x4b\x4b\xb7\xcb\x1b\x38\x6d\xed\x58\xd7\xaa\xf7\x28\x53\x41\x90\x7c\x63\x33\x6e\xe3\xe6\xef\x07\x7a\xd1\x11\xb9\x74\xe7\x50\x4b\xd9\x89\xf5\x66\xfd\xa1\xb1\xb5\x9a\xba\xa9\x1c\x78\xbb\x40"}, -{{0x39,0x73,0x03,0x8f,0xa2,0xef,0x6a,0x27,0x8d,0x3c,0x1c,0xff,0x9a,0x22,0x56,0x69,0xe4,0x65,0xa6,0x9d,0x07,0x50,0x50,0x3d,0xe7,0x48,0xc0,0x02,0xdb,0xf9,0x27,0x8a,},{0xc7,0x5e,0x77,0xc7,0x81,0x49,0xd9,0xd2,0xdb,0xc2,0x63,0xdd,0xf8,0xac,0x4d,0x65,0x4d,0x1f,0xf4,0x55,0xcb,0x18,0x97,0xe1,0xc3,0xce,0x31,0xb9,0x4c,0xfe,0x32,0x10,},{0xfc,0x0c,0x54,0x53,0x83,0x9e,0xa9,0x92,0x96,0xff,0xfa,0x50,0x1d,0x58,0x36,0x66,0x28,0xdf,0x89,0xf6,0x16,0x76,0x69,0x42,0xd5,0x04,0x0a,0x05,0x60,0x56,0xda,0xb1,0x8b,0x44,0x05,0xc0,0x4a,0xbf,0x90,0x59,0xc3,0x08,0x68,0xd7,0x9c,0x93,0x6c,0xcc,0xc8,0x4c,0x4f,0xbd,0x6f,0xd3,0x0b,0x60,0xf8,0xbc,0xbd,0x7a,0x66,0x40,0x42,0x02,},"\x33\x92\xe0\x2f\x3c\x84\x66\x1e\xaf\x81\xa5\xff\x04\x35\x7f\x21\x2e\x92\x36\x1c\x5c\x22\x07\x39\xd9\x6b\x4d\x3d\x9c\x22\xd1\x8d\xf4\x8b\xe6\xb5\x51\x26\xf5\x81\x60\x1f\xfe\x0d\xa6\x3f\x38\xe1\x9c\xbb\x12\x72\x6c\xa0\xa6\xaa\x32\x55\x67\xa0\x03\xa7\x84\x9d\x06\x78\x39\x92\xeb\x9e\xb9\x28\x53\x29\x7d\x72\x28\xdb\xa9\x80\xb2\x50\xbb\x11\x0f\x63\xd0\xb8\x46\x70\xe5\xec\xb3\x19\xcb\xfd\x61\x27\x8f\x1f\x4c\xab\xf1\xfc\xb3\xf7\x01\xf1\x2f\x6e\xf8\xd3\xcc\x42\x82\xfc\xbe\x58\x9e\xb5\x65\x95\x03\xa2\xdd\xd8\xbb\xa3\x8e\x5e\xff\x09\x2d\xfa\xf5\x39\xfd\x80\x4f\x21\xf7\x3a\x90\xad\xf5\x69\xa0\x0b\xf9\xd2\x5a\x9a\xd3\xa6\x33\x09\xcc\x60\x93\x14\x24\x71\xa4\x78\xf0\xb8\x99\x22\x86\xde\x02\x3c\x68\xef\xd4\x99\x87\xec\x27\x0b\xd9\x46\xf6\xdb\x48\xf6\x84\xf1\xc2\xad\xee\xe2\x6d\x68\xdc\xe9\x5a\x55\xe4\xcb\x27\xbc\x60\x52\x30\x80\xdf\x6b\xa2\xb1\x99\x99\x6b\x1f\x1d\xa6\x92\x0d\x15\x59\xf7\x9b\xfd\xe9\xfa\x1a\x02\xde\xae\x14\x80\xc7\x6f\x94\x7f\x9d\x21\x3f\xc4\x3b\xb2\x88\x0a\x1b\x4d\x03\xbb\x14\xf5\xb0\x44\xa0\xfd\x83\xce\x04\x92\xf4\x9c\xa3\xaf\x25\x21\x1b\x86\xfa\xa5\x73\x5a\xd7\xfe\xaf\x31\xa1\xa7\x49\x1e\x70\x8b\x41\x82\x9d\x68\xe3\x24\x14\xf6\x83\x52\xb7\x1d\x1c\xd2\x3c\x8e\x12\xfb\x02\xda\x71\x14\x84\xf6\xef\x97\x52\x8a\x00\xd2\x4f\xcf\x91\xd4\xe0\x6e\x9b\xad\xae\x9a\x44\xdb\xdb\x3f\x77\x80\x41\x76\x8d\x86\x37\x04\xd7\x36\x81\x04\x00\xe7\xf2\x93\x1e\xfb\x85\xc8\x72\x4a\x59\x34\x26\xaa\x2a\xf1\xec\x5b\x66\x4f\x85\xc2\x25\x48\x96\xfd\xcf\x31\x6d\xb0\x92\x4e\x11\xaa\xe8\xd6\x83\xe9\xa0\x21\x92\x9d\x0a\x9d\x6f\xec\xb4\x59\x4b\x1b\x3f\xbc\x16\xb1\x76\xd2\x9d\x1e\xfb\x18\x19\xa4\xa4\x23\xfb\xe0\xca\x05\x59\xc5\x7e\x9e\x54\x49\xf1\x4b\xce\x91\x36\x0d\xaf\xda\x6a\x42\x7c\xe4\xa0\x99\x3d\xd0\x30\x82\xdd\xee\x06\x65\x33\xf6\xd3\xbd\xa5\x66\x0f\x42\xfd\x77\x57\x69\x0d\x67\x05\x98\xec\x70\x96\xf4\x75\xa0\x1a\x51\x99\x50\x34\x1a\x83\x1f\xc9\xa2\x81\xc0\x94\x7a\x86\x3f\x1f\x6e\x03\xbb\xa7\x74\xde\x77\xad\xc2\x3f\xbe\x52\x5c\xae\x6c\xcc\xe4\x7a\x0e\xc4\x97\x9e\x8b\xec\x86\xf3\x32\xfc\x6a\x57\x36\xe3\xb9\x8f\xb3\x32\xe9\xe8\x24\x4e\x68\xa1\x00\x45\x5e\x64\x99\xba\x8d\xba\xe9\x8b\x92\xba\x3d\x9c\x6b\x4f\xf9\x80\x34\x3e\x4c\x8e\xf4\xd5\xa4\xaa\xcf\x8b\x1a"}, -{{0xc7,0x1c,0xc1,0x0a,0xd2,0xd4,0x43,0xe0,0x25,0xad,0x06,0x25,0x68,0x6b,0x12,0x35,0x03,0xe5,0x90,0x19,0x3a,0x2b,0xc8,0xcc,0x57,0xa7,0xb9,0xb4,0x15,0x8d,0xe6,0xcb,},{0xfc,0x06,0xac,0xaa,0xb5,0x3a,0xd0,0x8e,0x97,0x62,0xdd,0x11,0xcd,0x21,0x22,0xb3,0x15,0x99,0xbd,0x25,0x98,0xce,0x6f,0x24,0x87,0x95,0xe7,0x32,0x21,0x9c,0x2f,0xc7,},{0x2e,0xb3,0x3b,0xc2,0xd5,0xde,0xb7,0xf3,0xa2,0xdc,0xc3,0x77,0xb0,0xc6,0xa8,0x62,0x13,0x4b,0xf3,0x19,0x1e,0xc4,0x0f,0xc1,0x28,0xac,0x28,0xab,0xf2,0x31,0x6e,0xf1,0x40,0x16,0x49,0xb8,0xf4,0xcf,0xa1,0xa9,0x36,0xde,0x79,0xb5,0x32,0xdc,0x04,0x3b,0x6d,0x36,0x02,0x4b,0x4c,0x37,0xbb,0xa2,0x92,0x90,0xac,0x9f,0x44,0x9b,0xa6,0x0d,},"\x2e\x08\x46\x53\x6d\xc6\xcc\xe1\x9c\xcf\x82\xdc\x2d\x0c\xd2\x1b\xd4\xe1\xca\x7b\xc3\x17\x06\x7a\xf8\xd9\x0e\xe4\x81\x8c\x85\x18\xbc\x3e\xf9\x60\xce\x11\x2a\x41\xd2\xb9\x97\x9a\x28\x2a\xe1\x3d\x70\x6a\x00\x5e\x00\x34\xf0\x6b\x39\xff\x4b\x0a\x5a\xfa\xed\x70\xb5\x61\xbc\xce\xb1\xbb\xd2\xec\x19\xf9\x74\x48\xea\xed\x4b\xe6\x20\xe3\x6a\x96\x2d\x87\x8c\x6f\x80\x17\x2b\x9f\xad\x43\xee\xd0\x7f\xf9\x3d\xb9\xb9\xca\x22\x62\xd5\xa3\xc2\x29\xc5\x4e\x30\xa4\x5e\x73\x66\x08\x92\xf0\x48\xe3\x63\xf3\x71\x44\xed\x19\x21\xf7\x29\x92\xb4\xd0\x15\x29\x87\x0c\xfe\x37\x3b\x7e\x7c\xbe\xda\xf9\x69\x26\x9f\xb7\x0a\xa7\x83\xd1\xe7\x44\x17\xc7\xba\xe0\xfe\x03\xd9\x51\xfd\xb8\xc7\x1c\x62\xe9\xbe\x7f\xdd\x5d\x23\x3e\x39\xf4\x6f\xed\x05\x7e\x49\xb6\xf3\x40\x68\x45\x91\x48\xda\x3d\x42\x41\x61\xad\x2c\x86\x95\x08\x60\x2e\x9c\x0b\xb3\x0b\xfb\x88\xac\xd5\xf4\xdf\xdf\xfd\x47\x35\x03\xcd\xfe\xda\xbc\x44\x42\xb7\x43\xbe\x07\x5e\x7c\x6f\x61\x0e\x64\xff\xc2\xe5\x31\x87\x74\x5c\xd7\x19\x65\x8f\xc6\xe6\x2a\x5b\xe5\x18\x43\x7c\x5b\xd6\xa4\xfe\xba\x94\xae\x3f\x44\xf2\xf2\x93\x08\xe8\x31\xfe\xef\xed\x67\x69\x09\xce\x5e\x80\xc8\x4c\xbd\xca\xc4\x7e\x47\xd2\x7c\x97\x12\xa0\x1f\x6b\xc5\xda\xed\xc0\x2e\x64\x14\x40\x7e\x91\x1c\x0a\x5a\x53\xe5\x32\x8a\x5a\x5f\xd9\xf0\x40\xaa\x7f\xb7\x0b\x79\xb3\x1c\xd1\xb6\xfd\x9b\xd5\x02\x90\x40\xbd\x22\xae\x22\x2f\xd2\xf6\x87\x0d\x07\xf4\x35\x32\x26\x39\xcf\x31\x93\xca\x57\x09\xb8\x82\xb0\x7a\x58\xf9\x52\xa9\x96\x3e\x56\x8f\x8c\x5a\x58\x4a\x6b\x9e\x27\x5c\x5c\x07\x95\x7a\x4d\x2c\xda\xa9\xf1\xeb\x44\x4e\xd1\x22\x4b\xac\x65\x63\xb2\xf9\x27\x3e\x80\x30\x1d\x44\xd5\x0a\xe3\x83\xb5\x97\x21\x3b\x00\xda\x5b\xf2\x7e\x5d\x1f\xe2\x40\xcc\x3b\xb6\x5a\xa5\x03\x0d\x65\x1b\x6b\x5b\x31\x76\x1d\x53\xce\x0c\x6d\x74\xa1\x5d\xad\x54\x79\xf3\x1c\x91\x5c\xcf\x44\x66\x59\x85\x3b\x89\xa5\x1a\x28\xee\x89\x76\x85\x35\x53\xfd\x2e\x02\xfe\x72\x43\x53\x8d\x00\xb4\xed\x07\xd8\xb8\xa8\x0b\x5c\x16\x5c\xd4\x63\x41\xff\xd8\x16\x3c\x55\x57\x02\x66\x3a\x4e\x6a\xb2\x95\x2b\x7e\x74\x43\xd0\xf6\xb1\x23\xb6\x94\x67\x21\xaa\x63\xe8\x7b\x11\x55\xec\xa8\xa6\xa1\xbc\x9f\xd2\x5c\x67\x62\xe5\x27\x42\xc8\x6b\xca\x1b\xa9\xd8\x37\x04\x15\x24\x4f\x0e\xdf\xdb\xe0\x93\x2b\x5c\xa0\x61\x15\x09\xc9"}, -{{0x0a,0x4f,0x5e,0x16,0x70,0xf1,0xe2,0x4b,0xfa,0x37,0xb7,0x3c,0x99,0x43,0x30,0xb3,0x6e,0x7d,0xaa,0xf9,0x30,0x16,0x1b,0x78,0xa4,0xa8,0x48,0x66,0xff,0x25,0xe3,0xd5,},{0x9d,0xcb,0xba,0x90,0x39,0x81,0x59,0x4c,0x7b,0x67,0x7e,0xa8,0x00,0x20,0x01,0xd6,0x64,0xcf,0xf7,0xce,0x8e,0x5c,0xfa,0xe5,0x88,0x40,0xcf,0x74,0xaf,0xf0,0xd3,0xa9,},{0xdc,0xf3,0x53,0xb2,0xb9,0x9a,0x4e,0xf4,0x5f,0x3f,0xdf,0x65,0x28,0x63,0x2e,0x8a,0xbd,0xc4,0x33,0x34,0x24,0x76,0xa8,0xc2,0xb3,0x79,0x00,0x40,0x4a,0x4e,0x33,0x3d,0x38,0x78,0x14,0x23,0x57,0x57,0xef,0x7a,0xd0,0x38,0x58,0xa0,0xf3,0x5d,0x46,0x15,0xe8,0xab,0xa4,0x84,0xfd,0x64,0xf1,0x11,0x2e,0xc1,0xb1,0xae,0xd2,0xcb,0x64,0x0e,},"\xf4\xb0\x5b\x3e\xfd\xcb\x1d\x5c\x07\xda\x95\x0c\x46\x56\x55\x28\x44\x0b\xb4\x88\x35\xee\x4c\x13\xf4\x3d\x7a\x16\x18\xde\x11\x9e\xbb\xb2\x59\xea\x74\x80\xa5\x04\x81\x74\xfa\xec\xc1\x05\x5b\x32\xdc\x01\xac\x71\x56\x34\x43\x21\xe8\xeb\xa6\x98\xf3\x02\xee\x16\x43\xb5\xf0\x4b\x8e\x7e\xcc\xa6\x3b\x91\x56\x1c\xe3\x51\x4a\xbe\x78\x51\xb6\xfb\x17\xfc\x94\x3b\xdc\x94\xda\x30\x8c\x8e\x47\x69\xfe\xc2\x0f\xad\xf4\xfa\x8e\x7f\x62\xb6\xff\xb5\xf1\x70\xd6\x44\xed\x29\x35\x5e\xbd\x22\xcb\x3a\xa1\x48\x6b\x1e\x36\x7c\x72\x9d\xd3\xf7\x9b\xcd\x40\xff\xd0\x8a\xf2\x8c\xeb\xc8\xd7\x76\xe1\xa4\x83\xe9\x11\xd7\x9b\xc6\x13\xe0\x9c\xc6\x21\xca\xde\xb0\x34\xdd\x6f\x72\x37\x47\x71\x98\x51\x27\xf7\xa3\xa1\xaa\x78\x6a\x52\x3a\xe6\xe3\x4e\xe4\x33\xdc\x30\xc3\x75\x98\x7c\xff\x50\xbd\xcb\xc9\x97\xfc\xd5\x1c\x94\x56\x7a\x67\xae\xfb\x6e\xf5\xed\xf9\xbd\xd6\x59\x64\xd4\x64\xbe\x9e\xbd\xfb\x88\xc0\xe2\x31\xb0\x7f\xf6\x40\x5c\x00\xf8\x25\x31\xe9\x61\xbf\xc5\xea\xd2\x66\xbc\xc0\x87\x18\x87\x8c\xaf\xb1\xd3\x75\x36\xf1\x83\xe4\x8b\xf3\x8d\x3f\x6b\xe9\x00\x25\x2d\x1f\xb4\x19\xe6\xa2\xac\x58\x96\x03\x9f\x63\xc3\x14\x01\xff\xf9\x32\xce\x98\x14\xb0\x85\xab\x20\x41\x69\x72\xa2\xb3\x51\xc8\x15\xa6\x2d\xe5\x09\x67\x46\x28\xb0\xd3\x56\x6f\xc9\xc2\xe0\xa9\x23\x7b\x93\xf9\xbb\xb2\xde\xed\xf0\x2b\xff\x83\xbf\x6d\x86\x8b\x63\x99\x32\x6d\x48\x09\xd0\x41\x9f\x31\xb2\xf3\xa4\x81\x28\x5b\x94\x07\x8b\x47\x06\x1c\xe9\x1d\xad\x58\x3d\xd5\xb1\x3b\xd0\x10\xfb\x30\xf2\x49\x5b\xb7\x04\x20\x18\x3a\x93\x01\x59\xe4\xdb\x19\x3d\xf6\xac\xd1\x24\x42\x3e\x03\x9a\x67\xf1\x56\x88\xae\xc5\x0c\x59\x27\xfb\x27\x18\x22\xaa\xa6\x6f\x29\x4b\xc8\x05\xd3\xbc\x7c\x83\x41\x87\x8a\x54\x10\x09\xf3\x0d\xa9\x9f\xcc\x00\x85\x07\x9c\xe7\xfc\x55\xe0\x01\x16\x85\x56\x2a\xbd\xb3\xa9\x47\x1f\xfd\xe6\x17\x63\x00\xef\x5b\x31\xe0\xdf\x60\x9a\x54\xa1\xee\x66\x24\x07\x0d\xa9\x9c\x87\x76\x89\x1f\xdf\x6a\xa7\x8b\x4d\x55\xb1\xf5\xda\xdf\xc0\x61\xad\xd5\xaf\x00\xfd\x3a\xde\xdb\x44\x8c\x55\x9b\xff\xf2\x04\x06\x80\x43\xa5\xd1\xd6\x21\x47\x48\x62\x8c\x3e\xbc\x5f\x02\x24\x32\x6c\xa1\x8e\xf0\x48\x42\x5d\xa9\x30\x01\x33\xfb\x69\x5d\x4f\x26\x31\x65\xac\x22\xf3\x61\x9d\x40\x5a\xf2\x71\xa7\x1a\x9a\xfb\x19\x8b\xf6\x31\x24\x1d\x34\x59\xb9\x53\x98"}, -{{0xb8,0x55,0xc8,0x18,0x05,0xc7,0x08,0x74,0x10,0xe6,0x9f,0x96,0xb0,0x24,0x02,0x71,0xdc,0x76,0xc1,0xe4,0xad,0xe3,0x8c,0x6a,0x92,0x78,0xe3,0xc9,0x4f,0xbe,0xa2,0x56,},{0x6a,0xdb,0x02,0x5a,0x40,0x26,0x0f,0x56,0x98,0x84,0xb8,0xca,0xb3,0x75,0x2b,0x4f,0x25,0x5c,0x37,0x3e,0x2b,0x42,0x4b,0x62,0x87,0xeb,0xb5,0x10,0xfa,0x06,0xff,0xf0,},{0x3c,0xaa,0x81,0x32,0x73,0xe7,0x53,0x54,0x2f,0xfb,0xfe,0xb2,0x1b,0xc3,0xe2,0xcf,0x8c,0xa7,0xd9,0x20,0xfa,0xac,0x7c,0x49,0xdc,0x2a,0xa9,0x91,0x17,0x68,0xc7,0xad,0x43,0xb3,0x8b,0x02,0x36,0xdb,0x27,0xf3,0xee,0xae,0x0b,0x12,0x06,0x00,0x1e,0x66,0x5a,0x60,0x70,0x78,0xc5,0x22,0xed,0x7a,0x9d,0xc4,0x68,0x85,0x34,0x63,0x59,0x00,},"\x85\xa9\xbd\xb7\x0a\x6c\x75\x28\x97\xe4\x3a\x91\x10\x6e\xe9\xa9\x9c\x2c\xa9\x4f\xf7\xb4\x46\x1a\x44\xa3\x91\x74\xc1\x7e\xcd\x99\xdf\x46\xee\xcd\x81\xc3\xf5\x25\x13\xdc\x9d\x54\x7d\xad\x37\x21\xc6\xd5\xee\x1f\x8f\xac\x0b\xa5\xaf\xb3\x68\x70\x44\x73\x9e\xd5\x35\xb8\x44\x00\x87\x04\xc0\x9f\xe1\xe5\xd7\x85\xd4\xc9\xc3\xd0\xb0\x58\x89\xb9\xc2\x0f\xc3\xfd\x68\xdf\x12\xdb\xeb\x2c\x34\xf6\xf7\xec\x1c\x6f\xb7\xfa\x81\x1f\xf8\x46\xb5\xa6\x1f\xa5\xfe\x55\x37\x9e\xe6\x3a\xbc\xd3\x73\xfe\xd0\x02\x54\xeb\xd0\x6b\xc8\xb2\x2f\x7f\xbf\x2f\x72\x7a\x5f\xad\x88\x51\x41\x59\xe2\x6d\x78\xdf\xdb\x09\x57\xf6\xef\xaf\x51\xa8\xe8\x0b\x58\x5e\x83\x8b\x96\x21\xd0\x51\x07\x4a\x4f\x58\x67\xb4\xae\x2f\x2f\xf6\xd6\x2b\x85\xbc\xce\xc0\xb4\xaa\xa4\x79\x16\x37\x38\x8c\x09\x01\xfd\x49\xdc\xcc\xce\x72\x04\x85\x9f\x81\xee\xfc\x63\x9f\xed\x92\x28\x04\x56\xe6\x9a\x15\x09\xb4\xb1\xbd\x76\x24\x44\x7d\x86\x2c\x45\xa0\xc8\xb0\xc5\xbb\x2c\x4c\xa5\x12\xcb\xc0\x37\xf5\x1b\x78\x09\x82\xb1\x83\xa5\xca\xfa\x15\x29\x75\x85\xc9\x47\xa2\x5b\xe8\xc2\x24\x0e\xbf\xb6\x86\x8e\xce\x5e\xa2\xaa\xb2\xc2\x39\xc8\x37\x54\xc7\xd5\x94\xb3\x72\x5a\xce\xef\x34\x4b\xa7\xe6\xae\xf4\x9f\x7f\x31\x3b\x0a\xe8\x2c\xca\xca\xd3\x87\xa6\xe9\x33\x7f\x05\xf8\xc7\x99\xef\xe7\x82\x9b\x27\xb4\xd5\xb2\x01\xfd\x5a\xe5\x83\x43\x51\x69\x07\x59\xf3\xea\x17\x5f\xd4\x74\x1b\xe2\x28\xd8\x07\xfb\x54\xdf\x4a\x74\x10\x38\xfa\xee\x47\xed\xf1\xf5\x61\x65\x25\x98\x60\x1f\x27\x15\x5f\xc5\x0d\x9d\x50\x11\x43\x37\x11\xc1\x06\xd4\xb6\x07\x85\xa5\xcc\x93\xb3\xfd\xd1\xda\xd7\x0c\x0c\x8e\xaa\x33\xf1\x51\x2e\x35\xa5\x41\x74\x5e\x37\x6c\x15\x16\x7f\xa8\xf6\xb3\xb2\xc4\xc3\xa3\x66\xfc\x41\x49\x7d\x29\x73\x57\x81\x6a\xe7\x95\xa8\x04\xc9\x80\xe7\xcb\xfb\x0c\x74\xd8\x83\x5d\x92\x9a\xe3\xbb\x52\xba\xb1\x29\x64\x56\x6d\x74\x6b\xd2\xc1\xd1\x32\xb6\x23\x3f\xa3\x4f\x75\xe2\x68\xed\xee\x77\x5e\xb3\xce\x13\x2e\x6b\xeb\x2e\x8d\x71\xf0\xc8\x76\x29\x91\xcd\xe4\xe2\x6f\x71\x43\x9d\xfa\x83\x97\x8f\x99\x56\x03\x86\x1b\xc0\xb1\xd9\x06\x0b\xbc\xca\xcc\xf8\x6f\x87\x45\xad\x96\x99\x4d\x5d\x00\x7d\x52\xe8\x3a\xa5\xe6\x94\x12\x96\x4b\xdb\xfb\xe4\x78\x0a\xaa\x8d\xe4\x1b\xe1\x29\x8a\xbb\xe9\x89\x4c\x0d\x57\xe9\x7f\xca\xcc\x2f\x9b\xbd\x63\x15\xd3\xfc\xd0\xea\xf8\x2a"}, -{{0x95,0xb9,0xc8,0xa6,0xef,0x80,0xeb,0xd5,0xcb,0xd4,0x7a,0x04,0xca,0x54,0x38,0x73,0x73,0xdf,0x4d,0x67,0xa2,0xb4,0x75,0x59,0x77,0x65,0xac,0x89,0xfc,0xf9,0x3e,0x93,},{0xf2,0xc9,0x47,0xb1,0x8a,0xdc,0x3e,0xa6,0xa2,0x3f,0x7a,0xbc,0xa3,0x64,0xb9,0x85,0x3a,0xe8,0x5a,0x2b,0x0c,0x8c,0x26,0xf0,0xd3,0x17,0x3c,0x27,0x32,0xc3,0xc7,0xff,},{0x2c,0x8b,0xf5,0x43,0xe2,0xa3,0xe0,0x04,0x15,0xee,0x4f,0x10,0x7b,0x2f,0x5a,0x66,0x87,0x17,0x6f,0x5d,0x52,0x11,0x17,0x75,0x9c,0xeb,0x56,0x17,0x51,0xbc,0xc7,0x7d,0x9b,0x08,0xa6,0xa6,0x31,0xf6,0x44,0x7c,0xd9,0x01,0xde,0x96,0x69,0x9a,0xeb,0xb1,0x68,0xbf,0x97,0x50,0x0d,0xc5,0x4a,0x05,0x43,0xef,0x14,0xe4,0xb5,0xa0,0x81,0x06,},"\x78\x55\xbc\x39\x26\x30\xcc\xf5\x31\xd3\x06\x16\x06\xdd\xfc\x81\xa0\xfd\x92\x94\xc5\x47\x91\xb5\xf9\x55\x9b\x68\x27\x25\x4a\xa1\xf2\x5c\x54\x0b\x7d\x7d\xf3\xec\x9c\xdf\x14\x25\x66\x29\xdb\xcf\x9b\x72\x5f\xeb\x34\x12\xeb\xf3\x5f\x0e\xf9\x37\x9e\x41\x31\xcc\x77\xe0\xf0\xfb\x6f\x74\x59\xa7\x38\x36\x1a\x99\xae\x4c\xcb\x2b\x60\xa9\x9f\xe9\x2b\xd6\xc3\xa5\x3d\x6f\x45\x4e\xe9\x00\x5b\xce\xc5\xae\xdc\xfa\x82\x34\x73\x92\xef\xcf\x11\x75\xe5\x78\x39\x6a\x8d\x80\x0d\xab\xa0\xf4\xc2\xcf\x4d\x49\x13\xb0\x52\x86\x20\xe3\xba\xa0\xf6\xd8\x6e\x06\x28\xe4\x7c\x0c\xa2\x6d\xf3\xb0\xc7\x88\xc4\xe1\x65\x57\xf7\xfc\x28\xdf\x82\x0c\x12\xfb\xb6\xff\xbf\xec\xb9\x82\x9d\xdb\x65\xef\x8d\x63\xe9\x0d\x68\xfc\x71\x94\xb5\xb8\x85\x91\x3f\x08\xed\xee\x84\x56\x76\x47\xff\xa3\xf0\xd0\xd3\x25\xd0\x82\x60\x0c\xe7\x1a\x23\x45\xc7\x7d\x65\xbd\x96\x25\x20\x03\xe5\xc1\x25\xa7\x18\xa0\x73\x70\xc3\x1b\x57\x08\x07\x5c\xf1\x83\x7c\x69\x25\x63\x5c\xc6\x8d\xd1\xb7\x51\xe4\x0a\xb6\x08\xb0\xd9\xd8\x85\x2c\x18\xd3\x06\x92\x19\xef\x80\x7b\x76\xd2\x88\xf9\x2c\x29\xa9\x3e\x3d\x75\xb5\xb2\xe5\x36\x81\x67\x1d\x3a\xe0\x14\x5a\xc0\x3c\xca\xd3\x16\x2e\x44\x70\x3b\x04\x01\xd3\xeb\x16\x7c\xd8\xdd\xc1\xe1\xa5\xa3\x26\xb7\x28\xb1\xe0\xc0\x0a\x94\xd8\x6d\xe6\x13\x52\xa6\x61\xe4\x08\x97\x17\x5d\x28\xd3\x41\xe4\xd1\xd9\x96\x2e\x35\xf4\xde\x18\xa5\x40\x17\x61\x1a\xd0\x53\x59\xce\x08\xb9\x7b\xfe\xdb\xfb\xe3\x99\x2e\xd5\x8e\xd4\x0f\x51\x7a\xab\x01\xc0\xfe\xfe\x8b\x63\x64\x3d\xa1\xa4\x54\x15\x27\x30\xbf\x99\xaf\x87\x40\xad\xf9\x8a\x77\xb8\xd7\x3a\xdb\x08\xe6\x09\xe0\x0c\xe9\xb1\xcc\xdf\xef\x3e\x9a\x9b\x05\xaa\x56\xe0\xbc\x79\xb6\xbb\xba\x80\xdd\x8e\x46\x1a\xf7\xcb\x20\x28\x92\xd8\x9b\x2d\x05\xa4\x45\x8a\xb3\xfa\x54\xb4\x74\xb8\xf8\xf5\x81\x79\x5d\x6c\x27\x39\xe5\x9d\x0f\xe0\x62\x40\x0b\xae\x2d\x2d\x53\x4b\x34\x0b\xb8\xe2\x61\x57\x77\xa9\xa5\x61\x5b\xb2\xcf\x43\x7b\xa5\x25\xe0\x0e\x70\x38\xf2\x2a\x57\x88\x2a\xc5\x20\xb3\x33\xe7\x5c\x3c\x92\xa8\xb9\xf0\xe3\x7f\x67\x1c\x94\xb1\x5d\xd8\x18\x2a\x08\xd7\xc1\x43\xe9\x4e\x92\x62\xb3\xcc\x55\x44\xc2\x94\xf5\xf3\x35\xc2\xb2\x8a\xc1\x19\xfe\xa0\x0f\x96\x34\xdb\x06\x39\x93\x98\x8b\x5f\x15\x05\x79\xc7\xcc\x25\xb6\xa1\xfb\x0d\xde\x94\x80\x4f\xa6\xef\x66\xff\x79\xfb\x91\x07"}, -{{0xb7,0x86,0xcc,0xfb,0x58,0x6d,0x43,0xb8,0xc4,0x6b,0xb9,0x7b,0x96,0xc9,0x18,0x73,0x1b,0xc2,0xcc,0x11,0x92,0x77,0xf1,0x23,0x67,0x1e,0x30,0x14,0x81,0x58,0xd2,0xed,},{0x90,0xc7,0x00,0x46,0x00,0xf3,0xdc,0xe4,0x09,0xfd,0xea,0xdc,0x8e,0xd0,0x18,0xf9,0xea,0x26,0x3f,0x75,0x16,0x0a,0x74,0xab,0x54,0xf4,0xc2,0x39,0x9a,0x90,0xca,0x78,},{0x52,0xba,0x96,0x58,0xa1,0xa0,0xb3,0xe9,0x8e,0xd5,0x20,0x9e,0x39,0x3e,0x42,0x00,0x66,0xa3,0x7d,0x37,0x14,0xda,0xa7,0x3d,0x5c,0x67,0x1d,0x33,0x07,0x5a,0x5f,0x57,0x27,0xfe,0x4e,0x08,0x1e,0xe0,0xfa,0x3c,0x21,0x33,0xdc,0x95,0x3a,0x2d,0xa6,0x20,0x29,0x13,0x71,0xf0,0x0c,0xcb,0x57,0xd8,0x79,0x2e,0xb5,0x96,0xa2,0xff,0x81,0x01,},"\xba\xbf\x48\xbd\x55\xea\x91\xbd\x0c\x93\xb9\x70\x24\x1b\x52\x9d\x9d\xb4\x3d\x49\x27\xfe\xa5\xf1\xa1\xf7\x08\x2d\xd6\xcb\x50\xa5\x2b\x09\x4b\x31\x29\xfc\xd9\x03\xa4\x4f\xec\x8b\xfd\xb5\xc8\x6c\x00\x2a\x2a\x45\x28\x87\xca\x25\xa6\x0e\xce\xb5\xe1\xf9\xf5\xc9\x3d\xc5\x94\x23\xc7\xaf\xe7\x47\xc6\xbf\x40\x7c\xac\xad\xec\xcf\x5d\x78\x79\x70\xcb\x06\x17\xbb\x3c\xfe\x7f\xd1\x75\x63\xd3\xa0\xdc\x91\x63\x1f\x71\xb8\x4b\xe2\x4a\xe8\x00\x11\x37\x50\xf0\x31\xd0\x1f\xd0\x53\x64\xb4\xf2\x7f\x86\xf8\xdc\x3a\xd7\x40\x7e\x1a\xe9\xe7\x68\x15\x4e\x3d\xde\x58\xe8\x67\x12\x9e\x24\x74\x54\x7b\x40\x82\x17\x96\x48\x44\x85\x8d\x05\x6b\x31\xc3\x74\x99\x1b\x7f\x16\x1f\x52\xf0\x88\xb8\x06\xe0\xf3\x13\xd6\x8a\x15\xc5\x40\x1e\xd5\x5b\x2b\x77\xde\xea\x58\x6c\xb0\x54\xdc\xd7\x1a\xf2\xab\x6a\xb1\x1e\x84\xb3\x0c\x53\x93\x45\xde\x3e\xb4\x3f\xb7\xb3\xa3\xb4\x89\x87\xc3\xbf\xa7\x06\x55\xd5\x99\xf2\xe3\x1d\x12\xad\x23\xcc\x96\xe8\x6d\x38\x0b\xfd\xa8\x12\xfe\xff\x3d\xd3\x02\x42\x92\x91\x69\x07\x02\x28\x91\xe1\x19\xbf\xc3\xed\x9c\x25\x54\x6c\xd1\x9f\xc9\x92\xd8\xa6\x1e\x60\x59\xca\x3c\xe7\x80\x2a\xf1\x11\x87\x56\x62\x0b\x87\xa7\x24\x2b\xd8\x38\x97\xc9\x4d\xd5\xa3\x6e\xd4\x0f\xc0\xf3\x4c\x2c\x93\x11\x0b\x37\xd1\x7d\xd9\x6a\x22\x06\x25\x90\xbc\xdb\x54\x67\x42\xef\x72\x18\xad\xcc\xc5\xad\x28\xf4\xfc\xe6\xec\xf7\x05\x83\x5f\x41\x13\xd8\x2e\xa5\x33\x90\x3a\xec\x8c\x38\x20\xfe\x4b\x47\x15\xf3\x7e\x20\xce\xbc\x1e\x71\x51\x9a\xa0\xb2\x40\xb4\x84\x0a\xa4\xfd\xcf\xb5\x24\x67\xfe\xdd\x8f\x4d\x1f\x9b\xc3\x3e\xe1\x14\xf3\xef\x85\xf5\xfd\xb0\x9c\xa8\x84\xaf\x38\x8a\xd3\xad\xf8\x4c\x79\x3f\x38\x6e\xfe\x6f\xf8\xa4\x6e\xd8\x1e\x5d\x45\xa3\x7c\x25\xcd\x80\xf2\xd7\x36\x3f\x43\xae\x45\xe3\x77\x2c\x0d\xf8\x9f\x11\x44\x79\x39\x80\x6c\x09\x6e\xf9\x33\xa1\x39\x44\xf0\x89\x0d\x88\x7c\x2e\x5b\xbb\x6b\x12\xea\x95\x0b\x09\xb8\xfe\x42\x52\x89\x37\x73\x52\xf3\x5f\x84\xcc\x4d\xcd\x4d\x7a\x44\x94\x89\xfa\x92\x51\xc0\x31\x13\x48\x92\x25\x80\x9c\xdf\x3c\xb6\x34\x75\xf1\x0d\x34\x17\x09\x37\x1c\x6f\xd4\xbb\x7a\x94\x94\x83\xd1\xbc\x2b\x31\xdd\xf4\xd9\x63\xa0\x7d\xe7\xea\x5c\x3f\xee\x9a\x0e\x33\xf0\x76\x9f\x2f\xaa\x40\x61\x2a\x54\x69\x74\xbd\xe0\xb7\x33\x91\x79\xe4\x12\x4a\x44\x7b\xd4\x28\x79\xcc\xda\x5c\x8a\xd1\x81\x9c\x53"}, -{{0xdd,0x1a,0x97,0x74,0xf7,0x58,0x4d,0x85,0x89,0xb1,0x9f,0x92,0xab,0x69,0x39,0xac,0x48,0x56,0x02,0xfe,0x16,0x44,0xce,0xe2,0xf6,0xf3,0xcd,0x60,0xfb,0xd5,0x84,0x00,},{0x4b,0xea,0x7d,0x0b,0x0f,0x4b,0xd5,0x90,0xf9,0xe3,0x57,0x9f,0x0c,0x5f,0xa4,0xce,0xf4,0xd6,0x0a,0x49,0xd2,0xc4,0x37,0xa0,0xaa,0xea,0xd9,0xd4,0x3a,0x73,0xd4,0xa3,},{0x19,0x59,0xbd,0xe0,0xa6,0x97,0xa6,0x39,0x93,0xec,0x47,0xd1,0x58,0x22,0x37,0x39,0xfe,0x65,0x87,0x1f,0xa0,0x58,0x70,0xd7,0xde,0x0d,0x38,0x08,0x65,0x91,0x20,0x2a,0x51,0xb1,0x74,0xd1,0xc6,0x18,0x28,0x08,0xc6,0xce,0x62,0x63,0x1d,0x81,0xdb,0xa3,0x4e,0xbe,0xd4,0xaf,0x2f,0x29,0xb0,0x6c,0x00,0xa5,0x7a,0x3c,0xb6,0x66,0x36,0x06,},"\xe5\xdc\x3e\xd2\x6c\x1f\x69\x3c\xf8\x52\x46\x5a\x05\xe3\x04\x8b\x50\x5d\xb5\x11\x6d\x9e\x31\x59\x22\x05\xa9\xc3\xd4\x72\x0b\xc1\x0b\x6c\x20\x63\x9a\x0e\xe2\xf0\xe1\x47\x22\x5b\x5b\x19\xea\x51\x1c\xfb\xa0\xc2\x1a\xac\x10\x71\x5a\x2f\x23\x2f\x10\xc2\xc8\xaa\xd4\x11\x12\xb6\xb0\x12\xe7\x5a\x41\x55\xf8\xc6\x92\x62\x53\xca\x2b\x4d\xdb\x7b\xfe\x7f\x86\xe9\x0a\x53\xdb\xc0\xcb\xa8\x9e\x48\x5c\xec\xa8\xfd\x26\xe5\x0c\x7f\x28\x2a\x25\x35\x73\xcb\x0a\x8f\xa8\x8c\xc4\x46\x23\xe8\x2e\x8f\xa2\xed\xb6\xcb\xc7\x53\x8a\xc9\x2c\x11\xe4\xc5\xb1\xea\x5f\x68\x96\x6d\x15\xd9\x3c\x34\xf3\x96\xd2\x75\x72\xf8\x64\x38\x2a\xb7\x6a\x7b\xe6\x5a\x55\x7b\x13\x97\x66\x36\x8a\x20\x7d\x98\xbc\x0c\x20\x92\x63\x70\xde\xa2\x70\x48\x16\x03\x63\xed\x85\xf4\x09\x9e\x7c\xd6\x6d\x12\xd0\x98\x8c\xfc\x9e\x2f\x16\xaa\x56\x5f\x8f\x33\xb3\x9e\x97\x8c\x05\x87\x37\x1f\x92\xdb\x50\x56\x31\x75\x64\x41\x1b\xd8\xa3\xb6\xfe\xa0\x9d\x34\x87\xaa\xf7\x34\x03\x49\x18\xff\xed\x1c\x9f\xba\x7b\xde\xc6\xfe\x68\x87\x6f\xc7\x36\x0c\xc5\x62\x9b\x92\x10\x40\x27\xfe\x57\x59\xc5\xab\x36\x53\x54\x75\x1e\x79\x69\x11\x6c\x3b\x9a\x21\xb1\x52\x33\x0a\x96\xa9\x38\x1a\xf7\x30\xd1\x78\x22\xd7\x8a\xd6\xea\x86\x00\x06\x91\x5b\x5c\xab\x44\x7a\x75\x93\x72\xe0\x5d\x49\x5e\xbb\x32\x8e\x75\xd2\x48\xda\xa0\x2f\x5d\x2e\xb9\x78\xd2\x71\x0c\xf1\xc5\xfb\x82\x48\x76\x77\x0e\x32\xca\x6d\xe2\xc7\x30\x56\x48\x92\x41\x5b\xcb\x53\xe5\x98\x1d\x70\x7a\xdd\x96\x1c\x5f\x37\xfd\xaf\xa1\x39\x9a\xf8\xae\xa9\x60\x45\x8d\x2c\xa3\x10\x55\x3f\x7c\x98\x66\xcc\xbe\x8e\x9d\x88\xe0\x8a\x44\x68\x72\xea\x66\xfc\x30\x8c\x82\x45\x14\xb7\xda\xce\x03\x34\xdb\x73\x5e\x6f\x14\xc8\x5b\x5e\x61\x9a\x5d\x60\x56\x48\xa8\x81\xe8\x76\xc7\x8d\xbe\x06\x57\x23\x3d\x4f\x7f\x3b\xfd\xdf\x63\xb4\x45\x31\x1d\x6a\xbc\x47\x63\x47\xec\x4f\xb4\x3c\x89\x46\xf9\xd1\x7c\x36\x93\x81\xd1\xc5\x64\xff\xcf\xe2\xdc\x7b\x47\x26\xfd\x57\x38\x7f\x0b\x44\xdb\x8e\xf9\x5a\x0b\x4e\x32\xa7\xbe\xdf\x31\x9e\x53\xa9\xe7\x12\x6c\x28\x11\xf9\x82\x9d\x1f\x4a\xe9\xab\xd9\xd5\xf4\x2e\xfe\xf2\x07\x5f\x47\x05\x1c\x63\xa4\xf8\x20\x20\x40\xec\x47\x23\x68\x63\x82\xc6\x03\x31\x27\xc1\xfb\xff\xf4\xbc\x82\x37\x35\x08\x75\x2d\x43\x1d\xc4\x73\xf5\x2d\xde\xab\x03\x42\xdc\x4f\x54\x47\xf8\xf2\x57\x38\xef\x65\xd7\x85\x56"}, -{{0x66,0xf5,0xea,0x8c,0xdb,0x95,0xee,0x1a,0x75,0xe3,0x24,0x67,0xd7,0xc8,0x3c,0x59,0x44,0x77,0x42,0xc8,0x5d,0xdd,0x49,0x9c,0x43,0xc0,0x86,0x73,0xe1,0x49,0x05,0x3a,},{0xa8,0xad,0x04,0xb9,0xc1,0x44,0xb9,0x7f,0xe8,0x67,0x37,0x4d,0x4f,0xe5,0x7d,0x7e,0xc0,0xc2,0x49,0x18,0x3e,0x43,0xbd,0xfb,0x5d,0x52,0x64,0x4e,0x7f,0xbe,0x1d,0xf3,},{0xec,0x5c,0x7e,0x83,0x92,0xfa,0x8b,0x61,0xbc,0x82,0x96,0x81,0x86,0x6e,0x45,0xac,0x8b,0xe4,0xb5,0xb7,0xb6,0xa8,0x22,0xc1,0xbc,0xd0,0xf2,0xcc,0x2c,0x8c,0x44,0xc3,0x3c,0xf8,0x3f,0xa4,0x2d,0x43,0xa2,0xf1,0x88,0x41,0x41,0xb4,0xa5,0x9a,0xaf,0xf4,0x7f,0x9b,0xe0,0x7e,0x63,0x2e,0x20,0x18,0x75,0x93,0x24,0xea,0xc9,0xd1,0x49,0x00,},"\xc0\xd0\x1d\xce\xb0\xa2\xd1\x71\x91\x10\x18\x79\xab\xb0\x93\xfb\x07\x75\x71\xb5\x21\xbe\x7b\x93\xa1\x17\xc6\x96\xc0\x87\x2f\x70\xea\x11\x39\xab\x62\x83\x29\xee\x56\x55\xfc\x0a\xa7\x7e\x81\x11\xd2\xfc\x88\x47\x48\xc1\xf2\x67\xb9\xeb\x09\xdc\x26\xf5\x7f\xc4\x02\xd6\x1b\xa3\x6f\x63\xf4\xd5\x89\xaa\xe6\x3c\x76\xee\xee\x15\xbf\x0f\x9e\x2d\xcd\xe4\xe4\xe3\xe7\x8f\xc6\xc2\x9e\x3a\x93\xf3\xff\x0e\x9a\x6e\x0b\x35\x66\x45\x95\x38\x90\xde\xbf\x62\xdb\xea\xf4\x90\x51\x78\xd4\xf0\xa5\xa5\x92\xc1\x92\x94\xee\xba\x7c\x21\xcf\x8f\x1b\xb3\xf4\x51\x21\x87\x37\x6d\xe7\x2f\x11\x36\xa4\x8a\xc2\xdf\xaf\x32\xd0\xf3\x7d\xe0\x64\x59\x25\x92\xb6\xe1\xbc\x0c\x51\x2c\xf4\xd2\xd8\x5d\x16\x79\x78\x53\xa8\x09\x33\xb0\x9c\x2f\x7b\xfb\x9e\x54\xa6\x9e\x51\xa8\xe4\x23\xa9\x1c\x3e\x5f\xde\xb4\x79\x05\x33\xe8\x7a\x4b\x1c\x0e\x0e\x23\xa9\xdb\x95\x73\xac\x17\xab\x6e\xc7\x01\x4d\x8b\x7c\x44\x86\xe1\x57\x25\xf8\xd2\x64\xee\xa3\x05\x0e\x83\x5a\xe0\xac\x44\x9d\xb3\x34\x50\x2a\x6d\x97\x35\x8f\xa8\x59\x10\x6a\xd0\xf6\xf4\x29\x5f\x23\x44\x92\x0a\xdf\x93\x55\xa6\x94\x9d\x8d\x14\x5c\x25\x62\x8a\x46\xa1\x04\xca\x09\x9b\xd9\xdd\xe9\x41\x11\x9c\x83\x82\x0c\xdc\x2c\xb2\xd0\x97\x22\x69\x49\x01\x04\x3c\x37\xcf\x0a\xe8\x79\xbe\x20\x30\xd0\x37\x31\x58\xb9\xc4\xb0\x71\x82\x98\xbe\x45\xf6\x30\xf6\xfc\xdc\x19\x0f\x7b\x29\x26\xd8\x76\x55\xa1\x8b\xb7\x97\xac\x50\x75\x7f\xcd\x36\x55\xc9\xe4\x1d\x51\x63\x29\x3d\x9a\x13\xd9\x84\xf5\x91\xf7\x5b\x7e\x4e\x5c\xad\xb6\x4c\x4c\x9f\xdf\xef\x76\xca\xb6\x93\x81\xd0\xf6\x0b\x48\x3f\x80\x4b\xb3\xb3\x33\x64\xdf\x8c\xff\xac\xb3\xc9\xb1\x3f\xf4\xc8\xd8\xd4\xea\x40\x76\x6a\x7d\x42\xd8\x25\x6c\x6b\x1c\x11\xc1\x91\xda\xba\x1b\x8e\xf2\x15\x93\xe4\x7b\x18\x85\x8e\xc1\x9d\x81\x73\x58\x67\x8d\x85\x48\xff\x15\x35\xd5\xfc\xf4\x41\x4b\x6a\x11\xd3\x4a\x37\x42\xf8\xd7\x14\x9f\xa6\x81\x38\x3a\x94\x08\x88\x7f\x1c\x0a\x98\xed\x52\x1e\x72\x79\x32\x77\x82\x4d\x6f\x74\x6d\x49\xb6\x3d\x44\x4e\x31\x2e\x6d\x9b\x98\x66\x11\x25\x81\x96\xa5\xb0\x12\xb8\x8f\xaa\x29\xf9\xa6\xc6\x7e\xd2\x5d\xf8\x7b\x2d\xbf\x0d\xbd\x2d\xc3\x08\x0c\x5b\x8d\x15\xa3\x7d\x34\x72\x90\x98\xed\x0d\xe9\x2d\x75\x80\x74\x29\xb2\xca\xe5\xd7\x28\x3c\x4e\x5c\x9b\xd1\x96\xd1\xad\x43\x6c\x7c\x34\xf3\xc9\x46\x6e\x5c\xb3\x19\x6b\x44\x3f\x4b"}, -{{0xed,0x25,0x58,0xe5,0xc5,0x67,0x84,0xbc,0xfb,0x4f,0x4d,0xde,0xa3,0xc0,0xdf,0xbe,0xf8,0xd9,0x6f,0xf1,0xca,0xbf,0x15,0x8e,0xc4,0xab,0xe6,0x0a,0xff,0x66,0x99,0x9e,},{0x1e,0xdc,0x99,0x10,0x12,0xac,0x6f,0x88,0x8f,0xa7,0xe6,0x04,0x57,0x77,0xe9,0xba,0x1d,0x4c,0x03,0xc4,0x02,0x92,0xd2,0xda,0x6b,0x72,0x2b,0x4a,0xd0,0xa3,0xed,0x74,},{0xab,0x9e,0x01,0x16,0x65,0x24,0xfd,0x28,0x8e,0x5c,0x68,0x9e,0x56,0xd7,0x30,0xd4,0x98,0x30,0x00,0x55,0x10,0x30,0x49,0x33,0x34,0xa3,0x98,0x4e,0x22,0x23,0xdc,0x9f,0x7a,0x5b,0x91,0x0c,0x61,0x76,0x0c,0x61,0x57,0x99,0x0a,0x4c,0x33,0x5e,0x34,0x8e,0x3a,0x7b,0xc8,0x22,0x3e,0x09,0xc1,0x0c,0x5e,0x52,0x0c,0x8d,0x61,0xaf,0xf5,0x00,},"\x2c\x64\x33\xe9\xbf\xbf\x4c\xfd\x4e\x07\x1f\x15\xce\x6b\x12\x9d\x78\x0a\x4b\x3d\xe0\x14\xfa\xc0\x34\xe0\xd4\x4e\xf7\x72\xe2\xc8\xb0\xd6\xa3\x48\x1d\x7b\x3d\xde\xb2\x37\x63\x26\x73\x55\x33\x13\xde\xac\x1e\xfa\xfe\x37\x02\xa7\xa4\x41\x1e\x12\xbd\x34\x1e\x8d\x8e\x96\xc5\x9c\x5e\x30\xc3\x68\x07\xa8\x38\x5a\x53\x8e\x9b\x66\x90\x7d\x6a\x52\x84\x00\xbd\x9f\x95\xee\xdc\x52\x16\xb2\x8f\xd7\x43\x7d\x8f\x4a\x02\x9f\xdb\xdc\x7c\x93\x8e\x4e\xb9\x81\x2f\xec\x05\xea\x69\x32\x29\x62\x9a\xce\x6a\xcc\x7a\xf6\xba\x4c\x23\x8e\x77\x22\xf3\x12\xf7\x89\x6b\x00\x49\x22\xf7\x06\x7e\xde\x10\x6f\x8e\x70\x15\x4d\x78\x3f\xb4\x12\x91\xf3\xc7\xe2\xe4\x82\x60\x45\xb5\x74\x1b\xcb\x4a\x88\x38\xf8\x7a\x32\xe0\x04\x97\x04\xe9\xb5\x32\x34\xc2\x24\xff\x89\x8a\x75\x6e\x52\x91\x34\xc1\xa9\xbf\x50\xfd\x02\x98\x19\xb2\x23\x8b\x60\xb2\xae\xc1\x12\x8f\x34\xd2\x1f\x9d\x66\x98\x3b\xed\x39\x86\x59\xd8\x08\xb6\x7a\x2e\x50\x1b\x5a\x1f\x25\xf7\x1f\x0f\x0c\x1e\xb2\xfe\xa0\xab\x42\xd8\x2f\xf3\xbc\x93\x58\xbb\x20\xc2\x75\x20\xc1\x44\xcf\x21\x16\xf4\xa4\x9c\xbc\x61\x99\x4d\x2d\x71\x05\x46\x69\x4c\x4f\x60\x2d\xc4\x06\xe0\xb0\xc2\x7e\x5f\x5e\x64\x66\x7e\x95\xc2\xec\x9d\xf2\xd6\x52\x9c\xf5\x36\x22\xea\x10\xb9\x56\xb3\x45\xec\x55\xb6\xc3\x9a\x1e\x6e\xd8\x8a\xe6\x6e\x5b\x45\x71\x79\x42\x5d\x1a\x84\x90\x37\xb0\x7c\x46\xcf\x5f\x36\x33\x01\x09\x58\x37\xce\x81\x1b\xff\x49\x60\xbf\x9c\xbd\x15\x20\x1c\x1b\x67\x40\xbd\x70\x10\x21\x40\x74\x4c\x33\x27\xac\xa9\xd6\xd6\xd1\x54\x93\x67\x98\xac\x38\x1f\xa6\x39\xdb\x43\x6e\xe8\x16\x56\x67\xd5\x38\xa6\xc7\x4a\x23\x3c\x12\x4b\xf6\x04\xfd\xad\x51\x98\x4c\x41\x70\xb8\x20\x0d\x2d\xf7\x3c\x29\xbb\x1e\x37\x6a\xff\xc3\x14\xdd\xe3\xe8\x6a\xf9\xd2\xc2\xe6\xc3\xa6\x52\x4d\x32\x1b\xce\x93\xe2\x1f\xc9\x65\x56\x4f\xaf\x77\xd0\xcd\x1a\xcc\xb4\xd7\x62\x94\x85\xf5\x64\xc7\x9f\x4d\x8a\x2f\xde\xfb\x46\x54\x54\x02\x8c\x6d\xd1\x42\x80\x42\x80\x53\x70\x74\x33\x63\xbb\x18\x47\x6a\x3f\x23\x20\xdb\x25\x89\xc7\x21\x33\xcf\x5e\x29\xda\xfb\x7d\x07\xaa\x69\xa9\xb5\x81\xba\xb5\xa8\x3f\x40\x3e\xef\x91\x7a\xfa\x14\xb7\x64\xc3\x9a\x13\xc0\xc5\xea\x70\x19\xd2\xfd\xfb\xd7\xf3\xf7\xd4\x0e\xb6\x3b\x2a\x08\x4d\xa9\x21\x89\x5f\xe4\x8f\x4f\xd5\x94\x01\x7f\x82\x56\x9b\x46\x7a\xb9\x01\x16\x9e\xb5\xda\x9c\x40\x17\x1d\x5f"}, -{{0xb7,0x27,0x98,0xb8,0x11,0xe2,0x33,0x84,0x31,0x25,0x6d,0x24,0x80,0xfe,0x7a,0x36,0x63,0xac,0xec,0xbb,0xe6,0xe6,0xc1,0xb9,0x19,0x1e,0x9d,0x9a,0x22,0x44,0x79,0x40,},{0xce,0x49,0x1d,0xaa,0xd2,0x96,0xb5,0x57,0x27,0xb0,0x95,0x13,0xdf,0x02,0xba,0x59,0x28,0xa3,0x71,0x73,0x7c,0xd3,0x58,0x41,0xe5,0xf7,0x35,0xac,0xab,0x7c,0x5d,0xf8,},{0xdc,0xfc,0x6f,0xd4,0x77,0x99,0xfe,0xc7,0x72,0xc2,0x09,0x9b,0x3c,0x64,0x37,0x24,0x6c,0x3a,0xd0,0x72,0x29,0xfc,0x74,0x0e,0x05,0x31,0x1a,0x20,0x6b,0x18,0xb0,0x2e,0xcd,0xb0,0x26,0xc9,0x26,0xf4,0x9c,0x65,0x52,0xe3,0x47,0xfd,0x35,0xdf,0xde,0x06,0xcb,0x63,0x9a,0x79,0x7c,0x50,0x61,0x2f,0x98,0xe2,0x47,0x8a,0x92,0xaa,0xf6,0x09,},"\xa5\xd4\x62\x98\xb0\x79\x06\x10\xae\xdc\x09\x70\xfe\xa2\xa7\x07\x50\x81\x84\x72\x66\xf2\x2f\x12\x47\x8b\x93\xd7\xe6\x74\xc6\xc5\x17\xf3\xc1\x4e\xd0\x61\x26\x9d\x17\x0a\xc3\x1e\x2a\x64\xf9\x75\x4a\x56\x5b\xac\x1d\xd9\x75\x73\x22\xc1\x11\x32\xe7\xbb\xee\x5f\x32\x81\x8e\x0e\x30\x63\xab\x64\xe5\x52\xd0\x9b\x0f\xd1\x75\x76\x39\xb9\xb9\xd1\xc7\x70\x01\x6b\x67\x74\x65\x87\x2b\x66\x9d\xd4\x8b\xe0\x38\x66\x57\x51\x67\x4d\xd2\xf4\x0a\x96\x6a\x26\x74\x8f\xd3\xe5\xdb\xfd\x92\x26\x5e\xb9\x36\xf5\x5b\x09\x42\x86\xc0\x10\x62\x99\x04\x34\x7c\xb4\xc5\x26\xe3\x77\x47\x0a\xa9\x6e\x81\x69\xa6\xf2\x11\x63\x38\x07\xa5\x00\x30\xe7\xff\x68\xe3\x89\x11\xb3\x55\x5e\x72\x8e\xd8\x59\x0b\x2d\xc4\x5f\xea\x69\x94\x5c\xc0\xc9\xa3\xd3\xe6\xc9\x54\xb3\xe8\x01\x06\xa5\xc9\x1d\x3d\x22\xe8\x9e\x8c\x0e\x1d\xe9\x02\x05\x8e\x9c\xd0\xf8\xce\x80\x6e\xac\x4f\x89\x3e\xe0\x42\x99\x00\xfb\x54\x87\xb8\xfd\x36\xdb\xdc\xb3\x4f\x2d\x54\xfc\x6c\xc7\x4a\x92\x39\x51\xb8\x63\xda\x70\xf1\xb6\x92\xbf\x04\x38\x48\x43\x66\xcd\x85\xee\xb8\x80\xb2\x79\xf8\xfc\xa9\xd3\x24\x2c\x55\x83\x30\xf1\xca\x57\xc6\xa5\x86\x08\xcd\xbc\x07\x73\xe1\x60\x82\xbc\xa9\x64\xdd\xc4\x03\x47\xda\x8a\x36\xb2\xa9\x32\x8c\x2f\x46\x60\x9e\x09\x2f\xd6\x4b\x41\x34\xee\xe1\xd0\x99\x81\x3e\x12\x46\x48\x9e\x8e\xe5\xb1\x9b\x3d\x3b\x89\x1c\x28\xf3\x0b\x38\xb6\xa2\x8e\xc1\xd3\xe9\xb0\x05\xde\xc9\xc6\x3f\x8b\x98\x13\xbc\x1d\xe4\xaa\xf9\x95\xf1\x77\x9d\xde\xd1\x5c\x7a\x43\x0d\x70\xca\x46\xe7\xca\xfd\x4e\x9a\x54\x38\x04\x44\x6a\xb0\x80\x7d\x64\xf2\x55\xe2\x01\xef\x42\x8a\x47\x4d\xae\x8a\x0a\x75\x02\x1b\x62\xad\x39\x88\xff\xb8\x1c\xd8\x22\x1b\x24\x30\x85\xa0\xad\x04\x6f\xdc\x16\xc6\x7f\x17\xb9\xf8\x18\x20\x09\x59\x53\xa5\xb9\x8a\xcb\xdf\x93\xeb\xcf\x80\xbc\x9c\x99\xaf\x5f\xbf\xfa\xcb\x61\xa9\x25\x1c\x5a\xaf\xdb\x22\xb1\x12\x9b\xfc\x60\xc9\x8e\x0f\x17\x52\x63\xbd\xf9\x3d\xc9\xa0\x8b\x8e\xfc\x2e\x8c\xda\xf0\xf8\x3d\x6c\x49\xec\x90\x16\x45\xea\xc5\xa4\xff\x63\x38\x5a\x6f\x1a\xf2\x07\x18\x97\x66\x2a\x37\x22\x19\xc9\x30\x1f\x54\x5a\x2e\xbb\x8f\x59\x17\xdb\x7f\x29\xca\x13\xfc\x86\x1a\xf3\x8d\x90\xc3\x5c\x03\xac\x91\x84\xc1\x22\xe5\x7b\x05\x7c\xde\x42\x6f\xd7\x6d\xca\x79\xe2\x5e\x64\xdb\xb4\x1c\x84\x14\xa0\x45\x0d\xa4\x90\x5b\x90\x2a\xe9\x8d\x2d\xa4\xba\x79\x28\x01"}, -{{0x1f,0xe7,0x32,0x7e,0xa9,0x07,0xd3,0xff,0x17,0x9b,0x11,0x78,0x11,0xd3,0x01,0x93,0xfc,0xba,0x4c,0x34,0x7b,0x90,0x65,0x7f,0xee,0xd9,0x8d,0xee,0xec,0xda,0x9a,0xc9,},{0xee,0xf3,0x01,0xb1,0x6f,0xd7,0xbf,0x3c,0x7b,0x64,0x0b,0xf5,0xee,0x87,0x00,0xac,0x5a,0x87,0x16,0x9e,0xab,0x5f,0x56,0x01,0x5b,0x3f,0x49,0x9d,0x95,0x5e,0x07,0xeb,},{0x9c,0x7f,0xdb,0x53,0xfd,0x60,0x6b,0xc7,0xc9,0xc2,0x23,0xfe,0x94,0x31,0xe1,0xad,0x00,0x95,0x46,0xd0,0x00,0x98,0x81,0x2a,0x49,0x51,0x97,0xf2,0x54,0x1e,0x87,0xf8,0xd6,0xf5,0xda,0x22,0xec,0xef,0xcb,0xb7,0xda,0x56,0x66,0x2a,0x73,0x09,0xd1,0x0a,0x6c,0x4a,0x4f,0x7f,0x29,0x92,0x78,0xd5,0x1b,0xbd,0x11,0xe0,0xcc,0x1b,0x87,0x09,},"\x19\xa8\x32\xf2\x6f\xbb\x02\x39\xf0\xd9\xd2\x6a\x2e\xbd\xed\x24\x03\xc2\xa4\x06\xdd\x1f\x68\x31\x8d\x67\x7a\xfa\x64\xf3\x50\x43\x31\x6a\x5e\xfd\x72\x97\x83\xc7\xf9\xd1\x8c\x09\x82\x46\x14\x65\x20\x91\x88\x6c\xc9\x54\xbe\x9f\x93\x12\xd4\x58\x6b\xf3\x6f\x30\x35\xac\x70\x34\x38\xb0\xcf\xe3\xde\xc5\x07\x78\x13\xc7\x10\xd1\x44\x75\x61\xab\x61\x57\xbc\x7a\xd5\xea\xb5\xb0\xc0\xaf\xdc\xc9\xdb\x77\xe6\x6f\xa8\x07\x13\x66\x82\x9c\x50\x10\x96\xc3\xd3\xa9\x38\x21\x8a\x6e\x42\x07\x10\x9d\x1e\xb8\x1f\x7d\x88\xbd\x6f\xbb\x2a\xef\xb1\xad\xef\x35\x94\xaa\xe5\x7c\x46\xb7\xb9\x84\xdb\x94\x68\xcd\x96\x2c\x61\x84\xfb\x97\x6f\x0e\x2a\xa8\x41\x52\xde\xb1\xc7\x6a\xea\x75\xae\x48\x84\x42\x94\x3a\x80\xba\x7d\x98\xa2\x8c\xb8\x64\xb5\xe8\x7c\xdb\x28\x4a\xd6\xe8\xd7\xaa\xdc\x6b\x75\xd6\x9d\x3b\xd3\x45\x78\x3b\x3e\xbb\x67\x6f\xf9\x5d\x7b\x41\x91\xe5\x99\x85\x1c\x96\x28\x83\x5c\x7c\x01\x19\x7e\x7c\x8f\x86\xf9\xc8\xfb\x49\xfe\x3e\x28\x45\x8b\xa9\xb0\x23\x62\x19\xbd\x46\xc2\x8d\xf6\x53\x24\x96\x99\x4a\xc9\xba\x73\x3c\x01\x05\xa0\x2a\x26\x9a\x2b\xe8\xb7\xcb\x40\x07\x4b\x88\x16\x02\xef\x92\x47\x05\x2d\xe9\xd6\x37\x08\x91\x88\xbd\x4c\x18\x5c\xca\xe2\x58\xa2\xae\x98\x56\xa2\xcb\xf8\x45\x11\x17\x68\x3c\xe3\x41\xf8\x09\x6e\x1d\x91\xe8\x74\xc5\xcb\x8a\x4e\x09\x39\xeb\x77\x37\x3a\x9a\x0e\xb7\x91\x64\x5b\x8f\x54\x60\x47\x2d\x66\x9d\x80\x14\x68\x1a\x5e\x77\x87\x06\xcb\x55\x66\xbb\xd4\x72\x7d\x17\x16\xb2\x3c\x62\x0d\x22\x8b\x5d\x4d\xc2\xb3\x52\xb4\x23\x93\x1f\x8a\x7e\x8f\xb5\x9e\xda\xd8\xae\x42\x45\x87\x29\x86\x1a\x98\xe0\xc8\x50\xa7\x7e\xd6\x55\xe7\xfc\xfe\x4f\xe3\x6f\x97\x72\xdf\x1a\xc3\xc6\x43\xad\x31\xdb\x56\x30\xd5\x71\xdf\x9f\xcc\x9c\x50\xde\x76\x22\x10\x84\x11\x96\x2b\xbf\x72\xde\xfb\xf4\x9e\x99\x70\x59\xc7\x31\x1b\xd9\xdd\xd5\xb3\x38\xa9\x85\x19\x38\xd3\x7e\x7a\x26\x21\x08\xa2\x91\xe2\x01\x68\x03\xbb\xef\xf4\xf9\xc7\x76\x12\x5c\xeb\x7e\x72\x72\xb5\x1c\x7c\x33\x46\x1d\x80\x89\xf8\x40\x8d\x8d\xda\x92\x50\x6d\x50\x02\x08\x4d\x4f\x41\x4d\x8a\x4d\x28\xd3\x69\x4c\x88\x63\x0e\x31\x80\x19\x90\xd9\x52\x71\xce\xf4\x7a\xa5\xc2\x63\xf9\x7b\x7d\xac\xa1\x78\x87\x01\x43\x63\x29\xb5\xbf\xaf\x72\x65\x3c\x16\x6d\xb0\x87\x70\x81\x30\xc5\xc0\xd7\x8c\xc4\xe9\x06\x4f\x86\x06\x80\x27\x1a\xfe\x4c\x40\x98\x53\xc2\xfa\xd6\x75"}, -{{0x5f,0x9d,0xcd,0x93,0xfb,0x14,0x06,0x10,0xb0,0xe2,0x11,0xb3,0x9a,0xdd,0xb1,0xeb,0x87,0xba,0x97,0x80,0x48,0x77,0xaf,0xbc,0xc3,0x81,0x38,0x8c,0xad,0x65,0x08,0x45,},{0x18,0x2a,0x23,0x7d,0x87,0x8c,0x58,0x19,0x33,0x33,0x2b,0x41,0x78,0xb6,0x7e,0xc4,0x08,0xb3,0x19,0x4d,0x44,0xe4,0xe6,0x93,0x92,0xef,0x80,0x0b,0x26,0x7c,0x29,0x49,},{0xc1,0x91,0x5e,0x05,0x2b,0x66,0x47,0x97,0xe0,0xd5,0xfa,0xad,0xc7,0x8f,0x2a,0x00,0x9d,0x6f,0xbc,0xfd,0xe0,0x3f,0x3a,0xaa,0xd5,0x9b,0x9f,0x45,0x88,0xe7,0xfc,0x3b,0x21,0x99,0x0c,0x52,0x08,0xd3,0xd7,0x6b,0x4a,0xa9,0x5b,0xd9,0x34,0xe8,0x8d,0x3c,0x98,0xc5,0x91,0x93,0x0a,0x59,0xde,0x2a,0x05,0x67,0x01,0xd9,0xf7,0x57,0x74,0x00,},"\xc3\x8b\x87\x4d\x3f\xf0\x10\xff\xf1\xa6\x61\x3b\xfa\x13\x42\x57\xb2\x48\x33\xcb\x53\x6d\xe3\xe7\x49\x92\xc3\xcb\x01\xfe\x3b\xbd\xee\xd9\x7d\xc3\xc4\x59\x6f\xa4\x40\x61\x44\x2b\xd3\x1a\x9d\x4a\xa8\xc8\x1e\x34\xad\x98\x88\x71\x82\x06\x63\x55\x09\xb1\x33\xb1\xba\x69\xcb\x1a\xa0\xe7\x5c\x7a\x18\x93\xc0\x80\x16\x1d\x26\x15\x2a\xce\xf4\x0f\x6e\xf4\x21\x0e\x95\x2a\x49\x82\x8b\x5c\xdd\xe8\x04\xbc\xb5\x36\xcd\xc3\x49\xa8\xe8\x31\xb4\xb6\x9d\x37\x85\xa7\x6b\xd9\xfb\x27\x08\x05\x65\x97\x2d\x0b\x8f\xbd\x16\xf3\xf9\x60\xa6\xbf\x3b\xa0\xc5\xb9\xc4\x04\x96\x7e\xc1\xaf\xfe\x59\xb8\xc4\xec\xc6\x50\xfd\xde\x1c\xb0\x6b\x70\x59\x5a\xd4\xd3\x25\xda\x0f\xab\x4c\x55\x40\xa7\xa8\xd5\xeb\xea\xcc\x4e\x99\xbd\x0d\xc9\x6b\xde\x82\xf2\xbd\x7d\x95\x86\x30\x84\x65\xe5\x5b\x1c\xc3\x88\xd7\x50\x48\x6b\xdd\x5c\x72\x64\xd5\x4f\x56\x14\xd4\x87\x26\xd9\x9e\x44\xd7\x77\x8d\x9e\xd0\x32\x39\x58\xab\x98\x58\xe2\xb2\x5d\xf2\xbf\x99\x4b\xa3\xe6\x25\xe2\x80\x3b\x6c\x69\x31\xe7\xa9\x92\x6f\x1e\x61\xed\x86\x24\x03\xce\x39\x2a\xb8\x3b\x7d\x1b\x66\x08\x5d\xcc\x06\xd8\x2d\xbf\x17\x6d\x01\x6d\x9f\x44\xcd\xcb\x50\x72\xd0\x04\x59\x1e\x92\xd0\x45\x9e\xf0\x5a\x51\xb8\xf5\x4b\xa1\x72\x51\xe1\x66\x21\xeb\xb7\x53\xe5\xb1\x59\x0c\x02\xd2\x1e\x40\xf4\xb7\x5e\xee\x46\x02\x86\x0b\x97\x41\xfb\xbc\x0d\x2e\x38\x5b\x8d\xac\xa8\x3c\xce\x68\xc3\x4a\x99\xbd\xe6\xa6\x0d\x13\xba\x64\x34\x7d\x0a\x38\xd6\x4b\x2a\xde\x25\x0f\x38\x85\x2c\x4e\xda\x2e\x2e\x4f\x30\x3c\x3d\xe1\xa8\xa9\xd4\xab\x33\x00\xc9\xe6\x36\x22\x87\x9f\xc8\x53\x7f\xfc\x63\xb1\x85\x61\xfa\x1f\xff\x65\x53\x12\x41\x51\x5a\x62\xbb\x9b\x08\xb8\x0a\xf3\x76\x67\xa6\x01\xae\x04\x17\x17\x93\xcc\x83\xb1\x1a\xdf\x9c\x30\xca\x9f\x4d\xab\xc7\xb4\x01\xe1\x6a\x18\x14\xcf\xc7\x50\x24\x8c\xc2\xf7\x7e\x03\xf9\xc4\x33\x44\x65\xff\x6a\x2c\x83\xcb\xb5\x6d\xb4\xb7\x34\x75\x10\x43\x83\x2c\x40\x00\x97\x2e\xe3\x23\x2f\x92\x9f\x23\x33\x7e\xba\x5e\x65\x1e\x34\xcb\xdd\xfe\x68\xba\x21\x9b\x63\x2e\x7a\xcd\xbd\x46\x30\xa0\x31\xbf\x16\x89\xfb\xbc\x7f\xbb\xb2\x10\xdb\xf2\x5e\xe8\x7e\x2e\xf2\xb3\xcb\xaf\x8d\x9e\xbd\x8f\xc9\x2c\x3a\x58\xd3\xc0\x5b\x13\x85\xa7\x6c\x87\x79\x1d\x7c\xd3\x74\x1b\x71\xb6\xc3\x29\xde\x9a\x9d\x75\x08\xa0\xc1\x56\xa9\x52\x1a\x90\x20\x56\x30\x99\xa8\x2b\x87\x70\xae\x9a\x94\x4a\x7e\x94"}, -{{0x92,0x5e,0xbe,0x04,0xc6,0xea,0xc4,0x9b,0x26,0x73,0x8d,0x6c,0x13,0x00,0xf3,0x1f,0xd4,0x82,0x84,0x78,0xcb,0xe9,0x7d,0xab,0x18,0xbb,0x88,0x96,0x42,0xe1,0xe1,0x10,},{0xcd,0x72,0x31,0xb6,0xeb,0x74,0xe1,0xfe,0x9f,0x92,0x6f,0x00,0xd8,0xde,0x2c,0x51,0x3d,0x49,0x64,0x05,0x25,0xb0,0x79,0x5c,0xab,0x89,0x3d,0x0c,0x89,0x29,0xe3,0xe0,},{0x2c,0x4d,0x69,0xbe,0xd5,0xad,0x8b,0x95,0x84,0xd8,0x49,0xcf,0x3d,0xf2,0xba,0xc7,0x22,0x82,0xb5,0xf3,0x0d,0xe2,0x66,0xb1,0x4f,0x53,0x3c,0xa9,0x6e,0x95,0x50,0xc4,0xb8,0x54,0xc1,0x54,0xbd,0xc1,0x7a,0xa8,0x80,0xcf,0x00,0x1a,0x64,0x54,0xff,0xaf,0xaa,0x2e,0x50,0x17,0x8d,0xe2,0x12,0x16,0xed,0x12,0x6b,0x63,0xf7,0x7f,0x2d,0x02,},"\xe6\xc0\xba\xd2\x3a\x92\xae\x8b\x1d\x85\x77\x82\x88\x15\x7a\xc6\xc6\x17\xc6\x33\x63\x34\x1d\x77\x78\x70\x34\x1b\xb1\x0a\x8d\x3d\xfc\x89\xbe\x4f\x55\xad\x4f\x64\xe8\x3b\xf2\x49\x9b\x69\xfd\xf7\x21\x74\xd2\x84\x4e\x6b\xd2\x89\xda\xaa\x03\x5f\xec\x5b\xf7\xcf\x45\x52\x21\x19\xdc\x7a\x8c\x81\x1d\x79\x57\x8c\x5b\xb0\xf6\xd3\x4d\xb5\x07\xad\x1f\xb6\xdb\xff\xf9\x97\xb7\x9d\xac\xfb\x3d\xa5\x0a\x41\x5e\x35\x0c\x99\x8c\x0a\x02\x80\x0a\xa5\x0f\xfd\xfe\x5f\x42\x76\xd8\xe6\xbb\x82\xeb\xf0\x47\xfe\x48\x71\x1d\xaf\x7a\x89\x3b\xdc\x75\x37\xbd\xae\xdf\x3d\xcb\x4d\xec\x5d\x24\x58\x68\x11\xf5\x9b\x25\xb1\x9e\x83\xca\x61\xe5\x59\x2f\xed\xc0\x8c\xa5\x44\x73\xce\xa2\xec\x12\x1b\xaa\x0e\x77\xfb\x2d\x9d\x76\x56\x57\xde\x67\x98\x0e\xd5\x7f\x2f\x17\x78\x58\xb6\xde\xcf\x84\xff\x90\x21\x2d\x96\x47\xf4\x1e\xed\x9b\x9d\x0e\xa3\xd8\xd6\x21\xe4\xbb\x40\x41\xac\xc5\x14\x6e\x96\xdf\xcf\x14\xea\x96\x2d\x30\xc8\xcc\xb3\x9e\xa2\xbe\x95\x8c\x9b\x87\x74\x45\x1b\xfe\xb7\xdd\xce\x71\x6e\x94\x92\x3c\xc8\x5f\xbd\x3a\x31\x30\x78\x0e\x2b\x3b\x2b\xb7\x6d\xa5\x34\x19\x12\xa4\xe9\x94\xca\xfa\x19\xbb\xa1\x97\x32\xf2\xea\x40\x2d\x71\xd3\xd8\xa9\x69\x67\x9b\x9d\x10\x42\x43\xd9\x83\x9c\x69\xee\x9e\x95\x5e\x1c\x60\x44\x97\x88\xd1\xf4\xf6\x65\x1f\x4b\xc9\xb9\x4d\x73\x52\x2e\xc0\xcf\x72\xca\xcf\xcf\x19\xf1\xf0\x3a\xd6\x23\x21\x04\xb5\x5c\xbb\x8b\x5b\xb1\xe2\x13\x44\x71\x3d\x48\x27\x42\xd6\xab\xc5\xa9\x57\x17\x4f\x62\x3b\x84\x95\x27\x2c\xc1\xe2\xb8\x31\x5e\x5c\x80\xf9\x47\xf5\x00\xc8\x3d\x85\x44\xf7\xcd\x4f\x65\x34\x89\x49\xef\x44\x20\xd7\xfc\x83\x1f\xa4\xae\x2e\xe1\x8d\xbb\xa6\x14\x92\x5c\xe1\xd7\x67\xc1\x77\xa6\x26\xc4\x52\x7a\x81\x54\xb5\x72\x92\x18\x6b\x04\x4c\xbf\x92\x89\x42\x53\xb0\x0f\xd9\x34\x3f\x9e\x69\x7b\x14\x12\xeb\xa4\x35\x97\xeb\x72\xa6\x69\xaa\xa2\xd7\x7e\xac\xb9\x68\xc2\x0f\xe1\x95\x05\xa3\x80\x74\x15\x86\x21\xb6\x06\xf7\x7d\x97\xbc\x6e\xbe\x50\xe7\x58\x92\x93\xdb\x27\xfc\x7d\xfe\x63\x1a\x4b\xee\x83\xb2\x26\x82\xa7\x73\x28\xc3\x6d\x9d\x7d\x1d\x89\x1d\x65\x21\x7c\xc4\x78\x64\xf6\x80\xdc\x8b\x5f\xd1\xa0\x1a\x0f\x7c\x34\x43\x0f\x77\x06\x0b\x69\x1a\x1a\xd2\x13\xd2\x28\x68\xe6\x1b\xbd\x38\xf4\x3f\x0c\x8b\x4d\xa6\x8a\x58\x31\x86\x66\xc0\x99\x76\x61\x70\xc2\xdb\x76\x6a\xaf\x41\x7f\x55\x6c\xc9\xa0\xa3\x93\x4e\x9f\xce\xf1"}, -{{0x4d,0xd3,0xb4,0x78,0xeb,0xdc,0x59,0x47,0x2b,0xab,0x14,0xa8,0xcd,0xd0,0xc2,0xfd,0xac,0x57,0x23,0xee,0x04,0xdd,0x89,0x17,0xc7,0xcf,0xe7,0xa5,0x36,0x48,0x5c,0x77,},{0x5b,0xcc,0xb3,0x7e,0x68,0xc2,0x34,0xbe,0xad,0x49,0x33,0x7d,0xe2,0x08,0xaf,0xba,0xf6,0x11,0x81,0x1d,0x96,0x58,0x59,0xa0,0x6d,0x31,0x30,0x12,0x47,0xd6,0x6a,0xcf,},{0x57,0x88,0xe7,0x9e,0x84,0x3b,0xde,0x9e,0xf1,0x1a,0x9d,0xfa,0xc9,0x70,0x19,0x6a,0x56,0x7c,0x63,0x08,0xc3,0x48,0xe5,0x17,0x4b,0x38,0x77,0x95,0x04,0x6d,0x59,0x0a,0x47,0x49,0x1f,0xd7,0x1d,0x97,0xae,0xaa,0x78,0xc1,0x61,0x59,0x71,0xb8,0x34,0x90,0xe8,0x59,0x28,0x20,0xf9,0x59,0x2a,0xc7,0x62,0x69,0xb9,0xd2,0xba,0x70,0x29,0x01,},"\x1c\xdb\xd2\x85\x56\xec\x44\xe8\x70\x5a\xfd\xa9\x2b\xd5\xa5\x3f\x95\xd8\xfe\x8b\x0f\xfe\x46\x33\x73\x63\x33\x16\xc5\x22\x74\xc1\x1e\xdc\xd6\x15\x51\xe3\x19\x9e\x49\x4d\xff\x6d\x90\x6a\x73\x9e\x7b\x32\x43\x03\xfc\x47\x82\x7e\x56\xde\xf0\xbd\xcc\x46\xb8\x16\x01\x7c\x71\x23\x05\x37\x02\x63\xba\xbd\x2c\x71\xbe\x47\x8f\x41\xce\x30\xb1\xdf\x63\xbe\xdd\x3b\x2e\x6a\x51\x9c\x53\xdf\x51\x58\x52\xc4\x13\x7b\xc1\xac\xa4\x9b\xf4\xc4\x63\x1f\xd6\x56\x46\x57\xd1\x1c\xd8\x3e\xa7\x3c\xc3\xd0\xcf\x9e\x3b\x3c\x3e\x7c\xa9\x9b\x4f\x12\xa9\xc9\xb6\x7c\x87\x98\x14\x8e\x0a\x0d\xc1\xef\x8b\xf5\x86\x42\xa1\x4f\x97\xa5\x72\x13\x55\x14\xc1\x0b\x19\xaa\xbe\xc2\x5a\x9c\x6b\x35\xaa\x40\x34\xa5\x7a\xae\x1b\x6d\x05\xbd\xe2\xb6\x33\x0f\x25\x1d\x78\xdb\x09\x93\xf0\xca\x4c\x26\x38\x6e\x34\x89\xa2\x09\x28\x33\xb8\xac\xbb\xc4\xf4\x91\x7f\xd3\x09\x3d\xf5\x82\xff\xf7\x1e\xce\x21\x9d\x36\x72\x45\x55\x82\x60\x9c\x0d\xb8\xd9\x6a\x70\xfc\x8a\xed\x67\x98\xde\x54\xbf\xb2\xb3\xee\x6c\x5d\x32\x8d\xb1\x63\x59\x3f\x58\x01\x9f\x38\xf3\x39\xfd\x37\x53\xf8\x96\xa4\xa2\xcc\xa8\xc1\x40\x0a\x77\xea\x39\x19\x35\xf3\x4e\x26\x39\xc5\x60\x86\x08\x10\xbb\xbe\x4b\xe1\xd1\x6e\x01\x2c\x11\x49\x0a\xa8\x4f\x29\x64\xc8\x77\xc2\x93\xb3\x00\xf4\x3d\x37\x9f\x3e\xba\x9a\xf3\x91\xde\xe5\x10\x85\x6a\x4d\xdc\xf7\x6e\x0a\x0a\xe0\x6a\x6a\x7c\x0f\x9c\x5e\x3f\xa1\xb8\x35\x4f\xe8\x97\x7b\x4e\xa3\xb2\x06\x61\x49\x1f\xa4\x61\x3b\xa6\x2f\x55\x6d\x5d\x5d\xa8\x21\x3d\x01\x21\xde\x2c\x87\x25\xdf\x0a\xae\x04\x8a\xc8\x91\xab\xbc\x06\xbd\xce\xf3\xc3\xef\xfd\xf5\xa3\x17\x49\x47\x6f\x81\x4d\xb9\x45\x79\x45\xf0\xd9\x1e\x14\x08\x00\x56\xbe\x92\x1a\x16\xaa\x96\x4a\x92\x98\x22\x1b\x15\x75\x94\x97\x3e\x32\x96\x99\x93\x31\x0c\x87\x07\xe1\x9f\x31\x43\xab\xc4\xfd\xa7\xc8\xad\x01\x60\xac\xf0\x31\xab\xa6\x52\x80\x1a\xa8\x1a\x01\x6b\x31\x37\x03\x9e\x27\xd6\x73\x8d\x02\x80\x0a\x93\xa8\x6f\x9f\x55\x85\xc5\x18\xdf\xa9\xe7\xd8\xac\x72\x7f\x37\x43\x7e\x56\xd2\x78\x83\x86\xe1\x16\x53\xa0\x4e\x16\x51\x69\xf9\x03\x97\x2a\x01\x48\x47\x51\xe7\xcb\x38\x63\x25\x90\xec\x80\xd5\xfc\xe4\x54\x16\x01\xa0\xe0\x95\x78\x5a\x9e\xe8\xd3\x59\xed\xf2\x6b\x99\x46\xe7\x98\xda\x59\x98\xcb\xb7\x36\xf9\x4e\xb7\x13\x46\x3f\x79\xf5\x61\x75\x9b\xbc\xb4\xc4\xac\x69\x3c\xab\xf2\xe1\xe0\x36\xb2\xd0\xb0\x87\x9a"}, -{{0x07,0x4d,0x92,0x18,0xc1,0x21,0x7e,0x75,0x82,0x3c,0x90,0xe0,0x10,0x48,0x4c,0x2a,0xdb,0x88,0xec,0xcc,0xd2,0xbd,0xf0,0x12,0x0a,0xa3,0xed,0xff,0xcf,0xcb,0xd4,0xbf,},{0x37,0x35,0xad,0x19,0x19,0x03,0x3d,0x16,0x17,0xb8,0x5b,0xda,0x04,0xb1,0x61,0x21,0xda,0x1d,0x86,0x1b,0x40,0x41,0x54,0xfa,0x96,0x1d,0x49,0x46,0xe5,0x5e,0xcd,0x83,},{0xb1,0xf7,0x1c,0x3b,0xd1,0xb6,0xbe,0xc4,0x33,0x37,0xe2,0x6d,0xee,0x65,0x5a,0x8d,0x5f,0x4a,0x8d,0xad,0x84,0xa5,0x11,0x84,0xb7,0x75,0xb6,0x86,0xfa,0xd3,0x1d,0x80,0x29,0xe3,0x87,0x69,0x27,0xf9,0x57,0x6e,0x90,0xc3,0x62,0x48,0x75,0xfc,0x00,0x29,0xa5,0xc1,0x0a,0x8a,0x0a,0xf7,0x5d,0x7a,0x88,0x0c,0x68,0x44,0xa4,0xa8,0x3a,0x00,},"\x6b\x5a\xa4\x0e\x91\x67\xbf\xdb\x84\x7d\xaa\x7d\x27\x86\xe2\x8e\x75\x33\xe1\xd6\xac\x53\xbe\xb6\xf6\x9b\x59\x53\x79\x5a\x2b\xf5\x9b\xbf\x7d\x14\x19\x26\x96\x8f\x50\x96\x9b\xad\x74\x2a\x4f\xb5\x79\xd3\x25\x0f\xb1\xbe\x4c\x57\xeb\xf4\xf9\x11\x2c\x70\xcd\x9f\x72\xa0\x0d\xb1\xc8\x89\x6f\xe2\xb5\xbd\xa7\xc7\x03\x0f\x49\x7c\x0b\x00\x1e\xa2\x5b\xa0\xd4\x47\xf0\x8c\x36\xdb\x8b\x90\x7c\x2f\x2a\xbb\xbb\x62\x0d\x3e\x8a\x2c\x66\xe4\x17\x12\x85\xad\xca\xad\xd1\xc1\x4f\xe2\x39\xbc\x59\x5f\x09\x83\x96\xaa\x87\x80\xff\xb8\x0f\xe1\x44\x6a\x07\x00\x1e\xc2\x34\xd8\x2a\xbd\xcd\x81\x00\x79\x39\x15\xb0\xb3\xf8\x0d\x84\xe2\x0e\x51\xea\xbc\x79\x78\x06\xf3\xbe\x81\x08\xa4\xf4\x37\x55\x0b\x06\x69\x40\x50\xa8\x29\x31\xac\x40\xc0\xa4\x89\x77\xed\xf6\xce\xd2\x42\x8d\x7c\xfe\xa8\x20\x55\x06\xde\x86\x40\x80\x65\xd1\xa1\x98\x70\xfa\x33\xa7\x08\x10\x37\xb3\xee\x44\x91\xb6\xe7\xf3\xd1\x0b\x14\xa3\x0c\x20\x91\x59\xa1\xc8\x12\x31\xa3\x5f\x03\x65\xb4\x7d\x3e\x0d\xa0\x4a\x32\xc9\x5d\x98\x33\x3c\x44\xf5\x72\xcd\xaa\xa9\x05\xd0\x69\x19\x7f\x6e\x86\x1b\x5d\xfc\xdf\xb9\xdb\x6c\x7b\x0d\x0c\xb0\x0f\x37\xc9\x16\xa1\xc4\xc0\xb8\x98\x5b\x09\xf3\x34\x09\x5e\x12\x83\xed\xfd\xd4\xe6\x2a\x29\x41\x09\x9a\x2b\x69\x36\x96\x60\x4d\x99\x43\x11\xe3\xd5\xf6\x10\x66\x83\xe1\xd7\xa1\xc7\xe5\x3d\xf7\xb7\x90\x94\x7a\x9a\x80\x1a\x0c\xcd\x48\x43\x95\xf6\xcb\xfd\x9c\xa4\xd9\x80\x4f\x18\xd5\x2b\xb0\xf9\x46\xd1\xa8\x9f\x97\xa6\xfb\x06\x80\xa8\xc4\xc0\x57\xb6\x06\x2b\x2b\x9d\xe7\xc0\x37\x48\x79\xb8\xa6\xa6\xd2\xc1\x0a\xef\x78\x05\x08\xeb\x28\xbb\x56\x9a\x08\x35\x09\x44\xc8\x2f\x6e\xf2\x8d\xb2\x30\x4d\xb6\x97\xc3\xae\x1a\xf4\x3a\x50\x0b\x0b\x97\x48\x03\xe9\xf4\x6e\xa2\xa0\x2e\x85\xed\x27\xdd\xa6\x16\xd2\x4d\x6d\xb3\xcc\x4f\x5a\xed\x82\x40\xb1\xae\xa3\xdc\xf6\x9d\xee\x5f\x14\xf9\x5e\x6e\x72\x98\x7b\xbe\x61\x89\xbc\x20\x45\xf0\xd7\x83\xa7\xb4\x7b\xfc\x19\x83\x0b\xc7\xf4\xe7\x98\xab\xe9\x02\x45\xfb\xd4\x3f\x37\xc3\xf0\x36\xd1\xcb\xf1\xe7\x3d\xcb\x1d\x9d\xaa\x87\x37\x9b\x11\x06\x97\x34\x81\xa2\x15\xc1\xf4\xf4\x6c\x16\x03\xa5\xd5\xcd\x97\xb7\x07\x6f\x1f\x5d\xc7\x89\xaa\x6a\x71\xe7\x2e\xf5\x4e\xd3\x28\xa4\xab\x64\x34\x05\x39\xff\xd1\x64\xd0\xec\x64\x5f\x32\x2d\x1b\xc3\x71\x12\xdc\x08\xd8\xc8\x07\x9d\x19\xd3\x7a\xbb\x23\x53\xf4\x8b\x5c\x49\x2f\x80\x6e\xd2"}, -{{0xd2,0xea,0x2d,0xff,0x7a,0xf0,0xba,0x2a,0x6b,0xed,0x7f,0x6c,0xc6,0x8c,0x0d,0xf6,0x64,0xa6,0xb1,0x0c,0xe8,0x01,0xc4,0x2e,0xd5,0xbb,0xe6,0x17,0xbc,0xc8,0xb8,0x4a,},{0xab,0x44,0x70,0x63,0x44,0x02,0x6e,0xd3,0x5e,0x21,0x98,0x29,0x64,0xf7,0xb4,0xdb,0xbb,0xe2,0x07,0xfd,0x27,0xc4,0x67,0x99,0x70,0x1c,0x19,0xa4,0xd8,0x8d,0x1d,0x72,},{0x9a,0xbd,0xb9,0xdd,0x2a,0xb7,0x7b,0x6f,0x5e,0x1b,0x91,0xba,0x0b,0x61,0x3f,0x5f,0x36,0x0e,0xfb,0x50,0x0d,0x3f,0xe9,0x92,0x90,0xef,0x7c,0xa1,0x4b,0xd2,0xb3,0x30,0xf4,0x05,0xa4,0xf7,0xdc,0xda,0xef,0x49,0x23,0xd3,0x11,0x1d,0x40,0xbf,0x03,0x20,0x35,0x33,0x86,0xf6,0x34,0xb4,0x0d,0xe6,0xf0,0x4d,0xe9,0x19,0x0a,0xd5,0x1c,0x08,},"\x03\xab\x5d\xae\xbc\x6e\x70\xd3\x52\x97\x79\x32\xa0\x31\x07\x87\x9b\xd5\x5d\xaf\xd0\xc6\xba\x7a\xd9\x69\x7a\x17\xb1\x27\xb3\xa7\x4a\x3e\xae\xba\xbd\x0f\x8e\xee\xbf\xc0\x48\x3d\x63\xfe\xdd\xe5\x2d\xeb\x46\xa3\x75\x24\x49\xc9\xc4\x49\x5c\x51\xa1\xc9\x1f\x57\xe3\xad\x2e\x6d\x01\xa1\x3d\x0c\x47\x0c\x52\x91\xb8\xe9\x12\x28\x83\x40\x97\x0f\xbb\x85\x78\x7b\x8b\x37\x6d\x72\x17\x52\x50\xe8\xcd\x90\xc0\x78\x88\xbf\xef\x5e\xbf\x50\x86\xc8\xff\x2a\xbc\xdd\x12\xd2\x14\xb9\xc4\x5d\x12\x08\x73\xb4\x60\x2e\x57\xa6\xaa\xb0\xb8\x28\xd1\x08\x4d\xff\xaa\x36\x51\xee\x35\x66\x26\x95\xb7\xf3\x43\x3f\x4a\xb5\x30\xc2\x9a\xc6\xcc\x5b\xb4\x3e\xcc\xd1\xb6\x89\x8b\x9e\xf7\xae\xc6\xd5\xae\xc6\x8d\x5c\x11\x14\xbb\x5d\xf7\x82\x09\x66\x59\x4c\x99\x4d\x64\x08\x91\xb8\xf2\xdc\x5d\x25\x63\x8d\xe4\x35\x49\xd8\x6d\x34\x30\x6f\xf3\xf5\x74\x57\x51\x16\x40\x5b\x9e\x8e\x28\x6e\xe0\xcd\x97\x8a\x76\x00\x2c\x44\x35\xfe\xaa\xc6\xe8\x4e\xae\x16\x54\xf3\x39\xa5\x67\xd8\xd0\x4f\xcf\xa3\xeb\x6a\x04\xb9\xad\xc6\x66\x02\x13\x00\xe9\xee\x59\x72\xb3\xdf\x5d\x4d\x0d\xd4\xbf\x79\x21\xdc\x98\xde\x82\xce\xf2\xd1\xb1\xd6\x1b\x79\x7f\xc9\x96\x8e\x11\x84\x84\xc4\x13\x42\x41\x6d\xdc\x6a\xdc\x4e\xe5\xd6\x87\xd9\x4a\x40\xce\x57\x2f\x42\xa2\x04\x86\x68\xc1\x75\xcf\x7b\x1f\x24\xc4\xef\xd0\x20\x55\x4f\xc6\xf6\x42\xe1\x4a\x57\xba\xec\x23\xe9\x5c\x25\x14\x30\x6d\x0a\x6d\x33\x64\x88\x41\x49\x7e\xac\x48\xea\xbd\x96\xd0\x47\x31\xba\xb0\x8b\xf5\xea\x9d\x43\xe0\xcf\x9a\x37\xfa\xaf\xa7\x32\x86\x9d\x68\xe7\xd5\xfe\x69\x54\xf8\xa3\x19\xef\x55\xda\x1e\x17\x8e\x43\xe8\x4a\x3b\x9a\xa3\xad\x00\xc2\x9b\x1d\x16\x11\x63\xdf\x4b\x79\xf2\x88\xe9\x39\x1d\x70\xa2\xf8\x81\x3d\x66\x62\x2e\x8a\xc3\x33\xfa\x6a\xa5\x31\x1e\xab\xec\x38\x3b\xa4\xcc\x12\x28\x15\xde\x00\x88\x77\xef\xbe\x6e\x12\xc3\x22\xc9\x75\x43\x4a\xfa\xd1\x73\xeb\xe2\x42\x03\xd9\x16\xd5\x75\x78\xbd\x2b\xca\xcc\x78\xf6\xe2\x56\x45\x13\xf8\xd1\x13\xa8\x33\xc2\xc2\x26\xeb\x97\xba\x2e\x23\x36\x1a\x5d\x02\x66\x4a\xb3\x77\xf9\x64\xc4\x30\x0b\xe2\xd7\x7b\x62\xd9\x24\x08\x23\xa0\x98\x84\xdf\x30\x7e\xff\x3b\xe5\x66\x4d\x72\xd1\x1a\xd5\x13\xe1\xbc\x56\x10\xdb\xfd\x10\x09\xdb\x39\xf0\xcb\xfe\x47\x05\x55\xec\x1b\x56\xb8\x71\x67\x07\x93\xd3\xb7\x04\xfb\x06\xee\x95\x0b\x1a\xd2\xa4\xd7\x29\x7c\xa5\x8b\xba\xd8\x10\xc3\xfa\xd4"}, -{{0x7a,0x60,0xcd,0xf1,0x87,0x04,0x60,0xde,0x8a,0xe7,0x78,0x11,0x76,0xd5,0x12,0x7e,0x71,0x20,0x7f,0xaf,0x2f,0x21,0x0b,0xd4,0xdc,0x54,0x73,0x85,0xb6,0x67,0xf2,0xf2,},{0xea,0xd6,0x7a,0x9c,0xf3,0x4d,0x0f,0xf1,0x4e,0x79,0xaf,0xa4,0x6f,0x2d,0xc9,0x96,0xe9,0xac,0x0e,0x3e,0x07,0x63,0x22,0xfb,0xb4,0x00,0x97,0x67,0xb1,0x33,0xf0,0x1b,},{0xb2,0xe0,0x81,0x42,0xbd,0xd6,0x2b,0x78,0x65,0x92,0xc0,0x91,0xf5,0xfe,0x6a,0x9b,0x7f,0x30,0xce,0x13,0x4c,0x3b,0x23,0x6f,0xbc,0x6d,0xfe,0x67,0x34,0xf8,0x82,0x70,0xac,0x58,0xf6,0xd7,0x4b,0x4f,0xd9,0x9c,0x22,0x45,0x1c,0xa4,0x65,0xa4,0x2c,0x00,0x6d,0xb2,0x5a,0xf2,0x15,0xed,0x24,0x1a,0xf1,0x18,0x96,0x27,0xc6,0x05,0x0f,0x00,},"\x9d\xc0\x23\xa5\x25\xd0\x1b\xa3\x51\x37\x98\xb7\x38\xc7\x91\x62\x92\x6e\xbc\xcc\x0a\xdf\x1e\x57\xac\x47\xc2\x0d\xea\x6c\xe1\x37\x5c\x3d\x2a\xaa\x17\x33\xb7\xf0\xc3\xbd\x94\x5c\x33\x5f\xf3\x57\x61\x12\xbb\xdc\x10\xb6\x78\x3b\xa6\x54\xe8\xc6\x10\x47\xf2\x77\x3a\xa2\x29\xbf\x84\x69\x22\xa8\x9c\x6a\x73\xd5\xf1\x05\x1e\x8d\x96\xed\x36\xd7\xd6\x74\x7e\x06\x3a\x7a\xc6\x02\xf1\x9f\xc5\x2e\x02\x1a\x4b\xbc\x28\xb0\x35\x14\xfb\xd5\x1c\x7b\x3f\xd6\x59\xf1\x2d\x54\x7d\x05\x92\xdd\x09\xf8\x73\xc9\xec\xc6\x43\x9c\x7e\x93\x1a\xd0\xe4\x85\x6b\xe3\x1c\x60\x5d\xef\x2e\xd9\xb5\xd1\x3c\x59\x42\xb2\xf3\x25\x39\x7d\xac\x6c\x97\x60\xe9\xb1\xbb\x0c\x06\xf7\x13\xcb\x92\x0c\x23\x4b\xcc\xfe\xe9\xf0\xb8\x5d\xd0\x20\xf7\x98\x8f\x3b\xe1\xcc\x66\xe9\xe5\x1b\xab\xe2\xfe\xe2\x37\xeb\x84\xec\x7e\xff\x94\x09\xaa\x91\xc1\x94\xe3\x0d\xb1\xe0\x65\x01\x59\x55\xde\x97\x46\xbb\xa0\x3f\x7e\xdf\x9a\x58\x75\x12\x40\x9a\x41\x61\xfa\x77\xea\x62\xcc\xf4\x31\x60\x2d\xcd\xcf\x36\x5e\xd6\xbf\x0a\xed\xdd\x32\xf7\xc8\x44\xe3\xa3\x4d\x26\x6e\x28\x38\x2f\x40\x62\xfd\x4d\x6f\x82\x14\x25\x21\x04\xd6\x43\xa9\xbf\xd8\x07\x17\x16\x37\x1c\xcb\xb5\x4c\x8c\xc8\xdb\x79\xad\xd6\x5b\xcb\xce\xa0\xd0\x80\xd8\x40\x28\x03\xfe\x23\x2d\xf7\x0f\x76\x57\x72\x47\xa6\x3d\x55\x83\xbb\xd5\x64\x27\x67\xbc\x63\xf3\xc5\xa7\xbb\x3a\x47\xeb\x12\x98\x4e\x45\x41\xf4\x1f\xdb\x55\x86\x9a\x08\xfa\xde\x66\xc2\x0f\x69\xa5\xa9\xde\x25\xf6\xb3\x6b\xa1\x8a\xce\x5b\x4a\xc3\x36\xbb\x2a\x8e\xbf\x63\x0a\xd0\x3e\x8b\xb8\x73\x1d\x01\xe8\x4b\x91\xd0\x24\xd1\x17\x45\x9a\x74\x89\x2e\x93\xd5\x3b\x61\xe6\xb8\x06\x8e\x4f\x04\xb4\x18\x1f\x03\x87\xb4\x56\x7c\xcd\x45\xe1\xb8\x71\x8a\x2d\x7d\x78\x78\x72\xf3\xdc\xf8\x7a\x15\x93\x5a\xd7\xda\xaa\x74\x4e\xd6\x8a\x28\x66\x6a\x51\xa1\x0d\x39\xfc\x13\x9c\xdf\xe9\xa6\x87\x30\x76\xf7\xc4\x25\x00\x9c\x38\xfa\xee\x13\x5e\x51\x32\x07\xb0\x6e\x7b\xa3\x56\x85\xf5\x07\x2d\xa3\x4b\x60\x45\xb5\x7c\xd5\xd1\xb1\xa1\xfd\xf0\x17\xb8\xaa\x8e\xbd\x27\x52\x2b\xc9\x5e\x47\x90\x87\x34\xe4\x17\x22\xa7\x67\x90\x5c\x5e\xcc\x30\xc7\x24\x81\xb6\xc1\x2b\xf4\xac\xe9\x4d\x5b\xb3\xa3\x15\x56\x91\xb7\x07\x5b\x40\xeb\xf5\x96\x8f\xdd\x90\x3d\x8f\xd3\xcc\x50\xb8\xd6\x46\x48\x59\xb1\x0f\x75\x51\x32\xc6\xd9\xb6\xda\xd1\xd6\xf1\x4c\x41\x85\xb2\x64\xd3\x49\x7a\x4e\x54\x98\x77\xfe\x94\x6e"}, -{{0x33,0x79,0xd2,0x5c,0x11,0x17,0xcf,0x80,0x2e,0xc7,0x9c,0x06,0x57,0x5d,0x18,0xe6,0xbe,0xce,0x4c,0x70,0x93,0xdd,0x43,0xfd,0xee,0x03,0x68,0x5c,0x70,0xb2,0xfa,0x9f,},{0x85,0x25,0x15,0x6f,0xe2,0x9f,0xc2,0xfb,0xf6,0x61,0xba,0x50,0x18,0x2b,0xe2,0x0c,0x89,0x98,0xd9,0x41,0x49,0x3d,0x59,0x33,0xdc,0xa4,0xd8,0xb4,0x1f,0xb4,0x42,0xd5,},{0x4c,0x36,0xbf,0xc8,0x1e,0xef,0x00,0xb9,0xcb,0x3a,0xb5,0x14,0xc6,0xd4,0x51,0xb9,0x93,0x36,0x1e,0x09,0xa4,0xbe,0x4b,0x50,0x40,0x92,0x6f,0xeb,0x0e,0x0d,0x9b,0x52,0xf0,0x3d,0xe4,0x68,0xe7,0xba,0xd8,0x3f,0x37,0x91,0x54,0xbf,0x2c,0x43,0x7a,0x71,0xf7,0x54,0xf3,0xf4,0x07,0x98,0xee,0xeb,0xd6,0x2e,0x55,0xf2,0xbe,0x77,0x14,0x03,},"\x7a\xcd\xb3\x9f\x12\x26\xbd\x3a\xbf\xfa\x50\x35\x0a\x14\x97\xd7\x61\xf8\xf0\xaa\xef\xbf\xbb\xbb\x92\x5f\xf5\x63\xe3\x89\x76\xaa\x17\x2d\x40\x7b\x61\xff\xdf\xb1\xcd\x53\x8a\x4c\xd0\x00\xb5\x78\x18\xa0\xbc\x92\xc0\xe0\xcd\x0a\x5a\xbf\xcf\x57\x83\x00\xf5\xf4\xe6\xce\xfa\x26\x72\x75\xd1\x78\x45\xda\x70\x66\xfd\x4e\x18\x01\x00\x27\x96\x0c\xd3\x95\xe6\x82\xad\x71\xaf\x34\x9b\xbd\xad\x5e\xba\xa0\xf1\x1a\x77\x61\xe1\x9e\xa1\xbe\xf6\x61\x07\x43\x16\x4b\x17\x14\x14\x53\xb4\x72\xae\x2c\x8f\x36\xce\x6b\x08\x0f\x1c\x07\x45\x35\x24\x54\xce\x5a\xea\xe1\x1c\x9d\x75\xde\x3c\x08\x00\x42\x65\xfc\x4c\xa8\x0d\x33\xb2\x6e\xae\x14\x00\xdf\xd8\x97\x7b\xf7\x23\xa6\x16\xda\xeb\x6d\x42\x19\x90\x10\xb7\x3e\x19\x3a\xb7\x2a\x58\xbd\xd2\x48\xa7\xf4\x11\x1c\xa5\x0c\x1d\xe6\x46\xbf\xea\x7b\x4d\x5b\xaf\x0f\x93\xdd\x97\x3e\xe9\x36\x49\xe2\x1e\xc0\xc6\xc4\xfc\xca\x8c\xd6\xff\x69\xdf\x76\x16\x12\x02\x1d\x85\xff\x1f\xb2\xa9\x53\x37\xda\x48\x05\xa7\x6d\x34\x7e\xe7\x1e\xf1\x9c\x0d\xff\xb5\x9f\x15\xf6\x50\x29\x3a\xbb\x97\x21\x05\x3f\x74\x06\x90\x5a\xe6\x83\xf9\x6c\x83\xa3\xa7\x44\x7b\x1a\xfb\x14\xe1\x20\x8c\x63\x9f\x37\xa9\x75\x0b\xa2\x1d\xa5\x55\x2c\xc2\x04\xea\xc4\x53\xca\x03\x62\x82\xf7\xe0\x96\x10\x93\xc3\x9e\xc1\x18\x13\x8d\xcf\x71\xcf\x2d\x28\xfb\x96\xa2\x49\x62\xb5\x2d\x33\x93\xf8\x80\x65\x3b\xcb\xa2\xc9\xb9\xd5\x7b\x77\xc5\x22\xf4\x21\xfc\xf5\xad\x75\xfb\xa9\xcf\x33\x89\xb1\x23\xaa\x97\x52\x17\x13\xff\xf8\x84\x67\xde\xb8\xc8\x99\x1d\x4b\x57\xc1\x43\x81\x70\x53\x7c\xb5\x0c\xdc\xc6\x57\xe5\x0e\x5c\x48\x0e\x12\xc0\xd4\x49\x39\xb6\x39\x99\x44\xe7\xc7\x1e\x18\x6c\x2a\xbb\x81\xfc\x57\x34\x88\x36\xd5\xe5\x7b\x72\xb2\x24\xa6\xb7\x1b\x6c\xaf\x72\x1a\xca\x73\x47\x8c\xb6\xcf\x5f\xb8\x90\x71\xae\x3a\x39\x82\x02\xdb\xb3\x8c\x30\x81\x25\x63\xbb\x9a\x23\x40\x66\x57\xa9\x56\xd3\x05\xa3\x44\x9a\x60\xcc\x86\x41\xb6\x21\x75\xa7\x17\x0c\x23\xbd\x5a\x25\xf0\xf1\x2e\x15\xa7\xed\x91\xfa\xda\x6a\x4a\x2f\x0e\x7b\x15\x5a\x3d\x64\x85\xec\x03\xce\x6e\x34\xdf\x7e\x21\x62\x40\xbb\x28\xa2\xdd\x73\x2f\xf7\x90\xd2\x28\x6e\x20\x0b\x33\xc2\x9a\x31\xa5\xe1\x9a\xd2\xcd\x02\x97\x4b\xad\xc4\xbc\x22\xde\xb7\x50\x4c\x15\x24\x1f\xc1\x06\x0c\x8a\xce\xf4\xfb\xb2\x5e\xc7\x60\x2f\xce\x36\xa2\x7b\xb8\x7b\x6e\x64\x23\xe6\xb4\xf6\xe3\x6f\xc7\x6d\x12\x5d\xe6\xbe\x7a\xef\x5a"}, -{{0xef,0x38,0xc3,0xfc,0x74,0xf0,0x54,0xae,0x43,0xe8,0xd2,0x9d,0x6b,0xa6,0xdc,0x80,0xb5,0xaf,0x84,0x82,0x70,0xd4,0xaf,0x58,0x84,0x4d,0x24,0xbc,0xf9,0x87,0x41,0x4e,},{0x0a,0xe1,0x47,0x8b,0x05,0xfb,0x32,0x99,0x65,0xea,0x0f,0xa9,0x28,0xdc,0xbe,0x81,0xa0,0xbd,0xbb,0x6f,0xf6,0x6c,0x81,0x16,0x71,0x63,0x5e,0x43,0x88,0x88,0x80,0x51,},{0x1d,0x3a,0xc6,0xb6,0xbf,0x18,0xab,0x53,0x09,0x14,0x87,0x99,0x48,0x5b,0x27,0x6d,0x20,0x40,0x1c,0x6a,0xf5,0xf9,0xb2,0xf6,0x03,0x23,0x95,0xa3,0xc2,0xf4,0xb6,0x73,0xb7,0x14,0x0c,0x07,0xcc,0x26,0xf4,0xfc,0x56,0xa5,0xee,0x00,0xb0,0x74,0x6b,0x2a,0x80,0xda,0x6f,0xda,0xd1,0x7e,0xdd,0x11,0x49,0x20,0x10,0x1d,0x2c,0x89,0xc3,0x0e,},"\xbf\x29\x0d\xb3\xdd\xa8\x76\x39\x37\xae\x4c\x83\x74\x67\x05\x32\x72\x95\xc2\xc2\x48\x06\x8f\x5a\xb8\x5c\x8b\x5d\x75\x6f\x4e\x3e\x34\x06\x2b\x55\x49\x38\x72\x61\x47\x6b\xcb\xd1\xe7\x33\x19\x90\xf1\x19\x10\xd1\x1f\x94\x60\x7c\x2b\x71\xf6\x5b\x77\x1a\xac\xab\xdc\x10\xf4\x2a\xe9\x18\xdd\x25\x94\xac\x71\x05\x1c\x85\xb3\x30\x77\x9c\x47\xaf\x00\xa5\xb9\x81\x91\xb5\x6c\xbc\xf7\xef\xe4\x1a\x27\xe8\x7c\x67\x71\x68\xc8\xab\xe9\x49\x6e\xb2\xe7\xab\xbd\x0b\x16\x04\x28\x6e\xd1\xa1\xb1\x8d\x26\x4d\x73\x3d\xe8\x7d\x0d\x3f\x80\x55\x52\x8c\x4d\x42\x6d\x7f\x8e\x6e\xd0\x24\xa7\x41\x40\xab\xd3\x54\x00\x79\x62\xa2\xa9\x7a\x5c\x2f\xf9\x76\x54\x6a\x8d\x1a\xc4\x92\x4c\x09\x22\x3d\x34\x8d\xdc\xd8\x71\x0a\x37\x99\xf9\x1b\xb8\x70\xb3\xf4\x6d\x51\xf1\xe7\xf6\x89\x2d\x6b\x08\xb9\x91\x74\x8a\x03\x7a\x86\x7e\xcc\x39\xee\x8d\x64\x62\xa7\x61\x44\x88\xed\xd3\xc2\xba\x61\x5c\xa2\xe3\x78\x54\x88\x94\x41\xb1\x3d\xc8\x35\xc3\x6b\x38\x65\x3f\x65\x98\x61\x6f\x35\x78\x3e\x2e\x15\x83\x84\xbb\x93\x1c\x90\x1b\x70\x3a\xcb\x39\x91\xfb\x7a\xa5\xba\x69\xd9\xa5\xbd\x05\x70\x24\x29\x61\xa7\x1a\x52\x47\x03\x15\xe9\x82\xe3\x41\xa6\x1c\x64\xa6\x19\xbd\x16\xfe\x81\x19\xaa\xe0\xd7\x50\x3c\xe7\xd7\xe9\x26\x14\x6b\x91\xc2\x89\x2f\x13\x16\x69\xd1\xe3\x9e\x5b\x75\xe9\xc7\x24\x52\x61\x80\x99\xa5\x7d\xc2\xee\x37\x7b\xe6\x58\x75\xee\x01\xbb\x88\xed\x52\x6f\xc3\x94\xe2\xf5\xc8\x12\x7a\x5f\x69\x12\x5e\x67\x38\x5e\xf9\x4b\x1f\x33\xad\x52\x62\x9d\x72\x0e\x31\xc0\x2a\xe0\xb5\x82\x33\x9f\xf0\xf0\xbb\x07\xff\x2b\x03\x0f\x48\xfa\x7b\x69\x27\x16\x50\x1a\xd7\x77\x3a\xd3\x15\x12\x04\xa2\xa5\x40\xfa\x94\x36\xbd\xd4\x20\x2a\x15\x73\x09\xec\x36\xce\xcb\xe5\x8b\x33\xef\xf5\x57\xfd\x33\xe0\x3f\xd3\xeb\x19\x00\x9b\xd7\xa2\xde\xa9\xef\xee\xf8\x78\x55\x67\xaa\xb2\xa4\xc9\x8b\xd1\xf2\xa8\x10\x11\xb3\x43\xa9\xf2\x0c\x44\xc5\x77\xa4\x52\xfd\x54\xba\x21\x02\x9d\x47\x06\x81\x3b\x29\x87\xc7\x6b\xb2\x42\xab\x26\x20\x84\x3c\x22\x60\xb6\x69\xad\x35\x8e\xfe\xe7\xf9\x83\x0d\xc9\xc7\xd4\x78\xa2\xde\x4a\x2c\xf8\xc4\x3d\xa7\x70\xe2\x88\xe2\xed\xbb\x6d\x73\xbc\xf2\xec\xb0\x23\xde\x6b\x2d\xcc\x6b\x16\x6e\x87\xa3\x85\xeb\x0a\xdc\x30\x56\x65\xc5\xbf\xa5\x7f\x25\x0f\xe2\x23\xad\x7f\xf4\x51\x8d\xe3\x9c\x79\xe8\x7d\xc1\x01\xa9\xfa\xa6\x82\x1a\x74\x44\x2b\xfc\xfd\xf0\xa9\xe6\x3a\x50\x9e\x2a\x2e\x76"}, -{{0x7e,0x7b,0x39,0xaf,0x69,0x38,0x0c,0xf4,0x46,0x60,0xe2,0xc1,0xff,0x30,0x83,0x34,0xe8,0x25,0x0f,0xee,0xb8,0x8b,0xe0,0xd4,0x3a,0xab,0xe5,0xe6,0x8b,0x8e,0xf1,0x71,},{0xcc,0xef,0x9d,0xae,0xd9,0x25,0x23,0x53,0x3d,0x4a,0x2d,0xab,0x6d,0x24,0x19,0xf6,0xd0,0x86,0x04,0xdb,0x64,0xce,0x37,0xe3,0x29,0x04,0xac,0x77,0xb9,0xb4,0xa0,0x1c,},{0x10,0x62,0xa2,0xdc,0x9c,0xd5,0x37,0x96,0x75,0xc0,0x4f,0x5e,0x21,0x33,0x8d,0xcf,0xb7,0x7d,0xfb,0xab,0xce,0xdd,0x62,0xb2,0x60,0x71,0x00,0xd7,0x64,0x9a,0x05,0xe8,0x08,0x71,0xe9,0x61,0x23,0x21,0x4f,0x80,0xf4,0xf7,0x3b,0x0d,0x9b,0x06,0xe2,0xd3,0x1f,0x56,0x11,0x9c,0xea,0x69,0xda,0x23,0x47,0xda,0x84,0xa2,0x75,0xb7,0xb2,0x07,},"\xd4\xa3\x97\x6d\xbf\x83\x20\x18\x56\x67\xb5\xa8\x23\x66\x40\xf2\xeb\xc9\xe4\x5e\x6d\x5f\x2a\x8d\x92\x99\x79\x27\xdd\x9b\xc5\xdb\x95\xf4\x46\x34\xbd\x65\x4e\xef\xec\xe1\x0d\x99\xd9\x2b\x46\x71\x57\x91\x64\x50\x04\xac\xcc\x6d\x14\x0f\x32\xa1\xc8\x72\xe5\x4a\xa9\xa7\x49\x3a\xf9\x45\x88\xb7\xbb\x40\x0d\x94\xd4\x58\xd4\x32\x92\x30\x7c\x5a\x1a\x38\x82\xa1\xc8\xa6\xa7\x8d\x9a\x94\x5f\x79\xd6\x4b\x32\x94\xa2\x8c\x3d\x59\xd8\x20\x22\xb0\x09\xcc\x4d\x2d\xa9\x3a\x16\xb0\x71\xc9\xab\x8e\xe9\xa3\x66\x3d\x72\xed\x34\x4f\x15\x1d\x68\xc6\x66\xa4\xb4\x96\x52\xd9\x7a\x46\xd1\x42\xa4\x74\x11\x27\xf3\xc5\x7f\x15\x51\xc4\x09\x76\xcd\x13\x81\xa8\x2a\xea\xe7\xbc\x5a\xdb\x39\x87\x20\xeb\x43\x3f\x08\x99\x48\x7e\xd2\x37\x84\x46\xb1\xa8\xdc\x6a\x33\xfc\xd4\x53\x7a\x05\xfb\x60\x3e\xc0\xa9\x0a\x27\x53\x23\x00\x24\x2b\x20\x00\x10\x86\x21\xb6\x5a\xb0\x00\xbc\x06\x38\x15\x30\xf6\x90\xd7\xe5\x6f\x81\x60\x4d\xac\xff\x19\x10\x71\x50\x40\x41\x0a\xa1\xf9\x44\xc9\x2d\xd9\xbb\xaa\x5b\xd0\x8e\xa0\x0c\x84\x42\xdf\x94\xf0\x85\xeb\x3d\xe9\x73\x35\xb6\x00\x5e\x6f\x84\xf8\x23\xd4\x34\x70\xab\x1c\x67\xda\x12\xad\x44\x99\x36\xc6\xb5\x5f\x9f\xfd\x20\x3d\xfd\x6e\x3f\x33\x30\x9e\x8a\x99\x45\xa5\x93\x20\xe6\x67\x34\xc7\x9c\x48\x14\xdb\xa5\xa1\xc1\x40\x95\xc6\x29\x25\xa1\xe1\x73\x3e\xfd\x94\x81\x7a\x25\xef\x9e\x47\x9d\xd9\xcc\xde\x6c\xa8\xad\xb7\xa8\x05\x3c\x1b\x55\x13\x46\x97\x50\x4a\xf8\x05\x3d\x59\x5b\x84\x46\x40\xb6\x1e\x93\x16\x80\x75\x46\x84\x50\xeb\x5d\xe0\x35\x86\x97\xc1\x04\xaf\xa6\xa3\x79\x6a\x50\x9c\x26\xb4\xc2\x77\xc2\x3f\xff\x42\xdf\x14\x6d\xe5\x5e\x95\xd0\xd4\xb8\x0a\x7a\xa1\x77\xd9\x92\x27\xec\xb2\xa0\x59\x4d\xee\xde\xbb\x9c\xaf\xb1\xa4\x58\xac\xa8\x07\x2c\xc7\xd7\x7c\x71\x75\xf6\x10\xca\x30\x0e\xfd\x7a\xf9\x38\x83\x46\x49\x8c\x22\x99\x15\x64\x50\x0e\x0b\x0a\xa4\xd2\x94\x6f\x18\xe6\xf5\x37\x5a\x84\x82\x86\xf3\x69\x54\xc1\xca\x22\x68\x4c\x69\x28\xc2\xa2\x5c\x7f\xe2\x1a\xba\x4a\x71\x11\xd7\xe0\x5b\xc8\xd7\x0b\x3d\xcb\x4f\x6a\xae\xc0\x64\x84\x5e\xef\x55\x25\xf8\x50\x24\xc2\x57\x0f\x3b\x78\x69\x8c\x4b\xce\xc0\xd7\x1a\xad\x53\x78\xd8\x81\x9e\x1f\xac\x44\xee\x41\x63\x70\x21\x2d\xba\xaa\xe5\x4d\x2a\xf2\x93\x9b\x82\xcb\xaa\xe7\xf4\x2f\xf4\x85\xd4\x5b\x3a\xcc\x21\x09\x0f\x5b\xa4\x1e\xc0\xda\x30\x9e\x52\xef\x28\x38\xd1\xde\x47\x1e\x0b\x7c\xf9\x85"}, -{{0xa9,0x04,0x8a,0xf0,0xc2,0x0a,0x12,0x5f,0x5d,0x39,0xc5,0x0f,0x22,0xb8,0x05,0xae,0x74,0x2c,0xf6,0x4f,0x1f,0xe8,0xdf,0xbe,0x8d,0xfd,0xaa,0x51,0x1a,0xaa,0x57,0x6f,},{0x15,0x86,0x55,0xdb,0x94,0xb1,0x5c,0xa7,0x29,0x83,0x87,0x7b,0x6d,0xb2,0x31,0xa5,0x84,0x3d,0xf5,0xdb,0xca,0x28,0x10,0xa7,0xe4,0x96,0xfb,0x59,0xab,0x71,0x04,0xca,},{0x18,0xa3,0x12,0xb2,0x0d,0x86,0xac,0x33,0x9a,0x58,0xef,0x2b,0x85,0x2d,0x46,0x7c,0x23,0xbb,0x2c,0xb1,0x22,0x7c,0xb1,0x53,0x38,0xaf,0x07,0xfd,0x04,0xb9,0xa7,0x11,0xe8,0x56,0xee,0x5b,0x2c,0x82,0xe3,0x66,0xc1,0x7f,0x86,0x17,0x13,0xd1,0x08,0x8c,0x1b,0x21,0x44,0xd1,0xc3,0x7d,0x05,0xbd,0xc0,0x0d,0x73,0x96,0x73,0x85,0x20,0x00,},"\x8e\xef\x2d\x9f\x5d\x59\x70\x99\x59\xc9\x24\xf8\x7c\x22\x78\x97\x67\x39\x3a\x15\x5d\x5c\x87\xde\x48\x8c\xef\x50\xb7\xbf\x7d\xa8\x70\xe3\xad\xc3\x00\xae\xe6\x60\x3b\x2e\xf0\x87\x64\xd9\x9d\x9e\x77\x51\xe5\xdc\xe9\x2a\xaa\x71\xaa\x18\xa6\x9c\xc8\x23\x13\x4e\x85\x52\xd9\x59\xa0\xdb\xb4\x11\x17\xe0\xa5\x93\xc3\x18\x33\xb6\xec\x21\x72\xdd\xaf\xaf\x78\x48\xdd\xd1\x8d\x28\xd0\xd4\xed\x33\x23\x7e\xc8\x04\xf6\x59\x38\xae\xd8\xe8\xa3\x28\x0d\x42\xe3\x53\xd0\x1b\xe0\x18\x7b\x13\x01\xf8\x3d\x89\x84\x90\x67\xb0\x4a\x90\x31\xf7\xe0\xf3\x3e\x34\x16\x24\x0c\x53\xd9\x26\x5e\xd0\x66\x39\x59\x97\x1f\x41\x7c\xb5\xf2\x10\xcd\xc5\xae\xbc\xb5\xe1\xdb\x7d\xfb\x82\xdf\x43\x58\x76\xa6\xe9\x8f\x41\x5b\x0d\xf8\x69\xf0\xd8\x85\x15\x35\x37\x56\x45\xee\xf7\x0f\xae\xc7\x44\xee\x0d\xc3\xac\xbc\xb0\x40\xf6\x8d\x50\x2c\x2c\x62\xc8\xdb\x45\xeb\xe5\x48\x54\xa4\xb3\x6f\x43\xfe\xb4\x9a\x6d\x1c\x2c\x2e\xa7\x99\x14\xa7\xc2\x3c\x60\xba\xaa\x67\xcb\x47\xb2\x17\x8e\x12\xdc\xe7\x6b\x00\x4c\x87\xb7\xb8\x34\x6e\xfa\xdf\x38\x0b\x9e\x1e\x41\xf6\x31\x48\xda\x51\x78\x1d\x75\xce\xc0\x40\xe4\x26\x88\x20\x21\x1f\x3c\x46\x25\x01\xd8\x08\x99\x89\x4e\x79\xd6\x18\xde\x42\x46\x1d\x78\x5a\xea\xce\x53\xae\x14\xb7\x9d\x33\x50\x1e\xd5\x62\x9b\xbd\xd0\x71\x28\x15\x6d\xb0\x72\x5f\x5b\x4b\xed\x59\x3a\x95\x29\x47\x83\x03\x84\xf6\x1d\xf0\x0e\xe0\xaa\x09\x90\x99\xc3\xcd\x97\x65\xa9\xc1\xc7\xe8\xa6\xa8\x34\x30\xb8\xd9\x86\x7c\x8e\x17\x92\x0a\xd0\xff\x64\xd8\xcd\x2f\xf5\xf1\x14\x38\x8c\xe6\xd4\x3e\xec\x17\x15\xd0\x35\xf0\x22\xfa\x97\x96\x9e\x1a\x5d\xd9\xf5\x8d\x89\x6b\x17\xc1\x22\x1c\x9e\x6c\x85\x55\x59\x72\x35\xee\xda\x6e\xc4\x1b\x0c\x11\x76\x12\xb0\x0c\x5f\x0e\xd1\x81\x6b\x05\x73\x63\x58\x27\x07\xa8\xaa\x0d\x98\xd4\xd4\xbe\x5e\x8f\xa3\x2d\x6c\x9d\x27\x82\x21\xef\x30\x67\xb8\xba\x15\x16\xd9\xe0\x51\xd2\xf6\x8b\x7d\x1b\x15\x1f\x74\xa3\x53\x4e\x78\x12\xc0\x51\xe5\xf2\xb6\x3b\x30\x35\xf8\xe5\x70\x3b\x5f\x68\xfd\x2d\x65\xbb\x75\x65\xe8\xaa\x67\xbf\xd2\xa1\x2c\xaf\x0b\xc5\x48\x11\x97\xa9\xff\x89\xd7\x7d\xf7\xa0\xe9\x65\x5e\xf0\x29\xb4\x3d\xd9\x06\xd0\xb8\x88\xe3\x13\xae\x9d\x1c\x7e\x93\x68\xa0\x13\x52\xd0\x0c\x66\x80\xdd\x0f\x1f\x57\x4a\x58\x77\x34\x8a\x7e\xa2\xc0\xb9\xe8\xe2\x72\x75\x10\xbf\x0c\x9e\xf7\x44\xf3\x69\xeb\x3c\x6c\x4f\xc1\x6a\xde\xb6\xe1\x94\x5b\xe8\x28\x7d\x0f\x30"}, -{{0xf8,0xc9,0x18,0x3f,0x23,0x10,0x5f,0xad,0x0c,0x6e,0x51,0x03,0x35,0x8b,0x58,0x32,0x88,0xf9,0xff,0x6c,0x7d,0xfc,0x91,0x10,0x6d,0x07,0x98,0x7f,0xf6,0x9c,0xe1,0xeb,},{0x4c,0x79,0x62,0x8c,0x95,0x8c,0xde,0x0c,0xc3,0xcf,0x68,0x60,0x95,0xb8,0xa2,0xf4,0x4b,0x71,0x93,0xc6,0x16,0xf5,0x1b,0x21,0xb6,0x70,0xb0,0x38,0xce,0x6f,0x67,0xff,},{0xc6,0xa8,0xbc,0x7a,0x0d,0x5c,0x61,0x85,0xb6,0xec,0xd6,0x03,0x3e,0x42,0x32,0x1d,0x5c,0x87,0x1b,0xf8,0x89,0xbe,0x72,0xbd,0x54,0xcc,0x00,0x83,0xed,0x60,0xa4,0x70,0xb2,0xcc,0x0f,0xb4,0x68,0x2c,0x89,0x4c,0x75,0xb0,0xdf,0x95,0xf1,0xec,0xfb,0xba,0x2d,0x5a,0xce,0xf3,0xe1,0xaa,0xfe,0x54,0xb9,0xf7,0xe8,0x03,0xa1,0xd0,0x15,0x0a,},"\xb1\xd6\x05\x95\x32\x3f\xf3\xc8\x44\x87\x41\x90\xe1\x83\x6e\x41\x01\x40\x9c\xbc\xea\xe2\x8d\x5d\xa8\x1f\xad\x29\x8f\xe4\x7f\x6b\xdf\x44\x74\x5b\x7c\xd0\xd3\x71\x31\xc3\xec\x36\x5b\x92\xf5\xa1\xa6\x9c\x09\xfe\x2d\x9e\x81\xda\x10\xcf\x19\xd8\x5f\xf5\xff\x26\xf9\xe7\xdb\x9f\x07\x93\xb2\x5a\xb2\x6e\x6a\x74\xf4\x4e\xb8\xc4\xf0\x78\xeb\x7a\xd1\x8e\x65\xa1\x62\x10\xd5\xc8\x44\xd3\xce\xf7\x5f\x1d\xaf\x44\xee\xe5\x58\xf9\x0e\x52\x4a\x03\x2b\x6c\xae\x6c\x8d\x23\x36\x7c\x28\xce\x1c\x75\xfc\x25\xac\x87\x43\x39\x77\xd5\x97\x53\x3c\x92\xae\x65\xf2\x91\x3a\x18\x90\x7a\xc7\xd9\x54\x3d\xf2\x41\x27\x74\x39\x43\xfe\xfd\x9c\xf8\x3e\xd8\x33\xf6\x3e\xc8\x36\x72\x33\xd8\x97\xbf\xa1\x2d\x46\x6d\x2c\x4a\x9a\xd7\x0d\x5a\x67\x2f\xc1\x07\x75\xea\x2d\x20\x4e\x63\x6d\xe7\x01\x07\x88\xda\x27\x1d\xf0\x38\x81\xa2\x5c\x8d\xfa\x5a\xf7\x3e\xe5\x59\xf8\x1b\x52\x9b\x35\xaa\x12\x7f\xdc\x0e\xe8\xfd\x36\x9c\x7a\x04\x36\x62\x39\x86\xaa\x64\x07\xfa\x67\xa1\x42\x0c\x46\xf3\x21\x1a\xb8\x4f\x84\x46\x6d\xd5\x8b\xb7\x95\x08\xa1\xfe\xb0\xa5\xa5\xdc\x3b\xb0\xc1\xb2\x48\x09\x82\x62\xa0\x64\xf3\x7b\xb2\xf0\x19\xe2\x90\xc6\x0a\xfa\xa1\x20\x66\x51\xa2\x69\x7c\xaa\xcc\x3e\xcc\x02\xec\xfc\x07\x7f\x27\x2e\x8f\x75\xce\xa7\x1c\x3b\xc3\x35\x6d\x2b\x58\x07\x27\x6f\x19\x55\x00\x1c\xfe\x10\xa6\x17\x16\xb4\x08\x2b\xd6\xf8\x4c\xae\x4b\xb0\xd9\xa4\xb7\x5a\x4b\x57\x62\xf8\x10\x79\xf1\x9d\x7d\x19\xea\xff\x86\x31\xc9\x24\x88\x5b\xd3\xa6\x4e\x12\x9f\x4c\xf6\xb7\x9c\x7a\x98\x29\x66\x55\x11\xe9\xd8\x5c\x74\x5e\xb2\x2c\x1b\x7c\xb2\xa1\x7a\x49\xb6\x28\x5c\xce\x37\xb3\xde\x41\x59\x40\x32\x83\x23\xef\xe2\x4a\x1a\x07\xee\x87\x46\x8f\x65\x10\xe4\x2d\xd2\x06\xfe\x7f\x09\xe3\xd4\x33\xfb\x52\x15\x6a\xe3\x48\x38\x31\x15\x64\x88\x63\xe4\x5b\xf6\xa3\x71\xb1\x7e\x70\xe1\x9f\x96\x27\xd7\xf0\xa5\x8b\x95\xc6\xa4\x78\x8d\x5f\xd7\x86\x2f\x16\x12\xc0\x34\x73\x25\xb7\x97\x65\x1b\xe3\x0c\x3e\x1e\x60\xea\x4a\xe6\x0b\x57\x45\xa3\x8b\x6a\x9d\x4e\xb4\x93\x5d\x6f\x3c\xb8\xd7\x1a\xd3\xf3\x9a\xdd\xa5\xe4\x2e\x22\x19\xde\x0d\x38\x19\x09\xc9\xcd\x31\x7d\xd4\x37\x94\x21\xa2\xa8\x42\x68\xa7\xea\x71\x80\xa6\x4c\x12\x9b\xe1\xe5\xe8\xfc\xbb\xf5\xed\x65\x9e\x9f\x7e\x76\x3c\xe8\x4f\x63\x0d\x54\x07\x95\x4f\x9f\x75\x57\x50\xa6\xdb\xf9\xf7\x66\x07\x17\xde\x8e\x2a\xdc\x1e\x9a\xc9\xee\x31\x65\x4d\x18\x37\xce\xe3\x97\x95"}, -{{0x16,0x08,0x9a,0x1b,0x93,0x2f,0x8d,0x14,0x99,0x56,0x88,0xb4,0x8d,0xd8,0x41,0xed,0xae,0x3d,0xa5,0xcf,0xd2,0xcb,0x16,0x55,0x53,0x06,0xf3,0xfe,0x8b,0xd3,0xed,0xb9,},{0x9e,0xcd,0x9f,0xdd,0x7e,0x0b,0x92,0x3d,0xef,0xf5,0xd8,0x87,0xb2,0x42,0x58,0x5d,0x9d,0x41,0xcd,0x2c,0x7c,0x10,0xf9,0xc3,0x45,0xb3,0x9f,0x63,0x3f,0x4a,0xb9,0x03,},{0x78,0x78,0xab,0x74,0x1e,0xba,0xe2,0x74,0x7c,0x78,0x97,0xcb,0xb1,0xd1,0x05,0x48,0x2f,0x37,0xbe,0x2f,0x5f,0x91,0x79,0x52,0x32,0xcd,0xfb,0xcc,0xc5,0x26,0x60,0x89,0x18,0xe2,0x75,0x6d,0xdb,0x75,0x36,0xb3,0x68,0x0c,0x16,0x2c,0xf8,0xa1,0xef,0x38,0xa3,0x41,0xb9,0x36,0x2b,0xfe,0x5d,0x46,0x8b,0x4b,0xce,0x21,0xdf,0x23,0x4f,0x0f,},"\x58\x50\x02\x32\x38\x8d\x9a\xa4\xb5\xfa\xf8\x5b\x02\x33\x24\x7e\x71\x7f\xd1\x68\x40\xde\x9b\xfd\x0e\xf8\x6e\x01\xe6\x13\x02\x77\x55\x13\xe2\x24\x12\x5e\x0d\x20\x42\x0e\xa9\x49\xf6\xc2\x64\x25\xf7\x00\x77\x91\x1f\x97\x11\x31\x0c\xd6\xfd\x8b\xff\x27\xcd\xea\x11\x48\x0c\x73\xe8\xf8\xb3\xc3\x76\x41\xe7\xe8\xdd\x86\x07\xc1\x64\x02\x18\xfe\xc8\x0a\x02\x09\x28\xb9\x3d\x4d\x55\x7e\xbe\x82\xec\x0b\xb1\x75\x38\x86\x7d\x2c\xb1\x4d\x44\xd3\xea\x72\x7f\xdd\x52\x82\x0b\x0d\xa9\x44\xde\x21\xcd\x5d\xa3\x03\xd7\x76\xfe\x99\xcb\xc2\x64\x83\x65\xe6\xa0\xa9\x8d\x4d\xb1\x50\x84\x26\x61\x76\x8b\xe8\x4c\x68\x50\x7a\x5c\x45\xd2\x07\x84\x0b\x03\x35\x37\x78\x6c\xb2\x1d\xad\xad\x5f\xba\xb9\xc5\xcf\xc1\xe3\x54\x7d\xe5\x50\xd3\x13\x63\x1d\xd4\xfb\xb7\xca\x8f\x71\x93\x86\x27\x60\x8d\x2e\xbf\x65\x5d\xb4\x32\x5a\xbf\x3e\xd5\x04\xdc\x18\x30\x58\xf9\xde\x1e\x44\x93\x12\xd9\x04\xc8\x46\xa1\x84\xa0\x28\xf3\x64\xc0\x28\xb2\x7e\xb4\x94\x64\x27\xe3\x1c\x21\xe1\x05\x1d\xf3\x64\xd4\x99\xf4\x77\xbf\x51\xe7\xa8\x89\x31\x83\xe5\xec\xf7\x7d\x51\x3a\x1a\x76\xb1\xa6\xfd\xfb\x16\xbe\x90\xd7\x4b\xe4\xc4\x34\x5a\x4f\x9f\x87\xee\x44\x1a\x10\x22\xd6\x7e\xe8\x44\x78\x9f\x21\xb0\xc3\x1a\xdc\xc0\xd9\x56\x63\xcd\xfb\x40\xa8\x95\xb9\x22\xdc\xe8\x06\x9b\x93\x2c\x80\x2f\xd3\xab\x1e\xf0\xce\x6b\xff\xdc\xc5\x65\x3b\x1c\xd5\x25\x7e\x19\xa0\x95\x16\x87\xe5\x45\xfa\xf4\xaa\x66\x06\x5a\x55\xc4\xb4\x19\x1e\x34\xe8\x04\x7d\x6a\x4a\xb5\x2d\x1b\x06\xc3\x69\xa4\x26\xca\x2d\x16\xb5\x1a\x02\x71\xf2\x7f\x8d\x74\x4c\x71\x1f\xce\x3a\xad\x9d\x4a\xc0\x38\xee\x70\x0e\x4e\x97\x1b\x21\xca\x48\x9f\xf2\xb8\xc7\x78\xa3\x72\x1a\xdf\x47\xc1\xae\x5a\x41\xb9\xa2\x7f\xa7\x42\xfd\x0f\x18\x16\x4e\xf3\xc2\x6b\x8a\xe7\xd1\xfa\x29\xb7\xc0\xcc\x46\x83\xbe\x65\x02\x5c\x96\x53\x7a\x12\xd5\xfc\xeb\xbd\x05\xe9\x30\xc3\x69\x3e\xbb\xba\x0a\x78\xad\xf5\x9d\x8a\x3b\x59\x8a\x34\x8e\xaa\x9f\x47\xca\xf5\x31\xfe\x44\x96\x52\xdb\x5b\x20\xd6\x89\x94\xe3\x5a\xfe\xc2\xc2\x57\x09\x05\x5a\x1d\xe2\x60\x82\xe3\x91\x2d\x49\x7c\x64\x77\x20\xa3\xf8\x73\x62\x14\x56\xe6\xa5\xb9\xeb\x61\x3a\xcb\x43\xb6\x6d\x47\xd0\xb9\x54\xc6\x9e\x8f\xbf\x2c\x5e\x63\x4c\x48\x6e\x57\x24\x93\x0e\x0b\x56\xa5\x16\x94\x0c\x8c\xb0\xe7\x75\x27\x4d\xef\xf9\x7c\xbb\x77\x59\xce\x90\xa2\xb9\x3e\x9e\xfa\xa6\x24\xe6\xb3\x8a\x39\x84\x9d\xca\x1d\xf6\x12\x73\x6f"}, -{{0x94,0xd5,0x09,0x15,0x14,0x4c,0x7e,0x7d,0xd0,0xf8,0x5f,0xef,0x87,0xed,0xdc,0x22,0x06,0xc1,0x56,0x9e,0xd1,0x43,0x1c,0x8c,0x5a,0x15,0x3e,0x32,0xe1,0xcb,0x2f,0xb7,},{0x3b,0xb0,0x98,0xcf,0x16,0x0f,0x3a,0xec,0x31,0x70,0xb5,0x7d,0x6a,0xdd,0x4f,0x56,0x73,0x92,0x70,0xe4,0xb3,0xa8,0xef,0x79,0x66,0xec,0x30,0x61,0x9b,0x29,0x91,0x02,},{0x59,0xa1,0xce,0x55,0xf5,0xa6,0xba,0xdc,0x1b,0x93,0x91,0x26,0x36,0x20,0x54,0x2c,0xfc,0xae,0x87,0xa0,0xf2,0xb9,0x50,0x22,0x50,0xcf,0xe4,0xbd,0xcb,0xf7,0x6c,0x46,0x19,0x77,0xc3,0x34,0xa4,0x8d,0x91,0x6e,0xde,0xbd,0x56,0xc2,0x1c,0xe2,0x17,0xc3,0x5a,0x64,0x44,0xcf,0xbf,0xd3,0xb1,0x1a,0x3d,0x48,0xfa,0x2e,0xdb,0x6e,0xb4,0x0f,},"\x4d\x91\x5f\x27\x33\x2d\xd7\x50\x51\x71\x9a\x24\xae\x8d\x0e\x9c\x30\xda\x79\x09\x99\xe2\x2d\x9b\x58\x7e\xf2\x03\x21\xbe\xe4\xc0\x7d\x0a\x12\x49\x4f\xfe\x59\x9f\x47\xf9\x69\x25\xf5\xd9\x25\x17\xfc\x3e\x5f\x04\x1d\x0c\x70\x9f\x2a\x97\x83\x12\x5e\xec\xa6\x65\x29\x97\x20\x1c\x42\x9a\xa6\xf1\xce\x2f\x07\xa0\xd4\xa0\xa1\x8c\xf2\x0b\x3e\x9a\x4f\x76\x63\xea\x52\x62\xca\xd8\xf9\x49\x41\x1b\x05\xff\x5c\x5e\xdd\x7b\x30\xb2\x17\xd7\x5d\x8c\x86\xc9\x4e\x5f\x92\xc1\x67\x34\x37\x4e\x8c\xea\xd6\x1b\x0b\x27\xbb\x4b\xf5\xf4\x3a\x31\x3c\x1d\xd5\xb8\x3e\x0e\xa9\x33\xb6\xca\xdf\xed\xd7\xa6\x4a\xa5\xdd\x5b\x5d\x02\xc6\x95\xea\x20\xe0\x91\xfd\xaa\x72\xef\x4e\x7c\xa4\x0f\x38\x39\x5b\xe8\xbf\x7a\x25\x5c\x6d\x06\xa6\x32\xd7\xd7\x85\xd9\xe0\x47\xf2\x32\xaa\x50\xfa\x14\x52\x9f\x98\x6f\x9e\xf9\xd7\xb5\x80\xa0\x39\x65\xb0\x15\x47\x88\x82\x2a\x22\x5b\xb5\xab\x34\x38\xb8\x9a\x5c\x28\x74\x4a\xb0\xbc\x0b\x20\x14\xe5\x79\x6a\xcb\x49\x35\xa8\x1b\x02\xa0\x46\x32\xac\xb8\x8c\xaa\x7e\x39\xe0\x69\xc7\xc8\xe1\x75\x82\x91\x09\x4a\x53\xe3\x62\xfc\xed\xaa\xa5\x83\xec\xa7\x66\xef\xeb\xf6\x9b\x38\xe8\xcd\xe9\xce\x58\xe0\x12\xc6\x0e\xc8\x8e\x8c\x42\xbe\xad\xfa\x83\x8c\xfe\x44\x0f\xa0\xc0\x1d\x65\x9c\x96\x34\x57\x6d\x7d\x7a\x2d\x3a\x04\x4f\x99\xc6\xe4\x26\x3d\x4c\x0b\x37\x4a\x38\x8a\x2a\xcf\x38\xef\xf2\x9c\x77\x7e\x9d\xaa\x60\xd5\x98\x03\x5a\x7d\x9e\xdf\x67\xa5\x02\xc3\xf5\x73\x20\x7b\x11\x9c\xac\xac\x3f\xa7\x1e\x2a\x02\x07\xc6\x01\xcc\x0d\xd6\x37\xef\x56\x2b\xac\xc3\x5c\x57\x04\x27\x38\xf1\xf5\x58\x15\xa5\x26\x80\x82\xcd\x6a\x50\x82\x92\xfa\x29\xe3\x4e\x96\x45\xd8\x7a\x1a\x2b\x6e\x58\xad\xb7\xf4\xa5\x7f\xbb\x53\xe9\x21\x3e\xf3\xdc\x87\x3f\x29\x39\x62\x58\xa1\xea\x54\x6f\xb5\x95\x2c\xe3\x43\xce\xe9\xbb\xb9\x0c\x1c\xda\x72\xc6\x5a\x7c\x8e\x40\x31\x2b\x32\x8e\x23\x19\x20\xc2\x33\x07\x7d\xca\x34\xd0\x4f\x9d\x89\xda\xa9\xa2\xf4\x34\x59\x16\x5f\xd1\x02\xff\x56\x43\xc7\x17\x52\x30\xb3\x9e\xc7\xc3\xc4\x75\x65\x0e\xf1\x31\x60\x9d\x32\x20\xf5\xa2\x94\xa4\x03\xb1\xe1\xc4\x2c\xfa\x16\x2c\xd4\x26\xf0\xae\x43\xfd\x6b\x7a\xb5\x47\xa6\x2b\x7d\x5f\x84\x74\x03\xc4\xe5\x98\x79\x53\x87\x71\x58\xcf\xde\xe2\x3c\x04\xf7\x51\xc7\xc8\x6d\x07\x8e\x82\x4c\xa6\x3b\x5e\x65\x54\x3e\x97\x8b\x6b\x0c\xc6\x89\xef\x66\x44\x12\xb0\x1b\x8f\xf1\x65\xe7\xdb\xde\x3c\x09\x9b\xf4\xf3\x4e\xbd\xdc\xb4\xc4"}, -{{0x0d,0x81,0x92,0x6f,0x51,0x3d,0xb4,0xb2,0x5d,0xfa,0x1e,0x52,0xb5,0xdc,0xa6,0x78,0xf8,0x28,0xa6,0x1c,0x7c,0x91,0x3c,0x82,0x82,0x47,0xc2,0xeb,0x04,0x22,0xb7,0xd1,},{0x0f,0x32,0x41,0x1e,0xf9,0x1d,0x4e,0x4b,0x69,0x41,0xdf,0xca,0xab,0x14,0x2e,0xf3,0xbe,0xc1,0x60,0x98,0x39,0x93,0xa5,0x26,0x2c,0xcf,0x27,0xfa,0xdd,0x2a,0xf8,0x90,},{0xe0,0xcb,0x6c,0x71,0xeb,0xf8,0xd7,0x05,0xe5,0x0c,0xad,0x9f,0x0b,0x8c,0xba,0x3e,0xcf,0x4b,0x9e,0x37,0x93,0x40,0x00,0x92,0xaa,0x5b,0x12,0x1e,0x7d,0xbb,0xc8,0xbe,0xa7,0x1d,0xf2,0x95,0x28,0xca,0x9b,0x47,0xab,0xf8,0x7c,0x19,0x8a,0x8d,0xc4,0xe1,0x4d,0x51,0x80,0xce,0x93,0x2d,0xd2,0x11,0x4a,0x3c,0xda,0xa5,0x55,0x2c,0xc2,0x05,},"\xa9\x38\x37\x52\x2f\x7e\xc2\xe9\x3a\x2e\x4b\x4c\x8b\x46\xde\x92\x6a\x81\xad\xa2\xd2\x48\xbc\xd3\x3b\x39\xb6\xc9\x5f\xb6\x2a\x61\xdb\xbe\xda\x1a\xa8\x5a\x21\xd9\xb9\x6a\x08\x51\x0d\x8d\x3a\x65\x8c\xf3\x20\xa1\x09\x28\x69\x59\x99\xd2\xc0\xd6\x05\xc7\xf9\x5a\x12\xf5\x6a\x87\x18\x50\x7d\xb0\xf4\x97\xe3\xea\xd6\x13\x13\x2a\xb0\x92\xcb\xf1\x9d\x22\x60\x35\x86\x30\x35\x8d\x9b\x26\xe6\x8d\x50\xdd\xae\x37\xc8\xaf\x0b\xb7\xd2\x74\x1f\xd2\x92\x9c\x21\x27\x9a\x78\xd1\x0e\x2c\x5f\x3c\x5b\xf4\xa4\x2a\x36\x17\x03\x6d\x54\x74\x36\x47\x76\x5a\xfd\x8c\xd9\x10\xf8\x1b\x38\xce\xd7\x23\x90\x63\x0e\xe6\x89\x44\xa3\x7d\x29\xc2\xfe\xca\xda\x1c\xc5\x9e\xc5\x44\x07\x5b\xdb\xc1\x4c\x63\xc6\x23\x4b\x88\x40\x49\x00\x0c\x27\xc7\x34\x06\x03\x56\x04\xfc\xa8\x76\x0b\x49\xa5\xe2\x10\x9e\xf9\x12\x85\xad\xc4\xec\x48\xc8\x19\xd6\x2d\x94\x8f\xac\xa9\x0f\x62\xcf\xae\xf0\xb0\x7d\x6f\xe5\x76\xd7\x62\xbf\xd0\xee\xf9\x4c\xf6\xb5\x33\x2c\x4d\x42\x25\x11\x60\x7f\x2f\xac\xc7\xac\x04\x6a\x59\xb9\x61\x7e\x83\x83\xd1\x02\x9c\xc9\x1a\xc5\x92\xb5\x20\x84\x41\x30\x32\xbe\x84\x1b\xaa\x9b\xf9\x62\x51\xa6\xbd\xa6\x71\xd4\xcd\x4b\x12\x5d\xa6\x58\xa4\xe5\xa5\x0f\x44\x28\xee\xbf\x26\x14\xfb\x0c\xe5\xfe\xbe\x80\xf7\x21\xa5\xf4\xc0\x32\x55\x06\xd2\x7a\x8d\x31\xe3\x3d\x86\x25\x38\x70\xdd\x63\xc0\x8e\xdc\x73\x02\xb2\x80\xe9\xb9\xbd\xc2\x8b\xee\xf0\x5c\x7d\xcb\x30\xd4\xc1\x62\xe9\xbe\x83\x2e\x1c\x78\x5e\x37\x55\x12\x18\x42\x1e\xec\x85\x2c\x42\x98\x21\x3b\x2f\x27\xf8\xf8\xc7\x06\xd3\x91\xb9\xc6\x9a\x56\xdb\x7c\xe5\xd8\x15\x48\xfc\xa5\xfe\xd4\x56\xf2\xd8\xaf\xd0\xb7\x5f\x79\xf8\x58\x68\x31\x6f\x4a\x09\x21\xf0\xc6\x63\x99\x26\x51\x6b\x3c\x3e\x52\xa9\xcb\x22\x55\x45\x46\xef\x70\xe1\x4c\x77\xec\xbd\xcd\x5c\x0d\x59\xa8\x17\x69\xb3\x0d\x5d\x13\x1f\x2f\xb4\x49\xc9\x96\xb8\xde\x8a\xc7\xf8\x08\x4f\x84\x99\xe1\xa5\x6f\x7c\xd2\x9d\xb6\xaa\xef\xcc\xae\x8a\x60\xe7\x56\x16\xa1\xf7\x02\xc3\xbc\x8d\xea\xa1\x00\x4a\x8d\xae\x03\x92\xa5\x9c\xee\x54\x81\x0c\x6e\x94\x0e\xee\x25\xfb\x2e\x5d\x57\x32\x67\x04\x4b\x89\x3f\xfd\xe3\x78\xfe\x75\xac\x26\x13\x37\x3d\x84\xa0\xca\x81\x87\xaf\x4a\x33\x58\xe5\x0a\x99\x4e\xd0\x33\x67\xde\x64\x5e\x10\x39\x0f\xea\x4c\x33\xbb\x1a\x6c\x0c\x39\x85\x8b\x8d\xb4\xa6\x9f\xe8\x94\xa4\x22\x3d\x45\xaf\x69\xb3\x6c\x61\x17\xc4\xdc\x25\xde\x49\xa6\x30\x17\x00\x2b\xa9\xae\x55\x1e\xf9"}, -{{0x6c,0x8c,0x53,0xb5,0x6b,0xbc,0xb4,0xc0,0xa2,0x5d,0xc4,0x0c,0x18,0x24,0x0b,0x6a,0x5c,0x75,0x76,0xb8,0x9d,0xde,0x45,0xef,0x13,0xfb,0x15,0x8e,0xa1,0x7f,0x8e,0xd9,},{0x23,0x8e,0x51,0xd6,0xa4,0x4f,0xa7,0xac,0x64,0x26,0x88,0x01,0x26,0x1e,0xa3,0x5b,0x62,0x63,0x8a,0x00,0x6c,0xc4,0x52,0xbd,0xdb,0x9f,0x16,0xfc,0x58,0x03,0x06,0x0c,},{0x4b,0xf1,0xe7,0xd4,0x9c,0xd4,0xd5,0xc3,0xc1,0xfd,0x4a,0x4b,0xc4,0x8f,0xf6,0xb6,0xe5,0x2f,0xd9,0x51,0x0a,0x41,0x18,0x12,0x29,0x69,0x96,0xe4,0xfe,0xc5,0x6b,0xe4,0x45,0x14,0xc5,0x67,0xd1,0xd3,0x34,0x77,0xbd,0x5d,0xc0,0x83,0xc3,0x95,0x8b,0xd9,0x5b,0xfe,0x59,0x9c,0x15,0x3f,0x21,0xae,0x26,0x25,0x29,0x67,0xb7,0x32,0x60,0x03,},"\xb6\x0d\xf2\x94\x4b\xa0\x15\x75\x98\x02\xd3\xc5\x87\xbc\xfe\xbe\x52\x1a\x7e\x77\xb9\x98\x5b\x76\x1c\x96\x76\x45\x4d\x24\xa6\x64\xaf\x0b\x0d\x44\x22\x5a\x55\x75\x12\xe1\xc1\xcd\x7d\xd8\x33\x5c\x8f\x6a\xdf\x92\x8e\x18\xf8\x9f\xd5\xee\xdf\x6f\x41\x1d\xcd\xaf\x99\x69\x12\xe8\xc3\xe2\x3d\x1c\xb9\x5e\xca\x4b\x9e\x24\xe7\x53\x9c\x3b\x98\xbf\x3d\x07\xec\x25\x13\x92\x09\x6c\x19\xac\x53\x74\xdc\xba\x52\x61\x32\xb6\xd9\xbb\x8f\x6c\x85\x9c\xe9\x85\xd5\x84\xc7\xbb\xa5\xb0\x2a\x81\x03\x4b\x6d\x8b\x52\x1b\xd2\x80\xe5\x0d\x77\xda\xa2\xb2\x41\x3e\xd6\x79\x83\x4f\x81\x61\xd5\xd0\x57\x3b\xdd\x47\x6a\xc3\xcd\x0a\x3a\x7d\x8d\xb4\x53\x34\xe8\x9c\x00\xab\x66\xbc\x36\x8a\x07\xb4\x23\xe2\x46\x43\x46\x36\x27\x2a\xa4\xe4\x63\x7a\x53\x06\xb2\xc3\x39\x79\x92\x78\x1f\x30\x23\x8d\xe7\x9e\xc1\x04\xac\xc7\x20\x0d\xef\xad\x96\x08\x83\xd3\x91\x44\x3e\x70\xef\xbd\x22\xf1\xcf\xce\xec\x51\x12\xfe\x9e\x8e\x13\xbb\x94\x1c\x08\x34\x68\xdd\x71\xff\xca\x97\x6c\xd5\x1c\xe1\x61\x79\x31\x10\xef\x00\xaf\xf5\xee\x2c\xcb\x77\x06\xa5\x12\xb8\x5b\xeb\x94\xac\x49\xd1\x9a\xfb\x63\x33\x65\x5c\xf3\xae\xa5\x35\xa6\xf9\xc7\x5e\x03\x48\x41\xe7\x63\xc5\xa2\x49\xb4\x70\x4e\x1b\xe7\x8b\x0e\xca\xc6\x80\x2c\x34\x3c\x1b\x7e\x7b\x57\x70\xde\x4c\x93\xa3\xa7\x9c\x46\xe6\x83\x5d\xa8\xae\x5d\xb3\x83\x8e\x17\x96\xb5\x64\xa4\x80\xa4\xf2\x90\xb6\x0a\x1c\x63\xa7\x25\xff\x3f\xef\x43\x4d\x2a\x0b\x3d\x89\x31\x97\x87\x42\xb5\x25\xc8\x3b\xae\x67\x94\xae\x64\x19\x37\x94\xb3\x70\xc2\x89\xba\x35\xed\x79\xd3\x70\x72\xa8\xdc\xfc\xad\xb4\x6d\x5f\xfa\xee\xba\x1b\xfd\x4f\x87\xd7\x66\xb5\x04\xe6\x2b\x4a\xcd\xd7\x74\x46\xe7\x9b\xa9\x94\xd6\xdb\xf4\x76\x5e\xbd\x74\xb0\x36\x51\x00\xda\x56\x16\x2c\x36\xfe\x5a\x95\x07\x7f\x6b\x42\x65\xe8\x17\x96\xb4\xa5\x74\x43\x78\x29\x70\xb9\x6c\xb4\x56\x9b\xa9\x85\xc5\x5f\xe3\xa7\x18\x38\x0b\xca\x39\xf1\x66\x24\xf8\xe4\x7c\xc6\x3c\x1b\x6f\xa1\xbd\xe1\xae\xba\x9c\x51\xf9\x4b\x70\x2b\x13\x10\x8c\xc1\x48\x1d\x42\xe6\xfa\x98\x1e\x3e\xbf\xe0\x64\xd2\xdc\xa7\x42\x0c\x74\x59\x57\x92\x31\x2a\xe3\xfb\x91\x01\xd4\xb6\x6d\x99\x16\xdf\xd6\xc1\x3a\xe8\x83\xe6\x61\xc6\x28\x22\x8b\xe9\x79\x4c\xf6\x03\x45\x07\x6d\xb2\x61\x84\xb6\x17\xe2\x72\x29\x8c\xd4\x18\x3f\x27\xbd\x52\xd4\x05\x10\xbb\x01\x5d\x20\x97\xd4\xcc\x76\xe7\x6c\x0a\x62\xbb\xfd\xaf\x53\xc7\x26\x87\x75\xbb\xfb\xdb\x88\x70\xeb\x9b\xab"}, -{{0x69,0xb3,0x20,0xfb,0xd4,0x77,0x40,0x30,0xa2,0x97,0x67,0xa0,0xcc,0x15,0x50,0xd1,0x0b,0x74,0x9b,0x44,0xd6,0x19,0xd4,0x1d,0xce,0x11,0x46,0xf7,0xac,0x80,0xa7,0x55,},{0xdc,0x50,0x8a,0x79,0xc6,0xb8,0xab,0x86,0x6c,0xd1,0x17,0xa5,0xa8,0x4d,0xd9,0xd9,0x31,0xfd,0xa4,0x50,0xbe,0xc2,0x93,0x35,0x34,0x4d,0x0d,0x21,0x92,0x16,0xd6,0x5e,},{0x69,0x7d,0x4d,0x89,0x7e,0x0e,0x2c,0xc0,0x2b,0xc1,0xc2,0xdd,0xa5,0x7f,0x0d,0xda,0x62,0x0b,0x37,0xe8,0x61,0x82,0x2b,0xb7,0xf1,0xa7,0x01,0x93,0x5e,0x95,0x9e,0xa0,0xd8,0x45,0x3f,0x74,0x6f,0xb9,0x2c,0x08,0x7e,0xd6,0x5d,0x98,0x0e,0xea,0x1d,0x6f,0xdb,0xf2,0x3e,0x99,0xb2,0x89,0xaa,0xe0,0xdc,0xbb,0x12,0x8e,0xf8,0x36,0x64,0x0a,},"\x21\x7e\x33\xf8\x86\x22\xc9\x6f\x8d\x09\x2c\x9e\x26\x66\x4f\xe9\xef\xc0\xd8\xd2\xeb\x59\xa0\x36\xfa\x46\x4c\xee\x65\xce\x44\x89\xca\xf9\x03\xdc\xe1\x7a\xfa\xfb\xc4\xf1\x8d\xc9\xbb\xfd\x6c\x1a\x4b\xe7\xb8\x34\x85\xa6\xca\x94\x7d\xef\xb1\xd3\x51\x25\xd0\x77\x39\x62\xa3\x44\xa3\x8b\x6d\xca\x9a\x40\xc3\x1c\x1c\x4e\xb2\xd7\xf6\x81\x8f\x97\x8e\x57\x3d\x66\xb9\x90\x92\x1b\x92\xb7\x77\x47\x1a\x4f\x6f\x05\x47\x7e\xbc\x35\x3a\xce\x1d\x86\xb0\x0c\xc2\x51\x77\x7a\xaf\x6a\xf3\xaa\x11\x79\xbf\xf7\x8d\xf5\x04\x8e\x5e\xf2\x99\x68\x67\x0e\x53\x54\x83\x56\x8d\x6b\xb1\x6d\xa8\x29\x56\x8f\x81\xc7\x99\xb9\xaf\xd4\xaa\xd6\xef\x08\x52\x52\xc0\xce\x3a\xc0\x1a\xc2\x1a\x9e\xa6\x9b\xd5\x8e\xad\xc6\x69\x68\xf5\x5d\xee\x38\x6b\x65\x3f\x33\x34\xef\xc3\x98\xef\x3c\x37\xa3\x8c\xe9\x3b\x21\xf1\x07\xcc\x54\xde\xc2\x6f\x53\xfe\xe5\x60\x4e\xb0\x9a\x36\xaf\xe6\xb6\x65\xb6\x32\x4a\x84\xc7\xda\x7b\x7d\xd0\x1d\x92\x78\xe4\x72\xf1\x5a\x5c\xe9\xff\x0f\xd9\x3d\x0a\xa0\x60\x4d\xd2\xdf\x8d\x5b\xf6\xa9\x12\x73\x4e\xc5\x1d\xe7\x7f\x0c\xe0\x99\xba\x11\x67\x02\x10\xa6\xa2\x06\x10\x6b\x0e\xde\x2d\xed\x85\x8a\x6b\xc4\x11\xe7\x61\x3e\x6f\x80\xe1\xaa\x52\xc3\x23\xe3\x0f\xa8\x49\x95\x1c\xc9\xb7\x76\xe4\xcc\x58\xc9\x0c\xfc\x8f\x44\x2d\xf6\x41\x51\xa7\xfd\x4a\x3d\xd6\x1a\x43\x36\xda\x21\xd0\x39\x44\x63\x5d\x3f\xd6\x67\xbe\x74\x1e\xf4\x5b\x1f\x7c\xb2\x76\xd9\xf4\xde\x81\x07\xde\x64\x58\x2f\x79\x17\xc6\xea\xb3\x8e\x0a\x88\x90\xa4\xbe\xe4\x8b\xc9\x26\x17\xa3\x61\xcc\x7b\x1d\x25\xe0\x89\x45\x3c\xe0\xa5\x25\x44\xf8\x68\xdc\xb3\x24\x9d\xe7\x61\xe7\x9d\xf6\x3e\xfa\x07\x94\xe3\xc4\x61\x8c\x55\x47\x53\xee\x28\x1c\x52\xac\x8a\xd7\x8d\x53\x38\xf0\xda\xc3\x60\xa7\x69\x38\x1b\xb4\xa3\x9f\x19\x0b\x88\x7b\x47\x23\x80\x6a\xc4\xa4\xf2\xff\x30\x4b\xc6\xf9\x33\x7a\xb5\x4c\x86\x6e\x6b\xa5\x1d\xf5\x0c\x43\xea\xb5\x2e\x2b\x39\x79\x4c\x99\x17\xe0\xc3\x14\x33\xf0\x36\x81\xd2\xf1\xd9\x3a\x04\x36\x01\x8c\xaa\xae\x20\x20\x6a\x34\x58\xad\x6c\x03\x7a\xcb\x51\x1e\xf1\x28\xf6\xdc\xd0\x53\x05\xf0\x70\x49\xa1\x3b\x6c\x6c\x3c\x5b\x81\x70\xf1\x58\xc8\xf1\x2d\x46\xe1\x60\x93\x1b\xa1\x8b\xd5\x9a\xe1\x29\xec\x07\xa0\x65\x5f\xa4\x82\xeb\xbd\x3b\x85\x0d\x36\xb8\x32\xbb\xb7\x75\xf5\x38\xe3\xc1\xb3\xa4\x3e\xcf\x94\xca\x63\x0c\xa1\x5d\x50\x28\x13\xee\xd3\xe3\x5e\x8f\xd2\x3d\x2a\xb6\x38\x60\x04\x27\xd1\x59\x7c\xb2\x9d\xa2\xa5"}, -{{0x66,0xda,0x8b,0x25,0x4a,0x37,0x06,0x73,0x78,0xf6,0x81,0x38,0xaf,0xed,0xd6,0x64,0x96,0x59,0x6a,0x05,0x85,0x52,0x4c,0x71,0x6b,0xde,0x2b,0x31,0x24,0xc3,0xe7,0xd1,},{0x85,0xbd,0xe2,0x8a,0x92,0x2a,0xb5,0xee,0xaa,0x4a,0x62,0x94,0x52,0x1a,0x2c,0xca,0xc0,0xef,0x23,0x03,0xdc,0xdf,0x8c,0x7f,0xee,0x22,0x8f,0xb4,0x55,0x20,0x12,0xe7,},{0x40,0x82,0xa5,0xbc,0x73,0x0f,0xb5,0x4b,0x6b,0xd0,0xbc,0xd2,0xa0,0x44,0xed,0x5d,0x3d,0x32,0x7d,0xc1,0x9c,0xea,0xc8,0x82,0x5e,0x62,0x9b,0x9e,0x64,0x23,0xcb,0x1c,0x61,0x42,0x36,0xf0,0x97,0xa6,0xb7,0x3d,0x47,0x39,0x47,0xcb,0x81,0xc4,0xe2,0x70,0x85,0x2e,0xe5,0xf1,0x3a,0x5b,0x03,0xdc,0x18,0xe1,0xc9,0xc2,0x7a,0x9a,0x68,0x02,},"\x3f\xae\x36\x63\x88\x37\xd0\xed\xc8\xdc\xee\x51\x7e\x43\xc4\x88\xed\x57\xfa\x6c\x98\x53\xa7\x45\xaa\xed\xfb\x10\x9e\xc1\x40\x9f\xb8\xa2\xfe\x51\xd2\x3e\x0d\xd9\xfb\xfd\x94\xf9\x1c\x18\xe6\x11\x4d\x80\x89\x01\xbf\x61\x7d\x26\x67\xce\xeb\xd2\x05\xc5\xc6\x6f\x5d\x75\x34\xfd\x2e\xc3\x3d\xbf\xe5\x80\xad\x91\x9f\x50\x42\x04\xea\xf2\x42\xaf\x87\x00\xb1\x38\xcf\xbe\x0f\x37\x29\x19\xc0\x6b\x86\x1a\x27\xd7\x20\xd0\x9d\xf2\x0f\x4f\xb7\xb7\x48\xe7\x18\xb0\xfc\x48\x6d\xbd\xfc\xb6\x94\xcb\x3f\x14\x20\x03\x5a\xc1\xbe\x55\xd3\x1f\x30\xf9\x97\xa0\x43\xd0\x47\x08\xa5\xc5\x42\xee\x37\xc0\xf7\xfe\x0b\x32\x11\xd1\x8a\x87\x03\x3d\xcb\x15\xc7\x9e\x66\x81\xc4\x97\x05\x93\xd3\x2a\x13\xc4\x8f\x0a\x3a\xf8\xbf\xc1\x36\xe0\xf9\xb5\x6a\x12\x3b\x86\xc4\xc6\x40\xb6\x50\xcb\x7d\xee\x9a\x89\xe8\x2a\xee\xee\x77\x3b\x5c\xb0\x32\xfc\xa4\x1c\x20\xc4\x07\x32\x8b\xfe\xd2\x92\x44\xe4\x60\x55\xa8\x31\x14\x61\x4d\x3d\xb5\x65\x81\x60\x4b\x11\x5f\xba\x14\xf6\x18\xe1\x02\xa1\xe1\x6c\xb0\x36\xea\x69\xdf\x92\x75\xb9\x77\xa0\x85\x81\x18\xc9\x1a\x34\xb9\xa8\x51\x9b\xd0\xda\xc3\xb6\x14\x34\xea\x08\x8f\x38\x1b\xa0\x8b\xc1\x58\x31\x89\xa4\xa7\xc8\xb6\xad\x18\xf7\x32\xd7\x4e\xff\x3a\xce\xf4\xb6\x90\x4d\xf5\x8c\x64\x69\x43\x21\x51\x37\x2d\xf9\x32\x7a\xe7\x1a\x0f\x35\x6c\x94\x46\x8d\xcf\xc2\xe4\xa5\xc0\xe4\xec\x0b\x16\x6d\x90\xcd\x46\x5f\x92\x60\xeb\xd6\xa7\xa6\x2c\xe6\xc7\x15\xbc\xc7\x15\xbe\x0c\x7e\x1f\x28\xc4\x45\x60\x12\xd3\x31\x77\xa7\xd4\x11\x3c\x9a\x5a\x22\xac\xfa\xf2\xd6\xb6\x33\x09\x07\x8f\xc1\xb1\xba\xa8\xf3\x6c\x7e\x86\x6c\x1f\x97\x2a\x65\x00\xa5\xee\xa7\x92\x01\x65\x1a\x73\x05\x20\x8b\x6c\x93\xc4\x92\xbc\x77\xca\xcb\xc9\x9c\x9c\xde\xd1\x79\xe6\x64\xa2\xf4\xe1\x69\x38\xcc\x26\xfc\xa8\xb4\x33\xeb\x80\x12\xf7\xb3\xad\x19\xba\x1f\xb8\x58\xfe\x4a\x00\xfb\x3d\x1f\x8f\xd0\xed\xdf\x0c\x37\xdc\xdb\x2e\x5d\x35\xc2\x54\x6f\x22\xe8\xc0\xf8\xce\x90\xe2\xdf\x8a\xbf\x24\x82\x7a\x01\x9b\x2c\x33\xfc\x59\x0b\xbe\x71\x2f\x01\x92\x87\x00\x2b\xc2\x21\x7c\x0d\xc0\x93\x1d\xc8\xed\x8f\x50\xbb\x44\x2f\x8b\x2d\xe2\x78\x57\x36\x2c\xe5\xa9\xfd\x97\xf0\xfd\x1b\x2b\x92\x51\xca\xd2\xa4\xac\xa1\xa9\x4d\xe2\xe9\x53\x90\x2d\x72\x28\x14\x24\x07\x44\x3b\x1d\x51\x71\x07\x64\x8a\x7b\xab\x83\x07\x49\x87\xd0\x97\x8b\xc6\x1d\x41\x9b\xc8\x45\x91\xc9\x69\xc3\xd6\xf4\xe8\x6f\xc4\x73\x87\x37\xbc\x05\x58\x75\x5c\x11\x0a"}, -{{0x27,0x65,0x48,0x29,0x0f,0x3e,0x0f,0x90,0x05,0x15,0xdc,0x63,0x36,0x6c,0x03,0xfe,0x0f,0xc6,0xee,0x13,0x0c,0x21,0xfb,0x60,0xa4,0xdf,0x9c,0xf4,0x64,0x79,0x7c,0xda,},{0x7e,0x2a,0x35,0x78,0x00,0x0a,0x08,0x7e,0xdc,0xc9,0xe9,0x4f,0xde,0x50,0x9f,0xc4,0xbe,0x05,0xca,0x0d,0xd0,0x90,0xdf,0x01,0xae,0x11,0x21,0x12,0x35,0x36,0xf7,0x2a,},{0x88,0xa1,0x46,0x26,0x1a,0xd1,0x11,0xc8,0x0f,0xa4,0x29,0x95,0x77,0xe7,0x10,0xf6,0x85,0x9c,0xf0,0xd1,0xca,0x80,0xe5,0x12,0xa5,0x52,0xc7,0x25,0xb8,0x38,0x40,0x37,0xee,0xcf,0x64,0x65,0xce,0x97,0x58,0x5c,0x9d,0x66,0x0a,0x41,0xab,0x91,0x04,0xe5,0xf7,0xc9,0xb2,0xf8,0xec,0x6f,0xb2,0x1f,0x1d,0xdd,0x50,0xd6,0x5b,0x9b,0x66,0x0e,},"\xf0\xdb\x44\x2d\xe2\x9a\x7a\x1d\xed\x55\x0d\x12\x00\x02\xcc\x12\xab\xff\xf9\x8b\x1f\x57\x6d\x65\xbd\xe1\x6d\xea\xba\x68\x7e\x4e\x0b\x0d\x5a\x87\x48\xd7\x50\x3d\xa2\x96\x9c\x64\xd6\xa7\xc2\x8d\x27\xb6\xc9\x3a\xd2\x57\xce\x32\xec\xda\xee\x37\x5f\x43\xff\xf9\x7c\x43\x2d\x45\x3f\x71\x96\xc7\x09\xc3\xbd\xfb\x73\x88\xd4\xd8\xea\xf1\x39\xf1\x82\x94\x0c\xe1\x7b\x45\x52\xe2\xd2\x0a\xed\x55\x57\xba\x4d\x2a\xcb\xf8\x45\x73\x0c\x0a\x66\xb4\x5b\x40\x95\x0b\xaf\x6a\x94\x64\x37\xaf\x6c\x9e\x3b\x33\xa7\x9e\x04\xdc\xea\xe5\x7c\x2a\x54\x95\x42\xea\xbd\x21\x6b\xf1\x39\x48\xd4\x1f\xfb\x94\x83\xfe\x29\x80\x1f\xc8\xc1\x78\x28\x40\xde\xeb\x3f\xb4\xda\x31\x92\x78\x5b\xca\x13\xed\x0a\x9e\xff\x57\xd6\x13\x6b\xaf\xbf\x9d\xec\x69\x7b\x83\x24\x47\xb2\xb6\xe7\x30\xfa\x7f\x99\x95\xba\xc6\xb7\x83\x2e\xaa\x09\x90\x5e\xe4\x9d\x46\x5a\x5e\xe4\x50\xf5\x2d\x1a\x6d\x36\x4c\x61\x81\x44\xe8\x86\xe8\xef\x63\x3d\xc7\x9d\x0a\xf8\x93\xd1\x6b\x3e\xed\xa0\xfe\xfe\xfd\x87\x59\xf2\xa0\xda\x19\x30\x17\x0d\xd1\x9e\xb7\x8f\x0d\x7a\x7b\x74\x51\x54\x03\x37\x5a\x95\xbd\xbc\xce\x01\x8b\xc1\xed\xb0\x8d\x89\x7b\xb7\x98\xa9\x5e\x7e\x86\xa5\x2a\xf3\xd9\xb8\xa4\xa1\x4b\x03\x71\xd6\x34\x98\xdc\xb2\x01\x62\x48\xeb\xd0\xbe\x80\x0e\x9f\x21\xd5\x49\xe5\xe0\xe7\xb4\x89\x5c\xa5\xcb\x72\x5a\x0c\xab\x27\xda\x8a\x8b\x12\x99\xbe\x38\xa4\x26\x09\x00\xae\x10\xdf\x5b\xab\xa1\x1a\xe2\xba\xb7\x17\x9d\xd8\x45\x39\x69\x42\x9c\xcc\x4d\x41\x60\x55\xf2\xbc\xb9\x3c\x1c\xac\x6d\x7e\x80\x4c\xf8\x12\xdf\x14\x62\xf2\x2e\xe9\xe8\x33\xa9\x76\x9e\x8e\x67\x75\x50\x40\x2c\x40\x94\xdf\x21\x2f\xd2\xc5\xfc\xc0\x9a\x72\xc7\xce\x00\x77\x51\x00\x73\x09\x0d\x0e\x63\xdb\x63\x7d\x43\xd4\xc2\x1f\x86\x19\xd3\x4d\xa5\xdb\x08\x03\x3f\x68\x6c\xe8\xb8\xa0\x82\x12\x22\xf9\x54\x34\xac\x4e\x6f\x70\x30\x94\xed\xde\xd6\xfb\x1b\x84\x6e\x97\x96\x50\x97\x9d\x3c\x77\x45\x3f\x40\xf7\xfe\xe7\xc3\xe8\x8a\x96\xfd\x1d\x70\x2e\x81\xc2\xa4\xf3\xf3\x75\x3c\x79\x64\x84\x2d\xfd\x9d\x39\x58\xa7\x43\xda\x06\x3d\x1d\x64\x8e\x51\xb2\x10\xa2\x8e\xd2\x48\x7f\x14\xd5\xf1\xbc\x6f\x33\x9b\x2d\xd1\x7a\x66\x1c\x39\x73\x6d\xa9\x9e\x4a\x4f\x07\x36\x03\x42\xd2\x37\xe3\x81\x3e\xa3\x99\x8d\x66\xeb\x31\xa2\xd7\x08\xaf\x06\x5c\x32\xb9\x27\xf7\x57\xc3\x7a\x80\x06\x60\x67\x4e\x97\x17\xba\x58\xf2\x80\xeb\x2a\xa4\x64\xfa\x74\x40\x21\x08\xa5\xd5\x66\x2e\x8d\x0f\xea\xf3\x29\x68\x7a"}, -{{0x97,0x2c,0x06,0x16,0x55,0x6e,0xf2,0x2c,0x21,0x48,0x68,0xfd,0xd8,0x22,0xc5,0x57,0x39,0xe1,0xf9,0x6a,0x93,0xae,0x83,0x51,0x2a,0xfd,0xa9,0xca,0x7a,0xa7,0x4c,0xd2,},{0x9e,0x1c,0x6d,0x41,0x07,0xf8,0xab,0x81,0x61,0xc5,0xdb,0x5b,0x88,0xa3,0x7c,0xa1,0xde,0x9f,0x4e,0x29,0x13,0x67,0xab,0xb1,0xef,0xc8,0x4f,0x83,0xf7,0x07,0x69,0x53,},{0x54,0xdd,0x06,0xfb,0xb3,0xd7,0xc6,0x3f,0x8c,0xda,0xf7,0x83,0xc2,0xd7,0xba,0xc1,0x6b,0x4c,0x82,0x6e,0x2d,0x1b,0x18,0x07,0xc8,0x4e,0x04,0x9f,0x64,0xe2,0x71,0xb2,0x1c,0xfa,0x3e,0x37,0xc3,0x44,0x26,0x02,0x87,0x80,0x5d,0x71,0x88,0x06,0xb6,0x2c,0x56,0xb4,0x7f,0x6d,0x5c,0x50,0x81,0x25,0xc9,0xfb,0x5d,0x5e,0xa3,0x5f,0xd5,0x01,},"\x86\x89\xe2\xf9\x5c\x8f\xd5\x0d\xc4\x46\x64\xa1\x8f\xb1\xa9\xf2\xc8\xf3\xee\x73\xc0\xf9\x58\x7e\xe2\x8b\xfa\x35\xc9\x23\x1c\x75\xbf\xd3\xd9\x53\x41\x74\xe5\xad\x3f\xa9\xf0\x92\xf2\x59\x94\x2a\x0f\xf0\xba\x2c\xa2\xcb\x59\x04\x3d\x19\x2c\xa8\xe3\xc8\x86\x9b\xed\xd2\x35\x4c\xbc\x5a\xc7\x82\xd7\x27\xc0\xb6\x94\x07\xf6\x8d\x13\x26\xdf\x65\xa6\x0c\x4d\x32\xf8\x7f\x19\xa1\x0f\x3d\x76\x5f\xf9\x23\x43\x4f\x55\x11\xd1\x34\xd3\x97\xc4\xfe\xf6\xbb\x19\x53\xab\xfc\xe6\x08\x27\xc3\x59\xaa\x4b\x54\xf9\x12\xaa\x8b\x17\xb8\x3d\xcc\x7e\x3b\xcb\xc5\x05\xba\x04\x6f\xe5\x7c\x16\xda\xcf\x4e\xe2\xfa\xd5\x38\xbc\x06\x81\x7c\x9b\x9d\x8d\xbc\x5f\x9d\x9b\xbf\x9f\x4a\x93\x4f\x14\xa4\x2c\x29\xe0\xe2\xf3\xa4\x9f\x46\xb2\x0e\xe7\x6c\xfe\x20\xde\xa1\xe9\x74\x50\xeb\x6a\x8f\xda\x04\x81\x68\xdd\x82\x78\x10\x20\x7f\x00\x5a\x3c\xaa\x93\xca\x11\xf4\xee\x60\x8a\x7a\x93\x55\x49\x43\x13\xae\xc8\xd7\x07\x5a\xfc\x94\xc7\xcc\xcc\x75\xc2\x31\x9b\xb4\x58\xc0\xce\x37\x3e\x9d\x00\x7f\x75\x3b\x33\xb5\x27\x93\xd5\x84\x96\xb2\xd2\x5c\xd1\xdc\xd7\x83\x2a\xac\x5d\xdb\x38\xf4\xdb\x19\xc4\x27\x21\x9e\x1a\x04\x20\xea\xd4\x7b\xa9\x5a\xb6\xd8\x9c\x65\x93\x90\x41\xcc\x73\x4c\x08\xeb\x6b\x47\x6c\xaf\x7f\xc7\x6c\x59\x8d\x94\x7f\xf4\x44\xb1\x07\x70\xf6\x29\x45\xae\x65\x04\x4f\x78\x09\x82\x99\xe2\x62\x6b\x63\x8a\x73\x28\xd1\xb7\xda\xa5\x88\x9e\x8d\xb9\x4b\xbf\xf2\xde\xd6\x2e\x14\x46\x37\x60\x22\x7c\x3f\x32\x6e\xd4\x93\x56\x5d\xdf\x0a\x17\x61\xb8\xe4\xbb\x7d\x24\x10\xfa\x0f\xdb\xf3\x56\x84\x39\x7e\xef\xea\x95\x89\x58\x89\xa0\xa9\xdf\xfc\x5e\x02\xc0\x92\x38\x3b\x7c\xe7\x4d\x2d\x90\x93\x99\x16\xf2\x6b\x71\xaf\xd2\x65\xf8\xbe\xc7\x4f\x0d\xe2\x47\xc9\x64\x39\x05\x58\x3d\xf3\xce\xe2\x35\x37\xd6\xb5\x68\xc8\x33\x8c\xe5\xfe\xe4\x2f\x7d\xd1\x5d\xad\x52\x47\xf0\x09\xac\xbf\xd5\xd7\x69\xb6\x36\x69\x59\xcd\x0a\xe1\x50\xf5\x8f\x7c\x80\xfa\x10\xd9\x89\xed\x90\x11\x93\x72\xe5\xfe\xa5\xda\x48\xa4\xe8\xea\x9c\x72\x78\x75\xdc\x4a\x20\x05\xb0\xdc\x2e\x3f\x69\x7c\x0c\xe0\xa4\xbd\xb2\xf7\x50\xc0\x4f\xbc\x0c\x27\xd0\x2d\xd8\x28\x6e\x54\xc9\xc3\x95\x9b\x6f\xfb\xdb\x1d\xe2\xaf\xfe\x9e\x78\x26\x51\xe5\x16\x8a\x50\x0a\xfe\xd0\x37\xb3\xe1\x79\x0d\xdd\x59\x38\x51\xa6\xa6\xcc\xca\x9f\xff\xb4\xa9\x9e\x27\xdf\x43\x81\x88\x71\x53\x6a\xb0\x4f\x14\xa0\x6a\x1c\x7c\xb4\x7b\xed\x62\x41\xce\x74\x30\xad\x3e\x64\x0a\x72\x67\x52\xfa\x06\xa9"}, -{{0xe0,0x40,0x5d,0x37,0x89,0x3e,0x89,0xf5,0x38,0x11,0xd6,0xd4,0x46,0xe1,0xf1,0x93,0xf5,0x1a,0xfa,0x1b,0xbb,0xa7,0x25,0xf9,0x5e,0xb4,0x80,0x33,0x42,0x4a,0x25,0x09,},{0x45,0x10,0x4d,0x59,0x5e,0x44,0x3e,0x8c,0xe6,0x54,0xde,0x9d,0x65,0x50,0x54,0xbf,0x0a,0x99,0xd3,0x56,0x13,0xd7,0x7d,0x57,0x45,0x4c,0xa2,0xd1,0xc8,0x99,0xb5,0x17,},{0x77,0xdd,0xd4,0x91,0xca,0x66,0x2e,0xbf,0xfb,0x12,0xf7,0xf4,0x92,0xd7,0xfb,0xc1,0xa1,0xb4,0x47,0xf6,0xc8,0x59,0x98,0xf2,0xf7,0xcc,0x9a,0xdc,0xe6,0x7d,0xe6,0x3b,0x6e,0xeb,0xd0,0x81,0x17,0x84,0x5a,0x03,0x02,0xf7,0x34,0x97,0x14,0xba,0x9d,0xb2,0xaf,0x58,0x04,0x8b,0x85,0x83,0x7d,0x76,0x60,0xec,0x3d,0xeb,0xee,0xe2,0xd0,0x0f,},"\xdf\x58\xc4\xfd\x07\x02\xa2\x0f\xaf\xa3\xd1\xd4\xfe\x7d\x85\x93\x8b\x12\x0f\xc1\x1e\x8d\x41\xb6\x01\xf0\xe6\x0e\x42\x23\x6a\x49\xf1\x26\x81\x3b\xd5\x12\xee\x71\x35\x90\x61\xe1\x3e\xb3\x14\xd4\x17\xf5\x6d\x6d\x56\x02\x85\xfa\x89\x91\x21\x32\x84\xc4\x2b\xc2\xce\xf2\xdc\x93\x7b\xdc\x0b\x5e\x9d\xc2\x26\x9a\xfa\xb3\x2d\xb3\x0e\x68\x49\x85\x59\x51\xcf\xbc\x53\xec\xfa\x01\x64\x38\x63\xe0\x32\x89\x95\xfe\x85\x0c\x0d\xb5\x54\x21\xbf\xa5\x64\x60\x1b\x8c\x9d\xb7\x55\x2c\x7e\x6a\xa7\xad\xfa\x15\xa5\x80\x21\xa8\x42\x66\xe9\x59\x5c\x65\xfc\xa4\xa1\x5f\xa7\x0f\x55\xf5\xd2\x12\xc9\xe2\x77\xff\xb8\x30\xf4\xca\xd1\x86\x1f\x3f\x49\x5a\x9d\x67\x2f\x56\x91\x31\x06\x39\xc1\x2d\xcd\x07\xe3\xef\x17\xa2\x37\x50\xbc\xb4\x6b\x7a\xd7\xea\xc4\x62\xeb\x51\x22\x25\xf3\xbe\x7e\x32\xf8\xf4\x98\x7a\x11\xdf\x34\x11\x66\x06\x2b\x43\xc6\x3a\xb8\x58\xa6\x00\x49\x76\x67\xfb\xb8\x8e\x93\xc7\xe2\xe0\xaa\xb4\x1c\x09\xc0\x23\xeb\x90\x2e\xc3\xba\xf6\x79\xe2\x5b\x96\xe1\x06\x92\x1a\x91\x4f\xd5\xde\x20\x0a\x47\x88\x9d\xe2\x3e\x7b\x65\xd0\xcc\xdf\x0c\x29\x03\x64\x67\xa1\x21\x0c\x00\x30\x30\x9a\x2d\x04\xec\x25\x6d\x5a\x4d\x8b\x97\xd4\x6a\x3e\x15\xf3\x45\xb6\x67\x17\x08\x03\xcd\xac\xf6\xcb\x48\xad\xd0\xa1\x34\x62\xdd\x30\xfa\x06\x2b\xd4\x56\x66\x41\xda\x07\xd7\xf6\x1e\x06\x36\x86\xed\xd9\x6b\xfe\x8f\x97\xb9\x86\xb7\xc0\xe4\x42\x49\xcd\x2d\x73\x17\x47\x29\x99\xb8\xee\x4e\xa8\x0c\x90\x2f\x3b\x18\x89\x36\x71\x2e\x89\xd8\xbf\x02\xce\x8a\xe7\x7b\x6b\x31\xab\xb0\x63\x20\x65\x45\x5d\xdd\x9f\x9d\x1c\xd9\x53\xa4\xa4\x9a\xac\x1a\x15\x16\x9e\x68\x7d\x4f\xd3\xf7\xc2\xed\xfb\x3a\xab\xc3\xb6\x61\x55\xf7\xd3\x15\xf8\xa2\x94\xfa\xdd\xff\xdb\x49\x51\x36\x7a\x0c\xb8\x70\x75\x9e\x85\xa8\x38\xaf\x66\xba\x3f\xc1\x03\xda\x2b\xab\xc3\xf3\x81\x69\x6e\xf8\x88\x2d\x85\xa8\x27\x8d\x5f\xac\x3a\x72\xf1\x6e\xb1\x19\xee\x99\x00\xb1\xfd\x98\x6c\x2a\x9f\x94\xee\xd8\xe0\xd4\xf2\x73\x69\x7e\x43\x63\xa9\x75\xff\x6a\x7b\x80\xd5\xb4\xec\x53\x55\xbf\x63\xb4\x2b\x71\xcd\x48\x42\x40\x1d\x38\xb5\xe0\x0c\xc9\x7b\xfd\xa4\x0e\x45\x66\x53\x68\x3b\xc8\xe6\xda\xde\x7d\xcf\x98\x5a\x97\xb0\xb5\x77\x6c\x4d\x72\xca\x13\xa1\x47\x4e\x4e\xb2\xec\xcf\xcd\x42\x87\x86\xdd\xd0\x24\x6d\x73\xa6\x37\x7a\x79\xcb\x8d\xa7\x20\xe2\x26\xc1\x94\x89\xbd\x10\xce\xdd\xe7\x4b\x49\xfa\xc2\xcf\xa2\x07\x12\x9c\x6a\x10\x8a\xa1\x64\xbe\x9d\x80\x9c\x4d\x31\x14\x73\x60"}, -{{0x57,0x56,0xe7,0x52,0xdf,0xf6,0x9e,0x3e,0xed,0x84,0x8e,0x4a,0x49,0xc7,0xa8,0xba,0xca,0x12,0x15,0x4f,0x94,0x31,0xde,0xc3,0x56,0x26,0xef,0x8d,0x75,0xa4,0x45,0x14,},{0x59,0x10,0xef,0x00,0xa5,0xb3,0x54,0x14,0x3c,0x46,0x56,0x1d,0xa6,0x2c,0x41,0xaa,0x13,0xd2,0x9c,0x18,0xdc,0x61,0x53,0xbf,0x8e,0x50,0x2e,0x01,0x14,0x00,0x77,0x28,},{0x81,0x57,0xd8,0x33,0x4d,0xed,0x1a,0x32,0x69,0x9b,0x35,0x0a,0xc0,0xd4,0x12,0x00,0x28,0xcd,0x8e,0xf8,0x18,0x94,0x48,0x93,0x48,0x50,0xe5,0x0e,0xe4,0x99,0x9d,0x8f,0xa2,0xcd,0x25,0x76,0x46,0xd9,0x2f,0xba,0x5d,0x66,0x2a,0x82,0x3e,0x62,0x20,0x8a,0xb4,0xfb,0xe0,0x17,0x14,0xa8,0x48,0xa0,0xb9,0x0b,0x55,0xad,0xcd,0x24,0x69,0x02,},"\xeb\x21\x90\xa3\x21\x9c\x79\x2b\x66\x66\xb2\x75\x27\x33\xad\x9f\x86\xfc\x39\x01\x55\xc4\xb4\x38\xbe\x19\x69\x59\x38\x3b\x25\xf3\xa7\x49\x53\x0d\x5a\x4b\x15\xeb\xe2\xc1\x8d\x99\x17\x8e\x6d\x45\xbb\x4a\xa2\x12\x0f\x95\xa3\x52\xe0\x40\x6c\x63\xac\x86\x72\x48\xd9\xef\xba\x12\x42\x31\x06\x48\x73\xc8\x2f\xe9\x95\xdd\x03\x1c\x7c\xbc\x7d\x15\xec\x19\x1f\xbb\x6c\x47\x4d\xc4\xc7\x77\xe8\xf4\x57\x84\x1e\xb4\x62\x48\x41\xc1\x52\xd1\x5e\xde\x26\xe7\x84\x79\xa6\xa2\x5f\xfa\x33\x55\x63\xf1\x06\x4e\xf0\x95\x58\xb9\x10\xe2\x60\x84\x18\x82\x0f\x49\x55\x4b\x67\x0c\x6b\xab\x34\xd1\xd6\x09\x84\xde\xa5\x0e\xd6\xa3\x75\xf4\x5a\x74\xbe\xad\xfb\x04\xbd\x93\x00\xbd\x59\x4e\x2e\x20\xea\x5d\x30\x52\xbb\x7d\xdc\x51\xa9\x49\xa0\x04\x79\x72\x68\x2e\xbe\x66\xd3\x8a\xac\x62\x92\x72\x70\xde\x42\x15\x0d\x58\x22\x1d\x03\xb8\xac\xe3\x58\x99\x33\x48\x7b\xf2\x3d\x29\xc5\xc2\xc8\x43\xae\xfa\x2e\x1c\xa2\x2f\x9d\x16\x80\xf8\x0c\x76\x6d\x14\x3c\xe5\xec\xef\x25\x3a\x74\x5c\xb7\x1e\x72\xf6\x50\x4a\xd9\x11\xf7\xcb\x4a\x81\x9c\xd0\x74\x86\x3a\x92\x70\x69\x29\xa3\x14\x2f\x8d\xb7\xac\x16\x41\x02\xac\x2c\xa0\xd2\xe1\x9a\x72\x5e\x1b\x5f\x81\xf4\x43\xc7\x3e\x04\x84\xf2\x6a\x45\xa3\xae\xf8\x4f\x1f\x3f\xa0\x4a\x4a\xc6\x95\xd2\xda\xb6\xef\xba\x45\x6a\x28\x1a\x39\x73\xcc\x18\x6e\x68\x0a\x66\xdf\x52\x1a\x4d\x1f\x9e\xdf\x4d\xfb\x27\x4a\x42\x70\x97\xbf\x86\x32\x81\xcf\xb0\xed\x80\xf8\xd7\x67\x66\x38\xd6\xcd\xac\x93\x78\x43\xef\xbc\xfc\xe9\x1d\xe1\xdf\x6c\x52\xb5\x94\x57\x1b\x93\x15\x60\x0e\x4b\x65\x52\xde\xfb\x84\x37\xa8\x07\xba\x21\x29\x8e\x3d\x97\x22\x12\xba\x31\x46\x92\x91\x7f\x40\x07\x53\x11\xac\xd0\x09\x39\x52\x41\xb9\xf1\xb2\x56\xc5\x15\x73\x5d\xc6\x74\xf8\xe8\x66\xd1\xee\xb4\xc3\x28\x54\x8a\xee\x71\x23\x1c\x4c\x9d\x5b\xd2\x2e\x39\xde\x88\xd1\x9f\xab\xf4\x9f\x0b\x98\x69\xcb\xf8\x35\x21\x4b\x15\x52\x2a\x93\xd3\xa5\x00\x7b\x11\xf0\xb5\x0e\x52\x28\xd4\xee\xbb\x45\x71\xb3\x5d\xa8\x4f\x4f\x68\x7e\x3f\x43\x79\x3d\x54\xf3\x82\x5b\x37\xa5\x09\xea\x56\x4b\xdf\x21\x7f\xf4\xad\xf6\x84\x7b\xbe\xa4\x31\x6a\x1d\xbc\xc7\x44\x8e\xcd\x53\x63\xea\xab\xc1\x28\xde\xcf\x05\x4e\xe1\xa0\xee\x2d\x87\x19\x79\xf8\xa6\x3b\x26\x92\xb0\x9f\x6e\x98\x6a\x13\x8e\x7f\x68\xf6\x0a\xa4\x26\xa1\xc9\xb0\x1a\x49\x02\xe1\x3b\x17\xbc\x83\x12\x41\x0c\x28\xbe\xd2\x9b\x60\x1b\x0f\xc9\xf3\xbc\x2d\x22\x3f\x87\x52\x51\x10\x0f\x86\x9c\x6b\x58\x44"}, -{{0xb9,0x04,0xac,0xb1,0x9e,0x5c,0xf8,0x72,0xd3,0x64,0x0c,0xd1,0x8d,0xdf,0x3c,0x0b,0x66,0x57,0xe0,0x11,0x7c,0xe6,0x59,0xdb,0xf5,0x02,0x59,0x01,0x5d,0x3f,0xbf,0x32,},{0xe0,0x4a,0x8a,0xa5,0x6d,0x18,0x18,0x48,0x3b,0x10,0xd0,0xa7,0xc9,0x19,0xe1,0xd5,0xd8,0x00,0x1e,0x35,0x51,0x0e,0x1e,0xc6,0x2f,0x71,0x14,0xdb,0xe8,0x1a,0xe0,0xbe,},{0x9a,0xaf,0x8a,0xc9,0x71,0x40,0xd5,0x50,0x8d,0x58,0xf5,0xac,0x82,0xb7,0xfd,0x47,0xe6,0xb1,0xf6,0x8a,0x7c,0x78,0xa2,0xac,0x06,0xf0,0x41,0x6e,0xf8,0xe9,0x91,0x95,0x3f,0x62,0xc4,0x7f,0xd5,0xfb,0xc6,0xc1,0xe0,0x1b,0xae,0x1c,0x92,0xa3,0x3e,0xf5,0x2b,0x7e,0xfa,0x5f,0x17,0xbb,0x86,0x33,0xbd,0xc1,0xae,0xeb,0xce,0x31,0x8f,0x0f,},"\x83\xf4\x12\x4d\x5a\xf9\x55\x13\x9b\x1b\xc5\x44\x1e\x97\xc5\xfa\xc4\x91\xb4\xea\x91\x14\x07\xe1\x54\x20\xa0\x34\x7e\xd7\xfa\x1f\x88\x19\xe3\x6c\x8e\xd5\x74\x0c\x99\xd4\x50\x5a\x78\xb6\x19\xd5\x60\x74\x9a\xf5\x0b\x05\x73\x51\x08\x16\xd6\x13\x22\xcd\xa9\x76\xa5\xd4\xca\x32\x05\xf5\xf0\xe6\x0e\x75\x9a\x5d\xf1\xa0\xbd\xf3\x6d\xfe\x97\x17\x90\x6a\xc5\x7c\xbf\xc9\x70\xab\x43\xb6\xfa\x18\xe6\xc0\x00\x6c\x84\xfc\x72\x54\x47\x0a\x0b\x77\x47\x27\xbf\x5f\x8e\x67\x94\x23\xa5\x31\xe4\x1c\xb5\x31\x0f\x9b\xcb\xf5\xa5\x44\x5e\xbc\x39\xfb\xd9\x09\xce\x11\xe9\x7b\xc2\xf6\x6a\x4a\x1b\xb6\xc2\xf1\x67\xf2\xc6\xe8\x0e\xb9\xb8\xb7\x2d\xf3\xe8\xcf\xd4\xe5\x14\x48\xdc\x14\xc0\xb8\x37\xf2\x94\x96\x93\xd1\xd0\x54\xc8\xf9\x5b\xff\x7f\x1e\x36\x45\x67\xd0\x34\xf2\x22\x3e\x15\x94\x77\x2a\x43\xdc\xfe\x05\x97\xfd\x6d\x13\x3b\x3f\x2e\x96\xff\xc5\x66\x7d\xd5\x92\x8f\x23\xec\x3c\x75\x0f\x84\x59\x93\xa3\x4e\x97\x76\x15\x9a\x68\x30\xd6\xfd\x90\x13\xee\x7a\xea\xa1\xfc\xcd\x69\xb9\x6d\xf2\x84\x70\x4f\xd0\x88\x88\xb1\x5b\x64\xe2\xe9\x0d\x57\x8c\x5c\xfc\x0f\x95\x69\x3f\x6a\xb6\x5c\x69\x47\x44\x6a\x85\x7c\x02\x9c\x7c\xa6\x60\x80\xb7\x54\xc7\x73\x4b\x78\x99\x8a\xbe\x9b\x7c\xc6\xef\xd0\x9a\x44\x18\x19\x4d\x88\xb3\x4e\xc6\xc3\x3a\xf6\x30\xdb\x81\xde\x5b\x99\xfe\x65\xaa\xc8\xb7\x33\x62\x37\x91\x19\xc7\x00\xd1\x07\xed\xfc\x19\xf2\x70\x76\x04\x68\xee\x8e\x5f\x15\x5d\x9a\x34\x7e\x57\xb5\x93\x0f\x32\x7a\x8d\x11\xc6\x67\x4d\xdd\x02\x0f\x9e\x7d\x9b\x76\x1d\xba\x5b\x83\xa8\x73\x02\xf1\x83\x3e\x5a\xbd\x49\x52\x6d\x66\x39\x1e\x5b\xf0\xe3\x5b\x44\x53\xd6\x30\xbf\x7d\x0a\xdb\xfe\x50\x1a\xef\x81\xe6\xc5\x93\x8f\x92\xcb\x75\x2f\x5f\x14\xd2\x80\x6f\x90\xae\x15\x46\x05\x1c\xcc\x7f\x91\x3c\x5d\x6a\x38\xff\x3b\x7b\x9a\x23\x66\x2e\xf1\xf0\x08\x08\xed\xb2\xfa\x31\xec\xba\x5c\x8d\x33\x87\xe8\x75\x41\xcd\x06\x16\xed\xbf\x3a\xaa\x35\xa5\x37\x92\x28\x61\xf4\x4c\xbd\x9f\x99\x2b\x82\x46\xd9\xc6\x4c\x41\x98\x81\x70\x1a\xb4\x3f\x7f\xd4\x64\x21\x0d\x80\x2b\xa6\x56\xd9\x5c\x0f\x24\xa3\x45\x99\xb2\x0b\x1e\xc2\x00\x11\x48\x5c\xfc\xb3\x18\x6b\x7b\xcf\x69\xd7\x45\x81\xa7\xa3\xee\xd6\x13\x4c\x4e\xec\xd6\x55\x74\xa4\x32\x0d\x9c\x57\xa8\x49\xc4\xe7\x8c\x8a\x5c\xe8\x25\x05\x00\x4a\x54\xf1\x9d\x4b\xdc\x82\x23\x40\x1b\x34\x94\x6b\x7d\x66\xe4\x7e\x63\xcf\x9d\x0f\x57\xd0\x94\x54\x91\x38\x4b\xc6\x86\x8c\x4b\x47\x86\x90\xe5\x50\x02\x1d\xf1"}, -{{0x8a,0x35,0x01,0xb7,0x69,0x53,0x60,0x3c,0x90,0x33,0xe3,0xbc,0xbf,0x3e,0xc3,0x78,0xd2,0x57,0x01,0x1a,0x6c,0x50,0xb8,0x97,0x62,0xd4,0x91,0xea,0xa7,0x2c,0x5e,0x0d,},{0x77,0x8f,0x20,0x19,0xdc,0xd8,0xdb,0xb8,0x6c,0x67,0x37,0xcc,0x8d,0xc1,0x90,0xc5,0xa0,0x4c,0x50,0xb5,0xbf,0x45,0x88,0xbc,0x29,0xfa,0x2a,0x47,0xaf,0x25,0x26,0x72,},{0xa8,0xa3,0x09,0xba,0x52,0x12,0x5e,0x76,0xa4,0xa6,0x1e,0xb4,0x3f,0xd4,0x13,0x5c,0x41,0xab,0x11,0x79,0x9b,0x91,0xcc,0x54,0xff,0xc9,0xc6,0xa2,0x0f,0x05,0x0c,0xc5,0x95,0xb2,0x81,0x43,0xc8,0x74,0xbd,0xb9,0x28,0xbe,0xed,0x26,0x1d,0x9c,0x0f,0x12,0xaa,0x19,0x2e,0x66,0x40,0xbf,0xda,0xd5,0x4b,0xa0,0xd4,0x78,0x42,0x6b,0xce,0x09,},"\xe6\x09\xf1\x22\x4a\x6a\x45\x11\x40\xcb\xc0\x25\x4d\x43\x2c\xe5\xfd\xdd\x08\xa8\xe9\x12\xf8\x1c\x41\x2f\xdf\xd5\x18\x2f\xf6\xac\x2f\x13\xc5\x76\xc8\x14\x5b\x15\xf2\x5b\x40\x9d\x85\x3f\x91\x44\x09\xe4\xe0\x2c\xef\xc3\x9d\x9b\xef\x4a\x2a\x06\x04\x98\x57\x0b\x2d\x3a\x28\x38\xc9\xb0\xb8\xe3\xaf\x4f\xc3\x7e\x19\x15\xf8\x04\xa8\x01\x88\x58\x5b\x30\xb6\x8a\x3f\xfb\x2e\x96\x0c\x73\x20\xe8\x27\xd2\xfe\x36\xe6\xa3\x28\xcc\x6e\x78\x06\x34\x8a\xdb\x0b\x77\x3b\x78\x4d\xe5\x29\xbb\x6f\x64\x75\x1b\x21\x05\x85\x94\x94\xfd\x49\xdb\x0b\xc7\xf6\x2d\xf4\x6b\x9d\x7c\xe6\x76\x97\x5c\xc5\xf4\x38\x56\x49\x84\x36\x81\x2e\x04\xf2\x6f\xb8\xb8\xab\x7e\xba\x12\xf1\xd5\x67\x22\xeb\x82\xeb\xfa\xfa\x47\x35\x97\x7a\x26\x68\x1c\xb0\x3f\xa4\xbc\x69\x51\xab\x9c\xbd\xf7\x87\xe3\x27\x8f\x2f\x57\xf2\x9e\x12\x09\x5f\x8c\xa2\xa1\x78\xcf\xa7\x57\x13\x37\xf0\x27\x42\x37\x66\x9f\x97\x65\x7d\x4b\xad\xb3\x94\x36\xd7\x86\x49\x25\x80\xfd\x55\xd8\x6b\xe3\xa0\xcd\x17\xd1\x60\x57\x01\x7b\xaa\xae\xa0\x0c\x1e\x14\x55\x21\x59\xbc\xab\xc0\xe6\x66\xba\xd3\x41\x8e\x4e\xc1\x3b\xfe\x16\x3b\xe2\x56\xf0\xc8\x9b\xc2\x34\x4a\x8d\xdf\x99\xca\x81\x60\xb1\x89\x87\x5a\xd3\x22\xd9\x0f\x58\x13\x25\x28\x1d\x53\x89\x96\x5c\x0a\x7b\x7b\xca\xe2\x29\x4a\x3c\xbe\x35\xa4\xe4\xe8\x3b\x54\xc4\x27\x63\x53\x96\x0f\xad\x11\x85\x32\xd4\x9b\x70\x76\xf2\x5a\xd1\x90\xab\x56\x94\x91\x4f\x71\x08\xb0\xab\x69\x69\xa1\x91\x28\xfb\x0a\xef\x00\xe6\x5a\x04\xfc\x83\x2d\x07\x69\x61\x67\xb9\x34\x2b\x35\x5e\xc5\x77\x37\xca\x37\xcb\xff\x3b\xb3\x19\x31\xcb\x58\x71\x2a\x4c\x46\x89\x52\xc6\x45\x9d\x56\x7a\x26\xe7\x95\x01\xe4\xe3\x1b\x1b\x09\x53\x53\x76\x32\x02\x9e\x9b\x49\x0f\x72\xe5\xa6\xe0\x57\xdd\xb4\xb3\x17\x56\xfd\x97\x04\x21\x8b\x1b\x8f\x4d\xcb\x54\x30\xc0\x25\x04\x2f\x47\x16\x9b\xfc\x7c\x80\xd7\x1c\xab\x8c\xa0\x7f\x34\x0a\xfa\x00\x8a\xbb\xe2\xe3\xa0\xab\xe1\x41\xda\x8d\x41\xca\x6b\xd6\x9d\x36\xfd\xb1\x1a\x41\xce\x0b\x72\xfa\xbc\x00\xd9\x7e\xa6\x05\x27\x00\x10\xb2\x59\xdf\x8e\x10\xdd\x22\xdc\x17\xc1\x39\x90\xa0\x5f\x02\x33\xe3\xca\x85\x6b\x40\x97\x1c\xb3\xe2\x1c\x8b\x39\x50\xb1\x3f\xc8\x4e\x1f\x26\x6c\x2a\x6f\xbe\xce\x88\xd5\x97\x25\xc3\xcf\xb2\x22\x5d\xbc\x1e\xe9\x5b\x68\x6d\xb7\x04\xfc\x93\x7b\x76\x6f\x0a\x9b\xfe\x95\xa4\x2b\x90\x10\xf1\x22\x9c\x61\x0d\x7e\xde\x09\x57\x12\xc8\xf0\xf1\xfb\x00\x47\xc0\x40\xa8\x70\x30\x6c\xd8\xdc\x74\xc4\xda\x51\xbf"}, -{{0x42,0xb5,0x36,0x52,0xd0,0x8b,0x5d,0x76,0x6e,0x66,0xad,0x8f,0x3e,0xbf,0x69,0x3c,0xfd,0x77,0x90,0x7c,0xad,0xd9,0x8b,0x54,0x66,0xdf,0x77,0xdf,0xa2,0xc6,0x37,0xad,},{0x88,0x46,0x3b,0xb8,0xa4,0xb6,0x38,0x8d,0x92,0x4c,0xb8,0x62,0x09,0x83,0x41,0x95,0x43,0x5d,0x79,0xd7,0x7f,0x8c,0x02,0xf4,0x6b,0xbd,0x16,0xd8,0x2e,0xfe,0x42,0xb3,},{0x30,0xc4,0xb9,0x9e,0x68,0xec,0x33,0x51,0x30,0x8f,0xbc,0x76,0xd9,0xca,0xf0,0xaf,0x62,0x21,0xb5,0x96,0xb7,0x01,0x7f,0xe1,0x0c,0xc6,0x33,0x02,0x3b,0xa9,0x7f,0x02,0x38,0x96,0xfe,0x32,0x2b,0xaa,0x34,0x76,0x60,0x61,0x0e,0x05,0xfa,0x49,0x3d,0x21,0x8f,0xa3,0x60,0xf1,0x8d,0x93,0xe2,0x75,0xd1,0xef,0xf6,0x66,0xb6,0x3d,0xb2,0x04,},"\x9e\xe9\x13\xc7\x4e\xe3\xc5\xe8\xc9\x0d\x64\xb8\xae\x3a\x60\x04\x9f\xc7\x65\xe1\x76\x06\x0b\xcd\x1c\xd0\x9f\x0e\xda\x60\xbf\x23\xba\xdb\x8a\x1c\xaa\xc3\xd6\x6e\xbc\x52\x68\x14\x6e\xe4\xa5\x4e\x1e\xb2\x31\xed\x25\xef\xf9\x5b\x90\xa6\xe9\x83\x37\xa5\x40\xa3\xf4\x84\x49\x79\x4a\x48\x73\xbf\xc2\xe8\x47\x28\x96\x6b\xb7\xc6\xff\x67\x6a\x2f\xf5\x73\x11\xc1\xc2\x5e\x15\xfb\xf3\xd4\x0e\x9f\x25\xab\x5d\xb9\x1f\xdd\xb7\xa0\xae\x43\x6c\x8e\xc0\x70\x75\x4b\x6d\x74\x3a\xa1\xd6\x04\x8f\xb5\xbd\x7f\x5b\x8e\x4c\xca\xd2\x03\x28\x38\x95\x30\xf1\x13\x74\xa4\x89\xb1\xd5\x05\x31\xa3\x9c\x9b\x32\xb4\x03\x69\x62\x60\x06\xd2\x64\xa9\x9e\xec\x4f\xac\x13\x41\xf4\xe7\x46\x79\x45\x7b\x41\x8e\x6b\xbf\xba\x23\x3f\x1c\xa1\x58\xf7\xb2\x9d\x40\xd5\x03\x01\xf9\xd9\x25\x36\xfd\xc5\xc2\x3f\xe5\xde\xe4\xd6\xdf\x0e\xbf\x13\xdf\xa3\x75\x4a\x14\xc8\x56\x00\x9a\xde\xa1\xdd\xa4\x09\x30\x4c\x1f\x60\xd2\x53\x30\xfb\x10\x95\x79\x47\xa0\x05\x08\xf2\xfd\x76\x42\x2e\xac\x69\x4c\xc3\x9f\xa8\xae\x7f\xcc\x77\xa0\x2f\xd9\xee\x5f\x91\x0d\x93\xe8\xaa\xc6\x8f\x14\x5d\xd8\x78\x87\x6b\xa8\xed\xa0\xa4\x9f\xcb\x20\x9c\x34\xea\x22\x0d\x4d\x06\x05\x54\x6f\xc4\xa8\x09\xba\xf0\x10\xd5\x33\xe4\x5d\x17\xb0\xe1\x6a\x46\xe9\x1e\xa6\xfe\xc2\xcd\xc5\xa8\xb3\xec\x50\x14\xb2\x5e\x92\xd8\xe5\xc9\x28\xab\x06\x99\x3d\x4f\xe2\x3a\xc8\xd4\x5c\x89\x03\x78\xdd\x13\x3f\x00\xed\xb9\x37\xc0\x71\xf7\x5c\xfc\x13\xa4\x02\xe3\xe4\x29\xa8\x48\x65\x2a\x17\x5c\x9b\x6f\x6e\xac\x86\xf6\x18\x8a\x44\x48\xa9\x6c\xe2\x87\x2e\x5f\x65\xf9\xbd\xb8\x71\x66\xc9\xb8\x7a\x7e\x95\x8e\x80\xbb\x65\x66\xe3\xfc\xf8\x71\x19\x0c\xf4\xa8\x67\xe6\x12\xcf\xc1\xe4\x37\x1d\x2b\x73\xd2\xa0\xad\x0a\xa4\x00\xba\x69\xe6\x63\x36\x23\x3b\x0f\x3c\x52\xb8\xa6\x8b\xca\x05\x12\x56\x01\x25\x50\x46\xe6\xf4\x9d\x68\x8d\x2d\xb8\x5c\x7b\x82\x12\x70\x51\x6e\x3c\x06\x13\xf3\xf2\x3f\x9c\x57\xcb\x4c\x87\x14\x28\x5c\xdf\x95\xe1\x06\xa3\xb5\xaf\xca\xeb\x81\xb7\x2f\x34\x3e\x87\xbd\x92\xf1\x58\x1d\xcf\x9a\xa9\x0a\x02\x4f\xa4\xa1\x04\x80\x59\xe3\x0d\xe8\xff\x0d\x16\x79\x4d\xcd\x74\x5d\x2b\x2d\x53\x4c\x52\x0f\x82\x78\x53\x86\x74\xa9\x34\xc6\xf1\x4a\x84\x28\xe3\xda\x01\x8a\x36\xe4\x5a\xa5\x82\x7c\xf4\xb1\x52\x84\x34\x6f\xd6\x93\x63\x14\x92\x19\xbb\x0d\x1b\xc9\x27\xd8\xd1\x93\xc4\x82\x69\x2f\x97\xdc\x88\xd8\xed\x33\x7d\x0c\x9d\xc9\x9c\x7a\x5e\x11\x1d\xce\xd4\x22\x50\xd5\x80\xe2\x06\x92\xbb\x7b\x88"}, -{{0x14,0xcf,0xe0,0x0f,0xa7,0x19,0x0a,0xe8,0x10,0x88,0x8a,0xe2,0xbb,0xd0,0xff,0x64,0x12,0xcf,0x1f,0xd4,0x08,0xa3,0x08,0x29,0x43,0x83,0xa1,0x94,0x53,0xb5,0x90,0x73,},{0x4e,0x61,0xaf,0xe8,0xc1,0x74,0xb6,0xee,0x1a,0x29,0xfa,0x09,0xcf,0x87,0xb4,0x00,0x81,0x39,0xf1,0x07,0x0b,0xc8,0x53,0x1b,0x6d,0x06,0xf5,0x4c,0x95,0x62,0xa4,0xf3,},{0xf7,0x85,0xa4,0x6f,0x69,0xbb,0xd0,0x99,0xfa,0x01,0x11,0x24,0xba,0x90,0x32,0xc1,0x89,0x74,0x2c,0x9e,0x00,0x1d,0xbb,0x87,0x81,0xd8,0x22,0x33,0x45,0xa9,0x56,0x9d,0xc1,0x44,0xca,0x69,0x4d,0x90,0x24,0x5e,0x0e,0x51,0x3e,0x88,0xab,0x02,0x3f,0x7f,0x0f,0x99,0xb7,0x41,0x61,0x59,0x75,0x8d,0xd0,0x34,0xe7,0xa8,0x9c,0xff,0x36,0x00,},"\xbc\x66\xf8\x01\xda\xa8\x29\x85\x8e\x74\x02\x93\xd4\xd2\x18\x7b\x8e\x1a\x5a\xfb\xa5\xfd\x67\xb1\x09\x56\xc6\x53\x46\xac\xa9\x44\x29\xd3\x2e\x4c\xfb\x35\x84\xab\x0e\x00\x5d\x0d\xd7\x42\x78\x1d\x47\xe8\x94\x47\xc4\xe1\xd8\x1b\xf7\xe6\x15\x4f\x8f\x73\xaf\x03\x36\x1a\xd5\x6e\xa3\xc0\x60\x00\x75\x4b\x9f\x32\x7d\x4e\xde\xac\xc4\xd3\x48\xaf\xb5\x48\x23\xe1\xc9\xd4\x9c\xd8\xff\x2b\x19\xf4\x20\x21\xb4\x0d\x58\x0c\x39\xce\x3d\x24\x36\x61\xb8\x54\x21\xfe\xc9\x15\xba\x9d\xd2\x76\x2f\x85\x0b\xd2\x08\xfd\xbf\x20\xff\xab\xa5\x6a\x46\x86\x60\xf1\x7c\x00\xfb\x1c\x0f\x4e\x85\x27\xa5\x09\xdd\x4e\xec\x13\x36\x0c\xf6\xe3\xca\xc5\x42\xb8\x75\x18\x2f\x2a\x7c\xe7\xbe\x0a\x33\x30\x2f\xe2\x6d\x36\x29\x62\x93\x84\xe3\x5c\x06\x78\x9d\xe6\x34\xe9\x0e\x96\x4f\xbd\xa8\xcb\xba\x98\x11\x1e\x22\xe8\xd0\x76\x26\x84\x26\x6a\xab\x76\xae\xba\x4a\x38\x07\x78\x69\x68\x14\xa1\xe3\x11\x94\x3c\xb3\x50\x58\x92\x64\x0c\x44\xe3\xaa\xc4\x53\x0c\x50\xac\x60\x4a\x8d\x2c\xcc\x7c\xea\xbf\xfe\xa4\xaa\x3d\x7f\x48\xa6\x6d\xcd\x75\x88\xb8\x02\x09\xdb\xc1\x73\xf0\xc6\x63\xe8\xfc\x87\xa3\x6e\x89\x2e\xc9\xa3\xff\x8f\x60\xd2\xe0\xd8\x70\x4e\x5b\x6c\xbb\x87\x32\x75\x15\x1a\xd4\xcc\x00\x57\x16\x50\x31\x90\x50\x39\x65\x1c\xa1\x0a\x95\xc6\xfd\xa3\xb2\x78\x27\xa6\x57\xef\x9a\x5f\xc3\xeb\x5b\x53\xca\xc6\x1d\xda\xf5\xa4\x17\x04\xc8\x78\x57\x0c\xbc\x3c\x41\xc4\x75\xb1\x17\xc0\x5e\xab\x0b\xb1\x96\xbc\xb7\xc4\x33\x34\xde\xbd\x64\xb9\xe3\x74\x50\xd2\x3f\x5c\x10\x16\x1e\xc5\xab\x4f\xcc\xd7\xcf\x30\x8e\x2a\x99\x95\xcc\x9e\x57\x8b\x85\xe8\x28\x5a\x52\x08\xb9\xef\xd4\x2a\xf9\xcf\x2a\xc2\xb3\xb7\x46\x42\x54\x88\x9a\x21\x87\x31\x7e\x32\x49\x97\x09\xb9\x13\x95\x3a\xd4\x6f\x1c\x23\xe1\xb6\xb5\x6f\x02\x4c\x4a\x7d\x48\x46\x11\x92\xc0\x1c\x56\xc5\x4c\x56\x47\x91\xec\x0a\x67\xb6\x1a\xcb\xf9\x57\xe6\xd0\xd7\xda\x80\x53\xed\x13\xa4\x18\x93\xd7\x67\xfc\x57\x37\xcd\x19\x55\x53\xda\x5d\x5b\x07\x06\x5f\x47\xd7\x2a\x35\xc4\x2b\x00\x1e\xb6\xdb\xd0\xf8\xe7\x7a\x4b\x76\xa6\x26\x61\x92\x64\x7f\x41\x55\xea\x11\xbd\x12\x37\xba\x77\xc8\x7c\x62\xbf\x4b\x01\x14\x9f\xc5\x8b\xc2\x8f\x0b\x5a\x28\x64\x85\xd3\x71\x7d\x32\x39\x64\x04\x62\x18\xe7\x0c\x7e\x38\xb7\xd5\xe7\x4b\xa6\xb1\x2b\x02\x2f\x18\x19\x7d\x92\xc1\x3b\xca\x89\x33\x5c\x85\x6c\xbc\x57\x56\xaa\x3b\x64\xec\x1f\x46\xe3\x96\xb1\x16\x1c\x87\x1c\xd2\xdf\xde\xd1\xa4\xec\x91\x92\x74\x29\x37\xc0\x70\x45\x31\xc7"}, -{{0xac,0x0f,0x7f,0x04,0x18,0xde,0x67,0xe3,0x48,0xfa,0x6d,0x56,0x86,0xc4,0x6d,0x21,0xca,0x72,0x62,0x2e,0xe6,0x9e,0xaa,0xbe,0x00,0xd5,0xc9,0x07,0x5a,0x34,0xf1,0x79,},{0xfe,0xab,0xde,0x08,0xf0,0x0a,0x2b,0x68,0x2b,0xce,0x9d,0x45,0x99,0x0b,0xf4,0x5a,0xfc,0x95,0x83,0x39,0xdc,0x44,0x10,0x6d,0xad,0x33,0xb2,0xc4,0x90,0xef,0x70,0x90,},{0x75,0x91,0xcf,0x82,0x57,0xbe,0xad,0x39,0xa1,0xad,0x3b,0xa1,0x91,0x8d,0x51,0x8e,0x67,0x24,0x35,0x6b,0xf6,0x25,0xa5,0x73,0xea,0xe5,0x01,0xd1,0xaf,0x94,0x6c,0x13,0xc2,0x90,0xcb,0x63,0x15,0x6e,0xc9,0xd3,0x62,0x72,0x6e,0xe5,0x0b,0x39,0xfc,0x0a,0x7a,0x2b,0xbd,0x69,0xd4,0xa8,0x1b,0x75,0x93,0x2a,0x90,0xf8,0xc7,0xac,0x7d,0x03,},"\xe8\xd0\xe8\x32\x53\x35\xe0\xf3\x5a\x85\x46\x7b\xee\xd1\xe1\x1c\x6a\x20\x78\xc3\x5a\xe4\xa4\xa1\x05\x43\xed\xe4\x0c\x17\x12\xbc\x95\x20\x12\xd2\xf8\xfe\xc1\x05\xae\xf7\xc6\xc6\x5b\x36\x34\xb4\xa7\x4b\x22\xb4\x98\xb9\x13\x50\x7d\x1f\x6c\xfd\xe8\x38\x58\xe6\x83\x0c\x0a\xf4\xf4\x64\xa6\x89\x9d\x5c\x4e\x27\x9a\xff\x36\x75\x4c\x21\xda\x80\xa1\xbb\xd1\xdc\xf4\x62\x20\x37\x5b\x1e\x11\x2a\x5a\x72\xf1\xab\x6e\x8f\x64\x19\x42\xf6\x6d\x9b\xbd\xbb\x17\x9c\xf0\x13\x9e\xa8\xde\xb0\xf4\xb8\x14\xf5\x0c\x51\x33\x29\xa1\xa0\xe2\x67\xc4\x43\x3a\x23\x31\x82\xbc\x4a\x2a\xcb\x2c\x6d\x4f\x00\xb2\x40\x94\xd3\xbd\xc0\xeb\x81\xcf\x37\xd3\x82\x60\xc2\x10\x7d\xd9\x49\x06\x13\xd2\x76\xee\x1f\x72\x26\x6c\x6e\x4a\xcc\xa5\x24\x98\x11\xa0\xf8\xa7\xda\xe6\x6a\xed\xb7\x5c\x3d\xf4\xc8\xca\x3c\xb5\xd9\xc5\x67\xba\x54\x1e\xe5\xa9\x14\x0c\x50\x58\x72\x72\xaf\x34\x53\x0a\xb8\xb0\x8b\x9e\xc0\x32\xea\xc0\x60\x39\xe6\x92\x63\x0e\x2d\x55\x4d\xf7\x7c\x1a\x03\x88\xb3\xca\xaa\x3b\xe3\x75\x4a\x84\x96\x1f\xb2\x99\xe4\x02\x22\x71\x58\xce\x36\x3e\xac\x26\x47\x8d\x47\x97\x75\xe5\x68\x5a\xdb\xf8\x28\xbb\x35\x5e\x3c\x89\xcc\xe2\x41\x50\x3c\x15\x36\x64\x32\xba\x94\xcd\x3c\xd9\x54\x79\x14\x4b\x63\x6e\x0d\xe7\x0b\x3f\x16\xd1\xa3\xca\x51\x8e\x39\x90\x09\xa4\xc2\x47\xa7\xf9\x63\x67\xc7\x14\x66\x08\xaa\xcc\x00\x14\xfc\x35\xb8\x4a\xf9\x93\x3f\x09\xba\xbb\x89\x93\x7a\xbb\x8c\xed\x11\x18\x91\x34\x3d\xdb\x79\xf6\x0b\x78\x89\x8a\xb5\x93\x8f\x8b\xa3\x81\x4b\xd8\x00\x26\x05\xb1\xdf\xd2\x97\xfa\x07\xc4\x75\xa0\xd4\xf8\xf4\x45\x1a\xcd\x70\x7d\xe8\xaf\x6c\x0e\x88\x18\x83\x3a\x3a\xbe\x5c\x96\xd1\xa8\xc6\xc9\x6e\x2c\xb6\x33\x28\xeb\xa4\x4d\xd1\xd3\x46\x84\xe4\x12\xf2\x88\xe0\x65\x20\x9d\x11\xeb\x80\x94\xd2\x2e\x4c\xc8\x02\x62\x9c\xcb\xa3\x39\x26\xbf\x1a\xd3\x6a\x62\x85\x13\x8a\xbe\xe0\x5c\x5a\x39\xa4\x75\xf3\xfd\xd0\xb3\xec\x8c\x37\x0c\xd9\x57\xa8\x37\x9e\xc2\xcd\xaf\x03\xe8\x95\xc1\xba\x12\xb4\x49\xd6\xcd\x8b\xe0\xf3\x5d\x99\xe2\xb7\xfb\xaa\x92\xdd\x54\xe6\x4e\x7c\x35\xce\xb8\x8a\x71\xa6\x80\x52\x7c\xb3\x73\xaf\xe1\x4c\xdd\x15\x8a\x0b\x90\xbf\x2d\xae\xc8\x0d\x2e\xdb\xdc\x31\x28\xcd\x6b\x63\xfa\x53\x2a\x1c\x27\x8c\xdf\xe0\xf8\xeb\xb4\xab\xba\x5e\x1a\x82\xbc\x5c\x3f\xed\x15\xc5\x79\x5b\xd9\xff\xb5\x76\x08\x2c\xc4\x79\xfa\x1b\x04\xc5\xc5\xaf\xca\xd2\x69\xa0\xf1\xad\xdf\xe7\x60\x42\xc3\xa8\xf1\xf2\x53\x77\xb6\xcb\x72\xec\x16\x14\xeb\x63\x83"}, -{{0xb5,0xa7,0xc7,0x67,0x93,0x63,0x80,0xb3,0xe9,0x87,0x51,0xca,0xfd,0x3e,0xa8,0x9b,0x38,0x8a,0x32,0xcf,0x82,0x8b,0x32,0x1c,0x5b,0xd0,0xcc,0x8d,0xd8,0x5b,0xaf,0x00,},{0xbe,0x7f,0xa6,0x5f,0x1f,0x6b,0xe5,0x10,0x27,0xf8,0xb8,0x48,0xdb,0x7a,0x8c,0x40,0x49,0x61,0xbf,0x1e,0x21,0xa2,0x3d,0xf2,0x3b,0xb8,0xce,0x05,0x85,0x0c,0xda,0xa1,},{0x60,0xe4,0xd2,0x3f,0x1f,0x08,0xfc,0xe4,0x66,0xc9,0x91,0x5d,0xde,0xd9,0x32,0x56,0xb5,0x2b,0x32,0x7e,0x5f,0x81,0xfb,0xb3,0x1d,0x1d,0x10,0xd3,0x21,0xc3,0x90,0x36,0x6e,0xf0,0x01,0xfd,0x75,0x9a,0xa9,0xd0,0xa5,0x51,0x62,0xd5,0x36,0x4d,0x91,0x8b,0x48,0xc7,0x32,0x7e,0x77,0xcf,0x53,0x58,0xbc,0x43,0x19,0xe3,0x25,0xcd,0xd6,0x08,},"\x6b\x67\xc7\x95\xd6\x6f\xac\x7b\xac\x84\x42\xa6\xc0\x99\x2c\xb5\x75\x88\x43\xb3\xe3\x93\x9e\x3c\x27\x6c\x6e\x90\x08\xda\x82\x00\x76\x77\xbf\x9e\x67\xe9\xac\x5a\x1a\x0f\x48\x6b\xea\xc0\xd8\x56\x19\x1f\xae\x25\xa1\x27\x39\x2b\xed\x46\x9b\xc7\x8d\xeb\x0c\x4b\x89\x3f\x67\xf1\x71\x6d\x83\x50\x90\x77\xe4\xa1\xbf\xd4\x13\x6d\x03\x15\x2d\xcc\x3b\x76\xd9\x52\x49\x40\xa6\x06\x4c\x66\x9f\xbf\x51\xf6\xb9\x10\x34\xb6\xd5\xf2\x89\x86\x78\xa1\x3a\x24\x70\xf6\x64\x1e\xc8\x02\x45\x7c\x01\x02\xc3\xeb\xf6\x34\x5c\x32\x7e\x74\x1b\x80\x64\x4b\x3a\x99\xbf\x72\xb5\x9a\xb8\x01\x6f\x35\xd2\x51\x88\xa0\x85\x75\x0d\xc0\x60\xe5\xa8\xd5\x24\xae\x21\x3f\x07\x8f\x28\x8c\x7b\x34\xbc\x41\xf3\xce\x35\x6b\xf2\xda\xfd\xd2\xe0\xdb\x4f\xb8\xd7\xc2\xc3\x19\xf9\x90\x60\x05\x97\x17\x02\xe4\x9c\xa6\x2e\x80\x50\x54\x0d\x41\x21\xd2\x42\xf2\xee\xab\x1b\xd1\x34\xe6\x0b\xf1\x1b\x3e\xc7\x1f\x77\x65\xa9\x7c\x0e\x09\x84\x55\xe5\x9d\x22\x35\xd6\xb3\x7e\x7c\x9f\x5b\x21\xfa\x11\x2c\x3b\xa3\x9e\x4e\xa2\x00\x61\x4f\x58\xdf\xb3\xeb\x7b\x83\x6f\x0b\xec\x1d\xdd\x43\x8d\x14\x22\x45\x0a\xe7\xde\xd1\xdf\x9d\x71\xe5\xd9\xbc\x8f\xa3\xb6\xe6\xf7\x84\x46\xce\x7c\x79\xd0\xbc\xfb\x1c\x2d\x26\xc6\xfe\xce\x68\x68\x2d\xff\xc6\x0a\x9c\x6e\x0a\xd0\x5f\x2a\x09\xf2\x1d\x75\x23\x25\x1c\xb0\xc3\xd0\x8e\xfb\xbf\x8a\xc1\x63\x39\xd7\x17\x02\x4d\x67\x60\x24\xc1\xee\x3c\x1f\x62\xc5\xae\xab\x7f\xff\x93\x7c\x57\x45\x4d\xf7\xbd\x96\xf9\x84\x4a\x2a\x39\x99\x58\x41\x8a\xaa\x6f\x18\x48\xbe\xbf\x7b\xf1\x29\x2c\x24\xeb\x5c\xd8\xea\x56\x34\x0c\x5b\xeb\x26\x88\x02\x4a\x69\x53\x27\x5b\xe6\xef\xd1\xb7\x1b\xa8\xbe\x6e\xb7\x7f\x0c\x65\xa7\xc5\x11\x1b\x96\xc4\xc1\xf3\x9c\xb7\xaa\xf8\x3f\xda\xae\x8d\x14\x8d\x7a\x8a\xf4\x0a\xe9\xe6\x51\x91\x9f\x7c\xe2\x8c\x8b\x2b\x6e\x45\xe4\xd3\xd5\x6f\xdd\x54\xd0\x0c\x24\x12\x79\x0c\xbd\x6f\x80\xe1\x08\x19\xe0\xb8\xf3\x7c\x84\xfa\x00\x49\x88\xad\xaf\xcc\xbb\xc2\x1c\x63\xd6\xbf\x2e\x73\x2d\x9d\xd6\x3b\xd4\x9b\x04\x12\xb9\x67\x4e\x1e\x88\xf6\x14\x2f\x7f\x86\x7f\x1f\x26\x89\x1b\x22\x43\x04\x23\xce\xc4\xdb\x91\xb6\x1c\x2a\xbc\x5c\x8f\xbd\x46\xb8\xb9\x35\x96\xfc\x51\x60\x68\x31\x36\xe2\x11\x29\x82\x27\x96\xeb\x5e\xa0\x88\xe0\xa7\xd8\x12\x1b\x25\x57\x2e\x3e\xc3\x77\x43\xd1\xff\x6d\x8d\x1c\x35\x36\x43\x9a\x10\xe8\x4a\x66\x5f\x2c\x75\xee\x73\xcd\xc6\xff\xac\x4c\xc2\x87\x24\x46\x9f\x79\x70\xb4\x75\x07\xdf\x3e\x1b\x14\xd4\x77\xae\xc2\xbb\x20"}, -{{0xe1,0x36,0xf3,0x98,0xa6,0x05,0xd1,0x34,0x57,0x84,0x8c,0xea,0xd0,0x7c,0x72,0x86,0xf4,0x2e,0x2f,0x28,0xdf,0x8c,0x12,0x8a,0x3d,0x0b,0xb7,0x2b,0x29,0xaa,0xcc,0x19,},{0x6a,0xa5,0x04,0x5a,0x66,0xf7,0x72,0xa5,0x71,0xfe,0x3e,0x42,0xd1,0x17,0xef,0xcd,0xf6,0xc4,0x95,0x91,0x99,0x61,0x86,0x01,0x2f,0xa9,0x8f,0x7c,0x48,0xe0,0xcd,0xa7,},{0x75,0xa4,0x5c,0x6b,0x95,0x66,0x89,0x98,0x29,0xb4,0x1e,0xe5,0x17,0xb7,0x04,0x5a,0x47,0x3a,0x4f,0x7a,0x26,0x41,0x43,0x9b,0x5d,0x7c,0x56,0x73,0xe0,0x0d,0x8f,0x5c,0x06,0x6f,0x12,0x91,0xf8,0x5d,0xea,0xda,0x05,0x02,0xbd,0x16,0xe9,0x70,0x9f,0x82,0x7d,0x47,0x51,0xf2,0x87,0x38,0x62,0xe8,0x21,0x9e,0x57,0x74,0x6a,0x19,0xa9,0x00,},"\xd3\x28\x57\x9d\xe4\xc5\x37\x2f\x3b\x38\x2c\x48\x01\x1b\x2d\x4c\x60\x29\xf9\x04\xf3\xa3\x3e\x07\xd0\x83\xd7\xe2\xb0\x37\x56\xaf\x2c\x4c\x97\xa2\xd6\x6c\x10\xec\x41\x54\xd8\x74\x79\x20\x42\xb6\x46\xe4\xaa\xe5\x10\x1d\x50\x1b\xd1\xbf\x6f\x51\x17\x51\xd0\xaa\xf8\x21\xcd\x7c\x0b\x3e\xe6\xd0\xd7\xc6\x90\xa2\x77\x7f\xe1\x6b\xdc\x7e\x49\xb7\xda\x4b\xbb\x4c\xce\x3b\x61\x8e\xe9\xb6\xf2\xe3\xa1\x92\x40\xcd\xb7\x07\x33\xb9\x84\xb1\xc9\x40\xec\x66\x96\x0b\x72\x8c\xbb\x87\x4b\x80\x64\x31\x23\x72\x2d\xb9\xdb\xbe\x88\x32\x20\x08\x93\x1b\x1c\x89\x4e\xf5\xd2\x10\x99\xe6\x3e\x7c\x65\x00\x7a\xcd\x61\x78\x4d\xb4\x99\x4a\x2f\xb4\x0c\x3e\xfe\x9c\x47\xfa\xd6\x37\x63\xdd\xe0\x6f\xa0\x17\xa2\x6b\x82\xe7\x1b\x9d\xaa\xbc\x4f\xf0\xf6\xc7\x9b\x8c\xa7\xcc\xb4\xdc\x20\x31\xbe\xf1\x08\x73\x67\xc7\x08\x69\x74\xa0\x05\x66\xde\x41\xa7\x1e\x11\xd9\x93\xab\xe4\x33\x56\x98\x92\xb8\xf7\x5d\x76\x37\x99\x32\x45\xc8\x84\x47\x8a\xbe\x3f\x95\xf4\x4b\x0a\x4b\xbe\xde\xfe\xf8\x90\x6b\x75\xe0\xd3\x40\x20\xae\x53\x64\x55\xb0\xe0\x6f\x9b\xfe\xe1\x1e\xc9\xb8\x60\x4b\xac\x2c\xc6\xeb\xe0\x8c\x8f\xd5\xf5\xcc\xcc\xcb\xc1\x61\x7b\x7c\xf6\x9a\x3c\x51\x2e\x1f\x0b\xdb\x58\x5d\xf5\xe1\x27\x43\x06\x1f\x7c\x20\x53\xbc\x37\x14\x43\x61\xc0\xb3\x5f\xd3\x9d\x56\xb1\xef\xaf\x92\xc6\x10\x36\x01\x93\xec\x20\x59\x8b\x82\x85\x80\x50\xa6\xd9\x9e\x08\x2b\xce\xfd\xbd\x53\x18\xee\x5e\xfb\x3b\x26\x0f\x32\x76\xf3\xc7\x3f\x9c\x24\xce\x0c\xda\x33\xc7\xac\xc5\x0c\xa5\xdd\x61\xbd\xb8\x5d\x79\x38\x25\xf6\x73\x2a\x6e\x33\x0c\xe6\x72\xac\x44\xfe\x6b\x2b\x9a\xfe\x6e\x2e\x96\x5c\x02\xd2\xa1\xfe\x0b\x57\xcb\x1b\x31\x7c\x1d\x31\x3e\xfd\xc3\x56\x49\x2f\xe8\x96\xfd\x14\x9d\xae\x51\xc9\x5c\xcd\xbb\x7d\x11\xf7\xd6\x10\xe0\xc6\xe2\xfd\x3e\x57\xfc\xfe\xf1\xc5\x7c\x71\x19\xa0\xaf\x6c\x78\x21\xfe\xcd\xb8\x9d\x80\x30\x2b\x49\xfa\xd4\x17\x43\xf3\xd2\xd7\xa0\x75\x15\x4b\x31\x43\xe5\x1a\xeb\x94\x7d\x4b\x5e\x8b\x7e\x4c\xa8\x6f\xec\x3e\x80\xbd\x9a\x78\x6e\x4e\x46\xed\x1e\x6e\x9f\x7e\x0b\x63\x52\x66\xd9\xfa\x09\x7a\xa9\xe2\x0f\x32\xe3\xd2\x77\x2d\x7c\x1f\x00\x8b\xcd\xd3\xf9\x2c\x72\x83\xc5\x77\x90\xc3\x62\x2c\xba\xd3\xca\x35\x80\x3c\x45\xc8\x69\xdc\x37\x7f\xf3\x6b\xd7\xc0\xe6\xf1\xbb\x89\x2f\x73\x29\xa6\xe0\x8d\xf1\xdb\xeb\xc8\x1d\xc7\xb1\x15\xf8\x52\xe3\x6a\xe5\xd9\x28\x72\x5f\xa7\xc6\xfb\x9f\x28\xb0\xfb\x39\x4f\x9e\x38\xfd\x87\x62\x5c\x5f\xa2\x3a\xab\xa4\x70\x54\xe8\xcf\xea"}, -{{0x97,0xb6,0x70,0x2e,0x24,0x68,0x05,0xdb,0xcf,0xc7,0xfa,0x42,0x4a,0x8c,0xaa,0xbc,0xf2,0x62,0xd4,0x66,0xa0,0x5e,0x0d,0xd2,0xd4,0xe7,0xc3,0x74,0xd5,0x7d,0x52,0x51,},{0xa7,0x16,0xc3,0xd5,0xce,0x78,0xf4,0xd9,0xc5,0xbe,0xe3,0x44,0x7d,0xda,0xf4,0x88,0x1c,0x98,0x6e,0xfd,0xf6,0x67,0xac,0x89,0x77,0xb4,0xfb,0x69,0xb5,0xa7,0x11,0x0a,},{0x90,0x00,0x55,0x41,0xdc,0xc1,0xd7,0xab,0x83,0x7f,0x4d,0xe5,0x39,0x3f,0xad,0xd6,0xa9,0x2b,0x26,0xa7,0xd9,0x3a,0xf3,0xf6,0x69,0xe0,0xf1,0xbf,0xd6,0x21,0xcb,0xd0,0x0c,0x8a,0x23,0x05,0x6d,0x2d,0xa6,0x78,0x65,0x57,0xc8,0x28,0xa4,0x9b,0xe1,0xe4,0x02,0x1d,0x99,0x31,0x12,0x35,0xac,0x0d,0x4d,0x56,0xee,0xfc,0x7c,0x95,0x36,0x05,},"\xea\xa8\x6c\xf7\x6f\xcb\x65\xc6\xf9\xfc\x20\x8a\xc3\x6f\x28\xb2\x00\xd3\xb4\x03\xac\xa7\x32\x07\x46\x1d\x8d\x96\xaf\xa2\x46\xd7\xc6\x9d\x17\xa7\xa9\xbf\x77\xf0\x55\x43\x56\x3a\x7d\x3e\xca\x1d\x40\x79\xe2\x29\x38\xab\xa1\xf6\xe9\xe0\x4b\x49\xfb\xc8\xed\x6f\x63\xb5\x99\x73\x0d\xe9\x97\x98\x31\xc0\x2f\x8c\xba\x61\xe5\x55\x60\xd7\x11\x0d\x4c\x6e\x61\x67\x97\x06\xa7\x15\x5d\x5a\x67\x3c\x54\xd1\x6f\xe4\xd2\x28\xc2\xec\xa7\x54\x6f\xaa\x13\x39\xf2\x6d\x7a\x0b\xb4\xee\x33\x96\x11\xaf\xde\xc9\xa6\x8f\x5f\xf5\xb5\xd2\x03\xb6\x00\x53\x3a\xd5\xa3\xb3\x68\xc8\x5d\xa1\x15\x63\xf0\x98\xcc\x26\x87\x1e\x7f\xa9\x9a\xef\xd3\x8c\xc2\x61\x51\xdb\x3b\x0b\xae\x38\xdb\x6a\x87\xb6\x78\x9e\x58\x40\xb1\x08\x84\xaf\x51\x1f\x3e\xcb\x3e\xcb\xf9\x4f\xf8\x6f\xdb\x90\x55\x05\xa8\xc3\x4b\x2a\xa6\x1f\xf2\xec\x9e\xc8\xfe\xbd\x1d\xfe\xd0\x96\x5b\x6f\xc5\xb9\xf8\x86\x9d\xc3\xa4\x75\x59\x97\x4a\x88\x22\x99\x67\x06\xda\xef\xbc\x6c\x5b\xf9\x84\xce\x06\xb0\xd3\x2b\x31\xcf\x9d\x8a\xd1\x36\xae\xd4\xb0\x52\x58\x6d\xce\x70\x73\xb7\x67\xb2\x34\xe4\xa3\x7b\xeb\xbc\x39\x3d\xd2\xe0\xf7\xd1\x55\x17\x35\x48\xc3\x8a\x15\x83\xef\x94\xe0\xaa\x84\xe7\xfc\xe0\x4f\xcc\x9b\x4e\x30\x0a\xd0\x99\x44\x9a\x49\x23\x2a\xbd\xcf\x3d\x1a\x6e\x6f\xca\xb6\x96\xf5\x99\x6f\x9b\xd1\xb9\x48\x5d\x07\x47\x55\xac\x5b\x42\x97\xfe\xe3\x12\x4c\x7c\x03\x97\x6a\x40\xd5\x70\xbe\xae\xc2\xfa\xc9\x92\x33\x9f\x88\x5f\x74\xd4\x0e\xd4\xac\x87\xa4\xf4\x0c\xef\xbc\x48\x64\xf4\x4c\x36\x83\xaa\x8f\x10\x26\xe2\xc3\x7a\xef\xfc\xeb\xfd\xfe\x24\xdd\x0b\x01\x9c\x36\xa7\x98\x88\x20\x30\x04\xb2\xad\x83\xe8\x92\x21\xf3\xf6\x36\xf4\x55\xbb\x64\xe1\x7d\x17\x54\xc7\xc6\xdd\x7f\xc0\x9a\x0d\x65\xdd\xdd\xed\x46\x22\xfc\x4f\x9f\xba\x07\x2b\x45\x10\x34\x35\xe1\x02\x20\xa5\x86\xf1\x52\x26\xd2\xeb\x37\x7f\x40\x64\xd3\xff\x37\xcb\xb4\x70\x5a\x1f\xaa\xf5\xb3\x48\xf8\xc0\xef\x7f\xd1\x56\x4d\x42\x86\x88\xf5\x8f\x33\x92\x96\x7c\xf3\x96\xa8\xff\x2f\xd9\xe7\xb5\x17\xb7\xd6\xa5\xed\xe7\x44\x03\x73\xd8\xcc\x1a\x83\x99\x00\xe8\x4d\x42\x25\x42\x83\xd9\x69\x9c\x7c\xa3\x7e\x47\x76\x92\xa3\x49\x40\x08\xb8\x04\x44\xc5\xcf\x61\x4c\xbb\xc1\x69\xbf\xb9\x29\x63\x03\xc6\x45\xe2\xce\x28\xd1\x68\xdc\x6c\xba\xef\xae\x9c\x73\x19\x1f\x57\x15\x1a\xa4\x73\x00\x9d\x29\xe1\x80\x0b\x10\xf4\xc4\x98\x60\x9b\xa1\x15\x20\x98\x5c\x78\x09\x20\x58\x69\x6f\xdb\xca\x9c\x02\x0e\x2d\xfb\x8a\x04\x3a\x3d\xe8\xe4\x52\xd5\x8c\xd1\xad"}, -{{0xd1,0x52,0x8c,0x14,0x06,0xa6,0xe4,0x94,0xa0,0x2f,0x63,0x53,0x05,0xfa,0x74,0xd7,0x45,0xc6,0x93,0x27,0xfd,0x31,0xb7,0xd2,0xc2,0x62,0x3d,0xe2,0xc0,0x30,0xed,0x85,},{0x0c,0xfe,0x36,0x9c,0xf9,0x3d,0xaf,0x6d,0x53,0xef,0x02,0x8d,0xdb,0x9f,0x00,0x04,0x43,0xb0,0x97,0x2f,0xe2,0x53,0x2f,0x83,0xa4,0x1c,0xe6,0x57,0xc1,0x83,0x6c,0xa3,},{0xb8,0x39,0x9b,0xc3,0x32,0x6c,0xba,0x0a,0x93,0xa4,0x24,0x97,0x16,0x8b,0xf5,0x7f,0x91,0x06,0xee,0x43,0xd3,0x9b,0xf0,0xfc,0x86,0x68,0x51,0x99,0xdc,0x6e,0x0a,0x13,0xb9,0xc7,0x24,0xef,0x17,0xe7,0x88,0x2a,0xf8,0xc2,0xeb,0x70,0xf6,0xc9,0xe4,0x2d,0xfa,0x2f,0xbf,0x0c,0x1c,0xb5,0x00,0x2b,0x58,0xf1,0x08,0x66,0x19,0x73,0x3e,0x02,},"\xab\xb3\x67\x3f\x3f\xa1\x7a\x33\xa7\xaf\xf7\x6e\xac\x54\xe7\x68\x7c\x04\xbc\x84\xf7\x66\x65\x1a\x8b\x24\xba\x22\x94\x79\x08\xb0\x4c\xa4\x59\xfe\xb9\x8a\xce\x7c\xab\x1e\x74\x33\xa6\xa6\xbe\xff\xd8\xd9\x50\x4e\x29\x91\xda\xa0\x64\x4d\x61\xb8\xb2\xe4\x54\x48\xf5\x4d\xf8\x81\x3f\x50\xc4\x18\xb4\x8f\x49\xe1\x03\x4e\x85\x1c\xbe\xc3\xef\x0a\x18\x50\xef\x72\x67\x33\xaf\xaf\x68\xe1\xa4\x61\x04\x16\x51\xc1\x38\xd5\x4e\x4e\xf7\x81\x87\xaf\x9a\x73\x42\xf7\x12\x87\x27\xf9\x03\xbf\x4f\xc5\xef\x3e\x40\xc6\x4e\xc2\x6f\x89\x2f\x59\xad\xd9\x8f\xe3\x94\x76\x5a\xaa\x7d\x09\xca\xe8\x1b\x9f\x69\x9a\x9d\xd8\xbf\x2e\x2f\xe8\xe1\xec\x78\xfc\x88\x4e\xaa\x0d\x2d\xbd\xbf\xb8\xc1\x68\x83\x3e\xe0\xd2\x18\x03\xcc\x35\xdc\x62\x8d\x7c\x07\xe0\x44\x04\xfb\x60\xe8\xc4\x90\xa8\xdd\x34\xed\xbc\xba\xaf\x80\xcc\xda\xe3\xf7\xd3\x73\x9e\x0e\x89\x70\x23\xee\xb5\xb1\xa8\xc0\x0a\x96\x73\xc5\x92\x58\x24\x0d\xdd\x44\x20\x65\x0f\xe5\x77\x1f\x7e\x28\xcb\x23\x99\xf5\xe1\xe0\x2a\xd0\xb6\x43\x2d\x9b\x49\x60\x8f\xcf\x0b\x1c\x0d\x7c\x41\x2a\x44\x52\x55\xb8\xba\xdc\x53\x21\xc2\x4c\x1a\xc9\x2c\x79\xa0\xba\xcc\xb9\xde\xff\xed\x02\xd1\x2f\x55\x36\xcd\x59\x5d\xc6\x60\x83\xb3\x3a\x36\x03\xa9\xd1\x6e\xce\xa2\xbf\x38\xc4\xf2\xaa\xf5\x70\xf3\x0d\x21\x16\x2b\x2e\xfd\x7e\x4d\x5e\xbf\x1e\xca\xe9\x58\x8e\xee\x36\xdd\x9d\x3d\x8e\x3b\xe7\xbc\x6d\x4b\xc2\x18\x56\x22\xf1\x1d\x1d\xa7\xc4\x9c\x93\xe6\x23\xac\x56\xfe\xe7\xe3\x70\x6d\xb8\x31\x3c\xf9\x26\xbe\x92\xe5\xc8\xa5\x39\xfd\x16\xb0\xf4\x38\xda\x8e\x51\xa5\x1f\x2d\x27\x64\x03\x56\x12\x4e\xf7\xbe\x2f\x91\xff\xa1\x79\x6a\x91\xb1\x23\x01\x93\x4d\xde\xf0\xc7\x93\x8a\x7a\x45\xf3\x6f\x53\xb6\x32\x2d\x9c\x8f\x9d\x27\x5e\x1c\xd2\xc0\xf1\x29\xf8\xab\x8d\x74\x15\x5b\x5d\x9e\x5c\x15\xc0\x15\xb0\xb0\x00\x03\xb2\xbd\xdf\xa0\xbc\xfc\xc6\x93\xa1\xdf\xcb\x4f\x53\xda\xec\x12\x6d\x16\x69\xf3\x3f\x39\xad\x05\x51\x9e\xf7\xc5\xce\x40\xe6\xf4\x57\x3c\x24\x7a\x32\xc4\xa0\x16\x28\x31\x35\x2f\x6d\x55\x8f\xf5\x83\x6a\x53\x17\xdb\xc4\x51\x5b\x3d\xf2\x69\xa8\xac\x76\xd6\x43\x6f\x26\x4b\x64\x56\x1e\x79\x68\xb5\x82\x21\x08\x48\x7b\x04\x5c\x92\xd6\xc6\x14\x2a\x1c\x28\x55\xb3\x8b\xee\xbd\x64\x25\x65\x12\x3c\xc8\x27\xcb\x18\x31\x19\x9e\x6f\x12\xa7\xe4\x23\x68\x56\xb9\x4d\xad\x73\x8f\x69\xd1\x10\x6e\x77\x35\xd7\x11\xf7\xc6\xa3\xa3\x37\x80\x41\xfc\x7a\x21\x10\x3b\xbf\x86\x69\x07\xd4\xed\xdd\xaf\xa0\xe7\xf1\xbb\x5f\xfd\x41\xa6\x0d\x64"}, -{{0x51,0x23,0x40,0xf9,0x61,0xf1,0x42,0xd1,0x91,0x5e,0x85,0xfe,0x4f,0xa0,0xf5,0x51,0xf8,0x08,0x92,0xe7,0x5a,0xcc,0xce,0x7c,0xd1,0x86,0x9e,0x6e,0x2c,0x9e,0x80,0x15,},{0x0c,0xa0,0x26,0x04,0xfa,0x87,0xe2,0xc2,0x05,0x06,0x25,0x1f,0x07,0x92,0xcd,0x21,0x25,0x85,0x6f,0x0a,0xb1,0x6d,0x66,0x3f,0x28,0x11,0x96,0x3b,0x1f,0x2d,0x81,0x72,},{0x6b,0xb4,0xd9,0x75,0xaf,0xae,0xf4,0x1e,0xa9,0xef,0x08,0x5a,0x68,0xc5,0x68,0xa0,0x5d,0xa3,0x7e,0xf2,0x1d,0xad,0x46,0x4e,0xd8,0x6a,0xc0,0xd4,0x08,0x0e,0x7d,0x01,0x29,0xfb,0x02,0x31,0x31,0xec,0xa5,0xf7,0xad,0xb2,0x58,0x6a,0x18,0xbe,0x40,0x56,0x2f,0xa2,0x76,0x4c,0xa8,0x07,0xe6,0x70,0xa0,0x59,0x6a,0x5c,0x54,0x7b,0xc0,0x01,},"\xaf\x37\xb2\xc7\x58\x7a\x8d\x5b\xc8\x95\xcd\x35\x77\x46\xab\x03\x55\x2a\x0a\x56\x1a\x29\x3d\xc7\x16\x4e\x39\xb6\xa1\x33\x3a\x92\x0b\xb6\xda\xca\x60\x06\x67\x6e\x99\xbb\x7e\x92\x8f\x9e\xa3\x91\xe5\x48\x02\xa8\xd3\x15\x96\x28\x9f\xb9\xbf\xe3\x00\x00\xcf\x52\xeb\xf0\xc1\x24\xa5\x89\x5b\xce\x33\x98\xc1\xbf\x53\x56\xbe\x82\x61\x9b\x8d\xdc\x15\xa7\x7c\xa9\x22\x49\x4b\xdb\x04\xf5\xc2\xe1\xb6\xe8\xff\x77\xae\x74\x9f\xaf\x2b\x8a\x41\xd8\x22\xc1\x7c\x06\xdf\xb7\xa5\xf9\x43\x4d\x8b\xd7\x15\xec\x87\x78\xe8\x0b\x81\xd2\xe8\xd0\x62\x98\x74\x86\x90\xc6\x55\x52\x83\xc9\x8b\xb9\xb1\x9b\x92\x46\x66\x7b\xc4\x10\x46\xff\x98\xc2\xc3\x5d\x16\x1e\x1f\x4d\x69\xd2\x54\xec\x5a\x07\x6f\x25\xbd\x5c\x7e\x2c\x98\xca\x3c\x09\xd8\x08\x33\x96\x2c\xf9\x66\x02\x87\x88\x40\x96\xeb\x30\xc4\x6c\x54\x17\x41\x06\xaf\x4e\x29\x79\xa1\x12\xf3\xe8\x94\x4e\xaa\xf7\x66\x9c\x40\xd5\xaf\xb9\x1a\x02\x4a\xbb\xeb\x14\x66\x4e\x30\x89\x03\xe4\xd2\x6d\x70\x09\x44\x6e\xe2\xe8\x30\xab\x5e\xca\x0d\xbb\xc5\x13\xfb\x4e\x04\x35\x1d\xf2\xf6\x74\x18\x64\xfb\x23\x71\xb2\x50\x2b\xe4\x3d\xc1\x5f\xc0\x44\x31\xff\xf5\xeb\x8d\x4b\x68\xd7\x24\x62\xae\x32\x2e\x57\xba\x2d\x4a\xdd\xdf\x15\xa1\x90\x2c\x21\x13\xae\xbd\x3b\x5d\x61\x29\x17\xc1\xbb\x73\xe7\x08\xad\x54\x18\xe7\xd4\x5e\x4b\x72\x80\xfc\x88\x96\xab\x80\x85\x3f\xf5\xf8\xe9\x8f\x26\x55\x3f\xc7\x8e\x30\xb3\xb0\xd7\x27\xbf\x6d\x06\x4a\x8f\x32\x88\x87\x68\xc5\x1e\xbb\x61\xb2\xc6\x00\xb4\x02\x8a\x77\x06\x0f\xeb\xbb\x02\xeb\x3d\x20\x17\x80\xe7\x45\x66\xc8\x6a\x34\x03\x18\x36\xbc\xe9\xea\xda\x81\xe5\xd0\xf3\x39\x60\xcb\x2d\xf0\x8a\xff\x3c\x97\x49\x21\xfc\x9b\x7d\x3a\xa7\xc8\x1e\x9c\x67\x1e\xd6\xd3\x3e\x7a\xe5\xed\x03\xa5\x41\x7d\x7e\x5c\xd6\xfa\xac\x91\xb5\x4b\x8f\x79\x2f\x48\x28\x3c\x60\x64\x7d\xe3\xda\x81\x6c\xa9\x75\x6c\x5b\xfe\x1b\xb8\xb5\x97\x9e\x57\x54\x01\xbd\xa3\x4e\x9c\xbc\x4d\x77\xe7\x11\xd6\xb7\x3b\x82\xda\x19\xda\x47\x3b\x55\xe8\xe7\x2d\x34\x1b\x2d\x85\x03\xe4\x86\x09\xbe\x0f\xe2\x91\x44\x4c\x28\x36\x69\xe5\xde\xad\xea\xf5\x2a\xa8\xec\x48\xda\x83\xf5\x32\x8c\xc0\x99\xfb\x41\xf8\x2b\xec\xdd\x58\xd0\x4b\x1d\x66\x20\x3d\x73\x7b\xed\x06\xcf\x21\xc9\x78\x19\xac\x13\xed\x71\x1c\xa2\x17\xa5\x7c\xf7\xd8\x0f\xf0\x82\xaa\x1a\x1c\xf8\xfe\xa5\x55\xcd\x2e\x47\xe4\xdd\xab\x5e\x3f\x99\x41\xad\x4f\x77\x5f\x49\x41\x9d\xca\xdb\x5b\x00\x4b\x68\xca\xf4\x5b\x27\xef\x49\xba\x14\xfb\x52\xb0\x9f\x1b\x18\x5b\xe9\xf9\xc7"}, -{{0xb1,0xb6,0x36,0xe9,0x57,0x57,0x4c,0x21,0xa9,0x57,0xa4,0x5b,0xd1,0x95,0xc6,0xf9,0xfe,0x4c,0xc1,0xc5,0x7e,0x84,0x13,0x4d,0x39,0xb4,0x2e,0x1a,0x84,0x32,0x9e,0xdb,},{0x95,0xe7,0x7b,0x15,0xdd,0xa4,0x7c,0xaf,0x69,0xb7,0x28,0x88,0xdd,0x69,0x96,0x1b,0xac,0xbe,0xc3,0xbc,0x75,0x35,0x30,0x03,0xe8,0xbf,0xf0,0xa4,0x3d,0xdf,0x4b,0x7a,},{0x76,0x3c,0x7d,0x0d,0x46,0x87,0x8e,0x5c,0x7e,0xcf,0x71,0x04,0xfc,0x1f,0x22,0x30,0xe4,0x61,0x78,0xa2,0x7c,0x75,0xf1,0x96,0x16,0x9c,0x02,0x79,0xed,0xb0,0x1c,0x28,0xfc,0xde,0x3b,0x0d,0x5b,0x86,0x35,0xcf,0xe3,0x39,0xfb,0x23,0x27,0x74,0xb2,0x20,0x6d,0xab,0x8a,0x46,0x0c,0xe4,0x17,0xab,0xf4,0x90,0xbb,0xfa,0x78,0x5c,0x02,0x05,},"\xe2\x5d\x32\x9c\xad\x83\x64\xd2\xde\xc2\x43\x73\xe9\x2d\x9d\x50\xfc\x7a\xbe\x8f\xdc\x3d\x0b\x4e\xe5\x7e\x1c\xfa\x5b\x7c\xd5\x8c\x23\xbe\x91\x8f\x05\x17\x9b\xa8\x41\xb6\x1e\x18\x00\x34\xca\x7e\x74\xd4\x9b\x0a\x1a\x2c\xeb\xb4\xbe\x65\x34\x4c\x91\x3c\x46\xd3\x26\x52\x33\x6e\x6b\xda\x4e\xfa\x3f\x58\x73\x0d\x39\xa6\x33\xa1\x4c\xa3\xd9\xa6\x2a\xbb\x0a\x73\x98\xcc\x29\xaf\xf9\x16\xee\xea\x2e\x7c\xaa\xc8\x08\x45\x56\x2f\x73\xd4\x03\x0f\x9c\xab\x0b\xf1\xc6\x40\x7f\x54\x01\x51\x3e\xf8\x7f\xe6\xdc\x09\x9d\xbc\x5d\xfc\x33\x52\x91\x1c\x07\xaf\x6c\x52\x3b\xef\x4c\xca\x78\x37\x96\x59\xe8\x80\x3f\x58\x59\x04\xee\x6e\xf6\xfd\xe7\x73\x66\xd9\x6d\x2c\xcf\x24\x8a\x53\x20\xd9\xb8\x29\x8b\x2a\x73\x36\x38\x79\x10\x7a\x02\xb4\x7f\x57\x21\x3a\x85\x20\x3a\xbb\xca\x5a\x41\x95\xf8\xaf\x3e\x35\x93\xed\x2f\xa3\x50\x4b\xb7\x6a\x3e\x1b\xe2\x4b\x66\xd3\x55\x66\x29\x32\xcb\x67\xdc\x88\x50\x3a\xfa\xf7\x62\xbf\xf7\x41\xba\x1c\xac\xe9\x7a\xc5\x8b\xaf\xad\x5d\x36\xc3\xaa\x02\xe0\xcb\xe2\x0e\x5f\x3d\xc8\x09\x2c\x51\x2e\xaa\x9c\x49\x43\x47\x4a\xad\x41\x99\x00\x76\x72\x1a\xd3\xf5\x3f\xb0\x8a\xc2\x29\x82\xed\x9b\x15\xc7\x51\xa9\xe2\x33\x82\xf6\xa6\x9c\x72\xe6\xe2\x44\xe0\xeb\x68\x1e\x6d\xd2\x28\xd3\x77\x4f\xcc\xb3\x7e\xb6\x23\x2f\x82\x5d\x16\x9a\x2a\xc8\xb7\xe1\x8a\x42\xcd\xaa\x4f\x2c\xf0\x58\x90\xbb\x0c\x59\x8c\xf8\xc3\x1f\x82\x9e\xf8\xca\x24\x35\xbd\xcc\xeb\x0e\x61\x93\xad\xa7\x84\x1e\xe6\x92\xf3\x0a\xed\xf8\x8b\x62\x73\x11\xb1\x38\xac\x78\xb3\x91\x3e\x06\xf7\xc3\x21\xca\xfb\x39\xd9\x01\xdf\xe1\x74\x30\xb1\xa2\x0b\xc4\x37\xa5\x55\xa5\x78\xfa\x31\xe4\xb6\x80\x79\x54\x45\x6b\xd4\xb0\x4d\x5d\x88\x79\x87\xbd\xf0\x4e\x0f\x14\xaf\x31\x41\xb2\x4c\x3a\x7b\x9a\xc7\x5a\xa3\x2e\x2f\xcd\x21\x71\xa1\x26\x09\xe1\x5e\x73\x09\x4f\xd0\x92\x21\xb4\xd2\x70\x90\xe7\x32\x19\xb6\x48\xbc\xaa\xbf\x38\x07\xc9\x28\x0b\x6c\x4a\xd7\x50\xa4\x68\xbe\x0e\x1a\xd3\xe6\xe6\x30\x16\xcb\x5c\xec\x3a\xad\xdc\x56\x89\xc2\x95\x5a\x2a\x8d\x5b\x89\x84\xd7\xc4\x43\x76\xfd\xd9\x4d\x3f\x5f\xf1\x29\x8f\x78\x17\x2b\x56\x59\x13\x70\x4e\x90\xe5\xac\x03\x8c\xb1\x72\x0e\x19\xb0\x80\xf8\x1b\x53\xd6\xa4\x5d\x45\x28\x53\x07\x11\xb6\x3d\xfe\x1e\x47\x81\xc2\x4d\x74\xae\xb2\xbd\x8a\x73\xfd\x2a\x99\x3c\x5b\x08\x91\x39\x21\x96\xac\x32\xc5\x23\x69\x99\x60\xd8\xb2\x3e\x01\x66\x4c\xf9\x02\x1d\x93\x92\x80\x50\xca\xf9\x7f\xb9\x85\x55\x45\x80\xe3\x33\x36\xa4\x56\x32\x47\xdf\x59\xef\x6c\xae\x53"}, -{{0x10,0xca,0x41,0x3d,0x70,0xeb,0x3d,0xb6,0xe3,0x37,0xf0,0xf1,0x1a,0xbc,0x07,0x5c,0x95,0x85,0x9e,0x82,0x5f,0x87,0x61,0x76,0x07,0x69,0x52,0xd2,0xf1,0x88,0x80,0x30,},{0x50,0x28,0xba,0x38,0xaf,0xec,0xc2,0x42,0x63,0x5f,0x6e,0x35,0x3d,0x5f,0x4a,0xfd,0x12,0x3f,0x86,0x0a,0x04,0x25,0x22,0x0e,0x96,0x65,0x52,0xa0,0x57,0x88,0x08,0x23,},{0x6a,0xec,0x02,0xdc,0x6b,0xdf,0xcb,0x67,0xf0,0xef,0xc1,0xfd,0x31,0xe2,0x3e,0x69,0xe3,0x71,0xab,0x38,0x02,0x50,0x5b,0x32,0x01,0xa9,0x5d,0xd5,0x25,0x41,0x7e,0xd1,0xa1,0x28,0xdb,0x4e,0x18,0x2c,0xb3,0x7c,0x28,0xf6,0x28,0x06,0x66,0x70,0x99,0xa8,0xad,0x48,0x0b,0x0a,0xc9,0xe9,0x4c,0x2a,0x7d,0x5a,0x0e,0x96,0xe2,0xa7,0x36,0x0d,},"\xea\x7f\xaf\x79\xf6\xff\x5d\x78\xa8\x23\xa7\x54\x34\x71\x34\xf1\xb3\xc3\xe9\x1c\xe5\x18\xfd\xd6\x33\xfe\xb4\xf0\x5d\x12\x5f\x05\xcb\x54\x33\x6e\xf5\x60\xe9\x2d\xeb\x68\x51\x12\xa5\xff\xcd\x3d\xfd\x39\x64\xb2\x75\x8c\xe4\x78\x5f\x6a\x34\xbf\xeb\x39\x78\x4f\x0a\xee\x55\x95\x5a\xeb\xd1\x2d\xdd\xa6\x41\xd0\x57\x69\xf7\x44\x02\xf7\x06\xda\xd2\x01\xc4\x4c\x91\x08\x1c\x7d\x7f\x65\xe7\xaa\x42\x46\xde\x6d\xc3\xed\x64\x96\xd1\x0f\x4a\x41\x20\x60\xd4\x93\xba\xc9\xae\xd5\xbe\x4f\x6d\x74\x22\x9e\x3c\x55\xeb\x68\x76\xe3\xbb\x2e\xd4\x1f\xa4\x50\x4b\x66\x70\xdd\xa8\xc7\x98\xf6\xda\xa2\x80\xd1\xaa\x72\x02\x11\x74\xf6\xc0\x1a\xec\x49\xb3\x21\xd8\x7f\x53\xac\xbc\xad\xcc\x46\x07\xd5\xb1\xe4\x5d\x63\xfc\x48\x1a\x6d\x90\x57\x6c\x87\xc1\x88\x0b\x2e\x8f\xf3\xe5\x90\xa9\x6b\xee\xe1\x80\x47\x68\xc7\x56\xbe\xb8\x6b\xf1\xde\x8a\xdc\x40\x8b\x1b\x8d\x66\x6f\x74\xba\x28\x63\x08\x22\xf9\x2d\x18\xb0\x56\xae\x37\xce\x02\x93\xee\x61\xb9\xe8\x0f\x33\xac\x26\x96\x71\xbd\x62\xa4\x05\x9b\x24\xf7\xc1\xa4\x40\x80\x74\x40\xd5\xd5\x38\xa6\x54\x58\xad\xc8\x15\x87\x24\xb2\x5c\x12\x12\x7a\xa0\x34\x9e\x55\xf6\xe5\x5b\xc9\x20\x78\xfd\x1e\xf2\x74\xc2\xaa\x79\x19\x05\x76\x6b\xe3\x94\xa2\x62\x8f\x7b\xbd\x1a\x32\xda\x5e\x48\x74\x46\xbb\xef\xae\x88\xfa\x6c\xf3\xf7\xb4\x99\xf1\x31\xfa\x19\x31\x3d\x13\xb2\x80\xad\xca\x50\xf7\x78\x02\xd1\x73\x31\xb3\x81\x68\x3b\x5e\x7e\xda\xb9\x94\x73\xed\xd3\x1d\x77\x44\x34\x88\x21\x41\x35\xfd\x6f\x26\x44\x50\x93\xe9\xe2\xaf\xf7\xd7\xe8\x92\x33\x7f\xdc\x87\x79\x06\x5d\x4d\x97\xd6\xd6\x73\x57\x67\x94\x95\x8d\xbf\xa6\xc5\x0b\x1b\x13\xac\x39\x60\x7c\x1e\x66\xef\x96\x29\x76\x10\x71\x15\x5f\xbc\xa6\xf3\x6e\xb0\x2c\xee\xae\x16\x36\x7f\xea\xc0\x74\x76\x90\x8c\x84\x7c\x9a\x53\x3e\xf6\x8c\x94\x31\x1f\xa0\x89\xff\x28\xfb\xd8\x78\x09\xb0\xd3\x87\x6b\x43\x1d\x9a\x18\xb2\x02\xf9\xa4\x04\x9a\x05\x77\xb8\x17\x76\x10\xdd\x02\xe5\xc5\x20\xec\xa9\x55\xe8\x03\xc3\xad\x4f\x50\x97\x6f\x7c\x2e\xa8\xaa\x3e\xe4\x83\x6a\x19\x85\xdf\x0a\x4f\x16\xef\x46\x98\x15\x95\x41\x98\x97\x99\x35\x60\xaf\x82\x65\x1c\x2b\x49\x4e\x68\x0b\x37\x80\x2e\x75\x37\xef\x68\xa5\x75\xc3\x4f\x85\x88\x06\x3e\xe0\x19\x72\x06\xd9\xa3\x2b\xb4\x89\x0e\x7c\x21\x6a\x4d\x33\xfe\xca\x36\xb5\x49\xe5\x32\xfe\xa6\x85\x56\xe7\x54\x0a\x4f\xb1\x69\xd4\x9f\xc5\x53\xb2\xe6\x70\x0a\xe4\x2d\x9a\x51\x6e\x68\x16\x0a\xcf\x6b\x27\x0c\x77\xca\x5e\xc2\x6e\x5a\xd5\xdc\x75\xc2\xc3\x93\xe2\x99"}, -{{0x1f,0x0a,0x10,0xa2,0xcb,0x11,0x19,0x17,0xb9,0xa6,0x7a,0x2a,0x1f,0x38,0xfb,0x86,0xf8,0xed,0x52,0x60,0x7d,0x1d,0x65,0x3a,0x45,0x7d,0x7f,0x47,0x18,0xd9,0xa7,0xde,},{0x70,0xc0,0x75,0xb2,0xe9,0x4c,0x4c,0x02,0xf4,0x5e,0x73,0x04,0x4f,0x24,0x39,0x97,0x41,0xb1,0x61,0xfe,0xb6,0xf6,0x9e,0xab,0x63,0x54,0x17,0x28,0x2a,0x4a,0x93,0x68,},{0xa4,0x24,0x5a,0xa3,0x39,0x5e,0x7b,0xad,0xa2,0xbc,0xdf,0x16,0x03,0x14,0x7c,0xc5,0xf3,0xf0,0xba,0x91,0xf4,0x0f,0xda,0xd8,0xf6,0xd3,0x71,0xc3,0xeb,0xef,0xb4,0xc1,0x50,0x1d,0x07,0x87,0x5b,0x57,0x6f,0x40,0x79,0x78,0x06,0xa4,0x84,0xc7,0xa3,0xf7,0x05,0x69,0xe2,0x32,0xb0,0xc9,0x9d,0x29,0xca,0x23,0xa2,0x33,0xb6,0x8e,0xdb,0x0c,},"\x4f\x6a\x43\x4b\xd5\xfc\x77\xf0\xf1\xb7\x04\x9c\x91\x85\x3c\xcb\xd8\x94\x39\x96\x2a\x60\x78\xa6\x74\xb8\x67\x54\x3b\x6b\x7d\x10\x55\x2e\xc1\x75\x8c\x52\x83\x04\x2b\xd6\xb4\xce\xa8\x8c\x95\x20\xdb\x04\x74\x6f\x08\x9c\xf3\xa2\x60\xfb\x0f\x33\x85\x8e\xfd\x6f\x68\x0d\xe5\xb7\x2d\x98\x76\x32\x4b\xa5\x90\x29\x91\x38\xf8\x5a\x76\xf5\xbe\x0e\x05\xe8\x85\x9c\x02\xb2\x35\x12\x55\x9c\x8b\xea\xfc\x9c\xfe\x90\x1b\x28\x3e\x15\xd1\x6c\x79\x2e\xb0\x3b\x92\x88\x0f\x6f\xf9\x7a\xa3\x8e\xee\xad\x3f\x4f\xd6\xc0\xa9\x21\x43\x23\xaa\x39\xa1\xc1\x65\x15\xe3\x0d\xbd\x08\xb8\x33\xee\x40\xa8\x14\xa2\x88\x09\xc8\x70\xe1\xd0\xa6\x2c\x37\x93\x2d\x54\x08\xfc\x6a\xfc\x63\xe7\x9a\x65\x5c\x5f\xe3\xd4\x02\x6e\xf0\x9e\x02\x99\xfb\xde\x5a\xb3\x4f\xce\xab\x14\x13\x0d\xc4\xbe\x00\x7e\x8e\x64\x44\xd7\xaa\xae\xc6\x2c\x87\x3d\xf7\x7e\x80\x10\x74\x3c\x31\xe8\x75\x7f\x1e\xae\x9e\xdb\x55\x97\xa1\xb5\xd8\x4b\xd7\x7a\xe7\x64\x2e\x1a\xca\x99\x87\x3a\x15\x2f\xfd\xe0\x68\xa8\xe4\xad\x92\x40\xb9\x03\x33\x27\x95\xe4\x0b\xb3\x28\x65\xe5\xce\x03\x43\x07\xa6\xc9\xfe\x33\x9a\x1c\x93\x77\x0d\xf5\xca\x46\x32\x9f\x6b\x09\x41\x97\x85\xcb\xf2\x84\x7b\x0c\x68\x32\x83\x71\x23\x85\x3a\xd9\x52\x65\x32\x65\xc5\xb5\x74\x0d\x19\x4e\x00\xf2\x3f\x9e\x96\x67\x91\xf0\x05\xf8\xbf\x55\xc3\x88\xc2\xbe\x9e\x21\x53\x89\x25\xf8\x55\x5e\x0d\xbd\x83\xbe\x07\x3d\xf7\x65\xaf\x49\x40\xe5\x9a\x37\x90\xb9\x83\x6b\xab\x79\x09\xe5\x67\x6f\xbf\x1c\x21\x26\xfe\x22\x6d\x78\x1a\x44\x33\x0c\xc0\x1d\x32\x83\x0f\xf8\xae\x00\xb9\x79\x2e\x39\x8c\x2c\xbb\x4f\xb8\x3a\x10\x05\xc2\x45\x54\x9a\x89\x06\x3f\xbe\x06\xc6\x2a\x48\xda\xc4\x3c\x51\x01\x24\x99\x94\xe9\x5e\x37\xf2\x4c\x1d\x8b\x3b\xc6\x73\x53\x8c\x46\x05\x5f\x80\x0d\xb1\xc0\xf9\x56\x86\x9b\x6b\x29\x7d\x99\x0f\x44\xf0\x5b\x50\xc7\xad\x6b\x85\x6f\x46\x21\x28\x58\x47\x1d\xd0\xd3\x93\x72\xb0\xdb\x75\x15\x73\xdd\xb6\xb5\xb5\x6b\xa0\x1e\x37\x1c\x78\xfe\x58\xdc\xd1\xbe\x53\x11\x2a\x6a\x73\xda\x9a\x6b\xac\x75\xd3\xc3\x9a\x1a\x70\x5a\x36\xf6\x40\xfc\xfa\xd8\xcd\x04\x07\x75\x94\xd5\x96\x85\xf6\xe3\x0d\xe7\x1d\xfd\x4a\x44\xc4\xe7\xc0\x4d\x6e\xc7\xc2\xe8\xbe\x12\x78\x5b\xb0\x5b\x29\xb3\x91\x51\xd3\x29\xf5\x87\xfd\xc3\x81\xc2\xdf\x0c\xef\x73\xfe\x0e\x3f\xd9\x20\x8d\x7c\xcb\x6e\x08\xd0\x2f\x42\xd1\xfe\xed\x27\x56\x1d\x5e\x32\x3a\xa1\x48\x62\x4e\x55\x2a\xbe\x87\x53\x2d\xe1\x5b\x7f\x42\xc2\x2c\x98\xe4\x05\x25\xb1\x74\x7c\xbd\x75\x8b\xfb\x26\xfd\x3e\xed\x3b"}, -{{0x7f,0x05,0xba,0xac,0xf1,0x67,0x58,0x3c,0xf2,0xfe,0x95,0x62,0xa5,0x06,0x99,0x1e,0xd9,0x87,0xf6,0x8f,0xfb,0x71,0x56,0x7c,0x7c,0xcc,0xe3,0xfc,0xc5,0x9b,0x78,0xb0,},{0x0d,0xec,0x39,0x52,0x85,0x2b,0x96,0xfd,0x75,0x58,0x7e,0x97,0x74,0x3f,0x9e,0x41,0xc0,0x9f,0xbe,0x6b,0xa9,0x81,0xbf,0xce,0xb4,0xeb,0xb8,0x89,0x2d,0x98,0x6a,0x16,},{0x0d,0xee,0xd2,0xdf,0x82,0xac,0xf4,0x52,0x9c,0x40,0x8a,0x02,0x93,0x1f,0x67,0x6b,0xec,0x5c,0xb7,0xad,0xe8,0x4e,0xbd,0xcd,0x57,0x8f,0x70,0xf9,0x71,0x38,0x2c,0xf3,0x11,0xbb,0x83,0x09,0x73,0x00,0x45,0x6a,0x55,0x8b,0xc4,0xc0,0x9d,0x89,0x83,0xff,0x13,0x49,0x3f,0xd6,0x11,0xeb,0x66,0xc0,0x43,0xbf,0x01,0x9b,0xad,0x6f,0x33,0x02,},"\xa2\x7d\x1e\xab\x05\x15\x09\x20\xde\xd1\xb1\xc2\x57\x8a\xf5\x82\xb2\x94\xf7\x83\x7f\xe4\xfb\x1a\x31\x69\xc2\x5e\xfb\x70\x63\x4b\xa6\x6c\x7e\x29\x91\xb3\xe7\x5c\xc5\x12\x48\x26\xa0\x3e\x05\x72\x59\xb5\xcb\x70\x62\x28\x78\x0c\xbc\x82\x75\xc3\x39\xf8\x34\x0e\x40\x2a\x66\x50\x32\xa4\xab\x65\x78\x27\xb1\xc3\x48\x1f\x75\x66\xd3\x69\x73\x5b\x82\xdb\x76\x28\xc0\x22\xb2\x12\x73\x0d\xb1\xe4\x7c\x9b\x2d\x9b\xc4\xd8\x1b\x23\x42\xd8\x9c\x6e\xaf\xc3\xe0\xb6\xde\x50\xd4\x84\xcc\xef\x11\x23\x8c\x8e\x2d\x24\x0d\xd5\x95\xdc\xef\x8b\x2f\xc5\x7b\x54\xff\x9a\x8a\x74\x11\x1f\x61\xf8\xa6\x52\xf2\x0e\xa0\x12\xc1\xad\xe3\xe2\x80\xec\xde\x29\x4c\x0e\x35\x71\x71\x90\x16\x2e\xc6\xa2\x26\x5e\x7e\x6f\x3f\x07\x04\xcf\x8a\xb1\xa0\x3e\x5c\xc9\x53\xe2\x92\x62\x91\xcc\xd4\xb0\x59\x0d\x5c\x20\x56\x8f\x94\xf9\xff\x0f\xe2\xab\x78\xcf\x9a\xe2\xc3\x8b\xcd\x49\x1e\x51\x8f\x23\xe9\xb6\x36\xf8\x80\x61\x5f\xc5\x60\x78\xe5\x12\xd7\x57\x7e\x09\x49\x7c\x11\x83\x45\x3d\x50\x81\xfd\x47\x37\xf2\x80\xec\x5e\x26\x7c\x45\x86\xb7\x8b\x70\xff\xfd\xfd\x73\x0d\x80\x9d\xf5\x60\xf2\xe3\x77\x21\x91\x84\x7b\xbc\x3f\x60\x4f\xb7\xf8\xca\x49\xee\xd3\x18\xb5\xe7\xd1\xf2\xb8\x3a\x10\xda\x0c\x85\x94\xb3\x39\xb6\x87\x1a\x57\x72\xdd\x64\x16\x8e\xcc\x27\xe2\x40\xa4\x5c\x76\x72\x5e\x7d\x55\xbe\xf3\x7e\x13\x5e\x3d\x9e\x0e\x34\xe3\x6c\x16\xe3\x4d\x77\x45\x9a\x55\x2f\x40\x74\xd0\x67\xa3\x1a\x3e\xd2\xa4\x8c\xde\xa4\x89\x5b\x10\xbd\xf1\x65\x6f\x4b\x7a\x41\x3c\x6a\x08\x8c\x64\x9f\xc9\xd7\xbc\x56\xab\xf6\x44\x35\x49\x12\x14\x19\x2a\x66\x70\xcb\x8b\x9c\x91\x7f\x8e\x1b\xc7\xb2\xcf\xce\x78\xd2\x8f\xbc\x3a\xfc\x2a\x50\xe9\x82\x13\xe7\xe0\x26\x37\x8e\x4e\xa7\x11\xd1\x51\xad\xaa\xa7\x19\xbe\xb8\x97\x46\x56\xc1\x0e\xbc\x7d\xe4\x6b\x19\xec\x82\x95\x1e\xf4\x6a\x8c\x68\xe7\xf4\x36\xe1\xb3\xeb\xed\xb2\xd0\x9b\x05\x75\xc9\x91\x4e\xad\x27\x96\xb5\x3e\x00\x61\xe2\x12\x99\x4a\xc5\x02\x6a\xea\x81\xec\x37\xc8\x13\x78\xf4\xcc\xfc\x46\x77\x00\x08\x79\x68\x59\x7d\xa3\x8f\xed\x52\xfa\x48\x09\x3a\xe4\xba\x10\x66\xc3\x1e\x3c\x7d\x85\x08\x09\x5b\xb4\x5c\x28\x01\x20\xf4\xaa\x69\xa2\x4f\x3e\xfe\xf1\xf7\x67\x98\x5a\xa1\xa3\x0e\x14\x08\x56\xf7\x6d\x15\x20\x73\x28\x78\x48\x7b\xe5\x3f\x71\x2d\xbd\x7d\x77\x9e\x31\x51\x01\x58\x8f\xd7\xdb\xdb\x13\x2f\x92\xc2\x75\x75\xac\x14\x86\xf1\x76\xc7\x90\x66\x1b\x01\x48\x39\x4e\x92\xff\xa3\xae\x6f\x8a\xfb\x2f\xaa\x2b\x7f\x4f\xbd\x0a\xd9\x1e\x75\x9a\x70\x2b\x3c\x70\x2b\x4d"}, -{{0xd0,0x0c,0x21,0x64,0x26,0x71,0x0d,0x19,0x4a,0x3d,0x11,0xcf,0xc9,0x0a,0x17,0xa8,0x62,0x12,0xe7,0xa0,0xe5,0x4b,0xaa,0x49,0xb0,0x16,0x9e,0x57,0xff,0xf8,0x3d,0x61,},{0xcf,0xe6,0xae,0x89,0x03,0xc6,0xc7,0x01,0xaa,0x30,0x46,0x95,0xc6,0x51,0xbf,0xd8,0x50,0x33,0x1f,0x9a,0xd4,0x81,0x63,0x3a,0xe3,0x70,0xc8,0x6d,0x7b,0xd1,0x3f,0xb9,},{0x15,0xc4,0x5c,0x19,0x42,0x97,0xe8,0x87,0x02,0x9f,0x49,0xd8,0xbd,0xf9,0xd6,0x10,0xdd,0x8c,0x34,0x79,0x9e,0x1e,0x92,0x30,0x26,0x9e,0x7a,0x58,0x92,0x89,0x38,0xcf,0x39,0x6a,0x02,0xcd,0x42,0x20,0x54,0x90,0x39,0x1e,0x1c,0x64,0x35,0x3f,0xb0,0x6b,0x9f,0x8e,0x9b,0x81,0x8a,0x9a,0x36,0x1c,0x20,0x4a,0x38,0x69,0x95,0xbf,0x3b,0x03,},"\x82\xf9\x78\x41\xb3\xba\x22\xdd\x9a\x44\x50\x83\x7e\xa7\xbf\x8d\x27\xa9\x73\x14\x70\xca\xbb\x0c\x20\x78\x03\x4b\xf2\x4e\x4c\x1a\x62\x90\xc0\x3f\x40\x02\xb8\x6f\xa0\x9f\x07\xb5\x20\x9f\x1f\x53\xd0\xec\xf4\xd9\xe9\x22\x3b\xec\x12\x5a\x95\x45\x51\xfe\x8b\xff\x71\x8f\x5e\x26\x48\x68\xe2\x07\xf7\x01\x19\x4e\x41\xde\x39\x97\x1f\xd3\x85\xf4\x9a\x4b\x4a\xdd\xa9\x11\xeb\xa5\x52\x59\xfc\x68\x36\x65\x32\x73\xf6\x56\xf4\xaf\x60\xb2\x06\x64\x95\x6d\x4f\x21\x35\xd9\x0d\x09\xe9\x03\x7d\x53\x66\xa0\x25\x34\x44\xe0\x22\xc7\x21\x2a\xf5\xfd\x4f\xcc\xd7\x42\x37\xd2\x88\x53\x38\xe2\xfd\x72\x15\x22\xde\x67\x63\xc2\x54\x90\x28\xc6\x23\xb9\xcf\x38\x7d\x23\x4a\xb5\xe7\xfc\xbe\x5a\x47\xc6\x85\xb7\x9e\x75\xa5\x7b\x09\x57\x40\x82\xa0\x22\x21\xdf\x64\xa2\xe8\x41\x61\x80\x87\xe7\x22\xa2\x1b\xac\x1b\xa4\xf0\xd7\xd8\x7b\xdc\x51\x0a\xaa\x8f\xbd\x10\x75\x7f\x6c\x02\x9c\xa8\x20\x37\x1f\xc7\x4c\x3b\xc5\x0b\xd8\x98\xc5\x5d\x81\x67\xf7\x3a\xda\x37\x7a\xec\xc9\x16\x29\xd6\x4c\x36\x0c\x2c\x24\x1c\x5c\xb4\x2e\x3a\x51\x8c\x5d\xab\xf0\xf4\x18\xb2\xa7\xf3\xd8\x2e\xef\xd9\x20\x26\xd3\x1e\x8b\x81\x60\x35\x8e\xae\x82\x1f\x73\x0e\xca\xfe\x7a\xce\x64\x7b\xff\x87\x41\xde\x2f\x6a\x13\x1d\x11\xc9\x69\xe9\x78\x7c\xfe\x6a\x2f\xab\x37\xbf\x8d\x1c\x7f\x4a\x2f\x36\x4d\x2f\x1a\x76\xef\x04\x6c\x18\x43\xe6\x3e\xc0\x0c\xf7\x92\x0f\xfa\xae\x56\x1e\x73\x70\xb7\x19\xfc\x16\xfc\xeb\xca\x3c\xfd\xfa\xba\x43\xf4\xf0\x90\xc4\x6f\x47\x73\x03\xa6\x60\xee\x88\xdd\x4e\x89\xbf\x14\xb9\xf8\x04\xb6\xfd\x49\x5c\xb1\x41\x27\x53\x47\x4a\x05\x6a\x0d\x89\x31\xcd\x9c\xcb\xd6\x4f\x8f\xcc\x7a\x31\x23\x46\x7c\x5d\x47\xf6\x90\x67\x9e\x88\x71\x28\x80\x93\x73\x4f\xd6\xa1\x32\x60\x38\x65\x81\x56\x41\x36\x96\x59\x4c\x13\x4d\x73\x88\x7f\x34\xee\x67\x60\x9a\xe8\xff\xb3\x26\x6c\x16\xd8\x7f\x15\x34\x5a\x47\x6f\x72\x95\x0c\x15\x87\x96\xa8\x8b\xbb\x44\x4f\x1a\xa8\x09\xca\xd8\x75\xb8\x5f\xb9\x15\x1a\x0e\x2e\xef\x2e\x00\xe8\x0d\x6b\x7a\x9b\xa4\x06\xc0\x51\x9e\xff\xdd\x94\x12\x62\x32\xfd\xf6\xf1\xe7\xb9\xbb\xc0\x36\x2a\xa7\x75\x16\xfd\xf9\x39\xe7\x90\x6a\xab\x01\x30\x71\x28\xcf\x82\x4c\x10\x2c\x09\xb9\x29\xc9\xb2\xd7\xaf\x8f\x85\xb7\xd7\xf9\xa8\x38\xb2\xae\xd0\xc6\x97\xe8\xbd\xfe\xe6\x6e\xe0\x16\xbb\x1b\xf3\x5e\xff\x6b\x2f\x7e\xf4\xb9\x1b\x1f\xc0\x4f\xac\x9f\x11\x6e\x2e\xdf\xf4\x0f\x95\xc1\x5b\x77\xc3\x1e\xe5\x22\xf3\x93\x7c\x7f\xa0\x04\x7d\x62\x25\xe0\xc8\xe5\x5e\x27\x8c\x81\x03\x91\x1f\xea\xb2\xb7\xf4"}, -{{0xdd,0x12,0x39,0x72,0xe6,0x28,0x58,0x4a,0xcc,0x46,0x29,0x3b,0x8e,0x4c,0xe2,0xb2,0xdd,0x46,0x9c,0xc4,0xed,0xe1,0x4e,0xf3,0x95,0x21,0xcf,0x08,0x37,0x35,0x85,0xb3,},{0x35,0x22,0xf7,0xae,0x59,0x6e,0xed,0xb2,0x17,0x03,0x5d,0x95,0x39,0x5e,0x44,0x8d,0xbd,0x6f,0xfb,0xf4,0x25,0x85,0xea,0xeb,0x30,0x70,0x26,0x54,0x1c,0x78,0xa6,0x51,},{0x89,0x65,0xa8,0x89,0xd5,0x4c,0xd8,0x07,0x6d,0x35,0xbc,0x2e,0x12,0xb0,0x09,0xd5,0x6b,0x07,0x04,0xc8,0x94,0xf9,0x12,0xa0,0xd1,0xd3,0x07,0x20,0xc2,0x32,0xfe,0x44,0x04,0xbf,0x30,0x09,0x54,0x1e,0x8f,0x32,0x83,0xe8,0x9e,0xa8,0x6f,0x67,0x8a,0xfb,0xdf,0x1c,0x21,0xc9,0x24,0xb2,0x3a,0x52,0xb4,0xca,0x6d,0x63,0xf4,0x8f,0xc2,0x03,},"\x2b\x28\x57\xf4\x52\x80\x17\x3e\x2e\x0e\xf9\xd5\x94\xe6\x08\x3f\x1d\xc7\xa6\x54\x92\x97\x5b\x83\x7d\xef\x6c\xad\xd8\xc8\x54\x50\x31\xee\x9d\x68\x36\x9a\x93\x93\xcc\x7b\x79\x2f\xeb\x98\x04\x0b\x21\xf1\xeb\x84\x66\x5f\x87\x85\x37\xce\x41\x2e\x9d\xb6\x80\xd2\x9f\xbd\x8f\xfc\x77\x31\xea\xe9\x1a\x20\xb4\x75\x48\x99\x62\x04\xfb\x06\xad\x74\x0e\x78\xf0\xfc\x59\x0b\x67\x91\xdc\x7a\x0f\x26\x59\x28\x6c\xc1\x6d\x02\xc5\x11\x7b\x56\x58\x36\xb4\xb8\x73\x8c\xf4\x0e\x28\x5c\x69\xc5\x0e\x41\x29\x11\x29\x23\x67\x35\x2d\xfd\xae\xd9\x98\x2d\x0f\x89\x9a\x23\xc0\xab\x51\x81\x2b\x3e\xc6\x78\xf6\x88\x2e\xa4\x27\xcd\xc9\x3a\xb4\xb2\x48\x24\x37\x70\x54\xaa\x25\xd8\x22\x46\x65\x33\x40\x07\x8c\xf1\x1d\x14\xa5\x1f\x0e\x68\x6d\x7e\x01\x8b\x36\x74\x16\x68\xfc\xe7\x45\x8d\x16\x92\x93\x36\x1d\xd1\x6b\x3d\xeb\xbe\xd1\x9e\x1b\xef\x7c\x36\x93\x4e\x20\xf3\x3a\x09\xad\x3e\x82\xb5\x3a\xb4\xe9\x4c\x25\x5d\x04\x18\x98\xb9\x77\x37\xdf\x99\x58\x4a\xf1\x4e\x40\x40\x58\xd0\xc9\x3b\xca\xe7\xbb\xbc\x06\x39\x5a\x2a\xef\xbd\xef\xa7\xb2\xed\x17\xce\xbd\x15\x13\xfa\x39\x0f\xe9\xa9\xb0\xce\x68\xce\xcc\x2b\x9e\x12\x9b\x7a\x29\xf4\x9b\x6d\x18\xc2\x8b\xac\xd3\xaf\x39\xdc\x39\xca\x97\x2f\x0e\x0d\x06\x85\x5d\x57\xc2\xb5\xfc\xac\x2f\x79\xcb\x8c\x05\x79\x9e\x4f\x65\x73\x46\x68\xda\xd6\xaa\x7a\x43\xa1\x18\x56\xe2\x3b\x1e\x73\x2d\x00\xe5\xfe\x38\x85\xb7\xda\xd4\x2e\xc1\x8a\xc8\xe0\x96\xa0\x80\xf7\xd5\x50\x70\xfd\xcf\xf6\x07\xbc\x0b\x85\x2d\x8a\x08\x0d\x2a\x74\x05\xd5\x94\x14\x69\x5f\x2e\xb7\xfb\x0a\xca\x23\xc8\x63\x57\x42\xf8\xae\x57\xf1\x37\x80\x31\x6e\x28\x08\x72\x37\x4e\x69\x29\x59\x8d\x02\x8a\x33\xc0\x5d\x83\x1c\xda\xbd\x02\x94\x93\xc3\xcc\x85\x9f\xff\x1a\x67\xd5\x62\x16\xf0\x2a\x22\x95\x66\x53\x65\x88\x7a\x35\x0a\x80\xaf\xaa\x0c\x36\x7a\x74\xd3\x70\x1a\xe8\x8f\x59\xd8\xa9\xd3\xa1\xdc\xe0\xcf\xd2\xea\xbe\x2a\xf5\x06\x5a\x1c\x7f\xca\x4a\xad\xcf\x8e\x51\xe7\x56\x12\xa1\x37\x1b\x4d\xc8\xff\xc0\xc0\xb9\xc4\xfa\xdb\x2f\x08\x1e\x2e\x03\x2d\x96\x81\x8e\x55\x73\x7a\xdd\xe3\xe1\xac\x12\x1f\x56\xcc\x86\xfb\x58\xa0\xa5\x82\x69\x2f\x62\xce\x58\xac\xce\x17\xaa\xfe\xc7\xbc\xb7\xe4\x4f\x83\x92\x58\xcd\x4a\x85\x1f\xc0\x13\x44\xee\x9f\x1b\xd0\x3e\xb9\x43\x44\xf4\x77\x86\x93\xc1\x71\xdd\x28\x92\xb2\x42\x6a\x88\x29\xab\x0c\xfe\x33\xa7\xd4\xa3\x6e\xb4\x01\x7f\x7f\xcf\xd2\x41\x34\xab\x8a\x45\xf2\x37\x17\xcd\x13\x8a\xa6\x00\x01\x72\xe3\x7b\x40\x64\xdc\x9b\x6d\x1e\x1e\xf3\xaf\x84\x97\x1d"}, -{{0x33,0x35,0xea,0x92,0x81,0x17,0xcf,0xee,0xfb,0xee,0xae,0x14,0x60,0x03,0x88,0x1b,0xdc,0x88,0x89,0xd6,0x58,0x0e,0xed,0x13,0x52,0x37,0x08,0x20,0xad,0x1f,0x58,0x4f,},{0xcb,0x20,0xd4,0xfd,0x75,0x61,0x84,0x80,0x13,0x11,0x1c,0x3e,0x97,0x61,0x7f,0x34,0x18,0x1d,0x2e,0x7f,0xbc,0xf1,0xbb,0x2a,0x2c,0xd2,0xe8,0xc1,0x77,0x5b,0x8b,0x03,},{0xf7,0xc3,0x9f,0x92,0x47,0xd2,0x2f,0x01,0x89,0x99,0x24,0x7f,0x0e,0x00,0x05,0xcd,0x63,0x07,0x6c,0xcf,0x2f,0xee,0x41,0x63,0x42,0x1f,0x86,0x40,0x7a,0x41,0x69,0x8c,0x40,0x58,0x16,0x64,0x73,0x51,0xc0,0x4e,0x93,0xb5,0x44,0x15,0xb6,0x2f,0xc0,0x3f,0xc8,0xc2,0x5e,0x20,0xf7,0x54,0x1d,0xab,0x03,0x19,0x7d,0xc9,0x00,0xb2,0x9c,0x0c,},"\x0f\xa7\xf6\xa6\xfc\xa9\x81\x42\x9b\x57\x2a\x67\x04\x87\x1b\xed\x14\x0d\xab\x93\xee\x19\x92\x00\x6e\x9a\x3b\xb2\xe6\xcc\x9a\x09\xd4\xc9\xcf\x17\x06\x6b\x32\xff\x7e\xf5\xb6\xb2\xe7\x91\x11\x78\xed\x74\x62\xc4\xc1\x75\x60\x31\x71\xca\x61\x36\x68\xb3\xbe\x19\x3d\x94\xc3\x52\x1e\x58\x89\x13\xb5\x94\x8b\x55\x0b\xe9\x9d\x82\xd9\x66\x19\x7d\x71\x0a\xcf\xd9\x59\x14\xcf\x3e\x19\x75\x36\xe8\x3e\x68\x23\x0d\xc3\xd6\x7e\x67\xdc\xdb\xde\xe0\x4f\x0d\x9c\x48\x02\x37\xec\xd2\x8f\x74\x33\x8d\xb5\xf3\xf6\x97\xd3\xd0\x7f\xf3\x36\x13\xbb\xce\x54\x2a\xcc\x9a\x7f\xed\x5d\x12\x49\x0b\x9b\xfe\x1d\x10\x95\x40\xf8\x63\x80\x0d\xd3\x56\xda\x84\x1a\x45\xa3\xcd\x8a\x08\xa9\x45\xbf\xa3\xaa\x98\xe1\x71\x23\x12\xc4\xc0\xf0\xd9\xdd\x64\xf6\xef\xcf\x73\x6b\xd9\x7d\xea\xfc\xa9\xdc\xaa\x3f\x06\xd8\x7f\x2e\xd7\x2a\xeb\x6a\x94\xf3\x28\x00\x00\xc4\xbf\x72\x8a\x01\xc1\x86\x2d\xaf\xd9\xfc\x5c\x7d\x5a\x46\xec\x7d\x3a\x87\xaf\x59\xa1\x1d\x87\xf7\xff\x84\x40\x7d\x37\x01\x0e\x1d\x94\x6c\xf2\x25\xd6\xb3\xb1\xed\xee\x2e\x8b\xbf\x1e\x07\x9e\x47\xfb\x1f\x66\x66\x93\x94\xfb\xf2\xfa\x68\xfc\x56\xfc\x89\x82\x0a\x68\x09\xc2\x51\xdd\x62\xf5\xb8\x65\xc5\x47\xb1\x4f\xbd\x3a\x19\x50\x42\x44\xff\xbc\x7e\x52\x40\xf8\x8d\x43\x60\xf9\xca\xca\xaf\x5f\x82\x43\x3d\x33\x44\xfc\xae\xe0\xac\xde\xb7\xbe\xb9\xc0\xb3\xc7\x69\xea\xc9\x20\xef\x4f\x09\xab\xc2\xa2\x09\x55\x12\x04\x59\x43\xec\xcc\x53\xb1\xc0\x3e\xd2\x4e\x56\x7f\x3d\x7a\x71\x97\x7c\xab\x98\x40\xce\x89\x8e\xe5\x8e\xd5\xc7\x3f\x6a\xde\xa8\x23\x39\x4c\x5c\x8e\x36\x58\xa6\xbf\x5a\xcb\xbf\x00\x55\x99\x2c\x31\x2c\x26\xc7\x9c\x5c\xfb\xea\x38\x60\xb8\x76\x4a\x6d\x8f\xfe\x44\x91\xf8\xa5\xb8\xa2\x15\xe0\x11\x7a\x9a\x68\x16\x4a\xee\x25\xf8\xc0\xbb\x38\x11\x95\xb2\x40\x0b\xcb\x46\x44\xeb\xce\x1c\xde\x5a\x9a\x26\x58\x2c\xab\x9d\xc7\xf4\x3c\x33\xea\xe3\x50\xdb\x65\xaa\x7d\xd2\x2a\x07\x9b\xdd\xdc\xf5\x6d\x84\x8d\xeb\x0c\xfa\x50\xb3\xbd\x73\x2d\x9d\xa9\xe8\xd8\xab\x79\xe9\x34\x69\xde\x58\x02\xb6\xdf\xf5\xac\x2a\xa8\x48\x2b\xb0\xb0\x36\xd8\xf9\xd5\x95\xb8\xea\xd9\x4b\xb8\xd7\x41\x8e\x2e\xa4\x31\x92\xef\xcb\xfc\x05\xc4\x67\xbd\xe0\xa8\x68\xa5\x16\xa7\xc1\x4a\x88\x9b\x72\xc5\xb7\x3e\x7d\x85\xc2\xba\xe9\x02\xe4\xe6\x8d\x1f\x3c\xea\xb2\xb2\x77\x3a\xf5\xbb\xae\xe6\xa0\x0d\x08\x06\x3e\x78\x33\xcd\x4e\x29\x53\x47\xe5\x8f\x5d\x1b\x33\x97\xf6\x40\xc1\x59\xcc\x60\xa6\x74\xa2\x27\xb4\xcd\x8c\x10\xf1\xdb\xae\xd5\x16\xcc\xac\xdd\x29\x5f\x11\xb0\x81\x47"}, -{{0x32,0xa1,0x88,0x3e,0xff,0x57,0xa3,0xa7,0xec,0xdb,0x31,0x02,0x21,0xee,0x83,0xc4,0xde,0x92,0xb7,0x22,0x15,0x96,0x13,0xec,0xf8,0x16,0xe3,0x82,0x43,0x7b,0x60,0xb9,},{0x82,0xdd,0x1a,0x03,0xe5,0x85,0x20,0x62,0xba,0x4a,0x8b,0x6b,0x3b,0x93,0xc5,0xe9,0xc4,0x3f,0xf6,0x99,0x5b,0xd2,0xaa,0xc7,0x26,0x06,0xfa,0xc8,0x58,0x02,0xc6,0x82,},{0x83,0x09,0xcb,0xe7,0x2f,0x80,0x4b,0xd9,0x52,0x1d,0xef,0x5d,0xad,0x4d,0x8b,0xc1,0x38,0x86,0xb1,0xd4,0xf6,0x62,0xc9,0xbb,0x5b,0x97,0xba,0x47,0x90,0xf4,0x4b,0x80,0x1f,0x31,0x95,0xea,0xd0,0xd4,0xdd,0xb6,0x60,0x81,0x8e,0xcb,0xf9,0xa6,0x83,0xca,0xcf,0x85,0xf1,0xdc,0xc9,0xe8,0x2c,0x09,0x11,0x6d,0x73,0x36,0x58,0x09,0x1a,0x00,},"\xed\x2b\x12\x3b\x5d\xd7\xf5\xe7\x18\xe0\x26\xc7\x9c\xfa\x61\x11\x92\x49\x02\xd1\x89\xa4\x06\xef\x2b\x2e\x56\xa9\xee\x55\x73\xa7\x6d\xdd\x1d\x06\x29\xeb\xcd\xec\xf2\xaa\xa7\x4e\x84\xfc\xd0\x20\x8f\x14\xee\xa2\xe1\x71\xe7\xc8\x60\x8b\x81\x8f\xef\xf4\xdb\xea\x52\xdb\x35\x42\x27\xd0\x23\x25\x0b\x1f\x01\xcb\x4c\xc8\xc5\x21\x32\xa9\x8d\x4a\xcf\x55\xa5\x4f\xee\x81\xe0\x94\xae\xd6\x6f\xa0\xd6\xb6\xa2\x00\xb6\xb8\x74\x14\x40\x22\x78\x53\x8b\x90\x52\x9a\x8c\x60\x3d\x92\x7e\xdd\xda\x97\xbc\x4b\x8c\xb9\x5d\x04\xb5\x33\x7f\xa2\x2c\xea\xfc\x8b\x34\x0c\x46\xfe\xf6\x71\x98\xd1\xfd\x98\xd8\x9c\x65\xcd\x08\x9e\x23\xf5\x3d\xbd\xca\x96\x77\x98\xb5\xcd\x92\x32\x05\xad\x51\x1e\xdf\x70\x6f\x12\x25\xf4\x64\x8c\x98\x5e\x00\x9e\xf8\xa2\xf6\xa0\x11\x7c\xdb\xe1\x4e\x75\x31\x2d\x8a\xc1\xf0\x3d\x04\x6b\x37\xcd\xee\x7d\x69\xc0\xf2\x5c\xcf\x18\x14\x5a\x68\x8a\x8b\x3c\xa8\x87\x5f\xe8\xd9\x0b\xaf\x86\xd4\x39\x69\xe4\xd6\x10\x21\x4f\x1a\xc5\xdb\xba\x87\xa1\xef\x10\x37\x7e\x40\xd7\x80\x6f\xd9\xd2\x34\x57\xfc\x9d\xf2\x98\x99\x23\x9f\xd1\xd2\x78\x84\x96\x81\xa9\x43\xad\x9c\x91\xfd\x1b\xbd\x92\xb7\x3c\xb1\x77\xa8\x78\xf9\x05\x9e\xe0\x7a\xf7\xa8\x73\x16\x13\xe3\x3d\x59\xdf\x3d\x97\x79\x60\x79\xd5\x63\x1e\xd8\x5e\xb2\x24\x51\x06\xa5\xff\x6a\x2b\xca\x40\xdf\x5c\x6e\x87\x47\x3b\x2c\x08\xc2\x21\x2f\x56\xfc\x29\x33\xa9\x69\xa3\xc9\x58\xd3\x7c\x53\x43\xba\x27\x60\xc8\x13\xa7\xa5\x16\x5d\x23\x1c\x5f\xea\xae\x62\xb7\x55\xdf\x49\xfe\xca\x80\x04\x1a\x65\x35\xf7\xe0\x3b\xc4\x8e\x5f\x27\xf9\xbe\x26\xef\x53\x67\x3e\xb7\xc3\x7a\x2b\x64\x74\x4a\x6c\xf1\x7e\x88\x77\x34\xae\x01\x0b\xf4\x0e\xea\x03\xcd\xa2\x12\xf5\x12\xfb\xa0\x58\x59\x47\x17\x96\x40\xbc\xc4\x54\x4b\x8d\xeb\x4e\xad\x12\x9b\xc3\x32\x28\x00\xad\xf9\x88\x18\xf9\x95\x74\xbe\xfd\x9b\x00\x16\xd4\xee\xc8\x1a\x8e\x78\xdc\x3a\x2a\xf1\x3c\xab\x01\x64\x9a\xe2\xe3\x3d\x51\x6b\x9d\x42\x08\xad\x66\x13\xd8\xe2\x78\xc3\x93\xba\xa8\x82\x34\x0e\xf4\x61\xff\x4f\x94\x42\x3d\x55\xcf\x3c\xed\xd2\xa6\xb5\x6e\x88\x36\x55\x31\xdd\x29\xd6\x82\x73\xad\xbf\xe3\x69\x40\x2e\x6a\x7c\xee\x05\x3d\xa1\xf1\x00\x54\x00\x91\xa0\x09\x29\x25\x29\x83\x44\x90\x24\xb1\xc3\x39\x11\x10\x65\x00\x82\xf0\xe7\xdf\xdd\xb8\xed\xc2\x04\x2f\x3c\x17\x13\xc6\x94\x4b\xa5\x14\xee\x74\x07\xd3\x2b\xf0\x6c\x85\x8e\xfe\xc4\x2a\x78\xbe\xe9\x77\x46\xe5\xb4\x87\x91\x41\xa1\x3d\x9f\xc5\xcb\x12\x3b\x78\x32\x73\xb8\x4d\x57\xad\x35\x26\xb7\xda\x3c\x68\xb8\x39\xef\xd2\x3f\x5f"}, -{{0x22,0xec,0xef,0x6d,0xab,0xe5,0x8c,0x06,0x69,0xb8,0x04,0x66,0x49,0x73,0xe4,0x57,0xc0,0x5e,0x47,0x77,0xf7,0x81,0xc5,0x25,0x22,0xaf,0x76,0xb9,0x54,0x81,0xa9,0x14,},{0xd4,0x78,0x40,0x10,0xef,0x04,0x03,0xed,0xdc,0x5a,0x62,0xd5,0xd4,0x5b,0xb2,0x43,0xb8,0x0b,0x4b,0x9d,0x69,0xc3,0x9c,0xa3,0x87,0xc6,0xf5,0xcb,0xa0,0x28,0x64,0x0f,},{0x5d,0x0d,0x2a,0xf6,0x78,0xb3,0xd1,0xb6,0x77,0x51,0x6d,0x08,0xa7,0x9a,0xaf,0xd3,0x6e,0xc6,0x7c,0x14,0xca,0xf5,0xbc,0xda,0xae,0xaa,0xcc,0x51,0xa1,0x4f,0xb8,0x05,0xcf,0x29,0x04,0xe8,0x72,0x1d,0xb2,0x71,0xb2,0x0d,0xf7,0x09,0xbe,0xe1,0xa4,0xfb,0xfe,0x62,0x56,0x50,0x73,0xb2,0xa7,0xe9,0x42,0x72,0x44,0x61,0xf9,0x27,0x93,0x0d,},"\xc5\x35\xc1\x3d\x77\x9f\xc0\x98\x59\x73\xd6\xbc\xd5\x52\xd8\x17\x34\xe9\x2b\xdf\x10\x99\x4b\x00\xcd\x4d\x53\xce\x36\x5f\xad\x8c\x7c\xfa\x96\x20\x6a\xdb\x62\xd4\x56\x7b\xe5\xe4\x66\x31\x32\x38\x53\xe3\x8c\xe4\xbd\xc1\x6d\x7b\x8f\x63\x2a\x3a\xd9\xe0\x26\x19\xef\xf3\x71\x74\xea\xc3\xf0\xbf\x2f\x7a\x75\x17\xd4\xb8\x2d\xe6\xaa\x1a\xf0\x06\x38\x19\xd5\xe1\xf9\x27\x8f\xb4\xf2\x4c\x8c\xc0\x02\xaf\xb1\x5f\x33\x4c\x04\xfa\xdb\x00\x30\x30\x13\xc0\x16\x67\xf4\x93\x2a\x6c\x4b\x97\xd3\x9c\xd4\xa4\x59\x85\x06\xc0\xbd\x74\x0e\xa9\xf1\x16\x96\x35\x7d\x7d\x17\xfe\x4d\x75\xf9\xd7\x42\x41\xa7\xaf\x71\xf9\xd8\x69\xef\x6c\xd6\x95\x68\x7c\x03\xfc\x34\xad\x65\xa6\x8a\x48\x88\xa1\xa7\x41\x26\xcb\x55\xcf\x7d\xa9\xcb\x4a\x67\x17\xf6\xeb\x88\x48\x40\x89\xd2\xc5\x18\x9a\xe3\x81\xf2\x5e\x7b\x3b\xc3\xb2\x3d\x0c\x9d\x9f\x9c\xdb\xbe\xec\xfd\x1e\x72\xa0\x5e\x67\xbb\x48\x3a\x97\x64\xd9\xfc\x75\xad\x69\xe4\xab\x12\x70\xfb\x40\xf3\x95\x8f\xea\x4d\xa5\x59\xb4\x39\x80\xb2\x46\x81\x31\x3e\x85\x91\xe6\x85\x46\xa3\xbf\x76\xee\x34\xb3\x39\x70\x92\x95\xa8\xd4\x6f\xb2\x43\x2d\xda\x2f\x22\x18\x12\xdf\x69\x28\x95\xe6\x7c\xb2\x9c\xbf\x6f\xf4\x50\x2b\x43\x9a\x4e\x9e\x43\x63\x9e\xc0\x67\xbc\x90\xae\x81\x4a\x29\x3a\x7b\xd4\x69\x68\xe6\x56\x78\x76\x42\x30\x0a\x0f\xf2\x69\x7e\x33\x13\xf6\xa4\x18\xd3\xd1\x2a\x5f\x7c\x51\xa4\xc5\x7b\x63\x38\x5f\x2d\x2a\x21\xd5\xd1\xd7\x63\xfc\x8d\x1b\x93\xc1\x34\x35\xf9\xe4\x7e\xe7\xa4\x25\x98\x0a\x6a\xe6\xf1\xa9\xd0\x07\x60\x74\x76\x78\x3c\x6d\x0c\x78\x87\x38\x0f\x86\x8c\x65\xb3\x82\xd4\xcc\x8c\x04\x47\x8b\xbd\x79\xa1\xd9\xa9\x64\xb7\x81\x71\xd6\xbc\xf0\xb8\xee\xc5\x0a\x06\xa4\xea\x23\x4d\x1c\x23\x46\x5d\x3e\x75\xb8\x8b\xc5\x40\xda\xde\x74\xed\x42\x67\x5b\x07\xf7\xcf\x07\x82\x11\xe9\x07\xf8\x6d\x0d\xc4\xb9\x78\x62\x3d\x9f\x08\x73\x8a\xf9\x28\x69\x5e\x54\x2e\xc2\x98\x0e\x55\xa1\xde\x49\xe2\x52\x47\xfa\x0a\x09\x67\x81\x18\xe3\x93\x0b\xc4\xd2\x4b\x32\x14\xd6\xdc\xfb\x6e\xbd\xf4\x90\x6c\x92\x8d\xeb\x37\xbb\x9b\xa2\x9c\x8d\xe1\xbb\x94\x18\xdb\x71\x8b\x28\x53\xba\x57\xad\x8c\xae\x46\x77\xad\xdf\xd1\x8b\x6c\x7e\x8c\x24\x26\x21\xb3\x5c\x7f\x0e\xfe\x8d\xd5\xeb\x26\xff\x75\xfd\x57\x48\xb1\xd7\x83\xf6\xd6\x8a\x7d\x9d\x56\xda\x2c\x1a\x97\x8a\xc2\x5f\x84\xfb\xb2\xbe\x55\x68\xd9\x1e\x70\x93\x82\x21\xc1\x02\xae\xe6\x04\x09\xbc\xbe\xc0\xc8\x2e\x12\xdd\xb4\x25\xee\xb6\xec\xd1\x15\x51\xec\xd1\xd3\x3d\xda\xe8\x71\xae\x0c\x8f\x24\xd0\xd1\x80\x18\x73\x2b\x5e\x0e"}, -{{0x8d,0xe8,0x63,0x30,0xb2,0x56,0x09,0x5e,0x11,0x14,0xb6,0x52,0x9b,0xed,0xce,0x18,0x2c,0x16,0x6f,0x67,0xa9,0x15,0x39,0xce,0xbc,0x4b,0xec,0x25,0xad,0xd7,0xa4,0xa9,},{0x33,0xcb,0x05,0x4b,0x55,0xbb,0x79,0x0a,0xc0,0xf3,0xaf,0xdd,0x9a,0x6e,0x7c,0x05,0x0e,0xfe,0x90,0x06,0xc2,0x4f,0x60,0xb8,0x04,0x4f,0xd0,0x8a,0x5c,0x10,0x6c,0x11,},{0x6d,0x01,0xd2,0x37,0xdd,0x2b,0xb4,0x18,0x8d,0x29,0xbf,0xde,0xc3,0x87,0x97,0x6a,0x71,0xbe,0x7a,0xdf,0xbf,0x9e,0x23,0x63,0x9b,0x21,0x6d,0x0a,0xa0,0xc1,0x19,0x32,0x23,0x5e,0xdc,0xcb,0x3b,0x42,0xad,0xcd,0xb6,0x29,0x1a,0x0d,0x29,0x9a,0xed,0x64,0x8d,0xe8,0xb1,0x95,0x79,0x49,0xb9,0xd1,0xcf,0x2e,0x50,0x49,0x30,0x30,0xa4,0x0f,},"\x39\xe6\x1e\x0e\xcc\xec\x92\x9c\x87\xb8\xb2\x2d\x4f\xd1\x8a\xea\xbf\x42\xe9\xce\x7b\x01\x5f\x2a\x8c\xac\x92\xa5\x24\x48\xa4\x2f\xed\x4c\xba\xdc\x08\x5b\xbb\x4c\x03\x71\x2a\xe7\x2c\xfc\xb8\x00\xb9\x78\x35\x06\x69\xb0\x99\x00\x84\xf2\xda\xb7\x6e\xca\x60\x6d\x1a\x49\xfc\x55\xc5\x29\xe1\xe7\xda\xdf\x39\x12\x2d\xd5\xbd\x73\x38\x93\x85\x8b\x05\x23\xef\x62\xdf\x4f\x13\x4c\xf6\xc2\x6e\xed\x02\xfd\xbc\xb3\x0c\xe4\x74\xb1\xad\xa3\xf0\x60\x76\x9f\x93\x4b\xbe\x68\x6c\xce\xbd\x60\x88\x3e\xce\xc9\xce\x3f\xfb\x8a\xc4\xa0\x67\x8c\xdc\x5b\x00\x5a\xe3\xdb\xa7\xe4\xfe\x8b\xc0\x45\x73\x99\x57\xd8\x49\xf6\x9c\x14\x74\x05\x7b\x42\x8c\x54\x25\xf3\xcc\x25\x16\xe8\xbb\xe3\xbe\x81\xaf\xd4\xe7\xb5\x75\xab\xe8\x8c\x87\xf2\xf0\x3b\x56\xf6\x9f\x9e\x3b\x61\xb3\x78\x81\x20\xda\xa4\x95\xef\x0e\x50\xeb\x97\x0a\x64\x5c\x13\xd2\x13\xc7\xcf\xb7\xd0\xad\x55\x5c\x92\x0a\x1e\x5d\xbc\xb4\x67\x97\xd9\x39\xfe\x04\x01\xf5\x47\xbf\xd1\x75\x43\x22\x1a\x53\x01\x0d\xe0\x1f\x25\xb6\x45\x19\xc8\xf0\x39\x63\xe4\xb9\xca\x58\xb0\x11\x36\x27\xc0\x5b\x96\x08\xee\xaa\x7b\x9a\xe6\x30\x5c\x96\x18\x81\x60\x00\x0e\xe3\xa7\xad\xe9\x6e\x0b\x4b\xde\x9d\x0e\xd6\xa0\xce\xd7\x65\xd7\x86\x84\x0a\x48\x17\x5a\x6e\x09\x0a\x38\xaf\x6a\xde\xaa\x14\x86\xa9\xcb\x5c\x8c\x8c\x92\x23\xee\x0a\xe4\xc6\xc0\x26\x91\xa3\x54\x7e\x32\x58\x2a\x5b\x70\x59\xd2\xee\x66\xfa\x9c\xd9\x65\x61\x5c\x31\x5b\x47\x6f\xd8\x61\x27\x9c\xd1\xdd\x76\x07\x74\x3f\xc5\x56\x12\x96\x31\x2f\x11\xe4\x65\xca\x40\xbc\xe3\xcf\x0b\x1f\x1d\x5a\x30\xaf\x60\x87\xde\x4d\xe9\x6c\xe4\x39\x65\xa4\x6c\x4f\xcc\xa1\x5f\x28\x11\x49\xb5\xc1\xa0\xc8\x8f\xdb\xf2\x74\x09\xa1\x34\xed\x4f\x1f\xb7\x30\xfa\x19\x18\x16\xea\x78\x4d\x98\x6c\xc9\xec\x4b\x69\x44\x02\xde\x1d\xcc\xa9\xcc\xc6\x4f\xbd\x07\xb0\x7e\x54\xe9\x31\xde\x82\x7a\x84\x24\x60\xca\x0b\xf6\xb0\x4e\xbb\x57\x1f\xa7\x77\x87\xe3\x88\x4b\xe2\x2f\x1e\x40\x2c\xf2\xb8\xa9\x6a\x5d\x39\x77\x0e\xc4\xa8\x43\x03\x61\x42\xa0\xbe\x97\x0b\xb1\xab\x16\x5a\x63\x74\xdc\xf4\x3d\xeb\x8b\x98\x30\xb2\xc4\x9d\xb9\xcd\xfe\x4b\x52\x42\xe3\x6f\x95\xe0\xc3\xe0\x77\xe8\xd2\x38\xfa\x6a\x8a\xc0\xd5\x86\xbf\x61\xb8\x24\x8f\xb3\xa7\x9a\x27\x0a\xb2\x2b\xe8\xa9\xda\x05\x5f\xf3\xd5\xbb\x2d\x1c\xa9\xbc\x25\xf7\x01\x4b\x96\x40\x77\x19\xde\x34\x4c\x3e\x73\xb8\xc1\x14\xf7\x92\x07\x5a\x5c\x22\xfd\xd4\x16\x15\x4d\x34\x94\xec\x3f\x02\xfb\x11\x2e\xe5\x73\x7f\x70\x70\x4c\x1b\x6b\x07\xea\xcb\xf9\x45\x62\xca\x7b\x90\xdd\x84\xd9\x8c\x3e\xdf"}, -{{0xba,0xb5,0xfa,0x49,0x18,0x7d,0xa1,0xca,0xb1,0xd2,0x91,0x90,0x00,0x19,0xe6,0xcb,0xaf,0xec,0xcd,0x27,0xbf,0x7e,0xcb,0xf1,0x26,0x2a,0x70,0x05,0x16,0xe7,0xc2,0x9f,},{0xf6,0xfb,0x19,0x85,0xec,0x59,0x1f,0x69,0xe3,0xba,0xc8,0x07,0xb2,0xea,0xbf,0x26,0x39,0x90,0xcd,0xfa,0x09,0xb1,0x78,0x09,0xe4,0x8e,0x38,0x5d,0xa0,0x65,0xec,0x21,},{0xe3,0x16,0x03,0x8d,0x6a,0xa1,0x5b,0x1c,0x1b,0x61,0xc1,0xa1,0x6b,0x36,0x90,0x4f,0xe8,0xa2,0x89,0xc8,0xd6,0x02,0xbe,0xcc,0x51,0x4d,0x99,0x22,0x00,0x86,0xb2,0x67,0x85,0x9f,0x5b,0xf6,0xe9,0xc0,0x86,0x35,0x59,0xac,0x62,0x3a,0x56,0xd7,0x53,0x23,0x44,0xe8,0xd2,0xf2,0x8b,0x3f,0x9d,0xf9,0x20,0x89,0x70,0x8b,0x1b,0x05,0x90,0x08,},"\x5c\xf8\xff\x58\x7e\x52\xcc\xcd\x29\x84\xf3\x47\x91\xee\x68\x43\xe7\x70\x17\xc3\xb5\x5a\xd4\x5c\x44\x45\x09\x65\xb7\x5d\x83\x6e\x78\xfb\xd7\xa1\xd1\x72\x9e\xff\x6d\x6d\x34\x0a\x90\x3f\x3c\xf1\x7d\x9e\x2a\xec\xaa\xff\x2a\x32\x1f\xcd\xde\x0a\xbc\xfb\xbc\xbc\xc0\x9f\x40\x86\xf8\x12\xc4\x6e\xfb\x01\xb7\x83\x43\xaf\xbe\x48\x30\x9f\x91\x74\x78\x45\x5f\x32\x00\x0c\x6a\x69\xf7\x9f\xe2\x11\xb9\x9f\x03\x7f\x59\x56\xd7\x22\x75\xa7\xfe\x7b\x45\x29\x6b\x5f\x73\x9a\xa4\x51\xff\x05\x75\xbc\x70\x58\x85\xaa\x56\x31\xb0\xd0\x85\x0b\xc2\xb1\x2c\x41\x92\x43\x5a\xe5\xd2\xf5\x2b\xc5\x43\x86\x49\x7c\x4a\x24\xb8\xb6\xdb\x51\x6b\xe0\x9d\x8c\xcf\x1e\xca\x78\x5b\xde\x97\xe9\xbe\x1a\xc0\x64\xf0\x94\xe2\xaf\xcc\x30\x7c\x0e\x06\xb4\xc5\x64\xcd\x9a\x9a\x95\x30\x5b\x37\xb8\x1f\x43\x46\x11\xdc\xa5\x5c\xaa\xa0\x31\xe8\x84\x95\xd5\xdc\x5a\x04\xff\x5f\xaf\xdf\x0a\x82\xa0\xc0\x3a\xff\x1b\xfb\xf4\xff\xeb\xae\x71\x82\x4e\x35\xe7\x51\xb0\x92\x70\x00\x76\x69\x86\x0b\x58\x00\x35\x65\x9e\x23\xac\xe7\x6b\x3b\x36\x9f\xa3\x06\xf2\xbe\xd9\x57\x99\xfa\xfa\xbc\x2e\x69\xc1\x41\xbe\xb0\xba\xca\xc7\xea\xa3\x47\xe7\x7b\xe5\xaf\x3f\xcd\xbe\x7b\x36\x4a\x7f\x9a\x66\xd5\xe1\x7a\x07\xdf\x62\x02\xfd\x98\xc1\x4b\xfe\xe2\xca\x6f\x07\x45\x65\x1f\x0c\x85\x50\xf9\xff\xff\xca\xfb\x96\xff\xb3\xf1\x03\xe6\x52\xe7\x8f\x53\x91\x6c\xd6\xf1\xdd\x05\xb3\xfe\x99\xb3\x42\x01\xb0\x7e\xac\x26\x52\xf5\x25\x35\x71\xfd\x38\x22\xc6\x95\xd2\x65\xc7\xdf\xdd\x6c\x6b\x14\xa8\x0b\x6e\x87\x18\x3e\x6e\x03\x2e\x5f\x24\x01\xcd\x23\x8c\xdd\x37\x69\xbb\x6e\x39\x08\x23\x43\x8f\x56\x73\xea\x9a\x47\x9e\x5c\x63\xfe\x07\xa0\x7f\x4e\x14\xf5\x77\x57\xc4\xd7\xd2\x2b\x35\xd7\x1c\x44\xea\xad\x48\x73\xc8\xec\xa6\xf6\xb2\x1d\xcf\xa9\x55\x20\xff\x96\x14\xab\xf7\xa0\xe1\x88\x53\x09\xf2\xce\xd3\xbc\xdf\xc3\x19\x36\x3a\x2d\xa4\x6d\xed\x79\xa5\xcc\x7b\x6f\x69\x38\x3f\x94\xab\x35\xc2\x50\x62\x9c\xb9\x15\xd6\x67\xb6\x28\x11\x86\x75\x48\x95\x80\x3e\x4b\x95\xe7\x41\x82\x89\xa6\xac\x3b\xcd\xb6\xe1\xe7\xf6\xf1\xdc\x38\xe7\x7d\x28\x19\x14\xcc\x40\x4f\x97\xcf\xf1\x4f\xb2\xc4\xfd\x81\x41\x2d\x10\x1c\x1b\xfb\x36\x8c\xe5\x93\x11\xe8\x92\xa8\xb9\xcd\xca\x86\x93\x6f\x3b\xca\x7e\xc7\x91\x63\xed\xdf\x1c\xee\x68\xf4\x9f\x1e\xba\xa2\x7e\xc5\x0f\x49\x0d\x61\x60\x1c\xa3\x5f\x8d\x6e\xd2\x66\x05\x4a\xeb\x9b\x19\x9f\x93\x3b\xff\xd6\xe0\x05\x0f\x26\x1b\x4e\x13\xd5\xeb\xfe\x2c\xaa\x65\x57\xc3\x2d\xde\xae\xeb\xc2\xa1\x1f\x0a\xa2\x33\x24\x0d\xa1\xc7\xe4\x0f\x76"}, -{{0x74,0xca,0x12,0x2a,0xb6,0x0d,0xe5,0x0c,0xdc,0x04,0xa8,0xe2,0xed,0xa4,0x5d,0x96,0x31,0x06,0x1b,0xf1,0x87,0xd3,0x16,0xbe,0x5b,0x7c,0xc0,0x6f,0x02,0x0c,0x48,0x3e,},{0x78,0x7d,0xef,0xd4,0xfb,0x24,0xa3,0x99,0xbd,0x2a,0x4e,0x76,0xdf,0xf7,0xd6,0x03,0xed,0x0a,0xcb,0x32,0x69,0x81,0x3e,0x4d,0xf6,0x90,0xbb,0xf5,0xb2,0xbc,0x69,0x6e,},{0xbc,0xb4,0xb8,0x50,0x69,0x60,0x11,0x99,0x7e,0xb5,0xdf,0xe1,0x43,0xf1,0xa3,0xd5,0x62,0x8e,0xf1,0xa5,0x40,0x76,0x91,0xee,0x48,0xc7,0x9d,0x69,0xab,0xe4,0xd5,0x33,0xf8,0x17,0xad,0x73,0x13,0xb5,0x79,0x5e,0x46,0xe5,0x95,0xf3,0xae,0x3a,0x91,0x65,0xb1,0xb6,0xfd,0xda,0xe8,0x61,0x64,0xff,0xcb,0xa3,0x76,0x24,0x98,0x37,0xf6,0x09,},"\xa8\x0b\x46\x07\x9f\xa7\x75\xf8\xc1\xa1\x9f\xa0\x82\x9b\xe6\x66\xbd\xfd\xca\x07\x9c\xad\x43\xd7\x0e\x08\x42\x18\x3b\xc0\xdb\x95\x46\x8a\x53\x9f\x0d\xb2\xae\xa3\xab\x9c\x70\x73\xb4\x5d\x22\x8a\x9b\xde\x23\x28\x97\xa6\xeb\x6f\xc9\xed\xf7\x36\x5e\x71\x01\xba\x97\xc4\x46\xa5\x19\xa3\x64\x9c\xf5\x27\xc8\xa6\xde\x72\x51\xb9\x28\x06\x81\x5a\xc2\xfa\x00\x82\xef\xf7\x5e\x25\x82\xcb\xca\x7e\x1e\x4d\xa2\xa4\x46\xea\x23\x3e\x7c\xf7\xce\xdf\xb0\xe2\x39\x8e\xb6\xe1\x1b\xba\xef\xe3\xf7\xec\x89\xf5\xd7\x3d\xd3\x4b\xd4\x7f\xbc\xb4\xd7\xb2\x2f\x2a\xae\xe3\x73\x78\x56\x51\x84\x11\x35\xcd\x86\x61\xa7\x01\xb2\x10\x84\xa3\x16\xde\xac\x30\x74\xe2\x4a\x2e\x35\xa0\x33\x0f\x7d\x14\x79\xb9\x32\xf2\x85\x27\x7c\x18\xa4\x41\x78\x72\x24\xfb\xbe\x46\xc6\x2e\x83\x4a\x18\x51\xed\x23\x79\x98\xd4\x8d\xce\x20\xba\x11\x4d\x11\xe9\x41\xbe\x29\xd5\x6d\x02\xf7\x37\x0c\x8f\x6d\x6d\x7e\x50\x24\x8d\xcd\x8e\xc8\x9d\x3b\x22\xf4\xf5\x87\x78\x12\x9f\xaf\xd4\xbb\x92\xed\xe1\x77\x14\xbf\x02\x2a\x5b\xf9\x2b\xe4\x79\xf1\x8e\x63\x85\x2e\xcd\xcf\x8c\x42\x11\xf5\x30\xdd\x30\xf7\x9c\xbf\x4b\xfa\x57\x37\xf0\xba\xd3\xb0\x10\x60\x67\xf4\x13\x27\xc3\x18\x9e\x6f\x20\x6f\x0d\x4f\x3c\x70\x4b\xf2\xbd\x0b\x16\x1f\x01\x8f\xd2\x1c\xdd\xfb\x41\x8b\xac\x4d\x52\xef\x02\xc4\x1c\x87\x92\xe4\x13\xb0\x4f\x08\x36\xce\xa1\xf8\x6c\x92\xe5\xd5\x70\x3b\xee\x2b\x5c\x58\x99\xe2\x85\x99\x20\x24\xf6\x4e\x0d\x16\xc6\x0a\xd0\xfd\x92\x54\x79\x32\xd0\xc5\xcb\x98\xd8\xda\x22\xfe\xeb\xdb\xba\x8d\x1d\xe1\xe7\xe9\xbb\x21\x9a\x92\xeb\x6c\x1c\x69\x8d\x3b\x33\xa3\x7f\x9b\x81\x97\xd2\x6b\x55\x0f\xeb\xd2\x60\x1e\x7a\x64\x3e\xa7\xe1\xd9\xe4\x48\xae\x03\x7f\x62\x9a\x30\x6c\xe4\x17\xae\xb7\x9f\x2e\x3c\xa4\x4d\x8d\xb3\x84\x8a\x81\x1f\x18\x46\x81\x1c\xbc\xb8\x74\xf8\xaf\x09\xe0\xfd\x01\x73\xcf\x17\x5f\x30\x41\x15\x47\x6b\xf2\xc6\xc2\xd2\xf3\x32\xeb\xa5\x34\xf4\x6a\xae\x80\x1c\x26\x92\xc2\xd2\xfa\xdd\xfe\xac\xc0\xf1\xda\xce\x44\x0a\xbc\x2a\xe5\xe5\xa4\x9d\x57\x8f\xd7\xf9\xde\x2a\x84\x1a\xd6\xb6\x76\x9c\x32\xb1\x44\xce\xea\x16\xd0\xf3\xc0\xcb\x3a\x8e\xe6\x94\xc3\x8c\x28\x07\x35\x95\x09\x6c\x81\x37\x62\xcc\x2c\x5e\xc4\xb0\xd8\xd7\x23\xdd\x66\x08\x53\x27\x8f\xc7\x2f\xd6\xbd\x9d\x12\x72\x93\x3d\xd2\xa3\x8e\xd9\xd0\x4b\x13\x90\xff\xe4\xb2\x94\xa6\xff\xfa\x72\x1e\xe3\xbb\xa3\x3a\x03\xa1\x49\xc4\xa0\x34\x52\x65\xc0\x1c\xe0\x15\xe9\x4d\xb4\x19\xcf\xf7\x04\x98\x52\xee\x00\x00\x48\xa8\x57\x58\xf6\xd7\xb1\xc5\x9c\x50\x89\xee\x01\x8e\xd0\x9b\x52"}, -{{0x65,0xee,0xa9,0xff,0xb7,0x56,0x12,0xbd,0xe1,0xd9,0xba,0x3e,0xa4,0xfb,0x5e,0xda,0x0a,0xa6,0xf2,0x55,0x6a,0xb1,0x5b,0xf1,0x81,0x7c,0xee,0x3b,0x95,0xbb,0xba,0x12,},{0x5b,0x39,0x36,0xdc,0x74,0x9b,0x6b,0x92,0x39,0xf1,0x57,0x98,0xac,0xca,0xfd,0x88,0x4c,0x36,0x59,0xee,0x01,0xb2,0xd1,0x7d,0x74,0xfc,0x7d,0xa7,0x82,0x74,0xe7,0xe6,},{0xba,0xa7,0x11,0x31,0x55,0x35,0x8c,0x92,0x4f,0xed,0x57,0x48,0x8a,0x65,0x67,0xf8,0x72,0x38,0x50,0xa9,0xf5,0xc0,0x3a,0x0d,0x7d,0xe8,0x5f,0xcc,0xd8,0xfb,0x4d,0x17,0xd7,0x75,0x35,0x23,0xb0,0x0c,0x0d,0x8a,0xdb,0x88,0x4d,0xc0,0xc8,0xa7,0xa4,0x4d,0xc2,0xa6,0x00,0x83,0xaa,0x5b,0x3c,0x5b,0x94,0xa8,0xd8,0x80,0xf2,0xa9,0x4d,0x09,},"\xc0\x69\x36\x32\x3c\xe3\x25\x3c\xac\x5a\xb4\xf6\xb8\x32\x70\xcd\x4c\xfe\x85\xd0\xbf\x8b\xac\x1e\x1b\x8d\x5f\x0b\x15\x3f\x54\x1c\x8e\x8e\xd9\x5f\x28\xd5\xc8\x5a\x23\x15\xcd\x93\x1b\x7c\xf3\xed\xae\x50\xf9\x28\x30\x59\x91\x62\x80\x4b\x13\x63\xd3\xac\x0d\xa0\xab\xd0\x97\x51\x02\x3b\xdd\xc1\x62\x88\x94\x4e\x61\x6d\x21\xd9\x12\x71\x97\x8b\xb7\x82\xd3\xeb\xed\x7f\xa6\x12\x84\xc7\x49\x0d\x27\x59\x3c\xa8\xa3\xd5\xb4\x75\x62\x33\x07\x01\x0a\xbc\x1f\xbf\x79\x3a\x81\x6a\xaa\xb5\xe0\x92\x4d\xec\x79\xd6\x04\x98\x96\x5c\xf7\xf8\x0a\xb5\x9f\xc0\x29\xf7\x82\x16\x67\x55\xb7\x2b\x86\x90\x75\x43\x4a\xb6\x06\xcc\x87\x0a\x7c\x0b\xc8\xbf\x29\xae\xe0\x33\xfa\x9c\xc1\x22\xed\x7c\x8e\x06\x9b\x54\x7d\xba\xe2\x59\x01\xb9\xe2\x49\xb4\x1f\xea\x0b\xf8\xda\xf3\x82\x68\x66\xbc\xae\xd2\x75\x3b\x5e\x91\xae\x93\x7e\x71\x7b\x50\x8a\x0a\xcf\x4c\x3b\x06\x1f\xf0\xcb\x9c\xfd\x38\x0e\x24\x94\x50\x09\x51\xa6\x62\xfd\x49\x28\xfc\x5f\xca\xf6\xc1\x8e\x84\xb1\xd3\x78\xe4\x9b\xd9\xd5\x96\x86\xd0\x87\xeb\xd5\x52\xd0\x7f\xa9\xba\x81\x6f\xa5\x40\x2c\xa9\xe7\x25\x2a\x64\x8d\x10\x6c\xfe\x6c\x43\x1c\xc2\xa0\x53\xe2\x29\x46\x37\xcd\xb9\x9d\x96\xab\xe6\x89\xed\xab\xc5\xca\x07\x0f\x77\xc1\xec\xd1\xd5\x2d\x53\x85\x28\x9f\x17\xce\xd7\x68\xc3\x97\x16\x71\xb9\xc0\xb2\xf8\x55\xb8\x46\x1c\x1e\x74\x6c\x7b\x38\xf7\x78\x96\xb8\x5a\xfb\xbe\xdd\x08\x37\x5f\xe9\x22\x98\x46\x14\xdd\x84\x9f\xe2\xcb\x89\xae\x71\x49\xdc\xd1\xd3\x7f\x49\x36\xe6\x7b\x14\x40\xbe\x72\xe0\x09\x39\x8b\xe6\xf0\x83\xbf\x96\x11\x48\x0b\x59\x2f\xe2\xf0\x11\x8e\x25\x3d\xb5\xd2\xe9\xe4\xb4\x54\x1c\x11\xda\x00\xf7\x16\x1a\x73\x6e\x5f\x0b\xb9\x34\x20\x8e\x3e\xf4\xe0\xb9\xa5\x22\x58\x20\x3f\x06\x0d\x18\xa1\x95\x15\x9e\x5e\x26\x8a\xa2\x80\x53\xc8\x34\xf7\xbd\x5d\xb9\xbd\x71\xf5\x07\xd9\x13\x70\xb3\xff\xca\xbb\xd4\xac\xb3\x07\x1d\x3f\x6d\x52\xc3\x49\xac\xf3\x50\x95\x34\x8c\xeb\xf5\xa8\x6f\x8c\x59\xdd\xc9\x65\xef\xf6\x10\xac\x42\x58\x04\xc0\xe2\xf6\xbe\x42\x85\x3f\x5b\x46\x43\x4a\x2c\x31\xd9\xac\x99\x53\x9b\xfd\xc0\x4e\xcf\x2f\xef\xd0\x45\x98\xfa\x63\xc1\x39\xff\x6c\x6d\x88\x41\x0e\x73\xbd\x32\x8c\xc4\x34\x9a\xb4\xbb\x86\xf2\xe2\xed\x7c\x73\xde\x96\x52\x0e\xf7\x73\x0e\xf3\x83\x45\xe0\xf9\x72\xa8\x4c\x53\x88\x10\x36\x87\xe6\x8c\x50\xf9\xd8\xc9\xaf\x90\x3b\xc6\x32\xd4\x32\x04\x06\x2a\x4f\x50\x2e\x21\x4c\x07\x05\x9c\x2c\xbe\xf7\x2a\x54\x11\x0d\xbf\x73\xe4\x25\x40\x2d\x17\xe9\x78\xec\x19\x9b\x51\x8c\xec\x03\x10\xbf\xbf\x7d\x9a\xd3\x00\x43\x4a\x4a"}, -{{0x08,0xda,0xbd,0x4e,0x5c,0x11,0x9e,0xa9,0x07,0xce,0x45,0xf0,0xa7,0xaf,0x9e,0x62,0xc0,0xc3,0xf1,0xc9,0xec,0x61,0xad,0x10,0x56,0x7d,0x79,0x36,0x28,0x54,0xc5,0x57,},{0x94,0x54,0x06,0xb8,0x5d,0x7b,0x32,0xe0,0xb1,0xab,0x12,0x00,0xb9,0x42,0x22,0xde,0x1a,0xaa,0x68,0x62,0x4c,0x60,0xbb,0x47,0x16,0xb0,0xbc,0xe9,0xdf,0x00,0x57,0x71,},{0x33,0xad,0xbf,0xcd,0x4e,0xd4,0xfa,0x67,0xc5,0x8b,0x5c,0xb5,0x9e,0x16,0x98,0x71,0x48,0x69,0x78,0x12,0x66,0x0b,0x35,0x31,0xff,0x6a,0x21,0xc7,0x49,0xb9,0x60,0x16,0x60,0xba,0xee,0xe2,0x48,0x9b,0x82,0xb4,0xcd,0xe1,0x32,0xb6,0xe6,0x2f,0x2f,0x90,0xd8,0xf9,0x92,0x78,0x60,0xaa,0xad,0x25,0x28,0x1d,0x03,0xeb,0x17,0xa9,0x52,0x0f,},"\x6c\x47\x19\xa5\xa2\xa6\x89\x48\x35\xc4\xac\x1e\xd6\x91\x59\xe5\xeb\xb5\x69\x2a\xd8\xea\xad\xa4\x39\xf7\x9e\x96\x68\x4b\x36\xce\xcf\xb4\x4b\x89\x01\x56\x31\x66\x3e\x06\x44\xf6\xc7\xab\x71\x39\x89\xd7\x42\xda\x27\x42\x72\x53\x31\x8a\x52\x43\x2d\xfa\xb2\x12\x1d\x1e\x92\x33\xea\xd7\x19\xe2\xc8\x6a\x6b\xe0\x73\x63\xd0\x02\x17\x3f\x20\x54\x46\xca\x95\xfc\x17\xb2\x46\x35\x82\x7f\xe3\x15\xf2\x22\x40\x8e\x45\xe8\x33\xf2\x9f\xf0\x8f\xf3\x1d\xac\x58\x3a\x4b\xec\x70\x76\xd5\xcc\x78\xcf\xc9\x44\x51\xcb\xf4\xf7\xe2\xfc\x5b\x5e\xd8\x07\x0f\x4e\xf8\x08\xbe\x1d\x8a\x68\x0e\xcd\xff\x59\x01\x0f\x39\xb1\xde\x80\xbe\xf1\x71\x9f\x1e\x21\x8e\x0c\xe0\xa1\xe3\x93\xa5\x66\xc5\x17\x64\xd2\x37\x0d\x95\xa6\x11\x91\xd8\xf7\xaf\x74\x0d\xc2\x08\xfa\x78\x31\xb2\x10\x67\x05\x12\xcd\x73\x76\x6e\x60\x9e\x9b\x78\x00\x21\xeb\xb2\x0c\xc8\x79\x0d\x8d\xa5\xf1\x0f\x5b\x6a\x11\x4a\x1d\xb8\x8f\x66\x76\x65\x01\x80\x2d\x9c\x36\x6e\xa3\xfa\x6f\x1b\x1e\x1e\x8b\x04\x20\x94\x34\x13\xcc\x6f\xea\xb2\x8c\x6b\x68\x3c\xd2\xb3\x33\x06\x9c\x89\x51\xbc\x45\xe8\xa1\x3b\xd5\x22\x57\x83\x51\xc8\x82\xf7\xc3\x42\xfe\x43\x31\xb9\x21\xf5\x33\xc9\x2e\xc0\x4a\x49\xb2\x92\xbc\x56\x9d\xdc\xef\xca\xb5\x72\x7f\x9b\x56\x25\xb1\x67\xa9\x02\xdc\x89\x6d\x8b\xc7\xd8\xe9\x99\x20\xf5\xdb\x8d\xd7\x67\x83\x9c\x43\xe3\xcd\xf9\x47\x08\x0d\xec\x95\x42\x14\xa6\xfb\xbe\x04\x87\xa2\xf3\x2c\xd1\x7a\x6b\x00\x03\x70\xbd\x41\x44\x84\xfb\x73\xc5\x10\xea\x01\x24\xc6\xcf\x0f\xe5\x6c\x08\x46\xa7\x9b\xfc\x59\x77\x9d\x3b\x07\xa1\xbd\x2c\x7f\xb7\xe2\xd0\x03\x9f\x0b\xd2\x1c\x8a\x30\x8f\xb0\xf5\x8f\xdb\xf9\x4e\xfa\x08\x57\xac\x3b\xdd\xdd\x86\xd5\x76\x3e\x20\x5e\xe1\xb2\x21\xf0\x60\xce\xdb\x8b\xc0\x5f\x03\x1b\x60\x6c\xc7\x4d\xad\xc5\xdb\x04\x23\x27\x48\x86\x5a\x73\xd6\xcc\xdd\xb4\xd5\xe9\x30\xd5\x28\x34\x8c\x5b\xe9\x08\x8b\xfe\x34\x45\x84\x87\xa6\x7b\x19\xa1\x8e\xca\x25\xc0\xd3\xfb\xe2\x19\x5e\xb9\x17\x07\xb6\x5d\x91\x61\xea\x93\xed\xdd\x64\xa6\x34\xb2\x32\x80\x19\x5f\xdb\x0d\x13\x88\xf6\x99\x8e\x18\x58\xa4\x5b\x88\x69\x99\xb8\x44\xe6\x79\x5d\x83\xd3\x18\x37\xe4\x41\x1f\x71\x69\x92\x26\xde\x1b\xa0\x24\x56\x08\x00\x0d\xcf\x22\x3d\xd1\x83\x59\xb7\xc6\xd4\x59\xa6\x5d\xbe\x66\xc9\x0f\x5c\xb8\xc0\x91\x22\x18\x7a\x30\x46\xa1\x6d\xd1\x79\xc3\xf4\x37\x3e\x57\xcf\x5e\xe0\xea\xb6\xa2\x12\xcc\x9e\xd8\xb5\x4b\xf3\x7f\x1d\x27\xfb\xd7\x98\x48\xe4\xec\x1f\x56\x72\x43\xab\x87\x40\xa0\x51\x49\xd9\x60\x2e\xad\xa9\x20\xa4\x6d\x61\x0d\x3c\xc8\x23\xb5\x64\x98"}, -{{0xe0,0xf7,0xd0,0x08,0x24,0xc5,0xf3,0x70,0x1e,0x55,0x17,0xa4,0xab,0xc1,0x3e,0x2f,0x2c,0x0b,0x13,0x8c,0x83,0x69,0x77,0x84,0x3b,0xbd,0x1e,0xef,0xfa,0xbd,0x96,0x8a,},{0x52,0xfd,0xda,0xe3,0xe0,0x18,0xa6,0x84,0x73,0xb3,0x16,0x8d,0x07,0x64,0xcf,0xe2,0x74,0xdc,0xc8,0x34,0xc9,0x0a,0x91,0xfb,0x4f,0xe7,0x4b,0x93,0x9d,0xd2,0x38,0xb1,},{0xcc,0xdf,0xe1,0x8a,0xd6,0xd0,0xb6,0x5d,0x08,0x6d,0x63,0x2f,0x83,0xcc,0x46,0xff,0x3b,0x3f,0x2c,0x07,0xbb,0x8e,0x76,0x9d,0x0f,0xb4,0xe8,0x2d,0xf8,0xa3,0x87,0x3f,0x9a,0xee,0x35,0xfd,0xd1,0x8a,0x57,0x83,0x60,0x31,0x80,0xa9,0x5c,0x9f,0x74,0xce,0xd9,0xdb,0x51,0x46,0xaf,0xcf,0xbb,0xdd,0x40,0xdf,0x29,0xe0,0x42,0x01,0x20,0x0c,},"\xb3\x9e\x3a\xc7\x5a\x22\x1a\xdc\xce\xd0\x9a\x85\x91\xac\x5e\x2f\xe1\x5d\xfe\xd5\xb9\x19\xcb\xaf\x14\xc6\x5e\xb7\xcd\x93\x08\x6d\xde\xe3\xf7\x47\x25\x47\xe6\x6d\xdc\x70\x06\x2b\x97\x62\x97\xd1\xa3\xc1\x70\xee\x52\x5c\x9c\x53\xba\x93\xa4\xc4\xfd\xb2\x35\x72\xb7\xca\x6e\xd1\x38\x53\xe7\x0d\xb1\xd7\x2e\xde\xb9\x94\x4b\xbc\x35\x4a\x52\x0e\x77\xae\x59\x1f\x31\x80\x92\xef\xd5\xe6\x6d\x9c\x09\x81\xc4\xa4\xbd\xa9\x8a\xa4\xe5\x90\x45\xff\x9c\x4b\x4c\xa3\xac\xb2\xff\xd8\x93\x20\x1c\x70\xb3\x4a\x77\xf2\x4e\xda\x54\x54\x9d\xc8\x4a\xd1\x34\xa3\x55\x32\x55\x38\x15\x88\x8a\xe3\xdd\x9e\x24\x1e\xc4\xeb\xbf\xf8\x6f\x8c\x1e\x8a\xdb\xaa\xc4\xb9\x1a\xfd\x18\x22\x8c\xbb\xd5\xdd\x80\x5a\xca\xbf\x0a\x1e\x29\x0c\xe5\xdd\xa0\x25\x1a\xdf\xb3\x7c\xb7\x14\xc1\x39\xb5\xa3\x24\x2d\x88\xc6\x44\x84\xa3\x76\x55\xcc\x8f\xcb\xec\xff\xa9\x7f\xbd\x14\xd6\x4d\x51\x2b\xf8\xf6\x30\x5f\x89\xc5\x09\x22\xde\x54\x16\x92\x15\x8f\xb5\x47\xfd\x53\x9f\x1e\x58\x77\xcc\x64\x94\x95\x16\x63\x32\xea\x2b\x68\x5c\xfa\x3f\x60\x20\x19\xdf\x2a\xb2\xc2\x5e\xd9\x6b\x68\x74\x5e\x9a\xe8\x9c\x94\x8d\xa1\x1a\xd8\xa8\x30\xdf\x8b\x00\xf2\xe6\x68\x19\x2d\xad\xf2\xc5\x62\x0d\x35\xc6\xe8\x1a\x28\x53\xf8\x41\xe3\x75\xa0\xd9\xfc\xa2\xd2\x96\xef\xce\x2a\xc3\x8d\x40\xb0\x30\xb5\x75\x60\xae\x6e\x83\x41\x33\x9b\x3d\x3c\x2d\x06\x11\x64\x12\x43\x19\x59\x86\x88\xfc\xa6\x18\xfc\x64\xc9\xe8\xf5\xf8\x31\x09\x7a\x05\x3a\xf1\x9d\x7d\xbd\x61\x21\x8d\x92\x67\x42\xc2\xe9\xa4\x2a\x79\xcc\x1b\x14\x89\x12\x72\x2d\x8c\xd5\xca\x79\x3a\x1a\xd7\x3b\x5f\x14\x1b\x41\x80\x9c\x2f\xc0\x53\x0b\x76\x30\xe8\x03\x90\xc6\xb3\x38\xc7\x18\x68\xda\xcc\x59\xbf\x46\x3f\xfc\x48\x90\x16\xbf\x67\xf9\xc9\xd5\x55\x3c\x1e\xde\x17\x15\x28\x13\xfe\x0b\x26\x4b\x65\xdc\xa1\xb2\xb3\x8e\x4b\x80\x9f\x8c\x97\x25\xac\x5b\x1d\x8d\x2e\x56\xbe\xc9\x64\x9f\xe5\x5c\x75\x83\xff\x23\xb0\x43\xd6\xf3\x76\x86\x28\xf1\xf0\x51\x63\x37\x82\x4a\x5a\x56\xb4\x09\x52\x0a\x6a\x6c\xb7\x7e\x4f\x5f\xc2\x0b\x9f\x68\x99\xe0\x0a\xb2\x2d\xb1\x0d\x18\x2f\x09\xb8\x1e\x94\xf3\xad\x56\x8a\x0b\x81\x24\x4d\xf3\xf1\x85\x5c\x6e\xf2\x22\xa4\x1a\x51\xb6\x2a\x46\x49\xbb\x82\x69\x0a\xb6\x5f\xac\xac\x0d\x81\xd6\xfe\x02\x60\x11\x70\xa8\xdb\x62\xcb\xc5\xec\x99\x55\xd7\x71\x1a\x1c\x39\x65\x6a\x9f\x6e\x1f\xb6\xbc\x18\x3d\x9b\xea\x15\x03\x53\x1f\x17\x36\x27\x68\xbb\x84\x1f\x9d\x21\xf1\x3a\x2c\x99\x1e\x55\xdf\xf7\xf2\xb3\x36\xe2\x9e\xb2\x95\x07\x63\x8b\xdc\xad\x7b\xb3\x1c\x69\xe9\x09\x20\x7e\xba\xbc\xc6\x53\xff"}, -{{0x6a,0xcd,0x93,0x9e,0x42,0x22,0x26,0xcc,0x54,0x43,0xd4,0xaa,0xbf,0x58,0xc1,0x1a,0xf6,0x50,0xcb,0x40,0xb9,0x64,0x8b,0x4d,0xa3,0x8b,0x92,0x7b,0xff,0x9a,0x58,0xdb,},{0x4c,0x0b,0x91,0x75,0x6b,0x9e,0x20,0x6f,0x78,0x63,0xb1,0x55,0xff,0xc5,0x50,0x9b,0xb5,0x24,0x77,0xce,0xac,0xd0,0x1c,0xa0,0x11,0x43,0x51,0x53,0x67,0x86,0x46,0xcc,},{0x79,0x99,0x58,0x77,0xed,0x24,0xc7,0x91,0x68,0x4f,0x29,0x84,0xbd,0xf9,0x60,0x9c,0x3f,0x7b,0x57,0x6c,0x57,0xd1,0x62,0xee,0x62,0x2d,0x4c,0xe8,0xf3,0x6d,0x9c,0x55,0x73,0x16,0x9d,0x88,0x01,0x21,0x6f,0x1c,0x46,0xff,0xe2,0xf6,0xe2,0xc0,0x90,0x48,0xe4,0x7d,0x4b,0xeb,0x99,0x7e,0x9a,0xbc,0x4a,0xbb,0x12,0x9f,0x9b,0x79,0x69,0x0a,},"\x82\x50\xd5\x31\xcf\x2b\x66\xaa\xc2\xb3\x78\xd5\x4b\xc5\x7f\xd3\x29\xad\x5a\x41\x4a\x59\x92\x55\x89\x8b\x3c\x3b\x45\xbf\x9c\x0d\x2c\x77\x54\x75\x66\xb6\x60\xee\xcc\x76\xa6\x95\xa2\xd6\x08\xab\xf1\x1a\x5f\x6d\xb3\xe6\x07\xfd\x5a\x21\x71\x4b\x0f\xad\x5d\x81\x4c\x01\x5e\xbf\x48\xbb\x73\xad\x75\xda\x9c\x03\xc4\xaf\x54\x89\xe7\x82\xb6\xbf\x79\x08\xa1\xbd\x52\x8d\x7c\xe7\x88\xa1\x8b\xa3\x52\x8e\x35\x37\xaa\x7b\xbf\x75\xf6\x52\x4b\xbd\x19\xa5\x30\x4b\xa2\xa4\xa3\xee\x58\xc4\x1f\xec\x31\x32\xee\x65\x01\x64\x12\x15\xef\xf7\x46\xd7\x80\x0c\x4d\x33\xf5\x2b\xe8\x35\x7e\x0e\xe7\x58\x04\x1d\x91\xcf\xe4\x3c\x60\xc3\xce\xdc\x09\xb0\xd4\x6d\x4c\xfb\x9a\xe2\xa0\x23\x9b\x6f\x33\xc6\x94\x1c\xff\x35\x37\x26\x70\xee\xf5\xc8\x85\x9a\xb6\x5b\x6e\x9f\x7e\xbc\xe3\x2f\xa1\x5a\x9a\x47\x7a\xec\xdc\x96\x83\xa1\xe3\x3a\x1e\xdc\xdc\x90\xd4\x20\xa3\x1e\x78\xc1\x53\xd2\x60\x20\x87\x1d\xaa\x4f\xff\x28\xac\xc3\xf1\x1a\x72\x06\x78\x88\x06\xb6\xfa\x02\x34\x68\xea\x5a\x3d\x18\x6d\x10\xf0\xdd\x56\x77\x96\x66\x3b\xa3\x7c\x83\x2f\xe7\x5a\xae\x7d\xcc\xeb\xf3\x19\xf9\x36\x00\xc4\x6a\x22\xf5\x72\x23\x81\x2d\xdd\x0a\x68\xd7\x6b\xaf\x5e\x27\xa9\xfc\x8b\xd6\x8c\xc1\x0b\x5b\x51\x51\xd6\x2b\x41\xf9\x34\x8e\x21\xb7\x15\x35\x2f\x26\x30\xb6\x17\xf8\x13\xb0\xc2\x89\x96\x28\x59\x04\xcf\x29\x4e\x9c\x28\x56\xb1\x7b\xa3\x5f\x9a\x82\x19\x8b\x82\x14\xa0\x35\xe2\x89\x6d\x65\x68\xbe\x42\x39\x2c\xce\xf3\x2c\xd4\xeb\xfe\xeb\xf1\x2b\xe0\x12\x52\x06\xbb\xe8\x93\x36\xd3\xe7\x62\x99\x1d\xfa\xb6\x8f\xc9\x9d\xc1\x64\x9b\x89\x13\x83\xdb\x31\xfa\xb6\x49\xe6\x28\x82\x3f\x45\x98\xcb\x63\x6a\x38\xfe\x1d\xf7\x3e\x68\xd7\x42\x5f\xc5\xd2\xeb\x55\xa0\xfd\x1b\xc9\xf5\xce\xaa\xbd\x6d\xd4\x1f\x23\xe4\xf0\x86\xc6\x92\x63\x3d\xc3\xc4\x61\x9a\x97\xab\x0e\xad\xa1\x71\xf8\x4a\xdf\x20\xec\xc8\xec\xd4\x7c\x51\xcc\xa3\xe5\x9d\xd8\x09\xb0\xae\xaa\x73\x0d\xf9\x4b\xe3\xba\xcf\xd8\xee\x88\x8b\xba\x9d\x57\x08\x50\x65\x2c\xd4\xd5\xe6\xc5\x52\xa5\x7e\x9f\x48\xa2\xb0\x6a\xac\xdc\x70\x8d\x84\xa3\x76\xfb\xc6\xc9\x4b\xa6\xbf\x64\xa5\xf0\x18\x80\x0a\x7c\xc8\x51\x24\x5a\xed\xb2\x03\x78\xb3\x29\xac\xeb\xb2\x97\x7c\x13\x98\x08\x2b\x3a\x0e\x5e\x2a\x9c\x24\x84\xfa\x30\x1d\x30\x37\xa8\x22\x4d\xdc\xc0\x95\xb1\xdb\xd8\xa2\x31\x5b\x55\xbf\x33\x18\xc2\x78\x10\xef\xc3\xd8\xe2\x5f\xa7\xa8\x78\x9b\x73\xa4\xf5\x50\x59\x08\x0b\x08\xab\xb3\x69\x9b\x7b\x86\x26\xcb\x2a\x78\x0d\x97\xcc\x1c\xa8\x03\x28\x51\xba\xf4\xed\x8b\x64\xfc\x43\x30\x86\x5f\x84\xcc\xb1\x2a\x3d\xae"}, -{{0x4d,0xef,0xf6,0x47,0xcb,0xc4,0x5e,0xca,0xed,0xc3,0xf7,0xdd,0xf2,0x2c,0x16,0x7a,0xf2,0x4e,0x3d,0x63,0xda,0x22,0xb0,0xe6,0xa5,0xb8,0x43,0x9c,0x0f,0x3b,0x19,0x34,},{0x0c,0x27,0xc9,0xd7,0x7a,0xc8,0xc7,0x25,0xbb,0x06,0x63,0x93,0x3a,0xb3,0x0d,0x1a,0xad,0x09,0xcb,0xcf,0x2c,0xd7,0x11,0x6c,0x60,0x85,0xa8,0x49,0x9f,0x70,0x14,0x02,},{0xdd,0x54,0x89,0xfd,0xe4,0xba,0x87,0xd1,0x17,0x3d,0x4c,0xee,0x06,0x82,0xaf,0xdd,0x4b,0xad,0x80,0xdd,0x77,0x0e,0xa7,0xd0,0xdc,0xeb,0xaf,0x21,0xac,0xc6,0x1d,0xd6,0x32,0x4a,0xca,0x29,0x5e,0xd0,0xe2,0x3a,0x91,0x5e,0xcf,0xda,0xd5,0x0f,0x17,0x5e,0xbc,0x51,0x6f,0x1b,0xe5,0xb6,0xd8,0x7d,0x90,0xbb,0xe3,0x86,0x22,0x49,0x53,0x02,},"\xd6\x20\x1e\xbc\x21\xce\xc1\xe9\xbc\x28\xf9\x57\xc9\xd0\x29\xcc\x38\xf9\xe8\x5e\x06\xdf\xc9\x0b\xf2\x97\xe6\x1f\x2b\x73\xb4\x07\xd9\x82\xa6\x6b\x91\xe9\x4a\x24\xe9\x1d\x06\xab\x8a\x5c\x07\x9d\x0f\x69\xbe\x57\x88\xea\x8f\xea\xce\xbd\x91\x72\x91\x19\x22\x33\x86\x2e\x6a\xcd\xa1\xe8\xcf\x9a\x48\xbf\xfb\x54\x91\xdd\x65\xaf\x54\x1b\x6c\x72\xaf\x68\x1a\x81\x82\x3d\x98\xa0\xab\xee\xb6\xba\x9f\x95\x46\x5b\x84\x11\xf9\x9e\x11\x9c\xd2\x84\x79\xda\x98\x42\x59\xbd\xf8\x6c\x9f\xef\x3c\xca\x34\xe2\x24\x69\x1f\x18\x3c\xf0\x95\x03\x77\x27\xda\x9c\xad\x29\xf2\x42\xf8\x3e\xb4\xf7\x36\xe2\x7f\xdf\x67\x01\x8d\x71\x1b\x74\xc4\x5b\x29\x55\xa6\xa7\x6e\xc1\x53\x30\xdf\x5b\xad\x80\x30\xc6\xb3\xa8\x8d\x72\xf2\x84\x47\x65\x2a\xc8\x90\x2b\x5b\x76\xcb\xf6\xb9\x45\xce\xab\xfe\xc0\x4a\x9b\x8c\xb3\x0f\x43\xd9\xeb\x77\x3e\x67\x05\x59\x4f\x0d\xe1\xb7\x0f\x1a\x20\xc9\x9f\xc4\xb1\x22\x1f\x8c\x81\xb0\xbc\x30\xda\x12\xcd\x5d\xea\x8f\x4d\x90\xf1\x3a\x81\x1a\x2c\xc1\x1a\x96\x84\x6a\xaf\xb4\xc4\x2a\x00\xe9\xae\x7d\xa2\x56\xa0\xd2\x2b\x19\x8a\xfc\x25\xcc\x10\x41\xd2\x4e\x05\x6c\xf3\x87\x60\x1d\x7b\xf7\xeb\x31\x82\xd6\x05\xfe\x5e\x63\xb1\x8d\x53\x1a\x5f\x84\xe5\xdb\xd0\x18\x4a\x76\xc6\xc4\x67\xa8\x26\x3a\x98\xb5\xc0\x05\xfc\xb2\xaa\xf9\x89\xf5\xcb\xd0\xa9\xd9\x03\xfc\xfc\x60\x9d\x6e\x57\xd9\xc4\x39\x02\x1c\xea\x93\xe4\xc4\xe9\x91\xf1\x93\xca\xf3\x24\x37\x70\xb3\x25\x78\x74\x80\x76\xb7\xf4\xcb\x97\xf1\x7c\x17\xa7\x9b\x82\x25\x3c\x24\x23\xdb\x69\x8c\xd0\xa3\x3a\xb3\x3b\xb0\x9b\x0b\x08\xcb\x8c\xea\xdc\xa1\xe2\x9c\x5d\xe2\xfc\x12\xb2\x40\x7b\x6c\xc5\xaf\x5a\xe9\x76\xdd\x3e\xc6\x30\xd8\x33\x9b\x7d\xd1\x1f\xa3\x4c\xaa\xc1\x50\xc7\xc4\x79\x1d\x8c\x42\x7b\x0a\xd9\x2e\x05\x29\x06\x7a\x88\xd5\x20\x11\xe1\xe0\xa1\x82\x99\xb9\x69\x89\x6f\x8b\x83\x60\xf7\x5c\x45\xc4\x96\xda\x47\xb0\x9b\x45\x0f\x98\x22\xbc\xbc\xd4\x3f\x42\x93\xc5\x16\x80\x2b\xf7\x47\xc4\xab\xee\xdf\xaa\x3e\x79\xcb\x91\x03\xd3\x77\x0f\x56\x07\xb7\x75\x16\xe5\xb1\xce\x0f\x64\xb6\xee\xc7\xbe\xc3\xc6\x47\xc0\x06\x95\x6d\xc5\x5b\x6c\x79\xf6\xaf\xb3\x9d\x1f\xc3\xec\xf1\x1b\x97\x4b\x44\xae\xdb\x72\xae\xd1\x31\x66\x35\x08\x3c\x21\x24\x50\x2e\x5c\x72\xd8\x6e\xca\xb6\xac\x90\x24\x3e\xb3\x9a\x6a\xa9\xcb\x94\x80\xda\x38\xe1\xed\xb8\xd2\x8f\xf9\x09\x24\xc0\x5d\x5d\x21\xaf\x5a\xf9\x59\x57\xb8\x02\x07\x81\x37\x87\x11\xa2\x9d\x09\x20\xac\xad\x8c\xcb\x39\xa3\x11\x69\x32\x78\xc9\x90\x0b\x47\x0d\xa2\xbd\x4c\x12\xa0\x1d\x73\x96\x26\x44\x01\x7b\x60\x34\x71\x3b\x2a"}, -{{0x5a,0x19,0xbf,0x6c,0x94,0x1f,0x39,0x4e,0x93,0xbd,0x36,0x25,0xfb,0x81,0xcd,0x9d,0xa8,0x1c,0x90,0x20,0xb1,0xc5,0x31,0x25,0x7a,0x7b,0x59,0x57,0xbb,0x07,0x92,0x11,},{0x20,0xe8,0x69,0x9d,0x08,0x7c,0xe5,0xe8,0x15,0x1d,0x28,0x05,0x3d,0xce,0x66,0xc2,0x3f,0x28,0x08,0x1f,0x35,0xbd,0x26,0x81,0x9b,0xbe,0x85,0xd3,0x8a,0x09,0xd7,0x02,},{0x2a,0x2f,0xd6,0x05,0x4e,0xf4,0xe7,0x9b,0x72,0x19,0x1a,0x0c,0xcb,0xd2,0xb1,0x8a,0xeb,0xab,0xe8,0xb9,0xa7,0x18,0x61,0xde,0xd9,0x8b,0x7c,0xdc,0xb6,0xa6,0x25,0x53,0x28,0xbc,0x1a,0xec,0xb0,0xc9,0x33,0x57,0x21,0xa9,0xa9,0x6e,0xe4,0xb5,0xb4,0x3f,0x90,0xd3,0x22,0xec,0xf8,0x35,0xf7,0x8b,0x26,0x4d,0xae,0x6e,0x38,0x7b,0xfb,0x04,},"\xf7\x21\xca\x3a\x32\xc1\xe8\x1c\x9c\x6f\x46\xd5\xe1\xfb\x50\xe7\xce\x2f\x4e\x70\x93\x33\xca\x2b\x55\x0d\x52\x13\xb6\x77\x3d\x67\x0c\xa5\x9a\x2b\x50\x86\xa4\x43\x84\x3a\xc5\x08\x13\xb2\x44\xc9\xc9\xfa\xc6\xd1\x19\x69\x89\x27\x81\x35\x12\xc8\x4f\xe3\x0a\x89\x55\x30\x10\x13\x8f\x91\xe8\x17\x6f\x5c\xf2\x57\x89\xd7\x28\x1d\xdb\x83\xa2\x46\x70\x5d\xcc\xb9\x99\xc4\xcd\x0a\xe2\x19\xc6\x45\xf6\xd7\x1d\x45\x1a\xe1\xf8\xd2\xf9\x89\x1a\xf8\xcc\xce\x03\xf4\x38\x55\x9f\xb8\x36\x67\xb8\x07\x7f\xbe\x43\x5a\x74\x4a\xf0\x19\xd6\xd1\x39\x9f\xd2\x13\x7f\x5a\xfb\x8e\xf3\xf4\x7b\xcf\x73\x5e\x7c\x9e\xd8\xa5\x4b\xa0\xc1\xc6\x56\xb6\x65\x0b\xb3\x0a\xdb\x1d\x57\xec\xd2\x07\x46\x39\x49\x42\x31\xa2\xe9\xe2\xf9\x85\xed\x84\x22\xee\x03\xcb\x3f\xd7\x38\xc7\x35\xa1\xb8\x28\x06\x04\x74\x60\xed\x84\xf7\x46\x8c\x3c\x64\xb3\x5d\xb0\x6b\xc5\x8d\xe4\xbb\xa4\x63\xe6\x38\xa9\x41\x33\xdf\x10\x6a\xc4\xf4\x70\x36\x1c\xcd\xe4\x41\x57\x29\x9d\x22\x5b\x17\x79\x88\x91\xba\xf5\x92\x19\x86\xa2\xba\xe3\x26\xdd\xa0\xb8\x96\x17\xc6\x77\xbd\x14\x08\xba\x27\x48\xba\xa6\x7c\x8a\x2c\x5a\x96\x9b\xc0\x0c\xb4\x0d\xbf\x49\x0e\x07\xe2\x2c\x91\x3a\xfd\xde\x63\x04\xa0\x7f\xc9\xe6\x08\x46\x99\x24\x56\xbf\xb0\x66\x3a\x09\xde\xf6\x8d\xef\x67\xa1\x6d\x29\xe9\x8c\x7b\x55\x35\x18\x48\xa8\xcf\x92\x31\x0c\x74\x63\xc4\x75\xf2\x49\xc6\xf7\x55\x7f\xd0\xd7\x55\xca\x88\xf8\x77\x84\x7f\xe0\x76\x57\x56\xac\x34\xa2\x3f\x78\x40\xd9\x5c\x3d\x29\x4e\x66\x3b\xb1\x51\x8b\x75\x92\x7c\x41\x07\x57\xe0\xf5\xc0\x7c\x5a\x7f\xb2\x15\xdc\x72\x07\x43\x3e\xbf\x79\x1e\xdf\xce\xc9\x0e\x93\x0f\x8e\x3b\xa9\xdb\xbb\x98\x54\x13\xc2\x23\xbe\x87\x87\x3b\xd3\x23\x99\x75\x81\x80\x4d\x88\x96\xda\x38\x6a\x6e\x91\x20\x05\x0a\x0e\xae\xd3\x12\x40\xaa\x17\xc7\xb6\x69\x4c\x30\xcb\xcc\x3c\x69\x56\xa6\x82\x0f\xc9\xab\x21\x87\x55\x33\x96\x3d\xc3\xb0\xd8\x83\x58\x27\x12\x76\xc6\x05\x65\x28\x91\x0d\xd9\x89\xae\x0c\x33\x0d\x17\x98\xf7\xd8\xe7\xd1\x18\x4b\x84\xa8\x14\x34\x32\x5b\x8c\x30\x2e\xdf\x60\x1d\xc5\xe6\xf8\x47\xfb\xac\xbd\xee\xff\x78\xc6\x62\x1d\x1d\xaf\xdc\x23\x9b\x18\xb8\xc1\xaf\xdc\xb4\xb9\xda\xbd\x5d\x3a\x92\xa9\x32\xea\x15\x99\x54\x6e\x62\x5f\x96\xd6\xec\x6f\xb1\xcc\xcb\x76\xb4\x76\xb3\x30\xac\x59\x25\x9c\x63\x4f\xac\x9b\x3f\xa7\xde\x7a\xe7\x05\x37\x73\xb5\xbe\xfa\x00\x1b\x04\x92\x9f\x74\xb7\x12\x41\xe1\xb2\x57\x69\x6d\x65\xa2\x6c\x1b\x4a\xc8\x6b\x7b\x1f\xbd\x69\x57\xfb\x9b\x95\x08\x4c\xe7\xd7\x00\x90\xf5\x5d\x44\x53\x46\x94\x30\x5e\x91\x76\x9a\x82\x94\x13\x04"}, -{{0xb5,0x06,0xc0,0x1d,0x69,0x74,0x6e,0xb4,0xbc,0x63,0x58,0x72,0x0e,0x43,0x8a,0xd3,0x30,0xc8,0x8b,0x60,0x5a,0xad,0x65,0x2f,0x47,0x99,0x57,0x3a,0xb0,0xa1,0xaa,0xf9,},{0x7a,0xc8,0xb6,0x88,0x63,0xbd,0x69,0x15,0x15,0x83,0x78,0x9d,0x86,0x4a,0x73,0x57,0xe3,0xa0,0x45,0xfa,0x86,0x52,0x2a,0x9d,0xaa,0x6e,0x26,0xfb,0x79,0xed,0x6d,0x23,},{0x17,0xa1,0x9d,0x26,0x91,0xb7,0xb0,0x46,0xd7,0xb1,0x96,0x69,0xad,0x73,0x14,0x0d,0xb9,0x2f,0x0c,0x97,0x8c,0x7f,0x61,0xbc,0x38,0x67,0xd9,0x2c,0xa9,0xd4,0x75,0x80,0xa0,0x38,0x0b,0x59,0x01,0xba,0xd8,0x2a,0xf4,0x5f,0x67,0x6f,0x74,0x28,0x73,0x01,0x98,0x0f,0x71,0x87,0x1a,0x42,0x26,0x1d,0xbe,0x08,0x02,0x95,0x03,0x36,0xe6,0x0b,},"\xf7\xfc\x18\x06\x6e\xd0\x4b\x30\xe6\x33\xd9\x86\x5d\xa3\x21\x4b\xec\xa6\x0b\xd7\x96\x01\x9c\xd7\xec\xc9\x18\x66\xf9\xef\x24\x46\xc1\xfa\xb0\x6d\x86\x51\xbe\x7f\x10\x1a\xec\x7b\xb8\x4e\xe2\x1e\x71\xad\x02\x02\x15\xfc\xfb\x36\xf2\xd1\x1e\x45\x79\xac\x39\xf8\xe2\xb1\x29\x0e\x38\x96\xd5\x22\xbc\xf5\x13\xaa\xa0\x67\x71\xf8\x6e\xe2\x28\xcf\xf3\xa2\x0a\x1f\x10\xc5\x64\x33\x95\x89\xbb\xa9\x60\x53\x44\xc0\xa6\xe6\x82\xad\x5b\xa4\x0d\x10\x41\x94\x1b\xc4\x6f\x98\xb9\xd0\x9c\xa1\x7f\x8f\x04\x4e\x98\x3b\x8a\x49\x08\x93\x3d\xf2\x26\x3c\xf7\x88\x11\xc2\x4c\x8f\x48\x14\x35\x4f\x6f\x4c\x68\xb7\xee\x7b\x78\x30\x82\x93\xbf\x78\xfd\x0f\xf1\x22\xf0\x95\xc1\x4a\x73\xa5\x97\x97\x17\x2a\xe0\x5c\xfc\xec\x19\x56\x3e\xb1\x8d\x2b\xc5\x30\x0e\xd4\xbf\x6b\xdc\x44\x3e\xa9\xb8\xbc\x1c\xbe\xde\x94\xca\xb9\x05\xed\xa5\xa6\xa9\x31\x59\x7d\xe4\x02\x14\x6f\xac\x9c\xf8\xcd\x6a\x8d\x10\x46\x69\xf9\x13\xfa\x83\x40\x01\xca\x4d\x09\x0f\xb7\x94\x9d\x31\x09\xa6\x3c\x05\x49\xb0\x3f\x15\x1b\x71\x17\xc4\xf4\x69\x74\xba\x59\xc6\x82\x96\xed\xfd\xde\x76\x92\xee\x43\x2a\xce\xf7\x61\x06\x47\xe0\x95\x78\x65\xe6\x2c\x1a\x0c\xf0\x56\x59\x82\x3a\x55\x45\x2d\xd5\xe4\x71\xb3\x1c\x5a\x49\xab\x05\xb5\xaa\xfd\x5a\x0e\x53\x0e\x89\x6b\x58\xcc\x52\x2e\xcf\x19\xe5\x2e\xc8\x2f\xa1\x47\xf9\xe3\x85\x17\x4c\x7e\xc3\x3d\x1d\x9b\x86\x93\x4a\xeb\x4f\x6c\x57\x00\xf7\xd5\xeb\x33\xff\x73\xc9\xfc\x6a\xa4\x7d\xf5\x1e\x09\x22\x9e\x6a\xe8\x94\xe8\x6c\x81\x8b\xef\x06\x5f\x82\x59\x71\xa4\xcb\x90\xad\xfe\xfb\x31\xeb\xd9\xd1\xb7\x94\x22\xdc\x98\x68\xf9\xf7\x4e\x7a\x32\xcd\x40\x71\xef\xb6\x9b\x27\x23\x3e\x6e\x5c\x60\xde\xdc\xd5\x32\x1c\x03\x0a\x46\xcd\x26\xf5\x60\x2c\xac\x74\x7e\xe4\xb5\x22\xd8\x57\xa3\x32\x1a\x03\xf4\x03\xa6\x00\x62\x50\x40\x63\x61\xe4\x88\x15\xaf\xba\x77\xce\x08\x90\x34\x41\x84\x5b\xa8\x72\x25\xd8\xb2\x40\x46\x74\x5d\x40\x65\x64\x5a\x1b\x98\x41\x0c\xac\x48\xd1\x37\xcb\xbb\x8a\xb1\xeb\xa5\x0d\xa9\xc2\x31\xe9\xac\xf3\x22\xa6\xdb\xec\x0e\xf4\x16\xa4\x46\xc3\xb6\x10\xd9\x35\x69\xfd\xf4\x5a\xa6\xcd\xc1\xb6\x40\xd8\xf3\x01\xd7\x86\x93\xb2\x82\x6c\xc6\xed\x46\x85\x68\xad\x9a\x0f\x94\xaa\x9b\x9f\xb9\x2f\x7e\x78\xd4\x84\xfd\xf5\xd8\xd4\x5c\x99\x1e\x28\x07\x4d\xcd\xd6\x80\xd3\xb1\xf1\x89\xef\x6b\xdc\x32\x0e\xe6\xe6\x4d\xd1\xf8\x0d\x92\x64\xd8\x30\x42\xd2\xc4\x3d\x83\x58\x1e\xf0\x39\x4b\x1b\x5d\x1f\x69\xf3\xbb\xbf\x04\xb7\xc8\x08\xba\x34\xc1\x58\x0f\x16\xf7\x65\x37\xb6\xa7\xeb\xd0\xa1\x90\x8b\xe9\x49\x4d\x3f\xca\xa9\x87\x1d\xb1\x57\x50"}, -{{0xe1,0xcc,0xb8,0x0a,0x26,0x2f,0xf8,0xaf,0x1e,0xda,0x07,0x5c,0x97,0x2c,0x8e,0x94,0x1e,0x77,0xce,0xf5,0x7b,0xdb,0x0a,0x82,0x57,0x2c,0x28,0x20,0x0b,0x49,0x3c,0xa3,},{0x3d,0x37,0xe2,0xa5,0x02,0x7e,0xff,0xde,0xe0,0x7f,0xa5,0x11,0xe4,0x23,0xb2,0xbc,0x56,0xed,0xce,0xa0,0x75,0xb4,0x16,0x49,0x76,0x67,0x25,0xc6,0xb3,0x0a,0x10,0xf4,},{0xfd,0xa3,0x4b,0x65,0x2b,0x79,0x74,0x6f,0x89,0x7e,0x22,0x2d,0x37,0xb7,0x7a,0xa2,0x50,0xd0,0x2c,0x52,0x7c,0x48,0x33,0xdf,0x80,0xea,0x41,0xd5,0x21,0x89,0xd5,0x07,0x00,0xe1,0x28,0xb7,0x8e,0xe8,0x14,0x9c,0x9b,0x19,0xf3,0xab,0xf7,0x55,0xac,0xef,0x53,0x48,0xf5,0xfb,0xaf,0x1c,0xeb,0x41,0xc0,0x38,0x90,0x6a,0xc5,0x94,0x60,0x01,},"\xcf\xdc\x54\x97\xb0\x23\xaf\xa6\x2a\x7f\xe5\x92\xca\xa9\x2b\x87\x5c\x77\x05\x74\x78\x34\x00\x2f\x77\x84\xff\x16\x61\x89\x39\x88\x15\xd4\xe8\xa7\xa0\x03\x8e\x1f\xda\xdd\xde\xba\x51\x05\x73\x27\xad\x19\x60\xe8\x59\xce\xe5\x65\x26\xbb\xb4\x12\x7b\x6a\x5f\x90\xd0\x4d\x08\xb1\x5e\xee\x66\xc9\xcc\xf8\x8b\x4b\x7d\x1e\xe9\xd3\xb8\xb8\xc6\xf4\x2d\xb3\xc3\x4e\x59\x04\x8a\x15\xc6\x04\x1f\x14\x2c\x40\x79\x36\x8b\x7b\x11\xe2\x99\x70\x11\x8b\x99\xe5\x67\x0a\xe3\x1f\xcc\xfd\xff\x13\x99\x14\x2e\xe0\x6b\x2e\x3e\x2b\x3c\x97\x07\xdd\x64\x11\x97\x86\xe2\xfa\xb4\x7e\x0b\xad\x2c\xc8\xb5\x58\xd9\x63\xbb\x48\xa4\x9a\xd2\xc6\x37\xdd\x35\xb2\x5d\xb5\x4b\xc5\xa2\x63\x02\x22\xfa\x2a\xce\xce\x9c\xe1\x2a\xb0\x81\x30\x77\xf7\x65\x9f\x50\x74\x42\x9c\xa6\xb4\x94\x33\x10\x32\xae\x79\x2a\x59\x9c\x42\x5e\xe2\x97\x45\x1d\xcf\x5e\xe1\x95\x29\x03\x12\x74\x2e\x64\x7a\x77\x95\xb8\x4d\xcc\x66\x4d\xda\xe2\xa1\xfb\xf8\xc4\x54\x8a\x37\xfd\x82\xd8\x10\xe2\x14\x5f\x01\xdf\x1a\x6d\x3b\xcc\x42\xa9\x1a\x10\x76\x8e\x09\x1f\x3d\x69\x32\x9a\x7b\xad\x6c\x07\x2c\xac\x6d\x89\xaf\xa3\x1c\x02\x90\x56\xd6\xb6\x22\x12\x16\x5c\xeb\xcd\x49\xac\x67\x2e\x38\x30\x26\x7a\xf9\xf2\x8e\xa3\x19\xbd\x04\x2f\x6c\x59\xde\x47\x01\xe5\x82\x48\x73\x6c\x8d\x97\x6a\xcf\x93\xb9\x9d\x2f\x46\x47\xa5\x47\xd3\x92\x44\x7a\x48\xda\xc1\x11\x81\xe1\x6b\x15\x01\xa9\x4c\x93\x16\xe5\xa6\x7c\x99\x0b\x35\x81\x0b\x4c\xda\x04\x73\xa6\xa4\xe5\x76\x14\x21\x58\x68\xe2\xe0\x02\xc6\x05\x8b\x42\xe4\xee\xec\x84\x13\x9d\xc1\x9e\xdf\x5f\x80\xae\xef\xfa\x4f\x5b\x07\xe8\xfd\x23\x13\x9e\xdd\xa3\x18\x99\xeb\xe6\xfe\xe7\x86\x43\xce\x68\x6b\x29\x63\xa3\x20\x72\xbd\x3b\x3b\xba\x68\x48\x5a\x05\xc2\xcc\x04\x56\xc3\xda\x50\xc7\xc8\xc6\x51\xa3\x06\x6d\x13\xa3\x66\x0b\xd4\x7a\xb6\xdf\xec\x49\xe0\x15\x57\xa6\x74\x28\x96\xaa\x4b\xc6\x36\x3a\x79\x7d\xba\xd1\xa4\x09\xcd\x4a\x50\x91\x1e\x70\xea\x00\x7a\xf8\xe9\xb1\xbb\x7e\x3a\xb5\x62\x15\xa5\x75\xc9\x0f\x73\x9c\x2d\x48\xb3\xb3\x46\x94\xb5\xac\xdf\x07\x98\x0a\xe5\x28\xde\x06\x21\xed\xfa\xc8\xb8\xfa\x84\x95\x4d\x56\xdb\xb4\xd0\x30\x82\xb9\x84\xf1\x3e\x5d\xbe\x9c\x71\x12\xff\x97\x16\xf5\x50\x53\x06\x46\x62\xce\x0f\xb8\x1e\xa3\x5f\x98\xfd\x2c\xd5\x11\x37\xa4\x6f\x64\xe0\xc1\xca\xf4\x4e\x54\x07\xdc\x96\x17\x60\xb2\x59\x7f\x7f\x92\x00\x61\x7d\x47\x13\x40\xcf\x15\x17\x6c\x3d\xa8\x80\xfe\x4e\x0e\x93\xa7\x2f\xb9\x49\x26\xfa\xed\x86\x5d\xfd\xc7\x72\xe1\x85\x29\x2c\x1e\x36\xb1\x21\x17\x81\xc3\xe9\x38\xe3\xd4\xf2\x4e\x29\xaf\x51\x7a\x37\x96\x83"}, -{{0x4f,0xc5,0x12,0xef,0xd8,0x6e,0x3a,0x63,0xb3,0x95,0xea,0xff,0x1b,0xa0,0x11,0xe1,0x59,0x0f,0xb9,0x32,0x6a,0xd3,0xff,0xed,0xe7,0x87,0x6d,0xcc,0x3e,0x9f,0xab,0xdc,},{0x26,0xc2,0xa2,0x2f,0x9b,0xfa,0xd9,0x06,0x06,0xdc,0x61,0x3f,0xf1,0x07,0x02,0x1f,0xcd,0xdb,0xec,0x72,0x37,0x06,0x66,0x60,0xb4,0x88,0x96,0x43,0x49,0xe0,0xc8,0x28,},{0x82,0xc8,0x24,0xa7,0xd1,0x13,0x9e,0xc7,0x3a,0xe1,0xd0,0x23,0xad,0xf6,0x28,0x11,0x44,0x1e,0x96,0x82,0x87,0xf1,0xa5,0x80,0xb8,0x59,0xcd,0x66,0xcb,0x33,0xb5,0x8e,0x40,0x9b,0xde,0xb2,0xa8,0x74,0xbf,0x4c,0x23,0x61,0x0b,0xd4,0x4f,0x69,0x31,0x47,0xf2,0xf7,0xc2,0x9d,0x44,0x3a,0x90,0x50,0x84,0xf3,0xea,0xaf,0xd9,0x33,0x0e,0x04,},"\x07\xcd\x1e\x9b\xfa\x38\xa7\xd8\x85\x34\x65\xa9\x3c\x77\xab\x4f\x30\xfa\xf9\x14\xe4\x8b\xc4\x76\x3b\xa0\x7b\xf9\x6b\xa8\x08\xc1\xf5\x9a\xd4\xce\x9b\x7d\x92\x1f\xbb\xc7\x79\x65\x9d\x7c\xa3\x6e\xdb\x7d\xd3\xac\xf7\xa2\x94\x52\xa8\x45\xb4\x9f\xb6\x54\x3a\x3b\x6c\x5c\x1c\x29\x3a\xff\x61\x84\x85\xa1\x0e\xea\x60\xee\x96\x49\xac\x9d\x48\x1e\x69\x49\x96\x7d\x39\x38\xb5\x2f\xe0\x9c\x36\xb9\xad\xe0\x75\x81\xdb\x4e\xb5\x42\xa9\x7f\x5a\xc8\xac\x73\xd3\xee\xa1\x84\x72\x25\x56\x76\x0c\xf4\x83\x09\x05\x64\x55\x30\x61\xb9\x0a\x0b\x6d\x2d\xff\x47\x07\xbe\x76\x39\x37\xa1\x05\x94\xa8\x2b\x76\x6b\xb2\xcf\x6d\xaa\x52\xfa\x8d\x7b\x48\xf3\x21\x27\xc4\x31\xad\x9a\xae\xd3\xbf\xde\xb9\x9a\xd4\x21\x18\xa1\xb4\xde\x7b\x99\x21\x34\xed\x9c\xda\xd0\xb5\x29\x6d\x19\x7a\x48\x5e\x49\x3e\xcf\xec\xa3\x65\x3a\xd2\xce\x0f\x92\x41\xaa\xbc\x09\x6d\x7c\x4b\xa6\x03\xba\x7d\xdd\x07\xa8\xb2\x57\xfe\x52\x32\x76\x41\x70\x73\xa6\x5f\xa4\x43\x42\x56\xfd\x1f\x23\x9e\xc1\xde\x5d\xa1\xa0\xa8\xc5\xe6\x86\xee\x14\xd9\xdf\xa4\x38\xc5\x3b\x99\xc9\x54\xaf\xab\x2f\x79\xe6\x0b\x71\x26\xf2\xcb\x58\xa2\x6e\x29\x0d\xa1\xdc\xcf\xc3\x01\xf2\x39\x74\x8e\xde\x7b\xcf\x1b\xb7\xcc\xb4\x72\x0e\x69\x2f\x57\xe5\x3e\x6f\x59\x07\x53\x99\xe1\x08\x0a\xc8\xaa\x9a\x61\xa5\x68\xc4\xc5\x69\xd3\x6e\x76\xa2\xd7\x27\x1f\x2c\x44\xde\x4e\x36\x3a\x8c\x91\x6a\x4e\x44\x6b\x02\x7b\x64\x39\x2e\x90\xce\xab\xf6\xb6\x07\x1b\xc4\x7a\x13\x79\xb6\xaa\x63\x44\x76\x3b\x2a\x0e\x7f\xf7\xc4\xa2\x7b\xff\x31\x06\x72\x1c\x25\x3e\x4c\x1d\x67\xc3\x7f\xa3\xd7\xc1\xec\xd0\x55\xb8\xe9\x29\xd5\x2a\x8e\x45\xed\x89\xfb\x18\x0f\x74\xb5\x52\xfe\x06\xf0\x66\xc7\xe4\x31\x8c\xa2\xf9\x15\x94\x6e\x83\x20\xd5\x80\x65\x61\x47\x2f\xb8\xff\x7f\xa8\x07\x2d\x8e\x6f\xd1\xce\x63\xcf\x87\x38\x2f\x7b\x94\x04\x54\x0c\x1d\x40\x6c\x70\xb2\x26\x85\x36\x77\x09\x26\x45\xce\x99\x69\x22\xe7\x34\x5d\xc0\x7f\xb7\x33\x9f\x9a\x54\xff\x07\x35\x2d\xd2\xb9\x93\x06\x3c\x2c\x83\xd1\x28\x1a\x4f\xd1\x78\xe5\xa5\xf8\x0a\x5b\x33\xc2\x29\xd0\x57\x83\x67\xd4\x41\x92\xe9\xa4\xd2\x1e\x97\x34\xd3\xbd\xa0\x83\xb7\x0f\x47\x10\x3f\xd1\x25\x17\x70\x21\xdf\x3e\x53\xd7\x99\x86\xef\xea\x2d\xc0\x4f\x02\xc0\xac\x27\x87\x88\x31\x9e\xf3\xa9\x13\x2e\x62\x32\xea\x6d\xb3\x9c\xa5\x87\x08\x55\xf9\x59\x2f\xff\x6c\x20\x9a\xd2\xf1\xc2\x9d\xd1\x68\x55\x28\x98\x97\x9e\xcf\xf8\xc8\x11\x27\x24\x8f\x83\x10\x51\x53\x00\x65\x61\x29\xd9\xb7\xac\xbb\x7e\xd1\xe4\x6b\xc9\x8c\x04\xd1\xa3\x5b\x18\x91\x37\x38\xe9\xdd\xe4\xd2\xb0\x65\xf4\x18\x42\x42\xd8"}, -{{0x0b,0x7d,0xfa,0xd0,0x5b,0xa6,0x65,0x11,0x1e,0x16,0x81,0xbd,0xc0,0xbc,0x8b,0xa9,0x73,0x76,0x7c,0xb8,0x58,0x77,0x02,0x0a,0x2d,0xbf,0x91,0x83,0x25,0x57,0x1d,0x9f,},{0x95,0x05,0xd9,0xe8,0x6d,0xce,0xf5,0x6c,0x9d,0xb7,0x6f,0x28,0x62,0xb9,0x0e,0x1f,0x27,0x73,0x20,0x2f,0x17,0x50,0x40,0x5e,0x7e,0xe5,0xae,0xd0,0xfc,0x54,0xf8,0xb9,},{0x41,0x5a,0xdb,0xb2,0xf2,0xb9,0x84,0x05,0x77,0xfd,0x18,0x41,0xf9,0xaa,0xe2,0x52,0xaf,0xe8,0xf5,0xa7,0x22,0x36,0x01,0x7d,0x50,0xdb,0x22,0xd2,0x28,0xcd,0xee,0x9f,0x5b,0x3e,0x8f,0xe9,0xa1,0x7a,0x4d,0x4e,0x98,0xb7,0x34,0x13,0x81,0xe8,0xd8,0x62,0x5c,0xdc,0xea,0x95,0x6d,0x25,0x3b,0x74,0xe0,0x2d,0xac,0xb8,0x49,0x20,0xa0,0x09,},"\xc4\x3f\xd3\x4b\xb1\x42\x4c\xca\x4e\x4d\xfb\xa7\x5c\x28\xbe\x80\x18\x44\x44\x6c\xa0\x89\x02\x08\x85\xc7\x48\x38\x25\x47\x16\x4a\x9d\x4a\x7f\x95\x70\xd3\xd1\x71\xad\x69\x81\xab\x50\xee\xee\x08\xa4\xa6\xc6\x6d\x76\x99\xd2\x3e\xdb\xe1\xfa\xaf\x44\x66\x0c\x72\xf4\x55\x2d\x87\xd2\x65\xac\xe8\x79\x28\x23\x47\x4b\x90\xa5\xd7\xf7\x40\x1d\xeb\x93\x77\x62\x7f\x60\xb0\x36\xb3\x6e\x04\x4e\xb7\x6b\xf1\x32\xfd\xdf\xcc\x0e\xf5\x70\x4a\x63\x3d\x84\x5e\x96\x2b\x47\x51\x7f\x0b\xaa\x34\xd3\xd6\xe9\xa8\xb9\xf8\x16\x8b\xcd\xc8\x4c\x6d\x2b\x30\xc6\xf3\x43\xe7\x53\x57\xf7\xf2\xc0\x03\x9b\xd2\x54\xb2\x44\xd3\x6c\xd6\x16\x75\x58\x1f\xb8\x34\x57\x0e\xd4\x11\x3a\x78\xe6\x06\xf1\x45\xa1\x11\x99\x2c\x2c\x6b\x61\xc4\x26\x76\x28\xec\x87\xcd\x88\xc3\x6a\x3c\x84\x70\x6e\x44\xae\x96\xa9\x6e\x0c\x84\x80\x31\x85\x46\xd6\xea\x6a\x6d\xf1\x8a\x2b\x4f\x19\xf8\x36\x0c\xfb\xce\x4e\x9d\x1c\xf1\x01\x1f\xfe\xa5\x63\x3a\x66\x61\x9a\xa4\xa6\x5c\xf6\x9b\xe4\x45\x96\x17\x94\x5e\x43\x59\xa9\xd4\x32\x60\xca\x1a\x20\xf4\xed\x7c\x1a\xe5\xff\xff\x3b\xd9\x22\x94\xea\x70\xab\xba\xe0\x38\x5b\x09\x35\xcd\x1c\x0e\xb5\x18\x30\x29\xc5\x85\xa0\x29\x4b\x79\x99\xe3\x2e\xf7\xa2\x90\xfc\xb0\x95\x67\x5d\xc4\xf6\x01\xe8\xf2\xc9\x6f\x35\xb7\x34\x9a\x37\x05\x75\x09\xf4\xec\x70\xc9\xf5\x0f\x60\x11\xf1\xf5\xe6\xb0\x61\xc0\x91\xd1\x1c\x0e\xd5\xde\xc8\xec\xe8\x81\xaa\x34\x05\x08\xf6\x96\xd9\xe9\xcc\x72\x98\xe6\xbc\xcd\x7c\x21\x0e\x2c\xe0\xde\xd8\x35\x92\xa3\xcf\xa1\x3e\x80\x78\xfd\xb3\x25\x8b\x39\xf1\xd1\x1c\xdf\xe0\x96\x70\xc1\xe6\x0a\x39\x10\xa4\xff\xf5\x1c\x6c\x7f\x7d\x66\x24\xf4\xc9\x3d\xf8\x88\x8c\x52\x6f\x48\x4f\x9b\x13\xe0\xa7\xf6\x29\x64\x78\x39\x78\x68\x4e\x29\x26\x79\x80\x0e\xd5\xeb\x28\x0e\x28\x7c\x7e\x63\x9e\x85\xfa\xa5\x3f\xba\x2f\xa2\x04\x5c\xe2\x7d\x8f\xb3\x08\x36\x07\x26\x55\x0d\xf9\x75\x2d\xb3\x05\xf8\xf0\x66\x47\x97\x0d\x01\x46\x91\x99\x9a\xfa\x97\xb6\x19\x3f\xfc\xc6\xd5\x32\xf4\xfa\x69\xe1\x33\xa1\xd1\x0f\x30\x47\xfc\x00\x38\x1f\x49\x97\xbb\x84\xe5\xb6\xcd\x60\x28\xc6\x21\x32\xcf\xc0\x24\xbf\xeb\x98\x03\x01\xf2\x95\x12\xbb\xd1\x09\xd0\x89\xac\xe1\x82\xcf\x9c\x2f\xfa\xb1\xb1\x7e\xb0\x0b\x6e\xb4\x6a\xe1\x98\xda\x99\x3f\x5e\xfe\x7c\x1d\xc2\x2d\x25\x04\x7c\x1e\xe5\x24\x65\x17\xe7\xf5\x75\x8f\x99\x6a\xbd\x83\xf1\x3d\xa2\x2c\x13\xdd\x20\x5e\xe1\x91\xb5\x5a\xfd\x48\x31\xef\x07\x8b\xb6\xea\x07\x3a\x62\x5b\xc9\x7c\x81\x29\x61\x60\xbb\xf2\x55\x9b\x27\x5c\xc3\x7c\xcf\x01\xb9\x1f\xd8\x7d\x4d\x99\xa3\x67\xaa\x99\x78\xda\xdd\x06\x89\xf8\xa6"}, -{{0x78,0x18,0x8d,0xf8,0xc7,0x54,0x78,0x56,0x21,0xe2,0x7a,0xe5,0x8e,0x10,0x0d,0x50,0x80,0xe1,0x6e,0x0a,0x15,0xe2,0x77,0x05,0x1f,0x95,0xf0,0x80,0x90,0x0e,0xc0,0xd3,},{0xa1,0xbd,0xee,0xe9,0x8b,0x07,0x57,0xba,0x9c,0x2d,0x84,0x09,0xb8,0x74,0x24,0xe6,0x4e,0x42,0xf9,0x93,0x2a,0xcf,0xa9,0xbc,0x71,0xfb,0x3f,0x8c,0xa0,0xe1,0x1d,0x52,},{0xb9,0x41,0x14,0xed,0xa4,0x6c,0xcf,0xc2,0x2a,0x44,0x71,0xa6,0x4d,0x79,0x08,0x92,0xe5,0x9c,0x5d,0x50,0x56,0x18,0xeb,0x0e,0x70,0x13,0x92,0xc7,0x09,0x61,0x3e,0x2d,0x50,0x3a,0x5c,0x2b,0x66,0x60,0x1e,0x63,0x6a,0x3c,0x1c,0x7d,0x49,0xb1,0xac,0x79,0x8d,0x90,0x89,0xb0,0xf9,0xcc,0xd0,0x57,0x9b,0xb9,0x06,0x34,0xd0,0xbd,0x75,0x0e,},"\xcf\x70\xcc\xa5\x7f\xeb\x1b\xee\xfe\x98\x5a\xd5\xaf\x9d\x43\x48\xd3\xa4\x6a\x63\xde\x10\x75\x38\x1f\xb3\x63\x9a\x04\x4f\xd6\xe6\x09\x1f\x5d\xb9\xc9\x4d\x39\xbe\x0f\x13\xad\xe6\xd9\xa0\x74\xe6\x7b\xa7\x06\xb3\xa8\x80\x62\x95\xf6\xb6\x54\x86\x57\x28\xc5\x8c\xa6\xe9\x41\x9d\x5d\x04\x3f\x21\x10\x81\x4b\xbf\x36\xfc\x40\x70\xe4\xd9\x45\x49\x65\xc2\x51\x20\x2c\xa3\x95\xef\xe3\xfd\xbd\x54\x4f\xeb\x18\x7e\x34\xca\x3c\x80\x79\x51\x79\x55\x2f\xce\x9a\xa8\x04\x43\x0e\x5b\x6c\x86\x85\x34\x1e\x91\xd5\x88\x9f\xbf\x3f\x98\x19\x04\x62\x0f\xfe\x70\x13\xf5\x3b\x93\x9e\x17\x44\x3d\x61\x4e\x7e\x6b\xb5\x7a\xd6\x74\xf3\xb4\xb0\x01\x63\x05\x26\xcf\x73\x02\xa7\xd0\xaf\xe7\xdc\x24\xd6\xda\xde\xf6\xfe\xba\x3f\x96\x97\x3a\xa5\xb8\xd6\x27\x52\x62\xe4\x30\xa8\x2f\x67\x86\x96\x97\x1a\x8b\x60\xe3\x8d\x3b\x2b\xcc\x17\x0d\x5b\xc2\x03\x02\xa3\x9c\x59\x6d\x27\xfe\xe3\x9e\x5d\xa5\xb1\x0e\xa9\xf3\x82\x29\x9e\x19\x81\x97\x17\xa7\x18\xd3\x7d\x15\x5f\x13\x92\x31\x82\xb5\xb7\xa1\xc5\x4c\xa1\x09\xb2\x2c\xa8\xe8\xb2\x6c\xa5\xca\x3f\x3b\x90\x62\x21\x94\x61\xba\xce\x97\xe8\x90\xc9\x4e\x41\xca\x3d\x84\x58\x7f\xbd\xf6\xe2\x40\xc3\x5c\xca\xb7\x1d\x58\x47\x7d\x28\x16\x8e\x93\x37\x26\x86\xd4\x2a\xad\x32\x4a\x3f\x16\xaf\xe0\xe9\xb8\x9e\xe2\x0e\x48\x5f\xe6\xc8\x64\xb5\x01\x3b\xa8\x83\x99\xee\xaa\x15\x98\x35\xa8\xb2\xbb\x2f\x25\xf5\x79\xca\x3b\xae\x67\x5c\x63\xda\x1b\x50\xd9\x9d\x4e\xd9\x78\x69\x2e\x56\x00\x23\x3f\x38\xab\x7e\x7a\x5a\xe0\xfb\xf8\xc0\xb6\x9c\xc3\x8b\xd3\x0e\xab\xd9\x77\xef\xa0\x5e\xe2\xc8\x35\x14\x30\x2b\xd4\x0c\x4b\xdc\xe7\xa4\x11\x0a\xfb\xb6\x57\x9c\x62\x0e\x97\xf8\xcf\x2e\x9b\xab\x2d\xcc\x7c\x33\xf1\x96\xe5\x7f\xe7\x61\xa0\x50\x12\x28\x94\xb7\xa7\x5a\x92\x95\x31\x99\x6d\xda\xad\x78\xde\x1d\x4d\x92\x4c\xd9\x3a\x61\xdf\x22\x77\x76\xbc\x1c\x39\xfb\xb8\xde\x1c\x44\x38\x86\x8b\x6a\x3a\x2c\xd9\x4c\x07\xb2\x9e\x3f\x6b\x23\xcc\x7e\x0b\x63\x68\x90\x09\xd9\xd0\xba\xe1\x60\x6b\xaf\xc7\xa8\x08\xf2\xd2\xfa\x25\x62\xb8\xdc\x09\x38\x42\xc0\x1f\xdb\x84\x0d\xa4\x86\x0a\xce\xd3\xfc\x52\x5c\xa3\x34\xed\xcf\x65\x94\x8b\xc4\x16\xf9\x8c\x45\x0f\x00\x12\xa6\x10\x7d\xd7\xf8\xed\xe4\x0e\x1c\x48\xc9\xe8\xa5\x65\xa8\x10\xb9\xcf\xd2\x03\x56\xdb\x19\xf1\xdb\xde\x59\x89\x21\x33\x2e\x0d\x81\x3f\x0c\xb8\x76\x84\x37\x03\x88\x77\x2f\xf3\xcb\xfc\xbf\xa2\x99\xc1\x98\xc9\x7b\xfb\x96\x17\x76\x8a\x05\x16\x1f\x41\x69\xff\x5d\xe5\xd9\xf4\x00\x62\x09\x0f\xb8\x82\x98\x4d\x9d\x5c\x7a\xa7\x8e\xdd\xcb\x96\x34\xe4\x66\xb8\x85\x3d\x51\x2b\x4a\x54\x6d\x74\x23"}, -{{0x73,0xcb,0x02,0xb0,0xbf,0x26,0xa0,0x15,0xda,0x1d,0xc3,0x01,0xfc,0x12,0x5d,0x7e,0x6c,0x30,0xb6,0x3c,0x9e,0x6e,0xee,0x9e,0x06,0x5d,0x4e,0x84,0x71,0x32,0xc3,0x25,},{0xac,0x9e,0x3d,0xd2,0xce,0xb9,0xb2,0x3e,0x74,0x8c,0x04,0xba,0x75,0x77,0xfe,0xdf,0x7c,0xea,0xb9,0xed,0x87,0xdc,0x43,0x0b,0x5f,0xe2,0x2e,0xac,0x50,0x95,0x0e,0x0d,},{0x1a,0x5d,0xd4,0xc8,0x91,0xc8,0xe1,0x32,0x57,0x01,0x87,0xc2,0x3b,0x9a,0x1e,0x4b,0x26,0xf0,0x54,0x60,0xe8,0x75,0x67,0x38,0x19,0x39,0x6d,0xf5,0x61,0xc8,0xaf,0x0e,0x48,0x33,0x3b,0x62,0xc7,0x77,0x29,0xd4,0x9f,0xc4,0x0e,0x17,0x4a,0x7f,0x3c,0x21,0xf8,0x5e,0xf4,0xd3,0x39,0xce,0xb8,0x0b,0xd2,0xe0,0x37,0xd8,0x03,0xaf,0x56,0x0e,},"\x0a\x2b\x61\xba\x35\xe9\x6e\x58\x19\xb8\x8b\xfd\xb2\x8b\x7c\xe0\x2e\x64\xae\x9c\xf5\x72\xb2\x1f\x13\x55\x2c\x0d\xb1\x0f\x39\x60\xd4\x4b\xa3\x47\x2f\x43\xab\xc4\xe6\x29\x5b\xdf\x79\x0b\xd9\x33\xba\x39\x75\xfd\x44\x65\xfa\x3e\x2f\xe2\xdb\x02\xb6\x37\x77\x52\x22\x3d\xec\x98\xfc\xb2\x40\x4f\x3a\xba\x43\x26\x5a\x6f\xa7\x97\x6b\x6c\x6c\xb6\x86\x8b\x88\x1b\xd6\xf3\xd2\x5c\xd9\xd6\xf7\x0e\x51\x2f\x80\x89\xc8\xef\x26\xfd\x58\x24\x50\x53\x77\x9e\x59\xc4\x72\x5a\xef\xa2\x64\x67\xc9\xf5\x00\xe1\x7f\x3e\x15\x73\xf1\xa8\x55\xe9\xb8\xb2\x19\x25\xea\x05\x27\xf3\xce\x8d\x88\xfb\x54\xa4\x7a\xbe\xed\x14\xf3\x99\xcc\x2d\x9f\x1f\xe5\x46\x65\xfa\xe0\xa8\xf0\xc6\x88\x72\xa6\x00\x04\x6d\x1d\xc3\x63\x97\xd3\x10\xce\x39\x3f\xce\xaf\xe8\x7c\x17\xeb\xe1\x22\xfd\xb5\x43\xae\xa7\x10\x85\xba\xec\x98\x27\x3f\x41\xac\x96\x69\x8c\x15\x0c\xf9\x11\xd0\xe5\xde\x23\x92\xd8\x48\x41\xd0\x12\x76\xae\xfb\xfe\x99\x95\xe1\x0a\x6d\x46\xef\xdc\x26\x78\xd4\x56\xc9\xf3\x6b\x2e\x10\x11\x4d\x11\x87\xe7\xac\xa7\x39\x03\x7e\xa5\x1f\x85\xfd\x62\xa2\x94\x29\xba\x52\x9c\xdd\x8a\xd9\x13\x47\x49\x74\x87\xed\x7e\x87\x09\xd4\x77\x6e\xf6\x86\x70\x79\x2d\x06\x15\xbc\x96\xda\x51\x78\xd6\x06\xdb\x63\xe4\xe5\xcb\x17\x2a\xcf\xbc\x1c\xbe\x20\x26\x93\x50\xf1\xb6\x05\xf3\x5d\xcd\x47\x91\x35\xbd\x30\xfb\x4b\x5a\x39\x17\x6c\xff\x74\x4d\xdb\xb3\x06\xc9\xe7\xb4\x16\x7d\xe0\x37\x9a\x61\x66\xbe\x5a\xaa\x74\xd7\x15\x7f\xac\x95\x7d\x88\xdc\x57\x59\x7c\xfe\xf2\x3e\xb5\x10\x8b\x3c\xe5\x3f\xc6\x32\xda\xd1\xb9\x72\xa2\x9d\xa5\xde\x32\xd2\x0d\x8e\xce\xde\x67\xff\x00\xda\x4a\x08\xa0\xcc\x1a\x98\xbe\xe7\xa9\x4e\x3c\xb3\x2f\xee\x94\xae\x25\xa4\x13\x54\x47\x02\xc3\x7b\x3e\x17\x78\xa0\x70\xcd\xd4\x84\x0b\xd3\x9f\x5f\x45\x79\x51\x92\xa8\x67\x86\x38\x76\xed\x0d\x13\x0d\x46\xe2\x91\x39\x35\x08\x28\x09\xf7\xe1\x5a\x49\x67\x10\xf2\x55\xd7\x83\xda\x3d\x01\x6a\x65\x4c\x15\xff\x5d\xf9\x07\xa3\xcc\xaf\x37\xcf\xe1\x1c\x8c\x3d\x49\x65\x07\xd6\x76\x0c\x05\x38\x20\xf0\xf5\x94\xc3\xd0\x1c\xa2\x69\x17\x8a\xca\x52\x5a\xb2\x82\x1e\xf5\x5f\x92\xd8\x5f\xe6\x85\xea\x34\x47\x2e\xd1\x39\x81\x71\x06\x4d\x74\xa4\x22\xec\x91\xd1\xa6\x70\x61\x8f\xc9\xf3\x24\x24\xbc\xb1\x1a\x77\xf6\xfb\x4e\x2f\xef\xd2\xc4\xe8\xa7\x3c\x45\x28\x86\xe9\x31\x66\x4d\x1a\x83\xbd\x92\x73\x29\xc0\x4d\x25\x0b\x83\x52\x1d\x7d\xc1\x3c\x91\xce\xe1\xec\x05\x0e\x11\xd4\x2a\x4b\x0c\x8c\x06\x9b\x61\xc4\x42\x2d\x3a\x49\xc0\x7e\xff\x29\x05\xb7\xbc\x7f\x4a\x5b\x43\xe6\xb0\xd6\x1d\xfb\x50\xe4\xee\xa2\xe9\x0d\x29\x8a\x78\x1d\x05"}, -{{0xdb,0x05,0x60,0x63,0x56,0xba,0xcf,0x23,0xaf,0xf6,0xcd,0xdd,0x42,0xb2,0xc6,0x94,0x35,0x2b,0x5a,0x0f,0xec,0x56,0x0a,0xff,0x54,0xd9,0xbd,0x97,0x10,0xef,0xe0,0x6a,},{0x32,0xa5,0xc7,0xcc,0x49,0x09,0x78,0x6b,0x48,0xa5,0x3f,0x31,0x09,0x3f,0x54,0x9a,0x9f,0x17,0x30,0xca,0x66,0x90,0x38,0x3f,0xdb,0x5f,0x14,0xc2,0x66,0x6e,0x31,0x32,},{0x53,0x09,0x9b,0x76,0x6a,0xdf,0x29,0x44,0xb6,0x82,0x13,0x74,0x84,0x2c,0x25,0xd6,0xe6,0x7b,0x0c,0xcd,0xe9,0xc6,0x37,0xfe,0xcb,0x11,0xb8,0xb8,0xb0,0x72,0x03,0xe3,0x07,0x57,0x32,0x80,0x5f,0x4f,0x14,0xae,0xae,0x73,0xbd,0x62,0xe3,0x08,0xb5,0x88,0x7d,0x68,0x9e,0x29,0xcd,0x89,0xb2,0x3a,0x47,0x69,0x43,0x11,0x07,0x17,0xb1,0x00,},"\x1b\xc9\xc2\x83\x3f\x37\xcd\xf1\x35\x6f\xad\x16\x67\x68\x64\x27\x17\x70\x1b\x38\xa0\xab\x0c\x2f\x58\x1a\x26\xd2\x22\xd6\x5c\xce\xe4\xbf\x0f\x6d\xfe\x64\xd3\x3b\xc0\x23\x9f\x71\xd4\xb8\x26\x44\xb0\x16\x25\xa1\xa3\x5f\xe7\x98\x67\x62\x39\xe0\xca\x77\x9e\xf2\x31\x38\xee\xbe\x3b\xd1\x9d\xe2\xd8\xf7\xc1\x5b\x4d\x96\xf1\x3e\x51\xbc\x63\x3b\xea\x5d\x61\x22\x5b\xca\x1d\x63\x39\xba\x53\xe8\x1f\x7d\x8d\x24\xc5\xd6\x0f\x04\xce\x8c\x72\x67\x61\xd2\x64\x58\x4f\x1c\x7e\x5b\x5b\x69\x92\x45\x6c\x1c\x76\x89\x2d\x63\x52\x11\x1e\x3b\x92\x6f\xe0\x25\xc0\x00\x9d\xb6\x7c\xe0\xdd\xc7\xf7\x64\xe0\xc9\xad\xb0\x48\x1b\xc2\x79\x54\x84\xd9\x63\x73\xa9\x62\xa7\xb7\x4a\x55\x96\xf5\x27\xa7\x34\x76\x49\x8c\x78\x23\xdf\xfa\x6c\x85\x43\xb0\x79\x71\xb5\xaa\x27\x1c\x12\x25\x5e\x09\x18\xdd\x73\xf5\x0c\x30\xc9\xa8\x5a\xc7\xc2\x99\x3d\xd6\x55\xda\x59\x43\x12\x63\xf5\x91\x4b\xe7\x06\x37\x4b\xe9\xc0\x75\x85\xc2\x87\x13\x28\xb4\xdb\xc3\x94\x01\xc9\x57\x07\x38\x7e\x6e\x06\x9d\x44\xb9\xd8\xfb\x05\x8f\x22\xe3\x15\xaa\x0d\x5b\x4f\x11\x68\xfc\x10\x79\x62\xb0\x64\xf7\xd8\x45\xaf\x8e\x21\x31\x95\x1d\x1c\xd6\x6d\xc8\x4d\xba\x46\xd2\x00\xaf\x4f\x4c\x5f\x51\x22\x1b\xc9\xb2\x19\x69\x42\xf8\xb4\x0e\x7d\xdb\xc9\xae\xb3\xd9\xaf\xc0\x71\x25\x95\x13\x13\x5a\x01\x6f\x28\x66\x09\x9f\xa1\x0f\x4c\x3b\x73\x50\x0b\xd5\x5c\x47\x7b\x24\x15\xe1\x0a\x27\x9b\xa1\x10\xd2\x94\xf3\xdd\x18\x42\x17\x7d\x0b\x4b\xfb\x17\x34\xdd\x0c\xcb\x7e\x39\x4b\x43\xd1\x6f\x0b\x75\x48\x36\x22\x80\xf4\x34\x76\x4d\xa5\x7f\x19\xed\x3e\x30\x2e\x53\x70\xfb\xa4\x96\x64\xc2\x30\x05\x74\x33\xcc\x64\x7e\xb2\x7c\xd2\xc7\xc1\x8c\x7d\x66\x90\x6f\x08\x82\x46\xc2\x2f\x7f\x79\x03\x99\xde\xb4\xc5\xfb\xb9\x06\x18\x17\x69\xbe\xf5\xaf\xbe\x8a\xd1\xf5\xde\x55\xbe\x58\x8f\x52\xf6\x9c\x54\xd4\xef\x5a\x96\x9a\x0d\x99\x5c\x27\x40\x7b\x23\xed\xd9\x24\x3d\x24\x99\xfd\xf2\x94\x73\xb1\x95\x5c\x84\xb3\xf7\xcb\xdc\xd8\x1b\x76\x56\xec\x0b\xe9\xe0\xfd\xb3\x38\x13\x56\x96\x0f\xd0\xca\x70\xe7\xea\x74\xb6\x46\xfc\xd3\x13\x94\x8e\x6d\xdb\x47\x60\x94\x76\xfb\x6f\xa4\x84\x2f\xa7\x88\xa0\xd5\x7b\xe3\xb0\xa6\xca\x18\x19\xf7\x16\x14\x76\x00\x43\xec\x49\x04\x88\x19\x39\x96\x8a\x43\xb5\xd1\x92\x8f\x84\xa5\x91\x90\x93\xbc\x38\x41\x58\x81\x71\xa9\xcd\x39\x0f\x8f\xcd\x61\x53\x8b\x54\xe6\xef\x99\x77\x05\x73\xe1\x98\x6d\x15\x0f\xa9\x6b\x7a\x07\xe1\xd1\x94\xaf\x1c\x0b\x40\x55\x00\xac\xb3\xd1\x0e\x3b\xe6\x47\xc8\x98\x62\x00\x6f\xa7\x85\x83\xe7\x61\x66\x84\x29\x20\x16\x0e\xb5\x7f\x0b\x2a\x6e\xdf\x19\x3c\x44\xc5\xee\xac\xf4"}, -{{0x1d,0x13,0x9b,0x1a,0xd0,0xc3,0xaf,0x1d,0x5b,0x8b,0xe3,0x1a,0x4e,0xcb,0x87,0x8e,0xc6,0x67,0x73,0x6f,0x7d,0x4f,0xa8,0x36,0x3a,0x98,0x09,0xb6,0xd1,0xda,0xbf,0xe3,},{0x24,0x28,0xcf,0x1d,0xeb,0x20,0xfb,0xad,0x1f,0xdc,0x66,0x5d,0x82,0x5b,0x61,0x41,0x22,0xdf,0x10,0x1f,0xbe,0x14,0x73,0xa7,0x99,0x96,0xba,0xf6,0x96,0x74,0x34,0xb8,},{0xdd,0x64,0x5e,0x51,0xed,0xab,0x04,0xdb,0x31,0xe3,0x31,0x72,0xcf,0x27,0xac,0xee,0xed,0xcc,0x04,0x63,0xa9,0x63,0x91,0x4a,0x0e,0xac,0x8e,0xfd,0x5a,0x34,0x34,0x1f,0x6b,0xbc,0x52,0xe0,0x42,0xba,0xaf,0x3b,0x40,0xc8,0x9a,0x57,0xef,0xb6,0x45,0x74,0xe6,0x96,0x77,0xfc,0xe9,0x55,0x24,0x6c,0x1f,0xc0,0xf2,0x69,0xef,0x81,0x90,0x00,},"\x8d\xf2\xd2\xdf\x9b\x98\x4d\xa8\x44\x33\x48\x6a\x81\x3c\x98\xc5\x97\x3a\x69\x6c\x11\x62\x46\x10\xb2\x3a\xa4\x38\x08\x34\x64\xf6\x5a\x76\x79\x66\x15\xb7\x28\xc2\xed\x4e\x60\x71\x58\x55\xaf\xc2\x39\x45\x0d\x5b\xc0\x91\x1f\xf2\xa8\x52\x30\x20\x5c\x6f\x13\x49\xba\x5b\xd8\x7e\xa6\xf7\x20\xdb\x6b\xa7\x0b\x77\x42\x17\x88\xe0\xc6\x54\xae\xbc\x23\x07\x4c\x5f\x41\xd2\x29\x07\x72\x14\x0d\x98\x1a\x6b\xc4\xfe\x70\x9a\x26\x8e\x64\x17\x2a\x02\x6b\x27\x01\x18\xb4\xdb\x51\xab\x6a\x13\xc9\x9b\x06\x31\x86\xd8\xd5\xb3\x38\xe9\x77\xed\xdc\x6b\xb5\xfd\x7d\xd5\x7d\x98\x45\xa3\xc3\xfe\x76\x17\x7d\x57\x38\xdc\xa1\x6a\x8f\x91\x02\x85\x75\x00\x17\x4f\x23\xff\x4c\x3b\xf3\xc8\x53\x6f\x11\x58\x0e\xf8\x51\x4a\x40\x9f\x5b\xbc\x9c\x02\x96\xf1\x2e\x34\x78\xd4\x08\x7f\x95\xef\xaa\x6c\x63\x60\x71\xd2\x11\x57\xbf\x11\x77\x4b\xbf\xe7\x69\x33\x06\xca\x72\x13\xda\x47\x13\xeb\xaa\xab\x35\x54\xed\xf0\x80\x11\xa5\xff\x73\xda\x12\x03\x75\xae\xd1\x96\x28\x67\x0f\x28\xab\x24\xb6\xf5\xd5\xa1\xd5\x70\x48\x0f\x65\xd3\xc1\x52\xbf\xf1\xb4\x7b\xf0\x66\x69\x29\xcb\x7c\x99\xd9\x03\x3f\xaa\xe8\x53\x4f\xc3\x5d\xa7\x30\xb8\x11\xeb\xcc\x25\xae\x10\xa1\x95\xaa\xb1\x2c\x32\x6a\xa4\x5b\xf8\x05\xc6\x2d\xd4\xcd\x5f\x86\x86\x23\xc0\x4a\x8e\x1c\x6a\xa7\x2f\x1e\xa4\x40\x0c\x60\x86\x7d\xff\x62\x2f\x31\x64\x34\xf1\xec\x89\x50\x3c\x6f\x9f\x65\xc1\x37\xb4\x94\x4c\xbc\xb3\x5f\x08\x6c\x74\xcc\xea\xfa\x22\x42\xac\xca\x6f\xfe\x61\x1c\x4b\x55\x87\xf5\xb7\x5f\xfa\xd3\x49\xf0\x0b\xf9\x6e\x4a\x58\x0a\x87\x5b\x92\x65\x40\x69\xb6\x2e\xea\xc0\xbf\x78\xe5\xae\xdd\x71\x86\x9e\xe0\x5b\x9a\x94\xe1\xc9\x8e\x35\xa9\x78\x00\xa4\xa2\x12\x20\xb0\x39\xcd\x5e\xbb\xb7\x56\xd4\x0b\x40\x42\xe2\xc8\x4a\x2a\xe9\x81\x82\x51\x1d\xae\x8e\xd3\xb8\x9f\x4f\xa0\x0f\xb8\xed\x94\x63\x16\x45\x97\x10\x05\x2a\xd4\xc0\x2f\x63\xdf\x05\xd3\xbb\x1a\xce\x33\x67\x21\x51\xbd\xf5\xda\xb4\x6c\x7b\x58\x3d\xb3\x73\x89\x9d\x4f\x03\x5b\x6c\x11\x12\x58\xb4\xe5\xa9\xe7\x07\xa1\x1d\x21\x5e\x44\xe6\x8e\xf1\xa6\xf0\x53\x80\x9a\xa5\x1b\xd9\x02\xe1\x3c\xa9\x9c\x1b\x1c\xec\xc8\x3b\x9c\x23\x5c\x71\x0e\x79\x7d\x2b\x1a\x24\x9b\x2e\xa0\x79\xb5\xc1\x67\x4e\xd7\x16\x9f\x1b\x6e\x67\xf1\xac\x77\xf8\x6b\x74\x32\x98\x96\x93\x35\xa7\x72\x44\x0f\x7f\xbf\xa7\x25\x13\x50\x0d\x84\x16\x61\x14\xa8\xfd\x54\x13\x94\x64\xd4\x2b\x99\x55\x30\xd3\x23\x70\xb6\x9b\xff\xc7\x58\x9d\x6d\xcc\x97\xe0\xbf\x17\x85\x6c\xc3\xbf\x41\x64\xdb\xec\xcc\x8a\x88\x1d\x41\x4d\x6a\x62\x02\x92\x76\xc5\xf8\x13\x7c\x0b\x3c\x68\xbc\x8f\x4b\xd4\xe7\xcf\xf6\x5e\xf2"}, -{{0x4d,0x22,0xe3,0x31,0xe0,0xcf,0x6f,0x6a,0x27,0x2d,0xb4,0xd2,0x06,0x87,0xff,0xb0,0x59,0xf1,0x22,0x5d,0x81,0xe4,0x11,0x23,0xb8,0xc8,0x9b,0x07,0x4d,0xe7,0x6a,0x3b,},{0xb1,0xe4,0xcf,0xae,0xad,0xd6,0x7b,0x12,0xd7,0xb9,0xdb,0xfc,0x0f,0x88,0xed,0xd0,0x37,0x3f,0x9a,0x88,0xc7,0xfa,0x33,0xfb,0x7f,0x2b,0x1e,0x47,0x5e,0xcc,0xb6,0x1b,},{0xc3,0x66,0xb8,0x02,0xf6,0x82,0xfc,0xd7,0x05,0x25,0x26,0x4f,0xb1,0xa3,0xcb,0xcd,0x0e,0xe3,0x5e,0xcf,0xf5,0x97,0x7c,0x2a,0x55,0x4d,0xa9,0x39,0x22,0x9f,0x17,0x81,0x9a,0x96,0x1e,0xa7,0x4c,0x3d,0x7a,0x78,0x81,0xac,0x5c,0x1f,0xa1,0x6b,0xf9,0x84,0xd9,0x45,0x6a,0x13,0x88,0xd3,0x46,0x3c,0x44,0x94,0x42,0x9b,0x1d,0xc4,0x54,0x02,},"\x9c\x8e\x3f\x5b\x4d\x70\x40\x30\xe1\xba\x71\xf0\x2e\xfc\x4b\x87\xd6\xff\xfb\x55\xbc\x3d\x8d\x03\x81\x8f\x91\x56\x24\xfc\xf7\x01\xc5\x4a\xdf\xaf\xa2\xb6\x94\xb8\x77\x51\xcb\x9f\x69\x91\x8c\x0f\x05\x0f\x4c\x10\x5d\x5c\xcb\x40\x10\x0b\x28\xdf\xd4\xf4\x11\xd5\x91\xc1\x20\x19\x17\x6a\xc2\x01\x6b\xfb\xfd\xf0\xdd\xf1\x1d\xb8\xa7\xe3\x9a\xa7\xb9\xe2\x16\xf6\x67\xc0\xa1\x5f\xb9\x77\xea\xa9\xba\x3b\xc4\x55\xcc\x58\x94\x5f\x3e\x94\x4b\x8a\xc2\xfb\xf4\xd2\x4f\xe7\xe1\xe6\x19\xcd\xbe\xee\x3e\x5e\x12\xa9\xa5\x27\xd2\x8f\x5f\xd7\xcf\xd9\x22\x0f\x13\x08\xd8\x97\xb6\xd4\x31\x4a\x5a\x01\x87\x86\x4a\x2d\x62\x1c\xf1\xb2\x84\x42\x61\x24\x7b\xf5\x20\xba\xfa\x9b\xf2\x26\xe1\x15\x68\x1e\xcd\x77\x42\x79\x80\xcd\x12\xb0\x8c\x35\x9c\xec\xd1\xde\x3f\x55\x45\xf8\x07\xf8\x1e\xd7\x63\x02\xff\xd6\x47\x7f\x89\xb9\x58\xcd\xf1\x29\x54\xcf\x70\xc1\x42\x53\x29\x93\x83\x16\x47\xea\xca\xb0\xb4\x80\x7b\xfd\xad\xb4\x38\x9d\x7d\xff\x2c\x4e\xf0\xef\x5a\x5c\x61\xd0\xdf\x76\x2e\x2e\x90\x80\xa7\x18\x1c\xec\xd0\x6a\x53\x19\x9f\x0d\xfe\xf7\x02\x62\x7a\xde\xcf\x5f\xcd\x9b\x3e\x68\xc7\x23\x33\x16\x17\x27\xf8\x71\xc7\xd1\xc4\x30\x51\xff\x1c\x92\x1f\xd5\x3b\x64\x22\x38\xb9\x78\x80\xd6\x4e\x25\xfa\xc5\x12\xab\x95\x4b\xed\xbc\xa5\x40\xf5\xb2\x00\x91\xec\x72\xe6\x7f\x88\x77\x0a\xfc\x32\xf2\x12\x5c\xa0\xda\x4f\xe8\x7b\x56\xaa\xc9\x17\x7f\x1f\x4f\x67\xc8\x51\x72\x5c\x5e\x8a\xfe\x64\xf6\x64\x79\x98\x33\xfd\x79\x10\x0b\x77\xea\xd2\x58\x38\x87\x9f\xff\x47\x47\xaa\x0d\x56\x72\xec\x0a\x94\x34\x81\x34\xbd\xbd\x4b\xb3\x9b\x0c\x67\xa0\xcd\x30\x60\x2e\xdf\x4f\xec\x6f\x7a\xf0\xcc\x2b\xda\xe1\x26\xce\xa8\x42\xdf\xaa\x43\x91\xdc\x5d\xde\xa9\x38\xe1\x79\x21\x68\x24\x0c\x2d\x8b\x25\x35\x2f\x9f\x3a\x64\x42\x35\xce\x36\xfe\xfe\xb6\x99\x2a\xd8\x8e\x28\x7a\xd2\xd8\x5b\xd8\x50\x39\x6f\xc2\xe5\x17\xa1\x52\x09\xf5\x92\x0a\xc9\x8c\x53\x2b\x1f\x4d\x86\x9b\xeb\x08\xbb\x03\xcf\x7c\x91\xaf\x3f\xfc\xed\x68\xd5\xfb\xfe\xf8\x6f\xf9\x4e\xce\x6e\x2e\xad\x34\x84\xce\x08\x0d\xb1\x7b\xbe\x40\xf1\xdb\x43\x2e\xc1\x65\x0e\xd2\x4f\xdd\x25\x0f\x33\x45\x74\x5c\x9b\x7b\x91\x98\xc9\x10\x9a\x37\x26\x1f\xc5\xec\xbb\xb1\x2f\x83\xa0\xe1\x22\x0a\x18\x67\xd4\x5f\xdd\xfe\xa8\x1d\xcf\x75\xf4\xec\x7f\xdb\x52\x50\xe5\x77\x54\xd6\xde\xa2\x70\xb6\x28\xa7\x95\x30\xec\x28\xb6\x19\xbc\xa9\x49\x3e\x63\x05\xcf\xc4\x41\x4c\x1c\x1d\xe3\x38\x9e\x89\x01\x97\xc8\x5f\x28\x40\x4f\x3f\xa9\x6a\x1e\x2f\xd9\x20\x6b\x47\x2e\x8a\x0a\x0d\x32\xaf\x55\x60\x6b\xb0\x83\xf7\x6a\x19\xb8\xea\xe3\x47\x9a\xe5\x1d\x98\xa9\x9a\x62"}, -{{0xa5,0x22,0x8f,0xf9,0xbb,0xb6,0xf2,0x32,0x32,0x7e,0xb8,0xd8,0x79,0xd7,0xf8,0xb2,0x77,0xca,0x72,0xba,0xe1,0xf9,0xa9,0xd0,0xe2,0x60,0xdd,0x90,0x57,0x1d,0xb4,0xf9,},{0xd8,0x2f,0x6a,0x69,0x74,0xf5,0x1c,0x88,0x08,0xd9,0xd6,0x17,0xf4,0xce,0xc2,0xd8,0xa3,0x7e,0xb1,0x1a,0x14,0x23,0x7c,0x9a,0xb9,0xcf,0x11,0xeb,0xc8,0x0f,0xf6,0xc0,},{0x97,0x65,0x0f,0xae,0x3f,0x59,0xca,0x76,0x47,0x7f,0x25,0x47,0x16,0x77,0x49,0xc5,0x83,0x02,0x48,0x88,0x32,0x25,0xe3,0x54,0xff,0x46,0xc7,0xe3,0x81,0x96,0x52,0x20,0xd9,0xbe,0xf2,0xc2,0x05,0x7c,0x7d,0x19,0x90,0xf0,0x8b,0xca,0x4c,0xfd,0xe8,0x77,0xff,0xf2,0xb4,0xaa,0x81,0x3d,0x9c,0x4b,0x84,0xfb,0x79,0xec,0xed,0x81,0xef,0x05,},"\x1d\xf7\xa6\x83\x5e\x33\x10\x98\x3e\xe7\xec\x73\x11\x25\xf5\xb5\xcf\x11\x7a\xf0\xe3\x6b\x36\x85\xbf\x54\xac\xe1\xc4\x8c\x46\x30\x05\x60\xa4\x5e\x9f\x9b\xdd\x96\xa0\xbc\x4d\x14\xe8\x9d\x4b\x57\x21\xa2\xca\xff\x66\x18\xb1\x82\xed\xb1\x20\x2f\x3d\x0c\x5d\x11\x8d\x09\xb6\x18\x12\xc0\x10\xe8\xb1\x96\x34\x45\x41\xcd\xee\xfe\x5f\xd1\xf9\x61\xc5\xdd\x75\x45\x95\x55\xab\x72\xef\x2a\xa7\xa7\x59\xa4\xf3\xad\x3c\xae\xd4\x4f\x4c\x9a\x8e\xf9\x5b\x76\xed\x9a\x99\xb5\x5d\xd8\xa2\x60\xba\x08\x01\x0d\x29\xff\x81\x9f\x2a\xf3\x51\x3c\x1a\x64\x0d\x6c\xcd\xde\x49\x99\x20\x5f\x9f\xca\x88\x57\x11\x5d\x8b\x5d\xb9\xf7\x0a\x62\xe5\xee\xa0\xd5\xaf\x06\x5d\xe1\x53\xf2\xed\xed\xee\xc6\x3e\x15\xc8\xe0\x9a\x92\x58\x21\x82\xac\x07\xd8\x1c\xa6\x3c\xa4\xaa\x59\x7a\x22\x20\xe7\x04\x81\x95\x7d\x41\x52\x64\xe2\x58\xbc\x26\x3e\x1c\xc3\x6e\x53\x47\x8a\xac\x5c\xa0\x16\x94\xcc\xb0\x9b\x4f\xfd\x84\x73\x99\x72\xc7\xdc\xcf\x3d\xef\xea\xfd\xed\xe1\x62\xab\x6c\x58\xa1\xdf\x27\x37\x1e\x3f\x54\x93\x06\x7f\xc9\xe2\x06\x7e\x57\x96\x23\xc0\x09\xfc\x82\x5e\xef\x0e\x01\x0f\xd1\xcc\xf2\xa8\xd3\xfb\xbb\x31\x56\xf9\xdf\xde\x0c\x7c\xbb\xaf\x84\x33\x09\x85\x17\x49\x1b\x78\xdb\x96\x98\x61\x4e\xa4\x0e\x0b\x1e\x6a\x1e\x36\xb9\x00\x45\x3a\x16\xea\x27\x6f\x34\x42\xbb\xd2\x7a\x7e\xcb\x98\x15\x11\xf5\xc9\x20\x9e\xb0\x96\xe2\x85\x88\xb6\x5b\x96\xb5\x01\x88\xc0\x38\x1f\xf7\x12\xbc\x06\xb2\xc6\x55\xcc\xa0\x75\x1c\x09\x5d\x80\x16\x25\x15\x85\x85\x1e\x67\x74\x34\xdc\x3e\xfd\x08\x7a\x12\x68\x0f\xc2\x2e\x5b\x83\x10\xa1\x0e\x32\xca\xac\x9b\x71\xc8\x76\xee\xd3\x1e\xf0\x9f\x7f\xa0\x12\xba\x08\xdf\xd2\xad\x68\xc1\xe1\x47\xf5\x05\x98\xe5\x50\x46\x7e\xf9\x9f\x29\x5a\x31\x8f\xaa\x50\x7e\xbe\x77\x6c\xe5\x5c\x4d\xa1\x64\x32\x3c\x30\xa5\xe7\x2d\xbe\x02\x7c\x3c\xcf\x96\xc7\x01\x97\xa6\xfb\x1b\x74\xaf\x13\x3a\x8b\xe2\xb0\x3c\x1b\x99\xfd\x25\xb3\xce\xd5\x1f\xe3\x88\x20\x21\xa3\xaf\xd9\x22\x9f\x64\x1b\xc6\xca\xd4\xe1\xd3\xcb\x6e\xd9\xb6\xb6\x8a\x25\xf1\xe1\x39\x72\x89\x98\x1f\x78\x92\x4b\xff\x24\xc8\xde\xe6\xa1\x8a\x04\x21\xfa\x32\xae\x3a\xb6\x0a\x0d\x93\x3a\x6a\xf4\xff\x70\x48\x74\xb0\x9b\x07\x39\xe2\xf2\x9d\x8f\x25\x2d\x79\x05\x5f\x89\xd3\xbf\xf1\x0a\x22\xc5\x4a\xc3\xd8\xaf\xee\xce\x81\x83\x53\xa6\xab\xe2\xb7\xfb\x8e\x8e\x0d\xa5\xb7\xac\x1c\xfc\x98\x5d\xf9\x75\x80\xb1\x82\x11\xa4\xe3\xed\xff\x95\xaf\xdd\xa0\x61\x54\x7d\x3a\xe0\x40\x6d\x32\x86\xcd\x30\x5b\xdf\xd2\xc3\xab\xf8\xf7\x4a\xf9\xa0\x34\x20\xe5\xb0\x3f\x82\x5e\x9c\x53\x90\x7e\x13\xa5\x81\x21\x74\xbe\x42\x89\x86\x45\x14\x9d"}, -{{0xc0,0x4d,0xc0,0x9f,0x11,0x9d,0x67,0x0f,0xb1,0xea,0xe0,0x13,0x6f,0xcc,0x06,0x08,0x5f,0x29,0x0f,0x4a,0xd1,0xaa,0x1f,0xfc,0x9c,0x16,0x0e,0xa5,0xcf,0x47,0xf0,0x9d,},{0xff,0x49,0x8c,0xe8,0xc9,0xdb,0x78,0x67,0xf6,0xd0,0x27,0x64,0x52,0xa4,0x66,0x72,0x48,0x87,0xe6,0x17,0x2f,0x66,0x81,0x67,0x1b,0x8a,0xe0,0x35,0xf5,0x86,0x5e,0xa3,},{0x4b,0xd1,0x9f,0x3d,0x9c,0x51,0x16,0xec,0x6a,0xe0,0x02,0x4d,0x0f,0x24,0x6d,0x2c,0xe2,0x50,0xd9,0xe0,0x63,0x4a,0x23,0x2b,0xa0,0x6f,0xd3,0x56,0x6a,0xed,0x55,0xcb,0xe5,0x9f,0x12,0x33,0x2c,0xba,0xd6,0x5d,0x43,0x49,0xa9,0xd2,0x2e,0x7d,0x6e,0x46,0xd2,0xfb,0xdc,0x71,0xd5,0xc8,0xf9,0xda,0x15,0xdf,0xbf,0x17,0xba,0x22,0x51,0x07,},"\x1e\x42\x29\x7f\x8a\xee\xf2\x9a\x84\x2e\x0e\x21\xf5\xdb\xae\x06\x8e\x2c\x9d\xda\xa6\xfd\x34\x8e\x48\x88\x1f\x0d\x42\xc5\x0b\xf0\xec\xf1\x70\x6b\x94\xa5\xd1\x98\x17\xca\x02\xd8\x3e\x9a\xb2\xf9\x9d\x8b\xfa\xaa\x5c\x85\xad\x39\xa1\x50\xb2\x25\xad\x3e\xaf\xa0\x67\x81\x5b\x74\x67\x2f\xe0\x26\xc3\xcc\xc6\x77\x25\x54\x40\xb6\x84\xa7\x6e\x12\x8c\xa2\xcc\xc4\x29\xf1\x52\x57\x7d\x25\xb6\x9f\x40\xdb\x58\x2d\x49\x47\x9a\xfa\xe6\x80\x71\x2d\xc0\xfd\x1f\xe1\x41\x88\x39\x68\x7c\xa6\x0c\xdd\xe9\x74\x14\x04\x62\xf9\x61\x48\x29\x5d\xf1\xce\x43\xa9\x77\x35\x1c\x77\xf2\xf0\xb0\x9a\x6b\x26\xd6\xfe\x96\x5f\xce\xae\x17\xd7\xb8\x62\x03\x71\x40\x24\x28\x54\x4f\xdf\x91\x69\x0b\x44\xe9\xaf\xc2\xe9\x08\x8c\x83\xca\x48\xdc\x85\x76\xf6\x28\x72\x47\x98\xdc\x90\x32\x31\x74\xc4\x49\x96\x59\x65\x02\xa3\x5d\xf8\xb9\x82\xc5\x70\xa6\xcb\x51\xb9\xa1\x97\xd4\x31\xaf\x33\xf0\x2b\x80\x01\x15\x67\xfe\x50\xcf\x45\xac\x11\x1b\x3d\x55\x6f\x8c\x8c\xe5\xae\x8c\x99\x72\xf2\xa9\x93\x6b\x1a\x01\x2b\x9c\x33\x9e\x30\xc9\x73\x12\xb6\x5e\xa5\x9c\x10\x0f\x79\xd7\x95\xb8\xa2\x4b\x31\xa0\xa9\x7d\xc2\x5c\xce\xd6\xb8\xff\x5a\xe1\x45\x33\x9a\x04\x8c\xa1\x2a\x57\x90\x17\xfa\xe8\xd5\xcb\xcb\x61\xd5\x2e\x31\x4d\xd7\xc2\xe7\x20\x10\xc4\x72\x17\xb1\xd0\x68\x78\xbf\x28\x18\xca\x18\x8e\x8e\x30\x79\x60\xc1\x68\x9d\x7d\xfc\x02\x02\x97\x3c\xd2\x9f\x2f\x7b\xa7\x43\x46\x9e\x68\x5e\x0e\x70\x4b\x04\xba\xca\x4f\xab\x54\x88\x44\x8a\x92\x2e\xab\xf4\x0b\xe5\x81\xc1\x99\x4d\x74\xd1\x3a\x36\x6c\xe8\x57\xfb\x40\xa6\xe0\x5d\xa8\x55\x36\x94\x17\x2c\xc3\xfd\x28\x06\x2f\x53\x82\x50\xaa\x8c\x11\xf6\x81\x39\xe7\x9c\xd1\x19\x1b\xa3\x31\x4b\x5c\xea\x08\x64\x43\x7e\xd2\xe4\xb6\xfb\xd7\x5b\x9d\xed\x09\x87\xb4\x1c\x20\x2a\x58\xec\x02\x54\xd9\xd3\x71\xa7\x95\xf1\xdb\xec\xdd\xac\x11\x2b\xe8\xd0\x9e\x2d\x7b\x9c\xa5\x75\x2f\x40\x6c\xff\xb9\x11\xca\x36\x45\x0b\xc0\x5f\x1e\xc1\xca\x3c\xa8\xd3\x51\x24\xd1\x28\x6c\x55\xf1\x0f\x61\x33\x4e\x46\xec\xe4\x18\x3b\x92\x21\x9a\x9d\xcd\x0e\x5e\x78\xef\x2a\x76\xcf\xe9\xa9\xab\x37\x95\xdf\xdc\xb4\x4f\x63\xd4\x5f\x5f\x48\xff\xb4\x15\x61\x33\xad\x2e\x99\x50\x88\x4c\x5b\xbd\x2c\x1c\xb8\x72\x9e\x40\xa8\x78\x7f\x78\x49\x69\xfa\x88\x0c\x07\xff\xcc\x97\xd5\xc0\xd2\xd4\x88\x08\x5e\x91\x16\xd7\x10\x7c\xd5\xdb\x16\xce\xcc\xde\xad\x55\x02\x5e\xea\x2e\xde\xe9\x3c\x1b\x10\x64\x27\x61\x8e\xe0\x9d\xc3\xda\xd1\xe0\x56\x76\xa2\x36\x80\x69\xc8\x04\x5c\x3e\xbc\x6c\x67\xaf\xa5\x2d\x59\x39\x82\x48\xef\xcf\x15\xe9\x04\xc7\x14\x23\x04\xff\x61\x97\x1f\x4d\x9b\xf6\x46\x0c\x1d\x64\x17"}, -{{0x67,0x91,0xbd,0x74,0xd3,0xb4,0x62,0x0e,0xf5,0xf1,0xff,0x56,0x40,0x64,0x32,0xc2,0x6a,0xb6,0x46,0xf6,0xd5,0xe9,0xdd,0xa6,0x84,0x2e,0xd6,0x90,0x52,0x27,0x53,0x92,},{0xda,0x99,0x15,0xa7,0x55,0x2f,0x11,0x0f,0xae,0xa1,0x2d,0x47,0x92,0x0a,0x09,0x60,0x14,0x43,0xd4,0x00,0x0a,0x9c,0x7e,0x21,0x8d,0x5b,0xa7,0x2b,0x74,0x98,0x9f,0xa6,},{0xb1,0xe8,0xd4,0x81,0x06,0x5b,0xd5,0x12,0x1b,0xb3,0xbf,0x56,0x96,0x00,0xbc,0xc2,0x6d,0xf4,0x0c,0x49,0x9f,0xba,0xa9,0x54,0xb3,0x9a,0x61,0x9d,0xc4,0x0b,0x95,0x90,0xc3,0x17,0x56,0xb8,0xb6,0x3f,0x86,0x01,0x51,0x69,0x4b,0x95,0x76,0x5d,0x69,0x7b,0x2e,0x1a,0xde,0x08,0x06,0xe9,0x2a,0x06,0xc4,0xa5,0x59,0xe9,0x0f,0xcf,0xa5,0x06,},"\x36\xa2\x0e\x66\xbb\x29\x15\x51\x61\xad\x85\xee\xfe\x89\x3b\x53\xac\x5a\xde\x16\x5f\x08\x9a\x77\x19\x0b\x0c\x23\x9d\xec\x8a\x20\x16\x85\xb0\x76\xb4\xde\xd4\xa1\x0a\xa4\x59\xb9\x80\xa8\xcc\xa4\x7d\x5f\x8d\xe4\xd2\xa6\x62\xe4\x46\xd5\xf7\xfb\x70\xed\x9b\xe0\x5d\xb1\xcc\xea\xdd\x13\x0b\x33\x46\xd9\x40\x9f\x9d\x6e\xf5\x28\x24\xc7\x64\xac\x6f\xb1\xcd\x15\x6d\xbd\x6a\x47\x3a\xe7\x22\xd0\xeb\xb2\x56\x38\xc5\x12\x65\xa2\x2f\xeb\xbb\x14\x96\x7d\x6d\xd8\x25\x3c\x1d\x03\x88\x95\xc6\x73\x7f\x06\x7c\x8f\x73\xc3\xc1\xcb\xe6\xcd\xa4\x36\x96\x32\xd7\xf4\xc9\xac\xeb\xe8\x7d\x05\x71\xc8\x1a\x58\xcf\xd7\x2c\xce\x4a\x5c\xf5\x3a\x1e\x75\x25\x9f\x4c\x99\x3e\x67\xef\xc8\xd9\xc3\x57\x6c\x43\xaf\x04\xa5\xca\xf3\x3d\x85\x6f\x7f\x27\x55\xd3\xa9\x75\xab\x2b\x68\x5c\x6f\x65\x68\x0c\xba\x9a\xc8\x79\xf3\xa8\xc9\xa4\x76\x5b\x87\x9c\x0a\xde\x1e\x4b\xd0\xd4\xa7\x0b\xb6\xf9\x2b\x24\xd4\x29\xdc\x74\x6c\xc7\x8f\x84\x81\x1f\x07\x6f\x32\xc6\x1e\x35\x85\xcc\x8a\xad\xe9\xb0\xca\x15\x22\x4b\xfb\xfe\x18\xbe\x10\xa3\x36\x43\x60\x0f\x66\x12\xbf\x01\x3f\x0e\xfc\xca\x83\x72\x46\xa0\xee\x5b\x03\xc0\x2f\x15\x73\x62\x4c\x4a\x44\xa9\x0f\x9e\x42\x3d\x4e\x56\x06\x1a\x71\xd0\x14\x4f\x5a\x88\x7a\x8c\xd4\xa9\xd6\xf2\x47\x90\x4e\x26\x79\x59\x51\x95\x9d\xa1\x21\xc8\x3c\x6c\x94\x1e\x2b\x6b\x9a\xb7\x62\x09\xff\xe9\x17\x85\x91\xea\xd6\x82\x30\xb9\x4a\xe9\x7d\xf5\x8f\x9f\x17\x24\x28\xc9\x50\x67\x59\x8a\xc5\x82\xff\xb9\x50\x84\x0d\x82\x66\x30\xc4\x62\x5f\x5d\xea\xdd\xec\x13\x05\x20\x3b\x4d\xb6\xb9\x45\xf9\x91\xed\x7c\xd3\xd6\xfa\xbc\xa5\x1e\x21\x66\xad\xad\x0a\xad\x51\x17\x33\x6d\x52\xd5\x94\x22\xf0\x13\x5c\x8f\xa8\xcd\xd0\x88\x4b\xe7\x35\x86\xbf\x28\x4e\x5d\xdd\xdb\xcb\x95\xb4\x11\xf9\x85\x68\x52\x6f\xbe\x71\xa5\x59\x2b\x56\xad\x5a\x73\x45\xf2\x87\x4d\xb1\xd5\x7b\xea\xb4\x3e\x8c\xc6\x95\x47\x52\x06\x29\xf0\xee\x76\xdb\xf4\x32\xa3\x76\xfa\xd2\x8b\xfc\x77\xe1\x4d\x84\x0f\x0c\x02\xd4\x78\xf1\xe2\x33\x7c\x23\xb8\x9e\x73\xe5\x27\x91\x08\xb5\x60\x9b\x18\xe8\x0d\xb0\xde\x11\xcf\xa9\x4e\xcf\x72\x39\xbc\xff\x59\xc5\x41\x18\xe4\xed\xe4\xfb\xfc\x08\x23\xae\x54\x60\x16\xf7\x74\xc5\x21\x98\xa9\x63\xb5\x54\x5a\x34\x89\xb8\x9d\xf7\x62\x6f\xd1\x1e\xd4\x65\x8d\x71\x5a\x46\x57\x99\x40\x35\xd4\x03\xb3\x37\x0d\x14\xee\xd9\x71\x8d\x59\x8d\xb6\x75\xf0\x42\x59\x2f\xea\x89\x05\x65\x44\xb3\x2e\x5b\x9c\x80\x62\x82\x8a\xaa\x3c\xf5\x9c\xb4\x76\xad\x36\xdb\x1d\xaa\x24\x82\x22\x7a\x9b\x7a\xfb\xc1\x53\xce\x93\x25\x3d\x1b\x39\xda\x95\xeb\x96\xf8\x31\x28\xff\x25\x54\xa5\x47\xe3\x4e\xea\x4a\x00\x00"}, -{{0x23,0x4c,0xe4,0xd3,0x9b,0x5e,0xba,0xbe,0x9a,0x2c,0x1e,0x71,0x97,0x0d,0x71,0x81,0x38,0xdc,0xb5,0x30,0xcf,0xd2,0x96,0x02,0x34,0x27,0xd8,0x92,0xbf,0x88,0xf8,0xa4,},{0xcb,0x73,0x93,0x0d,0xb4,0x21,0xf6,0xd2,0x45,0x36,0x83,0x7b,0xd0,0xbf,0xf6,0xfa,0x75,0xbb,0xd1,0x41,0xc9,0x8a,0x40,0x5d,0x42,0x44,0xa3,0xc4,0x24,0x55,0x07,0x79,},{0xf6,0xd0,0x60,0xed,0x7d,0x18,0x27,0x3f,0x18,0xf7,0xa6,0x9c,0xd1,0xd8,0x12,0x6e,0x47,0x8e,0x88,0xa1,0xd7,0x29,0x4f,0xf6,0x04,0x08,0x46,0xd4,0x61,0x07,0xc3,0xe4,0x1a,0x42,0x3b,0xab,0xb2,0x41,0x71,0x39,0xfe,0x58,0x7d,0x29,0x10,0x27,0x1a,0x35,0x7f,0xe5,0xbf,0x57,0xc9,0x2e,0xe3,0xa7,0xb7,0x75,0x33,0x72,0x9d,0x0a,0xc2,0x0d,},"\x77\x73\x0c\xf8\xc8\xf9\x6b\x91\x87\x90\x2a\xcf\xf9\xff\x0b\x21\x74\x6c\xca\xf0\xa3\x82\xa7\xb3\x43\xd1\xc7\x20\x27\xae\x3c\x31\x68\xa7\x3a\x6b\x8f\x49\xbc\x87\x98\x14\x1e\x15\xc2\x73\x2b\x6a\x6b\x3f\x75\x7f\x8a\x8e\x86\xc7\xa4\xba\xcb\x39\x55\x1c\x54\x87\x4d\x6b\xf7\x16\x89\x7e\xe4\xaf\x13\x25\x3a\xa5\xbb\x79\xa1\x92\x10\x4f\x44\xdc\xb3\xde\x96\x07\x45\xa8\xe6\xaa\x98\x80\x52\x4a\x62\x9f\xb5\x10\xa4\xce\x4c\xbd\xa7\xe2\x95\x7d\xff\x1d\x62\xe7\x05\x60\x6a\x2c\xc8\x4f\x91\x85\x0b\xea\xac\x5e\x58\x46\xe1\x42\x0b\xc9\x1d\xcd\xd2\x42\x7b\x69\xcf\xa4\x6a\xe3\x8a\x4f\xef\x41\x46\xea\xe3\x5f\x9c\x22\xe9\x67\xcb\x14\xa1\xaf\x9c\xab\xf8\x3b\x18\x04\x65\xbe\xd6\xef\x2c\xda\x38\x2a\x84\xd9\x99\x4a\xad\x65\x5d\x89\x52\xe0\xfb\xb0\xf9\x6f\xc8\x08\x9f\x2e\x74\x89\x49\x7f\xac\xdc\xd6\x56\xa8\xa4\x51\xb9\x28\xc1\x1e\x7a\x40\x75\x07\x2a\xaf\xbf\x17\xd8\xf1\x05\x4c\x91\x96\x28\x8d\xed\x3a\xe2\x1f\x9a\xfd\x58\x10\xa1\x00\xd8\xe4\xd8\x4c\x4a\x35\xa9\x8b\x30\xd3\xe1\x85\x24\x43\x8d\xd4\x40\x2d\xfd\x8e\x76\x75\xf0\x9d\x08\x0c\xd9\x15\xf1\x4a\xf4\x37\x2f\x7c\xe5\x83\x84\x97\x2d\x5d\x11\x10\x79\x65\x1b\x2a\xcf\x39\xd2\xa1\x67\xc6\xa0\x0b\x2b\x17\xce\x0b\x26\x87\x91\xbd\x2b\xe5\x17\x8f\xe0\xf8\x2d\x64\xda\xcd\xde\x37\x7a\x1e\x8b\xe9\xe7\xd8\xdf\xc8\x2b\x08\x64\x45\x37\xbd\xc8\x70\xc5\x81\x92\x86\xfd\x51\xf6\x79\x2d\xc5\xf6\x7b\x54\xbe\x33\x6d\x44\xd5\x4f\xeb\xf8\x1b\x8d\xf8\xde\xc5\xd8\x68\x6d\xb1\x2f\x16\x4d\x0e\x8f\xf1\xaa\x2c\x16\xba\xcc\x98\x06\x01\x0e\xc8\xe9\x11\x96\x59\x7e\xf0\x6a\x4c\xf1\x70\x7d\xef\x50\x67\xa0\x48\x89\xd8\xe4\x8a\x9b\xc2\xc0\xbe\xf6\x64\xf5\xac\xd1\xb4\xf5\xbc\x2d\xa7\xda\x43\xdc\xb5\xf9\x63\x24\x5b\xa5\x52\xfd\x49\x30\x01\xd8\x70\xa9\x51\x7a\x17\x9c\x2f\x0d\xe8\x5b\xe0\xc6\x82\xd0\x57\x48\x8e\x35\xc7\x81\x6f\xf4\xba\x52\x9a\xef\xd7\xc6\x60\x91\xf2\x06\xf5\xf4\xd7\x5c\xac\x8b\xd2\x09\xec\x2f\xa5\x5b\xe7\x4a\xf2\x31\xe2\xf3\x89\xdc\xc2\xd6\x68\xbf\x69\x5e\xd2\x67\xc3\x59\x4b\xad\x9e\xfc\x00\x21\x7c\x7a\x0e\x9e\x7b\x6a\x56\xa3\x30\x79\xa3\x0e\x73\xc3\x73\x3f\x2d\x24\xef\xec\xdd\xe8\x7f\x72\xf9\x48\xd2\x77\xd6\xb6\xd5\xb0\x35\xb4\xc5\x31\x80\xd2\x3d\x66\xcc\x0f\xf1\x7c\x15\xdd\x46\x85\x85\xe3\x89\xd9\x1a\x4c\x97\xfd\x80\x11\x0b\x21\x8a\x0b\xf7\xa5\xe0\x35\x3f\x46\x09\xd2\xcf\x01\x8a\x06\x55\x71\x00\x1c\x78\x88\x55\x5e\xed\xbd\x36\x22\xc3\xb1\x76\x9c\xd1\x3f\x33\x37\x47\x72\xaa\x6c\x8a\x8f\x58\x81\x02\x01\x7d\x4e\xe4\xe5\x0d\xcb\xbd\xb1\xd6\x10\xc3\x26\x70\x93\x4a\x6d\x9e\x6d\x9b\x78\x4b\xbf\xe7\x18\x62\xbb\x38"}, -{{0x10,0x3d,0x11,0x8c,0x7d,0xd6,0x5d,0x07,0xe8,0xd5,0x58,0x2e,0x45,0x04,0x2a,0x75,0x79,0x24,0x17,0xc6,0x92,0x00,0x1e,0xe6,0xbd,0x9a,0x92,0x7b,0x2b,0x3d,0x90,0x16,},{0xb4,0x5c,0xc9,0x45,0x14,0xa6,0xad,0x67,0x24,0x96,0xcd,0x4e,0xb9,0xfd,0xaf,0xc1,0xd4,0xa1,0x67,0x07,0x2c,0x68,0x74,0xdc,0x8f,0xf1,0x6d,0x76,0x1f,0xb6,0x69,0x86,},{0x2f,0xaf,0xc1,0x3c,0x43,0xaf,0xe5,0x05,0x43,0x72,0xb9,0x23,0xd2,0x4f,0x29,0x2b,0x28,0x3a,0xfc,0xa3,0xac,0xa3,0xb3,0xe4,0x32,0x38,0x06,0x84,0x96,0x17,0x13,0xc8,0xd2,0x3e,0x86,0xb3,0x58,0x04,0x95,0xdf,0xba,0xe4,0x24,0xb7,0x67,0xe4,0x79,0x5a,0x0f,0x92,0x2f,0x71,0xb5,0x0f,0x5d,0x7a,0x36,0x9a,0xb8,0xc6,0xe8,0x80,0x42,0x0c,},"\x5a\x8e\xe0\x79\x18\x6b\x51\xcf\x46\x29\x83\x4d\xe0\xc6\xbd\x73\x34\x85\x50\x39\xa7\x63\x1d\x68\x87\x65\x2a\x77\x28\x99\x59\x72\xe3\x62\xc1\xc4\x09\xf0\x84\xf5\xaa\xf2\x98\x6a\xe3\xf5\x36\xbe\x00\x70\xc4\xba\xf4\x59\xef\x60\xa0\x15\xef\x9d\x70\xdf\xa3\xea\x96\x71\x1c\xbb\x18\xe9\x2a\xf5\x0c\x52\x7d\x7e\xd4\x57\x87\x7a\x07\xab\x83\x72\x15\x18\xc8\x9f\x7a\x86\x41\x91\xb1\xe9\x74\x33\xb7\xc6\xcd\x63\x4a\x83\x2e\x19\x89\x1e\x76\xc6\x21\x22\xa4\x9d\xbf\xfd\x83\x49\x8a\xa4\x16\xac\xcc\xb7\x73\x7f\xe7\x5f\x4f\xb2\xc3\x53\x28\xe6\xf6\xec\xec\xaa\xa4\x2e\x43\xdb\xa5\xbc\x96\x89\x67\x3d\xab\x96\xf0\xbe\xfa\x3c\x83\xeb\x41\xd4\xd8\x87\xb3\xa1\x17\xd0\x55\xe3\x0b\xb8\x7f\xbe\x7c\x71\x94\x72\xf6\xc7\xa4\xcc\x45\xf6\x28\xf5\xfa\xdd\xc4\x8c\xa3\x44\xf7\x7b\x73\x3c\x0e\x3b\x9f\x50\x79\xdb\xd0\x7a\xf3\xa3\x84\x7a\xf1\x41\x71\x9c\xca\x2f\x6a\x76\x65\x52\xb4\x5d\x0f\xdc\xdb\x98\x68\xf2\xc7\x62\xb6\xd4\x93\x3b\xa1\x08\x36\xf9\x5b\xff\x71\xcb\x88\x04\x00\x24\xc9\x05\x34\xc4\xd7\xa9\x5a\x23\x03\xb0\x4c\x29\x61\x01\x2a\xf5\x8b\xc7\x84\xa9\x63\x27\xbb\xfe\xd0\x39\xd0\x80\x2a\x05\x26\x2d\x8e\x66\x3b\x78\x50\x8e\x92\x50\x8b\xc1\xf2\xea\x2b\x9b\xe7\x58\x0b\xde\x10\xa4\xd6\x63\xd0\xd2\x5b\x0e\x97\x3b\x8c\x5d\xed\x59\xde\xbf\x19\xbb\x04\x4a\xff\x1c\x60\xc7\x0e\xa1\xae\xfe\x85\xf6\xd1\x5c\x2c\x1b\x84\x75\x3b\x59\x57\x6a\x49\x47\x3d\x65\xaf\x3e\xd9\x41\xa3\xd5\x14\xb5\xc4\x52\x2c\x14\x1b\xdb\xee\xd9\xcb\x33\x96\x95\xb2\xe0\x2d\xc0\x70\x00\x86\x7f\x1b\xf8\xed\x8c\xfd\x3b\x1a\xfe\x68\x8f\xbc\xa8\x0e\x2f\x9b\xa5\xc0\xb1\x88\xa1\x9a\xda\xff\x66\x86\xca\x0f\xf0\xed\xd4\x44\x66\x12\x91\xfa\x27\xca\x1f\xc5\x29\x42\x9a\x5d\x8f\xf7\x9e\xd2\x02\x7c\x60\xff\xe3\xb2\xc0\x3f\xb8\xa6\x6a\x39\x85\x41\x7b\xa4\xac\xe7\xd1\x4f\xd0\xe2\x37\x1e\xdf\x5d\x71\xbc\x02\xb9\x05\x27\x67\xc7\xf7\x2c\x4e\x6f\x3f\x30\xe0\x63\x82\x76\xb9\xc4\x20\xaa\x43\x33\x09\x5d\x31\x31\x30\x33\x09\x05\x82\xe3\xac\x4d\x9f\xd3\x20\x31\x20\xba\x25\x14\x97\x3a\xb9\xd1\xc7\xfc\x42\x29\x01\x16\xb5\x1d\xae\x9f\xd5\x79\x41\x0a\xe0\x78\xed\x32\x0a\x5a\x1b\x49\xaa\x7b\x5f\xef\xcd\x75\x63\x95\x21\x3a\xf8\x64\x1e\x29\xb0\xeb\xb5\xb8\x3e\x37\x80\xe5\xd1\x0e\x9d\x3d\x11\x99\x81\x48\xf6\xc6\xf8\x6c\x4d\x4e\xb2\x52\xe2\x8c\x70\xfa\x3a\x55\xc4\x3d\x4d\x7f\xaa\xfc\xbc\xdd\x45\xad\x26\x37\xf2\x15\xe8\x15\x49\xeb\x8a\x4c\xde\x47\x15\xb7\x10\x72\x07\x50\x3a\x79\x59\x50\x60\xb8\x3a\xce\x8f\xeb\x67\x3b\x99\x79\x68\x46\x9d\xd9\xb4\xad\x6a\x7e\xa8\x1c\x6e\x61\x81\x00\x33\xf3\xed\xfc\x13\x7d\x97\x42\x09\x57\x5c"}, -{{0x47,0xee,0xe2,0x02,0x4d,0xbe,0x09,0x95,0x3e,0x98,0x1f,0x69,0x86,0x52,0x0f,0x66,0x60,0x82,0xaa,0x9e,0xf4,0x89,0x2d,0xfd,0xfb,0xdb,0xd2,0x50,0xd2,0xa1,0xdf,0x28,},{0x9f,0x13,0xcd,0x8e,0xbf,0x50,0x80,0x34,0x79,0x75,0x15,0x9f,0x36,0x02,0x96,0xa7,0x16,0x40,0x14,0xd8,0xd0,0x69,0xe8,0x31,0xda,0xb0,0x33,0x26,0x07,0x99,0x7c,0xde,},{0x5d,0xef,0xae,0x0e,0x17,0x3e,0xcc,0x18,0xd5,0xf0,0x1e,0xc9,0x29,0x1b,0xe1,0x60,0xd5,0xea,0xbf,0xf6,0x3f,0xd5,0x42,0x3f,0x2b,0xc6,0x6e,0x3f,0x64,0x08,0xc1,0x96,0x35,0x35,0x02,0xdc,0xef,0x21,0xef,0xfa,0x4b,0x9c,0x14,0xbf,0x27,0xb6,0x87,0xd1,0xb6,0xe8,0x6b,0x2a,0x20,0x5a,0x89,0xeb,0x35,0xc3,0x76,0xa3,0xa3,0x25,0x69,0x0d,},"\xc1\x33\xf0\x33\xcf\x3b\xec\x6c\xd1\x92\x12\xea\x47\xdb\xec\xb1\x3f\x2c\x60\x18\xf9\xe0\x87\x8a\xc8\x84\xbf\xb5\x75\xc0\xf5\xd3\xfc\x5b\x49\x99\x58\x0e\xb8\xac\xbc\xaa\xc8\x3a\xe9\xac\x9b\x44\x3e\x6d\x1c\xff\x44\x9c\x36\x89\xb4\x33\xd5\x09\x00\xb2\xe8\xb7\x1d\x00\xe1\x19\xc8\xb8\x75\x09\x4b\xda\xb9\x16\xad\xaa\xb7\x5b\xcc\x85\x29\x59\xd8\xd7\x59\x79\x5b\xbd\x6b\x36\x0e\xe4\x84\xaf\xe4\x7b\x1a\xd2\x83\x91\xf2\x5a\xfb\x8d\x4e\x3a\xfe\x0c\x5b\x60\x04\x98\xa1\x28\x33\xfe\x2a\x1a\x54\x83\xdf\x94\x0b\x17\x3b\xa0\xd9\xd8\xc4\xd1\x32\x1f\xa4\xb7\x33\x33\x4b\x0f\x6d\x87\x8a\x0e\x5a\x76\xf4\xf1\x80\xac\x11\x9a\x82\x08\x2a\xcb\x14\x88\xe4\x9b\xbc\xa7\xa0\x36\x9c\x19\x1b\xd6\xd0\xc5\xd4\x45\x65\x68\x21\xa9\x9c\xcb\xc9\x45\x94\x9e\xca\x81\x36\xcc\x6e\x12\x7d\x9d\xe9\x2e\xf6\x4f\x17\x4a\x6c\x04\xc8\xb5\xe5\x24\x95\xf0\xdd\x67\x4b\xb5\xca\x12\x8a\x92\x09\x96\x8f\xd4\x50\xdc\xe3\x19\x91\x3f\xd6\xa3\x0c\x33\x82\x79\x81\x63\xe6\x58\x5f\x58\xef\x20\x8b\xe4\xd0\xc6\xa2\x51\x3a\x75\x23\x88\x39\x7a\x4a\xe4\x44\x83\x8c\x84\x66\xdb\xc3\x6f\xbc\x36\xae\x08\xbe\xc8\x8e\xed\xa1\x31\xc1\x4d\x06\x36\x6b\x67\x31\x51\x45\x41\x00\xde\xa1\x11\x81\x50\xfb\xe4\x41\xb1\xe7\x82\x6e\x54\x5d\x98\x68\x24\x2e\x89\x9f\x5e\xa5\x3e\x43\x4c\x37\x93\x6c\xe6\xfd\x06\x14\x62\x83\xe8\xfb\xd5\x36\x48\x0d\xe5\x5a\x16\x10\x2c\x44\x75\x4b\xc5\x54\xd5\xbc\x2d\xe2\xf2\x5e\x19\xe5\x67\xa0\x23\xdf\x46\x40\xe7\x4f\xf3\xa4\x9e\x4d\xd3\x0e\x0e\x25\x58\xb3\xdb\xc2\xaa\xb9\x2f\xdd\x5e\x79\x42\x5e\xcb\xc4\xc6\x99\xfe\x1f\x16\x19\x65\xf1\xd0\xb4\x5d\x8b\xda\xb5\x2e\xc9\xbf\x7a\x69\xd8\xaa\x0b\xd1\x71\xe7\x55\xce\x7b\x8d\x07\x18\xf7\x26\x7a\xfb\x73\x3e\xfc\xa5\x4b\x21\x3e\x6f\x5a\xda\xb4\xc9\xd7\x6c\x86\x7f\xcb\x69\xae\x05\xc7\x4b\xd2\x15\x16\xcf\x34\x2c\x61\x61\xf6\xfc\x9e\xcc\xac\xf9\x70\xeb\xce\x54\x0c\xd8\x92\xbc\x10\x6c\x6b\xd5\x63\x61\x02\x98\xb7\x09\x68\xf0\x91\xbc\xc6\xe1\xf7\xab\x4a\x5b\x2c\x63\x74\xa1\x90\x3f\x4d\x3a\xd5\xe1\xbd\x86\x43\xa9\xc2\xf8\x78\xc3\xd7\xa4\xdc\x49\xef\x31\x97\xed\xbc\xda\x7b\xb9\x1e\x7e\x06\x60\x60\x87\xd4\xe9\x81\xbf\xab\x93\xa6\x02\x49\x77\x96\x2e\x45\x26\x25\x17\xf3\x38\xb6\x85\x7e\xec\x21\x58\xa2\x97\xb2\xaa\x91\x52\x4b\x67\x7a\x21\xaa\xc5\x7b\xe0\xb6\x3a\x80\x74\xfe\x54\xe7\xa9\xdc\x70\xc5\xa5\xc3\xde\x72\x8b\x9c\x17\xec\x12\x12\xab\x11\x30\xeb\x17\x62\x2c\xd7\xb2\x2a\xb6\xeb\xa9\x18\x5e\x8d\x67\xbe\x6c\x47\xa2\xe5\xad\xc6\x63\xd4\x64\x2c\xc1\x20\x22\x2e\x29\x9f\xe1\x34\xfd\x7f\xcd\x00\xad\xab\xcf\xaa\x64\x2f\xe2\xe0\x8d\xd5\x2e\x2c\x3f\x32"}, -{{0xb6,0xc8,0x8b,0x4c,0x90,0xfd,0x19,0xa1,0x49,0xd3,0x81,0x67,0x19,0x53,0xb9,0xb1,0x6d,0x42,0x8f,0x63,0x61,0xcf,0x50,0x3a,0x11,0x04,0x77,0xe2,0x97,0xf8,0xd2,0xf8,},{0x8e,0xbf,0xb0,0x84,0xf9,0x97,0xb2,0xea,0x79,0x32,0xa2,0x35,0x3b,0x2c,0x8b,0x16,0xbd,0x82,0x5e,0x1a,0xf5,0x87,0xa8,0xeb,0xc5,0x1a,0x6c,0x45,0xae,0xa3,0x43,0xae,},{0x74,0x47,0xa2,0x01,0x81,0xb0,0x2c,0xf1,0xb6,0xad,0x52,0x95,0x69,0xce,0x43,0x7c,0x2a,0x05,0x08,0x11,0x6f,0x50,0x20,0x5c,0x41,0xe6,0x37,0x8b,0x74,0xfe,0x2f,0xc5,0x36,0x30,0xaa,0x0d,0xc4,0xb8,0x0c,0x31,0xcb,0x26,0xc8,0xf0,0x9b,0xf8,0xfa,0xb2,0x7e,0x3a,0xbc,0x8f,0x1f,0x60,0x4a,0x5e,0xc0,0x66,0x31,0xa8,0x4f,0x6f,0x2e,0x06,},"\x7f\x4b\xf4\xf5\x21\x73\xef\xf0\x72\xf8\x18\xd0\xaa\x97\xe6\x93\x5d\x8b\xac\xcf\x48\x39\x66\x32\x53\xb2\x41\x4f\xe6\xb1\xf3\x4c\xf4\x3a\xb1\x20\x15\x5a\x1a\x3a\xea\x7b\x48\x19\xdd\xd1\x03\x16\x73\xb8\xa7\xa6\xbd\x0b\x9d\xda\x4a\xde\xfe\x69\x2a\x56\x16\x2c\x64\x61\x80\x79\x42\x64\xc5\x12\x21\x15\xeb\x90\xa6\xd3\x05\x4f\x08\x43\x02\xdc\xe3\xd8\x36\xac\x3d\xe8\x20\x63\x8b\xd8\x9a\x86\xbf\x0a\x4c\x01\x54\x7c\xfd\xc5\x43\xd6\x76\xfe\x16\x39\xef\x72\xc5\xb8\x45\xc4\x94\xe0\x78\x14\xce\xc8\xa4\x7d\x03\xdf\x73\xbe\x4e\x33\xc0\x5a\xfe\x9a\x19\x0d\xda\x04\x33\x60\x49\x6b\xe4\xcf\x3a\x63\x19\xda\x9a\xb0\x64\x81\x67\x7f\x1a\x43\x74\xd6\x0d\x3d\x3b\x63\x94\xf8\x84\x3c\x86\x9b\x0f\x41\xa1\xe8\x1c\x2b\x1a\x54\xbf\x5a\xac\xbd\x98\x20\x7c\x8d\xba\xcb\x36\x42\x2a\x3a\xa0\x13\xd5\xe8\x49\xe0\x44\xaf\x92\x85\x45\xc0\x46\x09\x7c\xaf\x14\x9d\x97\x02\x15\x11\x5d\xea\x0b\x5a\x85\x40\x1f\xf6\x72\xe0\x2e\xd4\x0b\xd0\xf5\xa4\x40\xcd\x56\x49\x40\x53\xc8\x96\xc3\xbd\x32\x60\x63\x49\xf7\xcb\xe7\xec\xe2\xa2\x23\x0c\xf2\x36\xda\xc5\x9f\x78\x17\x96\x5f\x3f\xa8\x0f\xb4\x8a\xa3\x0b\x0b\x19\xef\xa9\xa9\x65\x91\x64\x6b\xd2\x5e\x67\xc1\x85\xf7\x7e\x21\xd6\x63\x0b\x28\x8d\x4e\x55\x14\x6b\x2a\xbc\x15\xe9\x50\x88\xd9\x36\x08\x07\x75\x61\x81\x54\xbb\xdd\xa1\x15\x70\x2a\x2a\xfd\x6f\xd5\xf5\x6b\x92\x3e\x18\x88\x33\xec\x44\x89\x44\xd3\x02\x83\xe3\x37\x25\x42\x42\xc5\x81\x2d\x72\x45\xa4\xe9\x26\x70\xbc\xe3\x54\x6e\xfa\xed\x22\xd2\x74\xe1\xe6\x04\x8b\x5a\x0f\x01\xef\xbf\x89\x5d\xc4\x24\x94\xba\xf1\x74\x71\x85\xcb\x1a\x4b\x88\xfd\xf1\xe6\x09\x9b\xaa\xbc\x6a\x5a\xb5\xa2\x72\x7b\x1e\x24\x87\x89\xd1\x70\xca\xa2\x44\x96\x71\xa8\xf6\xe0\x94\xc1\x13\x32\xea\x0a\xc2\xaf\xe8\x81\x32\xc6\x44\xff\x88\x3d\x0c\x49\x9a\xd7\x6a\x93\xdf\x47\x2f\xa0\x13\xea\xa2\x7a\xb4\xda\xd6\x79\xd2\x51\x1b\x50\x49\xc4\xe9\x8b\xaa\x2e\x7b\x00\xa5\x34\x89\x1e\x29\x02\x65\xed\xb0\x76\xf7\xdc\xa8\xe6\xfe\xf3\xf4\x33\x03\x4a\x16\x57\x5f\x0e\x53\xda\x45\x77\xe6\xb1\x3f\x0c\xb0\xd7\x85\x87\x0d\x0d\x09\x8d\x5d\x80\xf4\x13\xa2\x68\xba\x84\xe0\x43\x1a\x78\x69\x23\x77\x13\x78\xcd\x57\xb8\x19\x22\x58\xe2\x63\x3c\xdb\xe0\x3c\xc3\x16\xa0\x95\x09\x70\x52\x6f\xd3\xe0\x93\x76\xbc\xef\x0d\x03\xb7\x07\x4e\x59\xa5\xa8\x4f\xc6\x4e\x79\x5a\x81\x21\x56\xd9\x60\x56\x76\x50\xbb\x1e\x14\x24\xb3\xcc\x9a\x4d\x99\xd5\x7b\xa8\x58\xdd\x1a\x0c\xad\x35\x32\xe9\x98\x14\x6e\x79\x26\x40\x45\xe2\x8e\xbb\xfd\x75\xa4\x26\xb0\xbb\x85\x1a\x24\x4a\xd6\xbe\x7b\xd5\x76\x5a\xf4\x93\xdf\xc4\x4e\xe3\x78\xcd\x04\xda\xf3\x91\x7e\xef\x2a\x62\x06"}, -{{0x79,0x49,0xa9,0x47,0x2f,0x72,0x5c,0xe7,0xc6,0x8d,0x7e,0xa8,0xfc,0x16,0xe1,0x3d,0x9e,0x0e,0x0a,0x58,0xf5,0x8c,0x24,0xf9,0x22,0x8c,0x88,0xe8,0x02,0x64,0x09,0x0d,},{0xa3,0x70,0xf8,0x28,0x33,0xf8,0x8b,0x4f,0x5f,0x53,0x10,0xb9,0x18,0xe6,0xaf,0x93,0xbb,0x72,0x4b,0xfb,0xdf,0x3c,0x02,0xc5,0x03,0x78,0x0b,0x2c,0x83,0xab,0x6c,0xc6,},{0xe0,0x28,0x98,0xcc,0x7c,0x30,0xee,0x01,0x64,0x82,0x47,0x49,0x7b,0xe8,0xa9,0xc6,0x37,0x85,0x93,0xdc,0x88,0x20,0xbf,0x7c,0x17,0xff,0xcd,0x18,0x11,0x8a,0xf0,0x98,0x79,0xa7,0x69,0xf5,0x39,0xdd,0x92,0x37,0xe9,0x68,0x21,0x16,0x66,0x34,0x99,0x8f,0x94,0x6d,0xa6,0x5e,0x6d,0xba,0xd8,0x27,0x15,0x11,0x66,0x9e,0x2d,0x6c,0xad,0x02,},"\x95\x53\x86\xb9\x2d\xd6\xbf\x92\x60\x1b\xf8\x1e\x84\xd2\x51\x44\xb5\xfc\x0b\xcd\x7d\x23\xc7\x6e\x7d\xeb\x5f\x5b\xa6\x31\x6b\xb6\x1a\x5d\x8e\x74\x18\x5b\x01\x29\x67\xf0\xa4\x43\x8b\x53\x16\x96\xde\xb4\xb8\x10\x10\x89\xe0\xc0\x48\x2a\xdf\x13\xc0\x61\x31\x91\xb9\x77\xf7\x7b\x04\x19\x81\x41\x47\xf5\xda\x64\xa1\xd3\xbe\xb1\x27\x5b\x98\x49\xd1\x29\x7b\xa8\x53\x2a\xe0\xa6\x47\xa8\xac\xe3\x95\xae\x0e\xd0\x0f\x67\x34\x8c\x5e\xe5\xea\x19\xb5\xf1\xc5\xbd\x2e\x62\x28\x18\xe8\xad\xcb\xa3\xc1\x7c\x27\x98\x7e\x4e\x3d\x6d\x91\x0a\x56\xc7\xe5\x14\x9d\x3f\x55\x74\xfc\x06\x00\x9b\xf4\xdd\x3e\x37\xcf\xe3\xeb\xda\x2c\x21\x16\xd3\x66\xdd\x88\xce\x5e\xa7\x2a\xb3\x87\x49\x05\x85\x44\x3b\x08\x6e\x8a\xa3\x8d\x11\xd3\x82\x0b\x72\xc6\x58\xe4\x63\xcd\xb5\x9c\x53\x93\x01\x1d\x4a\x8f\x4c\xb6\xa1\x95\x22\x93\x04\xe7\x62\x39\xfa\x5e\x8c\x2c\xbe\x0f\x39\xdc\xad\x13\x8a\x0e\xcb\x3c\x51\x57\x9e\xc9\xa1\x20\xa5\x16\x07\xee\xfe\xbf\xa5\x9a\x44\x62\x0e\xa5\xb1\x91\x60\x87\xea\x33\x85\x33\xfc\x13\x2f\xf2\xe4\xa4\x3d\x05\x2f\xd0\x8b\x6b\x1b\x24\xfb\x67\x2f\x73\xc9\xb9\xba\x20\xb7\xc1\xc4\x1e\xa2\x4d\x91\x2d\xe9\xb5\x55\xb6\xe5\x68\x2b\x97\x06\x08\xff\x22\x9a\xd3\x08\x6f\x43\x1f\x9b\xe1\x90\xec\x39\x22\x4b\xa2\xed\x8a\xcb\x4c\x8e\xac\x85\x82\xe2\x3a\xaa\x79\x82\x7c\x44\xe2\x48\xc5\xba\x09\x2d\xda\xc0\xf2\xf7\x96\x84\xaa\x93\xfc\x06\x10\x73\xe1\x82\x1a\x56\xaf\xb9\xbf\xec\x95\x2d\xf2\x71\x9a\x9c\x7a\x40\x3e\x6a\x93\xf7\xa6\x56\xd7\x4b\x61\xc1\xd1\x90\x83\xf8\xd3\xf1\x9e\x65\x9f\xa2\xb7\x18\xe0\xbd\x04\xb6\x93\xd6\x3d\xaf\xb8\x6a\xdb\xee\x5d\x87\xc7\x5b\x7d\x12\x91\x22\xf1\x78\xa0\xe6\x69\xeb\x03\x5c\xa4\xd8\xeb\x45\x39\x7f\x18\x51\x26\x4e\x2c\xf0\xa0\xcd\xd3\x07\x20\xc5\xe1\x39\xcd\x6a\x57\x3f\x1f\xa2\x41\xca\xe9\x42\x58\x05\xac\x79\x60\x3e\x8d\xe3\x50\xef\xdb\x0b\x9b\xc9\x5b\xa7\xb0\x85\xc1\xed\x92\xc1\x2a\xcf\x53\xf5\xd4\xa1\x13\x75\x98\x00\x8f\x2a\x36\x72\xc8\x4e\x5f\x76\x9a\x25\xc7\xa4\xa1\x65\x79\xd8\x62\x88\x77\x49\x72\x60\x6e\x4e\x7d\x85\x26\x3a\xd2\x17\xe0\xdb\xcf\x34\x3f\xe5\x54\xc1\x09\xc5\xd9\x40\x9b\x79\x39\x07\x3a\xc5\x5a\x03\x42\x0f\xec\x28\x9b\x11\x4a\x5c\x54\xc2\x0b\x45\xea\x69\x93\x85\x33\xad\xe7\xb3\xae\x85\xe1\xa7\x83\xdd\x97\x89\x7c\x3a\xe8\x25\x41\x83\xcc\x54\x04\x5c\x2a\x18\xec\xbe\x52\x16\x91\xf2\x61\x9d\x9b\x8f\x1f\xb3\x47\xca\x05\x5a\x7b\x0b\x4c\x24\xf6\x4d\x17\x73\xe0\x14\x16\x44\x1e\xfe\x15\x99\x23\x21\x7a\x84\x87\x4b\x9c\x4e\xc2\x65\xcd\xaa\xb6\x43\x90\x80\x68\x49\x78\x12\xc1\xaf\x15\xc1\x88\x07\x1e\x78\xf5\x97\xfe\xdf\xce\x91\xc5\xd4\xc6"}, -{{0xd6,0x8a,0x5e,0x3c,0x47,0xee,0xdb,0x30,0x99,0xdf,0xfc,0x80,0x4c,0xf1,0x9c,0x5e,0x74,0xbf,0x7b,0xf5,0xf0,0x1f,0x54,0xd4,0xd9,0x1d,0x75,0x74,0xf3,0xd3,0xdc,0x7c,},{0x46,0x46,0x7f,0xe9,0xce,0x3a,0xcf,0xd0,0xd7,0x43,0x46,0xbe,0x21,0xc4,0x62,0x16,0xdb,0x81,0xae,0xce,0x6c,0xe0,0x30,0x8f,0xb8,0xdc,0x63,0x86,0xfc,0x34,0x46,0xcf,},{0x89,0x6f,0xc3,0xca,0xba,0x7f,0xd3,0xfc,0x28,0x5d,0x5e,0xdd,0xdd,0xc0,0x12,0x0c,0xd4,0x6d,0xa7,0xc6,0xef,0xab,0xe6,0x6b,0x15,0x0b,0x00,0x27,0x60,0xb8,0x41,0x4a,0x89,0xac,0x9e,0x7f,0x1f,0x7b,0x7c,0x7b,0x33,0x59,0x8f,0x61,0xf4,0x57,0x18,0xe4,0xff,0x4a,0xc3,0x68,0xff,0x12,0x96,0x14,0xb4,0xfe,0x92,0x19,0xf2,0x37,0xb0,0x09,},"\x59\x6c\x03\xd0\x87\x3f\x57\x2f\x45\xc3\xb1\x6f\x0e\xf4\xb5\x2a\xd2\xbf\x59\xec\x76\xd3\xc0\xe5\x34\xd6\x2c\x1f\x84\x16\x4d\xda\xa4\x25\xfb\x85\xc9\x54\x84\x85\xb7\x06\x46\x77\xe9\x9d\x04\xc3\x9b\x6e\xba\x04\xc9\x66\x39\x7b\xa6\xa5\xf4\xeb\xaa\x69\xa2\x41\xdf\x95\xa6\xe4\x45\x02\x50\x9d\x63\x50\x55\x7e\xbf\xea\x60\x26\x4b\x62\xad\x7f\x74\xd1\x6e\x5d\x25\xd4\x59\x70\xcf\xeb\xeb\x33\xe7\xb1\xba\xc3\x34\x8d\xd0\x3a\x8e\x99\x13\x3b\x26\xbb\xfd\x7a\xa7\x22\xc2\x58\x7f\x72\xd5\x52\x6e\x98\x0d\xa9\xee\xbd\xf1\x08\x21\x1d\xae\x50\xbb\xe8\xc6\x5f\x9a\xbe\xe6\x9a\x1b\xbf\x84\xc0\x3e\x40\x44\x8b\xab\xad\x03\xd3\xcf\x3b\x7d\xe4\x88\x7d\x2b\x47\x73\x77\x02\x79\x64\x82\xd2\x26\x5c\x56\x6b\x0f\x62\x3b\x53\xc8\x67\x1b\xd3\x71\x9e\xde\xc0\xff\xd5\xf4\x9b\x49\xb0\x72\xc1\x56\x4a\x57\xf9\xba\xb6\xb9\x2d\x1f\x06\x8d\x75\x66\x39\xa4\x33\x14\x52\xe6\x1a\xa7\xb2\x18\xa8\x8b\x9d\xb7\x7a\x19\xfb\x82\xf1\x3e\x98\x68\xed\xb7\x98\xd5\xbe\xec\xa5\x5d\x1a\xb0\x95\xb3\x16\x22\x5f\x3f\x63\x90\xf8\x95\x78\xf0\x16\x04\x28\x74\x7b\xcd\x21\xbe\x6a\xe1\xd8\x69\x91\xb4\x8e\xf8\x0d\x56\x92\x50\x85\x8f\xeb\xf3\x27\x6b\xd5\xde\x3d\xb6\x5a\x24\x5c\x8b\xdc\xf1\x48\x8c\x48\x25\x96\x89\x45\x78\x6b\xed\x63\xf3\xd1\x3f\x14\x09\x36\x3b\x94\x85\x60\x47\x68\x58\xb3\x96\xbc\xe5\x88\xe4\x0b\x31\x1d\xdf\xc2\x2a\xd6\x22\xca\x7d\x1e\x69\x56\x14\x64\xdd\xa5\x00\x9e\x63\x8a\xa5\xec\x9f\x4c\x03\x92\x93\xaa\xec\x75\x00\x1f\xfc\x68\xa7\xcb\x3a\xe0\x18\x74\xdc\x7f\x39\xd7\x50\x27\xf5\x9a\x28\x96\x5f\xc1\x95\x30\xc0\x75\x2f\xe9\x9b\x15\x3d\xa7\xc0\xe5\x42\xbd\xa7\x6c\xa1\xe1\x0b\x7e\xa1\x58\xef\xb4\xd8\x21\xfb\xc6\x5e\x72\x71\xad\x99\x41\x09\x53\x15\x44\x7a\xbc\xad\x08\x80\xa0\x07\x5d\xd0\x4b\x13\x25\xc7\x26\x33\xac\xbc\xb2\x61\xfc\xb4\x07\xc2\x64\xa3\x4d\x70\xbf\x1f\x04\x4f\xee\xad\x06\x9a\xf5\xa8\x7d\xd3\x52\xf4\xbd\x81\x10\xfa\x17\x8a\xdb\xd8\xdb\xf2\x3c\x6b\x57\x5c\xdd\x5d\xf2\x2c\xc9\xa5\xcd\xd3\x7d\x9c\x8f\xaa\xb8\x1a\x4c\xb3\xfb\x5c\x4f\xe7\xff\x62\x9d\xba\xa9\xfc\x06\xb8\x0c\x1f\xb6\x91\xc2\x86\x55\x95\x5c\xfe\x5c\xa4\x41\x49\xb1\x50\xb3\xcf\x14\x0d\x9a\xca\xcb\x14\x31\x3a\x72\xc8\x40\x98\xde\x72\xba\xcc\x02\x72\xd7\x9e\xd6\x61\x7f\x72\xde\xc8\x8e\x19\xb8\x44\x25\x49\x2a\x42\x9e\xc6\xd2\xec\x08\xb8\x63\x46\xdf\xbf\x20\xea\x2a\x36\x19\xe7\x7b\x6a\xc6\x42\x30\xeb\xe2\x5f\xa0\x06\x7a\xbb\x5f\x33\xee\x49\xad\xc7\xc4\x4b\xda\x70\x46\xd7\xf2\x24\xf2\xe7\xa4\x89\x56\x83\xfc\xa8\x68\x4e\xd6\xa0\x31\x84\x4f\x57\x86\xbc\xda\x48\xb5\x04\x23\x94\x48\x7b\x52\x40\x2a\x09\x90\x77\x88\xa1\xe1\x40"}, -{{0x31,0xe8,0x2b,0xc1,0xcc,0x5c,0xed,0x21,0xcd,0xc8,0xbf,0xc2,0xdb,0xbb,0x97,0x6b,0x08,0x78,0x0a,0xfc,0x69,0x44,0xaf,0x7e,0x88,0xe5,0x0e,0x67,0x87,0x4d,0x84,0xf1,},{0x8d,0xf9,0x77,0xe2,0xb0,0x40,0xac,0xeb,0xd3,0xda,0xfd,0x67,0xb8,0x7f,0x92,0x16,0xe8,0xc3,0x71,0xbe,0xce,0xd6,0x18,0xfe,0xf3,0xa4,0x96,0xd6,0x51,0xa5,0xd7,0xb5,},{0x24,0x07,0x02,0xac,0x6c,0x68,0xd5,0x97,0xd2,0x22,0xda,0x94,0x9d,0x0c,0x47,0xd1,0x6b,0x39,0x0a,0x47,0x7d,0x1f,0xb5,0x79,0xe9,0xd8,0x94,0x8a,0xdf,0x9b,0x3b,0x6a,0x7f,0xd4,0x45,0x8a,0xe6,0x38,0x5b,0x7e,0x2b,0x68,0x4a,0x05,0xb5,0x5c,0x63,0xfa,0x6c,0xd0,0x87,0xbb,0x90,0x11,0x3c,0xba,0xb8,0xe4,0xaf,0x14,0x2f,0xcf,0x81,0x0e,},"\x69\xd4\x61\xb6\xb7\xa8\x66\xe9\x4c\xd5\x9a\x5a\x23\xbb\xa4\xa1\x27\x66\x02\xf0\x42\xba\xa8\x50\xd5\xb2\x92\x49\xd6\x74\x3a\xda\x04\xd3\xd9\x38\x21\x9a\xbb\xc2\x2a\xda\x66\xa1\x77\x81\x97\xf7\x0b\xf8\x0b\x59\x7a\x8b\x4a\xe0\x0b\xdb\x87\x68\x12\xd3\xab\x4e\xc0\x11\xdf\x73\x34\x1c\x85\x05\x3e\xeb\xcc\x2d\xf0\xac\xfc\x21\x54\x82\x83\xb5\x53\xec\xde\x01\x54\x82\x8e\xd5\xaf\x47\x57\x19\x85\xf8\x97\x67\xb0\x05\xb6\x22\xc9\xe7\xc0\x79\xdd\xe6\x94\xe4\x9d\xc0\x55\x0c\x79\x18\xcc\x51\x5c\x27\x4d\xbd\x9c\x54\x69\xd2\xf1\x8e\xcd\x90\xde\x66\x4e\x03\xca\x41\xe5\x3b\xe2\x0b\x96\xe2\x5a\xf4\x0c\x54\xab\x0f\x7c\xbe\x9e\x05\xca\x3f\xa5\xa3\x7c\x1a\xa8\xeb\xfb\x64\x44\xa3\x2c\x49\x6e\xfc\x68\x15\x7c\x69\xf3\x58\xc1\x5f\x6a\xc0\x9d\x46\xef\xef\x9a\x68\x5d\xf7\xe8\xdd\x63\xb3\x04\xbd\x3c\x63\x8c\xcf\x53\x2f\xe9\x01\xf1\x1c\xf9\x7c\x5b\x1c\xbe\xd3\x3c\x70\x63\x7c\x72\x1b\x02\x89\xad\xf6\xbb\x6d\x87\xc3\x04\x79\xfa\x92\x6e\x04\x30\x74\x30\x2b\x76\xf1\x15\x7d\x0a\x81\xde\xc4\x93\xe8\x7a\x3c\x64\x3e\x7a\x20\xb7\xa4\x15\x25\xa3\x8d\xb0\x4e\x78\xda\xe5\xe7\x79\x70\x66\xbf\xae\x2c\xf4\x48\xa4\x47\xe9\x00\x4c\xce\x8e\x41\xf0\x98\x79\x91\xfa\xd3\x03\x11\xdd\xaa\x45\x9a\x26\x44\xf4\xb9\x41\xc0\x68\xc0\xd6\xc0\x77\x1a\xfc\xf4\x2b\xf9\x13\x9a\x68\x4d\xa2\x98\x48\x6e\xcf\x67\x52\x3b\xf8\x50\x9a\x45\xba\x5c\xb8\xb3\x86\x4a\xd2\x2c\x0c\x6a\x82\x8c\x6d\xb7\x2e\x37\x1d\xe4\x10\xb4\x7d\xac\x49\xae\x9d\x3b\x57\x02\xb1\x73\x9b\x8d\x76\x0c\xe9\x86\x11\xc0\x7d\x88\xdf\x5f\x04\x68\x38\x08\xa2\x1a\xfc\x2e\x61\x71\x3f\xc2\xc0\x25\xcb\x25\xfc\xc4\xee\x94\x18\x41\x08\x3b\x22\xf6\x1e\x26\x56\xfb\x3b\x8d\xad\x41\xc2\x62\xc8\x9d\x2f\x17\x61\x03\x09\xf2\xd5\xc2\x95\x89\xa2\xdf\x61\xe5\x51\x49\x89\x50\x32\xca\x98\x1e\x45\x57\xe1\x30\xa2\x37\xfc\x08\x26\xfc\x87\x25\x29\x86\x1b\xbb\x83\x28\xd6\x73\xf3\x9b\x58\xb7\x3d\x06\x0e\xc5\x96\xbf\x22\xe7\xee\x08\x1f\x44\xe9\x2c\x02\xa5\x67\x76\x79\x52\x0e\x2a\x2b\x4d\x22\xc7\x7f\x2b\x21\x2d\x5a\xaf\x05\x0b\xf2\xc1\x41\xe3\xe2\x8b\x85\x71\xd4\x32\x19\x37\x42\x62\x35\xc7\xa6\x46\xd6\x47\xe3\xef\xe1\x83\xc2\x7b\x74\x92\x56\x5e\xca\xcd\x7f\x43\xc6\x7a\x74\x45\x3f\x47\x80\xe8\x87\x11\xba\x2d\xd4\xa3\x94\x1b\x12\xdd\xd3\x90\x92\x70\xfb\x3d\xeb\xd4\x22\x43\x6a\xb6\x16\x6f\x08\xc9\x9c\x88\x6c\xc0\xe8\xe3\xce\xcd\x06\x42\xe4\x42\x85\xb8\x86\x4a\xa4\x16\x94\x3c\x5a\x18\x69\x74\xf4\x64\x53\x5a\x87\x0a\x01\x28\x61\xbc\x2e\x58\x71\x49\xca\xe9\x71\x62\x4e\x61\xc3\x1d\x8a\x50\x7e\x3a\xd8\x27\x73\xe7\x23\xbc\xb7\x5d\xf5\x4b\xef\x84\x7a\x40\x7b\xcb\x7b\x1d\x57"}, -{{0xcc,0x56,0xbc,0x7c,0xdf,0xa6,0x11,0x92,0x4e,0x72,0xb0,0x7f,0x68,0xab,0xc6,0xca,0x5b,0x85,0xff,0x8b,0xba,0xcd,0xff,0x40,0x6e,0x51,0xba,0x72,0x0d,0x09,0xa8,0x66,},{0x5f,0xfe,0xe2,0x21,0xab,0x4d,0x0f,0xe6,0xf4,0xc9,0x34,0x6c,0x5e,0x5a,0x4b,0x8a,0x63,0x6a,0x6a,0x0b,0xad,0xce,0x96,0x67,0xbe,0x73,0x9f,0x4c,0x9e,0x67,0x33,0xc1,},{0x9b,0x86,0xa1,0x92,0xb6,0x4f,0x4f,0x04,0x4f,0xfb,0xf8,0x7b,0x41,0xc7,0xee,0x52,0xf7,0xa7,0x21,0xaa,0x32,0x0e,0x7b,0xad,0x64,0x25,0x99,0x59,0x90,0x31,0x5c,0xdd,0x50,0x2b,0xe4,0xe1,0x11,0x60,0x19,0xd1,0x31,0xa9,0x21,0x8d,0x19,0x61,0x4a,0xd9,0x55,0x43,0xb1,0x88,0x9a,0xf0,0xa9,0x7e,0xd4,0xd2,0x56,0xdc,0x33,0xd7,0x6e,0x08,},"\x08\x83\x04\xf2\x2e\x1a\x28\x60\x62\xde\xfb\xeb\xb1\x82\x7a\x64\xb7\x6a\x14\xe8\x70\x15\xe7\xf6\x46\x17\x87\x77\xab\xa7\x97\x04\x68\x8d\x7b\xf3\x2e\x1e\xfa\xc9\x7a\x9f\xc3\x39\x81\x0e\xbd\x3d\xf9\x3e\x4e\xa0\x24\x68\x69\x53\xed\x91\xfa\x6d\x2a\xb6\xe0\x7e\xc7\x81\x1a\x6d\x91\xca\x91\xb0\x98\xdb\x47\x25\xdf\x65\x84\x6a\x95\xb8\x08\x63\x5a\x8d\x0c\x5f\xe5\xac\xe2\x5f\x07\x80\xe8\x96\x17\x7b\xc1\xbb\xa1\xcd\xb4\x44\x92\x51\xc0\x1b\x48\x2f\x02\x38\x62\xf8\x8e\x07\x2e\x79\xcd\xe5\xdb\xd6\xc1\xd9\xad\x9c\x07\xc6\x06\xf5\xdf\x85\xa6\xec\xa2\x96\x6c\xbf\xe0\xa1\x67\x39\x68\x11\x2f\x26\xa3\x17\x05\x3f\x16\x7f\x61\x1a\xf2\x97\xef\xa8\x02\xe0\xa9\x4b\x3e\x1f\x33\xa2\x7b\x73\xe5\x59\x7a\xbb\x22\x41\x15\xeb\xe7\x5e\x29\x4a\x1b\xcd\xcd\x97\x92\x55\xb0\xa8\x02\x65\xc0\x89\xaa\xa7\xd6\xbe\xd2\xe3\xd0\xc9\x18\xf5\x6f\x4a\x55\xf4\x48\xd8\x63\x36\x5c\x6c\x58\x46\xfb\x9b\x2b\x9b\xb5\x5f\x6b\x7c\x6d\xff\x58\x47\xb7\x1b\xfd\xd4\xbb\x5b\x9b\xb2\xe4\x24\x9b\xc0\x24\x3a\x02\xab\x4d\x22\xba\x78\xa4\x3d\x18\x21\x95\xae\xd7\x8f\xec\xe8\x4c\xb1\xdd\xae\xb9\xef\xf6\x81\x56\x04\x5b\x29\x32\xe6\x38\xd7\x73\x1d\x0e\x8b\x4c\x9c\x8c\x38\x3b\x0d\x6d\x39\x2d\x21\xfc\x64\x07\x62\xc8\x7d\x36\x92\xb1\x81\x0b\xcc\x4a\x42\x39\x2f\xf1\x3d\x45\x16\x9e\xcb\xf0\x13\x50\x55\x09\x31\x05\x09\x8c\x86\x9b\x68\x88\x7e\x93\x4e\x2b\x9d\xa5\x23\x2a\xc6\xc9\x37\x38\x00\xf7\x0b\x64\xec\x64\xa4\xaa\x0c\xa0\x44\xc0\x77\x7c\xa3\xa3\xac\xaa\x13\x8c\x14\x24\x96\x72\xa5\x5b\x24\xdd\xfe\x4d\xc3\x57\x57\x32\x41\xe1\x4a\xd0\xac\x16\x47\x5a\x8e\x38\x67\x88\x6d\x41\xee\xa3\x5f\xe7\x93\x2b\xa9\xae\xaa\x0c\x86\xc9\xeb\x6d\xb7\x80\x80\x49\xad\xe7\xb5\xcc\x1a\x40\x82\x2c\x66\xde\xa9\x3a\xd2\x2d\x44\xb9\xe4\x29\x04\xb5\xb8\x36\x84\xae\x29\x31\xfe\x36\xc6\x08\xff\x70\x96\xf1\xb0\x9f\x81\x1b\x02\x67\x28\x04\x40\x6e\x08\xed\x9e\x77\x45\x67\x6c\xe0\x47\xf0\xf7\xf6\x47\x08\xe4\x9b\xb7\x87\x54\x72\x0b\x8a\xa2\x26\xf5\x55\x6a\xbf\x05\xb5\x65\x84\x64\x52\x92\xda\xd0\x8e\x24\x73\x63\x9a\x8c\xe5\x47\x5e\x0c\xe9\x19\x2f\x8b\xa2\xdd\x32\xce\x14\xc9\x19\x75\xab\x60\x2f\x7c\x13\x53\x8c\x52\x95\x2d\x03\x96\x15\x8c\x7c\xc6\xb9\x42\xbe\x7d\x92\x3e\xeb\x52\x3a\x73\xb5\xb4\x11\x96\x6d\x14\xac\x96\xe5\xb0\x96\xa5\x29\x32\xa4\x16\x29\x2e\xcc\xdd\xb9\x10\x71\xc8\x85\x60\xe7\x0e\xcd\x4f\xe2\xfe\x24\xd5\x23\xfa\xfc\xb9\x8e\x40\x21\x50\x2f\x41\x90\xa0\x51\x5e\xdc\xb2\x40\x19\xea\xca\x09\xec\x26\x15\xa9\xbf\xde\xb6\x0e\xb3\x54\xc8\x4a\x1f\x3c\xec\x7f\xfd\x7e\x65\xa5\x51\x5d\x47\x95\x9a\x4c\x4e\xc4\x8d\x80\x21\xb1\x75\x4a\xe2\xbf\x84"}, -{{0x7a,0x57,0xf2,0xdd,0xa0,0xad,0x03,0x38,0xab,0x9a,0x13,0xc9,0xa3,0x49,0x7e,0x9c,0x75,0x23,0x8c,0x15,0x31,0x58,0x97,0x89,0x22,0x7c,0xd2,0x74,0x9b,0xc6,0xe9,0x50,},{0x6f,0x73,0x8d,0xc5,0xe7,0xd9,0xe2,0x40,0xc9,0xf4,0xd0,0xc0,0x6a,0x5e,0x02,0x17,0x47,0x56,0x8b,0x69,0xa7,0x5d,0x50,0x7a,0x2e,0x0b,0xe7,0xea,0x61,0x35,0x26,0xc5,},{0x98,0x91,0x23,0x76,0x1d,0x93,0x56,0x32,0x78,0xfd,0x0a,0x78,0xae,0xd6,0x4e,0x2d,0xe6,0xf4,0xa7,0x00,0xfc,0x9a,0x70,0xd2,0x18,0x77,0x48,0xac,0x06,0xd9,0xc2,0xc3,0x77,0xd1,0x99,0x5f,0x89,0xc7,0x72,0x7f,0xe2,0xf1,0x20,0x78,0x4e,0x41,0x71,0xc4,0x2d,0x63,0x53,0xac,0x3d,0x4e,0x3f,0x62,0x0c,0x63,0x9c,0x75,0x78,0x6c,0x46,0x0a,},"\x8c\x85\x75\xa1\x1d\x2f\xf2\xc2\x38\xe4\x19\xcc\xb0\x06\x33\xd0\x4e\x8b\x8b\xd7\x74\x29\x01\xd5\x88\xdd\x6a\x2f\x00\xaa\x12\xf0\x8a\xe4\x1d\xca\xa9\x33\x8f\x8c\x47\xe9\x53\x12\x19\x2c\xf6\xb2\x45\xa0\x0c\xe6\x88\xa0\x29\xda\x56\xdd\x1b\x1d\xeb\x0d\x34\xb5\x41\x4f\xe1\xc2\x1d\x6b\x63\xd0\x6b\x85\x34\xac\xe8\xe8\x66\xc9\x33\xfd\x7c\x5a\x65\xed\xa9\x5a\x17\x37\xa9\xec\xdb\x17\x85\x91\x49\xac\x69\x69\x51\xb8\x2c\x23\x0e\x82\x75\xe9\x6d\xd0\x2f\xd4\x55\xea\x67\x53\x79\xe6\x7b\xa6\x34\x84\xb6\x28\x38\x31\xfe\x3f\xfe\x52\xd6\xec\x49\xb7\x09\x10\x67\x05\xc9\xd1\x9b\x85\x9d\xe9\xfd\x20\x08\x87\xcb\x44\xd8\xfd\xfe\x69\x61\xfa\x4c\xa2\x34\x09\x44\xc7\x64\xc7\x04\x49\x12\x08\x25\x7e\x73\x54\x82\xaf\x8c\xb6\x90\x41\xdd\xe6\x85\x24\x1d\x3f\xbf\x46\xfd\xa0\x57\x24\x8b\x89\x87\xbe\x1f\x80\xb5\x4e\xb5\x40\x09\xf3\x24\xdc\x45\x0e\x88\x6e\x79\xf9\x12\x58\x5b\x91\xc9\xdf\xaf\xe9\x01\x22\x62\xc4\x71\x40\x3b\x1e\x8b\x5c\x31\xfc\x53\x75\xa1\xdd\xf9\x9b\x68\xed\xf9\xed\x70\xaf\x85\x94\xf7\xd8\x4b\x2c\xc4\x91\x1f\xe9\x05\x00\xc6\xee\xbf\xba\xc0\x85\x55\x35\x50\xe3\x5b\xd2\xe5\x25\x14\xe9\x79\xe7\x24\x1e\x9f\x8e\x34\xcd\xf8\x51\x3a\xbe\x72\x51\x0d\xff\x3c\xfe\xc7\xe2\xbc\x64\x88\x64\x1c\xfd\x0a\x65\xae\x0e\x09\xeb\xe9\x9b\x15\xb2\x9d\x45\xea\x67\xa5\x7a\xad\x55\x4d\x4f\x8b\xfc\xe1\x38\x6a\xce\x22\x88\x39\xe3\xa8\xa5\x34\x14\x0e\xec\x3d\x37\xd5\x1b\xe3\x61\xf5\xea\x18\x83\x73\x9f\x56\x61\x5f\x75\xb0\x55\xa0\x6a\x91\x47\x1b\xe9\x8b\xc9\x45\x37\x83\xc3\x58\x38\x2b\xd0\x55\x5a\xe9\xeb\x0b\xdc\xd6\x66\x29\xa6\x11\xfc\x1a\x11\xc6\x53\xc8\x22\x14\x58\x7d\xec\x12\xba\x12\x0e\x25\x13\x07\x0f\xe6\x9e\x98\x2f\x7a\x80\xad\x15\x9f\x6a\x32\x5d\x97\x7d\x01\xd0\x50\xd1\x16\xa6\x2a\x4f\x8a\xca\xb6\xc3\xd6\x9f\xf6\xc8\x78\x21\x3c\x60\xa9\x48\x45\xca\xe1\x06\xde\x6c\x5d\x6f\xe2\x50\x8d\x94\x56\x5b\x7b\xa7\x5d\x58\xd1\xad\x47\xd7\x6a\x20\xde\xfa\x75\x68\xcb\x7f\xd6\x6f\x57\xcf\x37\x74\xa2\x1d\x3f\xfa\x7d\x8a\xa6\xd8\x6d\xc2\x84\xb7\x0e\x0f\x17\xe7\x63\x0b\xfc\x10\xcd\x1f\xc9\xa8\xd9\xc5\x92\xd3\x9f\x24\xa7\xb5\xc8\xe8\xaf\xf3\x53\x57\x7e\x6a\xc9\x00\x86\x90\xc7\xa1\x59\xa7\xe8\x3b\xe5\xa6\xae\x8f\xca\x96\x44\xbd\xdf\xa3\x7a\x92\xb0\x70\x55\xf9\xfa\xc9\xfa\x97\xfb\x3e\x8f\x5f\x4d\x91\x7d\xda\x5c\x6d\xc6\xea\x34\xb6\x4d\x30\x24\x05\xbc\x38\x06\x2e\x07\xce\x93\xa1\xa8\x8a\xed\x5f\xba\xf9\x95\xa0\x9b\x45\xb2\x8a\xd4\xa6\xb2\x73\xde\xc1\x41\x3c\x54\x04\x52\x9d\x82\x5b\x5e\xdc\x2e\x27\xa3\x90\xeb\x7e\x8c\x2b\x43\x90\x5e\x11\x6d\x88\x7a\xb5\xfb\x99\x3d\xfe\x15\x0e\xbd\xcf\x81\x7a\xe6\x2e\x03"}, -{{0x32,0xef,0x6d,0x78,0x9a,0x1e,0xa3,0x93,0xf1,0xbf,0x9f,0x11,0xde,0x34,0xf5,0x7d,0x65,0x3c,0x4e,0x77,0xd5,0x1e,0x60,0x50,0xfe,0xf4,0xe8,0xd7,0xbf,0x18,0x3d,0xb5,},{0xc1,0xaa,0x18,0x1e,0x62,0x0f,0x60,0x52,0x5c,0x2b,0x17,0xda,0x8d,0x29,0x0b,0xae,0x5d,0x33,0x9e,0x17,0xea,0xbc,0xea,0xb5,0x8c,0xd7,0x6a,0xe0,0x66,0xf4,0x11,0x79,},{0x88,0xf3,0xa6,0xe0,0xbb,0xaa,0x3e,0x06,0x0b,0xc9,0xd9,0x1f,0xe2,0x96,0x8c,0x61,0x12,0x6b,0x20,0x31,0x7f,0x59,0x84,0x2e,0x4a,0xe4,0x87,0x11,0xcd,0xba,0xf6,0x2c,0x6c,0x02,0x07,0x40,0x5d,0x1c,0x48,0x49,0x95,0x02,0x71,0xf0,0xaa,0xa7,0x59,0x30,0x91,0x10,0x9e,0x47,0x8d,0x13,0xf3,0x56,0x96,0x4f,0x7d,0xba,0xb7,0x29,0xaf,0x00,},"\x11\xa9\xc3\xc1\xba\x7c\xfb\x61\xad\x10\x33\x05\xc2\x58\x86\xde\x9f\x88\x15\xc6\xc2\x1f\x17\xa8\x73\x3a\x02\x4f\x94\x97\xda\x05\x40\xdb\x36\x03\xa6\x71\xaa\xe8\x37\xdb\xbb\xa1\x9e\x19\xf8\x2d\xdf\xc8\xaf\x85\x59\x80\xa7\x01\x25\xfc\x61\xcd\x7f\xfd\x10\x77\x7e\x36\x6e\x5e\x95\x69\x92\x7a\xf0\xf2\x45\xd4\xf3\x9b\x3f\xd0\xf4\x58\x79\xc2\x53\x40\x14\x12\x85\x5e\x57\x61\x90\x5e\xd6\xef\x31\x8b\x6a\x06\xea\x6e\x9f\x90\x6f\x9b\xd0\x16\xbc\xb6\x94\xa0\xdf\x65\xa0\x16\xbd\xfe\x84\x5a\x09\xf2\x3e\x50\x86\xc5\xaa\xf3\x75\xef\xeb\x86\xda\x51\x23\x9d\xdc\x35\x0b\xac\x0c\xdb\x03\xb8\x74\xdb\x15\x07\xe6\xad\x4e\x2c\x9f\x46\x02\x8c\xa2\x38\x83\x63\x54\x14\x93\xb6\xcb\x92\xc1\xdf\xca\xa3\xef\xd6\x8c\x6b\x4e\x91\xef\xb4\x67\x51\xd2\x3f\x4c\x48\xa9\x73\xf0\xa5\xc7\xc6\xfe\x2a\x12\x69\xd2\xa6\x9e\x9f\xc4\xab\x8b\xa3\xb9\x2f\x79\x64\x49\xba\x3d\xc7\x02\x45\xed\x50\x5c\xc0\xee\xee\x16\x36\x64\x7a\x68\xc7\x67\x9d\x0b\x6d\x65\x1b\xba\x35\xc2\x9b\x81\x47\x8d\x17\xca\x36\x85\x70\x7a\xd6\x16\xe6\xe5\x60\x43\x81\xf8\x4e\xe5\x2b\x25\xad\x02\xfc\x0d\xfb\x85\x43\x2e\xfb\x1f\xec\xd0\x90\xc0\x2a\xd0\x02\xc1\x85\x7f\xce\xd8\x8f\xdf\xb2\xff\x26\xdd\x0f\x50\x18\xfb\x47\xd8\x13\x58\x1f\x65\x08\xca\x63\x7c\x73\x65\x17\x7c\x51\x3d\x1e\xe0\x58\x79\xa6\x5c\x5b\x67\x6b\x3a\xa8\x73\xa1\x93\x5c\x54\x37\xea\xdc\xb6\x6d\xfb\x05\x2a\x5e\x7c\x3e\x81\xd4\x4b\x3d\xaf\x69\x8f\x42\x24\x4e\xe2\xee\x4b\x6e\xd2\xb7\xe6\xe5\x6e\x61\xff\x9c\xb4\x5e\x71\x9f\xd7\x46\x19\x8b\xf2\xa7\xde\x6d\x25\xaf\x3b\xc6\xc7\xb0\xed\x8a\xbe\x3c\xb3\x89\xaf\xd8\x4f\xfa\x2a\x23\x0d\x93\xbc\x0c\x29\xd5\xa9\x41\x9c\xbf\xf1\x1b\x78\x83\x32\x99\x21\x48\x0b\x58\x44\x65\x5d\x99\x6c\x7c\xab\x29\xdf\xb2\xa3\x92\x7b\x82\xba\x7c\x30\x6c\x45\x77\xb6\xf8\xb5\xdb\xe2\xaf\xaf\x9b\xf1\x4a\x8f\x95\x54\xcd\x01\xa6\x9a\x99\x1b\xf2\x12\x82\x8d\xe1\xe6\x31\x72\xe8\x33\xde\x06\x69\x8c\xdb\x3b\x28\x71\x63\x80\x31\x45\x72\xbf\x5b\xcf\xd3\x4e\xf5\x2a\x6f\xad\xda\x87\xba\xbe\x6b\xac\xdb\x20\xce\x63\xc7\x25\xcb\x0f\xf6\x1f\xe3\x0c\x1b\x51\xdb\xda\x2c\x26\x25\xf9\x9d\xfe\xb0\x29\xa3\xe5\x8c\xba\x7d\x01\x90\x51\x11\xca\xf4\x2f\x27\x02\x5e\x72\x0e\x18\xee\xb0\x7d\xae\x91\x55\xc5\x5a\xa3\x00\xe2\x2e\xb5\xe9\x4d\xc7\xa0\xa8\x4e\xe6\x7d\x91\xa9\x60\xae\x08\xca\x63\x2d\xbb\x17\x37\xfc\x9a\x43\xdb\xcf\xb3\xa8\x79\xeb\x9f\xbf\xfd\x72\x99\x33\x8e\x26\x4b\xc1\x23\x7a\xb6\xa5\xbc\x2a\x26\x3c\xfa\x99\xe8\x54\x44\x39\xd9\x63\x31\x63\x9f\xe9\x40\x8e\x54\xa3\x50\x61\x0f\xf0\x1d\xe3\xf8\x57\x99\xad\xeb\x73\xd8\x2b\xe9\x38\x07\x4d\xea\x85\x8e\xa6\x36\xb6\x3a\xbd"}, -{{0x0a,0x55,0x25,0xa4,0x59,0x8f,0x60,0x99,0x2f,0x86,0xba,0x1a,0xb9,0xee,0xe6,0xe2,0x67,0x56,0x22,0xf9,0x43,0x28,0x4f,0xc0,0x55,0x3e,0x44,0x46,0xac,0x5a,0x4c,0x53,},{0xdb,0x60,0xd7,0xea,0x29,0xf8,0xd6,0x0d,0xad,0x33,0xd0,0x2e,0xc5,0xf4,0x22,0x32,0x05,0x7b,0xd1,0xc4,0xbd,0x61,0x80,0xa2,0x42,0xcb,0x7a,0xb6,0xf4,0x42,0x67,0x81,},{0x8f,0xa6,0xb0,0xae,0xac,0x71,0x13,0x2a,0xd8,0x82,0x97,0x58,0x68,0xf1,0xbd,0xb8,0xc1,0x1f,0x1a,0x6c,0x1b,0x9c,0x54,0x59,0x4e,0x0e,0x46,0x28,0x6e,0xa6,0xc9,0xa5,0xd6,0xd5,0xb0,0xea,0xea,0xca,0x9a,0xe3,0xaf,0x74,0xe7,0x23,0x26,0xb3,0xb6,0xf2,0xea,0xa8,0x93,0xc0,0xec,0x42,0xa4,0x9c,0x56,0xef,0x51,0x4f,0x75,0xc7,0x7f,0x01,},"\xf7\x87\x32\x1b\x42\xc0\x8d\x40\x52\x44\x9a\x48\x85\x93\xd8\x85\xb4\xe0\xc3\x4a\x5d\x64\x14\x9f\xa8\xb9\xc8\x5e\xe5\x4b\xcb\xec\xb5\x09\x09\xb2\xa8\x6b\x88\x25\x8a\x10\xe0\x7e\x8f\x8c\x2d\x06\x8a\x89\xfb\x16\x5a\x6a\xce\x7e\x64\x99\x8b\xa5\x7d\x89\xd9\xbf\x2b\x8b\x38\xa1\xf6\xd8\x36\x4a\xee\x05\xce\x33\x48\xbe\xd4\x8b\x88\xc2\x47\x3b\xf5\xf2\x66\x5f\x51\xca\x07\x3a\x53\x05\x35\x8e\xaa\xd4\x36\x5d\x58\xb8\x3b\xc9\x81\x4e\x25\xf5\x4c\x37\xcd\x9b\x68\xa8\x08\xa5\x7d\x6c\x2d\x7d\x7b\x6d\xeb\x5f\xe2\x0f\x4f\x96\xfe\x72\x5f\x8d\xe6\x5c\x29\xa4\xf1\xcc\xef\xd7\xc2\xc6\xf2\xfc\x01\x16\xd5\x86\x76\xac\xbc\x58\x69\x1c\x79\xc2\xb0\x06\x78\x5a\x09\x75\xa3\x1d\x8d\x3c\x94\x91\x61\x59\x6a\x06\x8a\xaf\x22\x26\xab\x84\x25\x50\xe9\xc0\xb2\x61\x0a\x29\x53\x1d\x1f\x3f\x7f\x00\x82\x6b\xb6\xc7\xdb\xe0\x4e\x28\xae\x1b\x9f\xf6\xf8\x88\xa4\x9d\x82\x81\x2f\x45\x2e\x1b\x32\x74\x0b\x23\x4d\xdd\x96\x42\xe1\x8f\x32\xad\x9a\x9a\xf7\xf8\x95\x25\x28\x67\x4a\x2c\xda\x25\xb4\xf7\xba\x86\x70\x07\xff\xa7\xf7\x8f\x16\x3d\xb8\xf3\x69\x14\x95\x6b\xfa\xec\xd5\x0f\x6d\x1a\xf4\xee\x13\x32\x75\xa8\xea\xab\x94\xbb\xc0\xae\x52\xb6\xd9\xb2\x83\x26\x34\x23\x2e\xc0\xe8\xb5\xf8\x02\x2d\x3e\xf1\xea\xd9\xb7\x9e\xf9\xa1\x65\x64\x27\x71\x94\xf2\x38\x0d\x90\x21\xe1\xf1\x7b\x18\x4b\x8d\x3a\x7a\x34\xd1\x51\x39\xa3\x9c\x77\x28\xc2\x2e\x1a\x3a\x67\xa2\x7a\x6c\xa4\xb8\xa8\xa0\x63\x6c\x60\x54\xd0\xf7\x41\xf0\x46\x67\x36\x19\xfc\x6b\x07\x0e\x62\xff\x48\x62\xf5\x9d\x26\x90\x07\xf3\x43\x13\x39\x63\x7a\x89\xf5\x64\xc0\xdb\x3d\x9b\xcf\xcd\x19\xfc\x25\x13\x8a\xc6\x6d\x47\x4d\x80\xf4\xad\x79\xf6\xd1\xe7\x84\x44\x08\xe8\x80\x34\xee\xaf\xf4\xa7\x90\x33\x8d\x54\x6b\xfc\xd7\x42\x4c\x11\x9e\x21\x1f\x36\x3c\xb8\x9c\x88\x87\x49\x34\x6a\x89\xd3\x2f\x02\x3b\xb6\xb0\x36\x6a\x1e\xde\x43\x25\x03\x2a\xa3\x5f\x52\xe9\xdf\x93\x8a\x50\x27\xeb\xee\x96\x88\xae\x48\x0d\xde\x1a\x9c\x9b\x42\xd1\xa9\xc0\x8f\x71\x92\x23\xdf\xae\x1c\xfc\xd4\x9d\xd1\x05\x3a\xaa\x38\x1c\x24\xcc\x9c\x7a\xbf\xcf\x8f\x6d\x86\xd6\xaf\x72\xee\xf0\x53\x04\x41\x2f\x3d\xb2\x58\x5a\xa9\xe0\xf3\xa4\xf1\xb6\xd7\x10\xd0\x2a\xb1\x1d\xb1\xfc\x90\xad\x4d\xe2\x5d\x04\x29\x9f\x31\x29\xc2\x12\xe9\xcb\x73\xc0\x04\x79\x53\x45\x5b\xf9\x8e\xc8\xfd\x26\x74\xe4\x7b\x94\x99\x57\xde\xed\xa0\x18\xba\xdc\x9f\x2f\x68\xa1\xb1\x8e\xf5\xc5\x83\xb0\x95\xe0\x8d\xd9\x06\xda\x5f\x22\x0d\xa0\x29\xb9\xc4\x00\xe3\xca\x91\xc7\xcb\xd8\x7f\x34\x30\xc7\x42\x33\x7f\x61\xcf\x54\x74\x5b\x06\x22\xbc\xb9\x07\x62\xc6\xba\xfe\xf8\x7e\x1e\xc8\x88\xc3\x64\xfa\xd6\x46\xc3\x3a\xcc\x22\xaf\x54\x38\xb8\x4c\xd5"}, -{{0x2d,0x5d,0xdf,0xfa,0x2e,0x58,0xc9,0x04,0x51,0xea,0x05,0xde,0x47,0xb8,0xc4,0x92,0x34,0xe2,0x6c,0xed,0x54,0x85,0x4e,0x3a,0xce,0xf1,0x1d,0x8e,0xe6,0x85,0x2d,0xa7,},{0x7b,0xfd,0x1c,0x8a,0x4a,0x0b,0xbb,0x46,0x06,0xd2,0xe5,0xbc,0x09,0x0f,0x56,0xb2,0x0d,0x58,0xf2,0x20,0x4b,0x6a,0xed,0x83,0x1d,0x3d,0xf4,0xd4,0x06,0xb4,0x76,0x05,},{0xce,0xd9,0xd6,0x10,0x10,0x33,0x9c,0x47,0x1d,0xdf,0x9f,0xef,0xca,0xa8,0x2d,0x1e,0xab,0x3a,0x2e,0x0e,0x60,0x27,0x85,0x53,0xb4,0xdd,0x9f,0x39,0x5b,0xe5,0x81,0x49,0xc9,0x15,0x94,0xe5,0x61,0x8b,0x0b,0x10,0xbf,0x3a,0xab,0x94,0xf1,0x59,0xb5,0x30,0xf6,0x44,0x63,0xee,0xd6,0x6f,0xa2,0xac,0xe5,0x4f,0xd9,0x25,0x72,0xa0,0x6a,0x0e,},"\x4f\x1c\x5b\x4e\x6f\xac\x3b\xaa\x3e\x90\x10\xf3\xbf\x29\x3c\x77\x9e\x61\xfd\x7b\xbe\x05\xa5\x86\xf5\xaa\xf0\x80\x26\x37\x16\x27\xa2\x09\xac\xd1\x88\xaf\xb2\xdb\xe0\x31\x15\x47\x94\x05\x59\x71\x16\x40\xf7\x8a\xea\x9a\x62\x81\x89\x62\xf4\x45\xa8\xe7\xed\x6f\xe6\xc5\xf4\x91\x62\xe7\x43\x5d\x1b\x62\x5b\x88\xba\x39\xda\xb0\xad\x56\xfd\x2c\x0a\xd6\x51\x26\x61\x36\x2b\xf7\x8a\xfe\x5a\x14\x16\xb6\x47\xf3\xb8\x8a\x05\x6c\x9e\x72\x89\xc9\xb0\xcc\x3a\xfb\x43\x40\x21\x98\x56\x34\x93\xe7\x37\xb1\xda\x05\x25\x06\xb6\xc9\x30\x6d\x75\xad\x66\x93\xdb\x6d\x15\x71\xf9\x6f\x6f\x52\x99\x0c\x4d\xf1\x96\x65\xa6\xbb\x63\x07\x3f\xdd\x9f\x55\x59\x68\x96\xa2\xe9\xc2\x62\x2f\x2b\x0c\x2c\xc9\x9d\xdd\x1b\x64\x9f\xb0\x31\x80\x58\xd7\x47\x94\xe3\x8e\xc6\x57\xeb\xc8\x2a\xbd\x5b\xed\xf8\xb3\xf4\xbb\xa3\xbb\x6c\x99\x35\xfd\xf6\x82\x65\x02\xb7\x69\x04\x6b\x36\xd9\x6d\xc6\x95\xd7\xc8\x54\x04\x28\x4d\x2a\x2a\xb7\xfc\xf3\xb0\x2f\x68\xa1\x49\x3d\xd3\x83\xca\x63\x39\xfa\xc1\xcd\xe4\x7f\x53\xc5\xe0\x26\xd0\x86\x9f\xaf\xfe\x40\xab\xdb\x98\x19\x52\x30\xf1\x7d\x0c\xfa\xa5\x33\x31\x5a\xfd\xbf\xe7\xd1\xaf\xc3\xa6\x15\xb4\xf7\x50\x90\x23\x3a\x50\x3f\x88\x61\xe3\x23\x74\xe1\xea\x95\x57\x67\x42\x31\xd9\xd7\x37\xd4\x77\xb3\x3f\xf8\x2a\xc0\xb2\xc0\xba\x93\xc1\x1f\xb5\x23\xe6\x13\x61\x8e\xd3\x70\x52\x4a\x60\xf4\xd4\xc8\x36\x94\xc0\x33\x60\x6d\x1d\x06\x9d\x54\x4d\xcc\xd3\x90\x0c\x37\xa3\xb3\x36\x3e\xfb\xcf\x66\x97\xf9\xf7\x62\xb3\x3b\x12\x94\x58\x39\x53\xfc\x53\x77\x3e\xf5\x67\x26\xee\xb4\x70\xeb\xe9\x21\x49\xb7\x36\x48\xa1\x61\x61\xd4\x94\x12\x0a\x31\x8b\xfb\x08\x0c\xc3\x8e\x49\x96\xf4\xb2\x63\xff\xe7\x8c\x78\x77\xfe\x13\xc2\xfc\x55\x21\x9f\x44\x26\x0e\x8f\x25\x3b\xdd\x37\x9d\x87\x0e\x6c\x91\x04\x8b\x1d\x8d\x4e\x88\xb8\x82\x18\xb2\xb0\x49\xfe\xf5\x3b\x2a\xe1\xf8\xc9\x21\xed\x2b\xcb\x43\x46\x69\xe3\x97\x5d\xcc\x3f\xe4\x52\x0c\xa8\x02\x48\x42\xf7\xff\x2b\xa1\xe2\x2c\xfe\xb5\xd4\xc9\xe4\x35\xea\xda\x60\x1f\xf1\x83\xb2\x63\x64\xee\xe1\xfa\xa5\x9d\x19\xe6\xaa\x4f\x09\x75\x23\x84\x96\xa7\x09\xe4\x6b\xf6\x83\x36\xb0\x68\xbd\x80\xb3\x46\xf1\x1f\xaa\x38\x17\xa0\x7d\x1c\xbd\x84\x38\x2b\x21\x02\x98\x6f\x29\x5a\x13\x98\x07\x7b\xa2\x91\xd6\xb5\xf5\xbd\x86\x0e\xc6\x17\x72\x73\x46\x8f\x0e\xe0\xf2\x59\x1b\x57\x5c\x43\x66\xe1\x89\xb2\x24\xe9\xff\xa3\x5b\xc7\x8a\x4a\xa8\xc0\x69\x54\xfe\x33\xd0\x80\xff\xc0\xb2\x3e\x20\x9f\xd0\xe7\x94\x21\xf1\xbd\xe8\x18\xa8\x68\x90\xcf\x17\x22\x36\xdb\x21\x16\x57\xd1\x00\x31\x19\xfe\x91\xd4\xe2\x7c\x52\x4c\xcc\x11\xfa\xde\x0a\x25\xf5\x7a\x7a\x1d\x67\x7e\x1d\xa0\xb9\xc0\x43\xd0\x2f\xca\x38"}, -{{0x4d,0xf5,0xe1,0x1d,0xec,0x80,0xec,0xd8,0x82,0x83,0x75,0x54,0xfa,0x31,0x35,0xb9,0xd5,0x02,0x9d,0xf4,0x20,0x27,0xaa,0x3b,0x3c,0x92,0x92,0x46,0x32,0x9f,0xee,0x96,},{0xef,0xd9,0x28,0x89,0x8f,0xa1,0x44,0xc2,0xd1,0xc8,0x33,0x4f,0xa2,0xe6,0xb5,0xb6,0xa3,0x25,0xa7,0x10,0x2a,0x2c,0x34,0x4a,0x14,0x55,0x41,0xee,0x9a,0x6c,0x04,0x6d,},{0x62,0x54,0x5e,0x6c,0x07,0x80,0x1f,0xde,0x95,0xb4,0x61,0xe2,0xe7,0x53,0xc4,0xb6,0xc8,0x4c,0x25,0x12,0x4e,0xb3,0x30,0xa2,0x72,0x59,0x89,0xd5,0xe3,0x40,0xdc,0xef,0x0c,0x74,0x56,0xd4,0xc7,0xc6,0xa1,0x78,0xa2,0x21,0xb6,0x32,0x83,0x48,0x25,0x3d,0xb7,0x87,0xa9,0xe5,0x51,0x0a,0xb9,0xcc,0x27,0x85,0x15,0xae,0x3e,0x58,0xfb,0x01,},"\xfb\xd6\xf3\x71\xb4\xc8\xb1\x52\xc9\xce\x0c\x63\x96\xa7\x7c\x0f\xe4\x80\xbc\x02\x00\x7f\x33\x6a\xc5\x8f\xd4\xad\xdd\xa9\xd6\x98\x55\xac\x9e\x93\xa4\x5d\x3e\x35\x0f\x41\xff\x50\x2a\xa1\xd8\xfe\x15\x9c\xe8\x9b\x06\x48\x02\xa0\xa1\x89\x0f\x6a\x40\xa7\xef\x57\xc6\xe5\xe5\xed\x04\x02\x80\xdf\x07\xe7\xf4\x8f\xe8\x19\xbe\x63\x17\x67\x10\x75\x7c\xb6\xe4\x40\xb4\xf7\x8b\x57\x59\xdc\xe0\x28\xbf\x58\x5b\x3c\x3f\xec\xa1\xcf\x59\x81\xda\xda\xdf\xd2\x7e\xa1\x24\xaf\x45\xef\x63\x85\x42\xa8\x61\x7f\xf4\x9f\x94\x70\xac\x22\x85\x94\x3c\x7c\x3b\x11\x63\xb9\x03\x95\x5a\xb9\x9b\x6e\xab\x17\xf4\xd4\x9f\xfa\x87\x20\x7a\xbb\xfc\x11\x1c\x4b\x91\xf5\x41\x3d\xfc\x9b\xea\x31\x84\x3d\x11\x5d\xde\xb1\xda\x40\xb4\x5f\x58\xf4\x7c\x41\x7b\x5e\x77\xd5\x81\x89\x34\xe7\x30\xeb\xa9\xc4\x55\x7b\xbf\x48\xcb\x7f\xd4\xe6\x64\x55\x8a\xf4\xfb\x44\xee\x3d\x94\xc1\x6e\x88\x36\x31\xf3\x84\x76\xf4\x83\x7d\xb9\x4d\x54\x12\x2f\xa1\x34\xca\x51\xa5\x25\xaa\xd5\xe2\x4b\x76\x01\x8f\xee\x9a\x2e\x8f\x60\xe2\xbb\x48\xd2\x4a\xb8\xb1\x46\xf8\x4f\xfa\x98\x20\x12\x0e\x7c\x50\xd4\x5c\x0c\xfb\xe3\x5c\x8c\x31\x41\x9b\x07\x8e\x90\x71\x2c\xfe\x93\x4c\x3b\xe3\xa9\x4f\xf2\x15\x88\x73\xae\xfe\x34\xdc\x6e\x36\x90\x2b\x16\x75\xe1\xa4\x7c\xb6\x08\xdf\xe9\x60\xfb\x4d\xa8\xd2\xa8\x49\x0c\xc3\x8e\xba\xdc\x73\xa1\x00\x3c\x49\x41\xfd\xa8\xfa\xe9\x44\xa1\xde\x8e\x3b\x10\xef\x6d\x9e\x67\xce\xec\x74\x59\x77\xd3\x33\xac\x9e\x71\x21\x41\x21\xed\xe8\x89\x22\x95\xe2\x77\x99\xf2\x06\x67\x5a\x9d\x54\xac\x12\x15\x9d\x3a\x1f\x95\x4f\xd0\xee\xff\xbd\x30\xa3\x19\x04\xfb\x2e\xee\x77\xa8\xaa\x9d\xc4\xcc\xbb\xe2\x85\x10\x96\x14\x6a\x4c\xe0\xe8\x1f\xb9\xc6\x24\x98\xdb\xd8\x3b\xf8\x3b\x55\x02\x9a\x5e\x90\x00\x86\xb9\x53\x1c\xe3\x24\x7a\x98\xf8\x65\x4e\xfd\x8f\xe7\xa8\x36\x43\x1f\x75\xda\xf0\x86\x8f\x01\x08\x32\x6e\x23\x02\x6d\x2d\xb4\xa7\x21\x24\xec\x4e\x39\xd4\xbb\xf3\xd8\x46\xc9\xf5\x1c\xa3\xcc\x31\xeb\x1d\x02\xc2\xba\x32\x1e\x46\x19\xf2\xb6\x59\xc0\xbf\x0f\xe5\xc1\x9b\x21\x3f\x3c\x79\x12\x4f\x36\x43\xf7\x4d\xd0\xff\x9c\xe5\xd2\x77\x27\xbe\x6c\x69\x58\x15\x9c\x16\x44\x04\xf4\x33\x01\xfe\x17\x42\xe2\x79\xde\x9e\xfd\x44\x1e\x73\xe4\xea\x7a\x84\x25\x87\xa7\x9d\x11\x5d\x36\xec\xa9\xc0\x3c\x90\xff\x0d\x14\x74\x74\x10\x9f\xc2\x0a\x91\xd7\xb3\xcc\x22\xeb\xcb\xb8\xc7\xf7\x1b\xd6\x1e\x8c\xae\x47\xc5\x05\x0c\xec\x1d\x48\x49\xa1\xd4\xa8\xe7\xa6\xf8\x45\x54\x84\x37\x70\x6c\x25\x33\x1c\x9e\x57\xc2\xcc\x6d\xa1\x17\xf2\xe5\xa0\xf4\xb3\x68\xc4\xcb\x20\x62\x65\xc4\x17\x8e\x06\x55\xff\x67\x5f\xfc\x1d\x4c\x58\xec\xeb\x9e\xdb\x4d\xa3\xad\x2c\x5f\x62\xcd\x13\xab\x48"}, -{{0x85,0xd3,0x23,0x30,0xe2,0xe0,0x73,0xa4,0x60,0x30,0xca,0x0e,0xe2,0xdf,0x2f,0x8e,0xb8,0x74,0xa9,0xfd,0xdf,0x56,0x24,0xc8,0x03,0x17,0x75,0x11,0x1f,0x11,0xee,0xa2,},{0x6e,0xa7,0xde,0x2e,0xd5,0xea,0x5c,0xdf,0x50,0xbf,0xff,0xee,0x77,0xf7,0xbd,0x2f,0xcc,0x21,0xd4,0x86,0x66,0xbb,0x1f,0x48,0x90,0xc7,0x6a,0x69,0xcc,0x7b,0xa4,0xe8,},{0x41,0x43,0x63,0xfe,0xad,0x6e,0x59,0xa3,0x43,0x8c,0xe5,0xa3,0xa2,0x77,0xd6,0x2b,0xdd,0x00,0xfa,0x2e,0xfa,0xc6,0x46,0x3d,0xd1,0x3f,0xcd,0xde,0xd9,0x3a,0x7f,0x10,0x8a,0xe1,0xf5,0x28,0xff,0xc8,0xff,0x4e,0xca,0x33,0x1d,0xab,0x91,0xae,0x5b,0x14,0x16,0xe2,0xdd,0xb7,0x3b,0x6d,0xaf,0x85,0x3b,0x03,0xc8,0x1e,0x99,0x36,0x56,0x0a,},"\xae\x61\x07\xf3\x8f\xf9\x4e\xd0\x32\x79\x03\xcb\xaf\x6c\x3e\x3a\x34\x98\xc4\x7a\xbb\x29\x89\xa8\xb3\x7b\x3a\x19\xdf\x88\xc6\xde\x79\x0a\xcc\xb4\xb7\x25\x81\x77\xb9\x15\x1d\x1f\xe0\x40\x63\x57\x7d\x3c\x3a\xcd\xb4\xc9\x29\x96\x8a\xfd\xad\x6f\x25\x2a\x67\xed\x4c\xa8\x9d\x06\x0f\x1a\x46\x53\x98\x3f\x7a\xb5\x8d\xdb\x93\xe2\x87\x8f\xba\xb0\x63\x7d\xbb\xeb\x95\xd2\x5c\x59\x86\x83\x9d\xe2\x74\x8d\x9f\x34\x02\x7a\xee\xbf\x1d\x9e\xb9\x36\xcb\x67\x70\xe0\x8d\x45\xb8\x09\x5b\xac\x9c\xbb\x71\xdb\x14\xe8\xa3\x42\x22\xb1\xf2\x23\x7b\x9f\x0b\xc9\x76\x6a\x23\x1a\x6d\x10\x27\x99\xf7\xc0\x81\xd5\x00\xfb\xea\xde\x60\x3c\xdc\xdd\x7d\x5b\x96\x5f\xba\xce\x4b\xe5\xc2\xcd\x93\x2d\xcf\x5f\x6e\xd3\x17\x22\xf4\x1d\x5a\x36\x3b\x34\xba\xbf\x3f\x63\x6f\xb3\x03\x82\x4a\xa7\x01\xdf\xe1\xd3\xe4\x12\x63\x07\x8c\x1e\xbb\xdc\xb1\xf7\x3f\x12\x45\xb8\x3e\x3f\xa7\x0a\xb8\xe3\xf1\x41\x3e\x6b\x06\xbd\xae\x02\x2b\x71\x4d\x60\xa4\x01\xd5\x74\x80\xdc\x64\xe7\xaa\xc6\xd3\xde\x85\xfc\x94\xd8\x53\xca\x13\xb7\xe6\x74\x15\x57\x9d\x5c\x67\x21\x23\xa5\xaf\x19\x4b\xee\x14\xae\x35\xdc\x27\x24\xff\x20\x9f\x11\x66\x63\x86\x61\xf8\x81\xb1\x19\x4a\xa4\xe3\x1b\x42\xa5\x27\x96\x47\x81\x59\x15\x04\xba\x76\x10\x3f\x97\xb7\xf5\x52\x03\x15\x47\x3e\xc9\x4b\xb0\x17\xa1\x66\x67\xb2\x2a\x85\x76\xa7\xcc\x2a\xc0\xb7\x75\x63\x03\xc7\x56\xf0\xdd\xaa\xe9\xd0\x18\x9e\x6c\x8d\xe3\x49\xf9\x19\x57\xc7\x2a\x52\x9e\x9f\x7e\x9b\x94\x56\x52\x48\x40\xba\x02\x34\x4f\x55\xad\x3c\x11\xa0\xb2\x59\x90\x14\x39\xf2\x65\x5a\xb9\xf8\xc6\xc8\xe8\xe9\x60\xc0\x57\xd9\xc7\xda\xfe\x42\x5c\x75\xd4\xa3\x3b\x80\x1d\x45\x47\xcd\x05\x51\xa6\x80\x2a\x80\x05\xdd\x72\x42\x47\x64\xdc\xf5\x7e\x4a\xa2\x22\x90\xea\x4f\x5b\xaa\xc5\x1d\x79\x39\xc0\x53\x42\x88\x2e\xe1\x43\x80\xef\x2d\x47\x04\xb4\x19\x49\xb2\x28\x2a\x1e\x1a\x3f\xa7\xdd\xea\x9f\xe8\x3b\x9f\xc5\x1d\x4e\xef\xa2\xeb\xac\x72\x2e\x4c\x0a\x7c\x59\x9b\x69\x25\xf0\x1b\x8a\x20\x66\xdc\x0c\x26\xf9\x21\x96\xf4\xf5\x03\xe8\x87\xc1\xe6\xef\xb0\x93\xf1\x53\x13\x87\xbd\x88\xc6\x91\x99\x7b\x9b\x89\xe3\xcd\xf7\xda\x12\xd3\x73\x41\x83\xa4\xb6\x12\x6b\xe9\xe0\x77\x47\x04\xb5\x29\x65\x9b\x55\x48\xf1\xb8\x75\x12\xcc\x18\x78\xca\x4e\xf5\x59\x90\xb4\x83\xc9\xaf\x6a\xa9\x76\x35\xf4\xf0\x79\x49\x72\x70\x65\xab\xf2\x1e\x21\xe3\x29\x90\xb1\xa7\xd0\x7d\x74\xe0\x2d\x9b\x07\xec\x63\x99\x31\xbf\x9e\x2c\xa3\x94\x1f\x2b\xa6\xb5\xef\x14\xdc\xc2\xa2\x47\xd2\x11\x7e\x9c\xb4\x1e\xfa\x3f\xcc\xa2\x47\x16\x64\x14\x52\xbe\xed\x2f\x92\x65\x7c\x2f\xb7\x31\xf0\xb9\x4e\x8c\x89\x2a\x81\xbb\xa9\x1f\x63\x9d\xf4\x37\x96\xac\xd3\x01\x3a\xc0\x44\xf6\x08"}, -{{0x66,0x59,0x0d,0x36,0x99,0x84,0xc6,0xf5,0xad,0x3a,0x89,0xc7,0x8d,0xdf,0xca,0x10,0xa0,0xa7,0x65,0x79,0x95,0xdc,0x01,0x88,0xb6,0xb5,0x7a,0xc3,0x16,0x47,0x31,0xa4,},{0x98,0x87,0x3a,0xb1,0x33,0x46,0xee,0x48,0x67,0x7c,0x4f,0x86,0x12,0xdb,0x31,0xeb,0xd1,0x3d,0xb5,0x8b,0x2b,0x03,0x4f,0xd1,0x55,0xaf,0xa8,0x72,0x0f,0x4e,0x93,0xe8,},{0xf0,0xdb,0x63,0xa1,0xbc,0x76,0x24,0x16,0x1c,0xa0,0x06,0x38,0x53,0xb2,0xde,0xe4,0x5f,0xcc,0xd2,0x24,0x71,0xe0,0x12,0x36,0x6f,0x86,0x8a,0x4a,0x9c,0x74,0x65,0x4e,0x13,0xf1,0xa3,0x15,0xad,0x83,0x91,0x6e,0xbf,0xb8,0xdc,0x31,0xa4,0x20,0xf8,0x3c,0xf6,0x45,0xc4,0xc9,0xd1,0x6b,0xb4,0xd5,0xd9,0x9d,0x23,0xc7,0xb4,0x3e,0x23,0x00,},"\x2e\xc1\xc6\xb0\x82\x97\x37\x83\x2c\x9c\x79\x8a\x92\xeb\x49\x0b\x23\xd3\x34\xc3\xbb\xe6\x27\xcb\x58\x2d\x17\xa9\xe4\x29\x60\xef\xcd\xc7\xd3\x47\x50\xe0\xb4\xaa\x86\x4c\x20\x4f\xb8\xd6\x2b\x47\x99\x2e\x91\xdb\xfc\xfd\x69\xf5\x1d\x93\x7d\xc0\x6c\x48\xc0\xad\x43\xe8\x59\x83\x71\xcd\x0e\x3b\xbc\xe4\x16\xbf\xd4\x4b\x09\x44\xb9\x93\xaa\x29\x93\xfd\xea\x48\x71\x34\xcd\xe4\x22\x77\x72\x3e\x06\x83\xec\x98\xe6\x95\x95\xe9\xb7\xb1\x4c\x8c\xf9\x61\x7a\x1e\x30\xdd\xb8\x06\x0e\xac\xba\x48\xd8\x82\x53\xb1\x65\x33\x61\x08\xde\x0c\xb0\x2f\xf2\x0f\x54\x24\xb5\x67\x83\x08\x69\xc9\xb4\x32\x9c\x99\x45\xf0\xbf\x2f\x3c\x7a\xcd\x1e\x77\x43\x58\x93\x0c\xd8\x90\xfd\x9c\xb8\x64\xd9\x50\x93\x5a\xd8\xa4\xa3\xbe\xcc\xae\x8f\x83\x3f\x63\x56\x19\x13\x71\xc3\x26\x33\xdc\xf8\x82\x70\x9b\x0d\x98\xbd\x80\x7b\x38\x3a\xed\x8d\x7b\xb0\x97\xb6\xe2\x62\xef\x70\x0c\x9d\x76\x8f\x4b\x56\x90\xe3\xa1\xa8\xf2\x17\x55\xd6\x58\xdb\x2d\x1b\xfd\x2f\x70\x71\xe0\xca\xec\x7c\x2c\x53\x81\xc5\xef\x5c\x2c\x22\x81\xc6\xbc\xed\xc8\x67\x39\x0b\x90\xf3\xb2\x7b\x0f\x0f\x64\xa3\x36\x58\x57\x8a\x5c\x0d\x66\xe2\x11\xe6\xff\xf6\xe8\x64\x88\xac\xf8\x2b\xc0\xf5\xe2\x66\x4b\x83\x69\x90\x46\x03\x7c\x0d\x33\xd3\x40\xff\x98\xed\x62\x63\x35\x4c\x24\x27\x31\x36\xff\x0e\x4f\x0f\x23\x3a\x6c\x82\x54\xfc\x0c\x90\x76\x43\x30\xe3\xb1\x05\x7b\x1e\x66\x6d\x5e\xcd\x5a\x2e\xfe\xaa\x6a\x10\x5b\xfc\x85\x84\x31\xb8\x8e\xd7\xfe\x55\x1e\xb3\x2a\xc0\xaf\x27\xc6\x6a\x98\x03\xa3\xbc\xf8\x76\x34\xc6\x6c\x70\x66\xdd\x01\x97\xa3\xcb\xd2\xd6\xf4\xe6\x5c\xfd\xb8\xf3\xda\xf9\xf3\xca\x5c\x4f\x4e\x0a\xdd\x45\xf5\x54\x1a\xa1\x8d\x04\x1f\x70\x6e\x4f\xa8\x7c\x34\xe9\xa2\x23\xd8\x85\x72\xeb\x50\x08\x3e\xe8\xc7\xc4\x75\xdf\x56\x8b\xc7\x3b\xd0\x8c\x0f\x0d\xea\xa3\x74\xaf\xb1\xc1\x78\xd0\xdd\xdb\x23\x6e\x15\xa8\xbc\x23\x85\xed\x3f\x52\xb8\x76\x1e\x63\x78\x87\x40\x7a\x20\xae\xc3\xe9\x9e\xc8\x30\xda\xe3\x16\x7e\xf0\xcd\xb3\xf3\xff\xd2\x00\xd8\x3b\x75\xb7\x49\x69\x0b\x9e\x25\xe2\x17\x1d\x07\x2c\xa5\x6f\x71\xba\xec\xd2\x1f\x7d\x45\xa1\x2c\x91\xb2\xc0\xfb\x3f\xea\x3b\x15\x8e\x54\x64\x82\x84\xbb\x00\x95\xb3\x62\x44\xb0\xb1\x21\xf9\xf1\x38\x4c\xe9\x00\x43\x65\xe7\x77\x2f\xa3\x08\x28\x25\x0f\x51\x98\x5f\x1b\x17\xb2\xd2\xf8\x0a\x33\xe8\xfc\x6d\x85\x65\xea\x15\xcd\xaa\xcd\x42\xa8\x7b\xd7\xc9\x40\x8b\x1f\xe1\xc7\x70\x66\x5b\xdd\xed\x75\x4b\xc2\xff\x2e\xf9\x1b\x97\x3a\x86\xb9\x9f\x10\x59\xc6\xf2\x27\x24\x6a\x69\x8b\x38\x54\x15\x09\xdd\x54\x49\xfc\xe6\x0d\x38\x62\x24\x18\x3b\x7d\xce\x1b\x38\x84\xf7\xba\xe1\xc2\xe4\xeb\x59\x45\x10\xb5\xca\x58\x52\x79\xd9\x04\x1d\xf8\x81\x7b\x06\x19"}, -{{0x41,0xcf,0x07,0x1f,0x48,0x42,0xec,0xd4,0x94,0x19,0x1b,0x8c,0xf2,0x8c,0xc0,0x92,0x31,0x85,0xef,0x1b,0x07,0x45,0x8a,0x79,0xa5,0x9a,0x29,0x6d,0x35,0x49,0x82,0x2e,},{0x6d,0xc8,0xe4,0x46,0xdb,0x1d,0xa3,0x53,0xb5,0x8d,0x0c,0x45,0xd8,0xb4,0xd8,0x16,0xba,0x59,0xe2,0x5b,0xb6,0x80,0x71,0x2d,0x62,0xd6,0xd3,0xdb,0xf7,0x8d,0x06,0x98,},{0x41,0x05,0x2b,0xc4,0x17,0xb2,0x4d,0xc4,0x83,0x83,0x96,0x6a,0xf0,0x14,0x3f,0x9c,0x0b,0xa8,0x5b,0xbe,0xfb,0xda,0xf7,0x91,0xb1,0x6a,0x4d,0xad,0x1f,0x57,0x0e,0xb8,0x07,0x03,0xc0,0xa2,0xcd,0xeb,0x2f,0x7a,0xd6,0xdc,0xd3,0xfa,0x7b,0xdb,0x5c,0x22,0x5e,0x86,0x9c,0xd8,0xfb,0x27,0x8d,0xff,0x06,0x67,0xd3,0x8a,0xcc,0xf3,0xdb,0x08,},"\xda\xeb\x5f\x0e\x84\xf1\x59\x0b\xca\x2b\x9d\x97\x19\xef\x5d\x1c\xfa\x79\xe0\x58\x34\x46\x33\x2f\x18\xe9\xe4\xfe\xb0\xb1\xf1\x53\x40\x29\x7a\xc9\xad\x67\x24\xc8\x5b\xb1\x65\x58\xea\x54\xeb\x5d\x70\x2a\x47\x24\x8b\xad\xc6\x25\x2a\x80\x43\x71\xb7\x4c\xfe\x10\x62\xd1\xdb\xa1\xec\x68\xfd\x1d\x4d\xd0\x29\xcb\x55\x03\x4b\xbf\x61\x06\x82\x51\xef\xf3\x98\x36\x36\xf6\xde\xbd\x57\x27\xbe\x91\x99\x3b\x3e\x4d\x0a\xbc\x96\xec\x19\x64\x21\xa4\x7b\x78\x93\xf8\x39\x86\xd6\xc0\x32\x3f\x0d\x19\xaa\xf2\xcd\xe9\xd3\x56\x5c\x10\x4c\x9d\x31\x76\xec\xb5\xed\x5e\x17\x3f\xee\x52\xb5\xa0\xc4\x2b\x6a\xb2\xfc\xb1\xcc\xba\x96\x49\xc2\xc6\x7c\x52\x0e\x9b\x96\xce\xa6\x93\xdf\x3e\x58\x60\x9a\xd6\xa0\xbd\x52\x2e\xfa\xaf\x03\x85\x8d\x24\x5d\xd0\xa3\x8f\x84\xa2\xfb\x10\x20\xf4\xdd\x97\xc3\xae\xef\x0e\x24\x47\x7d\x30\xd2\x56\x70\x1e\x90\x0b\xef\x26\xa8\xa6\x26\x9a\xb6\x60\xd7\x42\x93\xa2\xbf\x1d\x20\xc2\xcf\xae\xbb\x7c\x28\x20\xf5\xf5\xb0\x74\x53\xbb\x69\xee\x76\x9b\x52\x39\x15\x39\xf0\xc6\x06\xd2\x2e\xb3\x92\x3e\xe6\xf5\xa1\xd4\x60\x50\xaf\x90\xf0\x11\xf8\x51\xac\xe7\x63\x27\xd3\xd1\x8c\x48\x17\x0a\x9a\x25\xb0\x4b\x77\x0f\xd9\x38\xef\x8a\x30\xb7\xbd\x03\x39\x1d\xd3\x6c\x51\x6b\x62\xf0\xcb\x78\x67\x07\x40\xe0\x0e\x69\x59\x5c\x41\x8d\x96\x72\x53\x82\x0b\x75\x4c\x4f\xd6\x66\xe3\xcc\xe1\x6e\xe0\xc9\x41\x83\xbb\xea\x70\x6f\xe2\x98\xe1\xc9\x9d\xdb\x82\x12\x17\xed\x90\x08\xcc\x8e\x8b\x83\xbc\x8b\x81\x99\x15\xb0\x7b\x14\x6f\xe7\x45\x02\x4a\xc3\xc4\x61\x16\xcb\x4c\xce\x5e\x32\xec\x5d\x75\x24\xa2\x38\x8d\x9f\xe2\x97\xeb\x02\x81\x1a\xf4\x54\x6f\xcd\x58\x60\xe1\x4c\x0d\x13\xf0\x3d\xd7\x5a\x42\x49\x61\x59\x00\x07\x8a\x3c\x35\x8c\x53\x42\x96\x2b\xc1\xbe\xac\xf6\x8c\x24\x68\x21\xa4\x59\xab\x53\x21\xec\x9f\x57\x4f\x49\xd1\x03\x89\xf4\x0f\x14\xdd\xfc\x85\x13\xff\xe3\xde\xaa\x73\x36\x03\x5a\x67\x5f\xa5\x85\x8b\x49\x0c\x5d\x24\x77\x80\x06\x4a\xdb\xaf\x75\xa7\x63\x35\xee\xc9\xab\x91\x87\x71\xb0\xb1\xdf\x51\x47\x64\x2a\xef\x4a\x16\x6a\xb1\x72\xed\x60\x1f\xed\x21\x0f\x6c\x0c\xff\xd9\x18\x69\xf7\x49\x0b\x57\xe7\xc6\x52\x41\x86\x3e\x7e\x8c\x0a\x26\xeb\xa6\x3b\x53\x42\xd0\xfd\x82\x14\xac\x73\x1e\x1c\x43\x8d\x01\x77\x11\x5f\x6a\x19\xe0\x93\x5c\x7a\xf6\xbc\x7d\xbe\xb7\x55\x11\xd9\xbd\x8e\x63\xe3\xe2\xf4\x7a\xb0\xdd\x1c\xed\xd7\xb1\x80\xd7\x4a\x4b\x44\xd4\x61\x19\x7a\xef\xdd\x36\x20\x46\x51\x66\xa3\x9b\x45\x39\x50\x43\xce\x88\x74\xcd\xd7\x2c\x60\x2b\xd3\xd2\xee\xcb\xad\x34\x66\xb5\xcb\x1a\xa4\x1a\xe9\x2a\x8a\xfe\xf2\xd7\x64\xce\xc0\xc4\x49\xd2\x7e\xfa\xc4\x37\x93\x8f\x28\x0b\xea\x9c\x50\xa5\x82\xe5\x7c\x27\xf9\xb3\xde\x87\x2f\x0c"}, -{{0xa2,0xc8,0xe1,0x61,0xa8,0xd9,0xd6,0xe8,0x88,0xc3,0xd0,0x9b,0x0b,0x97,0x27,0x37,0x30,0x7a,0x2c,0xbd,0x2a,0xcd,0x7c,0xcd,0x80,0x4d,0x24,0x31,0xac,0x6c,0x58,0xd2,},{0x3a,0x32,0x57,0x75,0x88,0x67,0x32,0xde,0xca,0x40,0x68,0x57,0xa8,0x05,0x60,0x10,0xaa,0xea,0x28,0x75,0x54,0x5b,0xa6,0xf3,0xdf,0x30,0x75,0x45,0x71,0x38,0x69,0x92,},{0x56,0x0d,0x01,0xb9,0x4d,0xf1,0x1d,0x83,0x34,0x77,0x52,0xff,0x51,0xb3,0x54,0x5e,0xf5,0x5c,0x56,0x32,0xae,0x7c,0x8e,0xfb,0x11,0xaa,0xdd,0x83,0x12,0xde,0xf7,0x25,0x62,0xe8,0xf5,0xd7,0x5e,0xce,0x10,0xad,0x46,0xbc,0x96,0xc8,0x60,0xde,0xec,0xe3,0x9e,0x63,0x4a,0x5f,0x50,0x65,0x4d,0x4c,0xdb,0xa8,0x4a,0x8e,0x6f,0x70,0x24,0x0a,},"\x83\xa3\xbe\xbc\xac\x5f\x28\xc5\x43\x3e\x3c\x4f\x1e\x7b\xf5\xd2\xe4\xdc\xd2\xf5\xe5\x9d\xbe\xe0\xa8\x3b\x07\x02\x57\x15\x35\x07\x46\xf8\x56\x75\xf1\xdf\xea\x37\x4a\xa7\xd7\x94\x28\x7b\x89\x2e\xf9\x09\x7f\xf6\xd2\xe1\x22\xf0\xa6\x56\xfb\xa0\x79\x8c\xdc\xfc\xb3\x64\x5d\xfc\xfd\x78\x8c\x74\x0c\x0f\xd0\x45\x20\xe7\xa0\x6a\x02\xa0\x58\x29\x63\x0a\x2b\xf0\xcd\xfe\x2e\xcc\xa0\x09\xec\x44\x04\x99\x46\xbb\x1d\x23\x26\xdd\xd6\x1d\x7e\xc6\x40\xbf\x69\xeb\x44\xfb\x23\xcc\x1f\xf4\x78\xc5\x70\xc7\x5d\xb7\xe7\x66\xe3\x5b\x7c\x43\xdb\x73\x68\x0d\x14\x07\xa9\x43\x99\xfb\x62\x1b\xaf\x38\x45\x74\x5c\x1c\x4e\xd0\xb9\xf0\xb4\x85\xbe\x2d\x53\xc5\x68\x54\x5d\xdf\x18\x77\x5a\x83\x7a\x05\xd9\xc9\x15\x7b\x08\x4e\x8c\xd0\x1f\xc3\x24\xf0\x7f\x11\x68\x77\xe4\x07\x5d\xba\x24\x32\xc8\xa7\x75\x2e\x9e\x93\x95\x86\xad\x93\xf0\xc0\xaa\x5e\xda\xc9\x4b\x8d\x82\xe5\x44\x99\x97\xb1\x5b\x8c\x89\x61\x58\x9c\x44\x28\x21\xaa\x83\xb6\x02\x39\xec\x5f\x15\x8c\x3f\x5e\x9e\xc5\xbe\xa5\x11\x5d\x5f\xed\x61\x91\x8e\x8f\xcd\x5b\xce\x61\xc7\x77\xf2\x0b\x6b\xfe\x80\x3a\x69\xc6\xfc\x79\x4a\xb8\xc5\x7d\xf2\x71\xda\x86\x38\x72\xa6\x13\x35\xb1\xfa\x29\xf4\x60\x8f\xf0\x37\xf7\x12\x06\x98\x09\xca\x64\x2a\x03\x07\xc7\x9a\xa9\x2e\x10\xcb\x89\x3a\x29\xd1\x72\x01\xa0\xb6\xd1\xb4\x6a\x72\x12\xb3\xba\xec\x97\x03\xc0\xb0\x39\x2b\xa6\xb7\x6e\x5c\x9c\x10\xf8\x35\x99\xb8\x1e\xa2\x22\x83\xf9\x54\x7a\xac\xda\xa7\xf3\x08\x96\xd1\xff\x73\x1e\x11\xfb\x9e\x56\xad\x06\x03\x04\x17\x11\x98\x05\xba\xb6\x35\x21\x49\x6c\x3b\xb9\x2a\x12\xf5\xe5\x5a\xfc\xf6\x0e\xd4\x21\x77\x37\xf3\x04\x6b\x16\xca\x50\x66\x57\xa6\xd6\x96\xd7\x5a\x6d\x8e\x18\xe9\xef\xe2\xb0\x8c\x8b\x1f\xa0\x72\x82\x38\xe2\x7c\xfb\x32\x21\x66\xee\xe4\xee\x76\x96\x8b\x77\x7b\x50\xee\x6a\x2b\x80\x4e\x1e\x9b\x46\x01\x66\x20\x13\x2b\x65\x88\x71\x8d\x97\x8c\xa2\xc0\x02\x69\x79\xc4\x00\xd3\xc5\x33\x67\x51\x21\x0f\x0b\x00\xd2\x69\xec\x8f\x4e\x2f\x95\x59\xe1\x80\x33\x2d\xd2\x70\xe5\x0c\xc9\x46\x5c\x55\x58\x93\x63\x55\x52\x1b\xc3\xc9\x56\x0f\xc1\x9e\xc1\x42\x42\x12\x1e\x6b\xb2\xff\xf8\xf5\x03\x37\xfc\x26\x4a\xcf\x1a\xc1\x70\x43\x28\x33\x4b\x3b\x52\xcb\xa9\x6d\x93\x03\xb1\xb5\xdb\x85\x9d\xae\x31\xd8\x0f\x17\x11\xfb\xa2\x51\xe1\x0b\x4d\x12\x21\x28\xf9\xfa\xff\x68\x72\xd0\xc0\xb8\x1e\xef\x59\x54\x1f\x83\x2b\x0a\x9d\xf3\xa4\xcd\xd5\x91\xc8\x77\x36\xb1\xae\xcf\x24\x2c\x27\x5a\x10\xc3\xfd\x67\x83\x9d\xad\x4e\xf3\x99\xb9\x49\x4e\xcd\x77\xf7\xba\x5b\x5d\x4f\x2c\xa3\x04\xe5\xb2\x29\x21\x30\x7c\xb1\x8f\xa6\x4a\xa3\xd0\x1c\x44\x11\xc8\x36\x9c\xce\xde\x46\x5e\xe3\x69\xee\x63\x7d\x43\xd2\x88\x26\xbf\x60\xdd\xde"}, -{{0xd3,0xd1,0x88,0xb3,0x90,0xba,0xcc,0xd9,0x50,0x24,0x52,0x61,0x46,0xb8,0x2b,0x91,0x84,0xe1,0x97,0xe4,0x6a,0x93,0x40,0xa0,0xe6,0xec,0x18,0xbf,0x75,0xbe,0x7f,0xc5,},{0xd8,0xf7,0x94,0x94,0x8a,0xa6,0x98,0x61,0x00,0x21,0x4e,0x9b,0x7b,0x90,0x24,0x42,0x08,0x06,0xb4,0xc6,0x78,0x46,0xd5,0xbd,0x50,0x61,0x13,0xb3,0x53,0xa2,0xea,0x3d,},{0x16,0x97,0x6b,0x26,0x7d,0xe9,0x6e,0x38,0xdd,0xdc,0x84,0x78,0x07,0x5f,0x6b,0xdd,0x71,0x59,0xe5,0x63,0x34,0xb2,0xd2,0xd1,0x92,0x09,0x46,0x29,0x4f,0x33,0xcd,0x6b,0x7f,0x9c,0x50,0xf8,0x05,0x7f,0x49,0x6c,0xab,0x5d,0x94,0xbb,0x4d,0xca,0x26,0x2f,0x9f,0x0f,0xdf,0x9b,0x1b,0x64,0x74,0x1f,0x4b,0x72,0x2d,0x32,0xef,0xa8,0x22,0x03,},"\x5e\x65\x65\x8e\x42\x03\x75\x43\x3f\xd7\xc1\xf6\xbe\x67\x88\x41\xe5\x81\x04\xf1\x0b\x4c\x67\x63\x59\xd8\x4f\xce\x79\x92\xf5\xc5\x75\x57\xd7\x38\xf8\x30\xb5\x05\xfa\x0c\x2b\x9e\xab\xf8\xd1\xa9\xf8\x1f\xe8\xf3\x15\xd6\x62\xe2\xb8\x4c\xe9\x52\x99\xeb\xf4\xe5\x03\xb5\xe1\xf7\xf8\xcd\xb6\x68\xae\x73\x3f\x3d\x0c\xdd\x4c\x74\x2a\xb5\xf2\x72\xbe\xa4\xf1\x8d\x18\x3e\x89\x23\x84\x76\x62\xf9\xa3\x9c\xd4\xb1\x4e\xc7\x6d\x11\x03\x2f\xe5\x73\xc2\x62\x01\xae\xf6\x66\x01\xce\xc6\x83\xe3\x4b\x89\xaf\xd9\x64\xe9\x87\x80\x1c\x70\x6a\x85\xe2\x7b\xab\x33\x70\x1c\xd1\x09\xbc\xf0\x7b\x27\xca\x67\xf0\x22\xc4\x94\xa0\x4c\xbe\x5a\x9c\x6d\x63\xaa\xd9\x36\xcd\xf1\xa1\x80\xfd\x05\x86\x51\x98\xb9\x6f\x06\xa7\x8d\xa9\x57\x99\xd3\xaa\x4d\xf3\xb1\x70\x03\x3c\x69\xe8\xfb\x04\x28\x8c\x35\x46\x55\x3b\x57\x9c\x0a\xe3\x93\x80\x62\xd3\xd8\x42\x1c\xfa\x66\x26\x85\x29\xbe\xc0\x27\x1e\x53\xb4\xee\x7d\x09\x9e\x71\x48\xa8\x02\xdf\x80\xfe\x5e\xed\xee\x1c\x90\x3a\xe8\xed\x4d\x64\x0e\xad\x76\x12\x62\xdd\x40\x14\xf2\x5f\x93\x97\xba\x3f\x1c\x08\xd8\x3a\x3c\x48\x5c\xfb\x55\xf8\x99\x19\xaa\x97\x2d\x6b\x7e\x77\x11\xbe\x9e\x30\xc1\xeb\x96\xa0\xc3\x84\x53\x09\xfb\x23\xdb\xc7\x5b\x69\x91\xdd\x6e\x48\xcd\xde\x90\xe0\x4f\x22\x8e\x8c\xcf\x3b\xa2\x3f\x27\x47\xcf\xb9\xd3\x38\x1a\x93\x05\xf8\x16\xf2\x6c\xdd\xe4\x1c\x02\x20\xfa\xd2\x28\xff\x6a\x8b\x09\x5c\x77\xb6\xba\xe8\xfa\x33\x68\x14\x27\x24\xbf\x1f\x5e\x0f\x6f\xbc\xa5\x32\x0c\x21\x5b\x6b\xa8\x6b\x91\xe3\xa8\xac\xf7\x50\xe9\x3f\xa7\xea\xa6\x5c\x4f\x78\x5e\xf8\x42\x1a\x19\xc1\xe2\x7b\xc2\x4b\x42\x8e\x08\xa9\x02\x42\xab\xac\x9b\xd4\xaa\x03\xc6\x56\xf8\xf4\x6d\xc4\x0b\x36\x15\x2c\x1b\xd0\xde\xf1\xac\xfc\x0d\xa1\x0a\x2f\xa1\xdc\x3d\xa7\xac\xe5\xa8\xfd\x76\x22\x7b\xb1\xa6\x02\x39\x0f\xe5\x7a\xfd\x32\xef\xe2\x81\xf2\xea\x6b\x2e\x4d\x25\x45\xcb\x88\xd2\x30\x8d\x72\x69\x1c\x9a\x52\xb4\xca\x25\x23\x1a\x01\x07\xf2\x5d\x11\x7c\xc9\x35\x39\x76\x21\xc6\x83\xbd\xc8\xf2\x2e\x81\x03\x40\xf2\xcb\xac\x4c\xea\xa3\x46\x86\x65\x26\x18\x79\xf0\x07\x42\x00\x74\x3e\x0d\xe5\xf3\xe5\x83\x08\xb9\x8b\x04\xb8\xc7\x14\x8a\x4e\x00\x4e\x66\x7e\x83\x2b\x00\x84\xb5\xf2\xbd\xc6\xfd\xc9\x59\xf2\xfc\x28\xa8\xd3\x1d\x9a\x9e\x78\xe5\xd5\xf9\xc0\xb1\x19\xe5\xff\x1f\x68\xf7\xc0\xda\xf0\xc0\xf1\x69\x47\xcc\xa5\xb7\xce\xd0\x96\x01\xe2\xeb\xed\x28\x2e\xf2\xbf\x8f\xe9\xa2\x7e\xd2\x7f\xc5\xbc\xda\x8a\xed\x6c\x71\xbe\xe3\xe7\x75\x10\x04\x47\x26\x89\xbb\xf6\xd9\xd0\x79\x52\xa2\x42\xff\x87\x0d\x7c\x3f\x5e\x1f\xfc\x2c\x1f\x40\xfc\x9a\xb7\x57\x9b\x39\x2b\x55\x4f\x3d\xc5\x88\xc0\x3a\xb9\x57\x43\x1f\xe5\xd0\x2c\xbc\x71\x1a\xd4\x89\xfe"}, -{{0x61,0x91,0x7a,0x97,0x5c,0xb7,0xec,0x56,0x4c,0x70,0x8a,0x56,0x53,0x88,0xc5,0x72,0x36,0xa6,0x6b,0x69,0x7d,0xcd,0x5a,0x7f,0x10,0xba,0xe6,0x71,0x57,0x2a,0xc7,0xf0,},{0xec,0xc0,0xf0,0xb9,0x92,0x76,0xe5,0x28,0xf8,0x2b,0x42,0xf2,0xef,0xce,0x85,0x79,0xf8,0x3e,0x63,0x8c,0x6a,0xce,0xfd,0x07,0x28,0x28,0xc0,0x4e,0x43,0x4f,0x55,0xaf,},{0x6a,0xbb,0x3e,0x37,0x7b,0x5c,0x80,0xb7,0x4f,0x77,0x21,0x9c,0x1a,0x9e,0x09,0x6f,0xba,0x0e,0xb6,0x89,0x90,0x81,0x7a,0xcf,0xf1,0x2d,0xba,0x7f,0x61,0xc7,0x7c,0xcf,0x59,0x5f,0xb6,0x60,0x85,0x52,0x00,0x3c,0xea,0xd0,0x6c,0xa1,0x31,0x7c,0x9c,0xd5,0x1a,0xc4,0x72,0x4b,0x29,0xf4,0x09,0x21,0xfb,0x92,0x84,0x33,0x76,0x87,0x64,0x01,},"\x6e\x97\x0e\x0b\x1c\x92\xa7\xf4\x96\xa8\x2d\x8a\xe8\x0c\xfd\x0c\xce\xf1\xd2\xc7\x99\xd4\x17\x28\xf3\x5d\xdc\xd6\x03\xb4\x21\xc2\xa5\xab\x3b\x48\x9e\x78\xf4\xb6\x22\x97\xde\x43\x7c\x5a\xd1\xa9\x68\x3f\xf8\x7f\xa2\x8e\xb3\xcc\x38\xce\x24\x2a\xf5\x94\x19\xf9\xfd\x43\xfc\xaa\x54\xfc\x39\x89\x92\xf8\xc8\xe3\x1f\x2b\x33\xdc\xcc\xd0\xee\x11\xba\x7b\x38\x8e\x8d\x2a\x36\xea\xd0\x67\xc6\xbe\xce\xd5\x89\x0a\xb7\xd4\xa9\x4f\x55\xda\xb9\x21\x28\xa0\xf8\x14\xc0\xe6\x89\x71\xdf\x57\xbd\x50\x78\xa7\x40\x31\x75\xc7\xc2\xfd\xd4\xa5\x24\x47\x15\x3a\xb3\x74\x56\x72\x9a\xee\x33\xe5\xfc\x93\xdb\x8e\x7f\x48\x03\x09\x87\x5e\xcf\x6d\xb0\x7c\xe7\xf3\xca\xc5\xde\x49\xe3\x61\x27\x5c\xa5\x0b\x6b\x71\x9f\x4b\x71\x5b\x3e\x30\x86\x3c\xbb\x3b\x71\x64\xba\x9e\xb9\x6e\xf3\x30\x4b\x19\xad\x4d\x74\xdc\xe4\xbd\x25\xe7\x7b\xbb\xbe\xff\x1e\xe7\xd1\xfb\x55\xb9\xc4\xf7\xfc\x4c\xd9\xbd\x55\x10\x8a\xfc\xf9\x9c\x1a\x41\xcd\x6f\x6b\x1a\xdb\x29\x7b\x10\x6c\x8b\xa2\x4e\x31\x34\xf8\x7d\xd8\xef\xe5\xcf\x85\x49\x22\x91\xb9\x4d\x66\x00\x95\x8c\x28\xb9\x12\x2f\xe6\xe0\x1b\xd3\xe3\x29\xe4\x2d\x19\x26\xb8\x9f\x7a\x8c\x40\xa4\x98\x67\xe5\xaa\x3a\xd7\x49\xbd\x98\xda\xe7\xd0\x06\xb4\x53\x60\x9e\x7d\xae\x26\x36\x4d\x91\x72\xbe\x72\x83\x33\x01\x21\xed\x2b\x40\x27\xe0\x88\x51\x18\x74\x3a\x6e\xa0\xcb\x7d\xc2\x74\x09\xa9\xb2\x82\x0b\xcc\x24\x2e\xa1\x0a\x00\x93\x7b\xf8\x49\x20\x1e\x0f\xb6\x19\x94\x21\xf1\x63\xe9\x79\x4f\x2d\xd4\xb3\x32\x01\x4a\x09\xd3\xee\x80\x71\xda\x78\x77\x47\xf9\x90\xf5\x17\x99\x19\x02\x7d\xdf\xf7\xca\xb0\xf5\x5e\x9a\xfa\x8e\xcc\xb1\x6c\xc2\xdd\x3c\xbb\xea\xd7\xff\x7e\xc8\x18\xc2\x53\x39\x3f\x74\x87\x41\xf5\x54\x07\xf7\x40\x8e\xe3\x3a\x42\xae\x2d\x6e\xcb\x3f\xb6\x00\xa7\x1f\x30\xab\x63\x06\x06\xe5\x53\xb4\x36\x78\xe5\x98\x54\xf3\xa2\x94\x7b\xcf\x4e\xa0\xfc\xfe\xdc\x31\x4d\x83\x70\xd1\x26\x63\x95\xfd\xa3\xc9\x10\x5e\x97\x59\x52\xf6\x0e\x30\x86\xbb\x82\x48\x15\x13\xd6\xfe\x8a\xdb\x4f\x95\xef\xb9\xa9\x5b\x66\xd4\x80\xd2\xbb\x17\x10\x78\xcf\x40\x68\x4a\xc6\x9a\x78\x9c\x7f\xb7\xfa\x42\x53\x33\xd7\x05\xdb\x00\x06\x67\x55\xdf\x72\x8d\xe0\x2d\xf2\x5b\xae\x34\xf1\xd7\xd4\x9c\xaf\xfc\x51\xe9\xba\x2b\x10\xb9\x8f\xe4\xcd\x9d\x22\xb7\x76\x4e\xd9\x31\xed\xb5\xf0\xb5\x54\x49\x6e\x99\x53\x91\xe0\xaf\x0b\x8d\x1c\x7a\x82\x95\xa8\xd1\x5a\x7c\x65\x56\xd2\x9c\xb1\x9e\x08\x55\xca\x50\x5a\xd0\x1d\x2a\xa3\x09\x28\xa8\x4b\xc4\x89\x59\x57\x6d\x81\x2d\x9b\x27\xb8\xe8\x88\x79\xfa\xa2\x80\x6c\x08\x41\x36\x0e\xcd\x0f\xe8\x3f\x5b\x84\x8f\xc1\x2f\x65\x8f\x1e\x7f\x40\xe5\x61\xc2\xe7\x8d\x3b\x01\x25\x21\x0a\x92\x06\x1c\x2d\xb2\x1b\xa6\x60\xe8\x60\x8f\xf5"}, -{{0x7b,0xa2,0x5f,0x27,0x97,0xa2,0x83,0x6f,0x37,0x9d,0x6b,0xbc,0xbe,0x9a,0xbf,0x4f,0x2d,0xef,0x5e,0x52,0xf7,0x2b,0xd9,0xe0,0xb0,0x06,0x57,0x10,0x22,0xfa,0xc2,0xf3,},{0x6c,0x2e,0xd4,0xe8,0xc0,0x12,0x4d,0x5d,0x05,0x40,0x79,0x6d,0x39,0x45,0xd1,0xde,0x71,0xaa,0x69,0x69,0xe6,0xab,0xea,0x0f,0x1b,0x0e,0x6f,0xc4,0x29,0xc7,0x04,0x6f,},{0xf1,0xf5,0x90,0xa9,0x07,0xba,0x98,0x0e,0xb0,0xd6,0x48,0xab,0x4d,0xed,0x5f,0x92,0xfa,0xf7,0xcb,0x85,0x1d,0x81,0xd8,0x58,0xa7,0x8f,0xa6,0xb7,0x7c,0xbb,0xe1,0x2f,0x64,0xd2,0x0d,0xf5,0x27,0x71,0xa7,0xd5,0xe5,0x39,0xa1,0x52,0xd7,0x31,0xe1,0x90,0x3d,0x42,0x11,0xfd,0xcf,0xef,0x9a,0x48,0xb4,0x6c,0x8f,0xd5,0x39,0x4c,0xa0,0x09,},"\x17\x1a\x34\x09\x87\x80\x97\xb3\xb2\x2b\x2c\x00\x66\x0b\x46\xe5\x42\xc2\x16\x4c\x00\xbb\xee\x54\x55\x48\x37\x94\x0e\x70\xf0\x3d\xa9\x91\x6a\x40\xf9\xbd\xe8\x28\x8f\x45\xe4\x7b\xef\x7f\xfe\x4e\x55\x7c\xd4\x47\x40\x45\xe7\x40\xfd\x95\x9d\x98\x4f\x4e\xc8\x1d\xa8\x8d\x44\xa3\x73\xc1\xed\xa0\xcf\xc6\xb0\x8e\x35\x13\x73\xd3\xb8\x2a\xb0\x90\x2d\xf8\x06\x3f\xd9\x08\xe7\x03\xe0\xcb\xec\x41\x0a\xb5\xcd\xfe\xaa\xe0\x01\x88\xce\x2a\xd4\x2b\x8b\xf0\x4f\x7d\xaa\x5f\x0e\xe3\x33\xa6\xf9\x31\x1b\x4a\xd9\x81\x09\x52\xd5\xd5\xa6\x4b\x20\xf3\x7e\x84\x54\x15\xfc\x3c\xdd\x61\x6f\xeb\xec\x50\xdb\x29\x6f\xb3\xf3\xbb\x7f\x6b\x36\x6b\xbe\x52\xe4\x89\x7a\x05\x61\x7b\xf7\xc9\x81\xa6\x2e\xdc\xbb\xbe\x5d\xa4\xc3\x9c\xaf\xa8\x69\xaa\x2b\x27\x34\xe6\xcf\xed\x90\xed\x8b\xe7\x59\x49\x39\x0e\xe4\x45\x66\x89\x24\x55\xb8\x90\xcf\x56\x8b\x94\x5a\xab\xb7\x58\xd3\x85\x4b\xe6\x53\x9f\x3b\x86\xbf\x01\xd1\x88\xe4\x8c\xf2\x62\x6a\x0d\x7d\x38\x17\x03\xbe\x6e\xd1\x29\x0d\xfb\x94\x7b\xc2\xe0\xf8\x3d\xbc\x58\x70\x30\x80\xd7\xf5\xb9\xef\x19\xae\xf9\x30\x90\x8f\x68\xf0\xc8\x00\x10\xa9\x40\x1b\x30\x3a\x9f\x6d\xa8\x05\xbb\x8a\x0e\xd0\xf3\x94\x13\xee\xfe\xdf\x91\x9f\xfd\x8e\xa6\x39\x1b\xf9\x5d\x42\x29\x60\x4e\x49\x45\x7b\x8e\x23\xbe\xc6\x11\x48\x4c\xc7\xf9\x83\x2d\xd9\x5b\xdc\x3a\xd1\x77\xc0\x50\xf4\xab\x63\x3d\xcd\xb3\xe6\x91\xf5\x90\x28\x73\xb3\x8c\xb0\x72\x0b\x91\x13\x35\x7f\xe0\xcf\xb9\x8a\x68\xcc\xcb\x5d\x5f\x08\x09\xd5\x9a\x37\x5c\xf7\xb5\xa2\x75\xd4\x3c\x4c\x34\xff\x68\xe4\x48\x52\x6e\x8e\x1a\xad\x44\xe2\x00\x08\xa2\x32\xaf\xbc\xf5\x32\xa4\x2b\x50\xa0\x25\xa1\xb2\xee\x4e\x07\x7e\xb0\x12\x5a\x59\x3d\x51\xa2\x00\xec\x20\xd8\x72\xc0\x58\x38\xad\x36\xaa\xae\xec\xcc\x3e\xd9\xef\x41\xf6\xd1\x22\x67\x02\x17\xd5\xc0\x8f\x6e\x13\xc1\x72\x19\x45\x89\xac\xc3\xc5\x9f\x7e\xf7\x90\xc7\xc8\x5a\xa6\xd5\xeb\x69\xd4\xc8\x9a\x72\xf5\xe7\xc9\x24\x69\x85\xc1\xac\x0c\x5d\x19\x7f\x76\xa7\x3e\x37\x74\x83\x9d\x4a\xa2\x09\x6a\xca\x19\x0a\x30\xf4\xaa\xc5\x40\x57\xb6\x4f\x35\x8e\x0e\x06\x40\x0c\x0d\xf2\xf8\x76\x41\x2d\x34\x48\x4c\x43\x44\xf4\xd7\xc8\x66\x51\x7d\x3e\xfb\xa4\xa9\x0f\xa7\x14\x4c\x9b\xa5\xdb\x33\x61\xdb\x57\x69\x40\x3e\xc8\x16\x26\xa5\x11\xf9\x3e\x30\xf8\x58\x6e\xad\xfc\xaf\xd9\xa3\x6e\xcf\xf8\xd2\x4b\x42\x07\x9a\xda\x8e\x57\x9a\xc3\x08\x51\x17\x7b\xce\x90\x38\xb0\xe1\x30\x00\x72\xd6\x8e\xfd\xd7\x23\xf6\x35\x50\x64\x84\x32\x75\x81\x5a\x66\xb9\xd7\x3a\x12\x99\xaa\x59\xa1\x81\x2f\x64\x52\xfb\x41\x15\xea\x2b\x1f\x9f\xf4\xa9\x96\x90\x59\x6e\x3f\x20\x22\xd8\x1e\xd8\x74\xdd\x67\xe6\x18\x9c\xa0\xe6\x8b\x93\x04\xe9\x93\xa9\x5b\x66\x66\x5e\x0d\x07\x4c"}, -{{0xd1,0xe1,0xb2,0x2d,0xe5,0xe0,0x4c,0x9b,0xe4,0x65,0x1d,0xd7,0x39,0x95,0xa3,0x66,0x6c,0xb5,0x35,0x2c,0x65,0xac,0x7b,0x70,0x51,0xb3,0x66,0xfe,0x1a,0xc0,0xc3,0x10,},{0x12,0xfe,0x56,0xf1,0x01,0x2d,0x5c,0x12,0xf1,0x35,0xed,0x59,0x82,0xf3,0x82,0xae,0x5f,0x11,0x43,0xbc,0x90,0xe8,0xcb,0x8c,0x93,0x05,0x17,0x54,0x55,0x1e,0xe9,0x0a,},{0xab,0xaa,0xb4,0xfa,0x6a,0xeb,0x0a,0x0b,0x34,0xee,0x0d,0x61,0x3a,0x0a,0xf0,0x49,0xed,0xb4,0xce,0xdb,0xfe,0x9d,0x3b,0xeb,0xe9,0xc0,0x06,0x18,0xb1,0x15,0xb9,0xd1,0xfa,0x52,0x4e,0xc3,0x49,0x5e,0x13,0x30,0xb0,0x93,0x61,0x81,0xea,0xbb,0x14,0x29,0x9f,0xac,0xcc,0x40,0xea,0xa8,0xcc,0xa5,0x7e,0xd3,0x24,0xb7,0xa6,0x42,0x0c,0x0e,},"\xc7\xf2\x18\xb5\xaa\x7a\xae\x17\x99\x62\x5a\x56\xc4\xd7\xd7\xb0\x26\x37\xe5\x72\xf1\x41\x1a\x61\x22\xf1\x13\x79\x1a\xa3\xc6\x28\xe8\x19\x60\x2f\xb4\xf0\x33\x5a\x61\x23\x01\x3f\xa6\x4e\x9f\xdc\x4e\x4a\xe4\x97\xbd\x16\x9c\x2f\xa7\x7b\xc2\x36\x12\x97\x17\xf4\x62\x88\x6b\x41\x08\x93\xfa\x78\x09\xcb\xfd\xc8\x92\x22\x3b\x40\xee\x04\x1e\xbd\x4e\xc7\xdd\xab\x55\xbe\x60\x81\xa1\x64\x66\x43\xa9\x12\x0b\xaa\x46\x28\x9a\xcb\xa1\x5b\x3b\x48\xaf\x3b\x7a\xde\xcd\x69\xf4\x3e\xed\xe7\x9d\x9b\x19\x57\xe1\xd8\xc3\x12\x9e\x0f\xa0\x57\x9d\x3d\x39\x53\x70\x46\x1b\x0e\x12\x55\xc9\xca\xa9\x4e\x47\x25\x60\x1c\xb9\xd0\xe2\xd6\x02\x44\xd1\x5b\x64\xe1\xf7\xbc\x90\x15\x59\x0a\xd0\x99\x1f\x12\xf8\x26\x73\x11\x20\x6e\x9e\xb5\xd1\x6a\xdd\x0b\xa5\x21\x8f\xce\x5f\xff\xe1\xc9\xce\x5f\xfe\x1f\x73\x11\x32\xf4\xb1\x2c\xac\xb0\x2f\x97\x45\x17\x10\x84\x6b\x7f\x82\x4f\x4f\xa9\xe0\x89\x19\x26\x64\x69\x78\x9c\x00\xce\x0d\x94\xd3\x8f\xa8\xfe\xc3\xf5\x1f\x2f\x88\x6e\x9d\xb0\x9b\x80\x44\x70\xb1\x9e\xc9\xe8\x06\x63\xf1\x55\xb4\x98\x4d\x2b\xbd\x0b\x2c\xe9\x93\x02\xe0\x6c\x64\x44\x4b\x69\x6e\x31\x29\xfc\xef\x34\xc3\xdd\x00\xf7\xab\x5b\xed\xa7\x47\xa3\xfc\x63\x39\x19\x2b\x74\x0f\x35\x69\xb6\x7d\xbd\x6f\xfa\x39\xe2\x71\xfa\xa4\x00\xd9\x61\x6b\xff\x86\xec\x49\xa6\x59\xde\xf2\xe7\xf5\xd4\x51\xf2\xa2\xb3\x5e\x66\x2a\x6e\x7c\xc2\x2f\x1e\x5c\xdc\xde\x8a\x59\x98\x81\x35\xb7\xe7\x65\x62\x74\x3c\x1e\x6a\x09\x99\x01\xb3\xef\x97\xcb\xff\x23\xf2\x09\xbd\x70\x88\xc2\xf0\x32\x45\x27\x9a\x1d\xc7\x8d\xdd\xc1\xbb\x0c\x1d\x35\x10\x03\x57\x88\x21\x26\xb3\x28\xd3\xd9\x4e\x08\x71\xb6\x0b\xe2\x53\xfd\x1b\x6e\xcf\x03\xc1\xdb\x73\x1d\x9e\xed\x0e\xdf\x2b\x26\x43\x23\x07\x80\xa4\xd6\x6e\x99\x17\x9a\xad\x1b\x82\x40\x2e\x55\xf6\xd7\x85\xeb\xc8\x0f\x8d\xd2\xfd\x2b\xeb\x09\xf3\x10\x35\xdf\x62\xc1\x7f\x42\x8e\xd0\xb2\xd5\x65\x08\xdb\x31\xe6\xd2\xdd\x5f\xb6\x9e\xbe\xee\xa3\x25\x70\x70\xcf\x2f\xe6\x7d\x42\xd2\x88\x16\xa5\x5d\xba\xe0\xb1\x85\xdb\x44\x21\xbb\xfd\xae\xfc\x79\xc0\x8c\xdc\x1a\xcc\xf7\x16\x42\x56\x2e\xc7\x00\x36\xda\x2b\xba\xfa\x4a\x89\x19\x54\xc4\xee\x40\x49\xb5\x5c\x64\x0e\x91\x93\x0e\x39\xe3\xef\x10\x18\xdc\x16\x47\xf2\x69\x42\xc6\xdb\xdf\x4d\x56\xe4\x1e\xb2\xc8\x98\xc8\x21\xfa\xc1\x7c\xc2\x73\xe8\xe4\xaa\x56\x08\xa8\x12\xcf\x4b\x82\xf9\x60\x19\xc2\x52\xd5\x6e\x78\x05\x29\x8c\xcb\xe8\xce\x40\xb0\xbd\x0f\x93\x3b\x88\x4c\x0f\xaf\x97\xa9\x58\xb2\x04\x08\xb8\xa5\x29\x7c\xce\x55\x27\xb2\xca\x21\x28\x06\xe7\x2a\x32\x64\x45\x7a\x7f\xac\x86\x62\xb8\x2c\xa2\x33\xe1\xc7\x75\x8d\xc6\xe4\xf1\xb9\x99\x58\x63\xf2\x5f\x74\x7b\xce\xe4\x3b\x63\x9b\x1f\x8f\x20\x26\xd2\xd2"}, -{{0xdf,0x29,0x4e,0x47,0x7b,0x1b,0x91,0xc5,0xac,0x5b,0x98,0xc3,0x30,0xd2,0x22,0xd7,0xcd,0x2d,0x53,0xe7,0xd0,0xbc,0x0c,0xa4,0x03,0xdf,0x4e,0xc7,0x53,0x27,0xa2,0x74,},{0x5f,0x0b,0xd2,0x2f,0x2f,0x18,0x96,0xd1,0x56,0x3b,0x4f,0x69,0x40,0xc7,0xdf,0x89,0xef,0xc2,0x58,0xc0,0xff,0x6c,0x2f,0xcd,0x67,0x4d,0xaf,0x4f,0x59,0xfc,0xdb,0x60,},{0x99,0x45,0xab,0x73,0xb5,0x85,0x62,0xb3,0x55,0xda,0xbc,0x4e,0x2b,0x6b,0xe7,0xe0,0x5f,0x37,0xf8,0x95,0x71,0x44,0x0c,0xcc,0x32,0xc1,0xa9,0x47,0x37,0x09,0x5b,0x78,0x66,0x74,0x7d,0x21,0x00,0x70,0x00,0xa0,0xf0,0xe3,0x51,0x11,0x4b,0x88,0xe0,0x13,0x8b,0x55,0xdf,0x44,0xfe,0x72,0xeb,0xe9,0x59,0x14,0x10,0xe7,0x07,0xfa,0x9d,0x02,},"\x3e\x42\xd6\x68\x40\x96\x30\xcb\xb8\x48\x12\xac\x7f\xf1\x15\x4f\x70\xfc\xa8\xbd\xff\x3f\x1a\x04\x0f\xa3\xaf\x86\x8a\xa1\xc4\xe9\x15\x08\xb1\xae\xfd\xf5\xc3\xa8\xb4\xb0\x77\xa4\xd1\x62\xd2\xc0\x5b\xd3\x64\xfb\xbe\x8c\x5a\x08\x31\x4c\x2e\x07\xdf\xfb\xd6\xe8\xdd\x2e\x08\xa0\xdc\xc9\x6e\xa9\x2d\xdd\x4c\x97\xf7\x9d\xb9\x42\x5a\x6c\x6b\x34\xc4\x60\x43\xd0\x9a\x68\xb7\x68\x72\x36\xa9\x18\xd2\x1a\x56\x16\x10\xa1\x3a\xc5\xe4\x46\xe0\x88\x1b\xb2\x6c\xc8\xe2\x8a\xad\x16\x54\xf8\x67\xad\x82\xae\x33\xf8\xf7\xa7\x8a\x65\xbe\x57\x69\x94\x75\x51\x6a\x1a\x87\x46\x84\x3e\x93\xa1\xa2\x94\x35\x46\x24\xfa\xc0\x4d\x45\x2c\xcf\xbe\x4f\xdd\x92\xa9\x51\xaa\xa0\x7d\x26\x67\x6d\x5c\xb0\x77\xa5\x00\x0d\x43\x9c\x12\x42\x76\xc0\xdb\xcf\x86\xe7\xaa\x15\x3c\xc2\x4b\x5a\xff\x67\x7c\x6b\xad\xc2\x61\xc2\x89\xf4\xa4\xae\x51\x9b\x2e\x2f\xff\x31\x2f\xbf\x0f\x5b\x4c\x46\x98\xf6\xae\xdd\x8f\xcb\x1d\x23\x48\x94\x2d\xe3\xfb\x73\xba\x27\xf6\xdb\x14\xc2\xf0\x91\x80\x35\x6e\x5f\xca\xe1\xad\xf6\x5e\x22\x42\x5f\x8c\x27\xf1\x9e\x98\x94\x83\x50\x6e\x5d\xf5\x7a\x1b\x61\x3a\x22\xe3\x45\x03\x8b\x3e\xa9\x1c\x0f\x78\xff\xff\x46\x38\x3f\x38\xc7\x22\x25\x35\x8a\x34\x57\x0d\x6f\x66\x4a\x17\x45\x4a\x15\x16\x13\xf0\x1c\xba\x77\x7f\x62\xec\x83\x18\x75\xec\x5e\x27\xd2\x57\xf1\x80\xb6\x36\x6c\xb1\x83\x10\x7c\x40\xf5\x0b\x01\xb2\xb9\xbf\x91\xb3\xb5\x54\x9e\xd9\x31\xa3\x53\x7a\xa4\x16\x89\xf7\x2b\x25\x7a\x6a\xa3\x9c\xdc\x6f\xce\xdf\x14\x39\x83\xbe\x5b\xff\xe3\xae\x2b\x29\xf8\x2f\x88\x21\x22\xd6\x6a\x79\x25\xf5\xa7\x10\x82\x6c\x0d\xad\xb7\xe4\xfa\x4e\xc0\x79\xba\x2e\x76\xda\xda\x43\x3f\x30\x77\xcb\x1e\xf7\x46\x13\xfc\x5d\xbf\x82\x58\xb6\xda\x7c\x73\xc8\x66\x37\x24\x57\xed\x50\x0f\x97\xf9\x90\x7e\x1f\xc2\x63\x53\xc7\x0b\xa3\xbd\x9c\x36\x15\x1d\x46\x86\x5d\x2c\x65\x98\x65\x62\x48\x5c\xf8\x42\x1f\xeb\xbe\x77\x7c\x73\xe6\xcd\x00\x26\xd6\x6d\x35\x12\x8b\x9f\x8f\x33\x26\x4a\xeb\x56\xbd\x3e\x4b\x8d\x1f\x52\x66\x41\x1e\xf3\xb2\x3b\x76\xb3\x6d\x4c\x9d\xf3\xc5\x12\xfd\x56\x0c\x2b\xe5\x2a\xc5\x23\xc1\x93\x77\xad\x2a\xdc\x0e\x8c\x30\x9c\xf5\xbb\xf7\x2d\x9e\xb8\x5d\x65\xa9\x48\x47\xd4\x97\xd8\xd1\x02\x42\x4f\xb8\x43\x81\x66\x6e\xcb\x1c\x35\xa3\x72\x5d\x7d\x9e\x92\x84\xfd\xeb\xb6\xb3\x62\xaa\x6a\x9c\x6f\xb3\x7a\xba\x87\x35\x7f\x57\x4c\x0e\x63\xb4\x49\x7d\x49\x8f\xfb\xb7\xd0\x69\x2d\x78\x4b\x4b\x18\xce\x9f\x91\x50\xc1\x46\xd3\xd1\x8c\x38\x2e\xda\x04\x93\x8c\x69\xd0\x77\x8f\x29\x02\xd5\x23\x5a\x56\x52\xb9\x7c\xef\x6d\x5f\x60\xda\x6b\xd7\xed\x4f\xf9\x7c\xd9\x4d\x49\x39\xca\xca\x3b\x6b\xaa\x3c\xfd\xac\x04\xcd\xa9\x55\x96\xf4\x67\xcb\xc6\xcb\xcd\x92\x64\x16\x77\x43\xea\xc1"}, -{{0x70,0xc6,0x85,0x9f,0x08,0xcf,0x42,0xb4,0xbd,0xa9,0xeb,0x62,0x97,0x9d,0xff,0xb7,0xcb,0x08,0xeb,0x3d,0xab,0xe9,0x3f,0xe9,0x4b,0x01,0x38,0x46,0x17,0xcf,0x67,0x30,},{0x40,0x1c,0x9e,0x20,0x33,0xe2,0x25,0x9f,0xb6,0x38,0x3b,0x3e,0x8b,0x9e,0x17,0xb3,0xf2,0x06,0x27,0x46,0xbb,0xe6,0x48,0xcf,0x48,0x45,0x16,0xdb,0x0f,0x2f,0x1b,0x06,},{0x0f,0x03,0xa4,0xf1,0x5c,0x33,0x9b,0x4f,0x7b,0x88,0xb4,0xe2,0x1a,0xd9,0xe3,0xd6,0xbb,0xf3,0xef,0xfb,0x7b,0x67,0x8f,0xfa,0x50,0x0d,0x47,0x38,0x3b,0x71,0xa7,0x45,0x4f,0x62,0x90,0x7b,0x56,0xf5,0x9f,0x9b,0x9a,0xf6,0xd5,0xb2,0xa0,0xfc,0x1c,0x73,0x7a,0x64,0x10,0x51,0x95,0x08,0x98,0x99,0xf5,0x7a,0x2c,0x9d,0xba,0x50,0x9e,0x0a,},"\xdd\x06\x09\xea\x15\x99\x21\x39\x5d\x11\xfb\x2d\xa8\xea\x4f\x74\x7d\x7f\x74\xb5\x80\x52\xe0\x1c\xad\x40\xa2\x71\xfa\x0b\xbe\xed\x91\x02\x0f\x4f\x0c\x08\x46\xc4\xf0\x77\x78\xa6\xaa\x76\x8e\xb5\x17\x12\x29\x4e\x9e\x1f\x32\xa6\x02\xb1\x52\x51\x4f\x5e\x6d\x39\xf9\xe0\x8f\x7a\x78\x12\xbd\x90\x0c\x10\xa9\x14\x69\xe4\x7e\x8a\x78\xe5\x4c\xd4\xbd\x7c\xfe\xde\xde\xc1\x71\xef\x37\x3f\x1c\x4f\x9b\xbc\x2c\x81\x40\x2f\xb1\x4e\xd0\xbf\xac\x8d\x04\x3f\x11\x7d\x61\x24\x52\x1a\xfa\xe0\x91\x6a\x51\x0d\x56\x8a\xcf\xa3\xaa\x33\x01\xbc\x97\x9a\xc2\x8d\x55\x1d\xbb\xea\x6c\xea\xc4\xc2\x12\xaa\x8c\x84\x92\xb3\x61\x3a\xe7\x39\x5d\xd4\x12\x5f\xc4\xc2\x5d\x5b\x4d\x99\x23\x08\x21\xd4\xb1\x7e\xc2\xee\x6b\xe7\xd6\x04\x19\x5a\x21\x54\x33\x3b\x97\x35\x26\x58\x0c\xa7\xef\x9e\x30\xc6\xc1\xdd\x42\xef\x2a\xfe\x42\xb1\x1b\x1a\xa4\x9b\x9c\xca\xba\xca\x17\x09\x1e\xeb\x38\x0e\xc5\xe3\x4a\xd1\xe3\x82\x7c\xc6\x0d\xac\xf1\x44\x28\x6c\x78\x92\x59\x0b\xd2\x67\x1a\x8d\xc5\xf3\xa7\x02\xc1\xde\x7c\xd3\xb4\x2c\x1b\x15\x0b\x09\xc3\xe5\x8e\xf6\x94\x3b\x45\xd8\x9d\x41\xdf\x36\x1f\x1d\x5c\x25\x56\x55\x91\xb6\xac\x8d\xea\xa7\x36\x76\x53\x1f\x6e\x5a\xbe\x58\x04\xb0\x09\x7f\x8d\x45\xea\x29\x39\x17\x73\x33\xca\xce\xf1\x2e\x4b\x71\xfe\x49\x36\xba\xfe\x00\x74\x7a\x89\x30\xbc\xea\x55\xb8\xfd\x84\xa0\x1f\x6d\xf8\x4e\x7a\xcb\x93\x1f\xc7\xc0\x1d\xdf\xd6\x3d\xee\xc3\xad\x3e\x69\xdf\xa2\xb7\x35\x50\x58\x3d\x57\x47\xee\xe9\x6c\x55\x36\x36\x87\x97\xe2\x47\xf2\x3f\x53\x7d\x79\x07\x9a\xb6\xda\x31\x41\x02\xc7\x44\x3d\x41\x96\x0e\x3a\x3d\x8c\x35\x9c\x4a\x4e\xc6\x26\xfc\xc4\x4e\x11\x0e\xa7\x44\xd4\x17\xaa\x85\x0d\xb8\xec\xdb\xfe\x34\x0a\x96\x2d\xb0\xd8\xc5\x7d\xc5\x17\xbe\x8b\x40\xd1\x4d\xe9\x7b\x1e\x9e\x04\x26\x44\x7f\xde\x0a\x04\xe5\x06\x79\xc5\x3b\xa1\xaa\x3c\xdc\x38\xc7\xed\xe6\xdb\x6c\x05\x4b\x1e\x9c\xe7\xde\xad\xaf\x93\xeb\xdd\x47\x07\x91\x53\x5f\x3e\xcf\xab\xf3\x41\x63\x55\xf7\xa1\x8a\x38\xaf\xe6\xbf\xe5\x07\xef\x08\xc4\x37\x3a\x4a\x69\xde\xe1\xfc\xb6\x5b\x16\x31\xa0\xde\x14\x88\x64\x9d\x0b\xb2\x67\x9a\x9a\x45\xf6\x78\x20\xb2\xa4\xa1\xe5\xa5\x48\x07\x2d\xa7\x03\x2d\x17\x25\x55\xe7\x88\xcc\x98\x60\xeb\xb3\xc0\xc3\x59\x49\x37\x51\xb0\xc2\xc9\x50\xa7\xfc\xf4\x80\x3c\x14\x7f\x93\x40\xfc\x93\xd8\x5f\x1e\xfa\x57\xb3\x90\x81\xb9\x2d\x93\x47\x3f\xd2\x35\x16\xc4\x95\x0e\xd4\xb2\x9a\x2e\xd3\xa0\x42\xae\x3d\x92\xa1\xe5\x2c\xb7\x09\x63\x6f\xc7\x27\x2f\xd7\x47\x20\x8b\xee\x2b\x16\xd1\x91\xe4\xc6\xde\xb2\x76\x72\xaa\x34\xe4\x39\x14\xcf\xf2\x05\x5c\xa4\xee\x8b\xa3\xe1\xdc\x58\xa6\x79\xc7\xf7\xde\xe2\xc1\xd5\x3e\x28\x75\x09\x70\xf5\x7d\x85\xea\xb1\xc2\x6b\x89\xbb\x73\xe0\xb1"}, -{{0xc5,0x96,0x29,0x61,0x81,0x5b,0x57,0xcd,0x16,0x24,0x03,0xce,0x08,0xe4,0x10,0x5d,0xdb,0x8a,0xae,0x2d,0x3f,0x53,0x3f,0xb4,0x9c,0xc2,0x36,0xb5,0xff,0x50,0x4d,0x6e,},{0xdb,0xad,0xe7,0x22,0x36,0xba,0x12,0xd4,0x97,0x7b,0xa4,0x6c,0x36,0x4b,0xb6,0x9a,0x88,0x7f,0xf4,0x02,0xde,0x91,0xd4,0x7a,0xfa,0x9b,0x93,0xc9,0x5b,0xe7,0x1e,0x7e,},{0x81,0x01,0xba,0xef,0x00,0x4e,0xb6,0xf5,0xad,0x4d,0xe0,0x97,0x9f,0xf3,0x6d,0x34,0x39,0xb8,0x21,0x2b,0xdc,0x92,0x89,0x42,0xe4,0x31,0x91,0x5b,0x3f,0xd1,0x8b,0xc2,0xad,0x67,0xb2,0x6f,0x18,0x94,0x1d,0xcb,0x16,0xd2,0xc2,0x91,0x91,0x42,0x1e,0x77,0x9f,0xed,0x62,0x2f,0xd9,0xf5,0x82,0x64,0x4e,0xaa,0xdb,0x3f,0xe5,0xc0,0x98,0x03,},"\x4a\xe4\x14\x8d\x79\xca\x94\x25\x59\x2a\xa2\x40\xbd\x15\x34\x24\xa3\xbf\x4a\xe2\x73\x95\x87\x2c\xe5\x72\x8a\xc7\x61\x35\x96\xa7\x7d\x5c\xe8\x56\x5d\x8d\x6e\x1b\x59\x35\xb3\x90\x6c\xaf\xe1\xff\x88\x8e\xbc\x98\x15\xe0\x4a\x62\x4d\xfc\x4c\x69\x07\xb8\x5f\x6f\x1a\x0d\xbd\xdf\xf6\x2e\x91\x51\x22\x0d\x47\x44\x62\xcb\x9f\x13\xd8\x9d\x3a\x93\xa0\x0b\xa2\xb6\x0f\x7e\x7c\xa6\x3d\xa1\x7a\x63\x79\xd6\x73\x55\x1e\x79\x0b\x59\x11\x72\x7c\x90\x6d\xc9\x4f\x86\xd8\x27\x75\x46\xc1\x56\x4a\x45\x57\x3a\x77\x43\xbb\x8a\x13\x8c\xde\x87\xb3\xb2\xf2\x8e\x5e\x24\x59\x40\xa5\x1e\x7c\x45\x8c\xf8\xc5\xf0\xa7\x02\x75\x96\x25\x53\xe0\xd2\x39\x0d\x17\x1d\xb4\x4c\x2f\x7a\x5c\x9e\x9f\x93\xb9\x0f\x7a\x5f\x54\xf1\x91\xb0\xd8\x75\xba\xd7\xe0\xbe\xb9\x80\xc2\xa3\x36\x5c\xd7\xb9\x20\x87\x24\xf4\x65\x44\x18\x11\x7e\x16\xef\x71\x34\xe3\xe2\x79\x4b\x6f\x9e\x80\xec\xab\xec\xa3\x25\x4e\x70\x4c\x21\xb7\xad\x30\xc5\xde\xe0\x17\xea\x25\x33\xfc\xd9\x42\x51\xe5\x5a\xe7\x5a\x8c\xc6\xdb\x66\x74\xb3\x9c\x88\xca\x42\x00\x60\x43\xd6\xbd\x9b\x00\xec\xf6\x4c\xea\xfe\xeb\x40\x2b\x1f\x22\xfd\x89\x1f\x2d\x11\xc5\x15\xc1\xab\xa6\xa2\xd4\xc0\xbd\x21\x81\xa4\x8e\x43\xfd\x1c\x0a\xf9\x1f\x9b\x7b\x7d\x37\xf3\xdc\xd9\xe4\xc0\xa7\x59\x74\x84\x67\xd3\x48\xa8\xb1\x16\xdf\x6a\x4e\xac\xf1\x78\xae\xcc\xcd\x30\x66\xe9\x2d\xca\x45\xda\x7a\x3e\x31\x9f\x37\x71\xeb\x34\x90\x02\x21\x93\xc5\xb6\x52\xf0\x45\x68\x7e\x17\x05\xf2\xe5\x69\x1c\x13\x4b\xe4\x00\x63\x53\xd7\xec\xd0\xe9\x18\xd5\xde\x0f\x3b\x87\x80\x9f\xca\x4a\xcf\xab\x94\xe1\x14\x8f\xf7\xcf\x07\xf7\xcf\xd0\xc7\x45\xdd\x2b\xe0\x1a\x24\xa5\xe0\x69\x28\x06\x98\xbc\x3f\x54\x00\xa6\xdc\xd0\x8e\x44\x59\x5c\x03\x88\xe4\x48\x33\x76\x8f\xc4\x91\x04\xee\x11\x5b\xdc\xb0\x2b\xfb\xda\x17\x9d\x16\x4c\xe9\x69\x93\x66\x29\xf2\x33\x56\x01\xb5\x6f\xe8\xf7\x85\xcc\xa3\x80\x5f\x04\x03\x87\x2c\x62\xf7\x3c\x3c\xe8\x05\x63\xd0\x70\xe9\x76\xd8\xec\xc5\x11\x24\xe2\xca\xce\x7e\xe1\x86\x99\x04\x7c\xb0\xf8\xfb\x8d\x9c\x59\xb8\xa6\x0d\x12\xc0\x8a\x09\xfc\xe5\x8f\xd9\x2c\xd3\x6d\xb6\xa8\xe8\x9d\x11\x8c\xf8\x8a\x92\xdc\x8a\x26\x00\xbd\x95\xf5\xa8\xe8\x5d\xb5\xcd\xbb\x24\x9c\xa8\x12\xca\x20\x9c\x76\x18\x05\x1c\x45\x64\xa3\xa0\xe1\x92\xb7\xe4\x59\x92\x45\x6c\x87\xd1\x74\x12\xc1\x1a\xde\xad\x52\x6a\xb8\xdb\x21\x45\x2f\x74\x71\xd1\x7f\x2e\xbc\x90\x01\x54\x50\xed\xf4\xf0\xa4\x4f\xb2\xf4\x90\x5f\x74\xd7\x02\x75\xcc\xd8\x9b\x93\xa6\x50\x47\x3c\x02\xa7\xda\x0c\xbc\x67\x91\x5c\xeb\x7a\x1e\xa5\x9f\xa8\x88\x44\x72\xdc\x91\x7e\xe9\xd2\x46\x33\x9c\x59\x26\x84\x3e\xcf\x53\xfa\xfd\xc5\x6a\x69\x56\x01\xa2\x76\xc2\x3a\x84\x3e\x4d\x30\xf8\x9c\x97\xc9\xee\xe6\xdf\xc7"}, -{{0xde,0xe6,0x86,0x6c,0x78,0x74,0xc1,0x27,0x02,0x9e,0x96,0xe0,0x25,0xbf,0xfd,0x35,0xfc,0xfd,0xf4,0xdc,0x36,0x96,0x6c,0x15,0xee,0x62,0x93,0x36,0x80,0x13,0xd3,0x79,},{0x08,0xc9,0x4d,0xa3,0x51,0xbb,0x2b,0xee,0x72,0xe6,0xe1,0x96,0xbe,0x74,0x88,0x07,0x58,0x37,0x62,0xc5,0x29,0x6e,0x05,0xb1,0xe5,0x29,0xc4,0x7c,0x6b,0xba,0xce,0xc6,},{0xb7,0x8e,0xbd,0x6d,0x65,0xb1,0x75,0xd4,0xbb,0xd3,0xd9,0xa2,0x08,0x2a,0x0e,0xfe,0x6e,0x99,0x1c,0xb2,0xe4,0x03,0x52,0x1e,0xec,0xe0,0x0f,0x41,0x8f,0x2e,0x95,0x6b,0x66,0x90,0x78,0x80,0x65,0x8b,0x9e,0x8e,0x47,0x69,0x96,0x53,0xd1,0x59,0x13,0x23,0x80,0xd9,0xce,0x11,0x09,0xaf,0x9c,0x27,0x57,0xda,0xf4,0xcd,0xf1,0x8c,0x9c,0x0a,},"\xf1\xaa\x19\x77\xf5\x31\x1b\x53\x8b\x94\x0a\xe4\x42\xa3\xab\xc8\x9a\xac\xcd\xcd\x0a\x79\x38\x0a\x24\x25\x8d\x4a\x9f\x1c\xe6\x38\xfc\x2f\x5b\xa2\xe5\x3f\x8e\x1f\xa6\x17\x6f\x17\x8d\x90\x24\xa7\x78\x94\xc2\x8c\xad\x42\xd6\x29\xc7\x93\xd6\x8a\x02\xbe\x94\x11\xb5\x27\xac\xad\xae\x7e\x5c\x38\x51\xba\xbb\x45\xb5\xfe\xce\x32\x9e\x29\x03\x4c\xd4\x25\x71\x08\x37\x27\xf3\x5a\xec\xad\x7c\x9b\xe5\x95\x4e\xc6\x4e\x8f\x6e\xca\xb7\xcc\x05\x90\xe5\x41\x56\xa4\xe1\xa4\x53\x03\x84\x9f\x78\x97\xe7\x2c\xf2\xfb\xcd\x84\xf5\x6c\x72\xf9\x41\xdb\xb0\xb0\x9a\x32\xe6\x38\x6f\xbe\x18\xa4\x3b\xb9\xbd\x8b\x79\x3e\x4b\x9e\xdd\x53\x21\x03\xea\xb5\x4d\x62\x71\x17\xd2\x81\x39\xb6\x4e\x60\xfb\x0b\x81\xd0\x90\x01\xbb\x24\x04\xd9\x25\xe2\x65\xba\xbd\xc6\x9f\x96\xb1\x35\xe9\xe6\xab\x7f\xeb\xb1\xed\x30\x75\xd6\xaa\x2a\xbd\x2b\xbf\x9b\x65\xfa\x9b\x3b\x71\x91\xef\x37\xb6\x33\x60\x59\x10\xee\x88\xf6\x6e\xad\xa7\x9f\x00\xf5\x36\xd3\x80\xb8\x2f\x2f\x4b\x59\x85\x11\x2d\xe0\x04\xa5\x66\x03\xf4\x43\x6d\x8f\xf3\x00\xf4\x2b\xf5\xac\xdc\x7a\x4b\xf1\xea\x9d\x41\x96\xc4\x80\x49\x5b\xac\xb0\x06\x76\x30\xfc\xc0\x00\xb4\xf2\x79\xdd\x3f\x30\xf3\x53\x27\x60\x92\xd1\x52\xc3\xf4\x3e\xfd\xc0\x41\xde\xaa\x0b\xc5\xaa\xab\xa7\xf8\xbb\xd8\x5e\x69\xc1\x37\x42\xd6\x78\xdb\xb6\x53\x60\xaa\xf7\xb5\x48\xa0\x44\xc0\xec\x60\xa5\x7a\xf6\x50\xbc\x31\x97\x3f\x83\x2f\x96\x12\x65\xbc\x23\x18\xf8\x07\x75\xaf\xd5\x1f\x55\x19\x4c\x42\x42\x3f\x7b\xf4\xe0\x05\x2f\x98\xcb\x20\x69\x13\xff\xea\x48\x86\xec\xd2\x7a\x41\x79\xb1\x37\x73\xf9\x47\x50\x2e\x18\x1b\xf1\xa1\xf2\xc6\x2c\x6f\x08\xc2\x03\x59\xf0\x6d\xf2\xb1\x81\x27\x04\x3b\x10\x70\xd0\x19\x4e\xf5\xe5\xbf\xd3\x7d\x22\x79\x84\xcf\xb1\x09\x89\xf2\x1c\x71\xad\x0f\xe3\xb8\x12\x27\xd3\xa7\x17\x89\x45\x5e\xda\x38\x3c\x22\xf4\xd2\xfc\xc7\x25\x79\xf4\x65\xe0\x66\xf3\xd3\x8b\xef\xc0\x24\xef\xef\x6c\x2e\x32\x96\x49\xce\x43\x4d\x62\x73\x67\xa9\x00\xd0\x7f\xe6\x23\x42\x35\xc8\x46\x56\xea\xc5\xdd\x0d\x78\x8c\xf4\xcb\x31\x87\x18\x24\xd6\x6a\xe4\xbc\x89\xed\xeb\xa1\xb3\x67\x01\x29\x84\x53\xe8\xda\x1e\x69\xcf\xb8\x68\x09\x5c\x3b\xe6\xed\x21\x82\xda\x1c\xff\x49\x05\xaf\xd2\x07\x31\xac\x1e\xd9\x84\x16\x47\x37\x90\x3c\x7d\x8b\xb0\xad\x16\xae\xcf\x2f\xae\x33\x74\x04\xfe\x35\x66\x45\x15\xd9\x3b\x70\x1e\x2f\x87\x86\x64\x45\x4c\x0d\xec\xd1\xc6\x55\x8a\xda\xce\x3c\xdb\x22\x75\x07\xa5\x16\x06\xf0\xa5\x4d\xf8\xdf\xaa\x42\x02\x05\xdd\x57\xc6\x52\x42\xff\x24\xa4\x05\xef\x85\xc9\x2d\x60\x28\x86\x93\x2b\x35\xfa\xbe\x9c\x3b\xce\xbf\xc6\x23\x56\x39\xe8\x73\xfc\x2d\xd0\x84\xc5\x2c\xd6\xa7\x41\x3b\x83\x1d\x1c\xc9\x99\x31\x37\x3a\xab\xd8\x47\x62\x0e\xb6\x9b\xb0\xfa"}, -{{0x52,0x36,0x23,0x55,0x59,0x95,0xba,0xaf,0x2a,0x27,0xad,0xcb,0x1e,0xba,0xfa,0xa8,0x02,0xd2,0x3e,0xf7,0xab,0xfa,0x97,0x75,0xf2,0xc9,0xbf,0xa0,0x7d,0x64,0xe0,0xac,},{0xd3,0x4d,0xea,0xe6,0x52,0x3e,0x61,0x9d,0xd1,0xbf,0xc8,0xf3,0xc4,0xca,0x4b,0x78,0xb3,0x68,0xc0,0xf7,0x20,0x03,0x5e,0x14,0x4c,0x3f,0x2f,0xc1,0x05,0xd4,0xce,0x21,},{0xb1,0x87,0x17,0x29,0xfe,0xc8,0x3a,0xea,0x0a,0xaa,0x47,0x2b,0x70,0x0a,0xcd,0x09,0x48,0x13,0xfb,0x7d,0x57,0xb9,0x09,0xe0,0xea,0xaf,0x21,0xee,0x93,0x18,0x47,0xad,0xde,0xdd,0x2b,0xe8,0x53,0x3d,0x0c,0x30,0x5c,0xb9,0xcf,0xe5,0x08,0x0e,0x76,0xc2,0x80,0x8b,0x6e,0x51,0xc9,0x82,0x62,0x90,0xdd,0xb7,0xb9,0x4b,0x6f,0x7d,0x58,0x0b,},"\x05\x53\xe6\x9e\xf2\x11\x65\x2d\x62\xbf\x28\x1b\xfb\xdd\x37\xbe\x22\x76\x9d\x81\x97\x46\x36\x1c\x7d\x65\xdd\xd0\xfa\xd6\x77\xcc\x04\x38\xb3\x01\xd1\x51\x45\x78\xe0\xda\x58\xe5\x5f\x72\x9f\xa8\xe6\x6d\xde\xb7\xf9\x73\xa8\x18\xd2\x4e\xd8\xfe\x02\x7b\x84\x91\x17\x9d\x07\x77\x3f\xb5\xd2\xbb\x96\xaa\x85\xd6\xb3\x75\x04\x54\xe5\x0d\xe9\x1f\x9b\x88\xae\xe8\xaa\x68\xe6\xbb\x53\xed\xc6\x66\x77\xb4\x1e\x60\x1a\x46\xab\x4b\xb1\xe6\x56\xe7\xfa\x5f\x01\x79\x93\x36\x80\xa6\xec\x95\x04\x27\x5e\x7a\xdf\x7a\x32\x48\xe6\x3a\x0f\xc9\xc1\xea\x5a\xe9\x6c\xd0\xc6\x5a\x89\xa7\x7c\xec\x2b\x1f\xd8\xf4\x53\x7e\x82\xc1\xc4\x88\xa6\x9a\x0e\xf6\x4f\x58\x73\x4d\x9e\x73\x47\x8e\x1d\x1f\x12\x31\x14\xef\x66\x08\x5e\x0b\xa3\x19\xcb\x81\x0b\x66\xaf\x96\xd1\x30\x8b\x1a\x2b\xd9\x2b\xa2\xc2\x65\xaa\x30\x9e\xcd\x55\x57\xd4\x02\xc3\x80\x2c\xae\x8d\x7e\x95\x00\x7f\xe6\x10\xc2\xaa\x75\xfc\x66\x19\x6c\x3f\xad\xfe\x99\x7d\x6d\x59\x98\xe1\x8d\x26\x0e\x9d\xa3\x1d\xa9\x21\x8c\xba\xd1\x03\xcb\xfc\x2c\x75\x47\x76\x5d\x67\xe8\x1f\x24\xac\x83\x02\x2e\xf5\x1c\x6c\xc5\x08\x64\x36\x6a\x35\xf6\xb9\xb9\xaf\x94\xe8\x4c\xaa\x9f\xd3\xd7\x67\xc8\x31\xf0\x96\x7a\x61\x46\x2f\xbc\xfc\xc8\x03\xf1\x2e\x37\x39\x03\x9a\xcd\x5d\xbe\x93\x66\xf0\x5a\x33\xdb\xea\xf3\x60\xe2\xdd\xcb\xe5\xc4\x43\xf8\x0e\xf2\xad\x62\xe0\x3c\x1d\x5b\x70\xcd\xea\xb4\xa7\xdd\x41\x55\x30\x64\xc8\xd1\x52\x70\x9d\xef\xf8\x20\x76\xb9\x07\x11\x92\x37\x6f\x51\xd4\xc2\xc7\x1a\x84\xe8\x9f\x2d\x94\x01\x32\x0c\x2e\x45\x9b\x3e\x24\x3c\xca\x7c\x26\xfd\x09\x8c\x26\x4a\xc8\x8e\xf6\x38\x92\x1d\x98\x0b\x0a\xe9\xe5\x12\xd3\x72\x03\x7d\x81\xad\xc4\x81\x26\xd7\xc9\xe4\xb5\xaf\xa5\x7e\xc2\x65\xd4\x01\xb9\x65\x3e\x92\x8a\xfb\x7d\xff\x9b\x48\xe2\x95\xe4\x70\xd6\xb5\x2e\x88\xb3\x9d\x0a\x40\xcb\x8e\xba\x24\x9f\x8b\x13\xd8\x11\x13\xdb\x1d\x3e\x01\xef\x75\xc7\x22\xf2\x69\x48\x8e\x96\x3c\xc8\x18\x27\x04\xf8\xca\x01\x8e\x73\xdc\x07\x14\xe9\xa9\xfc\x79\xbc\x43\x63\xc2\x8c\xb3\x98\x43\x74\xf7\x3b\x2a\xa8\x78\x6e\x74\xe0\x15\x95\x07\xa2\x98\x83\xfe\x0e\xd1\xc6\x00\xf5\x25\x88\x5f\x2f\x10\xea\x00\x6c\x39\xe5\x9b\x92\x5b\x76\x5b\x1e\xde\x53\x42\x57\xa1\xf4\x0f\x28\x46\x58\x4f\x06\x97\x46\xb5\x2f\x56\x00\x43\x0a\x28\x63\xd7\x93\x60\x95\xfb\xc2\x2a\x6a\xda\x67\x4d\x41\xb3\x74\xe2\xb8\xb9\xa1\x9f\xa7\x12\xb5\x94\x45\x33\xbb\x6d\x6e\xc4\x3b\x89\xd4\x97\x1b\x70\x20\x5a\x6a\xcd\x72\xa8\x99\xda\x12\x61\x82\x04\xdb\x0c\x3e\x82\x67\xb8\x45\x79\x16\x93\xe0\xae\x6a\x35\xf1\x4d\xa1\xf8\xf4\xdd\x17\x4b\xce\x03\x18\xfb\x5a\x00\xf6\x72\xed\xe4\x23\x04\xcf\x04\xa6\x27\x60\x57\x75\x90\xf2\x7e\x2d\xfa\x6e\x5e\x27\x95\xd6\x60\x53\xb3\x0a\xf7\xf1\xbf"}, -{{0x57,0x5f,0x8f,0xb6,0xc7,0x46,0x5e,0x92,0xc2,0x50,0xca,0xee,0xc1,0x78,0x62,0x24,0xbc,0x3e,0xed,0x72,0x9e,0x46,0x39,0x53,0xa3,0x94,0xc9,0x84,0x9c,0xba,0x90,0x8f,},{0x71,0xbf,0xa9,0x8f,0x5b,0xea,0x79,0x0f,0xf1,0x83,0xd9,0x24,0xe6,0x65,0x5c,0xea,0x08,0xd0,0xaa,0xfb,0x61,0x7f,0x46,0xd2,0x3a,0x17,0xa6,0x57,0xf0,0xa9,0xb8,0xb2,},{0x90,0x3b,0x48,0x4c,0xb2,0x4b,0xc5,0x03,0xcd,0xce,0xd8,0x44,0x61,0x40,0x73,0x25,0x6c,0x6d,0x5a,0xa4,0x5f,0x1f,0x9f,0x62,0xc7,0xf2,0x2e,0x56,0x49,0x21,0x2b,0xc1,0xd6,0xef,0x9e,0xaa,0x61,0x7b,0x6b,0x83,0x5a,0x6d,0xe2,0xbe,0xff,0x2f,0xaa,0xc8,0x3d,0x37,0xa4,0xa5,0xfc,0x5c,0xc3,0xb5,0x56,0xf5,0x6e,0xdd,0xe2,0x65,0x1f,0x02,},"\x2c\xc3\x72\xe2\x5e\x53\xa1\x38\x79\x30\x64\x61\x0e\x7e\xf2\x5d\x9d\x74\x22\xe1\x8e\x24\x96\x75\xa7\x2e\x79\x16\x7f\x43\xba\xf4\x52\xcb\xac\xb5\x01\x82\xfa\xf8\x07\x98\xcc\x38\x59\x7a\x44\xb3\x07\xa5\x36\x36\x0b\x0b\xc1\x03\x0f\x83\x97\xb9\x4c\xbf\x14\x73\x53\xdd\x2d\x67\x1c\xb8\xca\xb2\x19\xa2\xd7\xb9\xeb\x82\x8e\x96\x35\xd2\xea\xb6\xeb\x08\x18\x2c\xb0\x35\x57\x78\x3f\xd2\x82\xaa\xf7\xb4\x71\x74\x7c\x84\xac\xf7\x2d\xeb\xe4\x51\x45\x24\xf8\x44\x7b\xaf\xcc\xcc\xec\x0a\x84\x0f\xec\xa9\x75\x5f\xf9\xad\xb6\x03\x01\xc2\xf2\x5d\x4e\x3b\xa6\x21\xdf\x5a\xd7\x21\x00\xc4\x5d\x7a\x4b\x91\x55\x9c\x72\x5a\xb5\x6b\xb2\x98\x30\xe3\x5f\x5a\x6f\xaf\x87\xdb\x23\x00\x1f\x11\xff\xba\x9c\x0c\x15\x44\x03\x02\x06\x58\x27\xa7\xd7\xaa\xae\xab\x7b\x44\x6a\xbc\xe3\x33\xc0\xd3\x0c\x3e\xae\x9c\x9d\xa6\x3e\xb1\xc0\x39\x1d\x42\x69\xb1\x2c\x45\xb6\x60\x29\x06\x11\xac\x29\xc9\x1d\xbd\x80\xdc\x6e\xd3\x02\xa4\xd1\x91\xf2\x92\x39\x22\xf0\x32\xab\x1a\xc1\x0c\xa7\x32\x3b\x52\x41\xc5\x75\x1c\x3c\x00\x4a\xc3\x9e\xb1\x26\x7a\xa1\x00\x17\xed\x2d\xac\x6c\x93\x4a\x25\x0d\xda\x8c\xb0\x6d\x5b\xe9\xf5\x63\xb8\x27\xbf\x3c\x8d\x95\xfd\x7d\x2a\x7e\x7c\xc3\xac\xbe\xe9\x25\x38\xbd\x7d\xdf\xba\x3a\xb2\xdc\x9f\x79\x1f\xac\x76\xcd\xf9\xcd\x6a\x69\x23\x53\x4c\xf3\xe0\x67\x10\x8f\x6a\xa0\x3e\x32\x0d\x95\x40\x85\xc2\x18\x03\x8a\x70\xcc\x76\x8b\x97\x2e\x49\x95\x2b\x9f\xe1\x71\xee\x1b\xe2\xa5\x2c\xd4\x69\xb8\xd3\x6b\x84\xee\x90\x2c\xd9\x41\x0d\xb2\x77\x71\x92\xe9\x00\x70\xd2\xe7\xc5\x6c\xb6\xa4\x5f\x0a\x83\x9c\x78\xc2\x19\x20\x3b\x6f\x1b\x33\xcb\x45\x04\xc6\xa7\x99\x64\x27\x74\x1e\x68\x74\xcf\x45\xc5\xfa\x5a\x38\x76\x5a\x1e\xbf\x17\x96\xce\x16\xe6\x3e\xe5\x09\x61\x2c\x40\xf0\x88\xcb\xce\xff\xa3\xaf\xfb\xc1\x3b\x75\xa1\xb9\xc0\x2c\x61\xa1\x80\xa7\xe8\x3b\x17\x88\x4f\xe0\xec\x0f\x2f\xe5\x7c\x47\xe7\x3a\x22\xf7\x53\xea\xf5\x0f\xca\x65\x5e\xbb\x19\x89\x6b\x82\x7a\x34\x74\x91\x1c\x67\x85\x3c\x58\xb4\xa7\x8f\xd0\x85\xa2\x32\x39\xb9\x73\x7e\xf8\xa7\xba\xff\x11\xdd\xce\x5f\x2c\xae\x05\x43\xf8\xb4\x5d\x14\x4a\xe6\x91\x8b\x9a\x75\x29\x3e\xc7\x8e\xa6\x18\xcd\x2c\xd0\x8c\x97\x13\x01\xcd\xfa\x0a\x92\x75\xc1\xbf\x44\x1d\x4c\x1f\x87\x8a\x2e\x73\x3c\xe0\xa3\x3b\x6e\xcd\xac\xbb\xf0\xbd\xb5\xc3\x64\x3f\xa4\x5a\x01\x39\x79\xcd\x01\x39\x69\x62\x89\x74\x21\x12\x9a\x88\x75\x7c\x0d\x88\xb5\xac\x7e\x44\xfd\xbd\x93\x8b\xa4\xbc\x37\xde\x49\x29\xd5\x37\x51\xfb\xb4\x3d\x4e\x09\xa8\x0e\x73\x52\x44\xac\xad\xa8\xe6\x74\x9f\x77\x78\x7f\x33\x76\x3c\x74\x72\xdf\x52\x93\x45\x91\x59\x1f\xb2\x26\xc5\x03\xc8\xbe\x61\xa9\x20\xa7\xd3\x7e\xb1\x68\x6b\x62\x21\x69\x57\x84\x4c\x43\xc4\x84\xe5\x87\x45\x77\x55\x53"}, -{{0x03,0x74,0x9c,0xa2,0x04,0x58,0xa3,0x5a,0x37,0xa8,0xd7,0xa2,0x6f,0x95,0x9f,0x0d,0x59,0xf6,0xdc,0x99,0x73,0xfa,0x36,0x3c,0x1f,0xf8,0xca,0x4e,0x63,0x8c,0x2c,0xd3,},{0xea,0xeb,0x94,0xf4,0x06,0xbd,0xe6,0xa7,0xcf,0x8b,0xde,0x2a,0xdf,0x30,0x81,0xf8,0x37,0x5b,0x87,0xd9,0x33,0x5d,0x49,0x6c,0x71,0xd0,0x42,0xcd,0x2e,0xaa,0x16,0x6c,},{0x78,0xa3,0x87,0x7e,0x02,0xbd,0xfd,0x01,0x5e,0x7f,0x86,0xa3,0x27,0xa4,0x8c,0xc3,0xa5,0x23,0x0b,0xbd,0xb1,0x24,0x3f,0x1a,0x8c,0xf2,0x27,0xf7,0x8a,0xb5,0xe7,0x68,0x0d,0xe3,0x01,0xa9,0x15,0xdc,0x11,0xb3,0x36,0xfb,0x5f,0x65,0x66,0x84,0x8b,0x42,0x50,0x0a,0xdb,0x5d,0x67,0x39,0x69,0x12,0x2b,0xa8,0xf0,0x05,0x3c,0xd3,0x06,0x0b,},"\xee\xf5\xce\xeb\xd0\x44\x5e\x9c\x91\x81\xaf\xf9\xc6\xf2\x66\x01\x28\xfc\xfb\x63\x69\x1a\x42\xcf\xa4\x43\xd6\xa6\x49\xef\xc5\xfa\xd8\xc2\x08\x03\x76\x3e\xe9\x7d\x1d\xba\x08\xe6\x3e\x08\xa2\x61\x6d\xa0\x50\x77\x48\x9f\x2f\xa2\xc5\x6b\x75\x34\xf9\x40\x26\x19\x25\x1f\xdf\x9c\x32\x0d\xe7\xaf\x10\x9e\x2f\xd8\xb2\x56\x5c\xe8\xa7\x52\x4c\x94\x05\xec\x0f\x8f\xca\xa7\x14\x9a\x6d\x21\x0e\xfd\xe8\x3b\x11\x1c\xf8\x2d\xc0\x83\x5c\xf9\x4f\x20\xcd\xb0\x21\xb7\x3b\xd2\x62\x66\x65\x55\xe6\xd6\x27\x07\xb4\x6e\xe4\x2f\xa9\x00\xb4\xf4\xf7\x05\xde\x33\xd3\xdb\xdc\x68\xa8\x8d\x1a\x4d\x0a\xe9\x33\x56\x6d\xb6\xc6\x23\x7e\xc8\xab\xe1\x02\x4d\xac\x4b\x7f\x46\xd4\x07\xbe\x16\x59\x4d\x90\x46\xc7\x31\x2d\xda\x66\x14\xd9\xbc\xdb\x01\xfb\x83\x24\xfc\x62\xb8\xee\xaf\x0a\xbc\x23\xcd\x57\x0e\x30\x4f\xca\x08\xe8\x8c\x73\x5e\x5d\x31\x59\x24\x09\xce\xb5\x83\x86\x2e\x6b\x0a\x76\x77\x29\xf7\x55\x6f\xa2\xc0\x53\x64\x4d\x36\xc8\x33\x7c\x02\x74\xe7\x49\x20\x29\x82\xfb\x4a\x17\x1a\xca\xc1\x96\xc0\x2b\x7f\x16\xa8\xda\x49\x07\x1c\x8a\xb8\x07\x6d\xd5\xd3\xab\xad\xfe\x3a\xf8\x2c\xa8\x5d\xa0\x2d\xcc\x1c\x4a\x6f\x2e\x19\x30\xbe\xe2\x00\x9e\xee\x0d\x97\x1e\x40\xdd\x12\x17\x5c\x8d\x00\x69\x4f\x03\x25\xa3\xb3\x13\x3c\x0d\x0b\xd3\x82\xa5\x19\x4f\xb2\x14\x22\xce\x67\xc7\x8a\x5a\x6e\x15\x37\xe3\xb9\x7d\x5e\x20\x4e\x5d\x19\x56\x96\x39\x0f\x77\xd1\x90\x24\xc1\xbf\x6b\x51\x25\xa0\xcd\xbf\x7b\x98\x80\x03\x61\x81\xc9\x8e\x1a\xc2\xe5\x16\x5b\xd4\x96\xcf\x99\x74\x51\xa1\xc1\x21\x02\xe6\x69\x46\xb1\x67\x6a\xbd\x4c\xbd\xd2\xc1\x16\x73\xf4\xf2\xcd\x5f\x3c\x9a\x43\x4d\x74\x7f\xa0\x5b\x40\xfb\xc7\x22\x68\xb4\xeb\x28\x42\xe4\x74\x1f\x51\xb7\x70\x9b\x6a\xcc\xc4\x7f\xca\xf7\x0d\x9c\x1c\x4c\x35\x86\x71\x19\xd8\x1c\xb3\xff\x1f\x16\x08\x11\x33\xf1\x65\x9a\xed\x85\xf6\x3b\xc9\x01\x98\x9e\x26\x17\xfc\xce\x15\x3c\x29\x78\xd7\x08\xfd\x02\x44\x9a\xe4\xd5\x38\xd1\x22\xdd\xb8\x52\x7c\x0a\x76\xa1\x02\xee\xff\x6e\xdb\x65\xdb\xa2\x98\xd3\xc2\x17\xf6\x55\x18\x14\xed\xde\xec\xe1\xae\xf5\xf3\x71\xa5\x4f\x12\xbf\xfd\x6b\x49\x61\x81\x9a\x0f\x24\x4f\xf0\xd7\xd8\x69\x4c\x14\x42\x2d\xe9\x82\x2c\x13\x17\x9e\x4e\xeb\x81\x59\x50\x79\xb9\xdd\x2a\xd1\xe7\xc3\x9b\xd3\x03\xcc\x44\xae\x3f\x36\x34\x88\x15\x77\xa2\x66\xfd\x6b\xb7\x91\x78\x12\xb9\x99\xdc\x80\x9d\xc0\x9c\x3d\x70\x19\xda\xcd\x28\xe4\x30\x13\xa2\xf9\xe4\xf9\x4b\xb0\xbf\x71\x24\xef\x09\x17\x83\xf7\x96\x39\x7f\x64\x63\xbf\x1e\xfb\x39\xcd\x46\xf3\x79\x0a\x1d\x9b\x6a\x7c\x30\xf1\x49\xb5\xe6\x6c\x29\x37\xe3\x9c\xb9\x74\x4d\xdc\x66\xab\x56\x1b\xad\x4e\x6f\xa8\x53\x4d\x69\x88\x38\x22\x64\x3d\x63\xd8\xbd\x7b\x18\x16\x21\xa2\x67\xe9\x55\xe7\x58\xd1\x79\x2b\x44"}, -{{0x53,0xcb,0xd6,0xf6,0x8c,0xee,0x27,0xb9,0xf7,0xbc,0x05,0x9b,0x80,0x3b,0x44,0x79,0x49,0xbb,0xc9,0xc5,0xd5,0xa3,0x86,0x52,0xd7,0x78,0x9c,0xa1,0x54,0x20,0xde,0xa1,},{0x61,0x16,0x99,0x0b,0x53,0x31,0xe2,0x16,0x5f,0x82,0x74,0x3f,0x01,0xd8,0xe7,0xbd,0x5d,0x70,0x88,0xb3,0x01,0x59,0x83,0x3f,0xa7,0xb9,0x39,0xcf,0xb1,0xcc,0x04,0xd7,},{0xd8,0x25,0x04,0x40,0x5f,0xf1,0x6b,0xa6,0x44,0x3d,0xc4,0x82,0x36,0x72,0x63,0xa8,0xe2,0x00,0x36,0x0a,0xca,0xaa,0x83,0xfc,0x4e,0x4b,0x72,0xbd,0x24,0x9f,0x16,0x10,0x3e,0xc7,0xe5,0xa7,0xe9,0xca,0x17,0x19,0x8f,0x88,0x8e,0xac,0xa1,0x6b,0x74,0x0c,0xc3,0xf5,0xc3,0xb7,0xb6,0x17,0xa3,0x4b,0x94,0x91,0xc3,0xed,0x76,0xaa,0xb3,0x0d,},"\x30\x6f\x8e\x1d\xf0\xa4\xca\x78\xbd\x77\xe8\xe1\x19\x1c\x94\xde\xaa\x82\x64\x83\x55\xc2\xae\xcb\x7e\x82\xfc\x56\xd6\x4c\x50\x46\x19\x24\x7e\x7c\xf8\x94\x33\x28\xd1\x1f\x3d\xb4\xb1\xdc\x14\x8e\x8e\xf6\xf6\xc3\xbc\x35\x59\x69\x66\x2a\x28\x1a\x65\x57\x63\x91\x24\x2b\x7b\xd5\xa6\x2f\x8f\xa7\xac\xb6\x04\xe3\xa3\x44\xae\x1a\x9d\x73\x2a\x25\x43\x15\xf3\x1a\x04\x64\xc1\xe6\x58\x74\x62\xd2\x92\x12\xc4\x0e\x5e\xcf\x06\x1e\x26\x9a\xa0\xb9\x03\x90\xba\x41\x04\x07\x21\x68\x4b\xf2\xaa\x95\x82\xd8\x30\x66\x22\x1d\xb6\x0d\x0f\x7a\xe2\xf1\x49\xa3\x6e\x16\x95\x27\x04\xfb\x1f\x3a\x98\x2e\xac\x6b\x45\x83\x66\x5c\x63\xe5\xa8\x99\x6f\x24\xa5\x66\xdd\x50\x6a\x33\xd4\xec\x8a\x02\xb2\xbd\x34\xb7\x14\xc7\x45\x00\x0c\x01\x28\xa3\xc8\x9d\x94\x25\x06\xd1\x2f\x4b\xeb\x90\x0e\x29\x03\xcd\xb3\x4b\x35\xca\x9b\x6d\x3a\xd9\xb3\x50\xac\x99\xf4\x1d\xb3\xac\xfe\x7f\xe5\x5a\x28\xc0\xf0\x06\xb8\x44\xc9\xdc\x48\x53\xfd\x98\x53\x5a\xda\x79\x41\x6d\xca\x5f\xee\x58\x03\xa2\xd9\xf5\xd6\x8e\x6b\x80\x53\x9f\xf3\x02\xe9\x73\xf2\x4e\x9b\xc8\x8b\x7c\x41\x94\x11\x7d\xdb\x9f\x93\x2b\x32\xd5\xec\x74\x86\x8a\x13\x63\x1e\xce\x68\x81\x4b\x93\x14\x21\xdc\x89\x02\x49\x57\x03\x41\xf4\xb4\x23\xe8\x6e\x8e\xe0\x81\xb2\x27\x02\xf6\x49\xa6\xc7\xa0\xb7\xbd\xf5\xfb\x75\x62\x02\xbd\x10\xb0\xbb\x22\x15\xc7\xd6\x59\x7e\xff\xd8\x52\xf0\xb8\x9a\xbe\xc1\x5e\xa8\x22\x57\x68\x9d\xf8\x1e\x33\x82\x54\xf9\x3e\x81\xcb\xf0\x61\x72\x9d\x48\x3e\xb5\xcf\x64\x98\x05\xd7\x8e\xd8\x92\xdd\x0b\xd2\x48\xca\x1e\x25\x2b\xea\x51\x84\x7e\x1e\x82\xd3\x9a\xf5\x80\x50\xdc\x4a\xfb\xf9\x11\x5a\x3a\x60\x49\x3e\x8c\x0b\xa2\xe8\x6e\x08\x98\xcd\x0d\x43\x08\x91\xb9\xeb\x0a\x40\xf8\x74\x31\xe2\x5f\x41\x53\x8a\x03\x0f\x88\x4f\xab\x36\xad\x11\x16\x5d\x26\x7e\x8d\xd9\x4d\xcb\x05\xb9\x3a\x5a\xe7\x79\x69\x43\x0e\x18\x10\x13\x4e\x15\x72\x51\xb9\x82\xdf\x34\x3d\xff\xae\x61\x23\xa9\x9a\xa0\x56\x2d\x5d\xf7\x24\x08\xf1\xa6\xe2\x9c\x40\x59\xa5\xa8\xaa\xa4\xe6\x21\x52\x8f\xc6\x3a\x9c\xbe\x1f\x4c\x0f\xef\x25\xfe\x3f\x8e\x18\x15\x77\x74\x09\x7a\x9d\x91\x02\x0a\x90\x06\xb6\xc8\x60\xec\x1e\xe1\x0d\x52\x1d\x20\x3a\x1f\x8b\xb8\x25\x61\x29\x6f\xaa\xd4\xb2\x20\x3d\xa5\x3b\x20\x7a\x45\x9b\x29\xc1\x8b\xc0\x64\x93\x32\xb1\x80\x7c\x13\xca\x61\xac\xfa\xf9\x07\x79\xfe\xbb\xc7\xf3\x24\x21\x64\x79\x7e\x6f\x57\x2c\xb1\x5a\x9b\xe5\x88\x73\x43\x45\x5e\x26\xb9\x10\xc8\xbe\xfe\xe4\x2a\xeb\x04\x7f\x9a\xbe\x6b\x37\x50\xdb\xd7\xde\x99\x20\x2a\x0b\xb5\x76\xce\x14\x89\xe6\x1c\x1f\x5d\x27\xc6\x79\x2e\x63\x21\x8e\xdb\xfd\xb9\xb3\xdc\x51\x5b\x42\x54\xd8\x2c\x85\x9e\x52\xce\x6b\xd7\xad\x29\x6d\xd0\xe3\x70\x9d\x4c\x46\x63\x62\xf9\x02\x65\xe9\x9d\xa7\xd0\xb7\x01"}, -{{0x8b,0x65,0x74,0xf6,0xd7,0x39,0x69,0x81,0xe2,0x23,0xa4,0x83,0x7b,0xc3,0x39,0xc3,0xfd,0x65,0x94,0x19,0x84,0x5a,0x21,0x21,0xbf,0x85,0xbe,0x2e,0x69,0x5d,0x86,0x0d,},{0xe3,0x81,0x1a,0xca,0x70,0x63,0x4f,0x5a,0x9c,0xe4,0xb5,0x92,0xa1,0x7b,0xb5,0xcf,0xda,0x53,0x44,0x24,0x22,0xe2,0x03,0xcd,0xa9,0x50,0x4c,0x9d,0x65,0xb2,0x63,0xe8,},{0x2f,0xd0,0x90,0x54,0x75,0xa2,0xce,0xc3,0xe7,0x6f,0x99,0x09,0xb8,0xaf,0xd8,0x3b,0xeb,0x8d,0xae,0xfa,0x77,0xaf,0xcd,0xa3,0x4c,0xb4,0xf1,0x17,0x28,0xef,0x15,0xfc,0x9c,0x1d,0x7f,0x6f,0x6a,0xff,0xfc,0x28,0xf3,0x87,0x4f,0x91,0x3e,0x17,0x98,0x0f,0x0e,0x8e,0x3d,0x5a,0xd2,0x39,0x51,0xdf,0x2b,0x32,0xef,0xaf,0x62,0x19,0xce,0x0d,},"\xa4\x8a\xac\xc0\x49\x5f\xa0\xf1\x25\x9b\x27\x86\x5d\x3d\x75\xdc\x52\xc2\xc8\x28\xea\x8c\x4c\x2a\xd7\x85\x77\x07\x2f\xef\x72\x70\xf6\xa4\xd5\x82\xbb\x7b\x96\x2f\x4c\x3f\xd1\x49\xa6\x0a\x06\xbc\x8e\xfd\x29\x70\xef\x03\x14\x8d\xdf\x61\x98\xb9\xb6\x95\xa6\x9f\xad\xb5\x34\x09\x51\xcb\x75\x39\x8a\xc5\x1a\x4f\xd5\x54\x30\x37\x8c\xd5\xda\x88\x85\x21\x0b\xfd\x21\x46\xf9\x5c\x62\x76\x32\xfe\x8b\xe0\x6d\xe0\x1a\x7c\x27\xb8\x9d\xee\xfd\x67\xef\xc6\x9c\x9b\x5c\x62\xb3\x81\x08\xf7\x76\x22\x91\x43\xda\xe6\x60\xc1\x0c\xbe\xa3\xcd\x4f\x7e\xe5\x3d\xc3\x69\x2e\xd0\x11\x77\xe4\xa6\xf7\xe4\x24\xb5\x66\x6f\x7f\x49\x5f\x2a\x65\x60\x2c\x7d\x08\xc5\xd5\x72\x23\x4a\x56\x7c\xb6\xc3\x8a\xfd\x79\xca\xb5\xc4\x03\x6d\x62\x63\x7a\xef\xab\x55\x88\x76\x9a\x44\x8a\xb4\xc6\x5e\x24\x55\x4b\xd4\x15\x80\x50\xe0\x9e\xb5\x8f\x99\xab\x40\x77\x7b\x03\x56\x70\x9b\x7c\x02\x5a\xe5\xae\x54\x22\xac\xf8\x74\x44\x93\x1a\xe4\xd9\xa8\xb3\xd9\x44\x76\x88\x11\x28\xba\x1e\xb7\x32\x8f\xaf\xc7\x5f\x6b\x9d\xac\xc9\x6d\x3b\x64\x87\xdd\xef\x7c\x59\x26\x2d\xca\xda\x42\x6a\xac\xb1\x39\x22\x93\x54\x11\x56\x62\x35\xe0\x58\x37\x26\x22\xd8\x85\xbd\x0c\xc0\x49\x58\xdc\xfb\x17\xe0\x8f\xcd\x7f\x14\x7e\x20\x15\x6c\x8e\x26\xaf\x85\x53\x0f\x55\x11\xa6\x8d\xb4\x3d\xaf\xc4\xe6\xa2\x3f\x66\x7d\xf3\x74\x3e\xed\xd7\x1a\x3f\x07\xf7\x6f\x94\xd1\x68\x8a\xfc\x84\x63\xbf\xa5\xa4\x39\xae\x31\x14\x69\x94\x8e\x74\x47\x06\x4f\x0b\x05\x06\xf3\x67\x19\xc1\x34\x66\xa1\xb9\x87\x76\xd9\x67\xec\x58\x20\x8b\xa6\x74\x03\x73\x03\xdf\xc6\x19\x0d\xa7\x83\xff\x27\x30\x3b\x86\xb5\xfc\x32\x11\xf0\x1c\x91\x5e\x83\xa6\xad\x01\x21\x44\x79\x11\xcb\xe1\xcf\x69\x6f\x61\x8f\x60\x23\x66\x43\xf2\xe9\x4e\x15\x5d\xb6\x57\x18\x29\x44\xc1\xa4\x3b\xdc\x7b\xd5\xea\xf3\x48\x1f\xe1\x28\x40\x92\xcb\x37\x89\xa8\x92\xbd\x79\xa1\x11\xfd\x41\x01\x43\xcf\x91\xae\x33\x28\x60\xb1\xd2\x9a\xa0\x41\xd1\x77\xb5\x0d\x6c\xc2\xb9\x66\x0d\x32\x8c\x0f\x23\x0a\x35\x15\xe6\xa0\xd6\x88\x70\x9c\x0c\xd3\x47\xad\x2f\xf3\x2d\x61\xd1\xe1\xe9\xba\x76\xf8\x1e\x87\x3a\x6c\x42\x0f\x17\x07\xf3\x84\x1d\xb5\x19\x6c\xb5\x3f\x50\x6f\x00\x06\x35\x2c\x7c\x44\xc0\x80\xf3\x09\x68\x01\xa5\x7a\x49\xcf\xe8\x42\x05\xbd\xd7\xa9\x80\x1f\x84\x3c\xf2\x6b\x95\x58\xa2\xdb\x78\x8e\xf1\xb2\x37\x91\x5d\x58\x7b\x9b\xa9\x77\x98\x90\xf6\x1f\xdc\x91\xe0\x3e\x4f\x4c\xdb\xef\xe4\x17\xcc\x22\xd5\x22\xa8\x6a\xdd\xdb\x53\xf3\x74\x74\x50\xab\x62\xb5\x76\x56\x5d\xb3\x2e\x0c\xd4\x42\x76\x54\x7d\x9a\x16\x65\x3c\x27\x96\x59\xdd\x4d\x17\xec\x04\x82\x7c\x53\x3e\x33\x39\x0f\xe9\x4f\x79\x35\x09\x25\x6d\xb6\x75\x31\x73\x6a\xb3\xfc\xee\x2a\x30\x1a\xc3\xf0\xa2\x4d\x3b\x10\x8d\x7e\x75\xc3\x2a\x5a\xba\x36\xd6"}, -{{0x29,0xb2,0x88,0x1b,0x8c,0xaa,0xdb,0x33,0x6e,0x78,0x80,0xc5,0x10,0xb8,0x00,0x85,0xf4,0xb1,0x22,0x18,0x60,0xb3,0x01,0xeb,0x45,0x25,0x65,0x07,0x52,0xa6,0xd2,0x89,},{0x0c,0x5c,0x44,0xed,0x29,0xd2,0x1b,0xca,0xde,0xe2,0x1c,0xbd,0xe6,0x1a,0x9c,0xdb,0x6d,0x59,0x36,0x00,0x9b,0xa2,0xf5,0xb2,0xe7,0x77,0xc9,0x24,0xdd,0xfb,0x67,0x51,},{0x99,0xe9,0x96,0xe8,0x5a,0x49,0x4f,0x19,0x80,0xcb,0x07,0xde,0x9c,0xa6,0x16,0x5e,0x7d,0xe1,0x04,0xd3,0x9f,0xe3,0xc3,0x22,0x67,0x35,0xc5,0xda,0xa5,0x69,0x51,0x6f,0xca,0xf1,0xb6,0xe4,0xdf,0xad,0x0d,0x38,0x9b,0x6d,0xb0,0xec,0x8a,0x8f,0x20,0xdd,0x2c,0x60,0x26,0x56,0xb5,0xe7,0x61,0xc8,0xf3,0xa6,0x55,0x83,0x82,0x15,0x19,0x09,},"\x19\x74\xa2\xe2\xb4\x79\x49\xf4\x67\xa9\x31\xd1\xd9\xdd\x5c\xe1\x16\xe9\xf5\x03\x0a\xd0\x9a\x8c\xc7\x28\xd1\xae\xb1\x48\xbb\xf9\xac\xf5\x98\x74\xda\x80\xe7\x08\xd5\x3c\x66\x8f\x2f\x14\xd7\x52\x20\x71\xe9\x09\x80\x84\x27\xb2\xab\x5a\x05\xf8\xb9\x4f\x21\x50\x5c\xd2\x6a\xbc\x53\x45\x89\x78\xc7\x84\xd4\x79\xea\x6d\xab\x10\x5c\x4f\x79\x84\xa0\xfb\x97\x90\xe5\x06\x24\xf4\x73\x4b\x55\x19\x05\xaa\x5f\xfa\x60\x18\x4c\xd2\x01\xcf\x2b\x26\xc9\x79\x5d\xa6\xe7\xe0\x8d\x6a\x0b\xc7\x72\x24\x00\xfe\xf9\x4f\xc2\x10\x38\xbe\x89\xd3\x4b\xcd\x14\xc4\x27\xb8\x5b\x68\x66\x73\x71\x96\x15\x2d\x4e\xeb\x66\xd0\x5b\x24\x5a\xe8\x4b\xdc\x77\x87\xc1\x4a\x8b\xec\x2e\xea\x53\x60\xf0\x42\x43\x3d\x70\x79\x44\x67\xd4\x73\x93\xb9\x37\x57\xf3\x31\xcf\x2b\x53\xc6\x60\xd7\x1c\x29\x58\x2a\xee\xa7\x9b\x12\x52\x7a\x28\xb0\xc5\xe1\x10\xdf\x6f\x85\x4e\xea\xd9\xa2\xb0\x0d\x42\x54\x2c\xa8\x27\x6b\xb8\xbf\x98\x8b\xaa\xb8\x56\x59\x96\xfe\xe5\x0c\xf3\x1b\x24\x59\xc4\xc5\x0a\xb4\x75\x26\x5e\x83\xe2\x28\x5d\x43\xfe\x1f\x75\x2a\x55\xb2\xdb\xc4\x9f\xca\x04\xa8\x10\xf0\x41\x3b\xf6\xbd\x81\xb7\x9a\xc6\x4e\xe1\xf8\x9b\x97\xbd\x7d\x26\xd6\x25\x12\x27\x3e\x24\xa6\xba\xb2\xd5\xf7\xd2\x22\x6b\xaa\xab\x7b\x11\x12\x09\xbb\x03\x73\x3d\x8a\x60\xdf\xa3\x1a\x51\x6f\x4a\x8c\x76\x99\xd8\x28\x5c\x10\x65\x15\x9a\x6c\x73\x31\xc1\xde\xfb\x47\xa3\x0e\xf5\x85\x8c\x50\xb7\xd0\x45\x12\x4a\x09\x81\x3d\x1c\xfd\xa5\xc9\xcc\x3b\xb5\xbf\xae\x73\xc9\x84\x19\x7f\x8f\x85\x7f\x18\x6c\x41\xab\x87\xfb\x79\x62\xb6\x31\xf4\xd0\x07\xcf\xbe\xe2\x21\xfc\x65\x72\x78\x4a\x55\x11\x94\xc1\x97\x77\xb0\x8e\x6b\x59\x67\x57\xe7\xcb\xa7\xa0\xe2\x7f\xe4\x53\xf9\x0d\xc5\x9c\xc0\x8c\x64\x72\x43\x1c\x02\x0e\x8d\xd0\x91\x75\x90\xe7\x9c\x1f\x20\x73\x83\xaf\xb3\x90\x76\xad\x24\xda\x8e\xe5\x24\x86\x73\x94\x53\xa2\x59\x0e\x51\xbf\xc8\x9b\x13\xc2\x03\x3c\xfa\x5f\x89\x03\xcb\xe9\x96\x1a\x85\x98\xba\x55\x62\x32\x86\x9d\xfa\xb4\xd5\x6e\xdf\x4f\x05\xe8\xb7\x7d\x05\x87\x18\x95\xe6\x3b\x53\x51\xf7\x6c\xb2\xd2\xc8\x38\x5c\x10\x9d\x73\x06\x19\x2a\x25\x44\x6e\x4d\x62\xdc\x7d\x62\x4f\x0c\x66\x73\x98\x6b\xe0\x62\x8b\x2c\x2d\x73\xeb\x94\x1d\x35\xa3\x43\x30\x90\xf5\x9b\x28\xa5\x97\x9d\x56\xdb\xc9\xfd\x69\x73\xf6\x36\x47\x64\x2c\xd9\x03\xb0\xcf\x7a\x6a\xcd\x33\x0d\x87\xe2\x29\x27\x10\xde\x99\xe0\xc1\x79\xca\x78\x92\x9c\xca\xec\xfa\xed\xbf\x27\x42\x41\x4f\x17\x6b\x60\x90\xc0\xd5\x9a\x9d\xb7\x81\xc9\x96\x7e\x28\xfa\x4e\x77\xd2\xa0\x82\xe4\x2f\x52\x16\x91\x67\xe9\x2d\x4f\xdd\x82\xe2\xcc\x05\xdd\x91\x84\xc7\xdf\xee\x49\x0a\x23\x7f\xda\xd4\xdf\xeb\xc0\x18\x68\xe0\xa4\x35\x3a\x29\x54\xd0\x90\x92\x84\x61\x82\x1a\x7a\x84\x8d\x1b\x60\x81\x7f\xc3\xbd\xef\xa1"}, -{{0x42,0xaf,0xe8,0x9d,0xac,0x83,0xe7,0xd3,0x89,0x96,0xc0,0xdb,0xce,0x0c,0x98,0x74,0xc0,0x09,0x27,0xba,0xbd,0x77,0xca,0x8c,0xea,0xc3,0x4e,0x56,0x44,0x74,0x28,0x2b,},{0xa4,0xc5,0xf5,0xe3,0x80,0x3f,0x0a,0x03,0xd5,0xc1,0xc9,0x06,0xca,0xec,0x9c,0xc6,0xd2,0x85,0x14,0x07,0xf1,0xca,0x29,0xf7,0x2a,0x45,0xf2,0x33,0xe6,0x65,0x62,0x44,},{0x4f,0xba,0x2d,0x6c,0xc1,0xb7,0x19,0x3d,0x35,0x62,0xf8,0xc8,0xbf,0xe6,0x90,0x5c,0x82,0x9d,0xb2,0x65,0xa5,0x42,0x7c,0x5c,0x26,0x57,0x14,0x78,0x5b,0x83,0xf6,0x95,0x14,0xc5,0xe3,0x0e,0x28,0xb5,0x66,0x84,0xc8,0x2d,0xae,0x26,0x37,0x58,0x1b,0xf3,0xf4,0xef,0x27,0x14,0x20,0xbc,0x7e,0x60,0x10,0x61,0x3a,0x38,0xfa,0x10,0x1a,0x0d,},"\xe7\x10\xa1\x63\xad\x28\x85\xae\xb7\x65\x8e\xb3\x74\xf1\x18\xb7\x68\x42\xec\x36\xef\x3b\x01\x0c\x3c\x6b\x95\x59\xe8\xb1\x60\xc2\x62\x8d\xed\x0b\x85\x11\xeb\x49\x07\x18\x0d\xa4\xb6\x21\xe9\xaa\x4a\x32\x22\x88\x88\x8a\x1c\x09\x13\x0f\x69\xf8\x90\x59\x7a\x92\x93\xe7\x4f\x92\x89\xbd\xaa\x5c\x91\xb6\xfd\x24\xaa\x04\x4a\xb9\xfc\xb3\x40\x2f\x7a\xbc\x48\xd2\xab\x7b\x38\x80\xa0\x48\xda\xa4\x48\x64\x5a\xd2\xec\xb5\x5b\x3c\xae\xe2\xd6\x8a\x8b\xed\xb5\xd1\x86\x5d\x5e\x21\x1d\xe3\x9b\x0e\xaf\x22\xe5\xda\xf1\x0f\x71\x68\x20\x3a\xa1\x5b\x85\xaa\x47\xbb\xd3\xcc\x41\x69\xcb\xc1\xfe\x80\xb4\x70\x0b\x62\x58\x71\xed\xab\xcd\x4f\xe7\x4a\x3e\x96\x55\x69\xce\x24\x5c\xfc\xde\x42\x09\xcc\x8a\xbc\xd6\x79\x7d\x44\x18\x5b\x4f\x96\xc0\x18\x1b\xbd\x27\x00\x87\x83\xe9\x35\x8a\x53\x94\xfe\x3a\x34\xa0\x68\x71\xd3\x79\xda\x35\xb2\x0b\xb5\x7e\xef\x9e\x55\x24\xee\x79\x12\xa6\xf4\x1b\x4a\x1f\x68\x4c\x39\x19\xcf\xcd\xc0\x0f\x45\x80\xba\xf9\xe0\x9d\x31\x6c\xef\xa0\xf4\x65\xdc\xa5\xd8\xee\xc5\x14\xe9\x5e\x5a\x57\xbb\xcd\x27\xe4\x1f\x81\x19\xb2\x64\xae\x14\xa3\x19\xd8\xc3\x85\x9b\xab\xf1\xf4\xa6\xb6\xb7\x7e\x44\x2c\x86\x1d\x6e\xe2\x8a\xd1\x2b\x82\x36\x2e\x90\xdb\x0c\x36\x72\xb0\xe0\xd9\xff\x58\x14\x6f\xd1\x59\xaa\x8f\xa9\x9d\xc7\x55\xfc\x85\xb9\x0c\xf9\x41\x92\x79\xc0\x62\x4b\x93\xe7\x5e\xda\x0e\xf7\xc0\x96\x95\xae\x93\xbd\x72\x82\x41\x93\x77\xb7\x6c\xa8\xbd\xc0\x52\x1c\xfe\xe6\xf6\xd7\x29\xc3\xad\xff\x89\x46\x87\xb1\x77\xef\x19\x52\x9a\x6b\xda\xce\x70\xb6\x85\xc6\xd7\xa5\xd7\x4a\x08\xe2\xa9\xe7\x24\x03\x59\x75\xc8\x0d\x18\xcb\x36\x94\x70\xde\x72\x99\xcb\xd6\xb0\xa2\x7c\x92\x32\xc7\xea\xba\xc8\x6d\x50\x93\xa6\x5f\xfe\x0b\x40\xd4\x0b\xef\xe8\x0b\x68\xcd\x9d\xce\x1e\xa1\xe6\x57\xe4\x5e\x9c\x49\x9d\x0b\x69\x0f\x74\x45\x5f\xb4\x70\x96\xed\x8c\x18\xd1\x51\x7f\x90\x44\x29\x01\xa6\xc4\x10\xb7\xf6\x41\x5f\x20\xae\x48\xc5\x8a\xde\x8d\x67\x5b\x6c\x05\x8d\xf1\x6a\xe7\x69\x8f\xce\xae\x95\xaa\x77\x1b\x4c\xd8\x8a\x0b\x3f\x22\xc5\x1f\x98\xc7\x1c\x1e\xb4\x6b\x26\x4b\xf9\x7a\x30\x0e\xcb\x1f\xd2\x62\x26\xad\x8e\x87\xa0\x58\xcf\x3e\x70\x8e\x26\x0f\x56\x6b\x68\x53\x14\x04\x51\x33\xf4\xa5\xe8\xfb\xc3\x45\x61\xb9\xa0\xf1\xff\x93\x39\xf5\x52\x31\x07\x6b\x73\x6b\x6e\x11\x52\x43\x19\xa2\x72\xbd\x44\x53\xa0\xaf\x14\x93\xda\xa0\x91\x67\xe8\x46\x43\xd2\x07\xa0\x2f\xee\x98\xfb\x22\x3b\x01\xa9\x9a\xa5\xce\xf2\xb7\x00\x1e\x47\x0f\x6f\x94\xa5\xdc\x20\x8e\xdf\xc0\xcb\x8c\xf3\x11\x4a\x91\x96\x00\xf0\x61\x17\x2f\x0e\xfe\x03\x90\x36\xbf\x4d\xdd\xbf\xd0\xd4\x5f\x91\x44\x3b\xf2\x6f\x8e\x15\xed\x7d\xb8\xe5\x5f\x08\x6a\x4a\x45\x83\xf4\xbd\xa0\xf5\x56\x28\x4d\xcf\x71\x29\x2f\xe7\x0f\xca\xa8\x25\x9b\x9f\xaf\xf3"}, -{{0x10,0xf0,0x09,0xaa,0x88,0x7d,0x91,0xce,0xd8,0x09,0xaf,0xe1,0x92,0xd7,0x8e,0x47,0x99,0xd9,0x03,0x77,0x62,0xf4,0xa9,0xd3,0xa4,0x29,0xfd,0xe0,0xf3,0x9f,0x7b,0x7a,},{0xcf,0x51,0x16,0xb9,0x21,0x21,0x2e,0x9b,0x78,0x82,0x9a,0x02,0x63,0x46,0x36,0x91,0xc6,0xfb,0xcc,0xdc,0x0c,0x11,0x8b,0xe1,0x41,0xc9,0x6f,0x8c,0x88,0x05,0x3d,0xd3,},{0xc3,0x7b,0xb7,0xb7,0x3b,0x11,0x05,0xbe,0x08,0x6f,0xf3,0x07,0x69,0x72,0x07,0x72,0x62,0xdf,0x4d,0x73,0x32,0xf6,0x08,0xc7,0xb2,0xb9,0xd9,0x78,0xd4,0x74,0xcb,0xbc,0x27,0x10,0x46,0x08,0x00,0x35,0xf3,0x96,0xee,0x36,0x47,0x9b,0x7a,0x67,0x11,0xc6,0x8e,0x25,0x61,0xc7,0x41,0xc0,0xec,0x5f,0xc9,0xec,0xa1,0x73,0x4e,0x81,0x1f,0x04,},"\x2e\xdf\x14\xd6\xcd\x56\x89\x6e\xea\xa7\x70\x21\x1c\x49\x84\xbe\xd8\x0e\xca\x8d\x65\x34\xd5\xd5\x10\x88\x4f\x55\xf1\x1f\x99\xff\xa9\xf8\x9b\x58\x6f\xfe\x7b\x1e\xc7\xea\xab\x6a\x9d\xc1\xa2\x4a\x3e\xe3\xc7\xa6\xab\x44\xad\xe9\x91\x78\x83\x26\x4e\xde\x2f\x13\x61\xbe\x7d\x7a\x38\x17\xf2\x9d\xec\x95\x81\xc3\x19\xf1\x8f\x95\xd5\xbe\x26\xd9\x11\x8b\xe6\x78\x34\x00\x37\xa6\x8a\xbf\xc5\xef\xbb\x9a\x3f\x3f\x38\x78\xaa\xe3\x72\x1f\xfe\xf5\xbb\x6a\x26\xc7\xb1\xa3\xa5\x6d\x2b\xda\x6c\x6e\x86\x0e\xb4\x1f\xd8\xd8\x37\x11\x74\xd9\x1c\x74\xc5\xeb\x67\xc3\x85\x5c\x63\x0d\x64\x1d\x2e\x57\x1a\x9a\x51\xc6\x40\x2c\xfe\x18\x42\xce\xf3\x89\x80\xcb\x8d\x0a\x64\xbc\xc8\x9b\xe3\x18\x9e\x68\x11\xf4\x7e\x8f\x4d\x00\x63\xa5\xb1\x60\x1f\x44\xfd\xa2\x0c\x1c\x4c\x2f\xc4\x9c\xbe\x27\xa4\x13\x7d\xc4\x63\x8c\x2a\xd2\xd0\xa5\x47\x47\x47\x22\x9c\x56\x8e\x38\x05\x43\x1f\xa3\x6e\xeb\xa7\x85\xf7\xb9\x78\x44\xb5\xe3\x19\xfa\x6a\x09\xcc\x5a\xe8\x40\x34\x74\xbb\x91\xdd\x89\x6c\x1e\xc2\xba\xc7\x3d\x2e\x50\x5e\xfc\x62\xbd\x50\x2b\x5c\xeb\x08\xd1\x6e\x83\x2e\xc5\xdc\x4f\x98\xb5\x1b\x9d\x07\x38\xb9\xfb\x28\xf3\xab\xe8\x96\x6b\xf2\x23\x75\xa0\xb2\x2c\x47\x1a\x9e\x58\xe3\xfd\x70\x0d\xe1\x5c\x52\x96\x37\x3c\x1b\xc9\xd4\x64\x0e\xb7\x81\x6e\x1d\xc9\xc8\xce\x86\x19\xa8\x11\x83\x00\x9e\xc9\x74\x87\x1e\x8f\x0a\x97\x72\xed\xe0\xa6\x38\xb3\x57\x4b\xf7\x5d\x8f\x55\x98\x7f\x3c\xfa\x6f\xec\x68\x97\x0b\xfe\x00\xb2\x3b\x59\xfb\x5b\xf4\x99\x6e\xa5\xd7\x70\x4f\xcf\x2e\xff\xcc\x0f\xd7\xf3\xd8\xe6\x05\x60\x08\x09\x7f\x26\xca\xff\xd5\x41\x5a\x28\x2a\x27\x6a\x9b\x26\x45\xe5\xca\xb1\x29\x68\x87\x2e\xb0\x52\xf4\xd7\xc1\x0c\xc7\xc2\x1d\x51\x61\x81\x8b\xb4\x4c\xc8\x56\xb0\xde\x76\x9d\x55\x9c\x55\xdf\x64\xad\x9a\xdc\x16\xc0\xac\x65\x83\x8f\x66\x0d\xa8\x13\x86\xb7\x0b\x93\x52\x5e\xc2\xf4\x0f\x6f\x63\xf8\xea\x5d\x48\x30\xb9\x64\x6c\x46\x18\x3b\xb4\xe6\xf2\x70\x47\xbd\xa2\xa5\x46\xbd\x34\xbd\x4d\xb5\xfb\x88\xfd\x8a\xb7\xc7\x5f\x65\x2e\x15\xd5\xaa\xa6\xb4\x6a\x8a\xcf\x6e\x44\x8b\xf2\xdd\x64\xde\xe3\xc1\x05\x64\x7c\x7f\x83\xad\x20\x0d\x80\x97\xc4\x44\xa1\x58\xd8\x5a\x54\xf0\xe5\xdb\xb1\x2b\x43\xde\x94\x3a\xf1\xa8\x18\x56\xac\x96\x9f\x52\xa0\xbd\x45\x43\x81\xbd\x26\x50\x41\xa2\x69\x1d\x1a\x4a\x0d\x81\x9f\xa7\x90\x92\xc8\x80\x35\x21\xfa\x53\x68\x9a\xb8\x52\xf1\xfb\xab\xe0\x0c\x94\xb7\xf6\x82\xd1\x21\xcf\xf5\x43\x91\x32\x25\x29\xc8\xd5\xad\x7b\xbb\x98\xea\xfe\x30\x0a\xb9\x22\xf1\xc8\x92\x40\xa1\xe6\x33\xcf\x56\xa7\xb0\x2f\x74\xa2\x92\x14\xe5\x69\xa0\x57\xbd\x58\x5e\x40\x4d\x7c\xd5\x35\x20\x41\x45\x6e\x6c\xf9\x0c\x15\x34\x2e\x02\x56\x70\xf4\xfc\xcd\xf9\x87\x83\xb6\x85\x32\x14\xca\xc3\xfa\x80\x8a\x66\xc2\x7b\x65\x3c"}, -{{0x45,0x78,0xc6,0x5a,0x7c,0xa4,0x8f,0x27,0x74,0x05,0x0a,0x7b,0x0c,0xe7,0xa4,0xfd,0x5a,0xd4,0xe6,0x96,0xb2,0xb8,0xaf,0x23,0x96,0x16,0x4a,0x1c,0x7e,0x1b,0x7b,0xd7,},{0x15,0xbf,0x9d,0xbd,0x3b,0x81,0x73,0xe6,0xf0,0x3d,0xcf,0xd5,0x75,0xd9,0x09,0x84,0x5f,0x03,0x8e,0xaa,0x09,0xc5,0xd9,0x08,0xfe,0xf9,0x08,0xa9,0x74,0x58,0xb3,0xef,},{0xa1,0xc2,0x42,0xb4,0x5e,0x94,0xfd,0x18,0x0f,0x05,0x4c,0x71,0x01,0xe5,0x5b,0x39,0x65,0x68,0xf4,0x83,0xdb,0x6f,0x0d,0xfc,0x41,0x68,0xb6,0x9b,0x59,0xd3,0x85,0x81,0x4c,0x19,0xeb,0x30,0x75,0x23,0x7d,0x1f,0xbb,0x1f,0xee,0xbb,0xfe,0xa5,0x0c,0x56,0x81,0x3c,0x8c,0x39,0xc2,0x27,0x52,0xe0,0x2d,0xb7,0xe5,0x7f,0x3e,0x3f,0xbf,0x0d,},"\x50\x6f\x32\xb9\x68\x14\x24\x3e\x4d\xd8\x87\x0a\x8f\xd6\x0d\xde\xf0\x9b\xb8\xc5\x63\x15\x10\x70\xd9\xbc\xb2\xb1\x60\xa3\xea\xbd\x71\xa0\x44\xd7\x1e\xc9\x3f\xba\x95\x28\x8e\xd6\xfe\x1a\x7b\x92\x16\x51\x60\x43\x07\xd6\x5a\x45\xec\x5d\x3f\x26\x31\xac\xe4\x0e\x58\xd5\x3c\x72\xe5\x26\x88\x6e\x16\x97\x2f\x6e\x0d\xb9\x4d\x57\xb5\x56\x34\xfd\x39\xd5\x5e\x9b\xb7\xf2\x12\xaf\xab\x00\xf7\x74\x64\x09\x26\x7e\x8d\x56\x5f\xf5\xc2\x25\x73\x33\xc3\xd0\x41\x52\x17\x4f\xe1\x2d\xe6\xa5\x7b\xea\x05\x7d\xc2\x19\xe2\xfb\xa5\xf1\x91\xed\x81\x41\xc0\x18\x96\x9d\xe1\x94\x72\xd6\xaa\xf7\x63\xf1\x9e\xc5\x54\x70\x2b\xb3\xdc\xbe\x13\xca\x9b\x23\xb2\x41\x8c\x99\xe7\x18\x38\xa8\x8c\xf4\x54\x72\x8c\xf9\x20\x8a\x16\xc8\x4e\xa3\x98\x29\xb4\xba\x9b\x4c\x77\xe1\x76\x11\x2b\xfe\x1b\xf3\x5f\x95\xc4\x02\x8c\x7d\xb8\x0b\x36\xfa\xa2\x9d\x2b\x89\xe9\xe8\x62\xf3\x10\x00\x06\x5f\x13\x9b\x3d\xa7\x7d\x9d\x86\x85\x30\x57\x4b\x7e\x39\x1e\xd9\x7b\x34\xf8\x78\x16\x4f\x6b\x8d\x87\xb4\x06\xc7\xdc\x78\x60\xa5\x17\x5f\x92\x0e\x5a\x62\xdc\x1f\xc8\x2e\xd8\x45\x25\x43\xb1\x07\x36\x0d\x35\xd2\xb4\xc4\x23\x9e\xab\x46\x6d\x32\xbf\xda\x34\xf5\x10\x37\xa6\xfa\xe7\x6f\x6d\x8b\x83\xe8\xf7\xf4\x89\xdd\x4c\x1b\x49\xc3\x8f\x53\x57\x6e\x62\x17\x2c\x17\xde\xe3\x66\x5f\xde\x8c\xbf\x01\x5a\xf9\x66\x5b\x0f\x1d\xa2\xfb\x77\xb1\x34\xf0\x4b\xe2\x71\xe4\x02\xf3\x15\x37\xc2\xfc\x05\xc2\xf9\xb6\xfc\x3f\xfe\x47\xde\x33\x69\x13\x38\x67\xc6\x9d\x10\xe7\xf5\x37\xba\xe4\x56\x7d\x46\x8e\x0f\x2e\xd8\x06\xfe\x33\x5f\x93\x9c\x75\x99\x4f\x36\x3c\xe3\xb7\x0d\xaa\x7d\x5b\xd2\x31\x7c\x83\x38\x51\xfd\x8c\xc9\x72\x51\xec\x41\x90\x23\xd9\xd0\x17\x4d\x84\xd5\x60\x9a\x69\x18\xa1\x74\x0e\xb1\xe3\x09\xbd\x12\x73\x66\xde\xb9\xc5\xab\x12\x99\x2e\x99\x02\xe0\x15\xfe\x58\xd6\xad\xbf\x52\xd2\x2a\x76\x0a\xcd\x63\xe1\xed\xd8\xf1\x38\xe9\xfb\x01\x37\x18\x86\x01\xe1\x97\x8e\x7d\x04\xfb\x2a\xda\x2b\x2a\xee\x12\xf4\x9f\x28\x36\xc6\x84\x2d\x88\xcf\x48\xc8\x66\xe3\xd3\x3f\xcd\x26\x9c\x27\x5c\x89\xc2\x5e\x36\x69\xca\x90\xde\x7b\x67\xa7\xe7\xa3\x82\xcb\x7e\xfa\x47\xe9\xc2\xbf\x76\x57\x1c\x79\xa2\x50\x85\xef\x02\x04\x87\x15\x2f\x06\xbf\xa1\x33\x01\x5a\x1b\x8f\x1c\x0f\x6a\x9f\x0e\xae\x1b\xa6\x2b\xf1\x04\xf1\xc1\x6a\xc1\x4e\x1e\x96\xc4\xeb\xdf\x06\x1e\x0c\xc7\x10\x1d\x38\xda\x7e\x9e\x09\x94\xda\xf0\xf3\x22\xaa\x3c\xfe\xf9\x1b\x61\x6c\x2d\x00\x06\x89\xab\x18\xed\x45\x26\x8d\xcd\x27\x50\x94\xf6\x56\xba\x3c\xf5\x15\x26\x10\x24\x74\x1f\x74\x44\xab\x7f\xc4\xde\xcc\xe1\x67\x56\x03\x2a\x1b\xe2\x70\xff\x0b\x03\x17\x54\x2b\xa0\x26\x62\x26\x0a\x37\x6f\xc9\x12\xcb\xb0\x29\xca\xc5\x45\x15\xf5\xa5\x51\x36\x4f\x6a\x99\xff\xad\x0b\x9c\xbc\xd0\xe6\x93\xb7\xa5\x21\xcb"}, -{{0xc2,0x1e,0x70,0xc4,0x6e,0xde,0x66,0xe6,0x8a,0x88,0x73,0xbb,0xc6,0x4b,0xa5,0x12,0x09,0x30,0x3a,0x0a,0xc4,0xfc,0x49,0xb1,0xd8,0x3e,0x81,0x93,0xad,0x46,0xc0,0x37,},{0x9f,0xbf,0x80,0xa4,0x25,0x05,0xd2,0xc9,0x52,0xf8,0x9f,0x45,0x58,0xc3,0xe6,0xd1,0x87,0xa7,0xbc,0x1e,0xf4,0x46,0xb2,0xe3,0x73,0x23,0x43,0xc1,0x3b,0x33,0xd2,0x00,},{0x0a,0xe3,0x43,0xbb,0x84,0xe3,0xa2,0x99,0x07,0x8e,0x24,0x34,0xba,0x22,0x00,0x22,0xf3,0x16,0x0f,0x96,0x8a,0xc0,0x44,0x82,0xbf,0x8c,0xad,0x13,0xb4,0x23,0xf2,0x67,0x0f,0x01,0xfb,0x5f,0x7b,0x32,0xc5,0x97,0x52,0x0f,0x84,0x60,0x7e,0x0f,0x79,0xc0,0x75,0xfa,0x70,0x78,0xe6,0xe6,0x9d,0x3c,0xec,0x31,0x92,0x65,0xd4,0x66,0x08,0x0b,},"\xf5\x5a\xa5\x70\xce\x4f\xc9\x5f\x73\xf5\x17\x20\xd2\x54\xe4\x69\x5f\xcd\xc8\x1a\xaa\x04\x01\x30\xc7\x68\x7f\x03\x9b\x8b\xa5\x9e\xd8\x57\xce\xb2\x9c\x12\x10\x25\xa8\x57\xfe\xac\xb4\xa0\x1f\x38\xe0\x11\x78\x31\x0a\xe6\xe3\x5c\x99\x8e\xbf\x89\xdd\x79\x05\x7b\x4a\xfc\x6d\xb3\x40\x60\x1c\x81\x70\x3c\x87\xa8\xc4\x0e\x5c\xeb\xb0\x44\x1d\xf7\x8a\x6d\xe1\x3a\x44\x7c\xb0\x16\xc6\x5e\x74\x1b\xb7\xdf\x30\x4d\x83\x05\x6b\x72\xc6\x82\xc7\x31\xfa\xc0\xa0\xc7\x0b\x78\x11\xca\x14\xa5\x01\x54\x61\x30\x99\xc2\xc4\x37\x52\x1c\x40\x4b\x63\x61\xde\x36\x21\xf8\xea\x56\xb0\x8e\xbf\xdb\x07\xb4\xf2\xbb\x8b\xa2\xec\xc1\x64\x33\x6d\xa8\xef\xc9\x42\x76\x6e\xf0\xc7\x4d\xfd\x3b\x49\xe0\x87\xe9\xa2\x7a\xe5\x4a\x7a\x2b\x98\x28\x1b\x9a\xf9\x3d\xc1\x1a\xa2\xf0\x92\x24\xab\x5a\x73\x0f\x02\x18\xf4\xa6\xe1\xea\x48\x85\xa7\x7f\xbd\x93\xa1\xc5\x82\x77\xd9\xe0\x1b\xe7\x3a\x25\xcd\xa9\x18\xfc\x27\xdd\xdb\x45\x3a\x5d\xa6\x90\x2a\xd0\x2b\xa0\x57\x75\xc6\x7e\x07\xbe\xa4\xdf\x86\x91\x34\x66\x74\x43\x65\xc1\x32\x6e\x0a\xb5\xe1\x25\x4c\x17\x96\x74\x47\xd5\x91\xba\x5e\xd1\xb6\x3a\x42\x54\x3b\x87\xfe\xd4\x14\x59\xa0\x89\xbc\xea\xff\x21\x98\x02\xa8\x7a\x87\x2a\x76\x3e\x69\x23\x33\xce\x1c\xc7\x39\x78\x25\x08\x4b\x2b\x83\x1e\x93\xd8\x0d\x67\x37\xf3\x29\x80\xf2\xf3\xae\x82\xc6\x21\x90\xfe\x3f\xa7\x00\xc5\xb7\x32\x9d\x6d\x50\x04\x2b\xdf\x83\x1f\x37\x54\x8f\xcc\x80\xb1\x1f\x57\xcf\x20\xf6\x7a\x3b\xb6\x51\xa7\xbe\xff\xcc\x48\xb7\x0d\x17\xeb\x60\xf7\x25\x9c\xc5\x3b\xf7\xff\x60\x80\xeb\x2b\xd0\x92\x3b\x04\x83\xaa\x30\x65\xa8\x95\x5f\x01\xd2\x3b\xa8\x09\x51\xe0\xae\xfd\x2a\x93\x72\x19\x15\x72\xbc\x52\x91\x6a\xa2\x2a\x2a\xec\x39\x37\x67\xfa\xfd\x08\x68\x39\xe2\x36\xfe\x04\x60\xce\x6d\x63\x9c\x7c\xe6\x9f\xe7\xf9\xd3\xaa\xd2\x13\x05\x73\x44\x35\x70\x44\x3b\xe6\xba\xb9\x3a\x06\xa5\x4b\x8a\xc2\x9b\xf3\x3f\xf9\x94\x9b\xc9\x21\x58\xe6\x92\x4b\x6b\x68\xec\xda\x5f\x6f\x3a\xaf\x42\xb3\xd2\x2d\xf6\xd5\xe6\x7d\x5c\xb3\xab\x71\xeb\x8e\xe0\xb0\xe6\x67\x32\xe1\xda\xca\x6c\xd6\x0d\x9a\xa7\x43\x05\xfc\xd5\x70\x07\x6d\x22\x8d\x44\x6d\x5e\xe5\x42\xb1\x04\x88\xbf\x8a\xa9\x88\xf4\x51\xfa\xeb\xe7\x4a\xb6\x69\xd6\x04\xd9\xdd\xb1\x51\x06\x62\x0e\xa0\x2e\x8d\xb3\x8c\xe6\x39\xb5\x74\x78\x12\xbb\x90\x48\xee\x8b\xf7\x2b\x1a\x95\x1a\x05\xdf\xfa\xc9\x54\x17\xcb\x43\xb0\x6d\xce\x61\xee\x3d\xa6\xf2\x83\x2e\xe8\x3b\x2e\x72\x88\xdd\xd6\x2e\xeb\x58\x93\xf7\xf2\xf6\xc8\x09\x0d\x99\xe3\x36\xc9\xf9\x06\x9e\x18\x15\x98\x58\x41\xbd\xd5\x05\xb5\xf8\x3d\x89\x5e\x87\x95\x93\xda\xde\xe7\x2c\xeb\x97\x65\x69\x9b\xf8\x0b\xd0\x6a\x5c\x55\x33\x1b\x25\x45\x52\x7d\x0c\x7c\xae\xce\x96\x58\x4c\xe3\xec\x7f\xe0\x22\x60\xf2\x0b\x8a\x1c\x06\x35\x76\x3f\xf4"}, -{{0xf2,0xc1,0x05,0x77,0xf7,0xdf,0x77,0xf0,0xc1,0x15,0x7a,0x8c,0x33,0x1a,0x7b,0xd2,0xae,0x63,0x86,0x67,0x0e,0xb6,0x5f,0x0f,0xae,0x12,0x23,0x31,0x69,0x0f,0x82,0x8a,},{0x0d,0x4c,0x34,0x0f,0xc2,0x31,0xaa,0xfb,0x3b,0x6f,0x74,0xb8,0x9b,0xce,0xf7,0xee,0xaa,0x0b,0x04,0xf2,0x93,0xec,0x85,0x44,0x24,0x7b,0xfc,0x3f,0x2d,0x57,0xc1,0xe0,},{0x60,0xb7,0x03,0x11,0x5a,0x32,0x2a,0xb8,0x92,0xc2,0x76,0xbf,0xd1,0x8f,0x70,0xa9,0xeb,0x0c,0x73,0x23,0xe2,0xc0,0xa6,0xeb,0x5f,0xc7,0xe3,0x30,0xb0,0xbc,0x3b,0x07,0xa5,0x78,0xa0,0x82,0x84,0x62,0x64,0xf0,0x32,0xc6,0x19,0x1d,0x04,0x0b,0xd9,0x8e,0x5d,0x5a,0x4d,0x4f,0x07,0x6f,0xb9,0x06,0x2a,0xcd,0x36,0xbe,0xa4,0x0c,0x91,0x02,},"\x38\xea\x1e\x02\x8a\x49\x3d\x1c\x60\xec\x70\x74\x9f\x14\xd4\x36\xeb\x3a\x2b\x2d\xe5\x4f\x21\x3d\x01\xa6\x45\xb5\x80\x43\x0e\xcd\x8e\xce\x6b\x55\x69\xcc\x01\x7a\x49\x43\xe5\x59\x5c\x5e\xd6\xe4\x8c\x94\x43\xf2\xfa\x5e\xb2\x22\x7f\xfe\x56\xd2\x11\xf2\x69\xbc\x8f\x6f\xa9\xee\x8c\xd5\x6f\x6b\x84\x70\x53\x92\x08\xaf\xe2\x9a\xb0\xa1\x95\x04\x4d\x95\x7b\x31\xf9\x3e\x18\x4a\x9c\xbe\xf1\xa1\x4e\x14\xf8\x08\xbb\xf5\x89\xac\x77\x70\x08\x4f\x99\x8e\x1b\x25\x4d\xa5\x9c\xa6\xd3\xe6\x2e\x7b\xe1\x79\x07\x16\xd2\x56\x0f\x01\x5f\x39\x9c\xbb\xce\x48\xcf\xd0\x39\x1e\xad\x19\x93\x44\x6f\x6b\x24\x93\x97\x7d\x93\xd7\xb0\x9a\x07\xa7\x9a\x59\xce\x15\xdc\xe7\xa1\xda\x9c\x64\x6f\x45\xaf\x2c\xca\xd5\x5b\xa1\x58\xe6\x38\xc4\xa3\x0c\x5d\x30\xe9\xac\x6e\x3a\x33\x39\xc2\x43\x42\x6d\x86\x49\x1b\x2d\x92\xda\xc1\x47\x8e\x8d\x74\xff\x0b\xf1\x49\xbd\xb5\xe0\x9e\x3f\xb6\xb8\x26\x2e\xb0\x68\x79\x81\x55\x4a\xe2\xcb\x47\x19\x63\x39\x07\x9d\xa0\xa1\xa5\x72\x39\xc1\x9b\xf7\x81\xf6\x2f\xda\xf4\xe3\x15\x60\xa8\x43\x17\xef\x03\x04\x92\xcf\x1b\xb1\x30\x5b\xa8\x51\x8e\xba\xf2\xb4\x34\xd3\x64\x16\x72\xc8\xf6\xea\x2d\xef\xa6\x96\xdc\x7e\x4f\x39\xef\xc0\x8d\x28\x8d\x1c\x96\x6a\x6c\x71\x48\xc0\x12\xee\xc4\x39\xf7\xe1\x2d\xba\xb5\xb8\x7c\xfa\x44\xc9\xae\x19\x00\xf8\x38\x6f\x24\x44\x4e\x10\x92\xb2\x3a\x27\x4c\x13\x8e\x95\xc6\x61\xe9\x37\x7e\x8a\xd2\xd1\xfc\xaf\x19\x39\xec\x9a\x63\x2a\x87\x3f\x7e\xad\xbe\x68\x7b\x4a\x03\x3b\x92\xa4\x77\xf2\xe0\x2e\x9e\xd9\x2c\xe4\xf9\x5c\xf1\x70\xb3\x90\x15\x18\xa0\x62\x14\x3e\x56\xdb\x05\x4d\xf4\xe4\x43\x15\x44\x78\x5a\x6d\xfa\x24\xee\xc0\xf0\xde\x7a\x69\x9c\xcf\x28\x6d\xad\xfa\xd8\x59\x03\x61\x22\x50\x76\x4f\x25\xcd\xea\x81\x27\xd0\x07\x8d\x55\x48\x25\xea\x6e\x73\x71\xc4\x38\xbc\x46\xf2\x9f\xb8\x93\x7f\x8d\x9a\x39\xcf\x88\x49\x05\x2d\x43\xec\xbf\xf6\xc4\xa3\x76\x2a\x5f\x40\x0c\x15\x14\xe8\x5e\x91\x38\x4f\xef\x9b\x40\xf4\x31\x4e\x22\x3a\x9d\x68\xc5\x26\xac\xc7\x02\x27\xd6\x2b\x8b\x63\x7a\x34\x2d\xf1\x13\xd3\x18\x20\x2c\x51\xed\xd3\xc1\xef\xd1\xff\x20\xb1\xff\x07\x8b\x32\x06\x8e\x79\x4d\x92\x81\x33\x03\x7f\x1e\x3a\x34\x68\x9e\x62\x9e\x43\xfd\x2b\x8e\x88\xea\xb5\x0d\x7e\x7a\xb0\x64\x70\x14\xab\x5e\x4a\xd5\x82\x00\x65\x67\xef\xf7\x2b\x5a\xf2\xda\xc5\x36\x89\x2c\xcc\x87\x1f\x8a\x80\xb5\xcb\x79\xd9\x0b\xcc\x6b\x77\xd4\xcd\x08\xf8\x76\x18\x4e\xf5\x8c\x06\x4a\xe4\x30\xbb\x79\xa6\xb9\xe9\x6b\x0a\xd8\x73\x68\xaa\x83\x8a\x8d\xcc\xff\xac\x0c\xd8\xce\x9e\xa0\xd0\xec\x4c\x4b\x0f\x42\x67\x34\x16\x65\x9c\x98\x49\x92\xcf\x53\xb1\xe4\x45\x43\x10\x07\x64\x0d\x47\xec\xe2\x6d\xee\x4a\x29\x43\xaa\x70\x97\xdd\x35\x6c\xff\x47\x54\xf2\x1a\xc0\x7f\x6b\x3f\x73\xc4\x69\x05\x55\x12\xf3\x7a\xba"}, -{{0x04,0x1a,0x97,0x90,0x6b,0x59,0x56,0xb9,0xd3,0x40,0xf2,0xe0,0xd7,0xa1,0xdc,0xbf,0xef,0xe6,0x63,0xe9,0xbb,0x40,0x26,0xf8,0xcc,0x1a,0xe7,0xe2,0xa1,0x4d,0xe2,0x7e,},{0xf3,0x82,0xd3,0x2e,0x88,0xc3,0xa7,0x2c,0x7c,0xad,0xda,0xfc,0xf8,0xaa,0x69,0x9e,0x21,0xdb,0x7a,0x6b,0xf4,0xed,0xd6,0xe4,0x9a,0x00,0x5a,0xad,0x70,0x2e,0x6a,0x79,},{0xa2,0x3f,0x03,0x2e,0x66,0x92,0xa0,0xe8,0xbf,0xee,0x5b,0x2d,0x30,0xb4,0x14,0xcb,0x16,0xc3,0x5a,0xd0,0x8d,0xa3,0x1f,0x69,0x6d,0x46,0x1a,0x02,0x85,0x78,0x22,0xc4,0xef,0x35,0x7f,0x0c,0xcf,0x31,0x02,0x5a,0x4d,0xc9,0x5c,0xed,0x30,0xa9,0x94,0xf4,0x1e,0xdd,0x1d,0x08,0x7a,0xfc,0xaa,0xf3,0xe8,0xe8,0x75,0x70,0x83,0x20,0xf8,0x0c,},"\x71\xa7\x59\x57\x41\x15\x44\x97\x5a\x48\xcf\x10\x3a\xa1\xf8\xe2\xad\x15\x24\x44\x59\xcd\xc0\xe3\x36\x96\x6e\xb8\xb2\x6c\x97\xf2\x16\x9e\x5d\x78\x53\x70\x37\xef\xc0\x77\xe8\x6f\x06\xe0\x5e\x9c\x1d\xc3\x41\x82\x88\xc0\xa2\xbe\x6b\xa3\x4b\x3a\x04\xab\x20\xba\xe7\xf3\x62\x10\x94\xb8\x7d\x78\xa7\xea\xcb\x86\x4d\x40\x78\xcb\x4e\xfc\xba\xc5\xad\xd9\x37\xa2\xc6\x01\x2e\xe1\xa8\xb2\x56\xcc\x27\x6b\x65\xd5\xe9\x2b\x4d\x00\xb9\xb1\x1f\xad\x88\x49\x91\xde\xc4\xc1\xcb\x9d\xce\x18\x63\xc8\xb0\xa2\x10\x16\x1a\xe6\xb3\xf8\xbf\x9c\xc4\xdc\xe4\xad\xfd\xc8\xed\x57\xd8\x3e\x95\xab\x9d\xd2\xd9\x26\x58\xdf\xbd\x3a\xfa\x99\xe3\xf8\x95\x1e\x2a\xd7\x4a\x14\x8f\x6f\x59\x7e\xb2\xc9\x45\xc1\xf1\xb9\x44\x61\xae\x07\x45\x48\x1f\xd0\xed\xf8\x38\xc6\x28\x60\x35\xe3\x6f\x01\x12\x38\x87\x5d\xbb\xa2\x28\x9d\x3d\x6a\x39\x42\xa7\xf9\x55\x4c\x64\x43\x05\x24\x4d\xdb\x77\xc1\x17\xcb\x4b\x56\x23\x77\x29\xdd\xe4\x28\xb8\xbb\x42\xdf\x9c\xe2\x9e\x14\x4d\xfc\x96\xcf\x6c\x67\x67\xb1\xee\x6d\x05\x3c\xe4\xf8\xbb\x20\x56\xab\x78\x10\xaa\x13\x68\xa8\x91\x0f\x2f\x69\xe0\x61\xc1\x9d\x88\x47\x18\x4f\xed\x53\x4f\x98\x75\x8d\x70\x3a\x76\x88\x5f\x91\xeb\x75\x2a\x21\x95\x4a\x10\xc6\xf6\xb4\xda\x10\x46\x4d\xed\x36\xb0\x00\x89\xf6\x62\x91\x54\x21\xbf\xda\xd4\x96\x75\x36\x89\xcc\xd0\x3b\x62\x40\x21\x08\x07\x61\xe6\x81\x76\xb1\x06\x97\xda\xc8\x78\xe4\xc3\xdb\x2f\xd0\xb2\x8c\x65\x53\x35\xd9\x80\x16\xf1\x9f\x26\x5b\xb0\xb2\x43\x4c\xb4\x63\x78\x44\xd9\x1e\xd0\xce\x05\xed\x25\x91\xfd\x99\x89\x65\xf8\x3f\x31\x97\xd1\x0e\xef\x44\x88\x50\xe7\x92\x03\x27\x24\x70\x1d\xa3\x05\xcb\x6d\x79\x46\x69\x48\x3f\xc3\xdc\x6f\x68\x6b\x18\x3e\x29\x99\x13\x0c\x8f\xc0\x05\x8d\xca\xbb\xc9\x18\x8f\x26\xb2\xd6\x3e\xbd\x6c\xb1\xe1\x8a\x09\x7c\x77\x04\xa5\x9b\x5e\x18\x7e\x01\x42\x59\x3b\x70\x83\xf7\x40\x0a\xfa\x9b\x1b\xf0\xc1\xcc\x6c\x35\x6b\xc4\x33\x4a\xf7\x72\xe6\x71\x53\xb4\x5b\x33\x1b\x99\x09\x20\xc2\x4e\xed\xe2\xc6\xe3\x23\x70\x3f\x52\xec\xd6\x07\x35\xb2\x3b\xf2\x2b\x81\xee\x77\x59\x27\xc3\x7e\x53\xda\xd7\x59\x6e\xa6\x5a\x73\xbb\x96\x77\x5f\x3b\x87\xc8\xb3\xc0\x88\xec\x69\x5b\xc3\xa7\x50\x2c\x0c\x51\x0f\x02\x0b\xf9\xac\xa3\xcb\xb7\xa2\xc0\x11\xc6\x7f\xf2\x7d\x63\x4c\xaf\x1d\xcf\xc5\x8e\x5e\x39\x7e\x66\x58\x25\x22\x72\x01\x1c\x8f\xfd\xd6\x42\x30\xa9\x32\x41\xff\xf6\x83\x72\xc4\xba\x85\x38\x2b\xbb\x22\x93\x09\x65\x29\x22\xdb\x68\x83\x66\x31\xe5\x5b\xe6\x9a\xb6\xad\xb8\xe4\x33\x53\x57\xfc\x92\x3e\xfe\x15\x4a\xfc\xc2\x22\xd6\x0d\x07\xf5\x69\x90\xa3\xe5\xa2\x14\xb2\x27\xae\xcf\xf2\xcd\x1b\xb6\xf0\xc7\x9f\xf5\x45\xf7\x0a\x61\x61\x41\xa9\xd5\x3f\x92\x2a\x02\x44\x3f\x7d\x2a\x46\x89\xc3\x5b\x09\x5d\xd3\x94\xd5\x0b\xf4\x9f\x96\x80\xa5\xf7\xd9"}, -{{0x4b,0xc5,0xe0,0x5a,0xa0,0x03,0xa4,0x49,0x2f,0x4b,0xad,0x10,0x2a,0x53,0x90,0xf7,0xce,0xba,0xb3,0xd3,0xec,0xa9,0x15,0x21,0x42,0xad,0x5e,0xf7,0xd8,0x40,0x30,0xae,},{0x67,0x51,0xd3,0xad,0x8b,0xb6,0xc6,0x4d,0x6a,0x17,0xd7,0xe4,0x47,0xa2,0x7d,0xa2,0x2f,0x5f,0x04,0x03,0xf4,0x37,0xba,0xc9,0x44,0x9f,0x13,0xcc,0x85,0x3d,0xd8,0x40,},{0xa2,0x4f,0xee,0x11,0xf7,0xec,0x6d,0xa3,0xe9,0xdf,0xaf,0x6c,0x85,0x8a,0xc0,0x04,0xb4,0x53,0x1a,0xbd,0x1c,0x9d,0x3b,0xb6,0x4f,0x40,0xdd,0x24,0x7f,0x00,0x35,0x93,0x50,0xe4,0x3b,0x2d,0x4b,0x8f,0xbe,0xc5,0xf6,0xb2,0x41,0xec,0xf9,0xf1,0x10,0x14,0x85,0xcf,0x41,0x87,0x35,0xb0,0x5f,0x71,0x20,0x18,0x33,0x5b,0x20,0x06,0x83,0x08,},"\xa8\xf7\x94\xdb\x17\x95\x66\x7d\x28\xd2\x4b\x70\xac\x22\x00\xa6\x23\x9a\x34\xe2\x43\x8c\xed\x1d\x03\xf9\x7e\xd4\x8b\xeb\x4d\x6b\xea\x67\xc1\x43\x38\xf7\x73\x64\x19\xdc\xd2\xa2\xa7\x97\x37\x26\x57\x2e\x6a\xfe\x7e\xdf\xef\x22\xc9\x9b\xe8\xb0\x69\xf0\x4f\x6d\xc6\x1a\x13\xb3\x43\xc6\xe5\x85\xab\xad\x22\x14\xd8\x5c\x36\xf0\x29\x96\xfa\xbb\x46\xbb\x91\xb5\x17\x6a\xc7\x08\xe4\x9a\x0b\x05\x30\x17\x04\x8f\xbb\x55\x45\x3f\x2b\x82\x08\xd6\x67\x8d\x1a\x8c\xf6\xa1\xee\x9a\xd7\xa9\x1e\x38\x03\x25\x63\x5d\x1e\x23\x6a\x6c\xa1\xd6\xcc\x7f\x6b\x59\xf2\xa2\xbf\x18\x4f\x5e\xe4\x51\xd6\x79\x9f\x69\xba\x11\xa0\xcd\x6b\xc0\x4b\xe8\xa3\x51\xa8\x0e\x72\x5b\x5f\xc4\x56\x3e\x45\xbd\x47\x49\xec\xbc\x45\x20\x52\x29\x10\x5b\x9d\xe7\x32\x61\x49\x85\x27\xf3\xd4\xec\xfb\xb5\x83\xff\x53\x27\x53\xd0\x7c\x38\x52\x6b\xb4\x82\xd1\x71\xa2\x61\xb9\xcf\x89\x90\x6a\x7d\xea\x8c\xbd\x7e\x72\x6b\xa3\x1e\xa6\x88\x03\xa6\xb0\x04\xf6\xdc\xd1\x9e\x67\x19\x50\x46\x37\x38\xcc\xa7\x8b\xb0\xdf\xfa\x3d\x64\x57\xe4\xae\xca\x65\x7e\xc6\x49\xb9\x7e\xe3\x0e\x97\xc8\xcb\xe6\xce\x43\xc2\xaa\x9a\x69\x95\x8e\x9d\xc8\x81\xe4\xaa\x7b\x32\x78\x07\x4e\x78\x7a\xce\x5f\xb6\x01\xd7\xfa\xf7\xca\x51\x03\xec\xbb\xd3\xbd\x55\x4e\xb1\xb0\x66\xf8\x29\x6d\x2c\xc5\x7e\x8c\x8a\x32\xe9\xc0\xe6\xa9\x26\x96\x4d\x6d\xf2\xd8\x64\x58\x64\xb3\x22\xc3\x22\xf1\xca\x80\x73\xce\xdf\x2b\x55\x67\x11\xa7\xa2\x0b\x77\xc0\xa1\xed\x27\x7a\x9a\x6c\xa2\xc0\x71\x54\xe8\x63\xfe\xf5\xa4\x04\xe3\xe8\x9f\x0d\x7f\x30\xf2\x18\xec\x4d\xe7\xa5\x3a\xeb\x9c\x41\xee\xaa\xf6\xce\x74\x96\x49\xc9\x99\x8f\xd6\x2b\xcb\xa2\x87\x23\x38\xe1\x9c\x94\xe5\x9d\xd5\xe2\xdd\x77\x6f\x53\x71\x9d\x21\x74\x69\x76\x93\x2e\xf1\x1a\xbf\x7a\x32\xae\x6b\x07\x44\x66\x5d\x0e\x0c\xe5\x13\x95\x5a\x9e\x68\x53\x1d\x8e\xe4\xde\x9a\x8d\x35\xdd\xfb\x88\xeb\x5a\x48\x6a\xd6\x31\x37\xe8\x89\x2f\xd7\xc6\x89\xd4\xf9\xe7\x02\x1b\x11\x73\xbb\x37\x52\xa5\xee\xcf\x29\x92\xe3\xfd\x46\x42\x26\x3c\x7b\x3d\x81\x5c\x29\xb4\x66\xab\x69\x28\x5f\xfe\x4b\x8d\xaf\xcb\xf3\xd0\x1d\x63\x55\x53\xab\x75\x75\xa7\xa3\x47\x1e\xdc\x7b\xe4\x12\xd3\xd0\x1e\x6f\xe8\xe3\xcd\xc3\xfa\x04\xd2\xa7\x59\x93\x81\xe2\x2b\xba\x49\xc5\x53\x9d\x79\xc6\x2b\x52\xbb\x0e\xca\x33\xf7\x42\x55\xe4\x1a\x95\x26\xa8\x92\x89\xb1\x5f\x18\x50\xd9\xaf\xa8\x7e\x6b\x6f\xa1\x27\x10\x1c\x1a\x6d\x88\xd4\x33\xe0\xc8\x6a\xa6\x0b\xba\x8f\xe7\x10\x0e\xd6\x1d\x5a\x9d\x00\xa0\x07\x64\x51\x3e\xb1\xc7\xf5\xf5\xc3\xb3\xef\xc4\x53\x2a\x36\xb4\x07\xfe\x2d\x17\xcf\xb4\xe6\xfc\xd6\x04\x9c\xff\x3a\x35\x56\x23\xa3\xa4\x13\x90\xea\x48\xf4\x21\x20\xd8\x97\x94\x91\x11\xbe\x3d\x16\x9b\x2d\x2e\xf4\x5b\xdb\x89\x4f\xe2\x0b\x1a\x95\xef\x66\x14\x94\x27\xa9\xd8\xf8\x0a\x9b\x2e"}, -{{0xa3,0xbe,0xd9,0xfe,0x23,0x54,0xbd,0x28,0x60,0x14,0x9a,0x3d,0xb7,0x5a,0x85,0xb1,0x29,0xcf,0x83,0xe9,0xd7,0x3e,0x63,0x17,0xba,0x70,0x54,0x52,0x19,0x33,0xf8,0x96,},{0x5a,0xc0,0x3b,0x4f,0x13,0xd9,0x1d,0x06,0x6b,0x2c,0xe3,0x59,0xe9,0xbb,0x1d,0xfb,0x6b,0xfa,0x5a,0xfa,0x38,0x2f,0xd1,0xcc,0xd7,0x2a,0xef,0x11,0x76,0x07,0x9f,0x89,},{0x33,0xbc,0x1e,0x0b,0xf1,0xb4,0x93,0xe0,0xcf,0xb7,0xea,0x40,0x48,0x0a,0x14,0x23,0xe0,0x91,0xf7,0x14,0x57,0x45,0x01,0x31,0x73,0x78,0x7d,0xf4,0x7a,0x10,0xdb,0x24,0xc1,0x65,0xd0,0x05,0x96,0xfa,0xb7,0x0e,0x68,0xc9,0x4c,0x10,0x4e,0x8a,0x74,0x07,0xcf,0x69,0x5c,0xd3,0xfb,0xe5,0x85,0xb5,0xb1,0x76,0xb8,0x5c,0xcc,0xa4,0xfd,0x08,},"\xdb\x85\x38\x08\x68\x6d\x6d\x21\xf4\xc5\x7b\x54\x1e\x5a\xd6\x33\x94\xd4\x65\xe6\x00\x78\x64\x3c\xab\x1e\x06\x5c\x9f\x30\x6c\x50\x00\x78\xf0\xcc\x41\xef\x0f\x95\x42\xb5\xfe\x35\x6a\xec\x47\x77\xef\x8a\x95\x55\x4c\x97\xb6\xa4\x40\x99\xe9\xbd\x64\x04\xfb\x0b\x2e\x41\xf9\x19\x14\xb0\x74\xd1\x22\x37\xcd\x44\x2e\xbd\x40\xb5\x1b\x8b\xc8\xbb\xe4\x37\xa2\xc5\x33\x32\xd2\xbe\xb2\x28\x1b\xf7\x32\x4a\x0c\xf5\xb7\x41\xbb\xf9\x8d\x1e\xb9\x85\x8b\xe9\x26\xe9\x15\xa7\x8e\x8d\x31\x4b\x41\x44\xf3\xd2\x0d\xfc\x6c\xb7\xf4\x8c\x23\xaf\x90\xf8\x71\xc6\xcd\xa9\x08\x45\xa4\x1a\xff\x17\x07\xa8\x7b\x4e\x55\x16\xf1\x8e\x8b\xd7\x68\x3c\xfd\x74\x07\x08\x03\xe8\x88\x33\x8c\x9a\x18\xf7\x92\xc8\xd3\xa7\x04\x17\x0f\xf9\x82\xbf\xfc\x9e\x8e\xc9\xea\x5d\x1a\x62\x59\x2f\x16\x88\xd4\xf2\xb0\x1e\x11\xf9\xf8\x87\x74\xc4\x7a\xc1\xd5\x8f\x69\x0b\xcf\x28\x8c\xf8\xa4\x73\xd3\x50\xa8\x23\x9d\xf9\xd3\xa6\x28\x81\xda\xdd\x33\x85\x31\xfd\xce\x76\x15\x80\x7c\xe9\x65\x49\x6d\x6f\x35\xd6\xc0\x42\xf0\xce\x7f\x21\xef\xe5\xce\x64\x25\x18\x59\x41\xed\x56\x36\xb8\xae\x91\x3a\x75\xd2\x1a\xb9\xdb\xdb\x3c\x3b\x66\x87\xa4\x5e\x04\x49\x38\xa9\xf1\xc1\x3a\x33\x0e\xa9\x76\x1e\x28\x3e\x61\xd4\xa3\x20\xe1\xf5\x59\x88\x2f\x34\xb6\x07\xfe\xfe\x32\xc3\x43\x17\x4a\xbc\xdc\x77\xb0\x65\xa9\x29\x04\xb4\x2d\x96\x1d\xb8\xed\x91\x6c\x01\x46\x4f\xfd\x43\xf9\x3c\x10\x77\xf1\xdf\x7e\xe6\x50\x31\xcf\xe0\x5d\x78\x0d\x01\xd0\x8e\xe0\x36\xf2\x2a\x2b\x05\x12\x19\x3b\x0c\x0f\x38\x01\xe0\xa0\x20\x8e\xef\x24\x5c\x9e\x51\x93\x52\xd2\xb0\x09\x63\x82\xf2\xcb\xa0\x6e\xb2\xa0\x1d\xac\xf6\x19\xea\xbb\xc8\x83\xc5\xd4\xf2\xfd\x7c\x34\x23\x17\x9c\x0f\x5f\xfd\xaf\x8c\xaf\xff\x5c\x46\xb3\x4a\x09\xc3\xc5\x0e\x29\x49\xc0\x60\x00\x20\x7d\x70\xd3\x7d\x65\xa7\x43\x07\x5f\xdc\x2b\xe6\x2d\x41\x2a\xa6\x3e\x36\x37\x06\xca\x90\xe6\xef\x44\xe1\x52\xea\x4d\xc5\xc2\x89\x3e\xcd\x08\xd7\x96\xd4\x1f\x17\x22\x54\xc3\xd1\xd1\x4b\xb0\x67\xb5\x3a\x08\x97\xbb\xd7\x3c\x99\x54\xd9\x64\x8b\x2a\xf1\x0d\x9c\x27\x03\xe3\x8b\x6c\x62\x46\x9f\x6f\x95\x8a\x1c\xa0\xa3\x20\xc1\x23\x39\xe9\x0c\xf7\x68\xc8\x7b\x47\x38\xc2\x19\xf8\x09\x3b\xff\x4c\x2c\xfd\x29\x45\x9f\x6d\x32\x81\x34\x93\x78\xe9\x15\xa3\xb0\xe7\x24\xc7\x4d\x2b\xd7\xa8\x51\xac\x7c\x6b\x48\xe8\xaf\xc7\x12\x4f\xdc\xbc\xab\x5f\xf8\x0d\x1d\xee\x30\xa6\xc0\x24\xcb\x43\x31\x97\x23\x66\xeb\xab\x26\xbb\xb9\xf6\x08\xca\xac\x7e\x51\x91\x4d\xf0\x58\xb9\xb3\x74\x5d\x98\xc5\xd2\x7e\x97\x10\x54\x75\xec\x01\x73\x77\xe6\x31\x61\x98\xec\xe4\xec\x59\x09\xf0\x4f\xc2\x7e\x7b\x38\x2e\x66\xad\xb6\x2a\xc8\xa9\x77\xf3\x76\xfd\x5d\xae\x43\x4f\xb5\x51\x75\x24\x9c\xa1\xab\x6b\xb0\x2d\xec\x06\x96\xf0\x89\xbe\x34\x54\x88\x7a\x0c\x32\x36\x1d\x17\x2b\xd2"}, -{{0x88,0xa2,0x4f,0x0d,0xf3,0xae,0x29,0x14,0xdf,0x79,0xda,0x50,0xec,0xf8,0xec,0xb4,0x2f,0x68,0xc7,0xba,0xad,0x3b,0x6c,0x3a,0x2e,0x0c,0xc9,0xc2,0x5d,0x09,0xd1,0x42,},{0x12,0xe6,0x60,0x3f,0x71,0x3b,0x23,0x05,0x35,0x85,0x68,0x71,0x00,0x18,0x68,0x5e,0x14,0x15,0x53,0xc4,0x75,0x91,0x39,0x6f,0xb4,0x25,0x9e,0x42,0xdc,0x53,0xb9,0xc9,},{0x17,0x07,0xcc,0x00,0x91,0x86,0xbf,0x3f,0x03,0xf7,0xbb,0x9e,0x3c,0xd4,0xcf,0x6b,0x73,0x7b,0x7a,0x6b,0xaa,0xde,0x7f,0xc6,0xc3,0xff,0x5c,0x12,0x25,0xdb,0xb2,0xba,0xf5,0x4f,0x47,0xc8,0x5e,0xaf,0xa1,0x32,0xc3,0x1e,0xac,0xa0,0x3e,0x6a,0xec,0x14,0x47,0x73,0x3f,0xac,0xd3,0x71,0x49,0xb7,0xc6,0xcf,0x0c,0xd4,0x1f,0x61,0x14,0x04,},"\x65\x4e\x9e\xdc\x69\xfe\x63\x4c\x23\x08\xba\x8c\x46\xa9\x55\xe8\x82\x45\x62\x86\xea\xe3\x59\x3c\xae\x73\x9c\x44\x86\x6c\x0d\xe9\xed\xcb\xbf\x0d\xb1\xc4\x41\x49\x66\x84\x67\x70\x9d\xc9\x70\x62\x98\xdd\x2e\xac\x33\x01\xda\xba\xd5\xbd\x8e\x93\xc5\xe8\xa9\x3f\x19\x4e\x0f\xc1\xd9\xf3\x76\xc1\x44\xc2\x93\xae\xfd\xa0\x86\xb2\x21\x8f\x2e\x9d\xfd\x7c\x2d\xc5\x2b\xa3\x3e\xb2\x29\xdc\xf7\xbb\x68\xce\x0f\x87\x6c\x5f\xd4\xe8\x1a\xfd\x80\x16\x9f\x73\xcf\x26\x4e\x5d\xc0\xce\x16\xe1\xb8\x76\xcd\x11\xc7\xad\x89\x05\x8e\xe0\x82\x0c\x40\x00\x5d\x01\xf1\x19\xf8\xbe\x6f\x1a\xfb\xe2\x4c\xa4\xae\xdc\x18\xe9\x78\x96\x82\x7c\x3e\xd6\x7f\xc4\x56\x30\xe7\x90\x3b\x7f\xee\x9c\x99\x0e\x36\x19\x37\xbf\x4e\xa0\xa4\xd8\xd1\x6c\xf6\xd9\xcf\x03\x81\xe9\x06\x5e\x36\x25\x14\x8f\x8a\xe0\x49\x1a\x03\x41\xd0\xff\x9f\x72\x7b\xe1\xf3\x10\xca\x1e\xc3\xf0\x10\x4a\xa0\x54\x32\x17\x84\xdd\x24\xd5\x3c\x98\x5b\x28\xd4\x40\x82\xf8\xe1\xc1\x08\xa4\x41\x09\x63\x8f\xf5\x11\x6e\xdd\x85\xae\xb8\x6b\x6e\xa5\x12\xa1\x9b\x60\x2e\xdd\x9d\x21\x10\x70\xd0\x44\xaf\x5b\xed\xb6\xc8\x52\x7b\xa3\x49\x1e\x34\x5b\xac\xc1\x30\xb3\x69\x60\x28\x2a\xe7\x37\xb8\x5c\x76\x92\x74\xf0\xf7\xc5\x88\xf4\x0e\x66\x25\xb2\x36\xbd\xc1\xa3\xb8\x73\x20\x46\x0e\xee\xad\xa2\x78\x12\x4b\x56\x68\x87\x4f\x39\xf5\x9c\x2e\x6a\xa2\x08\xc3\xb6\xa9\xb8\x45\xc4\xd0\xa2\x7a\x05\x46\x78\x6f\xa1\x3e\x51\xcc\x98\xb7\x3f\xd7\xee\x32\x7b\x62\x15\xec\x6b\x62\x9f\x4c\xc7\xe4\xbd\x3c\x0a\x3d\xb7\x8a\x21\xff\xfe\x24\xc7\x04\x38\x71\x6b\xc3\x7b\x8d\xa7\xc5\xff\x7c\x36\x88\xa9\x03\x39\xc2\x2e\xb5\x0b\x7c\x2c\xd3\x6b\x68\x83\x1f\xd5\x93\x91\x75\x68\x9b\xd3\xe2\x2c\x38\x81\xaf\x33\x7e\xe1\x44\x35\x70\x9e\x35\x10\x40\xef\x3d\xa9\x55\x72\x4e\x51\xc2\x4a\x5e\x2c\x09\xf8\x91\x80\x83\x93\xfb\xf8\xef\x7f\x1f\x5f\x02\x98\xde\xeb\xdc\xd8\xd6\x66\xcb\xcf\x3e\x86\x6c\x71\x89\x99\xab\x6b\x1f\xee\xc9\xc4\x7e\x02\xe7\xd6\x35\x40\xf8\x99\x63\xd5\x42\xc5\xd0\x1f\xb6\xfc\x30\x76\x89\x68\xae\x81\xb2\x0c\x35\x4b\x40\x00\xc1\x32\x77\x47\x64\xd6\xd4\x43\xad\xd6\x4f\x6d\xd7\x48\xf5\xfb\x5b\x7f\x6e\xba\x40\x1d\xb4\x31\x8b\xe9\x93\x98\x9f\xcc\x25\x77\x96\x1f\xa5\xad\x31\xf6\xa2\xa9\xd6\xa7\x55\x28\x58\x65\xcd\x5d\xc3\xa8\x8c\xfb\x5a\xba\x7d\x92\x3b\xaf\x78\xb5\xd1\x31\xb4\xc2\x14\xdf\x55\xb6\x17\x1f\x45\x20\x9e\x21\xca\x66\x45\x49\x0d\x3a\x36\x44\xdd\xa6\xdc\x92\x9c\x7c\x40\x95\x76\xd3\x71\x64\x75\x5e\xf8\xaa\xf3\xdc\xd4\xd2\x27\x75\xee\x7d\xea\x0e\x56\x5b\xd5\x47\x27\x92\x1c\x64\x9b\xc5\x1f\x20\xc1\xf6\x8c\x1f\xde\xac\x45\x5c\x67\xd7\x1a\x1c\xb8\x83\x7f\x46\x91\x44\x8b\xf0\xbf\x04\x4a\x46\xf1\x68\x5f\xbe\x22\xb1\xe0\x18\x77\xf7\x47\x7d\x34\x99\x40\x8c\x4c\x31\x65\x10\xce\x2e\x55\xb9\x80\x05"}, -{{0x18,0x4d,0x0c,0xe2,0xe9,0xdb,0x7f,0x25,0x7a,0x8b,0xf4,0x64,0x6d,0x16,0xd2,0xc5,0xef,0xc2,0x70,0x2c,0xed,0x02,0x6b,0x69,0x06,0xd3,0xc8,0xc0,0x11,0x8f,0x22,0x61,},{0xe9,0xda,0xb8,0xfd,0x9d,0x94,0xdc,0x9b,0x24,0xcc,0x79,0xc6,0x35,0xcc,0x57,0xce,0x66,0x51,0x89,0x82,0xba,0x3e,0x24,0x47,0x24,0x07,0x41,0xba,0xc0,0x73,0x0e,0xc5,},{0xb1,0xe3,0xbf,0x5f,0xa7,0x4d,0x7e,0x44,0x2c,0xed,0x9a,0x98,0xd9,0x27,0xd8,0xc4,0x5e,0x0e,0x64,0xd8,0x74,0xf8,0xea,0x59,0x20,0xa3,0x60,0xa4,0xbf,0x42,0xd8,0x3c,0xe1,0x8a,0x92,0x4a,0xc7,0x96,0xe1,0xa7,0x7d,0x1b,0x02,0x08,0x29,0x4b,0x50,0xf8,0x22,0x17,0x7f,0xdb,0xdd,0x45,0x8c,0x74,0x35,0x6f,0xcf,0x6b,0xd7,0x94,0x51,0x06,},"\x6a\x9b\x87\x6b\x0b\xf4\x18\x9b\x3c\xc1\x5f\x9e\xb4\xfb\xe7\x93\x2b\x55\x77\x89\x2a\x22\x20\x0c\xe1\x07\x15\x68\x53\xd6\xd3\xca\x36\x3f\x02\x5a\xd7\xa2\xd8\x62\xaa\xdc\x74\x2d\x94\x15\xbd\x8d\x1f\xca\x13\xc9\xdc\xa3\x58\x60\x44\xe5\x5a\x8c\xf5\xde\xe1\xce\x56\x45\x76\xe3\xe8\xe3\x65\x54\x05\x46\x50\x1b\x34\xca\x67\x5c\xf2\x00\xe0\x77\x1a\x81\x8c\x73\xd3\x7f\xcd\xa8\xcb\x15\xe4\x8d\x5a\x0b\x9e\xa3\xbe\xec\x0f\xf6\x61\x0b\x2a\x8a\x21\x4c\xa4\xf7\xef\xac\x0e\x71\x38\x10\x52\xd9\xbf\x3c\x00\xc3\x29\x59\x34\x74\xeb\xd0\xa6\x87\xa0\xb4\x1d\x14\x4b\x5e\x7a\xb1\x41\x2b\x97\x0a\x74\xba\xba\x4d\x27\x4b\xb0\xdb\xfd\xb0\x2b\x11\xf7\xf6\x39\x64\xba\x6f\x3b\xa0\xad\x23\x34\x1d\x08\x3b\x91\xa4\x30\x82\x39\xe3\x3d\x50\x82\x43\x96\x12\x65\x88\xde\x72\xa2\x39\x0c\x1c\x0f\xc0\x67\x47\xc2\x87\x72\xf6\x30\xbf\x4d\x14\x3f\x7a\x11\x59\xf0\x28\xc0\x93\x40\x48\x94\xe6\xd1\x6f\x63\x46\x35\xd4\xfc\x33\x0f\x3d\x7a\x73\x13\xef\x75\x6f\x5d\x49\xd8\xf6\x20\x5e\xb1\xc7\x92\xa9\x49\x5d\xa1\x31\xb4\x33\x45\xa0\x09\x0c\x12\xca\x56\xe6\xad\xac\x5b\xe0\xcb\xca\xc3\x60\x9d\x69\xf7\x24\x15\xf6\xc3\x7f\x3c\xfb\x2c\xf7\x6b\x3e\x65\xf3\xc9\x3a\xc9\x2b\x63\xf2\xba\xa4\x66\x24\x90\x75\xbc\xa6\x9d\x4c\x1d\x1f\x3a\xde\x24\xab\x31\xef\xfc\xb9\x04\x69\xc2\x4b\xb4\x10\xab\x47\x23\xe1\xb7\xe1\xc8\x8b\x3a\x36\x43\x35\x63\xf7\x1a\x99\xaa\xd5\x8f\xe8\x05\x68\xf9\xc1\x02\xda\x89\xba\xd9\x79\x63\xe7\x7d\x66\x22\x48\x31\x66\xf3\xae\x26\x1f\x32\xa5\x2a\x86\x10\x1e\xbd\x64\x5f\x61\x42\xc9\x82\xe2\xcd\x36\x25\xcf\x8b\x46\xb9\xb2\x89\x12\x46\x92\x0f\x69\x7f\xca\xed\x39\x7c\xb9\x22\xc2\x74\x94\x51\x67\xa0\xe6\x19\xb0\xb5\x06\x37\x76\x06\xdb\x04\x57\x83\xb0\xb8\x8e\xa0\x4e\x93\x2d\x21\xff\xc0\x64\xa1\x2a\x40\xeb\xe9\xb4\x80\xf1\xa2\xc7\xdd\xd3\x95\xa9\xb1\x5e\xfd\xc4\x95\xc9\x71\x4f\x36\xfa\x99\x6f\x79\xf8\xeb\x8e\xfa\x52\xd9\x9a\x24\xab\xfe\xf4\x3b\x32\xa2\x37\xc5\xbc\x00\x18\xda\x3b\x16\x2f\x59\xb8\xd3\xd4\x74\xe2\xce\x08\xfa\x80\x24\xc5\x8a\xcc\x0a\x99\xff\x61\x4e\x6c\xd7\xfd\xd9\xca\x4e\x8f\x41\xa1\x44\x9a\xa6\x18\xd0\x33\x37\xe8\xa3\x74\xd5\x60\x55\xb2\x07\xa9\xdb\xe6\x9f\x59\x48\xf9\x01\xca\x7d\xb0\x41\x0f\x01\xaa\x37\x3d\x9e\x02\x27\x62\x35\x99\xbc\x21\x28\x45\xb0\x06\xe9\x42\xfa\xbc\x58\x2c\xd7\x26\xdb\x5c\x44\x3e\xb2\xdf\xfb\xc9\xe3\xe7\xf0\xe5\xcb\x67\x44\xf7\xad\x71\x60\x50\xfd\xf2\xc6\x0c\x7c\x77\xc2\x53\xab\x74\x5d\xb9\xc8\x55\x26\x55\x68\x3e\xa7\xea\x68\x0a\xa4\xaf\x34\xdf\x13\x25\xc2\x9b\x88\x74\xb6\x1b\xe2\x3d\xe4\xff\xba\x25\x42\x4f\x46\x19\xec\x68\x2c\x26\xb3\xa6\x7b\xda\x9b\xc4\xc9\x4b\x79\xa9\xfc\x4d\x82\xd3\x40\x49\x5b\x43\x7a\x1c\xbd\x6b\x60\x30\x7c\xfc\xb1\x00\x26\xf9\x64\xa0\x17\x62\x3e\x33\xdb\xf2\x33"}, -{{0xd0,0x2b,0xbf,0x70,0xd5,0x13,0x51,0xe3,0xb4,0x7a,0xd8,0xe5,0xed,0x26,0x3d,0xbf,0x55,0x6d,0x14,0x98,0xfa,0x9b,0xd5,0xdb,0xd9,0x9f,0xb4,0x26,0x90,0x09,0xdc,0xed,},{0x8c,0xe4,0xb5,0x9f,0x94,0xce,0xd6,0xec,0x96,0x14,0xd6,0x7d,0x30,0x66,0xd9,0xd3,0xa0,0xdf,0x7a,0x46,0xb3,0x7b,0x4c,0x17,0x25,0xef,0x1e,0x57,0xbc,0x68,0xa0,0xd1,},{0x6e,0x7c,0x66,0xac,0xc9,0x54,0xff,0xd9,0xdd,0x4c,0x1c,0x63,0x35,0xab,0x4f,0xe7,0x9d,0xbb,0xed,0x78,0x2c,0x4a,0x47,0xec,0x30,0xd8,0x48,0xd8,0xbb,0x2b,0x4f,0x10,0x69,0xdc,0x62,0xe5,0x22,0xa1,0xe8,0x01,0x7f,0x54,0xa6,0x34,0x5e,0x17,0x28,0xc0,0x73,0xaf,0x64,0x47,0x85,0x6d,0x8c,0x1e,0xd3,0x58,0x78,0xb5,0x71,0xe5,0x23,0x0d,},"\x55\x45\x60\xf7\xa7\xfd\x1a\xe7\x75\x8a\x2f\xce\x7d\x78\x0f\x6b\x3f\x04\x3d\x3a\xf8\x9d\x4f\x19\xef\x57\x3c\x34\x99\x75\x54\xdf\x24\x3f\xaf\x2a\xaa\xb6\x5b\x2a\xfd\xd2\x86\x10\xd4\xa5\x1e\x9a\x4b\x46\x4d\xb6\xdb\x09\xeb\xf7\x3b\x7d\x24\x05\x4c\xc9\xb1\x28\x14\xbb\x29\xee\x99\xe1\xa7\x3b\xd6\x03\x89\x83\x60\xf9\xdc\xf0\x1e\x67\x08\x36\x28\x6f\x82\x36\xed\x8c\xef\x07\x5f\x3d\x56\x33\x12\xc1\x6c\x73\xfc\x37\xee\xdf\x25\x2f\x8f\x42\xd3\x0a\x13\xe7\xfb\xa3\xb1\x65\x23\x8c\x7f\x81\xea\xae\xb5\x31\x90\xf3\xec\x3b\x5d\x63\xf0\xee\x03\xe3\x98\x7e\x39\x0d\x1d\x81\xe8\x27\x7e\x9f\x6c\x1e\xe6\xec\x4e\xc3\xfa\x0d\x72\x0e\x9f\x53\xf9\xc2\x6f\x04\xaa\x2e\xd2\xb5\xef\x31\x60\x89\x59\x99\xea\xce\x29\xcf\x5d\xc2\x54\xad\x71\x10\x6b\xb7\xe8\xbc\x29\xa5\xb1\xd2\x41\x25\x93\xd0\x81\x94\xe8\x8e\x16\x59\xa7\x31\x59\xa2\xa2\x20\x33\xab\x06\x6e\x8d\x3d\x8c\x3b\xc8\x6b\x7b\x01\xde\x81\xa8\xc6\x60\x47\xb0\x7f\xe2\x4e\xd2\x40\x31\x8b\xa3\x7b\xa3\xef\xb6\xcf\x63\x26\x04\xca\x4f\x44\x6a\x75\xfd\x8e\x70\xc4\x53\xf0\xc6\x0e\xe1\x6e\xca\xf5\x24\xe7\x03\xf4\x7d\xf5\xc2\x82\xca\x32\x89\xb3\xaf\x61\xde\xe4\x70\x9e\xe0\x85\x32\x3b\x1e\x5c\x8a\x6b\xc0\x76\x62\x01\xc6\x35\x03\x14\x46\x89\x1f\x34\x94\xe9\xdb\x20\xdd\x4e\x9e\x08\x38\x24\x9a\x67\xe1\x38\xd1\x3e\xe2\xc9\x6f\x61\xe7\x71\x06\x15\x42\xaa\x16\xef\x20\xd8\x1e\x3a\x0f\x4e\x45\x21\xa6\xcd\x6c\x92\xfc\x26\xfe\xef\x03\xb6\x6c\x70\xe0\x35\xca\xfc\xc1\x9c\x96\xfb\x9d\x82\x91\x8f\xe1\x97\x78\x0e\xff\x0e\xda\x6e\x25\x12\xc5\x6e\x2a\x73\xd7\x70\x32\xb7\x68\x91\x9b\xea\x97\x72\xf5\x98\x9c\x8b\x6c\x65\xc3\xd1\xe9\x7a\x21\x80\xcc\x3a\x37\x57\x9d\xa7\x0c\xe9\x80\x6a\xc1\x28\x5a\x3e\xab\x41\x5c\x06\x07\xd8\x8c\xb8\x65\x42\xea\xb9\x0b\x9d\x2d\x67\xfa\xff\xfc\xad\x23\xa7\x14\x00\x0e\xe5\x9e\xd6\x8c\x95\x6e\x81\xc4\x45\x42\x88\x82\xf9\x7a\xf7\x4d\xb3\x62\xe4\x5c\x0d\x1b\xd8\x85\x6e\xed\x16\x6e\x4a\xec\x4b\xfd\xf9\x5e\xad\xb2\x51\xe2\xa1\xef\x80\x48\x52\xa9\xea\x77\xd3\x45\x77\xfe\x70\x83\x1a\x92\x8b\x10\x1b\x60\xac\x61\x3e\x7b\xa2\xe6\xba\x0a\x94\x01\x3a\x64\xc2\xf8\x21\x9f\xd3\x0b\xff\x40\x90\x99\x66\x7a\x78\x6f\x99\x32\x7b\xb0\x3e\x2f\x21\x87\xf4\x45\xb4\x6b\xee\xda\xb6\xd3\x25\xaf\xd9\x04\xe3\x95\x43\xe9\x3f\x4b\x6c\x54\x43\x24\x9d\x74\x4b\x2d\x1a\x43\xe1\x41\xe4\x76\x8b\xd4\x0a\xab\xe4\x05\x72\x44\xe1\xea\xdd\x9d\xae\xc1\x75\x71\x9e\x51\xa0\x93\xac\xe3\x2f\xe8\x2b\x2e\xac\xb5\xec\xb0\xda\x6c\x1f\xfe\x98\xc8\xce\xe7\x88\x6e\x30\x16\x70\xdf\xf8\x71\x13\xef\xed\x42\x82\x47\x1a\xfb\x6b\x8a\x0f\xdb\x50\x5e\x2e\x8e\x7d\xbc\x1a\x08\xa2\x2e\x96\x80\xbd\x09\x8b\xf1\x27\x58\x02\xbd\xb4\x59\x41\x3a\x3b\x23\x7d\x77\x13\xa1\xbb\xf5\x97\xe6\xad\xf2\xb6\x0e\xaf\x82\x37\x91\xb3"}, -{{0xaa,0x0f,0xda,0xe2,0xa5,0xa4,0xc9,0xc0,0x45,0x21,0x91,0x30,0x04,0xcd,0x89,0xef,0xbc,0x88,0xb2,0xda,0xdf,0x5a,0xbb,0x24,0x6f,0x3c,0xa7,0xf6,0x92,0x35,0x44,0xaf,},{0xbf,0xfc,0xb1,0x7c,0x35,0xc1,0x30,0x4c,0xdd,0x9d,0x62,0x4f,0xf6,0x9b,0xee,0x60,0xec,0x7c,0x9e,0xc3,0x27,0xd1,0x23,0x50,0xd7,0x0f,0xac,0x12,0xb4,0x7c,0xc2,0x5c,},{0xf9,0x37,0x29,0x89,0x69,0xca,0x34,0xd9,0x75,0x84,0x44,0x89,0x07,0x35,0x8b,0x0f,0x47,0x84,0x1f,0x30,0x23,0xaf,0xc7,0xef,0x76,0x81,0x52,0x1c,0x5b,0xe0,0xf5,0xe5,0x62,0x8a,0x8f,0x60,0x7e,0x2f,0x31,0x63,0x6e,0xf6,0x36,0x46,0xb0,0xe9,0x89,0x8a,0x72,0xad,0x35,0x57,0x06,0xd2,0xc8,0x06,0x0f,0xbc,0x64,0x0e,0xfb,0x3d,0x66,0x05,},"\xb1\x41\x84\xcf\xdc\x4a\x5f\x0c\x7f\x83\xf9\x4a\x83\x2f\x58\x85\x07\xe2\xd7\x2a\x89\x32\x98\x70\x07\x85\x71\xd2\x08\xa0\xc4\x96\x0c\x2f\xdc\x4c\x23\x6c\xf8\x82\x29\x98\x1d\x12\xb1\x0a\x1b\x68\x84\xc8\x65\x0d\xda\xf1\xd4\xb2\xeb\x98\x15\x75\xb1\xe0\x19\xfe\x3f\x60\x42\x36\x76\xf8\x85\x6a\x99\x2c\xce\x36\xd6\xd0\xa3\xd0\x26\x63\x1c\x8c\x1e\x1f\xfe\x34\x13\x4b\x29\x6f\x40\x84\x2b\x6d\xf4\xf8\x6f\x83\x3e\x01\x75\xba\xe5\x0e\x86\xbf\x85\x6d\x1e\xe7\x99\x25\xf4\x34\xb8\xbf\x2c\x84\x51\x9f\x1f\x5d\x25\x38\x60\x49\xce\x3c\xa6\x17\x77\xe3\x0b\x70\x0a\x60\x2d\x39\x52\x50\xb6\x0f\xc6\x4a\xc6\xf8\xdb\x02\x7e\x8d\xa8\xb9\x55\x0f\x24\xed\x11\xa1\x1d\x9f\x9f\x9c\x5e\x0a\xf1\x45\xb8\x65\x97\x51\xac\x6b\x55\x86\x1f\x63\x88\xa6\x43\x36\xb3\x1e\xfe\x45\xc0\x80\x2d\x76\xa5\x34\x86\xa8\x1e\xba\x07\x31\x4b\x4d\x96\x1c\x14\x1a\xb3\x4e\x2f\x76\xed\xac\x0e\x6d\xe3\x14\x22\xdf\x79\x2a\xf0\x81\xe7\x69\xc7\xed\x05\xda\x9a\x5a\xf2\xfd\xf3\x6f\x14\x17\x69\x90\x8b\x70\x09\x37\xf0\xe1\x06\x8c\x13\x1f\x17\x6e\xb9\x6c\x67\xaf\xdb\xe7\x8f\x40\xd8\x60\x07\xfb\xcd\x47\xe4\x9e\x2e\x4c\x4c\xe0\x49\x93\x6a\xdf\xf1\xce\x3e\xac\x42\xb9\x6b\x34\x29\xb5\x62\x6b\x1a\xa6\x2a\xcd\xe0\x7f\x45\xa1\x3c\xe1\xbd\x21\x1f\x32\xbd\x7e\xfe\x47\x90\xc8\x37\x1e\xbf\x87\xc1\x64\x47\x7a\x5c\x9f\xa3\xe7\x8c\x2f\x88\x07\x7b\x09\x73\x44\xcf\xfa\x03\x1c\x44\x29\xc7\xf4\x2d\xca\x07\x73\x78\x50\xee\x7a\x76\x9b\x36\xd0\xf0\x62\x5a\xdf\x12\x0e\xa2\x3f\xf4\xe3\x93\xa4\xfd\xcb\x65\x58\xdb\xf9\xb2\x66\xa0\x32\xe3\xb0\x59\x9b\x9d\x66\x92\xfc\xeb\xd8\x15\xa3\x89\x76\x07\x85\x63\x25\xfc\xd0\x11\x5d\xc3\x10\xdb\x3a\x87\x92\xfb\xeb\xd3\x99\x49\x4c\x83\x71\xe5\x85\x72\x7b\x3d\x63\x24\x14\x49\x68\x93\xd0\x38\x13\xba\x1f\x99\x66\x1b\xce\xb9\xdc\x18\xec\x5d\xc2\x7f\x52\x67\x03\x18\x68\x77\x69\xfc\x67\x8d\xdc\x7e\x40\x22\x7c\x20\x05\x22\x01\x3f\x5c\x0e\xec\x0e\x47\x81\xe6\xfc\x15\x3a\x0c\x2f\x4f\x3f\x95\xe5\x17\xc8\x41\x99\x24\xab\x39\x99\x2a\xf8\xc1\x94\x65\x05\x7f\x13\x44\x86\x69\x6b\xa7\xfd\x46\x51\x76\x8b\x4e\x74\x9e\xf3\x6f\x02\x44\x46\x17\xcf\x97\xf0\xa4\x23\xe4\xc1\x3b\x7b\x66\xba\x2b\x6c\x45\x68\x78\xb0\xb5\x0c\xe2\xee\x5e\xc5\x64\xed\x88\x54\xf7\x82\xaa\x1d\x1c\x6a\xa7\x60\xf2\x52\x2c\x7d\x97\xb9\xb1\xab\xe0\xba\x81\x09\x59\xd7\xaa\x40\x3a\x99\x37\x5a\xa3\xe3\x9a\x11\x5d\x1f\xc6\xfe\xdd\x00\x2f\x38\x30\xa5\x0a\x83\x7d\xc7\x20\x32\x9e\xc0\xc7\x3d\x5b\xfd\x50\x03\x85\xc7\x36\x83\x82\x87\xe1\x92\x01\x52\x5d\x18\x9c\x3a\x08\x4c\xd5\xa3\xf3\x59\x87\x5e\x3b\x83\x25\x28\x9c\xed\x18\xb6\x3b\x00\xff\x9c\xd0\x70\xc3\xe6\x74\x44\xbd\x3d\x83\x46\x17\x40\x85\xcc\x45\x13\x5c\xaa\x0c\x67\xb3\x22\x6e\x4a\x52\xe9\xa1\xc5\x5a\xed\x7e\xc5\xfa\xde\x6b\xf1\x6c\x19"}, -{{0x71,0x62,0xfe,0xf0,0xac,0xa4,0x97,0x4b,0x09,0x4a,0x6a,0x08,0x05,0x43,0x95,0xf8,0x77,0xff,0x94,0x33,0xf1,0xe3,0x3e,0x20,0xe8,0x8e,0xaa,0x90,0xf9,0x38,0x99,0x7d,},{0xa2,0x80,0x64,0x0f,0x13,0x9f,0x45,0xc3,0x5a,0x48,0x71,0x53,0x7e,0xef,0xe6,0xef,0x9d,0xb0,0x2d,0xe7,0x85,0xee,0x9f,0xd5,0x4f,0x80,0x5f,0xb5,0x7d,0x37,0x46,0xef,},{0xae,0x16,0x1c,0xce,0x95,0x40,0x33,0x84,0xb6,0x5c,0x6b,0xc9,0xb3,0x93,0xeb,0x07,0x25,0x64,0xc3,0x5f,0x3a,0x6c,0x04,0xfa,0x51,0x7a,0xb0,0x68,0xbc,0xd2,0x37,0x67,0xcc,0x0c,0x8e,0xdd,0x92,0xb1,0xa1,0x3a,0xe9,0xa9,0xce,0x48,0x64,0x13,0x7f,0xb8,0x9c,0x1f,0x37,0xb7,0x48,0xcf,0xc9,0x13,0x4b,0x67,0x41,0xba,0x1b,0x22,0x28,0x0d,},"\xc9\x0f\x45\x0b\xda\x1c\x6e\xfd\x8d\x12\x78\xde\xbd\x7a\xe0\x3e\x2e\xac\x27\x40\xa5\xa9\x63\xfc\xf9\x6c\x50\x4e\x31\xd4\xd6\xfc\xc5\xe2\xb5\x2a\x25\x18\xd2\x74\x1c\x55\xe9\x59\x18\x67\xb2\x42\x32\x28\xf9\xc1\x9f\x33\xc6\xf3\x87\x05\xc6\x20\x36\xd4\x80\xff\x53\xdf\x12\x07\x7e\x38\xfd\xb0\x73\xc6\x73\x10\x5d\xa1\xe1\x16\x19\xba\x53\x21\xa7\x1b\x5f\x49\x93\x23\x4a\x11\x94\x8e\xa1\x10\xcf\xa2\x42\xbc\x23\xfa\xc9\xaa\xe4\x62\x60\x6e\x39\x64\x1c\xa7\x14\x7e\xeb\xba\x1e\xec\x55\x3f\xce\x94\xe5\x3e\x4e\x01\xb0\x73\xdd\x78\x0a\x2f\xf6\x78\xb3\x15\x72\xca\x11\xee\x08\x77\xe7\x56\xbc\xdb\x66\x53\xe5\xe1\xb4\xcb\xfb\x56\x9a\x9d\x60\xe3\xee\x33\x61\x82\xdc\xb9\xb2\x5d\x1b\xe6\xdb\xf9\xb5\xc7\x14\x6d\x77\x55\x85\x83\x4c\xab\xde\x02\x78\xae\xe5\xd5\x7c\x85\xe9\x83\xf8\x4d\x88\x33\xa9\xe1\x5b\xcc\x11\x19\x8e\x1c\x1d\xa6\xba\x59\x28\x21\x29\xf1\xdb\x96\x6f\x54\x60\xc8\xfb\x65\x30\xfb\xc3\xa9\x8a\x31\xfc\x0f\x4e\x9b\x33\x73\x66\xee\xc1\xdc\xe1\x08\xc8\x26\xd4\x90\x45\xab\xfa\x12\xee\x88\x79\x7f\x08\xf0\x68\x3f\xef\x77\xed\xaa\x35\x43\xb9\x1c\xb1\x18\xe4\x24\xd9\xc4\x08\xda\x54\x74\x31\x12\x51\x07\xd9\xb0\x74\x4c\x24\x43\xce\x99\x17\xe1\xe3\x28\xd8\x18\x50\xba\xbb\xc9\x4d\x92\x0a\x1d\x06\xe5\x24\xdb\xb6\xc2\x3d\xd8\x2e\x17\x87\x82\x2d\x71\xc4\xcd\xc4\x09\xae\x85\xba\x4d\xeb\x58\x1f\x93\x47\x48\xf7\x5e\x7a\x76\x9b\x9d\x68\xc4\x58\x9e\x59\x4e\x65\xcb\x6c\x8f\x49\x03\xff\xba\xbd\x5a\x32\x6e\x89\x44\x1a\x54\x2f\x8a\xc2\x64\xcc\xc6\x4e\x95\xa8\x98\x2a\x71\x0b\x6c\x56\xff\x7d\x10\x91\x6a\xfc\x40\x9e\xa8\xa4\x1b\x74\x67\x9d\xd6\xa7\x66\xf5\x9c\x52\xb9\x30\x5b\xa7\x33\xb1\x3c\x9e\x81\x1e\xe1\x30\x83\x92\x5f\x42\x00\x68\x2b\xd0\x5d\xea\x33\x95\x32\x52\x29\x70\xaa\x14\x9d\x00\x4a\x2e\xa2\x0f\xf4\x61\xe9\xec\x0f\x3b\x62\x56\x5c\x1a\x10\x62\x59\xc8\x36\x60\x5c\xc2\x7c\xad\xc9\x51\x5c\xb9\x97\x9e\x89\xaf\x28\x7c\x02\x7d\x75\xed\xbf\x87\xd5\xcf\xf6\x3a\x7f\xec\x9b\xd1\x0e\x78\x77\xab\x9b\xf8\x68\xd7\x34\xbd\x3a\x23\x74\xce\xf7\x02\x5c\xc4\xda\xb7\x10\xe2\x54\x80\x66\x85\xa1\x36\xec\xd0\x3e\x36\x77\x03\x46\x51\x3a\x15\x14\x5b\x89\x0e\xee\xf4\x7b\x80\xea\x08\xe4\x6c\x81\xd2\x02\xe5\x33\xe9\xa0\x6a\x38\xa6\xf7\x6e\xf5\x7a\x9c\x73\x6e\xc7\x8d\x00\xb8\x08\xe3\xff\xd9\xc7\x9b\x9d\xc7\xa2\xe5\x89\x90\x76\x56\xc9\x32\xab\x8a\x8b\x57\xda\x1a\x49\x5b\xa7\x45\x20\x15\xe7\x92\x4b\x52\x69\xab\x1f\x67\xbd\xb4\x3a\x35\x83\x14\x87\xab\x90\x02\xf5\x2d\x78\xb1\x34\xcd\x37\x51\x92\x5a\xaa\xb0\xb4\x5c\x8e\x6b\x0f\x2b\xf0\xcc\x9a\x46\x59\x31\x71\x08\xfb\xa9\x13\x6a\xab\xb0\x92\x1a\x58\xfb\xb9\xb5\x0e\x51\x24\x3f\x9b\x53\x18\x47\xdc\x96\x57\xe9\x6f\xba\xf7\xaa\x69\x8f\xe6\xfe\x44\xf9\x05\x90\x14\x4c\x70\x33\x72\x50\xc5\x8b\xc5\xdd"}, -{{0xde,0xa1,0x80,0xc9,0x1b,0x53,0x3a,0xaf,0x73,0x6b,0xc5,0xd3,0xc8,0xe4,0x74,0xd5,0xe5,0xd4,0x75,0xb7,0x5b,0x92,0xcd,0xe6,0xbd,0x1d,0x10,0xf3,0xb8,0xf5,0x5a,0xd4,},{0x30,0xb2,0x0f,0xb3,0x20,0xb0,0x0e,0x77,0xc4,0xe0,0xa8,0xeb,0x37,0x30,0xaf,0x3c,0x0b,0x1c,0x5f,0x5e,0xd9,0xee,0x2b,0x05,0x62,0x70,0x7e,0x4f,0x55,0xc4,0x93,0x8b,},{0xd0,0x83,0x33,0x3f,0xb8,0x4e,0x79,0xc9,0xb3,0x3e,0x55,0xe8,0x19,0x2d,0x57,0x1f,0xfc,0x8d,0xc5,0x07,0x45,0xb6,0xb5,0xfd,0xd8,0xc4,0x4d,0x92,0xa6,0x3f,0xd1,0x78,0xc4,0xe5,0x7c,0x2a,0xb3,0xa1,0x21,0x1c,0x0b,0xa2,0xd3,0x9d,0xa3,0x0b,0x06,0x62,0x9d,0x8d,0x1c,0xc1,0xd9,0xf2,0x59,0x32,0x63,0xd5,0x24,0xfa,0x5a,0x2e,0xbc,0x03,},"\x60\x61\x44\xb7\xd4\xf9\x6b\xef\x7f\x11\x2b\x6d\x41\xbc\xb5\x00\xd2\x13\x6c\x13\x4c\xed\xa2\x20\xe2\x4d\x0f\x15\x24\xec\xa1\x2c\x30\xf2\xb1\x02\xc7\xf3\x78\xd6\xbb\xa2\x59\xc5\xb4\xa5\xef\x8e\xc9\x30\x9d\x5c\x8d\xa7\xe8\xd2\xde\xd3\x79\x2a\xee\xea\x21\x08\xf7\x7d\x66\xb2\x30\x45\x93\x8e\xd6\x47\x51\xf2\x0d\x48\x32\x6b\xe2\xfb\x99\x62\x8c\xfb\x18\x73\xd7\xdd\x27\x58\x1c\x10\x5e\xc1\x32\x49\xa9\x52\xa5\x07\x84\xb8\xb3\x4c\xb3\xb2\xc1\xa0\x04\xfa\x8b\x62\x8a\x07\x67\xfa\x9a\xbf\x05\x8d\x95\x5d\xf8\x5d\x13\x4a\x0f\xc7\xf4\xb7\xd7\xfb\x0c\x8d\x31\xbc\xe3\x45\xdd\x0a\x42\x82\x14\x5a\xfb\x2f\xf1\x97\x51\xf2\xcc\x3a\x1c\xae\xa2\x42\xba\xaf\x53\x87\x49\xbf\x38\x80\x00\xe3\xdc\x1d\x73\x93\x59\xdf\xeb\xae\x64\xae\x1e\x10\xfb\x6f\xc1\x7c\xc9\xfb\x95\x05\x35\xc2\xde\x12\x95\x87\xa8\x68\x59\xb7\xbe\x36\xdf\xe9\xb6\xc1\x14\x1b\x25\xe0\x91\x5c\x8d\x4a\xa1\xcc\xea\xe7\x04\x6b\x3d\x7c\xfa\x94\x0b\xc9\x8d\x4d\x69\xfc\x5a\x30\xdd\xe1\xde\xe4\x2f\xb5\x27\x22\x81\xbf\x8f\x8e\x7f\x3e\x1a\x04\x39\x7f\xb4\xf3\xad\xef\xc5\x75\x32\xdd\xbd\xe3\x68\x33\xa6\x76\xe6\xf3\x9c\x82\xaf\xf6\xbf\x48\x32\xec\x97\x1e\x03\xbe\x38\x29\xc0\x2a\x20\x3c\x82\xd9\xeb\x8c\x16\x30\xee\x96\x93\xf4\x5d\x26\xf5\xf5\x1a\x31\x03\xca\x64\xd4\x68\xec\xea\xc1\xb2\x9a\xf4\xc4\x2e\xb2\x16\xd7\x6e\xc8\x99\x48\x36\xb4\xbe\xc7\x64\x89\xca\x50\x70\x68\x0c\x2c\x2e\xb4\x57\x21\x0a\x77\xc4\x7f\xdc\xbf\x60\x01\x72\x07\x3a\x53\xf1\x45\x3b\xb5\xc8\x04\x39\xc8\x82\xf0\x73\x6d\xe4\x06\x37\xb4\xf5\xab\x1f\x76\x1f\xf3\x55\xc6\xe9\xbd\x4a\xbd\xe7\x56\x0d\x5f\xc1\x13\xc8\x30\x15\x9a\x1b\x77\xc4\xe8\x7b\xc2\xc6\x98\x80\xa4\x0c\x58\x05\xec\xc8\xaa\xaf\x57\x57\x5b\xcc\xd8\x17\x7f\xc6\xb8\x35\x69\x23\x3c\x0f\x5c\xa2\x23\xac\x40\x13\xca\x10\x6c\xac\x28\x54\x70\x6a\xea\xd7\x14\xfa\x29\xf2\x86\x0a\x5f\x97\x53\x26\x8a\x36\x71\xd9\xf5\x9c\xde\x60\x48\xcf\x0b\x89\x86\x05\x0f\x7f\x54\x9e\x4f\xd7\x55\x7f\x2f\xc3\xfc\xdc\xcd\xdc\xef\xda\x58\x6a\x64\xb3\x00\x6e\x58\x25\xf2\x7c\xa3\x16\x87\xca\xf6\x63\xbd\x90\xa0\x5b\x11\x52\xd7\xc8\x8d\x7f\x10\x51\xa9\xd7\x91\x74\x86\x51\xd8\x88\xa6\xa1\x2f\x22\xd6\xc8\xc3\xf7\x8c\x2b\x86\xea\xf5\x39\x4b\x4e\xf7\xee\xfb\x89\x79\x7b\x25\xe5\x42\xdc\x93\x10\x2d\x02\x1a\x1d\x0b\xed\x6a\x7d\xcd\xd8\x10\x2b\x8f\x04\x30\xa0\xbc\x21\xd9\x04\xa3\xc9\x34\x6c\x01\x83\x43\xdd\x99\x37\xcb\x35\x25\x00\x07\xa2\x84\x82\x5d\xb0\x8e\x9a\x11\xfe\xe3\x1c\xff\x7a\x31\x4c\x48\xc4\x2d\x8b\x31\x4a\xcc\x27\x82\x2a\xf0\x3d\x19\x54\xc7\xcc\x8b\xf9\xad\x4e\x9e\x98\xf4\xad\x4e\xfb\x35\x52\x88\xda\xa8\xc9\x0d\xe9\x03\x7e\x64\xa7\x86\x1f\x5e\xe4\x3a\xda\x9f\x0f\xcc\xde\x34\xd0\xbc\xf5\x02\x88\x55\x0f\x70\x0f\x21\x5a\x79\x44\xa5\x38\x0e\x2a\x8e\x3f\x04\xf2\xb4\xf5"}, -{{0x9d,0xaf,0x6d,0xbb,0x7f,0x76,0x29,0x66,0xe7,0xa5,0x7c,0x2e,0xc1,0x99,0x6e,0x9f,0x5b,0x55,0x5b,0x98,0x66,0xb8,0xe3,0x1d,0xea,0xab,0x43,0x56,0xeb,0x13,0x81,0x6e,},{0xf0,0x21,0xb5,0x5a,0x36,0xd9,0xfb,0xfb,0xf2,0x97,0x8b,0xc0,0xdf,0x73,0x6b,0x28,0x9c,0x82,0x41,0xd6,0x43,0x53,0x09,0x84,0x1a,0x13,0x4b,0x07,0xd4,0x7c,0xe4,0xed,},{0x49,0xb6,0xbc,0x46,0xb7,0xab,0xb5,0x69,0x4d,0xa9,0x42,0x15,0xef,0xc4,0xb3,0x0e,0xea,0x04,0xae,0x2e,0x73,0xeb,0x2d,0xa8,0xe8,0xc9,0xef,0x9b,0xe2,0x22,0x24,0x98,0xb1,0x7e,0x13,0x93,0x96,0x46,0xc2,0x9e,0x32,0xd6,0x45,0x58,0x46,0x40,0x64,0x15,0x90,0xb1,0xbb,0xdb,0xfe,0x24,0xf3,0x6c,0x6f,0x69,0x4b,0xf8,0x72,0x38,0xee,0x04,},"\x54\x45\x23\x90\x0d\xaa\x67\x78\xc0\x39\x1a\xe4\x04\x4a\x51\xc0\xc4\xa5\xe4\x44\x13\x3f\xbd\x77\x47\xd5\x39\xa7\x44\xfa\x60\xab\x5d\xc5\x4e\x18\x19\xdc\x8e\x56\x89\x9c\x56\xef\xd7\xef\x3d\xa3\x41\x79\x0e\xcc\x49\x64\x5e\xf3\x25\xc6\x56\x8a\xe9\x71\xd3\x0d\x21\xbb\x7f\x23\x46\x4f\x46\xa2\x4b\x80\xd4\x9b\xb9\x3c\x6e\x91\xde\x79\xb2\x43\x31\xd0\x70\x7f\x43\xd0\x66\x5d\x01\x97\x74\x3a\xdf\xf6\x90\xd6\x15\xa1\xc9\x25\x87\x77\xfc\x47\xd0\x21\x71\x42\x42\x6a\x47\x34\x89\x2e\xb6\x22\xab\x8e\x50\xbb\x12\x8e\xc3\xa8\x95\x26\x6a\x38\x61\xa3\x97\x68\xbc\x76\x09\x6f\x58\x1f\xd0\x82\xdf\x9b\x72\x23\xe8\x5a\x8a\xfb\xdb\x5c\xaa\x49\x22\xaf\x2a\x01\x4b\xf8\xa5\xcd\x11\xe5\xc5\xea\x93\xe9\x1c\xd4\x6d\x5a\x1b\x99\xb8\x5a\x26\x70\xe3\x21\xde\x2e\x32\x25\x5a\xfd\x67\xfe\x2c\x37\xfd\x93\x2c\xac\xa2\x2d\x24\x1f\xaf\x4c\xce\xfe\xff\x58\xd6\xbd\x04\xcf\xaf\x11\xde\xdd\x29\xc8\x71\x9f\xfc\xb0\x2e\xf6\x5c\x5d\x3e\xb7\x8b\x4f\xc0\xd1\x70\xa2\xe3\x43\x2c\xc8\x12\xf0\xd0\x41\xd9\x76\x0c\x13\xc1\x2f\x7c\x7f\x2f\x84\xfe\x5e\x0f\x70\x0c\x10\xb1\xa6\x9c\xa4\x66\xa7\x0b\xde\xff\x8d\xbe\xc7\xd3\x18\xfb\x09\xdd\xd8\x27\xef\x61\xca\xa6\x91\x0b\xbc\x06\x1c\xbd\xa2\xb5\x27\xef\x2e\x59\xed\x4c\x17\x22\x99\x72\xf8\x95\x67\xd7\x05\xde\x92\x31\x92\x4b\x41\xbb\x6e\x7c\x01\xfe\x85\x42\x64\x47\x4f\xa7\x6b\x1f\x88\xcd\x57\xea\xc3\x11\x17\x1a\xf1\x03\xd2\x30\x78\x42\x4a\x12\x67\x5f\x2f\xa3\x6c\x2d\xe0\xbf\x53\xc2\x95\xfe\xeb\x31\x57\xde\x95\x89\x22\x98\x6e\x32\x51\x3d\xfa\x33\xb3\x5e\x15\xc3\x94\xa1\x1c\x0f\xcc\x55\xb8\x2d\x6d\xd0\x59\x7c\xdd\xd2\x7e\xde\x7d\xe1\x29\x85\xa6\x16\xe6\x40\x26\xbe\xfb\x5d\x69\x04\x82\xb3\xff\x22\xc0\xdd\x21\xf2\x7a\x08\x6d\x37\xa0\x49\x9e\xa3\x6f\xe2\xc4\xb5\xa9\x59\xd1\x0e\x9a\x61\x0c\xab\x1f\xe0\xd2\x8c\xf1\x01\x3d\xca\xe6\x3d\x8f\xde\xe0\xec\xbd\x8b\x4e\x19\xd5\xd0\x40\xe2\xfa\xd7\xd0\x41\x3a\x38\xe8\xc4\xe7\x35\x52\xad\x46\x04\x7b\x5b\xbd\xd1\x5c\x09\xcc\x0d\x34\xe4\x8b\x91\xfd\xba\xe2\xa9\xd1\x62\xd4\xb2\x1e\xe2\x0a\x1e\xf5\x35\xea\x88\x35\x95\xbc\x49\x51\x69\x2a\x67\x16\x34\x54\xc7\x36\x7f\x13\x4b\xf6\x45\xd4\x8f\x99\x69\xe3\xd4\xf0\xf9\xea\xf4\x14\x4c\xe9\x80\xa0\xa2\xe3\x34\x2c\x74\x6c\x2b\xdc\x3c\xcd\xc2\xf8\xa7\xda\x57\xa0\xe8\x02\x87\x82\xd3\x0a\xf5\x85\x7d\x9e\xfb\x37\x66\x6d\xf6\x5d\x7c\xc3\x84\x71\x66\x61\xe6\x1f\xf5\xc0\x97\x52\x59\x5e\x94\x11\x2c\xa1\xa8\x40\xd6\xe4\xf6\xec\x0e\x55\x49\x4c\x5b\x44\xf7\xc0\xf0\xd4\xa9\x9c\xd7\x09\x05\xbf\x84\x85\x56\x17\x48\xf4\xdc\x0f\xd7\xa4\x4a\x1b\x13\x91\x13\xc3\x8a\x1e\x8e\xb5\xc7\xa2\x0f\x3e\x95\x2e\xae\xa8\xce\x38\xb2\x07\xc2\x8e\xd9\x72\x71\x8f\x03\x1f\x47\x7c\x62\x07\xce\x43\x3c\x51\x5f\x5a\xc2\x84\x0f\x49\x74\xf1\xf1\x69\x89\x62\x6c\x76\xbc\x98"}, -{{0x71,0x86,0xf8,0xd1,0x68,0xd9,0xdd,0xf1,0x7e,0xdb,0xaf,0x0e,0x7b,0x1a,0xbc,0xb2,0x6d,0xa3,0xe4,0xc0,0x27,0x2d,0x98,0x79,0xc7,0xfd,0xff,0x64,0x21,0xc4,0xea,0x50,},{0x96,0xb4,0xa6,0x56,0x23,0x20,0x29,0xfc,0x1b,0x83,0x64,0x70,0x3c,0xbe,0xa7,0xa5,0xd7,0x38,0x75,0x18,0xa8,0x8c,0xed,0x1a,0x91,0x5e,0xc8,0xd8,0x86,0x84,0x81,0x32,},{0xa9,0xc0,0x49,0x9f,0xc2,0x16,0xa1,0x45,0x32,0xd7,0x36,0x36,0x5c,0x63,0x55,0xf9,0x38,0xf8,0xd8,0x19,0x4f,0xa1,0x13,0x28,0x48,0xf8,0x3e,0x49,0x04,0x54,0xd4,0xbb,0xf6,0x92,0x69,0xf1,0x22,0x59,0xfc,0x6c,0x07,0x4c,0x10,0x15,0xe4,0x25,0xe4,0xf4,0xf2,0x7c,0x02,0x9c,0x93,0x33,0x49,0x51,0x36,0x1a,0x35,0xad,0x11,0x76,0x54,0x0e,},"\xa3\xe6\xcb\x6b\x84\xcc\x5c\xf1\xfb\x1a\x84\x8b\x4b\x8e\xa7\xcb\x7c\x87\xe0\x44\x57\x50\xc6\x1f\x9a\xa5\xd7\x7d\xed\xdf\x94\x94\x63\xec\xd3\x9b\xfc\x71\xf2\x61\x0c\x2a\x94\x24\x84\x7f\xb7\x6f\x84\xc5\xda\x1f\xa1\x0e\xf7\x18\xa3\x45\x66\xce\xc1\xb3\xe8\x99\xe7\x25\x2e\x8d\x4d\x34\x60\x16\x49\x8f\xf1\x19\x97\x27\x50\x06\x16\x60\xba\xed\x31\x28\x27\x58\x31\x81\x07\x3d\x1d\xc7\x4b\x76\xc4\x30\xca\x30\xd4\x09\xe4\xe8\x43\x9c\x0f\xc4\x8c\x00\x68\x06\x29\xd4\x3a\xe2\xa7\x7d\x69\x22\x8f\x7f\x8a\x12\x53\xaf\x15\xbd\x2c\xb6\xbb\x1c\x16\x96\x55\x0c\x4c\x79\x0f\x44\x98\x69\x63\x0a\xb9\x2b\x9c\x11\xcd\xe1\xf9\x61\xaa\x21\x03\xec\x23\xf7\xd9\xf0\xfe\x9c\x3c\x41\x32\x58\x2e\xfa\x79\xa6\x6a\xe3\x42\x6e\x51\x05\xb8\x0b\xfe\x5e\x04\xdc\x8b\xb1\xe3\x8a\x31\x10\xcd\x72\x98\x4b\x3e\xf0\x2a\x0c\xa6\x2a\xb6\x38\xcb\xcf\xbc\x8a\x6b\x59\x3d\x26\x13\xdc\x06\xec\x86\xfe\xe3\x4f\x65\x18\xd4\xa3\xfb\xdc\x15\x72\x37\x17\x45\x64\xda\xeb\x66\x74\xcd\xc3\x4f\x4d\x65\x37\xcf\x81\xd8\xaa\x9b\xdd\xbf\x3a\xed\xa3\x12\xda\xae\xee\x33\x6f\x9e\xd8\xbf\xf8\x1e\x29\x4b\xc7\xd4\x4d\x25\xcd\x78\x70\x72\xe6\xcb\x41\x4b\x65\xfb\x7a\x84\x6f\xc0\x65\x36\x7b\xa8\xe3\x7b\xef\xfd\xf0\xb7\xba\x8f\x98\xcd\xf1\xeb\x87\x0f\x4e\x8b\x71\x30\xfa\x34\x29\xd2\xe2\x4b\xce\x59\x94\xda\xf1\xaa\x65\xe5\xf6\x03\xb6\x31\x05\x3d\xc5\x10\xb2\xf0\x97\xe8\x6e\x9b\x9b\x55\x23\x02\x75\x79\x68\xd0\x13\x6e\xe6\x75\x4c\x42\xa3\x2c\x99\x0a\xdd\x9c\xb5\x29\xbc\x89\x75\x1d\xfa\x4e\x5e\x3a\x0b\xad\xaf\x4c\xc4\x0b\x6a\x09\x50\x7f\x9f\xcd\x24\xc3\xca\x72\x25\x95\x99\xc6\xee\x58\xd8\x57\xb3\xa1\x89\xe0\x48\x90\x2e\x88\x5a\x36\x07\x42\x60\x93\xcb\x0f\xab\x43\x7c\x0f\xb0\xed\x2f\x1e\x96\xe9\x44\x1a\x7e\x95\x4f\xe3\xef\x76\x46\xe2\x6a\x39\xa0\x70\x33\xd0\xa1\x55\x5d\xfe\xed\x9a\x6f\x57\x79\x4a\xf3\xa2\xab\xf0\x05\x7e\x9f\x85\x3a\xe5\xc3\x01\x38\xfd\x80\xe2\xf2\x9c\x2f\x4a\x93\xad\x31\x45\xda\x10\xa3\xe3\x1c\xe9\xff\x97\x86\xac\x65\xd8\x60\x37\xd9\x8b\x7a\xa6\xd1\x1d\xe8\x80\x00\x10\xe1\x33\x86\x9e\xb6\x7a\x50\x39\xb9\xb8\xfe\xb6\xef\x90\x3d\x0c\xc7\x46\x41\x26\x07\xda\x72\x5c\xe2\xdc\x6a\x35\x21\x09\xdb\xc6\xa5\xe4\x0b\x17\x0c\x23\x05\x0b\xc4\xfb\x1e\xfa\x0c\x34\xfe\xc0\x0e\xae\x32\x19\xc2\x90\x40\xe8\xf5\x97\x8c\x93\x84\xee\x91\x5d\x8c\x93\x98\xdd\x12\x0d\x5c\x3c\xba\x38\xf8\x52\x6b\x06\x19\x7c\xb2\xc2\x61\xde\xc7\xd7\x26\xae\x13\x0f\x9b\xee\x17\x26\x17\x00\xe9\x99\x31\xfa\xc4\xb4\xdc\xa0\xf7\x58\x70\x1a\xcb\xf3\x70\x7d\x47\xdf\x53\x21\x13\x0e\xc1\x0b\xb3\xb1\x30\x78\xc4\xdc\x5d\xe3\x47\x0f\x15\x8b\x57\xdb\xeb\x87\x8b\x3a\x85\x24\xe0\xed\x2c\x95\x47\x54\x5f\x0f\xdd\xf1\x31\x25\xe4\x5b\xb2\x3d\x6a\x7b\x38\x3a\x18\x7f\x4c\x5d\x54\xa7\xb4\xc8\x3d\x59\x57\xf2\xcd\x7e\x6f\xbc"}, -{{0xe8,0x6e,0x8c,0x62,0x56,0x6e,0x15,0x75,0x3b,0xd5,0x57,0x7e,0xaa,0xe7,0xf2,0x41,0x05,0xb7,0x40,0x55,0xa2,0x56,0x29,0x58,0x07,0x08,0xbf,0xc8,0x3a,0xeb,0xf0,0x6c,},{0x8c,0x8c,0xe8,0x82,0xd5,0xf7,0x65,0x86,0xd8,0xdd,0xcc,0xc5,0x57,0x9b,0xcc,0x1c,0xdf,0x4c,0xfd,0x71,0x62,0x30,0x4c,0xb1,0x0e,0x76,0x96,0x02,0x6e,0x70,0x7f,0x17,},{0x54,0xd2,0xfd,0x44,0xac,0xf9,0xe2,0x09,0xbc,0x7e,0x43,0x33,0x72,0xbd,0x73,0x07,0x4d,0x07,0x80,0x6a,0x77,0xc6,0xce,0x22,0x8e,0x9b,0xe9,0x94,0x41,0x8b,0x00,0xc7,0xec,0xbc,0xb7,0xac,0x00,0x6c,0x29,0x4a,0xec,0x9d,0xe6,0x68,0x57,0x2a,0xdd,0x51,0x7c,0x06,0xb4,0xeb,0x4f,0xe2,0xff,0x35,0x23,0xbf,0x04,0x3d,0xf4,0x4d,0x3d,0x0d,},"\x12\xfa\x63\x1b\x0e\x48\x2e\x9b\x9d\x63\x3e\x94\xb8\x2d\x8a\xb4\x36\xfe\x54\x8e\x5b\x95\xda\x92\x62\x46\x23\xd1\x3f\x2c\x70\xda\x77\x5b\xa1\x36\xc5\x22\x9c\x16\xa0\xc7\xa6\xfa\x91\x4b\x2f\xed\xa5\x64\xe1\x72\x19\xe4\x73\x70\xf9\x51\x5b\xb1\xd5\x9d\xe6\xe9\x58\x62\x04\xd9\x43\xdc\x56\x0d\x73\xe2\xe7\x57\xf7\xeb\x39\xbb\xc7\x11\x1b\xb4\x6b\xc6\x43\xc1\x3f\x60\x21\x12\x73\x9b\xec\x77\x8d\x7d\x4f\x49\xd0\x92\x56\x3d\x68\xf5\x77\x6e\x43\x0e\x3b\x0b\xf2\xdc\x1b\x01\xbe\xb3\x04\x01\x96\xda\x63\x02\x90\x8b\xfe\x91\xe0\xfc\x38\xe0\x4c\x15\x0e\xf9\x07\xdc\x73\x6c\x44\x5f\xf2\x1f\xdb\xd2\xdc\x1e\xac\x0a\x0f\x5d\x00\xa3\x0a\xf0\x28\xaf\xe2\xff\x61\x16\x2b\x75\x8c\x7d\xa9\xa7\x76\x66\x6a\x11\x23\x59\x43\x1c\x48\x85\x6a\x87\xca\x82\xd3\xdd\x1c\x8a\xf3\x76\x59\x86\x35\x43\x2b\xf8\x91\xbe\xcb\xc3\x3a\x8f\xda\x44\xce\x88\x3e\xa8\xaf\x4a\xd8\xb9\x1a\x92\x61\xce\x76\xb9\xe9\x39\xc4\x61\xfa\xc5\x3a\xe0\xf0\x76\xe8\x2d\x87\x9a\xac\xe8\xf3\x8f\x12\x0b\xc9\xb0\x4d\x81\x25\xed\x24\xbc\xd7\x79\xd9\xd2\x43\x86\xb1\xdd\x20\x17\xeb\xee\x81\x97\x37\x6e\x8c\x36\xfa\x3a\xef\x8c\x1e\x71\x3e\x2b\x8b\xce\x49\x66\xd8\x48\x88\x68\x1b\xa7\x84\x95\xfb\xd1\xd6\xcc\xa5\x86\x26\xe6\x85\x4c\xda\x60\x6b\x83\xd6\x29\x3d\x01\xe8\xe3\xe1\x3b\xbf\x4a\xac\x85\x1d\x9a\x1e\x00\xd0\x02\x4e\x26\x99\x3b\x0b\x30\x91\xbe\x7e\x80\x61\xbc\xbb\x3c\xbb\x23\x02\xce\xab\x96\x89\x7a\x8e\x1f\xf3\x67\xec\x86\x25\x69\x3c\xf3\x15\x34\x12\x4a\x9d\x5d\x72\x5b\xca\xe0\x01\xd6\x7b\xc2\x11\x1d\x0a\xb8\x11\x1f\xa1\xd2\x4e\x4e\xd0\x6d\x63\x58\x3c\xe6\x90\xf2\xa0\x46\x26\xd7\x91\xd2\x9e\x3e\x31\x5a\x41\x5b\xf2\xe8\x53\xa5\xf2\x97\x4c\x83\x3a\x3f\xe2\xe2\x90\x9c\xf6\x69\xc7\x3c\x1f\x59\x39\x2d\x30\xc3\x7f\x3b\x9c\x5a\x3d\xdc\xfd\x75\x62\x1f\xda\x36\xe4\xba\x2f\x16\x14\x78\x58\xf6\xf2\x06\xb9\xa1\x40\xf1\xdd\xc1\x46\x6c\x9a\x53\xed\x73\xf8\x24\x90\xbc\x95\x32\x2c\x95\x5f\x61\xd1\x1c\xb5\x1d\x5e\x8a\x58\xc6\xb3\xcb\x0f\xdf\x04\x19\x76\x32\x01\xbe\xea\x93\xa8\x51\x2b\x14\x05\x24\x5b\xfc\x38\x41\x55\xad\xc5\xce\x77\x8a\xa7\x4d\x00\xa3\x22\x72\x64\x65\x11\x9a\xf7\x95\x01\xf0\x40\xdd\x0a\x7a\x84\x06\x00\x01\xca\x89\xd2\xfe\x5e\x9c\xf9\x77\x9a\x54\x7e\x3e\xbd\x3b\xf8\x64\x29\x90\xa3\x69\x0e\x2b\x2c\x3e\x54\xcb\x7e\xee\xea\xbc\x24\x2b\x4d\xd9\x92\x74\xc4\x25\xa8\x67\x93\x1c\x92\x9c\xa7\x08\x08\x60\x1c\x39\x08\xcf\xd7\x88\x86\x7d\x68\x7d\xc3\x66\xe9\x76\x35\x0c\x9e\x70\x58\x4b\xd3\x90\xd6\x7e\xeb\x7c\xfe\xa2\x6c\x42\x68\x6d\x3d\x96\x20\xf6\x2f\x64\x10\x4e\xf4\x1e\xd1\xd1\x30\xd7\x9e\x32\x59\x38\x48\x62\x96\xb7\xab\x2d\x2a\xdb\x78\x52\x67\x43\xe4\x00\xac\xb2\xb7\xaf\x09\x62\x8d\x68\xcf\x94\x75\x10\x16\x25\xc2\x0e\x1d\xc0\x51\xd7\x3c\x99\x7c\x95\x2e\x12\x81\x2c\x80\x5b\x68\xff"}, -{{0xa5,0xca,0xb2,0x72,0x7e,0x2f,0x13,0x1a,0x4d,0x63,0xfa,0xce,0xe7,0x99,0x33,0x66,0x63,0x93,0x0a,0xa0,0x7a,0xfd,0xa6,0xbd,0x5a,0x8e,0x98,0x5a,0x02,0xde,0xb1,0xea,},{0xac,0x35,0x5f,0x95,0x26,0x0f,0xbf,0xea,0x77,0x8c,0x55,0xb5,0xaf,0x8b,0x3f,0xd1,0xf2,0x4d,0x26,0x93,0xda,0x35,0xde,0x4e,0xe5,0x08,0xa2,0x7e,0xd3,0x50,0x39,0x1f,},{0x13,0x8c,0x7a,0x8e,0xca,0x5b,0x5c,0x37,0x15,0x88,0x13,0x84,0x3c,0x9a,0x90,0x4e,0x5f,0x53,0x0a,0xd9,0x71,0xee,0x43,0x2a,0x44,0xf3,0x44,0xf8,0xc6,0x4b,0xbf,0xaf,0x10,0x2f,0xf4,0x1d,0xaa,0x5c,0xf7,0x22,0xa4,0xbc,0x66,0x40,0x58,0x87,0x59,0xb8,0xf3,0x6f,0x9c,0x05,0x9e,0xab,0x93,0x6c,0xc4,0x5e,0xd4,0x79,0x63,0x94,0xa0,0x02,},"\x48\x34\x39\x15\x4d\xd5\xe5\xd1\x09\x85\x7c\x24\xd1\xc4\xe7\xfb\xbe\xfd\x2f\x38\x65\x1d\xa8\x12\x89\xf2\xad\x3d\x61\x54\x30\x65\x38\xb8\x2a\xc7\xdb\xa9\x21\x0e\x74\x07\x76\xed\xe4\xcc\xf5\x1d\x4f\x63\x09\x4b\x03\xe4\x6a\xd3\xaa\x3c\x31\x94\x7d\x8c\x36\xce\x6f\x94\xe8\x52\x96\xbd\xed\xcc\x1e\xad\x62\xea\xa1\x44\x1e\xcd\xe0\xa2\x25\xd0\xbf\x02\xed\xca\xcf\x86\x50\x14\x89\x9a\xf6\x6d\x98\x08\x04\x0c\x2d\x02\x00\x0a\x0f\x5c\xe4\xf1\x68\x3c\x1a\x49\x52\x76\xd9\xc4\xd7\x28\xc9\xec\xd6\xf0\x78\xdb\x8a\x0c\xfc\x26\x71\x87\x23\x85\x62\xab\x1a\x1e\xa2\x81\x3f\xb4\xf1\x2e\x87\x8e\x1b\xa1\x43\xf4\xd0\x6a\x3b\xc8\x10\x0c\x35\x50\x11\x8d\x69\xda\xe6\x7b\x55\xed\x69\x2a\xcf\x94\x44\xda\xa5\xc3\xe3\xc0\xa9\x8e\xe2\x8c\xf1\x72\xde\x0c\x58\x4c\x9f\x2e\xc9\xbb\x6e\x9b\x57\xf5\x72\xa8\x6f\xf8\x72\x9f\x65\xf4\xc6\x5b\x7f\xea\xcc\xaa\x21\x72\x0e\xd7\x9e\x90\x61\x8b\xca\xfb\xfd\x95\x33\xda\x85\x23\x2b\x45\x08\x83\xaa\x91\x9f\x82\x7f\x04\xc4\xa9\x7b\xf5\x13\x90\xd4\xf8\x56\x9c\x19\x17\x26\xf4\x4f\x7e\x39\xfb\x3d\xb7\x3b\xfc\x41\x5b\x6f\xfc\xa8\xb9\x1a\xca\xad\x69\x23\x85\x72\xf1\x4b\x49\x98\x5e\xa0\x3c\x98\xd7\xb1\xd4\x4b\x3a\x65\x54\x76\x5b\x19\xab\xf9\xb2\x52\x74\xe9\x7e\x46\x34\xe4\xb0\xf9\xe8\x02\xeb\x6f\x74\x3f\xff\x95\x07\x57\xee\x01\x3a\x69\x88\x22\x18\x81\xa7\x44\x3f\x1f\x32\xbc\xcb\x00\x7e\x99\x37\x9c\x7c\xa4\xf9\x06\xd5\xfe\x11\xcb\x12\xf6\x6b\x53\xa3\xd2\x1a\xc9\x47\xbe\x0c\x81\x50\xbc\xd0\x4f\x1c\x81\x6b\x3f\x0c\x07\xc5\xfb\xc0\x90\x5a\x71\x36\x95\x68\x49\xda\x03\x83\x6d\xae\xc2\x5c\x3e\x1a\x06\xec\x3a\xeb\x20\x56\x48\x17\x6f\x89\xf4\xa2\x91\xfa\xc4\xf1\xd3\x89\x9f\x56\xc9\x06\x5e\xeb\xb8\x76\x8b\x84\xb3\x1b\x7c\xc0\x31\x08\xbd\x08\x88\x33\x8d\x17\x74\x99\x49\x70\x29\x2d\x93\x50\x31\xfe\xa3\x35\xd9\xe7\x90\x8f\xe0\x25\x48\x89\xc0\xb1\x71\xcf\xe0\xaf\x2e\x6f\xde\x7a\x5e\xa3\xde\x1f\xdc\xda\xe5\x37\xb6\x31\x31\x19\xc2\x7f\x77\x20\x24\xef\x36\xe4\x5c\x8b\x89\xf2\x6c\x93\xd9\xee\xa1\x37\x25\xe1\x2d\x81\x0c\xf9\x82\x4a\xea\x04\xcb\x80\x2d\xa7\xe4\x58\xe8\x42\xca\x37\x5e\x36\x71\x34\x6e\x00\x89\xde\xc5\x71\xbe\x16\x9b\x0d\x90\x96\x6b\xf3\x68\xfe\x36\x98\xfd\x3e\x72\xbf\x16\x24\x9d\xd9\x00\xaf\x6d\x29\xff\xa4\x83\x51\x36\x0f\x12\x24\x17\x14\x58\x5f\x7a\x9b\x4c\x7b\xaf\xc9\x52\x22\x67\x35\xde\x14\x62\x74\x3d\x78\xab\xad\x0f\x67\x11\xf2\x49\x5f\x33\x13\xad\x4e\x0b\xa2\x16\xb0\xde\xa5\xdc\x15\x16\xa9\x54\x9f\x7d\xfc\xfe\xb9\x3e\x59\x1a\xbe\xda\x5e\xa3\xc7\x04\x59\x06\x52\x3b\x40\x86\x8c\xa5\x73\x5d\x6a\x33\x71\xc3\xc2\x94\xc1\x11\x26\xd0\x97\xf4\xc7\x08\xe9\x04\x64\xc1\xad\x91\x42\xfa\x0b\xed\xf0\x7d\xfc\x5f\x4c\xb6\x7d\x6e\xd8\x0f\x1b\xfe\x72\x68\x3c\xfb\x2a\xd6\x65\x30\xdc\x43\xd7\x02\x3f\x37\x90\xff\x42\xd9\x5b\xd8"}, -{{0xcb,0x63,0x19,0x61,0x37,0x79,0xa4,0xef,0x66,0xbe,0x14,0x14,0x4b,0x28,0x40,0xad,0x01,0x67,0xc0,0x3f,0x3b,0x8d,0x04,0xff,0x59,0x2c,0xd1,0xd2,0xd7,0x22,0xe3,0x30,},{0x18,0xeb,0x03,0xf0,0xa3,0x34,0xb0,0x80,0xe1,0xaf,0x43,0x99,0xd8,0x37,0x6d,0x83,0xc5,0x33,0x31,0x6d,0xc6,0x87,0xcf,0x34,0x1f,0x0a,0xfa,0xb4,0x50,0x96,0x52,0x99,},{0xc1,0xb3,0x99,0xcd,0xc1,0x98,0xe9,0xa1,0x59,0xe6,0x84,0xfc,0x26,0x68,0x6d,0xe6,0x60,0xda,0x54,0xcf,0xe3,0x12,0xca,0x73,0x45,0xdf,0x0c,0x7d,0x15,0xa3,0x57,0x43,0x01,0x44,0x10,0xbd,0x2f,0x6c,0xd1,0x1e,0xef,0x33,0xa8,0x9b,0x3d,0x15,0xcb,0xc1,0x7c,0x7a,0x35,0x89,0x37,0xfd,0x99,0x72,0x05,0x05,0x1f,0x92,0x57,0xc2,0x56,0x09,},"\x87\x4a\x6c\x81\xd6\xdb\x71\x33\xa7\x91\x69\x76\x0c\x84\xd3\x6e\xea\x3d\x42\xea\x08\x92\xb7\xc8\xdd\xe8\x44\xa3\xa6\xb6\x0a\xa9\xf2\x66\x07\x26\xc9\xc4\xdd\x26\xa0\x1f\x4e\xd0\xdc\x1c\x53\xba\x60\x05\x46\x3f\x7e\xa6\x4a\x1e\xc6\x39\x53\xbc\x3d\x81\x05\x2a\x2f\x10\x84\x38\x9a\x77\x06\xdf\x74\xed\x41\x36\x08\x2a\xb5\xc6\xe8\xc7\xf4\x11\xdf\x9d\x3a\x0f\x3c\x40\xf5\xa6\x0e\x2d\x21\xa8\x54\x8e\x7a\x25\xde\xe3\x40\x30\xb3\xc3\xe7\x5c\xaa\x93\xdd\xaa\x9c\x19\x0c\xb6\xde\xda\x24\x13\xd5\x4e\x37\x3d\x43\x53\xdb\xa4\x3d\x39\x49\x1a\x2f\x56\xc8\xb3\x6d\x45\x01\x6f\x77\xd7\x47\x16\x91\x63\x45\x39\xe7\x6c\x4f\xb4\x19\x13\x47\x2b\x0a\x23\x05\x4f\x54\x8f\x54\xb1\xe7\x10\x9c\x8b\x65\x21\xb5\x7a\xe9\x81\xd0\x50\x31\x6a\x33\xc4\x9c\x71\x16\x26\x8d\xcc\x4b\x78\xc2\xba\xe5\x3a\x3a\xe4\xdd\x17\x8b\xb8\xb7\x6b\xb3\xbe\xfe\x19\xe4\x1a\x2c\xf1\x2c\xeb\xb7\x11\x68\xf9\x71\xf2\x02\x46\x1c\x63\xf7\xd6\xee\xf1\x07\xf5\xb1\x03\x0e\xdd\x4e\x75\x00\x9e\x91\x16\xc3\xcd\x0e\x8b\xdd\xc2\x99\xb4\x1f\x1a\x45\xe7\x84\xef\xa6\x46\xda\xda\x64\x06\x8e\x92\x48\xec\x98\x8f\x23\x26\x34\xad\x3d\x5a\xab\x19\x56\x0e\x83\x0a\x5b\xd6\x65\x45\x7c\x94\x29\x5e\x1a\xf0\x16\x0f\xbc\xe2\x72\xef\x48\x45\xdd\xf0\xc4\xf2\x4d\x97\x6f\x51\x86\x90\xea\x1f\x82\xff\x4d\xfa\x48\x13\x64\x1a\x67\x59\x8e\xa9\x84\x01\xe0\xff\x10\xa0\xe5\x82\xe2\xb9\x08\x67\xb4\xe6\x23\x2c\x34\xea\x49\x9c\x16\x99\x09\xa4\x41\x26\xf3\x77\xd8\xcc\x1c\x11\x90\x58\x66\x34\x0e\xfd\x1e\x7b\x07\x7d\xc7\x45\x6d\x59\xc9\xb9\x6a\x12\x4a\xac\x3b\x33\xbb\x22\x74\x41\xbb\x7a\x52\xe6\xc3\x14\x0d\x7a\x4f\x67\xca\x05\xbb\xc9\x3c\x93\x77\x5b\x92\x91\x19\xa2\x24\xed\x8f\x39\x00\x58\x20\xf4\x20\xcc\x6c\x53\x0e\x61\xe2\x0a\xdc\xa0\x1e\x93\x9c\xc0\x31\xdf\x49\xcd\xb1\xec\x8f\xf4\x93\xc9\xef\xbc\xad\x34\xc5\x71\x08\xef\xd7\x64\x55\x89\x66\xfb\x14\x70\xb0\x74\x5e\x69\x66\x19\x1a\x9a\x9e\x44\x58\x1b\x09\xfa\xf4\x69\xf9\x51\x53\x72\x03\xd9\x26\xbc\x8a\x55\xd0\x80\xa8\x05\x18\x1d\xd7\x29\x6e\xd2\x0a\x81\x82\x68\xf7\x55\xea\xa6\x6b\x08\x22\x42\xf4\xd0\x20\xf7\xcd\x67\x20\x89\x04\x84\xc0\x1c\x75\x7f\xe3\x5d\x87\xb5\xbc\x90\x6d\xea\xcc\x2e\x30\x71\xde\x46\x01\xbc\xf0\xdd\x6b\x83\x7c\x43\x31\x06\x04\x7f\xd8\xec\x9b\xd0\xe9\x8c\x9e\xe8\x06\xf7\xec\x8c\x5a\x10\xea\x21\x36\xf1\xf9\x0f\x90\x0b\x85\x3f\x95\x3f\x00\xb0\x76\xbd\x1e\xbd\x92\x9d\x08\xa3\x8b\xec\x68\xd8\x66\x43\x50\x47\xbc\xb6\x72\x1e\x06\xb6\x40\x85\xdc\x05\x58\xc1\xfa\x85\xa2\xc8\x3b\x0c\xaf\x4c\x81\x60\x84\xf1\x0a\x4c\x58\x85\x29\x5b\xca\x15\xff\x7c\x18\xe5\x96\xc6\x2c\x92\xee\x99\x21\xa2\x7c\x29\xd1\x95\xbd\x28\x22\x13\xff\x36\x60\xb6\xe7\x54\x6b\x4e\xaa\x77\x7c\xe3\x9f\xc5\xd2\x04\x84\xc7\x1e\xd6\xca\x06\xf9\xb7\x7a\xb1\xd8\x72\x39\x3a\xb2\xd1\x02\x55"}, -{{0xb2,0x98,0xad,0xf3,0x8a,0x67,0x08,0xf8,0xd1,0x8f,0xf1,0xed,0x96,0xbf,0xba,0xb4,0x21,0x54,0x0d,0x09,0x6c,0x4e,0x43,0x51,0xb9,0x22,0x09,0xb5,0xe6,0xaa,0xab,0x65,},{0x77,0x0e,0xdf,0x42,0xb8,0xa0,0x39,0xc6,0xca,0xb9,0xba,0x65,0xeb,0xfb,0x13,0x5a,0xbc,0x2d,0xa3,0x14,0xa4,0xc3,0x09,0xf4,0x6a,0x8f,0x32,0x5b,0x52,0xd0,0x65,0x93,},{0xe5,0x5f,0x8d,0x30,0x41,0x22,0xdc,0x17,0x5c,0xf0,0x27,0x46,0x74,0xfc,0x9d,0xed,0xfe,0xc2,0xb5,0xf8,0xa2,0xee,0xb1,0xe3,0xe7,0xf8,0xe0,0xdf,0xba,0x0d,0xac,0x2d,0x32,0xf4,0xe7,0x04,0xce,0x91,0xcd,0x59,0x91,0x84,0x13,0x3c,0x3b,0xf1,0x06,0x3d,0x2f,0xae,0x63,0xd7,0x3a,0xcc,0x57,0x72,0xd7,0x18,0xd8,0x11,0x83,0x31,0x86,0x02,},"\x9d\xf4\xd5\xd7\x56\x5d\x2c\x05\x22\x62\xdd\x34\xd6\x00\x7d\x86\xd9\xc0\xf0\x7c\x70\x89\xaf\x61\x19\xe3\x04\xf4\xd8\x01\x1d\x7e\xaa\xd7\x7b\x3e\xf7\x0c\xc2\x80\x84\x7d\x59\xf2\x97\x20\x2b\x7e\x18\x61\xae\xf3\x34\xbf\x38\xde\x14\x74\x0e\x80\x73\xc9\x55\xa8\x51\xd2\xcf\x3d\xad\xc3\xed\xce\x15\xbe\x49\x0e\xaa\x84\x5b\xa5\x53\xfc\x6e\x87\x46\xe5\x29\x15\xe6\x55\xaf\x4b\x86\xc6\x29\xd4\xc5\x22\x78\x36\x35\xd4\x64\xa2\x82\x57\x77\xd8\x9d\x70\x97\x67\x7e\xf0\xe5\xee\xae\x38\x53\x7e\xcb\x65\x6e\x3b\x28\xdd\x07\x35\x8f\xd9\xfb\x2c\xd4\x62\x51\x72\x86\x65\x9a\xef\xc7\x9d\x37\x4d\x1d\x13\xed\x93\x96\x7c\x53\x0c\xde\xa4\xf3\x14\xa0\xf9\x1d\x62\x89\xb4\xc7\xa4\x27\x9b\x6f\x4c\x4a\xbc\xa3\x33\x57\xf6\x9e\xd8\x4b\x91\x19\x63\x7a\xdb\x7c\x18\xe6\x94\xcb\x3c\x56\xe7\x36\x37\xda\x91\x07\x35\xd4\x3c\x38\xaa\x80\x86\x67\x5a\x06\xad\x37\x0e\x57\x26\x88\x1d\xa5\xe1\xa1\xdc\x61\x44\xd6\xa6\x2a\xff\x7f\xb0\xc3\x52\xd8\x8d\xc9\x71\xa3\xd7\x2d\x30\x71\xe1\x4b\x47\x42\x53\x56\xaf\x1b\x01\x92\x33\x53\x82\x61\x45\x1a\x99\xa6\xcf\x4a\x07\xce\x9a\xb1\xc3\x99\x0d\xe6\xab\x8d\xe2\x11\x6c\x75\x61\x05\xc5\x12\xb7\xa3\xee\xb3\x15\x7b\x15\x8b\x32\x1e\x44\x4e\x80\x6d\x89\x0b\x38\x90\xed\x9d\xdc\x86\x9f\x17\x11\x72\x3b\xb9\x9a\x72\xbd\xb9\x23\xd1\x31\xba\x4e\xdb\xfb\xb6\xda\xe9\x9a\x5c\x7b\x32\x8d\x31\x0d\xf9\xa6\xd1\xdc\xd8\x59\x18\x96\x28\x33\xe8\x9e\x20\xf5\xc5\xe6\x33\x3a\xc8\x61\x09\x4a\xe9\xe7\x99\xc8\x64\x1b\x9b\xae\xa1\x1a\x2e\x0e\xc2\x34\xbe\x59\x30\xe0\x28\x80\x85\x9c\xde\xc0\xd9\x78\x23\x7c\xbe\xa5\xc7\xc3\x2c\x11\x1b\xaf\xdd\x4b\xfb\xff\xe4\xfb\x34\x85\xef\xfe\xcd\x51\xbd\x19\x5a\x71\x40\x4c\xa5\xb5\x9a\xfa\x25\x2d\x7b\x5f\xf9\xd0\x30\xf4\x8c\x6f\xaa\xdb\xdb\xa9\x18\xf2\x1a\x0c\xd3\x9a\xf5\x69\x66\xdc\xcf\xa2\x5f\xb5\xa5\xcf\x9a\x4b\x26\xa7\xf5\x44\x1d\xf6\xe3\x20\xe3\x4b\x27\x39\x3d\xe2\xec\xfb\xd6\x9a\x15\x94\x90\x9a\x6c\x68\x5e\xc6\x45\xfc\xf3\x04\x8d\x01\x48\xfa\x38\xd3\xe8\xa6\x4d\xc3\xc2\x1a\xe4\x4d\xa7\xe4\x6a\x5e\xa7\x93\x6c\x2b\xa0\x83\x68\x9a\x78\xca\x3a\xc6\x0b\x87\xbe\x6d\x23\xea\x40\xf5\x96\x15\x83\x74\x28\x42\xe3\x75\x25\xa4\x9c\x5f\xe8\xfd\x15\xd7\xb0\xc9\xe8\xfc\xcd\x07\x93\x6d\x19\x53\x82\x12\xf7\x37\x3d\xbb\xf3\xdf\x7d\x46\xad\xf9\xd9\xf5\xdb\x09\x52\x4c\x65\xb8\x83\xae\x6f\x6c\xef\xa2\x4b\x19\xec\x48\xce\x28\xcf\xa7\x34\xd9\xbd\x6e\x77\x83\x7d\x1a\x14\xd6\xa1\x9d\x34\x5b\xfb\xea\x55\x9e\x7e\x6b\xfb\x71\xdd\xad\x83\xcd\x8d\xee\xab\x68\x7f\xe7\x3c\x05\x74\x88\xf8\xf2\xb3\xe2\xe2\x6d\x13\x00\x9f\x4d\x23\xe6\x61\x9a\x23\xc0\x69\x2a\xf7\x66\x69\x21\x7d\x5e\xbd\x46\x08\x5b\x39\x88\x90\xe5\xc9\x1f\xdb\x4d\xb5\xba\x40\xe7\x77\x3d\x51\x8d\x3c\xf0\x0c\x0a\x5b\x5a\x4b\x0f\x1b\x85\xd6\x29\x16\xa5\x9e\x56\x07\xb7\xb1\xeb\x80"}, -{{0xe9,0xcf,0x16,0xd6,0x96,0xf6,0x3b,0x59,0xe5,0xe2,0x5c,0x9e,0xe2,0xd7,0x5b,0xb0,0x5e,0xd2,0xba,0xa5,0x91,0xa7,0x55,0x7f,0x9f,0xb1,0x29,0xcf,0x98,0x3d,0xe0,0xba,},{0x6d,0x1a,0xe3,0x85,0xe8,0x0a,0x39,0x55,0xe8,0xd0,0xc5,0x93,0xa8,0x1f,0x43,0x1c,0xd4,0x32,0x67,0x1e,0x78,0xcd,0xba,0xfe,0x83,0xfe,0x58,0xdb,0xcd,0xb9,0x85,0x60,},{0x81,0x12,0xac,0x37,0xea,0xfb,0x74,0x9d,0x3f,0x4a,0x1e,0xa1,0x48,0x43,0x79,0xdf,0x3e,0x38,0x3b,0x01,0x9c,0x12,0xde,0x85,0x15,0xe3,0x49,0xe4,0xf6,0xf9,0x98,0x63,0x2e,0x30,0x96,0x83,0x47,0xa1,0xd1,0x5b,0x09,0xda,0x2e,0xb8,0x00,0xb0,0x3d,0x81,0x9d,0x20,0x2b,0xd1,0x0a,0x6a,0x46,0x3b,0xb0,0x2b,0x36,0x6d,0x68,0x55,0xfe,0x0e,},"\xa1\x0f\xea\x8f\xc9\x3e\xcc\xfe\x2a\x6b\x78\x26\x07\x95\x63\xad\xf8\xaa\x9a\x66\x64\x44\x93\x22\x00\xcc\xa9\x44\x7d\xd0\x27\xc5\xc7\x20\x4e\xa6\x2b\xf8\xf5\xe2\xe3\x91\x45\xac\x39\x48\xab\x3f\x31\x86\x88\x7b\x30\xbc\x60\x23\x30\x24\xb4\x83\xf3\xf5\x19\x03\x6a\x3e\x94\xc8\xd7\x51\x0a\x85\x3a\xc6\xe2\x0c\x6e\x52\x6e\xe3\xcd\xb7\x6d\xe6\x63\xf6\x73\x05\xad\x80\xdf\x23\x42\xc8\x50\x1b\x4f\x4a\x8e\xe3\x66\x5a\x79\x8f\xc4\x37\xdd\x81\x4e\x4e\x47\xe7\xa4\x66\x89\x0e\x0f\xfa\x8f\x51\x0f\x3e\x6e\x19\xc9\xc9\x69\xf7\x0a\x76\xe5\xcf\x30\x54\xd1\x7d\xe4\x59\xac\x8e\xe9\x95\x50\xbd\x38\x31\x9f\x36\xe4\x33\x43\x4a\x92\x6a\xd6\x8b\x96\x1e\x0c\xa1\x0a\xdd\x4b\xa9\x92\xb3\x65\x06\x60\xa2\xc3\xc2\x6f\x5d\x74\x0a\x31\xaf\xb7\x76\x3f\x54\x2f\x72\x3b\x8a\x3c\x92\xd8\xae\x92\xa5\x67\x76\x4e\xfc\x70\x53\x03\x12\xba\xab\xdd\x3f\xbb\xd5\x27\xfe\x0f\xcb\xca\x3f\x6a\x70\x64\xcd\xde\x18\x56\xe9\x7a\xb7\x86\xaf\x7d\x70\x22\xa9\xd4\x6a\x33\x8e\x8e\x17\x54\xaf\xd9\xad\xac\x85\x6a\x38\xde\x2a\x4c\x97\x66\xde\xe8\xdb\xc7\x09\xb0\x67\x1a\x6a\x6e\x6e\x1e\x5d\x12\x07\x4d\x22\x24\x5c\xd7\x3b\xee\xeb\x1b\xd8\xec\xfc\x1e\x85\xa2\x1b\xde\x25\x3f\x7c\x46\x5a\xbc\x1f\xea\xa9\x61\xc0\xff\x5c\xff\x2d\x89\x64\x72\xae\x17\xab\x84\x88\xe3\x3f\xfe\xfd\xb7\x2c\x10\x5e\x20\x4f\x94\x4a\xda\x51\xee\x13\x98\x1a\x13\x6c\x0f\x38\x42\x6e\x3e\x49\xb0\xe9\x18\x41\xc3\x27\x94\xd5\x2f\x13\x35\xdf\xa6\x37\xf1\x51\xc7\xe4\x0f\x9b\x83\x0a\xed\x53\x9a\xc5\x73\x1b\x81\xcd\xe3\x26\x4d\x22\xbe\xad\x31\xa6\xcc\x68\xd1\xa7\x31\x43\xb5\xba\x48\x16\x13\x92\x32\xf3\xf7\xf9\x79\x83\xf4\xec\xba\x64\xc4\x95\x53\xbe\x9d\x6d\x94\x3f\x91\xdf\xe0\x3d\x1e\xe8\x61\x8c\xd4\x0d\x2f\xb7\x23\x8a\x31\xd1\xbc\x38\xe7\x6a\x55\x1f\x9e\xee\x22\xe7\x3a\x27\xd7\xa4\x8b\x40\x87\x72\xea\x72\xc3\xed\x63\x7b\xb4\xb1\x68\xf9\xd7\xae\xad\x94\xea\x03\xbc\x11\x10\x99\x01\xc8\x89\x92\x7d\x51\xcd\xac\xf9\x62\x12\x59\x62\x55\x99\x79\xd3\xe4\xc8\xe3\xb5\xae\x58\x2f\x2d\xba\xd4\x99\x88\x02\x85\x6c\x4d\xf6\x9e\x8f\xb5\x49\x17\xe2\xf3\x6b\xb6\x7a\x19\xa2\x6e\x9a\x9a\x94\x85\xbc\xe9\x8d\xbf\xff\x0d\x2b\x02\xb9\x37\x7a\x91\x37\xa7\x34\xe5\x7b\x5c\xe6\x65\x05\x30\x17\xe9\x92\x67\x7a\x1a\xa0\x79\x24\x0d\x2c\xf9\x63\xcd\xf9\xbf\xea\x8d\x46\x00\x91\x23\x2d\xaf\x89\x80\x1f\xd7\x51\x71\xa6\x19\x5a\x5c\x04\x68\x15\x91\x4b\xe1\xf6\x28\x68\x78\x3d\x6f\x2c\xf2\x8a\xf9\x37\x8d\x6c\x68\x93\xe7\x5d\xe6\x41\x11\x1c\x68\x47\x27\xef\xfa\x31\xb8\xbc\x9b\x0a\x01\xdb\x9c\x9e\x81\xcc\xd8\xf4\xd4\xe8\x75\xd4\xbd\x90\xd2\x53\xf5\x89\x89\xa8\xa5\x2a\x20\x3a\x77\xa4\x96\xd6\x97\x98\x6b\x03\x1e\x9f\x69\x9b\xc6\xa1\x6c\xd5\xf9\xc3\x60\x18\xeb\xda\xa3\x6b\xad\x0e\x01\x4f\x4c\xf3\xb4\xb7\x46\x17\x1b\xf8\x93\x14\xe8\xb7\x2c\xbd\x47\xcc\x61\x6a"}, -{{0x23,0x8a,0x6d,0x49,0x79,0x32,0x1a,0x14,0xa9,0x97,0x23,0x6f,0x45,0x85,0x04,0x6c,0xf7,0xa0,0x5c,0x0a,0xdc,0x6b,0xa1,0xfd,0xb1,0x9e,0xc2,0xa3,0x2f,0x62,0xbe,0xeb,},{0x0b,0x4b,0xa6,0x74,0xe4,0x01,0x66,0x5b,0x67,0x90,0xcf,0xda,0x08,0x07,0x04,0xcd,0x90,0xe2,0xf3,0xd3,0xef,0xab,0x25,0x3e,0xd8,0xdc,0xfb,0xd1,0x8e,0x40,0x67,0x89,},{0x29,0x42,0xf7,0x08,0xc0,0xed,0xe4,0xcb,0x0d,0xde,0xf1,0x3b,0x85,0xd7,0x1d,0x72,0x13,0xe0,0x38,0x3d,0xd2,0x94,0xf5,0x34,0x13,0x5f,0xd6,0x9c,0xaf,0xbc,0xfc,0x0e,0x33,0x09,0x0a,0x2a,0x0c,0xa3,0xfa,0x57,0x2c,0x72,0xcd,0xf5,0x59,0x2d,0xe9,0x03,0xb1,0x58,0x44,0x95,0xab,0x63,0x99,0x81,0x50,0xf2,0xb3,0x93,0xa3,0xb3,0x40,0x0c,},"\x97\xcd\x61\x9a\x22\x51\xed\xa9\x16\x64\x64\x31\xd4\xcd\x15\x98\xc2\xd4\x4d\x06\xaf\x3e\x48\xbd\x18\xe3\xde\x7f\xb4\xbd\x4f\x78\xe0\x0a\x69\xee\xab\xde\x3f\x82\x06\x5c\xfe\xe6\xcd\x71\x1f\x07\xd2\x26\x37\x16\x1f\xf6\x85\xf6\x5a\x7d\xdf\x54\x55\x31\x97\xfd\x31\xc5\xc6\xb7\x1d\x9e\x36\x5a\x94\x1d\xce\x4c\x3e\x22\x5d\x19\xcc\x63\x3a\x7e\x12\x86\x2c\xd2\x3e\xbb\x7c\x74\xa7\x04\x85\x0f\x76\x1a\xc0\x24\x1b\xe5\x17\xce\x7c\x36\x09\x36\xce\x07\x25\x0d\x9f\x2e\xb2\x78\x71\x15\xee\xc3\x77\xe1\x13\x4d\xc0\x8f\x44\xeb\x0a\x2a\x2a\x27\x16\xf0\x01\x44\xa4\x9f\x01\x2a\x57\xb3\xcd\x06\xef\xeb\x3f\xae\x92\x0f\x28\x5c\xff\xd9\xa4\x01\xa0\xb9\x86\x59\x4e\x17\xb2\xc9\xc8\xfd\xab\x83\x5d\x9f\x3f\x5d\x47\x4b\xe7\x33\xc1\x92\x5e\xe6\xf0\x93\x86\x71\x10\x66\xc3\xfc\xd6\x45\xee\xb0\xfb\xe7\x05\x41\x69\xeb\x70\x9d\x4a\x3f\x0d\x16\xf2\x8a\x1f\xf5\x06\x6c\x84\x2b\xc6\x3e\x35\x9e\x92\x48\x5b\x38\x75\x7f\xf4\x6c\x27\xf7\x9d\x0c\xdc\xf0\xe1\x6e\x97\xe3\xc7\xb7\xe2\x17\x8d\xff\xd2\x70\x28\x2d\xd6\x12\x05\xd5\x85\x4d\x84\x1f\x0e\x3f\xc0\xe4\x82\xcc\x1e\xe4\x85\x52\xcf\xe6\x58\x93\x5b\x54\x27\xc3\x66\x23\x0a\xef\x79\xae\xf4\x02\x1d\x6f\xab\x5f\x18\x75\xcc\x84\x9e\x32\x1a\x75\x50\x0e\x9e\x1b\xa5\xdd\x59\x6b\x43\x8c\xf8\x8b\x23\x5b\x01\xa6\x76\x25\xc4\xbf\x84\xd0\x72\x4a\xe6\x88\x0a\x37\x85\xe3\x3b\xd9\x23\x5f\xd0\xf5\x98\x18\x04\xd2\x1c\xbd\x63\x3c\xb1\x80\xf3\x44\x56\x46\x02\x07\xa2\x90\xa2\x54\xd9\xfe\x61\x06\x3d\x40\x63\x4c\xa3\x87\x2f\x09\x35\xfa\x28\x32\x87\x95\xca\x41\xb0\x06\xa2\x11\x1f\xc5\x93\x2b\x1e\x77\x9c\xe9\x66\xcc\x47\xad\xb7\xc0\xdd\x98\x73\x33\xba\x75\x29\xa1\xa4\x99\x6c\xe9\xf5\x6e\x05\x19\x81\xfe\x1f\x55\x3e\x57\x8f\x43\xc3\xba\x94\xbe\xac\xc9\x3c\x3e\x73\x96\x67\xc7\xa7\xc6\xfa\x27\xe1\xe0\x81\x69\x5d\x20\xba\x70\x5c\x3f\x10\xb2\x0d\xf5\x30\xcb\xb0\xec\xb8\x74\x56\x50\x11\x09\x68\x70\x19\x31\x84\x52\x78\x5d\x38\xe7\x66\xb3\xcd\x35\xb0\x07\xd7\xe3\xcf\xe0\xb2\xcc\xa8\xaa\x6e\xf7\x39\x55\x99\xdc\xb9\xc4\xd2\x8b\xcc\x35\xc7\x6d\xfc\x35\x34\x3c\xb1\x34\x8b\xa3\xe9\x62\xf1\x0e\xe8\x6f\x86\xf5\xb6\xd4\xca\xe2\xe8\xc2\xb1\x85\xe3\xea\xa1\xae\xb8\x7b\xcf\xcf\x2f\xb7\x6c\xc7\xfc\xc6\x89\x50\x71\xb1\x68\xe8\xb7\xf6\xca\xa0\xfd\x63\x98\xe7\x78\xcc\x07\x91\x2f\xf5\xd6\xe6\x10\x21\xa8\xa5\x9a\xe0\x35\x21\x60\xf5\x6d\x54\x88\xfe\x2f\x2a\xcc\x94\x03\xda\x9a\x9f\xfc\x66\x1c\x1e\x9d\xc5\xbe\x88\xc4\x20\xdb\x0f\xd7\x7d\x84\x5d\xc8\xdd\x9d\x8e\x58\xf9\x96\x1b\x79\xaf\xc6\x86\x24\xba\xa8\x6a\xa6\x43\xa8\xa3\xc7\xed\xf7\x1d\x55\x3c\xc0\xd3\x22\x4a\x60\x69\xec\x67\x4f\x52\xda\x29\xa1\xcb\x60\xc4\x19\x23\x01\xa2\x43\x47\xa8\xaa\x83\x26\x26\x9e\x0a\x14\x78\x0c\x95\x83\xcd\xff\x51\x59\x27\xfd\x5b\xef\x52\x8f\x9d\x23\x78\x7a\xeb\x80\x3d\x70\xeb\x91\x6b"}, -{{0x59,0xd5,0x01,0x39,0x3d,0xc5,0x99,0x97,0x23,0x81,0x07,0x06,0xfa,0xd7,0xd6,0xef,0xd1,0x63,0xc4,0x47,0x10,0xc7,0x41,0xc1,0x85,0xc2,0x7e,0x04,0x25,0xe3,0xc0,0x5b,},{0x82,0x65,0xd4,0x3c,0xfb,0x07,0x35,0xb5,0xd7,0x25,0x0f,0xcf,0x0f,0xcb,0xd1,0x54,0xbf,0xc0,0xee,0xcb,0x13,0xb7,0xad,0x93,0xb6,0xb0,0x29,0x40,0x58,0x8b,0x84,0x3b,},{0xe6,0x46,0xf1,0x64,0xcf,0xed,0x8c,0x2e,0x06,0x07,0x10,0xdc,0xfb,0xc3,0xe9,0xfa,0x5e,0xb3,0x96,0x37,0x68,0x13,0x19,0x01,0x84,0xe3,0x46,0xf5,0x2b,0xb0,0xba,0x57,0x46,0xcc,0xb6,0xb5,0x95,0x22,0xb1,0xaf,0xf9,0x83,0x0f,0x2f,0x98,0xb9,0xe5,0xda,0xfc,0xd8,0x32,0x07,0x78,0x83,0xc4,0x4e,0x8a,0x35,0x38,0x8f,0x71,0x8b,0xf4,0x0c,},"\x56\x4e\xd2\x2c\x17\x2f\x5c\x3a\xfb\xb0\xb9\x5a\xd2\xfc\x64\xe4\xbe\x6d\x4d\xb1\xeb\xb8\xd3\x99\xc4\x3a\x5e\x16\x04\x8e\x7f\x87\x32\x18\x1e\x5d\x0e\xed\x8e\x63\x8e\xf2\xa5\x5a\xa0\xd7\xb6\x81\xfe\x02\xbb\x54\x23\xaf\x94\xbd\x35\x2d\x3c\x2d\xde\xc0\xf8\x47\x60\xa4\x11\x2b\x4f\xe0\x17\xcf\xbc\x50\x2f\x95\x43\xcf\xa4\x1f\xb2\xaa\xe7\x5a\x3a\x08\x1f\x8c\x49\x90\x33\xd1\xfa\xe5\xd9\xc5\x0c\xb4\x4d\xbc\x63\x60\x5a\x54\x39\x8f\xbf\x07\x98\x52\xeb\xa8\x6f\x2f\xdf\xc2\x72\xd0\xc4\x17\x9d\x7c\x13\xcb\xc1\xc2\xa3\xda\x0b\x82\x84\x5c\xf1\xa4\x6e\xbb\xe3\x1e\x79\xb6\x00\x97\x33\xc7\xbf\xe7\xaa\x4f\x9f\xfd\x71\x9c\x77\xdc\x7d\x74\x8e\x49\x2e\x14\xee\x5e\x41\x79\xbf\xa9\xe6\x49\xcf\x0d\x89\x53\x41\x86\x38\x5e\xe9\x94\x10\x05\x1d\x66\x56\xe6\x23\x43\x8c\xc7\xb2\xe7\x07\xe4\x8c\x84\x91\x55\x49\xae\x8d\x67\xa3\x06\xc6\x7b\x10\x6b\x7a\x25\xf4\x5f\x8e\x10\xdd\x7d\xd3\xea\xac\x31\xf1\x05\x22\x57\xeb\x6a\x75\x76\xb6\x85\xcb\x9e\x6c\x1c\xd0\xd7\x3c\x7a\x3c\xed\x5a\x8d\xd2\x73\x08\xae\x00\xf9\x5e\xab\xda\xe9\xd1\xc4\xaa\x89\x34\xe2\x42\x4c\x93\x28\xa5\x22\x8f\x4f\x82\xdd\x4a\x66\x55\x6d\x82\x17\xc5\xa2\x2b\x2b\xeb\x86\xa2\xa4\x34\x13\xee\x5e\x10\xf8\x83\xf2\xcd\x6c\x2e\x87\x49\xb5\x50\x88\x42\xec\xae\x5f\xfc\xcb\x79\x6d\x96\x33\xe8\x7e\xf4\xa9\x6c\x0d\xf7\xef\x47\xb2\x83\xd0\x96\x72\x3b\xa3\x13\x5b\xad\x75\xb2\xe1\x9e\xc0\x4f\x70\xa4\x78\x42\x8a\xd5\xd0\xaa\xc0\xdd\x2a\xb9\x90\x59\x13\xe7\xe5\xad\xe4\x08\x80\x1d\x5d\x3c\x54\xd9\xcf\x7b\x8f\x0f\x0c\x5e\xb0\x54\xc1\x47\x5c\xc2\x10\xa2\xc7\x98\xd8\xbd\x89\x93\x2f\xf9\xf3\x60\x42\x18\x58\x05\x3a\x70\x7b\x8b\xbd\x32\x05\x5c\x44\xb2\x07\x12\xa2\x67\x8a\x9a\x6a\xf9\xe3\x6d\x04\xdc\xff\x44\xf4\x31\xcf\x19\x30\xcd\x18\xfc\x93\x5d\x22\x67\x77\x5c\x69\x09\x67\x25\xed\x89\xa2\x91\xdd\x60\xe2\x1a\xc0\xb0\x12\x87\x34\x07\x29\x92\x82\x3e\xf8\x7b\x5e\xfa\x6c\xc5\xb0\x50\x17\x7f\x55\xf4\xce\xc9\x2a\x08\xa6\x5b\xca\xdc\xab\x9a\x41\xc3\x60\x86\x37\x0b\x7b\x9d\xd6\x29\x8a\xc7\xb0\xae\x6a\x09\xc9\x71\x0a\xbb\x46\x76\xa8\xfc\x87\xa3\x65\x12\x90\x14\x4b\x6b\x30\xef\x4f\x6f\xbe\x5b\x9a\xd2\x52\x37\xfe\x06\x05\xe3\xb9\xf1\x8a\x77\x18\xac\x9f\xca\x6f\x32\x5e\xa5\x5f\x49\xa8\x07\xfb\x80\xa2\x40\x2a\xe1\x34\x23\x08\x0d\x32\x77\x58\x64\x90\x23\x79\x8d\x57\x28\xe0\xdc\x64\xac\x88\xa6\xe2\x94\x5d\xbb\x3e\x3f\xfa\x9f\xdb\x4c\x7b\x58\xfb\xa3\xf5\xfb\xd6\x7c\x68\x6b\x29\x71\xbb\xd8\xba\x4d\x27\x5d\x57\x3e\xb7\x96\xeb\x91\x46\x77\x5d\x8c\xdc\xd5\xfd\x3e\xb5\xa8\x8e\xa5\xa9\x30\xec\x32\x44\xe6\xa3\x7c\x81\xf6\xa2\x55\x4e\x5b\xa7\x87\xf0\xe4\x53\x19\xfe\x4b\x8a\x2f\xfb\xfe\xd5\x07\x70\xe7\x82\x7b\x3e\x7b\xc2\xb4\x4c\xe5\x12\xae\x60\x51\xb6\xf9\xf1\x39\x31\xea\x6a\xcc\x09\x6b\x8d\xcb\x01\x96\xbe\x42\x24\x84\xdb\x5f\xcb\x29\x9d"}, -{{0x83,0x9f,0xb1,0x32,0xe6,0x92,0x50,0xca,0x1a,0xd9,0x45,0x10,0x08,0x7f,0x92,0xce,0x06,0x87,0x69,0x21,0x3a,0x19,0xb2,0xa6,0xc8,0x94,0x90,0xf1,0xf5,0x78,0x80,0x7a,},{0xeb,0x58,0x66,0x19,0xb4,0x4a,0x15,0x37,0x9a,0xcc,0x46,0x21,0xa2,0xac,0x71,0xea,0x58,0x97,0x00,0x26,0xc2,0x8e,0x24,0x09,0xfc,0x1b,0xa2,0xbd,0x8b,0x23,0x6d,0x1d,},{0x66,0x43,0x7b,0x6b,0xc0,0x5e,0x75,0xdd,0x16,0x26,0xc3,0xc4,0xff,0x1f,0x72,0xe6,0xdb,0x38,0x1b,0xa1,0x59,0x09,0x48,0xf8,0xf1,0x6a,0xd4,0xd6,0x6e,0x59,0x91,0x65,0x9a,0xa8,0x44,0x05,0x56,0x8c,0xfb,0xc0,0xa7,0x7c,0x02,0x5e,0x59,0xe4,0x3f,0xd5,0x3a,0xb9,0xff,0xab,0xba,0x7b,0x25,0x8f,0x78,0x79,0x62,0x39,0xf9,0x0d,0x45,0x01,},"\xc5\x72\x32\xfe\x32\xf1\x1e\x89\x4b\x43\x7d\x40\x45\x62\x07\xcc\x30\x6d\xb4\x81\x69\xb2\x0e\x07\x81\x10\x3a\xff\xe8\x02\xf5\xaa\xbe\x85\x82\x95\x2c\xa8\xe9\x57\x45\xe9\x94\x0d\x53\x5e\x00\xff\x65\xab\x3c\x64\xbe\xd3\xd1\x17\x3a\x0f\x3d\x70\xce\x4e\xbe\x2b\x50\xd0\x48\xbb\x47\x16\x4d\x2a\x2c\xd9\xd9\x5a\x10\xcf\x0d\x07\x3e\xd1\xc4\x1b\x3d\xe3\x33\x52\x8e\xe3\x29\x68\x22\x3a\x0d\x84\x7c\xad\xbb\x5b\x69\xf3\x82\x16\x4e\x9a\x28\xd2\x3e\xc9\xbd\xe9\xa8\x28\xe8\x77\x1c\x9e\xb4\x92\x20\xaf\x54\x18\x55\x08\xaa\x07\x3a\x83\x91\x95\xf1\x03\xbc\x2f\x32\xfe\x04\xf9\x51\xca\x45\xbf\xbf\x30\xd2\xfb\x81\x14\x05\x6a\x73\x6a\xdd\xf2\x7e\xcd\x9a\xf0\xf6\xe5\xe9\x7e\x57\x73\xc4\xfa\x90\x22\x68\xc3\x2a\x15\x14\x10\x95\x5f\x3c\x76\xaa\xe2\x55\x54\x9e\x0f\x03\x3f\x89\xe1\xa7\x8f\x26\x5c\xba\xb6\xbe\xb7\x51\x6d\x4b\xad\xc4\x9c\xda\x45\x88\x31\x62\x25\xb4\xc8\x5e\xa9\xfa\x99\xc7\xd6\x76\x6e\x94\x90\xc4\x9d\xe5\x9d\xa7\x17\xf6\x67\x65\x35\x30\x07\x1d\xd2\xf0\xc5\x3e\x31\xd8\x76\x81\x56\xfe\xb0\x8f\xaf\x00\xdb\x0a\x04\x53\x3d\xf9\x79\x57\xa8\x4a\xa4\x6a\xeb\x7e\x36\xc0\xb0\xbe\x69\x01\x89\x46\xf1\x53\x8a\x6a\xea\x71\xdf\x53\x6f\x14\x42\xc2\x44\x4a\x43\xa0\x43\xd0\x46\xab\xde\x1a\x78\x2b\x0f\x4f\x5c\x6a\xa7\x20\xaa\x60\xaf\xed\x94\x7c\x0c\xee\x47\x7d\xbe\xc0\x05\x57\xb3\x72\x12\xd9\x33\x57\xca\x2b\x6b\x6f\x82\x71\x5b\xa0\xe4\x84\xf6\xda\xf2\xd0\xb7\xa9\x8c\x03\x35\x19\xce\x38\x26\x35\x86\x79\x6d\x5d\x31\xcb\x2b\xc3\xd1\x12\x5b\xc0\xcc\xd3\x29\xa5\xc2\x1f\xd2\x7a\x21\x8d\xed\x60\x7a\x0e\x75\x15\xb5\x71\xf1\x92\xc3\x3f\x5f\xba\x51\x4a\xfe\x4d\x45\x81\x00\xf3\xcc\xba\x3f\x38\xeb\x43\x0b\x4f\xc8\x8f\xae\xf9\x99\xfa\x71\xee\xe4\x88\x22\x89\x03\xbe\x29\xf2\x4d\xf8\x1d\xc9\x11\x04\x4e\x92\x4c\xda\xa0\x17\xcc\x7d\x87\xe5\x6a\x6c\xba\x87\x60\x85\x9b\xd6\x3d\xd2\xd4\xf5\x81\xb9\x55\xec\x92\x4a\x49\xaf\xb4\x7c\xa0\xd6\x3e\x78\x26\xfd\xc7\x12\xb4\x94\x3b\x73\x9e\x18\x57\x75\x5a\x33\xc6\x50\x36\x75\xfd\xde\xae\x06\x27\x06\xe3\x4f\x74\x4f\xd9\x32\x64\x8a\x56\x08\xce\x60\x8a\x61\x99\x57\x83\xf3\x33\x9c\xa3\xfe\x10\x7e\x19\x72\x74\x4b\xf6\xd4\xed\xaf\xbf\x47\xce\x02\x1e\x05\x82\x1f\xb1\x24\xc7\x08\x39\x30\xe6\x8e\x6f\x5c\x32\xd2\xd9\xfc\x4a\x88\x4c\x0b\xc8\x84\x04\xe4\xcf\xe3\xc1\xa2\x42\x0d\x41\x82\x3a\x38\x5f\xb3\x28\x8d\xb6\x5c\x89\x54\x5f\x6e\x73\xf0\xd8\x00\x4b\x2b\xa1\x2a\x4e\x07\x72\x75\x23\xef\x08\x56\x70\xda\xff\xaf\x41\xc2\x8a\x4c\x11\x57\xbd\xd2\x45\xe6\x87\x50\xdd\x20\x0e\x02\x3a\xf9\x0c\x67\x56\x1e\x0f\xe4\xba\x34\x0c\x43\x3f\x75\x5e\xef\xab\xd4\xb0\x39\xbf\xc3\x23\xdc\x11\xad\xb7\x5a\xec\xc4\x48\xa8\x69\xc7\xf2\xa5\x8b\x9d\x86\x17\xc6\x4b\x8f\x89\xfc\x58\x3f\x8c\x94\x8e\x2d\xf0\x25\x1a\x6c\x7d\x8c\x73\x8c\x3b\x5a\x42\xb7\x49\xad\x5e\x8e\x98\x6b\xd8"}, -{{0xad,0xc1,0xe5,0x6c,0x3a,0xc9,0x4e,0x6c,0xda,0x04,0x11,0xcb,0xc3,0xce,0x2a,0xf1,0x28,0xd1,0x85,0xa2,0xa2,0x73,0xbd,0xb2,0xaf,0x8d,0x7e,0x50,0xfb,0x96,0xb5,0x26,},{0x5d,0xcf,0xec,0x1f,0x91,0x12,0x75,0x15,0x64,0xec,0xb6,0x07,0x15,0xeb,0xb2,0xc5,0x17,0xb5,0xec,0x37,0xb2,0x53,0x4f,0xd6,0x32,0x99,0x24,0x42,0x9b,0x7f,0xd5,0xc5,},{0xf0,0x2e,0x5d,0xbc,0xb6,0x87,0x04,0xaf,0xad,0x03,0xac,0xa8,0x10,0x61,0xdb,0xdb,0x99,0x85,0x70,0x04,0x9f,0x10,0xce,0x65,0x0e,0xc7,0xa2,0xef,0xf1,0x5c,0x79,0x3d,0xdf,0x5a,0x27,0x2c,0xb6,0x83,0xc2,0x2c,0x87,0x25,0x7c,0x59,0xbd,0xef,0x39,0xef,0xea,0x79,0xbd,0x67,0x95,0x56,0xea,0x15,0x05,0xed,0x00,0x36,0xcb,0x46,0x04,0x0c,},"\xd4\xf9\x59\x47\x4e\x0b\x89\xe2\xdc\xd0\x20\x66\x98\x4f\x88\xd7\x39\xdd\x11\x34\xa3\x33\x09\xf0\xa8\xb7\x80\x2e\xaf\x01\x33\x03\xc1\x35\x15\xdf\xeb\x46\x1e\xa3\xd2\x48\xe9\x98\xb9\xa4\xe5\x4d\xae\x5b\x00\x19\x0a\x45\xe7\x0d\xc6\x7e\x98\xf3\xd4\xcf\x90\x6c\x21\x4d\x4f\x63\x6d\x29\x52\x92\x5e\x22\xb1\xa8\x6a\x1a\xab\xb3\xa8\x92\xa9\xf8\xed\x45\x4f\x39\xc6\x3d\x35\xb7\x1e\x87\xa2\xda\x55\xa8\xe1\x67\xac\x83\xa8\x66\xad\x16\x7a\x17\xae\xd1\x83\xc0\x85\x18\xc1\x5e\x6b\xe3\x48\x58\xb4\xce\xe2\xb8\x42\x73\x14\x76\x0f\xff\xdd\xd5\x92\x38\x54\xb1\x74\x7f\x79\x6e\x1a\x52\x49\xfb\x30\x44\x89\x4e\xd6\x46\x82\x9f\x65\x43\x16\xee\x52\xf4\x01\x0c\x8d\xd3\x21\xfa\x1d\xec\x39\x7e\x50\x14\x5e\xd9\xe3\x16\x86\xfd\x52\x03\xf7\x23\x3b\x8d\xa7\x80\xac\xaa\x91\xee\x0b\x5b\x47\x20\x78\x66\xaa\xd8\x5f\x83\x7e\x03\xb4\xe6\xf6\xde\x8c\x04\xac\xaf\xd7\x07\xbd\xc1\xdd\x45\x50\x0a\xb5\x64\x80\x1b\xee\x9a\x58\xec\xe3\x60\xd0\x04\x82\x8b\xaa\xf5\x23\xe2\xf5\xab\x69\x32\x6a\x03\xaa\xbe\x01\x08\x78\xfd\x43\xff\xaa\x56\x87\x22\x44\xd7\x68\x1f\x16\x18\xe6\x23\xe3\xd4\x74\xc7\x3a\xf8\xb0\x80\xa6\x18\x21\xa5\x74\xef\x2f\xd7\x52\xd2\x3b\x60\x5e\xc5\x21\xc1\x9c\x15\x50\xde\x98\x0c\x09\x4d\x05\xe0\x23\x8f\x3e\x00\x8e\x6b\x19\x5a\xbf\xdd\x40\x28\xee\x1e\xe1\xd6\xc6\x6a\x76\xf1\x78\xf0\xb4\x31\xe4\xaf\x44\xdd\xcc\xfc\x52\x90\xed\xff\x36\xec\xe6\x3e\x83\x85\x56\x70\x13\xf4\x3a\x2a\xeb\xb6\x7e\x3e\xf4\x06\x30\x8c\x20\x48\x8a\x76\xd5\x8a\x21\x4f\x31\x39\xd9\x83\xb1\x9a\xfb\x12\xe3\x28\x36\x07\xfd\x75\x10\x7b\xd3\x1f\xeb\x62\x56\x17\x4b\x7a\x18\xae\xca\xc9\xf8\x56\x25\x82\x01\x8b\x0e\x6d\xe4\x05\x35\xe3\x5b\xef\x2b\x56\x25\x53\x88\x51\x29\x39\x75\x62\x90\x0d\x34\x17\xf9\x8c\xdd\x1e\x29\xd7\x31\xff\x48\x93\x3f\x29\x52\x95\x81\x63\xba\x67\xd5\x95\x61\x81\x1b\x83\x77\x2b\xd0\x57\x10\xb6\xe3\xcc\x04\x34\x60\x99\x37\x50\x72\x23\xab\xb7\x1a\x6a\x8c\x83\x8f\xec\xdb\x1d\x2d\x37\xc9\x5d\xc8\x06\xf6\x5f\x3f\x96\x63\xd9\x9f\x06\xe6\xc0\xf3\xc3\x2e\x95\xaf\x1d\xd7\x08\xe8\x11\x08\x63\x6a\x26\xb9\x68\xe9\x83\x39\xc7\x41\x28\xb6\xcf\x67\x13\x35\x88\x4a\xc7\x2f\x75\xb6\x37\x19\x5e\xa9\xec\xa0\x53\x60\x89\x96\xc3\x2e\xd4\x45\x41\x0f\x67\xfa\x10\x4b\x39\xf0\xfd\xf3\xc9\xb5\xc6\x15\x7b\x76\x80\x37\x56\xb2\x7f\x4c\x3b\xa1\xb4\x7f\x32\x85\x76\x24\x8e\x9b\xc5\x3e\x7b\x8a\xb0\xb2\xed\x97\xc2\xf9\x99\x8b\xcc\x7d\xfe\x39\xe2\x64\xaa\xd3\x0c\x6c\xfe\xf2\xb5\x55\x3f\xfb\x5a\x69\x9a\xa4\xbd\x0e\xab\xe4\x38\xce\x05\x22\xcc\x91\xfe\x4e\x72\xbf\x7e\xac\xba\x47\x71\xcc\xf6\x3a\x37\xaa\xfc\xad\xbf\xbf\x99\xdd\x76\xb8\x5b\x80\xee\x07\x5d\x3a\x7d\x1a\x90\xa5\x5b\x77\x29\xa5\x41\x6e\x5b\xe6\x96\xbf\x9f\xb7\xf3\x15\x8c\xfd\xb5\xcf\xda\xcd\xde\x81\x72\xee\x1a\xb9\x48\x6e\x24\xcc\xea\xd2\x9b\x45\x7a\xcf\x43"}, -{{0xdb,0x89,0xdf,0x6a,0x23,0xd8,0x90,0xb7,0xf0,0x02,0x60,0xe8,0x1f,0x4a,0xd9,0x8f,0xd0,0x94,0x40,0x36,0x51,0x31,0xe8,0x5e,0x22,0xc7,0x95,0x1a,0x18,0x7b,0x02,0x18,},{0xc9,0x67,0x63,0x67,0x2e,0xe4,0xa2,0xcc,0x5a,0x93,0xb6,0xa6,0x83,0xdf,0x9b,0x5d,0xe4,0xd9,0x38,0x6a,0x79,0x08,0x35,0x68,0x1d,0x12,0x17,0xd1,0x92,0x96,0xbd,0xc8,},{0x80,0xb7,0xfc,0x8b,0x6a,0xe6,0xee,0xce,0x81,0x66,0xb7,0xea,0x53,0x4c,0xb5,0xb2,0x14,0xc9,0xea,0x99,0x73,0x92,0x1e,0xd0,0x5d,0xe4,0x0c,0x78,0xe1,0x4f,0x16,0x2b,0x09,0xe9,0x78,0xca,0x6d,0x86,0xee,0x43,0x4d,0x98,0x4b,0x8b,0x00,0x70,0x40,0x9d,0xd2,0xad,0x11,0xb5,0x31,0x78,0xe2,0x39,0xda,0xb5,0xbc,0x39,0xc7,0xba,0x46,0x0d,},"\x54\xc1\xc5\x11\x1e\x08\xc9\x82\x45\xba\x4f\x13\x18\xba\x1d\xb1\xdc\xc7\x4d\x14\xa5\xc9\x8a\xb9\x68\x9c\xba\x1c\x80\x2c\x68\xbc\xfc\x81\xfd\x87\xff\xc6\x1c\xaa\x94\x2f\x66\xd7\xe5\x15\x7f\x65\x53\x8c\x7e\x7b\x33\x17\x04\x84\xb4\xb6\x54\x3f\x36\x20\xff\x29\x63\x8b\x64\xd4\xda\xe7\xb0\x22\x21\xcf\x77\x83\xf1\x87\xec\x42\x31\xe6\xb6\x94\x6d\x82\x76\x20\x74\xf0\x9c\x32\x78\x1c\x2f\x38\x46\xde\x3e\x82\x17\xf6\xe1\xb6\xe0\xd2\xb5\x59\x5d\x74\x2e\x2c\x4e\x32\x5a\x28\x41\x92\x40\x44\xdf\xcf\x12\xb4\x79\xeb\x69\xf1\xbb\xd4\x0e\xab\xdd\xd1\xff\x54\xa9\x18\x4d\x36\x6d\xff\x9d\x8f\x2d\x86\x3e\x37\x8a\x41\xf1\x0c\xd1\xda\xe9\x22\xcd\x7f\xbb\x2a\x54\x4e\x47\xea\xbf\x47\xca\x0a\x38\xab\xba\x34\x45\x49\x19\xbb\x9a\x4e\xf0\x44\xbf\xb9\x7b\x70\x8c\x2f\x74\x28\xd6\x8f\x9c\x57\xc0\xee\x7e\x79\x25\xf7\xa2\xb5\xc6\xe7\xdf\x82\xbb\x26\x80\xc8\x62\xdc\x7c\xc6\x8b\x0f\x54\x53\x0e\x64\xaf\xe2\x76\x3d\x9c\x7b\xaf\x45\xcc\x6f\xe6\x12\xd1\xf7\x82\x77\x39\xc4\x41\x13\x98\x88\x8f\x73\x67\xc3\xd4\x37\x79\x07\xac\xc0\x6a\x06\xf9\x3f\x88\x72\x26\x79\x8f\x48\xaa\x54\x64\xf6\x01\xc2\xc1\xed\xda\x77\xed\xfe\xb9\xb9\xb5\xd5\xf9\xcb\x6f\xed\x37\x90\x05\x47\x47\x7f\xca\x1d\x09\xab\x52\xd6\x3e\x49\x1f\xeb\x12\xfd\x6d\xc8\x05\xa7\x8c\xee\x3b\xaa\xde\x43\x52\x98\x20\x61\xde\xa5\xa2\x65\x3d\xb8\xe7\x60\x77\x72\xe8\x34\xb3\xa5\x05\xc1\x6d\xd6\xe7\xc7\x1b\x91\x1e\x84\x2e\xba\x92\x5d\x77\xa3\x3c\x5c\x57\xce\x11\x84\x09\x80\x78\xca\x2e\x6a\x3f\x69\xaa\x6a\x14\x63\x9d\xc9\x7b\x4b\x30\xc9\x9d\xc4\xfa\x3e\x2c\xf6\x3c\x70\x1c\x30\x6c\x5e\x25\x3c\x51\x13\x85\x4c\x18\x5e\xbc\x8b\x47\x98\xf6\x8d\x1f\xd7\x80\x05\x4d\x3e\xed\x2f\x39\x4c\x45\x43\x04\x96\x6b\xdd\xbd\x12\x28\x08\x34\xec\x9b\x40\xc1\xe9\x8b\xc2\xd9\x8f\x48\x45\xf6\xeb\x44\xf2\x53\x15\xee\xdb\x3b\x79\xff\xca\x41\x80\xc1\xbd\xdd\x97\xd0\xc9\xaf\xfb\xac\x58\x81\x49\x37\x68\x26\x80\x07\x6f\xe5\xa3\xba\xbb\x65\xd2\x8f\x25\x17\x03\x6c\x0c\xfb\x42\xf0\x29\x3e\xb2\xac\xb1\x39\x49\xfe\x91\xe0\xad\x06\x78\xaa\x24\x3d\x77\x34\xa8\x9d\x99\x78\x70\xbf\x9a\x6a\x58\x4e\xd6\xe6\x28\x16\x3e\x39\xd8\xaa\x61\x0d\x46\xb9\x28\x5b\x9e\x1d\xd7\xe8\xf8\x07\xfd\xf5\xca\x2b\xbf\x6d\xe5\xe5\xe6\x8a\xf7\xcb\x7e\xbd\x43\xec\xce\x22\x7c\xd7\x0c\x7b\xf4\xee\x14\x33\xed\xfc\xfe\x88\x66\x14\x67\x0c\xdd\x19\x63\x43\xfb\x91\xe1\x54\x16\xd2\xf6\xac\xba\xe3\xea\xdc\x03\x02\x31\xee\x9d\x2e\xcc\x52\xa8\x8c\xe8\xdc\x7d\x09\x8e\x7f\xac\x77\x68\x5b\x4e\xb5\x40\xe3\x01\x93\x07\x14\x32\x21\xb8\xef\x77\xf3\x63\x2c\x89\x3d\x55\x6e\x0b\xb7\x43\xa1\x96\x3e\xc1\x58\x86\xc8\x54\x5e\x87\xc9\x5c\xc8\x25\xf2\x00\xd0\xf3\xcf\x4f\x55\xa3\xd6\x60\xa5\x36\xa2\x3a\xef\xcc\x42\x8a\x43\x20\x34\x85\xee\x84\x34\x2f\x5c\x00\x1e\xe8\x40\x4e\x75\x90\x17\x00\x62\x82\xab\x8b\xa8\x90\x3e"}, -{{0x00,0xe6,0xbb,0x17,0xaf,0x3c,0x2d,0xf6,0x52,0xb3,0x4f,0x9a,0xbe,0x19,0xf9,0x90,0x19,0x07,0x42,0x33,0x68,0x6c,0x71,0x14,0xe3,0xa0,0xed,0xf0,0x83,0x09,0x93,0x4f,},{0x7b,0x82,0x32,0xa6,0x6c,0xec,0x2f,0x91,0x5a,0xaa,0x79,0x51,0xd2,0x9d,0x2b,0x9e,0xe9,0x3d,0x32,0x1d,0x15,0xb2,0x03,0xc5,0x1e,0x61,0xe8,0xce,0x83,0xd1,0x87,0xf8,},{0x04,0xb3,0xb8,0x50,0x1e,0x39,0x6c,0x4a,0x78,0x8e,0x14,0xac,0x49,0xf6,0x17,0x4c,0xdb,0x5c,0x85,0x5e,0x65,0x12,0x03,0xcf,0x68,0xd1,0xef,0xa8,0x9a,0xa5,0x86,0x78,0xd4,0xd1,0xf3,0x03,0xa9,0x87,0x7a,0x37,0x86,0xd2,0x03,0xc3,0x55,0xb0,0x9d,0x52,0x86,0xc1,0xca,0x0d,0xf0,0x4a,0x89,0xaa,0x06,0xcc,0x3f,0x9d,0x0f,0xd3,0x05,0x04,},"\x06\x32\x81\xe4\x1e\x8b\xa9\x70\x3e\xd0\x9e\xf3\xbf\x0e\xa4\x6e\x4c\xab\xdd\x6e\xbd\x76\x9d\x05\xdc\x04\x5d\x4f\x99\x0d\x69\xfc\x55\x41\x30\xa4\xe6\x1a\xa2\x1e\x2d\xe4\xc9\x2d\xb4\x8a\x20\xa3\x7b\x17\x47\xa7\xea\xc5\xeb\xb2\x73\x5a\x89\x38\x19\x7f\x13\x9f\xad\x14\x97\xb3\x51\xad\x06\x4c\x0f\x18\xf8\xfa\xf1\xfe\x11\xf6\x39\x79\xa6\x99\x68\xe2\x4c\xf9\x1e\x58\xa3\xab\x03\x26\x69\xe4\xef\xee\x27\x4f\x96\xb5\x8b\xe7\xd9\xe3\x91\xf3\x6f\xcf\x07\x09\xb2\xcb\x2d\x22\x69\x4a\x6c\xeb\x17\x24\x69\x45\xeb\xb3\xbc\x7f\x0f\x03\xbf\x0b\x08\xdc\x96\x26\xe3\xe7\x15\xc9\x91\x67\x1d\x53\xeb\xb9\xae\x83\xa7\xd0\x8d\x44\xf6\x36\x35\xc4\x0f\x8d\x48\x17\xf5\x8d\xe9\xeb\x77\xcb\x25\xb2\xac\xd6\xde\xf9\x69\xab\x56\x9e\x97\x4a\x8a\xda\xc1\x1a\x86\xb5\x8f\xe6\xc1\x00\x67\x49\x9f\xc9\x14\xdf\xf5\x69\x02\xcb\xc3\x93\xa7\x1c\xc2\x5e\x8f\x05\xc0\x3c\x94\xf1\x3b\x84\xa2\xb0\x1a\x58\xc1\x0d\xbc\xbb\x60\xeb\xce\xe4\x87\xf5\x29\x17\x74\x66\x29\x99\x25\xda\x50\xe2\xda\x5b\x55\x57\xf0\xae\xee\x3f\xd7\xf4\x7b\x5c\x2e\x3f\x84\xce\xfa\xb4\x67\x96\x91\x39\x4d\xd1\x22\x30\x3b\xb7\x69\xaf\xb3\xad\xfe\x83\x58\xb0\x2b\x67\x92\x73\xb3\x5a\xbd\xc6\x40\x25\x76\xcc\xce\x5e\x10\x44\x2a\x13\x7e\xf9\x45\x69\x39\xb2\x89\xef\x4e\x41\x7b\x1c\xc6\x23\x9f\x7c\xee\xdd\x68\xf1\xa8\x26\x41\x80\xe0\x68\xb4\x96\x6f\xd6\x7f\x2b\xad\x6e\xdd\x8b\x4a\x1e\x8d\x2b\x54\x2d\xaf\x26\xdb\x83\x1f\x1f\xb5\x1e\xb8\x6f\xfa\xde\xcc\xd9\xac\x3d\x66\x4f\x34\x6e\x7d\x04\x6c\x33\xa5\x72\x84\x1e\xa8\x33\x4e\x7f\x2f\x41\x7a\x05\x71\x2a\x9e\x33\x4e\x48\x7f\xd3\xae\x17\x54\x55\x16\x2f\xe8\xf4\x9c\xc0\x26\xa6\x40\xc6\xcf\x93\xcf\x58\x87\x50\x52\xf4\x1c\xc9\x82\x06\x15\x65\x3e\xa2\xd0\x84\xc8\x96\xea\xfe\x5a\xd4\x72\x55\x79\x65\x30\x84\x99\x4f\x95\x6d\x5c\x94\x59\x0a\x24\x09\x58\x1b\x6f\xc8\x6e\x40\xaa\x58\xbf\x6e\x60\x57\xa6\xf9\x0a\xf3\xb8\x7a\xea\xf3\x29\x94\xa5\x5a\x54\xf7\x9b\xdf\x3d\xbb\xf5\xce\x0f\xf8\x12\xe4\x86\xb0\x54\x5d\x9e\x9c\x2b\x0b\xce\x0d\x4c\x36\x47\xb1\x82\x72\x62\x49\x88\x34\xe1\x98\xa3\xec\x70\xf3\xb0\x3d\x6a\xad\x2c\x49\xeb\x80\xb5\xe2\x05\x14\x39\x22\x5f\xd9\xce\x94\x68\xd6\x9a\xf7\x0a\x26\x2e\xe3\xb8\xb6\x2a\x8e\x5b\x41\x34\x6d\xa3\x01\x2f\xfb\x45\x81\x6b\x7b\xec\xb0\xe7\x9a\x60\xbf\xf7\x16\x36\xa3\xe4\xbb\x1b\x35\xca\xf1\x95\xf5\x51\x17\x28\x0f\x78\x72\x17\xb3\xca\xa2\xe7\x93\x72\x6f\xc5\xa7\x4d\x11\x60\xdc\xad\x86\x89\x04\xc1\x97\x38\x11\x34\xed\x8c\x3d\xb3\x75\x0b\x75\x56\xf6\x9c\xcc\xe1\x8b\x77\x38\x8b\x58\xc5\xb8\x11\x3e\x59\x0a\xd6\xea\xc5\xb9\x1e\xce\x5a\x67\x05\x02\x5c\x80\x35\x3c\xeb\x1e\xd8\x4a\xaa\x1c\xc4\x8a\x41\x6b\xc0\x16\xae\xf1\x73\xbb\x80\xb2\xba\x28\xc5\x79\x60\xc6\xb0\x11\xb6\xb4\x95\xa3\xf3\x31\x1e\x79\xfe\x46\xbd\xb6\xa4\xc3\x81\xfb\x9d\xc4\x62\x8b\x0a\x83\x02\x35\x58\xf1"}, -{{0xfb,0xdd,0xf6,0xe6,0x1e,0x20,0xd8,0x06,0xe5,0x59,0x17,0x75,0x6d,0xe6,0x0d,0x0c,0x9a,0x99,0x97,0x6f,0x64,0x67,0x16,0xff,0x2f,0xf1,0x31,0x2c,0x54,0xdd,0x97,0x1d,},{0xac,0x53,0x8f,0xab,0xad,0x43,0x80,0xe6,0x0e,0x97,0x71,0x26,0xe7,0x69,0x5e,0xed,0xa5,0x41,0x7d,0x85,0xf7,0xd2,0x3d,0xb2,0x1b,0xd0,0xad,0x11,0x11,0x16,0xf0,0x5d,},{0x8c,0x9b,0x77,0xaa,0x0f,0x1c,0xf5,0x2e,0x8f,0x7a,0x91,0x8b,0x21,0xb4,0x68,0xe6,0x23,0x35,0x91,0x1b,0xc5,0x93,0x06,0xb3,0x0c,0xe7,0x7b,0xf6,0x92,0xc1,0x10,0x59,0xb0,0xee,0x9c,0x5d,0xaa,0xf6,0x83,0x9b,0xb8,0x13,0x73,0xc6,0x1d,0x28,0xd0,0x72,0x70,0x2b,0x59,0x5e,0x4d,0xce,0x28,0xcb,0x99,0x38,0x22,0xb2,0x48,0x13,0x04,0x0b,},"\x3e\x99\x53\xca\x55\xd0\xcd\x23\x3b\x98\x83\x3e\xb1\xbc\x79\xd3\xb5\x5f\x18\xc8\xfa\x1c\x42\x02\x7b\xca\x25\x57\x91\x53\xb5\x5d\xa0\xc5\xa1\x78\xb8\x38\x69\x56\xd9\xa5\x41\x83\xb2\x4c\x91\xdc\x4b\xe9\x94\x84\x72\x37\xd3\x66\x6a\x0a\x01\x30\xfe\x19\x92\x4b\xc0\xee\x50\x89\x6c\x35\xa2\xe1\x6a\x29\xe2\xe2\xac\xf1\x80\xbd\xd9\x37\x93\x54\x68\x7f\x0e\xce\x68\x82\xd2\x6e\x98\x0e\x68\x66\x98\x04\x3b\xb1\xb0\x12\x13\xaa\x64\x4a\x4f\x8d\x61\xf9\xb6\x13\xe6\x2e\xaa\x35\x76\xce\xa0\xb0\xb8\x3f\x05\xce\x25\x58\xff\x63\x56\x49\x5c\x45\xed\xe4\xa8\xf6\x5b\x81\x4a\xb8\xa7\x30\x94\x03\xdf\xd4\x3c\xbe\xa9\x08\x93\x93\x9b\x78\x00\xaa\x00\x23\x2b\x5f\x6b\x77\x14\xeb\xdc\xd8\xbc\xf3\x4a\x5a\x7e\x82\x2a\xc7\xb1\xb0\x99\xac\x61\x5f\x13\x5f\x8c\x35\x1d\xc4\x1a\xe5\xf6\x6d\x5f\x9c\x26\x00\x45\x4c\xa0\x1c\x00\x9b\xa6\xde\x04\x16\x2a\xe5\xf1\xf2\x70\x89\x3c\xa3\x90\x7a\xff\x7f\x78\xe0\x33\x96\xe3\x2b\x62\x2f\xf3\x40\x53\x7b\xf1\x23\xe5\x59\x95\xe9\x20\x96\x09\x33\x0b\x2e\xee\x51\x12\x74\x84\xa4\x0e\x25\x07\x00\x82\x3f\xeb\x0b\xc9\x7b\xb5\x09\xff\x73\x26\x75\xde\xc3\x2e\xcb\x63\x5e\xd9\x2c\x7d\x78\xfe\x30\x50\x20\x0c\xf1\xd9\x41\xd6\xb3\x88\x80\x0a\x84\x19\xd9\x6a\x59\x5e\xce\xd5\xec\x4e\xfd\xcb\x6f\x98\x7f\x54\x72\xa5\xc4\x30\x58\xd3\xa3\xa7\xbb\x56\xd7\x98\x03\x65\xed\x43\xdb\xc2\xbe\x48\xf1\xd1\x8c\xe7\x6a\x89\x18\x54\x26\xfd\x5c\x69\xdf\x7e\x92\x91\xab\x78\x23\xc2\x3a\x76\x94\x1e\xd3\x83\x6a\xac\x7b\x58\xc0\xd5\xfb\x6b\x63\x6c\x42\x47\x1a\x4d\x17\x03\x51\x6f\x03\xe9\x35\xf3\x1f\x19\x54\x50\xe5\x37\xb2\xa0\x7d\x54\x5b\xa4\xb6\x8a\xfb\x06\x38\xc6\x5b\xb0\xff\xaa\x0c\xfd\x69\xd7\x10\x48\x19\x79\x66\x19\xd4\x83\xa0\x24\x5b\x4f\xd9\x01\x7f\x62\xa7\xd3\xa5\xfc\x3b\x72\x89\xd7\x57\x35\xf2\x87\xca\x0a\x95\x1a\xd5\x83\x44\xb2\xab\x7d\x7d\xf8\xdb\xd7\x92\x2a\x5a\xbb\x8d\x7c\x2e\x79\x14\x7e\x6d\x36\xee\x31\xf9\x30\x47\x3b\x07\x27\xdc\xfd\x58\xd6\x44\xd7\xd7\x0a\x0e\xd3\x1c\xa6\xa1\x3e\xd9\xdb\xd2\x24\x49\x2e\xfd\xa1\x9e\x4f\x8e\xed\x46\x18\x0f\xe7\x50\xf0\x7b\xbe\x8e\x99\x85\x4d\x13\xf5\x8b\xa9\x68\xce\x38\x59\xd6\x11\x89\xcd\x2b\x66\x7f\x3b\x2d\x06\x65\xb5\x74\xc4\xba\xc1\x9d\x9e\x37\xe5\xb7\xa8\x0e\xb3\x34\xe3\x68\x10\x53\x0a\xa5\xd1\x76\x63\x93\xf8\x11\x5a\x52\x09\x0c\x91\x82\x34\x28\xc8\x97\xa5\xf3\x5e\x12\xa8\xaf\x2c\xd4\xfb\x13\x90\x7c\xa6\x60\x3a\x4f\x76\xf5\xc2\xe0\x23\x74\xa8\xdc\x3a\x47\xc1\xbe\x6f\x1d\x1c\x8e\xbc\x59\xb3\x6d\x1c\xfa\x0a\xb2\x3e\x9b\x0a\xe9\xb0\xe6\x37\xee\xed\xb9\xc6\x6b\xea\x62\xdc\x63\x0c\xde\xfa\x71\x82\x39\x61\x7e\x31\x18\xe5\xb6\xde\xb7\xc2\x94\x47\x52\x82\xe8\xab\xe2\x4f\xd5\xa5\x4b\x78\x6f\xff\x90\x28\xc5\xa0\x33\x38\x4e\x4b\xc8\x01\x4d\xec\x8d\xa1\x00\xa9\x4b\x17\x8e\xf8\x8e\xc3\x57\xb6\x6d\x2b\x90\x98\xab\x64\x79\x16\x96\xb1\xa6\x6b"}, -{{0x8a,0x55,0xe7,0x7b,0xb0,0xc8,0x74,0x0b,0x8c,0x2e,0x8d,0xdf,0xdf,0xdb,0x40,0xf2,0x7e,0x45,0xfe,0x81,0xfe,0x45,0x71,0x11,0xbf,0x1c,0x87,0x30,0xea,0xb6,0x16,0xb4,},{0x9f,0xf1,0xfd,0x0c,0x50,0xeb,0x24,0xf9,0x9f,0xe2,0xf7,0x71,0x1d,0x52,0x87,0x2d,0xfc,0x90,0x03,0x80,0xdd,0xdc,0xdb,0x86,0xfe,0x6f,0x4a,0x5f,0x35,0x0a,0x87,0x43,},{0x8a,0xae,0xba,0x53,0x5c,0x51,0x1c,0x31,0xd3,0xf8,0xe9,0x5c,0xb0,0x77,0xa9,0xa7,0xec,0x7d,0x08,0x44,0x1e,0x53,0x42,0xa6,0xab,0xe0,0xbf,0x2a,0x5d,0x7f,0xc9,0x30,0xb4,0x3d,0xac,0x3d,0x1e,0x8e,0xf2,0xcb,0x03,0x45,0x52,0xeb,0x4d,0x08,0x39,0xbc,0x8b,0xf2,0x94,0x55,0x1d,0xd2,0xd8,0x0c,0x53,0xfd,0x62,0x79,0x35,0x1a,0xc2,0x0c,},"\x20\xfb\x41\x4e\x26\x4a\x95\x47\x84\xf1\x12\xba\xce\x7e\x04\x74\xb3\x9c\xb3\xc9\xe5\x3d\xee\x0a\x21\xf4\xcf\x6d\x4a\x99\xb9\x34\x7d\xdf\xfb\xe2\x81\xa6\xc2\x30\xa7\x5d\x63\xa7\x2f\xd0\x5f\x6d\xb5\x3e\xa7\x01\x4e\xf7\x70\x9d\x18\xff\x97\x0f\x48\x5f\xe8\x3b\xa1\xd3\x71\x47\x33\x8a\xde\xd6\xda\x4c\xfd\xac\xc1\xe6\x9d\x2f\x3e\x0e\xf3\x62\xf4\x7b\x5b\xcf\xb7\x8a\x1e\x17\x9e\xb5\xc5\xb1\x06\xc8\xd8\x2a\x0a\x0b\x29\x0d\xf0\x75\xab\x27\x43\x69\x29\xcd\xe6\x56\xf0\x23\x09\xf9\x57\x50\xeb\x67\x65\x83\x26\x2e\x5f\x2f\x69\xf0\xff\x72\xa8\xe0\x57\x26\x63\x82\x26\x92\x05\x31\x87\x40\xbf\xe0\x6b\xf5\xc2\xcb\x45\x33\x90\x8e\xf9\xf9\xf2\x86\x9a\x75\xb9\x53\x35\x79\x82\x0e\x3b\xc0\xca\xff\xd6\x46\x17\x1c\x82\x86\xc3\xa4\xab\xa1\xff\x09\x15\xd9\x36\x11\x20\x5e\x23\x0f\x39\xff\x4c\x4c\xaf\x3f\x33\x3e\x75\x3f\xce\x2b\x71\x21\x3e\x53\xd6\x08\x41\x5e\xe1\x7f\xd4\x82\x12\xee\xdd\x88\x40\xf3\x37\x10\x1e\xf0\xd0\xb6\xf7\xbe\x4b\xff\xc0\x6e\xee\xfe\x80\x66\xdd\x27\xa0\x54\x1a\x46\x88\x31\xac\xdd\xc4\x90\x2e\x2f\xef\xef\xbe\xd1\x9c\x30\x8e\x56\x21\xe0\xbf\x46\xbc\xd5\x38\xaa\x13\xfa\xf0\x4d\x38\x07\x59\xc0\xe1\x07\xe9\x12\x00\x18\x39\xdf\xd0\xb6\x35\x44\x0e\x96\x38\xf5\x37\x7c\xa8\x45\x0f\x35\x0c\x01\x12\x9e\xe3\x37\x64\x41\x5c\x53\xcb\x2f\xfb\xf9\x68\xdf\x78\xb7\x42\xfd\x06\x65\xe7\x8a\x34\xab\xf4\xde\xcd\x1f\xd3\x86\x28\x9a\x13\x64\xe6\x45\x55\xee\xc5\x8b\x0a\xf9\xa4\xcd\x6b\x36\xd1\xd5\xc6\x11\xa2\x84\x6d\xfb\x55\x89\x34\x4b\xbb\xb0\x25\x60\x24\x1b\x74\xb9\x93\xa2\x5b\xef\x50\xfb\x1e\x73\x19\x08\x6e\x6a\x23\x98\x63\x00\x83\x4e\xd2\xdb\xa9\x8a\x16\x87\x21\xc2\xf7\x84\xdf\xb8\xd3\x80\x0d\x06\xa0\x54\xae\xf1\x4d\x17\x72\xb6\xc5\x74\xaf\x25\x63\xd1\x93\xef\x2e\x51\xbd\xc6\x2d\x2a\xbc\xe2\xee\xbe\xad\xa7\x92\x03\x49\x8e\x66\x86\xc2\x87\xf3\x7b\xd8\x8a\xeb\x16\x6f\x7d\xff\xc3\xe6\xad\x02\x94\x11\x7e\xf6\xee\x9d\xa8\x47\x9e\xd8\xa1\x6f\xe9\xbe\x24\x6d\x26\x68\x04\xf2\x96\x58\xdb\x75\xe7\xa0\x87\x3b\xe7\x1d\xc7\xd4\x07\xe3\x9f\xab\xd6\x6f\x98\x8b\x45\x74\x77\x42\x7f\xad\x81\x30\xf0\x9a\xb6\x65\xf1\x59\x7c\x90\x46\xe7\x37\x3a\xf9\xa8\x35\x2a\x86\x83\x0c\xb9\x2a\x80\x44\x88\x70\x0f\xe6\x89\x19\x24\xfe\x2a\x72\x01\x73\x3d\x95\xe5\x91\xee\x0a\x1f\xef\x1c\x26\x36\x07\x8d\x37\x0e\x7a\xd3\xb6\xa9\x44\xfe\xd2\xcf\x2b\x30\xab\xa2\xd5\x6f\x34\x95\xb2\x84\x9c\x03\xbb\x61\x4f\x48\xbc\x4e\x50\x7c\x39\x5a\x6c\x35\xd3\xee\xd4\xc7\xbe\x8e\x68\x0f\x2d\x45\xa3\x10\xb1\x87\xeb\x88\xcf\x0e\x8e\xd4\xde\x7d\x37\x24\x6a\x50\xa6\x36\x7b\x97\xee\x37\x84\x32\x2c\x0b\x71\x13\x1a\x28\x31\x98\xda\x48\x04\xde\x75\x1d\xcf\x70\xc4\xba\xd0\x0d\xd9\x8d\x87\x3a\x69\xdd\x1a\x09\xcf\x69\xdd\xfa\xd7\xae\x60\x35\x00\xb6\xa4\x62\x25\x80\x98\xd8\xb6\x6b\x85\x29\x35\x94\xe2\x08\x82\x9b\x52\x28\xfa\xe2\xfa\xfc\x39"}, -{{0x16,0x3b,0x0c,0xb6,0xa1,0x2e,0x8f,0x07,0xb0,0xc2,0x9d,0x6a,0x63,0xf6,0xa6,0x52,0xce,0x49,0x72,0x70,0xb5,0xe4,0x6f,0xcf,0x83,0x3c,0x99,0xbd,0x84,0x3f,0x8c,0x64,},{0x68,0xa3,0x5d,0xe4,0xba,0x6f,0x0f,0x82,0xec,0xf4,0xb1,0xe0,0xdf,0x8e,0x24,0xcb,0x4f,0x18,0xf2,0x10,0x3f,0xf0,0x4d,0xc1,0xb5,0x33,0x39,0x91,0xb6,0xd3,0x14,0xba,},{0x17,0x73,0x8f,0x57,0x26,0x55,0x07,0x80,0x65,0x1d,0x60,0x19,0x9f,0xda,0x39,0xd9,0xc4,0x76,0x8d,0xb5,0x91,0x7e,0x32,0x39,0x36,0x31,0xc5,0x4a,0x41,0x9d,0x59,0xf1,0x8e,0xf9,0x60,0xdd,0xd4,0x39,0x38,0x0d,0xab,0xc3,0x14,0x76,0x1b,0xd0,0xcd,0xb5,0x7c,0xce,0x48,0x1e,0x61,0x09,0xfe,0xd0,0x95,0xde,0xa6,0xe8,0x65,0xaa,0x67,0x0b,},"\x56\xa1\x60\x3f\x72\x5b\xe0\x76\x13\x05\x8c\xdb\x3a\xcd\xc5\x23\x54\xe3\xbb\x1f\xf2\xbe\xd1\x3f\x89\x51\x75\xb1\x5c\x8c\x5a\x90\xff\xbe\x46\xb1\x1a\x06\xcf\xe3\x62\xda\xdf\x73\x23\xc9\x40\x41\x72\x55\xaa\x7a\xa5\x43\x12\x10\x3e\x71\x46\x3d\xaa\x0b\x5c\xda\xeb\xd0\xbe\x72\x3c\x73\x22\x73\xe3\xc3\xf5\xbf\x7a\xa3\x51\x9d\x69\xdf\x6f\x47\x70\xda\xa1\xdf\x82\x80\xbb\x3c\xd2\xc7\x14\xac\x03\x02\x00\x54\x65\x79\xf5\x6c\x60\xb9\x1a\xe1\x1f\x4c\xf8\x74\xa3\x5f\xc5\x9b\x35\x4b\xed\x80\xf5\x6e\x11\xa6\xcd\x62\xa8\x8c\xe6\xb4\xf6\xbf\x39\xd6\x4c\xe3\xd8\x04\x09\x82\x5f\x90\x16\x2c\x3d\x96\xd1\x0e\x47\x86\x07\x36\x5f\x7a\x24\x1e\x71\xaf\x98\x00\x42\xfe\xc2\xd6\x88\x91\xe0\xc8\xa3\x7c\x58\xec\x4e\x60\x0f\xd5\x81\xe7\x90\xb0\xaa\xe8\xe0\x9f\x35\xd4\xcc\x18\x76\xdf\x43\x4b\x80\xee\xe0\x53\x69\xf8\x48\xfc\x49\x30\x57\x7d\x16\x84\x27\x58\x88\xf3\x25\x9c\xb4\x73\x76\xc5\x16\x9c\x99\x37\xf8\x55\xa9\x6a\x9e\x74\x8a\xd0\xa6\x9a\xe4\xab\x2f\x2f\x17\x44\xa3\x92\xf9\xac\xc6\x20\x99\x75\xb7\x84\x98\x4c\xb1\x2f\x98\x29\x2c\x36\xa5\x32\x21\x99\x4a\xbc\x56\xf9\xa6\x6d\xae\x45\x60\xb7\x93\x56\xff\x47\xe1\x28\xc0\x79\x6a\x7f\xb0\xe0\xbb\xc9\x60\x0a\xf4\x8e\x49\xea\xa9\x42\x7c\xf6\xeb\x66\x20\xb1\x0c\xd2\xc0\x85\xb0\xb3\x42\x00\x4d\x5b\x0d\x3e\xdc\x11\xd2\x92\x42\xa4\x63\x87\x80\x76\x2c\x9d\xc6\x06\x9b\x66\xbd\x84\x97\x3b\x50\x11\x96\x1c\xe5\x6d\xb5\x8b\xda\xf4\x8e\x6b\xe1\x2a\xb9\xad\x24\x41\x62\x97\x00\x4d\x02\x91\x4b\x95\x9f\x54\xe0\x92\xf8\xcd\x43\x65\xfa\x6a\xb7\x8d\xdb\xff\x4c\xe8\xda\xd4\xe2\xf5\x3a\x05\xc0\xcc\x49\x9b\xfb\x47\x81\x4a\x27\x13\x55\x1d\xcd\x19\xd4\x47\xf6\x27\x57\x6e\xa4\xea\x4b\xbd\xa8\xba\xe1\x8a\x64\x65\xce\xd7\x47\xea\x17\x18\x0b\x00\x9f\x01\x21\x21\x60\x48\x2b\x04\x33\xaa\xc6\x8e\x67\x64\x4d\x00\xf4\x1f\xdf\x99\x90\xb9\xe1\x11\x17\x63\x4d\xeb\x13\x9b\x1a\x40\xad\x3f\xce\x42\x99\xa1\x7f\xe1\xdd\x22\x53\x01\xc7\xf8\xd8\x01\x0a\x79\x6d\xc7\x9c\x13\x30\x7d\x3f\xf9\x92\xa8\x8b\xe6\x64\xd4\xc8\x86\xd6\x8c\xa9\xe4\x47\x0c\xfb\xe6\x3e\xbf\xfc\x42\x40\x10\xe3\x72\xb6\x92\x2a\xa9\x5c\x80\x1d\x1e\x94\x06\xda\x4b\xc1\x88\xca\x82\x06\x64\x05\xbc\xdb\x3e\xaf\xc9\x37\x62\x9b\x32\x63\xdc\x7d\x50\xee\x52\x78\xcc\xec\x6f\x11\xd5\x51\x7f\x56\xbc\x26\x9c\x87\x36\x91\xe7\xeb\x53\xfa\xef\xf0\x75\x64\xab\x46\xb4\x03\xf1\x5d\x9e\x0e\x69\x24\x86\xee\x09\x8e\x7b\x51\xb4\x28\x13\x46\x9b\x82\x35\x04\x22\x33\xca\x3f\x9c\x4f\x8f\xf2\x4a\x57\x1f\x47\xe0\xad\xf9\x14\x4a\xea\x48\x8a\x2d\x2d\xd0\x01\xe3\x1f\xc9\x61\xe0\x5c\x3e\x85\xf0\xd9\x81\x40\x7c\x87\x31\x58\xbb\x0d\x35\xba\xfe\x4b\x60\x42\x2e\x67\x55\x1e\x97\x01\x65\xce\x3f\xc5\x99\xd0\xfc\xc9\x2b\x16\xac\x36\xa9\x2b\x2c\x1d\xc6\xb3\xf0\x33\xfe\x31\x0c\xd1\x96\xda\x04\xa4\xe6\x39\x03\x11\x77\xcd\x27\xd7\xc2\xfb\xec\x65\xa0\x0b"}, -{{0x8c,0x83,0x93,0x81,0xb6,0xa7,0xce,0x26,0x49,0xc1,0xea,0x46,0x4a,0xe3,0xc2,0xd3,0xfd,0xb1,0xec,0x66,0x6d,0x7b,0x4b,0xe4,0xe2,0xa9,0x41,0xab,0x6d,0x65,0x57,0xa7,},{0x5c,0x72,0x4a,0x30,0xc6,0xfb,0x32,0x81,0x53,0x43,0xa8,0x0d,0xde,0xe6,0xee,0xe5,0x44,0x51,0x64,0x18,0xea,0x95,0xe1,0xba,0xc8,0x0a,0xfc,0x80,0x40,0xd6,0x3f,0xc6,},{0x5d,0x21,0x10,0xd1,0xd2,0xf3,0xed,0xd6,0x83,0xbd,0xfd,0xbe,0xa3,0xff,0xa7,0xcf,0x55,0x28,0xa4,0x0b,0x8b,0x3d,0x8d,0x8c,0x9b,0xfd,0x22,0xae,0xac,0x28,0xba,0xd4,0x71,0x66,0x6e,0x06,0x2f,0x7d,0x38,0xce,0xda,0x8b,0xb3,0x73,0x97,0xa1,0xc5,0xc3,0xf7,0x33,0xb5,0x37,0x96,0x70,0x45,0x70,0x64,0x78,0x43,0x7d,0x4d,0x18,0x7a,0x0a,},"\xcb\xcf\x89\xc3\x54\x89\x64\xc3\x8d\x70\xfd\x8f\x68\xe8\xec\xe3\x6c\xc3\x97\x55\xc9\x71\xd1\x4d\x7e\x05\x6f\x39\xb0\x23\xef\x16\x6d\x17\xf2\x43\x85\x22\xf0\x10\xd6\xd8\x35\xd8\x86\xe7\x1f\x47\x4c\x67\x27\xa4\x22\x1f\xd0\x3a\x75\x74\x57\x82\x89\xed\x54\x93\xac\x4c\x09\x47\xe3\xf4\x28\xd8\xfe\x06\x40\x06\xa2\x56\xce\xf2\x18\x11\xd7\x26\x78\xf5\xdf\xc6\xba\x66\xac\x29\xec\xd1\xb3\x2f\xf5\x55\x7c\xb0\x8c\x5f\x13\x05\x59\x21\x7a\x04\x13\xb7\x59\xc2\x4d\x83\x38\x8a\x2b\xb9\xb2\x9b\x6b\x91\xd1\xf3\x10\x1e\xd6\x25\x21\x1e\x4d\x73\x80\x51\x93\x47\x8c\xf9\x95\x39\x6c\x10\xb1\xc5\xaf\xfa\xcb\x00\x89\x9d\xa0\x4e\x3c\xce\x19\x3b\x49\x4e\x2a\x93\x3c\x4e\xeb\xe0\xa3\x7b\xfb\x8f\x1b\x83\x71\xbd\xe5\xfd\xa0\x9e\x80\x4e\x94\x0f\x34\x48\x96\xa5\x29\x46\x7a\xde\xe4\x5a\x8f\xeb\xf8\x5a\xb0\x36\xca\xb8\x80\x14\x3b\xe4\xf5\x9b\x77\x41\xd8\xe4\x50\x27\x8b\x06\x36\x55\x78\xd4\x0b\x19\xdc\xec\xc6\xe1\xee\x3d\xa3\x4a\xb2\x90\x13\xfa\x3a\xf7\x72\x92\x72\x96\x21\x10\xe3\x85\xab\x9a\x02\x2f\xae\x41\x46\xf8\x97\x16\xf7\xba\xb9\xd3\xdc\x68\x2f\x4f\xac\x77\x36\xd3\xe0\x89\x73\xc6\x85\xbb\xb2\x75\xbb\xf8\xf2\x17\x41\x9e\x5c\xae\x02\x19\xeb\xa5\x16\x6a\x5d\xe1\xb1\x1e\x3f\x9a\x90\x8b\x8a\xc7\xe6\x5b\xcd\x62\x3f\x8c\x18\xbb\x02\x4f\x60\x5d\xcb\xac\xda\x79\x0d\x83\x62\x95\x74\x44\xa9\x5c\x13\x0a\x37\xee\x9d\x56\x3d\x0c\xbb\x4c\xb2\xb0\xff\x71\x59\x1d\x93\x90\xb6\xc8\xfc\x28\x75\x3a\x0e\x40\x2d\x64\x87\xcf\xac\x60\x71\x35\x92\x7d\x89\x26\x75\x12\xb3\x4f\x87\x70\x57\xd9\x27\x1b\xcc\xc0\x24\xdf\xed\xcc\xc6\xc3\x2e\xdf\x75\xc8\xb7\x55\x1c\xdf\x80\x15\x4e\xe8\xe0\x8a\x0c\xc4\x30\x44\xe1\x03\x6b\xae\x01\x7e\xb4\x8b\x65\x02\xc7\xa9\xd6\x0c\x8b\x37\x0c\xf3\x79\x9c\x46\x4f\x96\x4a\x69\xee\x65\x95\x01\x22\x3e\x78\x9a\x64\x97\xb6\x34\x96\xdf\x1a\xda\x2e\x80\x8d\x24\x34\xfc\x8b\xb9\x79\x4e\x5e\x2a\x20\xbb\xf4\xd6\x92\x5c\xb3\xc5\xbb\x14\x84\x2f\x19\x20\x09\x05\xba\x93\x54\xe0\x0d\xc3\x3c\xff\x5b\x42\xd4\xe9\xd9\x66\x8b\x34\xe6\x61\xd4\x4b\xef\x76\xfe\xfe\x2e\xd5\x1f\x94\x42\x3a\x93\x3a\xc9\x4f\x15\x23\xbf\x37\x82\x3a\x23\x8d\x61\x6c\x6b\x17\x97\x34\x41\xe3\x5f\x94\x05\xa0\x4d\x99\xea\xa8\xf5\x04\x53\x4c\x8b\x5f\xa5\xe8\xe3\x35\xc7\x43\xbc\xf2\x1f\x5d\x49\x2b\x71\x12\xe0\x0f\xd8\x64\x2c\xb1\x2b\xfe\xc8\x49\xdf\x62\x12\x0d\xbb\x06\xbf\xc2\x94\x6a\x56\x01\xe2\x5b\xe7\x50\x11\xc6\xf0\x0c\x65\xd3\x5f\x44\xa4\x6a\xf9\xe4\xf7\x80\x9e\x57\x89\xa3\xa6\x1b\xa0\xa3\xb2\x13\x89\x04\x97\x29\x6c\x81\xe4\x2e\x88\xf0\xec\x0f\x5d\xef\xc1\xf5\xd3\x9f\xf2\xa4\x8b\x7e\x30\x26\xc9\xe5\x47\x20\x2e\xdc\x7e\xb7\x38\xc3\x4a\xd3\xa1\x5d\x37\x3e\xf8\x2a\x4c\x1d\x18\x1f\x28\x5a\x98\xbd\x33\x14\xc2\xc1\x94\x7c\x9e\x2c\x60\xac\xa5\x17\x50\xee\x7f\x94\x3c\xaf\x0c\x4e\x1e\x5c\x7d\xf7\x29\x1e\x97\x3b\x1f\x93\x6b\x73\x70\x76\x19"}, -{{0xaa,0xbb,0xb2,0xef,0xed,0xb5,0x99,0x42,0x4a,0x5f,0x3e,0x08,0xf9,0x0f,0xa8,0x82,0x6c,0x5c,0x92,0x17,0x0b,0xe5,0x01,0xa1,0x18,0x1f,0xe8,0xe8,0xdf,0x97,0x4e,0x0e,},{0xce,0x73,0x19,0xef,0x88,0xb2,0x42,0x42,0x06,0x66,0xca,0x69,0x7b,0xa8,0x50,0x1d,0x27,0x4e,0xc4,0xa5,0xdc,0xf8,0x44,0x59,0x66,0x08,0xb9,0xdd,0x5a,0x8a,0x3a,0xcd,},{0xa0,0xb1,0x9c,0xfa,0x6c,0x80,0xde,0x77,0xbf,0xcd,0x32,0x10,0x30,0xbf,0x8c,0x03,0x89,0x3e,0x2b,0x21,0xac,0xe6,0xc6,0xba,0x1f,0xf7,0x40,0x8e,0x6f,0xf0,0x7d,0x84,0x7e,0x6b,0x2b,0x68,0x8d,0x4f,0xd5,0x1a,0xa9,0x32,0x70,0x1d,0xb6,0x40,0x2e,0xf2,0x23,0x22,0xe6,0xe9,0xfc,0x7e,0x32,0x0a,0xbb,0x4d,0x24,0xe1,0xac,0xc6,0xcf,0x06,},"\xfc\xc1\x5c\xc5\x79\x70\x56\x9e\x9c\xcf\xa5\xa7\x78\xfc\x7a\xed\x71\x97\x8a\x3f\x56\x24\x57\x7b\x6f\x57\xfa\x3f\x16\x7e\xa2\x23\xef\x31\x76\x4c\x48\x8d\x05\x9d\x06\x53\x1d\x01\x6b\xcb\x17\xd5\x44\xd4\x69\x77\xaa\x24\x1f\x8e\x07\xaf\x47\x87\xa0\x81\x0f\x98\xd7\x66\x46\x0c\x08\x41\xad\x81\xb8\x8f\x4d\x5d\x81\x64\x48\x5a\x12\x58\xa9\x46\x22\xc5\x49\x24\x28\xd6\xd5\x75\x94\x37\x15\x76\x6c\x2b\x0a\x86\x5b\xed\xba\x16\x7d\x5d\x34\x0e\xdb\x57\x9c\x47\xaa\x32\x45\x9b\x8f\xc9\x8a\x79\xbb\x0b\xed\x1c\x96\x0b\x4c\xcb\x7f\x2d\x4b\x56\x81\xa2\xa7\x0d\x50\x5b\x85\xb8\x1e\x3d\x99\x67\x27\x14\xe4\xea\xb4\x1f\x3a\xb0\xca\x87\x4f\x41\x71\x86\xfe\xb6\x9e\xd1\x3f\xb9\x11\xf4\x9d\x15\x84\x75\x8b\x2d\x18\xb4\x67\x3e\xdf\xae\x49\x5e\x68\xda\xd5\x13\xa7\xac\x0d\x47\xb2\x75\x3c\xb4\xed\xa7\x8f\xb4\x31\xf0\x4d\xda\x8f\xe8\x03\x0d\x7b\xb4\xe8\xdb\xcc\xb9\x69\xd7\xf5\x80\xd9\xc1\xef\x93\x5d\x07\x4d\x7a\x41\xd1\xf8\xb9\xdc\x45\xc9\xa2\xe4\x10\x6a\x55\x29\xa9\x8b\x95\x52\x9a\xb0\xed\xea\x0b\x57\x22\xdd\x68\x6f\x5a\x7f\x3c\xd8\xfb\x26\x24\xab\x26\xc4\x2d\xf1\x1f\x51\x0a\x10\x3d\x8a\x92\x98\x30\xad\x85\xf5\x21\x24\xe3\xd5\x82\x7b\xa6\x0b\xfb\xcd\x73\x6c\xb6\xc5\x90\xee\x77\x7e\xad\x7a\xa2\x22\x4d\x7a\xe4\x6d\x25\x7a\x90\x40\x72\x47\x96\x0c\x9c\xb0\x38\x60\xae\xaa\x7f\x54\xc1\xa8\xe1\x11\x60\xd1\x1b\xb4\x73\x06\x5e\x19\xb7\x07\x21\xc8\xf0\x72\xe1\x90\x9d\x53\x9e\x9a\xc9\x41\x85\x90\x4b\xbb\xfe\x54\x87\x37\x54\xae\x1c\xa7\xbc\xed\x6f\x40\x56\x1a\xf4\xb5\x05\xf0\x3a\xc9\x72\xa6\xf0\xbf\xa7\x3b\x5f\x83\x2f\xe2\x3b\x89\x8b\x2b\xbb\x05\x74\xa6\x66\x2e\xe9\x3b\x3b\x36\x0d\xa1\xec\x7e\x83\x8e\xb2\xc7\x7c\x7c\xb7\xfc\x16\x4f\x7c\x46\x27\x01\x04\x89\xc8\x58\x90\x07\x52\xc9\x2d\x9d\x75\xad\x54\x71\x67\xe4\xbd\xd1\x1a\x07\xd2\x8b\x65\x1a\xa3\x0f\x16\xa8\x50\xe0\x60\xdd\x28\x82\xfb\x82\x09\x19\xa3\x98\xe8\x05\xeb\x63\x69\x9f\x4f\xf5\x95\xf9\x91\x52\x47\x31\x64\x1e\xce\x25\xfb\x3f\x8e\x89\xad\xa5\x01\x19\x2b\x1e\xdd\xae\xcb\xac\xc8\xb8\x98\x52\x8f\x2d\x5b\x33\x12\x69\x4f\x5e\xc2\xdc\x91\x42\xe1\x51\x3f\x77\x7a\x5c\x83\x34\x09\xc1\x71\x63\x3f\xf9\xfa\x26\x09\xd0\x49\x7f\x5d\xf4\xfb\xf4\x8e\xf2\xb7\x7d\x55\xe2\x55\x19\xd2\xee\x79\xb5\xfe\x9d\x8f\xa4\x60\x00\xde\xcd\xb4\xf2\x5d\xfb\x3f\x2b\xaf\xb1\x9f\xbe\x2c\xbd\xac\x00\x2a\x35\x9a\x95\x4b\xc6\x9b\xdf\xe2\xfb\x36\xad\xfd\x9a\x15\x09\xf3\xe3\xa4\xc6\xb1\xf3\xf3\x6e\x7c\xf8\x0d\x58\x3d\x44\x0f\xf2\xa1\x44\x64\x30\x98\x97\x4d\x71\x49\x3e\xcb\x64\x17\xc0\xb8\x06\x5b\xd2\xc2\x1c\x1e\x34\xaf\x09\x24\x3f\xb4\x9e\x9d\x35\x29\x7e\xb0\xa5\x2d\x56\xdd\x27\x0f\xea\x6d\xc5\xc0\x80\xa0\x55\x99\xf7\x85\x81\xe9\x0f\xd8\xcc\x4c\xd1\x1a\x50\x5e\xdd\xe8\x4b\x89\x2d\x89\x53\xbd\xbb\x23\x79\xd3\x3a\xad\x64\x65\x8a\xe2\x06\x07\xdd\x35\xb0\xbf\x3a\x26\x37\xd2\x0c\x3f\x86"}, -{{0xc2,0xe0,0x74,0xfa,0xa2,0x34,0xe9,0x9a,0xb2,0x0a,0xdb,0xbe,0xae,0x11,0xb8,0x10,0x97,0x23,0xb7,0x08,0xc5,0x45,0x86,0xdf,0x65,0x2b,0x40,0x2c,0x35,0xcd,0xd1,0x27,},{0x5e,0x52,0x4e,0xce,0x1c,0x69,0x6e,0x70,0x5a,0x35,0x14,0xdd,0x00,0x82,0xb8,0x40,0x79,0x5a,0x59,0xc3,0x6a,0x96,0xcb,0xc4,0x82,0xbf,0xf5,0xab,0x4e,0xf5,0x15,0xd1,},{0x65,0x7c,0x38,0x26,0xb3,0x48,0x3f,0xd4,0x2a,0xb6,0xdf,0x86,0x9d,0x1b,0x77,0xa8,0xc4,0xdf,0x67,0xa6,0xa5,0x90,0xc7,0xc6,0x77,0x29,0x69,0xe3,0xdf,0x33,0x12,0xae,0x06,0x54,0xfb,0x83,0x84,0x7a,0xf2,0x21,0x93,0x5a,0x05,0x12,0x29,0x16,0x36,0xec,0x05,0x95,0x70,0x08,0x79,0xeb,0xdb,0xa8,0xa1,0x46,0x7c,0x53,0xd4,0x0c,0x23,0x06,},"\x31\x29\x03\x38\xe4\x6d\x1c\xc2\x5c\xe9\x9c\xba\xcc\x40\x16\x03\x41\xb7\x85\x82\x3c\x82\x3c\x4a\xb9\xba\xee\x3b\x61\x25\x79\xf1\xc0\x11\x71\x67\x96\xe5\x6e\x26\x93\xf6\xdd\xad\x43\x92\x2a\xa7\x84\x7c\xbb\x41\x48\x10\x16\x51\xbb\xe6\x2d\x50\xbe\x90\x82\x5e\x8e\xab\x77\x7a\xa4\xb8\x02\x6d\xc5\x38\x5a\x97\xd3\xdf\x76\x16\x01\x91\xf9\x22\xcd\xd2\xf0\x7b\xa5\xf8\x5e\x95\xf4\x5d\xb2\x29\x28\xf9\x07\x34\xff\x52\x0c\x44\xdc\x8f\xe3\x90\x3b\x4c\x51\xcd\x23\xe0\x64\xf0\x1c\x82\x9e\xc7\x4f\xbf\xfe\x25\xfd\x0d\x36\x9d\x27\x65\x74\x0f\x43\x85\x6b\xd7\x39\x8a\x19\x11\xad\x74\x98\x36\x16\x0f\xd9\x8d\x04\xb2\x8e\xe8\x7e\x11\x1d\x40\x71\x8b\x5a\x16\x6f\x05\xc9\xa4\x71\xa4\x15\x66\x55\x70\x69\xf7\xa1\x4d\xe9\x88\xbb\xbf\x67\x77\x52\x1f\xcb\xa6\xdd\x65\xde\x4c\x06\x67\x4a\x11\x85\x3a\xf8\x3a\xcc\xb7\x0f\xb3\x28\xdd\x8f\xd6\x10\x5a\x7d\xf5\x26\x9c\x9f\xae\xc8\xd9\x00\x14\x7e\x92\x8d\x97\x0c\x36\xcd\x83\x4b\xd6\x05\x4f\x70\x65\x0d\xfa\xce\x94\xb7\x62\x9d\x16\xe3\x70\x3d\x76\x6c\xe7\x63\x8d\x0a\xd1\xe1\x7b\x77\x46\x9b\x95\x8d\x2b\xa2\xa1\xe6\x31\xa1\x63\x5e\xfd\xcb\x00\x6e\xbc\x6e\x5d\x8b\x9f\xaf\x7e\x5f\xb9\x89\xdc\x08\x96\xc5\x61\xa2\x6f\x3c\x25\xf0\x55\x71\x6b\x36\x71\x38\xea\x5d\xa1\xf8\x1d\xc7\x2c\xff\x7a\x55\xaf\xae\xe5\x83\x9e\xf5\xaa\x82\x2b\x29\x70\xaa\x18\xa8\x98\x21\x63\xbf\x5e\xed\x1b\x67\x7c\xca\xac\x12\x24\xff\x6c\x6c\xf2\x56\x37\x47\x80\xae\x65\x80\x3b\xf5\xc6\xe2\x3c\x80\xba\xcd\x76\xec\x3e\x2d\xdd\x3a\xb7\x19\x97\x50\x64\x48\xe1\x9d\xb1\x98\xef\xad\xc9\xf7\x57\x49\x1f\x1b\x09\x72\xc8\x2d\xb2\x94\x10\xe1\xe8\xbb\x67\xbb\xb2\x3d\x53\x56\x3b\x88\x07\xe5\xe0\xc2\xe3\x2e\xe5\x96\xb5\xb4\x40\x23\x28\xf9\xe1\x79\xe9\xce\x85\x6d\x3b\xd1\x99\xd5\x8d\xe6\xc5\xc2\x52\xe7\xa6\x12\x4d\x81\xfc\x9e\xea\xf2\x3d\x34\x7d\x2a\xb8\x89\x17\xaa\x68\x44\x50\xdd\x58\x30\x35\x16\xc1\xa4\xd2\xbd\xcd\xde\x22\x0c\x9a\xe3\x79\x0f\x29\x8d\x7d\x38\x4b\x70\xc2\xfe\x25\x88\x07\x84\x8f\xc3\x53\x20\xb5\x78\xb3\x35\x03\xb7\x5f\x38\xa1\xdf\x63\x0b\xd3\x3e\x6a\x85\xa4\xdd\x4d\xf9\xf6\xe5\x5a\x6e\x68\x67\xc7\x38\x01\xe5\x93\xe1\xd5\x91\xdb\x89\xba\x9a\x9a\xf0\xfc\x29\x2e\x06\xfb\x51\x5a\xc8\xa5\xe8\xe3\x43\xa8\x21\x33\x55\x75\xba\x48\xfb\xaa\xe3\xfb\x12\xde\xea\xae\xe6\x0f\x4b\x3d\x31\x7e\xc0\xa5\x54\xdd\xd4\x25\xc8\x49\x32\xc2\x7a\x7a\x12\xf2\x9d\x63\x71\x51\x07\x83\xbd\x75\xe6\x0e\x2f\x6d\xa2\x00\x52\x06\x9e\xd7\x1e\x69\x5a\x94\x31\x82\x19\x3c\xb6\x85\x1a\x7d\x2f\xa3\xc6\x66\xc1\x93\x02\x80\x15\xac\x8b\x7e\x7d\xaa\x6c\x52\x04\xf7\x7a\x62\x32\xb8\x8b\x4a\xbf\xfc\x53\x62\xfd\xe7\xde\xc3\x6b\x9d\x45\x48\x80\x84\x92\x83\xb1\x15\x63\x39\xea\x2e\x8c\x3b\x10\xe5\x1b\xfa\xbd\xf7\x25\x78\xc7\x26\x41\x9a\x38\x54\x2c\xf8\x64\x9d\xf9\xa0\x90\x9f\x58\x2d\xeb\xad\x5f\xd8\x9d\x8c\x81\xf8\x3d\x9e\x42\x3e\x75\x03"}, -{{0xb9,0xda,0x4e,0x6a,0xf0,0x7e,0x39,0x8a,0xb4,0xd2,0x17,0x52,0xa3,0x2c,0x8f,0xfa,0x9b,0xe0,0xc3,0x10,0xd3,0x50,0x59,0xfb,0x66,0x1b,0xd7,0x3a,0xfa,0x97,0xe2,0xa8,},{0xf8,0x62,0x80,0x3c,0x96,0xcc,0x42,0xad,0xc8,0x25,0x28,0x84,0x54,0x72,0x30,0xb9,0x70,0x04,0x7b,0x7e,0x5d,0xa9,0x96,0x26,0x0c,0xcc,0x02,0x40,0xab,0x71,0xa6,0xec,},{0x62,0x5e,0x1f,0x42,0xc8,0x74,0x34,0xa2,0x5d,0x62,0x2d,0x80,0xd1,0x25,0x32,0x80,0x6a,0xfb,0x25,0x09,0x33,0x24,0x49,0xe6,0x96,0xb6,0x5e,0x1e,0x58,0x88,0x50,0x8f,0x11,0xc4,0xac,0x25,0xf5,0x9b,0x8d,0x94,0xd0,0xbf,0x27,0xe4,0xc8,0xd1,0x86,0x70,0x07,0xc4,0x08,0xda,0x57,0x30,0x82,0xdc,0xf1,0x9d,0x15,0xa9,0xd5,0xcc,0xcb,0x0c,},"\x6b\x95\xaf\x0e\xeb\xb6\xa0\x8a\xfa\xda\xa1\x96\x21\xf7\x6a\x83\x9b\xe8\x08\x51\xc6\xdd\x31\x5e\x82\x76\xf5\x01\x99\x5d\x4c\xe6\xd1\x34\xdf\x5e\x79\x8e\xd5\x17\xa2\xf0\xe6\x2a\xa1\xd6\xc9\x8c\x36\xef\x14\xbb\x1e\x5d\xdf\xc9\x8d\x5a\x7f\xcc\x81\x14\x0a\x13\xc2\x0d\x2c\xa0\xc4\xb4\x0e\x6e\x6a\x03\xee\xd8\xc8\x99\xf9\xd1\xf7\x92\x46\x81\x52\x19\x9f\x4b\x95\xa4\x32\x66\x89\x47\xa5\x1d\x7b\x8e\x10\x4d\x8d\x1f\x12\xaa\xcd\x96\x7e\x08\xb0\x8c\x41\xc3\xc8\xca\x3f\xee\xda\xa5\xb8\xb6\x3b\xce\xc0\x61\x38\x64\xd9\x53\xd8\x11\x43\xec\x81\x42\x5b\xde\x29\x16\x4a\x08\x76\xf2\x3f\x37\xac\x9a\xc9\x47\x36\x72\xce\x11\xa0\x8b\xd5\x47\x6f\x6f\x66\xd6\x65\xe9\xad\x61\x7e\x34\xeb\x32\xee\x56\xff\xa4\x59\xf2\x0d\x1b\x93\x53\xd7\x82\x12\x98\x54\x57\x50\xc6\xef\xf3\xe7\xd4\x07\x3d\xc3\x18\x5e\xde\x03\x91\xcc\xe0\x57\x5f\x8b\xa6\x37\xd8\x00\x06\x8d\x9d\x7e\x54\x03\xba\x70\x38\xd2\xdb\x77\xda\x14\x47\x84\xf2\xe8\xea\x76\xae\xdf\xe5\x21\xe7\xdc\x6a\x67\x4e\xde\x35\x57\x95\x95\x99\x3f\xb2\x0d\x44\xb4\x05\x27\x83\xf5\x6c\x8c\x0b\xbd\x04\x40\xb6\x9e\xab\xde\x84\x46\x8d\xd1\x3c\x67\x1f\xb1\xbb\xd5\xcb\x02\x2c\x2a\x4f\xcf\x35\x42\xd8\xb3\xbb\x51\x8e\x5a\xde\xbd\xdc\x84\xe7\x14\xb1\x3b\xe5\x2c\x56\xb2\x82\xb4\x2a\xc0\x89\x2a\x54\x59\x28\x1b\xe7\x16\x07\x29\xf4\x11\x2c\x7d\x99\xdf\x9b\xe5\x43\x4f\x82\x3a\x9c\xe0\x50\x17\x89\xde\x1d\x55\x0a\xd5\x0b\xb1\x8c\x8d\x89\xa3\x36\x68\x27\x0b\xff\x7b\x91\xff\x11\x8f\x5c\xd9\x90\x9a\xdd\xde\x90\xc0\x24\xa3\xad\x71\x39\x15\x17\x46\x74\xf2\x8a\xaa\x9f\x94\xa3\x22\xba\xa5\x43\x73\x8e\xda\xb4\x97\x33\x12\xb5\xbf\xa1\x21\x55\xde\xbc\xee\x16\x3c\xfe\x2b\x04\xac\x9c\x12\x2a\xc8\xa4\xe1\xbc\x41\x8c\x14\x95\x5d\x96\x10\x45\x5b\xd9\x45\xe9\x79\x3b\x91\x62\x67\xc9\xc5\xf9\xe5\x3a\xc0\x45\x18\x92\x6e\xc9\x8e\xcb\x84\xa4\xf0\x44\x5d\xcb\x12\x36\xc7\x6c\x3a\x67\x8c\x69\xab\xe4\xe9\x2c\x22\x97\x1d\x62\x21\x72\x01\xa1\xbd\xf0\x5c\x04\xdf\x84\x20\xa3\xde\x6a\x91\x7a\x85\xe7\x1e\x2b\x97\x25\xe7\x7b\x52\x29\x15\xd4\xc9\x94\x60\x77\x63\x7c\x2d\x88\x13\xf0\x10\xb9\x49\x1c\xf0\xed\xdc\x3d\x46\x68\xcc\x0f\x8b\xc8\xa6\x83\x57\x9b\xe5\x43\x93\x4d\xa2\x85\x3a\x16\xf5\x71\x57\x24\xf7\x79\x81\x9f\x44\x43\x9e\x1d\xeb\xca\xa4\x27\x0d\x9b\x85\x94\xba\x4c\x86\xe1\x06\x3b\x3c\xe4\x79\xd7\x1a\x54\x09\xbe\xf2\x7e\xf4\xe5\xc1\xd1\xc9\x6e\x8b\xe1\x38\x65\xaf\x7b\xb4\x3f\x09\x16\x2c\xcb\xc8\x3a\x2c\xa9\xe9\xb8\xa2\x32\x4e\x6d\x99\x65\x75\xee\xfe\xd3\x7e\xf4\x99\x08\x18\x57\x38\xb8\xea\xe4\x3f\x8a\xdc\xa3\x30\xc9\x9b\xc6\x6c\xc1\xfd\x52\xc5\x30\xd7\x37\x1c\x60\x86\x9c\xe4\x2c\x19\x7d\xca\x0a\xd1\x28\xb8\x5f\x61\xc8\x75\x8f\x0d\x54\x2f\x3d\x32\x98\xb6\x5e\x93\xc6\xe8\xa6\x8f\xa0\xe9\xa1\xd5\xe8\xc5\xfe\xc8\x05\xb8\x3a\xff\x43\x90\xe1\x15\xeb\x64\xf3\xf0\x78\xa0\xb9\xb6\x6c\x27\x38\x43\xfc\x6c"}, -{{0x14,0x3f,0x7b,0x42,0x47,0xd5,0x49,0xf6,0xb7,0xc0,0x91,0x72,0x66,0xc5,0x0f,0x96,0x2c,0x28,0xa2,0xea,0x24,0x76,0x2f,0x53,0x7a,0xa0,0x6a,0xd1,0x5e,0x40,0xb3,0x5a,},{0xc9,0x95,0x9f,0x90,0xa2,0xd5,0xfe,0xac,0xba,0xe2,0xc4,0xc8,0x03,0xde,0xd5,0xde,0xab,0x86,0x98,0x76,0x37,0x06,0x43,0x37,0xaa,0x2a,0x0b,0x0d,0xde,0xf2,0xfd,0x86,},{0xc1,0xcf,0xae,0x58,0x51,0x57,0x13,0xea,0x72,0x8c,0xfa,0x09,0x09,0x0e,0x89,0x42,0xf8,0xdf,0x18,0x62,0x1b,0xa7,0x09,0x0e,0x3a,0x33,0x76,0xc3,0x80,0x27,0x75,0xa1,0xec,0xaf,0x43,0x6b,0x18,0x49,0x78,0x04,0x1e,0xbb,0x75,0x22,0x6f,0x97,0x0d,0xf7,0x1d,0x6a,0xd3,0x53,0xc0,0xfb,0x46,0x50,0x23,0xf9,0xe2,0x98,0xf6,0x4a,0x70,0x02,},"\xe2\x74\x20\x23\x47\xa0\xd0\x57\xa4\x8b\xf2\xa1\xf6\xe9\xf6\xcb\x42\x56\x07\x9d\x80\x03\x74\x09\x3c\x02\x0c\xbf\x52\x0e\x5f\xa2\x7f\xe9\x96\xff\x07\xf3\x3a\xd3\xb2\x1f\x74\xab\x0c\xd9\x3c\x86\x47\x5f\xf3\x7c\xf6\x22\xd3\xf9\xfa\x4d\x13\xbc\x99\xf0\x13\xe8\x50\x2b\x24\xe4\x6c\xc8\x7c\x47\xe6\xb2\xc3\x66\x2b\x50\xe9\x79\xa0\xf3\x45\xb7\x84\xff\x21\xa8\xa4\xd9\x2a\xdc\x65\xe8\x6e\x33\xb4\xdb\xe1\x7f\x52\x8c\xcd\xf5\xb4\x86\x46\x64\xba\x94\xff\xdb\x7c\x7d\x24\x12\xb4\x38\xe6\xe4\x3f\xa9\x66\x81\x47\xee\x33\x28\x22\x4d\x1f\x52\xa3\xf5\xb5\x43\x59\xb4\xf7\xfe\xf6\x9a\xf8\xf8\x67\xb4\x78\xf1\x30\xa1\x47\xbe\xa4\x2e\xd3\x98\x03\xbc\xbc\x25\x57\xbc\xa8\xc3\x99\x9f\x1d\x24\xf0\xa6\xb0\x3c\x98\x84\x60\x11\xf9\xec\x74\xf6\x66\x41\x7b\x95\x02\x0e\xb1\xfb\x2f\xb8\x8b\x63\x12\xe5\x00\x8c\xff\x03\xe2\xd7\x7a\x26\xaa\x53\x2d\x17\x80\xb5\x07\x7f\x9e\x8b\x82\x86\x74\x45\x5d\x6b\xc9\x57\x97\x5f\x7b\x2a\x50\xe7\xfd\x7c\x16\x12\xce\x02\x36\x2e\xfa\x4c\x55\x5a\x1e\xef\x68\xec\x34\xa5\xc0\x06\xa6\xda\x00\x8a\x31\xd4\x19\x3d\xc2\xcc\x64\x76\x85\xad\x3c\xfa\x3b\xd7\xc5\x60\xb7\xae\xd4\x5f\x0f\x1a\x3d\x1b\x5b\x36\x22\x68\xde\x53\x28\x57\x05\x5a\xb9\xd1\xd5\xd8\x58\xd9\xae\x9a\x75\x9a\x51\xbb\x94\x78\xe8\xf0\xee\x93\xc9\x84\xb5\x76\xb8\xb4\xab\x46\x02\x80\xbe\x3d\xe2\x05\xa3\x2f\x1d\xc3\xd5\x72\x92\x3f\xb2\x13\xac\x15\x12\xd8\x0e\xb5\xad\x5c\x18\x94\x4b\xe7\x7f\xc1\x7d\xef\x13\xa6\x1b\xbd\x31\xbc\x71\xac\xc2\x3d\x25\x0e\xc5\x89\x4e\xbc\x21\x4c\xfe\xc0\xc1\xb9\x06\x51\x6d\x32\xd8\x36\xad\xc8\x38\x80\x2e\x8d\xe3\x0d\xd7\x6d\xf6\xe6\x1c\x1b\xc4\x38\xb6\x8d\x2b\x02\x5a\x84\xf2\x11\xfa\xcf\x3f\x13\x84\xd2\x61\x2d\x0f\xae\xf5\xd1\x71\x31\xcf\xe0\xcf\xe8\x33\xfe\x95\x0e\x47\x9b\xc2\x9c\xbe\x7f\xd6\xda\x0c\xce\x30\x7c\xf0\xb1\xbd\x92\xc8\x0e\x87\x8e\x43\x2f\x63\x6e\xa0\xcd\x42\x48\x0c\x07\xe8\xb8\xe5\x7e\x69\xb2\xf9\x38\xb7\x81\x20\xf6\xaf\x4a\xbe\xbf\x7d\x4b\x05\xca\xcd\x6e\xed\x85\x44\x91\xc0\x29\x75\x5c\x4e\x66\x33\x89\x93\xed\x2a\xc2\x5d\x19\xa0\xc5\xb4\x0f\x5e\x32\xc8\xa8\xb1\xbc\xe3\x69\x71\x81\x86\xc9\x1d\x60\xed\xff\x24\xa8\x37\x7a\x99\x69\x75\x75\x99\x06\x7d\xd3\x12\x63\xa0\x6d\x6a\x61\x15\x47\x81\xf2\x96\x11\xab\x81\x2f\xf8\x2e\x81\x37\x39\x64\x62\x63\x70\x4c\xd6\x04\x63\x57\xa2\x3c\x04\x5e\x24\x07\xb7\xa8\x95\x08\x25\x93\x91\x31\x4f\x2f\xbe\xe4\x9a\xef\x08\x55\xc6\xe5\xe6\x3d\x91\x2a\x19\xdf\x15\xb1\x1e\xce\x34\xe2\x76\xdc\xb8\x8b\xf2\xf2\xe4\x75\x63\x58\xf3\x4a\x0e\xe3\x95\x2b\x68\x6f\xcd\x17\x57\x8a\x88\x41\x76\xd3\x4e\xa2\x91\x6c\x5d\x9f\xcd\x00\xeb\x9e\x0a\xa9\xf2\xcf\x0f\x16\xe2\x56\x4b\xfd\x28\xb6\xab\x59\x68\xb8\x44\x8f\x06\x83\x20\xe4\x18\x71\x60\xf8\x66\x57\x81\xb1\xe2\xed\x9d\x04\x9e\x1b\x54\xa7\xd7\x27\x20\xff\x9d\x4f\x07\x30\x51\x99\x6a\x9d\xb6\xf0\xc6\x82\x1c\x42\x4f\xa5\x1d"}, -{{0x0d,0x1f,0xe9,0xd8,0xb9,0xa2,0xf0,0x4c,0x22,0xbb,0xb0,0xed,0xea,0x38,0x33,0xa0,0xce,0x43,0x33,0x93,0x47,0x53,0x1f,0xdb,0x67,0xed,0x51,0x3a,0x13,0xd3,0x6b,0x39,},{0x67,0xc4,0x9f,0x41,0x0f,0x48,0x53,0x29,0x3d,0x0c,0x4d,0x39,0xf4,0xc1,0xb3,0xd6,0xc6,0x10,0x3c,0x5c,0xfe,0x20,0xa9,0xa5,0x9b,0x53,0x93,0x20,0x43,0x51,0x73,0x69,},{0xb0,0x57,0x25,0xe7,0x37,0x1e,0xd0,0xa9,0x1e,0xbc,0x89,0xf3,0xc3,0x0b,0xaa,0x99,0x18,0x37,0x63,0xed,0xb4,0xce,0x34,0xfe,0x90,0x1a,0xf3,0x73,0x1e,0x00,0x1c,0xc5,0x4f,0x28,0x71,0x18,0x91,0x5e,0x90,0x36,0x5d,0x91,0xac,0xa8,0xfe,0xb1,0x70,0x87,0x69,0xf9,0xf1,0xd6,0xee,0xf5,0xaa,0x11,0x3b,0xee,0x00,0xb5,0xef,0xab,0x27,0x04,},"\x64\x21\x7a\xc8\x41\xfd\x4d\x64\x59\xbf\xc4\xa4\x9b\x88\x01\xd6\x92\x9b\xf1\x9b\x40\x8e\x8a\x53\x79\x0c\xeb\x51\xec\x34\x1f\x9b\x46\xa3\x51\xe8\xc2\xe5\x9d\x88\x7e\x1e\xac\xcb\x91\x42\x31\xcd\xca\x1d\x3e\x5c\x47\xd1\x66\xb4\xcd\xb9\xb5\x8c\x01\x3c\x59\xa3\xbd\x28\x3a\xd1\x0f\x6b\xd6\x2c\x0f\x15\xf7\x64\xce\x14\xf3\xb2\x65\xf5\x37\xc6\x3e\x73\xb6\xc4\xfa\x65\xe0\x6c\xe1\xe1\xf4\xae\x0d\x11\x48\x9d\xd2\x60\x2f\x95\xfc\x40\x2b\x77\x12\x05\x2a\xbc\x84\xbd\xc7\x78\xc1\x9f\x10\x00\x1b\x4e\x0d\x5f\xbe\x46\x30\x90\xe8\x3e\xf4\x38\xfe\x06\x8f\x3b\xb6\xfb\xc2\xc1\x39\xaf\x06\x78\xed\x2a\x11\xfa\xa1\xb9\xe4\x9a\xaa\x46\x20\xab\xfc\x08\x43\x9f\xbf\xe2\xc6\x18\x40\x76\x9e\x5f\xda\x26\x77\xf8\xe2\xf0\xa1\x45\x64\xf9\xf5\x04\x23\x2a\x9f\xc0\xd9\xda\x47\x1e\x67\xfb\xc5\x74\xc3\xd5\x6d\x2a\xeb\x93\x7a\x58\x6e\xd5\x58\x35\x56\x30\x8a\x99\x8e\xb1\xdc\x47\x6a\x01\x4f\x5a\x08\x22\x8d\xbe\xd9\x5a\x12\x08\xbc\x1d\x1f\x5d\x76\xb4\xe8\xd0\xb2\x43\x4b\x99\x5a\xd4\x58\xe4\x29\xee\x61\x42\xa0\xc9\x71\x76\x8c\xc4\x0c\x40\xbc\xb0\x8e\x96\x03\xf0\x96\x11\x47\x44\x71\xb3\x85\x9d\x7f\xd5\x84\x21\x9f\x02\x65\x7b\x43\x0e\x9e\x56\x95\x5b\x34\x67\xac\x56\xff\x2e\xab\x22\xcc\x49\x84\x89\x03\x6a\x57\x41\x20\xe2\xdb\x76\x9a\x3b\x21\x50\x03\x89\x14\x2c\x78\xa8\x7d\x06\x9f\x0e\x25\x76\xca\xfd\xa8\xcd\xdd\x79\x15\xa9\x22\x87\x73\xd2\xac\x9a\x07\x5c\xb3\x87\xf2\xa8\x98\x61\x72\x13\xb2\xcc\x50\x59\xd1\x19\x41\xbc\x4f\xe5\x86\x41\xe7\xc1\x75\x02\x67\xe5\x3e\x99\xc4\x21\xcb\x4c\xf2\x1d\x09\x8c\xa2\xd1\xf4\x16\x44\xf7\x90\x89\x83\xeb\x17\x4a\x23\xa7\x81\xcf\x15\xef\x38\xeb\x91\x16\xed\xa4\x12\x3a\x15\x22\xf5\x3b\x81\xfb\x73\x68\xe8\x07\x5f\xb8\x38\x59\xd2\xcf\x98\xd9\x21\x53\x5a\x70\x9f\xaf\xa9\x87\x3c\x4a\x03\x9a\xae\x68\x2f\x7e\x62\x86\xb8\x99\x25\x7c\x09\x24\x01\x6c\xa5\xbf\x6d\x31\x69\x09\x92\x11\xa9\xa4\xa6\x74\x5c\xdd\x31\x98\xf1\x33\x7f\x60\x92\x82\x27\xce\x3c\x7d\x60\x96\x0b\x53\xde\xdf\x01\x1a\x89\x40\xf5\xc4\x68\x20\x7a\x38\x94\xbb\x08\x72\xb3\x33\xcc\xde\xc9\xd5\xec\xd9\x11\xec\xbb\xb9\x6c\x9b\xc4\xbd\x48\x75\x32\x0e\x4d\x3e\x9c\x02\xd9\xdc\x76\x10\x9e\xc4\x5e\x61\xd1\xcf\x5a\xc7\x29\xf2\xe3\x4a\x96\x47\xb9\x5b\xce\x70\xb0\xc6\x33\x17\x1a\xda\xf0\xdf\xdb\x5a\xfb\xa4\x03\x5b\x3c\xce\x8c\xb7\x14\x1a\xd1\x42\xbb\x7a\xdd\x4f\xc3\xf9\x61\xd4\x2d\x72\x03\x75\x4a\x4e\x31\x32\x21\xd4\x87\x83\x1e\x32\x94\x7d\xa9\x11\x38\xab\x64\x8b\x59\x52\xef\x69\x56\xe2\x7a\xa5\xd2\xc1\x75\x79\x4b\xf8\x1e\xf2\x77\xfa\xa6\xb9\x05\xe1\x45\x02\x86\x68\x87\xd8\x78\x80\x60\x6e\x81\xb2\x7a\xf0\x1b\xb2\x63\xec\xf2\xc5\x82\x05\x85\xea\x6c\xe8\xd8\xb3\x91\xd8\x6f\xce\xda\xdc\xd1\x1f\xdb\xb5\x66\xfd\xf1\x47\xf4\x02\x01\x0f\xc3\x5f\x51\x57\xe0\x36\x14\x6b\x37\x36\xc8\xa4\x33\x59\x12\x7c\x26\x1f\x6b\xf0\xca\xd3\xbd\x8a\x34\xcb\x15\x09\xf7"}, -{{0xc1,0x0b,0x5a,0xc6,0x05,0x5a,0x1d,0xdb,0xca,0x28,0x55,0x2e,0x5c,0x72,0xeb,0xd0,0x52,0x78,0xc9,0x22,0x39,0xb2,0xfc,0xd0,0xc1,0x35,0x36,0x51,0xa8,0xe5,0x59,0xa0,},{0xb2,0x18,0x3e,0x1b,0x00,0x81,0x6d,0x29,0x30,0x5f,0x74,0x68,0xe7,0xe4,0x5e,0xed,0x3f,0xd8,0xf2,0x3c,0x15,0xb3,0x05,0xf9,0xfd,0xa9,0x3e,0x81,0x2d,0x65,0xbc,0x27,},{0x8a,0x9a,0x32,0x17,0xfd,0xf0,0x64,0x3a,0xaa,0xa5,0xc8,0xfb,0x2a,0x88,0xa5,0x56,0x39,0x88,0x59,0xb8,0xfe,0xef,0xbc,0xb4,0x8c,0xcd,0x88,0xe5,0x85,0xa1,0x67,0xc9,0x4d,0xbb,0x5c,0x0c,0xad,0x24,0xd1,0x5b,0xca,0xbb,0xc1,0xed,0xb2,0x1f,0x02,0xa8,0xc4,0x57,0xc5,0x61,0x20,0xa3,0x23,0x4a,0xc3,0x35,0x77,0xb9,0xaf,0x2d,0xdc,0x01,},"\x35\x94\x90\x5f\x9e\xa4\x64\x61\x5f\x41\xb8\x7a\xbb\x9d\x16\x73\x37\xf2\x9d\x45\xd9\x7f\x7a\x14\x64\xec\x9f\x2e\xe5\x0f\x90\xf2\xe6\x73\x39\x87\x4d\x3f\x20\x93\xbe\x92\x26\x10\x77\x01\xec\x1a\xab\x94\x1c\x4e\x05\x9f\x1b\xb2\x6c\xe8\x6e\x14\x8d\x1d\x9f\x0d\xa2\xa2\xa0\xf9\x82\x9a\x36\x4f\xb4\xf1\x3f\x58\xb9\x60\xd0\xf8\xd7\x23\x23\x28\x3c\x44\x90\xef\xdf\x57\x87\x86\x45\x89\x0f\xf7\xbc\x50\x65\xda\xd6\xe5\x1d\xd1\xe5\xb9\xa5\x07\x51\x50\x97\x8b\x33\x67\xf1\xba\x84\xe4\x5f\xf1\xf1\x27\x6c\x57\x6e\x4b\xc7\x2b\xe8\xaa\x8e\x40\x5f\xc2\xb2\x7f\x81\x46\xb9\x99\x84\x5f\xaa\xa0\x59\x5d\x3c\xb7\x0e\x5d\x37\x12\xed\x54\xa0\xfb\x3e\x32\x2d\x45\x38\x0b\x5d\xe3\x60\x9b\x96\x7b\x95\x9b\xca\x5a\x58\x3c\xc5\x20\xcd\xcb\x7b\xcb\xb8\x29\xaa\x25\xd7\x93\x20\x95\xec\xb3\x03\x92\x3c\x25\x60\xaf\xc3\xfd\x73\x24\xb7\xb7\xac\xd0\x89\xa9\xf0\x0c\x03\xa7\x3d\x04\x3d\xc0\xcf\x0b\xa0\xd8\x41\x1e\x2b\x1b\x18\xd2\x1d\x2a\x32\xa7\x26\xa5\x30\x59\x14\x0f\x78\x4f\x7c\xed\xf2\xf3\x3c\xec\x66\xfe\x4a\xd5\xcc\x9e\xac\xcb\xe4\xae\x10\x03\x6a\xc3\x52\x3b\xac\x70\x0a\x11\x3a\x98\xb5\x98\xe6\xdf\x03\x04\xc6\xfa\x32\x12\xac\xc0\x4c\x4e\x3c\x7f\x66\x87\x36\x2e\xf8\x6d\x61\x7c\x6d\xd4\x83\xf8\xd8\x0c\xea\x66\xd1\x95\x11\x27\x42\x8a\x61\xc1\xe1\x55\xa6\x85\x0b\xb2\xaf\xb7\xf9\x1c\x82\xd7\x3e\xb2\xb0\x54\x3e\xe8\xfc\x1f\x38\xe1\xdc\xdb\x3c\x50\x3d\xdc\x9b\xa0\x81\x24\x56\xa5\xce\x2e\x11\xd5\x56\x48\x7a\x64\x69\x74\xa7\xbb\xf8\x6e\x80\x6c\x58\xc6\x8c\x42\x69\xa7\xc9\xbb\xca\xc0\xff\xef\x98\x35\xb3\x3d\xc4\x49\xa7\x54\x79\xec\xd2\x3f\x6d\x14\x9c\x1e\x5e\xa8\xb6\x92\x08\xff\x36\xe5\xfb\xd6\x82\x95\x55\x03\x18\xbf\xa0\xd3\xb1\xd6\xc1\xad\x42\x70\xbc\xab\x09\x04\xae\x53\x49\x1f\x9b\x1c\xa5\x02\xe0\x12\xee\xd7\x7c\x42\x7d\x49\xa0\x96\x2f\x10\x55\x12\x5d\xd7\xb5\x37\x33\xd8\x52\x89\x34\xb5\x58\x0d\xd5\xfd\x5b\xbe\x85\x49\x78\xba\xe3\xd2\x5b\xb4\xae\x94\x4e\x90\x65\xe8\xe2\xe0\x79\x46\x51\x8a\x6f\x54\x8e\x36\xe0\x56\xbe\x82\x4d\x9e\x02\xa7\xa3\xea\xad\xd3\x79\x29\xf5\x81\x01\xcb\x18\x53\xbe\x3d\x75\x47\xf5\x8f\x49\xe3\x8b\x01\x8a\x74\x8d\x3f\x19\xc4\x85\x82\xab\xbd\xbe\x95\x3a\x8a\x25\xba\x9d\x36\x5d\xea\x83\x59\x35\x89\x9c\x19\xfb\x0b\x51\x90\x6a\xa9\x72\xc5\xac\x45\xe9\x9c\x40\xb3\xb7\x6e\x35\xd3\x27\xe3\x21\xe8\xae\x23\x06\xa6\xeb\x3d\x8c\xb6\xec\x2f\xa5\x39\x9a\xdd\x19\xea\x00\x28\xa0\x17\x92\xc0\x8e\x27\xc1\x6c\xf4\xf8\x5a\xaa\xae\x72\xf9\x86\xb0\x99\xf9\xeb\xe4\xad\x0b\x25\xd0\x6d\x3d\xe4\x4a\x8b\xfa\x52\x84\x4b\xe4\xa9\x39\x44\x83\x3c\xe2\xad\xd5\x1b\xb5\x54\xb3\x56\xa7\xdc\x49\x74\x8d\xd4\x5a\xe7\xec\x9e\x8d\xb4\x26\xc9\x7a\x25\xda\x5e\xdd\x3b\x62\x1e\x4a\xdb\xde\x48\x19\x7a\x33\x14\xde\x1c\x50\xf4\xd6\x00\x20\x27\xdd\x75\x19\xdd\xe3\xe1\x57\x29\xe4\x86\x95\x5a\xc4\x0d\x9d\x66\x87\x6f\x90\x66\x8c\x68\x9d\x8a\xb5\x98"}, -{{0x06,0x1b,0xdd,0xab,0x28,0x0b,0x0f,0xdc,0xb2,0x6b,0xfd,0x9a,0x0f,0xc7,0x21,0xf6,0x8f,0x88,0x34,0x3b,0x5d,0x39,0x83,0xa1,0x6b,0x6d,0xfa,0xa5,0xe7,0x69,0x69,0xf3,},{0x81,0x55,0x78,0xbb,0xa6,0xe7,0x07,0x0e,0xbd,0xec,0xa1,0x17,0x56,0x8b,0xd7,0x7e,0xbf,0xf9,0xe1,0x4c,0xb8,0xbc,0x20,0x0c,0x32,0xbd,0x87,0xdb,0x1f,0xb3,0x7d,0x6c,},{0xb8,0x32,0x97,0xcc,0xdd,0x6d,0x00,0x98,0xeb,0xf5,0xd1,0x32,0xd1,0x74,0xde,0x19,0x58,0x31,0x1a,0x76,0x6b,0xcc,0x4d,0xa1,0x5f,0x86,0x4d,0x80,0x1f,0x38,0xe0,0x9d,0x61,0x3e,0x7a,0xa8,0xc3,0x36,0x30,0x27,0x35,0xd7,0x5b,0xe4,0x16,0x6d,0x73,0xb0,0x18,0x4b,0x0e,0x0b,0xc5,0xef,0x39,0xed,0xbc,0xcb,0x6e,0x0e,0x61,0xaf,0xeb,0x0c,},"\xee\x76\xb4\x0c\xd4\x29\xea\xc7\xbc\x12\x83\x9c\xa2\xf7\xcd\x31\xf1\xe0\x09\x8a\x39\xc5\xfc\x19\x80\x5b\xe0\x33\x1f\x44\x79\x9e\x31\x8d\x12\x57\x1f\x06\xe2\x99\x37\x53\xa3\x68\x5c\xd2\xa9\x6b\x23\x01\xe2\x00\x24\x20\x9a\xdc\x5a\xdf\x74\x79\xff\x90\xc4\x77\xc3\x69\x5a\xbb\x99\xbd\x28\x57\x9d\xbc\x78\x31\xa1\x92\xbe\xed\x0c\xe1\x7b\x03\x8b\x20\x76\x48\x00\x65\x3a\xf7\xaf\x02\x4e\x2a\x10\x4e\xd0\xf3\xe5\x2d\x4b\xbd\x3e\x10\x9c\xf1\x26\x29\x1f\x49\xb0\xa2\x1b\xe4\x33\xc1\xc5\xa2\x58\x9e\xa5\x72\x99\x7f\x63\xd2\xbb\x39\x72\xd5\x32\xbe\x35\xa0\x47\x1e\xf0\x57\x3d\x79\x5c\x07\x2b\x6a\x86\x85\xb9\x5e\x47\xb0\x9e\xa9\xf4\x75\xd9\x3b\xf1\x2b\xbd\x77\xb7\xd2\xbf\x5d\x5b\xdd\xf0\xae\x02\x37\x53\x71\xd1\xd7\x99\xea\x92\x04\xbe\x38\x9e\x6a\x8e\x5d\xee\xdc\xd4\x92\x02\xe9\x2d\xf7\xc3\xe7\x61\xf9\x2e\xf8\xd7\x9f\xa7\x38\xd2\xc5\xbc\x28\x0e\xd3\x28\x79\x83\x2f\xf2\xb0\x26\x42\x45\x89\xcd\xbd\x52\xd1\x5b\x60\xf2\xaa\x35\x26\xb8\x98\x84\x9a\x34\xa8\x5f\xf1\xc4\x7d\xc6\x55\x4b\x85\xac\x76\xaa\x79\x35\xcb\xf3\xf7\xbc\x80\xad\x00\x91\x92\xa8\x75\xca\x20\x9b\x40\xfe\xb0\x47\xcc\x44\x69\x68\xf9\x70\xda\x47\xb8\xcd\x67\xda\x7e\xb4\xe5\x4a\x0e\x5a\xb2\x0c\xb3\x5b\xc6\xfb\x7f\x13\x30\x7c\xe6\x7e\xb6\x20\x4a\x67\xce\x9b\xb1\xd1\x39\xc1\xb4\xbd\x5d\xbe\xd5\x80\x10\xc8\x7b\xf8\x31\xe6\x52\x2e\xe1\x82\xda\xd9\x45\x80\x4b\x76\x7c\x4d\xf2\x55\x4f\x15\xb9\xe9\xaf\xd2\x59\x9e\xf2\x58\xc6\x7a\x22\xca\xeb\x92\xa5\x79\x88\x00\x6b\xbc\x72\xc1\x04\xfa\xc7\xe5\x41\x3c\xd3\xd3\xb8\x02\xc8\x3e\x63\x9e\xaf\xe2\x12\xa3\x8b\xb7\xef\x77\x9a\xf1\xa9\x4e\xe1\x37\xf6\xc6\x06\x67\xbc\x48\xf2\x7b\xf4\xa2\x22\x41\xbc\x44\xbb\x60\x33\x83\x62\x39\xbd\x6e\xaf\x3e\x2e\x22\x31\x87\x84\x1e\x46\x41\xb0\xf4\xe9\xff\x8d\x5a\x41\xdd\xbe\xab\xb4\x13\x8f\x6b\x58\x5a\xce\x0f\xb6\xb5\x3d\xc3\xc9\xed\xc0\x37\x3b\x60\x47\xf2\x7d\x83\x5e\x8e\x24\x66\x44\xfd\x83\x2c\xcf\xe0\xdf\x25\xc3\xd7\xda\x18\x7c\x9f\xa0\x54\x20\xd4\x34\x55\xf2\xd0\x8b\x57\x19\x29\x38\x6b\x59\xc6\xe0\xe1\x0a\x35\x60\x1d\xa8\x99\xb1\xb4\xdc\x3d\x95\xb6\x7d\xd9\xa8\x38\x18\xb0\xa3\x18\xbf\xdd\xa0\x64\x64\xb4\xa4\x2d\x3c\xb9\x85\xf3\x0e\xc9\x7d\x6a\x2a\xf1\x32\x91\x15\x5d\x60\xce\xc5\x7c\xbd\x58\xd5\xcf\xcb\x35\xc1\x85\x35\xe8\xd2\x99\xb5\xb0\x07\x59\x08\x92\xea\x94\x9d\x1b\x13\x7a\x62\xb3\x9a\x43\x6c\xd7\xe5\xb9\xf8\xd1\xb6\x93\x8d\xba\xa6\x2c\x22\x68\xd4\x59\xc6\x22\x0a\x3e\x6f\xcb\xf8\x0b\xa0\x11\x8a\xcd\x23\x42\x56\x3f\xbd\xbc\x1f\x7c\x9d\xba\x7e\xa2\xc0\x72\xaf\xc8\xae\x21\x28\xe3\xeb\xca\x06\x44\xff\xd8\x16\x3e\x80\xa1\xa5\x57\xd9\xd3\x90\x34\xcc\xd9\xdb\xd1\x2c\x88\x55\xa6\xf9\x16\x5b\x08\x01\x83\x9c\xf6\xe0\x7a\x9f\xba\x4c\x64\xd9\xc0\x99\xe1\x54\x10\xe2\x90\xe6\x77\x03\x1b\x65\xcf\x7d\xeb\x00\x79\xbd\xad\xc5\x73\xcc\x05\x6d\x76\x66\xd9\x5d\x03\x3a\x0b\x6b\xdb\xa7\xec"}, -{{0x2c,0xab,0x5b,0xf5,0x5f,0xfa,0x91,0x4e,0x9a,0xd0,0x76,0x22,0x19,0x0d,0x34,0x3e,0xc5,0x5c,0x13,0xcd,0x91,0xb3,0x88,0xcb,0x75,0x00,0xff,0xe0,0x6d,0xf7,0xc1,0x80,},{0xb6,0x1e,0x43,0x2b,0xb9,0x7c,0xba,0xe3,0x88,0xa2,0x57,0x8a,0x74,0x84,0x99,0x8e,0x00,0xe9,0xad,0x3d,0xdf,0xd6,0xca,0xb8,0xd3,0xa5,0xfc,0x5b,0xa0,0x43,0x07,0xc8,},{0x4c,0xf0,0x8f,0x4f,0xab,0xbd,0x06,0xdc,0xcb,0xcc,0xe2,0xa7,0xa5,0x94,0x1f,0xe9,0xaf,0xdd,0xc4,0xd2,0xd0,0xbc,0x80,0x80,0x2e,0x93,0xb1,0x2c,0xb1,0x35,0xd3,0xac,0xf6,0x51,0x1e,0x0f,0xe4,0x11,0x3c,0x5e,0x3c,0x55,0x41,0xb2,0x7d,0x3a,0x21,0x50,0xa7,0x57,0x74,0x2a,0xc6,0x5f,0x95,0xa9,0xce,0x66,0x73,0xff,0x0c,0xd2,0x1c,0x0f,},"\x2c\x2d\x04\xdc\x3a\xd1\x98\x23\x59\xec\xd5\xbc\x3e\xe0\x35\xf3\x49\x8e\xed\xff\x61\x04\xa9\x3c\x60\x2a\xf2\x17\x9a\xeb\x2c\xb1\xf4\x1c\x5c\xdb\x0a\x77\xb1\x24\xf9\x46\xaa\x8a\x82\x4a\xa3\x07\x6c\x2e\x1a\xcf\xd4\x8f\x68\x07\x0b\x26\x27\x6a\x65\x6b\x4a\x47\x58\xab\x15\x1a\x6a\x9c\x41\xbd\x74\xe0\x9b\xbd\x9a\xdc\xce\x1e\x87\xa0\xa8\x0d\x17\xfd\x92\xe8\x5e\x4b\xda\x47\x2c\x98\x8b\x6b\xb1\x18\x3b\x7e\xe5\x9a\x09\xd8\x05\x70\x46\x6d\xb9\x0d\xd3\x74\x95\x79\xc4\xeb\x19\xab\x75\xfc\x15\x2e\xcd\xcd\x68\xcd\x10\x78\xef\x06\xe5\x93\xc7\x35\x16\xfa\x82\x91\x48\x1a\x66\x7d\x3f\x95\xbf\xeb\x14\x4b\xab\x59\xd6\xdd\xc7\x3a\x27\x95\xc1\x01\x7e\x09\x53\x6b\x31\x62\xe4\xbc\x58\xf8\xea\xd3\x89\x57\x01\x8c\xfe\xc7\x2b\xad\xbf\x22\x81\x9a\xb0\xb4\x06\xc6\x47\x30\xfc\x73\xfd\x9e\xe6\x1f\x74\x18\x7e\xda\x91\xed\x4e\x79\x93\xe6\x68\x84\xaf\x43\xef\x4c\x6b\xf7\xf7\xc3\x79\xe8\xf0\xf6\x3d\xcb\x80\x41\xe2\x6b\x8b\x82\x92\xb6\xb6\xd1\x90\xe4\xad\xf4\x30\xfa\x82\xdd\x74\xc5\x73\x85\xb9\x19\xc4\x46\xdb\x37\xb5\xe8\x76\x7e\x4a\x0c\x95\x01\x3b\xe8\x9b\x2b\xc4\xe9\xfd\x62\x75\x4a\x84\x44\x18\x40\x09\x68\xae\xd2\xdd\x32\x8d\x7b\x1d\xc9\x1e\x1a\x2b\x30\x09\xdc\x7a\xd1\x40\xa0\x68\x6f\x67\x31\x68\xa6\x0e\x88\xd8\x0c\x52\x0f\xc2\xdc\xfc\x56\xca\x9d\x4b\x0c\x88\x85\x90\x99\x23\x07\x14\xde\xc8\x3d\x26\xb4\x63\x05\x54\xdc\xb9\xc4\x90\x18\x95\xf7\x8f\x38\x34\xb0\x97\x66\xb6\x7a\x46\x5d\xe8\xc9\x49\x00\x65\xbf\x56\x83\x39\x24\x33\x99\xfd\xc9\xd5\x10\x03\x24\x66\x7c\x5a\xb2\x8f\x35\xc0\x0f\x61\x25\x63\x8e\x61\xda\xb7\x0d\x1e\xec\x48\x95\x1d\xe0\xfb\x3f\x7b\x23\xd3\xcd\x98\x24\x37\xc6\x34\x73\x41\x5b\xef\x37\x4a\x66\x32\x96\xf2\x98\x6b\x1a\xe9\x57\x9b\x9f\xfc\xe7\x1e\xc3\x5e\xec\xa1\x16\xd1\x94\xf8\xfb\xa9\xa4\x5a\x91\xba\xe2\x7a\xc4\x55\xdb\x71\xa6\xb0\x1a\x72\x9d\x0c\x13\x5f\xcd\xcb\xc2\x3e\x50\x4a\x29\x43\xc0\x0a\xa4\x20\x70\x51\x9d\x9c\xd7\x7a\xe6\x75\x4f\x31\xeb\x46\xa3\xe5\xbe\x9e\xeb\x3f\xc8\xd3\x1f\xf1\x82\xda\x9b\x08\x7b\xe3\x46\x2c\x84\x59\x12\x6e\x86\x29\x09\x23\x2f\xd5\xf2\xd8\x9c\x01\x81\x59\x57\x61\x1e\x6a\xe7\xca\xa9\x8b\x60\x53\x77\x6a\x77\x15\xc2\xf9\x3c\xcf\x03\x08\x87\x03\x0c\x56\xc2\xb8\x22\x6d\xae\x29\x77\x99\x5a\x6d\x3f\x1e\x9d\x79\x11\xa9\xc9\xd2\xa3\x03\xf0\xe0\x1f\x32\x33\x8e\xfd\xaf\x8e\xe6\x3f\xc4\x1b\x25\x39\x9c\xff\xd0\xb3\x5f\x7e\xe5\x67\x6b\xd8\xfd\x3d\xa2\xcb\xee\x4a\xe2\xea\x98\x08\xd7\xe7\x35\x83\xd9\x94\x33\x99\x31\x46\x67\x4a\x40\x40\xf4\x2f\x63\xd1\xb3\x13\x5c\xc7\x97\xa8\xd8\xf0\xb8\x85\x73\xa3\x28\x90\x69\x6c\xac\x94\x39\xd1\xe1\x5d\x19\x6d\x90\x90\xb6\x2b\x6d\xb7\xe6\x3c\x96\x47\x2d\x94\x6e\x66\x8c\xbd\xa1\xf4\xdb\x88\x93\x00\xcd\xcc\x25\xe8\x4c\x9f\x38\x57\xd1\xd9\xe5\x32\x41\xcf\x62\x5f\x39\x09\xaf\x1c\x8a\xaf\xf4\x30\x9f\x68\xf6\x54\xb7\xa1\x5b\x67\x71\x1c\x5b\x7f\x9d\xe7\x67\x75"}, -{{0xdd,0x7b,0x59,0xa3,0x3d,0x97,0x0b,0xef,0x62,0xe0,0xe2,0x1a,0x7b,0x6e,0x4c,0x30,0x96,0x06,0x86,0xf1,0x7f,0x49,0xaf,0xdb,0x4a,0x9f,0x4e,0x80,0x8e,0x35,0x5c,0x7f,},{0x53,0xa0,0xe5,0x72,0x77,0xd9,0xbb,0xee,0xcf,0x99,0xc4,0xd1,0x38,0xfd,0x66,0xfa,0xfc,0xae,0xc7,0xbc,0x5f,0x56,0x7f,0x83,0x20,0x80,0x0c,0x4e,0x58,0x4f,0xf8,0x2e,},{0x87,0x29,0x4d,0x22,0xd4,0xad,0x0d,0x08,0x14,0xe2,0xd6,0xd5,0xfa,0xf5,0x57,0x49,0xe9,0xb3,0x98,0x03,0xb4,0xd4,0xb7,0x87,0x9e,0x60,0xb7,0x77,0xc1,0xfc,0x41,0x58,0x4f,0xe1,0x51,0x35,0xba,0x11,0x23,0xff,0x5f,0x20,0x0d,0xb3,0x5a,0x34,0x68,0xdd,0x4d,0x58,0xda,0xd7,0x7b,0xd9,0x6e,0xe2,0xb8,0x88,0xa5,0xa8,0xb1,0x8c,0x32,0x04,},"\x75\x58\x03\x67\x93\x05\x18\x16\x8b\x0a\x76\x4d\x09\x58\xbe\xc4\xfc\x46\xcf\x59\x19\x99\xeb\x37\x37\xe4\x2a\x02\xea\x72\xd2\x10\xda\xad\x53\xe5\x4a\x7c\x2c\x13\x4a\x6d\x47\x83\x37\xd2\x63\x33\x68\x54\x81\x70\xed\xef\x0d\x85\x17\x9f\x30\x23\xe1\x50\x38\x68\xa6\xe5\xe2\x77\x5e\x41\x2a\xc0\x5f\x05\x89\xd4\x2a\x37\x7e\x75\xaa\x6b\x8f\x52\x20\xa7\x69\x9a\xe8\xaf\xf0\x10\x94\xec\x46\x9d\x63\x61\xd3\xe8\xf3\x86\x15\xed\xcd\xa4\xd2\xd5\x28\x9a\xcf\x73\xdb\x64\x56\x98\x57\x80\xc9\x2e\x07\xf6\x2c\x77\xa9\x09\xfb\x6e\xf5\x98\x82\x20\x62\xbd\x57\x2b\xf7\x05\x8d\xcb\x83\x5e\xf3\x44\x3d\x3e\x47\xb5\xc6\x03\xd9\x27\x36\xdd\x1d\xf2\x6b\xe4\xb9\x28\x3b\x76\xe3\x21\xd5\x5c\xe2\xb6\x38\xcd\xe2\x25\x77\xca\x59\xc9\x63\xc2\x47\x95\x56\xc5\x75\xcc\xb0\xd6\xd1\x8c\x80\x4e\x2e\xb0\x1f\xf5\x35\x81\xeb\x04\x0f\xfd\x2c\xc4\x67\x60\x73\x7a\x74\x67\x2e\xa6\xbf\x78\x05\x8a\x6a\x0a\x1f\x5e\xbf\x56\xde\xcb\xf9\x4b\x54\xaf\xb2\x3c\x11\xd3\x41\x79\xbf\x09\x76\xb4\x15\x80\x17\xd4\x07\xc9\x5a\x40\x1f\xa6\xf9\x62\x4d\x77\x13\x5e\xae\x81\x41\xeb\xea\x9f\x35\xd5\xf5\x1b\x3d\xed\x99\x5c\x7f\x70\xc0\x25\xb0\x94\xad\xef\x2b\x07\x1f\x97\x11\x55\xd7\x79\x6d\x61\x3a\x55\x0d\x09\xe7\xf4\xdf\xc3\x45\x17\xb3\xf8\xfa\x43\x93\x28\x6a\x2b\x22\x80\x17\xda\xf2\xe0\x15\x38\x7e\x13\x52\x7f\x63\x66\x1d\x3c\x13\xe7\x8e\x90\xfb\x29\x55\xee\xe3\x45\x73\x91\x19\xb7\x91\xf0\x5b\x07\xc8\xf4\x2a\x43\x6e\xfc\xad\x1e\xc5\xea\x10\xf3\x08\xf8\xe2\x3c\xa9\x8b\xc6\x5a\x5f\xd9\x39\x3e\xfa\xaf\xe5\xcd\xef\xba\x81\x05\x81\x70\xcc\x54\x93\xc0\x0c\xed\xf2\x54\x09\x74\x35\xd2\xe2\xfd\xe5\x5f\x86\x6b\xb8\x2d\xbd\xfb\x91\x54\x34\x49\x74\x86\x63\x59\x16\x7b\x46\x6c\xaa\x90\x9b\x91\x53\x0c\x9c\x7e\xe8\xc5\x3f\xa9\x01\x64\xbb\xd0\xb1\xfa\xdb\xdc\xd0\x81\x27\xf1\x9b\xe5\x03\x30\x71\x51\x8d\x3c\xf1\x0a\xe6\xbd\x6f\x98\x27\xe1\x20\x6f\x5e\xc0\x95\xc1\x98\x61\x70\xe8\xd5\xd8\xe7\x2e\x57\xd4\x22\x87\x01\xdf\x2a\x48\xc9\x54\x87\x30\x56\xcf\xdf\xba\xaf\xb1\x0e\x46\xa0\xc1\xf1\x44\xb1\xa0\xea\xcd\xd2\xcb\x66\xbb\x91\x2a\xc4\x71\x78\x7d\xab\xe4\x83\x53\x85\x91\x20\xb0\x34\x03\x56\x7c\x41\x5d\xdb\x88\xfc\x0d\x7f\xba\x40\x69\xbb\xfe\xf4\x06\xee\xd7\x24\xa1\x1a\xbc\x04\x1e\x8e\x7b\xeb\x66\x3d\x0d\xc9\x9d\xce\xf3\xac\x6a\x14\x90\x07\xb4\x2d\xd1\xf2\x2a\x77\xdd\x52\x90\x18\x14\x32\x51\x72\x22\x4a\x27\x78\xf3\x66\xfb\x9e\xb0\x2c\x81\x2b\x84\x2a\x42\x84\x25\x61\xc6\x8f\x2a\xc2\x31\xc2\x6c\xe9\xe8\xb1\x9a\xe9\x1e\xbf\xad\x3c\x0e\x9f\x66\x36\x3a\x13\xec\xd8\xb8\x97\xa3\xd0\x0a\x26\xd2\x57\x64\x8d\x56\xc6\x74\x74\x41\xca\x1c\x6e\xe9\x9f\x08\xdd\xad\x25\xd1\x16\xdf\xad\xab\x03\x83\x00\x0d\x3d\x72\x25\xcf\x2e\xff\x70\x76\xb2\xad\xab\x95\x22\x29\x25\x55\xf3\x19\x32\x06\x78\x60\x00\xd4\x2c\xa3\x4d\x70\x8d\xc0\x42\x84\xa9\x4d\x17\x4c\xc9\x2f\x10\x2e\xfd\xdf\x31\x48\xc2\x99\x69\x16\xd4"}, -{{0xd8,0x80,0xd2,0xfb,0x06,0x26,0x2f,0x57,0xab,0x87,0x78,0xe3,0x3d,0x16,0xb4,0x73,0x06,0x09,0x78,0xa6,0x54,0x9c,0xdb,0xcd,0x55,0x86,0xba,0x81,0x05,0xf5,0xac,0xa8,},{0x0d,0xe4,0x86,0xd2,0x11,0x5f,0xaf,0x2d,0x54,0x72,0x66,0x77,0x2e,0x43,0x0f,0xd9,0x72,0x7b,0xdc,0xac,0xe6,0xec,0xbf,0x2f,0xe2,0x3a,0xb6,0x0f,0x7b,0x52,0x54,0xb1,},{0x4c,0x00,0xa7,0x16,0x68,0xd3,0x21,0x3c,0x29,0xc7,0x04,0x1c,0x5a,0x03,0x7e,0xdf,0x13,0xc6,0x51,0x4b,0xd0,0xeb,0xc8,0x80,0xc9,0x09,0xca,0xff,0x15,0x06,0xa4,0x5d,0x27,0x80,0x9f,0xb7,0x4e,0x66,0x02,0xea,0x2a,0xad,0x0f,0x84,0x28,0x31,0xb7,0x4f,0xb3,0xd6,0x90,0x0c,0xcc,0x52,0x06,0x52,0xda,0x28,0x36,0x8f,0xd9,0x0c,0xa3,0x0e,},"\x11\x47\x43\xe8\x2a\x09\x93\xce\xc9\x70\x50\x67\xab\xd7\x7c\x16\x8b\x53\x67\x7e\xde\x5c\x15\x9f\xad\x36\xf0\x6f\xc1\xa1\x4a\xcd\x77\xf8\x83\x79\x9e\xd9\x88\x3f\x99\x15\xae\xa6\x38\xec\x17\x41\xf3\xf4\x21\x58\x55\xfb\x5b\x07\xdf\x37\x93\xbb\xe5\xb5\x68\xeb\x35\x94\x39\x1a\x9e\xf5\x72\x7f\xab\x93\xe5\x74\x69\xb3\x7d\xe1\x25\xb1\xe9\xf2\xe6\xfe\x2c\x3d\x1a\x10\xec\xf8\x7b\x6c\x0a\x66\x5c\x6d\x46\x0a\x17\x0e\xef\xb9\xbf\x71\x6c\xd8\xfa\xea\x97\x64\xf5\x79\xff\x34\xeb\xfa\x9c\x4c\xfb\x34\x70\x6d\x8d\xd7\xc9\xeb\x1d\x10\xb2\xdf\x46\x0a\x46\xbb\x57\x89\x43\x0b\xf4\x49\x15\x8b\x58\x24\xf2\xa3\xa7\xb9\x18\xb3\x3a\xcf\x2d\x9e\xbe\x90\x21\x6d\x1b\x7c\xbf\x4a\xf7\x70\xc5\xdb\x95\xfc\x62\xff\x3a\x3c\x38\x5c\x3a\x82\x17\x85\x3b\x73\x46\x63\x4a\xaf\x30\x60\x72\x88\xdb\x0c\x48\x3b\xd4\xc2\x22\xeb\x33\x2c\xb8\x9d\xc4\xa2\x17\xe6\x33\x4a\x26\x84\x13\xa3\x90\xbb\x37\x1a\xec\x35\x5f\xbe\x4c\x73\x6f\x7d\xa7\x5f\x9c\x88\x75\x41\xa2\xb7\xd0\xda\xc0\x18\xb6\x13\x8f\x02\x1e\x77\x26\x6d\xde\xce\x84\x68\x45\x2a\xda\x39\xf5\xe6\x3d\x02\x09\xb9\xd6\xda\xbf\x97\x54\x13\x25\x6d\xca\xa1\x5a\xc1\x4b\x60\x68\xe1\x77\x05\x6c\x7b\xf0\xf0\xf7\xc8\x84\xa3\x40\x20\x32\x29\x8c\xd5\x59\xa6\x31\x20\x39\x40\x06\x32\x32\x7f\x9c\x0e\x76\x3e\x52\x79\x8c\xb1\x77\xda\x44\x75\xe4\xb2\x40\x5c\x15\x7c\xa4\x27\x74\x11\x08\xd3\x3e\xd0\xb7\xa3\xf5\x34\x38\xce\x6b\x72\x5c\x6d\xd5\x81\x4a\xf5\x1c\xfa\x45\xdb\xce\xd5\x57\xf7\x26\xdb\x13\x0d\x55\xcd\xe7\x53\x3b\xc2\x09\x2d\x6b\x69\x9c\x2c\x87\x0a\xf2\x82\x73\x1e\x18\xd6\x51\xae\x85\xb3\xdb\x4b\xa0\x28\x53\xf8\xc8\x7f\xd5\xe3\xab\x69\xbc\x57\xb0\x8b\x81\xf8\x3c\x23\x9c\xcf\x22\xe8\x17\xe2\xad\xa4\xd0\xad\x14\x48\x7e\xd1\x46\x12\xc8\xb0\x97\x3e\xc0\x65\x0a\x55\xf6\xbf\x9a\xf4\xae\x92\x56\xad\x35\x46\xa3\xf6\x7d\xd3\x5d\x98\x7e\xf2\x19\x09\xa9\x4c\x50\xf0\xef\x06\x40\xe7\x55\xb1\xc4\xe1\xa0\x12\xaf\x0d\x31\x76\x6e\xeb\x5d\xf3\x1c\xd1\x04\xc6\x4e\xb6\x2e\xb4\xef\xb1\x39\xcf\x30\x57\x69\x40\x1d\x21\x3f\x96\xa4\x88\xd5\xee\x7e\x3c\xe3\x2b\x01\x92\xee\x8f\x08\x31\xbf\xbe\x8f\xe9\x5d\xe9\x56\x88\x6b\x52\x4d\x33\x19\xb7\x3f\xd5\x6d\xc6\x0e\x9f\x1c\x72\xd7\x81\x55\xa9\x7c\x6f\x43\x69\x7b\x20\x46\x6b\x3e\x7a\xeb\xd3\x57\xb9\x16\x96\xe7\x34\x8f\x45\x99\xb3\x4f\x35\x91\xed\xdf\xce\x2a\x7b\xd8\x49\xab\x16\xf7\xb4\x3e\xbb\x16\xe2\x3d\x6f\x52\x10\xef\xa3\x0a\xb3\xba\x8d\x32\xc4\x06\x62\xb8\x66\x2f\xd9\x11\x54\x4b\xc2\x45\x8c\x65\x69\xef\x75\xa9\xb9\xdf\x6a\x0f\x6d\x80\xd6\x58\xba\x86\xb2\x41\xca\x19\xce\x9a\x6f\xcf\x01\xd3\xda\xa9\x5a\xfb\x59\xc3\xd8\x9a\x18\xb9\x48\x62\x13\x94\x32\x7f\xc5\xe9\x20\xa7\x5f\x98\xf5\xe2\xb3\xd6\xc9\x5f\xd8\x52\xad\xf5\x67\xb6\xd3\x7c\x54\xd2\x97\x08\x56\xa5\x99\xf7\x49\xe2\xc5\x5d\xac\x7c\x23\xe3\xfb\x1a\x63\xbb\x4c\xc4\x7b\x8b\x94\xf3\xd5\x89\xac\x4b\xee\xf0\xaa\xd4\xe6\x29\x2f"}, -{{0x58,0x58,0x71,0x94,0x1c,0xc2,0x82,0xe3,0x33,0xd5,0x7b,0xbf,0xc3,0xd4,0xae,0xda,0x86,0x2c,0xfa,0x0a,0x37,0x50,0x30,0xcd,0x59,0x4b,0x36,0x92,0x84,0x8c,0x5f,0x00,},{0x4f,0x34,0x38,0x16,0xcd,0x48,0x05,0x0b,0x67,0x8d,0x3a,0xdf,0x70,0x00,0x88,0x77,0xc9,0xfc,0xf5,0xcb,0x66,0x2c,0xc4,0xad,0x2b,0x93,0x86,0x4c,0x02,0x09,0x07,0x07,},{0x29,0x88,0x56,0xe5,0x70,0x18,0x8a,0xef,0xca,0xd8,0x1b,0xb9,0x70,0xf0,0x76,0x96,0x57,0x70,0xc2,0x67,0x62,0xfe,0x29,0xe6,0x55,0x4d,0xc7,0xaf,0xcd,0xb8,0x01,0x72,0x3b,0xf6,0xc7,0x63,0xb4,0xcc,0xd6,0x5f,0x4e,0x15,0xd7,0xd8,0xea,0x38,0xfc,0xf6,0x7e,0xa9,0xd2,0x85,0x90,0xc7,0x92,0x55,0xc1,0xcf,0xeb,0xa7,0xb5,0xe4,0x5a,0x00,},"\x65\x1c\x10\x1b\x3e\x2d\xfe\xf0\x78\x3c\xe9\xf6\x1b\xd0\xa8\xbd\xc9\x30\x7a\xc0\x48\x8b\x9d\xd7\x0c\xd9\x0a\x7e\xd8\xf1\x79\xa7\x89\x35\x55\x62\x95\xb9\x1c\xc2\xb9\x72\x11\xe3\xb9\x81\xb8\xda\xfc\xb3\xd0\x6b\x76\xd0\xb6\xed\xa7\xfc\x61\x94\x5c\x0e\xe2\x65\x2c\x5a\xc4\x54\x25\x64\x96\xcb\x82\xf9\x8c\xc1\xcc\x92\xd8\x18\x93\xb1\x08\x2b\x31\xb4\x7e\x6d\x22\xa2\xde\x60\x9d\xe4\xce\x8d\x7c\xc4\xf4\xa1\x52\xc4\x7f\x41\x0d\x7f\xc3\x7d\x38\xcc\xd6\x29\xa4\xb3\x3e\x62\x21\x89\x60\x81\x79\x7d\x07\x53\xdd\x4f\xaa\x8a\x8b\x44\xd6\xc4\x67\x71\x66\xdf\xb4\xd5\x21\x54\x46\x36\x0a\x3c\x28\xd8\xf6\x8e\x38\xab\x54\x60\x8b\x98\x82\x1b\x83\xc1\x87\xb5\x39\x3a\xd8\x74\xa7\x6f\x4f\x5d\x72\x94\x93\xa1\xfd\x74\xcc\x77\x19\xca\xea\x99\x1d\x22\x9c\x5d\x0c\x8c\x4c\x5f\x89\xd8\xe4\x34\x5f\x4f\x52\x21\x43\x13\x41\x0b\x8c\x06\xb3\x31\x5f\x45\xed\x0c\x2f\x91\x38\xab\x96\x6a\xec\x0a\x64\x5b\x6d\xba\x76\x38\x0a\x53\x91\x23\xe0\xf3\x3b\x97\xf3\xd0\x60\x39\x4a\x30\x53\x58\x1f\xfd\xef\x3e\x6d\x36\x53\x11\x66\xb5\x53\xa9\xdd\xe0\x31\x05\xc0\x4a\xf6\x97\xd9\x5e\x95\x21\x7f\xd6\xdc\x96\x8b\xf3\xb4\x48\xd5\xf3\xa8\xe4\xf5\xae\x7e\xdc\x30\xec\x78\xb1\xae\xa4\xf0\xdb\x18\x9a\x94\x9a\x12\x21\x38\xcd\xfb\x5f\x96\x93\xdb\x00\x4b\xae\xd1\xa4\x21\xdc\x44\x12\x2f\x32\x72\x87\xf7\x27\xcf\x98\x9f\xca\xe3\xcf\x3b\xe3\xe3\xdd\x9b\x9f\x53\x50\x2c\xf5\xd9\xfb\x18\x6d\xe7\x91\xd3\x10\xd1\x22\x86\x9c\x9f\xc3\xb6\x95\xde\xc1\x60\x74\x77\xf3\xe1\x49\xe5\x2b\x63\xcf\xdf\xb0\xd9\x83\xe8\x9a\xf2\xf7\x5a\x8f\x48\x98\x43\xec\x05\xc5\xea\x5f\x0e\x72\x1a\xca\xb3\x87\xc6\x80\x25\xf2\x0a\xbe\x0d\x27\xb4\xce\x29\xf4\xa6\x4f\xb7\xf8\xe8\xa3\x32\x87\x3d\x3e\xd1\x21\xfb\x49\x34\x14\xb8\xcb\x0c\x00\xad\x3a\xb6\x16\xc5\xbe\x52\x41\x47\x1a\xde\xe9\xf8\xf4\x69\x74\xea\xe8\x4a\x4a\x8c\xe6\xfa\xbb\x7f\x5d\x9a\x6b\x75\xa7\xe6\x70\x45\x6f\xcd\xcd\x1d\x98\x2e\x8f\x82\x7a\x4b\xbb\x69\xde\xc7\xe3\x05\x3d\xfe\x83\x5b\x70\x30\x1b\x7b\x76\x3f\x00\x04\xbc\x90\x6e\x14\x55\x42\xf4\x87\xb4\xdb\xa2\xed\x56\x1b\xd1\xa2\x03\x06\x23\x6a\xf4\xb3\x6e\x40\x68\xe8\xc0\x07\xb9\x45\x4f\x87\x41\xa5\xf8\xf0\x79\xec\x1d\xb8\x83\x5e\xb6\x54\x42\x90\xd6\xad\xb5\x2a\x70\xd7\x67\x5d\x85\xdf\x4a\x9a\x12\x55\xbf\xd9\x36\xc3\x31\xfe\x51\xc0\x97\x7d\x12\x4b\x5a\x50\x6d\x29\xc6\xee\xc3\x3c\xaa\x25\xd8\xeb\x28\x95\x2d\x6f\xfb\x9d\x6e\x3d\xa8\x90\x38\x2d\x88\x87\x96\xd3\x74\x60\x7f\x66\x43\xb8\x9e\x73\x26\xd9\xed\xc4\x9a\x0f\x53\xbd\xcb\x8c\xc7\x6f\xfd\x39\x3a\x77\x06\x52\x2d\x04\x17\x00\x36\xcc\xb6\x63\x30\xdb\xac\x9d\xa7\xe6\x16\x8c\xaa\x88\xcb\x62\x18\x1e\x55\xa7\xb6\xd5\x21\xa2\x11\x5e\x23\xe2\x02\xee\x24\x80\xb5\x87\xbe\x45\x01\x44\x79\x79\xa8\xd7\x36\xf9\x01\x2e\xcf\x00\xe6\x7b\x31\xe8\x10\x4f\x6e\x7d\xf0\x8a\x96\x83\xcd\xc8\x9c\x03\xa4\xe3\x7e\xe2\x29\x28\xd4\x5f\xa1\x90\x94\xe0\xd6\xe7\xb4\x0b"}, -{{0x05,0x88,0xac,0xd4,0xe0,0x9b,0xa9,0x02,0x74,0xc8,0xf3,0xd1,0x57,0x5b,0x2b,0xf3,0x64,0xa7,0x76,0x88,0x4a,0x9a,0xeb,0x41,0x03,0x41,0x5e,0x16,0x3b,0xa0,0xbf,0x81,},{0x3e,0xca,0xe6,0x97,0xb4,0x25,0xd8,0x7e,0x34,0xa1,0xd9,0x44,0x09,0x8e,0x3d,0x32,0xe2,0xc1,0xec,0x56,0xc3,0x62,0x7d,0xf8,0x0b,0xa2,0xb8,0xa4,0x3d,0xdc,0x19,0x03,},{0xa1,0x11,0xb9,0x70,0x6d,0x24,0x2c,0xd3,0x6d,0x6e,0x87,0x41,0xcb,0xb0,0x97,0xb9,0xe2,0xff,0xfa,0x40,0xf4,0x3f,0xd6,0xf2,0xd3,0xd9,0x16,0x93,0x66,0x73,0x32,0xb5,0xf2,0xdb,0x5e,0xe3,0xea,0x20,0xb8,0x32,0x91,0xb8,0x40,0x57,0x95,0xb7,0x4d,0x63,0x3d,0x46,0xf4,0x75,0xab,0x7c,0x47,0x61,0x71,0x18,0x53,0x5b,0x80,0x51,0xd9,0x07,},"\xf8\x28\xf8\xc9\xda\xd2\x98\xc5\xb7\x19\xda\xa8\x52\xb1\x7e\x76\x25\x98\xa7\x0f\x4e\xcd\x16\xa2\xfc\x59\x6e\xb0\x26\x38\x99\xe9\x83\xd4\x4e\xdc\xc7\xbd\x24\x0c\xb0\x76\x10\x60\x0a\xe9\x6a\xac\x0d\xfc\x3b\xe3\x87\xb6\x16\x85\x08\x99\xb5\xcf\x44\xe1\x76\x7f\xfa\xca\x3d\xf3\x81\x58\x59\x84\x24\xf8\x07\x14\x14\xc7\x04\xe6\x0b\x42\x2a\xd7\x73\x77\xfa\x7f\x6a\x8c\x5d\x0e\xbc\x02\x35\xe2\xd4\x3a\x98\x4f\x3a\xdf\x75\x9e\xb1\x04\x47\xf3\xc2\xf6\xb8\x0d\x5a\x11\xef\x41\xd3\xa0\x98\x52\xc0\x93\x2a\x1b\x9a\xc2\x3e\x6f\x40\xa1\x67\xde\x21\x04\x1b\xec\x88\x85\xf9\x43\x3e\xb8\x0b\x95\xc9\x78\x59\x58\x04\x6c\xdb\x7b\xf1\x47\xa7\x99\x47\x82\x3b\x41\x49\xae\x05\x21\xd7\xe5\xaa\xbc\x15\x64\xfa\x40\x44\x10\x6e\x2e\x39\x2e\x9c\x34\x44\x57\xe9\x92\x93\x76\xea\x9b\x42\x29\xc6\xe7\x73\x8f\xe7\x90\x08\xd5\x54\xc4\x29\x39\x69\x14\xc3\x63\x87\xf5\x79\xb4\x6b\xab\x14\x6f\x6a\x95\x10\xeb\x6f\x8c\x85\x55\x1c\xbd\x84\xc7\xdc\x0d\x0b\x1c\x01\x0c\xcb\xa5\x96\x3a\x7f\x39\xf1\x81\xe4\x4d\xbc\x98\xe4\x95\xaa\x63\xc0\x10\x59\xcb\xe6\xa9\x9b\x07\xb4\x49\xe7\x75\x9c\x9a\xf9\xe0\xf8\xd9\x05\x4a\x67\xa3\x48\xfa\x19\xd7\xf9\x1e\xc0\xa4\xd4\xf2\xc7\x02\x6c\x3b\x84\x92\x59\xa3\x50\x41\x7f\xd8\x6c\xab\x21\x42\xe4\xcf\xe3\xc0\xaf\xbf\x25\x18\x2a\x2d\x52\xbd\x2e\x0b\xc9\x20\xe8\x50\x80\x83\x2b\x91\xb9\x27\xb6\x29\x48\xa6\x7c\x31\x7e\xb0\x90\x91\x46\x1d\x49\x3e\xea\x5f\xfc\x47\xbf\x08\x55\x82\x96\x82\x58\xa3\xc8\xdd\x81\xa8\x58\x27\x0b\xdd\xaf\xe7\x92\x56\x84\xa1\x5f\xfb\x51\xbc\xfa\xab\x93\x1a\xfa\x46\x5e\x30\x90\xe8\x6b\xe4\x1e\x35\x47\xcb\xa2\x34\xb8\x5f\xe7\xdb\x70\x04\x96\xa5\x05\x00\x2d\xf3\xca\x4e\xae\xc7\xb9\x62\x78\xc7\xd1\xa7\x7d\xb8\x34\xa9\x17\x97\xbb\xb8\x26\xd0\x92\xaa\x28\xb4\x95\x45\xed\x3b\x1e\xda\x23\xbe\x11\xa3\xf5\x28\xb9\x55\xcb\x0c\x4f\xa6\x6e\x16\xe9\x57\xe5\x70\x4c\xf3\x19\xe5\xf7\x9c\xc0\x9f\x2d\x05\x4e\x6d\xaf\x19\xe2\x92\x6b\x11\xe1\xe4\x13\xff\x82\x2c\xa1\x41\xf7\xc3\xd3\x85\xae\x95\xdd\x20\xb3\x46\xe5\x83\xcf\xb0\xc2\x29\xec\x39\xcf\x88\x9a\x54\x19\xcd\x37\xbc\x18\x4e\xf5\xfb\x14\x46\x22\x08\x0a\x30\x2d\x9d\x77\x45\xc4\x51\xf7\xd8\x82\x42\xcc\x26\xb9\x16\xa3\x56\x9a\xbc\x7d\x1f\x21\x6d\x57\x79\x7a\x47\x2b\xc6\x21\x76\x17\x58\xe8\x40\xeb\x8e\x29\xbc\x8e\xfc\xb7\xaa\xfc\x7c\xf8\xf4\xe5\x93\x30\xd3\x5e\xe1\x07\x49\x6d\xec\x6e\x71\x4b\x1f\xa4\x30\x98\x37\xbb\x47\xeb\x3a\x06\xb4\x60\x4d\xd2\x07\x33\xcc\x0e\xaa\xc2\x64\x9e\x18\xc0\x73\x42\xef\x55\xd1\x9b\x8d\x03\x95\x91\xac\x28\x69\xac\xc3\x4b\x6c\x3c\x1c\xa3\xcf\x26\x3f\xf8\x4c\xa4\x3a\x5f\x64\x65\xba\x34\x88\x8c\x10\x90\x13\xb3\x2b\xfc\x0d\x0d\x15\xf5\xa7\x6c\xec\x27\x0a\xb3\xac\x9a\x10\x63\x31\x31\x2f\x5a\x0a\x84\x28\x2c\x3a\x3d\x4a\xea\x1e\x7c\xf5\x3d\xbf\x8b\x24\x0b\xdd\x11\x1c\x34\xd2\xa9\x3d\xfd\x12\x58\xfe\x92\x67\x13\x3f\x75\x54\xdc\xc2\x1a\x8f\x43\x9c\x16\x5d"}, -{{0x7d,0x14,0x02,0x3e,0xb4,0x8b,0xbd,0x43,0x76,0x49,0xa2,0x41,0x87,0x79,0x05,0xa3,0xc9,0x32,0xf1,0x46,0x40,0xf2,0x9a,0x0f,0xb1,0x34,0x11,0x4e,0x8f,0x33,0xf5,0x82,},{0xea,0x5c,0x11,0xb4,0xb2,0xc5,0xef,0x4a,0xb7,0x06,0xcc,0xa3,0x47,0x50,0x43,0xc9,0x58,0x18,0xeb,0x56,0x5a,0x79,0x7e,0x33,0x68,0x8a,0xfe,0xac,0xd6,0x8a,0xdc,0xca,},{0x31,0x33,0x9d,0xce,0x23,0x33,0x6d,0xf5,0xb2,0xb1,0x93,0x52,0x2a,0xa3,0xdd,0x2d,0x41,0x14,0xa6,0x6a,0xf1,0x65,0x62,0x89,0xc9,0x52,0xbc,0x11,0xc9,0xb2,0x10,0xf7,0x7a,0x54,0xd4,0x61,0x61,0xf4,0xe0,0xc5,0x2b,0x30,0x13,0xe4,0x0b,0x9e,0x9e,0x84,0x27,0xd8,0x51,0x32,0x5b,0xd7,0x1c,0x4d,0x99,0x35,0x3e,0xee,0xd7,0x51,0x08,0x0d,},"\x90\x01\xdb\x31\xf2\x79\xbe\x50\x53\x19\xb8\xe7\x2b\xde\x11\x99\x51\x29\x80\xdf\x65\xf0\xd8\xa9\xb4\x93\x04\x67\x41\x3a\x99\x7b\x97\xa3\x62\xb5\x72\xa4\xb4\x4b\xc9\x40\x48\x7f\x18\xb2\x08\xce\x6a\xc5\xc6\x87\x16\xd3\xaf\x1b\xce\xf1\x70\x38\x3b\x5c\x4b\x5c\x47\xe4\x47\x37\x72\x6f\x93\x83\xbc\x4f\x14\x47\x68\xbf\x5c\xaf\xb4\xe9\xdf\xe3\x97\x61\xe6\xed\x47\x89\x71\xd1\xc7\x0e\x6d\xab\x2f\xd0\x49\x9d\xff\x92\x93\xb2\x39\xd1\x6c\x96\x02\x61\xc6\x82\x18\xb9\xf5\xb1\xbe\xe6\x90\xf0\xd2\x40\xc1\xb3\xdb\x71\x1f\x9e\x82\x1f\x08\x09\xbb\xeb\x9a\xaf\x24\x9c\xcb\x16\x8c\x67\xd9\x65\x56\x2d\x24\xf8\x48\x51\x61\x40\xbf\xd9\xfc\x05\x0d\x4f\x20\xda\x5a\x17\x94\x46\x8a\x9c\x07\x25\xea\x5c\x66\x9d\x5c\x63\x0d\x93\x10\xe5\x74\x51\x07\xda\xd3\x72\x61\xb5\xd9\x1e\x38\xe0\x85\x12\xe6\xf3\x73\xec\x5d\xca\xd5\xca\x09\x07\x29\x07\xc8\xfb\x7b\xf3\xb9\x26\xc3\x33\x94\x90\xb3\xf5\x1f\x76\x44\xe7\x3a\xe2\xec\x01\xd6\x1b\xe7\xc6\x52\x65\x36\xb4\xff\xd1\xab\x68\x49\xfe\x0c\x2f\x40\xd3\xbd\xa2\xa4\x9e\x55\x50\xb8\xdf\x97\x90\x81\xda\x85\x16\x8d\x0f\x71\x58\x2b\x90\x36\x77\x52\x6d\x1f\x1b\x15\x11\xe1\x38\xb6\x84\xfc\x46\xaa\xc8\xbd\x80\xc3\xde\xf7\xee\x81\x38\x19\x04\x61\x80\x7c\x55\x36\x12\x5c\xb0\xe2\xc3\xd0\x83\xa1\x87\xc7\x26\x9c\xb5\x31\xec\x36\x78\x78\x7b\x32\x55\x5c\xf0\x4a\xb0\x93\xc9\x00\x2e\x7d\x79\x2b\x4d\x93\x3f\x2e\x30\x70\xf3\x9a\xc8\xcc\xf8\xd5\xf5\x45\x5f\x12\x10\x9d\x8a\x8a\xeb\x4e\x21\x2f\xad\x4a\x70\xb1\x47\xc0\x4a\x7b\x91\x84\x60\xb1\x31\x63\x76\xe6\x40\x20\x85\x95\x17\xeb\x7e\xe3\x0c\x29\x0b\xe8\xb8\xd6\xf9\x67\x39\x15\x25\x6c\x3b\x04\xb9\xd9\x05\x4b\x52\x33\x8e\x0d\x36\x07\x85\xe4\x6a\x18\x28\x44\xc5\xc3\x76\x6a\xea\x8e\xd3\x11\xb2\xd4\x81\xc0\xb7\xb2\x11\x4e\x41\x8e\xd1\x7f\x8d\xeb\xf0\x1a\x83\xff\x37\x51\x70\x24\xee\x9e\x28\xe0\xc9\x0d\xce\x6d\x05\x9f\xfe\xe4\x13\xd2\x7c\xd6\x27\x83\xa8\xb8\xb5\x01\x6a\xd2\x76\xe3\x9d\xfd\x8f\x8f\x3d\xdf\xc4\x28\x10\x18\x18\xce\x50\x7f\x00\x3e\xb5\x8c\x9a\x5c\xc8\xb1\xaf\xf0\x5a\xab\x8f\x0d\x7f\x1d\x1f\x6d\x4b\x87\x1d\xbc\xed\x1f\x3d\x28\x66\x23\x97\x52\xfb\x13\xf6\xe1\x80\x34\xbb\x2b\x5a\x66\x35\xca\xa6\xec\xc4\x62\xe0\x58\xeb\xe2\xfa\x65\x1d\x3d\x0f\x36\xe2\x0a\x31\xf7\x65\xe4\xb9\x58\x27\x0b\xd8\x25\xc6\x81\x8a\xac\x1a\xd7\x56\x31\x35\xae\xed\xf1\x4a\x2b\x6d\x39\x8b\x6e\x34\x00\x84\x01\xb2\x18\x46\x18\x20\x07\x1c\x5a\xf7\x78\x46\xcb\x9c\x32\x81\x90\xc0\x61\xd5\xaa\x6e\x0e\xcd\xe7\xef\x58\x56\xb0\xe6\x81\x4f\x83\x3f\x70\x40\x96\xdf\x08\x25\xfa\x4b\x46\xdc\xda\xcf\xa2\x7c\xd8\x7b\xd7\xbf\xef\xf7\xf8\xca\xe1\x66\xa3\xa0\x4d\x43\x7c\x7b\xe7\x16\xc4\x90\x45\xc7\xbd\x3d\x13\x49\x62\x7c\x9c\xbd\x04\xc1\x5f\x00\xa6\x96\xe3\xcf\xfb\xb4\x5a\xf2\x91\x22\x62\x7e\x7e\xd3\x3b\x42\x49\x91\x3b\xec\x00\xf0\xe2\x8a\xa1\x12\x98\xcc\xe8\xb6\x49\x08\x1f\xe3\xb1\x69\xb4\xaa\xea\xca\x48\x5b\xda"}, -{{0xe8,0x30,0x6b,0xad,0xa6,0xd5,0x5e,0xb1,0x88,0xd9,0xf7,0x5c,0x81,0x5c,0xc9,0x14,0xe9,0x3c,0x9c,0x72,0x22,0x39,0x1c,0x15,0xbb,0xae,0xaf,0x93,0x54,0x43,0x79,0x35,},{0xbf,0x27,0x98,0xb8,0xe5,0x54,0xf5,0x1e,0x22,0x86,0xc3,0x03,0x4a,0x88,0xe5,0x77,0xff,0x23,0xfa,0x32,0xa6,0x72,0x44,0xea,0x82,0x45,0x91,0x2e,0x8b,0xf4,0x6d,0xa4,},{0xcc,0x66,0x27,0x30,0x8e,0x2f,0x42,0x43,0x83,0xfa,0x70,0x59,0x4f,0x57,0x57,0x91,0x60,0x05,0x40,0x02,0x7a,0x27,0x51,0x61,0x9b,0x28,0x3a,0xff,0xea,0xeb,0xc9,0xc9,0xd2,0x9a,0xc6,0xdb,0x28,0x6d,0xd2,0xc1,0xb5,0x96,0x58,0x7b,0x87,0x8d,0x1d,0xf4,0x78,0x1d,0x43,0x6b,0xb5,0x70,0xc1,0xc0,0xf0,0xd3,0x33,0x68,0xdc,0x66,0x52,0x0b,},"\xd7\x04\x38\x09\xc3\xe3\xdc\x00\xb1\x7e\xfd\x52\xc9\x13\x0b\x11\xb7\x86\xf1\xe2\x57\xb5\xe2\x2f\x81\xa7\xfa\xae\x60\x0b\xbc\xdf\xd5\x18\x53\x7f\xe8\x52\xc6\x42\x35\x97\x62\xfb\x75\xe8\xad\x85\x92\x49\xe6\xab\x49\xce\x1b\xb0\x4f\x24\x92\xf2\xaa\xc3\x54\x46\xba\x6e\xb0\x3e\x76\xde\x3a\xbd\x2d\x5f\xc7\xe6\x14\x68\x43\xad\xd0\x42\x86\x0a\x4a\x16\xb5\x9b\xdd\x7d\x03\x83\x78\xa3\x5e\x1a\x04\xb1\x21\x7a\x55\x71\x0d\x93\x7e\x2c\x90\x32\x23\x2e\xa2\xcd\xd1\xd2\x5a\x0b\xff\x71\xef\x5d\x3e\x0c\x05\x6b\x29\xcb\x92\xf6\xdf\x69\x2b\xde\x14\xdf\xa5\x0e\x13\x2b\xeb\xd8\x9e\x9f\x18\x33\x88\x0b\x65\x7a\x78\x1e\x94\xec\xb6\x03\x04\x17\x56\xe5\x51\x7d\x44\x23\xc5\x6f\xad\xc1\x3e\x2b\x31\x80\x88\xfe\xdd\xf3\xb5\xc8\x3c\x20\xb4\x6f\xdd\xbb\xa9\x23\x05\xe4\x86\x06\xda\xb7\x48\xce\x38\x48\xb8\x43\xf4\x71\x1f\x37\x0c\x3e\xc7\xd5\xe1\x9a\xb4\xc0\xac\x1a\xe1\x5a\xaa\xf2\x3d\x65\xfe\xce\xda\xbc\x08\x04\x9b\x9e\x29\x11\x3e\x57\x61\xed\x9d\x1c\x62\xeb\x07\x5c\xab\xb2\x67\x4c\xdb\xe1\xe3\xa8\x89\xba\xe4\xb1\xdd\x31\xb6\xa5\xb2\xea\x1b\x8d\xed\xcc\x3c\x51\x5e\xdc\x44\x67\xc3\x02\x31\x17\x6c\xd4\x4b\xec\x8a\x05\x79\x51\xab\x5c\xd3\x9a\x96\x23\xf8\xaf\x84\x73\xcd\x27\xd9\x33\x02\xbf\x8a\xa6\x24\xc9\xc3\xc5\x79\x9d\xa1\xdc\x49\x44\x94\xef\x8f\xf1\xdb\xe0\x18\x7e\xa5\x16\x26\x70\xb8\xd0\x98\xc3\xa9\x49\x19\x39\x8d\xad\xf7\x9e\x6c\x24\x91\xc4\x44\x39\x2c\x29\xcd\x50\xd5\x74\x35\x06\x32\x90\x84\x2b\xfa\x0e\x85\x30\xfa\xeb\xc0\x06\xd6\xea\x78\x01\x11\x7e\x0a\x3f\x01\x9e\xe2\x8f\xb3\x79\x22\x35\x40\x2e\x2f\x69\xb8\x7a\x43\xdc\x22\x7f\x9d\xe3\x16\x02\x97\x56\xc3\x16\x7d\x64\xa3\xa3\xf6\xd7\x31\x60\x33\x1d\x5a\x18\xee\xe5\xb0\xe6\xe2\x2a\x66\x3e\xfd\xcc\x8d\x67\xaf\x3b\xce\xd0\x41\xea\x84\x3a\x56\x41\x60\x3e\xc7\x2e\xfd\x64\x4e\x17\x3d\x19\x9a\x8c\x83\x0b\x2e\xa5\xfe\xc0\x37\x80\x27\xc3\x72\x25\xaf\xcb\x60\x4c\x4c\xdc\xf4\x09\xbe\x1c\x50\x9c\x9a\x37\x7b\xe0\xd0\x52\x41\x07\xc6\xd9\x2b\x5f\x09\xa2\x9e\xfb\x71\x09\x29\x56\x70\xbb\x1a\x1d\xd3\xea\x00\x8b\xb7\x91\x85\xf0\x9b\x98\xf0\x20\xc4\x3f\x14\x39\x68\x5b\x96\xf6\x19\x93\x11\xa0\x90\x87\x0f\x0d\x9b\x10\xd4\x95\xcd\x41\x0a\xa9\x5b\x7e\x53\x74\x9b\xe3\xa6\xc0\xfb\xc7\x29\xf9\x6c\xf8\x56\x43\x97\xb0\x9c\x13\x51\x40\x16\x82\x5f\x72\xf1\x4e\xb9\x32\x94\xd7\x01\x0a\xcc\xfd\x11\xf1\x7a\x6a\xc8\xf5\x44\x26\x3d\x60\x38\xd5\xc7\xdb\x29\x48\x62\x91\xb3\x0e\xa4\x9b\x6b\x54\xcf\x88\x82\x6d\xd2\x52\xcd\x9d\xbb\x57\xd8\x41\xb5\xa4\xcf\x70\x2a\x32\x64\xfa\xa4\xdc\xcc\x86\xab\x14\xda\xf1\x24\xef\x3d\x53\x35\xa6\x87\x8d\x06\x5c\x6b\xa2\x99\x91\x04\x57\x65\xee\x55\x42\xcc\x9f\x5d\x9f\x35\x4d\xcd\x2c\x6e\x0c\xf7\xff\x3a\x30\xf6\x49\xb5\x91\x2d\x97\x1d\x63\x35\x78\xf1\xe9\xf2\x63\x87\x4d\x05\x65\xc2\x47\x30\x1d\xcb\xd1\x5d\x76\x21\x1a\xe2\xd3\xd5\x06\xfc\x64\xde\xb7\xe0\x42\x56\x5d\x43\x8e\x2b\xfb\x24\x92\x43\xb7"}, -{{0x36,0x3c,0x1e,0xa7,0xc3,0x2e,0xa3,0x28,0xa0,0x55,0xaf,0x7b,0xd8,0xb3,0xbf,0xd2,0x04,0xfb,0x0b,0xbd,0x4b,0xf4,0x2f,0xfe,0x26,0x2f,0x3a,0x5e,0xbd,0x54,0xda,0x55,},{0x7a,0x83,0xec,0xca,0x51,0xef,0x6e,0x5a,0xa0,0x43,0xa5,0xce,0x04,0xd9,0x28,0x8a,0xdd,0x49,0xa2,0x77,0x54,0x8b,0xd3,0x01,0x6b,0x69,0x3f,0xfa,0x79,0xa2,0x2e,0xdc,},{0x5f,0xd1,0xe5,0xf9,0x92,0x2a,0x12,0xf6,0x36,0xb7,0x2a,0x7d,0x62,0x17,0x09,0x1f,0x94,0x8a,0x55,0xbc,0xb1,0x82,0x6b,0x8f,0xca,0xf9,0x9d,0x26,0x41,0x6c,0x7a,0xb1,0x35,0x1c,0x10,0xf4,0x09,0x3f,0xfd,0x8a,0x2a,0xf8,0x69,0x14,0xa0,0xa9,0x81,0x84,0xec,0x7e,0x06,0xd2,0xde,0xe8,0x7f,0xdc,0x0f,0x4a,0x47,0xf8,0xc6,0x3c,0xf5,0x01,},"\xc4\x1c\x1e\x1f\xb7\x59\x54\xa0\xae\x0e\xbc\x29\x09\x0b\x9f\xc5\x33\xe6\x93\xe7\xc7\x10\x5c\xfe\x40\xef\x52\x6e\x4e\x12\xa7\x40\x52\x21\xf2\x18\xc7\xac\x01\x9e\x1d\x4c\x92\xda\x28\x53\xf2\xd7\x26\xaa\x62\x27\x79\x24\xdf\x0c\x34\x3f\xc3\xd4\x7c\xd5\xa9\x9a\x3e\x27\x9b\x26\xa1\xb1\x3b\x1f\x2a\xa3\x6f\x7c\xcb\x4b\x54\xfb\xef\x18\xbd\x87\xa5\x5f\x1b\xc4\x0c\xe7\xb2\x02\x91\x45\xee\x7a\xab\x39\x17\x95\xac\x68\xde\x61\x99\xf5\x05\x94\xfc\x79\x61\x1b\x85\x13\x1c\x14\x30\x21\xf2\x6f\xa3\x58\xda\x0c\x7c\x6a\x65\xdd\xe0\x76\xda\xb4\x88\x67\x5b\x72\x23\x09\xe5\xed\x97\x46\xd1\x8a\x89\x30\x99\x06\xa7\xa9\xdf\x23\x7d\xd2\x7b\xd5\x90\xcc\xc7\x7c\x40\x2e\xf6\xe1\x9c\xa6\x3c\xc8\x6b\x85\x16\x03\x30\xee\x6e\x1f\x1f\x47\xa2\xff\x80\x7e\xef\xad\xc0\x09\x63\x52\x0a\x1c\x60\x0a\x3e\x45\xaa\x7f\xb2\x55\x4f\x47\xd8\x97\xbd\x86\xd8\x1c\x3b\x08\x77\x10\x12\x22\xfa\x78\x50\xb8\x0c\xe3\xbc\x06\xc9\xe5\x8c\x0c\x96\xe3\x2f\xec\x85\x30\xc9\xfa\x1e\x41\x63\xf0\xef\x84\x56\x95\x2b\xf6\xdd\x58\x04\x5a\x36\x3d\x61\x88\x0e\x9a\xc9\x76\xa3\x60\x3e\xf7\x7a\x4c\x39\x5e\x6a\x07\xe3\x42\xf6\x02\x3b\x8a\xf1\x02\x25\xcf\xf2\x40\xef\xc0\x36\x6a\x79\x9f\xd8\x6e\x9d\x06\x20\x60\xd8\x72\x40\x33\xbd\xf6\x75\x88\xcd\x73\xac\x28\x4d\xe4\xc6\x94\x3c\xf4\x5e\xe4\xf7\x5f\x59\x37\xd9\x7d\x78\x10\x5f\x0b\xbe\xce\x04\xd3\xdc\xb5\xe4\x24\xef\xf8\x9b\x77\x3e\x5d\x6b\x4f\x37\xef\xa9\xa0\x65\x4c\xb3\xef\x34\x52\x78\xa6\x2d\x87\x6c\xfe\xf9\xa3\xdc\xdc\xeb\x70\x81\x44\x18\x77\xeb\xd5\xfa\x30\xc9\xd9\x54\xe3\x68\x4f\xa4\x76\xa4\xf4\x85\xd4\x26\xfd\x3c\x8c\x32\xbe\xa0\xf9\xcc\x20\xb1\x5e\x8f\xdf\xc3\xca\x4b\x30\x2c\x07\x4f\x50\x81\x32\xd1\x5d\xe6\x25\xc1\x0a\xe0\x73\x78\x11\x46\x3d\xcc\x55\xfc\xc4\x01\x4b\x20\x20\x8f\xff\xce\xfa\x9d\xd4\x52\x11\x9b\x16\x52\xde\x41\x34\x8f\x69\xf2\xc4\x88\xf5\xcc\x18\x56\xd6\xe7\x8a\x5c\xbe\x3e\x37\x3d\xd4\x59\x8e\x2d\x39\xf8\x76\xeb\x94\xe0\xb0\x1b\x21\xfa\x91\x29\xef\x41\xb6\x39\xf4\xe0\x5e\x69\xde\xb1\x83\x5e\xd4\x4b\x91\x12\xa6\x86\x2a\x5b\xce\xa0\x72\xc6\xe1\xb8\xf0\xf0\x58\xf4\x6b\xac\x2a\x84\x5a\x58\x2d\x14\x8f\x17\x76\x0b\x9e\x0a\x2b\xa6\x0b\xbb\xf3\x88\x4a\xf9\x4d\xd4\xc7\xec\x9d\xb0\x8e\x9a\x5b\xcc\x6d\xde\x13\x46\x44\x2e\xe1\xf4\x70\x7d\x1f\x79\xb6\x9b\xa8\x67\xf4\x18\xdc\x27\x91\x73\xf7\x7a\xdb\xc5\x8a\xb8\x5e\xa3\x93\xb9\xdc\x68\x26\x19\x00\xc1\xca\xa8\x2d\x2f\x50\x47\x4c\x42\xae\xc9\x11\x31\x42\x78\xc0\xaf\xfa\x2a\x6b\x6c\x36\xd1\xff\x88\xf3\xb4\x9f\xb2\xb7\xc3\x39\xd2\xa7\xc2\xb3\x04\x9f\x8c\x0a\x08\xd1\x6a\x9e\x8d\xf9\x3d\x13\x0d\xa4\x84\xbd\xba\x6d\xbe\xc5\x34\xcd\x51\x09\x7a\x04\x82\x21\x10\x6b\xab\x48\xd6\x7f\x95\x1b\x75\x05\xa1\x48\x48\x92\xb8\x57\x79\xc5\xa3\x11\x17\x02\x12\x4d\x95\x7a\xcf\x2d\xc3\x52\xef\x9b\xa2\x47\xbc\x80\xe2\xce\x96\x26\x9c\xe8\x5e\x78\xb9\xeb\xda\x98\x90\x76\xdd\x5f\xf7\x3e\x1e\xb2\x75\xe5\xd7"}, -{{0xdb,0x22,0x28,0xff,0xff,0xa9,0xd2,0x53,0x4a,0xef,0x91,0x8f,0xb8,0x5b,0x82,0x1a,0xd3,0x60,0xe2,0xd3,0x9d,0xec,0x5a,0xeb,0x2d,0xb0,0xdf,0x02,0x49,0x7f,0x94,0x16,},{0x6d,0x01,0x95,0x77,0x7f,0x81,0x05,0xff,0x52,0x3b,0x79,0xc5,0x9e,0x3c,0x30,0x81,0xfe,0x89,0xdb,0x6f,0x87,0x03,0x3f,0x09,0x4f,0xa5,0xa9,0x40,0xce,0xf8,0x4b,0xb4,},{0x82,0x18,0x9d,0x34,0x0b,0xc1,0x1c,0xea,0xa4,0x00,0x41,0x0e,0x08,0xba,0xe9,0xd9,0x01,0xaf,0x05,0x91,0x25,0xe9,0x53,0x78,0x6f,0x8a,0x04,0x3d,0xdf,0x11,0xf7,0xb2,0xf8,0xe3,0xb6,0x17,0xac,0xcd,0x78,0xe2,0x93,0x9a,0xdf,0xab,0xf2,0xd2,0x47,0x1f,0xaf,0xd6,0xf5,0xbc,0x45,0xb1,0x40,0x75,0xb3,0x28,0xe3,0x4d,0x80,0x75,0xb2,0x07,},"\xfc\x07\xcd\x99\x04\x0f\x13\xe5\xa8\x4f\x94\x74\x6d\x6b\xb8\x68\xf7\x52\xb4\x48\xb6\x2d\x99\x59\x3e\xf2\x9e\x43\xcc\x82\x45\xf0\x47\x0f\x65\x55\x2d\x64\x32\x20\xf6\x71\x92\x85\xe1\x5c\x37\xa6\xd1\x74\xae\xf7\x60\x88\xcc\xda\x5f\x88\x68\x5b\x52\xda\xe2\x84\xc6\x5b\x38\x0d\xa3\x45\xa2\xe1\xaf\x2e\xd7\x64\x80\xd2\x69\xcb\x93\x4b\x43\x17\x62\x0b\x79\x2e\xbb\x39\xb2\xa6\x78\x24\x7d\x6d\x81\x5f\x2a\x5c\xb9\xaa\x56\x0e\x4b\xf6\xde\xba\x4c\x0a\x0d\xdc\x82\xd0\xe5\xa5\xa6\x5a\xcb\xc4\x78\xe1\xec\x6b\x06\x4d\x7b\xb7\x38\x8a\x73\xf6\xed\xa3\x0b\x0b\x6b\x73\xdd\x8f\x87\x92\x63\xad\x1a\x03\x48\x67\x1d\xcf\x21\x1c\xb9\x6e\xd0\x8e\xd5\x2f\x33\x17\xda\x68\x18\x5d\x6b\xb2\x58\x9d\xc1\x1d\x75\x5d\x47\xa3\xb6\xf6\xa0\x38\x6a\x85\x94\xd9\x57\x0b\x2e\x9b\x0d\x4b\x5e\x13\xdc\xcd\x9b\xb7\xac\xbe\xf0\xab\x27\x6a\x7a\xeb\xe1\x29\x31\xbe\x67\xf1\x0d\xe2\x67\xa0\x29\x89\x53\x01\xf5\x66\x25\x30\xad\x8a\xb3\xd2\x30\xb3\xb6\xd7\x09\x3a\xcd\xfb\xf2\x74\x75\x7a\x90\x78\xe2\x0c\x23\xbc\x82\x2d\xef\xfa\x61\x00\x54\x86\x10\x2c\x01\xab\x82\xbd\xc8\xcd\xcf\x1b\xb3\x7f\x9b\x56\xd3\x9e\x50\xfd\x5a\x68\x95\x41\x6e\x76\x7f\x4e\x36\xc1\xa4\x17\x78\x90\x81\x25\xb5\xca\x3f\x92\xa9\x0d\xa9\xad\xdf\xf1\x55\xfb\x1f\xd7\x76\x88\x08\xa8\x0f\x20\x3e\xd7\x37\xef\x00\x77\x63\xbd\x2f\xea\x9f\xf2\x8c\x84\xb4\x35\x51\xc9\xfc\x43\x8f\xfc\x47\xfc\xfc\xf6\x4d\xc7\x70\x06\x13\xaa\x8b\x3a\xf8\x63\x3a\xe8\xb6\x98\x74\x37\xc0\xaa\x47\x81\xbe\x1e\x82\x13\x96\xc5\x36\xcb\x30\x05\xd0\x55\x49\xb1\xcb\xa7\x01\x35\xaf\xb7\xfe\x30\x68\x96\x1c\xad\x3a\x14\x63\xcc\x0b\x55\x60\x68\x4e\x27\xbb\xa7\x7a\xef\x41\x9d\x82\x38\x68\xe0\xce\xba\xd1\xf1\xce\x0a\xe9\x02\x74\x4a\x15\x2d\xd2\x94\x51\xa1\x7e\x28\xa8\x9a\x71\x58\xa1\x83\x6e\xfc\xe4\xa3\xe5\xc7\xd1\xfa\xa4\xc3\x87\x5b\xc4\x6c\x4d\x9b\xe2\x2d\x66\xd3\x66\xac\x6f\x59\x53\x8a\x00\xb2\x75\xb0\x2f\xac\x6d\xa7\x55\xa8\x54\x08\x19\x97\xd5\xd1\xd0\xe6\xe5\x68\xa5\x95\x8c\xf3\x34\xc5\x18\xcd\x51\x7a\xb9\xd7\x3c\x48\xd6\xcb\xc4\xae\x4e\xea\x43\x53\x11\x3e\x7e\x4a\x7c\x05\x92\x0e\x68\x6b\xf0\x7a\xfb\xfb\x8d\xd2\xec\x4f\x18\xfa\x71\x38\xe5\x7d\x33\x2c\xd7\xa4\x22\x8f\xea\x73\xbc\x09\x25\x2f\x24\x42\x72\x94\xeb\xd3\x64\x5e\xe0\x99\x6c\x2e\x85\x1a\x8a\xa5\x1a\x7c\xd9\xfc\x2e\xab\x47\xc0\xab\x21\x3f\x4f\x51\xd2\x16\x09\x1e\xd0\x89\xe4\x59\x2e\x9b\xb0\x82\x8b\x85\x8f\x84\xf6\x0b\x93\xad\x84\xa0\xa2\x28\x27\xcb\xd2\x74\x14\xb7\x81\x32\x2a\x04\xd3\x96\x08\x28\xf6\x38\xdf\x28\x34\xc7\xf7\x83\x9d\x70\xdb\x12\x6b\xee\x5a\xf2\xee\x75\x59\xa8\xac\x4c\x01\xa6\xc3\x91\x39\x6a\xf9\x3f\xa0\x60\x89\x40\x29\x7d\xdf\x89\x00\xc5\xdd\xb4\x66\x34\x0a\xe5\x1c\x60\xc7\xea\xd7\x62\x44\x7e\x76\xd8\xbc\xcb\x57\x39\x97\xcf\x66\x14\xd1\x88\xa0\xb9\xa2\xf5\x6e\xed\x9b\x0f\x9d\x46\x3a\x19\x78\x7f\x40\x92\x58\x1a\x65\xc6\xbf\x78\x1b\x93\xc5\x60\x87\xe5\x4e\xe1\x34\x3a\xab"}, -{{0x66,0xb5,0x0f,0x69,0x2e,0x39,0x5e,0xb8,0x33,0x86,0xe0,0x27,0xc8,0x2c,0xe3,0xfd,0xee,0x3b,0xd8,0x99,0xb0,0xd3,0x17,0x9d,0xb0,0x86,0xfb,0xf5,0x24,0xf5,0x74,0x59,},{0x44,0x85,0x36,0xe9,0x82,0x40,0x84,0x37,0xce,0x89,0x67,0x40,0x53,0xe3,0xc5,0x89,0xc9,0x8c,0x09,0x5c,0x60,0x02,0x1a,0x11,0x81,0x78,0xc6,0x26,0x1d,0x88,0x10,0xfe,},{0xbd,0x13,0xf6,0x36,0x2c,0x07,0x07,0x89,0x22,0xf3,0x0c,0x63,0x30,0x75,0x1b,0xf6,0xe7,0xcf,0x42,0xa7,0x69,0x16,0xee,0x65,0x3e,0xb1,0x7a,0xcc,0xff,0x1f,0xbb,0xca,0x35,0x25,0x8c,0x4c,0xbc,0x58,0x2a,0x5e,0x8c,0xc9,0x4f,0xd2,0xc7,0xed,0xeb,0x53,0x76,0x2f,0x1f,0xc2,0x31,0x23,0xd7,0xf4,0xf1,0x45,0x40,0x9b,0x31,0xcd,0x38,0x02,},"\x74\x28\xa9\x64\x21\x2b\xcb\xe8\xdf\x7d\x59\xe4\x8e\x92\x34\x80\xaa\x0e\xe0\x9b\x91\x0d\x04\xef\xb6\x90\x36\x62\xef\xc3\x10\x7a\xc8\xfd\xc0\xc5\xf3\x92\x72\x74\x0c\xd8\x77\xe1\x6c\xd7\x1c\x54\x92\x38\xc3\x37\x22\x0c\xe2\xf6\xb5\xa1\xfc\x6f\x7b\x0a\x1c\xd4\xed\x21\xd9\x38\x89\x08\x1e\x34\xfb\x7f\xde\xcf\x41\x78\xbb\xd4\x31\xe6\x11\xe5\x39\xd9\x00\xc3\xd0\xac\x3d\xc7\x10\x7b\x36\xb4\x1d\x6d\x0d\x5d\x32\xc1\x97\x27\xf9\x08\xb6\xeb\x36\x7f\xeb\xb3\x52\xa4\x93\x58\x1f\xf1\x28\xb5\x6c\x4c\xaf\x6f\xb8\xe0\x99\x81\xf0\xd3\x79\x57\xd1\x28\x20\x17\xfb\xb8\x07\x61\x4c\x20\xf4\x65\xdc\x02\xb0\xcd\x96\x99\x83\xbd\x5a\xe1\xeb\xf6\x57\x8d\x7f\xf3\xce\xff\x32\x0e\x25\x56\x21\x99\xde\xe9\x34\x75\x7c\xc1\xf5\x8d\x55\x40\xc4\x1a\xac\x1c\xe4\xf2\x11\xf0\xb8\xec\x41\x07\x17\x40\x30\xe7\x02\xbc\x6a\x8a\x9c\x85\xc5\x05\xc9\x31\x6a\xef\xea\x3e\x43\x72\x24\x2d\xe0\x19\xb3\x5e\x2b\xd3\xc5\xa9\x56\x52\x19\x71\xc1\x06\xa3\xad\xbb\xc1\x3c\xdc\x4f\x7f\x9d\x3c\x58\xb9\x6a\x34\x4b\x4a\xc3\xef\x6b\xd8\xac\xa6\xed\x98\x76\xb4\x3e\x64\x97\xfa\xf7\xfa\x4c\xf2\x7f\xbc\xb6\x65\x73\x0c\x09\x1e\x13\xaa\xf7\xe9\xef\xe7\xdd\x10\xe1\x4e\xb1\x9a\x92\x00\x42\x42\x10\xec\x8b\x8f\xba\x7e\x69\x44\x4c\xe1\xa9\xe3\xa7\xb2\x6c\x11\xf6\xb7\x14\x5b\x69\x83\xa7\x80\x57\x76\x48\x40\x31\xbf\xf5\x2e\x81\xae\x76\x9b\x70\xa2\x82\xb0\x94\xff\xb5\xfb\x55\x25\xdc\x1a\x87\x2e\x20\x7e\x82\x7a\x2e\x11\xf4\xec\xf7\xb5\x30\x8c\x74\x8a\x92\x78\xea\x7b\xd6\x61\x88\x19\x44\x00\x43\x0c\x8c\xd5\x96\xeb\xb8\x72\x21\xe5\x36\xf6\xaf\xe1\xf1\x50\x5d\x6a\x59\xf4\x1d\x16\xa2\xf0\x14\xe1\xcf\xa5\x13\xf7\xa6\x97\x31\xd7\xbf\xdb\x2a\xff\xce\xfe\x05\x37\xd4\x2c\x79\x6e\x3f\xd2\x7e\x41\xb7\xca\x72\x05\x1b\xef\x28\xbb\x7b\xde\x70\x10\xdc\xfe\xd8\xaa\x16\xef\x67\x6d\xb6\xe5\x20\xc3\xce\xf8\xd6\xf5\x8a\x9a\x28\x13\xcf\xf0\xf7\x04\x1f\x87\xfb\xfb\x84\x31\xe0\x20\xed\xe1\xd4\xea\xf1\x9e\x23\xb9\x83\x44\x5c\x59\x15\xb5\x4a\xdf\xb5\x57\xfc\x20\xd0\x05\x8f\x40\xf5\xe0\x98\x25\xdb\xa8\xd8\xf2\x0c\x00\xf4\x3b\x3a\xee\xbb\x61\x57\xbe\x32\xec\x54\x62\x7d\x5d\x42\xab\x81\x3c\xf9\x7f\x09\x5d\x26\xdb\x80\x36\xc1\x2e\x82\xcb\x96\x3e\x80\x01\x16\x7e\x61\xab\x39\x3b\x4c\xca\x75\x5e\xce\xa8\x69\x95\x4e\x32\x3f\xa5\x26\x2c\x5f\xda\x3e\x0b\xe9\xa5\x1e\x5a\xf5\x1f\xa6\x44\x48\x24\xfb\x83\x7c\xc6\x7b\xe5\x37\xa8\x75\x69\xc3\x0c\xf0\x11\x4d\x39\xa0\x39\x42\xde\x4e\x1c\xd5\x23\x35\x5d\xab\x1a\xf3\x60\x80\xa9\xa9\xa5\x48\xbe\x1c\x2a\x7f\xbe\x54\x33\x77\x23\x15\xd2\x83\xe5\x15\x6d\xf6\x48\xbe\xe4\xb7\xdc\xda\x74\xf1\x59\x05\xd5\x42\xbe\x54\x87\x3c\x15\xc5\x3f\xf4\x2a\xca\xbf\x8c\x56\xf2\x57\xd7\x64\x72\x2d\xb4\xe9\xc7\x18\xe1\x20\x98\xa3\x45\x74\x86\xa6\xc9\x47\xac\x2d\xe0\xaf\x53\xe8\x2c\xf9\x50\xbb\x37\xca\x29\xc8\xda\xdf\xa3\x64\x6d\xb4\x98\x2a\xf5\x72\xd3\x9b\x26\x8c\x7f\x96\xb0\x3e\xf6\xb6\x53\xc8\x79\x45\xf2\x9b\xc5"}, -{{0x55,0x32,0x8b,0xe4,0xb3,0x70,0x82,0x27,0x33,0xff,0x39,0x89,0xa6,0xa3,0x28,0x2d,0x65,0xfe,0x8f,0x20,0x7a,0xb7,0x27,0x0d,0x7c,0x2e,0x72,0x7c,0xa3,0xcf,0xaa,0xc4,},{0x51,0x8e,0x02,0xee,0xf5,0x2f,0x5a,0xae,0xbd,0xe3,0xd1,0x08,0xea,0x79,0xec,0xad,0xfc,0x4d,0x99,0x4c,0xe1,0x95,0x36,0x21,0xe5,0x4b,0x7b,0x3b,0x12,0x1f,0xf8,0xff,},{0xf5,0x8d,0xb1,0x9f,0xd8,0x34,0xe1,0x51,0x94,0xc3,0xc0,0xf8,0xa6,0xa5,0x0e,0xbc,0x4c,0xf0,0x74,0xe8,0x0e,0xa2,0xe7,0x0c,0xda,0xf1,0xe1,0x69,0xbd,0x51,0xeb,0xd0,0x99,0x0b,0xad,0x77,0xc4,0xfa,0x20,0x8b,0x8d,0xd1,0xe2,0xc8,0x57,0x4c,0x01,0xb5,0xf5,0x96,0xc8,0xdf,0xa6,0xbb,0x8e,0x6a,0xe3,0xa4,0x7f,0xf4,0x12,0xe7,0xe2,0x09,},"\x6c\x24\xc9\xaf\xbb\xf1\x2d\xca\xee\x6f\x10\xe4\x08\x92\x52\xf2\xc6\x0b\x2a\xb9\x3a\x02\xc1\x60\x2f\xb5\xde\x4c\xe3\xbd\x92\x3e\xb0\x2f\xe1\x03\x9f\xdc\x15\x99\x6a\x44\x69\x15\xe7\x67\xde\xe0\x17\x6d\xdd\xb7\x8e\x9d\x6b\xbf\x06\x96\x75\x77\x5a\x82\x9d\xd8\x08\xd3\x76\xb0\xcf\x79\x20\xbf\x1a\x66\xe1\x30\x3b\xa5\x24\x19\x78\x5f\x25\xf2\x8b\xb3\x38\x99\xeb\xde\x84\x0c\x0a\xb1\x4b\x91\x9a\x65\x80\xcb\xaa\xc3\xa8\x05\x62\x7b\x9c\x4a\x77\xba\xa1\x6f\x82\x5a\x9e\xac\x2d\x6d\x36\x41\x65\x14\x93\x37\x0e\x50\xee\xe9\x4c\x74\x04\x97\x64\x36\x56\x05\xab\x4d\xac\x1a\x03\x02\x27\xa3\x30\xaa\x17\x8f\x2f\x8d\xa3\x77\xaf\x73\xf0\xbb\x04\x0b\xac\x12\x36\x6e\x65\xe0\x59\x10\x55\xf9\xf2\x3e\xac\xa3\x5e\x96\x88\xd8\x37\xa3\xc0\xd9\x9c\x16\x8f\xd8\x86\xac\xc9\x22\xcf\x37\xa7\x11\x8e\xf8\xa4\x4b\xb0\xa4\xfa\x42\x88\x04\x93\x09\xa7\xdc\x1b\xed\x80\x62\x1e\x10\x63\xe3\xe5\x92\xc0\xfb\xa4\x2d\x73\x98\xeb\x15\xf7\x40\x28\xac\x15\xd7\xed\x65\xa6\x36\x8a\x13\xb7\xf9\x56\xd1\x95\x47\xeb\x50\x6c\xe7\xec\x90\x73\x4e\xb9\x49\xcf\xf1\xd9\x8c\xe4\x14\xf1\x0a\xdc\xba\x8c\x00\x73\x20\x01\x87\x50\xa7\x1b\xd3\x6d\x3b\x6b\xfd\x61\x27\x05\x45\x08\xe3\xef\x65\xd9\x98\x48\x51\x4d\x33\xd6\x8b\x58\xe3\xa4\xb2\x24\xf7\x9b\x6e\x34\xdd\x48\x03\x40\x46\x7f\xe7\xf0\x25\xcc\x88\x21\x3d\x80\x8f\xbb\x5b\x91\xe2\xe4\x3c\xf9\xd9\x50\x64\x07\x98\x65\x92\x73\xd4\x7a\x25\xf1\xf0\x13\x2f\x68\x82\xfa\xad\xba\xfb\xa2\x8f\xee\x5f\xa1\x72\x72\xc1\xa9\x00\x11\x72\xb3\xab\x6f\xf2\xc3\x15\xf2\x6c\x07\x73\x44\x05\xb5\xee\x8b\x5e\x4f\x08\xe1\xe3\xb8\xae\xa0\x19\x46\x7f\xb0\x71\x88\x7f\x19\x19\x01\xa2\x1c\x59\x76\xc1\xca\x8a\xaf\x0a\x1d\x4a\x2e\x69\x8e\x76\x23\xe9\xbb\xe9\xca\x2a\x67\xa1\x53\xa1\x6f\x89\x5e\x6d\xd9\xea\x92\x44\x41\xb4\xbd\x0b\x67\x45\x52\xe3\x98\xb8\xd9\x70\x34\x3a\x9b\xc7\x76\xa3\xa3\xfc\x1a\x86\x60\xc5\x62\x5d\x60\x81\xb5\xd8\x7f\x0f\x8a\xc9\xf0\x7a\xb5\xab\xe7\x7c\xdb\x8e\x30\xd2\xfd\x1f\x6f\x46\x52\x5c\x75\xdd\x0d\xd1\xca\x32\x81\xcc\x89\x34\x6f\xb3\xe6\xd7\x38\x8e\xbe\xe1\x54\xcb\x59\xbd\x9e\x95\xed\x6a\x41\xd5\xdf\x66\x8b\x59\xea\x13\x78\x68\xeb\x12\x0b\x8a\x2c\xfd\xf4\x67\x44\x14\xfd\x27\x96\x99\xf2\x8b\x5a\x5c\xcc\x2e\x2f\xc8\x02\xa4\xc9\xe0\xb8\x5b\x76\xf2\x0f\x6b\xce\x2a\x49\x54\x88\x6f\xc4\x02\x67\x0a\x71\xef\xd2\x61\xf5\xdd\x7b\xca\x16\x88\x4a\x28\x7c\x62\x2f\xd4\x45\xf6\x8d\x44\x15\x1c\xc0\x13\x4b\x22\x9d\xa3\x8d\xaa\xab\x81\xb5\xc9\x60\xd5\x77\x00\xca\x92\xb2\x6d\x0b\x14\x21\x34\xce\x94\xb7\xbe\x6c\x18\x61\x0e\xa2\x13\x6f\x8b\xa8\x32\x9a\x2e\x8c\x00\x0b\x8f\x02\xfe\x05\xbc\xf7\x2c\xb7\x1f\x8c\x72\x53\x5f\xfc\xd8\x18\xe3\x8e\x79\x92\xa8\xf0\xc3\x2a\xc6\x21\x77\xd1\x52\x2a\xe5\x52\xc6\x0c\x1e\xe6\x16\xb7\x5e\x4b\x34\x42\xe7\x96\x57\xe4\xa3\x33\xc0\xb3\xd7\x44\xea\xf2\x60\xd0\xc3\x36\x93\x16\x86\xa6\xd6\x68\xc6\x4f\xef\x44\x00\x52\x35\x2c\x2b\x25\x8c\xfb\x65"}, -{{0x7d,0xa0,0x5f,0x04,0xe5,0xd3,0x8b,0x98,0x9b,0x83,0xf7,0x2f,0x7a,0xb2,0x6c,0x13,0x87,0x76,0x75,0x8f,0x4f,0x57,0x7e,0x49,0xdc,0x73,0xd6,0x01,0x3f,0xf4,0x37,0x59,},{0xb1,0xde,0x51,0x67,0xf4,0xd3,0x30,0x80,0x4e,0xec,0x9e,0xb5,0x65,0xef,0x40,0x55,0xf1,0xb6,0x4d,0xd9,0x5e,0x1c,0x9b,0x27,0xc6,0x7f,0xfe,0xf9,0x14,0x82,0xcc,0xa8,},{0x05,0xf1,0x17,0xf9,0xbc,0x3e,0xa5,0x5d,0x45,0x5e,0x9e,0xf1,0x35,0xe9,0x2e,0x76,0x65,0xd1,0x80,0x70,0xd8,0xf5,0xe3,0x75,0xdf,0x67,0xbe,0x18,0x17,0xce,0x14,0x35,0x7a,0x55,0xe7,0x01,0x66,0xf3,0x26,0xb7,0x7d,0x85,0x24,0x32,0x27,0xcf,0x67,0xd8,0xf2,0xe0,0xbf,0x84,0x40,0xca,0xbf,0xb0,0x52,0x75,0xb3,0x73,0xf1,0xe1,0x19,0x0e,},"\xa6\xa8\x61\xd8\x94\x7c\x5c\xd6\xad\x08\x19\x60\x2e\x32\xea\x76\x81\xc8\xf7\x30\x10\xee\xe5\x53\xe5\xde\xfb\xf7\x98\x20\x98\xb5\xf7\xb3\x99\x24\xbb\x79\x59\xad\x64\xc3\x03\x26\xbe\xd5\x60\xbf\x51\xe9\x98\x3c\xda\x5d\xff\x4f\x31\x1e\xea\x24\xcb\xe6\x8c\x61\x06\xce\xac\x9b\x84\x3a\xa4\xe2\xad\x1b\x6f\x8a\xe1\xe4\xf9\x68\x71\xfc\x02\x5b\xe4\xa6\x16\x38\x5f\xf2\xd4\xb7\xf5\x68\x29\xab\xef\xaf\x6a\xac\xbb\x78\x0d\x6c\xbb\xc9\x51\xb6\xe0\x5a\x78\x7f\x88\x5e\x33\x25\x61\x16\x65\xec\xc9\x24\x27\x4a\xa5\x31\xbc\x13\x3f\x62\xc7\x6c\xb3\xad\x14\x8f\x3c\x95\x79\xa8\x15\xa1\x42\x00\xb7\x64\x8d\xae\x0b\x07\xb3\x27\xd3\xbf\xcc\xdb\x6f\xe3\xb6\xcb\xd7\x0e\xa6\x5e\x6c\x0c\xc2\x51\x6a\x89\x66\x96\xd0\x7b\x2e\x77\x71\x3b\x0b\xee\x3b\x92\xfb\x1b\x6f\x75\xb0\x82\x0a\x5c\xb6\x2c\x5f\xe6\x20\x40\x03\x94\x3e\x24\x85\x71\x66\xfb\xdf\x57\x1f\x11\x5d\x45\xf4\x2e\x75\x90\x1d\xf8\xb1\x2c\x32\x61\x8a\xac\xb0\xd2\x42\x86\xc8\xd3\x03\x96\x05\x1f\xc2\x72\xaa\x17\xf4\xd2\xd4\x74\x61\x15\x2a\xac\xd3\xfa\xa2\xb7\xb2\x08\x31\x22\x78\xe8\x09\x24\x05\x92\xd1\xd1\xaa\x58\x5c\x56\x28\x0e\x66\xff\xd9\x2b\x57\x17\xd0\xcd\x1e\xb9\xfb\x74\x01\xde\xf8\x79\x48\x7c\x37\x4e\x5c\x53\x0b\x6f\xeb\xf9\x11\x12\x25\x74\xd2\x4f\xe1\x04\xb4\xf4\x5c\x7c\x60\x1e\x6c\x91\x7d\x3c\x18\x82\xc1\xad\x3c\x55\x5d\x8f\x2c\xe9\x55\xb5\xa1\x0d\xb0\xd5\xa8\xb8\xac\x7a\x62\x66\xb2\xe6\xb2\x7a\xd0\xee\x34\xf4\x7a\xd8\x57\x36\x7d\x52\xf7\x09\x6d\x4b\xac\xef\x0e\x46\x72\x54\x88\x42\x4b\x93\xb8\x9a\xcd\x42\x9f\xfb\x5e\xf3\x3a\x0b\x08\x1d\xd0\x94\x79\x67\x91\x96\x02\x3c\x39\x67\xf4\x4a\xd4\x1e\xb1\xa2\x39\x55\x27\xfd\x3b\x79\x76\x8f\x1b\x88\x5f\x04\x29\xb4\x95\xab\x60\x52\x56\x91\xbe\x84\x65\x06\x32\xa2\xf6\x6c\xb6\x3a\xd5\xbf\x2f\x6a\xe7\x0b\x66\x8c\x5a\x19\x3f\x74\x99\xfc\x4f\xc4\x2c\xf8\xcb\x30\x8c\xe5\x02\x9a\x50\x27\xba\xbe\xf5\x5d\x19\x25\xec\xfb\xa9\xf2\x7e\xb6\x08\x16\x19\xed\x0d\xf8\x56\x9f\xd8\x0e\x9d\xa1\x04\xdb\x39\xb5\xb8\x14\x0b\xfe\xbe\xbd\x29\x08\x54\x40\x06\x58\x19\xde\xba\x8d\x46\x9a\xe8\xb3\xea\x6d\x3b\xac\x58\x91\xf9\xa4\xdd\xfb\x7f\x1f\x06\xd1\x3c\x31\xa0\x7e\xe5\x3f\xb5\x4b\xc9\x7b\xd0\x86\x96\x39\x4c\x38\xe7\xf3\x68\x0c\x0f\x02\xf9\x75\xf4\x69\x92\x11\x47\xa4\x09\x85\x90\x97\x81\x3b\x4c\x3f\xa4\x3d\x17\x4a\xc4\x02\xf1\xa5\x28\xcb\x5f\xc4\xb8\x07\x51\x84\x32\xef\xf3\x34\x07\xa1\x11\xca\x3a\x3d\x7e\x9e\x84\x13\x5a\xba\xc8\xa8\xf5\x2e\xa6\x31\xc8\x6d\x74\xa1\xc6\xe5\x74\x9e\xdd\x14\x91\xc0\x02\x4e\x7d\xe7\xfe\x52\x85\x68\x29\xb7\x2f\xd1\x3d\xa6\x3a\x1a\x23\x43\x34\x9d\xf6\x62\xab\x31\x63\x53\x60\x32\x34\x6e\x53\x47\xf0\x43\xff\xf5\x28\xbf\x67\x15\x09\x22\xff\xf2\x02\x6b\xab\x74\x2d\xb9\xca\xe7\xcb\x2e\x3c\x74\x58\x07\x19\x65\x2c\x28\x44\x7c\x5e\x20\x98\x23\x17\x97\xee\x6e\xf1\x23\x1f\x57\x92\x05\x4b\xc3\x35\x9a\x32\xc8\x6d\x2f\x94\xf8\x5f\xa7\xd4\xa7\x41\x9d\xd2\x41\xff\x66\x2a"}, -{{0x1b,0x8e,0xc6,0x58,0x80,0xed,0xbf,0x03,0x9a,0x13,0xe9,0x70,0xb1,0x5a,0xa6,0x7e,0x19,0x2a,0xa0,0x2c,0xa6,0x5c,0xff,0x9a,0xda,0x17,0xd4,0x55,0x8f,0x40,0x13,0x7d,},{0x12,0xc1,0x19,0x1e,0x4d,0xe3,0xbd,0x44,0xd0,0x39,0x07,0x01,0x53,0xad,0xb7,0xb5,0x81,0xf6,0x00,0xe9,0xa1,0xdd,0x69,0xaa,0x89,0xf2,0x77,0xc7,0x06,0x9e,0x76,0xf8,},{0xbf,0xf2,0x69,0xa3,0x5d,0x6c,0x8e,0x55,0x2c,0xe7,0x16,0xd1,0x63,0x81,0x81,0xce,0x85,0x83,0xb4,0x5c,0x0e,0xc5,0x93,0xb4,0xe5,0x8c,0x40,0xac,0x76,0xe7,0xf8,0x5c,0xa1,0xda,0xff,0xfd,0x68,0x54,0x1e,0x62,0x3a,0x1e,0x35,0xa7,0xc0,0x97,0x26,0x88,0xb2,0x5e,0xed,0x72,0xf4,0xda,0x57,0xec,0xa1,0x68,0x57,0xa8,0x26,0x3c,0xaa,0x0b,},"\x37\xf1\x8b\x7f\x64\xc5\x13\x34\x79\xd6\xda\xe3\xbe\xf6\x79\xcd\xc2\x1e\xce\x3f\x5b\x57\x9a\x6a\x9c\x3f\xa2\xe5\x9e\x9b\xe8\x7d\x20\x09\xf7\x4e\x1c\xfd\xac\xcb\x1c\xe3\x7d\x00\x70\x23\x69\xbd\x16\x9d\x94\xfd\xcf\x85\xaf\x9f\xa3\x21\x7d\x27\xe6\xed\x6d\x1d\x8e\x5d\xf7\x61\x5e\x8e\x37\xea\x55\xde\x1f\xd0\xb0\x6d\x77\xb4\xc8\x3b\x92\x9d\x80\x58\x6f\xa0\x69\x4b\xe7\x2e\xc8\xb3\x65\xad\x2c\xbc\xdd\x2b\x1a\xd8\xcf\x7f\x03\x6d\xfa\x4d\xaa\x1a\x90\x36\xcd\xb1\x20\x43\x22\x27\xb1\xf0\x7b\x88\x66\xb1\x22\x12\x03\x09\xeb\x91\x4a\xb8\x4c\xdd\xeb\xa1\xde\xc4\x8a\xb9\x26\x36\x72\x85\x88\xfe\xdb\x3a\xaa\xd7\xe7\xdb\xb2\xac\x30\xe6\x3c\x6f\x5f\x90\xfc\x6c\xe6\x2d\x6d\x3b\xd8\x8b\x0d\x5a\xac\xfa\x61\xde\x9f\x32\x67\xb3\x00\x91\x7b\x57\xa4\x80\x36\xab\x20\xc9\xa0\x54\x46\xb8\x76\x74\x94\xaf\x24\x9e\x7d\xe7\xbc\x50\x7a\x22\x07\xcc\x95\x6f\x71\x84\x55\x5a\x7d\x5d\x88\x83\xbb\x4b\x3e\x93\xf2\xdc\xfc\x57\xb0\xda\x86\x38\x65\x8d\xcd\xce\x88\x5d\x44\xd9\xcc\x68\xb1\xd8\x17\x0a\x36\x77\xcc\x5e\x50\xcb\xf3\x3d\x54\x3e\xba\xe4\x47\x7d\x92\x39\xcf\x83\x38\x4e\xc5\x9b\x42\x33\xe8\xff\x33\x43\xf0\x6f\x30\x18\x77\x72\x9a\x53\xd4\x20\xbf\x01\xc6\x2e\x66\xab\x7f\xe5\x5d\xd8\x7e\xe8\x23\xa5\x8f\xcb\x87\x87\x0e\x1f\x52\xe8\x79\x17\x7c\xd4\x39\xc5\x33\xf5\xa2\x23\xe5\xa3\x43\x6f\xe9\xd6\x42\x65\x48\xda\xcf\xc8\x6a\x08\x46\xd3\xed\x23\xac\x04\x25\x63\xe8\x87\xff\x46\xaa\xd0\x05\xf4\xe1\xde\xe3\xee\x0e\xe4\xc2\x7a\x72\x51\x70\x9a\xe4\x0a\xbc\x5e\x25\x68\x64\xe4\x78\x5a\x4e\xdd\x8b\x2a\xdf\x1b\xc5\xb4\x01\x8e\x28\xd0\xb1\x75\x86\x7b\x02\xd0\x52\xa6\xe1\x7e\x41\x1a\x3d\x8b\xeb\x2a\x42\x08\xb7\x6c\xc6\x21\xfd\x18\xbe\x14\x8e\x23\x5d\x55\xaa\x71\x27\x70\x65\x57\xde\xc0\x53\xa1\x3f\x1a\x47\xdf\xda\x40\x5b\x3f\xe5\xbd\x28\xef\x5d\x34\x86\x19\xf5\x1e\x59\x5e\xf5\x05\x5f\x83\x9e\xfa\xf1\x10\xe4\x90\x16\x31\xac\x31\xa0\x2f\x4f\x7e\xe4\x24\xa3\xa2\xc3\xe0\x0d\x26\x02\xd2\xcc\x1e\x49\x29\x06\xee\xa4\x20\xa9\x26\x82\x38\xac\x66\x22\xa0\x89\x74\xe5\x73\x02\x92\xe6\xed\x51\x02\x56\xef\xde\x66\x7e\x0d\x9a\x0f\xf2\x21\x3f\x54\x12\x0c\xcd\x81\xff\xaa\x6b\x7c\xc4\x81\x41\xa2\xb7\x29\x85\x2a\xf5\x83\xd2\x6a\xa5\x1f\xbd\xe6\x7b\xe4\xdf\x14\xe5\x20\xc2\x25\x7a\x73\xc5\xc2\xe3\xc3\xd8\x7d\xfb\x25\x36\x11\x75\xfd\x18\xab\xd7\xe9\x9a\xa0\x9b\x85\xf8\x8f\x19\xc8\xd8\x2d\x45\x85\x8f\x31\x44\xc5\xdf\xb7\xa4\x9e\xde\x45\xb4\xef\xd8\x71\x05\x92\xa3\x72\x06\x36\xe7\xe8\x89\xc7\xe2\x2a\xd1\x3b\x2d\x44\xbb\x7e\x2b\x47\xb2\x96\x3a\x5f\xa3\xf2\x55\x7b\x85\xbc\x0c\x69\x3d\xe3\xd2\x2e\xf9\x46\x4f\x7b\x81\x4a\x20\xa4\x67\x6a\xd2\x6f\xca\xa0\x35\x44\xc6\xaa\xd4\x12\x83\x09\x5f\xcd\x12\x10\xaa\x8c\xc0\x29\xff\x5a\x26\x00\x5a\x89\x12\x26\xc2\x98\xe9\x4a\x52\xaa\x71\x33\x91\x3e\xc9\xd2\x2a\x5b\x2a\xc0\xbc\x6f\x15\xb2\x51\xd0\xb9\x38\x89\x21\x3c\xd1\xb1\xe5\xc6\xfd\x08\xf1\xa8\xf5\xcb\xd4\x21\x53\x29\xa3"}, -{{0xe7,0x53,0x88,0x02,0x6a,0x6a,0x6d,0x6c,0x6d,0x19,0x9e,0x36,0x29,0x93,0xa5,0xb1,0x04,0x49,0x01,0xe1,0x8a,0x76,0xc2,0xfa,0xc7,0x26,0x1a,0x6d,0x1c,0x19,0xa4,0xf3,},{0xb9,0xce,0x14,0x25,0x1c,0x0c,0xdf,0x3b,0xdd,0xb2,0x06,0xdc,0x6b,0x8b,0x2b,0x7f,0x5b,0x7e,0x4d,0xd1,0xbe,0x2c,0xe1,0x86,0x3f,0xf1,0x88,0x06,0xae,0x00,0xf1,0xee,},{0x6d,0x0f,0x83,0xd9,0xc5,0x5d,0x84,0xbc,0xf9,0xa8,0x61,0x47,0xd9,0xb6,0xba,0x9a,0xd5,0x37,0x83,0x2f,0xd0,0xf9,0x9d,0xae,0x7e,0x72,0xc8,0x13,0x9a,0xfc,0xb3,0x0c,0x7b,0x24,0xf6,0xb2,0x92,0xe3,0x2f,0x98,0x47,0x09,0x75,0x51,0xb7,0xfb,0xfd,0x51,0x0c,0x84,0xe8,0x9b,0xe9,0x82,0x54,0x44,0x14,0x57,0xbd,0x08,0xe5,0xf0,0x53,0x02,},"\xb9\x9c\xdc\x84\x72\x11\xc0\x66\x42\xdd\x11\x1b\xc5\xe0\xbe\xca\x53\xa7\x4f\xfb\xa2\xe3\xac\x93\xaf\xb4\xb0\x94\x75\x18\xe8\x32\x35\x27\x33\x0a\x4e\xfe\xfb\xe4\xba\xfa\x00\xba\xfe\xcb\x43\x4a\xb1\xe5\xb7\xce\x65\x65\x6f\x7a\x4f\xd8\x56\xaa\x6c\x38\x5e\xd8\xd7\xbd\x62\x85\x58\x0d\x7d\xd6\x08\x82\xe6\x9c\x19\xda\x07\x69\x09\xd6\x47\xde\x09\x5a\x80\xe9\x8a\xd8\x9b\x81\x4a\xad\xcb\xbf\x6f\x03\x3c\x49\x20\x2f\x65\x6c\x09\x10\x50\x39\x59\xcf\x97\xcd\x0f\xa8\x2d\x5f\x6d\x22\xfb\xa3\x38\x99\x51\x29\x4c\x4f\x7c\xdc\x21\xeb\x82\x44\xbd\x65\x60\x63\x7a\x5e\xca\x62\xa8\xeb\xa1\xf4\xa9\x33\xd1\x87\xa7\x5f\x86\x71\x16\x43\xaf\x35\x88\x31\xc8\xc1\x6a\x9a\x0f\x09\xe2\x53\xb2\x39\x5e\x9c\xb3\x71\x61\x1e\xec\xdd\x66\xb4\xab\x52\x1a\xa9\x4b\x3f\x20\x23\x7e\xae\x41\xcd\x10\xc5\xe2\x1a\x45\x2d\x48\xe7\x48\x18\x7f\x35\x4a\x67\xad\xf6\x81\xb0\xfe\x61\xcd\xae\xc9\x4a\x5e\xaf\x01\x26\x9f\xce\xb5\x70\xd5\x14\xff\x3c\x55\xff\x1d\xba\x2f\xd2\xdf\x17\xf8\x6a\x8a\xeb\x74\x78\x38\x11\x3d\xee\x94\xa4\x3b\x13\x84\xcb\xe1\x33\xcd\xf6\x42\x7e\x8d\x12\x2e\x4e\x93\x37\x04\xda\x6e\x26\xcf\xce\xe9\x7f\xe3\xf6\x29\xb6\x0b\x91\xb2\xdd\x86\x38\x67\xfa\x79\x80\x1e\x2b\x91\x6e\xc4\xc0\xfb\x62\xe0\x71\x59\x42\x1e\x65\x79\x74\x30\x7a\x1d\x02\xf7\xf2\xed\x47\x24\xa8\xb5\x21\xa8\x61\xf5\x5f\x35\x52\x1e\x8b\x2e\x1a\x84\x90\x4c\x42\x8c\xfc\x5b\x60\x14\xbb\x0f\x8b\xa8\x43\x4c\x22\x09\xbd\x40\xac\xa3\x11\x30\xdb\x97\x74\x33\x33\x59\x7d\x23\x51\xd5\xf6\x81\x17\x41\xf6\x26\x88\x97\x3b\xd7\x73\xd3\x02\x66\xfd\x1e\xfb\xd8\x9d\x47\xa9\x64\xf9\xd0\x19\x97\x15\x3d\x08\x7d\x92\x69\x66\x16\xdd\x10\x3a\x93\x4c\xcb\xac\x4c\x1d\x14\x2f\x20\x75\xd4\xe2\x2c\x3d\xa4\xa0\xe9\x73\xb2\x38\x63\x19\x62\x87\xb7\x91\x74\xfa\x29\x75\x5f\xc6\xd9\xb5\xe1\x00\xac\xe0\xa4\x59\x75\xe5\x03\xb2\x54\xd3\xf1\x95\xc2\x61\x71\x09\x10\xfe\xf1\x06\x89\x2c\x08\xbb\x29\x6d\x23\x0c\xde\xa9\xf5\xa1\x1f\x91\xac\xaa\x6e\x7c\x05\xe9\x2c\x28\x1d\x2b\x31\x55\xfe\x44\x80\xb0\xaa\x5e\x0d\xb4\x1d\x10\xe0\x5c\xfd\xef\xa4\x36\x40\x51\xcb\x75\x5d\xc7\x2f\xfa\x97\x8c\x00\xb9\x4a\x5f\x21\x2d\xc6\x91\xf8\x39\xb4\x9d\xe9\x7e\x01\x39\xd6\x5e\x8d\x73\xb2\xb2\x89\xb2\x6a\x12\xc6\xcc\xd8\xed\xc0\x4a\xdb\x45\x2a\xf7\xff\x09\x4a\xa9\x01\xea\xf5\x76\x51\xeb\x1b\x87\xb8\x33\xd0\xa0\x9b\x4a\x4a\x64\x62\xf4\x06\x64\x62\x37\x69\xe9\x50\x79\xf3\xc9\x62\x85\x0c\xc3\xb4\x01\xbb\x00\x58\xb8\x47\x5b\x10\xc8\x62\xf3\x2f\x30\x0a\x2b\x14\x3b\x3d\xea\x26\x9d\xdc\xbe\xa7\xbe\x7d\xd2\x42\x6d\x0d\x42\x04\xeb\x66\xa3\x9f\x13\x18\x82\x2d\xcb\x9c\x56\x13\x98\x63\x7f\x4a\xb8\xde\x19\x67\x68\xac\xe7\x4f\x34\x8c\x01\x2d\xd1\xba\xbe\xc1\x7f\x53\x00\xff\xe0\xd7\xaa\xae\xaf\xef\x7d\xb6\x50\xa8\xf2\xf3\x09\xa9\x79\x3f\x52\xc6\x85\xc7\xe1\xd5\x13\x32\x74\x91\x57\x84\x89\x9c\x48\x1d\x48\x5c\x9b\xd3\x0e\x99\xfc\xdc\x97\xd9\x6e\xf0\x74\x87\xda\x66\x3b\xef\xe6\x82\x99\xdf"}, -{{0x5b,0x32,0x3f,0xc0,0x1a,0x16,0xc4,0x5d,0x10,0x64,0x66,0x7d,0x2e,0xa4,0xa7,0xea,0x59,0xd2,0x03,0x42,0x56,0x2d,0x12,0xfb,0xc5,0x98,0xd5,0xaa,0x73,0x00,0x68,0x8e,},{0xd4,0x14,0x1b,0x45,0x5d,0x30,0x16,0x42,0xba,0xda,0x28,0x14,0xaf,0xcb,0x16,0x20,0xd5,0xeb,0x56,0xd9,0x2b,0x11,0x85,0xfe,0x5d,0xad,0xef,0x55,0x96,0x25,0xfa,0x71,},{0xe2,0xef,0xf6,0x07,0xf0,0x22,0x7a,0x29,0xd5,0x82,0xd6,0x9f,0x34,0x58,0xac,0xad,0xd3,0x22,0x6f,0xce,0xaa,0xc0,0xab,0xbd,0xae,0xd5,0x26,0x75,0xc5,0x16,0x30,0x07,0x3c,0xd3,0xa9,0x01,0x70,0x7e,0xcf,0x05,0xe8,0x93,0xf2,0xc3,0x6d,0xaa,0xf0,0xcc,0x49,0x01,0x11,0x69,0x46,0xb5,0x77,0x0d,0xc0,0x38,0x12,0x5f,0x6d,0x13,0x1b,0x09,},"\xad\x24\x66\x9e\xf5\x5c\x54\x0a\x8e\xd1\x62\xce\x1d\x28\xf0\x17\x60\xa6\x07\x19\xa0\x37\x73\x36\xeb\x00\xb1\xec\xbe\x6f\x61\x60\x1c\xd5\x64\xf9\x2c\x95\x68\x04\xf9\xbe\xd4\xe1\x47\x6b\x94\xe5\xea\x8c\xca\x80\xcb\x49\xa3\x04\xef\x85\x1f\x7f\x67\x5a\xbe\x58\xe6\x68\x1d\xc0\x12\xad\x55\xe5\x1b\x02\x1d\x98\x28\x56\x9d\x0b\xcc\x9e\x05\x27\xa3\xfc\x03\xc8\x91\xd1\x7a\x90\xe6\x33\x7a\x1e\xa6\x7f\x2f\x08\x81\x05\x87\x69\x38\x37\x08\x1e\x4c\x08\xa3\xd7\x2c\x53\x6c\x21\x40\xda\x20\x0b\xa4\x56\xc3\x76\xf6\x1d\x05\x65\x1f\x0c\x5f\x39\x57\x11\xf4\x1c\x0d\x6e\xae\x98\xc9\x06\x76\x4d\x1e\xbe\xf3\xf9\x04\x6c\xb7\xc8\x62\x26\x40\xfc\xaf\xaf\xbf\xb8\xf6\x2e\x1c\xd3\x2c\x66\xee\x1c\x55\x50\x94\x89\xa5\x38\xab\x61\x29\x99\xe7\x99\x7b\x77\x9c\x64\x22\xef\xf1\x09\xda\x4d\xf8\x29\x20\x93\x0d\x8d\x36\x3d\x78\x30\x90\x87\x95\xa3\x88\x8f\x25\xd6\x67\xe1\x4d\x15\x5e\xd4\x45\x81\xbe\x43\x0f\x79\x73\xb5\x74\xe2\xbc\x0b\x13\x4c\xf1\x39\xfb\x4b\xb0\x1d\xbd\xa4\x1b\x67\xb9\x81\x47\xd8\x01\x2f\x40\x67\x7f\x4b\x80\xce\x4a\x53\x4c\x90\xad\xea\xbf\x48\x4b\x21\xfa\x99\x4b\x7a\x17\x5f\x8a\x8b\x8a\x40\x75\x56\x44\x78\xdd\xb0\x50\x24\x58\x0b\xab\x03\x8c\xd9\xea\xa1\xdf\xda\x55\x2f\xb3\x12\x29\x42\x9b\x61\x4f\xa1\xd8\x0c\x52\x61\x4e\x84\xfa\xa2\x21\x7f\x26\x0f\xf7\xcc\xea\x8c\x7b\x06\xe3\xd7\x7f\xf8\x74\xeb\x81\xfc\x85\x97\xe5\xfc\xdc\xec\x95\x1b\x5f\xe6\x4a\x1a\xf8\x6e\x73\x19\x3a\x88\x24\x69\xeb\x3b\xa3\xc3\x82\x73\x4b\x28\x87\xb4\x19\x31\x6e\xa4\x48\xaf\xc2\x82\x47\x8c\x25\xf7\xbc\xa1\x84\x29\xcb\xbf\xfd\x88\x71\x17\x7c\x5e\xcc\x7d\x8a\xa9\xa1\xb9\xec\x87\x19\x2d\x29\xa5\x25\x39\xc0\x81\xc3\x59\x33\x32\x44\x4c\xbe\x66\x87\x2c\xf3\xd0\xe1\x97\x29\x2b\x82\xb0\xbe\x5f\xcd\x85\x8c\xd6\xca\x48\xb5\x3e\xe5\xb6\x16\x41\xbc\xaa\xf3\x1d\x81\x9c\x7e\x1c\xed\xaf\x9e\xe6\xb0\x7e\x09\xca\xed\xfb\x30\xb9\x20\x4a\x1d\x4d\xdb\x70\x56\x0c\xbe\x1e\xb0\xc0\xec\x43\xf1\xd1\x78\x20\x1b\x29\x08\x19\xfc\xdc\x92\xc6\x3e\x0d\xb6\x0f\xb8\x7d\xff\x00\xe5\x12\x64\x8c\x89\x58\xa8\x47\xef\xc3\x63\x46\x07\x3f\x1a\x4f\x1f\x23\x17\x06\x0f\x1c\x54\x3e\x6f\x01\xb4\x24\x85\xbe\xeb\x56\xca\xb3\xba\xb2\x6e\x6a\x0c\xa6\x93\x58\x02\xc7\x62\xb7\x99\x15\x9e\x32\x0f\x36\xb5\xe8\x3d\x4a\xca\x89\x62\xaa\x2c\x3c\x2b\x7a\x38\x70\xe9\xe0\x47\x31\xf3\x94\x8c\xf9\x41\xe2\x1d\x50\x96\x4e\x5d\x63\x5a\x35\xa5\x3e\x29\x98\x11\xb8\xca\xdf\xcb\x44\x16\xc5\x75\x98\xa3\xfd\x05\x41\x09\x10\xdb\xc0\xea\x2c\x78\xfd\xb9\x25\x74\x99\x7d\x58\x79\x62\x79\xea\xaa\x78\xb3\x6d\xce\xf1\xc9\xa1\x29\xee\xff\x82\x39\x9a\x26\xd0\x08\xff\xa3\xbf\x04\x18\xff\x7d\x39\xb6\x42\x7f\x34\x18\x95\x02\x4d\x16\xe2\x2a\x0c\x62\xa8\x2b\xeb\xa2\xe2\xba\xc2\x3d\xee\x18\xcf\xcd\x5d\xb2\x39\x7f\x37\x8c\x53\x67\x30\x90\x82\xc4\x4e\xb4\x3c\xed\xc1\x52\x20\x25\x3a\x62\x32\x03\x99\x66\x5f\x71\x34\x9c\xc1\xb9\x44\xf5\x8c\x73\xa1\x0a\x0b\xbf\xd4\xca\xf1\x28\x91\xe3"}, -{{0xbe,0x1c,0x11,0x2f,0x78,0xcf,0x13,0xae,0xfc,0x5c,0xe7,0xe3,0x37,0x64,0xac,0xa4,0x48,0x1f,0x9f,0x88,0xb0,0x18,0xe1,0x22,0xdb,0x9f,0x8d,0xac,0x14,0x62,0x46,0x05,},{0xae,0x38,0x99,0x36,0xbb,0xf6,0xd1,0x6e,0x3c,0x1e,0xeb,0x64,0x74,0x29,0x89,0x70,0x86,0x6e,0x12,0xec,0x9c,0x1d,0x6a,0xea,0x2f,0xd9,0xdb,0x6b,0x56,0xaa,0x59,0xc4,},{0xf5,0xfc,0x5a,0xcb,0x17,0xe9,0x95,0x7e,0xa3,0x04,0xf1,0x23,0xb6,0x50,0xe1,0x44,0xc9,0xe4,0x37,0x72,0x83,0x50,0x9d,0x43,0x1d,0xa6,0xa2,0xbb,0xd5,0x27,0xbe,0xb3,0x82,0xc9,0xf5,0x87,0x45,0xa3,0xe5,0x6d,0xcc,0x65,0x5b,0xd2,0xeb,0xb7,0xae,0xef,0xc9,0x3e,0xdc,0x3f,0x20,0xd8,0xd3,0xc3,0x79,0x23,0x03,0x1e,0xec,0x0c,0xb4,0x07,},"\xd7\x7f\x9a\xee\xa0\xfe\x98\xed\x7f\xb7\x4d\x58\x2a\x40\x2b\xcb\x79\x31\x47\x4b\x4a\x95\xd5\x23\xf3\xfb\x76\x9f\xb7\x09\x7d\x2b\xe4\xc6\xec\x10\x52\x14\x01\x63\x22\x25\x53\xaa\x8f\x4f\x89\xe4\x21\x73\x00\x14\xec\x73\x46\x97\x20\xce\xa9\x67\xf8\x8b\x6a\x48\xd0\x2a\x2d\xdc\x1a\x12\x1f\xdf\xfb\x8a\xe1\x27\x73\x8e\x29\x3c\x4d\x6b\x1b\x74\xad\x03\x84\x4d\xe6\xbf\xe8\x21\x50\x6b\x3a\x7a\x81\xd1\x9c\x37\xa7\xf0\x1c\xa4\x81\x47\x12\x19\xef\xe2\xa7\xb9\x2c\x4b\xd2\xac\x07\x74\x3b\x49\x75\x69\x64\x41\x71\x4b\x84\xd6\x3c\x54\x9d\x7a\x6f\xb6\x1f\x16\xfb\xcd\xb7\x2b\x91\x4d\x78\x82\xd0\x91\xf9\x70\x6d\xa3\x8c\x1a\x81\xa1\xc6\xa4\x0f\xbe\xc0\xd8\xe2\x38\xb5\xd5\x6d\x46\x0e\x90\x9f\x85\x47\x9f\x7a\xd8\xb1\x19\xf3\x54\x55\xe3\x40\x10\xca\xa7\xe5\xd0\x1f\x38\xe3\x01\xad\x37\xe8\x00\x5f\x6e\xd2\x9e\x4a\x10\x2d\xb3\xf6\x1d\x84\x09\x3f\x78\xc4\x9a\x96\x48\xc9\x77\xbf\x4d\x5b\x68\x9f\x71\xf4\x06\xf8\xad\x7b\x9a\xeb\x1a\xe2\x21\x33\xa8\x4c\xe1\xb2\x78\xb2\xcd\xde\x46\x59\x01\xb2\x3a\x17\x9d\x07\x2a\x80\x87\x9d\x0a\x24\xd2\xaf\x19\x7b\x32\x2a\x07\xbf\x5d\x40\xee\xab\x3a\xf1\x21\x17\xf1\x30\x21\xdf\xc1\x68\x1a\xba\x5c\x08\x3f\x25\x96\xe3\x7f\x11\x23\x42\x2b\xbd\xca\x3b\x2c\x32\xcb\x59\x4f\x56\xc3\x25\xe0\xc5\x64\xa1\x73\x32\x88\x05\x34\x59\xc6\x24\x88\x92\x5c\xd8\x0e\x7c\x94\x4d\xb9\x98\xc3\xc7\xbe\x54\x6b\xf8\x9d\x7a\x51\x1c\xcd\xba\x4b\x80\x9e\xee\x0f\xc2\x87\x3d\xad\x72\xb4\xcf\x3b\xa0\x51\x28\x9b\xb3\xf4\xe9\x92\x57\x32\xe4\x5a\xe7\x74\x10\x58\xc8\xfd\x11\x59\x9d\xd8\x43\x92\x7e\x3d\x14\x59\x8b\xb8\x30\x52\xd3\x35\x69\xcf\xb0\x2a\xf0\xc8\x8f\xa7\xae\xa4\xbb\x46\x84\x1c\xd2\xdd\xbd\xf5\x98\x8f\xcf\x32\x5f\xf1\x04\xa5\xdf\xc4\xa3\x0d\x26\x9d\x2a\x94\x97\x30\xc3\x61\x3b\xdd\xd3\x67\x3b\x42\xf6\x09\x0e\x6a\x60\xe4\xa2\x53\x06\x24\x63\xa6\x5d\x7e\x7f\xc0\x03\x0b\xba\x76\x9c\xa3\x44\xbf\xa9\xac\x82\x3f\x58\xcb\x5c\xee\x8a\x5f\xc0\xca\x37\x22\x8d\xe5\xa4\xd9\x3e\x0e\xcf\x7f\x10\x82\x16\x59\xa2\x26\x1f\x7e\xf1\x59\x6e\xda\x4e\x41\x1c\xf3\xc9\x66\x9d\x81\xde\x74\x54\x7c\xe4\xbf\x83\x3e\xb4\x32\xf3\x85\xce\x90\x38\xfe\x84\x8a\x8c\x96\xda\x7f\x01\xfd\x95\xbe\xa0\x6d\x1d\x74\x7c\x8a\xe7\x36\x49\x5b\xba\x22\x85\xbe\x5c\x32\xaf\xea\x44\x95\x20\xcf\xe8\xe1\xce\x25\xf9\x07\x7e\xd0\xec\x0f\x65\x98\xa9\xb8\xf7\x38\x6f\x15\x35\x81\x70\xcc\xef\xc3\xd5\xff\xb0\x09\x28\x81\x54\xde\x87\x7c\x24\x09\xae\x5f\xd8\xfe\xf0\x09\x3f\x1c\x36\xb3\xa8\xf5\x47\x43\x2c\xd0\xf6\x2c\x40\x33\x24\x2a\xd9\x92\x1a\x8f\x11\xc0\x0f\x36\x6d\xa9\x39\x69\x30\xa8\x0c\x99\x7d\xf4\x29\xa4\xf5\xf4\xe4\x5c\x7a\x6d\x7e\x02\xaf\x03\x31\x86\x75\x7c\x73\xcb\xe6\x4d\x2d\x4e\x78\xea\xaf\xe2\x75\x39\x52\x80\x35\xf2\xcf\xcf\x8e\xaf\x0a\x42\xbd\x25\xf8\x8b\x2f\xc6\x9e\x42\x66\x8f\xae\x66\x77\xc9\xac\x90\x91\xd9\xd1\x5a\x41\xf3\xac\xe6\x5d\x90\xa0\x22\x98\x73\xdc\xf2\x54\x25\x6c\xca\x44\x9e\xd4\xc1\x7d\x54\x35\xba\xe4"}, -{{0xbd,0x85,0x23,0xed,0xa8,0x99,0xb9,0x84,0x23,0x0e,0x32,0x88,0x75,0xb9,0x67,0x2e,0xdc,0x9f,0xcd,0x24,0xea,0x5c,0xc1,0x2d,0x7b,0x57,0x2d,0xa4,0xbe,0x01,0xfb,0x7b,},{0x02,0xb7,0x34,0xeb,0xbe,0x88,0xc1,0x3b,0xfa,0x95,0xa5,0xd9,0x64,0xfc,0x7e,0xf9,0xd3,0x95,0xbd,0x63,0x03,0xf0,0x65,0xdc,0x4e,0xe1,0x7b,0x3a,0xc1,0x54,0x8b,0x7b,},{0xfc,0xfc,0xdb,0x08,0x8d,0xcb,0xd0,0xa5,0x1b,0xd3,0x01,0xe3,0xe1,0x56,0x16,0x71,0x93,0x5d,0x8b,0x6f,0x71,0x9c,0x5d,0x92,0x69,0x06,0x40,0xd3,0xc9,0x1e,0x77,0x5b,0xf4,0x05,0x41,0x32,0xef,0xc0,0x5a,0x21,0x22,0xfc,0x20,0x9d,0xb3,0xc3,0x34,0x32,0x33,0xff,0x8a,0xec,0xeb,0xd5,0x2d,0xaa,0x2b,0x3b,0x21,0xee,0xb1,0x5f,0xd1,0x02,},"\x16\xc2\x16\xc9\xbe\x9f\x0d\x4b\x11\x54\x10\xbd\xfd\x15\x93\xc8\xe2\x62\x22\x1a\xb9\x7a\x2a\x39\x5a\x12\x19\x8f\x95\xc3\x02\x05\xb0\x89\x62\xd4\x89\x31\x18\xba\x9f\xf9\x9a\xb1\xc7\xa6\xe1\xf2\xf1\x75\x19\x10\x70\xac\x94\x53\x27\xad\x6c\x47\x0b\xab\xf7\x92\x8b\x07\xdd\x78\x8c\x85\xb6\x4b\x71\x2e\x0a\xae\x6c\x0e\xa2\x02\x81\xe4\x2f\xd5\x61\xe8\x3e\x3f\xba\xc6\x7f\x14\x00\x0e\xe5\x6d\x98\x1d\x2a\x2f\x0b\x9c\xa0\x0a\x9e\xa4\x7c\xa2\xf6\xfc\x8d\xca\x10\x35\xfc\xeb\x14\x2c\x3f\x26\xf2\x0e\x3c\x73\x22\x07\xff\xff\x11\xb7\x96\x95\xbd\xaf\xa4\x15\x21\x4a\x44\x99\x30\x23\x26\x60\x5c\xf0\xb8\xc8\x2f\x2b\x11\x39\x2e\xcc\x90\xcd\x74\xa7\xb4\x11\xb6\xd9\x07\xa3\xd5\xc1\x30\xc8\x79\xb7\xcf\x88\x0f\x22\xbb\xd7\xf0\xe9\x59\x33\x71\x8e\x96\xd7\xd1\x6c\xae\xa9\xf2\xc3\x9e\x89\xb1\x3c\xd5\x22\x66\x27\x36\x04\xa9\x6b\x51\xd6\xe3\x4f\x70\x67\x35\xdd\xd9\xfc\xa4\x4d\x09\xcd\x86\xbb\x72\x17\x60\x0e\x0d\x34\xd4\x16\xac\x24\x9f\x2e\x41\xbd\x0f\x4a\xbc\xbd\x25\x80\xad\xae\x21\xd7\xeb\xa5\xfa\x44\xf3\x9d\x78\x0f\x17\xeb\x85\xcc\xbe\xf5\x8f\xef\x90\x3a\x28\x0d\x95\xf8\xf3\x21\x07\x89\xfa\x12\xe1\x20\xe2\x1b\x6e\x8c\xad\x91\x78\x35\xbb\xdc\xc3\xb0\x7e\x84\x69\x39\x54\xe2\x3a\x94\xf9\x9f\x93\x7d\xdb\x0d\x4a\x18\xd4\x2c\x3e\xa8\xfc\xa7\xd1\xea\x6e\xd5\x3a\x00\x24\x6f\x99\xea\x52\x0e\x64\x05\xbd\x2a\xa5\x49\xb0\x6e\x7d\xa7\x22\xc1\xba\x74\xaa\x1c\x13\x6e\x8e\xa5\x8b\xaa\xf8\xd3\x76\x58\x69\x3f\x3e\x0b\x44\xf6\x31\xdd\x6d\x08\xff\xdf\x4f\x09\x18\x9d\x30\x35\xa3\xf0\x34\x68\xe2\x96\x96\xef\x05\xe0\x2c\xc1\xaa\xbf\xec\xbd\xa2\x30\x1b\x54\x0c\xb0\xeb\x0a\x75\xbc\xce\x73\xdb\x92\x73\xa9\x16\x1a\x98\xad\x89\x8f\xcd\x65\x79\xfb\x7e\x4b\x32\x79\x54\x4f\x2e\x0b\xd7\x74\xdd\x1a\x81\x57\xda\xa8\x8a\x70\x32\x11\x67\x70\x3c\x60\xa6\x08\xa4\xb5\x42\x16\x59\x03\x75\xe5\x97\xfe\x21\xae\xa9\x7b\x52\x18\x5d\x0e\x37\xa5\x3b\x63\x88\xa7\x07\xa2\xbc\x24\xac\xf9\x44\x25\xf8\x4f\x3d\x56\xbc\x9f\x7e\xe7\x41\x2a\x9e\x18\x33\xad\x55\xb7\xea\xe6\xda\x58\x16\x98\x16\x63\x83\xa2\xeb\xa8\xb6\xf5\x39\x20\xf5\x17\xa5\xc8\x0b\xd3\xe0\x3f\xaa\xd4\x08\x7e\x3e\xe8\xfe\xc9\xa7\x9a\x01\xc7\x79\x51\x21\x33\xd7\xb6\xe5\xf1\xde\xc7\x66\x30\x0d\xc4\x05\xcc\x21\xa8\xc5\x83\xfb\x73\xbc\x90\xcf\x24\x38\x5b\x08\x60\x49\xd3\xbf\x20\xc3\x00\x98\x3c\x0b\x35\x15\x38\xdc\xcb\x22\x7a\x14\xfa\xfd\x23\xac\x4b\x26\xbe\x81\xa2\xb1\x20\xcf\x21\x6f\xc5\x83\x54\xf9\xdc\xbf\x05\xf6\x63\x39\xad\x6d\xdc\x2c\xac\x14\x67\x7b\x90\xe2\x47\xeb\xb6\xc5\xc2\x29\x00\x7d\xc6\x0f\x37\x4a\x06\xd4\x04\xeb\x23\xeb\x1e\xc4\x99\x07\xc6\xe8\x81\x62\x9e\x18\x67\x26\x8c\xa6\xff\xfa\x59\xaa\x3c\xa8\xf6\xc2\x95\x16\x2b\x95\x36\xc2\xbe\x22\xbb\xe3\xb7\x23\x80\xef\x11\xb6\x1b\x35\x7a\x62\x53\x10\x0e\x30\xa5\x86\x81\x8b\xa0\x03\xfa\x3f\xfd\x1f\xc9\x19\x88\x1c\x05\x02\x2f\x94\x84\x85\x98\xf2\x17\xfe\xa2\x22\x50\x72\x20\xd1\x08\xa2\x8f\xc7\xbc\x39\xa8\xa1\x1c"}, -{{0x33,0xa8,0x5a,0xe1,0x50,0xbb,0xf5,0x52,0xf4,0x16,0x63,0xb2,0x15,0x21,0xc2,0x96,0xd2,0x46,0xdd,0x6c,0xf8,0x19,0x5d,0xf8,0x51,0xc6,0x95,0xbd,0x15,0xf4,0xa5,0x02,},{0xc8,0xc9,0xc4,0x25,0x21,0x00,0x8d,0x5e,0xff,0xf5,0x76,0xc7,0xe4,0xa5,0x60,0x83,0xce,0xd9,0xa9,0x28,0xda,0x6f,0xd5,0xcf,0x93,0xfd,0xa5,0x72,0xa5,0xa2,0xd0,0xc0,},{0xbb,0xe4,0xcd,0x63,0x67,0x6e,0x26,0xd6,0x75,0xa1,0x91,0x15,0x1d,0x30,0xdb,0x72,0xb5,0xb8,0x4d,0x46,0x1e,0xec,0x65,0x64,0xaf,0x86,0x7a,0xb4,0x1b,0xae,0x99,0x31,0x14,0x78,0x85,0x51,0x9e,0xc9,0xd7,0xe6,0xc8,0x18,0x74,0x3c,0x8e,0xf6,0xd5,0x16,0x7b,0x35,0xb4,0x21,0x36,0x3c,0x09,0xb3,0x57,0x36,0x7f,0xe8,0xde,0x44,0x3a,0x06,},"\x93\x7e\x05\xf2\xf1\xfd\xbd\x41\x73\x15\x53\xe7\x7c\xf1\x81\xb5\x07\x97\x58\x94\x0a\xee\x8e\x92\x62\x3f\xb1\xd5\xf0\x71\x28\xb7\xd7\xf1\x7e\x48\x42\x70\x7a\x56\x2c\x45\xba\x69\x26\x4c\x0f\x73\x0a\x82\x1c\x7d\xb6\xbf\x82\x99\x0d\xc6\x51\x26\x9b\x29\x6c\x33\x51\x79\x11\x30\x53\xd6\xf8\x5b\xb0\x96\xb2\x91\x11\x65\xfa\x39\x00\xcb\x10\x24\x16\x48\x7b\xa8\x07\x86\x79\xc6\xb3\x36\xdf\xf3\x87\x63\xc0\x8d\xcd\x20\xfa\x66\xdd\xa4\x5c\x57\x5d\xf1\x50\xd8\x51\x16\x5a\x48\x04\x97\x38\x30\xf4\x36\xdf\x60\xb8\x13\x19\xf9\xcf\xb5\x64\xc0\x65\x28\x96\xed\x5f\x18\x49\xcb\x33\x54\xf5\x0f\x00\x12\xf2\x86\xe8\xa3\x0c\x21\x35\x28\x69\x34\x74\x00\x4e\x85\x04\x01\x2b\x94\x55\x60\xc0\x74\xa6\xa1\x63\x43\x2c\xf4\xac\x4b\xa7\x17\x5c\xf2\x60\x05\xdb\x71\x99\xee\x96\xd8\x93\xcd\x1a\xad\x3f\xdf\x5d\x57\x46\x0e\xf0\x2d\xda\x6d\x3a\x14\x08\x25\x19\x6f\x3f\x8e\x2f\x37\xda\x36\xb6\xfd\xad\x18\x4f\x27\x40\xf1\x16\xde\x75\x8a\x92\x91\x70\x30\xc5\xfb\x80\xf0\x26\x24\x96\xd2\xdf\x93\xc7\xe2\x76\xf2\x5d\xa7\xdb\xed\x8e\xb8\xdd\x4c\x56\x3a\xba\x55\xb8\x2a\xf6\xba\x3a\x70\xca\x5f\x85\x8b\x44\xa0\x33\xcf\xb7\x95\x60\x4d\xde\xe7\x46\xe7\xc8\xae\x79\xd2\x72\xfb\x9a\x23\x41\xa2\xa2\x02\xdf\x5e\xac\x08\xde\x75\xad\x80\xc6\x58\x0d\x92\xb1\x69\xf2\xe1\x31\x88\x57\xb1\xb1\x42\x1c\x30\xf3\xdd\x46\x10\x93\xde\x2d\x34\x5e\xde\x74\x04\xb7\x2a\x45\x0d\xe0\x7b\x16\xee\xe6\x8c\xe6\x28\x87\xb6\xea\xa4\x36\xee\xe6\x84\xbe\x75\xce\x0e\x1f\x96\x26\x3e\x8d\x87\x36\xf9\xba\x00\x0d\x88\xe9\xe5\x86\x0f\x32\x8a\xe1\xe2\xdc\x73\x09\x9d\x32\xfc\xeb\x1b\xd2\xc0\x12\x36\x98\xa4\x9b\xea\xd1\x90\xa0\x0e\xc9\xa6\xf8\x71\x33\xed\xdd\x45\x31\x6f\x65\xeb\x0d\x32\x9b\x07\xb9\xa6\x6b\xb9\xfe\x42\x58\x8b\xf7\xb8\xd0\x6e\xfe\xc1\x98\x6b\x82\xa0\x81\xed\x3f\x68\x02\xe9\xbe\x73\x46\x47\x84\x55\x9a\x4f\x2c\x09\x7b\xa1\x4b\x0b\xfd\x5d\x7e\x0a\xff\x65\xcb\x69\xab\xd0\x3f\x86\x16\xcd\x7e\xdf\x7e\xc3\x68\x21\x9e\xdc\xf8\x93\xe9\xee\x71\xda\xd9\xf1\x8d\x79\xe5\x68\x26\x5d\xdc\x67\x16\x22\x32\x13\x23\x5b\xb9\x28\xe9\x08\xde\xa8\x27\x78\x4c\xd1\xaf\x39\x6d\x59\x0c\x81\xf4\xea\xcd\xfc\xf8\x9c\x5c\xac\x96\xfa\x05\x00\x64\xa2\x28\x41\xea\x71\x5f\x8c\x89\xd6\xd5\xaf\xbf\x59\x7a\x4d\x00\x5d\xbc\x6b\x13\x85\x6d\x33\x5b\x42\xa9\xa8\x2e\xdc\xb9\x49\x83\x5c\xca\x20\xb0\xa2\x3d\xe5\x1c\xc3\xae\xc3\x55\x66\xef\xf0\xc5\xae\x1a\xb3\x75\x13\x20\xd2\xc3\x10\x49\x52\x38\xed\xa3\x83\xc3\x8a\x41\x63\x15\x2b\x88\x15\x69\x0b\x8f\xf0\x15\x03\x5d\x1d\x00\xea\x4a\x0d\x6c\xaf\x32\x4b\xb7\x1a\x66\x4a\x1b\xed\x31\x48\x07\x84\xa6\x8f\x43\x8c\xaa\x35\x9e\x8d\x26\x73\xc8\x57\xd4\xb8\xc0\xb6\xc6\x95\x84\x7b\x86\x80\x0e\xa3\xd7\x34\xb5\xec\xc4\xd5\x2b\x50\x7a\xc6\x9b\x3a\x67\x78\x91\x60\x16\xeb\xc2\x31\x5f\x44\xc9\x0b\xf0\xc3\xe7\xda\xe0\x1d\x49\xcb\xc3\x03\x40\x2b\xbc\x63\x4a\xe1\x19\x1f\x3f\x6f\xd6\x3d\x30\x3b\x0c\x0b\xe0\x33\xa4\x7b\x90\xf8\xd3\xa7\x7f\x0a\x44"}, -{{0xba,0x9e,0x68,0x62,0x04,0x97,0x5c,0x3b,0xde,0xd4,0xc1,0xe9,0xf7,0x4c,0x7e,0x4c,0x7a,0x7e,0x3c,0x99,0x81,0xd0,0x1b,0xfc,0xa0,0xad,0x01,0x15,0xc3,0xf0,0xf5,0xc3,},{0x49,0x90,0xfc,0xe6,0x95,0x2e,0x8b,0x7d,0x0a,0xfc,0xf4,0xbf,0x9d,0xba,0x9b,0xce,0x1b,0xc4,0x81,0x5e,0x37,0x51,0x1d,0xa7,0xc2,0xad,0x48,0x92,0x58,0x1d,0xe0,0x3a,},{0xc7,0xd2,0x3a,0x58,0xe2,0xfb,0x2a,0x8d,0x4b,0x8e,0xd1,0xe9,0xea,0xe9,0x1e,0x11,0x29,0xc2,0xaf,0x8b,0xd0,0x5f,0x0b,0xd5,0x72,0xab,0xeb,0xbe,0x0f,0x30,0x82,0x59,0x25,0xf0,0xdf,0x71,0xcf,0xb7,0x21,0x8c,0x68,0x6e,0x55,0x48,0xd9,0x42,0x77,0x10,0xa6,0x90,0x36,0x6b,0xa8,0x55,0x41,0xc7,0x91,0x01,0xa5,0x8a,0x10,0xe8,0xaf,0x0a,},"\x46\xbb\x48\x95\x2a\xe5\x8f\x2b\xf5\x8f\x5b\xe8\xdf\x4f\x31\x6b\x50\xf3\x63\xec\x84\xee\xd8\xf8\x2f\xf4\xc0\x4b\x06\x92\xd0\x3a\xef\x26\xe8\xe1\xe6\xc9\x54\x9a\x22\x47\xd5\x40\xa6\xe2\x2f\xeb\x11\xe5\x7f\x4b\x80\x8a\x20\x97\xe8\xa7\xb6\xb3\xb7\xaf\x37\x69\xe6\xd8\x1d\x64\x88\x6e\x69\x62\x37\x2f\x4f\x39\xe4\x9c\xd4\x6c\x1b\x5f\x73\x5f\x38\x0f\x7c\x27\x7d\x09\x97\x76\xed\x1a\xea\xa5\x7a\x35\x9c\x0a\xa8\xc7\x2f\x40\xeb\x91\xa1\xbf\x07\xea\x15\x7f\x5d\xdb\x30\x40\x9d\x6e\x3a\xf9\x89\x90\xce\x7f\x30\xaf\xfd\xac\x5e\x22\x01\x06\x46\xdc\xa9\x6a\x54\x00\x60\xfc\x90\x8a\x31\x25\xb0\x00\xad\x1e\xd3\xa0\xf2\x55\xcd\x34\xf1\x5d\x7d\xd1\xfd\x68\x1c\x3c\x35\xa1\xcd\x65\x20\x56\xec\xc5\x26\x4d\x39\xaa\xf7\x2a\x9b\xb8\x3a\x55\x1c\xc9\x34\x88\x7a\xe1\x07\xaf\xdf\xef\x06\x32\x17\x27\x0d\x95\x96\x89\x14\x18\xbd\x46\x1b\xba\x63\xde\x65\xbe\x06\x7b\x1b\x78\x64\xfe\x46\x48\x4c\x7c\x9e\x96\x34\x9a\x7c\x03\xa8\x0f\xa0\x55\x05\x0a\xa1\x8a\xce\x2a\x44\xb4\xa0\x3c\x94\x78\x24\x17\x2b\x30\xe2\x10\x11\x15\x94\x43\xca\x3c\xef\xaf\x69\x6a\x7a\xa8\xf9\x80\x11\x26\x0c\x94\x36\xbf\x48\x99\x1f\x41\xd4\xd5\x07\xb9\x6c\xe7\x32\x3e\x53\x1a\xdc\xf6\x63\x47\xc5\x5c\x88\x55\x67\x3a\x9f\x2e\xc8\x9b\x5c\x80\x24\x46\x06\x17\xec\x72\x71\x77\x3b\x36\xd6\x4f\xc1\x4e\xb5\xd8\x26\x52\xc5\x3a\x30\x31\x45\x72\x27\x09\x3d\x11\x8f\xd8\xeb\x93\x84\xe8\x02\x29\x04\x1a\x96\xa6\x49\x34\x50\xf9\x7e\x67\x36\x26\x3a\xbf\x1e\xcd\x9e\x9f\xb9\xa4\xf0\xf6\xd6\x67\xfa\x82\x41\x51\x48\x5e\xdc\x37\xb3\x4a\xcf\x3d\x8c\x35\xf9\xc1\xbe\x48\xb5\xe9\x6a\x12\xaf\x8e\x2d\x35\xc2\x3a\x03\x58\x0f\x21\x1d\xa6\x31\x6b\x34\xc5\x6b\xee\x87\x2d\x47\x64\x1b\xca\x77\xda\x64\x0f\xdb\xba\xd5\xa9\xad\x8a\xb9\xdc\x79\x57\x91\x3d\xa7\x34\xad\x37\x49\x2b\xa4\xde\x8c\xf1\x36\xcc\xcd\xeb\x6b\xa3\xf1\xbd\x3f\x00\x3b\xe7\x26\x3c\x4f\x2a\x40\xc3\x3f\x24\xca\x33\x39\x59\x6e\x6c\x34\x28\x33\x81\x00\xeb\xcc\x07\x22\xd4\xf5\x0d\x30\xb3\x3b\x91\x2d\x4e\x7c\x1a\x9f\xe6\x5f\x66\x58\xa6\xf2\x39\x14\x0a\x62\xc3\x26\x1e\x10\x39\x2e\xd1\x93\x0a\xa9\x17\x65\x2d\x3b\xd2\xbe\x4e\x8a\x08\xab\x97\xe1\x45\xb9\x20\xab\xb3\x1e\xe4\xbc\xd5\xa0\xd7\x1f\x63\x81\x80\xf6\x1c\x24\x58\x23\xa3\x99\xa7\x34\xa4\xdc\xde\x09\x97\x88\x02\x45\xed\x71\xeb\x9b\xc6\x5e\x3c\x6f\xc9\x5a\xb9\x20\xb8\x02\x4c\x17\xd4\x4c\xed\x00\x37\xd0\x4a\x13\x3c\x26\x41\x78\x2f\x1d\x62\x2d\xf4\x52\x69\xb4\x91\xd3\xfa\x2a\x12\x27\x57\x9e\xaa\x38\x6d\xe3\xe7\xde\x7b\xc4\x55\xc6\xa1\x54\xee\xe5\x72\x7f\xff\x04\x37\xa2\x00\x76\xc5\xc3\xb0\x57\x7c\xac\x5b\x4b\x69\x34\xe2\x69\x38\x02\x22\x46\x1a\x60\xf9\x54\xe4\x89\x79\xc0\x67\x12\x17\xf1\x6f\x70\x27\x98\x30\x34\x12\x10\x93\x18\x6c\x78\x70\x5f\xc2\x7d\xc9\x2e\x2e\xda\x41\x16\xa6\xbf\x7d\x23\xe0\x54\x8d\x62\xb6\x7b\x25\xc4\x1e\xd0\x61\x92\xbc\x26\xef\x13\x97\xbf\x16\x01\xf3\xa6\xe2\xa0\xe7\xf6\x61\xfb\x05\x05\xee\x38\x2f\x27\xae\xc2\x80\x5a\x3e\x21\x17"}, -{{0x59,0x07,0xa8,0xc0,0x84,0x04,0x38,0x75,0x23,0x8e,0xdb,0xdc,0xb7,0x83,0x2f,0xbb,0xa4,0xc0,0x5e,0xa3,0xc5,0xf8,0x8a,0x96,0xf1,0xfb,0xf9,0x50,0x40,0x1e,0xc1,0x64,},{0xe2,0xf4,0x95,0x09,0xd1,0x00,0x7f,0x61,0x8e,0xfe,0x4f,0x1f,0xd6,0x7e,0xaa,0x6e,0x2a,0xb1,0x8a,0xfb,0x2d,0xec,0xce,0xd5,0xa0,0xb2,0xba,0x83,0x63,0x78,0x92,0x60,},{0x8c,0x49,0x12,0xc0,0xf8,0x85,0xd7,0x6c,0x91,0x40,0x59,0x50,0x53,0x73,0xa6,0x4b,0xdd,0xd6,0x7d,0xd4,0x68,0x36,0x9a,0xb9,0x18,0xf2,0x3e,0xa2,0x8e,0x04,0xc1,0x91,0x77,0xa8,0xd4,0x61,0x14,0x4f,0x0a,0x8b,0x51,0xd2,0x15,0x17,0x6c,0xb0,0x8b,0xd6,0x53,0x01,0xc3,0xc4,0x62,0x37,0xb6,0x1b,0xb1,0x49,0x8c,0xa7,0x9d,0x4b,0xe7,0x0e,},"\x43\x3b\x24\x78\xe1\x8f\xad\x5c\xb8\x10\x67\x06\x1d\x22\x55\x28\x22\x97\x78\x30\x78\x85\x47\x54\x60\xfb\xe3\x13\x7a\x5b\x44\x02\x48\x94\xdd\xbe\x56\xfa\x6e\xd0\x21\x49\x6f\x07\x86\xe4\x2b\xc6\xc2\xd2\x79\x7e\xa0\xa6\xbf\x35\x5e\x88\x11\x5f\xaa\x55\xcd\x92\xed\x42\x13\x3d\x9d\xcd\xa6\xb9\xeb\xf6\x3c\xe4\xa9\x94\xd1\xa8\x2d\x2a\x49\x26\x75\x58\xbe\x54\x18\x2a\x6f\x85\x11\x2b\xd1\x2b\x24\x7a\xda\xcf\x14\x05\xfc\x7e\xc7\xa0\x15\xd4\x3a\xb4\x0b\x82\xc6\x77\xf7\xf8\x5a\x0e\x48\x19\x7c\x5b\x96\x57\x61\x99\xf4\xc3\x34\x3f\xf7\x65\x4d\x52\x3a\x30\xc4\x3a\x05\x4c\x3e\x46\x44\x51\x27\x80\x34\xb7\xf1\x96\xc3\x66\x76\x8c\x62\x8a\xf9\x4f\xc0\xcc\xfc\x9a\x29\x55\xf9\xd3\x23\x38\xb9\x44\x78\x0f\x8e\x32\x70\x85\xb1\x03\x78\x18\x68\xe4\xfb\x79\xd5\x61\x22\xd7\xf3\xf5\xab\x30\x9e\x5d\x63\x4a\xdd\x15\xda\x38\x2c\x0d\x23\x58\xe6\x47\x18\x2b\xe4\xde\x6e\x9a\x9e\x43\xe6\xa3\xa3\xb8\x21\x5b\x20\x4d\x95\x07\x61\x0d\x46\x16\x21\x00\x0f\xb1\x89\x37\x07\xaf\x7d\x25\x95\xbf\xef\x8a\x8c\x5c\x5c\xd0\x8f\x30\x9a\x5f\xb5\x5e\x45\x51\x9a\xea\x9b\x84\x74\x8c\xa5\xc6\x72\xbf\xec\xd3\x0d\x25\x65\x12\x34\xa3\xcc\x31\x9b\x43\xdf\xce\xfc\x1a\x07\xb5\x5b\x4a\xca\x71\x4c\x2e\x7e\xf9\x63\x8f\xe7\x88\x4a\x77\xb2\x22\x53\xa0\x1a\x22\x29\x50\x0e\x9c\xe1\x0f\xda\x73\xa8\x43\xc1\x9c\xc0\x96\x26\xd2\x45\x6c\x22\xa9\xc9\x01\x88\x1d\x52\x1f\x4b\x15\xd2\xf6\x13\xcb\x46\x9d\x30\x4d\x57\x92\x23\xbc\x5f\xf7\x38\x04\xdf\x63\x71\x51\x7e\xba\xa5\xb6\x77\xea\x91\x0f\xf1\xa0\x2a\x26\xfa\xfe\x48\xfe\xf4\x69\xed\x79\x9b\xed\x6d\x56\xce\x96\x18\x34\xa2\xed\xc2\xe2\x3c\x0d\x94\x26\xec\xcd\xcc\x93\x4f\x4c\x22\x0e\x37\x81\x5f\x7c\x33\x4b\x73\x83\x60\x7d\x43\x05\x20\x94\x6a\x88\x1a\x08\x32\x5b\x41\x64\x97\x9d\x5e\x82\xcd\x81\x34\xd7\x8c\xec\x48\x61\xc0\x19\xf6\xde\x30\x1c\x1b\x9a\xec\x52\xbb\x98\x20\x33\xfb\x79\xb2\xe9\x73\x1b\xab\x29\x68\xbc\x3f\x93\xfa\x56\x04\xb8\x93\xc6\x02\x8c\x20\x4c\x36\xbb\x8c\x6b\x07\x4b\xe2\x8c\x96\x4d\x28\x49\xb5\xbb\x19\xd7\xe0\xba\x24\xe2\x2a\x20\x4d\x4f\xda\x83\xb1\x01\x31\xd3\x83\xf1\x0b\x13\x6b\xd0\xdb\xa3\x9e\xc2\x6a\xf3\x0e\x3f\xfb\x4d\xbc\x0c\x92\x1f\x0c\xc9\x91\x07\x15\xd5\x1c\x81\xfe\x4c\x62\x95\x0e\x85\x55\x49\xa1\x7c\xd7\x3a\x09\xac\x91\xe0\x6d\x46\x15\x18\x37\x6d\x0f\xcf\xa1\x23\xdf\x0a\x83\x71\x03\x45\x8d\x9c\xe2\x21\x80\x8d\x1f\x9e\xf2\xed\xc5\xcd\x2e\x68\x23\x14\x5b\x52\x48\x94\xea\x48\x52\x6d\x98\x5e\xef\xd3\xf6\x06\x79\x39\x95\x48\xe1\xed\xea\xdb\x53\x95\xb4\x3d\x87\x04\x4b\x2b\xfe\x7c\x60\x37\x02\x9b\x34\x6a\x40\x22\x27\xea\xb8\x1f\x33\x3e\x10\xe7\x7f\x1d\xbc\x06\xa2\x11\xd4\x3b\x82\x55\x86\x76\xc2\xdc\xff\x90\x82\xb1\xdd\x53\x36\x8d\xf0\x02\xde\x13\x29\xaf\x30\x00\xb1\x71\xa6\x91\x43\x89\xbb\x80\xec\x0c\x9f\x3e\x41\x2a\x44\x1b\x80\x0a\xfc\xeb\x04\x86\x70\x9a\xda\xc6\x6c\xaf\xee\xf2\x48\x83\x93\x31\xf5\xd8\x92\x19\x7e\x25\x42\x0f\x1e\x37\xd7\xc0\x24\x7f\x66\x9f\x5f\xcb\xf0"}, -{{0x60,0x20,0xae,0x27,0x3e,0x0e,0x05,0x37,0xba,0xc8,0x81,0xd7,0x54,0x9d,0x92,0x3e,0xb1,0xcc,0x20,0x0d,0x49,0xca,0x65,0xd4,0xbe,0x63,0x5e,0x39,0x17,0x3d,0xf9,0xda,},{0xda,0xaf,0x0e,0x69,0x9a,0x12,0xa9,0x2c,0x16,0xe0,0xde,0xd3,0xeb,0x34,0x50,0xa3,0x63,0x11,0x82,0x45,0x77,0xe3,0x61,0xf0,0x56,0x96,0x60,0x33,0x00,0x16,0x62,0x97,},{0xb1,0xba,0x88,0xfe,0xd7,0xe5,0xf4,0xb7,0x57,0xf3,0xfa,0x4d,0x1e,0xd9,0xb1,0x9e,0x49,0x8e,0x5d,0x2f,0x5e,0x6c,0xd4,0x6e,0x42,0x6f,0xe8,0xf0,0x39,0x88,0x2f,0x1b,0xe7,0x7a,0xc9,0xe5,0xa9,0x26,0x5c,0xbf,0x7e,0x3c,0xd2,0xa9,0xe9,0x92,0x6c,0x18,0x19,0x91,0x43,0x79,0x8d,0xa5,0xbe,0x47,0xa4,0x08,0x64,0x40,0x49,0x6b,0xa0,0x0f,},"\x6a\x80\x11\xde\x09\xaa\xc0\x0d\xb1\x6f\xf7\xe5\x5c\x2d\xe6\x7d\x8c\x98\x83\xfc\xb2\x04\x0d\xed\xbc\x1e\x32\x1c\xab\xa7\xbb\x03\x69\x71\x53\x01\x76\xd1\xdb\xba\xa9\x27\x52\x0b\xdf\xcc\xbe\xd8\x84\x01\x26\x04\x3e\xdc\x44\xcb\xb7\xfa\x35\x28\x68\x0e\x5f\x1b\x56\x64\x95\x1d\xc9\x01\x09\xae\xa4\xb9\xc3\x36\xca\x04\x3d\x82\x21\xa4\xc8\xd2\x01\x16\x56\xbf\x94\x4e\xfd\x36\xba\x0a\x10\xa4\xb3\x89\x19\x60\x55\x75\x0b\x0e\x38\x8f\xb5\x28\x70\xbb\xec\x8c\x55\x19\x81\x31\x44\x39\x45\xc0\x9f\x3a\xac\xe3\xe6\x91\x50\x14\x37\x40\x73\x26\x6f\x34\x88\x74\x42\xd7\x4f\x46\x8f\x8d\x70\x78\xbb\xa0\xbd\x81\x4c\xd6\xdd\x42\x3c\x97\xb5\x69\x05\x58\x7b\x15\x2d\x1f\xcf\xba\x0e\xb9\xfd\xe2\x11\x26\x91\xda\xfa\xf4\xf9\x21\x56\x2f\x24\x1b\x62\x84\x10\x01\x83\x4f\x6c\xe3\x66\x85\xf8\x2a\x8f\xaa\x3b\x7a\xfa\xd7\x3a\x5e\x59\xbf\x5f\x9e\x71\x3e\x59\x16\x3f\x31\xdb\xe6\x96\x11\x8a\xf3\x35\x06\xd2\xff\xea\x3d\x9c\x15\x56\xfb\x15\x2f\xd2\xb3\x21\xc3\x17\x57\xd0\xc3\xc0\xf6\x0e\xe1\x13\xed\xac\x02\xd6\x7e\xfb\xb3\x03\xdc\xe6\xfa\x88\xf7\xb9\x74\x6c\xa1\x10\xe6\xa0\xcd\x09\x9c\x08\x31\xf5\x3c\x55\xc2\x8b\x6c\x82\xaf\x44\x64\x56\xb8\x42\xb2\xc9\x50\xa5\x53\xee\x2c\x76\x5e\x97\x29\xe6\xb0\xc5\x46\xbf\xc2\x6b\xd6\xd4\x2d\x06\xb2\xed\x5d\x4c\x8c\xbb\xc7\x5f\x2a\x3a\xd8\x12\x93\x95\x79\x3d\x97\x9c\x03\x1f\xce\x7e\x20\xb3\x8b\xd8\x9c\x9b\x62\x47\x48\xb2\x01\x34\x23\xce\xba\xda\x02\xcd\xe2\x05\x2d\xa5\x66\x4c\x6c\x64\x26\xcb\xfc\x88\xf8\x4f\xf6\x02\xe2\xe2\x0d\xf9\x67\x8f\xbb\xa5\x77\xa4\xc1\x34\x51\x7e\xe0\x50\x68\x11\x51\x58\x0f\x7c\x5c\x97\x87\xb9\x6e\x55\xc4\x07\x5a\x26\xf4\xf8\xcc\xff\xbb\xb6\xea\x18\xde\x1b\x2c\xc8\xc4\x49\x6b\x16\x04\x27\x70\xb7\xec\x6e\xb5\x42\x9e\x7a\xc1\x89\x12\x32\xaa\x4e\x47\x46\x7f\x4e\x9a\x98\x5d\x80\x54\x7e\xcc\x4c\x6f\xd9\xf5\x97\x63\xed\xe9\x16\x71\xf2\xaa\x57\x36\xa5\xd1\x48\xe3\xa8\xff\xc8\x8e\x61\x25\x3a\x85\xb0\x95\x36\x54\x95\x8e\xb2\xd6\x94\x01\xcb\xea\xe7\x75\xf8\xcb\x8c\x3c\xa4\x2d\x21\x69\x3e\xbe\x29\x88\x38\xdf\x94\xc1\xd7\x7b\x12\x6a\x12\x05\xcc\x47\xd5\x0d\x53\x67\xb6\xf2\x76\xec\x8d\xb6\xb9\x53\x24\xa3\x1e\x8f\xd2\xed\x2e\x43\x42\x0c\x4a\xd0\x2e\xa2\x77\xdd\x94\x8a\x55\x19\x3d\x0f\x0b\x4d\x1c\xf2\x83\x86\xc7\x25\x97\x5c\xe5\xc1\x2d\x2a\x6f\x35\x67\x3c\xc2\x2a\x06\x94\xcc\xa4\xda\xf6\xaf\xbf\xd3\x26\xd8\x8c\x18\x50\xf8\x34\xc4\x2f\xf0\xe2\x92\xba\x4f\x13\xe5\xef\x07\x74\xa5\x96\xd3\x39\x04\xc0\x26\x2d\x31\xdf\x2c\x58\x4a\x0a\x4f\x45\x3f\x6a\xe4\xa8\x8a\x27\x5f\x7d\xe7\x9c\x13\xae\x1a\x73\x11\x5b\xe0\x2f\x42\x5c\x6f\x17\x7a\x1e\xc4\x63\x9c\x42\xa7\x92\x80\x9a\x2b\x09\x19\xeb\xd3\x21\xe3\x16\x00\x1d\x5b\x2f\x84\x89\x4f\xce\xbd\x50\xa1\xdc\xf4\x4d\x70\x2b\x92\x45\x32\xfc\x0e\x4d\x3f\x9f\xf8\x48\x6c\x0e\xd1\x80\xee\xcc\x3e\x09\xe2\x27\x2a\x94\xdc\x7d\x24\xa4\xe8\x7a\x93\x1f\xe2\x49\x5c\xbf\x99\x2c\x0a\xae\x92\x01\xe0\x79\x62\x98\xf9\x36\x3d\xba\xc4\x75\xe8\xed"}, -{{0x93,0x2a,0x20,0x0e,0xce,0xe7,0x22,0x3f,0x24,0x14,0x62,0x83,0xa4,0x04,0x8c,0x67,0xa6,0xa2,0xd2,0xfc,0x4b,0xa0,0xf9,0x24,0x8b,0xdf,0xfd,0x82,0xc6,0xcc,0xe3,0xcb,},{0xec,0x9b,0xfb,0x7a,0x6d,0x04,0xe7,0x26,0xfc,0x1e,0xa0,0xc4,0x24,0x61,0x0d,0xcb,0x79,0x67,0xbf,0x15,0xd6,0xd6,0x62,0x68,0x58,0xd4,0x11,0x19,0x8d,0x40,0xe2,0x39,},{0xcd,0x1e,0x4b,0xdf,0x4a,0x3e,0x4a,0x31,0xd6,0x52,0x54,0x33,0x3c,0x8c,0xc4,0x08,0x7e,0x4c,0xc4,0x0b,0x02,0xe2,0xa3,0x47,0xd0,0x9a,0x3d,0xde,0x69,0x84,0x90,0xc0,0x87,0xd7,0x10,0x9a,0xd0,0x20,0x9c,0x53,0xe9,0x87,0x58,0x9c,0xbf,0x3c,0xe2,0x64,0x12,0xa2,0xb0,0x2c,0xb8,0xa3,0xbc,0x93,0xfe,0xc7,0x5a,0xb5,0xd2,0xc3,0x87,0x03,},"\xdf\x95\x32\x07\x04\x82\x13\xaf\xb8\xe2\xaf\x45\x2c\x88\x9a\x21\xca\x13\x6a\x68\xc9\x29\xbd\xc8\x24\xf9\xa8\x9a\xc5\x96\xdc\xb9\x00\x19\xa4\x6f\xb6\x82\xbc\xfd\x96\x2f\xcc\xb2\x7d\x00\xba\xf8\xec\xca\xf9\xd9\xa7\xd8\x18\x3c\xab\xd7\xdf\xa5\x06\xf7\xba\xfb\x49\x35\xab\x04\x59\x31\xff\x8f\xae\xb7\x16\x31\xf9\xed\x6b\xb8\xf8\x47\x3a\xd6\x29\x0d\x7c\xf5\x19\xdb\x31\x0a\x44\x42\xc4\x61\x11\x8f\x67\xd1\xa6\xd1\x03\xba\xe6\xf2\x69\x7c\x94\xb7\x42\x6d\x9e\x02\xe3\xcb\x95\x22\xfd\x0b\x44\xae\xf6\x00\xc9\x62\xfe\xff\x58\x73\xd9\x8c\x27\x90\x88\x7b\x8e\x88\xd1\x60\x82\x4f\x1b\xba\x22\x01\x76\x39\xf8\xdc\xe6\x8f\x74\x34\x80\xde\xea\x1f\x92\xaa\x1f\xd4\x13\x5d\xd0\x64\x57\xa6\x0f\x36\xb7\xd7\xf5\x17\xd4\x0c\x94\xc0\xdd\xdc\x2e\x46\x58\x47\xd9\x09\xb9\xf6\x82\x45\xff\x2b\x42\x1d\x59\x19\x00\x1a\xae\x5a\xef\x24\xe0\x2c\x00\x2d\xa9\x07\xe8\x60\x5f\x16\x0e\xa6\x09\x6b\x58\x0b\x75\xce\xa0\x22\xd4\x02\xf7\xf5\xfd\xc4\x64\xf8\x7f\x78\xc7\x90\x6a\x01\xe8\xe4\x8f\xb5\xb3\x51\x74\x61\x2b\x48\xac\x8b\xc7\x50\xe0\xf3\xae\xb0\xa1\x2f\x7d\xfc\x09\xb0\x84\x2c\x17\x80\xa5\xfd\x9c\x54\xaf\xb9\x39\x9b\x94\x08\xba\xac\xcd\xa2\x0a\xfb\xe3\xd6\x82\x24\x8d\x7b\xf1\xef\xde\xf4\x90\x5a\x31\x9b\x0f\xfb\x10\x8b\x75\x3b\x71\xcc\x97\xe9\xe2\x1e\xc9\xb3\xdd\x28\xce\xe0\x39\xd9\x41\x8a\x11\x35\xf0\xad\xd0\x92\xaa\x66\x31\x2e\xa2\x91\x33\x00\xd1\xcc\x89\x16\x52\x43\x02\xbd\x3d\x1b\x09\xe6\xb2\x9c\x68\x57\xcb\xdc\x56\xef\x4b\x3f\x35\xd8\xee\x67\x72\x08\xef\xfa\x84\x6f\xdb\x06\x6b\x05\xeb\x71\x7b\x4d\x45\x12\x0c\xab\x72\xa7\xdb\x7a\x7c\xa8\x46\xe8\x7b\x16\xb6\x90\x47\xeb\x76\xd8\xf1\x8d\xa8\xe1\x39\x9e\xc0\xa8\xc9\xc3\x28\xcb\xe6\x0e\x0b\xf4\x20\x44\xd2\xeb\xf2\x81\x8b\x3c\x04\x75\x88\x45\x2f\xcd\x2b\x3e\xfc\x1e\x10\x09\xae\x07\x68\x87\x27\xdb\x8f\xb6\xdf\x2a\x2f\xe7\x5d\x1c\xf2\x2f\x32\xba\xc0\x9c\x82\xa6\xa3\xd7\xee\xd7\xd0\x05\x08\xcb\xe5\xb7\x24\x60\xec\xfc\xdd\x3e\xe9\x11\xef\xe5\x89\x8d\xbd\x8e\x4c\xe8\x59\x13\x26\xdd\x15\x22\xf9\xd2\x55\xda\x86\x1b\xf9\xeb\x2a\x1d\x57\x25\xd7\xd5\xd4\x27\x34\x03\x41\x94\x5e\x7b\xca\x8c\xf2\xff\x8a\x99\x74\x50\x95\x3e\x77\xd2\x03\x68\x3e\x4b\x0d\xaf\xc3\x30\xe0\x56\x72\xd2\xec\xd1\x3a\x3f\x44\x2d\xf1\x37\x04\x4e\x0f\x55\x6f\xfb\xce\xff\xea\x26\xcb\xae\x26\xcb\xa6\xf2\x56\x8c\xf3\x9f\x90\x84\x89\xe1\xa9\x2e\x76\xaf\xbf\x29\x79\x95\xda\x4b\x2c\xb1\xab\xc9\xee\x1f\xe4\xdc\xa5\xaa\x83\x8b\x2f\xbd\xc1\x09\xe8\x9b\xef\x3c\xe5\xa3\x6e\x5b\x2f\x71\x2a\xc4\xc8\x89\x43\x82\x48\xfa\x5a\x21\x50\xca\xc6\xc9\x77\xb5\xe0\x54\x3f\x40\x10\xb7\x31\x47\x32\xfd\x18\xe7\xfd\x59\x82\xe8\x32\x76\x51\x9e\x78\x72\x5e\x5a\x5e\xeb\x86\xf4\x89\x20\x84\xae\x52\xda\x38\x49\xc2\x28\xc8\x09\xed\xbf\x69\xa2\xcc\x47\xc4\x78\xd1\x87\x19\xf1\x11\xd7\x37\x88\x7c\x7a\x2e\xb3\x25\x08\x98\xdb\x34\xe5\xe5\x07\x6f\xab\x9f\x4a\x9e\x6e\x19\x29\xa3\x48\x08\x36\xde\xa0\x7b\xa4\xd6\x3f\xce\xfc\xe5\x54\x34\x30\xa8"}, -{{0x5c,0x48,0x3e,0x83,0x7e,0xb0,0x1e,0xd5,0xa4,0xad,0x5d,0xb3,0x79,0x26,0x99,0x82,0x4d,0xf1,0x3e,0x57,0x6b,0xe9,0x67,0xd1,0x21,0x15,0xc8,0x5e,0x02,0x86,0xe6,0x28,},{0xfe,0x1a,0xa8,0xb0,0x69,0xda,0x56,0xe6,0x76,0xef,0x3a,0x57,0xd9,0xbb,0xa8,0x83,0x05,0xea,0x03,0x28,0x08,0xee,0x63,0x52,0x73,0xb3,0x7c,0x5c,0x63,0x5d,0xef,0x4e,},{0xc1,0x7c,0x2f,0xbf,0x8c,0x00,0xbc,0xea,0x30,0x35,0xbf,0x0a,0x62,0xd3,0x02,0x29,0xdb,0x74,0x2c,0xab,0x11,0x99,0x67,0x7c,0x7e,0xb4,0xeb,0x0e,0xf5,0xc7,0xb5,0x1a,0xd4,0x87,0xa4,0x97,0x1b,0x63,0x1e,0x79,0x4a,0x58,0xbb,0x08,0x23,0xcc,0x0f,0xe6,0x26,0x10,0xfd,0xa6,0xa9,0xe0,0x3f,0x8c,0x4c,0x33,0x81,0xcb,0x15,0x4c,0xef,0x0b,},"\x58\xd5\xe2\xcd\x89\x9b\xa9\x85\x37\x8b\x3e\xc3\x3e\x9a\x86\x98\x22\xb2\x3d\x5d\x89\x6a\x28\xf4\x24\xfc\xd6\xe4\xcc\x28\xb8\x0d\x4a\xaf\x2d\xe8\x04\x36\x7e\xfd\xf5\xe4\x23\xb1\x23\x4d\x82\x1d\x63\xac\x05\xea\xed\x12\xc7\x3e\x8e\x36\x08\xaf\x0d\xdc\xcc\x83\x86\xb7\xd8\x42\xb1\x2e\x60\xd3\x0c\xed\xe3\x25\x53\x94\x5e\x78\x29\xe9\xb2\x3f\x5c\xcc\x2e\x71\x03\xa0\x8f\x2c\xdd\x9e\x75\xa7\xb3\x6f\x5e\x63\x72\x0e\xf0\xd4\x9b\x25\x92\xbe\xf3\x74\x02\x68\xc8\x9c\x86\xa6\xcb\xdf\xe2\x01\xde\x0d\xb9\x98\x5c\xeb\x19\x39\x9c\x9a\x1d\x5b\xb0\x58\x6a\xf3\xc8\xcd\xf2\x71\x32\x99\xeb\x04\x43\xa5\x41\xa4\x73\x84\x60\x72\x43\xc5\x4a\x05\x91\x50\x58\x36\x7d\x3f\x2d\xb3\x80\xed\x31\x7a\x8c\x12\xc7\xa6\x3e\x80\x9c\x2e\x84\xd4\xac\xb9\xd9\xee\xf5\x4c\x6f\x5a\xf7\xab\x59\xcb\x91\x68\xb1\x06\x8f\x9d\x2c\xcd\x97\x8f\xe7\x21\xba\xd6\x8a\x66\x9f\xfe\xde\xa3\xe9\x2c\x76\xb3\x2e\x31\x66\x65\x8e\xe3\xbd\x0d\xeb\x1b\x08\x41\x94\xce\x35\xd9\xa7\x41\xc5\x7f\xc2\x24\x1e\x68\xef\xaa\x65\x32\x0b\x23\xa1\xdd\x19\xea\x8b\x7e\xc8\x1e\x76\xf1\xe9\x16\x3f\x95\x92\xee\xee\x5a\xf8\xec\xed\x02\x72\xf3\x35\x12\xd0\xd4\xca\x06\x7f\x05\x55\x1b\x26\x53\x96\xe1\x00\x14\x78\x3c\xac\xac\x79\x43\x7b\x19\x84\x2d\xe6\xab\x91\xb9\xd9\x23\xbb\xeb\x50\x33\x25\xbc\x54\x86\x9f\x66\x3e\x6e\xa4\xae\x68\x97\x70\x1b\xe7\xe1\x1d\x16\xcd\xfa\xe0\xee\xe8\x61\x86\x20\x00\xe7\xa4\x16\x07\x81\x54\x7e\x42\x52\x6a\xf5\x1b\xa9\x69\x8d\x23\x4a\xaf\x51\x0d\xa8\x1a\x0d\xbf\x26\x43\x66\x15\x3d\x7a\x6d\x5e\xb3\xfb\x08\xb9\xbb\x5e\xa0\x65\xc2\xf5\xe5\xb6\xbb\x67\x9d\x2e\x21\x0b\x5b\x40\xe2\xbc\x82\xf7\x8d\xc9\xab\x58\x24\xb7\x4a\xad\xad\xd8\x9b\xf8\xa8\xb7\x3a\x0a\x2f\x43\xac\x74\x83\x78\x92\x1a\x73\xa2\x52\x70\x4a\x4a\xdb\xf7\x40\xcb\x99\xc1\xe1\x59\x4c\x37\xac\x9a\xcc\x19\xf5\x23\x15\xc6\xa8\x46\xa5\x7b\x36\x12\x8c\x64\xd7\x67\xaf\x44\xe9\xc8\x63\x05\xbf\x18\xba\x7c\xd5\x26\x80\x52\x3a\x3b\x10\x2f\xba\x6f\xe5\x55\x67\x06\x9d\x20\x47\xcb\xdd\x96\x05\xea\x12\xc8\x87\x7d\x39\x9c\x1e\x66\xe3\x38\x17\x73\x1f\x50\xb8\x4f\x81\x7d\x1f\x07\x60\xa4\x0f\x97\x46\x86\x18\x93\x41\x05\xeb\x00\xec\x50\xc7\x6d\xb3\xc5\x3f\xcf\x43\xfe\x17\x02\x90\x7d\x9a\x75\x6b\xcf\x43\x9f\x88\x31\xd0\xbf\xac\x92\xe7\x05\x8f\xb1\x57\xbe\x3e\x59\x1d\x37\xeb\x34\x16\x5e\x3c\x6f\xc6\x0e\x72\x29\x4c\x08\x3e\x47\x76\x26\xf9\x00\x1c\x1d\x73\x7c\x29\x03\x77\xdf\xa5\x8e\xa4\xea\xd3\x02\x8f\xc7\x62\xce\x8a\x3a\xfe\xc2\xe6\xe1\x32\xc6\x62\xdf\x60\x34\xab\x55\x4f\x93\xef\xac\x65\x7a\xd3\x4f\x61\x07\xd3\x47\xfc\x5c\x5e\x53\xf3\x73\x3e\x17\x8b\x76\x01\x4d\x2f\x9b\xbd\x06\xef\x2d\xfe\x60\xe2\x08\x3d\x88\x65\xf7\xf5\xb2\xac\xc0\x25\xd9\x12\xe5\xcf\x6c\xda\x6e\x79\x81\x43\xe9\xdb\xbc\x70\xa0\x21\x1d\x8e\x40\x03\xd7\x8b\x38\x3d\x66\xa6\xad\x29\x71\x7c\xa2\x4e\xdd\xef\x7d\xf7\xcd\x3a\x7e\xf6\x52\xab\xa5\x48\x7a\xfe\x5d\x02\x6c\x9b\x10\x28\x07\x29\x4e\xb2\x7d\x98\x24\xee\xb6\xb4\x0f\x08\x3d\xe7"}, -{{0xb0,0xd0,0xab,0xdd,0x84,0x44,0xe1,0x0f,0x29,0x37,0x54,0xac,0x9f,0x16,0xe3,0x1b,0xdc,0xdd,0x97,0xb7,0x06,0x71,0x28,0xaa,0xe8,0xe4,0xd7,0xf1,0x12,0x89,0xe2,0xcd,},{0x1c,0x78,0xcc,0x01,0xbe,0xa1,0x53,0x52,0xb6,0x3c,0x56,0x97,0xf1,0xcf,0xe1,0x2f,0xfd,0xd1,0x6d,0xdc,0x1d,0x59,0xe7,0x79,0x51,0xb6,0xe9,0x40,0x8e,0xe2,0x28,0xad,},{0x64,0x40,0x8b,0xdd,0x2d,0x0f,0xc8,0x92,0xa5,0xb6,0x2b,0x5a,0xcf,0x8e,0x3b,0x3c,0x73,0xc0,0xb5,0xc4,0xfa,0x2a,0x72,0xe3,0x9d,0xd6,0x08,0xd4,0x93,0x7f,0x93,0x32,0xf7,0x3e,0x14,0xd0,0x8b,0xad,0xc6,0x27,0x01,0x14,0xd1,0xf1,0xa5,0x56,0xcc,0x6e,0xe8,0x48,0x8a,0xbb,0x90,0x7f,0x79,0xae,0x17,0x5c,0x35,0x2e,0x9f,0x11,0xee,0x05,},"\xaa\x27\x6c\xc5\x43\xfc\xc6\x2d\x70\xa7\x04\x60\x8d\x98\xce\x51\xb6\x45\xb5\xc2\x4a\x64\x0a\x5d\xf1\x0a\x55\x91\x41\x7d\x10\x89\x26\xdf\x3f\x0c\xe1\xb9\x21\x03\x33\x09\xeb\x8d\x86\x59\xf4\x89\xfd\x6f\x79\xaa\x1b\xf4\x88\x2d\x72\xac\x69\xcc\x58\xd3\xbc\xe0\xfa\x89\xb1\x64\x11\xe9\x75\x3e\xb4\x0c\x6c\x4d\x59\x8d\xc8\xf4\xab\xb0\xbc\x48\xf1\x37\x03\x71\x32\x6c\x9a\x86\xbb\xc2\xac\x62\x14\x47\x8e\x78\xa3\x84\x08\xbd\xda\xfa\xa9\x59\x26\x00\xc4\x9a\x12\x9c\x05\x39\x2f\x8a\x7d\x64\x2b\x49\x13\x7a\x20\xf3\xfe\x9f\x11\xee\x17\xcf\xa3\xaf\xd2\xaf\x71\x56\x5e\x9c\x40\x08\x0b\x60\xcd\x0d\xbc\x37\x8e\xda\x06\x2c\x7c\xbc\x7f\xe9\x72\xbd\xe4\x50\x9a\x1d\xe9\x5f\x14\xdf\x48\x2f\x48\xaa\xcc\x46\x3c\xd5\x94\xf6\x6d\x64\x8d\x37\x94\x73\x8a\xd6\xab\x49\x6e\x2d\xa5\x0b\x0d\xb2\xba\x7b\x65\x91\x85\xe4\x58\x7f\x18\x2e\x83\x3d\xe7\x50\xfa\xac\xdd\xf2\x1a\xf5\xe0\xcf\x4c\x9a\xf3\x85\xb0\x4f\x7b\xe2\x31\x49\x8a\xd0\xb7\x42\xd5\xa8\x7c\x06\x11\x5d\xb2\x30\x97\x3a\x51\x42\x7f\x20\x2f\xa3\x9a\xfb\x98\x28\xb5\xf0\x3f\xa3\x27\xcb\xd5\x2d\xfe\xc6\x6d\x71\xea\x31\x98\x65\xdc\xf6\x81\x0f\x18\x58\x47\x2d\x8b\xea\x3e\x44\x7a\xdf\xb4\xb6\x07\x58\xe8\x6b\x48\x13\x37\x09\x73\x2d\x2b\xcf\x51\xc7\x6c\xaa\x84\x7b\x65\x37\xfc\xb0\x5b\xb8\xc8\x7d\xc5\xe9\xfb\x02\x2b\x32\x60\xc1\xd7\x1b\x14\x98\x59\xc9\x66\x3d\xbd\xae\x6a\x7b\xbf\xd6\xde\xb9\xd1\x23\x80\x9c\x24\x14\x01\xaf\x10\x71\x9c\xf9\x1a\x6b\xed\x16\x08\x4c\x44\x46\x07\x35\x9e\xd8\xf0\x18\xdb\x11\x15\x11\x89\x2b\x46\xbd\xac\x6c\x9c\x61\x38\x41\xde\xd8\x86\xb9\xde\xc0\x6c\x01\xe8\x04\x87\xe4\x8f\xbe\x77\x8e\x9e\x97\x50\x8f\xfd\xa0\x57\x78\x53\xaa\xbd\xca\xca\x8b\x0b\xab\x6c\xe4\x15\x57\xaa\xb9\x63\x1c\x96\xd6\x09\x77\xe3\x57\x18\xb6\x05\x95\x27\x3f\xdb\xa1\x40\xf5\x50\x0a\x8d\x35\x76\xf5\xa9\xfc\x8f\x3c\xa4\xc0\x2c\x16\x7a\xf2\xe0\x3d\x25\x75\x0b\x42\xad\xb0\x3b\x14\x17\xf2\xb6\xd2\x19\xbe\x5f\x84\x29\x33\x1a\x26\xa4\x49\xb5\xd4\xdb\x2b\x1a\x09\x15\x2e\xea\x2b\x25\xd2\xdf\x7e\xf6\xfe\x0a\x32\xe2\x5f\xae\x79\x36\x0a\x9a\xee\x15\x11\xfd\xa8\x06\x45\x50\x93\x7a\x71\x30\x97\x19\x30\xc6\x73\xbb\x35\x8e\x5f\x55\x95\x1f\x50\xb1\x46\xd8\x5d\x38\x3f\x3e\x01\xc1\x51\xec\xe6\xc0\x6d\x83\x67\x01\x25\x32\x80\xfd\xcf\xf4\xe1\x39\xd3\x31\x9a\xb2\xe2\xca\x71\xbc\xc3\xfa\x0f\xaf\x7c\x70\x2c\x9c\x60\x4e\x56\x51\xde\x4a\xf5\x70\x0e\x9e\xde\x72\x58\xb9\xbc\x14\x8d\x55\x95\xcd\x34\x17\x0e\x3e\x5c\xf2\x92\x82\x83\x90\x90\x8f\xda\x96\x1f\x22\x30\xac\x0b\x8c\xac\x64\x73\x97\x32\x70\x6c\xe2\xd5\xe5\x9a\xbd\x6d\x5e\x20\x7b\xda\xfe\xa7\x4d\x28\xd7\xa7\x58\xf2\x20\x0e\x4e\x00\xa0\xbc\xf0\x30\x6a\x3c\xab\xda\x47\x02\x4f\xab\xea\xe4\x88\xab\x5c\x32\x37\x15\xcf\x3c\xa7\x72\x0a\xf9\xeb\xbf\x85\x82\xe1\x15\x8a\x09\x9d\x73\x6b\x56\x9b\x9d\x40\x29\x58\x17\xea\x25\x54\x06\x8b\xef\x32\x44\x2c\x11\x1e\xc8\x14\xc6\xed\x41\x59\x19\xba\x73\x52\x63\x34\xdf\x30\xba\xc6\x66\x08\x4e\x56\x01\xc2\x28\x1c"}, -{{0x49,0x84,0x97,0xfd,0xcc,0x6a,0x10,0x58,0x91,0xe0,0x23,0xff,0x32,0xd7,0x5f,0x7c,0x37,0x48,0xd8,0xc5,0x2d,0x87,0xdd,0x3b,0x27,0x75,0xae,0xfd,0x81,0x60,0xa1,0x43,},{0x2d,0x79,0xae,0x9c,0xee,0x4a,0xc6,0x27,0x5b,0x05,0x74,0x9c,0x43,0x8e,0xbe,0x55,0x2b,0x41,0x3d,0x87,0x3c,0xc0,0x7f,0x14,0xf5,0xfa,0x13,0x01,0x77,0x21,0x4c,0x54,},{0xb0,0xa3,0x6a,0x2c,0x93,0x47,0x56,0x34,0x8e,0xb4,0x7c,0x25,0xa3,0x2c,0x3f,0x2a,0x5d,0xdb,0xd5,0x8f,0xcc,0x72,0xa0,0x8c,0x3c,0xea,0xd1,0xa2,0xd9,0x00,0x33,0x5c,0x30,0x01,0xe3,0x5b,0xfe,0x1f,0x3f,0xb5,0xa5,0x55,0x00,0x9b,0xa8,0xe9,0x68,0x74,0x49,0x4b,0x97,0xe8,0xb0,0x97,0x00,0xed,0xcb,0x1f,0x25,0x84,0xb9,0xd0,0xfe,0x03,},"\xbe\x38\xbc\x8c\xdf\x46\x19\x0e\x30\x4a\xb5\x3d\xd2\x9c\x2b\xc4\x09\x54\xfd\x4c\x6d\x2b\xb9\x90\xf9\x3b\x2b\x5c\x69\x1f\xdf\x05\x27\xc2\x60\xf5\x06\x61\x87\xf2\xd0\xf3\x1f\x43\xa0\x8b\x36\x0e\xa1\xed\x82\x00\x65\x17\x64\xb8\xfa\x49\x59\x5a\x15\x94\x10\x9e\x49\x67\x59\xab\x66\x23\xfa\x33\x37\x8d\x80\x0e\x61\x17\xe0\x79\xe1\x3f\xe8\x5c\x81\xb6\x3e\xbe\x24\x7b\x3d\xf6\xc1\x58\x4b\xc7\xcf\xfb\xdf\xa4\x5f\x2a\x2c\xe7\xc2\x37\xaa\xaf\xef\x8c\xbc\xa7\x0b\xca\xbc\xe0\xb8\x47\xd5\x51\xf4\x6a\x7d\x15\xce\x2a\x0d\x3d\x54\x5a\xba\xcc\x59\x30\x01\x0c\x53\x64\x88\x87\xd4\x76\xe0\xd1\x3a\x34\xfc\x1c\x54\xdf\x09\xd1\x06\xed\x75\x8d\xee\xdc\x76\x1d\x55\x7a\x73\xb2\xbc\xdd\xde\xfb\xa4\xed\x00\x59\x97\xb1\x92\x79\xb9\xd2\xde\x37\xd0\x41\xfe\x01\x3e\xef\x05\xa2\xe1\x1c\x9a\x23\x4e\x87\xcc\x0e\x16\xc0\xc6\xda\x42\xaa\xa5\xbf\x99\x64\x17\xbf\x64\xe5\xb7\x85\xd6\x7d\xc3\x25\x47\xc1\xf0\x52\x17\x8d\x69\x4c\xf2\x0f\x16\x98\x58\x9e\x7e\xd4\x9b\xe2\x9d\xd5\x9f\xd5\xc0\x1b\xa1\xd9\xf5\xfb\x06\xa7\x58\x95\xb7\xb1\xe1\x58\x95\x09\x7e\xbd\xe8\x4c\xad\x63\x03\xaa\x0a\x86\xdb\xc3\x24\x74\x7d\x97\x24\x5d\x70\xc5\x20\x3b\xe0\x1b\x06\xcb\xde\x06\xae\x03\x72\x04\xd2\x37\x30\xcd\x69\x61\x89\xf7\xac\x26\x7c\xf2\x02\x17\x99\x29\xce\x54\x10\xe0\xe3\xad\xe5\x13\xd2\x20\x1b\xfd\x20\xfe\xfa\x40\xb4\x47\x6f\x27\xbf\x90\x7c\x76\x2e\xb7\x26\x2a\x5b\xe1\x3c\xfc\x04\x7a\x84\x6d\x20\xa9\xf2\x31\x1b\x64\x69\xb0\x6a\xb5\x45\xf0\xec\x9f\xc4\x46\xea\x25\x0c\xd3\xb7\x3a\x7b\x6b\x96\x0c\x10\xca\x4c\x2d\x6c\x64\xa1\x56\xa1\x8c\x9f\xb8\x10\xe4\x9a\xfd\x0c\x36\xda\xab\x8b\x8b\x85\x66\x43\xa4\xcc\xaf\xa9\xad\x88\x6e\x91\xe5\x44\x53\x5b\x8e\xdd\xa2\x7c\x90\xc0\x6a\xb6\xbc\xc5\x36\x28\xbe\x18\xd7\xd6\x36\x9c\xa1\x80\x1f\x91\xc2\xe0\xb9\x5f\x36\xd7\x02\xf7\x72\x34\xb4\x10\x07\x19\xc0\x59\x95\x1e\x45\xb1\xf9\x16\x98\x39\x34\xe3\x2b\x4d\x4d\x8f\x29\xc0\xa3\x73\xf8\xd8\xf0\x91\x8b\x96\x78\x65\xcd\x0e\x4b\xec\xa0\x13\x27\xc9\x9d\x5f\xde\xd4\xc1\xa6\x9a\xc2\xd4\xd9\xb7\x8f\xfb\x83\x05\x67\x00\x21\x04\x02\x50\xcc\x27\x73\x7e\x75\xdf\x75\x76\x0f\xec\x8b\x8d\x30\xb2\x45\x65\x4f\x3c\x12\xf1\xf7\xce\xa0\xbc\xe7\x8a\xb3\x69\x35\x78\xaf\x3e\xa6\x1f\xfc\xcd\xf9\xba\xf7\xc3\xea\x65\xb8\x8f\xc8\x54\x12\x81\x26\x47\x67\x96\x89\x2c\x66\x3b\xd1\x45\x18\xc9\x91\x86\x29\xa1\x09\x5f\x61\x4e\x04\x92\x44\x6c\x3d\x84\xb1\x6e\xc9\x4f\x7e\xca\xda\xeb\x6b\x65\x9b\xbb\x48\x67\xb5\x79\x06\x17\x14\xfd\x5b\xb0\xfa\xa4\xad\x6b\xe0\xff\xb3\x88\x8b\xea\x44\x7e\x4e\x34\x38\xc8\xf0\xea\xe6\x44\xfb\xd4\x5a\x38\x02\xdc\x40\xec\x45\x1b\x21\x2b\xd5\x92\xda\xcd\x4d\xa9\x66\x86\xdc\x8b\x20\x24\x25\x7f\x25\xe9\xc8\x30\xbf\xf7\x95\xee\xe8\x5d\x87\xa0\x90\xc1\xa4\x23\x21\xe7\x10\x55\x57\x64\xed\x82\x57\xc9\x41\x5c\x7f\x22\x4b\x53\x75\x58\xce\xfd\xc6\x15\x12\x9f\x28\x35\x02\x67\xc0\x1b\xa0\x40\x3e\x07\xf5\xc6\x06\x7f\x91\xc8\x5a\x2c\x50\xc8\x66\xdc\x43\x88\xaf\x38\xd2\x16\x02\x03"}, -{{0xd9,0x62,0xa6,0x71,0x9e,0x5c,0xc7,0x72,0x4c,0xa4,0xa1,0xd5,0x59,0x53,0x68,0x12,0xb4,0xe2,0x2a,0xa7,0xbc,0xb1,0x3e,0x4f,0xb1,0x72,0x2d,0x28,0xe0,0x45,0x21,0x7c,},{0xa9,0x44,0x59,0x2d,0xbc,0x7d,0x77,0x03,0x9d,0x72,0x02,0x56,0xc3,0xfd,0x34,0x0d,0x34,0xdb,0x89,0x2a,0xb1,0x3e,0x48,0x12,0xd6,0x62,0xe2,0x84,0x0c,0x28,0xb6,0xd0,},{0xdf,0xb9,0xb6,0x35,0xac,0x0e,0xdf,0x83,0xb7,0xb5,0x9d,0x0b,0x84,0x09,0xaf,0x47,0x5f,0x66,0xfc,0x99,0x46,0xaf,0x0b,0x7c,0x63,0xab,0x8c,0xf5,0x92,0x9d,0x47,0x01,0xa1,0xbf,0x66,0x95,0x9c,0xde,0x62,0xfb,0xcf,0x59,0xa4,0x8a,0xb3,0xbb,0xaf,0x0b,0x9a,0x61,0xb6,0xe0,0x0b,0x21,0x81,0xeb,0x93,0x42,0x82,0x07,0x0a,0x5d,0x53,0x00,},"\xa6\xaa\x7a\x19\x0d\x00\x3a\xb1\x75\x33\x2b\x8f\x58\xe7\xca\xeb\x69\x08\x54\xd9\xdb\x56\xdb\xb6\x95\x7b\x3f\xb6\x54\xe2\xe0\xda\x99\x1f\x31\x54\x21\x42\x04\x13\x5d\xf1\xe1\x10\x43\x17\xc9\xe3\xc5\x8e\xed\xff\x1f\xc6\x1a\xba\x57\x74\x4c\x0c\x7e\xf4\x86\x00\x0a\x70\xb2\xc1\x42\xeb\xad\xdc\x07\xab\x06\x5e\x2a\x85\x5d\xaf\x19\x8a\x68\x03\xac\x24\xef\x37\x24\x48\x7c\x13\x51\xdd\xed\xa0\x51\x39\x13\x45\x7d\x76\x86\x0d\x78\xa9\xb6\xbc\x3d\xba\x66\xc4\x0e\x5f\xc3\x49\xa8\x73\xad\x60\x65\xce\x7d\x7f\xdc\x2c\xc4\x83\xb3\xae\xfb\xf2\xf0\x3d\xd6\x69\xbd\x9c\xb8\xf6\x3c\xee\x47\x78\x5c\xac\xb0\x9d\x87\x2c\x9a\xeb\x83\xe9\x86\x84\x05\x25\x43\x24\x03\x79\x82\xe0\x86\x13\x45\x5d\x95\x21\xd8\x8e\xa2\xfd\xa0\x20\xbe\x73\x0c\xfc\x8c\x07\xcb\x0b\x37\x61\x4c\xcb\xa2\xfa\x3e\xc4\x98\xb8\x15\xbb\x5a\xdb\x99\x6e\x84\x8b\x38\xc0\x15\xa6\xa5\xc7\x52\xeb\xda\xc7\xb9\xee\xd8\xb6\x96\x19\xd8\xc8\x46\xb6\x6f\x78\x16\xd1\xdf\x1e\xbc\x21\x07\x1c\xef\x0b\x25\x1e\x2e\xab\x59\x82\x7f\x6d\x60\x55\x08\x43\x70\xfd\x27\xc2\x03\xe8\x6a\x18\x9f\x1e\xe1\x1e\x84\x03\xab\xdc\xbd\x1f\x45\x34\x1a\x82\x05\x25\xd8\x63\x7d\xc4\x84\xa5\x18\x5d\x65\x51\xcb\x88\x2a\x96\xb9\x98\x1a\x5f\x1a\x82\x1f\x27\xb6\x56\xff\xf9\x0e\x7f\x69\xbf\x28\x6f\x75\x2f\x97\x0f\xfc\xa5\xc5\x3e\x08\x50\xb2\x0b\x94\xf9\x43\x16\x27\x09\x4a\xce\xa9\x12\xa8\x80\xb7\x49\xa6\xf8\x0b\xb2\x06\xcc\xaa\x74\x6f\xa7\x0c\x83\x3c\x9f\x32\x30\x89\xce\x05\x58\xc9\xdc\x20\x0d\x57\x39\xd1\xe4\x99\x63\x4f\x2c\x16\xe5\x4b\x7f\x6d\x78\x19\xc4\x70\x71\xb6\x0b\xd5\x4d\xd0\xf2\x73\xa3\x19\x75\x0f\xd3\xc5\x10\xa4\x9a\xb5\x6f\x63\x0c\x7c\xe6\xd8\x02\x3d\x97\x86\x23\x46\x85\x9b\xc0\xb4\xd6\x05\x22\x49\x69\x70\x89\x03\x76\x03\x01\x40\x9c\x60\xab\x25\x17\x56\x11\xf0\xbe\x98\xb2\x3a\x8c\xd8\xac\x53\x5e\x35\x13\xbc\x77\xe1\x45\x21\x93\xda\xdf\x44\x35\xe6\x3c\x36\x29\xb6\x66\xa5\xea\x4c\x4b\xad\x36\xea\xca\xd2\x60\x14\x04\xea\xbd\x8d\x9a\x07\x95\x6e\xc2\xb4\xb7\xbb\x63\x36\xed\x75\xb8\xdf\x8f\x16\xde\x42\xc0\xfc\xae\x93\x65\x2e\x3c\x40\x7c\xbd\x45\xe8\xd4\x13\xef\x51\xe8\x54\x2d\xf6\x25\x12\xee\x79\x3e\x41\x35\x8a\x1d\xe1\x92\x46\xc6\x58\x6b\x3c\x14\x07\x41\x04\x21\xf6\xe8\x65\xc7\x5a\x9f\x4a\x6a\x47\x88\xf8\x4a\x9c\x78\x1d\x8f\x80\x24\xbf\xdb\xe2\x5b\xdc\x7d\x4b\x69\xcb\xaa\x77\x19\x62\x8c\x0b\x07\xec\x2c\x4a\x23\x4f\xff\x4a\xc3\xd4\x93\x5b\x9c\xe4\xc8\xa1\x69\x47\xab\xe7\x95\x1f\xf8\xd9\xac\x92\x15\xe3\x38\xfa\x0f\xe9\x12\x41\x76\xd1\x7b\xac\x1e\x05\x59\x2c\x43\x98\x68\xae\x5a\x4f\x75\xfd\x1e\xa8\x2a\xa4\x54\xc2\x0a\x93\x9d\xed\xa7\x29\xa0\xe1\x96\x46\xce\xbd\x82\x20\x49\xc8\x25\xc7\xe3\x1c\x6e\xfa\xd4\x5e\x30\x6f\x2d\x9f\x05\x69\xe0\x71\x73\x31\xf4\x80\x04\xc2\x6e\xbf\xe6\x8f\x38\x43\xe9\x0f\x80\x67\x03\x2d\x21\xe7\x86\xc8\x53\x9e\x01\xbe\x3c\xea\xc5\x95\x4a\x05\x46\xc8\x4b\x73\x4d\x99\x94\x56\xa7\xc4\x5f\x8c\xeb\xaa\x47\x8e\x54\x80\x07\xf9\xd3\xaf\x83\x6f\x75\x4d\xe4\x12\x3f\x2f"}, -{{0xe1,0xd1,0x41,0x65,0x18,0x92,0x1d,0x07,0xc8,0xc3,0x9e,0x29,0x73,0xd8,0xea,0x12,0x49,0xca,0xa8,0xbf,0x65,0x9c,0xc3,0x6c,0x79,0x37,0xf8,0x4e,0xce,0x7a,0xd4,0xfc,},{0x48,0xbd,0xcc,0x3f,0x1a,0x5b,0x80,0x58,0xed,0x9a,0x32,0xef,0x1c,0xc4,0x8c,0xf7,0xa8,0xab,0x76,0xa6,0xe4,0x51,0x9e,0x5a,0x82,0x85,0x52,0x41,0xad,0x6f,0xff,0x8a,},{0x42,0x32,0xd2,0xa4,0x81,0x08,0x4d,0x11,0x96,0xdb,0x62,0xf2,0x2d,0xc7,0x4c,0xf2,0xea,0xf2,0xdb,0x0d,0xf0,0x5a,0xd7,0xcd,0xde,0x67,0xbf,0xc2,0x9b,0xff,0x56,0xcd,0xe0,0x19,0xac,0x9f,0x03,0xd8,0x1f,0x18,0x27,0xeb,0x1e,0x3b,0x0a,0xbe,0x02,0x04,0xca,0x7f,0x77,0xfa,0x87,0x4a,0xb5,0x26,0x83,0x54,0xff,0x08,0xbb,0x7f,0x48,0x00,},"\x3d\x26\x3d\xe1\xab\x91\xe8\xdd\x7b\x31\x7f\x7a\x27\xfb\x60\xa6\xe1\x83\x8c\x0c\x79\x3b\x03\xab\xbe\x70\x82\xb6\xbd\xa0\xc7\xc4\x60\x62\x26\x21\x92\xc8\x8b\x65\xc0\x26\xc1\x74\x58\x4d\x29\x64\x97\x10\x42\x9a\xe4\x4a\x46\x14\x0b\x4c\x82\xc8\xa0\xb7\x4d\x56\xa0\x04\xf8\xe2\xf5\xc1\x8f\x84\xf0\x46\x41\x53\x77\x2f\x83\x12\x63\x3f\xc6\xad\x28\xa7\xd9\xfb\x55\xf7\xd7\x8c\xd6\x48\x8c\xa5\x81\x17\xea\xf9\x23\xfa\x28\x87\x5e\x2b\x31\x89\x89\x31\x85\xaa\x3c\xcd\x04\x4d\x3f\x11\x0e\x2e\x7c\xab\xdf\x6f\x81\x4b\x9f\xdd\x67\x33\xbd\x5f\x30\x7a\x87\xbc\x73\xb6\x25\x0d\x58\x83\x93\x6d\xeb\x1d\xb0\xe0\xaf\x1b\xe7\xab\x32\x9b\x5c\x6b\xd9\x35\xbd\x8f\x8d\xc8\x88\xf0\xd1\xc4\x64\xed\xbc\x02\x3c\xbc\x08\x07\x53\xee\x8f\x79\x9f\x10\x72\xba\xd1\x14\x4d\xfa\xa6\x15\xa5\x9e\x2a\xed\xc6\x62\xe8\x3c\xb1\xf8\xe5\x20\x96\xa7\xee\x48\x3b\xf8\x73\xb2\x5a\x0c\x04\xc1\x85\x1a\x0e\x87\x37\x50\x63\xaa\x1a\x94\xfa\x83\x5c\x05\x26\x40\x36\x6b\x79\xf7\x35\xd3\x28\x61\x97\xab\x32\xeb\xdb\x51\x23\xf6\xb4\x7a\xd3\xf4\x42\xc4\x4c\x53\x0a\x68\xf8\x51\x27\x59\xe9\xcf\x38\x6f\xba\x07\xb8\x06\x4b\xc8\xfe\x83\xe2\x45\x49\x5e\xc4\x5f\x89\x38\xf8\x25\x9d\xc8\x01\x62\x05\xf7\x8d\x39\x54\x44\x2e\xc1\xb4\x45\xd8\x3d\x95\xad\x18\x05\xa5\xe0\xe8\xb3\xd5\x6b\x87\x0a\x20\xda\x18\xd7\x4f\x26\xf5\x50\xa9\xc7\x53\x4a\x41\x44\xdc\xbc\x1c\x3c\xdb\xbe\x47\x0c\xc1\x53\x90\x50\x43\x08\x8f\xac\xf1\xd3\x03\x55\x9d\xe4\x1e\x96\xc0\xab\x40\x9b\xb3\x6d\xcf\x38\xcc\x90\x38\xa6\xa4\x90\x8d\xea\x82\xa6\x53\x19\x5c\x16\xf2\x90\xa7\xc3\xac\x48\x76\x36\xcc\x5b\xcb\x18\xd1\x5a\x14\xac\x62\x4c\x70\xb6\xf6\x46\x2b\xf2\x49\xe0\x00\xce\xe9\x24\x01\x8b\xdf\x7d\xde\x39\x11\x4c\xb4\xf6\x52\xe1\x22\xe8\x74\x4d\xa2\x8b\x05\x89\xe1\x28\x4d\x70\xd9\xf1\x06\xde\x16\xd0\x73\x64\x80\x80\xe6\x43\x7f\xf3\x84\xe6\x81\x77\xd5\xcb\x71\x8e\x2c\xe3\xf1\x7b\xa1\xe9\x90\xae\x3c\xe9\x40\x66\x01\x30\xe9\x37\x50\xb8\x2e\x2f\xb4\x1a\xa3\x69\x77\x45\x68\xd7\xcf\x28\x67\x25\xe3\xc5\x8f\x63\xe7\x3f\x86\x97\xae\xec\xc7\x17\xc5\xcf\x1a\xf7\xad\x74\xf4\x46\x29\x2c\x90\x5d\x84\xe2\x2b\x23\xd4\xe0\xd2\x60\x4b\xff\x48\xfe\xfc\x40\xc6\x20\x4b\x5e\x34\xc0\x42\x29\x2e\x53\xbe\xc9\x36\x01\x59\xa5\xcd\x97\xb2\xdf\x57\x86\xb8\xf5\xa2\x92\xc0\xb3\x9d\x14\xa8\x70\xa4\x58\x8e\x67\xbd\x12\xb2\xc2\xf7\xa4\x40\x84\x62\x85\x1d\x2a\xa7\x87\x97\x1d\x93\x15\x19\x0f\x42\xcc\x58\x8a\xf0\xd2\xdc\xd9\x1f\x31\xbb\x71\x5e\x92\x50\xf1\x19\x28\x14\xf7\xb8\xa2\x1f\xef\x45\x17\xb0\xcf\x8b\xb8\xa1\xa1\xa5\xf5\x00\xee\x21\x9d\xfb\x46\x13\x2e\xfe\x8e\x90\xbc\x49\x09\x3a\x55\x59\xf9\x68\x1b\x4f\xb5\x9e\x5b\xa9\xef\x3f\x05\xd3\x4e\xed\x03\x4c\x14\xd7\x7e\xe9\x5e\xbd\x76\xff\xa5\xaf\x0b\xef\xcb\xa1\x8f\xdf\x93\x2a\xf4\x85\x45\x10\xb7\x5d\xb0\x0a\x72\x57\xb2\x34\x88\x7d\x49\x60\x7d\xfd\x16\x18\x0d\xb5\x16\xc7\xa2\x0c\xcf\xca\xed\xa6\xae\xdf\xb6\xa2\x37\x7f\xbf\x31\xe6\x7b\x51\x76\x55\xdb\x73\xca\x29\xe1\x18\x62\x4d\x60\x80"}, -{{0x2b,0xf7,0x4f,0x00,0x4d,0x7d,0x0a,0xf7,0x3a,0x83,0xea,0x20,0x8c,0xc2,0x06,0x72,0x3d,0x18,0x8f,0x4c,0xf6,0x07,0xbc,0xad,0x4b,0x69,0x80,0x26,0x8f,0xf2,0x1f,0xa7,},{0x8f,0xdc,0xd9,0x93,0x52,0x43,0x8b,0xeb,0x52,0xf0,0xd1,0x74,0x2b,0xae,0x71,0x84,0x45,0x12,0xdd,0x06,0x85,0xaa,0xf1,0xc9,0x09,0xe3,0x8f,0xc4,0xb5,0xaa,0xb6,0xcc,},{0x3e,0xb5,0xb3,0x39,0xe1,0x91,0xa3,0xb6,0x16,0x85,0x45,0xda,0x5f,0xb0,0xca,0x9b,0xe2,0x09,0x04,0x39,0x19,0xb9,0xc7,0x0a,0x07,0xb4,0xa7,0xa3,0xbf,0x64,0xb1,0x02,0xf6,0xff,0xd6,0xd2,0xb0,0x25,0x59,0xdc,0x68,0x1e,0xd3,0xb9,0xc8,0x22,0x97,0xb2,0x01,0xdc,0x25,0xc4,0x97,0x38,0x80,0xe1,0x55,0xe1,0x3a,0x29,0x42,0x6e,0xb4,0x0d,},"\x89\x8e\x43\x03\xea\x5b\xeb\xd2\x00\xa5\xf7\x56\x2b\xe5\xf5\x03\x26\x40\xa3\xf5\xcc\xfa\x76\x42\x92\x04\x5a\x1a\x36\x8d\x02\xaa\x59\x10\x77\xd8\xf3\x04\xf7\x4d\xbd\xfc\x28\x07\x34\x45\x4e\xd8\xc2\x72\x7a\xff\x39\x2c\x10\x8c\x52\x6e\x52\x7e\x67\x2c\x53\x97\xb2\xd7\x7c\x01\xf7\x74\x1e\xf8\xdc\xc2\x51\x0e\xe8\x41\xb5\x9d\xd1\x0f\x4e\x1d\x3a\xc5\x01\xaf\x7c\xbd\xb8\x5b\xa3\x11\x29\xc2\x62\xfd\xe1\xa0\xc8\xbc\x83\xd6\xff\x94\x4b\x6b\xae\x3f\xa7\xfb\x62\x58\x7c\x68\x1d\x8e\x34\x29\x65\xc5\x70\x5f\xd1\xa6\xab\x39\xe5\xa0\x77\x0e\xe7\x79\x8d\x9f\xb6\xc0\x01\x8a\x51\x4d\x53\xaf\x84\x8d\xb6\x04\x7c\xd0\x2d\xb3\x52\xd5\x56\x3b\x53\x66\x23\x73\xb9\x71\x93\x5a\x1a\xc2\xb7\xb6\x36\x1d\xac\x67\x48\x77\x18\x13\xf7\x74\x93\x16\x69\x49\x61\xb9\x40\xff\x38\x05\x81\x1a\x49\xfa\x27\xa9\xba\x45\x7a\xd2\x88\x48\xc6\x97\x05\x0e\x01\x88\xd0\x77\x3e\x17\xfb\x52\x19\x4e\x19\x0a\x78\x72\xa3\x98\xf3\x1c\x0f\x0a\xe0\x65\x37\xa2\x73\xff\xb5\x0c\x2c\x81\x64\x45\xab\x88\x28\x11\x92\x2c\x06\x21\x55\x6c\x46\xa3\xa0\xec\x40\xbf\xed\xb4\x11\xe9\x0b\x6d\xb1\xdd\xd4\xbb\xeb\xb5\x7d\x10\xdf\x56\x6a\x63\xd7\x26\xa3\x33\x08\x51\x4c\xe3\xb4\x99\xd5\xe5\x26\xc2\x2b\x95\x6d\x8b\x99\x91\x3d\xcb\x13\xe4\x37\xe9\x47\xb6\x66\xc4\x1c\x54\xd8\xb3\xae\x23\x56\x64\x7e\x80\x17\xab\x67\x83\x86\xc9\x27\x21\x9a\xe7\xbd\xdc\x0d\x82\x12\x65\xf9\xdc\x4f\xf3\xf8\xce\x5b\xe6\x0f\x8e\x9d\xef\xc5\xca\x33\x50\x68\xee\x29\xfe\x83\x04\x91\x7b\x78\x87\x84\xa2\x38\x8a\x32\x01\x92\xf9\x32\x5d\x0e\x6c\xff\xfe\xa2\x1e\x6e\xaa\x29\xe7\x70\x7f\x63\xa9\xea\x4f\xbb\x25\x58\xe3\xd0\x83\x5b\xab\x1f\x52\x36\x10\x37\xae\x59\xe5\x03\xee\x96\xb9\xd7\x08\xa4\x7a\x3a\xe4\xba\xd1\x13\xe2\xa4\x60\xa2\x69\xcc\xf2\x5a\x00\x03\xcb\x3e\x68\xa5\x51\x86\x4e\x59\x84\x09\x14\x79\x11\x26\xf9\x54\x78\x8b\x25\xb5\xaf\x5a\xaf\x58\x6e\xbb\x87\xfa\x5f\x37\x7b\x4d\x7d\x7f\x84\xc0\x00\xdd\x2c\xb4\x40\xe2\x14\xd3\x8d\x5e\xcf\x70\xf2\x0e\x98\x81\x82\x8e\xda\xa1\xdb\xec\x37\x09\x3d\xb9\x60\x68\x6c\xa1\x23\xf1\xec\xba\x63\x36\xb3\x7f\x46\xcf\x76\x5b\xe2\x81\x4b\x9e\x67\x05\xbc\x9d\x6a\x49\x31\x81\x18\xc7\x52\x9b\x37\xc8\x4e\xc8\x8d\x58\xa8\x45\x3d\xcb\x69\x2c\x9a\x36\x01\x6b\x94\x8e\xbe\x6f\xb2\xc1\xd0\xad\xf5\xf1\x98\xee\x30\x97\xa6\xff\x0b\x8e\xeb\xba\xd8\xb0\x76\x93\x30\xb1\x86\x89\x51\x6b\xc0\xfe\x66\x8b\x0d\x05\xe3\xa5\x84\xfc\xf8\x9c\x49\xdb\x50\x1d\x61\xc2\xde\xf7\xed\x37\x22\x07\x01\x93\xa5\xb6\x83\xc5\x08\x7e\xf2\x74\xce\x6a\x19\x3d\xd4\xa3\x03\x53\x6c\x67\x93\x4b\x46\x60\xa8\x41\xee\x1b\x44\x6a\x68\x92\xb1\x4d\x0b\x0a\xa3\xe9\x8f\xdf\xfd\x43\xc7\x97\xad\xd3\x65\x83\xf7\x4c\x94\xd0\xe2\xd6\x8e\x2d\xe8\x18\xd9\xaf\x20\x05\x98\xf0\xb2\xbe\xae\x16\x9c\x8d\xfb\xc4\xd3\x97\xe6\xd1\xce\xb6\xda\xa6\xc9\xf6\xbb\xf4\xf8\x31\x1b\xa2\x6f\xfb\x19\x4d\x44\x21\x6c\x51\x30\x52\x67\x07\x4e\x85\x6a\x1d\x6e\x92\x27\x80\xf4\x79\x8e\x2f\x22\x02\x23\xff\xf1\xdc\x37\x0c\x8e\x34\x51\x4a\xba\x42\xdf\x51"}, -{{0xf5,0xf7,0xd5,0xb7,0x3c,0x5a,0x65,0x30,0x1b,0x5b,0x4c,0x67,0x10,0xed,0x12,0xc1,0x6e,0x79,0x03,0x17,0x7d,0xb7,0x92,0xca,0x71,0x5e,0x23,0x38,0x9d,0x05,0xd8,0x3e,},{0x7c,0x47,0x62,0xe9,0x79,0xf0,0xc7,0xe2,0x07,0xbe,0x18,0x43,0xe2,0x66,0x6a,0xca,0x27,0xea,0x89,0xbf,0xf5,0xb6,0x1d,0x57,0x3c,0x98,0x5f,0xc7,0x02,0x5e,0x1e,0x28,},{0x58,0xfb,0x39,0x2f,0x82,0xd5,0xe5,0x2f,0xf0,0x72,0xcc,0x77,0xef,0xe0,0x48,0xf2,0x23,0x52,0x50,0xc7,0x11,0x25,0xee,0x82,0x1c,0x5f,0x3b,0x39,0x3b,0xcf,0x2f,0xa4,0x6b,0xe4,0xc5,0xd8,0xca,0xf1,0x3c,0xb5,0x19,0xef,0xe0,0xc2,0xfa,0xd9,0xee,0x23,0x1a,0xe9,0xb6,0xfd,0x1f,0xd5,0x09,0xc9,0x8c,0x69,0xc2,0xd3,0x6c,0x75,0x3e,0x0e,},"\x7c\x93\x18\xd5\x6e\x63\xf1\x65\x35\x43\x6f\xa4\x5a\xfe\x27\x8e\x74\xe6\x18\x81\xbb\x46\x89\x97\xd0\x41\x8b\xc7\x20\xb6\x30\xda\xdb\x81\x28\xb4\xb6\x5c\xa6\xe9\x21\xe5\x01\x81\x3d\xf9\xfe\x03\xb4\xef\x0a\xae\x80\x35\xdd\x08\xc5\xf8\x20\xce\x5d\xf1\x2e\xe1\x18\xd9\xc3\x6d\x3b\x15\x1a\x52\xc3\xf9\x6a\xe1\xca\x4c\x82\xfd\x19\xda\x66\x9d\xdb\xa9\x4f\xeb\xf8\xea\xc8\xc4\x2b\x44\x7b\xab\xc8\xa6\x0b\x36\xe8\x03\x62\x4f\x7d\x20\x47\xbd\x8d\x8a\x15\x36\x87\xf1\x0d\xc1\xca\x82\x10\x0b\x7c\x87\xd3\x23\x70\xec\x8f\x26\x71\xed\x7d\x06\x7c\xc8\x05\x87\xca\xb8\xdb\x3a\x71\xce\x5e\x40\x63\x27\xf7\x63\xec\x1b\x3c\x16\x67\x70\xa7\x55\x36\x63\x0c\x81\x5f\xd8\x26\x75\x82\xd1\xb5\x05\x1f\x0f\x82\x1c\x02\x15\x0b\x2e\xef\x34\x9b\x50\x59\x03\x14\xaa\x25\x70\x79\x3f\xa6\x4a\x76\xed\x2e\xd8\x3d\x2b\xa1\xf9\xb9\xf1\x16\x31\x54\x61\x2b\x49\xa6\x4a\xd8\xd5\x57\x3c\x25\xb1\xcd\x37\xc4\x1a\x44\xe3\xdf\x78\xf1\x05\x3d\x90\xb0\x68\xf0\xd3\x7a\xe0\x0c\x4a\x32\xb1\xa3\xff\x87\x4c\x41\xda\x4a\x70\x43\x39\x2f\x18\xef\xe5\x51\x8d\x76\xe8\x8b\x41\xce\xd6\x9e\x6f\x4c\x01\x4f\x06\xeb\xc5\x14\x6e\x61\xe8\x2f\xae\x1c\x49\xc3\x7c\x39\x4f\xea\x34\x19\x9a\xb8\x6c\x11\xa4\x46\x7a\x37\x4e\x40\x25\x5a\x05\xd4\x26\x97\x14\x30\xd5\x6c\xdb\xa2\x5a\x21\xad\x77\x9c\xc7\xf6\x2d\x22\xcd\x87\xb6\x0f\x08\x91\xbd\x85\x6a\x51\x7e\x14\xb7\x2a\x9a\xc7\x67\x2e\x4e\x8f\xb3\x74\xa9\x75\x8a\xb0\xc4\xe5\x96\x4a\xae\x03\x22\x89\x73\xf1\x73\xa5\xd4\x2a\xef\x9d\xb3\x37\x36\xc3\xe1\x8d\x8e\xec\x20\x4a\x1a\x17\xb9\xd0\x45\x93\xde\xa4\xd8\x04\xcb\xc8\x1b\x9a\xc5\x45\x80\x50\x49\x55\x39\x99\x9a\x99\x85\x48\x7e\x7c\xa1\x1c\x37\x58\x2e\xf8\x5c\x84\x1e\x8f\x06\x5e\xa9\x8f\xdd\x6b\x1c\x60\xde\xa1\xec\x28\x83\x52\x15\x68\x85\x6a\x6e\xbb\x27\x49\xf2\x07\x2e\xb4\x34\x48\xbe\x07\x05\xed\x47\x7c\xf4\xb2\x00\x48\x65\x21\x7d\xe5\xfa\xdb\xe2\xa0\xf9\xd6\xb8\x4b\x3f\xe7\xf7\xbf\x6c\x77\x53\x74\x96\x24\x6e\xc7\x96\xb8\xef\x2c\x04\xf6\x8a\xb5\xb1\x4f\xce\x0c\x6d\x28\x7b\x83\x62\x27\xd9\xf0\x8f\xa0\xee\x19\x72\x2f\x67\x98\xa5\xd8\x28\x0d\x10\x7c\xfc\x1b\xd5\x92\xd9\xdd\xc7\x24\xea\x86\xfc\x39\xdc\x94\xa3\x94\x01\x9e\x3a\x3d\xe9\xe0\xd1\xc7\x35\xe8\x62\xde\x2b\xb9\x52\x5b\x5f\xb4\xbd\x12\x12\x12\xbf\xaf\xf9\xff\x58\x6a\xc3\xc7\x5c\x5a\xce\x74\x6d\x9c\xa3\x07\xf7\x95\xff\x26\x97\xf2\xb4\x1a\x63\x46\xed\x23\x39\x7e\xb3\x88\x98\x69\x1e\x6f\x66\x84\x16\x37\xd0\xab\x0d\x96\x83\x09\xe0\x19\x40\x02\x30\x90\x15\x41\x6e\x74\x47\x2f\xe3\x24\x25\xd4\x5f\x07\xc7\x71\x19\x18\xb1\xe5\x79\x0f\x57\x2c\xe4\x44\x10\x42\xd4\x26\x03\x37\x92\x29\x7b\x5f\x81\xe0\x80\x9b\xd9\x69\x1f\x0a\x50\x5e\x32\x59\xfc\x03\xc9\xff\x10\x7e\xb9\xb4\x87\x95\xf4\x9f\xb0\x9c\x1b\xab\x56\x59\xd3\x9f\xfe\xcb\xdc\xc4\x03\xe3\x80\x3d\xc0\x12\x43\x8c\x2f\xb3\x6f\x68\x30\x15\xc5\xdf\x04\x82\xcb\x7d\x7f\xc5\x75\x73\x64\xa0\xa3\xc1\x0d\x0e\x12\x59\xc0\x1f\xcc\x4d\xd5\x49\x4b\x52\x90\xa6\x94\xae\xa3\xf6\xfa\xe5\x47\xac\x57\x6f"}, -{{0x43,0xd4,0xbe,0x6d,0xe9,0xcb,0x00,0x89,0x8e,0x99,0xdd,0xcc,0x2e,0x15,0x30,0x11,0x0f,0xa2,0xcb,0xc4,0x37,0x6c,0x48,0x5e,0x9c,0xa5,0x7f,0xd6,0x55,0x86,0xd8,0xa3,},{0x36,0x32,0xad,0x38,0x9b,0xe2,0xfa,0xb3,0xfb,0xa0,0xd8,0x04,0xbf,0x63,0x45,0xcd,0x32,0x2e,0xdd,0xd6,0xa7,0x5d,0x8c,0x37,0xfd,0x4b,0x5b,0xa1,0xc9,0xc2,0x5e,0x8f,},{0x86,0xae,0x93,0x25,0xf8,0x0b,0x98,0x86,0xc8,0x38,0x1f,0x96,0xa1,0x8c,0x21,0x20,0xe6,0xdb,0x01,0x6a,0x0d,0x6c,0xa2,0x82,0xed,0x93,0xba,0x9b,0x61,0xca,0xec,0x02,0xde,0x88,0xef,0xca,0x8b,0x8e,0x91,0x6a,0x4b,0x16,0xa5,0x85,0x25,0xa2,0xf6,0x8d,0x21,0xe5,0xfb,0xe6,0x7d,0xb4,0xc4,0xd6,0x20,0x95,0x95,0xc4,0xab,0xc3,0x2b,0x09,},"\xd9\xd5\x5d\xab\x0f\xa6\xda\x76\xb6\x8e\x84\x1c\x24\xd9\x71\xba\xc1\xf7\x9a\xf5\x13\xd8\x34\xe4\x26\xa5\xd0\x81\x14\xce\x8b\x54\xce\x8b\x7a\xfe\x01\x6b\x0f\xad\x03\xee\x74\x50\xc6\xc3\x09\x71\x73\x68\x1a\x4b\x2e\xb9\xf9\xc1\x79\xa8\x8e\x7c\xc3\x68\x13\xf2\xf5\xd1\x5f\x79\x98\xaf\xa9\xfd\x4e\x54\x6c\x73\xbb\x42\xe7\xf9\x52\x2b\xe6\xaf\xab\xca\x8c\x7b\x64\xfe\xd0\xe2\x92\xe4\x37\x5f\x3e\x1e\x5f\xd9\xfc\xb5\x39\xf4\xe5\xe5\x43\xfb\x6a\x11\xa0\xdf\x32\x1e\x70\x08\x4a\xaa\xbb\x70\xa9\x95\x0c\xee\xe3\xd8\x79\xc3\x86\xef\xca\x1e\x59\xc3\xcb\x7c\x45\xb5\x60\x09\x5e\x7a\xf0\x0f\xf5\x2f\x8a\x1a\xaa\x9c\xcf\x09\x2f\x0b\xb8\x06\xd9\x76\x10\x74\x2a\xc5\x82\xa3\xab\xbe\xdd\xf3\x9f\x49\xd2\x29\xd3\x2a\x11\x86\xd0\x21\x51\x8d\x74\x72\x8d\x13\xd9\x62\x63\x5d\x63\xba\xa6\x74\x3b\x12\x6b\xf4\x58\xfa\x2a\xc7\x56\xfb\xf8\x80\x96\xc8\xd3\x34\x0c\x62\x23\x90\x53\x4a\x74\x3f\x18\x64\xd5\x4d\xea\xb5\xe5\x53\x63\x72\xce\x5a\xc9\x37\x62\x28\x74\x14\xea\xe1\x58\xa7\x6b\xf8\x1d\xf5\x41\x7c\xf4\xc0\x47\xbe\x3a\xc1\x47\x5c\x51\x7e\xbd\x3a\xc1\xd1\xd1\xbd\xda\x11\xb3\xf9\x9c\x18\x17\x3e\x03\x0a\xcd\x51\xd2\xb5\xcf\x79\x51\x65\x09\x41\x54\x05\x07\x75\x11\xbd\xd9\xcb\xe1\x7d\x04\xf4\x78\x05\xe9\x8d\x0d\x14\x5e\x60\xa5\xd0\xe0\xf4\x53\xcd\x9b\x5c\x1a\x24\xf1\x2b\x75\xe8\xcc\x34\xd5\xe0\x06\x91\xff\xac\xbf\xf7\x88\xfe\xa8\x34\xd9\xd7\x79\xc1\xe6\x10\x29\x4d\xce\x19\x17\x0d\x28\x16\x0c\xff\x90\x9b\xea\x5a\x0a\xa7\x49\x40\x17\x40\xea\x3a\xf5\x1e\x48\xb2\x7c\x2b\x09\xf0\x25\x44\x42\x76\xc1\x88\xc0\x67\x1a\x6d\xa9\x4b\x43\xd1\xe5\x25\xe6\xa4\xa8\xa1\xa7\x3d\xfe\xdf\x12\x40\x18\x46\xba\x43\x06\x8a\x04\x09\x2b\x12\x91\x22\x70\xd2\xb6\x0d\xf6\x09\x97\x79\x75\x6b\x8b\xbb\x49\xec\xe8\x2d\x55\xf0\xf8\xdb\x1b\x80\xfb\x4b\x59\xbb\xa8\x60\xbd\x18\xc7\x5d\x6c\x83\x4d\x69\x44\x2a\xe0\x31\x4c\xf2\x39\x9f\x53\x92\xa3\xc6\x72\x8c\x63\xe5\xc5\x16\xc4\x22\x2a\xac\x60\xf9\x16\xdd\x63\xd1\xd0\x51\x7e\x8e\xb1\x0b\xd0\xe1\x5e\xb9\x06\x14\xde\xb2\x96\x40\x3a\xd1\x5b\x8c\x12\xb9\xe9\x71\xef\x2f\x01\xe5\x9f\xc3\x5d\x90\xc5\x5a\x8e\x20\xe9\x43\x7d\xd4\x34\xb2\x6d\x5c\x2c\x6e\xc2\xd5\x3a\xce\xc1\x7e\x81\xe4\x78\x31\xdc\x2d\xe8\x21\x83\xd7\x13\xb5\x9a\x4d\x1f\x46\x96\x9d\xdc\xdd\xaf\x27\xf4\x4e\x5a\x31\x1a\xaa\xc3\x9c\x3d\x5a\x97\xbc\x90\xca\xd7\x12\xf4\x6f\x85\xe6\xc8\xfb\xf5\xd5\x8d\x8b\xc3\xec\x27\xd3\x10\xa9\xea\xf2\xc3\x69\xcb\x00\x64\x97\x70\x39\x0a\x3f\x98\x8f\x36\x2e\xfc\x15\x5f\x56\xa1\x46\xa6\x26\x50\x54\x7e\x91\x53\x25\x07\x01\xee\xad\x1b\xd0\x1c\x89\x46\x22\x72\xdf\xaf\x0a\x43\x1a\xf4\xbd\x7c\x3d\xb4\x51\xad\xa6\x03\x23\x3f\xda\xd3\xaa\x89\x99\xaa\x21\xe2\xd3\xa4\x3b\x0b\x56\xfc\x6a\x91\x24\xd3\x35\x98\xb3\x73\x7f\x4e\x5c\xb2\x58\xbe\xda\x75\x6a\xd2\xe1\x7d\x06\x91\xd1\x5d\x41\x6b\xb7\xcb\x07\xec\x8d\x8c\x7a\xf5\xde\x80\xe5\xb9\x39\x4e\x32\x0c\x4c\x6e\x43\xef\xaa\xe6\x84\xad\x00\xf6\xdd\x20\xa8\x75\x0e\x95\x9c\x2f\x04\x20\x6f\xc0\x23\xaa\x19\x0c"}, -{{0x7d,0x01,0x0d,0x76,0x0f,0x24,0xe5,0xa2,0xde,0x34,0x08,0x9c,0x9f,0xdb,0x19,0xc3,0x3b,0x15,0x5b,0x0a,0x37,0xca,0x45,0x5a,0x5e,0x5b,0x1d,0xae,0x7a,0x07,0x31,0x76,},{0x4c,0x87,0x7b,0x3c,0x49,0x71,0xfb,0xb5,0x51,0x16,0x6e,0x21,0x4d,0x1c,0x76,0x24,0xc5,0x22,0x77,0x90,0x3c,0x59,0xa5,0x62,0xa8,0x0b,0x91,0xa8,0x54,0x83,0xfb,0x47,},{0x55,0x70,0x61,0x38,0x79,0xae,0x22,0x77,0x8b,0xd5,0x4f,0x14,0xfb,0x6e,0x8c,0x02,0x56,0xa7,0x1f,0x3d,0x79,0xc3,0xe5,0xcd,0x8e,0x41,0xae,0xa8,0xcf,0x77,0x3e,0x24,0xd2,0x9f,0x1f,0x1b,0x24,0xf8,0xc8,0x0d,0x29,0x49,0xe8,0x20,0x14,0x65,0xdb,0xde,0x89,0x40,0xb1,0xfa,0xb6,0x48,0x3b,0x08,0x5d,0x41,0x8e,0x25,0x10,0x14,0x20,0x0c,},"\x86\xe2\x11\x55\x72\xbf\x4c\x01\x3e\x6b\x4b\x04\xd0\xb0\x3e\x60\x6e\xe7\x0d\x92\x9c\xb8\xec\x36\xf4\xe2\xf3\x55\xdb\x3b\x5e\x15\x73\xd6\x58\xd1\x7b\xb1\xa3\x10\xc1\x69\x89\xa1\x6b\x95\x58\x92\x2e\xe4\x93\xf3\x59\x04\x21\x03\xc4\xdc\x1b\x40\xdf\xf7\x70\x99\x01\xfd\x58\x30\x13\x3f\x42\xc4\x65\x1e\xca\x00\x8b\x49\x9e\xe4\xf8\x4c\xd4\xec\x1e\xda\xa7\x82\x56\xed\xb6\x2f\x24\x02\x1a\x00\x76\x25\x69\x19\xe4\xe2\xce\x0a\x5a\x20\xf9\x21\xc2\x78\xcc\x29\x91\x59\x64\x4b\x5e\x3a\x3b\xbd\x08\x9d\xcb\xbe\xba\xd3\x76\x6a\xea\x77\xe9\xf0\x8e\xe5\xf7\xd4\xc1\x9d\x81\x70\xbc\x3d\xe1\xba\x77\x9a\x76\x99\x14\xf9\x65\xdb\xde\x2b\x61\xba\xd2\x14\xc5\x08\x18\x60\x41\xf7\x6c\x25\xbe\x95\x76\x56\xf5\xcf\xb7\x33\x4e\xb8\x38\xa3\xcf\xbc\x55\xcf\xba\xb6\x7a\xdf\x15\x52\x61\x99\x41\xb8\x35\xcd\x3e\x34\x10\x3b\x18\xb4\x91\x31\xe8\x20\x96\xf0\x5f\x57\x0b\x89\x98\x04\xba\xb8\xb6\xcb\xad\xdb\xbc\x02\xf9\xf3\xb5\x59\x73\x6d\x99\xca\x7b\x02\xd3\x26\x8f\xa2\x73\x99\x6f\xcf\x05\x71\x97\x7d\x1c\xc3\x00\x8c\x4e\xf8\x48\x97\x0e\xe3\x50\xb1\x58\xc4\x7e\xc2\x77\xad\xd4\x74\x2f\xa2\xbc\xbe\xa9\xbd\x55\x49\xc7\xbc\xa0\x38\x02\x0e\xce\x68\xf1\x88\xc1\xea\x3a\x62\xdd\x9a\x07\x3d\x4c\x13\x8c\xa8\xa9\xac\x04\x08\xdc\xfd\x46\xe3\x6b\xdf\xf7\x39\x88\xa5\x8b\x96\x17\xca\xa0\x8b\xd4\x1b\xf3\xe8\x12\xe7\x82\x4f\x0f\x7e\x81\x46\xa4\x44\xf3\x6b\xf5\x3a\x1c\xd8\x92\x03\x9c\xcd\x33\x5f\x5a\x2e\x79\x74\x5e\xac\x96\x14\x8c\x2a\x29\x99\x47\xf1\xb2\xe3\x28\xa3\x78\x9b\xf1\x3c\x6d\x73\x50\x6f\x3b\xdc\x68\xea\x48\xab\xf0\x02\x27\x0f\xe4\xee\x9e\xf9\xed\x6b\x10\xc2\xfb\xb4\xff\x12\x75\xb9\xd7\xdd\x35\xd8\xa5\x2e\x37\x17\x58\x57\x4c\xb4\x66\xc5\x7b\x5a\xbc\x24\x29\x76\xbe\xfc\x8d\x98\xa0\x13\x1b\x9b\xb8\x46\xb2\x19\xe4\x66\x91\x86\xa8\x3c\x05\x6c\xd8\x08\x06\x61\xde\x16\xb5\x1c\xe5\x76\x7b\x22\xe9\xa9\x32\x42\xbf\x8d\x32\x05\xc6\x6a\x67\x3c\xe7\x83\xd1\xc0\xd3\x7b\x63\x00\xfb\xf0\xd6\x12\x79\x40\xf8\x8f\x18\x19\xc4\x50\xdc\xc9\x05\x43\xed\x79\x4f\x1f\xd4\x4e\x65\x39\xfe\xba\xf1\x9a\x4c\xc9\x88\x70\x01\x4d\x7c\xca\xd7\x4d\x18\x76\xa1\x23\xec\xd1\x45\x51\x6c\x74\x3b\x4b\xba\x62\xd8\x21\xca\x9a\x79\x51\xe0\xdf\xb2\x3f\x38\xd9\xe3\xa3\x65\xfd\x83\x22\xf2\xee\x47\x99\xe9\xff\x11\xe1\xc5\xc3\x0b\x55\xa3\x55\xc8\xa5\xde\xea\x81\xa5\x45\xe3\x47\x05\xab\x56\xd1\x7b\x1f\xa0\x6e\xd7\x64\x15\x55\x67\x02\xf3\x64\x80\x82\x46\xf8\x63\xc3\x19\xf7\x5c\xdf\x6b\xd7\x48\x43\x8d\x1a\x2e\xaf\x42\x06\xc5\x60\xbf\xaf\xc2\x35\x67\x9a\xd6\x04\x9c\x1a\x01\x52\x6f\xcb\x9a\x3c\xe1\xb1\xd3\x9b\xe4\xdf\x18\xb1\x5f\xa0\xea\x55\x27\x2b\x17\xeb\xde\xdf\x6c\x30\x49\x8a\x8a\x14\xf2\x04\x2b\xe1\xc2\xcd\xb0\x9e\x9e\xf3\x84\x6d\x66\x59\xa9\xf6\xd6\x73\xdf\x9a\xfb\x7e\xde\xd0\x4b\x79\x3d\x97\x31\xf0\xac\xcc\x41\x46\x8d\xc1\xf3\x23\x6c\x99\xac\xad\xee\x62\x39\xc3\x61\xb8\xbd\x7e\x2d\x0c\xfe\x8b\xb7\xc0\x66\x87\xe0\x8e\x76\xb7\x1a\xd5\x7a\x03\x61\x79\xf2\x91\xd0\x96\xae\x2f\xa0\x81\x8e\xf4\xbf\x48\x66"}, -{{0xaa,0xaa,0xbb,0x7c,0xe4,0xff,0xfe,0x4d,0xc3,0x57,0x47,0xba,0xea,0x2b,0xc5,0xf0,0x50,0xbe,0xf0,0x6e,0xe0,0xc1,0xfd,0x63,0x2a,0x06,0x7f,0xec,0xe1,0xef,0x4f,0xb5,},{0x82,0x0a,0x24,0x42,0xd5,0xf4,0x5f,0x3c,0x79,0x14,0x78,0xe0,0x98,0xfb,0x3b,0x06,0x8d,0xa5,0x2e,0xc4,0xe8,0xda,0xde,0xc8,0x50,0x65,0xc3,0x56,0x59,0xf4,0x37,0xe0,},{0x05,0x0a,0xe8,0xae,0xce,0xec,0x96,0x27,0xb8,0x01,0x37,0x35,0x7a,0x22,0x96,0x2a,0xc8,0xb4,0x50,0x48,0x66,0x17,0x08,0xd3,0x94,0xd0,0xa5,0x1a,0xad,0xc3,0x81,0xfe,0x85,0x35,0x02,0x3d,0x6e,0x1b,0xda,0x0e,0x72,0xb3,0x49,0xb5,0x0b,0x26,0xda,0x7c,0x3a,0x30,0x85,0xe8,0x1e,0x9d,0xd6,0xcf,0x12,0x78,0x68,0xfc,0x5b,0xae,0xab,0x01,},"\xf9\xd2\x85\x97\xa3\xe2\xb6\x4b\xa3\x27\xac\x5c\xd2\x9f\x08\x1e\x74\xbf\x46\x1b\x2e\xb2\xd3\xcf\xd9\xd5\xe9\x21\x58\xd2\x1d\x1d\x2a\x47\xab\x50\x98\x1c\xb1\x9f\xe3\xf8\xc6\xfe\x48\x82\x49\xb1\xc4\x9f\xb8\x97\xa0\xfe\x21\xab\x54\x04\x41\x4f\xd9\x14\x87\x5c\x22\x0f\x1c\xbc\x12\xf5\xc3\x8c\xfb\xa7\x9f\x7a\xc3\x03\xa5\x23\x1a\x37\x2b\x02\xfa\xd6\xc8\x46\x2f\x8c\xc4\x9f\x0f\x64\x96\x5b\x65\x1d\xcc\xef\x0b\xb9\x60\x82\x15\x09\x08\x49\x17\x7b\xe4\x7b\x2d\x30\x72\x94\x4d\x36\xe8\x56\xda\x18\x5c\x7b\x3a\x68\x9f\x7e\xde\xf9\x88\x33\x8e\x09\x63\xed\x31\xa6\xb0\xa8\x0d\x5c\xb0\xb1\xcc\xcf\x6f\x39\x48\x37\xaa\x6f\x8b\x2f\x3d\xa5\xef\xbd\xf4\xd3\x60\xd4\xbf\x4d\xd7\x08\xce\x64\x45\x58\x7d\x94\x2b\x79\x76\x1c\xe9\x51\xb1\xbb\x4d\x90\x50\x70\x36\x18\xa6\xd9\x30\xa8\x0c\x69\x57\x6f\xc4\xaf\x30\x6a\x2a\x56\xdb\xd8\x84\xa0\x5a\x1e\x4e\x9f\x31\x36\xcd\x0b\x55\xae\x47\x4b\xb5\xd3\xd0\xfb\xc9\xb0\x33\x9c\xec\x34\x4f\xdd\x08\x5c\x19\x28\x10\x14\x81\xc6\x87\x94\xf5\xc8\x90\x13\x71\x08\xce\xa7\x91\xd2\x1f\x81\x68\x3d\x3e\x1a\x9e\xec\x66\xac\xe5\xc0\x14\xd8\x9e\x69\x80\x8e\x5f\xa8\x3d\x38\x12\xee\x68\x0f\x5a\x99\x71\x68\x1b\x8a\xdc\xd4\xa1\x6e\x9a\x4c\x16\x5b\x5e\xf9\x93\x2c\x5e\xd8\x25\x23\x7f\xd5\x03\x7b\xcb\xef\xe4\xcb\x11\x56\x4f\xa7\x07\xc8\xa9\x32\x90\x75\x14\x14\x89\x1b\x1e\xdd\x33\x13\xc6\x5f\x8b\x91\xc2\xe9\x25\xa3\xc1\x2a\x9d\x3a\xa4\x5f\xd5\xa6\x67\xb7\x83\x93\xc3\xe3\x9d\xf8\x8a\x8f\x0d\x11\x48\xb5\x31\x1e\x3d\x87\xc4\xa9\x2e\x0a\x3f\xb9\x15\xbc\x90\xd5\x55\x8d\x05\xb4\x75\xa8\x83\x47\x78\xaa\x94\x3e\xa3\x9b\x8e\xaa\x95\xad\x18\x32\xe5\x91\x6e\xa3\x10\x2d\x7d\xe0\xb8\x36\xcd\xe8\xf3\x75\x9d\xbb\x3b\x9d\x56\xea\x81\x7b\x3e\x49\xc9\x83\x21\x02\x77\xc2\xc7\xc5\xb0\xdb\x18\x74\x22\x53\x2f\xca\x98\xa2\x8b\x3b\x65\x9c\x6b\x81\x5a\xc1\x26\xfa\xdb\xe2\xf4\x00\xc7\x3e\x9d\x2d\xed\xcb\xbd\x2d\x3a\x36\x5f\xfa\xd7\xe6\x66\xc8\x96\xe3\x1e\x61\xb3\x84\xed\x3a\x9f\xcf\x12\x90\x53\x8d\xf1\x1b\x94\x74\xc6\x28\x1c\xc5\x92\xc7\x1c\x88\x08\x86\x8b\x42\x92\xc1\x7e\xce\x6b\x3e\xdf\x5e\x35\x42\xa7\x0b\x91\x15\x93\xe9\x3f\x35\xec\xd9\x72\x9b\xd8\x88\x0a\x24\xea\xf4\x1f\xbc\x65\x74\xdf\xe1\x67\xec\x2d\x0e\x7a\xb3\xdf\x5e\xc3\x4b\x8b\x55\xd5\x48\xab\x93\x73\x8a\x2e\xea\xf2\x1c\x88\x4c\x5c\x85\x51\xdb\x2e\xdf\x2b\x04\x9f\x1a\x2a\x84\xfa\x72\xac\x89\x78\xa4\xc2\x78\x09\xf2\x09\xc1\xb2\x19\x5a\xff\x50\x4f\x69\x98\x56\xcc\x4f\x22\xd4\x4e\xbd\xd0\xfe\x50\x37\x44\x68\xd0\xb1\x79\x2e\x57\x4b\x51\x10\xa1\xf4\xcd\x0e\x22\x1e\x82\x4a\x78\xdd\xc4\x84\x5f\xeb\x46\xd6\x6d\x63\x3d\x23\xcd\x23\xf4\xb6\xfb\xe4\xc8\xce\x16\xcd\x1a\xf6\x15\x36\xda\x5f\xa6\x7b\x10\xac\x75\x55\xa6\x8c\x0e\x0b\xdb\xf2\xf8\xd7\x23\x09\xd9\x95\x51\x6b\x81\x18\xbf\x43\x83\x5d\x0a\x01\xc0\x8f\xfe\xba\x3e\xa3\xed\x05\xcd\x2d\x54\xf0\xea\xbc\xda\x05\xd0\x03\x7d\x52\xca\xed\x3b\x19\x37\x4f\xaf\x73\x99\x90\x94\xf7\x90\x55\x92\x4b\xea\x9a\xec\x44\x70\x13\x5f\x5e\x8b\xf1\x83\xc9\xd1\xc9"}, -{{0xe9,0x5c,0xc2,0xa4,0xd1,0x19,0x3b,0x75,0x39,0xfc,0xbb,0xea,0xae,0xed,0x98,0x5b,0x6f,0xb9,0x02,0xdd,0x0e,0xfb,0xd6,0x38,0x74,0x57,0x55,0x0d,0x0d,0x6a,0x2f,0xea,},{0x72,0xa1,0xff,0x1e,0x9b,0xb1,0x1c,0x8d,0x88,0x96,0x8a,0x7b,0x16,0x96,0x37,0xad,0xee,0x43,0x8e,0x22,0x63,0xf0,0x06,0xdc,0xa4,0xfe,0x02,0xfe,0x06,0x6c,0xba,0xd3,},{0x1b,0x8d,0x7c,0xc2,0xad,0xf3,0x6c,0xae,0x16,0x31,0x25,0x0c,0x82,0x43,0x1b,0xd8,0x84,0x37,0x16,0x3a,0x63,0x49,0xad,0x96,0xe7,0xa8,0x64,0x44,0x7e,0x9f,0xee,0x75,0x3a,0xc3,0x65,0x5c,0x98,0x35,0xb4,0xd1,0xec,0xbb,0x30,0x6c,0x63,0x8b,0xa5,0x40,0x2a,0xd0,0x2b,0xa6,0xd2,0x25,0xd9,0x68,0x82,0x88,0x9f,0xe8,0xd2,0x04,0xa6,0x04,},"\x84\x26\x74\x39\x20\x1b\x05\x91\xdb\x60\xc0\xf1\x7a\x9c\x15\xe4\x54\x09\x29\x56\x52\xd5\xf5\x5b\x87\xfb\x35\x19\x67\xc8\x46\xa5\x67\xf5\xce\xba\xae\xd1\x76\x2b\xff\x54\x85\xf0\x48\x53\xca\x92\x69\xf4\x64\x09\x4e\x51\x2d\xf1\xf0\x2e\x13\xe5\x17\xb1\xda\xa5\x8d\x34\xca\xa2\xd5\xff\x9f\x9e\x79\xbc\xaf\xb4\xce\x96\xe8\xa0\x89\x25\x8a\xd6\x13\x43\xb4\x46\x62\x8e\xbc\x4f\x5b\x2a\x84\xd0\x3b\x72\xef\x3f\x73\x85\x89\xfa\x13\xc4\x25\x19\xa8\x28\x29\x9a\x3f\xae\xc0\x35\x03\x7b\xc1\x0b\x44\xe3\xbd\xfe\xd9\xe0\x87\x07\x17\xcb\xaf\x31\xbe\xf8\xb2\x2c\x4e\xa1\x6e\x81\x57\xfc\xbc\x63\xee\xfa\x39\xed\x82\x2e\xfd\x42\x15\xc2\x47\xdd\xa4\x87\x86\x27\x7e\xc0\x30\xa8\x6c\x0e\xf4\x85\x1d\x67\x3c\xfe\x75\x2d\x06\x77\x88\x3c\x2c\x45\x20\x38\x97\x0c\x09\xbd\x48\x17\x14\xbc\x3f\xbe\xcf\xa4\xff\x2a\x3c\x24\x56\x95\xd7\xec\xc2\xf4\xde\xc7\xf5\xed\xe0\x4f\xf6\xdb\x43\xe2\xbb\x91\xc0\x66\xb6\x49\xef\x73\xfd\x3b\xe8\x60\xcb\x83\xfa\x80\xb0\x74\x14\x9f\x43\x1e\xeb\xb9\x17\xec\x84\x78\xda\x87\x0c\x11\xe3\x17\x70\x38\x59\xf9\xf2\xf4\x00\x8a\x6c\x7c\x75\x4b\x06\xe1\xf7\xd2\x47\x96\x89\xda\x84\xe8\x89\x22\xf3\x82\x74\x98\x5e\x11\xce\x13\xcd\xbd\xb0\xf2\xec\xe6\x8f\xb6\x02\xad\xe0\x3d\xd5\x49\xa3\x62\x49\x1f\x4a\x20\x3f\xf8\x07\x44\xf6\x63\xc5\x23\xa0\x26\xb4\x31\xaa\xd4\x5c\x58\x29\xe0\x29\xad\x62\x56\xd1\x27\x6f\xd7\xb7\xa1\x2d\xdb\xf1\x72\x7d\x9e\x23\x3f\xb5\x34\x45\x73\x70\xa4\x26\xe5\x6f\xb3\x9c\xf4\x04\xa3\xec\xbf\x0c\x4b\x50\xbb\x52\x2d\xce\x98\x1e\x08\x30\xfd\x84\x06\xe6\xd9\x72\x5c\xeb\x1d\xdd\x3a\x19\x47\x93\x7d\x90\xe0\x4d\x76\x8a\xe1\xd1\x26\xe2\xae\xac\x21\xb8\xc9\xef\xc5\x4c\x40\x96\x1b\x7f\x4e\x9e\x88\x02\x5f\x7e\x0b\x9d\xe9\x01\xeb\xf0\x04\x9e\x74\x1b\x79\x79\x97\xd8\xdb\x78\xe9\x28\x3b\xbb\x5f\x90\xf3\x5a\x2c\x4d\xee\x27\x31\x42\xec\x25\x8c\x02\xad\x0e\xcc\x61\xcc\x5c\x9f\x12\x13\x2d\xb2\x8a\xf4\x1c\x1f\xb7\x8e\x52\x4b\xe5\x32\x7b\x5f\xfc\x35\x96\x27\x79\xfb\x11\xff\x0c\x5d\x3e\xe0\xa3\x1f\xf4\x7e\x73\xb1\x72\x9d\xfa\x46\xe8\x98\x6b\x1b\x89\xab\xc8\x8a\xd0\x6a\xbd\x5b\x6f\x76\x6d\x23\xab\xf6\x42\x25\x78\x94\xeb\xdf\xa7\x9e\x63\x09\xf1\x27\x23\x74\xee\x94\x33\x67\x7b\xa1\x3e\x45\x1b\xaa\x95\x33\x0e\x66\x0c\x80\x52\xae\x87\x2e\x0e\x32\xe2\xb2\xd1\x28\x6d\x01\xa0\xab\x58\x10\x42\x4e\xd8\xb9\x40\x54\x65\xbd\xeb\xa0\x3b\x69\x83\x84\x67\x6f\xe5\xea\x46\x4a\x03\x44\x6c\x4f\x7c\xd7\xb4\x33\x12\xec\xf1\x51\x36\x04\x64\x57\x1a\xd2\x86\x10\x58\x1f\xba\xdb\x94\x5a\x1d\x68\x18\x1d\xeb\x40\x3a\xa5\x6e\xba\x0b\xb8\x40\x32\x8e\xee\x36\x10\x3c\x7d\xe0\x73\xa6\x87\x9c\x94\x1c\x75\x54\xc6\xf6\xf2\xa0\x80\x80\x9e\xb0\xe5\xbd\x0e\x13\x0f\x29\xa2\x29\xe9\x30\xdb\x01\xfe\xca\xc2\xe0\x36\xbd\xf0\xe0\x01\xe2\xa8\xea\x32\x64\xf8\x64\x9d\x5b\x60\xc2\x91\x03\xf0\xb4\x9c\x24\xc9\x7f\xac\xaf\x7e\x81\x06\x9a\x2b\x26\xab\x3f\x93\x3f\x42\x7d\x81\x27\x2c\x6c\x8b\x7c\xd0\xdf\xb7\xc6\xbb\xe9\xc0\xea\xab\x32\xbb\xda\x22\x18\xb9\x62\x3a\x21\x19\xaa\xb1\xf3\xeb"}, -{{0x77,0xad,0x0f,0x94,0x2c,0x37,0xf0,0x31,0x3e,0x6b,0x04,0x56,0xda,0xba,0xec,0x81,0xb2,0xd6,0x1f,0x6c,0x11,0x8d,0xdb,0x29,0xea,0xf3,0xac,0x5b,0xf1,0x95,0x04,0xd4,},{0x69,0x2d,0x2d,0xa5,0xa9,0x5f,0x48,0x61,0x1a,0x6d,0xa8,0x9c,0xfb,0x3b,0x35,0x40,0xf6,0xaa,0x0c,0x85,0x0d,0x6d,0x98,0xde,0xea,0x87,0x0e,0x39,0x7f,0xed,0xe3,0x28,},{0x69,0x6b,0xd5,0x52,0xdd,0x01,0xdb,0x80,0xb3,0xd6,0x7d,0x61,0xee,0xb7,0xec,0xc5,0x68,0x78,0x40,0x4a,0xb1,0x19,0x44,0x2a,0x1c,0x74,0x22,0x99,0x2c,0xfa,0x35,0xae,0xa9,0x20,0x82,0x5d,0x2d,0xaf,0xd8,0x92,0xad,0x7e,0xb6,0x82,0x5a,0xd9,0x99,0xae,0xe5,0xc8,0x3b,0x7b,0x50,0x79,0x06,0x53,0x4f,0x91,0xac,0xe7,0x59,0xc5,0x51,0x0c,},"\x87\xe6\xde\xad\x2c\x85\x54\x9e\x3d\x8d\x25\x88\xa0\xa3\x36\x06\x03\xa6\x24\xfb\x65\xae\xbb\xc1\x01\xbf\x7f\x1f\xec\x18\xd0\xb2\x8f\xbd\x5d\xba\xee\xd3\x87\x52\xcd\xf6\x35\x5c\xe8\xdc\x84\xe1\x8a\xc1\xa4\x39\x3d\x2a\xb8\x88\x88\x2c\x4f\xf1\xc9\xc8\x13\x7f\x83\xbe\xe3\x63\x36\xbc\xbf\xbb\x72\xd5\x04\x9e\x0a\x40\x08\x74\x51\x4f\xdc\x36\x33\x04\x6e\x89\x38\x3d\xde\xd9\x3c\xa3\x1f\xde\x0d\x89\x8e\x11\xe9\x26\x8d\x3d\x5c\x24\x06\x66\xed\x55\x27\x61\x3d\xa7\x9f\xb7\xe4\x96\x25\xb4\x4c\xde\x78\xb4\x1c\x67\x90\x2e\xb0\x21\x6b\x3a\x7a\x3e\x56\x0e\x26\x1d\x71\xd7\x64\xaa\xcf\x15\x95\x9c\x17\xfc\xd6\x17\x6f\xb2\x5e\x24\x9e\xe6\xbb\x1b\x3b\xd7\xbd\x90\xf6\x0b\x0b\x0f\xfa\x03\x15\xa0\x65\xa2\x4b\xba\xe8\xf2\x55\xbf\x29\x8d\x7e\x4d\x44\xf0\xb4\x30\xc4\x15\xb4\xfb\x36\xcf\xa6\x62\x6a\x83\xf4\x9a\x25\x67\xf6\x24\x4f\x40\xe9\x23\xad\xd1\xd4\x9a\x72\xf5\x7b\x15\x30\xf5\xb3\x79\xde\x3a\x91\xc2\xe9\xa1\xac\x79\xab\x37\xbc\x3b\x9b\xa7\x3d\x88\x28\x13\x6b\xcc\x87\xd2\xc0\x11\x90\xde\x54\x57\xfa\xcd\x90\xf3\x69\x55\x3f\x7a\xc5\x21\xc5\x67\x2b\x08\x67\xdf\xa8\xda\x3b\x95\x2a\xd9\x5b\x67\xda\xb9\x9b\x48\x20\x57\x2f\x2d\x4a\x29\x8e\x95\x18\x63\x77\x79\x28\x9c\x03\x1b\x79\x3d\xee\x85\x9c\xde\x7b\x24\xad\xd6\x49\xff\xf8\x71\x24\x8a\x66\x02\xd2\x51\x62\x79\xda\x60\x58\xcb\xb6\x96\xfa\x8b\x1d\x89\xa2\x0d\x20\x99\xe6\x46\x44\x32\x10\x48\x3e\x5d\x41\x34\xe9\x28\xfa\xeb\x38\xa3\xb5\x08\x19\x9e\x0d\x69\xbb\x55\xee\x34\x77\x42\x05\xc0\xa6\x12\x05\xb5\x0b\x08\xfe\xbe\xaa\x40\x1e\x6e\x3a\x51\xa2\xbf\x98\xef\xac\x78\xb7\xae\x2b\x85\x2c\x53\x95\xa1\x2c\x40\xe2\xc7\xdd\x1b\x20\x25\x04\xb5\xa7\xd2\xf7\xe4\xfd\x4f\x86\x10\x93\x0d\x28\x68\xcb\xa8\x86\x43\x39\xe0\x41\xda\x21\xc0\x71\x5f\x41\xb2\xb2\x3d\x14\xd0\xb5\x45\x48\x0b\xc3\xbd\x7d\x72\x15\xcf\x2f\x81\x6a\x33\x32\x08\x1e\xca\xa0\x8c\x0f\x8b\x99\x52\x52\x51\xf5\x72\x31\xb6\x75\x0c\x2d\xbd\x11\x09\xac\x41\x60\x48\x6b\x76\x83\x24\xb6\xba\xc8\x7e\xf5\xa2\x26\x44\x8c\x43\x12\x40\x32\x8f\x42\xcc\xa5\x86\xbe\x7a\xff\x3c\xbe\x76\x05\xfa\x34\x15\x14\xfc\xcf\xb9\x66\xaf\x3d\x45\x30\xe8\xcd\x90\x37\xa1\x1c\xe5\x93\xc2\xd3\x83\xe1\x03\x5a\x0c\x2e\xda\x09\x8d\xe9\x0d\x50\xc5\x18\x4a\x9c\x01\xb5\x7f\x26\xb9\x4d\xed\xd1\x45\x4c\x34\x06\x37\xec\xcc\xee\x70\x62\x57\x54\xa3\x28\xc6\x5f\x42\x64\x5b\x5e\x1a\x56\x55\xee\xf9\x7d\xfb\x1c\x63\x08\xed\xf4\x9f\xa3\x68\xd1\x7d\x17\xe0\x6a\xdc\x51\x2b\x39\x73\xea\x65\x2a\xc4\x0a\x99\x78\xe1\xbb\x1b\x2f\x86\xc5\xa9\xff\xbf\x60\xdc\xc4\xf6\xbb\xc9\x8a\x64\xf4\xde\x65\xe7\xec\x61\x72\x1e\xde\xb0\xe5\x23\x84\x56\xf7\x61\xd2\xd1\x29\x3a\xf0\xde\x9f\x79\x3b\x11\xd8\xca\xdf\x01\xa9\x43\x19\xa0\x2a\x42\x73\xff\xc4\xd3\xff\xa7\xb3\x4d\x74\xfd\x2e\x0b\x10\x0f\xca\x58\xb5\x32\x5f\x90\x7a\x74\x91\x93\xe7\x51\xd6\xc1\x16\x68\x7a\xee\x37\x47\xb5\x94\x60\xd4\xef\x15\x6e\x72\x47\x6e\xae\x1b\x84\x55\xd7\x6e\x71\xb3\x06\xb9\x81\x29\xb7\x2f\xe1\xcb\x5e\xb4\x05\xa7\xc2\xf4\x32\x7f\x38\x62\xd4"}, -{{0x29,0x32,0x14,0x69,0xee,0x9f,0x2b,0xb1,0x65,0xa0,0x69,0x64,0x03,0x32,0xb4,0x89,0xbf,0x5c,0x3f,0xab,0x68,0x2e,0x93,0xda,0xe9,0xd8,0x63,0x17,0xbf,0x50,0xc5,0x2c,},{0x96,0xf7,0x30,0xf8,0xef,0x89,0x70,0x26,0x8d,0xba,0x0f,0x75,0x70,0x41,0x0b,0x61,0x88,0xa1,0xa3,0xc8,0x63,0x97,0x74,0x09,0x13,0xd5,0x3a,0xda,0x26,0x2a,0xb8,0x7e,},{0x4e,0x1a,0xff,0x84,0x63,0xbc,0xa1,0xb7,0xde,0xb1,0xd3,0x77,0x3d,0xf2,0xe7,0xa0,0x68,0x64,0x11,0x1b,0x6d,0xc4,0x2a,0x62,0xae,0x98,0xde,0xb2,0x31,0x39,0x43,0xb3,0x15,0x3e,0xe4,0x66,0x96,0xb1,0x5c,0x24,0xef,0xc2,0xa8,0x08,0xaa,0xba,0x81,0xc7,0x8e,0x3d,0xfa,0x4d,0xfb,0x50,0xca,0x9f,0xe8,0x44,0x45,0xea,0x68,0xbc,0x8e,0x0a,},"\x9c\x71\x2c\x83\xd5\x4f\x2e\x99\x3c\xa6\x8a\x96\x32\x84\x60\x04\x49\x9c\x51\x95\x44\x8d\xdc\x49\x1c\x3a\x0d\x2e\x3a\x66\x6d\x6b\x33\x09\x8e\x48\x64\xfd\xf8\x6e\x61\x9d\x50\xf1\x0b\x7c\xc6\xc3\x9b\x3f\xf2\x80\x1a\x94\x91\xf6\xfa\x97\xc5\xf1\xc4\xaf\xa7\xae\xff\x31\xd7\x38\xf9\xa7\x68\xa7\x9c\x73\xb2\x55\x77\x31\x0f\xb0\xad\x4f\xaf\x85\x43\xa0\x98\xf8\x59\x57\x1b\x61\x48\xe8\xb5\x29\x26\x44\x57\x57\xd5\x54\x9f\xd2\x5a\x26\x51\x85\x31\x56\x63\x79\xd1\xc2\x74\xe6\xc6\xa9\xd6\x41\x32\xe4\xac\x25\xac\x9a\xf9\x38\x1b\xcb\x88\x53\x32\x11\x3f\x43\x01\x4a\x13\x9a\x81\xf8\xd4\x3c\x8a\x6a\xb5\x4c\x11\xa5\xc9\x2e\x06\x19\x1c\x1e\x51\xb7\x57\xac\x9f\x11\xe3\xdc\x15\xdb\x44\x86\xd1\x67\xff\x9f\x2d\x65\xe2\x3e\x6c\x96\x22\x3d\x9a\xff\x8d\x10\xd1\x50\x2c\xf3\xdb\xce\x5e\x35\x7e\x6b\x12\xdb\xe9\xb7\xe9\x97\xc3\xd0\xa5\x07\xd3\xba\xe3\xcf\xef\x1f\xfc\x8d\x05\x6e\xf7\xdc\x72\xdd\xc1\xc8\x1e\x31\x0a\xd2\x05\xbe\x16\xe7\x7f\x27\x38\x35\x4b\x10\xb4\x84\xd3\x07\x6c\x27\xe6\xb4\xf1\x66\x38\x85\x81\xf3\x50\xbe\xfe\x22\xfb\xb0\x82\xb5\x41\x21\xee\x59\xec\xc7\xae\x5d\xec\xe8\x98\x82\xac\xf2\x6c\xb7\x47\xff\xaa\x3e\x2d\x05\xa6\x96\xf6\x0f\xd9\xe8\x29\xc7\x09\xd8\xf0\x2d\xaf\x53\x7b\x23\x69\xb8\x91\xfe\x6c\xcb\xf8\xdf\xcd\xd7\xf4\xa3\x64\xb1\x99\x85\xbe\x7e\xde\xc6\x7d\xdc\x1d\xb7\x13\xc0\xa9\x0f\xaf\xa4\x88\x37\x77\x25\x62\xde\xac\xc2\xd2\xa0\xe7\x89\xe1\x8a\x8b\x5b\x3b\xd9\xe0\x83\xea\x92\xff\xfc\x31\x83\xd5\xd4\x14\x15\x32\x59\xb3\x3a\x43\x29\xcf\xc8\x08\x24\xeb\xcb\xe0\x44\xa7\xe3\x3a\xb8\xa2\x4f\xde\x54\xbd\x95\x20\xae\xa2\x84\xb0\xc4\xc4\xfa\x94\x27\xd2\x51\xc0\xdd\xd0\x13\xec\xdd\x82\x90\xef\x55\x65\xf6\x08\x50\x8e\x36\x35\x89\xe5\x29\xd8\x4f\xf0\xf2\x6f\x9e\xcb\x03\x05\x2d\x58\x97\xfa\xbc\x91\x7e\x56\xe6\x01\xb6\x4a\xbf\xe5\xa1\x7c\x39\x50\x28\x9d\x0c\xdc\xaf\x1f\x60\x05\xa9\xf8\x10\x6f\x43\xe1\x7a\xdc\xaa\x2d\x1e\x26\x91\x66\x76\x2f\x80\x54\xde\x05\x13\x5d\x5d\x13\x93\xd7\x00\x0a\x15\xb8\x7b\xd6\x88\x46\xa8\x9d\x5b\xc2\x28\x63\x32\x51\x51\xaa\xc8\x43\xf7\x22\x78\xae\x6f\x4a\xf7\x2a\x4e\x44\x9a\xdb\x7e\xae\x6d\x43\x6a\x1e\xc7\xe5\x8e\x59\xb7\xb8\xbb\x9e\xf0\xdd\xaa\xa0\x01\x82\x6f\x8d\xcb\x44\x64\x79\xde\xaf\xd8\xb8\xd5\x42\x04\x1c\x19\xa0\x5b\x1e\x0e\xe4\x7b\x46\x40\x91\x0c\x31\x93\x0c\xa4\xe2\x0b\x10\x57\x58\xec\x75\xf1\x95\x03\x56\x94\x7f\x62\x61\xd0\x03\x7f\xe3\x07\x73\xa3\xec\xe6\xa9\x6c\x8d\x54\x33\x33\x3d\x82\x2c\x27\x77\xef\x7f\xf8\xbe\x60\x33\x34\x5b\x50\x55\xd5\x8f\x5e\xb3\x72\x9a\xf5\xae\x88\x24\xf3\x31\xee\x07\x31\xc8\x9b\x20\xac\x11\x8f\x55\x04\x27\xcd\x95\x8a\x55\xf6\xb1\xa2\x88\x8a\x08\x7b\xb7\xdb\x55\xbf\xc7\x3b\x29\x42\x9b\x44\x48\xdb\xe9\x11\x9c\x45\xa8\x73\x39\xb4\x49\x7a\x69\xa4\xcf\x83\x3e\x8f\x37\x70\xcc\xe5\xe0\x1f\xaf\x5e\x73\xbb\xaf\x62\x76\x83\xc0\xa2\x8c\x73\x05\x2f\xbe\xce\x20\x30\x43\x38\x9d\xfb\xfd\x45\x49\x5e\x51\xda\xb8\x6a\x25\x2e\x5b\xc1\xb4\xb7\xfe\x28\x07\xe3\xd0\xe2\x36\x3b\xea\xb5\x1c\x67\xfb\x31"}, -{{0x04,0x65,0x77,0x50,0x49,0x7e,0x68,0x15,0x2c,0x43,0xce,0x34,0xa5,0x8d,0x21,0x06,0xe6,0x4c,0x55,0x7c,0xd7,0xa8,0x4e,0xf0,0x5d,0x9e,0xb8,0x2e,0x6b,0xcb,0x05,0xf5,},{0x3b,0x3a,0x19,0x47,0xb4,0xcb,0xf6,0x0b,0x82,0x6d,0x60,0x9f,0x19,0x2d,0xc2,0x30,0xaa,0x9b,0x9b,0xaf,0x4c,0xd6,0xa6,0x09,0x2e,0x49,0x5f,0x1d,0x2e,0x47,0xad,0x62,},{0x7e,0x2e,0xae,0x5a,0x29,0x3f,0x41,0x83,0x91,0xf6,0xd8,0x5a,0x79,0x94,0xb0,0x7c,0x45,0x22,0x80,0x01,0x7e,0xe6,0x53,0xbf,0x61,0x7a,0x8d,0x5b,0xe2,0x4c,0xbb,0x5d,0x0e,0xfd,0xfb,0x7f,0x7f,0x00,0x13,0x12,0x26,0x0f,0x34,0x4e,0x6f,0xb9,0x15,0xad,0x8d,0x7d,0xe9,0xc0,0x51,0x98,0x27,0xc0,0x57,0x26,0xf9,0xce,0x25,0x45,0xdd,0x0b,},"\x29\x48\x22\x7a\x89\x0f\x6f\x84\x5b\x77\x5e\x62\xc5\x3a\xf3\x80\x50\x64\xa1\x57\x64\x46\xf0\x85\xd9\x0f\x8b\x9a\x5e\xd6\x8d\xf1\xea\x39\x3c\xe4\x79\xc4\x41\x41\x49\xa9\xec\x5a\x17\x10\x36\x42\x4d\xff\x03\x44\xb4\x95\x8f\x61\x32\x29\x8d\x0e\x24\xc9\x26\xd2\x8a\xd9\xd7\x9f\x98\xc6\xe6\xbc\xf1\xc5\x76\x76\x06\xec\xd2\x91\xc6\xad\x47\xb4\xf9\xfb\x2b\x02\x01\x15\x5a\xda\x62\x7b\x7a\x1f\xd5\xb0\x74\x19\x87\x40\x83\x05\x9e\xb5\x2b\x2f\x6e\xc2\x28\x18\xb7\x82\x46\x22\x8f\x3f\xe6\x35\x5d\xfd\xa7\x0e\xbb\x9b\xbe\x73\x22\x93\x78\x73\x63\x99\x55\x7c\xe2\x4b\x30\xbf\x64\x5a\x14\xe2\x25\x6f\x70\x01\x9b\x33\x36\xb2\x03\xfb\x77\xc6\xec\x94\xa7\xa2\x63\x48\x88\xfe\xea\xd4\xd7\x2c\x23\x91\xe9\x9e\x8c\x8d\x53\x3f\xd8\xa4\x2b\x08\xc1\x1f\x88\x7a\xb2\xde\xb6\xeb\xbf\xe3\xd2\x51\xde\x63\x53\x6c\x36\xcd\x53\x42\x23\x98\xe5\x44\xcf\xf8\x7b\x07\xa6\x33\x49\xfc\x50\x85\xdd\xe9\x3a\x1b\xfd\x71\x71\x13\x3a\x20\x43\x98\x1f\x60\x75\x22\xc8\x13\x3c\x63\x42\x8d\x1b\x92\x62\x6c\x79\xb7\x35\x8e\x70\x21\xcf\x1f\x41\x2a\x78\xaf\xa7\xcb\x3f\x59\xff\xef\x92\x79\x88\x5a\x5b\xdb\x24\x66\xac\xd3\x4c\xd5\x15\x80\x83\x0b\x83\x51\xeb\xd4\x40\xa9\x66\x23\x90\x7a\xd1\xf4\xb5\x62\x03\xf5\xe1\x59\xa4\x29\xe3\x54\x6e\xad\x0c\x01\x1d\xbe\xd0\x90\x28\x71\x7e\x3c\x3d\xfe\xd3\x91\x97\x76\x4d\x4d\x24\x5e\xf2\x28\xb9\x80\x44\x71\x8e\xf4\xd8\x82\x2f\x21\xb2\xc5\x68\x50\x38\x47\x3b\xf9\x3d\xc0\x93\x74\x51\xeb\x02\xd3\x1a\x46\xc8\xdc\x7e\x94\xc3\xe8\x67\x8c\x83\xb9\x8a\x43\x81\x8f\x12\x5b\x52\x8b\x47\x6a\xad\x31\xd1\x58\x4f\xfd\x48\xf1\x49\xe5\x73\x6e\x58\xf9\x42\x05\xd3\x88\x9e\x56\x7e\x4d\xd1\xea\xc2\xfa\xc1\xf8\xf4\xdc\x54\x0e\x53\x22\x46\x0f\xb9\x40\xe1\x2e\x93\xc4\xc9\x8d\xed\x19\x41\xc1\x90\x4f\x96\x7f\xb4\x64\x36\x84\xc1\x9a\x4d\x5c\x44\x1d\x60\xb0\xe9\xf4\x08\x55\xe5\x23\xfe\x7f\x99\x10\x76\x57\xa6\x80\x76\x27\x5b\xf8\x4b\x7c\x69\xa3\xf2\xb3\x85\x5b\xc8\x02\x6b\xa9\xb0\x0b\xc6\xfe\x34\xb9\x9d\xa0\x63\x17\x00\xa6\x7f\x52\xb3\x4e\x17\x96\x33\x98\x87\xa4\x83\x05\x12\x1d\x53\xab\x44\x40\xfc\x4b\x5c\x9b\xf7\x23\x94\xd5\xed\x37\x2f\xf1\x8c\xa3\xf0\x07\xbd\x02\xdf\x65\x1d\xc3\xac\x43\x82\x75\xf1\xa3\xe5\x24\x22\xb8\x6c\x45\x86\x76\x6a\x21\xcd\x89\xf8\x05\x80\x5d\xbb\x44\xfd\x89\xfe\x24\xfb\x2c\x0b\x40\xd1\xb7\x54\xc3\x35\xdb\xaf\xfc\x3b\x3b\xb8\xbb\x46\xc7\x4c\x36\x37\x45\x04\x04\x2d\x86\x78\x92\x27\x59\x98\x62\x31\x2e\x99\xca\x89\xeb\x50\x4c\xc3\xd7\x5d\x19\x49\x5a\xa8\x6b\x20\xb2\x73\x6b\x12\x1b\xb2\x07\x5c\x88\xed\x4a\x3f\xbd\xaa\x6b\x2c\x3f\x76\xd1\xff\x55\x25\xd3\xa2\x86\x3e\x4d\x83\xc7\x2b\xfe\x01\xe1\x02\x78\x80\x94\x74\xe1\x82\x2d\xe2\xd9\x62\x83\x48\x93\x20\x02\x96\x11\xaa\x9d\xff\xc4\x82\x9d\x66\x86\x9e\x63\x49\x4f\x9a\xad\xe7\x0b\x77\xa7\xb8\x0f\xbc\x93\xe3\xde\x4d\x93\x59\x13\x75\x2d\x04\x5e\x13\xb3\x12\xc5\xd0\x82\xf6\x24\x2d\x49\x85\xb0\x53\xb3\x78\x3e\xb0\x2c\x66\x14\x96\x3d\xc0\xd5\x5d\x4c\xbe\x88\x7b\xae\x29\xcc\x18\x97\x9e\x5e\x2e\xa9\x45\xbc\xd4\x0d\x89"}, -{{0x8b,0xd9,0x90,0x70,0xc5,0x0a,0x9f,0xa4,0x18,0xef,0x7f,0x75,0xc0,0x01,0x29,0x91,0x6a,0x41,0xc8,0x60,0x70,0x96,0x1c,0xcb,0x2b,0x20,0x2b,0xe1,0x8c,0x2d,0x10,0xd7,},{0xdd,0xd7,0x33,0x08,0xfc,0xe8,0xca,0x65,0x52,0xd0,0x39,0x42,0x8c,0x7a,0x1a,0x94,0x92,0x33,0x20,0xa3,0x1c,0x0f,0x58,0x0d,0x3c,0x23,0x52,0x80,0xf0,0x3c,0x18,0x30,},{0xb1,0x4a,0x7b,0x26,0x20,0x12,0xc5,0x90,0x9e,0x21,0xd5,0x87,0xfb,0x4f,0x29,0xa9,0x09,0x3c,0x8e,0x1c,0x29,0x99,0x81,0x6a,0x82,0x11,0x8f,0xef,0xbf,0x10,0xe6,0x8e,0xa8,0x98,0xbf,0x0d,0xa1,0x8e,0xbf,0xd0,0x34,0x1e,0xa8,0xf8,0x2a,0x18,0x44,0xc8,0xe0,0xdd,0x53,0x06,0xe5,0x09,0xb9,0xd0,0xc3,0x5b,0x47,0x3a,0x7d,0x20,0x95,0x07,},"\x48\x5f\x8d\x68\x0f\x79\xee\x2d\x82\x8b\xe7\xd0\x18\xa6\x5e\x0b\x64\xb0\xf0\x18\x48\x19\x86\x3e\x71\x10\xee\xa8\xf2\x99\xa7\x2c\x4d\xc8\x7f\x8e\xe8\xa8\xae\xaa\x81\xaf\x91\xdc\x71\xad\xea\x79\xfc\x97\x97\x42\x1c\xcc\x64\x6e\x6c\xd5\xdd\x48\xb4\xde\xc1\xde\x96\x86\x93\xfb\xce\x0d\x00\x21\xa3\xd9\x8d\x38\xa8\xbb\xc5\x81\x95\xe6\xdf\xc3\xb5\xe1\x46\x1b\x2a\x59\x41\x03\xe8\x0a\x29\x44\x1d\x5a\xaa\xf8\x89\xe3\x1c\xc8\x65\x14\x1f\x0c\x6b\x2c\x8c\x81\xf7\x21\x67\x9e\xa2\x39\x4e\xc6\xe4\x08\x1e\xc2\x03\xc2\xea\x39\x7d\x94\x84\x75\x7a\x7a\x0e\xcd\x53\xe6\x52\xdb\x9d\xf1\x7b\xea\x0e\x32\xfe\x8b\x2c\xbc\xe0\xd1\xd9\x7b\x96\x1e\xd7\x4e\x8e\x62\x2b\xcd\xd3\x55\x8b\x7c\x48\x69\x5a\xdf\x18\xaa\xe6\x11\x0e\xa9\xa3\x39\xb9\xda\x40\x7a\x9e\xda\xf2\xab\x08\x1a\x68\x1e\x18\x32\xcc\x21\x5b\x1f\x08\xa6\x7d\x55\x9a\x47\x44\xaf\x7c\xd5\x03\x18\xc2\x06\xee\x91\x15\x75\x82\xf8\x2e\xb6\xc0\xfc\x29\x02\x7b\x44\x61\xc3\x07\x33\xb8\x16\x9d\x14\x81\x32\x2c\x48\x60\x50\x9b\xa0\x96\xba\xcb\x71\xa5\x79\x24\x67\x51\xd5\x67\x54\x0e\x41\x43\x1e\x14\xf1\xb4\x6e\xf1\x6e\xba\x27\x61\x04\xbc\x01\x65\x0d\x5c\x49\x26\xe4\x7c\x9c\x60\x40\x78\x4b\x04\x3c\xd0\xaa\x48\x54\xef\xe8\x79\x7f\xd0\x46\x2d\x45\x39\xf3\x80\x35\xae\xf0\x8b\x45\x77\xc1\xa9\x11\x8d\x00\x4b\x6d\x01\x86\x2f\x52\x76\x77\x6d\xfe\xf1\x37\x18\x64\xf1\x55\xac\x0f\x07\x83\x89\xc2\x05\xcf\x05\x38\xd8\x5f\xa3\x48\x24\x4d\x7a\x42\x29\x11\x31\x0f\xf6\xc1\x01\x32\xb1\x59\x8b\xb4\x45\xc7\xe2\x07\x7b\x76\x3c\x47\x3d\x1e\x7a\x61\xa3\x8b\x64\x92\x9a\x64\x8b\x60\xb2\xe5\x43\x54\x37\x39\x22\x4b\x40\xfb\xf6\xd8\x7f\x10\x79\xc3\x0b\xc8\x73\xac\x38\x99\x1d\x51\xb8\x9e\x9d\x26\x1c\x4b\xcc\xb3\x75\x35\x5c\x07\x2c\x1e\xa2\x0e\x4f\xf9\x1d\x55\xd9\xf7\x54\x4e\x90\xd1\xc6\x64\x6c\x59\xaf\x72\x42\x4d\x8a\xaa\x8e\x0a\xed\x07\xb3\x88\x9d\x4e\x45\x0c\x12\x09\x68\x4c\xe1\x38\xd0\xc9\xda\x07\x95\x25\xf5\xaa\x02\x05\x0a\xf5\x70\xe4\x31\x5c\x2f\xa8\xb0\x99\xb7\x76\x5b\xfb\xb8\x94\xfa\xd3\x59\xb8\xe2\x48\x04\xec\xe0\x52\xac\x22\xa1\x91\x70\x53\x35\xe9\x88\x40\xa6\x24\xe4\xcb\xf3\xa1\xa1\xa3\x27\x81\x27\x85\xb2\xc0\xf5\xd6\x38\x14\x57\xb7\x2f\xdb\x63\x3e\x81\x93\x8b\xbb\x54\xb8\xc3\x7c\xcc\xb5\xd5\x9c\x58\x27\xc7\x68\x3a\x52\x47\x54\x49\x77\xe9\x84\x44\x21\x78\xd0\x85\x29\x06\xca\x6f\x94\x5c\x42\x29\xeb\x08\xad\x27\xe6\xc2\x75\xd7\xb4\xec\x8d\xc2\x5f\xb2\x81\x93\x37\xe5\x3e\xad\x6c\x7a\xa7\x87\xf9\x1a\x7d\xc6\xdd\xaf\xd5\x36\xee\xfc\xbd\xec\x2c\x50\x16\x7b\xe3\x43\x06\xa8\x2e\x16\xd5\xd5\x2b\x3b\x1b\xe0\x08\xa7\xa6\x11\x27\x4c\xe2\xcf\x8d\x62\xe3\xb9\x00\xc0\x99\x43\xbe\x70\xcc\xc7\x7b\x07\x06\x37\xc2\x50\x61\xd6\x1b\xe9\x10\xee\xf5\x0d\xf1\x87\x44\xc3\x3e\x76\xf6\x70\x1e\x0a\x8f\xf6\x29\x7f\xa6\x7e\x4b\x41\x08\xc1\x37\x56\x72\x7a\x9d\x74\xbc\x9e\x17\x98\x3e\xec\x08\xf8\x66\xb7\xc7\xff\xb3\x7f\x3c\xcb\x01\x41\xa8\x0f\xef\xf6\x32\x2b\x2a\xc6\x2b\x84\xce\x27\x97\xfd\x98\xd6\xff\x26\x9a\x41\xa0\xc3\x84\x82\xdb\x67\x98\x62\xa3\x8c\xd2"}, -{{0x1a,0xf4,0xcf,0x6d,0x24,0xab,0x37,0x82,0x86,0x7d,0x96,0xa1,0xc2,0x75,0xce,0xeb,0x02,0x2c,0x69,0x1a,0x30,0x8e,0x62,0x45,0x66,0x5d,0x61,0x6b,0xf6,0x7c,0x2c,0x32,},{0x19,0xd3,0x17,0xea,0x98,0xd3,0x5b,0xa5,0xfa,0x67,0xc1,0x2e,0xcf,0xb3,0x27,0x50,0xdf,0x27,0x5d,0x7a,0x45,0xb8,0xe2,0x11,0xa7,0xac,0x47,0xed,0xe7,0x71,0x2d,0x9f,},{0x7e,0xb4,0x6c,0xd0,0xde,0x31,0x55,0xb4,0x37,0x47,0xd7,0x32,0xf1,0x04,0x5d,0x8e,0xf7,0x44,0x92,0xad,0x82,0x7a,0x22,0x45,0xbd,0x17,0x10,0x28,0x28,0x44,0x2e,0x43,0xa0,0xce,0x7e,0x8b,0x26,0x8e,0xd7,0xfd,0x8d,0x3e,0x7b,0x28,0xf0,0x72,0x79,0x5d,0xa3,0xe0,0x70,0xf1,0x2b,0xc4,0xe2,0x3e,0xae,0xf5,0x7b,0x85,0x3c,0xee,0x88,0x0a,},"\xf4\x45\xfd\xcf\xe2\x8c\x17\xbd\x44\x27\xae\xa5\x67\x6c\x0e\x12\x80\x84\x15\x97\xe9\xd6\x6d\xe7\xd7\xa7\x17\x23\x11\x09\x39\xbe\xd0\x0f\x4e\xba\xf9\x60\x3d\x53\xc9\xcb\xf6\x27\x1b\xe5\x47\xaf\x29\xb2\xa0\x45\xec\x41\x28\x8a\x7b\xb7\x9d\x66\x2d\xc2\x10\xe2\x15\x95\x7f\xa8\x46\x88\xc9\x16\x54\x3e\x56\x17\xf5\x60\xe4\xd3\x8f\x73\xba\xef\xc3\x7e\x11\x91\x4e\x47\xc5\x15\x06\x78\x51\xe8\xed\x21\x39\x3e\x13\xdd\x19\xed\x9b\x73\xd9\x89\x45\xfc\x82\x6a\x25\x8e\x95\x7d\xc0\x83\xdd\x8e\x53\x5c\x30\xa5\x4b\x42\x66\xdd\x71\xd1\x13\xce\x85\x6b\x46\x28\x2a\x18\x03\x36\x27\xa9\x8e\x64\x72\xcc\xb4\x63\xed\x3d\x96\xfa\x7b\x35\x5d\x3b\x2c\x2a\x2b\x60\x10\xdd\x14\xf4\xea\x39\x65\xdd\x87\xbe\x1c\x42\x9b\xde\xa8\x30\x0b\x4b\x0b\x44\x45\x86\x35\xb4\x97\x9f\x5e\x3e\x8e\xb5\xc6\x18\xd4\xe1\x3e\x1d\x68\x8b\xf8\x8c\x7e\x4a\x3d\x93\x8e\x84\x33\x6d\x67\xbe\x68\xdf\x34\x35\xc5\xc9\x90\x86\x32\x1c\x02\xe1\x3b\x4a\x12\x52\x4b\x34\xe4\x6a\x0b\x4d\x27\xf3\x0d\x7e\xd4\xf5\xce\xcb\x36\xde\xad\xf0\x9e\x7e\xfc\xc7\x55\xca\x66\x75\x68\x29\x79\x14\xc6\xbc\x24\x06\x27\xd9\xd0\x9a\xac\xf8\x54\x15\x41\x2c\x06\x35\x62\x34\x53\x27\x8d\x9b\xf0\xe1\x0e\xec\x65\xfc\x72\xaf\xff\xfa\x93\x92\xdc\x78\x81\xd1\xe5\xc7\x60\xa4\x02\x80\xf1\x6b\x14\x75\x12\x7b\x91\xb6\x9c\xcb\x65\xdc\x4b\x35\xde\x10\xf9\x43\x25\xc0\xcb\xe1\xc4\x70\x19\xa2\xea\xf2\xb4\xba\x92\xd7\x85\x22\x9a\xac\xfa\xd1\x82\x6e\xbb\xde\xbe\xfb\x7d\xad\x4b\x05\xf8\x82\x43\xe1\x5f\x27\x97\x66\xe3\x32\x1d\xd8\xdb\xa6\x50\x44\x4d\x81\xfb\x08\x78\x76\x7a\x9c\x63\x53\x4b\xb4\xba\x21\x28\x5a\x24\x16\xcb\x8f\x85\x6d\x11\xa9\x6e\x0a\x8c\x8d\xe1\xe1\xa7\x51\x32\xf1\x56\x4c\xd9\x94\x99\x56\x90\xbb\xed\x2e\xe1\x54\x53\x7f\xb6\xf2\x79\xfb\x09\xc8\xde\xa6\xf6\xaf\xab\xc6\x28\x56\xe3\xd1\x28\xfd\xfa\x79\xfc\x49\x76\x19\x3b\xb9\xb3\x36\x86\x1e\x47\xb5\x6d\xc2\x58\x23\x93\xd2\xe5\x44\x65\x1a\xc8\x5b\xc5\x8e\x9e\x6a\x94\xdc\x4c\x39\xc4\xef\x72\x53\x8a\x14\xf8\x56\xcd\x95\xc3\xe2\x79\x0a\xde\xe0\x3a\xb2\xe5\x2c\xa0\xae\x47\x1d\xe5\x02\xcb\x19\xe6\x76\xaf\x35\xf5\xf9\x3d\x84\x0f\xef\x96\x06\xcb\xe9\x2d\x8b\xc2\x50\x06\x10\x5d\x92\x34\x45\x88\x83\x88\x42\xc3\xbe\x50\x5c\x73\x50\xe3\x51\xb7\x35\xe6\xcc\x6f\xb7\x92\x75\xb2\x7b\xd9\xeb\xd3\x6b\xa4\xd0\x60\xac\xee\x73\xb5\xa3\x15\xce\xff\xab\x86\xd0\x6f\x21\x68\xa6\x70\x65\x57\x81\x96\xa0\xed\x04\xa4\xdd\x71\xd6\x73\x48\x37\xdb\x08\x38\x57\xab\x1e\xb5\xe0\xee\xc4\xff\xba\xc9\x54\x4f\x4e\xc1\x9b\xde\x19\x4d\xf8\x4b\x1c\x84\x83\x41\x57\x4b\xf1\x0d\xae\xe8\x5b\x81\x78\x19\x6f\xb6\x08\x12\x3a\x80\x81\x71\xd7\x3c\xe4\x20\x6a\xd6\x52\x16\xad\x1a\x5c\xbd\xe4\x0b\x19\xd6\xae\x7f\x40\xdf\x97\xab\x84\x32\xe2\xc5\x3a\x50\x4e\xd1\x22\xe2\x5f\xb7\xa5\x1c\x14\x35\x4a\xb3\x92\x8e\xde\xb3\x9c\x29\xeb\x24\x6b\x74\xa0\x76\xf8\x9d\x03\x50\x4f\x40\x1b\xd1\x76\xb5\xcf\xfe\xe4\xb9\xdb\x09\x7c\x45\x76\x4f\x51\xaa\x37\x67\x04\xb5\xa7\xf2\x10\xb3\xf1\xa9\x05\xe2\x5d\x67\x00\x2f\x65\x57\xeb\xb7\x49\x73\x7c\xda\x31"}, -{{0x2a,0xac,0xc8,0x19,0x7f,0xf8,0xfa,0xe1,0xc1,0xcf,0x38,0x62,0xe3,0xc0,0x4a,0x21,0x78,0x29,0x51,0xf8,0xe4,0x8e,0x40,0xb5,0x88,0xf8,0xbc,0x74,0x60,0xc3,0x0a,0x03,},{0x9a,0x1b,0x01,0xe2,0x15,0x4f,0x1c,0x36,0xa8,0xe1,0x6b,0x79,0xee,0x7d,0x2d,0x05,0xb8,0x71,0x2e,0x0d,0x27,0xa0,0x61,0xa6,0xd4,0x1d,0x47,0x57,0x78,0xb0,0xdf,0x8c,},{0x64,0x7c,0xdd,0x6c,0x1a,0x67,0x29,0x0e,0x57,0x67,0x6a,0x78,0x11,0x3a,0xaa,0xdc,0xa6,0x9a,0xc5,0x7b,0x99,0x77,0x15,0xc5,0x09,0x89,0x5b,0x8c,0x5c,0x94,0xe8,0x2c,0x0b,0x6a,0xce,0xcc,0xf3,0xba,0x8b,0xd7,0xcf,0x61,0x75,0x2b,0x1b,0x19,0xd1,0x3b,0x49,0xf1,0x5f,0x8b,0xfa,0x04,0x6e,0xb4,0x42,0xa5,0x5c,0xd5,0xba,0xb1,0x42,0x02,},"\x5d\x82\x75\x2c\xe5\xda\x31\x80\xfa\xf4\x78\x7a\xed\xfb\x19\x29\x4b\x43\x48\xa1\xd9\x20\x2c\x85\x39\x83\x31\x32\x3e\x0f\x42\xb0\x83\x52\x27\xe6\x8e\x11\x56\xf2\xd4\xba\x2f\xe4\x50\xe6\xd6\xef\x2b\x92\xd8\x9b\xbb\xe4\x09\x6e\x12\xca\x83\x97\xeb\x2f\x45\xe6\x76\xf1\x67\x3a\xa4\x1c\x95\x9f\xcd\x30\xd5\x57\x88\x53\xb5\xdb\xd1\xc0\xd5\xb3\xa0\xf0\xd8\x70\xec\xa7\x1e\xa1\x33\x90\x11\x1b\x25\x8f\x65\x48\xb3\x2f\x37\xa0\x5e\x97\x44\xa6\x56\xfd\x77\x8d\x65\x72\x19\x65\xc6\xd9\xb3\x28\x60\x0b\x45\x70\x47\x70\xe0\x4b\x09\x97\x90\xaa\x78\x84\xf0\x0d\x7b\xb7\x65\x9e\x33\x72\x10\xbd\xc2\x3e\xaa\x71\xd7\xb0\x16\x03\x0a\xca\x62\x23\xb5\x56\x9b\xdf\xc2\x90\x81\x1a\xac\x40\x95\x24\xdc\xcb\xf9\xba\xbc\xbe\x4b\xf2\x09\x46\xb5\x44\x31\x7c\xa6\xf2\xf9\x18\x31\xc7\x9f\xb2\x73\xb6\x40\x4e\xb4\xe6\x1e\x1f\x7b\x10\x6e\xbd\x0d\xb9\xf2\xb1\x97\x4d\x2f\x03\x1b\xce\x25\x80\x36\x06\x55\x2c\x34\x41\x65\x5e\xfc\xf2\xc7\xea\x52\xad\xcb\x30\x99\x3d\x85\xf2\xdd\xa7\x96\x03\xe9\x41\x5a\x02\x32\x45\xa6\x6c\x07\xa9\x56\x93\x31\x46\xf5\x3c\x99\x3c\x08\x89\x18\x08\xb8\x16\x6b\x30\x72\x1f\xbd\x1f\x8a\x1b\x93\x7d\x14\x07\x0d\x78\x6e\x9e\xb4\x51\xf2\xab\x51\x42\xf8\x3a\x60\xf3\x5d\x76\xad\x8b\x81\xd6\xa5\x7c\xf3\x68\xfc\x6f\xca\xcc\x0c\x47\x58\x44\x0d\x9c\xd5\x95\xb1\xb0\x94\x2a\x36\x55\xe2\x50\xda\x98\x3b\x72\x41\x54\x6d\xcf\xbe\x0a\xe8\x10\x77\x65\x02\x95\x40\x9f\xf9\xe9\x09\x77\xfb\x99\x60\xcb\xf4\x0a\x2a\xf5\x17\x74\x02\xba\x2f\xaf\x50\xdb\x6f\x1a\x73\x65\xcf\x99\xe9\x92\x42\x9e\x38\xdb\x43\xea\x83\xfd\xdc\x95\xa6\x48\x67\x6c\x0b\x16\xbc\x95\x2b\x15\xde\x99\xd5\x2f\x6b\x52\x33\xda\x4e\xae\x19\x78\xe8\xba\x25\xe6\x23\x5a\xfb\xc5\x11\xc7\x6c\x4c\x87\x4c\x92\x37\x92\x2b\x1c\xef\x08\x47\xd0\x7a\x80\x20\x0c\xba\xe3\xc7\xc8\x1f\xcb\xd0\xd1\x72\x52\xed\x8c\x61\xad\x19\x54\xfc\x86\x2e\x1e\x04\x44\x4c\x32\x08\x6f\xee\x38\x0d\x1c\x17\x54\x13\x22\xb9\xa6\x0d\xa6\x62\x35\x2e\x21\x0e\x9a\xe2\x15\xe3\x53\x29\x6d\xb9\x22\x33\x9a\xa1\x7d\x21\x73\xec\x31\xf1\xc5\x30\xa2\x4b\x1f\x34\x8a\x31\x57\x2e\x14\x69\xca\xac\x80\x8f\x9c\x76\xec\x27\x31\x87\x3b\x80\x3e\xad\x3e\x54\xea\x24\xbc\x24\x49\x9b\x97\x04\xb3\xbd\xce\x81\x38\x9b\x9d\x14\xd4\x95\x27\xc0\x4b\x3b\xb9\xe3\xba\x6d\x94\x6c\xea\x58\xcf\x78\x6d\x4d\x28\xb8\x9b\x41\xc5\x82\x74\x03\x5a\x86\x90\x5a\xd9\x57\x58\xc3\x16\x13\x66\xab\x93\xda\x81\xe6\xb4\xc8\x08\x36\x4e\x08\x7d\xae\xea\x4c\x4c\x5c\x2a\xa6\x87\x19\x37\xc5\xfe\xab\xa2\x14\x9f\x01\xf7\x38\xf4\x53\x96\xe6\x6e\xa8\x06\x32\x21\xe1\xc8\x1c\x05\x25\x5b\xa5\x64\xad\x44\x0c\xb5\xd0\x7c\xbd\x4b\xab\x94\x1e\xa5\x93\x24\x49\x30\xbc\x5c\x28\x9b\x31\x65\xd3\xec\x88\x47\xeb\xc4\xb6\x74\xc0\xa4\x9f\x91\x69\xad\xef\x78\x6d\x77\x67\xbc\x8f\x21\x3d\xb7\xd9\x5c\x06\xe9\x9b\xc1\x1e\x20\x00\x55\xb6\x5e\xb7\x9a\xda\xa0\x1b\xcd\x2c\x85\xda\x43\xce\x63\x70\xe1\x2e\x34\x9b\xf6\xd4\x75\x48\x7a\xff\xdf\x92\xe2\x0a\x3a\xcd\xed\x1d\x76\xf9\xe8\x3e\x91\x9e\x98\xde\xf1\x95\x07\x2a\x50\xd0\xc5\x71\xdd\x25"}, -{{0xff,0x86,0x21,0x56,0xc7,0xea,0xb6,0x81,0xc9,0x5e,0xff,0xf8,0x00,0x3e,0x00,0xa1,0x4f,0x1f,0x0d,0x50,0x5d,0x55,0x07,0xe6,0xe5,0xb3,0x91,0x79,0xdf,0x9b,0x1c,0xda,},{0xe1,0xb8,0x9f,0xb3,0x11,0x14,0xea,0x46,0x10,0x7f,0xfd,0x03,0x29,0xf1,0x06,0x64,0x28,0xde,0x54,0x70,0x8e,0xdb,0xec,0xf3,0xed,0x9d,0x47,0x08,0xcd,0x14,0x3f,0xe2,},{0x4b,0x81,0x37,0x04,0x2d,0x67,0x84,0x75,0x7d,0x4a,0x9c,0x06,0xbc,0x74,0x32,0xf4,0x80,0x9b,0x1c,0x6a,0x90,0x35,0x42,0x73,0x6d,0x9a,0x57,0x66,0x8c,0x20,0x84,0x5c,0x17,0xd4,0x68,0x55,0x70,0x85,0xc5,0x7f,0xb6,0x32,0x13,0xda,0xd3,0xbe,0x0f,0xa3,0x6a,0x11,0x8f,0x7c,0x1a,0xef,0xf2,0x56,0x2f,0xf4,0xb8,0x88,0x8c,0x26,0x90,0x0e,},"\xb3\xd1\xdb\x72\xa6\xa9\x85\xec\xd7\x0a\x2c\xff\x6c\x18\xc1\x79\xe2\x17\xd4\xf4\x10\xfd\x39\x34\x96\x96\x85\x90\x1b\xd0\x71\xbc\xe6\xc2\xfb\x67\x63\xe1\x0c\x6f\xa1\x6e\x75\xa1\x17\x60\x66\xb8\xec\x81\xae\x3a\x80\x39\xe7\x1d\xc2\xcd\xc6\x4a\x40\xfd\x62\xb7\xce\xe7\xbe\x4b\xa0\x33\x2f\xe4\x5d\x0b\x60\x15\x86\x52\xe3\x3f\x8d\x3a\xff\x3c\xb4\xd6\xb0\x21\x74\x4d\x0d\xd1\x78\xb1\xbf\x0a\x1c\xc1\xd3\xfe\x93\x21\xbe\x28\x42\x1e\xb8\x82\x63\xa1\x24\xf4\x97\x92\xd0\x79\x47\x5a\x8c\x55\x5f\xf5\x69\x08\x73\x51\x4b\x5d\x48\x3e\x53\x21\x7e\x0c\xbb\x12\x86\x2b\x85\x0f\xe3\x90\xc8\xf8\x30\x08\x08\x6e\x64\x9a\xc9\x04\xb0\x18\x35\x0a\xb4\x91\x57\xee\x9b\xca\xe6\xc0\x7a\x4b\x87\x8b\x48\xe2\x5e\x98\x4f\xbb\x4d\x36\xb6\x1d\x68\x9b\x13\x46\x8a\x28\xd1\xe3\x87\xe0\xe8\x86\x57\xf8\xc8\xac\x95\x86\xa6\xe2\x6c\xf9\x4d\xff\x6f\x82\x64\xe3\xff\x62\x58\x86\x5c\x6d\xcf\x85\x7b\x00\x14\x78\x86\xe1\x75\xdf\x04\x32\xe3\x2f\x04\x40\x0e\x29\x9f\x21\x18\x83\x12\xb3\x2d\xfc\x05\x0e\x7b\x7e\x87\xee\xaa\x0c\xba\xac\x6b\xe9\x93\x7a\x5e\x0c\xc3\x11\x13\xde\x7c\x8b\x23\x3e\x1c\xe8\xe5\xd9\xc5\x64\xfb\xe9\xf3\x7b\xbd\x41\x1d\xf7\xa5\xe4\x4e\x6c\x7e\xbb\x67\x6d\x85\x89\x4d\xcc\xf4\x86\x5e\x4d\xda\x0c\xad\xef\x2b\xbc\x55\x00\x0b\x3a\x29\xf1\xf7\x1e\xf4\x46\x1d\xdc\x3b\x33\x1d\x91\x56\x65\x34\xc5\xd6\xd8\x4c\x73\x13\x76\x29\x53\x20\xf8\x0a\xdc\x90\x28\x8f\x99\x53\x55\x4f\xcd\xf9\x21\x3d\xe6\xa9\x05\x21\x0d\x4c\x80\x64\xaf\x91\xcd\x98\x32\x5e\xf9\x18\x98\xd3\x3d\x70\x03\x82\x02\xe3\x2f\xb6\x70\x9c\xa3\xd7\x88\xfe\xcb\xd1\xb8\x41\xfa\x4e\x5e\x90\x62\xd6\x42\x67\xc3\x5c\xfd\x44\x4f\xb6\x9e\x2f\x60\x47\xf5\x8b\x1c\x2a\xf4\xcc\x7e\x4c\xac\x2f\x89\x08\x88\x36\x05\x92\x11\x3e\x96\xad\x3a\x85\x7e\xd0\x5e\xaa\xba\x6f\x91\x53\xef\x89\xb9\x3e\x00\xe8\x74\x37\x33\xec\x47\x2d\x9b\x0e\xec\x1c\xd8\xfa\x52\x42\x5c\x4a\x26\xbd\x7d\xf7\x3a\x27\x12\xbe\xbe\x51\xae\x3b\x25\xeb\x78\xdb\x82\x14\x90\x31\xfe\x7b\x28\x1a\xf6\xcb\x77\x14\xed\xf8\x9d\xe9\x15\xf3\x47\x0f\x15\x3e\xed\x7f\x45\x62\x43\xbb\x90\x34\x2e\x19\x0e\x64\x7f\x39\xe0\x46\x88\x3c\xe2\x8a\x89\x20\x03\x31\x5e\xa3\x79\x42\x9e\x95\x82\xa9\x35\xeb\x78\x96\x33\x96\xd1\x36\x84\x5f\x86\xc4\x66\xe8\xfa\xf2\x27\x2f\x43\xff\xef\xc2\xad\xa5\x60\x1f\x8a\x6b\x2a\xc4\xcc\x6b\x92\x82\x09\x17\xf2\xe0\x39\x3c\x8f\xaf\x98\x2d\x6c\x5f\x4f\x23\x0e\x27\xce\x22\x78\xa7\x23\x77\x47\xfa\x85\xa9\xc8\x57\xbf\x18\x02\xc3\xea\xe0\xd2\x35\xb5\xad\x58\x49\x7d\x66\xa0\xd3\xa9\xba\xeb\xcc\x41\x7f\x18\x33\xe9\xcc\x44\x60\xf9\x75\xd7\x28\x58\xcd\x11\x8d\x7a\xaf\xaf\x1c\x87\x82\x97\xca\xcf\x71\xac\x75\x67\x6d\xc1\xb4\xfb\x51\xc1\x77\x58\x10\xd0\x35\x37\xf2\xd7\x66\x27\x8b\x99\x71\xbb\x97\xd3\xc4\x9b\x51\xfe\xb2\x6d\x37\x5e\x0c\xb9\x10\x95\x74\xa8\x16\xf8\x4e\x76\xfc\x7e\xf0\x72\xd5\x79\x3c\x2f\x65\xab\x2e\xfd\x90\x52\xe6\xb8\x56\x9f\x28\x05\x86\x1c\x31\xa7\x34\x4a\x3c\x44\x06\x9a\x94\x32\x0d\x27\x4e\x27\x12\x71\xea\xfa\x3b\xfe\x64\xde\x75\x37\x84\x6a\x01\xe5\x1f\xda\xe0"}, -{{0x58,0x26,0x19,0xab,0x3c,0xf5,0xa3,0xae,0x77,0x66,0x88,0xbf,0x6d,0xba,0xcb,0x36,0x33,0x0a,0x35,0xad,0x75,0x24,0xe4,0x9e,0xf6,0x63,0x68,0x77,0x64,0xcf,0x6e,0xc7,},{0x20,0x02,0xea,0x0a,0x38,0xa3,0x27,0xe0,0x38,0x4a,0xea,0xe4,0x68,0xdb,0x0f,0x6c,0x85,0x16,0xa6,0x96,0x09,0xaf,0x9e,0xee,0x93,0xe9,0xec,0xb9,0x4b,0x44,0x9c,0x66,},{0xfe,0x97,0x01,0xda,0x1a,0xa8,0x1c,0x55,0xba,0xc3,0x36,0x38,0xf7,0x75,0x54,0x2b,0x80,0x44,0x80,0xf3,0x4b,0x7b,0xfc,0x78,0xda,0x99,0x16,0xe5,0x24,0x6a,0x60,0x4d,0x39,0x0b,0xf9,0x20,0xc8,0x72,0xa7,0x79,0x24,0x24,0x6e,0xe8,0xd0,0x39,0x3b,0x20,0x2e,0x7b,0x25,0xb2,0x48,0x4f,0x65,0x4a,0xc3,0x67,0xcb,0x09,0x25,0xec,0xe3,0x05,},"\xca\x74\x28\x4f\x11\xc5\x6e\x25\x98\xd7\x8a\x4e\xcd\x03\xb4\x0e\x01\x7a\x55\x81\x76\x01\x2b\x26\xfd\xf6\x95\xc3\xde\x98\xa7\x4f\x8f\x40\xa4\x7d\x79\x78\xed\xc2\x4e\xe8\x09\x2b\xfe\x5e\x61\x59\x68\x34\xde\xed\x1d\x9d\x34\xa0\xf5\xcd\xae\xbe\x34\x21\xaa\x19\xe0\x12\xde\x86\x5b\x9e\xe1\xb7\x34\x79\xb2\xbd\x1a\xc9\x82\xf9\x7e\xd9\xc7\xcd\x20\x45\x9c\x60\xfb\xb1\x1e\x1e\x2b\x4e\xac\x5d\xb6\x84\x4c\x71\xd7\x29\x49\x50\x2b\xba\x50\x3a\xce\xc9\x05\xad\xba\x25\xf6\xb1\x19\xea\xf9\x63\x9f\xa8\xab\xb3\x02\xdf\xf9\x93\x2d\x85\x0c\xc4\x4c\x57\xcf\x90\xb2\xe5\x8a\x8b\x52\x51\xc1\x26\xa9\xe2\x8f\x5c\x76\x1b\x62\x80\xe2\xcd\xdd\x79\xcb\xd6\x8e\x53\xff\x4a\x62\x26\xd3\xbd\x4c\x96\x1b\x9b\x9e\x43\x45\xa2\x54\x58\x62\xc7\x97\x38\x66\xf0\x42\x0b\x89\x8e\x7b\xae\xa9\x0e\xa4\xee\x00\x40\x42\xef\x38\xa1\xfd\x95\x6a\x72\xfd\xf6\xfd\x43\x25\x7d\xa9\xfd\xb9\x66\x80\xef\x4f\xdf\x9e\x94\x3d\x26\x5c\xdc\xf2\xe5\x2e\x32\x01\xd5\x40\x8b\xc6\xce\x10\xe5\x70\x0a\xdf\x12\xb5\x5b\xa1\x4a\xa8\x29\xd8\x69\x1c\x31\xf2\x4f\xc4\xa5\x1c\xe6\xfa\xa1\xf3\xef\x2e\xad\x78\xe5\xe7\x53\x44\x6a\xd3\xfa\x4a\x84\xc1\x93\x97\x9a\xeb\xc8\x30\x9b\xad\x60\x81\x4f\x48\x59\xb9\x31\xd7\x04\x14\x76\x44\x91\xc6\xc9\xed\x8d\xb6\x73\xc5\x43\xd3\x51\x85\xcd\x28\x88\xaa\x21\xc1\xa9\x20\x34\x27\xe0\xac\x0b\x1f\xe3\x4c\x0e\x4a\x40\x01\xe0\x95\x6c\x13\xcb\x59\xa3\xba\xf8\x7c\x21\x09\xa8\x88\xa4\xc9\xe7\xaa\x48\x17\x67\xd8\x02\x0f\xf3\x5d\xd7\xc5\xcc\xec\x7c\x08\xe9\x71\xa7\xe2\x18\x13\x8c\x90\x54\x6a\x7d\xdf\x36\xad\x11\x4b\xe5\x85\x57\x43\x2c\x2d\xdf\x34\xce\xd3\x37\x9f\x70\xd4\x40\x7e\x58\x79\xf9\x84\x2f\x38\x17\x17\x05\x1b\x16\x85\xaa\x7a\xb0\xad\x38\x54\x1e\xc1\x68\xf5\x1c\xb6\x88\xf3\xcd\x1a\x01\x9a\x33\x6c\x9f\x4f\x3f\x82\xde\x78\x5c\x07\x48\x67\xfd\xc8\x80\x0f\xc7\x6f\xba\x04\xc8\xad\x8d\xe1\x0d\x2e\x9b\x43\x05\x81\xbe\x44\xc4\x1e\xcc\x8f\xc8\xa6\x16\x31\x43\x99\xd1\x8c\x64\x79\xf5\x7e\x57\x3b\x22\xa6\xee\x5c\xe2\xdc\xc0\x89\x48\xa0\xde\x1f\x0d\xd2\x5b\x65\x71\x5a\xb1\x8c\x70\xc7\x62\xfc\x3d\x7d\x60\x0c\xad\x63\x22\x60\x38\x50\x9c\x19\xab\x35\xb5\x49\x3e\xee\x73\xa7\x03\x73\x1e\xc5\x35\xc9\x0c\x6f\x06\xd9\x4d\x3e\x5f\x7e\x51\xa0\x9f\x9f\x8f\x42\xc5\x01\xb8\x50\x46\x86\x36\x5c\xee\xe9\xe0\xfe\x00\x13\x29\xf3\x03\x52\x21\x46\x71\x7c\x6a\x12\x58\xd0\xf1\x57\xcb\xea\x4b\x5a\x5e\x3d\x13\xbc\x90\x7e\x95\xfd\x6e\x8a\x71\x89\x6a\x02\xc3\x10\x6b\xd2\x6a\x51\x00\x51\xf1\xb3\x02\x58\xab\x27\xf8\x75\x67\x3b\x13\x37\xee\x36\xb7\x1a\x37\x6e\x0f\x9e\x78\x09\xa6\x7c\x67\xd9\xac\xc1\x6c\x25\x1d\xcb\x8c\x92\x6c\x8e\x93\x25\x16\xd3\x8b\x72\x33\xea\xc6\x15\x9c\x59\xca\xd0\x30\x7c\x59\x0e\x71\x31\xb6\x22\x19\x14\x5a\xaa\x35\x5b\xfb\x4a\xcb\x6a\xf0\xa5\x50\x00\x06\xcd\xd8\xb8\x13\xfe\x19\x08\x60\x2e\x08\x74\xc9\x62\x2b\xb3\x76\x73\xba\x1a\xcb\xa4\x14\x23\x16\x67\xbc\xc4\x90\x7a\xc8\x71\xf8\x7e\x6c\xe3\xf5\x91\xc1\x91\x71\x05\x7a\x9f\x45\x7f\x53\x62\xae\xda\x10\x5d\x18\xfb\x84\xf7\xd0\xf0\xa7\xda\x7e\xf8\xda\x91\x14"}, -{{0x2b,0xbd,0x83,0x0c,0xe7,0xde,0xf3,0xfe,0xce,0xa1,0xec,0xd6,0xea,0x0a,0xe9,0xc9,0xf4,0xfa,0x8f,0xfc,0x3b,0x1f,0x19,0x38,0xc5,0x05,0x05,0x1b,0xab,0x40,0xcf,0x7a,},{0x0f,0xdf,0xed,0x8d,0xe3,0xc1,0xea,0xf8,0x91,0xce,0x37,0xe3,0x4c,0xb4,0xa2,0x44,0x1c,0xbb,0xae,0x08,0x83,0x38,0x3d,0x70,0xde,0x24,0x64,0x85,0x0b,0x4a,0x64,0x2a,},{0x13,0xeb,0xc9,0x79,0xa8,0x87,0x10,0xe3,0xc5,0xf3,0x45,0xcf,0xbb,0x82,0x48,0x13,0xb3,0x08,0xa9,0xd5,0xc6,0xde,0xe3,0x28,0xbf,0xd2,0x35,0xa9,0x7d,0xe7,0xb3,0x26,0xde,0x6c,0x73,0x8f,0x96,0xf6,0x98,0x31,0x94,0x92,0x09,0x99,0x68,0x52,0xdd,0x9c,0x09,0x8d,0x58,0x08,0x41,0x87,0x09,0xf2,0xbf,0x51,0x0d,0x46,0xb7,0xf0,0x36,0x06,},"\x5f\x1e\xde\xaa\x3c\x0b\x2a\x63\x31\x1d\x97\xf1\xc5\x4e\x7e\x2f\x68\x71\x70\xe6\xb4\x6e\x21\x69\xcb\xf5\x6c\x66\xf2\x31\xbf\xc4\xa5\x76\xbd\x2b\x84\x20\xbf\x35\x7d\x3a\x90\xf8\xf3\x2e\xa1\xad\x99\x39\xb4\x67\x25\x4b\x66\xa1\xdf\x1f\x5b\x4c\xba\xc6\x3a\x5c\x27\x24\x26\x0d\x24\xd8\xdf\x8e\xdb\x58\xae\x24\x7a\x25\x91\xe9\x20\xb1\xa4\x20\xcf\x8d\x85\x39\xea\x57\xdb\x0d\xad\xff\x1a\xd3\xe9\x8c\x31\x72\xd0\x33\x16\x3c\xb4\x34\xa7\x66\xb0\xc1\x18\xa5\x6a\xbd\xcc\xe7\x9c\x82\xaf\x7b\xac\x74\xed\x0e\xa0\x24\xac\x4c\xe0\x22\x2d\x0a\xa9\x14\xf4\x32\x09\x2b\x1b\x51\x78\x04\xdb\x59\x18\xa8\x45\xe9\xcc\xa5\x5a\x87\xdb\x7c\x28\x52\xf7\xdd\x2e\x48\x36\x01\x85\xcc\x44\x2c\x79\x30\xaf\xe1\x5d\xd6\x22\xcc\x02\xbc\xd1\xee\x77\x8b\x59\x70\x5f\x14\x33\x32\x41\x58\x8a\x52\x2d\xe2\x44\x07\xe8\xe6\xe1\x0d\x5e\xf3\xa8\x8e\x3a\x3c\x44\x38\xc1\x7f\x75\x04\x67\x4f\xd7\xe4\x18\xcb\x2f\x77\xad\x0a\x56\xd2\x38\x67\x03\x15\x5e\x9a\x40\x1c\x43\xdd\xb5\x1e\xad\x55\x20\xaa\x7b\xa0\x38\xe7\xde\x53\x31\x41\x8a\xd5\x52\xbd\xcd\x18\x5f\x50\x3a\x85\x48\xf5\x5b\x63\x86\xe4\x68\x7c\xa5\x15\xf7\xc0\xee\xa5\x70\x98\x3b\xfb\x24\xbe\x16\xf7\xb3\x00\x3f\xb7\x56\xe3\x26\x56\x2f\x2a\x32\xfe\x65\xff\x84\x4c\x39\x84\xc7\x2e\x40\xdd\x49\xe4\xf3\xae\x8c\x0f\x81\x9a\x79\x39\xb2\xe7\x36\xe3\x81\xf5\x82\x3c\xbc\x61\xb2\xed\x01\xd9\xb0\x5c\xf8\xb1\x46\x48\xa4\x8b\x0d\x7c\xbe\x88\x2a\xc1\x6c\xad\xd8\xc4\x2a\xa2\xc7\x02\x46\x34\x7b\x4d\x84\x95\x36\xa7\xac\x22\xc7\x20\xda\x3c\xf1\x78\x72\x5e\xe5\x57\xa9\x2c\x25\xb1\x2b\x8b\x95\x6d\x3b\xf4\x80\x2e\x9e\x8a\x15\xb5\xab\x75\x42\x35\xcc\xa0\xe5\xb7\xe5\x5e\x4a\xec\xe4\x5a\x47\xe0\x84\xce\x14\x47\x44\x05\x98\xef\x5d\x4f\x5f\xdc\x2c\x98\xa5\xad\x13\x6c\xff\xbf\x87\xd3\xcf\x52\xf6\x73\x8c\xca\x79\x48\x35\x60\x92\x07\x8f\xdf\x25\x45\x77\xf5\x59\x69\xa0\xc6\x52\x46\xda\xc8\x09\xa2\xfc\xa1\xf6\x0a\x1d\x92\x98\x77\xb9\xa6\x54\x0e\x88\xa9\xe6\xe9\x15\x59\x38\xd2\x2c\x68\x7e\x63\xb3\x87\x53\x4d\x38\x5e\x89\x61\xe5\x88\x67\x43\xf9\x5f\x4a\x70\x80\xd9\x16\x62\x45\x17\xb1\x53\x36\x03\x0a\x46\x71\x4b\x16\x8b\x83\xd6\xf9\xcc\xe0\x60\x66\x49\xc0\x1f\x0a\x1d\x0a\x2a\x53\xf5\xe3\x78\xf6\xaa\x98\xc3\x84\xaa\xfb\x3e\xef\xdb\x34\x21\xfa\x3a\xc9\x8a\x0d\x3a\x9c\x02\x9c\x23\x00\xae\x02\x41\x06\x7d\x1a\x4f\xc9\x2e\x43\x86\x88\xea\x88\x9f\xcb\x1a\x1a\x9e\x86\x34\xb9\x16\xc6\x0b\xaa\x0c\x18\xbf\xcd\x13\x9b\xfe\x30\x17\xbf\xbe\x16\x29\x13\x43\xce\x86\x05\xbb\x78\x72\x55\x8c\x6b\x5f\xd5\x6d\xfd\x22\x15\x77\xed\xcf\xfa\xa8\xbd\xa3\x4d\x7a\x11\xab\x8c\xb2\x78\x28\x8e\x58\x34\x84\x26\x76\xfc\xcf\xfa\xa9\x11\x1b\xce\xd2\xb3\x57\x5f\xdd\x49\x62\x1b\x76\xe8\xd1\x29\xb6\x17\x00\xee\xab\x03\x14\xef\x94\xd5\x50\x50\x6a\x4b\x8d\x1e\xe6\x55\x08\xd8\x9d\x0e\x99\xe9\x33\x6b\x41\xd9\xf7\x4a\xa4\xd7\x22\x11\x4d\xe0\xf3\x1e\xcf\x00\xb0\x97\xf5\x3c\x9a\xca\x9c\x7a\x28\x5b\x58\xa3\x5d\x70\x29\x8c\x5c\x34\xf7\x4b\x4a\x70\x53\x08\x03\x31\x00\x34\x9f\x0c\x62\xf9\xc2\xeb\xf7\xde\xad\x0a\x77\xb2\x98\xeb"}, -{{0x1a,0x7a,0x3c,0x2f,0x54,0x81,0x13,0x1b,0xe5,0xf8,0x68,0x45,0x6a,0xa2,0xfa,0x90,0xe5,0x6d,0x52,0xcb,0x72,0x1c,0x71,0x84,0xeb,0xff,0x06,0xfe,0xd2,0xfe,0x68,0x5d,},{0x7c,0x2a,0xd0,0xf2,0xa5,0x70,0x55,0x03,0x26,0xfb,0x50,0xa8,0x50,0x83,0x58,0x21,0x67,0x6d,0xe1,0xde,0x12,0x7f,0x6d,0xe1,0x67,0x02,0x99,0xd8,0x14,0xf6,0xe3,0xce,},{0x97,0x61,0x60,0xfb,0x5b,0xbd,0xab,0xe5,0xc8,0x96,0x2f,0x23,0xba,0xba,0xcf,0x0b,0x0a,0xb4,0x1c,0x2b,0xb1,0x3e,0x9c,0x0d,0x44,0x90,0x67,0xb7,0xde,0xcc,0x7d,0xb4,0xe9,0x4e,0x76,0xa7,0x1b,0x9c,0x0a,0xc4,0xd6,0xaf,0x38,0x7a,0x72,0xa8,0xcd,0x73,0xe3,0xbc,0x63,0xb7,0xed,0x65,0x0b,0xee,0xbf,0x17,0x42,0x4c,0x49,0x0b,0xd6,0x0d,},"\xc6\x28\x34\xd9\xd5\x5d\x1a\x44\x03\xe9\x25\xd0\xa5\xb5\x52\xda\x17\x4c\x02\xf4\xe9\x45\xde\xc3\x38\xc1\xbb\xb2\xae\xb4\xff\x40\x02\x0e\xf7\x0f\xf5\x05\x20\x5c\xf8\x81\xb6\x29\x96\x0a\xbd\x62\x76\x4e\x5a\x54\xf2\xb5\x10\x56\x67\xb1\x1c\x7d\x5b\x7a\x4c\xcc\x3f\x48\x8b\xdd\xdb\x95\x8a\x7b\xe9\x54\x62\x07\xe6\xc4\x67\x18\x97\xc0\x53\x50\x8e\x1f\xd8\x32\x22\x13\x0a\x79\x33\x97\x6d\x2b\xec\x61\x4e\xd8\xf9\xb6\xa6\xb9\xf4\xef\xb2\xa5\x8b\x9d\x00\x5b\x94\x3e\x42\xf1\x71\xb7\x09\xa7\x31\x30\x70\xcb\x2e\x06\x8d\xa3\x9c\xf9\x99\x22\xb6\x9e\x28\x5c\x82\xad\x97\xf2\xd6\xc7\x79\x22\xca\xe2\xb5\xe3\x20\xe8\x35\x77\xc0\xd0\x88\x76\x1e\xc8\x81\x52\xc2\x97\x49\x29\x78\xa9\xd7\xa3\xff\x67\xed\xe4\x4c\x2a\x70\x7c\xf3\xe2\x35\x2e\x23\x2f\x53\xc8\x78\x2b\xa4\x89\x28\xa9\x7f\x8a\x36\xb2\x0a\x41\x68\x16\xe9\x45\x79\xb9\xd7\x25\x0a\x29\xdc\x84\x70\xf6\x3a\x70\x58\xe2\xd2\xa9\x9d\x6f\x0c\xcb\x53\x0d\xf5\x96\x95\x05\xef\x5c\x78\x44\xeb\x16\x7d\x20\xf4\x12\xa5\x08\xfa\xb1\xf8\xcd\x9c\x20\xc5\xeb\x9a\x41\x7a\x54\x12\xb5\xda\x6a\x57\x13\x57\x59\xfa\xb1\x7f\x63\x14\xf6\x8d\xf3\x5b\x17\x72\x42\x14\x43\x67\x6f\x31\x25\x79\xaf\x6b\x14\x11\x53\x5a\xda\x8f\x76\x01\x2b\x69\xbb\xeb\x60\xb2\x89\x7e\xe6\x60\x7c\xb3\x69\xcd\xf5\x2f\x4f\x6d\xdf\x88\xcd\xb2\x63\x0d\x78\x89\x6f\x13\x61\xfe\xa2\x2a\xe6\x34\x21\x76\x96\xff\x11\x4f\xb4\x2d\xbe\x4f\x43\x46\xf1\xbe\x5b\x57\xad\xb3\x84\xae\x7e\x49\xb4\x1f\x74\xb3\x1b\x9a\x62\xbc\x69\xdc\xa1\x65\x89\xc6\x34\xeb\x9d\x7c\x6c\x94\xf8\xec\xe4\x4b\x60\x62\x8f\x98\xe1\x02\x4c\xf3\x2e\x3e\x3d\xd6\xdc\xe5\x5a\x12\x22\x53\x2f\x49\x0d\x63\xe6\xa2\x75\x28\x1c\x0f\x3a\x6c\x10\x18\x91\xb8\xd5\x7a\x45\xde\x11\xde\x35\xeb\xb1\x51\xc0\xdc\xd7\x5e\x6c\x05\x0b\x3c\xd8\xba\xba\xe8\x45\xc3\x9f\x66\xc3\x6c\x77\xcd\xe0\x5b\x68\x3e\x4f\xb0\x10\x3d\x93\xe7\x65\x93\x35\xc8\x7f\xc0\xe3\x23\x5b\x2e\x82\x48\x8c\xda\xbe\xb5\xc5\xc8\x75\x80\x87\x45\xee\xa9\x2d\xe8\x6b\x8e\xfc\xb6\x3e\x16\xd0\x82\x91\x9a\xee\x2e\x92\x89\x9c\xb0\xbc\xf1\xc1\x42\x15\x77\xa4\xa0\xd9\xdb\x09\xee\x1f\x9f\xeb\x92\xa5\x38\x21\x03\xcf\x7c\x32\xcf\xe4\x63\x72\x5a\xe4\x86\x6d\xaa\xfe\xda\x05\x34\xc1\x69\xf8\xf9\xbe\x40\x4f\x3b\xaa\xe1\x23\xfa\x76\x8a\xce\x46\x17\x8d\x4b\x9b\xbc\x5b\xd7\xae\xec\x79\x03\xb0\xa5\xbc\x57\x53\x89\x86\xee\x09\xe0\x7e\x32\x07\x7b\x3b\x9d\xe5\x0d\xd1\x96\x7a\x37\x2c\x38\x5a\xc8\x86\x28\x7c\x18\x45\x1a\x64\xef\xb3\x7d\x05\x6f\x9f\x41\x94\xc0\x8b\x1e\x3e\xc9\x70\x22\x26\x7b\xf0\x04\x3c\x13\xd2\x6b\x9c\xe1\xf5\x39\x05\xf6\xe4\x1b\x3d\x99\xdc\x81\xb3\x31\x90\x9b\x72\x26\x66\xef\x24\x32\xe6\xaf\x8a\x45\x31\x07\x53\x12\x30\xce\x4a\x1a\xf8\xee\xd6\x26\xda\x22\x3d\xa7\x6b\x46\x50\x7e\x33\xd7\xcd\xbd\xe0\x2d\x41\x10\x40\xc8\x9a\x11\xd9\x51\x56\xed\x4a\xc2\x60\x5b\x82\x69\x39\xc6\xcf\x87\x7b\x4e\xe7\x36\xc5\xda\x77\xcf\x46\x50\xa9\x99\x7a\x3b\x9c\xf4\x6a\x82\xba\x2b\xc0\x13\x33\xc0\x44\x78\xb5\xc9\x2e\x24\x98\xbd\x00\x2f\x01\x31\x40\xae\xdb\x30\x1b\x95\x99\x3d\x1d\x75\x08\x70\xd9\x88"}, -{{0x19,0x1a,0x1d,0x90,0x32,0x1c,0x7f,0x4e,0x74,0x94,0xbb,0x98,0x29,0x09,0xa9,0xeb,0x40,0xc3,0x34,0x1d,0xd3,0x2a,0xe4,0xd9,0x67,0x50,0xb7,0xd0,0x29,0x66,0xb4,0x0f,},{0x95,0x62,0xd9,0xe2,0x13,0xf1,0x45,0xc4,0x56,0x93,0x5b,0x70,0x31,0xc6,0x80,0x66,0x9f,0x8b,0xbd,0x31,0xa4,0xc2,0xed,0x3c,0x91,0xc4,0x00,0x2a,0x56,0x29,0xe9,0x7b,},{0x74,0xcb,0x02,0x8d,0xc6,0xb7,0x5b,0x37,0xa1,0xda,0xea,0x1c,0xf8,0x84,0x65,0xdb,0x83,0xa0,0x09,0x3f,0xec,0xb2,0x2d,0x99,0xba,0x85,0x5e,0x9a,0xb5,0x9d,0x05,0xcb,0x22,0xc8,0x7d,0x0b,0x09,0xdf,0x7c,0x11,0x62,0x13,0xba,0xa8,0xf1,0x89,0xb2,0x70,0x3f,0xf9,0x53,0xcd,0x20,0x2e,0xb9,0xde,0xa3,0x97,0x6e,0xe8,0x8f,0x5f,0xa7,0x03,},"\x85\x89\x0d\xb4\xe2\xfb\xce\x09\x3d\xde\x5a\x80\xbf\x8f\xe0\x9a\x98\x4b\x83\xa4\x9b\x7c\xcb\x5d\x4b\x06\xcd\xaf\xdd\xd3\x82\xe4\xb8\xa8\xa5\x05\x30\xe8\x2c\x20\x06\x12\xc9\xd7\xd8\xa0\x89\xbc\x8a\xa8\x45\xc3\xcf\xcc\x38\xa6\x19\x5d\x21\xc2\x61\x8c\x3d\xba\x2b\x57\x09\x20\xec\xcf\xcd\x23\x6f\x17\xf0\x8d\x81\x42\x68\xf8\x82\x24\x2d\xdf\x07\x02\xda\x87\x85\xf4\x07\xaa\x8f\x86\xfe\xcf\xa9\x03\xc4\x8d\xa8\x3f\x83\x97\x77\xeb\x6b\x4a\x2b\xbf\x5d\xf7\xa4\xda\x53\x47\x5a\xf1\xff\xe4\x4b\x5f\xe0\x07\x2b\x8f\xbf\x3d\x26\xe6\xd8\x9e\xa6\x7d\x8a\xc8\x45\x94\x92\x89\x0a\xda\x65\x7e\xb3\xdc\x24\x92\xb8\x8d\xe1\x75\xb4\xbb\xa1\xa5\x08\x06\x4d\x61\x96\x74\xaa\xae\x2a\xf0\x9d\x31\xa5\xc2\x7c\x8d\x5d\x5a\x29\xb0\x37\x79\xf4\x28\x6b\x89\x66\xce\x40\x7e\x6f\xf6\x92\xfb\x94\x25\x20\xa9\x93\x8d\x69\xcc\x70\xac\xb0\x6b\x01\x4b\x6d\xfc\x19\x83\x42\x06\xcf\x1a\xc6\xc4\x48\xae\x6f\x07\x80\x25\xb5\x5f\x3d\x82\x72\x01\x26\x8a\x92\xad\xd9\xad\x17\x8e\xf7\x6a\x29\x89\xfe\xdc\x6e\x39\xf4\xeb\xb9\xf9\x6c\x9b\x83\x52\x69\x4f\xa5\x4f\xa0\x22\x01\x9c\x0e\xc0\x01\x2d\x0d\x76\x9e\x23\x67\x80\x3f\x92\x5f\x17\x5f\x9f\xb9\xcb\xec\x4a\x0c\x9c\x1e\x2c\x83\xea\x57\xe6\xa9\x2a\x17\xf5\x55\xca\xb9\x34\x27\x1e\x72\xc8\xcc\x32\x15\xfc\xb8\x7c\x20\x53\x9b\xf1\x42\x77\xb1\xbf\xbd\x6e\x58\x80\xef\x95\x3f\xc7\x5f\x23\xc0\xdd\x4f\xcc\x1e\x0b\xe3\x40\xaf\x94\x7d\xe0\x2e\x87\x7f\xd5\xc7\x7d\xd1\xdf\x7b\x41\x4b\x5c\x0b\x40\xc7\x49\x56\xa5\x45\xa1\x15\xb0\xc6\x99\x3a\xb2\x33\xb7\xe7\x2c\x82\x2b\x6b\x33\x81\xbb\x1f\xc1\x08\x75\xbf\xfe\x3e\x2e\xd1\x19\x0f\xa3\x3f\xc1\x5d\xa0\x83\x79\x4f\xcc\x2c\x5b\xf5\xa0\x79\x09\x06\x3c\xb2\x89\xa0\x8a\x2c\x8a\x33\xd3\x43\x84\x2c\x2d\x6a\x3c\xfa\x2a\x16\xca\x2e\xaf\xca\xb7\xea\x10\x0d\x1c\x71\x4b\xaa\xbb\x71\x49\xf0\x7e\x25\xde\xe3\x23\xe7\x80\x75\x7d\xfa\x80\x16\xfa\xa7\xc0\x62\x62\x22\xc3\x65\xf8\xf2\xf6\x68\x7d\x1d\xed\x23\x4f\x79\x9c\xc5\x0d\x1c\xd2\x6b\x4c\xfa\x40\x45\x91\x70\x56\xfc\x79\xc3\xb8\x8b\x2b\x19\x08\xe3\x72\xdf\x66\xda\xc8\x73\x46\x31\x64\x83\x49\xbc\x37\xfa\x34\xb2\x5f\xff\x3b\x07\x47\xb6\xbc\x16\xb9\x4e\x3e\x58\x95\xe4\xbb\xd9\x3d\x47\x8a\x6c\x1f\x75\xe4\xfa\x30\xfa\xa9\x22\x04\x9e\xd4\xc5\x0f\x12\xf4\xb3\x12\xa8\x97\x4d\x0f\xed\x8d\x44\x25\x5d\xcb\x2b\xf0\xfe\xbe\x47\xfb\x3f\xb8\xed\x99\x03\xb5\xba\x4c\xa1\x8e\x3c\xc6\x76\x2c\xfa\x1e\xaf\x04\xdf\xa9\x44\xd4\x96\xe0\xfe\x8b\xb7\xdc\x04\x54\x51\x39\x6b\xfa\xba\x54\x85\xd9\xd5\xf3\x91\xa9\x54\xc3\x71\x42\x53\xcc\xd9\xb1\x99\x64\xd4\x28\x06\x80\x72\x07\x83\x03\x6b\x3a\xbf\xaf\x28\x84\x58\x3e\xa5\xbd\xbc\xf6\x9d\x08\x89\x7a\xb2\x88\x31\x46\x35\xab\xb4\xc2\x96\x4b\x71\xad\x92\x91\xfe\xb5\xb6\x1f\x80\xe9\xb0\xcc\x07\xf9\x12\xa8\xe5\x59\x8d\x55\x48\xde\xfe\x0e\xea\x1c\x44\x85\x73\x71\x0a\xac\xdd\xb1\x52\xf9\x3c\x7c\x6f\xd3\xf7\xe4\xed\x9f\x74\x42\xa6\xb9\x00\xf2\x3c\x3c\x54\x4c\xe5\xc9\xba\x5f\x5e\x92\xaa\xfd\x11\xc9\xff\x5f\x79\xc0\x8b\x9d\x04\x5f\xef\x07\x97\x06\x25\xf6\x2e\x2f\x43\x34\xa4\xd6\x64\xca\xf7"}, -{{0x62,0x85,0x63,0xaa,0x3e,0xe2,0xfc,0x61,0x1b,0xcf,0xf7,0x8b,0xfb,0x2a,0x75,0xe9,0xfd,0x87,0x80,0xe8,0x7a,0x93,0x94,0x99,0xa6,0x1b,0xea,0xa6,0xa4,0xb7,0x19,0x13,},{0xda,0x20,0x61,0x6e,0xe4,0xa4,0x1c,0x2e,0xbf,0xdc,0x50,0xab,0x54,0x95,0x3b,0x6d,0x38,0x7b,0x06,0xc6,0xde,0xf7,0x57,0x96,0xb0,0x88,0x09,0x56,0x5c,0x6c,0xf8,0x05,},{0xc9,0xa6,0xaa,0xa9,0xb4,0xe1,0xcc,0xe1,0xb5,0x84,0x45,0x72,0x5f,0x61,0xf5,0x52,0xc8,0xfb,0x45,0x83,0x1f,0x03,0x48,0x27,0x98,0xf0,0x1f,0x66,0x3e,0x99,0x83,0xdb,0x1a,0x82,0xfd,0x33,0xab,0xa3,0xec,0xcb,0x96,0x22,0x64,0x26,0xd5,0x0a,0xe1,0x7c,0xc5,0x12,0x74,0xce,0x18,0xa3,0x88,0x60,0xf4,0x0b,0x2f,0x82,0x36,0x1b,0x5c,0x03,},"\x05\x6f\xb9\x54\xfb\xe6\xa6\x01\x4f\xad\xac\x1e\x1a\x9f\x56\xcc\x08\xaf\x37\x34\x8e\xba\xf6\x92\x06\x83\x38\x4e\xfa\x47\x62\x6c\xcd\xdf\xea\xd2\xd5\xe9\xe8\xcf\xff\x45\xf7\xac\x63\xde\x63\xf6\x9d\x12\x84\x8c\xe3\xc0\xef\x1f\x53\x0a\xde\x43\x0f\x0a\xfd\x5d\x8e\xcf\xd9\xff\xd6\x0a\x79\x74\x6a\x2c\x5b\xee\xdd\x3e\x67\x24\x99\x82\xf8\xb6\x09\x2e\xe2\xd3\x40\x47\xaf\x88\xa8\x1f\xea\xb5\xd5\x2b\x47\xd5\xb3\xf7\x6c\x20\x41\x72\x5f\x6f\x81\x32\x93\x05\x0a\xaa\x83\x4b\x01\xa3\xa5\x8f\x69\xaa\x4a\x8c\xa6\x1f\x5b\x74\x6f\x60\x0f\x3d\x45\x2c\x62\x82\xff\xdc\xa4\x42\x9b\x93\x38\x96\x7b\xa3\xa7\x26\x66\x90\xae\xc7\x5e\xbf\xbf\x7b\xe9\x8d\x99\x9b\x03\xed\xdc\x72\x92\x58\x1b\x0d\x69\xe3\x0a\x03\x51\xa1\x51\xdb\x70\x41\x2b\x0b\xfd\x43\xd3\xba\xa9\xd4\x56\xcb\x3e\x0b\x4f\xc1\x9c\xb0\x9e\x6c\xad\xcb\x6d\x3f\x3b\xe5\x13\x7c\xc7\xa8\xd3\x21\x9e\xc2\x03\x6e\xc6\x70\xed\x7e\xc5\x23\xb1\xb1\xc6\x87\xb5\x46\x53\x07\x88\x2f\xe3\x8d\x74\x72\xd0\xba\x87\xa4\x71\x86\x83\x09\xd2\xf7\x73\xff\x24\xc8\x7d\x39\xc1\x6b\x70\x8a\x4e\xd9\xaf\x43\xf7\x4c\x8d\x85\xcf\xe8\xab\x54\x06\x90\x7e\x94\x1a\x14\x97\x0e\x20\x9c\x29\xff\x7e\xd8\xa2\xf9\x35\xae\x41\x70\x9f\x27\x0d\x0d\x08\x55\x5e\xf7\xaf\x2e\xdf\xe4\x0d\xf3\x99\x22\x3c\x78\x5a\x43\xe7\xf3\x69\x15\x89\xe2\xea\x4c\x03\x6f\x11\xd0\x3d\x7d\x1e\xea\x14\xf6\x20\x03\x53\x25\xcf\x2b\x33\xba\xf3\x86\x39\x3e\x8a\x97\x2a\x7a\xf6\xcd\x9b\x85\x43\xb3\x2e\x25\x33\xd1\xfc\xc3\x17\x7f\xd9\x6d\x1e\x13\xbf\x8b\x68\xde\xb2\x22\xf9\x44\x97\x26\x5d\x3c\xcb\x34\x57\x51\xbd\x5b\x66\x90\x78\x08\x19\x98\xd6\x08\xca\x5f\xdc\x13\x48\x39\xd4\xed\x2b\xeb\xb2\x95\x2f\xea\x5a\x39\xc6\xf0\x33\xc1\x55\x8f\x69\x8c\xe4\x94\x6e\x4f\x6c\x08\xaf\x87\x4f\x27\x35\x7f\x87\x0e\xbe\xeb\x21\x99\x97\x6f\xfa\xef\xac\x95\x1f\x8e\x17\xfe\x7d\x08\x21\xe1\xb9\x2a\x90\xaa\x4e\x9d\xef\xd3\xfa\xfd\xa0\x52\xa4\x44\x47\x6d\xb1\xce\x38\xa9\xe1\x76\xe8\x41\x18\x9a\xbd\x8f\xec\xde\x0f\xbc\x5c\xb5\x5f\x51\x1f\x5f\xde\x07\xea\x97\xde\xb3\x9b\x7a\xa8\xdc\x84\xa3\x94\x6a\x6c\xf9\x26\xd3\x9b\x95\xc1\x1a\xf9\xd6\x4d\x98\xb8\x07\xf4\x70\x4d\x0a\x2b\xda\x97\xda\xd9\x88\x1a\xda\x1b\xf6\x63\x63\x66\xe6\x0a\x52\x2b\x48\x21\x04\x78\x61\xc7\xaa\xe2\x14\x6a\x02\xee\xf6\xb2\x5d\x51\x37\x1a\x0f\x17\xd2\x4b\xc1\x87\xdc\xdd\x05\xd5\x41\xc2\xf7\x22\x01\x42\x79\x15\xa3\x92\x8c\xd3\x78\x68\x91\x03\xac\x50\xb3\x3f\x87\xa4\x7e\x8c\xdf\xa6\x87\xa5\xf0\xaf\x8a\x56\x73\x1d\xab\xe6\x62\xf4\xf2\x83\x6d\xe0\xba\x8f\xaf\xd8\x6a\x38\x54\xbc\xa0\x12\xd7\x08\x8a\x00\xb9\x85\x4c\x2d\x3c\x70\x8d\xdf\x58\xfa\xa3\x55\xa8\x9a\xfc\x2c\x80\xf3\xf5\x33\x6d\xa0\x1d\x72\xa2\x77\x1a\x05\x58\x13\xfb\x35\x33\x0f\x7d\x2e\x01\xb1\xd1\x2d\xaa\x95\xed\x55\xd3\xbd\xc5\xdf\x77\x39\xcb\xc3\xca\x09\x7a\x41\xb6\xb2\xbd\x7f\x0f\xf9\xdd\x1d\x86\x58\x98\x3b\xa3\xff\x79\x20\xc1\x5f\x29\x2a\x1e\xf9\xfc\xad\xa1\xc6\x07\xec\xb4\x5d\x3a\x73\xc9\xff\xd4\x2f\x3e\x16\x02\x2f\xdf\xe1\x27\x44\x92\x63\x95\xf7\x4f\xb3\x11\x17\x93\xfa\x92\x81\x82\x1a\x66\xa0\x1d"}, -{{0x91,0x41,0xf7,0x9e,0xd3,0x0b,0xf6,0x00,0x61,0x1a,0x13,0xf3,0x67,0xb4,0x03,0x96,0xf2,0xec,0x83,0x9c,0x56,0x12,0xbb,0xf1,0xe6,0xe4,0x97,0xf8,0x39,0x54,0xbc,0x88,},{0xf1,0x4e,0xda,0x96,0x26,0x40,0xbe,0xcb,0x66,0xc4,0xd1,0xf1,0xa0,0x21,0x11,0x02,0x51,0x91,0x7b,0x8b,0x1d,0x34,0x82,0x82,0x98,0xd3,0x21,0x45,0xba,0xf6,0xe5,0xd9,},{0xcf,0x20,0x2d,0x7f,0x2f,0x9e,0xd1,0x17,0xf4,0x29,0x50,0x2b,0x2a,0x5a,0xff,0x54,0xa7,0xf7,0x51,0xd2,0x17,0x15,0x15,0xa4,0xd2,0x03,0x75,0x34,0x46,0xdf,0x0e,0xba,0xc8,0x69,0x84,0xc8,0x8b,0xd4,0x2b,0xd1,0xfb,0x8d,0xcb,0x40,0x87,0x76,0x72,0x2a,0x38,0xf3,0x2c,0xce,0xb2,0x5f,0x32,0xa2,0x5d,0x73,0x93,0xf1,0x38,0xee,0xdf,0x0a,},"\x8f\xec\xaa\x7a\xe9\xa3\xd4\xa4\x85\x1a\x66\x36\x2b\x36\x6e\x16\x7b\x9f\x43\x00\xfd\xab\x20\x56\x54\x75\x19\x87\xf0\x85\xde\x61\xbe\xc9\x34\x4a\xa8\x6f\x5e\x5c\x64\x77\x51\x4c\x28\x04\xce\xd7\xac\x0c\xd0\x62\x85\x29\xa3\xa1\x59\x92\x36\xed\x67\xbe\xbe\x1f\x2e\x95\xaa\x15\x1f\xe0\xf3\xb3\x01\x1a\x1d\x4b\xe9\x90\x1c\xaf\xab\x2f\x18\x91\x90\x4d\x4b\xff\x01\x28\xc1\xd3\x5e\xce\xcb\x32\x2b\x3c\xc0\x1d\xac\xc5\xae\x3d\xca\x69\x14\xa7\xd3\x4d\xa8\xc9\x65\x7b\x95\x0f\x89\xd1\xd6\xae\xc3\x29\x9b\xb6\x90\x11\x10\x71\xfa\x87\x28\x27\x74\x94\x3d\x96\xa4\xab\x7c\x3d\x6d\xe7\xd1\xbf\x11\x93\x63\x06\x8c\xc8\x2d\x45\xe4\xb7\x64\x54\xc6\x08\xbc\x35\x66\xb7\xf9\xb3\x85\xcc\x7e\xb3\x8e\xe4\x29\xaf\xc2\xda\x99\x66\x9f\xc5\xc1\xbe\x82\x16\x1a\x1b\x0c\x33\xf7\xba\x9a\xd4\x41\x9d\x20\x62\x97\x19\x01\xdb\x00\x3b\xfa\x23\xc4\x47\x14\x99\x5c\xb0\x6b\xfa\x96\x6e\x50\x23\xaa\x93\x46\xfd\x37\x5a\xe2\xa1\xe8\x40\x84\x31\x4d\xf3\xf0\x8c\xe2\x08\x00\xc2\xc2\xad\xfb\xb8\x13\x66\xf6\xb1\x04\x24\x3d\x62\xd5\x04\x1e\x72\x73\x43\x3f\x17\x58\x1b\xf9\x3f\x4c\x61\x46\xfa\x96\x6f\x63\x8a\xb0\x7e\xa1\x66\x94\xa7\xce\x30\x5c\xc6\x09\xa6\xe1\x06\x23\xff\x7f\x6c\x79\x16\xb6\xe4\xdb\xde\xbb\x7b\x52\xec\xa7\xf0\xd5\x18\x7f\xf6\x64\xd7\xc3\x70\xed\x22\x88\x6a\xa2\x67\x13\x29\xd9\x28\xe0\xa3\xbe\xa3\xb4\x71\x1a\x12\x8b\x9a\xab\x90\x26\x6f\x86\x51\xd2\x20\xb9\xcc\x1c\xbf\x5b\x1c\xe7\x26\x59\x31\x80\x36\x90\xd3\x29\x1c\x01\xea\xd4\xdb\xc3\x32\x9a\x97\xe8\x5c\x4f\xe1\xd3\x56\x60\x8c\xc9\xe6\x0b\x05\xbc\x14\x83\x8a\x86\x08\x27\x9a\x00\x61\xde\x28\xff\x7b\x8e\x81\xf5\x9c\x8a\x8c\x55\x23\x92\x4c\x4c\x48\x5e\x6e\xa8\x0a\xc8\x17\x50\xbb\x0e\x41\x9e\xfc\x78\x58\xcd\x4a\xf5\x0c\x8b\x8c\x80\x65\x0f\xac\xab\x4d\x82\x58\xf9\xca\xfa\x03\x10\xa0\x07\xcc\xcb\xc4\x18\x5c\x82\xfd\x14\x6d\xf1\xd8\x11\x87\x9d\xa3\x65\x0d\x57\x16\xf1\x00\x4b\x71\xd2\xc7\xf2\xbd\x65\x03\xc3\x54\x58\x9f\x86\x02\xc9\x50\xa1\xf5\x13\x9f\x81\x14\x60\x75\x28\x80\xa3\x41\x11\x66\x30\xe4\xff\x84\x94\x8e\x74\xa9\xeb\x35\x0d\x64\xd8\x29\x30\x02\x20\x02\x33\xf2\x09\xb1\x7d\x78\x89\x7c\x7c\xe6\xce\x29\xe2\x9f\x82\xd4\xad\x6c\x61\xeb\x79\xf5\x73\x9c\xb6\x68\xb2\x1a\x74\x55\x55\xc9\x6e\x19\x52\x68\x45\xe8\x2c\x6e\xd2\xb1\xc6\xbd\xd6\x36\x4b\x8f\xc7\x9b\xa9\xa3\x2d\xbd\x3f\x8b\x97\x5e\xb9\x23\x62\x39\x58\xae\x0d\xaa\x4f\xfa\x13\x92\x17\xc0\x0e\x02\x1f\x93\x7e\x9b\x79\x1c\x37\x99\x1a\x35\xe5\x23\x1a\x19\x14\xc0\x45\xa7\x87\x43\x2f\x97\xb8\xe2\x06\x3d\xb1\x05\xe1\x4d\xa9\x79\xc1\xc4\xcb\xa7\x85\x21\x0e\xb0\x20\x11\x33\x4b\x23\x0c\xfb\x68\x31\x99\x8c\xcc\xe2\x53\x86\xf4\xf3\xba\x0d\xce\x20\x06\xe9\xc3\x94\x0b\x4d\x5a\x56\xaa\xcc\xdc\xab\x02\x71\x86\x89\x81\x63\x60\xf1\x88\x52\xfd\x19\x98\xa9\x9f\xce\x9a\x04\xda\x3f\x5e\x23\xaf\x94\xc6\xe8\xa5\xba\xdf\xd3\x93\x04\xb9\xe2\xa3\x76\xa1\xf9\xba\xc0\x9a\x85\xbd\x04\x24\x76\xe2\x6b\x58\xec\x73\xf1\x23\x6d\x41\xab\x4b\x4e\x7a\x54\xde\xf9\xd6\x6a\x38\xf8\xe5\x46\xde\x7b\x38\x8e\x1e\x7d\x66\x81\xe5\xe2\xa0\x96\xf1\x60"}, -{{0x69,0x5c,0x96,0x0b,0xbb,0x0d,0xd5,0x7f,0xfa,0x36,0x15,0x1c,0x85,0xde,0x73,0x51,0x54,0xfe,0x5a,0xd5,0xf5,0xfc,0x77,0xd0,0x05,0xa0,0xa3,0x20,0x11,0xde,0xb3,0x0c,},{0x34,0x12,0x5e,0x4e,0x21,0xf7,0x89,0xed,0x0e,0x11,0x80,0xc1,0xf6,0x36,0x9c,0x72,0x1d,0xca,0xe9,0x85,0x9b,0x6f,0x7b,0x04,0xf9,0x57,0xe5,0x10,0x01,0xee,0xde,0x8a,},{0x4a,0xf4,0x1c,0x55,0x4d,0x99,0x08,0x12,0x68,0x6c,0x32,0x9a,0x87,0x5c,0x41,0xee,0x24,0xb4,0xa7,0xfd,0x7b,0x3d,0x4f,0x8c,0x8d,0x52,0x75,0xf2,0xe7,0xcb,0x24,0x2b,0x25,0x8b,0x58,0x58,0xa4,0x66,0xde,0x59,0x5c,0xe2,0xa2,0x17,0x7e,0x35,0x1c,0x7f,0x08,0xc7,0xfc,0x4e,0x0b,0xf9,0x7e,0xc5,0xfb,0x2d,0xcb,0x82,0x52,0xd2,0xc9,0x0a,},"\x37\x06\x69\x6c\x7a\x90\x66\x90\xd0\xd3\xb7\x1e\x7e\x21\x1c\x7b\x06\x71\x68\xf3\xa8\xf1\xed\x98\x4a\x0a\x5e\x60\x78\x59\x76\x62\xe4\xe7\x88\x9d\x52\xdb\x0f\x78\xe0\xd5\xef\x0e\x5f\x7a\x0a\x0f\x42\x63\xb6\x84\x8b\x07\x25\xca\xa4\xb1\xce\xa6\x98\x74\x09\x51\x1c\x8e\x5e\x98\x2d\x3f\x5b\x82\xbb\x56\xa4\xa7\x94\x71\x21\x93\x7f\x8e\x10\x5c\x5a\x14\xb5\x3e\x6c\x37\xcc\x71\x6b\x1e\xba\x92\x24\x21\x82\x8b\x04\x6f\x68\x56\xc4\x4f\xab\xf1\x3a\x75\x16\xc6\x2a\x5f\xf9\x85\x68\x45\x0c\xee\x78\xb1\x40\x33\x50\x47\xbf\x1c\xa7\x7e\x15\x49\xa8\x94\xfe\xeb\x07\x80\x45\xe4\x64\x18\x32\x25\x3b\xf6\x95\x48\x54\x52\xec\x36\x90\x65\xa6\x00\x29\xa6\xc9\x07\x7a\x37\x9d\xb2\x04\x85\xea\x2e\xdb\x6c\x96\x95\x47\xbb\x26\x53\x28\x9b\xc6\xe8\x1f\xfc\xb8\x4b\xdb\xf7\x73\xdd\xea\x4b\x37\x50\xe9\xa7\x23\x95\xd1\x17\xf6\x44\xb0\xe2\x20\x61\xd4\xf3\xbb\x7c\x5b\x61\x2e\x4b\x70\x39\x5e\x07\x79\x51\x6b\x46\x65\x91\x16\x90\x2f\xd0\xfb\xcd\x23\x40\xee\xa4\x5e\x9c\x23\xdb\x25\x64\xa5\xe1\x1d\xc7\x9e\x8f\x4b\x33\x2a\x44\x3e\xc3\x5a\xad\x96\x04\xfe\x79\x12\x52\x08\x82\x95\xe8\x4f\x65\xa3\x07\x31\x25\x50\xd9\xeb\xf6\x1f\x36\x7e\x4a\x0f\x2b\x56\x23\xe5\x3e\xf6\xbc\x13\x28\x25\xfc\x24\xeb\xee\x4e\xbf\x33\x8c\xbf\xb5\xdf\x69\xb3\x2d\x03\x0d\x44\x7c\x44\xf3\x13\xba\x96\xfe\x07\xbb\xfe\x5b\x01\x66\xea\xec\xbc\x61\x9b\xb6\xb2\xe5\x92\x40\x10\xba\x3e\xc1\x50\xff\x6a\x69\xfe\xc4\xde\xd9\xc4\x42\xf9\x8c\x15\xe7\x7f\x31\x9b\x48\x43\xb3\xb7\x48\xb5\xd2\x60\x89\xa7\x6c\x2b\x83\x4f\xf9\x3c\x41\x3e\x04\xca\x95\x50\xcd\x21\x1c\xe2\xd6\xa5\x83\xd7\x82\x57\x50\x66\xdb\x6d\xd3\x3e\x8d\x5e\x83\x74\x35\x5d\x06\x8a\x5e\xb9\x6f\x8b\x3d\xa8\xdd\xdf\xb5\xba\xf5\xc5\x96\xda\xaf\x55\x6a\x8f\x2c\xb5\x78\x1e\x50\x42\x32\x7f\x92\xae\x06\x21\xea\xe0\x88\xb5\xf0\x13\x59\x2e\x77\x87\x3a\x81\xd7\xe0\x68\xd7\xb8\x33\x7d\xb9\xf1\x09\xa8\x35\xb4\x75\xe5\xca\xf7\xce\xa5\xaf\x3b\x4a\xd6\xd9\x0b\xaa\xf1\xc7\x36\x55\xec\x67\x67\x47\xfc\xdd\x41\x77\x5b\x4f\xbe\x39\x24\xc3\xf4\x1d\x8a\x73\x75\x28\xd1\x2d\x61\x56\x65\x3a\x22\x35\x8c\x68\x21\x42\x6b\x2c\x0a\x33\xe1\x63\x4c\x62\xc7\xc8\x38\x56\x49\xbc\x23\x3e\x7d\xaf\x94\x39\xf0\x9d\xb9\xbd\x11\xea\x01\xe2\x8b\x77\xec\xbb\xc4\x59\x0e\x29\xfd\xcf\x0f\xdd\xe1\x52\xf6\x47\x81\x32\xfe\x4c\x3a\x5b\x45\xa7\x30\x5a\xf6\xe3\x81\xca\xdd\x72\x49\x6e\x66\xbb\xb8\x66\xce\xa4\x7f\x7e\x7d\x7e\x63\x34\x16\x00\xaf\x3f\x49\xce\x9c\x9e\x4e\x37\x39\x4d\xf5\xdf\x71\xdc\x10\xcd\x39\x1f\xdc\xb8\xa1\x93\xdc\x98\xfc\x19\x05\x9f\xa3\xac\x23\x0e\xc5\x47\x6b\xf9\x4d\x85\x55\x6a\xce\x6e\x1b\xa3\x24\x21\xbf\x59\xdc\xbe\x05\xc5\xe1\x5d\x34\xc6\x64\x4e\x27\xd0\xa0\x2b\xe9\x7f\xa8\x38\x7e\xe0\x37\x06\xf2\x2a\x8f\x4b\x3b\x40\x40\xad\x7d\x3f\x8a\x86\x97\x1a\x20\xa0\x9e\xc8\x1b\x76\x96\xd8\x34\xc5\x26\xb8\xe5\x1c\xb9\x7d\x27\x64\x3f\x9a\xbf\x5e\x29\xff\xd0\x33\x3f\x95\xde\x15\xd1\x10\xc2\x06\x4c\xa4\x94\x67\xc1\x4e\xf2\x27\xf4\xba\xbf\x1a\x55\xe7\xb1\xcd\xa0\x42\x9c\xff\x25\x6b\xe3\x1c\xf1\x16\x71\x9a\x81\xb9\xc5\xfb\x75\xfd\xf6\x4e"}, -{{0x25,0xcb,0x17,0xfc,0x33,0xd2,0xbf,0x83,0x84,0xae,0x4d,0xf2,0x0c,0x1f,0xad,0x5c,0x35,0xfd,0x76,0x5a,0xff,0xde,0x04,0xb5,0x25,0x6d,0x4d,0xe0,0x1c,0xa8,0xde,0x14,},{0xb8,0x6c,0xa3,0x12,0xfe,0x59,0x85,0x20,0xc6,0x4b,0xe5,0xc7,0x2f,0x5b,0x23,0x81,0x65,0x07,0xf6,0x9e,0x07,0x0f,0x82,0x8e,0x02,0xd2,0xaf,0xcf,0xe1,0x1b,0xfa,0x01,},{0x8c,0xcb,0x0d,0xbc,0xf7,0xcc,0x03,0xe8,0x3e,0x21,0xc5,0x74,0x74,0xaf,0xd3,0xad,0x88,0x98,0x09,0x7b,0x97,0x2e,0xde,0x17,0x5a,0xca,0xae,0x48,0xe3,0xec,0x17,0xb2,0xdb,0x06,0xfc,0x82,0x77,0x6b,0x07,0x51,0xc0,0xf9,0x56,0xfd,0x71,0x96,0xf3,0xd1,0xc9,0x63,0x21,0xa6,0xcf,0x3d,0x89,0x24,0x15,0xd8,0xf8,0xee,0xb4,0xa1,0x41,0x08,},"\x4b\x4a\x71\xcb\xf8\xcb\xaf\x57\xa7\x7d\x4e\xa1\x88\xa6\xf9\x64\x84\x0f\x0d\x71\x4a\x5f\x38\xa0\x95\xa1\x3b\x4e\x57\x12\x97\xa8\x8b\x79\x24\x17\xd1\x61\x84\x42\x7f\x90\xe0\x43\xdd\x8a\x55\xb7\xf1\xc1\x3e\x00\xdf\xa6\x05\x16\x44\x5c\xbe\x77\x06\x8c\x79\xc8\xc3\x5e\xbe\xac\x33\x0c\x33\xf1\x12\x1d\x05\x73\x1a\x8f\x51\x32\xd6\x48\x00\x73\x27\x46\x41\x19\x5a\x75\x20\x21\x16\xff\xf1\xc3\x18\x81\x71\x78\xfd\xd7\x68\xbb\xdf\x10\x5f\xa0\x69\xc7\xa3\xd1\x43\xfd\xf5\xd1\x7b\xfa\xd7\xc0\x62\x4e\x52\x92\x06\x8f\xd7\xbb\x6d\x30\x3b\x4a\x27\xcb\x20\xa4\xe6\x18\x75\x07\x67\x87\xd1\x9f\xa6\xf7\x29\xc9\x4d\xc0\xba\x9b\x8c\x0b\xfd\x98\x66\xda\x5c\xb2\xe7\xa2\xcd\x2e\xdb\xdc\x95\xac\x34\x9e\x5e\x5c\x21\x72\xe5\xa4\xcf\x7b\xd9\x0c\xab\xe2\xc6\xe2\x24\x59\x80\xbd\x72\xd0\xf6\xf5\x47\x98\x81\xe8\xc4\xc3\x54\xf6\x8a\xa7\x28\x41\xd0\xc7\x3b\x98\x6b\xa5\x10\x21\x20\x31\x61\x02\x6e\xe3\xd7\x29\xdd\xf1\xa0\x49\xff\xe9\xeb\x25\x43\x98\x02\xf0\x30\x11\xd1\x44\xe5\x0b\x02\xbd\x4a\xca\x5e\x55\x06\xd3\x2f\xcf\x69\xe3\x2f\x54\x25\x44\x79\x8f\x4e\x87\xf7\x2b\xdf\x24\x33\xb1\xff\x32\x59\x29\x2e\x1d\x90\x81\x2c\xff\xd7\x9f\x6a\x54\x32\x70\xba\xf2\x4a\x3c\x39\xdd\x35\x98\xe1\xc6\x61\x61\x29\x22\x52\x2f\x38\x7d\x51\x59\x76\x92\xf3\x14\xc4\xd5\xac\x4b\xf1\x88\x3a\x61\x46\x36\x33\x6a\x55\x44\xd5\x9f\xf4\x1d\x1e\x0d\xbc\xf8\xe6\x62\x7e\x7c\x80\x85\x64\x63\x22\xdf\xc2\x0c\x33\x2c\xbd\xf3\x53\x70\xd4\x7d\xca\xbb\x80\x2e\x17\xca\x84\x78\x0e\xec\x66\x1c\x90\x4d\x5b\xfb\xc2\x40\xad\x6a\x14\xa7\x53\x3f\x71\xa2\x75\x00\xc6\x1d\xd3\xe4\x73\x98\x38\x87\xa8\x68\x35\x18\x7a\xbb\x0d\xf0\x8f\xa6\x2c\xda\x69\xdc\xe8\x6e\x21\xfa\x5a\xe9\x54\xc2\x2e\xdd\xb6\x0e\xe3\x13\x15\x04\xa6\x9b\x50\x48\x6a\x17\x76\x70\x91\x88\x37\x60\x63\x8a\x29\xc3\x80\x30\xe1\xe0\x5f\xdb\x28\xe1\x58\x63\x30\x10\x38\x5a\x62\x06\x13\xcc\x10\xd5\xa5\xf3\x50\x95\x5f\x4a\x34\x7c\x65\xed\xdd\xb7\xe2\x51\x59\xda\x8d\xcc\x26\x55\x92\x8a\xd6\xf6\xd8\xc4\xc1\xab\xb8\x17\xd7\xfe\xf3\xba\xe5\xde\x04\x02\xed\xde\xe7\xb5\x15\x21\xce\x28\x0a\x66\xb7\x96\x14\x0f\x56\xaf\x9b\xc2\x0e\x46\x58\x75\xce\x26\x28\xa8\xa1\x04\x77\xce\x9b\x2e\xac\xc7\xd8\x6f\x88\x27\x24\x57\xbf\xd4\x43\xe7\x12\x52\x69\x96\x25\x43\x80\xf0\x13\x52\x27\xe9\xfc\x15\x1c\x86\x95\xe9\xcc\x64\xd2\x72\xb2\x56\xab\x95\xc9\xa9\xf5\x68\xe9\x37\x16\xe0\xe5\x3d\x29\x88\x2e\x3c\xe7\x42\x61\x25\x7a\x02\xcd\x49\x7c\x37\xd7\x64\xd9\x0f\x7f\xd4\x78\xa1\x7a\x89\x0a\x8b\x2e\xa6\x1a\xb8\x1f\x68\x69\xb1\x20\xa2\xf6\x48\x4a\x88\xc1\x51\x95\x33\x91\xec\xa4\x45\x01\x53\x77\xb3\xa5\xdf\xfe\x4c\xfb\xac\xfb\x5b\xab\x2c\x47\xf6\x54\xf7\x2a\x9d\x19\xcb\xc4\xd2\x95\x37\x19\x84\x05\xe3\xa0\x4b\x4b\xfe\x11\xbc\xdb\x5c\x1f\x30\xd9\xac\x02\xf5\x48\x49\xc5\x7a\xa9\x6f\x7b\x56\x63\x61\x16\xf2\xbb\x6f\x25\x83\xd9\xaf\x94\xc8\x6a\xff\x5c\x13\x7f\x63\xce\x54\xe8\xf0\xc2\x1b\x6c\x25\xc1\xf0\x47\x2a\x22\x9c\x90\x81\x7e\x61\x62\xea\xc7\x1c\xcd\xa3\x09\xa1\x64\x3b\xd6\x31\x2a\x52\x63\xa2\xef\xe6\x46\xdf\xfe\x79\xeb\xd8\x15\x7a\x28"}, -{{0x49,0xe2,0x4d,0x16,0x99,0x83,0x37,0x26,0xb1,0x8c,0x78,0xea,0x65,0x68,0x40,0x1a,0x97,0x1e,0x1c,0xa3,0x9d,0xd0,0x6d,0x75,0x63,0xac,0x8b,0x42,0x50,0xd4,0xa9,0xf5,},{0x71,0xcf,0x05,0xe9,0x0d,0x30,0x1a,0x6d,0x9f,0xad,0x7f,0x0b,0x38,0xec,0x8b,0xb0,0x44,0xfc,0xfd,0x97,0xc8,0x49,0xb0,0x4c,0x00,0x36,0x25,0xde,0x29,0xbe,0x86,0xbb,},{0xa0,0xb6,0xa2,0xaf,0x15,0xb6,0xbe,0x9e,0x95,0x1e,0xf3,0xf3,0x2c,0xbd,0x1c,0x67,0x02,0xe8,0xe0,0x17,0xfb,0xd3,0x15,0xa3,0xf2,0x59,0x9c,0x3f,0x1a,0x11,0x86,0x5d,0x46,0xe7,0x84,0x59,0xa0,0xd7,0xf7,0xbe,0x04,0x6a,0xae,0x29,0x3c,0xad,0x09,0x13,0x7e,0xc8,0x47,0xe2,0x69,0x28,0x10,0x6d,0x9a,0xa3,0x5e,0x09,0x82,0xb9,0x92,0x02,},"\x6d\x26\x05\xf6\x1e\x1a\x04\xb6\xae\x18\xc2\xc2\x5a\xe1\x00\xdd\x42\xa6\x1e\x66\x4e\x2d\xb5\xc3\x4d\x7a\xd1\xf8\x4a\xc5\x07\x55\x2b\x74\x1c\x20\x86\xc1\x7c\x85\x2b\xab\xe0\x7a\x91\xe1\x29\xa5\x06\xee\x59\xed\xb9\xce\x73\xbe\x1b\x1d\x06\xd1\x20\xec\x36\xa1\xe9\x4c\x62\x81\x05\x4e\x78\xce\xb1\xbd\xef\xfb\xcb\xf4\xf0\x10\x51\xed\x38\x1b\xfc\x8a\xd1\x76\x9f\x41\xe2\x40\xbf\x60\x59\xd9\x70\x4c\xac\xec\x66\x66\x11\xf4\x1e\x4d\xd4\x38\xb7\xf5\x02\x42\xea\x86\x75\x6b\xb1\xf8\x1e\x59\x42\xc0\x92\x12\x9f\xbc\x6d\xe4\x95\x5d\x28\xdf\xf3\x52\x37\xdb\x30\xe4\xa5\x03\x6a\x99\x14\xc9\xf8\x4d\xbd\x8c\xcf\x82\xba\x2b\x1b\x3b\x55\x54\xa2\xb7\xa7\x4c\xb0\xb2\xa1\xe1\x96\x33\x45\x28\x6e\x25\x8d\xc8\xe7\xd5\x67\x18\x03\x5f\x95\xf3\x13\x81\x1c\xfb\xd8\x52\xa0\xf8\xf4\x9a\x29\xef\x93\x3e\x7c\xda\x7e\xd9\xc7\xe8\xb1\x62\xcd\xba\x1a\x82\x26\x2c\xd4\xdf\x7c\xf8\xea\x4b\x58\x6d\xb4\x3d\xcc\x1e\x37\x64\x59\x8e\x9c\xa4\x66\x73\x82\x2b\xaa\x2a\xd8\x7f\xb1\x4b\x6f\xdb\x9e\x20\x32\xd0\xca\x51\xc2\x6c\x5e\xf3\xd9\xf7\x97\x85\xfa\xc2\x49\x1c\xdb\xf7\xc3\x99\xf3\xcd\x17\x74\xc1\xa6\xb1\xe4\xa6\x7f\x54\x36\xd8\x0d\xb0\x25\xf8\xfb\x64\x09\xe2\x75\xbd\x0e\xd5\x08\xb5\xe0\x39\xed\x2e\x4e\xec\x8b\x0f\x4d\x5b\xe9\x9d\xca\xfa\x6a\x14\x01\x25\x27\x32\xa6\x5b\x37\xc9\x43\xc0\x7e\xf3\xac\xbc\xfb\xb3\xdc\x06\xda\xd0\xa8\x8f\x2f\x5e\xb5\x51\xa3\x99\x7a\xd6\xc6\xee\xd9\x5e\xdd\x9a\x0a\xf4\xa2\x88\xd5\xe4\x32\x86\xb2\xac\x07\x29\x77\xc4\x36\xb7\xc5\xff\x7a\xb6\x1c\x94\x84\xf2\x57\xf5\x8e\x01\x0c\x9b\x6a\xd4\x15\x81\xd7\x42\xcd\x19\x75\x2c\xde\x54\xd2\xb4\x20\xd6\x43\x65\x4e\x90\x96\xa8\x1e\xb9\xdc\xf8\x04\xc7\xc2\xed\x0e\x38\xd1\x3a\x5c\xe3\x99\x78\xcd\xd0\x2b\x25\x35\x09\x45\xde\x78\xfe\xec\xc0\xc2\xc2\x2f\xfd\x70\x5c\x3b\xa8\x11\x32\x65\xc7\xb9\xa7\xc8\xdd\xb5\x91\x78\xbd\x21\xd7\xf6\xc3\x1c\x6b\xe2\xc3\x67\x49\xee\x0f\x9a\xb8\xbc\x1d\xcf\x5d\xa5\xcb\x2d\x2d\x59\x62\x35\x8f\x71\xf9\x6a\xb3\x79\x2a\x25\x2a\x51\x9e\x41\x53\x51\xf4\x3e\x7e\x12\x03\x5b\x03\x28\xf2\x82\x08\xcf\x4b\xe5\x29\xd2\x99\xaa\x5c\x12\x8c\x9d\x5e\xd5\x75\xbf\x90\xc5\x35\x05\x69\xea\xa6\xf2\xd5\x52\x1d\xe1\x18\x03\x09\xf6\x86\xc9\x7e\x9a\xd6\xfa\x1e\xc1\xdd\x86\x27\xae\x89\x51\x58\x1c\xf6\x04\xb8\xb9\x17\xc5\xba\x43\x4a\x63\x7b\xe1\xbc\x8b\x79\xf4\xac\xaf\x77\x95\xf4\xe5\x1a\xab\xdb\x88\x50\x77\xbc\x4f\x3c\x68\xfc\x33\x18\xde\x58\x23\xd7\xe0\x80\x4e\xe9\x95\xb7\x03\x87\x95\x0f\x79\x93\x53\x68\x23\x00\xd4\xe7\x97\xf3\xca\xd6\x11\xb4\xc5\x62\xc8\x64\x0f\xf2\xb3\xfe\x29\x29\x16\xa9\x70\xfb\x98\xc1\x47\x5c\x1f\x4e\x27\xb9\xb3\x3c\xfe\x0d\x3a\xd9\x32\xa1\xeb\xe6\xa2\x7f\xc3\xb4\x46\x62\x29\x54\xae\xe1\x68\x36\x68\xc8\xbd\x4a\x3f\x90\x3b\xe5\xc7\x7d\xfd\xb8\xe8\x91\x4c\xed\xc5\x1f\x65\xfe\xd2\xd9\xc4\xd0\x3e\x13\xa6\x68\xd4\xc7\xea\x5e\x31\x88\x3e\x1b\x3d\xb6\x43\x63\xe2\xac\x5c\xc5\x4b\x54\xce\x69\xc6\xad\x52\xf8\x74\x99\x9b\x5d\xd2\xc5\x78\x2f\x03\xc3\xd5\x15\x05\xdf\x53\x6a\x1f\xe0\xd8\x60\xd3\x3e\xab\xed\x64\x1a\x94\x00\x89\xf1\x29\x7d\xd0\xf5\x7f"}, -{{0xf8,0xff,0x97,0x03,0x2a,0x34,0xcf,0x99,0x99,0x08,0x80,0x58,0xaf,0x56,0xff,0x70,0xb6,0xac,0xb2,0xed,0xf7,0x59,0xe1,0x31,0xfa,0xec,0x84,0x40,0xfd,0xec,0xf6,0xc4,},{0x54,0x38,0xb4,0xe3,0x3f,0x1c,0x5e,0xa1,0x12,0xfb,0x1b,0xaf,0xef,0x40,0x59,0xbf,0x09,0x5a,0x11,0x40,0x9b,0x64,0xd4,0x6b,0xfb,0x4d,0x25,0x47,0x3c,0x1c,0x08,0x74,},{0x50,0x9e,0x9e,0xad,0xfe,0x8d,0xde,0x79,0x14,0xac,0x20,0xca,0xfc,0x0b,0x0a,0xf2,0x2b,0x84,0xdd,0x8a,0x21,0x0a,0x48,0x12,0xcd,0x8c,0xae,0x39,0xb0,0xa2,0x72,0xe5,0x3e,0x02,0x24,0x6d,0xc8,0x93,0x9e,0x92,0x26,0x92,0x03,0x36,0xe1,0x40,0xb3,0x15,0x32,0xd0,0x68,0x13,0x7a,0x34,0x16,0x1e,0x59,0x9a,0x86,0x94,0xa9,0x5d,0xdf,0x01,},"\xdf\xb4\x1f\xb9\xd5\x37\x02\xcb\x2b\x9e\x3f\xfc\xad\x4e\xa6\x02\x71\x6f\x71\x8a\x7e\xa3\x3e\x21\x84\x3e\x2a\x6c\x05\x2c\x70\xc6\xc5\x14\x85\xd7\x2b\x53\xa5\xbb\x4e\x34\xe0\x3e\x3e\x1d\x1a\x52\x51\x8e\xb3\xe7\xf1\x8f\x2a\x1e\x1c\xaf\x78\xac\xb2\x11\x60\x89\xbe\xd4\xc6\x17\x13\x8e\x71\x6a\x91\x43\x1f\x2c\xf6\x44\xa1\x21\x0f\x6d\x19\x20\xd2\x85\x99\x42\x64\xd6\x46\x6b\x0d\x8d\x2c\x62\x63\x80\x44\x61\x6f\x57\x6e\xdc\x7d\x0d\x93\xcb\x66\x01\x31\xd4\xbb\x50\x87\x5e\x15\x36\x40\x12\x3a\x96\xf1\x5b\x75\xa5\xbc\xee\x46\xd5\xcc\x5e\xb1\xa4\x31\xc5\x9d\x2e\xad\xdf\xd5\x53\x15\x02\xfe\xb1\x55\x1b\xf7\x79\x1c\xd5\x98\x9d\x17\xd1\x02\x96\xd0\x1b\xa3\xae\x3e\x38\x4c\x67\x45\x26\xca\xb6\x2a\x7c\x24\xc0\xff\x67\x7d\xe7\x1c\xa1\x72\x62\x1a\x28\xa8\x5e\x01\xee\xfe\x07\xf6\xee\xf9\xc3\xec\xfd\x7f\x94\x98\xac\x42\xf4\x6a\x43\x71\x6f\x61\x53\x18\xa3\xb2\x87\x57\xc3\xa1\x5f\x4f\x1c\x38\x22\xae\x7a\x75\xc2\x03\xa2\x98\x25\x8d\x75\x36\x38\xcf\x42\x5e\x15\xbb\xc4\x62\x02\xb0\x93\xb8\xe4\xf3\xe6\x70\xfb\xb6\x63\xdb\x2b\x69\xc8\xfb\x0f\x62\x50\x74\xd8\x5a\x44\xd3\x50\xe0\x42\xbb\x1b\x74\x02\x1d\x19\x29\x97\xa2\xc2\x7d\xd6\xc8\x63\x48\x41\xd1\x00\xa0\x34\x4b\xae\xd7\x50\xa3\x9f\xf5\xdc\xd9\x84\x8d\xfc\xf0\x9e\x5c\x8c\x47\x96\x7b\x96\x55\x6e\x23\x32\xca\x17\xd8\xe4\x2d\xd8\xf3\x93\xa5\x44\x5a\x37\x22\x44\x60\x0b\x30\x01\xb8\xfe\x86\xc4\x5e\xaf\xc6\xe7\x38\xaa\x7e\x11\x7b\x4a\x79\xfa\x2e\x6b\x00\xf4\x64\x92\x8d\x18\x56\xc8\x3e\xcf\xe8\x7d\xd3\x4d\x15\x8f\x5c\xb4\xe4\xf4\xd6\x10\xf5\x97\x17\xec\x79\x0b\xd3\xff\x87\x20\x40\xb6\x7e\x8d\x39\x39\xe8\x04\xe3\xb5\xdb\x98\x5a\x09\x56\x21\xcb\xcc\xd6\x86\xc0\x93\x4e\xce\x3e\x27\xab\x2c\x6c\xe3\x3f\xb5\x2b\x11\x1f\x48\xe4\xf2\x74\xbd\xf3\x20\xd0\xb0\x23\x84\xc8\x3c\x49\xe1\xa0\x41\xbd\x23\x19\x10\x9c\x85\xa0\x6d\x80\x48\xa9\x93\x35\x7a\xbf\xd8\x11\xac\x2f\x38\x05\x9d\x07\x7a\xcb\xc3\x6a\xa9\x66\xc0\x28\x90\x37\x48\x62\x5f\x92\xe8\xf7\x9d\x51\xbd\xa1\x0f\x78\x52\x29\x77\xf7\x6e\xc4\xe8\x85\xe4\x9a\x46\xc6\x8d\xe0\x9f\x3d\xa8\xf8\x6b\x71\xae\x64\x23\xbd\x29\xde\xef\x1c\xc6\xa1\x13\xea\xc1\x15\xa6\xcd\xe2\xcc\xd0\x11\xfc\x1c\x0f\x0e\x34\x27\xf4\x3c\x3e\x96\xfc\x41\x56\xed\xf6\x2d\xdf\xb7\xb0\x83\x6b\x88\x8b\xab\x3c\x43\x45\x05\x5a\x6c\x41\x78\xe9\xe2\x28\x29\xfd\x8c\xfc\xe3\x9b\x0b\x84\x44\xeb\x26\x48\x7c\xc9\xdc\x82\x60\x6f\xea\xad\xaf\x49\x78\x69\x4e\x65\x64\xf2\x72\x9c\x1b\x13\xab\x37\xc9\x07\x2d\xb4\xe9\xde\x94\x0e\xe5\xf1\xd0\x58\x84\xae\x7f\xd9\xd9\xec\x9c\xb7\xde\x56\x34\x76\x00\xa8\x8d\xea\x92\x08\xa6\x34\x19\xfc\xe2\x9e\xe5\x00\x55\xa3\x74\xa8\xf2\x2f\x9a\xe2\xbe\x98\x05\xa9\xf4\x76\x15\xaa\x59\x57\x6b\x44\x04\x2f\xf1\x26\xa8\x98\x24\xe3\x6a\xd6\xbc\x58\xe0\x6b\xb9\x0f\xbe\xef\xba\xe5\xd6\xd7\xd6\x24\x30\xf3\x73\xb6\x29\x6f\xbf\xcd\x4d\x66\x20\x16\x83\x53\x58\x3f\xbd\x3d\x5a\x29\x2b\x95\x72\x51\x75\x34\xe2\xfb\x0b\xee\xf2\xfa\x98\xa4\x64\xe5\x91\x03\xe7\xa0\x42\x87\xf1\x5d\xad\x0f\xac\x54\x97\x0e\x77\x15\x07\x8d\x63\xec\x26\x36\x2f\x6f\xba\xbc\xdd\xea\xf7"}, -{{0x2e,0x4c,0x39,0x21,0x9f,0xc9,0x2a,0x53,0x8e,0x48,0xe9,0x5f,0xbf,0xcf,0xef,0x30,0xf5,0xa2,0x1b,0x78,0x94,0x0b,0x81,0x05,0x3b,0xda,0xd4,0x60,0x2b,0x4c,0x96,0x90,},{0xf8,0xee,0xd8,0x92,0x17,0x66,0x20,0x43,0x4c,0x7f,0x0e,0xc5,0x3d,0xcf,0xf3,0x98,0x63,0x10,0x9e,0x7c,0xa4,0xd0,0xb3,0xc6,0xc4,0xb5,0x64,0x10,0xbe,0x01,0xe5,0x37,},{0x39,0x45,0x20,0x12,0x2b,0xb0,0xa5,0x64,0x64,0x8a,0x7a,0x8b,0xc8,0xdc,0x73,0x63,0x6c,0x51,0x77,0x46,0xa3,0xc8,0xa0,0x5b,0x90,0x1e,0x72,0x52,0xfe,0xf0,0xe5,0x02,0x3d,0x90,0x99,0x1e,0x31,0x1b,0x53,0x82,0xd4,0x91,0x00,0xe5,0x26,0x33,0xc7,0x0f,0xe9,0xc2,0x6c,0x14,0x50,0xe0,0x60,0x3e,0x6d,0x45,0x22,0x99,0xaf,0x4d,0xae,0x07,},"\xc8\x7d\x1f\xba\x9d\x94\xa6\xa5\x40\x89\x80\xfc\x80\x83\x98\x0f\xd2\xd2\x52\xfa\xe5\x40\xf6\xee\xc1\x9e\xd6\x74\x6c\x29\xe3\x39\xa1\xc2\x9f\x6f\x53\xbc\x23\xfd\x6b\xfa\x43\x85\x07\xef\xf5\xda\xf9\x03\x40\x3c\xda\x70\x7b\x4d\xc5\xe8\x44\x80\x5d\x6b\x1c\xeb\x4a\xff\xf4\xb2\x32\xe8\xe6\x9d\x7d\x27\x1f\x3c\x06\x7c\x48\x54\xf3\xd9\x4f\x27\xfe\x32\x55\x81\xfa\xca\x79\xd1\xf0\x2a\x26\x29\x0a\xd2\x3a\xf7\x11\x00\xc1\x2c\x09\x15\x76\x47\xca\x9d\xa4\x3d\x76\x90\xdd\xcd\x94\xdb\x65\xe0\x00\x98\x9c\x87\x8b\x75\xa0\xff\x22\xd2\xc7\x09\x62\x59\x4c\x9b\x08\x08\xf2\x78\x46\xcc\xac\x85\x67\xbc\xe5\xd2\xe3\xb7\x60\x28\x09\xf2\x3b\x59\xcd\x71\x8a\x08\x05\xd1\x08\xf3\x1a\x63\x2a\x05\xb8\xdf\xa5\x03\x5a\xb9\x46\x1a\xeb\xa4\x16\x00\x9d\x74\xfd\xf9\xe0\x07\x20\x28\x56\x89\x0d\x2c\xff\x80\xfa\x24\x0b\x97\x8a\x48\x27\x0f\xcb\x2f\x47\x36\x97\xbc\xba\x8e\x73\x0a\x55\xc2\x87\x61\x91\x9a\x23\xbe\x41\xda\x27\xff\xea\x09\xe3\x55\x9c\xaa\xab\xf9\x51\x9e\xc0\x8e\x1f\xfa\x86\x81\x7a\xa3\xe8\x87\x4f\xa8\x16\xe7\x71\x8c\x5b\x2f\x34\x49\x67\xba\x1b\xc2\x81\x9c\x4f\x04\x5a\x97\xb4\x05\x44\xea\x61\xd7\x17\x08\x3c\xca\xf1\x1e\x9d\xdc\x04\xa3\x59\x8e\xf1\x81\xe7\xbe\xf4\xac\xef\x45\xb6\x55\x1b\x47\x8a\x0d\x77\x31\xc4\xf0\x8c\xe5\x80\x2f\x78\x25\x8d\x41\x90\x17\x66\x10\x76\xd7\xd6\xd2\xef\x39\xe5\x7c\xf9\xcd\x93\x97\xdc\xc5\xde\xbf\x64\xab\x82\xb6\x61\x59\xf5\x78\x31\x6e\x74\xcd\x49\xf5\xad\x2c\x6f\xef\x83\xcf\x08\x68\x3b\x95\x70\xa9\x46\xad\x49\x03\xdf\x4e\x96\xec\x00\x8e\x14\xa5\x01\xfa\x93\x86\xbd\xaf\x2a\x63\x99\x3c\x6c\x9b\xdf\x23\x1f\xd0\x9e\xa6\xf9\x6e\xf4\xd4\xe2\x9a\x3a\x33\x27\xcb\xf7\x4e\xa8\x31\x05\x4e\x66\xca\x86\x68\x0c\x6c\xe5\x3b\x66\xf9\x46\x5d\x06\xb3\xfa\x07\x98\xbb\x69\x05\xae\x38\x45\x59\x34\xf2\xfb\x7e\x0b\xa4\x72\x32\x89\x89\xf0\x01\x30\x86\x71\xcc\xcb\x56\x6d\x22\x2c\x72\x16\x5b\xb3\xa7\x44\xfb\x98\xe2\x21\x0f\x96\x20\x68\x0d\xf3\xe3\xcd\x14\xa8\xbd\x94\xb5\x74\x5c\x00\x16\xdd\xa7\x7f\x05\x9f\x26\x05\x3b\x64\xcf\x45\x23\xc3\xd4\x29\x11\x2f\xb6\xb3\x28\x39\x8b\xc6\x30\xa2\xe9\x06\xb9\x5a\x6c\x57\x80\xcf\xdc\x06\x41\xbe\x47\x51\xbe\xbd\xdf\x77\x24\xdc\x9c\x27\xe7\x8d\x60\xed\x0f\xd7\x36\xd5\xab\xd8\x89\x29\xc1\x79\x5d\x47\x3a\xbd\x2b\x03\x20\xc5\x40\x47\x57\x28\x82\x18\x67\xa4\x09\xa2\xff\x13\xcc\x44\xce\x35\xe5\x98\x1e\x9f\x6b\x87\xa2\x8d\x4f\xa8\xb8\x67\x5e\x50\x3f\xae\xfc\xa7\xc1\xd7\x98\x47\x37\x87\x1f\xe9\x19\xac\x41\x4e\xea\x26\x5e\xe3\x1f\x9f\x78\xf5\x21\xf3\xf4\xf8\xd0\x0c\x3f\xb7\x91\x71\xf3\xc6\xa5\xdb\xf5\xe1\xac\x8b\xf6\x3b\x4c\x3d\x8d\x8b\xc1\x21\x03\x6e\x9e\x55\xbb\x70\x2e\xa6\xc8\x6e\x92\x5e\xc0\xb9\x84\xde\xd2\xc7\x1f\x3b\xfd\x49\x32\xe6\xc4\x1b\x58\x2f\xd0\x2c\xa5\x9f\x53\xce\x29\x74\x45\x78\x5c\xc4\xca\xc2\x47\xb0\xb8\x4e\x7f\xa0\xbc\xdc\xf7\x9b\x3e\x4a\x15\x5f\x98\x78\xc1\xf6\x43\xbe\x9c\x42\xf7\xa4\xf2\x72\x60\x44\x45\x05\xc1\x84\x5b\xd5\x3b\x55\x0a\x31\xd7\x95\x3c\xc7\x38\x86\x1f\x46\xbd\xf4\x87\x0f\x3a\x77\xac\xe1\x91\xab\xd6\x3c\x45\xad\xb1\x53\x90\x9f\xb5\x9a\xb5\xdb\x9b"}, -{{0xf0,0x92,0xe6,0xbe,0x8d,0x2d,0x9a,0xd0,0x69,0xa3,0xe2,0xb9,0x76,0xd2,0x44,0xe3,0x4c,0x15,0xc2,0x8c,0x48,0xd3,0x2f,0x55,0x60,0xa5,0x41,0x85,0xd1,0x50,0x15,0x02,},{0xcf,0xeb,0x3e,0x74,0xe4,0xb5,0xc8,0x35,0x6a,0x81,0x75,0x7b,0x8f,0x1b,0xe4,0xb4,0x29,0xfc,0x18,0xfc,0xaf,0x49,0x7c,0xbf,0x8d,0x8b,0xc0,0x48,0x0f,0xf9,0x78,0xf9,},{0x63,0xcd,0x4c,0x0b,0xa3,0xbe,0x93,0x97,0xcc,0x0f,0x3c,0x1a,0xf3,0x48,0xec,0x4b,0x8a,0x91,0xe4,0x2f,0xee,0x67,0x5d,0xa1,0xd0,0x59,0x00,0xb9,0xa8,0x6c,0x13,0x8f,0x91,0x74,0xeb,0x99,0x6b,0xbd,0xf3,0x1c,0x42,0x95,0xe0,0xc5,0x78,0xac,0x0f,0x9d,0x53,0x76,0x41,0xa2,0xaf,0xd5,0xdf,0xf9,0x3a,0x39,0xc5,0xcd,0x9d,0x3c,0x48,0x0b,},"\x2c\x25\x5f\xb2\x5d\x45\xb0\x86\xc0\x71\xe0\x3e\x52\x5b\x4d\x72\x85\x78\xfb\xb6\xb0\xc6\x0d\xa9\x41\xe6\xbf\x2a\x48\x98\xb2\xd5\xb6\x98\x8c\x53\x30\x27\x85\xab\x7a\x3b\xc4\xbb\x2c\x20\x5a\xcd\x27\xd6\xa4\xcb\xdd\x1a\x0c\x08\x89\xde\xd7\x84\x26\x4c\xb7\xc0\x28\x89\xc5\xc7\x11\x3f\xc9\x0b\xbb\xcd\x31\xff\x00\x14\x32\xc0\x53\xf9\x71\x07\x3c\xf6\x71\x2f\x66\x7f\xce\x46\x98\x77\x6b\x98\xcc\x54\x44\xc6\x92\xab\xd1\x28\x81\x98\xbe\x5a\xd5\x67\x46\x09\xf7\xe1\x39\xad\x1b\x9c\xcb\x94\x3f\x8d\xfd\x9d\x12\xc5\x4e\xce\xe2\x78\x34\x1b\x2e\xe1\x27\x79\x91\xca\x62\xcd\x3b\xfe\x12\x8d\x13\x92\x96\x4e\x95\x88\xe2\xf9\x7c\x32\x17\x04\xa3\xde\x10\x61\x88\xc5\xeb\x33\x5a\xa5\xa1\x9a\xcc\x90\x67\xb4\xa9\x41\x29\xb9\xd1\xa6\x16\x7c\x4b\xbf\xb5\x6f\xb9\x76\x84\xcb\xbd\x72\x0c\x86\x86\x9e\x00\x20\xab\x07\x76\xcd\xc9\x95\x4f\xeb\xa8\x62\x12\x4b\x07\x3f\xba\x8d\xe9\xea\x9a\x38\xea\xcf\xa0\x03\xae\x4f\x1c\xdc\xbf\x15\xc3\x2f\xb6\xb9\x70\xc7\x31\x15\xdd\xff\xcd\x4f\xa3\xb7\x18\x46\x11\x0e\xde\xc2\x57\xfc\xae\xd6\x11\x36\x04\xf7\x19\x25\x72\x57\x72\x64\xb9\x90\x5c\xa6\xae\xd8\xda\xec\x13\x84\x03\xca\x41\xaa\x95\x42\x78\xa5\x72\x0b\x26\x7b\x90\xca\x16\x3a\x9b\xdf\x44\x7e\xad\xe8\xde\xb7\x69\xa3\xb4\x92\x37\xa7\x35\x16\x97\x7c\x28\x73\x45\x55\xdd\x23\x4c\xa7\xde\x49\x99\x26\x1b\xc7\x96\x0f\x53\x6b\xa8\xa3\x5a\xd3\xd0\x2c\x75\xf1\xc2\xbe\xa0\xa0\x61\x2e\x7d\x49\xc4\x03\x97\xdd\x6a\xf5\xff\x58\xba\xe6\xa6\x4b\x6a\x77\xe9\x81\xf9\x2d\x15\x9e\x0b\x2b\xd2\x05\xab\x15\x70\x52\xf4\x70\x17\xa3\xe1\x8a\xec\x94\x4d\x04\x65\xee\x00\x17\xe9\x61\x48\xa6\x12\x9f\x74\xd3\xcc\xb4\x89\xfe\xa1\x3a\x15\xa9\xb9\xac\xed\x58\xc6\xee\x0e\x6e\x84\xe0\x5f\xda\xdf\xae\x07\xb3\x34\xa9\x8f\xc3\x7f\x7e\x51\x1c\xd5\xa4\x4e\x9c\x74\xe4\x78\xd3\x49\xe3\x0e\x29\xae\xb4\x6a\x4d\xf0\x1e\x43\x07\xfe\x65\xe1\x39\x4a\x75\x8f\x6a\xda\x2f\xb1\x20\x22\x5c\xcd\x50\xa4\x90\x13\xe6\xc9\xf1\x75\xaf\x90\xf3\xfc\x8c\x57\xe7\xa6\xa9\x69\xa9\x16\xc3\xf1\xaa\xcc\x22\xf3\xe0\x1a\x07\x0c\xc4\x8e\x6f\xd8\x78\xe2\xbd\x07\x3d\xf9\xee\x6f\x05\x9b\x98\x56\x84\x04\xfc\x7e\xae\x7d\x4b\xf6\xfa\x16\xc0\xc8\x03\xc6\xbe\x84\xe8\xb7\x9c\x67\xaf\xfc\x8c\x88\xca\xbd\xee\xbc\x11\x34\xbb\x23\x86\xe2\x2b\xa4\xd2\xe9\xe0\xf3\xe1\xab\x3a\x0d\xac\x7c\x80\xdd\xee\xd7\x73\xcd\xa0\xc4\x1d\xc9\xde\xfa\x67\xfe\xa3\x77\x69\xcb\x4a\x1e\x15\x22\xd7\xe0\xb3\xd7\xc4\x63\x8b\xcd\x98\x31\x53\xd4\x78\xbe\x5e\xcf\x2b\x6a\xb1\xb4\x01\x24\xe4\x22\x2b\x8c\xaa\x46\x47\xbd\x50\xd7\x4d\x20\x39\x43\xab\x20\x93\x8d\x5f\x27\xd9\x08\xa6\x73\x67\x40\x46\xce\x2e\xf1\x8e\x85\x8b\x0a\x01\xa7\xe7\x53\x0d\xed\x0f\x8c\xc8\x9e\xf0\x9b\x73\xca\x59\x7c\xf7\x3a\xfb\xc9\xa2\x71\xa4\xd2\x3c\x92\xfe\x59\x18\x83\xc4\x40\x10\x9c\x4e\xf4\x16\x67\x0b\x7f\x2c\x59\x05\xb7\x7f\x65\xf5\x6d\x09\xd4\x02\x50\x35\x6f\x9b\x1d\xbc\xaf\x1e\xe2\xc0\xb6\x36\x96\xf8\x4d\x68\xdd\xbe\xa1\x60\x08\x51\x51\xa9\x52\x62\x74\xd7\xb8\x46\xcc\xeb\x6c\x43\x48\x09\x84\x84\xde\x3b\xb7\x23\xae\x5e\x85\x27\x6d\xf4\x9f\x56\x34\x13\x0f\xf9\x05\x75\x4f"}, -{{0x01,0xa2,0x47,0x94,0x3a,0xfe,0x83,0xf0,0x36,0xb6,0xb6,0x0f,0x23,0xd9,0x77,0x74,0xfd,0x23,0x20,0x8e,0xdc,0x31,0xcf,0x3d,0x88,0x20,0xe9,0xdc,0x63,0x66,0x11,0x03,},{0x8c,0x97,0xa5,0x8b,0xe0,0xe8,0x47,0xc4,0x8a,0x6a,0x39,0x87,0xcf,0xe2,0x50,0xa8,0xd7,0xb0,0x7d,0x97,0xf9,0x61,0xf6,0xb7,0xb7,0x9e,0x7d,0x80,0x42,0xb8,0xbd,0x7b,},{0xed,0x2c,0xed,0x1a,0x4f,0xdd,0xb3,0x44,0x2a,0x63,0x73,0x48,0x17,0x9a,0x6a,0x5b,0xee,0xdc,0xb4,0x4c,0x8e,0x98,0x8c,0xa2,0x6f,0x78,0x93,0x6d,0x2c,0x8d,0xb5,0xc5,0x16,0xd5,0x4b,0x8c,0x4f,0x08,0xd9,0x1d,0xd7,0x04,0x2a,0xb6,0xab,0x26,0xd8,0x7f,0x23,0x0e,0xb2,0xb2,0x15,0x6f,0x3c,0xe2,0x99,0x4f,0xce,0x7c,0x2b,0x0f,0x10,0x0e,},"\x08\xd8\x14\x95\xda\x77\xf4\x07\x25\x5c\xc4\x1a\x81\x8e\xef\xa7\x27\xe2\xc4\x7a\xe4\x11\xf4\xb5\x41\xf0\x1f\x81\x1d\x90\x6d\x55\xfb\x1e\x3c\x9c\x48\x4d\xf3\x05\x65\x36\x4d\xe9\xdc\xb9\xfe\xa0\xaf\x66\x11\x2f\xe7\x5f\xd1\x1a\xe8\x1d\x26\x41\xb5\x47\x58\x9f\x8b\x97\x4a\x97\xe7\x97\x6e\xd6\x92\xaa\xd6\x40\xed\xd2\x88\xbd\x86\x3d\x11\xc4\xca\x98\x36\xf9\xd7\xc1\x15\xc3\xd9\x88\x30\xd6\x42\x47\xcb\x6f\x8f\xb6\x03\xc6\x98\x11\x33\x55\x2a\x32\x04\x04\x19\x61\xbd\xd8\x3e\x2f\x9d\xeb\xa7\x70\xc0\x39\x4f\x9b\x60\x2a\x45\x35\x51\x07\x49\x21\xa3\xde\x28\x32\x13\x69\xd7\xf8\xca\x64\x0c\x45\x10\x9e\x8f\x52\x2c\x97\xed\x9f\x35\xb9\x27\x7a\x35\x0e\x29\x59\x31\xb4\x2e\x01\x35\xe9\x4a\x92\xfe\xd3\x63\xd6\xca\xe3\x92\xf7\xc4\x51\x99\x32\x7e\x24\xb4\xcf\xa5\x89\x8a\xb5\x99\xae\x7b\xd5\x0b\xd3\xa0\x0c\x0d\x00\x7e\x95\xfa\xf8\xf2\xae\x10\x38\x02\xca\x7e\x53\xb2\x79\x18\x4d\x06\x90\x5f\x57\x48\xca\x8b\xe1\xf7\x2e\x66\x8c\xb8\x32\x83\xdd\x00\x40\x64\x91\xf8\xb9\xb4\xe5\xa9\xd4\xa5\x43\x8b\x2f\xa4\x37\x1e\x0b\x05\x68\x6f\x87\x57\x5b\xaa\x79\x6e\x30\x2f\x08\xff\xc4\x25\x66\x27\x50\xa3\x3a\x0c\x9c\xfa\xa4\xb4\xd7\x04\x1f\x92\x64\xfe\xd7\xbe\x4f\x9f\xde\x2c\xac\x68\xa2\x15\x82\x36\xf6\xac\x43\x04\x7e\x91\x1f\x4c\x4e\x8b\xc6\x63\xfd\xd5\x05\x17\xdf\xaa\x8f\xbc\xd2\x19\xdd\x7a\x0e\x93\x69\xf4\x3d\x0d\xd2\x5b\x4f\x0c\xf9\x30\xf2\x0b\x7b\x7c\x6d\xb9\xd5\xbe\x0c\x6e\x19\x60\x94\x1a\x3e\x04\xd1\x41\xc0\x3e\x59\x61\xaa\x33\xe9\x02\x44\x77\xd5\x33\xc9\x95\x37\x87\x96\xbf\x22\x92\xad\xe9\x22\x69\x5b\x14\x56\x9f\xc3\x39\xb3\xd9\x08\x5c\x63\xfc\x6e\x5b\xef\x4d\x99\x0c\x80\x33\x3a\x6b\x57\xaf\x47\x8f\x93\x8e\x3e\xe7\x38\xb1\xd1\x29\xbd\x97\x6a\xfe\x68\x61\x28\xbc\xac\x08\xcc\xbe\xb0\x34\x9b\x9b\x53\x73\x13\xbc\x7b\xf5\x91\xc6\x5d\x4a\x71\x23\xad\x30\xbd\xbe\x14\x86\xb4\x28\x08\x47\x48\xb6\x50\x7f\x6f\x5e\xf6\x7c\x26\xca\x86\x2c\xf7\x26\xaa\xc1\x40\xb8\x61\xae\x0d\xc7\x4b\xb3\xc0\xb4\x89\x78\x9f\x17\x14\x5e\x9a\x85\x5a\x3e\x2b\x5d\xaa\xc4\x18\xd8\x35\x37\x33\x23\x9e\xf6\x9c\x7b\x56\x5b\x53\x03\xeb\x87\xbd\x7f\x64\x9a\xbf\x40\xa2\xf1\x35\xa2\x9e\xd2\x7e\x3b\xe4\xc1\x2c\xd6\xdd\xd2\xe5\x41\x8a\x99\x97\x43\x83\x66\x3f\x58\x49\xbf\x3c\xe5\x53\x2b\xf6\x4a\x80\xaa\x52\x11\x91\xd2\x53\x90\xbc\x19\xa4\x5e\xed\x1d\x3f\xec\xa1\xd9\xfc\xc0\xdb\x03\x1b\xfb\x48\xe4\x50\xbe\x3d\x45\x93\x35\x6d\x5b\xa0\xf3\x10\x47\xb4\x57\x74\x5f\x21\xe3\x2e\xbe\xa3\xca\x6c\x35\xf0\x5d\x78\xd8\xc3\x16\x40\xb0\xfe\xcb\x94\x01\x16\x56\x75\xc7\xf9\xcb\xb1\x9b\xc4\xb5\x67\x7c\x2c\xce\xdc\x4e\x7a\xaf\xb8\x41\x84\xc1\x91\x99\xac\xa0\xdb\x21\xcf\x50\x67\xdc\x3a\xf7\x69\xbc\xc6\x29\x35\x5f\xf7\x25\x7a\x9e\xfd\x71\xa6\xa9\x2d\x13\x0d\x35\xab\xee\x6e\x70\x60\x5b\x5c\xab\x93\xc0\x28\xfa\xc3\xaa\x23\x44\xba\x86\x1a\xc1\xe8\xce\x9a\x4b\x07\x0c\x3d\xf7\x40\xd2\x8c\x5e\xce\x0f\x1b\xc3\x1c\x2d\x7d\x1e\x5e\xcc\x76\x10\x44\x80\x93\x91\x33\xa1\x86\x60\xe4\xa3\xe4\x84\x6b\x25\x17\xbe\x3b\x8e\x7a\xfa\xfe\x07\x83\x91\xd8\xaa\x8e\x5c\x30\x13\x7e\x85\xd9\x4d\x64\xa2\x79\xfb\xee"}, -{{0x91,0xfd,0xef,0xcd,0xbc,0x99,0x0d,0x3e,0x8e,0xeb,0x60,0x17,0x04,0x34,0xda,0x10,0x83,0x1b,0x03,0x08,0x1f,0x6a,0xfd,0x0d,0x7e,0x12,0xb1,0x00,0x11,0xe0,0x2a,0xef,},{0xc5,0x8d,0x3e,0x20,0xb8,0xd4,0x7b,0xa4,0x55,0xb9,0x12,0x57,0x2d,0xc8,0x40,0x81,0x5e,0x3d,0x88,0x5f,0xa5,0x91,0x7d,0x1d,0xa4,0x84,0x08,0xb9,0xa9,0x56,0x40,0x98,},{0x51,0x01,0x12,0x22,0x3b,0x33,0xa5,0xab,0x15,0x64,0xf7,0x53,0x71,0x91,0xcd,0x29,0x2a,0x9d,0xbd,0x5a,0x32,0x3d,0x7a,0xdd,0x05,0x84,0xc1,0xb0,0xad,0x00,0xd0,0xac,0x71,0x99,0xc3,0xfb,0x75,0x8e,0x91,0x3f,0xf3,0xd7,0x16,0xc2,0xe9,0x0d,0xd9,0x0d,0x4e,0x8f,0x59,0x95,0x1e,0x87,0xef,0x8b,0x78,0x21,0x4a,0x51,0x75,0xc4,0xe6,0x08,},"\x5b\x0c\x1a\x3a\x95\xe0\xba\x74\x74\x76\x6c\x9b\xad\xfa\xe3\x4a\xb8\x60\xe0\xa6\xc0\x33\xa2\x2f\xba\x72\x11\x27\xf5\xbb\xee\xe8\xe2\xcb\xde\x1a\x1d\xfe\xb1\x8d\x55\x1c\x95\x99\x4d\x21\xe3\xeb\xc6\x8a\xfa\xe6\x85\x44\x4a\x3a\x41\x95\xbc\x75\x55\x38\x90\x3a\xcf\xa6\x71\x55\x92\xdd\xe2\x56\xe7\xa1\xb4\xc3\x63\xec\xa7\x1e\xf0\xf3\xa4\x8a\xe3\x44\x2d\x50\xd5\x66\x1b\x39\x40\x96\xb7\xec\x27\xbb\xf5\x29\x53\xf3\x04\x0c\xd2\x5b\x78\xce\x47\x55\x27\xe0\xcc\x59\xf1\xef\x9a\xe2\xe0\x59\x04\x31\x58\x2b\x2d\xf8\x14\x14\x99\x82\x9a\x2c\x5f\x7b\xbe\x35\x98\xe4\xc9\x6c\xc0\x1e\xde\x2f\x43\xb6\x56\x05\xb4\x88\x59\x37\x09\xc0\x94\xb5\xa0\x42\xb2\x85\x55\xfb\x52\x27\xa6\xd1\x56\x37\x6f\x3f\xf0\x7b\xd5\xc8\xbc\x68\x04\xd3\x9a\x32\x82\xac\x59\x70\xba\x08\xae\xbf\x75\x42\xb8\x45\xf6\xb5\xc2\x38\xc2\xce\x20\x44\x3f\x7f\x77\x55\xd7\x5f\xe4\xfa\x16\xb9\x64\x4c\xa3\xe2\x1d\x91\xa9\xa8\x7c\x68\x61\x15\x74\x8a\x16\xc0\xae\x4a\xe4\xe1\x6d\x1c\x71\xae\x60\x0b\x39\xcd\x25\xe5\x63\x3b\x39\x9f\xee\x7f\xf2\xe3\x62\xbe\xd2\x51\x25\xc6\xfd\x5c\x7f\x5f\xfa\x2d\xa2\x35\x3f\xd3\x5b\x78\x4a\x1b\x1b\x03\x19\x77\x47\x58\xb7\x39\x0c\x44\xdc\xc9\x2f\xca\x42\x01\xdf\xe1\xa3\x75\x69\xde\x05\xf0\x66\x4d\x08\xb9\x0d\x6e\x2b\xad\xc2\x1b\x92\xf9\xce\x87\x21\x42\x35\x7b\x96\x15\x08\x0a\xb7\x65\x9a\x24\x6f\xf0\x85\x2a\xdb\x17\xdf\xda\x70\xcf\x17\x54\x15\x7b\x13\xbc\x03\x2b\x4c\x5d\xeb\x8e\x10\x68\xb4\x69\x2b\x93\x16\x5d\xa3\x5e\xfc\x9d\xa8\x6a\xcb\xe6\xf8\x0f\x01\xbb\xc2\x6f\x57\x5e\xc5\xaf\x5b\x05\x0e\x98\x28\xaf\xde\x6c\x3b\x78\xe7\x33\xeb\x5a\x91\x24\x92\xf7\x65\xbc\xad\x73\x1b\x95\xe3\xab\x88\x96\xb6\x17\x58\xbf\x91\x3b\x9a\x15\x68\xf9\xc5\xb4\x60\x33\xcf\x45\xdc\xc1\x75\x0d\xa2\x06\x6c\x60\x8d\xc3\xd3\x43\x73\x8e\x84\x8d\xc3\x90\xcd\x47\x44\x32\xe9\x91\xd7\xaa\x2c\x5b\x27\x81\x42\x1e\xfe\x55\xe3\x6b\x0b\x42\xc1\xf4\x9a\xe2\x77\x48\x0b\x0f\xc5\xff\x68\x5b\xb5\xa3\x1b\xe3\xa0\xfa\x44\x82\x38\x16\x07\x70\x37\x54\x8a\x5c\x9b\x0e\x1c\xc6\xc6\x35\x04\xa4\x07\x57\x9a\x36\x32\xb3\xc9\x6f\xcd\x0d\xe5\xea\x1e\x4d\x6e\x87\xc0\xca\xf7\xb6\xca\xe3\x12\x0d\xb8\xb1\xf4\x61\x5c\xe6\xa7\x5a\x81\x65\x4f\x39\x04\x28\xb6\x4c\x21\x3e\x72\x7e\xec\x3a\xe7\xf9\xf4\x2d\xb9\x06\xf4\xde\x1f\xda\xdd\x34\xa3\xda\x2a\xeb\x12\xb4\xd9\xa1\x85\xf4\xa6\x0c\xb0\xc2\x67\x45\xf5\x30\xb4\x81\xfc\x97\x6a\x09\x3c\xe2\x4a\x30\x91\x6a\xf6\x05\xee\x94\xb0\x87\x85\x19\x3a\x94\x9d\x56\x9c\x4b\x7e\xf5\x96\x03\xbb\x62\x43\x60\xe7\xb4\x08\xd9\x8c\xa5\x09\xda\xf5\xa9\x2a\x6d\x40\x15\xbd\xb6\xf9\x7a\xd4\xff\x0c\xf0\x5c\x8f\x0c\xd5\x47\x6a\x93\x44\x26\xa0\x59\xf2\x44\x44\x46\xe5\x86\x4f\x08\x9e\x0f\x06\x75\x61\x59\x10\x66\x2d\x7c\x1e\x79\xa6\xc7\x5f\xa3\x14\xb7\xba\x2c\x64\x3b\x0d\x37\x65\x3e\xef\xe5\x93\x17\x2d\x1d\x33\x2c\x8d\xd6\x44\x92\xea\xf1\x04\xfb\x19\x57\xba\xa5\x20\x49\x44\x2d\x10\xb5\x6a\xf8\xea\xe8\xff\x82\xcd\x8f\x46\xa0\x49\x4b\xec\x2f\xcb\x9f\xad\xf1\x0c\xf7\x1a\x6e\xec\xd0\x54\x7d\xaf\xdc\x7a\xdb\xaa\x45\x03\x78\x3f\x94\x3a\x46\xb4\xad\x0e\x6d\xd7\xf2\xca\xb5\x56\x17"}, -{{0xef,0x00,0xb3,0xc1,0x81,0xf6,0x32,0x7d,0x02,0x25,0x67,0x51,0xcb,0x51,0xc2,0xc3,0x6c,0x0c,0x0a,0x78,0x07,0x63,0x40,0x54,0x8f,0x5b,0xc0,0x70,0xd8,0x6d,0x9e,0x26,},{0xdb,0x14,0xcd,0x32,0x58,0x8f,0xd7,0x41,0xe8,0xf4,0x2e,0x51,0x21,0xcc,0x81,0x1a,0xd4,0x50,0x63,0xf2,0x81,0x41,0xe8,0x3c,0x66,0x8f,0x07,0xd9,0x12,0x28,0xf0,0x49,},{0x13,0x9f,0x9c,0xb9,0x9b,0x99,0x5b,0xe6,0x58,0x8c,0xdd,0xb5,0x05,0x16,0x94,0x83,0x8f,0x9d,0x82,0xa6,0x07,0x61,0xfd,0xe3,0x04,0xb0,0x02,0x7f,0xf8,0x65,0x84,0xbf,0x65,0xc7,0x3c,0xc6,0xd2,0x53,0xe5,0x60,0xf6,0x55,0x25,0xdf,0x04,0xbf,0xe1,0x46,0xc8,0x3b,0x42,0x26,0x9c,0xf3,0x78,0x0f,0x8b,0xc3,0x92,0x43,0x78,0x94,0xae,0x01,},"\x7d\x6a\xbe\xc7\xa1\x1a\xf6\x73\x24\xce\x17\xb1\xd2\x0b\xb4\x0c\x66\x8a\x21\x9b\xc9\x5d\xf0\x5e\x32\x5d\x86\xf8\x87\x95\xe2\x64\xd4\x54\xfc\x5f\xa7\xd9\xc8\xaa\xfe\x77\xe9\x0a\x6a\xf6\xb5\x74\x53\xd8\x5b\x97\x0b\x55\x2a\x85\x6b\xa6\x59\xab\x31\xbd\x8a\x66\x0e\xb7\xd3\x58\x7b\x45\x3e\x5c\x5f\xc6\xb7\x94\x72\xb2\x6e\x8f\xf7\xdd\x6d\xb6\xbe\x35\x72\x54\x8b\x0d\x75\x4e\xd4\xd9\x85\xb8\xd9\x96\x5f\x88\xb9\x52\xfc\x4f\xa3\xb7\x61\xcc\xff\xc3\x53\x54\xdb\x0e\xb9\xc5\xa1\x71\x71\x8a\x8a\x55\x92\x87\x02\x13\x82\x7d\x36\x91\xba\xe7\xfd\x9c\x63\xf2\x05\x03\xe0\x43\x19\xb5\xe9\x53\x57\x9d\xe4\x7e\x3e\xf8\xe1\x62\x85\x49\x50\x3c\xb4\xf6\x87\x1b\xa2\x5d\xb8\x73\x47\x08\x0e\x53\x1a\x51\x7a\x8b\x72\x21\xe6\xad\x84\xdf\xf8\x32\x56\xd9\xab\x9a\x43\x3d\xe8\x71\xb9\xcb\x9c\x50\x44\x58\x9e\x67\x20\x6b\x31\x7a\x52\x06\xae\xba\x96\xc9\x2f\xd6\x09\x40\x71\xc6\x44\xfe\x52\x65\x8d\xed\x92\x20\xcf\x6a\xbd\x50\xe2\x30\x5a\x1c\x90\xfd\x66\xaa\xcf\xb3\x8e\xb0\x5e\xaf\xf6\xca\x5f\x85\xf4\x29\xcd\x57\x71\x6e\xb8\x77\x39\xa0\x2b\x64\xcf\xfa\x08\xc4\xf6\x85\xb0\x03\x10\xb5\xb4\x84\x49\x20\xdf\x21\x5a\x9f\x24\xa1\x76\x13\xae\xf8\x5f\xec\x94\xf5\x11\xdc\x8a\x42\x94\xed\xdc\xea\x11\xc0\x8c\x0b\x39\x9a\x23\xd9\x16\x38\x3e\x29\xad\xeb\x98\xc6\x5d\x41\xc7\x05\xa5\x7f\x84\x05\x20\xfa\x80\x8d\x7f\xd2\x5f\xdc\xe1\x59\xf7\xa0\x84\xd0\x62\x97\x4b\x30\x13\x2a\x57\x12\x42\xba\xff\x41\x96\x24\x6d\x6d\x75\x7b\x31\x2e\x9d\x60\x85\x53\xd2\xdc\x53\xb6\x23\xb2\xe9\x5c\x75\x38\xfb\xc5\xde\xb6\x2b\xa7\x37\x76\xd8\x5e\x51\x18\xfa\x1a\x30\x2d\x4d\x07\x6d\x99\xe1\x00\xf0\xdf\x11\x9c\x33\xfc\x66\xcd\xfe\x6f\xd4\x4d\x71\x99\x7b\x78\xc8\xf7\x89\x0c\x70\x73\x46\x05\x62\x20\xd1\xe9\xde\x88\xbc\x17\x3c\xf0\xb7\x6c\xb3\x02\x87\x7e\xc1\x6a\xf4\x6e\x4c\x31\x63\x9f\x54\xee\xdc\x16\xda\x9d\x9e\xb0\xad\x95\xbd\xa5\x45\xdf\xc4\xa7\x32\xb6\xda\x98\x14\x13\x6a\xb1\xb9\x39\x2a\x07\x1b\x02\x24\x73\xb3\x49\x05\x57\x69\x8b\x77\xe7\x44\x7a\xc8\x59\x0d\xca\xf4\xf2\x42\xad\x3d\xfb\xc0\xdf\x71\x6c\xc0\xea\x75\x36\x26\x97\x3d\xf0\x8d\x93\x5d\x17\x8e\x33\x12\xfb\xe2\xa7\xba\x9c\x50\x93\xc5\x3b\x92\x55\xea\xca\x29\xb7\x25\x78\xe3\xba\x1b\xdf\xaf\x0c\x9e\xce\x21\xa5\xdf\xf6\xea\x42\x15\x24\xf7\x0f\xc1\x90\x4e\x9a\x2c\xf7\xc5\x18\xbf\xcc\x7e\x36\x73\xee\x87\xff\x27\xe1\xca\x2a\xc3\x2b\xcb\x40\x91\xcb\x34\xa8\x2a\x71\x56\x3f\xf6\xa6\xa1\x5d\xa0\xeb\xd5\xbd\x10\x25\x6c\xe9\x60\xf4\xea\xa7\xfe\x35\xe1\x28\x88\x60\x50\xd0\x49\xfe\xc3\xa4\xab\x16\xd5\xb0\xc1\x07\x26\x7e\xae\x1a\xb8\x01\xea\x5b\x91\x98\x38\x39\xda\x1c\x48\x8c\x12\xf8\x64\xd7\xc3\xa7\x7f\x2b\x6a\xe2\x7d\x54\x01\x09\xf6\x8d\x78\x36\x4b\xb6\x27\x18\x3b\xd5\x03\x91\x75\x47\xaa\xf3\xb3\xa1\x80\x9d\xa0\x25\x77\xb3\xf0\x3a\x9a\x3f\x5a\xf4\x8c\x88\x02\xe2\x97\xc8\xbb\x63\xdb\x6a\x86\xd3\xea\x72\x7a\x6d\x71\x48\xb3\xaa\x44\x4b\x8d\x16\x8f\x38\xc6\xc8\xf2\x40\x88\xa4\x9a\xf3\x31\x77\xa3\x44\xad\xab\x2c\xf6\xe0\x8e\x0c\xb0\x37\x1e\xd5\x2b\xde\xad\x13\x2f\x77\xe7\xae\x3e\xe5\xd8\xfb\x17\xaf\xc0\xa0\xbb\x73\x11\xb9\x56\x0b\x67"}, -{{0xd0,0x71,0xd8,0xc5,0x57,0x8d,0x02,0x59,0x49,0x93,0x2a,0xa6,0xbf,0x6a,0x80,0xb1,0xcc,0x41,0x2f,0x10,0x6f,0x91,0x57,0x4e,0xe2,0x46,0x54,0xb4,0x45,0xee,0x9a,0x97,},{0x9b,0xcb,0xf7,0xd2,0x21,0x2f,0xb6,0x2c,0xcc,0xf8,0xb6,0xc7,0x68,0x03,0xa5,0xea,0x24,0x40,0x9d,0xa6,0x28,0x7e,0xfb,0xb8,0xb1,0xf0,0xc7,0xb3,0x0e,0xbd,0xd9,0x3e,},{0x0c,0x29,0x7a,0xbe,0x0f,0xd8,0xeb,0xcc,0x6b,0x77,0x19,0x98,0x75,0x5e,0x2c,0x6b,0xe0,0x7c,0x81,0x2b,0x5a,0x80,0x54,0x49,0x57,0x06,0x31,0x70,0xca,0x69,0x43,0x2e,0x72,0xb6,0x0d,0xaa,0xe3,0x22,0x95,0x8a,0x22,0x38,0xcd,0x6a,0x46,0x28,0x94,0xa3,0x87,0xee,0xf6,0x5b,0xf9,0x6f,0x63,0xf5,0x4c,0x08,0x56,0x87,0xa5,0x02,0x75,0x0e,},"\x3e\x8e\xe7\x0e\x51\xe5\x6e\xf5\x7f\x6e\x66\xb3\xa8\x84\xaa\x04\xa7\xb4\xd4\x59\x9f\xb9\xb4\x39\x96\xb3\x93\xa8\x68\x09\x35\x12\xea\x74\x1a\x0c\x6a\x94\xf4\x0c\xe4\x98\x62\xd2\xfd\x1f\x75\x51\xf4\x64\x7a\xbd\x80\x75\xbc\x1b\x74\x2a\xd4\x0e\x29\xa6\x04\x61\x30\x12\x24\xfe\x8f\x76\x92\xb1\x47\x72\x78\x2b\x4e\x89\x6b\x63\xfe\x05\xab\xd5\xff\x53\x14\xf9\xec\x80\x75\xf2\x8d\x90\x8c\xca\xaa\xce\x5e\x90\x5e\xa7\xf5\x7a\x49\x1b\x99\xb3\x59\x1e\xea\x54\xa6\xb7\x81\x91\x67\x74\x9d\x38\xa0\x47\x62\x06\x76\xa1\xa7\xaf\x11\xf4\x85\xa5\x5b\x7c\x87\x9e\x68\x50\x38\x08\x58\xc8\xf4\x5c\x0c\x1c\xcb\xd7\x40\x6e\xd0\x99\xd8\x4a\x74\x71\xb9\x35\x0c\x4d\xdb\x28\x47\x0b\xf5\xbf\x32\x7d\x5b\x3c\x22\xd8\x99\xb4\xc6\x60\x83\x9e\x10\x4a\x06\x22\xae\x85\xc8\x4a\xa9\xfc\x7f\x0a\x2c\x7c\xeb\x6e\x69\x1c\x49\xc0\x64\xb5\x31\x34\x99\x68\x3e\x8e\x03\xb2\x11\x5e\xda\x7d\xda\xd5\x5a\x49\xf9\xfb\xe6\x25\x44\xf9\x14\x51\x1c\xfb\xec\x6b\x84\xdb\xde\x7e\x80\x90\x9b\x45\xfb\x10\x50\x2e\x2c\xaa\xa7\x21\x24\xfd\x94\x56\xa3\x87\x2f\x95\x92\x70\x7e\x9a\x4c\x50\x12\xda\xa9\x72\xea\xf6\x5f\xab\xe5\x53\xde\xbe\x82\x57\x01\xef\xef\x5c\x75\x6b\xb4\x65\xe9\x66\xab\x68\xdd\x52\xf3\xdd\x00\xa4\x5c\xf6\xdc\x3f\x19\xb8\x6b\xb0\xdb\x4a\x86\xe4\x66\x98\x85\xa0\x74\x69\x6a\x67\xd8\xea\x21\x18\xc7\x66\xef\x62\x5f\x8a\x98\x02\x6f\x9f\x4a\x3c\x5c\xcc\xf9\x84\x6f\xdc\x90\xed\x93\xec\x7c\x1f\x3c\x70\x86\x95\x4f\xa2\xf0\xa4\xca\x96\xd4\x01\x84\xaa\x57\x54\x55\x27\xa1\xf9\x65\xc1\x1d\x84\x3c\x90\xc5\xa5\xe0\x8d\x7c\x11\xf2\xd5\x61\x00\x4e\x90\x57\x48\x52\xeb\x50\x46\xaa\x1e\xa7\xb6\x10\x09\xfd\x5d\xd7\xd6\x24\x2a\x8d\xf5\x8a\x9e\x8e\x55\x5c\x7f\x4c\xdc\x13\x0d\x69\x01\xbf\xe6\x79\x7f\xdc\x6c\x39\xbe\xec\xfb\xba\xb6\x62\x5b\x2e\x4f\xb9\xd8\x00\x02\x76\xd4\xa9\x4f\xc6\xfc\x10\x51\xfe\xff\xf5\xad\xeb\x72\x4b\x87\x09\x0d\xb0\xa2\xc6\x97\xd0\x56\x66\x4d\x99\x1f\xad\x80\xdc\x80\xfa\xb7\x00\xb1\xf1\xf2\xee\x27\x73\x4e\xbc\x26\xb2\xa6\x41\xc3\x2a\x0c\x91\x1b\x27\x0a\xc7\x6b\x0d\xa5\xc0\x89\x14\x97\x1c\x91\x12\x46\x3a\x70\x70\x9c\x0d\xda\xc7\x91\x00\x16\xf9\x13\xf6\x21\x00\x86\xd7\x25\x5c\xef\x11\x95\x57\x10\xf6\x51\x88\x9c\x83\x62\x1d\xd8\xa4\xfc\xd5\x36\x63\x02\xd6\xc9\xb5\x6e\xef\xcf\xac\x85\xc1\x4a\x94\x78\xb6\xd7\x18\x07\x54\x28\x80\x07\x60\x51\x5c\xab\x5f\x3d\x44\x55\xe2\xb9\x70\xdf\x9f\xe4\xbe\x83\x83\xd7\x04\x83\xbb\xdd\x75\x60\x71\xf5\x3b\x2f\x9c\x27\x5c\x7c\x85\x12\xd1\x63\x51\x8f\xe5\x55\x83\x75\x14\xc8\x67\x76\xc9\x47\xf2\x9a\x77\x57\x02\x87\x44\x6b\x69\xbe\x40\xc8\xd4\xab\xbd\x65\xef\x25\x07\x24\x9b\x5a\xec\x33\xac\xb7\xb8\xbd\x3f\x35\xbc\x85\x9b\xa4\xe3\x7b\xdb\x49\xcf\x91\x3d\x93\x98\x9c\x44\x38\xd2\xab\xcf\xa3\x88\xcc\x89\xd7\x8a\xc0\x62\x70\x65\x64\x92\xe7\x52\x8f\x29\xbd\xfe\x8c\xbb\x9b\xfa\x9e\x73\xc1\xda\x01\x3f\xc3\xce\x21\x05\x65\x76\x13\xff\x62\xbb\x0c\x3b\xf4\xde\xe3\xb0\xd2\x65\x9c\x72\x6e\x7b\xcd\x9e\x97\xec\xce\x92\x47\xd4\x60\x0d\xfe\xaf\x60\x44\x4e\xd8\x62\xb0\x0b\xa1\x1e\x70\xea\x88\xd4\xf0\xb6\xb5\x39\xfc\x9f\x36\xbb\x2a\x1a\x9e\xd2\xb3"}, -{{0xe9,0xd4,0x86,0xc2,0x9a,0xe8,0x11,0xb9,0x42,0xe1,0x0d,0x81,0xf0,0xa6,0x71,0x63,0x17,0xb8,0x42,0xc2,0xc5,0xbf,0xde,0xf5,0x5c,0xc4,0x32,0xb7,0xfc,0xae,0xb8,0x18,},{0x43,0xa5,0x2d,0x15,0xb9,0xf7,0x31,0xd7,0x37,0xb1,0xc4,0xdb,0xc3,0x22,0x27,0xa4,0x80,0x96,0x30,0x91,0xd2,0xc6,0x28,0x6f,0x48,0x2e,0xf1,0xe8,0x36,0x70,0x54,0xe5,},{0x65,0x19,0x1a,0xa8,0x85,0xdd,0xab,0x9f,0x67,0x27,0x18,0x79,0x95,0x2f,0xc6,0xaf,0xfe,0x41,0xca,0x20,0xeb,0x3b,0xcd,0x86,0x67,0x31,0x61,0xb0,0x3b,0x53,0x26,0x94,0xd6,0xdd,0x88,0x90,0x8e,0xb1,0xb1,0xee,0xc0,0x03,0xcf,0xcb,0xe6,0x14,0x6b,0x45,0x38,0xe2,0x1d,0xf5,0x59,0x69,0x91,0x2a,0x0d,0x7d,0x88,0x18,0xad,0x79,0x59,0x0d,},"\x14\xfe\x1e\xd5\xbb\xbd\x76\xcc\x73\xdc\x56\x50\xbd\xa9\x2d\xe8\x63\x26\xe2\x4d\x2f\x1f\x62\x24\xba\x85\x68\x94\x4d\x6f\xe3\x44\x26\x75\xdb\x96\xf1\xd8\x49\x8f\x16\x34\xff\x9b\x6e\x50\xcb\xa9\xdb\x4e\xb0\xb0\xb0\x21\xb2\xbe\xcf\xce\x4b\xef\x33\xc4\xce\x0e\x32\xc8\xa9\x83\x89\xec\xa9\xe0\x59\xa6\x62\xd6\xf0\x37\xc5\x4a\xa4\x0c\x76\xcd\xee\xe8\x56\x50\xf0\x89\xea\x56\xe1\x38\x3a\xb0\xf5\xc3\x6f\x6d\x66\x45\xff\x7e\x87\x66\x73\x01\xf9\x44\xfd\xc2\xed\x35\xb0\xd2\xc3\x5c\xb2\xe4\xb4\x56\x36\xe7\x49\x8e\x92\x7f\x58\x46\xb3\xe1\xed\xfb\xd1\x60\xa4\xae\xf3\x32\x0c\x34\x28\x49\x6b\xda\xaf\x7d\x3e\xd5\x6e\xf0\xb7\x25\x4a\xc5\x97\xbe\x58\x9a\x70\x58\x44\x16\x30\x0c\x1a\xdc\xfb\xa4\xf2\x2c\xfd\x4c\xd6\x61\xe1\xf5\x0f\x15\x5d\x17\x2f\xa5\x74\x8d\x29\x6b\x29\xcd\xd7\xeb\x81\x21\x48\x3f\xf1\xd9\xfe\x95\x3f\x94\x51\xc7\xc7\xa5\x42\x00\x72\x85\xee\x72\x46\xbc\x0f\xde\xa9\x38\x81\x40\x29\xab\xce\x05\x7a\x0e\xcb\x97\x4b\x12\xd3\x60\xea\xb6\xaf\xd3\x07\x97\xd6\x14\x45\xad\x2b\xac\x7e\x52\xbc\xe4\x34\x63\x15\xf7\x8e\xb8\x75\x42\xd5\x95\x28\xb2\xf6\xc5\x6d\x66\x24\x1c\xb4\x42\x03\x3f\x64\x3d\x3d\x2a\x67\xcb\x63\x7d\x8d\xa9\x5d\x4f\xd1\x23\x4b\x03\x1a\x3e\x51\x72\x3a\x1d\x26\xe6\xf5\xca\x07\x98\x73\x21\xad\x11\xa9\x0f\xcc\x1d\x4e\x2b\x0b\x89\x66\x50\xc3\xa7\x51\x8d\x56\x55\x29\xbe\xa8\x06\xa0\x5d\x44\x7e\x08\xd2\xa6\xa3\xdb\xf1\xa3\x69\x15\xb2\x95\x7c\xa5\xb4\x0e\x58\xb9\x7a\xd0\x36\x97\x35\xc4\x28\xbd\x6d\x69\xbd\x21\x00\x44\xb6\x51\x41\x8d\x98\xb0\x59\xd9\x0c\x83\xe4\x60\x11\xf4\x1c\x03\x2c\x56\x55\xa5\xef\x21\xac\x2c\x8c\x2b\xc9\x4b\xe0\x7e\x45\x42\x6a\x7a\xe5\xd4\x7b\x45\xf2\x7c\xf4\x28\x9c\xa4\xdd\xab\xe0\x8a\x12\xb9\x10\x20\x7d\xab\xb3\x4a\x46\xab\x75\xce\x69\xb5\x8e\x7e\x17\x66\x4b\xf3\x35\x9a\x8f\xb6\x8e\xb0\x32\xc9\xea\xa6\xdf\x87\x38\x29\xf0\xe0\x84\x85\x53\xf7\x32\xe1\xc3\xc0\x84\xb3\x2b\x7a\xf7\x50\x74\xe7\xbb\xaa\x4e\xb5\xd7\xea\xd7\xaf\xf9\x75\x80\x10\x9b\x60\xf4\xc7\x92\xf9\xe2\xa6\x51\x37\xb0\xaa\x48\x17\x5b\x81\x15\xd9\x13\x05\xf4\xc7\x7e\x2d\x08\xe7\xe8\xd7\xe7\x78\x5c\x96\x68\x42\xc2\xe3\x50\xfe\xd4\xf9\xe3\x3b\xf6\xe1\x84\xc5\x50\xb4\xb0\x6e\x95\x74\x14\xed\xf5\x2f\xa0\x79\xe8\x19\x73\x45\x84\x61\xfb\xb9\xb7\xd7\xd3\x4b\xef\x15\x03\x57\xf4\x32\xca\xac\x3a\xe9\xf3\xdc\x96\xeb\x5a\x2d\x12\x3e\x09\xed\xa1\x70\x2e\x1d\x10\x70\x17\x7b\xb2\x20\xc4\x23\xc0\x96\xec\x24\x42\x43\x85\xc6\x79\xbe\x02\xef\x84\xd0\x9e\xd1\x02\xf4\x9c\xad\x3b\x1f\xd6\x70\x67\x9a\x39\x71\x4f\xf1\xd6\xe4\x22\x8d\x8d\x7d\x0e\x19\xed\x0e\xba\x13\x2f\x21\x28\xd4\x7b\xaa\x56\x9a\x8e\xcb\x7b\xd4\x8a\x82\x62\x82\xf9\xcf\xcb\xf6\x0d\xde\xce\xaf\x1d\x02\x13\x2c\x8a\xff\xed\x3a\x03\xd2\x34\x0d\xeb\x78\x7c\xd6\x49\xc5\x1c\x6e\xcb\x9f\xf7\x5d\x7a\x7b\x4e\xf9\xb1\x51\x39\xcf\xea\x27\x62\xab\x18\x61\x51\x97\xa6\xb5\x1f\x6e\x75\xdb\xd0\x45\x73\xa2\x44\x80\x94\xd0\xcd\xeb\x0f\xe4\x58\x58\x83\xff\x9b\x68\x82\x4a\x04\xb8\x3e\xc9\x1c\xf8\x4a\xcd\x6a\x74\x46\xcb\x1f\x5e\xe3\x7d\x5d\xf8\x0f\x17\xcb\x2b\xdc\x3f\x31\x22\xa8\xfa\xf7\x6e\xbd\x06\xcf\xe8\x17"}, -{{0xe6,0xfa,0x10,0xdb,0xb4,0x78,0xe1,0xe3,0x6b,0x35,0xdf,0xeb,0x02,0x50,0xf6,0x3c,0x08,0x51,0x50,0x70,0xae,0x79,0xb2,0x2f,0x04,0x7e,0x27,0x17,0x08,0xd6,0x4f,0x5c,},{0xe0,0x2e,0x1f,0x2b,0xd8,0x79,0x2e,0xf4,0x83,0x48,0x1c,0x6d,0x11,0xf7,0xc7,0xc9,0xdb,0xde,0xec,0xc9,0x85,0x94,0x32,0xe7,0xf2,0x79,0xe9,0xd1,0x73,0xd3,0x11,0x64,},{0xc0,0x3c,0x47,0x03,0x59,0x12,0x7e,0x9d,0xe3,0xaf,0x0e,0x0e,0xd7,0xd3,0xb1,0x9f,0xae,0xe0,0xec,0x14,0x0b,0x79,0xc2,0x99,0xe2,0xcb,0x6d,0xac,0x0a,0x3e,0x7e,0x31,0x41,0x41,0xcc,0x85,0x4b,0x45,0x96,0xce,0x4c,0x51,0xc7,0xb0,0xde,0xc8,0xa5,0xc8,0xcf,0x09,0x36,0x20,0x53,0x61,0xd5,0x36,0x5f,0x4b,0xcc,0x07,0xc4,0x28,0x7c,0x07,},"\xad\x31\x60\x75\x8d\x8c\x08\xa6\x61\x52\x5c\x95\x28\x0a\x37\x18\x87\x49\x69\x85\x9f\x1c\xc9\x18\xe3\x4f\xec\x00\x8a\xcf\x23\xb8\x89\x6e\x8d\x50\xc3\xc0\x51\x23\x31\xdc\x89\x78\x0f\x8b\x10\xfc\x34\x9c\x67\x5c\x4c\xd8\x2a\x5d\xf8\x58\x6b\x43\xc8\x64\x44\x8f\xac\x00\xb8\x47\xb9\xc9\x80\x54\xab\x79\x3f\x63\xc7\x1a\xa5\xe5\x24\x8e\x22\xd0\x69\xbd\x3f\x85\x2a\x3b\x8c\x6e\x2a\xc8\xef\x86\x1d\x90\xbc\xd9\x84\xbf\xca\x87\x58\x3e\x59\xe9\xa7\x46\x8f\x29\xb8\x08\xdc\x2f\xe5\x30\x2a\x98\x9d\x6f\x2e\xcd\xe7\x58\x5c\xd9\xbe\x4e\x4c\x76\x1c\x4d\x4b\x3e\xea\xf4\x69\x9f\x65\x56\xef\x03\x9a\xf2\xb8\x0f\x94\x07\x60\x5a\xc3\x97\x35\x1d\xd8\x55\x95\x58\x44\x95\xba\xa1\x77\xb0\x8c\x88\xd2\xec\x1f\xc4\xe3\x2d\x1c\x0b\x8d\x7e\x7a\xc5\x83\x9d\xfb\x92\x3f\x09\xb3\x23\xe7\x8e\xce\xb7\xe9\x6c\x06\x04\xb0\x1a\x19\xe4\x9c\x9b\xea\xf4\xf2\x5e\xc4\xa8\x4c\x1a\x08\xf2\x38\x0e\xdd\xc3\xa7\xf0\x12\x18\x49\x59\xcc\xd1\x9e\xcb\xba\xc6\x5e\xac\xa1\x55\xce\xe9\xec\xfe\xc1\x1e\x7f\xee\x05\x8e\x17\x4f\xc4\xed\x7c\x67\x9f\x2c\x15\x63\x1d\x4e\x15\x27\xbc\xdb\x0e\x3b\xb0\x81\x5f\xfd\xff\xc0\xc8\x56\xbe\xf0\xdc\x0f\x5c\x82\x37\xf7\x09\x8e\x26\xbd\xb6\x9e\x87\x82\xd1\xca\x51\x11\xec\x3c\x7e\xdb\x42\x5d\xff\x80\x32\x02\x6c\xba\x3d\x2e\x08\x1b\x71\x31\x0d\xb9\xba\xda\xd1\xad\x02\xf1\xec\xcc\x53\x7d\x87\x4c\xd1\x8c\x6b\xb0\x12\x21\xf7\x1e\xe6\x62\x50\xd9\x4c\xf8\xec\xce\xaa\x96\xd3\xc5\x7e\xea\x2b\x0a\x8e\xc7\x24\x29\xd7\x60\x64\x88\xbd\xf1\x9e\xc3\xbb\x16\xe5\x08\x67\xc7\x93\x7d\xef\x09\xfc\x78\x3f\x20\xa2\xa5\xec\x99\x25\x3d\x6b\x24\x0d\xf4\x67\x7d\xd2\xd5\x27\x7b\x01\xc5\xb8\xe5\xbd\x6c\x7d\xf0\x87\x42\x05\xbc\x8c\x2f\xff\xdb\xa1\x31\x46\x74\xd3\x1c\x9b\x2c\x91\x99\x22\x8e\x19\xe0\x42\x18\x34\xc1\x65\x7d\x06\x98\x28\x69\x16\xc7\xe3\x92\xf0\xab\xd5\x54\x5b\x96\x3a\xc1\xff\xa9\x97\x21\x61\x6c\x23\x79\x6f\x85\xc3\x4a\x5c\x66\x4a\xe8\x1d\x16\xb2\x16\xa5\xb0\xcf\x5b\xc6\xb5\xa9\x08\x29\x72\x85\xd6\x16\x44\x12\x8f\x88\x6f\x38\xaf\x9e\xdd\x25\x19\x3d\x7e\xcc\x77\xa7\x99\x94\x27\x8d\xa0\x71\xf5\x44\x95\x93\x7f\xee\xf5\xa5\x19\x57\x52\x7c\x3e\xec\x7c\xb0\xb4\xe8\xaa\x7a\x4e\x85\x6d\xef\xd5\x7d\xd9\x23\x34\x15\x1b\x98\x6a\xa6\x9c\xa6\x92\x60\xd1\xe2\xd7\xb5\x3c\x05\x67\x7e\xe0\xd2\x16\xb2\x8d\x03\x62\x52\xdd\x30\x06\xde\xbe\x1b\x65\x74\xa2\x5e\x6b\x19\xdf\xb4\x8f\xa6\x43\x16\xaf\x8f\xd6\x8d\x78\x93\xb3\x97\xe7\xdb\x57\x80\xab\x27\xbf\x87\x26\xff\xf6\x05\xd3\xb4\x6d\x80\x05\x95\xb4\x62\x4b\xee\x30\x2c\x96\x43\x26\x03\x4b\x52\x34\xd1\x75\xdf\xdc\xc2\xce\x88\x2e\x65\xb3\xd9\x3a\x04\x38\xf6\x92\xe9\x69\x5d\xe1\xf2\x4c\x70\xa7\x9b\xee\xd2\x54\x15\xec\x5a\xae\xcf\x33\x91\x95\x3b\x2f\xfd\x45\x3a\x8f\x04\x67\x56\x1a\x4a\x47\xee\x14\x4a\x43\xfd\xff\x83\xdf\x2b\xea\x5f\x66\xa7\x22\xb5\x2a\xbe\x86\x13\xf2\x0c\x59\x4a\xf0\x98\x2e\xb3\xf0\x45\x05\xa5\x24\x61\xdd\x03\x4d\xa8\x6c\x36\xca\x16\x21\x77\x05\xc0\x48\x23\x91\x1d\x72\xa2\x47\x69\x51\x76\x33\x56\x28\x86\xf2\x50\xf2\xcf\x78\x8b\x8f\x32\x86\x4a\x94\x74\xf5\x7e\x62\xe5\x7d\xe8\xfd\xaf\x95\x9a\x6b\x72\x28\x74\x40\xa8"}, -{{0x05,0x8e,0x36,0x80,0xb8,0xfc,0xc0,0xaa,0x14,0x90,0x08,0x9c,0x11,0x24,0x67,0x7f,0x98,0xd7,0x4b,0x1b,0xfb,0x71,0xee,0x86,0x63,0xf0,0x25,0xf0,0xd9,0x46,0xcd,0x20,},{0xec,0x72,0xce,0x0e,0x82,0xc6,0xa3,0xb2,0x12,0x43,0xd2,0xf0,0x0e,0x9e,0x88,0x3a,0xdb,0xc5,0xcb,0x63,0xb3,0xd9,0x36,0xef,0xa5,0x0c,0x07,0xcb,0x92,0x91,0x48,0xe2,},{0x57,0x34,0xec,0x50,0xa7,0xf8,0x2e,0x48,0x53,0x6b,0xdc,0x43,0x70,0xcf,0xef,0x2e,0x15,0x0a,0x63,0x1d,0xab,0xaf,0x89,0xed,0xcf,0x0f,0xda,0xbe,0x4f,0x58,0x39,0xf4,0xf5,0xfb,0xd8,0xdf,0x8e,0xc4,0xa3,0xac,0xd4,0x0a,0x8b,0xfb,0x96,0x3d,0x18,0x55,0xff,0x92,0x74,0xdb,0xc3,0x31,0x65,0xb5,0xe6,0xd3,0x7a,0x23,0x9d,0xac,0xe9,0x03,},"\xe6\x3d\x14\xf5\xbe\xa7\xa1\xab\xb8\xfe\xe6\x97\x74\x6c\x22\x80\xdf\xd0\x62\x2d\xe7\x35\x72\x26\xcc\x07\x42\x72\x2a\x32\x29\xbe\x12\x6b\x08\x3e\x86\x8a\xea\xf0\x7d\x2f\xc9\x7a\xdc\x33\x42\x70\x96\x74\x19\x3c\xa2\x81\x74\x4e\x85\x0e\xa1\x54\x40\x05\x0a\xec\x93\x0e\x45\xd7\xa8\x7b\x8a\xc8\x01\x5c\x89\x67\xc2\x00\x33\xa5\x32\xd2\x95\x91\xb1\x35\x58\x6c\xe0\xfd\xd2\xe6\x68\xb5\xc8\x64\xb3\xbd\xe7\x0c\x7e\x71\x9a\xd2\x41\x93\x12\x51\x86\x19\x33\xff\xbf\xa9\x64\x83\xff\x82\x85\x67\x48\xc5\x6d\xc2\x6e\x25\x7d\x69\x2e\x51\x34\xd8\x2f\xc7\x19\x1c\x11\x0d\x95\x90\xd3\xfc\x75\x1c\xd6\x36\xb0\xc4\x6f\x44\xf8\x80\x3e\x59\xe2\xf9\x3f\xa0\xcb\xe2\x47\xa1\xa6\x25\xb4\xbc\x2c\x7b\x1f\xdc\xeb\x5a\x2b\x22\x59\x1f\xa6\x13\x7c\x54\x04\xdf\xec\x6a\x69\x63\x9e\x3f\x63\x2b\x59\x76\xab\x9f\xe1\xc6\x3a\xa3\xda\x9d\x52\xb0\x44\x00\x8f\x3a\xe4\x4b\x7c\x36\x4f\x08\x56\x64\x32\x3a\x88\xeb\x45\x83\xe8\x71\x40\xf7\x63\x78\x2b\xff\x88\x19\xcf\x74\x1a\x87\x5d\x50\x6c\x92\x9d\x34\xbb\xd4\x30\x07\xde\x4b\x18\xf6\x87\xa7\x58\x11\x11\x28\xb1\xdb\x86\xfc\x5a\xd2\xfb\x9f\xca\xd1\x2c\x9d\xd2\x8f\xee\x5a\xd1\x0d\xe0\x73\x9f\x8e\xfd\x9b\xff\x66\xf8\x40\xb1\x1b\x3f\x91\xc5\xe0\x7c\x21\x45\x2c\xab\x24\x24\x2b\x6e\x32\x16\x5c\xd1\xe6\x95\x72\xbf\x21\x6e\x86\x04\x53\xda\xd2\xfd\x12\x9c\x33\x37\x58\x58\x0b\xb7\xd0\xf1\x95\x09\x74\x5e\x85\x14\x63\xd1\x27\xa5\xf9\xbe\x21\xfe\x54\x9c\xae\x55\xd5\x6b\x8b\xea\x80\xbf\xaf\xda\xc1\x0a\xcd\x83\x8e\xa8\xaf\x31\xc0\x07\xdc\x32\xbf\xd7\x40\x82\xd9\x11\x0a\x3e\x91\xe6\x1e\x03\x57\x58\x7e\x4e\xd3\x28\x27\xad\xe9\xb6\x91\x0a\x98\x8c\x1d\x3b\x2d\xd2\x2c\x0e\xe7\x6e\xf3\x5f\xe1\x5e\x09\x94\x04\xa4\x5d\x4b\x2a\xca\xb9\x12\x3e\xcc\x45\x55\x0a\x40\xfa\xf8\x33\x6b\x46\xc6\x30\xa9\x08\x03\x58\xff\x8b\x8e\x58\xaf\x0b\xcc\xbd\x35\x01\x0c\x1e\xcc\x12\x81\x66\x55\xa5\xec\xeb\xa9\x5a\xd3\xf5\x03\xa1\x8e\xc5\xbe\xce\x3a\x33\xf4\x69\xdf\xe9\x17\xe1\xc5\x5e\xf1\xd8\x1e\x5a\x75\x56\x1e\x6b\xbd\x99\xc6\x53\xa6\xd0\x95\xb9\xf3\x87\x91\x1e\x40\x33\x2f\x62\x16\xf9\x56\xa3\x5c\xf7\xd9\x9a\x9f\xdd\x0c\x44\xc5\x1e\x90\xa5\x64\xf1\xc3\x6b\xf3\xd4\x0a\x7f\xaf\x4b\xa2\x8b\x1a\x12\x0b\x32\x05\xfb\xac\x1a\x98\x56\x92\x90\xbe\x37\xc5\x8b\xbd\x74\x5c\xe0\xfb\x74\x83\x52\x70\xab\xa2\x25\x2a\xda\xec\x15\x7d\xc4\x24\x61\x22\x1a\x2c\xff\x68\x7b\x9e\x65\xce\xb5\x7c\x2d\x77\x70\x0a\xea\x63\x20\x48\x6c\x5b\x1b\xec\x9c\xc5\x3e\x7e\xf9\xe4\x8f\xcd\x1b\x77\x83\xac\xbe\x75\xa6\xbe\x02\x67\x27\x88\x12\xdb\xf3\xd2\x57\x6c\xf7\xad\x39\x11\x27\x1a\xce\xbe\x0f\x2c\x04\x60\x2a\x08\x0c\x8b\x96\xc1\x20\xfd\x86\xfd\xa2\x82\xaa\x4e\x1c\x13\x1f\xe9\x7c\x90\x7c\x15\x85\x5f\x87\x75\x5f\x51\x1c\x03\x7b\xef\xad\x0f\x56\xb3\x9f\x32\xa2\x13\x3a\x22\xf3\xd5\xa9\xbe\xc3\x44\x3f\x29\xa6\x94\xe9\x7f\xe0\x5e\x10\xfb\x8e\xf9\x99\x13\x02\xb9\xe0\xd8\x4d\x92\x9a\x19\xeb\x03\x47\x1f\x3a\x86\x13\xd3\x93\x68\xe1\x58\x83\xa7\xe4\x97\x0b\x53\xcb\xaf\x29\x29\xd8\xde\x43\x1b\x48\xb4\x35\xd7\x53\x3c\xaa\x2e\x36\xce\xab\x6c\xdd\xb3\x46\xe5\x35\xe5\x15\xc4\xb3\xdb\x76\xde\x07\xd9\x85\x54\x14"}, -{{0x51,0xba,0x3a,0x4f,0x3d,0x85,0xd1,0x54,0x8c,0x2f,0x24,0x94,0xa3,0x51,0x1f,0x3b,0x95,0x15,0x66,0x3d,0x7e,0x85,0x37,0x0f,0xb6,0x15,0x02,0x37,0xe9,0xbc,0x98,0x0b,},{0x77,0x49,0xde,0x02,0x10,0xbc,0xe0,0x6d,0x48,0xf5,0x9b,0x95,0xae,0xb1,0x52,0x8f,0xd9,0xb4,0xe5,0x2c,0xdd,0xe2,0x2f,0xb8,0x19,0x3b,0xed,0xd5,0xdf,0x12,0x81,0x7c,},{0x16,0xfb,0x29,0x0c,0x91,0x3b,0x20,0xeb,0x1c,0x3d,0x7b,0x79,0x82,0x49,0xeb,0x84,0x59,0xd4,0xbe,0xe8,0x12,0x5d,0xb2,0xb3,0xf1,0xda,0xab,0x8a,0xf9,0xd9,0xa7,0x00,0xed,0x79,0x8a,0xdd,0xd8,0x02,0xdf,0xcd,0x29,0x7a,0x41,0x25,0x93,0xcd,0xa7,0xbe,0x99,0x79,0xa1,0xf0,0x93,0x50,0xe8,0x6f,0x69,0x8a,0xc3,0x38,0x0e,0x34,0x1d,0x07,},"\xd1\x8d\x0c\xbf\xc1\x6d\x0f\x9b\x67\xf2\x53\x9a\xd6\x20\x7c\xd9\x21\x7a\xd5\xed\x03\x33\xcd\xdb\x10\x41\xe0\xac\x2b\xdd\x92\x02\x76\x62\x96\x52\xb4\x9c\xbc\x98\x02\x59\x3e\xc3\x64\xea\x79\x5a\xbc\xd1\x58\x20\x85\xf5\x5b\xc6\x6c\x48\xfd\x3e\xed\xe6\x18\xd6\x36\x96\x17\x10\x0e\xae\xcc\xc1\x5f\x24\x9d\x6e\xee\x5b\xb2\xc4\x3c\x01\xb0\x62\x3f\xe6\x03\xce\xee\xe4\x9b\x40\xfb\x7c\x53\xfc\x68\x47\x36\x73\xc0\x9b\x1a\xc7\x7e\xa9\xbe\xb7\xe8\x53\x03\x79\xa8\x6d\x69\xec\xd1\xff\x11\x81\x3f\xbb\x88\xf6\x92\xf0\x5e\xf1\x32\x07\x42\xb4\xfe\x7e\x06\xd5\xba\x71\x65\x66\x46\xcd\x75\x00\xde\x19\xbb\x93\xd8\x44\x53\x66\x03\xf4\x0b\xd4\xae\xea\xf0\xc4\xdb\xc0\xac\xfd\x20\x2b\x28\x6b\x64\xaf\xb8\x3d\x4a\x37\x8d\xd4\x5e\xe3\xc1\xdf\x6b\x3e\xf1\x6b\x8b\x1a\xcc\xbc\x04\x06\x32\x50\xec\x47\xb8\x6a\xe5\xa7\x1d\x1d\xab\x38\xb5\xeb\x80\xd6\x63\xfa\xa7\x88\xf8\xb5\x9a\x75\x4c\x0f\x9c\x9f\x6d\x90\x62\x52\xaf\x46\xab\x1f\xff\xed\x27\x6d\x23\x88\xdb\xe7\x0d\x96\xba\x67\x47\xd1\xfe\xd4\xfc\x0b\x55\x29\x3d\x5f\x78\x7b\xda\x0c\x0d\xf4\x6a\x73\xf4\xaa\x7d\x29\xe1\xc9\xcc\x85\xcd\x04\x3e\x3d\xff\xe0\x57\x46\x2c\xa5\xfe\x5c\x64\x70\xe7\x39\x27\x6f\x8b\x53\x4c\x01\x72\xe4\x60\xf3\x40\x48\x7a\x56\x94\x68\xaa\x58\x90\xcc\x14\xf2\x0d\x67\xd7\x9c\x66\x1e\x87\xfe\xba\xc6\x27\x59\x71\xc3\x73\x08\x07\xeb\xf1\x75\xe0\xde\x10\x49\xbe\xe6\x7c\x89\x5e\x57\xb7\x1a\xb8\xa2\xf3\xcf\x36\x41\xfd\x54\x8d\x09\x41\x4f\x5f\xc3\x02\x6a\x0a\x35\xf6\xba\x95\x16\x73\x94\x49\x41\xcb\x23\x6f\x3d\x19\x76\xdc\x69\x07\x7d\x95\x14\x50\xe7\x66\x03\x16\x98\x8f\x6f\x2a\x6f\xbb\xff\x3b\x37\xce\xaa\x02\xfd\x6f\x02\x73\xbd\x80\x31\x85\xa1\x09\x03\x9c\x63\xf2\x51\x9b\x98\x3d\xaf\x65\x54\x25\x3b\xed\x54\x97\xc0\xb0\xbd\xaa\x0b\xd4\xa1\xfa\xc9\x00\x26\xad\xe3\xe4\x0c\x55\x4c\xff\x2c\xcb\x36\x99\x0e\x71\x55\x67\x08\xc5\xc4\x03\x92\x56\xff\xc7\x33\x7e\x5f\xea\x11\xf5\xe9\x0d\x3e\x4d\x93\x35\x91\x79\x11\x6a\x85\xc2\x41\x36\xca\x34\x83\x5c\xd3\x40\x12\xe4\xd7\xdd\xc7\xb7\x21\xc2\x46\xc7\x37\x00\xe2\x76\xdc\x2f\xf9\xf2\x77\x0b\x43\xc8\xe8\x0a\x17\xf0\x1d\x32\x68\x0b\xae\x22\x8e\x64\x23\xa8\x80\xc3\xfb\x99\x6a\xb8\xd2\x21\xbc\x62\x74\xac\x5f\xa7\x70\xd2\x05\xfc\x87\x8f\xba\x9b\xbd\x77\x6a\x3d\x79\xed\x77\x04\x89\x50\xf3\x6d\xc0\xaa\x3c\xcd\x28\xe4\x75\x6a\x99\x19\x04\xae\x05\x1b\x8a\x4b\x7d\xe3\xa1\xf2\xad\x0f\xb4\x5a\x33\xd0\xc6\x82\x25\x84\x1f\x8e\xb6\x5b\x6a\x16\xe9\x5f\x89\x35\x91\xe1\xaa\x73\xa6\x4f\x0d\x2e\xe9\x38\xab\x69\xad\xcc\x8c\x59\x51\x8b\xec\x50\x1c\x39\xf1\x39\x17\x4b\xbb\x00\x69\x9e\x1a\x0f\x0e\x0d\x88\x9a\xae\x54\x3a\x55\xe6\xac\x56\xd5\x20\x4c\x1a\xde\x1f\x27\xd8\x2a\x6a\x95\xe1\x4b\x2d\x69\x09\xdd\xa7\xbf\xaa\x7f\x48\x7f\xb6\x19\x59\x01\x4b\x78\x79\x5c\xb4\x63\x9f\x09\xf0\xd3\x29\xfe\xb3\x5c\xcf\x52\xed\xc2\xdb\x72\x19\x14\xe4\x23\x30\x68\x89\xa4\x83\xfe\xe8\x76\x36\x0e\xe3\x26\x33\x53\x19\x07\x0c\x56\x4f\x3a\x8b\x95\x3f\x52\xf4\x15\x13\xa2\x26\x08\x83\xc3\x8d\xd9\x78\xa2\x48\x60\x4a\x41\xbd\x4b\xfc\x9e\x84\x18\x4d\xc9\xe8\x4d\x25\x89\xf4\xaf\xff\x84\x17\x82\x4c\xe5\xad\xba"}, -{{0x7d,0xde,0xc5,0x26,0xa4,0x97,0x1d,0x89,0x12,0xa6,0xbd,0x43,0xc6,0x9f,0x92,0xed,0x86,0x44,0x2b,0x15,0xf4,0x2f,0xba,0xbb,0xf2,0xd1,0x7e,0xff,0x98,0x99,0x31,0x61,},{0x0d,0xfe,0xff,0xb2,0x76,0x23,0x09,0xb4,0x73,0x4e,0x4c,0xe2,0x52,0x3c,0xf1,0x86,0x31,0x49,0xf7,0xe1,0x9a,0x7c,0x14,0x7e,0xc0,0x89,0x9e,0x11,0x0c,0xa9,0xd8,0x7d,},{0x9e,0x60,0x3b,0x01,0x5f,0x42,0x87,0x1b,0x78,0xeb,0x27,0x52,0x3f,0xbb,0x7c,0xe9,0x62,0xfc,0xa3,0x2a,0xe2,0x70,0xe8,0xe1,0x2d,0xca,0xdd,0x25,0xaa,0x85,0x2b,0x89,0x1f,0x6f,0xef,0x77,0xb5,0x9a,0x54,0x6c,0x9a,0x7a,0x7c,0xac,0xb5,0x5e,0x1d,0x32,0xad,0xc8,0x05,0xae,0x5f,0x61,0xa6,0x9e,0x67,0x64,0xc7,0xc0,0x82,0x92,0xeb,0x03,},"\xe8\x77\x4a\x45\xd4\xd8\xf8\x6d\xda\x5c\x08\x80\x2b\xa2\x47\x2e\xf3\xc8\xd3\x6c\x7f\x38\x3a\xc0\x46\x12\xa4\x64\x38\x2e\x9d\x6c\x07\xd8\xd3\x58\x22\xc5\x3f\x43\x88\xf5\x15\x36\x14\xfe\xfa\xf4\x63\x74\x74\x7b\x9d\x4f\xd4\x46\xa8\x64\x76\x9a\x4c\xad\xe8\x43\xc1\xea\xb8\x57\x43\x19\x11\x2f\x01\x79\xd2\xea\x9e\x3c\x19\x5d\xc0\x68\xf0\x69\x74\x62\xb9\xe0\x7c\x87\x94\x87\x0f\x8f\xb8\xff\xc0\x81\xe4\x58\x6a\xfb\xcd\xba\x7a\x4f\x59\x25\xe9\xfd\x9e\xc9\x42\xd8\x43\x47\x33\xc2\xdd\xd5\xe2\x9b\xbd\xfc\x73\x42\xb9\x28\x68\x71\x9b\x54\x40\x88\xa4\x8e\xba\x4c\x82\xf1\x87\xdd\xca\x8f\x47\x46\x25\xa7\x1c\xf6\xb7\xaa\x5f\x08\x1c\x74\xf7\x40\x8f\x53\xb7\x81\x63\x6e\x7e\x9d\x29\xb0\x7f\xdb\x6d\x9c\x35\xe5\xeb\x38\x2d\xb7\xa3\x1a\x8b\xa5\x16\x91\x5d\xf8\xde\xe9\xe1\xad\x3f\x18\x28\x43\x68\x3e\x8d\x1d\xc5\xd8\x66\x9d\xbf\xcf\x09\x54\x1a\x43\xc0\xa0\x46\x13\x38\x1a\x5b\x5e\x4e\x71\xb2\x3c\x5a\xd0\x9b\x8e\xaa\x51\xcb\x93\x8d\x0c\x75\x2c\xc3\xd3\xa1\x0f\x10\xb4\x2b\xe8\xee\x7f\x6b\xda\xc8\x07\x85\x68\x43\x49\x46\xbb\xf5\x6d\xa7\x0e\x7d\x54\x15\x7a\x6e\xfd\x48\x46\xeb\x15\x52\x78\xc9\x4c\x38\x88\x65\x8a\x7a\x2f\x8e\xa3\xba\xc1\x47\xaa\x89\x16\x92\xae\x8b\x23\xf1\xaf\xe7\x1e\xcf\xde\xca\xa6\xc1\x13\xb5\xca\xaa\xa1\x93\x98\xc7\xdf\xe7\x3f\xac\xb4\x15\x5f\xd6\xba\xc1\x8d\x5d\xf2\x12\x9e\x8b\x29\x07\xec\xee\x15\x1b\xdd\x14\x7a\x7c\x3e\x46\xea\x72\x75\x4d\xe3\x2c\xeb\x06\x6d\x9d\xb1\xc2\x6e\x80\xdf\x36\x31\x29\x2b\x16\x17\x4c\xfa\x6f\x1d\x9c\x08\x28\xb8\x49\xc2\x2d\x29\x65\x1a\x73\xe9\x10\xd9\x27\x58\x77\xf4\x64\xce\x93\x26\xc6\xe4\xed\x6b\x07\xdc\xb3\xa3\x53\x63\xc1\xaa\x64\x72\xe0\x2c\x5c\xd8\x55\xe3\x8a\xab\xe9\x65\xac\xe9\xf3\xf5\xa4\xf5\xde\x03\x00\x86\x94\xcb\x90\xaf\xe4\x16\xc9\xd4\x86\x88\xde\x7f\x75\xcf\xe2\x43\xff\x7f\x41\xe0\x59\x31\x09\x34\x90\x3d\xb5\x68\x84\x45\x08\x26\x2c\x89\x9d\xfa\x75\x0c\xd6\xa2\x82\x98\x24\xba\x02\x7a\xea\x1b\x6d\x01\x77\x72\x6a\x34\x3a\xdd\x4e\xcd\xc5\xf7\xe6\xe9\x09\xab\x7d\xe6\x15\xef\x28\x07\xf9\xe7\xd7\x1c\xe2\xf7\x8a\xcf\xf5\x7e\xba\x79\xc3\xf5\xe0\x7c\x8b\x66\x1c\x1e\x30\x27\xf8\x17\x6d\x28\xbf\xef\x76\x7d\xd6\x8d\x4e\x5d\x62\x8f\xec\x0b\xfe\x88\x79\x93\x41\xf3\x06\x12\x87\x34\xfa\xd2\x02\xaa\xfc\x9f\x11\x12\x3f\xb3\xe3\x63\xd1\x0a\xee\x0d\xb5\xe2\x7a\x15\x70\xdf\xae\xe4\x7e\x24\xda\x47\x3b\x07\xfe\xe5\x9a\x6c\x93\xf0\x98\x1d\xbe\x32\x5c\xd8\xcc\x2d\x2e\xd7\xdc\x17\x16\x6b\x26\x7c\x1b\x11\x05\x36\xf2\x63\x6b\xba\x34\x75\x1a\x78\xf7\xf6\x29\x81\x82\x44\x2d\x83\xc1\x23\xbb\xee\x4f\x50\xc5\xb0\xfa\xcf\xf0\x3e\x7c\x55\x6e\xd9\xe6\x4c\xa2\x7c\x4b\xca\x5a\xb0\xde\x0d\x5f\x9c\x2c\xbb\x54\xcc\x2d\x94\x73\xa3\x2d\xf9\x99\x39\x0a\xc2\xff\xee\xd3\xd4\xcb\xa3\x49\x73\xdc\xec\x3f\xba\xba\xfc\x4d\x54\xca\xe4\xe7\xe8\x5d\x4a\x6e\x8a\xfe\x45\xca\xcd\x71\xe0\xf2\xe6\xd0\x4b\x4f\x9d\x3b\xcf\x43\xd3\xfa\x41\xe9\x98\xcc\xbe\xd0\xf1\x50\xd5\xca\x1d\x52\x72\x93\x2d\x93\xec\xa1\x04\x95\xc6\x83\x34\xfa\x32\x68\xf3\x1d\xe5\x22\xcb\x12\xa7\x44\x9f\xfb\x5c\xb5\xe8\xf1\x46\x2c\xd9\xb5\x17\x70\xcc\xaf\x58\xb1\xe0\xd8\x2e\xf9\x29"}, -{{0x0b,0x65,0x90,0xdd,0x7c,0x2f,0x15,0xf9,0x4a,0x56,0xe2,0x40,0x16,0x93,0x63,0xc2,0x67,0x32,0x30,0x2b,0x9d,0x44,0x0b,0x53,0x27,0x23,0x00,0x2e,0x15,0x5d,0x02,0xd9,},{0xcd,0x18,0xe0,0x32,0x57,0x7c,0x55,0x76,0xf2,0x23,0xf3,0xe3,0xd8,0xa1,0xfa,0x8e,0x9a,0x87,0x0f,0xef,0x09,0xe9,0x40,0x9f,0xaf,0x40,0xd7,0x14,0x3e,0x52,0xfc,0x44,},{0x64,0x2d,0x81,0xac,0xf3,0x8c,0xf0,0x99,0xa8,0x33,0xa7,0x4f,0x2d,0x80,0xb8,0x54,0x48,0xec,0x2b,0x1a,0x5d,0xdc,0x64,0x47,0x0b,0x21,0x3d,0x54,0xb7,0xbe,0x61,0x33,0x68,0x9a,0x71,0x94,0xf5,0xd8,0x97,0x92,0xe1,0x6e,0x5d,0xf7,0x55,0xa4,0xfd,0x9e,0xf4,0x68,0x9e,0xa9,0x52,0x92,0x6e,0x0e,0x4e,0xcb,0x3b,0xd4,0x81,0xfd,0x91,0x02,},"\x71\xfe\x0f\xd5\x5d\x5e\xd1\x20\x6f\x28\xee\x16\xe4\x19\xfa\xb6\xfa\x66\xa2\x51\xfa\x6b\x06\x01\xda\x26\x1e\x42\x9f\x55\xb8\xd5\xae\x3f\x3c\x52\xa1\x7f\xe1\xec\x73\x4b\x81\x0a\xb6\x3a\xad\xe4\x44\x70\x39\xca\x0a\xe4\x68\x7c\x24\x35\xf5\x61\xe4\x6c\x5b\x30\x97\x17\xab\x31\xe0\xf6\x40\x76\xb2\x16\x92\x11\x57\x2b\x74\xe1\x8a\x1f\x45\x25\xa6\x4f\xa7\x17\xa5\xed\xf1\x49\x75\x81\x29\xcb\x04\x03\x5e\x7e\x20\xba\x40\x05\xb7\x48\x09\xde\xc6\x44\x50\x4c\x24\x54\xa7\x7f\x99\xb2\x0c\x53\x74\xf3\xce\xe7\xd8\xc6\xb6\x8b\x24\x3c\xaf\xb3\x00\x98\xdc\xe9\x04\x90\xfd\xc3\xb9\x2f\x54\x94\x8f\x42\x46\x39\xe1\x9f\x8f\x20\x20\xd1\x55\x13\xda\xef\xad\xd9\xe9\xb1\x2a\x84\x76\x1e\x5e\xce\xa0\x88\xad\x56\x1f\x06\x20\x9f\xd4\x42\x3f\xcd\x00\x3f\xbc\xd1\x87\x3e\xa5\x49\x63\xa2\xfa\x07\xc7\x47\x6b\x13\x88\xf9\x01\x5d\x9e\xac\x30\x5b\xea\x5a\x3d\xe1\x94\xf5\x5a\x17\xb4\x2d\x59\x9e\x5c\xe6\x2c\x8b\x7c\x19\xe7\xe7\x09\x61\x37\xb9\xd0\xa6\x5e\x63\xc1\xa3\xb8\x45\x38\xca\x65\x36\x9a\x20\xe8\x82\x2f\xff\x5e\xcb\x57\xfc\x09\xb4\xe6\x84\x5b\x4f\x24\xd4\x88\x69\x71\xac\x1a\xc2\x8c\x77\x58\x0e\xa5\x67\x2a\xd1\x4c\xe4\x44\x17\x19\xc2\x14\x54\x6d\x07\x36\xcb\x7a\xd0\xbd\x9f\xb5\xb2\x6c\x6d\x9c\x53\x6b\xf8\xc8\x57\xae\x42\x57\x7b\x36\x34\x1d\x39\x2b\x43\x32\x3b\xda\xe7\xdf\xaa\x49\x19\x86\x87\x2a\x23\xd8\x27\xc6\xef\x8b\x57\xe7\xd0\x0f\xea\xe3\x83\x4c\x46\x64\x00\xaa\xd1\xd3\x67\x82\x39\x84\xaa\x02\xd2\xef\x49\x29\x14\xae\x11\x27\xe7\x55\x1b\x81\x25\x59\x37\x83\x05\xe4\xfd\x52\xd8\xbc\x7e\x41\x57\xec\xca\x45\x1f\x43\xee\x9f\x54\xc8\x21\x53\xc7\xdb\xfa\xf7\xec\x35\x23\x87\x73\x05\x1b\x4e\x58\x7d\xb1\x36\x95\x7e\xc5\x71\x38\x2b\x90\x59\x0b\x5d\x10\x26\x02\x45\x80\x96\x6b\x72\x52\xd2\xcd\x3f\x4f\x16\x25\xc4\x85\xba\x90\x6b\xff\x17\x59\x92\x18\x89\x78\xf2\xd6\x27\x4f\x3a\x03\x17\x49\xba\x7e\x70\x2f\x56\x54\x7e\xdc\x96\xec\x26\x7b\x84\x89\x28\x80\xd7\x50\xd7\x31\x0e\xbf\x6d\xb2\x41\x25\x3c\xab\xe4\xb2\x5a\x97\x74\x58\xc6\xff\xc9\xe3\x53\xe6\x2a\xdf\x05\xe6\xef\xc0\xfc\x1e\xbe\x89\xf5\x27\x70\x5b\xcc\x26\xb7\x01\x28\x56\x10\xd9\x8a\xa3\xbf\x23\x87\x2b\x69\x96\xd3\xde\x48\x0e\x8d\x09\xd7\x83\xc4\xa0\x8c\xd3\x83\xc9\x01\x26\x35\xaa\x68\x97\x8b\x50\x06\x81\x8b\xbd\xe4\x4f\x29\x87\x47\x9b\xcb\x2b\x71\x1c\x1b\xee\xed\x27\xcf\x09\x97\x0a\x16\x4e\x45\x4f\x71\x08\x22\xee\xf5\x55\xc1\xc7\xbf\x9f\x76\xd5\x25\x4c\xe2\x20\xc9\xaa\xa7\x16\x84\x7a\x24\x94\x88\xf9\xcd\xb4\x4c\x48\xf4\x52\xab\x52\xc4\x0f\x6d\x03\xad\xc8\xbf\x3f\x19\x7b\x25\xe3\xd1\x27\x83\x0e\x74\xfd\x81\xeb\x14\xf7\x54\x20\x5b\x3a\x48\x44\xc5\x96\xb6\xe3\xa9\x93\x6a\xd6\xfd\x9e\x80\xa1\x63\x20\xb3\x81\xc3\xff\xc7\xb6\x9e\xab\x54\x53\x6f\x55\xab\xe2\x2c\x91\xd8\x98\x40\x8e\x88\x0c\x6d\xbf\x0f\xa5\x64\x8d\x51\x77\x72\xca\xa5\x35\x3b\x25\xdb\x60\x50\xd7\x53\xfa\xf1\x98\xec\x1d\x37\x5d\xe0\xfa\x72\x18\x0a\x93\xba\xb0\x3d\xed\x77\x16\xcb\x87\x50\x5b\x68\xac\x6a\x35\xe7\x3d\x0f\xcf\x34\x45\x7e\xff\x82\x17\x89\x52\x14\x2c\x7b\xac\x9d\xfd\x87\x2a\x9a\x82\xf8\x5b\x24\xb8\x8f\xa4\x2d\x4b\xe0\xa0\xca\x0b\x2c\x70\xf4\xc6\x22"}, -{{0xc6,0xd9,0xac,0xc5,0x17,0x5f,0xa2,0xb8,0x96,0x5c,0x15,0x8c,0x56,0xba,0x0a,0x5a,0x66,0x6a,0xd2,0xc7,0x40,0xcd,0x5b,0xb6,0x79,0xbb,0xa9,0xb1,0xdc,0x50,0x92,0x84,},{0xf5,0xcf,0xca,0x21,0x1b,0x02,0xfb,0xa7,0x72,0x03,0x47,0x70,0x3b,0xf1,0x63,0x1c,0xb3,0x08,0xfa,0xbc,0xda,0xa6,0x74,0x29,0x52,0x7c,0x5b,0x7b,0x67,0x6d,0xba,0xef,},{0x4d,0x2c,0xe7,0x07,0x09,0x0b,0x0f,0x3f,0x41,0x46,0x2f,0xd7,0x5b,0xd6,0x09,0xa2,0x72,0x4f,0xad,0xfe,0x5c,0xa3,0x90,0xe3,0x13,0xa4,0x2c,0xab,0x42,0x86,0x8e,0xd6,0xe9,0xa8,0x91,0x4d,0xc1,0x39,0x09,0xc0,0xd6,0xf6,0x1e,0x63,0x71,0x29,0x57,0xc7,0x6f,0x3b,0xd8,0xb7,0xf5,0x53,0x49,0x71,0x5a,0x3a,0x31,0x75,0x15,0xc0,0x71,0x08,},"\xf2\x45\x10\x0c\xd2\xd3\x16\x48\xf5\xf3\x51\xbd\xa5\x64\xc9\xdb\x4a\x35\x82\x0c\xc3\x0e\xf6\x51\x33\x7c\x4c\xd8\x88\x07\x05\x69\xd1\x17\xa9\x34\xb9\xc9\x18\xe5\xdf\x8b\x37\x44\xdd\x66\x20\xcc\xbc\x49\xf6\xb3\xe5\x78\x2a\x30\x33\x9d\xbb\x9c\xbe\xd0\x5d\xd2\xb3\xb8\xc5\xbf\x15\x46\xe7\x0a\xf6\x36\xe6\x61\x5c\x48\xb2\xc3\xc2\xd1\x9f\xe3\x54\x20\xdf\x53\x14\xf6\x3c\x48\x12\xb5\x8e\x82\xa2\xa6\x0b\x18\x02\xf3\x8e\x50\x5c\xe7\x48\x01\x7a\xfa\x97\x7d\x3f\x9b\x1b\x6b\xea\x21\x92\xac\xec\x73\xbd\xce\x12\xd6\x5e\x68\x4d\xa4\xd8\xb4\x1f\xa9\xa8\x6f\x11\x08\x6e\xdc\x2d\x52\x96\xf6\x7e\xfc\x53\xac\x84\x07\x0f\xde\x13\x69\x3e\xb2\x31\x8f\x5a\x8c\x3b\x11\x7c\x23\x34\x22\xad\xcd\xd3\x52\xf3\x28\xf0\xec\x69\x9a\x46\x50\xc9\x3f\x9b\x4a\x7d\x79\x5d\x7f\xc2\x62\x2a\x03\xd9\x9b\x64\xf7\xb3\xdc\x31\x94\xf6\xc3\xb1\xb6\x9d\x99\x07\xce\x09\x24\x01\x07\x3f\x47\xa2\x8f\x47\x99\xd2\x29\x09\x2a\x1b\x07\x41\x29\x95\x4b\xe8\x0c\xa4\xa3\xe6\x58\x2e\xe0\x5c\x30\x2c\xac\xb7\x43\x1d\x1c\xa6\xa4\x51\xaa\xed\x72\x78\xab\xc7\xf7\x85\x75\x24\x1c\x2a\x2e\xea\x2e\x84\xcb\xf9\xa3\x34\xdf\x40\x21\x09\xc0\x28\xe3\x45\x47\x3a\x13\xaf\x9b\x00\x8e\x20\xbc\x8c\xf0\xbc\xef\xbb\x7a\xa7\x27\xec\x85\x6e\x99\x25\xb4\xdd\xd9\x9d\xeb\xa8\xf2\x52\x91\x1a\x59\x01\x54\xb5\x79\xa8\xaa\xa3\x1f\x07\xdd\x50\x25\xdf\x5c\xd8\xa0\x9f\x74\x29\x64\xcc\x8c\x36\x5d\x8a\xff\x4e\xb1\xd7\x9f\x6e\x5a\x07\xda\xc5\xf4\xed\xe9\x2b\x4e\x2e\x61\xd3\x4c\xc2\xd4\xf0\xaa\xaa\xb0\x37\xad\x5f\xdb\x95\xde\x6c\xd5\x98\x4e\xba\xf7\xcc\xe7\xf0\x8d\x0c\xa0\xdb\xbe\x48\x3c\xe3\xcb\x35\xcd\x79\x0c\xa0\x42\x70\x65\xa3\x4d\xf7\xf4\xc2\xaf\x86\xef\xe9\xb7\x65\x71\x3a\xff\x25\x7f\x5c\x1d\x54\x70\x95\x27\xad\x18\xac\x33\xab\xcd\xee\xdb\x20\x80\x64\xeb\xae\xa4\x83\x5b\xe4\x94\x2b\x8f\xc6\x66\xad\x1b\x79\xb6\x65\x13\x09\xe5\xea\x1d\xa3\x02\xd7\xfb\xa2\xe9\x9f\x0e\x63\x19\xe8\x2b\x99\x05\xa1\xea\x48\x2b\xa0\x43\xb6\x80\x0b\x33\x0d\xc4\x8b\x33\x13\xf5\x9b\xb2\xf9\xe8\xa7\xf0\x7e\xb1\x80\x0a\x70\x27\x45\xdb\x14\xc6\x29\x9a\x98\x2d\xad\x89\x79\x54\x44\x5b\x7d\x98\xeb\x58\x37\xfd\x70\xbf\x19\x0c\x64\x95\x52\xc8\xe8\x6f\xeb\x7f\xf5\xb3\xed\x8e\x0a\x06\x70\x4d\x45\x53\xa3\xc2\xdd\x74\xf1\x8e\xa8\x23\x3a\xe0\xa5\x0d\x91\x4f\xe0\x8f\xbc\xd3\xa1\x43\x5f\xed\x56\xa9\xf3\xa7\xef\xfa\x14\x0f\xb5\x52\xdd\xd2\x1d\xff\xff\x7f\xa4\x73\x32\xdd\xfc\x1e\x53\x17\xf4\x17\x7d\x5e\x2f\x11\xa0\x6e\xc8\x4c\xcf\xb8\x9b\x65\x4e\xa8\x1b\xd4\x2d\x7e\x07\xa3\x87\x30\x1d\x0f\x40\x26\x4a\xbb\xf9\xf9\x10\x7b\x30\xed\xe8\x64\xcc\x76\x90\xc0\x6d\x2e\x24\x7a\x06\x0b\xb2\x24\x4a\xd7\x8e\xd5\xc5\x51\x5a\x1a\x2a\x61\x2d\x61\xe3\xd9\x31\xe2\x8b\xc9\x39\xb4\xd3\x43\x5e\xee\x4f\x73\x31\xb1\xf0\xf8\x53\x75\xd8\x2a\xc9\xa7\x7c\x43\x74\x00\x32\x05\x17\x46\xdc\x92\x69\x45\x8c\x14\x7d\x18\x8d\x84\x40\x19\x54\xa4\x89\xcb\x4f\xbf\x9b\xf8\x4b\xa7\xd8\xf1\x00\x90\x3c\xe6\x78\x31\xb4\x05\x4d\x0f\x58\xcd\x88\x3d\x54\x2c\x49\x33\x10\x3f\xf0\x70\xcd\xfc\x9d\xbb\x0f\xcc\x31\xef\xca\x46\x6e\x77\xa3\x3f\x1a\x81\x3d\xa6\xdc\x0c\x7c\x31\x58\x5e\x8f\x4f\xef\x1e\xbf\x42\xfb\xd1"}, -{{0x7d,0xfa,0xe4,0x16,0x41,0x9d,0x7b,0x0d,0x4f,0xc1,0xf8,0x23,0x84,0x0c,0x3e,0x4b,0xd4,0xad,0xcd,0x4d,0xc2,0xdc,0x17,0xb3,0x86,0x37,0xac,0xed,0xac,0xbd,0xbb,0x45,},{0xbc,0x51,0xd7,0x74,0x59,0x31,0x31,0x7e,0x1e,0x34,0x6e,0x2e,0x7c,0x92,0x03,0x91,0x81,0xb6,0xbf,0x38,0xee,0x2f,0x5a,0x44,0xfb,0xe2,0x33,0x9c,0x4f,0x95,0x2a,0xb9,},{0xda,0x34,0xb1,0x98,0x3e,0x8c,0x55,0xe4,0x1f,0xda,0x8e,0xc8,0xab,0xf2,0x3b,0x36,0x7a,0x0d,0xa6,0x06,0xc8,0xcd,0xbb,0x1e,0x8b,0x57,0xe0,0x34,0x3c,0x05,0x57,0xa5,0xf0,0xe8,0x15,0xe7,0xf2,0x2f,0x86,0x05,0xae,0x93,0xb2,0x7d,0x03,0x77,0x6a,0xc1,0xf7,0xde,0x3d,0x79,0x2e,0xa2,0x93,0x3a,0xc2,0x2d,0x2d,0xc2,0x3b,0x32,0x3d,0x0c,},"\xec\x84\x3d\xc4\xdd\xa6\xe9\x02\xe9\xbe\x31\xb7\x0f\x11\x76\x3b\x75\x7a\xb6\xce\x73\x34\xdc\x00\x76\x4b\x2d\x08\x4e\x9d\xaf\x24\x84\x48\x59\x84\xee\x28\xa2\x83\x0f\xcb\x94\xc5\x41\xcb\x46\x94\x40\x03\x67\x31\xde\x80\xff\x56\x0f\x53\x0c\x9d\x9e\x6e\x1f\x7d\x9c\x4c\x5b\xdf\x50\xb0\x4f\x54\x03\xc2\x9f\x76\xd7\xe3\x6e\x00\xbb\xea\x35\xdb\x1c\xc6\x0d\xa8\xd7\x76\x52\x62\x66\xc3\x32\x4c\xe7\xef\xec\x64\x50\x85\x96\x09\x26\x68\x56\xd7\x01\xa4\x7a\x48\xde\xe8\xbf\x37\x40\x95\x65\xc7\xfb\xfa\x99\xa2\x04\xe5\x53\x0c\x97\x1c\x60\x5b\x44\x30\x5d\x5c\x74\x67\x89\x41\x14\x25\x3c\xf4\x3c\xdd\xf1\x8b\x62\x96\xdd\x25\x4a\x4d\x96\xac\x70\x00\x91\x81\x86\xdf\xd4\xbf\x45\x4e\xd3\x09\x74\xc5\x53\xd0\xae\x15\x1a\xd4\xcf\x54\x0c\xec\xaa\xa0\xb5\x94\x8b\x09\x85\xa9\xc7\xb6\xe7\x81\x59\x32\xba\xc1\x17\x32\xfc\x7d\x10\x26\x7f\x6b\xf8\xf1\xe7\xc0\x8d\x65\x0e\x56\x7b\x4e\xdd\x15\xae\x79\x58\x41\x0e\x42\xf1\xf5\x37\xfa\x73\x2f\x72\x7a\x26\x83\x88\x32\x1d\x53\x44\xc4\xe7\x8b\xb9\xa7\x4e\xab\x9d\x6a\xbf\x96\x89\x65\xc6\x66\x93\xd5\xf1\x12\xdd\x4c\x14\xfd\xfd\xd9\x60\x05\xea\xa6\x75\x7f\xa2\xcc\x10\x13\xfe\x43\x27\xab\x09\x99\xd1\x17\xf3\xdb\xf3\x25\xb0\x7c\xd4\x54\xd4\xb1\x41\x99\x1e\xf7\xe2\x3d\xb5\xee\x24\xbe\xda\x35\x88\x4a\xa3\x70\x48\x08\x64\x8a\xa4\x3c\xd6\x25\x62\x59\xf7\xd3\xdb\x5e\x05\x53\x11\xf2\x53\xe8\xb5\x7a\x4c\xda\x5a\xfe\x0b\x0a\xdf\xc3\x64\xe1\x60\xca\x37\xe8\xde\xc6\xb9\x5a\xa6\x15\x2e\x5d\x5d\xa6\xeb\x91\xbe\x0e\x44\xff\xe8\xe4\x95\x33\x26\x7b\x7e\xb7\x95\xf5\xf8\xe0\xb2\xc3\x5b\x29\xdf\xbc\x87\x58\x5f\x22\xbd\x5b\x90\x9d\xfd\x6a\x5e\xdc\x0e\x3a\x9d\x97\xb0\xc4\xf3\xad\xc5\x1e\x96\x99\x37\xc0\x8f\xd6\x5f\x53\x7a\xac\xda\x8f\x11\x27\x5a\xf0\x2c\x33\x54\x54\x26\x30\xf3\x92\x0c\x39\x3f\x5c\x42\xb9\xfc\x63\x3d\xe9\xd9\x4c\x72\xe3\xf2\x00\x02\x34\x9a\xd0\x41\x80\x35\xb3\xf2\x5f\x02\xca\x92\x8e\x5b\x2d\x40\xa7\x7a\x1c\x3e\x56\x22\x1f\x4b\x9d\xb0\xc2\x5b\x09\x6d\x6e\x5d\x0f\xe7\x58\xda\x2c\x69\x05\x3e\x8d\x08\x6d\xef\x4e\xdc\x6e\x34\x53\x78\x3f\xfc\x63\xa4\x96\x01\x22\xd9\x23\x67\x1a\x90\x60\x08\xba\xc1\x05\x61\xae\x62\x19\xd2\xb5\x1d\x53\x67\xbf\x13\xcc\xab\xf5\x93\x1b\x9f\x18\x6e\xb1\x09\xba\xcd\xe4\x0e\x1a\xf2\xb5\x64\x81\xe0\xc6\xdc\x6f\x5c\x54\x73\xf8\x00\x1c\xf3\x71\x91\x9a\xcb\x40\xce\xc5\xb9\x62\xeb\xba\x80\xe3\x2d\x6e\xba\xc4\x80\x6d\x04\xd2\x47\x68\xc2\xad\x2e\x3f\x92\xa8\xcb\xe4\x77\x54\xf9\xbf\x61\x59\x53\x52\x2b\x26\x3d\xc2\x49\x37\xfb\xd9\x32\xc8\xc4\x59\xeb\x8b\x10\x94\x43\xaf\x6c\x19\x5a\x59\xfd\x27\x21\xb0\x12\x56\x28\xf2\xb8\x14\x3c\xf3\xc1\x28\xbc\xec\x13\x92\xef\xd1\x6b\x73\x4c\x10\x71\x6d\x96\xba\x7d\x1f\x41\x39\x17\xcc\xaf\xa5\xbf\x5f\x83\xf5\x24\xfe\x84\x06\xa1\x52\x11\x5e\xa7\x70\xe1\x74\x5e\x82\xe8\xb5\x1d\x75\x2b\x8b\xd7\x85\xdf\x48\xbf\xc1\x20\x41\xbf\x87\x4f\xc7\x3a\xfb\x42\xca\x5d\x69\xc6\x41\x64\x79\xce\xb4\xaa\xa0\x49\x2b\x6f\xf2\x1e\xe1\x2d\xb2\x21\x3a\x42\x86\xfd\x56\x05\xc9\x3a\x7b\xb8\xa3\xb0\x71\xb0\xb2\x5f\xb0\x1d\x77\xab\xbc\x87\x71\x48\x94\x70\xa1\x07\xaa\xda\xe9\xf6\x40\xc2\x4d\xfd\x53\x28\xf6\x0f\x4b\x7d"}, -{{0x70,0x94,0x16,0x07,0x49,0x97,0xb9,0xc9,0xaf,0x4d,0x37,0xa0,0x11,0x39,0xe8,0xa3,0xf9,0xf2,0xce,0x5d,0x72,0xa5,0x7d,0x80,0x5e,0x82,0x2a,0x81,0x18,0x6d,0x01,0x7e,},{0xae,0xe1,0x10,0xf1,0xf4,0xd4,0x6e,0xa6,0x06,0x49,0xd7,0x86,0xb1,0x50,0x05,0x2e,0x28,0x7a,0x9d,0xa6,0x01,0x22,0xc4,0x7b,0x09,0x08,0xfa,0x8b,0x2c,0xa2,0x8a,0x80,},{0x8e,0x4b,0x41,0xf0,0x97,0xd8,0x36,0x14,0x18,0x4b,0xa7,0xf5,0x2b,0xa2,0xfd,0x9f,0x05,0x65,0xf8,0xa6,0x37,0x21,0xef,0x55,0xf9,0x31,0x62,0x82,0x6b,0x9f,0x0a,0xc0,0x70,0xc0,0xe2,0x86,0x4b,0x5f,0xfd,0x8e,0xcc,0xc1,0x8e,0xfa,0xd1,0x8b,0x2c,0xe8,0x4b,0xe5,0x7c,0x0b,0x4a,0x41,0xc5,0x2e,0x20,0xef,0x37,0x72,0x23,0x77,0xc6,0x0f,},"\xed\xda\xa3\x69\xc0\xe3\x1a\x1f\xcc\x1d\xa4\x6f\x65\x36\x24\x42\xa0\xcc\x21\xc7\xdc\xdd\x5c\xd9\x0e\x0a\x2e\xe9\xf2\x51\x10\x81\x2b\xa1\x14\x93\x1c\x86\x8a\x70\x86\x07\xac\x16\x08\x4d\x79\x71\x5d\x13\xb3\x38\xc0\x5c\x6a\xef\x73\x43\xe7\xda\xd2\x82\xf9\x6f\xe2\x81\x93\x18\x8f\x0c\xc8\x93\xc7\xdc\xe8\x05\xfd\x3a\x7c\xd2\x68\xb7\x28\x94\x16\x0b\x52\x45\xfe\xd9\xfa\x99\x43\xb7\xc8\x0a\xdb\x3c\x2d\x1a\x35\x3d\x8f\x12\xdf\x25\xa3\x1d\xde\x7f\xa3\x85\xbb\xec\x35\x1d\xa6\x6f\x15\x30\x32\xe1\x77\x56\x27\x3f\x8d\x54\xe9\xa3\xb9\xea\x25\xae\x67\xd1\xe9\xc1\x8c\xc6\x8b\xe6\x01\xe3\xd6\x82\x82\x81\x8c\xe0\xe7\xcf\x88\xa4\xd1\x33\x64\x53\x02\x17\x32\xf0\x8d\x9e\x76\xcd\x23\x63\x79\x29\xb0\x91\x1d\x5f\x86\x14\xf4\x84\x2e\x67\x0c\x14\x28\x60\xaf\xc2\x65\xc5\x01\x72\xb1\x3b\xfd\x35\xad\x8f\xc5\x4b\x28\x65\x7d\xa3\x2b\xac\x15\x3b\xa9\xaf\xfc\x89\x7a\xfb\x3c\x72\x1f\x48\xca\xa4\x62\x40\x58\x57\x10\xb0\xf2\xd2\x4d\x5f\xf4\x96\x5d\x1d\x10\xf1\xa0\x7b\x06\xab\xea\x6a\x08\xe1\xd6\xf1\x50\x0d\xa1\x2c\x43\x4a\x6d\x77\x8c\x94\x10\x67\x10\x80\x00\x47\x5c\xe8\x31\xbc\xfe\x2d\x0a\xfe\x40\xb7\x41\x9d\x07\x05\x9b\xc0\xcd\x8d\xce\x4b\xe9\x58\x7f\xf2\x9a\xd8\xbf\x0b\x26\x8a\xe2\x3c\xe0\xda\x5b\xb5\xbf\x74\xff\x0b\x2b\x31\xb8\x21\x12\xa9\xfd\x5a\xbd\x9b\xfd\x0a\x90\xe6\xf4\x72\x35\x48\xc6\xbb\x2f\x99\xdc\x06\x1b\xa3\x2e\xba\x2d\x53\xe6\xbc\x79\xbf\x44\x1b\x23\xfb\x74\x60\xde\x04\xe8\xe8\xef\xbc\xd4\xd4\xcc\x73\x55\xde\x9e\x3b\x08\x61\xa6\x81\xb9\x83\x83\x9d\x44\x88\xe5\x51\x75\x1f\x23\xe9\xa6\xe2\xe4\xd4\x43\x27\x3b\x9e\x0f\xe6\x4d\x8a\xcd\x1c\x74\x8b\x55\x59\x43\x82\x23\xdd\x21\xb5\x18\x31\x89\xe0\xf3\xc0\xe8\xed\x41\x4c\x03\x56\xba\xb7\x7a\x65\x4d\xe1\xa5\x77\x14\x62\xef\x14\x34\x49\x70\xa4\x91\x51\x1a\x72\x29\x14\xf4\xa8\x9f\x4f\x1a\x82\x7e\x18\xcd\x84\x47\x9c\xc9\x25\x92\xea\xdf\x8d\xe2\xdf\x82\x4b\x97\x6d\xcb\xd2\x84\xa3\xba\x64\xbc\xdb\x0d\xf1\x5e\x8f\x41\xc0\xb2\x47\x15\x86\xb2\x6a\x06\x35\x3d\x90\x50\x28\x23\x5c\x1c\x6e\x5c\x45\x87\x22\x27\x25\xaf\x08\x3e\x11\xe7\x9c\x94\x3a\xa4\x44\xd4\xaa\x41\x21\x8d\x3e\x97\x43\x36\xe3\x72\x81\x3e\x99\xe2\xb0\xc5\xf0\xae\x81\x0f\xfe\xd9\xa7\xa3\xd6\xcb\x74\xc5\x47\x3d\x99\x0a\x59\x11\x32\x9b\x8e\x82\xec\x6b\xf2\xbd\x43\x21\xbb\x48\x73\x70\xf8\x73\x9e\x7a\x2a\x4a\x53\x43\x08\x33\xd4\x5b\x9f\xe3\xde\xb9\x3f\x79\xfc\x6a\x51\xd5\x63\x69\x5e\xcd\xb9\x78\x58\xd2\x13\xda\x58\x44\x34\xb7\xc7\x15\x46\xaa\xe8\xd9\x67\xe1\xc6\xd0\x08\x2b\x10\xd4\xa7\x2d\xe1\x74\x2e\x53\xc4\xb2\xf9\x2e\xb8\xb5\xc8\xc3\x5a\xb6\x53\x5e\xa8\x10\x0b\x37\x92\x4a\x0a\x91\xd2\xa7\x28\xd0\xf5\x64\x24\x37\xaa\x66\xc8\x2a\xb7\x4b\x5d\x07\x45\xec\x08\xf7\x70\x5c\xb8\x1f\xa0\x79\xd8\x9e\xcd\xc9\xaa\x1f\x8d\x7d\x82\xdc\x77\x46\xd3\x46\x15\x34\x3a\x69\x25\xdc\x31\x8f\x35\x2a\x2b\x45\x01\x24\x38\x42\x4f\x90\x98\xfd\xdf\x6e\x61\xfd\x1f\x8f\xb4\x9d\xa4\x0b\x3e\xec\xe8\x9a\x1a\xf1\x99\x6d\xe7\x0c\xd1\x69\x6c\xbf\xd9\xe3\x01\xea\x5f\x44\x37\xc7\x1a\xc2\xa0\x32\x25\x4c\x14\x0a\x90\xe8\x5f\xb8\xff\xc4\x66\x7f\xa1\x39\xc1\xee\x9b\xbf\x12\xee\xd9\x06\xa9\x67\xbc\x09\x21"}, -{{0x3d,0xcb,0x7a,0xe7,0xd9,0xf0,0xf1,0x41,0xf1,0xd9,0xf0,0x78,0x83,0x63,0x5b,0x91,0x3e,0xd2,0x9f,0xb6,0x1d,0x0f,0x74,0x1c,0x9a,0xfd,0x05,0xa2,0x7b,0x04,0x5b,0x06,},{0xae,0x62,0xb7,0xee,0x1b,0x8d,0xb5,0x76,0x4d,0xaf,0xdd,0xd9,0x72,0x4a,0xcc,0x10,0x6d,0x6c,0x0a,0x4d,0x1e,0x85,0xd8,0x90,0x6f,0x75,0x84,0xb5,0x58,0xf5,0x77,0xdf,},{0x09,0xa1,0xe6,0xfe,0xdf,0x97,0x1b,0x3e,0xdb,0xfa,0xef,0xbe,0xb8,0x9a,0xa5,0x39,0xca,0x0b,0x02,0xb3,0x7e,0x7a,0xc4,0xea,0x89,0x20,0xd6,0xd4,0x34,0x8e,0xe0,0xcf,0x9a,0x2d,0x5e,0x96,0xfc,0xe5,0x17,0xc6,0x65,0xe7,0xc3,0x83,0x68,0xba,0xf2,0x49,0x79,0x24,0x9a,0x95,0xb7,0x0e,0xa7,0x43,0x6c,0x00,0x78,0x5f,0x16,0xa3,0xae,0x09,},"\x38\x11\x6a\x57\x26\x69\x07\x0d\xd5\x86\x32\x18\xc9\x1a\x77\xa4\xab\x47\x55\x36\x88\x48\x8c\x79\x28\x38\x50\x9e\x9a\xba\x25\x06\x7a\xdb\x7e\xa4\x24\x98\x48\x00\x9d\x91\x4a\xe9\x87\xa6\x03\x23\x48\xc1\xc0\x68\x1c\xf9\x77\xa9\x55\x2d\xd6\xbb\xf4\xe6\xff\x32\xac\xc9\xfa\x61\xcb\xee\x25\xa3\x93\x07\x65\x0f\x8b\xa6\xa7\xce\x42\x1e\xf2\xf7\x1b\xcc\xc0\x95\x81\x38\xf9\x32\x4c\x86\xbf\x2e\x52\x8f\xa3\xe4\xd1\xb1\x9f\x9f\x2c\xa5\x26\x84\x09\xb8\xcc\x19\xc6\x2d\xd9\x79\xb8\x96\x97\xe4\x57\xed\x2d\x98\xbd\x20\x96\xf6\x2d\x3d\x9e\x24\x73\x88\x79\x59\x27\x80\x3e\x79\xab\x71\xd4\xf7\x2f\x56\x8e\x94\x5a\x8a\x16\x21\x59\xd9\xb8\x48\x36\xe4\x58\x56\x44\xd4\x97\x9f\x61\x4a\xad\xa7\x3a\xd4\x13\xa8\x33\x91\xe9\xcf\x88\x0c\x42\xac\x2a\x98\x34\x3b\x6a\x82\xcd\x2b\x61\x58\x14\x56\xf6\xde\x5c\xeb\x24\xfe\x46\xb7\x62\x5d\x52\xab\x2c\x2c\x32\x4a\xc7\x47\x03\xd1\x5e\x15\xf1\xae\xff\x80\x55\xd2\xf7\x39\xf7\x36\x3e\x16\xec\x1d\x78\xbe\x2c\x62\x99\x43\x6c\x8c\x8d\x33\x6b\xd2\x92\x71\xa8\x97\xa6\xec\x93\x2e\xd0\x87\x25\xbe\x21\xb2\x8f\x9a\xa1\x4e\xaf\x4f\x71\x85\x31\x54\xdb\x14\x58\x7c\x93\x0a\xb3\xeb\x02\x27\xad\x7f\xfb\x45\xb3\xba\xa6\xa9\x99\x49\x9c\xc8\xa6\xe4\x5b\x1a\xb4\xd0\xb3\x39\x78\x2b\xcd\x9c\xfb\xcf\x88\xcf\x7e\xae\x89\x1c\xc8\x41\xe9\xc8\x8a\x1f\x6a\x69\x1f\x39\x48\xa6\xbc\x85\xba\x7f\x46\x11\x64\x2e\x84\x22\x3c\x3b\x17\x89\x46\xdd\xbe\xdd\xcf\xcd\xef\x4a\xe4\xc4\xe1\xa8\x14\xb9\xb1\xf0\x2b\x1e\xaa\x82\x4d\xb9\x3f\x44\xb2\x7d\x14\x20\x6b\x34\x04\x65\xa1\xce\xfc\xf5\x35\xc6\x3e\x55\xc4\x28\x72\x24\x26\x27\x33\xd9\x8a\xaa\xa1\x54\xf3\xad\x42\xcd\x85\x46\xa4\x61\xce\x0d\x46\xd8\x86\xd3\x46\x1a\x21\x50\xcb\x45\xdb\xe5\x64\x73\xff\x63\xd3\xdc\x7a\x2b\x95\x7b\x82\x39\x69\xf1\x9b\x59\x68\xe8\xb4\x24\xc8\x79\x74\x19\x26\xd8\x2c\x63\x86\x75\x3b\x0f\xa1\xf0\x80\x28\x4e\x55\x78\x94\x23\x63\xaa\xde\xb2\x1f\x8e\x1e\x89\x09\xfa\x6c\x38\x07\x64\x14\x9b\xc9\x15\xb2\x28\x60\x4e\xfc\x56\xd9\x2e\x4b\xeb\x72\x0e\xdc\x74\xc4\xd7\x8f\x92\x5d\x6c\xfd\xf7\xba\x2f\x14\xb5\x62\x37\x75\x81\x0d\x2d\x07\xbd\x38\x8c\x57\x3e\x36\x52\x3f\x21\x57\x38\xe6\x91\x14\xdc\xf8\xd8\x0f\x17\x0b\xfa\x67\x6e\x31\xfb\x62\x6a\x7d\x44\x9e\xd9\x66\x47\x36\x34\x75\x97\x0c\x8c\x47\x80\x97\x09\xbc\xb5\xe7\x20\x0f\x2a\x22\x7c\x7c\x8e\x7b\x00\x0f\x30\xc0\xbd\xe6\x1d\x67\xbd\x68\x95\x36\x16\x29\xa3\x6c\x8f\xdd\x5a\x56\xb8\x1e\xfb\xac\xf1\x5c\x1b\x35\x30\xa0\x8c\xde\xd5\xb1\xfd\x45\x7f\xbd\x2f\x03\x04\x2f\x56\xf1\xb3\x7e\xd1\x5c\xdb\x91\x2f\xa0\x29\x8c\x27\x67\x25\x08\x7e\xe2\x7d\x3c\xf2\x55\x0f\xe6\xe8\xa0\x33\x0a\xf4\x17\xf4\xf5\xba\xf0\x36\x27\xed\x67\xc5\xf8\x32\x33\x63\xab\xac\x5a\x1f\xe3\x48\x23\x18\x0e\x3e\x0e\x20\x80\xf7\x5b\xfd\x91\xc2\x07\xcf\x6b\xaa\x9a\x22\x9c\xf4\x43\xdd\x44\x2c\x59\x02\xe0\x67\x3f\x32\x52\xb8\x52\x63\x46\x58\x58\x72\xf6\xcd\x36\x60\x25\xa5\x69\x92\xb7\x0e\xde\x39\xbc\x8d\x32\x2f\x9c\x22\xa1\xdc\x59\x9e\x9f\x0d\x52\x4c\xb6\xd2\xea\x5a\xe2\x87\x8e\xf6\xbe\xd4\xb7\x02\x80\x7f\x1e\x1e\x73\xeb\xf2\x90\xeb\x6c\x0e\xeb\x85\xc1\x37\x16\xf6\x26\xaa\x90\xd3\x64\xb4\x90\x48\x37\xce\x05"}, -{{0x29,0x73,0x11,0xdd,0xef,0xfe,0xc9,0xd2,0xbe,0x68,0xef,0x7b,0x2a,0x20,0xfe,0x2d,0x27,0x7e,0x1d,0x8e,0x51,0x64,0x8b,0x03,0x57,0x2a,0xda,0x27,0xec,0x1f,0x9f,0x43,},{0x6a,0x6c,0x28,0xe7,0x61,0x64,0x0c,0x40,0x08,0x33,0x3a,0xae,0x5a,0x33,0x66,0x30,0x2e,0x2f,0x46,0x77,0xa9,0x53,0xba,0x48,0x2a,0xb6,0xfb,0x4a,0x1d,0x70,0xb4,0x47,},{0x4b,0xf0,0xb9,0x2c,0x6e,0xe4,0xea,0xce,0x5e,0x8e,0xb1,0x03,0x70,0xff,0x9d,0x9c,0x68,0xa5,0x74,0x9d,0x59,0x89,0x9d,0x04,0x32,0x7a,0xaa,0x38,0xf8,0xf8,0x25,0xe0,0x32,0xe5,0x97,0x42,0xb3,0x7d,0xe2,0x31,0x07,0xa3,0xec,0xdd,0x3f,0x7a,0x0d,0x08,0x12,0x26,0x14,0xb7,0x8f,0xdd,0x37,0x29,0x3c,0x8d,0x05,0xe2,0x8f,0x5f,0x71,0x08,},"\x26\x52\xac\xfc\x3b\xdf\x09\xa5\x99\xec\x67\x86\xbb\xd9\x4f\xe5\x77\xcf\x57\x8e\x02\x63\xcc\x68\xd9\xf5\x7a\x6c\x83\x45\x8f\x80\xac\xd8\xa7\x5e\xf0\x30\x40\xa6\x35\x67\x2b\x96\x8f\xf2\xaf\xdb\x28\x8d\x28\xb9\x99\x6f\x64\x15\xb2\xf3\x17\x5e\x9e\xa3\x7a\xeb\x05\xdf\x81\x81\x2e\x38\xa4\xc9\x76\xeb\x92\x85\x6c\xed\xb9\x1a\x26\x9a\x46\xfc\xa5\xdf\x9b\xd7\x30\xfd\x84\x45\x2b\x4b\xd9\x35\x77\xc6\x1f\x42\xc1\x41\x13\x97\x98\x82\xa8\x6a\x9f\xe6\x32\xe4\x75\x6a\xfd\x89\x81\x6f\xc4\x67\x0a\x31\x05\x03\xfd\xaa\xd2\xdb\x76\x4c\x37\x21\x21\x3c\x3e\x60\xf2\x9c\x26\x68\xd4\xde\x8f\x42\xb0\x87\xf2\x5c\xd5\x6c\x69\xa4\xe4\x8f\x13\x4f\x55\x98\xcf\x14\x5b\xe6\x38\xa5\xc2\x31\x88\x63\x32\x90\x61\x72\x9a\xac\x91\xda\x6a\x19\x1f\xd7\x74\x88\x0c\xf9\xcb\x55\x5e\xec\x15\xb0\x04\x4f\x10\xe5\x43\x3f\xb4\x6a\x9b\x88\x92\xda\x8f\x6d\x24\xf1\x42\x58\x8b\x70\xff\x0b\x49\x20\x0c\x50\x6b\x88\xbe\xd4\x49\xad\x10\xd3\xf9\x2c\x2b\xae\xda\x6b\xbf\x58\x67\x6c\x5b\xbc\x67\xd3\x1f\x64\xfb\x12\xe8\xd5\xe7\x88\x76\xd5\xc8\x49\xfc\x31\x4b\x2c\xf8\x01\x0c\x51\x02\x04\xc8\x63\x3d\x0c\xc3\x18\x56\xec\x6a\x11\x4e\xa8\xa8\x9c\x48\x92\x7b\x07\xa3\x1a\xb8\x42\xc9\xb8\x35\x2d\x93\x67\x34\x51\x41\xa9\x9b\x40\x04\x9d\x5c\x48\xe7\xd2\x7c\xab\x42\x7a\xde\xfd\x1f\x0f\xc1\x13\x6b\x35\x3c\xb0\x1c\x3d\xef\x91\xff\xfe\xe8\xad\x91\xe8\x8f\x4b\xb7\xd2\x61\x5c\x0d\xcc\x95\x34\x4c\xd0\x19\x50\x93\x8e\xcb\x14\xb8\x44\x6b\x56\xa0\x6b\xf2\xf2\xf6\x5f\xb8\x73\x5e\x8a\x7b\xc9\x6b\xb4\x6c\xe9\xca\xc7\x1a\x88\xeb\x8f\xda\x5e\x69\xd6\x9e\xb2\x9a\xa4\x2a\x01\x6b\x85\x83\x89\x3e\x9d\x72\x77\xcb\x13\x59\xc5\x68\x7e\xed\xcd\x59\x9d\x8a\x46\xe6\xc1\x49\x63\x63\x7d\xb0\x4a\x92\x9f\x4b\xc7\x93\x04\xac\x2d\xae\x73\x3b\x3a\x83\x9e\xb7\x4f\xbe\x3d\xe5\x04\x2f\xd6\x55\xea\xec\xb1\x5f\x39\xb2\xfe\x16\xda\xd8\xa6\xff\x8d\xbc\x05\x4f\xed\x51\x28\x2a\x85\x6e\x9d\xa6\x31\x6f\xac\x6d\xb5\xd5\x6f\x77\xf1\x8d\xa8\x41\x2e\xb3\x77\xe5\xb1\xb8\xf4\xcb\x13\x54\xec\xfe\x8f\xe8\xfd\x54\xe6\x2d\x76\x7a\x80\xde\x04\xcb\x76\x20\x22\x9a\x88\x31\xdb\xc9\xec\xd4\x57\x8f\xfa\x2f\xf0\x6b\x54\x45\xe4\x40\xd6\x9a\xab\xc9\x4c\x47\xbd\x17\xf2\x2b\x69\xf5\x2e\xea\xe5\xcf\xcd\x01\xa5\xca\xfe\x05\x80\x07\x2a\xe9\x16\x6b\x95\x74\x3d\x68\xc3\x56\x4c\x5a\x7e\x46\xf2\x4b\xc4\x8a\x89\x8a\x1a\xb2\xeb\xe6\x3f\x36\x85\x1d\x2a\xac\xfa\x0c\x4f\x32\xd9\x93\x77\x1d\x31\x4e\x72\x5a\x43\xd9\x80\x5d\x13\x71\xcf\x72\x3e\xf1\x61\xd4\x2e\x63\xff\xca\x68\x8d\x7f\x0e\x21\xef\x5b\x3f\x9a\x56\x1a\x62\x10\x70\x2b\x85\xfb\xd1\xf8\xca\x75\x38\x9c\xc7\xa2\x27\x39\xba\xe4\xde\xd9\x37\x57\xf1\x52\x0d\xc3\x88\x44\xa1\xa8\x8b\xe8\xe0\x96\x45\x05\x91\x48\x80\x7b\x93\x37\x70\x87\x8c\xb8\xa9\xad\x92\x11\x31\x71\x31\xe6\x93\x24\x53\x2f\xd0\x27\x9b\x83\x18\x5b\x62\x8f\xc2\xf9\xe2\x15\x00\x38\x46\x93\xfa\x29\xf2\x6b\xd1\xb9\xc3\x01\x60\x13\x67\x66\x5f\x05\xf3\x72\xda\xb4\xe3\x10\x77\x26\xcd\x3f\x63\x9c\xa6\x2b\xf6\x3a\x75\xf7\x7e\xaa\x75\xf7\x13\x61\x57\xad\xa2\x37\x4e\x65\xfb\x4f\xd3\x49\xb4\x5e\x25\x44\x1f\xd2\x1b\x13\xe6\x91\x13\x66\xb9\x7c\xfb\x4d\x6a\xd5\x22\xb8\x50\xad\xf4\x0c"}, -{{0x4d,0xb2,0xb5,0x81,0x44,0xa8,0xd2,0xd0,0xec,0x03,0xbb,0x9b,0xc2,0x9b,0x4c,0xa8,0x93,0x85,0x4c,0x80,0xb6,0x4a,0xfa,0x4a,0xf7,0xa9,0xc9,0x36,0x93,0x5e,0xcb,0x04,},{0xfc,0x5c,0xd7,0x50,0xe1,0x74,0xed,0x71,0x8b,0xd9,0x38,0xfa,0x8e,0xd9,0x9a,0x1b,0x9d,0x55,0x6b,0xa7,0x67,0x0f,0x2a,0x77,0xda,0xf1,0xc7,0x20,0x11,0x37,0x32,0xa5,},{0x42,0x45,0x17,0xaa,0xdd,0x85,0x3c,0xe3,0x98,0x57,0x59,0xa3,0x27,0xe7,0x76,0x0d,0x91,0x56,0xd3,0xb2,0x73,0x45,0x38,0x3f,0x0e,0x4a,0xd6,0x66,0x1e,0xe4,0xa3,0x72,0x4d,0x18,0xd8,0x20,0xf6,0xc5,0x57,0xf8,0x27,0x97,0xbe,0xb6,0x2d,0x2f,0x08,0x54,0x33,0x74,0x4f,0x89,0xa2,0xd8,0x52,0x93,0x79,0x64,0x81,0x86,0x2e,0xf8,0xa4,0x0f,},"\xc8\xd1\xdb\xc9\x36\x91\x1e\x12\x2c\xee\x18\xf9\x2b\x16\xa3\x9a\x2e\xef\x08\x23\xb2\x27\xf8\x98\xcd\xf5\x84\x2b\x93\xd5\x9f\xc0\x02\xed\xb5\x49\x8a\x20\x87\x2e\x19\x55\x4e\xf7\x39\x99\xeb\x3a\x7b\x3e\x2f\xdd\x90\x70\xe1\xef\xa9\x22\x8e\x9e\x93\xb2\x9a\x86\x8a\xe3\x79\x9e\x4e\x57\x23\x24\x83\x6b\x1a\xd5\xaa\x81\x2b\xf0\x0f\x84\x5b\xc2\x17\xeb\xbc\x3f\xab\xdc\x4e\x1b\x6e\x51\xef\x9e\xfa\xc2\x77\x0a\xa0\xa4\xa1\x1e\xe5\x2a\xb9\x56\xac\x64\x48\xaa\x26\x29\xcb\x61\xdb\xb1\xf1\xed\xb3\xbd\xe9\x9b\x48\x76\xda\x39\x2a\x6e\x0b\x9a\x0c\x31\x84\x9a\x58\x90\xae\xa9\x52\x2f\x56\xd0\x15\xa1\x93\x50\x15\xb9\x1b\xf4\xc6\xa0\x01\x1d\x23\x77\xd6\x71\xc3\xd0\xd7\x53\xc2\x7f\x8c\x76\xe4\x05\xd0\x23\x0f\x1f\x4b\x9b\x88\xfc\xeb\xba\x1e\xaf\x13\x77\x72\x35\xe5\x53\x24\xb7\xd3\xf8\x1e\x68\x61\x09\xd9\x1c\xe6\x89\x53\x0b\x90\xd2\xc5\xc7\x1d\xd1\x87\x72\xb3\x85\xd6\x2c\xcb\xfd\x2e\x08\x9a\x1b\x67\x09\x83\xf6\x0c\x21\xc4\x45\x5c\xb9\xd1\xa0\xdc\xaa\x74\xc8\x74\xe3\x52\x11\xf8\x22\x7f\xf7\xc2\x34\xdf\xf8\x5e\xc0\xb0\x7e\x36\x8c\xfa\x50\xa3\x43\x57\x83\x95\xa1\x4c\x68\xf1\xf8\x9b\xd4\xec\xbc\x17\x2e\xf8\x05\xe5\x83\x1e\xc8\x94\x75\xfc\xc8\xd6\x85\xca\x92\x55\xa7\x7e\x3b\xa3\xc1\x47\x50\x8e\xc9\x2d\x7b\xcc\xe8\x79\xaf\x0a\xbd\xd2\x41\x6b\x67\xb5\xf5\x05\x07\x33\x79\x14\xf3\x90\xbb\xe0\xb4\x50\xb6\xa2\xf1\x15\x93\x72\xc4\xbc\xce\xa3\x82\xce\x3d\x6d\x9f\xb2\x51\x5e\xcf\x79\x30\x05\x9a\x05\x52\xb7\x5f\x97\x88\x62\xbf\x97\xe8\x32\x5a\xf2\x4d\x1b\x8c\xe9\x51\x2b\xfc\x7c\xef\x88\x42\x32\x04\x23\x41\xd8\x2f\x9b\x5d\xad\x2e\x50\x2a\xc6\xac\x79\x5f\x99\xda\xc7\xfc\x60\xe3\xb8\x63\x9d\x0e\x15\x00\xde\xad\x4e\x78\xac\xa1\x09\x95\x7d\x57\x7a\x13\xc1\x92\x5d\x74\x03\xc1\xac\xf9\x89\xa9\xde\x67\x11\xe2\x3c\x67\xbf\x87\x22\xf5\x51\xb7\x74\xca\xda\x93\x1b\x5f\xd9\x73\x43\x4e\x3b\x71\x72\x81\x98\x83\xe7\x0c\x52\x78\x5e\x3b\x49\xd3\x23\xd0\x56\x36\x64\x11\x58\x64\x0d\xcf\x6a\x4c\x20\x0e\xb2\xc1\x3b\x1b\xee\xb2\xdc\x36\x03\x52\x47\x0d\x15\x38\x6e\x59\xe6\xfa\x60\x36\x7e\x5e\x7f\x17\x2b\x21\x15\x9d\x5e\xe7\xca\xb0\xd7\xf5\x86\x82\x39\x85\x8e\x2a\x93\x55\x04\x80\xfe\x8f\xb4\xdc\xaf\x4f\x22\x4c\x4b\x2a\xd5\x44\x87\x91\x63\x2d\xf3\x0e\x8e\x5f\xb9\x98\xb3\x5e\xa9\xae\xc8\xc9\x34\xa4\x40\x3a\xef\x82\x18\x7c\xa1\xab\xf8\x2a\x34\x4d\x00\xff\xb9\x93\xd9\xff\x34\x61\xd6\xfe\xcd\xaf\x5d\x3b\x48\x1e\x0d\x31\x15\x3d\xbf\x6a\xed\x28\x8c\x8a\xdd\x06\x4e\x83\x31\x55\x01\x41\xbd\x5f\x7a\x7e\x04\x7b\x86\x07\xd8\x46\xa6\xbf\xb7\x2d\x68\x34\x46\xa4\x45\x11\x46\x06\x25\x0d\x8d\x2d\x3a\x8b\x95\x08\xbb\x07\xd4\x62\x3c\xdf\x17\x88\xb5\x49\x9e\x9c\xb9\xa1\x37\x98\x49\xbf\xa1\x9c\x9a\x9f\x4c\xd3\xd9\x25\x3a\xdf\xfd\xa2\x5f\x47\xc8\x11\xbe\x83\x3b\x02\xf3\x32\x7e\xbb\xa8\x37\x30\x19\x5d\x61\x4b\xae\x6f\xe4\xe7\xa3\x83\x08\x15\xd2\xaf\x40\x0d\x20\xa9\x41\x7a\x09\x5e\x7e\x8e\xea\x10\x44\x91\x7c\xbe\x51\x2c\x40\x18\xd6\x56\xe2\xdb\x67\xbb\x98\x9c\x00\xe1\xe5\x07\x62\x3e\x82\x78\xd7\x29\x92\x5b\x84\xfb\x5c\x18\x6a\x7b\xac\x18\x9e\x6d\x6a\xb1\x4f\xd7\xb6\x2f\xdc\x63\x2b\xeb\xb5\xf7\x7c\xb5\xcc\x2f\x70\x7d\xf4\x05\x30\x99"}, -{{0xc8,0x20,0x41,0x3c,0x24,0x56,0x74,0x71,0x04,0x66,0x2e,0xf4,0xdf,0xf3,0xac,0x23,0x3a,0xc4,0xb9,0x1a,0x76,0xd3,0xc4,0xea,0x75,0x44,0x90,0xbc,0x9b,0x1e,0x29,0x1f,},{0x89,0x93,0xce,0xa2,0xf7,0xf2,0x80,0x6c,0x77,0xb3,0x98,0x1b,0x54,0xbf,0xa9,0xbf,0x17,0x62,0x15,0x1b,0x41,0x8e,0x5e,0x72,0x53,0x71,0xca,0x2c,0x04,0xd2,0x23,0xee,},{0x7e,0xf7,0x0e,0x4a,0x14,0x95,0x4d,0x50,0x9f,0x11,0x7f,0x4b,0xd0,0x1b,0x22,0x0b,0xcc,0x19,0x2d,0x3b,0x5f,0xdf,0xc3,0x48,0x2f,0xbb,0xc3,0xb6,0x9d,0xc0,0x68,0xa7,0xc4,0x76,0x1d,0x1b,0xeb,0xc2,0x31,0x7d,0x6d,0xb7,0x4f,0x90,0x6a,0x15,0x56,0x42,0xb0,0xa3,0xc6,0x59,0x2b,0xdc,0x72,0xe6,0x4e,0xac,0x6f,0x20,0x3f,0xb7,0x4e,0x02,},"\xd2\x99\x2f\x83\x92\x4a\x59\x48\x87\xe6\xef\x13\xf2\xae\x80\x8f\xc8\x63\x9c\x7b\x2c\x99\x4f\xaf\x0f\x79\x5e\x36\x01\x6d\xab\x77\x00\xa0\xee\x53\x01\x70\xf0\xb9\xfe\x98\xab\x75\x88\xce\x03\xbc\x50\xc2\xba\xe6\x5e\x05\x26\x47\xe7\x56\x73\x5b\x35\xd0\xb5\x9c\x96\x4e\x91\x7d\x8c\x83\xe2\xf9\xfe\xcc\x4c\xb0\x55\x64\x28\x7f\x0e\x34\xc9\x49\x40\x05\xe2\x5b\x1a\x8b\x1b\x94\x2b\x54\xd8\x90\x35\xf1\xb1\xc3\xc9\x45\xfc\xc8\x4e\x4a\x39\xef\xa2\xca\x50\x95\x9b\x45\x9a\xf7\x4d\x21\xb6\x24\x2e\x2f\x56\x51\x8f\x70\xe8\x67\x92\x57\xc0\x89\xd2\x6c\x3b\xb7\x92\x68\x7c\x92\x33\x55\xb2\xc1\x8e\xe2\x13\x6d\x40\xcb\xa4\x5a\xcb\x64\x24\x0d\x96\x67\xf3\x9d\xba\x36\x39\xb6\x51\x6d\x4c\x49\x47\x57\x3e\xf4\xce\xd8\x76\xb5\xb2\xea\x34\x89\xea\xea\x53\x9f\x55\x7f\x58\xda\x20\x46\x91\xa7\x6e\x29\xc9\x4b\x8b\x05\x38\x23\x2c\x5f\x7d\x0b\xb0\xfd\xd0\x16\x91\x04\x31\x35\x4b\x3e\x1e\x7c\xe6\x2a\xd4\x36\x91\x7c\xd5\xc3\x15\xa5\xbe\x9b\x97\x1c\x80\xf9\x7b\xc9\xd5\xc1\x56\xff\xd6\x4f\xd4\xe3\x1d\xa5\x60\x83\xe0\x2a\x0c\x8f\xce\x55\x4d\xb6\x86\x74\xcb\x62\x70\x0b\xa9\x51\x75\x2b\x82\x9b\x03\xc5\x42\x32\x74\x12\xee\xc9\xcc\xc6\xa5\x0a\xdf\x47\xbb\xee\x15\x44\x66\x82\xda\x2f\xea\x42\x04\x89\x36\xd7\x63\x06\x0c\xd8\xf5\x39\x65\x26\x16\xdf\xa8\x08\xd6\x23\xff\x77\x7b\x41\x13\x65\x2e\x78\x9e\xc0\x25\xb8\x5e\x04\xef\xe8\xad\x4c\x96\x0b\x19\x0b\xf4\xa5\xa6\x32\x4d\x6f\x57\xc1\xad\x22\x01\x8c\x83\xcd\x7e\x7e\x09\x7f\xc6\x7b\x80\x26\x9c\x13\xb4\xdd\x97\x01\xca\x98\xf9\x87\x69\x58\xba\x76\x89\xc6\xf6\xf1\x0a\x73\x2a\x64\xbe\xf2\x2e\x8b\x98\xbd\x30\x4d\x5d\xbf\x4f\xb1\xf9\xe4\xca\x53\x9a\x5c\x4a\xa6\x19\xc4\x4d\x6f\x58\xf8\x24\xb2\xdb\xae\x77\xb7\xe8\x3b\x56\xdb\x5e\x5a\xa7\xb0\xae\x9c\xe1\xcd\x10\xa6\x9f\x04\xa8\x0f\x13\x79\xeb\x0c\x47\x4e\x47\x82\xdf\x0e\x3b\xa6\xa1\x48\x22\x6b\xd1\xa6\x62\xd9\x5e\xe2\xd6\x7c\x52\x07\x33\x3c\xb1\xd5\x41\x76\xd9\xe5\x06\x45\x94\x79\x02\x9f\x31\xdc\xac\xe2\x69\x93\x8f\x6b\xc5\x62\x78\x78\x41\xdc\xfe\x10\x1f\x4d\xb6\x0b\xd6\x60\x16\xe1\xee\xbb\x6b\xfb\xd9\xcd\x83\x04\x2d\xd1\x37\x9a\x46\x4f\x40\x5a\xaa\xe3\xc1\x18\x07\x84\x8c\xc4\xf9\x5c\x3c\xc6\xfa\x92\xab\x4e\xa5\x30\x58\x34\xeb\x86\xb8\x73\xfa\x30\xed\x1f\x7f\x47\x0b\xf6\x63\xf1\xa7\x0c\xf9\xe6\x0a\xb6\x80\xcd\x1d\xbb\xd0\x3a\xc0\x43\x3b\x3d\x4b\xb4\x82\xf8\xb3\x44\xd4\x6b\x3a\xa9\x34\xb8\x63\x3f\x57\x09\x0b\xea\x5f\xcc\xca\x64\x88\x79\x98\x35\xf1\x33\xf8\xbc\xf6\xe8\x87\xca\x59\xd1\x90\x76\xd6\xca\x19\xd4\xe2\x83\x49\x05\x1e\x01\x6b\x03\xe9\xa9\x20\xf4\x12\x0f\xb5\x23\xd1\x37\x1d\x0e\x38\x46\x73\x19\x54\x3f\x12\x7e\xd9\x14\xb4\x3a\xd0\x62\x22\x6a\x53\x65\x82\xdb\x72\x8c\xcd\x76\xe9\x83\xf1\x17\x66\xa8\x86\x3c\x2f\x42\x4f\x65\x50\x8d\xcb\x26\xfe\x0c\x5a\x80\x0c\x35\x09\x39\x60\xa1\x21\x97\x6e\x30\x51\xe2\xef\x1a\x2a\x99\xc1\x2f\xb7\xbd\x8b\xc0\x37\xa4\x39\x68\x68\x06\xeb\x72\x01\x7a\x07\x1a\x91\xb3\xe3\x9c\x90\xe8\x6b\xc3\x35\xf9\xbb\x54\x3b\x12\x7c\x98\x86\x73\x8c\xb5\x38\x06\xb9\xcb\x3c\x25\x94\xc7\xef\xfc\x2a\x59\x20\xaa\x83\x4b\xe6\x5c\x49\xf4\x79\x64\xe8\x9e\xec\x74\x72\x8d\xe7\x71\xf3\xd6\x75\xde\x9d\x1e"}, -{{0x67,0x69,0xcc,0x8e,0x12,0x56,0x17,0xc2,0x2c,0xe5,0x72,0x37,0xa4,0xfc,0xa1,0x50,0x7f,0x94,0x12,0x34,0x66,0x1d,0xf7,0x43,0x28,0xd0,0x4a,0xb6,0x2e,0xf8,0x6c,0x47,},{0x05,0x11,0x2c,0xa6,0x0b,0xaf,0xf7,0x9b,0x49,0x16,0xc1,0xbe,0xe2,0xb9,0x39,0x0c,0x04,0x7a,0xf0,0x8c,0x35,0xeb,0xb3,0xc3,0x81,0xb9,0x74,0x8d,0x1d,0xd4,0xc4,0xfd,},{0xd3,0x9d,0x85,0x3d,0x2c,0x2c,0x5d,0x21,0xb5,0x87,0x1e,0xa5,0xa7,0x5c,0x04,0x10,0x48,0xd9,0x3a,0x47,0xdc,0x59,0x9a,0x5f,0xdd,0xc0,0x85,0x62,0x85,0xce,0x63,0x6f,0xcd,0xfd,0x85,0x64,0x08,0x3d,0x06,0xff,0x28,0x4a,0x52,0x4b,0xc6,0x33,0xcf,0xdf,0xc3,0xb0,0x37,0x16,0x3d,0x67,0x4c,0xb9,0xbb,0x5b,0xa3,0xbc,0x25,0xbe,0xd0,0x0e,},"\x68\x54\x89\x73\x9b\x98\x56\x47\x49\x58\x7f\xf1\xac\x96\xba\x68\x2d\xa3\x0b\x40\xa4\xde\x24\xf5\x4e\xc8\xb0\x83\xdd\xa4\x53\x33\x16\x21\x67\xcb\x3f\x97\xb2\xc7\x31\x4c\xe7\xa3\xf3\xf3\xd3\x19\xcc\xc3\x5b\xb6\xa9\xf0\x07\x7d\x56\x31\x61\xe2\x81\x46\x9c\xf0\x89\x68\xd9\xdc\xf7\xae\x5f\xff\x83\x0a\x5d\xb0\x0b\xc3\x80\x10\xe6\x66\x2d\x49\x4f\x3c\x86\x47\xc4\xf7\x0c\xe2\xd2\x9a\x9d\xa8\x46\x10\xa0\x80\xb5\x75\x9a\x3b\x58\x20\x52\xdf\xde\x66\xe4\xa7\xfa\x5f\xb2\x7f\x06\x50\x73\xfe\x72\x3d\x83\x70\x1d\x5b\xac\x06\xca\x43\xb4\x6d\x1e\x58\x09\x76\x70\xc1\x94\xa1\x3a\xf8\xb5\x73\xa3\x79\x1a\x96\x61\x55\x7c\xbc\x04\x27\x57\xab\x8a\xdd\x0e\xf7\xcf\x4f\x35\x43\x5a\x42\x12\x35\x3f\xcb\x3c\x20\x3c\x73\xdb\xc9\xd2\x68\x52\xd0\xe9\x17\x32\xe3\x62\x1c\xe8\x28\x92\x9c\xdc\xa4\xd9\x19\x20\x48\x75\x19\x22\xed\x22\x5e\xab\x29\x00\xcf\xf9\x71\xa2\xa2\xd3\x42\x46\x36\x48\xbb\xb1\x94\x43\x19\xa8\xef\x6d\x43\xdb\x62\x48\x0f\xbf\x1d\x72\x57\xd2\x26\x94\x53\x97\x93\xf2\x5c\x92\x79\x17\xca\xab\x25\xc1\x19\x3a\x2d\x2b\x23\xbb\x5c\xb8\x56\x9a\xef\xff\x4f\x0c\xa4\x23\xd1\x9b\xbd\x46\xfc\x5e\xf7\x52\x4f\xf8\xcb\x70\x6f\xfc\x47\x07\x65\x09\xc0\x5a\x81\x58\xaf\x77\xf9\x8d\xf6\xa9\xb5\xcb\x32\x44\xab\xa4\xb5\xc5\xf9\xce\x59\x7e\x7d\x29\xba\x07\x01\x3d\xca\xc1\x91\x1b\x6d\xe7\x11\x3c\x73\x6a\x40\x05\xc4\x59\x99\x29\x79\x01\x9a\x45\xb2\xdd\x80\x2a\x07\x66\x09\x09\xeb\x4c\xe2\x05\x40\x81\x70\xd8\x25\x45\xda\xcb\xa8\x68\x6d\xbd\xe9\x27\xdb\xc9\xc7\xd9\x62\x05\x8e\x9a\x95\xea\x66\xb8\xdf\xd3\xea\x43\x53\x57\xa9\x3c\x73\x94\x8c\xd3\x55\xf6\xac\x65\x52\x32\x3f\x17\xc2\xa6\x78\x66\x2b\xc0\xe9\x72\x6a\xd5\xa5\x25\x1d\xd2\x76\x47\x40\x4c\xbf\xe6\x1c\xea\xaf\xdc\xfc\x08\xa4\x75\xff\xd8\x7c\xb7\xf5\x97\xe5\x6a\xc1\x67\x04\x09\xdd\x94\x08\xae\x47\x70\x42\x0c\x6e\x5e\x6d\xd8\xe7\x48\xfe\x03\xa7\x2d\xc1\x28\x03\xd0\x27\x71\xd9\x2f\x47\xe6\xe7\x17\xcc\xc1\x44\xfc\x03\x72\x75\xb6\xf7\x45\xdd\x30\xda\x1a\x45\xd2\x9d\xb6\xd9\x07\x3e\xee\x50\x09\xcf\xd5\x46\x27\x33\x41\x4a\x49\x5f\x34\x9d\xb0\xb6\xdb\xf2\xce\xa9\xcc\xd5\x72\x38\xed\x5e\xe9\x1a\xd8\xbc\x86\x17\x9a\xd5\x69\x5a\x85\xa5\x04\x84\xe6\x17\x75\x1d\xe5\xef\x7a\x7d\x8a\x8d\xb9\x50\xa9\x8a\x6b\x7f\x7d\xee\x9d\x42\xa5\xdf\x69\x2f\xcc\xf5\x55\xc9\x40\xdc\x39\xcf\x2e\xac\x48\xcb\x9d\x15\xcd\xa1\x4d\xd2\xa7\xec\xc0\xb7\x6e\xbe\xc6\x8a\xd4\x17\x7d\x11\x17\xe0\x77\x66\xc4\x85\x90\xd4\x3c\xa7\x66\x28\x68\xeb\x97\x90\xac\x29\xf4\xf2\x39\x2b\x9a\x93\xf8\x97\x59\xe7\xba\x54\x6b\x92\x5b\xd8\x6f\x80\x7d\x8d\x16\xc7\xe6\x37\xdc\xc6\x66\xe9\x05\x90\xbf\x43\x0d\x98\x6a\x67\xf1\xb0\xc7\xc2\xc9\x49\x30\x84\x58\x69\xed\x8d\x8a\xdd\xe1\x8f\xc1\x88\x74\x56\x88\x1b\x4b\x26\xb5\x3d\xcb\xa7\xa5\x26\xf0\xec\xa1\x4e\x8b\xb6\x89\xd6\x6f\x0a\xa1\xb2\x53\xc3\xdc\xfc\xf5\x95\x40\xd5\xd2\xf5\xad\x61\x7f\x52\xc3\x09\x38\xa5\xa9\x2e\xa3\x85\x07\x7d\x75\xaa\x4a\xc0\x7a\xfc\x2b\x35\xfb\x8c\x1d\x5e\x78\xeb\x29\x5f\xc2\x0f\xe3\x7c\x41\xac\x06\x95\x9d\x3a\x17\x97\x84\x3a\xd7\x05\x6c\x1b\x41\x2d\xd0\xb4\x80\xaa\x3b\x39\xbc\xc2\x05\x87\xd9\xa0\xfe\xf9\x2c\x6c\x95\x0e\xbc\x5b\xb8\xe1\x42"}, -{{0x1d,0xf7,0xac,0xfb,0x96,0x33,0x04,0xe5,0x1e,0xc4,0x71,0xca,0xf1,0x81,0x10,0x25,0x56,0x78,0x3c,0xb7,0xd9,0x1e,0xad,0x30,0xbd,0xc2,0x53,0x4d,0x07,0x8a,0x14,0x88,},{0x05,0xa3,0x1f,0xfc,0x70,0xe4,0xe3,0x56,0x9f,0xc2,0xbe,0x11,0x0c,0x64,0x3a,0xd5,0xf0,0x87,0x91,0x3c,0x7a,0xa4,0x76,0xdc,0xd8,0xd6,0xe4,0xbc,0x7e,0xc2,0x2d,0x24,},{0xb1,0x81,0x93,0x8d,0xe1,0x01,0x42,0xf3,0x24,0x07,0xb4,0xe7,0x86,0xcd,0xdd,0xe9,0x32,0xeb,0x11,0xdb,0xc0,0xbf,0x0e,0x5a,0xc5,0x09,0xfa,0xe7,0xa5,0xbc,0xc3,0x29,0x61,0xfe,0x34,0x48,0xf9,0x12,0xc8,0x50,0x0f,0xc6,0xdb,0x4e,0x1d,0x32,0x62,0xa8,0x3c,0x9d,0xbe,0x76,0x9b,0xb8,0xc3,0xa7,0x61,0x00,0x0f,0xe3,0x6c,0x0d,0x71,0x04,},"\xb0\xc3\xee\xb5\x7f\x14\x60\x6a\xb7\xab\xea\xb2\xee\x05\x73\x84\x3c\xa2\x2e\x6d\xb2\xfd\xf2\xc9\x06\x4c\xea\x51\x98\xdc\x58\x30\xeb\x15\x8d\xa8\xe2\xda\xa8\x88\x57\xaf\x8b\x8e\xef\xcc\xf0\xc2\x6c\x3e\xc0\xf3\x30\xe9\x2c\xff\x06\xbc\x05\xa2\x9b\xfc\x99\xf9\x40\xb6\x1f\x3c\xfb\x29\x64\xb3\x37\x09\x7a\x65\x50\xa3\xe9\xa3\x28\xc8\x5b\xe6\xf1\x60\xd2\xc0\xa5\x7f\xf6\xf1\xb3\xc5\xff\xcc\xa8\x90\x89\x42\x5a\xb6\xbe\x01\x72\xe1\x75\xba\xf4\x0c\xf1\x2b\x24\xa8\x15\xf7\x0f\x29\xa3\xa4\xcd\x0a\x6a\x13\x2f\x12\x00\x97\x75\x2f\x4b\xc7\x43\xed\xe0\x8f\x5f\x21\xd4\x2f\x28\x2f\x76\x71\xf7\x78\x3e\x27\xb2\xa8\xe2\xc1\x46\x92\xf1\xe0\xe5\xde\x82\x85\x5d\xab\xf9\x8a\x1a\x63\x97\x60\x06\xff\xbf\xe5\xf5\xa5\x79\xb4\x60\xe2\x6d\x06\xbd\x54\x28\x42\xa5\xf9\x26\x1b\xbf\x26\x04\x51\xd2\x32\x1c\x50\x89\x32\x01\x3c\xc6\xe9\x04\xf7\x9b\x5e\x46\x86\xd0\x33\xe1\x2c\x7b\xbd\x7e\xb1\xc9\x23\x79\xc5\xec\x34\x1b\xf6\x45\x7a\x3f\x17\x26\x4a\x7c\x27\x8b\x27\x50\x1e\xca\xed\xc3\x61\xeb\xa8\x44\x44\x23\x42\xb4\xb1\x0f\xa9\x4d\x26\x58\x65\x11\x6a\xcf\x43\xfc\xbe\xc9\x65\xd2\xab\x4b\xbb\xe6\x14\xc4\xf9\x0a\xb6\xb3\xe0\xd5\x38\x3f\xa0\x49\x88\xbf\xbb\x26\x03\x07\xdd\xe2\x2d\x84\x09\x8b\x63\x31\xd1\x55\x14\x1a\x92\x7b\xb7\x8d\x66\x4b\x34\x1d\x2f\x2a\x93\xe2\x91\xcf\x79\xba\xae\xcd\x26\x12\xf6\xb1\x04\xf3\xfc\x81\x37\x3a\x7c\x6a\x04\x5b\x59\x24\xbf\x95\x0c\xd5\x42\xf7\xb7\xac\xce\xf3\xaa\x7d\x72\x5d\xe0\x53\x05\x5d\x95\x1b\xd7\x68\x11\x13\x92\x59\x66\x38\xae\x09\x71\x70\xf4\x49\x2b\xa5\x0a\x46\x8f\x8e\x34\x77\x63\xdb\x61\x2d\x3c\x7d\xe7\xe5\x64\x59\xb2\x6e\xe0\x29\xc6\x30\x82\x7a\x35\x3a\xee\x73\xde\x68\xd6\xd7\x2b\x27\xaf\xd7\x5d\x22\x16\x45\x27\x94\x5c\x72\x26\x84\x4f\xab\x15\xb8\xdc\xc9\x14\x34\x9e\x31\x41\xc6\x13\x16\xad\xc8\x94\xde\xdc\xdc\x84\x39\x84\xd9\xc7\xfe\xae\x39\xdb\x33\x2d\xc3\x93\xe9\xe8\x96\x1b\xbd\xe0\x71\xc3\xd2\x85\x8b\x3c\xb5\xf3\x3b\x16\x4a\x15\x61\x6c\x6f\xe1\xbb\xc2\x4a\x35\xf2\x13\x36\xd2\x61\xc5\xd8\xcf\x75\x9e\x27\xe2\x2c\x91\x01\xc4\xae\xbd\xe3\xe1\x26\xcf\x64\x6c\xa7\xb2\xe0\x31\x28\x09\x5c\x59\x76\xbf\x3f\x6e\x49\x1a\xf0\xf0\xb6\x40\xc7\x31\x09\x66\xac\x59\xc5\x9f\xbc\x5b\xfe\x05\x48\xf8\x8e\xe6\x1a\xd9\xec\x40\xc1\xc0\x6d\xd2\x9d\x79\x4c\x44\xa3\xea\x22\xc3\xd4\x76\x26\x22\xec\x1e\x8b\x33\x3e\x45\x07\x4d\xb9\x37\x41\xfd\xa1\x93\xc9\x11\xf6\xdb\x58\x79\xe5\x5e\xe3\x6e\xf6\x02\x61\x4a\xe6\x4a\x5c\xde\x9d\x83\x06\xd2\x2f\xbc\x4a\xe9\xc8\x81\xa5\x94\xbd\xe6\x79\x61\x25\xfc\xb6\x28\xb9\xf3\xb6\xfb\x3f\xfd\x51\x1b\x35\x3f\x14\x6a\x27\x27\x2a\xfd\x3e\x5d\x28\xb7\x7f\x58\xa6\x7f\x1f\xd2\x72\x85\xc2\x5e\xcc\x1c\xcf\x64\xe3\x8d\x21\xf3\xb9\xff\x22\xe0\x0e\xe9\x00\x62\x9e\xf1\xa6\x3e\x71\x3f\x25\x88\x83\xdd\x91\x1f\x30\xc0\xd3\x98\xb7\x4b\xd7\x97\x14\x9b\xe5\xe2\x69\x67\x22\xda\x09\xd5\x2d\x4e\xbf\x3c\x67\x39\x29\xd2\x98\xaa\xc3\x4c\xe0\x5b\xea\x08\xea\x9a\x42\x4e\x93\x45\x9c\x2e\xb8\xfc\x22\x22\xc3\x1c\xc1\x3d\x80\x3b\x90\xa8\xa7\x0b\xcd\x0a\x30\xc2\x09\x21\x1d\xc2\xcc\xc8\x5b\x0b\xcd\x45\x82\xc6\x95\xf5\x8d\x80\xbf\x6e\xc4\x71\xa2\x50\x5f\x68\x84\x7a\x75\xf6\xe9\x11\xfd\x87"}, -{{0x7e,0xd8,0x7c,0x36,0xdf,0xdb,0xae,0x60,0xc9,0x40,0xa3,0xb3,0x25,0xc1,0x9f,0xde,0xd8,0x14,0xd7,0x6a,0x54,0x48,0x20,0xa3,0x2f,0x28,0x6a,0x5c,0x0a,0xd7,0x1d,0x72,},{0x3c,0x4a,0xc5,0x10,0xb3,0x62,0x22,0xc2,0x52,0xa2,0xdc,0x1a,0xfc,0xb4,0x0f,0xb0,0xeb,0x85,0xbc,0xa9,0x03,0x91,0x19,0x6a,0x58,0x83,0xaa,0x2c,0xc9,0x12,0xb2,0xdf,},{0x57,0x9b,0x38,0x12,0x4b,0xd0,0x59,0x1a,0x59,0x7c,0xc9,0xa3,0x89,0x12,0x7c,0xea,0xf5,0x51,0x56,0x07,0x73,0x63,0xed,0xb8,0x11,0xd0,0xb6,0x55,0x52,0xac,0xfc,0xc6,0x77,0xb2,0x72,0x94,0x21,0x99,0xca,0x25,0xab,0x79,0x0d,0xe6,0xe0,0x84,0x60,0x3a,0xd1,0x05,0x2e,0xc2,0x10,0xcf,0x6f,0xcb,0x14,0x17,0x28,0x90,0x67,0xce,0x3c,0x08,},"\x62\xd3\x13\x91\x2a\xbb\xb0\x06\xb7\x77\x4a\x67\x37\x71\x4a\x34\x99\x70\xce\x04\x21\x11\x2f\x40\x04\x63\xd3\xdb\x0e\x2f\x7f\x12\x8d\x7b\x96\x93\x9f\x43\xc1\xe7\x10\x7b\x51\x18\xa7\x7c\x11\x96\x83\xd8\x66\xb7\xe3\xd7\x2a\xc2\x1f\x6b\x42\x72\xb4\xbe\x92\x89\xb6\x55\x6f\xe3\x1b\x60\x51\xa0\xb4\x2e\xd5\xea\x0c\xf3\x47\x69\x6d\x30\xfb\x8b\xff\x6b\x8b\x57\x27\x19\xde\x19\xa2\x31\xcc\x85\x45\x9a\x99\x0c\x37\x80\x1f\x08\x37\x18\x6c\xef\xbb\x55\x21\x56\x96\x66\x96\x7c\xd4\x24\x3d\x73\x07\xf1\xb0\xb2\x4c\x8e\x2b\x9b\x69\x23\x17\x30\x4f\xbe\x3d\xd0\xa2\x63\x65\x01\x91\xb3\x52\x16\xf5\x29\x16\x57\x3a\xf9\x05\x24\xf9\x1d\xb1\xa9\x24\x71\xd7\x58\xc9\x2d\xc6\xd1\x4d\x1a\x4b\x26\xf4\x1b\x40\x40\x3c\xa8\x7d\xcf\xab\xdc\xa4\x7b\x9f\xc2\x53\x35\x78\xf1\x61\xf3\xb0\x19\x9b\x5c\x69\x8e\x08\x07\x04\xb2\x1c\x9e\x61\x52\x69\xfc\xd0\xd4\x04\x39\xed\x8b\xc3\xbd\xfb\xc9\xaf\xb4\x4c\x11\xfa\x89\x27\x5f\x0e\xaa\xa5\xd0\x8f\xa9\x59\xd6\x37\x8d\x0d\xb8\x99\x10\xd4\x8f\x2d\x86\xa1\xeb\xfc\x5c\xbf\x10\xeb\x2d\x5a\xad\xf5\x1b\xbd\x83\x44\xff\x8b\xbb\x5b\x8a\xfe\x05\xa4\x50\x11\xb5\xe4\xb7\x2e\xb8\x64\xad\x26\x3e\x8a\x03\xa6\xc7\xf9\x8a\xee\xb3\x54\xf7\x30\xa3\x18\xaa\x30\xfb\x56\xd3\x3d\x80\x74\x8c\x98\xeb\xec\x15\x87\x8c\xcf\x3c\xe8\x22\xf6\x9d\x34\x56\x84\x3c\x40\x0d\xc5\x6b\x48\x1a\x95\xe6\x88\xb8\xa4\x73\x5b\xf3\x84\x3f\x58\x33\xdd\xa0\xef\xe0\x9e\x71\x75\xb5\x67\xc6\x61\x38\x7a\xfd\x2e\xbc\x07\x9a\x48\xe3\x49\x67\xec\x97\xb9\x27\xdf\xa5\x81\x88\x8f\x23\x1a\x98\xa7\xed\x33\x10\x3b\xfa\x8e\x8f\x9b\xa6\x51\x35\x27\x90\x0b\x39\xb8\x62\x31\xda\x79\x11\xa2\xfc\x93\x58\x88\xa7\x5f\x11\x29\x58\x4a\xff\xf2\x02\x52\x49\xc4\x18\x8f\x09\x05\x2f\x85\x68\x77\x06\xd0\x5e\x29\x91\x44\xd4\x0d\xe8\x89\x8b\x7c\x8b\x2d\xfe\xf0\xc3\x70\x85\x73\xd8\xb0\x56\x3a\x6b\xd0\xa5\x04\xc0\xb6\x74\x57\x02\xb1\xb5\x71\x21\xc6\xf0\x40\xaf\xf2\x71\x98\x94\x8b\xa6\x9c\x21\x25\x3a\x28\xd3\x9e\xba\x72\x62\x19\xbe\xda\x1f\x82\x09\xfb\x83\xe9\xad\xb0\x7a\xd4\x09\xfb\xd6\xd2\x55\x65\x88\x9a\xb4\x51\x23\xf9\xd9\x45\xec\xd7\xd9\xca\x70\x28\xec\xe0\x92\xe3\x5f\xbb\x7c\xb3\xf3\x28\x12\x6e\xfd\xda\xc5\xd8\x59\xf2\xb2\xc6\xeb\x09\x01\x33\x69\x0e\x20\xc1\x7d\xea\xf3\x88\x26\x85\xf0\x7e\x9e\xd2\x65\x3b\x80\x3b\x9b\x38\x3b\x70\x74\x8a\x1f\xa9\x2c\x86\xf8\x6d\x6c\x47\xea\x87\xb1\x0b\x12\xe3\x63\xba\x50\x80\x60\xf4\x7c\xe2\xa2\xf3\xb6\xa3\xee\xfc\xd4\xda\xcf\xc7\x1c\x41\xf4\x36\xfe\x0c\x2b\xc3\x4d\x4b\xaa\xd4\x95\x74\xe7\x44\x3c\x12\x6a\x58\x9f\x6e\xf7\xbc\xa4\x49\x54\xf0\xbb\x28\xec\x71\x51\xb0\x51\x1c\x23\xc6\xbc\x42\xd5\xe8\x59\x83\xec\x16\xbb\x5f\x50\xa3\x82\xd6\x88\x15\x0a\x49\x60\x9c\xbd\xe5\x69\x8e\x86\xdc\xbf\x02\x12\xc2\x29\x22\x99\xdc\x4d\xcf\x87\x42\x9f\x6c\xd2\xee\xc8\x09\x48\xce\x86\x7e\x25\xc9\x45\x84\xcd\xc6\x4b\x09\x90\x29\xeb\x85\x4e\xdc\x26\xea\x21\x42\x1e\xff\x48\xcf\x4e\x41\xf4\x9e\x2d\x89\x47\x8d\xef\x06\xc4\x2b\xea\x22\x0a\x13\x3e\x50\xf5\xc7\x44\x64\xc7\xe7\x3f\xb1\xc1\xa7\x7c\x50\x7c\xf6\xcd\xa8\x5b\xe4\x02\xb7\xe6\xd6\xd2\x1e\x81\x0d\x6d\x0b\x59\x72\xb9\xfe\x77\xe5\x4e\x74\xae\xe1\xf3\xbb\xfd\x6e\x7d\xe6\xb5\xc0"}, -{{0x6a,0x29,0xf8,0x1b,0x8d,0x9a,0xa4,0x8a,0x1b,0x23,0x36,0x4e,0xac,0x8f,0x6a,0x4b,0xdd,0x60,0x7a,0x84,0xcf,0xe8,0xe8,0x8d,0x90,0x17,0x5d,0x80,0x64,0x3a,0x58,0xa8,},{0x4c,0x3b,0xe3,0xa2,0xa8,0x42,0x5f,0xf3,0x1c,0x3a,0x0d,0xb4,0xa5,0x2a,0x0c,0xb1,0x41,0x6c,0xeb,0x48,0xcc,0x3e,0x4c,0x28,0xa4,0xf2,0x28,0x4a,0xb3,0x46,0x07,0x15,},{0xdf,0x09,0xcb,0x9b,0x87,0x8d,0x3d,0xc9,0xe5,0x42,0xdb,0xac,0x28,0x94,0x3e,0x28,0xe4,0x1d,0xce,0xcb,0x92,0xcb,0x7e,0xa4,0x40,0x09,0x88,0x5e,0x46,0x49,0x97,0x43,0x33,0x05,0x61,0xba,0x1d,0x36,0xae,0xdd,0x46,0x76,0x75,0xfd,0xca,0x2b,0xaa,0xa4,0x70,0x1b,0x6f,0xad,0x97,0x9f,0xd8,0x39,0xc4,0x70,0xd1,0x3c,0x82,0xda,0xa9,0x05,},"\x78\x76\xa3\xf4\xeb\x69\xbb\x7e\x54\xe9\xff\x95\x4e\xbd\x3b\x10\xb9\x3a\x4c\x1a\xfe\xae\x92\xfa\x03\xc1\x03\xcb\x63\x13\xa2\x01\xc5\xb3\x3a\x9a\x72\x23\x75\x5c\xb5\x10\xe2\x5e\xc5\x82\xb5\x4e\x81\xb8\x49\x56\xf6\xc5\x3f\x1f\x08\xa6\x3b\xf0\xc4\xa2\x61\xaf\x45\x0e\x52\x3f\xe8\xf6\x1d\xdb\x3c\x0e\xea\xb8\x75\x10\x72\x68\x88\x01\xb2\xa4\x73\xb7\x1a\x2e\x38\x70\x8d\xa6\x8c\x2f\x37\x92\x5c\xb0\x5a\x20\xc4\x28\x3b\x3a\xf9\x7b\x6f\x0b\xa6\x5a\x54\x03\x55\x43\x75\xe2\x15\xd9\xe3\xaa\x1b\x0f\x9f\xdb\x0f\x84\x99\x23\xed\xbd\xaa\x0a\xb4\x81\xc5\x45\xa5\xdf\x8f\x51\xd1\xf6\x8b\x22\x35\x07\xea\x0e\xcc\xfa\xeb\xb5\xfc\xcf\x5e\x3d\xfa\x65\xa4\x4e\xea\x50\x45\x68\xa8\x81\x80\xa0\x60\xbb\x06\xc5\x15\x57\xb8\x1e\x66\x7b\x4b\x04\xe3\x21\x0f\xa4\xc3\x79\x87\x6c\x49\xf3\xe5\x6b\xf2\xbe\x1c\xf5\x19\xa7\x41\x83\x93\xd2\x40\xdc\x8a\x22\x4c\x6c\x38\xac\x2a\xb9\xd8\xfa\xdf\xc5\x36\x20\x30\xc7\x93\x0c\x3c\xe7\x79\x5b\x14\x7c\x26\xc8\xa2\x8c\x65\x34\x29\xd9\x0a\x17\x3a\x86\xa8\xb1\x8a\x00\x9e\x62\xae\xf6\xec\xa9\x5d\x39\xbd\xbe\x45\x64\x77\x78\xa2\x53\x2a\x41\x5a\xe1\x9b\xad\x23\x11\x29\x12\x78\x42\xfe\x1d\x0f\x11\xfa\xb4\xa1\xcf\x0b\x17\xe4\x98\xcd\x59\x52\xc9\x39\xe0\x90\x09\x02\x87\xb1\x44\x89\x5d\xff\x00\xce\xc8\xd6\xae\xda\xf6\x24\x81\xa4\x17\x83\xe0\x21\x08\x2c\xe3\x52\x06\x3e\x62\x81\x1f\xd9\x99\x90\x10\x4d\x8a\x46\xcd\xca\xee\x2b\xab\x45\x8e\x52\x47\xfb\x02\x3e\x92\x33\x30\xa4\x28\xc7\xbc\xfd\x20\xb0\x8f\x52\x0e\x89\x46\xdd\x65\x83\x47\x35\x2a\xe0\xc4\xbe\x73\xc3\xd5\xec\xcd\x11\x14\x9f\x3a\xb7\xb8\x05\x2c\xfd\x95\xc3\x5d\x41\x64\x54\x6f\x5d\x8f\x37\x75\x17\xa7\xf4\x32\xc0\xd5\x56\x3a\x7b\xcc\x7b\xd1\x19\xd3\x42\x1d\xfe\xba\xae\x84\x45\x99\xb2\x9b\x38\x3b\xb8\xd5\xdb\xf1\x40\xd9\xbd\x47\xa0\x78\xb7\xae\x7c\x6a\xa8\x7b\x1e\x29\x23\x6c\x9f\xcf\xd6\x54\xb7\xf8\x09\x79\x4c\xcc\xb2\x61\x58\x8e\x18\xde\xc6\xc4\x04\x6a\x93\x40\x67\xd0\xdf\xa0\x37\x91\xd0\x3d\x83\xb7\x18\xac\x4d\x24\xdc\xe7\x85\xa3\x02\x8d\xe0\xc9\x59\x2d\xba\x7c\x5c\x58\x45\x18\x4a\xfc\x9c\x0d\xfc\xf9\x40\x95\x86\x0f\x0e\xb8\x02\xeb\xea\x20\x17\x8e\x78\xb5\x64\x2e\x5d\xd6\x1c\x33\xb3\x97\x69\x05\x2d\x9d\x85\x4d\xce\x90\x2f\x47\x6e\x21\xf9\x6c\x65\x0b\x46\x3b\x7b\xc3\xd0\xff\x29\x96\xb6\x5c\x57\x83\x1f\x8b\x7c\x0f\xb9\x15\xf4\xdd\x72\x26\xac\x95\x5c\xbc\x7d\xfb\x03\xf9\xb7\x58\xdd\x3e\x0d\xfc\xe2\xe0\xe5\x80\xc9\x1a\x30\xc7\x83\xff\x56\x7b\x17\xf1\x2d\xfd\x5d\x31\x37\x64\x6e\x20\x01\x1c\xdc\xaa\xe1\x11\x02\xdc\x71\x68\x86\xcb\xf1\x23\xc0\x94\x88\xb1\x73\x63\x6a\xbd\x54\xe9\x62\xca\xee\xc9\x7d\x5e\xb9\x40\x68\x2e\x70\x3b\x73\x0f\x61\x56\x2c\xd1\x4b\x9e\x65\x61\xb5\xe9\x3f\x60\xcd\x0e\x1e\x86\xd1\xa1\xb4\x71\x9c\x5b\x50\x82\x42\xbd\x6b\x2d\x9a\x54\x8f\x59\xbb\xb8\x75\x07\x59\x69\xef\x20\x32\xf3\x19\x6b\x8a\xec\xcc\x45\xa4\x4d\x9d\xbd\xaf\x87\x8e\xd1\x6f\x1d\x85\x5e\x89\x18\xed\x65\xa4\x5e\xe5\xc7\xfa\x32\xa1\xec\x69\x32\xa1\x59\xcf\xb5\x0f\xfc\x87\xbe\x06\xdf\xcf\x72\x28\xae\x88\x70\xcc\xd3\x57\xfc\x65\x6e\x33\xfa\x4b\x6b\x8b\x7d\x1a\x72\x15\x55\x3c\xab\xac\xc7\x0a\x39\xc9\x80\xb9\x71\xe5\x1a\x17\xed\x63\x18\xb4\x3b\x29\xbb"}, -{{0xef,0x12,0xdf,0x47,0x9d,0x98,0x3a,0xd9,0x6e,0x8b,0xa6,0x53,0x30,0xb3,0x6d,0x49,0xaa,0xdb,0x98,0x31,0x64,0xe1,0xc0,0xb4,0x52,0xb5,0x60,0xde,0xd1,0xd0,0x8d,0x60,},{0xf7,0x61,0xcf,0x28,0x26,0x92,0x7a,0x7c,0xda,0x8c,0xb0,0x4f,0xaa,0x2c,0x59,0xf8,0x42,0x5a,0x8f,0x7d,0x39,0x8f,0x76,0xe8,0x67,0x02,0x1c,0x95,0x1f,0x07,0x38,0x09,},{0x4c,0x80,0x10,0x86,0x6d,0x91,0x15,0xf0,0x52,0x93,0xb9,0x34,0xca,0xc6,0x81,0x04,0xcc,0x2c,0x34,0x37,0x56,0x8c,0xb9,0xd5,0xc5,0x70,0xb1,0xa8,0xbe,0xe7,0x06,0x60,0x30,0x75,0x53,0x70,0x33,0xbd,0x70,0x8a,0x9c,0x9f,0x3d,0x1e,0x25,0x19,0xa9,0x15,0xb1,0xc4,0xae,0x4c,0xcd,0xdf,0xcf,0x0e,0xd0,0xc0,0x49,0xd3,0x42,0xa0,0x2e,0x02,},"\xe5\x8f\x34\xda\xea\x75\x5a\xc4\xe4\x13\x33\xd6\xf0\xed\x01\x35\xf7\xdb\xce\x50\x30\x9b\xb1\x95\x6b\xc7\x1a\xcb\x12\xc7\x70\x67\xa6\x47\xff\xd8\x6a\xa5\x87\x0c\x0c\x00\x07\xe8\xf9\x95\xa2\x2b\x88\xc4\x67\xde\x22\x54\x44\x54\x42\x01\xc5\x57\x49\x5e\x25\x3e\x33\x19\xcc\x5c\xa3\x76\xd3\xe7\xcc\x1e\xb4\x67\x34\x6e\x52\xad\x95\x6a\x6f\xa7\x33\x72\x0b\x17\x11\x7b\x5b\x75\x85\xe4\xd5\x59\x40\x9a\xae\xfa\x95\x58\x0f\x91\xe5\x02\x01\x5f\x49\x7c\x5c\xdc\xb7\xd4\xd5\x61\xf5\x44\xef\xa3\x5c\x1e\x2a\x53\xb7\x2b\xdd\xec\xee\xc2\xd1\x05\x0f\x17\x7d\x48\x0f\x68\x74\x05\x66\x4d\xfd\xde\xc0\x6e\xee\x4b\xd1\x47\xa9\x12\xfd\xbf\x74\xf2\xa9\x5d\x1f\xd1\xe1\x12\x68\x69\x4c\xe4\xd4\xec\x4f\xff\xd6\xdd\xb3\x25\x4d\x36\x0f\x23\x6f\xab\x4d\x1a\x17\xf8\xd0\xd1\xa5\x11\xf9\x44\x69\x2f\x23\x96\x39\xae\x03\xd6\x4f\xac\xec\x65\x38\x42\x7a\xb7\x1f\x71\x27\xf4\xa2\x76\xf9\xbc\x45\xbb\xa6\x11\xdf\xcc\xe6\x44\x6c\xc1\x39\x68\x97\x6c\x8b\xb6\xd6\xfe\x21\x06\xd7\x05\x92\x2d\xca\xc9\x56\x96\x6a\x76\xd4\x8f\x2a\xff\x4b\x86\x51\x4e\x39\xa6\x7e\x16\x43\xfc\xc3\x21\x85\x80\x24\xe6\x93\x18\x98\x33\xc8\xad\x59\xb4\xb6\x25\x29\x8e\xba\xfe\x64\x62\x6b\x48\x0f\x32\x6f\x13\x40\x72\x3c\xb3\xd3\x83\xf4\xfc\xcb\xfc\x23\x7a\x3f\x4c\x4f\x7e\xcf\x0b\xa4\x36\xb3\x2c\x2f\xe3\x51\x79\xda\x93\x11\x1b\x48\xcc\x9e\xa2\x42\x02\xbd\xc1\xb2\xfb\x60\xa4\x31\x9d\xfd\x98\x64\x47\x0f\x73\xf5\x41\x37\x20\x6e\x0b\xf0\x07\xf5\xae\x88\xa8\x87\x47\x00\x8a\x60\xf4\x78\x9a\xd1\x67\x72\x4f\x17\x9c\x02\xb6\x3a\xed\x00\x25\x73\xd2\x8a\x6b\xcf\x88\xe0\x7c\xe8\xda\xea\x5d\x5f\x1a\xcf\x48\x7b\x4c\x5c\x16\xc2\xbf\xe1\x12\x31\xea\x5e\xa7\x63\xe8\xf3\x32\xcc\x73\xda\x1b\x2f\x8c\x19\x8e\xa8\x17\x3f\xd3\x3d\x4b\x2a\xe6\x9e\x5d\x4d\x1a\xad\xdd\xf2\xfd\x82\x1b\x85\xbe\x45\x15\x19\x62\xd1\xf9\x9d\xf8\x13\x08\x61\x88\x52\xad\x7c\xf4\x1d\x72\xda\x08\xa1\xb3\x9d\xf7\xd8\xb9\x94\xb4\xdd\xff\x37\xf9\xdf\xe8\xf3\x8c\xe3\x0e\x91\x06\x1d\x95\xd5\x8f\x7a\xe8\x26\xb0\x23\x85\x27\x2e\xc0\x9f\x01\xa7\xb3\xe4\xb3\x91\xd0\x9b\xce\xd6\x65\xda\xd6\x95\x05\xb4\x19\xda\x84\x81\xbc\x37\x92\xbf\x8b\x8e\x7a\xd6\x4b\x63\xf2\x45\x66\x6c\x8c\x32\xfd\x5c\x1b\x1b\x48\xc9\x95\x1e\x1c\x21\xa1\xeb\x5f\x50\x7c\xff\x13\x7c\xfb\x86\x2c\x2c\xc9\x87\x66\xe8\x78\xc9\x30\xa0\x83\x82\x8c\x9d\x8d\xb1\x8b\xf1\x67\x16\x68\x5f\x39\xd6\x57\x2a\x8c\xa8\xb2\xa5\x14\xf7\x70\x03\xd4\xe7\x5b\xc1\x54\xae\xbf\x14\x10\x37\x78\xf3\x65\xb1\xc3\xf0\x35\x41\xdd\xbd\x07\xd6\xe2\x3e\x56\x76\x2d\x97\x1e\xb0\x29\x83\xe9\x3c\x4e\x01\xba\x4b\x8a\x21\x78\x92\x8c\x43\x37\xd3\x02\xf3\x1c\x9c\xcb\x75\xb2\x49\xa8\x2d\xc9\x68\x21\xe9\x5a\x03\xab\x6b\x77\x0d\xf2\xc3\xdf\xdb\xf1\xfe\x97\x73\xf8\xbc\x1b\xc5\xb3\xaf\xa0\x44\x0b\x10\x25\x78\xf3\xd2\x13\xc8\xd0\x19\xcf\xf1\x24\xf7\x5c\xe4\xac\xcc\x8c\x66\x7f\xeb\x27\xc7\x51\xa6\x12\x00\x74\x81\x31\x04\xe0\xcd\x07\x0c\x9f\x5e\x45\x1d\xcc\xff\x4c\x80\xd7\x11\x07\xc9\x75\xab\xfa\xc0\x7d\x4d\x27\x0c\x72\x7d\x8a\x2f\xec\x34\x9b\x53\x39\x68\xe2\x71\x89\x2d\x2b\x62\xc1\x25\xfb\x79\x74\x60\x3c\x30\x5e\xa3\xbf\xa3\x0f\xb6\x10\xfc\x5a\x23\xeb\x68\xa8\x40\x64\x44\x39\x1a\x52\x13\x37"}, -{{0xf7,0x31,0x31,0x7c,0xf5,0xaf,0xfe,0x58,0x70,0x4c,0x4d,0x94,0x97,0xae,0x86,0x0b,0xbf,0x73,0x9d,0x0f,0xd9,0x6b,0x7c,0x02,0xef,0xb6,0x77,0x7b,0x3c,0x85,0x8a,0x19,},{0xd7,0xd6,0x38,0xae,0xcc,0xe1,0x46,0x1e,0x31,0x42,0x55,0xaa,0x29,0xd9,0xa6,0xb4,0x88,0xae,0xa1,0x39,0x6e,0x96,0x82,0x69,0x5a,0x47,0x0e,0xff,0x23,0xf3,0xed,0x84,},{0x2a,0x4f,0xea,0x98,0xf9,0x24,0x01,0x71,0xa1,0x82,0x3f,0x2f,0x69,0x35,0x20,0x62,0x67,0x2e,0x6c,0x6e,0x66,0x52,0xd3,0x88,0xa8,0x77,0x14,0xd6,0x47,0x99,0x5d,0xf7,0x5b,0x6e,0x1e,0xd1,0x74,0x6a,0xf2,0xad,0xf4,0xe8,0x06,0x13,0x5d,0x60,0x75,0x4e,0x60,0xfe,0xa0,0x32,0x12,0x8e,0x35,0xab,0xc1,0xf1,0x61,0x51,0x81,0x12,0x5f,0x0b,},"\x16\xf5\x1c\x59\xe9\xae\xfc\x26\xb0\xda\x5e\x00\x85\xeb\x2e\x2f\x1f\x85\x6d\xef\x97\x25\x76\x9e\x3a\xf1\x2f\x86\x09\x05\xae\x13\x3f\x65\x07\x4d\xa7\x6d\xbf\x25\xc6\x7f\x62\x57\xd2\xdc\x66\xc0\x5f\x9b\x31\xae\x17\x7b\x69\x92\x9f\xc1\x83\xb5\x88\xc5\x19\xbc\xa1\x47\x96\xa0\x89\x6d\x29\x05\xfd\x94\x2d\x7a\xb4\xa3\xfd\x95\x41\xa5\x52\x9f\x72\x9c\x58\x51\x41\x9b\x5f\xbe\xf7\xb1\x34\xd6\x76\x2e\xb9\x7e\x8a\x95\x1a\x8f\xf5\x2a\xa0\xd7\xe6\x74\x44\xd0\x6b\x07\xaa\x55\xe4\xeb\x9a\xb8\x92\xf4\x7b\xfd\x11\x1d\xf5\xb6\x2f\x6f\x3f\xd1\xa5\xed\x84\x12\x5f\xee\xbb\x77\xda\x63\x7c\x05\xd5\x26\x5c\xed\x11\x3d\xfe\x87\x82\xdb\xd1\xce\xcd\x2c\x6c\x03\x2b\x8f\xa8\x85\x5b\x3a\xe7\x8d\xe7\x4f\xaa\x5a\xa2\x0a\x76\x14\x63\xc2\xa3\x0b\xe6\x6b\xd3\x8c\xde\xc7\x5f\x89\x57\xcb\x94\xc1\x13\xa4\x5d\x54\x6d\xaf\x47\x5d\x89\xaa\x14\x82\xf8\xd2\x80\x3a\x23\xc9\x39\x20\x20\x15\xa0\x8e\x94\xb1\x32\x72\x8f\xbe\x8f\x60\x19\xd7\x16\x8a\x08\xa5\x93\x01\x70\xe5\x63\x9d\x11\x0e\x47\x39\xdb\x85\xe6\x1e\x64\x49\x59\x44\xb5\x42\x3a\x74\xad\x5a\x8a\x0a\x51\x06\x12\xec\xe6\x55\xce\x18\x86\x40\x51\x52\x5b\x90\x8e\x0b\x19\x29\x0a\xbe\x8b\x11\x82\xc4\x8c\x70\x0d\x35\x05\x15\xfd\x34\x99\x56\xe8\x08\x73\x27\xf3\x0b\x6f\xc3\xf1\x31\xc2\x14\x4a\xbb\x3f\x0e\x9c\xa3\x31\x17\x2b\x35\x06\x4a\x82\x81\x1a\x68\xe2\xcf\x36\xb4\x3e\x3a\xd2\xe8\xdf\xa5\xb1\xce\xf5\x0e\x2a\x60\x29\x3f\xc5\xf6\x35\xc9\xa9\x99\x8d\x8c\x1a\xd2\x96\xe7\xc7\x8f\xc0\x58\x20\x22\xd6\x30\x67\x18\x6b\x65\xe7\x64\x82\x8c\xc0\xf5\xf7\x63\x2d\x5e\xef\x86\x3e\x6c\x6d\x90\xe3\x8c\xcc\x87\xd7\xb7\x47\xfa\xc8\x49\x1d\x63\x2c\xf7\xf5\x4b\x9a\x9e\xed\x16\xee\xbe\xc0\x1b\x6c\xc3\x3d\x24\x63\xf7\xf9\x50\xd8\x28\xb5\x5e\xe3\xf7\x7c\xbe\x97\x4f\x48\x94\x8e\xb7\x57\xae\xd4\xe0\xdb\xb0\x0a\xd9\x5e\xe0\x13\x23\x48\x6e\xba\x3c\x8d\xa8\x86\xed\x7f\x57\xbb\x40\x0d\x63\xa1\xb2\xeb\xea\xa2\xe7\x0a\xdf\x03\x79\xe3\x39\x30\x01\xba\x62\x6c\x0d\xd5\x4b\x7f\x0c\x9a\x25\xaa\xe6\xc9\x87\x5d\x4e\x76\x22\xf3\xed\x42\x8f\xb3\x12\x4b\x29\xc5\xdb\x9a\x7e\xf1\x6e\xbd\xdd\x68\x05\xf0\x95\xf5\xe7\x69\x82\x3c\x43\xf2\x62\x86\x8f\xf4\x3e\x3e\x05\x25\x74\x6d\x94\x97\xaf\x12\x4a\x01\xdf\xf6\x1e\xc7\x18\xaf\x3b\x5b\xb7\x46\xfc\xc0\x8a\xeb\xd1\x66\x84\xd4\x56\xae\x79\x32\xff\x5e\xd7\xd6\xb0\xf1\xb2\x5c\x7a\xde\xef\x59\x8b\x5d\x58\x87\x75\x90\xac\x1d\xc0\x59\x75\x15\x67\x96\x99\x87\x74\x08\x1e\x5b\x66\x82\x2a\x94\xa6\xa8\x02\xc3\xa2\xcd\x9f\x48\x9e\x16\x28\xaa\xf4\x65\x2b\xe1\x18\x4b\x0f\xc7\xc5\xee\x7f\x97\xce\x08\xb9\x23\x3b\x4b\x83\xd9\x36\x7b\xe5\xf4\xaa\xe9\x78\x25\x93\xa3\x52\x65\x15\x4d\xea\x4c\x37\x5c\x16\xf0\xca\xf6\xdc\x45\x94\xd2\xbd\xbf\xc3\x37\x5b\xb2\xa0\x43\x2c\x48\x2f\x13\x94\x1c\xe2\xaa\xab\x4d\x83\xe7\x4d\x11\x6f\x5d\xe4\xab\x28\xf8\xdc\x3d\x1c\xd1\x9d\x27\x1e\x56\xe1\x03\x98\xbd\x1d\xf5\xc8\x70\xfc\xbf\x93\xa7\xd1\xdf\x39\x39\x54\x7c\x10\x7b\xfd\x90\x64\x3f\x6f\x50\x01\xae\x7e\x06\x39\x7a\xe1\xa2\x71\xbb\x82\xa1\xf3\x8e\x09\x7b\xec\x66\x74\x66\xb8\x0e\xe3\xe5\x0d\xd4\xfc\x9d\x5d\x54\xf1\x8f\xaf\x7a\x5b\x55\xa8\x83\x45\x94\xef\x0c\xb7\xe5\x08\xbb\xd2\x8f\x71\xfd\x34\x23\x5b\xbf\xd3"}, -{{0x49,0x8e,0x5a,0x21,0xa9,0xb0,0xc3,0x47,0xba,0x83,0xa4,0x7a,0xc1,0x00,0x69,0x45,0x7f,0x57,0x83,0xc2,0xe1,0xe6,0xe4,0x64,0x00,0x45,0xe5,0x94,0xb1,0xc6,0x93,0x32,},{0xfb,0x39,0x48,0xc8,0x11,0x99,0x56,0x91,0x05,0xcc,0x1b,0x7d,0x9c,0xeb,0x3b,0x41,0xa3,0x43,0xbb,0x00,0x57,0x55,0x38,0x59,0x2e,0x09,0x84,0xf4,0xf4,0x71,0x0a,0xbe,},{0x28,0x60,0x83,0x0c,0xcd,0x1d,0x41,0xd9,0x50,0x76,0x81,0x6a,0x39,0x84,0x24,0xf7,0xb7,0x39,0xc4,0x9f,0xda,0xcf,0x56,0x54,0x52,0x9d,0xa8,0x5f,0xe3,0x56,0x55,0x84,0xf6,0xaa,0xc2,0x61,0x4c,0x63,0xf7,0x74,0xb6,0x1d,0xb9,0x08,0x1f,0x14,0x10,0xfb,0xa8,0xe5,0x0a,0xb3,0xb4,0xc3,0x9d,0xc0,0x63,0x14,0x24,0x3f,0x3f,0x0d,0x8e,0x0f,},"\xe4\xfb\xea\x86\x4a\xa5\x11\x90\x82\x66\x45\xd2\xf7\x72\xcb\x0f\x9e\xdd\xd3\x03\x44\x73\xfa\x31\x77\xc7\xaf\x9a\x5d\x41\xe1\xa7\x3a\xd5\x78\x4c\x70\x96\x55\x9f\xcd\xdb\x7b\x7c\x85\x89\x1c\xf2\x4e\x82\xc5\x88\xd7\x47\x74\xff\xca\xc0\xc6\xb4\xee\xbc\x2f\x3f\xa4\x3e\x9d\x45\xf2\x59\xd6\x75\x64\x03\x0c\xfe\xea\xb9\x23\x6c\x66\x5b\x65\x0a\xf0\xc9\x2c\x87\x51\x89\xf5\xf9\x38\x35\x04\xb1\x53\x60\xa0\xb9\xa5\xa0\x0d\xa3\x1f\x63\x5b\x96\xf6\xc7\x3e\xf4\x7b\x6b\x06\xf0\x28\x11\xd1\xd1\x9c\x2e\x8e\x53\x55\x0c\xe2\x2e\x42\xec\x50\xa1\xeb\x2e\xa2\xf4\xcd\x03\xc4\x42\xd4\xaa\x43\x68\x94\x23\x8c\xeb\x18\x35\xfe\x99\xb2\x40\x35\x8a\xa0\x56\x2c\x24\x96\x98\xa3\xf1\x23\xc2\xc1\x7e\x59\x10\x10\xbd\x6f\xdf\xcb\xd7\xdb\xe7\x0b\x04\x52\x05\x02\xec\xe3\x7a\x9a\x1d\xfa\x1a\xe3\x37\x04\x17\xb0\x04\x21\x7a\x5b\x8f\xe9\x90\x3c\x9a\x3b\x9f\x4b\x6d\x5c\x46\xc0\xed\x0c\x53\x8c\xec\x22\xf2\xdf\xcb\x2a\x28\x0a\x42\xad\xc4\x89\xcf\x2e\x06\x29\x12\xbe\x99\x28\xf0\xc0\x60\x89\x1e\x43\x20\x91\x17\x75\x26\xf1\xb3\xa9\x68\x06\x9d\x4a\x57\xad\xe8\x28\x55\x98\x10\xae\x03\x60\x68\x1f\xf9\x93\x29\xfa\x0f\x59\xe7\xe5\x9c\xdf\x87\xf9\xf3\x3c\x40\xe9\x70\x31\xb9\xf8\x1d\x48\xfc\x12\x28\x6e\xfb\xb3\xd4\xe5\xa6\x2e\xf5\x7b\xc0\xd5\x2d\x53\x3b\x99\xc5\x10\x6a\xa7\x9c\xfe\x17\x93\xa9\x08\x51\x85\x96\xc3\x83\x48\x3e\xc4\x9f\xf9\x8e\xc5\x57\xbf\xff\x74\x90\xa4\x6d\xaf\x67\x14\xf2\xc2\xc3\x2f\x57\x93\x2c\xa0\xd7\x30\xf0\x3f\x38\x1d\x69\xde\xcd\xbd\x9a\x7a\x6d\x4a\xfc\x62\x40\x65\x43\xc8\xeb\xe9\x0a\xc7\x6e\x6a\xfa\xbd\xb8\x24\x92\xa2\x06\xa3\x69\xe0\x42\x86\xd3\x13\xe1\x11\x07\xd8\xcd\x9b\x4b\xf6\x8f\x81\x5d\xba\x4e\x99\x0b\x04\x9d\x79\x21\x6d\x36\x53\x13\x83\x42\xcd\x11\x8b\x13\x0f\x66\xb0\x06\xf3\xd8\x9a\xc3\xcf\x89\x83\x70\x48\xb0\xf8\xa6\x2d\x94\x05\x1d\x2e\xab\x89\x1a\xc5\xf4\x78\x88\x87\x9d\x88\xe5\x46\x67\x6d\x1d\xae\xeb\x4d\x17\x5d\x3f\x04\xa9\xd7\x4f\xfc\xdd\x47\x74\x60\x16\xf8\x4a\xd0\xd1\x12\xaf\xb5\x9a\xd1\x21\x87\xe9\x4f\x22\x53\x5d\x77\xe9\xe0\x51\x6f\xa4\x21\x85\xc1\x97\xba\x77\x4b\x39\x32\x27\xf7\x41\xfe\x68\x27\x3f\x42\x3f\xb0\xe0\xe0\x47\x4b\xfd\xaf\x2d\xa7\x8a\xeb\x1c\xd5\xb9\x8c\x1d\xc0\x83\x21\x24\x74\x2a\x47\x54\x12\x5f\xc7\x8b\x19\xc5\x59\xa5\xb3\xf7\x71\x1e\x06\x8c\x44\x0c\xc0\x46\x9a\x1c\xfa\x5c\x18\x64\xbe\x18\x73\x5a\xa8\xbc\xd4\x06\xc4\x37\x1e\xb8\x57\x75\x4d\x90\x8b\xf3\x79\xb9\x1f\xcb\x24\xe3\x43\x96\xbf\x87\xc1\x9a\x04\xa8\x3d\x59\xda\xe7\x1f\x3f\x38\x39\x82\x9d\x06\x22\x13\x01\xef\x59\x56\x96\xe7\x19\xd5\x6b\x79\x52\x0a\x0e\x50\x99\x29\x83\x3b\x1d\x80\x4a\x6a\x0e\xa4\x04\x00\xbb\x45\x02\x8c\xe5\xd3\x69\x33\x88\x3e\x17\x40\x6e\x27\xa8\x10\x90\x57\xb1\xa1\xa5\xe5\xda\x21\x0a\x69\x21\x99\x4f\x46\x7a\xb4\x1a\xa8\xf0\xd8\x87\x75\xa8\xa8\xeb\xb4\xec\x77\xd7\xc8\x0e\x45\xa7\xbb\x42\x2a\x4c\x00\xc9\x05\x83\x91\x14\x65\xe6\xb5\xf0\xfd\xcd\xea\xb7\x28\x71\xca\x54\x2e\x1d\x1a\x2c\xa9\x4d\xf4\xed\x2e\xab\xf9\x0d\xed\x00\x45\x29\x03\x24\xa9\xff\xfb\x30\x14\x54\x70\x20\x9f\x38\x26\x58\x09\x89\x34\x91\x99\xdc\x5a\xb8\xd4\xa2\x5d\xf7\xa0\x52\x9c\xf9\x14\x71\xe3\x08\x42\xab\xfa\xcd\x44\xab\x78\x1d\xfc\x13\x95"}, -{{0xc2,0x4c,0xbf,0x40,0x1a,0xd0,0x3b,0xd8,0x8d,0xcc,0x7b,0x51,0x9e,0xcf,0x62,0x4d,0xb2,0x22,0x3e,0x99,0x02,0x89,0x30,0x9e,0x1e,0x9f,0x1f,0x8f,0x61,0x27,0xc6,0xc9,},{0xa7,0x46,0x66,0xf3,0x57,0x20,0x9f,0x71,0x89,0x90,0x37,0x88,0xf1,0x07,0x56,0x3e,0x50,0xc0,0x51,0xc3,0xd4,0x0c,0x3f,0x3d,0xad,0x10,0xd3,0xc3,0xcf,0xf1,0xe6,0x78,},{0x58,0x1e,0x6c,0x85,0xae,0xc6,0x23,0xb6,0x2b,0x3d,0x4c,0x9b,0xc9,0xc7,0x77,0x59,0xd5,0x49,0x27,0x22,0xe2,0x52,0xd4,0x4c,0x1f,0x8a,0xda,0x9d,0xa2,0xec,0xc6,0x7c,0x17,0x08,0x32,0x73,0xaa,0x09,0x1b,0xba,0xc0,0x46,0xae,0x63,0xc7,0x88,0x93,0x15,0x2e,0x14,0xd9,0x26,0xc4,0x1a,0xe3,0x5f,0x0e,0x6e,0x39,0x59,0x49,0x6b,0x13,0x06,},"\xe7\xfa\x35\x9e\x6a\x09\xb2\xc5\x4a\xab\xed\x3b\xba\xbf\xb7\x28\x53\xa8\x05\xaa\xbc\xf4\xd1\x8d\xda\xd3\x9f\x03\xf3\x46\x01\xe5\x5b\x6c\xe2\x63\xc9\xa3\xca\x6a\x3e\x5f\x14\x25\xc8\x21\x92\x8c\x61\xe7\xf7\x50\x91\x9b\xd3\xaf\x32\xbc\xb7\xb9\x4d\x45\x9a\x7a\x9a\x35\xf6\x1c\x94\x17\x92\xe2\xcc\x2e\x43\x27\xbe\xb3\x44\xa8\x41\xa0\x7f\x32\x06\x8a\xf1\x02\xb3\xde\x61\xea\xb6\x4e\xf6\xd5\xe6\x90\x62\xe3\x93\xab\x5e\xdf\x6a\xc9\xef\x7b\x38\xd4\x9a\x01\xbe\xf0\x00\x3f\x42\x11\x74\xc8\x88\x59\x75\xc0\x18\x32\x89\x9c\x31\x35\xe7\xa8\x6e\x5b\x55\xd9\xb1\x32\x8b\xb4\x28\x9b\x5c\x40\x20\x0f\x49\xe5\x52\x3b\x3c\x46\x1d\xc7\x17\x5e\x14\x65\x02\x22\x97\xc3\xd3\x80\xf2\xb1\xfe\xf3\x9c\xb8\x2c\x00\xfd\x16\x0f\x44\x7e\xb5\x12\x63\xfa\x25\xb4\xdf\x0f\xca\x41\xec\x0c\xa2\xec\xe7\x47\x22\x01\xaf\x86\xc3\x03\x8c\x49\xdf\x09\x9a\x9a\xef\xa1\xf8\x8d\x0e\xdf\xd1\x7c\x0b\x3c\x86\x04\x66\x29\xc0\x94\x54\x05\x4a\xa0\xfb\x2c\x69\x49\xdd\x9c\x13\x01\x85\xdf\xa5\xd9\x03\x89\x1e\x08\x74\x2c\xd0\x42\x94\x03\xf5\x7f\x40\x52\x15\x8b\x2f\x40\x1d\xa4\x75\x68\x54\xe4\xaa\xf0\x24\x22\x1e\x37\x51\x3c\xf6\x77\xee\x6a\x0b\x15\x9f\x50\x1d\x37\x7e\xa3\x2e\xb7\x1e\x77\x80\x04\xf2\x72\x03\xcd\x6d\x55\x3f\xda\x5d\x65\xe1\x87\x94\x77\x04\x6f\x3e\xa3\xd1\xd7\x5c\x9d\x0d\x30\x31\x14\x56\x70\x9c\xc7\xf6\xab\x68\xc7\xb0\xd5\x2b\xe4\x0f\x04\xcf\x65\x56\x55\x32\x32\x85\x31\x83\x29\xe8\x4c\x6a\x5b\x07\xe0\xce\xed\x5f\x78\xf7\xf1\xfa\x62\x29\xbe\xf8\x78\x79\x3c\x58\x47\x28\xab\xf4\x51\x0b\x7f\x27\x79\x4b\x59\x42\x91\x62\x54\xc5\x89\xa0\x9c\x8e\x91\x1f\x0b\x95\x42\x11\xa6\x36\x99\xa7\x52\x14\x7f\x2a\x4e\x1a\x18\x95\x66\x44\xbe\xa2\xca\x26\x92\xba\x18\x22\x80\xe0\x4a\x72\xdd\x89\xb0\xd1\x26\x85\x00\x93\x8f\x34\x7b\xf4\x3f\x2a\x24\x2e\xe9\xb9\xa6\xba\xac\x9b\x35\x0d\x65\x6f\xb1\x9e\xc8\x34\xab\xe3\x16\x44\x40\xf2\xd2\x07\x1f\xe5\xe3\x2c\x8e\x4c\xf9\x05\x53\x9b\x83\x9c\xee\xca\x26\x20\xfc\xb2\xa0\x87\xf7\x80\xe6\xc7\xf5\xe0\x5c\x50\x68\x88\x25\x0e\xa7\xc8\x56\xfb\x30\x98\x32\x00\xaa\x8f\x78\xfc\x17\x71\x05\x4a\xda\x0f\x3f\xac\x38\xae\x2f\x33\xdc\x4a\x4f\x85\x1b\x76\xed\x74\x0c\x09\x62\xa7\x6a\x4d\xe4\x40\x80\xdc\x62\x0a\x44\xad\x8f\x23\xd3\x46\x2b\x79\x2a\xb3\xaf\xb1\x9c\xb8\xa9\xf4\xd9\xe5\x9a\xd7\x65\xa7\x71\x89\x9d\xa8\xcb\xec\x89\xe5\x07\x7e\x85\xc0\xc9\x31\x26\x37\x6c\x94\x1b\xef\x1f\x8b\xb9\x92\xd3\xa3\x5f\x27\x07\x25\x84\x6f\xb2\x52\xf8\xb5\xfb\xb7\x56\x7e\x40\x6a\x1b\x53\xb6\x19\x76\x9e\x63\x2b\x2b\x40\x87\xcd\x4c\x27\x6e\x5d\x58\xff\x2b\x56\xe8\x9e\xde\xc4\x8c\xe5\x3a\x52\xe3\x29\xca\x15\x59\x53\x8f\x10\x90\x2c\x01\xa8\x5f\xbb\x3c\xd7\x2e\x6b\x82\x91\xe5\xfe\x63\x9b\xee\x9d\x47\xd3\x4c\x24\x9a\x7a\x07\xd7\xa1\x42\x7a\x01\xf6\x3d\x60\x98\x4c\x45\x0b\xef\x81\x9b\x19\xf6\x5e\x26\x14\xfd\x9c\x2f\xae\x7b\x92\x31\xa0\xbc\xa4\x14\xed\x94\xa5\xee\x7e\x66\x32\x7d\x2a\x99\xc8\x48\x78\xb7\xbe\xe0\x87\xe8\x91\xf2\x53\xfa\x1f\xec\xe3\x13\x64\x8c\x06\xc4\x5d\xb2\xd9\xf3\xbc\x85\x99\x93\x7b\x75\x2d\x38\xce\x50\x63\xd0\xed\x9a\x43\xec\x9d\x40\x15\x89\x3d\x43\xbf\x5b\x2d\x1c\x60\x47\x85\x10\x46\x89\x68\xb7\x96\xf0\x15\x37\x89\x59\x54\x41\x72\x2a"}, -{{0x8b,0x3d,0xcd,0xe4,0xab,0xbf,0x4e,0x62,0x11,0xc4,0xa5,0x1c,0x4b,0x02,0x68,0x00,0xa8,0xa2,0xa0,0x61,0xcb,0x38,0xa2,0xec,0xc7,0xc9,0xcf,0x11,0x3f,0x92,0x70,0xbf,},{0x51,0x45,0x35,0x58,0x0f,0x0d,0xe3,0x59,0xbb,0x0d,0x41,0xf2,0xef,0xdd,0xaa,0x04,0xc2,0xec,0x95,0x01,0x19,0xf3,0x16,0x34,0xb2,0xc1,0xa3,0x2f,0x19,0x5f,0x69,0x68,},{0x4f,0x3d,0x4d,0x22,0x85,0x03,0x01,0x7e,0x74,0xa6,0xbb,0x58,0xaa,0xfa,0xe3,0x5c,0x3f,0x37,0xbd,0xee,0x4f,0xf6,0xbe,0x2e,0x62,0x40,0xb5,0x08,0x2f,0xed,0xdb,0x22,0x27,0x35,0xe1,0x2f,0x31,0xe0,0x56,0xfa,0x68,0x54,0x47,0xe5,0x38,0x48,0x03,0x00,0x7e,0xa7,0x91,0x0e,0x60,0x5c,0x1b,0x78,0x11,0x8c,0xd5,0xac,0xc5,0x87,0xa6,0x06,},"\x48\x14\x25\x02\x7d\xa6\x72\xb6\xf2\x6c\x91\xb8\x0e\x55\x58\x2c\xae\xf4\x7b\xb1\x5a\x2d\xe8\xfc\xa8\x52\x22\x17\x85\x18\x0b\x20\xa7\xfd\x6d\x49\x07\xb5\x88\x1c\xc1\xd6\xe3\x9a\xb9\x61\x2c\xc7\x4d\x69\x77\xe9\x14\x1f\x70\x87\xbb\x27\xab\x30\x84\xa2\x62\x85\x58\x6f\x84\x11\xdb\x1f\x50\x3a\xdf\x52\xdc\xb2\x5a\xb8\xff\xfd\x2e\xc1\x50\x4c\x17\x77\xb9\xd6\xdd\x4a\x29\xe2\x01\x9e\x5c\xba\xe1\xb7\xeb\x26\xf9\x5b\xbe\x07\xd9\x0c\x2f\x6f\xb0\x88\x4a\x59\xa8\xd5\x8d\xde\x51\x16\xed\xc3\xbc\x34\x9d\x37\xc1\x60\xb2\x7b\xef\xbe\x5a\x5c\x18\x1c\xe7\x25\x63\x92\x35\x4d\x22\x1b\x58\xc4\x7e\xb0\xbb\x10\x92\x9e\x74\x21\x79\x5f\x4b\x7a\x7c\x27\x5e\xdd\x08\xc0\x88\x56\x87\x72\xe9\x93\x21\x8d\xd6\xf3\xc2\xcb\x4a\xc6\x57\xa0\xa3\xf9\x1f\x31\x26\xb9\x91\xad\xf6\xcb\xe7\xd1\xb1\x9b\x8c\xd8\x3b\xe3\x60\x2e\xd1\x8f\x03\x96\x33\xfb\xd2\x38\x7b\xda\x69\xe2\xcf\x03\x87\xd8\x64\x4d\x97\xb3\x03\xfb\x00\x63\x9a\xee\xe7\xae\x46\x3f\x6f\xe1\xa2\xc4\xb8\x9a\xeb\xa3\xe9\x09\x4c\x11\xfc\x29\x11\x4b\x20\x28\x3f\x28\x7c\x6d\xd2\x8c\xb0\x98\xda\xe8\xda\xbc\x48\xe8\x5b\xb5\x9c\x0d\xc6\xe7\x8c\x95\x66\x05\xcb\x7c\xf0\x69\x42\x35\x3e\x7a\x22\xe9\x6f\x80\xa3\x7a\x66\xf7\x18\xd9\xe4\xdb\x8c\x52\x45\x2a\xa0\xa3\x57\x72\xe8\x1b\xa2\xb3\x03\x20\x5b\x41\x2d\xd2\xbf\xc1\x5c\xe9\xb4\x36\xf9\x9f\xbb\x32\x12\x6b\x63\xce\x9c\xb4\x31\x99\xf1\x57\xd8\x17\x51\xa7\xc4\x93\x7d\x13\xaf\x4c\x58\x29\x52\xb5\xd6\x06\xb5\x55\xb0\x46\xbf\x1d\xe0\x6c\xf3\x9b\x63\xa8\x02\x87\x37\x18\x03\x60\x9a\x38\x7e\xe8\x0f\x3a\x5d\x88\xb9\xd6\x21\x96\x50\xed\x17\xd3\xcc\x18\x3b\x2c\x70\xd5\xeb\x94\xe3\xbc\x52\xae\xa7\xaa\x7f\x53\xbe\x0e\x20\xb8\x97\x2f\x14\x3d\x8e\x20\x16\x2e\x80\x3e\xdb\x4a\xa8\x3d\x55\x53\xfd\xd5\x53\x39\x8b\x0f\xa1\x76\xb9\x59\xcb\xa1\x40\xd6\xe9\x80\xc9\x25\x1b\x0f\xa0\xb6\x5e\x90\x84\x17\xf8\x2f\x45\x1f\xf9\xf2\xde\x6b\x9c\xa5\xe3\xb5\xf4\x1b\xa4\x0d\x05\xa5\x4f\x3d\xab\x48\x86\xaa\xcc\xa0\x5c\x9c\x27\x98\x13\x9a\x4c\xb3\x3e\x96\xa9\x14\x94\x74\x99\x10\xa1\x7c\xe8\xb3\x92\xfc\x0f\xc7\x76\x29\x74\xd7\x9d\x33\xdb\x92\x4b\xfe\xf8\x65\x5a\x72\x37\x76\xff\x87\xf9\x50\xfd\xc5\x68\xb1\xe5\x26\x53\x45\x41\xf5\x72\x72\x3b\x84\x06\x63\xc1\x91\x88\xc4\x24\xf7\xc4\x89\x23\x5a\x42\x4b\x09\xfe\x25\xc3\x07\x27\xea\x1c\xb0\x49\x53\xd7\x06\xd6\x8b\xfe\x12\x10\x0e\xf6\xf6\x4c\x35\xc6\xb8\xde\x67\xed\xf0\xe3\xad\x01\x4a\x40\x0e\x82\x1e\xa3\x40\x24\x32\x19\x99\x86\x7b\x43\xc8\x2c\x45\x01\x84\xb7\x8f\x74\x25\xce\xbd\x73\x19\xdc\x6f\x65\xd3\x60\x66\x5d\xfb\xe7\xc3\x66\x74\xda\xc3\xa5\x4e\x96\xda\x91\x0c\x02\xd3\x64\x07\x80\xb2\x2d\x51\x2c\xa0\xe3\xca\x35\x87\xb9\x4e\xa9\xfc\xd7\xa3\x1b\x4a\xf6\x9f\xd6\x20\x7c\x68\xfe\xd2\x5f\x89\x92\x1c\x1c\xdc\xde\xfd\x1c\x09\x02\x04\x49\x2b\xff\x9b\xbb\x52\xe0\x88\x85\x82\x9d\x01\x2b\xc2\xdf\xb4\xfe\x8c\x35\xe5\x9c\xd1\x3b\xcb\x8e\xad\x34\x19\x3c\x40\xb0\x3e\xe4\xd8\x25\xee\x13\x22\xff\x4e\xf0\x71\x27\x95\x74\xcb\xae\xe7\xc0\x7f\x14\xbe\x60\x6b\x9c\xd0\xe2\x61\x11\x1e\xf2\x0d\x96\x81\xd7\x6c\xf7\x8c\x89\xa8\xc3\x97\xd6\xb8\xdc\x77\x8f\x49\x84\x16\x6a\xd5\xdf\x3a\x81\xaa\xf2\xe6\xde\x09\xf7\x00\x19\x5a\xe2\xc1\xd4\x60\x96\x47"}, -{{0xd4,0xa7,0xa9,0x52,0x4d,0x30,0xa6,0x33,0x7c,0x0a,0x0b,0xe9,0x5c,0xa9,0x05,0x91,0xde,0x98,0x88,0x03,0x8e,0x3e,0x59,0xe1,0xb2,0x5a,0x41,0x81,0xef,0x94,0x66,0x29,},{0x9f,0xc3,0xeb,0xd1,0x39,0xcc,0x5b,0x7c,0x0e,0x05,0xaf,0x47,0xbf,0xf6,0x61,0x9b,0x81,0x28,0x15,0xbb,0x01,0xce,0xec,0x39,0x2a,0x3f,0xf0,0xae,0xc3,0x81,0x1d,0x2c,},{0xd1,0x57,0x88,0xbc,0xd8,0x8d,0x1d,0x81,0xb9,0xe6,0x1d,0x4f,0xe2,0x6e,0xa4,0x9e,0x66,0x81,0x9a,0x59,0xd2,0xae,0x48,0x32,0x32,0x1b,0x81,0x4d,0x50,0x62,0xfa,0xdb,0x87,0x80,0x7d,0xb6,0x85,0x2e,0x1d,0x82,0x95,0xe3,0x1a,0x29,0x1b,0x1e,0x78,0x5d,0x01,0xd8,0x34,0x89,0x5f,0x88,0xf4,0x00,0xdf,0x88,0x32,0xc1,0x60,0x7b,0x5b,0x0c,},"\x17\x19\x80\xc0\x3f\xdf\x7a\x72\x7b\xd5\xba\xb3\xba\x09\x45\xe6\xad\x5f\xaf\x0a\x7f\x50\x6a\x56\xd1\xd0\xed\xd9\xa3\x06\xb3\x15\x8d\x84\x32\x66\xd3\x09\x1f\xc1\xe4\x22\x81\xdf\x97\x55\x9a\x22\x01\xf5\xbd\xdd\xfe\x68\x3d\x0e\x10\x28\xd1\xd9\x5b\x2f\x31\x3b\x48\x4c\x39\x2f\xfd\xb1\xcd\xf8\x85\x08\xaf\xde\x3d\x6f\xd2\xa1\x28\x88\xba\xce\xde\xb7\x9f\xf3\xdb\x40\xc9\xac\x0e\xc3\xfb\x90\x1b\x22\x86\x98\xad\xf8\xd8\x45\xff\x4f\xce\x10\xde\x55\xd4\x24\x36\xdc\xe9\x30\x97\x3a\x34\xbe\x05\xd1\x40\x1f\x33\x4d\x4c\xe8\xe3\xa7\x93\x79\x9e\xaf\xdb\x94\xd0\xf2\xab\x09\x50\xb0\x79\xe6\x65\x3e\xeb\x49\x9f\xc7\x44\x7c\xcb\xee\xed\x8d\xbd\x54\x56\x80\x8c\xd7\xa3\x8f\x9a\x15\xa2\xa9\xc7\x38\xd6\x13\x34\xca\xb8\xce\xeb\xbb\xf4\xa4\x81\x4d\x94\xc6\x18\x59\x17\x87\x84\x60\x4e\x0c\x21\x54\x59\x7e\x72\xcf\x58\x7c\xd1\xf5\xda\xfe\x59\x22\x05\x18\x90\xe7\x6d\x61\x6d\x8c\xd5\xb0\x5d\x64\x78\xd0\x62\x6e\xa8\x3c\xe8\x08\xc4\x61\x43\xe6\xfb\x06\xb4\x18\x2d\x22\x8d\xa8\xf6\xd4\x13\x9e\xca\x5b\x8f\x3b\x1b\x98\xaf\x68\xc5\x9b\x4b\x5a\x53\xc1\x36\xee\x90\x43\x2a\xca\x2b\xb9\x15\x52\x9d\x26\x36\x79\x49\x82\x62\x33\xb4\x3e\x55\x80\x4b\x55\xfc\x9f\x21\x5e\xb0\xb0\xb7\x92\x91\x46\x5b\xb3\x4e\xda\xea\xdf\xfa\xbf\xe6\xcf\x41\xbc\x07\xb5\xdd\x4d\x01\x42\xf0\x36\x1f\x05\x8e\xe1\xb3\xb9\xfc\xc1\x96\xeb\x9b\x35\xb1\x34\xbe\x3d\x1d\x23\x20\x04\x48\x9e\x8f\x69\x93\xf6\x25\xa6\x30\x15\xbc\xd3\xf1\xe8\x75\x88\x32\x48\x58\xcc\xfb\x77\x0d\xdd\xd8\x94\xbf\x29\x7b\xd7\x63\xef\x58\x28\xe2\x1f\x5c\x89\xaa\x98\xcf\xbc\x1c\x08\x2d\xd7\xfb\xaa\x43\x07\xbd\xa4\x0b\x4a\x75\x8c\xa8\xf3\x9f\x4e\x4a\xae\xd3\x09\x04\x12\x68\xdb\xcf\x0a\xf3\x2d\xe0\xd7\xfa\x90\xa5\x23\x96\x3b\x78\x0b\x6a\x93\x2c\xf8\x94\x99\x02\x5f\x0e\x0d\x04\x74\xc7\x43\x48\x94\x75\x10\xe6\xc5\xec\x7c\x9e\x05\x06\x6e\xeb\x4a\x73\x52\x0c\x3d\x92\x7c\x39\xac\x26\xad\x75\x96\x32\x5b\x2c\xc4\x7c\x5e\x82\xa7\x75\x45\x5b\x7a\xf0\x31\x20\xb1\xcf\xbf\xd6\xec\x3f\xc0\xc3\xbe\x60\x78\xb0\x0c\xfd\xf8\x34\x2a\xe8\xbf\x14\x71\x59\xf5\x0e\x9d\x56\x4e\x2f\x68\x30\x6d\xae\x3c\xae\xdd\x10\x19\xf3\x23\xc4\x78\xa1\xe1\xf6\x75\x98\xdd\x83\x4b\xd1\xd1\xa8\x73\x3f\xd7\xfd\xd8\xa8\x76\x52\x6c\x53\x15\x18\x93\x6e\xdb\x72\xd0\x16\x56\xb3\x44\xc7\xd6\x5a\xc1\xce\xe3\x7c\xe5\x99\x7b\xa4\x8d\x3f\x4d\x06\x4d\x88\x05\x7e\xfe\x9a\x48\x2d\x9e\x00\xab\x5c\xae\xb5\xac\xa2\xd6\x60\xe3\x37\xbd\x15\x48\x73\x65\x69\x79\x56\xa5\xe4\x7b\x02\xab\xdc\x30\xd8\xe3\x53\xfe\xd4\xe1\xac\x41\xd2\xbc\x21\x20\x02\x11\x43\x63\x59\x35\xc6\x20\x18\x6a\x52\x2b\xde\x54\xbe\x04\x46\xfb\xd2\xdc\x88\xb5\x63\x04\xb3\xa6\x42\x27\xd0\xac\xd5\xf8\x5a\x6b\x67\x87\xa3\xad\xcf\x2d\x7c\xfc\x86\xc6\x34\xb4\xd7\xab\x43\x15\xb9\x7d\xe9\xe6\x66\xcf\xf3\xff\x1b\x88\xf3\x29\x5e\x7b\xab\x9e\x9f\xd4\x6f\xaf\xdd\xb4\xf5\xfa\xc5\x1c\xc0\x17\x01\x29\xc6\x51\xb4\xef\x4d\x39\x50\xd6\x94\x2f\xf0\x20\xd1\x66\x8a\x52\x8b\xde\x1d\xa9\x36\xc0\xec\x1a\xe0\x9e\x84\xf8\x20\x58\x61\xff\xf4\x91\x50\x2a\x87\x2c\x81\x54\xa9\x6e\x7e\xa2\x5e\xda\x95\x5a\x7f\xd2\xe4\xb4\xc7\xa8\xd2\x73\xf6\x0b\xc7\x4f\xab\x7b\x49\x68\xca\x6f\x75\xda\xea\x50\x40\xf8\x39\xfd\x56\xc2\xa9\x80"}, -{{0xd0,0x8f,0x4b,0xab,0xba,0x3b,0x53,0x65,0xfa,0xf7,0x38,0x79,0x5c,0x9d,0xa4,0x5d,0xb1,0x86,0x2c,0xb2,0x8b,0x93,0xeb,0x66,0x35,0xd1,0x32,0x0d,0xa0,0xf4,0xd9,0x37,},{0xef,0x31,0xb4,0x54,0xf7,0x34,0xe5,0x2b,0x34,0x38,0xee,0x2f,0x1c,0xbc,0x35,0x63,0x1b,0x19,0x69,0xde,0x54,0xac,0x98,0xfe,0x46,0x33,0xf2,0xf5,0x00,0xac,0x87,0x12,},{0xac,0xeb,0xe4,0xc8,0x6f,0xa9,0xfe,0x2c,0x1a,0x5c,0x57,0x6a,0xc0,0x50,0x1e,0x8a,0xb0,0xf6,0x40,0xfa,0x40,0x38,0x05,0x36,0xfc,0xf9,0x50,0x59,0xd5,0x3d,0x4a,0x35,0x55,0xd2,0x20,0xac,0x36,0x35,0x87,0x17,0x5e,0x4b,0xde,0x16,0x3c,0x0d,0x00,0x65,0x0a,0x12,0x96,0x3d,0x46,0x76,0x6c,0x99,0xbb,0x62,0xbf,0x75,0x73,0xe2,0x87,0x0c,},"\xa3\x94\xd8\x85\x4c\xeb\x5c\x43\xaf\xee\x1a\x48\x92\x6b\xbd\x66\x85\xaa\x8a\xec\xfd\xcf\x85\x41\x33\x33\x39\x74\xd6\x24\xbf\x2f\x1f\x9c\x30\xf0\x05\xbb\xf3\x4c\xee\x3a\xfe\x2b\x29\x06\x00\xee\xae\x6f\x1d\xd1\x2a\x0c\x34\x6f\xbb\x2a\xb9\xc9\x16\xc5\xd5\xd8\x0d\xcd\x87\x88\x78\x75\xa0\xac\x84\x76\x78\x03\x9f\xdc\xd3\xa9\x79\x35\x41\xf5\xd6\x75\x14\x3a\x6a\xba\xdc\x3b\x18\xf0\xfe\xf5\x10\x8c\x19\xc2\xdb\xfb\x59\x71\x0e\xef\x98\x66\xa4\xf3\xf2\x97\xa0\x9e\xe4\x8c\x68\x03\x00\x7d\xd6\xba\x8f\xd4\xbe\x84\x1c\xfb\x10\xff\x05\x14\xc3\x0f\xc4\xdd\x49\xa3\xcd\x43\xbb\xd1\x6e\x46\x04\x43\xa1\x1a\xfe\x64\x9e\x90\x1d\x63\xd8\x9a\xf5\x98\xaa\x68\x6b\x2f\x60\x7e\xc1\x1f\x35\xe1\x7a\x79\x8a\x42\x13\xb7\x5a\x38\x78\x8d\xa4\xf2\x7c\xf2\xb0\x2c\xad\xdf\xe6\x1c\x37\x29\xa8\x7e\xc6\xe6\xb0\x98\xf6\x8e\x7a\xed\x28\xa8\x00\xc4\x84\xdf\xa0\x13\x04\x01\x20\x8f\x98\x6d\x79\x2f\x54\x63\x5a\xdd\x28\x48\xe1\x51\x26\x2a\x36\x5e\xb2\x1e\x27\x27\x19\x1e\x1f\x70\x0f\x3b\xf5\xc7\x3b\x0f\xb4\xc5\x46\xd0\x04\x8a\x15\x5c\x18\x71\x79\x20\xfc\x04\x25\xc8\xc8\xfa\x8f\x16\x7c\x43\xa2\x77\xbb\x36\x6e\x0a\xd7\x02\xc8\x9b\xc5\xaa\x06\xfd\x47\x09\x43\xbe\x05\xcb\x9e\x32\x59\x78\x72\x29\x71\x4c\x30\xa4\xe8\x7b\x00\xa6\x33\xaa\xf7\xbe\x6b\x58\x75\x01\x0d\x12\xe1\x07\xc9\xa5\x26\x1c\xa5\x62\xd6\x70\x25\xbe\xa0\xfe\x22\x34\x63\xed\xb9\x2e\xa0\x1c\xca\x92\xc4\x4f\xf2\x4d\xa9\xd8\xa8\x0a\x64\x21\xf3\xd4\x13\x5d\x64\x7d\x1b\xb0\xfd\x98\x8c\x46\xc8\xa1\x70\xce\xb4\xf3\x3f\xff\x9c\x0f\xfb\x6a\xba\xd1\x09\x2c\x84\xdf\xad\x82\x90\x89\x8b\x24\x95\x16\xa2\x92\xe8\xda\x96\xfd\x51\xa8\x10\x05\xee\xcf\xde\xbb\x05\x93\x30\x99\x27\x7d\x07\x3a\x48\x0c\x3f\x9e\xb8\xaa\x11\x96\x8c\x4d\x8d\xc0\x78\x7a\x9a\xec\x3e\x05\x27\xb7\xfe\x4c\x06\x35\x41\x13\x35\xa1\x81\x16\x89\xe8\x8f\x6d\x5c\xed\x0d\x40\xd6\xb4\x8b\x7f\x2d\x99\x29\x52\x93\x48\x94\x15\x30\x76\xa8\xd3\x73\x72\xfa\x00\xd9\xce\xfc\x5c\xf8\xc2\x6a\xdb\x5a\xcf\x32\x5a\x01\xcd\x00\x5a\xb8\xd4\x74\xa5\x2d\x67\x11\x40\x78\xc6\x51\x6a\xef\x80\x4b\xba\x19\xb8\x87\xa2\x8e\xd5\xe4\x6e\xe9\x99\x5e\x5a\xd3\xa8\x2f\xb9\xcd\x93\x28\x34\x33\x68\x09\x21\x11\x4b\x4d\x9a\xf8\xfc\xb6\xb2\xb5\x35\x83\x9c\x36\xde\x8d\xf1\x2b\x17\xea\x6d\xdc\xfc\xb3\x33\x4f\xf4\x0e\x6c\xf0\x4c\xcd\x5c\xa6\x40\x3b\xa0\xb6\x2b\x4c\xb7\x1b\xbd\xe9\x1d\x8b\xab\xda\x69\x15\x2c\x9c\x93\xae\x76\x9b\x55\x29\xc8\xd5\x2f\xd9\xa6\x90\x9a\x15\xe1\xa0\x60\x1a\x71\x46\x49\xc9\x6e\xc9\x96\xc1\x70\x6d\x10\x21\xb9\x74\x87\x98\x0d\x7b\x2c\x2a\x39\xbb\xb0\xe4\x70\xd8\xe4\x6a\xc4\xaa\x60\x9a\x09\x22\xc9\xbd\xc0\x16\x12\xea\xde\xac\xcd\x5f\xa5\x23\xb2\xa8\xd0\xe6\x2f\xfe\x56\x28\x16\x47\xd6\x1f\xff\xbb\xc8\x40\x53\x57\x45\xd1\x44\x25\x9c\xc8\x13\x00\xfe\x99\xdf\xbf\xfe\xa6\xb0\xb9\xbc\xd2\x84\x73\x98\x2d\x32\xe9\x3e\xd4\x66\x34\xa9\x98\x79\x06\xd6\xf4\x89\x39\xd8\xdf\xbf\xb3\x7d\x33\xb8\x88\xdb\x60\x8c\xb2\xff\xe3\x9a\x8c\xf6\x7b\x72\x64\x46\x11\xc7\xd3\x2a\x4a\x8d\xf6\x12\x46\x8c\xd5\xe5\xd7\x5f\xbb\xa7\x9e\x63\x8a\xa1\xda\xa2\x8c\x4e\x0e\xeb\x9a\x63\x7f\xf8\xa0\x8b\x65\xf7\xa7\x61\x24\x14\xdf\x76\xbc\x7b\x0b\x56\xb5\x53\x7d\x66\x6f\xac\xfd\xda\xf6\x5a\xf1"}, -{{0x8f,0x47,0x4f,0x88,0xcf,0x86,0x3c,0x48,0x54,0x56,0xa5,0xa2,0x15,0x52,0x81,0xff,0x27,0xb2,0x84,0x59,0xf6,0x3b,0xc4,0xf1,0xdb,0x00,0xe0,0x03,0x10,0x64,0xf6,0x49,},{0x43,0x14,0x4a,0x32,0x9d,0x75,0x1d,0x04,0xe0,0x71,0x69,0xb7,0x79,0xee,0x92,0x0d,0xd0,0x29,0xcb,0x44,0x5b,0xf3,0x76,0xba,0x3a,0x66,0x85,0x72,0x18,0x23,0x44,0xa3,},{0xf6,0x1f,0x78,0x07,0xc3,0x3e,0x19,0x6d,0x0f,0xe1,0x82,0xef,0xa4,0xd4,0x51,0x6a,0x98,0x15,0xdd,0xd4,0x49,0x53,0x8b,0xba,0xa6,0xb8,0x6b,0x69,0x01,0xa0,0x5f,0x5d,0xdd,0xa0,0x60,0x1e,0xc9,0x0f,0x39,0xf1,0x55,0x47,0x79,0xdb,0x7a,0x09,0xa6,0x05,0x72,0xef,0xfd,0x4d,0x12,0x8d,0x0d,0x3c,0x2d,0xd4,0xe8,0x83,0x57,0x4b,0xc6,0x0b,},"\x84\x08\x91\xd9\x48\xec\x19\xc8\xc7\xf7\xc9\xd3\xc4\x77\x53\x62\xa5\x44\xa0\xec\x97\x45\x7a\xb5\xd1\x4e\x12\x5d\xc5\x4b\x59\xc8\xdc\x9a\x63\x5e\x7b\xad\xb6\xbe\x73\xc3\xa5\x8d\xc0\xe9\x92\x9f\x2b\x42\x0d\x83\x56\xd6\x17\xc3\xd4\x1b\xfe\x69\xb4\xe1\x58\xd4\xbf\x08\xfb\x17\xe6\x88\xd3\xcf\x3c\x94\x8b\x69\xb3\x5f\x0b\x6d\xb6\x62\x72\xa8\xeb\x2b\xd4\x10\xd6\x50\x9f\x6c\x82\x8b\x6a\x20\xd6\x58\x6e\xaf\x85\x76\x01\xed\x9d\x60\x54\x79\x9c\x25\x32\x0e\xba\x80\x77\xfe\x1a\xe2\x26\x71\xb3\x3a\x15\x88\xff\x2b\x23\x5d\x3c\x71\xa2\x7c\xe5\xc6\xc6\x6e\x18\x88\x91\x98\xd1\x16\x93\x36\x76\xbc\x4f\xb0\x71\x0d\xb7\xff\x1a\xc2\xf2\x0c\xe3\x69\xbe\xf5\x6b\x43\xcd\x1d\x40\x6c\xef\xda\xcf\x00\xf1\xf3\x48\xb8\xca\x7a\xa6\x14\xdb\x11\xa3\xa6\x40\xfd\xb5\x93\x89\xd1\xa6\xa3\x94\x75\x5c\x13\x3f\x1b\x01\x9c\x83\x08\xca\x5a\x95\x1e\x73\xb8\x10\xa1\x80\xf6\xff\x25\xb2\x9d\xbb\xcc\xef\x4c\x13\xa9\x75\x03\x39\x39\x07\xa2\xdb\xa0\x96\xa8\xce\x5c\x86\xc0\xee\x6f\x97\xc1\x44\x1b\x8d\x63\x31\xcb\xa5\x3b\x19\x60\x6b\x42\x1a\xf5\x2f\x65\xf9\xc6\x63\xe6\x3d\x39\x82\x71\x8f\x94\x8c\x6b\xae\x96\x1b\x8e\x4b\xf8\xcd\x9e\x31\xcd\x09\x92\x8e\x4e\x80\x61\x65\x97\xcc\xfa\xdc\xb8\xa6\x14\x15\x49\x33\xbc\x37\x58\x9c\x85\xc7\x76\xe3\x4e\x5a\x90\x66\x0f\x59\xa6\x5b\x5e\x93\xad\x43\x88\x42\xf9\x82\xd0\x2b\x04\x1e\x6d\xbd\xdf\x17\x10\x99\xf8\xdb\x70\x99\x57\x31\xa0\xdb\x8c\x46\x25\xc9\xbc\xa7\x10\x80\x59\x61\xfb\x17\x6d\xae\x81\x97\x68\xfc\xad\x7f\xf9\xbf\xce\x36\x40\x3c\xa7\xf7\x83\xe7\x61\x37\x26\xd7\xdc\x59\xf2\x4e\x24\x7c\xf1\x50\x68\xff\x3b\x19\xc7\x25\xfa\xd6\x5e\xa8\xe8\xa7\xf7\x22\xd5\x28\xc9\x5f\xce\xf1\xc0\xcc\x79\xd1\x8e\xf0\x7c\xee\x8b\x01\x1e\xea\xbd\x99\x21\x63\x4d\x76\xa6\x1a\x8a\x3c\x89\x31\xb8\x27\xe8\x18\x98\x81\xf8\x1f\x7a\x17\x5f\x21\xfb\x03\x78\xb8\x18\x8e\x58\xbd\xb2\x01\x7b\xef\x39\x0f\x18\x00\xd9\xd7\x4f\x26\x3a\x81\xdf\x8e\x67\x52\x2d\x09\x2e\x77\x5d\x01\xe0\x04\xe7\xf8\xd8\x28\x1a\xe2\xc2\xfd\xf8\xc3\xa4\x45\xf9\xef\xf7\xfd\xf1\x3f\x26\x1a\x77\x3d\xdf\x2d\xd9\xcc\x6b\xa5\x58\x5d\x99\x0c\x99\x5e\x6e\xb8\x9d\xff\xd9\xff\x0a\x9d\xbb\x76\xce\x5e\x10\xdd\x02\x72\xd5\x00\x14\x97\x88\x13\x66\xf5\xd6\x36\xa9\xcc\xea\xa2\x83\x22\x8d\x3a\xc6\x14\xdb\x21\x7a\xb8\x91\xd6\x68\x9d\xbe\xb9\x50\xe1\x20\x0c\x3d\xe5\x3b\xc5\xda\x07\xf1\xd3\x63\xda\xe9\xbe\x6e\xc3\x6e\xda\x6e\x68\x7d\x26\x29\x0f\x7a\xbc\xa2\x68\xa7\xfa\x03\xd9\x31\x88\x64\xed\xa9\xa1\x1e\x3b\x26\x14\x06\x05\x92\x0a\xc1\x3a\xde\xc1\xb5\x54\x8c\x9a\x7a\x32\x15\xa5\x87\x6b\x7e\x94\x1a\xfa\x1c\xb5\xd7\xf7\xf0\xc1\x16\x30\xcd\x42\x9f\x3b\x2b\x37\xdc\x76\xc6\xcb\xea\x4f\x3b\x72\x6a\xa8\xa5\xf8\xb9\xf7\x05\xb0\x5d\x7e\x94\x51\x95\x6f\x8a\xf1\x3c\xe0\xa8\x59\x55\xc7\x13\x5d\x64\xad\xe5\x49\x6e\xa5\x42\xe7\x0f\x8d\xa5\xb5\x73\xaa\xf1\x37\x08\x5d\xc9\x6c\x69\x27\x09\x96\x95\x67\x26\x68\xb3\xc7\xc6\xf9\x3c\x97\x7a\x4e\x8e\x9e\x77\x02\x95\xf2\x0d\x52\xdf\xf1\x87\xf8\xdb\xb2\x5e\xe7\xe7\x74\x02\x4e\xb9\xbe\x08\x12\x1e\xd7\x4b\x6d\x54\x62\xf4\xbb\x7d\xc2\x00\x38\x74\xca\xa3\x1b\xb7\x59\x5c\xd9\x3a\x99\xeb\xe1\xef\xf9\x28\xbb\x5f\xcb\x9e\x9c\x89\xdd\x31\xd4\x87\xfc\x0e\x20\xbb\xe1\x50"}, -{{0xe4,0x2b,0x30,0xd4,0x9c,0x43,0xc4,0xfa,0xd8,0x3d,0xd5,0x1f,0xdc,0x2a,0x4a,0xc5,0x90,0x13,0x27,0xad,0xd8,0x00,0xb6,0x69,0x72,0xc8,0xc7,0x0b,0xde,0x18,0x0a,0xdc,},{0xf7,0x34,0xaa,0xfa,0xa4,0xdb,0xaf,0x31,0x5c,0x25,0x8c,0xca,0x8b,0xbc,0x1d,0x4f,0x34,0xe8,0x36,0x01,0x10,0x98,0x74,0x22,0x2a,0xa0,0x55,0x89,0xf3,0xa6,0x63,0x5f,},{0xff,0x8e,0x07,0x6e,0x34,0x3c,0x8b,0x73,0xaa,0x45,0x3b,0xfe,0xe9,0xb2,0xba,0xb6,0xd5,0xc2,0xf7,0x4c,0x35,0xe1,0xba,0xd1,0xe5,0x2a,0xe7,0x77,0xd6,0x9f,0x79,0x76,0x40,0x83,0xf9,0x94,0x36,0x8a,0x1a,0xc8,0x51,0xa6,0x41,0xcd,0x24,0x70,0x08,0xa3,0x4f,0x3b,0x60,0x89,0x62,0xf4,0xdd,0x51,0x09,0xac,0x71,0xcc,0xe9,0x78,0xec,0x02,},"\x0d\x49\x70\x51\x86\x1e\x22\xd8\xa9\xc6\x0e\x5f\x7d\xe6\xc8\x95\xcb\xa3\x35\xb2\xe8\x2e\x60\x21\x18\xad\x83\x42\xb4\xd4\xed\xaa\x80\xf9\x5e\xfb\xb5\x9c\xfd\xa1\xfc\xc0\x29\x17\x25\x70\x0e\x8a\x81\xbb\x12\xa0\xb8\x62\x3b\x1f\xe2\x89\x1b\x8d\x98\xf7\xa8\x4c\x59\xfd\x92\xf8\xa7\xad\xfc\x06\x50\x42\xf7\xf4\xfd\x7e\x1a\x79\xf5\x5a\x1d\x4d\x5e\x54\xe0\x4e\x67\x2f\x1c\x9e\x4c\x4c\xd8\xd0\x00\x3f\x3c\xd5\x4b\x76\xe2\x16\x3d\xd7\x37\xac\xb2\xde\x5c\x26\x3a\xc1\x02\xa4\x8f\x69\x6b\x60\xca\xf9\xbe\x39\xc6\x65\xcc\xe1\xe0\xf3\xd4\x98\x55\x3f\x57\x90\x61\x88\x9a\x5e\xc5\x60\x3e\x4d\x14\x1c\xfd\xed\xe8\xe7\x31\x75\x72\xcf\xe7\x6a\x0f\x48\xe4\xae\x06\x06\x2c\x91\x57\xb5\xea\xac\x34\x68\x93\x81\x92\xdb\x4b\x16\x10\x5c\x73\x64\xa9\x44\x32\xb2\x15\xa7\x17\x97\xfe\xe1\x4c\x3c\x9c\xe2\xf7\x46\xed\x79\x03\x02\xfc\x41\xdc\x49\x2d\x37\xd9\xef\x02\x4a\xb5\x1d\xa3\xbd\xaf\x0f\x81\xd9\xa9\x30\xaa\x0e\x02\x5c\x04\xfd\x71\x02\x6b\x6a\xfe\xb7\xed\x01\xa9\x1a\x1e\xfd\x6c\x39\xf5\xe4\x47\xc6\x6d\xd3\x8a\x76\x56\xc6\x13\xd0\x21\x26\xf3\x58\x5d\xfa\xa0\x2d\xf9\x30\x25\x3f\x83\xbd\x42\x19\x64\x63\xeb\xc5\x0f\x8c\xfc\x94\x9e\xd3\x50\x39\x2e\x61\xce\xec\x13\x09\xda\x15\xa4\x32\xf8\x0d\xfe\x94\x8e\x26\x1c\xe6\xd8\x42\x1c\x54\x59\xcd\x21\xf3\xff\xa2\xed\xb5\x00\x98\x2b\x2a\xbf\xa5\x2e\x82\x43\x7c\xa2\x30\xf6\x09\x11\x63\x20\xd9\x89\x3e\xb8\x2a\x14\xdf\x72\xb7\x73\x66\x67\x51\x6f\xc0\x12\xb2\x8a\x03\xc9\xdd\x88\xea\x43\x08\xd8\xce\xea\x44\xcc\x60\x44\x54\xcd\xfa\x2c\x79\x76\x15\xbc\x0a\x6b\x3e\x00\x89\xaf\x0a\x81\xbe\x54\xd1\xb1\x10\xa1\x3a\xb9\x11\xb4\x52\xc3\x42\x80\x0c\xee\x2a\xd2\x39\xa2\xb1\x88\xa7\xfa\x87\x5e\x94\x1d\xaa\xeb\xcf\xc8\x8b\x70\xae\x4b\x1c\x57\x5c\xdb\x6e\x6d\x89\x44\x81\x36\xf6\x0e\xe8\x1c\x70\x3c\x47\x82\x2d\x2c\x0e\x50\xc7\xf1\xe8\xb7\xfc\x7e\xbd\x80\x78\x9f\xcd\x7e\x06\xc7\xe5\x0b\x5f\xc8\xb7\x76\xe8\xb9\xa4\xcd\x59\x05\xa2\x90\x69\xbc\x3a\x55\x8d\x7c\xab\xce\x2a\xf4\xf3\x10\x76\x7d\x5b\x11\x7e\x30\x76\xb3\xa0\xd5\x27\x17\x55\x43\xb2\xcc\xea\x28\xd5\xf7\x16\xfa\xc3\x2e\xfe\xd3\xd2\xe0\x27\x6b\xe4\x4a\x89\x56\xfc\x82\x40\xf2\xdb\x33\x97\x61\x4f\x2f\x2d\xa0\x21\x66\x69\x4e\xc6\xa7\xfe\xec\x6e\xce\x39\xd7\x2b\x64\xbb\xc6\xb4\x76\xa4\xf8\x4f\x8d\x87\x93\x80\xa3\x84\x88\xe4\xd6\xe5\x8c\xac\x03\x90\xae\x25\xa5\xfc\xb7\x3d\x47\x41\x4b\x4c\x26\xbb\xb9\xb4\xcc\x66\xe4\x25\x94\xbd\x56\xd8\x41\xa3\x60\x92\x34\x91\xd1\x17\xbe\x2c\x6e\xb2\x32\x0f\x3c\x61\x75\xe4\x4e\x27\xb6\x65\x3c\x5d\xac\x6f\xae\x73\x60\x0b\x67\x96\x0d\xca\x50\xaa\x85\x5a\x89\xe0\xff\x51\x1e\xa0\x4f\x14\x3e\x89\xf1\xda\x02\x84\x76\xbe\x4b\xf6\xd9\x4c\x80\xff\x72\x63\x39\xe8\xbc\xfb\x7d\xd9\xf8\xcf\x20\x22\x59\xc0\xac\xb6\x27\x6c\x28\x1e\x38\x47\xc2\xcc\x8d\x2f\xba\x84\x43\x8d\x2d\x3c\x60\x31\xf2\xa7\xb9\x5c\x1d\x8f\x9f\x3c\xc8\x6a\x5e\xff\x65\xcc\x01\x1d\xe9\x5a\xd8\x96\x85\x8e\x1f\x7f\x6d\x6b\x94\xbf\x49\xdf\xff\x5d\xe2\xd7\xfd\x71\xef\x10\x81\x34\x28\x5f\x61\xae\x47\x54\x83\x44\x2d\xc9\x0b\xf0\x13\xfa\xed\xf3\x77\x1c\x47\xc5\xb9\x6d\xc3\xcf\x8e\x48\x51\x00\x60\xad\x8d\x45\xfd\x54\x61\x62\x27\x80\xd8\x69\xd4\x61\x7b\x57\xfe\x3c\xb5\xcc\x02\x03\x15\x3a\xae"}, -{{0x5c,0xb5,0x14,0x21,0x74,0x82,0xbf,0x42,0xf6,0x11,0xfc,0xec,0x36,0xa5,0x28,0x68,0x07,0xc2,0xbd,0xbb,0x56,0x96,0x76,0x91,0x35,0x3f,0x54,0x31,0x0e,0x1a,0xd5,0x53,},{0x28,0x06,0x99,0x00,0x3d,0x5d,0x3e,0x1c,0x05,0xad,0x10,0xfb,0x10,0x95,0x9b,0xbc,0x59,0x5c,0xfe,0x21,0x30,0x69,0x96,0x5c,0xd8,0xcf,0x39,0xdd,0x42,0x6a,0x05,0x68,},{0xd5,0x3e,0xe2,0xe0,0xf0,0xfd,0x65,0x7b,0x20,0x52,0x47,0x8f,0xd1,0x5d,0xf1,0xd3,0x8f,0xe0,0xe9,0x3a,0x54,0x83,0xeb,0x4a,0x6e,0x7d,0xe9,0x3d,0x02,0xa4,0xcd,0x54,0x4d,0x8f,0xdd,0xdc,0xea,0x82,0x2b,0x71,0x57,0x6e,0xd0,0x28,0x53,0xd9,0xa6,0xb1,0x4e,0x1a,0x54,0x8a,0xef,0xe9,0x0d,0x92,0xf8,0x83,0x79,0x2b,0x7f,0x1d,0x86,0x09,},"\x2f\x57\x25\x8c\xca\x79\x32\xe5\x8b\xed\x54\x6c\xb0\x04\x11\x15\xbb\xad\x23\xd1\x83\x46\xef\x7a\xb5\xe3\x11\x00\x82\xb3\xa9\x71\x2f\x6c\xbe\x12\x70\xe6\xdc\x0c\xea\x33\x64\xa0\x6a\x5f\x2f\x28\x3e\xc3\x9b\x63\x05\x8d\x34\xd5\x99\x79\x07\x2f\xcb\xbd\x7a\x5d\x0f\x44\x2b\xbd\xf0\x82\xd5\xbf\xe2\x99\x8a\xeb\x51\xbd\x26\x12\x78\x03\xe5\xc7\x96\xc3\x88\x43\x20\x0a\xe2\xf6\xe6\x05\xaf\x31\x2f\x54\xfd\xff\x17\xed\x1d\xfa\xa8\x9d\x28\xfa\x67\xdc\xe4\x62\xde\x4f\xe2\x52\x68\x21\x2b\x28\x2e\x22\x2a\x44\x3e\x2f\x31\xe2\x69\x05\x41\x71\xaa\x73\xc7\x19\xa8\x96\xcd\xb7\xa5\x39\xdf\xd1\xd4\x29\x91\x97\x81\x97\xd7\xc4\xf2\xd3\x0a\x64\x1b\xe3\x4b\xf1\x38\x0a\x4f\x4d\xc6\xd9\xb1\x01\x63\x66\x36\xa4\x96\xbe\xb3\x57\xe3\x47\xc1\x66\x65\x16\xdf\x8e\xb5\x60\xa0\xe0\xd1\xe1\x52\x9c\xe3\x6a\x60\xe0\x0e\xd2\x78\xda\x38\x02\xbe\x19\x23\x42\x98\x9b\xb6\x11\xb4\xe3\xcb\xd9\xc3\x7e\x8c\xce\x07\xef\xc1\x2d\x29\xbe\xfd\x7e\x2f\x3a\xdb\x13\xd2\x8f\x70\x8d\x97\xb6\x3e\x10\x74\x82\xc8\x62\x95\x6d\x7c\xe8\xdf\xc2\xaf\x5c\xac\x8d\x51\x65\x92\x67\xb0\xbb\xed\xdd\x5e\xfa\x41\x4d\xde\xab\xd1\x7b\x23\xca\x6e\x84\x3f\xf4\x9e\xff\xc8\x2a\x5d\x07\xe3\x6a\x83\xb6\x7c\x2a\xd7\xe4\x8e\xb9\x99\x0b\x42\x1c\x55\x58\x00\x9b\xd6\x93\x4e\x86\xd5\x4a\x8a\x6a\xc4\x07\x87\x96\xe3\x05\xc7\xcc\x81\x0d\x3f\x66\xea\x6b\x95\x04\xfe\x0a\xe6\x75\x7c\x50\x4c\x55\x52\x53\x0a\x6f\x8b\xbb\x52\x40\x9b\xe0\x79\xd8\xe4\xa2\x8a\x6f\xd7\xdc\x89\x35\xf8\xeb\x94\x98\xad\xc0\xf2\x3d\x08\x07\xec\x86\x29\x5f\x48\x98\xf5\xd0\x5e\x15\x0b\xdc\x43\xaa\x8b\x7b\xdc\x89\x3a\x0a\x68\x4c\x30\x63\x89\x8b\x6c\x95\xe7\xd5\x6a\x4c\x10\x26\x90\x43\x8e\x9d\xf9\x97\x58\xa9\x0f\x47\xc6\x08\xda\xcc\x4c\xa2\x40\x26\x6f\xab\xa3\x5f\xa1\xeb\x2e\xaa\xbe\x28\x8d\x2c\x2a\xd5\x0b\x6c\xbf\x10\x7c\x00\x25\x75\xe9\x1f\xf4\x72\xa4\x41\x79\x40\x66\x7b\xe8\x18\x01\x73\x85\x4c\x93\xdf\x84\x46\x4b\xcd\x31\x2b\x7a\x7a\xe4\xdc\x2b\x90\x59\xfb\xe6\xf8\x3f\x53\x80\x64\x25\xbd\xff\x03\x1c\x6a\xed\x6e\xfa\xfd\x9d\xe8\xdc\xd0\xdf\xab\xea\x8e\x6f\xa6\x81\xe9\x91\x93\xfb\x3c\x64\x7e\x44\x21\x12\xc9\xa2\x3f\x59\x6e\x65\x41\x1d\x8d\x6b\xfc\x39\x23\x00\x4e\xce\x91\xea\x6d\xeb\x88\x11\x11\xb1\xdc\x29\x94\x3f\x57\x89\x81\xee\x8c\x3b\xce\x85\x25\xf7\x85\x65\xf3\x4b\x85\xff\x20\x01\x5f\xea\xe8\x46\xf9\x5b\x18\x70\x0b\xc5\xcd\xf1\x4b\x2d\xb6\xca\xc6\x98\x14\xd6\x3d\x74\xbf\x20\x32\x93\x03\xe5\xca\x9f\x04\x73\x1f\x68\x81\xce\xc6\xd3\xab\xf8\x7f\x5e\xac\x08\x73\x4f\xaa\x34\xcf\xf4\xd3\xcd\x9a\x4a\x11\xd7\xb1\x2f\x73\x25\x3b\x4d\xd0\xa4\x31\x78\xf0\xd3\xc1\x9c\x0c\x40\xd9\xed\x91\x8d\xd1\x76\x46\xf6\x16\xaf\x79\xfd\xf6\x19\x42\x62\xf0\xfa\x4f\x71\xb3\x18\x7d\xed\xca\x48\xd9\xcb\xcc\x19\x93\x1a\x15\x19\x67\x74\x56\x25\x6e\xd3\x83\x54\x56\x7c\x3a\x67\x57\x1c\xdf\x82\x17\x0a\x2c\x85\xbd\x2c\x5e\x68\xe0\x5a\x0f\x3b\x93\x90\x3f\x19\x1b\x89\x4f\x84\x94\x6f\x89\x00\x05\x68\x05\x4c\x1c\xea\x9f\xd0\xb8\xbb\x55\x01\x95\x06\xc5\x43\x41\xc2\x49\x31\x98\x45\x48\xba\x45\x8a\x4d\x81\x30\x89\x89\x6e\x86\xa2\xdc\x33\xd9\x46\x04\x00\x3f\x35\x4a\x7c\xc9\x41\xc7\x54\xaa\xea\x24\x25\x3c\xbe\x4c\xf2\x14\x7f\xfe\xc5\xe7\xb9\x50\xcb\xf2\x8e\x28\x44\x81"}, -{{0x87,0xd3,0xba,0x95,0xc4,0x0d,0xf8,0x00,0x69,0xb1,0x79,0x7d,0xdf,0x68,0xe8,0x66,0xe6,0x6d,0x46,0xc5,0x1f,0xde,0x60,0xe7,0x68,0xa9,0xdb,0xc5,0xc9,0x2f,0x57,0xa9,},{0x2b,0x81,0x2b,0x2c,0x9b,0x60,0xff,0x31,0x97,0x5c,0x42,0x9a,0x86,0x73,0x6d,0xcc,0x17,0xa5,0x8d,0x3d,0xc1,0xda,0xa3,0x46,0x23,0xa4,0xbb,0xcb,0xe2,0xcc,0x05,0x81,},{0xfa,0x0d,0x12,0xcd,0x53,0x23,0x6c,0x41,0x08,0x6b,0xea,0x8c,0x0c,0xc6,0x0b,0x77,0x64,0xa3,0xed,0x72,0xbd,0xeb,0x9d,0x1a,0xe5,0xee,0xac,0xb4,0x88,0x11,0xfe,0x52,0x97,0x62,0xa2,0xc6,0xf2,0xbb,0x06,0xd9,0xb3,0x18,0x21,0x8d,0x96,0x8f,0x64,0x44,0x35,0x49,0x7a,0x1b,0xd0,0xd0,0xd8,0xc1,0x61,0x2a,0xb8,0x99,0x6d,0x98,0xd7,0x07,},"\xe1\x12\x56\xf8\x2a\xd7\x6f\x3f\x4a\x49\xd7\xba\xd3\xce\xd8\x71\x8d\x36\xd2\xf2\xbb\x3d\x31\xbb\x61\xed\xd1\xec\xbc\xee\x66\x21\xfd\x2e\xee\xd3\xe3\xde\xb5\x97\xb1\x49\xff\x71\xb8\x51\xf6\x1c\x8c\x68\x19\xe1\x31\xf9\xa2\xaf\x76\x73\xc3\xf2\x07\x02\xac\xfd\xc8\xb8\xf9\x06\x4b\x41\x5c\x9a\x3e\x35\x56\x8e\x37\x1d\x74\x0a\x38\x12\x7c\x1f\x27\xb3\x91\xb4\x5d\x07\x04\x5a\xea\xf0\x0a\x54\xe5\xb7\xfa\x54\x8a\xfb\x5f\x96\xfe\xb5\xf5\xb4\x4f\x60\xcd\x17\x07\xe8\xfa\x95\x67\xf7\x80\x6e\x15\xf6\xa0\x1a\xa0\x20\x77\x73\x3f\xe7\x38\xb0\x8f\x21\xef\xbc\xf9\x8c\x19\xd5\xb9\x70\xe6\x16\x3e\x5f\xe8\xf4\x80\x0e\xf9\xed\x22\xa0\xf9\xb5\x12\x6f\xf1\xeb\x1c\x7d\x65\x01\x9c\x8b\x44\x03\x91\x92\x70\x29\xb8\x13\xda\xb7\xc7\xe8\x63\xd4\x82\x29\xf8\xdf\x85\x39\x43\x45\xfc\xc8\x8a\x30\x0f\x60\xa8\xd5\x16\xd8\x77\xa5\xa3\xa7\xe3\xc4\x9a\x9e\xb0\x6c\xd9\xf2\x66\x5c\xe2\xa8\x90\x22\x96\x2b\x1d\x49\x59\x2b\x09\xc7\x54\x3d\xa8\x35\xce\x63\xbc\x9a\xbb\x82\x21\x45\x76\x2b\x71\xcb\xe1\x50\x29\x2c\xe5\xc8\x70\x4e\x5a\xd3\x4f\xb4\x59\x2f\x97\x20\x44\xe4\x3e\x69\xf0\xe1\x67\x2d\x6c\x83\xcf\x25\xaa\xc6\x8e\xfe\x3d\x27\xaf\x2a\xd3\x42\x74\xb9\xd2\xb7\x77\x42\xd9\xc6\xdf\xbd\x57\xf9\x2f\xf6\x4d\x3e\x4c\x67\xc5\x41\xd8\x50\x2a\x7d\x03\x18\x95\xaf\x85\x31\x9a\x4e\xae\x2d\x25\x43\x35\x83\x5e\xff\x11\xe7\xa3\x67\x1a\x6a\x0d\x21\xb7\x2c\xe1\xfc\x2a\xcb\xa1\xa9\x20\x18\x38\x34\xbc\x0a\x4b\x73\xf6\x39\xff\xcb\x0f\x6b\x81\xcd\x92\x0f\x2e\x94\x20\xd6\x12\x16\x6d\x56\x82\xa0\x60\x60\xea\x0b\x6f\xa6\x95\xfe\xcc\x77\x04\xbb\xe4\xb0\x52\xaa\x3e\xc8\xf7\x20\xf7\xd4\xf3\x2e\x8a\xff\x86\xb8\x0b\x8c\x1c\xc1\x27\x64\xa0\x48\x74\x03\x7c\x31\x03\xe9\xdf\xec\xb8\xf7\xab\xcb\x0e\x07\x3b\x23\xe6\x7c\xa0\xa9\xb1\xfc\x72\x99\x3a\xbf\x31\xdb\xc2\x4a\x8f\xee\x09\x5b\x32\x51\xc2\x26\x26\xaf\x5d\xd1\xb6\xd3\x4b\xe5\xea\x06\xa0\x2a\xe1\x76\xc7\xb8\xcb\x9d\x06\x35\x01\xbe\x6f\x61\x20\x82\x88\x9f\xdb\xdc\xbf\xad\xc3\x3a\x0d\x31\x1b\x08\x0b\x8d\x64\xe4\x9f\x16\xb1\x6d\xd8\xed\xd3\xb2\xed\x11\x93\xa7\x4e\x5b\xe5\x07\x60\x9b\x04\x27\x27\xcc\xf0\x8a\xfb\x05\xcc\x6c\x50\x52\x4e\xf0\xe2\x66\x46\x21\xdc\x8b\x05\xb1\x5f\xfa\x81\xab\x6f\x7e\x3c\x8a\x5b\xb3\xea\xb1\xf6\x8e\x36\x56\xc1\x19\xd9\x69\xe4\x14\x4c\xf3\x28\x5a\xf2\x3c\x04\xdb\xec\xc0\x38\xae\xfd\x91\x83\xc4\xe7\x24\x47\xb2\xaa\xa8\x31\x5f\x46\x96\xce\x6d\x1e\xf4\x29\xba\x0e\x5c\x3d\x5f\xfa\x7f\x05\x0b\xe3\x9c\x7f\x61\x2f\x4e\x10\xf8\xef\x07\x0d\xf7\x2f\x8a\xdd\xbe\xaf\x33\x39\xc1\xad\x8b\x5f\xc3\x9a\x2e\xcf\x29\xa8\x7f\x82\xe2\x9a\x01\x17\xba\xac\x66\x25\xad\x5c\x80\xcf\xe7\x59\xfa\x1d\xbc\xfa\xa1\x2b\x37\x44\x77\xd8\x0b\xfc\xf0\x67\x96\xc3\x0f\x2c\x39\xcf\x03\x03\xd0\x0d\xc5\x6a\x32\xd1\xd0\x39\x59\x2d\xdb\x06\xc2\x2a\xa0\x68\x84\x1c\x0b\x46\xfd\x48\xdf\x8f\xbb\x74\x92\xcc\xbc\x59\x0c\x56\x3c\x8f\xec\xce\x42\x63\xc8\xc7\x53\x92\x18\xbb\x97\xb3\x57\x11\x53\x7e\x98\x81\x95\xdb\xf5\xbc\xd5\xcc\xaf\x06\xfa\xf5\x08\x47\x09\x77\xa5\x35\x8e\x6f\x02\x60\x83\x49\xfb\xb9\x9a\x23\xfb\xe3\x6b\x8c\x97\x15\x5a\xdc\x24\x6a\xd7\xd9\x3a\x8c\x20\x3f\x75\x44\x6c\x83\xc4\x34\x2c\x35\xba\x10\x4e\xcc\x67\xe6\x69\xdb\x4a\x95\x46\x6e\xe6\x8f\x45\x8a"}, -{{0x7c,0x27,0xae,0x47,0x07,0x2b,0x0c,0x9b,0x9c,0x2c,0x35,0x1f,0x13,0x27,0x89,0x98,0x95,0xef,0xa5,0x36,0xc9,0xc0,0x67,0xd0,0xe0,0xce,0x8e,0x82,0xe6,0x29,0x27,0x93,},{0xf9,0xfe,0xbd,0x12,0x1e,0x17,0xdb,0x72,0x29,0xb5,0x67,0x09,0x02,0x18,0x49,0xc3,0x5d,0x69,0xfa,0x08,0xb5,0x06,0x20,0xe6,0x67,0xf8,0x42,0xec,0x7a,0xc7,0x82,0xdc,},{0x32,0x71,0x96,0xdd,0xd4,0x3b,0xb6,0x02,0xd0,0x4d,0x19,0x64,0xcc,0xc0,0x59,0xed,0x62,0x7c,0xef,0x0a,0x88,0xd8,0xad,0x91,0xbe,0x49,0x31,0xf1,0x7c,0x25,0x0d,0x55,0x29,0xf5,0x52,0x79,0x4a,0x3e,0x26,0x9d,0x17,0xa6,0x3b,0xd3,0x29,0x33,0xeb,0x5e,0x51,0x9c,0x1d,0x50,0x65,0x74,0x77,0x0a,0xe4,0xa7,0x29,0x64,0xe0,0x6f,0x7d,0x00,},"\x15\x47\x87\x6a\x98\x8d\x1b\xe7\x14\xa4\x2f\xb9\x1c\xb0\x37\x63\xf1\x91\x3a\x89\x2e\xcb\xd4\xde\x2c\xcf\x83\x44\xd2\x07\x58\xb7\xb6\xd0\x02\x59\x10\x1f\xe9\x72\x25\xb2\x97\xf8\x7b\xfe\x22\x20\x04\x32\x5d\xb7\xf6\x32\xce\xaf\xfb\xd1\x34\xc9\x6c\xbd\x57\xe9\x85\xbe\xc8\x43\x4f\x81\xa4\xee\x6a\xf8\x5c\x3f\xad\xe5\x0e\x4c\x4e\xf2\x0c\xb0\x39\x35\x45\xe4\xd4\xa8\x6e\x1f\xa3\x9a\xaf\x33\x3f\xe4\xde\xd0\x54\xbf\xc0\x50\xa8\x98\x3a\x03\xdd\x1e\xcf\x2b\x5e\x95\x17\xba\xf9\xe1\x15\x21\x29\xa8\xa7\x59\x35\x71\x1e\xdb\x20\xaf\x5c\x8c\xf9\xc6\x94\xa3\x3c\xee\x45\x1c\xd9\x50\xb2\xff\xf0\x8e\x31\x58\xc5\xcf\xb7\xb1\x5c\xb3\xe9\x0d\x46\xf4\x94\xb6\xa1\x08\xd8\x88\x8d\x5e\xc2\x9a\x33\xc0\x66\x02\x3b\x49\x77\x09\xb2\xd9\x40\x1f\xea\xf2\xe7\x4f\xf2\x6c\x16\xd3\x6c\x39\xe6\x51\x7f\xf9\x54\xbd\x98\xbc\xe7\x70\x06\x71\x98\x8f\x66\xe8\x51\x07\x64\x4b\xa2\xea\x00\x7a\x13\x01\x8c\x1c\x14\x4e\x3c\x5b\xb8\x0d\xb9\x51\x1f\xcc\xa4\x10\x1b\xf4\x9f\x8c\x80\xff\x3c\xa7\xd2\x98\x25\x7c\xbf\xea\x62\x9f\x83\xd5\xe0\x66\x39\xd3\x1f\x63\x9d\xb4\xb8\x72\x6c\xbe\x22\x4d\x75\x88\x29\xba\xb1\x09\x05\x17\x1c\x9c\x0e\xc3\x70\xd5\x80\x31\xef\xe4\xcc\x5a\xe7\x2a\x49\x5a\xcf\xf6\xcb\x2e\xd9\xee\xc6\x58\xba\x11\x70\x88\xdd\x3c\x6e\xd1\xdf\x8f\x9c\xb1\x0b\xd4\xfe\x0e\x5e\x8a\xd9\xf5\x03\x4e\x34\x65\x2d\x98\x66\x8d\xb1\x5c\x85\x33\x39\x3a\x6e\x9e\xc0\x87\x0c\x35\x66\x6c\xe5\x4e\xfe\x2b\xcb\x45\xc3\x4a\x72\x30\xe6\xa7\x00\x67\x63\x49\xc7\xb3\xab\xf3\x1d\xe7\xb7\xb0\x52\x1f\x89\xb3\x0a\xc4\x03\x4c\x2a\x4b\xa8\x21\x8e\xef\xdf\x8d\x2a\x5c\x1f\x8e\xd9\xb7\x01\x57\x9e\x47\xaf\x8a\x52\x9a\x95\xa1\xff\x64\xd8\xfd\xb8\x85\xc3\x68\x39\xb4\xc5\xf6\xd7\x2a\x99\x25\x7e\x86\x78\xdc\xcf\x31\x27\x54\xb9\xd4\x61\x9b\xee\xce\xb8\x25\x52\x6d\xe6\x22\xbd\x96\x76\xfd\x5f\x35\x76\x93\xab\xab\x07\x8b\x9e\x03\xae\x21\xe8\x7c\xa1\x61\xe7\x78\xaf\x77\x09\x6e\xaa\xc2\xd2\xd3\x2b\xfe\xc8\xec\x94\xaf\x79\x65\xf6\x1d\x68\xef\x66\xa4\x52\x3c\x1c\xc7\x0c\x95\x19\xb0\x75\x0b\x3c\x9e\xed\x5a\xeb\xa9\xf0\xa9\xb7\xef\x52\xcd\x4a\x2d\xe2\x9b\x39\x5b\x70\x5f\xa5\x3f\x02\x8f\xa7\x66\x15\x9f\x20\xe7\x5f\x4d\x38\x4e\xc4\xfd\x66\xdf\x06\xe7\x44\xc9\x9a\xc8\x8c\xb8\x49\xc2\x85\x75\x7c\xc5\x57\xe2\xee\xdd\x86\x95\x9d\xa2\xc1\xb8\x1f\x5b\x27\x15\xa6\x51\x98\x48\x90\x1a\xe4\xf8\x9d\x09\x13\xc8\xde\x57\xc5\x3d\xad\xf2\xe5\xe1\xaa\x2a\x9c\x5f\x46\x4f\xc7\x61\x0e\x8e\xf5\xf5\xcd\xd8\x20\x3a\x67\xa9\x3c\x33\xa0\x6d\xab\x35\x8d\xc5\xae\x23\xed\xfe\xe6\x33\x42\x62\xf4\x7b\x19\xb1\x13\xd6\xca\xfe\xda\xc1\xb4\x39\x02\x53\x9d\x74\xfb\xa2\x9a\xaa\x7b\xce\x68\x88\x4b\x72\x61\x6a\x05\x42\xc9\xfc\x69\x54\x7c\xd1\x9a\xe1\xdf\x01\x72\x3a\xbd\xda\x65\xe9\xbf\xac\x5d\xa0\xd0\x42\x40\xc6\xa2\x17\x5c\x00\x62\xe4\xe1\xed\x8a\x5b\x39\x7a\xfc\xd4\xde\x38\xe8\x62\x09\x27\x2c\x7a\x42\x4b\x5a\xe8\xd5\xa4\x0b\x48\x4c\xe1\xb4\x70\x4a\xf2\x83\x16\x09\xad\x0f\x36\xe9\x0e\x07\xb2\xaf\xed\x01\xdc\x05\x57\x4a\xd3\x97\x17\x23\xc5\xb5\xc1\xdd\xd4\xfc\x8b\xd2\x63\xbc\xdf\x56\x8a\xf7\x5e\x73\xd8\xab\xd1\x00\x8c\x9e\xc7\x12\xf8\x0f\xfc\x65\xac\x34\xe2\xa7\x93\x04\xea\xde\x1d\x2a\x1d\xff\xec\x0e\x4c\x98\xc3\x58\x24\x68\xf3\x20\xbf\x8f\x66"}, -{{0x08,0xed,0xdc,0xb5,0x62,0x5a,0xe1,0x9f,0xfe,0x7b,0x49,0xa7,0xdc,0x82,0x9c,0x89,0x3c,0x75,0x38,0xb0,0x88,0x5e,0x18,0xf9,0x8d,0xb7,0x8c,0x8b,0xeb,0x56,0x9c,0x26,},{0x83,0x47,0x8b,0x1c,0x58,0x57,0x6a,0x0d,0x18,0x34,0xb2,0x8d,0x46,0xfb,0x80,0x51,0x6d,0x6f,0xb6,0xf9,0xf5,0x91,0x69,0x4b,0x44,0x35,0x2e,0xec,0xd1,0xe7,0xe8,0x9a,},{0xec,0xe7,0x53,0x22,0x99,0x51,0x54,0xb2,0x92,0x43,0x7e,0x47,0xd3,0x8a,0x6a,0x70,0xaf,0x37,0xe2,0x02,0x07,0x16,0xfd,0xe4,0x6b,0xfd,0x39,0x3b,0x3d,0x36,0x9b,0xdd,0xb5,0x32,0x53,0xb5,0x56,0x62,0x1c,0xfb,0x34,0xc8,0xa9,0x02,0x54,0xe1,0x32,0xfd,0x28,0xec,0xd0,0x98,0x43,0x34,0x13,0xa2,0x1b,0xd3,0xa9,0x79,0x8c,0xa1,0xf3,0x09,},"\x01\x5b\x1d\x3e\xeb\x00\x92\x9e\xa8\x0b\xd8\x68\x7d\x18\x28\x6f\x0a\xdf\xe6\x45\xcc\xf2\x5a\x22\xb5\x06\x19\x21\xe2\xa0\x30\xfc\x76\xd0\x33\xfb\x53\xd0\x93\x7c\x69\xb3\x1c\x5b\xe4\x99\x13\xca\x1f\x2c\x3d\xca\x12\x1b\x2b\x87\xc5\x9b\x3c\x84\xc7\xae\x52\xaf\x19\xc6\xb9\xfa\x1b\xd6\x75\xfb\x6d\xd8\xb3\x29\xd5\x66\x87\x86\xdc\x78\x83\xe2\xd2\xe8\x58\x6f\xf4\x12\x8b\x90\xde\xe8\x4b\xe0\xab\x54\xd6\x81\x3f\x7a\x8c\x61\x34\x75\x71\x73\x98\x17\x75\xde\x84\xc4\xdd\x39\xe3\x36\xf8\xa4\xef\x8d\xca\xde\xc9\x43\xe9\x0d\x42\x1b\x22\x9c\x11\x78\x5f\xcd\x3f\xe9\x63\x03\x74\x58\xe7\x6c\x82\x0b\x3b\xc2\xc9\x47\x60\x01\x26\x2b\x26\x1d\x28\xb6\x5b\x48\x9d\x76\xb4\xbe\x23\x65\xe4\xa8\x0f\xa8\x71\xb0\xa5\x3b\x6a\x5f\xb2\x43\x68\x82\x35\xac\xc5\xf4\x77\x4d\xb1\x5d\x47\xb4\x2d\xd6\xc8\xd9\xe1\x2d\xcb\x0b\x5d\x98\x0d\xab\x0f\x3a\xd8\xa4\x96\xf7\x6e\x50\x06\xc2\xca\x82\x67\x5f\xf1\x94\xca\xf8\x07\x0d\x04\xbd\x38\x4f\x97\xe5\x83\xe7\x3c\xbc\x4f\x7f\x25\x73\x10\xa6\x1b\x1c\x80\x62\x32\x2d\xce\x81\x15\xf6\xdd\x93\xee\xe8\xa9\x3f\xfa\x5c\xab\x66\x34\x11\x6e\x1a\xb7\x05\xfa\x86\xc4\xa8\xea\xa5\x56\xc6\xc8\x9d\xbc\xad\x01\x04\x36\xbf\xfe\x45\x18\x22\x49\x1f\x1e\xa8\x6c\x20\x20\x7e\x4d\x12\xdf\xa3\x62\x61\x6c\x58\x9f\x97\x10\x7e\xa5\xd8\xbd\x8a\x72\x15\xc6\x00\xff\xc7\x0b\x80\xe2\xab\xb1\x5a\xcb\xe4\xbe\xcc\xa2\x0d\x72\x15\x5a\xbc\x3d\xbe\x8e\x37\xcf\xd7\x3f\x74\x20\xf2\x1c\x9b\xcd\x0c\x32\x73\x51\x3b\x50\x49\x67\x08\x74\xd5\x51\x9b\x3b\xc1\xdb\x52\x3c\x1d\x7e\x90\xc1\x65\x96\x7c\x4c\xb2\x84\x5a\x2e\x8b\x47\xb5\x88\x92\x54\xf5\x8a\x9b\xbb\x82\x6f\x94\x52\x1c\xdb\xd0\x41\x6f\x5f\x18\xff\x78\xa3\xfd\x0d\x7a\xb8\x97\x90\x62\x64\x48\x3c\xde\x64\x2d\x8e\x70\x3f\xd8\x2e\x5a\xe7\x0a\x9f\x97\x8f\x64\xee\x80\x52\x05\x54\x85\x05\x28\x58\x1c\xa9\xa0\xb3\x8c\x19\x6f\xd1\x66\xda\xe5\x87\x9b\x3f\x72\xf5\x9c\xde\x91\xcc\xa2\xc8\xbf\xaa\x47\x8b\x98\xd6\x24\xcd\x34\x72\x44\x02\xde\x57\x8e\x57\x54\x82\x5c\xe2\x27\xd2\x87\x1b\x45\xa5\x11\x71\x49\x51\x5b\xff\x81\xa9\x23\x24\x6f\x3b\x72\xd0\x7b\xd4\x58\x12\x5c\x70\xa1\x4d\x87\xc3\xfd\x13\x39\x2a\x3b\xda\x65\x53\x01\x6e\x8b\x2d\x07\xbd\xe9\x03\xcf\x68\x7b\x44\x5c\xfd\x6f\x76\x14\x92\xeb\xa4\x65\x22\xad\xa8\x4a\x96\x15\xd8\xda\x34\x98\xb2\x58\x06\x72\x69\xb7\x88\xe5\x59\xb6\x59\xd4\xb4\x8a\x87\xd8\x80\xd6\x37\x8b\xe6\xa8\x87\x46\xf3\x5b\x32\x2b\x04\x78\x45\xaa\xdc\x52\x3b\xea\xff\x30\x70\xf7\x21\xc3\xc0\x71\xea\xa3\x19\xb7\xa4\x7c\x1b\x20\xd3\x00\xdc\x03\x21\x90\x9b\x66\x9e\x57\xd3\x9a\x1c\xe2\xfd\xbe\xaa\xfa\xc2\x13\x50\xec\x2d\x6e\x6d\x5b\x88\x01\x86\xc0\x28\xa8\x61\x47\x4d\x50\x76\xa4\xad\xc5\x03\x2f\xec\x91\x40\x78\x7c\x36\x80\x6e\xf7\x9c\x72\xe3\xa1\x9d\x8c\x8b\x70\xbd\xaf\x20\x72\x95\x54\x2d\x96\x82\x5a\x5d\xe7\xdf\xe1\x08\xef\x57\x45\x99\xb8\xf1\x84\xc6\x3a\x5a\x13\x1d\xb1\x9b\x3b\xe5\x3f\x69\x9c\x10\xfc\x4c\xa7\xc6\x3f\x35\x00\x21\x1b\x35\x6a\x0a\xc6\x64\xdd\xfc\x1a\x92\x52\x59\x00\x26\x39\x5b\x47\x9b\xe9\xa5\xe4\x75\x84\x23\x56\x0b\x65\xbb\xce\x5b\xba\xde\x49\x3b\x13\xd0\x0c\xf8\xc1\xd3\xb7\xe9\x22\x13\x67\xe8\xf0\xea\xda\xb6\xe6\xd1\xb5\xff\xfd\xe7\xb2\xd7\x41\xfc\x2c\x83\x02\x24\xff\xf7\xff\x14\xae\x5c\x07"}, -{{0x22,0x73,0x94,0x2d,0xb3,0xe5,0xd3,0x22,0x1e,0x80,0xd9,0x94,0xfd,0x5e,0x11,0x63,0xaf,0x55,0xf5,0x45,0x5a,0x8e,0x52,0xbe,0x85,0x2d,0xd3,0xad,0xf7,0x62,0xb4,0x40,},{0xbc,0x58,0x67,0x4e,0x99,0x6b,0x6f,0x3e,0x32,0x20,0xb3,0xe9,0x4f,0x00,0x67,0xbb,0x0e,0x9b,0x0d,0x97,0xd9,0xe1,0x05,0x9c,0xf1,0x39,0x97,0xa1,0x93,0xac,0x03,0x2a,},{0x87,0x4d,0xde,0xce,0x08,0xf3,0x0b,0x30,0xf0,0xd4,0xc8,0xb3,0xed,0x7c,0x61,0x51,0x49,0xb8,0xaa,0x74,0x0d,0xaa,0x34,0x7b,0x55,0x95,0x8f,0x1e,0x21,0x19,0x04,0x4f,0x69,0x5a,0x21,0x06,0x96,0x90,0x50,0x64,0x48,0xd8,0xe7,0x35,0x2b,0x90,0x46,0x51,0x1d,0x7f,0x39,0xa5,0x41,0x5b,0xb9,0xc5,0x70,0x50,0xfc,0x17,0x05,0x5c,0x38,0x08,},"\x8a\xa0\x50\x9e\x4b\x91\x41\x86\xff\xff\x07\xae\xb9\x7a\x04\xb5\x46\x27\x2d\xa2\xf9\xea\x7b\xfa\x65\x9a\x24\xcb\x50\x96\x6c\x23\xeb\x65\x42\xe4\xf2\x2d\xeb\xe3\x3b\x65\x76\x92\x45\xc4\xd1\xb5\xdc\xf3\xe6\x99\xc7\x0c\x5c\x2b\xaa\xd9\x73\x4e\x9d\x1e\xfe\x54\x48\xab\x71\xc8\x94\x6a\xec\xce\x52\x68\xd2\x6f\x19\xcf\x60\x5e\xb3\xbf\x38\xb0\xb3\x32\x26\x94\xac\x0d\xcb\x76\xb0\xf9\x46\x84\x2f\x6c\x5c\x68\xd7\x63\xfc\xe7\x47\x01\xbd\x6b\x78\xe7\x1c\x8c\x31\x42\xad\xd4\xed\x46\xe0\x96\x9b\xb9\x55\x5b\xe0\x36\x02\xd5\x62\xe4\xc8\x9f\x3a\x91\x99\x40\xe8\x83\xa9\x69\x40\x54\x2f\x27\x79\xfb\xf9\xec\x0a\x28\x5d\x9d\x8a\x72\x36\x01\x46\xe3\xff\xbd\xb7\x8d\x21\x03\x16\x03\x8d\x95\xd6\xab\x75\x71\x65\xaa\x94\x3c\x03\x3e\xeb\xb3\x21\xc0\x5a\x39\x95\x69\xbc\xf6\x6b\x4d\xdb\x0b\x2e\x0e\x33\xc4\x79\x3d\x81\x7c\xcf\xf5\x7f\x99\xb3\x18\x9c\x60\xd5\xd7\xb9\x41\x9d\x1e\xbc\x94\x3a\x79\xd4\xd8\xc3\x94\x56\x61\x80\x59\x4f\x55\x9a\x80\x52\x9c\xc1\xba\x28\x87\x7a\xf8\xf5\xc0\x50\x3e\x94\x3c\xd3\xaa\xd9\x98\x11\x64\x52\x72\xda\xfb\x49\xb9\xb3\xe6\x10\x7e\xb5\xe5\x18\x6e\x16\x08\x75\x71\x26\x05\x3d\xeb\xce\xc7\x5d\xd9\x56\x5c\xee\xa0\x6a\x13\x91\xa8\x22\x6d\x1f\x45\x93\x79\x22\x40\xcc\xd9\x7c\x67\xa6\xc2\xb1\x34\x4c\x22\xc9\x1f\x42\x03\x3a\xde\xf5\x28\x61\xf3\x2a\x4e\x07\x12\xa9\x17\x87\x9a\x0b\x05\x18\xb5\x42\x4b\xcd\xc0\x54\xb4\x4e\x97\x2e\xd2\x4d\x01\x68\x9f\x4f\x27\xf5\xf1\x76\xf0\xa5\x78\xab\x2d\x3c\x08\x78\x27\x2e\x8c\x08\xc2\x15\x82\x11\x86\x54\x12\x4d\xca\x39\x58\x53\x37\xc1\x3c\x18\x65\x81\x4c\xaf\x09\x96\xca\xdf\xa6\x5b\xe5\x80\xde\xe3\x22\xeb\xcc\xda\x70\x4b\x22\x80\x58\x26\x04\x06\x7d\xc3\xc6\xb1\xf7\xd8\xa2\x69\x78\xa6\x5c\xff\xd1\xed\x31\x96\xa2\xb0\x65\xfb\x3c\xaa\x79\xe6\xb5\xb6\x6c\x13\xd7\xbd\x7d\x0e\xc1\x4a\x3a\x4d\x58\x41\x3f\x21\x2f\x47\x1e\xca\xad\x3a\x84\xaf\x35\xe5\x98\xa8\x9f\xb3\x44\x7d\x33\x24\xf0\x20\xfb\xf1\xb7\x3e\x2a\x98\x6e\x0d\xa1\x6c\x01\x83\xbf\x92\xa3\x98\xc4\x19\xa0\xf9\xf3\x05\x37\xbe\xa0\xdf\x8d\xf2\xdc\x53\xc1\x54\xe8\xea\x16\x06\x89\xe7\xbb\x4d\x72\x9d\xd8\xab\x90\x03\x14\x27\xaa\x39\x45\x86\x3a\x85\xe8\x96\x52\xb9\x35\x38\x05\x16\x6f\x7c\x0a\x18\xc9\x39\x95\x4b\x27\x87\xc3\x70\x94\xf9\x25\x12\x72\x2e\x52\xb0\xc9\x76\xb9\xe4\x2a\xf4\x03\x9d\x2c\x05\x78\xff\x14\xfa\xe1\xd8\xc2\xd1\x39\x6b\xeb\x2d\x6a\xa6\xeb\xd5\x54\x74\xa9\x34\x98\x67\xa0\x3f\x3a\x99\xd7\x87\x80\x63\x4a\xb4\xb3\x5c\xfe\x1b\x87\xa9\x13\x32\x52\xa6\x98\xbc\x40\x7d\x63\x84\x28\x70\xe2\x2c\xcf\x39\x33\x62\x0a\xc0\x42\x3c\x3d\x1f\x68\x1d\xd7\x3c\x01\xd0\x6c\x3b\x94\x15\x06\xc9\x8e\xed\x9b\x78\x68\xe0\x17\xb7\xf9\x97\x16\xb0\xb7\x7f\x11\x32\x1e\x5a\xb2\x3d\xbf\xcf\xca\x93\x50\x84\x5e\xe1\x80\x44\x4c\x50\xff\x0a\x9c\x96\x5f\xcb\xf7\x77\x70\x8e\x4f\x34\xcc\xc6\x37\xc6\xa0\x8d\x85\x43\x84\xf8\xd3\xe2\x51\x69\x56\xc1\x51\xd0\x31\xbb\x1c\xbe\x71\x2a\x5e\xf9\xee\x16\x61\x92\x28\xbd\x29\x6f\x2a\xfe\x58\x2d\x99\x53\xd5\x90\xd1\x8b\xb2\x05\xf7\x0f\x84\x4c\x16\xc0\xa2\xd8\x31\x80\x37\xd4\x3d\xd8\x0f\x65\xc6\xa7\x53\xf2\xa8\xe2\x7c\x89\xc8\x3e\x7e\xd7\x0c\x52\xf7\x06\x2d\xfb\xb1\xf5\x44\xaa\x23\x6b\x5c\x70\x4e\x7b\x39\xce\x0a\x55\xfd\x46\x52\x80\x83\xca\x61"}, -{{0xdb,0xfa,0x45,0xab,0xaa,0x55,0x41,0x52,0x38,0xb1,0x28,0x76,0x34,0xd5,0xee,0xc4,0x02,0xda,0xdf,0x62,0x2e,0x27,0x0c,0x04,0xa8,0x91,0x4c,0xed,0x27,0x0a,0x72,0xbe,},{0xc0,0xfe,0x32,0x35,0x81,0xea,0x29,0x67,0x50,0x79,0x7e,0xb5,0x50,0x8c,0xa1,0x9a,0x58,0x3b,0x53,0x7f,0xa7,0xdf,0x45,0x29,0xf0,0x80,0x4a,0x33,0xc1,0xa4,0xbe,0xf4,},{0xa4,0x62,0xa9,0xba,0xa5,0x6d,0xc0,0xf7,0xa7,0x1b,0xf8,0x7b,0x95,0xf4,0x8d,0x64,0x20,0x22,0xd9,0xd1,0x73,0x3e,0xe3,0x68,0x37,0x77,0xa3,0x78,0x22,0x28,0xac,0x85,0xfc,0xd8,0x30,0x26,0xbe,0x4c,0xa9,0x7a,0x34,0x5b,0x08,0x4f,0x50,0x87,0x4e,0x91,0x24,0xe1,0x6b,0xa1,0x7d,0xea,0xd4,0xad,0x85,0xc0,0xe5,0x6f,0x16,0xef,0x18,0x04,},"\xe2\x6e\x8d\xcb\x44\xe6\x41\xfc\x20\x08\x0e\x95\x47\x4b\xd3\x9d\x71\x6c\x5a\xfe\x5a\x1f\xfb\x05\x6d\x1e\xaa\xb0\xc4\x9f\x85\x70\x71\x7d\xb6\x43\x7a\x03\x22\x8a\x9a\xd9\xf4\xbb\x0b\x34\x3b\x95\xe1\x60\x23\xc0\x80\x7e\xb2\xa1\x51\x06\xa6\xeb\x12\xdc\x76\x68\x3e\x69\xdd\xa3\x36\x31\x48\xc5\xd7\xdd\x97\x13\xaf\x6f\x87\xa0\x94\x10\xea\x8f\x76\xb6\xb7\x8a\x11\x44\x29\xbc\x85\xf7\x84\x81\x2f\xca\x31\xac\xb0\x30\x95\x52\xcc\x18\x8c\x6e\x96\x97\x09\x3c\xf4\x04\xc6\xf0\xf4\xab\xe8\xa1\x60\x86\x73\xfd\xfa\x5e\xb7\x8f\x65\xfc\x1d\x49\xcd\xec\x40\x94\xb1\xbd\x23\x4a\x46\xe0\xec\x62\xa4\xb6\xd3\x1b\x82\x96\x11\x54\x01\x27\x87\x6b\xff\x4c\x17\x3d\xe0\x58\xcf\x61\x00\x4b\x01\x4a\x7b\xdf\x79\x3d\xfd\x6b\x63\xc5\x07\xd2\xb2\x3e\x0f\x56\xbc\x2f\xe6\xba\xf6\x37\xce\xe4\x0d\x18\x99\x22\x95\xd8\x48\xef\x49\x8f\x8a\x16\x1b\xd8\x7e\x60\xc9\x1f\x97\xa9\x1e\x9e\xf3\xf6\xd9\x7f\x2b\x2d\x21\x04\xba\x6f\xdd\xd6\xc6\x80\x70\x62\x73\xda\xe8\x7e\x6e\xec\x1a\xf2\xa4\x59\x84\x98\x50\x69\xe8\x09\xe8\xde\x32\xc1\x28\x89\x29\x9a\x32\xd4\x0f\x38\x77\x45\x99\xac\x33\x24\xb7\xcb\x0a\x4e\xa6\x32\xc5\xf9\x10\xad\x87\xf5\xad\xbf\xa5\xc3\xbb\x20\x49\x82\x79\xfd\x53\xc1\xc2\x67\xfe\x0a\x84\x77\x30\x85\xda\x26\x6b\x25\x3c\xd8\x53\xdf\x7e\x96\x35\x58\xcb\x06\x88\x07\x80\x97\x34\x23\xc5\x64\xcd\x0b\xcd\x6b\x93\x33\x4c\x19\x59\x53\xd7\xcd\x89\x9f\x8a\x54\x7d\x1a\x1a\x0a\x8d\xef\xf1\x38\x1b\x43\x21\x57\x47\x28\xcf\x71\xb9\x6f\xf2\x09\xe8\x99\xda\xa8\xf1\x3f\x41\xb2\x30\xe1\x7b\xff\xdf\xdd\x2a\x89\x43\xaa\x5d\x21\xe5\xf3\x6e\x1d\xa0\x7e\xdd\x6c\xee\x92\xdc\x48\xb5\xb2\xa7\x58\x01\x46\xa9\xba\xf7\x13\x95\x0c\xe6\x76\x25\x5a\x89\xe3\x4f\x87\x87\x54\x7d\x62\x86\x8d\xb1\x4b\xa4\x65\x94\xda\x31\x0d\x7e\x2d\x9e\x7c\x7d\xbe\x17\xdb\xd7\x1e\xb4\x7c\x56\xc5\x72\x1d\xc9\x6d\x69\x64\x70\x57\x37\x94\x80\x94\x11\xcd\xfa\x27\x6b\x05\x9d\x00\x07\xc2\x5d\x74\xb2\xa6\x7d\x38\x24\x6d\xe1\x1e\xf4\x6d\xfe\x26\x70\x92\x6f\xe4\xb6\x36\x56\x23\x1b\xc7\x26\x8b\xba\x23\xf3\x78\xe8\x4a\x42\x8c\x3c\xbf\x45\xcc\x53\x96\x78\xfd\x46\x7c\xd3\x3d\xd0\x75\x7c\xfa\x02\x4e\x54\xda\x1f\xf5\x4c\xe8\x20\x22\x9b\x77\x8b\x18\x4b\xe1\xfa\x2e\x84\x68\xcc\x19\x95\x59\x40\x73\x5e\xaa\xa8\x84\x02\x2f\x64\x18\xb0\xb1\xf2\x6b\xcc\xf1\x69\xf1\xbc\xac\x7d\x82\xa3\x5a\xb6\xef\x84\x7e\x1d\xba\x53\x7d\xca\xff\x57\x25\x0a\x8d\x1c\x71\xfa\xcb\x13\x4c\xd0\x6b\x01\xc4\x53\x19\x13\x27\x45\xdc\x48\x88\x88\xa1\xd7\x76\x1b\x84\x86\xa3\x7e\x69\x88\xa1\x12\x0b\xcc\x16\x82\xdb\xfc\x89\x14\x3f\xc3\x5b\x46\x93\x5d\x8a\xcf\x6e\xf3\xc4\x2f\x0f\x4b\xf6\x79\xdf\xd6\xff\x44\xb6\xad\xa2\x6b\x01\xa9\xf8\x9f\x37\x4c\x7d\x2e\xe4\x8d\xfe\x1a\x41\x0e\x89\x7c\xdf\xd9\x7f\x62\x6d\x26\x68\x50\x28\x14\x40\x07\x93\xb3\xb0\x7c\x87\x20\xbb\xdd\xc5\x9c\xb0\xf9\xde\x96\x4a\xe0\x75\xb4\xaf\x3d\xd4\xba\xf6\xd0\xe4\xf9\x4f\x29\x4e\x81\x09\xd6\x57\x7c\x4f\x8a\x9c\x7a\x5f\x7d\x69\x4b\xf8\x8f\x1a\x5e\xa7\xeb\xa0\xa6\x6d\xa6\xc7\x70\xc0\x8b\x3a\xbf\xfc\x53\x4d\xf2\x19\xdc\x3e\x33\x23\xb0\x22\xe9\x6c\xc8\x60\x02\xb1\x89\x18\x1a\x1d\x2b\x52\x7d\x27\x95\x0b\x7f\x42\x5a\x47\xda\x40\x13\x77\x8b\xd0\x0b\x71\x10\x59\x22\x20\x49\x21\xe9\xdc\x69\x2c\x23\x3f\x7b\xaa\x04"}, -{{0xef,0x64,0xe1,0x7a,0x53,0xf7,0xfb,0xca,0xfe,0x3e,0xa4,0x68,0x76,0x84,0xa0,0xda,0xdb,0x18,0xd0,0x37,0x35,0xa4,0x0a,0x53,0xb3,0xed,0xb0,0x49,0x07,0xee,0x61,0x62,},{0x91,0x86,0xe6,0xbc,0x14,0x29,0x61,0xc4,0xd3,0xeb,0x36,0x9e,0x9e,0x11,0x57,0x82,0x92,0xde,0x5b,0x6a,0xf5,0x34,0xd4,0x23,0xff,0x24,0x0f,0xa2,0x6e,0x21,0xa7,0x81,},{0xf5,0x8f,0x39,0x6b,0xa2,0x7e,0x06,0x7a,0x5f,0xe0,0x03,0xe3,0x85,0x58,0x2a,0xe3,0x49,0x0e,0x05,0x95,0x77,0x15,0xd7,0x04,0xda,0x0d,0xa6,0x3a,0x64,0x19,0xd2,0xe4,0xf6,0xdc,0x66,0xb7,0xe8,0x8e,0x42,0x8a,0x6f,0x21,0xb9,0xea,0x20,0x22,0x99,0xa3,0xc3,0x6b,0x24,0x2b,0x0e,0xa0,0x64,0x76,0xff,0x12,0xd0,0xb6,0x58,0x0c,0x04,0x03,},"\x68\x82\x45\x6c\xc3\xd1\xad\x0d\xaa\x9b\x88\xef\xf0\x96\x9f\x15\xe9\x7b\x48\xd0\x51\x96\x7e\x13\x90\x84\x72\x25\xf2\x6a\xc2\x55\x59\xf0\x24\x6b\xf7\xd6\x83\xfa\x28\xec\xed\xad\x21\x49\x1d\x77\xbd\x26\x96\xfa\x83\x5d\x0f\xd1\x19\x88\x4f\xec\xe9\xd8\x03\x69\x1b\x2f\xd3\xde\x17\xee\x08\x7c\x74\x00\x7a\x7d\xe9\xbc\x65\x34\xbb\xfe\x95\xfd\x32\xe9\x7c\x37\x5f\x4c\xb6\x57\x31\xaa\x1e\x83\x46\xbe\xa2\x1b\xe9\xf2\xc3\xdc\x87\x4a\xf0\x43\x19\x06\xcc\xbc\x2c\x60\x01\x27\xf4\xd3\xb0\x69\xeb\x09\x1d\x16\x5e\xc4\x53\xe6\x72\xe9\x3c\xae\x8b\x72\xf0\x33\x71\xd8\xb8\xa8\x24\x4e\xc4\xec\x2e\x09\xf3\x1d\xf4\x02\x06\xa2\xb1\xc8\x4c\xaa\x1b\x99\x3c\xc6\x75\xfd\xe1\xc7\x9b\xd4\xa7\xd1\x59\x74\xfa\x29\xce\x2e\x89\x2c\x28\x99\xcf\x48\x2c\x3d\x96\x63\xf6\xd2\xa7\x97\x84\xf4\x1c\x1f\x58\x66\xd3\x7c\x85\x46\xf3\x57\xd5\x64\xd3\xc4\x21\x8d\xfa\x6d\x20\xb6\xc2\x82\xb4\x00\xfe\xdd\xe5\x24\x39\xd4\x72\x21\x2c\x57\x67\xa3\x5d\xa5\x20\x10\x32\xda\x87\x30\x96\x8b\x07\x20\xe8\xa6\x04\xde\x6c\x1b\xaa\x3f\x4e\x89\x6a\xc2\x61\x4f\xb1\xab\x6e\x3f\x6c\xf3\x87\xa8\xeb\x2f\xf8\xa9\x21\x47\xab\x34\x92\x38\x43\x2e\x50\x9d\x82\x9c\xb7\x5b\x2c\x17\x65\xc5\x12\x21\x84\x8e\x25\xaf\xff\x5f\x16\xe4\xdd\x0c\xd5\xc9\xf7\x13\xc4\xaa\xab\x2c\xe8\x36\xf8\x49\x45\x06\xb5\x30\x9d\xc2\xb0\xae\x74\x5b\xb9\xc4\x79\x80\x98\xfb\x86\x41\xd5\x20\xa0\x8b\x02\xf7\x5a\xd8\x0d\xbc\x2c\xe2\x9e\x89\x0b\x4d\x72\xa3\xff\xb2\xa1\xcb\xd5\x38\xe1\x22\x9f\x57\x9c\x29\xae\x66\xbc\xa8\x5e\x0f\xa0\x8c\x86\x47\xa1\xab\xcf\xe8\xa4\x9f\x5e\x50\x8d\x4d\x24\x95\x55\x66\x23\xd9\x26\xce\x49\xef\xa4\x35\x0a\xaa\xab\x5c\xec\x2c\xd8\x85\xbe\x1d\x63\x47\x5e\x3b\xab\x7c\x7c\xdc\x8d\x65\x61\x73\xb8\xd4\x56\x02\xf4\xb3\xd2\x81\x24\x1d\x17\x19\x03\x27\xb2\x4c\x38\x36\xb1\x93\x11\xa1\x93\xaf\x86\xa6\x76\x8f\x04\x85\x2a\xb0\x6e\x67\xc8\xea\xd5\x91\xcd\xcb\xf3\x78\x9c\x61\x32\x09\xcf\xe0\x3f\x58\xc0\x30\x5f\x63\x20\x3b\x48\x7f\x7c\x5f\xc0\x98\x87\x7e\xc9\x8a\x68\x9c\x9d\x35\xaf\x81\xe8\x40\x78\xd6\x6f\xe9\xe4\xec\xcb\xb1\xcc\x6c\x71\x99\x1c\x03\x01\x7b\xb8\x11\xf4\x1f\x07\xde\x68\xfa\xd1\x94\x14\x60\x61\x32\x4f\x3d\x0e\xf2\x17\xa5\x4c\xf3\x8f\x7a\x62\x5a\x38\x86\x9f\x67\xd0\xb7\x43\x1d\xf9\x37\xcd\xe3\x49\xc1\x75\xce\x8b\x26\xac\x88\xd3\x9a\x43\xe2\x79\xb0\x18\x76\x4e\xfa\x4d\xd6\x27\xcb\xf5\x91\xf6\x20\x9c\x4a\x5b\xb1\x9e\xbf\xa7\xc7\x13\x55\x92\xd0\x2e\x50\x1c\xae\x5e\x6b\x31\xc9\x0e\x72\xfa\xab\x47\xf7\xdc\xed\x2c\x48\xad\xf8\x84\x43\xb3\xed\xe6\x0c\xef\xb0\xd6\x37\x9d\x69\x22\xec\x43\x7f\x08\x6b\xad\x62\x17\xd4\xd4\xff\xef\x18\xe2\x25\x23\x66\x4b\xf4\xe9\xca\x1e\x65\xa2\x8c\x2a\x7a\x60\xc5\xf6\xbc\x90\x6b\x73\x7c\x29\x93\x5f\x90\x97\x46\x30\x48\x57\x5b\xef\xd1\xa2\x54\x9d\xc4\x74\xb1\x3e\x68\xae\xec\xf1\x66\x04\x3e\x07\x5a\xac\x51\x55\x40\xf8\x31\xb4\x30\x66\xce\xf9\x32\xe6\x3d\xcd\x5b\x37\xb6\x15\x78\xc3\x5b\x09\xe4\x5c\xc2\xa8\xde\xf5\x71\x03\xed\xfc\x5f\x64\x98\x31\xa8\x96\x1f\xe4\xa4\xb3\x72\x1f\x1d\x6d\xf4\xea\x9f\x03\x38\x81\xb4\x74\x30\x0e\x0f\x12\xcb\x9c\xd3\xba\xbd\xcf\xfb\xb9\x18\xdd\x9b\xb0\xe2\xf5\xb2\x10\x33\xe4\x30\x23\xa0\xd2\xe6\x6d\xa3\xab\x0f\x07\xee\x98\x8b\x16\x88\x9c\xa5\xd5\x1a\xbd\xc0\x5f\xde"}, -{{0x33,0x47,0xdc,0x47,0xbb,0x3d,0x2e,0x5d,0x02,0x86,0xac,0x06,0xa5,0x4f,0xd9,0x21,0xc9,0xe9,0x6b,0x68,0x99,0x86,0x2a,0x54,0xe5,0xcc,0x81,0x15,0xd3,0xd0,0xba,0x99,},{0xd0,0x0b,0x64,0x5d,0x86,0xdb,0xb7,0xe5,0x24,0x75,0x7e,0xc7,0x78,0xc6,0x2b,0x7e,0x60,0xd0,0xb6,0x57,0x68,0x83,0x33,0x8c,0x9b,0x67,0xc2,0xc7,0xe4,0x50,0x92,0x68,},{0x9a,0xb4,0x29,0x9b,0x17,0x72,0x93,0x44,0x75,0x0b,0x69,0xdc,0x60,0x37,0x36,0x8c,0x98,0xf4,0x7b,0xe6,0x27,0xfb,0xd9,0xad,0xfd,0x8d,0xb3,0x9f,0x99,0x64,0xdd,0xb7,0xbc,0x92,0xd6,0x74,0xc7,0xbe,0x74,0x07,0x56,0x39,0x6b,0xaa,0xee,0xac,0xbf,0x74,0x94,0x7b,0x61,0x91,0xc6,0xed,0x1f,0x5d,0x32,0xa6,0x3d,0xf3,0x6d,0x54,0x26,0x01,},"\xe2\xf4\x8e\xdf\x9d\x64\x33\x20\xab\x99\x1c\x8f\xf9\xf6\xaa\x75\xfe\x06\x6e\x7d\x88\xff\x1e\x47\x2a\x5a\xc9\xc5\x18\xde\x1f\xb6\x29\x83\xb1\x00\x7f\x64\x22\x80\x91\x17\xbd\xbe\x8a\x0e\x57\x87\xf6\x6b\xb0\x57\xd2\x7f\x12\x9a\x20\x0b\x40\x57\x6e\x17\x19\xcf\x9e\x98\xfc\xb7\x2a\xf9\x4b\xb8\x2e\xe7\x0f\x37\x19\xa2\xe2\xcd\x9b\x64\x77\x7c\xea\x5e\x44\x64\x59\x87\x4b\x74\xbf\xbf\x56\xb2\xd2\x52\x64\x00\x59\x2a\x9b\x45\xa5\xcb\x79\x80\x92\xb6\x0a\x81\xb7\x1d\x82\xf0\x68\x5f\xae\x7f\x81\x0b\x52\xd2\x26\xad\xac\x7a\xd8\xa9\x18\x3f\x09\xfe\xbe\xe9\xd2\x50\x46\xc0\xfe\x30\x66\x81\xac\xe2\xbf\xf9\x1b\x34\x82\xb0\xbc\x30\xb2\x02\x1c\x43\x41\x64\x5d\x67\x51\x34\xfe\x30\x81\xc5\x1e\x5c\x59\xe4\x0b\x37\x5a\x14\x34\xf6\x3b\x42\x6e\x30\x53\x0d\xa9\x35\x3b\xb2\xa9\x42\x32\x20\x43\x4a\xe5\x9d\x7b\x6f\xdc\x14\x3f\x49\x82\xeb\x8c\xfa\x77\x51\xb7\x5b\xf3\xe9\xc9\x13\xc7\x3b\x76\x0b\x07\xd3\x95\x31\x0c\x59\xf3\xb7\x7e\xbf\x12\xed\x2d\x7b\x03\x59\x0d\x33\x17\xaf\x17\xdf\x42\x1e\x78\xb0\x84\x9f\xd5\x6d\x94\x5c\x56\x96\xa0\x40\xfc\xaa\x78\xa9\x3e\xcc\x16\xd5\xac\x34\x45\x06\x36\x11\xf3\x01\x3e\x9a\x3a\xe2\xe1\xc2\x70\xdd\x01\xa8\xff\xe3\xe6\x12\x6b\xc1\xe4\xc9\x5f\x65\x47\xa8\x65\x1f\x26\xb6\x40\x4e\x39\xee\x4c\xe7\x61\x89\x18\xf3\xf9\x37\xa5\x25\x73\xec\x27\x7b\x77\x1e\x91\xad\x09\x6f\xa1\x5c\x7a\x34\x0a\x80\x9b\x47\x03\x18\xa4\x63\x64\x23\xeb\x48\x88\xa1\x21\x60\xc4\x66\x3f\xce\x29\x96\xd6\x38\x89\x6c\x83\x9b\x2c\x7a\xd4\xb3\xa9\xb2\xe6\xcb\x71\xe9\x12\xfe\x39\xb8\x43\xc6\xe0\x83\x2e\xca\x22\xde\x93\x8b\x50\xae\x86\x3e\x48\x58\x2c\x10\x85\x12\x32\xf7\x5e\x52\x25\xb8\x89\x6b\x5a\x47\x0f\x81\x8b\x6f\xa3\x9e\xb7\xbb\x59\x03\x57\x67\x86\x12\xd2\x5f\xe1\xa4\x0e\xa1\xb9\xd7\x1d\x88\x09\x09\xc1\xbd\x4a\xd1\x76\xcc\x0c\xef\xfd\xce\xe7\x09\x9e\x78\x82\xa7\xc9\x07\xe4\xbe\xc7\x98\x30\xc6\x77\x1a\xcb\x89\x94\x4b\xd5\x4a\x51\x65\xb3\x18\x70\x91\x69\x21\xb1\x98\xac\xd4\x43\x2e\x7e\xed\x8c\xe1\xde\xb3\x45\xb1\x07\xed\xa7\x60\x26\x6f\xcb\xda\x3b\xa5\x22\x94\x00\xa3\x03\x60\xa4\x64\x5c\xa8\xdb\x38\xc3\xd5\xf4\xa8\xde\xf1\x57\xbb\xdb\xbf\x2c\x1f\xa1\xdc\x6b\x05\x14\xa4\xf5\xa0\x36\x4f\x92\x83\x81\xb4\x0f\x95\x57\x9a\x26\x46\x7f\x22\x82\xa8\xa2\x55\x75\x84\x02\xac\x9c\xa8\x0e\x89\xb9\xcc\x68\x60\xa3\x4b\xb3\xf9\x0c\x32\x37\x65\x7c\x21\x29\xea\x48\xc8\x52\xb9\x25\x69\xe8\x11\x06\xbc\xe4\x61\xe2\x02\x44\x54\x82\x1a\x91\x75\x92\xd1\x99\x1b\x5b\x69\xf2\x7b\xbe\x01\x99\x77\x52\x8a\x2f\xc0\x11\x92\xc5\x6b\x4a\xea\x87\x3c\xf8\xc5\x8d\xfd\x7c\xb4\xb0\xe9\x17\xe8\x7a\x87\x04\xc9\x92\x82\x0f\x98\xd7\x74\x04\xd3\xf1\xd2\x05\x0c\x67\x43\xf6\xe9\x3c\xdb\x51\xa6\x1a\xa6\xf4\x5b\x35\x1b\x26\x46\x1d\x13\x29\xf3\x15\x12\x72\xac\x39\x62\x34\xd0\xd6\x7c\x17\x8a\xcf\x91\xfc\x51\x0d\x86\x42\x9c\x69\xa8\x7f\xdf\x10\x11\x55\xda\x8d\x94\xde\x67\x22\x23\x8a\x6f\xb1\x70\x16\x86\x2b\x11\xd5\x02\xc6\x67\xee\x9c\xa0\xaa\xbe\x1c\x20\xb9\x77\x89\xf1\x86\x7a\xdd\x78\xb8\xb8\x7e\x9a\xb5\x19\x34\xc0\xb4\xa1\x6c\x2c\xbc\x4d\x2e\xfe\xdb\x79\xc0\x5b\x23\xe0\xcf\x78\x92\x01\xac\x75\xfe\x07\x6d\x31\x5f\xcb\xac\x20\xba\x0d\x31\xe4\xdc\x61\x69\x27\xd6\xea\xb1\xb1\xc8\x7a\x1c\x9c\x77\x8e\x4b\xd2\x85\x29\x58\x74"}, -{{0xff,0x15,0xd6,0xe7,0x4e,0x28,0xe4,0x1d,0x05,0xa8,0x66,0x3a,0x70,0x2f,0x03,0x8d,0x5b,0x85,0x78,0xc4,0x27,0x5e,0x77,0x2b,0x73,0xba,0x44,0x0b,0xc5,0xf5,0x5a,0x06,},{0x47,0x47,0xe2,0xe9,0xb8,0x26,0x37,0xb3,0x84,0x4b,0x85,0xf7,0x5b,0x59,0xf7,0x13,0x6b,0x7f,0xdb,0x1a,0x62,0xe7,0xb7,0x0d,0x6a,0xac,0x17,0xb3,0xc5,0x75,0x2f,0x2f,},{0x42,0xc1,0x29,0x5f,0xaf,0xe2,0x6d,0xe3,0xea,0x34,0x92,0x6b,0xf1,0xef,0x80,0xbc,0xaf,0xe4,0x7b,0x21,0xb9,0x0e,0xae,0xd1,0x96,0x35,0xed,0x75,0x38,0xd7,0x67,0xcb,0xf3,0xa1,0xe5,0xde,0xda,0xab,0x82,0xad,0xf7,0x51,0x20,0x37,0x3e,0x92,0x32,0x02,0xf7,0xfd,0xa0,0x82,0x67,0x84,0x29,0x2e,0xba,0x8b,0x23,0x8b,0x6c,0xb8,0x83,0x04,},"\xce\x7b\xf9\x72\x84\x4f\x51\x84\xae\x8e\xac\x87\xb1\x2b\xe9\x20\x2c\x72\x39\x96\x1d\xc2\x3c\xd4\x1f\xf5\x5b\x9b\xfa\xac\x0c\xc0\x6f\x3f\x1d\xec\xfa\x95\x71\x09\x5c\x8e\x82\xb4\xeb\x6f\x8a\x1c\x52\xc8\xd3\xde\xaa\x61\xa9\xaa\x94\xe2\xec\xd9\xab\x5b\x80\x63\xf2\xda\x6d\x80\x15\xdf\x0a\x51\x44\xfa\x3a\x48\xe3\x05\xad\x9f\x41\xea\xa1\x1c\x4d\x74\x85\x43\x74\xec\xbf\x38\x2e\x30\x02\x57\x9a\x9a\x24\x9e\xfa\x1e\x1c\xa0\x4d\x33\x84\x47\xd7\xf2\x20\x67\x03\xe6\xca\xbf\x5b\xbd\x33\x2b\x42\x57\x3b\xcb\xd3\xb6\xf7\x1b\x7c\x3b\xf7\x3d\x4c\x77\x4a\xa0\x1e\x86\x68\x41\x43\x28\x29\xd0\x7f\x96\xe1\xf6\x1a\x20\x21\x6d\x96\x8c\x90\xe3\xed\x11\xf6\x63\xf7\xd6\x27\x16\x22\xfe\xfc\xf3\xab\x68\xf3\x44\x32\x85\x15\xd5\xcc\xe2\xce\x85\xe8\xbf\x3d\x1d\x09\x04\x36\x92\xe1\xfb\x8b\xbd\xdc\x07\xa4\xab\x0a\x3e\xef\x8c\xa6\xa4\x20\xe7\x4b\xff\x8d\x3d\x71\x55\x96\xaa\x82\x16\x82\x95\x4f\xe8\x96\x29\xae\x27\xc1\xbb\x03\xb6\xaa\x09\xf3\x6a\x39\xa3\xe3\x7b\xa9\x81\x32\xf4\xe2\x38\x88\xf9\xf3\x35\xe7\xbe\xaa\x2c\xb2\x72\x7a\xcc\x3d\x27\x77\x30\x9b\x85\x29\x52\x32\xe5\x4d\xa8\x8e\xbb\x6f\x10\x53\xd6\xde\x79\xac\x66\x09\x85\x2e\xb9\x3a\x0a\x35\xbc\x1a\x7b\xdc\x22\xd6\x28\xbc\x86\x12\x4d\x69\x6c\x3f\x98\x28\xb6\xf8\xb9\xaa\xde\x1a\x65\x21\x61\x77\x48\x6c\x25\x2a\x4b\x42\xd9\x0a\x4e\x0f\xea\x20\x93\x48\x9e\x24\x4d\x80\x8e\xf7\x02\x1a\x97\xd5\x60\x8c\x0a\xe1\xd6\x63\xc7\x75\xe8\xbb\x9e\x9a\x73\x15\xf1\xfe\xb6\xd1\x29\xb5\xa5\x41\xea\x59\x29\xa2\xc6\x33\xb6\xd8\xc3\xc4\x54\x41\x71\x79\x46\xcf\x87\x3e\x9b\x4c\x51\x21\x80\x13\x5d\x54\xf0\x53\xab\xe4\x4c\x6d\xf3\x9b\x7b\x06\x2e\xf7\x24\x01\x62\xcb\xd0\xb8\x51\xaf\xe5\xf9\x15\x36\xa9\x49\x94\x18\xe8\xbf\xf4\x99\x64\x73\xd8\x05\xeb\xc1\xae\x48\xda\x2d\x0b\x12\x9e\x8e\x82\x52\xf1\xd5\x3c\x32\x8f\x32\xdb\x25\x2d\xe3\xbe\xfb\xe5\xf3\x12\x80\x12\x11\x43\xa8\x00\x4a\x4c\xae\x63\x1c\x82\x74\x09\xe5\x20\xe3\x94\xcd\x0f\x89\x50\xcd\x4c\x3c\xf3\xf3\xdb\xd4\x95\x2a\x4d\xfe\x69\x87\x5f\x56\x53\x89\x06\x1a\xd0\xa0\xce\xe6\xb6\xaf\xf0\x9c\xec\xa2\x6d\x99\x0e\x89\x6a\x2a\xba\x9f\x3b\x26\x01\x5b\x63\x42\x37\x68\x68\x4c\x03\xed\x0d\xe6\xce\xe7\xac\x5b\xbd\xf9\xf4\x85\xc2\x27\x5c\xd1\x2a\xef\xa8\xf9\x07\xb8\x51\xa0\x2d\x51\xc3\x4f\x12\x1b\x77\xf3\xa5\x6a\x9e\xbd\x1d\x65\xff\xe8\x9b\xee\x38\x1f\xf2\xa7\x48\x0e\x89\x68\xcf\xf2\x5a\xc8\xd0\x4e\x14\x9a\x9d\x50\x27\xd1\x4b\x88\xf8\xae\x26\x04\xd2\xac\x22\xac\x67\xd1\x3e\x90\xad\xa6\x20\xc2\x04\x6d\x28\x29\x93\x84\xd0\x95\x9f\xb7\x6e\x22\x58\x87\x96\xce\x42\x7a\xae\xaf\x4e\x2a\x8a\xae\xc3\xe8\x7f\x84\xcc\xd0\x82\x52\x4c\x96\xd7\x66\xee\xc6\x6f\x0b\xec\x3e\x79\x95\x58\x14\x5f\x09\xd3\x30\x13\x4f\x1c\x63\xf3\x70\x53\xcd\x4b\xdc\x1c\x37\xfd\xe9\x72\x91\x85\x75\x51\xf5\x0a\xc8\xe1\x5f\x06\xac\x1c\x73\xda\xa1\xe8\xc5\xbc\x92\x77\xe3\xd6\x9c\xb4\x4a\x32\x37\xec\x57\xdb\xbc\xcf\xdf\x66\x85\xad\xa2\x0b\x74\xa1\xbc\x6b\x74\xab\x05\x69\x0e\xaf\x9b\xd0\xc4\xbe\x17\x04\x2f\x5c\xd3\x20\xcd\xd6\x13\xdc\x08\xd2\x9a\xf3\x46\xaa\x41\x91\xce\x0b\x4f\x85\xbb\x2a\xd7\xf3\xba\xc7\x38\xa9\x37\x7e\xc6\xb8\x40\x62\xcc\x70\xfc\xa9\xec\xfb\xe1\xf5\x7f\xe5\xb2\xce\x7a\x4f\x73\x9c\x81\xca\xbc\xde\x04\x64\x51\xdd\x61\xce\x1d\xbc"}, -{{0x1e,0xd3,0x7b,0x61,0x0b,0x8b,0x35,0x41,0x7d,0x04,0xe5,0x9a,0xaa,0xda,0xc6,0x88,0xff,0x81,0xf1,0xe5,0x07,0xc8,0x9b,0x4f,0x40,0x01,0x60,0x94,0x19,0x08,0xcb,0x8c,},{0x48,0xe8,0xcb,0xeb,0x12,0x40,0xbd,0xeb,0xf0,0xa2,0xd9,0x29,0x53,0xaa,0x89,0xb2,0x82,0xc4,0x9a,0xab,0x2c,0x38,0xae,0x69,0x04,0x4c,0x51,0x51,0x5c,0x33,0x00,0xd5,},{0x86,0x08,0x81,0x5e,0x10,0x59,0x0d,0x55,0x04,0x87,0x4d,0x89,0x99,0xfd,0x6f,0x09,0x62,0x6f,0x95,0x0b,0xe2,0x0c,0x91,0x2c,0x27,0xc9,0xde,0x6e,0x79,0xb0,0xfa,0xf7,0x77,0xa5,0x33,0xbd,0x5b,0xb6,0x67,0xab,0x51,0x3a,0x49,0x45,0x8e,0xcd,0x67,0x87,0xa0,0x9e,0xc0,0xdf,0x6c,0x9c,0x9d,0x63,0x33,0xc5,0xe3,0xae,0x61,0xea,0x37,0x0a,},"\x1e\x67\x67\xdf\x97\xdb\x1c\xfb\x40\x88\xda\x7b\x20\x0d\x9f\x59\xec\x8d\xd4\x53\x3b\x83\xbe\x30\x9f\x37\x65\x00\x31\x06\x57\x27\xcd\x52\x02\xce\xf4\x84\x26\xa5\xf3\xa1\x1d\x50\xb3\x81\xf8\xbc\x22\xff\x10\x18\x27\x35\x9f\x2d\x0a\x61\x0a\x4f\x75\x54\x64\xa0\xc8\x91\xcb\xd9\x8d\x2d\xcb\x41\xd9\x77\x9d\x28\x8f\xcf\x1f\xea\x62\xe5\x21\x63\xae\x67\xe9\x04\x28\xb8\x63\x98\xef\xa2\x18\xf1\xb9\x82\x08\x1f\xc5\x13\x30\x5f\xd3\xe8\xec\xe7\xf9\xac\xb0\xe1\x0e\x00\x1d\x2e\xd2\x99\xa4\x8a\x80\x87\x0b\x3d\x5d\x8a\xb9\x00\x63\x09\xb3\x15\x91\xca\xf0\x58\x33\x80\x07\x3a\x2d\xb6\x1f\x45\x25\x4a\xb9\x65\xb5\xe4\x67\x2c\x4b\xfa\xa8\x6e\x33\x6c\x49\x27\x85\x52\x72\x9f\xb2\xda\x76\xff\xe5\x02\xec\x61\xe1\x69\x6c\x7f\xc9\xef\x19\xf7\xcc\x2a\x27\x75\xb2\x97\x00\xcb\x38\x42\x94\x06\x3a\x17\xfe\xd4\xfc\x63\x5b\xc1\x32\x82\xa9\x0d\xad\x0c\x00\xaa\xdb\xcd\x56\x9f\x15\x6a\x85\x4f\x8b\xa9\xe7\xd6\x07\xd2\x0f\x2e\x9e\x53\x37\x98\x11\x61\xd8\x04\x64\x46\x68\xd0\x64\xfa\x63\xdc\xeb\x9f\x58\x01\x35\x3d\x0a\xb9\xf4\x1d\x1d\x8b\xdc\x76\xc1\x3a\xb2\xf0\x23\xea\x01\xad\xbc\x4c\x81\x68\xd9\x39\xe9\x8f\x64\xfd\x89\x19\x38\x4a\xbe\x76\x70\x92\x63\xc0\xcd\x7c\x3e\xfa\xdc\x28\x01\xcc\x4a\xbd\x80\xa0\x9b\xb3\xed\x6b\xb7\x8c\xd6\x20\x96\x9c\xd3\x5c\x6a\x3a\x5d\x01\x48\x5e\xad\x4c\x45\xeb\xb6\xac\x6a\x83\x21\x2a\x7c\x76\x67\x54\x27\xb2\x1d\xa8\xa7\xa5\x04\x7b\x30\xa6\x10\x0c\xda\x02\x47\x6c\x18\x6e\x6c\xe4\x0d\x27\x68\xa9\x42\xc9\xf8\x73\x05\xe9\xd3\x63\xb5\x24\xc0\x09\x4a\x9e\x2e\x29\xf5\x85\x89\x4c\x0a\xdb\xfc\xd6\x06\x90\xfc\x7f\xb0\xa9\xc7\x17\xcf\x43\xb4\x84\xfd\x45\x15\x1b\x13\x04\x16\x9c\x26\x92\x1d\xb2\x27\x6e\xc0\x5a\xd2\x2a\xd1\x66\x85\x4f\xd2\xf9\x40\x85\x77\x8c\x47\x0d\xc4\x52\xe5\xcf\xa4\xae\xe0\x4f\xac\xb7\x70\x52\x6e\x1f\x24\x8d\x3d\x15\xc2\x72\x80\xfd\xfa\x1f\xd2\xc1\x04\x4b\xcb\xc8\x81\xc3\xd9\x98\x15\xc9\x7f\xbe\xa4\x61\x10\xbe\x02\xda\xb7\x74\xf3\xa6\x10\xe5\x80\x2a\xbf\x36\xa4\x98\x75\xc6\x82\x63\x8e\x0a\xe4\xcc\x82\x77\xc5\xe9\xaa\x73\x07\x44\x5e\x6b\xbc\xbe\x54\x9e\xec\x2a\x45\xb1\x59\x7f\x74\x47\x10\x7b\x62\xe2\xce\xe0\xa5\xfc\x51\xbe\xae\x3e\x1f\xe9\xbe\xfb\x18\x85\xd9\xb3\x0f\x9b\x4f\x1f\x56\x20\x6d\xee\x0d\x67\x77\x9c\x57\xf4\x84\xc8\xc3\xc8\x99\xa5\x15\xa9\xd1\xc1\x0f\x60\x59\x84\x0c\x1c\x73\xd3\xf0\x5b\xcb\x88\x59\x0c\x52\xf7\xda\x39\x18\x38\xdc\x2e\x73\x22\x8f\x09\x81\xc2\x89\xa4\xc2\x7f\x0c\x75\x7f\xaf\x7b\x3b\x89\x14\x6e\x33\xda\xfa\x49\x0d\x9e\x0f\x92\x75\xb0\xcf\xa6\xa7\x71\x0a\x73\x83\x14\x59\x59\x5b\xf7\x32\x11\x2b\x62\xfc\x86\x4c\xa4\xc8\x29\x78\x4a\x3f\x16\xee\xc4\xe1\x8f\x93\x69\x18\xa7\xb9\x89\x16\x69\xe9\x33\x22\x3f\x74\x5f\xda\x56\x2b\xc0\xa4\xe6\x1e\x3d\x14\xea\x45\xdf\xc3\x27\xe2\xfc\x0c\xdf\xe6\xf2\xf9\x75\x46\xc9\x0f\xce\x82\xf5\x22\x29\x14\x80\x11\x1a\x1e\x6b\x93\x88\x27\x2c\x0b\xe2\x8d\x20\xed\x84\xbb\x84\xd4\x9b\xc1\x99\xcd\x59\x99\x48\xb8\xf2\x03\x9d\x07\x82\x7a\x3f\x40\x75\xd3\xa6\x7e\xe5\x72\xa0\x13\x79\xa3\x62\x13\xfe\x11\x6e\x76\x8b\x41\x14\xe8\xa4\xb3\x13\x4c\x38\x18\x96\x07\x72\xd7\x27\xb0\xca\x6f\x7c\x99\x7c\xa9\x98\x43\xb7\xeb\x02\xff\xc0\x13\x97\x1c\xbe\x0e\x6e\x60\xd4\x97\x73\xf1\xe8\xc0\xb3\x06\x06\x13\x1c\xb1\x0c\x3e\x04"}, -{{0x84,0x36,0x44,0x78,0xec,0x94,0xbd,0x25,0xc4,0xbd,0xb8,0x2d,0x29,0x62,0x29,0xe6,0xda,0xce,0x2b,0x13,0x59,0xd6,0xd2,0x1b,0xe2,0xb3,0xaf,0xcd,0x7b,0xda,0x19,0xc7,},{0xa1,0x81,0x4f,0x8c,0xe0,0xfc,0x3b,0x23,0x60,0x93,0xa5,0x0f,0x46,0x8c,0x13,0x16,0x21,0x1f,0xe6,0xc5,0x2e,0x23,0x45,0xd9,0xf0,0x76,0x6b,0x36,0x88,0xa0,0x3c,0xad,},{0xb4,0xc2,0x32,0x1a,0xde,0x3c,0x19,0xed,0x4e,0xd4,0xc6,0x39,0xd5,0xa4,0xd6,0xf2,0xbe,0x8e,0x2f,0xb1,0x3b,0xb7,0xbd,0x62,0x5a,0xd6,0xdc,0x87,0xe2,0xc2,0x0f,0x93,0xad,0x6b,0xe7,0xb7,0xe4,0x27,0x11,0xa8,0x78,0xdb,0x9d,0x76,0x05,0x4b,0xfd,0x7b,0xc2,0x5e,0x37,0x74,0xa9,0x3d,0xa1,0x54,0x3c,0x9b,0x4f,0x66,0x33,0xb0,0xbe,0x09,},"\x7b\xb7\x29\x3d\xe5\x5f\x05\x8f\xb2\xec\x22\xb6\x87\x26\x05\x43\xdc\xaa\x90\xf1\x40\xb9\xf4\x5e\xdd\xd4\xbc\x22\xe4\x09\x77\xe0\x0e\xd3\x3c\xd1\xef\x1b\xba\x13\xc1\xd0\x99\x08\x59\x00\x55\x69\xa8\x07\x67\xe4\x86\x4a\x2c\xd2\x88\xc8\x13\x93\xe0\x4a\xd9\x71\x78\x2e\x2b\xc4\x93\x10\x8c\xbe\x80\xda\xcf\x0b\x7b\x9c\xd5\x34\x98\x84\x07\xa4\xf9\x32\x7e\xc8\xe9\xc4\x04\x32\x84\xef\x6e\xe5\xa2\x6a\x5b\x41\x77\x65\xd3\xea\xbb\x48\xa0\x07\xe7\xc7\xf3\x29\x87\xd7\x0a\x13\x9a\xc4\x16\x78\xcd\xf7\xa5\x5c\xb8\x0c\xf9\xdb\x5e\xaa\x45\xf3\xde\x0f\xbf\xba\xdf\xfc\x40\x99\x63\x70\xe4\x8b\x1f\xf5\xed\xd9\x79\x40\xe7\x50\x79\x21\x64\x83\x6a\x4a\x5a\xc2\xe3\xff\x53\xe4\x8a\x1e\x55\x6d\xb9\xad\x0c\x5c\x0b\x94\x4f\x4a\xee\x51\x9a\x2b\x0a\x88\xbb\x1c\x1f\xc7\x45\x45\x24\xcd\x57\xaa\x53\x50\x98\x62\x43\xd3\x4f\xc5\x8e\x24\xe8\x19\xec\x0b\x85\x45\xd8\xdf\xcf\x6b\x20\x31\x14\x41\xd3\xa3\x5d\x3e\x71\xb3\xe3\xec\xd7\x88\x4d\xda\x84\x33\xa4\x05\xe3\xd9\x96\x90\x00\xc8\x20\xa8\x9b\x95\xd1\x97\x84\x1d\x98\xae\x73\x4a\x2e\x81\xda\xf6\xa7\xdc\xf5\x6c\xb2\xfc\x26\xf2\x16\x5a\x5f\x42\xb8\x6c\x7e\x9e\x5b\x11\x16\x17\x00\xa1\xab\x98\x31\xf3\xfa\xe5\x8e\x14\x20\x8b\xe1\xbf\x33\xb5\x8e\xcc\xe8\x1b\x0c\x6b\x7e\x02\xf8\x8a\xdf\x9a\xb0\x30\x26\x3e\x2c\xc9\xb6\xe3\x3e\xbc\xa3\xf4\x95\x49\x2e\x32\xbf\xe3\x72\x53\x7d\xe6\xc6\xb8\x76\x44\x82\x8f\x74\x94\x2a\x02\xb0\x07\xf1\x4c\x3f\xc5\xdb\xde\x76\x33\x3d\x36\xd0\x76\x31\xb7\xa9\x92\x4f\x71\x75\x50\x04\x06\x97\x92\x3f\xa7\xb9\x54\x6b\xfb\x02\x17\x02\x4e\xa3\xf2\x52\xb5\x15\xb5\xd6\x4a\x62\xc4\x8e\x02\x7c\xef\x67\x50\xbe\xda\x49\xa0\x24\x47\x03\x9b\x25\x0a\x0b\xda\x07\xdc\x06\x24\x91\xa6\x62\xe2\x68\x74\xc8\xd0\x0f\x80\xe6\xcf\xc8\xb3\x0f\x2c\x3b\xf7\x72\x0b\x57\xf2\x61\x5f\xc4\x78\xfe\xfa\xa6\xd3\x17\x05\xb4\x3c\x5a\x54\xf7\x58\x66\x6b\x30\x2a\x8d\x34\x95\x31\x31\x94\x1b\x79\x57\x73\x04\x76\x79\x4d\x0b\xd9\xd2\xdf\xa7\x2f\xd2\x03\xf2\x2d\xf5\xec\x6b\xba\xac\xe8\xb9\x39\x4b\xeb\xda\xea\xa5\x61\x46\x10\x11\xb4\xfc\xa6\x18\x5c\x9a\x38\x28\x3f\x54\x03\xfd\xac\x32\x6d\x1f\x73\x4c\x6a\x5d\xed\x67\x24\xd9\xf3\x84\xae\xbd\x6c\xab\xfc\xbe\xc1\x2a\xba\xb9\x82\x0d\x08\x07\x32\x51\x5e\x05\x00\xcf\x5d\x3e\x2f\x9e\xf8\x0a\x4d\x76\x46\xa7\xda\x9e\xff\x41\x0f\x50\x7c\x69\x87\x3b\x32\xd5\x40\xec\x32\xb2\x83\xef\x31\x79\xa4\xc6\x32\xb3\x66\x57\x6d\xff\x05\x8f\xaf\x8c\x8c\x70\xbc\x69\xbe\x80\x89\x82\xec\x14\x97\xae\x89\x11\xb0\x01\x65\xa6\x66\x95\xf4\xd3\xb9\x87\xe7\x39\x0b\x5c\xf8\x78\xe3\x5e\x67\x65\x41\x28\x5e\x4e\x13\xdf\xae\xb2\xf3\x68\xcb\x51\x1b\x77\x8b\x10\x6a\x42\x87\x78\xa1\xb8\xf2\xa7\xd2\xe0\x93\x51\x9b\xc9\xb5\x18\x8e\x38\xc6\x79\x3e\x96\xbd\x0d\x30\xe2\xa3\xdb\x9e\xe1\x46\x8c\x3d\xc8\x7c\xc3\x65\xc8\x10\xf9\xdb\xdf\x01\xa4\xb5\x14\x21\xf6\xfc\x8d\xfd\xa3\xa1\x6e\x2d\xa7\xca\x71\x59\xb6\x86\xa5\xe1\x67\x33\x89\x37\x88\x2f\xf7\x15\xd3\xe7\x50\xd9\x58\xfc\x9e\x4b\x1f\x05\x53\x12\x92\x99\xaa\x84\x30\x18\x3e\x50\x6c\xd7\xf2\xb2\x79\x07\x6e\x0e\x1c\xca\x97\x49\xcf\x12\x3c\xe5\x07\xfe\x07\xdd\xbb\xc4\xdc\xca\x6c\xdb\x9e\xf1\xb8\x33\xf6\x1d\x4b\xff\x00\xbe\xc0\x12\x15\x8f\x43\x2c\xeb\x75\xb4\xf2\xed\xb1\xbb\x84\xe5\xeb\xb9\x25\x9e\x09\xf9\x62\x5c\xe3"}, -{{0x00,0xdb,0x37,0xad,0x2a,0x19,0x5f,0x08,0xa0,0x84,0x40,0xd0,0x59,0x25,0x9e,0x53,0x9f,0xeb,0x40,0xb4,0x74,0x92,0x82,0x55,0xe7,0xc9,0x4e,0xbc,0x3b,0x05,0x03,0x8c,},{0x04,0xf8,0x8b,0xf6,0x39,0xe0,0xf7,0x1a,0x57,0xd0,0xd0,0xaf,0xff,0x5f,0xe9,0x7d,0xde,0x38,0x09,0xff,0x28,0xec,0x68,0xeb,0x6f,0xc4,0x23,0xf4,0xfa,0xff,0x43,0x90,},{0xf4,0xd1,0xc8,0x0f,0x5e,0x7b,0x91,0xc5,0xc7,0xa8,0x2a,0x68,0x2d,0x49,0xba,0x6f,0xb1,0x9d,0x40,0x0a,0x29,0x97,0x48,0xa0,0xc9,0x69,0xbb,0x99,0x81,0x69,0x98,0xbe,0x63,0x4e,0x84,0xda,0x78,0x58,0x1b,0x06,0xe3,0x47,0x0e,0xfe,0xc3,0x98,0x04,0xfe,0xd9,0x3d,0x29,0x73,0x9f,0x04,0x39,0xa8,0x09,0x5a,0xc4,0x0d,0x9d,0x38,0x5e,0x04,},"\x5a\x94\xf7\x29\xd3\x0d\xd8\xaa\xe2\xa5\xc8\xc2\x85\x47\xbf\x45\x06\x29\x5d\xc6\x1b\xfe\xad\x97\x27\x74\x60\x82\xd4\x3b\x0f\x81\x14\xc8\xc1\x8c\x5e\xda\xf2\xfe\xc7\xca\xe8\x19\x35\x63\x38\xf0\xbf\x11\x5a\x17\xb0\x38\xac\xfd\x7c\x96\xba\x62\x62\xca\xbd\x57\x10\xfc\x0e\xfb\x43\xd1\x3d\xf4\x06\x5b\xec\xbf\x1b\x9e\x27\x9c\x03\xec\x9b\xbf\xed\x54\xd9\xa1\x3f\xe0\x6a\x55\xa3\xbd\x05\xc8\x07\x85\x8b\x41\xe1\x8d\xbd\xe1\x3b\x09\x07\xd4\x03\x41\x32\x26\x2d\x9c\x2f\x4d\x2d\x37\x6e\x16\x09\xad\x28\x0d\xe2\x0b\xa7\x09\x84\x4d\xbd\x12\x95\x02\x57\xf1\xb0\x7e\xf8\xcc\x33\x37\xc0\x1a\x70\x26\x93\xfb\x4d\x92\xd0\x47\xe6\x98\xc3\xa6\xdd\x46\xc4\xa9\x2a\x10\xd4\xc7\x80\xe5\x2e\x50\x25\xe0\x9d\x56\x53\x5d\x7e\xeb\x9f\xe7\xf0\x33\xe6\xe9\x26\x0a\x68\xf9\xd5\x4b\x6f\x37\xcc\x06\x96\x56\xe3\xbc\xee\x06\x92\x2b\x34\x96\x81\xa8\xe7\x75\x1c\xde\xcb\xe1\xec\xb6\x63\xfb\xc6\xf7\xc8\x61\xf8\x53\xdc\x31\x0f\x33\xde\xfa\x98\xee\x34\x3a\x68\x63\x2e\xc2\x2c\xaf\xec\xb7\xf3\x21\x2f\x81\xe7\x0b\x71\x84\x3b\x9f\xe8\xc8\x6a\x68\xb5\xc8\x6f\x03\x22\xd3\x48\xa7\x6d\xa7\xf1\xba\x0c\xa3\xcd\x7b\x6f\xd1\x5f\xf8\x92\x92\xb3\xf6\x36\xcd\x08\xcf\x62\x5c\x74\xd5\x10\x2c\xab\xb5\x71\xa3\xdb\xa8\x6a\x1c\x92\xf4\x1c\x72\x03\xb4\x49\x42\xf5\xa2\x46\x25\xac\x37\xd7\x7e\x49\xa5\x7f\x11\x82\x38\x69\x9d\x80\x7c\x25\x0d\x5b\xf4\x6f\x7a\x3c\xec\x57\x79\xa6\xe5\xae\x1a\x6c\xa1\x60\xcf\xf3\x7f\xb3\xb7\x83\x88\xfe\x9c\x03\x0c\x40\xe7\x15\x46\x01\x08\x1a\x51\x7f\xc0\xaa\x18\x02\xcd\x3b\x84\x5b\x94\x6e\xfe\x94\xaa\x8b\x9e\x03\xf6\x8a\x80\xde\xd0\xdf\xbf\xad\x4d\xae\xe4\x0f\xa8\x38\xc1\x33\x84\x1a\xe8\xa3\xce\x0d\x79\xfa\x8a\x2b\x94\x34\xba\xc5\xe1\xda\x6e\x0c\x71\x93\xe8\xde\xa4\x35\xa0\x3a\x85\xf7\x61\x84\xf7\xeb\xe2\xaa\x74\x9b\xe9\x41\x31\x04\xa1\x78\x68\x9b\xa6\xd2\x7e\x94\xfc\xcf\x61\xeb\x3a\xba\x0e\x6a\x5a\x63\xaf\x0c\xa8\xf0\x5a\x35\xcb\x63\x70\x51\x94\xe4\x4d\x92\x93\xde\x39\x29\xb0\xd9\x2b\xe6\xf8\xe6\x27\xc3\x50\xa8\x3f\xc9\x00\x0a\xa9\x5b\x93\x82\x0b\xe9\x79\x5c\x80\xb5\x66\x2c\xd7\xb3\x48\x22\x32\x80\x61\x35\x6d\xc5\x80\x57\x8d\x1a\x35\xb1\x01\x40\xdc\xd2\x48\xe4\x85\x31\x04\xd2\xc5\xb2\xc1\x3f\xf6\x83\xdd\x5c\x30\x79\x4b\xe4\xa7\x68\x58\xaf\x1c\x0d\x9a\xf3\x47\xce\x1d\xcd\x97\x2e\xe4\x9a\xac\x12\xbb\xcd\x89\x9c\x93\x29\x87\x1d\x3e\x7a\x06\x83\xd1\x75\x77\x9a\xfe\x35\xf2\x6a\x2d\x24\x8f\xd7\x80\xea\x85\x1d\xc4\xba\x6d\x21\xf8\xa1\x71\xaa\x6c\xb8\x69\x7d\x9d\x11\x21\x61\x54\x03\x07\xcd\x54\xf9\x31\x77\x5d\x70\xb3\x3d\x3b\x6d\xe1\x09\x1f\xc1\x75\x05\x31\xc0\x8f\xa7\x0f\x7b\xe3\x8a\xa1\x10\xd6\x74\x6b\xb5\x65\xdb\x7b\x47\x0f\x90\x08\x50\xfb\xbf\x1c\x66\x2f\xd6\x13\xe4\xf3\xa5\x68\x95\x49\xe3\x10\x7e\x9b\x0f\x17\xde\xf7\xa5\xbd\x7f\xd7\x59\x6c\x4d\x04\xc7\xf4\x8c\x77\x9f\xc3\x5e\x09\x33\x5e\x1d\xf7\x84\x08\x4e\x55\xd8\x55\x1d\x1f\xf4\x9d\xe5\xb3\x11\xcd\x35\x0f\x34\x7a\x0b\xd2\x86\x3a\x2a\x30\xe6\xea\x18\x3a\xd2\xe3\xee\xde\xbc\x18\xdd\x28\xc6\xa5\x96\xe6\x93\xdc\x33\x89\xf7\xd9\x0b\x71\x3e\x3a\x85\xa6\x25\x16\x30\x5a\x70\x66\x7f\xc1\xfb\x3c\xb1\x0e\x8a\x95\x57\x50\x27\x39\x43\xc5\x68\xe1\x07\x69\xce\xf7\x81\x99\xdf\x44\x50\xdb\xc4\x90\xfe\xf1\xb3\x04\xb0\x52\x22\x1b\x2d\xb9\xc4\x4f\xe0\x03\x45"}, -{{0x6c,0xa1,0xa1,0x48,0x2a,0x07,0xf2,0xa6,0xc5,0x7f,0x04,0x11,0x97,0xb3,0x4a,0x51,0x19,0xe6,0x89,0x03,0xcf,0x6d,0xfb,0x51,0x71,0x1d,0x95,0x50,0x97,0x31,0x63,0xc0,},{0x80,0x34,0xa5,0x5e,0x3b,0x6e,0xd7,0x99,0xf4,0x9e,0x2e,0x70,0x3a,0x81,0xf4,0xac,0x02,0x57,0x3c,0x44,0x5d,0x76,0x5e,0x30,0x69,0xbe,0x42,0xf0,0x9c,0xbd,0x18,0xad,},{0xdd,0x9b,0xdb,0xad,0xd9,0xfd,0xc8,0x1c,0xe2,0x30,0x28,0x8c,0x4a,0x06,0x8d,0xf0,0x7e,0x18,0xb4,0xc7,0xcc,0x51,0xc0,0xca,0x48,0x11,0xdf,0xbd,0x04,0x76,0x5c,0x56,0xbc,0x88,0x32,0x40,0xe4,0x6e,0x3a,0x42,0xc0,0x1d,0x8d,0x24,0x24,0xfb,0xc3,0x32,0xb7,0xc5,0xa1,0x7b,0xce,0xb1,0xf6,0xe8,0xda,0xd0,0xbf,0xe5,0x62,0xca,0xd3,0x02,},"\x08\xfd\x84\x87\x50\x3c\x3f\x32\x96\xb6\xf1\xb6\x4d\x6e\x85\x90\x6f\xd5\x98\x6c\xf9\xc5\xd9\xfa\x8a\x59\xd9\x2f\x44\xe6\x47\x0a\xf3\x4b\xcd\xef\x33\x6f\xfd\xc8\x64\x56\xec\x7a\x7b\x57\x61\xf1\xad\xea\x02\x73\x26\x63\x0e\x68\xab\xc6\xb8\xcd\x5d\xdf\x40\xb6\x41\xa2\x59\xad\x02\x43\x21\xbf\x3e\xf9\x8e\x76\x32\x79\x71\x49\xc4\x92\xd5\x35\x94\x75\x2c\x55\x0d\xfb\xc4\xfa\x6b\xf4\x71\x76\xf4\x23\xa2\x70\x56\x93\x94\x7a\xa9\x0d\x68\xdd\xc8\xef\xb6\xcb\x9d\xbe\xca\xfd\x28\x30\xd0\x4f\xd9\x3b\x1e\x9e\x7c\x12\xb9\x3e\x0d\x0f\x3e\x26\x34\x90\x0f\x25\x86\x0d\xda\xdb\xae\xce\x17\x80\xff\x2d\x3f\x3d\x9f\xb8\x38\xfd\x0d\x5d\x66\xf8\xaf\xb3\x05\xff\x1a\x1a\xed\xca\x2b\x97\x4b\x63\xe4\x3f\x5b\x3c\xc9\xdf\xed\x1b\xcf\x11\x99\x91\x76\xed\x95\x85\xac\x82\x9b\xc6\x79\x4e\xf3\xac\xd8\x72\xe8\xd2\xe9\x26\x08\xb3\x20\xf8\x94\x99\x6a\x56\x2e\x1e\xb1\x77\xe2\x1b\xe5\x7c\x22\xc4\x1e\xc2\x59\xa3\xdf\xf9\xc7\xc9\x49\x1d\xb8\x38\xd7\x6c\xf9\xb0\x38\x31\x11\x59\x8e\x35\x7f\x44\xba\xbe\xbf\x12\x1b\xdb\x24\xee\x9d\x55\x7b\x7d\x5a\xf4\x91\xa0\xa0\x36\x5c\x90\x36\x1f\xe4\xf7\xe3\xd1\x3a\x17\xda\x3a\x39\xfd\x43\xf6\x90\xdf\xb0\xb2\xd8\x60\xca\xb4\x19\xf7\x75\xab\x71\x52\xcd\xc8\xf2\xaf\xdc\x50\xe8\xd5\xda\x5d\xa0\x17\x06\xee\xa2\xa2\xff\xad\x4b\xab\xee\x8b\x03\xda\x33\x6a\x4d\x84\x3d\x9d\x7e\x0a\x93\xf3\x6a\x92\xe6\x61\x0a\x36\x8b\x63\x13\x3f\x05\xa3\xfd\xc5\x5e\x3e\x1a\x44\x0b\x0f\x87\xa5\x33\x64\xc1\xd3\x72\x42\xc5\x7a\x10\x9e\x6d\xf6\x93\x45\xb0\x1c\x21\xc1\x08\x9e\x79\x0a\x66\xf4\xf3\x38\x0d\x3b\x76\xff\xb4\x20\xdf\xe1\xe6\x20\x0e\xac\xe5\x79\x26\x5a\x42\x7f\xbd\x35\x55\x14\xef\x95\x3e\x1a\x6e\x96\x8e\x37\x02\x1b\x3c\x6a\x29\x0d\xcd\x02\x93\xda\x67\x68\xda\xd7\xc6\x63\x11\x63\x30\x51\xc0\xac\xcb\x0b\x91\x65\x46\x4d\xfd\xdf\xde\xd2\x3b\xd1\x3e\xf9\x08\x74\x4f\x9c\x21\x11\xdc\x15\x31\x42\xd2\xf1\x05\x34\xd8\x93\xfe\x0b\x54\x5f\xec\x53\xfd\xb3\xb3\x5b\x51\x83\x98\xb0\x2a\xb2\x17\x91\xfa\x97\x7e\x30\xcf\x4b\x40\x4e\x7a\x29\x9d\x37\x87\x10\x8b\x83\x6a\xa0\xd5\x9c\x11\x4f\x1f\x36\x71\x9a\x7a\xcf\x85\xac\x99\x4d\x9c\xb7\x23\x06\xf2\x58\xf7\x8a\xc0\xa3\xb6\xc0\x53\x43\xe0\xb7\xa9\xaa\x72\x6e\x52\x26\x7e\xdf\x97\xf4\x97\x2f\x76\x64\xf4\x37\x20\xad\x33\xce\x6e\x61\x54\x40\xe3\x65\x37\xcb\xc5\x69\xbd\x6f\xf9\x4f\xfd\xae\xa5\x1e\x06\x02\x9d\xae\x78\xc5\xb9\x15\xc5\x37\xca\xea\x6f\x15\x04\x14\x79\x79\xb8\xaa\xae\x0b\xcd\x96\x18\x43\x7e\xbe\xd0\xb5\x5e\xfa\xec\x32\x0e\x84\xc7\x59\x59\xa3\x7a\x26\x0a\x02\xd4\xef\x1b\xb6\x26\x41\x52\x0f\x1a\x03\xdd\xea\x8c\x4c\x1d\xe8\xd7\xfa\xc5\x8d\xa4\x08\xb0\xab\x47\x57\xa1\x35\xf1\xd0\x75\xc9\xf7\xc9\x9f\xb9\x9d\xb9\x42\x7c\xe9\xb0\xd6\x26\xcb\x1a\xc1\x89\xad\x86\x63\xd7\xa7\x14\xfb\x5c\xd1\x58\x5c\x3b\xf9\x9a\x0a\xa4\x6d\x76\x39\x78\xd0\xb1\x2d\x65\xc4\x38\xbb\xb7\x3f\xea\xa5\x1b\xa2\x6a\x45\x9e\x7b\xea\x25\x43\x94\x66\xc0\x86\x13\xe4\x25\x40\xc8\xc6\xd5\x43\x67\xf2\x21\xfc\xce\x0c\x5e\xb6\xaf\x2f\xaa\x18\x1e\xa2\x15\x21\x80\x9b\xe7\x56\x49\xcf\x8d\xee\x76\x71\xdb\x7f\x94\x8f\x34\x6c\xbd\x03\x02\xbf\x9a\x06\xea\xbc\x72\xe2\xe5\x12\xb3\xdf\x88\x5f\x6d\xaa\x39\x8f\x93\xe3\x6d\xae\x2d\x6a\x04\x47\x81\x21\xf9\x77\x87\xd4\xce\xdf\xf6\xdb\x09\xaa\xf1\x0f\x27\xb1"}, -{{0x27,0x84,0xdf,0x91,0xfe,0xa1,0xb2,0xd2,0x1d,0x71,0x3d,0xe2,0xed,0xc6,0x65,0x24,0x51,0xa0,0xc1,0x59,0x54,0xb8,0x65,0x60,0x62,0xea,0x1d,0xed,0xc2,0x44,0x5b,0x2a,},{0x95,0x56,0xdb,0x53,0x70,0xf8,0xfb,0x3c,0x74,0x78,0xde,0x03,0xd2,0x3d,0xf1,0xcd,0xa9,0x6f,0x27,0x40,0x11,0x8e,0xfd,0xd3,0xd1,0xa9,0xfa,0x4c,0x3b,0xfe,0x88,0x49,},{0x17,0xd1,0x71,0xd9,0x46,0xde,0x35,0x16,0x15,0x84,0x07,0xe1,0x32,0xcc,0x1a,0xce,0xca,0xef,0xd6,0xd0,0x92,0x11,0x2b,0xe6,0x53,0x99,0x95,0x23,0xe2,0x0b,0xd4,0x95,0xf7,0xb7,0xf6,0x00,0xe8,0xd5,0xa6,0x71,0x33,0x0d,0x32,0x69,0x3d,0x60,0x19,0xc0,0x8d,0x2d,0x00,0x3b,0x17,0x6e,0x63,0x19,0xc3,0x53,0x94,0x20,0x0e,0x02,0x7d,0x0e,},"\x2e\x3b\xc5\x4d\xf4\x16\x74\x1d\xbe\x79\x16\xad\x25\xf0\x4e\x48\xd5\xa9\xd7\x7a\x62\x3e\x57\xf9\xcd\x61\xec\xb4\x4f\x09\xf7\x68\x33\xeb\x2a\x3e\x9a\xb7\xaa\x89\xff\x5d\x2d\x56\x0c\x07\x17\x7d\x85\x4d\x7c\x49\xcb\xef\x49\x2b\x7f\x4f\x7e\x56\x7d\xe1\x27\x51\x24\xe1\x6c\xa4\xa7\x98\x01\x62\xfa\x0f\xd1\x62\xa8\xe5\xfd\x6f\x35\x61\x70\x07\x03\x4b\xce\xec\x57\xc8\xfa\xf7\x66\x4f\x4b\x3b\xaf\xfd\xea\x8d\x8f\xc2\xba\x22\xd5\x85\xe9\xe2\xd7\x39\xf5\xff\xc9\x9b\x4e\x0d\xbe\x9c\x36\x86\x54\x7e\xa0\x48\x15\xa5\x9c\x4a\x25\xb5\xf2\x39\x06\x68\xe4\x18\xba\x0f\xcb\xdf\x4c\x4a\x51\xf3\x39\x05\xc7\x4f\xbb\x83\x0a\x19\xf9\xbc\x86\x36\xdb\xaa\xff\x20\x99\x95\x44\x79\x96\xd2\xe5\xb1\xc3\x77\xb4\xcb\x87\xa4\xe1\xef\xe1\x2d\xe3\x4d\x33\x59\x9f\xf3\x97\xb7\x40\x17\xd7\x11\xed\xd3\xe7\x72\x15\x5b\xe5\xa4\x40\x6e\x74\xcb\xe2\x93\x1e\xf5\x13\x59\xaf\xd5\x1b\x5b\x1a\x7b\x3e\xa2\x2e\xe8\xed\xa8\x14\x76\xbc\xc1\x7e\xa7\x68\x0f\x6f\x31\x04\x70\x3b\x9f\x2a\x35\xcf\x26\x27\xeb\x74\x1d\x1a\x30\xaa\x4b\xee\xf6\x57\x9e\xc7\xd0\xb0\x7a\x4e\xf3\x2a\xbc\xb4\xd7\x56\x97\x0f\x70\xa3\x67\x8e\x17\xe6\xe5\x73\x18\x90\xae\xbc\x8c\x92\xb9\x56\xd4\xb3\xb5\xfe\x2a\xdf\xd7\x9b\x21\x1a\x18\x83\xdf\xc8\xc9\xa4\xb1\xb9\xc8\xc1\xbb\x26\x5e\x1f\x3d\xd3\x92\x44\x5e\xa5\x9b\x59\x0a\x01\x95\x51\xf8\x12\x18\x49\xf4\x35\xb3\xac\x1b\x29\x90\x2f\xc8\x39\x25\x54\x05\x6b\x93\x90\x3d\x5f\x26\x3b\x3d\x54\x08\x43\xd6\xaf\xa7\x5a\x2a\xd8\x30\x4b\x76\x90\xde\x99\xa7\x34\xc3\xd1\x30\xb6\x95\x47\xb1\x8b\x09\xe9\x8c\xbf\x25\x27\x30\xe4\xae\xdb\x6d\xc4\xb5\x8b\x22\x43\xfe\x55\xe8\x09\x39\xd3\x7b\x0a\x59\xd7\x22\x26\xd8\xa2\xcc\x51\x53\x09\x5e\x15\x99\x4a\xd6\x21\x95\xaa\x31\x0f\x2a\x64\x26\x67\x6b\x66\x1e\x47\xb9\xfc\xff\xfa\x04\xd6\xdc\x62\x5f\x29\xf4\x4c\x7c\xf6\x20\xb3\x78\xa6\x5d\x23\x83\x44\xb3\x80\x44\x8c\xd1\x19\xcc\x7f\x37\x3f\x62\xcd\xfa\xd6\x41\x49\x90\x63\x53\xf3\xa5\x41\x07\xc5\xdb\xa6\x5e\x3c\xc4\x94\xb0\x53\x1f\x4d\x64\x74\x93\x63\xf2\x30\x73\x8b\x2c\xfe\xed\x98\x35\x20\x22\x7d\xd5\xbc\x43\xbe\x59\xb3\x26\x8e\x28\x32\x16\xf6\xe9\xc7\x5e\x0c\x1c\x71\x27\x2e\x54\xfd\xb2\x9c\x78\x58\xd2\x87\xd1\xef\xa1\x91\x7b\xe3\x7c\x8e\xea\xb5\xe4\x4c\x3a\xd7\xb3\x6e\x8a\xc9\xf6\x69\x91\xeb\x82\xa5\x14\x8e\x59\x72\x03\x4a\xd0\x1c\x62\x61\x5a\x45\x15\x45\x79\xfa\x50\x86\x9e\x7b\xe9\x87\x6b\x56\x56\xea\xad\x2e\x43\x02\x5a\x62\xdd\x13\x4b\x61\x2d\x8f\x4d\x5e\xbc\xf8\x05\x6e\x19\x8b\x71\x34\x38\xe8\xe0\xe3\x47\xca\xfb\xfc\xb8\x9e\x39\x4a\xa3\x30\xd4\xc7\x88\xd4\x9c\x65\x8f\xcf\xc8\x0b\x3e\x00\x78\xf0\xe8\xe1\x9a\xa9\xb8\xfe\x8e\xb0\xba\xb9\x3d\xe7\x85\xd0\x43\xe0\xf4\x75\xae\xb6\x0d\x62\xe3\x8f\xb1\xf8\x38\x4a\x00\xb7\xa9\x02\xda\xee\x13\xd2\x13\x62\x69\xe5\x08\x01\xb8\x0a\x65\xb2\xf9\x13\xcf\xe3\xff\xb3\x65\xd9\xaa\x2f\xd1\x93\x72\xa0\xb0\x22\x56\x95\x44\x4e\x4b\xc5\x48\x71\xd1\x08\xe0\x9c\x7e\x1c\x2b\x42\xdc\xbb\xac\xce\x24\xea\x5b\xd5\xbf\x1f\xcf\x4a\xc6\x97\xa3\xfe\x09\xa5\x46\x77\xb7\xa8\xdc\x8d\x5e\xec\xb8\x6c\xc7\x92\xee\x9b\x6f\xea\x2d\xe1\x6a\x47\x32\x69\xfd\xc6\x5d\xbb\x73\xc2\x58\xc8\x21\x44\x04\x07\xc6\x42\xf7\xd3\xd3\xf5\xc7\x08\xd5\x53\x32\xda\x83\x43\x10\x6c\x19\xb2\x30\xa5\x14\x27\xf3\xb7\x71\x91\x6a\xe3\x68\x8b"}, -{{0x4b,0xb7,0x92,0x36,0xfa,0xda,0x31,0x44,0xb6,0x82,0x96,0x49,0x9b,0xa4,0x4a,0xe5,0x34,0x07,0x4c,0xa9,0x4d,0x4b,0x58,0x1e,0x5e,0xdc,0xff,0xfe,0x13,0xb3,0xad,0x19,},{0x0a,0x83,0x99,0xf1,0xe5,0xa4,0x23,0xdc,0xf7,0xb2,0x5b,0x2f,0xb0,0xac,0x9e,0x1e,0x95,0x48,0x14,0x8b,0xea,0x84,0xd0,0x21,0xe0,0x42,0x87,0x60,0xe0,0x5d,0x58,0xbf,},{0x69,0x8f,0xab,0x68,0x51,0x0d,0xb8,0x12,0x1a,0x46,0x5d,0xb7,0x7e,0x4f,0x8b,0x58,0x6a,0xee,0x89,0x58,0x16,0xe6,0x3b,0xbf,0x0b,0xeb,0x24,0x2d,0xb4,0xe8,0x4c,0x15,0x7f,0x4b,0xe2,0x01,0xae,0x65,0x64,0x51,0x7a,0x87,0x0d,0x17,0xf6,0x0c,0x85,0x83,0x70,0xc0,0x1c,0xca,0x17,0x18,0x9c,0xb4,0x18,0x9e,0x81,0x43,0x91,0xd1,0x50,0x0d,},"\xad\x81\xab\xf6\x93\x7a\x7a\xcd\x7f\x18\x37\xf0\x4d\x3f\x10\xe7\x08\xc6\x1a\x5f\xbe\xde\xee\x4d\xb7\x6e\x15\x98\x57\x03\x84\xe6\xef\xec\xe9\x7c\x92\x5d\x2e\x5c\x34\x88\xca\xb1\x0b\x5b\x52\xb8\xa5\x48\x6e\x99\xd8\xff\xe8\x6c\x19\x81\xa1\xf1\xd5\x32\xdc\xd4\xd4\x89\xe5\x54\x6d\x86\x65\x32\x98\xe7\xa5\xf9\x6e\x81\x44\x55\x2d\xda\x8a\x18\xe7\x5b\x5f\x73\x55\xb1\x35\x41\x62\x11\x06\xe4\x97\xe5\x1a\x56\xd8\x65\x9d\x19\x8f\xe1\x00\x37\xe2\x21\x28\xaf\xc2\x71\x4a\x2c\xb5\xa1\x2c\xc5\xdb\x09\x68\xa3\x43\xef\x91\x8e\x87\x69\xdd\x6a\x3e\x5b\x9e\x32\xaa\xb6\x6c\xb0\x23\x9e\xbe\x4c\x17\xf1\x82\x18\xe2\x52\xeb\xa6\x16\x2e\x97\x70\x49\xeb\xac\x0b\x38\x04\x8b\x3a\xaf\xb7\xd4\xd7\x22\x63\xe9\x21\x28\x99\xa3\xbf\xe0\xa6\x9c\x99\xe2\x2a\xc6\x1c\x5e\x96\x12\x45\x63\x03\xd9\x24\x58\xb5\xc5\x02\x91\x6c\x34\xa8\xee\x5c\xd9\xa5\x82\xa5\x25\x76\xb6\xdc\x9d\x7d\x4c\x64\x2f\x21\x29\x98\xbf\x33\x58\xd4\xa8\xc2\xea\x67\x68\x6e\x55\xd4\x89\xf6\xa7\x6e\x6b\x07\x0e\x6e\x99\x5a\x74\x53\x26\xc9\xaa\x63\x63\x0a\x00\x33\xad\x30\x72\x1a\xa6\x5f\xac\x60\x4a\x6e\x58\xc7\x50\x72\x1a\x56\xca\x67\x60\xc9\x41\x34\xd6\x11\xfa\xb4\xd3\x54\xe4\xf6\x6a\x29\x67\x7b\x1a\x66\x66\x01\xe9\xda\x79\xf2\x13\xf5\x82\x03\x74\x33\xc0\x7f\x94\xd5\xf0\xde\x6a\xa9\xfa\xa0\xb3\x2f\x7b\x02\x3f\xb9\xfc\x13\x5a\x26\xf9\x70\x52\xac\x80\xb3\x9b\x30\x6a\xed\x13\x92\x6c\x28\x54\x19\xa2\x9b\x20\xe2\x37\x0d\x8a\x09\x5b\x32\x25\x8f\xa9\x89\x34\x89\xee\x21\x08\x9c\x75\x2e\xc0\x62\xe1\x20\x35\x9e\x2f\x35\x15\x12\x82\x54\xc8\x09\x8c\xca\x65\xa9\x1a\x02\x2d\xd0\x57\xa2\xc2\xa1\xb6\xb8\x5d\x13\x7c\x3c\x96\x7d\xcb\x70\xaa\x17\xa2\xff\x4b\x37\x67\x8b\x38\x29\x02\xf0\xf9\x31\xee\x74\x3f\xc3\x98\xac\x1b\x8c\x10\x46\x98\x67\x30\x84\x79\xe4\x0d\x7f\x2f\x04\xa4\xb0\x4c\x44\x89\x15\x84\x88\xdd\xb7\xbe\xc5\xa4\x7f\x20\xff\x35\x6d\x99\xa1\xb3\xe9\xd0\xb7\xfe\x9b\x0a\xd9\x49\xf2\x98\x96\x0e\xfa\x4d\x97\x28\xf8\x10\x1c\xf5\x3d\xa3\xbf\xfd\xd9\x52\x4b\xf4\x40\xa5\x8b\x32\x73\x8d\x0b\x62\x93\xe8\x53\xf4\x66\xff\xd4\x2c\x56\x07\xac\x9e\x35\x3b\xa0\x3e\xfb\x57\x8c\xc9\x96\x3d\x8a\xaa\x9d\x2e\x26\x6d\x1d\x2a\xe9\x29\x6f\x30\xc9\xef\x44\xec\x69\x10\x30\xd5\x96\xa4\x01\xb6\xce\xe7\x2a\x54\x0e\xf3\xc4\x2e\xc0\x17\x42\x66\xba\x54\x01\xf3\x54\xad\xc8\xe2\x54\x04\x43\x7e\x88\x8b\x08\x28\x69\x39\xbe\xde\x30\x8a\xcd\x30\x32\x7e\xbf\xf0\x62\x70\x09\x7c\xc2\x94\xf0\xa0\xf3\x9f\x9a\xa3\xc6\x65\x85\xca\x47\xe6\x0c\x4b\x8e\xa3\x60\x89\xeb\x8a\x90\x88\xbb\x18\xb0\x34\x31\x35\xbb\x6a\x45\x6d\x2f\x6a\x3b\xf3\x90\x72\x3e\x78\xb4\x2c\x03\x7c\x2d\xe2\xe1\x43\x2c\xaa\xd3\xa5\x94\x02\x12\x94\xd4\x3f\x5b\x15\xa2\xe8\x19\xdc\x74\x8e\x45\x1d\xe4\x00\x68\xc8\xf0\x32\xf1\x3b\x47\x11\x37\x70\x12\xed\xcd\x4f\x11\xde\xc1\x11\x1b\x12\xeb\x6e\x1b\x00\x63\x38\x18\x70\x6d\x71\x32\xd9\x91\xce\x20\xdf\x3b\x92\x1d\xb2\x18\x5e\xe2\x5b\xb6\xf5\x82\x75\x76\xec\x01\xad\x89\x0f\x79\x79\x3b\xaa\x35\x8c\x2b\xbf\xb6\xfa\xad\x11\xd8\xcb\x0d\x0d\x2d\x2b\x29\x81\xfb\xf4\xe3\x72\x34\x9f\xc6\xa0\x1c\x36\x07\x7b\x59\x32\x5f\x70\x2b\x38\x00\x59\xa6\x5c\xf2\xf5\xea\x98\xd6\xbd\xc8\x15\x20\x53\xb8\x5b\x28\xc8\x1e\x41\x3c\x4c\xac\x7e\x22\x6c\x13\xdb\x32\x67\xd2\x18\x30\xf0\xe5\x43\x11\x02\x91\x70\x05"}, -{{0xaf,0xd7,0x65,0xe6,0xaa,0xc0,0x14,0x6d,0x48,0x11,0xef,0x95,0x97,0xbc,0x3f,0x44,0x76,0x3f,0x03,0x37,0x8b,0x7b,0xe0,0x33,0xd6,0xe6,0x4c,0xa2,0x9d,0xec,0xae,0xf9,},{0x6b,0xb7,0x61,0x23,0xd9,0x25,0x89,0x22,0x68,0x6c,0x53,0xfb,0x69,0x17,0xb9,0xa4,0x59,0xca,0xbd,0x30,0xbe,0x8c,0x43,0x97,0x0d,0x80,0xf5,0x35,0x0c,0x2d,0x98,0xef,},{0x3d,0xc9,0x19,0x4d,0x50,0x81,0x14,0x19,0x04,0x9e,0xaa,0x07,0xb6,0x55,0xb7,0xd4,0x06,0x4b,0xcb,0x0e,0x7f,0xb5,0xf9,0xe5,0x32,0x6b,0x5f,0xc8,0x56,0xfc,0x0a,0xb8,0x70,0x59,0x73,0xae,0x10,0x01,0xdf,0x55,0x37,0x39,0x77,0xdd,0xe2,0xd9,0xb8,0x10,0x79,0x55,0x14,0x14,0xad,0xc7,0x1c,0xc8,0x52,0xd4,0x99,0xb0,0xcf,0x82,0x4f,0x07,},"\x18\x3b\x10\x92\xc7\x90\x4e\x47\xa1\x42\x03\x17\xa2\x5d\x0f\x59\x11\x0a\xa8\x4d\x6b\x34\x19\xad\x45\x68\x65\xc4\x3b\x29\xe9\xd1\xda\xcf\x75\x5d\x9e\x5c\xf9\x4c\x55\x91\xd5\xd9\x12\xd0\x5c\xa9\xa5\x2d\x01\x5d\x6e\x8f\x5d\xc9\x4e\xfd\xce\x0d\x7c\xf5\x65\x12\x03\xb1\x1e\x54\x27\xa9\xf6\x79\x42\x9e\x00\x41\x4a\x48\xea\xb1\x3f\xd8\xe5\x8b\x87\xeb\xa3\x9d\x10\x25\xd6\xa1\x8b\x2c\xdc\xbe\x14\x74\x36\xdb\xf3\x8a\x1c\xe8\x64\x13\xae\x31\x87\x65\xe1\xbb\x1d\xf7\xe2\xb3\xbe\x97\xe9\x04\x08\xb1\x17\x17\xcf\x45\x9b\xcd\x0f\x3c\xac\x58\xb4\xa0\xd3\x5b\xff\xb5\x33\xe2\x0d\xf3\x74\x51\xc1\x14\x01\xce\x1d\xab\x02\x05\x5c\x7e\x08\xc5\xec\x46\x39\x0c\xd6\x17\xa6\xb5\xf2\x2f\x65\x18\x30\xa1\x11\x2a\x06\xed\xe4\xc4\x0a\xb7\x95\x78\x51\xd6\xc6\x6f\x17\x1c\xd1\x62\x41\x59\x09\x00\xb8\x52\xa3\xd0\x19\x95\x7b\xe1\xb7\xbb\x7a\xcb\x89\x23\xf2\xa3\x57\xc3\x26\x44\x56\xcf\xca\x9b\x42\x9d\x71\xfe\xcb\x7e\xda\xe3\x9b\x25\x2b\x4e\xb6\x10\xe8\xc7\x18\x83\x56\x99\x75\x4b\x8d\x41\x24\xb4\x92\x48\x8e\xde\x62\x61\x0c\xce\x44\xb5\x92\x18\x66\x3b\x6c\x96\x46\xa1\x4a\x84\x17\xed\xdb\xb6\xf4\xfb\xe5\xa4\xbb\xbb\x48\x2b\x37\xa4\x45\xe3\xc1\x6b\x65\xa1\x41\xcd\x3e\x12\xa5\xb2\xc0\x48\x1d\x61\x4d\x6d\x20\x84\x79\xb9\xb2\x09\xb8\x28\x85\x4d\xae\x0e\xa1\xed\xed\x50\x65\x55\xfe\x18\xe1\x85\x40\x05\xcf\x00\x1a\x80\x77\x08\x34\x98\xd2\x7f\xad\xf1\x18\x28\x6b\x53\xb8\x97\x4d\x69\xfa\x28\x25\xbe\x8c\xa3\xd6\x03\x6a\x92\xca\x52\xf9\x1d\xde\x6d\x5b\x1f\xfe\x28\x88\xf4\xd6\x07\x79\xfa\xd1\xfb\x41\xd8\xc0\x71\x40\x49\xaf\x68\x1b\x75\x5f\x2d\x42\x04\xee\xcd\x09\xe0\x77\x21\x0a\x48\xa1\x95\xe7\x2c\x80\xe1\x27\xc3\xd4\x87\x50\x95\xc6\x57\x0a\x1f\x78\x09\x59\x07\x52\x8c\xf7\x74\x6f\x31\xd9\x71\x11\xc6\xf4\xcb\x25\xb3\x74\x12\x99\xa7\x57\x48\x22\xd4\x6b\x6e\x79\xed\x23\xc2\xfe\x05\x7b\x3a\xc7\x29\x0b\x46\x0b\x16\x6e\xe9\x0a\x45\x56\x2e\xff\xed\xcc\x6b\xa8\xf4\x79\x5f\x73\x95\x81\x8d\xb5\x6b\x6e\xdd\x59\xca\x2c\xc4\xae\xa1\x84\x1f\xd9\x56\x5b\xec\xd6\xc0\x81\x04\xcd\xee\x26\xba\x9d\xe2\x00\x77\x3d\x09\x1b\xc7\x7a\x57\xc5\x47\xf1\xa6\xba\x0a\x2c\xd7\x17\xab\x32\x56\x1d\x74\x22\xea\x72\x35\xad\xb0\xcb\x36\xbf\x5c\xbd\xf8\x8f\xca\xe0\x66\x30\xa1\x56\x47\xd9\xa3\x57\xb4\xe0\xe5\x02\xd2\x73\xf3\x79\x6a\x51\xe0\xbc\x3f\xed\xbf\x7a\x1e\x64\xaa\xd7\x22\xaa\xc5\xfd\x02\x2f\xa7\x9d\x60\xfc\x70\x73\x25\xf1\x27\xeb\x1f\x03\x86\x87\x95\xcc\xdc\x0b\x4c\xb2\x6f\x20\x23\xd1\x52\x15\x3a\x97\xa2\x60\xbf\xf1\x17\x45\xd2\xe2\xcc\x0b\xf8\x60\xd4\xa6\xe3\x58\xa6\xd8\x17\x6d\x2a\xc1\x78\xa9\xae\x1a\x2d\xc7\x5e\x8b\x49\x04\x08\xff\x7c\xdf\x99\x13\x29\xf3\x3c\xb0\xc0\x5e\x1e\x35\x69\x25\x08\x7e\x0b\x8d\x96\xa5\x23\x51\xd1\xd1\x77\x68\xeb\x13\x4c\xdb\x21\xa1\x54\x6a\xae\xdc\xc6\x87\xdf\xa1\xb2\x2e\x92\xfb\x52\x41\xa8\x36\x77\xa1\x53\x44\x5b\x77\xd5\xe7\x03\x50\x8e\x2a\xbc\x58\x8a\x9f\x42\xe5\xbc\x71\x06\x73\xe4\xdd\x8a\xd7\x03\xfa\xb2\xd7\xdb\x1e\xb8\x42\x26\xc8\x9d\x87\x62\xa7\x09\xe3\xe9\x13\x8a\x1f\xa7\x90\xf2\x92\x9b\xff\x61\xbc\x1e\xa6\xe8\xaa\x1a\xd0\xe3\x88\x7d\x70\xa5\x6d\x4e\x65\x47\xfc\x60\x6a\x50\xd3\xbe\x3b\xd6\xdb\x03\x66\x3e\x00\xca\x9e\x4f\x24\xfe\x8c\xbf\xd7\xd8\xc9\x73\x8d\x63\x67\x55\x4b\x7b\x60\x1f\x74\x19\x0b\x59\x70\xa3\x98"}, -{{0xeb,0x34,0x71,0x45,0xf3,0x39,0xed,0xd8,0x02,0x78,0x5b,0x6f,0xbe,0xcd,0x5c,0xb8,0x08,0x89,0xac,0x7c,0xe4,0xeb,0xad,0x2f,0x67,0x07,0x67,0x65,0xdb,0x93,0x9b,0xca,},{0x99,0x4a,0x45,0x6e,0xad,0xa0,0x30,0x20,0x92,0x1c,0x3d,0x10,0x9c,0x13,0x5e,0xb9,0x61,0xfc,0xd4,0xa0,0xa4,0x00,0xba,0xfd,0x32,0xca,0x06,0x1b,0xbc,0x86,0x25,0x43,},{0xfd,0xbd,0x15,0xe1,0xe6,0x46,0x9d,0xf7,0x20,0xd9,0x55,0x2c,0xb5,0xdd,0x17,0x7b,0xcb,0xd2,0x92,0xfc,0xda,0x83,0xcd,0x93,0xc8,0x8d,0x01,0x14,0x91,0x2d,0xc8,0x70,0x31,0x09,0xba,0xc0,0xd4,0x59,0xac,0xe9,0x95,0x7d,0xf2,0x29,0x3a,0xc1,0x6d,0x40,0xd5,0x14,0x89,0x35,0x56,0x85,0x32,0x99,0xb9,0x7b,0x4f,0xd4,0x13,0x7a,0x3d,0x00,},"\x5b\x8b\x31\xba\xf8\x84\x83\xf0\x95\xb5\xd0\x2e\x17\xd8\xb7\xb4\x6c\xf4\x64\x60\xe6\x4c\x6b\x02\xc5\x6d\x8d\xaf\xe3\x48\x23\x70\x6c\xb5\xc1\x5f\x33\x8a\xd9\xb5\x65\x86\xa9\x49\x71\x1a\xa7\x31\x2c\xc9\x34\x50\xd2\xfb\x9a\xf4\x61\x3f\xc3\x07\x93\xa6\x31\xa5\x5c\x14\xe5\x3c\x0c\xb1\x5f\x06\x11\x63\x99\x39\x8c\x8d\xd6\x18\x76\xc6\x29\x15\xf9\xf9\xe4\xcd\xf8\xf7\xd8\x9a\xde\x12\x9e\x6d\xde\x7d\x63\x67\x1a\x18\x63\xf5\xda\x8f\x42\xea\x64\xc0\x79\xec\xb9\xa2\xc1\xb1\xdd\x9a\xda\xe6\x0e\x96\xb9\xcb\xbc\x76\x24\x53\x2a\xa1\x79\x75\xeb\xa1\x7a\x7a\xf0\x2b\xfb\x21\x9a\xac\x02\xb3\xd4\x30\x6c\xd3\x89\x33\xa8\x50\x60\xcd\x62\xab\x51\x3a\x39\x65\xb0\x91\x50\xa4\x88\xc9\x2b\xf7\xca\xb0\x48\x2e\xee\x56\x46\x3f\x01\x39\x00\x9b\x9f\xbb\x3f\xf4\xec\xae\x21\x1f\x42\x8b\x5b\xfb\x88\x76\xf0\x04\x98\x3b\x90\xc4\x47\x84\x6c\xa4\xb7\x45\x66\xe9\x79\xbc\x30\xc9\x5e\x99\xfa\xab\x69\xa3\xeb\xbf\xe4\xda\x60\x34\xc8\x2d\x63\xe9\xc5\xcc\xaf\x84\x86\xaf\x3b\x5e\x0d\x38\x14\x22\x93\x8b\x0c\x22\xf5\x16\x95\x5b\xdc\x36\x94\x31\x73\xf5\x83\x27\x08\xa3\x3c\xf5\x2d\x88\x75\xd9\x7f\xde\x58\x5b\x49\x17\xe4\xad\xec\xdd\x1e\x79\x85\x67\x62\x03\x3a\xf2\x2f\x25\x4b\x50\xce\x9d\x0c\x70\x0e\x77\xa7\x31\x55\x4f\xa0\x11\x3a\x0c\x66\x66\x83\xf3\xfd\xb1\x9e\x3a\x42\x63\x02\x23\x0b\x63\xe3\x3a\x78\x5e\xf2\x4a\x92\x89\x45\x5b\x3b\x8f\xc6\x18\xff\xfe\xf4\x9c\x2c\x6e\x48\xfd\x4b\xb4\x22\xf5\x04\x14\x9d\xe2\xb4\xc0\x35\x5c\x36\x34\x08\xe6\x6d\xa8\x1c\xbb\x58\x15\x52\xa4\x11\xe3\x64\xfe\x3e\x4c\xa9\x6d\x70\x72\xab\x07\x2e\x75\x68\xc1\x3d\x35\xe4\x1c\x78\x25\xa1\x3a\x5c\x68\xfb\x9f\xb5\x98\x8b\xbb\xfb\x9a\x0b\x51\x16\x57\x64\x66\x0c\xdf\xa2\x41\x1f\x3d\x42\x16\x5d\xa1\x87\xc5\x8e\xde\xf0\x10\x5a\x6d\xb1\x77\x42\x05\x43\xe9\x58\xd5\xd5\xe8\xa3\x71\xf7\x98\x70\x51\xc4\xe1\x78\x6d\x01\x8e\xb3\xd7\x32\xc2\x10\xa8\x61\xac\xaf\x67\x1b\xe9\x5b\xb6\x3f\xbc\x88\xbf\x8b\xe7\xbe\x53\x90\x93\x9c\xd9\xfb\x2a\xcf\x39\x81\xdd\xa6\x1b\x78\x7a\x7b\xbd\x78\x46\x8e\x1d\x32\xca\x46\xaf\x8f\xb3\x2a\x18\x46\x3c\x18\x0f\x52\x4b\xe1\xda\x91\x0d\xa5\x50\x8d\x42\xa0\x05\x17\x41\x22\x7c\x9b\x62\xde\x6d\x19\xb3\x3c\x0b\xd4\x80\x67\xb0\x35\x85\x9a\xd9\xbd\xc2\xdd\xd9\x7b\xef\xca\x31\xe6\x5a\x88\x6c\xfc\x75\x3a\xfc\x4f\xf2\xa7\x21\x2a\x89\xd3\x7c\x04\x6c\xdf\x39\x99\xc0\x51\xff\x13\x96\xbd\x99\xcb\x54\x94\x56\x39\xeb\x64\x62\xdb\x9e\xce\x84\x07\x7b\x0b\x3d\x6b\x3d\xf3\x95\x2d\xd3\x67\x56\xc6\xda\xb2\xab\xc2\x5a\x51\xbf\x32\xc1\xe9\xcd\xd0\xa7\x28\xa7\x98\x5f\x7b\x7e\x0d\x9c\x1a\x6f\x66\xce\x12\x16\x37\x3d\x25\x2d\xaf\x59\x58\xf2\xe8\x97\x3f\xd2\x68\xfa\xd0\xef\xe2\x51\xce\x76\xfe\x47\xbd\x0a\x4d\x0c\x4f\x10\x17\x94\x9d\x4c\x2b\x16\x71\x72\x18\xe1\x49\x15\x4e\xd6\xfb\xe5\x6f\x86\xd8\x2e\x19\xef\x0a\x91\x63\x19\x12\xf2\xa8\xf3\xde\xbb\x00\x76\x6b\x61\x77\x80\x2f\x4b\x2e\x79\xf6\xe7\xbf\xa9\xc6\x2c\xfa\x2f\x75\xcd\xb6\x04\x92\x63\x0a\x85\xc9\xb4\x31\x77\xd2\xdd\x9b\xa8\xd0\x54\x8a\xbe\x24\x92\x3a\xe8\x44\x3e\xea\xdc\xd0\xf5\x8a\x7b\x82\xdf\xf5\x0d\x88\x40\x03\x88\x9c\xb5\x60\xf7\xac\x53\xe7\x10\xa7\x55\x75\x36\x24\x64\xb1\xaa\x43\xd2\xa9\xb2\x2f\x2b\xd2\x16\x2d\x30\x2f\xaa\x74\x52\x34\x4c\xe7\xad\xe9\x98\x36\x87\xb6\xc6\x8e\xca\x47\xdd\xdb\x28\x9b\x15"}, -{{0x32,0x08,0x83,0x7d,0x15,0x54,0xb6,0x51,0x1a,0xdd,0xa0,0x9c,0xba,0xe5,0x65,0xda,0x78,0x43,0x9a,0x47,0x2a,0x5d,0x1b,0x10,0x7c,0xe0,0xa9,0xb1,0xd7,0x75,0x7d,0xb7,},{0x9b,0x52,0x5e,0x35,0x36,0x8a,0x92,0x1e,0x3a,0x2e,0x9a,0x35,0xa4,0xde,0x9e,0xa4,0xc4,0x36,0xca,0xba,0x27,0x12,0x3e,0x5c,0x36,0x9e,0x2a,0x6c,0xf5,0xc9,0x0a,0xb6,},{0x70,0x9d,0x1c,0xa9,0xca,0x2f,0x74,0x2a,0xb9,0xdd,0x0b,0x04,0x93,0x35,0xf5,0x44,0xcf,0xfb,0x2f,0x1a,0x36,0x93,0xd5,0xf5,0x3f,0x8b,0xa0,0x83,0xb9,0xb0,0xd8,0x6e,0x52,0x08,0xfa,0x8e,0x1e,0x81,0x56,0xc9,0xcc,0x22,0x42,0x77,0x5a,0xbb,0x7e,0x15,0xaf,0x30,0x85,0x86,0x8e,0xf4,0x57,0x63,0x4e,0x99,0x26,0xc4,0x04,0xec,0xf3,0x0f,},"\x43\x6a\x3c\x31\x76\x3f\x93\xd4\xd5\x46\xc6\xd1\xec\xfb\x7a\xe4\x59\x16\xaf\x75\x4f\x83\x9d\xcf\xe9\x6d\x6b\x69\xc6\x12\x14\xd0\x16\xfc\x84\x2f\x56\x46\x2a\x3f\x07\xf6\x61\xb2\xe2\x50\x5a\xcf\xaf\x48\x2a\x0b\x0f\x4f\x55\x01\xee\xc4\xb2\xd2\xd7\xd4\x44\x54\x4d\xe0\x00\xb9\x90\xf4\x36\x3d\x3f\x98\x3f\x5d\x4e\x09\x30\x97\x52\xff\x57\x9c\x73\x20\xc9\x15\x95\x1c\xc3\xa1\xe3\x23\x8c\x1b\xa7\xa1\x91\x30\xea\xbf\x6a\x37\xf5\xf0\xbc\x56\xe2\x52\x42\xf7\x52\x06\x1f\x3c\x63\xac\xad\x99\x2a\x75\x01\xe9\x67\xde\xb9\x25\xb3\x0e\xd1\x05\x43\x1e\x58\x21\x02\xfa\x4f\x30\x8c\x2f\x06\x83\x61\x2b\x56\x68\x6d\x52\xda\xed\x69\x43\xa7\x21\x9f\x3b\xee\xa2\xe0\xa2\x92\x42\xe8\x6d\x55\x62\xff\xab\x83\xb5\x6b\x26\x33\x26\x66\x4e\x02\x9e\x96\x1e\x70\x17\xd8\xe8\x9f\x5e\x3e\x1d\x10\xf5\x93\x28\x54\x55\x0c\xe6\xe5\xcd\x76\x97\x1f\xd2\x35\xcf\x9c\x00\x27\xd0\xcf\xed\x33\x15\xc2\xcb\xf1\x85\x08\x62\x4d\x8a\xcf\x04\x7f\x9b\x96\x8f\x90\x7d\x9e\x6f\x4c\xfa\x5e\x45\xc8\x0a\x27\x2c\x2d\xbb\x62\xc5\xd4\x19\x45\x80\xdf\xab\xed\xd8\x2c\xb4\xd7\x64\x92\x34\x4b\xe9\x6c\xcf\x5d\xaa\xf6\x1e\x6b\x2b\x55\xef\xdb\x3f\x65\x21\x0a\x3d\x6e\x1f\x36\x98\x87\xca\x0e\xa0\xd5\x8c\x3d\x14\x6a\xe3\xcf\x9b\x00\x00\x76\x88\x41\x15\xfa\x51\xb5\xfd\x66\xbe\xc0\xcc\xbf\x0d\x29\x20\x19\x6a\x7d\x7a\x38\x44\x5f\xbe\xd2\x2d\xfc\x75\x64\xdc\x56\xf6\x0d\x6e\x29\xe5\x92\x48\x53\x74\xc6\xbd\x1e\x5b\x15\x93\x1b\x69\xca\x6e\xe6\xb3\xaa\x25\x25\xc2\x35\x85\xf0\x92\x9f\x31\xcb\xd1\x1f\xb1\xa5\x33\x02\x16\xb9\x0a\xe5\xa6\x56\xdf\x7a\x07\x4c\xec\x64\xe5\x98\x18\x4f\x50\x3f\xb2\x3c\xc0\x5e\x65\xda\x9a\xe7\xe8\x44\x1f\x40\xe2\xdc\x26\xb8\xb5\x6d\x2c\xb5\x23\xa7\xc6\x35\xdc\x08\x47\xd1\xcd\x49\x8a\xbf\x75\x6f\x5a\x13\xea\x14\xf8\xfa\xb2\xc4\x10\xb1\xa4\x70\xf4\x9a\xa8\xdc\xa4\xac\x02\x56\xb1\x18\x00\xde\x0d\xd0\xec\x42\xb1\x42\xc5\x61\x12\x8d\x35\x7e\x78\x3b\x12\xf6\x1c\x66\x8f\x5e\x6e\x06\xb7\xb4\x8b\x7b\x22\x54\xde\x5b\xdc\x18\x04\xb7\x23\xd5\xfd\x6a\x0f\x4b\xc7\xc5\x9e\x7c\x50\x54\x18\x26\x13\xbb\xd2\xfa\x92\xb4\xc1\xda\x16\xbc\x8c\x97\xe1\x6b\xcb\x0d\xbf\x8c\x92\xb7\x48\x99\xb3\x7f\x31\x87\x57\x14\x0b\x6c\x4f\xd5\x35\xe2\xe1\xe0\x57\x0a\x50\x81\x8c\xf7\x8f\xb9\x88\xe1\xf4\xce\x40\xe7\x6e\x8f\xe3\xd6\x97\xd7\xa4\x58\x50\xf2\x93\xce\x17\x0f\xd8\xab\x07\xcf\x15\x34\xea\x5f\xfa\xd3\x4f\x6f\xcf\xa4\x2d\x0d\x21\xa9\x1d\xfb\xfe\x05\x97\xc7\x3f\xd9\xb9\x76\x76\x14\xeb\xdf\xd0\x2c\x3a\xc0\xc4\x9a\xd1\x0c\x94\xbe\x59\x69\xee\x08\x08\xc0\xa3\x0b\x2a\x1e\xaa\x90\xea\x43\xb8\x57\x5c\x30\x56\xf4\x23\xcd\x4b\x6f\x34\xae\x51\xc2\x22\x37\x65\xa9\xea\x21\xf6\x45\x73\xc1\xa1\x39\x61\x32\x12\x46\xe3\xb5\x34\x9e\xe0\x48\xfb\x62\xd5\xfb\x61\xb1\x71\x43\x91\x18\x25\x62\xb9\x15\x98\x36\x0e\x5f\x9b\xf4\xac\x80\xdb\x24\x64\x32\xaf\xb3\xa4\x3d\x34\x96\x50\xde\x03\xd3\x43\xc2\xe9\x7a\x8e\xef\xd1\xbf\x30\xc1\x0c\x25\x86\x7f\x53\x26\x6b\xd1\xf0\xdc\x14\xae\x1a\x6b\xe9\xef\xde\xcf\xf6\x7e\x7d\x29\x2c\x6c\xdf\xc9\x0d\x80\xb8\x86\x66\x8f\x04\xc2\xa0\xf5\xad\x7f\xa1\x7c\x17\x8b\x6e\x9b\x45\xa1\x1f\x4d\xdf\xe2\xd6\x69\x60\xa3\xf7\x51\x35\xad\x5e\xd1\x54\xe5\x13\xe1\xa5\xd1\x38\xe7\x37\x1e\x84\xd7\xc9\x24\x53\xe6\xc6\x2d\xc5\x9b\x8e\x1f\xa9\x3d\x77\x3a\x25\x40\xd9\x1c\x25\x7c"}, -{{0x4e,0xc6,0x82,0x9b,0x43,0x99,0x70,0x56,0xd9,0x96,0x85,0x38,0x9b,0xd5,0x3c,0x52,0x8d,0xe7,0xe5,0xff,0x27,0x15,0xd6,0x5c,0x95,0x66,0x19,0x82,0x6e,0x3f,0xb5,0xb5,},{0x7d,0x92,0x2d,0x57,0xfd,0xb1,0x27,0x92,0x87,0x9a,0xec,0x4e,0x8c,0x65,0x14,0x63,0xec,0xe0,0x64,0x49,0x2c,0x72,0x17,0x53,0xd2,0x2e,0x11,0x55,0x09,0xfe,0xd7,0x06,},{0x15,0x9c,0xa4,0x04,0xf7,0xf7,0x41,0x17,0xc5,0x16,0x3c,0xf4,0x04,0x11,0x09,0x49,0xeb,0x57,0xae,0x2d,0x76,0x62,0xb1,0xff,0x41,0x78,0xcc,0x67,0x56,0xe9,0x0a,0xda,0xea,0xb7,0x1b,0x06,0x4c,0xe1,0xdf,0xf4,0x57,0xb2,0xdb,0xa7,0xe2,0xdc,0x13,0xc2,0x17,0xbc,0xae,0x8a,0x61,0xfc,0xf8,0xce,0x14,0x87,0xa6,0x49,0xc2,0x57,0xff,0x07,},"\xed\x26\xb4\x13\x0d\x4e\xbf\x3f\x38\x61\x49\x1a\xa3\xdd\x96\xa4\xeb\x69\x75\x21\x73\xfa\x6c\x84\xca\x65\xdf\xc9\x91\xc7\xfe\x44\xe0\x2b\xd6\x16\x50\x25\x2a\x1d\x23\x78\x66\x82\xec\x38\xc1\xfe\xe8\x2c\xc3\x50\xdb\x7c\x3c\x39\x49\xa1\xc9\x35\xff\xeb\xd7\xba\xa2\x4f\x35\xa3\x93\xfb\xd2\x7e\x7c\x34\xc2\xf9\xff\xda\x60\xa1\x8d\xf6\x6c\x3e\x46\x5d\x90\xed\x48\xfb\xba\xd3\xfa\x79\x47\xde\xe7\xe6\x59\xa3\xee\xad\xb8\x87\xf0\x96\x3f\x6b\xdd\x76\xc3\x6c\x11\xae\x46\xd0\x88\xee\x50\xbc\xa8\x18\x7a\x0a\x88\x32\xdb\x79\x84\xb7\xe2\x7c\xbe\x6a\xbf\x12\xd2\xc9\x4f\x33\x7e\xc7\x8c\xb3\x8b\x26\x24\x1b\xd1\xa3\xd2\xf5\xfa\x44\x07\xfd\xd8\x02\x27\xd2\xb1\x70\x14\x4b\x41\x59\x78\xe3\x72\x01\xd0\xfc\xf4\x31\x74\xb9\xd7\xb2\x11\x5d\x5e\xb8\xbc\xec\x27\x6a\x77\x5a\xea\x93\xf2\x34\x0d\x44\x25\xd3\x4d\x20\x47\x49\x4d\x91\x7e\x0d\xbe\x37\x85\x7e\x6c\x99\x85\x9b\x71\xc9\x14\xaa\xd5\xe5\x4f\x7b\x2b\x03\x3e\x59\x4e\x27\x2c\xc5\xcf\xe9\x19\xf8\x88\xe5\x5c\xb6\x15\x7a\xff\xcf\x35\x72\x46\xd0\x0b\x53\x2c\xc4\x71\xb9\x2e\xae\x0e\xf7\xf1\xe9\x15\x94\x4c\x65\x27\x93\x15\x72\x98\x53\xda\x57\x2c\x80\x9a\xa0\x9d\x40\x36\x5f\x90\x87\x5a\x50\xd3\x1c\xa3\x90\x0d\xa7\x70\x47\xc9\x57\xc8\xf8\xbf\x20\xec\x86\xbd\x56\xf9\xa9\x54\xd9\x98\x8e\x20\x6b\x44\x4c\xa5\xa4\x43\x45\x21\xbf\xc9\xc5\xf3\xa8\xa0\x61\x47\xeb\x07\xd1\x1d\xfe\x11\x71\xec\x31\xff\x55\x77\x15\x88\xb3\x33\xee\xe6\x21\x5d\x21\x6c\x47\xa8\x56\x6f\xbb\x2b\x18\x97\x46\x46\xac\x5a\x92\xc6\x99\xd7\x75\x84\xc0\xde\xfe\xfd\x2d\xfa\x58\xfc\xa2\x71\x99\xe4\x1e\xc5\x8a\x24\x63\x20\xb3\x5f\xaa\xb7\x5b\x97\x95\x19\x24\x22\x6d\xa4\xab\x28\xf0\x1b\x47\x07\x8e\x71\x2e\x4f\xd9\xf7\x7b\x25\x1c\x96\x67\x85\x8c\x28\xe3\x2e\xf1\xcd\x01\xfc\xbe\x43\x5c\x54\x2d\xba\xd0\xa8\x4a\x13\xcd\xbb\x57\x75\xe6\x2d\x81\x1d\xc6\x90\xd9\x55\x5c\x37\xf1\x5f\x91\x76\x7a\x56\x13\x57\xdf\x10\x6e\xef\xe0\x56\xe7\x36\x06\x70\x65\x0f\xb8\x18\xfc\x6a\xdc\x59\x97\x3e\x9a\xd5\xcd\xcd\x80\x98\x07\xab\x56\x39\x7f\x3c\x13\x94\x87\x32\xd9\x8d\x67\x6f\x4a\x44\x70\xa9\x5d\x8b\x51\x82\x37\xe2\x26\xf0\xcc\x5f\x47\x65\x16\x4a\x5c\x3e\xf0\x50\x71\x4b\xe0\x2a\x12\x6b\xe8\xf6\x65\x46\x48\x15\x81\xb9\xe9\x4a\x26\xaa\xd2\x4c\x69\x3b\x7f\xdb\xc1\x8a\xcd\x3e\xd7\xcf\xc4\x7d\x8a\xb2\x67\x45\xd7\x8e\x70\x1d\x0c\xf0\x5d\xd8\x44\xb5\xb3\x45\xa2\x9d\xab\x68\x4c\xbc\x50\x92\xba\x02\x2e\x3c\x58\x2d\xfc\x04\x4c\x31\x00\xad\x02\x75\x66\x97\xa8\x49\x82\x29\x15\xa1\x6e\x2a\x2b\x81\x0e\x68\x15\xf5\x44\x21\xd2\xf3\xa6\xff\xf5\x88\xc0\xd9\x01\x3c\x76\xf3\x3e\x09\xbe\xae\xef\x60\xd8\x77\x42\x30\xe8\xce\x71\x31\x28\x9a\xef\x2a\x40\x68\x6c\x81\x9f\xb2\x04\x0b\x06\x12\x4d\x3d\x9a\xa4\x19\xd5\x67\x88\xf1\x7f\xa7\xed\x9b\x9b\x57\xce\xaa\xd1\x33\x7a\x01\x01\xbe\xa0\x44\x0c\xff\x74\x5d\xdd\x97\x22\x05\x5d\x1f\x9b\xcf\xb0\x09\xce\x2c\x2f\x41\xa9\xe7\xe8\x68\x06\xb8\x72\xcd\xc2\x05\x9b\xc8\xec\x68\xf5\xee\x56\xc4\xba\xcf\x4b\xbd\x30\xea\x4c\x71\x55\x86\x4d\x60\x0c\x0e\x2e\xee\x73\xb3\x19\xbd\xa4\x37\x2e\x9c\x60\x3c\x77\x2c\x25\x89\x0c\x76\x10\x48\x99\x89\x47\x5d\x37\xa7\x7a\x45\x74\xa2\xba\x55\xbf\xd9\xc9\xcf\xd1\x46\xfb\x97\xe6\x16\x5d\xcc\x19\x55\x9f\x4f\x85\xdf\xca\x2f\x97\xf3\x70\x2e\xd8\xfa\x6b\x3c\x2a\x97\x41\x97\x4a\xa0\x7a\xb6"}, -{{0xb1,0x50,0xa7,0x89,0x29,0xed,0x1e,0xb9,0x32,0x69,0x21,0x3e,0x1e,0xbc,0x22,0xe2,0xe4,0x0a,0x60,0x1b,0xdb,0x00,0x54,0x99,0xb7,0xbe,0xb0,0x58,0x91,0x7c,0x53,0x40,},{0x28,0x86,0x6b,0x6d,0x1c,0x39,0x3c,0xb0,0x8e,0x46,0x4c,0xf5,0x57,0x14,0x40,0xa6,0x49,0xe5,0x06,0x42,0x38,0x0d,0xdf,0x4f,0xfb,0x7a,0xd1,0x50,0x48,0x5c,0x10,0x8e,},{0x27,0x6d,0xd0,0x96,0x2e,0x6e,0xe6,0x4f,0x05,0x92,0x44,0x1a,0x8a,0xf0,0xe5,0xef,0x8f,0x93,0xbf,0x0b,0xae,0xba,0x20,0x50,0x4b,0x9d,0xb4,0xf9,0x5a,0x00,0xb9,0x39,0xea,0x38,0xde,0xf1,0xc7,0x97,0x86,0x28,0x98,0xca,0xbe,0x9d,0xc4,0x64,0x4f,0x0e,0x67,0x7e,0x87,0xc0,0xa3,0x3b,0x87,0xb6,0xa4,0xd2,0x2a,0x80,0x7d,0x0e,0x1e,0x02,},"\x1b\xf5\x5d\x27\xf9\xdd\xe6\xc4\xf1\xc0\xdd\xd3\x60\xa2\x5d\x94\x93\xc0\xff\xdc\xa7\x4a\x7e\xd5\xe5\xa5\x14\xe9\x55\x15\xcd\xa4\xaa\xd8\xf4\x5c\xd6\xed\x79\x01\xf8\xf2\x24\xa6\x3b\x38\x12\x1c\xbe\xac\x2f\x56\xda\xe2\x10\xdd\x05\x37\x50\xcb\x20\x75\x14\xa8\x89\x1e\x24\x5a\x5d\x07\xe7\xde\x78\xa2\xe3\x81\x44\x63\xf1\x48\xd2\xac\xb7\xdc\x71\xf9\x95\xc9\x29\x9a\xd0\xd6\x26\x6c\xfe\xfc\x94\x26\x96\x57\xfd\x47\xcf\x53\x12\xb9\x2a\xf2\x75\x06\x51\xc4\x79\x63\x6c\x9d\x36\xae\xf0\x8f\x7d\x11\x95\xe7\xfa\x1b\xa3\xab\xb5\xdc\xb9\x01\x36\xb0\xfb\x9a\x37\x66\x8b\x87\xa2\xdb\x88\xd1\xe2\xb6\x44\x0d\x3e\x6e\x60\x1e\x6d\x4b\xc1\x0c\xf1\xcb\xdf\x1d\x61\x69\xc0\xdc\x2c\x4a\xec\xde\xb6\xcd\xd4\x56\x7d\x42\x50\xb2\xaf\xa7\x15\xb1\x66\xc9\x46\x7f\x90\x7d\x3f\xa5\xa6\xda\xf2\x00\xb3\x09\xc1\x09\x37\x68\x30\x49\x9c\xaf\x31\x49\x00\x1c\xf3\x33\x94\x48\xca\x3d\x76\x52\x25\xd6\xb3\xc1\xcd\x26\x7c\xba\x93\x6e\x7a\xa4\x83\x25\x39\x46\x6f\xd2\x0c\xbb\x38\x32\x3c\xbb\x22\x28\xa2\x71\xf2\xd2\x82\x56\x1c\x73\xed\x79\xa1\xad\x04\x69\x8e\x27\xef\xe3\x93\x23\x5f\x34\x56\xc2\x95\x40\x7d\xa0\x96\x0f\x00\x34\xd8\xde\xef\xd1\xc1\x85\x73\x6f\xd3\xea\xf1\xf9\xa1\xe3\x2f\x09\x17\x4c\x1f\xe1\x27\x20\xb7\xc9\x6f\xeb\xdb\x33\xe0\x1b\x1b\x6a\x1c\x63\x71\x50\x19\x4b\xe4\xff\xab\x15\x9e\x45\xb2\x45\x85\x57\x68\x46\xbb\x64\x27\x4e\xca\x7b\x39\xa3\xed\x93\x57\xde\x7b\x08\x42\x13\x02\x4a\x9e\x85\x89\x26\x36\x00\xa2\x86\x7c\x2a\x7c\xf8\xb9\x90\x76\xa1\x2a\x07\xbd\x7d\xf8\xd5\x27\x7b\xb0\x4a\xd7\x2e\x63\x9b\x77\xea\xca\x1e\xc5\x8e\xf9\x63\x7e\x9a\x23\x76\xba\x87\x8a\x45\x72\x35\xa0\x6f\x78\xfd\xf0\xe0\xd9\x25\xcb\x2f\xd2\xa3\x8c\x77\x18\x8f\x60\x37\x2e\xf6\x00\x97\x92\x42\x43\x99\xc9\xb6\x79\x28\xda\x2e\x3b\xa9\x1c\xbd\xe4\x07\xe7\xe8\x76\xba\x98\x13\x9e\xd2\x2c\xa3\xb9\x83\xbe\xde\x00\x00\x52\x87\x96\x44\x8e\x4a\x10\x55\xac\xb2\xde\xaa\x56\xbc\x30\x82\x54\xc5\xbd\x49\x8c\x27\x5e\xce\xdc\x13\x57\xef\xe1\xfd\xa0\x1d\x34\xd9\x16\xdd\x4d\x86\x47\xe5\x77\x19\x95\xa6\x53\xe0\xf8\xa5\x28\x4c\xc7\xbf\x73\x15\x7b\x33\x49\xd5\x9e\x6f\x92\x0c\xad\x6c\xdd\x17\x19\xf0\x38\x02\x5c\x43\x00\xe0\x21\x0c\xe2\x49\xfa\xf3\xc8\x2d\xe1\xfd\x1c\xda\xbe\x61\xc1\x4e\xcb\x1d\xf0\x0c\x5c\x46\x6a\xa6\xa0\x12\xa9\xc1\x0d\xcf\xe5\x9b\x7e\x9d\x3b\x15\x5d\xab\x6c\x7b\x7c\x16\x08\xc1\xed\xd5\x1d\xbd\xad\xf6\xba\x58\x76\xb5\xe6\x0f\xdf\x7f\x19\xe6\xef\x71\x2c\xd1\xa7\xdd\x3a\x06\x2a\x65\x74\xa7\x43\x6b\x31\x9e\xfb\x94\x4e\x42\x23\xf5\x42\xb2\x50\x2c\x1b\xa9\x76\xbe\x91\xe0\x5b\x0f\x85\xa0\x9f\xd7\x93\xbe\xca\x88\x33\x75\xfb\x67\xcd\x13\x3f\x52\x84\xd8\x99\x84\xff\x3c\xaf\xa7\xe1\x1a\x9d\x85\xe7\x89\x32\x32\xa5\x24\xec\x54\xb2\x0f\x97\x5d\x3c\x0a\x11\x43\xa0\xef\x41\x17\x6b\x70\x51\xea\x91\xd4\x0c\x5f\x44\xfd\x9e\x10\x05\x58\xbf\x12\x12\xa7\xb8\x91\xe6\x8b\x55\xca\x61\xf4\xbe\x94\x52\x66\xd9\xa1\x00\x7a\x14\xaa\xeb\x68\xc4\x8e\x25\x7f\x0f\x46\x31\x0a\xd1\x64\x81\x46\x7e\xc1\x77\x35\x35\xd5\xfc\x08\x49\x15\xf5\xd0\x04\xba\x0d\xc7\x59\x1d\x21\x23\xc6\x22\x07\x90\x9d\x84\xf2\xb3\x82\xf5\xef\x12\x75\x9a\x95\xcd\x3f\x51\x89\x80\x6e\x27\x39\x60\xae\xe1\x62\xc0\x0f\x73\xe7\xfa\x59\x36\x39\x57\x65\x4b\xb1\x91\x6b\x57\x09\xbb\x0a\x9d\x04\x05\x14\xae\x52\x84\x95\x1e\x6b"}, -{{0x9f,0xc7,0xc4,0x9c,0xb8,0xc4,0xf0,0x97,0x2d,0x6e,0xd9,0x70,0xae,0x2c,0x6a,0xc3,0x37,0xe6,0x75,0x42,0x5c,0xc8,0xdc,0xe7,0x30,0xfc,0x41,0x44,0x43,0x02,0x93,0x5d,},{0x47,0x82,0x52,0x0b,0x06,0xf9,0x33,0x44,0xaa,0x76,0x67,0x80,0xe5,0x44,0x01,0x36,0x3d,0xfd,0x7d,0x96,0x7c,0xc3,0xbf,0x06,0x48,0x8a,0xf9,0x09,0x20,0xa3,0x0f,0x85,},{0x5c,0x78,0x3a,0x86,0x0a,0xa6,0x68,0x18,0x4d,0xd2,0x2c,0x4f,0x9a,0x54,0x6b,0x5e,0xc9,0x6e,0xba,0xd2,0xe4,0xaf,0x00,0xf9,0x68,0xc6,0x88,0x67,0x13,0x54,0xe0,0xcc,0x9b,0x57,0x2c,0x73,0xbc,0x6f,0x19,0x93,0x7a,0x05,0xf1,0xba,0xf3,0x43,0x47,0x63,0x96,0x5c,0x96,0xe1,0x03,0x40,0x7f,0x0e,0xb6,0x42,0xc5,0x64,0x41,0x54,0x29,0x0b,},"\x82\xbc\x2c\x70\x0d\xb2\x22\xa4\xac\x91\x4a\xa2\xbe\x8f\xa2\x8e\x42\x20\x67\xf9\x4f\x33\x44\xf5\x36\x2b\xeb\xaa\xbe\xd7\x61\x2b\x0e\x46\x4a\x73\xa6\xc4\x56\x90\x35\x64\xb1\x53\x93\x48\x51\x40\xdd\x0f\x3a\xff\x90\xaa\x6e\x16\x61\xdd\xf6\x82\x85\x0d\x04\x90\xaf\xc3\xd7\x35\xde\xa0\x5b\xa4\x7c\x85\xd9\x7e\x83\x35\x33\x51\x4c\x19\x8b\x4c\xf6\xe6\x6d\x36\x0e\xe5\xbf\x00\xe1\x4a\x3a\xab\x1a\xd0\xe7\xb8\xab\x2a\xac\xc9\x64\xd4\x28\x30\xc7\x84\x53\xdf\x19\x55\xbb\xed\x1c\xd6\x8a\xda\x3d\xb0\xec\xdb\x60\x1a\xd7\x66\x7d\x5c\x5e\x2f\xd4\x9e\x36\xf7\x32\x8e\xaa\x33\x7d\xbd\x6f\xf7\x0e\x78\x98\xa3\xf9\x8c\x15\x9d\x04\x5a\x24\x27\xad\xe5\x33\x3c\x88\xfc\x4a\xfd\x38\x19\xdc\x82\xf4\xda\xa3\xc5\x23\xcb\x57\xe3\x5a\x2a\x5a\x72\x5d\x63\xd4\x02\xba\xef\x51\xe5\x1f\x1e\xf4\xf8\xf9\xa5\x95\xc9\x37\x9c\x9a\xba\x87\x3f\xb4\xe7\x65\xa9\x31\xda\x09\x14\x8a\xba\x6e\xc5\xb4\x48\x59\xb0\xe8\x1f\xf9\xfc\x22\x95\x98\xac\x9f\xbd\xb0\xbd\xbd\xdb\x56\x92\xa5\x22\x22\xdf\x52\xea\x38\x7b\xbb\xf3\x6a\xd6\x4d\x19\x46\xbd\x28\x2e\x32\x3f\xf4\x82\x2a\xd9\xda\x89\x7f\xf7\x3f\x01\xb3\x90\xcf\xe2\xe6\x4d\xe4\x92\xd5\x5d\xe7\x7f\x5d\x7d\x00\x60\xa6\x87\x2a\x01\x83\xcc\xba\x61\x0f\x53\x27\x4c\xcb\x29\xce\x6d\xce\x6a\x03\x6c\x53\x17\xa1\xed\x2a\x7c\x10\x68\xc1\xb2\x46\xfc\x1d\x58\x81\xd0\x0d\xe0\x6e\xb4\x01\xcf\xf9\x5e\x6b\x69\x14\x86\x99\xdb\x13\xe9\x4b\xb5\xb2\x80\x21\x2d\xff\x54\xc7\x0e\x56\xde\x23\x5a\x5f\x14\x00\xb5\xbe\xa5\x67\x72\xd0\x60\x17\x0f\x1d\x06\x57\x32\x15\x61\xe4\xb4\x91\x07\xeb\x96\xd9\xb3\xbc\x5a\xdf\x45\x1c\x2a\x52\x4e\xba\x4d\xb0\x03\xb7\x7b\x63\x2a\x5d\x89\x82\x7a\x62\x24\xcc\x79\x8e\x09\x6b\xa2\x7f\xb3\x3b\xf6\x1e\x3b\x8e\xaf\x18\xd0\x01\xae\x8e\xb5\x2f\x85\xc9\x0d\x9e\x12\x54\x48\x03\xe6\x7f\xf0\x20\x47\xe0\xd2\x3c\x22\xe7\xf8\xb9\x80\xc0\x1c\x3d\x48\x24\xb2\xa9\xa1\x4a\x2e\x8f\x67\x2a\x7b\x0c\xe0\x3b\xdb\xb3\xbd\x56\xd7\x54\xa0\x96\x4d\xb0\x1c\xa8\x99\xd4\x88\x00\x15\x08\x65\x7b\x7b\x02\x2c\xcf\x04\x2c\x38\xfc\x19\x49\xd0\xe0\x0a\xf4\xd3\x01\xd4\xf0\x0c\x3d\xea\x20\xe3\x08\xa0\xf9\xdc\xac\xb4\x32\x22\xb3\x82\x41\x44\xaf\x77\xbe\x18\xa5\x04\xaa\x8d\x26\x8b\x8a\x56\x00\x72\x5e\x7c\xc5\xf3\xa2\xe6\x25\x6a\x80\x74\xd1\xae\xbc\xa1\x23\xea\x53\xa0\x76\x7a\x92\xe1\x78\x3a\x49\x83\xc5\xef\x3d\x7d\xd7\xf0\x2a\xa9\xd1\xf4\xf9\xaa\xc6\xce\x25\x45\x93\xf0\x87\x92\x01\x4f\xb8\x67\xea\xf8\x79\xb8\x8a\x4e\xfb\x18\xe8\x9b\xa1\x10\x06\xad\x09\xd8\x54\x31\xcc\x26\x57\x5b\x53\x8d\x8e\x78\x90\x64\x6c\x59\x88\x64\x7c\xc1\x05\xd5\x82\x90\x7a\xe6\x25\xe0\x9c\xd0\x89\xf4\x72\x49\xe8\x18\x14\xda\x14\x04\x4c\x70\x14\xe8\x0e\x7a\x8e\x61\x9c\x7b\x73\x5f\x70\x16\x16\xb6\xa3\xc6\xf4\x92\xcd\xc6\xed\x46\x3e\x71\xa3\xd2\x22\x91\x48\x2d\x90\xa1\xde\x6f\x09\x7c\x4a\xe2\x54\x87\x61\x84\xc5\x62\xb1\x65\x75\xb9\xd0\xd1\x93\x13\xed\x98\x86\x4f\x49\xfe\x2e\x1d\x07\x4a\x21\x21\x1b\x2b\x2a\x6d\x27\xdd\xb2\x86\x11\x52\x0d\x5f\x71\x23\x05\x8f\xd0\x07\xbb\x01\x00\x1d\xef\x07\xb7\x92\xbb\x05\xbb\x74\x1c\x12\x9c\x6a\x36\x37\x6c\x38\x53\xb8\xbb\x4f\x66\xb5\x76\x0c\x8e\xb4\xec\xc7\x30\x6b\xa3\xa9\x0c\x70\xda\x47\xc9\x65\xf6\xdc\xcb\xdb\x61\xa7\xfd\xa1\x8e\xe9\x67\xcf\x8c\x5f\x05\x03\x11\x09\x2d\x0f\xde\xea\xed\xd1\x26\x5d\xef\xdd\x66\x0a\xbe\x70"}, -{{0x08,0xbf,0x05,0x9b,0x4d,0xa9,0xaa,0x7f,0xfc,0x70,0x2f,0x5b,0x23,0x04,0xc4,0xf9,0x6c,0xa4,0x9b,0x7d,0xab,0xb6,0xaf,0xb4,0x1d,0xc9,0x1c,0x0f,0x00,0xc6,0x5b,0x78,},{0xa6,0x28,0x9b,0xa2,0x8e,0x80,0xe8,0xd1,0xa3,0x19,0x22,0x3e,0x41,0x65,0xdc,0x0b,0xce,0x73,0x52,0xaa,0xf2,0x42,0xf7,0x0c,0xc9,0x68,0xd2,0x1d,0x77,0x75,0x28,0x32,},{0xe2,0x47,0x65,0x86,0x01,0x37,0x68,0x9a,0xad,0x50,0xeb,0xee,0xfc,0x8d,0x6d,0xb8,0xe9,0x36,0xa4,0xcb,0xa6,0x2c,0xe8,0x7a,0x7f,0x58,0x02,0x09,0x38,0x4a,0x9d,0x7e,0xec,0x90,0x70,0x90,0x5f,0x60,0xad,0x63,0xa7,0xbe,0xfd,0x7c,0x70,0xf0,0xae,0x7c,0x81,0x09,0x16,0x9a,0xee,0x4e,0x51,0x8f,0xce,0xbf,0xac,0xa7,0x23,0xc5,0xb2,0x07,},"\xbd\x4f\xb2\x8a\x1d\xd0\x8b\x07\xba\x66\xe1\x7f\x0c\x4f\x21\x85\x3f\xef\xef\x1c\x9d\x20\xba\x79\x77\xf1\x54\x64\x1e\xa1\xa1\x8b\xec\xf6\xbb\xb8\x03\x88\x88\x62\x94\xe0\x75\x6a\x3c\x50\x8f\xfd\xfe\x90\xb5\x1e\x13\x56\xd1\x12\xd8\xcd\xe5\xee\x2c\xc6\x33\x2e\x61\xd1\x69\xcc\xc8\xcc\x93\x49\x94\xf1\xbb\x56\x0f\xa4\x66\x0c\x0b\x0f\xd4\xe8\x14\x9a\x22\x5e\xd4\x88\x3e\x68\xfb\xb6\x9d\xa7\xaf\x8a\x52\x4b\x17\x14\x1c\xcb\x76\xb5\x0c\xd8\xe1\xb6\x7d\x3c\xe0\x37\xde\xd7\xdf\xa5\x9b\xc7\xc2\x67\x42\x26\xec\x7e\x07\xb7\x8e\xa3\xf7\x82\xfd\xa3\xe5\xf1\xe9\xca\xea\xb6\x08\xca\x38\x7c\x30\x46\x54\xf8\x01\xd0\x0e\x10\xa7\xc2\x9f\x4b\x0d\xa3\xe5\xf8\x95\x13\xa9\x80\x37\x71\x9a\x1a\xef\x4c\x25\x06\xc1\x77\xaf\x54\x51\xa0\x07\x57\xa5\x9f\x16\x22\x9c\x4f\x44\x14\xdf\x51\x58\x0d\x48\x21\x0d\xab\xc9\x37\x73\x70\xb6\x06\x8a\x88\xe8\x1d\x3a\xd1\xbe\xd4\x98\x51\x55\xc3\x60\x0f\xf4\x87\x68\xb9\x03\x02\x2f\xe0\x2a\xe4\x80\xf2\xe6\x32\x9f\x0b\xcc\x91\xd7\x5f\x5c\x6a\x09\xfd\xf7\x7b\xde\x90\x49\x9f\x3c\xa3\x95\xcb\x20\x06\x2a\x09\x84\xad\x6a\x01\x41\xfd\x01\xc2\xd5\x4d\xfb\xb1\xee\x58\x46\x10\x64\x07\x73\x43\x9a\x16\x58\xd2\xc9\xf8\x62\xf1\x83\xbf\xef\xb0\x33\xa3\xbe\x27\x18\x12\xf1\x3c\x78\x70\x46\x57\xe7\xfb\x4f\x85\x01\x75\xfc\xd6\x3d\x3e\x44\x05\xd1\x92\x24\x2c\x21\xf2\x7c\x51\x47\x7f\x32\x11\xa9\xce\x24\x8e\x89\x2b\x42\xfb\x6d\x85\x82\x0f\x41\xb8\x97\x83\x6f\x20\xf8\x5a\x13\x11\x53\x4b\x5c\x40\x4f\x8b\x7a\x4a\x03\x19\xbc\x6c\xec\xaa\x57\xfe\x4d\x4f\x20\x60\x7c\x99\xc2\xdf\x22\xfa\x06\x76\xf9\x9d\x1b\xd8\x78\x86\xc9\x28\xc4\x98\x8c\x6e\x78\xc5\x7d\x75\x83\x30\xe6\x92\x2c\xbe\x03\xc1\x03\x40\x25\x3d\x0d\xd4\x83\x79\x2c\xe7\x5e\x6c\xd0\x9d\x12\xfb\xbb\x04\x1f\x02\x05\xe6\x5a\xd2\x5c\xe7\xc1\xb2\x4e\x77\xee\x8d\x6f\x91\x5e\x3b\xc3\xe1\x0d\x09\xfb\xd3\x87\xa8\x4b\xda\xab\xfd\x1c\xed\xb5\x2c\x0b\x17\x33\xb5\xf4\x70\x88\xc0\xd3\x5e\x0e\xf4\x58\xc8\x54\x14\xc2\xb0\x4c\x2d\x29\xf6\x3f\x77\x58\x61\x31\xee\x65\x53\x0f\x20\x9b\x51\x8a\x0f\x25\x7a\x07\x46\xbb\xd5\xfe\x0a\x2e\x0c\x38\x8a\x6c\x48\x0e\x1b\x60\x71\x4f\xee\x1c\x59\x41\xbb\x4e\x13\xf7\x07\xea\xc4\x87\xa9\x66\x6a\x72\x3b\x57\x93\x13\x4a\x26\x8b\x77\x59\x77\x86\xc3\xa3\x19\x3b\x46\xd3\x55\xdd\x08\x95\xfc\x62\x16\xc5\x36\xa5\x42\xff\xd7\xd7\xb0\x80\x10\xc8\x6f\x54\x7a\x5d\xaa\x38\x33\x5a\x8b\xfa\x26\x55\xd5\xf7\x1b\x4d\x88\x07\xf5\x0c\x85\x45\xc5\x83\xdd\x0b\x69\x00\x22\xee\x65\x87\x3a\xea\x3e\x8f\x1a\x56\x5f\x3b\x0e\x4e\x02\x95\xfb\x0d\x32\x1f\x5c\x0b\x39\x7f\x2f\xd0\x52\x8f\x86\xa0\xd1\xb7\x07\xf7\x37\xb1\x75\xc6\x9e\x9e\x7a\xe3\xc8\x4d\x4b\x2c\xf3\xa3\x8a\x63\x1a\xa8\x03\x2b\x3e\x65\xbb\x45\x28\xf6\x6d\x0b\xfd\x34\x47\x3e\xd0\x10\x1d\x2a\x61\x25\x5b\x21\x5b\xc1\xcb\xab\x9a\x26\xd2\xb9\x69\x32\x4b\x77\xc8\xa5\x46\x4e\x5b\x23\xdf\x6c\x51\x12\xf9\xd1\x7c\x58\x7d\x95\x55\x9d\xe2\x12\xad\x24\x1d\x8b\x12\x60\x50\xe5\xfd\xdf\xcc\x83\x9a\x7e\x5a\xa2\xfd\xa1\xca\x20\xc0\x91\x0d\x86\x34\x18\xf1\x95\xb3\x8a\xdf\xcc\x36\xe9\x2f\x23\x96\xac\x31\x44\xb5\x37\xb3\x0f\xbe\x4d\xde\x61\x49\x02\xf8\x99\x78\xb7\xfb\x42\xcd\x99\xf1\x3d\x99\xc4\x5c\x73\x4f\xb8\x2c\x32\x59\xf9\x0b\x88\xfd\x52\xbd\xcb\x88\xf7\xee\xec\xdd\xe4\xc2\x43\xd8\x80\xba\xc7\x61\x4e\x15\xcf\x8d\xb5\x99\x3f\xfa"}, -{{0xdb,0xbd,0x0f,0x7e,0xcb,0x64,0x82,0xcb,0x01,0xc4,0xdb,0xdc,0x38,0x93,0xc0,0xdb,0x81,0xe8,0x31,0x35,0x3a,0x5b,0x01,0xcc,0x75,0xd3,0xb1,0x1f,0x2f,0xf3,0xc5,0x9c,},{0x2d,0x4e,0x58,0x8d,0x31,0xa3,0x84,0xb1,0x78,0x58,0xc0,0xd7,0x84,0xf6,0x71,0x2b,0xaf,0xd0,0xb4,0x12,0x04,0xcf,0x8f,0x0d,0x57,0x97,0x3e,0x59,0xc7,0x70,0xd3,0xda,},{0x96,0xc0,0x03,0x61,0xfb,0x71,0xc5,0x23,0x05,0xe1,0xab,0x77,0x07,0xe0,0x46,0x52,0x03,0xeb,0x13,0xdf,0x3e,0x06,0x55,0xf0,0x95,0xfb,0x33,0x19,0x42,0xa4,0x0b,0x15,0x58,0x41,0x43,0xb3,0x70,0xa7,0xdd,0x57,0x61,0xfb,0x03,0xc0,0x75,0xd0,0x4a,0x83,0x48,0x66,0x1c,0xce,0xa9,0xad,0xa5,0x33,0x65,0xb5,0x00,0x08,0x7d,0x57,0xec,0x0c,},"\xe0\xff\xf3\x59\x75\xeb\xa7\x8d\xa2\xb0\xff\xcc\x5c\x1b\x66\x36\x00\x88\x8e\x82\x55\xcd\x20\x8f\x6d\xce\x7e\x88\x95\x3b\x71\x42\x93\x73\x89\xa3\x37\xae\x82\xf4\xcf\xe3\x2f\xcb\x34\xf5\x52\xa4\x8f\xa8\x89\x9e\x1a\x65\x9e\x3e\xd3\xd3\xd2\x90\xef\xc9\xa0\xf7\xde\xdf\x33\xe2\x1d\x04\x8d\x8d\x91\x07\x57\x03\x7b\x76\xe8\xa7\xee\x9e\x4e\xca\x30\xf5\x29\xdd\xc0\x2c\xef\xfc\x26\xd6\x4f\xda\x73\x03\xcc\x0d\x89\x40\xe9\xef\x59\xdc\x98\x3c\x12\xcc\xd1\xd2\x71\x7e\x64\xd3\x00\x6a\xf8\x2a\xb1\x5b\xb8\x78\xbb\x89\xd1\x75\x8b\xe4\x43\x10\x42\x06\x38\xb9\x6a\x0b\x5e\x1e\x65\x00\x9d\x69\x39\x5d\x02\x7a\x5d\xa4\xa8\x5e\x90\x1b\xe9\xaa\x2c\x0b\x3a\xcc\x50\x8e\xe1\x85\x74\xc1\xb2\xfa\x9b\xd5\xd7\xae\x7c\x7d\x83\x07\x12\xda\x5c\xbf\x26\xbe\x09\xa3\x12\x84\x70\xa1\x2a\x14\x90\x9a\x80\xa2\x66\x65\x9b\xef\xda\x54\x8f\xd2\xb2\x2f\x24\xc5\xfd\xc2\x06\xed\x3a\x4e\x75\xf5\x32\x06\x82\xed\x0e\x4c\xe8\x17\xd6\x3d\x5c\x7f\x1e\xe2\xb4\x40\x64\x33\x55\xbe\x65\x42\xf5\x9d\xc6\xc4\x5a\xb1\x57\x72\xf2\x21\x9a\x81\x2e\xf7\x52\x76\x42\x01\x5b\xc7\x5f\xe4\x5b\xa9\x69\xe8\x10\x0c\x26\x8e\x24\xce\xef\x92\x05\xa8\x3a\x3f\x7b\x5a\xe8\x00\xad\x06\xe0\x95\xb9\xb1\x39\x21\x94\x89\x79\x3a\x7b\xce\x84\xeb\xeb\x65\x4a\xb6\x66\x9e\x28\x55\xcc\xbe\xb6\x94\xdd\x48\x65\x15\x05\xb9\x59\xd3\x2a\x77\x02\x0b\x86\x95\x33\xe3\x25\x6d\x40\x68\x5a\x61\x20\xba\xb7\x94\x48\x5b\x32\xe1\x16\x92\x56\xfb\x18\x8f\xe7\x6e\x04\xe9\xef\xa6\xd1\x0d\x28\x6a\xe8\x6d\x6f\x1c\x87\xe8\xfc\x73\xad\x9b\x59\xfe\x0c\x27\xee\x92\xa4\x64\x15\xb3\x9d\x78\x6d\x66\x32\x5d\x7f\xa6\xfd\xa7\x12\xf1\x99\xda\x55\x4f\xc1\xc8\x99\x44\xa4\xe8\x4c\x19\x6e\x97\x9a\x80\x75\x53\x71\x8c\xb8\x1c\x07\x6e\x51\x1e\x60\x9d\x5c\xac\x23\xd8\xf4\x5b\x38\xb9\x4b\xcf\xcf\x15\x8d\x0d\x61\x60\x22\x38\xd5\x2e\x3a\xe8\x4c\x81\x53\x22\xf5\x34\xf2\x54\xe6\x33\x89\xae\x15\x5d\xee\x2f\xa9\x33\x96\xf0\xea\x49\x9d\x5d\x08\xc2\x47\x59\x08\xc6\x48\xbd\xdc\xee\x59\x1e\x13\x37\xe9\x42\x1d\xc5\xa2\x57\xce\x89\xcc\xce\x4c\xee\xa8\x09\xd7\xe8\x71\x34\xe0\x39\xdb\x1b\xe5\x98\x19\x6d\x30\x89\xfd\xcf\xa8\x97\x8e\x02\xc1\x55\x58\x32\xda\x0a\x72\xb0\x8a\xd0\x7c\xdd\x07\x26\x27\x40\x9c\x87\x39\x37\xb0\xe8\x35\x71\x5b\xaa\xf2\x60\x8b\x23\x95\x32\x74\x67\xcf\x69\xa1\xcd\xcc\xe6\x37\x24\x18\x38\x3e\x7b\x89\xc8\xdf\x4d\x53\x1f\x58\x51\x49\x50\x9e\xad\x1e\x41\xb6\x62\x7f\xea\x81\xc7\x95\x8c\xb4\x9d\x2d\x3c\x3e\x2f\xc6\x91\xe0\xb8\xcf\x72\x67\x9c\x08\xb8\x90\x46\x54\x53\x1b\xc4\x36\x8f\xb6\x17\xac\x75\x57\xd9\xdb\x8d\x32\x9d\x77\xe4\x8d\x8f\xb4\xde\x73\xab\xe7\xcb\x93\x88\x27\x4a\xf5\x85\xf8\x75\xc0\xda\xb7\x93\xe4\x35\x35\x18\xbb\x24\x69\x53\x42\xaf\x0f\x5d\xf5\xbe\x4e\x9c\x7a\xd2\x15\xbe\x90\xe2\x55\x40\xda\x34\x89\x71\x7d\xd3\xd2\x92\x54\x58\x5a\x45\xc1\x3e\x6d\xcc\x7e\x9c\x8a\x3a\x79\xff\x75\x5c\xbe\x46\x5b\x25\xe2\x3a\x1d\xa6\x08\xe1\x08\x4f\xec\x83\xbf\xf8\x0c\xfb\x74\x42\xb1\x46\x01\x87\x30\x7a\xcd\x75\xe3\xf2\xd1\x28\x43\xa7\x70\x94\xac\xc3\x28\x88\xfb\xe5\xf1\xfc\x24\xc6\x15\xd1\x9a\x06\x53\x91\xd4\x17\x64\x74\x64\x42\x46\xb5\x34\x3d\xa7\x76\x26\xa2\xd4\x83\xfe\x20\x4f\x83\x93\x28\x77\x5b\x71\xa4\xcb\x56\x72\x73\xe1\x69\x64\x0a\xf9\x3d\xde\x3e\xca\x91\x16\xf4\x00\xe2\x3a\x7a\xd3\xd8\xfc\x3a\x28\xe5\x65\xf1\x25\xd6"}, -{{0x74,0x8b,0xb3,0xcd,0x47,0x71,0x37,0xbc,0x88,0x0e,0xa7,0xc6,0x1d,0xf2,0x5c,0x1d,0xac,0x6e,0xbe,0xc9,0xe6,0xc3,0x19,0x3d,0x81,0xff,0xa6,0xf7,0xa8,0x1e,0xc6,0x67,},{0x10,0x6f,0x28,0xcf,0xed,0xf0,0x96,0x45,0x42,0x26,0xb3,0xb0,0x1f,0xc2,0x4a,0xb1,0xc9,0xbb,0xd7,0xf2,0xb0,0x97,0x3e,0x56,0xfe,0x2f,0x4c,0x56,0xa0,0xb1,0x47,0x5b,},{0xe1,0x3c,0xa8,0xe5,0xce,0x7c,0x26,0x80,0x90,0x90,0x8d,0x61,0xcf,0x2f,0x0a,0x3e,0x45,0x72,0x41,0x2b,0xf5,0xad,0xfc,0x5a,0xdd,0xfe,0x88,0x55,0x6f,0x14,0x8b,0x5f,0xcb,0xe3,0xe1,0xbc,0x65,0xff,0x16,0x11,0x7d,0x35,0xc9,0xd5,0xdc,0x3b,0x11,0x71,0x98,0xf8,0x84,0x92,0x5b,0x40,0x35,0xb2,0xc0,0xde,0x6c,0x40,0x2e,0xd4,0x7a,0x01,},"\x00\xde\x6d\x99\x0c\x84\x33\x8a\x39\x8f\xda\x5f\x4a\x2c\xca\x73\x3c\x56\xb2\xa2\xea\x39\x6c\x2f\xe6\x67\xc2\x68\xe3\x81\x45\x87\x85\x39\xbd\x41\xbc\x14\x0a\x2c\xdf\xe7\xe1\x83\x60\x41\x10\x48\xcc\xa6\x0f\x35\xce\x51\x09\x91\xdf\x26\x1c\xbf\x66\x90\x39\xd9\xd2\x56\x87\xa0\x7f\xc0\x47\x6a\x41\xf5\x0e\xcc\xf3\x81\x53\xee\x6a\xe9\xff\xd3\x92\xb2\xbe\xc0\xcc\x67\x10\x1e\xc3\x69\x6d\x7a\x2e\xc8\xcb\xd4\x47\xb6\xa6\xea\x06\x3d\x33\xec\x12\x8a\xe8\xb5\x75\x77\xde\xe1\x7b\x97\x16\x25\x63\xf1\x5e\x42\xb5\x5c\xa4\xbe\xdb\xdf\xb6\x31\xa9\xf6\x26\x2f\x94\xae\x35\xbb\x35\xf7\x95\xc3\x5a\x01\xde\xdb\x46\x45\xa7\x3c\xfa\x6e\xd9\xee\x52\x1e\x46\x31\xfb\x17\xbb\xc0\x6e\xe5\x73\x16\xbe\x52\x74\x27\xc8\xaa\x55\xc6\x31\x18\x74\x62\xd4\xb2\xc8\x82\x2c\xa4\xe1\x8b\x7a\x5d\x4c\x11\x4c\x11\xdc\x22\x06\x9b\xc8\x32\x65\x6d\x5f\x4d\x39\x54\x87\x18\xc5\x1f\x5e\x4f\xc8\x28\xf6\x0e\x37\xf0\x13\x07\x50\x52\x65\xac\xb2\x2d\x5e\x8d\x76\x7b\x9a\xa7\xb8\x66\xa1\x57\xc6\x43\x87\x3e\x09\x08\x4a\x1a\x40\x4a\x7b\xb5\x8c\xcc\x4b\x5a\x39\x0f\xd3\x06\x01\xc8\x96\x93\x5e\x35\x56\xf6\x0d\x2d\xc6\xbd\xff\xe4\x7d\xa0\xa6\x87\xc8\xec\xe1\x24\x1f\xf6\xc0\x7d\x77\x61\x11\xca\x65\x98\xfc\xa9\x68\xcb\x6a\xfa\x0a\x14\xa3\x4a\xb8\xf5\x4b\x95\xd3\xd8\x47\x3a\x17\x4b\xc7\x25\x52\x3f\x86\x74\xdf\xb2\xb1\x0f\x87\x42\x07\xfe\xe1\xb0\x8b\x42\xda\x1f\x58\x65\x53\x05\xa3\x59\x75\x7a\xa0\x25\x1f\x14\x13\x8e\xed\xbc\x28\x0c\xbd\x38\x5b\xf4\xbb\xf5\x53\x01\x14\xcc\x43\xb0\x47\x47\x79\xe2\x04\x96\x2f\x85\x60\xd4\xaa\x42\x3e\x17\xe6\xae\xca\xce\x66\xc8\x13\x78\x4f\x6c\x89\x8b\x5b\x9c\xb7\x46\xa9\xe0\x1f\xbc\x6b\xb5\xc6\x60\xf3\xe1\x38\x57\x4f\x59\xb9\x74\x54\x45\x48\x6c\x42\x2b\xc0\x6a\x10\xcc\x8c\xc9\xbc\x56\x45\x8e\xf8\x5e\x0e\x8a\x02\x7c\xb0\x61\x7d\x03\x37\xdd\xda\x50\x22\x0b\x22\xc5\xc3\x98\xf5\xce\x05\xec\x32\xf0\x9b\x09\x0f\x7c\xf6\xc6\x0f\x81\x8c\x6b\x4c\x68\x30\x98\x3e\x91\xc6\xea\xdf\x1e\xae\x4d\x54\xbd\xe7\x54\xf7\x5d\x45\x0a\xe7\x31\x29\xf6\xc4\xff\x5c\x4c\x60\x6f\x7c\xad\xbf\x4f\x78\xa1\x8d\xb2\x96\x1c\xc8\xc8\xdd\xab\x05\x78\xcf\xed\xfc\xf9\x5e\xf0\x88\x8a\xfd\x38\x55\x37\xd1\xd0\xa0\x76\x48\xa5\xce\x25\x22\xd0\x63\x35\x07\xd7\x75\x93\xe1\xa0\x36\x6d\x1e\xce\x84\x3d\xe6\x98\x67\xd7\xac\x44\x2b\xa7\xda\xd2\xa9\x0b\x59\xd8\x98\x4e\x4a\x94\x6b\xbe\x5f\x17\x2d\xa4\x27\x63\x8b\x2b\x61\x20\x90\x41\xff\xf5\x0e\x60\xec\x02\xec\x2c\x0b\x1d\xc4\xbe\x2e\xdd\x13\xe8\x7b\x64\xd1\xd1\x66\x31\x14\x57\x3c\xf5\x8a\x17\x73\x9f\x46\x3a\x1c\x3d\x6b\x21\x23\x39\x01\x83\xb5\x05\xc8\xee\xff\xb2\x05\x39\xbd\xfe\xeb\x40\x77\x6d\x20\xc4\x59\xba\xc4\x56\x99\x68\xfc\xaf\xe4\x4e\xa4\xcd\x62\x4a\x84\xbf\xcc\xd7\x87\x6d\xd7\xbf\x55\xf8\x3a\xc7\x04\x0e\x30\xf3\x26\xdc\xe3\x25\x58\x8e\x1b\xa5\xbc\x07\x90\x26\x5d\xfd\xba\x09\x83\x9e\xef\x57\x16\x41\xe8\xa1\x23\x4b\x6c\xfc\x3a\x36\xa8\x66\xbd\x6b\x92\xcd\x71\xec\x74\xe0\xd4\xde\xb9\xe7\x4d\x15\x82\x01\xaa\x50\x2f\x07\xc8\xba\x34\x8a\xc2\x6a\xaf\x9b\x3d\x07\x0c\x9a\x40\xb5\x2a\x44\xe9\x32\x55\x2b\x67\xa2\xdf\x05\xa7\xf0\xf0\x3c\x61\x7b\x48\xdc\x27\x82\x36\x6a\x23\x1e\x0c\x4e\x39\x38\xa4\x27\x4b\x36\xaa\x94\x50\xff\x93\x6b\xe1\x32\xdc\xb6\x92\x83\x8d\x65\x4c\x94\x54\x2c\x6e\x04\x7a\x7f\x78\xba\x71\x19\x19\xf9\x08\xa1\x5b\x30\xb9"}, -{{0x39,0x3d,0x44,0xdd,0x0d,0xed,0x71,0xfc,0x08,0x47,0x7b,0xd2,0x5e,0xd0,0xe6,0x62,0x9f,0xa7,0xf8,0x8f,0x08,0x2e,0xbc,0xef,0x09,0x18,0x98,0xe5,0xc9,0xe3,0xd5,0xb8,},{0xc5,0x2a,0x99,0x3b,0x80,0x2d,0x84,0x54,0x0d,0x27,0x54,0x79,0xa1,0xaf,0x5e,0x28,0x7d,0x19,0xea,0x13,0xb3,0x80,0xfa,0x30,0x68,0xd2,0xf2,0xc6,0x8e,0xb9,0x7a,0x09,},{0x84,0xc7,0x16,0xe6,0x0d,0xe6,0x7b,0x02,0x0c,0xc1,0xa6,0xa2,0x4e,0x65,0x49,0xfe,0x56,0xc6,0xd9,0x41,0xa8,0xed,0xea,0xe4,0x07,0x62,0x66,0x66,0xc3,0x1c,0xb6,0x0d,0xee,0x6b,0xe5,0xa7,0x1e,0xbd,0x76,0xba,0xf7,0x1b,0x75,0x11,0x4b,0xcc,0xfd,0x37,0xd1,0x63,0xa9,0x68,0xbb,0xee,0xc1,0xf7,0x69,0x72,0x15,0x12,0x96,0xc4,0x7e,0x07,},"\x14\x2b\x6e\x82\x50\x13\x62\xd5\x5a\x04\xb8\x9d\x54\x1a\x79\x68\x63\xd7\x78\x38\x40\xd3\x4c\xbd\xfc\x51\x6a\x3c\x84\x77\x2f\x92\x44\x6f\x5f\x0d\xf4\xc4\x5c\x6e\x0d\xc8\xec\x1e\x9b\xb0\xff\x7e\xc1\x69\x6a\x09\xcd\x7a\xe3\x4c\x10\xf8\xe6\x1a\x9a\xca\xbd\x43\x03\xf0\xa9\x24\x72\x37\x62\x1c\x49\x0e\x8d\x9d\x0f\xe4\x44\x82\xc5\x60\xd0\x51\xb8\x2b\x07\x4a\xc3\xd8\xe4\x9b\xb2\xac\x71\x5a\xc4\xcd\xe3\xd4\x70\x9d\x0e\xa3\xaf\xc5\x1b\xfd\xef\x4b\x65\x67\x71\xfb\xd5\x5f\x89\xda\x9f\xa6\xdc\xaa\x62\xcb\xae\x56\x12\x08\xd9\x8c\xfa\x24\xcb\x81\x25\x2b\x89\x5f\x6a\x4a\x92\xc8\xe4\x07\xaf\x6c\x1f\x1e\xf4\x9d\x8d\xde\x15\x4f\xbc\xb1\xca\x45\x7a\x20\x4b\x5e\xa5\x43\x2e\x4d\x71\xfb\x7e\xb2\x4d\x43\xf6\xfe\x25\xe7\xb4\xc6\x59\xb0\xee\xbc\x4c\xbc\xc8\xb3\xcf\xde\x07\xc8\xf0\x7b\x18\xa5\x15\x70\xe7\x16\x3e\x33\xb3\x17\xb6\x13\x60\xf9\xce\x08\xd9\x5d\xe2\xc3\x15\x6a\xf1\xcc\xc9\xb5\x5b\xcf\x81\xea\xbf\x3c\x40\x43\x40\x46\xbb\xe8\x2e\x02\x99\x2a\x2a\xc8\xb3\xb4\x25\x68\x0a\x23\xd9\x34\x72\x6c\xb1\xb7\xbf\x26\xce\xb5\x2a\x39\x02\x2c\x00\xac\xf4\x25\x25\x71\x67\xb8\x21\x18\x5f\x68\xe3\xed\x17\x90\x3d\x8d\x22\x27\x54\x98\xc3\x9a\x9e\x8d\xf8\x84\xec\x00\x55\x8d\xcf\xa4\x3b\x8a\x11\x9c\x2e\x85\x3b\x9a\x03\x18\xbb\xea\x08\x7f\x9c\xec\x17\xca\x49\xb7\x08\x17\xb8\xd7\xc1\x70\xa8\x90\x6f\x3e\xe9\xe8\xf8\xcb\x27\xa1\xd0\xf5\x75\xab\xfa\x62\x7e\x88\xf0\x8c\xa4\xb9\x3c\x32\x97\xc4\xf3\x17\x07\x2f\x42\x1c\x5e\x60\x2e\x2f\x83\x1d\xfb\x82\x55\x1b\xdc\xe8\xd7\x12\x16\xf0\x5c\xf9\xa2\x77\x3b\x90\xfc\x93\xb9\xd8\x55\xa9\x1e\x35\xad\xe3\x32\xa5\x06\x1f\xdb\x82\xb3\x09\xba\xb4\xf5\x6e\x2d\x58\x6a\x84\xc6\x74\x81\xd1\x90\x2c\x26\x1b\x3f\x97\xdc\x30\xb1\x84\x61\x9d\xf9\xfd\xfc\x7a\x32\x9d\x06\x1a\x41\xdf\x33\x22\x02\x13\x3d\x8e\xae\xed\xdb\x4c\xfc\xee\x53\x53\x6e\x07\xaa\xd1\x15\x53\xdc\xf5\xed\x1e\x94\x9d\x45\x35\x5f\x9e\xf4\x2c\x78\x32\xb0\xde\x7c\x2f\x15\x26\xfb\xef\x86\xb6\x36\x49\xb6\xb8\x5a\xe5\xca\x86\xf0\xce\xa6\xdf\x9c\x12\x6c\x1d\x79\x48\x9c\xc3\xbf\xc6\xe8\xbf\x03\x46\xeb\x30\xd0\x16\x43\xc0\x10\x15\x0c\x5c\x8d\x0e\xb5\x01\x0a\x46\x11\x22\x15\x13\x79\x91\x08\x5e\x57\x49\x3b\x22\xe8\x35\x26\xb7\xb1\x72\xc6\xc7\x34\x1c\x40\x32\x1e\x9c\xeb\x7c\x82\xbf\xba\xa4\x8f\x3b\xd8\xf5\x13\x72\xd9\x6d\x47\x44\x4f\xf0\xd8\xbb\x2e\x5f\xd2\x65\x14\xeb\x63\x91\x05\xe3\x38\x95\xfd\xc4\x1f\x6d\xf1\xfb\xfd\xcb\x08\x46\x6e\xc2\xd2\x17\xfc\x99\xfb\x01\x2f\xe6\x54\x0c\x0c\x5a\x59\x66\xed\x3e\x66\xfa\xb1\x20\x2a\xb9\xda\xff\xe8\xe2\x7e\x8f\x74\x62\x82\x8d\x66\x26\x59\xea\x3b\x2c\x60\x8c\xf6\x8e\x30\xdb\xac\x62\xff\xd8\x22\x9f\x4a\x53\xf5\x9a\xe1\x68\x33\xb8\x1a\x15\x91\x61\xf1\x93\x69\xf6\x0f\x51\xc4\x3a\x21\x7e\xfc\x5e\xfd\x6a\xb7\xa9\x1f\xe2\x49\xc7\xb8\xa0\xc1\x4e\x9f\xae\xa5\x33\xde\x13\x38\x49\xa9\x24\x47\x67\x6f\x6c\xc1\x8b\xef\x4f\xec\x7f\x37\x31\x97\x59\xce\x80\xea\x3e\xac\x18\xfa\x2d\x9f\xa0\x23\x09\xe1\xce\x93\xac\x6c\xf4\xcd\x2c\xb2\xc9\x5f\x1e\x2a\xff\x7b\x2a\x88\x56\x40\x5a\x7b\x8e\xba\xbe\xb4\x90\x6d\x9b\x97\x34\xda\x9f\xb5\xe5\xd3\xf3\x22\xbb\x5b\x55\x9f\xa6\x1e\xc8\xf5\x15\xdb\x90\x65\xab\x4b\x91\xa7\xa3\x1d\x5c\x62\x50\x61\xc2\xfd\x2b\xcf\xe1\x7f\x94\xbb\xde\x47\x76\x30\x2b\x8a\xef\x3d\x5b\x52\xdb\x3b\xc7\x3a\xe4\xa3\x0c\xc4\x41\x7a\xcb"}, -{{0x71,0x19,0x36,0x40,0xa0,0xa2,0xb2,0x2f,0xb2,0x2d,0x00,0xa8,0x0b,0x33,0xa5,0x51,0x4f,0x3d,0x10,0x00,0x03,0x4f,0xcc,0xd8,0x85,0xd8,0xea,0x86,0x38,0xf0,0xb0,0xf8,},{0xb1,0xd3,0x6f,0x72,0x3b,0x70,0x86,0xd9,0x23,0x11,0x9f,0x46,0x75,0x9b,0x39,0xfa,0x1e,0x40,0x38,0xc6,0x41,0x8c,0x37,0x9b,0xa9,0x8b,0x58,0x40,0xc7,0xea,0x50,0x68,},{0xa9,0x70,0x2a,0x33,0x95,0xac,0xd2,0x0d,0x75,0x43,0x73,0x09,0x5d,0xc6,0x14,0x45,0x58,0x4d,0x8e,0x57,0x10,0x80,0xe1,0x79,0xad,0xcb,0xa3,0x10,0x6b,0xb0,0x6a,0x7c,0xe4,0xd4,0x60,0xf1,0x26,0x1a,0xef,0x86,0x43,0xab,0x16,0x34,0xf4,0x7c,0x94,0x14,0xa3,0x2e,0x18,0x3a,0x32,0x76,0x91,0xe6,0x58,0x43,0xdd,0x6c,0x05,0x50,0x72,0x07,},"\xe0\x28\x79\x48\xbb\x85\xa3\x98\xe6\xaf\xfa\x2d\x25\xfc\xff\x8b\xdb\x93\x26\xf5\xd1\x4f\xde\xb6\x05\x49\xf5\xfb\xf0\xc1\x81\x6f\x11\xcb\xdd\x4e\x90\xfe\xa0\x39\xdc\xa6\x0f\xaa\xd1\x69\x60\x03\xf9\x15\x15\xc9\xb2\x72\x88\x2c\x95\xc9\xa4\xab\x6e\x27\x77\xbd\x92\x7e\x7d\x84\x42\xae\xa6\xce\xa6\x19\xc9\xb1\x52\x55\xfe\xd6\x12\xb5\xcc\x31\x58\xfc\x70\x5b\xb7\xa5\x06\xf4\xaf\xec\xf4\xe3\x4e\xd5\x17\xb2\xc1\x2b\x83\x62\x61\x0e\x5e\xa2\x70\x48\x5c\xcc\xb3\xc9\xaa\x97\xec\xd6\xcb\x19\x63\x09\x00\xf0\x7d\x94\xcb\x29\x3c\xb6\xe0\x89\xa9\xa7\x7c\x01\x94\x07\x3a\x7f\x71\x77\xb0\x23\x0d\x25\x76\x3a\x2e\xf9\x8d\x47\x70\x4c\xb2\xc3\xaf\x4c\x3c\x1b\x49\x56\x31\xb4\xa5\xb2\x1b\x2e\x56\xbf\xf2\xed\xe0\x3e\xa4\xfe\x7c\xf8\x29\x17\x34\x7e\x3a\x9d\x4d\xbe\xef\x37\xd1\xcf\x17\x61\x5a\xda\xa0\xfd\x17\x05\x79\x69\x91\x7d\x47\x8d\x03\xcc\xd8\xf8\xb8\x8e\x5e\x5a\xca\xe6\x73\x2a\x81\x61\xdf\xb5\xf7\xd0\x21\x23\xc8\xd5\xa5\x65\xcf\x4d\xd9\x8d\xfc\x9a\xaf\x5a\x33\x50\x58\xa9\x41\xca\x43\x07\x3f\x26\x59\x61\x5a\x72\xfe\x78\xc1\x01\xc4\x1a\xed\x07\xf3\xbc\xf9\x80\xb0\xa5\xb3\xfb\xaf\xdb\xbe\xa9\x2f\xd8\x89\xcf\xd5\x3d\x40\x32\x78\xbc\x15\xa5\x9a\xa1\x40\xc2\xd7\x73\xb8\x88\x9b\x96\x3d\xce\xa3\x65\x36\x2e\x42\x6e\xf4\x60\x98\x45\xc9\xbc\xe9\xf8\xae\xb5\x91\xd1\xa4\x69\xb0\x72\xb4\x12\x09\xf5\xa8\xb6\xdc\x23\x95\xad\x90\x60\xeb\x2e\x37\x09\x78\xae\x33\x11\xd1\xcf\x0a\x8f\x20\x51\x42\xd4\x36\xba\xb6\xb9\x59\x43\xa9\x7c\x23\xe6\x1b\xd1\x4b\x2d\x95\x67\x2c\xb9\x32\x5e\x9a\xb1\xfc\x9e\xee\xaa\xcc\xd5\x8b\x9f\x4a\xc1\x55\x0b\xde\xc8\x44\x9b\x03\x60\x39\x49\x6c\x5f\x07\xa5\xed\x64\xd5\xd8\x51\x71\x69\x01\x44\xdb\x5c\x81\xc8\x1c\xbc\x4c\x16\x71\x8d\x52\xc4\xdf\xd1\x95\x8c\xa5\xc9\xc8\xba\x58\x2c\xd9\xd7\x06\xf2\x7a\x74\x74\x4c\x3a\x05\xbf\x1c\xcd\x51\xf1\x09\x20\x10\xd3\x6f\x15\x78\xb5\x78\xae\x0e\x9f\xfa\x47\x07\x90\x55\xef\x94\xfa\xbc\x9f\xf7\x2f\x73\x8b\xef\x68\x46\x1e\xb3\x40\x4c\xce\xe9\x53\xf5\xee\x86\x4c\x97\x4c\xe7\x0e\x90\x37\xe3\x38\x8f\xba\xf2\x88\x9e\x13\x66\xca\xa0\xf6\x51\xe2\x1b\x33\x9e\x3d\x56\xb9\xd9\x5a\xc3\x0b\x35\x92\xa9\x48\x91\x2c\x90\xbf\x54\x47\x3c\xeb\xc4\x67\xb0\x9a\x39\x43\xdc\xac\x48\x68\xac\xb5\xb3\x5e\xa6\x91\xef\xf4\xd8\xcc\x1c\xda\x0c\x6c\x0a\x9c\x16\x9a\x4e\xe1\x00\x41\xf3\x5f\x43\x3f\xb5\x3d\x26\x06\x7b\x29\x10\x56\xb1\xda\x69\xff\x46\xfb\xea\x1c\xa7\x21\x36\x59\xa9\x90\xd5\xd5\xdf\x14\x06\xb0\x93\xda\x2a\x33\xc8\xdf\x95\xab\x3c\xe8\x11\xaf\xb9\xc9\x8c\x5b\xfd\x7c\x4e\x98\x1b\x3e\xa9\x4e\xef\xd2\xe2\xfe\x95\x70\x7d\x89\xf3\x07\xfa\x76\x82\x8b\x5c\x67\x74\x95\x0a\xee\x80\x62\x67\x14\x25\x6e\x19\x7d\xc7\xda\x97\x21\x58\xc7\x68\xbb\xee\x7f\xbd\x16\x9e\xc1\x5b\x4b\xb7\xbe\x72\x97\x6d\xbe\xd3\xe5\x12\x76\x6e\xf2\x2e\xf3\xb8\x12\xbc\xac\x4a\xa3\x11\x5a\xfe\x83\xd3\x12\x84\xaf\x8e\xac\xea\x4e\xe4\x9a\xfd\x42\xd9\xc4\x4f\xff\x2d\x86\x1c\x08\x62\x9b\x55\xda\xe0\x0f\xf6\x74\xfb\x02\x8e\x73\x8b\x05\xdc\xb3\x8a\xea\xa6\x96\x3c\xc3\xfa\xaf\xc7\xb6\x92\x45\xa2\xa1\x22\xa9\x6d\xd2\xf0\x3a\x82\x4d\x72\xb0\xfe\x0d\xd7\x98\xdf\x5c\x4b\xb7\x5a\x87\x32\x4e\x76\x4a\x50\xa5\xff\x52\x54\x7a\xda\x8f\x8f\x88\xe6\xf3\x8a\xee\x49\xd5\x8d\xdb\x01\x26\x48\x85\x4c\xd5\x9d\x0e\xc9\x7b\xc3\xd5\x8d\x0a\xd4\x49\x1f\x08\x59\x07\x67\xce\xb1"}, -{{0xbf,0xc9,0x62,0x6c,0x91,0xf3,0x48,0xfd,0xaf,0x46,0x9d,0xef,0x23,0x02,0xe9,0xe3,0x8f,0x90,0x51,0xe7,0x34,0x9e,0x48,0xf8,0x50,0xcf,0x35,0x2a,0x83,0x31,0xa2,0x8b,},{0x4e,0x81,0x93,0x06,0x1c,0x9d,0x65,0xa8,0x2b,0xcb,0x25,0xda,0x08,0x9b,0x4a,0x80,0xba,0x41,0xb3,0xdd,0x2f,0x8e,0xd1,0xdc,0x81,0xe1,0xcf,0xd0,0x3c,0x84,0x91,0x15,},{0x66,0x02,0x42,0xc1,0xdc,0xf3,0x29,0x13,0x69,0xc6,0x5c,0x9d,0x7f,0x89,0x87,0x2e,0xab,0x48,0x22,0x00,0xe3,0x44,0xb2,0x96,0xe3,0x36,0xa0,0xa2,0xe6,0x31,0xfa,0x79,0x60,0x24,0xb6,0xe1,0x11,0x9c,0x27,0xd5,0x22,0x64,0xa4,0x98,0x15,0xdd,0x78,0x19,0x27,0xa7,0xdf,0x46,0x7e,0x88,0xb8,0x01,0xe6,0x84,0xfc,0x60,0x22,0x96,0x25,0x0e,},"\x2f\x11\xf4\x0b\x2a\x19\xf6\x40\xc0\x04\x4c\x7b\x13\x96\x80\xc3\xc3\xb6\x9f\x00\xff\x9f\x6a\x41\x86\xfd\x7d\xed\x56\x9c\x1d\x8c\x57\x20\xf1\x9d\xd3\x5c\x78\x16\xd0\x8a\x94\xc0\x82\x04\xe4\x76\x43\xe2\x64\xd4\x25\xe2\x1c\xef\xb8\x31\x29\xc9\x09\xa3\xd7\x8c\xaf\x72\xc4\x6b\xf1\xa7\x29\x76\x5e\xf4\xb8\xca\x80\x3f\xda\xf8\x05\x2f\xfc\x6c\xc4\xa6\xb5\x79\xa1\x60\xb7\x03\xb1\x53\x55\xc6\xfc\xd3\xb9\xa2\xec\xbc\x26\x7e\x60\xdd\x59\xf6\xa2\xb1\x94\x20\xe5\x57\x27\xa8\x0b\x0b\xb6\x41\x67\xc8\x3b\xa0\xc8\x05\xde\xed\x49\x1d\x93\xe7\x23\xf3\xb4\x32\x63\xd1\x74\x20\xb8\x5b\xe8\x6c\x16\x5c\x55\x27\x79\xdb\x96\x0e\x0a\xa9\xeb\x4d\x9f\x3a\x16\x4a\x5a\x21\xfa\xb3\xf5\x09\xa8\xf0\x19\x9a\x69\x43\xc4\xb2\x23\xcf\x9d\xac\xa7\xe1\x10\xe0\x56\xa8\x1d\x9c\xe0\xe0\xc0\x2a\xc2\x65\xee\xac\x05\xec\xd8\x44\x48\x46\x8a\x4d\x12\x2b\x87\xa3\xe0\x4c\x28\x37\xe4\x3d\x21\x27\x04\xfd\x41\xe7\xf3\xd1\x98\xa2\xe7\x6b\xec\xa0\xe7\x02\x9c\x43\x2a\x06\x54\xec\xd4\x4f\x98\x4c\x5d\xf0\x67\x41\x96\x4d\x83\x72\xc8\x6e\x16\x2a\x8c\x54\x18\x84\x9b\x41\xe5\x71\xfe\xb8\x3e\xb4\x2f\xbb\xcd\xdb\x8a\x08\x21\x43\x90\x9e\xaa\x50\x12\xb9\x79\x93\x1d\xc7\xe3\xcc\xcb\x44\xc7\x91\xe0\x4b\x80\x65\xee\x63\xf0\x56\x1d\xa1\xbb\xf3\x7b\xf6\x50\x34\x77\x87\x9c\xfb\xaf\x6d\x9d\x7d\x9a\x74\x75\x55\x3f\x53\x53\x5f\x84\x7a\x76\xdc\x3b\x2b\x7a\x3d\x1d\x47\x0b\xbe\x17\x12\x4a\x88\xe0\x3f\xe9\x94\xba\x10\xc2\x42\x21\xe3\x9e\x3d\x0f\xf5\x3c\x79\xe2\xfa\xaf\xa1\x90\x12\xd5\xef\x19\x2b\xc6\xd5\x26\x0b\x66\xf9\x97\xb6\x44\xcf\x48\xd9\x9f\x38\x99\xd7\xc4\x85\xe6\x84\xaa\x1e\x6e\x30\x85\x5c\xf7\x5c\x2d\x80\xc7\xa3\xee\x43\x54\xfe\x13\xc6\x76\x09\x1c\x86\x67\x37\x3d\x30\xe6\x0f\xf8\xe0\x9f\xed\xef\x17\x5a\x1a\x87\x39\x5f\xef\xa0\x72\x2b\xf6\xc0\x1c\x65\x55\xcf\xf0\x68\x89\x2a\xfe\x94\x86\xcb\x1f\xcc\x5f\xb6\x64\x1e\x82\xd8\x70\x79\xba\x5d\x7a\x9c\x13\x93\x55\xd6\xc1\x4c\x50\x7d\xbd\x59\x47\x24\xb5\x53\x51\x10\x09\x65\xbe\x9e\x5d\xbf\xa7\x70\x88\x78\xc4\xb2\x9f\x4d\x54\xc2\x17\x74\x6e\x32\x6a\xb2\xa5\x4f\x99\xb8\x81\xd7\xda\x5b\x11\xed\xb0\x8a\x6d\x79\xd8\x85\x69\x1b\x1f\x70\x85\x51\x73\x10\xb3\x09\xcf\x9b\x1b\x71\x4a\xab\xc5\xc1\x7a\x50\x9b\x14\x0b\x89\xb3\xf9\xdc\xee\x50\xca\xb4\x41\xbf\x5a\xd3\xbb\xc2\x99\x90\xf6\x27\x40\x61\x70\xa7\xa1\x0f\x2d\x47\xdf\xc9\x25\x61\x54\xf9\x62\x30\x8e\x76\x9a\x2a\xb1\xb2\xa0\x0e\x27\xe3\x27\xf0\xd1\xfa\x16\x4d\x1e\x38\xea\xd5\xce\xaa\xe2\x38\xba\x52\x6f\x54\xb8\x1b\x45\xde\xa6\xc8\x97\x41\x86\xb1\xb6\x72\x5f\xa4\xc8\x3e\x62\xf3\xe2\x54\xf7\x29\x87\x1b\xda\x4d\xc4\x44\xbc\xe7\x8f\x09\x03\xfa\x31\x8e\xaa\xc8\x22\xa9\x55\x32\xab\x01\x9e\x9c\xfc\x56\x19\xe2\xc2\x06\x7f\x25\x8f\x43\x75\xd2\xe0\x22\x2e\xa5\xbf\x96\xa2\x53\xa2\xa3\xfa\x9e\xea\x02\xc3\xee\xcc\xb0\x28\xc7\x6b\xc6\x0d\x38\x29\x8b\x95\xb9\xaf\xe6\x60\x31\xb1\xa2\xa2\x61\x52\xfd\xaa\x7e\xf4\xf8\x37\xab\xb5\x11\x85\xdf\x8b\x2e\xf8\x5a\xd2\xc9\xbe\x6d\xfb\xa7\x5e\x37\xdc\x7d\x12\xe1\x78\x7f\xc5\x5f\x86\x6f\xd0\x66\xf1\x22\x91\xdf\xf1\x97\x6a\xfc\x10\xda\x91\x31\x01\xe7\x04\x95\xd8\x78\x33\x48\xd6\x11\xb0\x11\xec\x67\x1c\x0d\xa7\x37\xbf\x96\x2c\xdc\xc9\xe4\xa8\x00\xb5\x13\x93\x5a\x56\xd0\x84\xea\x64\xa7\xd4\xe8\xe9\x9e\xe9\x44\x0a\x73\x61\x32\xe4\x2c\x90\x95\x03\xc2\x22\x4a\x14\x1b\x25\xce"}, -{{0x39,0x3b,0x76,0x94,0x82,0x37,0x5b,0x82,0x14,0x27,0xa6,0x6d,0x16,0xe4,0xf5,0x51,0x85,0xb7,0xa3,0xb7,0x33,0x8f,0x1a,0x06,0xf6,0x7c,0xdf,0xa7,0xe3,0x5c,0x54,0x1c,},{0x84,0xaf,0xd7,0x06,0x78,0xff,0xa8,0x5a,0x9f,0x65,0x74,0xcb,0xcf,0xe3,0xb1,0x5d,0x04,0xa9,0xfd,0x15,0x01,0x6f,0xf8,0x55,0x0a,0x98,0x7c,0x4b,0x95,0x1c,0x71,0x22,},{0x31,0xf9,0x8c,0x0a,0x08,0xfd,0xa8,0xe7,0x35,0xb5,0x73,0x66,0xaa,0x1b,0x83,0xb9,0x3d,0xae,0x63,0xb5,0x81,0x0c,0x82,0x1d,0x99,0xcb,0x39,0xdf,0x52,0x1f,0xea,0xc0,0x7f,0x3c,0x41,0x0b,0x27,0xba,0x33,0x07,0x75,0x7d,0x60,0x49,0xf2,0x24,0x54,0xfb,0x6d,0xe9,0xe2,0xc3,0xc2,0x43,0x8d,0x68,0x31,0x90,0x97,0xd1,0x12,0xcf,0xdb,0x07,},"\x8a\xe8\x05\x3e\x03\xbe\xbe\xae\x54\x40\x43\xb8\x41\x4b\x38\x53\x64\xad\xd1\x67\x37\x37\xcf\x8a\xb2\x01\x93\xd4\xaa\xbc\x8a\x78\xe1\xd6\x9b\x9c\x7e\x52\x72\x9e\x69\x30\x78\x06\xe9\x27\xce\x38\x07\xb0\x7c\x68\xc8\x33\xc4\xfc\xf1\x6d\xb1\x5e\x7d\xce\x60\x4d\x17\x98\x91\x5f\xd4\x21\x16\x89\xb4\x86\x46\x42\x50\x2d\x38\xe9\x1b\x19\x97\xb7\x18\x23\x31\x8b\x69\xab\xe5\xbe\xd6\xf5\xe3\x01\x5b\xfb\x22\xdf\x30\xdb\x37\x1f\x22\x60\xc5\xc2\x2e\xba\x60\xdf\x39\xb3\xed\xd3\xc4\xd7\xa1\xe1\x11\xcd\x9b\x8a\xa4\x6f\x67\xbd\x0c\xf3\xa7\x17\xaf\x06\xec\x0c\xe5\x67\x02\x8e\x06\xe4\x79\x79\x34\xad\x69\xb1\xf5\xbe\x44\x0f\xf3\x7a\x8a\x03\x4b\x15\x33\xfa\x94\x64\x24\xac\x59\x54\x00\xad\x27\xd3\xbe\x76\xdc\x89\xba\x9d\x6c\x49\x93\x9a\x09\xf2\xe4\x01\xc8\xf2\x0f\x7f\x7b\x4b\x9e\x63\xb9\xd5\x52\x01\x53\x4a\xb4\xcc\x7b\xe8\x85\xf0\x43\x2a\x2c\x66\x73\xd2\xe7\x65\x19\x4d\xff\xd9\xb6\x09\x6d\xd2\xb2\x84\x39\x18\x75\x09\x59\xa8\xdd\xe4\xa3\xab\x40\x7e\xb2\xf7\xe1\xa4\x9c\x25\x97\xe3\x08\x05\xf8\x48\x0d\xd0\xcc\x82\x72\xa3\x20\xc0\x0a\xa2\xb2\x10\xf5\x76\xe4\x25\x77\xd3\xaa\x41\x97\x03\x69\x7c\xa4\x06\xd4\x3a\x1a\x4f\x99\xb0\x73\x36\x64\xf6\xd6\xb2\x40\x3c\xba\x1b\xdc\xc5\x1f\x54\x1c\xf2\x42\x36\x07\x05\x70\x54\x07\x55\xc7\xa8\x63\x1f\xcc\x2f\x18\x93\x8f\xa1\x1b\xc2\x91\x15\x5b\x39\xd7\xa7\x62\xa1\xff\x4d\xca\x97\xb4\x48\xf7\x0e\x2d\x3d\xe4\x47\xcb\x08\xf9\x18\xea\x20\xcb\x43\x3f\xa1\x15\xe3\x08\x80\xc9\x6c\x8c\xf5\xf0\xeb\xbc\xf4\x82\x30\x9d\xb6\xdc\x1f\xb6\x4e\x17\xc0\x4d\x7c\xdf\x7a\x90\xf4\x01\x4d\x15\xae\x76\x96\xb4\x44\x23\xb0\xba\x08\x4e\xed\x4d\x3f\xb2\x8c\x1e\xfb\x39\x82\x8a\xca\x2f\x40\xca\x6d\xf3\x42\xc2\x0e\x95\xf8\x00\x6b\x27\x67\xa8\x3f\x50\xc3\x1f\xcc\x15\x81\xa0\x97\x53\xe7\x82\x91\xf0\xd9\x93\x1d\x99\x2a\xd3\x60\x44\x73\xce\xb8\x85\xec\xbe\x78\x57\xcc\x52\xad\x55\x85\x33\x4d\x14\x85\xd0\x22\xe1\x06\xb7\x1c\x29\xbd\xfc\xf2\x3e\xe8\xa4\x75\xdf\x2c\x09\x05\x32\x35\x6a\x6f\xfc\x02\x23\x23\x17\x98\x8a\x2c\xbc\xfb\xc2\xa3\x6b\x4b\x48\x3c\xb4\x45\x10\xe8\x55\x99\xb6\x12\x59\x6b\x62\x65\x72\xb0\x99\x6d\x8a\x61\xc0\xee\x3e\xff\xf1\xf7\xc7\x1c\x05\xfb\x5a\x8d\x8c\x5d\x09\xd9\x24\xeb\xaa\xc8\x80\x04\x51\xc9\xdb\x24\x56\x71\x0a\x27\x9d\xfe\x2d\x22\xf6\xae\xa9\xde\x31\x80\x1d\xc7\x42\x53\x43\x62\xb0\xe8\x10\xe9\x9e\x84\x1d\xbb\x7f\x0c\xf9\xaf\x1a\xef\x54\x2a\x52\xc7\x76\xcc\x51\xf2\x87\x36\x8f\xbe\x6a\xd6\x51\xfa\xd5\x78\x7e\xf7\x7c\x73\x53\x5f\x3d\xfb\x36\x18\xcc\x8f\x0d\xbb\x54\x9d\xdc\xa9\xb9\xbf\x91\x13\x5a\x34\x56\x00\x1a\x46\x21\x5a\xde\x38\x8e\x7c\xeb\x9f\xcd\xfd\x0d\x2d\x0a\x03\x56\xaf\xbe\x2c\xec\x1c\x2e\x78\xb4\xd9\x98\xd4\x55\x4f\x46\x21\xf1\x15\x1d\xd3\xff\xd3\xba\x4c\x0b\xc8\x52\xf3\x11\x75\x8c\x5d\xca\x42\x5d\x18\xba\x15\xa8\xd6\x7c\xa4\x01\xd0\xe6\xcf\x28\x0c\xb8\x83\x84\xa2\xda\xd4\x9f\xae\x39\xba\x2a\x77\xb4\x67\xb3\x23\x8a\xa2\x8c\xfd\x13\x7e\x5c\x5c\x0f\xf9\x00\x0f\x8b\x06\xa2\x19\x2e\x16\x29\x20\x69\x22\x65\xdb\x24\xab\x6a\xed\xe5\x35\xe3\x1c\x20\x93\xbe\x57\xeb\xf8\x80\x5d\xf1\x78\x89\x14\xf3\xa8\x84\xf8\x84\x17\x90\x15\x80\x8d\xb4\xd3\x02\x0f\x3e\x78\xbc\x34\x28\x5d\x23\x37\x62\xe8\x99\xeb\xff\x28\x42\x82\x15\xe2\x44\x40\x4d\xe2\x91\x72\x8f\xbf\x41\x24\xce\x5b\x24\x35\x26\x0a\x8e\x34\x11\x80\x07\x5a\x56\x51\xe6"}, -{{0x26,0xcb,0xc2,0x51,0x0e,0xe6,0xea,0x39,0x0a,0x2c,0xb9,0x48,0xa0,0x15,0xd1,0x31,0xab,0xf4,0xc0,0x95,0x49,0x15,0x62,0x0b,0x78,0x16,0xae,0xcf,0x4e,0x11,0xda,0x6d,},{0x14,0x5e,0x8d,0xd2,0x2b,0x44,0x00,0x28,0x9d,0xaf,0xb6,0x26,0xd9,0x5a,0x94,0xc2,0xf3,0xb6,0x9c,0x65,0x19,0x77,0x17,0xcb,0xdc,0xd8,0x50,0x98,0xc5,0x49,0x21,0x07,},{0x67,0x10,0xd0,0xdd,0x00,0x54,0x5b,0x44,0x4c,0xf7,0x14,0xb7,0x91,0x44,0xfe,0x79,0xf3,0x8c,0xb1,0xc0,0xf5,0xb7,0x42,0x48,0xd4,0xf0,0x1f,0xe3,0x60,0x11,0x7a,0x26,0xff,0xed,0x4a,0x3b,0xf2,0x13,0x23,0xb2,0x8a,0x39,0x3a,0xe9,0xde,0xe0,0x7d,0x69,0xe5,0x83,0xe3,0x16,0xc6,0xa5,0x73,0xd3,0x7c,0x64,0x4a,0x8d,0x62,0xc4,0x05,0x06,},"\x9c\xeb\xe2\x4b\x4f\x8a\xde\x86\x43\x0e\x27\x9a\x3c\x43\x3e\x4a\xe1\x7e\x00\x88\x52\xa2\x4f\x08\x69\x0c\xbc\x3d\x75\xe3\xb7\xf2\x00\xda\x89\x7c\x25\xf7\x48\x3b\x37\x63\x7d\x4b\xc1\x10\x08\xd9\x22\x4c\xd5\x81\xfb\xc0\x38\xad\xad\xa0\x2d\x27\x1e\xd2\xa5\xd2\x85\xd8\x43\xa0\xf8\xb7\x9e\x37\x94\x5d\xc3\x5b\xc2\x64\xbe\xcd\x80\x43\x07\xe1\xd4\x42\x18\xa6\x43\xe4\xb5\x9a\x93\x11\xde\x98\x5d\x24\xb4\xc2\x6f\xb1\x46\x03\xbe\x5d\xba\x18\x39\xee\x0c\x8d\x2e\xde\x6c\xb5\x0a\xf6\x7c\x80\x45\x19\x03\x7b\x1b\x16\x63\x31\x8c\xfc\x6e\x75\xd0\xf0\x51\xdb\xb5\xd3\xea\xf3\xaa\xd1\xf7\x8e\xf0\xcf\xf4\x8d\x5c\x55\xb2\xfd\x25\xdb\x15\x39\xd0\xf0\x2d\xae\x9f\x25\x14\x8a\x8d\x33\x8b\x97\x87\x9b\xbd\x39\xdf\x96\x1a\xa2\xc3\x96\x31\x5a\x2a\x86\xcc\x78\x35\x81\xe6\x7e\xa8\x44\xac\xfe\x86\x45\x42\x8a\x27\xb8\xd3\x2e\xa3\x06\x4e\x3b\xf6\x2d\xcf\x58\x01\x0e\xc4\x34\x88\x62\xfa\xc2\x5e\x3d\x9f\xcd\x4e\x5d\x65\xbe\x59\x90\x5d\x81\x6d\xfb\x96\x49\x92\xba\x7a\xce\xef\x8c\x20\x75\xa3\x12\xe5\xff\xc4\xf9\x53\x0e\xa2\x0f\x77\xf9\x3e\x81\xcf\x8a\x01\x9d\xc3\x94\x56\x34\x36\x4b\xab\xf7\x97\x72\x04\x5a\x0d\xba\xa7\x7c\x47\xa2\x2b\x77\x22\x3b\x70\x4d\xeb\xd2\xd0\x03\xf6\xa5\xc7\xbf\x6b\x19\xcd\x2c\x49\xb6\x14\xfd\x4d\x47\xfd\x25\x1f\xe6\x22\xcb\x98\x17\x85\xc1\x46\xbd\xb7\xc1\xd2\xea\x02\xb1\x16\x92\x3b\xf9\x8a\x1a\xfb\xb7\x85\x8a\xdf\x2d\xf9\x38\xa7\x90\xec\x1f\x90\x74\xad\xb8\xd1\xaf\xb5\x63\x3f\xa9\x61\xa8\x47\x64\x01\x0d\x3b\xde\xd1\xc0\x33\xd2\x5a\xbd\xb4\xb0\x0f\xb0\x5e\xd7\x64\x0f\xae\x61\x87\x9d\xf8\x8f\x0b\x09\xe3\xab\xd0\x57\xb9\xa5\x21\x08\xa9\xbc\x98\x5f\xb7\x3a\x5f\x29\xd8\x4d\x1c\xa6\x92\x1b\x62\xf1\xb7\x03\xc7\xee\xb4\x81\x5d\x9d\xd6\xd0\x66\x73\x8d\xb1\x18\xba\xf6\x1b\x04\x22\xf3\x88\xf1\xbf\xc9\xe3\xa9\xbe\xd8\x3a\x1a\x72\x7d\xcc\x26\x6a\x99\x88\x36\x48\x46\x80\x7f\x4d\x55\x18\xbc\x2e\xdd\x0e\xcb\x34\x13\xc2\x6f\xd0\xc7\x9b\x75\xd8\xcb\x5b\xcd\x85\xc0\x6f\xcc\xea\x4d\x03\xfb\x89\x88\xdf\xf3\xed\x0c\xc9\xdb\xae\x78\xd6\xae\x8d\x5f\xc4\x02\x46\x17\xa2\x3f\x52\xbd\x61\x53\x85\xd4\xee\xe0\x8f\x91\x34\xeb\x3b\x25\x0c\x8f\x82\x2b\x47\xd9\x1e\x8c\x4d\x4c\x29\x29\x80\x16\xe6\xfc\x81\xf1\xf1\x09\x92\x53\xd7\x94\x5e\x07\x98\x95\x5d\xa0\xdd\xe1\x4e\xbb\x93\x4e\xcf\xae\xea\xba\xe8\x78\x83\xe1\xcc\x39\x80\x67\x40\x0f\xe4\x62\xa2\xc4\xe9\xf2\x32\xdb\x5c\xdd\x61\xeb\xa9\x49\x18\x8c\xf0\x1b\x23\x8b\xe7\xad\xa9\x38\xf0\x02\xdc\x3a\xe3\x1f\xdf\xd4\x25\xc8\xd4\x6e\xa0\x32\x32\x3a\xaf\x20\xdd\x3d\xe2\x50\x7d\x36\xbb\x45\xfb\xb9\x1c\x40\x96\x9a\x9e\x5d\xa2\x0f\x7f\x93\x6b\x0f\x4b\x13\x7b\x62\xfe\x2b\xa3\xa6\x67\xbc\x03\x62\xd9\x3f\xc5\x0d\x3f\x22\x95\xe1\x67\xfc\xba\xb0\xfb\x3a\x39\xb7\xcb\x02\x4b\x57\x8f\x94\x90\xf7\x34\xb2\x8c\x9c\xcf\x71\x92\xf1\x83\x94\x7d\x5a\x51\x3e\xfa\x49\x16\xe4\xd8\x2b\x2a\xb4\xba\x7e\xc2\xff\xba\x21\x3c\xe8\x2a\xd6\xed\x3b\x10\xe4\x85\x53\xe7\x33\xc9\x40\xaa\x9b\x9c\xe7\x13\x37\xc6\xc2\x80\x5d\xfb\x8d\xd6\x61\x8b\x6d\x40\x90\xa3\xd6\xcc\x96\x3e\xce\xa2\x6d\x1c\xdc\x2b\xf5\xac\x99\x9c\x11\x27\x61\x68\xa9\x31\xd8\x16\x46\x9d\x79\x08\x3c\x24\x08\x1a\x50\xdc\xbd\x22\x27\x52\x38\x52\x67\xce\x1b\xfc\x1d\xb7\x6b\x15\x54\xad\x57\xe3\x47\x52\xb7\xf8\x98\x31\x47\xc1\x16\xd4\xa3\xfa\xe6\xf6\xd5\x7e\x65\x4f\xed\xd7\x37\x8d\x2b\x49\x89\xea"}, -{{0xb1,0xf5,0x9e,0x3c,0x23,0x80,0xd7,0xaa,0x41,0x4d,0x0b,0xf9,0x08,0x93,0xa3,0x8d,0xdd,0xfc,0x29,0x38,0x59,0x30,0x3d,0x16,0xf0,0x0d,0x9e,0xae,0x6c,0xb3,0x45,0x0e,},{0x84,0xe3,0xf5,0xf7,0x2f,0x19,0x09,0x5b,0x0f,0x53,0x38,0x48,0xa5,0xa9,0x1d,0x0f,0x07,0x43,0xb8,0xe3,0xa3,0xe2,0xf5,0x2f,0xcb,0xd7,0xeb,0xe7,0xc5,0xb5,0xa9,0x98,},{0x60,0xaf,0xc1,0xe9,0x91,0xfd,0xd2,0x7c,0xc4,0x72,0xb9,0xac,0xc9,0xd4,0x05,0xb4,0xd2,0xb9,0x13,0x08,0x92,0x90,0xb3,0x11,0xc4,0xfa,0x89,0x1a,0xe2,0xee,0xa0,0x56,0x71,0xfd,0xe7,0xa0,0xef,0x86,0x55,0x7b,0xd8,0x67,0xd1,0xc0,0xb7,0x47,0xca,0xf3,0x52,0x29,0xd6,0xef,0x52,0x8f,0xe3,0xe0,0xd0,0xbc,0xf6,0x30,0x38,0x0e,0xa9,0x0e,},"\xc6\x17\x4c\x9a\xd3\x68\x5d\xd6\x48\x63\x60\x17\x83\x7b\x8d\x99\x22\x00\x31\x9e\x9a\x5a\x0d\x26\xd9\x4d\x2d\xa7\x5e\x2c\x3a\xff\x46\xf4\x2d\x7b\x3a\xba\x47\x2b\x7f\x86\x0b\x0f\xe1\xf6\x95\x52\x97\x31\xfd\xc8\xcf\x0d\xa7\x05\xd1\xd0\x9a\xca\xd0\x4f\x01\x08\x37\xec\xef\x41\x9d\x57\xe9\xea\x6c\xac\xf1\x68\xc5\x21\x56\x96\xf4\x71\xf3\xca\xa8\x97\x60\x7c\x62\x9d\x44\x3d\xe0\x99\xd3\x17\x53\xc2\x46\x77\xd8\xd7\x5f\x4b\xf1\x72\x46\x81\x8b\x58\xad\xc0\x42\x4b\x76\x2a\x19\x1e\xf3\x9a\x70\x76\xa5\xad\x12\x61\x4c\xf5\x4c\x47\xeb\x09\x08\xbb\x86\x65\x18\xc5\xfa\xc1\xca\x2d\x2e\x5b\x65\x75\x20\xa2\xb3\x69\x5c\x6f\xb3\x60\xf1\x6f\x4a\xb3\x57\x99\x8e\x4c\x0e\x97\x23\x1d\x6f\x89\xc9\x68\xdc\x29\xec\xc1\xaa\x91\xfa\x0d\x75\x43\xb5\xd2\x24\x7b\x0d\x85\xe4\x87\x43\xab\x7c\xc8\x15\xcf\xda\xa8\x2b\xf6\x8c\xa6\xd3\xe2\x25\x0b\xfd\xa2\x70\x24\xd6\x1b\x47\x4c\x6b\x81\x54\xac\x8d\x1b\x5a\x36\x20\x97\x82\x51\x5c\x16\x46\x68\x0d\x37\x06\x9b\x8b\x44\x12\xf9\x51\xb0\x25\xa4\xd5\x43\x62\x5d\xd0\x22\x90\xbf\x03\xc6\x73\x46\x13\xf9\x9b\x7a\x4c\x3a\xf5\xc5\xf9\xe9\xac\x34\x74\x46\x5e\x64\x84\x23\x01\x8d\x40\xa6\xad\xbe\x88\xa3\x30\x1d\x3d\x25\x9b\x04\xee\x44\xcc\x05\x62\xee\x0d\xed\x4f\x5e\x26\xad\x97\x7a\xb5\x63\x1f\x85\x76\x8d\xbc\xe5\x3f\x61\x6c\x02\x9a\x8b\x8f\x93\x3e\x2a\x92\x64\xb1\xc8\x1f\x51\x7e\x9f\xf5\x8a\xb9\xf4\x5a\x23\xee\xed\x42\x04\x35\x8f\x8f\xff\x0c\x8f\x97\x5e\xf1\xdf\xa5\x77\x6a\x5f\x77\x93\xba\xe2\xf2\x81\xd7\xb0\xcb\xef\x24\x0b\x3f\xc6\xbe\x05\x88\x21\xea\x2b\x80\x0f\xff\xe5\x5a\x7d\xe0\xaf\xc9\x3e\xde\x9c\x60\xc8\xde\x00\x5a\xbb\x9a\x2c\x88\xf4\xe6\x1e\x8d\xeb\x31\x70\xf1\x07\x8a\x36\xe2\xd8\xf2\xa5\x82\x39\xbd\xee\x49\x6e\x90\xd1\x37\xd2\x11\x0f\x0a\xd8\x57\xa8\x8b\x35\x27\x66\x4f\x78\x19\x39\xe0\xb2\xf7\x66\x34\xff\x9f\x6c\x57\xe1\xc4\x3f\x58\x24\x31\x71\xcd\x86\x2e\xf4\x28\x45\x76\x17\x2a\xf1\xf6\xc3\xbd\x37\xd5\xd7\x4b\x28\xa7\xa9\x86\x98\xbd\x74\xe5\x7b\xbc\x14\x2e\x67\xf7\x03\xf9\xd6\x2c\xde\x76\x1a\x02\x26\x8f\xec\xb3\x43\xfc\x01\x41\x88\x36\x41\x4f\x12\x22\xca\x24\xbc\xdd\x69\xd0\x05\x90\x1d\xa2\xa0\xf9\x44\x65\xe4\xd4\xba\x68\x89\x88\x16\xbf\x7e\x3e\x4b\xb7\x9c\x8c\xa5\x99\x7f\xba\x9a\x8d\xf8\x4f\xaa\x2d\x24\xb0\x44\xc4\xea\x61\x02\x9a\x46\xcb\xa7\x03\x42\x1e\x36\x1d\xfa\x52\xca\xaf\xf3\xbb\xaa\xb7\xfd\x75\x3f\x28\x56\xd7\xc0\x83\xae\xb9\x76\x8d\xa1\x1d\x82\x1e\x2d\x30\x9f\x7a\x73\x5c\x39\x96\x92\xda\xc2\xf2\x62\x84\x6b\x89\x1b\xf6\x46\x1a\xf2\x3c\x8c\x7c\xe1\xd4\xd9\x03\x2c\x3c\x14\x0f\x73\x9e\x55\x84\xc3\x6f\x05\xea\xf4\x34\x9f\xf4\x54\x5f\x28\x3a\x4e\x0f\xea\x49\x43\x0a\x1b\x18\x0d\x08\x71\xe3\x74\x2b\x88\xcc\xb5\x91\x12\x4f\xc4\x27\xed\x67\x3b\x5f\x27\xb0\xb0\xa6\xf5\x4a\xf2\x2b\xa4\xa6\xd1\xc6\xc1\xdb\x2a\x1f\xca\xa6\xd8\xa0\x30\x8b\x77\xef\x2d\x0c\x61\xbb\xf5\x1b\x95\xf1\xe8\xb6\xab\xc5\x04\x1d\x97\xb6\xb6\xf1\xb5\x69\xb3\xf6\x3c\xec\x05\xcb\x56\x7a\xae\xa1\x06\x72\x70\x96\xee\x8a\x9e\xa8\x7b\x88\x04\x90\x1f\x7e\x88\xa7\x40\x9c\x66\xf1\x52\xde\x9d\xbf\xcb\xe3\x19\x52\xe6\xfd\x83\xb2\x87\x7a\x77\x5f\xae\x42\x5b\x38\x51\xe0\xef\xf8\x79\x2f\xfb\x38\x48\xf8\x4a\x65\xcc\x31\x72\x53\xb2\x72\x47\x5e\x71\x7e\x49\xe9\xc6\xff\x6b\x78\x59\xd1\x1b\xba\x7c\x44\x28\xc8\x2d\x17\x89\xe0\xdc\xa5\xbc\xad\xca\x2f\xdb\x25\x9e\x98"}, -{{0xdb,0x46,0x1b,0x9f,0x70,0x7e,0xb2,0xcd,0x77,0x48,0xc4,0x4c,0x99,0x56,0x2f,0x13,0x02,0x39,0x74,0x89,0x35,0x3d,0xf5,0xf3,0x03,0x79,0x7f,0xe0,0xd0,0xb5,0x8d,0xe1,},{0x63,0x51,0x16,0xda,0x8b,0xa5,0xa3,0x6a,0x37,0x77,0x28,0xe2,0x86,0x18,0xe7,0x5c,0x55,0x92,0xae,0xcc,0x18,0xe3,0x40,0x11,0xc4,0xc4,0x25,0x91,0x97,0x0b,0x73,0x66,},{0xdd,0x04,0x9c,0xa7,0x9b,0xeb,0x9e,0xac,0x32,0x5a,0xcf,0x44,0x67,0x2f,0xf5,0x78,0xa9,0x68,0x50,0x2f,0xe1,0xbc,0xf5,0xea,0x19,0xd5,0x2c,0x0f,0x67,0x78,0xc7,0xf1,0xc7,0xbb,0xf7,0x42,0x74,0x79,0x07,0x78,0x6e,0x60,0x81,0x23,0x91,0x1a,0x92,0x07,0x78,0xd2,0xf9,0x59,0x6f,0xe2,0x9b,0xe7,0xcc,0x28,0xfd,0x00,0x9d,0x7c,0x44,0x0e,},"\x1a\x2a\xc8\xc1\xb9\xea\x09\x9b\x83\x1a\x68\x12\xd2\xb4\x26\x13\x09\x05\x8e\xa5\x88\x3d\x70\xb1\xc6\x07\xb9\xcd\x3f\xdf\xdb\x86\xe7\x99\x02\xb0\xfe\x89\xe8\x0e\xa7\xc4\x78\x20\x76\x74\xb2\xd8\x03\xb0\xb9\xca\x14\x7f\xfe\x62\xe5\x94\xf5\x06\xc7\x96\xd6\x89\x97\xce\x48\x2b\x51\xa4\x6e\x49\xb4\xa5\xd8\x58\xcd\xea\xe2\xc6\xec\x9b\x69\x41\x98\xe6\x82\x2f\x0e\x33\xed\x57\xbe\xdb\x03\x35\xc7\x89\x0a\x72\xa7\xee\x3c\x23\x82\x3b\xe7\x9b\x7f\x94\x71\xe0\x33\xc7\x9a\xee\xd5\x2e\x57\x60\xfb\x0c\xcb\xb9\xd3\x8f\xde\xd8\xb4\x73\x83\xc1\x91\x03\xce\x44\x70\x58\x34\xc5\x9d\xdd\x86\xf7\x03\x39\x48\x61\x2d\x66\x62\xf5\x16\xce\x4e\x39\x9f\xf2\x03\x63\xcc\x72\x81\xa6\x9b\x2d\x5c\x30\x7b\x10\xb7\x04\x15\x01\x84\xec\xe3\x2f\x39\x0d\x77\x2c\xcf\xa7\x84\x83\xbb\x77\xa9\xfb\xa8\x44\x25\x36\x69\x84\x17\x1c\xc2\xbb\x60\xb0\xec\x6c\x62\x8d\x4e\x90\x30\x74\x6d\xac\x1c\xab\xca\x60\xf0\x56\x83\x81\x33\x46\xa1\xa5\xbc\x14\x72\x75\x49\x79\x5c\x1c\x92\x68\x69\xe1\xaa\x25\x09\x3d\x59\x1b\x43\xe0\x86\xe4\x3a\x04\xd1\x70\xd9\x42\xc4\x16\x5e\x1c\x5c\xe7\x6c\x3e\x64\x97\x3d\x91\x36\xf9\x32\x5b\xee\x82\x16\x82\xf1\x04\x3e\x95\x1b\x02\x76\x7f\x3f\xb4\x58\xd0\x24\x49\xad\xd3\xe8\xa6\x6e\x51\x6f\xdb\x1e\xd5\x80\xe0\x56\xe0\xf7\x8e\xe3\x3f\xd9\xee\x32\x80\x91\x2f\xae\x07\xfe\x1e\xa0\x25\x27\xcd\x00\x1d\x6f\x6f\x2f\x89\xee\x64\x9f\x51\x74\x14\xd5\x6f\x57\x35\x9a\x84\x68\x91\xf0\x22\x2c\x32\x1d\x7e\x70\x81\x79\x95\xa8\xcd\x8e\x94\x76\x0b\x6e\x74\x83\x2b\xab\x68\xd5\x5b\xc4\x64\x18\x84\x22\x1f\xd2\x9f\x12\x2d\x87\xa9\xa8\x68\xb6\xa6\x06\x0c\x87\xb2\x38\x2c\xf7\xbb\xdd\xa4\xcd\x6a\xaa\x1b\xbc\x8e\x6d\x63\x4a\xb5\x80\xc8\x65\xf5\xad\xd6\xa1\xd5\x4e\x61\xa6\x07\xdc\x2c\x37\xb0\x8a\x8c\xba\x6e\x61\x0c\x12\xcf\xeb\xef\x9c\x98\x9e\xef\x3b\x78\x2a\xcb\xd1\xbc\xec\x5f\x04\xe8\x35\xca\x10\x12\x98\xb5\xe9\xbd\xd8\x81\x3a\x71\xb0\xd4\x69\xfc\xf1\x27\x27\xd3\xde\x1c\x3f\x97\xdd\xbc\x6a\xb2\x65\x84\x40\xdd\x64\x21\x01\x9b\xc6\x8f\x35\x6d\x6f\x25\x53\x68\x65\x85\x1d\x92\xd9\x0f\xe9\x96\x9c\x3b\x7c\x35\xa2\xe8\x8c\xe1\x53\x47\x6e\xc3\x97\x3a\xf9\x35\x9f\x16\x77\xa4\xca\xf1\xcc\x48\x1c\x71\xbd\x90\x22\x8f\xf5\xfc\x6d\xd8\x3b\x8a\x69\x9f\xfe\x51\x49\x29\xf5\xc9\x5c\xb4\xf0\x4b\x00\xdd\x18\xa2\x87\x2c\x41\x86\x8d\x3b\xeb\x76\x49\x8d\xdc\x92\x34\xb6\x3f\x59\x9d\x70\x71\x80\x1d\xb2\xc2\x87\x8f\x7b\xef\x4f\xfd\xdd\x81\x32\x26\xf0\x6d\xb8\x4e\xb3\x02\x17\xa7\x18\x30\x82\xe3\xc1\x24\x2b\xb6\xd0\x1c\xd3\xa6\xce\x27\xbf\xf1\x6b\xfb\xfd\xd7\x5b\x7e\x51\x04\x31\x2c\x49\xc4\x3a\xad\xfc\xd5\xb4\xed\xba\x0f\xf5\x0d\x28\x90\xca\x3c\xd9\xcc\xa3\x3e\x4f\xc6\x94\xc0\x57\xc4\x7e\xbe\x1c\x20\xa4\xad\x11\x5f\x98\x5d\xc7\x44\x2c\x6f\x6d\xa7\xbe\x53\x0b\x69\x02\x28\x9c\xab\x9c\xa1\x39\xc6\xb2\x4c\xb8\x0f\xfd\xd7\x82\x32\x4e\x60\x2c\x45\x91\x0d\xb6\x3d\x8b\x5c\x44\xca\x29\xd2\x7f\x56\xdb\xf0\x01\x86\xba\x58\x3c\x34\xe1\x60\x31\xdf\x35\x75\x46\xb3\xab\x9a\x3d\xd6\x5e\x91\xd7\x12\x8c\x93\x91\x95\xe6\x46\xa0\xf0\xb8\x9b\xf5\xdf\x04\xba\x23\x3d\x6a\x12\xa2\x71\xf7\xe0\x4a\xa4\x5c\xda\x99\xb4\xa5\x5a\x21\xcb\xbb\x73\x85\x15\xe3\x2c\x56\xaa\xc2\x49\x62\x32\xb1\x00\x8a\x67\x61\xc8\x04\x5a\x1f\xe0\xf9\xa3\x64\x40\x47\xb5\x96\x6a\x58\xa6\x00\x46\x6c\x1b\x1d\x11\xdd\xad\x5a\xa5\x73\xc4\x3e\xbd\xa8\x87\xe1\x6a\x05"}, -{{0xf5,0xc0,0xa7,0xf8,0xf6,0x58,0x4c,0x5d,0x2f,0x2e,0x1d,0x08,0x10,0xe8,0xe8,0x61,0x03,0xe4,0xe2,0xd4,0x5c,0xf9,0xa7,0x21,0xd8,0xc4,0x7f,0x67,0x49,0x33,0x96,0xa4,},{0x3c,0x6d,0x6c,0xce,0x49,0x63,0x31,0x41,0x07,0x86,0x96,0x13,0x1a,0x8d,0x84,0xed,0x82,0x3f,0x30,0x66,0x4b,0x28,0x9a,0xf9,0xdd,0x30,0xc6,0x40,0x7f,0x6f,0x03,0x13,},{0xd4,0xc3,0x0a,0x48,0xc4,0x52,0x3b,0x1f,0x84,0xb1,0x4b,0x65,0x7a,0xf8,0xf8,0x59,0x75,0x5b,0xba,0x63,0x59,0x98,0x8b,0x67,0x5c,0x6d,0x85,0xdd,0xf3,0x54,0x62,0x82,0x0d,0xa4,0x76,0xd8,0x4f,0x6c,0x40,0x2e,0x65,0xb0,0x20,0xd9,0xe8,0xa2,0xc2,0x85,0xc1,0x67,0x08,0xae,0x58,0xd1,0xf8,0xdb,0xc6,0x57,0x82,0xa8,0x98,0xa6,0x65,0x08,},"\xd6\x8a\xbc\x60\x9a\x7a\x0c\xe2\x56\x69\x9e\xb1\x70\x43\xde\xfe\x1e\xb8\x22\xc9\x70\x8f\x65\x71\x8a\x06\x58\x1f\xab\x21\x10\xec\x2d\xb0\x92\x13\xbb\x9e\x0f\x36\x12\xce\x4a\x3f\x8f\xdb\xe7\x57\xa9\xf0\xeb\x2c\x3e\xba\x43\x8a\x90\x88\xb1\x8f\x6c\x5c\xaa\xbb\xe5\xc8\x2f\x7a\x9a\xb2\xfe\xcf\x0f\x58\x59\xd1\x75\xe1\x39\x26\x30\x33\x74\x24\x58\xf8\x2a\x6f\x38\x75\x6c\xd5\xbc\xdf\x9e\x07\x36\xdb\x2c\xab\x20\xa0\xcd\x3f\x0f\x1c\xdb\xea\x85\x56\xd8\x49\x09\x35\x8d\xd8\xf6\x9f\x0d\xac\xd4\x9a\xbf\x8a\xc1\xbf\xe7\x59\x40\xd6\x93\x9e\x6a\x55\x38\x5b\x5a\xce\x7c\xe1\xfd\xe1\x20\x67\x9a\xb6\xea\x7a\x89\xd1\x42\x68\xd2\x9f\xfb\x46\xdf\x10\x5b\xf3\x90\x92\x42\xc6\x60\x5f\x3e\x3e\x2a\xb7\x44\x89\x37\xd6\xdb\x2b\xa0\x54\xc7\xb1\x4f\x43\x2d\xb4\x1d\xc1\x8a\x5b\x95\x73\x36\xb7\xf5\x2d\x97\x8e\xc0\x3e\x7d\x57\x64\xe9\xbd\x2f\x4b\x68\x95\x8d\x93\x7b\xf2\x98\x23\xb2\x7e\xfb\x31\xe2\x5b\x43\x92\x5c\x4d\xac\xbe\x67\x18\xa6\x0f\xea\x3b\x32\x70\xe7\xb7\x6b\x0d\xe0\xe7\x0f\x7f\xa3\xc1\x2c\x21\x5e\xf7\x2b\x95\xdc\x1b\x52\x76\x23\x81\x79\xdf\xc5\x2f\xc4\x88\x59\x64\x9f\xa5\x82\xd0\x5a\x60\xdf\x68\x59\x9a\x1c\xee\xa6\x4f\x64\x12\xd3\xf8\x49\x8a\xe2\xce\xdb\x12\x42\x45\x88\x3a\x24\x0b\xc0\x85\x1f\x0e\x32\x49\x65\xbe\x12\x04\x86\xe1\xea\x89\xa0\x18\x2d\xfa\x8e\xab\xd3\xb8\xfa\x66\xa9\x9c\x51\x49\x13\x89\xf3\xc8\x3a\x3c\xdb\x42\x67\xf3\xe4\xdb\xc9\x8f\x0c\x44\x85\x6b\x04\x4d\xc8\x8d\x90\xee\xee\x84\x15\xbf\x73\xde\x17\x1a\xfe\x84\xbe\x90\x35\xe0\xdc\x4c\x80\xcf\x04\x22\x46\x9f\xe0\xc9\xbd\x1c\x6a\xa6\x54\xa5\x9b\x5e\x34\xee\xd3\x51\xcd\xa2\x87\x12\x69\xac\x47\x8e\x8d\x38\x2e\x74\x0e\x9a\xc7\xab\x4d\xdc\x4c\x0d\xef\x0a\xea\xb7\x97\xb6\xf1\xa4\x27\xb8\xe4\xa8\x49\x7a\x0b\x97\x97\xda\xdc\xd3\x5c\x41\x4f\xd5\x5b\x78\x31\x30\xf6\xcd\xed\x38\xa4\x4c\x1a\x89\x28\x83\x07\xeb\x84\x25\x48\x41\x37\xa8\xae\xdb\x03\x0d\x54\xb6\x16\xa8\x2e\x3c\x5a\xcf\xfb\x08\xd6\xcc\x1a\x61\x74\x5c\x29\xaf\xc6\x8a\x0c\x18\x38\xb1\x39\x15\x9c\x5f\xa6\x67\x4d\x66\xb9\xe3\x38\x11\x5a\xad\x4b\x1b\x47\x10\xaa\x5d\x95\x17\xbc\xf7\xe1\xcb\x12\xd4\xe6\xa5\x1c\x11\x78\x9f\xdc\xae\x9d\x9b\xbe\x78\xf6\x9a\x33\xe5\x2d\xf1\x83\x3c\x87\x6b\x02\x68\x7a\x40\x4f\xac\xad\x32\x84\x1c\xb2\xd5\x25\x54\xe7\xb8\xe2\x20\x9e\x3f\x88\xfd\x94\x8c\x1e\xcf\x83\x95\x7c\x96\xf4\x3b\x03\x4b\xed\xa6\xc4\x76\x09\x6b\xcb\x09\x30\x1a\xd6\x1f\x83\x67\xcc\x43\xe1\x56\x13\x18\x62\xb4\x2e\xce\x28\x5b\xec\x2d\xcc\x2d\x02\xd0\x94\xd0\x42\xa1\x60\x72\xeb\x22\xab\x98\x88\x01\x3b\xe8\x23\x71\x56\x94\x00\xec\x1f\x8e\xc7\xe7\x91\x08\xc4\x1b\x85\x33\x65\x26\x8f\xa4\xcf\xbc\x62\xc4\xac\x12\xcc\x98\xd2\xec\x38\xa8\x7d\x60\x85\x85\x95\x67\xc0\xf2\x7d\x6d\x43\x1a\x04\x6e\x88\xa9\x81\x55\x58\x66\x07\x05\xfd\x05\xeb\x06\xc6\xc0\x5e\x5b\x7d\x62\x34\x7c\xee\xe2\x7d\xff\xed\x71\x41\x54\x0d\x60\x8c\xb9\x75\x07\x5a\x96\x44\xac\xc6\x32\x84\x39\xf9\xfa\x68\x2b\x22\x6b\x18\x61\x54\x54\x90\x11\xc3\xb0\xf0\xff\x4f\x74\xca\xa7\x1c\x19\x44\xe4\xcb\x83\x6c\xe8\x51\xd9\xb5\xd9\xe7\x27\xc5\x53\xe3\xc7\x23\xcf\x98\xc2\x73\xe5\x67\x5c\xab\x89\x9b\xb6\x6f\x46\x33\xa7\x6d\xea\x35\x73\x41\xf9\x83\xc5\x3d\x91\x58\xad\x31\x9a\xda\x75\x40\x8b\x41\xc0\x6f\x26\xb7\x43\x5b\x80\xdc\x3b\xc0\xaa\xf2\x2a\x83\x3d\xde\xdc\xd6\x78\x5c\x87\xd1\x96\xb0\xaf\x2c\x9a\x43\xd1"}, -{{0x1a,0xb9,0x46,0xc0,0xc1,0xae,0xbf,0x9c,0xa3,0x7c,0x2f,0x4e,0x2a,0x4b,0x33,0x7d,0x5b,0x1e,0xbc,0xcd,0x24,0x73,0x4c,0x9c,0xb2,0xa1,0x60,0x8c,0x88,0x1e,0x57,0x57,},{0x9a,0xfc,0x63,0xdf,0xce,0x0d,0x48,0x9b,0x40,0x90,0x7a,0xee,0xd6,0xdf,0xfe,0x4c,0xd8,0xef,0x5a,0x6f,0xfa,0x22,0x98,0x95,0x56,0x44,0x5c,0xbf,0x9b,0x35,0x19,0xc2,},{0xbf,0xab,0xde,0xa4,0x18,0x10,0xa5,0x3f,0x8e,0x52,0x7a,0xcd,0x66,0xec,0x10,0x6c,0xe2,0xae,0x1a,0x67,0xff,0x6a,0x9b,0x52,0x2e,0x0f,0x08,0xfb,0xbf,0x12,0x52,0x68,0x2c,0xb3,0xa1,0xdc,0xc8,0x75,0x60,0x19,0x44,0xcb,0x88,0x00,0x0f,0x72,0xe1,0x39,0x07,0x00,0x79,0x03,0xa7,0x7c,0xd0,0xdb,0x03,0x16,0xd4,0x19,0xac,0x38,0xc2,0x04,},"\x9b\xb0\x71\xb6\x2c\x04\x06\x4b\x0c\x96\xe2\x43\xdd\x19\x8c\x39\x71\x7b\x25\xc9\x94\x48\xc2\xc0\x02\xb8\x4a\x99\x20\x4c\x5a\x6e\x23\xb4\xb9\x12\x02\x86\x75\xbf\xdc\x4d\xf9\x3c\x5b\x2f\xb8\x08\x81\xa2\x3e\x0d\x44\xba\x18\xbd\xe9\x91\x21\xee\xe8\x6a\xdc\x6f\x84\x28\x19\xd6\xeb\xc7\xa2\x88\x99\x2d\xa3\x28\x58\x05\xa8\xb8\xb6\xfb\xcd\x22\x67\xb6\x86\xb3\xe1\xbf\x79\x60\xb4\x5f\x24\x4f\x85\x2e\x82\x49\x29\x44\xe3\xd6\x18\xbc\xc4\x51\x4c\x17\xf7\x22\xba\x49\xac\xa7\xf2\xf3\xbb\x4e\x91\xf9\x40\xe9\xce\xf0\x15\x65\x0c\x3e\x40\xb0\xc8\x55\xa1\x7c\x42\xf1\x1e\x3a\x34\xac\xc8\x52\x87\xdb\xe0\xf9\x09\x3c\x00\x37\x3d\x50\xc0\xb3\x06\x4a\x5a\x5f\x2b\x1e\x89\x20\x65\x17\x52\x82\x95\xfd\x87\x17\x03\xa8\xe7\x62\xb5\xe7\x6f\xb9\xb7\x47\x3d\x21\x49\xb8\x5b\x94\x61\xf5\x58\x7e\xd7\xe7\xfc\x8b\x50\xaa\x09\x87\x6d\xee\xb6\xe2\x37\x07\x85\x02\x14\x2c\xec\x6b\xdd\xc7\x01\x40\xfe\x1d\x1f\x16\x58\xd5\xd3\xe9\x10\xfd\x70\x36\xa2\xf9\x24\xb4\x99\xdb\x17\x56\xf7\xc8\xce\x0d\x5f\x0d\x04\x5b\x39\xbc\x81\xc5\xc2\xf1\xa7\x61\xf5\x2f\xf3\x93\xe0\x64\x9b\x8d\xb0\xbd\x88\x54\xbd\x02\x6b\xe2\xc7\xc3\xcd\x63\x52\x6b\xa5\xa8\x0d\x48\x33\x5f\x03\x38\x32\xd6\x33\x76\x07\x1b\x63\x08\xf0\x59\x60\xcb\x3f\xc9\xfa\xc9\x32\xed\xd8\x37\x6d\xae\x51\xf2\xc6\x61\xf7\x5b\x7c\x6f\x4a\xc8\x56\x75\x3a\xca\x62\x06\x28\x77\x60\x9f\xc4\xa0\xff\x60\x67\x02\x82\xc0\x5e\x88\x2d\x1a\x03\x5b\xf9\x89\x0c\xab\x29\x6a\xc7\xa8\xdf\x24\x4c\x56\xf4\x90\x25\x0f\x02\x00\x54\xb8\xaf\x51\xbe\x4f\xc3\x18\xbe\xba\x50\x62\x32\xbf\x45\xe1\x7f\x5c\x74\x0c\xf0\x9d\x37\x51\x5a\x8b\xc8\x94\xbc\x95\x5c\x8a\x46\x08\x77\xc7\x85\x4f\x8b\xe3\x63\xb2\x19\x33\xe1\x62\x87\xae\x0c\xb7\x0f\x22\x2d\x4e\x36\xb8\xb4\x24\x97\x55\x59\xbb\x4b\xfc\x8d\xd1\xd5\x1b\x3c\x0f\xaf\x4a\x53\xe3\x02\x19\x6f\x9f\xed\xb5\x32\x87\xd0\x93\x15\xdf\xff\xa2\xbc\x4b\x3a\xcf\xf1\x37\xf9\xa7\x6d\x68\x56\x21\x7f\x79\xcb\xb2\x54\x33\xfc\x97\x89\x9f\xd6\x54\x0f\x18\x08\x8e\x84\x41\x7e\x48\x33\xe4\xa9\x1a\xab\xa4\x65\x8a\xe9\xad\x7f\x76\x0d\xd9\xc5\xb7\x19\x1a\x0d\x3c\x05\x54\x1b\x83\xc0\x25\xa7\x99\x21\x38\xe6\xd1\x08\x0d\xa1\x4c\x2c\x88\x7c\x6d\x67\x0a\xab\x37\x4d\x43\x6c\x27\x2f\x9e\x96\xf8\x5a\x9c\x42\x33\x79\xc0\xd4\x7c\x46\xdf\x6d\xe3\x34\xea\x20\x57\x15\x8d\x33\x23\x1e\x14\x26\xa6\x6d\x3c\x70\x82\x7a\xad\x55\x11\xb8\x46\xe0\x3b\x94\x92\x3d\x5f\x94\xba\xf1\xf8\xcf\x11\xa8\x61\x37\x3a\x5b\x80\xad\x5e\x31\x7e\xc2\xa5\x29\xe9\x4e\x63\x6c\xdc\x3a\xa2\x9e\x5d\xac\x20\x5a\x0c\x13\xf6\x8f\xb1\x98\xcf\x94\x56\xe6\x39\x0a\xea\xd4\xd9\x78\x2a\x10\x38\xf6\x47\x8d\x33\x9a\x81\xba\xe7\xaf\x2a\x04\x15\x1c\x2f\x22\xe8\xd3\x9f\xe0\x71\xe1\xa5\x21\x68\xd5\x7c\x84\xc3\x62\x93\x41\x3f\x8e\x6f\xf6\x93\x4f\x05\xe7\xef\xad\x6f\xa1\x20\xc8\xc1\xc3\x8a\xd1\x88\x6a\x3d\x00\xbf\xc3\x06\x45\x92\x03\xc0\x2c\xdf\x4f\x06\x65\x2b\xc8\xfa\x0e\x8b\x9c\xc7\x79\xd4\x3f\xbb\x78\x9e\x7d\xad\x5d\xc9\x9f\x41\xd4\xcc\x58\x8c\x1b\x65\x42\x6a\x4e\x77\x38\x9e\xdd\x04\x97\x75\x78\xf8\xf3\x16\xbc\xdd\x94\x61\xd6\x66\x47\x2c\xdd\x27\x6a\xa5\x69\x72\x1c\x65\x23\x22\x56\xba\x1c\xf0\xe7\xf5\xea\x55\x32\x17\x29\xbb\x0e\x03\x86\xa7\x7b\x86\x55\x32\x02\x46\x96\xed\xde\xf4\x85\xb7\xd7\xb2\x8c\x15\x73\xb9\x34\x7e\x41\x4d\x42\x61\x99\x54\x82\xe3\xb3\x12\xde\x13\x31\xf8\x4e\x75\x48\x60\x7a\x84"}, -{{0x04,0xbb,0x88,0x7a,0x8a,0x31,0x84,0xff,0xc7,0xea,0x09,0xc9,0xbc,0x7c,0x1f,0x7c,0x34,0x11,0x55,0x6a,0x7c,0x7c,0x39,0x8c,0xb8,0xb2,0xd9,0x8f,0xfd,0x9e,0xe8,0x66,},{0x6a,0xb1,0xe4,0xae,0x4a,0xa0,0xd3,0x89,0x89,0xae,0xef,0xa8,0x05,0xb5,0x78,0x80,0x6e,0x2e,0x97,0x1a,0xc7,0xac,0x05,0x40,0x99,0x58,0xbf,0xe6,0x00,0x71,0xf4,0xa7,},{0xcd,0x84,0xf5,0x5e,0x5e,0xf4,0x53,0x19,0x24,0xc5,0xa2,0x18,0x1e,0xc8,0x7a,0x64,0x54,0x13,0x88,0xc1,0x05,0x94,0x06,0xbc,0x07,0xd5,0x31,0x57,0xa1,0x68,0xe2,0x03,0xcc,0x8a,0xa0,0xf0,0x06,0x9d,0x53,0xff,0x58,0xa9,0x5b,0x8a,0x8c,0xaa,0xfd,0xad,0x26,0x36,0x3c,0x7d,0x0f,0x80,0x45,0xc4,0x35,0x9e,0x97,0xb4,0x36,0x02,0xc6,0x06,},"\xb7\xab\x0c\x81\x63\xf4\x78\xc6\xca\xbf\x2b\xbd\x7c\xa3\x7c\xb0\x24\x56\xd7\x6e\x52\x7e\xea\x1b\x0d\x26\xdb\x24\x2e\x37\x87\x76\x32\x98\x5a\x3e\x3c\xa4\x1b\x52\xe2\x1d\x79\x01\x7b\xff\x81\xee\x55\x1a\xd7\x2a\xf2\x77\xb4\x10\xe4\x2a\xf8\x22\xc6\x08\xcd\x69\xd0\x0b\xf4\x40\xb7\x5b\x78\x7a\x8c\x91\x5d\x70\xb6\xc6\x37\x6c\x3f\x67\xfa\x64\xd6\x12\xa1\xb4\x49\xa7\xe2\x13\x4d\x9c\x23\x23\x01\x57\xd5\x76\xe0\x6a\x66\xa8\x42\x2a\x61\x1e\x2a\x0f\x09\x72\x86\xc1\x99\xea\x2a\x16\x28\x61\x86\x4b\xd0\x35\x07\x6a\xb2\x0b\xba\xe2\xb4\x40\x8a\x2c\x64\x33\xcb\x23\x43\x3a\x88\x9f\xe6\x59\x8f\x47\xbe\x53\xbb\xd2\xc8\x0f\x07\xa8\xfc\xcb\x8a\xae\x51\x11\x61\xe6\x09\xda\x4d\x18\x0a\xce\xa5\x44\x81\x1e\x94\x49\xc5\xdc\x22\x50\xe3\xe5\xa0\xcd\x41\xda\x33\xa2\xda\x63\x2e\x60\x38\xbd\x86\xf1\x6d\x5b\x7c\x1b\xe4\x9f\xc6\xdb\x49\x90\x76\xca\x91\xf7\xaa\x02\x8f\xe3\x85\x29\x70\x0b\x21\xd0\x72\xd2\xb7\x5d\xcc\x8b\x43\x78\x1d\x4b\xc4\xd3\xbb\x58\x4d\x9d\xa0\x1c\x3e\xcc\x85\xb1\xe9\x3f\xce\x04\x5d\xad\xce\xea\x51\x06\x46\x8b\xdf\xe5\xf7\x0d\x66\xa4\xfa\xd6\x0e\x4f\xb8\x64\xec\x15\xea\x50\xf6\xcb\x79\x72\x23\xc8\xc7\x56\xf7\xa1\x93\x1a\x39\x46\x4e\xbb\xb9\x67\x9f\x6b\x01\x68\x7c\x17\x4e\xaa\x32\xb9\x68\xb9\xcf\xac\xe8\xc1\x67\x12\x0a\xa7\xbd\x02\x42\xf0\x03\xa0\xc3\x77\x70\x25\x51\xb3\x0d\xa2\x48\x8e\xb2\x94\x40\x52\x93\x4a\xef\x4b\xfe\x11\x5f\x0a\xb7\x40\x5a\x3d\x5f\xa9\xbd\x79\x6b\x37\x17\x42\xbc\x11\x4a\x9b\xf2\x8c\x5b\xd2\x56\x26\x29\x5c\xe2\x61\xa6\xa8\x3e\xf6\x0b\x77\xd2\xd3\x2d\xd7\x10\x5f\xc8\x36\x64\xaa\x89\x76\x5b\x3f\x81\x91\xee\xee\xd8\x78\xf2\xeb\xff\x2f\xb9\x76\x63\xa6\x18\x77\xc0\x93\x93\x3b\xbd\x07\x31\xe6\x37\x57\x57\x1b\x0e\x37\xca\xc9\x9e\xd0\x1f\xd2\x14\xcb\xd4\xfe\xb9\x77\xe8\x56\xe0\xa1\xa7\xef\x0c\x40\x8c\x20\xe0\xdd\xaf\x1f\xd8\xf0\x28\xcf\xa0\x8c\x85\x0f\xa7\x09\x0d\xca\x8c\xdd\xe0\xcb\x69\x03\xda\x18\xc6\x29\x0c\x66\xa1\xc0\xae\x0a\x08\x4b\xf2\x50\xc5\x1a\x9d\x03\x5e\x5b\x16\xec\x61\x66\x36\xaf\xb9\xb5\xbc\xe3\x6a\x77\x5f\xe2\x17\x5b\xcc\x2e\xe0\x72\x20\x83\x4e\xeb\x31\xca\xee\x50\xe9\xf8\x06\x3f\xb1\xfc\x84\x68\xae\x25\xe3\x96\x67\x89\xa6\xd8\xdf\xfe\x08\xa6\xf7\xa1\xe6\x72\x6f\x93\xae\x74\x82\xde\x02\x62\xbb\x1f\x8d\xe0\xc9\x5a\x99\xec\xb9\x56\x84\xd4\x4b\x3f\x1a\x33\x2a\x18\xd2\xcd\x3d\xcf\x25\x3c\x33\xd7\x35\x52\x2f\x79\x6b\x65\x1c\x9a\x63\x3a\x8e\xbe\x95\xd0\x2b\xc0\x46\x58\x25\xee\x54\x1a\x7d\x92\x7b\xb5\xb9\x0a\x6d\xb5\x49\x9f\x8d\x99\x3a\xb4\x04\xb1\x65\x0b\x75\xe7\x92\xa7\xc8\x34\xeb\x41\xf0\x47\x01\x38\xb0\xf5\x78\xa0\x4c\x9b\xa5\xad\x95\x0a\xc7\xc9\xb5\xd3\x28\xf3\x40\x8b\x64\x5a\xd9\xc6\xbf\x19\x6d\xd9\x61\x44\x55\x96\xbc\x78\xf2\x84\xb8\x91\x4b\x2a\x8c\xf9\xb7\xbd\x3a\x71\x6d\x8f\x14\x4b\xb6\xb1\x5d\x83\x10\x23\x71\x3b\x5e\x41\xfd\xa9\xb5\x87\xff\x9d\x6c\xc4\x3c\x08\xd3\x5a\x70\x7f\x49\x52\x83\xe1\xac\xe9\x60\x48\x7e\x7f\x02\xb7\x54\x3b\x68\xa7\x31\xa2\x9b\xf3\xbe\x14\xb6\xe9\xc3\x71\x74\xa9\xf4\x6f\x56\x11\x99\xdb\xd2\x7b\x46\xbf\xe6\x22\x43\xe0\xc1\x1c\x0e\xdf\x13\xb6\x4f\x41\x1c\x8e\x8e\xce\xd3\x5d\x84\x28\xf7\x9f\x10\xea\xcf\xfb\x72\x34\xe5\x46\x41\x3d\x1e\xb0\xfa\xd8\x8c\x0e\x93\x85\x93\xb4\x3b\x5e\xe0\xe4\x28\x5d\x4d\xdd\xf5\x29\x5d\xbf\x1a\x3d\xdb\xe9\xf4\x13\x4d\xd7\x6d\x3d\xe7\x04\x62\xc2\xf0\x4f\xe0\xae\xbd\xf5\x9a"}, -{{0x97,0x76,0xa4,0x67,0xfa,0x14,0x00,0x73,0x54,0x12,0xa7,0x9b,0x49,0x5f,0x9f,0xca,0x07,0x8c,0xe1,0xd8,0x7a,0x85,0x30,0xd8,0x5c,0x26,0x05,0x5d,0x3a,0x39,0x44,0x88,},{0xc7,0xdb,0xe0,0xe4,0x1c,0x0a,0x31,0xc0,0x94,0x27,0x93,0xff,0xd1,0x42,0xd8,0xb9,0x5c,0xc8,0x2e,0x5c,0xaa,0x92,0xa3,0x79,0xba,0x23,0xf6,0x44,0xed,0xf2,0x24,0xda,},{0xe1,0x31,0x7b,0xa2,0xa1,0x23,0xae,0x3b,0x29,0xe7,0xb6,0x0e,0x8e,0x93,0xbe,0xed,0xd7,0xa0,0x84,0x51,0xa0,0x13,0x69,0x5b,0x6d,0xcf,0x35,0x8e,0x40,0x34,0x02,0x6d,0xc7,0x40,0x37,0xaf,0xbd,0xd2,0x17,0xff,0x4b,0x14,0x8b,0x02,0x91,0x38,0xf4,0xbc,0xc8,0xf9,0x83,0x6a,0xbb,0xae,0x7e,0x62,0x76,0xe9,0xe7,0x69,0xdb,0xd8,0xf0,0x07,},"\xd7\x85\x53\xa1\xb7\x05\x5b\x58\xb2\x13\x10\x1b\x1c\x84\xc5\x3e\x16\x4e\x39\xc6\xe9\xd3\x6d\xb4\x3f\x30\xe1\x9e\x2a\x12\x5a\x9a\x67\x70\x9e\xaf\xef\x96\x4f\xa5\xba\xb7\x26\x1d\xdb\x3a\x8a\x01\x88\x45\x7d\xfb\xf5\x15\x9c\x40\xe5\x1d\xa8\x20\x84\x83\x24\x57\x81\xd7\x13\x1e\x23\xa8\xbe\xe5\xe5\x06\x33\x18\x16\xb9\xde\xee\xfe\x6e\x55\x6e\x3f\x0c\x95\xc6\x68\xd1\xbe\xdb\x7d\xa6\x35\x06\x54\x58\xad\x20\x46\x70\x12\xf5\x9f\x17\x13\x52\x06\x80\x20\xce\x3c\x75\x87\x86\x93\xf6\x43\x7b\xc4\xa0\x9f\x13\xb9\xb0\xf0\xcd\xda\xf1\x69\x1b\x87\x2f\x82\x00\x80\x93\xeb\xfb\xe2\x33\xd0\x31\x3e\x72\xc8\x63\x2d\x7d\x17\x93\xf0\xb8\x1c\x76\x88\xf5\x44\x70\x33\x0f\x04\xe6\x48\x60\xe6\x44\x6b\xfc\x6d\x96\xc8\x75\x69\xbf\x18\x2f\x0f\x43\x85\xaf\x48\x5d\x42\x99\xca\xc0\x4e\x06\xba\x47\x34\x65\x56\x6c\x47\x7f\x07\xb9\xdb\x27\x7a\xb4\xa9\xde\x2f\xb2\xde\xd0\xa5\x01\x1c\xd0\x6d\x67\x5c\x08\x00\xb3\x4f\x55\xbc\xf3\xec\x72\xd2\x1c\xa1\x50\xc8\xbf\x23\x61\x28\x7b\xe8\x1e\xfa\xbb\x96\xd8\x68\x8a\x1d\xee\x3f\x43\x0f\x06\xf6\x37\xdf\xd0\x6f\x15\x14\x64\xa0\x5c\x95\xf5\xfe\x76\xaf\x2e\x06\xd0\x12\x3f\x69\x48\xa2\x6b\x3b\xe8\x35\x04\x5a\xa2\x68\xcc\x1b\xe9\x76\x69\x71\x07\x77\x02\x08\xa7\x56\x8f\x02\x5c\x2d\x53\xc7\x19\xe5\x24\xcc\x36\x9d\x9b\x4a\x33\x7d\x8f\xd1\xef\x34\x5b\x9b\xca\x57\xfb\xd7\xb6\x5a\x6b\x99\x7c\xad\x3f\xce\x4c\xf0\x6f\x2c\xa4\x3e\xbe\x29\x86\xd0\x96\x82\xd4\x7c\x92\x2b\x2c\xb7\x56\x9d\x98\xde\x97\xa6\x16\x4f\x54\x70\xee\xc7\x1c\xed\xa5\x20\xcc\xec\x77\x32\xbd\x01\x68\x9e\xf8\x16\x56\xe9\xf6\xd0\xc5\x8a\x89\x55\x58\xae\xe8\x63\xf5\x46\x9e\x7a\xb9\x79\x15\xbf\xe0\xb8\x0a\x06\x4c\x65\x9b\x18\x30\x31\xf7\xf1\xa8\x6f\xb1\x1a\x9d\x52\x8c\x28\x15\xdc\xaa\x2f\x0d\xec\x3d\x21\xa8\x82\xe1\x06\xe2\x04\x93\xee\x0a\xcb\x77\x08\xea\xa2\x91\x25\x74\xae\x97\xbb\x28\x8b\x41\xfc\x09\x25\x05\x3a\x29\xb0\xbf\xbc\x0e\xba\xe8\xd6\x3c\xc0\xb4\x6e\x37\x38\x04\x6c\x5a\x20\x25\x30\xbc\xb1\x5b\x18\x7a\x72\x85\x4a\xa2\xd8\xa7\xa7\x6c\x89\xa8\x9a\x5d\xb4\x60\x32\x07\x4e\x1b\xd7\xde\x77\xef\x20\x65\xa0\x8f\x38\x9d\x78\x3c\xf7\x59\xeb\xd5\xa6\x3a\x44\xd9\x19\xf9\x48\xf5\x60\xc3\xe9\x4c\x42\x39\xe2\x74\xe0\x51\xa2\x04\x85\xa4\x30\xcb\xd5\x29\xf3\x13\xd9\xf7\xed\x67\x9a\x34\x18\x7b\x24\xf8\x41\x30\x87\xa9\x02\x1e\x47\x31\x73\x0f\x5f\x46\x1f\xc5\xaa\xd6\x65\x4d\xfa\x1c\x05\x04\xd2\x61\x24\x70\x7e\x63\xee\x57\xf9\x31\xb2\x78\x59\x08\xf8\x6b\x10\x4b\x3e\xcb\x96\x00\x02\x51\xd0\x6c\xe1\xfa\x45\xe4\xcd\x6d\xf9\x1a\xc1\x5b\xbf\x7c\xa3\xc3\xeb\x8e\xe0\x82\x76\x12\xa2\x9e\xcb\x7a\x36\xd5\x47\x0c\x40\x50\x51\x82\xfa\x9a\xc9\x13\x57\x0d\x0c\x10\x50\xd9\xa4\x34\x55\xcb\x7b\xdc\x17\xd1\x69\x80\x5f\x01\x89\x56\xf8\x54\xf8\x91\x9b\xbf\xb7\x19\xe1\x86\x7b\x36\xa6\x4a\xab\xcd\xb8\x07\xf4\x8d\xcc\xc0\x67\x2f\x67\x88\x74\x50\xb3\xf3\xe9\x58\xd7\x84\x99\xe0\xd1\xab\x36\x8a\xa4\x94\x42\xe5\xe8\xa3\x32\xbf\xfd\x44\xc1\x69\xea\x67\x62\x9c\x85\x72\x4d\xb6\xf1\x58\x6b\x6c\x6b\x5b\xe4\x86\x4d\xfd\x53\xda\x7c\x0f\x7b\x8b\xb3\x57\x31\x16\xbe\x50\x77\xd3\x32\xbd\x12\xa6\x30\x0f\x3a\x68\xa8\x98\x66\xb4\x79\xec\x2b\xaa\x27\x7f\x9f\x56\xf6\xe1\xd4\x9d\x74\x1e\xb3\x22\x03\x5f\xf8\xcb\x1d\xe8\x5c\x8d\xc8\x7a\xc8\xe6\xe4\xc5\xd2\x0b\xfb\x6d\x31\x7a\xb1\x25\x93\x0c\x42\x60\x9b\xe3\xae\x82\x24\x2a\x9e\xf0\x56\x88\x58\xd8"}, -{{0x09,0xd8,0x12,0x26,0x97,0x12,0x6d,0xfc,0x7e,0x11,0x68,0x5a,0x04,0x12,0x3f,0xdf,0xb4,0x7c,0xcd,0xdb,0x44,0x99,0xd8,0xa3,0xae,0xf4,0x18,0xcb,0x65,0xae,0xd7,0xa7,},{0xf8,0xdd,0xb1,0xc0,0x0f,0x6e,0x0f,0x4b,0xea,0xa6,0xfc,0x38,0xe5,0xd0,0xa5,0x77,0x5e,0xe2,0x8c,0x80,0xdb,0xde,0x3f,0x0c,0x79,0x30,0xa3,0x3a,0xad,0x71,0x50,0xf3,},{0x18,0xcf,0xaf,0x6d,0xc8,0xe4,0xe8,0x58,0x2b,0xce,0xfe,0x0c,0xdc,0x6f,0xce,0xfe,0x6a,0x4a,0x87,0xea,0x62,0x95,0x85,0xf3,0x7d,0x2f,0xba,0x44,0x6b,0x3a,0xeb,0xd4,0x52,0x42,0x63,0x82,0xda,0x0d,0x49,0x1c,0x39,0xcb,0x7d,0x54,0xd2,0x73,0x00,0x5d,0xc1,0x32,0x12,0x15,0x68,0xd2,0xab,0x67,0x45,0x20,0xad,0xda,0x75,0x23,0x84,0x0d,},"\xa0\xd8\xd8\x79\x8e\xba\x22\xf5\x67\x60\xc3\x06\x43\xe9\xfc\x67\x95\x54\x7e\xa5\xf2\xf2\xbb\xd1\x1c\x03\x92\xb2\xeb\xf7\x11\xac\xa2\x2f\x08\x24\x19\x9f\xc3\x18\x8a\x45\xbd\xff\xde\x70\xec\xe9\xab\x15\xa5\xea\x89\x62\x2a\x58\x71\xe0\xef\x76\x85\xd1\x0f\x12\x74\xcc\x19\x5b\x4f\xda\x81\xf8\x79\xd1\xe9\xbf\x42\xf8\x73\xb2\x0a\x85\x9c\x23\x3f\x9e\x49\xad\xbf\x05\x77\x31\xe1\x13\x35\xe9\xb6\xd8\xed\x0e\x06\x9e\x13\x4e\xc4\x61\xca\x88\x90\xd7\xb0\x47\x3c\x40\x5e\x8a\x9d\x95\xd1\x57\x11\xb1\x24\x76\x10\x37\x62\xc6\x26\xd9\xf2\xaa\x5d\xd5\x19\xbd\x82\x5b\x60\xb3\x23\x4e\xbf\x65\x1e\x0d\x19\x33\x37\x1c\x52\xbf\xd8\xce\x33\xfc\x36\xbb\xa3\x28\xf7\xf3\xf2\xcc\xc0\x10\x00\xa8\x99\x04\xaf\x37\xe4\xe1\xe9\xe1\x5f\xff\xab\x5c\x2b\x0c\x47\xf3\x7c\xdc\xb0\x68\xdb\x33\xac\x36\xa5\xf0\xd6\xde\x12\x03\xfb\xf8\x94\x93\x24\xbd\x3e\xfd\xa0\xf9\x88\x9d\xb0\x0d\xa2\x31\x7b\x49\xfd\x18\x69\x99\xdf\x7f\xcd\xc3\xcb\x4e\x1d\x18\xfa\xa2\x54\x56\x1c\x25\x11\x78\xb8\xd3\x3f\xdc\x9d\xcc\xd8\xd2\xd7\x21\xb9\x3a\x53\x6c\xcd\x3c\x0e\x9c\x85\x63\x37\xf1\x95\xee\xe7\xda\x9a\x7f\x6b\x0a\x42\xb7\xc5\x41\xc6\xa6\x8c\x59\x5b\xf3\x47\x04\xd9\xfe\x3a\x56\xd2\xec\x84\x81\xd5\x77\xc9\x6e\xcc\x08\xb8\xe4\x0a\xcd\xbf\x05\x0e\x20\xc6\x83\xf3\x9c\x41\x4e\x8c\xbf\xcf\x4a\x01\x52\x31\x4c\x05\x98\x7a\x83\xbd\xe3\x02\x5b\x73\x5c\xca\x30\x23\xab\xc5\xfe\xb7\xe0\x0d\x02\x36\xb4\xf2\x4b\x15\xe6\x79\xdb\x05\x2c\x8d\x2f\xdd\xb3\xbe\xf8\x66\x3a\x6d\xf8\x19\xa9\x81\x55\x27\xa1\xa2\xf6\x0a\x0f\xa4\xe5\x07\x8d\xdc\x6d\x43\x5f\xe8\x92\x87\xb3\x0f\xfd\xeb\x5d\x9a\xe0\x5d\x1a\x86\x90\xfb\xc7\x59\x0a\xad\x57\xd4\x3d\x22\xc1\x2a\xce\x2c\x81\x96\x88\x8e\x35\x4e\x9f\x78\x2f\x5d\xbb\x44\x14\x9e\x83\xfb\x8b\xbc\x9d\xa6\xd8\x9c\xe2\x06\xc1\xe2\xb6\xb2\xb2\x8f\x93\x3f\x3e\x5f\xf1\x17\x5a\x31\xa8\xff\x5d\x31\xe6\x5c\x8b\x00\xc5\xba\x46\x22\x24\xa1\xe0\x9d\x4f\x09\xcb\x40\xfc\x87\xc3\x6e\x7d\x28\x5c\x77\x4a\x96\x97\x62\x03\x65\x18\x28\xe7\x83\x62\x88\x47\xac\x51\x2e\x5d\x1c\x35\xb3\x5b\x03\x01\x71\xf9\x23\x96\xf5\xff\xaf\xf5\x85\xce\xad\x04\xb6\xae\x21\x0d\x80\x70\x7c\xc6\x83\x2d\x98\xa2\x0d\x3a\x94\x76\x48\xda\x26\x04\x93\x7f\xef\xd2\x5a\x9f\xe0\xfc\x5c\xac\x08\x3d\xdd\x7d\x20\x75\x30\x7f\x4f\x38\x26\x64\xf6\x87\xdc\xe8\xc6\x55\xde\xd9\xc1\x2d\x48\xff\x76\x01\xdf\x2a\x48\xd3\x7f\xe2\x14\x97\x08\x44\xc0\x75\xf2\xea\xb0\x02\x05\x9f\xc2\x27\x1e\x61\x7c\x96\x57\xa0\x1b\xec\x1d\xd3\x8f\x6c\x28\xba\x8a\x61\x7b\xd3\x08\x51\xe3\xf9\xdb\xac\x90\x44\x18\xdf\x1d\x02\x15\xad\x45\xdf\xc9\xf0\x2b\x5c\x5e\x9f\x9b\xbc\x6d\xe8\xb0\x7a\xf0\xbd\x1f\x7f\xa8\x92\x25\x44\xf1\x2d\x2a\x3e\x1a\xad\xff\x7e\x9c\x6b\x93\x32\x0c\x3a\x61\xef\x33\xda\x07\xeb\x87\xb1\x61\x7f\x9e\x77\xd7\x70\x2e\x55\x8b\xc7\xd8\x12\x2e\x0d\xfe\x2a\xe8\x3e\x83\x6c\x5b\x1a\x62\xaa\x58\x5c\x0d\xff\xe7\x16\xf7\x46\x3c\x0b\x33\xda\x5b\x1e\xda\x55\x6a\x1e\xf1\xe4\x50\x42\xc7\x9b\xdd\x3e\xc3\xcb\x88\x63\xa7\xbc\x1b\x0f\x7e\x1c\x05\xbd\x99\x20\xf0\x5b\x4e\xda\x86\x51\x77\x05\xed\x07\xf6\xdc\xa7\xbb\x00\xae\x04\x56\xe6\x78\x7d\x9f\xae\x8e\xde\x4e\xcd\x0b\xc5\x72\xeb\x5c\xc6\xd1\x9e\x89\x1f\x1b\xcb\x22\x9e\x94\x09\xe0\x65\x74\xc7\xdf\x05\x81\x73\xcb\x58\xc3\xfd\xf2\x0f\x3f\xf1\x7c\x37\x05\xaf\x62\xd9\xb7\x22\x5c\x57\x43\xf6\x00\x60\x7f\x77\xcb\xe7\xd6\xe7\x61\x8a\xbc\x79"}, -{{0x10,0x20,0x1b,0xf0,0x08,0x43,0x67,0x59,0x0d,0xe6,0x74,0xcc,0x0e,0xd2,0x64,0x8e,0xc2,0x5d,0x3b,0xa8,0xdb,0x40,0xd0,0x0e,0xde,0x15,0x33,0x98,0x50,0x8b,0xc1,0x26,},{0xba,0xdb,0xd0,0x5e,0x5f,0x79,0xe3,0x11,0x69,0xf7,0x40,0xba,0x46,0xa5,0x89,0x10,0xa1,0xb7,0x77,0x05,0xaf,0x45,0x71,0x7b,0x2a,0xf8,0x08,0x56,0x45,0x7c,0x58,0xc9,},{0xf1,0xd9,0x96,0x58,0x8b,0x29,0x8f,0x27,0x1e,0x97,0x0c,0xeb,0xd2,0xa1,0xb3,0x39,0x97,0x9c,0xd2,0x9d,0xdd,0xee,0x36,0x45,0xd0,0x7f,0xab,0x8a,0xb4,0x65,0xdd,0xe3,0xe9,0x86,0x67,0xec,0x01,0xad,0x7f,0x1c,0x0a,0x65,0x92,0xe0,0x69,0x7e,0x66,0x5c,0x72,0xfd,0x38,0x14,0xdb,0xe1,0x89,0xed,0x5f,0x4e,0x76,0xc7,0x94,0xe5,0x38,0x09,},"\x7b\xb1\x47\x06\x17\xd1\x1e\x45\xeb\x60\x2a\x82\x9a\xd7\x73\xee\x2b\xb7\xe6\xb8\x8d\xa4\xc0\x4a\x72\x16\xa4\x50\xf8\x49\x93\xa4\x98\xcb\xd3\xb9\x25\x40\x28\xf2\xf9\x9f\xc2\x1a\x23\x28\x8b\xdc\x1e\x15\x1a\x72\xa9\x13\x0c\x3d\xed\xda\x1b\xbb\xcc\xd4\xe6\xc0\xf4\x8a\xe9\xf3\x53\x18\xcb\xef\xc9\x59\xf4\x05\x04\x5e\x6e\x0b\x5f\xb2\xe7\x38\xf2\xb7\x65\xbe\x11\xb1\xb6\xa0\xf1\xe8\x31\x95\x49\xd9\x5f\xa8\xd1\xdf\x81\x67\xcd\x4a\x77\x17\xae\x16\x36\xa9\xdf\x54\xd9\x6e\xaf\x2d\x63\x23\x69\x00\xfd\x11\x33\x82\x52\xa5\x00\x8d\x5d\x48\x0e\x2b\x1e\x98\x61\xd1\xf7\x06\x88\xc4\x7e\xae\x46\x89\xda\x01\xa4\x7d\xa3\xdf\xb6\xd2\xba\xb3\xcd\xf5\x05\xee\x5d\x80\x1a\x15\x2c\x26\x70\x93\xd1\x7e\x9b\xf7\x13\x7a\x6e\xe7\xb8\x34\xd0\x08\x55\x00\xe4\x01\xc1\x7f\x32\x86\xc1\x57\x5d\x1c\x01\x00\xfa\x98\x07\x63\x0c\x4a\x99\x06\x54\xc1\xe7\x1a\x8b\x71\x56\x27\xbb\x13\xd4\x42\xc8\x4a\x44\x98\x44\xc4\x04\xb8\x72\xbf\xba\xc7\x18\xa4\x8d\x0e\xa0\x94\x5c\x77\x16\x6a\x53\x13\x9b\x0f\xf0\x09\x81\x34\x76\x4f\x9e\xcd\xb8\x8e\xab\xe0\x7c\xcb\x2c\xce\xd4\x95\x5e\x08\x24\x9b\x2f\x57\x70\xad\x41\xfc\xcd\x7b\x5b\xb3\x72\xe6\xc3\x37\x67\xe0\x7f\x5b\xe7\xd1\x07\x12\xde\x81\x84\x1b\x13\x4e\x19\x3d\xf0\x77\x6a\x0f\xc1\x56\xff\x5d\x0e\x96\xf4\x0a\x70\x47\x53\xe1\x14\x5e\x9f\xa0\x83\xc4\xdd\xee\xf4\x41\x62\x34\xf6\xe1\xa2\x38\x2c\x8e\x5b\x3a\xd4\x05\x45\x8e\x89\xd2\xf4\x93\xa4\xd7\xc2\x9a\x23\xde\x21\x07\x48\x5b\x7f\x56\x35\x01\x24\xe7\xe0\xd6\x95\xc5\x22\xb6\xde\x7a\x92\x47\xa2\x92\x4c\xe6\xf2\x86\x32\x36\xc1\x0c\xc2\x12\x64\xad\x54\x59\x0d\x31\x47\x63\xea\x1a\x19\xaf\xac\xd9\x0e\xba\x95\x58\x70\x40\x7e\x8c\x63\x65\xa1\x43\xa5\xc1\xb9\xa8\xbe\x5e\x4a\x4d\xca\xdb\x72\xe0\xd4\x76\x49\xbd\x53\xab\xd4\x6b\x5c\x69\x60\xea\xe2\xca\xb7\x73\x75\x3c\xc0\xe0\x4e\x99\x41\x4b\xc2\xcb\x30\xf4\x8b\xb5\x41\x39\xd0\x66\xe4\x3e\x2f\x0e\x1a\x4a\xe9\x63\x85\x8b\xef\x96\x7d\xf8\xc8\x41\x40\xd2\xd0\x92\x02\xb4\x06\xd5\xd8\x5c\xb7\xa9\x6c\xc5\x7f\x23\x3e\xb2\x18\x7f\xfd\x02\xf9\x4e\x92\x29\x7b\x5e\x69\xd9\x69\xd3\xa5\x93\x6e\xfe\x49\x29\x14\x4f\x25\x8b\xfb\x39\xdd\x0c\xe2\x63\x59\xc4\x54\x9f\xc2\x18\xa0\xaa\x54\xf3\x1b\xd5\x51\xb8\x78\x1a\xcb\xbf\x61\xcb\x3f\x73\x2c\xda\xf6\x22\xc6\xa6\x91\x88\xcf\x55\x7a\x3a\x92\xed\x15\x3e\x69\x12\x5a\x40\x90\xac\x45\x15\x36\xa0\xe9\xa6\x3a\x41\x78\x29\x10\xff\xcc\xb4\xe8\x50\x02\x11\x23\xff\xd1\xf3\xbf\x39\xc7\x34\x60\xa6\x5c\xcf\xe4\xdb\xa9\xbd\xef\xb5\xd5\xf4\xda\x6c\x46\x9a\xa1\x32\x2f\xa2\x70\x43\x23\x83\x63\xee\x72\x91\x86\x88\xd7\xca\x1c\x4c\x29\x52\xe4\x30\xd5\x63\x25\x6b\xb8\x6d\x35\x0a\x35\xee\x82\xe0\x15\x04\x74\x7f\x31\xd0\x2e\x03\xae\xdd\xa5\x46\xd0\xf1\xb2\xf4\x51\xb8\x70\x82\x16\x02\xd0\x0e\x81\x90\x36\xad\xe5\xa7\xc7\xfc\xd2\x1a\x6d\xe6\xaf\x35\xb1\xf9\x63\x2a\x70\xaf\x65\xdf\x64\x45\xf6\xfa\xdf\xbc\x0f\x41\x67\x55\xc8\x24\x66\x40\xe5\x6b\x85\x6b\x66\xdd\xd9\x2a\x60\xc0\x35\x38\x22\x1d\xc8\xfb\x14\x2c\xe2\xdb\xac\xdb\x74\x25\xf3\x3c\xb8\x5d\x85\x0c\xc0\x2c\x31\x5c\xfc\x11\x1f\x6f\x65\x1d\xde\x1b\xdb\x67\xfb\x20\x8e\x1f\x6b\xde\x78\x4d\xdc\xf7\xbd\x18\xc8\x05\x1a\x2e\x0b\xbf\x10\x18\xb8\xf3\x95\x36\xc5\x89\xde\x65\xea\xdc\x6c\xf3\x79\xb7\x7c\xad\x13\xf9\x08\x9c\xb3\x23\xfb\x2e\x94\x3d\x06\xcd\xd1\x07\x05\xc1\x21\x13\x4c\x65\x48\xdc\x53\x41\x5f\x8c\x37\x0e\xc6\x90"}, -{{0xc4,0xaa,0x42,0x52,0x46,0xb5,0x17,0x3f,0x5e,0xf8,0x98,0x15,0x2e,0xca,0x3d,0x09,0x2b,0xb4,0xc2,0xdd,0x02,0x85,0x3f,0xcf,0xc7,0x17,0x83,0x99,0xf4,0xe2,0xf7,0x58,},{0x29,0xb7,0x7a,0x30,0x75,0xf4,0x19,0x24,0x3c,0x0c,0x1b,0xc3,0x96,0x59,0xd7,0x31,0x17,0xac,0x00,0xe5,0x5e,0x8d,0xe3,0x8f,0xe9,0x82,0x9a,0x87,0x9c,0xc5,0xb8,0xa0,},{0x5d,0x85,0x45,0xa4,0xbe,0x3f,0xd6,0xda,0x25,0x78,0xc2,0xec,0xcb,0x64,0x8d,0x83,0xfc,0xfe,0x58,0x71,0x33,0xfa,0x7a,0xe4,0xa1,0xcf,0xca,0x9a,0xe6,0xda,0xa4,0x92,0x59,0xc9,0x52,0x04,0x4a,0x85,0xa2,0x0b,0x6f,0x53,0x24,0xf8,0x27,0xdb,0xa2,0xd1,0xa8,0x38,0x8c,0x40,0xa9,0x28,0xb9,0x50,0x91,0x3c,0x63,0x4f,0xb3,0x09,0x27,0x07,},"\x7d\xf9\x78\xa1\xf4\x97\x68\x38\xff\xed\x74\x49\xa4\xdc\x13\x8b\x60\x4f\x4b\x2a\x4a\xe6\x89\xce\x75\x01\x8e\xbc\xcd\xab\x2e\xaa\x0b\x60\x76\x8f\x72\x08\x25\x7f\x2b\x28\xe7\xaa\x09\xbf\x6c\x05\x88\x8d\xa4\x6f\xd3\x96\xd1\xc8\x03\x01\x17\x50\xe3\x0e\xb4\x84\x87\x0c\x88\x06\x97\x76\x96\xf1\x2e\xbb\x9f\xee\xb4\xca\xf9\x2a\x02\xdb\xaa\x22\xbb\xff\x63\xf8\x42\xc3\xba\x14\x7b\xca\x7c\x00\x31\x42\x78\xac\xd0\xdb\x17\x35\x69\xf4\xe3\x65\x27\x95\x8e\xf6\xf1\x00\x2b\xd3\xcd\x01\xf4\x07\xa8\x65\x31\xed\xcb\xd9\xf3\x1b\x3a\x4a\xb8\x80\xa4\xf5\xb5\x2b\x42\xd0\xd4\xa1\xba\x66\xa2\x09\x86\x51\xae\x3e\x6c\x91\x51\xf4\x02\x73\x28\x5f\x7f\x6a\x4e\x81\x60\x6b\xf9\x80\xf6\x89\x50\x4b\x42\x08\x0f\xdb\x97\xc7\x28\x46\xfb\xa9\x04\x7c\x7e\x66\x0b\xa5\xc6\xbf\x12\x6a\x9a\x59\x9e\x25\x71\xfa\x13\x50\x5a\xf7\x58\x1b\xfe\xbc\x16\x51\x3f\x5c\x94\xdc\x71\x93\x7e\x6e\x61\xb3\xea\x10\x93\x9b\x02\xea\x10\x85\x9f\x32\xd7\x91\x2b\x9e\x38\x06\xab\xef\x61\x85\xfc\xff\xa6\x88\x21\x47\x80\x05\xcb\xfc\x1d\x63\x7d\xd0\x20\x42\x56\x20\xa3\x18\x07\x48\x98\xbd\xc3\x09\x31\xc5\x9a\xc0\xc6\x6c\x4d\x12\x38\xb0\x97\xcd\x5b\x17\x0f\x08\x44\x35\xd4\xba\xe4\x8a\x03\xd9\x2f\xd4\x8f\xc2\xca\xa4\xff\xc5\x05\xf1\xbc\xa5\x16\xfb\xd6\xe4\xf8\x88\xcc\xed\x98\x2a\xe0\xdd\xb8\x8f\xc2\x8a\xa6\x97\xb7\x07\x1d\x01\x5b\x0a\xcb\x28\x09\xb0\x1d\x1d\x9c\x7e\x7b\x53\xee\xe6\x82\x4c\xc3\x7c\xce\x5b\x69\x93\xd8\x8d\x83\xea\xfc\x2e\x92\x8a\x6f\x14\x7d\xb6\xeb\x80\xb1\xa6\x9f\x01\x60\x5b\x04\x6b\xd2\xfd\x1d\x92\xc5\x45\x9d\x6d\x33\x98\xa9\xca\xa2\x99\xdd\xd0\xc3\xba\x2e\x08\x94\x13\x07\xb1\x20\xcc\x13\x99\x2f\x70\x03\xac\xed\x14\xa4\xa4\xd9\x23\xbb\xb1\x2f\xc3\x93\xff\xcf\x92\x0b\x9f\x6d\x47\x75\xe9\x4d\x4a\x51\x22\x67\xfd\x26\xa6\x99\x7c\x60\x62\xb4\xc9\x90\x0f\x98\x62\xb9\xea\x0c\x8d\x7d\xf1\x9f\x05\xc2\xb6\x04\xaf\x5b\x98\x64\xfb\x27\x54\xa8\x07\x3b\xbb\xfb\x18\x23\x3e\x6e\x15\x0f\x72\xa5\x25\xe3\xa5\x76\x0f\xcd\xa7\xd3\x2a\x60\x03\x4f\x95\x6e\x3c\xbd\x34\x36\xc2\x00\x83\x0b\x3e\x7a\x14\x57\x12\x20\xbc\xb6\x27\xd5\xa4\xbe\x72\xc2\x0b\x23\x35\x1b\x2d\x92\x06\x02\xa5\x1c\x3e\xb3\x2c\x12\x37\x03\x9d\xfb\xff\x43\xc9\x87\xfd\x85\x63\x77\x7f\x0e\x5a\x39\xf8\x14\x6c\x16\x4b\xdf\xfc\xe4\x4f\x3b\x13\xee\x74\xd6\x4b\xfd\xcf\x98\x03\xf0\x3d\xd0\x17\x2a\xc4\xfa\x4b\xf6\xc7\x83\x9c\xb1\x1f\x3d\x34\xba\xef\x0e\x32\xb5\x49\x42\xfc\x4f\xa3\x8f\x47\x3e\x29\x66\xf4\x91\x1c\x0e\x80\xd7\x69\x37\xb2\x5b\x76\x32\x27\x5b\xa8\x83\x09\x63\x5a\x60\xdf\x13\x54\x89\x20\x8d\x3e\x73\x4b\x67\x2e\xda\x7d\x2b\xa2\x15\x79\xab\xa8\xd8\x86\x0e\xa7\x64\xfd\x67\xea\xf9\xc3\x8e\xa7\x63\x7d\x1b\xad\x57\xb2\xf3\xd7\x82\xb9\x1e\x1d\x5d\x92\xac\x30\x0b\xdb\xa7\xab\x91\x13\xce\x91\x3d\x0c\x79\x3c\x12\xa9\xa7\x26\xe3\xfc\xab\x05\xcb\x47\x99\x77\x87\x16\x40\x63\x0d\x45\x9e\x69\xe8\x1c\xa5\xcf\x56\xdd\xb2\xa0\x61\x1d\x61\xd4\x81\xc1\xb8\xce\xf3\x80\x4b\xd4\xe5\x75\x4a\x61\xeb\x49\xb1\x7e\xf2\xb0\x3c\x83\x05\x7b\x5d\x20\xd8\x82\x05\x8c\x00\xf5\x4b\x6c\xca\x86\xbe\x95\x35\x0d\xd7\xbc\xb2\x5e\x4c\x1c\x46\x58\xf4\x52\x29\xc8\xbb\x9f\x5c\xdf\xcc\x44\x79\x5c\x97\x8e\x33\x88\xd3\x25\x76\x01\x06\xe5\x2b\xe9\x83\x4b\xd8\x1f\xfc\x5c\x62\x48\x6b\x6f\x33\xc2\x74\x59\xdf\x17\x8e\xb9\x46\xe7\xa8\x2d\xb9\xce\x0d\x29\x5b\x92\x5b\xb6\x12\x6d\xd5\x5c\x31\xf4\x9a\x68\xdc\xef\xc7"}, -{{0xf1,0x3c,0xaf,0xde,0x6f,0x39,0xb9,0x63,0xdc,0xa9,0x66,0x26,0x86,0x2f,0x4f,0xbc,0x5c,0x2e,0x00,0xdd,0xf0,0x8b,0xec,0xea,0xc7,0xa6,0xe2,0xfc,0xa9,0xe1,0xcc,0xf7,},{0xc1,0xb0,0x1a,0x91,0xe8,0xee,0x0b,0x9f,0x19,0xa7,0x2e,0x5e,0x7e,0x0a,0xef,0xcf,0xdc,0x44,0xa1,0x57,0x47,0x4e,0x99,0xfe,0xeb,0xd0,0xff,0x55,0x2d,0x73,0xb2,0xac,},{0x6c,0xa9,0xf8,0x0a,0x62,0x50,0x1f,0xaf,0x31,0x9f,0xb8,0x4a,0xf4,0x71,0xf6,0x76,0xae,0x3f,0xff,0x85,0x56,0x5c,0x97,0x98,0x1f,0x14,0x57,0xcb,0xb8,0xc4,0x9f,0x97,0xb2,0x66,0x31,0x6a,0x99,0x2d,0xb0,0xd4,0x2b,0xc5,0x02,0xf0,0x95,0xa5,0xf2,0xd9,0xa4,0xe1,0xcf,0xac,0x0c,0xc9,0x35,0xd3,0x88,0x2c,0x8a,0x3a,0x0e,0xa6,0xe1,0x0e,},"\x2b\xee\x73\xb7\x4f\x1b\x76\x22\xeb\x09\x6a\x28\xd8\x3a\x81\x9b\xce\xc2\x2d\x99\x99\xa3\x20\x62\x10\x3d\x60\x4a\xe6\xd7\x8e\xdf\x8f\x89\x38\x95\xd2\x22\x0a\xb7\x56\x90\x41\x0c\x58\xaa\xb5\x90\xa9\x8d\xdf\xf2\x3a\x94\xd2\x35\x0f\x88\x9e\x53\x46\x42\x00\xa5\x27\xd5\x4d\x62\x57\x11\x07\xb2\x7e\x57\x4f\x54\x2e\xba\xc2\x49\xb8\xe2\xe3\xce\x08\xd1\xbd\x27\xbd\x8d\x29\xf2\xe6\x12\x43\xde\xef\x0e\x69\x38\xe5\x2e\xe2\x99\x2f\xf2\x18\x7d\x7a\x7f\x52\x82\xed\xd9\x8f\xc4\x98\x5b\x61\x9a\xcb\x80\xaa\x9d\x03\xd6\xcb\x84\xb8\x21\x10\x6f\x40\xd6\xe5\xf4\xc3\x87\xab\x0a\xf6\xf2\x06\x61\x5d\x0a\x17\x5f\x7e\x60\xee\x27\x55\xae\xa3\x46\x75\xfd\xd8\x23\xeb\x24\x10\x9a\x9b\xd8\x18\xea\x2d\x9d\x9b\xd1\x99\xcf\x8d\xfe\x79\x62\x4b\x03\x72\xae\x85\xe9\x8c\x60\x20\x02\x34\xbd\x41\x3f\x4a\x62\xce\x68\xa4\x7b\x6c\x9b\x12\x85\x7c\x0d\x39\x9a\x44\x8e\x5a\x52\x80\xe9\xf2\x2f\x9b\x12\xea\x2c\xd3\xc6\x87\x13\xe7\x7d\x0a\x11\xf3\x62\x8d\x8e\xc5\xe0\x60\x63\x90\x31\xd3\xb6\x40\x02\x1c\x9c\x38\x80\x9d\xc5\xf4\x2d\x2e\x1c\x2e\x23\x46\xc8\x6e\x24\xee\xdc\x59\x84\xa1\x15\xa4\x2d\xe8\xde\x7e\x35\xc9\x91\x75\x39\xe8\x98\x85\xca\x91\x6e\x07\x2a\xfd\x5d\x46\x84\x6b\x2a\x93\x59\x61\xc2\xfe\x28\xe9\xeb\x3c\x8f\x89\x6b\x86\xfc\x12\x0c\xbd\x3a\xf2\xaa\x13\x9c\x49\x9d\x29\xcf\xc3\x69\x9d\xb7\x9c\x14\x48\x4e\x9e\xc2\x57\xa5\xf6\x43\x44\xb7\xad\x1e\x3d\xfb\x34\xee\xe7\x65\x4c\x6b\xf1\x2f\xd3\x8f\xbb\xa8\x0f\xe1\x76\x2a\xab\x57\x11\x2b\x3a\x94\xe2\xbe\xe7\x90\x41\xd1\xe8\x84\x40\xf8\x5f\xb7\x2d\xde\x68\xd4\x9e\x84\xbc\xed\x99\x8a\x2f\x63\x35\x44\x6e\x4a\x83\x5e\x70\xc5\xf8\x27\xfb\x3a\xd7\x82\x3d\x5f\xbe\x3b\xe5\xf6\xec\x7e\x43\x4e\xe5\x24\xcc\xd9\xff\x5b\x7e\x72\xa3\x2d\x09\x1a\x7e\x17\xc8\xb1\xae\x41\xa1\xaf\x31\x79\x3c\xce\x91\xd8\x4c\x36\x22\x67\x89\x69\xc8\xf5\x17\xdc\x26\xe3\xcd\x61\xd2\x44\x69\x12\x28\x3f\x93\x53\xbb\x5a\xd0\x3c\x11\x1c\x62\x33\xde\x31\x4c\x61\xb8\x31\xcb\xf3\x8b\x04\xfe\x58\xcf\x44\xf1\xd2\xd0\xb4\x5f\x25\xa6\xb4\xe0\x25\x68\x59\xcd\x5d\x83\x0f\xac\x5e\xc3\xc8\xd7\x63\x98\x55\x9e\x9b\x26\x01\x0f\x5e\x1d\xa5\xf2\x5d\x22\x00\x93\x54\x53\xff\xac\x5a\xea\x51\xf7\xe8\x1e\x72\xec\x8e\x5f\x04\xd2\xf8\x85\xc7\xb4\x5c\x63\xf6\x44\x56\xcf\xe2\x31\xb8\xcb\x24\xaa\x16\x20\xa9\x02\x63\x9c\xa7\x8d\xd3\x91\xaa\x4a\x3d\x03\xe1\x19\x75\xc8\x90\x7f\x96\x4f\xd5\x5d\xf9\xbb\xb1\x40\xe3\x8d\x6d\xb9\x32\x56\xb4\xb3\x9c\x2b\x7b\xcb\xe3\x5b\x11\x82\x6b\xbf\x8c\x08\xf1\xdc\xb4\x8e\xdc\x4b\xfb\x70\x46\x2a\x35\xea\x8c\xd8\xcb\xa7\x9f\xab\x8b\x4c\x44\xe7\x3b\xe7\xec\xfa\x11\x21\x66\xf6\xdc\xab\x70\xd8\xbb\x55\xd8\xb8\x42\x8c\x2d\xa7\x1a\xac\xa2\xfc\x3d\x90\xf3\xcc\x5e\xd0\x15\x51\x35\x8d\x60\x78\x9b\x9d\x57\x1e\xfe\x10\x89\x20\x27\xfa\x37\x40\x4a\xaf\x59\xec\x1c\x2d\x71\x11\xec\xc3\x59\x24\x67\xed\x1d\x9b\x8a\xba\x8e\x22\x9e\x32\xd2\xa0\x0c\x19\xdb\x71\x87\xfb\xcb\x12\x20\x61\x96\x1c\x1f\xda\xca\x30\x7e\x9c\x9c\x9d\xe9\x72\xad\x51\x40\x2f\xa6\x7d\xc1\xc2\xa4\x03\xb3\xc5\xe8\xb1\xe2\x46\x86\x2d\x6a\xd6\xa4\x98\xdb\x6d\x76\x1f\xb5\x66\xf6\x06\x59\x42\xb6\x0a\xd4\xb4\x30\x9d\x18\x2b\xc5\x15\x4c\xfc\x36\x86\x31\x85\xa8\x7e\x23\xab\xaa\x1d\x54\x1a\xb7\x63\xa4\xa1\x06\x6c\x0a\x7a\x8c\x3d\x82\x1a\xe3\x2f\xd3\x1c\x88\x92\x40\x10\x46\xd0\xa2\x0e\x91\xa6\x47\x79\xf4\xbd\xa8\x11\x20\xaf\x3f\xb3\x48\x6d\x3f\xc0\xa7"}, -{{0xc8,0x46,0x34,0x42,0x61,0xa3,0x48,0x65,0x39,0x38,0x34,0xbf,0xaa,0x3a,0x15,0xa3,0xf5,0x3a,0xc9,0xe1,0x38,0x33,0xb0,0xb2,0x87,0x12,0x27,0x81,0xb7,0x9d,0xe3,0x92,},{0xeb,0xad,0xe0,0x22,0x61,0x95,0xae,0x25,0x4b,0x61,0x15,0xe2,0x16,0x96,0xa9,0xc6,0x5a,0x19,0xd5,0xe0,0x40,0x44,0x31,0x31,0xc2,0x2b,0x89,0xf0,0x2f,0x69,0xab,0x78,},{0xd5,0xe4,0x1b,0x47,0xad,0x0f,0x34,0x00,0x70,0x97,0x70,0xed,0x43,0x91,0x9b,0xaf,0xdf,0x24,0x38,0x1b,0x66,0x15,0x44,0xe5,0x1d,0x8b,0x5c,0xee,0x9e,0x97,0xb3,0x67,0x6a,0x4c,0x0f,0xfa,0xeb,0xb2,0xcb,0xd2,0xdb,0x79,0x85,0x32,0xb6,0x5c,0xf6,0x54,0xa5,0xb6,0xc1,0x66,0xef,0x88,0x6c,0xb0,0xfb,0xbf,0x4a,0x4f,0x84,0x4c,0x44,0x0b,},"\x5a\xbd\x13\xe9\x5b\x6e\xe1\xd5\x51\x47\x68\x28\x22\x00\xa1\x4f\x7d\x1a\x57\x1f\x34\x68\xe2\x2e\xfe\xc9\x93\x46\x30\x66\xa3\x7a\xec\x83\x73\xe5\xfb\x49\x95\x64\x19\x1f\x32\x94\xa9\xb3\x0a\xfb\x5f\x1a\x34\xd4\xd8\x8a\xbc\x3e\x9b\xc3\x03\xc1\xab\xa0\x5b\xd8\xfa\xca\x90\xee\x35\xd9\x7a\xc3\xdd\x91\x06\xf6\xfa\x3c\xa8\x1a\x38\x10\xec\xce\xfa\x6a\x20\x9e\xa3\xf3\xfc\x30\x49\xdc\xb1\xb0\x03\xc7\x28\xf7\xf6\x37\x4c\xa9\x8c\x58\x2d\xe6\xdb\x1a\xf7\x60\xf0\xa0\x21\x33\xca\x4a\x01\x03\x24\x30\x4d\x26\xa0\xe5\x0a\xf0\xd1\x3c\x13\x4d\xa3\x4a\x03\xa4\x1e\x83\xec\x8f\x10\xea\x5b\x85\x9b\xec\x1f\x51\xb0\x1c\xab\xb2\xd1\x6c\x1f\xc5\x2b\x05\x8f\x8e\x5d\xef\xae\xde\x12\x81\x71\xc2\xe0\x26\x90\x23\x16\xf8\x71\xb3\x5e\x32\x92\x65\x6f\x0e\x5b\x39\xbb\xbc\x81\xd0\xc0\x83\x0e\x6a\xc0\x1f\xac\x9b\x45\x39\xf4\x7f\x9a\xcf\xbd\x58\xb7\xab\x9f\x5a\x12\x56\x00\xf2\x51\xa2\x71\xd7\xbf\x16\x7f\x29\x54\xca\x8e\x1e\x0c\x96\xe1\x6b\x06\xe8\x30\x7d\xf8\x8b\xb8\xe9\xd5\x7d\x5b\xa0\x44\xf2\x7f\x3e\xaf\xf8\x1d\x9f\x15\x05\x54\xaa\x71\x22\xfd\x10\xd1\x1f\x35\xd2\xbe\x2b\x16\x24\xe3\xe1\xa1\xd7\x7f\xea\x4c\x5c\x7f\x8b\x98\x3e\x94\x5b\xa8\xc0\x8d\xc1\x54\x5b\x3e\x6b\x29\x73\xad\x04\x1c\x44\xd0\x61\x7e\xcc\xc8\x71\xa3\x82\x1a\x9f\xfe\xa9\xdb\x7c\x2b\x0d\x05\x5d\xa5\x5d\xe0\xb3\x50\x63\xe4\x22\x5a\xee\x6b\x22\x5a\xb2\xa7\x90\x6a\x8e\xe3\x29\xd1\xb3\x97\x2e\x0d\x1f\x70\x81\x7c\x50\xcc\xfe\x94\x03\xd1\x2a\xd6\x2c\x94\x92\x3b\x9a\xa2\xd7\xf8\x5a\x8d\xda\x47\xbe\x4d\xce\xc0\xdc\x2b\x0b\x58\xf7\xac\x19\x0a\xe0\x57\x9b\x9b\x13\xbb\xb8\xb1\x6a\x31\xb0\xab\x4d\x6f\x27\x91\x25\x3a\xb4\x75\x1b\x53\x6b\x88\xd3\xb4\x93\x7c\xc3\xa1\x10\xaa\x82\xa6\xff\xed\x68\x53\x52\x4b\x66\xb3\xef\xfc\xd2\xf6\x3c\x6f\x96\x45\xce\xa1\x3a\xa2\x3c\xd1\xc9\x9d\x9f\xfd\xa4\xcd\x3a\x9c\x5d\xf4\x5e\xc7\x47\x26\xc3\x47\x11\x28\xb7\x08\x9f\xbd\x82\x69\x4d\x2d\x3f\x08\xdc\x93\x06\xc0\xfc\x9c\xe7\xc8\x01\x13\x8e\xb1\xec\xb7\x56\xe5\x71\xe9\x05\x9b\x75\xed\x03\xf9\x2a\x31\x50\x2f\xbe\xb5\xfe\xc5\x1d\xe9\x35\x90\x10\xc4\x39\x7d\x28\xb6\x5e\x35\x6e\x38\x00\x1d\x0d\x51\xac\x96\x00\x72\x8c\x78\xb5\x76\x6e\x0f\x21\x79\x38\xb4\x10\xe7\x85\xb4\xc0\x1e\x86\xa3\x45\x2b\xcb\x38\x84\xac\xa4\x75\x40\x85\x9c\xc4\x9b\x00\x0f\x0b\x61\xfd\xbe\x72\x75\x25\x74\xb2\x7a\x22\xd4\xc4\x04\x13\xa4\x3b\x31\x09\x24\xb1\xbb\x14\x0f\xc9\xfd\xaa\xe2\x66\xd6\x59\x30\xe3\xf2\x34\xfe\x84\x1d\x82\xb2\x61\x76\xff\x86\xc5\xd2\xbd\x8d\x96\x5c\x52\xd7\x28\x06\x4e\xbd\xf6\x8d\xc8\xe4\x83\x49\x41\x80\x1c\xca\x0b\x2f\x25\x6d\x4f\x6c\x3d\xd1\x9d\x35\xd5\x36\x2b\xbf\x9b\x8a\x3a\x1c\x86\x3e\x09\x26\x89\xdd\x28\x52\xad\xd4\x88\xbf\x42\x68\x5b\x11\xe1\xe1\xad\x57\x45\xd0\x75\x62\x8d\x73\x1f\x91\xcf\xd7\x49\x15\x9e\x2e\x1c\x83\x7f\x4e\xf8\x3d\x80\xea\x1d\xd9\xbd\xed\x5f\x88\x01\x8c\xe1\xd4\xb3\x37\x1f\x95\x43\x53\xf3\xd8\x94\x37\x00\x62\xc0\x96\x5d\x67\x98\x6d\xbc\x48\x17\x15\xf4\x2d\xd2\xc9\x16\x07\xab\x8b\x5f\x0d\x89\xf6\x6e\x68\xd7\x3d\x50\xd6\x40\x52\x4d\x72\xe6\x91\x34\xb8\x87\x29\x8e\x5c\xd8\xc4\xb9\x05\xba\x5e\xfa\x0e\x9d\x68\x52\x14\xb8\x42\xf5\x0a\x2a\x39\x83\xa1\xaf\x58\x5a\xf2\xca\x43\xdb\xcf\x02\xc4\x08\x97\xae\x2e\x1a\xb5\x1d\xbc\xe5\x70\x34\x5e\x8e\x13\x5f\xb7\xb4\xeb\x0a\x1d\x6a\x0b\xb5\xa8\xa1\x80\x7e\x42\x5b\x2d\x62\x83\x60\x76\x80\x58\xe6\x1a\xd1\xcf\xaa\x20\x99"}, -{{0xfa,0xaf,0x55,0xd3,0xc2,0x97,0x14,0xb6,0x5c,0x22,0x81,0xe2,0xc2,0x2d,0x61,0x34,0x97,0x1a,0x2e,0x74,0x00,0x8f,0xb9,0x40,0x89,0xa7,0x73,0xee,0xeb,0x44,0x83,0xa6,},{0x39,0x86,0x2e,0xac,0x6d,0xd5,0x2e,0x38,0x1b,0xb3,0x4d,0xc1,0x96,0xba,0x8a,0x37,0x4d,0xcb,0x7d,0xf6,0xcb,0x14,0x0f,0xd0,0xcf,0xa6,0xcf,0xa3,0x9b,0x8c,0x75,0x3f,},{0x5b,0x00,0x83,0xf7,0xa8,0x20,0x61,0xc6,0x5c,0xf6,0xc7,0x56,0x40,0xc8,0x1c,0x28,0xe8,0xd6,0xd2,0xe8,0x7f,0x6d,0x57,0x95,0xc9,0xaa,0x3b,0xb3,0xe3,0x90,0xe9,0x19,0x90,0xe8,0x2d,0xb6,0xf0,0x7e,0x61,0x4f,0x50,0x7a,0x56,0x0a,0xba,0xa1,0xec,0xa6,0x56,0xc6,0x78,0xdd,0xca,0xe8,0x19,0x82,0x51,0xe6,0xaf,0x0b,0x76,0xb8,0x8d,0x0d,},"\x94\xe6\x61\xc2\x52\x40\xa8\x9e\x82\x3d\x7f\x5d\xc0\xe6\x92\xed\xdd\x13\x70\xc3\x5a\xc4\x4d\x5a\x8c\x87\x98\xd0\xc9\xaa\xfd\xf0\xbb\xfb\x54\x92\x60\x56\x8d\xba\x1c\x69\x08\x6b\xee\x63\x6b\xe8\xed\xcc\xd3\xcb\xb2\x70\x16\x24\x4d\x54\xd7\xed\x2f\xeb\x7f\xa6\x46\x14\xd4\x54\x49\xd7\xe0\x58\xe7\x1b\x30\x6c\x22\xe6\x91\x1c\x2a\xc7\x42\x07\xba\xe5\xa8\x4d\x0f\xc2\x47\xbe\x49\xd3\x56\xe5\xd4\x35\x3b\xa5\x58\x6b\x6e\x4b\x2b\x97\xce\x9e\x23\x77\xb6\xee\xd9\x2c\x84\x9e\x67\x69\x44\xae\x90\xdc\x42\x08\xe3\x00\xe1\x9c\xc9\x1d\xc2\x6b\xbd\xd5\xa3\x0c\xfa\x92\x81\xa1\x5e\xfd\x87\x30\x66\xf8\x5a\xf3\xa2\x6f\x31\x06\x23\xe0\x09\x80\x48\x53\xcc\x68\x55\x90\x3e\xa6\x4a\x90\x98\x97\xe3\x15\xe7\x3d\x31\x29\x48\x98\x0e\xf6\x28\x9d\xb2\x1a\x5e\xbb\xec\x8c\x8e\xfe\x20\xd1\xd5\x3d\xfa\xad\x6d\x9f\x42\x96\x53\x2e\x88\x7c\x37\x35\x01\x05\xa6\x33\xab\xc7\x73\x18\x87\x51\xb2\x8c\x3a\x08\xf1\xb5\xee\x04\x72\xde\x46\x27\xe6\xb6\x1b\x68\x27\x8d\xd5\x1c\xed\x6a\x61\xec\xf3\x88\x86\xe4\x53\x39\xdc\x6c\x60\xc3\x1e\x85\x0e\xf8\x29\x6a\xe8\x0f\x9d\x31\x70\x17\x76\xeb\x9a\xf2\x16\x93\xf4\xc5\x2e\xc0\x62\x62\x57\x38\xd4\xe3\xaf\xbf\x71\xd1\xc8\x1f\xc4\x84\x63\x60\x36\x3e\xa5\x41\xa9\x76\x62\x3a\x5e\x4e\x6b\x6a\x67\x23\x7e\x92\x37\x17\x3f\x1a\x1d\x54\x33\x02\x85\x88\x85\x71\x4c\x2a\x59\x1d\x0a\x78\x62\x82\xa0\x28\x5a\x37\x11\xf7\xbc\x2b\x63\xca\x79\x87\xe9\xae\x7d\x02\x03\x55\x55\xcf\x3b\x6a\xd6\xf7\x1c\xa9\x8a\xa9\x28\x88\x3b\xf8\x1d\xd6\xf8\x64\x93\xea\xab\x56\x37\xb4\xdd\x56\x9d\x1e\xe8\xde\x6a\x44\xbc\xed\xb6\x2b\x97\x06\xb1\xdb\x89\xe3\xf0\x5d\xf1\x63\x10\x01\x7d\x89\xef\x3e\x4b\xc0\x99\xb7\x21\xa5\xc8\xd3\x80\x43\xd6\xe4\xa2\x2c\xf0\x40\x09\xc0\xfc\xee\x6b\xe6\x99\x37\x82\x99\x54\x94\x1b\x8b\x4a\x1e\xbf\x4d\xae\xa0\xd7\x74\xd0\x78\x2b\xe1\x76\xc8\xe5\x91\x90\x77\x56\xc2\xcf\x75\xde\xa6\xf7\x87\x7d\xd6\x87\x5b\x8f\xe1\x01\x2f\x30\x50\xcf\xb1\x28\x9c\xf0\x88\x66\x7e\x15\x22\xee\xed\xc9\x27\xac\x86\xbf\xe2\xc4\x07\x43\x2b\x4a\x81\x3a\x6a\x7a\x55\x04\xe9\x99\x20\x6d\xb1\x82\x7e\x25\xfa\xfd\x70\xce\xd3\x6d\xb3\xb2\x81\xb6\xf7\xb1\x4e\xd5\xba\xa0\x57\x23\x15\xa9\x39\xc5\xbf\x4a\xbb\x13\x3d\x2e\x7b\x16\xd5\x2d\xe2\x08\x17\xaf\x05\x5d\xf5\xf1\x41\x20\x77\x34\x61\x0a\x0c\x6e\xeb\xed\xaf\xff\xd9\xcc\x9f\x06\x9b\x67\xf9\xa1\xc0\x45\x4b\xe4\x1d\x54\xc1\x38\xbe\x54\x2e\x5e\x38\xcf\xe2\xf2\x93\xf7\xd2\xd3\xdf\x66\x97\x7a\xcb\x36\x6a\x42\xc1\x9b\x31\x85\xac\xfa\x1b\x36\x3c\x61\x31\xa4\xa8\x11\x1c\x3b\x1f\x4f\xd7\xac\x40\x6d\x0e\x69\x10\x3b\xa1\x5b\x8c\x4b\xf2\x9b\xc2\xed\x9c\x45\xcf\xd1\xd2\x79\xd8\xd9\x31\x44\x4b\x2b\x18\x49\x25\x2b\x8a\x70\xee\xd8\x0f\xd2\x60\xed\xf5\xa3\xc0\x1b\x96\x90\x16\x0d\x23\x11\x85\x1d\x21\xc9\x30\x2d\x98\x59\x86\xea\xee\xb3\xae\x2c\x07\xc7\xc7\x67\x20\x94\xf9\x1d\xb0\xbd\x50\xbe\x37\x7e\x4d\x1e\xb0\x7e\xe7\x6a\xf4\x9d\xc1\x36\xa1\x45\xa1\x1b\x17\x2f\x08\x11\xfe\x73\xd6\x25\x9b\xe3\x70\xc4\xdf\xca\xb6\xf1\x9e\x4a\x64\xb1\x51\xd0\xa6\xdb\x80\x50\xc3\xde\x2c\xc3\x25\xf5\xc5\xf6\x59\x4c\xf6\x24\x8e\xb0\x81\x20\x95\x39\xe0\x8c\xa3\x42\x29\x84\xe7\xbf\x80\x3d\xe3\xa4\x19\xb1\x44\x23\xf1\xe5\xa5\x42\x24\x04\x2c\xe4\xf0\x54\x88\xa6\x04\x4f\x40\x42\xbd\x64\x9b\x1a\x08\xce\x10\xc2\x00\x6e\xa7\x6e\xfa\xb4\x64\x1f\xef\x28\x97\xef\xd7\x24\xe6\x05\x4a\x3b\xd1\xa6\x9e\x39\xa4\xa5\xe2\xd5\x02"}, -{{0x6d,0x78,0x55,0xe3,0x0f,0x7a,0x13,0xe2,0x37,0xb0,0x67,0x14,0x43,0x46,0x43,0x4b,0xb4,0xb0,0x51,0x78,0xc7,0xd8,0x8d,0x49,0x2e,0x79,0x02,0x7c,0x4b,0x0f,0x3c,0xdd,},{0x72,0x73,0x29,0x38,0x28,0xef,0xa3,0x49,0x82,0x23,0x92,0xdb,0xba,0xb0,0x78,0x79,0x57,0x7e,0x1a,0x77,0xa6,0xfd,0x6a,0xfe,0x33,0x75,0x3a,0x9e,0xec,0x88,0xc4,0xaf,},{0x0f,0xe2,0x8e,0xad,0xd9,0xe5,0xdd,0x57,0x4b,0x3f,0xaa,0xea,0x81,0x0d,0x44,0x52,0x2c,0x8b,0x1b,0xfb,0xb3,0xe3,0xd5,0x7e,0xd8,0x89,0xfa,0xed,0xec,0x91,0xd0,0xe1,0x4a,0x86,0xb9,0x14,0xc4,0xc7,0x66,0xf1,0xbf,0x9b,0x8f,0x18,0xb0,0xdb,0x89,0x0d,0xb6,0xc1,0xb1,0x25,0xd5,0x78,0x04,0x33,0x36,0x19,0xb1,0xe0,0x72,0x0a,0x33,0x00,},"\xf8\xb9\x36\xe7\x93\xb0\x17\x58\x0c\xc0\xe9\xcb\xda\x2a\xcb\x64\x74\x50\x7f\x4b\xca\x3a\xfc\x87\x83\xec\x46\xee\xb8\x2c\xcd\x4d\xd2\x52\x56\x76\xaa\x6a\xb5\xc0\xdc\xf7\xd7\x5f\x7e\x03\x11\xe6\xfe\x6b\xf2\x72\x63\xf8\x57\x8f\xeb\x55\xc5\x61\x2d\x1f\x28\xe8\x88\xb7\x66\x56\xc4\x1c\xcd\x8a\x70\xb9\xbc\x60\x4b\x42\x72\x4f\xa2\xbc\x41\x1d\x44\xc3\x1a\xb6\x8c\xe8\x4f\x83\x93\x39\x9e\x34\xd5\x40\x85\x79\xc2\xba\x29\x21\xf2\xf8\xd1\x14\x87\xaa\x7e\x52\x55\x7f\xee\xd9\x67\x57\x19\x9d\x3a\xae\x63\x77\x77\x01\x54\xb1\x7f\x35\x77\xc7\xac\x3d\x8c\x76\xcf\x74\x61\xb5\xe8\xd4\x2a\x71\x85\x07\x8e\xd4\xf8\x62\xfc\x57\x50\x2f\x61\x50\x75\x30\x7b\x6e\x10\x3c\x77\xc1\xf6\xc8\xbd\xa7\xaa\x17\xe4\x35\xe2\x1b\x94\x9a\xf4\x4d\xff\x5a\xa3\x0a\x62\xda\x71\x2f\xa9\x96\x6a\x61\x2f\xfc\xa1\x48\x71\xfd\x6f\x86\x0b\x4a\x96\x14\x01\x2c\x53\x69\x91\x0e\x0f\xfd\x6f\x0f\xbd\x88\x9a\x9c\x25\x7c\x32\xbd\xcf\x90\xbb\x80\x62\x7c\xb2\x72\xec\xd4\x59\x98\x97\x55\x59\x55\xe1\xfe\x08\xcd\x7e\xbb\x21\xc0\x71\xbe\x0f\x48\x98\x96\x96\xcb\x39\xaa\x82\xad\x11\xba\xa5\xd4\xac\x61\x3a\xbf\x1b\x6d\xb8\xa2\x0e\x68\x68\x36\x22\x28\x33\xf8\xb6\xdd\x2f\x00\x06\x22\x7b\xe4\x8e\x85\x80\xdc\xc8\xde\x62\x0d\xac\xb2\xf6\x5a\x69\x36\x75\xd6\xcb\x45\xba\x5d\xd1\xaa\x70\xdb\x76\xbc\x64\x1d\x4f\xb5\x67\xec\xbc\x71\x11\x44\x2e\x29\x41\x58\xbe\x57\x5c\x71\xdd\xc2\x6e\x94\xf4\x12\x66\xa2\xfd\x3a\x0d\x43\x57\x81\xfc\x09\x46\x48\xfa\xdf\x5f\x17\xcd\x41\xab\x89\x58\x21\x89\x4e\xc0\x80\x6b\x26\x2c\x39\x35\x34\xfe\x66\xf2\x1e\x37\x83\xc1\x4a\x96\xc8\x8f\x2e\x06\x53\xfe\x32\xe7\x5d\xce\x8a\x46\x3b\xb9\x7e\xed\x6c\x16\xf3\xf3\x22\x81\x69\xab\xb5\xb4\xbf\x9e\xa3\x27\x8c\x1f\xf0\xf8\x6e\xae\x71\x38\x9b\x64\x33\xac\xd0\x97\xee\xfa\x9e\x6e\x05\xf4\x95\x5c\xd5\x17\x83\x0b\x8d\x98\x70\xcc\xb5\x22\x74\x15\xe5\x0f\x23\xf6\x47\x32\x17\xa7\x45\x09\x64\x70\xdc\xa9\x3d\x2b\x34\x67\x3c\x5d\x6a\x57\xed\x02\xc8\xe0\xca\xe1\x19\xb3\xf3\x29\xd8\xab\x64\x98\x49\x4c\x29\x21\xbb\x6f\x49\x6d\xd0\x83\x81\xe7\xd3\x9f\x2d\xb5\x76\x3b\x14\xa2\x82\x1b\xef\xcc\xa0\xa9\xfd\x31\x25\x45\xde\x68\xab\xf2\x06\xd1\x2d\x8e\x02\xe7\x3b\xc7\xe3\xcb\x79\x6e\x7e\xe2\x6c\xc6\x3d\x74\x1e\xfa\xfc\x53\x45\xf8\x13\x29\x51\xbc\xfb\xfd\xdf\x63\x1f\xb7\xcb\x43\xef\x35\xb9\x45\x3c\x93\x90\xeb\x23\xb1\xf9\xd8\xb1\xc7\x2d\xeb\xd2\x4f\x09\xa0\x1a\x9d\xc6\x0e\xe6\x81\x53\x06\x18\x83\x57\x78\x1a\xf6\xe1\x82\x0a\xa3\x5e\x4e\xc1\x21\xb7\xca\x34\xd7\xde\x76\x11\xb2\x46\xa3\xe7\x03\xed\x48\xc7\xeb\x03\xa6\xfe\x8f\x85\x2e\xe7\xd3\x25\x45\xc9\xd8\x52\xd6\x4d\x5d\x75\x93\x0e\x5f\x1e\xbe\x21\xa3\x07\xef\xa7\x62\x2e\xda\xce\xd6\xd8\x79\x02\x6f\x0f\x85\xa9\x11\x20\x12\x80\x37\x05\x58\x22\x69\xd3\x9f\x14\x32\x34\xdf\x89\x09\xab\x3d\x94\x8e\x76\xd3\xda\xaa\x24\x22\x6d\x9a\xc6\x01\xee\xf2\x77\xfd\x2c\xfc\x4a\x19\xae\xdf\x43\x87\xa2\x16\x17\xb0\x3e\xc3\xd3\x84\x5a\x38\x55\x4f\x5e\x97\x03\x6e\x56\xec\x1c\xe6\x60\xdf\x9c\x06\x2c\x2c\x99\x3b\x77\xc5\xba\x6a\x6d\x05\x23\x1d\xae\x37\x64\x18\x3c\x3e\x96\xaa\x53\x9c\xfb\x34\x15\xfb\x16\x3c\x64\x5b\x23\x03\xb2\xd6\xd4\xbd\xa8\xca\x6c\x72\xbc\x03\xd5\x30\x5f\x9b\x11\x8e\x92\x5e\x27\xd2\x9a\xb7\xdc\xb1\x96\x47\x0e\x63\x39\x63\x1b\x23\x80\x74\x4c\x04\xd1\xda\x34\x8f\xc0\xfe\x27\x42\x77\xf8\x2f\x95\xbd\xfb\x0b\x64\xb4\xcf\x3b\x51\xe5\x71\xc0\xdd\xb3\xb5\x3c\xa6"}, -{{0x7e,0xe4,0xe7,0xe9,0x8c,0x6a,0x40,0xf0,0xe7,0x44,0x13,0xf2,0x40,0x39,0xbd,0x22,0x0d,0xf1,0xf8,0xc7,0xf0,0x15,0x52,0x8d,0xbf,0x52,0x84,0xab,0x9f,0x7c,0x82,0xe2,},{0x4d,0x5a,0x80,0x0f,0x9b,0x22,0x07,0x0e,0x01,0x6e,0xe2,0x3a,0xf8,0xa3,0x10,0x90,0x2b,0x36,0x9d,0x58,0x9a,0x84,0x7f,0x34,0x5c,0x2e,0xa2,0x96,0x8d,0x6d,0x09,0x24,},{0xac,0x3b,0xfe,0x3a,0xdf,0x94,0x1c,0x93,0x4d,0x33,0x49,0xc4,0x92,0xde,0x70,0xd5,0x16,0x6b,0xe3,0x89,0xf9,0x55,0xbe,0x87,0xc2,0x88,0x3f,0x41,0xf2,0xda,0x14,0x6c,0x91,0x06,0x51,0xa3,0xb4,0x52,0xc2,0xd7,0x39,0xdc,0x9b,0x53,0x1c,0x57,0x45,0x56,0x5e,0x69,0xd9,0x83,0x59,0xf1,0xd7,0xd9,0x3e,0xbd,0x36,0xd7,0x0a,0xbb,0xf0,0x0d,},"\x8f\xb0\x13\x73\xc4\x2e\x69\x61\x4a\xea\x99\xaf\x49\x32\x37\x85\xf3\x38\x61\xb9\x4e\x90\xf5\x65\x38\x9e\xbf\x70\xe2\x19\xf5\xde\xc7\x32\xe0\x01\x0b\x58\xf7\x29\x05\x30\xdf\x22\x2a\xc9\xc7\x3e\x1c\x2e\x92\xa5\xe6\x06\x1d\xe5\x59\x0c\xaf\x9c\x0d\x50\x21\xd7\x29\xea\xa1\x15\x41\xfa\x1d\x08\x21\x60\xbe\xaf\x61\x1e\x7c\xfd\xc0\xeb\xb3\x15\xd3\x88\xe5\x38\xb4\xb5\x02\x8f\x9b\x30\xd3\xd9\x73\x34\x7f\xfd\x44\x26\x3e\xef\x08\x3b\x81\xb2\x1b\x82\xec\xa5\x75\x6a\x49\x4b\x1d\x81\xc0\x7d\xe8\x49\x50\x6d\x3e\x3b\x66\x87\x97\xa5\xc5\x44\x25\x4d\x4e\xbe\x5c\xf8\x17\x1b\x39\xf8\x72\x4c\xbc\x41\x89\x29\x1b\x3c\x53\xc2\x1e\xce\x49\xa1\xd7\x39\x56\x3c\x65\xb4\x90\x25\x93\x56\x47\xa7\x30\x3a\xe0\xef\x7f\x6d\x24\x55\x46\x45\xa4\x28\xdb\xbb\x42\x44\x9f\x53\x99\xe3\x6d\xc7\x87\xb7\xd6\x95\x8a\x02\xee\xbb\xb8\x36\xe5\xe5\x3e\x26\xe4\x87\x23\x9d\xe9\x4d\x1d\x25\x0e\x79\x43\xac\x0e\x22\xd9\x27\x50\xa0\xcf\x34\x73\xbe\x1a\x62\x25\xcb\xe7\x95\x45\x04\x82\x69\xf6\x23\x7e\xc9\xf9\xec\x30\x7e\x8a\x34\xb7\xbb\x34\xcd\x49\x06\xe4\x31\x62\xa3\x70\x8f\x32\x9c\x5b\x98\x9d\x7a\x7f\xcd\xe1\x09\x9a\x54\x25\x46\xfe\x9c\x33\x18\x2b\xa5\x1b\x84\x3e\x96\xd1\x1c\x79\xe9\x1a\xd2\x1f\x71\x70\xe2\x57\xfd\xc2\x81\x8e\x12\xf9\x16\x8a\x97\x4c\x96\x8a\x4d\x27\x3f\xa3\xff\xa9\xf3\x5f\xf9\x05\x98\x0e\xaa\xd3\x72\x1c\xae\x80\x2b\xee\x36\x21\x0b\x40\xb9\x93\x19\xbb\x66\x99\x82\xe9\x43\xb2\x70\xa4\xc4\xd0\xa9\x2e\xcb\x5b\xba\x2d\xd8\xb4\x0a\xc3\xd2\xf0\x32\x5c\x46\x9d\x5e\x9d\x48\x3f\x52\x41\x97\x40\x10\xc5\xc0\xda\x33\x5f\x16\xe9\x62\x19\x6c\x2e\xf1\x4e\xb2\x4a\xaf\xbb\x31\x1b\xfd\x5f\xa8\xdc\x8d\x2d\x61\xe6\x87\x8a\xd2\xcc\xe0\xdc\x99\x39\xe4\x45\x22\x72\x3d\x42\x7e\xf3\x2f\xb4\x3b\x96\x7f\x5e\x44\xfc\x66\x57\x92\x79\x6f\x8c\xf9\x34\xf0\x1c\x32\x5d\x63\xd5\x83\xdc\x3c\xa9\xd4\xfc\xc7\x57\xd9\x17\x85\x80\xda\xef\x53\xaa\x3a\xb2\x1d\x2c\xe4\x35\x95\x5d\x1c\x6d\x47\x63\x8c\x5e\xdb\x62\xff\x55\x61\x69\x3d\x1c\xbd\x10\xec\x9e\x39\x9a\x71\xbf\x9d\xb1\xc9\x96\x9f\xd5\x9e\x4e\xeb\x31\xaa\x59\xbf\x39\xe9\xf1\x84\x17\x8d\xef\x72\x46\xed\x4b\x8f\x4b\xe5\xba\xda\xa5\xdb\x4a\xf8\x67\xf4\xf2\xec\x39\xa1\x37\x04\x20\x2c\x87\x84\xfa\x16\x8c\xe9\x6f\x9c\xfa\xc7\x10\x17\x23\x62\x75\xfd\x85\x7c\xc3\xc5\x1a\x9c\x7a\xc2\x56\x21\x5e\x14\xb8\x43\xf7\x21\x4d\xc9\xf8\x24\xb9\x1d\x1a\x51\x70\xd0\xef\x1d\x37\x69\x6f\x93\xee\x96\x6a\x2b\x7d\xec\xe2\x2b\x4f\x3a\xfd\x39\xc1\x6d\x60\x1e\x5f\xf8\x40\x8d\x45\xc1\xa6\xce\x71\xf0\x60\x97\x6c\x5b\xe4\xc0\x42\xb1\xb7\x38\xdf\x95\x80\xba\x5a\xe7\x78\x80\xa7\x0c\x0b\x94\xf0\xe1\xc9\xf9\xaa\x34\xc0\x90\xd6\x12\xd5\x7a\x9b\x93\x1f\x50\xa1\x25\xfa\x35\xce\x40\xa2\xcb\x7f\xaa\xd5\x30\xf8\x09\x08\xc7\x3c\xb7\x82\x58\xaf\xd2\x63\x13\x90\x04\x1d\x92\x61\x7e\x9b\xf6\x4c\xe9\x6e\x8e\x4a\xc7\xf3\x12\x6d\x8a\xf8\xa0\x4c\x75\xff\xd4\x38\x76\x9d\xe0\x6f\x74\xc2\xfc\x20\xcc\x81\x92\xda\x35\x3e\x79\x06\x12\x83\xbb\xa0\x8a\x8d\x24\xe6\xe4\xe2\xe8\x3b\xa5\xb0\x8e\x42\x75\x22\x60\x62\x14\x8d\x8a\x02\xaf\xad\x65\xb6\xf6\x27\xcf\xbd\x29\xb7\x1c\xa1\x8a\xee\x5b\x1f\x97\x16\x9b\xf0\x22\x8b\x37\x6f\x41\x06\xb5\x0f\xd9\x1a\x38\xa6\x62\x11\xd6\x9e\xbb\x4a\x7a\xf0\xe1\xc2\x21\x7f\x1b\xa0\x14\xd1\xe0\xcd\x17\x50\x8d\x58\x15\x5d\x16\x3d\xd9\xde\x2f\xe1\xc6\x4c\x7f\x88\xd5\xb5\x53\xe9\xba\x1e\x1f\x25\x43\x0d\x7e\x12\x5b\x07\xa8\xc2\xed"}, -{{0x1f,0x28,0xd9,0x09,0x1d,0x19,0x6c,0xba,0x3d,0x45,0x52,0xe5,0xa3,0x37,0xa4,0xd8,0xaf,0x3f,0x29,0x5e,0x62,0x9e,0x4b,0xa6,0xfe,0x99,0x70,0x31,0x20,0xae,0x41,0xe0,},{0x81,0x4d,0x34,0xbf,0x28,0xee,0x6d,0x90,0xf0,0x39,0x59,0x90,0x41,0xdb,0x81,0x0f,0x7c,0x9d,0xaa,0x91,0x8e,0x03,0xe9,0x61,0x97,0x41,0x4b,0xc9,0xaa,0x31,0xec,0xdc,},{0x5b,0xe5,0x52,0xfa,0x73,0x1e,0x83,0x67,0x93,0xf6,0xdd,0xa8,0x95,0xdc,0x9b,0x1e,0x2c,0xcd,0x66,0x9d,0xe1,0xc8,0x43,0xe0,0x0e,0xa6,0xfa,0x3c,0x5e,0xbf,0x97,0xa3,0x4b,0x26,0xf1,0xf3,0xac,0x7f,0xf2,0x22,0x5e,0xe4,0xa7,0xe4,0x30,0x07,0x2c,0x13,0xda,0x40,0x66,0xdc,0xdc,0xc0,0x5b,0xa2,0xb5,0xf6,0x1a,0x6e,0x8d,0x21,0x07,0x09,},"\xa6\x94\x68\xbc\x33\xeb\xfe\xf0\x61\x5c\x64\x3c\x49\xda\xc6\xe0\x4f\xdb\x6c\xfb\x8e\xc4\x58\x57\xbb\xb7\xa2\x7e\x52\x8f\xd6\x31\xfc\x34\x11\xba\xee\x65\xcc\x1f\x94\xfc\xc9\x4a\xed\x4a\x43\x32\xfa\x68\x61\xe0\x65\xe0\x61\x63\x54\x17\x09\xd7\x97\x28\xe0\x1b\xe2\xb1\x40\xa0\x22\xc8\x3e\x7b\x23\xb9\xed\x2a\xd2\x83\x21\x69\xdf\xc9\x56\x90\x91\x3c\xf3\x72\x01\x30\x65\x70\x80\xc9\xd5\xa7\x82\x7e\x56\x60\x75\x74\x52\xc5\xfc\x3d\xcd\x80\xcc\x6b\xe0\x98\xc6\x29\x22\x6d\x54\x66\xe0\x2b\x97\x12\x6b\xe7\x4a\x14\x52\xee\x16\x81\x50\x95\xde\xb4\x2b\xf0\x65\x66\x71\x50\x28\xc1\x18\x25\x82\x0a\x8a\x23\xc6\x0d\xa2\xb6\x8d\xd9\xa5\x5d\xad\x2a\x29\xa4\x96\x44\x43\x81\x7c\x07\xd7\x76\xb2\x44\xb1\x51\x86\x81\x9a\x3b\xbe\xd4\x14\xab\xf4\x57\x9a\x3e\xce\x3a\x3d\xc7\xb1\x05\xd0\xa9\xdb\xa3\x7b\x9e\xaa\x78\xbe\x8e\x46\xe1\x69\x8b\x59\xb0\x94\x0b\x01\xf3\x8b\x28\x3c\x33\xa9\xa4\xb1\xd4\xf8\x14\x4b\x16\xee\xb5\xfc\x0a\x7a\xf0\xd0\x81\x69\x66\x45\xa1\xea\xb3\xa7\x87\xcb\xcf\x88\xfa\xd9\x3d\xd6\xcd\x46\xd2\x95\xa8\x79\xa1\x77\x50\x33\xa9\x85\x63\x82\x2e\xf1\xf6\xb6\x9a\x58\x1e\x49\x73\x6c\x8d\x70\x1b\x44\x53\x96\x93\x40\x52\x1e\x4a\xd4\xbf\x94\xb9\x11\xb0\xe2\xd8\x6f\x34\xee\xce\x4a\x63\x85\xff\x1f\xe6\x32\x20\xcd\x3c\xc5\x92\xf3\x6d\x6c\x49\x1f\xa1\x8f\x7c\x14\x04\x36\x0d\x2a\x77\x53\xfe\x07\x3e\x09\xa2\xfc\x42\xa4\xbb\xea\x55\xbc\x96\xd7\xf0\x5c\x98\xae\xd2\xcc\x4a\x9f\xae\x8f\xd4\xa0\x19\x7f\xf0\x1f\xa7\xf0\x04\x6e\x3c\x3e\xb5\x9a\xaa\xbc\xa3\x13\xa4\xdd\xaa\x5d\x20\xd2\x7c\x2c\x5f\x1a\xc6\xd8\x7f\xd3\xcb\x4b\xd3\x5a\x1e\xc7\x5d\x10\x4f\x7c\x36\x73\x31\xa3\xe2\x95\xe5\x3c\x4e\x80\xba\xe1\x4b\x97\x92\xd0\xd5\x26\xf7\x40\xd4\xff\x03\x6f\xaf\x54\x87\x96\x7f\xfa\xbe\x8e\x88\x3d\x3f\xb0\xd1\x6f\xaa\xdb\x28\xe1\x28\x5d\xed\x41\x57\x0c\x0b\x07\xc2\x55\x9b\x53\x1e\x0f\x92\x54\xef\x88\xe5\xb1\x0f\x64\xf4\x83\x9a\x9a\x0b\x6c\x3c\x7f\x1b\x78\x50\xf4\xad\x9b\xf0\x99\x9a\x7f\x2a\xe7\xc4\x5a\x65\x8e\xa5\x30\x36\xfc\x70\x19\x98\x42\xb8\xe4\x9e\x60\xf9\x67\xde\x1f\xf3\xab\xff\xf6\xcd\x73\x5b\x7c\xd8\xb8\xf9\xe2\x48\xf1\x56\xf6\xc6\x54\x38\x69\xeb\x99\x82\x3d\xae\xa8\x8d\xeb\xaf\x79\xf0\x1e\x65\x21\xec\x63\xfe\x72\x72\x4e\xe3\xc8\x22\xb8\x8b\x39\x68\xb2\x48\x52\x09\x15\x83\xc4\x9a\xb3\xc1\x5f\xa1\xf7\x9b\x18\xd9\x8f\x04\xd9\xb6\x84\x1c\x9a\x7c\xa0\xde\x2f\xcc\x02\xf9\x5d\xd6\x49\x49\x2e\x8b\x56\xa3\x1e\xc1\xe2\x44\x33\x7a\xf6\xaa\xae\xde\x8b\xf9\x9f\xc8\x14\xef\x57\xc0\xd5\xe0\x8c\x3c\x7e\xcc\x18\x97\x98\x0a\xa1\x69\xa9\x92\x6d\x20\x69\x8d\xf6\x93\x0e\x21\x10\xcb\x46\x0f\x49\x39\x01\x00\x74\x10\x95\xf8\xed\x00\x41\x2a\xe6\x96\xd9\x8e\xfe\xfd\x29\x0d\xa5\xf7\xd0\xb7\x28\xd2\x0a\x1e\xbf\xa6\xbd\x7d\x27\x0f\x28\x1a\x98\xc7\xb1\xe4\x08\x43\x51\x25\xaa\x48\x3c\x6b\x7d\x63\x3f\xf7\x58\x8a\x94\x16\x58\xf6\x12\x95\x44\xd6\x29\x45\xb9\xb8\xaf\x71\xa8\xc6\x2c\x0a\x50\x07\x6c\xb8\x54\x1b\xa7\xe4\xbd\xe4\xed\xe4\x41\x72\x2c\x6e\xb9\xdf\x8c\xfd\x06\x56\x33\x9e\x86\xd2\x26\xab\xae\xa0\x5e\xa0\x47\xf6\xb8\x30\x77\x01\xf6\xc9\xa4\x4c\xc9\xcb\x83\x7b\x8e\xb6\x24\x45\x92\x5e\x8a\x88\x81\xd2\x53\x8f\xcb\x2b\x24\x9e\x4e\xe8\xb6\x86\xec\xfb\x49\xc4\xdf\x86\x40\x1d\x24\x9a\xac\x35\x84\x1e\x91\x40\x04\xf9\x45\x5d\x3f\xde\x37\x5d\x20\xa0\x1f\xba\x27\xb1\x97\xa6\x98\xd3\x84\xc7\x65\x05\x10\x68\x01\x62\x7e\x83\x36\xbd\x2d\x76\xd7\x61\xa8"}, -{{0xc6,0x4d,0xd2,0x0d,0x42,0x62,0x75,0x26,0x19,0x8a,0x22,0x64,0x76,0x90,0xc8,0x95,0xb5,0xb4,0x5b,0x69,0x8f,0x57,0xa6,0x9d,0xfb,0xe4,0x8d,0xbd,0x42,0x6a,0xa4,0x70,},{0x2e,0x01,0xd4,0x04,0x16,0xf7,0x8a,0xcd,0xdb,0x34,0xb8,0x44,0x5e,0xa4,0xfd,0x0a,0xb3,0xfa,0x9e,0x66,0x43,0x04,0x47,0x52,0x21,0x3f,0x07,0xc7,0xf0,0xff,0x43,0xa0,},{0xde,0xac,0xc8,0xc2,0x32,0x18,0x72,0x76,0x76,0xd5,0x40,0xa2,0x3b,0xda,0xd7,0x81,0x02,0x11,0xe6,0xd5,0x7a,0xd2,0x94,0xc3,0x7d,0x4b,0x1c,0x9a,0xf6,0xb3,0x37,0xa5,0x3f,0x78,0x80,0xd2,0xba,0xfa,0x73,0xb3,0x05,0x08,0xc0,0x08,0x42,0x6b,0xf8,0xd7,0xc9,0x65,0xa1,0xf4,0xa4,0x22,0xa1,0xbc,0x7d,0x6a,0xd6,0x22,0x6f,0xd1,0x97,0x06,},"\x82\x1b\x9f\x7c\x16\x10\x4b\x53\x3b\xd1\x27\x18\x4f\xd7\x2a\xde\x09\x2b\x13\xbb\xd9\xac\xee\xd2\x9b\x8d\x10\xf1\x66\x88\x92\x2d\x16\x5f\x89\x31\xd5\x3d\xf5\x90\xfb\x71\x3b\x67\x4d\x80\x5c\xe0\xc9\xd6\xce\x6c\x43\xba\x69\x68\x19\x1d\x12\xbf\xa0\x8a\x8c\xe2\x2e\x8f\x33\x6b\x2b\x49\x1a\xf2\x5d\x1b\x16\x06\xf9\x30\xca\xeb\xe5\x22\x39\x2a\x87\xd4\x2c\xe7\xbc\x16\x7a\xa7\xb6\x10\x59\x72\x20\xaf\x31\xa6\x65\x35\x30\x71\xe8\xd9\xe5\xf4\x20\x78\xb9\xc3\x88\xbf\x04\x02\x58\xe2\x1f\x9c\x3a\xb3\x8c\x04\x27\x61\x8b\x2c\x28\xd3\x43\x0d\xf2\x79\x21\xbf\xc5\x84\x87\xb3\x46\x19\x78\xbf\xa8\xbf\x58\x6c\xfe\x83\x58\xe0\x92\xf8\xf4\x74\x66\xe7\x62\x45\x1d\x50\x16\x4a\x0d\x74\x36\x0f\x66\xb4\xcd\x3a\x35\x75\xda\x01\xda\x23\x75\x24\x30\xc0\x35\xda\x85\x9f\x57\x7d\xe2\x22\x90\xaa\xb4\xed\x7f\x34\xd2\x67\x40\x6a\xb5\x47\xeb\x44\x5c\xc6\x4d\xf5\x30\x19\x42\x7f\x4e\xb7\x2b\xca\x55\x39\x71\x53\xd0\x1c\xcf\x7e\xc9\x7d\x7a\x96\x7d\x9a\xff\x46\x23\x1d\x2e\x20\x27\xb3\x8f\x3b\x41\xbd\x2c\xb1\xb7\x98\xa4\xae\x88\xab\xf4\x89\x62\x16\xd3\x15\xbd\x53\x83\x02\x42\x59\xe5\x97\x42\x80\x2a\x91\x1b\xad\xcf\x84\x73\xdb\x91\xaf\x31\x97\x33\x32\x0c\xb9\x52\x1e\xf9\xce\x43\x72\x67\xb6\xea\x17\xbc\xaf\xe5\xd0\x90\x3b\x12\x3a\x35\xc9\x88\xf4\x98\x34\xf6\x1d\xd5\x52\x64\x0a\x32\x76\xda\x26\xaf\x17\xec\x21\xa2\x02\x96\x58\x6d\xd6\xf4\xb3\x6c\x7a\x4f\x0b\x89\x9d\x70\xb4\x2a\xf8\x9e\x29\x37\x01\x32\xed\xfb\x72\xd6\x83\x41\x94\xa1\x60\x93\x60\xb1\xf1\xfe\xab\x89\xb9\x6b\x8e\x8f\x0f\x68\x98\x7c\x57\xcc\xe0\xba\xb7\x68\x11\x37\x18\xfb\x17\x09\xde\x2d\xf3\x21\x77\xd4\x40\x85\xda\x5e\xfd\x9d\xa7\x0e\x1a\x85\x8c\x92\xf2\x45\xac\xfe\xe6\x4b\x71\xf3\xeb\x16\xe0\x4f\xc1\x39\x89\xe6\x93\x37\x99\x97\x01\xdd\x73\xab\xc2\x66\xc9\xfd\x4c\xff\x91\xa0\xfd\x04\xfb\xd8\xb1\x3b\x12\xe6\xf4\x50\x38\x57\x15\x84\x8e\x00\x7f\xa0\xd4\x63\x11\x9f\xd7\xde\x63\x25\xb6\x40\x04\x2b\x65\x42\x12\xe0\xdb\x8d\xa1\xad\xeb\xd2\xa7\x58\x9f\x77\xee\x4f\x75\x2d\x28\x2c\xa1\x11\x9c\x43\x1b\x17\xad\x0a\x02\x1e\xf2\xbf\x95\xe5\xac\x47\x04\xe6\x2d\x70\x39\xd0\xe6\x51\xe4\x56\xd6\x0e\x63\xba\xde\x40\x1c\xca\x77\xc9\xa8\x91\x63\x17\x4d\x50\x22\xd7\x45\xab\xdc\x76\xb9\xff\xe2\x54\x41\x55\x23\x5e\x30\x63\xe6\xe4\xae\xec\x44\xed\x5d\x8a\xb4\x08\xd9\x66\xfe\xc1\x20\x16\xc1\x30\x73\x0b\xbc\x55\x87\x32\x06\x5d\xa8\x00\xa7\x0c\xbf\xb0\xfc\xcc\xa4\x5d\x00\x28\xcb\xfd\x96\x32\xdd\xb2\xf0\xed\x12\xed\xae\x7b\x93\x0b\x10\x6c\x9d\x12\x85\xa4\xb8\x70\xde\x75\x07\x99\x9c\x74\x79\x3d\xd4\x97\x40\x87\x19\xc8\x98\xab\xe4\x9f\x7f\x33\xa3\x3e\x69\xb5\x0f\xa5\xaf\x94\x80\x06\x85\x66\xd1\xfd\xdf\x44\x82\xd7\x97\x04\xad\x8e\xf1\x1b\x88\xb4\x2c\xc6\x9f\xce\x8a\x55\x7b\x5b\xa5\x10\xe7\x08\xb9\x37\x51\x23\x03\x85\x68\x27\x0d\xe4\x07\x23\x2e\x95\x62\x1e\x2d\x04\x57\x0b\xec\x2c\x41\xec\xcf\xd8\x55\xb2\x1f\x0c\x9b\xba\xa2\x3b\x5c\x58\x15\xfc\x88\x8f\x7f\xbe\xd4\x82\xc3\x20\xff\xa1\xe0\x63\xe8\x7b\x55\xbc\x8f\x7e\xee\xa3\x74\x06\x3a\x9b\xe6\x5f\x7e\xd9\x22\x5b\xf6\xca\x34\xcf\xa3\x11\xb7\x9f\x3a\x25\x8c\x25\x2e\x63\x45\xed\x6a\xc8\x47\x48\xf4\x68\x07\xa5\x5d\x4b\xa4\x12\x66\x16\x9c\xd2\x62\xd4\xf7\x22\x79\xef\x0c\xaa\x77\xff\x44\x93\x35\x32\xbd\x13\x74\x75\x6c\x23\xec\x85\xf5\x5e\xfe\x9f\xc2\x33\x1f\x26\xf8\x81\x62\x9f\x80\xc2\x69\x2f\x7f\x53\xe4\xbc\x6f\x22\xef\xb4\x54\x57\xa2\x23\xf0\xd1\xc4"}, -{{0x0f,0x8e,0x9f,0x35,0x26,0xb4,0xfa,0xea,0x92,0x76,0xf2,0x2a,0x17,0x79,0xe6,0xf8,0x27,0x09,0x80,0x8f,0x6d,0x0c,0x61,0x2a,0xdf,0xe3,0x2a,0x6e,0x8a,0x06,0x10,0x05,},{0xd4,0x8c,0x3f,0x0f,0xde,0xf3,0x82,0xd1,0xd8,0x03,0x13,0xe8,0x46,0xfc,0xa9,0x5e,0x41,0x81,0x76,0xbb,0x5d,0xfa,0x9d,0x39,0x8c,0x1d,0x21,0x24,0x77,0x6f,0x69,0x0a,},{0x2f,0x59,0xa2,0x93,0x60,0x73,0x91,0x38,0x34,0xeb,0x15,0xa0,0xe0,0xbc,0xb9,0xaa,0x80,0x40,0x89,0x46,0x8f,0x24,0xdd,0x1b,0x2d,0x37,0xa1,0x93,0x4a,0xe9,0xba,0x10,0x20,0xff,0x64,0xb7,0x2e,0xec,0x03,0x26,0x8d,0x0a,0x7c,0x01,0x2c,0x4e,0x79,0x63,0x00,0xf6,0xdf,0x7a,0xdd,0xa0,0x1c,0x8b,0xc5,0xe9,0x01,0x5c,0xcd,0xee,0x1a,0x00,},"\x0c\xcd\x37\xc4\xcf\xd8\xe7\x0c\xa3\xbb\x39\x46\xd0\x9d\x70\xd0\xf6\xa4\xb8\x1d\x6d\xfb\x07\x9d\x78\x73\x74\x80\x71\x58\x98\x80\x92\x73\x82\xf7\x43\x6a\x6e\xf8\xf5\x1c\x25\x54\x73\xdd\x01\xfe\xb5\x2c\x8e\xdb\xe4\xd3\x25\x57\x13\xe6\x8d\x64\x0f\x3d\xcf\x15\x8f\x2b\xfb\x9f\xbe\xcf\x71\xf0\x71\x9d\xfe\x8c\xe6\xb6\x01\x28\x1b\xa6\xc2\x0a\x56\xb4\xf8\xe7\xca\xa4\xaa\x9f\x86\x8f\xbf\xc5\xe4\x32\x1c\x22\xd6\x5f\x03\x82\xc4\x89\x6b\xf9\xbe\xbe\x35\x46\x94\x9e\x81\x85\xa4\xd8\x17\xe4\x5b\x5d\x12\x93\x95\x38\x21\xbd\xd9\x8e\xc2\x59\xf6\x4a\x3d\xe5\x38\x65\xb1\x49\xea\x01\xc8\xf6\x83\xec\xda\x61\xda\x5d\xc1\x0e\x7e\xbd\xdd\xfe\x74\x84\xf5\xeb\x10\x31\xb7\x91\x65\x87\xca\xa3\x99\xa0\x6b\x6f\xea\x4c\x5e\x6e\x0b\xe6\x50\xfb\xdf\x06\xc1\x03\x6d\xf2\xcc\x35\xf6\x2e\xa0\xea\x71\x3f\x52\x80\x9d\x77\xf4\x7c\x2e\x55\xc9\x23\x92\x48\x16\x80\xb6\x33\x20\x56\x22\x69\x13\xb0\xce\x88\xa6\xc5\x5a\x26\xbd\xb5\xb8\xba\xb3\xcf\x46\x95\xa8\xc5\x22\x30\x2c\x4e\xba\x37\xd3\x1f\xf7\x7e\x58\x30\x1b\xcc\xfc\x7c\x7b\xe8\x58\x0c\x63\x42\x68\x79\x95\xf4\x4a\xcd\x19\x09\x65\xae\x0d\x7b\xf0\x66\x95\x92\xb6\xad\x88\x74\x3e\xbb\x36\x0c\x73\xe0\x48\x4a\x23\xd2\xf9\xe9\x9e\x9e\xb0\x38\xdc\xbd\x87\xca\x9b\x1a\x49\x8f\x1b\x2d\x35\xfe\xdd\x7f\x8e\x1f\x7f\xd8\xca\x52\x64\x86\x91\x1e\x07\x6a\xea\xb4\x87\x7b\xba\xcf\x37\x8a\x28\x55\xf9\xc5\xac\x03\x91\x30\xdc\x69\x0e\x17\x7d\x67\xb2\x44\xcc\x8a\xd0\x32\x37\x9e\xf7\x1f\xe0\x5e\x9c\x86\x13\xd8\xf5\xd6\xea\x3d\x4e\x3e\x47\x22\x20\x29\xcc\x00\x42\x53\xbe\x47\xf8\x7f\xb5\xe3\x31\x4c\x48\x98\x13\x4b\x87\xac\xf1\x0b\x25\x38\xba\xd8\x97\xbd\xc5\x01\x2d\x8f\x97\x62\xc8\x71\xb6\x53\xd4\x00\xfe\xe0\xce\xed\x5e\xf6\xbd\xd1\x6f\xaf\x3f\x0a\xbd\xbd\x72\xcd\x0a\x12\x94\x05\x46\xf0\x99\x5f\xf1\x4b\x0f\x1b\xd5\x48\x56\xff\x74\xc3\x6e\xb4\xf2\x2d\x72\x87\xae\xfd\xc6\x09\x99\x8c\x1f\x41\xbc\xc3\xbb\x3a\x5f\xa4\x92\x34\xf4\xfa\x8e\x92\x9c\xd0\xf5\x54\xb3\x15\x39\x5d\xae\x87\x3c\x61\xca\x70\xe0\x41\x0c\x2f\xd5\xa1\x15\xd2\xa6\xff\x1f\x1c\x94\xb2\x7b\xa4\x50\xb8\x19\x4b\x21\xf0\x95\xc6\x1a\x5f\x21\x5e\x3c\x84\xf5\xd4\x3f\x0e\x73\x62\x86\xd3\x3b\x8c\x47\x81\x4d\xb9\x79\xf9\xdc\x00\x91\x98\x46\xbe\xe6\x85\x33\x7d\x99\x55\x5a\x24\x47\x2e\x6b\x00\xb3\xf4\xa1\x43\x11\xa6\xc7\xc9\x04\xba\x58\x89\xda\x6c\x1d\xdc\xc1\x11\x75\x80\xf5\xfb\xc4\x1f\x2b\x8a\x42\x68\xcf\x0e\x9f\xa5\xbf\x41\x25\x34\xc9\xe4\x05\x2a\xac\xb5\x04\xcb\x86\xe2\x14\x7a\xb8\x02\x3d\x58\x80\x0b\x76\x3f\x9a\xbf\x9d\x04\x40\x78\x8a\x51\xdf\xe5\xcb\xd4\x42\x30\xba\x52\x28\xf1\xf5\x96\x0e\xa3\xa4\xe4\x04\x4d\x36\xda\xf8\x11\xcb\xdb\xec\x5d\x69\x64\x63\xd8\xe9\x41\xf2\x72\x17\x56\x3b\xb4\x4a\x21\x18\xa4\xf5\xac\xd6\xe7\x94\xde\x17\xe0\x28\xcb\xde\xef\xde\xf2\xcb\xf0\x3d\xd3\x2e\x78\x99\xe6\x5a\x1c\xf8\x39\xf5\xd9\x0e\x1f\x8c\x36\x4b\x57\x7f\xe3\x10\x53\x53\xf6\x67\x68\xdb\xf7\xaf\x0c\x52\x1a\xa8\xa4\x9f\x7a\x22\x08\x2d\x88\xf9\x01\x49\x8c\x90\xb9\xd7\x77\x7e\xd2\xf9\xf0\xe8\xa5\x52\xd8\xa1\xfa\x5e\x96\x32\xed\x85\x32\x58\xc9\xc2\x15\xb6\xdb\xb4\x11\x1d\xcf\xca\x55\x4b\xfb\xc9\xbb\xa2\x2f\x88\xbc\x55\x55\x2c\x6d\x86\x25\x56\xd7\x41\xda\xd5\x9f\x21\x5e\x37\x28\x83\x46\xca\x7d\x7f\xd8\xc6\x5a\x38\x0d\x72\x0c\xaf\xf9\xef\xa1\x49\xf3\xfd\xa2\x32\xda\xa5\xb1\x2e\xf1\x1c\x0a\xf0\x86\x2b\xd0\x22\x9e\x07\x5a\x3c\x6b\x60\xef\x0b\xbb\x3d\xad\x7f\x29\x08"}, -{{0xfe,0x7c,0xdc,0x79,0x66,0xd0,0xff,0xb9,0xc7,0x6f,0x4a,0x18,0xe7,0xf0,0xbf,0x90,0x69,0x0e,0xb7,0x6d,0xc3,0xd3,0xd5,0x08,0x84,0x64,0x8e,0x2e,0x39,0x37,0xd0,0x20,},{0xa1,0x2e,0xe9,0x81,0x2d,0x6a,0xf6,0xaa,0x48,0x79,0xfa,0x72,0xbc,0x0a,0x69,0x80,0x4e,0xa1,0xa8,0x5f,0x9b,0xc4,0xa2,0x6a,0x5b,0xa7,0xcf,0xbb,0x91,0x4d,0x0d,0xd9,},{0xb5,0x2d,0x03,0xfd,0xeb,0xcd,0x42,0x97,0x37,0xef,0x70,0x92,0x06,0x87,0x21,0x1f,0xbb,0x4c,0x04,0xf8,0x1e,0x35,0x5c,0xec,0x70,0x72,0xc5,0x05,0x41,0x75,0xd2,0xed,0x77,0xf3,0x8f,0x46,0x6f,0x00,0x14,0x22,0xda,0x8f,0xcd,0xf0,0x67,0xdb,0x14,0x51,0x00,0x7c,0xab,0x60,0x7f,0x04,0x9c,0x2e,0x26,0x07,0xb5,0x7d,0x44,0x71,0x3c,0x04,},"\xdc\xb9\x1c\xf1\x55\x46\x1a\x60\xdf\x07\xee\xc2\x9d\x98\x61\x6e\xd1\x72\x8b\x34\xef\xa9\xe1\xf7\x44\x5a\x91\x58\xa8\xf8\x8d\x7f\xaa\xae\x0e\x24\x72\x5a\xef\xf2\x63\xc3\xf7\x4f\x0c\x68\x4f\x18\x58\xf0\x5b\x69\x95\xd2\x84\x6b\x6a\x83\x2f\x67\x08\x5a\x42\x76\xd8\x66\x1a\xeb\xd3\xbf\xcc\x73\x18\x1f\x1f\x51\x02\x93\xb6\xde\x5e\x4b\xb2\x3f\xf2\xdc\xa1\xdf\x60\x8c\xb1\x4a\xe5\x22\xac\x4b\x51\xe1\xf9\xb9\x73\xab\x8b\xaf\xcd\x53\x4e\x71\xc5\x71\x81\xb1\x18\x96\xee\x10\x61\xfb\x36\x9c\xa4\xd2\x93\x9d\x1e\x57\x06\x0d\x9f\x4d\xb0\xa5\xc0\xb0\x7d\x52\x68\x7f\x15\x78\x17\xe6\x3e\x2f\xe7\xeb\xcc\x3e\x7c\x95\xef\xe0\x5b\x85\x99\x10\xc9\x5e\xed\xe8\x6d\x14\x39\x9e\x61\x62\x48\xa2\x8c\x24\xc4\x14\xdb\xb6\x93\xaf\x9b\xe4\x35\xa3\xa9\xcd\xc3\x3e\x0e\x2a\x58\x69\x18\xd9\x1b\x8a\x85\xce\xdd\x16\x12\xd7\xc1\xa2\x17\x92\xbd\xd4\x3a\x91\x5b\x15\x7e\x04\xbb\x3a\x44\xec\xbe\x23\xfa\x49\xcc\x55\xda\xab\xbe\xaa\x15\x5a\x73\x7f\x76\x5b\x8d\xdb\x0f\x3b\x15\xd4\xec\xf2\xce\xf7\x05\x4c\xa7\x3e\xc8\x7d\x91\x75\x2c\x2e\x99\x19\x5c\xdb\x19\x58\x84\x4f\x14\x4e\xda\xb8\x2a\x97\x54\x9f\xc9\xce\xc0\x8e\x87\x11\xcf\xf8\x63\xb6\x3f\xc2\x31\xa7\x7f\x76\x2e\x5c\xd9\xda\x9d\x59\x40\x92\x52\xe9\x9a\xb0\x4c\x42\xbc\x57\x09\x7e\x46\x4e\x3c\x6a\x48\xd8\x02\x41\xe6\x32\x5e\x3e\x40\x94\x98\x9b\x34\xc0\xe8\xb3\x2b\x1a\x78\x29\xd5\x4d\xf3\x2a\x05\x0e\xe8\x7d\x8f\x7c\x4f\xe3\xe4\xf4\xf7\x04\x9d\x1f\xee\xcd\xbe\xa6\x71\x08\x35\x0d\xb4\xe8\xed\xbe\x3c\x3f\xf8\xab\x2a\x25\xd1\x47\xb1\xc1\xc5\x82\x1b\x0f\x8c\x21\x04\x2d\x65\x5d\xb8\x31\x69\x1f\x59\x98\x3f\x27\xd2\xed\x1d\x49\x06\xc5\x44\xe2\x4e\x79\xbe\x68\x65\x3c\x9b\x22\x9a\x7f\xb6\x1e\xf5\x45\xba\xb1\x6e\x98\x81\xcb\x4d\x92\x65\xe2\x93\x59\x0a\x0b\xc2\xdc\x86\xba\xd2\x30\x07\xff\x40\xc9\x58\x61\x92\x3b\x49\x82\x41\xc1\x0d\x26\xbf\x48\x48\xf6\x2b\xa7\x38\x3f\x64\x9d\xc3\x8a\xf1\x84\x0d\x0d\xe9\x28\xa9\xbf\xee\x5e\x11\xb5\x14\x34\x16\x3a\x7a\xb1\xed\x53\x74\x15\xf1\xe9\x32\x85\xe3\x69\x92\x05\x72\x01\x58\xf9\x55\x7d\x86\x41\xed\x2b\xf4\x85\xb8\x21\x2c\x8f\x82\x66\x8b\xac\x3c\x22\x8e\x69\x24\xc1\x7d\x0d\x98\xf2\xe6\xd9\x23\x43\x71\xc4\x42\x5e\xb7\x58\x68\x9f\xdb\x0d\xc1\xce\xa1\x39\x4a\x28\x62\xe8\x7b\xb3\x8e\x62\x4c\x34\x79\x91\x68\x61\x32\x78\x22\x5f\xb5\xe1\x9c\x92\x47\xad\xa3\x55\x54\xf2\xc4\xad\xdb\xb6\x1d\x5a\x50\x2a\x70\x81\x27\xd6\xef\xbc\xa8\xf7\x35\x09\x0b\xdf\xdd\x88\xdb\x29\xfb\xd1\x4b\x69\xab\x12\x62\xf0\xc3\xe2\x6d\x26\x3a\x59\xc5\xae\x46\x39\x06\x53\x83\xd5\x25\x0b\x54\xcf\x59\x2b\xb7\xad\xfe\xaa\xe0\xd2\xfe\x81\x6b\x63\x81\xe8\x6e\xa2\xd1\xc7\x18\x13\xcb\xc3\xd8\xfe\x2d\x31\xde\x7b\x30\xfb\x6e\xc2\x29\x4f\xe4\x53\x6a\x36\xc6\xa1\x83\x5a\x71\x62\xab\x4b\xf8\x9d\x19\x46\x61\x19\x65\x7b\x0e\x46\x45\xae\xf5\x03\x50\x5b\x4d\x55\xdf\x97\x7b\xd2\xc9\x0c\x64\x40\x6f\x49\x70\xd5\xcf\xf2\x45\xb8\x35\x32\x2a\x6f\xbe\x23\x4e\x5e\xfb\xb5\xea\x45\xe8\xf0\xd3\x97\x3b\xe4\xaa\xa2\xaa\xda\xab\x07\x7d\x6c\x9b\x25\xbd\x44\x94\x40\x9e\x93\x47\x9d\x2d\x15\x07\xf6\x6b\xc8\xbe\xf8\x29\x99\xa1\x3c\x79\x43\xb4\x72\xb9\xe6\x1e\xc2\x9d\xeb\xef\xbf\x22\x41\x42\x3e\x0f\xaa\x42\xc1\xa3\x38\xa7\xa6\x13\x1d\xed\x93\x5b\xa0\x3a\x28\x66\x2e\x68\x59\x33\x68\xdd\xe5\x4b\x46\x2f\x2a\x5f\xb7\x46\x18\x5f\xf5\x50\x3e\x69\xba\x36\xbf\x16\xf7\x14\x58\xcd\xd0\x57\xe5\xc1\x72\x67\xf6\x74\x98\xd6\x52\x86\x0b\x46\x5e"}, -{{0xf6,0xc9,0xab,0x5e,0xa7,0x5f,0x29,0x4e,0x8e,0x0c,0x07,0xc4,0xc0,0x9e,0xd8,0xee,0xa3,0x11,0x3b,0xdf,0xc2,0xef,0x75,0x9e,0x20,0xa2,0x64,0x57,0x16,0x04,0x10,0x8d,},{0xb1,0x2f,0xf5,0x5b,0xd3,0xec,0x42,0x61,0x0e,0xac,0xea,0x28,0xb3,0x13,0xa1,0x6e,0x19,0xc9,0xe8,0xb4,0x7c,0x2b,0x15,0x17,0x09,0x91,0xbe,0x08,0x8d,0x65,0xcf,0x63,},{0xa7,0xf9,0xd0,0x8b,0xa1,0x41,0x83,0xef,0x24,0x7f,0x2c,0x25,0xfe,0xcc,0x2b,0x83,0xed,0xa6,0xde,0x58,0x02,0x2e,0x46,0x6c,0xe7,0x8f,0xcf,0x50,0xf7,0x1c,0xe2,0x61,0x62,0x44,0x65,0x62,0xee,0xa4,0x5d,0x63,0xa2,0x1c,0x3b,0x22,0x56,0x1f,0xd4,0x68,0x00,0x58,0xac,0xb8,0x25,0x40,0x7a,0x15,0x40,0x8f,0x27,0x13,0x61,0xa1,0x46,0x0f,},"\x71\x62\x3b\x39\x74\x3e\x39\xc7\xe0\x86\x38\x80\x6d\x46\x8a\x1a\x8a\x6f\x35\xc2\xae\x38\x8e\xef\xc2\x73\x74\xbb\x52\x53\x88\x14\xc4\xb3\x6c\x9b\x8e\x38\x9a\xd8\x31\x83\xde\x02\xa1\xbb\xd0\x32\x57\x34\xe4\x61\x87\x54\x09\x23\x37\xd3\xe7\xdc\x12\x56\x92\x8e\x35\x28\x87\x0c\xa7\xf0\x06\x13\xa2\x5b\x71\xbb\x15\xd1\xd9\xea\xaf\xf9\xf2\x26\x9b\x71\xc1\x97\x69\xe0\x03\xce\x84\x56\x14\xb2\xec\x95\xed\x28\xca\x85\x5b\x52\x21\xd4\xcb\x80\xa6\xca\x94\x66\xaa\x33\xe2\x51\x0d\xdf\xf7\xdc\xe1\x86\x15\x9d\xa7\x0f\xc8\xb1\xfb\xac\x12\xa2\x6e\x1f\xc0\x94\x22\x76\x89\x2a\xd6\xe9\xb0\x03\xf5\x69\x59\xbd\x31\x3a\xf2\x89\xe7\xa0\x53\x2a\x66\x4b\x76\xb9\x6b\x91\x98\x54\xe0\x65\x0c\xb8\xc5\x2e\xc4\xc5\xfb\x50\x53\xaf\x2f\x0c\xf8\xc0\xf2\x2a\x52\x3f\x9e\x2c\x64\x19\xdf\x8d\x0b\x71\x4e\xe3\x77\x68\x00\xeb\xfa\x70\x77\x60\x84\x66\x7d\x6d\xcf\x54\x1f\x14\xcf\x16\x62\x62\xe0\xf6\x4c\x42\x76\xae\x28\x88\x5e\x6c\xfd\x09\x7b\x70\xc0\xd6\x18\x6e\xa5\xdb\xd0\x33\x32\x3c\x98\x76\x13\xda\x08\x64\x5d\xe0\x72\x08\xba\xe1\x2a\x17\x8d\x8f\x7f\x65\x0a\x25\xaf\xbd\x70\x1c\x85\xa1\xba\x63\x9e\xf9\xf1\x21\xc4\x0c\x5c\x12\x9a\x47\x37\x34\x33\x86\xa4\x81\x83\xff\x3c\x59\x13\x89\xd8\x9e\xcd\xa5\x26\xcf\xfb\x26\x74\xf1\x7b\xb1\xc2\x30\x90\x55\x4b\x13\x40\x84\x97\x96\xa6\xd4\x44\x46\x0b\xb4\x19\x42\x7e\x93\xe6\x58\x5b\x0f\x4f\x06\x5a\xd8\x7e\xe6\xed\xf5\x4b\xe6\x18\x8a\x1d\xd5\xac\xe1\x36\x4d\xef\xa5\x61\xf7\x4e\x26\x76\x9c\x9b\x29\x1e\xe7\x55\x52\x76\x50\x1c\x6a\x49\x08\x0d\xa0\x92\x4f\x37\x92\xc2\xa7\x28\xa5\x20\x07\xb1\xc0\x7c\x95\x57\x8f\xed\xaf\x40\x39\x96\x23\x9e\x9c\x55\xa9\xa4\x4c\x3d\xfc\xc3\x7c\xdf\x03\xfb\x48\x5d\xb5\xa0\x8d\xff\x15\xa7\xa4\xf7\xb7\xf1\x54\x74\x2e\x84\x31\x56\x4d\xc1\x7d\xbd\x43\x2e\x10\x33\x7c\x22\x76\xfc\xfd\x9d\x70\xf7\xc3\xd5\x70\x39\x3a\x0c\x19\xf6\x40\x51\xc7\x3a\x87\x0e\x20\x55\x84\x10\x65\x31\xd1\xfd\x2a\x1d\xd1\xc9\xd0\xfc\xe1\x4f\xfa\xaa\x07\x7b\xb7\xe2\x60\x25\x1e\xed\x6c\x62\xbc\x6e\xdc\x24\x22\x51\x94\x40\xc2\x24\x4e\xba\x38\x40\x46\xb0\xed\xda\xa6\xcf\x2c\x1c\x7e\xee\xbf\xcd\x78\xfc\xae\x18\xb8\x22\x90\x55\x2b\x59\xc0\x46\x3d\xc4\x50\x61\x8b\xa6\x7c\x77\x0d\xec\x0e\x22\x9b\x84\x60\x93\x6c\xa8\x19\x56\x2b\xcb\x36\x96\x9c\x8f\xf7\x0b\xf1\x13\xc1\x16\x71\xe0\x0b\x94\x13\x55\xbf\x01\xad\x54\xb0\x5c\xfe\x2a\x04\x8b\x38\x72\x8c\xbd\xd1\xb4\x98\x09\xe1\xf2\x07\xac\xa3\x09\x8d\x99\x42\xee\xc4\x7d\x6c\x9d\x41\x3b\x37\xc9\x14\xfe\xdd\x38\xac\xd5\xff\xe4\x96\xca\xc7\x57\xc2\xef\x8b\x77\xbd\x84\x03\xd1\x4b\x1f\xc9\x8a\x90\x3f\xe2\xb9\x79\x46\x82\x33\xa7\xf2\xae\xd6\xf8\xd5\x09\xd8\x74\xe1\xdc\xe0\x51\x49\xaf\x9d\xf3\xfe\x45\x95\xc7\x1e\x8b\xc4\x63\xde\xe9\x38\x4d\x5e\x05\x05\xd2\xa6\xb0\xa2\xb8\xa1\xed\x62\x16\xaa\xae\x9d\xcc\x76\x02\x48\x7a\x4c\x08\x51\xfd\xf0\x96\x29\xc1\xe9\x91\x18\x80\x9a\x95\x44\xa6\x57\x7a\xf9\xf9\x15\xd1\xe6\x5d\x81\x62\x20\xc4\x8c\x84\x90\xfa\x9b\x70\xda\x42\x2a\xd6\x80\x02\x23\xd6\xd8\xc3\x40\xf9\xea\xb2\xcc\x7e\x14\x93\x62\x12\x4a\x30\x0b\x40\xcb\xb8\xc0\xa6\x5d\xa3\x01\xdb\xba\x93\x1b\xa5\x64\xf3\x59\x73\xca\x8b\xf2\xd1\xed\xb5\x6c\x19\x46\x61\x95\x5b\x3b\x68\x38\x1f\xa1\x5d\x4b\x8d\xc6\xad\xa1\xa5\xce\xbd\xa3\xa4\xcc\xc5\x51\x23\xe0\x05\x7f\x4f\x82\x10\x41\x93\x7d\xd5\x49\x20\x9c\x82\xe1\x16\x57\x0b\xc9\x08\xa2\x8e\x32\x99\xa9\x44\x14\x43\x49\x8f\x74\xb3\xcc\x88\xe1\xa6\x2d"}, -{{0x43,0x10,0x3d,0xf0,0x1a,0x48,0xa0,0x3c,0x57,0xf3,0x2f,0x52,0xd7,0x0c,0x68,0x49,0xee,0x44,0x58,0x0b,0x2a,0xb4,0xee,0x72,0xd5,0x48,0xd8,0x48,0x13,0x4f,0x7c,0xeb,},{0xa3,0xcb,0xe0,0xd6,0x4b,0x05,0x60,0xbc,0xb5,0xae,0x00,0x90,0x01,0xe3,0x14,0xd9,0xec,0x90,0x79,0x01,0xdd,0x74,0xa8,0x04,0xa0,0x05,0x90,0x22,0xed,0x9c,0x6d,0x04,},{0x19,0x54,0x47,0xbe,0xb1,0xde,0x4a,0x7e,0x36,0xea,0x89,0xa6,0xce,0x3c,0x99,0xbc,0xc8,0x94,0x11,0xdf,0x5e,0x0b,0x15,0xf7,0xba,0x0b,0x1d,0x11,0x0c,0x45,0x6a,0xbc,0x6b,0x3f,0x5f,0x1d,0xa6,0x10,0x6e,0xd8,0x87,0x86,0x4b,0xa5,0x6a,0xab,0x46,0x6a,0x8a,0x63,0xb3,0x35,0xcf,0xcf,0x4c,0x64,0xd6,0x5c,0x0e,0x6f,0xb4,0x80,0xb4,0x01,},"\x73\x8c\xbf\x06\xd0\x0d\x4d\xcd\x5e\x5f\x24\x3a\x1c\x18\xdd\x5e\xc2\x02\x78\x88\x46\x95\xa1\xcf\x3b\xea\x67\xbb\x5b\x05\xdd\x7e\x60\xa2\xa2\x4f\xd3\x25\xbe\x6b\xf4\x6b\x46\x28\x73\xec\x90\x7f\x9d\xe8\x8d\xc2\xc7\x62\x62\x0b\x7e\x0e\xf7\x27\x65\xd4\xbd\xa6\x62\x45\x49\x93\xc8\x28\xa1\x74\x6e\x9e\xd8\xd1\x9d\xff\x43\xc4\xc4\x85\x27\xac\x84\x5f\x21\x86\xa4\xad\x7c\x1d\x99\x2a\x16\x24\x5c\xd5\x73\x07\x3e\x09\x40\xdc\xee\xd3\x68\x11\x0b\xb5\xfd\x0a\x4c\x88\x34\xce\x88\xa7\x71\x25\xb9\x14\x73\x93\xc8\xb5\x8c\xb1\x6e\x5e\xbd\xc1\x82\x44\xeb\xfa\x48\xba\xba\x46\x97\x3f\xdc\xd4\x85\xb1\xb2\xe5\xf3\xb0\xe7\x09\x92\xcf\x19\x99\x58\x06\x38\xd8\x7f\x1f\x5b\x27\xc4\xd7\xf9\x1d\xec\xf3\x7d\xe2\xe7\x34\xe3\x19\x55\x35\xc6\x31\x08\x2b\x3e\xba\xa8\xce\x30\xa9\xc2\xc2\xdb\x01\x6d\x7d\x35\x47\xe6\x21\x61\x88\x50\xe2\x20\x40\x03\x8d\x0f\xe0\xfa\xea\x2f\x9b\xf5\x10\xb6\x82\xc4\xfd\x14\x75\x0e\x89\xb4\xc1\x99\xef\x0c\x99\x05\x00\x54\x3e\xee\xab\x5f\x0b\x50\x7a\x31\x31\x99\xc2\xa2\xa0\x26\x2d\x6d\x81\x4c\xbc\x09\x33\xc5\x92\xe2\x56\xc3\xe2\x9d\x52\x4b\x06\x6e\xa5\xa4\x54\x33\x61\xa1\x04\x50\xe0\xaa\x67\x5c\x61\x40\x8f\x30\x7f\x26\xee\x58\x96\x9d\x63\x27\x8f\x13\x5b\x7d\xcb\x66\x6b\x93\xf2\xca\xcf\xd8\x38\x73\x47\x1e\x97\x4a\x28\x6b\x09\x02\x3f\x50\x15\xfa\x1a\xaf\x18\xbf\xbf\xa5\xf7\x43\x85\xd0\xdf\x6b\x9a\xdd\x51\x6f\xfc\x0c\x31\x13\xe3\x7e\x09\x78\x38\x64\x6a\xc9\x30\x54\xff\x4d\x96\x02\x06\x67\x44\xba\x33\x96\x95\x3f\xd7\x81\x68\x13\x01\x70\xbb\x27\x5c\x15\x2b\xdd\x36\x6f\x73\x06\x5c\x0a\x7a\xd7\xad\x00\x75\x8c\xb9\x9a\x7a\xc1\xb7\x80\x9d\x26\xdf\xaa\xc7\x58\x46\x82\x01\xee\xb6\x0d\xea\x36\x8c\x33\xf2\x57\xaf\xe2\xf1\xb4\xc0\x2e\x37\xba\xfe\x40\xf5\xd7\xfd\x40\xc8\x7d\x1c\x56\xa0\xcb\x28\xe9\xd2\x83\x69\xa3\x92\x4b\xce\xf8\xb6\xd9\x99\xdc\xf4\x29\x4d\xd8\xc4\x14\x3d\x75\xc6\xc2\x5b\x5a\x45\x44\x48\x8d\xde\x72\x52\x48\xc7\x8d\x93\xc1\x5b\x81\x5b\x01\xcb\xd0\xf3\x1d\x1b\x00\xac\x04\x83\x7e\xf8\x5b\x40\x03\xfc\x96\xd4\x45\x7a\xc5\xa0\x23\x62\x3e\x67\xb6\x6d\xa4\x70\x0a\x08\x59\xf8\x3f\xdc\xcd\x3c\x7a\xae\x09\xde\x09\xa0\x57\xe0\x0d\xb4\x4a\x2a\x6a\xac\xaa\x21\x74\x6a\x49\xb8\x22\x46\x89\xa5\xcc\x18\x54\xba\x3d\xc4\xaa\x2a\xa3\x45\x24\xe7\xa5\xa8\x9d\x11\xee\xa3\x56\xaa\xea\x5e\xf5\xfb\xf5\x42\xc9\x9f\x54\x4d\xb9\x40\xf5\x08\x68\x38\xee\x2a\xb2\x18\xb8\xd3\xf2\xe1\x07\xd0\xb2\x9d\x4b\x04\x83\x0e\xed\x79\xc0\x76\x8e\x02\xc2\x84\x4b\x3c\xba\x32\x68\x95\xf4\xab\x38\xa3\x99\x4b\x83\xab\x30\x60\x0f\xf5\x11\xcc\xb5\x95\x99\x2f\x8c\xc0\xd2\x95\x48\x07\x97\x2d\xa3\x65\xb0\x6f\xbd\xab\x53\x9b\x2e\x03\x59\x8b\x34\xe5\x3c\xfc\xf9\x39\x90\xb9\x7a\xac\x1d\x32\x97\x83\x36\x6d\x45\x1f\x97\x2b\x8d\x8a\x00\xb6\xb8\xec\xdb\x37\x27\x96\x44\xce\xc1\x44\x7c\x09\x98\xee\x4f\x70\x90\xf3\x4c\x9c\xc8\x53\x05\x90\xca\xe7\x65\x36\x0a\xad\xb0\xab\x31\x35\x00\x49\x41\xc9\x23\x02\xcb\xb2\xb3\x50\xa1\x4e\x8f\x30\xaf\x53\x25\xc2\xb4\x38\x00\x5e\x3a\x9d\x45\x85\xe6\x32\x65\xc3\x27\xba\x72\x57\x54\xb3\x32\x56\x91\x7f\xb9\x65\xae\x9f\x02\xed\x21\x26\xb4\x81\x47\x3d\xc0\xe9\x31\xc2\x52\x2b\xf0\x0f\xe6\xa2\xec\x95\xc7\x92\x24\x7b\x1e\x03\x39\x61\x12\xf7\x83\x07\x0e\x2f\xe6\xc2\xcb\x98\x22\x50\xd1\x3f\x2d\x54\x60\xc7\x44\xfd\xe4\x53\x23\xe6\x31\xcc\xcb\x54\x0c\xd7\x25\xf2\xc5\x5a\x70\x58\xf2\x30\xe8\x2b\x79\xf3\x66\xaf\xcb\xb0\x25\xb4\x92\x55\x43\x95"}, -{{0xf9,0x13,0x9e,0x57,0x9f,0xa9,0x6e,0xbd,0x62,0x87,0xdb,0x3b,0xab,0xcd,0xa6,0x0f,0x92,0xe7,0x31,0x53,0x56,0x6f,0x92,0x4c,0xb5,0xde,0x04,0xde,0x44,0x93,0x48,0x1e,},{0xc0,0x6c,0xe3,0x35,0x53,0x3a,0xf8,0xd8,0xf3,0x37,0xf2,0xb3,0x8e,0x0a,0xaf,0xa2,0xce,0x9b,0x27,0x22,0x3c,0xd9,0xdd,0xc5,0xef,0x32,0x02,0x7f,0x04,0x88,0x9b,0x7f,},{0x05,0x1d,0x8d,0x7f,0x0b,0x68,0xd2,0xee,0xc7,0x2c,0x81,0xad,0xfc,0xfb,0x31,0xae,0x85,0x58,0xf6,0x0a,0xb6,0x3c,0x9f,0x56,0x52,0xa8,0xdf,0x63,0x8f,0x66,0x6f,0x1e,0xbc,0x0c,0x6e,0x0b,0x41,0x19,0x53,0xbc,0xda,0x6b,0x51,0x51,0xb2,0xb9,0x3a,0x39,0xe3,0xc5,0x33,0x0a,0x85,0x73,0xe1,0x68,0x79,0x22,0x72,0xab,0xd3,0x6c,0x81,0x0a,},"\xb3\x30\x76\x4d\xdc\x62\x8e\x4a\xd6\x7a\xa4\x98\x2a\xe8\x6d\x45\x81\x07\x1c\x19\x3e\xc3\xc5\x8f\x81\x3d\x79\x21\xb8\x4d\x2a\x54\x56\x2b\xd8\x74\x17\xae\x1d\xe5\x90\xa1\xa4\x8c\x4e\xc7\xd5\x56\xad\x93\x1d\x65\xc0\x54\x3f\xdf\x06\x07\xc7\x49\x85\x9e\xe1\x2f\x99\x52\x02\x0c\x19\x5c\xf8\x74\x60\x95\xe1\x08\x7c\xc6\xc3\xc8\xef\x9d\x24\x05\x25\x60\xce\x81\x3d\x61\x39\xb7\xa7\x5c\x8f\x4b\x8e\xa3\x0a\x9c\x4a\xb8\x88\xd0\xa6\x34\x1c\x99\xab\xd3\x5e\x09\x03\xbf\xe5\x6c\x93\x15\x23\x40\xc4\x12\x76\xd7\xf2\x4e\x09\x12\xb1\x2a\x4d\xb3\xd7\xee\x44\x84\xdf\xa5\x3a\xfc\x0b\x1a\xea\x14\x09\xd1\xe0\x32\x8a\xa1\xc8\x60\x41\x27\xca\x2e\xb1\xa5\xe8\x1b\xf3\x1f\x8c\x7a\x51\xc6\x05\x2c\x53\x4e\xfe\x6b\x3d\x0e\xe7\x4f\xf5\xa9\xb1\x1c\x61\x57\xe3\x64\x77\xef\xa9\x38\x2f\x57\x51\xbe\x8c\x8c\x64\x54\xc4\x46\xd6\xf8\xdc\x7e\x92\x95\x25\xcc\x3d\xe7\x8c\xb1\xba\x4a\xba\x9b\xd4\xbe\x15\x26\x10\x43\x75\x82\xc9\x65\xee\xa4\x8c\xbd\x4c\xaa\x6f\x30\x8f\x85\xf4\xf8\xd0\x06\xa0\x42\xf6\x19\x20\x07\x62\xe1\xbb\x9b\xa4\x22\xe6\x54\x75\xb3\x3a\x94\x94\x29\x8c\xfb\xb7\x5a\x15\x2b\x36\xd2\xa0\x55\x01\x80\x77\x05\xb9\x52\x76\x53\x50\xcd\x14\x14\x1d\x35\xd4\x98\x66\x92\xd6\xc3\xbc\xfc\x6d\x61\xdf\x00\x52\xa6\x20\xaa\xb8\xcc\x13\x20\x5e\x75\x4c\x16\xf9\x3e\xca\x79\x20\xbb\xea\x51\x57\xef\x11\x2f\x0b\x64\xc1\x05\x4f\x90\xa5\xdd\xc1\x75\xa8\x9e\x29\x24\x2f\x57\x64\x6e\x74\xcc\x88\x5e\x81\xa1\xcc\x14\x4c\x3d\x78\x2d\x11\x52\xa9\xe4\xcf\xe7\x6c\xb3\xff\xab\xe7\xdb\xe6\x03\xfb\x38\x69\xec\xa8\x69\x96\x98\x70\x9c\xc8\x7f\xc9\x61\xc1\xe2\x99\xcf\xca\x22\xe3\x24\x2e\xae\x78\x8c\xff\x11\xbf\xca\x61\x02\x67\x45\xf4\x97\x62\x25\xb2\x6e\xe2\x00\xc4\xf1\x91\x0c\x4b\x83\xdf\x5c\xe4\x6e\xf4\x87\xd7\x48\xd9\xc4\xc5\x02\x14\x1b\x78\x74\xca\xf4\x1e\x5a\x29\x7b\x24\x8c\x2b\xac\x69\x90\xa1\x5b\x07\xb4\xcf\x81\x0e\x59\x28\x74\x42\xd9\xa3\x69\x6c\x02\xe8\xd7\x32\x4d\x3c\xf7\x30\xdd\xa5\x40\x53\x6b\xeb\x13\xcf\xde\xae\x61\x80\xdd\x74\x84\x83\x2d\xfa\x94\xe9\x4a\xa6\xcb\xa1\x17\xaa\xe1\x72\x70\xf4\x8f\x93\xb2\xf9\x8a\xe9\x58\x17\x18\x16\x3f\x44\x63\x54\x6c\x0a\xe0\xf2\x79\xc3\x6b\x92\xbe\xe6\x6f\x1c\xa2\xd6\xa4\xf7\x26\xd2\xdf\xee\x0b\xc1\x1c\x1d\x8a\x1f\xa6\x2c\x3c\xc8\xab\xa2\x66\xb9\x87\x59\x28\x6c\x10\x68\x48\x3b\x23\x76\xb4\x03\xc8\x87\xfb\xb6\x57\xdc\x0f\x25\x5d\xea\x90\xdb\xd2\x33\x08\xf7\xe0\xe8\x42\xb4\x98\xa8\xdf\xc7\xc9\xcd\x5a\xef\x0e\x87\xd5\x6b\xe4\x0d\x50\xfc\x1d\xd4\xc0\xaa\x7d\xee\x55\xae\xbe\x4d\x6b\x6a\x52\x05\x39\x62\xb8\x7b\x0f\x2e\xe0\x9a\x90\x81\x61\x55\x33\x3d\x5c\x57\xa1\x47\x24\xe0\x01\xbc\x3d\xed\x17\x84\x3b\x76\xe2\xc4\x7a\x17\x63\x39\xc8\xde\xfc\x54\xb5\x5b\x23\x58\xae\x7d\x01\xb0\xf6\xe0\x8f\x31\x21\x6a\xe9\x03\x40\x69\x41\x68\xa5\xa7\x9e\xe8\x83\xea\x78\x58\x00\x7d\x17\xc3\x73\x59\xc9\x9d\x65\x97\xef\xe4\x60\xc1\xa2\xf7\x73\x8a\xc3\x2c\x5e\xb5\xe3\x9e\x50\x0c\x49\xc0\xdf\xf9\xc4\x65\x9e\x8c\x50\xcc\x5c\xa7\x9d\x8b\xa4\xe5\x97\x2d\x67\x22\x54\x68\xfb\xa6\x41\x67\xa6\xb2\xc6\xf3\x68\x93\x5c\x7a\x04\x9d\x35\xd3\x55\xc7\x67\x25\x20\xd3\xc9\xe4\xe4\x3c\x67\x1c\x3c\xb8\xde\xe2\x59\x04\x74\x95\xde\x0f\x56\xdd\x71\x91\xd5\xbd\x4b\xbd\x29\x51\x7e\x36\x47\x92\xff\x89\xd3\x37\x99\xb6\xe7\x81\xc2\x01\x93\xf5\xa3\x16\xfb\x40\xde\x74\xfe\xe2\xac\xc2\x5e\x47\xf5\x12\x21\x4d\xe3\xb1\xe9\xb3\x82\xa8\x69\x29\xc1\x57\x3d\x37\x24\xc2\x50\x17\xc0\xe5"}, -{{0xc8,0xee,0x95,0x4d,0xb5,0xa1,0x1b,0x29,0x2e,0xd9,0x77,0x64,0xfa,0xe6,0xb2,0x83,0x05,0x1d,0xb5,0x7d,0xcd,0xc0,0xaa,0x0d,0xf5,0x39,0x3b,0xb6,0x0c,0x11,0x2e,0xd3,},{0x5c,0x2f,0x81,0x82,0x4e,0x99,0x75,0xdd,0x7e,0xa3,0x53,0xbc,0x66,0x80,0x7d,0xed,0xc7,0x61,0x03,0x49,0x79,0x4e,0x2f,0xc0,0x8e,0x5a,0x31,0xe0,0x02,0xe3,0xfe,0x07,},{0xf3,0x07,0x7a,0x75,0x10,0x1e,0x12,0x1e,0x5c,0x3e,0x77,0xd8,0xed,0x97,0xb5,0x78,0xd2,0x39,0xbd,0x42,0x18,0x03,0xd3,0x45,0x5b,0x56,0x54,0x40,0x5a,0x4c,0x58,0x6a,0x60,0x92,0xe1,0x3a,0x85,0x29,0xba,0xce,0x46,0x8a,0x30,0x57,0x84,0xb3,0x73,0xe4,0x33,0xfe,0xe4,0xa3,0xdf,0x89,0x56,0xbe,0xfa,0x01,0x2f,0xd8,0xa8,0xee,0xd1,0x0c,},"\x7b\xa3\xfb\x56\x83\x15\xaa\x81\xe2\x1f\x19\x77\x80\xed\xc2\xc6\xea\x26\xd8\xd0\x6a\x43\x78\x91\x2f\xca\x23\x01\xcf\x1e\xab\x3d\x80\x3c\x84\x69\xde\xdd\xf3\x76\x70\x3d\xdb\x7c\xe0\x6a\x77\xda\xb2\x0e\x02\x34\x4f\xad\xcc\x50\x02\x2a\xb3\xc7\x13\xcd\x03\xc1\xda\xa9\x3f\x1c\x7e\xa5\x72\x62\x9f\x61\x0b\x5e\x3c\x51\x41\x1b\xb8\xc1\x96\x94\xbb\xce\x90\x3c\xac\x47\x05\xf9\xb5\xdd\x0f\x47\xbc\x5d\x0a\xa3\x25\x3f\x90\x88\x70\x29\x90\x27\xff\xbd\x34\x49\xee\xba\xd4\x53\x32\xb5\xd0\xc4\xf5\x33\xdb\xed\x18\xa9\x9a\x24\x98\xb9\x16\x4e\x24\x5f\xb6\x5c\x0a\xfa\x0b\x05\x37\x03\xa0\xcf\x95\x94\x0a\xc7\xa0\x19\x5d\x4f\x70\x46\x60\x9c\xf0\x43\x71\x33\x87\x06\xb9\xb1\x98\x6c\x0f\x11\x81\x75\xd2\xcd\xfc\xe7\x4a\x6f\x88\x65\x98\x25\x85\x4e\x94\xec\xe5\x8f\x51\x57\x63\x6d\x62\x35\xb7\x6d\x32\x74\x5a\x2a\x81\xa9\x67\x1a\x8f\x86\x02\x7b\xa9\xe0\x17\x63\x88\x8f\xc1\x71\xce\xf7\xc4\x51\xc3\x60\x72\xbc\x74\x99\x83\x9d\x43\x1c\xf1\x8c\xd7\xc6\xc9\xfb\xa3\xaa\x71\x2a\x05\x43\x28\xcc\xd6\x2b\xe4\x82\x0a\xbd\x5e\x78\x21\x62\x76\x46\x11\xd4\x53\x9b\xa2\xce\xbd\xc2\x09\xb3\xf4\xe4\xb6\x9c\x3d\x64\x07\x3e\x92\x0d\x21\x52\x14\xfb\x0f\xda\x44\x18\x5a\xad\xa5\xc3\x61\x27\xa1\x5b\xa1\x5c\xa2\x8a\x3a\xd0\x86\xe9\xd0\x33\x66\x86\x9c\x60\xc3\xfb\xce\xbd\x86\x9d\x2e\x40\x64\x3e\x83\x3f\x89\x48\x03\xf9\x80\xa2\xda\x7e\xa4\xe5\x9c\xe4\xd7\xc0\x6f\xd2\xaf\xf0\x87\xee\x7b\xcf\xdd\xaa\x3b\x32\x81\x7c\xe6\x3a\x63\x58\x7d\xba\xfe\xf3\x80\x01\x3a\x6f\x1e\xe3\x73\x4b\x94\xca\x3d\xf9\x64\x4d\xd0\x43\x43\x02\xec\xb3\x24\xaf\xe3\x5f\x46\x5c\x9c\x1c\x93\x1b\x27\x29\x4f\xc6\xee\x02\x72\xde\x22\x42\xae\x90\xd7\xf2\xe0\x67\x02\x7e\xf8\x64\x2e\x8f\x17\x1e\xd8\x80\xff\xab\xce\x8a\x20\xa1\xb3\xe3\x39\xad\x4e\x3f\x1a\x90\x01\xf2\x0f\x90\x02\x61\x88\xfd\xe3\x4b\x21\x7a\x6e\x26\xaa\xff\x18\x42\x2b\x7f\x84\x3d\x0f\xdd\xa3\x21\xc3\x19\xc7\x78\xf2\x31\x37\xf2\x0c\xcc\x1b\xda\x18\x90\xe5\xbc\x91\x6a\x54\x56\xd0\x68\xd3\x7b\x5a\xcc\x63\x47\x72\x0c\x56\xa5\xa4\x91\xbc\x34\x8d\x6c\x84\x8a\x9c\x8f\xec\xfe\x58\xc9\x2b\x1f\x30\x2f\xe1\x49\x19\x71\x8c\xd5\xe7\x8b\x7f\xd6\x01\xd0\x9d\xc0\x1e\x69\x04\x86\x1e\x8d\x68\xb3\xc5\x75\x35\xb6\x13\x66\x76\xcb\xc6\xe8\x39\xaf\x0d\xd7\x39\xdb\x89\xa7\xab\xd9\x13\xfd\xf6\xb0\x0e\x9c\xa0\x26\x02\xde\x6c\xa0\xaf\xd0\x91\x3d\x99\x2f\xba\xa8\xff\x82\x2b\x9d\x9b\x09\xdd\xa7\xa2\x9b\xe9\x19\x10\xd8\xfa\x3c\xaa\x2a\x5e\x51\x83\x46\xc1\x67\xc9\xf5\x19\x41\xcf\x73\x53\xf3\xf3\x4c\x1d\xab\x33\x48\x5d\x0a\x8c\x19\xda\xf9\x51\xfd\x3e\xf2\x0d\x0b\x11\x9d\x80\x38\xdf\x90\xc1\x14\xa2\x5a\x5b\x93\xae\x40\xec\x44\xb9\xa5\xd2\xbc\x1c\x65\x17\xc6\x82\x50\x0d\x4c\xdc\x19\x71\x42\xbe\xc3\xaf\x82\x32\xc0\x71\x42\x8d\xc5\x4c\x0d\x30\x45\x42\x72\xe7\x33\x6b\x0b\x58\x88\xa6\xe8\xfe\xcd\xe8\x59\xe2\xac\xcb\x7f\xb0\x94\xac\xc5\x4f\xfa\x48\x1f\x76\x23\xd9\x44\x69\x1f\x04\xfb\x36\x13\xa9\x95\x49\x80\xf1\x7e\x2a\xd2\x17\x3d\x68\xcf\x0e\xc1\xb6\x7d\x8a\x91\xd6\xec\x82\x94\x6b\xcf\x05\xcb\x90\x68\x1a\x71\x62\x7b\x59\x02\x38\x33\x4e\x3d\x5a\xb9\xda\x6a\x08\x9b\xd7\x26\x24\xdf\x90\x74\xcd\xd2\x30\x9e\x04\xdf\xca\xe0\x32\x81\x2f\xe8\x4f\x9d\xb8\x82\xcd\xea\xae\x69\xee\x5d\xaa\x5a\x66\xff\x42\x7f\xc4\x52\xed\xd0\x76\x9b\x6a\xab\xcc\x13\x9d\x0f\x70\xaf\x8b\x97\x43\x0e\x64\x4f\x58\xa4\x12\x87\xa9\x3f\x63\x1d\xed\xa8\x2c\xa0\x71\x6d\x79\x75\x4c\x5c\x50\x3e\x52\xa6\x65\xda"}, -{{0x6d,0xbc,0x55,0x9e,0x4a,0xb1,0x93,0xee,0xbf,0x70,0xc5,0xc3,0x2d,0x79,0x7b,0xe0,0x0b,0x73,0x11,0xe8,0xe6,0x69,0x1d,0xa9,0xaf,0xcc,0x18,0x72,0x91,0xf2,0x50,0x1c,},{0x38,0xa7,0x03,0x44,0x76,0xfb,0x93,0x82,0xf1,0x41,0x77,0x68,0xc4,0x21,0x62,0x95,0x1a,0x26,0x36,0x90,0x2c,0x38,0x98,0xc0,0x29,0xbe,0x27,0x8a,0xb4,0xc3,0x1f,0x31,},{0x31,0xf1,0x6a,0x7c,0xaf,0x2b,0x74,0xf6,0x5e,0x05,0x7c,0x93,0x33,0xa1,0xa2,0x63,0x3d,0xac,0x73,0x46,0x33,0x8f,0x79,0x85,0x10,0x73,0x0e,0xb8,0xd5,0xd3,0x25,0xfc,0x10,0x80,0xdd,0x5a,0xad,0x5f,0xce,0x05,0x34,0xe9,0x54,0x3f,0x3c,0x93,0x58,0x68,0x04,0x46,0x4a,0xf5,0x88,0x6e,0x86,0x44,0x12,0x9c,0x77,0xeb,0xaa,0x48,0x5f,0x01,},"\x88\xee\x23\x65\xf7\xcf\x9d\xe3\x3a\xcd\x53\x56\x49\x68\xb2\xdc\x7f\x73\x70\xb7\xe7\x03\x3f\x4c\x66\x3a\x88\xc2\x5f\x60\xf7\xf7\x11\xd6\x19\x08\xeb\xf1\xf5\xbb\x72\x83\x55\x53\xc8\xaa\x8c\x8e\x4f\xcd\xec\xd3\x79\x78\x23\x82\x89\xbf\x6c\xa8\x48\x76\xd2\x28\x21\x7a\x28\xd8\x1b\x0b\x45\x7c\x92\x2e\x91\xec\xba\x8d\x3e\x1d\x2e\x66\x59\xc2\xb0\xae\xa0\x51\xb9\xc2\xe0\x9c\x7d\xfe\xb5\x1d\x30\xed\xe7\x67\x57\x03\x41\xff\xac\x1e\xcf\x0d\xe2\x0c\x82\xd1\xe9\xed\x07\x75\xde\xac\x72\xda\x7c\x2d\xec\x23\x48\x65\xde\xc8\x3f\x67\x15\xe1\xc3\xc5\x9d\xe2\x03\x3c\xc2\x4d\x86\xbc\x2d\x31\xaa\x16\x64\x96\x86\xed\xe0\xdb\xbd\x89\x64\xc3\xa6\x4a\x3d\xca\x55\x88\xd7\x24\x8b\x1f\x24\xdf\x8d\x75\xf0\x9a\xac\x62\xc0\x78\x28\xca\x43\x1a\x3a\x2d\x77\xa6\x0c\xc9\x3c\xfa\x34\x95\xca\xbe\xb1\x90\x4e\xd5\xb5\x63\x98\x4e\x8c\x20\x77\x7b\xac\x87\x74\x10\x8a\x64\xed\xa5\x8f\xb3\x20\x24\x4a\x3a\xdd\x3e\x3e\x7a\x76\xcd\x13\x7c\xfa\x4a\x09\xb6\xe6\xe9\x30\x11\xea\x0a\xe6\x51\x71\xaf\x13\x07\x11\x76\x6c\xd2\x5b\x3c\x74\xec\x54\xc0\xbd\xfa\x02\xb3\x12\x0a\xc2\x90\x87\xeb\xac\x98\x37\xfc\xa6\x5b\xa9\x71\xbc\x42\x81\xdd\x55\x7c\x50\x0e\x22\x5e\xa6\x6c\x3c\x3f\xd5\x22\x06\xc1\x9a\x9f\x93\x95\x46\x31\x69\xf8\xc7\xa8\x46\xbd\x9f\x83\x4d\x7f\x33\x7d\x0b\x61\xfb\x30\xbc\xe2\x94\xf4\x78\xae\x1f\x1d\x97\x7e\x45\x4e\x43\x3e\xe8\x72\x9f\xb0\x65\xcc\xe0\x3f\xb2\xe4\x35\xdc\xbc\xbf\xba\x01\x53\x7e\x7a\x67\x62\xe5\x5e\x7e\xd2\x25\x28\x30\x37\x04\xbe\xb5\xae\x38\x1f\x2e\x18\x10\x56\xf2\x51\x33\x27\x3c\xf1\x7d\xdf\x2b\x06\xe2\xd9\x47\x7f\x2c\x09\x75\x5f\xc8\xd9\xc7\x3c\xb3\x31\x00\x46\x8c\x64\x13\x1c\x68\x6c\xac\x79\xfd\x38\x45\x01\xe5\x0f\x8b\x0b\xee\x28\xba\x39\x58\x3f\x42\xe4\xfd\x37\x99\xe2\x4f\x60\xda\x5f\xd3\xc7\x79\xaa\xbf\x69\x9f\xfd\x23\x21\xed\x04\x5a\x85\xbc\x64\x24\xf6\x0f\xdc\xc4\x9c\x1c\xb3\x1f\x24\x9a\x42\x36\xc0\x94\x91\x76\x81\x81\xb9\x21\xf5\x86\x02\xfd\x41\x5c\x1e\xde\xb2\x6f\x39\x32\x4a\xdd\xff\x14\x77\x13\x24\x73\x7c\x67\x20\xcc\x92\x39\x1b\x94\x9d\xcb\x42\x12\xbd\x69\x31\xd4\xde\x51\x40\x1e\x7f\x95\x3b\x7b\x03\x6b\x22\x3f\x0a\xf7\xa8\xe4\x08\xb0\x4e\xa6\x35\xa2\x3f\xa0\x70\x9b\xa0\x42\xa5\xd9\x92\x95\x4c\x09\xd8\x58\x1d\xcc\xcf\x52\x56\x8a\xd2\x7a\x1c\xc7\x1d\x18\xaa\x27\x40\xf6\x21\x21\x2e\x7f\x4c\x5e\x5e\x5e\x5e\x45\x32\xd9\xa6\x7e\xc2\x77\x3a\xc2\x1c\x8a\x4b\x00\x2d\x65\x24\xf6\x18\x2d\xd3\x71\x73\x5d\x2c\x2a\xbe\x6c\x95\xc2\x81\xc6\xfb\x1e\x97\x6b\xc1\x7e\x38\x3f\xd5\x2a\xea\xaa\x9f\xbd\x4a\xbb\x82\xa2\xcc\x65\x39\x5f\x8c\x2c\xc7\xd8\x18\x2a\x0d\x25\x0c\x68\x5c\xfc\xba\x93\xa9\x51\xee\x7c\x50\x3c\x6e\x3e\xec\x23\x6c\xe3\x3e\x08\x6c\x61\x07\x28\x73\x7c\x1c\x3b\x3a\x24\x25\x2d\xa7\xf2\x16\x72\xd9\x28\xeb\xda\x99\x3a\x94\xc4\x58\xab\x99\x0f\x5d\x19\xd8\x00\x23\xc3\x6a\xa1\x6e\xaf\xca\xb1\x43\xf3\x52\xe9\x7d\x64\x09\xf3\x24\x99\x41\x11\x9b\xfd\x9f\x5f\x90\x84\x72\x4d\x9e\xba\xd3\x83\xb1\x0f\x34\xd3\x3a\xc8\x30\xcc\xe9\xe5\xcb\x8a\xec\xee\x6f\x40\x30\x1c\xbb\xe3\x09\xfd\x06\x15\x34\xa7\xd0\xc3\xed\xaa\xea\x02\xa1\x71\xd8\xb2\x34\x9d\xbe\xec\x62\x85\x20\xac\x33\x4a\x5b\xfe\x28\xa9\xd5\xf4\xc0\xd7\x40\xf7\xc7\x2d\x4d\x72\xd8\x9a\x97\x32\x6a\x03\x00\x2d\x1e\xf3\x85\x22\xbc\xd3\x7b\x42\x84\x7a\x31\x4b\xd8\x43\xec\x88\xd1\xf2\xf9\xd3\x9f\x57\xf2\xf1\xa1\x3d\x01\x40\xa8\x84\x74\x50\x44\x8c\x88\x0b\x3a\xe7\x65\x31\xe9\x5c\x43\x92\x97\x32\x50"}, -{{0xc9,0xd4,0x16,0x83,0x0a,0xe2,0x02,0x8f,0x21,0x75,0xd2,0x2b,0x61,0x4c,0x79,0x19,0x8c,0x67,0x0c,0xfa,0xa0,0xe7,0xa3,0x61,0x50,0xef,0x0f,0xee,0x21,0xa9,0x5c,0xe6,},{0x6e,0x3e,0xb4,0xd0,0x18,0x73,0x07,0x2d,0xf9,0x46,0xf1,0x79,0x2f,0x71,0x06,0x33,0x08,0x95,0xe7,0xa7,0x6d,0xd9,0xae,0x27,0xf8,0xa9,0x88,0x03,0x94,0x90,0xfd,0x4b,},{0x47,0xfa,0xad,0x4e,0x65,0x52,0x93,0xed,0xa1,0x56,0xb2,0xa1,0xfa,0xbb,0xfb,0x7e,0x00,0x9f,0xc2,0x90,0xaa,0xfe,0xdb,0xd5,0x65,0x21,0x14,0xa4,0x78,0x53,0xbc,0x77,0xa8,0x23,0x3a,0x2b,0x17,0x9f,0x60,0x54,0x77,0xd7,0x87,0x87,0x8c,0xbb,0x15,0xea,0x61,0x24,0xdf,0x8d,0xc5,0x7b,0x2c,0xe7,0xbe,0x7d,0x18,0xb7,0x16,0x2f,0xb5,0x0d,},"\xff\x9a\xd4\x83\x7c\xd0\xbb\x77\xd6\x21\x0f\xdd\xdc\x75\x5e\x6c\x0f\x1a\x73\xc2\xbc\xd0\x3f\x7a\x58\x69\xe7\x34\x2c\xfd\x73\xcf\x70\x86\xf8\x65\x56\x15\x60\x27\x7b\xf6\xc3\x42\x1a\x91\x2d\x67\x65\x8b\x1f\xa9\x70\x57\xc4\x96\xf4\xbe\x8e\xdc\xbe\x18\xb5\xec\xd0\x8a\x1e\x7d\xb2\x52\x23\xab\xda\x20\x8f\xa5\x31\xf4\xb2\x80\xaa\x03\xb0\x4b\x60\x60\x34\x11\xd3\x74\xba\x7c\xbb\x02\x0b\xb9\xa8\xce\x4c\x0e\x45\xa7\xe1\x32\x14\x48\x43\xc3\x1f\x8b\x45\xc5\x8e\xb3\xea\x85\x3c\x2c\xeb\x61\x37\x6e\x9d\xf8\x1d\x97\x78\xe7\x21\xad\xac\x77\xb5\x03\x54\x93\x7f\x34\x37\x2f\xcc\xd5\x75\xe8\x8d\x9d\x05\x8e\x43\xdf\x94\x2f\x2c\x43\xb5\x23\xc8\x09\x8e\x6d\xd9\xe6\xbd\x21\xd5\xa6\x49\xb4\x72\xd4\x1e\x34\x5f\xcd\x5e\xfd\xdd\x49\xea\xb3\x02\x70\xcd\x87\x88\x40\x4f\x28\x51\x6e\x09\xd3\xac\xc4\x00\x48\xb3\x9d\x32\x46\xf7\x57\xe4\x82\xe1\x45\x9c\x62\x6b\x79\x9e\x04\xd0\x67\x27\x13\x73\x71\xe1\x20\xaf\xb9\xfe\xc3\x9a\x25\xf4\xe6\x76\x4b\xf9\x79\x2f\xe4\x92\xee\x0f\x21\x0b\x57\xdb\x9e\xbb\x9e\x8e\xf4\x1b\x02\xc7\xfe\xe9\xed\xd4\xb6\x17\x4c\x57\x0d\xe0\x20\xa3\x91\x28\x71\x33\xfe\x8c\xcb\x41\xa8\x3f\x91\xbd\x22\x38\x2b\x21\xe1\xd7\xeb\xc2\xc7\xe5\x01\x8e\xf5\x14\x2d\x82\x63\x7d\x02\x62\x0f\xbc\x05\x69\xcc\x09\xc4\x4e\x91\x11\x12\xbb\xae\x99\x06\x4d\x68\xd1\xc6\x9e\x77\xc9\x93\x0b\x0d\xe0\x30\xc8\xc1\xd7\x48\xc4\x14\x05\x9d\x5e\x29\x9b\x7e\xdc\x08\x94\x06\x51\x89\x4b\x30\x3a\x2b\x32\xdd\x2c\x36\x5a\x06\x7c\x97\x23\x58\x55\x94\x64\x4d\x3e\xe8\xde\x1a\x51\xfa\xea\x0e\x65\x0f\x21\x24\x88\x5a\x94\xcb\x99\xeb\x90\x3b\x7d\x45\x79\xbd\xe5\x91\x49\x7d\x95\x39\x30\xd3\x63\xdd\xdb\xda\xc6\x27\xb9\x7a\x91\xf4\x96\x82\xdf\x8e\x72\x50\xa7\x07\x3d\x38\x3a\x7a\x22\xcf\x11\x3f\x28\x58\xce\x6b\x63\x2a\x28\x92\xc4\xe8\x8a\xa9\xa0\xd2\x89\xeb\x57\x62\x9b\x00\x8d\x3b\x1b\x60\x81\xe6\xfe\x5d\x3c\x0a\x6c\x80\x21\x89\xb5\xf1\x08\xe7\x66\x31\x9e\x15\xb3\x3e\xaa\x5b\x8c\xed\x40\x27\xea\xec\x83\xb4\xac\x68\xb1\x4b\x82\x98\xbc\x51\xcd\x8e\xb3\x80\x9b\x7a\x2d\x68\x4f\xe3\x2b\xbd\x9f\xab\x5c\x91\x8e\xeb\x17\xcc\x44\x4d\x73\xf7\x30\xd4\xc8\xcc\x05\x7b\xd3\xa2\xf1\xf0\xae\xbb\x61\x63\x29\x34\xe6\x17\x02\x16\x88\x29\xcd\x7e\x91\xde\x81\x50\x96\x29\xd0\x1a\x8c\xde\xfe\x0d\x1a\xc4\x9e\x21\xf0\xc5\xfb\xe1\xb2\x24\x48\x27\x26\x8a\x0a\x27\x35\x7e\x15\x8b\xd7\x68\x84\xa2\x1e\x7f\x1f\xac\x1b\x62\x72\x16\x6d\x5a\x9f\x64\xf9\xb6\x72\x98\x9a\x87\x62\xf5\x12\xbf\x1d\xf4\xb2\xab\x69\x97\x65\xf2\xcd\x83\x96\xf4\x76\xe7\xf5\x99\x95\xde\xe7\xd8\x90\x20\x7e\xff\x0f\xd2\x72\x63\xec\x23\x2e\x37\xcf\xed\xfe\x7c\x44\x05\x55\xd4\xca\x74\xe5\x2d\xa2\x46\xc4\xb8\x37\x57\xbe\xaf\xd2\xab\x2a\x51\xef\xe1\x60\xbb\x02\xb9\x8c\x26\xd6\xb2\xc3\xf0\xc1\xaa\xcb\x2f\x3c\x34\xa5\xb2\xa3\xb6\x6f\xee\x17\x5b\x78\x75\x48\x07\x3d\x8b\x57\x77\xc6\xbe\x88\x0b\xdc\x19\x6b\x33\x74\xa2\x15\x4f\x94\xd9\x36\x0f\x77\x55\xac\x68\x15\xa2\x8a\xf2\x96\x27\x1e\x22\xa8\xf2\x35\x43\xc7\x49\x55\xa6\x09\x12\x5b\x02\xa5\x69\x21\x80\x11\x42\x02\x95\xcc\xf0\xd7\x35\x69\x99\xa5\xb8\x95\xcc\x88\x48\x3f\xad\xf7\x97\x0c\xec\x6c\x64\x24\x0f\x70\x79\xfd\xb1\x5f\xfc\x5c\x42\x27\xe5\x39\x26\xd2\x78\xba\x0f\xed\x3c\x39\x93\xbc\x86\x82\x28\x23\xdd\x58\x1a\x32\xab\x2e\x3a\x07\xf7\x94\x30\x22\x4b\x27\x4e\xad\xd8\x45\x59\x8a\x7d\x1d\x89\x67\x6a\xaf\x23\x67\x77\x74\xb7\xb0\x58\x3b\xcc\x83\x59\x9d\x15\x5d\x14\xb0\x9a\xdc\xf4\x9e\xd5\x05\xe8"}, -{{0x2d,0x27,0x7d,0xd5,0x5f,0x57,0x19,0x5e,0xc0,0x72,0xb4,0x7c,0xb1,0x44,0x8c,0xb5,0x82,0xc8,0x35,0x73,0x9e,0x6c,0x98,0xba,0x71,0xab,0x12,0x8f,0x70,0xce,0x6b,0x79,},{0xdf,0xa9,0x25,0x93,0xef,0x0f,0x0d,0x97,0x4a,0x11,0x37,0x83,0x0a,0xd1,0x38,0x48,0xaf,0xef,0x3b,0x81,0x0c,0x2a,0x21,0xbf,0x77,0x91,0x78,0xce,0x4b,0x3a,0xb9,0x74,},{0x73,0xc1,0x06,0x06,0x49,0xa7,0xc0,0x14,0xed,0x01,0x94,0x58,0x51,0xb5,0x3e,0x28,0x53,0x24,0xe6,0x0d,0x06,0x1c,0x83,0x1d,0xda,0x41,0xf0,0x33,0xb5,0x65,0x83,0x06,0xa1,0xf1,0x12,0x32,0x7a,0xfe,0x93,0xca,0xa9,0x21,0x02,0x07,0x30,0xaa,0xe0,0x06,0x9c,0x9a,0x2b,0x45,0xee,0xf5,0x5c,0xbb,0x4a,0x5a,0x9c,0xd4,0x6c,0xda,0x80,0x08,},"\x14\x54\x9e\xdd\xd5\xf2\xb7\x90\x5d\xda\x19\xd7\x4a\xb2\x07\xaa\xc6\xfb\x3e\x3d\xf3\x29\x5d\x84\x52\x31\xef\x3a\xea\x6e\x1f\x04\xee\x03\x3c\x90\x38\xdc\xb4\xbd\x3d\x5e\x45\x2c\x54\x83\x4d\x0f\xf2\xb7\xde\x3f\x32\x2e\x56\x26\x94\x9c\xd6\x1d\x6e\x89\x01\x38\xff\x0e\xa8\xad\x84\x6e\x8f\xe8\x87\xae\xe1\x5f\xc4\x8b\xbe\x4f\xba\x42\x45\x5f\x5c\x17\x45\x7a\xe7\x89\xb4\x05\xaf\x85\x96\x11\xfe\x1f\x87\x46\x18\x5a\x65\xae\xf2\x13\x4e\xa4\xd8\xf3\x98\xd4\x8d\xf7\xc1\xbb\xa4\x30\x44\x08\xae\x7e\xfb\x35\x29\x24\x09\xd5\x08\xdd\x55\xce\x21\xde\x8c\x28\x16\x0d\xc9\xe8\x77\x70\x0c\x76\x3d\x06\xb0\x1b\x85\x42\x05\x2d\x7d\xdb\x63\x35\x54\xe3\x58\x42\x79\xc7\x96\x93\x70\x23\xc8\xea\xc3\x72\x77\xbe\x2b\x82\x04\xff\x3e\x0e\x10\x31\x19\x0a\x01\x01\x4c\xf5\xf5\xb4\xd7\xad\x99\x67\x27\xf9\x75\x31\xe0\x35\x5b\x87\xc9\xe6\x11\x52\x5a\xad\x07\x99\x58\xe9\xaf\xe2\xab\x10\xe4\xa3\xe7\xa1\xb6\xba\x0a\xff\x81\x5d\xa2\xcd\x81\xea\x9e\xb9\xf5\x36\x98\x66\x33\xf3\x16\xdd\x06\xc2\x50\x3c\x6b\x19\x8d\xc5\x93\x04\x80\x7b\x98\xb4\x29\x35\xf5\x1f\x63\x7d\xdb\x59\xe2\x33\xfe\xd5\x66\x43\x9c\x1f\xe9\x6c\xda\xaf\xa4\x9f\x44\x12\xd0\xc1\xe6\x54\xd8\xc6\x90\x42\x47\x0b\x3a\x59\xac\xb6\xbf\x67\xe4\x0b\x38\xa7\x70\x67\xd5\x99\x7b\x8d\x35\xed\x61\xd6\xeb\x3c\xc7\x8b\x8b\xdc\xb9\x57\x4b\x1c\xed\x9f\x6f\x33\x9e\x9e\x38\xf9\x41\x46\xef\x63\xf0\x49\xe6\xb8\x02\xbf\xed\x2a\x51\xab\x42\xe7\xd4\x89\xf3\x16\xff\x4d\x1c\xd8\x98\xbc\xf8\x50\x56\x51\x68\x74\x40\x74\x9c\x0f\xb7\xa5\x7d\xbe\xff\x72\xe6\x46\x89\xfa\xa4\x1c\x07\xb4\xad\xe5\x99\x33\xd2\xfa\xc6\xd5\x73\xde\xb7\x39\x54\x9e\xb7\x5f\x1e\x6f\x73\x85\xd8\xc6\x14\x28\x94\x97\x3e\xd6\x85\xeb\x8e\xd0\x80\xc2\xa4\x9f\x3a\xc6\x57\x11\x61\xaf\x96\x63\x5a\xd0\x57\xdf\x14\x86\xd3\x96\x77\x3a\xc8\x98\x32\x10\x97\x89\x86\xe1\xbf\x21\xa2\x08\x06\xd6\x67\xa4\x8a\x55\x5a\x96\x32\x21\xd5\x06\x14\xa8\x97\x6b\x2e\xec\x97\x51\x2d\xb1\x1a\x35\x81\x94\x49\x2a\xb5\x45\x58\x01\xba\xa1\x4a\x51\x1b\x26\xeb\x0c\x68\x28\x9d\x79\x05\x23\x71\x2f\x2f\xf8\x70\x98\x92\x69\x5c\x4d\xb9\xad\x31\x0d\xf8\xc6\xee\x7b\xd8\x3c\x87\x1f\x05\xae\xc3\x3b\x7a\xd3\x26\xf4\x46\x69\x2a\x42\xf7\x22\x23\x76\x24\x6d\x53\x6a\x32\x6c\x4d\x73\xeb\x57\x2f\xea\xda\x11\xb8\xac\x71\x14\xf6\xcb\x44\x4c\xa2\x78\xfc\xf0\x7b\x97\x0d\x2a\xd4\x65\x37\x2a\x68\x7d\x36\xb7\xda\xac\x47\x87\x48\xec\x6a\x93\x2d\xa2\x08\x43\x94\x8e\xfa\x39\x30\x97\x81\x42\x72\xe5\xca\x1c\x73\xe7\x11\x97\x3a\x52\x68\x3f\x98\xc0\x1e\x55\x24\x1c\x15\x4d\x28\xe3\x8d\x3e\xdf\xad\xe2\x30\x3a\x4e\x7c\x45\xc2\xa7\xa1\xc9\x96\xee\x11\x37\xaf\x86\x4a\x98\xb6\x98\x09\xfc\x92\x14\xee\xa8\xcf\x3a\xfe\x84\x2f\xee\x3e\xb9\xa9\x32\x2c\x3b\x82\xfd\xdb\x05\xd4\xd1\xa2\xde\x09\xc1\xce\x72\x73\x44\x53\xa8\xdd\x3a\x89\x20\xd0\xd0\xac\x96\xef\x77\x8b\x9e\x02\xc6\xa3\xf1\x28\x72\xe1\x7d\x3a\x81\xba\x75\xfd\x23\x3b\xaa\xdb\xe2\x16\xea\x0a\x58\xe9\xdd\xa0\x08\x40\x87\x02\x08\xae\x41\x35\x40\x03\x0b\x3c\x05\xe5\xd0\xb8\x32\xdf\x87\xc8\xee\x7f\x15\x34\x87\xaa\x11\xba\xd9\xf1\x39\xc7\xdd\x4b\xcf\x41\x8f\x4b\xcb\x95\xbe\xe8\x57\xd0\xe9\x60\x84\x47\x23\x87\xcb\x39\x12\x7a\x94\x71\x34\x50\x19\x63\xa7\x07\x1b\xdb\x34\xde\x69\x61\xbe\x2b\x6b\x06\xe4\x03\xe7\x59\x18\xe6\xf6\x9d\x08\x02\x1c\xf2\xa8\xac\xb8\x0a\x01\x11\xf4\xd5\x06\x10\xc1\x52\xd3\x9c\x66\x21\xc0\x57\x8a\xc6\x89\x95\x9b\x1c\xe6\xf3\x76\xf4\x3d\x18\xaf\x06\x2e\x4a"}, -{{0x42,0x80,0x66,0xc5,0x24,0x45,0x72,0x6d,0x0e,0xa2,0x00,0x7e,0x50,0x46,0x37,0x27,0x4d,0x84,0xee,0x23,0x23,0x25,0xb5,0x05,0xf2,0xc5,0x16,0x35,0x7f,0x80,0x75,0x83,},{0xdd,0x40,0xfe,0x8f,0x67,0xc6,0x65,0x61,0x3b,0x3c,0x45,0x9f,0x6a,0xce,0x8d,0xc2,0x8d,0x34,0xe0,0xe7,0x7e,0x2f,0x6a,0xa0,0x60,0x59,0x28,0x19,0xbe,0x6a,0x9d,0x68,},{0xc9,0x38,0x82,0x9f,0x59,0x8b,0x1f,0xf1,0xb8,0x18,0x33,0x60,0xd2,0x23,0xf4,0x3c,0x59,0x47,0x30,0x60,0x68,0x76,0xa9,0x9a,0x3f,0x31,0xb2,0x06,0x5d,0x04,0xe6,0xf0,0x75,0xd1,0x39,0x6b,0x3c,0x8c,0xff,0xb0,0xe1,0xe2,0xea,0xab,0xda,0x7d,0xa5,0xe7,0x89,0xcc,0xd1,0xc0,0x20,0x83,0x5f,0xe3,0xa7,0x1d,0xcd,0xb6,0xaf,0x03,0x96,0x0c,},"\xe2\x79\x6c\x50\xd9\x3d\xf8\x12\xbc\xa4\x1b\xf2\xa1\xe1\xdd\x73\x7d\x8c\xf6\xf6\xb4\xf7\x62\x42\xe3\x91\x78\x18\x67\x58\xcb\xae\x08\x84\xe6\x0c\x6b\x4a\xaa\xdd\xae\xc9\xa8\x99\xa9\x12\xe5\xc5\xb9\x80\x4d\x7b\x04\x97\xba\xb4\x45\x8c\x58\x5d\x4f\x25\x92\x22\x49\x8c\xe9\xe8\x0e\xb6\xa7\x97\x9b\xbe\xd6\xd5\x2c\xc3\x80\x72\xf7\x45\xcb\x2c\x63\xe6\x63\xbc\x3b\x9d\x6c\xaf\x01\x2a\x60\x7f\x6d\x3b\x70\x6e\x15\x57\x57\x87\x17\xec\xbb\x97\x1a\xeb\x7c\x48\xe1\xdf\x95\x71\x1c\x55\x0e\x00\x69\x93\xbf\xfb\xa9\x11\xcb\x64\xad\x52\xd5\x17\xed\x18\xbe\x82\x36\x9e\x81\x58\x19\xd3\x17\x59\x47\xd4\xa3\x5b\x2c\xc7\xb9\xdc\x6c\x10\x05\x13\x26\xb3\xf1\xdc\x1e\xdb\x1b\x68\xba\x01\x5f\xf7\xca\x1d\xc3\x61\xd8\x96\x7a\xbc\xff\xd3\xc3\x1f\x7d\x6b\x0c\xb1\x39\x6a\xe5\x41\xf2\x97\x59\xc4\x13\x0b\xe5\x2e\xcc\x11\xd9\x92\x61\xc3\x65\xbf\x7c\xde\xc7\x81\x49\x4c\x5f\xa0\x52\x6d\xb4\xdb\xbe\x66\x0a\x43\x2b\xe5\x60\x43\xc6\x6e\xa0\x7c\x25\x62\x7a\x5f\x72\xb7\x81\x23\xdc\xf9\x86\xff\x71\xed\x1a\xff\xd1\x65\x9b\x13\x93\xd9\x62\x1f\x71\x1d\xfa\x63\xea\xda\x38\x34\x30\x79\x70\x58\xf1\x56\x6a\x00\x05\x2d\x67\xba\x53\xc1\x23\x7b\x56\x91\xde\x3b\x03\x9f\xd4\x47\x6f\x11\x51\xe5\xed\x5f\x5a\x98\x67\x2f\xa3\x3a\x1d\x85\x4f\xa0\x15\x66\xb3\x32\x31\xd4\x6a\xcd\x7f\x34\xb8\x03\x44\x79\x98\x18\x53\x76\x4d\xab\x87\xf4\x98\x44\xcb\x62\xc6\x3d\x53\x6f\xac\xa9\x20\x44\x7d\x8c\xd1\xe8\x11\x3e\xdb\xc8\x3e\x4a\x6b\x78\x15\xe1\x80\xcd\x78\xb9\x33\xd9\x68\x7f\xd5\xbe\x99\xd0\x51\x8a\x44\x66\x29\x89\xbc\x64\x01\x11\x24\xf1\x87\xd4\x39\x79\x99\x4a\x95\xe0\xc9\x03\xa0\x06\xc1\xc0\xbe\xf1\xc0\xf3\xdf\x1e\xb7\x00\xf9\x80\xc2\x8c\x3c\x1e\x99\x7d\x0c\x56\xd1\x13\xda\xe1\x96\x88\x2b\x05\x01\x8f\xca\xb3\x14\xd8\x11\x7f\xaf\xba\xbe\x77\x00\xb9\x32\xd4\x7c\x57\x36\x2b\x20\x35\xed\xdc\xe2\xd2\xef\x33\x64\x1e\xa9\x0c\x3e\xa3\xfe\xc6\xea\x5b\x87\xe1\x61\x01\x4c\x4f\x82\x14\xfd\x03\xce\xbf\x94\xab\xe1\x22\x53\x7a\x98\x70\x32\x39\xdf\x58\x21\xc5\xab\x63\x3f\x98\x36\x5c\xc6\x36\xe3\xf1\xd2\xf7\x4e\x0f\xf8\xf1\xfe\xe0\x6a\x3f\x73\x90\x7e\xe5\x04\xb3\x10\xfd\x52\x24\xad\x4d\x05\xcd\x23\xc3\x56\xdf\x8b\x34\x64\x72\x98\xc4\x98\x28\x72\x5b\xa5\xfd\x60\x61\x1e\x82\x9b\x63\x37\xbc\xc9\xdc\xf8\xe8\x97\x1c\xab\x3e\xe9\xc2\x63\x37\xd3\x8d\xfd\xfa\x03\x6b\xf6\x09\x6b\x63\x5a\xc1\xbd\x55\x25\xec\xd3\x77\xa1\x52\x72\xa8\xac\x9b\xbe\xf1\x33\x10\x7a\x42\x25\x8d\x8b\x19\xec\x69\xdc\x42\x61\xbe\x53\x00\xa2\xd2\xd5\xca\x99\xf3\x1e\xfd\xf2\x59\xf9\xd0\x79\x86\x9a\x34\x41\x37\x79\xf3\x02\x88\x24\xd7\x47\x68\x6c\x46\x0f\xfc\x49\x6f\x20\x10\xf4\x03\xe9\x03\xe2\x7a\x87\xdd\x07\x5a\xe0\xa7\xf1\x68\x94\x16\xd3\x1b\xcc\x15\xf4\x90\xca\xf9\x75\xc4\x0e\x71\x5d\x54\x99\x03\xe8\xbc\x0f\x7d\x91\x41\xe0\x20\xf4\x10\xf3\xca\x2b\x2c\x07\x97\xca\x0d\xc8\xd7\x39\x2b\xff\x24\x35\x28\xc7\xf3\xbe\x13\x89\x97\x18\x5a\x4b\x36\xf4\x53\x76\xd9\xfd\x70\xba\x20\x98\x9d\x2d\x1a\x91\x1d\x4b\x98\xd1\x60\xd2\xb8\xde\x59\x2d\xe2\xf4\xc0\x4f\x35\x86\x0d\xf3\x20\xc5\x48\x44\x0d\x5e\x3a\x34\x6a\x14\xd3\xa6\x3f\xe4\x85\xc2\x88\x91\x26\xb7\xf4\x1d\x55\xa6\xeb\x23\xd5\x62\x0b\xab\xf8\x56\x4a\xa7\x9d\x15\x6e\x98\x3f\x36\xd9\xed\x49\x8d\xa9\xca\x88\x8d\x94\x6b\x53\xcc\x47\x68\xa5\x89\x2d\x52\xd5\x41\x52\x69\x60\x28\x25\x24\xba\x61\x94\xda\x65\x94\x1d\x1e\xa3\x0f\x80\x6b\xb6\xd9\x7c\x74\x88\xb9\x3f\xd0\xa7\x70\xa9\xb1\x5e\xfc\xd1\x2c\x5c\x46\x94"}, -{{0x31,0x45,0xbc,0x68,0xd8,0x29,0x79,0x40,0x8e,0x46,0x57,0xb7,0x75,0xf1,0x50,0xc6,0xd2,0x8a,0x32,0x4d,0x74,0x6e,0xa6,0xde,0x90,0xfd,0x72,0xb1,0x7a,0x25,0x79,0x82,},{0xc7,0x76,0x18,0x6c,0xe4,0x7f,0x30,0xad,0x08,0xfa,0x1d,0x2c,0x61,0x6a,0x36,0x44,0x66,0x5b,0xa5,0x4f,0xf7,0x30,0xfc,0x2f,0x4d,0xb1,0xdb,0xa3,0x8d,0xde,0xed,0xca,},{0x24,0xa4,0x33,0x33,0x76,0x83,0xbc,0x71,0xa6,0xca,0x3b,0xcc,0xd8,0xcc,0x24,0x00,0xc2,0x44,0x64,0xfa,0x67,0x71,0x4b,0x46,0x51,0x5f,0x2a,0x14,0x32,0x71,0x27,0x05,0xd5,0x70,0x61,0x4d,0xb6,0xd2,0x6b,0xbb,0xd3,0xf0,0x26,0x7c,0x14,0x27,0xca,0x1c,0x2f,0x40,0xdc,0x9a,0x6f,0x1f,0xb0,0xf0,0xfc,0x71,0x4a,0x02,0xe2,0x4b,0x47,0x08,},"\x2e\xa8\xdc\xe1\x48\x7f\x45\xd6\xff\x8e\xb8\x3c\x54\xfb\x7e\xdd\x76\xad\x6e\x60\x8b\xb8\xda\xf1\xa1\x82\x3d\xa4\xf4\xe4\xe9\x86\x31\x73\x89\x7c\x19\x7a\xc6\x58\x04\x82\x3b\xca\x95\x09\x1f\x59\xe8\x6d\x63\xc1\x8d\xbc\xdb\x85\x74\x3f\x88\x93\xee\x69\x4d\x81\x56\x01\xf8\xf2\x2f\x4d\x7d\xf0\x87\xf0\x11\x4b\xb2\x6c\x37\x95\xe1\xfe\x4b\x7f\x4a\x8f\xa3\x1f\xd9\xf4\xff\x10\xfe\x5d\xd4\x52\xc5\x4c\x55\x78\xc7\x52\xf8\x88\x21\x30\x76\xbe\x46\x7b\xa3\x0d\x2e\x2f\xbb\xee\x87\x7c\x4b\xe9\xb6\xec\x4f\x04\x02\x1c\x00\x6f\x92\x66\x31\x19\x43\xca\xb7\xce\xa9\x9a\x2a\xce\xbb\x69\xee\xc3\xe6\x18\xc1\x31\xf9\x74\x30\x07\x5f\x79\x75\xe3\x9f\x26\xd5\x31\x51\x78\xb6\x9a\x1d\xdf\x73\x17\x61\x05\x1b\x93\xfb\x8d\xf7\xe0\xe8\xb4\x1e\x82\xe7\xf4\xf7\x5e\x91\xd6\xc8\x90\xb1\x4c\xa5\x33\xe0\x94\xeb\x8e\xa4\x48\x6d\x38\x71\x85\x96\x6c\x98\x29\x5d\x3f\x58\xb1\x7e\xef\x6c\xc3\xb4\xd0\x7e\x93\xa3\xd9\xf4\x77\x2e\xe5\x2f\x18\xa5\xbb\x30\xaa\x39\x72\x85\x0e\x65\x81\x70\xbd\xdb\x67\x6f\x33\x26\x6c\x9f\xd1\x0f\x59\x90\xba\xd8\x91\xf0\xce\xb7\x82\x73\x6b\x40\xf0\x1b\xd8\x65\x09\xb0\x63\x04\xa9\x6d\x93\xda\x23\x3d\xbe\xd1\x8a\xfa\x18\x18\xaa\xf5\x7a\xf9\xbd\xbc\x86\x7b\x39\x7f\xf2\x35\xa8\x3e\x85\x72\x24\xb1\x50\x65\x22\x5e\xec\x03\x9d\xd4\xe2\xd6\x9a\x04\xee\x10\xbe\xa0\x69\x50\x41\xed\xa5\x9b\x05\x8e\xc0\x5f\x49\x04\x8e\xe3\x24\xd1\x6c\x4d\x61\x07\xb6\xec\xd0\x48\x75\xeb\x74\x4e\x93\x65\x47\x1b\x4c\x5f\xe6\x61\x1b\x26\x18\x93\xf9\xd2\xb1\x28\xe1\x35\xf9\x2e\x47\x41\x56\xb2\x71\xb3\xc8\x2e\x9a\x76\x63\xda\xd4\x95\x3d\x30\xe1\x0e\xda\x08\x62\x60\x7d\xec\x33\x72\xb3\x99\x70\xf2\xa8\x4b\x12\xf6\x0e\x6d\xae\x7f\x31\x79\x90\x86\xd3\x8a\x7e\x34\x94\x84\x19\xc1\xb0\x7f\x44\xc2\x15\x9c\x86\xb8\xc0\xcf\xe8\x74\x7f\xc2\xba\xd5\xbf\x47\x53\x56\xcf\xe6\x9d\xe2\xdc\x6a\xd5\xa5\x19\xfd\x65\xc1\x25\x64\x70\x1c\x05\xf7\xc2\x77\xec\xaf\xcf\x4c\x87\xb1\x48\xdf\x1f\x98\x79\xa9\xae\x44\x3c\x55\xae\xa5\x21\x38\xc6\xfa\x01\xef\x0c\x3a\xbb\x5f\x2d\xf9\x0a\x57\xab\x66\x24\x17\x8c\x73\x7b\x54\x91\x5b\x7a\xa2\x9e\xa7\x8e\x8e\x49\xef\x5a\x81\x6d\x8a\x92\xc2\xf8\x1b\x8a\x19\x63\x27\x79\xc8\x92\xd6\x6f\x75\x3d\x51\x8c\x41\xcc\xcc\x9e\x59\x3e\x50\x74\x26\x25\xbc\xaf\xa4\x68\x80\x5c\x37\xa2\x1f\x8e\x29\xa6\x96\x0d\xdf\x5c\x5e\x5c\xa1\x4a\x7b\x05\x2a\x7b\x60\x15\x69\x7a\x02\x10\xed\x6f\x01\x43\xe6\xb4\x84\xc3\xf5\xb3\xb4\x72\x6c\x60\x7d\x07\xbf\xb3\xd5\x4a\x09\xc9\x80\x43\xf2\x1d\xcc\x5c\xc2\x0b\xb4\x75\x4e\x2e\x5a\x73\xb2\xf8\x06\xc2\x20\x4b\x72\xf3\x6a\xb9\xe9\x6a\x62\xc6\x27\x7c\x0a\xd6\x6b\xe7\xab\xff\xc1\x63\xb4\xe8\xfa\xfc\xef\xf5\xe2\x02\xe5\x94\x3f\x4f\x0e\x6b\x92\xb4\xdd\xb9\x53\xcb\xb7\x91\xf8\x31\x66\x03\x69\x38\xe6\xc4\x4a\xd9\x1a\x59\x6a\x55\x73\x44\x0f\xb3\x07\x41\xe6\x60\xb6\xcd\x5f\x86\xff\xa7\x46\xe6\xe9\x72\xb8\x05\xc1\x0b\x7b\x7b\x9a\x63\xc0\x55\x1d\xb8\xeb\x4f\x84\x00\xcd\xe2\x86\x8c\x0d\x0d\x4e\xb4\xcf\x11\x7f\x8e\xc4\xab\x97\x44\xfc\x58\x79\xde\xa7\xf0\xef\x16\xc2\x91\xd5\x5c\x17\xf0\x8b\x73\x1b\x7c\x65\xd0\xc4\x41\xb6\x3b\xc8\xff\x5e\x94\x90\x4c\x02\x6a\x13\x61\xda\xcc\x80\xa9\x3a\x9b\x9f\xba\x3b\x40\x36\x17\xae\xb9\x4a\x56\x85\x41\x84\x80\x11\x95\x42\x34\xae\xad\x70\x0f\x03\x4c\x47\xc7\xde\xf8\x77\x90\x52\x55\xf1\x8b\xdb\x9a\x25\x7c\xe5\xbd\xcf\x0e\x17\x67\x0c\xda\xaf\x13\xb1\xc7\xe0\x9d\x58\xf9\x2a\x96\x63\xaf\x23\x9e\x22\x07\x8e\x18\x0a\x23\xcc\xb6\xf6\x4d\x64"}, -{{0x5a,0x25,0xea,0x5e,0x18,0x2d,0x9b,0xf8,0xe9,0x30,0xa2,0x0b,0x6c,0xf5,0x5e,0x24,0xe8,0x38,0x62,0x78,0x9b,0x38,0x39,0xb1,0xce,0x9a,0x71,0xe9,0x38,0xc4,0x2d,0x37,},{0xc9,0x81,0xfc,0x36,0xf1,0xa6,0xd5,0xf7,0xd4,0x51,0xcd,0x5e,0xf3,0x9c,0xd3,0xab,0x02,0x08,0x7f,0xcc,0x6a,0xf2,0x7d,0xd7,0x8e,0xa8,0x27,0x49,0x7e,0x77,0x9e,0x21,},{0xa4,0xf3,0x5b,0x49,0xd7,0xe1,0x98,0xe5,0xd3,0x26,0xe3,0x53,0xfb,0xb0,0x1f,0xa1,0x3b,0x6a,0xe2,0x60,0xd1,0xe4,0x8e,0x30,0xc1,0xb9,0x67,0x73,0x7a,0x5e,0x79,0x93,0x6c,0x97,0xca,0x2b,0xa7,0x99,0xca,0x34,0xe5,0xe7,0x88,0xce,0xa5,0xac,0x8e,0xd1,0x0d,0x5c,0xd1,0x5d,0xae,0x53,0xe4,0x24,0x32,0x32,0x1c,0xc2,0x6d,0xc9,0x98,0x09,},"\x21\x4d\xd1\x92\x7f\x2c\xac\xd9\x88\x87\x14\x24\x9b\x85\x43\x46\x02\xac\x78\x45\x3b\x4a\xf5\x38\x6e\xee\x39\x29\x5d\x3d\x5a\x22\x67\x80\x6e\xb0\xcf\xf2\xc1\x32\xd3\x64\xc2\x42\x0d\x04\xe3\xf6\xcc\x0a\x96\x7b\xf0\x5a\x10\xff\xcf\x12\x17\xbb\xf3\x15\xe7\x5b\x98\x06\x0f\xd4\x58\xd6\x7e\xba\xad\x93\x80\xf4\xad\xc4\xdb\xdf\x74\xcb\xf1\xc6\x47\x92\x02\xbd\xd7\xfe\xd3\xa9\x46\x69\x7d\xc3\x84\x44\xd8\x8b\xfe\x51\xd4\x1d\x7a\x9b\x38\xda\x60\xb8\x50\xc5\x6b\x48\xba\x98\x4f\x6a\x18\x89\x51\x49\x55\xc0\xda\xdb\x69\xa8\xc7\x36\xcc\x76\xcd\xc4\x9f\x13\xf8\x5a\x8b\xfb\x79\x28\xff\x0a\x0c\x0c\x03\xf1\x7c\x74\xb5\xe1\x06\x2d\x75\x53\xfb\xeb\x9d\xd3\xd5\x08\x1d\xe1\xdf\xd8\xa6\xa9\x97\x66\x97\xc6\xa2\x59\xbc\xf7\xd4\xbe\xf1\xc2\x1e\x0a\xaf\x32\x98\xb0\x42\x1b\x91\x9f\xdd\xfc\x1d\xcb\x3e\xc6\x83\xd8\x6f\xf3\xd4\x23\xd7\x1c\x8f\x2d\x72\x3a\x42\xff\x68\xd8\x2e\x9f\x39\x17\x49\xb8\x29\x98\xdc\xfa\x11\x21\x60\xf5\x2a\x41\x3a\x23\xd9\x5f\xc4\x2c\x3b\xd2\x23\x84\xba\xd7\x77\x54\xa7\x10\xd8\xb9\xf8\x4a\xe0\xa8\x02\xfc\x46\x50\x9e\x7f\x2b\x07\x07\x90\x12\xb4\x3b\xfe\xea\xb7\x19\xbd\xe5\x6f\x00\xe5\x9b\x8e\xdf\x1c\x47\x28\x83\xb1\x98\x5b\x2f\xa6\x99\xa1\xae\x90\xcf\x45\xd7\xac\x58\x0c\xeb\x5f\x27\x97\xde\xf5\xb8\xbf\x4f\x2b\x9b\x35\x19\xa7\x27\xb9\xf2\xcd\x12\x56\xa2\xf0\x76\xed\x22\x96\x49\x5b\x5c\x2d\xf7\x88\x7f\xf8\x9e\x88\xe2\x36\xa1\x4c\xde\x63\x24\xf4\x3d\x68\xd9\x01\x72\xb0\xb8\x8b\xd2\x88\x03\xe9\x99\xdb\xed\xcc\x50\x1d\xb6\x54\x54\x4e\x17\x1e\xc1\xf9\xf3\x2d\x4d\x33\x21\xd5\x89\x39\x2e\x03\xca\x65\x9f\x96\x75\x2e\x1f\x08\xa5\x5d\xb5\x53\xd8\x66\x98\x55\x41\xf5\xbe\xf8\x4c\xe2\xee\x32\x3e\x17\xd1\xf7\xdc\x16\x4b\x50\x51\x5a\x28\x7d\x53\x05\xfc\x28\xc5\x98\x3b\x9e\x53\x98\xb2\x40\x7a\xe4\x72\x96\xfe\x4a\x48\x1d\x22\xff\xb4\xb8\x65\xa6\x6b\x97\xa6\xc2\x79\x35\xdd\x8e\xb8\x69\x94\xb7\x9d\x36\x83\x63\x71\x3f\x10\x1d\xc3\x7f\x42\x9e\xee\x0f\xee\x24\x41\xc2\xdc\x17\xbf\x43\x92\x4f\x0c\x04\x4f\x14\x32\x90\xea\xf3\xf9\xee\x4d\x94\x6d\xbe\x45\x83\x1a\x0d\x83\xc0\x76\xe7\x51\xc1\x4f\x3b\x1a\x72\x67\xf5\x44\x6c\x18\x86\x98\xd2\xb4\x6d\x87\xe6\xf3\xb2\x0b\xb3\xfd\xaf\xe2\x4c\xc0\x96\xbc\x31\x2d\x86\x78\xb3\x8a\x80\xc3\xf0\x52\xa0\xc9\x6d\x5a\xd8\x7a\x5d\xd8\xc1\x33\xcc\x9a\x15\xbe\x33\x57\x4c\xd9\x43\x08\xc2\x4d\xec\x1a\x9b\xdf\x18\x9b\xa6\x87\x19\x9f\x72\xef\x67\x09\x87\x8e\x10\xf8\x7b\xd8\xa0\x3d\xc8\x4c\x8f\xa9\x64\x20\x28\x58\x98\xca\x32\x11\xd8\xb0\xcc\xef\x64\x01\x1e\xc2\x4f\x38\xe5\x74\xda\x34\xda\xb9\xd2\xf0\x02\x10\x52\x27\x89\x0f\x92\x48\x8c\x62\x1e\x57\x13\xe4\x7d\xbc\xb1\xa8\x2a\x6d\xa6\x0d\x8b\x22\x01\xeb\x29\xd4\x94\x49\x33\x60\xed\x5a\x3f\x4b\x52\x25\xea\xe7\x70\x7e\xe0\xb4\xc0\x40\x73\x05\xc1\x67\x54\xc7\xf6\x30\xfc\x85\xc1\x3e\x49\x17\x04\x7b\xcf\xf3\xb2\xa2\x93\xfe\x95\x55\x06\xc7\x26\x4e\xa6\x5b\xf3\xa9\xb2\x5a\xcf\x34\x36\x00\xd8\xfa\x0c\x7c\x1a\x29\x0d\x02\x71\x10\x1b\x7f\x40\xb9\x6e\x7f\xda\xf2\x9d\xef\x9d\x93\x27\xa5\xae\x05\x44\x6c\xb5\xa6\xd3\x22\x45\x3a\x8b\x09\x8b\xcf\x3a\xee\x1f\x70\x4e\x14\xd0\x0b\xe3\x42\xb8\x93\x4d\x19\xe5\x29\x21\x88\x72\xea\x3a\x2f\xb2\x12\x4b\x52\x66\x7c\x01\xfc\xa5\x84\x1c\x66\xe1\xe6\x4a\x1e\x68\x0e\x09\xba\x18\x6e\x04\xd1\x05\x18\x6c\xf6\xeb\x72\x8b\x9d\x50\x2a\x66\xb8\x29\xfb\xc9\x92\xa3\x88\x10\x04\xec\xdc\x80\xad\xfd\x04\x4e\xda\x88\x0f\x8a\xf7\x2a\x14\xfb\x55\x0d\x7c\xc7\x41\x94\xa9\x45\x20\x7d"}, -{{0x42,0x33,0x5c,0x30,0xb3,0xf6,0xb3,0x59,0xce,0xf5,0xaa,0xb6,0xa3,0xce,0x28,0x58,0xa1,0x51,0xb7,0xa4,0xfd,0x78,0xd2,0xfd,0x3e,0xe3,0x6f,0xc2,0x9d,0x24,0x94,0x04,},{0x30,0x1c,0x51,0x5a,0x02,0xa4,0xc6,0x6b,0xc6,0x40,0x10,0x80,0xc6,0xca,0x79,0x23,0xb7,0x83,0x1e,0x3c,0x9a,0x72,0xb5,0x5b,0x14,0x02,0x7e,0xb2,0xe7,0xb3,0xb1,0x52,},{0x67,0xb0,0xf1,0x74,0x49,0x03,0x9e,0x8c,0x79,0x7b,0xf9,0x13,0xaa,0xe6,0xe4,0xf0,0xbb,0x99,0xc7,0x4d,0x6d,0x10,0xc9,0x73,0xb9,0x90,0xff,0xe0,0x3e,0x7e,0xe4,0xab,0x5b,0x35,0x80,0x6d,0xb1,0x5a,0x98,0xc0,0x84,0x6a,0x82,0x7e,0x7b,0xcd,0x53,0x9c,0xd3,0xbc,0x09,0xdd,0x11,0x8a,0xb3,0xe5,0x26,0x63,0xa3,0x57,0xb1,0x29,0x91,0x07,},"\x6d\xa2\x25\x1e\x6f\x55\x95\x36\xb0\x9b\xfa\xfb\x81\x60\xa2\xe8\x10\x2d\x31\xf8\xb5\x93\x24\x08\x3e\x52\x27\xb2\x0c\x3e\x5c\x3a\x06\xe2\x39\x67\x68\xdc\xa3\xec\x76\xdc\x7f\xc0\xeb\x3d\x14\x5e\x62\xed\x07\xfc\x1a\x8b\x1b\x2e\x34\x70\x13\xa0\x52\x72\x74\xd0\xb2\x34\xfe\x72\x50\x26\xa9\xd1\x28\xf8\xdf\x20\xdb\xfa\x3b\x65\x03\x81\x8e\xde\xbd\x7f\x24\x93\x40\x80\x94\x5a\x7e\x1e\xa0\x22\x73\xfe\x48\xb6\xed\x1e\x83\xfd\x16\x8d\x79\x73\xfb\xb7\x94\x1b\x40\x37\xd3\xcd\xa5\x55\xe0\xe8\x9c\x2b\x94\x3f\xb1\xe2\x07\x65\xac\x7d\x4f\xa3\x77\x7f\x35\xa0\xa8\xbc\x11\x8f\x59\x9c\x84\x7b\xe3\xfd\xb2\xd8\xe2\x01\xae\x12\xa3\x0b\xde\xfb\x03\x4f\xf2\x4e\x3e\x2e\x70\x1a\x0d\x17\x33\x73\x40\x78\xbd\x1f\x9a\x69\xbb\xc6\x67\xe4\x61\x21\x1f\x2c\x76\x9d\x29\xdb\x7c\x4d\x62\xd6\xb1\xb9\x2b\x56\xf5\xf1\x8a\x93\x1a\x92\x60\x64\xb7\x8d\xa1\x46\xe1\x8b\x48\x13\x9b\x9b\x39\x86\x2a\xec\x37\xbc\xce\x12\xcb\x78\x94\x29\xe6\x8e\xa3\x81\x12\xd0\xb5\xcc\xe3\x0b\xd2\xd2\x6c\x5f\x7f\xd4\x15\xda\xf7\xca\x31\x7b\x33\x68\xb7\x61\x7d\x45\x25\xe5\xbc\x97\xd9\x46\x1d\x5d\x64\xf6\xb5\xd3\x18\xd0\xbc\x3b\x76\xf2\x5b\x06\x05\x42\x69\x09\xf2\xaa\x0c\xd6\x67\xa4\xf0\xe0\x75\xb9\xa9\xfb\x2e\x9a\x6c\x82\x70\x4d\x8a\x9f\x16\x66\x84\x4e\xdc\x32\xf6\x3a\x3d\x4e\x0f\xd9\xfd\xba\x30\xb5\x1b\x33\x36\xb9\x6e\x9e\xae\x39\x2a\x34\x2d\xe4\x9e\x9b\x5f\xa0\xf9\xb9\x01\x71\xbd\xe0\x9c\xf1\xe9\x46\x49\x91\x40\x00\x81\x59\xeb\x18\x65\x56\x3c\x28\x39\x4b\x03\xa8\xd7\xa5\x52\x27\x1b\x28\x76\x68\x75\x66\xb8\x0f\xd3\xbe\x2b\x66\x33\x2f\xca\xd1\x96\xca\xb8\x52\x7c\x56\xe2\x15\x36\xa1\x41\x65\x2c\xdc\x7f\xa7\x45\xb2\x6a\x33\x1d\x78\x7b\x93\xe5\xe8\x16\xd8\xd8\x51\xa5\x8f\x6a\xc0\x7a\x58\x27\xfc\xdf\x47\x2e\x86\x85\x43\x3a\x40\xca\xc0\xc4\x9a\xa5\x69\x31\x9a\x2e\x57\xb4\x1c\x99\x98\x16\x5e\x69\x72\x3b\xa7\x7e\x5c\x04\x23\xc4\xb4\xca\x07\x18\x7b\xb7\x44\x2e\x7d\x31\xca\xac\xb2\x77\x00\xc7\x1a\xe4\x8c\xd0\x55\xed\x2f\xe4\xda\x36\x3f\x44\x82\x11\x24\xcc\xa1\xbf\x2e\x63\xd9\xb8\xab\xd2\xfa\x41\xb1\x42\x2f\x52\xd5\x58\xbc\x5f\x11\x0c\x86\x3c\xc6\x00\x86\x49\x84\xed\x25\x9b\x73\xcd\xdd\x57\x96\xb3\x29\x79\xed\xdf\x76\xa0\x7b\xc5\x9b\x73\x68\xc4\x8e\x12\x9e\xcc\x0d\x45\x35\xdc\xce\xe2\xc3\xb8\xe5\x6d\xe5\x0e\x6f\x5c\xc6\xea\x51\x5c\xd6\xa0\xeb\xdf\x1c\xa7\x9a\xa2\x79\x48\x21\xad\x2e\x10\x9e\xdd\xa4\x50\xc9\xfc\x3c\x84\xd8\xc9\x6b\xc3\x8d\x4b\x43\x7a\x73\x8f\x81\x8b\x4d\xdc\xb6\x84\x38\x3c\x09\xb1\x1b\x36\x05\x2e\x9d\x2f\x76\xa6\x1e\xb4\xd6\x20\x49\xce\xd5\xf6\x16\x62\xc4\xb9\xec\xd2\x4a\x67\xf4\x51\x9d\x46\x52\x8c\x5b\x2e\xb2\x10\x05\xf4\x9c\x73\xa3\x37\x0c\x68\xe3\x7a\xc2\xb1\x8d\x48\x1f\xa1\x0f\x96\x71\x4f\xe0\x5c\x16\x8d\xf1\x1c\xda\x54\xf1\x4f\x49\x37\xe9\xfc\xe1\xf5\x16\xc0\x37\x1b\x36\xa2\xc0\xa0\x50\xba\xc7\xfa\x51\x22\xa6\xe3\x5e\xc9\xc4\x04\x36\x58\x5f\x31\x6e\x6c\x91\x1b\xdf\xd7\xdb\x4b\x80\xb4\x30\x64\x79\xb8\x2a\x2b\x24\x3a\x52\xb2\xd2\xb6\x27\x42\xed\x11\x28\x27\x90\xcf\x6f\xdc\x7c\x9c\x82\x43\x64\xcf\x25\x63\x6a\x85\x51\x50\xbd\xdb\xdf\x7e\x64\x0f\x9f\x95\x2a\x94\x7e\xc7\x97\x49\x25\xe8\x24\x50\x68\xb2\x92\x10\x1b\x1f\x4b\x20\x18\xe8\x5d\x07\x8c\x2f\xee\xf4\x49\x23\x49\x72\x9a\xd4\xac\xb3\x8f\x1c\x7c\x02\x70\xb6\x1d\x3d\xfd\x76\x36\xc6\xcb\xf1\x81\xe4\xc8\xa0\xe6\x4f\xa0\x61\x32\x55\x3c\x2b\x9d\xb7\x01\x9e\x3b\x3c\x48\x5d\x8d\x5b\x7d\xfd\x5f\x51\x5e\x4d\x71\xed\xe5\x35\xae\x7f\x2a\xae\xdc\x23"}, -{{0xbe,0x6b,0x2b,0xab,0xdd,0xd2,0xdc,0xa1,0xb0,0xe1,0x0d,0x12,0xd2,0x0a,0x9c,0xe2,0x9c,0x67,0x85,0xda,0xc1,0xd6,0x0f,0x2e,0xdf,0xa9,0x4a,0xc2,0x78,0x4b,0xa7,0x66,},{0x39,0x8f,0x22,0xf0,0xef,0xbf,0x8c,0x38,0x35,0x5e,0x47,0x91,0xbf,0x67,0x08,0x98,0x95,0x1f,0xbb,0xd5,0x51,0x8f,0x0e,0x2a,0x60,0x5d,0x46,0x00,0x23,0xf6,0x13,0xf0,},{0x70,0x2a,0xb9,0xac,0xbf,0xa7,0x5e,0xa2,0xad,0xbe,0x4b,0xe2,0xb6,0x84,0x76,0x25,0xae,0xb4,0x09,0xee,0xf9,0x59,0x6f,0xab,0xe3,0x9d,0x2c,0x53,0x3a,0x03,0x43,0x1e,0x5e,0x57,0x95,0x52,0xe8,0xa6,0x4f,0xc4,0xfb,0x7d,0x92,0x6a,0xa8,0xff,0xfe,0x06,0x40,0x69,0x84,0x64,0xc4,0x45,0x4c,0xe3,0x5f,0xe8,0x3f,0xf2,0x63,0x05,0x1a,0x01,},"\x5c\x92\x95\x88\x1b\x7a\x67\x06\x69\xb0\x4c\xbe\x0d\xab\xd8\x96\x93\xb7\x7f\x7c\xce\x0d\x4a\x33\xf5\x2e\x02\xeb\x26\x95\x9e\x71\x3d\x9a\xef\x5f\x95\x44\x2b\xdf\x91\x72\x83\x83\x32\x52\x02\xaa\xcc\xc0\x37\x47\x7e\x36\x66\xfa\xca\xf2\x4e\xac\x95\x34\x87\x9a\xa3\xef\xe1\x8f\xfc\x1a\x5c\x54\xe3\x9c\x76\x87\xd0\x93\x7b\x24\x71\xba\xb3\x89\xb6\x46\xcb\xe6\xb3\xe5\xd5\x96\x1e\xa6\x3b\xd4\x52\xb4\x74\x33\x44\xce\x4c\x79\x33\x74\x52\x37\x95\xc7\x81\xee\x84\xd5\x11\xe2\x94\x11\x19\xba\xd1\xf4\xa7\x46\xed\x9d\xba\x89\xc8\xd0\x75\x1a\x64\x02\x71\x86\x35\xf6\xe3\x1d\x9e\x18\x68\x1c\x69\x56\xc5\x37\x32\x51\xd3\x5f\x53\xba\xa1\x98\x7c\xd4\x48\xc9\x03\x1a\x07\xf3\x2c\x80\x29\x11\x9d\xe3\xa9\x16\x31\xde\xde\x1d\x93\x3e\x0f\xa3\x26\x29\xaf\xe1\xb4\x2e\xb5\x91\xc2\x2f\x87\x33\x1e\x93\xcc\x08\x3c\x23\xf6\x4a\x6e\x5e\x58\x6f\xf3\x1c\xc0\x4e\x42\x3c\x56\xae\x3f\x6a\x73\x94\x6c\x48\xde\x4d\x85\xab\x00\x17\xba\x24\x45\x6d\x69\xb5\x9d\xca\x6d\x40\x3b\x64\xb0\x7c\x40\xd3\xb9\x0e\x12\x23\x21\x5e\x3f\x7e\x87\x6c\x67\x01\x11\x1e\x37\xe5\x17\x77\x08\x87\x31\x0c\xa8\x56\xf0\x09\xa0\xd6\x06\x54\x83\x5d\x94\xe6\x58\x7a\x43\x9d\xa5\xdb\x0a\x0c\x37\xd7\xc9\xd3\x7c\xa1\xd7\x03\xe1\xb3\x22\x76\x31\xad\xac\xaa\x79\x42\x1a\x1c\x43\x9d\x60\x34\x9a\xe5\x77\x41\xb7\xa8\xad\x09\xec\x29\x31\x23\x03\x0b\xf6\xba\xc0\x68\x9e\x53\x1c\xa7\xe7\x27\x18\x22\x3f\x9e\xa4\x3b\xec\xb0\xee\x9d\x9c\x1a\xb8\x45\xed\x1c\xae\x44\x3e\x3c\x5d\x4a\x9b\x1e\xde\x6d\xb3\x41\x7c\x3a\xce\x28\x11\x43\xf4\x2d\x85\xf5\x99\xb3\xb9\xd3\xd0\x5f\xa0\xed\x07\xc1\xec\x35\xff\xab\x03\x05\x16\x8b\x4e\x56\xe5\x8a\xfa\x06\x17\xf9\xa8\x6b\x1b\x5b\x20\x1d\xcc\xb0\x72\xb4\xce\xf0\xbb\x7b\x95\xc5\x2d\xae\xef\x9d\x9e\x74\x24\xa5\xc0\xf1\x48\xf9\xff\xe6\x0a\x5b\x23\xe0\xff\x82\xc7\x30\x99\x2a\xc9\xc1\x7f\x97\xf0\x65\xcf\x0a\xd5\x37\x7e\xac\xcb\x31\xd8\xbb\x92\x3b\xd2\x60\xea\x11\x9e\x6f\xa9\xbd\x69\x83\x48\x2d\x70\xd9\x21\x91\x02\x40\x2d\xc6\xa3\x49\x91\x93\xd0\xc1\xcd\x3e\xd2\xa6\x69\x21\xa9\x8d\xf6\x9b\x79\x14\x13\xf4\x97\x0b\xbc\xe0\x4f\x63\x9a\xf9\x09\xc6\x4f\x45\x60\xdb\x0a\xf6\x00\x3d\xc4\x62\x19\xe8\xad\x2b\x37\x2f\x8b\x5f\x81\xcf\xaa\x04\x1a\xb7\x1a\x34\x8c\x93\x1e\x8d\xfd\xbc\x40\x9c\x22\xd7\xee\x6e\x07\x62\x6e\x10\x4e\xc6\xcc\x7c\x6a\x41\x16\x17\x7f\x93\xaf\x16\xf1\x24\xf1\x96\xda\xb6\x19\xb6\xf6\x98\xc2\xd1\x91\x85\x8e\x96\x0c\x2e\x94\x7b\x51\xf3\xac\x48\x38\x75\x9c\x21\xfe\xf7\xeb\xae\x35\xda\x24\xf5\x5e\xbd\xa9\xb9\x87\x9a\xea\x17\xa6\xd8\xd9\x27\xde\x48\x7b\x17\x5f\xd7\xfa\xa2\x14\x38\xa2\x09\x23\xdd\xbb\xca\x72\xe6\x72\x69\x34\xbd\x6c\x21\xe8\x11\x80\x19\xf6\x5b\x38\x10\xa0\x7f\xa2\x7b\x1c\xba\x64\xd0\xf3\x9f\x0b\xfd\x49\xdc\xfa\xfd\xef\xe3\x79\xbd\xea\x82\xf3\x1a\x9c\x39\xf7\xe8\x1d\x29\x43\x37\xd1\x0f\x1e\x9d\x8b\x50\xeb\xa4\x58\xce\x7b\x75\x3d\x36\x96\x85\x38\x51\x3e\xdd\xb0\xe8\x45\x34\x41\x1c\x4a\xf3\xf0\x21\x46\x10\xee\x39\x01\xa0\xeb\xf3\x16\x17\x3c\xca\xf1\x5c\xd7\xee\x49\x6d\xbf\xc2\x46\x5e\xb8\x34\xdf\x62\x02\x9d\x62\x1f\xe9\x11\x82\x4d\x79\x87\xdf\x2d\x46\x34\x6b\x4d\xce\x1e\xce\x7d\x19\xd5\x51\x18\xc0\x37\xc9\x95\x51\x11\xd0\x7f\x1f\xc3\x62\xc7\x39\xf1\xea\x5b\x27\x5c\x71\xc0\xae\xbf\x59\x65\x5e\x2d\xef\x16\xe1\x23\xb3\xeb\x25\x26\xc3\xca\x5e\x83\xcb\x24\xd5\xb6\x8d\x7a\xc4\x0a\x67\x59\x33\x84\xc5\x63\xaf\xe0\xb5\x52\xad\xaf\x60\x80\x50\x35\xbe\x97\xb8\x06\x76\xad\xeb\x15\x76\x52\x08\x33"}, -{{0xb1,0xe4,0x7c,0xa3,0x1c,0x64,0xb6,0x8a,0xaf,0xaf,0xb4,0x43,0x51,0x2e,0x66,0x78,0x7c,0x65,0x92,0xf3,0x34,0xaa,0x78,0xfa,0x21,0x9a,0x3d,0x93,0xc3,0x3a,0x4a,0xb3,},{0x58,0x11,0x9b,0x38,0xe6,0xa1,0x48,0xa9,0x36,0xbc,0x5f,0x92,0xf4,0xf2,0x9b,0x98,0x2f,0xf2,0xcc,0xa6,0x4a,0x5a,0xff,0xa1,0x4c,0xa1,0xb6,0xa6,0x2f,0xe3,0x28,0xc4,},{0xdf,0xac,0x86,0xdf,0x58,0x6e,0xc3,0x4c,0x7c,0xfe,0xa5,0xd5,0xa6,0xcd,0x11,0x40,0xe5,0x0b,0x6b,0xf0,0x50,0xf8,0xe4,0x1a,0x19,0x0e,0xbf,0xd3,0xb1,0x43,0x2b,0x95,0xa5,0x7d,0x56,0x52,0xdb,0xae,0x8f,0x53,0xe0,0x37,0xae,0x32,0x6e,0x7f,0x18,0xcf,0xef,0x7c,0x77,0x9f,0x40,0x34,0x6f,0x7c,0x0d,0x86,0x44,0x61,0x05,0x93,0xf2,0x09,},"\x76\x7e\xc1\xb3\xda\xf2\x04\x38\x7f\x3f\xd3\xb2\x00\x10\x78\x1a\xfb\x1f\x38\xf6\x14\x47\x42\x13\x28\x7f\xff\x11\x30\x7f\x5f\xf5\xae\x7e\xc9\x45\xa2\xb9\xb4\x87\x00\x49\xd4\x53\x2f\x8f\x61\xc1\xa7\xb5\xf2\x11\xfc\xa2\xe6\x7c\x37\x4d\x96\x21\x9d\x8e\xa9\xde\x73\xf0\xe3\x87\x04\xfc\x94\xc0\xe9\xe7\x2f\x2e\x15\xda\xba\x3f\x88\xf7\x49\xb1\xed\x70\x26\x60\xdb\x1a\x35\x2a\x26\x67\xd4\xdf\xd4\xe0\x0a\x18\xef\xa4\xc6\x60\x9e\xe9\xc9\xa8\x8a\xda\xcb\xbb\x98\x5d\x3d\xe8\xdd\xd1\x7d\x4e\x4e\xb7\xcf\x74\xa1\xda\x91\xed\xb3\x90\x85\x2e\xa4\xcb\x9a\x42\x4f\x7f\xa2\x22\x9e\x08\x30\x33\xa3\x40\x59\x11\x7e\x5e\xfa\x7b\x66\x13\xd7\x5e\x58\xb7\x02\xc6\xce\xe5\xd0\x04\xe8\x59\x9b\x97\x50\x3a\x5f\x10\xc4\xc4\xe5\xb9\x57\x73\x71\xd3\xd0\x5b\x2d\xfb\xf7\xcb\xef\xe6\xd0\x92\xd6\x5c\xbd\x40\x51\x38\xd9\xb0\x4c\x51\x86\x23\x59\x83\xfa\xb6\xd4\xce\x85\xb6\x36\x27\x62\x06\xd7\x4a\x2e\xe7\xdb\x61\x64\xda\xc4\x7c\xce\x78\xf5\x0d\xb9\x9a\xf6\xac\x6e\x70\x64\xc1\x3a\xab\x79\x3b\xe8\x7e\x66\x28\x9c\x94\xa0\x9f\xb0\xa3\x1d\x97\x97\x1e\xdd\x74\xea\x9c\x0c\xe8\x74\xd2\xb7\xd6\xc4\xab\xae\xff\x07\xf8\x70\x22\x51\x51\x94\x6a\x5c\x47\x6f\x6b\x97\x89\x96\xb8\x7d\x8c\x98\x46\x06\xc7\x91\x28\x7d\xa6\xba\xd0\xaa\x44\xb0\x13\x0b\xe8\x86\x71\xa5\x56\xe2\xde\x35\xc4\xcb\x03\x8e\xe7\x81\x27\x35\x30\xac\xe0\xa1\x04\xc2\x78\x09\xae\xe0\x33\xc8\xbf\x90\x29\xd9\x0f\xe7\xba\x06\xaa\xa9\x4e\x16\xa5\x2c\x64\x3d\xfd\x92\xa7\x62\x4f\xbb\xee\x77\xa7\x15\x8b\x2c\xc1\x51\xbd\x3f\x61\xa1\xa7\x6f\x32\xb2\x84\x89\x30\x7a\xcf\x0d\xd8\xc2\x6c\xc4\xad\xbb\xb8\xde\x43\x0d\xb4\xe4\xf5\x83\x08\xb6\xab\x90\x45\x61\x11\xde\xac\x29\x78\x17\x2f\xe1\xfc\x0c\xe4\x98\x08\x8a\xdd\x4c\x31\xc2\x1f\x24\x27\x90\x25\xfe\xb4\x8c\xbb\x7a\x92\x0c\xff\x2d\x28\x71\x05\x87\xaf\x52\xc8\x44\xdb\x8a\x7a\xeb\x7d\xf1\x0d\x43\x41\x1a\x3c\x8e\xee\xbb\x40\x6d\x6e\xfc\xb1\x92\x48\x88\x7d\x45\x0b\x57\x3d\x90\x30\x5e\x1f\x23\x75\x3e\x89\x05\x11\xdc\xc7\x7c\x74\x0e\x31\x6a\xd7\xf5\x2d\x49\x02\x07\x3d\xb3\x99\x8e\x4e\x4a\xcc\x4e\x01\x88\x5b\xd1\x18\x8e\xcd\x61\x65\xae\xde\xd1\xe7\x78\x70\x2b\x6a\x6a\x79\xa9\x49\x99\x10\x2d\xf7\x20\x18\xf7\x92\xf8\xf1\x62\x00\x7e\x81\x2a\xef\x8f\x95\x6e\x12\x32\x82\xbb\xdb\xd0\xc3\x56\x12\xc2\xd3\x47\x3f\x94\x4c\x6d\x76\xbe\x9e\x86\xff\xfa\x46\xcc\xb1\xae\x13\x50\x5a\x4a\x81\xf3\x1b\x84\x26\xb8\xb6\x0d\xe8\xe8\xa7\xc1\x6d\x1e\x16\x65\xb2\x71\x43\x46\x65\xc4\x42\xa9\xc6\xa9\x77\xce\x98\x6f\x69\x93\xb7\x43\x9a\xf0\x3b\x40\x2e\xea\xff\xf1\x45\x6d\x15\x15\x26\xd9\xc5\x8f\x51\x5f\xd2\x48\x5e\x0c\xbb\x32\x4a\x50\x3a\x8d\x49\x13\x44\xcd\xb2\xaf\xf4\xc4\x1a\xa8\xe2\xed\x66\xe5\x80\x83\xbf\x0d\x2f\xbf\x48\x77\xc8\x5a\x4b\xcd\x6b\x9c\xbb\x82\x12\x42\xc9\x41\x47\xe5\xfd\x8b\x7d\xd7\x92\xad\x0a\x28\xd4\x9d\x41\x10\x0b\x43\x1b\xb4\xd8\xc7\x83\x3d\x85\x05\xdd\x9e\x26\x49\xf9\xca\x70\x51\xbe\x68\x71\x2e\xf3\x63\x71\x02\x03\x6b\x00\x26\x49\x47\x3c\xe2\x59\x67\x7d\x82\xc6\x06\x28\x95\xe1\x61\x92\x8b\x75\x2f\x13\xc9\x1a\x45\x95\x5e\x80\xf0\x07\xde\x69\x0e\xdf\x8a\x0e\x5e\xee\x44\x22\xe1\x62\xb9\xd2\xb4\xa9\x21\xd3\xa6\x48\x45\x79\x3a\xa2\x22\x9e\x9c\x23\x9e\x57\xa6\xb1\xa9\x0a\x52\x54\xc3\x51\x2f\x99\x34\x53\x15\xac\x7d\x34\x57\xf9\x15\x42\x96\xc6\x68\x22\xab\xe1\x84\xd6\x4e\x57\x2b\x9c\x38\x49\x29\x58\xe2\x1b\x02\x92\x67\x54\x10\xe7\x34\x8b\x2b\x71\x8a\x0b\x75\x92\xca\xee\x94\x58\x1a\x94\x8d\x2f\x41\xfa\x03\xc6\x1e"}, -{{0xfb,0xd5,0x5f,0xa7,0x43,0xc3,0xa5,0x91,0x0b,0x38,0x57,0xdd,0x0b,0x6a,0xa5,0x84,0xf3,0xb2,0x38,0xde,0x05,0x6b,0x76,0xab,0x76,0x17,0xae,0xb5,0x26,0x38,0xfe,0xf6,},{0xa7,0xa1,0x63,0xc4,0x18,0x3b,0xd8,0x4b,0x75,0x6d,0xf3,0xc8,0xaf,0xdf,0xb9,0xcd,0x5b,0x24,0x23,0x52,0xd9,0x49,0x9e,0xbd,0xab,0x90,0x78,0x5c,0x3b,0xd6,0xdb,0x2d,},{0xef,0xfb,0x29,0xda,0x69,0x85,0x97,0x1c,0x20,0x2e,0x24,0x50,0x30,0x1d,0x49,0x71,0x1b,0xed,0x25,0xfa,0xd8,0x5f,0x61,0x99,0xd1,0xeb,0x1e,0x71,0x91,0x4d,0x96,0x4c,0xbe,0x18,0xe3,0x4c,0xc3,0xe3,0x28,0x72,0xcd,0xec,0x02,0x6b,0xd1,0x19,0xa4,0x1c,0x1c,0x07,0xca,0x41,0xe8,0x2a,0xcb,0xa6,0x2f,0xb0,0xa7,0xc8,0x2a,0xed,0x80,0x0c,},"\xbf\x52\x52\xb2\xae\xca\x11\x63\x77\x1f\x76\x62\x78\x76\x80\x66\xf2\x19\x71\x35\x7e\xa7\x99\x61\x58\xa8\xd6\xe9\x08\xdd\x59\xb5\x99\x71\x34\x9f\xa1\x78\x82\xcb\x92\x24\xb9\x72\xd0\xff\xab\xe8\x55\x10\xdc\xf2\x5a\x9f\x9f\x9b\xde\xfa\xd2\xf4\xca\xdf\xbb\xda\xcc\x1f\xca\x9d\x94\x8c\xb5\x41\x2f\x47\x4c\xad\x23\xb5\xb9\x19\x9b\xf3\xc7\x37\x06\x41\x33\x9b\x75\x0e\x1f\x78\xc2\xad\xb4\x60\xaa\x5b\x21\xb1\xfa\x8f\x97\x71\x4a\xbb\x4e\xd5\xe9\xcb\x51\xd6\xde\x55\x81\x66\x18\xab\xd3\xfd\x2b\x28\x6b\xc1\x1c\x67\xba\x01\x12\x93\x73\xd4\x35\xb3\xe7\xe3\x91\xba\x37\x26\x14\xda\x83\x22\x87\x5e\x46\xa6\x75\xb6\x45\x15\x60\x24\xca\xd2\xdd\x13\xf9\xa0\x81\x61\x6b\xf1\x31\xa2\x43\x58\x89\x4e\x0e\xfa\x1d\x56\x64\x8f\xfb\x42\xef\xb5\x40\x31\xda\x7f\x37\xd1\x97\x61\x51\x55\xae\xdb\x69\xc4\xe7\x09\xc8\xbb\xbe\x7f\xbf\xcb\x59\x83\x47\xac\x5d\x0c\x63\x84\x07\x84\x7b\x28\x1c\xf1\x16\x43\x30\x97\xf5\x66\x21\x58\x71\x9f\xcd\xd3\x7b\xeb\x48\x92\x68\xce\x71\xde\x7d\x70\xed\x92\x5f\x74\x3f\xc6\x3a\x71\x5f\x7e\xee\x75\x49\xfd\xb9\x09\xcc\x45\x4c\x98\x8b\x30\xae\x4d\x77\xd6\x2f\x65\xa0\x7e\x2c\x8f\x93\x62\x38\x5d\x02\x8a\x60\x31\x08\xc9\x45\x87\x2f\x5e\x1a\x97\x41\x98\x78\xed\x49\x54\x2e\x28\x8e\xf0\x7b\x5c\x90\xf5\xc4\x15\x9e\x16\x23\x03\xd0\x80\xf6\xac\x2b\x05\x8d\xdc\xac\x60\x74\x6f\x9e\x1c\x9e\xc1\xdf\x8e\xda\x42\xd6\x27\x38\x58\x6d\x3f\xdd\x65\xdf\x55\xf4\x37\x4f\x32\x94\xe0\x86\x8d\x41\xef\x0b\xb1\xfd\x55\xe0\xcb\xf1\x95\xbb\xfc\xfc\xde\x5b\xdb\x41\xfa\xd9\xa0\x47\x7e\x4c\x90\xca\x27\xfa\x8c\xf5\x03\x36\x2a\x33\xfd\xec\xa5\xa4\xf0\xff\xea\x26\xe8\xd7\xe1\x34\xfa\xd3\xb1\xec\x3d\x05\x60\x55\xbb\xa5\xe6\x5d\x81\x15\x3e\xe8\x31\x87\x3b\x93\x8d\xf7\xd2\xc8\x3c\x2a\x52\xb3\xc2\x21\x82\x7f\x96\x1b\xd0\x08\x36\x22\x32\xd8\x82\xa0\x41\x2a\x04\x7a\xfd\xfb\x85\x97\xc8\x65\xa2\xaa\x2c\x2c\xf5\x18\x99\x34\xa8\x3e\xe6\xb7\x52\xa6\x26\x94\x1e\xdc\xe0\xc2\x0b\x6f\x7a\x69\xf1\xcf\x12\xf9\xa3\x31\xcd\xfa\x9e\xda\x24\xc8\xde\xfa\x76\x9c\xcc\xe2\xef\x74\x6c\x30\x7d\x8b\xb0\x48\x91\xfc\xef\xd4\x9a\xf3\xe6\xf9\x69\x91\xa7\xa2\x0f\x27\xb6\xc0\xaf\x12\x18\xbe\x31\x79\x1d\x1d\x02\x93\xe0\x81\xb9\x0a\xf3\xb9\x2e\xcb\x17\x5e\xc8\xc7\x89\xf7\xa8\x64\x2e\x04\x1e\xc3\xa6\x1a\xae\xfe\xf6\x2a\x80\x7d\x1a\x50\x54\xad\xf8\x32\x3b\xed\x94\x22\x41\x62\x37\x32\xa2\x05\x1d\xc0\x1f\x9a\x20\xa2\x9a\xa4\x8b\x3f\xdf\x26\x5d\x0b\xa6\xc1\x38\xfb\x57\x93\xe2\x87\x50\x02\xe7\xde\x3f\x5c\x3f\xf7\xe8\x3a\xd2\x7d\x11\x1c\x84\x8b\x7e\x6e\x2e\x5a\xd5\xf2\x8e\xb7\xc3\x63\xf9\x5f\x96\x0c\xbc\x42\x13\x36\xce\x98\x5f\x94\x6b\x05\x15\xb1\xbd\xd3\xa8\x32\xc3\xfe\x90\x3f\x7b\x44\xe2\x0c\x92\xea\x80\x82\x6f\xbf\x97\xe2\xa4\xfc\xaf\x2d\xb1\xa0\x86\x98\xdd\x62\xed\xd0\xa8\x45\x89\xd7\x46\x2c\x44\x7b\x4a\x89\x6f\xe0\x08\x60\x04\x24\x96\xbd\x51\xb1\x92\x5c\xb7\x9c\xc3\xb8\x29\x01\x6a\x4c\x7e\x62\x79\x0f\x80\x58\xc5\x46\xf2\x14\x5a\xaa\xef\x4d\x4b\x1e\x27\x3f\xf6\x13\x00\xf8\x00\x8e\x94\x6b\x62\x2f\x60\xe5\x05\xf5\xf6\x29\x0d\x51\xeb\x99\x7d\x20\xfc\x3f\xbb\x3e\x99\xed\xd6\x8f\xf5\xcc\xe9\xe8\xc2\x83\x88\x1c\x36\x4f\xf2\x15\xcb\x50\x04\x5e\x60\xf4\xa7\xee\x45\xb6\xc9\xd8\x64\x47\xf3\x81\x41\xd3\x42\xdb\xc5\x30\x8f\x8c\x66\xef\xc4\x7f\x7c\x45\xf6\xd2\x5e\x65\x64\x30\x9a\x86\x2d\xb9\x0f\x4d\xf3\x31\x78\x7e\xcd\xd8\x9d\x3a\xaa\x46\x05\x3e\x29\xf1\x02\x62\x4d\xdf\xe8\x0e\x8a\x3f\x99\x28\x7c\xec\x19\xfa\x83\xe4\x4d\x55\x7c\x04\x41"}, -{{0x5d,0x66,0xce,0xb7,0xc6,0xe5,0x8c,0xac,0x91,0xe2,0x88,0x27,0x91,0x70,0xe8,0x18,0xe7,0x87,0x18,0x0c,0x6b,0x42,0xdf,0xa1,0x68,0x78,0x7d,0xd0,0x7f,0x80,0x9f,0xa4,},{0xef,0xc9,0xb3,0x5d,0xb8,0x1f,0x34,0x61,0x98,0xa7,0xac,0xc6,0x9f,0x65,0xfd,0xfb,0xf4,0xc2,0x2e,0x68,0xdd,0x76,0x12,0xe3,0xb8,0xec,0x68,0xd3,0x78,0x55,0x3b,0x8d,},{0x6e,0xf2,0x64,0xab,0xf8,0xb0,0xe5,0xc2,0xd7,0x93,0xb2,0xc7,0x52,0x79,0x61,0x4a,0x39,0xc7,0x75,0xeb,0x2b,0xcc,0x08,0x91,0x06,0x7a,0xbc,0x61,0xf6,0xd6,0x44,0xa6,0x9f,0xf8,0xf8,0x14,0xa3,0x05,0x22,0xcc,0xa9,0x05,0x36,0xf0,0x12,0xc6,0x28,0x3a,0x76,0xc3,0x2b,0x89,0xee,0xe1,0xbd,0x9a,0x43,0x36,0xf4,0xfd,0xda,0xc8,0xdc,0x0b,},"\x94\xd7\x2f\x6d\xec\x4f\x7c\x92\x06\xb4\x15\x10\xce\x71\xa0\x29\x55\x60\x4f\x3c\x5d\xe8\xe4\x47\xd5\x87\x18\x65\xa7\x58\x98\xa4\xd2\x07\xa2\x6c\xf3\x3d\x10\xca\xf0\x5a\x0b\x6e\xd0\xd3\x89\xfe\xe9\xed\x49\x27\x50\x98\xa8\x8e\x1c\x0d\x83\x04\xe8\x1b\x40\x74\x21\x4c\x7a\x5c\xe1\x57\xeb\x26\x17\xef\x04\xe1\x32\x4b\xa9\x42\x12\x9f\xaf\x32\xc3\x1c\xb4\xaa\xe4\xa5\x91\x6c\x75\x08\x08\x72\x68\x56\xf7\x18\x0e\x57\x97\xed\xe4\x43\x62\xd7\x47\xd7\x0c\xec\x15\x9d\x3b\x6a\xce\xc6\x3a\x51\x4c\x7e\xf3\x1b\x2e\xcd\x16\xdb\x7f\xe6\x8e\xa9\xc5\xea\xd9\xd8\x70\x92\x18\x00\x34\x8f\x69\x54\x12\xf3\x09\x3e\x61\x98\x5a\x31\xea\xdb\x79\xb5\x9d\x91\xdd\x9a\x37\xf8\xd4\xef\x7a\x5d\xdf\x22\x3d\x4b\x24\x77\x4c\x2e\x44\xe3\xf2\x71\xff\xb8\x50\x0d\x59\x53\x81\xb3\xdf\x2e\x8e\x6b\x79\xee\x65\x53\x5a\x51\x9a\x43\xea\xa5\xe5\x2b\x25\x6c\x26\x43\x30\x5e\x31\x70\xcb\xe5\x76\x06\xa0\x54\x5f\x85\x86\x56\x5c\xfb\x75\xbf\x5e\x95\x64\xc6\x2a\xf0\x5f\x15\xee\x6e\x62\xaf\xee\xf8\xc2\xc7\xa9\xda\xe2\x35\xc9\xed\xd1\xd7\xc2\x5c\xf4\x9a\xdc\x03\x3e\xe7\xb5\x83\xf5\x18\xbc\x16\x8e\xa4\x88\x36\xb5\x0f\xfe\xdd\x20\x32\xb3\xf6\x30\xcc\x56\xda\xad\xd5\x13\xeb\xda\x86\x48\x23\x61\x0f\xc6\x7a\x72\xb9\xa7\xd8\x11\x71\x05\xc1\xc7\x1d\x85\xa9\x6b\x1d\x27\xa4\x41\xfa\x1e\x7c\x6c\xf8\x02\x33\xa4\x9f\xe0\xe7\x6a\x40\x27\x8d\x06\xe3\x43\x47\xd8\x7b\xe7\x7b\x98\xde\xd5\xe2\xa3\xea\x1a\xfb\x13\xbe\xe1\xe6\xcd\x6c\xa6\x3b\xe5\x4f\xcf\x88\xa2\x0c\xcb\x7a\x9f\xc3\x24\xbf\x61\x43\x20\x1b\x44\x48\x3b\xcc\x96\x40\x33\xda\xb7\x1c\xf8\xf2\xa5\x91\xfc\x05\x0d\x57\x24\xe9\x5a\xa5\x0d\x32\x89\x6e\xec\x0f\x3b\x34\x31\x1d\x2a\x99\x34\xe9\xf8\x52\x97\x7e\x25\x3f\x15\x30\x4c\xae\x24\x16\xc2\xc4\xfc\xd8\xf1\xfe\xcc\x3f\x1f\x64\xbb\x79\x75\x99\x29\xab\xb0\xe8\xe8\xf5\xf7\x29\x3d\x69\x1a\xf2\x2a\xbd\x3b\x2a\x67\x70\xb0\xcf\x14\x46\x08\xf2\xd6\x2c\xc7\xe5\x2b\xfe\x33\x3b\x2e\xd2\xde\x39\xb9\x9a\xfd\x37\xe3\xac\xf0\x7e\xda\x37\xdd\xf0\xdf\x02\x9b\xff\x2e\xc2\x25\x44\xb6\x0b\xd7\xdb\x23\x8d\xf1\x97\x5f\xfa\x00\x75\xa8\x2a\xbd\x8d\x6b\x05\xb2\x67\x18\x0b\x87\x0e\x21\xab\xf3\x69\x81\xae\x77\x68\xde\x53\x99\x3b\x30\x4f\x1c\x54\x53\x87\x2f\xdf\xa8\xed\xad\x45\xf8\x00\x1a\xa0\xe7\x34\x2b\x3b\x58\xec\x0f\x38\x9d\xcb\xc2\x71\xfb\x0f\x90\x00\x62\x87\x57\xab\xba\x58\xc0\x57\xe1\xa0\x89\x9f\x6f\xaf\x15\xf3\x74\x0f\x31\x43\xf5\xc0\xb7\xa9\x15\x96\x80\xde\x8c\x55\x72\x66\x44\x1b\x3b\x01\xca\xac\x12\xec\x27\x8f\x5a\x10\x25\xdf\x53\xed\xb6\x13\x4c\x96\x66\x3a\x96\x66\xae\x3b\xaa\x90\xfc\x83\x51\x11\xef\x05\x1b\xd9\x12\xf6\x79\x67\x44\x91\x13\xb6\xa8\x5f\x71\xdf\x8c\x60\x37\x72\x4e\xb8\xfc\x7d\x83\x19\xbc\x03\x85\xbe\x9b\x0e\x99\xe9\x5f\x9a\xed\xca\xe8\xd4\x5a\x51\x44\x76\xf0\x5b\xcd\x72\x35\xc0\x13\xeb\xc3\xae\xa9\x12\x3c\x67\xaa\x6f\x3b\x79\xc8\x5e\xa5\xdb\x15\x9e\xef\xad\xfb\x75\xa5\x0a\xc6\xb9\x5b\x49\x6b\x55\x72\x58\x1a\x76\x11\x2f\xf6\xdb\x26\x3f\xc1\x4c\x58\x18\xaa\xd5\xbc\xa3\xb2\xcb\x3a\xc8\x11\x6d\x42\x94\x82\x78\x1e\x06\xf6\x1e\x75\x63\xe6\x50\x5e\x51\xc8\xff\x99\x8b\xf8\x4a\xed\xb5\x20\x2e\x2f\x9f\xf4\xc2\x68\x98\x20\x29\x6c\xc6\x96\x03\x09\x1b\x8b\x81\x8f\xbe\xb2\xaf\x5f\x4c\x57\x06\x0d\x98\xc1\xa9\x04\x84\x3a\x70\xbf\x97\x5b\x3c\x3c\xa6\x03\x1a\x4c\xad\x5b\x4b\xbf\xba\x7e\x9b\x47\x49\x1a\xb7\x40\xd9\xeb\xe4\x1d\x76\x88\x10\xcb\x8c\xc5\x1a\x93\x7f\x7e\x3b\x22\xe3\xcf\x07\xce\xae\x0c\xe2\x08\x31\x49\x5a\xfc\xdd\x8c\x1a\x98"}, -{{0x62,0xed,0x86,0x82,0xbd,0x3a,0xb3,0x96,0x6e,0xba,0x3b,0xff,0xb7,0x75,0xa3,0x18,0xa0,0x3d,0x99,0x93,0x19,0x79,0xe9,0x9f,0xeb,0x2d,0xdb,0xd6,0x94,0x55,0xa0,0xef,},{0xd3,0x2a,0xda,0x17,0x8b,0x3e,0xc7,0x70,0x0c,0x47,0xdd,0x6d,0x36,0x53,0x22,0x03,0x3f,0xe4,0x31,0xc3,0x02,0xb4,0x6f,0x8d,0x58,0x79,0x8e,0xd8,0x33,0x71,0x56,0x6b,},{0x3d,0xa8,0xd1,0x4d,0xc4,0xe7,0x1f,0xe6,0xc3,0x2e,0xde,0x46,0x37,0x88,0xe4,0x1b,0x82,0x6b,0x4e,0x21,0x60,0xba,0x10,0xc9,0x5f,0x1c,0x8a,0x27,0x49,0xaa,0xd8,0xf1,0x2e,0x98,0xae,0x24,0x68,0x30,0x3b,0xaf,0x69,0x08,0xbd,0xb3,0x5e,0xf3,0x8a,0x5e,0xcd,0x77,0x74,0x1e,0x72,0xee,0x3a,0x42,0x7f,0xd9,0x04,0xda,0xe6,0x6f,0xcf,0x03,},"\x9e\xb1\x3b\xc7\xfa\xcf\x51\xa1\x80\x54\x1e\xc1\xdc\x5f\x5a\xcb\x14\x8c\x8d\x5e\xad\xcd\x2c\x4e\xf0\x68\xbc\xdd\x11\xb3\x49\x25\xea\xbf\xaf\xab\xfe\x82\xa2\x84\xbc\xba\xee\x13\x81\x15\x2a\xf8\xe5\xe0\x9f\x03\x7c\xf1\xbb\x64\x84\xac\x18\xe3\x73\x59\xbf\xaa\x4c\x87\xaa\x07\xd3\xd1\x4e\xd0\x89\xb0\x53\x91\x0d\x1f\xa4\x73\xf7\xbc\xe1\x43\xe2\xa5\x9c\x4d\xaf\x99\xb6\xc6\xe4\xe9\x29\x1d\x97\xc8\x64\x71\x2a\xf3\xea\xba\x53\xce\x25\x17\xa4\xf7\x5c\xd7\xec\xf2\x78\xf3\x4e\x22\xb7\xdf\xfd\x08\x8f\xa5\xec\xad\xc0\xdd\x22\x13\x5e\x42\xa5\x36\xc6\x84\xf2\x19\x5d\x31\x5f\x69\x24\x57\x1e\x46\x3f\x5c\xfc\x11\xb9\xf9\xd0\x5a\x7e\xa1\x1b\x98\xa1\x69\xa1\xe3\x93\x60\x97\x3c\x50\xad\x45\xc7\x49\x1b\x57\x13\x8e\xc0\x50\xf4\x3c\xbd\x5d\x17\xeb\x3f\xe0\x01\x3e\x3d\x28\xd5\x26\x05\x4e\x07\x63\x31\x52\x24\x6f\x16\x55\x4f\x30\x54\x74\x9e\xea\x68\x7b\x9c\x37\x1b\x40\x9c\xd3\xec\xef\xb1\x11\xa1\xd6\x00\x40\x73\x44\xe6\xd6\xec\x38\xc6\x0f\x6e\x54\x5a\x92\x38\x2e\x46\xc4\xd1\x13\x12\x5d\xbe\x5b\x98\x26\xe1\x27\xf1\x01\x81\xa3\x5a\xcf\xff\x28\xab\x37\x64\xca\x7f\x23\x8f\xf4\x79\xfd\xbc\x45\xb7\xa2\xad\x0f\xf5\x38\xc8\xac\xd0\x01\x8d\x44\x70\xfe\xbc\xc6\xa3\x07\x65\x1c\xb5\x83\x2f\x32\x6b\x19\x24\x1b\xe9\x86\x7e\x4e\xca\x6a\xe3\x6f\x0e\x2d\x83\xfd\x77\xb9\x72\x02\xb3\x64\x71\x6e\x36\xd1\x89\x5a\x36\x85\x3e\x7e\x76\xe8\x8f\x62\xdb\xbf\x77\x26\xc2\x18\x05\x69\xc6\x66\x73\x83\x7a\xd7\x2f\xf9\x36\xcf\x0e\x2f\xdb\x9e\xc6\xaf\xcc\x79\xf8\x82\x9e\x15\x7f\x95\x22\x88\xf4\xe0\x0d\x04\x10\xa7\x22\x53\xbf\x60\x5e\xdd\xce\xb0\x14\x40\xde\xe5\xdd\x32\xb5\xa8\x03\x43\x9f\x03\x8c\x06\xaf\x1c\x90\xb2\x7b\x5f\xe9\x84\x3c\x27\xae\x76\x60\x9c\xbf\x83\x28\x35\xc0\xe3\xc4\xbb\x59\x97\x6c\xce\xde\x44\x87\x86\xd9\x1e\x43\x8e\x07\x75\xc0\x6a\x92\xd0\xf0\xb8\xdc\x0e\xf6\x82\x60\xf7\xdd\x9e\x68\x71\xc4\xd0\xc0\xc0\x94\x63\x85\x26\x15\x21\x85\x16\xf4\xa6\xde\xbf\xdb\x46\x27\x3b\x28\x33\x82\xcd\x9c\xa7\x44\xab\xf9\xfd\x43\x91\x94\xb8\xcf\x1b\xdb\xb3\x17\x5c\xa9\xc5\x7a\x1c\x37\x3c\x41\xfc\xe9\x2b\xd5\xfc\x01\x2b\x19\xa0\x69\x8a\xef\x37\xba\xf8\x06\xae\x09\xad\xd8\xcb\x97\x2a\x9e\xf9\xa7\xa5\xa9\xb1\xfd\x9a\x41\xd8\x54\xc3\x0c\xca\x13\x96\x14\x0e\x20\xc2\xb9\x86\x54\xfe\x6e\x51\x1b\x62\x6a\x43\x91\x5b\x22\xfb\x2d\xad\x74\x7b\xa7\xfe\x74\x60\xd8\xce\xbb\x20\x06\xfe\xa1\x9b\x32\x84\xb0\x9c\x06\xa6\xf5\x2f\x17\x9a\x32\xbe\xb5\x63\x57\xb9\x29\xa6\x59\xf0\xfe\x6a\x26\xb6\x97\x03\x3d\xef\x58\xba\x60\x3f\x43\x0f\x74\xaa\x35\x07\x09\x81\xdb\x74\xcc\xf1\x91\x90\xa1\xfb\x05\x14\x4e\xc0\xa0\x9a\x51\xe5\x47\x65\x06\x97\x30\xb0\x9a\x7a\x23\x31\xff\xb3\xde\x2a\x7e\x02\xc5\xe1\x84\xda\x40\x13\xdf\xe9\x37\xc3\x71\x11\x75\x24\xf7\xb2\x10\xba\x60\xe2\x69\x2d\xcd\xce\xf3\x6a\xb2\x27\xb4\xc4\xf0\x2a\x9f\x48\x89\x72\xb8\x47\xf0\xd6\xb5\x9d\x02\xee\x54\xfe\xde\x88\x21\xdb\x6c\xf7\x31\xcc\x8a\xc8\x95\x35\x0a\xc5\xcd\x4d\x6b\xaa\x3a\xd0\x36\xf0\x6f\x20\xd1\x0a\x14\x0c\x4a\xd3\xd1\x0c\xa9\x85\x53\x2e\x31\x60\x46\x27\x73\x38\x5a\x2e\xb5\xe4\x64\xd5\x28\xe1\xe5\x9c\x29\xf6\x6b\x3d\xe5\x9e\x9e\xa2\x8a\xf3\xf9\x7b\xfc\x55\x89\x03\x57\x52\xa5\xa5\x52\x3d\xec\xd2\xdf\xf0\x1f\xc0\x0f\xf3\x1b\x30\x15\x2f\xf5\xda\xfa\x33\x1c\x6a\xb1\x58\x73\xaf\x41\xaa\x96\x0a\xac\xe7\xd2\xcb\x4f\x95\xc2\x3d\xf4\x4b\x9e\x6c\x6e\x2f\x86\x78\x8a\x87\x2f\xd3\xa5\xcb\xe4\xac\xc9\x58\x10\xda\xa0\x9d\xcc\x1d\xf9\x33\x46\x5e\xf0\x40\xc5\x3d\x9d\x95\x9f\x9d\xad"}, -{{0x4e,0x57,0xf0,0x31,0x1f,0xff,0x0e,0x5d,0x53,0x88,0x49,0xb1,0x21,0x6f,0x69,0x5b,0x1a,0x52,0x77,0x94,0x17,0x08,0x20,0x4d,0xb2,0xf0,0xc1,0x5b,0x3c,0x73,0xc8,0x2a,},{0xe3,0x37,0x1f,0xe2,0x36,0xad,0x2f,0x6f,0x42,0xf9,0xe1,0xfa,0x4e,0x1e,0xda,0x2c,0x3e,0x29,0xc3,0x6c,0x8a,0xd2,0x21,0x8a,0x3c,0x03,0x79,0x82,0xf0,0xb5,0x79,0xec,},{0x4f,0xdc,0x7b,0x6e,0x28,0x27,0xf6,0x4b,0xa3,0xc0,0x33,0xc7,0xfb,0x6d,0x1b,0x35,0xdd,0x68,0x0f,0x53,0x29,0x99,0xa0,0xd7,0x7a,0xeb,0x27,0x6c,0x31,0xbd,0x9e,0x39,0xc6,0x70,0x97,0x8b,0xe4,0x72,0x43,0xc1,0x13,0x22,0x3a,0x57,0xaa,0x10,0x23,0x31,0x50,0x67,0x8b,0x40,0xdb,0x78,0x59,0x1c,0x04,0xd0,0x8d,0xf5,0x7a,0x70,0xa2,0x09,},"\x05\x2a\x1f\x41\xeb\xfd\x4b\xf6\x5e\xfb\x0e\xc8\xe7\x4d\xd7\xb3\x06\x5e\x9c\x48\x2c\x49\xb9\x92\x62\xe6\xdf\xa8\x40\x7d\x9e\x31\xed\x34\xd2\x29\xba\x41\xfc\x49\xa9\x4a\x13\x09\xf9\x90\xa9\x9c\xb9\x90\x2f\xb8\x4f\x4e\xde\x91\xbb\x64\x71\x45\x64\xa9\x13\xd5\x74\xd4\xa3\xc2\x86\xf0\xa1\x92\xa7\x8c\xe2\xd5\x5a\xae\x5c\x9f\xb0\x57\xff\x36\x12\x00\x18\xb2\xa8\xb5\x4d\x98\x08\x55\x37\xea\x64\xae\xa9\x99\xd5\x32\x1c\x78\x80\xb3\x6a\xb4\x30\x18\xea\x2c\x92\xa5\xe6\x83\x50\xd3\xde\x85\x26\xe2\xc8\xbc\x91\x41\xf4\x34\x9a\x18\xa3\x4f\x21\xde\x0a\xbb\xf2\x93\x09\x87\x56\x7f\x0a\xaf\x8e\xb1\x91\x45\x58\x0d\x71\x30\x6c\xe8\xa6\x9e\x79\xf8\xee\xa2\x6c\xfa\x0b\x8b\xeb\x49\xcc\x5a\xa2\xbc\x77\xb7\x97\xd4\xf8\xd5\x03\x26\xff\xb9\x37\x39\x9e\x94\xfd\xec\x85\xe1\x92\xf1\x27\x2a\x80\xe9\xa0\xeb\xba\xf5\xd0\x1f\x1b\x97\x06\x08\x02\xbd\x4a\xf3\x4c\x0f\x7d\x7e\x98\x54\x3f\x9d\x66\xd6\x0e\x0e\x6b\xc0\xbf\x9c\x99\x0b\xe3\x1e\xea\x19\x78\xff\xd1\x67\x33\xa8\xab\xe4\x95\x58\xb3\xad\xd0\xdc\xe6\xde\xfd\x64\xdc\x04\x3f\x15\x19\xb1\xe9\xbe\x66\xe0\x6e\x41\xec\xab\x16\x8c\x83\x39\xa8\x5e\x0b\x91\x38\x18\x64\x4e\xa7\xc5\x33\x44\x68\xfd\x71\x96\xa0\x1e\x1d\x4c\xe8\xdd\x1e\x7e\xe3\x13\xdd\x53\x50\xb8\xdc\xe4\xf5\xd7\xa6\xac\x09\x85\x7c\x4d\x3d\x0f\x10\xa3\xd9\x06\x26\x09\x75\x45\x92\xad\x10\x77\xb2\xe2\x09\x6f\xc9\xe5\xb1\x97\x8c\x98\xb5\x66\x0d\xdf\x51\xb4\x6e\xde\x9f\x9d\xcd\x41\xb2\xef\x44\xe7\x9f\x6d\xaf\xf7\xd3\x62\x68\x70\xe2\x24\x3c\xaf\xb2\xf4\x36\x79\x39\x10\x9e\xd9\xc0\x14\x84\xb7\x9e\xaa\x30\xa1\x89\x1e\xa1\x8f\x98\x4e\x16\x1d\xcd\xd1\xbd\xa3\x71\x34\xbf\x67\x35\xd2\xb2\x14\x9b\x48\x98\xda\xcb\xfd\xa6\x1e\x60\x02\xd7\x2a\x6f\xc5\xd2\x1f\x10\x98\x21\x32\x31\x13\x2d\x56\xdf\x68\xd6\xa9\xbf\xdf\x4e\xdd\xc0\x52\x4d\xb8\xfd\x8f\x24\x88\x52\x04\x9a\x68\x25\xa5\xed\xd2\x36\x0c\x00\x9a\xf2\x4f\x0a\x94\xc5\x07\x9d\xdf\x6f\xe7\x96\x94\x5f\xf9\x84\xaa\xc3\x64\x11\xce\x80\xd9\x87\xc6\xed\x67\xb6\xb0\xdd\xb6\xd4\x17\xf6\xe8\x09\x99\x1e\x72\x9d\x14\x7d\xd0\xd2\x1a\x09\x32\x41\x36\x3c\xf4\xef\x3b\x8e\x3b\xa0\x2d\x48\x66\x33\xb6\xb2\x17\xf5\x49\x3e\x2e\x43\x2b\x8c\x2e\x27\xd0\x0c\x5b\x56\xc9\xb6\x5f\x9a\xed\x49\xce\x93\xd7\x7e\x7d\x0b\xf5\xf9\x2f\x92\xf5\xbb\x4b\x59\x5d\x66\xf8\x87\xa4\x88\x01\x33\xf9\x70\x46\x3a\xb8\xb7\xf3\xd8\xc7\x94\xc0\x40\x6e\x88\xe3\xea\xb9\xae\x65\xf1\xa1\x85\xd6\xe3\x9e\x2d\xd6\xab\xb8\xa9\x3d\x2a\xc4\xb9\x20\x83\x98\xda\xb8\x9d\xbc\x07\xa4\x1a\x50\x26\x40\x26\x41\x2d\xa0\x22\xb5\x8f\x48\x9d\x4d\xba\x31\xfb\x88\x2f\xec\xb1\xff\x8c\xa1\x82\x0d\xda\x18\x65\xaf\x15\x51\xe4\x6c\xd6\x18\xb4\x4c\x4e\x6e\xb3\x03\x7a\x93\x33\xfd\xcc\xef\x4b\x89\x51\x89\xe4\x39\x0e\x93\x14\x5d\x26\x4c\xa5\xf4\x52\x02\xa3\xeb\x28\x53\x59\x3f\xee\xd6\xc6\x6d\xbb\x28\x8f\xf3\xa3\xc0\xfa\x83\x2b\x2a\xa7\xe5\x29\xb5\x56\x88\x97\xb3\x14\x94\x02\xa9\x07\xe7\x41\xe1\x01\x1c\xe0\x73\x1c\x91\x5f\x91\x44\x6a\xa0\xd5\xca\xf0\x59\x5f\x18\x16\x43\x4f\xa4\x57\x6d\xb3\xbc\x31\xe1\x0c\xc2\xaf\x33\xf6\x13\xf0\x3c\xa7\xb9\x49\x1a\x0a\x34\x05\x25\x27\x1a\xb5\x37\xf6\x2a\x11\xa8\x4d\xa0\x1c\x7f\x55\x81\xad\x57\x38\xc3\x72\xb5\x33\x5b\xab\x9b\x2b\x9d\xc2\xfe\x91\xe9\x33\x30\x4d\x94\x01\xba\x8e\x1c\xe8\xdc\x55\xc4\xfb\x46\x6b\x3a\x8e\xd7\xf5\x3a\x12\x2b\x83\x81\xd8\xf2\x90\x47\xd7\x26\x4d\x06\xfb\x51\xec\x3e\x70\x07\x1f\x27\x36\xa4\xe7\xe1\x53\x7a\x52\xfa\x25\x6a\x04\xee\x86\xfa\xd2\x7a\xd2\xd2\x8a\x9b\x36\x29"}, -{{0x39,0xf0,0x55,0x6b,0x1c,0x5d,0xca,0xb3,0x87,0x10,0x41,0x81,0xbb,0x30,0x4d,0xe0,0xcf,0x81,0x59,0x20,0xb9,0x72,0xe8,0x71,0xd5,0xf0,0xfb,0x41,0x6d,0x8e,0x61,0x6a,},{0xd8,0x5f,0xb7,0x6e,0x78,0xc3,0xd5,0xbb,0x7c,0xa6,0xb0,0x5b,0x31,0x01,0x91,0x82,0x1a,0x4a,0x7d,0x2d,0x9b,0xdf,0x02,0x29,0x2c,0xc7,0xae,0xa5,0x64,0x2e,0x48,0x19,},{0x01,0x66,0xaf,0xed,0x5a,0x8f,0x7c,0x3f,0x7a,0xd6,0xf3,0xfd,0xd2,0x93,0x8e,0xff,0x00,0x89,0x8e,0xab,0x81,0x5c,0x54,0x55,0xac,0x90,0xfb,0x51,0xf6,0xe1,0x85,0x4f,0x0c,0x07,0x53,0x19,0x4b,0x76,0x29,0x59,0x4c,0xc1,0x27,0x1b,0x00,0x34,0x31,0x22,0x1c,0x57,0x4b,0x0c,0x0d,0x19,0x08,0x2f,0xee,0xda,0x51,0xb0,0x84,0xae,0x5e,0x03,},"\xa8\xd0\x34\xe1\x70\xfc\x22\xb5\x7a\x44\xaa\x62\x69\xed\x1f\x01\xcb\xa8\x01\xf3\x98\xdf\x1a\xdf\xe7\xdf\x04\x4d\x5f\xa4\x68\xbb\xfa\x8a\xf4\x74\x9a\xb5\x0d\x24\xd6\x2e\x31\x3a\xc0\xe7\x3a\x64\xb4\x28\x2b\x74\x62\x6a\xf2\xb4\xa4\xb5\x4c\x27\x4e\x5a\x6b\xc2\x80\xb6\xdc\x25\xdc\xfe\x07\x81\x4c\x9c\x81\x6d\x2f\x9e\x36\xc0\x5b\x9b\xfe\xdf\xf7\xc6\xb0\x3c\xdd\xeb\xd4\x73\x5e\x09\x93\xd3\xc3\xfd\xc6\x54\x04\x43\xc6\x00\x5e\x90\x0b\x40\x35\xe1\x40\x8a\x85\x01\x6a\xa1\xb8\x92\x02\x99\x0e\x5d\x84\xed\x99\x81\xc2\x9b\x77\x20\x6d\x7c\x11\x30\x52\xa2\x02\x98\x12\xc6\xea\x13\xaa\xe8\xbe\x0a\xca\x7a\x33\x06\xbf\x61\x72\x42\x29\x8e\x68\xbe\xcd\x0d\x5d\x16\xc8\x88\x7f\xd1\x95\x0b\x77\x85\xa4\x6b\xb0\x22\xb3\x9f\x76\x07\xcd\x89\x13\x71\x8b\x30\x17\xfc\x3f\x86\xd6\x93\x3f\x75\xee\xc5\x19\x1a\xd1\xf1\x98\x9a\x8d\x26\x17\x86\xf5\x6b\xe4\xa9\x88\x37\x0d\xb8\x29\x61\xa9\xfc\xc9\x53\x54\x2e\x51\xc2\xe0\x86\xdb\x0e\x02\xb4\xfc\x34\x66\x94\xab\xd9\x05\x9d\x5b\x11\x72\x26\x47\x66\x9e\x7f\x17\xb7\x45\xa6\x0b\x02\xf7\x33\x9f\xcc\x99\xbc\x35\xd5\x9f\xd0\xb9\x8b\x60\xc3\x14\xab\xd4\xbf\x8a\xa4\xb7\xea\xe0\x9d\xd0\x09\x7a\xcb\x91\x89\xf0\x2c\xf8\x5a\x25\x1a\xc9\x2a\xaf\x69\x1b\x15\xcd\x4a\x33\xb5\x8d\x76\x63\xab\xd0\xb0\x44\x43\x33\x04\x4a\xf5\xce\x20\xfd\x71\xcb\xaf\xfc\x0d\x29\x83\x58\x19\xf4\x92\x93\xfc\x26\xe7\xf9\x78\x7f\xc3\x68\xc4\xd3\x5c\xae\x92\x74\x7f\x21\xca\x1f\x3e\xfd\x87\xa0\xd8\x10\x41\x99\x41\x64\x82\xd0\x7b\xfe\xc1\x28\x1c\x66\xf5\x65\x28\x5b\xf6\x72\xd5\xe7\x48\x64\x00\x66\x0c\x01\x75\x55\xe9\xfa\x2b\xf6\xa4\xe7\x02\x7f\x0e\x7e\x5f\x44\x3e\xd6\x58\xb7\x5b\x59\x06\x12\xab\xde\x0d\x80\xd1\xa2\x6c\xb8\xbd\xe7\x6b\x99\x6e\xff\x6a\x74\xe3\xda\xfc\x59\xeb\x1b\x58\x4f\x45\x97\xa2\x39\xcd\x83\x9f\xa1\xf1\xb7\xbd\xa1\xa2\x4d\x15\x0c\x4e\x24\xb9\x1c\xec\x01\xee\x53\xa3\xac\x85\x2a\x91\x2d\xe1\x95\xa3\xc2\x9d\xd7\x07\x9a\xa7\xe8\x8a\xa8\x1e\x9d\x31\xb8\xfc\xcd\x43\x5e\xda\x11\x3c\x3f\x82\x45\x8b\x7f\x79\x33\x57\x2b\x77\x67\x53\xc9\x22\x40\xcc\x03\x61\x58\xa4\xba\x0e\x56\xef\xed\x53\xec\xb5\x3f\xc0\x93\xfe\xad\x14\x34\x34\x85\xae\x5d\x91\x05\xbb\x16\x3f\x26\x25\x14\xe4\x8b\xe7\x41\x59\xc9\xfa\xbc\xb7\x1d\x1a\x42\x80\xd9\xed\x70\xd7\xe4\x2b\x75\xf7\xfd\xad\xd0\x2d\x69\x19\x8f\x5f\x46\x5b\xf6\x04\xcb\x42\x54\x41\x7b\xac\x37\x14\xb3\xa9\x9e\x6f\x1a\xce\xc9\xe3\xb3\xd0\x97\xf9\x72\xfb\xc3\x6f\x2e\xda\x39\x26\xd5\x61\x12\xd4\xe9\x09\x7d\x89\xbd\xc3\x59\x37\xb9\xa3\x15\x8e\x7c\xdd\x5d\xa4\x01\xe1\x80\xd3\xed\xe6\xb1\xff\x02\x86\x41\x92\xeb\x72\x97\x81\x53\x4f\x49\x64\xdd\xf2\xaf\x11\x80\x0d\x8b\x5b\x6d\x01\xb2\x09\xaa\x33\x69\x36\x6c\x19\xa2\x8c\x79\xa8\x7d\x21\x74\xec\x22\xfb\x14\x89\xa6\x75\x5c\x34\x8a\x99\x6d\x0a\xa5\x6e\x0f\x60\xd5\x8e\x26\xbe\xfa\x23\xa8\x6b\xef\x4e\x35\x29\x51\x2e\x30\xa9\xd1\xc5\xe4\x88\x50\x18\xcb\x97\xae\xb7\xc9\x3c\x5c\x41\xca\xa3\x42\x36\x57\x5c\x22\x6f\x3b\x23\x5e\xdd\xba\x36\x4e\x28\x5b\x6e\x35\x27\x07\xbb\xb3\xb3\x39\xbb\xf2\xa6\x3a\x9c\xb9\xbd\x33\x3a\x77\xe7\x9b\xd5\x8a\x48\xe1\x4c\xe5\x88\x6e\xd0\xcd\x07\xc2\xd1\x65\xa8\x1b\x5e\x6a\x31\xa8\xae\x78\x06\xbc\xf2\xe0\xc4\xec\x29\xa9\x67\x72\x5e\x57\x7f\x17\x41\xee\x68\xf3\x45\xf5\xf7\xab\x0f\xad\x31\xc8\xb4\xb1\x8b\x43\x1c\x49\x77\xd5\xc5\x84\x00\x4b\x45\xf7\xcd\x19\x61\xaf\xfe\x87\x38\xe2\x4c\x38\x26\x10\xef\xe9\x98\x35\x3d\x7e\xba\xf9\x19\xb2\x79\xbb\xb6\x91\xc3\x05\x2b\x8b\x2c\x5f\x09\x80\x8e\xf3\xa6"}, -{{0xba,0xb3,0xff,0x7a,0x44,0x48,0xd8,0xa0,0x3d,0x8a,0xcf,0xdb,0x91,0x3f,0x77,0xfe,0x77,0x80,0x43,0x95,0xc3,0xe5,0x4e,0xc2,0x35,0x11,0x79,0x27,0xe3,0x2b,0x50,0xd5,},{0x54,0x97,0x5e,0x35,0xe5,0xb1,0xd0,0x32,0x3f,0x2d,0x6f,0xb5,0xc6,0x15,0x8b,0xf6,0x65,0x4b,0x08,0x4f,0x76,0xbb,0xdc,0xfd,0x72,0x34,0x92,0x29,0xe8,0xe4,0xa6,0xe8,},{0xd6,0xb4,0x13,0x5f,0xc7,0xac,0xb3,0xd7,0xcd,0xf9,0x87,0x89,0x6d,0x91,0xb8,0xa9,0x0d,0xb5,0x84,0xd8,0x93,0x3a,0x6f,0x30,0x29,0xe3,0x26,0x1e,0xc1,0xc3,0x90,0xcb,0xac,0xfa,0xaf,0xef,0xf4,0x43,0xb6,0xda,0x4f,0xdb,0x1d,0x84,0xc6,0x4a,0x54,0x56,0x0f,0xef,0xfa,0x2f,0x1c,0x7a,0x91,0xbd,0xe9,0x73,0x02,0x22,0x92,0x3b,0x67,0x03,},"\xb6\x47\xb6\x7c\xf0\x1c\x2c\xac\xc3\x9d\xe5\x96\x9e\x19\x9b\xe6\xd9\x32\x01\x67\xa4\xce\xbb\xf1\x62\x59\x50\xb1\xe6\xb7\xad\xf5\xca\x24\xd1\x34\x95\x68\x86\x5f\xbb\xfd\x90\xf5\x13\xf0\x5f\x79\xf7\x0a\x63\xa2\x38\x73\xdc\x7a\x19\x5d\x4b\x28\x5a\x08\xf3\x0e\xe0\x61\xd0\xb8\xe6\xb4\xd6\xbf\x9b\x2e\xcf\x2c\x69\xf3\xd5\xa0\x7a\x67\x30\x53\x7c\xca\x4a\x4e\x4c\x7e\xe6\x84\x70\x2b\xff\x88\x3f\xab\x8b\xca\xf8\x93\x11\xc5\x49\x8b\xcc\xb5\xa0\xf7\xc8\xd4\x9b\x54\xf4\x82\xff\xfb\xca\x6e\x7d\xa2\x62\x45\x2b\xa5\x9a\x57\xa6\x87\x9d\x81\xb7\x3c\xd7\xad\xf7\x2a\x3b\xe2\x8a\x37\x3c\xd6\x33\x10\x40\x84\x61\xc2\x1b\x90\x7f\x63\xe0\x86\xb2\x92\xff\x02\x83\x3e\x8a\x2f\x46\xad\xbd\x67\x1d\x02\xb0\x3a\x69\xac\xa2\xe1\x1d\x28\x7c\x52\x2a\x95\x45\x20\x44\x2e\xce\xfa\xa9\x05\xdb\xfc\xc8\x25\x4c\x58\xc3\x95\x4a\x89\xbf\x56\xcb\xe0\x1a\xd5\x63\x19\x71\xeb\x39\xeb\x43\x2a\x85\x4e\x69\x19\x29\xdf\x7e\x48\xb9\x00\xca\x6e\x74\x0a\xcc\xf5\x78\xb3\x17\x95\xb4\x9a\x6c\xa7\x74\xbd\x8b\x99\x31\x06\xa9\xc4\x94\x8c\x18\x71\x49\x48\x31\x59\x90\xa5\xf1\x91\x69\x24\x20\xf2\x89\x32\x8a\xb7\x13\xec\x19\xb7\xea\x89\x4d\x16\xe6\x47\x61\x00\x87\x1c\xf3\x16\x8e\x4f\x93\x5b\x55\x05\xd1\xed\x5b\x0a\xa2\x9b\xe3\x6f\xa3\xa3\x46\xac\x3e\x76\xf1\x43\xc4\x6c\xa6\x91\x23\xb7\x9c\x36\x39\x9a\x0d\x2e\xd3\x02\x77\x24\x94\xad\xf4\x42\xbb\xaf\xbc\x4d\x01\x53\x26\x92\xc7\x85\x9d\xf0\x4d\x2c\xa7\x8b\xa5\x5d\x77\xfd\xf3\xe5\xad\x99\x37\x86\xa2\x4c\xff\x21\x99\xbb\x49\x38\x78\x73\xcc\x41\x4b\x4c\xf1\x13\x7a\xbb\x7e\x94\xae\x3d\xdb\xf9\x7f\x53\x4a\x18\xfc\x5a\xe5\x85\x23\xa3\xcc\x52\x28\x3d\xc7\xb0\x16\xf3\x1c\xd6\x55\x79\x81\xc5\x07\x6c\x77\x4f\x30\x3a\x47\xc4\x27\x87\x0e\x20\x7e\xd8\xbd\x66\x64\x0f\xf0\x92\xdb\x50\x3f\xa1\x24\xbf\xdc\xf0\x20\x05\x1d\xad\xd1\x06\xdd\x24\x58\x40\xb3\x19\x10\xb8\xa9\x06\x0d\x59\x86\xf0\x2b\x60\xaa\x5e\x33\xb4\xd7\x55\x09\x12\xcd\xc5\x77\x6c\x77\x2a\xac\x93\xae\x19\xc7\x3b\x7e\xcf\xca\x38\x9e\x62\x76\x81\xa8\x78\x1e\xb4\x7d\x84\xe9\x34\x60\xba\x89\x1d\x3f\xf6\xea\xdf\x8f\x2a\x90\x3c\x38\x34\x74\xbe\xaa\x42\xb9\x0e\x03\x22\x36\xdc\xd8\x98\xd0\x2a\x40\xef\xb4\x4e\x47\xea\xd5\x2b\x75\xb0\x9c\x7d\xa1\xcd\x6a\x2d\xfd\x4d\x1c\x04\x52\xde\x69\xf6\xac\xac\x1a\x68\xdd\x78\xda\xf9\x72\xae\x26\x08\x21\xe2\xec\x52\x2f\xb5\x74\x9b\xeb\xe0\xad\xb4\x52\xbf\xa4\xfa\xa1\xe9\x79\x11\xc1\x29\x9f\x16\x56\x8d\x68\xee\xf4\x05\xf4\xb1\xcd\xac\xab\xed\x59\xf7\xb0\xfb\xce\xab\x71\x9a\x34\xb2\x99\xf5\x8a\x4a\xe8\x15\x4f\x98\xf4\xd9\xf4\xf1\x40\xb1\xf0\x85\x00\x69\x46\x72\x5e\x7c\x29\xbb\x0b\xc6\xcc\xf2\x53\x44\x97\xc6\x1d\x4c\x16\x12\x62\x4a\x61\xd7\x0d\x26\xc3\xef\xb7\xd7\xc3\x51\x84\x86\x57\xf7\xf8\xee\xbf\x8b\x99\x07\x47\x74\x0e\x6f\x91\x0c\x97\xce\xf1\x50\x37\x57\x65\xc8\xc0\xb3\xb4\x49\xc0\xd0\x9d\x66\xf0\x08\xe6\x7c\xfa\x76\xea\x2b\x68\x08\xb6\xfe\x63\x2e\xaf\xe0\x58\x7f\x37\xe3\x6b\xe9\x8d\xcb\x17\xa3\xf4\xa1\x5b\x65\xa9\xf6\xfc\xf9\x64\x2b\x52\x52\x20\x77\xb1\xfb\x4c\xc3\xc0\x8d\xf4\xb4\x67\xca\x71\x6d\xb1\x6b\x73\x7f\x78\x2c\xdf\x38\x71\x70\xa5\xf1\xf6\xa7\xae\x0a\xb3\xf5\xb7\xc5\x85\xe3\xb0\x65\x5a\x64\x56\xa5\x03\x59\x5c\xe8\xea\xea\x25\x37\x85\x5e\x7f\x0d\x50\x61\xbc\x29\xb4\xe6\x7d\xaa\x82\x46\x3c\x19\x0e\x9f\xdd\xd5\x2f\x83\x22\xdd\xb4\xe0\xf2\x6b\x68\x77\x82\x28\xeb\x57\xe1\xa1\x85\xb7\x02\x5d\xa1\x49\x87\xd4\x4b\xaa\x76\x7b\x22\xee\x7f\x4c\x84\x59\x10\x32\xe8\x8e\xc1\x2e\xb8\xc5\xa4\xb9\xe1\x57\xec"}, -{{0x48,0x6c,0x7b,0x43,0x6c,0x1d,0x43,0xd6,0xb7,0x03,0x51,0x22,0x83,0xc1,0x66,0xdc,0x86,0x3e,0x5a,0x33,0x80,0x2f,0x4e,0xa6,0x5f,0xc7,0x38,0x77,0x89,0x02,0xd0,0x14,},{0xb5,0xdc,0x94,0x7d,0x64,0x33,0x7c,0xae,0x82,0x12,0x2b,0xd6,0x8c,0xc8,0x08,0x40,0x59,0x6d,0xe3,0xbe,0x56,0xcb,0xd0,0xc8,0x33,0xaf,0x3f,0xaa,0x3a,0xdc,0x37,0x76,},{0x31,0xf9,0x5c,0xbb,0x74,0x63,0xb8,0x75,0x28,0x65,0x42,0x27,0xbb,0x13,0x97,0xbf,0x10,0x65,0xb4,0xf5,0x76,0x80,0x80,0x78,0x20,0x7d,0xfa,0xf0,0x6d,0x12,0x4b,0x41,0xf4,0xc3,0x18,0xf4,0xa9,0x31,0x5a,0x66,0x08,0x5b,0x9e,0x56,0x8a,0x71,0xe4,0x14,0xed,0x94,0x14,0x51,0x73,0x10,0xc6,0x99,0x94,0x6d,0xb0,0xc9,0x76,0x28,0x52,0x07,},"\xaf\x03\x60\x53\x67\x2d\xcf\x3a\xa2\x6e\x28\xec\x6a\xa6\x42\xce\x28\x4b\x89\x6c\x69\x88\x7d\xfd\xcf\x08\x24\x51\x5e\xb0\x84\x8d\x9d\x97\x0c\xa2\x72\xdf\x77\xa8\x6b\x3f\xf6\xdd\xaf\x3c\xba\xdd\x3a\xb6\x28\x3b\xc3\x7c\xdf\x7a\x56\x07\xd5\xdf\xc7\xcf\x96\x32\x92\x99\xcc\x53\xed\xbb\xe6\x57\xfd\xfa\x2c\xa2\x44\x67\x05\x0a\x0a\xeb\x8c\xff\xd7\xd3\x3d\x54\x3e\xc2\xc1\x91\xcc\x0b\xce\x89\xac\x37\xd3\x32\x93\xb1\x88\x8c\xcb\x76\xc2\x8a\xdc\x67\x1a\x49\x35\xa8\x46\xd9\x07\xe4\xad\xd0\x11\x0f\xeb\xbe\xe5\xae\xc8\x0f\x9d\x2f\xf7\x4e\x2a\xf4\xfd\xbe\xbb\xcf\x49\x10\x5a\x64\x69\xd7\x38\x00\x06\xb2\xca\x44\x36\x48\x14\x45\x4e\x44\x5e\x36\xdc\x00\x12\xf3\x39\xc9\x68\x54\xf8\x36\x44\x2a\x05\xa5\x0b\xec\x90\x73\x27\xf7\x4b\xa9\xf6\xfd\x79\x0f\xf0\xad\x37\x83\xd2\x97\xbd\xcc\xa7\x64\x60\x78\x37\x03\xeb\x5f\x2b\x1f\x51\xb0\xa7\x40\xce\x7a\x8f\x00\xa3\x87\xe3\x63\x62\x70\xa9\x71\xfa\x8f\x15\xb4\x49\x67\x30\xd8\x8a\xdd\x80\x7a\x7f\x7e\x98\x7c\xd4\x15\x95\xa2\xe7\x43\x5d\xf5\x19\x55\x76\xa3\x5f\x5e\x91\xb2\xfc\xfa\xc9\x4e\xd5\xd7\x76\x63\x78\x3b\x61\xe6\x67\x1d\x34\x83\x8b\x6b\x56\x44\xfb\xc1\xc5\x39\xfe\x15\x9b\x77\x92\xdb\x96\x7e\x83\x52\x61\x8d\xda\xca\x0c\xde\x73\x43\x7b\x59\xe7\x80\x1b\x49\xeb\x46\x09\xb1\x05\x77\xca\x26\x92\xdd\x6f\x9d\x5e\x9d\x4b\x5e\x5e\x62\xc5\x91\x3e\x7b\x87\xe6\xb3\x47\xbe\x61\x53\xb1\x71\x99\xc9\x16\xa1\x3f\x8a\x88\x5b\x37\x8e\xf0\x9e\x13\xca\xe4\xd8\xb0\x79\xd7\xd5\xcb\x90\x94\x19\x9b\x0f\x20\x53\x3c\x90\x08\x3b\xc3\xac\xb2\x66\x76\x97\xee\xd2\x2e\x36\x70\xab\xb4\xa5\x53\xe9\x95\xc9\xdd\x95\x94\xe5\x92\x39\x1a\x00\x04\xb6\x55\x65\x44\xf3\x56\x12\xc4\x97\x13\x59\x57\x7c\x47\x63\x82\xca\x53\xb3\xf2\x62\xa5\xe3\x3e\xd2\x6e\xec\x80\x9f\x4f\xdb\xa4\x89\x8a\x11\x36\x75\xcb\x6a\xf7\x17\xdb\x62\x57\x9f\x39\x80\xb2\x14\x63\xbe\x02\x9c\xb4\x16\x0f\xe5\xd2\x57\xc4\x6c\xd6\x66\x4f\x98\x61\xac\x50\xfe\x05\xc1\x44\x05\x7d\xce\x2f\x8d\xf1\x53\x2a\xa7\xaf\x58\x9f\x41\x27\x06\x01\xce\xf0\x6b\xbe\x4f\x35\xc3\x1c\x78\x2b\xb3\xcf\xff\x7d\x5a\xb6\x4a\x14\xec\x41\x73\x61\xf1\xd3\x2c\xbd\x38\xb6\xbd\x0e\x02\x50\x5d\x14\x16\x30\x2b\x85\x05\xae\x2a\x96\xe8\xd5\x33\x9c\x34\x6c\x2b\x06\x62\xd3\x50\x25\x9c\x50\xc5\xe4\x87\x95\x91\x4e\x6f\x88\xe9\x7c\x81\x1c\x39\x3b\xdf\x9a\xec\x7e\xf8\x20\x47\xca\x28\xee\x97\x1c\x17\x5c\x27\xe3\x6e\x10\x97\x27\x96\x0d\xdf\x1a\x1b\x97\x6a\xb4\x4f\x48\x51\x60\x7b\xd9\x66\x80\x8a\xc4\x6d\x54\x00\x31\x28\x29\x7f\x5f\x44\x87\x10\x8d\x6a\x02\xe7\xa1\x64\x13\xd2\xb7\x5e\xcb\x42\xfd\xdf\xb6\x69\xc8\x01\xd2\x3d\xe5\x0a\x6f\x7b\xf6\x58\xf7\x53\xc6\xb2\xb3\xb4\x7c\x06\x40\x10\x5d\x0a\x80\x1b\x32\xa1\x94\x3c\xdc\x15\xc8\x86\x55\x5e\xb7\x5b\xb7\x92\x7b\x93\xc3\x5c\x5b\xe1\xf9\x8b\x19\x6c\xaa\xc2\xda\xd9\x91\xb1\x04\x4e\xa8\x63\x94\x4d\x54\xd8\x83\xab\xc3\xc6\xde\x66\xed\x86\x8e\xe8\x4b\xcf\x9c\x34\xcc\xdb\x80\xfc\xd9\xcc\x04\x02\x74\x77\x32\xcd\x63\x0b\xbf\xa3\xbb\xe8\xb0\x38\xdc\x1d\xbd\xaf\x43\x6d\x9a\xc0\x0c\x02\xd5\x28\xec\xe2\xe7\x91\xee\x31\x2a\x86\x8f\xeb\x2f\x58\x7c\xa4\x4d\xb5\x73\x13\x84\xfa\x18\x31\x14\x20\x61\xb2\xea\xd2\xb8\x0c\x66\xbd\x2f\xa5\xdc\xca\xbe\x6a\x25\xf2\xa4\x93\xfe\xaa\xcd\x23\x1d\x2f\x40\x96\x46\xb9\x42\xa5\x78\x54\x5e\xa4\xfe\xea\x9a\x73\x47\x3f\x79\xdc\xf1\x3e\x0c\x9f\x1b\x49\xfd\x89\x12\xec\x48\x73\x28\x04\x5b\xd0\xfa\x22\x89\x22\xee\x6e\x97\x3e\x61\xf6\xe9\x33\x65\x29\x65\x78\xdc\xc2\x1c\x36\x14\x79\xee\x2d\x24\x87\x9f\x2e\x9b"}, -{{0xa6,0xe6,0xad,0x2c,0x37,0x9c,0x6f,0xcc,0xad,0xb4,0xa4,0x9b,0x23,0x2a,0x91,0x42,0x61,0x8e,0xa3,0x01,0x03,0xc3,0x3c,0x22,0x6f,0xf6,0x28,0xbc,0xfd,0x81,0xf4,0x26,},{0xf7,0xc4,0x32,0x3f,0x5c,0x41,0x9d,0x9b,0x3f,0x34,0xa8,0xeb,0x42,0xae,0x7f,0x1f,0xaa,0x23,0x33,0x07,0x90,0x30,0xc5,0xd6,0x4f,0x9f,0xfb,0x1e,0x9b,0x16,0x00,0x2d,},{0x07,0xd9,0xfc,0x24,0x4f,0xda,0xb0,0x01,0x59,0xeb,0xec,0xc5,0xa0,0x08,0x83,0x45,0x3f,0x08,0x31,0x01,0x71,0x76,0x9d,0x29,0x70,0x01,0xe8,0x77,0x01,0x0e,0x3e,0xce,0xd9,0xfb,0x60,0xec,0x91,0xcb,0x4d,0x88,0xe7,0xba,0x40,0xc5,0x30,0xb1,0xf9,0x23,0x79,0x78,0xcc,0xd9,0x6d,0x5c,0xba,0x9e,0x4f,0xa2,0x7e,0x2a,0x0a,0xd9,0xd6,0x0c,},"\x2e\x85\x76\x76\xa5\xbb\x1c\x6e\x9e\x94\x50\x7f\x83\xc6\x0a\x67\xf5\x47\xc5\xde\x9e\x94\x56\x6b\x19\x7a\x6a\xf6\xcf\x47\x52\xe9\x3d\xbd\xef\x6b\x9f\x66\xd1\xfe\xbd\x95\x7e\x42\xa7\xf5\xad\x64\xef\x1d\xbc\xc4\xfe\x69\xae\x95\x25\xd1\xa4\xde\x67\x05\x4c\x88\xf2\x9c\x06\x47\xba\xcf\x8b\x82\xf3\x21\xff\x99\xfe\x9e\xed\xc9\x92\xed\x34\xc1\x17\x7f\xc5\x42\x12\x27\xcc\xac\x10\xfe\xb9\xce\xd4\x08\x2f\x56\x58\xda\x63\x71\x47\x23\x97\x97\x37\xe7\xdc\xbf\xe2\xe8\xb5\xd5\x0f\x91\xdf\xca\x83\xe7\xf9\x5f\x35\xd1\xad\x8d\xd5\x11\x44\x50\x2f\x3d\xf6\x72\x43\x26\x11\xf0\xe7\x66\xa9\x0d\xcc\x2a\x57\x39\xc8\x05\xd9\x5f\xe5\xb0\x41\xde\x9d\x7f\xb4\x7b\x44\x04\xaf\xc8\x03\xa3\xbd\x48\x04\xc7\x81\x7e\xbc\x5b\xdf\xef\x8a\xdd\x9e\x25\x0b\x50\x96\x6c\xa8\x93\x9b\x22\xb3\xc6\xff\x93\x6e\xaa\x65\x9a\x24\x0c\x0c\x84\x8b\x81\x0a\xce\xcf\x61\x81\xe0\xe4\xdb\x8e\x4c\xf8\xfc\xce\x7d\xe5\x59\xcb\xe8\xaf\xa9\xdb\x84\x99\x57\x09\x11\xa3\x88\x7e\x85\x0e\x50\x9c\xdb\x70\xde\xbc\x34\x77\xd1\x21\x75\x01\x4f\x79\xf8\x1b\xa1\x13\xd0\xb7\xb3\x35\x11\x8f\x85\xcf\x59\x99\x6f\x80\x67\x58\xeb\x90\x3c\xc4\x50\xf5\x2f\xee\x10\x2e\xfc\x01\x44\x1e\x9a\xe5\xfa\xe7\x4c\x23\x1d\xfd\x85\xeb\x6b\xad\x17\xd6\xb7\x0e\x93\x85\x84\xfa\xcb\x21\x72\xcb\x03\xbd\x5e\xa0\x7b\x7f\x0d\x37\x1f\xfa\x35\x1c\x0e\xe4\xef\xe9\xba\x4a\x3f\xd5\x43\x87\x46\x55\xe7\xd3\x9c\x53\xae\x86\x32\x98\x02\xe5\xc3\x85\xe9\x28\x3a\x29\x73\xca\xb8\xcf\x7a\xc7\xff\x0f\x91\xd1\xd4\x8b\x58\xab\xfd\xad\x65\x8d\x81\x2f\x07\x88\x16\x76\xbd\x22\x6b\xfe\x95\x7d\x7d\xf3\x0c\x41\x30\xa4\x48\x35\x4a\x6b\x94\x40\x5a\x41\x16\x50\xa9\xc8\xfc\x85\x11\x55\xec\x5a\x8a\x3e\x3b\x67\xae\x0c\x4b\x5c\xb8\x9b\xb7\x3f\xc8\x29\x74\xbe\x62\xda\x73\xf0\xe2\x30\x92\x93\x7d\x40\x5b\xa4\xaf\x6c\xab\x94\x65\xea\x43\xa6\x25\x3f\x44\x57\x08\x2a\x06\xac\x12\xb7\x5e\x88\xec\x68\x44\x87\xf9\x07\x63\x73\xfa\xb8\x89\x28\x59\xd8\xe8\xba\x43\x14\x23\xaa\x80\x5a\x22\x0c\xbf\xda\x43\x1b\x32\xb1\xe0\x31\x21\xf7\xfd\x4d\xe1\x85\x91\xf2\x50\x5c\xc0\xf5\xb2\xb1\xa7\x60\x5f\xbc\xc6\x37\x57\xb0\x7e\x29\x9f\xef\x5a\x2b\x73\x65\x23\x0c\x2e\x92\xa2\x59\x62\xc2\xe8\x01\x2a\xd3\xfa\x9e\xe9\x48\x82\x70\x96\x25\xba\x68\xc7\xb2\x13\x66\x4a\xe2\x53\x2b\x60\x9d\x7c\x9a\xa0\xe8\x3d\x49\x3d\xbc\xe7\x63\x2f\x35\x58\x0e\x06\xd3\x11\x1c\xed\x32\x0d\xd0\x19\x04\x41\xf6\x2d\x9e\x35\xf5\x0d\xe5\x9c\x27\x2f\xb0\x0f\x56\x8a\x00\xb0\x74\x6c\x33\xa9\xbd\x24\x90\xc0\x74\xb9\x1c\xdd\xc4\x87\xef\x2e\x45\xa0\xf0\x30\xe0\x8f\xdc\x18\x17\xbc\xa8\xa9\xce\x29\xd2\x92\x79\xe7\x55\xde\xbc\x28\xdf\xad\xc3\xc4\xd1\xb4\x58\x48\x6e\x3c\x8d\x0c\x43\x18\xe7\xe6\xf9\xeb\x5a\x36\x53\xb3\xf7\xc4\x95\x07\x07\x7c\xd5\xeb\x81\xf1\x0b\x88\x10\x7c\xc0\xf9\x31\x69\x32\xab\xe9\xb6\x4e\x88\x86\xd0\x68\x56\xa8\x5b\xe6\x3b\x0c\x2b\x47\x5c\x0a\xfc\xb0\x69\x44\x26\x86\x0f\xb2\x4b\x5c\x17\xab\x6a\xb7\x73\x3d\x5e\x64\x1b\xe7\x4f\xd5\xf6\xa1\xff\x18\xd2\xf9\xa4\x27\x70\xfb\x30\x75\x0f\x56\xf4\x85\x4e\x38\xd5\x8a\xef\x18\xa2\xa6\x1c\xbf\xb4\x9e\xe5\x76\xed\x97\x73\x7b\xc2\x8d\xf3\x26\x8a\x33\x41\x75\x51\x3d\x97\xaf\x00\x9c\xbb\xcf\xdf\xad\x50\x39\xd6\x9b\xb4\x6f\x70\x88\x67\xd9\xb3\xce\x0b\xf2\xf5\x69\xe3\xcf\xbc\xf6\x13\x6f\x88\x70\xd2\x52\x08\xb2\x1a\x3e\xdc\xb7\x33\x93\xdf\xcd\x41\x72\xc1\x40\x2c\x41\xf3\x6e\x3f\x82\xa4\xea\x6d\xcd\x89\x16\x86\xba\x66\xe1\x43\x20\xaa\x0e\x22\xba\x0c\x1e\xf0\x33\xd6\x62\xcd\xb8\x60\xcd\xfa\x3a\x40\xf6\xcc\x53\x2a\x08"}, -{{0x9b,0x6d,0x7e,0x28,0xeb,0x05,0x15,0x97,0x32,0x4d,0xce,0xb7,0xa1,0x89,0x41,0x24,0x67,0x25,0xe8,0x8d,0x53,0xab,0x2c,0x34,0x77,0x11,0x05,0x33,0x0c,0xf1,0xf4,0xae,},{0x88,0x72,0xa5,0x0b,0x5f,0xe3,0x62,0xf8,0xea,0xd1,0xd4,0x0e,0x20,0x45,0xf0,0xd4,0x0b,0x2e,0x7b,0x50,0xb5,0x9d,0x80,0x90,0xbc,0x47,0xad,0x68,0xeb,0xee,0x09,0xed,},{0xc6,0xdc,0x5c,0xa1,0xe8,0x56,0x00,0x15,0xb4,0x93,0xaf,0xe2,0x66,0x6c,0xcf,0x6f,0xef,0xa8,0x03,0xd8,0x52,0x6c,0x83,0x7f,0xe7,0xf1,0x23,0xc7,0x99,0x14,0x27,0xab,0x03,0x0d,0x7c,0x77,0x0e,0x45,0xf6,0xde,0x84,0x81,0x52,0x3b,0x94,0xec,0xe9,0x7f,0x3f,0x16,0x1c,0xf5,0xb8,0xc7,0xae,0xa3,0x9f,0x5a,0xd8,0x26,0xbf,0x8d,0x0a,0x02,},"\xd1\xe1\x98\x7b\xff\x65\xf6\x2a\xd6\x76\x24\xc6\x65\x79\x24\xf5\xd6\x73\xb7\x82\x4e\xbe\x40\x40\x26\xc0\x56\x2d\xed\x31\x43\x44\x0b\xe6\x37\xf9\x8c\x9e\x01\xa6\xaf\xdf\xa9\xa4\x7d\xd4\x9c\x7c\xba\x6e\x3f\xd2\x3e\x45\x52\xf7\x63\x2b\x14\x38\x0b\x27\xcd\x3e\x96\x06\xcc\xe3\x50\xf1\x52\xab\x12\x6b\xea\xd0\xa5\xd3\xbc\xe4\xd4\x20\x92\xd9\x34\xc8\xca\x33\x7e\x98\x7e\x11\xd8\x6c\xfb\xfb\xd2\xac\xc3\x22\x3b\xd1\x67\x44\xa9\x27\x72\x8f\x48\x53\x72\x17\x5c\xc6\x94\xdf\x30\xa7\x3f\x9d\x33\x76\x5f\xf0\x14\xef\x00\x8d\x58\x63\x21\x03\x38\xcc\x34\x82\xcc\x27\xea\x31\x7e\xec\x92\x1b\x0c\x56\x8c\x38\xab\x27\xc4\xa5\x64\xe8\x02\xb1\xb9\x46\x68\xc6\x51\xe2\x0a\x0b\x55\xf3\xa7\x9d\x21\x5f\xc3\xa0\xd0\x49\x04\x01\x09\x32\xc4\xcc\x68\xc2\xa9\xe7\xd0\x0e\x5d\x38\xd8\x2d\xf5\x52\x06\xba\xb9\x5c\xf6\x97\xbe\xbc\x72\x06\xee\xde\xf6\xfd\x18\xd9\xa2\x0c\x2c\xbb\x28\x5b\x00\xef\xa7\x69\xa0\x8d\xab\x2b\x3a\xba\xdf\x00\xd1\x98\xb4\xf1\x92\xdd\x44\xbc\xb9\x14\x31\x82\x3a\xe6\xfd\xf9\x84\x58\xec\xa3\x9c\xd2\x92\x63\xf0\x99\x93\x03\xe7\x0d\xc6\x94\xfe\x01\xc5\x3a\x11\xc1\xd1\xc3\x4c\x1e\xe5\x06\x8a\x20\x1d\xbe\x7e\x10\x08\xd7\x64\x35\x89\x68\xb4\x02\xaa\x39\x85\x49\x50\x7f\x7b\xd1\x85\x08\x00\xe4\x11\xb1\xc4\xe2\x8d\xdc\x04\xa8\x59\xe1\x79\xbe\x8a\xd7\xe6\x67\x0e\x50\x9d\xb0\x27\xad\x7e\x51\x7e\x44\x25\x95\x4f\x5a\x80\x74\x14\xa6\xda\x26\x7a\x76\x4e\x71\x2a\x99\x84\x65\x06\x49\x82\xd8\x51\xa2\x65\xea\x3c\x4d\xfb\x74\xf9\x92\xa7\xcc\xcd\x9a\x82\x68\x7f\xa6\x1c\x32\x2c\x4f\x58\x9e\x86\xb8\x82\x52\x13\xbf\xa9\x51\xda\xe6\xaf\x35\x4a\xce\x18\xf0\x73\x99\x5a\xdc\x95\x83\x9d\xac\x01\x65\x51\x1d\x61\x75\x37\x91\xa5\x3e\x48\xe3\xa8\x27\x3d\x44\x82\x3d\x25\x96\xf2\xa2\xdb\x2e\x5f\x1a\xe5\x97\x22\x1b\xa7\xf3\xeb\xaf\x4a\x7b\x28\x88\x39\x50\x02\xbd\xaf\xf5\x1f\xa5\x4b\xfb\x97\x9d\xe1\x03\x14\x04\xca\x77\x89\xfe\x09\x5d\x4d\x17\xf0\x7a\x35\x55\x6b\x10\xfe\x8e\x14\x17\xc8\xa6\xa6\x31\xc2\xed\x36\xcb\x7a\x0e\x61\x81\x77\x62\x89\xc3\x44\x81\x4d\x42\x13\x1a\x73\xb1\x2f\xaa\x35\xd7\x78\x14\xc6\x81\xa6\x01\x37\x4b\xa7\x1c\xb9\xad\x53\x15\xfa\xd4\x2d\x3a\xcf\xc7\xc1\xd6\x28\x81\x02\x56\xda\xf7\xd8\xc3\xc9\xa2\xe5\xbd\xcf\xb7\x70\x08\x2f\xa6\x38\x16\x89\x58\x52\x3a\x1c\x3b\x03\x5d\xbc\x6d\x5a\xdf\x26\xdf\x89\xa7\xcc\xab\xed\x3e\x7d\xd3\x77\xc1\x6d\xa8\x41\xf1\x3c\x68\x94\xd4\x3c\xeb\xb4\xe3\x90\x22\xf1\xcc\xec\x22\x74\x44\x5c\x78\xb3\xad\xc7\xbb\xf7\x0d\x89\x0b\x80\x23\x6c\xc4\x46\x8f\x95\x69\xc5\x9a\x7e\x33\xb5\x70\xe6\x70\x38\x0d\x24\x4e\x4e\x31\x0e\x11\xc3\x92\xf1\xe3\x34\x05\x4b\x92\xc8\x38\x6c\x16\x1c\xe0\x41\x09\xb0\x37\xbd\x62\x8d\x91\x9d\xcb\x62\xda\x14\x35\xbf\x94\xe8\x8b\x0a\x88\x46\xd4\x86\xd1\x67\x78\xf7\xa3\xb8\x80\xe6\x60\xf4\x41\xfd\xf8\x6e\x56\xb8\xaa\x06\x61\xf5\x5a\xae\xce\x27\xf9\xdd\xaa\x0e\x2a\x22\xc2\x15\xb0\x40\x53\x97\x26\xb9\x85\x39\x15\xa1\x59\x2d\xff\xea\xe3\x2d\x7b\x5b\x67\xeb\x62\x05\xbb\x0b\xd7\x27\x9f\x78\x8d\x5f\x83\x3c\x40\x66\x78\x0c\xa0\xa4\x2d\x3e\x4e\x1a\xa2\x2b\xd0\x6b\xb5\xee\xd8\x9b\x94\x13\x77\x1e\xca\xb6\x44\xca\x72\xd1\x29\x1d\x00\xf7\x40\x90\x1a\x73\x11\xdc\x03\x67\x15\xd2\x3e\xbd\x9a\x59\x89\x16\x28\xf0\xd8\x7e\xd4\x89\x50\x2f\x06\xd7\x5b\xbd\x11\xcd\x16\x02\xa3\x5e\xe7\xe1\x33\x35\xd6\xa1\x44\xb0\x88\x30\xe6\x69\xc0\x2e\x65\x2f\x3f\x10\x0d\x39\x3e\xf9\xb4\xac\x05\x32\x14\x39\xbc\xe6\xce\x36\xff\xc5\xab\xca\x89\x0b\x87\x96\xcc\xb5\xe1\x63\x03\x55\x9c\x5d\x91\x17\xf0\xf3\x1d"}, -{{0x70,0x09,0xed,0xd0,0x79,0x50,0x96,0xed,0xc4,0xfe,0xd5,0x5a,0x17,0xcc,0xf4,0x84,0x13,0x1e,0x60,0x8c,0x6d,0x5d,0x66,0x96,0xbf,0x33,0x76,0xe2,0x69,0x24,0x95,0x9b,},{0x77,0x57,0x4b,0xf0,0x69,0x52,0x71,0x45,0xe7,0x2d,0x3e,0x85,0xce,0x7d,0x4f,0xcd,0x67,0x1a,0x33,0xe0,0xa7,0x1e,0x6b,0xf0,0xda,0x7e,0xa4,0x71,0xdd,0x6e,0x86,0xa4,},{0xb7,0x01,0xb8,0xf9,0xa4,0x34,0xe0,0x6d,0x71,0x9a,0xd2,0x5d,0xcc,0x54,0x06,0x0c,0x79,0x86,0x64,0x7f,0x44,0xf3,0x88,0x4b,0xcb,0x6e,0x5e,0xe1,0xd7,0xa4,0x46,0xcc,0x26,0x5c,0xec,0x02,0x9b,0x53,0x7d,0xa7,0xf2,0x52,0x33,0x26,0x55,0x8a,0xc9,0xba,0x34,0xf4,0xcc,0x2a,0x97,0xcc,0xa3,0x45,0x2e,0x70,0x56,0x2e,0x7a,0x8f,0x55,0x04,},"\xb1\x2c\x12\x47\x05\x39\x54\x7c\x2d\xe6\xbc\x4e\xea\xc7\xb6\x3e\x50\x8e\xd7\x10\xf3\x56\x37\xd9\xfd\xd2\xdc\xca\x32\x2a\x7a\x50\x71\xda\xb2\xb2\x84\x5e\x30\x79\x28\x06\x03\x5c\x9f\xcd\xaf\xe2\x78\x3e\x3b\x67\x7d\x6b\xe5\xaa\xc7\x0b\x33\x91\x0a\x2b\x95\xe8\xb5\xd5\x9b\xda\x61\x59\x35\xa4\x17\xb7\xae\x19\xa7\x85\x37\x74\xe8\x9a\x12\xaa\x54\x7b\x41\x92\x97\x9a\x01\xef\x6e\xf3\x2a\x40\xde\x79\xd6\x80\x05\x7a\x83\xa0\x74\x61\x7c\xa6\x50\x1f\x59\xe7\x35\x64\x92\x7c\x38\xb5\x8c\x19\x58\x5a\x2c\x03\x65\x9c\x02\x6e\x4d\xe3\x80\x6d\x6c\x1c\xa8\x95\x8d\xee\x47\xbc\xb8\x89\xe7\x6d\x2c\x3a\x9a\xb5\xb8\xb6\xaf\xb2\xe8\x42\x29\x80\x56\x56\x7b\xf9\xb5\x89\x57\x41\x54\x83\x33\x62\x33\xef\x49\x20\xfa\x57\xf4\x96\xe1\xf0\x34\x8c\xca\x20\x36\x64\x96\xfa\xb3\xa7\x5b\xf4\x21\x4e\xce\x47\xa4\x5f\xea\xa1\x39\x2d\xb3\xf2\x54\xd9\x6a\x7f\x37\x40\x2c\x98\x11\x14\x0d\x73\x58\xb4\xef\x8f\x20\xa2\x98\xee\xef\x90\x4e\x37\xd6\x8f\x37\x8d\x33\xcb\x96\xd0\x0c\x03\x10\x9f\xc8\x3f\xd0\x6a\x87\x6c\x92\x48\x2f\x61\xab\x79\x14\xeb\x7c\x2e\x5e\x84\x06\x6e\x0e\x91\xe2\x1e\x42\xe9\xbe\x23\xdf\x12\xb5\xc7\x47\x97\x3c\xb8\x64\x42\xc3\x22\x91\xd3\xd1\xae\x71\x9b\x36\xa6\x2f\xaf\x3a\xba\xa2\x05\x3a\x31\x3f\x62\x5d\x85\xc5\x1a\x51\x98\x57\x19\x15\xef\x8a\x2b\x19\x9b\xa3\x7d\x25\x88\x45\x75\xba\x1b\x72\x84\x4c\xab\x43\x28\xb5\x7f\xab\x1e\xc9\x74\xee\x8e\xa1\xdf\x7c\xa9\xc7\x8a\x4d\x3a\x03\xbc\xb0\xab\x41\x69\xbf\x06\xa3\xa4\x38\xd9\x56\x6c\x6c\x50\x1d\x8d\x9c\xcc\xcb\x1a\xc2\x6b\x4d\xa4\xae\x1a\x9d\x8e\x8b\x9d\xf6\x62\x82\x1a\xd9\x75\xc9\xb0\x15\xfe\x26\xf6\x89\x8d\x22\xab\x91\x2f\x0e\x40\x5a\x5b\x27\xcf\xd3\x9d\x65\x7d\xcd\x92\xcd\xeb\xe6\x79\x19\x02\x71\x34\x84\x40\x6d\xdd\xce\x71\x18\x87\x31\xe4\x43\x19\x38\x1a\xf2\x7d\xaf\x76\x79\x22\x73\xb8\xc3\x52\x51\xd1\x1b\x83\x6a\xfe\x8b\x3c\xe9\xb4\x02\x73\xf6\x91\x5e\xbe\x6b\xc9\x5a\x75\xbb\x94\x1a\x42\x92\x09\x86\x7f\xba\x87\x64\xbf\x6c\x40\xdb\x6e\xec\xb4\xf2\x17\x47\x83\x7c\xf6\xae\x7f\xbf\xe3\x6d\x50\x23\xdf\x7f\xce\x2c\x0c\x3c\x57\xaf\x28\x98\x88\x53\x13\xc5\xc4\xbd\xa3\x5c\x7d\xa6\xcb\x29\x93\x2f\xb1\x99\x1f\x62\xbb\xb0\x80\xb3\x2e\x20\x50\x61\x93\x11\xae\x69\xab\xb3\x02\x2d\x91\x3f\xa9\xea\xbd\x5d\x5c\xb4\xdc\x54\xd7\x5d\xca\x63\x8c\xda\x9a\xf3\x31\xc0\xcf\x4d\x20\x07\xb6\xca\x39\xf6\x55\xa6\x1c\x01\x03\x9f\x12\xa4\xb9\x78\x2b\xc3\x9a\xec\x4d\x22\xef\x00\x93\x38\x8d\xd7\xd5\xb5\x6d\xfb\x8a\x7f\x9d\x86\x69\x00\x4e\x28\x78\xdd\x8a\x6d\x76\x85\x7c\x08\x45\x24\x50\x68\xfe\xe1\xc5\x31\x96\x31\xe7\x8d\x37\x85\x16\x5c\x70\xaf\xd6\x52\x99\x30\x13\x78\x55\x1e\xbf\x61\x35\x84\xc6\xa7\x62\x0a\x0e\x3b\x67\x79\xf3\x8c\x09\x40\x06\x24\x97\x00\x8e\xb2\x33\x87\x08\x68\xc2\x1c\xcc\xac\x23\x95\x01\xb6\x3b\x74\x9a\x85\x60\x2c\x28\xa0\x95\xca\xfc\x74\x9b\x05\x11\xa6\xc8\x78\xed\xb3\xb7\x80\xea\x17\x4d\x07\xb1\x21\xe3\x15\xa8\x26\xdd\xa6\xec\x8d\xc5\x43\x63\xe2\xcd\x2e\x63\x05\xa1\x94\x82\x5c\x0e\xa9\x0e\xfd\x7a\x9f\xd8\x9c\xd9\x7b\x99\xc4\x30\x0b\xd3\xbf\x93\x53\xd8\x2f\xbc\xce\xea\x71\xb4\xee\x3f\x1a\xae\x95\x39\xb4\xcc\xe9\x0c\xa4\x77\x59\x7c\x17\x4e\xf2\x0f\x4b\x9f\x4e\x62\xd0\x9a\x57\x0d\x31\x35\xaa\xbe\xe9\x55\x1f\xa6\x09\x83\x95\x8c\x0b\x7b\x8c\x37\x44\x55\x3e\xe1\x4e\x7f\x3c\xd1\x03\xa1\x92\x51\xc9\x9b\xf6\x38\x4a\xbb\x60\xa7\x6a\xfc\x66\x58\xb8\x0d\xfc\x51\x10\xad\xc4\xc7\x32\xfe\x0e\xe3\x29\x33\xfb\x28\x48\x28\xe0\x08\x88\x7a\xef\x80\xf6\xf8\x13\x34\x04\x46\xc0\x21\x7c\x12\xee"}, -{{0x12,0xfe,0x8e,0x5c,0xe2,0x0c,0xaf,0xaa,0x32,0x79,0xda,0x7b,0x34,0xaa,0x87,0x75,0x2e,0xad,0x67,0x9f,0x15,0x61,0x28,0xaa,0xef,0xb4,0xaf,0xa5,0xdb,0x4f,0x2a,0x6f,},{0xe7,0x7f,0x44,0x20,0x6b,0xb0,0xc4,0xc5,0x9a,0x28,0x70,0xcf,0xc2,0xec,0xac,0x63,0x36,0x2d,0xee,0xcb,0xe8,0x11,0x5d,0xe5,0xcb,0x1a,0xfc,0x2d,0x9a,0x3d,0x47,0xf1,},{0x04,0xea,0xf9,0x00,0x96,0x6e,0x09,0x92,0xd3,0x6e,0x3c,0x22,0x0a,0x4b,0xd4,0xd8,0x2b,0xcc,0x6e,0xb9,0x98,0xed,0x05,0x1d,0xbc,0xb9,0x16,0x0b,0xcd,0x35,0x74,0x09,0x73,0x6b,0xcf,0xf7,0xe6,0x63,0x0e,0x96,0xf5,0x53,0x8a,0xec,0xa6,0xab,0x8b,0x0d,0x0b,0xd8,0x2c,0x0c,0xd7,0xc4,0x54,0x99,0x17,0xfe,0xbb,0x9c,0xba,0xda,0x08,0x0c,},"\x6b\x80\xcc\x6f\xbb\xd3\x32\xf8\xc6\x19\x7c\xdf\x2e\x6d\xc1\x9a\x21\x30\xfa\xa2\xec\x93\x8e\xf5\x58\xb8\x84\xba\x4f\xa5\xe1\x13\xe5\xb3\xe4\xb1\xaa\xf5\x1b\x69\x5f\x13\xef\xfe\x13\xf7\x7d\x39\xca\xb3\xc0\x7d\x04\xd6\x6d\x43\x0d\x99\x74\xb1\xda\x3d\x39\xdf\x12\x78\xc0\x0d\x6b\xcb\xfd\x4b\xae\x75\xb8\xc0\x76\x40\x4d\xbb\xb8\x34\x48\xfb\x49\x3d\xf6\x70\x00\xf9\x7d\x24\x7e\x8f\x23\xdc\x08\x1f\xce\x99\x2b\x65\xa2\x1b\x35\xd7\xbd\x7f\xa7\xdc\xcc\x54\xa5\x60\xaf\xd1\x4b\x1e\xc4\x36\xc1\x09\x46\xf6\xaa\x59\xea\xe1\xbe\x3e\xcf\x31\x1d\xef\x51\xe4\x6b\x6b\x4d\x1d\x08\x0d\x17\x84\xb2\x33\x4b\x80\xcf\xba\x72\xcd\x93\x1f\x55\xec\xd2\x98\xb0\x5d\xc8\x36\xab\x12\xd0\xad\x8b\x5d\x6e\x9b\x1e\x3c\xea\x3d\x84\x33\x68\xee\xf1\x9f\x5c\x14\xc6\xbb\xad\x94\x14\xcc\x7a\x4d\xb6\xa7\x26\xe4\xfc\xae\xd4\x44\x40\xa0\x19\xfe\x12\xa6\x05\x73\x40\x3c\x0e\x66\x2d\xc9\x02\xd1\xc8\x73\xff\x30\xc9\x31\xba\x7e\x43\xa3\xb3\xbf\x71\xd5\xb0\x94\xea\x50\x49\x71\x64\x7c\xa9\x43\x56\xf0\xa5\x3e\x44\x4b\x4c\x00\x8e\xe5\x97\x72\x04\x22\x1b\x40\x0d\xee\xc3\x7f\xc2\x73\x45\x25\x45\xf8\xf2\x18\xbe\x98\x87\x25\xbc\x38\xc8\x5d\xf2\x12\xea\x73\xdc\x0b\xc7\xcb\xba\xc9\x07\x98\x2f\xef\xad\x68\x0f\xbd\x97\x5c\x20\x93\xa7\xfe\x8e\x6b\x37\xc1\xcc\xed\x87\xf8\x1d\xaa\x57\x29\x1a\x5a\x18\x47\x6d\x11\xa1\x8e\xc4\xb5\xcb\xce\x5d\x55\xac\x9b\x62\x4b\x04\x84\x30\xf2\x54\xf6\x71\x07\x85\x06\xe6\x98\x9d\xf7\xc0\x92\x56\x52\x50\x39\x08\x5a\xb7\xc1\x30\xc2\x40\x00\x4a\xbb\xb3\xaf\x6b\x48\x1c\xc1\xa0\x61\x7e\x57\xe3\x88\xee\x4b\x1f\x05\x2f\x34\xa0\x03\xfe\x6b\xb2\x02\xcb\x87\xd2\x74\x1b\xd8\xe3\x45\x4c\xa7\x3d\x2f\x61\x20\x11\xec\xc7\x4d\x88\x34\x35\x10\xa6\x3c\x93\x13\xdd\xc3\x6c\x25\xd3\xfb\x03\xe1\x88\xf5\x60\xbd\x02\x9c\x80\x15\x85\xce\x55\x29\x88\xdc\x55\xb7\xd8\x52\x2a\x33\x96\xc0\x1d\x5e\x71\x5a\xe2\x6c\x62\x2c\x64\xfe\xd5\xb9\x8e\x9c\x55\x9e\x4a\xa7\x8d\x1e\xd3\xb7\xb8\x90\xd4\x77\xec\x8c\x50\xa0\xff\x10\x7a\x3f\x83\xb0\x7b\xd3\x5e\x9c\xe9\xa0\x8b\xcf\xc0\xf1\x68\xee\xc7\xaa\x31\x1f\x71\xc6\x6a\x71\xce\xb9\xd5\xa2\x19\x9a\x14\xbe\x36\x86\x5c\xa8\xd0\x7e\x18\x6b\x13\x92\xb9\x29\x0c\x57\x80\x04\xd5\x84\xf1\x91\xc8\x2a\x53\xd8\x50\x89\x0b\xcc\x0d\x12\xdf\xf8\x40\xe0\x43\xdd\xdc\x2e\x67\x0c\x83\x60\x20\x92\x4f\x58\xc0\x44\xb2\x18\x76\x3c\xa6\x19\x82\xbc\x33\x2d\x24\x7b\x2a\x00\x8a\xb5\x70\xb6\x56\x5a\x06\x89\x2a\x26\xcf\xb0\x85\x3d\x79\xda\x28\xef\x8b\x91\x0a\x93\x29\x54\x4b\x79\x2a\xe4\x45\x6b\xa7\x76\x50\x66\xb9\xd1\xb4\xa3\x00\x21\x04\x48\x66\x0a\xe4\x8b\x50\x44\x41\x01\x7c\xdd\xd1\xf6\xf0\x09\x38\xb1\x07\x2c\x8a\xb8\x24\xad\xfe\x8a\xe3\x49\x23\xc8\x2e\xec\x75\x4b\xee\x1a\x65\x50\xab\x1d\x3d\xa0\x86\xe3\xae\xbb\xf2\x11\x69\xc4\x44\x69\xe0\x3b\xba\xe0\xd7\x2c\xe8\x63\x45\x77\x84\xcf\xe1\xdf\xc2\x76\xf1\xaf\xad\x9e\xe5\x3e\xba\xb5\xa3\xc6\x57\x2e\xb1\xca\xe0\x99\xa4\xa5\xfe\x19\x31\x92\x90\xe6\xa1\xb8\xb0\xe7\x54\x1e\xd7\x35\xb3\xf2\x1b\x1e\x2c\x75\x09\xf8\x7f\xd1\xfe\xd0\x00\x07\x47\x9b\x3c\x1b\xb7\x84\x32\x46\x63\x02\xd2\x46\xd8\xd0\x31\x99\x63\x07\x26\x0a\x0c\x41\xa0\xe3\xec\xd1\xe7\xfd\x83\x4d\xac\x11\xa1\x3e\xb0\x36\xb3\x9c\x36\x99\x66\xfd\xef\x39\x4c\x18\x3e\x54\xe7\xb0\xcb\x3d\x0c\xeb\x19\x8b\xd0\xe6\x6c\x00\xd3\x8d\xb7\x03\xaa\xce\x30\xcb\xbd\xab\x36\x9d\xfd\x1d\x9e\x51\x4d\x09\x68\xf1\x00\xc9\xf0\x7c\x31\x50\x89\xad\xb3\xad\x02\xe5\x9c\x04\xb9\xbe\x46\xe9\x9f\xbf\x5a\x62\xc6\xbb\xec\xdf\xf5\xb3\x81\xe5\x51\x27\x82\x4d\xdb\x18"}, -{{0xee,0x9b,0x6c,0x2e,0x0c,0x9b,0x01,0x47,0x2c,0xe3,0x2d,0x54,0xd1,0x76,0x2a,0xb0,0x30,0x33,0x17,0xd7,0x6d,0x3a,0xa7,0x8f,0x5e,0x08,0xa9,0x02,0x4c,0xa1,0xe0,0x83,},{0x01,0x6d,0xf0,0xf7,0x17,0xbc,0xb7,0xad,0xf6,0x26,0x95,0x8d,0x83,0xbf,0x8a,0xa3,0x25,0xc7,0x05,0x18,0xc6,0x8b,0xc7,0xef,0xd8,0x42,0x53,0xb7,0x5d,0xb0,0x87,0x88,},{0x4b,0x00,0x1d,0x96,0x42,0x83,0x5d,0x72,0x13,0x8d,0x68,0x01,0x98,0xe6,0xaf,0x70,0xb5,0xde,0x7a,0xf0,0x15,0x13,0x1e,0xa7,0x26,0xf4,0xe5,0x1b,0x5e,0x8b,0x6d,0x48,0xc2,0xa6,0xca,0x8e,0x87,0x09,0xcc,0x82,0x22,0xa5,0x04,0x7c,0x09,0xa6,0x6e,0x51,0x8a,0xc5,0xe8,0xb6,0xe5,0x35,0x48,0x94,0x82,0x61,0xf0,0x70,0x1f,0x68,0x73,0x08,},"\x77\x2c\xc2\x5c\x3b\x69\xbb\x3f\xf5\x65\x56\x64\xef\xa4\x78\xac\x41\x4a\xdf\xae\xa7\x0a\xc4\xa2\xa8\x87\xed\x39\x68\xc5\x4d\x34\xdb\xf1\xbe\x32\xcc\x9a\x9b\x54\x20\xa4\xad\x3c\x9a\x87\x7b\xc8\xcc\xec\x94\xad\x47\x3a\xa7\xa3\xc7\xde\x08\xa0\xfd\xb5\xed\x1e\x89\x87\x2b\xe7\x81\x70\xbe\x22\x1d\x27\x97\x76\xbb\xc6\xed\x9c\x5a\x67\x16\x89\x80\xd5\xea\xf8\x95\xe1\x34\x0f\x5d\xfa\xa3\xdf\x62\x2d\x65\x44\xb3\x99\xd7\x49\x45\xfd\x13\xbb\x11\x73\x62\x1e\x05\x61\x51\x46\x40\x13\x7a\xa7\xbc\x9c\xb7\xde\xbe\xff\x2c\x62\x69\x77\xd4\x47\x26\x3b\x7e\x57\xd4\x3d\x69\xef\xb2\x30\xcd\x25\x86\x5e\x4d\x92\x48\x28\xf5\xe3\x6f\x96\x4e\x40\x3e\x34\x93\xf3\x0d\x6d\xfe\xa6\xca\x3b\x78\x10\x75\xb5\xe3\xb2\x5c\x05\xac\x50\xe5\x55\xf1\x5b\xa1\x2b\x0e\x05\x9b\xff\x99\x64\x84\x12\x9d\xb6\xea\xfd\x88\x99\x3d\x6f\x0b\x7e\xcd\x15\xdc\xe2\xfc\x99\xf8\xb8\xe4\x35\x16\x35\x2d\xdb\x46\x1a\x04\xb9\xff\x34\x86\x45\x2e\x6a\xa6\xa5\x4b\x2d\x10\x62\xa7\x71\x42\x50\xcd\x2a\x88\xff\x6c\x4c\x17\xb6\xcc\x66\x52\xd8\xc5\xac\x27\xd4\x44\x3a\xeb\xf3\xd5\xfb\xaa\xee\x45\x21\xec\x76\xf0\x41\x3d\xb6\x44\x21\xec\x8d\x69\x49\x62\x67\x25\xfe\x56\x16\x0a\xb3\x07\xc0\xe7\x39\x06\xc4\x51\x55\xef\xab\xb4\x72\x22\x02\x1f\x22\x0d\x32\xbd\x3d\xb0\x71\x2a\xbd\xe2\x59\x9e\xa4\xff\x79\x97\x17\x81\x1d\xcd\xf8\x18\x2d\xf6\x71\x6d\x2a\x03\x8a\xee\x15\xd7\x78\xda\x55\xac\x20\xf0\x1f\x25\x30\x9c\xea\xd5\xb5\xb7\xb2\x23\x22\xe1\x82\x8e\xa7\xc9\x1a\xe6\x66\xf2\xdc\xd6\x84\x07\x31\x48\xe3\x1b\xb2\x24\x7d\x5f\x93\x50\x6e\xa8\x08\x52\x27\xad\xc9\xae\x19\x82\xe9\x50\xf0\x06\xa9\xda\x15\x8b\x9c\xec\xff\x89\x29\x76\x1c\x84\xf9\xd9\x76\xfd\xcd\x31\x7f\xfe\xd3\x6c\xbf\x6a\xcd\xa3\xe5\x0c\x9b\x73\xbd\x2c\x80\x85\x40\x9d\x11\x9b\x64\xce\xd7\x34\x9a\x26\x74\x26\x2a\x83\x2b\xec\xb0\x3c\x2e\xdc\xca\xc0\xec\x54\x12\x4e\x82\xf8\x10\x18\x17\x92\xda\x49\xea\x10\xbd\x94\x1f\x98\x95\xa0\x69\x59\xfd\xe0\xd3\xb0\xae\x84\xc3\x9d\xf0\x53\x90\xab\x33\xc3\x6c\x79\xca\x22\xe6\x59\x4d\x7f\xc6\xe3\xf8\x69\x22\xd7\x8e\xb7\xf5\xc2\x54\x95\xd8\x22\xa3\xb4\x10\x51\xb2\x4e\x57\xa7\x6f\xcf\xc1\x65\xcd\xe6\xd0\x96\xcc\x7b\x7e\x9d\x05\x5f\xe8\x64\xd5\x29\x42\xd6\x29\xa8\xac\x26\x1b\xe1\xdc\xd3\xa2\x1f\x89\x5f\x49\xb6\x7e\xe4\x7e\xab\x7c\xf1\x64\x4d\x57\x1d\x5f\xf3\x8c\x17\x9f\x5c\x6a\x54\xa3\x61\x2f\xb3\x47\x53\x41\x2a\x1b\x95\xbf\x62\xff\x31\x79\x80\x4f\xfb\xb9\x90\x51\xf2\xb0\x80\x56\x3a\x4a\xe0\xf2\x7c\xf9\x96\xea\x8b\xe3\xba\xe0\xa4\x33\x9d\xcc\xdf\xf6\xb6\x67\x15\x59\x26\x6e\xaf\xf4\xef\xf6\x82\xb8\xde\xe8\x9c\x9d\x2d\x45\xac\xdb\xec\x4a\xa6\xce\xcd\xbd\xb1\xd2\x84\x60\x9e\x65\xef\xb7\x7b\xb8\xf1\xa5\x1f\xc4\xd4\x56\x8a\x70\x5f\xb9\xc9\x7b\x23\x03\xc1\x46\x7d\xff\x8c\x8c\x5e\xe2\x75\x59\xb9\x3a\xd1\xc5\xb9\xc5\xc6\xc7\xc5\x29\xfa\x8c\x55\xc7\x5e\xbb\x59\xb2\xa8\x18\xaa\x9b\xda\x1e\x9e\x79\xbc\x66\x02\x97\x72\xf8\xae\xa1\x1b\xad\xd3\x22\x65\x65\xd5\x4f\xd0\x1b\xda\x8c\xb2\x70\xe7\x0d\xc9\x33\x9b\x46\x90\x0b\x58\x18\xe9\x32\x07\x5b\xe6\xc2\x8e\x73\xa1\x91\xd0\x2c\xbd\xc7\x45\x4b\xe1\x23\x87\xb0\xd4\x7a\x1a\xb1\x42\x32\xd2\x34\x2a\x6f\x15\x18\xea\x97\x09\x8b\x81\x5a\x1c\xa3\xf9\xc7\x0b\x25\x72\x2b\x1b\xcd\x7d\xac\xda\x63\x56\x22\xfc\x8e\x72\x95\x9f\x57\xf7\x67\xea\x56\x3d\xa4\xc1\x58\xee\xf7\x20\x01\x09\xf6\x14\x16\xc2\xe7\x04\x39\x92\x30\x62\x43\x7b\x1d\x08\x2a\x8c\x7f\x43\x94\x71\x3c\x1b\x7b\xa0\x58\x7b\x84\x1c\x11\x44\x75\xee\x3f\xf0\x59\xdf\x8c\xfa\x12\xa3\x21\xd9\x01\xcb\x47\xf5"}, -{{0xa3,0xd2,0x35,0x05,0xd0,0x7c,0x5f,0x93,0x7f,0x13,0x63,0x9d,0xbd,0x81,0x8e,0x85,0x14,0x52,0x34,0xee,0x70,0x17,0xec,0xee,0x86,0x36,0xc7,0xba,0x76,0xeb,0xef,0x5b,},{0xfd,0x7f,0xdb,0x3d,0x02,0x2b,0xa3,0x6e,0xad,0xfe,0xd0,0xda,0xaa,0xe5,0xbf,0xf0,0x45,0x05,0x40,0x3f,0x17,0x14,0x73,0xe4,0xd3,0x61,0xee,0x8d,0x15,0x0a,0x0e,0xb4,},{0x67,0xa6,0x67,0xee,0x0d,0x62,0x54,0xca,0x0a,0x8f,0x21,0x25,0x82,0xc0,0xcb,0x8b,0x6e,0xd9,0x7c,0xc9,0x67,0xdb,0x02,0x12,0x96,0xad,0x6a,0xa9,0x9f,0x0a,0xd3,0xa9,0x44,0x97,0x8c,0xfd,0xaf,0xf1,0x3f,0xe5,0xf8,0xc6,0xe8,0x8c,0xbd,0x83,0x1a,0x54,0x73,0xd0,0x74,0x2e,0x37,0x34,0xb3,0xe2,0xdf,0x00,0xff,0x32,0x40,0xa5,0xde,0x02,},"\xbc\x29\x8e\xd6\x98\x92\x90\x40\x28\x72\x5e\x21\xb1\x14\x46\x2d\x89\xd8\xc0\x06\xdc\x88\x4b\x17\x87\x56\x83\x8a\xf4\x95\x4f\xf0\xf1\xb7\x95\x17\x30\x7a\x25\x8a\x0e\x76\x81\xe8\x79\xac\x47\xd7\x92\x02\x30\xb0\xcc\x1d\x66\x17\x1e\xb2\x14\xd7\x7c\xd9\x7f\x61\x7c\x40\x5e\x6c\x21\x72\xfc\x58\x9f\x16\x25\xcc\x5e\x1b\x59\x31\x10\x53\x1f\x6e\xb5\x3f\x1e\x6f\x48\x6d\x19\x64\x61\x24\x47\x75\x0a\x04\x1f\xe5\x1b\x33\x2e\xb3\xfb\xc7\x11\x61\x6c\xe3\x5f\x04\x04\x42\xb4\x31\x63\xb8\x0b\x75\x1e\x21\xec\x12\x45\xf1\x2e\x48\x83\xc7\x9d\x3b\x41\x32\x82\xc6\x9b\xfc\x6a\x46\x5d\x1e\x78\x96\xba\xb0\x38\xdc\x89\xb4\xcf\xc0\x32\xfc\xcd\xfc\x87\xb0\x7f\x06\x11\x0e\x1f\x50\x6a\xcc\xa8\x15\x7a\x32\x25\x43\xbf\x1e\xd8\x90\x67\x27\xf2\x8d\x0d\x68\x9b\xcd\x7d\xd3\xdf\x85\x93\x52\x04\xa9\x04\xab\x3f\x7a\x0d\x99\xc1\x6e\x5a\x54\x2c\xc2\xbc\xde\xbf\x5b\x50\x2d\xba\xbe\x33\xb9\x72\x48\x0e\x02\xe7\x1a\x43\x8a\x19\x80\xa8\x76\x6f\x10\x8b\xd8\xad\x51\x10\x42\x23\x99\x4d\x9b\xfb\x3c\x3a\x4b\x7a\x59\x23\x8c\xe2\xef\x7d\x72\x88\x38\x3f\xfb\xf2\x91\xe1\x60\x2b\x38\x4a\xf6\x07\x00\xd7\xda\xf0\xe8\xfe\x60\xf8\xca\xed\xe4\x3d\xb0\x6b\x3f\x4c\x8c\xff\xf7\x49\xae\xaf\xa4\x6f\xc6\x1c\x49\xb2\xd5\xa4\x12\x04\xcf\x86\xf0\x49\x25\x4d\x80\x9e\x94\x98\xaa\x9d\x4c\xfd\xb9\x4a\xcb\x2b\xab\xfc\xf7\x86\xdd\xfb\x03\x69\x15\x16\xb3\x83\x8b\x0d\x4f\x20\x1c\xb2\x59\x1e\xdb\xb0\xb0\xf6\x74\xe1\xe2\x82\x03\x16\xb7\x2e\x81\xb4\x8c\xc5\xa6\xb2\x93\x38\xbc\x36\x68\x1f\x8f\x7d\xca\x43\xee\x6c\x0b\xd2\xe4\x02\xaf\xbf\x96\x77\x97\x51\x64\x53\xbc\x01\xbe\x86\xbf\x42\x29\x9d\x1b\x73\x6a\x0d\x97\xbb\xc9\x22\xf5\xa7\x8a\xf2\xdf\x42\xe6\xf8\xc2\x8e\x95\x3f\x2c\xea\xda\xff\xc5\xe9\x30\x64\x04\x1e\x42\x5a\xd6\x97\x5f\x88\xc7\xaa\xdf\x81\xc3\x68\x69\x1a\x58\x1e\x88\x5f\x2a\x6b\xa7\x2e\xd6\x8b\x8f\xef\xbc\xd6\xce\x36\x86\x26\xd4\x48\x92\xa2\x02\x70\xb5\xf7\x09\xc2\xe3\x4b\x83\x35\xd4\x2e\xeb\xd6\x7a\x24\xdf\x73\xf4\x54\x55\xc4\x19\x44\x18\x7b\x66\x92\xf0\x54\xb2\xfc\x95\x91\x37\x3f\x19\xfc\x71\xaa\x7f\xa2\x7d\xf6\x00\x6a\x1d\x54\x9b\xbf\xae\x7d\x3c\x3e\xb3\x6e\x5a\xb2\xaa\xa1\x0a\xa5\x53\x8d\xa7\xef\x36\xc8\xff\x35\x4b\x60\x58\x13\x40\x04\xd6\x60\xa4\x03\x63\x21\xca\xad\x00\xa3\x0b\x1c\x49\x8b\xa3\xd8\x08\xc4\x40\x5e\xf7\x96\x18\xfc\x22\x12\xa7\xb8\x33\x96\xa3\xd7\xce\xdc\xeb\x86\x3c\x66\x37\x4d\xc4\x69\xae\x18\x3c\x7e\xd7\x4b\x3e\x70\xd6\x37\x4a\x06\x2d\xe0\x37\x9b\x21\xcf\x25\xd3\xc4\xc5\x76\x21\x15\xcd\xfe\x75\x55\x45\xe8\x9a\xd4\x05\x2b\xb0\x27\x9d\x93\x8e\x90\xde\x3a\xbf\x50\x44\x10\xca\xad\x72\xb7\xc2\x9f\x53\xd0\x1d\x9d\xd7\xf2\xec\x5e\x45\x9a\x04\x59\x2b\xdd\x66\x41\x66\x13\xe6\xed\xd0\x04\x56\x9e\x0e\x6c\x98\x82\x7b\x8c\x1d\x70\x02\xa6\xd1\xbf\x30\x3e\x18\x25\x95\x01\xdd\x89\xf6\xee\x94\x76\x6d\x18\xaf\x81\x04\x63\xeb\x13\xb2\xef\xdd\xf1\x72\x3a\xf7\x35\xa8\x87\x16\xe1\xfc\xb4\xb7\xb4\x3c\xb9\x7e\x1c\xc9\x03\xb2\x40\x8e\xf4\x53\xad\xa4\x16\x47\x86\xf0\x08\x45\xfb\xfa\x1f\xfc\xa5\xcc\x3e\x1c\x4b\xd9\x94\x0e\x7d\x99\xae\xf9\x19\x16\x6d\x05\x8b\x51\x45\x3c\x9c\x14\xfb\x9f\x32\x51\xec\x5f\xe4\xf1\x53\xc7\x0a\x44\x92\xdc\x34\x96\x29\x61\x86\xf2\x3a\xd4\x7e\xba\xd1\x3c\x66\xe6\x87\x27\xce\x50\xba\x94\x87\xf1\x80\x18\x90\xb6\x93\xef\xeb\xfc\x37\xbb\x5d\x95\xf8\xaf\x54\x8e\xc8\xd6\x49\x82\x89\xe5\x5f\x98\x83\xfc\x5b\xe8\x4c\x25\x6d\x2b\xc5\x48\x49\x38\xc7\x09\x82\x0d\x9b\x6b\x80\x59\xc0\xaa\x42\x67\xdd\xe6\x90\x78\xe4\x87\xc8\x86\x5c\x0b\x13\x0a\x0c\xa8\xca"}, -{{0x6e,0x26,0x51,0x05,0xee,0x71,0x71,0xd1,0xbd,0x79,0x3e,0xff,0xd8,0x7d,0x1e,0x2c,0x79,0x45,0x0d,0x5e,0x18,0x8b,0x57,0xbe,0x3a,0xa1,0x62,0xe2,0xa5,0x25,0x28,0xad,},{0x1f,0x40,0x3c,0x7a,0x75,0x50,0x31,0xc1,0x3c,0xa6,0x3a,0xf5,0x76,0x35,0xdc,0x6e,0x2c,0x4f,0x23,0xbd,0x6b,0x1d,0x67,0xca,0x65,0xda,0x68,0xb0,0x99,0x43,0xc5,0x54,},{0xb5,0xa8,0x3a,0x11,0x7a,0x60,0x34,0x5a,0x67,0xe4,0xa6,0x65,0xf3,0x7d,0xe7,0x22,0xa6,0xec,0x03,0x91,0x38,0x29,0x38,0x99,0x59,0xf3,0x76,0xee,0x62,0x64,0x77,0xe6,0x54,0xac,0x8d,0x72,0x0f,0xc7,0x27,0xd4,0xbb,0x8f,0xe1,0x54,0x4f,0x5d,0x0b,0x0b,0x85,0x05,0x14,0x29,0x0b,0x24,0x27,0x3c,0x4c,0xd4,0xb7,0x3a,0xca,0x4a,0x53,0x00,},"\xf8\xb9\xd4\xb0\x27\xeb\xb1\x0e\xe5\x11\x81\x9e\x6e\x56\xfb\x1b\xa9\x58\x40\x18\x41\x8d\x82\x88\x5a\x38\xa4\x49\x08\x60\x07\xb8\x78\x5b\x51\x05\xca\xf7\x82\xbf\x9b\x36\xda\x03\x9c\xc6\x0e\x22\x7c\x7e\x16\x14\xf2\x9b\x64\x0b\x1e\x9b\x22\x74\x7e\xea\x7a\x67\x25\x61\x4e\x89\xe0\x78\x3e\xbe\xbb\xb7\xee\x55\x7e\xf3\x6b\x2b\x46\xcf\x64\x61\xe5\xbe\x2a\xd1\xd7\xa7\xc2\x71\x1a\x47\x5c\xa4\xfb\xc3\x30\x92\xba\x42\x56\x67\xe3\x4d\x09\x00\x60\x51\x8f\x2f\xec\x63\x6b\x04\x91\x23\x87\x6a\xb2\x1c\x8b\xd9\xc5\x0d\xcc\xb9\x84\xca\x01\x1a\x02\xee\xa0\x20\x56\x4f\xa8\x21\xfc\x36\x2b\xfe\x39\x2a\xab\x50\xc2\x73\xfc\x7b\x5a\x04\x21\x88\xe3\x31\x62\x1b\x9d\x2f\x74\x3e\x5c\x8c\xf3\xab\x1f\xaf\xfa\xfe\x2a\x00\x04\xc8\xef\x7c\xdf\x5e\x6d\xbb\x5e\xb5\x44\xe4\x28\x9f\x71\xa6\xfd\x15\xc6\x38\xce\x29\xd2\x8e\xfb\x9c\x03\x9e\x47\x74\x29\xa3\x49\x7a\x83\x82\x7e\x76\xce\x77\xa4\x98\x16\xd9\x0b\x41\xa8\xe1\x52\xf3\x7a\x09\xe6\x34\x0d\xfe\x06\x9a\x4a\xc6\xf2\x7d\xd2\xea\xc7\x47\xfd\x21\xe3\x15\x20\x88\xc1\xb1\xec\xd3\x2a\xc6\x79\x92\x74\x90\x75\x04\x88\xc2\x91\x78\x51\x47\xb6\x3b\x0b\x8f\xf1\x1d\x18\x9b\x90\x49\xb8\xa3\x96\xb6\x93\x2f\x85\xbd\x6a\x15\xef\xf9\xf0\xce\x18\x08\x41\x1a\xf0\xf9\xc8\xe6\xe9\x7b\x81\x4f\x11\x0b\xd4\xdf\x13\x86\xa9\x79\x7d\xc5\x11\xf0\xaa\xb6\xab\x65\x07\x1d\x9e\xa8\x36\x53\x2c\xec\x51\xb9\x2c\xa7\xfb\xdb\x8d\xe1\xc8\x43\x66\x58\xde\x2e\xb6\x5e\xdd\x86\x04\x4f\x6c\x1a\xba\x31\x78\x64\x7a\xd6\x78\x61\x2e\xe7\x4f\x04\x6c\xa3\xc7\xfe\x2f\x39\xc0\x9d\xd2\xe0\x7d\xf2\xb4\x22\x70\x85\xfe\x93\x6e\x79\x4d\x22\xfd\x5f\x40\xa2\x5f\x08\x77\x15\x80\xac\x80\x1d\x98\x89\xf5\xa7\x6a\xea\xe1\xf0\xcc\x4a\x9e\x1e\xdb\xdd\xa3\x75\x0c\x74\xc8\x50\x52\x4b\x32\xf4\x49\x33\xfd\x88\x3b\x53\x72\xbf\xb7\xe7\x61\xe0\x69\xfe\x7c\x1c\x0e\x7f\xbd\x4a\x7f\x58\x46\x7e\xa6\x88\x3f\x9d\x5b\x7f\x66\xd3\x86\xb0\x49\x9b\xb6\xfb\x5e\xad\x89\xc9\xa1\xfd\x2c\xce\xb9\x73\xe2\x87\x9b\x5d\x03\xea\xa4\x52\xe1\x60\x22\xd5\x96\x17\xda\xa0\x48\x6f\x4d\x4c\x11\x78\x07\xfd\xa8\x49\x9d\xfb\x7a\x28\x6f\xd2\xf7\x1a\x8e\xb5\xfe\x64\x06\x5c\x41\xe4\xe1\xe2\x36\x2a\xb4\xe4\x77\x96\x9e\x3a\x40\x8a\x24\x7e\x3a\x56\xfc\x86\xf2\xb0\x1e\xf8\xd3\xcd\xda\x87\x25\x82\x34\xbc\x7f\x25\xb6\x69\x07\xf3\x64\xb3\x7b\x62\x45\x29\x6c\x4f\xdf\x49\x9f\x20\x23\x7f\x48\x64\x85\x2f\xc5\xd8\xcd\x5d\x05\x41\x8b\xe8\xb1\x38\x59\xee\x9a\x43\xe1\x7e\x1f\x57\xa4\xc3\x5e\xa2\x82\xed\x68\xeb\xcd\xa6\x82\x81\x74\x24\x5a\x49\xc6\xcb\x65\x90\xeb\x1f\x2d\xcf\xb0\x07\xbf\xa1\xc3\x20\x77\x95\x6d\xa9\xac\xbe\x3e\xf0\x72\x37\x99\xfd\xb8\x69\xd8\xde\x30\x70\x6a\x9c\x02\x68\x14\xd1\x6a\x01\xe0\x33\xc9\x1b\x59\x07\x0d\xfe\x44\x5c\x5b\x84\x8a\x51\x66\x12\xe5\x13\x1f\xe8\x48\x69\x21\xe3\x6b\x8e\x7e\xf1\x57\xa8\x88\x22\x88\x6c\x68\x1b\x5d\xa7\x1f\xea\x94\xd9\x57\xda\xfe\xc2\x6f\x41\x47\xa3\xb2\xac\x38\x3a\x5f\x47\xc8\x58\x5e\xb1\x7a\x8a\xc6\x57\x90\x64\x1b\x42\x18\xd7\x55\xf8\xbe\xa4\xd9\x7a\xe2\xa4\x5b\xdc\xdc\x23\x23\x62\x94\xd8\x52\xc9\x5d\x08\x40\x6d\x2e\x9b\xd3\x0c\x32\x64\x52\x53\x8c\x1f\x5e\x50\x04\xd4\xa1\xa8\x27\x20\xda\x32\xe5\x9d\xc3\xab\x18\xea\x08\xa0\x58\xf7\x91\xd2\x44\x18\x55\x60\x86\xc1\xe4\xed\xce\x89\x82\xaa\x23\xb1\x18\xfb\x26\x6e\x60\xb5\x42\x78\x0a\x69\x33\xad\xd9\x13\x26\x55\x12\xc0\x7b\x11\x49\x78\xd4\x4a\xf7\x3b\x20\x30\xec\x47\xb0\x6f\xd0\x9d\xda\x8c\x4f\x1d\x4e\x31\x37\x75\x46\x8c\x45\x1f\x9e\xe6\x11\xe9\xcd\x4c\x08\x45\xc2\x50\x19\x48\xa7\xb1\x4e\xf1\xd4\xb5\xcf"}, -{{0xc4,0x37,0x0d,0x2a,0xaf,0x35,0xac,0xd1,0x58,0xfc,0x0d,0x16,0x22,0xa3,0x99,0xc9,0x9f,0x41,0xb9,0xda,0x4e,0x97,0x0b,0x35,0x4e,0x5b,0xa0,0x5c,0xbe,0x84,0x4c,0xa8,},{0x35,0x45,0xd7,0xd4,0xc9,0x5c,0x3d,0xb6,0xa5,0x45,0x30,0x53,0x7a,0xfa,0xfa,0x4d,0x86,0xdd,0xec,0xf9,0xcc,0x7e,0x66,0xc3,0x19,0xba,0x9f,0x7d,0xd7,0xd0,0x7e,0xe7,},{0x9f,0xeb,0xab,0x5a,0xe1,0x61,0xd6,0x92,0xa6,0xa3,0x94,0x50,0x0a,0x28,0x90,0xd2,0x1c,0x7f,0x0e,0xe2,0x6f,0x46,0x40,0xaa,0xba,0x4f,0xe6,0x6b,0x90,0xb8,0x9e,0xdc,0xb8,0x0e,0xa4,0xcd,0xca,0xbb,0x4d,0x2c,0x3a,0x5c,0x41,0x54,0xe8,0xff,0x20,0xd0,0xe2,0x37,0xfe,0xfd,0x00,0xc7,0xba,0x97,0x82,0xe1,0x74,0x8f,0x64,0x88,0xac,0x01,},"\x61\x9f\x57\xde\x2b\x1d\xba\xee\x20\x9a\x82\x5d\x8c\xa9\x7f\x84\xee\x49\xeb\x12\xa0\xb1\x3d\xcd\xd2\xb3\xa4\xee\x45\xe0\x17\x6d\x47\x4c\xf0\x94\x60\xc8\x31\xa8\xae\x1d\x3f\x39\xbe\xeb\xd0\x88\x08\xb3\xed\x17\x61\x21\x3b\xa9\x53\x42\x18\x60\xcc\x07\xe2\xdb\x31\x2e\x68\x0d\xf0\x3e\x60\xa6\x87\x02\x64\xab\xca\x8f\xd5\x13\x01\xe1\xc1\x56\x20\x23\xd8\x02\xcc\xd5\xc7\xd1\x96\xdb\x39\xfb\xb8\x30\x4b\x0e\x59\xe3\x33\x16\x41\x92\xec\xc3\x33\x38\x7e\xef\x69\xc7\xa7\x8a\x5d\x11\x25\x88\x62\xd6\xc2\x81\xb1\x9c\x0b\xd3\x36\xcd\x3e\xdb\x2f\x9f\xaa\xd4\x02\x1a\xc2\xf2\x05\xc1\x68\x14\xb3\x85\x48\x43\x3f\xf9\xed\xdf\xd6\x11\x33\x77\x97\x69\xdc\x69\xaf\xac\x65\x8a\xfc\x1d\x1b\x41\x6d\x39\x0a\xd5\xb4\x5a\x1a\xd5\xcc\x4b\x00\xb4\xb2\x78\xfb\xe4\xb5\x9d\x52\xe6\x1a\x6a\x5f\xd0\x02\x41\xc6\xcb\xc3\x82\xd2\xd6\x21\xa3\xde\xd0\x02\x01\x9b\x33\x05\x60\xe3\x61\xfa\xab\x28\xf4\x1d\x1a\xf9\xc9\xc0\x02\x0f\x2b\xaf\x99\xe8\xd8\xee\x58\xe3\x12\x22\x02\x14\x7c\x0a\xdc\x57\xd6\x70\xc5\xb3\x80\xaf\x59\x4c\xc7\xed\x57\xb8\x7e\xc6\x67\x4a\xb6\x3f\x3a\x98\x49\x75\x3b\x94\x62\xaa\xb5\xde\x88\xc9\x48\xa8\xb1\x09\xaf\x4d\x49\x54\x92\x7a\xac\x58\xbe\xe9\x53\xbe\x0d\x8d\x7d\x71\xaa\x11\xd1\x1f\x1a\x87\xb1\x47\x7b\x91\x70\xbd\x73\x5c\xfc\x24\x49\xf0\x51\xb8\x2b\xc5\x9b\x0b\xee\x76\xa1\x72\xe8\xd3\x26\x70\xf5\x1d\xdd\xdb\x80\x4a\xd1\x10\xa5\x65\xe3\x84\xcd\xb7\x6f\xad\x04\xcf\xf6\x78\x93\x09\x1e\x41\xe6\x9c\xfd\xf7\x0e\xa9\x26\xc2\x63\x69\xa5\xb6\x19\x3b\x19\xab\x0a\x62\x55\x8d\xa5\x5f\xfa\xfe\xb8\x78\x97\x57\x71\x06\x44\xaa\x19\xf4\x74\xbe\x4a\xda\x9d\xc1\x84\x9b\x07\xd5\xe1\x7b\x85\xf9\x21\xe1\x01\x6a\x54\xaa\x60\x95\x77\x72\x53\xa7\x34\x26\xfc\x78\x64\xb9\x95\x5f\x04\x90\x70\x23\xdb\x20\x7f\x85\xdd\x21\xa6\x51\x06\xcf\x0d\x62\x23\x85\x87\x0c\x34\xc2\xda\x9a\x11\xe4\x72\x63\x95\x12\x1e\x4a\x67\x61\xfb\x52\x22\x29\xd9\xe5\xcc\x9d\xab\x35\xae\xb8\x7d\x0d\x79\x69\x3c\x00\x6f\xde\x1c\xfa\xf1\x16\x20\x8b\xba\x96\x20\x59\xcf\xc0\xd2\xd6\x37\x0a\xac\x77\x48\x36\x2e\xe6\xa0\xa3\xca\x7b\xf1\x33\xeb\xcf\xa2\x0f\x1c\x4e\xd8\x30\x7f\x80\x0c\xca\x7e\x6c\x4b\xea\xa3\xfb\x2a\xb0\x86\x12\x53\x64\x28\x5c\x44\xed\x1a\x73\x7a\x67\xcb\xf3\xb7\x63\xc9\xf8\xb1\x42\x7e\x89\xdf\xa9\x6d\x29\x0e\x9d\x48\x42\xfe\x63\x16\xaf\xef\x83\x4c\xd8\xcd\x1f\xdc\x1f\x12\x4c\xa3\xfe\x26\x26\x6d\xa6\x2e\x27\x5c\x0b\xf7\xfc\xc8\xe5\xf9\xbb\xa6\xc0\xd3\x8e\x23\xfa\xfa\xb1\xe0\x49\x48\x17\x94\xc1\x4f\x4a\x8c\x53\xbe\x1c\x96\xf7\x69\xc9\xb1\x3e\xac\xa3\x9a\x0e\x49\x36\x6d\x2c\x9f\xfe\x8f\x20\x63\x60\xa9\xd5\x03\xde\xc5\x98\x62\x11\x12\xe3\x77\x67\x13\xe7\xfc\x06\x49\x43\x3e\x25\x7e\x50\x3a\x54\x60\x59\xa9\x89\xda\x89\x15\x7d\x76\x47\x60\x05\xfd\x90\xe4\xb0\x7a\xaf\x0d\xb0\xbc\x0b\xc0\xb6\x7d\xb8\xdc\xba\xdf\xf3\x93\x74\xe1\xaf\xae\x55\x16\x34\xe0\xe3\x28\x31\xad\x0e\x5f\xa7\xd5\x21\x6f\xa7\xc6\x44\xf7\x3e\x1e\x8e\x07\x23\x83\x94\xa4\x16\xc1\x69\xaa\x9d\x53\x03\xf4\x69\xa5\xd4\x07\x43\x08\x72\x1f\xfd\xde\xff\x65\x59\xe5\xad\xf0\xc2\x77\x3b\x3f\x52\x64\xe7\xaa\xa8\xc2\xdb\x88\x8e\x28\xe8\x15\xc7\x10\x69\xc3\xb4\xce\x6c\x29\x03\x4c\x0a\xb3\xb5\xc1\x9a\x80\xa9\xd8\xc2\xe8\x74\x81\x35\x31\xc4\x22\x75\x2a\xd6\x2b\x3c\x5a\x1a\x3d\x6c\x5a\x5d\xb5\x87\x27\x06\x93\xaa\x75\xd5\xf1\x72\xee\xdd\xf4\xeb\x83\x9b\xd7\x93\xaf\xfb\x1c\x79\x6a\x1d\xf0\xe4\x42\xdd\xf9\x9b\x78\x0a\xa4\x1e\xea\x0f\xe6\xf8\x65\xbb\x53\x9c\xa5\x3a\xa4\x5d\xb9\xa8\x56\xcb\x75\xd0\x15\x1d\x35\xed\xea\x80\xf2\x94\x6d"}, -{{0xbd,0x3d,0xe1,0xa1,0xd1,0x64,0xbd,0x6e,0x9b,0xe0,0xa6,0xd1,0x07,0xf7,0x03,0xa6,0xdd,0x91,0x4c,0x86,0x67,0xcd,0x34,0x1d,0x13,0x9f,0x19,0x57,0x8d,0x93,0x3b,0x16,},{0x9b,0x02,0x49,0x64,0xbd,0xfa,0x85,0x2e,0xb2,0xd4,0x14,0x4f,0x35,0xb7,0xcd,0xc2,0x67,0x81,0x14,0x3c,0x2b,0xd7,0xf6,0x60,0x23,0x3f,0x8b,0x8a,0xa3,0x60,0x71,0xee,},{0x13,0xcc,0x15,0x8f,0xd0,0x61,0x79,0x2f,0xce,0xd1,0x56,0x87,0x95,0x98,0x25,0x1d,0xd0,0x1d,0x57,0x5b,0x40,0x0f,0xe3,0xe3,0x9a,0x70,0x08,0x63,0xaa,0xe8,0xdb,0x1f,0x91,0x97,0xfa,0x50,0x1c,0x0c,0xf9,0x93,0xe4,0x4d,0x6a,0xc5,0x51,0x80,0xb8,0x69,0x83,0x8e,0x8a,0xe2,0x4b,0x21,0x4f,0xa3,0x5e,0x24,0x4b,0x7a,0x6c,0xff,0x6d,0x0d,},"\x17\x69\xfc\xdb\xf5\x12\x47\xed\x4c\x83\xa0\x0b\xbb\xf0\x2f\x44\x28\xda\x6f\xce\xdd\xd0\x16\x1a\x02\xfc\xcd\x15\x00\x97\x06\x65\xe1\xc7\x63\x0a\xd2\x2e\x3d\x97\x49\xc7\x92\xe7\x1a\x26\x0c\xff\xf6\x05\x32\x56\xe0\x2f\x5b\x47\xbb\xa1\x4b\x76\x1a\xe5\x3c\xa7\x21\x9e\xd2\x80\x1d\x2d\x78\x8e\x26\x41\x9f\x36\xc8\x1e\xf9\x2c\x23\x03\x68\x37\x35\xc8\xa1\x75\x6a\xda\xb6\xa4\x87\x92\x31\x53\xe4\x35\x60\x3c\x96\xb2\x39\x55\x3e\xdf\xde\xb0\x93\x29\x8f\x7a\xe7\xdc\x90\xf1\x6a\x7e\x56\x64\xb9\xe4\xc0\x2b\xa7\x31\xa2\x3c\xf2\x23\x4e\x25\x0a\xc9\x74\x26\x33\xa9\x32\xa9\x48\xbb\x83\xdc\x3d\x79\x4d\x05\x9f\xed\xf4\xec\x86\x18\xc7\x43\x3c\x5d\x8f\xe5\xe6\x2c\xf0\x7b\x57\x68\xc4\xd9\xb2\x61\xc7\x15\x36\x80\x4f\xe2\xe7\xca\x70\x98\x87\x65\x21\xd5\x76\x77\x36\x14\x24\xe4\x7f\x1b\x95\x92\x37\xf9\x07\x10\x42\x1f\x5b\xc4\xf1\x09\xf7\xd4\x89\xc7\x55\xe9\x4e\xef\xdf\xb3\xc8\x5b\x90\xec\x01\x31\x81\xa2\x3b\xb9\x53\x5f\xee\xa4\x94\x1d\x0a\x06\xa5\x40\xbd\x6b\x58\x8e\x55\xb7\xf3\x57\x57\x14\x9c\xa3\xe6\x40\x96\x5e\x1a\x0f\xf7\xf3\xc8\x25\x92\x59\x95\x7f\xf5\xda\xb9\xfb\x87\x32\xea\xe7\x19\xb6\x24\xa4\x49\x28\x78\x17\x9b\x5a\x83\xab\xe5\x1c\xaf\x02\x08\x3d\x73\x7c\xeb\x4f\xcf\x04\x2f\x2e\x60\xba\x02\x97\xac\x72\xb8\x7f\xe3\xe1\x4b\xa5\xfb\xc5\x4b\x48\x09\x10\x73\x89\x68\x23\xbf\xa2\x89\xce\x8e\x16\x87\x3b\x48\x81\x2c\x32\xbf\xea\x5f\xf6\xbb\x22\x1d\x1e\xa5\x46\x3d\x32\x5b\xbe\x31\x1e\x7f\xd1\xe7\x83\xde\x65\x0b\x79\x52\xea\xe4\x61\xd6\x3b\xc7\x47\x05\x22\xaf\x5b\x77\x89\xf8\xfc\x2e\xb1\x92\xd2\xcf\x77\x6c\x5c\x24\xb4\x4e\x29\xcd\xb0\xcc\xcb\x1d\x90\x36\x14\x38\xe4\x95\x0f\xf3\x4d\xbc\xb3\xcb\x0e\x81\xcc\x45\xf8\xd0\xff\x57\x09\x49\xf7\x80\x84\xe1\x06\x0f\xf5\x59\x4a\xd5\x16\xf5\x0f\x1c\xb0\xa7\x65\xe1\xc0\xe0\x38\xd5\x94\x3b\x93\x6e\x4a\x8b\x49\x33\x54\xe7\x9a\xbc\x91\x7b\xb9\x27\x12\x66\xee\xba\x77\xa9\x3a\x65\x7f\x9a\xd8\x7b\x29\x1a\xc7\xea\x38\x6f\x5d\x4f\xcb\xc5\x82\xe7\x2d\x5c\x23\xd9\x2b\xa9\x44\xb0\x06\x4c\x20\xe3\xe2\xdc\xf5\x04\xbc\xc7\xc6\x96\x6c\x63\xf2\x08\x08\x43\x60\x0b\xa3\x13\xec\x27\xcb\xa9\x5e\x7e\xf3\x18\x16\x8c\x90\x67\xdc\xe8\x6c\x1e\xf0\xd5\xd9\xeb\x7a\x61\x58\x48\x9d\xf3\x2e\xd5\x8b\x69\x31\x03\x08\x18\xf0\x07\x05\xa0\xdc\x55\xd3\xdb\xf8\x00\x6a\x85\x46\x64\x1b\x18\x65\xd9\x19\xbc\x24\x22\x02\xcb\x3a\xe3\x00\xbf\x86\x53\xe3\xb3\x78\x94\xc3\xdc\x0e\x47\x7b\x9d\x7c\x41\xba\xf8\xd3\x88\x7c\x2e\xb5\x9b\x1e\x4d\x50\xbb\xb6\xf1\x79\x2a\x1c\x93\x67\xc6\x5c\xdb\x45\x0c\x2d\xfa\x21\x45\xe6\x11\xa9\x7a\xd8\x1c\xff\x1f\xd8\x3c\x6c\xf7\x23\x09\x47\xea\xff\x4c\x21\xdc\x1b\xaf\xb7\x1e\xc4\x1e\x5b\xc7\x2b\x37\x45\xec\x3e\x38\xbf\x59\x30\xc1\x26\xd0\x60\xf0\xc5\x0a\x89\x5f\x00\x9a\xa1\x8e\x87\xf2\x17\x4f\x58\xab\x53\x79\xa7\x21\xfd\x83\xaa\xd5\x51\x7f\xd9\x9d\xff\x14\x6e\xde\xea\x61\x52\x12\x35\xe2\xf1\xa1\x6e\xe5\x83\x03\xe0\x91\xbe\x8d\x57\x90\x94\xc1\xd8\xa2\x0b\xc7\x4a\x55\x0d\x77\xc0\x0d\x08\x75\x71\x51\x7a\x63\xcd\x41\x26\x93\x3a\x4f\x09\xa0\x70\xbf\x8e\xa4\xff\xb8\x46\xa9\x78\x0e\x97\x34\x04\x3b\xac\x4c\x0f\xf4\x7b\x1a\xfc\xcf\x52\x93\xac\x14\xbc\x73\xeb\xf6\x71\x29\x65\x7e\x4b\x8a\x8b\x33\xdd\xac\x7b\x0f\x4d\x71\x9d\x2d\xc6\x5d\xf6\xea\x0a\x3f\x24\xcf\x44\xc8\x33\x8e\xd6\x01\xa3\x93\x9c\xa3\x58\xfc\x4b\xe1\x3e\x8e\xde\x02\x75\x39\x71\x2c\xa2\x3e\x3f\xfb\xa7\x06\xe8\xfd\xd6\x2a\x07\x4e\xe0\xad\x74\x20\xf7\x80\x60\xcc\x96\xfb\x2a\xbf\x30\xe9\xea\xa2\x41\xc0\xf8\x7e\xbb\xe3\xec\x73\x51\x75\x96\xf7\xc3\xc5\xa8\x0c"}, -{{0xf6,0xae,0x51,0x6a,0x51,0x29,0x6f,0xc5,0x23,0xce,0xa5,0xf0,0x08,0xcf,0xbd,0x09,0xe7,0x3f,0x78,0xb6,0xfd,0xd3,0xb6,0x94,0x26,0x12,0x80,0x41,0xa5,0x60,0x4c,0xf9,},{0x37,0x6c,0x82,0xba,0x7b,0x87,0xaa,0x77,0x41,0x87,0x27,0xdb,0x33,0xd3,0x26,0xae,0x75,0x8b,0xf7,0xa1,0x35,0xc1,0x04,0x60,0xcd,0x8b,0xf8,0xfe,0xb8,0x3c,0x2b,0x10,},{0x0f,0xe4,0xdd,0x7e,0x1f,0x60,0x8e,0xe8,0x2b,0x7f,0xe8,0x63,0xd1,0xb0,0x3a,0x81,0x84,0x3c,0xe2,0x0c,0x76,0x2c,0xd8,0xbb,0x24,0xef,0xd4,0x6b,0xa0,0x25,0xff,0xf3,0x33,0x1d,0x87,0x57,0x52,0xca,0x72,0x20,0xc5,0x3d,0xd3,0xc7,0x1f,0x2b,0xc1,0xe2,0xc6,0x4a,0x2f,0x9c,0x58,0x86,0x5a,0x2a,0x24,0x48,0x09,0xf4,0x13,0x4e,0x53,0x07,},"\x83\x42\xf2\x5a\xc4\xb1\x7e\xba\xd6\xf7\x9b\x9a\x03\x31\x75\xc7\xf2\x8a\xf0\x9e\x65\x8e\x8c\xb9\x8c\x29\x4f\x15\xc3\xc8\x34\x26\x29\xcb\x2a\x32\x47\xdf\xc8\x75\xb8\x2f\x5b\x38\x0c\x5d\x11\x42\x6a\x2e\xeb\x62\x45\x0b\xd8\x85\x65\x01\x07\xc6\x83\x62\xa3\xb7\x2c\xe8\x23\xf2\xd1\x59\x42\xb7\xdd\xa3\x01\xd2\xfb\x63\x8f\x30\x2a\xa9\x57\x0b\x47\x91\x1d\xad\xd3\xbd\xdb\xfe\xd5\x54\xc1\xc8\x0b\xd7\x18\x07\x8b\x8b\xd2\xc9\xc3\x14\xa5\x16\x6f\x26\x5e\x82\x66\xee\x2d\xb3\x57\x56\x1a\x55\x85\xc4\x14\xa7\x84\x0b\xfa\xe6\x09\xd7\xcd\xdd\xe1\xfa\xde\x85\x56\x0f\x23\xd6\x38\xef\x3d\x52\xe5\x1f\x5c\xf3\x13\xa0\x72\xc5\xea\x0f\x81\x7f\x72\x81\xe2\xcb\xa5\xc5\xc8\xd2\x6c\x92\x85\x92\xb8\x1f\x0f\xf8\xcd\x18\xdb\x5a\x2c\x41\xd8\x80\xd7\x44\x73\x86\x3c\x7b\xbd\x00\x56\xfa\x4d\x4a\xfa\xbd\x17\xa3\xb8\x9d\x97\xd3\xfe\x5d\xc0\x6b\x0f\x61\x2a\x1d\x66\x42\x39\x23\xba\x8d\xfb\xb8\xec\x82\x46\x62\x4d\x83\x78\x4e\xba\x4f\x57\x36\xba\x38\x5e\x44\x22\x96\xc8\xcb\x0f\x1b\x68\xe0\x33\x42\xb2\xc6\xc1\x03\x34\x6f\x6d\xd7\x40\xe2\x6c\x3d\x13\xca\xef\x80\x1d\x1b\x26\x21\xd8\x9f\x06\x93\x91\xa0\x78\xd4\x3a\xe6\xff\x12\xee\xca\x66\xbc\x32\x63\x7b\x45\xf0\xac\x62\x7c\x2d\x7b\xbf\x8a\x49\xd9\x46\x81\x75\xe2\x68\x85\xe0\x28\x21\xd3\xa3\xba\xa2\xc3\xe3\xa6\xbb\x96\xb5\x75\x26\xe2\x24\xcf\x3d\x85\x9f\x66\x95\x73\xcb\xd5\xc8\x73\x93\x74\x61\x56\xf3\xd1\xc7\xa8\x03\x08\xdc\x1f\x24\x05\xbf\x0d\x40\xbe\x1c\xa7\x3b\x76\x7d\xed\xf4\x03\x13\x37\xc0\x81\xbf\xa3\xae\x6e\x54\xf6\x02\x3f\x42\xf0\xcb\xd8\x77\x62\xdb\x55\x91\x3c\x70\x72\x06\x03\x40\x10\xdf\x2a\xa8\x75\x3d\x03\x0f\x03\xc2\x67\xe7\x1a\x9d\xd2\xc6\xc1\x9d\xe3\xe1\x85\x1a\xbf\xac\xbb\xd5\xdd\x5b\xf8\x96\xfa\xb8\xe4\x15\x31\x7b\x49\xf1\xe4\x09\x6e\x3d\xa9\x9a\x5b\x5d\x0a\x3c\x42\xda\xf9\xde\x94\x84\x7c\x1e\x53\xc8\x81\x8a\x5b\x84\x33\x23\xf5\x01\xe3\xa7\xfa\x68\xdf\x89\xa5\xf4\x1f\x2c\x62\xc3\x8d\x17\xf2\x50\xb0\x2a\x67\xfa\xe4\x7d\xaf\x06\x3f\x55\x89\x42\x37\x7e\xf8\xa8\x90\x52\xf1\xa2\x15\xd7\x68\xf7\x91\x3a\x7e\xc1\x4e\x98\xb8\x1e\x4b\x2c\xcf\x26\xba\xca\xd6\xf3\x96\x64\xaf\xc0\xe9\x1a\x3c\xad\x69\x1d\xb2\xbf\x56\xa7\xab\x66\x77\xb4\x95\x96\xdb\x88\x7c\x97\xde\xf4\x35\x08\xa7\xa2\xec\x2a\xb7\x55\xec\x36\x8e\x2e\x53\xd1\xe1\x6b\x60\xff\xf0\x9c\x3b\x52\x26\x3f\x0f\x7c\x1e\xa9\xcc\x35\x37\x31\x97\xe9\x5c\x11\xe6\xd2\x2f\xa9\xd8\x29\x9c\x42\x37\x36\xf5\x81\x4f\x1e\x79\x8d\x22\x75\x18\x60\x0d\xf6\xa7\x90\x35\x8d\xea\xe3\x8d\x56\x39\xe1\x98\x3f\xe0\x18\x43\x6e\xa5\x8b\xa8\x46\x75\x48\xc9\x29\xef\xbb\x16\xdf\xea\x41\x02\x25\x3a\x35\x0f\xb8\x4d\x98\x31\xc4\xc2\xcb\xcb\x76\xe1\x8d\x7f\x3e\x95\x36\x41\xad\xa4\x14\x21\x39\x30\x91\xe6\x3d\xfe\x66\xde\x24\xc9\x92\x32\xc7\xd6\xa2\x83\x7a\x48\x98\x3c\xf5\xb1\x63\x31\xce\x00\x05\x0d\x1c\x71\x39\x58\xff\xce\x5f\x2e\x93\x48\xc5\x2f\x53\x12\x05\x79\xa7\xc9\xa1\x60\x08\xd1\x34\x83\x8e\x59\x61\x29\xc7\x02\xfc\xd2\x11\x48\xbd\xf9\x17\x4d\x48\xe2\xda\x0a\x8a\x66\x35\x9e\xde\xe0\x1c\x50\x09\xef\x67\x42\xfe\xc4\x1c\x1a\xce\xcd\x03\xef\xe1\xcc\xc9\xb1\x30\xd6\xe5\xac\x92\x57\x6a\x85\xcc\xb7\xcf\xc7\xd0\xe4\x23\x31\x06\x17\x29\x31\xa0\x86\x99\x79\x0b\xc4\x1a\xcf\xbb\x73\x1a\xdb\xb2\x6d\x56\xb3\x9a\xaa\x5b\x33\x3b\xc1\xa1\x0e\x2c\x70\x64\xca\x86\x11\x9d\x8c\x71\x71\x48\xf9\x24\x41\xaf\x24\xcd\x2a\xa8\xf5\x7c\x86\xba\x38\xa5\x9a\x10\x0b\x92\x76\xdf\x38\x27\xec\x7f\xb4\xd3\xfa\xf5\x8b\xe3\x1c\x6e\xca\xfd\x69\xcf\x1c\x64\x10\xa4\x9c\xd7\x08\x1f\xf6\xe9\xfc\x39\x7c\x2d\x20"}, -{{0x83,0xf7,0x89,0x90,0x0f,0x04,0x0d,0xc6,0x2f,0x4d,0x18,0x78,0x4c,0xb6,0x4b,0x63,0xc8,0x8e,0x8d,0x18,0x00,0x16,0x96,0xbb,0xeb,0x47,0x07,0xc4,0x69,0xd1,0x1a,0x5b,},{0xed,0xfc,0x2b,0xab,0x7e,0x79,0xf4,0x00,0x37,0xfe,0x4d,0x90,0x41,0xde,0x48,0xda,0x9a,0xee,0x8f,0x97,0x80,0x98,0xd7,0xb0,0xae,0x17,0x92,0x90,0x25,0xe4,0x27,0x3d,},{0xea,0x65,0x82,0xcc,0x23,0xe0,0x46,0x09,0x17,0xf7,0x82,0xd9,0x64,0xe3,0xbb,0x6d,0xcd,0xe0,0xae,0xea,0xc4,0x2c,0xc1,0x49,0x19,0xd3,0x6c,0xe7,0x8a,0xa0,0xaf,0xd9,0x80,0x72,0xf5,0x4c,0x79,0x5f,0xbf,0xd7,0xa4,0x1d,0x99,0xd7,0x06,0x06,0xc2,0x8a,0x5d,0xcf,0x19,0xbe,0x38,0xa0,0xce,0x2d,0x09,0xbb,0x8f,0x84,0x4c,0x31,0xbf,0x00,},"\x6c\x11\x2a\x20\xd3\x06\x57\xab\x5f\x8c\x5c\x04\x47\x8d\x6c\x42\xd1\xc6\xbd\xef\x38\xcd\x4f\xe0\x06\xac\x2a\x57\xe2\x90\xff\x29\x28\x78\x96\xee\xa8\xc3\x0a\x01\x39\xc1\x8f\xc8\xc9\x75\x64\x56\x3e\x86\xc8\xd3\x40\x56\xa6\x71\x9b\xfe\x47\x9d\x9e\x87\xe8\x1b\x19\x45\x23\x31\xbf\xa1\x54\x80\x68\x82\xe5\x03\x9a\x20\xc9\xe9\x54\xb1\xfc\x7c\x01\x5d\xcf\x58\x15\xbd\x7c\xf7\xb6\x35\x7d\xf9\x28\x0b\x9b\xd4\x3f\x89\xff\xc9\x19\x45\x32\x3b\x5a\xcb\x2a\xe0\x02\x54\xd4\x16\x28\x68\xd1\xc8\x3e\xc6\xe0\xfc\xbe\x7a\x8a\xb9\x25\x41\x92\x14\x9c\x6b\xc9\xe5\xfe\x35\x06\x94\x16\x5d\x66\x38\x33\x1e\xb2\x4e\x3b\x13\x90\xc6\x98\xc4\x83\x83\x78\xc0\x1b\x2c\x61\xa3\xeb\xe2\xc0\x60\xb9\x8b\xa6\xee\x02\xb5\x19\xb4\xea\xc1\xe0\xbc\xc0\x9b\x23\x24\xcc\xf5\xb1\xa7\xfe\x8f\xd0\xb1\x54\x5a\x94\x27\x83\x2a\xbb\x25\x74\x4e\xeb\x36\x32\x6b\xe6\x4e\xfe\xd3\xa7\xb0\x7d\x63\x0a\x21\xc3\x08\x1b\x55\x26\x1c\x35\x32\x87\xc6\x6c\x57\x66\x3a\x99\xdb\x46\x6a\x5d\xee\x22\x74\x6b\x81\xc7\x50\xef\x85\xbe\x51\x14\x3e\x22\x1e\xcd\xf1\x14\xfe\xf1\xb3\x08\x2f\xf5\x4f\xd0\x44\xbc\x88\x4b\xfb\x3c\xc5\xc5\x33\x59\x97\x00\x98\x67\xce\x94\x91\xa8\x0f\xe6\x96\x82\x5f\x99\x42\x6d\xef\xab\x6a\x49\xba\xdc\xde\x40\x3f\x58\xe8\x31\x79\x66\x21\x07\x47\xb5\x67\x75\x4d\xe5\x30\x76\xb3\xec\xbf\x65\x34\x6c\xb8\x39\x05\x83\x2e\x16\xd0\x1b\x50\xb9\x3d\x37\xeb\x9b\xfe\x20\x17\x2a\x31\x63\x0d\x25\xf3\x21\x7d\x87\xd9\x34\x65\xfd\x8a\xc5\x54\xcb\xbb\x39\xd9\x82\xea\xd7\x21\x93\x91\x23\x4c\x88\x9f\x0b\x92\xa2\xe0\x41\x3d\x86\x6c\xac\x08\x7d\x62\x8c\xe3\x1c\x61\xc6\x32\x3e\xcb\x8e\x68\x95\x55\xaf\x10\xde\x2b\x65\x6e\x6a\xea\x2c\xde\x93\x2e\x24\x1f\x6d\x1f\x8a\x9e\x33\x16\xcf\x13\xf1\x35\xac\xef\x83\xa0\xc0\xcf\x22\xf9\x5c\xa8\x18\xe6\x1f\x92\x76\x87\x74\xc6\x30\xe0\x92\x5b\xe9\x9d\xbd\x32\xb4\x99\xc0\xfe\x7d\x84\xa4\x2e\x39\x32\x87\xf6\xf5\xce\x3d\x0b\x27\x1f\x17\x00\x45\xa6\xd4\x8e\xab\x31\x6f\xe1\x7b\x18\x58\xb1\xff\xee\xe9\x08\x88\xf3\xa3\x7a\x24\x80\xdf\xd0\x4a\x4a\x86\x29\xf8\x68\xb5\xc0\xa8\x0e\xe1\xf0\x37\x19\xf3\xa4\x7d\x40\x95\xbe\xf1\x0e\x02\x34\xfc\x30\x0e\x2a\xf4\x82\x28\x5d\x78\x93\x79\x68\x31\x9d\xa9\x4b\xeb\x6c\x40\xe0\x78\x57\x7c\x02\x4f\x3a\x5c\xda\x00\x84\xe2\xf8\x55\xa9\x39\x6a\xaa\x9e\xe9\xbf\xaf\x2c\xc7\x71\xfe\x68\xc4\x0b\x62\x9e\x8d\xcf\x11\x5e\xf0\x3e\x75\x7a\x2a\xc9\xee\xf0\x73\xf1\xbd\xf9\xc5\xa4\x41\x00\x31\x55\x8a\x6d\x38\x2b\x5f\x16\x02\x4b\x15\x1b\x1c\x01\xee\x78\x17\x41\x3a\x3c\x4d\xe9\xdd\x64\x78\x78\x5b\x81\x10\x1d\xf5\x52\x24\x30\x05\x87\x80\x20\x7e\x79\x0f\x61\x2d\x78\xe5\x70\x5c\xee\xd4\x6b\x0e\xc0\x75\xe7\xc1\xdc\x07\x3b\x17\xb2\xb4\x3d\x72\x53\x59\x27\xbf\xd2\x71\xe9\x2e\x3c\x93\x63\x8e\x40\xa9\x60\x1d\xc2\xc1\xab\x76\xd9\x1a\x41\x03\xdf\x65\x7d\x91\x1c\x82\x9e\xe8\xa5\xf7\x47\xf7\x64\x2f\x5a\x91\x5a\x5f\x40\xf6\x30\xb4\x30\x39\xc7\xd4\xbd\x2a\xd2\xb3\x21\x29\xd9\x4e\x5b\x2f\x03\xad\x4a\x3d\x45\x57\x7e\xb8\x1f\x36\x9c\x9e\x3e\x2a\x4f\x6a\x8e\x41\xac\xf8\x28\x3b\xe5\x84\x25\xea\x99\x3b\x8e\x98\xee\xa6\x33\x05\x56\x64\x86\x18\xda\xd9\x8f\xa2\x55\x62\x0d\x83\x6d\x3c\x7f\x29\xb9\x07\x89\x58\x49\x28\x61\x67\xc7\x18\x1e\x2c\xaf\x55\xc2\xc1\x84\xa9\xa9\x11\xf8\xe4\x1c\xb0\x42\xe2\xcd\x48\xb0\x54\x4e\xa7\x9f\xe2\xef\x38\x1e\xbc\x5b\x15\xe3\x9a\x9b\x5c\x6d\x99\x8f\xae\xaa\xa7\x77\x3c\xfe\xc0\x84\xc0\xbf\xae\xd1\xbc\xab\x96\x3a\x4e\xf3\xd9\x4d\xbb\x3d\xfe\x72\x4c\x04\x0c\xe4\xd1\xe2\xee\x7f\xc2\xda\x4b\x25\x12\x7c\xe3\xa5\xdf\x69\x3f\xcf\x5a\x6e\xd1"}, -{{0x43,0xbf,0xf3,0xcd,0xd5,0x30,0x7e,0xd7,0xd2,0x5c,0xf9,0x6f,0xdb,0xba,0x64,0xab,0x18,0x11,0xc8,0xbb,0x93,0x4e,0x21,0x87,0xea,0x7f,0xfc,0x01,0x8d,0x85,0xe0,0xf2,},{0x00,0xf1,0xb5,0xd3,0xca,0xc6,0xe5,0x6c,0xa5,0xf8,0x94,0xd4,0xcd,0xbf,0x9b,0xeb,0xd9,0x68,0xd2,0x4d,0x5e,0xff,0xa5,0x05,0x8b,0x0e,0x20,0xbb,0x08,0x98,0xf6,0xf1,},{0xa6,0xb5,0x6b,0x76,0x86,0xdf,0x1d,0xc5,0xf4,0xed,0x54,0x4a,0x4d,0x97,0xe6,0x70,0x36,0x19,0x5a,0x32,0xb2,0x2e,0xcd,0x5d,0x31,0xea,0x17,0x30,0xe6,0xed,0x8f,0x81,0x0d,0x25,0x8b,0x44,0xc0,0x8e,0xa4,0x5f,0x03,0x2b,0x93,0x74,0x41,0xb7,0x2c,0xd0,0xdc,0x37,0x55,0x6f,0xd7,0x87,0x4e,0x9f,0xe6,0x4f,0x15,0x76,0x5c,0x52,0x10,0x03,},"\x64\x6f\x8b\x34\x18\x2d\x5e\x60\x2b\x51\xca\x73\x29\x34\x7c\x0e\x19\x8c\xb7\x47\xe4\xda\x0a\x6b\x80\xf3\xf6\xf9\xf3\x36\xf6\x70\x8d\x85\xcb\x42\x9a\xb2\xd6\xbe\xd3\x5d\x50\x13\x12\x9c\xd1\x00\x14\x2c\xdd\xce\xe8\x63\x51\x79\x02\x1b\x3e\x24\x92\x2b\x81\xae\xf1\x3c\x13\x70\x28\x69\x39\xd6\x3d\x6b\x6a\x41\x95\xed\xa1\xd8\x12\xca\x51\x82\x04\x76\x8f\x87\x34\x8c\x68\x89\x55\x2c\x63\xd1\x37\x2c\xde\x6a\x5e\x9d\xaa\x7f\x84\x45\xec\x8d\x61\x30\xa3\xf5\xae\xf0\xed\xea\xce\x01\x0b\x6c\x7f\x0b\x9d\x24\x16\x2a\x8d\x04\x45\x4b\x81\xd4\x8e\xa9\x09\x7b\xd8\xdf\x09\x34\x59\x71\x9c\xcb\x54\xaa\x10\xf5\x1c\x24\x6a\xa9\x9c\x58\x0b\xea\xf9\xc9\xc5\xbc\x60\xfa\xf0\xae\x5c\xec\x7f\x51\x37\xf6\xc5\xc1\x44\xdf\x45\xd1\x2e\xe9\x95\xad\xcc\xf2\x5a\x9d\xb8\x1b\x85\x58\xbd\xfb\x65\x83\x01\x86\xe7\xb9\xd4\xee\xd9\xf6\xb4\xd7\x32\xb1\xb5\x82\x2d\x03\xeb\x01\x7c\x07\x24\xf4\x8f\x87\xba\xaa\xe1\x04\x5d\x6f\xdb\x12\x5c\x91\x34\x06\x4f\xaf\x18\xdb\xed\x58\xd8\xfb\xac\xea\xcd\x4f\x09\x7d\xf9\xb3\x42\xe5\xc4\xa5\xbc\x85\xb2\x95\x97\xd4\xb6\x40\xf1\x55\x1c\x5b\x62\x4a\xb2\x1b\x48\xe9\x4a\x90\x30\x04\x9b\xe1\xf0\x5a\xa8\x51\xd0\x82\x7e\xaf\x87\x00\xdf\xe1\x47\xfd\xcd\xee\xdb\xc9\x8c\x4f\x15\x77\x4f\x01\x20\xfb\x59\x70\xa2\xf8\xb2\x17\x94\x34\x0b\x62\x83\x79\xa8\x02\xb9\xf7\xc0\x68\xb0\xdf\x63\x19\x3e\x51\x0f\xc7\xb2\xaf\x97\xee\x38\xde\x47\x92\x97\x85\x53\x55\x28\xd3\x50\xd8\x86\x20\x61\x0c\xfd\xb5\x5d\x24\x9e\x38\xfb\x73\xc8\x28\x71\x13\x91\x9c\xe3\x32\x67\xd7\xdb\x92\x4e\x49\x19\xa4\x4e\x6e\x29\xa9\x0d\xbe\x3b\x7b\x0d\x39\x21\x16\x3f\xeb\x5a\xc1\x05\x62\x4e\xd8\x52\xbe\xce\x35\x38\xe9\x91\x93\x30\x0c\x89\x33\x45\x69\x93\x50\xa8\xf9\x9e\x8c\x6a\x41\x09\x5f\xc9\xfc\x08\xda\x07\xf7\x57\x11\xf7\xdf\x03\x44\x06\xde\x14\xed\xd8\xe2\x2a\x63\x3a\x86\xe4\xa5\xa5\xc9\x75\xac\x5d\x34\x89\x1c\xcc\xfc\x85\x43\x77\x1f\xfa\x08\x0e\x0b\x45\xd6\x5a\xb8\x30\xa3\x61\xac\x4c\x42\x62\x94\xd3\x68\x5e\xa8\xc2\x60\x39\xc7\x1c\x90\xfc\x3f\xb5\x12\xbe\x9f\xc9\x48\x07\xd7\x6d\xbd\xaf\x8f\xfa\xa4\xfb\xf9\x84\x9d\x68\xe8\xa5\x7d\x30\xc4\xa0\xb9\x73\x5c\x23\xf0\x8e\xf2\xe2\x84\x45\x84\x67\xe1\x5d\x66\x53\x62\xcb\x64\x6f\xde\x69\x37\xec\xba\x53\x09\x12\x64\x63\x83\x57\xa7\x22\x42\x5b\xc6\x2d\x1e\x30\xec\x5f\x0d\xd8\xfe\xa2\x6b\x2e\xa4\xa8\x49\x00\x35\xde\x43\xf2\x74\x84\x6f\xb0\xcf\x02\x09\xec\x74\x37\xf3\xc3\xd0\xa5\x60\x37\x3d\x03\x4e\x5f\xd7\x9e\x25\xb6\x42\x4d\x9b\x2c\x17\x61\x63\x2b\x35\xa1\x21\x32\x52\x18\x27\x34\x5c\x55\xe4\xe7\x14\x2d\xd6\xfe\x94\xd6\x20\xfe\x51\x5c\x15\x3e\x83\x95\xb5\xd1\x30\xc7\x44\x13\x9b\x6a\x92\xef\xd3\x7f\x22\xba\x13\xfe\x4c\x09\x53\x73\x55\x0e\x2e\x4f\xcb\xa0\x32\x5b\x3e\xa3\xb9\xfe\x25\xcc\x7d\xd9\x2c\xbf\x42\xe1\x5f\x45\x54\xb7\x7a\xc2\x7a\x4a\x34\x63\x82\xff\x61\x00\x45\x15\x08\xd6\x02\xcf\x64\x3f\x60\xb6\xca\x42\x86\x35\x6f\x21\xa3\x11\x0d\x4e\x2c\x8a\x89\x62\xa7\x80\xfc\xff\x43\x9b\x3a\xa8\x04\x99\xdf\x27\x0f\xc3\xe6\xca\xd8\x89\x33\x48\x87\x2f\x0f\x70\x2f\x93\x90\x00\x0c\x7f\x6e\x06\x27\xd2\xbb\xb7\xb7\xce\xf5\xc4\xda\x25\xda\xdf\xea\x80\x32\xe5\x02\x32\x97\xa7\x0a\x65\x8e\x9a\xe7\x3b\xdd\xc3\xb2\x27\xa1\xc1\x17\x41\x13\x3f\x01\x2f\x0f\x48\xfe\x26\x44\x6f\xa6\x7e\x64\x72\x0f\xc8\xdc\x97\xf3\x0d\x0d\xd0\x26\xf6\xdc\x21\x64\xea\xd8\x57\x82\x4a\x0a\x7a\xeb\x20\xf1\x15\xd5\x0d\x1b\x65\xdd\x5d\x82\xe0\x9a\xbe\x83\x4e\x8c\xa8\x89\x57\xe3\x99\x84\x82\x49\x55\xa1\xa1\x3e\x3b\x94\xa0\x01\x57\x18\x6d\xcd\xc2\x89\xe3\x4b\x67\x8c\x91\xcb\x2a\x1a"}, -{{0x06,0x3b,0x90,0x25,0xe3,0x21,0xe9,0x72,0xd6,0x53,0xa0,0x62,0xbe,0x34,0xf9,0x93,0x65,0xaf,0xfd,0xcc,0x98,0xec,0x9f,0xf4,0x3e,0xf4,0x22,0xbe,0x0f,0x80,0x44,0x60,},{0x10,0xd0,0x1a,0x63,0x01,0x2a,0xc0,0x99,0x56,0xba,0x9e,0xd6,0x1d,0xf3,0x5b,0xb7,0xaf,0xe3,0x65,0x8b,0xb3,0x00,0x48,0x52,0xe4,0x71,0x74,0xbd,0x07,0xdd,0x4d,0xe7,},{0x85,0xc8,0x1d,0x6b,0x0d,0x85,0x78,0xfa,0x58,0xe1,0x3a,0xb3,0x91,0x00,0x15,0x28,0xb4,0x6a,0x1d,0x63,0xa0,0x32,0x7c,0x7a,0x4a,0x04,0x08,0x7f,0xc6,0x68,0x75,0x8a,0xa6,0x5c,0x01,0xd5,0xa1,0x50,0xf9,0x35,0x67,0x4e,0xf3,0x07,0x50,0x7e,0x6f,0x4c,0x91,0xe1,0xfc,0x35,0x00,0xb2,0x6f,0x64,0x9b,0xee,0xa8,0x7d,0x27,0x56,0x37,0x04,},"\xa7\xee\xd2\x96\x52\x84\x4e\xe0\x04\x9b\xaf\xb2\xcf\x63\x40\x29\x71\x02\x0d\x7e\x65\xc1\x0b\x91\xac\x57\x26\xee\xa8\x6f\x40\xdb\xc5\x3c\x3f\x0a\xbe\xde\xba\xf6\xcc\x44\x9b\x4f\xea\x48\xc0\x15\xfe\x4d\x90\x7b\x3e\x55\x05\xcf\xf5\x0a\x12\x18\x19\xa2\xe4\xa8\xa2\x96\xd5\x75\x10\x15\xbb\xcd\x7e\xf6\xfb\x7c\x27\x27\xbb\x00\x0b\xe1\x34\x2a\x7d\x14\xbc\xa9\x79\x04\xed\xfe\x8b\x18\xdd\xb6\x39\x33\x41\x83\x27\xa5\xaf\x81\x7e\x95\xba\xd7\x4e\xb7\x90\x20\x36\x15\xd0\x82\xe7\x14\x93\xea\xd4\x7c\xcc\x09\x01\xa2\xca\x9f\x50\x13\x3c\x44\xef\x85\x08\xd5\x1f\xb7\x3c\x61\x6f\x01\x47\x53\x22\x45\x82\x2d\xd1\x02\xb3\x37\xa1\xb2\xaa\xe2\xef\xc7\x2d\xca\x7a\x94\x19\xd5\x98\xa6\x47\x52\x33\xdc\x1a\x4e\xe0\xec\x6d\x05\xda\x12\xa2\xb2\x87\xcb\x77\xff\xaf\xdd\xe2\xd0\xac\xc2\x81\x99\x93\x3e\x66\x21\xee\xc1\x6a\xb4\x24\x51\x70\xcf\x02\xda\x80\xd4\x92\x26\x31\xa2\x32\x72\x91\x51\x65\xad\x88\x72\x27\x50\x03\x5d\x2a\x09\x77\xbc\x79\x1d\x14\xfb\x3d\x8c\xb0\x2b\xc7\x7f\x7c\x71\xbe\x52\x42\x62\x9a\x4c\x9a\x58\x8d\xfd\xde\x95\x78\x49\x4d\x8b\xaa\x4e\x68\xf5\x19\x4b\x80\x02\xc8\xe3\x78\xa0\xe8\x33\xb7\xc1\xa9\x69\x81\xc4\xfb\x05\xe4\x57\xff\x48\x26\x0b\x72\x49\x3c\xbc\xb8\x2a\xe1\x16\x73\xd1\x4c\xee\x85\x28\x8f\x63\x70\xbd\x4b\xca\x92\x51\xa7\xe2\x14\xc3\xeb\x79\xe7\xbb\x6f\xce\xbb\x16\xc9\xe0\x56\xf2\x9b\x62\x72\x74\x3e\xfa\x6f\xe8\xbf\xd2\x55\x97\xce\x86\x89\x8a\xb3\x05\x9e\xb0\x23\x1c\x73\xb5\x30\x59\x03\xfd\x13\x19\xbd\xf4\x9e\x59\x9d\x8b\xbc\xd7\x4a\x8b\x97\x67\x30\x8b\x61\x56\x3c\xcb\xac\xd3\x8f\xc5\x0c\x83\xab\x44\xca\x75\x9d\xc9\xb6\x5b\x2a\x4b\x54\x7c\x50\x97\xf2\x20\xc1\xc8\x8b\x2b\x0a\x48\xf6\x5f\x91\xfe\x78\xb1\x50\x12\x78\xe1\xe3\x04\xde\x58\xb4\xc8\x2a\x5c\x39\x99\x81\x09\x8a\x17\x84\xeb\x90\x42\x50\x18\x59\xf2\xa9\x3f\x31\x7e\x41\x77\x2f\xd5\x2f\x97\x2e\x51\xb0\x7e\xd9\x4d\x31\x4e\x1d\x1a\xf4\xed\x82\x90\x9a\x0b\xef\x67\x1f\x54\xb5\x5d\xb7\xb7\x0d\xa1\xf7\x18\xc8\xe6\x48\xae\xdd\x6d\xa6\x4b\x05\x77\x05\x26\xf1\x2b\xc4\x3f\x68\xb9\x55\x48\xda\xc5\x08\x09\xa6\x87\xdb\x97\xd7\x3f\x06\xf4\x7e\xd0\x88\x31\xb6\x0a\x28\xe9\x82\x92\x06\x32\x05\x8f\x0e\x6c\x90\xc0\x18\x7f\xf4\x45\x64\xf8\x1e\xfd\x8f\xd9\x3e\x32\x7b\xc6\xd8\x0b\x49\x0e\x08\x8b\x9a\x10\x03\x6c\x80\xdc\xda\xd4\x9d\x2b\xe0\x74\xfb\xba\x31\xe0\x6f\x71\x80\xe5\xad\x1c\x88\x23\xd6\x09\x66\xa9\xce\x15\x50\x3c\xe6\x0d\xd4\x0e\x91\xee\xf2\x35\x9d\x83\xd7\x0d\x98\x40\x1d\xde\x7b\xe3\xc6\xb0\x7e\x57\xd4\xe4\x7d\x04\x21\x76\x33\xd8\xe2\x63\xca\x34\x8f\x81\xfb\xe9\xa4\xa6\x2f\x45\xd7\x7c\x84\x3b\x6b\x1a\xd2\x84\x66\xd9\xda\xfb\x1b\x91\x0b\x34\x8e\xd8\x7c\x68\x6c\xab\x29\x2d\x48\x0c\x19\x1d\x18\x7b\x40\x4a\x9b\x1d\x13\x2b\xa4\xe2\x93\xd3\xad\xa9\x91\x72\xac\xc1\x21\xfe\x66\xb8\x45\xb9\x8b\x16\x0c\x58\x23\xf6\x01\xc7\x75\x8f\xb2\x6c\xae\xe8\x57\x01\x59\x5b\x2d\x52\xca\xa2\xf5\x68\x8a\xa2\xbf\x2f\x6c\x4b\xb6\x37\xf8\xe0\x0f\x49\xab\x6c\x26\xbc\x6a\xd8\x9e\x13\x67\xfd\x28\xe4\x91\x7d\x25\x08\x93\xa7\xb3\x2d\x39\x66\x0b\xde\x8d\xb4\x9f\x08\x6f\xb7\x39\xe5\x60\x12\xc3\x6b\xea\x0b\x26\xcf\x6d\x93\x57\x94\x0b\x00\xd5\xa4\x52\x8f\x90\x59\xaa\xf0\x86\x69\xe5\xf4\x6c\x99\x5e\x60\xf8\x87\xb5\xc4\xab\x88\xac\x74\x42\xed\x01\xa1\x4c\x6a\x42\x00\x6b\xaf\x1f\x34\x3f\xef\xe3\xe4\xac\xa8\x43\xa3\x24\xe1\x76\xb2\xfe\x7e\xc7\x88\x3d\x1c\xbd\x06\x8b\xc2\xfc\x96\x2f\xfa\x60\x24\x4f\x65\x4c\x77\xac\x56\x50\x81\x7d\xc0\x84\x46\x55\x45\xa9\x23\x0a\x74\x82\x6b\x0c\x50\xeb\x85\x25\x2a\x88\x6f\xf2\xb1\xaf\xea\xf8"}, -{{0x88,0x3c,0xc1,0x38,0x17,0x57,0xb0,0xfe,0x04,0x55,0xb7,0x7b,0xc9,0xcd,0x0d,0xd4,0x64,0xd2,0xb4,0xbf,0x0c,0x7a,0x3c,0x0c,0x2d,0xc7,0x75,0xfb,0x78,0xaa,0x37,0x32,},{0x83,0xa8,0xb6,0x69,0xcc,0xd0,0x12,0x45,0xce,0x3b,0x81,0x8d,0xcb,0x1b,0x58,0x8f,0x86,0x53,0x58,0x50,0xe6,0xc7,0x10,0xc7,0x92,0x17,0xfe,0x43,0x98,0x24,0xf3,0xfa,},{0xc7,0xcf,0xd5,0xc9,0xfe,0x93,0x0d,0x15,0xa1,0x1e,0xbb,0x34,0xe3,0x43,0x1f,0x48,0x9d,0xa0,0x10,0xeb,0x19,0x3e,0xdb,0xfa,0x6f,0x23,0xd5,0xd1,0x4d,0xd8,0xfe,0xab,0xd7,0x88,0x0d,0x2d,0x5a,0x56,0x00,0xd3,0x85,0x46,0xce,0x3b,0xc6,0x4a,0x86,0x29,0x1a,0x1c,0xe3,0x1f,0x27,0x2f,0xf0,0x20,0xdf,0x8c,0xb6,0xa0,0xfd,0x4d,0x3a,0x0d,},"\xff\xec\x29\x3d\x12\xea\x63\x6c\xa4\xc4\xa0\xa5\xe2\xdb\x15\x34\x26\x39\xc4\x76\x67\x4d\x2e\xbd\xab\x4a\xef\xd4\x04\x6b\x5d\xdb\x56\xae\xb2\x10\xc1\x19\xaf\xdf\xb8\xa8\x91\x28\xa3\x4f\x6d\x77\xf2\x61\xed\xea\x07\x72\xa2\xf8\xdb\x14\x0a\x26\x40\xfd\x8e\xca\xdb\x0b\x47\x92\x16\x9b\x6b\x28\x10\xae\xe2\xc5\xcd\x83\x52\x88\xbf\xf4\x93\xbc\xeb\xee\xea\x28\xa7\xa2\x48\xc3\x61\x16\x54\x0f\xa7\x17\x36\xd6\x6b\x0a\x47\x5b\x5f\xa9\x2c\x0d\x46\x00\x2f\xca\x7a\x1e\x69\xd1\xb5\x9e\x81\xa3\xa6\xd4\xf3\x39\x76\x9d\xae\xb2\x0b\x5f\x9d\x75\xc4\xc2\x8f\x69\x21\x32\xd2\x8d\x3c\x56\x4c\x09\xfe\x3d\xcc\xa0\x35\x9c\x3c\x63\xec\x37\x7a\x33\xf9\xee\x87\x4d\x8a\x78\x9d\x77\xc9\x6a\xc0\x5f\xdf\x3a\xb3\x8b\x2c\x82\x74\xa9\x02\xef\x8b\xb7\xf4\x67\xfc\x7e\x07\x3c\x77\xb1\xdb\x5f\xc8\xef\x96\x6c\x12\x0c\x4d\xae\x3f\xb7\xf5\xb7\x4a\xbb\x99\x01\x66\xc8\x12\xa5\x25\xd1\x23\xf7\x6e\xd5\x12\x12\x50\x80\xa1\x53\x4f\x3d\x8b\xdc\xcc\x54\x1f\xc9\x75\x90\x28\x75\x46\x09\x6f\xc8\x80\xbf\xcf\xdd\x00\xe6\x5c\x0e\xbf\x4a\x09\xfd\x64\x76\xce\x1b\x7c\x8f\xaa\xa5\xa1\xcc\x27\x86\x71\x9a\x30\xd8\x25\x58\x11\x18\x47\x52\xa8\x8b\x08\xac\x9f\x0f\xf1\xd6\x26\x2f\x25\x86\x94\x0a\xfe\x1f\xe4\x5e\x0b\x56\x34\x48\xa5\x5f\x30\x30\xe4\xc3\x9c\x1f\x3f\x86\xa7\x33\x67\x03\x80\xea\xb0\x88\xe3\x93\xde\x09\xd1\xf5\x08\xd2\xfb\xca\xfc\x64\x9a\xea\xe6\xb8\xc3\x0e\x32\x9e\xc3\xfd\x28\x29\xbe\x6d\xb0\xab\x8e\x63\x7e\xa1\x09\x5b\xdc\x3d\xf3\xac\xc2\x3d\x3c\xf7\x05\xa9\x54\x2c\x19\xe5\x90\x92\xec\x41\x3a\x4e\x2b\xd5\xde\xd2\x8c\xd3\x4d\xdb\x3d\x32\x94\x9a\xa4\x87\xf1\xc3\x37\xd6\x97\x9c\xf5\x12\x62\x2d\xbf\xb7\xda\x1c\xbb\x1c\x7e\x5a\xbe\xea\x70\x09\xe2\x94\x3f\xfb\xa2\x25\x2e\x1d\x86\xec\xa9\xd6\xd5\xc2\x46\xcd\x2e\x13\x4a\x3e\x5d\xad\x37\xef\xef\x71\xce\x39\x7a\xda\xfb\xd9\xe7\x2b\x3f\x9a\x86\xff\x0f\x5d\x81\x2c\x46\x22\x5b\xeb\xd0\x70\x3b\xc5\xcc\xe9\xc6\x45\x82\x00\x8f\x7e\x55\x8c\x40\xa3\xb3\x52\x20\x96\xd1\xaa\x2b\x61\xbc\x90\xcd\x88\xc6\x28\x5d\x94\x20\x87\xd8\xa4\x66\x5a\x0e\x64\xd3\x57\x2f\x74\x68\x9b\x4f\x24\xef\x40\x0d\x74\x1b\x57\x14\x06\x13\x47\x14\x44\xde\xcc\x65\x4a\xf0\xff\xb2\xed\xfd\xf9\xfd\xd0\x75\x09\x81\x90\xb3\x4c\xde\x28\xdd\x16\x68\x72\xc6\x08\x65\x67\xa6\x87\x61\xce\xf2\x5d\xa4\x0b\xd4\xc3\xd3\x4f\xdd\xd7\x2e\xe5\x65\xb0\xb9\x37\x67\x8e\xe8\x43\x49\xd1\x16\x0f\x5f\x07\x05\xf8\x95\xd0\xf1\x41\xce\x8f\x51\xa1\xe4\xfd\x2d\xc4\x70\x4b\x52\x7a\x40\x25\xa9\x39\xcb\x2b\xb7\x88\x57\xeb\x18\xd7\x88\x72\xed\xc9\xee\x70\xe6\x0b\x2a\x42\x70\x0a\x19\x8f\x4f\xff\x6c\x31\x92\x51\x68\xbe\x07\x7d\xc2\x3c\x32\x2a\xbb\xca\x97\x36\x1f\xec\xaa\x3f\xcb\x19\x6e\x65\x6c\x12\x8f\x39\x82\xfe\x11\xe5\x51\xa4\xa0\x88\x5d\xa6\x0d\x39\x7d\x0e\x40\xd0\xd8\x97\x26\x2f\x1b\x4b\x67\x2f\x78\xa2\xd2\xad\xfc\xdd\x6e\x15\x25\xc2\x6e\x71\x95\xfb\x9a\xc6\x06\xbb\x1b\xa4\xa9\x89\x08\x03\xb4\xbd\x84\x34\x6a\xe8\xd8\xc7\x19\x6c\x90\xae\xcc\xb2\x96\xa4\xc3\xeb\x4e\xfa\xcb\xfc\xb6\x2e\x38\x3b\x8a\x49\x4a\xc7\x23\x56\x2d\x0d\x8c\x37\x91\x87\xa9\x2e\x3b\xda\x6b\x15\x69\x47\x6a\xed\x21\xae\xd7\xa0\x56\xb4\xa5\x82\x67\x44\x01\x7c\xc0\x06\x0b\x4d\x55\xfa\x87\x72\xb5\xb1\xc1\x5f\x57\x48\xad\x72\x98\x00\x5a\xec\xbc\xbd\x90\xa3\xe5\xc6\x15\x9a\x86\x74\xab\xbb\xa3\x79\x14\x41\x50\x02\xb5\xa6\xef\x5d\xf3\xc6\x49\x42\x6e\xa1\x27\x5a\x01\xd8\x0a\xdf\x49\x0a\xc5\x46\x06\x2d\x93\x99\x9a\x6d\xcc\xac\xb9\x6a\x09\x04\xad\x33\xd9\x05\x76\xdc\x6a\x21\xb6\x72\xe8\xff\xb0\x66\x13\xfb\x3f\x14\xe6\xcb\xdd\xe8\x8c\x24\x37\xc9"}, -{{0x5e,0x40,0xa7,0xaa,0xbb,0xb0,0x83,0x0a,0x9a,0xb0,0xfd,0x79,0x69,0x0e,0xe0,0x43,0x39,0x01,0xc6,0xcb,0x06,0x76,0xab,0xe4,0xbb,0xa0,0x6f,0x5b,0xbe,0x58,0xfa,0xc2,},{0x4d,0x4f,0x28,0xfe,0x09,0xc4,0xaa,0xbf,0xca,0x01,0xef,0x6e,0xe7,0xfd,0x63,0x72,0xfb,0x62,0xdb,0x61,0xaa,0xee,0x82,0x7c,0x43,0xfd,0x1a,0x6d,0x1c,0x25,0x90,0x32,},{0x59,0x76,0x72,0xab,0x8d,0x3a,0x60,0xde,0x54,0x56,0xfc,0xc9,0xc3,0x82,0x53,0xf5,0xf3,0x7b,0x80,0xe7,0x4a,0x00,0x7c,0x9f,0x6d,0xb9,0x09,0xd2,0x7d,0x0e,0xad,0x16,0x27,0x89,0x24,0x49,0x94,0xf3,0x5b,0x80,0xd6,0x1b,0xe1,0x99,0xc4,0x17,0xc7,0xea,0x90,0x1b,0x98,0xcc,0x63,0xfe,0x3c,0x50,0xfc,0x3c,0x63,0x38,0x49,0x0f,0xa2,0x06,},"\xfd\x4e\xc8\xb3\x4f\xc6\xb7\x43\x81\x3f\x59\xe2\xfd\x1f\xef\xa8\x70\xf5\xa9\x70\xe2\xeb\x75\x16\xef\x7c\x30\x6f\x4b\x82\x3f\xfe\xe9\x2d\x60\x1f\x76\x5d\x79\xca\x14\x6a\xba\x8b\xc6\xe7\x98\x44\x55\x99\x35\xcd\xdc\x24\x26\x49\xc0\x59\xec\xf2\xdb\x84\xfd\xc2\x19\x36\x66\x88\xa8\x8f\xc2\x5b\x85\x1c\x36\x61\xe5\x19\x88\xc2\xbf\x73\xbb\x8e\x3d\xc1\x6d\x22\x41\x5a\xb1\xa7\xb3\x55\x79\xda\xac\x73\x25\xe3\x19\x15\x7d\x7d\xa5\xfe\xe8\x7c\x93\xa4\xdf\xcb\xaf\xc9\x2f\xba\x7e\x17\xcc\x68\xe3\x90\x37\x33\xc6\xc8\x01\x57\x2d\x90\x73\x20\xb2\xfe\xb5\x17\x10\xe8\x56\xa1\xf7\x6f\x85\xa7\xee\x1a\x11\xe6\x2d\x2e\x45\xa3\x52\x93\x8d\xd8\xcf\xc2\xbc\xcb\x90\x2d\xea\x44\x4f\xaa\xae\x6d\x84\xc5\xf3\x91\xe1\x0a\xef\x76\x92\x8a\x45\x15\x3d\xb6\xcd\x25\xa2\xbf\x35\x3d\x80\xd9\x7b\xf4\xb3\x80\x86\x05\xe8\x98\x00\xd2\x98\x40\xea\x60\x97\x8d\x9e\xc9\xb2\xc3\x02\x74\x98\x88\xf9\xde\xbc\x84\xdd\x1e\x2a\x79\xaa\x0b\x6b\xa0\x2a\x03\x91\x93\x08\x1b\xdb\xff\x05\x99\xa1\x4d\x91\x8c\x0c\x8d\xea\xc4\xf6\x0b\x6e\x99\x47\x4a\xb5\x30\x11\x74\x10\x34\xfe\x2a\x20\xcf\xf4\xe0\xf0\x23\x42\x4c\x8e\x57\x97\x76\x8a\xd5\x3d\xf6\xd0\x1a\x24\x01\x1f\xa9\x0f\x0b\xb1\xd5\x06\x9c\xdb\x36\xb4\x50\xf4\x33\x11\x0c\x2c\x56\xf3\x4a\x1d\xe4\x26\x09\x14\xcd\x46\x96\xb1\x4a\x09\xc0\x26\x8b\x2a\xe2\xe9\x8e\x6b\x4e\x99\x2b\x91\x25\xf8\x78\xf1\xac\x09\x82\x31\x70\x62\x83\x88\xf0\xf6\xe2\x56\x25\x9c\xa7\x86\xbb\xe1\x44\x88\x4c\xb2\x98\xcc\x04\x3d\x02\xf5\xc3\xdc\x68\x4f\x78\x7f\xaf\x16\xc1\x0f\xdd\x84\x37\xa8\xc3\x09\x74\x63\xbd\xb9\x9b\x78\x03\x0f\x94\x74\xfc\x5c\x99\x51\xdc\x75\x26\x49\x05\x86\xfe\x1c\x2d\xb0\x54\x11\x34\x14\x60\x23\x9d\x5e\x8b\xc5\x30\x65\x90\x2b\x95\xfb\xa2\x82\xc2\x76\x65\xe8\x69\xa1\x9d\xae\x84\x60\x6d\x17\x26\x67\x51\x55\xd3\x80\x39\xb9\xe5\x5d\xb4\xd5\xce\xec\x95\xcd\x6d\x87\xf8\x5e\x99\xdd\xe5\x4a\x04\x76\x1e\x6e\xad\xa6\x61\x9d\xa8\x95\xb6\x54\xfe\x38\x45\xe8\xa6\x0f\x3a\x3b\x32\x48\x3d\x6d\x27\x97\x8a\xf5\x45\x02\xb2\x20\xe4\x78\xdb\x78\xcf\xf7\x7a\x9c\x97\xfb\x79\xfb\x5a\xcf\x56\x28\x9f\x38\x1a\xcb\x10\xde\x64\xc3\xf2\x38\x42\xb1\x2b\xf5\xf1\xb2\x83\xbd\x25\xd4\x8d\x09\x12\x8f\xb5\x5d\xda\xe2\x55\xbe\xb7\xc6\x6a\x74\xcf\x6f\x06\x95\xa4\xf8\x28\xcb\x29\xe4\xaf\xdb\xb3\xb4\x2a\x23\x5d\x4f\xdb\x66\xb9\x63\xac\x8f\x68\xe8\x2b\x00\xa1\xc4\x50\x08\x63\x29\x62\x47\x17\x8c\xfd\xef\x80\x3b\xb7\xb1\x14\xf0\xc0\x32\x76\xf6\x71\x66\x9a\x08\x7d\x92\x28\xa3\x7a\xe7\xb9\x9b\x06\x15\x49\xc1\xcf\x8e\xc1\x72\x46\xea\x1e\xe0\x3d\xbc\x88\xbf\x42\x64\x16\xd5\x86\x57\x2f\xf1\x0a\x31\x45\x60\x6f\x27\x84\xe4\x35\x7b\xe4\xed\xee\xc6\xc3\xa7\xbf\x11\xbb\x5b\x0e\x90\xcf\x50\xed\xaf\x89\x1e\x51\xd2\x63\x57\xbf\xc8\x53\xce\x23\xb2\x99\x15\x5c\x82\xc1\x03\x1d\xfa\x64\x07\x4d\x72\xa0\x9d\x29\x72\x0e\xad\x6e\xbb\xbf\x75\xd5\x73\x8e\x32\xcd\xa6\xb6\x46\x6a\x8d\xef\x6b\x50\xa1\xed\x9b\x86\x5a\x9a\x88\xa0\x80\x18\xac\xb5\x01\xa4\xde\x9d\xb5\x4d\x05\x22\xce\x9c\xec\x7a\x06\xbd\x9a\x5f\x86\xb0\xb4\x6c\x07\xbf\x3e\x7f\x5a\x42\x6f\xf6\xb4\xbb\xe1\xe0\x03\x13\xa5\xac\x27\x19\xa9\x59\xed\x44\xee\x0a\x44\xbd\x97\xda\x6d\xb2\xcb\x97\x1b\xd6\x83\x34\x90\x89\x49\xed\x85\x0f\xbf\x73\xd0\xe0\x20\x49\xda\x18\x1c\xce\x9c\x2d\x9c\xa1\xb6\x24\xc8\xd8\x7c\xf9\x04\xeb\x82\x1d\xc7\x95\x92\x95\xda\x57\x77\x92\x06\x60\xb4\x3c\xcc\x25\xcd\x38\x9f\x15\x7f\x67\xfa\x03\x90\xfe\xac\x97\xa7\x52\xc1\xac\x20\x4c\x21\xdf\x56\xbb\x0f\x4f\xc0\x16\x41\xb4\x80\xaf\x2b\x89\xb5\xd1\x6d\x4a\x0b\xcb\x0a\x50\xb8\x2b\x0e\x04\x84"}, -{{0x3a,0x34,0x13,0x6a,0x97,0x34,0x80,0xd9,0x70,0x06,0xdc,0x27,0x93,0x58,0xe6,0x60,0x62,0x93,0xd8,0xcb,0xc1,0xa4,0x4e,0xe5,0x52,0x33,0xaf,0x2b,0x52,0x64,0xb9,0x0c,},{0xe5,0xef,0xfd,0x92,0x1b,0xe8,0xee,0xc5,0x30,0x75,0x2f,0xcc,0xc5,0x76,0xef,0x0d,0x9b,0xcd,0xe4,0xb3,0x2c,0xc6,0x49,0xd3,0xf7,0x95,0x47,0x17,0x56,0x28,0x60,0xcc,},{0x42,0x5f,0x27,0x22,0x12,0x83,0x57,0x55,0xad,0xcc,0x05,0x22,0xc6,0xf6,0xe0,0x5f,0x68,0x00,0x8a,0x3b,0xe9,0xba,0x59,0x74,0xe4,0x20,0xc4,0xc5,0xcb,0x56,0xe6,0xc5,0x5d,0xec,0x0d,0xe3,0x47,0xb1,0x6c,0xae,0xf8,0xbd,0x33,0xb7,0x1b,0x44,0xc8,0x35,0x7d,0x05,0xb6,0x32,0x1d,0x7b,0xf4,0x93,0xd2,0x58,0x61,0xdb,0x48,0x7b,0xd6,0x03,},"\x98\x1c\x8e\x10\x90\xe3\x96\x95\x1b\x07\x2e\xf8\x49\x70\x62\x02\x08\x97\xbf\x7d\xd7\xad\x50\x5b\x4d\x6d\xc1\x1b\x3e\x1d\xbc\xb0\xda\x24\x99\x84\xa1\x40\xe1\x64\xfc\x2e\x02\xb3\x1d\xa3\x98\x46\x55\x4a\xa8\x90\x5b\xc8\xb3\xdf\x8a\x76\xbf\x60\xeb\x5f\xfc\xf2\x2c\x97\xb6\x71\x22\x7d\x24\x90\x71\xda\x8f\xf6\xbb\xa7\x5b\x2f\x76\x68\xce\xc1\x9a\x89\xe6\x47\x5a\x12\x46\x3d\xab\xf3\x68\xb3\xca\x24\x45\xbb\x30\x35\xcc\x00\xfa\xe8\x5b\x70\x72\xfb\xcf\x59\x54\x01\x75\x5b\x80\x51\xe6\x09\x70\x65\xae\x42\x9f\x18\xee\xb1\x3f\xfa\x6d\xde\x59\xdf\x6f\x3c\x20\x6b\xfd\x9c\xe1\xf8\xa8\x00\xc8\x59\x0a\x40\x21\xd1\x60\xf6\x6d\x67\x40\xa3\x69\xae\x83\x56\x17\x53\x8b\x58\x90\x23\x1f\x13\xc5\x66\x7b\xaf\x51\x0a\x60\x6b\xda\xa8\x4b\x8d\x10\xee\x60\x15\xe1\x2a\x4c\x1e\xc0\xbd\x04\x21\xa2\x94\xc5\x1c\xf6\x3b\x5d\x1f\x05\x8e\x11\x53\xdc\x42\x5d\x10\xce\xe8\xb1\xb0\x84\xd6\xc2\x93\x47\xe9\x6f\x0f\x31\xb8\x39\x60\x7d\x07\x8b\x79\xa9\x0c\xa3\xd1\xf0\x63\x80\x7a\x46\x3b\x7c\x32\xf4\x5a\x53\x44\x98\xd7\x1d\x47\xed\xc3\xb1\x7a\x4d\xff\x27\xfe\xdc\xff\xab\x30\x1f\x34\xf1\xa6\x4c\x02\x78\xa5\x35\x89\x34\x9a\x23\x3a\xf3\x0b\x1e\xc1\xae\x41\x0f\x7b\x16\x30\xc7\x14\x5c\xa4\x2c\x96\x63\xf5\x12\xe8\xa5\x78\x26\x7d\xc9\x5e\x83\x28\x9c\x17\x03\x2e\x09\x78\x2e\x2f\xe8\xe1\x6e\xfb\x87\xf0\x3c\xa0\x3b\x11\x95\x61\x4f\x89\x96\x1c\xa3\x93\x9d\x3b\xdf\x73\x72\x21\xa2\x2d\x7a\x18\xec\x30\xfc\x12\x6d\x0c\xa6\x63\xe8\x8d\x60\x60\xd0\x4c\x6a\x44\xe5\x61\x6e\x55\x6e\x07\xd6\xd4\xa8\x47\xf1\x71\x1c\xf4\x37\x17\x81\x0c\x70\xaa\x4b\xe7\x30\x27\x8b\x3b\xd6\x55\x5c\x95\x4d\xc6\xed\xb0\x9d\xb0\x8f\x0e\x21\x18\x03\x59\x62\x80\xf3\xc7\x86\x8d\x23\x42\xcc\x23\x08\xea\xae\x4d\xa1\x91\x35\x14\x66\x4b\x1d\xb9\x62\xe9\x9c\x8a\x8c\xff\xe5\x79\x31\xf5\xdf\xcd\xdb\xc1\xcb\xb3\x6c\xe1\xc8\x42\xe2\xdd\xde\xad\xfd\x7e\x7d\x0a\x50\x48\xcd\xcb\x96\x1b\x14\xf3\x5f\x43\x5e\x73\xa6\x83\xc8\xce\x25\xc8\x16\x81\x25\x66\xfd\xf8\x17\xe0\xd3\x36\xae\x0b\xd2\x47\x32\x85\x12\xb2\xa8\x56\x76\x32\xbf\x20\x55\x3d\x9b\xd6\xfe\x15\x7f\x22\x0f\xfb\x0b\x46\xeb\xae\x89\xa7\x04\x59\x72\x8a\x57\xee\xd1\x79\x62\x56\xf1\xbd\x50\xb6\xd5\x47\xea\x3e\x25\xfa\x59\x13\xd3\x89\xa2\x25\x83\xe9\x15\xeb\x49\xde\x35\xa9\x7b\x5a\xcc\x52\x1d\xb0\xd0\x05\xc2\x95\x75\xe1\x66\x11\xa7\x55\xf2\x1a\x3a\x5a\x82\xa2\x0a\xa9\x00\xa7\x07\xce\x36\x82\x54\x92\xc3\xca\x15\x39\x5f\x17\x00\xb4\xaf\xab\x94\xda\xa7\xa0\x2f\x14\x53\xb1\xf9\xa6\xbd\x36\xef\xb2\x04\xd9\x28\xee\x1f\x4d\xcc\x86\x0f\x3a\x85\x9b\xad\xc0\x06\xfb\x30\x5f\xa1\x23\xd4\xc7\x9b\x23\xa2\x0e\x32\x29\x5d\x04\x0a\x7f\x8f\x6c\xac\xa2\x5d\x83\xf7\x1c\x62\xe3\xaf\x78\x36\xef\x76\xb9\x3a\x83\xd3\xc3\xb4\x93\xaf\x14\x17\x53\xda\x19\xe4\xcd\xcb\xa5\x66\x17\x27\x10\x34\xb4\xf4\xf3\x94\xc7\xc6\xb7\xd7\x96\x66\xf3\xaf\xb6\x92\x24\x4f\x06\x1c\x69\xa8\x88\x1d\x1b\x52\xb8\x84\x9f\xb5\x34\x99\x0a\xc2\x39\x19\x09\x47\x1e\xbb\xb7\x28\xe2\x9c\xd2\x0f\x42\x23\x54\xc4\x30\x97\x17\xeb\xff\x3e\xfd\x18\x33\x37\x08\x06\xd5\xbf\xb5\x3c\xa2\xda\x31\x6d\xac\xb5\x0a\xb7\xfb\x73\x96\x73\x23\x5a\x1d\xc5\x3a\xa8\x89\x30\x72\xd5\xb9\x1c\x9f\x6d\xb8\x3f\xc4\xea\x41\xd1\xee\xf4\x9a\xc2\x8a\xfc\x1c\xed\x8f\x36\x18\x90\xab\x9f\x77\x9d\x19\x30\x82\x83\x1c\xb8\xc4\x2f\xb2\x79\x2b\xee\x3b\x26\x29\x6b\x62\x95\xeb\x78\xa8\xd8\x53\x11\x76\x61\x62\x4e\x11\xf7\xf5\x7a\xfd\x60\x85\xa7\xb9\x12\x36\x79\xfd\xac\xa1\xcf\x2a\x78\xd3\x80\xbc\x4c\x36\x0a\xa7\xc3\xcb\xfd\xe0\xc0\x09\x1f\xe5\x3e\x22\x19\xc0\x70\xf2\xf0\x2f\x14\x83"}, -{{0xcf,0x33,0xe7,0x97,0x4d,0x8f,0x0b,0xf8,0x99,0xac,0x5b,0x83,0x4c,0x7c,0xf9,0x64,0x79,0xce,0x1c,0xfd,0x45,0x3a,0xf0,0x7f,0x97,0x05,0x27,0xf3,0x6a,0xa8,0x5c,0x1f,},{0x57,0x8f,0x60,0x33,0x8b,0x1f,0x04,0x1a,0x97,0xd3,0x19,0xfe,0xcf,0xa3,0x0c,0xfa,0xed,0x36,0x93,0x03,0xcc,0x00,0xb3,0xec,0x8c,0x5c,0x99,0x04,0x11,0x58,0xe2,0x0c,},{0x97,0xa5,0xb6,0xd2,0x68,0xa5,0xb4,0x17,0x5f,0xb0,0x6f,0x1f,0x37,0xd0,0xa6,0x33,0x51,0x92,0x96,0xed,0xc3,0x00,0x11,0xc9,0x54,0xd8,0xf0,0xb9,0xbb,0xe2,0x64,0x18,0x00,0x39,0x6c,0x4b,0x35,0xd4,0xb0,0xd7,0xd2,0xa1,0xd1,0x7c,0xbb,0xeb,0xdc,0x55,0xa8,0x09,0x46,0x2d,0x6c,0xc1,0x9a,0x6f,0xad,0xbe,0x1b,0xd1,0xba,0xe8,0x8a,0x01,},"\xe8\x13\x14\x4b\xd1\x16\xf6\xac\x36\x38\x92\x17\xb5\x17\x1a\x90\x2f\x06\xb7\xdd\x7b\x14\x4d\xf4\xf9\x09\x15\x53\xc7\xc7\x83\x57\x53\xa2\x96\xcb\xb0\xd7\xfa\xb9\x9c\xef\x77\xb6\x1f\x34\xa0\x4c\x8a\xf0\x4e\x7d\x5d\x1f\x96\x13\x02\xde\x89\xe2\x00\x5f\x29\x9f\x5a\x4a\xa1\x79\x24\x61\x7d\x00\x66\x93\x93\x77\x45\x53\x9c\x30\x48\xee\x36\xb8\xc2\x3a\xfe\xc0\xaf\x9f\xea\xa0\x06\x6c\x8a\xf8\xe0\xa7\xf0\x90\x93\x49\x82\x10\xf6\xd8\xdc\xc0\xaa\xad\xa5\x66\x87\x86\x91\x0f\xf7\xc5\xb3\x48\xd4\xcc\xd6\xee\xef\xfa\x3a\xcd\x18\x16\xd9\x01\x1a\x4c\x40\x25\xf6\xc2\xfd\x2c\x02\x0a\x10\x59\x36\x27\x52\x0d\x4d\xd9\x9e\x07\xc6\x2d\x2d\xbe\xbe\x84\x13\x9e\x1c\x7d\x86\x7c\x09\x35\x74\xfa\x60\x1e\x4e\xe3\x07\xac\x92\x6e\x5d\x36\xb6\x2d\x7e\xd8\x4a\x26\x15\x88\xb7\xe2\x88\x3c\x79\x26\x61\x2b\x4c\xc6\x7e\x2b\xb7\x25\x44\xa1\x0d\x6b\x49\x29\xc8\x8e\xf6\xc4\x7c\x26\x25\xd2\xf6\x81\x6b\xd7\x3c\x3b\xae\x89\xd2\xe0\xc8\x61\x71\xac\x4b\xd0\x80\xae\x55\x5d\x62\x74\x0d\x1d\x2a\x76\x1c\xed\x86\xdf\xc3\x28\xec\xc2\x7e\xe3\xdb\x6d\x40\x41\x08\xef\x4e\x0b\x64\x90\x62\x53\xb4\xc0\xa7\x71\xad\xef\xed\xc8\xa2\xc5\xb5\x3c\x42\x5a\x70\xcd\x6f\x63\x95\x6f\x7a\x0a\x61\x9f\xdf\xbf\xd0\x0a\xa0\x78\x41\x8e\xb4\x65\x2f\x8b\xc6\xf3\xc2\x53\xbe\xec\x98\x38\xb7\x7f\x9c\xbe\x2e\xf2\xb8\x05\x5c\x57\x73\x53\x9e\x35\x6b\xd8\x19\x26\x06\xec\x10\x1e\x3f\x60\x58\xb1\xdd\x08\xa6\x8f\xdb\xc5\x49\xdf\xe6\xb7\x72\x5d\xc2\x54\x9e\x8e\x3f\x90\xdc\x5b\xe3\xcc\xfb\x0a\x38\xba\xf9\x37\x7c\xb3\xf6\x50\x1d\x2e\x15\xcc\xb3\x55\x6a\x89\x5c\xcb\x23\xf0\xb6\xdf\x9f\xe5\x93\x11\xcf\xf5\x53\x74\xc3\xfb\x3a\x32\x98\x1c\xa2\x6a\xb4\x26\xf3\x66\x3d\x04\xe3\x16\x7e\x53\xa5\x37\xb7\x58\x9a\x9f\xb7\x36\x79\x09\x0a\x20\x55\x32\xc1\x32\x90\x66\x34\x33\x4a\x7e\x87\x49\x79\x3f\x8c\x59\x3f\x3f\xd6\x27\x8c\xe0\x05\x03\x83\x48\x7f\x3b\x24\x50\x67\xaf\x94\x88\x1a\xa1\xae\x96\x8d\x0c\xae\xba\x5f\xa5\xc7\xbe\x5f\x4e\x4b\x72\x57\x51\x86\x95\xd8\x9b\xcc\xde\xc5\x07\xb9\x67\xb4\xfd\x64\xb6\x89\x3b\x3e\xe7\x80\x3c\x1d\x36\xea\x8a\x02\xfc\x42\x6f\x9a\xfc\x8e\x9f\x24\x32\x15\x27\xec\x98\x44\xbc\x3c\x54\xa0\xf7\x66\x7e\x03\x43\x00\xbb\xb4\xfb\x02\x0f\x6d\x5b\xb9\x54\xe7\xb5\xa3\xa7\x06\xa4\x93\x9d\xb3\x3c\x15\x48\x92\x64\x34\x76\xa2\x91\xd4\x7d\xc1\xe6\xf7\x2c\xe9\x1d\x13\x6f\x11\xdb\x26\xb9\xc9\xba\x73\x6e\x40\xdf\x0a\x15\xc1\xa8\x91\x49\x99\x6b\x25\x1d\xd9\x88\xb3\x90\x04\xe6\xef\x41\xbd\xc0\x61\xdb\x58\x0b\x7b\x74\xde\x2a\x65\x18\x10\xbd\x89\x17\x53\xb9\x73\x86\xd7\xf8\xcb\xdb\xb6\xec\x38\x6f\xa2\xc3\x42\xf5\xef\x20\xe6\xe3\xa8\xbb\x4d\x51\x49\xa7\xd4\xde\x12\x24\xdf\xf1\xd1\x72\xc8\x75\x70\xf7\x76\xd5\xef\x45\x95\x9b\xe0\x93\x8a\xd7\x9f\x5d\x33\x95\xcb\x27\x21\x62\x71\x22\x88\x7b\xd7\xa8\x98\x3b\x64\x77\x97\xbd\x41\xd8\x82\x64\x1c\x81\x43\x1c\xe8\xd9\xb3\x06\x7a\xde\xc4\xcd\xe9\x26\xc5\x13\x13\xf0\xcf\x84\xc5\x29\x25\x62\xdd\x49\x08\x64\x2d\xd2\x45\x28\x84\x84\xc5\x56\x8a\x78\x7d\x0c\xed\x36\xa3\x52\xf0\x32\xda\x4f\x7e\x4d\xe0\x6b\x11\x47\x3f\x65\x0e\xec\x65\xdd\xa9\x96\x39\xaf\x2d\x42\xd8\x4e\xe2\x30\xf4\xf8\x36\x23\xd9\xc9\xaa\xa3\xb1\x6b\xda\x10\xdd\xaa\xd2\x5a\xf5\xc1\xc1\x0f\x81\xc8\xc5\x1c\x81\x1a\x3a\xa3\xe3\xdb\x58\xa7\x02\x5e\x43\x80\xe2\x85\xda\x47\x4a\x61\xba\x59\x17\x3f\xf0\x42\xa4\x6a\x79\xab\x18\x4b\x07\x01\x08\x41\x6f\x9d\x61\x58\xcf\x96\xd0\xe6\xdb\x44\x76\x14\xa0\xd9\x08\x9e\xbb\x6a\xee\x4e\xf1\x07\xbe\x45\x93\xd7\x1e\x79\xf6\x79\x86\x68\xa7\x40\xae\x4b\xac\x5a\xc7\x59\x4e\xcb\xd5\xdc\x82\xe7\xd0\xf9\xcb"}, -{{0x51,0xb1,0xad,0x0f,0xfc,0x21,0x49,0x7a,0x33,0xdb,0xdb,0x85,0xea,0x2b,0xc1,0xce,0x3d,0x0c,0x2d,0x95,0xd9,0x46,0x1a,0x39,0x09,0x73,0xfe,0xe3,0x77,0xfc,0x75,0xf4,},{0xba,0xd0,0x41,0x25,0x75,0xd3,0x80,0x13,0x01,0xed,0xee,0x6b,0xc0,0xf2,0x76,0xe7,0x87,0x35,0x7b,0x41,0x22,0xf5,0x2d,0xe9,0x81,0x88,0x58,0x51,0x88,0x42,0x49,0xcb,},{0xcf,0xb6,0x5b,0x6f,0xf0,0x37,0x7c,0xef,0x51,0x1f,0xd9,0x7b,0x90,0xc3,0xec,0xb8,0x08,0x33,0xf1,0x42,0xa7,0xcf,0x50,0x22,0xce,0xd3,0x0b,0x3f,0xb7,0x86,0x20,0x86,0xd0,0x13,0x39,0xb8,0x86,0x6a,0x23,0x8c,0xb0,0x70,0x27,0x6e,0x19,0x44,0xb5,0xfe,0x32,0xcc,0x40,0x99,0x47,0xcb,0x91,0xde,0xb1,0x43,0x2c,0x29,0x1b,0x60,0xfb,0x0d,},"\x78\x82\xe8\x6e\xf3\x40\x2f\x6d\xbc\x65\xcc\xe8\x31\x5b\x39\x76\x5f\xaa\x4b\x1f\xc8\x76\xfa\xd5\xf8\x22\x0c\xb2\x2a\x7d\xf2\xe3\x58\x0e\xab\x3a\x7e\x8f\xa7\xfb\xb6\xb5\x94\x82\xca\x0e\x36\x4a\x13\x13\x96\xdf\x79\x2a\x32\x41\xa0\x60\xe4\x41\x43\xb6\x76\x74\x93\xc6\xbf\x75\xf1\x87\xa9\x64\x3a\xa1\x1e\x11\xeb\xa7\xb0\xa8\x0f\x0a\x68\xb9\xf1\xb7\x9f\x75\xb6\x6c\xc5\x9d\x9d\xa7\x79\x55\xfd\x7e\x87\x99\xf9\x9d\x6e\xb0\x8f\x90\xd3\x18\xf4\xef\xcb\xfe\x71\x15\x9b\x10\xa8\x3a\xa5\xfd\x69\xbb\x75\x33\x6f\x5d\xf2\x96\xea\x06\x0a\x42\x6c\x95\x45\xdf\x94\x0b\xc1\x45\x4e\xfc\x1f\x9d\xc9\x65\xf1\xf2\x2d\x94\x73\x03\xfb\x8e\xc1\x24\x07\xff\xf6\xb1\xdb\xe4\x7e\x34\x21\xc3\x17\x64\xfd\x90\xc8\x3a\xc7\x11\xd1\x99\x26\xe2\x29\xa0\x64\xc6\x1f\xe3\x67\x6a\xf3\x00\xa1\x71\x6f\xab\xe4\xe3\x84\x22\x64\xad\xb3\x2e\x0d\x9c\x9f\x5d\x4a\x65\xd0\xd7\xb5\xc3\x77\x0d\x73\x7e\xe1\x3c\xbe\xd2\x1d\x7a\x1d\xa3\x6a\xaf\x7e\xc0\xf3\x6f\xcc\x47\x6f\x65\x96\x81\xe5\x16\x0a\x5a\x1f\x49\xe7\x59\xb9\xd0\xfc\xd4\xfd\xb8\x54\xec\xcd\x99\x17\x2a\x47\xd2\xc4\xef\xbe\x0b\x37\x57\x63\x1d\xf1\xba\xe1\x75\xf0\xfa\x74\xdd\x04\x8b\xb6\xa5\xfe\xd8\x43\x02\x84\x34\x9d\xa3\xd6\x7d\xf2\xa6\xf7\xe8\x26\x9b\xc7\x9f\xb2\xc5\xd5\xed\x60\x84\xe9\x07\x6f\x45\x5a\xb6\x38\x91\x90\x46\x36\x9a\x44\x6d\x57\xfc\xad\xa7\x01\x1c\xc7\x71\xbf\x6d\x87\x4a\x8e\x5d\x23\xc6\x87\x74\x7d\xe4\x1d\xd0\x4b\xff\xc7\x17\xd6\x12\x81\x83\x84\x6e\xb5\x94\xb3\xcb\x1c\x1a\x8a\xa0\x4f\x0d\x7e\xba\x53\xaf\x39\xcb\x1d\x4e\x6f\xec\xf3\x11\x3b\xd8\x42\x24\x16\xf4\xc4\x40\x37\xae\xee\x9e\x0f\xdc\x51\x7c\x48\x73\x1f\xd0\x4e\xe9\xc9\x9f\x5d\xbc\xa3\xd5\x74\x50\x9d\x7b\xaf\x32\x88\xf2\xc2\x30\xa0\x2d\x17\x03\xbd\xb1\x61\x1c\xde\x2a\x76\x6d\xac\x19\x3d\xe1\x67\x44\x3d\x20\x09\x0d\xc3\x4d\x29\x27\x7a\x86\xb1\xe9\x98\xb2\x45\x64\x51\x17\xe5\x11\x1f\x12\xf1\x46\x06\xc5\x54\x46\xdd\x91\x2d\x34\x75\xc1\x98\x76\xe1\x9a\xc5\x36\xd3\x17\x87\x6c\x4b\x0a\x2e\x0f\x98\x61\x61\x29\xa5\x68\x37\x32\xa4\x23\x17\xc5\xe8\x09\xdc\xa9\x56\xb2\xab\xb4\x84\xad\xa8\x10\xa1\x5c\x81\xcc\x85\x62\xb5\x55\xda\x94\x58\xf9\xb4\x43\x38\x49\x02\x30\xc7\x40\x4f\x3d\x48\x61\x1f\x84\x12\x7e\x73\xe2\x77\xd8\x8c\x62\x21\x2d\x2a\x3a\x35\x1f\xc6\x76\x65\xb1\x8d\x77\x21\x62\x30\x63\x2c\xbc\x78\x12\x88\xe1\x5c\xeb\xf3\xec\x33\xa7\x20\x5e\xb2\x2b\x9a\xbe\x4c\xdb\xc7\xdd\xba\xaa\x53\x64\x08\x75\xeb\x76\x3f\x52\x2c\x36\xcf\xff\x2e\xb2\x3e\xe5\x86\xd7\x75\x28\x62\x59\xfa\x94\xa4\x4f\xa7\xec\x01\x50\x96\xa2\xa4\x46\xb6\x73\x2b\x80\x02\x42\x67\xfe\x3d\x5d\x39\xd1\xc4\x85\x09\xb3\xec\xaa\x2e\x24\xe5\x4d\xe4\xd6\x1c\x09\x7b\x70\xf7\x53\xb5\xaf\x9a\x6d\xb6\xf9\x75\xd2\x5f\x4f\x83\xd0\x6f\x87\x9e\x17\xef\x7c\x50\x9a\x54\x14\x44\xba\x3e\xb6\x86\x78\x38\x09\x0e\x22\xda\xfd\xbb\x0e\xb3\xb0\x56\x5b\xe1\x57\x9c\xee\xcd\xed\x20\xf5\x44\x25\x6c\x7c\x4e\xde\x3b\x62\x84\x3c\x65\xb0\x46\x6b\xe6\xb7\xe2\x73\x05\xb9\x63\xca\x91\x4e\x3b\x7d\x21\x73\x61\x18\xed\xb3\xd6\x58\xd9\xd7\x6f\x50\x9d\xb3\xb9\xca\x2e\xae\x28\x96\x4a\x4b\x3b\x3c\x38\x4a\x81\xa4\x89\x0e\xe9\x6f\xbe\x93\x4a\x6f\x2a\xec\x8e\xeb\x6c\xfe\x59\xac\x9d\x3b\xbc\x16\x46\xba\x32\xa1\x14\x2f\xee\x59\xfe\xd6\xfb\x7b\xbc\x04\x98\xcc\x27\xde\xad\x41\x3b\x7b\x43\x51\xec\x20\x63\x43\xc0\xab\x89\xfc\xf8\x72\x43\xb1\xab\x45\x0e\x58\xff\x11\xa1\x14\x0a\x38\x3f\x19\x6a\xa3\x97\x6c\xe1\x7c\xf3\x45\x30\xf0\x49\xa1\xde\x90\xe3\x17\x53\xcd\x85\xe7\xf1\xfd\x5c\xf2\x04\x26\xc9\x37\x9f\xeb\x8c\x31\xb4\xbf\xec\x35\xea\x5a\x78\x95\x3d\x75\xc5\xcf"}, -{{0xfa,0x2f,0x46,0x1c,0xe8,0xc7,0x12,0x62,0x18,0xc4,0x7c,0x91,0x56,0x9e,0x87,0x99,0x79,0x7c,0x83,0x36,0x8f,0xc8,0x42,0xb6,0xe1,0xc2,0x2f,0xd5,0x2a,0xec,0x70,0xbf,},{0x6b,0x89,0xb2,0x3f,0x1e,0x11,0xa7,0x5a,0x53,0xf9,0x92,0xf6,0xca,0x57,0x75,0x00,0x8c,0x6e,0x9e,0x7e,0x49,0xc0,0xd8,0x51,0x0b,0x0e,0x83,0x69,0xb7,0xa2,0x0b,0xcc,},{0x84,0xf7,0x9d,0x9e,0x8f,0x30,0xe5,0xbb,0x63,0x62,0x23,0x97,0x14,0x55,0x6b,0x04,0x73,0x6f,0xa4,0x44,0x65,0xca,0xba,0xad,0x23,0xbe,0xaf,0x5a,0x99,0xfc,0x45,0x1a,0xd4,0xae,0x5a,0x18,0xc7,0xf6,0xf9,0x64,0xfa,0x41,0x03,0x92,0x16,0x01,0x8e,0xc5,0xa2,0xac,0xca,0xe1,0x07,0x5a,0x6b,0xb3,0xa6,0xec,0xbc,0x1f,0xca,0x02,0xb9,0x04,},"\x79\x9b\x39\x80\x2a\x18\x27\xe4\x5c\x41\x12\xfe\xe0\x26\x03\x4c\x0e\x59\x8a\xff\xce\x2c\x55\x0c\x19\x3f\xee\x73\xf1\xdf\x8c\x30\xc8\xd3\x87\x33\x40\x08\x8c\xe8\x59\xde\x34\x71\xe9\xd0\x57\x68\x6c\x82\x9b\x54\x08\x79\x5e\x08\xb3\xdc\x7a\xa3\xb6\x37\xc7\xde\x9d\x21\x72\xad\x03\x33\xc1\xbe\xa8\x61\xa6\x23\x2f\x47\xf0\x5a\x10\xbf\x5d\xf8\x08\x15\xa2\x71\x25\x6e\x37\xe8\x08\xa0\xe6\x2f\x1f\x07\xd9\xe1\x0e\xbb\x94\x7d\x3e\xfa\xbf\x8a\x28\xfa\x9d\xcc\xd9\xa1\xd5\x99\xf5\xfd\x61\x65\x50\x8e\xfd\x67\x9c\xf3\x56\x01\x50\x58\xbf\x4b\x34\x11\x8f\x83\xaa\x3e\x5b\xc2\xce\x19\xec\xa8\x4f\x71\x83\x98\xad\xbc\x0a\x52\x76\xcf\x9d\x8c\xaf\xfc\x27\xe3\xe6\xab\xbe\x34\x5b\x0e\x9e\xcf\x89\xc6\x77\x1b\x0e\x75\xd4\x08\xba\x2f\xbb\x90\xfc\xfd\x70\xc5\x3f\x2e\x4d\x52\xba\x54\xd9\x78\x4c\xf7\x1c\x34\x9e\xf6\xf1\x4a\xe4\x97\x0d\xef\x6e\xfb\x5f\x30\xe9\x84\xd6\x01\x6a\x19\x6d\xea\xec\x7e\x04\xb4\x76\x19\xc4\x8b\xf4\x9d\xc0\x2f\x7f\xef\x3e\x13\xb7\x56\x17\x4e\x90\xd0\x5f\xcb\xdd\x5e\x13\xf0\xe4\x34\xef\xd5\x42\x1b\x09\x1d\x51\x79\x00\xed\x0d\x57\x85\x96\x88\x62\xb4\xbf\xe5\x09\x3a\xb6\x72\x17\x18\x0d\x97\x55\x4c\xcd\x9c\xc3\x14\x29\x32\x6c\xab\x42\xf3\xf8\x39\x80\x60\xc1\x9d\xb4\x88\xb5\xd1\xc8\x0b\x29\x09\x0a\xfd\x1c\x6b\xac\x36\x42\x26\x48\x00\x21\x1b\xc2\x78\xfc\xb9\x9d\xae\x9d\xbf\x49\xda\xf1\xb2\x4a\xb5\x69\xdc\xbb\x87\xd4\xd3\x54\x73\x35\xe3\x5d\xb9\x84\x00\xcd\xfc\xe6\x79\x06\x82\xe9\x36\x00\x22\x0e\xc4\x99\x24\x5f\xa4\xee\x15\xd8\x43\x83\x1b\x56\xcc\x26\x41\x80\x25\xbf\x87\x00\x16\x05\xc6\x69\x1c\xa6\xbd\x40\xa4\xe2\x48\xc3\x09\x80\x1b\x76\xa7\x95\xed\xe8\xad\x53\x08\xbc\xb6\xd1\x75\x4a\xb3\x37\x1f\x00\x03\xbb\x8c\x4e\x4e\x47\x19\x54\xe2\x8b\x1e\x98\x66\x37\x9f\x82\xe1\xfb\xac\xb7\x9d\x50\xad\xdd\xad\x5b\x97\x78\xb5\x58\xcd\xdb\xb0\x03\x8a\x5f\xf3\xd5\xc9\x55\x7b\x96\x5d\xe3\xa7\x08\x2c\x45\xa8\xec\xf3\xe7\x72\x1e\xb6\x90\xb6\xc7\x1f\x3d\x89\x75\xd5\x30\x0f\x67\xc4\xdc\x4a\x73\x68\x46\xe4\xcc\xd2\x6f\x93\x46\x3d\x5b\xc6\xf4\x6e\xdc\x48\x86\x64\xbe\x96\x96\xbe\x12\xb0\x2d\xd1\x04\xd1\x0c\xc6\xb1\xd8\x2e\x81\x17\x81\x12\x14\xa6\x48\x7d\x17\x36\x7e\x39\x5a\xde\x2e\xf6\xb2\x6a\x17\x83\xa7\xe2\xf2\x45\x21\x3b\xc0\x3a\x75\x5d\xf3\xee\x8e\xf9\xf1\xef\xf9\x72\xc6\x91\x90\x65\xcb\x7b\x75\x66\x78\xd4\xdd\xfd\x19\x3e\xdd\xc0\xb4\x2e\x86\x89\x61\x36\x43\x14\x6d\x74\x28\xca\x37\xbf\x31\xbd\xf1\x4e\x31\x86\x78\x58\xf3\x9d\x23\x23\x70\x9e\xb3\xb7\xd7\xf4\xe3\x97\x02\x23\x78\x42\x4b\xde\xe9\xbc\xb7\x4e\x9d\x5d\xfd\x37\x1f\x47\x34\x99\x8f\xc1\x8d\xf4\xcd\xfb\x4b\x5c\x21\xc2\xe5\x0f\x8d\x6c\x15\xbc\x14\xbf\x4f\xda\x6c\xeb\x9d\x80\x82\xca\xe4\x32\xdf\xc9\x8b\xfb\x3e\xcd\x16\xb8\xd7\x4f\x83\x0b\x64\x2b\x04\x28\x75\xe9\x21\xb0\x54\xbd\x1a\xaa\x58\x1f\x60\xd7\x18\xdf\x66\x9f\x56\xdc\x2f\x10\xd4\x78\x99\x77\x22\x16\x2e\x83\x94\x0e\x61\xa1\xb6\xe4\x2d\xf2\xa4\xa3\xa7\xcb\xcd\xd6\x11\xce\x96\xcb\xcf\xb5\xa9\x5c\xc4\x73\x23\x1c\xa1\x3c\x06\x09\xd0\xce\x1a\xe5\xdd\xb5\x46\x6d\x6d\x65\xee\xfa\xd9\xda\xf2\xa3\x69\x01\xbc\xc9\x45\x84\x7d\xa1\xed\x6e\x2e\x24\x0e\x84\x8b\x23\x1b\x7d\x0e\x1a\xcd\x06\x54\x3e\xc9\x3e\x76\x8e\x59\x98\x5d\x7e\x96\xc8\xc3\x1f\xcd\x12\x10\xf0\x96\x42\x71\xe2\x18\x77\x52\x5c\xb1\x34\xbc\x35\x36\x25\x7d\xbb\x11\xd3\x0a\x3c\x4f\x94\x9f\xb8\x2a\xe0\xc3\x1c\xcd\xfe\x41\x94\x32\x51\xe5\x0a\xa4\x35\x53\x92\xac\x30\x9e\xf6\x0f\xc1\x74\x32\xa2\xbe\x4b\xdb\x2f\xcb\x28\x60\x7c\xc4\x5a\x52\xb6\x00\x16\xbb\x1d\x2e\x23\x97\x2f\xf2\xc2\xa2\x47\xd7\x25\x58\x5b\x1e\xf2\xb1\x5f"}, -{{0x1b,0xe2,0x94,0x9d,0x51,0xe7,0x20,0x81,0x75,0x82,0x62,0x13,0xee,0x6a,0xe3,0xc0,0x91,0x17,0x27,0x42,0xe8,0x8c,0xaa,0x02,0xed,0x0f,0x31,0x3e,0xcb,0xe5,0xd9,0x10,},{0xd7,0xbf,0x47,0x48,0xd6,0xdd,0xed,0x5b,0x57,0xa2,0xab,0xf7,0x97,0xfa,0xcc,0x56,0x0b,0x48,0x56,0x3d,0xfd,0x9d,0xcf,0xf4,0xbe,0x52,0x2c,0x71,0x7a,0x6c,0xfd,0xa9,},{0xf4,0x1f,0x2e,0xf6,0x59,0x5f,0x17,0x66,0x0b,0xb2,0xfe,0x93,0xe5,0x1f,0xc6,0xfa,0x9c,0x31,0xda,0xdc,0x9d,0xb9,0x0c,0x3f,0x46,0x60,0x7a,0x7f,0xb4,0x80,0x0b,0xb7,0x5a,0xd9,0x63,0x25,0xdc,0x7e,0xab,0x78,0x24,0x72,0xb0,0x4d,0xa6,0xd8,0xe6,0xfe,0x64,0x65,0x5d,0xea,0x55,0x1f,0xbd,0x50,0x49,0xe8,0x76,0xce,0x5a,0x40,0x5f,0x02,},"\x04\x5e\x2b\x0e\xc7\xbb\x20\x3a\x49\xbd\xcb\xa9\x41\xe2\xb7\x3c\x23\xc1\xfe\x59\xa1\x7d\x21\xa0\x12\x4e\xa2\x4b\x33\x7f\x92\xab\x9c\x92\x3a\x20\x57\x6b\x62\xd5\xd0\xf6\x24\xe7\x93\x2c\x11\x5b\x54\x74\xe0\xa4\x6a\x4d\xc9\xec\x51\xf6\xa0\xce\x8d\x54\x74\x4d\x1d\x52\x09\x33\x20\xe3\x9b\xe2\x03\xf7\x4a\x0f\x5d\xfa\xc5\x2c\xf0\xf9\x95\xc6\x6d\xf2\x91\x4b\x68\xad\x87\x1f\xbe\x81\x52\x5a\xd2\xd8\x8a\xc6\x99\x33\xa7\x5a\xea\x74\xac\xe4\xe3\x63\x43\xdd\xc0\x6d\x32\x08\xf1\x6d\x80\x5f\x5d\xd7\x86\xb4\xda\xaa\x16\x67\x48\xcf\xee\xc5\x71\x4c\x85\xc1\x04\x78\xb5\x97\xac\x7f\x6a\xe2\xc9\x88\x91\xe3\x8f\xd4\x14\xaa\x81\x1b\x76\x21\xd8\x05\xeb\x8f\xcc\x46\xcf\x4d\x56\x8a\x8a\x92\x58\x7c\xbb\xc1\xae\xcc\x12\xf1\x0d\x90\xac\x1e\x01\xae\x98\x6d\x14\xfe\x82\x95\x1c\x68\x2c\xea\xc8\xc9\x25\xfc\x66\x54\xd8\x38\xac\x93\x53\xae\x2f\x93\xf3\xc8\x8b\xf7\xb8\x2c\xbc\x43\xb1\xe4\x9e\x5c\xeb\xfb\x19\x49\xad\xe4\xb2\x2e\x4b\xcf\x1b\x40\x0c\x0a\x8f\xa8\xa6\xfe\x76\x70\xf6\x9f\xc3\xfa\xec\xd4\x80\x5b\x8c\x95\x4c\x01\xa5\x40\xd1\xa1\xe7\x88\x43\x6e\xae\x07\x3a\xe9\x56\xda\xe3\x17\x69\x05\xa8\xf0\xa3\xc6\x0f\xd9\x80\xda\xb4\x19\xd4\x1e\xc0\x6e\x52\x73\xfb\xb1\x3d\xb9\x38\x1f\x89\xb6\x63\xcc\xc4\xbd\x75\x3f\xd9\x0f\x14\xa7\x7b\x3d\x81\xc4\x5d\xd3\x56\x1c\xd1\xfa\x0e\x94\xd2\x34\xce\xf9\xd7\x85\x9a\x2e\xc9\x42\xbf\xc1\x88\x49\xd7\xf2\xad\xa3\xa5\xd6\x57\xbc\x19\x3d\x2e\x14\x91\x68\x2f\x16\x65\xa5\x34\xb1\xac\x20\x83\xb7\x38\xbe\x8f\x9e\x96\x3f\x59\x41\xed\x48\x3c\x6a\xcc\x82\xe9\x59\xb8\x1b\x8a\xf0\x2f\x47\x1c\x08\xf5\xf8\xb1\x2e\x10\xe0\x08\x19\x28\x98\xa4\x45\x02\x02\xaf\x73\x15\x92\xe7\x4e\xfe\x2a\x94\x8e\x51\xd0\x6e\x44\xde\x9b\x95\x6b\x7b\xc9\xa6\x9b\x6e\x74\x68\x7a\xb2\x06\xde\xc4\xd3\x5b\x31\x73\xfb\xc4\x38\x82\x9d\x50\x64\xbf\xbc\xf7\x43\xc1\xe2\xd4\x6f\x62\x8f\x2e\x51\xc6\x26\xd8\xe4\x16\xd7\xbe\x6e\x55\x5a\x24\x96\x91\xab\xb1\x67\xf1\xd9\x2f\x4f\xa3\x39\x2f\xde\x24\xe9\x93\xce\x7f\xf5\xc1\xb8\xe1\x57\x7a\x7c\x0e\x73\x02\x5c\xc6\xfc\xd7\x27\xa8\x2e\xf0\xc1\x29\xe9\x1e\x55\x33\xe0\x21\xa3\xcd\xbb\x99\xd5\x4b\xf7\xcd\xcd\x3f\xf1\x19\x15\x4f\x3f\xad\x92\x42\xb6\xed\x35\x0d\x10\x37\x2c\x97\x6f\xf3\xa4\x37\xd0\x97\x86\x7d\x9b\xfb\xa9\x1d\x84\xbd\xa5\x5a\x6b\xcd\x6e\x36\x41\xb2\x13\xa2\x18\xb3\x04\x15\x89\xc5\x5a\xfb\xb3\x44\xde\x6e\x97\xd8\xc3\x5b\x5c\x86\xcf\x3b\xe0\x63\xf9\x01\xff\xee\xa8\xcc\x91\x06\x99\x67\xd2\x34\x60\x35\xa9\x1e\xb5\x70\x6a\x3b\x53\xf6\xd1\xc3\x4d\x4d\x21\x16\x70\x6b\x65\xc2\x98\xec\x57\xde\x82\xab\xc4\x00\x3c\xe8\xcc\x5e\x0b\x88\xff\x71\x0d\xda\x1d\xce\xf6\xf1\x54\x27\x71\x06\xb8\x3e\xb4\x6c\x04\x5b\x08\x2d\x11\x3b\x36\x1d\x6a\x62\x58\x08\xc9\x13\x05\x84\xdf\xc9\x67\x07\xef\x89\x55\x90\x7b\xaa\x61\xcf\x88\xc6\x6b\x6d\x1f\x60\x58\x11\x19\xcb\x62\x17\xa8\x52\x15\x73\x36\x17\x8c\x68\x5e\x6e\xd4\x85\x26\xed\x5c\x4e\x3b\x79\x67\xd5\x1f\x99\xdf\x68\x76\xa1\xac\xfb\x84\x5c\x57\x1b\x89\x86\x56\xe5\xe3\xbc\x73\x98\x0b\x9b\xed\x11\x98\x86\x63\x59\xc9\xe9\xb1\xef\xa9\x15\xf8\x10\xd1\xef\x8a\xd6\xcb\x3f\xc2\x1f\xbf\xe6\x54\x30\x6d\xe6\xca\x13\xa3\xa6\xa4\x8e\x7a\x13\xed\x87\x46\xac\xbd\x07\xf4\x8e\xb0\x0c\x36\x37\x4b\x1e\xb4\xf3\xf0\x1c\x19\xe2\xe8\xd3\x7e\x9f\xc0\x64\xb3\x3c\x0d\x66\x9b\xba\x55\x4d\xdc\x68\x21\xa7\x7b\x40\x89\xca\xbd\xca\xfc\x97\xf6\x0e\x60\x50\xbc\xa4\x44\xae\x8c\xfc\x44\xd9\x3c\x40\xef\x53\x18\xbe\xe6\xf8\xcf\x0c\x06\x7b\x85\xcd\xdd\xc4\x59\x74\xa4\xea\xcf\xc3\xef\x51\x31\x5b\xa0\xf3\xf6\x29\x68\xc7\x00\x3a\x7f\xf4\x44\x61\x24\x00\xb1\x59"}, -{{0x3b,0x6b,0xa6,0xd5,0xcc,0x9c,0xd6,0x24,0x1d,0x8b,0x00,0x97,0xa3,0x72,0x2e,0x4d,0x06,0x6f,0xea,0x3d,0x56,0x0a,0xea,0xb4,0x67,0x3e,0x86,0xf1,0xf8,0xec,0x60,0x26,},{0x8c,0xa6,0x52,0x07,0x17,0xcf,0x36,0x3c,0x4c,0xef,0xfa,0x76,0x32,0x8a,0x0a,0x16,0x6f,0xf8,0x3e,0x45,0xca,0x7d,0x19,0x1c,0xc8,0xef,0x6c,0xa6,0xe5,0x24,0x33,0x67,},{0x78,0x8c,0x9f,0x45,0x54,0xdd,0xba,0x5c,0x7d,0x64,0xba,0x75,0x9e,0xc4,0x56,0x94,0xec,0x79,0xfb,0x85,0xe8,0x23,0x68,0xa0,0x74,0xbd,0xd8,0xdf,0x34,0x42,0x13,0xa5,0x6d,0xd0,0x9f,0x33,0x4c,0xd9,0xac,0xb9,0x41,0xbe,0x28,0x3d,0x98,0xc4,0xb1,0x5d,0xcf,0xec,0xd1,0x4e,0x93,0xf6,0xa2,0xe3,0xcb,0x0c,0x1a,0xa2,0xde,0xe7,0xd9,0x0b,},"\x36\xde\x93\x0c\xc8\xe1\x88\x60\x83\x6a\x0c\x82\x9d\x89\xe9\x63\xa5\x8b\xdd\x9c\x6b\x6e\xf5\xbc\x61\xf7\x59\x92\xd2\x07\x52\x42\xdc\xa2\x3e\x28\xde\x20\x5a\x33\xdf\xea\x86\x1f\xc4\x4a\x32\x62\x8e\x8e\x7c\xdd\x3e\xd7\xff\x49\xea\x6a\x70\x97\xe0\x09\x0c\xfd\x9f\xf5\xec\xab\x1d\xe8\x22\xfc\x0a\x4c\x37\x76\xdd\x56\xc1\x91\x92\x04\x51\x6a\x94\xce\xc5\x63\x8d\xa1\xd9\x9e\x52\xb8\x66\xf5\xec\x41\x62\xa9\x12\xed\xb4\x1c\x1e\x92\xed\xfc\x35\x3f\x67\x05\xe1\xc1\x2c\xd4\x1c\xb6\x2d\xed\x4a\xd8\x15\x79\x40\x05\x9b\xfc\xf5\x07\x19\xd3\xf2\xad\x00\x84\x85\x40\xce\x89\xf3\xf9\xaf\xa6\x10\xcc\xba\x5e\xcc\x37\xe3\xe2\xc1\x53\x4f\xcb\x38\xfc\xd3\x9a\x2d\x14\xd5\xb5\xda\x6f\xea\x24\xe0\x06\x65\x4e\x30\x90\x47\xa2\x9c\xad\x0a\xe4\xda\x8e\x70\x8f\x97\xa1\x8c\xad\x5f\xbd\xc9\xac\x84\x40\x0c\x53\x2c\xed\x54\x88\x86\x53\x9e\xdd\x6c\x54\x10\x74\x79\x0a\xe4\x50\x2f\xdf\xe9\xf3\x27\x3a\x87\x6a\x21\x86\x23\xa2\x57\x06\xa1\x52\x5e\x67\xe5\x7a\x16\xd2\x2c\x21\xb6\xa4\x5e\x23\x84\xe2\x87\xac\x44\x52\xae\xc4\xe0\x63\x05\x6b\x4c\x17\x8a\xb0\xe5\xb2\xa5\xba\xd3\xf4\x63\xc4\x72\xc4\xea\x1f\x9c\x1a\x66\xe5\x27\x04\x73\xa8\x35\x09\x4e\x8f\x0e\xef\x68\x0c\xd7\xb2\x0d\x0e\x70\xf4\xd6\xc9\x58\xfe\xe0\x8a\x93\x60\xaa\x60\x66\x88\x8f\x4d\xd7\xce\x5e\xc2\x22\x59\xfa\x0b\x53\xfe\x92\x71\xc0\x83\xc6\xfc\xdb\x72\x83\xb0\x90\x61\x08\x8c\x52\xf7\x1b\xfd\xd2\x77\x7c\xe0\x80\x1f\x41\xa6\xc4\xce\x90\xef\x13\x1d\xe1\xe1\x83\xcb\x89\x49\xce\x32\x3c\x9e\xb1\x3a\x4b\x0c\xac\xf9\x9d\xef\xdf\xdb\x68\xd5\xed\x1f\x68\x91\xb4\x8e\x21\x04\x76\x68\xd6\x9d\xe8\xa8\x0f\x8e\x56\x34\xde\xd0\x87\x36\xa4\xfb\x54\x10\xcd\xea\x9c\x72\x59\x6e\x36\xdf\x68\x41\xf2\xee\xa4\x68\x50\xc8\x74\x73\xc8\x95\x54\x02\x05\xb0\x92\x19\x60\xff\xa5\xd9\xd8\xff\xb8\xe2\x9c\xde\x96\xa3\xed\xe0\x15\xac\xbc\x26\x97\x40\x04\xd3\xe4\x38\xa8\x5b\x2e\x33\x85\xf6\x4d\x18\x14\x00\x39\x41\xff\xd3\x63\x99\x2d\x39\x40\xc6\xe6\xd8\x1f\xf8\xe4\x5f\xce\xd6\xd3\x6c\xe1\x98\xd8\xcc\xbe\xfe\xe4\x32\xa7\x7d\x8f\xca\xdd\x73\xfb\x79\x9f\x6b\xaf\xef\xb5\x1a\x2d\xa7\x98\x72\x1c\x3d\x46\x5b\x16\x3e\xf1\x3e\x6e\xcc\x65\xe6\x03\xb2\x89\x3e\xe4\xcc\x9e\x1c\x6d\x1d\xe7\xa6\x5c\xab\x5c\xbd\xf5\x36\x85\x5e\x28\x8c\x3c\xcd\xa8\xd2\xfa\x3c\xe1\x0c\xf4\x93\x58\xa2\xef\x4e\xf0\x76\xe5\xbf\xa9\x1b\xbc\xf3\xd9\x66\xdf\xa3\xdc\x6e\x71\x2f\x19\x56\xd4\xe5\x8a\xa3\x6e\x71\x2d\xd3\x34\x71\x69\xb1\x9c\x8d\x44\xbe\xc5\xbc\xb7\x30\x77\x8f\xcc\xcc\x58\x9e\xd5\xd3\x50\xd4\x4c\x17\xbd\xe2\xee\xbb\x6f\x5e\xc5\x9f\xb2\x40\xd6\x7d\x81\xae\xa9\x26\x7f\x34\xf1\x5e\xee\x2d\xe3\xf4\xfa\x67\x39\x14\x79\xbd\xbb\x43\x0f\x48\x43\x70\xfb\x0e\x08\x95\xb9\xae\x06\x5b\xbd\xd4\x3e\x23\x0c\x62\xac\x07\x18\x4e\x8b\x06\xb2\x4b\x8b\x97\xec\x02\xdc\x6f\x37\xef\x61\x64\x1e\xd5\x6e\x3f\x5e\xb8\xd2\x08\x0b\x51\x44\xef\x76\x0b\x51\x87\x52\xe1\x97\x54\x79\x2e\x19\x34\x3a\x38\x55\xe1\xe2\xf7\xa7\xdc\x62\x35\x17\xee\xd2\xf5\xd2\x65\x48\xa6\x8e\xb8\xff\xd7\xbf\x70\xf7\x8f\xd1\x86\xdb\x63\x49\x28\xbb\x98\x13\x8f\x2b\x8f\xe8\x44\x81\xcc\x53\xf5\xaa\x35\xe2\x66\x6c\x63\x25\xe1\xd2\xb8\xac\x5e\x2d\xf2\x93\x5b\x7f\x64\x13\x95\x2d\x10\xd6\x07\x6f\xfc\x75\xbb\x6a\xf6\x3b\x29\xb0\xb9\x66\x3b\xec\x37\x24\x7b\x66\xb5\x08\xdd\xe4\x1f\x2f\x11\xb8\x43\x33\x55\x9d\xfa\xc7\x3f\x76\x1b\xcd\xa8\x4a\x48\xd2\x66\x07\x3a\xef\x16\x38\x46\x08\x49\xe7\xa1\x72\x06\xa2\x5f\x68\x00\x77\x0b\x91\x4c\xc0\x26\xba\xf9\xe3\x25\x59\x14\xe1\x32\x58\x44\x1c\xef\x35\xad\x1d\x66\x83\x3e\x98\x7e\xbe\x44\x31\xe6\xa6\xbb\x22\x2c\xbb\x65\xaf"}, -{{0xdd,0x99,0x87,0xb1,0x8f,0x9a,0x92,0x2c,0x0f,0x6f,0xea,0x18,0xeb,0x00,0xb8,0x96,0xc7,0xa2,0xd3,0x09,0x3d,0xb3,0xea,0x31,0xd3,0x84,0x21,0xda,0x0d,0xe5,0x12,0x31,},{0x57,0x39,0x21,0xa9,0x55,0xfe,0xb6,0xdd,0xe4,0x1b,0x05,0x5c,0x8d,0xac,0xac,0xcd,0x1d,0xb7,0xfe,0x9e,0x36,0xb5,0x09,0xd3,0xc9,0xe3,0x6f,0x97,0x35,0x75,0x23,0x24,},{0x3e,0x9f,0x2b,0x00,0x7c,0x0e,0x29,0xec,0x87,0x59,0x95,0xa6,0x30,0x9b,0x97,0x3d,0xeb,0x8b,0xaf,0x11,0x3d,0xed,0x13,0xf1,0xe0,0x00,0x3e,0x9b,0x9b,0xf9,0x39,0x16,0xa4,0xdf,0xe4,0x79,0x37,0xda,0xdf,0xc7,0x8a,0xa6,0x63,0xc5,0x5f,0x67,0x4e,0xc3,0x5c,0x38,0x46,0x25,0x8f,0x18,0xe7,0xbb,0x93,0xfb,0xba,0x3e,0x82,0x6a,0x1f,0x0d,},"\x48\x16\x2f\xdc\x3a\xbf\x73\x19\xc6\xca\xab\x60\xcb\x8d\x05\x20\x87\x5c\xb4\xee\x8a\x07\x09\x27\x83\x16\x7d\x47\x33\xff\xe5\x20\x4e\x5f\xeb\xe7\xd2\x91\xe9\x53\x6b\xde\xa3\xdf\x06\x37\x15\x9a\x65\x3e\x09\xfd\x99\xaf\x66\x1d\x83\x00\xae\x74\x1a\x3e\x91\xa8\xbd\x85\xea\xd0\x5d\xc7\xd9\xe6\xf9\x29\x32\x33\x16\xed\xc4\xca\x62\x4e\xa7\x81\x8b\x25\xbd\xc0\x61\xf7\x14\x92\xfd\x22\xd4\x65\xab\x22\x6f\xd9\xa1\x0d\x8b\xab\xfc\x07\x4c\x68\x6c\x43\x6c\x24\xa3\xa5\x3f\x8f\xf3\x89\xce\x9c\xa1\xdb\xc8\x90\x74\x45\x88\x92\x41\xf8\xfd\xa3\xa7\xa3\xf5\x02\x4f\xa8\xcb\x0d\x04\x4b\xda\xf6\x71\x6d\x98\x3a\x6d\x83\x98\x14\xff\xe7\x0d\xdc\x55\xbb\xba\x11\xac\x97\x88\x7b\xdb\x4d\xad\xa9\x65\x65\xbb\x07\x5d\x5f\xc1\xd3\xc5\x24\x4b\x9f\xff\x77\xde\x58\x72\x9a\x05\x9a\x91\x1f\xb3\xe0\xeb\x16\x4f\xb8\x42\x9e\x26\x56\x85\xd1\x4a\x63\x23\x30\x46\xd2\x0e\xcf\x28\x9c\x55\x72\x31\x69\xa9\xd6\x3d\xda\x0d\x52\x55\x15\x3d\x9e\xf4\xa6\x1b\x92\x12\xf4\xb8\x20\x69\x7a\xe7\xc3\x08\xcf\xab\x40\x3b\x2c\x34\x31\x90\x62\x26\xe4\x5c\xe2\x19\x20\xdf\x52\x01\x60\x9d\xaf\x83\x0f\x28\xad\x79\x60\x05\xa9\xbd\x8e\xba\x62\x0c\xf8\x39\xc3\xba\x22\x7b\x96\x3c\x7b\xd0\x91\x48\x22\xdf\x2c\xa0\x3c\x22\x54\xd0\xcb\x8a\xca\xe0\xd5\x9e\x4c\x3e\x0e\xc2\x15\xc8\x36\x96\x9d\xcd\x1d\x49\xbf\xe1\x97\xe2\xf3\xee\xa3\xfa\x8a\x37\x3b\x55\x8d\x0f\xb9\x06\x3c\xf1\x56\x8e\x73\x9a\xad\x8f\x09\xfb\x43\x7c\xaf\xb5\xa2\x72\x37\x5f\x43\x60\x64\xee\xe1\x1b\xd9\x03\xd3\xaa\xea\xb4\xe3\xfd\xcd\x36\xbd\x20\x76\xee\xa1\x79\xa4\xf0\xd4\xfb\xc8\xdf\x42\xbf\x26\x60\xf0\x8d\xe7\xd5\xc6\x39\x7c\xae\x10\xb7\x27\x74\x58\xaa\x6c\xfa\x01\xe8\xa6\x73\x7e\xb1\x26\x22\x78\x56\x64\x66\x91\x68\x1c\x10\x6a\x15\x7a\x26\xae\xd2\x1b\x1a\xaf\x0e\xd2\x76\x64\x21\xcf\xc3\xd1\xc7\xdd\xfb\x72\xfc\xdf\x4b\x8b\x49\x0f\xc0\x9a\xce\x49\xae\xdd\x77\x12\xb2\x1a\xc5\x6f\x86\x01\xf6\x25\x56\x3c\x78\x43\x06\xf3\xb9\x17\x4a\xdd\xf7\x64\xe0\x51\xaa\xdf\xe1\x28\x31\xaf\x96\x69\xe6\x2c\xab\x12\x1c\x74\xdf\x34\x37\x24\x42\x9d\x6c\x26\x66\x02\x71\xc3\x2f\x40\xcf\x7c\x2d\x08\xbd\x0a\xfc\xc7\x28\xde\xf4\x13\x5d\x4e\xb5\x5b\x6a\x3e\x76\x29\xd8\x06\x86\x4a\x85\xb3\x6a\x32\xb9\xb2\x1a\xc0\xd3\x96\x80\xa2\xae\x4e\xc4\x18\x97\x09\x17\x8e\x34\x94\x97\xf3\x93\x99\xfb\xc7\x8b\x3c\x6c\xfa\xca\x6e\xde\xa7\xc3\x3d\xda\x3c\xc1\x1e\x43\x84\xf1\x58\x3d\x6c\xfc\x6b\x58\xf4\xea\xa2\xbc\x56\xab\xa4\x2f\x73\x8a\x42\x9b\x93\x58\x08\x50\xde\xe3\xfd\x25\x39\x94\xf8\xb0\xfa\x66\xee\x8e\x27\x3d\xec\xab\xd5\x32\x09\x5f\xb0\x4a\x4a\x3c\x34\x0a\xf0\xe5\x5b\x57\xef\xab\x43\x63\x0f\xc0\x2e\xf2\x0b\x42\x5c\xa2\x18\x7e\x3c\x6c\x5e\x10\xf1\x2d\x61\x8f\xd2\x43\xa2\x24\xf6\x50\x1e\xbe\xb9\xd3\x21\xc6\x38\x5b\x81\x27\xef\x9c\xdc\xd0\x97\xce\x7f\xa0\x21\xcf\x40\xd2\x1c\x39\x91\x23\x43\xf6\x7a\xcc\xe1\x82\x5e\x3a\x51\xb8\xa7\x18\xe8\xc3\x40\x62\x2f\xff\x65\xfe\x00\x53\xd2\x4a\xa3\x35\x1b\x6a\x24\x00\x18\x5d\x7a\xeb\x88\xe8\x7a\xc4\xa1\xd3\x94\x90\x9d\x49\x41\x4a\xef\xc2\x2b\xa0\x09\xaf\xf6\x96\x2c\x92\x17\xd7\x55\x69\x4e\x4d\x6a\xa8\xa5\xd6\xa8\x03\xce\xbb\x15\xde\x8f\x54\x16\x34\xb6\xfc\xeb\x0c\xac\x79\xdd\xa8\xa1\x8e\xef\xbb\x53\x7e\x70\xff\xe9\xaa\x5a\x6a\x6a\xaf\x92\x40\xfa\xc2\xea\xcb\xfb\xef\x01\xad\x6b\xdf\x50\x75\x87\x80\xf8\x6a\x4e\x48\x89\x85\x36\x2d\x58\x25\x01\x1f\x5e\x8b\x66\x42\x5a\x61\x6b\x7e\x10\x4e\xb2\x3f\xe8\xf1\x00\xcb\x02\x49\x82\x36\x62\xbd\xa3\xda\x47\xa4\xc3\xc1\xca\x2f\x91\x4b\x25\xb9\x73\x85\x34\x02\x60\x47\xdf\x6d\x7f\xf6\x31\xdf\x2c\x41\x31\xf6\x80\xe1\x37\x43\xc9\xcc\xf2"}, -{{0x38,0xd2,0xef,0x50,0x9f,0x93,0x05,0x1f,0x14,0x51,0x67,0x73,0x7c,0x22,0xe1,0xa5,0xbf,0xe8,0xf4,0xa9,0x1e,0xba,0x0b,0xb8,0x7c,0x39,0xce,0x04,0xa8,0x9b,0xae,0xc6,},{0x01,0x11,0x5f,0x6d,0x89,0xa5,0xda,0xab,0x54,0xf8,0x92,0xbb,0x4a,0x4b,0xda,0x1c,0xe5,0xd8,0xf6,0xc9,0xc8,0x8a,0x50,0xce,0xe8,0x3b,0xd9,0x87,0xa2,0xc0,0xdd,0xf7,},{0xde,0xc4,0x62,0x53,0x50,0x9b,0x11,0xe4,0xb5,0x2a,0x6a,0xe4,0xf3,0x66,0xb6,0x80,0xdf,0xfc,0x28,0x0d,0x0a,0x04,0x4f,0xc0,0xcb,0x79,0x0b,0x6e,0x75,0x13,0x81,0x46,0x1e,0x1e,0x60,0x2a,0x89,0xe3,0xb3,0xd3,0x06,0x4c,0x40,0x7f,0x60,0x2f,0x1c,0x22,0x40,0x4b,0x68,0x23,0xbd,0x24,0x67,0x54,0x93,0x14,0xa0,0x00,0x01,0x66,0x4a,0x08,},"\x42\x7b\x5a\x01\xe8\x59\x7f\x04\xfd\x42\x2f\x0a\x66\x2d\x0b\xe2\xdf\xa8\x53\xed\x5f\x9d\x3f\x60\xff\x90\xf2\xc5\xee\x08\xbb\x59\xfd\x03\xd4\x02\xb7\x54\xca\xf5\x4d\x00\x58\xf5\xa2\xcf\x87\xaf\x4f\xef\x21\x77\xd5\x9e\x18\x22\x62\x93\xfd\x2a\xf3\x76\xbc\x98\x7b\xf7\xb3\x20\xb9\xd1\xe2\x49\xab\x9e\xfb\x75\x07\x8e\x6d\x3d\xf2\x9e\x03\x50\x47\x76\x35\x43\x44\xaa\x69\xe7\x2e\x1e\xbc\x52\xa3\xc3\x8a\x4c\x2a\x16\x73\xb4\xe9\x74\xa2\xe4\xe1\x2a\x2e\x78\xea\x3e\x3f\xe5\x0c\x53\x63\x0d\x09\x6d\xa3\xe2\xfe\x82\x99\xf7\x1a\x1b\x44\x1b\x4c\xf0\xca\xeb\x93\x7a\xfa\x4a\x0e\x39\x15\xcc\xab\x39\x96\xc9\xf6\xa8\xf4\xfd\x37\x54\x3e\x8f\x75\x90\x0c\xfd\x47\x17\x53\x70\xef\xb8\x52\xa5\xf6\x9d\x67\x36\x83\xf9\x98\xfd\xcf\xf8\x5f\xf8\xf3\x2b\xaa\x80\x70\x66\x60\x44\x22\x02\x7d\x51\xa4\x35\xdd\xf9\x88\xed\x2f\xd8\xeb\x19\x1f\x10\xb4\x68\x07\x42\x00\x08\x75\x6e\xb4\xe3\x00\xc4\x09\x9c\x2d\x64\x50\xbc\xc6\xa4\xe7\xd0\x67\x31\x56\xb8\x37\xf0\x50\x63\x38\xf3\xd1\xb5\x73\x4b\x16\x6c\xa5\xcc\x2f\x24\xa4\xef\x02\x6c\xda\x2c\x4a\xe3\x10\x5b\x63\xca\x85\x70\xd1\x85\x46\xcf\xac\xb8\x60\x42\x96\x6a\x00\xef\x52\xc7\x29\x90\x19\xf6\x8a\x2d\xf0\x8c\x8b\x70\x4e\x85\xe7\x13\xc3\x48\xd7\xf1\x67\x76\x60\xe1\x8e\xba\xb5\x9b\xf4\xe1\x2e\x6f\xf2\xd7\x83\xd8\xd5\xd4\x2a\xab\x6e\xf0\x17\xb7\xa1\x96\x6a\xee\x8d\xc1\x4d\xda\xbe\xd4\x9b\x4b\x64\x3d\xf4\xe9\xb0\xb6\x03\x83\xc7\xd8\xb4\xb8\x8c\x65\xa8\x98\xc1\xc7\x7d\x43\xd6\xbd\x68\xb2\xa5\x74\x3f\x1f\xed\xd6\x54\xdc\x84\x49\x6d\xa0\x2c\xeb\x69\xb9\xb4\xd3\xa8\xe0\x0c\xcd\x72\xe7\xc7\x5f\xc5\x0a\x8d\xd0\x87\xe1\x83\xe6\xc1\xf5\x79\xba\xeb\xc5\xc6\x3f\x28\x07\x93\x67\x91\xb5\xfe\x48\x47\xcd\xcf\x15\x17\x74\x23\x52\x05\xcd\x2d\x7b\x8b\xf4\xae\x88\x19\x22\x5e\xa7\x08\xb7\xba\xac\x66\x99\x8f\x0c\xba\xb2\xc7\xdd\xf2\x51\xf3\xb1\xde\x10\x17\xd3\x97\x69\x22\x05\xee\xa6\x39\xf1\x2d\x77\xbe\xef\x6c\x13\xbb\x12\x10\x0f\xf8\x90\x64\x70\xbc\x7b\x21\x29\x80\x53\xbe\x1a\x61\xb7\xb3\xa4\x99\xed\xc3\x10\x99\x6c\x8b\xc0\x87\x19\x07\xca\x46\x8e\x89\xed\x31\x1a\xdc\xa2\xe2\xb8\x29\x30\x97\x5b\x3e\xfb\xbf\xc0\x3c\xdd\xf4\xd9\x48\xc4\x76\x5e\x8c\x10\x59\x08\x82\x16\x9a\xcd\xdb\x8f\x8c\x36\xd8\x4c\x2d\xac\x3b\x79\x8e\x7a\xbf\x84\x47\x12\xfa\x45\x8d\x27\x7c\x24\xe8\x14\x04\x7d\x74\x23\x19\xa8\x34\xdd\x9f\x92\x7a\x2b\x44\x85\xef\x13\x74\x5f\x7a\x60\xdd\x6b\xb3\x37\x93\x63\x04\xc9\x7d\x3f\x9f\x14\x4e\xb2\x9b\xb6\x95\xb8\xdc\x31\xb9\xd8\x49\x10\x61\x1d\x28\xd5\x81\xca\xa9\x36\x5d\x6d\xff\x52\xd4\x10\xa4\xad\x52\xbd\x12\x17\x29\xff\xf5\x28\x88\xf4\xda\xae\x17\x07\xf6\xf5\x6d\xac\x61\xff\xb9\x96\x1c\xda\x71\x76\xaf\x44\x60\xa6\xd5\x54\x2a\x20\x44\x6f\xb5\x14\x7f\xce\x72\x72\x04\xce\xc6\x89\x9b\x9a\x3d\x4f\xf6\x22\x6b\xb8\xa1\xc7\x8e\x36\xfc\xdd\x9e\x50\xc0\x40\xd7\x2d\x0f\x40\x07\xd3\xfa\x9a\xa7\x67\xe4\xab\xd0\xad\xd6\x2f\xdb\xcc\xde\xff\x67\x21\xeb\x25\x9e\x00\xa7\x21\x63\x20\x06\xbe\xde\x0d\x17\x3d\x38\x34\x4d\xea\x44\xf9\x6b\x67\xd9\xa2\xee\xa1\xd2\xaf\x5f\x74\x8e\x8e\xbd\xb4\x41\xbf\xb4\xe5\x8e\x2d\x42\xfe\xc7\x40\x56\x6a\xcf\x73\xa3\x03\x35\x8f\x7d\x89\xc8\x15\x8c\xf2\x1f\xe8\x5b\x0d\x4a\x41\x7e\xbd\xc8\x6d\x04\x69\xf6\xb9\x1c\x24\xad\x61\x0d\x48\x6d\xed\xc2\x18\xb2\xce\x7a\x8b\x96\x75\x47\x23\x15\x1f\x0d\x00\x76\xff\xf9\xf1\x9d\x11\x2d\x9c\x05\x92\xfb\x8d\x92\xc9\x9d\xcb\x8d\xdf\xaa\x46\xfb\xe0\xd9\x2d\xf4\x6b\x8c\x00\xca\x43\x45\xad\xb6\x9a\x5a\xca\x69\x4a\x86\xcf\x30\x64\x64\x51\xbb\x17\xba\x6e\x60\x7a\x91\x2b\xf1\x09\xd5\xfc\x2d\x3e\x27\xd0\x0d\x94\x56\x00\xa8\xa5\x7c"}, -{{0x43,0xbf,0xb3,0xdb,0xe4,0xd9,0xbd,0xaa,0x82,0xb3,0x54,0xdd,0x59,0x63,0x34,0xe6,0x60,0xd7,0x6f,0xc0,0xb2,0xeb,0x69,0x89,0x93,0xae,0xf3,0x76,0x7f,0x1c,0x7c,0x7f,},{0xd0,0x0a,0xec,0xef,0xf0,0xce,0xb8,0x32,0xc2,0x51,0xd1,0xfe,0x6b,0xcb,0xea,0xea,0xcb,0xb4,0x11,0x3f,0x52,0x81,0xba,0xba,0x4e,0x87,0x8f,0x7b,0x95,0xf9,0x3f,0x07,},{0xa9,0x99,0x55,0x23,0x02,0x0a,0x0d,0x22,0x2b,0xc4,0x8f,0x98,0xd0,0x55,0x04,0xe3,0x06,0x8f,0x30,0x4a,0x6d,0x19,0x70,0x06,0xcc,0x9c,0x03,0x5e,0xea,0xde,0x09,0x9e,0x7a,0xa9,0x7e,0x90,0x89,0x4e,0xad,0x17,0xe8,0xc3,0x0b,0x0a,0xa4,0xa9,0x80,0x88,0xf0,0x38,0xb9,0x22,0x44,0xc4,0xb2,0x0f,0xde,0x96,0x4f,0x85,0x34,0xe8,0xfb,0x03,},"\x3f\x3e\xed\xdc\xae\xf4\xe1\x66\x2a\xdb\x66\xbb\x1b\x20\x7d\x79\x3f\xcb\xef\x81\x50\x05\xe8\x26\x43\xed\x70\xc9\x85\x54\x03\xda\xc2\x8b\x52\x07\x27\xa9\x01\xa5\x32\xd2\x8b\x9b\xd1\x34\x8d\xb2\xf8\x96\x7b\xbb\x8c\x90\x98\xb0\x7f\x57\x0a\x2e\xae\x1e\xe4\x82\x64\x0c\x0b\x67\xa5\x2a\x38\x61\x21\x33\xa1\x5e\x25\x8e\xde\x38\xcd\xa8\x78\xff\x36\xed\x32\x1d\xff\x87\xcc\x6a\x01\x38\x3b\xa8\x40\x67\xd6\x0a\xf4\x17\x76\xac\xf8\x0a\x8a\x4e\xac\x77\xf7\xd8\x7c\x37\xa7\x04\xa3\xe2\xac\xa1\xe8\x81\x5e\x49\xfb\xca\xb7\x97\xc8\x56\x52\x95\x38\xbe\x07\xd5\x16\x96\x32\x1f\x69\xb0\x9b\x5d\xc5\xa1\x5e\x5f\x0e\x4c\x22\xd2\x28\x37\xf6\x2e\xe4\xc8\xbc\x7f\x25\xa9\x48\x7b\x96\x2c\xc2\x0f\x13\x3f\xcb\x87\x0e\xd1\x25\xcc\xa5\x85\xd1\x81\xbd\x39\xf9\xdf\xa6\x61\xf1\x9b\xe7\x6d\xa7\xf6\x5f\x22\xfb\xbc\x80\x75\x2a\xeb\x39\xe8\xd5\x9e\xd9\x6e\x14\xf5\x95\xd0\x49\x29\x40\x2b\x50\x29\xc6\x0c\xee\x37\xc0\x21\x7b\xc5\x31\xd8\x0d\xb3\x41\xda\xce\x3c\xce\x76\xe6\x43\xaa\xc5\x38\x87\x47\x3e\xdc\x6e\x19\xcb\x39\xfe\xcf\x6a\xf4\x24\xa2\x06\x63\x93\xd1\xc3\x3f\xc7\xb9\x36\x76\xd7\xe6\x10\x5b\x9b\xfc\x96\x7d\x1e\x29\xaf\xdc\x4c\xf1\x5b\xca\xfa\x09\xc2\x95\xa6\xf9\xde\xee\x33\x1a\xb3\xb0\xd4\x93\x12\x6e\x2b\x2f\xff\xb4\x2a\x6b\x68\xe7\x9e\x13\x8d\xb5\x50\x82\x72\x62\xe4\x87\xa8\x3f\x37\xf0\x1d\xd7\x92\x2b\xe7\x5e\x92\xfc\xf5\xd9\xd4\x80\x3b\x3a\xc2\xf3\x5d\xa2\x10\xfb\x38\xb2\x63\xb0\xff\xb6\xc2\x70\x8d\x4b\x55\xb7\x57\xaf\x52\x07\x7a\x7e\x31\x84\xd0\x1e\x82\xf6\x4d\x32\xcc\xe4\xfd\xee\x0f\x8d\x4e\x36\x4b\xcf\xb9\x58\xeb\xbf\xdb\xb6\x22\xb3\x8b\x51\xe9\x30\x27\x1c\x7b\x1b\x70\xaa\x9d\x4b\xb3\xaa\x4b\x99\x7c\x52\x14\x4d\x3a\xa6\x21\x62\x57\x3a\x3a\x1d\x9c\xe4\x6c\xdb\xee\xb8\x44\x9f\x12\x25\xc4\x49\x63\x1e\x88\x97\x52\x1c\xd0\xf6\x37\xb7\x21\xa1\x25\x2b\x8a\x10\xab\x0b\xe8\x70\xaf\xbc\xd8\x9d\x58\xb2\xeb\xb6\x32\x11\x95\x0c\xad\x7a\xb8\x2c\x81\x95\x02\x6b\x50\xea\x8b\x77\xb9\xe9\x0e\xd5\x59\xaf\x44\x84\x30\x88\x51\xa3\xa1\x56\x71\x68\x53\xa8\xac\x4e\xcb\x8c\x5c\xc7\xd9\x35\xb0\xf4\x66\x12\x41\x43\xb1\x17\x7f\x05\xd0\x8b\x97\xd1\xad\x54\x2e\xd2\xc2\x46\x5a\xf1\x85\xe7\xdb\x42\xb6\x9c\xb8\x02\xa7\x17\x94\xa3\x13\x98\x83\x02\x96\x70\xc9\x56\x74\x2a\xaa\xd7\x90\x7a\x71\xd9\x59\x85\xfc\x1d\x45\xb6\x59\x97\xb4\xec\x6c\xe8\x25\x5d\xe9\x59\x27\x0a\xfa\x7d\xe9\x0f\x29\x29\xde\x63\xf9\xb1\x72\x11\xd7\xf1\xae\x82\x0a\xda\x9c\xe3\xe4\x86\x49\x17\x9d\x60\xb0\x14\x94\x93\x48\x1f\x01\xd4\x59\xdb\x7d\xad\x05\x26\xb5\xbd\x9f\x4b\x33\x80\xd2\x5b\xa2\xc5\x02\xba\x8f\xa3\xc4\xd4\x13\x1b\x46\x62\xad\xde\xfb\x41\x82\x7f\x75\x9f\xa7\x1d\x44\x7d\x5f\x02\x92\x45\xf4\x8c\x62\x2e\xb7\xc6\x8c\x8e\x71\x08\x1f\x7f\x78\x9d\xe7\xa2\x83\xd2\xed\xa8\x3a\x7d\x17\x22\xa0\x5f\xb7\x2e\x17\x60\xc2\x40\x40\xc4\xd8\x34\xde\xf5\xdf\x5f\x74\x2e\x02\xb3\x04\x51\xc8\x93\xbc\xf7\xd7\x71\xdb\x78\x4c\xbb\xda\xec\x87\x6d\x8a\xc8\x67\x43\xb5\x29\xa2\x92\x00\x7a\xc7\x53\xc9\x9a\x57\x99\xcc\x32\x4f\xe5\xeb\xb5\x44\x8a\xb5\x54\xb1\x0d\x41\x36\x97\x4a\x12\x54\x2d\x25\xc6\x14\x7c\x67\xc5\xd2\x33\x6c\x9d\xb7\x5c\xba\x2f\xd6\x08\xcd\x43\xab\x95\xbe\xac\xd0\x43\xa1\x34\x9c\xef\xa8\x28\xe2\x3b\x5f\x0b\x6e\x0e\x29\x51\xf3\x35\x3b\xb9\x2b\xfd\x1f\x0a\x49\xc3\x3f\xb3\xcf\x37\x99\xa0\xb5\x43\x19\x8a\xd5\xd0\x3d\x26\x3c\x1a\x06\xc3\x5a\x26\xad\xe1\x51\x84\x91\xc8\xc1\xd2\x7a\x2d\xb0\x33\x80\x89\x32\xcd\x1c\x47\xb5\xa1\x26\x98\x5a\xcb\x8d\x88\x83\x60\xee\xcc\xfe\xb3\xbf\x51\xb0\xd1\x89\xb4\x19\x04\x40\x40\x4d\x12\xfb\xa6\x5d\x0a\x7a\x14\xc6\x20\xc5\x55\xf8\x22"}, -{{0x51,0x4e,0x07,0x0b,0x01,0x90,0xd1,0x8c,0xbe,0x98,0x1a,0x5a,0x15,0x1e,0x77,0x53,0x39,0x8a,0x27,0x2b,0xcf,0x01,0x48,0x13,0xad,0x37,0x97,0x22,0xc3,0x6e,0x13,0x3d,},{0x6f,0xbd,0xe0,0x47,0x4c,0xc4,0x81,0x0e,0xff,0xa5,0x0a,0x07,0x82,0x0c,0x96,0x5a,0xa0,0x03,0x95,0xff,0x3a,0x5b,0x3e,0x2e,0xdd,0x7d,0x35,0x6b,0x7d,0x6a,0xef,0x2b,},{0xb6,0xc3,0x55,0xc9,0x58,0xb5,0xba,0xa7,0xeb,0xe9,0x77,0xa9,0x3f,0xcf,0x53,0x95,0x89,0xa3,0x66,0xd4,0x01,0x60,0xe4,0xe0,0x31,0xb8,0x8a,0xb9,0x64,0x02,0xc7,0xbd,0x57,0x7f,0xf6,0x35,0xfc,0x07,0x78,0x24,0x23,0x59,0x8d,0xca,0x43,0x66,0x81,0x24,0xa8,0xb2,0x87,0x51,0x0e,0x2c,0xfd,0x07,0xa1,0xe8,0xf6,0x19,0xf6,0xc8,0x54,0x0a,},"\x83\x14\x55\x76\x2a\x5d\x80\x09\x7b\xb2\x84\x50\x42\xf4\xc8\x76\xe7\x10\x85\x35\xbe\xd6\x83\xe8\xc4\x46\x19\xd0\x81\x54\xa2\x29\x44\x4b\x10\x1e\x3e\xd7\xc0\x15\x07\xe8\x70\x94\x14\x46\xaf\x97\x8c\x0f\x53\x41\xd1\xac\x1d\xd1\x5b\x14\xe8\x96\x67\x12\xdf\x19\xf5\x2f\xeb\x51\x03\xcf\x62\xb6\x63\x27\x56\x44\x6c\xc7\x54\xdf\x00\xa3\xf6\xdd\x71\x99\x68\xa2\xce\xf6\x6c\x3a\xdf\xb7\xd1\xfc\x49\x1f\xbb\xf3\xd5\x92\x94\xab\x34\x61\x9e\x17\x6d\xb0\xd4\x46\x15\x1e\x37\xea\xa3\xda\xf1\x72\x40\x6e\x98\x3d\x9d\x23\xa6\xb6\x9e\x92\x97\x60\x30\xf5\xac\x70\x40\xad\x51\x14\x12\x9f\xea\xf9\x7a\xf1\x5b\x22\x96\xfa\xe7\x04\x92\xdb\xbe\xb2\xb4\x82\x76\x87\xfb\x79\x87\x15\xc9\xbb\x2c\x32\x55\x7a\x81\xd8\x91\xb8\x97\x05\x29\x00\x70\x71\x59\x75\x1f\x07\xdb\x07\x4c\x77\xf0\x71\x96\x71\xf1\x76\x66\x89\x02\x9a\x3c\xdd\xf3\x9d\xf3\x48\x3c\xf2\xb0\x4f\x71\xc2\x5d\xe0\x5f\xc2\xd0\x2b\xb4\x8e\x53\x9e\xaf\x1a\x32\x16\x46\xcd\x80\xef\x2f\x0a\xc7\x03\xf4\x5e\x73\x89\x53\x08\x00\xe5\xd4\x17\xcc\xea\x8a\x5c\x08\x66\x82\xf0\x47\x45\xd5\x0b\x5d\xfc\x8f\x6e\xdc\x87\xa9\x5c\x7d\x20\x2a\x9c\xfd\x99\x87\x14\xb7\x46\x92\x0e\xbb\xe2\x33\x5b\xca\x1a\x01\x71\x76\x20\x16\xf5\xe4\xbd\xa8\x9c\x57\xd0\xed\xc6\x91\x0c\x6d\x22\xc8\xf9\x09\xda\x3d\xb1\x35\x2f\x0c\x8b\xd1\x8f\x3b\x5a\xac\x25\xf1\x93\xb8\x94\x70\xf9\x76\xbc\x4f\x1a\xff\xb3\xc6\x6b\xc5\x87\x6c\x6f\xe2\xac\x75\x08\x53\x3d\x97\xbb\xcf\x77\x11\x9d\x9a\xae\x19\x3f\x07\xe0\xb6\x4b\x46\x1c\x9c\x6c\x3b\x9d\x29\x3b\xd3\x7d\xe3\xd8\xe1\xab\x1e\x8d\x87\x2c\xd9\x4e\x6c\xf0\xeb\x68\x43\x9f\xdc\xd3\xb2\x5c\xe8\x48\x34\x60\xbd\x8b\x7c\xce\x88\x9f\xb7\x22\xb4\x36\x1e\x11\x8d\xa9\x83\xef\x4a\x9e\x45\xce\xbc\x0c\x1b\x82\x29\xea\x53\xe6\xf5\x55\x05\xf6\x44\xe0\x9a\xca\xa4\xc4\xb8\xcc\x64\x0b\x2c\xd2\xb3\x12\xe1\xc3\xa2\xc0\x26\x69\xe1\xf9\xc0\x63\x11\xc7\x8d\x36\x00\x09\xdb\x9e\x67\xc3\x9b\x49\xd1\xe5\xd7\x70\xc0\x1d\x28\x4b\x0a\x17\xa4\x1b\x4e\x7c\xa7\x45\xd6\x65\xec\x07\x50\x0e\x4d\x9f\xc8\xeb\xc1\xcc\x6a\xf5\x3a\x3f\xc7\x6b\x0c\x3f\x14\x31\xd4\x98\x43\xf2\x0e\x18\x27\x82\xc8\x2b\x3b\x5a\xae\x36\xfe\x20\xca\x64\x26\x18\x06\x8b\xe2\x33\xd4\xb5\xef\x9e\xae\xff\x40\x15\x36\xdc\x59\x3a\x2b\xc1\x83\x44\xf5\x5a\xc5\xd5\xfc\x7b\x3e\xb5\x06\xd1\x1c\xb3\x75\x33\x00\x63\xc6\x20\xc5\x33\x4d\x72\x3c\x7d\x1f\x04\x28\x16\xbc\x47\x85\xb3\x5a\xc0\xe6\xf1\x74\xf7\x36\x87\x8b\x7b\x49\x16\x58\xca\x67\xd8\xfc\xab\x53\x8f\xc6\xec\xd2\x77\xea\xd9\x0d\x95\x4b\x46\x0d\xa4\x25\x3a\x1c\x3a\x30\xb3\xd8\x92\x8f\x69\xac\x98\x76\xa2\x89\x19\x69\xfc\x2d\x06\xa6\x68\x99\x2b\x8e\x21\x15\xdf\xe5\x35\x8a\x71\x24\xba\x7c\xcf\x42\x1d\x80\x54\xea\x04\x34\x44\xcd\xeb\x40\xb7\x16\xdc\x7a\x36\x59\xa3\xca\x94\x34\x72\x93\x48\x90\x60\xe2\xcf\x67\x12\xa2\xa6\xc7\xb8\xad\x14\x67\x85\xfc\x40\xcc\xb9\xda\x28\x78\x30\xd0\x11\xd0\xd2\x4d\xf3\xe7\xaf\xbe\x97\x2d\x6f\x41\x7d\xe5\xcd\x75\xf2\x59\xea\x07\xca\xfd\xde\x20\x5f\xc0\xa3\x65\x13\x5c\x23\x2c\xbd\x7c\x1b\xc5\x39\xfa\x4b\x7e\x1c\xce\x35\x18\x52\x37\xc2\x3f\x80\xae\x97\xc1\x86\xd0\xd3\xb1\x05\x03\xd5\x98\x4a\x20\xec\x41\xc3\xcd\x04\x2c\x28\xa4\xc3\x1f\x95\x74\xb0\x6a\x87\x2b\xf9\x59\xab\x0a\xdd\x1f\x5d\xee\x14\xa1\xe7\x41\xef\x23\x8d\xfc\xde\xc0\x85\xaa\x08\x8d\xcf\x39\xa3\x6d\xda\x8f\x2a\x85\xed\x0d\x36\x2c\xcb\x00\x5d\x02\xe5\xac\xcc\x09\x2a\x37\x6d\xc1\x1a\x56\x61\x70\xd5\x83\xdb\x35\xf1\xde\x0b\xe3\xf1\x59\x08\x59\x6e\x9b\x78\x1a\xc8\x1b\xe0\x7b\x9b\xd2\xaf\x46\xc5\x6f\xb4\xd9\xd8\x42\x76\x01\x1e\x46\x18\xb7\xf7\x6f\x96\x79\x4c\xd0\xfd\x57\xed\x41\x4b\x63"}, -{{0xbc,0x79,0x0a,0x73,0x85,0xdd,0x1d,0xdd,0xc7,0x62,0xe3,0xb2,0x02,0x21,0xdc,0x07,0x8b,0x6c,0x3d,0xa8,0x98,0x6d,0x41,0x80,0x94,0x07,0x27,0x25,0x7c,0xfd,0xcd,0xf1,},{0xc9,0x26,0x46,0x26,0xf6,0x8f,0xed,0xb5,0xb3,0x9c,0x28,0xf0,0x30,0x45,0x3b,0x54,0xd0,0xd5,0x1a,0x98,0xb1,0x77,0x21,0xf2,0x61,0x1d,0x7f,0x27,0x7e,0xf4,0x8b,0x81,},{0x6d,0x6b,0xd6,0x5f,0x37,0x26,0x79,0xfe,0x9d,0x94,0x5f,0xf5,0x65,0x16,0x33,0x3e,0xce,0x0b,0x7a,0x25,0xb1,0x5a,0xd2,0x48,0x73,0x81,0x67,0x0e,0x53,0x6f,0x52,0x46,0x77,0x5e,0xb3,0x9a,0x11,0x4d,0xb2,0xb9,0xcd,0x50,0xf3,0x12,0xb3,0x60,0xd9,0xd0,0xbe,0xa2,0x95,0xdc,0x37,0xb8,0x17,0xb3,0x32,0x89,0x0a,0xdb,0x65,0xe4,0xc4,0x01,},"\x14\x3d\xd7\xbf\xbf\xf2\xad\xc7\x1f\x5d\x12\x3d\x47\x4e\xa0\x69\xdf\x14\xae\x92\x3e\xd9\xbf\x8f\x98\x91\xe6\x0b\xae\x43\xf0\xc9\xf5\x55\x37\xac\x9d\x1a\xe5\x23\xce\x4e\xcf\xd3\x3b\x20\xae\x44\x5e\x9c\x42\x63\x72\x05\x0f\xa5\x21\x7c\x1e\x4f\xb0\x13\x53\xeb\xf2\xe3\x29\x04\xef\x7e\xef\xcf\x72\xe8\x02\x3b\xae\x06\xbb\xb6\x40\xcf\x77\x7d\x5b\x0e\x11\x52\x7b\xc8\x35\x49\x3a\xd6\x98\x0a\x15\x7b\xb2\xd5\x0b\xe2\x33\x65\xe7\x2c\xbf\x0b\x3f\x20\x9e\xf0\xc4\x4a\x00\xb4\x1a\x62\x26\x24\x88\x09\x6c\xae\x5a\x69\x6b\x4d\x64\xcb\xad\x34\x50\x0d\x41\xfb\x4e\x4b\xc7\x0f\x8b\xf6\x21\x44\xd0\x1c\x22\x75\xd6\xd2\x9f\x5d\xe7\x5b\x17\x21\xd5\x04\x6b\x68\x29\x16\x44\x43\xeb\xfd\x9c\x17\x81\x31\x9d\x88\xf5\x40\x10\xed\xc2\x96\xab\xbe\xd0\x2b\x7d\xad\x9b\xa5\x85\xb5\x52\xe0\x00\x5d\xcc\xa4\x00\xbf\x4f\x45\x9e\xed\x7d\xb8\x6e\xa8\x61\x2b\xe9\xe9\x18\xdf\xd4\xe2\x70\x0c\x47\x10\x08\x32\x83\x62\x6f\xac\x75\x44\x17\xe0\x08\x7d\x26\xba\x14\x5d\xfc\x45\xb1\xc9\xbf\x7b\x4d\xd7\x0e\x6c\x50\x87\x47\xef\x80\x5c\x9a\x02\x42\x5a\xeb\xc6\x42\x1e\x0d\xeb\x6a\x79\xd8\x9a\xce\xee\xe0\x1e\xce\xcc\x9f\x3c\xa3\x65\x38\x38\x26\x58\x4c\x43\x0e\xbd\x39\xec\xf0\xa7\x28\x66\xae\x0a\xce\xca\x5a\xd4\xf0\x40\x5b\x67\x77\x9c\x04\xc5\xde\x03\x30\x61\x4d\xa3\x47\x0b\x80\x5d\x78\x7c\xe7\x9a\xc5\xa6\x96\xdd\x6f\x6b\x55\x39\xb1\xa6\x51\xb4\x24\xce\xfb\x19\x49\x1d\xa6\xe0\x88\x92\x23\xcc\x98\x39\x8b\x42\xc0\x04\x14\xff\x8d\x6c\x06\x27\xeb\x97\xcf\xf2\x0a\x8c\xbe\x7f\xcc\xb4\x1d\x81\x0f\xcf\xe8\x58\xca\x74\x75\x24\x7e\xf6\x28\xe8\x4a\x09\xd0\x12\xfe\x12\x23\x5b\x38\xc1\xcc\x9d\x82\xe2\xb6\x9d\x01\xd6\x21\x8c\xfd\x48\xe8\x5f\x26\xae\xad\xd1\x95\x40\x8c\xdd\x4c\x2f\x80\x6a\x89\x04\x1f\xd0\x31\x7f\xb1\xa7\xb6\x20\x9f\x90\x42\x70\xd3\x4e\x60\x61\x95\x04\x72\x88\xb0\xfb\x11\xa5\x72\x29\x38\xf6\x7c\x22\xb3\x13\xf7\xf7\x4b\x20\x25\xc7\x5b\xcd\x1e\xcc\x5a\x9a\xdd\x4a\x64\x0a\x41\xf2\x99\x6e\xb6\x6e\x5a\xf1\x96\x19\x8d\xb5\x8a\x3f\xb9\x93\x8f\x34\x9f\x92\x2a\x24\xd8\x6f\x4e\xd8\xa9\x6a\x09\xa1\x96\xc2\x4d\x6d\x01\xed\x76\xf3\x81\x6c\x05\xc4\xf2\x6b\xac\xa9\xb9\xd6\xdc\xc7\x9b\x58\x0d\xfb\x75\xd6\xc9\x05\xd4\x80\xda\xd7\x69\x51\x85\x4b\xda\x1c\xaa\x7f\x4a\x81\x95\x43\xae\xd0\x1a\xe9\x56\xbf\x30\x58\xfe\x8b\x3c\x7d\x5d\x72\x49\x62\xf1\xa6\xa8\x31\x43\xdd\xad\x27\x4f\xda\x3a\xd5\x78\xe9\x8a\xa9\x67\xc4\x10\xee\x57\x57\x5e\xf0\x1c\x02\x58\x56\x0f\x0a\x1f\xa4\xb7\x93\x27\x79\x6d\xe9\x94\x20\xcf\xd0\xa4\x15\x50\x63\x60\xf1\x24\x2c\xcc\x58\xa6\x88\x09\x27\x75\x0d\xbb\xff\x13\xd7\xc1\xb4\xed\x51\x9c\xda\x35\x72\x10\xf1\x2f\xb0\xd1\xc4\xd4\x8f\x04\x11\xbd\x7e\x05\x8c\xc4\xcb\x93\xd3\xc7\x75\x97\xe2\x65\x3f\xfa\x28\x2d\x3c\x2f\x12\x8a\xc3\x3a\x23\x7a\xf2\xfc\xbc\x9e\xf9\xc8\x11\xf3\x78\x14\xba\x2b\x0b\x85\x09\x3d\x0f\xd1\x8b\x8c\x6f\xb0\x9a\x43\xce\x52\x25\x4d\x23\xd5\x5f\x32\xe1\xd3\x24\x2a\xed\x1f\x23\xd9\xcf\x20\x4a\xa0\xdf\xd4\x4a\x34\x6f\xe0\x9e\x55\xa4\xa0\x6c\xf1\xbe\xf8\xbb\xf3\x7b\xa1\xf1\x59\x8a\x58\xae\xf8\x95\x01\xec\xba\xc0\x45\x35\x43\xe4\x80\xed\x0a\xdd\xe9\x0c\x84\x1d\x95\xeb\xd6\xeb\x23\xba\xa9\xf7\x0f\x83\xc1\x49\xea\xb3\x2d\x09\x13\xc7\x9b\x09\x93\xd0\xe1\xd3\x57\x4f\x0f\x54\x2e\x56\xa2\x06\x16\xcf\xe4\xa8\xbd\x7a\xae\xeb\xe0\xb0\x83\xdc\x2c\xe0\x14\x61\x78\xc0\x74\x82\xa0\x11\x29\xbc\x6f\xef\xdc\x81\x41\xc1\x38\x48\x94\xb6\x9c\xbe\x2f\x29\xda\x18\x8f\x7f\xd4\xac\x34\x1a\x2d\xf6\xfd\x90\xde\xe6\xa4\x46\xd2\x74\x63\x24\xc7\x5c\x1e\xf5\xb1\xac\xe1\x87\xd3\xbc\x16\xd7\x05\x59\x89\x29\x75\xd7\xe4\x71\x38\xf0\x40\x63\x85\xea"}, -{{0xdb,0x3a,0x44,0xdf,0x40,0xd2,0x55,0xa2,0x5c,0xf2,0x3f,0x53,0xc4,0x52,0x23,0xb7,0xd8,0xf1,0xf1,0xf1,0x11,0xba,0x07,0x40,0x6b,0x71,0xe1,0x84,0xa8,0xcd,0x06,0x12,},{0x6b,0x12,0xbd,0x95,0x80,0xae,0x20,0x7a,0x9b,0x0b,0xaa,0x82,0x87,0xb8,0xbb,0x86,0x66,0x93,0x73,0xee,0x5e,0x5a,0x62,0x5a,0xb4,0xa6,0xef,0x2d,0x08,0x71,0x25,0x97,},{0xcc,0x28,0xb5,0xef,0x4b,0x97,0x73,0x63,0x7f,0xae,0x7e,0x5f,0x08,0x4b,0x69,0x94,0xaa,0x35,0x98,0xf8,0xf4,0xa6,0x5d,0x0b,0xb2,0x01,0xd1,0x72,0xd8,0x61,0xa3,0x01,0x49,0xb3,0x33,0x8d,0x3c,0x3a,0xb7,0x5b,0x32,0xb2,0x55,0x95,0xcd,0x8b,0x28,0x96,0x30,0xc3,0x37,0x6a,0xcd,0x10,0xba,0x2a,0xb2,0x6b,0xc1,0xab,0xa9,0x00,0x84,0x0e,},"\x52\xdd\x8b\xa4\xff\xfa\x34\x4d\x1e\x08\x11\xd9\x67\x5c\x31\x3f\x9c\xc0\xe5\xa1\x38\x47\x86\x91\x98\x9d\x2b\x7f\x73\x89\x02\x50\x68\xfa\x35\xf7\x4f\x9a\xea\xf1\xe9\x56\x65\xec\xf8\xd5\x70\x7f\x75\xf6\x5f\x22\x56\xee\xa9\x33\x98\xbe\x59\xc0\xd5\x38\xf5\xe8\x58\x4b\xfb\xb3\xa2\x40\xf5\x01\x6d\x79\x27\x23\x4c\xb3\xea\xc3\x5b\x39\x1b\x8b\x53\xf2\x0e\xd8\xba\xe0\xba\x11\x08\x96\x94\xbf\xea\xde\x11\x07\x16\x56\xd4\xcf\x18\xef\x2d\x36\x81\x92\xe0\x4e\x08\xe3\x02\x4f\xc1\xd2\xfd\xa6\x31\x2a\xfc\xa6\x8d\x10\xc9\xc3\x36\xa0\xe3\x68\x50\xbe\x1a\x4f\x35\xb0\x33\xa8\x5a\x2a\x95\x49\xf2\x67\x3a\x99\x5f\x2a\x9a\xb4\xbd\x46\xc8\xfd\x2d\x83\x8e\x64\xf7\x61\x71\x34\x27\x32\x9c\x9a\xf5\xe4\x21\x1a\x22\xab\x20\x8a\xaa\xb8\x0e\x19\x4c\xd0\xf6\xa5\x02\xb3\x08\xfe\xd6\xc5\x83\x51\x78\x01\xa4\x8e\xd4\x33\x0e\x2f\xad\xdc\xd4\x18\x09\xc3\x91\x9b\x30\xe8\x4d\xb3\xc6\x87\x31\x03\x1e\x79\x85\x7d\xd9\xf9\x7f\xfd\x12\x54\x7d\xa7\x06\x67\x98\x07\x41\x51\xec\x88\xa5\xfa\x96\x3b\x9d\x9d\x83\xba\x2f\xee\x13\x58\x33\x95\x0e\xf7\xbc\x62\xb3\x40\x1e\xa1\x1b\xb3\x6f\x25\x56\x1b\xc0\x52\x2b\xb0\x2d\x8d\xad\x05\x43\xf6\x3d\x54\x7b\xe7\x7d\x0a\x4c\x9b\xf6\x5d\x42\xf3\xa2\x76\x14\x4d\x2e\x47\x4e\x29\x42\xf3\x79\x02\x21\xe2\x6f\xba\xe7\xca\x91\xef\xd8\x59\x21\x99\x08\x35\xfa\xfb\x6d\xc6\x74\x63\x5c\x96\x01\x82\x10\x38\xb5\x27\x11\x34\x3d\x1a\xa2\x5f\x1c\x46\xba\x4e\x3c\x6e\x71\x2b\xac\x19\xe5\x3e\xae\x30\xe5\x24\x6e\x4f\x04\xdd\xf2\xac\xdb\xb3\x41\x63\xc2\x43\x67\x76\x90\xbe\x0b\xf2\xe3\xfa\x16\x48\x70\xb5\xe6\xf5\x36\xb2\x2f\xb8\x9e\x5e\x8e\x1d\x87\xcd\xb3\x40\x44\x97\x7e\xd2\x83\x6e\x54\x4d\x7b\xa4\x93\xdd\x42\xa2\xb6\x49\xbc\xf3\x13\xc5\xb3\x9a\x1d\xbf\xff\x3e\x7f\x2a\x59\xad\xe8\x7d\x3e\x7b\x25\x8f\x58\xe5\x65\xfd\xba\x3e\x4d\x92\xb1\xed\xb8\xbf\xf5\x4d\xc4\x9d\x86\xc5\x3c\x03\x0c\xf5\x8b\x97\xef\x06\x6d\x24\x1b\x54\x05\x30\x21\x39\x05\x73\x9d\x8e\x1a\xa7\x2e\xd9\x0f\x68\x5d\x39\x58\xea\xa2\x42\xb0\xcb\xf7\xa2\xeb\x97\x6e\xe9\x6a\x63\xe6\x67\x86\x46\x41\x69\xa7\x42\xd4\x57\xe4\xd9\x11\x7c\x7d\x66\x42\x84\x45\xa4\x69\x30\xc2\x8b\xa7\xa2\x65\x82\x41\x80\x5e\xbe\x72\xc7\x8e\x02\x03\x5d\x26\x3a\x21\x1e\x59\x0b\x49\x0c\xdb\x84\x41\x50\x62\xee\xd1\x4f\x13\xb8\xa1\xa9\xe7\x7c\x8d\x7b\x75\x51\x5b\x18\xfb\x85\x38\x6e\x4a\x7e\x05\x39\x80\xd3\x0f\x48\x99\xe8\x38\x63\xbe\xe8\x75\x58\x58\x87\xc5\xf4\x8b\x51\x6c\xcb\x73\x1c\x4b\xca\xa3\xdf\x07\xd0\x47\x95\x81\x40\x96\xc7\x9d\x7c\x5f\xdc\x4d\xab\xf5\xe2\x6a\x4c\xa1\x83\x8e\x0e\x5d\x87\xdb\x71\x30\x9b\x81\xea\x7c\xe4\x61\xe5\xe4\x4c\x7a\xb2\xf1\x05\xad\x75\xc5\x43\xc1\xe9\x17\x9c\x36\xa5\xfa\x55\x5e\xc9\x22\xff\xed\x1b\x76\xd2\x58\x01\xdd\x74\xf8\x0c\xd0\xa6\xba\x7b\xc2\x0d\xb0\xad\x58\x0b\x7b\xbb\x9d\xdc\xfd\x93\xad\x1c\x5f\x20\xf3\xe2\x7c\x3e\xa3\xa1\xe7\x1e\xb7\x4f\xf5\xf9\x44\xcd\x3b\x98\xf6\xd0\x45\x29\x59\x30\x11\xc4\xae\xce\xf6\xdc\xaa\x60\xfb\x18\x36\x8c\xb1\x2b\x6e\x39\x1b\x3f\x5d\xf7\x65\xcb\xab\xff\x15\x89\x8c\x84\x79\x6f\xc2\xb5\x3f\xa4\x90\x0d\xad\x03\x4a\x13\xb0\xce\x14\x45\xad\xda\x4e\xf7\x19\xbe\x74\x14\x19\xe2\x31\xe9\x2f\x1f\x66\x7a\x32\x84\x2a\x42\xdb\x79\xbd\x7a\x01\x4a\x80\x9c\x81\x59\x6e\x82\x62\x73\xd1\x6f\xe5\xd4\x04\x58\x24\x2a\xe1\x0e\x12\xe6\x0b\x34\x89\x53\x0c\x66\x22\xb5\xbb\x44\x45\x4f\x29\x61\x6e\x47\xe9\xa2\x97\xce\x1c\xa0\x74\x13\x7f\xd9\xae\x13\xe3\xee\x8e\xdb\xcf\x78\xaf\x26\x54\x59\xdb\x1a\xf3\x42\xdc\x0b\x2f\xc8\x09\xbd\xa0\x15\xb5\xa8\x2b\x2b\x7c\x54\xef\xe4\xe5\xfc\x25\x2e\xb1\x3d\x66\xe8\x08\x93\x6f\x19\x10\xf4\xc4\x8b\xe0\xef\x7a"}, -{{0x77,0x96,0x4d,0xad,0x52,0xb5,0x79,0xb8,0x96,0x67,0x53,0xda,0x31,0x86,0xd1,0xc5,0xe9,0xd3,0x3d,0x33,0xa4,0xdb,0x38,0xbc,0x0d,0x7a,0x1a,0x6c,0x11,0x2c,0x13,0xc2,},{0xfc,0x25,0x12,0x5e,0x78,0x29,0xf6,0x42,0x34,0x37,0x5e,0x52,0xae,0x9f,0x77,0xae,0x10,0x13,0xf9,0x9d,0xf5,0xf9,0x96,0x5a,0xd2,0xaa,0x16,0x58,0x95,0x96,0xd0,0x91,},{0x3d,0x1b,0x4b,0x4e,0x82,0x0d,0x25,0x0b,0xe2,0xa8,0xfa,0x97,0x1e,0x59,0x9e,0x1e,0x98,0x97,0x75,0x28,0xb2,0xf9,0x30,0x18,0x96,0x81,0xa9,0x3b,0x05,0xe1,0xa7,0x06,0xfc,0x80,0xef,0xfa,0x94,0xe9,0x29,0xbc,0x43,0x92,0x16,0x56,0x89,0x73,0x88,0x28,0x8a,0x9b,0x29,0x27,0x1f,0x37,0xa1,0x4b,0xe0,0x14,0xb8,0x73,0xc6,0x8f,0xc9,0x04,},"\xc3\x39\xe7\x18\xa7\x57\xf3\xf3\xbd\x1b\xab\xdd\x2e\x00\xaa\xa5\xcd\x7f\xc9\x00\x5e\xe3\x4b\x6f\xdc\x09\xd7\x1f\xbd\x9c\x92\x89\xab\x1d\xd1\x4d\xba\x2c\xad\x58\xcb\x80\x51\x16\x77\x7b\xd8\x0c\x85\x96\x64\x33\xad\x46\xf9\xca\x6e\x54\xf1\x3d\xd3\xca\x7e\x56\xe4\x7f\xea\x41\xe5\x48\x8a\x45\xad\x53\xbc\x5d\x65\x74\x27\xe1\xd7\x93\x8f\x55\x19\xf1\xb0\x9f\x5b\xdd\x98\xaa\xe5\xac\x96\x43\xef\x78\xeb\xa4\x93\x49\x25\x33\x9a\x15\x5d\xc6\x68\x28\x57\x10\x02\x09\x7a\x11\xa5\xce\xe7\xb5\x1a\x44\x1b\x75\x6b\x0c\xe6\x5b\x77\x9a\xfe\x19\xda\x6a\x18\xef\xc1\x45\xf6\x09\x0c\xe7\x70\xde\x9e\x0e\x91\xf5\x43\x27\x0a\x09\x85\xea\xb4\x75\x29\x3c\xcf\xdd\x31\x41\xc4\x14\x2e\x47\x22\x23\x3b\x26\x74\x99\x44\x76\x41\x23\x5d\x72\x8b\xd7\x5c\xd1\xad\xc0\xdb\x14\x2f\x73\x31\xad\xdd\xf8\xc5\xee\xa3\xd5\x76\x40\x5d\x86\x99\x15\xb5\x60\xf9\x64\xe3\xe0\x00\x3c\x91\xf5\xe9\x6b\xff\xbe\xee\xc7\x3e\x51\x02\x4e\xf5\x2c\x55\xc6\xdc\xb5\x4d\x58\x20\x3e\x62\xf4\xdd\xb6\xe1\x37\xeb\x08\xe1\xbf\x13\x26\x01\x8a\xfd\x1a\x86\xca\xb6\xc8\x41\xe0\x66\x1c\xe0\xa1\xa7\xae\x96\x7f\x24\xc1\xa7\x7f\xc7\xca\x50\x5f\x72\xe5\xf7\x93\x6e\x39\xc6\xf4\x83\x7e\x25\x95\x19\x5a\x69\xcd\x67\x65\x10\xa7\x16\x1a\x4d\xc5\xe3\x18\xf3\xd4\xf3\xac\x0a\xf0\x3f\x8c\x4a\xe5\xbc\xe3\x93\x24\xe9\x73\x8a\xea\x49\xf0\x02\xd3\x2d\x16\xde\x23\x17\xe9\x5a\x9f\x32\xee\x60\x4e\x13\xdb\x80\x38\xb2\x64\xcf\xc1\x7a\xed\x29\xc9\xde\xbf\x81\x91\xde\x9e\x0e\xfc\x95\x1a\xd6\xd5\x48\x67\x06\x8c\xf5\x0a\x26\x9c\x37\xa2\x41\xf8\x52\x06\x78\x8d\x23\x14\x31\x77\xf6\x59\xcc\xa6\x6c\xfc\xe0\x3b\xc0\x50\x22\x55\x33\x7f\x16\xb3\xda\xd6\xf7\x91\x32\xab\xf8\x0f\xf1\x2b\x6d\x22\x81\xe6\x37\xeb\x6c\x71\xf7\x6e\x26\x33\xa1\x14\x56\x52\x40\xee\xd0\x0f\xab\xea\x9e\xd8\xde\x28\xc8\x32\x21\xf8\xcb\x48\x5f\x51\x2d\x90\x08\xbf\xc7\x4a\x36\x6d\x4c\x2b\x4e\xd1\x72\xd3\x67\xe0\x24\x7c\xb6\x50\x98\xc1\x10\x28\x2e\x83\x1d\xf8\xe9\xbd\x4f\xbd\x5f\x4d\xd2\xb7\xf2\x42\x0c\x23\xb8\x5a\x63\x7a\xa2\x26\x2c\x3c\xb8\x84\x05\xf7\x07\x30\xc9\xab\x4c\x9d\x0f\x22\x7e\xe4\xfa\x4e\xf9\x1e\xfe\x9a\x59\xb3\xe6\xd8\x43\xdb\x87\x9f\x56\x50\x05\x9e\x99\xf0\xe4\xa0\x38\x68\x38\xe6\xf9\x87\x6f\x67\xd5\x0f\x89\x83\x2d\xda\x5f\x30\xa9\xcb\xfd\x71\x01\x34\xf9\xb5\xb5\x46\x27\x49\x6a\xa3\xa4\x32\x12\xb0\x7f\x03\xdb\x11\xd3\xd4\xf8\x75\xd4\x1d\x1f\x4a\xc4\x59\x69\xdd\xef\x69\xf8\x1a\x06\xd2\xb0\xc6\x46\xc9\xcd\x93\x1c\xf2\x50\x2f\xef\x0d\xd3\x2a\xbb\xf0\x95\x1e\xd3\x03\xf5\x28\x48\x25\x93\x43\x97\xfc\x22\xe7\x86\x98\xd3\x5a\xd8\x1d\x82\x25\x6b\xf9\xe1\x54\x00\xa1\x09\x16\x23\xa9\x82\x6f\x1e\x57\x79\x23\x67\x41\x7e\xf0\x25\x86\xd6\x4e\x65\x0d\xa9\xac\xe2\xf1\x8a\xa0\xa1\x26\xd8\x67\xca\xc4\xb5\xd4\xc9\x1b\xf5\x20\x9e\x53\x59\x55\x63\x86\xf8\x27\x08\x3e\xb5\x3e\x8b\x47\x09\xff\xfa\xbe\x92\xc6\x1d\x78\xff\xb5\xda\xf1\x02\x74\xe2\x42\xa7\x00\x91\xf3\xf9\xb9\xd5\x96\xc1\x25\x8c\x9a\x63\x38\x4f\x4b\x05\xb0\x28\x66\x12\x22\x18\x1c\x0f\xca\x96\x5f\x0a\x2c\xb5\x6e\x4b\x55\x6d\x6f\xbf\xf7\x1b\x64\xd9\xb3\x58\xda\x31\xaa\x37\xc7\x4f\xf5\x96\x2f\xb8\xd9\x6a\x38\x3d\x04\x97\x24\xc1\x9e\x24\x9c\x9e\xdb\xb2\xa3\x75\xb2\x3c\xe3\x10\x4d\xa0\xec\x58\xd2\x63\x5b\xa0\x3b\x55\x42\x3f\xa2\xdb\x7e\xb3\x49\xa4\xfc\x58\xa1\xef\x54\x0e\xe9\xa0\x2c\x2e\x70\x3c\x68\xd7\xf8\x47\x5f\x43\x4d\xdd\x32\x00\xdb\x1f\x06\x74\x57\x91\xa3\xac\xc3\x16\x0d\xba\x50\xa3\x93\x44\x7f\xfe\xef\x6d\xc7\xb9\x8f\xb0\x66\x84\xcc\x90\xfd\x85\x20\x3d\x11\x9d\xcd\x81\x99\xe4\xd9\xa8\x9a\xe3\x46\x7a\xe4\xbb\x19\xfb\x71\xcf\x74\x70\x29\xc2\x40\x96\xf9\xa5\x0e"}, -{{0x5c,0xaf,0xd8,0x17,0xa4,0x41,0x0c,0xcb,0x27,0x12,0x17,0x23,0xef,0x32,0x07,0xc1,0x73,0x1a,0x08,0x61,0x94,0x5b,0xe9,0x62,0x71,0x4c,0x0e,0xd9,0x50,0x38,0xa1,0x95,},{0x4e,0xa0,0x86,0xbe,0x43,0xec,0xe1,0xc3,0x2d,0x08,0x05,0x9b,0xba,0xdc,0x9e,0x9a,0x2b,0x2f,0x4f,0x3f,0xe3,0x70,0xf1,0xf5,0xcc,0xd7,0xdb,0xde,0xc0,0xaa,0xf3,0x03,},{0x28,0x85,0x15,0xfa,0x72,0x59,0xf1,0xeb,0x58,0x7f,0xe8,0xa2,0xc4,0x03,0x43,0x4c,0x46,0xf8,0xd7,0xe7,0x5b,0x6d,0x22,0xbb,0x38,0x96,0x56,0x6c,0x01,0x7d,0x09,0xb6,0x98,0xc2,0xc8,0x07,0x79,0x9c,0x2f,0x65,0xf9,0xcd,0xb4,0xeb,0x58,0x15,0x1c,0xcf,0xc4,0x8d,0x10,0x80,0x61,0xa6,0xb3,0x14,0x84,0x32,0xb2,0xbf,0xc1,0xcd,0xab,0x05,},"\x50\xb2\xf0\x53\x42\x41\x80\x46\xd1\x6a\x30\xbe\x4f\xc6\x2b\x67\xda\xf6\xc1\x8d\x2a\x74\x24\x2b\x7c\xb5\x5b\xa9\x0a\xd2\x0b\x6c\xaf\xdd\x60\x15\x57\x37\xc2\x9d\xe4\x8a\xa5\xd7\x99\xfe\x54\x95\xfe\x59\xdf\x5a\x9b\x8c\x0a\x8e\x54\x18\x90\x47\x63\xfb\xad\x83\xea\x69\x86\x65\x1b\xac\x31\x11\x79\x39\xce\xf4\xe0\xc7\x99\x30\xd5\x2d\xfd\x7d\xb4\x3c\x31\xad\xda\xe3\xcf\x93\xe3\xef\xc5\xa9\x16\xef\xd0\xd6\x5f\xdc\x30\x90\x9f\xa3\x56\xcc\xbc\x52\x47\xd7\xaa\xa0\x67\x13\x1b\x6b\x48\x20\xfd\x02\xf8\xe3\x95\xf5\xa9\x70\x4c\x9b\xdd\x75\x60\xa6\x11\xd6\x25\x59\xa8\xdf\xe1\xd2\x85\x9c\x52\x48\x6c\xc1\x1e\xd3\x33\x19\x92\x48\x8f\x41\x75\x20\xd9\x20\xdc\x73\xa3\x2d\x4f\x08\x11\x00\x82\x50\x0f\x5a\x96\x2a\x30\x69\x32\xc6\xa7\x80\x29\x55\xce\xda\xd7\xab\xf5\x3b\x0f\x19\xfe\x47\x94\xa3\x1d\x6b\x85\x53\x80\x28\x43\x06\xcc\xff\x71\xa4\x00\x78\x59\xa2\x32\x8b\xb1\x90\x24\xc4\x3e\x10\xd7\x70\x64\xd8\x66\xd9\x62\x2d\x14\x2c\x27\x35\x4b\x84\xac\x3b\x4f\x82\x32\xf7\xa2\xf8\xaf\x64\x09\xd5\xcc\x75\x7a\x18\xef\x81\x3d\xfa\xf4\xb9\xbc\x04\x0c\xb0\x06\xd7\x7f\x14\x36\x41\xaa\x20\x36\xac\x7b\xc9\x28\xdc\x96\x58\x5d\x9e\x36\xc7\xbc\x9c\x56\x4d\x25\xf1\xc2\xcc\x0b\xea\xb9\xd5\xf2\x07\xe8\x4b\x21\x5f\x1e\x7a\xa6\xfc\x32\x82\x37\xb7\x9c\x39\x92\x3a\x4e\x09\xc7\xc7\x3d\xc6\xb2\x4b\x14\x16\x29\x4d\x79\x8a\x4e\xd5\xf7\x58\x33\x6d\x91\x5a\x87\x0a\x7d\x6b\x75\x92\xb5\xb8\x8a\xac\xe2\xdc\x5f\x26\x7b\xdb\x49\x11\x41\xcb\xba\xe2\xa6\x77\x40\x7c\xc0\x95\x5f\x96\x19\x62\x59\x93\x04\xba\x0b\x83\x96\x71\xa5\xc0\x00\xe9\x20\x10\x8a\x05\x29\x80\x87\xe4\x97\x70\xae\xee\xaa\xb3\x63\x27\x24\xcb\x0f\xc2\x28\x57\x96\xdc\x41\x48\x14\xfd\xa7\x8a\x54\xe6\x7f\x00\xa0\x2f\x77\xd3\xcc\xde\x1e\xd9\xd7\xb1\xde\xf1\x4e\xa1\xf6\x19\x10\xbd\xf3\x0a\x11\x96\xfc\x63\x51\xb6\x22\x54\xd6\x44\x5e\x6c\x90\x44\x5b\x16\xef\xaf\xe2\x89\xa2\x78\x4b\x92\xe4\x2b\x78\xa4\xa9\x00\xc3\x5f\x55\x63\x0b\xbb\x77\x62\xff\x9e\xb7\xfe\xf7\xd0\x4c\x90\xb9\x57\x1c\x4f\xc7\x60\xa4\x10\xdb\xfc\x25\x29\x91\xd0\xba\x27\xf2\xd4\x14\xfe\x64\xee\xfd\xff\x4a\xbc\x18\x81\x7c\x97\x06\xc6\x31\xbf\xa2\x03\x82\x1d\x3b\x92\xcb\x33\x8b\xaa\xf5\xd1\x23\x2b\x46\x26\x47\x95\x4d\x09\x02\x46\x2f\xb1\x69\x6e\x99\x1f\x07\xfa\x9c\x3d\xbc\xf2\x87\x29\x60\x83\x1b\x4d\xed\x92\xa4\x21\xcf\x21\xb7\x53\x16\x5f\xf3\x09\xef\xe2\xef\x54\x38\xc0\x12\x70\xd1\x0c\x6a\x03\xd3\x4f\x71\xeb\xc2\xda\xb1\xda\x90\xda\xa3\x57\x98\x4d\x24\x62\xbc\xb3\x5e\xe3\xde\x55\xc3\xa5\x5f\x8b\x98\xae\xc2\x11\x4f\x74\xc8\x43\x41\xa6\x41\x27\x86\x3c\x12\x0b\x5e\xca\xd9\xe3\x29\xa5\x75\x6a\xe4\xa2\x55\x5d\x84\x92\xcd\xa8\x35\x22\x5a\x8d\xeb\x3f\x9c\x15\x58\xf0\xd4\x25\xbc\x17\x2f\xf7\x64\x0c\xc7\x9d\x97\x80\x04\x16\xfd\x62\x94\xcc\xcc\x70\xcd\x1c\xf5\xb6\xa8\xe2\xaa\x07\x28\x9b\xd5\x22\xbf\x99\xdc\x96\xc3\x6b\xfe\xe8\x0e\x84\x6f\x5d\xd7\x46\xdd\x4c\x50\x03\xe4\xbf\x7d\x29\xef\xee\xa7\x50\x8a\x01\x61\x23\x68\x82\xc9\xa8\x2a\x56\xaa\x2c\x25\x74\x66\x96\x52\xc6\x30\x92\x3a\xb4\x70\xdd\xb9\x5d\x45\x6f\x7b\x8e\x8f\x07\x59\x9b\xa0\xd1\xd3\x8b\xc7\xf8\x17\x6e\x3f\xdf\x02\x09\xbd\x6f\x75\xd4\xcc\x11\x80\x3a\xfb\x18\x56\xcb\xc0\xe9\x1c\x73\x73\x0e\x4f\xb9\x8f\x3c\x94\x8a\x87\xd5\xa7\xed\xcc\x0a\x6a\x8a\xc8\x10\xea\x3e\xaa\x6e\x06\x3c\xec\x5f\x55\x66\xcd\x6d\xed\xc5\x37\xdb\x6d\x68\x6b\x80\x21\xf6\xea\x82\x5a\xd7\x47\x5e\xc7\xf1\xc5\xdb\xde\x45\xd3\xff\x4b\x5e\xe5\x1c\x0d\x04\xf1\xd7\x40\x18\xeb\x91\xe5\x04\x0d\x01\xc8\xb7\x1a\x4a\xab\xbd\xe6\x09\x4d\x4a\xfe\xcc\xb1\x8d\xfc\xde\xd7\x3e\xa7\x5e\x3b\x9f\x8c\xe1\x67\xdf\x62\x09\xae"}, -{{0xd5,0xca,0xc8,0x55,0x21,0xaf,0x78,0x1f,0x3d,0x5f,0x66,0x86,0x2a,0x04,0xb0,0x87,0xd0,0xcc,0xdc,0xac,0x92,0x6c,0xfe,0x9e,0x74,0x7b,0xe8,0xd5,0xc2,0x63,0x3f,0x78,},{0x10,0x0d,0xcc,0x53,0x03,0x9b,0xf0,0x5e,0xa0,0xa9,0xf5,0x88,0x82,0x12,0x69,0x3d,0x4f,0x9e,0x0e,0x75,0x25,0x95,0xbb,0xcd,0x02,0x06,0x10,0xe0,0xae,0x21,0x35,0x96,},{0x5d,0xc0,0x33,0x63,0x41,0x4e,0xea,0xc0,0x08,0x6f,0xb6,0xfe,0xba,0x44,0x21,0x7c,0xef,0x4c,0x52,0x0d,0xb6,0x19,0x26,0xdf,0x68,0x0c,0xa6,0x02,0xdc,0x11,0x00,0x3c,0xe6,0xaf,0xbf,0x3d,0x13,0xc8,0xc5,0xb0,0x52,0x73,0xd2,0x14,0x15,0xe6,0x7c,0x14,0xa2,0xee,0x5d,0x0b,0x1d,0x53,0x52,0x41,0x9a,0xb9,0xb3,0x9c,0x00,0x3a,0x51,0x0c,},"\xd5\xe7\xdd\x59\x49\x09\x37\x5a\x4b\xe0\x8e\x74\x82\x5d\x59\x8d\x53\x5b\xf4\x6e\xc0\x84\xde\x52\xb5\x73\x91\xc1\x27\xef\xf5\x22\x4a\xb2\xd1\x94\xdf\xb2\x66\x33\x47\x8d\x02\xfb\xda\x74\xd1\xdc\x58\x21\xf7\x91\xbf\x96\x2d\x8d\xad\x9e\x4e\xf2\x42\x24\x89\x19\x07\xb0\x18\x9c\xcc\xc8\xb1\x33\xd3\xaa\x20\x78\x92\x6d\xae\xf2\x89\x8c\x19\xc2\xe0\xbf\xe0\x20\x41\xa9\x04\xb9\xf0\x4b\xe7\xcb\x50\xae\xd0\xd9\x62\xd1\xad\xd2\x0b\x40\xa8\x8a\xb7\xab\xad\x62\x6c\xf4\xda\x0a\x78\xf9\xf5\x36\x85\x50\x1f\xdf\xa5\x85\x43\xdd\xf2\xea\x0e\xea\x69\xe7\xba\x16\x0f\x8a\x17\x7a\x25\xfc\x21\xe8\xa2\x9c\x66\x16\x33\xe3\x0e\x52\x3b\x0e\xc0\x1b\x2a\xee\xe2\xd4\x26\xe4\xae\xad\x45\x74\x88\x10\x8f\xe5\xf5\x69\xcf\x6e\x2f\xdb\x68\xc2\x8f\x2b\x30\x52\x82\x35\x77\xcd\x93\x4e\x7b\x06\x2c\x8a\x34\x24\xcd\x43\x67\xfb\x31\x5b\x74\x4c\xa3\x52\x55\xd7\xf1\xaf\x4e\xdc\x9b\xc9\xd8\x83\x71\x23\xd9\x79\x03\xb4\x3d\xf3\x67\xc7\xd4\x18\xc7\x93\x47\xff\xaf\xe7\xc7\xb1\x72\x4b\xba\x34\xed\xe8\xd3\x56\x8d\xb5\x05\x98\x3e\xad\x47\xf6\x2b\x56\xe3\x61\x8c\x11\xdb\x8f\xf0\xbf\x49\x2a\xc6\x75\x97\xd2\xf9\x6a\x6f\x42\x0f\xf9\x85\x34\x1b\x78\x6a\xd6\xce\xae\xdd\x10\x5d\x0d\x15\x63\xb2\xd5\x35\x43\xd7\x8e\x72\x56\x72\x5d\x20\x4e\x82\xed\x3a\x2e\x6a\x6e\x83\xdf\x61\xfc\x28\x2a\x62\xca\x06\xe6\x21\x74\xb5\x5b\xef\x40\xa0\xbd\xf8\xd2\x3d\x1c\x33\x0c\x71\x44\x14\x85\xee\x85\xe7\x0c\xed\x12\x1e\xac\x60\x7f\x58\x06\x78\x16\x3e\x4b\xd7\x5c\x67\x09\xff\x3b\x41\xde\x80\x59\x4b\x9e\x2f\x2a\xa2\x78\xfe\xfc\x21\xd7\x3e\xe3\xf7\x28\x54\xb9\x58\xd9\xa8\xf6\x3e\x3d\x70\xf7\xfe\xad\x8c\x3d\xca\x8e\x71\xbf\x4b\x9c\x2a\x36\xf2\x12\xb3\x2e\xb3\x29\x2e\x63\x55\x80\x38\x65\x59\xee\x1a\x11\xdf\x15\x29\x3a\x0c\x21\xcd\x73\x60\x86\x98\x46\xba\x5b\x7b\xa8\x5c\x99\x4f\x5b\x2f\x9c\xc5\x0e\x5e\xea\x8e\x4b\x36\x91\xd8\x86\x06\x2a\x18\xcf\xb1\x82\xf1\xe8\xb6\x11\xfe\x1b\xc2\x63\x15\x9c\xb8\xa0\x86\x78\x7c\x81\x1b\xea\x48\x12\x53\x00\x08\xc7\x0c\xa0\xc4\x7e\x64\xeb\x2f\xba\xd5\xb0\x27\x27\xa6\x6f\x2c\xdd\x6d\xde\x86\xf5\xd2\xa9\x64\x5a\x1e\x9a\xa6\x6e\xe0\xe1\x5b\x97\xf5\xfd\x22\x95\x96\xee\x02\xe6\x61\xca\xb9\xa5\x4e\xee\x1b\x81\xf9\x8f\xe2\x56\xed\x6c\x54\xfe\xaa\xa0\xba\x04\x7e\xea\x35\x33\x44\xf6\xe5\xc6\x2b\xe1\xe9\xd5\xc0\x9a\x2a\x69\x94\x11\x11\x0c\x56\xd1\x94\x9e\x90\xc0\x7b\x19\x38\xba\x95\x55\xac\x1b\xe8\x51\x1b\x51\x02\x18\xd7\xcd\xe7\xe1\xd7\x4a\x68\xaf\xb6\x42\xf8\x17\x15\xfe\x9e\x6c\x96\xc5\x03\x81\xae\x5a\x9d\xf3\x06\x51\x87\x85\xdc\x4d\xbc\x3a\x64\xf6\x0f\x24\x5c\x56\x4b\x80\x29\x51\x2f\x38\x1b\x56\xee\x78\x77\x03\x42\x68\x03\xc8\x0a\xb1\xc3\x11\xf4\x77\xb8\x91\x70\x8b\x59\xfa\x74\x8f\x32\xde\xbf\x54\xd2\x41\x37\x71\x97\x8c\x26\x5c\x9b\x87\x11\x4a\xdf\x25\xb8\x33\x7a\xa9\x3b\x0e\x63\x2a\x5b\x6e\xda\x47\x4b\xec\x16\x32\x81\x59\xfb\xed\x06\x7b\x00\xb8\x7a\xdd\x61\x96\x54\x92\xec\xcc\x6f\xd3\x46\x1c\x10\x00\xe4\x03\x7a\xb1\xe8\xac\x89\xa8\x52\x4f\x78\xae\x09\xd3\x08\xea\x6c\x94\xff\x88\x37\x32\xb7\x12\xee\xc0\xef\x07\x71\x8d\x33\xc0\x11\xb9\x39\x8f\x8c\xfe\xa7\x33\x07\x5a\xf3\x31\xfb\x3f\x97\xcd\xc1\xe8\xc9\x9f\x6a\x10\x72\x5a\x68\xc5\xc5\x8f\xdd\x8b\x0b\xaa\x50\x22\x7f\x34\xd7\x3d\x23\x90\x52\x03\x69\x8e\xaf\xf6\x26\x65\x4c\xe8\x3d\x86\x51\x08\x49\x9b\xe6\x86\x1f\x61\x41\xbf\xa6\x21\x9d\x7a\xb8\xb5\x84\x51\x91\x99\xf8\x80\xcf\xa1\xb2\x6d\x91\x94\xd3\x01\x71\x1c\x30\xfb\x44\x6d\x6e\xa7\x64\xa4\x31\x0f\x70\xe4\xb8\x59\xcf\x95\xfd\x44\xaa\xf8\xc1\xe2\x40\xe8\x0a\x71\x61\x1d\xbc\xf5\x2d\xa5\x8e\xdc\x32\x03\x11\xde\x38\x8d\x5d\x9d\x76\x9e\xb5\x9b\xe0\x93"}, -{{0x15,0x9a,0x9e,0xdd,0xea,0x5d,0xe6,0x34,0x03,0x98,0x7b,0x56,0x70,0xdb,0x6f,0xac,0x98,0xff,0xe5,0xec,0x3a,0x6c,0xf0,0x15,0x16,0xee,0x2c,0x70,0xce,0x3b,0x3b,0xe0,},{0xf6,0x1f,0x4a,0x04,0xa5,0xa1,0x2c,0xca,0xec,0xfa,0xf4,0x4c,0x1c,0x9c,0x18,0x88,0x47,0x5a,0x2c,0x89,0xfb,0x02,0xf2,0x6b,0xb8,0x1a,0xb5,0xf7,0x8f,0x4c,0xe3,0xa8,},{0x05,0x43,0x71,0x2c,0xef,0xa2,0x9a,0x22,0x0d,0x90,0xf8,0x1b,0xaa,0x4e,0x4c,0xf7,0x7a,0xc6,0x52,0x08,0xb2,0xd5,0xce,0x9f,0xd1,0x7c,0xe2,0x14,0xad,0x4a,0x93,0x7b,0x7f,0xc5,0xc7,0x86,0x41,0x3b,0x58,0x05,0x1c,0xca,0x3b,0xb8,0xb2,0xeb,0x55,0x65,0x7d,0x89,0x57,0x2b,0xc5,0x0e,0xa2,0xe5,0xec,0xdc,0x55,0x50,0x88,0x49,0x16,0x03,},"\xd1\x95\xe5\x90\x0d\xd3\x93\x14\x81\xbc\x01\x2e\x77\xbf\x06\x0a\xaf\x31\xcc\xcb\x0f\xe1\xa6\xc4\x0e\xaf\x28\x6a\x61\x66\xa1\x66\xb1\xea\x37\x05\x34\x26\x28\x4b\x92\x0c\x67\xfe\xe1\xd4\xb9\xd8\x6f\xb8\x61\xcc\x6e\xdd\x34\xe1\x0c\x52\x23\x37\x34\xd9\xcd\x92\xf5\xdb\xf4\x33\x51\x2e\xd2\x55\xac\x6b\x26\xe5\x6f\x5c\x66\x4b\xcc\xb2\x60\x69\x2c\xf4\x9d\x08\x36\x3e\xe9\x4e\x33\x6a\xcc\x48\x96\x00\xa6\xaa\x51\x2a\x04\x0f\x10\xeb\xf1\x8f\x7d\x2c\xbe\xe9\xca\xd1\x4c\x4f\xf8\x73\x77\xa3\x26\x34\x19\xd8\x29\x75\x29\x40\x1f\x15\x33\x7a\x4c\x4d\x23\x25\xed\x7d\xef\x76\x3a\x0d\x47\x9c\xaa\x40\x82\x66\x83\x4d\xa2\x42\xf3\xa1\x6b\x79\xa4\x58\x66\xb9\xd9\xd7\x1a\x48\x29\x31\x76\x74\xcf\xf7\xae\x6c\x8c\x58\x7b\xa4\xd4\x98\x0e\x81\x86\x13\xd3\xad\x82\x50\x7a\x7a\xb0\x32\xbb\xf9\x9c\x5e\x9b\x64\x03\x71\xbb\x41\xb9\x1e\x96\x5d\xc3\x1e\x8c\x7d\x4b\x3b\xaf\xd4\x95\x70\x52\x7f\xaa\xa8\x7a\xbb\xf6\x41\x6c\x47\xb1\xb1\xb0\x9d\x34\x01\x25\x31\x26\xcb\x24\x6a\xe4\x5a\xcf\x5f\x10\x0b\xb1\xf9\x2f\x11\xa5\xc6\xc9\x37\xe0\x58\x8d\x8b\x14\x6b\x3e\x4d\x3c\x7e\x5b\xf5\x74\x84\xe9\x84\xfe\x3a\xfc\x47\x72\xf2\x4e\xbf\x89\x4c\xdb\x39\x83\x7f\xbd\x46\x9a\x92\x1a\x96\xac\x5a\xf5\xe0\x70\xf6\xc9\x62\x4c\x58\x8e\x9d\x4f\xe6\xdd\xfe\xed\x1f\x8f\xe2\x0e\xb9\xc4\x60\xce\x6e\xe3\x8b\xf4\x71\xdd\x56\xdc\xf2\xe3\xee\x99\x8b\x8e\x7f\xdc\xf6\x12\xe7\x8a\x2e\x7c\x71\x73\xc0\x16\x09\x82\xbe\xde\xcc\x2c\x62\x1e\x5f\x66\x11\xb4\xef\x21\x02\xe3\x2e\x7c\x29\x80\x3a\x7e\x25\xfe\xe1\x51\x24\x31\x58\xa7\x6e\xe5\xd8\xc1\xbb\x2e\x7d\x8c\x88\x87\x1b\xa4\x33\xc5\xe5\x41\xc2\x60\x26\x93\xd9\x01\x10\xbe\x79\x5b\x52\x3a\x8f\xad\xb6\x05\xd8\xe3\xd7\xe4\x93\xfe\x24\x5d\x9c\xc5\x32\x0d\x32\xb8\x5d\x61\x35\xa4\x4b\x11\x68\x72\x94\x14\xc2\xca\x21\x56\x0f\xb4\xfe\xec\xde\xef\x0c\xf7\xd8\xe0\x71\x27\x4e\x88\x56\xc0\x04\x03\x3e\x80\x01\x3c\x73\xaf\x71\x77\xc3\x19\x78\x16\xa5\x03\x2d\x90\x59\xb1\xb6\xe4\x15\x2c\x38\x61\x92\xdd\x54\xb9\x0f\x9d\x30\x8b\xe9\x8e\xd7\xd0\xca\x9d\x12\xe8\xaa\xf6\xf9\xd8\x69\x38\x6a\xa9\xdb\xb0\x15\x93\xd3\x7e\x72\xf0\x90\x12\x4d\x34\x55\x29\x8e\x9b\x4c\x9e\xc3\xca\xe7\x3b\xb8\xee\x41\xeb\x63\xe3\x8c\x56\x13\x3e\xfd\xba\xf4\x49\xb8\x4e\x1e\x49\x1e\x49\x6f\x1c\x70\xa4\x4d\x06\x99\x86\xba\x88\x18\x42\x20\x69\x06\x1b\xb6\xeb\xcb\x7b\x20\x54\xe6\x3d\xf3\x81\xba\x03\xc6\xa7\x67\x4a\xbd\x61\x05\x0d\x69\x3d\x41\xbf\xe3\xca\x50\x46\xc6\x5f\xfb\x06\xa0\x74\x98\x09\xe5\x8d\x4c\x93\xa9\xff\x69\xed\x30\x95\x0b\xde\x1f\x99\x21\x6f\xff\x29\x9f\x22\xf1\x6b\x07\xc2\x54\xc2\x65\xae\x0b\x12\xe3\x13\x16\x3c\xcd\xf5\x03\x6d\x49\x05\x5f\x9a\x96\x67\xb0\xb7\x12\x92\xbc\x3b\x62\x60\xcb\x87\x56\x8f\xd2\x67\x17\x0b\xc9\x40\xc3\x33\x29\xd7\x29\xc9\xe3\x2d\x0f\x91\x80\xb1\x34\xbf\xf8\xae\x93\xb1\xbf\xeb\xfa\x38\x42\xfe\xf2\x0b\xc0\x4a\x29\x7b\x00\xa8\x4a\x0f\x42\x8d\x5f\x42\xfa\xb8\x61\x42\x99\x6d\x4a\xd9\xef\xab\xc4\x98\x52\xf8\x81\x2f\x3b\xfb\x5e\x57\x53\x9e\x21\x86\xeb\x8a\xe2\x29\x58\x0b\xc6\x04\x48\xac\xde\xf5\x72\x3c\x88\x15\x88\xb5\x37\x89\xf0\x5b\x91\xe0\x22\x89\x22\x32\x52\xd7\x53\xf7\x98\x13\x77\x9a\xce\x70\x5e\x04\xae\xd1\x52\x65\xd3\xbd\xf2\xa2\xe4\xb1\x56\x54\x77\x0a\x27\x58\x54\xe6\x4c\xf4\x43\x90\x60\x7a\x45\xd7\xbb\xa9\xaf\x3e\x1a\x2e\x28\x30\x67\xfc\xd6\xe6\x33\xaa\x2d\x24\x03\xbd\x81\xf7\xc7\x92\x76\x55\x10\xb5\x98\x41\x2f\x6b\xda\x07\xb2\xa9\x45\xb9\xf6\xd4\x6a\xb2\xf7\xc3\x20\x07\x5b\xc6\xb6\x0a\x80\xda\xa4\x4a\xf3\x91\xf4\xcd\x56\x21\x31\xbb\xdd\x40\x7d\x66\xf8\xdb\x12\x59\xbd\x76\xfa\x7e\x4d\x52\x64\xe1\x45\x54\x6c\x94\x2d\xfe\x90\x07"}, -{{0xed,0xa0,0xfe,0xac,0x0f,0x2a,0xfe,0x01,0x74,0x49,0x15,0x52,0x48,0x7f,0x39,0x62,0x17,0x13,0x32,0xb8,0x22,0xdc,0x3d,0xa4,0x26,0xf9,0xa5,0xf6,0x2b,0xef,0x7b,0x8d,},{0xef,0xf2,0x7c,0xb5,0x1f,0x4d,0x39,0xc2,0x42,0xf3,0x23,0x01,0x9a,0x12,0x34,0x81,0x8e,0xf2,0xe4,0xcd,0x1b,0xda,0xbc,0x0f,0x2d,0x8d,0x21,0x34,0x58,0xdc,0x47,0x1a,},{0x6c,0xbc,0x7e,0x6f,0x5e,0x12,0x14,0x5b,0x01,0x68,0x7a,0xd9,0xca,0x6b,0xf6,0xe4,0x7f,0x94,0x17,0xc2,0xce,0xfa,0xd3,0xfb,0xd6,0x8f,0xd6,0x5d,0xd7,0x4f,0xaa,0x97,0x50,0xcb,0xa9,0x92,0xde,0x4c,0xeb,0xcf,0xcd,0x35,0x80,0x8c,0xbb,0x3f,0xf1,0x2c,0x8d,0x93,0x07,0x99,0xaf,0x36,0xef,0xe7,0x97,0x6b,0xf2,0xfe,0xa7,0x9e,0x3e,0x0e,},"\x90\x11\x19\xda\x4e\xd1\x81\xaa\x9e\x11\x17\x0b\x20\x62\x6e\x00\xab\xf0\xb5\x48\x24\x5e\x3d\xeb\xf9\x4b\xf5\xed\x50\xae\xef\xe9\x42\xb4\x02\xcc\x99\x48\x94\x78\x52\xde\xdf\x2b\x53\x04\x01\x76\x65\x74\x9c\xd4\x7c\x21\xfc\x65\x2e\xe9\x95\x67\x9f\xf9\x31\xe3\x0e\x94\xaf\x98\xb4\xa9\x8f\xd4\x4e\x84\x9e\x98\x47\x0f\xe0\xa7\x6c\xe8\x0c\x61\xf8\x3f\xb4\xe8\x5b\xa5\x23\xee\x3f\xd2\x5d\xb0\x00\x05\x3b\x49\xd0\x93\x0e\x3b\x07\x9e\x86\x6e\x15\x3f\x7d\x86\x36\x7f\x23\xa4\xc4\xab\xc6\x3b\x30\x75\x46\x1e\x90\xe4\xfd\x89\x6d\xa0\x49\x2e\x27\xd7\x14\x94\x1e\x96\x7f\x52\xc9\x3f\xfa\xec\x44\x80\x3f\x57\x87\x7d\x86\x6e\xb5\xf8\xc5\x28\x17\x85\xaa\x48\x26\x79\x2e\x39\x64\xc6\x65\x90\x82\x1e\xea\x66\x75\x20\x74\x26\x40\x18\xa5\x71\xf5\xb0\x13\xb3\x8e\x15\x2c\x95\xc0\x24\x8a\xe6\x03\x68\x22\xa6\x7a\xfc\x9e\x02\x69\x45\x73\x15\x2b\x86\x4c\x56\xc2\xf7\x30\xa0\x82\x10\xf8\x5e\xc4\x6f\x98\x4a\x64\x3d\x51\x6a\x15\xfc\xfa\xa8\x48\x40\xf5\x12\x04\x7d\x11\x0e\x07\x18\xd2\x93\x95\x5f\x01\x58\x25\x7f\xba\x0d\x78\xeb\x7d\xf2\xf0\xb7\x7e\x6e\xeb\x76\xdb\x5e\x71\x70\x73\x10\xe8\x27\x36\x1c\xd4\xe1\x19\x74\x0e\x63\x92\x2d\xb4\x2c\x2c\xeb\x5e\xe1\x75\xd5\x0d\xec\xc7\xb7\x49\xfd\x23\x25\xbc\xe1\xe6\xa8\xf7\x10\xff\xcc\x1e\x1c\x9b\x33\xc3\x80\xe5\x2a\x64\xda\xa9\x58\x5f\xab\xe4\x06\xd9\xcf\x24\x48\x8f\xe2\x6f\x3a\x49\x5f\xb0\xab\x50\xe1\xe2\xba\xd8\x23\x81\xaa\x22\x43\x10\x99\xcc\x8a\x56\x98\x13\xd7\x9c\x9d\x78\x56\x9c\x0d\x95\xda\x9a\xad\x2b\xfb\x57\x75\x8d\x52\xa3\x75\x27\x52\xe0\x23\xd6\x51\xc9\xcb\x66\xa4\x12\xa5\xc8\x0f\x6b\xa5\x47\x93\xf7\xec\x87\xb4\xc5\x98\xfe\xd2\xce\x24\xab\xd7\x60\x87\x08\x89\x5c\x46\x72\x73\x59\xff\xec\xa6\xd6\xc6\x2e\x10\xa6\x78\xca\xa7\x18\xb4\xcd\x26\x32\x92\xcf\xef\x53\x5b\x9f\xbe\x27\x56\xb7\x39\x6d\x69\x7b\x31\x46\xc5\x51\xe6\xaa\xc1\xf5\xf1\xc2\x4b\xe9\xb6\x7a\x1e\x2a\x2a\xff\x74\x53\x01\xba\x6a\x21\x22\x17\xc5\x3d\x68\x16\x81\xbb\xb4\x01\xbf\x4a\x43\x65\x6f\x5d\x15\xcd\xe9\x69\xc1\x78\x00\x99\xa3\x32\x37\xeb\x19\xa3\xb8\x58\x5d\x6b\x5d\xea\x2f\xb5\x77\x84\x5f\x25\xee\x2a\x82\xcc\xf4\xb2\x85\x02\xf9\x0f\xe8\x0b\x8c\xdc\xdf\x2c\xcf\x93\xc4\x34\xc0\xe6\xaa\x5d\x87\x52\xa4\x43\x43\xc2\xb1\x8d\x20\xfe\x40\x04\xc4\x70\x38\x65\x93\x56\xf8\x7a\xbe\xd5\x44\x50\x34\xd8\xe2\xd3\xd1\x47\x68\xf5\xef\x31\x2c\xf1\x02\xa9\x88\x46\x83\xbc\xc0\xcd\x8a\x71\xe3\xec\x36\xfb\xb6\x33\x4a\x1b\xba\xed\x5d\x2b\xf1\x04\x16\xd8\x2b\xd6\x53\x04\x75\x38\x0a\xb6\xe2\x57\x7b\xbc\x69\xce\xbd\xa7\x5f\xaf\x02\xad\x82\x7b\x54\x51\x82\x13\x20\x6f\xd4\xcd\x66\xf2\x52\xb2\x34\xac\xa9\xee\xde\x7e\x3e\xeb\x81\x5d\xdc\xd8\xd5\x19\xc5\xd7\xf5\xd9\xd1\xfb\x9c\xa0\xfa\x44\x67\x99\x00\x95\xfa\x46\x22\x0c\x20\xa2\x07\x1d\xfc\xaa\xd5\xf0\x24\xda\xe3\x41\x6f\x7c\x49\x2d\x75\x74\x88\xc4\x9a\x2e\x4d\xf4\x83\xbc\x9b\x80\x09\x8e\x0d\x5d\x68\x3f\xac\xb8\xc9\x60\x82\x9d\xff\x09\xb3\x03\x36\x9d\x46\xcb\x57\x33\x1f\xf2\x17\x91\xee\x25\xd6\xbe\x7d\xec\x7e\xba\xf1\xb3\x24\x79\xa7\xf5\x14\xdc\x64\x71\x05\xc9\x44\xc3\x6f\x7d\xbf\x0a\x5b\x58\x91\x28\xdb\xaa\xa4\x21\x71\xd6\x42\xf2\x5a\x98\x1c\xe1\xf8\x37\x9f\x91\x69\x0b\x36\xaf\x77\x46\x48\xd5\x62\x4c\x08\xdb\xd0\xa9\x0f\x70\x87\x16\xdf\xab\x20\x24\xda\xe8\x65\xb9\xc4\x9a\xb2\x74\x73\x82\x6c\xd4\xa0\x10\xbf\xdb\x52\x01\x1d\x8c\x7c\xb3\xf4\x21\xca\x8c\xa3\xcd\x04\x86\x88\x91\x88\xe6\x7d\xf0\x0f\xb8\xc2\xa6\x43\xe7\xad\xb2\xf8\x27\x9f\x76\x3e\x5b\x9a\x81\xb6\xdf\xc3\xf7\x21\xfc\x5f\x68\x49\xf6\x67\x36\x78\x8c\xc5\x57\xc4\xeb\xc6\xfc\x68\xd6\xf6\xac\x77\xbe\xdd\xa8\xac\xb3\x62\x24\x3b\xda\x74\xe7\xb2"}, -{{0xec,0x05,0x9f,0xc6,0xbe,0x98,0x3c,0x27,0xec,0xa9,0x3d,0xdc,0xdc,0xb5,0x3a,0xf7,0x28,0x62,0x55,0xda,0x91,0xe2,0xa5,0x6a,0x68,0x4f,0x64,0x1e,0xc2,0xd0,0x9d,0x6e,},{0xff,0xc6,0xcb,0x75,0x1c,0x70,0x07,0x1b,0x65,0xec,0x2a,0xc6,0xb4,0x5f,0xd1,0xd5,0x5f,0xe8,0x36,0x96,0x5f,0x80,0xb3,0xe7,0xc7,0x84,0xfc,0x70,0x4a,0xcb,0xdf,0x69,},{0xa7,0xb8,0x8e,0x5a,0xbf,0x13,0x28,0x24,0xbd,0xde,0x77,0xc5,0xf8,0xdf,0x94,0xab,0x26,0x48,0x1f,0x6b,0xee,0x66,0x0e,0xa1,0x62,0x24,0x70,0x82,0xa2,0x50,0xd3,0x90,0xc7,0x1d,0x32,0x0a,0xd0,0x60,0xd8,0xef,0x34,0x1f,0xb6,0x9a,0x48,0x32,0x94,0xf0,0xd6,0xde,0x72,0x6f,0x0c,0x86,0x2f,0xa3,0x7e,0xa4,0xbc,0x6d,0xab,0x52,0x15,0x09,},"\xd1\xac\x63\x25\xa4\xe6\x90\xfa\x79\x53\x68\x83\xd5\xc2\x0e\xac\xb7\xd9\x64\xc0\x17\x8f\x74\x2c\x2b\x23\x72\x7d\xeb\x62\x64\x5a\xf7\xc8\x19\x22\xa0\xe7\x2e\x5e\x30\xb5\x83\x9a\x2e\xd5\xe5\x67\xec\x31\xce\x22\x41\x15\xb8\x2d\x2b\xf2\x51\xb7\x39\x3f\x01\xb0\xd0\x3a\x60\x2b\xc1\x20\xae\x62\xaf\x7f\xbc\x37\x9d\xfc\xf9\x5b\xbb\xba\x98\x4a\xab\xa3\x4f\xe2\x12\xac\x99\x00\x33\x28\xb8\x32\xc3\x53\x2d\x42\xee\xe1\xe1\x87\x4d\xc2\x2a\xd6\x7d\xb6\xc9\x1d\xbb\xfb\x2b\x45\x78\x5d\xbc\xd3\x99\x17\xd3\x6f\xb4\x8c\x1b\x5d\x6f\x38\xbd\xda\x5d\x28\xfb\xba\x64\x17\x55\x75\xaf\xea\x46\xc8\xed\x67\x57\xff\x30\x16\x4e\x0d\xf2\xe7\x21\x76\xe8\xb6\xc9\xdb\x5b\x5e\xf3\x90\xb7\x2f\x2d\x4d\x94\xe3\xb6\x6f\x0d\x44\xa7\xe0\xf0\x6e\x89\xde\xbc\xdf\x13\x63\xc0\xe7\x5d\x50\xdb\x5b\xb7\x01\x90\xd1\x9f\x66\xa3\x9c\x6f\x7d\xba\x70\xdf\xcd\x4a\x9f\xed\x02\xc2\xf1\xd0\x67\xe7\xc7\x88\xc5\x8f\xdb\x3e\x17\xa2\x37\x7c\xe4\x86\xec\x65\x82\xf3\xba\x99\x7b\xb5\xf7\x0c\xd6\x21\x00\x29\x56\xf5\x13\x1a\xa3\xa1\x61\x7c\x0c\xeb\xcc\xd9\x39\x1d\xe1\x30\x7c\x85\x97\x0a\x8b\xc1\x55\xf5\x19\x87\x26\x68\x45\x0c\x91\x48\x86\x89\xf5\x3c\x2c\x1a\x7e\xd5\x3f\x38\x8c\xb1\x3a\x2c\x38\x96\xfe\x5b\x7d\x3a\x0d\xc1\x68\x3f\x27\x66\x4c\x8b\xea\xea\x68\x0c\x8c\xc5\x4a\x90\xe4\xc6\xf9\x9f\xbf\x05\xf2\xc2\x2d\xf6\x0d\xe9\xae\xc8\x0c\x79\xb7\xd6\x62\x07\x05\x06\x67\xb4\x52\xd7\x85\x7f\x9a\x8c\xa7\x23\x28\x0d\xac\x79\x92\xe2\x07\x92\x67\xec\x3a\xd9\x11\x40\x46\x42\xc4\xe3\x26\xbf\xb9\x6b\x43\xc8\x94\x34\xba\x4b\xc7\x8c\x25\x2f\x4d\x4c\xa8\xd1\x3a\x88\x74\xc6\xfc\x82\x52\xea\x0b\x56\xc6\xbc\x78\x68\x47\xd4\x31\x83\x06\xe1\xc6\x52\xc4\x52\x58\x5e\xef\xd0\xbd\x9d\xd3\xc1\x48\xa7\x3b\xa8\x6e\xed\xea\x94\x5f\x01\x67\x13\xed\x7d\xf0\x85\xd0\x06\x66\x89\xe7\x92\xda\xcb\x2b\xfc\x1e\xb5\xc8\x24\x37\x2a\x26\xc5\xe9\x44\xaa\x74\x44\xac\x97\x73\xd4\xa1\x92\x1e\x49\xbd\xd4\xf8\xf6\xd7\x88\xc2\x63\xfe\xe0\x4c\x7b\x44\x4c\x53\x05\xed\xb6\x33\xe1\xff\xe0\xba\x4e\xa8\xda\x01\x1a\x62\xf2\xbb\xfe\xf4\xb8\x95\xad\x3f\x22\x4c\x3b\xa3\xbf\xf0\xc9\x5d\x75\x75\x0c\x9b\xcc\x66\xff\x8a\x20\xb6\xc2\x4b\xde\x75\x81\xa7\xec\x38\x66\xf8\x71\x6f\x78\x1f\x46\xdc\xad\x45\xa9\xeb\xcb\x6e\xd4\x69\x53\x36\x83\x97\x01\x17\x35\xd4\xb5\x2d\x00\xe8\xdb\x39\x79\x95\xdb\xdb\x3d\x4f\x42\x54\x68\x7f\x04\x68\x8a\x26\x8c\x30\x5b\x2b\x1f\x62\x2c\xf5\x1b\x17\x47\x75\xba\xd7\xf6\x67\x4a\xdc\x2e\x58\xe0\x5c\xce\x86\x5f\x12\xd7\x56\x9c\x8e\x9b\x35\xbc\xdf\x3c\xcc\xe6\x33\x0d\x08\xce\x53\x40\xa7\xc6\x30\xf2\x7a\x6c\x80\x86\xb5\x14\x6b\x29\x2f\xcb\xf5\x0f\xf6\xaa\xae\xf8\x84\x8a\x70\x7b\x25\x43\xc6\x18\xd1\x7b\xd9\x76\xc2\x40\xbc\x79\xd3\x3e\x00\x4e\x49\x53\x48\x29\x15\xe7\xe6\xef\x94\x96\x4b\xde\xa4\xe0\x2d\xd7\xc2\xf4\x75\x23\x5f\x2b\x99\xe4\x32\x29\xc9\xac\x3a\xba\x0d\xb5\x9a\xc2\xda\x03\xa9\xee\x4f\x37\xdb\xf2\x47\xa3\x3e\x6d\xfe\x5b\xe7\xc7\xf8\x25\x84\xf0\x4a\x46\xd4\x9f\x66\x21\xda\x31\xb9\x1a\xc3\xda\xa4\xd6\x8d\x48\xa5\x66\x59\xb4\x48\xc0\xed\x36\x5c\xb4\xaa\x0c\xfd\x90\x88\x53\xdf\x5b\xbf\xa8\x8e\x60\xe1\x0a\x5a\x00\x2c\x32\xab\x33\x33\xf2\xc3\x9b\xbf\x3e\xe0\x1a\x4a\xa6\x0d\x2d\x01\x42\x3e\x60\x97\xdc\x54\x30\x5f\x81\xa2\xd9\x3e\x2f\x6b\x4e\x8b\x35\x19\x71\xcb\xf2\x45\x7d\xc7\x6e\x1f\xb8\x92\x93\x38\x47\x98\xef\x28\x23\x4e\x9b\x1a\x47\xde\xdc\x23\x36\xf8\x6b\x8e\x13\xc4\xae\xf7\x90\xf5\xa1\x12\x39\xc7\x47\xd9\xd8\x65\xc9\xa1\x5a\xde\xb0\x71\x07\x02\x67\xe5\x34\x62\x56\x64\x8a\xdc\x0f\xa4\xdb\xdf\xd7\x87\xca\x14\x65\xfc\x24\x0a\x32\x4c\x3c\xaf\x29\x31\xda\x41\x49\x9e\x27\x5f\xd4\xb3\x5f\x6d\x08\xdb"}, -{{0xf1,0x6a,0xbd,0xbc,0xc0,0xbc,0xc6,0x1a,0x1a,0xee,0x3a,0xbd,0x87,0x67,0xab,0x52,0xe5,0xf7,0x99,0x99,0xbb,0x77,0xa3,0x97,0x6c,0xbc,0x82,0x67,0x0d,0xfd,0x2f,0x73,},{0x10,0xf4,0x51,0x71,0x9d,0xb0,0xfd,0x21,0x37,0x6e,0x22,0x8a,0x41,0xc3,0x03,0x5c,0x8c,0x2b,0xc4,0x2e,0x5a,0xaa,0x92,0x6f,0xe6,0x08,0x87,0x8d,0xbb,0x0d,0xc7,0xab,},{0x33,0xd8,0x05,0x29,0x08,0x69,0xb8,0xe0,0x4f,0xf0,0x89,0xfa,0xa2,0xd1,0xfa,0xb8,0x37,0x43,0xba,0xda,0x68,0xad,0xe5,0xb3,0x8a,0xe5,0xf0,0xcc,0x58,0xc3,0x37,0x4e,0xba,0x43,0x94,0x3c,0x1f,0x51,0x10,0x67,0x8e,0xb3,0x9b,0x46,0x58,0x61,0x18,0x22,0xa2,0x6d,0x35,0xff,0xe1,0x9e,0x9c,0xfc,0xb9,0xba,0x95,0x89,0xe4,0xec,0x31,0x05,},"\xbf\xac\xd7\xdd\x4e\xea\x46\x7d\xcc\xe4\x04\xf4\xa3\x52\x0a\x45\xb9\x4e\xba\xa6\x22\x19\x7d\x02\xd6\x15\x29\xd2\xb3\xbf\x27\x3c\x4e\xe1\xfb\x95\xa1\x80\xc8\xf8\x7d\xe1\x90\xa2\xe5\xea\x70\xb8\x4a\xe1\xeb\x6f\xd4\x44\x7d\x8a\x3a\x8d\xed\x10\xf6\xed\xe2\x4f\x0e\xb9\x2b\xd3\x0b\xc6\x5d\x48\x71\xe8\xf5\xda\x08\xcb\xe8\xcd\x3c\x0a\xc6\x4f\xd5\xa5\x7a\x6b\x06\x4a\x89\xd5\x15\x9b\x42\xf8\xb3\xe5\xa1\x83\x8c\x9c\xb1\x9d\x88\x10\x6c\x07\x73\xa2\x75\xcd\x2a\x1d\x60\x99\x30\xbf\x6b\x30\xae\xca\x62\xb9\x7e\x31\x9b\xbf\xa9\x34\xf4\xd0\xa1\xe6\xac\x80\xba\xeb\xcb\xa2\xd8\xea\x4b\xed\x9c\xa8\x56\x2b\x4a\xcb\x56\x97\x9b\xf8\x85\x32\x4a\xc4\x0a\xb4\xa5\x0b\xfb\x9f\x34\x90\x49\xfc\x75\xa0\xe0\x3d\xe4\xcc\x43\xea\xe3\xc6\xa6\xcf\xfb\x5f\x6a\xe6\xc9\x45\x04\x41\x5e\x6c\x7e\xd3\x04\x5a\x93\x2f\x47\xfd\x20\xb9\xf3\x48\x3a\x77\xb6\xd4\x49\xd8\xdf\xd4\xa6\x38\xdb\xf5\x6f\x03\xf0\xf0\x31\x87\x90\x59\xb2\xfb\x49\x76\x79\x43\xf4\x6b\x38\x72\xe2\xde\x56\x7d\x5f\xef\x80\xb0\x29\x25\xe9\x86\x3e\x0f\x1d\x31\xa8\x0f\x4e\x64\x51\xc3\x25\x69\x4b\x80\xcf\x1f\x19\x18\xc6\xe4\x98\x87\x8e\xdc\x47\xc4\x53\x0c\xac\x46\x6f\x1a\x29\x4d\x55\xdf\x09\xaf\x4f\xdc\x80\x72\xad\xb1\xbf\x26\xca\x8c\x92\xf9\x12\xa2\xb9\xfe\xbc\x8b\x97\xb5\x8c\x1e\x9d\x32\xc7\x80\x32\x30\x52\x97\x2b\x6f\xbd\x53\x30\x4c\x05\x19\x3c\xae\xb6\x7c\x5b\xd3\xe6\x74\x79\x72\x5d\x29\x7d\xff\xb0\x68\x90\xab\xf8\xcd\x9e\x42\x45\x8e\x16\x8a\x61\x18\xf9\x05\xb1\xd5\x34\x86\x01\x6f\x85\xdc\xd9\x8d\xd3\x39\xe3\x46\x05\x33\xd0\xb8\xa4\x9f\xae\x6d\xc1\xa0\x71\x72\x5e\x6a\xe5\xf2\x94\x47\x9e\xe3\xbd\xca\xeb\x74\x06\x18\x41\xfb\x26\x08\xe8\x8a\x49\xfd\x0f\x38\x95\xb1\x8f\x85\xb9\x0f\x72\x41\xdd\x13\x87\x71\x00\x53\xfa\xa6\x2b\xae\x75\xe9\xae\x39\x36\x9c\x1c\x02\xde\x5d\x19\x24\x2e\xfa\x16\xe1\x1d\x44\xa4\xba\x57\x78\xce\x77\x22\xa9\x1c\xec\x0b\xc0\xa0\x8c\x06\x9b\xdf\xa1\x30\xd1\xc6\xc4\xb5\x6c\x6e\x93\x54\x24\x03\xcc\xf2\x76\x84\xde\xf5\x7d\xef\x26\xdf\x86\xce\xd5\x71\x28\x2d\xc9\x60\x97\x46\x18\xf0\xa7\x4a\x0c\xde\x35\xb6\x53\xcc\x6e\x77\x30\x43\x1b\x82\x5f\xfb\x9b\x8a\xaa\xb3\xc7\xa3\x97\xc9\x92\xbc\x2f\xa2\x32\x70\xfb\x11\xee\x43\x1a\xfd\x5f\x9a\x64\x44\x83\x01\x11\x73\x99\x3f\x19\x48\x5d\xd3\xcb\xdd\x18\x7b\xd3\xd9\x95\xeb\xf0\x03\x1b\x1b\x0d\xe4\xa8\xde\x9c\x14\xeb\x6f\x78\x0e\x36\xb8\x92\x57\x56\xb9\x79\x06\xa1\x96\x9d\x85\xe9\x67\xd8\x80\xe6\xe7\xdd\xa4\x2f\xd3\xc3\x00\x19\xf1\x1d\x70\x81\x07\x1e\xee\x66\x26\x42\x28\x36\xbb\xed\x27\xd4\x6d\xd0\xdf\x1f\xeb\x66\x10\xdc\x85\x9f\x51\x3c\x0b\xc6\x53\xd7\x02\x20\xfe\x04\x8d\x2e\x97\xc2\xe0\x6a\xf5\x30\xe1\x1b\xdc\x70\x29\xbc\xcc\x5c\x92\xed\xec\xef\x5e\x4a\x2e\x0b\xe2\xd2\x51\xf4\x41\x5d\xca\x3e\x55\xb3\xa8\x50\xf2\x63\x0b\x87\x9e\x4e\x03\x6c\xe8\x63\x3b\xf2\x09\x20\xb6\x80\x94\x21\x59\x29\xac\xcc\x7b\xe4\x0c\x57\x78\xbc\x55\x4e\x6e\xdd\x7e\x54\xc9\xe1\x45\xb2\xee\x07\xb6\x5d\x06\x1c\x11\xde\x0e\x83\xf3\x81\xce\x4f\x57\xc6\x48\x3f\x51\x06\x93\x63\x51\x10\x74\xc7\xa5\x77\x35\x3b\x45\xc6\xeb\x71\x19\x9d\xce\x50\x59\xfd\x2c\x46\x11\xb0\x54\x23\x8a\xaa\xdf\x2b\x6b\xa5\x34\xbf\xff\xc2\x72\x2a\xe3\xe3\x1f\xf7\x9a\xe2\xeb\xca\x99\xcc\x35\x07\xf8\xa0\x33\xcf\x4f\xea\x70\xc5\x2f\x7d\xb5\xde\x44\x2b\x42\xb8\xd4\x1e\x99\x01\x2e\x42\xca\x0e\x85\xa9\xfb\x6d\x4f\x16\x5b\x33\x0d\xe6\x38\x3c\x57\x26\xef\xca\x2f\xe9\x71\x34\x00\x02\xf5\x62\xdc\x6c\xb8\xf2\xfa\xf0\x66\x57\x25\xe0\x97\x79\x9d\x09\x60\x91\x86\x4d\x66\xa9\x50\xa5\x79\x09\x53\xee\x16\xb9\xea\x58\x20\x09\x21\x87\x08\xc4\xac\xcd\x81\x38\x13\x58\xa2\xc6\x89\xa0\x41\xd0\x2d\x78\x61\x21"}, -{{0xbe,0x79,0xd1,0xae,0xea,0x86,0xe8,0x6f,0x39,0x81,0x37,0xe6,0x2f,0xfd,0x79,0xe5,0x0e,0xff,0x9f,0x31,0x3f,0x25,0x19,0x2f,0x89,0xe5,0x2f,0x0b,0x4b,0xbd,0x5d,0x32,},{0x18,0x7d,0xac,0x85,0x5c,0xa4,0x42,0xfd,0x9a,0x3d,0xdc,0x32,0x89,0xc2,0x4e,0xb2,0xd2,0x6f,0x7a,0x40,0xfb,0x29,0xd8,0xe7,0x44,0x31,0xb2,0x50,0x22,0xc3,0xa0,0xcc,},{0x6d,0xab,0x59,0x3b,0xb1,0xd4,0x48,0xc9,0x74,0xa6,0x5c,0x6a,0x0b,0x6f,0xad,0x22,0xb4,0x73,0x26,0x32,0xd0,0x04,0x89,0x17,0x6e,0xf1,0x26,0xaa,0x59,0x01,0x09,0xe0,0xa7,0x23,0xa1,0x13,0x10,0x7b,0x53,0xe1,0x7d,0x69,0x0a,0x0d,0x40,0xb0,0xfa,0x33,0x6c,0xc8,0x7f,0xd5,0xfc,0xe8,0xf5,0x41,0xac,0xce,0xc6,0x7f,0x7d,0x1e,0xbc,0x06,},"\x6d\x63\x2a\x7d\x3c\x9b\xe5\x36\x49\xd0\xd1\xa5\xee\xdf\x51\x9a\x41\x3b\x13\xac\x64\xe9\xad\x85\x4d\xfa\x04\xf2\xe1\x73\x29\xd8\x22\xbe\x57\x3d\x9e\x35\xac\x06\x6f\x02\x22\x13\xa3\x44\x62\x0b\xba\x28\x9f\x53\x31\x69\x55\x84\xd1\x34\x3e\x81\x54\x05\xae\xab\xe3\x86\x1d\x63\xb3\xa5\xb9\x2b\x8c\xd8\xee\xed\x22\x80\x22\x2a\xbd\xe3\x0a\x1b\xcc\xd3\xf3\xe4\x11\xaa\xb9\x22\xfa\x1b\xaa\x09\x7a\xa5\xc7\x80\xd0\xea\xef\x94\xea\x10\xfe\x21\xf7\xd6\x39\xb7\x6d\x47\x88\xae\xb5\x92\x4a\x9d\x26\x2d\xcb\xc5\x68\x8a\x3e\x43\x54\x4b\xec\x08\x8c\xa2\xe0\xd0\x6d\x77\xa7\x1f\xb6\x41\xd5\x52\x26\x61\x44\x52\xb1\xe0\x80\x7a\x9f\xcd\x3c\xa6\x9b\xf7\xf2\x5d\x80\x41\x47\x0c\xeb\x7b\x21\xea\xd0\x3e\xc0\x37\xa1\x62\x9b\xd5\x00\xaa\x23\x3b\x59\xbe\x44\x97\x82\x10\xb6\xa3\x66\xf2\x23\xac\xfa\x07\x97\x95\x40\x07\xb0\x0e\xfb\x4f\xfa\xdb\x5f\xc9\x2b\xdb\x37\x86\x3e\x50\x2d\x7d\x70\x68\x10\x39\xed\xf3\x37\x70\xdf\x3d\x1d\xe3\x43\xdc\x35\xf2\x26\xd5\xe7\x39\x44\xba\x02\x55\xe2\xa8\x8e\xf6\xc4\x1e\x47\x2b\x21\x45\x67\xc2\x49\x59\x4a\x50\x87\x8b\x67\x31\xc1\xae\xb5\xb1\x0f\xa9\x1f\xa7\x6a\x37\xe1\xf9\xf1\xc0\x0f\xdb\xfe\x34\x85\xde\xd5\x4a\x00\x9a\xb6\x13\x39\x27\x11\x56\x68\xb5\x9f\x51\x15\x50\x8d\xa9\x37\x0f\x6b\xc9\x2a\x11\x85\xc0\xd5\xca\x01\xd2\x91\xe1\x8c\x54\xac\xfa\xca\x73\x8b\xd7\x19\x68\xa3\x42\xa0\xcb\xa6\x2e\x4b\xb1\x04\xa5\xbb\x37\x9f\xc8\x3e\xe1\x82\x0d\x1d\xb9\x80\x25\x3d\x6c\xb3\x83\xe9\x5a\xf1\x5f\x53\xc8\x5d\x17\x58\x90\xdd\xe5\xe4\xed\x03\xd2\xd0\x13\x5e\x3d\x60\xb1\x82\x93\xf5\xb5\x64\x1e\xf8\x3c\x6e\xce\x3d\x52\x59\x8f\xc6\x35\x36\x86\xe6\xf7\xb0\x9f\xde\xc1\xf6\xf1\x53\x67\x2d\x34\xb4\x89\xb4\x8a\x0d\xb9\xe4\x2c\xed\xa7\x17\x55\x48\x1c\x04\x70\x16\xc2\x25\x34\xe9\x0c\x6d\x20\x1e\xd7\x85\x96\x02\x63\x6e\xa7\x7a\xe8\xc6\x73\x4b\x7c\x4c\x5b\xd9\x95\x79\xc5\x08\x73\x1c\x72\x46\xa2\x95\x86\xe4\x06\xe1\xd9\x32\xf6\x71\x30\x71\xd4\xbe\xa6\x3d\xc5\xe2\xa3\x76\x1e\x16\x02\x4d\x2c\x32\x84\xf7\x09\xa1\xf2\xba\x08\x5e\xad\x32\x00\xc7\x04\x62\x75\xcb\x96\xb6\x1a\x60\xb5\xac\x55\x9b\xc4\x88\xbd\x10\x64\x67\xc3\xde\x50\xbf\x5d\x74\x0d\x05\xc9\xcd\x70\x1d\x65\xb7\xda\xea\x29\xe6\x4d\xd5\xa9\x7a\xdb\x6b\x5c\x82\xcf\x7f\x23\x01\x7a\xa7\xca\x1a\xc9\xa3\x9e\x58\x27\xeb\x47\xe2\x0d\x35\x9b\x67\xc7\xd4\xe1\xa8\xe3\xe2\x7c\x52\xd3\x3d\x93\x03\xa5\x92\x62\x34\x84\xd7\x97\xb4\x02\xcb\xb4\x58\xd1\xac\x2e\xa5\x3e\x1c\x4f\x7a\xbb\x70\xcc\x02\x95\x54\xa2\x34\x57\x4d\xef\x9b\xc3\xb0\xd3\x83\x5d\xc3\x14\x90\x2e\x25\xab\xb2\x2d\xfd\xed\xdc\x67\x9a\x3c\xc8\xf0\x73\x40\xb1\x5f\x57\x62\xf4\x40\x7f\x38\x03\x42\x55\x4e\xd0\xc6\x2f\x73\xb6\x18\x16\xea\x8c\x52\x94\x61\xe1\xbf\x0e\x9d\x1c\x2d\x5e\x4c\x57\x46\x33\x6b\xc0\xe1\x32\x87\x3c\xde\x0d\xc2\x15\x8b\x54\xfa\x1b\x67\x8a\x00\x6b\x4d\x95\xed\xa8\xa9\x55\x71\x42\x73\xb7\xcc\x5c\xf2\xad\xd9\x09\x4d\x46\xe4\x9a\xbc\x09\x6a\x45\xf4\x18\xe2\xed\xbe\x99\xdd\x85\x29\x11\x68\x80\x64\xdf\x7c\xf0\x61\xd0\x7a\xee\xf4\x27\x95\x69\x0f\x48\xc9\xba\x19\x56\x54\x75\xd5\x46\x8a\x9e\xf4\x5d\x7b\xf7\x5f\xd7\x11\x82\xdd\x6e\x64\x01\x38\xf1\x82\xa6\xa0\xc6\xcb\xbd\x00\xc4\x95\xc4\x38\x95\x30\xac\x8e\x67\x96\x0e\xb5\xc5\x76\x3f\x54\x84\xea\xb1\xc1\xab\x85\x01\x40\xda\x04\x2b\xa4\x7e\xd8\x52\x88\x00\xd4\x17\x87\xf0\x75\xfe\x0d\x85\x50\x1a\x7a\xb7\x66\x35\xd0\x34\x10\xd2\x86\xc0\xe1\x7d\xb4\x02\x3a\x76\x39\x74\x68\xcc\xb0\x91\xcc\x5a\xc1\xf6\x43\x45\x87\x91\x3e\xab\x92\x2b\x50\xca\x55\x67\x01\x6d\xde\xa3\x2f\xb5\x32\x55\xbe\x67\xf2\xdc\xf9\xff\xa8\x5d\x11\x7f\x1a\x65\x5f\xa7\x0d\xd3\xa5\x4c\xf9\x91\x53\x1f\x19\x13\x0e\xaa"}, -{{0x26,0x99,0x52,0x17,0x2c,0x3f,0xa9,0x76,0xde,0xfb,0xf4,0x0b,0xd6,0xed,0xd8,0xf1,0x5c,0xfd,0x4b,0xe1,0x0c,0x75,0x8e,0x37,0x41,0xd7,0x41,0x62,0xd8,0xea,0x22,0x9a,},{0x4a,0xea,0x57,0xc7,0x21,0xe3,0xdc,0xca,0x82,0x39,0xe9,0xad,0x9b,0x22,0xc1,0x9b,0xab,0x8d,0xf7,0x2c,0x88,0x79,0x3b,0x24,0xd8,0xdc,0x47,0xcf,0x97,0x40,0xfc,0xf8,},{0x3a,0xc8,0x0d,0x1e,0x8f,0x68,0xb4,0x05,0x8c,0x3a,0x04,0xda,0xd7,0x18,0x73,0x73,0x95,0x9f,0x26,0xa2,0x70,0x02,0x49,0x6f,0x8a,0xfa,0xac,0xcd,0x8b,0xea,0x09,0x01,0xc5,0x4c,0xab,0x87,0xb2,0xa2,0x30,0x2e,0x1f,0x36,0x25,0xc2,0xb0,0x6c,0x7e,0xbc,0xf3,0xce,0x96,0xde,0x3a,0xfd,0xf0,0x0f,0x51,0x94,0xa3,0x5e,0x05,0x52,0xc7,0x0e,},"\x7c\xcb\x6a\x05\x70\xc5\x33\x73\x7b\x9a\x53\x4a\x34\x1a\x7a\x96\xdc\x76\x52\x8b\x99\x7a\x9b\x48\xe6\xe0\xfd\xe1\x0f\x47\x4b\x27\xec\x98\x99\x12\xd1\x76\xca\xb7\x42\xd8\x9a\x84\x8b\x36\x66\xe9\x27\x7d\x69\x5b\x02\x2f\xd5\x3a\x9e\xb8\x9e\x88\xc7\x20\x39\x9e\x24\xed\x25\xdb\x9e\xb3\x5d\x6d\xa0\x09\xe9\xf0\x24\xef\x8e\x65\x51\x65\xbd\xef\x1c\x0d\x79\x7c\x74\xf0\x19\xcd\x59\x1a\x04\x42\xa1\x2d\x1c\xa8\x93\x83\x6c\xa2\x62\x8b\x33\xe8\x54\xf3\x42\x8e\xec\x4a\xa5\xed\x84\xf4\xbd\xd2\xee\xf8\xb6\xd2\x25\xca\xf9\x49\x6d\xf9\xed\xff\xd7\x35\xea\x54\xdb\x1b\xde\xa8\x83\xad\x5d\x47\xeb\x0b\xd4\xa6\x65\x3f\x0a\xb0\x37\xf0\x40\xa4\x15\x17\xa7\x74\x1f\x91\xe8\x2f\xdb\x6f\xda\x04\xf0\xdf\xa1\xbc\xf8\xb9\xb3\x7b\xf2\xbf\xbd\x87\x32\x7a\x63\x6f\x90\x7f\xdf\x96\x8d\x01\x89\xd1\xa1\x18\x09\xc4\x23\x0b\xa6\x9d\x5c\xbd\x84\xf5\x61\xbc\xac\x3a\xd0\x02\xe5\x58\xc5\xb9\xb0\x97\xa0\x19\x02\xf2\x9c\xe3\xf1\xec\x26\x41\x53\xd6\x68\xc7\x8b\x84\x51\x05\xb9\xcd\x2e\xf3\xc9\x43\x53\x1b\x75\xaa\x42\x8f\x17\x9e\x4b\x34\x18\xb1\xd5\xa4\xaa\x7a\xb1\x20\x3e\xfa\x49\x5c\x87\x69\x62\x8e\xb1\x06\x3a\x93\x7b\x73\xe4\xb5\xcd\x0c\xda\x33\xda\xb0\x1a\x50\xc6\x4f\xeb\xd9\x75\xc5\x7a\x1e\x84\x15\x08\xe8\x60\x60\x94\xd0\x82\x4f\xdd\x96\xcc\x6c\xfa\x18\xfa\x82\x09\xb3\x0f\x0a\x2a\x78\xea\xc9\xa7\x67\x17\x6f\x57\x3e\x78\xc0\x68\x80\x9b\x19\x9a\x69\xac\x6d\x33\x5d\x7c\x92\x09\x99\xc4\x0c\xba\xd8\x7c\xf4\xcc\x7c\xa5\xc6\x44\x29\x1d\x75\xad\x7a\x74\xbc\x1e\x63\x92\xd1\xce\x31\x1e\xcf\xd2\xeb\xc9\x16\xe3\x9e\xb6\xaa\x3e\x7d\x89\xfb\x80\x5a\x27\xa5\x5f\x17\x89\x12\xb1\x57\xbc\x01\xa0\x55\xf6\x7a\xef\xa7\x8e\x55\xc8\x06\xcb\xd9\xc0\x1b\xaf\x8e\xf9\x2c\xad\x22\x60\xb4\xbb\x14\xcf\xe6\x17\x82\xde\xe5\xc5\x99\x72\x50\x69\x41\xc4\x62\xa4\xda\x7e\xb8\x99\x53\x1c\xf9\x96\xbc\x98\xba\x36\x29\xef\xfe\x6f\xcd\x17\x06\xd1\xb4\xee\x4f\x2a\x14\xe9\x21\xbd\x40\x8f\x30\xe1\x2e\x73\xfb\x7a\xa8\x60\x53\x6b\x03\xe7\x7c\xa9\x37\x82\x32\x81\xa1\x64\x53\xfe\x82\x79\x35\x94\x32\x01\xe6\xec\x14\x3a\x67\xee\xfa\x4f\x94\xe9\xab\xf9\x4f\x7e\x3d\x41\xb7\x0a\x82\xbe\x69\xde\xd8\xa5\x30\x60\xc2\x30\x5f\x42\xf6\x2f\xe6\xa2\xf7\x04\xb6\x7a\x1e\x8f\xdd\xc7\xd9\x8b\xa7\xf3\x45\x71\x19\xb3\x11\xd4\x49\x66\x3e\xd9\xe3\x20\xd6\x18\xdc\x23\x68\xd4\x95\x08\x75\xb9\xc3\x8c\x5d\x8c\x03\x10\x4e\x2e\x32\xc4\x32\x5d\xed\xd2\xbc\x26\x7e\x2a\xcc\xb0\x11\x20\x18\xe9\xc5\xa8\x00\x7c\xca\xb2\xf6\xd7\xc7\x37\x79\x20\x02\xac\xb7\x30\xd7\x2e\x9f\x73\x08\x29\xeb\xc4\x2c\xa5\x64\xc1\xd9\x27\x1b\xf1\x86\x9c\x4d\x35\x83\x55\x89\xb7\x43\x1e\xf7\xa3\x1a\x07\x00\x60\xfe\x4a\x08\x9f\xb1\x1f\x2d\xd3\xdc\xe6\x5a\xe0\xfb\x45\xbc\x3a\x28\x60\x91\x7d\x93\x3b\xa2\xd0\x90\x56\x9e\xf5\xed\x43\xbc\x25\x32\xdb\x87\x9e\x0f\x1f\x22\x5e\xad\xcb\xef\x1c\x03\xd9\xed\x78\x29\x9e\x23\x3e\x4c\xf0\x7b\x06\x4a\x7b\xaa\xc3\x4c\x5a\x0c\x19\xfc\x3a\x55\x42\x08\x9f\x70\x16\x7b\xe2\xf8\x5b\x4a\x10\xe7\x78\x52\x52\x23\xbe\x8f\xfd\x5c\xff\x96\x48\xb1\x00\x5a\x09\x8b\x4b\x39\x24\x39\x8f\xb0\xbc\xab\xcc\x6e\xdf\x30\xc0\x61\xec\xe7\xae\xa3\x5f\xe9\x8a\x92\x03\xf8\x71\x13\x69\x53\x0f\xeb\x5e\x67\xbb\x2d\x4f\x59\xd9\xc8\xbc\x99\x38\x54\xdd\x47\x47\xcd\xe3\x99\xbd\x0e\x63\x74\x0c\x1c\xc8\x39\xad\x0f\x09\x8a\x38\xa8\x0b\xea\xdd\x64\x8e\x14\x36\xde\xee\x60\xe9\x31\xe6\x8f\x52\x97\x9c\xe4\x9f\x30\x1f\xe3\x9a\xfb\xb6\x15\x35\x20\x91\xc8\xb6\x58\x5f\xe8\x84\x47\xed\x6e\x59\xa0\x20\xb2\xbb\xe6\x6a\x94\x23\xae\x52\x28\xc2\x03\xbf\xd4\x84\x7b\x51\x81\xe2\xc3\xb4\xda\xd8\x3a\x6d\x4f\xa7\x69\x85\xee\xf7\x6a\xdd\xe3\xb3\x4e\xdb\xdd\x28\xd6\xa0\xb4\xa4\xee"}, -{{0xcc,0x31,0x38,0xe5,0x02,0xa5,0xff,0x6f,0x80,0xd2,0x46,0x36,0x6e,0x84,0xd6,0x5c,0x59,0xf1,0x2d,0x4f,0x49,0x63,0x97,0xe6,0xeb,0x99,0xb5,0x26,0x7b,0x8c,0xbe,0x2a,},{0x9e,0x2d,0x3e,0x88,0xaf,0x7b,0x52,0xdd,0xcf,0x00,0xe6,0xd0,0xc7,0x75,0x9c,0x12,0x38,0xb8,0xfb,0x3e,0xb1,0x44,0x21,0xfe,0x82,0xc3,0x48,0x33,0x43,0x78,0x35,0xbd,},{0xa2,0x70,0x0e,0x38,0x95,0xed,0x0c,0xc2,0xaa,0xf0,0x12,0xa4,0x0b,0xc7,0xbd,0x0b,0xd2,0x9d,0xd7,0x9c,0x69,0xc0,0xb4,0xa6,0xed,0xd0,0x53,0x0c,0xf3,0xe2,0x67,0xc0,0xf8,0x2d,0xd8,0x4e,0xda,0xf1,0x74,0x4d,0xc4,0x11,0xd6,0x2c,0x00,0x28,0x71,0x52,0x58,0x82,0x2d,0x7b,0x63,0xd3,0x97,0x05,0x61,0x2b,0x3f,0xad,0x4b,0x5e,0xfb,0x04,},"\x58\x5e\xcf\x2f\x09\xeb\x92\x3d\xf2\x0a\x85\x55\x64\x2a\x2b\xc0\xb6\x8c\x6a\x5f\xcf\xd6\xb8\x40\x1c\x4a\x0c\xba\xbb\x4c\x6e\x6a\x20\x67\x62\xb7\xa3\x9f\x2c\x54\x55\xd7\x80\x8e\xbf\xbe\xd5\x6d\x67\x60\xa4\x31\xc7\xd2\x0c\x2d\xc6\xef\x1b\x73\xca\xa3\xc4\x94\x88\xe3\x0b\x1c\xa2\x52\x0a\xd2\x0b\x26\xa1\x97\x00\x78\x0e\x5e\xf3\xce\x01\x44\x38\x8d\x84\x07\xb6\xa7\x0c\x1c\xda\x37\xdb\x7f\x12\x09\x1d\x89\x2f\x2e\x91\xad\x40\x78\xbb\x4d\xb1\x76\x2e\x46\x28\x5a\x7b\x66\x4b\x2a\xd3\xa3\x4d\x26\xd8\xa9\x4d\x64\x58\x7a\x84\x52\x77\x22\xea\x83\xcb\x8a\xa8\x89\x84\xe1\x48\x97\x43\xb4\x21\x4e\xa6\x04\x1a\xa1\x8e\x55\x20\x09\x54\xef\xc7\xed\xb3\x19\xdf\x94\x7e\xfb\xfc\x6c\x8d\x0f\xea\x48\xa1\x31\x61\x34\x65\xd8\xf4\xc4\x94\x98\xf2\x26\x91\x45\xc6\xda\xe5\x04\x78\x05\x25\x98\xe1\xca\x3b\xe0\xe3\x36\x11\x57\x1f\xa3\x84\x77\x1e\xee\x40\x2c\xc2\xb1\xd8\x48\x36\xc8\xf1\xad\x28\xf2\xad\x23\xde\xe9\xff\x1d\x7e\x1f\x25\x21\x63\x58\x74\x11\x5d\xef\x4d\x93\xe8\x9b\xe7\x61\x80\xbc\x55\xf7\x61\x14\x43\x60\xa8\xb2\x22\x89\x2d\x64\xd1\x57\xcc\xb5\xd8\xf4\x85\x5d\xca\x56\x70\x14\x95\xa0\xe1\x00\x2d\x34\x0a\x4a\x46\x15\x6b\x9b\x7f\xe0\x6b\x7c\x07\x59\xe0\xb6\xdf\x55\x9b\x69\x1e\xde\x78\xb5\x5a\xf6\x4e\x7c\x8d\xd9\x08\xb7\x88\xdd\x6b\xa3\x5a\x90\x2c\x81\xdc\xeb\x37\x88\xb6\x15\xde\x22\x5a\xfa\x58\xa8\x11\x81\xab\x24\xa7\x37\x05\xee\x83\x8b\x6e\x86\x3f\xe1\xbc\xc2\x6c\x1b\x94\x32\x39\x23\x0c\x27\xc6\xb3\x97\xb2\x3d\x13\xde\x6a\x02\xc9\x7f\x36\x45\xda\x91\xd4\x13\xf9\x16\x47\x3b\x01\x8a\x61\x59\x4b\x6f\x51\xce\xa4\x44\x57\xda\x1e\x3d\xbb\xba\x6d\xe1\x68\x66\x65\x7e\x92\xef\x02\x02\x71\x8a\x84\xad\x03\x33\xe8\x33\x6b\x05\x2b\x00\x47\x33\xe8\xe9\x5e\xc1\x3e\x5f\x91\xb3\x80\x6a\x98\xd3\xdb\x72\x9f\xb7\x35\xb8\x14\x7c\x4a\x98\x2a\x2d\x5b\x4e\xfa\xe9\xc0\x9d\x0a\x9b\xf8\x91\xcb\xbc\x3c\x8f\x53\x1e\x76\xe4\x04\x4e\xc9\x1f\x4d\x7c\x5c\xf7\x73\x10\xe2\xb2\xcd\xe2\xe0\x7c\xcf\x3e\x0a\x19\xdd\x6a\xe1\xb3\xfc\xb2\xdf\x42\x18\x6e\x9c\x72\x92\x2d\x2d\x4c\xe5\x1b\x30\x6e\x81\xb1\x6c\xfc\xf8\xf0\x0d\x51\x3f\xbd\x2c\x52\x39\xb4\x5a\xfc\x65\x4f\x6f\xe2\x1a\xcb\x7e\x8a\x0c\x9a\xa8\x7b\x0b\x60\x50\x74\xdf\x95\x76\xa6\xdd\xd9\x00\xac\xa5\x67\x61\x7c\xb7\x96\x56\xb3\xb5\xec\xb9\xff\x68\xb2\xf6\x24\x1e\xd0\xd0\x24\xac\x27\xaa\x6e\xb4\x86\xb6\x9f\xdc\x0a\x0d\xb9\x20\x96\xab\xf8\x60\x02\xde\xc7\xaf\xd8\x47\xa0\x06\xa3\xf6\x95\x5b\x49\x56\x90\x53\xbe\x9f\x1d\x0a\x49\xb7\x93\xa5\x41\x1e\x59\x16\xf4\x18\xec\xab\x95\x32\x43\x55\x3b\x66\xe6\xba\xdc\x4e\x90\x9b\xe0\xef\x5c\xc7\xc6\xd2\x71\x99\xec\x3f\x21\x42\x3b\xc4\x57\x73\xfb\x40\xb9\x7b\x61\x18\x5b\x57\x08\x0e\x8f\x0b\x89\xa3\xea\x57\xc8\x44\x4a\xb2\x7e\xcf\x70\x06\xa7\x66\x04\x7e\xef\xf5\x4d\x85\x56\xcf\xed\x23\xde\xf1\xda\x2c\xc8\xae\xbb\x48\xc9\x4e\x77\x9e\x82\x03\xae\x2c\x90\x2b\x51\xde\x0e\xde\x04\x56\xfb\x73\xfb\x4d\x5f\x51\x4a\x4c\xeb\xc4\x7f\xec\x3f\x94\x84\x69\xa5\x45\xc6\xbc\x57\xb4\x13\x8d\xb3\x4e\x7c\xc0\x06\xde\x26\xef\x50\x7b\x54\xd2\x81\x47\x56\x7a\x8c\x29\xac\x1e\xce\xf5\xbb\x84\xfb\x99\xac\xeb\x23\xa2\x02\x94\xd7\x4a\x85\xae\x36\xb3\x34\x50\x66\x8a\x5c\x26\x09\xd3\xa9\x39\x34\x58\x6f\xf9\x0c\x3b\x6d\x27\x32\x9e\xee\xf3\xa7\x54\xe9\xa9\xcb\xd5\x61\x7e\xf3\xb0\x93\x97\xbd\xc9\x71\x37\x07\x66\x58\x9a\x12\xd8\x90\x05\x0d\x16\x51\x45\x8b\x3f\xc5\x33\xc8\x43\xbf\xfd\xf9\x75\x4d\x93\x2c\x4e\xd7\x61\x1d\x4d\x27\xc3\x2a\x08\x75\x55\xb5\xea\xa3\x7a\xe9\x0c\x49\x79\xef\x54\x29\x9c\x42\x0a\xb5\xe2\x9a\xe2\x84\x5d\x4d\xcf\x21\x78\x92\x0a\x86\x51\x75\xfb\x9c\xc0\xe6\xb8\xc5\x24\xb1\xee\x49\x58\x05\xd5\x17\xbf\xe0"}, -{{0x5c,0x69,0x2c,0x68,0x11,0x98,0xb1,0x72,0xdf,0x2f,0xac,0x2a,0xec,0x3f,0xcf,0x70,0x15,0xc2,0xbb,0x68,0x30,0xf2,0xa9,0x8e,0x30,0xa3,0x96,0xb6,0x4a,0xf4,0x28,0x0e,},{0x33,0xb1,0x69,0xd4,0xca,0x27,0x10,0x40,0x92,0x6e,0xa8,0x78,0x35,0xe5,0x06,0x6f,0x9f,0x05,0x78,0x2f,0x08,0x7f,0xca,0x7a,0x55,0x6f,0x7b,0xf4,0xcb,0xa2,0xe8,0x86,},{0xad,0x8f,0x37,0x9c,0xaf,0x41,0xf7,0x2d,0xcc,0xad,0xc3,0xe9,0x15,0x35,0x7a,0xb0,0xcd,0x30,0x4e,0x10,0xf4,0x12,0x0e,0x0d,0xbb,0xfa,0xac,0x01,0xbf,0xfa,0xf2,0xbe,0x89,0x3f,0x70,0x07,0x2d,0xc9,0x64,0x06,0x91,0x81,0xbe,0xc1,0x7f,0xe0,0x25,0x10,0x55,0xb2,0x1e,0x23,0xde,0xe4,0x36,0x3b,0x27,0xef,0x1f,0xff,0x67,0xaa,0xfe,0x06,},"\xb1\x60\xee\x3a\x93\xcf\x6b\xc3\x45\x6e\x5b\xd0\x19\x7c\x09\xaa\x76\xc2\x25\x80\x52\xf9\xa3\x4d\xbc\x2e\xd5\x89\xf8\xdb\xe5\xff\x99\x69\xa6\x1c\xfe\x84\x6b\x2f\x67\x39\xdc\x7d\x4a\x14\x96\xe9\xad\x58\x60\x5b\x5a\x27\x58\xca\x07\x8c\x55\xa9\xfc\x1c\x4e\xeb\x54\x91\xa8\x4b\xfd\x46\x8a\x2c\xeb\x14\x1a\x77\x34\x93\xa9\xb3\xee\x82\x8b\x5d\xde\x9c\x00\xc2\x36\xff\x01\x56\xe4\xe2\xe4\x5f\xa0\x79\x31\xda\x68\xbb\xd2\x03\x0a\x88\x14\x05\xc4\xf7\x87\x28\x81\x3a\x5e\x04\x81\x24\x04\xc2\xa1\x9c\x9b\x87\xb1\xcf\xe9\xaf\x95\xe2\x73\xec\xf9\xc5\x18\xc5\x39\x35\xf8\x42\x56\x3b\x19\x2f\xae\x12\xa7\x3c\xef\x08\x5f\xe1\x9e\x89\x9e\x5b\xa0\x89\x79\xe3\x11\xfb\x28\x6f\xbf\xc7\xb2\x48\xaa\xbd\x40\xdc\x61\x61\x0e\x1d\x4f\xc9\x80\x6d\xd2\x12\x92\x39\x2d\xb2\xdb\x40\x42\x6c\x5d\x19\x6a\x48\x9c\x5d\xb7\x7e\x3e\x9c\xf0\xbd\x04\x1e\x3c\x23\xb5\xba\x1d\xb7\x81\xa1\x07\x90\xbe\x1f\xe0\x7a\x2b\x00\xca\x3a\xf8\x9c\xbd\x46\xef\xce\x88\x0e\x1e\xf2\x8b\x0c\xd7\x9d\x53\xb4\x2c\xd8\x0e\xaa\x13\x7e\xff\x7d\xf9\x0b\xcb\xcf\x95\xc9\x85\x8d\xc0\xcc\xc6\xd8\xca\x8a\xe3\x54\x7b\xdb\xf9\xff\x90\x24\xf3\xcf\x17\x01\x15\xeb\x28\xbf\x12\xb7\xd3\xb7\x01\x46\x0f\x48\xd1\xb4\xb2\x3d\x7f\x6f\xf7\x2f\xfd\xc9\xa6\xc5\x26\x24\xd1\x53\x12\xd7\xf1\x9d\xdb\x60\x26\xa1\x5e\xb5\x42\x95\xd3\x31\xfd\x79\x50\x91\x03\xbc\x59\xa3\xb6\xe1\xba\x7a\xc8\xc1\x12\xe4\xde\x28\x17\xe5\x1c\x1e\x16\x50\x7b\xa6\x6f\x25\x47\xbc\x89\x9f\x69\xc1\x20\x7a\xe5\xe3\x7b\xdb\x0e\x16\x1b\x15\xb6\x12\x30\x5b\xc0\x94\x0f\x9d\x1b\x38\x2a\x37\xec\x2d\xa6\x39\xa6\xec\xba\x1b\xcd\xfc\x51\x21\x4c\x32\x23\xc1\x1b\xba\xb7\x9f\x3f\xae\x3d\x55\xe2\xd4\xbe\x58\x4f\xd7\x60\x1e\x4e\x2e\x55\x8b\x3b\xe5\x70\x71\x15\xa6\x1f\x5a\x81\x5e\xc2\x4a\xac\x18\x09\x34\x57\xbc\x46\xc0\x5c\xfb\x7a\x3f\x25\x33\xea\xda\xdc\x9e\x6c\x1f\xe3\x10\x77\x9e\x69\x7f\x68\x30\x35\xce\x57\x87\x3d\xf5\x5d\x79\x1f\x6d\x2f\xb0\xe2\x10\x7e\x68\x66\xf8\x39\xc3\xa1\x26\xe9\x02\x38\x65\xce\xd1\xbc\xf6\x77\x99\x55\xaf\x54\x7e\x1d\x87\xeb\x32\xa9\xbf\x32\x28\x57\xfd\x12\x6b\x0c\xdc\x5d\x5e\x90\x4e\xb7\x6c\x67\x06\xe3\xc8\x97\xae\xfd\x6e\x47\x56\xfb\x8a\xca\x81\x70\xca\x5b\x39\x66\x90\x89\xaf\x1b\xb1\x41\xa2\x5d\x6b\x8b\x06\x03\x4d\x8b\x11\xab\xf1\xff\x8f\x8d\x43\x37\x58\x46\xfa\x8f\xa8\xa3\x4b\x5f\x26\x48\x20\x74\x4d\x31\x14\x9b\x7d\x57\x32\x6c\x59\xb1\xdb\x74\x13\x16\x78\xf6\x34\xe7\x23\x2c\xa5\xea\x51\x88\x76\x0a\x70\xdc\x35\xdc\x89\xf8\xe4\x53\xb4\xc6\x5b\x77\x2c\x2b\x6b\x62\x76\x8d\x83\x73\x23\x65\x51\xba\xaf\x24\xd3\xc3\x04\xc4\x1b\x62\xc3\x6e\x6a\x33\x83\xb3\xa1\x63\xb7\x3e\x78\xd8\xba\xdb\x75\x74\x1e\x50\x01\xd4\x19\xd3\x0e\x2e\xd7\x7c\x30\x96\xe8\xd8\xdf\x71\x3b\x93\x76\x2c\x97\x07\xbd\xd0\xf3\x65\xa8\x74\xb9\xda\x8a\xb7\x10\x49\x5d\xd5\x6a\xea\x93\xbb\x77\xfb\x22\x26\x35\xc6\x3b\xce\x9f\x63\xaf\x91\xfa\xc8\x9c\x66\x98\x6b\x8e\x21\x76\xdd\x45\x1d\x58\x33\x94\xc1\x90\x7c\xba\x17\x25\xf0\x6d\x25\xd1\xd0\x91\x2b\x3e\x5c\x6c\x7d\xcd\x34\x35\x8f\xad\x59\xdb\xc6\xf6\xb1\xc2\xef\x33\xd3\xca\x82\xf4\x35\x18\xfe\x4f\xf3\x13\x78\x01\x6e\x57\x8a\x7b\xab\x0b\x77\x67\x6e\xba\xe0\xd4\x8d\x08\x89\xd6\x90\x29\xd2\x09\xf2\x83\xce\x8f\xe0\xec\x23\xcd\x83\x2a\xdc\x12\xa9\xc3\xe3\xae\xc2\xd6\x03\x66\x95\x55\x6d\x93\x13\xf1\x2a\x89\x9d\xd5\x9a\x66\xbe\xf2\x8e\xde\x17\x5f\x8a\xae\xee\xb2\x94\x2b\xb9\x08\x92\xa0\x4b\x44\x0d\x04\xb6\x6f\x5e\xef\xf6\x1a\xda\x72\x79\x02\x94\xce\x55\xc8\x6c\x6d\x92\x78\x5d\xdd\x26\xc7\xa7\x31\x60\x3b\x06\x9c\x60\x3c\x92\xe4\xfe\x8f\xf7\x82\x54\x4c\x8e\x89\xb4\x0b\x8b\x55\xf9\x0e\x2a\x5e\x9a\x0f\x33\xc7\xfe\xc7\x7d\xad\x81\x52"}, -{{0x9d,0x5f,0x85,0xd2,0xe7,0xdf,0xd0,0x3b,0xb6,0x89,0xd9,0x00,0x28,0x5f,0xd4,0x46,0x15,0x38,0xa5,0xf2,0x71,0x0a,0x13,0xed,0x21,0xc7,0x75,0xf6,0xef,0xf6,0xb3,0xff,},{0xb8,0x67,0x97,0xe4,0xbe,0x02,0x86,0xae,0x39,0xe4,0x4d,0xf0,0xa0,0x0c,0x01,0x6d,0xb4,0x55,0x5e,0xf8,0x6f,0x2f,0x05,0xd0,0xa3,0xed,0x89,0xd8,0x9a,0x4c,0x3e,0x5e,},{0x17,0x6b,0x95,0x92,0xf8,0xc2,0x51,0x35,0x29,0x2a,0xdd,0x4d,0xaa,0xcc,0x9c,0x4f,0xaa,0x21,0xd4,0xf4,0x9b,0x27,0x84,0x80,0xc4,0xe8,0x88,0x1c,0x01,0x62,0x4d,0xf9,0xa3,0x7e,0x23,0xe1,0x8e,0x84,0xca,0x32,0xd0,0xd8,0xcb,0x85,0x10,0x54,0x22,0x2f,0x10,0xa4,0x95,0x41,0x9f,0x19,0x7e,0x7b,0x3d,0x18,0xdf,0x0a,0xdf,0xb1,0xb3,0x07,},"\xf7\x0b\x5b\x05\x3a\x46\x72\x51\x2c\x24\xb3\x16\x83\x92\xf6\xa1\x7d\xd7\x7d\x86\x89\xc2\x1c\x86\xef\xc2\x58\x29\xa1\xa0\x4f\xab\x4f\x76\xc8\x52\x16\x84\xd3\x20\x10\x45\x59\x07\xa2\x69\x08\x67\x7b\x40\xdc\x69\x47\xd6\x54\xf2\x91\x4c\x30\xec\xee\x72\x4f\xa6\x84\x46\xb5\x9d\x09\x1e\x25\x8f\xc8\x62\x41\x1c\x96\x4d\x66\x8d\xef\x83\x03\x4b\x62\x7e\xd4\x16\xdc\x19\x0b\xb5\xa2\x63\xa6\xff\x8d\x55\x9e\x13\xb8\x93\x62\x25\xfb\x4d\xab\x4f\x7b\xda\x04\x68\xe5\x47\xe7\x08\xcb\x04\xce\xbe\x1e\x5c\xfc\x69\xf7\x6a\x1d\x28\x3f\x28\x16\x82\x86\xf2\x4e\xce\xa5\x53\x5e\x44\x90\xa0\xc5\x55\x67\xa7\x34\x5e\xf9\x53\xce\x42\x6b\x20\x9a\x3d\xe3\xdf\x59\x5e\x80\xee\x61\xe5\x72\xa2\x78\xab\x02\x21\x95\x51\xb7\x3d\xa4\x19\x84\x80\x82\x85\xa8\x35\x98\xa0\x2d\x9b\x28\x67\x12\x10\x00\x4e\x31\xd8\xaf\x92\x42\xc1\x6f\x90\xd5\xea\x8f\x63\xa1\xff\x66\xcf\xe6\x0e\xcb\xe5\x37\x24\x5f\xa1\x2a\x9b\x15\x41\x15\x29\x58\x06\xea\x2d\x11\xf3\x67\x17\x82\xb9\xaf\x4f\xa8\x6a\x12\x88\xe1\x23\xcf\xd2\x40\x9a\x5d\xc9\x8f\x41\xb8\xf6\xdf\x29\x9b\xbc\xc4\xbb\x64\x47\xdc\x03\xa6\xd6\x0e\x9b\x2c\x5b\x8f\xfc\x40\xd9\x83\x95\x6b\xe9\x77\x68\xdd\x06\x12\xd4\x7c\xbf\xa7\x57\x1c\x99\x69\x85\x6c\x15\x2c\xd3\xb4\x73\xac\xe0\xb8\xa1\x44\xaa\xc2\x09\x5c\x0f\x72\xf1\xd3\x14\x71\x52\xb9\x08\xef\x66\x26\xd5\x22\x28\x19\xb2\x0b\xb3\x35\x0a\x46\x45\x2f\x67\x54\x90\xc2\xa8\x21\x50\xee\xc4\x0d\x75\xb6\x6a\x32\x5d\x6e\x92\x9a\x90\x5a\xde\x1e\x31\x60\xab\x95\x01\x81\xef\xc6\x6e\x59\x23\x08\x65\xd5\xe5\x99\x69\x8a\x8a\x3f\xf5\x60\xc4\xc6\x01\xa7\xa9\xa5\xda\x3b\x5d\x89\xbc\xa9\x3f\x7c\xf5\xbc\xf5\xbd\x5e\xcf\xf8\xf1\xa1\x85\xc8\x22\x0e\x4c\x77\x82\x1e\x62\xad\xf9\x5a\x03\x7f\x2d\xf7\xce\xf4\x3a\x4c\x60\xac\x75\x80\x1e\x9f\xcc\xdc\x5b\x08\xee\xd3\x28\xdd\x93\x10\x09\x04\x11\x56\x45\xec\x1e\xe0\x85\xcc\x77\x8b\x0f\x4e\x46\xe1\x72\x98\x98\x4a\x70\x2e\xce\xb3\xe1\x52\x83\xd8\x20\x00\x4f\x74\xa0\x79\x52\x0d\x63\xa7\x5f\xae\x33\xec\x3f\x4b\x83\x64\x69\xe1\xaa\x99\xea\x24\x4a\xf1\xfb\x08\xb0\x0a\x8c\x9d\xfd\x03\x30\x8d\xfc\x20\x23\x5e\xa9\xc8\x28\x3f\x4d\xa4\x7c\xfb\xcd\xbd\x03\x1a\x02\xd1\x64\x16\x0f\x2a\x58\x98\x67\x00\xb1\x95\x26\xd4\x1e\x4d\x7f\xd4\x58\x43\x4d\x72\x64\xbc\x8e\xb6\x42\xe6\xd8\xdd\x27\x59\xce\x2b\x85\xc9\x7b\x37\x02\xe7\x0d\xa7\x1f\x18\xed\xc5\x3e\x91\x40\xa6\x45\x62\x7e\x02\x78\xe8\xe7\x05\x39\x03\x74\x84\xdc\xd1\x8c\x62\xfa\x33\x07\x17\xd6\x14\x8a\x0d\x62\x3f\xf8\xb6\x5e\xa8\x56\x7e\xc7\xfa\x04\xc8\x92\xe3\xa1\xec\xee\x96\xe8\x32\xf4\x15\x50\x74\xc8\x3c\xbc\x93\xe9\x8c\xc6\x7f\x1f\xa1\x12\xaa\x06\xe9\x91\x5f\xa4\xd2\xde\xa9\x31\x55\x1e\x7c\x62\x3a\xa8\xa3\xa7\x61\x9e\xa2\x4f\xf9\x14\xe2\x64\xf3\x1f\xc7\x3d\xfa\x8c\x43\x0a\xc4\x6c\xe1\x6d\xc9\x68\xc5\xa4\x08\x5d\x5c\x38\x0d\x30\xcd\xc6\xf4\x3d\xee\x80\x6f\x38\xd1\xdf\x42\x0a\x06\x55\x74\x14\x47\x37\x05\x6d\xaa\x62\xf0\xc0\x98\xc9\xc5\x2f\xcc\x04\xcc\xa6\x42\xc4\x5d\x68\x73\x45\xa0\x94\x61\x3d\x4a\x3c\x6c\x87\x88\xbf\xa2\x18\x53\x8a\xd7\xec\xe1\xbd\xb6\xc9\x39\x24\xee\xc4\xba\xaa\x3e\xb1\x5d\xc1\x49\x4d\x65\xff\xa1\xa2\x3f\xf8\xe9\x85\x26\x34\x08\xfb\x02\xbf\xe3\x9a\x8c\x55\xb3\x00\xb1\xa0\x2e\xd3\x6c\x67\x14\xdd\x5a\xb7\x50\xd4\x7f\x02\x1f\x65\xe0\x8c\x63\x5f\x1d\x6b\x7b\xaf\x39\x6c\xb4\xf9\x3d\x56\xc1\xca\x46\x1b\xb1\x2e\x94\xde\x7e\x5d\x98\x65\x9a\x8a\xf0\xbf\x01\x9f\xc4\x22\x80\xe1\x11\xe0\x48\x00\xff\x80\xe0\xc1\x57\x15\x0e\x16\x56\x09\x45\x42\x81\xb2\x00\x07\xe3\xed\xfa\xa1\xea\x85\x44\x65\x54\x7a\x00\x6a\x4c\x32\x36\x41\x14\x95\xda\x16\x60\x98\xaf\x28\x23\xa4\x59\xcf\x10\x0a\x1f\x3c\x92\xc6\x39\x0c\x60\x66\xcd\xbf"}, -{{0x4a,0xaf,0x2d,0x13,0x28,0x84,0xf3,0x0d,0x11,0x27,0xcf,0x18,0x7e,0xe0,0x93,0x88,0xb4,0xa5,0xc4,0x4a,0x9a,0x92,0x67,0xe6,0x72,0x83,0x17,0x39,0x89,0x51,0xfb,0x61,},{0x83,0x72,0x7e,0x92,0x57,0x34,0x91,0x28,0x55,0x9e,0xbf,0x75,0x9f,0xdc,0x82,0x12,0x2c,0xce,0x76,0x74,0x66,0x39,0xc0,0xad,0xa9,0x76,0x1f,0x0d,0x60,0xb9,0x40,0xb1,},{0x5f,0x11,0xdf,0x39,0x06,0xa7,0x12,0xa9,0x53,0xf4,0x7c,0x85,0x98,0x06,0xb5,0x23,0x73,0x58,0xd0,0x8b,0xa9,0x5e,0x49,0xf9,0xe5,0x30,0xa3,0x71,0x65,0x83,0x5e,0x93,0x59,0xd9,0x76,0x9d,0xc2,0x1f,0xbb,0x4d,0x44,0x49,0x7b,0x93,0x90,0x5b,0xca,0x8d,0x99,0x17,0xc7,0x28,0x49,0x3f,0xee,0x3a,0xcd,0x5b,0x52,0x1d,0xbd,0x1e,0x24,0x08,},"\xd7\x3e\xaf\x11\x41\x3b\xf4\xd5\xbc\xcf\x6a\x2e\x80\x9c\xd6\x83\x2a\x51\x82\x3a\xa2\x2b\xd1\x6e\x09\xcf\x56\xff\x04\x5e\xef\x2d\x1a\xda\xdd\xa5\x0c\x2e\xbd\x67\xbb\xc4\xd7\x0e\x49\x3c\x96\x8c\xb4\xde\x49\x77\x06\x5d\x44\x63\x30\x06\x94\xc9\xca\xa5\x72\x06\xd6\x66\x46\x93\xd8\x46\x2c\x3c\x57\x6b\x52\x5c\xc7\xac\xf7\x9f\x26\xf9\x05\x5a\x1b\xcf\xa7\xd0\x77\xf4\x5e\xbe\x0b\x2d\x48\x1e\xbd\x63\xf7\x34\x0a\x33\xe4\xab\x68\xf1\x60\x49\x75\xec\x1d\xfe\xc4\x5a\x79\x1a\x2a\xbb\x10\x44\xd7\x5a\x4d\xb5\x5a\xdf\x59\xb8\x39\x4e\xbd\xe6\x82\x4c\x21\x14\x5b\x00\xef\x3b\x1b\x08\xed\x11\xfd\x51\xdd\xa5\x14\xed\x7e\x21\xe5\x4d\xba\xf6\xab\xb6\xd9\xe3\x17\xfc\xf9\xfd\x37\x5b\x18\x76\x4e\x64\xac\x9b\xe5\xb0\x8f\xec\x3b\x78\xab\xba\xb1\xd1\x2a\x2a\xb0\x9d\x55\x9a\xcd\xc7\x13\x3f\xb2\xe0\x00\x8e\x0c\x11\x4b\x7c\xad\xb4\xbf\x76\x30\x78\x67\x4d\x03\xe9\xc8\x07\xbe\xc1\xe2\xca\x71\xad\xcd\xaa\x31\x0d\x58\x7f\xa5\x69\x50\xfc\x0f\xb2\xe9\x79\x04\x3d\x50\xf9\xae\x23\xfa\x8f\x82\x1c\xd9\xd6\x23\x27\x89\xd0\xee\xcc\xfc\x4f\x47\xe3\xad\x80\x4e\x25\xcf\x5a\x42\x5f\x94\x37\x7d\x17\x87\x48\x33\xe6\xae\x36\x38\x17\x8c\x78\xb7\x95\x19\xd6\x4d\x97\x93\xf4\x50\x46\x06\xa0\xea\xb6\x87\x07\xf6\xe1\xf7\xcc\xcb\x51\x5b\xe3\xd1\x20\x1b\xcd\x19\xf2\xf0\xe2\x55\xc7\x22\xea\xb1\x2b\x43\xaf\xf8\xc8\xc5\x56\x11\x25\xfb\xca\x1f\x65\x42\x07\x6a\x06\x15\x2e\xb7\xe4\xb0\x78\x63\x24\xc2\x49\x5e\x79\xd7\x9c\x0a\x8e\x29\x5b\xb2\xe3\xdf\xd0\x5a\x90\x33\x19\x00\x65\xa2\x84\x55\x2a\x6e\x73\x60\x06\xac\xe4\x1f\x97\xcc\x43\x4a\x25\x12\x05\x1b\x72\x7c\xe5\xbc\x9c\x4a\x75\x52\x9e\xc5\x3d\xd7\xd1\xf1\x26\xe7\x93\x85\x77\x47\xb5\xba\x8d\x03\x15\x5d\x45\x55\xf5\x9e\x8b\xaf\x2f\x0c\xdb\xa8\x71\xac\x16\x0e\x75\x19\xa8\x52\xdb\x00\x4f\x70\x16\x41\xa4\x0a\x42\x2d\x4c\x38\xb6\xc0\xc3\xcc\x8f\xbb\xd0\x53\x22\xdd\xc0\x00\x1f\xb8\x67\x28\x6e\x29\x6c\xbd\x69\x86\x2c\xbc\xcc\x74\x47\x03\x8e\xb3\x0f\x8a\x81\x23\xb7\xb3\x13\x73\x98\x47\x02\xc3\xbe\x45\x7a\x4b\x8c\x54\xe6\xe5\x28\x04\x85\xa2\xc4\xff\x84\x52\x1f\x29\x8d\xde\xb3\xb3\xb2\xbc\x91\xf1\x14\xdd\xce\x67\x03\x02\x48\x04\x44\x69\xdc\x06\xf3\x62\xf2\x91\x9a\x3f\xec\xe5\x08\x23\x75\xd0\x40\x80\x37\x6f\xe2\x19\xd9\xb4\x57\x5b\x1c\xf1\xc9\xec\x4d\xca\xc5\x74\x9f\xc7\x78\xf5\x15\xdd\xa1\x3f\xa0\xd5\x86\xc2\x64\xb9\xbb\x61\x50\x33\x10\x76\x2c\x78\x9c\xa1\x16\x08\xd2\xfe\xe6\x74\xc7\x0a\xc4\xfc\x6d\x5e\xbc\xf6\x8c\x4a\xb8\x9b\xd8\x45\x55\xfc\x00\x75\x23\xc2\x8a\x7e\x1d\xd0\x8a\x98\x62\x04\x4d\x52\x45\xb9\x1a\x87\x78\xec\x9e\xe9\x84\xa4\x1a\x9e\x13\xb7\xab\xd6\x57\xae\x2a\x46\xae\x86\x01\x52\xc6\x44\xac\xd9\x53\x67\x67\x8f\xf6\x4c\xc5\x40\x06\xe3\x66\x14\x80\x5e\xd6\x18\xa7\xc6\xd0\xfd\x33\xa9\x08\x52\x30\x90\x84\x1c\x23\x0a\xf0\x98\x46\xd1\x32\xbb\x4c\x6b\x60\xe2\x44\x1f\x9d\x3c\x49\x87\x14\xf4\x70\xf6\xbc\x03\xa8\x0d\x14\xa2\x94\xb5\x65\xd1\xd5\xe7\x81\xcf\xfc\xb1\x30\x4e\xfd\xbb\xc7\xbf\xea\xbd\xed\xc8\x57\xac\xc4\x2e\x27\x62\xbb\xf9\x7a\xf8\x39\xa1\x66\x75\x2d\xa2\x95\x67\x28\x17\xf1\x0d\xbd\x47\x2d\x38\x1f\x53\x16\x55\x55\xac\x82\x22\xa7\x85\x35\xa8\x68\x05\xf1\xbe\xd4\x22\x88\x9f\x20\x61\x09\xaa\x74\x77\x2e\xdc\x0b\xb5\x1e\x8a\x98\x40\xcf\x62\xc9\x2f\xa6\x35\xb9\x0c\xae\x07\x6d\xd5\x0e\x5a\xed\x9d\xea\xc8\x43\xfa\x8a\x6b\x53\x99\x88\x28\x5f\xf1\xad\xab\xe4\xc7\xb8\x3d\x9e\x29\xac\x2d\x94\x09\x2d\xaa\xfe\xc9\xf6\x67\x36\x89\xba\x9e\x92\x52\xd8\x64\xd7\x57\x7a\xa8\x95\x05\xd3\x31\xfe\x78\x09\x86\x12\x77\x00\x2a\x0b\x44\xa9\x6b\xa6\xae\x4a\x52\xb3\x54\x8b\xf2\x68\xe7\x77\x78\x0c\x00\x20\x9b\x24\x5f\x8b\x14\x17\xee\x5e\x70\x1a\x12\x33\x4a\xd5"}, -{{0x4b,0xc7,0xda,0xab,0xc5,0x40,0x7c,0x22,0x6d,0x19,0x20,0xdb,0x4a,0xfd,0x21,0xb2,0xa5,0xb3,0xe5,0x9b,0x8e,0x92,0x46,0x05,0x3f,0x6a,0x1a,0x6a,0xfa,0x54,0xe7,0xe7,},{0xdc,0x53,0x98,0x85,0xfc,0x7b,0xee,0x00,0x2a,0xc5,0xde,0xba,0xe1,0x6b,0xdd,0xbe,0x4b,0x55,0x3f,0xa1,0x5e,0x81,0xee,0x79,0x88,0x76,0x94,0x0f,0x38,0xcf,0xc4,0xc5,},{0xa7,0xa6,0x48,0x88,0x39,0xbb,0xae,0x04,0xde,0xc9,0x2f,0x96,0xd7,0x28,0xc4,0x64,0x68,0x5d,0x7a,0x96,0xdf,0x51,0x2b,0x00,0x51,0x16,0x3d,0x22,0x53,0x8f,0x74,0x54,0x6f,0xa9,0x86,0xb1,0xb6,0x0a,0x6d,0x8c,0xc7,0x66,0xa2,0x6c,0x69,0x84,0xc9,0xcd,0x26,0x88,0x39,0x58,0x98,0xe2,0xb2,0xae,0x72,0xdc,0x6a,0x2d,0x5a,0x9f,0x75,0x0e,},"\x6a\xcc\xe9\x98\x43\xb2\x41\xaf\xe6\xed\xd5\xd0\xab\x78\xd0\xfb\x21\xc8\xc3\x5a\xff\x88\x13\x89\xd5\x05\xf2\xf1\xdd\x91\xaf\x1e\xb2\xad\x22\x92\x54\x92\x7c\x7f\x0e\xcf\xb7\xa8\x14\x16\x90\x57\x3a\x65\x5d\x69\x85\x3d\x74\xd0\x70\x8b\xf8\xb1\xe6\x0a\x03\x96\x30\x28\xa6\x25\xb7\x9f\x3d\xfe\xa2\xb1\x13\xff\xca\xb4\x6f\x3c\xfd\x4a\x62\x1e\x8f\xd8\xff\x0a\x96\x81\x43\xb0\xae\x03\xcc\xb6\xf4\x2e\x25\xe2\xd7\x4d\xbf\x51\x5b\xc3\x58\x69\x9b\x63\x50\x09\xb0\x1d\x61\xfe\x59\x7f\x1d\xc2\xc3\x5a\x7b\xa4\x55\x52\x78\xee\x0e\xa4\x56\xc7\xd3\x5f\xa8\x75\x7a\x41\x79\x24\xb1\xd0\xa8\x35\x1f\x22\x6a\x13\xec\x29\xd0\x25\xb4\x26\x96\xec\x1d\x99\x25\xb7\x69\xcd\x59\xc8\xe2\xf9\xcd\x3c\xe4\xe5\xc0\x20\xe0\x51\xe7\xa3\x6f\x3f\x97\xc1\xe8\xec\x71\x97\x4b\xc1\x6a\xc4\xde\x46\x51\xad\x4d\xf2\xe9\xc0\xee\xd6\x86\x92\x42\x24\xfe\x6d\xe6\xc6\x0d\xd4\xac\xc2\x6e\x0a\xab\xd8\x0c\x21\xd5\x09\xd9\x59\xb8\x0b\x43\x53\x95\x8d\x00\xe4\x4c\x51\x1d\x23\xbc\xf4\x45\x52\x60\x8b\xfa\x56\xa9\xc5\xae\x79\xde\x62\xbb\x23\xf1\x1d\x74\x0f\x48\x24\x0c\x27\xe1\x01\x99\x97\x51\xf2\x53\x47\x42\xc0\xa6\x91\x3f\xf6\x4b\x68\x3a\x18\x99\x5a\xbc\x39\x3f\xeb\x9d\x57\xc7\x1f\x49\xa0\x80\x55\x72\x98\xcc\x40\x5d\x11\xb7\x98\x8d\x71\x16\x84\x0c\x5a\xda\xf5\x3b\xc6\x72\xb4\x69\x23\xcc\x45\x7c\x70\x39\x94\x0a\xd4\xd5\xbf\x07\x3c\x6c\x88\x6b\x13\x39\x52\x59\x26\xd2\x81\xdb\xd1\xa7\x97\x39\xb2\xe3\x64\x14\xcb\xd3\x21\xb1\x85\xfc\x88\xf1\x8d\x2f\x81\xc8\x09\x97\x5b\xe9\xa0\x93\x64\x4c\xc5\x59\xed\x2a\xe5\xcc\x0e\x35\xcb\xdd\x18\x11\xf7\x02\x86\x05\x7a\x3f\x70\x30\x67\xed\xdd\xf5\xeb\x16\x90\xa7\x42\x7b\xb7\x3f\xe3\x02\x4e\xd0\xdb\x82\xa5\xce\x8f\x17\x16\x42\x8a\x76\xfd\x29\x2b\xa9\x9a\x30\x0c\x4b\x2f\x36\x0d\xa2\x12\x46\x17\x59\x0b\x10\xe3\xb1\x62\xa6\xe6\x7d\xd5\xd5\xa5\x9b\xcc\xa1\x0f\x61\x0f\xa0\x64\xaf\xfd\x55\xf8\x48\x3b\x98\xa6\x8d\x07\x6f\x27\x8a\xbf\x88\x8a\x08\xa0\x14\xe0\xea\x49\x91\x80\xfb\xc7\x98\x40\xce\xed\x13\xcc\x6b\x24\x58\xbf\xab\x9b\x0d\xd7\xae\x9d\x86\x46\x1f\xe2\x15\xe7\xc9\xf6\x3f\x76\x8c\xee\x4a\x88\x2d\xf0\xdd\x84\xe3\xeb\x4f\x2d\x7f\x6b\x18\xfa\x57\xd8\xbc\x7d\x9a\xfb\x63\xc2\x1a\xc4\x65\xe7\x90\x3b\x9b\xfb\x86\x38\xa2\x93\x61\xf7\xeb\xfc\x6e\x54\xe5\x46\x5a\x6c\xef\x46\x3a\xe2\x26\x43\xae\x41\x02\x58\x77\x9c\xa7\x4b\x70\x40\x1a\x94\x55\xa4\xd1\x57\xd7\x4a\x70\x29\xef\xe6\xb5\x19\xa8\xc4\xbe\x69\x67\x56\xe0\x45\xae\x40\x81\xb7\x7d\xd6\x03\x1f\x0d\x25\x0f\xa7\x61\xe6\x0f\x85\x9d\x90\x63\xfc\x10\x5a\xa0\xa1\xa7\x45\x0a\xf1\x53\xe7\x05\x47\x77\x77\xc4\x42\x58\x6d\xf4\x07\x40\x2b\xa2\x38\x75\x2f\xae\xf7\x4f\x33\x45\xc2\x6a\x45\x33\xbe\x9a\x61\xf5\xfc\x6b\xde\x48\xe3\xcb\xa7\x5c\x04\xd6\xf7\xb3\x33\xe3\x70\x06\xdd\x0c\x94\xfd\x3b\x6a\x13\x0b\xd6\xfc\xdb\x3c\x6a\xbe\x21\xca\x60\xeb\x43\x1c\xc2\xd8\xa2\xec\xe7\x16\x9d\x2d\xcf\xce\x27\x60\x82\x56\x57\xfd\x4c\x26\xf3\xc3\xb8\x30\xac\xdf\xd5\x08\x01\x1d\x14\x76\x4b\x3b\xe9\x17\x15\x57\x1a\x31\x83\x01\x8e\x0d\x22\x1f\xb9\x53\x2b\xb2\xe1\x71\x1e\x72\x5a\x27\x3a\xe0\xcc\x2f\xac\xcb\xa7\xd5\x50\x49\x29\x45\x9c\x99\x25\x17\xb0\x5c\x1d\xdd\x03\xaa\xcc\xd9\x37\xb8\x6e\xb6\x7b\xc8\x20\x2d\x01\xca\xb3\xd4\x89\x58\x6e\xea\x1a\xcc\xa7\xdc\x20\xcd\x0b\x64\x75\xc2\x58\xff\x67\x36\x61\x49\x6a\x22\xea\x96\xb8\x9d\xb4\xbf\x3f\xca\xae\x3b\xb0\x4f\x67\xdb\x09\x6a\x47\xff\x7e\x1e\xe2\x39\x56\x2d\xc1\x0d\x40\xf0\x53\x94\x4f\x3d\x7b\xcc\x3f\xf4\xc0\xff\x76\x56\x54\xba\x5e\xa6\x4f\x0e\xa6\x3e\x45\xa2\x1d\x9b\x12\x94\x9f\x14\xf7\xea\x70\x74\xe9\xb6\x59\xc5\xc5\xd4\x48\x16\x84\x2d\xe8\x96\x98\xa8\xfc\xca\xce\x43\xeb\x6b\x41\x35\xe0\xb3\x33\xac"}, -{{0xf2,0x6a,0xf2,0x10,0xe3,0xb2,0x01,0x73,0x99,0x0c,0x77,0x45,0x92,0x2c,0xdf,0x94,0x24,0x77,0x3a,0xbb,0x37,0x4d,0x77,0x7a,0x51,0x2c,0xf5,0xb9,0x7b,0x3a,0x00,0x0d,},{0x54,0x58,0x6a,0xbf,0x04,0x11,0x76,0xe0,0x6a,0xec,0x5b,0x60,0x10,0xe1,0x90,0x91,0x6d,0xa5,0x4a,0x8c,0x4b,0xde,0x28,0x8c,0xf2,0x4d,0x8c,0x10,0x7c,0xb3,0xb7,0x30,},{0xce,0x45,0x45,0x30,0xb9,0x22,0xba,0x5e,0xa1,0x62,0xf1,0xa4,0x52,0xe0,0x5c,0x00,0x36,0x3a,0x49,0xa9,0xdb,0x8a,0x56,0x94,0x97,0xc0,0x0c,0xaf,0x1c,0xbe,0xa9,0x91,0x80,0x77,0x05,0x54,0xed,0x4e,0x31,0x40,0xdf,0xca,0x45,0x55,0x15,0x9e,0xbf,0x48,0xef,0x5d,0x2a,0x50,0xf3,0x94,0xae,0xbd,0x78,0x21,0x16,0xed,0x65,0x69,0xa4,0x09,},"\x88\xe2\x6d\xa3\x5c\x54\x88\x4b\x47\x14\x6f\x4e\x3f\x01\x4a\xb6\x5b\x3d\x71\xaa\x7e\x3c\x33\x91\xad\xbe\xb1\x9e\xf2\xe7\xb9\x30\x2e\x28\x19\x91\xb2\x61\xb6\xa0\x99\x2e\x2e\x89\xa4\x9f\x48\x0c\xa2\xd8\xe6\x84\xb1\x2f\x9b\x15\x09\xb3\x8f\x6a\x7a\x98\xa5\xdd\xb4\xc2\xd8\x69\xfd\x03\x18\xe9\x8e\xcd\x8f\xd9\xdf\x49\x1b\xaf\x99\xa9\x29\x4d\xe4\x9e\x1c\xf8\xdd\x41\xee\x85\x73\x0a\xf0\x25\xa7\x01\x14\x3e\x4f\x0c\x8e\x3d\x92\xd5\x5b\x59\xca\x7d\x4a\x6c\x89\xad\x76\x0d\xff\xc0\xc2\x18\x92\x09\x50\x8e\xf6\xc2\x21\x4e\xdf\x99\x67\xb1\x7d\xef\x12\x3d\x86\x92\xc9\xe4\xe2\x0b\x1e\x98\x26\x88\x08\x70\x4f\x5f\x9f\xe1\xa6\xd6\x05\x5e\x32\xc8\x72\x56\x4b\xd1\x7e\xdb\x73\x59\x57\x86\x29\x01\x7f\x0c\x30\xfe\xab\x8b\x50\x4e\x22\x89\x23\xad\xc7\xe8\x1a\xe2\x0a\x85\x2d\xb0\xad\x67\x6a\x78\xe0\x81\x33\x6d\x6b\x04\x02\xf9\xcd\xc5\xd5\xe9\x01\x28\xca\x94\x5d\x10\x51\x5c\xa0\xc5\xef\x03\xf7\x31\xb1\xd4\x0a\x71\x07\x41\xd4\x1c\x1d\xd1\xca\x16\xb1\x06\x0f\xeb\xf2\xa0\x53\x2e\x6f\x5d\x76\x51\xef\x44\x63\x75\xec\x18\x09\x0c\xb8\x41\x8b\x82\x02\xf2\x5a\x03\x89\x03\x1b\x30\x7f\x22\x3c\x5b\x5f\x6a\xfe\x36\xa9\xad\xc1\x06\x8f\x2c\x6e\x0e\xa5\xb2\xb6\xcf\xeb\x8d\xc0\x04\xf7\xb8\x29\xc8\x04\x39\x06\x9b\x81\xa7\xbd\x90\x74\x77\xc6\x13\x5e\xf2\x82\xb7\x71\xf1\x41\xdb\xe7\x5a\x0f\xa0\x56\xe0\x6b\x8a\x1a\x1f\x98\xc2\x5f\xa5\x4d\x14\xc8\xfd\xb4\x2d\x65\x02\x59\x5c\x59\xd2\x5b\xac\xf1\xa1\x9a\xde\xfc\xc1\x31\x70\xf7\xa4\x31\x7b\x6a\xb6\x10\xb6\x09\xd4\x14\xb0\x07\x3e\xa0\x4a\xc2\x9e\xb1\x0e\xe7\x3c\xd7\x1a\x4c\xa6\x04\x09\xf8\xe7\x60\xe6\x0f\x93\x95\x10\x10\x0d\x0c\x8c\xd7\x6f\x26\x4b\xb3\x78\x11\xf9\x7a\xa5\x29\x9a\xc0\xb1\x2d\x41\x68\xff\x38\xec\xdf\xa8\x0b\x1e\x5c\x1b\x3b\xbd\x4d\x40\xd3\x54\x47\x35\xdf\x71\x67\xeb\x15\x8a\x9a\x9a\x23\x4d\x44\x5f\x1d\x66\x3d\xed\x71\x71\xed\xc6\x8d\x17\x2c\x92\x21\x4b\x82\xef\x13\xfe\x6b\x8c\x43\xaa\x89\xb7\x39\xb4\x99\x0a\xe9\x47\xa3\x4f\x02\x0a\x8d\x89\x43\xb0\xf7\xa5\xd6\x1d\xfa\x76\xad\xde\x02\x72\xe9\x8c\x11\x59\xc0\xfd\x8a\x1d\xe3\x3f\x2c\xef\x8e\xdd\x32\x85\x7b\x21\x89\xed\x96\x12\x80\x57\xeb\xde\xa8\x1f\x7a\x3a\x3d\xff\xe1\x89\x3b\x5b\xa8\x77\x55\x6c\x90\x38\x3f\xa2\xc5\xa6\xfd\x68\x0e\x8a\x67\xde\xe4\x80\x2d\x90\xdf\xe9\x71\x62\x3a\x7b\xe2\x2a\xb3\xca\x56\x06\x7b\x1e\x5c\x69\x4a\xa8\x4c\x19\xf1\x6d\x69\xe2\x84\xdd\xfa\x03\x9c\x10\x8d\x04\x35\x81\x38\x12\x39\x0d\x8e\xbc\x1e\x50\x13\x81\x76\xf2\x59\xdc\x0f\x26\xbc\xa1\x3b\xc9\x43\xf5\x0d\x5a\x35\x00\xb1\x8d\x59\x35\x74\xc6\x20\xfc\x09\x7a\xce\x43\x0f\xb8\x07\x28\xd3\xa1\xaa\x64\x4e\x50\x4b\x10\x09\xad\x67\x53\x6c\xeb\x01\x1f\x2a\x35\x7d\xbd\x00\x9e\x4a\x63\xf5\x24\xd5\xb5\x95\x7f\x33\x15\x67\xc5\xb4\xd1\x85\xa6\x1d\xf2\x2d\x70\x71\xd3\x1a\xe9\x21\x41\xe1\x99\xc1\x22\x89\x51\x5a\xed\x80\xc9\x10\x21\x45\x6b\xcd\x45\xcc\xc6\x34\x03\x7d\xcf\x69\xb4\x1d\x6b\x1f\xf5\x34\x71\x01\x0d\x99\xf1\x87\xf0\x46\x54\xf4\x36\x22\x28\x78\x71\xfe\xe6\xdc\xf5\xf3\x02\x3c\xbd\x09\x13\xd9\x9a\xff\x43\xfa\x95\xb3\x2e\xa2\xb1\x33\xb4\xc9\xac\x4b\x01\x7b\x7c\xf8\xf9\xbe\x50\x86\xfe\x92\xb4\x2c\xb8\xdb\xed\x5b\x63\x0b\xf0\x97\xc1\x8e\x2e\x55\xc3\xdd\x93\x27\x1e\x09\xc2\xd1\xcc\x6a\xf8\x7d\x83\xfd\xef\x3c\x3e\x3c\x4c\xba\xfb\xea\x9b\x60\xfd\x5e\x9c\xf0\x01\x1d\xe2\xe9\xe2\x6f\xbf\x09\xaf\xee\xf5\xc6\x98\x02\xa6\xc4\x6b\xdf\x54\xc1\x45\x86\x29\x44\x17\x3e\x01\x7e\x30\x14\x9e\xa5\xc0\x3c\x7a\xef\xa2\x8a\x9c\xac\x77\x67\x00\x2e\xa3\xfe\xfb\xde\xae\x5b\xae\x00\x5c\x37\x0d\xbc\x06\x42\x44\xd5\xb9\xbe\x55\x00\xa3\x57\x26\xa9\x9b\xc9\xe8\xc2\x75\x2d\x51\x0e\x13\x9a\xf2\x25\x58\x00\x98\xc8\x18\x9a\xa9\xc5\x20"}, -{{0x39,0xbf,0xfe,0x00,0x7f,0x8d,0xf7,0xce,0x4e,0x56,0xfd,0x17,0x6b,0x10,0x2b,0x92,0x3b,0xa4,0x8a,0xeb,0x82,0x69,0xfd,0x0c,0xd5,0x20,0xc2,0x3a,0x7b,0x23,0x6e,0x6c,},{0x95,0x32,0x63,0x68,0x00,0x01,0x0b,0x3d,0xd4,0x01,0x2e,0x34,0x1f,0xca,0xd6,0xd2,0x9a,0xfa,0xd4,0x84,0xe6,0xfd,0x73,0x6e,0x89,0xd5,0xbc,0x02,0xba,0x0a,0xc8,0x53,},{0xa2,0x7c,0xca,0x4b,0x9f,0x5b,0x95,0xad,0x0e,0x44,0xe4,0x74,0x0c,0x15,0xde,0xae,0xb9,0x3f,0x22,0xa9,0xb2,0x54,0xeb,0xbd,0x23,0x29,0x36,0x5a,0x00,0x96,0x6c,0x9f,0x4e,0xc1,0xe5,0x5c,0x58,0x94,0xe7,0xbf,0xc2,0x3d,0x39,0x8d,0x39,0x70,0xb9,0x46,0x5e,0x98,0xa8,0xd2,0x3e,0x72,0xda,0xe8,0xe3,0x50,0xda,0x35,0x31,0xae,0x69,0x08,},"\x7a\x8c\x20\xbf\x2e\xff\x69\xaf\x8b\xad\x6b\xdf\xab\xc7\x90\x9c\x58\xce\x74\x6c\xc4\xdf\x78\xb6\x9b\x33\xc1\x05\xba\x3b\xd8\xda\x75\x24\x47\x58\xb5\x17\x2d\x5c\x45\x01\xbc\x39\x97\x01\x85\xee\x3d\x43\x70\x83\xa9\x95\x9f\x81\xe7\x66\x5b\x82\x9a\x69\xa5\xd7\x2e\x03\x4d\x35\x1a\xdd\xdc\xeb\x3d\x3f\xff\x58\x99\x88\xdf\x18\x2b\x46\xfa\x53\xd2\x6e\x7c\x9e\xac\x06\x22\x15\x78\x8f\x23\x37\xbf\x90\xf0\x17\x7d\x8c\xa7\x44\xf9\x5f\x28\xfe\xa8\x54\x59\x3c\x43\x62\xc8\x2e\x9d\xed\x19\xb9\x04\xff\x99\xd2\xbe\xa8\x24\x32\x82\x2e\x52\xc3\xda\x6d\x46\x2d\xa7\x54\xff\x1f\x8b\xd1\x09\x94\x2d\xf5\x1d\xba\x25\xb7\xcd\xe8\x38\xd5\xf5\x24\x23\x9f\x13\x31\xf4\x63\x19\x4e\x10\xff\x56\x79\x5b\x29\x68\x78\xfe\xb1\xf5\x5d\x43\xec\x7d\xaf\x0c\xa5\xab\x3d\x68\x4b\x55\xbb\x0a\xa4\xc7\x20\xd4\xb5\xc2\xe8\x30\xc8\x58\x69\x4d\x3d\x0f\xdb\xaa\xd0\xbf\x67\xd8\x73\x18\x2d\x95\xb2\x41\x2f\xce\x5e\x7b\x00\xfa\x6b\xfc\x38\xb1\x32\xef\xb9\x6f\x87\xbc\x6c\x10\x07\x0a\x57\x16\xec\x9b\x33\xa2\x69\x2c\xdf\x5b\xc4\x1c\x7f\x73\x7e\x28\xc4\x22\x03\x17\xa4\x89\xb7\x32\x3d\x5e\x20\xf6\x5d\x37\x5d\x76\x9f\x9e\x79\x37\x6f\xd0\x2d\x85\x36\x86\x71\xe7\xe0\x81\xeb\x75\x3f\x88\x85\x45\xeb\xe5\xc0\x00\xb2\xf8\x01\x43\xeb\x35\x8d\x43\x18\x5e\x2f\x1c\x29\x4b\x9f\x29\xc8\xbb\x91\x48\x2d\x43\x87\x49\x4a\xad\x17\x6d\xeb\x85\x54\x0f\xd0\x05\xc9\x7d\x13\xe6\x66\x3f\x09\x94\x4e\xb4\x3a\x46\xe6\x23\x67\x94\xbf\x6e\x21\xf8\x1d\x0a\x42\x09\x0f\x9c\xce\xf9\x0a\x6c\x48\x07\xb5\xff\x54\x13\x00\xe5\x93\x48\x81\xa8\xd9\x21\x96\xb4\xce\xe8\x5d\x28\x09\x2a\x82\x8e\xa3\xbf\xc6\xb7\x45\xad\x21\x9b\xe9\xf5\xe9\x57\x41\x17\xd0\x79\xe0\x2f\x4b\x74\x8e\x2c\xc0\x1a\x32\x82\x6a\x37\x08\x23\x19\x14\xd2\x77\x2c\x76\x41\x19\xfd\x99\xd5\x3a\xb5\xb5\xa2\xe9\xd8\x91\xa4\x8a\x9a\xaa\xac\xc2\x63\x38\xb1\x82\x48\xdb\x8a\xb2\xd5\x25\xda\xf1\x5f\xf5\x3a\xcb\xc3\xaa\x98\xd4\xf2\xd4\xa3\x37\xbb\xaf\x6d\x1b\xe2\x19\x85\xa4\xaf\x60\x0e\x29\xbb\xb4\x2c\x8d\x89\xe6\xb3\x89\xc6\x6f\x42\x27\x0c\x3a\x0b\x05\x1b\xdb\x62\x38\x81\xe0\x2f\x2f\x42\x94\xce\xc3\x47\x63\x86\x74\x7a\xba\xe6\xc7\x70\x0b\x8f\x9b\x03\x87\xcd\xdf\xb7\x36\x68\xfb\x57\x69\x3d\x84\x74\x19\x6b\x33\xab\xd1\x2d\xce\x59\xa5\x7c\xf7\x2e\xe6\xcc\x1d\xdb\xaa\xdf\xb1\x9e\x90\xaf\x81\x31\xb3\xa9\x0f\x98\x67\xf4\xc7\xe1\x5b\xdf\x9e\x21\x84\x77\x01\x6b\xd0\xad\x3b\xe8\xdd\x05\x96\x71\xff\x65\x6c\xbd\x4e\xd8\x98\x08\x6d\xe4\xd4\x23\xf3\xdf\xb2\x70\xbb\xf1\x9d\x9f\x53\xf7\xf6\xf2\xd2\x2c\x6a\xc9\x02\x5c\xba\xdb\xa4\x42\xe3\x1d\x98\x11\xe3\x7e\x84\x7d\xbd\x48\x4d\x80\xcf\x74\x30\x39\xff\xa7\x04\x84\x70\xfb\xdc\x60\x80\xf6\xd3\x81\xdc\x7e\x3f\xa2\x71\x22\xdf\x53\xcc\x06\x39\x4e\xa6\xfc\x44\x6e\x1b\xa7\x25\x38\x73\x3e\xd3\xab\xb6\x85\xf1\x6d\xfd\x5c\xcf\x58\x5a\xe8\xfb\xf9\x95\x4b\x50\xf1\x0b\x7e\x54\x32\xa2\x2b\x36\x94\x06\xa9\xb7\x08\x89\x61\xf0\xae\x20\x74\x95\xae\x71\x85\x39\x6d\xcc\xf2\x92\xdc\x46\x3f\x41\xf3\x76\xa1\xca\x89\xee\xfb\xae\x19\x26\x91\x52\x03\x1b\xfd\x81\x52\x88\xe8\xb5\xba\xf3\x48\xc4\xf8\xff\x3d\xff\x4f\xd6\xd1\x08\xf8\x71\xda\xa3\x52\x11\x0f\xa6\x41\x88\xb0\x1b\x85\x26\xa8\x45\xaa\xed\x13\x3e\x45\x6b\x4c\x83\xc4\xfd\x4b\xbb\x16\x5b\x40\x90\x30\x7e\x8e\xb1\x7d\xf1\x76\xc3\x22\x52\x0f\x37\x59\x9c\x21\x05\xaa\x81\x20\x75\x83\x94\xa4\x22\x24\x73\x47\x67\x64\xcf\x0a\xf7\xc5\x51\x83\xeb\xa9\x68\x3d\x72\x70\x63\x14\x43\xf3\xc5\x1f\xb8\xab\x0c\x13\x0a\xc4\x36\xab\x60\x3f\xf4\xf1\xd8\x65\x6c\xdb\xed\x22\x9a\x20\x2b\x40\x00\x8e\xa1\x0b\x17\x15\x42\xf7\x4a\x70\xb7\xbb\xac\xc4\x01\x6b\x7f\x63\x6a\xa8\x96\x33\xb7\x66\x80\x58\xf1\x33\x12\xf5\x7c\x51\x62\xd1\x8e\x39\x9e"}, -{{0x3c,0x40,0x80,0xcd,0xa0,0xfc,0x3c,0x03,0xb6,0x14,0xd9,0x80,0xf2,0xff,0x83,0x1f,0x5b,0xe0,0xe7,0xa9,0x81,0xd5,0x38,0x1a,0x16,0x18,0xe0,0xb8,0xfd,0x00,0x17,0x76,},{0xf1,0xc3,0x26,0x9d,0x87,0x04,0x02,0xca,0xa4,0x38,0x82,0x13,0x5d,0x9d,0xba,0xdb,0xbb,0x16,0x2d,0xfc,0xa0,0xb3,0xda,0xd1,0x97,0xe6,0xb8,0xa7,0xee,0x67,0x9a,0x70,},{0xc9,0xd4,0xa4,0x72,0x8b,0x8f,0xdd,0x24,0x0d,0x9c,0x49,0x8a,0xa3,0x5d,0xe9,0x5a,0x4b,0xbd,0x51,0x78,0x5b,0x73,0xc8,0x40,0x3f,0xdf,0x04,0x0d,0xfa,0xed,0x94,0x47,0xef,0xad,0x00,0x69,0xb6,0x7c,0x78,0x3d,0x4b,0x81,0xd9,0x66,0xbe,0xf6,0xe3,0xd9,0xa8,0x08,0xa0,0x58,0x4b,0x98,0xec,0x2b,0x18,0x32,0x2c,0x4c,0x92,0x0e,0xb0,0x0a,},"\x0c\xee\xbc\x0e\x8a\x47\x72\x0f\x25\x83\x5e\x2b\x9a\xcf\x89\x1b\xcc\xa4\xbd\xa3\x86\x37\xf3\x63\x27\x44\x58\xba\xa9\xe2\xbb\xaf\xed\xd0\x93\x8f\x56\x88\x73\x4e\x22\xac\x50\xfb\x12\x0f\x66\x5f\x6c\x4c\x61\xc6\x53\x17\x39\xb9\x29\xac\x83\xcd\x77\xf8\x96\x3b\x75\x44\x88\xb9\xb8\x59\xc1\x38\x53\x63\x7c\xf0\x25\xc1\x4e\x8f\xdd\x11\x8f\xaa\x14\xcf\x39\x30\xce\xb3\x5f\x10\x4d\x95\x44\x1e\x56\x48\x94\x40\xf6\x20\x41\xef\x1a\xa7\xc4\xb0\x8b\x28\x07\xe3\x2b\xb9\x58\x4b\x90\x04\xd7\x6e\x76\x53\x33\x48\x50\x6d\x64\xf1\x12\xe1\xff\x6f\x93\x8f\x64\x22\x30\xbf\x38\xaf\x01\x0e\x41\x98\x72\x70\x24\x8b\x13\x63\x5a\x35\x67\xb3\x55\xbb\xa5\xb5\x74\x48\xc6\xd1\x3b\x74\xf3\xbe\xbf\x61\x79\x15\x82\x10\x28\xfc\xa5\xde\xfa\x4c\xe5\x42\x4c\xa1\x91\xcd\x54\xa2\x29\x44\xa3\xd9\x40\xe4\xee\x2e\x2b\xa5\xd5\x04\xc8\x5f\x95\x9b\x51\x4c\x4f\xab\x41\xcc\xb5\x74\x3d\x9c\xb2\xf9\xbf\x33\xd1\xd8\xc2\xa5\x86\x9e\x9f\x46\x60\xc3\xfb\x22\x4b\x39\x14\x1e\x31\x10\xc9\xee\x8a\xeb\x87\x1e\x14\xc6\x2c\x6b\xe3\x8f\xb9\xa4\x56\x8d\x73\x68\x10\xbb\x9d\x20\x73\x17\x8b\x6c\x7e\x87\xe3\x58\x2e\xfc\x62\xb5\x3c\x23\xc5\xd4\x65\x20\xba\x33\xff\xb3\xa9\xca\x64\x9e\xf2\x6f\xe7\x4a\x3c\xff\x61\x88\x42\x73\x26\xb8\xc9\x6f\x74\x35\x4c\xb3\xec\xaa\x61\x1b\x12\xcd\xed\x56\x5e\x59\xfe\x1f\x8f\x40\x00\x97\xe9\x3e\xa8\x59\x51\xb5\xb4\xe9\x00\x9e\xea\x7d\xb9\x37\xe4\x34\x9c\x4e\x5e\x00\xc4\x45\x6c\x6c\x5f\x4e\x57\x41\x1b\xaf\x4e\x46\xe7\x00\xac\x40\x02\x57\x76\x5f\x48\xda\xb0\x3e\x43\x9f\x76\xc1\x49\x9b\x51\x08\x04\x7c\x83\x01\x09\xdc\xe7\xf7\x40\xd1\x39\x37\x87\xe2\x9d\x37\x16\xd3\xc4\x7e\x75\x5c\xb8\x28\xe7\xd4\x40\xa9\x71\x97\x51\x97\xeb\xdb\x3f\x9b\x73\x7b\xa1\x1f\x7f\xd0\x38\x6a\x95\x92\x49\x01\x7d\xe7\x23\x4d\x5e\x5a\x9b\x47\x3b\xb9\x58\x3a\x37\x42\xc7\x74\xee\x55\x2a\x12\xa1\xf3\x6e\xb3\xf2\x6c\x88\x5b\xed\x22\xe9\x1c\x74\xcf\x32\xa8\xdd\x3e\xdb\x08\xb6\x74\xbf\x38\x6e\xf4\x27\x72\x79\x12\xd5\x7c\x5f\xaf\xaa\x1c\xfe\xb7\x40\xcd\x52\xb9\xde\xe9\x95\xe3\xd0\x16\x1c\xd9\x21\x3f\x38\xfd\x68\x1d\x53\x8a\xb8\xbf\x97\xb7\x45\xf5\x49\x80\x03\x0e\xf8\xb7\x26\x96\xd4\xe2\x74\x73\xfb\x0f\x1a\xcd\x5d\x0a\xae\x02\x97\x21\x16\x80\xea\x0f\xc5\x9d\x7b\x6d\x51\xc6\x32\x92\x58\x5a\x1d\x55\x3d\x0c\x89\x54\xb4\x2a\x4b\xd6\xfc\xd3\xa4\x95\x75\xbf\x5c\x88\x95\x3f\x1f\x4e\xa7\xfe\x0e\xd7\xa5\x79\xd1\x69\x7e\x64\x5e\x2a\x61\xc6\x9d\x1a\x56\xbc\x60\x5b\xb0\x40\x60\xa2\x77\x8d\x50\x9a\x8a\xad\xbf\x35\xd9\x46\x97\xcc\xee\x9d\x35\x43\xdd\x01\x28\x1a\x03\x1f\x2a\x0e\xb3\xa9\xeb\x13\xae\x56\xff\x44\xfa\x0a\xed\x4f\x34\x88\x74\x7d\x6a\xf8\x20\xf3\x98\x9b\x71\x33\xf4\x49\xea\x56\xd3\xa7\xf7\x31\xe7\x91\xb7\xed\x2a\x5d\xb9\x39\xbb\x75\x35\x2d\xe7\xda\xec\x50\x66\xfd\x57\x55\x71\x65\xad\xff\xa6\x31\xcd\x3f\x96\x7c\x3c\x7c\xfc\x11\xcc\x1f\x14\xfa\x23\xde\xfe\xc3\xeb\x02\x39\xb4\x5e\xd6\x01\xa3\xa8\x07\x8c\xcf\xc7\xf8\x38\x09\x02\xa8\x59\xee\x9c\xe2\xdb\x79\x5e\xfa\xca\x0a\x01\xdc\x08\x79\xd5\x06\xac\x97\xd1\x07\x04\xd7\x75\x7b\x3c\xcf\x3b\x37\xc3\x39\xb4\x2d\xb2\x37\x82\x27\x80\x23\xe4\xc2\xe7\x7d\x74\x24\x6c\x9e\x54\x41\x49\xa5\x5c\x0c\x92\x0e\xbf\x29\x86\xb4\xc5\xb4\xb3\x57\x2f\x74\x8c\x4b\x15\xc7\xf8\x63\x99\x9b\xc5\x13\x2a\xda\xd0\x97\x61\xeb\x76\x50\x50\x19\x76\x9f\xb5\x54\x22\xf6\x03\x18\x4e\x24\xc0\xd4\xf3\x76\x19\x87\xb5\xc5\x0f\xea\xfc\xce\x53\x30\x2a\x3a\x41\x5e\x20\xf5\x6a\x05\x48\x03\xe5\x53\xba\xcd\x24\x2a\x5e\x13\x64\xaa\x3b\x2d\x7c\xb3\xbc\x1e\x1b\x86\xa4\x74\x31\xcb\xd3\x96\x95\xb6\x7f\x55\x4c\x46\x45\xb7\x23\x69\x04\x09\x4c\x11\xaa\x1b\x40\x32\x6b\xa9\x1b\x8b\xf4\x87\x3e\x9a\x4d\xe0\x4e\x2b\xf4\x62\x59\x72"}, -{{0x45,0x43,0x8f,0x91,0x46,0x5d,0x74,0xa2,0x82,0x5b,0x0f,0x66,0xa3,0x5b,0xd7,0xc8,0xd0,0x05,0x86,0x54,0x79,0xb3,0xdc,0x10,0xa9,0xb5,0x6f,0x29,0x7d,0x31,0xb9,0x26,},{0xf0,0x92,0xb5,0x88,0x03,0x30,0x87,0x1e,0x5a,0xaf,0xdd,0x3c,0xeb,0x38,0x50,0xee,0x7e,0x09,0x41,0xa2,0xa1,0xdc,0x89,0xf4,0xfb,0x47,0x71,0xd7,0x5a,0x22,0xf6,0xf2,},{0xd9,0x28,0x7b,0x7f,0xec,0x01,0x7f,0x2e,0xa4,0x0a,0x14,0xa1,0xf6,0x2d,0xca,0x78,0xb0,0x2a,0x3d,0x66,0x32,0xdf,0x7c,0x60,0xeb,0xd9,0x0f,0xc5,0xe4,0x92,0xc5,0xc6,0x2c,0x43,0x16,0x6b,0xf8,0x56,0x58,0xfb,0x30,0xa0,0x8b,0x57,0xa5,0x81,0x31,0x21,0xb8,0x03,0x97,0x57,0x1a,0x31,0x2b,0x6d,0xd1,0x1b,0x65,0x39,0x20,0x54,0x16,0x02,},"\x30\x71\xd4\xb7\x20\xdf\x10\x93\x65\x99\x67\xcd\x4e\xef\xef\x2e\xf9\x67\x84\x75\xf7\xde\xc5\x8f\xec\xec\x1d\x92\x8d\xea\xf8\x02\x45\x7a\x19\x34\xe6\x04\x55\xf4\x96\xcf\x42\x51\x82\x0e\xd6\x0a\x3d\x81\x33\xb6\x24\xd3\x3a\xf2\x6a\x26\x27\x84\xb5\xa2\xfb\xa7\x3c\xca\x2a\xa5\xe5\x19\xe1\xf5\x39\x58\x47\x80\x64\x98\x64\xba\x5f\xbc\x1f\x01\x1d\xdd\xac\x38\x1f\x8d\x48\xd0\xd6\x0c\xe8\x23\x17\x01\x17\x3c\x9d\x2a\x30\x7a\x76\x30\x2e\xbc\x69\xdc\xbc\x93\x0d\x28\x43\x14\x75\xb5\x16\xf9\x8f\x77\x8e\xd2\xe1\xff\xf2\x72\x90\x9a\x27\x2c\xc3\xfb\xb6\xb3\x1c\x80\x41\xa3\x7c\xb7\x77\xe0\x62\xe4\x96\x49\xaf\xad\x12\xc1\xb5\xf7\xfc\xb8\x06\x5a\x99\xe7\x42\x33\x62\xad\x16\x90\x60\x31\x26\x5d\xb7\xe8\xb8\x97\x51\xf8\xa4\xa4\x07\xf2\x50\x26\x50\xfe\xd7\x53\xe4\x2c\x8c\x91\x1e\x50\xb9\x4b\x38\x00\x69\x5b\x0e\xba\x7d\xff\x06\xb7\xa7\x10\x11\x7e\x49\x20\xd4\xb1\xc6\x05\xa3\xeb\xf3\x2e\x06\x96\x67\x16\xed\xa1\x4b\x30\x42\x99\x8a\x3c\x7a\x5e\x9f\x83\x54\x2d\x7d\xde\x65\xe5\x28\xbe\xd6\x10\x1d\xeb\x33\x1d\xeb\x94\xcd\xd4\x60\x44\xbe\xf8\x8c\x09\x7b\xaf\xd4\x0d\x69\x21\xa7\xc4\x84\xc8\xf9\x66\x84\xdc\x37\x16\x71\xd9\x4e\xee\x7c\xbe\x5d\x58\x77\x15\x31\x4c\xff\x0d\x18\x77\x27\x2d\x81\x90\xa9\x0e\x18\xbf\xb3\x21\xd5\x2b\xf7\x47\x05\x13\x7b\x2a\xbf\x91\x65\x73\x17\x67\xa1\x3a\xdc\x9c\x85\xe0\x39\x7b\x47\xae\xf9\x6b\xad\xb2\xca\x7f\xcb\x82\x93\xb0\x1f\xd1\xde\x31\x6e\xe1\xe6\x5f\x35\x6b\x9d\x6e\x8e\xa1\xfd\xd8\x37\xbd\x96\x08\x11\x49\xea\x2d\xcd\x73\xc4\x88\x1f\x32\xb7\xde\xeb\xc3\x71\x5e\x2d\x7c\xdb\x64\x3e\x0d\x98\xf4\xe8\x46\x50\x8b\x04\xb3\x24\x39\xff\x14\xb1\x16\x4f\x46\x84\x6d\xf9\xaf\xae\x44\x46\x4c\xf5\x50\x10\x4c\xd3\xaa\xb3\x81\x75\x40\x47\x0a\xaa\x2a\xb9\x55\x9a\x68\xb7\xff\x6b\x1b\x9c\x0c\xe9\xf5\x86\x9c\xbd\xcd\xd6\x17\x09\x09\x42\xe3\x53\xb4\xc7\x7f\x09\x39\x58\x96\xbe\xcd\xdf\xf1\xab\x7f\x07\x58\x6a\x51\x4d\x81\xfb\x09\x63\x61\x55\x75\x66\x87\x0f\x16\x91\x98\x34\x85\xa8\x0c\x34\x13\xda\x98\xb8\xd1\x9c\x78\xe6\x37\x9f\x94\x3e\x5b\xd5\xa5\x69\x7a\xa3\x3c\x5e\x6b\xfc\xfb\x7b\x8d\xf1\xe1\x57\x4e\xe4\x16\xfa\xb3\xc8\xa7\xd0\x88\xb3\xa0\x57\xcf\x86\x53\x21\xb7\x4e\x61\x03\x52\x6d\xd9\xad\x15\xca\x5a\xd3\xc0\xf6\x97\x18\xe2\x70\x81\xd4\xb3\x4a\x7c\x6d\x1a\xab\x6b\x96\xc0\xa7\x54\xb9\x89\xb4\x94\x06\x38\xc9\xed\xe3\xd1\x7b\xd4\x9f\x65\xbf\x78\x3d\xc8\x5f\x1c\x4b\x14\x48\x76\xcd\xbd\xb2\x28\x2a\x95\x64\xaa\x81\xb5\x70\x92\x08\x0d\x64\x48\xfb\x65\x80\xec\xf0\x9f\x82\xa7\x55\x01\x0d\x55\xd4\xa5\xe4\xf3\x05\xe2\x59\xdb\xe9\x95\x08\xb4\x79\x25\x0d\x80\xec\x17\xc8\x76\x0a\x93\xe0\x5a\x29\x57\x1f\x68\x56\x07\x30\x22\xc8\x70\x69\x13\xc4\x6a\x2e\xfd\x2e\x9c\xaa\xe4\xff\xa1\xb4\x22\x2e\x3d\x70\xe9\x79\xe8\x1a\x71\x95\x1d\x7c\xb8\x30\xbc\xbc\xf9\x01\xaf\x24\x4f\x64\xe4\xad\x9f\x52\xfa\x3b\x62\x03\x1e\x35\x16\xda\x50\xbc\x2b\xce\x78\xeb\x9d\x61\xbf\xed\xd9\xb3\xf5\x7e\x89\x35\x5f\x17\x7d\xb6\x16\x2b\xf6\x1d\xa0\xe4\x54\xc3\x42\x88\xb9\x67\xc3\xfb\x4c\x34\x1b\x32\xd4\xd1\x3a\x31\x98\x69\xb8\xe3\x60\x46\xf9\xe3\x38\xb5\xf3\x6a\x1f\xc1\xa7\xed\xa7\xd7\xb0\xd4\x38\xe0\xa7\x5d\x84\xbb\xe4\xd6\x8c\x87\x9a\xda\x80\xdd\xe2\x3f\x71\x55\xb5\x32\xcc\xcf\x7a\x63\xf1\xbe\xdf\x84\xf8\x2f\x44\x0c\x9e\xc3\xcb\x0e\x45\xf3\x2c\x92\xf7\x64\x38\xf5\xb4\xb9\x10\x44\x1e\x67\x38\xaf\x3f\x5d\x20\x50\xd5\x79\xee\x96\xb8\x8f\x3b\x00\x81\x0a\xb1\x26\xff\x3a\x8f\xef\xd9\x71\x04\x43\x24\xdd\x4e\xb3\x44\x7d\xac\x5b\x77\x80\x9c\xda\x8c\x71\x68\x25\x49\xd7\xcf\x2d\xce\xe3\x40\xed\xcf\x94\x94\xac\xa4\x29\x01\xe2\xc1\x1e\xd9\x77\x90\xaf\x48\xbc\xea\x29\x52\x1e\xf0\xe3\xd0\x3c\xda\xde\xcd\xc8\x94\xdd\x07\x56"}, -{{0x72,0xcf,0xce,0xf4,0xc9,0xd6,0xa1,0x98,0x6d,0x19,0x03,0x11,0x84,0x0e,0x55,0xcb,0xaf,0xac,0xc8,0xa6,0xeb,0x5e,0xcc,0x72,0x93,0x4f,0xda,0x53,0x5b,0xdc,0xff,0xb2,},{0xa9,0x44,0x64,0xd8,0xcc,0x8f,0x3e,0x43,0x39,0x39,0x47,0x64,0x9f,0x91,0xc2,0x75,0x23,0x27,0xe4,0x0d,0xac,0xa1,0x1a,0x99,0x70,0xc5,0x18,0x1e,0xda,0x37,0xd6,0x06,},{0xdb,0x72,0x70,0xac,0xce,0x78,0xd7,0xfb,0x09,0x08,0x0a,0x32,0x79,0x41,0xbc,0xe7,0xeb,0x14,0x5b,0x9e,0x36,0x61,0x86,0x6a,0x86,0x83,0xf9,0xa1,0xa3,0xde,0x97,0xfb,0x02,0xb0,0x25,0xdb,0x9e,0xc7,0x6f,0xf3,0x25,0x60,0xfe,0x63,0x88,0x27,0x74,0x2e,0xa2,0xf4,0xeb,0xef,0x6b,0x7c,0xce,0x44,0xf9,0xaa,0xee,0x43,0x4f,0xd7,0xc1,0x08,},"\x66\xa6\xcb\xe8\x8a\x8a\xb9\xa3\x38\x47\x79\x7f\xc4\x80\xb2\x44\xe8\xa2\xb8\xec\x79\xe8\x0b\xc2\x63\x77\x53\xde\xb3\x6f\xa3\x01\x4f\x84\x3e\x22\xa4\x7d\xb0\xa3\x17\x78\x38\x5e\xc1\xf4\x55\x67\x2e\x0d\xff\x6c\xa2\x1c\xa4\xcf\xd2\xb9\x89\x47\x1b\x7f\xfc\x30\x78\x28\x13\x8b\x0a\xd4\xe6\x47\xc2\xd1\x3c\xef\x72\x44\x69\x05\x4a\xbd\x37\x40\x24\x5a\xea\x4b\x78\x9e\x24\x4e\x95\xcf\x9e\xcf\xd0\x8a\x0d\x13\xc7\xce\xd3\x93\x33\x27\x27\xa7\xf3\xd8\xfb\xda\xbd\x93\x9d\xe2\x8c\xaa\x41\xcc\x96\xc7\x08\x11\x98\xe2\x26\x53\xd9\x4e\x02\x4a\x61\xf5\xf3\xdc\x5a\xa3\x7f\xa9\xad\xdd\xc9\x6c\xf1\x69\xd3\x50\x62\xa0\xa2\x9b\xa4\x5a\x53\x9c\x87\xa6\x8a\x3a\x03\x04\x36\x13\x09\xd2\x13\xe6\x14\xee\x83\x73\xda\xfb\xa2\xa7\xd6\xed\x7d\x2a\xd3\x77\x04\xc0\x94\x6e\x4d\x09\x3e\x2d\x94\xd0\x61\x36\x4c\xc1\x23\x10\x63\x72\x91\x03\xa7\x7c\xcb\x50\x18\x91\xbb\xc3\x18\x54\x57\xbb\xd2\x86\x9e\xb6\x3d\xc6\x0f\x19\x6f\x10\xa3\x8b\x7b\x36\xcb\x3f\x64\x3d\x35\xdd\xbf\x43\x8a\x44\xbf\x0c\x8f\x57\x0f\xad\x41\xbd\xde\x26\x7f\x0f\xfc\xf1\xf2\xf9\x27\xd6\x26\xd1\xb0\xd9\x80\xa0\xce\x22\x3f\x2f\x00\x54\x84\x5a\xfe\x41\xd3\x9d\xe5\xa4\x57\x21\x9f\x27\x6c\x67\xe6\x9b\xe2\xd5\xc9\xe0\x70\x13\x16\x39\x56\x1c\x26\x75\x1f\xb0\x64\x35\xe0\xe4\x2e\x25\x08\xc5\xf4\x9c\xd1\x2b\x51\x7c\x98\x33\xff\x97\xf5\xe5\x1e\x1d\xce\xaf\xa9\x42\x6d\x3d\xc5\x2f\xd1\x37\x9c\x64\xcc\xaa\xbb\x26\xdb\x1a\xf6\xde\xd7\x15\x36\x28\x84\x2f\x0c\xbd\xbb\xbd\x6a\xa0\xcf\xa5\x40\x7f\x40\x94\x96\xc0\x65\x32\xdb\xea\xc9\x4d\xab\x9b\xab\xa0\xb3\xc9\x88\xfa\x03\xd3\x6f\x91\x1d\x80\xe4\x9b\x37\x0b\x68\x37\x03\x7f\xf2\x49\xe7\x6d\x69\x2c\xd1\x77\x37\xe0\xd0\x79\x65\xd3\x3f\x17\x04\x2b\xbc\xd1\xe9\x90\xe0\x40\xf7\x19\x36\xf6\xfc\xa2\x54\x2a\xe3\x37\x48\x36\x77\x87\xc0\x1b\xde\xa7\x5c\x9a\x0e\x66\x15\x02\x81\xc4\x68\xfe\x5c\x73\xaf\x9e\x5b\xec\x37\x2d\x50\x20\xc3\xd3\x7f\xa1\x03\x5a\x67\xe2\x24\xd0\x95\xf0\x66\xa5\x1f\xe1\xf6\x81\xc3\x07\x39\x39\x27\x2f\x6a\xf7\x75\x0e\xd8\xd1\x83\x49\x17\x8a\xb4\xa2\xee\xb4\xe9\xca\x82\xbb\x67\x29\x6e\x98\x90\xf3\x16\xc9\xd9\x49\x59\x53\xd6\x84\x36\xeb\x1c\x1a\x2f\xb6\xa1\xcc\xa4\x5a\x8e\x88\xa0\x9b\xdd\x65\xa5\x55\x80\x25\x61\x8b\x36\xd7\xf3\xcb\x38\x9d\x2e\x2a\xb1\xed\x23\x32\x28\xec\x92\xa3\x27\x97\x8c\x0a\xdc\xed\xdb\x6c\x96\x32\xd3\xab\xd7\x97\x16\x21\x71\x37\x54\x75\x8e\x21\x01\x3a\x0c\x3d\x00\x9b\x6e\x31\x93\xcc\x15\x2c\x57\xef\x73\x10\x7b\xd4\x35\x7d\x52\x8b\xe4\x08\x73\x02\x7b\xf1\x84\x0f\x68\x55\x36\x08\x0f\x12\xc5\xff\xa9\x3c\xa6\x29\x73\x67\x80\xe0\x15\xe8\x6d\x19\x09\xf0\xd8\xf3\x72\x01\x0c\x9c\xb7\x2c\x09\x89\x84\x5f\xc8\x83\x15\xe6\xb9\x37\x0d\xc9\x2d\x36\x83\xef\x44\xd3\xf7\x5f\xc9\x6c\x4b\x0e\x89\xe1\x3d\x68\x2d\x19\x88\xb6\x85\x71\x3e\xad\xa8\x42\xbe\x9d\x2b\xbe\x2a\x76\xbb\xa1\x5d\x38\xcb\xaf\xb6\x5c\x40\xc2\x15\x9b\x0c\xee\xb0\xd7\x69\xb9\xbe\x35\x55\x40\x73\x4f\xf3\x77\x36\xc0\xf0\xfa\xcb\x95\x15\x93\x09\x36\x5b\x96\x46\xbc\x4b\x34\x4f\xb1\x9a\x5c\x16\x39\xa8\x8e\x87\x31\x7b\xfb\x3b\x5e\x7b\x51\x30\xfa\x7d\x56\x43\xed\x4d\xa0\x64\x30\xc8\xa0\xc1\x85\x8c\xcf\x2f\x9a\x6e\x3d\x62\x01\x22\x53\xf0\x12\x2d\xba\xb4\xa3\x54\x75\xa6\xf6\x55\x89\xb2\xb0\x95\x99\x28\x26\xe4\xf1\xb5\x8f\xa0\x50\xb8\xf9\x5c\x4f\xeb\xa3\xfb\xaa\xdd\x2c\x22\x44\xad\x4a\xbd\x41\x01\x39\xad\xf4\xc1\x53\xcb\x5e\x69\x33\x7a\xf1\x76\xa7\x83\x7e\xea\xea\x99\xbd\xcd\x59\x38\x5a\xfd\xed\x34\xff\xba\x80\x63\xa3\x5f\x4f\x55\x8e\x4e\xeb\x48\xf1\x48\x7b\x56\xb1\xf8\xd1\xf7\x30\x67\x62\x1c\xb5\x48\xc8\x08\x75\x3e\x35\x26\xa2\xf2\xaa\xbd\xe1\x26\xbe\xa5\x21\xcf\x67\x3d\xea\xfa\x79\x2c\xa5\xbd\x22\x12\x79\x5b\xd6\x6b\x86"}, -{{0xa6,0x33,0x7e,0x4d,0x3b,0x1a,0x49,0xb1,0x26,0x31,0x67,0x78,0xc6,0x13,0x51,0x6c,0x03,0xac,0x88,0xc9,0x6d,0x92,0xff,0x5c,0xc7,0xe0,0xc8,0x52,0x7c,0xce,0x1a,0x62,},{0xf5,0xea,0xc4,0xfe,0x0e,0xa1,0xa5,0xf2,0x36,0xb4,0x9d,0xa3,0x3a,0x24,0xe2,0xf3,0xa8,0x3d,0x4b,0x26,0x0c,0x54,0xd3,0x41,0x6c,0x64,0x4e,0x05,0xc8,0x38,0xbf,0x51,},{0x78,0x13,0x76,0xc9,0x51,0x2f,0xa3,0x3c,0x45,0x70,0x47,0xa1,0xf4,0xf0,0xda,0x31,0x76,0xe6,0x0e,0xe4,0x77,0x82,0x86,0x9b,0x7e,0x9f,0xa5,0x84,0x1d,0x96,0x4f,0x3c,0x1a,0xd6,0x6b,0x70,0xc1,0x14,0xb1,0x77,0x1c,0x32,0x4c,0x83,0xff,0x6c,0xd9,0x97,0xae,0xfc,0xcd,0xc5,0x9c,0x11,0x4d,0xb9,0xf2,0xf3,0xca,0x7d,0x84,0xa7,0xb6,0x0f,},"\xe3\x34\x30\xc3\x8c\x4a\x40\xb3\xc6\x6e\x20\xcf\x3b\x70\xe9\xfe\xa8\xcc\x50\x76\x1f\x2a\xfe\x24\x9e\xc0\x59\xc0\x7b\xc3\xb3\x7e\x5b\x94\xf4\xa4\x3e\x31\x00\x99\xb1\x9a\x85\xf5\x9d\xff\x73\xa7\xe4\x95\xc4\xdf\x31\xf7\x47\x80\xcd\xef\x7b\xd6\xe4\x7c\x39\x4c\x18\x91\xea\x30\x52\xe3\xcc\xf5\xd8\x4b\xae\x08\x2d\x24\xba\x71\x78\xac\x65\xd2\x29\xad\x18\xa8\x49\x40\xf6\xb4\xdb\xc5\x96\xee\x63\xc1\x81\xb5\x7b\x5b\x49\x69\x89\x79\xc1\x86\x32\xfa\x82\x1c\xa6\x1e\x35\xa0\xd0\x35\x1f\xe1\x3d\x69\xe0\x6d\xdc\xc8\xd6\x66\xdc\xa2\x45\x02\x17\x7f\x34\x4e\x2f\x44\x05\x75\xd3\x9e\xbf\xe5\xe7\xf1\x06\x53\xb6\x5b\xef\x29\x1d\xc8\x13\xa0\x43\x4c\x97\x5d\xe1\x64\xc1\xa7\x6b\xf6\xfc\xef\x98\xf2\x31\x81\xc0\x09\xb9\x18\x30\xb6\x18\xe4\x87\x48\x47\xd2\xe2\x1b\xbd\xb9\x3f\x20\xcd\x8b\x1f\x4b\xaa\xdf\x99\x42\x8a\x22\x67\x43\x86\xa6\x68\x15\x2b\x4b\x90\x39\xff\x06\xab\xcf\xe3\x34\xa0\x62\xf7\x94\x05\x61\x72\xec\xbc\x07\x94\xdf\x98\x27\x1b\x9a\xcf\xe4\xb7\xda\x55\x3a\x87\x63\x42\x37\x63\x00\x09\xa0\x5b\x25\x7c\x18\x4c\xbe\x23\xd9\xcd\x5a\x03\x86\x58\x01\x0f\x57\x48\x99\xf3\xb2\xd1\x54\xd1\x85\xee\x67\x23\x09\x13\x65\x0c\x3a\x05\xb5\x4a\x2e\xdc\x24\x3a\x42\x87\x39\x8e\x37\x69\x28\xea\x9c\x6b\x2c\xba\xf3\x71\x25\x25\x40\xe2\xb8\x04\x3f\xcf\x55\x68\x13\x19\x6a\xe5\x72\xc2\x7c\xfb\x5a\x46\xab\xb9\x72\x9a\xf2\xdc\xfc\x29\xe0\x33\xdd\x11\xf3\x3e\x86\xcc\x6a\xc3\xbc\xe6\xf3\xf9\x57\x7d\x36\x78\x1a\x69\xed\x7e\xaf\x8c\x82\x63\xa0\xf1\x8e\xba\x0f\xe8\xa4\x81\xf3\xe1\x5a\x55\x59\x94\x34\x19\x5f\x7c\xb0\x57\xdd\x36\x4e\xaa\x07\xdd\x0d\xfd\x26\x6b\x80\x7f\x53\xa2\x07\x0f\xd7\x91\xe8\x72\x42\x2f\xd9\x07\x13\x4f\x4a\x8a\x78\xa8\x76\xbd\xcb\x03\x1a\xc8\x60\xdf\xe0\xbb\x57\xe1\x05\xdb\x82\x87\xb3\x1a\x60\x4e\xb7\x12\x69\xbe\x5b\xa2\x29\x98\x5c\xea\xbc\x2b\xdf\x16\x5a\xc7\x41\x65\x0b\x1f\x01\x3a\x66\xc9\xbd\x24\x3d\x03\xa8\xb1\xc5\x08\x13\x81\xcb\x92\xe2\x3f\x90\x57\x77\x1f\xc0\x7c\xa3\x2d\xff\x1d\xb9\x4f\x5a\xdf\xd2\xf4\xff\x9a\xf3\x1d\x25\x0d\xd4\xf8\x6b\x22\x59\x2f\x60\xa7\x45\x75\x15\x62\x13\xf1\x08\x46\xc7\x46\xa9\x20\xfe\x39\x85\x1b\x32\xfe\x4c\x8b\x87\x58\x76\x5b\xc5\xb8\xb9\xd5\xb9\x92\x63\xdf\x36\xf9\x78\x88\x05\x3f\xd1\x0f\x1d\x68\xf5\x77\xae\xd5\x59\xbc\xfd\xe7\x44\xbc\x65\x11\x07\x6c\xaf\xd6\x89\x44\xa0\xed\x10\x55\x2d\x11\x34\x4b\xc7\xe4\xd9\xef\x93\x6d\xac\xce\xd5\x27\x43\x31\x32\x95\x9b\x1c\x73\x24\xad\x1c\x4c\xbc\x3a\x1a\x73\x6b\x1f\x02\xaa\xe8\xe0\x61\x1a\xe2\x3f\xdd\x47\x4f\x5b\x8e\xe7\x05\x6f\xcb\x5a\xf6\x13\x3e\xcc\x08\x4b\xb9\xf1\xf5\x0c\xbd\xac\x66\x24\x44\x37\xb4\x34\x8f\x4e\xdf\xe2\x37\xfc\x3c\x38\x29\xab\x94\xeb\x4f\x14\xca\xb1\xcc\xd6\xca\xee\x36\xfa\xdc\x20\xa3\x10\xcf\x06\x90\x62\x2c\xdc\xa8\x48\xae\xd0\x3f\xf4\x03\xa6\x63\x3f\x4f\x65\x79\x94\xb7\x80\xdd\x60\x48\x14\x9c\x3b\xfb\xc1\x78\x89\xe3\x7d\x90\xb1\xe5\x42\x0e\xb3\xd4\x59\x6b\x91\xba\x11\xbc\x02\x29\xc6\x5d\x05\xb9\x3c\xd7\xe0\x45\x4d\x1f\x3c\x6e\x1e\x80\x71\x98\x37\x92\xc4\xd4\x36\x8d\x07\x78\xae\xf4\xe1\x23\x33\x5f\xd2\x96\x2c\x65\x7b\xd0\x51\x35\x71\xa5\xfc\xe2\x11\xde\x62\x87\x4f\x27\xca\x10\xdc\x15\xba\x2d\x44\x5f\x1c\xf4\xbe\x5f\x83\x3c\xf0\xb5\x64\xc0\x22\x57\x6b\x98\xc0\xa2\x43\x49\xb6\x70\x85\xf9\x22\x02\x67\x5d\x7d\xac\x48\xb9\x5e\x3b\xfd\x65\x55\xa9\xec\xb7\xc7\x2f\x08\xbf\xec\x0d\x22\x02\x22\x49\x2f\xdc\x96\x36\xf0\x36\xec\x45\x08\xa3\x65\xb7\xb7\x09\x79\xf9\xeb\x4a\x72\x63\xa8\xba\xcb\x1c\x1d\x01\x55\x73\x86\x46\xcd\xd4\x6a\xb9\x23\x4a\x17\x03\x11\x50\x0d\x0b\xae\x6e\x55\xa8\x63\xbd\xaa\x56\xf5\x16\x45\xad\x85\x29\x7a\x73\x81\xf8\xd2\x0c\xf9\x6c\x47\x4d\x1b\xb8\x1f\xce\x13\x2b\x14\x55\x5d\x1a"}, -{{0x10,0x7d,0xa9,0x8d,0x0e,0xe8,0xe7,0xc0,0x0f,0x6d,0x41,0xec,0x26,0x59,0x44,0xce,0x67,0xef,0x8c,0x8f,0xfb,0x51,0xf4,0xf1,0x1f,0x4e,0x5f,0x1a,0x27,0xfb,0xe8,0x05,},{0x3b,0xec,0x34,0xb1,0x61,0xb1,0xbc,0xff,0x00,0x9f,0x8c,0xfc,0x50,0xd8,0x4c,0xeb,0x6a,0x2d,0x5b,0x20,0x3b,0x52,0x38,0xa8,0xaa,0xd8,0xa8,0x36,0x18,0xb4,0x42,0xe7,},{0x53,0x25,0x2b,0x92,0x3a,0xd1,0x9c,0xc3,0x97,0x84,0xd3,0xa9,0xae,0x59,0xd6,0x2a,0x63,0x00,0xdc,0xc5,0x0a,0xc8,0xfd,0x07,0x13,0xcb,0x58,0x84,0x45,0x01,0xd8,0xd3,0x80,0x5a,0xfa,0x0f,0xda,0x64,0xc7,0x3e,0xa0,0xf6,0x0e,0x6a,0x8b,0x34,0x45,0xbf,0xff,0xe6,0xca,0x6b,0xfd,0xc8,0x7e,0x12,0x8b,0xaf,0x99,0xbf,0x62,0x68,0xfc,0x09,},"\x1a\x7b\x7f\x3e\x1c\x7c\x41\x49\x2a\x7c\xe7\x99\xef\xdb\x2d\x9d\xc2\xf2\x48\x9c\x84\xae\x28\xbb\x7d\x08\x4f\x32\xec\xa8\xfb\xb0\x66\x88\x5a\xc6\xf2\xef\x74\x49\xe7\x12\x26\xa8\x2e\x9f\x15\x37\x72\xa9\x93\xeb\x6b\x6b\xca\x64\x91\xd2\x6a\xca\x5d\xee\x98\xb7\x7a\x1d\xdc\x59\x92\x2b\x31\x45\xc4\x47\xde\x73\x7f\xaf\xac\xba\x5a\x75\xf2\xa8\x01\x37\xb5\x59\x46\x97\x22\x0d\x19\x61\x76\x74\xa6\x91\x13\xfd\xf7\x7c\x34\x3a\xf2\xb7\xe3\x86\x1b\x5b\x78\x22\xf5\x8d\x60\x08\x9c\x3c\xa5\x4c\x74\x9d\x27\xf8\x83\x79\xc0\x67\x59\x8f\x06\x39\x39\xba\x86\x31\xd1\xf5\x2d\xc9\xab\x45\x50\x45\xfb\x36\x0c\xc2\xa5\xb6\xb0\x12\x7f\xac\xfc\xf5\xb1\xb4\xc3\x3e\x3f\x19\x4f\xc9\x24\xb8\x54\x16\x8c\xb1\x16\x9a\xb1\x09\x97\xb4\x38\xb7\x1c\x80\x87\x83\x47\xbe\x88\x7a\xf4\x48\x10\x13\x4b\x51\x4c\x80\x69\x08\x20\x1a\x3d\x3e\x6d\x0c\x56\x12\x0c\x43\x14\x87\x4d\xc2\x94\x4d\x84\x44\xf0\x1b\xaf\xa3\x4a\xa6\x2e\xce\xf0\x98\x15\x45\xe5\xd0\x2f\x40\x16\xc0\xb1\x64\xfc\x05\xae\x18\xf5\x35\xc3\x1b\xf2\x0b\x86\xf3\x1f\x7a\x79\x4a\xba\x14\x89\x84\xc3\xff\x43\x3d\xc2\x22\xc4\x43\xb5\xd2\x6c\x1f\x66\xe6\xc5\xf1\x9d\x19\xcd\x6e\xad\xd4\xdc\x94\x10\x1b\x2f\x52\xb5\x8c\x9d\x45\x90\xcb\x10\xdb\xc5\xd6\xea\xcd\x11\xd4\x2e\xd0\x9f\x15\xbd\xe4\x4e\xe9\x27\x1d\xef\x29\x2f\x73\x1b\xf3\xb4\xac\x6c\xd1\x27\xe4\x88\x4c\x2c\xb3\x0b\x28\x5f\xc9\x24\x76\x38\xa2\x99\xe4\x16\x52\x06\x24\xd1\xec\x8d\x0d\xf2\x49\x89\x39\xc7\x19\xa9\xe7\xbd\x29\xa3\xc5\xc3\x2a\x3e\x82\x41\x36\x8d\x6e\x4f\x90\xfe\xa2\x9d\xc3\xa3\xf1\x47\xea\x9f\x76\xc5\x78\x0e\x73\x14\x3f\x55\xd3\xde\xc7\xb6\x63\x41\xd3\xf3\xea\xc1\xd9\x8f\x8e\x7d\x4e\x87\x75\x09\xb4\x43\x8c\x3a\x52\x46\x6d\x24\x2a\x10\xb4\xc2\x7c\x4a\x0d\xb9\x23\x2d\xad\x01\x14\x14\xeb\xfb\xd5\x79\x06\xf1\xa4\x10\x20\x7b\x52\x6b\x0d\x1f\x1b\x69\x86\xb3\xeb\xd7\x55\x0a\x2b\x3c\x15\xfc\x24\x09\xc7\x62\x6e\x0d\xd3\x30\xef\x67\x22\xe3\xba\x48\xb1\xd9\x20\x56\x52\xac\x19\x4c\x21\x47\x3c\xe2\x58\x55\x9d\xb5\x11\xef\xad\x3e\x5d\x55\xf2\xa7\x96\xd6\x5a\x6a\xb9\x7d\x86\x31\x06\x2a\x59\x3a\x13\xaa\xa0\x95\xdb\xc9\x3e\x62\x17\xce\xd6\x19\xcb\x16\xa5\x7e\x74\x43\x55\xa1\x6b\x15\xe7\x7d\x49\x79\x11\x92\x99\xbb\x04\x3e\x48\xfa\x3e\x61\x54\x60\xe1\x64\x88\x29\x84\xa2\x23\xd4\x18\xca\x95\x34\x0c\x5b\xfc\xda\x67\x3f\xcd\x13\xb2\x9f\x2c\x47\xd2\xf9\x7e\x3e\x8c\x61\x3b\x6c\x58\xdf\x0e\x62\xcf\x23\x06\x1d\x6f\x54\x5b\x75\x50\x33\xfd\x3d\xc1\x40\x5e\x5f\xef\x35\xa1\x3e\x01\x5f\x98\xb1\xcc\x42\xf7\x1b\x99\x68\x1f\x96\x81\x25\x82\x29\xa4\x47\x3d\x86\xea\xbb\x0c\x17\x92\x79\x41\xe5\x0c\x08\xf3\x4a\x76\xb4\x3b\xcc\x6d\x04\x2e\x56\x32\xef\x9c\xcc\x91\xb6\xe6\x95\x0f\x5d\x30\xf6\x70\xfb\x39\x02\xc3\xd4\x09\x31\x5a\x40\xb0\x82\x1c\xe8\xa9\x9a\x97\xfe\xca\x54\x78\xbf\xd7\x82\xe7\x87\x67\xb3\x11\xf3\x74\x16\x3f\x58\x96\xb0\xbe\xb9\x58\x38\xe6\x45\x87\x8c\x64\x99\x03\x85\x12\x3b\x61\x57\x5d\xd8\x42\xdc\x76\x35\x4b\xac\x9c\x6d\x5a\xcd\x99\x35\xb6\x09\xbc\xcc\xb8\x46\x3d\x39\x22\x5d\xa1\xaf\xb8\x91\x1d\x36\xe6\x09\x89\x2d\xd1\x72\x38\x52\xab\x9f\x82\x75\x8f\x3f\x1e\x4d\x28\xdc\xf0\x2c\xb0\x6e\xed\x26\x84\x4a\xae\x68\x82\xed\x44\xbc\xe4\x4a\xbc\xd1\xdf\xba\x63\x34\x18\xc9\xf1\x55\x87\x9c\x97\xab\x27\xf8\xae\x23\x83\x30\x39\x2b\xe5\x49\x1a\x07\x86\x62\xda\xaa\x02\xa3\xd5\x45\x8b\x77\xc5\x49\xc4\x9b\xe2\x01\x24\x5e\x7a\xae\xc0\xd9\x4e\x54\x37\xbe\xca\x6e\x5a\xb0\x46\xd6\x94\xe9\x6b\xf5\x1e\x04\xfb\x44\x37\x9b\x2b\x9b\x80\x16\x75\xfe\x14\x77\xf3\xe0\x89\x87\x4a\x60\x11\x71\xd8\xb6\x8f\x02\x02\x01\x46\x01\xa5\x3f\x81\x2f\x53\xe5\x81\xc3\xb9\x63\x12\xb3\x6b\x9e\xe0\x4f\xff\x11\xd9\xea\xb4\xe4\x51\x48\xdc\xc8\xf0\xfa\xb1"}, -{{0x8b,0xc2,0x29,0xfc,0x23,0x46,0x53,0xb1,0x3c,0x92,0x47,0x10,0xcb,0x46,0x8b,0x8f,0xa9,0xb2,0x80,0xe2,0xad,0xb4,0x9c,0xb4,0xb3,0x6b,0xf5,0x9d,0x6f,0xa4,0xa6,0x39,},{0x46,0x14,0x69,0x75,0xdf,0x67,0x04,0xcb,0xf4,0x53,0x20,0xa5,0xe6,0xcb,0x6d,0xe8,0x13,0x46,0x9f,0x31,0x31,0xe6,0x1d,0x44,0x7b,0xbc,0xa1,0xa4,0x77,0xa0,0xc5,0x57,},{0xd2,0x43,0xb8,0x7d,0x13,0x97,0xd5,0x94,0x13,0x9d,0x83,0xc3,0x9a,0xcf,0x85,0x01,0xd0,0x73,0xbd,0x4b,0xe7,0x18,0xb4,0xc2,0x06,0x98,0x07,0x29,0xe7,0x20,0xa4,0xc5,0xb0,0xea,0x91,0xa2,0x8e,0xa1,0x26,0x04,0xa9,0x87,0xe6,0x95,0x91,0xc5,0x43,0x04,0x9f,0x29,0x73,0xbb,0x91,0xc1,0x70,0x21,0x3c,0x32,0xa6,0x4a,0x0f,0xac,0x82,0x04,},"\xba\xe2\xdc\x7f\x94\xab\x5c\xcd\xca\xa8\xcf\x49\xed\xbe\xf0\xf6\xd7\xae\xb1\xfa\x89\x07\x80\x05\x33\xaf\x44\x92\x61\x11\x94\xe5\x6c\xef\x37\xb1\xf0\x33\x30\x37\x38\xae\x2c\x3b\xc4\x58\x8f\x5c\xb3\xd5\x5f\x34\x5b\x9a\x40\x7e\x78\x77\x42\xa0\x6a\xf0\xb6\xee\x20\xde\xe3\xdf\xe9\xc9\x1d\x76\x2a\x3e\xbd\x19\xae\xd0\x79\x07\xbb\xb9\x1c\xd7\x76\x32\x65\x40\xde\xd9\xf7\xff\x7d\xda\x76\x61\x5f\x97\x8e\x94\x90\xf4\x06\xed\x2d\x91\x16\xe2\x09\x3f\xa7\x85\xe9\x71\xb5\x06\x2d\x31\xcb\x40\xff\xf9\xe3\xc5\x51\xa7\x3b\x20\x24\x5d\x46\xdf\x4d\x7f\xd1\x30\x3a\x28\x18\x01\x72\xd9\xa2\xbf\x55\x93\xc4\x79\x17\xb5\x86\x90\x91\x7c\x1f\xb0\xe1\xe2\x99\x4d\x1f\xa9\x77\x35\xae\x37\x8d\xe6\xea\xfd\x5c\x1a\x25\xab\xaf\xa3\xcf\xd2\xdf\x7a\xea\xbd\x6e\x68\xfc\x44\xed\xf8\x2f\xc8\x36\x94\xe5\xd8\x41\xa1\x5b\x14\x56\x8b\x61\x10\xbe\x64\x4b\xf2\x2b\x71\xfc\x47\xd7\xf0\x7e\x16\x66\x95\x7d\x0f\x87\xda\x17\xf1\x3f\xcd\x63\xc1\xc2\x96\x6f\x68\x7d\x25\xdc\xbd\x99\x63\xf0\x1e\xff\x13\x2d\x5f\x2b\x86\x67\x78\x16\x58\x8c\x12\x3e\x94\x57\xbe\xfc\xce\xd2\xd3\xcd\x1d\x1b\xeb\xe8\xdd\x8f\xbb\x15\x87\xe5\x53\xcb\xcc\x4c\x87\x62\x06\x4c\xd3\x2e\xf7\xa1\x70\x24\x10\xf7\x7f\x15\x24\x0d\x7e\x2b\xb5\x82\xc6\x78\xc0\xda\x88\xef\x45\x22\x83\x0b\x14\x36\x60\xac\x9c\x43\x4d\x95\x77\x2e\x6e\xee\xed\x60\x14\xae\x16\x82\x4c\xcd\xc4\xdf\x2d\xf6\x4a\xeb\x69\x80\xb5\x1d\x11\x89\x85\xdc\xbb\xd1\x96\x1f\x31\x5e\x6a\x94\x33\xf0\xb9\x6b\x1e\x63\x51\x25\x7e\xad\x83\xe0\x5b\x4c\xc8\x9c\x92\x4b\xf8\x35\x58\xba\x7d\x2e\x7c\xa3\x7c\x03\x17\x9a\x8f\x85\xb8\x31\xe7\x21\x7b\xf4\xc5\x53\x83\x87\x61\xd3\x26\x02\x85\x3b\x81\x59\x3b\x0e\xbf\x8e\x4b\x9f\xfa\xf0\xec\x40\x5b\x2a\x83\xaf\x7d\xe5\x55\x4d\xaa\xd2\x8b\x58\x2e\xe0\x8b\xd8\x4b\x37\x55\x50\xca\xe0\x8a\xe4\xa5\xbd\xa7\x15\x81\xfc\x3b\x7b\x54\x49\x8c\x4e\x1a\xfb\x96\x6b\x4a\xf1\xd9\xc8\x43\xa6\xb2\x5b\x34\xe0\x4c\xfd\x9b\xd2\x37\x42\x44\xf1\xfe\x20\xec\x62\xbe\x3c\xcf\xab\x4e\xde\xf7\x9e\xd6\x4e\x6b\x71\xaa\x92\x28\x12\x7c\x63\x59\xea\x1c\x4a\x80\x87\x89\x08\x96\xff\xa4\x6e\x00\x92\xde\xc7\xef\xbc\x96\x0a\x17\xb7\x70\x91\x6f\x95\x40\x70\x13\x2e\x26\xd9\x8d\x97\x74\xa2\xac\xdf\x80\x9d\x58\x6d\xf0\x25\x2f\x67\xcf\xe8\xd9\x85\xa3\xe2\x48\xdb\x0f\x90\x73\x1a\xce\x7a\xbd\x99\x9c\x74\x6b\x69\x64\x8d\x5c\x3b\x4b\xd6\x11\x37\xe0\x8f\xcc\x8b\x2e\xfc\x56\x76\xbc\xd8\x56\xa1\x3b\x36\x21\x51\x47\x4c\x4a\x1e\xfd\xed\xc5\x92\xcf\x3e\xad\x1a\xba\xbc\xd4\x8e\xe2\x04\xd2\x77\x26\xad\x1b\xda\x4f\xe4\xb0\x9a\xb5\x10\x89\xd0\x16\xde\x6b\xa2\x59\xea\x81\x80\x7f\xaf\x21\x1c\x87\xe4\xc9\xef\xbf\x6a\x4c\x75\x3e\x08\xf7\x80\xed\x55\x33\x8c\x0f\xde\x14\xfb\x99\xb3\x07\x22\xb5\x59\x4b\x3a\xbe\x02\x04\x7f\x46\x62\x42\x42\x1f\xb8\x11\x76\xc9\xc4\xf0\xfd\x2b\x5e\x7c\x5a\x0f\x65\xa0\xc5\x9a\xa8\xc3\xa9\x86\x08\x7d\xe7\xba\x40\xba\xca\x77\xbd\x36\xac\x21\xce\x34\xe9\xfe\x97\xfa\xcc\x4e\x29\x83\x30\xee\xce\x1c\x8e\xc6\x23\xe6\x6a\x4b\x0f\x23\x42\xd2\xc5\xa0\x2c\x5f\x5a\xbd\xdc\x5f\xf1\xf1\xf2\xd0\x3c\x1d\x4e\xe9\xb4\xb3\x42\xed\x3b\x1c\xc2\x65\x61\xf3\x21\x7b\xf8\x50\x0e\x08\xf0\x27\x57\x1c\x53\xc9\x23\x26\x05\xa5\x3f\x2b\xda\x02\x4e\x39\x92\x91\x63\xa8\xe0\x07\x91\xac\x06\x56\xbb\x07\x83\x82\x5e\x71\x05\xff\xa9\xd9\x09\x69\xdc\x09\x4a\xf4\x6f\x70\x2e\x85\xcc\x11\xe4\x42\xb3\xd5\x53\x4c\x1d\x32\x75\x20\x7d\x6d\x29\xa9\x42\xc3\x58\xed\x5f\xa0\x75\x57\xc3\xc0\x14\xcf\x54\x1f\x9a\xae\xea\x60\x25\xb4\x1e\xcd\xd8\x48\x51\x2b\xa2\x5e\x72\x1e\x43\xd3\x29\x18\x5f\x8f\x94\x89\x2e\x9e\x2d\x5e\x7c\xbb\x99\xe7\xad\x25\xf6\x9e\x5b\xef\x73\x2c\xfc\xeb\x07\x86\x11\x55\x3c\xc7\x83\x77\x37\x5e\x74\xe6\x6f\x1b\x9d\x8d\x20"}, -{{0x3e,0xdb,0x50,0xff,0x07,0x4e,0xf9,0x71,0x7f,0x4f,0xb0,0xb6,0xce,0x25,0x2b,0xf4,0xbd,0x04,0x9c,0x90,0x83,0x77,0x5f,0x52,0x9e,0xaf,0x51,0xe9,0x75,0xcb,0x32,0x45,},{0x4b,0xc2,0x1f,0xe0,0x3e,0x67,0x9a,0xbb,0xfc,0xd8,0xc5,0xea,0x2b,0xcc,0x4d,0x83,0x8a,0x78,0x7d,0x48,0x40,0xc3,0xbc,0x39,0xde,0x4b,0x04,0xc4,0x17,0xc7,0x68,0xa5,},{0xde,0xb3,0xd9,0xfc,0x7b,0x2d,0x86,0xab,0x4b,0x92,0x6f,0x99,0x52,0x79,0x70,0xab,0xb5,0x18,0x38,0xbc,0xc2,0x91,0x9e,0x94,0xcd,0xa3,0x37,0x1f,0xd0,0xe7,0x69,0x3f,0xe3,0x7e,0x0c,0x40,0xe1,0x23,0x3b,0x09,0xff,0xa9,0x03,0xa0,0x34,0xdd,0xe2,0x87,0xc0,0x23,0x7d,0xc5,0x94,0xf5,0x3a,0xbc,0x87,0x84,0x48,0x69,0xdc,0xe9,0x20,0x02,},"\x97\x5e\xce\x4e\x81\xf0\x01\x5f\x5a\xc3\x04\x46\x09\xd0\xac\x3a\x8d\xf9\x14\x5b\x50\xc4\x28\x89\xdd\x31\x2f\x56\x3c\xf6\x12\x6e\x36\xff\xfa\xf2\x1e\xb6\xb8\x4f\xbd\xa1\x5a\xa8\x5c\x66\x14\x5f\x75\x41\xe5\xb4\x1a\x8e\x81\x70\x0b\xe3\x56\x22\x4f\xc1\x09\x32\x7a\x69\x19\x66\x56\x73\x53\x4f\x5c\x8a\x4a\x00\x17\x50\xb1\x99\xdb\xfd\x63\x06\x91\xaf\x55\x2d\x4d\x26\xa9\xd9\xaf\xb3\x3a\x16\xaf\x39\x11\x54\x12\x4b\x53\x42\x6c\x9f\x69\x50\x57\xb1\x81\x4f\xd6\xd3\x10\x29\x8a\xf6\xc8\x30\x68\x6a\x4a\x00\x7a\x14\xe0\x05\x7b\x72\xfb\xad\x5b\x80\x3a\xd3\x53\xd1\xc3\xfd\xb8\x90\xa9\xc8\x18\x08\xe8\x9f\x22\x91\x87\xbc\xb4\x4f\xee\x16\xa4\xeb\xca\xd5\xeb\xa4\x59\xb0\x28\x27\x2a\x56\x2c\x05\x07\x9f\xa7\xae\x3e\xca\xe8\x04\xa9\xe8\xc4\xf3\xf3\x15\x81\x3c\x5e\xe0\x84\x1b\xbc\xcf\xe4\xa9\x56\x23\xb5\x17\xa4\xb4\x2b\x2c\x6d\x97\xa3\xbf\x26\xac\xdb\xe2\xe9\x79\x63\x3f\x02\xaa\xc4\x66\x52\x6a\x3e\xbb\x14\xda\x19\xbc\x95\xf2\xc3\xfd\xf6\xbd\xb0\x8b\xe8\xbd\xe9\x7a\x86\x4c\x90\x7e\x91\x8c\x67\x9a\xb7\x26\xf8\x01\x77\x14\x58\x40\x21\x6b\x9d\xc3\xf9\x81\xef\x17\x87\x4f\x08\xb2\xfc\x66\x11\xa6\x34\x6c\x3d\xa6\xa5\x5e\xcf\xa7\x53\xc9\x91\x9f\x4f\x19\xe3\xc7\x90\x93\xbf\xd7\x8f\x86\x15\x98\xe4\x66\x6e\x1c\xab\x68\x8e\x46\x04\xd4\x6c\x9c\x58\x2e\xad\xb9\x2c\x98\x8f\x47\x8d\x16\x0f\x5a\x15\x18\x2b\x33\x40\x20\x17\x97\xd0\xb9\x55\x28\x2e\x4a\x21\x7b\x50\xb1\x4b\x10\xc9\xf4\x90\x67\xea\x3e\x84\xe5\x27\x4d\xca\xec\x74\x47\x4c\x57\x07\xc2\x8b\xba\x0d\xb8\xcd\xe3\xe8\x38\xd7\x31\x3c\x17\x1b\x85\xff\x2b\x9a\x3d\x2b\x16\x7e\x90\x61\xf8\x4d\xf3\xb1\x3b\xdd\x08\xb2\xd5\x01\xe5\x37\x92\xd6\x80\x54\xd0\x48\xab\xfe\x3b\xce\x98\xd9\x78\x25\x6f\x2f\xd2\xc6\xc4\xe7\x6f\x39\x68\x8c\xcc\xf0\xfe\x14\x9a\xf9\xd3\x47\xe7\xb0\x40\xef\x24\x1d\xd5\xa5\x3e\xaa\x5e\xab\x35\xa1\x8c\x68\xc7\x54\xa0\x6b\x03\x39\x9b\xbe\x56\xa2\x52\x68\xc8\x29\xa5\xba\x82\xb2\x81\x92\x04\x1d\x3b\xd2\x44\xeb\x08\xbf\x78\xe7\x6d\xef\x87\xcd\x09\xf3\x2b\xea\xc9\xbb\x63\x98\x23\xb3\x69\x67\xa5\x74\xd8\x96\x0d\x1b\xd0\x34\x35\x67\x9d\x93\xed\xdc\x55\x80\x63\xc5\x40\xb9\xc2\xf6\x09\xfe\xd2\xe2\xe3\x57\x6d\x19\xe6\x20\x9e\xab\x46\x6c\x20\x67\x91\xc3\xaa\x19\x96\x23\xfb\xae\x7d\x34\x97\xe8\x0f\xdd\x3f\xcb\xaf\x5b\x89\x11\x0e\xd7\x22\x44\x23\x4b\xe8\x5c\xca\x4b\x27\xa0\x9b\xb7\x0a\x26\xec\xe4\xeb\x8d\xd9\x70\xa2\x6e\x5b\x04\x36\x1f\xa5\x0e\x90\x38\x0e\xd6\x5f\x41\x4c\x1b\xe9\xf5\x06\x4f\x71\x42\x91\x16\x26\x7e\xdd\x69\x76\x42\x2a\xd9\x2d\xeb\x2b\x80\x4a\x92\xe8\x1c\x9f\x65\x22\xa0\xf3\xb5\xd8\xad\x36\xb4\xf8\x7d\xb5\x16\xa2\x28\x73\xe6\xf2\x72\x84\xf2\xca\x36\x0a\x2f\x40\xff\x3d\x8e\x23\xde\xc8\xef\x8a\x17\xa4\x3a\xcb\xb6\x12\x71\xa7\x27\xcb\x86\x90\xd2\x9b\xb8\x20\x16\x73\x6b\x31\x02\x62\x01\xdd\x3d\x38\x8d\x2c\x64\x3a\x73\xcf\xbd\x0a\x94\xe2\x05\x51\xfb\x5f\x8e\x1f\xfc\x39\x74\x12\x72\xaa\x23\x08\xdc\x8d\x21\x33\xa3\xfa\x9c\xf1\x09\x79\x6d\x69\xd2\xcc\x8a\xdd\xc4\x4a\xe2\x52\x77\x81\xee\x99\x3a\xf2\xa6\x37\xa8\x72\xf0\x2a\xff\x47\x4a\x70\x73\xf2\x9d\x9c\x89\x50\x77\x01\xfe\xcb\xbf\xd5\x10\x13\x53\x53\x7e\xba\x17\xc2\x96\x69\xda\xc0\x42\x7e\x38\xe2\x2d\xfa\xac\x91\xfc\x20\xd9\xe3\xfe\xe7\x91\xf4\x62\xa8\x63\xbb\x19\x08\xfb\x1e\x42\x04\xb6\x88\x80\x31\x4d\xda\xca\xaa\x35\xa1\x7a\xf5\xf5\x7a\x39\x9f\x19\x31\xe7\x8f\x5a\x37\x45\x4f\xd3\x8c\x57\xa6\x8e\x8d\x36\x78\x48\xa9\x73\x45\x18\x9c\x70\x07\x7f\xd1\xaa\x07\x54\xe7\x03\xe3\x52\x61\x80\x63\xb9\xe3\xfa\xf3\xb1\x4b\x5f\x0b\x27\x11\x36\x33\xc5\xd1\x73\x63\x74\x1e\x96\xa6\x7e\x81\x64\x01\xe8\x09\x8c\x17\xbf\xfe\x9c\x6f\x35\x87\x64\x6f\x40\xe9\xfd\xb6\x81\x9f\xd2\x2a\x74\x3a\x7a\x6e\x10\xfe\xba\x11"}, -{{0xcd,0xa4,0xba,0x93,0x94,0x0a,0xa0,0xc0,0xc3,0x15,0x0b,0x39,0x29,0xb9,0x5e,0xe7,0x76,0x9c,0xe4,0x3f,0xd9,0x8e,0xca,0xff,0x9c,0x4a,0x50,0x9e,0x73,0x6d,0x5c,0x8e,},{0xf4,0xc7,0xa2,0x5f,0x1a,0x74,0x3d,0xaf,0x41,0x41,0x7e,0x47,0xe0,0x27,0x53,0x7f,0x24,0xf4,0x81,0xbd,0x1a,0x75,0xe6,0xb1,0xd3,0x3e,0xc4,0xc8,0x2c,0x55,0xa2,0xd3,},{0x31,0x04,0x8d,0x33,0x4a,0xf0,0x5a,0x4f,0x27,0x5f,0xf8,0x27,0x54,0x4e,0xa2,0x96,0xa4,0xa7,0x75,0xfa,0x59,0xef,0xa0,0x00,0xc5,0x76,0x13,0xfa,0x6e,0x5c,0x49,0x3c,0x3a,0x9b,0x79,0xe8,0xce,0x56,0xe7,0x22,0x5b,0x0f,0xa3,0x26,0x20,0x4f,0x03,0x36,0xc2,0x13,0x53,0x5a,0xe5,0x89,0x17,0x7a,0x8e,0xae,0xdb,0x6d,0xf8,0xb2,0x02,0x03,},"\x3a\x1d\x66\x8c\x66\x88\x41\x48\x96\xa7\x69\x7f\x3c\x2e\x43\x10\x98\xed\xfc\x45\x7e\x04\xd2\xda\x86\x95\x68\xad\x5b\x33\x10\xe5\x9e\x4c\x72\x7c\x90\x3c\xbf\x18\x17\x40\x88\x02\x31\x9a\x8c\x23\x1b\x58\x02\x3d\xfa\xe4\x94\xc0\x13\xaf\x0f\xdb\x78\xc9\x1d\x5b\x45\x7f\x8c\x47\xa3\xdc\x31\xd8\xc8\x59\x4a\xa0\x8f\x14\x62\x03\xfa\x2c\x28\xb3\xdd\x79\x6a\x11\xa9\x7a\xde\xde\x6a\x7a\x70\x9b\x5a\x19\x18\xef\x1b\xea\x83\x53\x3c\x78\x34\x73\x70\x33\x56\xf5\xbe\xea\x7f\xd1\x8a\xc4\x4e\xc6\x89\x04\x95\xed\x17\x0d\x03\xf1\x5b\x41\x86\x08\xa7\xd9\xef\xd5\x2f\xa1\x09\x18\x63\x80\x51\xc4\x48\xd9\x8d\x57\x24\xf5\x67\xc8\xc6\x7f\xd5\xb6\xec\x8c\x3d\x63\x60\x08\xb9\xba\xe5\xe8\xb1\xe9\x84\xf8\xff\xb8\xb6\x4b\xee\xbd\x63\x45\xa1\x05\xc1\xc1\x08\x31\x32\xfd\x45\x08\xd6\xac\x0d\x4e\x91\x45\x50\x12\x10\xe5\x17\xd9\xb2\x24\x78\xe2\x15\xb6\x02\x59\x9f\x80\x37\x62\xdc\xd5\xa4\x09\xb3\x46\x0e\x7f\x34\x0f\x47\xef\x77\x28\x1a\xd2\x38\x3d\xe0\x8c\x5b\x80\x95\x38\xaa\xec\x92\x2b\xfc\xa0\xd6\x75\x2f\x14\x79\x72\x64\x6d\x0a\x8d\x83\x40\x77\x2c\x87\x1d\x3b\x34\xab\xc0\x60\x37\xde\x3a\xb4\xe3\x71\x29\x86\x5d\x5b\xa7\x0b\x6f\x3c\xc9\xa0\x59\xef\xb7\xdd\xdc\x38\x82\xf4\xfc\xfe\x13\xf4\x48\xc9\xbc\x66\x48\x88\x58\x96\x03\xba\x98\x68\x3a\x93\xb4\xb3\xb1\x01\x49\x92\xa5\x5c\x8e\x4e\xa1\xba\xf9\xcc\x00\xd1\xba\xdf\xf5\xfd\x7f\x5d\xa5\xe3\x07\xfb\xd1\xb4\xc9\x84\xe0\xfa\x0e\xde\xc5\xd3\x0b\xfe\xf5\xf4\x77\x30\x12\x63\xb5\xd7\x52\x00\x1b\x85\xdd\x52\xdf\x3b\x4a\x7a\xc2\x3b\x93\x0a\x91\xc0\xa4\x57\x65\xa6\x64\x88\xd8\xeb\x59\x01\x85\x70\x60\x06\x7b\x82\x37\x81\x88\x54\x92\x88\xdd\xc6\x18\x31\xe5\xb6\x84\x1b\x34\x4c\xae\x22\x50\x04\x22\x19\xcf\xb4\xac\xe0\x23\xe6\x91\xf9\xe4\x8d\x00\x6e\x9a\x07\xc6\x7d\x24\x68\xf9\x35\x93\xb4\xaf\xc1\x61\xc0\x76\x8b\x6c\xeb\x74\x4c\x24\xc9\x23\xda\x34\xaf\x3d\x5e\xd5\x77\xcc\x7f\x85\xd4\x91\x56\x0f\x4c\x0b\xcb\xcd\x1d\x5e\x34\x21\xbd\x1c\xcf\xaf\xb3\x73\xd6\x51\xbd\x61\xed\x71\xc0\x9e\x99\xf6\x12\x00\x17\x04\xd0\xc6\x30\xd8\x54\x7b\xd9\x70\xb6\x6e\x7f\x5c\xe7\xa0\x14\xe0\xff\x5a\x33\x7d\xc5\xc5\x6a\x99\xf1\x31\xb9\x12\x91\x40\xee\xea\x39\x39\x7c\x48\xca\xa9\xa8\x08\x6f\x9f\xd9\x91\x50\xbe\x7e\xf8\x7b\x6d\x4b\x94\xb1\xbd\x52\x87\x8b\xf3\xbb\xfc\xce\xac\xc2\xcc\x45\xe8\x97\x1c\x3a\x4d\x4a\x3e\xb8\x6a\xf9\x87\x4d\x4f\xa5\xe7\xca\xa7\xf4\x5d\x15\x53\xff\xbb\x41\x64\x5b\xf0\xf5\xe9\xb2\x97\x72\xe3\xdc\x08\x1b\x25\xb5\x2e\x1c\xb7\xe2\x16\x74\x83\xd5\x4f\xba\x69\x0d\xdb\x29\xd5\x46\x2d\x2a\x27\xa3\x5d\x85\xf0\x07\xad\xed\xe2\xa3\xdd\x72\x81\xf6\x54\x33\x6a\xfa\xfb\x73\x70\x78\x2b\x29\xca\xd6\x43\xd9\xd9\xdb\x2f\x05\xf2\x81\xb5\x3e\x13\x3e\xc3\x0e\xec\x09\xfb\x0d\x06\x1b\x74\x58\x1a\x2b\xd2\x79\x0b\x13\x73\x91\xf1\x93\x28\x88\x0f\x64\xc5\x3b\xe7\x00\xd0\xfa\xdd\xb7\x0d\xc1\x65\xd2\xd6\x2e\x67\x1e\xb9\x44\x9a\x2e\x6e\x9d\xf2\xc1\x6d\x8f\x49\xfa\x4b\x5b\x84\x30\x9f\x73\x35\x13\x3d\xbe\x87\x2c\x5a\x8f\xdc\xfb\xc4\x98\x0a\xbf\xb3\xc9\x59\x7d\x5d\x66\x7a\xd2\xf6\x88\xc7\xab\x24\xc9\xe4\x40\x29\x8d\x72\xb2\x8b\x0f\xcd\xe9\xc6\xf0\x71\xbc\xcc\x93\xe8\xdd\xbb\xa7\xb6\x0a\x0b\x54\x4a\x2e\x06\xc3\x9c\x67\x23\xd4\xf7\xdc\x18\x5c\x21\x13\x5f\xd1\x3a\x72\x77\x0b\x97\x61\x19\xe4\x9a\x1f\x81\xed\x47\x6b\xe0\x7c\x44\x3d\xe0\xb0\xee\x76\xfb\xd9\x19\x38\x93\x28\xb3\xeb\x86\x07\xbc\x2f\xe3\x8f\x85\x74\x5e\x28\xad\xb7\x48\x2b\x70\x1c\xcc\x66\x90\xe4\xae\x5a\x93\x32\xea\x44\x61\x31\x79\x38\x7d\xc6\xfc\x47\xc1\xd1\xec\x36\x60\x35\xe9\x91\xe1\x40\x43\x23\xbd\xbb\xf5\x35\xf1\xc3\x3c\xf5\x7b\x67\x23\xf1\x3c\xa6\xca\x32\x9e\x2a\xaa\x4b\x46\xb4\x26\x07\x33\x99\x06\xc7\xef\x49\xb3\x2d\xb8\x2c\xdf\x6a\x87\xad"}, -{{0x21,0x7e,0xcd,0x6a,0x7f,0xcc,0x98,0x71,0x92,0x10,0xc3,0x4c,0xc2,0xe1,0x4f,0x5e,0x2d,0x6b,0x5a,0x22,0xf2,0x68,0xc1,0x4b,0xc4,0xd8,0xa7,0xf2,0x81,0x72,0x00,0xc3,},{0xd5,0x91,0x91,0xce,0x28,0x2d,0x72,0xfe,0x3a,0xc4,0x58,0x78,0xe2,0x4b,0xb2,0xf2,0x8c,0x40,0x9b,0xa0,0x5d,0x76,0xce,0x9b,0xcf,0x22,0xf5,0x0b,0x0c,0x77,0x86,0x75,},{0xa0,0xb1,0x69,0xe8,0xe9,0xce,0x55,0x75,0x55,0xe0,0x33,0x4a,0x0d,0xe7,0x43,0x8e,0x55,0x36,0x75,0x48,0x9e,0xa4,0xba,0x9c,0xc6,0x3a,0x23,0x4d,0x00,0xde,0xd8,0xab,0x69,0x67,0xa3,0xbe,0x90,0xef,0x69,0xe0,0x76,0xdb,0x9e,0xa3,0xd5,0xca,0x23,0xb3,0x24,0x8d,0xd2,0x59,0x91,0xee,0x1f,0x4d,0x80,0x62,0x0b,0xf4,0xdb,0x43,0x8f,0x0e,},"\x9b\x53\x37\xe7\x8f\xb3\x82\xf2\x2e\xa6\x0e\x03\xc0\xbf\x3e\xe4\x70\x0b\x69\x78\xa9\x1e\xe6\xac\xdf\x6a\x40\x9e\x49\x18\xd1\x68\x48\x81\xfa\x1d\x11\x8c\x08\xc9\xf6\xf2\xca\x0c\xab\x56\x74\x02\xc9\x50\x10\xe7\xab\xdf\xe8\x48\xae\x79\xba\x24\x9a\xdc\xb9\x6e\xae\x1d\xfa\x08\x43\x95\x21\x39\xcf\x49\xb5\x88\x64\x78\x95\x69\x1a\x2e\x98\x80\x46\x6b\x7e\x77\xe5\x4f\x6f\x60\x81\x5e\xbf\xd5\xe5\x74\x8f\x41\x3c\x0e\x15\xf9\xd5\x76\x79\x9b\xcf\x31\x28\x47\x10\x63\x6f\x6e\x9d\xc7\x87\x85\x00\x79\x6e\xed\x80\xc8\xaf\x4b\xe2\x96\x19\x52\xea\x80\xbb\xed\x14\x04\xbd\x5d\xae\x9e\x6d\x05\xfd\x4f\x32\x5a\x3b\x83\xcd\x45\x28\xa0\x86\x9c\xef\x84\xb4\xd3\x0e\x02\xf9\x41\xd7\x49\xa8\xda\xc9\x7b\xb3\xfa\x83\x9d\x25\x73\x9b\x97\xec\x37\x45\x36\xbd\xea\x50\x04\x84\xa9\x41\xdb\x9f\x22\x99\x97\x06\x58\xd4\x11\x48\x29\x5c\xa0\x84\x6c\xa2\x36\x62\x38\xb6\x20\x1a\x48\xb3\xe4\x47\xed\xbe\xa7\xa4\xc8\xf7\x10\x20\x14\x27\x69\xe1\x5f\xa7\x2a\xe5\xf2\x87\x14\x0b\xc5\x95\x3b\x8a\x9a\x24\x2d\x20\x5f\xc0\x19\x09\x1f\x2a\xbe\xd0\xfd\xa4\x7f\x52\xd5\x9a\x02\x04\xce\x74\x01\xc1\x82\x9b\x58\x57\xb9\xa0\x91\x6f\xce\xbe\x2e\xef\x99\x1c\x41\x3a\xcd\x71\xb1\x8d\x85\x90\xd6\xb6\xd0\xfb\x39\x94\x30\x26\x78\xc2\x9f\x2b\x6a\x53\x02\x3f\x91\x87\xe4\x6c\x36\x79\x0b\xce\x73\x87\x3c\x54\x5a\x72\xbe\xb5\x53\x29\x4b\x1e\xe5\xd0\xd0\xdf\xf2\x39\xe2\x8e\xc6\x3b\x01\xe4\xd8\xfe\x0d\x6e\x69\xb1\x60\x1e\xfa\x24\x11\xf0\xc0\x60\x1e\x7e\x4f\x65\xc9\x84\xf8\x29\xf0\xdc\x2a\x84\x21\xe7\xf6\x6d\x93\x30\x53\x71\x51\xc7\x24\x3c\xa5\x24\xd7\xa5\x47\x35\xc6\xe3\x44\xf1\xfc\x93\x8e\xae\xea\x27\x79\xc9\x40\x89\x1d\x6d\x01\xaa\x55\xf4\x0c\xc1\xad\xba\x12\xe8\xa6\x7a\xd9\xa2\x7f\xe6\x3f\xb4\xf3\x8d\xc0\xf0\x18\x41\x92\x57\x18\x42\x72\x55\xbd\x66\x5d\x5e\xb3\xbc\x86\x98\x96\xdb\x86\x25\x20\x4a\xd4\xb0\x2f\x5a\x22\xaa\xee\xad\x6e\x30\x04\x71\xfe\xa6\x1d\xbb\x1b\x55\xc0\x71\x36\x5c\x58\xb1\x51\x1f\x38\xb0\x9a\x46\x71\xbd\x66\xb3\xfe\xdd\xa9\xc8\x7e\x43\xd1\xeb\xf3\x01\x76\x4e\x18\xfc\x0c\xf1\x6b\x2d\x2d\x67\xed\x23\x9b\x39\x3a\xc7\x19\x68\xa9\x03\xc0\x24\x77\xfb\x2d\xf9\xef\x01\xdb\xfc\x31\x67\xde\x72\x65\xf8\x91\xe4\xfd\x24\xd0\x2c\x63\x10\x35\x19\xb8\x6a\x70\x85\xb1\xec\x2f\xb4\x19\xdb\x76\x6b\xee\x7a\x64\x1a\x4b\xe4\x29\x61\x4a\xb8\x9f\x20\xf9\x75\x34\x10\x72\xbf\x04\x41\x9f\xb6\x9b\xe7\xa9\xee\x71\xa5\xb4\x9a\xf8\x3e\xd3\x22\xba\xc6\x8a\x42\x9f\xf5\xc5\x20\x67\x73\xbe\x54\x38\xb6\x5e\x53\xf6\x09\x72\x9f\x4f\x6a\x21\xc1\x33\x39\x11\x26\x4d\x63\x92\x70\x17\xe8\x13\x6b\x47\x25\xcd\x1c\xc9\x64\xe0\x8c\xa0\x93\x3a\x56\x1e\x7e\x3f\x59\x87\x76\x83\x30\xe2\xe5\x4f\x8d\x72\x8f\x59\xed\xfe\x2c\x91\xc4\xf9\x9a\xef\x97\xd1\x85\x59\x19\x5a\x3d\x8e\xb3\x15\xdf\xf9\x6f\xe2\x76\xda\x71\x37\xef\xf9\x30\x57\xac\x73\x1e\x06\xa6\x0a\x58\xbd\x8a\x9a\xe8\xc7\xcb\xaf\xf0\xcb\x33\x72\xc6\x8d\xaa\x17\x5c\x42\x8d\x52\xf1\x07\x3a\x38\xbf\x29\x46\x5d\x2a\x71\x28\xbb\x40\x07\x40\x06\xed\xcb\x72\x5a\x83\x1d\x81\x28\x64\xef\x43\xf3\xb8\x66\x7c\x9f\xb7\x10\x93\xa1\x67\x30\x49\xde\xc0\x5e\x09\x16\x9d\x86\xfe\xe9\x2d\xf2\x86\x00\x8a\xd9\x90\x65\xa2\x92\x97\x97\xa9\x13\xd0\x23\x3f\x4d\x1a\x95\xa2\x20\xbd\x91\xc1\x1d\xd9\xc4\x56\x85\xdc\xad\x38\x57\x80\xa0\xc4\x8b\x9c\x4a\xd2\xd6\x63\x03\xe8\xde\x4a\xf1\xdb\x3c\x04\xe4\xa3\xdd\x42\x19\xfe\x77\x3f\x83\xa8\x92\x4b\x0f\xcb\xff\xfc\xf2\x64\xab\xce\x32\x83\x29\x24\x03\x6b\xfa\xbb\xa6\x54\x6b\x1d\xf4\xe3\xf7\x88\xed\x8a\xd5\xc2\xcd\x92\xb2\x64\x1b\x47\x09\x0a\x10\x3c\xf5\xbd\xc4\x6d\x8b\x21\x43\x17\x47\x57\xda\x80\x1c\x36\x0a\x7a\xa1\x07\xfa\xc6\x54\xb3\x4c\x86\x0b\xd5\x4f\x76\xbb\xf4\x3c\x48\x47\x8d\xf4\xfe\x7a\xa5\x9c\xf9\x1d"}, -{{0x08,0xd1,0xd0,0x6f,0x3e,0xc2,0x9e,0xb5,0x22,0x93,0x90,0x7b,0x70,0x5e,0xc5,0x6c,0x5a,0xb3,0x54,0xfb,0x78,0x67,0x37,0x73,0xae,0x61,0x25,0x30,0x94,0xb8,0x9e,0x82,},{0xc1,0xb9,0x9a,0x87,0xad,0x15,0xbd,0x46,0xf6,0xc8,0x48,0x45,0x2a,0xf0,0xfa,0x3c,0xcc,0xcb,0x5c,0xdf,0x6e,0x34,0x8d,0x81,0x6e,0x36,0xc5,0xd0,0xfc,0xa6,0x6e,0x66,},{0x0b,0x8e,0xdc,0xb8,0xb1,0x5a,0x8c,0xd0,0x74,0xc4,0x1d,0xc2,0xa1,0xba,0x29,0xd9,0x64,0x8d,0x6a,0xcb,0xdc,0x33,0x83,0x14,0x70,0x7e,0xca,0x6f,0xb4,0x71,0x4c,0x99,0x54,0x3b,0x49,0x07,0xb9,0xf8,0x5e,0x57,0xee,0xcf,0xfe,0x0f,0x7a,0x6b,0x70,0x73,0xa8,0x09,0x46,0xf8,0x08,0x75,0x53,0xf4,0x68,0x31,0x09,0x27,0x3a,0x60,0x4a,0x08,},"\x12\x0b\x35\x57\x3c\x34\x91\x4b\x37\x30\x51\x88\x0d\xa2\x7e\xd2\x41\x37\x7f\x0e\x78\x97\x2c\x98\xd0\xfa\xeb\xaa\x76\x7e\xb7\xa7\xc7\xe7\xc6\xfc\x34\x05\xa4\x33\x6e\xf9\x5b\xc5\xda\x92\x25\xbb\xd0\x9e\x9e\x11\xf2\xa1\xbf\x14\x2a\xf4\xe8\xa0\xf9\x24\xd3\x23\xdd\x5a\x49\xdf\xe5\x84\xf0\x90\x43\x9c\x08\xe5\x15\x11\x34\x4d\x47\x0c\x62\x00\xac\x7e\x7c\xa1\x50\xd0\x88\xa9\x1e\x47\xc4\xc9\xff\x74\xe3\x8a\x42\xa3\x32\x15\x5d\x81\x52\xae\x4a\xbd\x11\x61\xad\xca\x93\x4c\x23\x4c\xe4\x60\xaf\x87\x89\xe5\x3f\x10\x9d\x7d\x31\xee\xde\x0a\x90\x9b\xd1\x93\xfc\x8d\x3c\x2c\xfe\xc1\x0b\x14\x3c\x31\x47\x67\x11\xbb\xec\x27\xe1\x96\xa5\x49\x85\xbc\x34\x71\x67\xac\xd2\x33\x50\x88\x27\xba\xd3\x6e\x54\x8c\x88\x06\x42\xb8\x6a\x28\xc6\xd3\x40\x4b\x51\x1d\xa2\x4f\x11\xdf\xaf\x6a\x8f\x46\xdd\xcb\xc9\xde\x9e\x39\x15\x97\x66\x9b\xdd\xfc\xa6\x56\x0f\x91\xac\xd3\x45\x9f\x32\x9b\xb0\x71\xdd\x80\xda\xdf\x35\xf0\xe5\x0d\xf5\xb1\x0f\x88\xd2\x67\xac\x9d\x30\x62\x33\x0d\xd9\x9a\x6b\xcf\xa1\x31\x87\xf4\x5c\x0c\x21\x4d\xcd\xe2\xcd\xf9\xc3\xba\x4d\x59\xe6\x33\xa3\x54\xa4\xe2\x77\xc6\x77\xbb\xdf\xa2\x41\x91\x17\x9c\xbc\xaf\x05\xa1\x0d\x40\x78\xd8\xad\xd9\x3b\xc9\xed\x8f\x6c\x6c\x49\x97\x57\x40\x36\x55\x34\x1f\x90\x4e\x37\xd9\x27\x75\x0c\x69\x9c\x26\x9d\xc9\x0d\xc2\x6d\x00\x56\x25\xc3\xf4\x12\x4b\xff\x66\xfe\xca\x59\xd4\xab\xff\x41\x72\xba\x3d\xf4\x5a\x87\x43\x02\x23\x10\x30\xfa\x78\x33\x84\xf5\x09\x99\xe3\xc4\xba\xa5\xea\xdb\x45\x14\x52\xc8\x88\xb5\x19\x27\x2e\x90\xf7\x3c\x68\x72\x76\x8e\x0d\xe2\x0e\xe2\xe5\xf9\x50\x2f\x35\xe4\x9f\xec\xc2\x8b\x75\x20\x18\x87\xfe\xd2\x81\x8e\xff\x54\x53\x98\x39\x2f\x5e\x5b\x68\x76\xbc\x55\x6a\xc1\x3a\x19\x03\xad\xa1\xb9\xd7\x25\xb0\x4a\x14\x20\x4b\x59\x9e\xc3\x3d\x62\xb7\xdc\xae\xea\x8c\x52\x87\x7b\x2c\xfd\xc3\x55\x8a\x91\xd2\xc9\x15\x75\x00\xa3\xbb\x6d\x45\x2e\x5e\x2f\xf0\x93\x29\x4f\xc4\x33\xcb\xd6\x34\x65\xbb\x19\x13\x07\xed\x80\x1a\x15\xb8\x5d\xc2\xff\x0b\xb3\x83\x12\xf8\xb8\x17\xa4\x36\xd4\x22\xcf\x46\x07\xc6\x4e\xe7\x03\x59\x23\xdb\x6b\x96\xa3\x89\x99\x10\x14\x9b\x0d\xa4\xaa\x3e\x96\x68\x5d\x71\x63\xaa\xcf\x9e\x61\x9d\xc6\x08\x13\xce\x4f\x34\x4f\x30\x79\xb4\x3f\x18\x7f\xa3\x1b\xda\xcb\x9a\x1d\x77\x20\xb9\x39\xd5\xbd\x24\x1b\x96\xa1\x77\xd7\xb7\x76\x8f\xfe\xbf\x79\x04\x4c\xd2\x95\x6d\x6f\x88\xdb\x1c\x24\x3a\x10\xfe\xde\x68\x14\x85\x2c\xf4\x04\xb2\xcd\xcf\xa7\x74\x07\x6d\xc1\x25\xc7\x0a\x57\xc6\x90\x7e\x99\xaf\xe3\x96\x22\xae\x11\xf5\x57\xe7\xd3\x4b\x39\xaa\xaf\x45\xf8\x34\x05\x8d\x2f\xe5\xf1\x5b\x5e\xb7\x0a\xc1\x5a\x90\xa3\xde\x58\x50\xab\x1d\xcb\x48\xb0\x6b\x6c\xca\xa4\xb4\x2f\x85\x7e\x71\xec\x00\xb8\xa3\xd8\x97\x4b\x0b\xea\x68\xfa\x0f\x66\x55\x92\x11\x5b\x4f\xa5\x55\x72\xcf\x0b\x07\x38\x64\x1f\xc8\x68\xd4\xa2\xe7\x14\xdb\x3a\xd7\x21\x9a\x82\x3d\x54\xb7\xf7\xc2\x65\x6b\xa5\xc5\xee\xbe\x35\x94\xc7\xdb\x12\x29\x8c\x16\x25\x1d\x98\x45\xbf\x2f\x78\x00\xb4\x19\x0b\x74\x6e\x21\xb0\xc1\xa5\xc4\x7a\x3d\xf9\xa0\x59\xce\x09\x56\x67\x4e\xb7\x03\xde\xcb\x0a\x00\x45\x43\x7d\xa4\xda\x10\xf2\x86\xd7\x20\xd1\xb9\xdf\x05\xfb\x24\x41\x5d\x68\xe0\x65\x57\x0e\x6b\x31\x50\x31\x42\xd0\x33\x35\xa8\x07\xbd\xca\x30\x89\x2e\xdb\x5f\x55\xf8\x98\x9d\x9e\x64\x96\x59\xc0\x74\x4c\x54\x33\xbf\xb4\xde\xeb\x11\xc2\x62\x6a\x86\x50\xe5\x4d\x4d\x39\x8b\xa1\x9b\x64\xf6\x8b\xed\x06\xd7\xfc\x40\x8f\x47\x0a\xc7\x04\xe2\xac\x92\x2a\xc1\x41\x1f\xee\x24\x54\x3e\x56\xf2\xf5\x0b\x6b\x08\x95\x3d\xc5\x6a\x7a\x75\xed\xae\x43\x0a\x6d\xf2\x8a\x22\x7a\xda\xc9\x1b\xa2\x6f\x0e\x19\x85\x95\x32\x77\x39\xcb\xa3\x03\xe9\xaa\x39\x3e\xa6\x61\x8a\x84\xf8\xf5\x03\xd0\x05\x6e\xe8\xd8\x7e\x37\x96\xe0\x36\xcc\x51\xcc\xb7\x91\xde\xb7\x95"}, -{{0xf0,0xc8,0x5c,0x76,0xb1,0x53,0x2e,0x89,0xae,0xa9,0x75,0x15,0x6d,0xdd,0xb1,0xd3,0xd0,0x66,0xf6,0x40,0x9f,0x84,0x1b,0xb4,0x41,0x09,0x22,0x72,0x5f,0x26,0x9d,0x86,},{0xfd,0x75,0xfc,0x75,0xc3,0x6f,0x83,0x49,0x8d,0x8f,0x08,0x27,0xf0,0x1d,0x3b,0x45,0x7f,0x8b,0xc4,0xd9,0xdc,0x55,0xe4,0xa4,0x62,0x74,0xdd,0xf0,0x03,0x4f,0xe1,0x6f,},{0x42,0x18,0xfe,0x4c,0x1d,0xce,0x79,0x5c,0xa9,0x2a,0x49,0xa6,0xf4,0x79,0x8e,0xb5,0x41,0x2d,0xc8,0x25,0x86,0x03,0x14,0xec,0x46,0x9f,0xed,0x45,0xde,0x3a,0x7b,0xf8,0xea,0x55,0xe8,0x53,0xa3,0x49,0x58,0x4b,0xd9,0x5a,0x82,0x6a,0x58,0x5a,0x50,0x3f,0xd5,0x0b,0xfe,0x4c,0x63,0x5e,0xf1,0x83,0xd0,0x73,0x01,0x36,0x7e,0x90,0x10,0x0a,},"\xae\x2e\xb0\x18\xd4\x8d\xbd\x4f\x21\x0b\x16\x77\x8b\x5b\xd2\xfd\x14\xc9\x4e\x6b\xbf\x2b\x3f\xf8\x55\x18\xe5\x60\xab\x8d\x3e\x72\x20\x1f\x43\x34\x20\xf0\x0f\x11\xbc\x78\xe0\xe9\xf3\x72\x08\x75\xb2\xe9\xdc\x11\xe0\x43\x25\xb8\xb3\xf0\xd4\x65\xdd\xab\x21\x51\x1c\x45\x7d\x6a\xca\xd8\xf2\xfd\x5f\xdc\x0d\x28\x23\xfe\x6c\xaa\x66\xa1\x91\xa3\xb6\x32\x6b\x32\xa1\x6b\xef\xd6\x4d\x15\xb3\x61\xa4\x15\x13\x64\x1b\xce\xba\x26\xbf\xe9\x3b\xdf\x85\x4a\x4f\x8f\x8a\x0b\x29\xf7\xe2\x82\x62\xe2\xd6\xe9\x8a\xa2\x4a\xc2\x7f\x6f\x78\x83\xac\x01\xa7\x4c\x40\xcc\xe9\x47\xeb\xac\x70\xe9\xfe\xf2\xa1\x6e\x62\x89\xe4\x68\x95\x0e\x39\x1e\x9e\x24\xef\x58\xe8\x8a\x44\x37\x72\x69\xce\xba\xfe\xd8\x98\x7d\x22\x0d\xca\xe2\xd8\xb1\x26\xb6\xbf\x81\x21\x67\xd0\x23\xd9\xba\xac\x95\x0d\x9d\xb8\xcf\x52\xde\x63\x06\xbd\x48\x99\x96\x10\xc0\xa4\x33\xfa\x9e\x17\x71\xcb\x83\x2d\x41\x97\xaa\x34\x0d\xd0\xcc\xd0\x74\x4f\xc6\xb6\x2f\x90\xbd\x3e\xbb\x53\x08\xca\xb5\xf9\x40\xe2\x91\x64\x23\xcf\x0f\x3b\xf0\x80\xc0\x6a\x94\xf0\x26\x91\x04\x60\xdd\xa8\x09\x37\x4e\x64\x57\xf0\x64\xf1\x78\xe3\x08\xe7\xa1\xb5\xaf\x4d\xef\x31\x90\x07\xd0\x41\x77\x8c\x3d\x6a\x41\x9f\x51\xba\xdf\x87\x66\x38\x79\x30\x2b\x53\xff\x26\x9d\xf4\x42\xd0\xe0\x5c\x95\x8d\x5b\xaa\xcc\xee\xd7\xf5\xf8\xaf\xc8\x11\xc1\x89\x00\xee\x3b\x0f\x61\xe5\xdc\xcf\xd5\xda\xc8\x53\x32\xd3\x2e\xbb\xa3\x71\xaa\x2d\x47\xa6\x06\xf5\x95\x46\xe4\xbb\xb6\x05\xa7\x46\x77\xb1\x9a\x0f\xe8\xe9\x5f\x9f\x77\xc0\xb8\xb7\x1d\x07\xe9\x83\x00\x4d\xc2\xab\x2c\xb3\x79\x3a\x32\x3c\x10\x8d\xfa\x79\x70\xda\x00\xdb\x19\x86\x74\xbd\x34\xbf\x73\x10\x76\x7f\x76\xa2\x24\xe0\x7b\xdb\xc6\x2b\x9d\x07\x8c\xbc\x75\x36\x7e\x2e\xba\xa2\xc5\xd2\x74\xbf\x34\x27\xf2\xa0\xcc\x5d\xbe\xf0\xaf\x4e\x63\xad\x88\x9e\x13\x1b\x12\xbc\x8c\xa3\x2d\x82\x7f\x72\x60\xb0\x44\x9d\x04\x43\xfa\x28\x84\x40\xef\xd1\x36\x4e\x3c\x98\x49\x47\x7e\x73\xee\x0b\xa4\x24\x0d\x49\x2a\xf5\xce\x13\xc3\x45\x61\xb4\x50\x10\xc1\x09\xd8\x42\xc1\xfe\xd1\xbe\x3f\xa9\xe1\x84\xaa\xa1\x40\x64\xf4\x3f\x6d\xea\x0b\x65\x9c\x5b\x97\x89\x3c\xf2\xa4\x33\xbc\xfb\x1d\x2a\x87\xeb\x56\x4b\xd9\x09\x2c\x26\x66\x70\x47\x31\xf8\x3e\x56\x43\x4b\x2a\x42\x99\x65\x0c\x70\x60\xf9\xff\x7e\x8a\xad\xcb\x45\x93\xf6\x09\x18\x8d\x8b\x46\x76\x46\xcf\xe9\x52\x70\x06\x7a\x1d\x35\xcd\x75\x9f\xe5\x81\xaf\x4e\x62\x60\x2c\x02\xef\x14\x74\x41\x43\xeb\x42\x4f\x2d\x9f\x33\xa6\x02\x88\xc1\xb2\x5f\x08\xe4\xb2\xf5\xfe\xae\x06\xcb\xcc\x2b\x20\x52\xbf\x38\x4e\x1a\x6f\xcd\x84\x71\xce\x5e\x56\x58\xd7\x7f\x40\xc3\x5c\x41\x5e\x2a\x9e\x09\xfb\x58\x3b\xb7\x47\x12\x58\xe7\xc8\x06\xf3\xc2\x18\x22\xdd\x10\xf5\x6a\x64\x0c\xdc\x00\x12\x8d\x3b\xa5\x56\xba\x51\xdc\xaa\xb4\x7c\x3b\xaf\x9f\x01\x97\xd3\x66\x3d\xe8\xd0\x93\xe8\x31\x73\x32\x5d\xef\x1e\x83\xa2\xf5\xf5\xac\xf1\x2a\xe0\x9f\x3c\xe9\x6c\xd8\x88\x03\x4d\xcb\xe6\x14\x7d\xc5\x99\x83\x62\xa4\xbc\x40\x6d\x28\x84\x6a\xb1\x50\x3c\x17\xc9\x4f\x9a\xfd\x90\x3c\x9a\x58\xe1\xce\xbb\x4a\xbb\x4f\xf6\xf2\xa4\x10\x24\xe0\x6d\xca\xad\x14\xf5\xb7\x0c\x1b\x26\xe6\x9f\x96\xec\xf1\x4b\x8d\xa3\x1c\x62\x1f\x9a\xd4\xe3\x0a\xeb\x98\x23\x78\x67\x1f\x7d\x1f\x2c\x4b\x57\x2c\x41\xbb\x88\x30\x84\x0a\xc5\xdd\xce\xd8\x81\xf8\xff\xf2\x10\xc3\xc7\xf2\x36\xd8\xc5\xf2\xcf\xda\xcd\xa2\x98\x93\x30\x2f\xde\x15\x28\x2d\xb5\x40\xcb\x54\x37\x37\xdd\x77\x85\x25\x69\x22\x1f\xdd\xcd\xd6\x8d\x87\xe2\x40\x21\x79\xd3\xa5\xa7\x77\x34\xc2\x75\xa1\xd5\x60\xa4\x62\xf4\x03\x18\xbb\x68\x19\x83\x7d\xa3\xd3\x05\xeb\x49\xb3\x86\x50\xef\xdc\x8f\xe4\x09\xd4\x0f\xb9\x4c\xd5\xdc\x3e\xb0\x27\x38\xf3\x88\x52\xf6\x71\xa0\xc4\x14\x14\xb7\x6f\xb4\x36\xf3\x41\x7b\x8e\xf3\x00\x92\x1c\x00\x9e\xbb\xd7\xcf\x8e\x11"}, -{{0x18,0xe2,0x68,0xb1,0x5a,0x25,0x01,0xdd,0x4c,0x97,0x9d,0xc1,0x03,0xca,0x6a,0x84,0x22,0x16,0x13,0x2b,0x3b,0x50,0x81,0xd7,0x75,0xf8,0x86,0x40,0xf8,0x9c,0x80,0x41,},{0xb3,0x4e,0x19,0xc1,0xe2,0x08,0xfb,0x48,0xa8,0x85,0x07,0x9d,0x9f,0xbf,0x37,0xc7,0x4f,0x92,0x71,0x09,0x60,0xf8,0x32,0x15,0x4f,0xab,0x18,0x57,0x0c,0xfb,0x4c,0x1d,},{0xf2,0xdc,0xfc,0x06,0xef,0x1d,0x8e,0xcc,0xd8,0xe4,0x0b,0xdf,0x01,0x30,0x7d,0xd1,0x96,0x83,0xf2,0x14,0xd4,0xf0,0x84,0xe6,0xb6,0x93,0x4f,0x63,0x72,0x78,0x30,0x0d,0xbb,0x18,0x89,0xf2,0xd3,0x7f,0x53,0xb3,0xae,0xf2,0x6f,0xbb,0x3e,0x36,0xbd,0x75,0x98,0x5f,0xa7,0xc8,0xea,0x6d,0xdf,0xfa,0x72,0xc8,0xe4,0x06,0xf2,0x4b,0xb2,0x0e,},"\x42\x4b\xdc\xf0\xb2\x56\x00\x14\x39\xd1\x69\x58\xff\xf6\x48\xcf\x7a\x86\x04\xaf\x22\xcf\xa5\xb4\x43\x31\xb4\xdc\x35\x6d\xff\x25\xcc\x05\x63\xda\x9d\x64\x01\x33\xac\xb7\x0b\x6a\x11\x76\xc4\x82\xdb\xc9\x40\x8c\xd6\x79\x3d\x56\xbc\x29\xcc\x40\x88\x23\xd3\x88\xed\x88\xb2\x4c\xeb\x66\x21\xdb\xac\x00\x23\xee\x69\xf7\x6f\x82\x96\xa7\x39\x52\x11\x68\x5b\x3c\xea\xa9\x95\xf0\x35\x5d\x9a\xad\x3d\x97\x35\x8f\x4a\x37\x9e\x59\x20\xec\x54\x5f\x46\x96\x21\xcf\x76\x8a\xbf\x55\xd2\xa5\x54\xc9\x49\xb0\xed\x70\x18\x7c\x22\x05\xad\x03\x29\x85\xc9\xb5\xb2\xe4\xba\x57\xe0\xb4\xa4\x7d\x34\x45\x12\xb8\x4b\xfe\x9f\x3a\xa5\x60\xfe\x6e\xcf\xc5\xbd\xf8\xc3\xb4\x18\x45\x29\x35\x73\xf8\x1e\xd3\xb7\x0e\xdc\x63\xa3\x0c\x70\xcd\xa3\xf4\x55\x90\x13\x13\xf6\xd2\x3d\xb3\x09\x47\x8f\x03\xe3\x4e\x71\x35\x6d\x83\xfa\x5d\xb9\x28\x0c\xc2\xb4\x36\x9c\x3d\x24\xdd\x90\x38\xf2\x47\x59\x6c\x39\x1e\x48\xb2\xf3\xf8\x90\xa1\x41\xca\x1d\x12\x07\x7c\x69\x34\x47\x35\xa5\x9b\x1d\xd4\x07\x6b\x22\xe1\x61\x89\x99\x1e\x5f\x1b\xe4\xfb\x76\x95\xaf\x90\xeb\xea\x5d\xf2\x86\x13\x5c\xec\x2a\x6e\x99\xaa\x1d\xda\x32\x8e\x62\xc0\xdf\xb6\x37\x42\x20\x2d\x63\x62\x4d\xcc\x0c\x5c\xf1\xa5\xdf\x79\xe2\x87\x8d\xbc\x71\xfa\x96\x57\x66\x01\xaf\x22\x84\x4f\x54\x57\x33\x12\x6a\xf7\xd3\x98\x4c\x3e\xd2\x52\xe6\xa8\x76\x44\x5c\x92\x25\x9f\xbb\x47\x0a\x10\x56\x9b\x49\xe5\x79\x1f\xd0\x18\x2c\xfe\x1c\x3f\x88\x29\x7f\xac\xc8\xc3\x1a\x53\x32\xf1\xf4\xeb\x49\x58\xdb\x13\xb6\xc0\x79\xaa\x9c\x94\x94\x87\x26\x34\x03\x19\x0c\x83\xc1\x1a\x43\x19\x1f\xfe\xc6\x02\x3f\xb3\x4c\xfa\xb2\x52\x5b\xeb\x54\x6c\xf9\x20\x0a\x96\xf5\x85\x4b\x2f\x78\xec\xb2\xd9\xa5\x3a\xa9\xd2\x87\xa9\x0d\x4d\x41\x0a\x63\xad\xa0\xe9\x75\xd3\x04\xd5\x14\x83\x53\x46\x3f\xa8\x05\xb4\x80\x5f\xb4\x68\x7e\xd8\x85\x7d\xfc\xe4\xbc\x6e\x80\x83\x3c\x8f\x9a\x79\xcd\x4f\x02\x9a\x2d\x80\x2b\xfd\xc8\x19\xed\x0c\x0a\xc8\xf2\x10\x23\x28\x7f\x2b\x4b\xaf\xbc\xc8\x99\x93\xfe\x46\xd5\x2a\x9c\x62\x46\xde\xad\x61\x7d\xf7\x97\xd4\x8e\xe9\x85\xf0\xf0\xdf\x9a\xa8\x2e\xa2\x0e\x0d\x0d\xb2\x8a\x25\x4a\x9a\x25\x3f\x39\xf9\xcf\x01\xe3\xdb\x8f\x3e\xbc\xf7\xcb\x97\xce\xc5\x8c\x4e\xfe\x03\x12\x69\xb4\xb3\x7e\x4c\xbb\x36\x1f\x73\xab\x4b\x49\x80\xbd\x90\x08\x49\x53\x88\x44\xc5\x2c\xb3\xac\x75\x83\xb8\xf8\x96\x53\xa0\xde\x65\xa8\xbe\x91\x58\x2c\x55\x23\x9c\xb8\xf5\xd5\x31\x8a\x88\xd1\x60\xe1\xc8\x71\xe5\xea\x7e\x75\xf5\xa6\x9c\xba\x85\x38\x22\x1a\xb4\x2c\xe2\xa2\xc4\xd9\xc3\xb7\xec\x85\x7f\x23\x0d\x57\x37\x31\x13\x36\x86\xae\x8a\x7e\xd6\x40\xf4\x2f\x31\x02\x94\x89\xe4\xe6\xaf\x2b\x3e\xa4\xc7\x94\x8e\xd5\x37\xc0\xc5\x90\x67\x26\xc2\xb6\x25\xfd\x5f\x94\x9e\x3a\x7c\xf3\xb6\xe9\x98\xec\x76\x1d\xd6\xe2\xb5\x17\x1a\x68\x74\x97\x52\xe7\x21\xb7\x88\xc3\x47\x7f\xa1\x90\xcd\x6e\xa8\x1d\x57\x9d\xce\x64\x62\xd9\xc6\x62\xad\x89\x62\xe7\x93\x38\x71\x0c\xc8\xd2\x73\x8a\x5f\xb0\x4a\xdf\xdb\x3f\x14\x32\xcf\xd8\x0e\x2e\x96\x7d\xa0\x00\xd8\x3a\x0f\xa8\x5a\xba\xe2\x95\x2f\x3f\x36\x83\xe2\x54\xd8\x68\xf4\xbf\x80\x9e\xb2\xe3\x00\xe7\xb2\x09\x73\x4a\x3c\x89\x4e\x96\x6b\x16\x08\x8d\x5e\xd3\x54\xbf\xfb\xff\xbb\xf2\xec\x2b\xe9\x3a\x32\xa8\xbe\x5c\xfa\x18\xfa\x56\x53\x01\x2e\xda\xe5\xaf\xd8\x70\x9c\xa5\x5c\x0c\xf2\x3a\x55\x0d\x34\xca\x0f\x32\xd8\xf6\x66\xfb\x47\xa1\x2f\x2b\x73\x53\xa4\x0c\x53\x79\xf7\x53\x66\xc1\x3f\x4a\xb9\xf1\x4c\xf8\x0a\x94\xe1\xf1\x3d\x8b\x09\xb7\x6f\xd8\xd1\x4f\xfa\x53\x8f\x31\xfd\x8a\xeb\x49\xd3\x34\x33\xf4\xdf\x7c\x2c\xa6\x73\x99\x57\x9f\xe9\x90\x78\xaa\x72\x1d\x6b\x6f\xc0\xc5\x0e\x8a\x91\xfc\x71\xca\x25\xea\xc1\x37\x6f\xc6\x71\xbf\x61\x53\xe7\x20\xb2\x5c\x7e\x97\xa3\xd4\xef\x84\x42\xac\x67\xac\xf5\x8b\x50\x4b\x67\x15\x8f\x91\x30\x25"}, -{{0x3c,0x39,0x3f,0x9d,0xf1,0xfb,0x0b,0x1e,0xec,0x09,0xb7,0xf2,0x70,0xb8,0x59,0x82,0xba,0x0f,0xd5,0xe4,0xb1,0x79,0x5e,0x1a,0x7f,0xa9,0x91,0x37,0xfe,0xe2,0x4d,0x7d,},{0x97,0x4f,0xe2,0x37,0x30,0xfc,0x17,0x94,0x56,0x70,0xfb,0xc1,0xf8,0x0b,0x93,0xf9,0x45,0x93,0xc8,0xd4,0x4b,0xc7,0x5d,0x18,0x9a,0x6b,0xbf,0xaa,0xba,0xf5,0xdb,0xd9,},{0x22,0x33,0x3e,0x56,0x41,0x0f,0xdc,0xbf,0x84,0xf6,0xa8,0xde,0x74,0x13,0x37,0x69,0x16,0x84,0x49,0x5b,0xa6,0x9e,0xff,0x59,0x6d,0xb9,0xc0,0x3a,0x28,0x12,0x10,0x88,0x1e,0x6c,0x91,0xef,0xa9,0x1b,0x21,0x83,0xc0,0xea,0xc9,0x16,0x15,0x28,0x17,0xa7,0x8c,0xa7,0x24,0xba,0x7c,0x8b,0x51,0xbb,0x4c,0xaa,0xde,0xa9,0xa3,0x41,0xeb,0x0e,},"\x54\xd8\xb8\xd5\xfa\xc2\x8c\xff\xa7\x7a\x09\x16\xd6\x33\x3c\x16\xed\xbc\x8b\xb7\x4a\xa0\x6e\x56\xdc\x00\xe4\x7e\x39\x29\xe4\x08\x64\xb8\x84\x0d\x91\x20\x79\x59\x7e\xac\xd8\x1d\xae\x43\xe2\x78\x5d\xfc\x68\x9f\x3e\x85\xf8\xc6\x65\x81\xef\xc5\xe8\x53\xd1\xfa\xaa\xc7\x44\x40\x0a\xb0\x8c\xbd\xb5\xd1\x61\x46\xfa\x60\xf9\x99\x05\xed\x84\xfd\x29\x36\xdd\x73\xf4\xbc\xa2\x57\x2b\x7c\xf5\x16\x05\x60\xff\xaa\x68\xda\x7a\x67\xe4\x0e\x08\xa7\xbb\x7a\xef\xc4\x04\x3e\xbe\xd5\xfe\x80\xa4\x14\x81\x7e\xdf\x2c\x63\xf6\x2f\xac\x0d\x47\x44\x6e\xd0\xbb\x58\x40\x58\xf4\x87\x2f\xec\xff\x62\x15\x59\x31\x1a\x27\x0a\xea\x37\xa6\x29\x68\x64\xe8\xd1\x68\xbf\x1e\x2f\x55\xcd\x3b\x27\x6e\xdf\xa6\x12\xb5\xd9\xc3\x36\x2e\x61\x8b\xe6\xe8\x2a\x6e\x5f\x82\x66\x79\x24\xf3\xd1\xd3\xdf\x82\x5f\x9d\x23\xf4\xd6\x14\x2d\x31\x00\xdf\xc7\x0f\x70\x60\x3a\xbf\x3f\xda\xda\xca\x69\xef\x6a\x18\xef\x90\x92\xb3\xc4\x1e\xc6\x58\xab\x27\x21\x6f\xc6\x14\x7a\x08\x0a\xcd\xa6\x0a\x84\x19\x84\xee\x83\xf4\x1a\xc4\x2a\x80\xea\xac\x91\xff\xfc\x82\x28\x39\x1e\xf5\x83\xab\x3e\xdd\xcf\x87\x65\x23\xc2\x02\x81\x35\x53\x00\xd8\x6c\x11\xa4\xe7\xc1\xad\xe8\xe5\x05\x60\xf4\x39\x06\xc9\xbc\x8c\xa5\xfb\xf8\x33\x9f\xbe\xbd\x02\xe3\x3e\x85\x18\xbe\xe5\xe8\x06\xb8\xc1\x0f\x82\x77\xf4\x10\x66\x47\x35\xa2\xbf\x55\x68\x39\x63\x54\x92\x45\x2e\x6c\xa0\x79\xde\xb9\x75\x1c\xfc\x67\x97\xf4\x9b\xca\x96\x13\xff\x2e\x7f\xdd\x36\x46\xf7\xc5\x23\x6a\x36\xbd\xf0\x05\x17\x45\xe5\x95\xdc\x00\x72\xfd\x66\x51\xd5\x76\x27\xa6\x00\x4c\x0f\x0c\xfa\xe8\x56\xbb\xc2\x8a\x12\x31\xcb\x83\x96\x65\xff\x04\x15\x2e\xc3\x1c\x00\x7b\x3e\x2e\xd0\xa9\x73\xb2\x4c\x93\x14\x9c\xe7\x01\xe6\xfd\x65\x39\x20\x6a\xe9\x1b\xec\x4c\xe6\x5a\x89\xdb\x26\xc7\xd3\x8c\xec\xb8\x91\x9f\x96\xfb\x6c\xb8\xf6\xc1\x93\x9d\x90\xfb\x3f\x90\xb8\x87\x78\x9f\x29\x57\x5a\xb2\x0e\x0b\x08\xbc\x35\x81\x53\xd8\xc0\x35\x21\xdc\x89\x18\x70\xb5\xf7\xee\xdc\xc1\xe6\x2b\xee\x7d\xa0\x63\xae\x66\xff\x0a\x4b\x7d\x98\xd1\xcb\x75\x8f\x69\x74\x3c\x3d\xb3\xae\x2a\x2c\x9b\xe1\xbe\x09\x4f\x17\xcd\x28\xf9\x2d\x8c\xcb\xca\x98\x3c\x74\x9c\x75\xc6\x10\xf8\x40\x83\x6e\x2c\x43\x0c\xcd\xef\xf0\xaf\xa5\x44\x44\xf1\x2b\x4a\x4f\x00\x2c\x60\x94\x51\x83\x42\x44\xc0\xc0\x7d\xf8\xe1\x22\x02\xa6\x5f\x94\x44\x7c\xd4\x90\x3a\xcb\x60\x6d\x77\x25\xa8\x6e\x4a\x23\x43\x98\x4e\x67\x9c\x4a\xf1\xb3\x67\x9c\x75\x5e\xa5\x0d\x0a\xbe\x2f\xcc\x0c\x1c\x33\x51\xa9\xee\x19\x6b\x46\x44\xc4\x24\x22\x2b\xe9\x9e\x2f\xb3\x73\xf9\x64\x1e\x3f\xae\xbf\xf4\x31\x70\xeb\x03\xfb\x8e\xc4\x55\x7d\x15\x1a\x55\xfa\xb6\xc4\x99\xd4\x44\xc8\x4b\xe8\x9f\x24\x47\x68\x2d\xe4\xe6\xf6\x35\x34\x75\xef\xcb\x8f\xc5\x32\x56\x76\x3a\x94\x8d\xc7\x5c\x51\x5f\xa3\x53\x54\x5d\x0c\xba\xd2\x9d\xf5\xe9\xdb\x5c\xc4\x57\xed\x30\x86\xcf\xfb\x3d\x75\xe8\x46\xc4\xe8\xd8\x81\x47\xfc\xd0\xd8\xaa\x5a\xba\xb4\x9b\x5e\x05\xc3\xd7\xfe\xef\x63\x79\x43\x34\x7a\xd3\xf4\x92\xee\x35\x6e\xf3\x48\x81\xcf\xd8\x5a\xbc\xe8\xa1\x44\xce\x77\x61\xe2\x84\xe8\xb8\xcb\x08\x96\x60\x49\x04\x7a\x99\x6e\x23\x55\x9f\x77\x6b\x1a\x9f\x41\xcb\xa3\x95\x41\x08\x48\x6e\x29\x27\xbe\xb6\x43\x3a\x36\xff\x8b\x2f\x03\xaa\x74\xb3\xd2\x09\xc4\x88\xe0\x77\xf9\x24\xf2\x31\xe2\x83\x45\x94\x2c\x7d\xcc\x2e\x61\xd7\xc9\xb5\x22\xb6\x59\xfc\xb5\x36\x62\xaf\xf3\x64\x8f\x66\xda\x3e\x83\xe5\x9b\x0d\xaa\x90\xb9\x4c\x51\x5d\xad\xab\x10\xd5\xa8\x39\xcb\x3a\x2f\x1d\x3c\xd0\x92\xde\x55\xd9\x95\x13\x8c\x3a\xc0\xb9\x07\xaf\x15\xac\x63\xec\x18\x74\x11\x43\x27\xe2\x19\x71\x34\x5e\xf1\x70\x31\xd5\x26\x17\xe7\x84\xda\x37\x71\x43\x9b\xe2\xe8\x41\x48\xbc\xfe\xa1\x32\xbd\xe1\x0e\x6f\xda\x54\x7d\xcb\xb1\xc4\xd8\xf7\x4d\xdc\xe1\xfc\xcf\x82\x13\xe0\xda\x6e\x97\xb8\x1f\x75"}, -{{0xf8,0x66,0x9c,0x88,0xf1,0x68,0x5b,0xbf,0x04,0x80,0xcc,0x92,0x21,0xac,0x2e,0xad,0x8f,0x55,0x1b,0xfa,0x87,0xec,0xba,0x2f,0xd4,0xdd,0xf3,0xba,0x34,0x76,0xeb,0xda,},{0x34,0x72,0x3f,0xb8,0xe2,0x53,0xad,0x9c,0x71,0xce,0xfd,0xe0,0x36,0x28,0xd2,0x04,0xe5,0x35,0xde,0x47,0x9e,0x10,0x48,0xe5,0x18,0x87,0x62,0xa1,0xf3,0x37,0xfe,0x5f,},{0x37,0x46,0xda,0x6c,0xd8,0xca,0x10,0x8b,0xee,0xf0,0x64,0x87,0xbe,0xe6,0x35,0x84,0xf8,0x12,0xc8,0xe0,0x69,0x5f,0xc8,0x63,0xb8,0x6e,0x5d,0xb1,0x32,0x38,0x0b,0x62,0xff,0x85,0x44,0xf6,0xf3,0x74,0x82,0x5b,0x0e,0x3e,0xa0,0x62,0x0e,0xf8,0x54,0xc1,0x33,0x11,0x14,0xd6,0x67,0xdf,0x1f,0x9e,0xa7,0x76,0xc3,0x96,0x38,0x70,0x29,0x0d,},"\x5b\x49\x41\xbe\xec\x22\x41\xc9\xfb\x76\xd8\x48\x4f\x4f\x3f\x3a\xb4\xff\xe8\xec\xc8\xe7\xae\xc7\x6d\xe2\xab\x8c\x36\x85\x84\xd7\x51\xb0\xd3\xfe\xb8\xa1\xdc\x81\x68\xcd\xc6\x94\x96\x8f\x66\xb2\xa0\xb0\x52\xaf\xbf\x8b\xe3\xa7\xd9\x51\x63\xe9\xda\x91\x41\xc5\x9c\xa5\x59\x76\xc2\x92\xc5\xc7\x4d\x31\x31\x8d\x6a\x91\xe7\x81\x7c\x5a\x8b\x2f\x81\x21\x18\xcb\xeb\xa3\xa1\x33\x23\xcd\x97\x48\xbf\x86\xed\x1a\x85\xdd\x4e\xbc\x0d\xf4\x95\xcf\xa3\xd4\x62\x74\x34\xbf\x14\xaa\xe8\xab\x67\x81\x46\x7a\x56\xd9\x65\xd1\x0e\x63\x71\x98\x9d\xfa\x0f\x6b\xc0\xf7\x85\x9f\x37\x71\xeb\x90\x04\xb3\x43\x67\xdb\x27\x05\xdb\xd6\x0f\xa8\xf7\x89\x5c\x1e\xad\xf5\x9f\x53\xda\xb1\x68\xb4\xf9\x36\x39\x79\x02\x55\x01\xdd\xd9\x68\x0d\xeb\xc0\x7c\xd1\xca\x4a\x09\x97\x87\x6e\x92\x11\xf3\x07\xd9\xb7\xb9\xd9\x04\xe4\x8d\x28\x61\xa7\x78\xb8\x79\xad\x59\x0a\x9a\x2f\x14\x1b\xd5\x68\xe3\xa1\xbb\x24\x94\x62\x8e\x9e\xc0\xc6\x42\x55\xae\xea\x6f\x0e\xed\xca\x30\xad\x38\xa1\xf3\xff\xec\x3b\x2b\x5e\x94\x2e\x21\x94\x01\x04\xe9\x14\xd1\x1a\x44\xc0\x0f\xdd\x47\xda\x3e\x55\x13\xaa\x85\x30\xae\xe2\x47\xc9\x5c\xa6\x6d\x08\xa2\x60\x8c\x75\xba\x98\x58\xda\x14\xf9\xa8\xa3\x2b\xe7\x13\xd3\x09\xe0\xf5\x84\xc8\x1e\xf5\xbe\x04\x0e\x00\x65\xf0\x7b\x77\x5a\xe1\x75\xdf\xe2\xc8\xb9\x0a\x88\xcc\xda\x17\xfa\x4f\x21\xc7\x7e\xad\xf5\xd2\x5b\x6e\x40\x4b\xf0\x04\x47\x9e\x05\xa0\x1a\xc0\x04\x2b\x89\x93\x7e\xb2\x78\xc1\xc3\x4f\x33\x02\x8d\xb7\x80\xba\x3b\x61\x79\x18\x59\x5a\x39\xc0\xfc\xad\x67\x4b\x85\xc4\x0c\xac\x8d\x34\x5b\x7c\xa0\xbb\x48\xa2\x8e\x66\xc4\x4d\x8b\xb5\xf2\x79\x41\xe4\x0b\x0e\x9c\x70\x97\x97\x6c\x62\xdf\xef\x50\xc9\x8f\x17\x56\x6c\xcb\xac\xc8\x7c\xb0\x3b\x94\xdf\xdf\xaf\x32\xf1\xe5\x6f\xfa\x63\x9d\x63\x61\x1e\x21\x3c\xeb\xf5\x4c\xd0\xa3\xe2\x17\x2d\x81\x1c\x0e\xbd\x75\xb1\xa8\x64\x62\x64\xdd\x8b\x1a\xbd\x46\xe5\x48\x97\x2a\x1b\x26\x2c\xd9\x5d\x51\x15\x36\xdd\xdc\xb4\x97\x29\xfe\x7b\xd0\x0b\x38\x38\xbd\x2f\x20\xa1\x42\x64\x0e\xdb\x1b\x6e\x76\x5b\x65\xda\x72\xe7\x23\x32\x61\xc8\x89\x2e\x2f\x49\x49\xbb\x51\xf3\x2a\x1a\x5a\x3e\xe1\x49\xbe\xa2\x6f\xdc\xed\xb9\x91\xd2\xcd\x12\x66\x37\xe2\x97\x1e\x9b\x6f\x0b\x78\x5d\xf2\x8a\x48\xf3\x01\x70\x73\x49\x42\x3f\x44\xe8\x46\x22\x89\xd7\x25\x49\x82\x30\x48\x9d\xf1\xb5\x1b\xe3\x0f\x08\xd7\xe3\x25\x05\x65\xc6\xef\x82\x4b\xc5\x3a\x1b\xa7\x4a\x57\xa2\x5c\x06\x86\xad\xcb\x6c\x82\x5a\xb1\xca\x70\xc8\xa5\xd4\x6d\xbb\xc6\xfa\x60\x74\x61\xe2\x6d\x16\xfe\x93\xbb\x3d\x3a\x94\x3a\x3d\xc0\x5f\x30\xea\x6d\xc8\xbb\x12\xd7\x08\x21\xd3\x20\xf1\xad\xf1\xce\xba\x4b\xe6\x57\x19\x4f\x7f\xcc\xd2\x19\x90\xf8\x62\x9d\x74\x46\x01\xcf\x52\xea\x6d\x94\x05\xaa\xa2\x87\x8f\x1e\xec\x40\x03\xb4\x5a\x42\x18\xd8\xf8\x0b\xb0\xf5\xaf\x04\x73\x26\x48\x77\x52\xe2\xb7\x6d\x68\x87\x25\x20\xbb\xea\xe7\xb3\x09\xd7\x82\x82\xa0\x73\xfe\x0b\x1a\x1a\x7a\x98\xda\x23\xdf\x68\xca\xf8\xc2\x69\x9b\x1c\x7d\x0f\x47\xbd\x7d\xe2\xc0\xbb\x23\x36\x99\x63\xe6\x8a\x69\x74\xc8\xe2\xb5\x95\xb8\x29\x3a\x9f\x4d\x98\xdf\x7e\x9a\xe3\xad\xd2\xa3\xf6\x4e\x83\x03\x97\x39\x64\x2d\x19\x22\x04\xe8\x5e\x6c\x48\xd5\xd6\x71\xf6\xc7\x5a\x0a\x89\x57\xed\xbb\x74\x18\x76\x20\xf2\xab\xa9\x9c\x1c\x62\x58\x4c\x59\xac\x00\x64\x7e\x3f\xb4\x02\x92\xb9\xdc\x1a\x33\x46\x86\x85\x53\x39\x2f\xd3\xf1\x1d\x6d\xc6\xf5\xf2\xf4\xe8\x5e\xe2\x51\x25\xcd\xd6\x44\x74\x3c\x7d\x45\x28\x1e\xda\xc6\x38\x4c\x77\xcb\x98\xa6\x7d\x9a\xe6\xfc\x9a\x0a\x76\xb9\xf6\xfa\x69\x6f\xdf\x4a\xce\xab\x5f\x79\x4e\xe5\x21\xb1\xe5\xa0\xee\x57\xaf\x53\xbd\xf1\x76\x80\x1b\x4f\x45\xcf\xb3\xca\xe3\x28\x72\x34\x23\x4b\x77\xce\x21\xed\xf8\x68\x0d\x68\xc4\xa8\xee\xcf\x1b\x03\x53\x7e\xa5\x69\x9a\xcb\x56\x27\x77\xe4\x2a\x48\x6f\xe7\xcd"}, -{{0xce,0xcc,0xc6,0x83,0x11,0xfc,0x45,0xb6,0xc2,0xa2,0xf1,0xff,0x9c,0xdd,0xe0,0x07,0xec,0x78,0x7f,0xdf,0x25,0xd0,0x2c,0xcd,0x2a,0x1c,0xad,0x9d,0xe3,0xfb,0x4c,0xff,},{0x6f,0x80,0x47,0x34,0xef,0x92,0x82,0x41,0x80,0xda,0x71,0xe5,0x5c,0xf3,0xbf,0x1a,0xfe,0xf6,0x5b,0xcf,0x56,0x09,0x62,0xe0,0xb0,0xac,0xbb,0x2d,0x8c,0xca,0x59,0x84,},{0x3c,0x44,0x62,0xaa,0x47,0x01,0x01,0x32,0xdb,0xb2,0x63,0x11,0xe4,0x44,0x72,0x72,0x79,0xed,0xad,0xe1,0x5a,0x4d,0x66,0x2c,0xf6,0x47,0xf3,0x27,0x5c,0xf3,0x25,0x3e,0x6d,0xe9,0x33,0x38,0x30,0xe0,0x51,0x7a,0xa5,0xfa,0x7b,0xc2,0xd0,0xe6,0x3e,0xa2,0x59,0x7a,0x94,0xb0,0xfe,0x92,0x70,0x6e,0xcd,0x17,0x2c,0x5e,0xc5,0xc7,0xf0,0x06,},"\xba\xc1\x86\xd9\xfe\x5a\xbd\xa7\x9c\x3a\x35\xa7\xa3\xc2\xea\xe6\xae\x6a\xb2\x82\x47\x91\x27\x70\xc8\x4e\xfd\x04\x8e\xbd\x3a\xba\x57\xc3\x7c\xf4\xc6\xc7\xf3\x0a\x79\xf6\x8a\x3f\x76\xb2\x0c\xd8\xc6\x63\x1f\xcc\x96\x67\x05\x22\x08\x0e\x6b\x62\xe8\x87\xae\x6f\x44\x36\xd4\xca\xf5\x69\x43\x13\x1c\x52\xdd\x28\x2b\x25\x1c\xd0\x75\xf1\xf7\xf8\xe0\xbd\xb6\xbe\xdf\xc9\xa0\x79\x6f\x55\x79\x04\x2b\x56\xe6\x93\x74\x96\x1b\x11\xdf\xd6\x1b\x12\xde\x2b\xb7\xd4\x9b\xfc\x50\x9c\xdb\x31\x38\xf3\x35\x6a\x0d\xde\xd9\x8f\x53\x01\xb7\xc4\xa7\x48\xbf\x89\xb2\x3d\xf4\xf7\x47\x2f\xf8\xb1\xf5\x05\xd7\x65\xc6\xff\x82\xdb\xad\x74\xb9\xd7\xae\xf2\x2f\xbc\xca\x0b\x7f\x35\x04\x2f\x9a\x76\x2b\xd0\x69\x02\xbb\x21\xc7\xf9\xf7\xf6\x6b\xef\x38\x90\x1d\x75\x01\x2d\x61\xd7\x44\xde\xe7\xaf\xd8\x9f\xc7\xe9\x08\xc4\x06\x85\xbd\x44\x0a\xed\xa4\x20\x4d\x00\x6f\x26\x30\x7d\x82\xa4\x96\x96\x31\x15\xf9\x0e\x09\xf7\x66\x88\x29\x1f\x4a\x67\xd6\x41\x1f\x76\xd1\x66\x17\x87\x5b\x2b\x99\x82\xdf\xdc\x5e\xe9\xb8\x3b\x98\x17\x00\x93\x19\x11\x0b\x54\x04\xc6\x31\x16\xfb\x6e\x94\x64\x84\x6f\xa0\x09\x55\x56\x32\xf0\x76\x98\x4c\x15\xe1\xf6\x08\x17\x33\xa0\xd4\x6f\x2d\x6a\x3c\xeb\xf7\x9e\xd9\x02\x0c\x9d\xec\x8d\xf1\x58\xa3\x34\x1f\x39\xea\xa5\xfc\xf1\xcf\x42\xa9\x48\x49\xb2\x35\x2c\x1a\x1e\xcd\x4f\xb8\x14\xc2\x0d\x07\xdf\xda\x31\x2b\xd4\xf2\xf5\x8c\x15\x76\xb4\xaa\x31\x5c\x96\xc8\x78\x6a\x4c\xfb\xb7\x36\xb2\xd2\x3c\x38\xb1\xd8\x1c\x46\x44\xea\x36\xaf\xa0\x76\xe0\x55\xbe\x59\x17\xcd\x7a\x92\x35\x0a\x7e\xd6\x6a\x5a\xb2\x25\x3f\x55\xc4\xfd\x1a\x0d\x0e\x6d\x4e\xda\xb5\xf7\x12\xed\xb4\x40\xc0\x6f\xac\x8f\x07\xe6\xd7\x3c\xc9\x0b\x2b\xa7\x13\xd7\x3c\x73\x80\x23\x61\xce\x46\xa4\xeb\x5e\xd1\x06\x0c\x4c\xf5\x32\x07\xd3\x01\xf0\xfc\xd4\xf0\xc9\xd1\x58\x0d\xb2\xfc\x10\x59\xd3\x72\x07\x64\x38\xa0\x11\x92\xa7\xf9\xfd\x6f\x78\x83\xf5\x64\x22\x86\x6f\xd9\xf0\xaf\xe5\x3f\xdc\x91\x0a\xfa\x5a\x75\x1c\xbf\xa3\x77\x59\x25\x79\x16\x5c\xb5\x6d\xc3\xeb\x4d\xce\x67\xe3\xdb\x33\xa9\x81\xa5\x6b\x7d\x9f\x7b\xde\xa7\x4f\xba\xea\x34\x78\xe6\xab\x2c\x64\x4f\xd7\x77\xb8\xbf\xa7\x2a\xa0\xf0\xa5\x21\x98\xd3\x6e\x5b\x63\x4d\x2c\x9a\x11\xb7\xfe\x0a\xb2\xf9\xa4\x09\x01\xc5\xb1\x48\xa0\x19\x2e\x95\xa1\x70\xba\xf7\xd5\x35\x0f\xe0\x1e\x56\x95\x42\xb9\x34\x85\xa4\x19\x71\x44\x34\x85\xfa\xf5\x7f\x67\xf5\x6d\xfe\x2c\x58\xe5\x39\xc9\xf9\xb4\x49\xc3\xf9\x12\x49\xa1\x0c\x1a\x1b\xe7\xe0\xb3\xea\xbe\x8e\xe0\xba\xb1\xf1\x1f\x89\x61\x4d\xce\xd4\x18\xc6\x2a\x07\xa0\xb5\x9a\x13\x70\xd6\x53\x1b\xa1\x77\x09\x1c\x6a\xd5\x95\xfb\x59\x48\x82\x04\xf6\x33\x44\x73\x6e\xa1\x01\x7a\xff\xbe\xb7\x53\xa9\x97\x86\xb1\xeb\x64\x51\x0e\x2e\x71\x7e\xc9\x0e\x02\x74\x4b\xc3\x52\xd3\xf1\xb2\xab\x7b\xe0\xeb\x65\x62\x3d\x04\xfb\x3a\x04\x6c\xe7\xf4\xda\x69\x7d\x82\x98\x28\xa5\x2c\x7b\x04\x3b\x2a\x82\xec\x97\xfb\x04\x1b\xf5\x19\xb4\xde\x31\x6f\x4e\x2f\x5b\x0d\xb6\x2a\xed\x0e\xed\x95\xca\xd4\x32\x0c\x19\x47\xc3\x5f\xd8\x84\x7a\x58\x67\x87\x28\x83\x56\x11\x19\xc0\x1b\x00\x89\x21\x3d\x84\xdb\x99\xd4\x39\xf0\xf6\x44\x4d\x87\x83\xdd\x4b\x64\xbe\x35\x77\xcd\x46\x1c\xf7\x53\xc8\xe6\x1c\x91\x2d\xe2\xe5\xd7\xa7\xe2\xba\xef\xa2\x58\x97\x5d\x16\xef\x31\x17\xda\x59\xa6\xc8\x93\xf3\x33\x91\x87\xdf\x31\x68\xb8\x9f\x0f\xb0\xb2\x19\x8b\xb6\xf1\x59\x4b\xb8\x8f\x3d\x61\x0f\xce\xc3\xe3\x6d\xe0\x4a\xe1\x03\x28\x11\x2e\x6f\xf7\x4f\x5a\x8c\xe6\x8d\x40\x71\x74\xb4\xc0\x69\x1c\x76\x02\xea\xb1\xbb\x10\xf3\xc4\x9d\xd2\x2b\x84\x50\x78\x2d\xea\xe9\xa7\x31\x5e\x3b\x88\xde\x79\xcd\x15\xe6\xc9\x26\x81\x65\xed\x3a\x0f\xb3\xf8\x9b\x18\x3e\x1a\x21\x21\x52\x00\x3f\x32\xa2\x66\x5d\x37\xcd\xd7\xf6\xb5\x6c\x24\x53\xe5\x58\x0c\x4d\x21\xf9\x98\x3f\x38\x79\x8e\x9b"}, -{{0x7b,0x30,0xb4,0x2d,0xc2,0xc6,0x70,0xa1,0x95,0xfe,0x2a,0xf8,0x79,0xfc,0x5d,0xe3,0x74,0x02,0x45,0x88,0xfe,0x3d,0xe4,0x3e,0x2d,0xd5,0x08,0x44,0xf4,0x8f,0x42,0xbe,},{0x82,0xa2,0xac,0x60,0x79,0xf2,0x12,0xb5,0xee,0xdd,0x0c,0x19,0xe9,0x39,0x4f,0xaf,0xac,0xd7,0x4d,0x71,0x6f,0xde,0xfb,0xfc,0x6c,0xb8,0xa7,0xea,0xf4,0x1c,0x03,0x62,},{0x0a,0x63,0xb8,0x4f,0x46,0x93,0x5f,0xaf,0x3e,0xa1,0x64,0xb0,0x0a,0xf2,0x27,0xb0,0x08,0x68,0xa0,0x3f,0x56,0x12,0x93,0x5e,0x18,0x61,0x9a,0x84,0xa2,0xe5,0x7b,0x88,0x51,0xd7,0x46,0xe6,0x3f,0xd9,0x10,0x07,0x87,0xf5,0x33,0x8d,0x51,0xc1,0x07,0x3c,0x2f,0xc5,0x30,0x30,0x99,0xe1,0x87,0x3e,0x5e,0x3d,0x3e,0x5c,0x03,0x6f,0xbe,0x01,},"\xc6\x68\x7a\xef\xeb\xc5\xc8\x16\xd1\xa3\x34\x53\xbe\xca\x50\x20\xd3\xa9\x7c\xda\x1d\xac\x56\x62\xf0\xaf\x72\xba\xd4\x44\xe2\xfd\x11\x76\xa7\xb0\x4c\x1b\xd0\x9d\x83\x26\x18\x20\x9b\xf3\xe3\x3e\x52\x35\x38\xd6\xda\xa7\x53\x04\x6e\x87\x1d\xd3\xb3\xc7\xac\xad\x33\xe7\x9c\x1b\xb7\x89\x64\x07\x86\x5d\x16\x8d\x4b\xc3\x75\x7b\xde\x4f\x82\x3c\x08\x77\x86\x26\xf8\xc7\x1f\xb7\xcf\xcf\xdf\x03\xa8\x24\x97\xbd\x8b\xe7\xd8\xf8\xef\x64\x90\x30\xb5\xf3\x6a\x33\x94\x59\x96\x8e\x24\x6a\x1e\x42\x08\x53\xda\xce\x41\xca\x85\x0a\x4e\xea\xe8\x34\xae\x11\x96\x10\xca\x4c\xd0\x66\x2a\xac\x39\x62\x15\x86\x99\x80\x27\xef\x2f\x61\x48\x5c\x02\x85\x06\x71\x4a\xe0\x9c\x76\x39\x9d\x87\x3e\x80\x81\x58\x57\x8a\xa5\x9e\x82\x12\xf5\x88\x65\x31\x9f\x9e\x0d\x2b\x8d\xa7\xad\x52\x9e\x0a\xc1\xf1\xeb\x43\x5a\xec\xfd\x35\xf5\xab\xb9\x2b\xea\x50\x73\x49\x6b\xf4\xc0\xbf\x15\xba\xa2\x73\xbf\xc5\xc3\x10\x44\x74\xa2\xdc\xf1\x32\xc3\x33\xeb\x36\xec\x2c\xbf\x04\xfa\x95\x80\xb7\x68\xf5\xce\xa7\xb5\x61\x7e\x58\x80\xaf\xf6\x32\x01\xc2\x74\xd6\x69\x74\x3e\x1b\xc5\x56\xb0\x67\x90\x2e\xee\x29\xd2\x91\x11\x28\x89\x69\xcf\xfa\x87\x9f\xc9\xcb\xf6\x6f\xbf\x93\x26\xd9\xd9\x25\xac\x41\x02\xfa\x9f\x1a\x06\x08\x1a\xde\xc0\x79\xcb\xc9\x67\x46\xd7\x9b\x63\xa0\x12\xed\x77\xd8\x2c\x9f\xfd\x4e\x3f\x16\x1f\x6c\xea\x28\xcc\x23\xfa\xc2\xa5\x43\xf5\xb1\xd0\x64\x4e\xc0\x48\x38\x32\x7b\xcc\x65\x2b\x85\x8f\x93\xff\x46\x3f\x7e\x94\x9e\xec\x8c\x9d\xb6\x56\x9a\x86\x98\x4f\x83\x1d\xf6\xac\x6d\x95\xf3\x8f\x46\xce\xbb\x6e\x65\x83\x65\x7f\xac\xd2\x10\x8d\xbc\xd0\xaf\x23\xab\x01\x01\xa1\x30\x1b\xeb\x48\xa4\x4c\xac\xcb\x91\x09\x44\x73\xd7\xe5\xa5\xc8\x8c\x64\x4f\xd3\x42\x05\x73\xb6\x78\xf1\x7b\x51\x74\xcb\x14\xe9\x0f\xac\x69\x4d\x1d\xbc\x6c\x96\x32\xb5\x97\x4a\xef\x28\xac\x08\xd7\x20\xb2\xea\x30\x44\x0d\x2a\xfb\x04\x93\xb4\x0d\xb2\x4e\xfb\xdb\xf5\x3c\x43\x09\x21\xe5\x2a\x10\xb5\x46\x61\xe1\x49\xd1\x65\x59\x1a\x7c\xf9\x1d\x65\x08\xea\x47\x2f\xb3\xbe\x16\x39\x5e\x30\x31\x2f\x19\xb8\x7c\x47\xe4\x68\x04\xa0\xfa\x29\xb5\x6b\x5a\xc9\x50\x67\x7b\xc6\x02\x38\xb5\xe9\x9e\x03\x0b\x1e\x55\x21\x46\xa0\xe8\x8c\x29\x4c\xfc\xa8\x35\xc1\x01\xc5\x5f\x34\x23\x87\x4c\xc1\x28\x75\x6e\x73\xa5\xde\xbe\x8e\x97\xfe\x21\x66\xb6\x5c\xb4\x46\x42\x77\x0c\x6d\x1d\x23\x90\xaf\x1b\x0f\x31\xb9\x58\xc8\x30\xe9\xac\x4f\xe2\xf5\xad\x59\x05\x82\xfb\xb8\x92\xbf\x94\x95\x84\x47\x7e\xf7\xbd\xe2\x3f\x7d\xd0\x2b\x63\xf7\xc2\x90\x88\xa5\x72\x51\x00\x91\x32\xff\xbb\x78\xed\x14\xde\xfb\xef\xd9\xfd\x31\xfd\xca\xb0\x3b\xa8\x0a\x23\xf3\x33\x98\x37\x60\xab\xad\x4f\x16\xdd\xf9\xdd\x44\x14\xf0\x4d\x00\xdb\x56\xba\x72\xd6\x3a\x3a\x13\xd2\xc4\x42\xf5\x49\xfd\x66\xc9\x88\xd2\xe4\x60\x1d\x13\xb5\x2f\x77\x50\x0d\xd6\x92\xbe\xc9\xd6\xbd\x3b\xaf\xa9\x24\x2f\xdc\xfa\xeb\x69\xb9\x8b\x0b\x57\x89\xb2\x80\x38\x40\xde\xc6\x37\xb4\x9a\xf4\x38\x1a\xe3\xfa\x42\x9f\xb5\x34\x61\xa0\xc6\x74\xeb\x5a\xa1\x8d\xbd\x60\x7a\x2b\x77\xa9\x6d\x3a\xb4\x64\xec\xd9\x74\x92\xf6\xde\x46\x0c\x9f\x11\xb5\xc1\x75\x6c\xb5\x9c\xb1\x34\x8d\xfd\x77\x95\x6b\x71\x90\x7c\x54\x82\x1e\x30\x3c\xb8\xb1\x49\x06\xc0\x03\xe3\x48\x4b\xe4\xea\x05\xa6\x90\x1d\x69\xb0\x74\x85\xe8\x58\xf7\xb4\x71\xc6\x35\xf9\x03\x95\xb9\xa3\xe2\x24\x7f\x1a\xd1\x2b\x11\x8f\xfa\xfc\x72\x21\xa5\x7b\x10\xe3\x19\xb6\x1a\xf1\xc1\x36\x06\xa8\x16\x16\xce\x3f\x1d\x62\xba\x93\x2f\xf4\xe6\x3e\x74\xb8\x42\x55\xe3\xaf\x52\x10\xbb\xd5\x71\xbd\xa4\x4c\xbf\x44\xb7\x14\x42\x2c\xb4\x5c\x2e\xf2\x1f\x98\x13\x1b\xa9\x6b\x7e\xdb\x9b\x03\xe3\x3d\x7d\x18\x8d\x5b\x8d\x90\x4c\xb4\x13\x6f\xe2\x69\xdb\x14\x69\x88\x16\x8e\x7e\xe2\x45\x35\x63\x54\xf0\x02\xa5\xea\x8b\x35\xa3\xa9\x9e\x83\xa1\x32\x72\x27\x41\x44\xb3\x3a\x60\xca"}, -{{0x66,0x56,0xf4,0xd4,0x71,0x81,0x57,0xc4,0xba,0xc3,0x8f,0xf7,0xab,0xe5,0xeb,0x1f,0x81,0x2c,0x0b,0x98,0x6d,0x9c,0x01,0x4a,0xba,0xd5,0xb0,0x9a,0xa6,0xc8,0xee,0x4a,},{0xf3,0x08,0x78,0x98,0xe4,0x52,0xbe,0x9e,0x30,0xae,0xcc,0x4e,0x8f,0xfe,0x0c,0x01,0x16,0x98,0x88,0x68,0x3f,0x62,0xa4,0x5b,0x8d,0xa3,0x82,0x99,0x01,0x4f,0x5b,0x4a,},{0x9c,0x2c,0x39,0x91,0x5a,0xed,0x6a,0xdd,0x00,0x4e,0x7d,0xd6,0x84,0xee,0x3d,0xcd,0xd1,0x0d,0x87,0xa4,0x87,0xf6,0x77,0xe7,0x3c,0x2b,0xce,0x0f,0xca,0x7d,0x50,0x87,0x96,0x46,0x41,0x50,0xa5,0x2a,0x44,0x0f,0x52,0x37,0x85,0x0a,0x00,0x9c,0x72,0x16,0x2d,0x9d,0x29,0x85,0x47,0x0a,0x33,0x49,0x0e,0x66,0xd3,0xc4,0x01,0x70,0x4c,0x05,},"\x94\xd9\xe5\xe5\xa7\xb7\x05\xd9\xd9\x76\xfe\x71\xe9\x4d\x3f\x7f\xa7\x86\x6a\xfb\xf7\xec\xe4\x24\xf1\x36\x32\x77\x99\xb2\xb2\x06\xce\x4e\xf4\xc3\xf3\xe7\x05\x55\x3a\xfc\x8f\xd5\xc1\x95\x2a\x4c\x16\x65\x8d\x4a\x78\xaf\xbb\x9a\x97\xf2\x71\x93\xc6\x5b\x65\xb8\x2e\x8f\x3b\x71\x51\x5f\xac\x82\x64\x0e\x0f\x8a\x5f\xb3\x5a\xe6\xfc\x6a\x3d\xb0\x51\xa2\x2d\x4a\x53\x00\x41\x3e\x6e\x33\xd1\x9c\x20\x13\xc2\x98\x3a\xca\x8a\xd6\xce\xc2\xce\x64\xa8\x14\x16\x4f\x06\x1a\x1a\x3c\x5a\x86\x10\xa7\x65\x0b\xfb\x54\x23\xd4\x36\x2c\xe0\x22\x06\xdb\xe4\xa6\xfa\x82\x6f\x03\xb4\x2a\xc3\xcd\x9e\xa4\xc6\x51\x40\x1b\x3c\xea\x82\xc3\x99\x3f\x6a\xf8\xb2\xc9\xe2\xe6\xff\xe6\x92\x80\xab\x3f\x09\xfb\xe9\x0d\xd5\x47\xcc\xda\x9d\x9e\x8e\x8a\x53\x7b\x3b\x36\x05\x54\x22\x7e\xd0\x70\x9f\x29\x31\x98\x98\x2e\xfb\x5e\xfb\x0e\x73\xe0\x00\x42\xd1\xa0\x63\xb5\x74\x52\x02\x7d\xce\x1a\x39\xe4\xb0\x06\x8f\x58\xb1\x11\xec\x5d\xc1\x42\xbf\x41\x9a\xd8\x93\xd5\x4f\x42\x60\xcb\xde\x76\x28\xf7\x83\xde\x84\x96\x38\x03\x06\xa4\xef\xf6\xd8\x28\x69\x10\x42\x59\xc9\x4c\x54\xad\x5a\xa8\xb0\x67\xc4\x24\x96\xcb\x88\xdd\x31\x15\x0e\xa0\x4d\x49\x9b\xfa\xc9\x1f\x4b\xb3\xe6\x8a\xf5\xaf\x7a\x56\x8a\x3e\x4c\xe7\xf1\x70\xd9\x86\x01\x16\x3f\x49\x52\xf1\xd2\x5e\x12\xe0\x0e\xf0\xa2\xd8\xf1\x11\xaf\xdb\x0f\xaf\xba\xd2\xbf\x8e\x8b\x9d\x49\x36\x3f\xca\x68\x18\x36\x17\xb5\x41\x27\x0d\xda\x46\x09\xb2\x61\x67\x29\xab\x1b\x8c\x42\xdb\xdd\x7b\xf9\x86\xaf\x8f\xba\x52\xe7\x33\xe4\x2b\xa0\x3c\x89\x2e\x1e\x1e\xc0\x6a\x90\xb1\x63\xf5\xa7\x9f\x61\x65\xeb\x73\x16\x97\x2a\xc1\xad\xbf\xcf\x1d\xca\xb0\x78\x47\xef\x82\xc2\xca\xb1\x01\x5d\xbb\x50\xaa\xdc\x79\xfe\x11\xc8\x32\x09\x8c\xac\xc3\x98\x20\xab\x08\x5b\x69\x63\xbd\x42\x16\x0e\xd6\x61\x3b\xae\x5e\x20\x1f\x17\xc0\xfd\x7f\x32\x35\x7a\xe3\x50\xce\x9c\xbb\xe9\x26\xfa\x42\xdc\xbd\x42\x2a\xc1\xbf\x09\xa1\x9a\xd1\xf6\x94\x69\xe4\xd1\xdc\xb1\x24\x11\x8e\xd4\x52\x2d\x35\x3c\x17\x42\x98\x65\x0f\xf8\x83\x82\xfa\x2f\xdb\xb2\x86\xc4\x5b\x18\xa9\xba\xf6\xf6\x76\x3a\xc2\x0c\x9c\xa4\x76\x7d\x34\x8c\x4b\x8d\xed\x63\x00\x76\x65\x7b\x85\xb1\x4c\x11\xae\x27\x37\xea\x29\xa4\x35\x15\xb7\xf0\x56\x74\xa0\xcd\x3e\xd4\xbf\x6a\x3d\x18\x9a\xe9\x72\x21\x8f\x87\x7c\xd8\xaa\x69\x49\x9d\x5a\x08\xc9\x9e\x44\x06\x94\xcc\xac\xcd\xf1\xf6\x42\xe1\x4e\x90\x10\x5b\xee\x6d\x98\xed\xee\xab\x3b\x4f\x33\x9f\x30\x01\x88\xae\xc0\xc1\x6b\xd6\x45\x21\xd9\x28\x73\x98\xe6\x48\xdb\x94\x33\x0e\xd8\xf6\xb9\xab\x6c\x7a\xd9\x3f\xfc\x43\xe8\x79\x2e\x63\x7c\x61\xbf\xf7\xd8\x56\xe5\x4e\xf4\x98\x73\x84\xe3\x12\xcb\x57\x01\x7a\x50\xea\xe5\x95\x2a\xbe\x19\xd8\x99\x9c\x8c\x82\xdf\xc4\x57\x98\xcc\x17\xc8\xd9\x49\x6b\xf5\x20\xec\xc5\xb7\x7f\xe2\x84\x91\x55\x66\xc4\x56\x85\xc3\x04\xa2\xac\xd5\x25\xef\x12\xc8\x6f\x38\xae\xf5\x54\xd8\xa2\x38\x47\x37\xcc\x41\x33\xfb\x7e\x2b\x65\xc1\x3b\xef\x31\x66\x8a\x6c\x2f\x60\xee\xcd\x84\x12\xee\xff\x7f\x6b\x60\x5c\xbe\x95\x08\x3e\x23\x3e\xc1\xa7\xbb\x36\xde\x23\x6c\x8a\x71\xba\x28\x72\xbe\x94\x6c\xd3\xb3\x89\x35\xf5\xda\x64\xc8\xfe\xc8\xe1\x4f\x45\xcc\xf6\x12\x4b\xab\x7f\x70\x56\x7c\x2f\x2b\xfd\xd5\x66\x67\x60\x95\x72\x03\x7c\x76\x14\x6c\x99\x17\x07\x65\x9b\x57\x09\xb0\x74\xe3\x45\x1f\x92\x1a\x2d\xf2\x83\xb9\x6a\xa2\x6a\xb4\x76\x62\x50\x16\xf1\x81\xad\x64\xc9\x91\x9c\xf4\x1d\x71\x4a\x1a\x9a\x5e\x2b\xb2\x6b\xaf\x87\x70\xb2\xeb\xa7\x7b\x77\x8a\x33\x26\x77\xa7\x57\x2e\xe3\xa2\xb1\xdc\x05\xf7\x35\x6b\xdc\xae\x5f\x55\xe3\x53\x29\xe3\x4c\xaa\x79\x43\x0b\x27\x0c\x03\x61\x60\xdc\x9f\xca\xab\x5b\x25\x45\x43\xac\x94\xb2\x46\x81\xf1\x71\x72\xb6\x15\x9d\x16\x62\x1d\x7a\xd0\xee\xbd\x89\x5a\x1e\x1d\x09\xb9\x16\xa8\x6f\xb4\x8e\x4c\x91\x66\x10\x57\xee\xe9\x5c\x08\x70\xed\x54"}, -{{0x14,0x38,0x3e,0x6e,0x56,0x04,0xc9,0x9c,0x24,0x8d,0x39,0xbe,0x51,0xd1,0x64,0xb1,0x34,0x42,0xb0,0x5e,0x51,0xd7,0x8e,0xcd,0x99,0x93,0x64,0x22,0x1a,0x45,0x03,0x6b,},{0x2f,0xc1,0x61,0x38,0x22,0x0a,0xb7,0x4b,0x3b,0xd4,0x46,0xf8,0xa7,0x14,0xb5,0x8d,0x54,0x63,0xd4,0x0d,0x43,0x67,0x92,0x50,0x07,0x47,0x4c,0x5b,0x9e,0x35,0xd4,0x94,},{0x45,0xe8,0xed,0x1a,0x75,0x1d,0xfc,0x3b,0x9b,0x7b,0xd7,0xa1,0x0b,0xf5,0xbd,0xcf,0x8c,0xa4,0x61,0x86,0x5a,0x49,0x0c,0x10,0x5f,0x10,0x45,0x29,0x41,0xcf,0x87,0x72,0x12,0x14,0xbf,0xbf,0x3a,0x35,0x60,0x6b,0x7c,0xe3,0x5d,0x6f,0x70,0xaa,0xf2,0xd5,0xea,0xdc,0xc0,0xde,0x03,0x5e,0x9b,0x2f,0x6d,0x7b,0x86,0x2f,0xc2,0x84,0x90,0x04,},"\xc4\x75\x3b\x7f\x7a\x6f\x6d\xea\x25\x15\xc6\xe3\xd2\x95\x61\x50\x6f\x4f\x36\xe0\xde\x84\x99\x92\x21\xf2\x28\xe2\x0b\xd5\x12\x8e\xd9\x3b\xdb\x8d\x11\x93\x23\x7d\x8e\x29\x41\x69\xa2\xbc\x44\x8a\xf9\xdd\x36\x06\x63\x01\xef\xb7\xfe\x12\x31\x35\x3c\x06\x23\xff\xe1\x11\x5d\xeb\xb6\x90\x5a\xc6\x94\x6e\xe3\x82\xa2\x7c\x3c\x09\xe1\xb1\xf5\xc1\x14\x93\xdb\xa3\x7d\xa0\xff\x6e\xea\x75\xd9\xfa\xb0\xee\x92\x6d\x70\x1d\xac\x2f\xc5\xb7\xef\x57\x88\x80\xa5\xd5\xee\xec\xad\xc1\xf4\xbc\xc4\xcd\x4e\xc6\xf2\xf1\x4f\x52\xa8\xc1\x64\x07\x2e\x6f\xde\x5a\xb2\xee\x9c\xee\x0b\x48\xe5\x1a\xf0\x55\xf9\xfe\xc7\xc6\x37\x50\xfe\xdf\x72\x33\x2b\x23\x86\x3a\x1e\x54\xc5\x2b\x46\x1a\x21\x50\x6d\xfd\xfc\x63\x88\x0e\x22\xd8\x9c\x89\x44\x12\x66\x6c\x92\x98\x21\xc0\xe4\x39\xe7\x45\x41\x5f\x71\x79\x69\xe6\x05\x85\x54\xd6\x4b\x94\x7a\x4f\xc9\xd1\x6a\xca\xe3\xe4\x9a\xec\x08\x80\x1a\x09\xd9\x72\xf7\x9e\xad\x68\xd5\x29\x76\x80\x69\x73\x5c\xaa\x74\x2b\x45\xa5\x83\x05\x81\xb8\x0c\xa0\x61\xa6\xc1\x51\x5e\x3f\x7d\x5a\x93\x37\x87\x8c\x19\xfc\x94\xee\xf2\x26\x98\xea\x6c\x4d\x05\xf9\xed\x41\x1b\x6b\x8f\x05\x2b\x5f\xf1\x5d\xc2\x3a\x64\xbe\xea\xae\x99\xf8\x48\x93\xde\x3d\xf9\x40\xa4\xe0\xb8\xe9\x93\x93\x01\x39\x05\x2d\x99\xbe\x47\xbc\xa8\x77\x5f\x85\x63\xbd\x40\x26\xb7\x13\x43\xd5\x19\x68\xf2\x33\x75\x28\xf4\xc9\xdb\x8b\xbd\x0a\x29\x8a\xf0\x4b\x27\x69\x5d\x86\xb7\xf7\xba\x6c\x4c\xcc\x62\x73\xfe\xbc\xd8\xf7\x5c\xff\x26\x69\x95\x24\x4f\xc1\xfa\x13\xd8\xd8\x43\xf0\xbf\xf4\x9c\xc2\xd5\x08\xf4\xa2\xb3\xaa\xd1\xd9\x5f\xb2\x2a\x2b\xc6\xad\x1b\x96\x6b\x08\x12\xd9\x90\x70\xbb\xa0\x7c\x92\x3e\xe4\xd0\x81\x07\x48\x6d\xc0\x1a\x06\xdb\xa6\xf1\xd5\xf1\x05\xac\xea\xde\x33\xb1\x66\x51\x0e\x42\x7e\xbb\xce\x52\xa3\xe7\x83\x1f\x0f\x78\xa3\xc6\xe0\x72\x60\x83\x34\xd8\x02\x1c\x33\x8a\x73\xcc\x0c\x47\xf1\x9c\x9f\xae\x40\x3b\x97\x16\xd0\xd1\x5f\xbd\xf6\x46\x6b\x08\xf6\xac\xce\x3f\x50\xa7\x03\xb1\xde\xa8\xd8\x26\xdf\x84\x2c\xa1\xba\x20\xd2\x9f\x45\x48\xac\xfc\x75\x4c\xf0\x11\xf5\x70\x68\x1b\x59\xe4\xda\x25\x38\x5e\xbd\x6d\x5c\x3a\xdc\x93\x05\x29\xe1\x66\xce\x67\x05\xf6\x01\x02\x10\xdb\x10\x64\x62\xb3\x33\x32\x04\xe7\xad\xad\xee\x66\x06\xa5\x62\x06\xb4\x7e\xef\x20\x74\xb1\x16\xe2\x2a\x61\x54\x18\xec\x2c\xdc\x33\x1f\x1e\x19\xe0\x7e\x8a\x37\xb9\x2d\x69\xdf\x07\x34\xe0\x85\xda\xee\xb9\x01\xec\x6e\x8c\x35\xf1\x03\xf1\xd8\x6e\xf0\xd2\xa2\x65\x2b\x01\xd1\x83\x59\x7e\x4c\xfd\xee\xdf\xe5\xdf\x9a\x7e\xf6\x6a\x1c\x79\x6a\x37\xa2\x71\x13\xb9\x44\xdd\x7b\xa1\x7c\x46\x00\x15\xab\x8a\xce\x45\x1c\x57\x85\x0e\xc6\xc2\x90\xc5\x4e\x51\x13\xf5\x5e\x99\xa8\xe6\xe4\x71\x1e\x3b\x78\x17\xbf\x91\xa5\xad\xb3\x7f\xb9\x46\x1b\xe6\xb1\xb5\x5d\x58\x60\x46\xe4\x2a\x54\xc5\xde\xf4\x07\x6f\x1f\xf6\xc3\x1b\x80\x6f\xc6\x02\x47\x43\x56\xaa\x28\x99\xea\xe7\x0f\x5e\x5a\xbf\x1f\x75\xa7\xf2\x4c\x13\x4c\xde\x11\x79\x3b\xb1\x62\xe0\x3a\x58\x3d\x5b\xe0\x46\xac\xc7\x34\x56\xd1\x2d\x50\x9d\x92\xf7\x70\x57\x68\x68\x6f\x6c\x71\x4a\x4e\x57\xec\x88\xb7\x13\x98\xe2\x3e\x83\x5d\x6d\x65\x47\x22\x59\x96\xb7\xed\x08\xf3\xb7\x44\x3b\xb1\x7c\x89\x94\x09\x49\x3d\x0e\xfe\x84\x55\xbe\xc8\xe8\xc2\x84\xa3\xb1\x49\xa5\xb4\xca\x63\x1e\xa6\x20\xb1\xbb\x81\x7c\xed\xab\xa5\x0b\x04\x44\x11\x84\x9d\x26\x0a\x6f\x2a\x0d\x3f\x2c\xce\xec\x38\x42\x71\x9a\x5e\xa4\xfe\x18\xdd\xe0\xd4\x2d\xcb\x33\xad\x21\xe6\x45\x33\x25\xaf\x6f\x3c\x00\x9f\x2b\xb9\x78\xd3\x0c\xee\xae\x9a\xa4\x92\x8b\xf7\x37\x67\xcd\xa9\x29\x2a\xb8\x93\xce\x5f\xa3\xaa\x4c\x23\x21\x63\xb4\x5c\x64\xed\x79\x77\x77\x9b\x1c\x0c\xaf\xcf\xc2\xb9\xfa\x08\x4a\x32\x4f\x11\x3a\xde\xec\x21\x8b\x47\x35\xb6\xb4\x64\xdb\x6d\x46\xc2\x79\x1a\xf3\x45\x5f\x1c\xa5\xea\x1e\x9a\x04\x8c\x05\x1a\x54\xdf\xa0"}, -{{0x59,0xb0,0x72,0x63,0xb2,0x2c,0x0a,0x38,0xbb,0xc5,0x91,0x05,0x95,0x94,0xb2,0xbd,0x92,0x7e,0x80,0x59,0x61,0xdd,0x07,0xe1,0xf9,0x42,0x45,0xb2,0x3a,0xa2,0xe0,0x16,},{0x0b,0x1e,0x4c,0xf5,0xaf,0xf2,0x78,0xec,0x65,0xb4,0x05,0xf5,0x10,0x8e,0x1b,0x5b,0x18,0xa9,0x69,0xad,0x1f,0x1e,0x63,0x81,0x91,0x2c,0x82,0xd6,0x98,0x90,0x7c,0xba,},{0x88,0x6d,0xa3,0x3e,0x35,0x53,0x28,0x5e,0xa5,0x9c,0x14,0x31,0xb6,0xe8,0x6e,0xa4,0x9b,0xb6,0x8b,0x2e,0x0e,0xfd,0x2b,0x15,0x7e,0x77,0x91,0xb7,0x4f,0x35,0xa2,0x42,0x1b,0xb3,0x59,0xf3,0xdc,0x1e,0x4c,0xe5,0xf1,0x1f,0x73,0x65,0x2e,0x03,0xbf,0xc0,0xb4,0x29,0xc5,0x8f,0x0f,0x2d,0x74,0x18,0xc7,0xc2,0x0b,0xce,0x2e,0x2d,0x19,0x01,},"\x08\xce\x0d\x4d\xb5\xc2\xaa\x50\x0a\x19\xef\xbc\x8d\xc8\x54\x92\x50\xf7\xdd\x46\xa7\xa9\xa5\x40\x74\x17\xb3\xd5\x18\x20\xe4\xb0\xd6\x12\x75\x58\x3f\x56\xf8\x97\xfd\x94\x2b\xdd\x73\x11\xad\x6b\xaf\x73\x81\x28\x56\x7a\xf6\x55\x8d\x75\x90\x6a\x02\xc4\x34\x3a\x99\x55\xd5\x9b\x11\x08\x8c\x58\x8d\xc7\xdd\x08\xf6\x79\x65\xc5\x60\x2a\x56\x92\x8d\xda\x4a\xe1\x64\x29\x31\x63\xb5\x17\xca\x17\xde\xd0\x4f\xe4\xab\x2f\x97\x89\x13\x0a\xe9\x6a\xb2\x31\xf0\x7e\x09\x01\x5b\x78\xf3\x84\x8c\xef\x43\x5d\xb0\xad\x9f\x35\xe0\xfb\xc9\x85\x1e\x3e\xcf\xc9\xfb\x18\x6d\x14\xd8\xda\x4d\xda\x45\xd0\xb3\xeb\x3e\xe4\x50\x0c\x10\x1e\x31\x94\xb5\x72\x14\x06\x89\xcd\x75\xda\x12\x87\xb2\x54\xf3\x74\xe3\xd9\x33\x26\xae\x5f\xaf\x11\x40\x18\xac\x71\x4b\xd0\x03\x75\xd9\x2a\x8b\xb6\x59\xc3\x29\x12\x83\x1f\x4f\x20\x77\x6e\x9e\x2c\x25\x02\x9f\x0a\xff\x39\xfd\xda\xc7\x24\x15\x43\xa0\x36\x6b\x84\xde\x7b\x1f\xf2\x3e\x8e\x4d\xc0\x93\xdf\x0d\x2d\xd5\xe5\x3e\x68\x47\x94\x8c\xf3\xd0\xff\x3f\x56\x4a\xd9\x4d\x9c\xc0\x0a\x5e\xa5\xb6\x95\xe4\x08\xbf\x50\xf5\xba\xb2\xf6\xea\x87\xba\x8a\xd3\xa1\x94\x01\x95\xcf\x1b\xc2\xb5\xb3\x48\x47\xad\x3a\x5e\xff\xb8\xa7\x82\x3d\xe9\x1e\xf1\x63\x38\x69\xd1\xf0\x46\x43\xaf\x4d\x82\x6a\x59\xe7\x8b\x9d\x18\x63\x12\xb3\xd9\x72\x26\x36\x54\xac\x55\x87\xb8\x0b\x71\x76\x46\xf3\x10\x03\xdb\x81\xac\x70\x86\x0d\x3f\xc8\xcd\x3a\x6a\x0a\x0d\x57\x6d\x25\x73\x1e\xf7\xb8\x96\x62\x63\xd7\xa0\x5b\x55\x00\x9e\x8a\x23\xda\xc0\xf9\xa2\x1a\x24\xb0\x6e\x13\x90\x0e\x44\x44\x46\xfd\xfe\x56\xcb\xc1\xa0\x26\xdf\x41\x06\x6b\x20\x1b\x14\x81\xe5\x61\x58\x92\x6c\x0c\x9e\xa9\x0f\x0c\x64\x5a\xab\x4b\xef\x12\xd4\xe0\x72\xcb\xfd\xc3\xc3\xd5\xe0\xc7\x2c\xf8\x8f\x16\x6d\xe0\x48\x87\x4f\x35\x34\xe0\x40\xc6\x2b\x16\x62\x82\x1b\xdd\x16\xb0\xe8\x58\x28\x17\x46\x1c\xb2\x68\x92\x79\xb4\x46\xd7\x0c\x8a\xc2\x0a\xd0\x3e\x59\x8c\xad\x49\x08\xc5\x2c\x35\x0d\x42\x43\xee\x8a\xed\xb8\x7a\x4a\xf9\x77\xf7\xdb\x57\xcd\x94\x7b\x47\xd6\xbb\x51\x40\x9d\x80\xd8\x1f\x6d\xb0\x3c\xb9\xa6\xa6\xb7\x98\x12\xf4\x70\x69\x0a\xfc\x18\x36\xa5\x31\x33\x80\x94\xcf\x26\xd3\xc1\x23\x2f\xd5\x60\x5d\x8f\x8c\x55\xb6\xf8\xa2\xa7\xef\x1e\x0c\x78\x15\x55\x94\xb2\x37\x95\x6d\x2a\xba\xd6\xa9\xad\xcd\x58\xe1\x1c\xcd\x35\xcc\x99\x5b\x9a\x0a\xec\xbf\x7f\x57\x41\xac\x05\x1b\x04\xef\x6b\x97\x44\xb5\x6f\xcc\xb4\x63\x98\x52\x8b\xb3\x1f\xbe\x84\xe0\x78\x84\x3e\x69\xbf\x33\x88\x98\xcd\xef\x69\xad\x41\x87\x23\x95\xe4\x6b\x59\x39\x04\x82\x55\x47\xe0\x0b\xda\xf2\x21\xf8\xfa\x58\x7e\xa2\x03\x7f\xfb\x9a\xc9\x30\x7d\xd3\xf8\xf3\x5e\xc5\x38\x6b\xa9\x66\x33\x3e\x2a\xc8\x72\x7b\x0e\x1b\x80\x61\x2d\x3c\x7f\x2c\xb8\x8b\xaa\xca\xdf\xe2\x16\x3b\xc3\x8c\x88\x84\x2e\x76\xa3\x94\x57\x1d\x40\x61\x0e\x8a\x29\x76\x02\x79\x37\x63\x29\x6e\x3e\xab\xf7\x20\xe9\x84\xb2\xed\xd2\x8c\xf5\xc4\xe0\xf9\xa0\xf7\x6a\xce\xba\x28\xcc\x1f\x1b\x69\xff\x1d\x35\xb4\xbd\x33\x47\xb7\xf9\xa9\x5a\x4c\x1e\xa1\x07\x34\xe1\xc9\x18\xeb\x96\x24\x9d\x0c\xc7\x0b\x47\x7f\x6f\x23\x80\x9b\xbd\xa9\x01\xd5\x3f\x48\x5a\x71\xf5\x08\x60\x02\xc1\xb7\x1e\xfc\xc4\x1c\xb1\xae\xb5\x12\x2a\x3f\x3b\xfc\x96\xc5\x1a\x55\xd7\x5c\x02\x98\x42\x88\xbe\x65\x78\x87\x85\x4c\xfa\x73\x89\x74\xbc\xd5\x44\x01\x46\xf9\xbb\x14\x04\x0d\xe5\x4f\x54\x44\xad\x43\xb7\x9a\xf9\xbd\xb2\x4e\xd6\xa4\x8e\xb2\xfd\xee\xd7\x1f\x31\xf0\xec\xe1\x02\xe9\x18\xe9\x56\x35\xc7\xa0\x38\x63\x3e\xe3\x48\xd8\xb5\x78\x16\x52\xd5\x05\x9d\x21\x5a\xc9\x7f\x30\xea\x20\xd2\x77\xeb\xbf\x15\x24\x69\x05\x42\x8a\x7b\xec\x02\xb8\xf9\x26\x31\x5b\xad\x67\x23\xfd\x64\xd7\x1f\xc9\x5f\x33\x33\x64\xcb\xe9\x0d\x46\x46\x33\x3c\x40\xdd\xa6\xd1\xd4\x33\xb7\xc1\x95\xa7\x58\xdb\xb4\x03\x8a\xf5\xdc\xc7\x23\x2d\x45\x47\xf5\x40\xe3\x94"}, -{{0x5c,0xc1,0x15,0xd8,0x39,0xe0,0x58,0xcd,0xb6,0x51,0x8e,0xe9,0xc1,0x61,0xc0,0x04,0xd8,0x8b,0xd3,0x90,0x8d,0x3c,0xf6,0xd5,0x2c,0x8f,0x29,0x6a,0x1a,0x07,0x6b,0x9b,},{0x1e,0x8f,0x33,0x05,0xbf,0x2f,0xa1,0x1b,0x17,0xd9,0x24,0x16,0xab,0x0e,0xa7,0x62,0x39,0x6d,0x88,0xf2,0xf9,0x70,0xef,0x0b,0x10,0x0e,0xd3,0xbf,0x5c,0xc1,0x34,0x40,},{0x03,0x71,0xc2,0xd6,0x4c,0x5e,0xc0,0xc8,0x27,0x6c,0xa5,0xff,0xa6,0x15,0xef,0xf4,0x2f,0x9e,0xff,0xfc,0x58,0xdd,0x8e,0xcf,0xcf,0x67,0x62,0x0a,0x9b,0xcb,0x38,0xfa,0xf1,0x18,0x93,0x2b,0xf2,0xcd,0x5b,0x92,0x05,0xfa,0x55,0x13,0x34,0xdf,0x2a,0x75,0x7c,0x59,0x77,0x44,0xf7,0x91,0xf3,0x71,0xfb,0xed,0xd9,0x8b,0x21,0xf7,0x34,0x05,},"\x53\x3e\x49\xc1\xd5\xf3\x3c\x5e\xc4\xbe\x84\xc6\x19\xf4\xec\x64\x9c\x25\xfd\x70\xbd\xcf\xe2\x57\xa6\x3c\x33\x73\xa4\xd0\x89\xc8\x9a\xf6\xee\xb7\x16\x0d\xd7\x7a\xb6\x6b\x1e\xe7\xe1\x08\x50\xab\x4f\xc1\xf3\x51\x32\x33\x2b\x53\x78\x9b\x2b\x01\x40\xc4\xf2\x0f\x97\xf2\x14\x20\x72\xd6\x24\xaf\xf7\xaa\xd3\x24\xaa\xcd\x06\x8c\x03\x5a\xff\x52\xfa\x71\x2f\x4e\x74\x83\x2d\xe0\x31\xb2\x64\x23\x14\xd1\x71\x10\xde\xe6\xfb\x85\x76\x2d\xc3\x0d\x7e\x97\x78\x2f\xd1\xfb\xff\x71\x79\xf0\x09\x17\xf5\x5a\xf7\x50\x3a\x5b\x7e\x23\xc6\xea\xdb\x65\xe1\x04\xf1\x51\x7b\x66\x24\xc9\xe5\x20\x4b\x3f\xd2\x9a\x65\x85\xe9\x2c\xe3\xa3\xee\xe2\xc5\xae\x17\x79\x20\xf7\xb4\xab\x2c\xac\x87\xd6\x72\xab\x6b\xaa\xc1\x18\x6d\x90\x4a\xea\x34\x98\x53\x4e\xb5\xab\x23\xe4\xac\x4c\x0d\xdb\x0d\x82\xa5\xae\x53\x1d\x76\x54\x9d\x36\x76\x28\x57\x7b\xac\x42\x35\xe8\x97\xd9\xfe\x20\x55\x22\x04\x7d\x21\x4f\xf6\xcc\xf3\x11\xc4\xe3\x97\x82\x7d\x97\xf2\x86\x8e\x70\xac\x17\xd2\x8e\x33\x49\x99\x74\x4d\x35\x93\x76\xa4\x82\xfd\xcb\x41\x4b\x02\xb2\x68\x7b\x96\x2e\xe8\x08\x6e\x57\x3f\xe0\x00\xdc\x51\xde\xe0\x68\x79\xc6\x84\xe2\x5f\x94\xce\xe5\xe8\x61\x34\x7e\x7b\xe7\xfc\xa5\x49\xa0\xf7\x65\x13\x6a\x2f\x4b\x88\xfe\xde\x07\x02\x4d\xd2\xfc\xe1\xf6\xd0\xc0\x35\x4d\xa1\xa1\x6e\xf3\x66\xb3\x15\xb3\xf7\x23\x30\x31\xf9\x79\xb7\x0e\xac\x6e\x23\xbf\x3b\x34\x9e\xfb\xd0\xe4\xf5\x3f\x4d\x5c\x41\xfc\x00\x42\x76\xa5\x96\x70\x65\x9f\x69\x05\xef\x03\xd2\xfc\x09\x8d\x58\x9f\xcb\xc1\x32\x82\x82\xfa\x22\xb1\x0d\xb8\x3c\x5d\x70\x86\x59\x94\xfd\x19\xd7\x60\xa3\x9d\x47\x6e\x02\x33\x0d\x2c\x6d\x19\xe7\x42\x26\x7d\xd3\x65\xbb\xe1\xfe\x5c\x71\x1a\x95\xb1\x84\x50\x8c\xe4\x8c\x1c\x96\xd7\xe6\x39\x90\xb4\x08\xd4\x50\x89\xbe\x79\xe3\x2f\x9c\xb0\x16\x2f\xd1\xe7\xd0\xd1\x9d\x97\xd0\xae\x78\xff\x82\x4c\xc6\x98\x94\x86\xc0\xbd\x03\x83\x52\x55\x1f\x37\x49\x9e\x9e\x98\x26\x80\x4e\x9d\x26\x24\xad\x0c\x7b\x75\x34\x56\x0f\x45\xfd\x7d\x32\x4b\x8e\x51\x7e\x01\xc9\xb2\x74\x3c\x14\x97\x9c\xfd\x51\x2b\xc3\xfe\x66\x72\x79\xb3\xa2\x77\xfb\x46\x3e\x9d\x73\x49\xb6\x4f\xfc\x9f\xe6\x08\x84\xc2\x1e\x48\x10\x81\xed\x70\xe6\xda\x5a\x35\x39\xc4\x48\x97\x1f\x0d\x97\x87\x28\x9f\xcb\x00\x80\xf2\x19\xe9\x94\x49\xf8\x29\x8c\x42\x47\x5f\x87\xfd\x10\xae\xb5\x09\xc5\x30\xcf\x6a\x57\x74\x8e\xb8\xf3\x56\x21\x61\xfa\x48\x75\xea\x95\x3f\x09\x65\x9c\x7d\xf7\xa9\x95\x0f\x03\x17\x46\x7c\xb4\xe5\x36\x6e\x19\x6e\x32\xf5\xe2\x69\x67\x33\xa2\x5e\xac\xbd\xe4\x92\x10\x49\x07\x62\x06\x0e\xa2\x31\x37\x0d\x40\x90\x42\x9b\xb0\x6b\xb8\x67\x39\x9e\x8d\x37\xbf\x5d\x21\xa0\xe7\x21\x47\xe4\x96\xcf\x3b\x7d\xd6\xfe\x6e\x5e\xde\xa9\x66\x8d\x80\x21\x90\xa9\x1c\x60\x0e\x29\x52\x3f\x8e\xb9\x04\xe4\x8b\x70\x41\x2b\xc1\x0a\x70\x20\x98\x4c\x5f\xf0\xf5\xf3\x83\xf2\x14\xae\x59\x4d\xc8\x59\x71\xe4\x80\x37\x28\x48\xd0\xd7\xe7\xcc\x5c\x18\xff\x88\xba\x9b\x26\x2d\x78\x84\x69\x8a\x41\xc6\xc7\x81\x9c\x03\x19\xfd\xc6\xbb\x07\xb9\x1d\xc1\x69\x4d\xaf\xe3\xaf\x37\xa5\x38\xbf\x2b\x2d\x8c\xac\xb2\x7d\x24\xcd\xc6\xea\xdb\x8c\x6a\x2e\x6b\x7d\xf8\xa4\x65\x4a\xe9\x37\x85\x0c\x89\x0a\xd9\x30\x98\x0a\xfc\xc1\x49\x2d\xb8\xa0\x16\x8c\xbc\x9f\x10\x65\x7e\xb4\x8d\x2a\xc8\x7f\x51\x75\xd2\x3c\xae\xd4\xb5\xe6\xf1\x0b\xbe\xaa\x5e\x33\xfc\x5f\x64\x18\xd6\x3b\xa3\x74\xab\x1a\x3c\xbd\x36\xb7\x29\xdd\xbd\xab\xa9\x89\xd4\x64\x5e\x3a\x66\x13\x0b\xae\x41\x7c\xad\x08\x6d\xad\xd3\x08\x43\x35\x25\x14\xc3\x75\xf2\x57\x1a\xba\xf9\x3e\x9a\x07\x71\xfa\x10\x3a\xe9\x25\x85\xb0\x4f\x55\xc4\x34\x76\x9b\x43\xd6\xd2\x2f\x75\x3f\x93\x06\x03\x6e\x53\x52\x4f\x6f\x4d\x9c\xcb\xd2\xc3\x03\x17\xa8\xe8\x99\xf3\x16\x14\x90\x35\x89\x4d\xa9\x45\xb7\x6d\x90\x82\xbf\xee\x32\x8e\x7a\x31\xb6\x63\x28\xee\x8b\x94\xe0\x68\xc7"}, -{{0x75,0xa5,0x03,0xf4,0x8f,0xfc,0x22,0x16,0x17,0x67,0x25,0x19,0x11,0x1b,0xf9,0x0d,0xa3,0x9d,0xa9,0xea,0xb2,0xe2,0x91,0x4f,0xd3,0x75,0x5f,0x10,0xf5,0x39,0x36,0x68,},{0xf6,0x80,0xcc,0x0f,0x63,0x58,0xcd,0xcf,0x53,0x7a,0xa7,0x11,0x28,0xcf,0xad,0xfc,0x0f,0x3a,0x89,0xc1,0x00,0xaa,0x34,0xbc,0xd2,0x42,0x7e,0x24,0x8b,0x6e,0xd5,0x0b,},{0xdf,0x28,0xe3,0xe6,0x30,0x36,0x08,0x67,0x86,0x4b,0xc4,0x1e,0x43,0xfd,0x7d,0xde,0xb5,0x28,0x76,0xdc,0xe9,0xb2,0x34,0xa3,0xfc,0xc3,0xd8,0x54,0x9d,0xb0,0x11,0x2e,0x17,0x63,0x90,0xa6,0x85,0xeb,0xd4,0x84,0x93,0x6e,0x25,0xc0,0x8c,0x8a,0x38,0x78,0xa3,0x7b,0x3c,0x4e,0x23,0x9a,0xd0,0xa0,0xe5,0x01,0x99,0x37,0xff,0xbc,0xd4,0x07,},"\x7b\x01\x09\x04\x23\x23\x6c\xb4\xb1\x3c\x41\x77\xfc\xe5\x2a\x7f\xf6\x58\x05\x88\xcc\x2e\xb5\xa3\xf3\x9f\xf5\xd0\xc7\x3e\x01\xe0\x1b\xf7\xbd\x74\xaf\xe4\x15\x12\x50\xc3\x91\x42\x6e\xa5\x07\x27\x1b\xea\x1d\x6d\x85\xf0\xb2\xfe\x35\xc4\x05\x00\xf9\x8d\x06\x56\xc6\x38\x8f\xc9\xef\xba\x18\x37\xdb\x22\xdf\xa2\x9d\x89\x26\x76\xf5\x0e\x57\x5f\xe8\x9f\xd2\x93\x89\xd0\x9d\x08\x0b\xad\x67\xba\x54\x4c\xac\xab\xf5\xa7\x73\x82\x37\xc5\x5e\x28\x75\xed\x49\x16\x30\x2a\x2b\x4d\xc4\x96\xe7\x42\x73\xbf\x05\x19\x11\x37\x81\x0e\x50\xe4\x81\x95\x26\x0b\xab\x6d\x81\xf9\xc8\x05\x62\xee\x73\xcc\xb9\x33\x3c\xd9\xb6\x1d\xaf\x5b\x00\x38\xa4\xe6\xc5\xc9\x58\xa9\x1f\x68\x50\x8c\x1d\x88\x25\x19\xc1\xaa\x4f\xfc\xc5\x35\x62\x46\x3a\x0a\xe3\x01\x63\x69\x6f\x84\xb9\x7c\xcb\xd8\x67\x98\x20\xed\xd3\x61\x7e\x7b\x89\x6e\xef\xfe\x34\x1e\xc6\xb5\xb0\x3f\x73\xb6\x25\xd7\x41\xc6\x55\xfe\x6e\x82\xd1\x1d\x47\x8a\x7d\x54\x3f\xf6\xc0\xfa\x3a\x3a\x8c\x94\xa6\x16\xfb\x84\x70\x70\xd1\xfb\xdd\xe6\x01\x0f\x02\x6b\x08\x9c\xd8\x63\xc3\xbd\x29\xb1\xc4\x26\x9f\x77\x65\x9e\x51\x57\x28\x89\x0c\x97\x3b\xe8\x7f\x0b\x83\x3c\xa5\xaf\x6b\x4c\x31\x33\xad\x4f\xa4\xf9\x16\x55\xc6\xad\xb5\xb7\x23\x5c\x27\xfe\x34\x82\x84\xf3\xf1\x33\x66\xa6\xa0\x3a\xd2\x2b\x87\xc6\xf5\x58\x4b\xde\xae\xa4\x8c\x70\x32\x5d\x6e\x33\xa4\x75\xf5\x05\x11\x06\x38\x75\x19\x2a\x87\xed\xc3\x88\x08\x9b\x84\x39\x53\x90\xc2\xa3\xad\x89\xa2\x25\x95\xdc\x4a\x71\x5a\x42\xa2\xc0\xef\xde\xf6\x7b\x35\x4b\x34\xfc\x75\xca\x98\xdf\x91\x3e\x75\x9e\x51\xc7\xf6\x25\xdd\xd5\x98\xac\x22\xd4\x21\xde\xcb\x57\xbe\xbd\x54\x22\x0e\xc6\xda\xa5\xec\xe7\x69\xd2\xe0\x1b\xe7\xb6\xbe\xe2\xff\x5a\x0b\x06\xb3\x2d\x6d\xa1\xd7\xbc\x05\x7e\x3a\xbf\xaa\xb2\x42\xa3\xf7\xe6\x64\x6a\x15\x9e\x4f\x50\x5e\x46\x62\x98\x2b\x13\xd0\xcc\x1f\xba\x91\xd1\x03\x09\xa4\x2d\xc1\x08\x7c\xf1\x0d\x36\xe3\x1f\x17\x06\x15\xa0\xac\xb5\x08\xbf\x68\x3e\x2d\xe0\x0c\x87\x64\x0d\x30\x4a\x94\x7b\xc4\x97\x1f\xf3\x61\x9c\x72\xab\xd8\x3c\x7b\x2c\xbb\x34\x64\xc4\x04\x0c\x26\x62\xb5\x85\x08\xb7\x46\x80\xcf\xa6\xde\x06\xe8\xd2\x1e\x3b\xec\x85\x11\x19\x93\x12\x68\x00\x09\x07\x1f\x70\x6b\x7b\x13\x3a\x24\x87\xd5\x74\x5f\xfa\xdd\x5d\xc0\xeb\x2b\x55\x3d\xf4\x40\x78\x7f\x01\x1d\xda\x37\x71\x9f\xa7\x13\x15\xe8\xb2\x91\xef\xd7\x7d\xa3\xba\x14\xfb\x99\x5f\x03\x57\x1a\x3d\xb5\x22\xb6\x3c\x60\xbe\x56\x19\x94\x16\x99\xb3\x92\x22\xb5\x9d\x0f\x23\xe5\xeb\x37\xea\xd4\xb7\xf7\x50\xed\x4a\xbf\x4d\xb8\x7c\x70\xda\x66\x5b\xef\x4d\x7a\x29\x21\xb2\xc9\x98\x97\xf2\x32\x1c\x9b\xe6\x07\x5e\x74\x4c\x82\x28\x63\x9a\xb7\x36\xdb\xeb\x2b\xea\xb4\x40\xc1\x56\xa3\x9a\x2e\xfd\x26\x1d\xb5\x08\x55\xe3\x04\xd9\xcf\xeb\x99\x14\x1c\x61\x35\x58\x10\x9f\x21\x47\x4d\x27\x2a\x2d\x90\x6d\x48\x93\x93\x4a\xff\x8e\x08\xa4\xfc\xee\x96\x4a\x5c\xd0\x07\x32\xfd\x33\xaf\x29\x84\x9c\x8d\xfc\xa6\x59\x79\x42\x18\x57\x18\x5c\xf6\x29\xf8\x68\x07\xa8\x59\x73\xd3\x44\x0a\x6b\xf8\x11\xa5\x8d\x04\x13\x87\x24\x98\x11\xec\x04\x7e\x5e\x8b\x34\x3b\x23\x87\xd0\x18\x1e\x0d\x0b\xd4\x61\xef\x10\xe8\x16\x4a\xae\x35\x7d\x9b\x29\xdc\x0a\xce\x3e\xc6\xd7\x43\xae\x34\x54\xab\x9f\x84\x2a\x28\xd5\x71\x02\x17\xdf\xfe\x50\x34\x4e\x8d\x93\x2f\x18\x01\xb0\xe8\xf9\x66\x19\x8e\xf1\xc9\xcc\x69\x69\xf3\x47\x34\xaa\x6a\x63\xae\xaa\xb4\x33\x9f\x75\xd3\x4f\xfa\x8a\xcb\x93\x7e\xd9\xc7\x30\x92\xa3\x09\xa9\xb8\x4a\x25\x01\x1e\x31\x14\xc2\x65\xe4\xf6\x02\x33\x7e\xb6\x99\xb5\xa2\x2d\x57\x2b\x03\xe4\xda\xd0\x3b\x04\x61\xc0\x0d\xb9\x67\x9b\x72\xfc\x5b\x49\x3e\xf4\x48\x6f\x85\x53\x5d\x81\x3a\x58\x08\x03\x85\xaf\xd4\xe8\xd8\x71\x82\x80\x34\x33\x4b\xfe\x44\x1d\x18\x98\x4e\x4d\xfc\xde\x02\x44\x03\xb5\xae\x66\xcc\x50\xa4\x73\x01\xb5\x7f\x9a\x32\xf7\x40\xbd\xc7\xff\x1d"}, -{{0xd8,0xaa,0x2a,0x0a,0xa5,0x14,0xfd,0x84,0x5f,0x7a,0xa6,0x6b,0x83,0xc0,0xea,0xbb,0x9c,0x16,0x02,0x3a,0xbc,0x16,0x95,0x77,0x34,0x50,0xb2,0xbb,0x33,0x25,0x22,0xf2,},{0xe4,0xe8,0xd6,0xb2,0x98,0x24,0x8c,0x15,0xfe,0x08,0xf8,0x7a,0x3b,0xc6,0x08,0x4b,0xf2,0xd6,0x4d,0x7f,0x1e,0x4b,0x2d,0x51,0x59,0x9e,0x9f,0xad,0x9c,0xc9,0x10,0x92,},{0x14,0x6f,0x65,0xd4,0x3e,0x71,0x55,0x42,0x89,0x4b,0x79,0x00,0xa2,0xf8,0xcd,0x4b,0x17,0xd3,0x87,0x0a,0x61,0x00,0xe3,0x7d,0xe0,0x05,0xb0,0xdb,0x5d,0x81,0x51,0x24,0x6d,0xe4,0xee,0x38,0x42,0xd3,0xeb,0xca,0x20,0xa5,0xda,0x22,0xa3,0x63,0xa7,0x57,0x5e,0x7a,0x55,0x12,0x82,0x95,0xf2,0x72,0x11,0x48,0x4a,0xf5,0x7c,0xd5,0x31,0x09,},"\x08\xde\xb3\xb8\x32\xf5\x2d\x65\x56\xf7\x8c\x3f\x0a\xbe\x46\xf1\xef\xe4\x5e\x3d\x5d\x88\xe7\xf8\xed\xf8\x03\x67\x0c\xe4\x61\x29\x21\x74\x9e\x9e\xce\x63\xfd\xc9\xbe\xf2\xba\x48\x38\x12\xbb\x62\x2b\xe7\x44\xd4\x04\x04\xfd\x6e\x09\xc9\xe1\xcb\x7c\xe1\x9d\xe8\x1a\x9d\xad\xf5\x56\x35\x2e\xe8\x98\x10\xc7\x6a\x9b\x10\x47\xac\x62\xb1\x6e\xbb\x7d\xa2\x3d\xdc\x2d\x4a\xb7\x6a\x02\x05\x61\xd0\x2d\x41\xb5\x8b\x94\x95\x3a\x23\xfa\xaf\xdd\xd7\x81\xb7\xdc\xa7\xb7\xfb\xee\x70\x6e\xc1\x0a\x73\x12\x5b\xf7\x44\x36\x05\x6b\xf3\xb4\xf2\xa0\x70\x1c\xfe\xf0\x5b\xeb\xd3\xdd\x8e\xef\x30\x6c\x1a\xc1\xb0\x09\x50\x88\x1f\xf0\x5a\xb5\xc8\x24\x8a\xd1\x09\x6a\xc9\x1d\x52\x6a\xe5\x9b\xa0\x58\x3b\x27\xdb\x7d\x1e\x39\x0f\x57\xa5\x88\x9e\x27\x99\xa4\xa1\x51\x9b\x15\xd9\x3d\xbf\x0b\x21\xd4\x50\x87\x3c\x76\xba\x52\x04\x61\xe8\xbb\x5c\x83\xc9\x01\x2e\xac\xd5\x57\xbe\xa6\x40\x58\x6e\xfc\xb8\x69\x00\x76\x47\xd4\x49\xf9\x1c\xcd\x52\xaf\xe3\xa8\x94\x77\xde\x7c\x2b\x64\x7e\xcc\x9b\xf9\x67\xfb\xf5\x76\x9d\x74\x88\x94\x47\xd9\x52\x2d\x9e\x80\x69\xc3\x49\x9a\xf6\xa8\xa1\x09\x7a\x95\xd3\xbc\xc5\xf8\x34\x33\x93\x44\x84\x31\x4c\xb3\x07\x58\xb5\x25\xfe\x53\xe9\x07\x21\xdf\x5c\xbe\x03\xd9\x6f\x0d\x0f\x98\x52\x1f\x01\xa5\xfb\xe5\x7c\xe8\x80\x4d\xbd\x18\xf8\xf5\xea\xc8\xf7\xdb\xb5\x8c\x41\x78\x9a\x44\x43\x3f\x8a\x8d\x12\x45\xd2\xad\xda\x8c\x78\xd8\x81\xc6\x5e\xa6\x61\xab\x17\x8d\x4f\xc2\x63\x4c\xd6\xcb\x51\x4a\xb6\xf2\x54\x3e\x91\x12\x18\x3f\x3f\xf7\x3a\x3f\x45\x01\x06\xb0\xee\x8a\x34\x7a\x80\xcb\x82\x4a\xc1\xf8\x01\x64\xe3\xbb\x51\x23\x69\x8d\xe0\xe7\x47\x35\x9c\xa3\x5a\xca\xa3\xba\x0c\x94\x3b\xea\xcd\x7a\x9b\xdf\x8f\xf7\x39\x78\xe9\xfb\x00\x20\x45\xe8\xfe\x56\x48\xcc\x0f\x9c\xfa\x88\xb0\xd8\x12\xe8\x1a\xa6\x2e\x0d\x9c\x73\xfe\x61\x3a\xfd\x95\x39\xbc\xb6\x15\x72\x1f\xb4\x97\xd6\x2f\x65\xc8\x3b\x87\xa6\xd2\x14\x3f\x9b\x1c\x88\x0e\xc8\x67\x1b\xd4\x2c\x8d\xe9\x57\xb1\xa6\x8e\xe4\x92\x26\xff\x71\x7c\xcc\x6e\x74\xf2\xee\xe4\x9c\x30\xde\xa5\x3f\xec\x3c\xd4\xd9\x0f\x2c\xcc\xd8\xf9\x7c\x55\xd5\xc7\x52\x45\x4b\xe2\xba\x7b\x6f\xf2\x03\x0b\xe6\x7e\x0d\xf5\x0c\x5e\x88\x38\x43\xe7\x16\x12\xf2\xb9\x53\x59\x54\x3e\x2b\xa1\xbf\x2e\x98\xde\xbc\xf5\x76\x8f\x2b\xe6\xfd\x50\x4d\x97\x83\xce\x92\x1a\x81\xe0\x94\x16\xdb\xcf\x2b\xb6\x55\xa9\x24\xb1\xef\x01\x12\xd6\x71\xf0\x84\xa5\xb6\x90\xb0\xb6\x4a\x8b\x9b\xf5\x03\x33\xc3\x59\xff\x3f\xef\x19\x96\x94\xf9\xb6\x29\x24\x24\xf0\x06\x66\xce\xf6\xd0\x6d\x16\x1a\x79\xe3\xa1\xb9\xb9\x62\x9e\xea\x53\x50\x5f\x5e\x36\xae\xad\xfe\x0d\x75\x96\x72\xb0\xff\xe4\x98\x39\x7d\x90\xa5\x5d\x99\x44\xb3\x05\x41\xa7\xe1\xbd\xac\x53\x02\x06\x40\x13\x7d\xc2\x52\xae\xf6\x22\xf3\x81\x9d\x36\xab\x49\x8d\x76\x3e\x43\x27\xba\x85\x80\xdd\x9f\x7e\x5f\x47\xc2\x4c\xc9\x92\x87\x34\xb7\xe6\x21\x12\xc5\x7e\x3e\x0c\xfe\xde\xcd\xcb\xac\xcb\x0c\x45\xaf\x82\x19\x45\x5e\xe7\x22\x3c\x71\xe7\xe2\x04\x10\xc5\x24\x4e\xb8\x27\xaf\x2f\x39\x35\xce\x47\x55\x44\x47\x47\xaa\x94\x5f\x4c\x26\xdb\x3a\x29\x85\x19\xe7\x5f\xc6\xba\xce\x91\x52\x99\x72\xe8\x69\x1b\x69\x4d\x30\xaa\x8b\x5e\xc4\xc1\xa0\x28\xd3\xbd\x10\xbd\x0c\x8a\x40\x8f\xb7\xd9\xd7\x03\x49\x55\x53\xec\xea\x59\x8d\x06\x22\xdc\xc7\x4d\xe4\x89\xba\x71\x95\xcd\xae\x8d\x5c\xff\x98\x55\x92\x18\x37\xb5\x28\x43\x3e\xe5\x5c\x0b\x70\x90\x85\x7a\x0c\x27\x84\xd9\x31\x0b\x48\x25\xa7\x99\x3a\xd9\xc6\xf1\x8f\x83\xbc\xa5\xcc\x6a\x25\x04\x71\x68\xa8\x37\x6b\x06\x2e\x3a\x48\xea\x90\xca\xd8\x8e\x33\x11\x87\xc2\xb6\xf2\x81\x42\x6f\x81\xf7\x88\x04\xa8\x95\xc4\xec\x06\xc3\x41\xfe\x84\x6a\xf4\x52\x7e\xa2\x60\x69\xdc\xf6\x1d\x81\x3f\xdd\xf0\xfc\x43\xc7\x07\x35\x0b\xfb\x2f\xc1\xcf\xfc\xee\x7d\x7c\xcd\x7d\x75\xf7\xa4\x65\xa3\xd1\x4d\x57\x30\x2c\x14\x6a\xba\x3e"}, -{{0xde,0x8f,0x1c,0x99,0xe7,0xf8,0x55,0x6d,0xf2,0x0b,0x59,0xb8,0x50,0x4c,0xff,0x7c,0x6c,0x52,0x41,0xa8,0xae,0xeb,0x30,0xb9,0x2e,0xab,0x97,0xbf,0x48,0x1d,0x0f,0xe9,},{0xe4,0x63,0x79,0x1d,0x0f,0x56,0x7e,0xe7,0x3a,0xbb,0xf4,0x7d,0xd5,0x71,0x67,0xa5,0x35,0x61,0x3b,0x05,0xcd,0x48,0xd9,0x2e,0xbc,0x7d,0x24,0xe6,0xeb,0xff,0x95,0x73,},{0x30,0xab,0xc4,0xe4,0xe4,0xb3,0x88,0x58,0x1e,0x66,0x8b,0xd4,0x09,0xee,0x18,0xa6,0xed,0xe8,0x1a,0x13,0x6c,0x28,0xa2,0x92,0x4d,0xf5,0xfc,0x00,0xd7,0xc2,0x80,0xd9,0x78,0x62,0xae,0x3a,0x67,0xa9,0x35,0xce,0x49,0x23,0x64,0x13,0x5e,0x65,0x9a,0xdb,0x5f,0xba,0xbe,0x68,0x98,0x16,0x59,0x1f,0x49,0xac,0x50,0x22,0xa3,0x87,0xcc,0x09,},"\x38\xd9\x3e\x5c\x98\x01\xdb\x90\x17\x97\xec\x75\xc6\xdd\xdc\x65\xae\x79\x80\xde\x21\x0b\xed\x43\xb3\x3e\xb4\x4c\xdc\x6d\xc9\x93\x3f\xb6\xbe\xc7\x42\x1d\xb1\x0f\x0a\x59\x32\x0b\x9e\x64\x2a\x21\xf1\xdd\x23\x56\x01\xfc\xd6\xc5\x3b\xe4\xa8\x77\xf4\xfe\xd3\xfa\x4a\x0a\xd4\xdc\x6e\x9b\x39\x1b\xcf\xa4\x34\x90\x69\x25\xba\x45\xec\xc5\xb4\x35\xd9\xab\x8c\xfa\xfc\x39\x4b\xdc\xca\x9b\x07\xd5\x66\x83\x93\x44\x6e\x34\x00\xe9\x03\x94\x35\xa1\xdc\x78\xcb\xc0\x88\x07\xa3\xfb\x24\xca\x8b\x19\xf6\x4e\xa0\x8b\x8b\xf6\xc2\x0a\x19\x5b\x51\xff\x80\x15\xf3\xe7\xc9\x1d\x08\xe4\xbc\x62\x41\x55\x95\xa5\xa8\x82\xfb\xa6\x51\xdc\x3a\x67\x51\x87\xaf\x61\x82\x49\x74\x7b\x46\x80\xd1\xd1\x5a\x20\x2e\xa9\xdf\x48\xb1\xc2\x14\xfd\x40\x34\x66\xfd\x1a\x26\x5f\x2d\xef\xaf\x8e\xd5\xa6\xbf\x0e\xb0\x8d\x18\x64\xf2\xa2\x8e\x94\x72\x14\x3c\x6f\xd1\x03\xb6\xb1\x08\xc0\xd1\xd1\x36\x3b\x99\xf9\x20\x2d\x11\xf0\x20\x56\xc2\x79\xcc\xa3\x15\xdb\x1a\xb6\xd3\x10\x18\x45\x8f\x57\xba\x33\x16\xcd\x27\x38\xe8\x0c\x49\x2d\x85\x7c\xb1\x74\x99\x25\xe3\x31\xc6\x58\x58\xb5\x09\x83\xcd\x98\x38\xcf\xd2\x18\x8a\x5e\x8f\x05\xb4\x71\xfd\x3c\xdd\xcd\x30\xd9\x69\x01\x19\x40\x20\xf1\x15\xfb\x46\x9a\xb5\x84\x90\x06\xdf\xfa\x2d\x54\x3a\x13\xb3\xb5\x06\xed\x65\xcc\x45\x75\x32\xb8\xaa\x3e\xe3\x1d\x9d\x8d\x9e\x52\x98\xd7\xac\x70\x7a\xc1\x5b\x82\x7a\x57\x8c\x81\xd4\x34\xf8\x4c\xb1\xb5\x61\x20\xd6\x67\xb2\xaf\xe6\xd1\x53\x0a\xfd\xdf\xb9\x66\xd9\x53\xbe\x7e\x32\xdf\x07\xde\x38\x9e\x2d\x04\xb2\x32\xd3\x51\x2c\x7d\xb9\x35\x8f\xc9\x44\xd1\xb1\x18\x07\x8e\x69\x99\xe8\x91\xbb\xfa\x4a\x43\x29\xf6\x5d\x80\x71\x88\xb5\x98\x58\xc4\x31\x21\x1b\x29\x57\x6f\x44\x96\x13\x8b\x7c\x0c\x12\x8f\x7b\xef\x5f\x79\xb0\xf4\x46\xfc\x6b\x4a\x0e\x20\xbc\xa4\xc4\x0a\x83\x57\x1a\x36\x64\x4a\xbf\xfa\xbd\x49\xcb\x58\x5f\xd0\x64\xc8\xe5\x09\xd9\xa0\xfc\xff\x46\x26\x76\xf0\xeb\xcb\x61\xce\xc6\x1e\x51\x2b\xe6\xf1\x82\xab\xd5\x9e\x09\xf6\x42\xaa\x61\x96\x34\x85\x34\x82\xec\xe8\xf8\x98\x00\xf9\xc5\xbc\xfb\x84\x14\x31\xca\x06\x91\xed\x8d\x80\xe0\xa2\xfc\xb7\x97\xa0\x36\x89\x7c\xfb\x65\x37\x58\x6b\x31\xc0\x0b\x79\x65\xef\xdd\xfd\xa7\x28\x61\x84\x50\x26\x45\x91\x57\xf7\x9e\xba\x1b\xca\xf6\xcd\x41\xd6\x18\xae\xb1\xbd\x8d\xa1\xbe\x98\xf0\xcd\xc7\xf2\xe0\x9b\x90\x3d\xe4\x9c\x0c\x1b\xe9\x1d\xcc\x17\x7b\x29\x80\x96\x83\x6d\xce\xa4\xf6\x01\xdd\x86\x69\x15\x55\x12\x83\x25\x43\x8b\xd9\xcc\xbf\xc0\xe7\x77\x92\x0a\xe8\xbb\xd5\x76\x34\xc6\x10\x4f\xe6\x9a\x3a\x72\x01\x2a\x23\x60\xb6\xe5\x52\x55\x0c\xff\xb4\xe2\xf0\xb4\x1f\xe1\x55\x37\xee\x0e\x6f\x37\xe7\x88\x0f\xb4\xd1\x2b\xef\x6c\xad\x26\x6c\xe5\x8d\xf9\x81\x6b\x35\x96\x0c\xd0\xbf\x86\x52\x86\x2e\xe7\x89\xcc\xc3\x1a\x7e\xfc\x21\xa8\x1b\xda\x46\x14\x6b\x11\x1f\xcf\xd9\x4f\x04\x85\x6a\xb6\x1a\x55\x7b\x1f\xf7\xc8\xe4\xea\x6d\x9c\x4b\xcd\xd9\x3b\x15\x1a\xa0\x84\x61\xc5\x68\xde\xfb\x2a\xef\xdf\xce\x96\x39\x4d\xc8\x22\xd4\xef\x6c\xc4\xb9\xa3\xe6\xc3\x32\x03\x9f\x65\x38\xaa\x0d\xf8\xde\x81\x26\xd9\x0c\x31\x2f\xf4\x96\x88\x74\x86\x11\x15\x65\x53\x43\x46\xa7\x46\x26\x25\xd6\x3d\xf6\x9f\xcb\x57\x41\x90\x6f\x19\xe0\x0f\xc8\x00\x3f\x08\xb9\x59\x85\xc3\x8b\x86\x74\xaf\x42\x3c\xa5\x6d\xe5\xf8\x81\xb5\x9c\x46\x62\x43\xa7\xad\xba\xdb\xa2\x9c\xaf\x57\xfa\x77\x71\x22\xe6\x18\x23\xb4\xe7\x08\x18\x2a\xaf\x37\x20\x6d\x7d\x5e\xd0\x51\xc1\x2a\x5c\x0f\x6b\x43\x71\x04\x3f\x56\x2c\xdc\x02\x9d\x5e\x1b\xa9\xb2\xbf\x5f\xfb\xf1\xf5\xf5\x23\xdb\x06\xfe\xca\x42\x7d\xb7\xa0\x88\x19\xff\xb2\xd0\x58\x52\x42\xe2\x0d\xa5\x8e\x32\x0b\x16\xb1\x6e\x44\x8d\x8b\xe0\xef\x74\x02\xd2\x4a\x71\x94\x25\x71\x33\xbd\xc9\x82\x31\x4d\x83\xad\xbc\xd1\x2e\x8a\xf3\x13\x03\x42\x6c\x59\xff\xd8\x26\x9c\xe4\xb9\x87\xca\x9b\x6f\x0f\xfd\xbb\x4d\x1d\x12"}, -{{0x07,0x36,0xf8,0x01,0x72,0x0a,0x94,0x7c,0x5c,0x2f,0x32,0x58,0xce,0x0d,0x51,0x1c,0x3e,0x17,0xe9,0x4e,0x37,0xb3,0x0a,0xdf,0xa5,0x20,0x95,0x92,0x11,0x71,0xd4,0x00,},{0x4f,0x69,0x42,0x55,0x92,0x0d,0x0c,0x38,0xde,0x6e,0x72,0xe1,0x65,0xc3,0x3a,0xee,0x76,0xb1,0xcb,0xf6,0xf4,0x83,0x7a,0xa5,0x90,0x14,0x75,0x66,0x7a,0xcd,0x28,0x26,},{0xc0,0x3c,0x03,0x14,0x85,0x12,0x79,0xed,0xcd,0xe9,0x70,0xc2,0x3e,0xfa,0x23,0x6f,0x23,0x5e,0xda,0x96,0x0d,0x2c,0x27,0xd3,0xca,0x94,0x6f,0x65,0x0c,0x20,0x0b,0x4e,0xba,0x04,0xbe,0x66,0x8f,0xf6,0x2e,0xaf,0xfa,0x6c,0xea,0x35,0x1a,0xbd,0xfc,0x54,0x40,0x1d,0xcc,0xce,0x3d,0xba,0x78,0x00,0x4a,0xec,0x95,0x81,0xa2,0xcc,0xf4,0x0f,},"\x7f\x87\xb5\x1f\x6e\xad\x2d\x44\x02\xa3\xbd\x3c\x37\x69\xa2\x67\xac\x8e\x82\xf7\x79\xad\x7b\x98\x6d\xec\x82\xcb\xfc\x1e\xa5\x12\x91\x88\x43\x26\xd9\x22\x69\x67\xcb\x66\xa9\x68\x73\x18\x4f\x0e\x83\xb3\xab\x25\xa5\xab\x2f\xa8\x05\xfe\x3a\x0e\x7b\x19\x0a\x62\x2d\x46\x1b\x78\x30\xa3\xf6\x97\xc8\x31\xc2\x9e\xa7\xc0\xcd\x4b\x68\xd8\xe7\x7a\xa6\x97\x11\xcf\x86\x4d\xc1\xd5\x39\x4f\x48\x45\xe2\xfb\xb5\x07\x64\x04\xe0\x9a\x88\xb7\x9f\x05\x67\x05\x51\xbc\xe2\xef\x54\x68\xb7\x9d\x57\x88\x8b\x98\x52\xa4\xbb\x47\x9a\x4f\xd0\xbe\xb6\x81\xfd\x52\x3f\xc5\xbf\x44\x58\xab\xbc\x38\xec\xe7\x2e\x10\x6e\x00\x22\x20\x15\xa5\x7e\xbe\xc5\x5b\xf4\x75\x13\xe2\x5c\x3c\x45\x54\x84\x3b\xda\xcb\xcf\xe9\xf1\xb8\xd0\xae\x35\x4e\x48\xd0\x3f\xde\xbd\xf2\x0d\x65\x5b\x52\x68\xd8\xbb\xbf\x33\xb1\x28\x89\x10\xf0\x44\x4f\xcd\x56\xc0\xda\x7b\x89\x03\x36\x2b\x7e\x37\xa8\x64\x65\x42\x77\xcf\xfb\xe6\xc6\x08\x57\xf0\xb3\x51\x4d\x22\xa4\x0b\x9d\xd2\xd3\xfe\x5c\xae\xa5\x50\x7a\x0d\xe3\x05\x1b\xb3\xa4\x01\x5f\xa0\xfe\x4c\x46\x2b\x98\xfe\xf2\x35\x7d\xcf\x6b\x97\xdc\x75\xde\xf3\x82\xf9\x01\xf9\x6f\x4a\x04\xa3\xef\xc6\x02\x54\x20\x0a\x2c\x4c\xdc\x8a\x58\xb2\x5d\x94\xe3\x29\x54\xea\xff\x15\x11\xac\x46\xe3\x60\x66\x63\xb6\x87\x5f\x13\x64\x99\xda\x6a\x76\x90\x97\x87\x9a\x6e\x08\x34\xd5\x64\xfa\x7f\xdb\x99\x58\x11\x83\xed\x0c\x9d\x48\xfd\x19\x5d\x7e\xcd\x9f\x4d\xd4\x86\x55\x65\xfd\x17\xa0\x08\x71\x8d\xcd\x76\xf6\x8a\x54\xe5\x16\xa2\xb7\x30\xed\x3d\xba\x5c\x2c\xf4\x06\x30\xbb\xfe\x7f\xa0\x3b\xb7\xcd\xd9\x67\x69\x54\x95\xa7\xc8\x6e\x2e\x84\xcb\x01\x7e\xc6\x96\x01\x92\x46\x31\x59\x5a\xff\xaa\x8c\xfd\x04\x8d\x14\x26\x7c\x73\xe5\x4c\xfa\x53\x90\x47\xe7\x17\x69\x1e\x39\x97\x37\xfa\x50\xcc\x48\x44\x96\x12\x57\xc9\x3d\x72\x53\xd2\x32\x26\xb7\xcd\x0d\x1b\xd3\x1f\x3f\x0d\x2d\x89\x2d\x07\x3d\x8c\x50\x73\xc6\x02\xf6\x1a\x04\xd6\x43\x7c\x39\x03\xeb\x4a\x64\xa0\x1f\xbc\xc0\xc7\xe1\x59\x20\x1c\xdc\x4a\xa4\x2e\xf3\xb1\xff\x9c\x78\xfc\x27\x5c\xfb\x11\xa0\x5f\xfe\xd8\xf9\xf2\x2d\x85\xba\x92\x4d\x8d\x32\x23\x1c\x25\x4d\x89\x8d\xa7\xf0\x67\x9a\x64\xca\xb8\x40\x26\x90\x6e\x9e\x85\xf9\x5e\xfd\x8e\xe2\xa1\x72\x56\x33\xf4\xde\x2b\xa6\x7d\x99\xaa\x7f\x05\x50\xaf\x13\x9e\x9f\x8c\x52\x93\x78\x67\x27\xd8\x26\x30\x29\x6d\x5d\xaa\x9e\x83\x0a\xa1\xb3\xb5\xb3\x02\xb8\xb6\x62\xac\x83\x2e\x92\x13\x01\x6b\xa4\x93\xa0\x3a\x28\xcc\x3e\x95\x40\xd0\xd6\x5a\xcd\xdb\xfe\x12\x52\xb5\xc1\x6a\x84\xa4\x45\xce\x75\x41\x5c\x6c\xd8\xab\x16\xfe\x5e\xef\x11\x70\x97\xd7\x1e\xb5\x67\x6b\x9a\x95\xb3\x58\x82\xa7\xc3\x50\x6b\xc5\xd0\x2f\x03\x91\x0a\x63\xd4\x68\x46\xb2\x13\xc3\xc9\xbb\x2f\xc3\x4e\x6c\x69\x01\x7d\x20\x65\xa1\xad\x3c\xe3\xfd\x14\xab\x00\x14\xf5\x84\xe5\x7e\xa9\xd9\x03\xe4\x0a\xce\xb2\x30\xa8\x69\x3f\xa2\xe6\x36\x41\xc2\x54\x38\xff\x7a\x16\x38\x76\x04\x38\x84\x4c\xdf\x00\x11\x80\xf5\xb1\x77\xbe\x69\xed\xf7\xef\x66\xb3\x93\x12\x80\x52\x14\xcb\x17\x70\x6c\xef\xe5\x45\xbe\x5a\x77\x01\x9a\x5e\xc5\x2b\xbf\x78\x85\x0f\xa3\xd9\x7d\xe2\xd4\xd7\x4a\xa6\x8b\x58\xca\x81\x2a\x1b\x15\x6a\x0c\x40\x01\x12\x9f\x06\x72\x32\xa6\xec\x91\xa5\xed\x42\x70\xf2\xa4\xc6\xef\xee\xe7\x87\x00\x47\x70\xc8\x59\xe4\x50\xe8\x37\xef\xb0\x4d\xc9\x98\xbd\x27\x3c\x27\xa0\x98\x55\xe4\xec\xa1\xa2\x2a\x9b\x88\xc1\x7b\xdb\xf2\x53\xa7\x97\x61\x07\x0a\x76\x81\x7a\x7f\x74\xff\x3f\x07\xfb\x71\x8b\xff\xa0\xb4\xf3\x26\xf2\x84\xe6\x2f\x83\x68\x32\x42\x7b\xe8\x2f\x48\x33\x73\x51\x5b\x9b\xf5\x9a\xf4\xa7\x6a\x57\xe2\xf4\x0b\x91\x03\x4d\xd5\x68\xec\x14\xac\x10\xe2\x30\x9b\x87\xe2\x92\x2f\x9c\xd9\xfc\x1a\x46\xa4\x7e\xd3\xbc\x7e\x1b\x9f\xeb\x9e\xe0\x67\x07\x3f\xa5\xdc\xe2\xa6\x75\x30\x52\x6d\xe6\x7e\xe0\xe5\x09\x66\x3c\x44\x46\x7e\xeb\x59\x42\x01\x03\xeb\xcd\xff\xa7\x09"}, -{{0xfa,0x75,0x65,0x04,0x91,0x04,0x74,0x28,0xd3,0x63,0xb5,0x82,0x22,0x22,0x12,0x2d,0xff,0xb5,0xa9,0xfd,0xdc,0x60,0x3c,0x33,0xc8,0xa6,0x08,0x61,0x83,0x75,0xdc,0xf3,},{0x98,0xc9,0x64,0x1f,0xa9,0xdf,0xa8,0xea,0x13,0xe0,0xd1,0xc7,0x16,0xb8,0x67,0x9e,0x26,0x4b,0xe1,0x5d,0xd2,0xd4,0xc0,0x6a,0xb4,0x3c,0xbe,0xe4,0x79,0x16,0xee,0x01,},{0x1e,0xff,0xbf,0x92,0x99,0xa1,0xb9,0x35,0x4f,0xe1,0xf1,0xde,0xc1,0x76,0x65,0x95,0xea,0x76,0x7a,0xb8,0xe4,0xda,0x9b,0xb5,0x7b,0x4f,0x69,0xbc,0xbd,0x8c,0xb3,0xd8,0x6f,0x76,0x83,0x92,0xf5,0x9b,0x39,0xfa,0xfa,0x8a,0x21,0x0a,0x65,0x09,0xfe,0x0d,0x60,0x08,0xd6,0x35,0x61,0x11,0xad,0xfb,0x37,0x99,0xc1,0xd5,0x59,0xc2,0x63,0x09,},"\xf5\x4e\x41\xb9\x39\xe3\x7d\xf1\x7c\x7d\x60\x43\xfd\xed\x14\xa9\x15\xd9\x34\xe8\x67\xc3\x45\x26\x9f\xdc\x01\x77\xf5\xbd\x10\xc4\x34\x8f\x31\x9e\x0a\xb9\xa6\x4c\xc0\xb7\xd4\xe0\xc9\x1c\xa9\xaa\xda\xab\x2e\xdc\xba\x54\x4f\x14\xed\x2c\xb5\x39\xca\x89\x75\x09\x7d\x87\x92\x70\x95\xb4\xeb\xd4\x90\x34\x43\x40\x06\x1e\xd9\x3c\x38\x16\x7e\xda\xa0\x96\xa2\x30\xdb\x59\x62\x4c\x67\xfb\x9a\x1e\x1d\xda\xc4\x02\x13\x3f\x4d\x47\xcf\xc1\x1e\x2f\xae\x6b\x3f\x3c\x50\x01\xcb\xa9\xa8\xae\xd9\x00\x73\x10\x32\x40\x22\x7e\x71\x6f\xf7\x1b\xf6\x8a\x59\x1b\xa2\xce\xff\x2d\x31\xb8\x6e\xf2\x1a\xb0\x12\xec\xcd\x40\x9a\xd5\xc2\x9d\x65\x9a\x1b\x37\xc4\xd8\x55\x05\x30\x41\x40\xfb\x2c\x34\x37\xa2\x06\x86\x8b\x13\x52\xc1\x02\xbb\xfa\x3b\x9a\x76\x52\x2a\x2b\xfc\x54\x06\xb2\x57\x69\x6d\xe7\x4e\xe7\xd3\x15\xc8\xe9\x9c\xaa\x96\xbd\x83\x80\x06\xc6\xda\x2a\x42\x33\x31\x5a\x85\x6a\xcb\x8e\x80\xc3\x31\x68\xb3\x33\x55\x1d\x91\xd0\x74\x05\x57\x34\x13\x0b\xd7\xd1\x4c\x56\x81\x1e\xba\xbf\x7d\x5a\x25\x0e\x60\x72\x59\x3d\x9f\x2f\x8b\x97\xc1\x2a\x70\x3c\x2c\x47\x9c\xb0\xb1\x5b\x7a\x27\x75\xc9\xdc\xd2\xca\x46\x24\x67\x23\x68\xa2\xe6\x14\x54\x67\xf3\xbe\x66\x15\xf9\x3b\x81\x20\xa0\xa1\x2d\xa1\x56\x06\x63\xa2\x6a\x61\x73\x19\x66\xb4\x4b\x29\x9e\xbf\xad\x2a\x95\xc6\x23\x60\xf3\x9c\xe0\x5d\x95\x58\xe3\x05\xee\x23\xa5\x2f\xa5\xce\x20\xf6\xbe\x5e\x26\x2a\xff\x3a\x86\x4d\x5d\xda\xbe\x23\xff\x94\x3f\x71\xd5\x99\x84\x93\xd9\x9f\xe2\xac\x23\x74\xb4\x64\xa6\x91\x83\xc3\xbc\x4f\x1d\xdb\x88\x36\x11\x14\x9d\x7d\xdb\xf1\xe8\x38\x0b\x54\x43\x35\xe2\xb8\x93\x95\x05\x4c\x9f\x25\x58\xdf\xc5\x6e\xa9\x3f\xf1\x4d\x0f\x15\xd2\xe0\xbd\x89\x37\xa5\x56\x38\x7d\xe9\x6e\x41\x8d\x8b\x3a\x7d\x66\x6f\xb1\x90\x36\x4b\x2c\x21\x90\xd3\xc2\x5f\x17\x52\xd5\x48\x3d\xcb\xb5\x96\x00\x64\xf0\xc8\x7f\xcf\x8f\x31\x3d\x28\x78\x1c\x11\x4a\x16\x9b\x69\x0a\x87\x01\xc5\x0d\x89\xc7\x73\x24\x53\x1c\x0f\x84\x9d\xba\xd1\x63\x3d\x92\x5a\xcd\x06\xc1\x6a\x9c\xea\x19\xa4\x34\xeb\xc4\x2a\xeb\xb1\xfd\xb9\xb0\xba\xcc\x93\xce\xc3\x99\x19\x94\x36\x64\xea\x1a\x95\x84\x06\xff\x9e\x49\x35\xc9\x2c\xa7\xc3\x97\x08\xf9\xca\xb7\x10\xa5\x83\x09\x6b\x4e\xd9\xf4\x8d\x9e\x09\x06\x47\x24\x0d\x76\xec\xcb\xab\xa5\x91\xf5\x5f\xe7\xe3\x6d\x72\xc2\x17\x27\xac\xba\x0f\x80\x30\x95\x4e\x62\xbc\x58\x0b\x8b\x67\x0c\x44\x57\xc3\x40\x3e\x36\x9a\xc2\x0e\x66\x0d\x66\x2f\x7f\x6a\x41\x42\x13\xea\x43\xf7\xc0\x10\x50\x09\xc1\xde\x81\x7a\xdf\x6f\xfd\x9c\xca\x3b\x45\xa6\x3a\x82\x22\x81\xc6\xe2\x77\x2f\xd7\xb7\x80\x96\x03\x18\x4b\x48\x79\xb1\x8c\x88\x79\x03\xf0\xfc\x8d\x8e\x1e\x2d\xbf\x6e\x77\x2f\x0b\x2d\x9b\x8a\x29\x92\x7a\xcc\x81\x71\x4a\x22\x56\xad\x8d\x7b\x73\x30\x52\x7d\x7d\xbf\x8b\xef\xd8\x2f\x8c\x9b\xb4\x01\xcf\x0a\x90\x24\x9a\x64\xca\x6f\x88\x33\xdb\x31\xbd\x03\xb9\xe7\x94\x6d\x06\xdd\x04\x38\x3d\x7c\x08\x2d\x70\xae\xb3\x7f\xf8\x4c\x2b\x05\x7d\x97\x3b\x89\x4b\x4a\x03\xec\x7b\xf0\x31\xae\xa6\x56\xa1\x90\x84\x88\x89\x4a\x4a\xda\x3f\xd7\xfa\xdf\x91\xed\xe9\x55\x0d\x38\x41\x5f\x82\xa0\x94\x55\xc0\xf4\x32\xfb\x55\x98\x71\x32\xf0\x00\x42\xaf\xd6\x0e\xa5\x1d\x1f\x1c\x6c\x1a\xfe\x0c\xf8\x7c\x34\x6e\x31\xe6\x3e\x26\xf4\x9b\x13\x71\x77\xb2\xd4\x7a\xb3\x0f\x07\xce\xa0\x71\x93\x12\x74\xcf\x01\x08\x36\xd6\x83\xff\xf3\xbe\x71\x34\xc7\x8b\x8b\xfd\x8b\x1b\x8f\xc2\x04\x9e\x18\xcc\xb1\xe1\x8a\x0a\x95\x85\xa7\xd8\xa1\xe2\x54\x92\x60\x86\x68\xc9\x6d\x62\xa0\xac\xa8\xef\x90\xe0\x48\xd2\x03\x78\xc1\x08\xd0\x6b\x03\xfe\x3e\xc4\xad\xb2\x75\x28\xae\x08\xf7\xde\xd9\x48\x78\x93\xae\x64\xca\x4b\x93\x92\x02\xaa\x4c\x17\xaf\xe7\x18\xcd\xca\x49\xff\x96\x16\xd0\xcd\xf8\x33\x4b\x6a\xee\x2d\x6d\x20\x94\x7c\xa4\xbd\x7d\xf5\x31\xdd\x1d\xa9\x95\x81\xff\x72\xea\x56\xfe\x62\xca\xa2\xc9\x5e\x35\x87"}, -{{0xe1,0xc1,0x29,0x46,0xd2,0x21,0xa1,0x94,0xf2,0x2f,0x27,0x62,0xc0,0xe5,0x1c,0xbe,0x3f,0x98,0xb9,0x14,0xa4,0x7d,0x3d,0xc4,0x1a,0x1f,0x45,0xc5,0x43,0x70,0x63,0x7c,},{0x10,0x40,0x81,0x36,0xa6,0x8f,0xc5,0x6c,0x7d,0x3b,0x36,0xb7,0xfe,0xf1,0x22,0x09,0x4d,0xe0,0x81,0x03,0x11,0x89,0xcc,0x84,0xa4,0x88,0x06,0xaa,0xf6,0xcb,0x91,0x85,},{0x8f,0xd7,0xfa,0x40,0x0c,0x03,0x2f,0xcf,0xbc,0x40,0x29,0x42,0xfc,0x78,0x63,0x75,0x26,0xbe,0x97,0xab,0x82,0xf2,0x37,0xbb,0x39,0x3e,0xa3,0x9e,0x35,0x73,0x8c,0x67,0xd7,0x54,0x09,0x54,0x3a,0x8b,0x3c,0x05,0x5f,0x08,0xbf,0x69,0x19,0x9a,0xf6,0x3b,0x69,0x11,0xa4,0x82,0xfb,0x4f,0x65,0x80,0x80,0x2e,0xc9,0xd2,0xdc,0x3c,0x11,0x06,},"\x87\x0f\x4c\xd9\x7c\xfc\x0a\xaf\xad\xa4\x00\x72\x31\x2f\xb5\x4b\xcc\xc0\x76\x28\x71\x4e\x49\x62\xd4\xbe\xf4\xee\xb5\xde\x40\xa1\x9a\x24\x6b\x5b\x7d\x52\xd4\x87\xb7\xe5\x2d\x65\x6f\x2c\x64\x03\xb9\x16\xd0\x2e\x02\xa6\xd2\x91\xc1\xe1\x82\x8d\xd9\x45\xa5\x83\xb4\x38\x52\x8d\x1c\x39\x76\x5a\x57\x20\x31\xff\xa9\x16\xb6\x83\x21\xf3\x2e\x66\x46\xf0\xdc\xc1\xc6\x02\x35\xff\xaa\x32\x35\xf4\x84\xa5\xc4\x97\x8f\xa3\xe6\xbf\x14\x30\x1d\x53\xe1\x2f\x4c\xc5\x21\x18\xb1\xf6\xf0\x7f\x53\x36\xf5\xd0\xa9\x37\x89\xbb\x01\xd1\x62\xfb\x31\x26\xdc\xd7\x56\xe0\x64\x2e\x7e\x69\x89\x63\xc0\x34\x59\x11\xa5\xcf\x3c\x99\x53\xf7\x73\x19\x42\x6c\xea\x2c\xde\xda\x3e\xfe\x98\x9e\xcb\x63\xcb\x9e\xb8\xb9\x20\xde\x76\x6c\x4f\xcf\x63\x36\xe5\xbc\x43\x71\xa0\x68\x37\x1f\xed\x95\xc8\xc2\xb6\x1e\xe9\xb7\xc3\xe3\x83\x1c\x20\xbf\xfe\x87\x07\xc0\xc9\x8b\xe9\x61\x53\xc8\xa8\x73\xd7\xf2\x8a\xfc\xa1\xbf\x71\x08\x5c\xe0\xe3\x89\x9e\xef\x55\x91\xbd\xd6\x66\xdc\x2d\x07\x64\x17\x72\xd7\x45\xc5\x16\x44\xa2\x60\x81\x5b\x20\x8c\x4d\xd3\x05\xf0\x5f\xe4\x63\xd0\xd9\xd5\xa9\xee\xff\x97\x79\xf5\xb1\xd4\x4f\x26\x08\x30\x78\x56\x6d\x0e\x5f\xf5\x6b\x3a\xf0\xe6\x4c\xc3\x87\x08\xaf\x5a\x65\xf6\x54\x35\x2d\xf1\x04\x37\xf1\xdd\xf9\x45\xa0\xda\x1f\x4d\xef\x6a\x71\xa0\x60\xe0\xc4\xad\xec\xca\xac\xf8\x5e\x09\x0f\x70\x90\x37\x0a\xe2\x4e\x52\x38\xd7\x68\xa0\x8f\xe6\xb4\xbb\x5e\xc4\x97\xa6\x60\x31\x98\x60\x84\x15\xc7\xc6\x49\x00\x48\xaa\x36\x73\x7c\x08\x50\x30\x08\xae\xce\x0f\x49\x42\x19\xdd\xf8\x9b\x72\xea\x77\x17\x1c\x6d\x31\x17\x08\x9e\xb8\x89\x07\xe8\xc3\x3f\xb9\xe7\x0b\x0d\xc2\x81\xf6\x64\xb5\xf9\x65\xb5\xd2\xad\xb1\x25\x07\x10\xef\x23\x52\x02\x5f\xb2\x93\x39\x5a\xe1\xd2\x3e\xe3\xb5\x92\xb4\xc5\xf2\xd5\x55\x69\xa5\x45\x86\x54\xce\x3f\xc2\x5d\xd0\xe3\xf7\xe6\x75\x7a\xa7\xb3\x47\xc1\xff\xd3\xba\x4d\x4f\x2c\x4b\x6d\x36\xaf\xd5\x98\x63\xa3\x2a\x59\x4e\x74\x53\x7e\xce\x9b\x8b\x1e\xc2\x69\xbb\xc4\xcb\x54\xd7\x62\x38\x21\x1f\x62\xa9\x8a\x46\xa4\xaf\x66\x2f\xa8\x1e\xba\x6f\x30\xf5\x14\xb8\x66\xb7\x94\x2b\xc1\x73\xf7\x21\x1a\x6c\x01\x4d\xa1\x4e\x74\x13\x27\xa5\x68\x62\x3d\x14\xb8\xf8\x35\xef\x1d\x5d\x62\xb2\x52\x3c\xfe\x6a\x85\xbc\x69\xfa\x05\x20\x0d\xea\xc1\x56\x8b\x94\x6a\x81\x6b\x75\xc5\xd7\x60\x31\x74\xfd\x4e\x2f\x91\x01\xa7\x90\x63\x79\x1b\xc3\xd5\x92\x97\xcd\xc1\x0b\xda\xa6\x63\xab\xf3\xc1\xbe\x2f\xda\x17\xe4\xe5\xce\x39\x4e\x90\xbd\x76\xb1\xf9\xe0\x40\x5f\x56\x75\xb9\x9d\x63\x8a\xbc\x2c\x1b\x2d\x8b\x53\xa6\xfd\x3d\xc8\x37\x58\x55\xec\x54\xcc\xbd\xa2\x4e\x67\x25\x27\x72\x3b\x07\xbb\x59\x9d\xb5\x4e\x38\x79\x33\x91\xcf\x09\xef\x3b\x1f\xd7\x61\x49\x90\x06\x5b\xbd\x4a\x19\xe8\xd3\xd1\x04\x82\x53\xba\x4c\x97\x1c\x2f\x98\xd2\xb3\x59\xdf\x50\x90\x87\x32\x3a\xa6\x90\x50\x29\xf5\xcc\x5e\x1a\x0a\xaf\x2f\x7c\x01\x08\xdd\xb1\xa4\x0f\x56\x2b\xe6\x4e\x57\xe6\x95\xed\x21\xdc\x7d\xb1\x7d\x53\x36\x77\xef\x12\xfc\xbb\xe2\x9f\x3b\x23\x7b\xb6\x34\x4b\x11\x09\xb3\x2a\x94\x62\xab\xc3\xad\x3c\x07\x10\xb0\x4f\x38\xc6\xf5\x95\x2d\xb2\x75\xe7\x7e\x2f\x37\xe9\x5d\x55\x09\x6b\xba\xf3\xe3\x05\xd5\xd7\x43\xd3\x65\x95\xbf\x05\x67\x89\x2c\x21\x0a\xc7\xba\xe7\x37\x1d\x16\x45\x84\x78\x5d\xd8\x90\x17\x41\x59\xb3\x93\x0a\x9a\x6c\xe3\xa1\x66\xdd\xa2\x38\x3e\x6e\x2a\xf2\x8c\x1b\xf3\x19\x24\x47\xe9\x05\x11\xdc\xd8\x0e\xbd\xf9\xee\x2c\x9b\xde\xdd\xee\xb6\x10\x55\x86\x41\x53\x2d\x07\xcd\x13\xda\x61\x25\x41\x54\xcc\x0f\xd9\xd4\x81\xe3\xb0\xa2\x37\xaf\x2e\xc2\x62\x56\xd4\xab\x21\x9f\xaf\x15\xad\x2b\x7e\x8e\x57\xab\x72\x6f\xf2\x72\x32\x16\xa5\x74\x58\x5e\x2a\x63\x9d\x94\x8c\x2c\x4f\x69\xee\xaa\xd2\x83\xe3\xa4\x4f\xf2\x68\xea\xef\xd7\xe6\x6b\x73\xed\xe4\x73\xa8\x39\x7c\x76\xb4\x8d\x56\xcb\x3c\xcd\xab\xc9\x1a\x89\x29\xcf\x42\x99\x83\x50\xe0"}, -{{0x76,0x2f,0x06,0xca,0x01,0xe3,0x14,0x71,0x5f,0x92,0xc9,0x0b,0xbe,0x72,0xa2,0x5b,0xf2,0x62,0x12,0xc8,0x1e,0xb1,0xd1,0xa0,0xda,0xe2,0xc3,0x11,0x30,0xf7,0xcd,0xbb,},{0xf9,0x62,0x6f,0xfd,0x69,0x27,0x31,0x92,0x5e,0x5a,0xac,0xfa,0x1b,0xde,0xd0,0x1a,0xa8,0xf7,0x30,0xb7,0x72,0xd5,0xe4,0x6a,0xdb,0xc3,0x15,0x56,0x5b,0x9b,0xf2,0xc9,},{0xe8,0x42,0xb4,0x9e,0x53,0x3d,0xbc,0x92,0x99,0x8d,0xc0,0x78,0xe5,0x97,0x93,0xa2,0xc2,0xfa,0x63,0x6b,0xdf,0xaf,0xdb,0x48,0x93,0x4c,0x93,0xcf,0x34,0x79,0x71,0x02,0x93,0x8d,0x13,0x7a,0xb7,0xea,0xd1,0xa0,0xf7,0x0e,0x94,0xa6,0x7d,0x57,0xef,0x6a,0x02,0xc9,0xec,0x77,0xd7,0x1f,0x70,0xcc,0x57,0xf1,0x53,0x3b,0xec,0x87,0x73,0x0e,},"\x94\x97\x48\x3a\x4f\xba\x78\x43\x3b\x38\xe9\xde\xb8\x91\x5c\x75\x0b\x6d\xa0\xf7\x8a\xf4\xa6\x8b\x62\xf9\xfc\x03\x91\xe3\x38\x87\x3b\x1d\x64\xb1\xb7\xf0\x9f\x12\xf0\x56\xa3\xc9\x16\x53\x49\x8a\xd5\x6e\x06\x9b\x8b\x16\x08\x87\xe8\xe3\x78\xa7\x6d\x8b\x3c\x66\x70\x83\xc0\xa2\xb2\xd2\x31\x7d\x3b\x87\x48\x57\xe5\x78\x62\xef\x0c\xb7\x04\x36\xa9\x02\x8f\x01\x91\xcc\xc6\x16\xe9\xd7\xc9\xbd\x86\x98\x08\xcf\x09\x48\x35\xff\x51\x86\x77\xb3\xfb\x08\x9f\x4c\x9d\x07\x7c\xc7\x74\x24\x05\xb4\x86\x3a\xc7\xa5\x96\x45\xc9\xcf\x54\x0d\x57\x39\x9d\xa6\xae\x9d\x07\xfd\x19\xfc\xa9\x5b\xc8\xa8\x6d\x8b\x8e\x24\xe4\x87\x33\xf3\x21\x58\xfd\x19\xa8\xa1\x11\x1d\x1d\xa1\xf9\xb5\x80\xa3\x9c\x10\x48\x46\x16\xcf\x2b\xc0\xec\x29\xf6\x3f\x77\xc8\x53\x56\x15\x8e\x16\xda\x59\x4b\x5a\x89\x0e\x55\xd0\xb6\x45\x99\xb3\x02\x93\xe9\x00\xed\x92\xad\x26\x19\x69\xe7\xdf\x4c\x4b\x1d\x0b\x60\x24\xbd\xce\xb6\x90\x67\xef\x48\x6c\x20\xfd\xcd\x22\xa1\x0d\x5d\xa4\x5f\xbf\x90\x5b\xa1\xe9\x35\xc9\x6f\x50\xaf\xb6\x35\x71\xbc\xff\x31\x30\x68\x4e\xda\x0b\x56\xe6\x0b\x26\xcf\x4c\x0e\xf9\x93\x8a\x92\x76\x8f\xc8\x63\x1f\xe3\x08\x23\x6b\x01\x2f\x92\xaf\x24\xa8\xf6\xe6\xec\xbe\x76\x62\x9b\xba\xf8\xff\xe5\x4c\xdb\xe8\x67\x1d\xe2\xba\x62\x4a\x7c\x0f\x61\x93\xbb\xa4\x11\x04\x12\x90\x2b\xac\x29\x90\x92\x2a\x9e\x5a\x81\x05\x3c\xf8\x76\xa4\xc8\x05\xa0\x4c\x56\xa8\x13\x9d\x34\x19\xe4\x54\xa6\x22\xd0\x34\x2b\xf4\x26\xe9\x80\x2c\x3d\xc1\xb4\x08\x0c\x75\x49\x2a\xfe\x9d\x7b\x15\x45\xfe\x08\x6d\x96\x35\x41\x32\x4f\xf5\x2a\x48\xc6\xbf\xae\xa2\x66\x68\xb3\xe0\x1e\x52\x36\xfd\x45\xfe\x54\x59\x45\x35\xc0\xb2\x3e\x28\x7e\xbd\x14\x28\xc8\xbe\x0a\xd1\x41\x60\x0e\x91\xcb\x51\xe1\xea\x66\x27\x1a\x64\x21\xfb\x68\x9e\x88\xa0\x79\x0a\x65\x1d\xbd\x21\xee\x20\x89\xb2\x74\x66\x6f\x66\x0c\xa0\x9c\xe2\xd6\x0e\x39\xe2\xee\x5f\x03\xb6\xeb\x82\xd1\x99\x76\x96\x6e\x79\x90\x0a\x81\x0f\x6d\x5b\x5c\x1a\x54\x8e\x50\x64\xf5\xc3\xd8\xa9\xf2\xde\xf0\x17\x9d\xf9\x9d\x14\x3f\xde\x69\xb0\x71\x2c\x09\x1c\x29\xe9\xb2\x5f\x40\xca\xfd\x57\xa0\x24\x65\x8d\x77\x74\x03\x76\x10\x34\x2f\x38\x00\xfd\x51\xf4\x9e\x79\xa5\xb3\xde\xcc\x11\x2f\x58\xd0\x3e\x3d\x29\x58\x75\x85\x88\xbc\x4b\x1c\x6a\x6c\xda\x7b\xc5\xf5\xbe\x18\x3e\x41\x51\x3c\x1f\x23\x0f\x3c\xc3\x64\x30\x4b\xf8\x24\x84\xb7\xcf\x19\xa0\x02\xe1\x50\xf9\x8c\x5e\x97\xc6\x16\x6e\xa1\x5b\x86\x34\x0b\x8c\x5e\xbe\x5c\x1a\x18\x3e\x55\x88\xe6\x6f\x55\x90\x50\x86\x31\x3f\x37\xa4\x09\xe8\x9b\x47\xdb\x31\xae\x97\x45\x3e\xdf\x69\xfe\xd7\xbe\x08\x11\x30\x71\xf3\x74\xb2\x6e\xc6\x04\x3f\x2a\x0e\x9c\xf8\xba\xd8\x02\xab\xad\x69\xe6\x17\xe7\x62\x43\xb3\xcc\x03\x4b\x09\x9d\x87\x29\xee\x40\x7a\x53\xeb\x03\xbd\xc6\x41\x0a\x03\x95\x04\xb3\xb1\x2c\x81\x9b\x64\x54\x5d\x40\x5c\x6a\x4f\x08\x49\x21\x93\x5b\xdf\xf4\x13\x0a\xe6\x29\xd9\x09\x62\x6b\x06\x26\x76\xe5\x38\xea\xfd\xff\xb1\xd6\x22\x9c\x08\x89\xd3\xcd\xdd\x33\x65\xdc\x3d\x65\x36\xf7\x24\x8c\x49\x31\x7c\xb5\x0c\x56\xfb\x57\x85\x55\x41\xd6\xfe\xeb\xac\x81\x6c\x99\x28\xfa\x66\x2d\x0a\xe8\x0a\x0f\x39\xe5\x70\xbb\x7d\x22\x41\x6f\x98\xf3\x71\xb6\x42\x47\x96\x89\x51\xa8\xa2\x46\xf7\x4b\x30\x61\x74\x3c\x9a\xf7\x68\x4b\xbb\x96\x6a\xe0\xbd\x78\xa8\x10\x49\x3e\xa4\xcc\xd7\x11\x74\x87\x1c\x82\xbb\x65\x2b\x27\x48\xe5\xbc\xcb\x0a\xb6\x38\x8a\x50\xf0\x53\xa0\x48\x08\x7f\xd9\x7e\xb1\x5c\x1a\x21\xb1\xee\x18\x25\xe5\x4a\xa1\x30\xd6\x63\x18\xaa\xf6\x61\xbb\xb2\x47\x63\x57\x7e\xb3\x7d\x31\x0e\x21\x9b\x0a\x9b\xba\x03\x75\xeb\x9c\x9b\x4a\xf8\xc4\xb9\x9a\x36\x99\xe0\xd3\x26\x67\x33\xb6\xe4\xe9\xc5\x34\x49\x0a\x13\x41\xcb\x19\x90\xca\x5b\x1c\x84\x7b\xc8\x12\x60\x26\xfe\xa9\x03\xa1\xf5\x49\xd6\x5a\xf8\xfe\x02\xa9\x16\x3f\xf8\xea\x28\x1e\x72\x26\x24\x3e\x2a\x15\x3b\x92\x18\x51\xde\x10\xf7"}, -{{0xc5,0xcc,0x0b,0x95,0x81,0x8c,0x4b,0xf3,0x8d,0xa1,0xd6,0x5f,0x02,0x16,0x27,0xe9,0xe5,0x7d,0x26,0x2b,0x02,0xec,0x6d,0x91,0x7a,0x7d,0x46,0xb1,0x1c,0x7f,0xe4,0x8a,},{0x45,0x7d,0xa4,0xef,0x14,0x51,0x9d,0x54,0x1e,0xdf,0x92,0xca,0xbe,0xd9,0xb0,0x4d,0x8a,0x2f,0x2a,0xfd,0x15,0x10,0xa9,0x2f,0x00,0x9b,0xb4,0xe8,0x75,0x4f,0x1e,0xba,},{0x3b,0xa0,0xaf,0x8a,0xf1,0x27,0xc4,0x58,0x48,0x26,0x09,0x0e,0xcd,0xaf,0x48,0x5e,0xbd,0xf0,0x7b,0x82,0xbc,0x49,0x9c,0x9a,0x2b,0xef,0xca,0x28,0xd4,0x93,0x44,0x97,0x4a,0xdd,0xbc,0x8d,0x80,0xa5,0x25,0x60,0xe0,0xf3,0xd7,0x3f,0xf5,0xcc,0xcc,0x72,0xc7,0x4b,0x5b,0x47,0xad,0x2e,0x6d,0xe9,0x61,0x2d,0x1a,0x00,0xae,0xc9,0x27,0x01,},"\xd6\x60\x8b\xf5\xac\x00\x0e\xca\xf9\x5f\xc0\x9f\x9c\xb7\x49\x8c\x51\x8a\x6e\x02\x55\x58\x6e\x63\x37\x85\x3b\x1d\x7d\x9d\x7d\xe4\xdf\xe1\x24\x5d\x59\x03\x1a\x31\x7d\x4e\x2b\x6a\x73\xc4\xc3\xf9\x5b\x58\x2e\x72\xa6\x42\x02\x21\x58\x7b\xac\x12\x0f\xb8\xed\x73\x48\x07\x0f\x28\x60\xd8\x58\x66\xa0\x9f\xe7\x56\x74\x34\x97\xf2\x11\x9b\xc1\xbf\xdf\x57\x3b\xe3\x5d\x10\x91\xbe\x37\xf1\x8b\xcd\xa6\x74\x1c\x90\xd5\x66\xcc\x92\x4b\x72\x16\x4b\x74\x9a\xf9\xa6\xf4\x0f\x71\xd3\xea\x5d\x87\x64\xcd\xc8\x17\x14\xbd\x73\x95\xe5\xf6\x79\x97\x36\x36\xef\xf1\xdb\x1c\xf0\x01\x29\x83\xf7\x1a\x2f\x2b\x12\xd4\x5a\x29\x4e\x5a\x38\x9f\x4c\xd2\x48\x3e\xb3\x9d\xa0\xdf\x26\xb7\x36\xc7\xaf\x6e\x41\xdd\x35\xa7\x8e\x45\x29\x2c\x39\x4e\x34\x68\x95\x32\x88\x87\x21\xf8\x63\xc5\x6d\xb9\x7d\xa1\xcd\x10\xa6\x6a\x20\xa6\x70\xb2\x7f\xe8\xce\x55\x68\xa4\x2b\x89\x37\x79\x0c\x7b\xe1\xaa\x42\x0d\x20\x3d\x7a\x88\x5c\x17\x29\xcd\x6b\x8e\x19\x71\x89\xe4\x79\xd5\x42\xcb\xcb\x9b\x53\x65\x6f\x2b\x9f\x53\x9c\x32\x5c\x34\xaa\x59\x8f\xd9\x1e\x7d\xf7\x0f\x9a\x74\xab\xec\x46\x76\x54\xb1\xc9\xa3\xd1\x44\x38\xe7\xc0\x83\x60\x40\xb7\x93\x87\x1e\xcb\xe9\xe5\xf6\x68\x0c\xcc\xcd\x5d\x46\x96\xa8\x7e\x37\xe8\x9e\xab\x28\xb6\xbd\x67\x9e\x8f\xe1\x62\x7b\xdc\x9d\x37\x3b\x82\xf5\x2c\xd8\xc4\x9b\xe9\xba\xcd\xc6\x30\xa3\x2f\xd1\x28\x35\x25\x5a\x54\x2f\xb7\xb1\x23\x93\x77\x9d\x44\x98\xaa\x06\xa0\xe7\xe1\xa4\x97\x79\x39\x81\x7e\xb2\x08\x8a\xf1\xe1\x9b\xb0\xe5\xac\xa8\x54\xc1\x25\xdc\x60\x3d\x83\x57\x36\xa0\x3d\x93\x80\x51\x53\x0c\x9a\xb1\xaa\x3b\xc7\x79\xb3\xba\xe7\x45\x0e\xf5\x7d\x1b\x3f\xc0\x93\xa3\x7d\xbe\x9d\x1b\xd6\xd0\x40\xf2\xf8\xee\xba\x77\xf7\xfa\x88\xc1\x49\xf0\x65\xc7\xac\xe3\x32\x77\xaa\x99\x69\xc2\x66\xea\x6d\x85\xca\xd6\x2c\xfa\xf5\x50\x8e\x70\x32\x71\x6b\xe6\x84\xa2\x28\x56\x41\x3e\x0e\x65\xe4\x2b\x6e\x9e\x6d\x86\x5a\x87\x36\x3c\xbb\x62\xd5\xbb\xb6\xa3\x73\x1d\xdd\xa0\xfa\x6a\xd0\x29\x3a\xf9\x89\x3c\x09\xa9\xe7\x43\x09\x0f\x2c\xee\x2f\x44\x37\x73\x6d\xd4\x33\xe2\xac\x74\x28\xbd\xc8\xc7\x7c\xb9\x96\x43\x55\xfa\x44\x15\xcc\x38\x31\xd8\xc7\xca\x5a\xf9\x3d\x51\x75\x2e\x71\x8c\x60\x66\xec\xa1\x42\x6a\x87\xc2\x98\x08\x28\x1a\x85\xac\x7e\x0b\x40\x44\xff\x6e\x28\x0e\x28\x01\x4b\x93\x83\xd1\x9c\x9d\x38\x7d\x29\xdc\x14\xde\x43\x3d\xa2\x60\x78\x4a\x49\x44\xca\x76\xc2\xfe\x8a\x08\x0d\x09\x96\xd9\xa6\xc2\xa3\xd3\xa7\x07\x72\x80\xed\xce\xe0\x38\x9a\xa8\xe5\x36\x5d\x1d\x9b\x34\x6e\xca\x09\x47\xb0\xff\x52\x65\x94\x3c\xcf\x09\x93\x9a\x4b\x4a\x8f\x98\x5f\x6a\x5e\x72\x72\x3c\x79\x5d\xa0\xbc\x36\x0d\xce\x50\x1f\x67\x3a\xb6\xea\x84\x43\xf1\x29\x42\x79\x52\x45\x3e\xb7\x2b\x3a\x8d\x0d\x97\x6c\x27\x8c\x5b\xd1\xa9\x85\x3c\x91\x8e\x0c\x24\x0c\x3c\x73\x49\x32\x95\x3f\xdb\x50\x39\xfb\xb0\x46\x87\x93\x7c\x9f\xf0\xab\x74\xa1\x6e\xae\x21\x2b\xc6\xf2\x0e\x70\x0a\x77\xc0\x92\xd2\x3d\x2e\xfb\x58\x0e\x0c\x19\xd6\x5f\x30\x41\x29\xab\x8e\x6c\xc1\x2e\x58\x05\x22\x57\xba\x09\x44\x9f\x30\xd3\xd9\x74\x39\x1a\xff\xf5\x63\x3d\xef\x2f\x5c\x4e\xbd\x57\x3a\x9e\x44\x4b\xf3\xa3\xdd\xac\xed\xf0\x2c\x05\xf3\xcc\x2e\x75\x06\x64\xa8\x4a\x1d\x24\xc5\xd2\x8b\x49\x67\x0d\xe8\xa2\xf2\x09\x08\x39\x48\x3c\xa3\x89\x59\x99\x1a\x7d\x37\x27\xe2\x1a\x15\xe8\x20\x16\xc1\x5a\x09\xee\x71\xf4\xf4\x3c\x0a\x60\x8b\x48\x48\x5c\x99\x34\xa3\x86\x14\x79\x4d\x62\x91\xda\xa3\x9c\x01\xc4\x5d\x3d\xeb\xe5\x79\xb5\x82\x3b\xf3\x40\x64\x04\xb4\xc8\x0e\xe6\xff\x34\x2b\x46\xb3\x34\xb0\xb8\x83\xb4\x0b\xfd\x2f\x9a\x53\x59\x5a\xb6\x2f\xd1\x35\x1e\xbc\x88\x30\x83\x70\x49\x72\x18\xdf\xc9\x8c\xe0\x81\x40\x7d\xa8\x12\xa4\x6d\x64\x97\xd7\xaf\x9e\xc6\xd8\x3e\x1c\x60\xee\xb7\x12\xd8\x89\xdf\xbe\xd0\xc8\x05\xaa\x11\xcf\x81\x7d\xd8\xf0\x43\x96\xef\x87\x1a\x26\x11\x2d\xcb\x7c\x0e\x1d\x2e\x68"}, -{{0x61,0xfa,0x86,0x77,0xee,0xda,0xde,0xd6,0x9b,0x16,0x5c,0x8d,0x27,0x7c,0x97,0x82,0x49,0x66,0x30,0x28,0x30,0x1d,0xf6,0x16,0x3e,0x39,0xb0,0x6a,0xc2,0xf5,0x62,0x5f,},{0x87,0x33,0x9e,0xb5,0x72,0x38,0xdb,0x2e,0x4e,0x60,0xf3,0xc2,0x8a,0x3f,0xd5,0xfb,0x61,0x1c,0x65,0xfd,0xdc,0x81,0xee,0xd7,0xcf,0x77,0x71,0xdf,0x34,0xd9,0x22,0x67,},{0xc0,0x4e,0xbd,0x11,0xc3,0xeb,0x09,0x39,0x6f,0xe8,0xd6,0x82,0x79,0x51,0x0a,0x9e,0xfe,0xe3,0x91,0xab,0xee,0x40,0x81,0xf0,0xd2,0x75,0x67,0x4a,0x30,0x47,0x94,0x83,0x5a,0xad,0x7f,0x3e,0x34,0x5b,0xcf,0x0a,0xf8,0x02,0x7f,0x97,0x47,0x7e,0x79,0xe6,0x79,0x2b,0x8f,0x29,0x98,0x46,0xae,0x28,0xcb,0x13,0xbd,0x88,0x75,0x37,0x99,0x0d,},"\x02\xc5\x81\xde\xe0\x3f\x2c\x60\x39\x35\xaf\x5e\xce\xec\xfa\x67\x71\x34\xa3\xe0\xae\xa5\x4f\xec\xaf\x42\x71\xfb\x52\x95\x1a\x27\xb7\x68\x77\xcc\xd4\x9a\xb4\x86\xdf\xc2\x27\xcf\x31\xc9\xd9\x57\xcc\x97\x30\x65\x73\xfc\x7f\xe1\xd3\x1b\x6c\x7d\xf3\xd7\x80\xf3\xa0\x5c\xa6\x39\x56\x57\xa9\x42\x43\x42\xc9\xc6\xb7\x03\x12\x7e\x03\x8d\xf0\x79\x21\x54\xe3\x0a\x49\x47\x61\x12\xcb\x92\xd0\xd5\xa2\xd2\x2e\x89\x57\x52\xa8\x6e\xdd\xdd\x91\x2f\xdc\x81\xb1\xe6\x4a\x7b\xb7\x50\xf0\x99\x18\x21\x32\xee\x48\x23\xfd\xe8\x45\x80\x2a\x94\x45\x39\xd4\x12\xb2\xa8\x1a\x15\xb0\x00\x71\xa9\x50\x50\x4c\x5b\x55\xa7\x1b\xdb\x8c\x5a\x58\x26\x39\xe8\x55\xe8\xbe\x24\x1c\xda\x1b\xa6\xb3\xb4\xf6\x45\x54\xd1\x78\x24\x90\x4c\xb3\x0c\xd7\xef\xd9\xac\x04\x9e\x39\x0b\xb7\x9f\x53\x59\x8e\xf1\xe8\xfc\x27\xdd\x7b\xf5\x99\xc9\x02\x8c\x9e\xbf\x92\xfc\x3b\xe1\x1d\xf3\x29\x61\x2a\x22\x8e\x0f\x56\x84\x68\x7b\xf4\x1f\xf2\x03\xe9\x7a\x76\x86\x12\x6a\x39\x36\x6b\xdc\x26\xd5\x0b\xe0\x25\xd5\x18\x7c\x6b\xa0\x66\x6e\x37\x9b\xe4\xa8\x0a\x9e\x62\xef\xfc\xd9\x16\xd7\xf9\x8d\xe6\x51\xe0\x0b\x97\xad\xf5\xd2\xd5\x3d\xaa\x7f\x8d\x69\x5a\x29\x15\x60\x75\x5c\x74\x44\x82\x36\x4c\x4f\x1f\xa4\x7e\xc0\xb1\xda\x16\x1a\xa3\x88\xf9\x59\x79\x89\xa9\x77\x26\xd3\xed\x2c\xec\x82\xf1\xa1\xbb\xc4\xac\x0b\xe0\xa0\x0c\xb4\xa8\xdb\x1f\xb7\xc1\x4b\xa0\x5d\x89\x63\x48\xdc\x05\x59\xd2\xa9\x0b\xea\xc2\x04\x1d\xd7\x7f\x82\xd6\xb1\x2a\xeb\x22\x43\xca\x0f\x41\x9a\x57\xd3\xca\x9c\x7d\x25\xa3\x0f\xf0\xe8\xbb\x0d\x94\x51\x55\xd1\xb3\x6a\xd1\x07\xb5\x5b\xea\xa9\x5b\x7d\x5e\x32\x00\x34\x07\x62\x9f\x15\x15\xf8\xa7\x08\x9e\x24\x88\xd0\xd7\x54\x4c\x2f\x7c\xc7\xc7\xf0\x98\x5d\xa4\x28\x40\xd4\x36\x8f\xf4\xf0\xfa\x4f\xa2\x98\xe3\xb7\x22\x93\x03\xab\xa5\x14\xae\x94\xe7\x02\x65\x35\xa3\xf4\x26\xff\xbb\x4e\x00\x1c\xd5\x0e\xd1\x2f\x21\x4b\x3a\xbe\xf9\x6e\x30\x16\x35\xc9\x87\xb1\x33\xfc\x5e\x61\x84\xe7\xb7\x57\x2b\xc3\xd9\x9a\x45\x23\xcb\xd5\xaf\xe5\x93\xce\xdf\x4c\x9c\xd0\x2f\xf2\xe3\x62\x37\xe4\xee\x12\xef\x1a\x22\xd1\x6d\x7c\xf4\xc0\x72\xdc\xed\x91\xcd\xd2\x6e\xe1\x44\xcc\x2b\xef\x49\x50\x02\x63\x49\xe9\x44\x47\x84\x08\x1f\xe4\xe0\x49\x8b\xc7\x5f\x72\xe6\x81\x8f\x45\x9b\xba\x90\x49\xc5\x61\x31\x6c\x9f\x49\x8e\x7b\x1a\x99\x4b\x0e\x93\x05\x5f\xe7\x3e\x44\x4c\xbd\xf9\x6a\xc3\x5e\x9c\x4e\x92\xe6\xb4\x9e\x3b\xc0\xe9\x9d\xe1\x71\x6d\xf8\xea\xca\xeb\x8d\x2f\xd7\x48\x70\x04\x4c\xb3\x9c\x0e\x36\x7a\x1f\xe3\x2a\x9b\xb2\x97\x44\x16\x36\x4e\x73\x0d\x52\x48\xdf\xb1\xdf\x16\x4a\x8d\x58\xca\xa1\x00\x5f\xdc\x91\xba\xc2\xbc\x01\xcc\x77\xde\xcc\x14\x89\x3e\xf9\x46\xfb\x3c\x81\xbe\x08\x32\xc7\x2f\xba\x37\x20\x62\xf8\x36\x0f\x4d\x8e\x6d\x5b\x74\x1c\xf7\x03\x2d\x8d\x89\xde\x2e\xdf\x4c\x71\x4a\x29\xf7\x5a\xbd\x8f\x5f\xf4\x3e\xcd\xd4\xb7\xa0\x4d\x7d\xb0\x88\x2d\x16\xe7\x44\x73\xa0\xfb\x79\xdb\x44\x4a\x78\xea\x44\xaa\x26\x31\xb8\xc0\xd7\xb0\x30\x0d\x55\xcb\x6a\xc4\x85\xf2\x4c\x0a\xcc\x64\x77\x47\xc4\x3d\xb3\xb2\xa8\x67\x7b\xaf\x65\x6f\xa7\x35\xa5\x75\xf1\x81\x3f\x36\x68\xa2\xac\xa9\x17\x57\x11\xb5\x25\xeb\x49\x6e\x9e\xf9\x71\x1d\x75\xf5\x90\xc7\xd9\xef\x99\xe0\xf5\x9e\x84\x83\xcb\xf9\xf2\x84\xe3\xf5\xa3\x3e\xe7\x78\x1e\x62\xb8\xb0\x55\x51\x77\x7e\xfe\x0f\xbf\xd1\x9e\x54\xb6\xbb\xd1\x42\x94\x4b\xc2\x95\x9a\x82\xeb\xd2\x95\xd2\x3d\x34\x43\xb6\xce\x65\x8c\x2d\x57\x9a\x76\x37\xb5\x49\x52\x04\x91\x90\x8e\x34\x28\x2e\xc2\x71\x69\x72\xe6\xf0\x35\x39\x29\x54\x7e\xf1\x53\x7a\xec\xc9\x6b\x2d\xf6\x16\x14\x85\x99\xb0\x9d\x9b\x81\x39\x4a\x13\xfe\x7d\xb8\x67\x60\xb1\xe2\xa0\x60\xef\xd4\x84\xe8\x18\x99\x39\xeb\xdf\x6f\x21\x64\x0d\x89\xd8\xe7\x36\xde\xe0\x82\xad\x72\xa0\x18\x4a\xde\xdd\x8d\xf2\x14\x74\xc9\xf5\x26\xbc\xfd\xf7\xe8\x56\x58\x19\x4b\xb6\xd9\x42\xe7\xf3\xfe\x96\xc2\x3f"}, -{{0x70,0x48,0xc6,0x52,0x1a,0xef,0xaf,0xa4,0xea,0xc6,0xd6,0xc3,0xa7,0x02,0xb9,0x52,0x54,0x80,0xa6,0x64,0x82,0xe4,0x96,0x98,0x96,0x75,0x7f,0x2c,0xd1,0xac,0x7d,0x5b,},{0xed,0x93,0x11,0x3c,0x16,0x43,0xa5,0x3a,0xa0,0x64,0xca,0xa6,0x31,0xce,0xb6,0xe2,0x0f,0x6d,0x6e,0xc2,0xfc,0x6c,0x07,0x11,0xcb,0x8a,0x1f,0xe7,0x31,0x39,0xaf,0x93,},{0x7c,0x45,0x70,0x3e,0xd3,0x94,0x2e,0x44,0x04,0x1c,0x7f,0xa1,0x85,0x8a,0xa5,0xf1,0xdc,0x38,0x1f,0x49,0x3a,0x45,0x2d,0xfb,0x52,0x70,0x80,0x17,0x89,0x8f,0x71,0x0e,0x31,0x11,0x8e,0x33,0x1f,0x00,0xaa,0x64,0xcb,0x73,0x88,0x36,0x68,0x2b,0x7d,0x17,0x7e,0x97,0x95,0x5c,0x00,0x31,0x9a,0xbd,0x79,0xa4,0x9e,0x0f,0xcd,0x16,0xfe,0x00,},"\x53\xf7\x4c\x72\x4d\xb1\x57\x8a\x1a\x29\x6a\x7c\xca\xc9\x04\xa2\x50\x4d\xd9\x00\x53\x89\xb4\xf8\xd4\xea\x4b\x63\x07\x29\x8f\xc6\xdc\xce\x98\xa6\xbc\x07\x28\x0d\x20\x36\x4e\x40\x5a\x46\x7e\x73\x65\x78\x96\x52\x69\xc8\x14\x61\xd6\x1f\xc6\xb7\xe4\xba\xd6\x8d\x2b\x6d\xd0\x00\x58\x50\x10\x5f\x0a\x67\xbb\xc6\xee\x22\x3e\xc1\x75\x4a\xf4\xe3\xb9\xaf\xa5\x06\x2d\x1c\x18\x61\x04\x8f\x18\x5b\x12\x8f\x1a\x5c\x0f\xb2\x5c\x39\x19\xb4\x83\x3e\x29\xe2\x02\xbc\x94\x1a\x90\x5e\x63\xc2\xc0\x5b\x10\x14\x64\x7b\xd7\xed\xe5\xbe\x9f\x99\x66\x15\x18\x7a\x3d\x3b\xb2\xc7\xdc\x4c\x28\xf7\x05\x3d\xef\x9b\x28\xb2\x9e\x23\x31\xf1\x62\x96\xdc\xe8\xf1\xed\xe4\x84\xca\xec\x99\x67\x02\xbd\x99\x02\xe5\x26\x84\xc8\x12\xc8\x74\x40\xf6\x9b\xd1\x41\xc7\xe0\x0c\x69\x47\xd1\xfc\x7c\x3b\xdc\x0b\xc5\x50\x6b\x6e\xa4\x62\xe6\x5f\x9e\x74\x3b\x72\xc0\x07\xdd\xc7\xa3\x77\x49\x37\x77\xd4\xeb\x12\x62\x0c\xa6\xc0\x19\xc8\xbf\xc4\xc2\x9e\xc8\xaf\x38\x2f\xc3\xea\xc8\x41\x02\x1a\x74\xe4\x67\x4b\xa3\xe4\x3e\x5d\x7b\x41\xe3\xfe\xeb\x17\xda\x00\xa7\xce\x45\x5a\x1c\xec\x70\xb0\xbe\x6e\x56\xf8\x5f\xc3\x7f\x64\xcf\x07\x33\xb7\xe3\x12\x41\xde\x64\x1a\x8a\x8e\x5b\x91\x89\x7b\xc1\x58\xfe\x93\xd1\x02\xc0\x1d\x1f\x5e\x16\x6d\x40\x81\x65\xfe\x3f\xcb\x13\xd5\x30\x45\x90\xab\x8e\xf0\xdc\x8d\x5a\x8c\x1d\x8a\x93\xfc\xeb\x85\x4f\xc1\xfa\x36\xd0\xcc\x48\x0c\xf8\x51\x2d\x80\xbe\xe6\x9b\x06\x50\xa9\x57\xda\xed\x28\x3c\xd7\x63\x81\x55\xed\x77\x30\x86\xe8\x6a\x8f\xfb\x19\x8a\xcc\x74\x23\xb5\xd1\xa6\x09\xa1\x75\xa5\x6b\x94\xc9\x6b\x73\x18\x51\xb9\x3a\x94\x97\x71\x01\xe2\x55\xf1\xce\x92\xe2\x32\xa0\x5e\x2e\x33\x87\xfc\xb4\xdc\x13\xa3\x1b\xee\x6e\xe2\x55\x07\x32\x2c\x73\xc9\x88\x30\x80\xa7\x4c\x00\xf8\x03\xa9\x98\xdd\x53\x0a\x79\x12\x6b\xb1\x44\xed\x55\x74\xc4\xb2\x31\x80\xe3\x4e\x09\x92\x83\xb4\xbb\x1d\x28\x82\x2f\xce\x37\x17\x04\x6f\xf3\x2e\xf9\xe2\xcd\xf9\x67\xe3\x18\xea\x72\x6a\x2a\xee\xc5\x78\x06\x64\x3a\xd4\x80\x1d\x3e\x0d\xa5\x2a\x1d\x77\xbf\x04\x3f\x5a\xe9\xf3\xae\xa9\xe4\xbc\x4f\xa7\x95\xd0\x84\x01\x08\x5c\xa9\x4c\xfc\x4c\xe7\x19\xda\xbc\x7b\x23\x90\xd0\x3d\x29\x4a\x65\xb7\xaf\x9b\xc3\x90\x72\x28\x5b\x77\x7b\x2f\x13\x3d\xc1\x1a\x70\xc0\xa9\xf0\x60\xe1\x04\x41\xf4\x02\x16\xac\xb6\x41\x63\x7a\x2e\xad\xf1\xf7\xb8\xd2\x62\xfe\xc1\xb4\xd0\xf0\xf4\xfa\xa9\x3f\x3f\x73\x2c\xac\x38\x2d\x8a\xc4\x2e\x17\x8e\x22\x44\x99\x9d\x76\x4a\x9d\x0e\x98\x17\x14\x68\x6e\xb4\x92\x44\x97\xe5\x6b\x50\x15\x7e\x99\x39\x03\x2c\x9f\x88\xeb\x65\x7c\xfd\xe4\x4a\xd3\x47\x14\xaf\x4a\x51\x32\x4e\x5e\x77\xd0\xde\xea\x99\xc9\xf2\x44\xd2\xe0\x9e\xa4\x25\x82\x0a\x74\x6d\x88\x3a\x0c\xf4\xb7\x05\xc2\x9d\xf8\xc0\x37\x44\x81\x54\xdc\x08\xa4\xd4\x33\x74\x05\xfb\x87\x65\x82\x31\x14\x37\x0b\x37\xed\x86\x08\x6e\xc5\xf8\xbd\x6c\x72\xab\xf1\x3f\x51\x84\x30\x71\x0f\x59\x7b\x06\x10\x8f\x65\xb3\x0a\x48\x34\x96\xe2\xed\x81\xda\xb1\x0f\xee\x94\x7f\xe0\x4b\x54\x85\xf2\xe3\x07\x40\x49\xd2\x22\x84\x26\x66\x51\xad\x10\xdd\x08\x6a\xaa\x5d\x45\x2e\x0d\x1a\x61\x12\x9d\x1e\x77\xc6\x63\xc2\x6d\x08\x89\x62\xb5\x54\x56\x45\xb7\xa1\xa8\x71\x3d\x51\x32\x7a\x7a\x35\x9b\x12\xda\xad\xb8\x5a\x2c\xd4\xb5\x41\x0d\x5c\x20\x26\x7f\xa7\x66\xb8\xc4\x2a\x84\xdc\x42\x66\x45\x88\x87\x9b\x3e\xae\xfd\x4c\xc8\xdc\x69\x3f\x98\xac\x20\x56\x09\xe5\x70\x66\x5b\x01\xea\x46\x55\xe3\x94\x29\xa7\xa7\xe5\x42\xef\xb4\xf7\x89\x0d\xbf\x4e\x34\xc6\xcf\xf0\x7e\x4d\x35\xbd\x3e\xee\xdf\x5b\x46\x28\x0f\x4a\x0d\xa0\xc2\xe7\x3c\x94\xea\x81\xcf\xea\xe7\xf9\xbd\x04\xfe\x2d\x45\x97\x65\x00\xf7\xdc\xac\xb0\xdf\x2a\x5d\xc7\x36\xa8\x23\x67\x1d\xb6\x79\xbe\x66\xcb\x33\xc1\x62\xfd\x2c\x74\xae\x71\xfb\xf4\xd2\xb0\x5a\xf0\x42\xb3\xa9\x77\xf5\xb9\x44\xb9\xfd\xb6\xc3\x44\x24\x42\x1b\xcf\x4f\x62\x23\x76\x84\x28\xfa\x14\x0f\xd4"}, -{{0x3e,0x63,0x73,0xb2,0x65,0xb9,0x67,0x89,0x00,0x7a,0xd2,0xa1,0x0c,0x30,0x9a,0x56,0x76,0x38,0xf2,0x55,0x87,0xd7,0x7e,0x28,0xb0,0x82,0x3a,0x4f,0x17,0x9a,0xe4,0xfe,},{0xa3,0x23,0x4e,0x5d,0x13,0xb0,0x34,0x72,0x16,0x50,0x36,0x40,0x4f,0x6d,0xe8,0x0e,0x70,0x28,0x39,0x50,0x0f,0x13,0xd9,0xc9,0x85,0xa0,0x77,0xd4,0x5c,0x69,0xff,0x45,},{0xf5,0x1e,0x0f,0x87,0x8a,0x5a,0x70,0x96,0x47,0xe8,0x5f,0xea,0x83,0x9f,0xd5,0x66,0xe6,0xf3,0x5c,0x8a,0x61,0x85,0xd0,0xc9,0xeb,0x13,0xe0,0xd5,0xb9,0xe6,0xe8,0xaa,0x95,0xc3,0x33,0xa8,0xf5,0x06,0x32,0xa4,0xd6,0x65,0x7b,0x51,0x8c,0xe4,0xcf,0xde,0x40,0xb8,0xf5,0xa0,0x5b,0x2d,0x9f,0x84,0x41,0xfc,0xc9,0xd2,0xd6,0x92,0xd5,0x09,},"\xb9\xd0\x68\xbb\xca\xe7\x72\x2f\x82\x8b\x0f\x8c\x98\xa7\x38\xe3\x6a\x7d\xf4\xc9\x97\xc7\x24\xba\x27\x53\x1a\xf3\x4a\x2f\x10\x6c\x75\x13\xa4\x4a\x46\x1a\x9a\xa4\x30\x9b\xc1\x5c\x4e\x0d\x42\x75\x91\x93\xea\x1c\xde\xa9\x56\xbb\x81\x59\x85\xf5\x78\x67\x14\x5e\x9e\x2c\x75\x85\xfc\x8d\x61\x02\x7e\x47\xd2\xd7\x35\xe2\x44\x8a\xf3\x78\x29\x09\x40\x4e\xde\xaa\xc0\xfd\x73\xf6\x04\x5d\xcd\xb0\x4f\x03\x77\x75\x8f\x02\x20\x4a\xae\x3a\x72\x20\x31\x1c\x0f\x47\x23\x58\x27\x10\xcc\x44\x0c\x36\xc9\x58\x7b\x5c\x9e\xbc\x40\x63\xfe\xa8\xca\x3f\x43\x19\x58\x94\xf7\x9a\x36\x50\x87\x13\x72\x82\x30\x2d\xbf\x2e\x7a\x0d\x41\x1a\xb5\x8b\x70\x26\xcc\xde\x19\x88\x69\xaa\x73\x43\x34\xc0\x52\x38\xe2\x75\xe3\xc3\xab\x21\x70\x83\x49\x57\x69\xe2\xfa\xd3\x74\x05\x14\x52\xd7\xf5\xb1\xdb\x0e\x78\x58\x36\xd4\xbd\x5e\x29\x78\xa3\xe9\x91\xaf\x0f\xf7\x16\xf4\x38\x89\xa0\x7f\x5d\xf2\x99\x60\x36\x21\xc3\x9e\x2c\xde\xe0\x89\x98\x5d\x9e\x6b\xf7\xb2\xfb\xd0\x23\x73\xae\x1b\x5e\x9b\x88\xf5\xb5\x4a\x07\x6e\x67\x6d\x77\x90\xbf\xc8\xf5\x7d\xcc\x59\xef\x52\x85\x0c\xe9\x92\xa7\x3b\xa7\xbc\x99\x1d\xeb\x4d\xde\x5e\xb0\xb2\x16\x70\xb1\xb3\xd4\xb6\x4f\x36\xcc\xa8\xe3\x07\x09\x85\x68\x49\x7d\x89\x16\xf6\xb5\xd0\xe9\xe8\x9f\x99\xf8\x60\x06\xf3\x9b\xd3\xa8\x10\x76\x9c\x8f\x78\x01\x77\x3c\x96\x38\xab\xcf\x5e\x27\x11\xb1\x9d\x11\x67\x59\x3a\xcb\xe8\x5e\x41\x61\x42\x89\x97\xa2\x19\x4d\xc5\xe7\xb7\x64\x0f\x0d\x2c\x1e\xb2\x05\x55\x3b\xe9\x16\x7f\xfb\xc2\x2b\x7c\x2e\x76\x98\xf3\xaf\xa1\x07\x54\xcb\x44\xd4\xb1\xd4\x5b\x83\x73\x03\xb1\x66\x90\x73\x41\x5a\x22\x60\x6b\x50\xf2\x1f\x82\x65\xe1\x39\xf2\x30\x5a\xc0\xe0\x12\x7a\xe0\x56\xce\x8a\xbe\xab\xa2\x0e\x1d\x26\x9a\x2b\x2e\x89\x9c\x49\x54\x72\x68\xa0\x69\x6a\xe4\x50\xdc\x02\x67\xf7\xf6\x3a\x8e\xdf\x07\x4c\x47\xd3\xc2\xdb\x1d\xa3\x63\x93\x73\x73\x04\xe6\xdd\x4f\xac\xcd\xb6\xab\x55\xe5\xf8\x52\x0c\x3d\xff\x5f\x6b\xea\xc3\x0b\xa8\x5b\x86\x08\x23\x51\xe3\xde\xd8\x40\x0a\xa5\x7f\x65\x0c\x0c\x33\x03\x6d\x65\xb3\x9b\x7d\x2f\xb6\x11\x28\x63\xd5\x9b\x72\x55\x82\x42\xe8\xb0\x45\xad\xdd\x35\x7d\xe6\xfd\x37\xa8\xf6\x61\x17\x65\xc9\xb5\xff\x19\xcc\x4d\xb7\xe1\x17\xc6\x5a\x00\x45\x89\x08\xb0\x24\x5d\x04\xf7\x90\x8f\xc7\x3b\x16\x5d\xff\x6e\x4b\xe4\xb4\x20\x32\xd8\xcf\xd7\xd6\xf7\x77\x2c\x1b\xfe\x72\x1d\x4b\xcf\xe2\xfc\x52\x79\x98\xf3\x4f\xb4\x41\x8a\x1f\xae\x1e\x6c\x37\x67\xc4\xd0\x78\x06\x21\xf9\x23\xda\x1f\x0a\x0d\x3d\x21\x9c\x03\x6a\xcf\xd3\x70\x9d\xad\x4c\xf2\x4d\x90\xbc\x69\x1d\x70\x0e\x6a\x9c\x80\xcc\xfd\x10\xbd\xe8\xe7\x91\xc0\xfe\xa8\x28\x80\xc0\x7b\xaa\xaa\x31\x1e\xef\x79\x24\x07\x84\xf6\x28\xa7\xd2\xa0\x91\x84\xe0\x16\xf8\x10\x08\xe7\x74\x29\xa8\x65\x8b\x15\x3e\x44\xe7\x9a\x98\xad\x24\x8f\x7f\xda\x23\xb5\x90\xd6\x46\xd7\xc1\xd8\x41\xf4\x92\x7d\x6e\x8b\xc7\x32\x14\xd1\x0a\x7f\x3c\x29\xc8\xf8\x39\xa8\x90\x8d\x20\xa7\x4e\x82\x7a\xf4\x67\xac\x5a\xbf\x0f\x1d\x0e\xd3\x9c\xdd\xd9\x69\xdd\xe9\xee\xb4\xa4\xb7\x52\x7a\xb3\xe2\x47\x5a\x19\x5e\x24\x47\x4a\x4e\x36\xb0\x90\x52\xe2\xda\xd4\xa5\xeb\x46\x91\xe2\x63\xb8\xc6\x1b\xbd\xe8\x77\x72\x20\x7e\x01\x1c\x4c\x1e\x14\x23\x5f\xb2\x4e\x4d\xa4\x38\x87\x5d\x18\x53\x0f\xef\x90\x26\x19\xdd\x48\x5d\x77\xb5\x45\xab\xb5\x6b\x69\xc7\x55\xaf\xe7\x58\x60\x69\x71\xab\x97\xdd\x3a\xce\x1c\x1a\x34\xa3\x37\x94\xc8\x15\x6d\xa7\x99\xe8\x22\x4d\x88\x5e\x18\x68\xf9\xcb\x46\x6d\x80\x2c\x82\x7c\xc3\xe1\xec\xd0\xae\x6e\x0b\x01\xf8\xf7\x91\xb1\x22\x08\xfc\xc0\xfe\xd3\x85\xb7\x96\xeb\x2f\x29\x08\xb5\x8d\x30\xb3\x73\x3f\x14\x70\xf2\xe2\xef\x12\xad\x43\xfe\xb7\x2d\x08\x16\xde\x3c\x13\xa8\xb5\xa5\x23\xe1\x4c\xdf\x5f\xf3\x72\x0b\xf8\x77\x69\xcd\xe7\x49\x5d\x22\x6b\xf3\x82\x38\xa8\x25\xf7\x5a\x09\xf6\xbb\x9a\xfc\xe5\x16\xa7\xbc\x70\x11\x43\x70\xbb\xc4\x0f\x17\xc7\xbc"}, -{{0xf5,0xe8,0x59,0x7e,0xac,0x0e,0xbf,0xa9,0xd3,0x85,0xde,0x85,0xa1,0xfb,0xaa,0x35,0x14,0x63,0x95,0xb1,0x34,0x57,0xb5,0xb1,0x4d,0x36,0x70,0xda,0xca,0x69,0x05,0xe7,},{0xce,0x93,0xe6,0x42,0xc2,0xf1,0x50,0x84,0xbc,0x83,0xba,0xfd,0xaa,0x19,0x67,0x63,0xde,0x2a,0x3c,0x51,0x3b,0x0e,0x44,0xf6,0x8d,0xdb,0xde,0x37,0x85,0x14,0xc4,0x41,},{0x57,0x65,0x43,0xfc,0x21,0xab,0x0a,0x7c,0x5f,0x63,0xb1,0xcf,0xf0,0x1b,0xf8,0x45,0xdf,0x91,0x79,0x2e,0x7a,0x97,0x50,0xc5,0x50,0x8b,0x51,0x66,0x5e,0x7f,0x89,0xf1,0x7c,0x6e,0xc3,0x35,0x5a,0x0a,0xed,0x87,0xdb,0x8c,0x77,0xbd,0xb2,0x71,0xfb,0xed,0xc7,0x14,0xff,0xad,0xb7,0x8b,0x5e,0x0f,0x97,0x81,0x16,0x77,0x1b,0xa7,0xcf,0x0b,},"\x27\x33\x41\xf2\x19\xff\x5c\xf3\x81\xc7\x7b\x2d\xd2\x26\xc5\x8f\x8f\x33\xc4\x52\x70\x48\xcb\x00\x6a\xff\xef\x8c\xee\x15\x1e\x30\x0e\xfe\xf6\x29\xfe\xd2\x1b\x70\x45\x1f\x72\x92\x92\x62\x7d\x1f\x3f\x1b\x52\x57\x35\x9e\xe5\xa6\x71\xcf\x62\xae\x57\x32\x49\x40\xf2\xd0\xb1\x5a\xac\x76\xff\x39\x82\x20\xc0\x80\x24\xe2\x9a\x8c\xf3\x65\x04\xe1\x2a\x4e\x96\x43\x8f\x42\xc3\xda\x0c\x00\x05\x41\xbc\x11\xf0\x91\x38\x1b\x0b\x72\xb5\x8a\x92\x08\x3f\x44\x6e\xca\x19\x91\x99\x68\x78\xde\x35\x08\x1c\xc4\xab\x90\x95\x8c\x96\xcf\x5c\x99\x79\x6c\xba\x79\x51\xee\x18\x6f\x26\x52\x7a\xed\xe6\x9d\xb3\x04\xce\x29\x41\xba\x15\xcc\x00\xba\x2f\x14\x11\xf2\x08\xda\xd4\x5e\x87\xbc\xf6\x38\x79\x2d\xe0\xa6\x86\x24\xb6\x67\x29\x7c\x27\xa3\x43\xdb\x4b\xaf\x34\xa0\x22\x8e\xaf\x0d\x10\x22\x00\x9b\x5d\x06\x8b\x25\x34\xd9\x20\x30\x2e\x71\x31\x0f\xeb\xf0\xdf\x1b\xb0\x2c\x2e\xf0\xad\x1a\xe1\x49\xde\xad\xf8\xc1\x84\x37\x3c\x0f\x7e\xb6\xb2\x56\x95\xbe\x82\xd1\x2c\x71\xb6\xc8\x32\x67\xd9\xa2\x33\x66\x7e\x77\xbc\x20\x59\x83\xf8\xb8\xd8\x77\xd8\x5a\xea\xd3\xf6\x0e\x82\x0f\xfc\xb1\x7a\xdd\xdd\x92\xa7\x71\x2b\xbe\xb3\x4e\xe7\x19\x66\xda\xfd\x99\x07\xd1\x93\xdd\x9d\x72\x5a\x31\xa6\x13\xd2\x9e\x32\xbe\x72\x13\x28\x08\x92\x6d\x94\x37\x47\x7f\xee\x25\xed\xa6\x10\xae\xb1\xdc\xe1\x2e\xa3\x16\xc6\xae\xc6\x68\x9e\x50\x1c\x55\x19\x23\x82\x5a\x34\xb4\x2c\x4f\x06\x75\xb8\x6a\xb2\x6a\xde\xea\x2e\x60\xda\xe6\xc6\xd1\xcd\xd0\xcb\x3c\x34\x7b\x16\x38\x40\x39\xa8\xe3\xfd\x60\x87\x38\x13\x87\xcb\x4b\xc7\x2d\xdb\x5f\x25\xb3\x74\x85\x9b\x02\xe5\xbb\x1b\xa0\x6d\x3c\xc6\x9e\xc4\x4c\xec\x4b\x98\x5c\x84\x76\xe3\x50\x32\xe9\x9a\xbf\x00\x1a\x1d\x44\xdd\xc6\xe2\x88\x9c\x3c\x2c\x3e\xca\xce\xd6\x09\xb2\xb2\x68\x0e\x00\xb1\xef\xa7\xe9\xd2\x6d\x62\xf2\xb3\xab\x36\xf9\x21\x04\x47\x90\xab\xbd\x49\x36\x07\x56\xdc\xff\xcc\xf2\x30\xf6\x6d\xbb\x70\x1a\xa1\x64\xda\xd6\x06\x9a\xa2\xb8\xb3\x30\x9f\x2f\xe4\x4d\x5e\x0b\x25\xbd\x55\x64\x31\xf0\xdf\x4c\x2e\xa9\x7a\xe7\x9e\xd4\xa5\x75\x78\xd6\x6f\xc6\x93\x9c\x57\x62\x8a\x90\xca\xc9\x7a\xdf\xa8\x70\x2a\x4a\x1c\x89\x65\xba\x1a\x90\x26\x25\x67\x28\x66\x64\x00\x30\x03\x53\x3c\xc9\x31\x4c\xaf\x7d\x3b\x98\x2e\x0a\x43\x2f\xf5\xaa\x4e\xd5\x74\x19\x83\xd9\xb5\x43\x23\xac\x7e\x29\x9b\x2b\x49\x56\xc1\xa2\xc1\x91\x55\x7b\x27\xd8\x6b\xe7\x14\xb5\xb6\x8f\xcb\x1d\x41\xf7\x8c\xa5\xdd\xb6\xb5\x3b\x3d\xfc\x8e\x7d\x6b\x3c\x3d\xb0\x59\xaf\x9f\x2d\xd7\x65\xef\x04\xb6\xd1\x6e\x67\x37\xc7\x27\xaa\x11\xf3\xdf\x37\x74\xa3\xfc\x96\x18\x2e\x28\x2a\xcc\x3d\x23\x3e\xea\xbf\x8c\x72\xd3\xf2\x46\xae\x18\x45\x05\x28\x8f\xef\x39\xb3\x67\x66\xb1\x0d\xd1\xbf\xbf\xbf\xa7\x0f\x97\xb3\xc9\x01\x72\x6d\x1e\x0d\x0a\x83\x7d\x11\xf0\x12\x3a\x34\xab\xad\x1a\x79\xaa\xbe\x80\xb1\x25\xb1\x28\xee\x16\x0b\x51\x18\x48\xf7\xf0\x4c\x49\xc8\xd5\xc2\xf2\x04\x1d\xa7\xd9\x59\x9c\x29\xb1\xda\xc8\xc6\x80\x77\xef\xac\x3e\xca\x58\xbb\xc1\x63\x7a\xad\xce\x21\xc7\x74\xfe\xa4\x2d\x2b\xcf\x4a\x0b\x98\x92\x30\x7e\x36\xfa\x25\x0a\xce\xe7\x95\xad\x2b\xfe\xcf\xbf\x60\x31\x9b\x81\x66\x3e\x2a\x26\x57\x19\x46\xf7\x5a\x8d\x96\x9a\xf1\x6b\x3b\x57\xc3\xec\x3e\x66\x15\x8a\xaf\x42\xcc\xf5\xe5\x8b\x93\x7a\xae\xf6\x13\x31\x86\x06\x60\x33\x17\xe5\xaa\x31\x8b\xe7\x0f\x8d\xa3\xc0\xc1\x6b\xe6\xc2\x9e\x3e\xc9\xfe\xf4\xe4\x6e\x8c\xa2\x41\xd9\x41\xd5\x80\x49\xa0\x63\xd9\x0a\xfc\x95\x3c\xa3\x2e\x8a\x50\xa6\x47\x36\x32\x58\x8a\xc4\x1e\xae\x97\xf2\x0c\xe9\xb7\x41\xed\x41\xc9\xa4\xaa\x65\x51\xfd\x82\x3c\xe0\xc8\x11\xa5\xbb\x5a\x17\x1c\x1e\xa4\x23\x8a\x02\x46\x81\x1e\x46\x9c\xf4\x98\xb7\x96\x21\xc3\x23\xeb\xa7\x98\x53\x44\xfe\x11\xe6\x74\x99\xed\xf4\x96\x74\x91\xaa\x74\x9f\x8f\x3f\xe3\x99\x61\xd7\x68\x92\xc9\x3a\xac\x3b\x19\xfa\x4b\x4f\xc1\x74\xd7\xd4\xd4\xd8\xbd\x6e\xe4\x75\x47\x50\x08"}, -{{0xcd,0xad,0xc5,0xb8,0x9c,0xb2,0xb6,0x30,0x8a,0x00,0x6f,0x2f,0x4e,0x95,0x5a,0x91,0xaa,0xf3,0xba,0x70,0x16,0x5f,0x2d,0x44,0x4e,0xf1,0xff,0xeb,0xbd,0xaa,0xa2,0x21,},{0x05,0x41,0x41,0x5f,0xf5,0x46,0x7f,0x28,0xce,0xac,0x83,0x9b,0x13,0xa1,0x76,0x6e,0x72,0xc9,0x9e,0x65,0x45,0x20,0x7d,0x9d,0x5d,0x96,0x97,0x41,0x1e,0xb6,0xbc,0xa7,},{0xff,0xed,0xe7,0x01,0xeb,0x18,0x29,0xce,0x23,0x61,0xcd,0xa2,0xc8,0xbb,0x63,0x33,0x85,0x39,0xd8,0xad,0x2f,0x66,0x77,0x58,0x55,0x31,0xe7,0xbf,0x1d,0x39,0x22,0x38,0x26,0x79,0xa1,0xae,0x84,0xff,0xeb,0x75,0x3f,0xc9,0x75,0x4e,0x50,0xc0,0x18,0x52,0xf9,0x55,0xe3,0xfd,0x60,0x9f,0xf6,0x4b,0xf0,0x5b,0xbe,0x70,0x75,0xcd,0xbe,0x00,},"\x91\x17\x27\x03\x6d\xb3\x09\xd6\xe2\xe3\x36\x9e\x4f\x17\xd9\x8d\x99\xec\x07\x0c\x33\x28\x3b\xb1\x24\x4e\xfd\x62\xe7\x6b\xd7\x0a\x69\xb9\x72\x3b\xd2\xb5\x20\x47\x2b\x98\xaa\x06\x59\x24\x36\x6d\xe7\x80\x90\x0b\xcd\x8b\x77\xb5\x0f\x87\xc3\xc3\x61\x87\x02\x4b\xbc\x59\xcc\xf4\x48\x2c\x7b\x4a\xad\xb5\x6e\x2e\x5e\xcc\x00\x03\xd9\x89\xd6\xaf\xc6\x3e\xc1\x02\x42\xe5\x74\x82\xfe\x39\x21\x52\x61\xd5\xfc\x95\xa0\x18\x5f\x95\xe9\x54\x0c\x55\xf7\x4d\x69\x60\x48\xbc\xa7\xab\x11\x26\x81\xa5\x55\x8e\xa9\x3c\x3b\x1f\x1c\xd3\x64\x65\x9e\x94\x33\xce\xee\xbe\x05\x4e\xe7\x13\xc4\x77\x60\xd7\xad\x13\x2a\x7f\x3f\x8f\xe3\xd5\x04\x1b\x81\x1a\x26\xb6\x5e\xfb\x1f\x34\x0e\x18\x1a\x4e\xc7\x20\xea\x13\x6b\x3a\xf3\xd9\xe5\x46\x1d\xd2\x43\x70\x33\x6f\x10\xe6\x35\x4c\x8c\x17\xac\xf9\x99\x85\x44\xce\xc0\x87\x3e\xfa\x68\x7c\xb1\x32\xae\xcf\x70\xae\xbb\xc5\x67\xba\x03\xc5\x36\x49\x9e\xf9\x6c\xc8\x41\x2e\x7a\xaa\xd5\xbf\x96\x42\x2b\xe4\x7c\xb9\x41\x36\x45\xdf\x2c\x17\x03\x19\x23\x47\xdc\xbb\x12\x31\x27\x45\x59\x71\xae\x15\x7e\x9f\xa2\xdb\xff\x88\x74\x5a\x96\xc6\x58\xb8\x65\xe4\x1f\x55\xae\xbf\x98\x39\x50\x05\xdd\xcb\xd5\x98\x3e\x6a\xe0\x2c\x4f\xbb\x5e\x17\x91\x67\x96\x32\x5f\x76\xed\xf5\xb6\x4a\xfa\x4e\xc5\xa7\x41\x8a\xfe\xd2\x3a\x97\xef\xad\xe6\x8b\x6a\x5b\x31\x45\xf0\x8a\x5d\x3d\xb9\xc2\x98\xa5\x12\xfa\xbd\xac\x68\x56\x2b\x3f\x55\x37\x7f\xf4\x4b\x00\xc1\xc2\xf3\xef\xd1\x81\x32\xda\x71\xf9\x71\xa9\x53\xa9\x31\x8c\x57\x52\x33\x61\xa1\x60\xf9\xb7\xe3\xb5\x1c\x52\x4e\x95\xdd\x5e\xf4\x56\x8e\xf1\x8a\x80\x07\x75\xe9\xd2\x6e\x07\x13\x19\x42\xd2\xbe\x4e\xf2\x2c\x0c\xbc\x13\xdf\x01\xc6\x8b\x1b\xcd\x3b\xce\x9b\xd5\x1c\x4c\xed\x65\x2a\xdc\x40\x07\xbe\x43\xb3\x7c\x67\xa5\xc5\x5e\xd4\x02\x9e\x8a\xd1\x5d\xef\x83\x05\xc9\x68\x62\x1a\xed\x4c\xd4\xbf\xe0\x79\xa6\xf4\x88\x84\xd8\x56\x80\x39\x2c\xa9\x2b\xa6\xe1\x2f\xea\x6f\x4a\x05\x6f\x79\xd6\x7b\x19\xb0\x5f\x90\xd6\x84\xbe\x7d\x45\x72\x5f\x79\x67\xc6\xa4\x67\xaf\x43\xb8\x6a\x6b\x1b\x9d\x9e\xed\x3a\x42\x48\x97\x1c\x76\xa7\xac\x29\xc2\x92\xdf\xba\x4d\x75\xc5\xf7\xba\x70\x9a\x39\x05\x8e\x96\xad\xf6\xdb\xd7\x60\xd3\xce\xf4\x02\x4b\xf3\xed\xc4\x41\xef\xbf\x11\x47\xa2\xc1\x08\xbd\x6f\x9e\xb4\x39\xc1\xc5\xc4\xd3\xa6\xea\x4e\xc3\xd9\x2c\xef\x38\x13\x61\x88\xbe\xc9\xe0\xb6\xc0\x51\x8d\x8b\x79\xba\x59\xc5\xdc\xba\x39\x3a\xed\xfd\xff\xb0\xb7\x0d\x77\x9c\x2b\x97\x65\xce\x44\x52\xe7\xe3\xb0\x8c\x44\x02\xb1\xa6\x08\x32\x08\x40\xfb\xe9\x6d\x1e\xb8\x65\x6e\xb1\xc2\x0d\x95\x51\xdd\xf5\x33\xb9\xf1\x5e\x4e\xb5\x78\x37\x56\xc5\x3d\xdd\x3b\x14\xd8\x07\xf8\x38\xac\x96\x80\xf8\x9f\x1a\xdf\xb7\x8d\x68\xcc\xb0\x67\x31\xa9\x0b\xea\xc5\xf0\xd7\x09\xd5\xb8\x8c\x75\x43\x7a\x66\x3c\xb9\x62\xd3\x7f\x96\xb8\xe8\x92\x84\x77\xb5\x61\x12\x28\x01\x5d\x33\x7f\x04\x9e\x8b\x62\xe4\xdf\xf8\xd0\xbb\x6c\xda\x24\xa5\xdf\x90\x83\xe3\x48\xbe\xf1\x25\x85\xf5\xf4\xc4\xd3\xbb\x3c\x7e\x78\xd5\x50\x19\x4a\x45\x25\x1a\x08\x79\xa1\x62\x4b\xf9\xdd\x35\xeb\x65\x5c\x39\x39\xfe\xa8\x90\x9f\x6d\xf3\x95\xbe\xbd\x02\xb6\x8a\x17\xa8\x97\xc9\xaa\xdd\xd6\xe2\xe2\x04\x61\xe3\x03\xf5\x7c\xde\xb0\x0a\xe0\xf2\x3e\x60\xa9\x4c\x19\xc7\x71\xd8\xaa\x60\x53\x3b\x93\xce\xdc\x1b\x76\xd2\x29\x0a\x01\xbf\x43\xb2\x72\x5f\x12\x5b\xef\xa5\x75\x15\x4e\x98\x6c\x9c\x62\x05\xa1\x59\x6c\xba\xa2\xd1\x34\x70\xc2\x34\x22\xf2\xdf\x7b\xec\xe4\xe6\xeb\xd7\x52\xe9\x38\x9a\xe6\x08\x57\xb5\x29\x69\xd2\xdd\xef\xa9\xc0\x34\xf1\xbf\x35\xae\x33\x16\x30\x4e\x94\x9c\x89\x90\x82\x0e\x26\xe6\xcf\xfa\xe4\xb3\x88\xd1\x50\x5f\x92\x37\x06\x29\x7f\x8d\xb5\x56\x53\x79\x19\xeb\xbe\x30\x86\x02\x3f\x12\xf4\xde\xd3\xb1\x1a\xcf\x2a\x6d\x97\x3d\xdd\x8e\xb2\x7b\x07\xc5\x80\xbf\x44\x8c\xaa\x5a\x2e\xa1\x16\xc5\xea\xf3\x6f\x7a\x6b\x17\xa8\x5b\x39\x55\xdc\x8a\x44\xa6\x20\xd8"}, -{{0x2d,0xdd,0x79,0xe7,0x60,0x64,0xc2,0xe6,0xb3,0x22,0xaf,0xb0,0xc5,0xc6,0x85,0xcd,0xbe,0xc6,0x28,0x21,0xcd,0xfc,0x0c,0xb1,0x4d,0xb7,0xd0,0x1b,0xa3,0xbf,0x21,0xa5,},{0xf5,0x5b,0x4a,0xb6,0x4a,0x25,0x82,0x21,0x2b,0x96,0xcc,0xac,0x06,0x40,0xe2,0x71,0x94,0x4a,0x34,0xa2,0x86,0xd0,0x35,0x83,0x30,0x45,0x81,0x0e,0x34,0x18,0x24,0xbb,},{0xa4,0xc3,0x96,0xe1,0x9d,0xd4,0x2e,0x03,0x91,0x84,0xcd,0x25,0x11,0x88,0xff,0xa2,0x45,0xf0,0x36,0x7c,0x69,0xc0,0x2d,0x12,0x47,0x4e,0x5c,0xa9,0xe5,0xc7,0x68,0xa7,0xee,0x3a,0x3d,0x47,0xeb,0x22,0xd1,0xac,0x9e,0x04,0xb7,0x04,0xa7,0x4f,0x41,0x69,0x47,0xf3,0xf4,0x9a,0x32,0x42,0x59,0x4e,0x7b,0x63,0x90,0xe8,0x2b,0x60,0xd5,0x05,},"\xa5\x66\x74\xa1\xe1\xf0\x97\x95\x25\x1a\xbe\x54\xab\x43\xc2\x98\x20\x8f\xef\xc9\xbb\x91\x76\xfd\xb2\x3e\x1e\x9f\x60\xf0\x32\x64\x79\x15\x56\x7e\xbd\xcc\x2b\x86\x9e\xdb\x70\x55\xf4\xab\xa6\x7e\xcf\xe7\xfa\x19\xed\xa4\x5c\x06\x04\x7c\x7a\x51\x84\x8b\xe9\x97\x32\x51\xf8\x5f\xf7\x6f\x1c\x59\xe3\x65\x43\x82\x85\x8c\x9b\xe1\x23\xdb\x8a\x94\x90\xc6\xc9\xb3\x09\xb8\x2d\x1e\x2c\xa6\xf4\xa0\x7d\x00\x12\x02\x83\xc6\xc2\x95\x64\x49\x95\xa9\x66\x28\x61\x2b\x8d\x67\x91\x57\x35\x18\xe2\x55\x6a\x68\x8a\x09\xf1\x49\xbc\x84\x6a\x68\xbd\x0e\xf7\x92\x79\x03\x57\x10\x03\x1e\xf0\xa8\xfe\xd1\xdd\x0b\xf0\x26\x12\x5d\xc6\x64\x8f\x86\xf6\x43\x09\x94\x2e\x18\xf2\x3b\x12\xd1\xdc\x68\xc6\xf2\x77\x0c\xa8\xb5\x48\x5b\x36\x9b\x0c\x92\x00\x7a\x94\x61\xc1\x39\xfc\xbb\x41\x17\x5f\x31\x6d\x44\x67\x06\x0a\xb4\x3d\x12\x22\xf5\x80\x24\x04\xbf\x63\xc2\xdf\x7e\x00\x4b\xdc\x40\x0c\xa8\x0f\xe0\xd2\xcb\x68\xa2\x10\xfb\xc3\xfc\x0b\x90\x32\x09\xd5\x47\x6e\x7a\x56\xba\xef\xb8\xfa\xd7\xf3\x28\xb7\x2f\x32\x71\x13\xe1\x39\x41\x4b\xa6\xf3\x4e\x99\xc2\xec\xcd\xe0\x44\xe7\xa3\xac\x70\xc5\x80\xcd\x26\xc7\x45\x01\x92\xca\x4c\x82\x3c\x7a\xc5\xea\xe8\x76\xc0\xd1\xc8\xc7\x68\xc1\xcb\x0b\x7e\xa4\x1f\xc9\xb7\xd2\x94\x37\xbb\xad\xab\x18\xe0\xf5\xed\x1d\xef\xe0\xcf\x6c\x0e\xba\xa6\xb6\xd7\x77\xf4\xda\xd9\xab\xdd\xbf\xc0\xfd\x6a\xb5\xee\xea\x80\x3c\xfa\x01\xc0\xbd\x46\xf6\x5f\xef\xa4\x69\x01\xab\xbe\x0d\x89\x10\x4e\x3b\xc4\xae\xe1\xf0\x59\x9c\x69\xb6\x7b\xa5\x45\xab\x9b\x54\xf5\xde\xe3\x40\xac\x69\xd8\x82\x99\xe8\x68\x22\xac\xdd\xdd\xce\x60\x11\x22\x01\x2f\x99\x29\x97\x74\xaa\xf1\x7c\x96\x4e\xde\xcb\x95\xe1\x27\x7d\x46\x2d\xe6\x4e\x91\x15\xa6\x1a\xd9\x8a\xa3\xd2\x2e\x3b\xa6\xf8\xf1\xcd\x69\xb6\xb5\x2b\x83\x38\x28\x23\xf3\x0e\x96\x6b\xda\xd1\xff\x5f\xc1\x98\xae\x32\xe9\xb6\x80\x55\xd4\x39\x2b\xc7\xc3\xdf\x10\x15\xf1\x28\xae\xe1\xe4\xfa\x3d\x49\x99\xe3\x29\xf2\x2f\x0f\xf6\xaa\x77\x8b\xae\x02\x94\xa1\xdf\x74\x36\xcb\x16\xa2\xbf\xcd\x74\xb4\x63\xab\xe7\xcb\x4b\xac\x53\x62\xc8\x9c\x9d\x1a\x37\x8a\x2c\xb8\x85\xcc\x3b\x26\xab\x4b\xe8\x81\xef\x1a\xfc\x14\x43\x0e\x10\xd2\x65\x39\xca\x35\x8c\x36\x76\x28\x6a\xd8\x1c\xe1\xc9\xe7\x85\x92\xaf\x66\xf1\x82\xbb\x1f\x7f\x86\x2f\xe7\x55\xbf\xfb\x5b\xe5\xc5\xf2\xb7\x31\xc1\x32\xe2\x38\x8a\x76\xa1\xa7\xb1\xcd\xdf\x05\xae\xd2\xac\x9e\xc4\x08\x47\x52\x71\x94\x2c\xca\xdd\x32\xe4\x9d\x87\x91\xed\xf8\xb8\xde\x11\x75\x51\xce\x26\x4a\x60\xb8\x41\x05\xea\xe8\x7e\x66\xf6\xa4\x01\xd1\x32\x2b\xb2\x1a\x98\xe8\xac\xd2\x77\x49\x32\x54\xe5\x04\x00\x4f\x72\xc7\x6e\x79\x03\xd2\xfa\x38\xfa\xb7\x17\xe9\x4c\xe6\x27\x94\x7c\x4e\xa3\x26\xbd\x25\x75\xc3\x73\x10\xf3\xb4\xd8\x43\xb9\x0f\xa7\x7d\x32\xd9\x95\x21\x94\x15\x0b\x62\xf8\x50\x18\x7a\x4f\xdf\x38\x46\x6d\xfa\x06\x56\xc0\xa2\xe0\xb3\xf0\x74\x92\xac\x8e\x37\xe5\xd0\xdf\x95\xcc\x89\xdf\x30\x85\xa2\x69\x29\x1d\xc2\x51\x22\x10\xd3\xfe\x44\x24\x8d\x7a\xb9\x96\xbe\x09\x9a\xf6\x4c\x22\x75\x66\x66\xf8\xde\xa5\x6c\x00\xb9\x06\x77\xd1\x18\x25\x00\xdd\x27\x4f\xd0\x76\x92\x53\x82\x6d\x67\x7a\xb1\x6a\x55\x7b\x08\xb3\xc5\x22\x65\x49\x8d\x85\xc4\xcb\x2b\x60\x0e\xe0\x48\x1b\x7c\x1c\x47\x6a\x9d\xaa\x8b\x88\xc7\x1f\xc2\x1b\x6f\x89\xbf\xdf\xec\xe5\x8d\xa9\xe8\xd5\x65\x65\x2e\x43\x95\xbd\xf4\xc8\x11\xb4\xf4\xf2\x2d\x2b\x96\x13\x26\x1f\x88\xc6\x04\xc2\x97\x4d\x3e\x97\x7d\x14\x0d\x04\x6e\x1b\x66\x25\xb7\x07\x16\x40\xd3\x52\xcb\x7e\x7e\x65\xd4\x6c\x61\x34\x47\xbe\x8d\xc5\xa2\x00\xaa\x9a\xca\xb4\x6a\xfc\xcf\xeb\xb6\xb1\xc3\x19\x73\x24\x6c\x34\xfa\xaf\x8d\x26\xea\x5e\x83\xbe\x15\x71\x8f\x8f\xdb\x0c\xfc\x44\x4e\x2e\xb6\x0f\x36\x59\xb0\x20\x16\x1c\x22\x8e\x6b\x92\x40\xb7\xac\x39\x4c\xab\x81\x2d\xe1\x05\x15\x76\x6f\x22\x47\x3e\xcc\xa5\x35\x59\x4c\xe5\x28\xa5\x7c\xf5\xda\xb2\xeb\x32\xab\x84"}, -{{0x3a,0xbb,0xdb,0x0b,0xa1,0x1a,0xa1,0x06,0x3b,0xd2,0x6b,0x02,0xc1,0x16,0x03,0x78,0x62,0x28,0x5b,0xab,0xd2,0x15,0xd2,0x40,0xbc,0x9c,0x09,0x26,0xf4,0xec,0xea,0x81,},{0xb8,0xfc,0x59,0x43,0x8f,0x8c,0xe9,0xe3,0x78,0x5a,0x47,0x3b,0x22,0xc8,0x89,0x2c,0x51,0xea,0xc2,0x56,0x8c,0x68,0x1d,0xcc,0x77,0xb6,0xf0,0xe0,0x79,0x9c,0x4e,0x33,},{0x98,0x1f,0x20,0x05,0x5a,0x45,0x75,0x25,0xae,0xe5,0x61,0x62,0x64,0xe6,0xaf,0x42,0xe8,0xb3,0x87,0xcb,0x08,0xf8,0xb4,0xa7,0x3f,0x9b,0xe0,0xb3,0x66,0xf1,0x03,0x5b,0xb3,0x0a,0x1c,0x87,0x48,0x94,0xcb,0xec,0xe0,0xa8,0x46,0xd8,0x49,0xb7,0xec,0xc5,0x56,0x58,0x5d,0x0d,0x3d,0x39,0x56,0x45,0x80,0x7f,0xf2,0xa3,0xca,0x5a,0x59,0x0c,},"\xdc\xcd\x55\xf9\x22\xcd\x27\x4f\x69\x75\x00\x0a\xdc\x8d\x98\x63\x0c\x6d\x75\x2c\x12\x02\xa9\xdd\x12\x10\x48\xb9\x39\x45\xaf\x2b\x11\x10\x96\x77\x88\xf9\x9e\xc0\x28\xe3\xd3\xb4\xcf\x82\xfb\x07\x17\x3e\xa4\x40\x1e\x3b\xb4\xb0\x7b\x7b\x0b\x24\xb0\x59\xa7\x66\x33\x95\x32\xd9\xdf\x3e\x31\xb7\x2c\x95\x8c\x11\x9d\x8d\xfa\x15\xa5\x07\xaf\x6c\x5f\x7e\x78\xfe\x27\x0f\xa8\x1b\x9d\xf0\xf2\xe4\xaf\x24\xbd\x99\xfb\xeb\x14\xe0\x03\x30\x84\xd7\xfb\xf8\x4d\xde\xdf\xd5\xce\x56\x75\x1d\x15\x90\x84\x75\xdf\x8a\xf0\x13\xd0\x91\x17\x3c\x13\x86\xb9\x13\x94\x26\xcc\x60\x81\xea\x16\x5b\x8c\xe4\x81\x94\xb8\xe1\x8a\x9b\x91\xa4\x63\x13\x44\xfe\x29\xc8\xe7\x28\x18\xb7\x1f\xa1\x5c\x92\x92\xd1\x3f\xdf\x5f\x9d\x18\xe2\x9b\xd0\x29\x1b\x81\x38\xde\x73\x8f\xd3\xa3\x6c\x35\x23\x90\x22\x36\x8b\x45\x6f\x1f\xac\xba\x90\xa0\xd8\x0d\x6e\x31\x1c\x5f\x6c\x6f\x04\x67\x7e\x92\x37\x3a\x5f\xc4\x73\x88\x94\xdb\xed\x20\x6c\x30\xda\x34\x1b\x3b\x19\x6c\x94\x78\x58\xa6\xd2\xad\xc6\x8a\xac\x3f\x20\xcf\xdb\xe0\x49\x79\x61\xda\xe3\x34\x70\x26\x6d\x17\xec\x71\x9a\x59\xf0\x58\x6f\x82\xf9\x9f\x1c\x90\xed\x70\x05\xa2\x07\x21\x9a\x55\xed\xc7\x60\xf4\xeb\x8f\x24\x02\x64\x7f\x6f\x77\x97\x1f\xf7\xb6\x34\x35\x7b\x6b\x29\xbb\xd7\xea\x05\xe2\xe2\x58\x54\xe9\x9c\x62\x0f\x4b\x8b\x64\x73\x90\x22\xff\x0b\x33\x8a\xfe\xf3\x5f\xb6\xf4\x1a\x53\x62\x9a\x51\x8e\xb9\x3d\x66\x02\x0f\xb3\x53\xae\xf8\xdd\x07\x1e\x09\xc9\x16\xd4\x70\x4a\xcd\xf7\x76\xb3\x8c\xa9\xc5\x9f\x21\x1f\xf8\x8c\x43\x0a\x57\xe8\xf1\x71\x39\x23\xb3\xf3\x0c\xa8\x69\x70\xa1\x4a\x52\xdb\x4b\xcb\xe6\x0d\xf4\xbc\x3c\xfd\xf2\x54\xbf\x10\xf8\xaf\xae\x87\xbd\x61\xb3\x58\xf4\x3c\xc2\x96\xc0\x41\x29\x64\xc4\xe0\x0f\x71\x21\x33\x97\x46\x85\x17\xcb\x01\x37\x9c\xb7\x29\xc7\xb9\xe3\x5b\xd5\x0b\xdd\x98\xc3\xd3\xb7\x62\x97\xa1\x38\xb5\x7c\xeb\x6c\x77\x74\x2d\xf0\x88\x1d\x07\x66\x8c\x08\xa6\x30\xa4\x4e\x6e\xd7\xeb\x20\x6d\x6a\x56\x44\x07\x10\x43\x8a\x51\x11\x42\x4b\x61\xaa\xee\xce\x40\xe9\x00\xf5\xe3\xc4\x57\xe9\xd6\xe3\x1a\x79\xec\x5b\x4b\x42\xb6\x8e\x66\xe1\x99\x30\x92\x87\xca\xd6\x53\x36\xfc\x7f\xe4\x3f\x43\xcd\x8c\x77\x3d\x3c\x65\x80\xd7\x21\x7e\x2c\xab\xec\xd3\xea\xbc\x48\x5c\x4a\xcf\x47\x71\x8c\x39\xb0\x2c\x78\x58\xff\x34\x7c\xec\x75\x35\xed\xdc\xd4\xfc\x81\x5d\xf8\x14\x56\x9a\x88\xae\x70\xf2\x73\x3a\x65\x39\xf2\x08\xc7\x9c\xf4\xe7\xc4\xf9\xea\x24\x1a\x92\xe9\x51\x51\x71\x36\x14\x18\xa4\xc2\xe5\x3c\x07\x6a\xaa\xbc\x47\xe4\xc9\x71\xbd\x04\xb1\x00\xc2\x62\x82\x30\x88\x57\xe0\x6e\x7e\x5f\xbc\x43\x42\x56\x4f\xb3\xb1\xea\x4a\x17\xa9\x25\xe9\x1e\xe6\x91\x22\x32\x1d\x39\x2b\x24\x69\x65\xb8\x6b\x54\xfd\x5c\x83\xfa\x5c\x47\x41\x63\xf9\x8a\x9f\x44\x7d\x88\xcb\x59\xfe\x2c\xdf\x9f\x54\x12\xfc\xbe\xb3\xef\xfa\xc8\x97\x67\x91\xc6\xa4\x7b\x66\x9a\x2f\xc5\x5a\xbe\x8e\x09\xe7\x41\x57\xef\xcd\x1c\xa7\x8f\xc1\x0f\xa6\x87\x01\x0c\x68\x26\xc6\xe8\x96\xef\x5c\xd7\x1d\x0f\xe4\xd1\xbd\x07\xc1\x0d\xac\x3b\x03\x48\x5e\xdd\x25\x69\xa7\xee\xcf\xbc\x4e\x5d\x2e\xe2\x37\x98\x59\xe2\x65\x26\x7b\xed\xaa\xd6\x9d\x93\xb7\xc1\xbd\x18\xf2\x7e\xa4\x24\x83\xc7\xe4\x10\x0e\xe0\x5b\x28\x30\x39\xbf\xb9\x89\x1d\x37\xc4\x67\xed\x83\xb8\x8c\x79\x4e\xab\x6b\xab\x9d\xc6\x77\x89\x26\x50\xe2\xd8\x96\xfb\xfe\xc1\xb1\xcd\xb7\x21\xbe\x30\xb0\xb8\xe5\x35\x87\x09\xe1\x65\xcb\xe3\xa1\x82\xc9\x3b\xc0\xa0\xce\xa2\xf8\xcf\x3a\x62\x57\xad\xf7\x64\x53\x40\x41\x20\x22\x41\xa5\x27\x9b\x66\x8e\x40\x12\x5f\xc0\x94\x58\x5a\x3c\x58\x8a\xba\x82\xb6\x7c\xd9\x1d\x48\x3e\x54\x30\x04\x28\x42\x68\x63\xa4\x23\x64\x04\x9d\x7c\x45\xa1\x69\x38\x5a\xa8\x9b\xf3\x77\xf0\xd3\x2b\x07\x80\x9b\x58\x71\x39\x5e\xc0\x53\xa2\x57\xd9\x3e\x48\xbb\xf4\x07\xeb\x60\x91\x40\x1e\x25\x65\x46\xe3\x1f\x9f\xcd\x24\xd2\xc5\xb3\x33\xcf\x65\x78\x50\x02\xf0\x8d\x54\x8d\xb2\x6a\xd1\xf3"}, -{{0x8a,0x44,0xd6,0xaf,0xc6,0xc8,0xee,0xe1,0xbc,0x7d,0x5f,0x69,0xe4,0x95,0xb0,0xb1,0x8c,0xa7,0xae,0xe0,0x07,0xde,0xa7,0xcf,0x0d,0x17,0x14,0xd7,0x85,0xa9,0xf4,0xed,},{0xd4,0xf3,0x66,0xb3,0x37,0x7f,0xa3,0x9b,0x36,0xf9,0xae,0x14,0xda,0x40,0x4e,0x22,0x40,0x49,0x0d,0xbd,0x8d,0x79,0x6b,0x1a,0xb8,0x72,0xdf,0xcb,0x83,0xa5,0x95,0x40,},{0xe0,0x72,0x7e,0xb7,0x2e,0x84,0xd2,0xb8,0x2c,0xdb,0xd0,0xa6,0xbd,0x2f,0x49,0x49,0x63,0x16,0xaa,0xe8,0x35,0x1e,0x49,0x02,0xac,0xd5,0xe3,0xcc,0x57,0x34,0x6e,0x7e,0xba,0xfd,0xd9,0x2a,0x90,0xde,0xd7,0x6f,0xd0,0xc6,0x69,0x0d,0x68,0xbb,0x2f,0xed,0xd6,0x13,0xe4,0x4f,0xa2,0x22,0xbe,0x01,0x26,0xda,0x52,0x0a,0xcc,0x2c,0x41,0x05,},"\xde\x80\x32\x69\x66\x53\x6c\xe9\x49\x96\xaf\x2d\xe7\xa0\x76\x05\xcc\x4f\xcb\x9e\x75\xee\x0a\x67\xa1\xe2\x09\x32\x11\x1d\xe9\xb3\x56\xd5\xbe\xea\xe8\x6c\xc5\xf5\x64\xc1\x0d\x66\xe3\xde\x95\xa5\xb9\x9e\x84\x49\x28\xea\x8e\x77\x58\x6c\xf3\xc1\x0a\xd3\x63\x3d\xde\xeb\x1d\x9d\xcf\x3f\x94\xb7\x0b\xf1\xef\x63\xd2\x38\xdf\x20\x4d\x70\x5c\x0b\x17\x4f\x83\x28\x25\x45\xf5\xe4\x07\x5f\x8d\x69\xa4\x81\x79\xc2\x9e\xab\xf5\xc1\x74\x2e\xf3\x9e\x1a\xd9\x63\xbe\xbb\xb6\x6f\xce\x94\x91\xa9\x84\x65\x12\x15\xc2\xe7\x50\xe6\xee\x83\x65\x76\x64\x40\xa8\x44\x19\xe5\x2d\xcf\x67\x1f\x1c\x52\xea\xa2\xb9\x90\x2b\xcc\xa4\xb3\x7c\xff\xdb\xac\x8e\x7e\x7e\x6b\x0a\x5c\x87\x48\xef\xbf\x45\x2d\xf6\x16\x3f\x4c\xa0\x7b\x61\xf9\xa0\x5e\xc2\x0a\x2b\xd6\x33\x38\x9e\x67\x0b\xb5\x45\x4a\xcd\x6f\x3a\x06\x33\x5b\x5d\xa9\xec\x32\x62\x64\xe9\x62\xc7\xd9\xd0\x6c\xe7\xe9\xff\x04\xa0\xa5\xbb\xdf\xaa\x4c\x41\x08\x66\xa5\x72\x01\x16\x51\x43\x9f\x2d\xbc\xe5\xde\xe6\x67\x92\x4a\xc4\x93\x4d\x20\x54\x96\xbd\x1d\x4d\xf0\x8b\xd0\xcb\x3f\xd2\xde\x73\xa2\xef\x34\x2f\xf0\x09\x1e\x10\xe1\x5b\x3b\x76\x0a\x57\x5d\xf9\x3c\xf1\xc9\x7c\x01\xc5\xab\x11\xc0\x94\xbf\x34\x87\x82\x06\x71\x8f\x6b\x28\x5a\xa5\xcc\x51\x27\xbd\x7f\x98\x8b\x84\xa9\x04\x95\x30\x6f\xd9\xe9\x9d\x89\x55\xe6\x68\xd1\xa3\xff\x10\xf6\x5b\x7c\x47\x9f\xac\x24\x11\x9a\x3c\x10\x12\x2d\x4d\x18\xa8\x05\xb2\x47\xdf\x16\x8c\x0a\x51\x00\x16\x9b\x55\x72\xd1\x70\x12\xd7\x51\xa4\x2e\x83\x37\x61\x15\xe1\x15\x61\xc1\x60\xc1\x5e\xfa\xd7\x6d\x21\xf7\xab\xb4\x30\x36\x64\x75\x23\x86\x31\xf8\x4c\x88\xf8\x38\xb0\xac\x40\x4c\x91\x3d\x2f\xa1\x24\x50\x23\x84\x85\xc3\x02\xfc\x20\x1f\x44\x15\x1c\x19\xbc\xbd\xc1\x19\x0c\x12\xd1\x54\x08\x31\xfb\x19\x58\x1c\xb9\x31\x72\xb0\xd2\xff\x5c\x65\xf3\x1c\xaf\xf2\x0f\x81\x38\x81\xf8\x4e\x5e\xf9\xd5\xc1\x65\xe0\x96\xd2\x54\xca\xdf\x89\x52\x49\xaa\xb8\xd4\x49\x6c\x94\x0a\x40\xf9\x07\xbd\x40\x93\x5a\x94\xf5\xe5\x5b\x6d\xd0\x51\x15\x41\x00\xfe\x33\x17\x70\xef\xf2\xba\xd6\x54\x56\x19\xb8\xa3\x3e\xf6\x46\x2a\x50\xc0\xb2\xc4\xed\x2f\xba\x4e\x4e\x38\x3e\xbf\x29\x32\xe6\x19\x27\x66\xa4\xaa\xd1\xd6\xe2\xb6\x92\xd9\xf2\xbd\xc2\x33\x93\xe8\xaa\xcf\xba\x32\x3b\x53\x4f\x84\xed\xf2\xdc\xed\x7c\x94\xd5\x16\x87\xda\xa2\x71\x98\xa9\x14\x4b\x31\x2b\x71\x6f\xe1\x70\x14\xa7\xbe\xd0\xc1\x4a\x24\x38\x73\x3d\x55\x5c\x65\x64\xc8\xc1\xa3\xd9\x97\xeb\xae\x7b\x3d\xe8\x87\x7a\xf5\x3c\x1d\x1a\x50\x29\x15\x8a\x80\xaa\x0c\x87\x48\x9f\xef\x27\x0c\xdf\xfe\x10\xd3\x4b\x15\xc1\xa9\x69\x3a\xe0\x39\x02\x43\xe3\x14\xcf\xac\x06\xef\x6e\xef\xeb\xcc\xf4\x3d\x42\xea\xc2\x4c\xe9\x87\x94\x29\xd2\xfc\x72\x53\xb3\xed\x17\x58\x25\xbc\x4d\xa0\x76\x2b\x49\x33\xa9\x8a\xfd\xb9\x4b\x06\xf4\xfc\xd2\xad\x36\x11\xaa\x99\x9d\x7c\x1c\x8d\x85\x2d\x01\xdd\x9e\x52\x64\x84\x55\xa0\x4e\xb2\x33\x0a\x76\xfd\x94\x2c\x53\x1e\x51\x4b\x5e\xc0\x72\x8a\x89\xd3\x4c\xa5\x90\xea\x99\xc8\x8f\xaa\x20\xdf\xb7\xbb\xf6\x56\x54\xaa\x6c\x21\x2b\xeb\x8a\xd6\xbf\x7c\x77\x73\x91\xcd\x49\xc3\x9c\xf8\xab\x51\xb9\x5b\x41\x9e\x3d\xfc\x8d\x94\xa9\x3a\x1e\xf0\x22\x3c\x6d\xe9\x0b\xf9\x62\x18\xd8\x04\x5b\xd4\x95\x2a\x0d\x83\x72\xa5\x57\x8c\x6a\xaf\xa7\x4b\xa6\x62\xe3\x18\x8e\x6a\x6e\x56\x7e\x4d\x2f\xe8\x22\x7d\x07\x43\x98\x2a\x41\xeb\xfa\x0d\x31\x0f\xe7\x9f\xed\x27\x04\x17\x90\xef\xd5\xaf\xac\x22\x43\xe1\xd1\x50\xb1\x45\x01\x5d\x9d\xea\xb0\xed\xed\x63\x94\xac\x36\xfc\x5f\xb2\x01\xf5\x20\x4f\xbd\x42\x2a\x36\x04\x23\x30\x15\xbb\x0a\x48\xa9\x20\xe2\xe5\xe0\xd4\xde\xed\x67\x20\x25\xf2\x3c\xfb\xa9\x38\x89\x59\x7e\x50\x4c\x88\x87\xad\xd4\x6c\xfe\xf4\x02\x4a\xfb\x8a\x26\xee\xb7\xdc\xdd\xb2\x39\x7b\x44\xa1\x79\x63\x67\x34\x00\x42\x13\x70\x28\xc3\x30\x76\x26\x81\x6c\x29\x31\xe6\x1e\xbb\x6b\x69\xed\xcb\xcb\x61\x2c\x9b\x18\x1a\x28\x53\x01\xce\x46\xf8\x2f"}, -{{0x8a,0x97,0x2d,0xd0,0xf1,0x19,0x0c,0x2b,0x9d,0x54,0x8f,0x4b,0xa5,0x82,0x64,0xbb,0x04,0x82,0x67,0x75,0x50,0x2a,0x8d,0x5c,0x2b,0x20,0x9e,0xe8,0x8d,0xce,0xa5,0xfb,},{0x6d,0x80,0x37,0x5f,0x3c,0xf1,0xaa,0xb2,0x83,0x55,0x1d,0xf4,0x45,0xd1,0x7e,0x7d,0x3b,0xaf,0x9b,0xcb,0xec,0xbb,0xb2,0x67,0x05,0x2e,0x02,0xfd,0xb6,0x91,0x44,0xd3,},{0xbd,0x45,0xb3,0xc0,0x45,0x85,0x0e,0xbe,0xf7,0xb8,0x0d,0xd1,0xde,0xab,0x48,0x03,0x7b,0x13,0x46,0xc7,0x1d,0xea,0xf1,0xe5,0x8f,0x2a,0x7b,0x16,0x26,0x74,0xf9,0x4d,0x1e,0xf3,0xd4,0x23,0x90,0x37,0x33,0x0b,0xd6,0x33,0x5f,0xe4,0xf0,0x14,0x92,0x50,0x90,0x1f,0x00,0xa8,0xe4,0x6b,0xe5,0xfa,0x0a,0xae,0xc6,0x9d,0xe0,0x6d,0x73,0x04,},"\x30\xb2\x89\x48\x93\x9a\xa2\x63\x43\x7e\x45\xc5\xc0\x25\x4f\xb2\x0e\x61\x7e\xd0\xf3\xfa\x7d\xac\xe5\xa0\xa8\xe0\xfe\x3c\x1f\xc4\xad\xb2\x80\x9b\x61\xc5\xe8\xd9\x2c\xd2\xf3\xde\x93\xb1\x73\xbe\x70\x7b\xad\xa9\x42\x40\xc6\x26\x2c\x16\x0e\x8c\x78\x21\x65\xbe\xef\x99\xd0\xbe\x8e\xcd\xad\x63\x16\xdc\xd7\x34\xbb\xb9\x0a\x66\xcb\xd5\xb1\xcb\x4f\xd8\xf2\x22\x6c\xea\x94\x8e\x4d\xf7\x6b\xbe\x25\x1d\x47\x8f\x5c\x3f\xe0\xd6\xde\x4b\xe5\x4f\x67\xf5\x02\xb2\x80\x4f\x62\x8b\x79\xa5\x50\xfb\x1a\xc4\x83\xad\x2b\xa1\x66\x37\xc4\xbc\x9d\xa6\x7f\xb4\xf9\x86\x59\xc4\xc4\x39\x4d\x16\xb6\xd1\x4b\x3e\x0b\x0c\x1e\x62\x5d\x71\x0d\xcc\x1c\x11\xdf\x5d\x34\x14\x7b\x1e\xc5\xa4\x17\xb9\xe2\x1f\x90\x8c\xfc\x52\x3d\x43\xe3\xf1\x81\xc7\x20\x9c\xc5\x6b\xdb\x5a\x21\x62\x86\x95\xed\x32\x0f\x8d\x4c\x07\xfd\x6d\x84\xaa\x03\x42\x6f\x21\x64\x4a\xae\xfe\xee\xc3\x11\xc7\x4e\x94\x99\x93\x60\x47\x35\x0a\x9b\xf5\xb7\x03\x96\x2e\x77\xce\x55\x13\x36\x83\x5f\xc3\x2c\xcb\xd2\xc9\x0a\xe5\x2e\x24\xd4\x7d\x8d\xcb\x98\x7a\xbd\x12\x1d\x3f\x74\x6b\x5d\xe2\x30\xf2\x64\x69\x60\x3f\xb0\xc4\xa8\xf6\xcd\x79\x73\xd7\xda\x88\x2e\xd1\xd6\xe4\xd9\xc5\xa4\x6e\xc2\xc2\x19\x40\xad\x33\x89\xa1\x86\x01\x4e\xe9\x72\x78\xe5\x35\x09\x88\xb1\x5e\xcd\x9e\xa7\x45\x6b\x3c\xb5\x5e\x4d\x30\x93\xf1\x3a\x87\x5b\x50\xd6\x51\x63\x78\xec\xaf\x58\xd7\x52\xc6\x37\x4e\xd1\x56\x38\x40\x93\x11\xfc\xd3\x79\xd1\x22\xc8\xd8\xc5\x9b\x86\xf4\xe8\xdc\x46\xad\xb7\x30\xa9\x33\x84\x6e\x0b\xd2\x48\xd3\x60\x82\x52\xd9\x70\xb5\x04\xc8\x13\xc6\xde\xa9\xfc\x88\xa3\xde\x64\x19\x56\xdc\xa2\x91\x20\x4d\x39\x0b\x6b\x39\x98\x1f\x8c\x0a\x6b\xcf\xc3\x1c\xa0\x74\x44\x20\x66\x2a\x9b\x35\xeb\x3f\xc2\x11\xf8\x10\xa3\xe8\x06\x25\x00\xb1\xe4\x9b\xdf\x85\x76\x65\xff\x32\xa9\xba\x76\x19\x4b\xbb\x77\xfb\x9c\x15\x41\x29\x64\x24\x4b\x98\x65\xf7\x3d\xed\x9f\x25\xb4\x9b\x42\x5a\xa2\x53\xd8\x07\xd9\x81\x82\x92\x76\x3a\x51\x3e\xc8\x07\x47\x34\x4f\xba\x0a\xcf\xe5\x93\xcc\x26\xb1\x33\x0b\xb9\xad\xe6\x6c\x4e\x88\xcf\x1b\xae\xd6\xd6\xe7\xb7\x50\xe6\xc7\x23\x9d\x7b\xcb\xfa\x3f\xbe\x45\x40\x5a\x63\xb9\x6d\x50\x34\xcc\x0c\x07\xff\xc3\xb5\x08\x58\x08\x1d\x19\x55\xe2\xd2\xfe\x5b\xe5\xfd\xa7\xa8\x99\x69\x43\x76\x8b\x05\x51\x70\xb7\xfd\x52\xf0\xa3\x20\x97\xfe\x1b\x7a\x94\xf1\xbf\x87\x9a\x0c\xba\xbe\x10\xac\x9a\x7c\xc1\xf9\xf5\x50\x68\xc4\x8e\x3c\xcc\x06\x51\x36\x43\x10\x18\xd3\x8d\x20\x10\x9d\xc9\x5d\x99\xcc\x2b\xbe\x7c\x62\x7a\xb1\xa8\xaa\x5f\x43\x16\x13\xb7\x90\xc2\xe6\x52\x6c\xf0\x4f\xdc\x9e\x55\xf5\x1c\x05\x5f\x3c\x20\x45\xa6\x75\xe3\xa1\xe5\x4b\xa4\x09\xf7\xae\xfa\x7e\x4a\xa0\x7a\x2b\xbd\x5e\x4a\xb1\x63\x21\xa9\xf0\x99\x69\x43\x91\xfd\xa6\x8a\x74\x58\x1e\x2f\x1f\x11\xdd\x9a\x6d\x52\x4b\x1b\x83\x26\x0d\xb5\x7b\x72\xef\x29\xc2\x8c\x8d\xb5\xc3\x7f\xd1\x85\xb7\xc2\xd8\x45\x50\x90\x65\x3a\xf3\x32\xdb\xc8\x2b\xfb\x0d\xb5\xdc\xca\xbf\xb6\xb2\x8c\xaa\x35\x05\x25\xcb\x54\xcc\x84\xe5\x53\xe1\xcf\x39\x54\xb6\x12\x39\x3e\x79\x93\xff\x7e\x8b\xf5\xec\xe3\xf1\x45\x09\x4d\xd7\xa2\x7c\xb4\x7f\x22\x74\x76\xf2\x89\x23\x52\x51\xf7\x72\xb3\xba\x77\x6b\xb7\x73\xaf\x0c\xc5\xf7\x86\xa3\xfb\x9e\x93\x1a\x53\x0c\xfb\xd8\x91\xcb\x5a\x5d\xfe\x25\x16\x9e\xf9\x33\xcc\x82\xc9\x08\x0f\x32\x39\x61\xa1\x20\x15\x8e\x4b\xbd\x71\x13\x4e\xf1\xf9\x01\x08\xb8\x15\xc2\x89\xd4\xe9\xa9\x58\x9e\xc6\x4c\x05\xfb\xb4\x2a\x21\xb2\x3d\x16\xe2\xa6\x46\x78\xae\xcf\xab\x65\xcd\x9a\x80\x6c\x59\x81\x03\xd4\x1f\x70\x09\x77\x63\x17\x83\x1f\xed\xdd\x1c\x90\x02\xd4\xa9\x22\x04\xf9\x7b\xa9\x49\x0c\x61\x46\x98\x03\x07\x21\x02\x52\x4b\x9d\xf5\x19\x00\x5f\x98\xaf\x54\xd6\x0c\xa5\xba\x60\xb5\x5b\x09\x6a\x4a\xc2\xb1\x6e\xb9\xcc\x81\x97\x3c\x31\x35\xd3\xfb\x68\x73\xdd\x96\x53\x80\x0a\x22\xbb\x5d\x0d\x61\x17\xca\x5d\x91\x65\x53\xbe\x39\xc9\xa3\xb5\x11\xeb\x3d\xb7\x30"}, -{{0x12,0x38,0x0c,0x45,0xa7,0x9a,0xde,0x0f,0x48,0x3c,0x88,0x1a,0xaa,0x37,0x30,0x43,0x8b,0x08,0x35,0x90,0xf4,0x04,0xdc,0x9e,0x60,0x1f,0x76,0x15,0xf3,0x75,0xa6,0x28,},{0xd6,0x6f,0xc5,0x9a,0xe9,0x17,0xf7,0x6d,0x24,0xce,0x8a,0xb8,0xee,0x03,0xfb,0xcb,0x71,0x5d,0x5e,0xea,0x4b,0x08,0x39,0x2b,0x59,0x1e,0x64,0x85,0x91,0xc7,0x3c,0x89,},{0x02,0xb2,0x51,0x74,0xa3,0xdd,0x52,0x19,0xed,0x48,0xb2,0xc9,0x4c,0xa2,0x12,0xb6,0x3a,0x6a,0x3a,0x25,0x97,0x70,0x3c,0x07,0xb7,0xf0,0xc9,0x65,0xc3,0xc6,0xac,0x2e,0xb4,0x50,0xef,0xe3,0x87,0x16,0xa2,0xa2,0x8b,0x3f,0x89,0x84,0x6b,0x06,0xeb,0xdc,0xa4,0xbd,0x09,0xaa,0x58,0x1f,0x24,0xe8,0x4d,0x80,0xfc,0x10,0xac,0x1a,0x00,0x0a,},"\x68\x45\x23\xc2\xe7\xfa\x8b\x4b\xd7\x54\x8c\x4b\xac\xaa\x86\x78\xa3\x30\xdb\xbb\x96\x06\x32\x94\x01\x66\xb2\xcc\x9a\xfc\x15\x35\xc8\x0c\x11\x2c\x8d\xc4\xad\xa7\x62\x92\x33\xfe\x90\x90\x55\x23\x7d\x51\x3e\x29\x2a\xf1\x5a\xd7\x69\x2f\x11\x5a\xa0\x92\xda\x65\x75\x32\xf5\x18\x99\xc3\xf7\xf5\xd9\xd4\x07\xed\x5c\x16\x3e\xb3\x95\x04\x80\xa4\x12\x2a\x09\x92\x98\x1f\x07\x7b\xc8\x67\xf9\x06\x07\x54\x07\xba\x98\x49\xc4\xea\x04\x73\xce\x54\x0a\x79\x67\x44\xef\xa3\x86\x03\x78\xe1\xb8\x93\x43\xe5\x83\xd0\x80\x7e\x5a\x67\xc4\xd5\xbd\x7c\xe6\x41\x29\xfe\x90\x2b\x8c\xfa\xbd\x2c\x21\xfa\x3d\x2a\x10\xe9\xbf\x9e\xa5\xe5\x47\x3a\xe2\x50\xc9\x16\x05\x09\x97\x26\x78\xf9\xa7\x40\xe6\xca\xdb\x3b\x52\xf5\x02\xfa\x61\x6c\xff\xae\x1d\xef\x89\x3d\x54\xe4\x1e\x54\xd3\x26\x46\x4c\x9f\x43\x5c\x63\x50\x5f\xb1\x5e\x3e\xea\xf5\x02\x1c\x65\xdc\xd0\x10\xf8\x40\xaa\xb3\x17\xc8\x60\x5d\xfb\x1a\x0c\x8a\x3d\x55\x49\x86\x1b\x69\xaf\x2c\x93\xd8\x6c\x98\x1d\xf3\xa5\x1c\x5b\xf5\x78\x5c\x2f\x85\x26\x10\xe4\x4f\xa4\xff\x1c\x71\x61\x15\x2e\x56\x18\x38\x47\x44\xfe\x83\xba\xbf\x0b\xcb\x75\x61\x78\x9a\x02\x31\x25\xf6\x24\x2a\x18\x3c\xac\x95\x49\xc9\x32\x73\x3a\x86\x8a\xa1\x82\x65\x6e\x2b\xa0\xa8\xc0\xbe\x10\x69\x96\xa8\x5c\xeb\xf1\xbd\xad\x12\x3b\x98\x2b\x4e\x05\x55\x10\x87\x94\x82\x02\x1d\xae\xa9\xd8\xf2\x6c\x58\x8e\x6c\xd1\x01\x26\xcb\x31\x96\x88\x03\x56\xbe\xe8\xf2\x98\xbc\xa3\x06\xec\x56\x99\xc7\x57\x6b\x76\x50\x87\xc2\x53\xa6\x02\x14\x01\x0c\x6e\xd7\x0d\x87\x1c\xfc\x87\x38\x01\x8a\x0e\xdb\x57\xf1\x06\xb4\x21\x8d\x85\x5e\xab\x2c\x91\xf3\x9f\x85\x8b\x3f\x25\x90\x56\x31\xa0\xee\xe2\x98\x56\xfd\x34\xf7\xb8\xc9\xba\x51\xc1\xc4\xc6\xa7\x35\xd6\xc7\xa1\x3d\x22\x0d\x7a\x56\x6c\x3f\x50\x6c\x72\xbc\x74\x17\xab\x37\xf0\xd6\xd7\x96\xff\xc7\x1d\xf9\xdc\x7c\x6e\x13\x7d\xa5\x6b\x7a\x3e\x10\xcf\x0b\x1a\xbb\x3f\xfb\x70\xbc\x66\x29\x3b\x5d\x75\xb4\x05\xed\x8b\xec\x0d\x6f\xcd\x06\x92\x5c\x38\x11\x68\xac\x18\x8d\x0b\x8a\x1a\xf0\x83\x9f\x5b\xde\x84\x3b\x69\x91\xe5\xa5\xd6\xcd\x66\xfe\x6b\x0f\xde\x86\x7c\x08\x6e\xd4\x38\x76\x91\x9a\x1b\x72\x33\xd8\xd7\xe1\xd2\x74\x2f\x61\xc7\x7d\x8e\x59\x91\x68\x9c\x83\x28\x67\x66\x55\xb7\x6a\x37\x50\x56\x0e\x75\xd1\xc7\xe8\x5e\x3c\x00\x85\x05\x93\x31\x09\x4b\xba\x57\x10\x03\x2c\xf6\x79\xa5\x25\xc7\x8b\x31\x70\x0e\x6d\x91\xf7\x52\x94\xc4\x22\x48\x92\x97\xe1\x73\x59\x43\xe4\x17\xfc\xd3\x55\x80\x58\x2f\xdd\x02\x39\xb5\x11\x46\x53\x0c\xc0\x9d\x83\xb2\x8f\x0a\x1d\x64\x22\x20\xdf\xb9\x9b\xad\x62\xf3\x95\x41\x03\x50\x81\xd6\x5d\x77\x8d\xdf\x32\x39\xba\x0e\x6f\xa9\x91\x4b\x17\xb3\x97\xa5\x34\xcb\x8f\xd3\xb4\xff\x42\xa8\xd8\xc8\xee\x66\x15\x3f\xbb\x1f\xf0\xfa\x54\xf7\xbd\x03\x27\x85\x16\xe6\x34\x1a\xf8\x0f\xcd\x1f\xce\xe7\x0c\x35\x9d\x20\x53\x68\xac\x49\x0d\x75\xa3\x54\x51\x2d\xa4\x6b\xa7\x63\x4c\x15\xb2\x84\xb2\x44\x77\x80\x8f\x17\x63\x33\x60\xa4\xb4\x9f\xb3\xbc\xaa\x84\x18\x41\xcf\x92\x41\x7e\xb2\x4c\xe4\x82\xd5\xa2\x4b\xfd\x2d\xac\x37\x22\x31\xda\x53\x9a\x05\x42\x00\x02\xff\x7a\x20\xc4\x76\x09\x7d\xa0\x6f\x59\xf0\x33\x14\xe6\x05\x9f\xad\x88\xc5\x0c\x3b\xaa\xc0\x3c\xef\xa7\xcd\x82\x11\xd2\x46\x1b\x16\x60\xea\x6b\xcf\x47\x68\x38\xc9\x1a\x10\x07\x4e\xb4\xb4\x0e\x6e\x97\x4a\x94\x5a\x67\xf6\xee\x69\x04\x23\x1e\xf0\x41\x88\xf1\xea\xd5\xba\xf3\x56\x94\xef\xe3\x01\xed\xc7\xe8\x66\xda\x23\xb5\xa6\xc5\x8f\x01\xb2\xa5\x2c\xf3\xab\x80\x5e\xdc\x5c\x13\x68\x62\x6b\x95\xb9\x4e\xb4\x64\x5b\x69\x3e\xc8\x80\xf2\xb8\x11\x7a\x69\x3a\xfb\xdc\xd2\x48\x24\x31\x89\x0f\x41\x0b\xc5\x80\x53\x0f\xef\x37\x58\x79\xc2\xe4\x60\x49\xca\x89\x1a\x2c\x3e\xcd\x60\x43\xae\x80\xd8\xaf\x34\x66\x34\x67\x4c\x6d\xfe\x90\x59\x97\xde\x5d\x05\xd6\x20\x09\xee\xed\x27\x75\x02\xfb\x5a\x5a\x31\x55\xee\xee\xb6\x73\x48\xb6\x0d\x89\xa3\x4a\x78\x12\x63\x9f\x54\x1f\xfe"}, -{{0xd1,0xb3,0x43,0x0d,0x4e,0x63,0xaa,0xbf,0xa9,0xef,0x96,0xbc,0xba,0xf1,0xfa,0x6a,0x9e,0xb5,0x21,0x9d,0xd4,0x4d,0xf3,0xb1,0xa6,0x15,0x63,0xdf,0xfe,0x1c,0xcb,0x28,},{0xc2,0x8a,0x05,0x19,0x52,0x45,0x29,0x0e,0xcd,0x38,0x53,0x55,0x85,0xce,0x51,0xf3,0xc2,0x35,0xc5,0xd6,0x50,0xc8,0xc5,0x7c,0x2f,0x79,0xbb,0x0a,0xc0,0xe8,0x08,0x34,},{0x4c,0xb6,0xff,0x5d,0xd7,0x06,0xb1,0xae,0x81,0x6c,0xdb,0xaf,0x9e,0x9e,0x1e,0xdc,0x80,0xa6,0x62,0x84,0xf9,0x46,0x52,0xd5,0x0e,0xc1,0x4e,0x28,0x3b,0x2a,0xdc,0x59,0x2f,0xd0,0x84,0x33,0x71,0x44,0xff,0xa7,0x12,0xdc,0x34,0xce,0x8e,0x61,0x06,0x68,0xa6,0x5e,0x96,0x9f,0x05,0xce,0xb5,0x47,0x86,0x30,0x4d,0x0d,0x58,0xd3,0x1a,0x08,},"\x07\x6c\x0c\x87\x62\xe4\xbc\x00\x3c\x36\x0a\x12\xa1\x95\x98\x05\x05\x51\xd1\x6b\x4b\x8d\xa0\xfb\x9c\x4a\xfc\xc8\x1a\xdb\xe6\x19\x95\xf2\x5c\xbc\x28\xdc\xa4\x20\xbf\xa9\x46\x10\x54\xd3\xee\x00\xad\x78\x18\x3e\x7f\x26\xdf\x68\x98\xaf\x9a\x4d\x22\x5f\xca\xb6\x7c\x04\x2e\x9a\x13\x52\x5d\x1f\x75\xff\x0e\x3d\x8d\xa8\x08\x96\xb7\x28\xf3\xe2\xdb\x65\x94\x4a\xe0\x71\x7d\x77\x59\x90\xb5\x9e\x5b\x70\x43\x4b\xd4\xb3\xee\x45\x2f\x10\xac\x06\x10\x57\x0b\x38\x22\x08\x32\x96\x8f\x54\x4d\x3e\x4d\x11\x9b\x1d\x4b\x50\x15\xc6\xcd\xf4\xcf\x22\x0b\x56\xb5\xc0\xcc\xd8\xe3\x98\xd5\xe4\xa5\x8d\xa3\xb0\xe2\xb2\x70\xa5\xd3\x9b\x82\xab\xb7\xf9\xd2\x7a\x41\x90\x18\x55\x0b\x62\x00\xae\x51\xc8\x48\x82\xf0\x86\xae\x7e\xa5\x35\x16\x71\xb6\xdd\x96\x09\x23\xad\x6b\xef\xc1\x34\x09\x87\x9a\x8d\xf6\x19\xbd\xf6\xc8\x8a\x6f\xe1\xec\xc0\xf0\xf3\xaa\x21\x9f\xb6\x19\x02\xbe\x48\xa5\x3d\xf2\xbc\x66\xc5\x6f\x1c\x1d\x17\xf7\xe6\x16\x7d\x25\x51\x65\xf1\x74\xba\xa9\xca\xf5\x3c\x73\xcb\xbb\x7c\xc2\xc7\xc0\x87\xf4\x3a\xbe\x2a\xed\x5a\x21\xfe\x42\x90\xb8\xd6\x79\x60\xa8\xa9\xcb\xc2\xa5\x7a\xbe\x22\x65\x4d\xc1\x84\xcf\xf9\x16\x8b\xb6\x97\x27\x03\x75\xfe\x88\xd5\xc4\x9c\xf9\x5b\x06\xcf\x9d\x0d\xac\x81\xfb\xd9\xc0\xd7\xb8\x2d\x05\xed\x2c\x3f\xd4\x9c\xcc\x29\x40\x44\x41\x71\x25\x45\xf9\xa9\x91\xe4\xf0\xdd\xb6\x21\x90\x83\x82\x96\xf9\x67\x29\x9a\x38\x60\x72\x26\xd8\xa6\x81\xf0\xa8\xf3\xc4\x38\x4f\xd1\x8b\x30\x25\x7c\x46\x3c\x0a\xbd\x0f\x4f\x6f\x12\x25\xa5\x1b\x76\x2d\x6d\x0a\xc7\xd5\x9c\xd2\xef\xd6\x98\xb8\xd1\x3e\x23\xd7\x04\x09\xf6\xb0\x7d\x69\x5c\x16\x71\xcd\x6f\x59\x44\x3b\x1d\xb0\xab\x35\xb9\xdc\x06\x40\xe4\xc6\xd1\xac\x50\x47\x5d\x28\xef\x94\xf8\x17\x90\xe2\xe5\xb2\x54\x55\x14\xb2\xa4\x9c\x5c\x21\x53\x45\x9b\xe5\x40\x89\x0f\x53\xbc\x18\xe4\xa1\x6d\xcb\x5d\xcf\x50\xf3\x7a\x95\xc6\x06\xfd\xf4\x85\x98\xe5\x2a\xf3\x17\x9a\x20\x48\x61\x5d\x93\xd9\x7e\x05\x99\xb7\x08\x8c\x11\x74\xbb\x9f\x15\xe3\x70\x18\xf9\x9a\xcb\xce\x5b\x13\x02\xf8\xd8\xce\x2a\xb8\x54\x37\xfe\xeb\x0c\xaa\x77\x84\xdc\x83\xc9\xe7\xc3\x6f\xe0\x59\x90\x6b\x03\x0a\x86\xa3\xde\xd0\xab\x9d\x8b\x73\x52\x9d\x47\x5e\x66\x1a\x08\x08\xd6\xd3\xf0\x90\x7f\x85\x28\x87\x3f\x08\xd5\x74\x8b\xe1\xd6\x97\x12\xe8\x52\x62\xd7\x7b\xdf\x13\xbf\xd1\x8a\x5c\xde\x6f\x71\x46\x26\x73\xab\x29\xb1\x61\x73\x15\xa9\xa6\xe9\x36\xa8\xe8\x1a\x8e\x43\xbd\x0f\x66\x44\xa5\xc6\x9e\xaa\xac\x89\xbd\xaa\x99\xcc\xa8\x03\x83\x37\x05\xe5\xaf\xa6\x9b\x3b\xd1\xd0\x25\x2b\x85\x46\x50\xf2\x19\x97\x91\xe6\xac\xa7\xc7\x5a\x86\x12\x83\x21\x62\x33\xa2\x63\x3a\x6a\xef\xf9\xd3\x01\xee\x5c\xb4\xdd\x72\xc0\x8a\x45\xcd\xae\x8f\x54\x58\xc0\x95\xb2\x2e\x75\x9c\x43\xb4\x9b\x98\xe9\xf4\xcb\x33\xd5\xde\xa8\x79\x44\x9e\xae\x73\xcb\x87\x4c\x73\x59\x43\x25\xeb\xf6\x8c\x1e\xd4\x06\x4b\x6f\x61\xab\x2f\x01\x4a\x2f\x19\xf3\x2e\x12\xb3\x3c\x5e\xaa\x8a\x29\x20\x4d\x5e\xba\x58\xdc\x07\x50\x72\xfe\x39\x9b\xe7\xd1\xab\x18\x08\x20\x8f\xb4\x08\x12\x3b\xdc\x0b\x4a\xb3\x13\x0f\x9f\x70\x6d\xc3\xeb\x19\x4b\x60\x5e\x73\xa3\x2f\x12\x5a\xe4\x91\x28\x5c\xe6\x03\x9f\xb6\x23\xc3\x8b\x81\xd5\xab\xa0\xf5\x59\x9f\x6c\x86\xe8\x72\x48\x6b\x4e\x96\x49\xda\xff\xe3\xa3\xd0\x6c\xb0\x73\xdd\x3b\xc6\xf4\xe1\x0a\x18\x70\x0e\x45\x72\x2d\x78\xa6\xb0\x97\x2d\xc9\x4d\x5c\x7a\x7b\x66\x41\x75\x7b\x79\x60\x75\x71\x9d\x7b\x8e\xc3\x6a\x1e\x79\x6f\xb5\xf8\xfe\x6f\x1b\x79\xa0\x85\x9c\xb4\xd6\x7c\xec\x05\xed\x91\x4c\xfa\x32\xc1\xdd\xfe\x21\x8e\xf9\x63\x43\x6c\x3a\x11\x48\xac\x2c\xf9\x09\xdf\x73\x59\x89\x06\x57\x46\x3a\x4e\xa2\x5f\xed\x59\x61\x8a\x06\x81\xa1\x21\x7e\x22\xd6\x4e\xf9\xd9\xb4\x55\x9d\x0a\x0f\x6b\x3c\xe8\xd8\x47\x93\x0b\x23\x23\x01\xca\xf4\x4c\xdf\x7a\x3f\x18\xa2\xac\x13\x0b\x92\xcf\xd9\xc0\x33\x60\x55\x7b\x5f\x7c\x47\x75\x46\x2a\x10\x71\xf7\x03\x44\xc7\x18\x37\x4b"}, -{{0x03,0x3e,0x00,0x3d,0x7a,0xab,0x7b,0xc7,0xfc,0x8a,0xc2,0x04,0xc7,0x33,0x79,0x9a,0xe5,0x53,0xc3,0xfe,0xc5,0x3f,0x10,0xdb,0xf7,0x95,0xb5,0xf4,0xb8,0x7f,0x1c,0x95,},{0x68,0x2f,0x46,0xf5,0xc0,0x56,0xdd,0x45,0xba,0x0b,0x5a,0x78,0x20,0x31,0xf9,0x59,0x6a,0x73,0xaa,0x29,0x2c,0xa2,0x32,0x6b,0xed,0xa7,0x4a,0x52,0xfc,0x32,0xb7,0x16,},{0xed,0xb4,0xe0,0x20,0xd6,0x76,0xfa,0xc6,0xa8,0x45,0x53,0x48,0x80,0xbf,0x61,0x36,0x37,0x4a,0x8b,0x7f,0x2c,0x53,0x85,0xbb,0x9e,0xe2,0x25,0x38,0x1f,0x49,0x4e,0xfb,0x74,0xa5,0x5b,0x41,0x3a,0xe0,0xea,0x70,0xad,0xd6,0x1b,0xfd,0xfb,0x87,0xfb,0x42,0xd5,0xbc,0x0c,0x53,0x59,0xdd,0xdd,0x57,0x3d,0x53,0x8a,0xe9,0x3a,0x6b,0x36,0x09,},"\x59\x6a\xa2\xc4\x0b\x33\x18\x87\x89\x38\xeb\xc1\x38\xdb\x27\x4b\xb3\x8a\x52\x01\xeb\x7c\xaf\x87\x5e\x6c\x64\x57\x91\xda\xe0\x12\xbd\xef\xd4\x85\xe6\xbd\x9d\x84\x99\xc4\x2a\x2a\xe8\x6c\xf3\x2b\x18\x00\x2e\x76\xbb\x58\x2c\xca\x0d\xec\x48\x15\xde\xd8\xa1\x21\x1f\x8f\xc8\x85\x7f\xce\x1d\x57\xf6\x15\x1d\x88\x78\x7b\x97\x8f\xab\x56\xbf\x92\x6b\x15\x33\xe1\x94\x99\xe8\xbb\x99\x15\x8c\xdd\x6e\x98\x0f\x6b\xa5\x43\xae\x83\x1f\x9d\xd1\x34\xb0\xfe\x6d\x5c\x24\x88\x7d\xc7\xa8\xd4\x78\x1d\xd9\xb7\xfc\x5d\xc9\x46\x4b\x04\x5c\xbf\x9d\x1e\xf5\x03\x6b\x5b\xf2\x8b\x54\x9a\xc7\xaa\x8f\xaf\xb9\x1a\xdc\x9f\xec\xa7\xa1\x45\x54\xd1\x10\xe3\x10\xc7\x49\xe4\x85\x33\xf3\x59\xc7\x0f\x05\xfb\x7a\xed\xef\x13\x66\x36\xb8\xef\x72\x23\x88\x65\x39\x86\x4e\xe5\x2d\x34\x11\x8b\x4b\x8b\x74\xe0\x8f\xe6\xb6\x58\x96\xe4\xb1\x9b\x6d\x7c\x3f\x25\x28\x26\x55\x85\x48\x17\x10\xd2\xd7\x49\x48\xeb\x4b\x17\x08\xa5\x0f\xa7\x40\x21\xbd\xa4\xb3\x61\xbc\x68\xd2\xa5\xd2\x02\x10\x9f\x8d\x28\xd8\xaa\x67\xd7\x8c\x11\x36\xcd\x2e\x90\x3c\x8d\xfa\x17\x5a\xf7\xbd\x96\x3b\x73\xda\xe4\x95\x87\x3c\xcd\xae\x62\xbf\xef\x88\x56\x36\xdd\x83\x55\x0f\xf9\xc0\x5c\x37\xba\x33\x89\xd1\x54\x36\x85\xd8\x94\x83\xb0\xc1\x04\xe7\xef\xbb\x77\x02\xc5\xa0\x39\x8a\xc7\x20\x48\x4c\x50\x93\x68\x35\xee\x9d\xf2\x53\xf0\xef\x8c\xbe\xf3\xe0\x7d\xe9\x69\x51\x1c\xcb\xf8\x75\x57\x49\x3a\x0b\x97\x2e\xf0\xe8\xe6\x29\xcf\x38\x22\xdb\x21\x28\x6e\xd7\x27\x66\x1b\xd3\x17\x86\xfc\xa1\x42\x11\x06\xda\xcd\xee\x1c\xaa\xf4\x94\x54\xe8\x54\x79\x4f\x70\x4d\x22\xa9\x5a\x4c\x8e\x6b\x1c\x2f\xee\xa5\x7e\x56\x23\x8c\x20\x96\xf1\xcc\x57\x86\x47\xfe\xa5\x44\xd6\x76\x44\x82\xbd\xf5\x14\x88\x79\xa2\x5f\x94\x3d\xb1\x6f\x29\x02\x1b\x9e\xcf\xe3\xe0\x90\xb4\x25\xc8\x1c\x70\x09\x84\x2e\x1c\x7a\x02\xd9\x1c\xa6\x0c\x12\x01\xc3\xbd\xae\x9c\x53\x73\xaf\x03\xf2\xf4\xdb\xef\x40\xde\x8d\x9b\x21\xfe\xd6\x8d\xee\x51\x0d\xe0\x42\x72\x34\xca\xa1\xc2\x0a\x3a\xe5\x49\x95\x48\x34\xc9\x33\x73\xd9\x13\xb8\x75\x0f\x23\xa0\x37\x80\xd7\xa9\x45\x4e\xd6\xfe\x51\xfd\x2d\x27\x6b\x9d\x4a\xa3\x2d\xe0\x5e\x03\x81\x6e\x64\xe9\x46\x6f\x4f\x0e\x22\x46\x51\x42\x8d\x34\x2c\xbc\xc6\x97\x17\x0a\x47\xef\x99\x6b\xda\xcb\xce\x91\x11\x7c\xa1\xf8\x45\x5b\x25\xb2\xb0\x84\x43\xe9\x91\x4e\x3d\x90\xc4\x89\xee\xaa\x77\x31\xdd\xea\x21\x23\xd5\x5d\x67\xb1\x66\x83\xfb\x7c\x82\x36\xaa\xa5\xa1\xb0\xfc\xaf\x8d\x17\x00\x11\xdb\xe9\xaa\x28\x57\xbe\x61\x2c\xbb\x85\xef\x69\xe5\x68\x31\xb4\xda\xcf\xbc\x7a\x59\xb4\x65\xa6\x6d\xc7\x41\x2d\xdb\x3d\x6a\xf4\xeb\xfd\x70\x58\x64\xe7\xd4\xfb\x99\xa6\xcc\xb4\x8b\x11\x83\x68\xfe\xab\x02\xa3\x40\xc4\x32\x76\x8d\xe0\xe0\x67\x87\x1e\x9e\xa8\x08\xd6\xd9\x93\x81\x58\x29\xe7\x1f\x6c\x04\x2b\x66\x49\x95\x09\x8f\xee\x94\xd5\x43\xdf\x15\xe5\xb1\x69\x57\x03\x1b\xd2\x38\xbc\xad\xbb\xdc\xc5\x76\xaf\xfb\x64\x03\x03\xd6\x9c\x5b\x25\x0b\x3a\x53\x9a\xfd\x12\x7f\x7e\xe2\x60\x9e\x52\xe5\x15\x4f\xbd\xff\x3e\x45\xf9\xc4\x40\x66\x65\x6d\x56\x1e\x0f\x64\xdf\xf2\x80\x5d\xf8\x8e\x30\xa3\x80\x53\x08\x22\x41\x3a\x7a\xb7\x6a\x1b\x9a\x86\x53\x78\xd2\x47\x63\x06\x9a\x81\x40\x02\xa9\xa9\xd0\x37\x95\xca\x8d\x2b\x5b\xd1\x09\x03\x93\xe9\xe4\xb1\xff\x7d\x7f\x0e\xb8\x4e\x71\x2a\x01\x8f\x68\xc9\xe3\x84\xf0\xa0\xae\xf3\x96\x78\x79\x28\x4f\x40\x9e\x30\xd2\x36\x50\x86\xe6\x69\x52\x27\x8c\xa9\xb6\xf9\x0e\x8f\x69\xa4\x8d\x9b\x28\xbb\x4c\x4e\xd6\x32\xab\xca\x3a\xf4\x14\x4d\xa7\x42\x2b\xf5\x19\x92\xf7\x34\x73\x14\x53\xc7\xa3\x3e\x15\xe5\x9f\x53\x08\x12\x9d\x6a\x77\x4a\x94\x58\x6f\x72\x33\x11\x17\x91\x76\xc0\x94\x8f\xff\x4e\x30\xc1\xb9\x59\x81\x2c\xac\x97\x7c\xc7\x43\x47\xb0\x07\x94\x0f\x2f\xb9\x62\xa9\x0d\x66\x06\x6a\x6d\xe8\x80\x19\x84\xde\xe4\xa5\x32\xd4\xb0\xac\xd6\xdc\xaf\x06\x72\x7b\xab\x70\xb3\x86\x62\x32\x23\x4c\x91\x00\xbf\xdc\x66\x9f\x77\xca\x49"}, -{{0xee,0x55,0xfc,0xf7,0x0a,0x27,0x5c,0x72,0x6b,0xd4,0x85,0x66,0x83,0xb3,0x47,0xde,0xcf,0xd4,0x22,0xf1,0x82,0x6c,0x07,0xa9,0x32,0xcb,0x85,0xbe,0x9f,0xa4,0xef,0x3c,},{0xdf,0xcf,0xfb,0x5e,0x15,0x53,0x78,0x9d,0x56,0xa9,0xf3,0x91,0x4b,0xce,0x50,0x0d,0x07,0xc5,0xac,0x31,0x1f,0x92,0x78,0x54,0xb2,0xcf,0x1e,0x58,0x33,0xc0,0x32,0x37,},{0x9d,0x8c,0xb2,0xea,0xf3,0xff,0x3e,0x0c,0x2b,0xc6,0x72,0xe1,0xd2,0x55,0xc5,0xb8,0xe8,0x07,0x31,0xbf,0xf6,0xf6,0xab,0xa5,0x17,0xe1,0x33,0x54,0xe8,0x51,0x08,0x0f,0x4a,0x8b,0xb8,0x12,0x1b,0x26,0x24,0x24,0x4c,0x9e,0xe9,0x5c,0x8a,0x09,0x2f,0x10,0x37,0x03,0xfb,0xe6,0x6f,0x9c,0xba,0x10,0x0d,0x2e,0x91,0xed,0x77,0x4a,0xc9,0x07,},"\xb8\xc8\x45\xcf\x7c\x54\x85\xf0\x62\x2d\x1d\xdc\x17\xf7\xa0\xf6\xf0\xfd\x70\x74\xfe\x19\x4b\x0e\x0c\xd4\x26\x50\xcf\xc8\x17\xf5\x7f\x09\x5f\x8c\xdf\xad\x1e\xbe\x0d\xfb\xc1\xbd\x76\x17\xab\x4f\x20\x4e\x9d\x55\xd8\x1a\x7c\x8a\x43\x39\x40\xec\x6f\x17\xc8\xa8\xe3\xd5\x6c\x1a\xfb\x0a\xf3\x74\xbd\x32\xd5\x4e\xf7\x13\x2d\x26\xb8\x9c\x47\x0c\x2a\xb5\xbe\x16\xfa\xbb\x4c\x75\x19\x3d\x6d\xa5\x9b\xa2\xfd\x15\x7e\x9e\xa4\xe0\xc5\xc0\x8a\x52\x02\xf5\xed\xc6\xa6\x17\x01\xf0\x8b\xb3\x44\xca\x64\x55\xd7\x5d\x14\x5a\xdb\x24\x4c\x53\x4c\x8c\xfc\x62\x3f\x4d\x4b\x67\x67\x59\x4b\x39\xa7\x69\x0b\xee\xec\x4d\xf9\x74\x6a\x57\xff\xee\x05\x14\x54\xc4\x27\x8e\xa4\x3c\x81\x0f\xf1\x3c\xd7\x69\x61\x5f\x9d\x05\xd4\xfe\x4a\x51\x58\x3e\x80\xc0\x15\xdc\xfe\xd9\xaf\x05\xf9\x3d\x05\x4d\x34\xff\xd9\x39\xbd\xd8\xf0\x51\x8f\xa3\x03\x0a\x96\x4d\xc9\xd8\x0d\xf0\x0f\x16\x35\x82\x40\x72\xcd\xf2\x9b\xc8\x02\x59\x20\x9d\x50\xf5\x6f\xca\x9f\xbd\x6a\xe1\x51\x4a\x67\x19\x89\xce\xa4\xf6\x84\x6b\xc1\x91\x79\x09\x7c\xca\x40\xc6\x24\xd7\xed\xbf\x91\xfb\x5b\x25\x39\xeb\xbd\x50\x2d\x36\x46\x71\x14\x30\xba\xe4\x23\xfd\x11\x58\x48\x09\x33\x18\xb7\xd0\x87\xef\x1e\x3b\x89\x4b\xc3\xb9\xea\x27\xaf\x85\x3f\xca\x85\x95\xd3\x6f\xb7\x29\x99\x69\x16\x2f\x2e\xd6\xa2\xb5\x50\x75\xb2\xc6\x30\x80\x28\x57\x17\x6d\xec\x4c\xb5\xac\xf2\xb1\x3a\x35\xa9\x94\x9b\x91\x2b\xb5\x7d\x81\xeb\x0c\x8a\x8a\xdf\x3c\xf6\x4c\xb5\x71\xbf\x5f\x3d\x71\xf9\x87\xd6\x4d\x74\xe9\x19\xa0\x03\x36\xe5\x7d\x35\xee\x4e\xec\xfc\x65\x70\x00\xdd\x5b\x12\x99\x5e\xe1\xb1\x16\x59\x1c\xe5\x8e\x56\xde\x25\xb2\x9c\x94\x82\x9d\x1d\x68\x52\x1b\x95\x58\xe4\x72\x5e\xc7\x70\x39\x06\x9c\x0c\xd1\x7b\x2a\x00\x33\x59\xe9\xe1\xe1\x12\xc7\x59\x01\x76\xce\xbc\xe7\xf0\x01\xf1\xd1\x36\xe8\x18\xf4\x81\x8c\xfd\x94\x74\x5a\xfa\xab\x56\xf1\xa4\x06\xf9\x7d\xd9\xe6\x1b\x73\x52\x66\xd6\x82\xad\x7d\xf2\x6d\xd7\x0c\xde\x0b\x57\xfe\xa7\xdb\x2d\xf8\x32\xfa\x88\xa3\x5f\x53\x97\x94\x88\x4d\xdc\x41\x21\x84\x03\x01\x6c\xb6\xd5\x22\x1f\x3f\xeb\x5d\x3a\xee\x4a\x98\x40\xa9\x13\x07\x2d\x29\xf8\xd1\xa9\x36\x7b\xb0\xbb\xf5\x45\xf7\xda\xe7\xc0\x0a\x0d\x0c\x03\x42\x23\x1a\xe4\x62\xbb\x74\x2e\x14\x98\xee\x58\x4a\xe6\xc8\x3f\x2f\x1f\x2d\x04\x52\xbe\xad\x98\x22\x68\xcd\x3c\xfd\xe7\x8f\xf4\x22\xe2\x26\xbf\x7b\x2a\xf1\x13\x77\x57\x79\x7f\xb0\x2e\x52\x75\xc3\x48\x09\xd5\x4c\xa9\xee\x2a\x65\x27\x5e\x6e\x5c\xff\xdd\x20\xad\x1f\xa1\xee\x0b\xd8\xb2\x1e\x04\xce\x82\x9e\x02\xcd\xb6\x3c\x48\xbf\xcd\xd8\x6d\x3a\x08\xc5\x97\x89\xc9\xd7\x8e\x36\x18\x1d\xef\xeb\x72\x27\x10\x72\x75\xed\x6b\x5c\xcb\x12\x7c\xd7\x2b\x37\x4e\x17\xf5\xee\x0b\x5e\x47\xb4\xb3\xe1\x4a\x8e\xc6\xd8\x6b\xb7\x50\x71\x87\xf2\x8d\xb3\x2b\x3f\x3f\xa1\xca\x13\x44\x6f\xe5\x25\x3e\xe7\x83\x64\x5e\x79\x42\x72\x79\x9a\x86\x3b\x4f\xca\x99\xe4\x43\xcb\xaa\x05\xde\x3c\x50\xed\xf3\xd5\xcd\x7c\x10\x52\x9c\x6c\x09\xa0\xc1\x45\x34\x06\xac\x7e\xca\xfa\x9b\x3a\x1f\x36\x9d\x68\xf3\xc6\x18\xf5\x8e\xfc\x35\x9d\xf2\xf3\xfc\xd2\x47\x8b\x55\xa4\x1a\x11\xf2\x48\x7e\x7f\x70\xec\x29\x3b\x3e\xcc\xc7\x00\xef\x44\x4a\x33\xd1\xea\xe9\x84\x9c\x5b\x76\xd2\x9a\xfd\x5a\x23\x86\x1a\xef\x4f\x2a\x7b\xa3\xf6\x66\x30\x1f\xde\xb5\xd3\xd8\xf0\xdc\x9e\xe2\xe0\x14\xb2\x4c\x74\x65\xde\xe3\xc0\x96\x4e\xdd\x49\xed\x49\xed\xab\xb5\xca\x7a\xfb\x99\x57\x4d\x00\x1e\x58\x12\xa0\x85\x23\x1f\x24\x1b\x6b\x08\xc7\x3e\x80\xfb\x44\xbb\x2a\xdf\x55\x4f\x14\xfd\x6d\xce\x94\xa6\xf6\x36\x23\xd9\xc1\xde\xb4\x1a\xd1\x01\x65\x1a\x6b\x67\xae\x52\x34\xda\xae\x81\x97\x9f\xbd\x82\x33\x89\x64\x9a\x3b\x0a\x06\xc6\x8b\x80\x46\x8a\x99\x1d\x30\x07\x74\x87\x51\xfa\x69\x28\x1d\xb1\xb9\x4d\x6c\x16\x0a\x1c\xab\x50\x94\x3c\xdb\xb8\xde\xa5\x75\x09\x06\xb3\xc6\x59\x5b\xb5\x80\xde\xdb\xfa\xe5\x74\x64\xcc\x7a\x65\x1d\x4c\x51\xdb\xb5\xfa\x98\x05\x97\xd1\x76\x69"}, -{{0x49,0xc2,0x98,0xa2,0xdb,0x3d,0x25,0x89,0xc9,0xfe,0x16,0xa4,0xe5,0x71,0xe5,0xaa,0x23,0xcb,0xaa,0x77,0x7b,0x86,0x47,0x02,0x90,0xa3,0xed,0xa7,0xa5,0xd3,0xe9,0x6b,},{0xda,0xc5,0x23,0xd6,0x37,0x4c,0x8f,0xf1,0x5f,0xc4,0xdd,0xc7,0x13,0x71,0x5a,0xc3,0x5c,0xf5,0x54,0x7f,0xc1,0xb1,0xb2,0x64,0x6b,0x63,0xfb,0x41,0xa7,0xf2,0x16,0x21,},{0x2a,0x43,0x9c,0x73,0xc9,0x81,0x17,0xfb,0x29,0x52,0xe2,0xb1,0x61,0xf7,0xf3,0xb9,0x9e,0x7d,0x39,0xbc,0x69,0x7f,0x79,0x40,0x75,0xdb,0x7b,0x63,0x4d,0x29,0xf1,0xff,0x57,0x24,0xf6,0x77,0xf8,0x31,0x2a,0xd5,0x15,0xb0,0x97,0xcc,0xa9,0xdf,0xc3,0x0e,0x79,0xee,0x8a,0x7c,0x9d,0xd7,0x28,0xbd,0xd4,0x5d,0xf8,0x59,0xc7,0xbd,0xe3,0x0a,},"\x35\x82\xee\xb0\xd3\x71\xdf\x38\x5d\xe8\x8b\xaa\xd3\x80\xcb\x0c\xdb\x60\xea\xb2\xba\xeb\xb3\xc7\x98\x37\x75\x3d\x08\xe1\xcb\x78\xc0\xbd\x76\xdd\x11\x04\x45\x49\x56\xd5\x71\xce\xb7\xe6\xb5\x71\xa5\x23\x68\x35\xd7\x84\xb5\x0f\xf6\x60\x57\xb1\x35\x95\xe7\xd0\xc8\xf2\x5d\x08\xae\x8b\x54\xb6\x12\x3b\xa0\x81\x51\xac\x7d\xb0\xc5\x6a\x98\x0f\x7f\x0b\xb3\x9a\x54\xb4\x37\xf5\x48\x51\x97\x99\x86\xab\x13\x67\x83\x5e\x5c\x4f\x3a\x3b\x3d\x76\x0d\x38\x27\xe7\x6c\x56\x8a\xe7\xae\xbb\xb6\x12\xe7\x75\xbd\xde\xcc\xd3\x34\xac\x6b\xcd\x32\x53\xab\xc2\x9d\x4b\x7c\x3f\x10\x36\x26\x66\xf6\xae\x75\x08\x03\x70\xa3\x6c\xba\x55\xdb\x3a\x91\xcb\x57\x89\xe4\xd6\xf9\xef\xea\x4d\xf1\xdd\x77\x30\xa5\xe2\x79\x60\xd5\x3b\x51\x21\x94\x8c\xce\x5a\xf6\x53\xff\xf1\xd5\xb4\xe5\xb0\xa8\x8c\x71\x8c\x49\xb3\x1c\x79\x3d\x88\xc1\xcc\x45\xab\x8d\xa2\x9d\x05\xe9\x06\xcd\x05\x94\xb5\xf6\x63\x8c\x8e\xc3\xf1\x76\x0b\xa4\x23\xb5\xab\x1d\x08\xa5\x87\x70\xaf\xb0\xf1\x39\xab\xd3\x49\xc1\xbf\x16\x0d\x89\x02\x23\x9c\xe2\x4f\x19\xb4\xe1\xbe\x09\x5f\x7e\xd1\x65\xf3\x93\x1e\x3c\xbc\xc3\x07\xe9\xfc\x5c\x65\x80\x31\x22\x8e\x55\xcb\xbe\xec\x0d\x0b\xcf\x8f\x69\x51\x54\xa9\xee\xd1\xbe\xf3\x52\x28\x78\x9b\xfc\x0d\x23\x8b\x83\x72\xd3\x18\x32\x8c\x13\x39\xfe\xa0\x88\x14\xdb\x86\x21\xab\xca\x3a\xeb\x82\x09\x8b\x5a\xa8\x7b\xb9\x8f\x5e\x40\x52\x2a\x08\x88\x53\x2c\x17\x48\x45\x3d\xb2\xd2\xb3\x94\x3e\x4a\xbb\x31\x2d\xe3\x19\xae\xc4\x8c\xc1\xc9\x47\x75\x97\x29\x53\xfb\x64\x96\xb8\x16\x89\x37\x62\x35\x10\xcd\x48\xc8\xb2\x47\x95\x6d\x31\x68\x48\x6c\x17\x6a\xe7\xa4\xcb\x38\x4e\xac\xfd\xab\xfa\xdd\x9f\xba\x30\xa2\x3b\x81\x1b\xd7\x79\xf3\xcb\xa5\x43\x38\xc2\x8b\xb3\x38\x22\x38\xed\x3b\x8d\xd2\x1b\xea\xb2\xf5\xca\xde\x28\xc5\xe0\x9b\x31\xa4\x54\x80\x8a\x53\x48\x12\x2e\x3a\xe3\x81\x22\x96\xf7\x86\x9c\x38\x65\xc3\xc9\xd8\xfe\x18\xbd\x81\x2f\x2e\x60\xe9\x14\x97\x5c\xfe\x1b\xef\x8d\xbb\x80\x97\x00\x6f\x0d\x7c\xf3\xfc\x15\xeb\x95\xc2\x78\x54\xb1\x43\x12\xb8\x8d\x52\x80\x15\xaf\x69\xfb\x75\x05\xb8\xf3\x27\x03\xf6\x4e\xb1\xc9\x58\xf0\x46\xdd\x25\x12\x42\xf8\xbe\xa7\x46\x7f\xc7\x29\x1d\x09\x5e\x96\x96\xe1\x1a\xa4\x5a\xbe\x79\x24\xe8\x56\x35\x15\x35\xaa\x07\x73\xd3\xd9\xe6\x1c\xc9\xa2\xd8\x9b\x5b\x07\x74\xd7\x64\x5e\xe1\xaf\x7e\xb6\xfc\xd4\x40\xbc\x69\xd4\x3e\xde\xaa\xf9\x35\xfd\x2a\x52\x95\xac\x19\xa9\x7d\x70\xaf\x92\x98\x83\x0f\x81\xc0\xa5\x09\xf2\x42\xf4\x73\x37\x24\x78\xfa\x58\x79\xfb\x2c\xb8\x51\x10\x80\xfc\x2e\xcd\x82\x59\xb8\xc3\xce\x9e\x8b\x64\x07\x61\xdc\x79\x27\xc3\x2e\x7f\x5b\xae\x97\xa8\xb8\xac\x93\x56\x62\xe5\xf4\x5d\x14\xca\xd6\xd3\x4a\xff\xc9\xa1\x94\x14\xc4\x56\x6f\x45\xf9\x77\x39\x67\x10\x89\x4c\x53\x99\xed\x44\x80\xf1\x8e\x90\x95\x7f\xaa\x76\xcc\xb5\x12\xa2\xd0\x75\x73\x05\x8a\x95\xb4\x2f\xe1\x81\x02\x49\xd1\xc8\x5e\xc4\x31\xa0\x49\xd1\xae\xcb\x0f\x11\x83\x79\xbd\xc3\xf1\xee\x49\x0b\xc8\xa0\x54\xc3\x2c\x3d\xac\x76\x59\x96\x6c\xdb\x66\xf9\x95\xac\x40\x3d\x5e\x79\xeb\x6b\x25\xb3\xf3\xf6\x5a\x6c\xee\xc2\x20\xd6\x6c\x05\xf8\xa8\xa9\x8b\x80\x79\x9b\xa4\xf2\xc6\xdb\xbb\x4d\xfb\x58\x62\xc9\xa4\x6b\xca\x01\x3e\xbd\xfa\xba\x74\x94\xa3\x0c\xe1\x46\x06\xaf\xc0\xb0\xf9\x93\x14\x3f\xed\xee\x78\x96\xd9\xa6\xbb\x81\x49\x91\x66\xed\x02\xe9\x41\x86\xaa\xf3\x21\x87\xae\xb6\xe2\x82\x50\x1b\xca\x43\xb5\x7b\x7e\xfa\x09\x39\xc9\x34\xbc\x8f\xbb\xd2\x6c\x44\xb6\x18\x33\x5a\x35\xc6\x92\xff\x99\x6a\x5b\x95\xd3\x27\xdf\x9b\x2a\x66\x21\xb3\xb0\xf1\x90\xdb\x1f\x36\xd9\x11\xd1\xa6\x63\xa4\xeb\xf9\xa2\x85\x4b\xb4\xf4\x06\x10\x95\xb6\x98\x12\xc8\x2c\x2f\xfe\x3f\x92\xe9\xb4\x4d\x2e\xa6\x31\x69\x88\x1c\xae\x84\x53\xd6\xee\xf7\xcf\x69\xc2\x5a\x28\xb3\xf8\xdd\xc7\x01\x48\xef\x26\x72\x1a\x3c\x1f\x2e\x62\xd9\xd1\x0c\xea\x42\xfc\xa3\xfa\xcd\x74\x67\x3a\x4e\x7f\x33\x50\x73\x64\xaa\x28\x6c\x0f\x38\xd7"}, -{{0x82,0x3f,0x0c,0x29,0xfb,0xfd,0xd3,0xd1,0x82,0x8f,0x30,0x55,0xe9,0xec,0x01,0xff,0xd1,0xb5,0xa3,0x75,0x11,0x8d,0xdd,0x7e,0x4e,0x0c,0x43,0x71,0x9f,0x57,0x3f,0xf7,},{0x73,0x12,0x5f,0xc8,0x3a,0xbb,0x8b,0x7c,0x65,0x85,0x59,0xfc,0x12,0x73,0x93,0x23,0x1d,0x03,0xca,0x58,0x46,0xe0,0xc8,0x81,0x18,0xd1,0x3d,0x55,0xca,0x44,0x78,0x9d,},{0xfa,0x74,0x7b,0x6f,0xe3,0x38,0x1a,0xd6,0xbc,0x82,0xa9,0x56,0x43,0xc1,0xf4,0xa2,0x0b,0x76,0xba,0x73,0xbf,0xf0,0x0e,0x63,0x5d,0x64,0x20,0x2d,0x8b,0x0d,0xf0,0x3d,0xbc,0x56,0xb0,0x13,0x8b,0x3a,0x6d,0x41,0x98,0xff,0xaf,0x58,0xcc,0xd3,0xd3,0x88,0xed,0x25,0xeb,0xcf,0x77,0x04,0x43,0xe4,0x1e,0x9d,0x21,0x47,0x95,0x0a,0x30,0x0b,},"\x80\x2c\x39\xce\x7f\x2a\x50\xbd\x81\x62\x2a\xdd\x0d\xf4\xe0\xfe\x03\xec\x3d\x2d\x30\x5a\x45\xa6\x16\x52\x71\xed\x79\xad\xd2\x43\xb9\xa0\x0e\x52\x18\x31\x92\xfe\xb2\x4c\x4f\xdb\xd2\x2c\x80\x7a\xe1\x00\xef\xcf\x16\x5b\x9c\x99\x61\x94\xe0\x0f\xa8\x17\x76\x5e\xa9\x4a\x03\x07\x0e\x48\x66\x86\xb4\x45\xfc\xb2\x63\xcc\xfe\x1f\x58\x62\xf3\xb8\x4b\x10\xf3\x90\x08\x0b\xfc\xae\x44\x7a\xe0\x06\x97\x42\xb8\x61\x8f\xa9\x57\x5f\x7e\x63\x7a\xd5\x4e\x83\x4c\xaf\x03\x94\xd7\x45\x03\x2c\xe1\xe2\x55\xc0\x27\x32\x50\xf1\x50\x4b\x37\xa0\xad\xd9\x4a\xa2\x45\xc7\xde\x52\xc8\x0e\x05\xd6\xe0\xa9\x6a\x14\x41\x05\x43\x82\x6a\x49\xe9\xb9\x45\x62\x6d\x4e\x89\xf5\x50\x27\x16\x3d\x4b\xd6\xd0\xe9\xbd\x1a\x24\x77\xf6\x7d\x3d\x56\x68\xa4\x2e\x94\xd8\xb6\x11\x93\xd8\x21\xe0\xd1\xb2\x30\xfc\xad\xc5\x36\x13\xb7\x5b\x02\xcf\xb8\x15\x84\x56\x07\x7e\xbd\xf5\xa5\xf0\x0c\x3b\x5b\x18\x63\x70\xca\xfe\xc4\xa2\x1c\x69\xdc\xe1\xf0\x1e\xfe\xf2\x3c\x37\xab\x90\xf8\x58\x23\x8a\xef\xbe\x21\x2b\x55\x6d\x2f\x07\x34\x06\x55\x9f\x1a\x51\xd8\x4e\xff\xfd\xce\x07\xb0\x0d\x01\xbb\xf3\x37\x71\xcc\x12\xc9\x60\xac\x89\x36\x5a\x9c\x82\xc5\x23\x43\xf7\x60\x33\x81\xb8\x90\x23\xc1\xa6\xe7\x02\xa5\xb1\xe4\xbd\x19\x1e\xa6\x97\x0b\x5e\xa4\x51\xea\x05\xb5\x9b\xf8\x3e\x55\xf2\x9a\x1f\x80\x32\x12\xbb\x2e\x58\xf0\x61\x63\x33\xd9\x11\x47\x08\x52\x9e\x8b\x6c\x60\x81\xde\xeb\x7c\x29\x9a\x5a\x2a\x53\xcc\xd2\x4e\xd5\x8f\xfb\xfe\x50\x3d\x80\x61\x4a\xdb\x05\xca\x11\xcf\x29\xde\xd0\x09\x04\xea\x12\x39\xf8\x2b\xa4\x0c\x79\x3e\xbc\x33\x97\x75\xf8\xb0\xfe\x39\x01\xf5\x48\x2e\x31\x0c\x79\x3c\x6e\x2c\xf0\x1d\xc1\x57\x72\x7a\xf2\x38\xf4\x9c\x98\x62\x80\x4b\x04\x75\x51\xfd\x88\x6f\x4a\x48\x99\xe2\x2a\x6a\x65\x70\x11\x17\xa3\x85\x80\x55\xbb\xfe\x96\x6e\x37\x0e\x73\x3e\x17\xef\xad\xa2\x85\x9f\xd8\xff\xa9\xe0\x1f\xce\x56\x06\xa2\x55\x36\x76\x78\xf4\xbd\x4e\x21\xe5\xda\x0f\xef\x30\x75\x7f\x34\xe3\x89\xf7\x6b\x7d\x57\xc4\xe4\x10\xa0\x02\xe9\x00\xe4\x8f\xb2\x18\xc8\xf2\x77\x8f\x14\x8f\xee\x56\x96\x5f\x5b\x47\x3e\x25\x25\x6c\x23\xa7\xaf\x19\x83\x42\xcf\x3e\xf0\x2b\x84\xdf\x2c\xd5\x80\x0a\x46\x1c\x1b\x07\xbd\xa2\xf4\x26\x28\xa6\x8a\xd2\x9d\xbb\x82\xa4\x70\x96\x7d\x73\x02\xc9\x93\xb2\x34\x13\x6e\x5b\xf2\x55\xe6\x24\x8b\x10\x2c\x2b\xff\xb2\x01\x72\x37\x1f\x1c\xa3\xe1\x0b\x08\x10\xe8\x64\x95\x03\x54\x6d\x9a\x73\x1c\xf1\x9b\x08\x33\x57\xd4\xcf\xec\xc8\x9b\xed\xb5\x35\x06\xfe\x19\x9b\x67\x03\x91\xa6\x20\x06\x9a\x30\x81\xf2\x53\xb4\xd7\x90\x88\x0a\xa2\x3b\x53\xe9\x7c\x75\xdc\x0c\x36\x05\x40\xe5\xb0\xa3\xef\xb1\xac\xcf\xfd\x13\x74\x14\xff\x84\x23\xd5\x46\x46\xfc\x56\xba\x5f\x53\xbd\x84\xc7\x26\x7c\x2f\x7e\xe3\xe3\x76\x07\x54\x41\x54\x36\x5f\x9f\x85\x08\x1d\xd7\xd2\xee\x75\xd3\x02\x27\x5c\x79\x9e\xf2\x42\x7c\xa6\x49\x63\x55\xdc\xda\x1d\x44\xe0\xd9\x77\xbf\x68\xdb\x30\x06\x50\x0a\xe3\xf4\x00\xd6\xa8\xc7\xcf\x47\x05\x7d\x4f\xc8\x7e\xee\xcb\x02\x11\x6b\x73\xee\xd6\xce\x1f\xcc\xef\x6e\x8f\xb8\xae\xa3\x63\xb2\xf6\xf5\x32\x2a\x5f\x07\x53\xf4\x58\x99\x53\x76\x46\xd5\x86\x51\xbe\x90\x37\xbf\x91\x42\x3c\x29\x86\xf5\xcc\x2b\xcb\xce\x4f\xae\xc9\x03\x49\x8b\x40\xfc\x2d\xea\xb6\x60\x3d\x6e\xea\x58\x5d\x27\x20\xd2\x1b\xb2\x72\x2b\xc0\x5b\x35\xae\xd2\xbc\xc0\xe8\x04\xfe\x9d\x23\x9f\xaf\xda\x7d\xda\xfe\x1d\x78\x60\xab\xb0\xfb\x28\xf4\xbf\x2b\x1f\xbb\x62\xa7\x86\xe4\x55\xbe\x02\x4b\x19\x3b\x78\x30\xbe\x0d\x55\x8f\x02\xc9\xf3\xae\x31\xdc\x10\x7e\xe9\x42\x1d\xc5\xf0\xb0\xf8\x94\x02\xb7\x1a\x45\x81\x40\x15\x36\xbc\x47\x30\x85\x06\xd9\x69\x39\xa2\x06\x36\x27\x44\xe2\x7d\xde\x94\x4f\x40\x96\xa1\x2b\x5f\x63\xda\xb6\x4d\x04\x14\x84\xd3\xfd\x91\xa6\x2c\x2f\x0e\xf9\xae\x78\x74\x22\xeb\x27\xfe\xd0\x80\x2e\x25\xf9\xbc\x77\x5c\x49\x15\xa8\x37\xfe\x3e\xb7\xb9\xd5\x84\x3e\x4d\x82\x10\xc6\xb4\x94\xb6\x12\x81\x63\x7a\x6b\xe3\x20\x52"}, -{{0x65,0x67,0x66,0x33,0x37,0x42,0x14,0xc4,0xac,0x4b,0x7b,0xce,0xa9,0xf1,0xcc,0x84,0xb1,0xb7,0xe7,0x94,0x11,0xe3,0x10,0x52,0x5a,0xce,0x38,0x5f,0x45,0x66,0xc1,0xd5,},{0x0e,0x6e,0xc5,0x80,0x1d,0x8b,0xd6,0xb1,0xeb,0x42,0x14,0x21,0xa1,0x40,0x8f,0x13,0x4c,0xf7,0x12,0x33,0x8e,0x0f,0xfc,0x24,0xcd,0xcc,0xdc,0x4f,0x7f,0xa3,0x1d,0xbe,},{0xe0,0xb8,0x67,0xc9,0xdb,0xda,0x35,0x32,0x34,0x33,0xc0,0x46,0xe0,0x83,0x0c,0x25,0x1b,0x43,0x46,0xc5,0x39,0x59,0x72,0x28,0x6b,0x3a,0x72,0x31,0x0e,0xd4,0x52,0x6e,0x54,0x5d,0xc0,0x9d,0x39,0x18,0xf2,0xeb,0x99,0x20,0xbc,0x9b,0x24,0x1e,0x90,0x50,0xd8,0x48,0xd3,0x83,0x02,0x88,0x65,0x15,0x91,0xf9,0x36,0xd3,0xba,0xe4,0x53,0x01,},"\x9d\x62\x2c\x20\x67\x87\x69\x40\x93\xc6\xf2\x9f\x93\x61\x9f\x21\xbb\x64\xc0\x39\x41\x6d\x20\xdc\x70\x8a\x08\x4a\x9d\x2e\x49\x0c\xf5\x65\x8e\x13\xd6\x2c\xb0\xd2\x1e\xab\x00\xe4\x2d\x85\x1b\xc6\xec\x75\xda\xf4\x05\xd2\x37\x32\x46\xee\xa4\x15\xe8\x66\x29\x1b\xab\xf7\x64\x97\x68\x0a\xaf\x04\x42\x5a\x42\x55\x2b\x10\x7d\x58\xcd\x18\x56\x1c\x8c\x94\x83\xf7\x40\x74\x4c\xbf\xa6\x05\x4c\x1b\x12\x6f\x5a\x76\x65\x9a\xc1\x9d\xdd\xad\x4a\xb5\xa0\x91\x55\xd8\xc0\x50\xb5\x35\x4e\x06\xa4\xdd\x3e\xe3\xa6\xf9\xc9\x1e\x8b\x4c\x7a\xf2\x74\x96\x64\xe7\xab\xe9\x70\x61\x58\x9e\x15\x3c\x58\xe2\x7c\xf2\x99\xa2\x5f\x2b\x53\x0c\x06\x07\x31\xec\x0f\x43\x66\xbd\x1d\xeb\xeb\x4d\x4e\x91\x2e\x76\xe5\x08\x53\x4d\x43\x3e\xc4\x8f\x96\xb6\x2e\x15\x0d\xe9\x39\x63\xa1\xb3\xe6\xc8\x09\x1b\x49\x5a\x96\x51\x8c\xe3\xd3\xb9\xa8\xdb\xdc\x2a\x13\xfd\xd0\x77\xf2\x23\x1d\xe8\xd7\x6f\x56\xd9\xab\x1c\x2f\x9e\xfa\xbc\xe4\x63\x83\x64\xf8\xfb\x2a\x2c\x68\x3c\xa8\x19\xb7\x03\xab\x45\x3b\x11\xd3\x7a\x69\xfa\x4b\xcb\x80\x23\x98\x08\x34\xf7\xb9\x02\xad\x18\x19\xfc\x02\x92\x12\xfd\xea\x0a\xbf\x11\xde\xc8\x8c\x55\xd6\x8e\xf8\x7a\x26\xdb\xb1\x5d\xc3\xd3\xdf\xbc\xdd\xdd\x5e\xd7\x1b\xe8\x6f\x32\xc7\x6e\xe2\x22\x1d\x92\x43\x68\x3d\xf9\x51\x65\x64\xb2\x6b\xab\x5c\x84\x5d\x4d\xfe\x0a\xdc\xc7\xcb\x9f\xe1\xee\x2c\x05\x1a\xf5\x90\x8c\xe0\xcc\x3a\x90\x90\x4d\xbc\x0d\x36\x80\xed\x49\x92\xf4\x6c\xe2\x5c\x2e\xe8\x51\xc4\x14\xf0\x18\x7d\x89\x3e\x5c\x3b\x01\x89\xa7\xbb\x68\x93\xd6\x83\xf5\xe3\x39\x4c\xc0\x46\x29\x9a\x16\xa1\xc1\xb5\x69\x59\x33\xa8\x9b\xb1\x30\x30\x85\x5b\x81\xb3\xc7\x46\x85\xf7\x19\xde\x01\x60\x57\x5a\x0f\xf0\xa9\x1f\xd9\x43\x47\xb8\xbc\xbe\x12\x5d\x1d\x3f\x9c\xe7\x72\xa8\x12\x6e\x00\xf5\x63\xb3\x18\x96\x56\xd5\x52\x2c\x18\x7a\xb8\x31\xa7\xad\xe7\xac\x06\xfd\xca\xc7\xf1\xd4\x58\x82\xe5\x1f\x9b\xf5\xb4\x4a\x2d\xab\xa4\xa5\x3d\xbb\x31\x97\x0b\x4a\x0f\x12\x72\xfe\x14\x08\x7e\x0c\x3c\x7e\x45\x42\x31\x2f\xe7\x4d\x76\x7f\x21\xe7\xea\x48\x7d\x52\x84\x28\x4f\x46\xf2\x0f\x32\xc5\xb1\x6e\x1e\x0a\xc8\xd7\x96\xab\x2f\x80\xb3\x44\xe7\xa8\xd8\x4d\x5d\xe8\x23\xa5\x08\x97\x75\x2d\xc5\x49\xa4\x8f\xc1\x0b\xcd\x43\x6a\x7a\x93\xe9\x7c\xd0\x5d\x78\x30\x13\x8f\x32\x38\x79\x68\x0c\x34\x3c\x16\x46\x7d\x26\x4d\x74\x9b\xf4\x5e\x40\xf3\x9f\xbc\x3a\x00\xc4\x3b\x00\x69\x3b\x01\x56\x76\x8f\xf2\xe3\xf8\xad\x9e\xb6\x40\x50\x22\xf5\xca\xda\x66\x94\xe8\xa3\x3c\xdc\x59\xc6\x67\x3c\x44\x11\x72\x44\xeb\x03\xfd\x7f\xd6\x75\x93\x0c\x29\x4e\xdd\x29\x40\xf5\xf1\x80\x95\x3d\x91\x0c\x55\x48\x5b\x20\x57\xae\x0c\x93\x02\xf4\xa8\xe8\x31\xa5\x53\x0e\x3c\xbb\xf6\xf4\x72\x22\x40\x83\xa9\x52\xa8\x39\x0a\xb0\x0d\xc0\xf6\x9d\xfd\x88\x0e\xea\x2d\x73\x9d\x21\x8d\x6a\x66\xf2\x37\xf1\x0d\x44\x01\xaa\x75\x8f\xf8\x12\x0c\x0a\xe2\x76\x61\x27\x84\x90\x24\xf5\xa4\xcc\x57\x4a\x5b\x02\xb9\x35\x96\x68\x12\xcd\x1f\xb6\xd7\x9d\x0c\x4f\x59\xff\x80\xf0\x35\xa0\xb1\x09\xcc\xcb\x22\xfb\x08\x53\x5b\x87\x41\x49\xed\xf2\xa0\x97\x0c\x14\x88\x84\x27\xd0\x7d\x1e\xaf\xa6\x84\xa6\xd3\x45\x4e\x49\xb2\x25\x18\x4c\x6b\x99\x3e\xc8\xdd\xb8\xb5\xa3\x5e\xe4\x5f\x87\xf6\x92\x66\xd4\x90\x96\xa3\x17\xd8\x6a\xde\x27\xf4\x52\x9f\xe7\x23\x64\xd0\xb9\x58\x00\x72\x99\xd9\xde\x87\xd6\xff\x9f\xb0\x4d\x57\x3a\xea\x46\xba\xc8\xeb\x76\x47\x52\xeb\x46\x5c\xaa\xab\xa6\x89\xa6\x46\x0c\x11\x07\x30\xbd\xd0\x8b\x16\x89\xde\x7b\x05\xde\x59\xaf\x9f\xe2\x44\xac\x36\x3e\x95\xc9\x8b\x66\x93\x59\xaf\x90\x31\xa3\xa9\x3b\xa6\x31\xab\xf1\xf6\x1d\x20\xef\x7f\xc6\x88\x3b\x48\x40\xfc\x92\x67\x12\xe1\x3d\x87\x4b\x72\x2f\x6a\x79\xb1\x60\x70\xc0\x31\x13\x25\xe9\xa7\x0f\xcd\x86\x91\x6c\xfa\x1d\xa7\xf9\xd0\x56\x3a\x22\xfe\x9b\xfe\x85\x4b\x0c\x18\x6c\x86\x63\xb0\x61\xb6\x5b\xc0\x71\xe8\x39\x93\x8d\x8f\xdd\x7c\xf8\xf6\x95\x2a\x64\x67\xfa\xd8\xe5\x84\x90\xed\x2b\x26\x81\x33\x01"}, -{{0xd2,0xed,0xed,0xcd,0x85,0x32,0x06,0xcb,0xf5,0x9b,0xd7,0x4a,0x25,0xa3,0x03,0xfa,0x2d,0x6c,0x39,0x36,0xbb,0x48,0xeb,0x42,0xf6,0xd9,0x00,0xcb,0xe8,0x07,0x72,0xbe,},{0x22,0x44,0x11,0x1e,0x2e,0x76,0x9e,0xab,0x81,0x87,0x1e,0x06,0xc5,0x80,0x17,0x8c,0x23,0x5c,0x7b,0xf4,0xa5,0x2d,0x2e,0xcc,0xe1,0x18,0x87,0xa9,0xb4,0x6c,0x45,0xc8,},{0xbe,0x3c,0x2b,0x56,0x7f,0xe8,0xc2,0x08,0xc9,0x8e,0x71,0x97,0x11,0x7e,0xb0,0x1b,0x3c,0x19,0x7b,0xdf,0xc8,0x58,0x56,0x2d,0xc5,0xcd,0x90,0xf8,0xe2,0xc0,0x35,0x70,0x42,0x30,0x39,0x95,0xba,0xba,0x2f,0x40,0xb7,0x34,0x5c,0x56,0xdb,0x0b,0x46,0x25,0x58,0x0a,0xa8,0xdc,0xc4,0x8d,0xf6,0x01,0x9d,0x23,0xa8,0x38,0xea,0x71,0x72,0x02,},"\x80\x70\xbc\x0d\xb0\x89\xa5\x92\x54\x46\x01\x9b\x7e\x40\x3c\x74\xec\x78\x90\x3e\x4b\xd5\x4b\xc1\xd0\x8a\x54\xa6\xf0\xed\x75\xa8\x5b\x76\x3f\xf5\x4d\xc3\x3a\x26\x00\xcc\xb4\x57\xfd\xba\xea\xe5\x48\x47\x7f\x6d\x69\x47\xae\x26\xde\xb7\x1e\xac\xd1\xd2\xd6\x22\x82\xa0\x83\x84\x3b\xe4\xe5\x93\x1d\x91\xc9\x3b\x62\x82\xc5\x88\x07\xce\x8f\x0d\x88\x0b\x14\x38\xda\xd8\xfd\xcb\xa8\x61\x2d\xf7\x3b\x9f\xaf\xf3\xa9\xf7\xdb\x30\x05\x25\x05\x36\xaa\xbd\x98\xae\x02\x7a\x89\x5e\x10\xb5\xcb\x7b\x69\x87\x5c\x0f\x39\x93\xaf\x24\x51\x92\xf4\x39\x3e\x9c\x4d\x34\x05\x74\x6e\x31\x1d\x3a\x91\x44\x7f\xcd\xbd\x73\x06\xb6\x02\x0c\x93\x3b\xba\xb9\xe3\x9d\x13\x49\x16\x25\x03\x5c\x9c\x63\x6e\xfa\x17\x39\xc3\x58\x87\x10\xa8\x79\xd9\xe3\xce\x17\x64\x61\x6f\x10\x82\xe8\xdf\xf5\x75\x59\xc3\xf5\xa5\xd7\x6d\xd3\x01\x12\x4f\xa4\x89\xfb\x94\x9e\x9e\x03\x9d\xd4\x62\x1b\xda\x60\xf0\xb8\x6b\x31\x1e\x78\xed\x0a\xb3\xb5\x28\x96\x50\x44\xb2\x3d\x78\xee\x2f\x81\x06\x1f\x8e\xdb\xd6\x92\x99\x33\xd1\x8c\x02\x07\xde\xc4\xb5\xb6\xb2\xfa\x4a\xca\x27\x47\xcf\x5b\x11\x0d\xf0\x0b\x0c\x98\x27\xbd\xb3\xd9\xdb\x2c\x7b\x03\x28\xd4\x0d\x99\xe1\xf6\xb2\x28\xe4\x0d\xad\xae\x78\xae\xda\x02\x89\xb6\xa2\x3d\x4e\xb5\x83\x70\x88\xe5\xd8\x84\x13\x63\x2c\xcc\x22\xe2\x1a\x73\x76\x8c\x67\x32\x01\xe9\xa8\xd8\xdc\x6e\xb6\xf7\x39\x7f\xed\xbd\x39\x8d\x26\xf9\x69\x2c\xa7\x2f\x6d\x6c\xf0\x56\xaa\xac\x50\xac\x2f\x3b\x26\x6d\xbe\x5e\x7b\xe7\xa0\x24\x77\x45\x78\xea\xd5\x85\x24\x5d\xaa\xa7\x3e\x0a\xaf\x83\x3c\x07\x0b\xa4\xb2\x04\x4c\xcb\x5e\x5c\xd1\x6f\x9c\x0a\xd9\x2e\xa8\x44\x80\x55\xdd\x82\x8c\x79\x93\x5a\xa6\xc0\x74\x1f\x9e\x2b\x81\x03\x24\xfd\xc6\xe6\x1e\x84\x2f\x94\x57\x22\x68\xbf\x7d\x5a\xdf\xa7\xab\x35\xb0\x7f\xb1\x9e\x78\x15\xa8\xaa\x5d\x81\x13\x01\x30\xac\x5c\xda\x8a\x47\x51\xee\x76\x03\x8c\x0a\x6b\xc2\xfa\xba\x4c\x49\x7e\x62\xb9\xf1\xf1\x94\xb8\xa5\x99\xb0\x77\x01\x81\x4b\x6d\xfb\x7d\x84\xbc\xdd\x5b\x7b\x5b\xc2\x24\x9f\x1d\x38\x45\xef\xf9\xef\x8c\xc7\x32\x85\x35\xd7\x0d\x53\xc7\xaa\x0c\x73\x05\x90\x1d\xe7\xc4\xed\x2f\xe1\x83\x82\x65\xd4\xa4\x17\xb8\x76\xad\xbd\x88\xeb\x93\x3f\x27\xc9\xaa\x48\xc8\xc7\xe3\x4e\x48\x14\x7c\xcf\xfb\x2f\xb6\x1a\x34\x8f\xea\x13\xef\x67\xcd\xf2\xe0\x39\xe3\x3f\xd8\x9e\x2c\x1a\xd2\xa4\x25\x4e\x3b\xf7\x48\x45\x2a\xa8\x3e\xfe\xca\x46\xe7\x80\xed\xe1\xd1\x3f\xf4\xcc\x5e\x7d\x01\xed\x45\xeb\x8c\x74\x81\x8d\x48\x60\xaf\x47\x59\xa8\x3e\x14\x88\x96\xab\x68\x73\x43\x95\x76\x0e\x00\x14\x6b\x79\x3c\x3e\x72\x89\x8a\xa0\xb3\xc5\xe0\xc1\xd3\xfd\xf1\x21\x58\xd2\xe8\xff\x11\x23\xa3\xa0\xc6\x4c\xf6\x37\x4a\x7f\x44\xf1\x1a\x57\x5e\x48\xa3\x79\x18\x1b\x30\xa4\x86\x5c\xfd\x02\x2a\xa9\x83\x27\x56\x35\xce\x4f\x2c\xc4\x0b\xfe\x06\x60\x67\xec\x4f\xe2\x41\xfa\x04\x7b\x55\x27\x0a\x1a\xd0\x77\x6c\x5f\x96\x86\x10\x14\xcb\xf4\x0a\x04\x32\xc5\x59\xf2\x2d\x79\x34\x2b\x79\xf8\xe7\x04\x2d\xcc\xfb\x1c\xf5\x0f\x83\x08\x5f\x80\x63\xfb\x18\x87\xed\x2d\xfc\x9d\xb7\xef\xc9\x6d\xaa\x0f\xf2\xbc\x4f\x52\x33\x5b\x02\x11\x2d\x16\x39\x2e\x13\x4c\x02\x23\xde\x45\x8f\xc0\x72\xcc\x22\xbf\x9e\x7e\xab\xc0\x62\x08\x18\x0a\x57\xe7\xce\x48\x05\xee\x4e\x0f\xc0\x15\x84\x09\x98\xfd\x56\x86\x44\xa0\x38\x6b\x3d\x8e\x7d\xda\x52\xab\xf6\x4f\x7d\xd0\x08\x68\xfc\x84\xf0\x36\xca\x8a\x78\xe9\xba\x81\x71\xca\x90\x26\x7c\x74\xe6\x15\x9a\xca\xc7\xaf\x5b\xf2\x37\x59\xab\xc5\x3d\x82\xe7\x93\xdb\x87\xfd\xad\xe1\x36\x33\x54\xff\xdc\xb0\xbd\x4c\xc9\x21\x3f\x5c\x84\x54\x45\xfc\x64\x9b\x2a\x1f\x32\x9f\x9d\x41\xd8\xa0\x31\xab\x46\xb4\x72\x16\x0f\x03\x43\x4b\x4b\x6b\xc5\xa4\x01\x52\x4d\x61\x79\xad\x66\xf9\xe2\x21\xc9\x06\x7f\xc8\x7f\xe4\xa7\x7e\x21\xe8\x02\x3b\x61\x69\xeb\xf1\x09\x0c\xd5\x56\xa9\xbe\x50\xb9\x18\x7f\xe4\x60\x7c\x59\x25\xe6\x0b\x41\x4f\x6a\x5c\xbf\x8a\xfa\x15\xed\x0e\xb3\x4b\x67\xb4\xc9\xc5\xd5\x4a\xdb\xe6\x40"}, -{{0xb5,0x69,0xf7,0xc1,0xaa,0xdf,0x56,0xed,0x1b,0x5f,0xa1,0xb6,0xfa,0xd6,0x48,0xd0,0xdc,0x54,0x4f,0xf8,0xfc,0xd1,0x73,0x78,0x0d,0xe4,0x1a,0x7d,0x4d,0xe6,0x0c,0xb6,},{0x9e,0xff,0xa4,0xae,0xd9,0xc6,0x58,0xe4,0x34,0x60,0x71,0x43,0x44,0x68,0xa0,0xb8,0xa0,0x4e,0xcf,0x78,0x41,0x69,0x9d,0x63,0xe8,0x88,0x7c,0xe2,0x05,0x57,0x0c,0xea,},{0x2e,0x32,0xba,0x05,0x56,0xbd,0xe9,0x74,0xd7,0xa1,0x9b,0x3b,0x9a,0x1e,0x92,0xf1,0x83,0x92,0x4c,0x4b,0x74,0xc5,0xd7,0x51,0xb5,0xab,0x3d,0x00,0x79,0x67,0x01,0x6e,0xc0,0x3a,0xfe,0x91,0xd7,0x42,0xfb,0x22,0xb6,0x3e,0x5e,0x55,0xb2,0xfc,0xb6,0xc6,0x1a,0x46,0xe9,0xdc,0xe7,0xfe,0x9f,0xa3,0x0b,0xbf,0x66,0xae,0xf4,0xb8,0x5f,0x09,},"\x7c\x5a\xa4\xdc\x80\x78\xaa\x77\xe8\xb3\xb7\xfe\xe6\x10\x84\xcf\xad\x76\x47\x62\xf1\xef\x26\xd8\xde\xb7\xf2\xf3\xb1\x86\xdf\xc7\x72\x48\x75\x50\x19\x78\x45\xfb\xa2\xf4\xc2\x3c\x83\x5b\x9b\x58\xdd\x0b\x63\x5c\x64\x91\x35\x13\x7f\x24\x8f\x5e\xf7\x13\x56\x4d\xe3\xc9\x66\xef\xa5\xf6\xdb\x6b\xea\x9e\x30\x97\x07\x49\xf8\xe8\x72\xd8\xd7\xae\x45\x35\xb7\x5e\x17\x6e\xa0\x48\x9b\x91\x5f\x34\x71\xd8\x27\xeb\x5b\x44\x45\x86\x48\x8c\xfc\x3f\xa6\xa4\x50\x82\xda\xcb\x82\x64\x95\xe5\x0a\x3b\x5d\xc6\xbb\x93\x0a\x33\x1f\x30\xc3\x85\xbc\x3b\x24\xce\x70\xb8\x95\x96\xdb\x6b\xfb\x68\x7d\x99\xa5\x81\x98\x7c\xa8\x76\xea\x0e\x75\x76\x96\xb3\xfc\x03\x77\x9a\x65\x81\x30\xc4\x10\xb3\x44\xed\xac\xc4\x27\x7d\x44\x84\x54\x99\xd6\x78\xe1\x41\x4f\x15\xf3\x6e\x16\x63\x35\x18\x95\x69\xce\xf3\x56\x7a\xc2\xe3\xab\x82\x1c\x91\xc9\x32\x74\xf5\xc2\x8a\x5d\x1f\x7c\x1b\xf5\x09\x9b\x10\xf8\x4e\xcb\x13\xa4\xe4\x53\x8f\x66\x49\xbf\x74\xf7\x39\x4b\x70\x3e\xf5\x36\x49\xd8\x15\x16\xcb\x1d\xb5\x21\x41\x60\x65\xcf\x9f\x27\x6a\xb8\x0c\x93\x08\x89\x7a\x27\xdf\xe3\x7e\x5e\x14\x2f\x18\x19\xb8\xd3\x48\xdf\x50\xa0\x46\xa1\x28\x88\xe3\xb7\xf2\xdc\xc7\x0f\x52\x18\xd1\x5e\xbb\x9a\xa7\x29\x1a\x1a\x92\xac\x44\x5c\x51\xd3\xa5\x3d\xd6\x91\xef\xff\xcf\x5a\x01\xe8\x76\xa7\x2a\xa4\x81\xeb\x4f\x12\x1a\x07\x23\x97\xd8\xcc\x93\xbb\xc2\xc9\xa6\xc2\x8c\xc8\x9b\x11\xff\xc0\xe9\x10\xd8\x2d\x9d\x62\x98\xa3\x67\xa0\xe1\xe3\xe8\xc8\x65\xe4\x32\x6a\x31\x9b\x22\x66\x6e\x52\x9f\x19\x98\xf1\xb3\xc8\xef\xb5\xfc\x21\xcc\xe9\x70\x40\xfb\x62\x47\xda\xa0\x00\x0a\xc5\x55\x4d\x89\xe7\xb2\x71\x59\xdd\x0b\x18\x00\xb7\x60\xb7\x9c\x91\xef\x6e\x97\x0b\x1e\x6c\x5f\xf4\x24\x42\xb1\xb3\xae\x4d\x3c\x43\x9e\x08\xec\x2f\x6b\x94\x17\x73\x87\xca\x5c\x01\xdf\x6f\x07\xf8\xe3\x4d\x25\xed\xbd\x49\xd8\xb7\x4e\x31\xa5\xe6\x5d\xec\x1f\x87\x60\xfa\x22\xc0\x0e\x6f\xb1\xcd\x55\x5b\xe6\x8b\x0a\xb4\x35\x99\xf0\xb9\xf4\xa5\x4a\x7c\xcb\x06\x26\x83\x89\x5d\x5e\xf6\x6d\x24\xdf\xb1\x67\x8c\xb0\xd0\xe8\xc8\x01\xd8\xe5\xff\xe7\x9b\x91\x39\xfc\x96\xd1\x18\xeb\x39\xb9\xc8\xd4\x40\x44\x89\x32\x5d\x45\xb4\xa3\x20\x2b\xea\xdc\xa6\x6f\x83\x1c\x68\xef\xb8\x15\x94\x15\x81\x93\x0e\xad\x29\xfd\x5f\x21\x1b\x90\xe7\xa3\x9f\x0d\x4f\xf4\x8c\x62\xa5\x45\xe2\x8a\xc2\xce\x29\xbe\xdc\x35\x6d\x92\xfc\x00\x34\x71\x76\xd7\x76\x23\xe0\xe1\x80\x9e\xff\x3f\xe6\x2b\x75\xa7\xd9\xde\xb7\x27\xd8\x61\x72\xd1\x4e\xdb\xf2\x78\x9a\x57\x14\x3c\x69\x92\x5c\x91\x7d\x43\x3b\x46\x83\xb0\x69\x3b\x3c\xd9\xe7\xe3\x77\x99\x64\x10\x72\x7f\x5e\x6f\xb8\xf5\xcc\xd1\x86\x0a\x20\x29\x4e\xcf\x33\xfa\xf9\x7a\x1e\x0f\x85\xb7\x61\x44\x7d\x47\x61\xb9\x6e\x4d\xf1\xb3\x12\xbd\x41\x4c\xab\xcf\x49\x84\x97\xb0\xea\xd6\x7c\xd1\xe5\x90\x1b\xbf\x3a\x16\xa8\x89\x1c\xcc\xed\x8a\x90\x7d\xf8\x87\x26\x95\x2d\x4a\xb3\x70\xa6\xb7\xdf\x29\x42\xcf\x13\x61\x5a\x5b\xc1\x2b\x4e\x10\x6d\xc3\x01\x3c\x68\xb8\xfb\x90\x63\x99\xdf\x15\xf1\xaa\x90\xd5\x6a\xa9\x74\xb1\xd2\xb2\x8c\x1a\x84\x53\xb9\xbf\x07\x92\xa5\x1c\x97\xce\x8a\x12\xaf\xc9\x34\x1b\xb4\xc0\xc3\x7b\x12\xdc\xb1\x2c\x63\x94\x49\x77\x5d\x9a\xc5\xc2\xec\x49\x67\x3d\xa5\xaa\xf7\x49\x3e\xd5\xf1\xf2\x11\x6e\xae\xf7\x2b\xb7\xfb\x1e\x09\x3e\xde\x2c\x26\x31\x7f\x4f\x4b\x6a\xd5\x85\x34\x62\x05\xdf\x91\xa6\xe9\x6b\xc6\x6d\x30\x64\xbc\xe9\x52\x39\x8f\xfc\xe8\x80\x71\xed\x9f\xf2\x75\x0c\x65\xc0\xc3\x04\x12\x5a\xc2\xca\xdc\x4f\xef\x71\xa8\x18\x73\x24\x96\xa8\x4c\xa5\x74\xd4\x82\xd5\xa3\xbb\xa2\x0e\x16\xdd\x2f\xa2\x4d\x32\x70\xf6\xc6\x09\x92\xf7\xf6\x3e\x88\xf5\x2e\xff\x62\x22\x99\x8e\xb4\x41\x67\x27\x38\x43\x75\xf5\x9f\x00\xe4\x75\x12\xee\x46\x4c\x31\x84\xac\xea\xff\x3c\xcf\xb0\x6b\xd1\x5c\x18\x3c\x5e\x48\x59\x26\x28\x8b\x99\x7b\xfa\xaa\xec\xf6\xec\xbb\xf7\xd2\xab\xf4\x90\x6d\xf7\x6b\x12\x77\xc5\xf5\xa8\x7e\x68\x17\xb1\xc6\x36\xe9\x1e\xfd\x7e\xcc\xf6\x4f"}, -{{0x32,0x34,0x65,0xd0,0x31,0x3d,0x10,0x01,0xa2,0x61,0xab,0xfd,0x44,0xfe,0x65,0xc3,0x8c,0x9a,0x00,0xca,0x0f,0x20,0x33,0x5d,0x65,0x53,0xde,0x49,0x26,0x99,0xfc,0x46,},{0xe2,0x2f,0x16,0xbd,0x4c,0xc7,0xe9,0x4c,0x46,0xba,0x31,0x96,0x1a,0xf8,0xc5,0x83,0xf9,0xd2,0x71,0x8c,0x68,0xf7,0x3d,0x85,0x06,0x9f,0x60,0x8e,0x15,0xba,0x87,0x66,},{0xda,0x3a,0xad,0xb3,0x43,0x60,0xb2,0xda,0x0c,0x26,0x54,0x2e,0xa7,0x1d,0xef,0xa8,0xa0,0xbf,0x7f,0xbd,0xae,0x3e,0xe9,0xe1,0x1c,0x84,0x08,0x4a,0xd0,0x5c,0xce,0x7b,0xa7,0xd9,0x4d,0xe2,0x5d,0x85,0x63,0x98,0x26,0x16,0xbc,0xdb,0x5b,0xb6,0x39,0x5f,0xac,0x4a,0x7e,0x84,0xbc,0x77,0xe2,0x1e,0xd3,0x6d,0xf7,0x5d,0xec,0x99,0x0b,0x06,},"\xbb\x10\x82\xe1\xcf\xdc\xd2\x9b\xfc\xa2\x46\x4d\x5c\xe4\x46\xb5\xba\x65\x4b\xa5\x8c\x22\x53\x8d\xa9\x26\xb8\x30\x3c\xab\xfd\x28\x4a\x7b\xd5\x99\x4a\x78\x6f\xa6\x6a\xed\xf0\xe1\x5f\x20\xc3\x82\xcd\xac\xf3\xd1\x45\x57\xff\x7a\x82\x67\xfa\x04\x67\x2c\xac\xab\x76\x70\x08\x65\x0a\xa9\xb4\xa7\xc9\x07\x1c\x47\x99\xf1\xff\xa4\x5c\xa4\xd5\x86\xe0\x20\x47\x44\x4c\x14\x23\x19\x43\x46\x7a\x3a\xba\xef\xa5\x39\x59\xda\x22\x6e\xb0\xc1\x53\x92\x01\x97\x60\x15\x96\x97\x74\x82\x93\xc0\x25\x56\x87\x83\x58\x8a\x39\x10\xe7\x8e\x5e\xa4\x27\xc4\x40\x7a\x89\x01\x06\x1b\x8b\x99\x2b\x82\xa2\xdf\x58\xc0\x4a\x1b\x2c\x5f\xad\x11\xc6\xb3\x79\x85\x6c\x2e\x0f\xef\x8a\x95\x0d\xe7\xe0\xfc\x22\x31\x03\x09\xe0\x8b\x13\x2b\x0c\xce\x4f\xc1\xec\xbf\x94\x57\x4a\x38\x8d\x4a\xe3\x66\x75\xd3\x29\x9a\x95\x15\x54\xeb\xf1\x80\xeb\x38\x1e\x1b\x5d\xf9\x77\xd9\x38\x43\x38\x91\xbc\x47\x8d\x76\x81\x85\x0b\x9d\xc9\xc5\xc7\x69\xd4\x05\xf5\xd8\x83\x9f\xc9\x73\x61\xd6\xcb\x30\x6c\x20\x30\x26\xcf\x2e\x2b\x3d\x39\x84\x9e\x1f\x4b\x12\x25\xeb\x25\xef\x8a\xcd\x40\xb0\x06\xf2\x0c\x64\x4d\xb6\x50\xc7\x5d\x38\xc0\xfc\xdd\x48\xf5\x98\xc7\xb4\xa6\x01\x06\xe6\x9e\x19\xcd\x71\x25\x89\xce\xdc\xcf\x50\x86\x4e\xa5\xf9\xe9\x5e\x01\xf1\xdd\x85\xc7\x51\x4f\x2c\x94\xb2\x83\x59\xde\x41\x32\xb8\x8c\x3e\xe1\xd1\x0a\x80\xa9\xfa\xdf\xb6\x90\xe3\xd8\x86\x41\xb3\x16\x8f\x0b\x89\x6a\xf8\x99\x0a\xdb\xf0\xe4\xf8\xe9\xd3\xf9\xd4\xcd\x31\x4e\x12\xc3\xbc\xe0\xcc\x87\x38\xe0\xcf\xc1\x90\x5b\xe5\xef\xa0\x71\xf7\x10\xb3\x2f\x8e\x58\x98\xc6\x0e\xb1\xbb\x8f\xee\xb7\x40\x00\x56\x0f\x41\xcb\x2e\xbc\x32\xb2\x60\x0b\x69\x80\xa2\xa4\x06\x4d\xfa\xa3\x79\x7e\xc4\x4c\xfb\x72\xd3\x79\xf8\x09\x73\x79\xca\xd6\x7e\xcd\xc0\xc3\x24\x14\xfa\x41\xc7\x2b\x1b\x9e\x4e\xdf\x55\x18\xcb\x39\xfe\x90\x92\xb4\x39\xaf\x3a\x4e\xbd\x5a\xfe\x79\xbe\xdc\x0e\xa8\xbf\x17\x47\x9a\x28\x21\xf5\xe9\xbd\x91\xd7\xf4\xaa\x5e\x38\x46\x99\x52\x37\x19\xb6\x95\x7f\x82\x36\x7c\xd8\x5f\xea\x9d\xed\x62\x36\xa2\x07\xc9\x4c\xb3\x73\xe3\x39\x3c\xb4\xfe\x11\xf9\x0a\x1b\x87\x79\xe4\xab\x4c\x34\x66\x13\x6b\xf2\x1e\x2a\xab\x78\xf7\xd2\x72\x6d\xb6\x41\x4f\xa5\xc4\xa3\xf7\x31\x3a\xd2\x11\x6a\x6d\x7c\xe4\x0a\xaa\x10\x01\xc2\x70\x4d\x5b\x05\xae\x54\xc7\xcc\x6f\x56\x72\x17\xf1\xa4\x7b\xfd\x0e\xe7\x38\xea\xea\x5e\xad\xb5\x37\x10\x75\xbe\x07\x6c\x87\x50\xae\xce\xfc\x41\x7e\xa7\xbf\xda\xac\x3c\xc3\x8b\xf1\x6c\xc2\x6d\xf7\x60\x0e\x3c\x7e\x8e\x43\x1f\x26\x76\xfc\x2a\x8c\x43\xa6\xa1\x43\x68\xba\x62\xbb\x32\x43\x9a\x06\xbe\xac\x38\xa0\x47\xb3\x74\x5e\x26\xf4\x07\xad\x82\x3d\x6a\xd1\xc0\xb6\xa4\x43\x41\xe1\x5f\xc9\xb3\x31\x21\x4f\xfc\x89\x69\x82\x11\xb0\x51\x33\xd6\xd3\x43\x3b\x5d\x59\xf7\xab\x4d\x10\x9e\x54\xe4\xc5\xd6\xf3\x2f\xcf\x72\x30\xfa\x4e\x25\x28\xc8\x61\xbb\x21\xcc\xc9\xe3\x10\xe9\x49\x7e\x07\x7e\xa6\x75\x51\x0d\xa7\x12\xb1\xa5\xdf\x57\x5c\x5d\x1b\xf7\x36\x2d\x07\x11\x80\x03\x9a\xec\xfa\xa5\xc8\x57\x3c\x24\xc0\xf4\xeb\xe8\x1c\x2f\x88\x9a\xed\x3d\xe5\xa0\x00\xbe\x12\xfe\x3d\x0a\xf2\xdc\x2c\xd4\x24\x0e\x31\x4a\x17\x6c\x55\x3e\xfd\x5c\xba\x79\x8d\x9f\xf1\xe3\xd4\xbd\x9e\x90\xbb\x81\x13\xe3\x84\x9d\x73\x5a\xfa\x4a\xf6\x94\x5c\xc5\x7d\x4c\x37\x8d\xb8\x4f\x20\x6e\xf7\xea\xb1\x1c\x63\x7a\x7f\x72\x60\xf1\x22\xa9\x7d\xff\x67\x47\xe9\xb4\xc1\x74\xed\x0d\x64\xf9\xef\xd7\xfc\xcc\xf9\x81\x51\x9e\xc5\x80\xa8\x18\x25\x47\xd1\x79\x68\xc4\x01\x51\xfd\xf6\xd5\x4b\xc5\x7a\x91\x15\xf0\x40\xfa\xb5\xc1\x00\xde\xb0\x39\x12\x2b\x7d\x2b\xfd\x98\xb6\xad\xf3\x8f\x42\xb2\x96\xea\x3b\x37\x8a\x90\x42\x59\xb7\x5d\x60\x70\x3b\x48\x40\xb3\xf5\xda\x09\x62\x0a\x54\x77\x62\x80\xe9\xca\x9e\x8c\xd9\x24\xae\xd2\xb5\xdd\x2b\x49\x83\x4e\x58\x1c\xae\xd5\x27\x1c\xd7\x8c\xe0\x8e\x4b\xba\x49\xb5\x9c\xd7\x7c\x1b\x62\x76\x64\x91\x48\xab\x72\x47\xf9\x7f\xc0\x13\x16\x35\xde\x47\x4d\x3c\x23\x49\x3c\xa9\x8d"}, -{{0x60,0xff,0xdb,0xae,0x00,0x3f,0xa2,0x79,0x4f,0xca,0xbb,0xf8,0xf5,0xb4,0x16,0x44,0xfe,0x3a,0x7f,0x44,0xed,0x6c,0x83,0x41,0x93,0xda,0x07,0xa9,0xdc,0x5e,0x26,0x65,},{0x35,0xb5,0xeb,0x31,0xab,0x55,0x64,0x92,0x57,0x8b,0x3d,0xbd,0x6c,0xf1,0x68,0x7d,0x1f,0xdb,0x21,0x6a,0x72,0x58,0x18,0x07,0x96,0x63,0x48,0x2f,0x22,0x1c,0xe4,0x21,},{0xb8,0xf3,0xe1,0xf3,0x78,0x5a,0x2a,0x39,0xbb,0x08,0x6c,0xa4,0x65,0xc0,0xab,0xf0,0xa3,0xe8,0x74,0x43,0x22,0x5a,0xc6,0xe9,0x66,0xed,0x9b,0x45,0x31,0xc5,0x4a,0x89,0x4a,0x9a,0xbd,0x01,0xac,0x31,0xb8,0x57,0x57,0xfe,0x75,0x30,0x8c,0x95,0x94,0xff,0x65,0xf9,0x7c,0xdd,0x91,0xe8,0xd8,0xa9,0x3c,0xf1,0x2b,0x9e,0x6d,0xbe,0xe9,0x0b,},"\x3f\x8f\xf2\x0b\xb4\xf0\x08\x34\xc8\x0f\x2e\xe6\x89\x3d\x6f\x73\xbf\x7a\xce\x27\x29\x60\x1b\xb2\x6a\x0f\xb2\x72\xa4\xd0\xee\xa1\xfa\xe1\xd3\x06\xac\x2c\x5f\x32\xad\xd6\x01\x35\x85\x1d\xa2\x7e\x4f\x12\xe6\x4e\xa5\xe9\xe9\x96\x0b\x13\x83\xb0\x4c\xe0\x5a\x98\xb0\x41\x4d\xad\x97\x1e\xa9\x89\x44\x87\x1d\x41\x5c\xc2\xc4\x6d\xa4\x03\x97\x6d\x9f\x21\x93\x89\x58\xd4\xea\x8c\x79\x03\xb1\x4f\x2a\x44\x85\xfd\x69\xaf\xb2\x4a\xbe\x10\x2d\x8f\xec\x26\x6f\xb4\x68\xb4\x11\xeb\x20\xa3\x39\x67\x7d\x88\xeb\x31\xc9\x97\xb4\xdc\x88\x56\x13\xf0\xbe\x7c\x70\xda\xf8\x56\xa3\xdf\x92\xda\x96\x02\xfb\xa2\xe6\x74\x9d\x2f\x42\x6b\xee\xf6\x86\x62\xd5\xb0\xc2\xfd\x31\x32\x1b\x22\xb5\xec\x59\x7d\xa5\xd7\xe6\xa2\x88\xeb\xd9\x44\x3c\x5f\x39\xeb\x87\xdc\xf4\xa5\xad\x9d\x56\xc6\xba\xf6\x08\x09\x96\xa7\x79\x36\xbd\x87\xdc\x3c\xb4\x2e\xd4\xc4\xd4\x26\x88\xa9\xe1\x93\x82\x9b\x76\x1f\xf3\x20\xe2\xa6\x6c\xc6\x76\x48\xe7\x0e\xea\x3a\x1f\x2f\x9b\x9d\x5b\x42\x02\xfb\x5a\x39\xe9\xad\xc6\x09\x08\x6a\x9b\xe2\xa8\x32\x3a\xc6\x69\x31\xbd\xf6\xc5\x04\xd3\x33\x62\x11\xe4\x6f\xde\xfc\x48\x1f\xbf\x17\xf6\x13\xda\xb1\xfc\x5c\x09\x7c\x92\xdb\x06\x09\x90\x6d\x78\xb2\x5a\x45\x5a\x30\x45\x71\x8e\xfd\x3e\x3b\x14\xe2\x52\xb1\xae\x59\xc7\xc3\x89\x3e\x31\x91\x3b\x2c\x26\x4c\x0f\xfc\x3b\x60\x6c\xa1\xb0\x1d\xc4\x7e\xe8\x28\xa0\x8e\x46\xaf\x60\x4e\x59\x0d\xef\x44\xd2\x7a\xab\x93\xa4\x03\x25\x1f\xca\x07\x72\xe9\xdf\x0f\xab\x7a\xf0\xcb\xc5\x18\x1e\xfd\xa4\xda\x91\x3d\x8e\xb6\x45\x2f\x6c\xec\xbd\xa2\x04\xbc\x72\xd7\xc9\x90\xf6\x0c\xe0\xdd\x83\xc6\x34\xe9\x12\x23\x60\x91\xb0\xa6\x67\x3a\x7c\x89\xea\x59\x30\x8d\x55\xbd\x7e\x63\xa8\x52\x67\x74\xcb\xdd\x7a\x13\x39\xfa\xc2\x12\x4c\x90\x22\xab\xd6\xfe\xce\x7f\x2d\xae\xdf\xd8\x7f\xa6\x83\xdc\x0e\x3e\xf4\x08\x06\xa0\xab\x19\x87\x69\xd3\xa9\x9f\xe8\x1a\x99\xb6\x86\x00\x31\x90\x87\xaf\xa4\xea\x79\xd7\xee\x45\xda\x9c\xd4\x08\x09\xf4\xee\x8f\x4e\x25\xa0\x17\x75\x21\xee\x9d\xba\x8b\x56\x21\x2e\x88\x71\x9b\xb7\x36\x73\x36\xf4\xa7\xbc\x71\x22\xb4\x1a\x7d\xfa\xa2\x67\x2f\x92\xf2\x34\x03\xa1\x0c\x4f\xb2\x53\x88\xc6\xb2\x00\x81\x09\x3d\x49\xf3\xbe\x8a\x9e\x1c\x63\x4e\xf7\xba\x96\xb6\xd5\x23\xdd\x6f\xf6\x13\xc0\xa2\x3b\x60\x45\x70\x26\xcd\x48\x5b\xa8\xdb\x61\xd8\x0a\x0d\xc6\x59\xd9\xaf\x42\xa3\x8c\xae\x77\x7f\xec\x68\xe3\x9c\x52\x98\x6f\xf9\xfc\x20\x78\x9c\x10\x58\x51\x07\xc0\x40\x47\xb6\x6b\xa1\x4e\x93\xfb\x90\x4e\xa9\x0d\xf7\xac\x9f\x01\x54\xc9\x6f\x32\x36\xac\xf6\xdc\x8b\x44\xf5\x54\xc0\xcd\x51\x31\x93\xe5\xdf\xd8\x7e\x08\x5a\xd4\xb3\x8a\xa4\xc5\xe3\x6b\x24\x27\x72\x20\x88\x81\x6e\xcd\x2b\xc3\xa3\xdd\xa0\x1e\x4f\xb3\xff\x5e\xec\x7a\x64\x17\x32\x2b\xa6\xa2\x77\x73\xd2\x44\x95\xa8\x39\x19\x4a\x4a\x58\x2f\xe5\xab\xdb\x8b\x5d\x53\x3a\x24\x26\x25\x89\x24\x1f\xc8\x1f\xdf\x5e\x79\xfd\x26\x77\x64\x28\xf8\xe1\xce\x9e\x92\x6c\xf2\x72\x71\x6e\x75\x83\xab\xfc\x67\xa9\x4a\xae\x08\x16\xc1\x00\x0a\x19\x61\x70\xbb\xff\x1f\x45\xe5\xed\x9e\x26\x7a\xce\x1e\x4d\x91\x5d\xce\x72\x16\xc5\xf4\x04\xde\xf6\xfe\x2b\xd8\xb2\x8b\x2e\xcc\xf3\xe2\xae\xa0\xc0\xd6\x62\x63\x90\x27\x4e\x47\xe7\x45\xed\x3a\x23\xbc\xfd\x21\xd2\x84\xc3\x95\x37\x9d\xc0\x20\x80\xf0\x79\x36\xbc\x15\x4e\x7b\x99\xee\x73\xdb\x18\x8b\xd2\xa3\x94\xe0\x3a\x01\xff\xe2\xd1\xb3\x30\xce\xb7\x21\x58\xf9\x58\xc7\x16\xa8\x17\x11\xdb\xf6\x5a\xff\x8c\xd1\x2f\x5d\xfa\x53\xb3\x76\xeb\xb8\xb9\x8f\x86\x28\xf1\x7e\xf8\xb2\xab\x9c\x0b\xb6\x84\x12\xf4\xe3\x47\xa6\x33\xe2\xf8\xda\x1a\x55\x6d\x96\xf4\xaf\x72\x11\xc0\x78\x07\x9c\x10\x54\x1c\x07\xdc\x37\x22\xd1\x8d\xab\x8f\xa8\xbc\x49\x25\xab\xa5\xc9\x66\xf8\x05\x04\x03\x22\xdf\xbb\xbe\x87\xfb\xfe\xb1\x96\x1f\x5c\xcd\x40\xa9\x1b\x99\x7e\x54\x31\x5a\x7e\xef\xc3\xa4\x7b\xb0\xc8\x7d\xc2\x37\x55\xce\x72\x27\x57\x49\x96\xf4\xbe\x7a\xa3\x44\xfe\x0d\x17\xb9\x7b\xc5\x0c\x58\x38\xf9\x92\x92"}, -{{0x17,0x4e,0x99,0x3d,0x9b,0x81,0xf2,0xaf,0x67,0xe9,0xff,0xb8,0xeb,0xd5,0xda,0x41,0x79,0x66,0xa9,0xe7,0x7f,0x66,0xc6,0x5c,0x76,0x77,0x38,0xfe,0x83,0x57,0xd0,0x7c,},{0x3b,0xb7,0x38,0x6f,0x1b,0x1c,0xbf,0xae,0x55,0x37,0x03,0x83,0x3e,0xbc,0xbf,0xe2,0xdf,0xff,0x8c,0x89,0x9a,0x07,0x92,0xd7,0xce,0x23,0x22,0xb5,0xba,0x64,0x5a,0x5f,},{0xe6,0x07,0xbc,0x9a,0x53,0x60,0xb3,0x1d,0xa5,0x6b,0xe1,0xc5,0x44,0xc2,0x00,0x02,0x84,0x95,0x1d,0x86,0x89,0xf4,0xb7,0x22,0xbc,0x46,0x73,0xa0,0xc8,0x48,0x9b,0x84,0x48,0x3e,0xd8,0xe7,0x6e,0x29,0x7e,0xa0,0x46,0xe8,0x5b,0x37,0xba,0x56,0x30,0x58,0x5e,0x53,0x75,0x56,0x6a,0x18,0x7a,0xfb,0x56,0x96,0x66,0x1e,0x5b,0xfd,0xc1,0x0e,},"\xa4\x01\x75\x0a\xfc\x48\x37\xdf\xe3\xaa\xcc\x28\x4a\x59\x71\x45\xdf\xef\x02\x62\x9e\xf8\x7b\xd0\x93\x8d\x44\x39\x79\xdf\x76\xf2\x9f\xcd\x66\xa5\xb7\x1e\xa8\xab\x78\x72\x77\xe3\x05\x6f\x6e\xa1\x1b\x08\xbd\x23\x89\x79\xf9\xd3\xb0\x62\x53\x8c\x4d\x60\x40\xa8\x6b\x6e\x32\x04\x7a\xec\xc5\x9c\x23\x77\xad\x0e\xa4\xc4\x0c\x79\xff\x9f\xe9\x8c\x95\x8b\x2b\xf2\x5f\x2f\xd6\x34\x24\x32\x63\x6f\x5f\x7d\x5b\xb0\xd2\xec\xf1\x81\x83\x42\x6c\x73\x14\x79\x84\xd9\x5b\xbe\x16\x2e\x11\x97\x2d\xdb\x78\xa2\xa7\xc3\x45\xc5\xc0\xbb\xba\xba\x9c\xf3\x8a\x2d\x5d\xd5\x09\xa7\xdf\x8b\x84\x28\x74\xa9\x6e\x64\xb5\xd6\x4f\x5c\x41\xa2\x1d\x20\x8d\x14\xce\xa7\x06\x6c\xf2\x2d\xee\x0c\xa4\x1a\xa4\x6a\xb9\x21\xd4\xce\xec\x89\xec\x87\x3f\x77\x96\x0e\xda\x60\xd9\x67\x6c\xfd\x0d\xbf\xae\xc8\x72\xc2\xad\xe8\xfb\xa4\x28\x5a\xac\xd5\x27\x14\x3a\xe0\x34\x1d\x67\xd0\x07\x81\x19\x65\x3b\x5d\x23\xd4\x6e\x6e\xf7\x02\x64\xb1\xb0\x91\x38\x70\x87\x76\x23\x71\x6d\x0f\x1a\x59\x02\x1b\xe7\x4c\x91\x4b\x43\x24\x71\xa4\x3a\x29\xf2\xb6\xdb\xeb\x6a\x22\x3e\x2d\xba\xab\xb8\x20\xb4\xad\xbe\x33\x78\x29\xe1\xde\x0c\x18\x4d\xd0\xd0\x9f\x9d\x01\xd4\x25\x27\xe5\xd4\x0a\xbb\xda\xcc\x8a\xc0\xf1\xb2\xc5\xc1\xcb\x2f\x23\x87\x6d\x2d\x1b\x6b\x43\xdf\xe4\x82\xf9\xd4\x5a\x18\xf5\xc2\x2b\x15\xf1\xfe\x52\x1e\xf5\x7b\x08\xae\xc6\xa3\x03\x39\x25\xc7\x45\x4c\x93\xe6\x31\x9e\x77\x8a\xc4\x94\xfb\x14\x0a\xe5\xf1\xa3\x1c\xc8\x32\xca\x24\x88\x65\x10\x04\x06\x3b\xcf\xf8\xfd\x9a\xe9\x26\x6a\xf5\x27\xf2\xc3\x1f\x6a\xcb\x8f\x3d\xeb\xd9\x97\x8e\xf9\xdf\x01\x08\xe3\xd5\x0c\x49\x19\x90\xc9\x0d\xd8\xee\x9d\x64\xea\x4e\xbf\xd7\x11\xc9\x9d\x90\x44\xec\x11\x34\x2c\x53\x83\xca\x39\x23\x2e\xd9\x7a\x07\xe4\xdc\x51\xdb\x4c\x1f\xe9\x47\x34\x8d\xff\xe7\x0a\x95\xc9\x9d\xb1\x47\x51\x31\x48\x01\xf1\x3f\xa2\xbf\x42\xd8\x67\x37\x5a\x08\xee\x9b\x3b\x79\x9e\x0b\x15\x27\x8e\x95\xe9\x1a\x89\x68\x06\x4d\x6d\xfd\x8f\x51\x15\x43\x8c\xcb\x8b\x51\x6c\xa0\xc4\x1d\xbb\x19\x87\x3c\x6e\x10\xa2\x36\xec\xc2\xda\xd5\x22\xf8\x0f\x01\xc1\x4e\x2f\xa1\x4a\x0d\x79\x2b\x9f\xc4\x86\xc6\xfb\x0e\xfb\xdf\x21\x30\xf0\x2d\xf1\x49\x7d\xb5\xab\xa8\xbe\x61\xca\x70\xb2\x93\x88\xe4\xee\xc7\xe0\x69\x4a\x38\xc0\xd0\x3c\x59\xbb\x6a\x2d\xc3\xcc\xd6\xdd\xe1\xe2\x9e\xe2\xc1\xb3\x25\xac\x72\xaa\x8e\x6f\xab\x91\x38\xf8\xb6\xf5\xd3\x24\xd4\x6a\xf3\xa3\x54\x2c\x8b\xd8\x7c\xb0\x4f\xaf\xc5\x4b\x5d\xb8\x27\xde\x60\x67\x62\xa0\x97\xb6\x22\x79\x9c\xa8\x27\xbd\xa9\xc1\xc0\xbb\x26\x7e\xba\x82\x54\xa8\x1c\x6b\x85\x8a\x37\x5b\x94\xbd\x09\xf3\x9e\xeb\x88\xcb\x14\xb8\xd4\x6e\x47\x40\xdc\x1a\xb4\x2a\x89\x5f\x86\xd2\xc5\x7f\xc2\x8b\x07\xb7\xf6\x0f\xc4\xf8\x84\x7b\x8b\xc8\xad\x83\xa2\x48\x1a\x28\xf2\x9b\xca\x35\x10\xff\x8b\xf1\xdd\x75\x81\xe3\x35\x71\x64\xf4\xfe\x92\x0f\x9d\xe8\x39\x37\x6d\xe0\x64\x90\x0d\xc7\xf8\xbc\xf5\x11\xdc\x57\x2e\x0f\x0f\x6a\x75\xb9\x29\x79\x7d\xa4\x1c\x52\xea\xe6\xfe\x13\x75\x0c\xe3\x51\xe8\x76\x76\x30\xba\xdf\x6d\x7d\x4e\xab\x90\xcd\x19\x04\xc9\x6c\x04\x8a\x9a\xcb\x21\x3a\x9e\x5b\x86\x46\x15\x73\x8a\x84\xf2\x22\x98\x6a\xc2\x35\x54\xcf\x4c\xe5\x4e\x80\xab\x57\x33\xc0\x65\xb8\x04\x59\x92\x1d\xd3\xd8\x37\x2d\x0e\x85\x94\xd4\x36\x43\x51\xbf\x04\x1c\x14\x6f\xa8\xd2\x3a\x19\x3e\xb8\x07\xec\xe2\x3f\x24\xab\x65\x95\xe9\x32\xc9\xce\x1a\x75\x9b\xf7\x88\x91\x4d\xb0\x08\xe8\x70\x98\xdd\x81\x46\x5e\x26\x10\x64\x7a\xc3\x8e\x08\x86\x66\xf6\x0e\xc5\xd0\xe2\x17\x33\x20\xa4\x0c\xd9\x85\xf0\xe0\x0d\xbc\x2b\x45\x70\x72\x74\x83\xa8\xc2\x5f\x6f\xc1\xe0\x93\xbb\x57\xcc\xaf\xd1\xca\x20\x2f\x29\x86\xc7\xc5\x54\x0a\x7c\x3e\x10\xc4\xa6\xfc\x26\xd1\xd6\x2c\x2c\xa5\xaf\x83\x05\xce\xeb\xe4\x2f\xf9\x6e\x7d\xc5\x48\x21\x43\x75\xe8\xa7\xf9\xf7\x12\xba\x8b\xd8\x75\xe4\x3c\xa1\x0c\xf9\xb1\x83\xf0\xc8\x51\x95\x12\x92\x85\x38\xa4\x78\xcb\x98\x25\x9b\xd8\xb3\xe3\x34\xbc\xc4\x63\x55\x95\xca\xd3"}, -{{0xe5,0x37,0x15,0xfe,0xc9,0xd3,0xb2,0x0e,0x9c,0x29,0x91,0xe5,0x4b,0x5e,0xb0,0xa8,0xcc,0x81,0x87,0x55,0x69,0xc9,0x5e,0x22,0xa2,0x00,0x13,0x60,0x02,0x17,0x60,0x04,},{0x53,0x51,0x89,0x9b,0x69,0xb2,0x11,0x6b,0xc7,0xf8,0xa8,0x81,0x4d,0x1e,0x5b,0x9f,0xc7,0x85,0x69,0x8b,0xeb,0xd9,0xab,0x14,0x27,0x7c,0x3e,0xcc,0x01,0xef,0x8b,0x1d,},{0x3d,0x0a,0xdc,0xe7,0x7a,0x4e,0x04,0x6f,0xcb,0x9b,0x49,0xad,0x5e,0x6c,0x68,0x09,0xc8,0xac,0x33,0x6c,0x73,0x34,0x04,0xe5,0xd3,0xf0,0x15,0xc9,0x22,0x5c,0x3d,0xf4,0x6e,0xf2,0x1e,0xa3,0x4c,0xff,0xb3,0xaf,0x69,0x97,0x4f,0x8b,0x7e,0xab,0x2d,0x23,0xfc,0xd5,0xa1,0xe1,0x75,0x3a,0x40,0x23,0xde,0xb3,0x81,0x86,0x29,0xa9,0x8a,0x0b,},"\x84\x31\xcd\x16\xd5\xc0\x93\x77\x5e\x18\xc0\x82\x52\xc4\x3f\x95\xb1\x01\x7e\xb7\x11\xfc\xaf\x73\xe1\xe0\x0c\x0c\xd6\xf3\x44\x87\x44\xab\x9b\x0e\x64\x33\x55\x18\xc4\x83\xae\x94\xde\xb9\x76\x77\xf8\x18\xf0\xe8\x1a\x74\x90\x61\x5b\x71\x41\xb9\xc3\x5f\x80\x55\x6e\x69\x71\xce\xa2\x8e\x9a\x32\xc3\x28\xcc\x26\x69\xfc\xa5\xb1\x23\xcb\x66\x2d\xeb\xab\x2b\x98\x15\x77\x64\x66\x80\x70\xe1\x8e\xdf\x76\x1a\xe1\x96\xbd\x4b\x24\x4f\xea\x7b\x74\x98\x45\x16\xbe\x2c\x00\x73\x9e\x76\xe6\xc4\xb6\x21\xcb\x39\x83\x76\x5a\x20\xd8\x47\x78\xd5\xa4\x35\x0b\x16\x8f\x6a\x0f\x71\x2a\x98\x20\xa8\x5a\x63\x6f\xaf\x92\xc7\x89\xc4\x28\xcf\xd2\x96\x2e\xd2\x07\xc3\xac\x88\x99\xc2\x58\xca\xc1\xad\xb5\x15\x9f\x76\x4b\xa3\x72\x29\xc5\xcb\xf7\x83\xfc\x9a\xa4\xd1\xea\x46\xec\xc8\x5f\xe0\x96\x14\x85\xd4\xfc\x5c\xb2\x1d\xf0\x01\x2a\xc9\xb9\x55\x37\x3b\x14\x22\xe5\x1a\xfa\x1c\x55\x09\x88\x86\x2c\x86\x13\x3b\x76\x0a\xa6\x30\xfc\x0a\xce\xe8\x98\x91\x17\xd1\xdd\x96\xe3\xe6\x28\x7b\x69\x28\x7c\x59\x0b\xdc\xa9\xcb\xc8\xee\xce\xf2\x81\xee\x6d\x1c\x8d\x88\x82\x2b\xfe\xa5\xfa\x0f\x53\x0f\x23\x27\x80\x93\xc7\xc8\x5a\x0d\x44\xc3\xa7\x74\x04\xee\x79\xf1\xc8\x36\x8c\xd7\x32\x1b\xf1\x48\xfd\xa4\xdc\xf2\xeb\x07\xe4\x63\x0e\xa4\x22\x58\x75\x86\x37\x17\x80\x51\x45\x36\xb8\x94\xc5\x24\xe6\xb8\x3d\x5a\x76\xa1\x5c\x83\xe9\x5a\xb3\x14\xe0\x7b\x34\xb9\x8c\xd9\x9e\x07\x70\xb4\xeb\x9b\x3f\x3f\x50\x5b\xae\x8a\x06\xf7\xf9\x50\x25\x8d\x79\x07\x48\x10\x71\x95\xeb\x4f\x6b\x84\x84\x0f\x8c\x05\x90\x72\x73\x96\xed\x14\xe3\xf5\x32\x39\x47\x6c\x4d\x2a\x72\x69\xb2\xe1\xf9\x72\xfb\xff\x33\xe4\x72\x44\x26\x74\x5e\xc8\x86\xa3\x29\x16\x29\x5e\x70\xd4\x68\xd0\x6c\x7d\xbb\x5f\xf9\xa3\x54\xe1\xac\x90\x3b\xb4\x5c\xa5\x26\xf0\x8b\x49\xa6\x5e\x82\x29\x7d\x8d\xd3\xfb\x25\xaa\x42\x8f\x64\x34\x5b\xca\x97\x40\xd9\x07\x8d\xac\x9e\x11\x38\xc9\x21\xbd\xd7\x48\x81\x67\x3d\x49\xd0\xcd\x20\x06\x81\x17\x23\xde\x28\x7c\x6c\x95\x83\xe4\x56\xa0\x1a\xb1\xa3\x4d\xfa\x1e\xaa\x96\x3b\x71\xe8\xbc\x7f\xa8\xa9\x8c\xad\x4f\x94\x1e\x4b\x37\xb6\x0e\xef\x92\x3b\x32\x94\x88\x23\x50\xb3\x8e\xa4\xea\xc0\xe9\x23\x2e\x93\xc5\x32\xdb\x5d\x7e\xec\x8e\xcf\xae\x65\xe0\x80\x47\x30\x78\x77\x7d\xdf\xdd\x11\x50\x8a\x6e\x59\xf0\xeb\xaa\x3f\x60\x44\x1f\x82\xa7\x1a\x73\xc8\x4b\xca\x06\xa3\x71\xff\x5c\x9f\x77\x21\x3a\x2d\xb7\x95\xd4\xa8\x89\x78\x23\xd8\x8f\xd9\x2a\xe3\xe0\x57\xe8\xbb\xd8\x0c\x99\x0a\xf8\x38\x6b\xdf\x26\xf1\x2d\x97\x3c\x8c\x5f\xf9\xed\x6f\x7b\x2d\x8e\x61\x83\xcf\x6e\x68\xf3\xbb\x89\x8f\x59\xa9\x3e\xc4\xde\x3b\xea\x60\x5a\x5d\x8b\x15\xdf\xab\x71\x3f\x35\x85\xc4\x8d\xc9\xa5\x76\x82\x42\xb3\x31\x01\x43\x80\x30\xe7\x04\x48\x80\xd1\x7c\x2e\xe8\x4f\x89\xd2\x6a\x1f\x7b\x19\x86\x19\x3f\x96\x63\xc5\x87\xd5\x0c\xa9\xdd\xf6\x18\x6a\x51\x76\xaf\xef\x1a\xdb\x24\x81\xb7\x92\x54\xb7\x8d\x3b\x34\xc6\x97\x90\xeb\x28\xb9\x0b\x14\x61\x17\x0c\x3d\x73\x81\x83\x76\xcd\xf3\x71\xaf\x0a\x0f\xea\xf1\x4f\xdf\x70\x16\xed\x6e\x7f\x08\xc0\xc1\x4b\x52\x70\x5c\x86\xd4\xf0\x00\x3b\x5e\x45\xf9\x74\xc0\x64\x16\xcc\xb5\xca\x3e\x9d\x52\x9a\xa9\xd4\x15\xc2\x5a\x44\x6f\xa2\xd6\x9e\x82\xf4\x99\x4e\x57\xe9\x22\xc1\x7c\x1c\x34\x2d\xd7\x28\x1e\x41\x00\x52\xd9\xe4\xaa\x1b\x30\x9b\x7d\x47\x0d\x45\x8c\x66\x3e\x17\xff\x25\x00\xd0\xbb\x8e\x46\xa9\xc4\x36\x7e\x09\x1c\xaf\x87\xdd\xfc\x06\x2a\xae\x08\xa6\x5c\xb9\xe0\xea\xa7\x1c\x99\x45\x9c\x5e\x7c\xb1\x12\xa2\xee\x98\xa5\xe4\xcb\xee\x0d\xc5\x20\xf8\x7c\x30\x22\xda\x65\x49\xbe\x1e\xe7\x0a\x0a\x73\xad\x84\x99\xc9\x7d\xd0\x6a\xa1\x4c\x9f\xd8\x62\x8a\x92\xca\x6d\xb4\x87\x32\x2d\xb9\x59\x8a\xda\x1f\xce\x28\xf4\xb9\xfc\x1d\x3c\xc3\x9d\xcf\x2e\xd1\xdf\x3d\x86\x2d\x87\xf5\x5c\xc1\x01\x6f\xb9\xe7\x3e\x7c\xc8\x97\xb9\x70\xd5\xff\x35\xac\xfe\xb0\x5c\x1c\x89\x19\x28\x08\xae\xeb\xfb\x2c\xd1\x7c\xb1\xc9\x4f\xab\x05\x98\x98\xfe\xdc\x2f\xbd\x44\xcc\xef"}, -{{0xab,0xfd,0x69,0x7b,0xfb,0xc5,0xb6,0xff,0x2b,0xdf,0xf3,0xbc,0xe1,0xd7,0x77,0xe0,0x5f,0xbe,0x3e,0xc8,0xb9,0x5c,0xe6,0x93,0xd6,0x23,0x93,0x12,0x09,0x31,0x3d,0x4f,},{0xa7,0x09,0x32,0x1a,0x02,0x10,0xcb,0x80,0xab,0x58,0xbf,0x95,0x5e,0xcd,0xeb,0x8a,0xaf,0x9e,0xe4,0xc3,0x75,0xf9,0x59,0xc5,0x30,0x89,0xd4,0x37,0x48,0x8c,0x08,0x2d,},{0x8c,0x36,0xb5,0xa1,0x11,0xc5,0xa8,0x11,0x9f,0x2d,0x9d,0xb5,0x7e,0xbb,0x59,0x2d,0xae,0x86,0xad,0x4b,0xf6,0x78,0xc1,0x49,0x2e,0x26,0xf3,0xc1,0x0f,0xbe,0x03,0xf1,0x05,0xca,0xe0,0xdc,0x68,0xb5,0x52,0x59,0xb9,0xb5,0x98,0x92,0x89,0xdb,0x33,0xd9,0x5d,0x2e,0xe6,0xb7,0x56,0xc7,0x60,0xf9,0xd3,0xaa,0x0e,0x68,0xa1,0x89,0xde,0x02,},"\x89\x6b\x7a\xb8\x41\x3f\xfe\x43\x9a\x2f\x44\x87\xec\x49\xd6\x4e\x31\xc7\x4f\x50\xac\x83\xf5\x5d\xa6\x1a\x70\x03\xaa\x71\x6c\x2a\x9d\xf6\xb4\x38\xe6\x2f\x53\xd8\xf0\x19\x2f\x37\x36\x32\x47\x60\xd7\xe8\xc4\x4a\xc0\xba\xca\x3a\xe2\xa6\xfb\x93\xf1\x3d\x96\x88\x67\x99\xfd\x2c\x45\x51\xb0\xab\x36\xf1\x73\x08\x55\x55\x12\x65\xa5\xa3\xc3\xc2\x1d\x95\x16\xa2\x37\xf5\xdb\xc1\xc8\xe7\x29\x99\xb7\x82\xc5\xca\x41\xa4\xf6\xe9\x30\x8e\x64\xaf\xde\xe0\xbf\x47\x9e\x54\x6b\x89\xc5\x1b\xc5\xe4\xf7\x1e\x57\xfb\x24\xce\x43\x7a\x8b\x81\xb9\x1d\xc7\x98\xb5\xab\x36\xf2\x9a\xfd\x5b\x48\xe8\x1c\x17\x6a\xe5\xed\xf9\x53\x71\xba\x32\x46\xfb\x43\x94\x05\xbd\x10\xee\xd3\x67\x8e\x3e\xc6\x23\x07\xa3\xb3\xdc\x1b\xad\xba\x05\x1f\x16\x77\x4b\x85\x08\x81\x88\xc2\xa9\xe3\x20\xa1\x61\x8d\x5f\x26\xce\x94\xee\x2b\x93\x3c\x30\x5f\x6d\x95\x84\x95\x8e\xea\x31\x56\xc3\xd1\xe0\xef\x39\xa1\x86\x27\x5e\xe6\x2c\x40\xf3\xc1\xac\xd1\x5d\x8b\xe6\xe0\x74\x35\x1f\x53\x49\xce\x3d\xf6\x95\x17\x50\x5f\x45\xfa\x06\xa8\x15\xc6\x9c\xa1\x8f\x45\x0f\x42\xb5\xcf\x4e\xbd\x99\x26\x84\x45\xe0\xf6\x81\x04\xa7\xde\xeb\x0a\x11\x5b\x81\x7b\x99\xe1\xa7\x3e\x0f\xa9\xd8\x7d\xb7\x1f\x8e\xc9\x4f\x87\x08\xc9\xbc\x2e\x62\x2b\x96\x33\x65\xeb\xcf\xb9\x7c\xfe\x73\x32\x63\x00\x70\xe9\x65\x4e\xaa\x60\x36\x1a\x45\xd4\x02\xdc\x0a\xb2\x97\x66\x52\x42\x66\x7f\xbd\x99\x40\xf6\xcd\x33\x19\x52\x46\xa8\xc2\x86\x9a\xf7\x59\xa8\x62\xd4\xb6\x41\xdb\x14\x4d\x57\x32\x36\x6b\x20\x63\x6c\x40\x27\x78\x7f\x55\x80\x27\xd7\x6f\xcb\xf8\x43\x2e\xb9\x3e\x6d\x14\x56\x7d\xf8\xdb\xf2\x11\xda\xeb\x56\x55\xdb\x10\xac\xdd\xd0\x5e\xca\x06\xac\xce\xe9\xfd\xa8\xd3\xb7\x0c\xa1\xe6\xdc\x58\x7f\xa4\xb7\x8f\x63\xcd\x66\x3f\xf0\x24\x38\x70\x57\x0f\x4d\xcb\xaa\x3f\xb6\x26\xb4\xe1\x13\xbd\xe4\x7d\x5c\x9d\xb2\xb4\xba\x6e\xc6\xdb\xf9\x18\xac\x05\x69\x49\xef\x3c\xfc\xb1\x15\x56\x16\x15\x77\x1a\x03\x5a\x43\xd3\x3b\xa2\x65\x1d\xbe\xb4\x63\x48\x26\x1c\xe3\xc4\xc9\xf2\x46\xd2\x3f\x94\xdb\xc2\xd0\xc1\x9b\x92\x1e\x24\xc7\x7d\xa5\x99\x2f\x1b\x4b\xdf\x2e\xde\xa4\x99\xf5\x41\x11\x68\xac\x0c\x12\xe9\x6f\x3b\x15\xd2\xe1\x2a\xc8\xd7\xb3\xed\x8d\x1e\x07\xc4\x26\x7a\x25\xd3\xa3\xc3\x53\xa4\x20\x8b\x74\x06\x27\x8a\xab\x9e\x70\x0f\x7b\x20\x6f\x48\xe6\xea\x7c\xc9\x7e\x55\x4f\x15\xc9\xbe\x34\x9d\xd9\x15\x14\xdb\xe8\xd8\x89\xf2\xdc\xbb\xfa\x18\x2c\x9f\xaf\x58\x07\xa6\x9b\x2e\x97\xfa\x77\x1a\x6f\x23\x1a\x4c\x7b\x31\xd1\x17\xb8\xed\x0e\x63\x0c\xdf\x13\xe0\x82\xbb\x4f\x63\xc3\xf9\xac\xb3\x55\x32\x04\xcc\xd7\x6e\x18\x35\xc4\x6e\xec\x3d\x43\xc5\x61\xbb\xf1\x7c\x92\x21\x4a\x6d\xb1\x21\x2b\x60\x03\xcf\x2c\xc2\x6c\x7a\xe6\x75\xfc\xd0\x53\xb9\x47\xe7\x22\xf9\xe8\x57\x62\xce\x8a\x16\xe4\x65\x4e\xc6\x34\x2f\xc6\x46\xe5\xca\xb4\x72\x79\x7e\xab\xf6\x58\xba\x4a\xfd\x14\x2f\xc8\xfc\x4c\x8f\x98\xf2\x3c\x24\xdc\x99\x84\x7a\xe8\xce\xf0\x87\x9e\x1a\xb3\xbb\x80\x97\xe4\xc3\x52\x9a\xdd\x2d\x8e\x8e\x2c\x20\x69\x21\x0f\x50\xac\xe1\xae\x32\xa6\xc8\xe6\x38\x4a\x2b\xf7\xd7\x9c\x66\xc7\x46\x14\x9c\x84\xad\x75\xa3\xa1\x76\xe4\x5e\x13\x6d\x94\x69\x5a\xed\x4b\xfd\x08\xb4\x26\xea\x8c\x4b\x93\x79\xf3\x74\x25\x50\xe1\xcf\x5a\xc8\x4c\x18\x17\x4d\x68\x0e\x92\xaf\x2c\x18\x74\xac\x1c\x13\xd2\x82\x32\xde\x19\x37\x68\xe5\x61\x94\x7c\xbd\x6b\x79\xe9\xb9\x9d\xa6\x5c\xfb\x74\xff\xb3\x2f\x7d\x3d\x20\x25\xc6\x07\x63\xdc\x07\xf5\x55\x39\xb4\xd2\x53\xde\x1e\x6c\x25\x82\x3a\x62\x58\xc7\xa9\xce\xd1\x50\x1d\xce\x27\x86\x89\x8a\x3e\x05\xc9\xbf\xf8\xfc\x5b\x21\x25\xd0\xf4\x71\x08\x8a\x13\x4b\x48\x73\xc8\xd5\x5c\x04\x45\xf6\xca\x39\x6b\x3d\x7b\x4b\xc2\xbf\x5c\x4d\x22\x40\xda\x41\x82\x93\xaf\x6a\x3e\xd8\x53\xde\xdd\x3b\xf6\x68\xd9\x37\xb3\x5a\xa0\xc2\xac\xbf\x23\x76\x6f\x9f\x3e\x96\x82\x84\x75\xab\x08\x64\x96\x61\x7a\x6e\x81\xd6\x53\x58\x9b\x2f\xe5\x0b\x7b\xa8\xf0\xcf\x1e\x5a\x44\xd8\xd6\x2f\x08\x37\x7a\xbf\xc2\x62\x97"}, -{{0xdc,0xfa,0xd5,0x9f,0xc6,0xb6,0x97,0x10,0x9e,0x72,0x7f,0xf6,0x6a,0x5f,0xe9,0x3a,0x6a,0x22,0x6f,0x63,0x1a,0x64,0xe5,0x79,0x7a,0xd8,0xd8,0xc8,0xb6,0x35,0x87,0x34,},{0xe7,0x9f,0x4f,0x51,0x13,0x72,0xe3,0x55,0xe7,0xe9,0xe0,0xe8,0xb5,0x34,0x6f,0xdb,0xcd,0x2d,0xf1,0xfc,0x5c,0x3a,0x18,0x90,0xd2,0x7f,0xa1,0xfa,0x92,0x8d,0x27,0xa6,},{0x05,0x2f,0xf7,0x95,0x40,0x73,0x74,0x56,0xc6,0xa4,0x2c,0x41,0xc9,0x7d,0x6b,0xf5,0x17,0xb8,0xcf,0x28,0x9b,0xc7,0x8b,0x50,0x3d,0xee,0x6a,0x30,0xef,0x51,0x68,0xb3,0x8f,0x75,0xbe,0xac,0xa1,0xe1,0x4d,0x97,0x1f,0x87,0x73,0xe3,0x94,0x1b,0xd6,0xdf,0x5c,0xb9,0x77,0x8d,0xea,0x12,0x5a,0x4c,0x4f,0xe0,0x11,0x6b,0x70,0xee,0x84,0x0b,},"\x7d\x92\xdd\xd8\x13\x3c\x61\xc6\x10\xc1\x30\x8c\x23\xae\xaf\x99\x38\x84\xa4\xe6\x7f\x7b\x94\xbb\x88\x6d\xad\x50\x98\x69\xa9\x32\xec\x4a\x27\xd4\x10\xd2\xc2\x9c\xa7\xae\xae\x6f\x92\x80\xcf\x6c\x4b\x06\x7e\xc7\x51\xe5\xe8\xc3\x9f\xf4\x44\xd4\x22\xce\xab\xae\x14\x5d\x42\xf0\x47\x45\x3d\xd4\x02\xd1\x79\x74\x05\x03\x34\x09\xe7\x2c\xc1\x9f\x79\x3d\x5d\x26\x8f\xb3\xfd\x2c\x11\xea\x2c\xb0\xd7\x04\x36\xe1\x8f\x9e\x88\xa0\x15\x15\xdc\x86\x5f\x6a\x1e\xb2\x36\x90\x32\x8f\xd7\x5d\xe2\x63\x21\xa3\x8f\x12\x19\x7a\x97\x20\x1b\x1d\x84\x52\x94\x4f\xbc\x54\x1c\xb6\x8c\x77\xd4\x95\x15\xdb\x53\x26\xf2\xb1\xd0\x76\x3e\xda\x06\xd2\x50\xce\x2a\x5e\x0b\xbd\x7d\x16\x76\xd7\xd4\x1f\xb3\xab\xe8\x8b\xdb\xe3\x72\xf9\x6b\xf7\xbb\x52\x6d\x6b\x65\xa2\x51\x5e\x83\xa5\x77\x04\x5b\x54\x79\xb3\x8b\x85\x2f\xe4\xab\x01\x1c\xbf\x21\xc0\x85\xef\x5f\x0a\x7c\x1b\xed\x76\x57\x2b\x0f\x86\x02\x28\x06\x7a\x89\x9f\x89\x5a\xe7\xf6\x25\x6e\xb6\x51\x40\x87\xf9\xd6\xf5\xc3\x55\x96\xc1\xf4\x80\xc7\x31\x13\x54\x6c\xb9\xcc\x30\xf5\x6a\xb0\x74\xa9\xff\x28\xac\xab\x7e\x42\x65\x0a\x96\x1d\xa3\x25\xac\x5b\x65\x94\xb8\x1c\x93\x25\x0a\xe7\xd3\x92\x67\xa1\x9c\x97\x62\x54\x07\xed\xda\x04\x04\xcb\xe5\xa3\x6e\x95\x9f\xc8\x20\xb2\x7e\xf5\xca\xd7\x96\xc1\x1e\xaf\xf1\xc0\xe2\xf9\xd4\xb3\xc6\x49\x15\x02\x19\x5d\xe0\x36\x59\xb3\x64\xe4\xe8\x7b\x2b\x2d\x73\x3e\xc2\x5e\x6f\x9b\x63\xd5\xf6\x91\x79\xe0\xd2\x7b\xd4\xae\xcc\x8f\x12\xa5\x07\xa9\x1b\xaa\x48\xd9\x9b\x3a\x42\x6c\xec\xeb\xae\xf3\x7d\x73\x61\x10\x6a\x84\x90\x64\x43\x09\xf6\xeb\x4d\x25\x96\x44\x3b\x6b\x01\x18\xb9\x45\xac\xec\xc6\x44\x3e\xa6\x1f\xcd\x15\x5b\x54\x32\x5b\xc2\xc3\x1b\xe0\x25\x0f\x94\x82\xe1\x3f\xd8\xeb\x44\xe2\xae\xd7\x6b\xe8\x12\xaf\x54\x53\xcb\x7f\x86\x32\x45\x8f\xc8\xa0\x2a\x2f\x45\x48\x0d\x79\xb0\x6c\x7d\xda\x38\xb4\x69\x5d\x08\xb5\xa4\x30\x50\x4f\x1a\xe2\x27\x5b\x05\xc9\x1e\x79\x9d\x44\x70\xf3\x8a\xbe\x77\x73\x6d\xfa\x89\x5c\x19\x7e\xa4\xb6\x3c\x2d\xf1\x8e\xfe\xb1\x41\x84\x83\x7b\x8d\xdf\x48\x90\x95\x20\xd9\x10\x45\xb9\xd9\x65\x5c\x22\x5a\x83\x17\x39\x60\xb4\xd7\xcd\x0d\x8b\xae\x30\x23\x75\x57\xf8\x69\x70\x8b\xe1\x38\xad\x52\x46\xc8\x66\xc6\xc0\x59\xdc\x59\x7a\xbf\xd4\x94\x32\x37\x37\x68\x96\x73\x6b\x97\xb7\xe0\x28\x9e\xf9\xbb\xd2\x94\x77\x74\x5c\xb6\x0f\x46\x20\x2f\x1d\xe9\x84\xf5\x09\xb1\x80\x88\x33\xf5\x80\x18\xcd\xe8\xc2\x6b\xef\x4c\x00\x5b\xdc\xa3\x85\xb0\x57\x35\x11\x0c\xa0\x2e\x56\x2b\x50\xed\xdf\xf6\xfd\xe9\xfb\xb8\xd0\x30\xce\xdf\x70\x31\xbb\xeb\x32\xb1\x2b\x24\x2b\xe4\x9f\xde\x01\x60\xc1\xfb\xde\x99\xb0\x3c\x06\x2a\x1a\x47\x06\x23\x45\xc9\x2e\x0b\x60\x4d\x08\x0f\xac\xce\x92\x43\x48\x15\x29\xc7\x05\x97\xdf\xd6\x43\x82\xcb\x54\x06\x91\xb5\x9b\x71\xb0\x94\x33\x2b\xaf\x0b\xbb\x12\x5b\x63\xa4\x46\xbb\x97\x49\x1c\x04\x64\x32\x8c\xab\xd7\x62\x7c\x46\xf3\x92\xf3\xb1\x24\x82\x2f\x20\x13\xc6\xe1\x6d\x3c\xa8\x7c\xc5\xbe\xcf\x56\xb0\xfc\x6e\xb2\xbf\x99\x23\xb3\x01\x2b\xa2\xb6\x12\x50\xa6\x33\xa4\xd2\xee\x39\x12\x56\xc5\x20\x95\x73\x82\xaf\xf9\x70\xc5\xd2\x23\x85\xc3\x34\x4c\x6d\x4b\x45\x61\x57\x1c\x96\x32\x9b\xf7\x56\x15\x29\x75\x16\xb9\xf2\xce\xb9\xf9\x97\xa3\x95\x23\xaa\x0f\x58\xb4\x88\x77\x2d\x82\xfc\x0d\x78\xc5\xdd\x52\xec\xfa\x6b\xfa\xc6\x3a\x76\xe1\x48\x08\x8b\x36\xf2\x4a\x88\xe6\x83\x85\x49\x6d\xda\xdf\x30\x23\xf7\x2d\x87\xc2\xef\xa2\x6e\x87\x7d\x32\xf1\xda\x97\xcd\xb4\x2c\x8f\x15\x71\x89\x88\xe4\x28\xcd\x02\xf4\xd0\x95\x43\xbd\x0b\xd5\xb2\xf4\x09\x96\x3d\x0f\xa3\x73\x53\x1f\x78\xb5\x92\xbd\x13\x7e\xea\xea\x0b\x4e\x7f\x91\x82\x08\xe1\xd5\x90\x08\xa8\xaf\x50\x58\xf5\xd9\x23\xc4\xf3\x2d\xf1\x99\x90\xf1\x0d\xd3\xf0\xeb\x20\x62\x93\xb2\xb3\x44\x3f\x4a\x5d\x2d\xcc\x5f\x7d\x3b\xba\xf6\xaf\x43\xfe\x45\xf5\xdb\xbe\x53\xec\xf4\xbf\x1b\x4a\x13\xe2\xd4\x6e\xf8\x02\x98\xd4\xf0\x1c\x40\x2e\x21\x0f\xcb\x9f\xf2\x08\x4e\xc0\x3e\x42\x00\x8d"}, -{{0x69,0x6d,0xc4,0x81,0xf6,0x19,0xa9,0x49,0x85,0x63,0xc8,0x3d,0x0d,0x0e,0x55,0x56,0x5c,0x14,0xa0,0x78,0x45,0xfe,0x4a,0x66,0xab,0xa2,0x24,0x7b,0x11,0x3f,0xf8,0xef,},{0xc9,0xd7,0x37,0xab,0xc4,0xa9,0xe7,0x3c,0x14,0x9e,0xad,0xc1,0x95,0xa8,0x37,0x89,0x9f,0x2c,0xd5,0x01,0x93,0x73,0xc3,0x0e,0xca,0xf6,0x2e,0x5f,0x8e,0x14,0xb6,0x45,},{0xde,0xd5,0xd9,0x91,0x93,0x5c,0xd1,0xf9,0x39,0x0f,0x1e,0x85,0x92,0x9c,0xa1,0x6d,0xab,0xfc,0x83,0xe6,0x5e,0x43,0x27,0x2e,0xb1,0x75,0x16,0x71,0xaa,0x31,0x93,0x0c,0x72,0x85,0x55,0x34,0x14,0x30,0xce,0x7c,0x80,0x48,0x5d,0xe5,0x80,0x06,0x42,0x71,0x29,0xa4,0xd3,0x4f,0xd6,0x81,0xd5,0x2d,0x84,0x0a,0x16,0xba,0xfa,0x15,0x30,0x02,},"\x2d\x4b\x3a\xd0\xcc\x99\xf9\x83\xe4\x1f\x9b\x48\xc4\xa8\x18\xef\xf7\x5f\xcf\xb9\x3a\x12\x29\xec\x27\x40\xed\x19\xc1\x07\xd6\x21\xdf\x78\x05\x8d\xe7\xc2\xdd\x72\x51\xf5\xff\x45\x43\x40\x86\x5f\x6c\x86\xda\x65\x83\x1f\x66\x72\xdb\x23\x17\x26\xfd\xfe\x4b\x9e\xe3\x15\xd9\x3c\x72\x44\xa9\x20\xdf\x37\x05\x4c\x82\x44\x9d\x31\x0f\x89\x29\x32\xdd\xba\xd9\x4c\xc9\xbb\x39\xac\x89\x37\xcc\x76\xc9\x65\x21\xd3\xfd\xc0\x28\xba\x23\x41\x0b\x29\x02\x3e\x81\x38\xfd\x3f\x52\x43\x19\x88\x4e\xe5\xda\xd0\xd2\x34\xc8\xdf\x66\x1f\x88\x24\xbe\x47\x7e\x21\x69\x9f\x63\x69\xb1\x5f\xf3\xff\xef\xc1\x51\xaa\x55\x5b\x3c\x3d\x76\xad\xb4\x5f\x25\x67\x2d\x38\x0d\x47\x2b\x31\x48\xda\xbd\xef\x42\x45\xb6\x8e\x82\x85\x62\xf2\x5c\xc5\xb8\x1d\x9b\xbb\x24\x1b\xca\x9d\x19\x34\xea\x35\x3f\x95\xf7\xdb\xf3\x64\x64\x33\xe8\x1a\x35\x4e\x1e\x20\x56\xb8\x1c\x15\xaa\x1f\xa8\xed\x7a\x9d\x1a\xf9\x92\x38\xcd\x5a\x5a\xe9\xe8\x41\xc4\x8d\xc3\x48\xae\x1d\xe7\xc4\x1a\xca\x23\x32\x82\x36\xbc\x38\xb4\x7f\x47\xc7\x36\xb2\x57\xa3\x07\x8d\x57\xd5\x74\xb6\x47\xa7\xfc\x8c\x4d\x01\xbc\x50\x30\x21\x50\xd5\x03\x2b\xfa\xcb\x04\xbb\x0f\xd1\x55\xd9\x4d\x92\x06\x66\x77\x20\xe1\x80\xa6\x45\xaf\x46\x24\x59\xe3\x32\x6d\x46\x0d\xa3\xc4\x8e\x75\x72\x67\x8e\x19\x19\x26\x8d\x3e\x47\x40\xd6\x2a\x26\xf7\xc8\x55\x9c\x1c\x43\x9b\x4b\x0b\x0c\x59\x42\xa6\x20\xcf\xdb\x93\xcc\x68\xaa\x15\x52\x0f\xf2\x86\x42\x69\xd7\xa0\xc1\x55\x78\x0a\xdc\x6c\x18\x8e\x0b\x56\x5f\xb9\x59\x43\x19\xe6\xf5\x1d\x15\xca\xf6\xb2\x80\xe7\x15\x8f\x25\x79\x94\x07\xf3\xba\x0d\xd1\xce\xea\x64\xb9\x32\x6d\x2c\xfd\xef\x01\x7e\x1f\x17\x2f\x4d\xde\x0f\x7e\x46\x13\x50\x1a\xf0\x1e\xe0\xac\x30\x09\x5f\x48\xb5\x95\x90\x90\x2b\x1a\xec\xfe\x09\x34\x13\x91\x8d\x83\x5a\xdf\x96\x2e\xcf\x18\x58\x0d\x16\xf9\xfd\x4f\x6f\xa1\x09\x8a\xf1\xd8\xa2\xbc\x24\xdc\x86\xf7\x1d\x0a\x61\xff\x15\x00\x10\x86\x7d\x08\x69\x87\xb5\x1d\xd0\x30\xf5\x0a\xb6\xe3\x74\xb8\xe0\x11\x84\xb3\xe2\xb2\x14\xab\x1c\x7f\xdf\xae\xdb\xc5\x45\xe3\x8c\x3c\xd2\xf6\x98\x29\x79\x54\x1f\xe0\xff\x88\xbe\xd6\x75\x06\xda\x95\x72\x7a\xf1\xa2\x03\x8f\x32\x40\xae\x5b\xfd\x30\xee\x09\x21\x0e\x00\xfd\xcf\x2a\x06\x4d\x5d\xb4\x61\x49\x46\xbd\xa9\x72\xc6\x70\x08\x1a\x6e\xe6\xa1\x0b\x63\xf6\x73\xc8\x3c\x91\x5c\xa5\x57\x3e\x0e\xd6\x87\xb0\x06\x7c\x40\x07\x92\xa9\xbc\xc3\x34\x4e\x0e\x43\xf5\xdf\x63\xfe\xd5\xef\xa8\x5e\x9a\xaf\x85\xe4\xd7\xa2\xc5\x3a\x6c\x92\x82\x8e\x07\xfe\x63\xe2\xd2\x3f\x1b\xdf\x97\xd8\x4a\xdc\x36\xe9\xfc\x95\xfa\xad\xf0\x3e\x06\xd6\x5a\x19\xc5\xe2\x85\xef\xfd\x0e\xa0\xcf\xa8\x39\xd5\x5a\x0a\x0d\xbf\x6d\xa2\x87\x85\xc7\x7f\x5c\x04\xbf\xd5\x99\x74\xef\x37\x93\xcd\xc3\x98\xdf\x7a\x1b\xbc\x9c\xfc\xfc\x3a\x51\xff\xa9\xa2\x0d\x60\xc4\x7b\x24\x5d\xaf\xa3\xe4\x46\x23\xcd\x71\x1d\x77\x62\xc5\x0a\x67\xd6\x50\xc7\xe8\xc4\xfd\x3b\xeb\xc0\xc4\x98\xd2\x15\x2a\xb9\x82\x7c\x70\x0c\x7b\x28\x61\x56\x57\x49\xb5\x86\x4f\xec\x95\xb7\xf6\xb1\x99\x4e\x78\xd8\xf8\x5d\x06\x9c\xc1\x1f\x85\xbe\xd9\x71\x2f\x7a\x9f\x06\x0b\x0b\xf6\x75\x32\xe8\x8e\xb9\xdf\x3e\xb4\xa8\xd2\xfb\xba\xa8\x5e\xda\x92\x6d\x81\xc4\x9f\xb8\x6e\x73\x73\x1b\x7e\xd2\xa1\x90\x50\x78\x51\x3f\x7c\xa0\xfd\xcc\x3b\x1d\x57\x6e\x6a\x60\x12\x4c\x44\x61\x8d\xf1\x89\x0e\x16\x97\x94\x95\x6c\xb1\xec\x50\x1b\xa2\x04\x99\x70\xc8\xe7\x4c\xc1\x80\x06\x4c\x18\x44\x68\xbe\x4f\x08\x9a\x3a\xe2\x26\x3c\x85\x58\x63\xb6\x2c\x28\x31\x3d\xdf\x9c\xa8\x5b\xf6\x6b\x08\xa2\x64\x15\x5a\xd7\xc3\x28\x23\x8d\xfe\x61\x4a\x07\xed\xe9\x15\x5a\x09\xcc\xaf\xf9\x22\x92\x24\x93\x41\xba\xed\xcb\xe0\xe6\x46\x6e\x2c\x76\x04\x5e\x46\xda\xd2\xfc\x89\x9a\x17\x82\xe0\x09\x98\xe7\x9a\x83\xab\xfa\xe9\xb7\x06\xf7\x07\xf5\x8e\x73\x02\x03\xe1\xd2\xcc\xa0\x28\xc9\x22\xbe\xb6\xd1\x57\xfa\x7a\x98\x13\x2a\x92\x1a\x3d\xa2\x1f\x2f\x76\x9b\xb6\xc1\xf5\xf1\x9e\x9e\x85\xa1\x3b\x78\x1a\xf1\x41\x03\x9d\x51\x4e\xe1\x07"}, -{{0xf3,0xf8,0xd6,0x2f,0xee,0x3a,0xf3,0x75,0x66,0x96,0x30,0xcb,0xf0,0x63,0xbf,0xa9,0x30,0x18,0x9a,0xf1,0x36,0xcd,0x75,0x91,0xe2,0x4d,0x57,0x8d,0x73,0x66,0xbf,0x61,},{0x47,0x14,0xc6,0x04,0xaa,0x95,0xe1,0x82,0x8a,0x28,0x36,0x7b,0xa7,0x87,0x60,0xb5,0x89,0x64,0x31,0x68,0x3e,0xe9,0x96,0xcf,0xf9,0x68,0x71,0x77,0x32,0x91,0x95,0x3c,},{0x8d,0x6f,0x7c,0xee,0xb9,0x30,0x8b,0x4a,0x30,0x38,0x79,0xfc,0x6c,0xfa,0x5c,0xa8,0xe0,0x5d,0xfc,0x3d,0xef,0xc2,0xb2,0xcd,0x29,0x10,0xdd,0x4b,0x17,0xc9,0x4e,0xae,0xe8,0x45,0xab,0xe6,0x5f,0xd7,0x15,0xdf,0x05,0xb0,0x12,0x8e,0x43,0x16,0xe2,0x33,0x47,0x99,0xc6,0xe8,0xfa,0x74,0x7e,0xbc,0x8a,0x04,0x0c,0x74,0xf5,0xa1,0x48,0x0c,},"\xe1\xdd\x1f\xfd\x73\x7a\xc6\xdc\x24\xb3\xb9\xce\x3b\x79\xe8\x35\xbf\x69\x8e\x93\x13\x03\xd8\x09\xce\xa1\x78\x2d\xc3\xaf\x63\xa0\xd5\xe6\x73\x92\x82\x3d\x14\x39\xe7\xb6\xe3\x37\xb0\x1c\x8b\x21\x54\x34\xc2\x78\x2b\x3b\xe7\x44\x3c\xb5\xc8\x81\xe5\xfb\x6c\xf3\xbb\x24\x41\x28\xb4\xda\x6a\x6f\x42\xb2\xbb\x2c\xd7\x51\x29\xd5\x64\x18\x85\x43\x48\xc3\x39\xdc\xd9\x12\xb4\x55\x57\xa9\x15\xe9\xfd\x7f\x37\x91\x62\x36\x51\x0c\xb6\xc3\x31\xc1\x40\xb8\x7d\x22\x53\x11\x60\x0b\x8d\x13\x2a\xc4\x74\x73\x83\x9c\x72\x0f\x9f\xf0\xf9\xc1\xdc\xaa\x85\x81\x5a\x9d\x27\xb9\x75\x8c\xd9\x1d\xc5\xd3\xe5\x33\x26\xfc\xdf\xb2\x73\x0e\x52\xbe\x31\x03\x95\x7a\xc8\x91\x49\xa4\xc3\x00\x4c\xb6\x03\x8c\x0d\x80\xfa\x72\xac\x63\x0d\x33\x3b\xe5\xad\x4a\xdb\x58\x5a\xeb\x71\xae\xf1\xcd\xfd\x57\xb9\x15\xfa\xc4\xf1\xaf\x78\xe7\xa5\x97\xf8\xd1\xba\x06\x67\x2b\x19\xc0\xb6\x58\x08\xa8\xa0\x71\xff\x84\x09\x03\x43\x79\x58\x9f\x3d\x41\x30\x2d\x2d\x39\xb3\x31\x8e\x8c\x00\x90\xfa\x36\xcb\x95\x88\x57\xff\x5b\x21\x1c\x96\x66\xe2\x7b\xc8\x95\xab\x9d\x00\x6a\xba\xf5\x95\x0a\x03\xff\x17\xea\x98\x21\x78\xa4\x46\xdd\xa2\x46\x6f\x5a\x40\xb8\xf8\x95\x50\x9e\x4f\x4d\x4a\x6a\x27\x39\x99\x7f\xbd\x49\x68\xf8\x94\x36\xce\xe3\xd8\xed\xb8\xa6\xda\x9b\xd3\xd5\x5b\x06\x64\x90\xe8\x33\x9c\x78\x93\x5b\x77\x88\x3f\x95\xb9\x32\xfa\x5e\x6b\xb7\xdf\x30\x3b\xe3\x0f\xa5\x67\x24\x9f\xff\xb4\x73\xa1\xe4\x64\x32\x2d\x7c\x10\x3f\xe8\x22\x4c\x7e\xc5\x7b\xd3\x9b\xcd\x03\x0b\x96\x78\x7a\xeb\xcd\x20\xe9\xad\x65\x1c\xfa\x2b\xf0\x4b\xa7\x0a\x1c\xf6\x48\xe0\xa5\x44\x95\x67\x20\x2a\x93\x7a\x45\xbe\xcb\xb6\xfc\xde\xd3\x0c\xf9\xb5\xc7\x48\xf8\x82\xb5\xdc\x2a\x4d\x65\xbe\x69\xfd\x7d\x9c\x38\x1e\x83\xd0\xdc\x2a\x34\xb6\xde\xe9\x12\x20\xba\x90\x6e\x51\x2f\xcd\x63\x36\x8e\x2c\xe7\x33\xe4\x66\xb4\xb8\x2b\x84\xfb\x0c\x71\x7d\xc8\x94\x5c\xaf\x6d\x46\xac\x1c\x2f\x64\x18\xf7\x72\x9e\xf4\xc3\x5e\x40\x24\x22\xd6\x4b\x1c\x3e\xbd\x1b\x32\xa3\x0f\xc4\xc5\xee\xce\x7d\x44\x08\xff\x67\x9f\xf0\x1a\x1c\x7b\x03\xca\x51\x7b\xe5\x2e\x6a\xe7\x65\x0f\x7b\xad\x38\x90\x1e\x34\x8a\x55\x93\xbc\x99\x8f\x7c\xf2\xea\x97\x72\x9c\xb0\x04\xf5\x61\xb3\xb5\x8f\xe5\x98\x09\xa4\x1f\xd4\xb3\xb7\x66\x60\x90\x6a\xd9\xed\xa2\x3b\xf9\x25\x43\x7e\xf4\x52\xb1\x6f\x54\x0b\x3b\x80\xa3\x5a\x70\x93\xc2\x73\x4e\xef\xe6\xfa\x97\xd8\x81\xd7\x9e\xf5\xb7\x67\xd9\x88\x9f\x11\x84\x77\xb7\x3f\x58\xa4\xc0\xcb\x15\xe0\xac\x81\x01\x12\x05\x71\xca\x32\xce\x87\x1f\x30\x8a\xd9\x05\x7a\x80\xc8\x28\x15\x4f\xb1\xbc\x2b\x20\x1d\x0c\xd1\x00\x6e\x02\x2d\x44\x4d\xc9\x3f\x1b\xcf\x22\x4d\xb7\x4a\x5b\x37\x3e\x15\x3e\x85\x18\x54\x94\x8b\x6d\xa1\x47\xb7\x32\x87\xcf\x17\xd1\xfb\x72\xb4\x82\x76\x11\x10\x36\x09\xca\xb2\xa1\x77\x9e\x97\x93\xb9\xa7\x08\x20\xfc\x6f\x38\x28\xa6\x4c\x9e\xac\x35\xef\x7a\xa7\xb1\x76\x09\xd8\xef\xf8\xa9\xe5\x2e\x4e\xbc\xd8\x6b\x1e\x14\xfd\x14\x0b\xea\x47\xc6\xb8\xdd\xc4\x1e\x8c\xd2\x71\xeb\x92\x28\x7c\xbd\x06\x10\x51\x22\x42\xf7\x6a\x1e\xf3\xea\xc1\xe4\xbb\xbc\x1a\xda\xe5\x00\x34\xa7\xa2\x64\x7e\x08\xb2\xfd\x20\xaa\x93\xa9\x3c\xb2\xff\xde\xbf\x2e\x46\x1e\xcc\xef\xbb\xd1\xfe\x89\x4c\xe7\x0a\xdf\x79\x01\x73\xba\xe9\x6f\x5a\x55\xa1\x88\x7e\x9a\xe0\x9f\xce\xd1\xd4\x30\x6c\x29\x1c\x6b\x19\xec\xac\x47\x07\xe9\xef\x71\x3e\xa1\x8a\x75\x62\xc6\x67\x83\x26\x22\x89\x92\x07\x7a\x46\x69\x73\x49\x66\x10\x80\x00\xb4\x14\x4f\x45\xa0\xc3\xa2\x86\x3a\x4c\x6a\x3c\x07\x63\x2c\xb9\x3e\xb1\x97\xd2\x94\x88\x4d\x9c\xa3\xdd\x4b\x21\xf3\x9d\xb7\x07\xf6\x3a\x7f\x9a\x57\x0f\x7f\x0f\xeb\x99\xb2\xca\x7d\xa7\xdf\x92\xa1\x77\xab\xcf\xe8\x6e\xc6\x61\xd3\x0b\xcd\xcf\x15\x22\xbd\xb1\xfe\x11\x67\x32\x58\xdf\x7e\x46\xef\x4d\x32\x66\x65\x09\x31\x56\x55\x3f\x28\xb3\x56\x3f\xe7\x19\x2f\x72\xf5\xf9\xb3\x90\x3d\x79\xfe\xa0\x4e\x2c\x48\x8b\x46\x5b\x49\x78\xd6\x9f\x26\xe0\x5a\x59\xd5\xed\x4e\xf4\xca\xb2\x32\xac\xfd\x56\x4f\xc6"}, -{{0x86,0x5a,0x43,0x2e,0xcc,0xe7,0xe7,0x8c,0x42,0x70,0x9f,0xc1,0xe5,0x31,0xdf,0x5e,0x39,0x59,0x13,0x2b,0x2b,0x6f,0x31,0x8f,0xd1,0xc3,0x45,0x21,0xf9,0xa2,0x6e,0x3b,},{0xc7,0xa8,0xca,0xf8,0x93,0x0b,0x62,0x2a,0x50,0x13,0x37,0xf9,0x28,0x40,0xed,0x96,0x61,0x1a,0x32,0x20,0x80,0xfd,0xe5,0xe4,0x9f,0x0a,0x2f,0x6e,0x33,0xb8,0x82,0x83,},{0x32,0xbb,0x75,0x20,0xe2,0x63,0x9c,0x6c,0xca,0x19,0xa2,0xb9,0x83,0x6b,0x08,0xf8,0xb0,0x83,0xca,0x33,0x36,0x9d,0xdf,0x5f,0x9a,0x87,0x7d,0x4c,0x7a,0x9e,0xb0,0x5f,0x9c,0x3d,0xc3,0x4e,0xd4,0xcf,0xa4,0xb2,0x83,0xe5,0x19,0x22,0xb0,0x94,0x06,0x6c,0xe9,0xff,0xa4,0xd9,0xdf,0x62,0x19,0x10,0xca,0x37,0xb0,0xb3,0x7f,0xba,0xbb,0x0e,},"\xb2\x31\xb6\xd2\xec\xde\x49\xf5\x13\xb0\xdf\x25\xaa\xfc\x3e\x5d\xa4\x5b\x6a\x99\x58\xd6\x0f\x54\x64\xca\x59\x3c\x03\x00\x5e\xcf\x36\x1e\xf1\x69\x6b\xb6\xe5\x5d\x65\x38\xe3\x4b\x38\xf3\x24\xc2\x1c\xea\x5c\xc8\x1a\x00\x73\x27\x8b\xb9\x27\x27\xef\xf8\x1a\xf5\x61\x80\x2d\xce\xf3\x3b\xec\x10\xad\x65\x94\xe2\x2d\x9c\x44\x18\xaf\x39\x88\xa4\x3e\xd0\x87\xb9\x95\x4b\xf8\xd6\x28\x3e\x4b\xea\xe8\xc0\x96\xde\x66\x06\x75\x1c\xbe\xd6\x85\x84\x6c\x66\x30\xb9\x52\x8f\xf3\x64\xa7\xc4\x84\x64\x11\x34\x72\xc9\x86\x0b\x33\x71\x96\x3c\x91\x14\x95\xa9\xc6\x28\xa3\xe3\xe4\x7a\xb0\x99\x1f\x10\xdd\x1d\xd3\x31\x61\x52\x52\x62\xd6\x3b\xab\x64\x88\x19\xd5\x7d\x12\x69\xe1\x14\x82\x5c\x54\x34\xe6\xb2\x84\x5f\x42\x79\x5d\x4f\xb0\x83\xad\x79\x40\x1f\x2a\x07\x61\xc6\x34\xa5\x45\xae\xc7\xcd\xb1\x3b\x5b\xe4\x49\xf1\xd8\x29\x32\x63\x78\xed\x1f\x49\x3f\xe8\xc8\xe9\xb0\x68\xcc\x1d\xbc\xf1\x65\x55\x0b\x81\x32\xc3\x19\xda\xc4\x87\xb8\x7b\xb2\x2a\x54\xcd\xf6\x0a\xac\x71\x51\x61\x82\xa4\xe6\x9b\xa0\x83\xf6\xe8\x6d\x1a\x4f\x05\x08\x3a\x77\x61\x9e\xf2\x39\xf7\x02\x39\x6d\x7e\x46\x96\x8c\xc0\x4a\x3b\x34\xdf\x32\x65\xec\xf1\x61\x57\xab\xe1\x5c\x64\x2c\xd7\x42\x70\x96\xd8\xd4\x0d\xb0\x02\xd1\x96\xca\xb1\xbe\x30\x4b\xcf\x32\x2d\x9d\x1a\x24\x51\xb6\xc1\x1e\xea\xf3\xe8\xe3\xd9\x29\xf4\x80\xb6\xb7\x78\x04\xfe\x84\x49\x6c\xa7\x57\xe0\x43\x37\x91\x4c\xe9\x44\x75\xd7\x99\x0c\x74\x57\xc8\xe6\x06\xf8\xbc\x20\x7d\x2d\x48\x11\x9c\x80\xa6\xb4\xa9\xe0\x7b\x22\x92\x26\x57\x0d\xcd\x99\x49\x89\xfe\xcc\x69\x4c\x6c\x2f\xb5\x97\x5c\x9a\x6a\x9b\x74\xe8\x15\x9c\x27\xdd\x36\x77\xdf\xd5\xcb\x65\x1f\x1e\x32\xad\xfa\xfd\x81\x0b\x6e\x5d\x5e\xfb\xac\xe3\x1a\xe6\xd9\xb1\x21\x91\xe8\x93\x98\xda\x06\x3f\x13\x8b\x75\x84\xc5\x8e\x77\xe7\xf9\xfd\xd7\xfb\x9e\xf5\xd6\x8a\xe4\x9c\x6c\xca\xd2\x8d\x18\xbc\x60\x09\xd4\x18\x7e\xd1\x42\x02\x24\xa5\x65\x8a\xad\xf1\x35\xb5\xa9\x53\xf2\xdc\x3c\x8b\xfc\xaf\x66\x9e\xd5\xda\x38\xd0\x14\x4f\xd9\x66\x5e\x6f\x06\x77\xd3\xfc\x88\x04\xe2\x1c\xc2\x5f\xd5\xe0\x1a\x3f\x3f\xa8\x3e\x57\x1e\xb2\xf8\x82\xa7\x65\x9c\xe5\xd8\x64\xd8\xbb\x54\x07\x2b\x09\x86\xa8\x54\xf1\xa7\xf2\xd2\x72\x0d\xf8\x57\xe6\xd4\x21\x96\x30\x84\x1b\x1c\xcd\xcf\xc6\x72\x6b\x91\xbf\xc1\x7e\x18\xc3\xe3\x48\x0c\x23\xa2\xc0\x5e\x4b\xfe\xdd\xd4\xdb\x9e\xf4\x23\x88\xf2\x34\xfd\x3e\x4f\x3d\xad\x66\x60\x26\xe2\x78\x06\x12\x37\x41\x61\x31\x6a\xfc\x76\x65\xf9\x41\x1b\x6c\x5a\xa7\x89\x33\xb1\x80\x21\xc0\x12\xb0\x84\xf3\x24\x47\x60\xa4\xea\x1b\xcf\x31\xcc\x9f\x5c\x40\x44\xa9\xbc\xc7\x5a\x98\x67\x07\xf3\x8f\x45\xac\x1c\x7f\xa1\x39\xee\x95\xa6\xd8\xf1\x6c\x3c\x1e\x12\x76\x4c\x4b\x0b\x11\x94\xc0\xfc\x5f\x7e\xef\xf9\xa8\x48\xc4\x05\x0b\x0e\x65\x16\x84\x71\x9d\x43\x8a\xad\x56\x01\x91\x64\xfa\xe4\xf4\x88\x82\x20\x5e\xce\x0b\x99\x73\x67\x91\x08\x4a\x75\x3b\xa7\xd5\x6e\x88\xfc\xee\xa5\x33\x56\x6c\x3a\x2c\xa4\x8d\xd6\xef\xc4\x9b\x27\xdb\xf1\x4f\x26\x16\xce\xd6\x52\xe1\x38\x33\xab\x90\x28\xad\xa4\x54\x43\x1c\x89\xb3\xcb\x74\x41\xfd\xb8\xf2\x3e\x12\xb6\x0a\x1a\x10\x4a\x2a\x8c\xf4\xa6\x4e\x87\x8a\xa2\x6f\x54\xe8\x88\x1a\x4b\x15\x1a\x16\xa9\x6d\xe8\xb9\x80\x7e\x72\x93\x96\xeb\xe3\xe3\xd3\x94\xf8\x08\xbd\x74\xb7\x31\x2f\xe6\xb8\x4b\x13\x12\xaf\x8a\x1e\x41\x33\x59\x9d\x07\xbd\xf3\x3d\xb2\x1e\x01\x6b\x5c\x19\x6c\x1b\xa3\x11\x57\x08\xf5\x81\xbb\x82\xf4\xb5\x7a\x6c\xa1\xa5\x29\xe6\x4d\x19\x30\x42\xc1\xdc\x5f\xaa\x0a\x03\xab\xf5\x38\x49\xe1\xbd\xef\xba\xb6\x4b\x1c\xb6\x0f\xe1\x0a\x3f\xc1\x82\x3a\x23\x4c\x45\xf3\xb0\xdc\xe6\x6a\x46\x73\x9c\x01\xae\xad\x12\xde\x6f\x03\x13\xc7\xbe\x71\x40\x5f\x3f\xdc\x4a\x50\x7a\x9d\x84\xe8\x68\x6f\x6f\xc9\x26\x35\xdb\x0f\x78\x56\xc7\x37\x3a\x61\x8a\x72\x52\xc1\x29\xa7\x76\x0e\x20\x29\x54\x3d\x72\x62\x28\xc2\x1d\x00\xad\x4a\xc5\x2e\x5b\x1a\x6e\x31\x20\x09\x17\xf1\x5a\xf5\x15\x85\x9e\x08\xf2\xa7\x9a\xce\x67\x99\x1e\xd6\x90\x44"}, -{{0x2b,0xe1,0xf9,0x8c,0xe6,0x55,0x3c,0x91,0x5b,0x6a,0x09,0x33,0xec,0x0d,0xe3,0x47,0xb3,0x70,0xe2,0x9c,0xa2,0x94,0xe8,0x00,0x55,0x41,0x23,0x9f,0x63,0xb4,0x30,0xd0,},{0x7a,0x6f,0x44,0x69,0xc3,0x0a,0x63,0xf5,0x60,0xf9,0x87,0x34,0xfc,0x19,0x06,0xeb,0xd1,0x37,0x1e,0xd8,0x01,0x25,0xfa,0x3e,0x4c,0x86,0xb4,0x3f,0x26,0x2c,0xab,0xbc,},{0x8e,0x65,0x9a,0x3f,0x53,0x5a,0x58,0x9a,0x5f,0xd2,0xd2,0x17,0xcb,0xcb,0x8b,0x77,0x7e,0x5a,0xf2,0x0b,0x23,0x44,0x32,0xf7,0xda,0xc2,0x9f,0x81,0x0a,0x2b,0x47,0x37,0xc5,0xca,0xb1,0x0b,0x59,0xdf,0xd0,0x14,0x4f,0x30,0x90,0xf5,0xf9,0xe0,0xe6,0x67,0xf0,0xe2,0x1a,0x9f,0x57,0x3f,0xe1,0x3b,0x1c,0x28,0xec,0xcb,0xb5,0x31,0xa2,0x05,},"\x62\x68\x20\x1f\x93\x2a\x7c\xd3\xf8\x79\xae\x6a\xb8\x38\x55\xa2\xf5\x02\x91\xde\x78\x4d\x7d\x9e\x9a\xda\xa1\xb9\xaf\xed\x6f\x5a\xea\x20\x24\x0e\x59\xfe\x93\xe5\xa7\x08\x8c\x95\xec\x8e\x15\x74\x5f\xb8\xfd\xeb\x91\xdf\x01\x51\xc7\xb4\x60\x50\x67\x56\x1e\xa0\x8d\xbf\x00\xc4\xff\xe1\xfd\x0a\xcf\x10\x36\x56\xa7\xb5\x4f\xad\x0f\x25\xab\x16\xb4\xbd\xa3\x47\x17\x9e\xd1\xca\xdb\x7b\x98\xbe\x08\x95\xe0\x50\xdc\xbc\x37\x9d\x1f\xd5\x53\xe9\x97\x95\x92\x8b\x67\xa7\x52\xf8\xd2\xec\x1b\x9d\x66\xbf\x6a\xc9\x97\xe7\x44\xdc\x32\x7f\x24\x22\x30\xf9\x2e\x79\xae\x31\x27\x45\xa5\xab\x6d\xde\xc1\x99\x8f\xb6\x3d\xc4\xf6\xb0\x5f\x14\x72\x22\xd4\xb6\x5a\xce\x90\x17\xdc\x1b\xcd\x67\x5e\x49\x5f\x9e\xab\xb5\xf6\x02\x13\x3f\x6c\x72\xe0\x53\xe9\xf4\xae\x30\xd8\x72\xd7\x8b\xf7\x1f\xeb\xa3\x7a\xcc\x59\x50\x55\xc3\xbe\xa5\x3a\x05\xef\x0c\x7f\x21\x2d\xcf\x4e\x0a\xf8\x38\xea\x29\x28\xf4\xcd\xc9\xfd\xc8\x37\xda\x25\xf2\x69\x66\xb2\x45\x6a\xbe\xa6\x6a\x5d\xfb\x8f\xaa\x8f\xa0\x91\xf7\x33\x1d\x54\x36\xe9\x8a\x8d\x63\x23\xcc\x9e\x9a\x91\xd5\xa0\x2a\x49\x51\x17\x14\x84\x9b\x47\x45\x4b\xaf\x99\xc5\xf8\x50\xa0\x8d\x3d\x98\x41\x0e\x93\x9a\x9e\x89\xb1\x50\x53\x82\x5f\x3e\x9a\xee\x71\x44\x74\x16\x14\x07\x82\xe1\xbf\x3b\x0d\x8b\x4f\xf6\x2e\x77\xa4\xa0\x3f\x71\x0a\x8a\xb7\x6c\xf6\x35\x92\xc0\x5c\x44\x0c\x8f\x06\x47\x70\x09\x91\x63\xc1\x22\x70\xf3\xd5\xec\x9a\x6b\xc9\x71\x5b\xff\xfe\xc7\x69\x61\x1d\x21\xfa\x00\x3c\x3c\xc8\x35\x6c\x97\x5d\x37\xb6\x2b\x88\xaa\xbb\x85\x97\xda\xca\x19\x6c\x96\x48\xa3\x1d\x15\xbb\x0b\x86\xcf\x07\x0e\xe0\x1e\x51\x1e\xf3\x73\xb4\xa4\x4c\x6a\x00\x16\x0a\x79\x7f\x2e\x82\x0b\x71\x6f\x5c\xa6\x44\x64\xe4\x18\x9a\x00\xfe\xe9\x78\xd3\x5b\xf2\x04\xf7\x1d\xb1\xf5\x01\xf9\xb6\xe5\xdf\xc8\x21\xa8\xaf\x5d\xbf\xef\xd3\x53\xad\x36\x81\xf9\xbc\x3c\x22\xc6\x7c\xb2\x11\xb4\x30\xb6\xa5\x5f\x3e\x73\xda\x7c\x3a\x07\xce\xb7\xd2\xfe\x25\x4b\x10\xc2\x70\x3a\xb2\xe2\x29\x4d\xd0\xd3\x15\x2d\xc7\xb2\x1a\xab\x87\xb1\x50\xf7\x37\xa9\x47\x46\x3f\xb2\x04\x17\x5d\xe8\x54\x32\x36\xfb\xb0\xda\x5c\x7d\x48\xc5\x7f\x61\x74\x4d\xe6\xf9\x84\xaa\x8e\x61\xb9\x70\xc6\x2d\x0e\xeb\x84\x9d\xa7\xe8\x9a\x61\x22\x2d\x43\x20\x79\xcb\xcf\x5f\x8a\x2b\xa9\x30\x30\x16\x83\xc0\x78\x5c\x26\xfd\xf8\x5d\xa3\x02\x08\x74\x60\x45\x99\xac\x6c\x84\x7e\xc2\x60\x86\x58\xb5\x78\x8c\x7b\x8d\x3a\x37\x44\xfd\x54\x42\xe2\x4c\x8e\xec\xcd\x42\x07\x56\xbd\xd8\xb8\xa7\x7c\xfd\x80\x58\x96\x05\xdc\xed\x9a\xfd\xa2\xbd\xb6\x30\xa0\xcb\x61\x2f\x73\x9c\xe6\x17\xd5\x4e\xde\x6c\xcf\x36\xaa\x31\xe7\xe3\x73\xd8\xa0\xfb\x1b\x7c\x99\x06\xf7\x6b\x5f\x9d\xe8\xc2\x68\x91\xde\x00\x6e\xb7\x97\xea\xd4\xa8\x6f\x70\x16\xf3\x4b\xcd\xe9\x2f\x94\xac\x3e\x92\x0b\xa5\x8d\x6d\xff\x77\x20\x78\xd8\x02\xa9\x4f\x56\xcb\x26\xbf\x79\x4f\xd9\x0c\xa0\xad\x4f\x2e\x7a\xcd\xc5\x92\x9b\xc7\x36\x49\x97\xde\xd9\x8c\xa6\x9c\x57\x39\x91\xbb\x9a\xb8\x5f\x23\x5b\x63\xe7\x6f\x77\xe0\xab\x45\xe7\x89\x12\x38\x98\x69\xaf\x21\xe7\x4e\x66\xf7\xc4\x56\xb8\x27\xe6\x70\xbe\xb0\xf0\x72\x66\x88\xbb\x1f\x90\x36\xd3\x8d\xa0\x7d\x69\xea\x36\x66\xf7\x6b\xd6\x05\xd8\x2e\x2d\xd6\x38\x7e\xce\x6e\x82\x4a\x56\x97\x00\xf0\x1b\x19\x5d\x1a\x9b\xdc\xb0\xf9\x6a\xb5\xc5\x4e\x06\xc2\x11\x9b\x40\x6b\xc4\x88\x84\x80\x66\x04\x18\xbb\x42\x88\xea\x2f\xda\x96\x63\x1b\x0e\x1f\x60\xac\x86\x1d\x6c\xcc\x4c\x84\x4b\x64\x7a\x7d\x74\x03\xbc\x2d\x15\xba\xfe\x4a\xf6\x77\xe8\x56\xfe\x0d\x2b\x5f\x66\x3b\xe4\xe4\x80\xb3\x8f\x6b\x76\x6a\xdc\xd3\xd0\x52\x98\xef\x13\x98\xd0\x4d\x15\x23\xa6\x8b\x91\xdd\x31\xcf\x5d\xc4\xb7\x3d\xec\xbf\xd7\x21\x3f\x98\x1b\x20\x7e\x1f\x6e\xf2\x25\xd7\x94\x8a\x1a\xa1\x7d\x8d\x57\xa1\x12\xf1\xd4\x46\x8d\x2d\x28\xf7\xec\x2e\x54\xb7\x4a\x69\x2c\x59\x58\x02\x2e\x82\x03\x1a\x41\xb3\x15\x09\x0e\xd4\xd5\xbd\x7b\xd0\xb4\x51\x47\x63\x38\xf7\x39\xa7\xd7\x03\x1a\xf2\xd3\x6c\xaa\x09\xff\xdb\xb7\xc3\x96\x50\x7c\x75"}, -{{0x10,0xbb,0xe6,0xe7,0x61,0xa7,0x5c,0x93,0x5b,0x51,0x7f,0x09,0x36,0xfe,0xcb,0x9e,0xc6,0xfc,0x21,0x5e,0x58,0x13,0x08,0x00,0xea,0x18,0xd1,0xff,0x44,0x2a,0x4f,0x13,},{0x86,0x43,0xdd,0xf8,0xaa,0x8d,0x9c,0x8a,0x78,0xb6,0xeb,0x69,0x9f,0xd2,0x0a,0x57,0xf6,0xf1,0x86,0x36,0xb0,0x6c,0xe6,0x9d,0xac,0xdc,0xa1,0x26,0x7a,0xcb,0x39,0x54,},{0xf0,0xf3,0x57,0x41,0x03,0x73,0x31,0x3b,0x7c,0x62,0x52,0xd6,0xd9,0x66,0x00,0x36,0x0c,0x23,0x75,0x2d,0x43,0x1c,0xa8,0x07,0x5b,0xcf,0xb7,0x72,0xd4,0x9c,0xd6,0x09,0xb6,0x5c,0x9c,0xd8,0x38,0xd6,0x34,0xd8,0xd9,0xb9,0x5d,0x1e,0xe3,0x0e,0xde,0xcc,0x13,0xe3,0xca,0x99,0x7b,0x24,0x37,0x30,0x3f,0x8a,0x33,0xa1,0xff,0xc8,0x33,0x06,},"\xe8\x10\x8c\x6d\xe4\x13\x37\x33\xdc\x19\x9a\x73\x39\x2e\x22\x6f\x71\x2c\x36\xa2\x4f\xa9\x1d\x6f\xb0\x9f\x92\xdf\x21\x8d\xeb\x2d\x28\x30\xa6\x68\xfd\x69\x4b\x48\x09\xd0\x25\x35\x07\x23\x12\x47\xc7\xf2\x58\xb4\xd6\x5c\x56\xbb\x69\x34\x5e\xf6\xaa\x97\xe7\xc5\x9e\x81\x53\x77\x5a\x5a\x3c\xf1\x09\xc4\xbc\xa9\x81\x55\x69\xda\x69\x32\xe8\x21\x83\x42\x5b\x42\xd7\x48\x3c\x9d\xbf\xcb\xd8\xeb\x38\xc8\x47\x29\x57\x1e\x8e\xc9\x39\x82\xc3\x17\x71\x67\x59\x59\x8c\x4f\x6a\x1b\x7f\x8d\xa7\x30\x6a\x78\x15\x72\x1c\xaf\x02\xe7\x02\x46\x71\x23\x14\xf7\x66\xbe\x9c\xb1\x77\xcd\x2f\xa3\xbd\xa2\x2c\xd6\x76\xc5\xd2\xe8\x6e\x8d\x79\x8f\xd3\x4f\x54\x3c\x9b\xe3\x12\x96\x51\xf2\x73\xf4\x84\xf0\xb9\x46\x7b\x14\x09\x55\xcd\x29\x81\xff\x26\x03\xc0\xbd\xbb\x43\x6a\xc0\x95\x5a\x11\x6c\x5e\x5f\xc3\x04\x25\xe1\xfe\x78\xf6\x41\x0f\x6e\xf7\x57\xf6\x04\x66\x88\x54\xba\xe7\x9b\xfe\x22\xe1\xa8\x5c\xe5\xee\x5d\x64\x34\xb4\x61\x01\x20\xea\x7e\x5d\x3d\x13\x7c\xe2\x07\x51\x4f\x85\x34\xad\x9b\xf3\x92\xb7\xdc\x53\x55\x51\x4b\x59\xf8\x35\x46\x6c\x8e\xb5\x6f\x44\xed\xdc\x5b\xad\x20\xcf\x0b\x48\x0b\x2e\x82\x2a\x6f\x46\xfd\x95\xf3\x0f\x18\x3c\x7b\xb3\x14\x3e\x4e\x61\x00\xe2\xdb\xc9\xf2\xbf\x0d\x43\x07\x3e\x0f\xe6\x5f\x01\xbc\xce\x6a\x1a\xe4\x01\xc1\x25\x41\xbe\x3a\xe6\x8c\xde\xac\x2a\x4a\xc7\x1f\x16\x63\xb5\xfd\xfc\x2e\x50\xf0\xe0\x77\xfb\x3a\x0a\x8b\x8e\xee\xad\x62\x7c\x1c\x3e\x79\xdd\x73\x61\x04\x6f\x7e\x57\xc1\x74\x36\xc3\x2d\xc4\x43\x2f\x05\x00\x28\xcc\x7a\xa4\x40\x8c\x2d\x29\xd1\xd7\x99\x8f\xdc\xdd\xa3\x2b\xb3\x2f\x70\x4d\xc2\x63\xdb\x9b\x8e\x06\xc5\x76\x30\x87\x0f\x8b\xb6\xec\x66\x1f\xde\x1b\x7d\xa9\x4d\x53\xb0\x47\x70\x1a\x45\x88\x47\x8c\x1c\x66\x23\x46\x74\x1a\xea\xc4\xc2\x53\x38\x55\x6a\x3d\x84\x8d\xe5\xb2\xa2\x3e\xce\xa6\x1b\x77\x6b\xd0\xe8\x03\x7e\xfb\x85\x01\xef\xf2\x39\xc7\xfa\xcc\xa6\xc8\x36\x7e\xd7\xc8\xad\xce\x91\x9f\xef\x1a\x15\x5a\xe0\xd5\x47\x8a\x98\x00\x2c\x95\xa1\x6f\xbf\x4c\x0e\xd0\x16\xea\x5d\x38\x66\xfe\x1d\xe4\x54\x83\x2a\x4e\x95\x65\x97\x6b\x60\xb3\xdd\x2e\xaf\x7f\xee\x61\x2f\x2b\xc0\x40\xd9\x39\x75\x43\x5e\xeb\xd1\x2f\x06\xeb\x09\xec\xea\x2c\x66\x76\x83\x08\xf5\x8c\x77\xac\x51\xed\x7b\xd2\x16\x36\xfc\x9c\xc3\xfd\x14\x87\x0b\xd0\x6b\xdf\x12\x8a\x81\xb1\x47\x92\xe6\x08\xc4\x7e\xa2\xd5\x35\xca\x7a\xa2\x1e\xb8\xa8\xa5\x6d\x76\x99\x16\x63\xa8\x19\x0a\x95\x05\x7d\x33\x67\x1e\x73\xc7\xcb\xce\x5a\x98\xd3\x1e\xf0\xd7\x3b\xd0\xb1\x63\x78\x7b\x7f\xdc\xd2\xdd\xfc\x72\x96\x0f\x2b\xe3\x20\x84\x6d\x4b\x29\x08\x0d\x7a\xeb\x5b\x7e\xa6\x45\xa2\xad\x5a\x59\xc0\x12\xbf\x7b\x95\x15\xd8\x59\xe1\xc1\x47\x2e\xf8\xa4\xd3\xc9\x5e\x71\x1a\xf9\x7a\xe4\x61\x8e\xfb\xab\x3d\xff\xe8\x8c\x9f\x6a\xf4\xa0\x9b\x0e\x73\x38\x7e\x25\x1b\x77\xd7\xbf\xf5\x21\x4f\x79\x18\x62\xdb\x69\x88\x41\x1e\x2a\xe2\xc7\x5b\xf2\x8d\x28\x60\x2a\x63\x7c\x26\xf4\x9c\x18\xd3\x09\xd2\xfc\x58\xa1\x26\x66\x7a\xd3\xc2\xec\x16\x0c\x99\xba\x40\xfb\xda\xc1\x7e\x7e\x4c\x21\xa5\xd5\x07\x85\x97\x62\xeb\xa0\x9c\x41\x60\xdf\x66\xf5\xfe\xef\xe6\x71\x5a\x28\xc5\x29\x6c\xf4\x3e\x5e\x77\x1f\x31\xfc\xe5\x13\x3b\xe9\x7c\xab\x57\x30\x1b\x4c\x9d\xf9\xcd\x9a\x4a\xcf\x1c\x33\xfa\xc9\x46\xfa\x15\x96\xfa\x65\xc8\xf3\x65\x8b\xe4\x7a\x47\x3a\x62\xc5\x21\x81\xec\xa1\x83\xe4\x24\x6c\xd6\x24\xd8\x78\x3d\xcc\xe5\xfd\xcc\x1f\xea\x17\x3f\x80\x71\xf7\x07\x4f\x55\x89\x7d\xe9\xbf\xe8\x4a\x6c\x4f\xdf\x80\x2d\x50\x26\xb8\x14\x5e\x6c\x8c\x89\x50\xaf\xc5\xb4\x0f\xd0\x35\x6f\xc5\x5e\xe1\x7e\x1f\x85\x3a\x4c\x2f\xcc\x34\xa1\x36\x9b\x87\xd2\x8d\xc2\xfd\x20\x10\xf1\x99\x03\xaf\xf8\xe4\x6d\xe0\x49\x38\xf4\x94\x82\x45\xd5\xb4\x25\xd0\x74\xac\xdf\x2b\xd8\x0b\xfc\x37\x35\xcc\x34\xa2\x25\x90\xf1\x94\xaf\x93\x13\xee\xf4\xab\x5f\xde\x61\xf1\xf9\xb5\x85\x78\x63\x8f\xcb\x4f\x28\x50\xb2\xfc\xe6\xe0\x3d\xb4\xd0\xa8\x34\x84\x81\x63\xc4\xb2\x7e\x12\x9f\x5c\xc7\x4f\x67\xf0\x08\xa2\x71\x2d\x1d"}, -{{0x18,0x6d,0xcc,0x7e,0xfc,0x5e,0xd7,0xe6,0x1a,0xe5,0x3d,0xc4,0x20,0x93,0xba,0xe8,0xf1,0x5d,0xd9,0x9f,0x0f,0x03,0x33,0x26,0xc5,0x76,0xff,0x75,0x69,0x50,0xd0,0x6d,},{0xc8,0xd1,0x41,0xac,0xb6,0x42,0xaa,0x9b,0xfb,0xd5,0x43,0x27,0x7c,0x2d,0xca,0x8a,0xa9,0x88,0x8e,0xef,0xf0,0x45,0x43,0xb3,0x78,0x9b,0x21,0xf2,0x6a,0xeb,0x0f,0x71,},{0x89,0x45,0x06,0x97,0x87,0xc1,0xc6,0x76,0xa8,0x4a,0x70,0x3c,0xae,0x1e,0x0b,0xac,0xae,0xff,0xd3,0x3e,0x91,0xbe,0xc3,0x60,0x3e,0x1f,0x13,0xfb,0x17,0x0e,0x31,0xe6,0xd7,0x04,0x9e,0xda,0x2b,0xf6,0x27,0x18,0x0f,0x45,0x6c,0x3f,0x7a,0xab,0xfc,0xd3,0x6c,0x49,0xa8,0xc0,0x4f,0x8a,0xe6,0x92,0x9e,0xc5,0xad,0xa0,0x7b,0x65,0x72,0x08,},"\x97\x43\x64\xd6\xc8\x38\x84\x2c\xcc\x4e\x74\x9e\x6a\xfd\x53\x71\x70\xdc\xd8\xcc\x50\xd6\x66\x54\xd1\x05\x48\x23\x39\xca\xbd\xf7\x4e\x32\x93\x5e\xe2\x19\x27\x2e\xa1\x68\x4f\xb9\x3c\x1f\xab\x42\xb5\x63\x18\x39\x24\x35\x91\xbd\x07\xd3\xbe\x94\x9b\x0d\xd1\x5e\x31\x96\xdf\x19\x6b\xa7\x52\xad\x11\x21\xac\x71\x12\xd5\x66\x94\x4e\x15\x3a\x4e\x06\x19\xb3\xa2\x32\x24\x1f\x02\x0b\xe0\x71\x9f\x6b\xec\x91\x8b\x26\x82\x8e\xb1\x67\x0e\xcf\xc7\x3c\x66\x84\x4e\xa3\xe4\x04\xc6\xa2\xfc\x01\xbe\xb4\x03\xc9\xd6\xca\x55\x1a\xd8\xa6\xe7\x1f\x46\x64\x7f\xa6\x05\x3f\x03\x14\xf8\x12\x4d\x8d\x2b\xc1\x2c\xc8\xfa\x8d\xb9\x5f\x2b\x73\x53\x75\x20\x1b\x81\x6a\x9c\xf4\x0f\x83\xee\x4b\x86\x71\x61\x80\x32\xde\x22\x9c\xe7\x62\x71\xd0\x3d\x26\x72\xa1\xae\x4a\x28\x8c\x85\xdc\xd2\x7f\xb8\x45\x2a\x81\x32\xe9\xff\x29\xe1\xe8\x9b\xf1\x1b\x1c\x83\x51\x92\xc0\x4b\x13\xbe\x14\xf3\xcd\xe5\xd3\x7c\xe9\x6f\x1d\xc2\xa9\xcc\xda\x0c\x4d\x73\x7b\xca\x1f\xa2\x20\xd2\x1b\xf3\x60\xb9\x05\x15\xbb\xd2\x26\xbb\x2a\x6c\x8d\x5f\x2a\xb0\x18\xd4\x08\x4e\x24\xee\x33\x3c\xe4\xe3\x9b\xcb\x6b\x46\xe7\xae\xb4\xdb\x9b\x6c\x65\xb2\x44\xd9\x82\x82\x3a\x77\x0f\x9c\x62\xa0\xbd\xe2\xcb\xb7\xec\x36\x84\x0d\x45\x51\x87\xfa\xff\x4e\x48\x8a\x5c\x60\x8e\xbd\xb7\xdb\x84\xd8\x7d\xad\x38\x67\xe3\xb0\xd0\x4b\x64\x71\x5e\x16\x56\x0a\x62\xf1\xee\x03\xdf\x61\x83\xfd\x5e\x37\x55\x5d\xa1\x97\x2f\xca\x06\x2d\x12\xbb\x84\x20\xe0\x82\xda\xcb\x8d\xeb\xb9\xc1\x43\x85\x41\xd0\xda\x24\x64\xef\x7e\xc5\x22\x63\xfb\x9b\x9a\x4c\x46\x9c\x83\x32\x3e\x48\x19\xdf\xdf\x4f\xa0\xa7\x70\xc3\xa7\x09\x25\x4e\x05\x31\x48\x30\xe8\x7f\xbb\x67\x36\xc7\x2d\x9d\xab\xe0\x1a\x31\x0e\x91\xeb\xbf\xae\x76\x7a\x1f\xcb\x62\xf6\x4f\xa3\xba\x8d\x53\x40\x0d\x64\x69\xad\x1c\xcb\x81\x1f\xb9\xe1\x15\xf1\x41\x27\xb1\x3e\x83\x64\xaa\x2f\xe8\x0b\xbc\x88\x6a\x10\xdf\x1b\x9c\xc4\xae\x46\x01\xf5\x46\x1a\xf0\x91\xf5\x26\xd2\x72\xda\x9b\x20\x38\x57\xa4\x44\x7e\xab\xde\xf4\x39\x83\x04\x96\xa5\x75\x9c\x21\xde\x65\xba\x3a\x3c\x8b\x8e\x93\x9c\x46\x13\x32\xa9\x24\x85\x2c\x20\x5c\x77\x11\xf3\xa6\x8a\x23\x67\xa9\x45\xde\xf4\xfb\xe5\xf8\x1c\x60\xcb\xb7\xe3\x94\xa2\xa4\x9b\xe9\xec\x2a\xae\xb1\xf3\x30\x57\x59\x79\x44\x6a\xd9\xd0\xd5\x4a\xbd\x43\x6f\x28\x60\xf0\x42\x34\x26\xf4\xbb\xc2\x6b\x3b\x9f\x65\x0d\x69\xb1\x00\x72\xd7\x47\xa3\x9e\x47\x8f\x45\x5e\xaa\x12\xc7\xc6\xe1\x2b\xfc\x45\x36\xa3\x59\x43\x44\xbd\x02\xb6\x20\xe3\xe2\xb4\xe0\xd5\x34\x08\x9d\xd7\xb0\x4f\xa6\x34\x80\x45\x67\x58\x6c\x62\xbe\x03\x91\xc7\xbd\xb0\xa9\xfb\xc1\xef\x3b\x33\x21\x1e\xdb\xf8\xef\x58\xc2\xb7\xa4\x9d\x06\x66\x79\x59\xd7\xe5\xd4\x46\x71\xee\x73\x57\xa1\x0b\xa0\xcb\x1a\x44\x5a\xe5\xd7\x09\xce\x25\x5e\x92\xde\x71\x59\x75\xaf\x94\xb8\x9d\x4a\x29\xc7\x1f\x9d\x88\xc8\x5b\x6c\xd1\x1d\x8b\x33\x5b\xf8\xf2\xc6\x58\xe6\xdd\x7c\x3f\x6c\x80\xad\x4d\x0e\x5a\x6c\x87\xdb\xa7\xb5\xb8\xa8\xa4\x7e\x72\xf4\xd1\xd3\xc7\x43\x63\x1d\xf9\xad\xfc\xfa\x45\xce\xe0\x49\x8d\x5a\x44\xa9\xf7\x5c\x83\xb7\x5b\x2a\x3c\x23\x0f\xf0\x76\x7d\x38\x88\xf9\x41\xee\x1b\x66\x24\xdd\x0e\x12\xd0\x6e\xd1\xab\x8b\xb1\x35\xff\xd3\x79\xe9\xde\x37\x88\xbe\x54\x1a\xad\xb2\xd6\xa7\xcc\x60\x13\x16\xf2\x1e\xb9\xaa\xa9\x22\xf5\x6a\x8e\x35\x26\xc9\xbd\x11\x77\xfe\xfc\x2f\xbe\x3e\x43\x0b\x62\x8e\xeb\xd6\x66\x1e\x3b\xa2\xd6\x31\xc6\xa8\x42\x2c\x24\x1e\xcd\x96\x99\x72\x41\x2f\x74\xda\x6b\x12\x43\xbf\x0f\xbe\xe8\xa8\x4d\x52\xe4\x0a\xee\x3f\x1e\x4f\xc8\x31\x40\x2c\x62\xf3\x57\x6b\x22\xe8\xe3\xc3\xdc\x4e\x16\x0b\xc3\xb6\xb9\xd2\xce\x00\x58\x53\x81\x2e\xaf\xc0\xa4\xe2\x5b\xa7\x12\x27\x9b\x00\xba\x3f\x91\x30\xff\x36\xe3\xef\x19\x71\xdd\xe7\x50\x8b\x27\x92\xfe\x64\xd4\x75\x68\x8f\xc6\xf3\x31\x3a\xad\xb7\x85\x30\x2e\x6b\x7f\x9a\x84\xf2\xdb\xc2\xf3\xcf\x06\x0e\xe0\x8b\x46\x37\x36\xf8\x36\xdb\xb2\x62\xd3\x29\x68\x4c\x20\x84\x92\xd1\x7d\x81\x12\x21\xbe\x02\xb6\x5e\xe2\x8e\x11\xb5\x46\x92"}, -{{0x07,0x05,0xb3,0x36,0xc8,0x9c,0xa3,0x5f,0xfd,0xde,0x0a,0xf0,0xf9,0x06,0xea,0xcf,0x62,0x3c,0x56,0xc3,0xf7,0x67,0x38,0x16,0x8e,0x76,0xfc,0xd5,0x88,0x2d,0xf7,0x9e,},{0xea,0xaa,0xf2,0xa1,0x5f,0x44,0xb6,0x34,0xce,0xf1,0x5a,0x63,0x8b,0x80,0x20,0x7f,0x61,0x09,0x9a,0x07,0x96,0xf5,0xd4,0x3f,0x3e,0x9d,0x04,0x8e,0x6a,0xe7,0x96,0xc1,},{0xd4,0xa9,0xba,0xe8,0xec,0xc4,0x72,0xc3,0x76,0xba,0xb8,0x05,0xc2,0xce,0x0c,0x1c,0x2e,0xd5,0xfc,0x77,0x37,0x15,0x46,0x8c,0xb1,0xa4,0x93,0x45,0x64,0xda,0xce,0xcf,0x43,0x8b,0x1d,0xd2,0xac,0x1b,0x5c,0x5e,0x33,0x6a,0x1e,0x20,0x70,0x1d,0x5d,0xcf,0x3c,0x8e,0xe3,0xad,0x22,0x3b,0x13,0x9f,0xa9,0x0a,0x1b,0x55,0x2e,0x1b,0x77,0x07,},"\x61\x6f\xe1\x5f\xcc\xb3\x31\x0f\x9e\xc7\x45\x64\x47\xda\xda\xf8\xe0\xa5\xfb\x26\x9b\xe1\x69\xb0\xc3\xea\x2c\xfd\xaa\xa5\x5d\x37\x93\x7f\xe7\x5b\x78\x32\x4a\xc2\x78\xa6\x50\x47\xe0\xae\x4f\x32\x7e\x97\xef\xfc\xb7\xbe\xd9\x1d\x09\xda\x72\x0b\x0a\x10\x1b\xe9\xe9\x6d\x0b\xa8\x5b\x1f\xf4\x9d\x8d\x1d\xf3\x62\xd3\x45\x4f\x0d\xb6\x82\x55\x96\x10\x1c\x97\xe5\xda\xca\xd0\x7e\xc4\x92\xd3\x0f\x2d\x0c\xb7\xe7\xde\x4e\x74\x4b\xb6\xa6\x10\x0b\x75\x4d\xa8\x47\x41\x1d\x09\xaa\xce\x8d\x5d\x41\x07\x58\xb8\x30\x87\xdb\x4b\x5e\x62\x97\x97\x9a\x21\xfb\x65\xaf\x39\x09\x52\xc4\xf9\x36\x26\x0e\x72\xd7\xc7\x83\x27\xb9\x4a\xa6\xcd\x61\x72\x78\xb0\xce\x9e\x1b\xd3\xfb\xed\x93\xb6\x9b\xc6\x49\x85\xdd\xe0\xe2\xc4\x35\x7b\x50\x2f\x05\x5e\xe7\xb0\xa0\x38\x84\x74\xda\xe0\x2d\x6c\x1a\x73\x1f\x87\x78\x5d\x75\x3a\xeb\x0d\x9c\xfd\xf8\x50\x02\xdf\x56\x6f\xc2\x50\x7d\xe7\xba\x6f\xd0\x35\xbe\xe1\x7a\x2e\x80\x8b\x4a\x75\x88\xc5\x83\x37\x5c\x82\x40\x7a\x40\xae\x9e\xeb\xdf\x94\xdf\x2f\xb8\xca\xbf\x17\x60\x6c\x43\x9e\xa7\x04\x59\xb2\x12\xaa\xe4\xa3\xf5\x30\xec\xad\xc5\xe8\x8e\x25\x48\xfa\x64\x3c\x7d\xdf\x50\x63\xb2\xe1\x06\x73\xe5\x9d\x07\xfe\x90\x68\x92\xb6\x7e\xb5\x8f\x93\x88\xa5\x6b\x37\x04\x52\xe9\x97\x77\x55\xfc\x04\xdf\xbc\x77\xda\x6c\x05\xbe\xdd\xeb\xf0\x36\x52\x56\xb5\x2c\x9a\xef\x8a\x82\x17\x3b\x8c\x89\xfb\xd9\x8c\xea\x36\xa8\xb8\x96\xfe\x66\xd3\x7c\xa7\x9b\xec\x7f\xbf\xe9\x58\xfe\x89\xf6\x76\x50\x85\xb3\x35\xdc\x77\x03\x43\xe2\x30\xca\xdd\xfa\x28\x33\xda\xa6\x62\xfe\x82\x08\xdd\x88\x5a\x6f\xdf\x72\xe3\x6e\xcf\x22\xbb\xbb\xcb\xe7\x9d\x37\x06\x50\x23\x69\x40\xbc\x2e\x6d\x4a\xc7\x4f\xe4\xd5\x54\xc9\xbc\x23\x2f\x07\xd2\xaf\x62\x20\xd1\x57\xbd\x2d\xa6\xa6\x61\x2a\x08\x1b\x4c\x99\x04\xa2\x86\x9b\x13\x7e\xe3\xa0\x85\x6f\x12\xb2\xeb\x87\x62\xdb\x94\xed\x0b\xa1\x36\xf2\x3e\x7f\xb4\xbd\x1f\xcd\xee\x10\xdd\x84\xe2\xcd\x3b\x0a\x49\x14\x8a\xc7\x4d\xb4\x66\xdb\xee\xf8\x1e\x6a\x8c\xe0\x86\x11\x02\xde\x9b\x1a\x3e\x1d\xcf\x5c\x6b\x03\x08\xa8\x2e\x3a\xc7\xc2\x28\x3c\x7c\xc2\xf3\x4f\xfa\x14\x5b\x9f\x74\xb7\x99\x04\xb3\x2b\x79\xe9\x60\xb8\x14\xaa\xde\x63\xa0\xdf\x01\x67\xdc\xd2\x4e\xd9\x0a\x8d\xa7\xb9\x34\xc7\x72\x93\x2f\x5a\x47\x8f\xe2\xa7\x2f\x94\x5a\x13\x09\x6e\xc3\x7c\xe7\x64\xb5\x81\xeb\x89\xe5\xf6\xb2\xbd\x7e\xb8\x8b\x85\xa8\x95\x87\x77\x4d\x45\x8c\x58\xcd\x87\x94\x57\x97\x3d\x64\x8e\xf7\x71\xc5\xf1\xde\xb2\x7a\x0c\xc5\xb2\x92\x46\xac\x2f\xa1\x2d\x18\xdd\xc6\xb9\xf9\xac\x9c\xf1\x46\xc3\xf2\x2b\x1e\x44\x99\xad\xee\xfb\xcd\x22\x49\x74\x0e\x13\xa2\x24\xe7\xb6\xb3\xef\x15\x60\x5e\x7e\x74\xe6\x8d\x7b\x72\x64\x24\x09\xb9\x0c\x4e\xc1\x61\xeb\x24\xc9\xb4\x0f\xf9\xc7\xe6\xe5\xda\x98\x32\x2a\xca\x52\xc4\x6a\x8d\xdc\x19\x0f\x1c\xab\x15\x7c\x4c\x76\x19\x60\x1a\x6b\x33\xdf\x6a\x50\xda\x66\x1b\xc7\x53\x60\xdf\xf6\x97\x50\xd3\x45\x74\x09\xcc\x02\x41\xc3\xe8\xc4\xb3\xe5\x06\xd4\x26\xaf\x52\xb7\x02\x31\xcd\x6c\x91\x26\x0c\xc4\x31\xe4\xcc\xfd\x49\x6c\xa1\x4c\xea\xae\x1c\xda\x78\x72\x1e\x16\x33\x9d\x52\x68\x2b\x69\x51\xf9\x66\xc7\xda\x5c\x6e\x10\xd9\x19\xae\x66\xa9\xf5\x2d\xec\x10\x86\x75\x38\xd3\xdf\x6d\x59\x3a\x32\xdb\x69\x5a\x8d\x77\x45\x70\x35\x16\xea\x56\xf8\xc1\xc8\xf0\xef\x53\xbd\xeb\x7f\x53\xc2\xd9\x44\xf5\x11\x94\x0c\xcb\x90\x62\x49\x22\xac\x59\x9f\x46\x19\xc3\x04\x62\x07\xd6\x05\xf6\xff\x94\xde\x78\x8d\x25\x34\x22\x29\xdc\x8a\xf9\x2b\x5f\xdf\x0d\xd7\x1d\xf2\xb4\x46\xcd\xf1\xd9\xa2\x05\x24\x33\x9e\xe1\xc3\x18\x26\x28\x7e\xf7\x27\x81\xa7\xa3\x52\x89\xf8\x5a\x15\xba\x57\xc7\xfd\x5d\x88\x5b\xd0\x55\x3a\xb4\x08\x05\xf5\x17\xe8\xf1\xb1\xb3\xc4\xfc\x67\x71\xe6\xf2\x24\xbc\x03\x11\x24\xb9\xc9\xae\xb1\x9c\x5a\x96\xbf\x14\x88\xe1\xe6\x6c\x6e\x88\x80\x92\x30\xc8\x3a\x74\x15\x55\x54\xa2\x19\xec\x37\x9a\xe5\x4a\x9f\xe7\x9d\xbe\xde\x3d\x57\x60\x42\xa6\x35\xd1\x97\xf4\xd8\x18\xc7\x78\x75\x5b\x8b\x45\xe5\x13\xde\xac\x88\xf6\x04\x25"}, -{{0x95,0x17,0x4a,0x09,0x15,0x68,0x4c,0xdb,0xb6,0x19,0xb0,0x55,0x49,0x5b,0x00,0xf1,0x92,0x82,0xcf,0xfc,0x3b,0x05,0x01,0x9e,0x6a,0xb7,0x09,0xa4,0xa1,0x74,0x2b,0xab,},{0xaa,0x8c,0x87,0x2d,0x7e,0x10,0xb6,0x7f,0x7f,0xf2,0x41,0x72,0xc3,0x63,0x7e,0x80,0x82,0x5a,0x0a,0x71,0xee,0x0c,0x48,0x86,0x3a,0x2a,0xcd,0xcb,0xe8,0xda,0x45,0x9a,},{0x78,0x0f,0x40,0xc2,0x0f,0xea,0x3b,0x11,0xc9,0x42,0x2a,0x43,0xb9,0xa6,0xf7,0x96,0x11,0xe7,0xf1,0xf5,0x9d,0x14,0x88,0xc1,0x5a,0x5f,0xd2,0xd3,0x2c,0x07,0xda,0xdc,0x39,0x1c,0x38,0x95,0x3e,0xdf,0x0d,0xe4,0x8b,0xe5,0x2d,0xa2,0xaf,0x33,0x5c,0x47,0xb8,0xd2,0xe4,0x4a,0xb9,0xd3,0xdf,0xb7,0x6b,0xa5,0x38,0xb0,0x66,0x49,0x52,0x08,},"\x5e\x1a\x74\x00\x45\x6c\xad\x4f\x9b\xa8\x66\x43\xbc\x7c\xbf\x3b\x35\x68\xdc\xb5\x22\xb3\x70\x55\xe8\xc3\x9d\x3c\x80\xf2\x28\x42\x38\xe5\x72\x7f\xd7\x51\x3c\xc8\xb3\x1c\x57\xae\x7b\x40\x50\xaa\x81\x9f\xc2\x36\x09\x30\xeb\x0d\xd6\x77\xa5\xb2\xc7\x29\xfe\xb2\xda\x3a\xd7\x9a\xe7\xfc\xcd\xdd\xb6\xc0\x84\x46\x26\x1e\xc9\xbb\xe5\x9c\x64\xe9\x9a\xbb\xc8\x6d\x3c\x48\x35\xf0\x0f\xef\xe5\x27\x43\x3a\x50\x1a\x3b\x6d\x57\x2c\xf5\xe1\x2a\x88\x01\x0b\x46\xa4\x72\xb9\xbd\x86\x91\xa4\x07\xc3\x65\xf9\xf7\x16\x34\xb4\xd9\x7e\xdf\xdf\xf0\x63\x14\xc0\xc1\xb4\xeb\x93\xc7\x60\x7f\x1d\x6f\xa3\x54\x65\x93\x22\xc2\x84\x07\x3f\x42\x60\x25\x18\xc5\x4f\xdf\x26\xea\x2c\x27\xc8\x0a\x6d\xfa\x20\x56\x83\x91\xab\x35\x72\x82\xc0\x6b\x23\xbe\xdc\x1d\xf1\x26\x4b\x61\x1c\x1e\x9c\xf1\x8a\xeb\xe2\x49\xfd\x86\x17\xc6\xe3\xee\x98\xc5\x3c\x0f\x6f\x21\x75\xc5\x7e\xf8\xe2\x06\xbd\x3c\xf1\x05\x62\x7a\x98\x92\xeb\x68\x99\x20\x21\x3a\xae\xb6\x3d\x87\x66\x3d\xbf\xa5\x3f\x0f\xb2\x81\x62\x69\x48\x29\x6b\x2d\xbc\xdd\xe1\xc5\x1a\xf8\x62\xee\xcf\x1c\xfe\x8a\x46\xa2\xc4\xb2\x8c\xfe\x71\x30\x33\x0a\xd1\x73\xf8\x71\x27\xaa\xca\xff\x43\xc0\xbd\xde\xa4\x8b\x00\x38\x97\x6e\x66\x2c\x04\xb6\xb0\x4a\xd0\x3d\xe1\x24\x62\xc2\x76\x5d\xb5\x35\x04\x95\x20\xcc\x11\x4a\xfd\xb6\xc9\x25\x49\xb0\x54\x6a\x90\x27\xd4\x49\x75\x5b\xeb\x8d\x4c\x17\xe6\xa2\xa4\x75\xf9\x67\x6a\x33\x7b\x4e\x86\x6d\x96\x32\x5e\x38\x9a\x52\xc1\x6c\x51\xe1\x8e\x0d\x81\x03\x34\x0c\x84\x17\xb2\xc5\x7a\x55\xd0\x42\xff\x5e\x5f\xc6\x5d\xf4\x23\xe0\x09\x2b\x0e\xa8\x8b\x96\xa9\x07\xc9\x51\x21\xc5\x47\xa6\x80\x61\xf2\x7b\xcf\xb5\x8c\xe6\xc0\x77\x28\xd4\x84\x6b\xdc\xbf\x0c\x62\x54\x10\xed\xf8\xde\xa8\xcb\x4c\x9d\x0b\xbe\xef\xcd\xe1\x92\x73\x36\x5f\x48\xd7\x5a\xec\x07\xd1\xc2\x2c\xcd\x23\x06\x8a\x97\xc3\xfe\x75\x2e\x87\xa3\x01\x18\xfe\x2d\xfd\x52\x18\xb6\xb1\x25\x15\x4e\x0e\xa3\x86\xcf\x23\x9e\x31\x37\xf8\xca\x6d\x8b\x74\x6b\x6a\x67\xd5\x08\xcf\x8c\x1a\xb6\x3e\x57\x15\xe6\x72\x1e\xda\x5c\x2b\xc3\x93\xa4\x93\xdb\xd2\xf9\xa1\xfa\x92\x6b\x9a\x59\xe4\x5a\x18\x0a\xee\xb0\x25\x99\xa8\xcd\xd6\x86\xf8\x89\xb4\x85\x27\x23\xcb\x6d\xbf\xb5\x01\x4c\xab\x5f\x65\x8a\x30\x9a\x47\x22\x39\x36\x0e\xea\xf6\x4f\xc8\x20\x3a\x3c\x70\x89\x70\xe1\x5c\xbc\xf1\x36\x25\x5d\x96\x44\x6c\x39\xa9\x27\x03\x1d\x26\x7d\x69\xec\xd5\x1d\x7a\xf6\xe9\x1f\xb4\xae\xf9\xd7\x8c\x33\x35\xe9\x07\x11\x33\xcf\xb8\xe2\x12\x99\x90\xc6\x46\x37\xc7\xad\xf1\xda\xef\x2d\xc2\x6c\x11\x63\x39\x9f\x3f\xe1\xe7\x92\x33\x80\x92\xef\x6f\x8d\xfa\xf2\x57\x30\xdd\x2f\xe8\xd9\x78\xf6\xf7\x70\xf5\x2b\x68\x23\x81\x76\x56\x4c\xee\x5f\xbb\x98\x50\xb3\xb3\xa0\x4d\x94\x84\x60\x41\x78\x26\xeb\x2e\xb2\x4f\xcc\x5f\xe3\x53\x34\xbb\x95\x21\xe8\x7b\xc4\xdb\xde\x2a\xc9\xe1\xc9\x89\x49\xdc\x2d\x29\xad\x27\x9e\x38\x84\xb9\x05\x26\x8e\xbd\x08\x08\xbf\x41\x82\x57\xe7\x5e\x26\x2b\x4d\x01\xb0\x24\xa6\xe9\xaa\x7b\xd5\x01\xdb\xa9\x4f\xf5\x06\x39\x4b\x4b\x0a\xe6\x08\x1e\xa7\x30\x30\xc4\x3a\x6a\x91\x76\x6e\x80\xf9\xf4\x2c\x0b\x68\xb9\x84\x19\xad\x4e\xee\x4e\x9a\x72\x8a\xde\xfb\xd7\x9e\x83\x1f\x70\xf4\x1e\x62\xb4\x3f\x0b\xf4\x2b\x3b\x2c\xd5\x3b\x55\x89\x11\x76\x64\xbc\xeb\xc4\x09\xa7\x64\x5b\x1e\xed\xda\x48\x2f\x6b\x68\x95\xa6\x57\xba\x78\x9b\x89\xe5\x02\xd6\x99\x87\x51\xd6\x30\x3d\xed\x5f\xa1\x56\xee\x7c\x7e\xaf\xe5\x46\x26\xd1\x03\x2c\x4d\x7d\xff\x97\x7f\x1d\xcc\x86\xaf\x89\xb1\xe6\x46\xa4\xaf\xc2\x42\x7e\xd0\x2c\x0a\xf5\xd3\x28\x90\xf9\x5f\x13\xf9\x8c\x1a\x5b\x1d\x9f\xbb\x78\x1a\x9a\x89\xb2\xd7\x90\xc1\x46\x5c\x2d\x15\x20\x92\x6f\xdf\x28\xc1\x7d\x9b\xa1\x58\x7a\xd7\x61\xf0\x65\xd3\x39\xbd\xbe\x38\xf4\x13\x3f\x45\xbb\x59\x78\x74\x26\x42\xf9\x0c\x06\x5e\xe4\x89\x25\x73\xf6\x05\x9f\x8b\x4c\xe2\xc1\x3e\x73\xb8\x91\xcd\x05\xf2\x37\x31\xed\x9a\x07\xe2\xb8\xff\xdc\x96\x3b\x06\xa5\x10\x20\x9c\x32\x99\x80\x94\x9f\x40\xd8\x07\x3a\x01\x3e\xf8\x43\xdf\xcc\x4a\x33\x94"}, -{{0x5a,0x84,0xaf,0x28,0xa5,0xdf,0xbb,0x32,0x33,0xa1,0x2f,0x08,0x37,0xf6,0xe8,0x65,0x4e,0x7b,0x0d,0xe1,0x6b,0x02,0xab,0x3c,0xd1,0x78,0x64,0x43,0x1e,0x27,0x46,0x67,},{0x80,0xd4,0xba,0x78,0x9f,0x8a,0x4b,0x20,0x47,0xad,0xaf,0xa5,0xed,0x26,0xcd,0x8c,0x54,0x67,0x33,0x29,0x2e,0x8b,0xf6,0x93,0xcf,0xd1,0x7e,0x28,0x4e,0xfc,0x68,0x71,},{0xa0,0xb8,0x4c,0xa5,0xaf,0x76,0x46,0xe6,0xf6,0x2a,0x69,0x35,0x37,0x94,0x73,0xfa,0x6e,0x4c,0x27,0x69,0x58,0x51,0xfc,0xbd,0xae,0x29,0x17,0xb2,0xdc,0x68,0xd7,0x96,0xe2,0x78,0xd7,0x0c,0xd6,0x7f,0xce,0xdf,0x6c,0xa6,0x29,0xb8,0x81,0xf7,0xc4,0xf2,0xaa,0x25,0x59,0xb2,0x0d,0x67,0x06,0x11,0x76,0x6b,0xd6,0x5a,0xa4,0xfe,0xf2,0x04,},"\x8a\xac\xd1\xb8\xa3\x9b\xf0\x8f\xd5\xc9\x18\x44\x6b\xe5\x76\xe6\xa3\xf2\x7f\x36\x11\x16\x07\xf2\x7b\x56\xa9\x12\x14\xe7\x63\xf9\xa8\x7f\xb1\xd1\x84\x48\x98\x96\x17\x97\x64\x44\x60\xbf\xf5\x48\x8c\x10\x3a\xf6\x05\xe8\x74\x0e\x46\x58\x8f\xb9\x3e\x44\x3c\x3b\xb2\x3b\x92\xc0\x98\x70\xa5\x57\x65\x3a\x1f\x22\xc2\x18\xcc\xbc\x2f\x07\x3a\x27\x2d\x17\xa8\x42\x23\xef\x14\x3f\x4c\x7c\xa2\x58\x46\x0b\x79\x81\x69\x67\x3d\xa1\x07\xd7\x1d\x53\x56\xce\x9f\x75\x59\xa9\xb0\x38\x39\x99\x51\xf5\x75\xc7\x7e\x5b\x9d\x05\x29\x57\x8e\xca\xa2\xe2\x08\x92\x66\xfc\x52\x6c\x5d\x40\x9f\xbd\x46\xbb\x86\x84\x1c\xb5\x54\xf5\xbd\x3c\x99\x71\x3b\x04\x3e\x40\x46\x53\xa7\xd0\x13\x44\xd4\xdb\x83\x1a\x21\x72\x82\xc4\xb3\x36\x40\x56\x53\xb8\x5d\x27\xa4\x6b\x25\x9c\x85\x5c\xdd\x85\xad\x6f\x7a\xed\xd8\x35\xff\x55\x00\xcc\x8b\xaf\x0f\xb2\xf0\x18\x09\x10\xc6\x46\x72\xb8\xa8\xd4\x9d\x98\x4a\x78\x29\x3c\xf5\x77\x9c\x91\x0c\x3a\xcb\xbc\xa4\x55\xa8\x54\x66\xe5\x35\x04\x4f\x34\x80\x26\x2c\x09\x0f\xbf\x4e\x0b\x0d\xb4\xd1\xef\x87\x59\xda\xaf\xdd\x8d\x05\x90\x74\x82\x46\x1f\xf9\x10\xc4\x37\x19\x5d\x5c\x7f\xed\x9d\x82\xcb\x94\xe7\xe4\xec\x24\xda\x05\x3e\x47\xf6\x2b\x48\x8e\xb7\xb2\x44\x65\x5c\x7d\xbb\x20\xed\x60\x7e\xed\x45\x31\x44\x9e\x07\x80\xe6\x1c\xfd\x57\x40\x86\xff\xc5\xdc\x52\x42\x83\x77\x5c\x44\xf7\x54\x7c\xda\xb0\x4a\x51\xee\xe4\xe1\xb7\xb6\x5a\x57\x57\x3a\x92\x48\x4a\x35\x90\x0a\x90\x9f\x81\xe4\x15\x02\x9d\x22\xca\x93\x7a\x3a\xcd\x9e\x61\xf8\xc0\xe6\x86\xb2\xd2\xad\x03\x77\xaf\x8e\xe1\x66\xe4\xa2\x0a\x82\xaf\xf4\x51\xe1\x51\x10\x3e\x0a\x17\x67\xb2\x71\xfa\x9c\x2b\x1d\xd1\x20\xf8\x05\x85\x3b\x3b\x8a\x56\x0f\xc8\xb9\x37\x62\x83\xb5\x11\x24\x32\x4a\x28\x4a\x0e\x9a\xc4\x9d\xf6\x9f\x52\x4c\x8e\x04\x2d\xf8\x2e\xfb\xcd\x16\x88\x1e\xc1\x31\xa1\x52\x10\xdf\x73\xde\x02\x94\x34\x47\xf2\x2a\x2e\xa1\xdc\x8b\xf9\x68\x29\x8e\xe9\x7f\x3a\xd5\x46\xd7\x8b\xc6\x60\x89\x7e\x08\xd2\xa2\x8b\x2b\xa6\x8b\x54\xb9\x54\xf1\x47\x64\x51\xc6\x92\x07\xe5\xdd\x24\x8a\xe4\x7e\xf3\x56\x94\x99\x0e\x6f\x05\x8b\xc0\x01\x7b\x74\x95\x10\x5c\xc8\x73\x90\x66\xaf\xb1\x1e\x1f\x26\x60\x19\x42\x54\x6a\xe8\x49\xff\x2f\x56\x73\x0f\x13\x26\xbb\xee\xa6\x40\xee\x17\x8f\xa2\x47\xad\xff\xef\xc0\x46\x49\x4f\xc7\xff\xc0\x77\x7d\x5d\xbe\x8a\x55\xda\xee\x61\x40\x6f\xe3\xc7\x08\x8d\x43\xd9\xe1\x4d\xa2\x1c\xa5\x2f\xd8\xc1\x60\x09\x1c\x8f\x99\xa6\x7d\xad\x65\xc6\x4f\xea\x9d\x18\xb1\x53\x7d\x06\x1f\x5d\xce\x87\x9e\x0b\xc4\x26\x48\xd2\xea\xa0\x2d\x97\x21\x85\x75\x3c\xb2\xf6\x22\x5d\x8d\x03\xbb\x07\xf9\x44\xb1\x0c\xf4\xea\x22\x27\x5c\x3d\x70\x84\x80\x20\xf3\x0c\x82\x3b\x76\x14\x3a\xcf\x54\x59\x99\xa2\xcc\x4b\x58\x98\xd9\x4b\x4a\x25\xef\xbe\x5a\x60\x33\x1c\xc0\x09\xfe\xc0\xa2\x5b\xc9\x89\x47\xb1\xb7\x13\x9e\x22\xd2\x32\x80\xff\x88\x54\xa1\xec\x76\x22\x1b\x1b\xf3\xd1\x08\x32\x8c\x8a\xc4\x63\xc6\x52\x63\xa2\xd7\xca\x74\x33\x48\x29\x31\xa1\xd8\xfc\x14\x4b\xbe\x9b\xef\x67\x8c\x92\xe1\xc2\xd1\x09\x21\xb6\xad\x43\xa7\x5c\x53\xbc\x07\x58\x54\xed\x2d\x99\xd8\x25\xf3\x0a\x5e\x10\xd5\x17\x43\x8e\x4d\x4f\x71\x13\x42\x9f\x1e\xdb\x38\x7d\x6b\xd7\xaa\xd2\x92\x74\xf8\xd2\xdc\x88\x9b\x7e\xfb\xeb\x58\x68\x6f\x8d\x66\x9c\xea\xef\x92\xc7\x5e\xd5\x30\x7f\x0c\x03\xf5\x90\x01\x81\xce\x57\x3c\x8f\xa2\x86\x75\x20\x5f\xb1\x05\x7f\x62\x6a\xa2\x30\xd0\x3e\x2e\xaa\x8c\xff\xcd\xe2\x00\x81\x47\x5d\x80\xb2\x45\xa1\xca\x60\x45\xba\x20\x4a\xb0\x00\x69\x07\x9c\x63\x7f\xc3\xfb\x3e\x80\xca\x04\x62\xe7\xa4\xcd\xd9\x28\x3f\xf9\x00\x85\x30\x36\x48\x16\x79\x2f\xdf\x3b\x9a\x4e\x4d\xc8\x37\x92\x28\xed\xcb\xb1\x54\xbe\xf3\x87\xd3\x77\x60\xd7\x9a\xfb\xb7\x36\x26\x0a\x1d\xb1\x01\x38\x36\x1f\x24\xb8\x26\xdb\xcd\x5f\x0f\xc9\xe7\x83\x0d\x26\xd8\x0c\x52\xa7\x92\x18\x92\x76\xbc\xe3\x47\x60\xfb\x77\xbe\x13\x12\xac\x8c\xf9\x7d\x92\xcb\xf3\xd0\x77\x80\x28\xdb\x5e\x8e\xae\x89\xe0\xb9\xbc\x87\x78\xae\xb1\x27\x8f\x04\x71\xcb"}, -{{0x79,0x3a,0xc8,0x8d,0x7d,0x3b,0x6f,0xa7,0xf4,0x7d,0xee,0xc3,0x1f,0x68,0xdd,0xcc,0xb7,0x01,0x82,0x0f,0x1b,0x13,0xdd,0xc6,0x52,0xf7,0xc6,0xa8,0x5b,0x60,0x52,0xa5,},{0x91,0xb6,0x22,0x7a,0xcd,0xd1,0x83,0xda,0x62,0xc5,0x19,0x65,0xc6,0x35,0x35,0x8b,0x20,0x4d,0x68,0x3e,0xe0,0x64,0x43,0xcb,0xd4,0x0e,0x71,0xc1,0xf7,0x6a,0xd1,0x02,},{0xa8,0x4f,0x55,0x2b,0xf4,0x43,0x22,0xa6,0xdb,0x24,0x5c,0xa0,0x06,0xd1,0xcf,0x78,0x0c,0x61,0x68,0x0f,0xe7,0x42,0x9a,0x89,0x47,0xc3,0x5f,0x21,0xbc,0x4b,0x44,0x22,0x8b,0xa3,0x0a,0xea,0x0c,0x74,0x4b,0x86,0x64,0x59,0xd3,0xb8,0xac,0xad,0x45,0x3b,0x06,0xac,0xe2,0x47,0xba,0x69,0x52,0x8c,0x6b,0x3b,0xc4,0xb2,0x0e,0x75,0x63,0x0e,},"\xec\x50\xaf\xad\x8a\xde\x74\x05\xe2\xc6\xf5\xc6\x24\x7b\xbb\xcc\xfb\x2c\x17\x16\x6f\x78\x84\xfe\xae\x10\xd9\x0f\x5d\x83\xc4\xb6\xf0\xbf\x76\xde\x2f\x78\x97\xba\x11\x94\xd6\xd3\x44\x9d\xdb\x80\xae\x74\xeb\x8e\xd6\x8f\x04\x9b\x35\xc6\xf2\x19\x16\xdb\x4d\xfc\x27\x24\xdc\x3a\xf7\xad\x8d\xd5\xc4\x4f\x60\xd2\xf4\x9f\xad\xd7\x00\x4d\xa1\x59\x30\x93\x94\x2c\xae\x52\x08\xbf\x54\xcf\x90\x3b\xee\x64\x69\x05\xfc\xe2\xeb\x2e\x37\x0d\x0d\xca\x48\xd8\x20\xad\xea\xb1\x6a\x3b\x67\x5e\x5a\x4a\x8e\x26\x7e\x34\xff\x96\xf3\x12\x2b\x18\xde\x0c\xad\x92\x92\xab\x63\xd2\x6e\x5f\x31\x0f\xa2\x16\x8c\x29\x66\xbd\xb6\x3b\x0d\xe0\x86\x26\x76\x7b\x37\x9d\xe4\x63\x3b\x9f\x3e\xda\x79\x17\x28\x1d\xad\x66\x1e\x9f\x77\x2b\x84\x4a\x79\xe8\x00\xfd\x84\x27\x02\x44\x6e\x4a\xa7\x31\x75\x71\x07\xf3\xfd\x65\x47\xbf\x40\x75\x96\x3d\x5f\xd5\xf5\x8e\x80\x85\x3f\xc4\x27\x51\xdc\xa0\x78\xa9\xfa\x8d\x5b\xb3\xd9\xa3\x4a\xbc\xab\x02\x93\xd6\xce\xae\xc4\x89\x67\xa1\xe6\x22\x43\x98\xca\xd0\xf6\x05\xa3\xbe\x8e\x67\x58\xea\x8f\x29\x20\x9d\x8e\x4c\x4c\xa1\x89\x3b\xaa\xd9\x1e\x37\x9b\xa3\xb1\x73\x30\xc1\x2a\x5b\x6f\x21\x9b\x38\x4a\x8a\xb9\x78\xbf\x1b\x37\xc3\x73\x1a\x1b\x47\x4b\x24\xb5\xd6\x7d\x4c\xec\x28\xaa\xc6\x51\x0b\x11\xf2\xcf\x21\xbc\x16\x96\x3d\x51\xf5\x53\x87\x27\x71\x8f\xc4\xe2\xe5\x17\x2e\x3c\x0c\xda\xbc\x27\x7f\x0d\x70\x37\xc3\x4c\xa6\x8f\x73\x28\x88\x48\xb9\x26\xbd\xe0\xcf\x47\xab\xfa\x66\x60\x09\x16\x94\x6f\x07\x65\x1c\x28\x0a\x20\x86\xb1\x4d\x52\x57\x0c\xc8\xa4\xb7\x43\x58\xb5\x9c\x30\x2b\x9d\x00\xe1\xb4\x98\xf3\xbc\x33\xee\x4e\xcf\x2b\xce\x2c\x65\xed\x7e\x8b\xa7\x4d\x35\xb7\x51\xd3\xc9\x9f\x40\x86\x19\x68\xc2\xb7\xf3\xa5\xbe\x34\x8c\x57\xd9\x3b\x40\xff\xd0\x51\xed\xd7\xca\xca\x6e\xe6\xbc\xa7\x21\xdc\xba\x8d\xb8\xd0\x06\x4f\x54\xd3\x6e\xc5\xe8\xd6\x2a\x71\xfd\x1c\x90\xf1\x49\x24\xf4\x1c\x16\x3f\x00\x7a\xfc\x6f\xbb\xfe\x86\x45\xfa\x47\xc3\xc9\x80\x24\x6d\x1b\x92\x27\x43\x85\x95\x3c\x53\x41\xcd\x64\xc3\x4a\xe9\x71\x7c\xc2\xc3\x7f\x58\x35\x9c\x0a\x99\x91\xc2\x3f\xe6\x37\xde\x6c\xdf\x08\x62\xf7\xd0\x32\x9f\xe7\x58\xaa\x89\x2a\xd4\x58\x3b\x9d\xf2\xf3\x33\x7d\x5b\xe5\x70\xba\x65\x49\x98\xed\x29\x2f\x11\xf0\x17\x72\x38\x2a\x04\x34\x2f\xdd\x99\xe6\x9e\x0d\x97\xc4\x3f\x10\xac\x9b\x96\xf1\x40\xa6\xf8\x3c\x47\x29\xe7\xa9\x00\x47\x1f\x2b\x1d\xf2\x40\x1b\xc5\xc6\x80\x42\x2b\x13\xb0\xc8\x00\x7d\x63\x68\x1f\x66\xa0\x59\x5a\x1c\x5d\x3a\xcd\xe5\xb7\x79\x42\x6e\x73\x6b\xc1\x00\xc5\xe6\xf5\x26\x08\xdc\x39\x1e\x3e\xf9\xb1\xbb\x6a\xf1\x3d\x24\x9b\x7d\x32\xce\x06\x80\xc3\x68\xf5\x4d\x5f\xe0\x39\xcf\xe1\x01\x30\x25\x1e\x4d\xb1\x4c\x79\xc8\xd0\x44\x06\x04\x65\x82\x29\x90\xd8\x80\x93\xcd\x73\x65\x32\x85\x2e\x44\x78\x89\xdb\x89\xcc\x60\x05\x29\x96\xa3\x2a\x64\x36\x5c\x07\x26\x05\x1c\x11\x9e\xda\x90\x1d\xe5\x76\xb3\x34\xfc\x70\x49\x48\x23\x92\xe2\x62\x0b\x0a\x3a\x13\xfa\xb1\xd3\x6f\xc0\xa5\xf2\x3d\xb1\x47\xfd\x85\x7b\x26\xa6\x98\x04\x8f\x8b\x81\x1e\x23\xd7\x22\xe2\xe9\x02\x7e\xd4\x12\x4b\x48\xdc\x5e\x57\x8a\x7a\xeb\x19\xa1\xb4\xf9\x48\xee\x5b\x46\xf6\x5b\x97\x96\x46\xe2\xbe\x07\x47\x14\x11\x8b\xaa\x4b\xfc\x15\xb0\x89\xa0\xe0\x66\x27\xda\x46\xe4\xbb\x06\xaa\x3c\x7c\x5d\xd6\x48\xe0\x3c\x9c\x2d\xec\x3f\xac\xd9\x56\x26\x56\x2f\x30\x00\x88\x32\x30\xd2\xb0\xa1\xf8\xa7\x47\x8c\xb7\x7f\x93\x9a\x5f\x18\x8f\x45\x8d\x10\x37\xb9\x01\x76\x66\x4d\x86\xea\x85\x0b\x8a\xf5\x08\x7f\x86\x60\x5a\x77\xe0\x25\xef\x6c\x7e\x6a\x2a\x59\xf0\x06\xcb\xa1\x89\xfa\xd9\x33\xf4\x2c\x53\x27\x08\x10\x9b\xc1\xaf\x81\x48\x19\x59\x5f\xfc\xb9\x5f\xbf\x5b\x7e\x93\xa7\x11\x97\xe4\x77\xee\x7c\x04\xb8\x51\xc1\xc3\x66\x22\xcd\xd8\xe6\xc8\x60\xd9\xab\x2c\xac\x56\xd2\xdc\x98\xfa\x69\x12\x4f\x2b\xb2\xa6\x47\x1e\x1c\x73\xb6\x61\xf0\x71\xf5\xd8\x6d\xe7\xd1\xde\xaf\xa4\xed\xcd\xc7\xbf\x1f\x70\x5c\x56\x30\x0a\xff\xd0\x58\xb9\x69\x77\x91\x41\x9e\x5f\xb2\xa5\xb7\xf7\x8c\xe3\x40\x1f\xf5\x50"}, -{{0x89,0xde,0x74,0x42,0xd7,0x4b,0xa9,0x38,0x59,0x69,0xc9,0x65,0x1a,0x88,0xfe,0x28,0xe0,0x40,0xd5,0x93,0x90,0x7d,0xac,0x1a,0x39,0x87,0x41,0x8b,0xdf,0xdb,0xad,0x89,},{0xfd,0x3b,0xa9,0xfa,0xd3,0x20,0xeb,0xa4,0x5d,0x07,0xb8,0x4a,0x49,0x7b,0xe1,0x7d,0x3f,0xc7,0xdd,0x99,0x99,0xc9,0x68,0x88,0x3c,0xd6,0xac,0x13,0xb0,0x66,0x9b,0x17,},{0xba,0xb5,0x72,0x84,0xd2,0x0e,0xe5,0x4c,0xc7,0xf9,0x70,0x8d,0x71,0x77,0x06,0xd8,0xfa,0xf6,0xe4,0x63,0x32,0xb0,0x69,0x1d,0x6f,0x21,0x3a,0x8d,0xb8,0x01,0x15,0x5b,0x4e,0x33,0x8c,0x13,0x61,0xb5,0x92,0xbe,0x75,0x85,0x01,0xb1,0x82,0x17,0x93,0xae,0x52,0x27,0xcc,0x3b,0xa8,0xdf,0x8a,0xdf,0xc6,0xed,0x9a,0xca,0xb5,0x4c,0xc4,0x01,},"\x9d\x52\x72\xf0\xb7\x84\x88\x2b\x94\xc7\x6d\xfb\x9d\x46\x0c\xa4\x95\x02\x5e\x0a\xec\x5d\x52\xcc\xff\xfe\xce\x9f\x81\x73\xc1\x05\x58\x26\x6c\x49\x85\x25\x89\x1a\x97\xbf\x38\x78\xe3\x3c\x3d\xe2\xfc\x2e\x52\x55\x0b\x43\x15\x62\xcb\xe4\xa3\xd0\x11\xec\xc9\xe7\x7e\xc3\x6a\xd3\x83\x41\x35\x8c\x88\x32\x1c\x03\xd0\x8b\xb4\x26\xa7\xd5\x85\x41\x71\xc0\x27\xec\x48\xd5\x78\x19\xa9\x1a\xfd\x02\xa6\x18\xcc\xbc\x25\xe6\x8e\x53\x09\xd0\x47\xb1\x56\xe3\x57\x05\x37\x3a\xda\x2e\xb8\x31\x32\x1a\x20\x3e\x1b\xd8\xf0\xef\xec\xc0\x96\x18\x64\x7b\x41\xdf\xf2\x2b\x39\xd0\x22\x35\xf8\x71\x53\x2f\x60\x85\xe9\xcc\x52\xec\x00\x9b\x33\xee\xbc\xdc\x26\x7d\x77\x67\xc9\x0c\x92\x7e\x15\x4f\x72\xf3\xf4\x8a\x34\x95\x63\x19\xb2\x93\xc8\xa8\xb3\xe3\x4e\xfc\x5f\x62\xf2\xb4\xe8\x01\x9b\x50\xa0\x8f\x5c\xcf\x95\xbc\x83\x1b\xaf\x40\x81\x1d\x87\xe5\xed\xbd\x2f\xd5\x36\x5b\x26\xa4\x31\xae\x95\x80\x0f\xf3\x81\xcd\x62\xca\x40\xe1\x86\x6d\x95\x0d\xce\x14\xf0\x30\x91\x8a\xba\xc6\x8e\x79\x16\xdd\xb9\x5a\xdc\x19\x71\x28\x78\x74\xd0\x7e\xb0\xed\xef\x64\x29\x66\x52\xc4\x80\x44\xb0\xc5\x52\x1a\x8d\x27\x0d\x53\xd7\x4e\xc6\x3b\x89\x0f\x33\x63\xf9\x20\x7f\x66\x52\xae\x8e\x78\x35\xc3\x82\x0a\xd6\xd9\xe3\x63\x3f\x4b\xfd\x53\x79\xa4\x4f\x29\xd6\x5f\x36\x09\xfe\x35\x58\x17\xdc\xa5\x51\x8d\xfe\x3b\xd7\x69\x32\x0a\x03\x19\x02\xe9\xcf\x66\x69\xc2\x4f\x88\xb0\x1e\xb3\x69\x95\xbd\xb8\xdb\xed\x6e\xe0\xc9\xb7\xf3\x22\x95\xc6\x1b\xa8\x90\x5e\x55\x98\xf3\xc9\xe1\xc8\xbf\x72\x64\xf9\x82\x93\xfa\xea\x17\x74\x7f\x88\x44\x0c\x31\x81\x8c\x43\x3e\xa3\xd2\x3c\x01\xf4\xf7\xe9\xc3\xdd\x3d\x5f\x32\xec\x9e\xac\xd7\x1a\x09\xe3\xa9\x97\x38\x1f\x1c\xbf\xfd\xf4\xb5\xba\x49\x79\xde\xb7\xb0\x98\x41\xaf\xa3\xb0\x3d\x1c\x93\x11\x09\x7b\x86\x2c\xae\x11\x70\x7c\xbd\x3a\x4a\xe6\xc8\xa2\x6a\x30\x6a\x68\x7c\x41\x4a\x4e\xa1\xe8\x12\xf1\x15\xf6\x0f\x70\xbd\xa7\xf8\xfb\xe7\xbc\x2d\x50\xcc\x55\x0b\xba\x29\x1d\x5e\xc5\x23\x22\x9a\x08\xed\x56\x8b\x5c\xee\x18\xfe\x6f\x46\x78\x2c\x17\xcd\x82\x88\x01\x63\x92\x15\xbc\x5e\x9b\xe4\x55\x5c\x9a\x18\x00\x97\x67\xa6\xc5\xc7\x4a\x82\x29\xd2\xff\xaa\x39\x9d\x8e\x64\x32\x4e\x88\x42\x23\xd5\x07\x0f\x73\x5a\x75\xd8\x5f\xf6\xc9\x4a\x9f\xbc\x2b\x36\x51\x38\x6d\xe5\xa2\x3c\xce\x95\xc8\x78\x81\xc7\x93\x99\xae\x71\xf0\x90\x73\x7e\x21\x87\xfe\x90\x4a\xab\x1d\x92\xd6\x18\x67\x95\xc9\xb4\x6c\x62\xa5\x91\x4f\x36\x30\xfd\xcb\xac\x3b\xd4\xb0\xda\x4e\xc3\x13\x6a\x1f\xb2\xba\x40\x32\x2d\x7c\xc4\x08\x5e\x16\x70\x09\xcf\x74\x50\xfc\x6a\x28\x6c\x2f\x79\x51\xd5\x1a\xae\x23\xb8\xf3\x30\x20\xef\xb5\xe3\x24\x5b\xa6\xa3\x54\x3a\x2b\xde\xc4\x47\xd5\x1a\xe0\x0b\x5e\x16\x78\xb7\x60\x93\xcf\x21\x6b\x95\x07\xc9\x63\xeb\xfc\x02\x4c\xcd\x6e\xf6\xc7\x8c\x45\x72\x27\x3b\xea\xaf\x55\x07\x6d\xc4\x4a\x22\x4b\x58\x61\x57\x05\x79\x19\x65\x30\x7c\xef\xd4\x86\x72\xc0\x81\xbc\xcf\xbc\x1d\x15\xb0\x62\xb3\x8b\x4f\xba\x9b\x9b\xec\x95\x6c\xd1\x44\x44\xee\x43\x7e\x79\x60\xcc\x60\x1e\xdd\xc0\x2f\x1a\x76\xb6\x85\x74\xd5\xf8\x84\x31\x50\xc0\xb9\x00\x99\x34\xa2\xbf\xaf\x60\x57\x70\xc1\x36\xba\x29\xf3\xdc\x7e\x29\x59\x7a\x24\x80\xdb\x23\xe2\xb2\x67\x7e\xc6\xc5\x1b\xd3\x01\xf2\xb5\xa3\x9d\xfd\xa7\xb4\x77\xbe\xdd\x1c\xda\xed\x10\xe2\x9d\x29\x54\x62\x9b\x98\x76\xf8\xee\x54\xe4\x04\x73\x69\xd5\x34\xca\xb5\x4a\xea\x44\x1d\xc9\x47\xeb\x3f\x59\x38\x2b\x21\x83\x60\x57\x2f\x26\x59\x58\x31\x53\xc0\xe2\xb9\x12\xcf\x30\xc8\x15\xb2\x6f\x05\x85\x3d\xd3\x05\x51\xee\xcf\x64\xb8\x58\xa4\x41\xbb\x8c\x6d\xb8\xa9\xfd\xe7\x7a\x32\xa7\xb4\x6a\xf6\x6f\x8c\xb9\xf3\x5e\xe0\xfa\xfb\x0b\xd4\x2d\x9e\x65\xb2\xa9\x05\x82\x41\xa3\x1b\x8c\xa1\x11\x54\x34\x23\x76\x70\xaa\xb4\xef\xf3\x60\x10\xed\x03\x71\xf4\x65\x95\xda\x1b\xdd\x57\x9b\xbb\x67\xaa\xdb\x68\xe7\x7a\xd3\xa3\x8c\x8f\x26\xd2\xaf\x5a\x71\x03\xba\x5f\x22\xb4\x2c\xc1\x2a\x8c\x3c\xe5\xc9\x21\xc9\x1c\xfc\x0e\x63\xdf\x90\x27\xd2\x62\x29\xb1\x04\x7c\xbc\x18\xf6\xb0"}, -{{0x26,0x22,0xbd,0x9b,0xbe,0xf7,0xff,0x4a,0x87,0x62,0x9e,0xa0,0x15,0x3d,0xc4,0xd6,0x08,0xc3,0x1f,0xa5,0x84,0x79,0x88,0xff,0x50,0x0d,0x88,0x06,0x81,0xf1,0x13,0x72,},{0x19,0x97,0x58,0xa9,0xc3,0xd0,0xee,0x3e,0xeb,0xcb,0xbd,0xa3,0xe1,0xef,0x54,0x55,0xff,0x46,0xd7,0x36,0xbb,0x4e,0xf0,0xc0,0x6a,0x73,0x9f,0x9a,0xc5,0x84,0x83,0x95,},{0x43,0x78,0x96,0x6b,0x78,0x31,0xde,0xf4,0xae,0xcb,0x49,0x89,0xbc,0xaf,0x9c,0xae,0x99,0x46,0x1c,0xb9,0xb5,0x9d,0x19,0x51,0x8c,0xc1,0xec,0x7b,0x83,0x51,0xbc,0xd1,0xf7,0x23,0xaa,0xc5,0xf0,0x61,0xb3,0x83,0x63,0x57,0x4f,0xf9,0x6b,0xa1,0x0e,0x19,0x6b,0x1b,0x05,0x31,0xe1,0x18,0x30,0x36,0xa4,0x25,0xe6,0x9c,0x45,0x98,0x04,0x0c,},"\x89\x1e\x82\x12\x25\x47\xd6\x1e\x83\xb0\xab\xaf\x27\xc7\x30\x3f\x05\x22\xa2\xec\x4a\xf4\x4e\xf0\xac\x19\x6a\x99\x78\xb1\xc6\x23\xef\x1f\xa7\x2b\xaf\x70\x91\x0a\x5c\x51\xc4\xf7\x8e\x0f\xe9\xfe\x37\xe2\x43\x9c\x47\x95\x91\x6c\xfa\x22\xab\x47\x1a\x25\x57\xcc\x7b\xa6\xb6\x69\x56\x06\x3d\xde\xb3\x9c\x50\xf1\x4f\x06\x34\x8f\xa6\x6b\x60\x64\xdc\xff\xca\x50\x43\x96\x7f\x05\x25\x4d\x57\x7a\xbf\x22\xae\x8c\x90\x00\x0c\xe2\xe6\xa1\xa8\xb2\xe3\xa6\xb3\xab\xc5\x63\xeb\xff\xb2\x04\x45\xf0\x91\x1c\xc4\x2a\x98\x7f\x84\x56\xef\xba\x41\x30\xe6\x8f\x01\xfc\xdf\x7b\xf7\x71\xfc\x1d\x35\x37\x1a\x0d\x75\xdd\x5f\x90\x00\x2c\x90\xb6\xcb\xad\xe4\x0d\x5b\x23\xfd\xb4\x9a\xba\xcb\x72\x19\xae\x27\x56\x1a\xa2\xa8\x79\xda\x88\xdf\x34\xa8\xc5\x81\xf0\xc6\x71\x98\xff\xc6\x08\xfe\x91\x95\xb5\x55\x5c\x8a\xe9\x34\xc8\x30\xaa\xe2\x88\x5b\xea\x87\x48\x74\x48\xe1\x1b\x4f\x2f\x17\x2e\x4d\x5c\xfe\x4f\xd1\x13\xf9\xd2\x01\x6c\x24\xa7\x34\x51\x2b\xb9\x18\xf5\x75\xe7\x54\x13\x97\x18\xe3\xd2\x0e\x79\x0a\xbb\x94\x2c\xba\x3e\xc8\xb2\xdb\x59\x07\x96\xdc\x43\x5f\x13\x9f\xc6\x4d\xdc\x85\xa2\x24\x94\xef\x2b\xfa\x1f\x5c\x0f\x18\x75\xea\x58\xe8\x4e\xb3\x74\xec\xf8\xce\xc6\x46\x8b\x6b\x09\xd1\xe7\x4f\x15\x41\xed\x45\x4a\x28\x07\xd3\xf4\x05\x35\x66\xb0\xe4\xe2\xc6\xae\xce\xd1\x0d\xc0\x07\xe9\xdf\x41\x6f\x26\x7f\xcb\x3f\xe1\x7b\x8b\xac\xe0\x3f\x07\x43\xe0\xe6\xd4\xa4\x8c\xe7\x6e\xdf\xf6\x0c\x0e\x3a\x30\x84\x56\x99\x54\x13\xc1\x07\x6f\xf3\x7e\xcf\x23\x81\xa0\xd4\xe9\xe4\xa9\x13\xa2\x58\xd9\x83\xb9\x69\x6b\x5c\x45\xaf\x37\xc8\x68\x40\x70\xe4\x00\xb8\xf8\x65\xa5\x04\x04\x3f\x45\xd7\x8b\x97\x13\xf3\x35\xaa\x41\x6a\x46\x16\x64\x10\x73\x5f\xb5\xd8\x22\x10\x45\x8d\x5a\x08\xa1\x04\xd4\x00\x2a\xb6\x11\x88\xf9\xdf\x45\x7d\xd7\xed\x59\x37\xca\x50\x77\x60\x6b\x41\x8b\xbc\x86\x84\xa1\xd5\x25\xbf\xa5\x51\x08\x76\x40\xb1\xd1\x77\xca\x6d\x4f\x64\x71\xb3\x9b\x2c\xe4\x3a\xfb\xf8\x28\x5e\xcd\x68\x7e\x43\x8f\x44\x25\xdf\x56\x8a\xb8\x6f\xa2\x31\x63\x49\xa1\x10\x2b\x41\x43\xd7\x1e\xf4\xe2\x4f\x5c\x53\x0c\x77\xaf\xb0\x10\x07\x88\x63\x64\x40\xe7\x40\x67\x5a\x61\x74\xc5\xf0\x57\x10\xb2\x53\xa4\x11\x17\x3f\x9e\x82\xce\x6e\x22\xf4\x09\x5e\x77\x14\xb8\x73\x7e\x14\x7a\xa0\xf2\x31\x91\x57\x8f\xfd\x93\x82\x3c\xe4\xbf\x91\xc1\xd1\x10\x98\x2a\x5d\xa0\xe4\xb8\x1b\xd2\x5b\x9b\x9c\x21\x42\xa7\x67\x1e\xe9\x37\xc9\x0f\xd0\x71\x5e\xc9\xaf\xa4\x4d\x86\x04\x68\x98\xb4\x2f\x75\x35\x89\xd2\x26\x8d\x2a\xaa\xa9\x85\xcc\x90\xe0\xf9\xe8\x27\xa3\x92\x3e\x77\x16\x34\x6f\x4f\x89\x31\xc7\x28\x21\xb3\xeb\x64\x5d\xaa\x74\x52\xc8\xaf\xc8\x98\xd7\x97\x55\x45\xc1\x2d\xa1\xbd\xb2\x09\x04\x5c\xb0\x0f\x4b\xfd\x53\x83\xdf\x01\xf0\x03\x68\x0b\x97\x34\x40\xf1\xa3\x9c\x9d\x82\x09\x59\xef\x6f\x85\xbd\x33\x63\x90\x65\xae\xfd\xc8\xbc\xfe\xcb\xd9\xb9\x55\x40\x49\x73\x8a\xf2\x9f\x12\x94\x63\x9d\x39\x15\xd6\x32\x99\x5e\x8f\xaf\x71\x3e\xf2\xee\x3c\x29\x8b\x55\x96\xfa\x10\xc9\x9f\x94\x6d\xdb\x32\x34\x06\x95\xdf\x1c\x19\x45\x94\xea\xf3\x77\x8d\x73\xc8\xba\x60\x40\xc0\x4e\xb3\xa4\xff\x86\x77\x93\x6b\x88\xe0\xc5\xf0\x44\x14\x80\xd1\x07\xd7\xac\x22\x02\xb3\xb6\x94\xe5\x7c\xcc\xa6\xd8\x25\xe2\xa0\x7e\x81\x2e\xd2\x9b\x2c\x20\xd5\xc6\x05\x47\x15\x79\xe3\xed\xff\xc2\x23\xf2\x42\xc5\x93\x91\xdb\x41\xe9\x8d\x5f\x3d\x6c\x5b\x1e\x32\xac\x82\x37\xfc\xfd\x10\x20\x54\x3a\x40\x41\xe0\x3d\x92\xad\x3e\x2e\xc5\x52\x91\x47\x07\xc7\x7c\xd0\x1f\x3e\x48\x01\x14\x44\x28\x3f\x09\x68\xfa\x4d\xee\xee\x55\xc4\x56\xed\x1f\x87\x7a\xde\x04\xac\x8e\x8d\x2c\xb6\xc8\x58\x20\xb4\x92\x9b\x25\xbf\x31\xe9\x25\x43\x5d\x6b\xcc\x50\xd3\xe2\xe9\xb8\x51\x02\xe9\x70\xd7\x89\x5c\x25\xad\xe5\x21\x61\xa3\xb6\xbf\x50\x1a\xb0\x19\x61\xcb\x63\xed\x99\x0a\xeb\x93\xed\xa3\x82\x8b\xf0\x4c\xa5\x28\x53\xc7\xb6\xb8\xe9\xe4\x9e\x34\x9d\x69\xb5\x3b\xe0\x74\x85\xf5\x42\xb7\xcd\xd0\x6b\x52\x7d\x41\xdd\x11\x9c\x70\xb5\x64\xf1\xa9\x3a\xec\x62\xae\x74\xe6\xe8\xf8\x55"}, -{{0xae,0xb1,0x3c,0xcb,0x90,0xc8,0xcb,0xef,0x90,0xd5,0x53,0xda,0x3f,0x69,0x01,0xb3,0xd7,0x5c,0x13,0x01,0x1f,0x02,0x49,0x74,0xda,0xf7,0x9a,0x17,0x89,0xc8,0xc6,0x32,},{0x5f,0xaa,0xfe,0xb5,0x95,0xf1,0x6d,0x33,0x8f,0x1c,0x72,0xa9,0xf3,0xe4,0x98,0xf3,0x8b,0xab,0x69,0xa8,0x1b,0x37,0xd2,0xd0,0x92,0xb7,0xbf,0x7e,0x50,0x5d,0x82,0x0d,},{0x06,0x11,0xb1,0x9a,0x74,0x72,0xa4,0x43,0xe8,0x7e,0x54,0xd7,0xc6,0x64,0x7f,0xaa,0xb1,0xb7,0x9a,0x83,0xfd,0x43,0x71,0xc9,0x2b,0x97,0x54,0x00,0xfd,0x62,0x8a,0xcf,0xc3,0x25,0x77,0xcc,0xbb,0xaf,0x03,0xd8,0x8f,0x89,0x3c,0x88,0xf2,0xca,0xc7,0x84,0xc7,0x22,0xa0,0x8f,0x38,0x7a,0xbc,0x31,0x9a,0x70,0x2c,0x86,0x84,0x79,0x65,0x0b,},"\x86\x1a\x10\x18\xd6\xbd\xc4\x80\x5a\x5c\x4d\xf8\x7e\xfa\xa4\x62\xc6\x8b\x4b\xf4\x06\x5c\x68\x4c\x2a\xf1\x31\xc6\x37\x73\x88\xba\xee\x58\xc6\xc8\xf8\x84\x23\x62\xec\x6e\x3b\xce\x07\xc8\xaf\x55\x88\x5e\x82\xdb\x87\xa1\x52\x27\x80\x0d\xd3\x3a\xfc\x5e\x5f\xd1\x57\x01\xe9\x5f\x53\x50\x1b\x1a\x6f\xf8\x3c\x64\xe8\x51\x71\x49\xbf\x3f\xf0\x11\xb0\x94\xa0\x9c\x67\x3d\x0f\xc4\xa3\x9e\xe5\x5e\x69\xf0\x71\x17\x7b\x8a\xa3\x64\xe1\xe2\x56\x06\x4c\xf7\x02\x79\xcc\x76\x69\x5a\xe4\x9d\xaf\xcd\x80\xca\x0a\x14\xe1\x69\x1d\xb9\x46\x42\x2e\xc7\x5a\xb4\xf7\x86\x59\x15\xa6\x9b\xd4\x8d\x89\xb1\x2a\xdf\x48\x7d\x4d\xb9\xbe\x87\xcd\xdc\xa2\x11\xaa\x88\xe9\xbb\xe8\x49\xda\x21\x39\x89\xeb\x08\x44\x59\x2a\xd6\x3e\x28\x1b\x2e\x4a\xfe\x6a\x88\x36\x00\x66\x09\x92\x6c\x0f\x78\x7e\x84\xf2\xa9\x5b\x46\xb6\x6f\x0e\x45\x55\xc9\x48\x3c\xe2\x17\x6f\xc6\x3f\x7c\xc9\xf4\xf2\xa2\x2d\xb0\x55\xaa\xe2\xe6\x8b\x30\xa0\xda\x5f\xeb\x80\xc2\xa6\x0e\xa1\x0d\xbf\x67\xfb\xbc\xdb\xe0\xbe\x33\xf2\xe9\xc1\x3c\x46\x9e\x77\x68\xf2\xff\x59\x60\xa5\x5e\xb4\x82\xec\x11\xd4\x7e\x15\x4b\x7c\x42\xa5\xfb\x75\x6c\x8a\xd5\x39\xb3\x3d\x12\x5a\x4a\x65\x19\x2c\x6c\x9b\xd5\x76\x23\x8c\xa7\x2a\x73\xcd\x17\x9e\x8c\xf5\xcd\x04\x8e\xd3\x30\x21\x38\x23\xab\xba\xfc\x36\x82\xb2\xb7\xf6\x8c\x5b\xc4\x6f\xd0\x9a\x8c\xb2\xa3\xfd\x09\x95\x73\xee\x2e\x6f\x28\xc8\x2e\x27\x1b\xb5\xef\x93\x4b\x0b\x0c\x38\x1c\xfa\xae\xc6\x66\xd7\x17\x10\x6a\x87\x4a\xf3\x0a\xa7\x41\x25\xea\xe9\xac\xc2\xf1\xf2\x41\x18\xcb\x4e\x68\x3a\x73\x1e\x37\xe5\xe4\x64\xa1\xea\x3d\x2a\x53\xcc\x0d\xca\xd4\xc1\x7c\xea\x9a\x43\xe2\x36\x5f\x3a\xe3\xdd\x89\xeb\x39\x97\x74\x20\x04\x55\x50\x74\x5f\xc2\x67\xfc\x7d\xcc\x56\x02\xe9\x14\x97\x2a\x4d\xa6\xeb\xeb\x68\x7f\x68\xa0\xcd\x7d\x8b\x4f\xdd\x73\x72\x21\x06\xa8\xe4\x36\xb9\x3e\x5b\x58\xf5\x98\x2a\xce\xcd\xec\xfd\xb3\x82\xfe\x98\x53\x82\x61\x42\x6b\xa6\x40\x52\x55\x76\x43\xce\x9f\xec\x71\xea\x43\xcf\x5b\x6c\xba\xde\xb4\x95\x31\x93\xff\x3e\xd1\xa1\xf9\x22\xa9\xaf\x2e\xc6\xf3\x38\xe7\xfb\x0a\xff\xe3\xd1\x3c\x33\xe3\x95\x87\x3e\x4a\x7a\x7f\xb0\x44\x98\x1e\x05\xa6\x71\x97\xb9\x96\xb1\x99\xb4\x30\x11\x11\x93\x63\xe5\x61\xd5\xb8\xa5\x17\x84\xfd\xff\x58\xab\x80\xed\x4c\x49\xe9\x3f\x0c\xf4\x19\x24\xf9\x83\x5e\xfb\x09\xf6\x44\x63\xb6\x55\x17\xb6\x7b\x15\xdc\x3f\x28\xad\x9a\x9b\x2d\x29\x46\x8d\xe2\xc6\x3e\x62\x00\x4b\x6a\x3f\xd0\xc5\xc2\xe2\xaa\xa6\xcf\xa1\x5e\x4f\xaa\xfa\x1e\x2c\x71\x3e\x98\xd3\xfd\x25\xca\xb9\xe5\x17\x03\x59\xc8\x36\x51\x52\xb4\x74\x27\x6e\xd0\x03\x7c\xdf\x77\x18\x28\xe2\xfb\x7c\xce\xc4\x89\x5f\x21\xad\xcc\x5b\x68\x87\xc8\x6e\x51\xad\x05\xf2\x55\xf6\xe9\xda\xd2\xc4\x1f\x56\xb9\x8b\x7b\xbb\xf9\xfc\xb6\xba\x8c\xad\xfd\x38\xad\x8c\x62\xf9\x2d\xd8\x77\x40\xfa\x1e\x1b\xd1\x70\xc0\x0b\x20\x49\xc5\x13\x0f\xe7\x33\xf1\x6b\x1f\x2c\x7f\x00\xb2\xef\x97\xb3\xa9\x54\x58\xc5\x3f\x19\x9d\x46\x53\x36\xd5\xff\x59\x77\x80\x6e\x1a\xfd\xe3\xea\xa2\x46\xd8\x5c\xab\xf7\xe1\x23\x48\x1e\x23\x92\x99\x76\xed\x19\xc4\x0e\x29\xff\x33\xd8\x0e\x7d\xea\xb1\x92\x71\xde\xcd\x5e\xe0\x61\x72\xb0\xb0\xa1\x39\xbd\x62\xa2\xe7\xc8\x3a\x8a\x65\x60\x1d\x0a\x05\xd6\x1a\xf9\xc6\x03\x2d\xf5\x80\x01\xd4\x73\xe2\x0d\xd6\xc6\xaf\xd7\x8d\xdb\xd7\xcd\x17\x8e\x9c\x27\x1e\x05\x72\xf8\x59\x82\x82\x3c\xe6\xc4\x02\x93\x0c\xf8\x0f\x5e\x0c\x7c\xda\x85\x12\x2a\x76\xd1\xce\x02\x1b\x1e\x3d\xe2\x55\x6d\x1b\x45\xac\x7b\x01\xb5\x9c\xad\xa2\x52\x91\xd6\x38\xa5\x2a\x5e\x7d\xbc\xdd\xf9\x6b\xb1\x77\x4a\xb0\xb0\x77\xe4\xb3\xda\x5a\x95\x8f\xe1\x1d\xee\x4a\x02\xe6\x9b\x91\x8d\xdb\xfa\x1c\x5b\x3b\x7d\xca\x9f\x87\x84\xbb\x6b\x0b\x9d\x5a\x7f\xee\x74\xbb\x03\x74\x7f\x61\xc2\xb2\xf1\xb4\x92\x45\x2d\x3b\x56\x0b\x48\xd3\x9d\x87\x21\xe9\x83\x75\x25\x56\xd4\x4d\xa6\xb0\x28\xd9\xae\xf8\xbf\xf9\xaa\x37\x9c\x8e\x2b\x0a\x63\x6d\x74\x88\x60\xab\xd8\xe6\x4f\xc8\xe9\x65\x20\xa3\x4a\x27\xf7\x67\xaa\x97\xa8\xf7\x7b\x60\x95\x21\x8e\xad"}, -{{0x73,0x87,0x2b,0x14,0x76,0x2f,0x68,0xda,0xe4,0xfc,0x10,0xdf,0xd6,0xf4,0x2d,0x3f,0x96,0x22,0xbf,0x2a,0xfe,0x6b,0x34,0xa9,0x56,0x49,0xaa,0x38,0x74,0x24,0xee,0x6c,},{0xdf,0xab,0x2c,0xe1,0xab,0x99,0x81,0xaa,0x7c,0xbf,0x32,0x07,0x35,0x00,0x07,0xfa,0x6c,0xe6,0xca,0x60,0xa2,0xed,0x7b,0x59,0x0f,0x3c,0x2f,0x62,0x92,0x2d,0x8f,0x61,},{0x85,0x25,0xc3,0x46,0xca,0x3a,0x6a,0x6c,0x5f,0x65,0xc4,0x17,0x78,0x59,0x93,0x77,0x65,0x98,0x70,0xcb,0x6d,0xf9,0xa4,0xa0,0xe5,0x5b,0x40,0xc3,0x5b,0xeb,0xa5,0x5c,0x8e,0x00,0x9e,0x56,0x00,0xb6,0x44,0x7d,0xc7,0x40,0x2b,0xa2,0x77,0x49,0x29,0x7e,0x8f,0x95,0x28,0x69,0x18,0x56,0xf7,0x2d,0x2a,0xd7,0x61,0xed,0x1b,0xc1,0x53,0x09,},"\x43\x3d\x71\x78\x1c\xea\xb2\xb4\x7d\x82\x6e\x67\xd3\x9f\x9b\x80\xd2\xff\xd7\x25\xf8\xc5\xae\xb4\x0c\xbe\x4f\x9b\x5f\x48\xef\x93\x52\x1c\xce\xc6\x04\x36\x0b\x96\x47\x32\x31\x90\xbf\xef\x75\xac\x93\x15\x62\xd2\x7f\x4a\x4e\x31\xf4\x6e\x57\xbc\x99\xfa\x51\x58\xc8\x2e\x12\xb7\x37\xe4\x5c\x5d\xe9\xf7\xdd\x7c\x86\x22\xd4\xa7\xea\xad\xf7\x20\x2f\xb4\x9d\x81\x9c\x9a\xd2\x4f\x88\x07\x31\x3c\x5f\x37\xdc\x20\x45\x3b\xdf\x05\xc9\xbf\x1a\x3c\x21\x17\xc9\x3e\x7f\x3c\xc8\xa2\x54\x20\x98\xe8\xfc\x1c\x64\x2f\xa4\x7b\x05\x54\x36\x57\xb8\x5f\x48\x0b\xc8\x6e\xc4\x28\x00\xbb\x14\x22\x35\x9c\x7c\x3e\x8f\xf4\xbe\x59\x8b\xd5\x4f\x1d\xc5\x86\xac\xae\x45\xa4\x74\x06\x22\xb9\x62\x74\x2b\xc8\x6e\x17\xcf\xa6\x3e\x77\x53\x54\xe7\x70\x7e\x50\x79\x58\x9e\x8d\x10\x8b\x1f\x11\xda\xce\x05\x75\xcb\x9a\x6d\x26\xb5\x9f\xce\x98\x14\x65\xd9\xbc\x34\x4e\xa6\x94\x5a\x95\xb8\x62\x79\x63\x84\xfa\x81\x70\x56\x08\x57\x45\x7b\xef\xf9\x5a\x9b\x5a\xc3\xd6\xad\x28\x2d\x44\x92\x9a\x30\x30\x26\xb4\xbb\xed\xd6\x0e\x2e\xf0\x55\xa3\x1f\x52\xd7\xce\x8d\xf2\xca\x5d\x18\x51\xc5\xb1\x67\xdb\x08\x09\x25\x9b\xb8\x12\x56\x90\x74\x10\x5c\x73\x4c\x85\xd6\x23\x12\x73\x75\x5f\x3a\x8b\x56\xdc\x50\x8d\xb5\xc2\x3d\xac\xb7\xa0\x61\x67\xbd\xa5\x1b\xc0\x13\x50\xf0\x16\xcd\x41\xb2\x1e\x8c\xc5\xbc\x93\x34\x3a\x9b\xb6\xea\x47\x38\xc5\xc8\x4b\x78\xfa\x96\x3c\x41\x0e\x43\x3d\xc5\x98\x19\x6c\x22\xe5\xb7\x91\xe1\x2a\x4b\x34\x3f\x7c\xd4\x7b\xbb\x0e\xb0\x78\x2b\xdb\x1a\x4e\x46\x68\x46\xa0\x30\x52\x8e\xeb\x89\x05\x6f\x73\x25\x71\x93\xad\xaa\xbc\x1b\x22\x98\x62\x03\x48\x78\xc3\x25\x8a\x53\x25\x48\x76\x2e\x29\xec\xc0\x01\xab\xd9\x89\x64\x9d\xa5\xe1\x44\xcf\x35\xd4\x86\x99\xf2\x3b\xc4\x6c\x5b\x34\xe0\x4a\x53\xe7\x27\x24\xb2\xb0\xb8\x78\x98\x25\x75\xd6\x88\xe2\x3c\xbe\x3a\x34\x06\x7f\x49\x71\xe5\x55\x97\x2e\xc2\x90\x8a\xe5\xf0\x3e\x88\x31\xec\x67\x75\x5b\xe9\x56\x87\xce\x63\x72\x93\x9e\x1e\x2f\xb6\x95\x1e\xc9\xec\xf4\xbf\x7d\x15\x35\x43\x1e\x25\x9f\x29\xad\x43\x12\x22\xb5\x4b\x65\xaa\x7d\x07\xcf\xb5\xdf\x16\x2a\x87\xc4\xd0\x34\x81\xeb\x44\x1f\x22\x1d\x7f\x58\x62\x7a\x14\x16\x4e\x7f\x4c\x2e\x3a\x1d\x50\x7e\x89\x9d\x53\x58\xe0\x08\x29\xb0\x8c\xf3\xae\xcb\x8a\x75\xb2\xa3\x1c\x31\x85\xa5\x80\xe1\x2b\x13\xf0\x64\x28\x69\xff\xfb\x05\x67\x23\xe9\x61\xaa\xf6\xfe\xfe\x67\xb4\xa7\xc4\xc9\x3d\xb3\xfe\x1f\x61\xad\xcc\x76\x55\x69\xa9\x9c\x09\xa3\xc8\x24\xed\x4a\x98\xba\xbe\xae\x43\xef\xb1\xf3\x51\xba\x13\x0e\x22\xaa\x97\x81\x19\x86\xbe\x92\x3c\xc4\x18\x0a\x7c\x4b\x78\xbc\xc1\x40\xce\xc1\x55\x74\x65\x4a\xa6\xd6\x5a\x06\xb9\x7e\xcf\xa5\xf3\xa9\x35\x5f\x96\xe4\xee\xaa\x76\x89\x21\x7b\x66\x3f\xba\x4d\xab\x0d\x99\xb1\x9c\x8d\x8d\xbf\x47\xa1\x57\xe5\xd5\x96\x9a\x35\xef\x84\xdf\xf9\x56\x2e\xdd\x43\x4e\x73\xae\xe7\xd0\xd8\x92\xdd\xa7\x2a\x36\x2a\x22\xa7\xe9\xfa\x86\x34\xa5\x7e\xeb\xd1\xa9\x07\x48\x5c\xa8\x92\x1b\xdc\x19\xee\x9e\xe5\x88\xf3\x95\x68\x7d\x3f\xc8\xf8\xc2\x5f\x2e\x95\x76\xca\x60\x31\x3f\xbb\x2c\x26\x5a\x99\xf2\xcd\xd5\x57\x5b\x1d\xd5\x30\x60\x4e\x9a\xd6\x69\x5c\x9f\xb3\x59\x94\xa8\xb8\x7d\x5c\x85\x70\x54\x9a\x4d\x32\x9b\x9f\xe0\x87\x06\x9a\xb7\xeb\x0d\x71\x4a\x94\xe1\x92\x61\xf8\x6e\x44\x8f\x2d\xa9\xb1\xcb\x0c\x0d\xbe\x41\xd4\x4c\x3a\x82\x47\x83\xd1\xbd\xbd\x73\x26\x05\x1a\xeb\x10\xad\xab\x80\x5c\x5c\x59\xd0\xe8\x3b\x1c\x11\xa2\xfd\xd3\x5e\x44\x4a\x49\x9e\xd1\x5d\xaf\xd8\x38\x62\x77\x5f\x6c\xdf\xc6\x75\x95\x81\x84\x07\xbe\x55\xec\xbf\x7b\xf8\x6c\x73\x06\x9a\xac\xe5\x77\x62\x6a\x85\x63\x53\x6f\x60\x50\x42\xcf\x7c\xaa\xf6\xfc\x8e\x3b\x54\x5b\x77\x41\x4d\xf8\xd9\xf6\x49\xb9\x9e\xe4\x25\x41\xda\x38\xc3\xaa\xe6\x27\x20\x78\x45\xb8\xf4\x14\xa8\x07\x4d\x70\x86\x8a\x5c\x0b\x07\xb0\x70\xc3\xc6\x53\xbe\x04\x07\x6b\x83\xca\xd7\xb0\x30\x5d\x95\x00\xaa\x44\x45\x5c\xb8\x60\xdc\xc7\x64\x00\xaf\x93\xc3\xd2\xef\xb4\x2a\xe0\x56\xf1\x42\x8b\x65\xf1\x22\xe1\xc7\xb9\x58\x4d\x81\x4d\x50\xac\x72\xef\xdb"}, -{{0x67,0xcf,0x27,0x15,0x52,0x87,0xbe,0x6b,0xfa,0xb6,0x62,0x15,0xe0,0x17,0xc3,0x46,0x63,0x22,0xf2,0x1e,0x6e,0xb1,0x40,0xbe,0x4f,0x1b,0xde,0xcf,0x55,0xab,0xfd,0xc1,},{0xd0,0x70,0xaa,0xb2,0x95,0xa8,0xaf,0x93,0x57,0x27,0xc3,0xbe,0x44,0x2b,0x25,0x1d,0xb9,0xe7,0x74,0xd2,0xf4,0x4b,0x3c,0x24,0x24,0xc5,0x2f,0xc8,0x96,0x56,0xe1,0x69,},{0xc9,0x34,0xa3,0xa1,0xaa,0xab,0x78,0xd9,0x26,0x9d,0x1e,0x9d,0x13,0x39,0x2f,0x72,0xc6,0x37,0xbc,0x5d,0xe5,0x4f,0x04,0x69,0x1e,0xfc,0x29,0xd4,0x73,0xb4,0x75,0x02,0x5d,0x8d,0x8f,0xe3,0xc5,0x23,0xd2,0xd2,0x9c,0x41,0xc5,0xf3,0xde,0xc6,0xca,0x38,0xce,0x6d,0x68,0xd7,0xff,0x09,0xb6,0x13,0x5b,0xa2,0x4d,0x0d,0x32,0xcc,0x15,0x02,},"\x0f\xf0\x52\x97\x03\x1c\x89\x27\x74\xcb\x2c\x01\xe8\xca\x60\xdd\xd0\xce\xac\xc0\xb8\xd5\x91\xa8\x91\xe3\x3b\x19\xe1\xbe\x9e\x36\x3b\xc6\x42\x0d\x6f\x52\x9f\x04\x84\x0b\x3b\x08\x85\x3c\x83\x5a\x03\xe0\x36\x97\x8b\x04\xa4\xf9\xec\x6b\xe4\xae\xf3\x31\x95\x61\x90\x99\x6d\xea\x27\x26\x19\xf1\x68\x6d\x33\xbe\xf0\x3d\xbc\x08\x5a\x92\x3a\x0f\x11\x5b\x78\xf6\x53\xfe\xeb\x60\xbb\x9e\x45\xf3\x4f\xb8\xbe\x5a\x4c\xbb\x64\x8c\x7d\x29\x95\x6f\x0d\x0e\x96\xbd\xd3\xc8\xd0\x64\x97\x20\x62\x4c\xbc\x20\x79\xe8\x4f\xd6\xd0\x10\x24\x11\x24\x09\x84\x59\xf1\x2a\xf2\x99\x1d\x38\x28\x77\x0f\x50\xb1\x04\xea\x6e\x5f\x51\xfd\xad\x30\xa9\xb8\x07\x9d\x21\x59\xe4\x6d\x64\xaf\x91\xd0\x7c\x10\xed\x19\x81\x4d\xf2\xaf\xe6\x60\xd7\xd8\xf2\x40\x35\x34\xe9\x2c\x62\xe1\xea\x6d\x68\x82\x03\xbc\xa3\xd9\x7c\x2a\xfd\xa8\x3b\x25\x55\x20\xff\xe9\x2a\x33\x62\x57\x72\x51\x3b\x1f\xe3\x4f\xaf\xe3\x2b\x6a\x9b\x8c\xf9\x94\xdf\x7e\x63\x4e\x68\x65\x91\xe5\xf0\x07\x3a\xba\xbc\x64\xa8\x92\x10\xba\x53\xa4\x99\x1c\x11\x55\x7e\x03\x34\xe6\xc6\xa5\x03\x6c\x64\x2a\x31\x8f\x22\x95\x11\x71\x39\x08\x5f\xb3\x40\x75\x64\x70\x06\x75\x8e\x32\xbc\x00\xad\x10\x9f\xe8\x03\xf7\xee\x9f\x5e\xc2\xaf\x4d\x25\xc3\x07\x0a\xbc\x51\xcf\x4d\x78\xe1\x3a\x7c\xe2\x83\xd4\xfb\x4e\xb4\x1d\x3e\x8c\xe9\x02\x38\x50\x0a\xe0\xce\xda\x32\x0e\xc5\x92\x2e\xfa\x10\xb9\x03\x74\x8e\x1e\x85\x3a\x37\x29\xd2\x4c\x10\x54\x39\xdf\x2f\x70\x00\x12\x3d\xb9\xb2\xc0\x15\x33\xbb\xf0\xd0\x28\xeb\xb2\xfc\x00\xdc\xe3\x8a\xd0\x63\x28\xee\x9e\xcd\x84\x9a\x6e\xfc\x3a\xe8\x84\xef\x69\x33\xcf\xeb\xed\x05\x5b\xb2\x96\x8a\x0b\x06\x76\xb5\x72\x92\x16\x17\x8c\x75\x19\xef\x07\x88\x59\x3f\xc0\xdc\xff\x50\xd7\xe0\xb1\xeb\xb3\xcf\x49\xbb\xd1\xbf\xa5\xc3\x0e\xa7\xb8\x8c\x36\xe1\xa1\x59\x3a\xef\x0b\xb3\xf9\xe2\x09\x1c\x85\x89\xf7\x41\x4b\xee\xd8\xdf\x46\x6a\x2e\xd8\x7b\x2c\xb5\xf3\x5f\x1d\x31\x24\x6c\xeb\x96\x86\x09\x25\x36\x15\xd7\x80\x43\x51\x73\x79\xee\x69\x74\xa6\x69\xcb\x48\xda\x6a\xc2\xf9\x6d\x70\x0b\x7e\x44\xa4\x35\xcf\xef\xec\x40\x2a\x1e\x31\x10\xe7\x69\x81\x92\x4f\x26\x01\xc0\x1d\xc0\x35\x46\xfd\x4f\x51\x16\x49\x30\x2f\x06\x33\xdf\xbd\x25\x65\x1c\x5a\x59\x9c\x90\x95\x44\x89\xc7\x6a\x65\xec\x05\xa7\xe4\xcc\x74\x61\x6c\xe2\x56\x01\xcc\x37\xb8\x04\xe1\xf0\xbc\xc8\x65\x10\x23\xb1\x2e\x13\x56\x84\x41\xe8\xb8\xef\x4c\x30\x5f\xcd\xad\x3d\x2b\x13\xfa\x08\x03\x24\xb2\xfd\x6b\x61\x99\x8c\xf8\x64\xb6\x58\xbc\x7f\xef\xcc\x48\xa5\xa7\x68\x1d\x7c\x86\x6c\x34\x2c\x7f\x5d\x6c\xf1\x08\x81\x52\x2c\xc7\x10\x25\x7d\x25\xa4\xc1\xe3\x52\xd2\x70\xe9\x02\x08\x2a\xb9\x54\x1d\x59\x00\xce\xff\xa0\x91\x4b\x16\xb5\x5e\x0d\xd3\x78\x6e\x98\xd4\x17\x20\x87\x5a\x14\x8e\xb4\xab\xdb\x01\x53\x85\x66\x79\xfb\x98\xc0\xec\x48\x5e\x5f\x45\x8d\x63\x5b\x78\x61\xa2\xb3\xa8\xba\x5e\xc2\xc1\x44\x4d\x35\x39\x80\x20\x0e\x5e\x07\x18\x08\x85\x4a\x26\x8c\xc7\x6c\x60\x5c\x94\xf3\x73\x29\xc3\x61\x87\xa4\x1f\xdd\xf9\x2a\xab\xdb\x49\x96\xa0\xe1\x0b\x31\x55\x26\xaf\xea\xc8\x0e\xb2\xfa\x32\xaf\x78\x6a\x34\x31\x6b\x36\x11\x1e\xe9\x35\x21\x08\x14\x4d\x70\xf7\xd1\x72\x3b\x32\xf4\xdb\xaa\x82\x20\x13\x53\x41\x1d\x65\x77\x13\xe5\x5e\x35\xdf\x78\x58\x0b\x1b\xc0\x86\x80\xf0\x15\x9f\xa1\x16\xfa\xf4\x63\x56\x6a\xaf\xe8\xae\xa6\x98\x57\xe7\x2e\x44\xac\x80\x9a\xc4\x3f\x5c\x45\x93\x9d\x85\xa1\xa5\xf4\xa3\x70\xa1\x89\x96\xc8\x51\x4a\x46\xf3\x43\x71\xef\x9e\x5f\xb2\x04\x42\x2c\x93\x4a\x1d\x29\x3d\x10\x1b\x8c\x16\xf9\x9c\xc0\x73\xea\x36\x6a\x13\xa4\x5c\x43\x7d\x62\x0d\x13\x2b\x74\x40\x9c\xbf\x8b\x9c\x07\x5b\x41\x63\xf7\x26\xaa\x67\xe5\x09\xa2\x48\x74\xfc\x1b\x1f\xb6\xfb\x7c\x73\x55\x15\x9c\x02\xaa\x13\xe6\x4b\xad\xf1\x50\x35\x6b\x18\x41\xb3\x21\xf8\x04\x1e\x13\xed\x77\xe8\x46\x1c\xfb\xb8\xe8\x28\x48\x8b\xf5\x17\xa5\xd2\x9f\xf8\x2e\x73\x67\x48\x0a\x8e\xdd\xde\xb5\x35\x0e\x7a\x83\x42\x3b\xd0\xb1\xc5\x5f\x7b\xb4\x24\xca\x04\xc2\x05\x72\x3c\xd5\x40\x56\x71\xe7\x33\xf3\x91\x60\x0a"}, -{{0x18,0xc2,0x1c,0x0d,0x0d,0xe1,0x3d,0x4c,0x64,0x49,0x7e,0xf0,0x26,0x0d,0x66,0xcf,0xd3,0x42,0x16,0x98,0x1a,0x1b,0x49,0x39,0x1a,0xe5,0xcb,0x0e,0x41,0x43,0x6e,0x9f,},{0xf7,0xd4,0xdd,0x1e,0x05,0x9c,0x36,0xf6,0xd1,0x21,0xc0,0xaf,0xfe,0xb2,0x1f,0x0c,0x57,0x2b,0x45,0x99,0x2f,0x84,0x94,0x8b,0x09,0xaa,0xfb,0xcd,0x86,0xbb,0x53,0x5c,},{0xc9,0xc0,0x99,0xe2,0x1d,0x09,0x5a,0xfa,0xdd,0x4e,0x71,0xc9,0xab,0xf6,0xb7,0x08,0x33,0x24,0x77,0x62,0x25,0xb5,0x87,0xb6,0x0a,0x0e,0x60,0x92,0xec,0xb3,0xd3,0x3c,0xff,0x39,0xc6,0x7d,0x34,0x77,0x6a,0xe9,0x9d,0xda,0x75,0x4a,0x3c,0x2b,0x3f,0x78,0x11,0x35,0xa3,0x8c,0x78,0xed,0x64,0x55,0xaa,0xf0,0xae,0x0c,0x31,0x3b,0x62,0x05,},"\x68\xab\xca\x7c\x16\x6a\xfe\x06\x3e\x47\x7b\x80\xe3\x7d\xb2\x24\xe1\xa2\x35\xde\x8f\xcd\xeb\x7f\x42\x7a\xf6\x7e\x00\x12\x47\xcc\x5e\x05\x71\x82\xfd\x9b\x6d\xb8\xba\xba\xa6\x58\xcf\x3b\x3f\xe4\xb0\x76\x3b\xf8\x8d\x67\x31\x1b\x11\x90\xbe\x83\x40\x18\xcf\x57\xa3\x32\x92\x24\x13\x76\x46\x20\xac\xe0\x54\x45\xee\x01\x9a\x06\xdf\xf9\x8b\x23\x89\x79\xad\x6d\x30\x90\x1b\xef\xa3\xc6\x4f\x6b\xd8\xc6\xeb\x09\x2c\x2e\x62\x84\x13\x88\xfd\x8c\x4e\x84\x19\xe2\x77\x89\x84\x89\x67\x37\xed\x90\xa2\xcd\xb2\x19\x96\xae\xf7\xc2\x16\x38\xd6\xcb\xe6\x80\x32\x2d\x08\x99\x65\x97\xa9\xe3\x03\xf6\xf5\xf4\x79\x40\xf8\xc5\xba\x5f\x5f\x76\x38\x3e\x7e\x18\x06\x4a\x3d\x2d\xff\x5f\xdf\x95\xe9\x0c\x5e\xb3\x0f\x4d\x8d\x45\x9e\xe1\xd5\x06\xa8\xcd\x29\xcd\xc6\x9b\x67\x54\x96\x3b\x84\xd6\x74\x94\xb3\x53\x05\xd1\x0d\x12\xb9\x48\x74\x17\xb2\xce\x28\xad\xcb\x10\xb6\x5c\xc9\x31\xfb\x33\x81\xae\x02\xe7\xaf\x79\xa0\x2b\xf9\x9e\x25\x8a\x56\x36\x10\x90\xe0\xb7\x12\x22\xb3\xac\x60\xbf\x2f\xb7\xba\x83\x2d\x03\x4f\x5b\x6b\xc6\xfa\x66\x3a\xe7\x41\xf7\x6d\x97\xc1\xac\x32\xbc\xb7\x41\x15\x07\xd5\x18\xd2\xf6\x05\x4b\x57\x83\x28\xc5\xf6\x7f\x75\x8a\xc0\x1b\xfe\x6f\x4d\x35\x90\x0f\x50\xa5\xdc\xd3\x0d\x2f\x92\x61\xb6\xbb\xec\x4c\x1d\x1f\xc1\x8d\x2a\x7e\x70\xc4\xd3\x6c\x21\xfa\xf8\xcf\x94\xa5\x87\xc3\xa0\xd1\xa9\xcd\xe7\x83\x1a\xe6\x26\x77\x54\x68\xdd\xcd\x40\xa8\xba\x18\xf4\x2b\x34\x18\x8d\xe5\x74\x1e\x1b\xe8\x30\x7b\x10\x84\x58\x65\x15\xec\x01\x5e\x4e\x37\x1d\x29\x44\x3a\x40\xb0\xc0\x69\xc6\x41\xd8\xce\xe5\xe4\x61\x18\x62\x98\x7c\x3e\x35\x6b\x12\x93\xb0\x51\x8b\x4a\x4c\x8e\xa9\x7f\xc5\xa4\xdb\x1f\x01\x29\xab\xee\x72\xfb\x80\x92\xea\x35\xc2\xda\xb6\x75\x73\x85\x02\x07\xb8\xe8\x27\x18\x99\x9a\xd9\x9c\x4c\x83\x9e\xac\x14\x63\x6b\xd5\xe4\xd8\x43\x6a\x27\x0d\xd9\x0b\x8e\x32\x13\x02\xe5\x2a\x92\xd8\x91\xff\x18\x91\x54\x2a\xe2\xca\xa0\xd6\x6e\x0f\x66\x1e\xae\x37\xb2\x5b\x08\xbb\x2e\x0e\xee\xc4\x83\x80\x09\x77\x8c\xd5\x25\x98\x43\x80\x98\x3b\x2b\xaa\xdd\x71\x02\xa1\xe3\x56\x73\x4e\x41\xd7\x61\x83\x82\x9e\xa9\xab\x82\x44\xc3\x36\x59\x7c\xa2\xd6\x79\x88\xf2\x81\x43\x84\x67\xe4\x53\xf5\x62\xc6\x7b\x22\xd0\xa4\xdd\x9f\xcb\x46\xa5\xf8\x0d\x29\x9d\xb5\xf0\x1f\x59\x16\x0a\x19\xd7\x4c\x64\x4f\xa5\xa9\x40\xe3\x2c\x9d\x8d\x98\x3b\xab\x7e\xfb\x0d\x7c\x7d\xa4\xe3\xfd\xa1\xcd\x0d\x18\xa4\x55\x8e\xb9\xfe\x46\x40\x8a\xab\x50\x85\x91\x2b\xf2\xf4\x6a\xb6\x3a\x93\x54\xf9\x02\x7c\x93\x69\x12\x23\xff\xaa\xb8\x46\x3b\xac\x4c\x4b\xc3\xb1\x1a\xbc\x46\xba\x68\x71\x7c\x91\x78\x0d\x3f\x30\x47\x0d\xbd\xd8\x8b\x37\x80\xa1\x94\xc8\xa4\x0a\x2c\x0a\x81\xa4\xd5\x6d\xec\x2d\x89\x62\xc3\x4d\x2a\xb7\x33\x69\x02\x8e\x1b\xfe\xaa\x6b\xb5\x82\x41\xff\x4f\x89\x8f\x80\xad\x3b\xb1\xc6\x91\xb8\x64\x7f\x2c\x69\x83\x95\x4c\x1c\x77\x95\x74\x58\xee\xbf\x1c\x50\x55\xc3\x16\x93\xab\xce\xd0\x53\x84\x73\x5a\x4f\x74\x19\x68\xbd\x6a\xc3\x15\x65\xcf\xee\x71\xc8\x84\xc1\xe2\x9e\x9e\x7a\xe0\xf7\xec\xd0\x4d\x46\x3b\x1d\xc3\x89\xc3\x60\x37\xe8\x14\x58\xdc\xec\x61\xd0\x76\x40\x32\xdd\x58\x9b\x92\xaf\xda\x2f\xc9\x02\x8f\x41\xab\x53\xcc\xa2\xd0\x4e\xc6\xa9\x56\x59\x55\xcb\xcf\x1a\x34\x63\x98\x9c\x71\x39\xbb\x90\x2a\x59\x21\xe8\xb2\xc9\x9c\x48\xe1\x37\x11\xf0\xbc\xc3\x99\x25\x95\x16\xc8\x1a\xe9\x42\xa6\x79\xd4\xba\x33\x97\x9e\xb1\x2f\xcd\x28\x60\x60\x2e\x47\x24\xb1\x33\x0f\x1c\xd2\x57\xb5\xb2\x89\x1d\xae\xe8\xef\x4c\x92\xfc\x3b\xfd\xb3\x4e\x53\x2d\x58\x70\xf3\x80\x59\x86\xac\x97\xb5\x03\xfd\x85\x87\x35\x48\xe3\x09\x50\x00\x0f\x8a\x70\xbe\x51\xfa\x75\x76\x03\x50\x1f\x2d\x30\xe8\x52\xef\xea\xc4\x82\x68\x62\xae\xd7\xf6\xd2\x0c\x9a\x8c\x8d\xbe\x36\x2d\xfe\xe4\x18\x93\xf2\x7e\x6f\xd5\xe9\x1d\x0e\x7e\x3d\x4f\xd8\x15\x5f\x44\xfd\x8e\xf1\x7a\xf1\x4a\x84\x8d\x44\xa8\x76\x31\xae\xee\x75\x14\x62\xb2\xa5\x40\x87\x06\x8d\xae\xab\x3e\xa3\x28\x9e\xce\x62\x12\xb3\xb5\x2c\xe7\xa8\x88\x6d\xf2\xa7\x27\xb7\x2a\x57\x0c\x2f\xb9\xc5\x03\x41"}, -{{0xdb,0x9a,0xae,0xe1,0x98,0xcd,0x26,0xa5,0x2b,0x11,0x81,0xfa,0x3f,0xd9,0x2a,0xbe,0x42,0x5e,0x66,0x6d,0x89,0x0b,0xf9,0x69,0x46,0x7d,0xd2,0xce,0x28,0x0e,0xd4,0xa7,},{0x3c,0x89,0x7c,0xaf,0xe2,0xb4,0x99,0xec,0xb2,0xe1,0xdd,0x01,0xea,0x55,0xf3,0xfc,0x88,0xf6,0x8c,0x25,0xb6,0x4a,0x63,0x6b,0x31,0xa1,0xfd,0x1c,0x78,0xf3,0x7f,0x3f,},{0xb2,0xe3,0xd9,0xc5,0xd0,0xff,0x32,0x99,0x96,0xbc,0x89,0xd2,0x6f,0xb3,0xac,0x12,0x6b,0xde,0xd3,0x13,0xcb,0xf8,0xdf,0x86,0x71,0x86,0x38,0xc1,0x99,0xe0,0x57,0x27,0x3d,0x09,0xeb,0x16,0x3c,0x6c,0x18,0x1f,0xd8,0xbc,0xe5,0x1f,0x72,0xd4,0xd9,0xd2,0xe8,0x4a,0xbb,0xe0,0x83,0x30,0x77,0x3b,0x9f,0xcc,0x21,0x66,0xf1,0x40,0xd6,0x0e,},"\x47\xfb\x62\x15\x61\xf8\xb7\xee\xce\xc6\x03\x3f\x2b\xcb\x6f\x43\xac\x68\xc9\x58\xdf\xd2\x65\x6f\x52\xa0\xc2\x9b\x4a\xcd\x44\xf4\x30\x4c\x6b\xf7\x7e\xea\xa0\xc5\xf6\xd3\xb2\x2d\xb1\x96\x99\xc3\xdc\xde\xde\x69\x8a\xbd\xe6\x23\xec\x4b\x2b\x90\x91\x0c\x80\xac\x3a\xf3\x9c\x55\x0b\x6d\xd4\x09\xe6\x3d\x77\x70\x66\x55\xa9\x19\x9c\xb5\xc0\x25\x8f\x5b\xa3\x82\x85\xff\xdc\x64\xb8\xa8\xf3\x73\xd1\xfb\x29\xba\x87\xf8\x4d\xdf\x5f\x34\xd8\xf1\x40\xbb\xc1\x7b\x39\x61\x68\x2d\xf5\xd0\xa8\xf9\x10\x2e\x37\x9a\x99\x98\x13\x9d\xfe\x40\xab\x8c\xe7\x53\xbf\x56\x26\x10\x82\x37\x77\x1a\x7d\x8e\x10\x9e\x9e\x0a\xfe\x9b\x66\xd0\x42\x09\x42\xe1\x63\xa4\xf3\xc0\x3f\x71\x81\x3e\xe0\x78\xbd\x09\x0a\xc3\xd0\x77\x2e\x26\x22\xc2\x59\xe6\x82\x55\x2c\x75\xb0\x8d\xd0\x55\xa4\xa5\xeb\x5e\x60\x94\x40\xbc\xd3\xf3\xa6\xfe\xb8\x76\xfd\x16\x92\x15\x20\xc6\xcb\x68\x84\x71\x0d\x2e\x15\xcd\xad\x6d\xaa\xee\xd9\x59\x62\xdd\xa2\x1c\x67\x88\xf7\x84\x91\x79\x17\x98\x2e\x1c\xcb\xb5\xfd\xd9\xbd\xc1\x76\x9d\xb6\xb6\xdb\x57\xca\x35\x4e\x01\xa1\x33\x9d\x8e\x77\xe9\xdb\xbb\x58\x12\xfb\xab\x6a\x14\xc5\x40\x85\xc0\x65\x95\x99\xf1\x50\xe2\x24\x72\x47\x0f\x1e\x5e\x67\x2c\x42\x5f\x37\x5f\x9e\x0d\x6e\x8d\x52\xfa\x17\xb7\xa8\xd7\xa4\xd7\xca\x3e\x12\xf4\xdb\x53\x83\x6a\xed\x2b\xeb\xd7\x45\x89\xba\xca\x8c\xe9\x10\x02\x91\xbf\xb7\xe4\x56\xdb\x7f\x2f\x0a\x84\xdc\x0a\x74\x88\x85\x13\x66\xa9\xa5\xfe\xa0\xe3\xef\xc7\x4b\x9c\xdd\x4b\xd9\x7b\x65\xab\xf3\x61\x39\x3c\xe1\x70\x3d\x85\x71\x80\x5e\xe6\x8a\x13\xd3\x65\x4f\x03\xdc\xec\xfb\x77\xa5\x34\x30\xd0\x94\x96\xad\x73\xec\x01\x75\x99\x57\xe5\x10\x46\xaa\x73\x96\xf5\x92\x33\x86\x50\x11\x7a\xc7\xb4\xdd\x35\x73\xeb\x53\xd9\xc9\xf9\xdf\xa6\x2e\x23\x69\xc7\x7a\xf9\xc0\xd4\x2f\x61\xba\xe7\x4b\x28\x7d\xdf\xa2\x7b\x7f\x1c\x1b\xe9\x88\x3a\x04\x46\x91\xd5\x6d\xc1\x37\x34\xad\x4e\xe3\xa3\x2a\x9f\x40\xe3\x28\xc5\x00\xd0\xfe\xd8\xea\x05\x10\xe9\x38\xf2\x75\x80\x04\x02\x2b\xca\xa6\x90\x2b\xda\x10\x14\xb8\xae\x33\x65\x27\x28\x29\xed\x94\xfa\xba\x63\xcb\x14\xa3\x6c\xf8\x13\x90\xec\xa8\x3f\xc1\xc6\x27\x17\x20\x13\x26\x1b\x39\x93\x77\x9a\xa0\x76\xa5\xc5\xd8\x1d\x90\xd2\x70\x62\xe1\xa6\xd9\x0b\x5c\xf1\x00\x5c\x70\x19\x17\xb7\xad\xac\x18\x0c\xb7\x5b\xbc\xe0\xf2\x7f\x2f\x18\x0e\x2c\xb9\x01\x40\xc1\x4c\xc6\x00\x9d\x2d\x41\xaa\xb1\xdb\x94\x18\xf9\x1d\x4c\xf3\x94\x00\x2c\xd7\x0a\xc9\xdc\x11\xce\x86\x53\x47\xfa\x3f\x56\xf8\x7c\x14\x9e\x2b\x17\xd2\xc7\x2b\x66\x3a\x58\xe3\x18\x7b\xb1\x9b\x9b\xac\x2d\x11\x48\x3b\xa1\x2f\x77\x0a\xc0\x4d\xc4\x6d\x38\x85\x18\xfa\x54\xdc\x15\x2e\x9a\x9d\xfb\xff\x14\xf1\x4c\x61\xcb\x37\x58\x97\xe3\x0c\x53\xe6\xde\x42\xd5\xe1\x40\x1d\xae\x1b\x22\xba\xaa\x0e\x8a\x41\xc6\xaf\x9d\x0e\x0b\x13\xa9\x1a\x23\xd9\xb7\xd5\x55\x20\x47\x02\x9a\x35\x21\x94\x6c\x71\x20\xd3\xd2\x58\xb3\xae\xfc\xf7\x54\xd1\x95\x94\x87\xa1\xfe\x77\x43\xac\x7e\x1c\xc8\x9e\x36\x8b\x19\x78\x09\xc3\xa2\x73\x17\xe0\xec\x48\xd5\x46\xdb\x1e\x21\xeb\x62\x9a\x29\xbc\x62\x47\xcd\xd4\xa1\x37\x14\x37\x56\x3e\xdd\x12\xfa\xea\x2c\x5c\xb7\x7e\xed\xed\xbf\xc5\x80\x08\xfa\xd1\xf6\x5a\xf3\x58\x43\xfa\x27\x4c\x73\x4e\x3f\xbb\xaa\x9c\xc5\x0d\x68\x37\x48\xb7\x5a\x48\x5f\x94\xd6\x30\xb0\x32\xa5\xf1\x06\x7d\x1d\xeb\x30\xe9\xd2\x21\x8c\x93\x5c\x98\x1d\x01\xc0\xc5\x47\xfd\x68\x41\x31\x36\xed\xf4\xc0\xc7\x70\x28\x6e\x82\x34\x42\xe1\xc5\x13\x65\x19\x29\x21\x3c\x12\x1c\x1d\xe7\x00\x98\x91\x41\xab\x4a\xf3\xb3\xfe\x74\x04\xb4\xd2\xa3\x8c\x53\x0b\xaf\xb4\x98\xe6\x49\x53\xce\x1c\x0f\xb7\xd3\x40\xe2\x11\x35\xbf\x8a\xfd\xd8\xdd\x65\xb1\xb1\x8c\xf1\xc8\xfb\x9f\x40\x2b\x26\x70\x40\x0b\x86\xdd\xaf\xb1\x84\xcc\x51\xd5\xfd\xa2\x73\xb8\x0c\x26\x52\x1f\x91\x2f\x35\x83\xb4\xae\x30\x1d\xae\x15\x1c\xb5\x5c\x75\x70\x3a\xad\xef\x03\x24\x15\x22\x7d\x53\xe3\x95\xdb\x6c\x15\x0a\x1e\xe8\x39\xad\x26\xba\xe5\x52\xe1\xab\x73\x62\x14\xdc\x04\xb0\xf3\xc4\x1b\x7c\xfb\xd0\x49\x68\x1b\xc8\x4c\x3d\x16\x53\x07\x68"}, -{{0xa8,0x04,0xc3,0x3b,0x4d,0x38,0xcb,0x3c,0xe3,0x1c,0xf3,0xba,0xc1,0x04,0x9e,0x0d,0x4e,0xc6,0x3a,0x1a,0x0b,0x7b,0x59,0xfd,0x8a,0x36,0xee,0x37,0x54,0x16,0x56,0xaa,},{0x60,0x72,0x25,0x6d,0x65,0x74,0xa2,0x93,0xbd,0x7c,0x22,0x1c,0x55,0x1c,0x32,0xcf,0x2f,0x77,0x15,0xe1,0x9e,0x43,0x3a,0x49,0xd9,0xb8,0xb0,0x49,0x0e,0x56,0xef,0x62,},{0xb1,0xb4,0x4a,0x14,0x2a,0x7c,0x4c,0x3d,0x0b,0xf4,0x66,0x1e,0xda,0xc5,0xb7,0x67,0x00,0x57,0x26,0xc1,0x4a,0x27,0x69,0xb7,0xc2,0x14,0xfb,0x58,0x73,0x7e,0xc2,0xe4,0xbc,0x51,0xc3,0xa1,0x95,0xd2,0xba,0x1b,0x74,0xa5,0x4e,0xff,0x4c,0x33,0xa9,0x0f,0x41,0xcc,0xde,0xfa,0x9e,0x93,0x65,0xfd,0xe8,0xdd,0x85,0x9f,0xd3,0x97,0x8c,0x0a,},"\xdb\xfe\x30\x7f\x2a\xae\x9e\x07\xec\x7c\x4b\x68\x21\x06\xd2\xc9\x36\x7b\x0c\x4a\xaa\x58\xae\x80\x4e\x0a\x39\x04\x75\x4e\x6c\xf8\xfe\xe7\x3c\xf9\xe2\xd4\x5d\x02\x89\xe5\x07\x82\x93\xdf\xc4\x69\xd4\x6e\xa6\x70\x26\xc5\xaa\x69\x2d\x2f\x2c\x9f\xb4\xec\x57\xcd\xab\x4c\x04\x3f\xf9\xae\x61\x85\xf2\x7a\x70\x44\x54\xe5\xf5\x39\x50\xaa\xbd\x25\xc9\x91\x04\x74\xd4\x5a\xf8\x83\x68\x62\x72\x3e\x0e\x6a\x27\x82\x3d\x82\xbc\xbb\x68\xa9\x60\x52\x42\x2a\x18\x19\x51\x2e\x3b\x43\x40\x8c\xf4\x89\x57\xad\x6a\xe2\x35\xb7\x23\x3d\xf1\x82\x84\x74\x91\x53\xdf\xa5\x7d\xe3\x50\x74\xa3\x0e\xdf\xab\x8a\x56\xdf\x28\xab\x2e\x29\x40\x30\x6c\x22\x1a\xa5\x54\x90\xcc\x66\x4e\x14\x68\x3f\x30\xee\x61\x5e\x2d\x93\xfd\xf9\x71\xf5\x96\x66\x34\x65\x84\x3b\x3a\xdd\x63\x92\xba\x33\x90\x31\x1e\xf8\xdc\x59\xf2\x51\x44\x5d\x66\x9e\x10\xa0\x06\x19\x91\xe1\x13\x56\x19\x23\xaa\x21\x52\x44\x46\x3d\x82\x64\x19\x9a\xc5\x88\x92\x4e\x23\x1e\x84\x19\xd8\x68\x5f\x33\x8e\x59\x9b\x5f\x40\xbf\x9b\xd1\xae\xce\x77\x25\x35\xbb\xbc\xb8\xf6\x88\x1c\x2e\x80\x04\x91\xab\x3b\x57\xb4\x4b\x8a\xe4\x3a\xeb\x5c\x4a\xe5\xe7\xed\xeb\x22\x8f\xed\xc9\xf6\xb9\xca\xde\xa1\x76\xe1\x34\x93\x6d\xed\x60\xaf\x1c\x22\x87\x34\xfb\x00\x57\x0f\x23\x74\xbb\xbf\xa1\xbb\x17\x07\x85\x80\x5d\x6b\x6c\x70\x1e\x82\x09\x52\xea\xe4\x5b\x8c\x23\x66\x11\x3a\x1d\xfb\x2e\x35\x85\x2a\xf4\x19\xb7\x54\xf9\xcf\x7a\x08\x1c\x3d\xde\x6c\x80\x53\xbf\x1c\xe0\xc8\x53\x39\xd5\x69\x9c\x42\x24\x76\xfc\x21\xf2\x6c\xe7\x5d\x2a\x7f\xed\x09\xfc\x0f\x41\x75\x78\x98\x47\xd8\x76\xc5\x1a\xa4\xe0\xbf\x7c\xe8\x42\xb8\x30\x8d\xc7\xa2\x8c\x82\x39\x52\x07\x14\xdc\x23\x31\x36\xe0\x9f\x55\x7c\x7e\xf3\xe0\xf8\x3b\xad\x63\xcb\x28\xac\x61\x6d\x39\x28\xf3\x83\x7d\xce\x1d\xd5\x8a\xcb\x8d\xdb\xc7\x2e\x82\x2d\xee\xe4\x5f\x00\x77\x6a\xcc\x88\xe0\x0c\xd3\xa9\xdb\x48\x6d\x92\xd5\x35\xa5\x7a\x0f\xdc\x4f\x90\x3b\x62\xe5\x17\x22\x1c\x30\x8c\xba\x2e\x30\xff\xe7\xb9\x19\x37\xa9\x94\x17\x72\x1f\x56\xfe\x6d\xf4\x48\x40\xe9\xe4\x11\x36\x92\x9c\x0c\xa3\xdc\x28\xdd\xf2\x37\x9e\x4d\xcf\xde\x83\x72\x3e\x2d\x4c\x9e\x23\x29\x9c\x05\x6a\xfb\x31\xd3\xe7\x0d\x08\x5d\x0a\x31\x2c\x5c\xd5\x70\xb6\x99\xde\xa8\x71\x74\x58\x53\x13\x48\xc9\x6f\x6e\xb5\x2d\x7e\xe6\x1d\x56\x60\xf6\x5e\x90\x9a\x14\xce\x10\x33\xdc\x85\x3f\x2f\x25\xd0\x9c\xf4\xe4\x0d\x07\xef\xf7\x2e\x15\xa3\x90\x56\x4a\x2b\xe3\xc0\x42\xd8\x9a\x68\x66\x0a\x97\xff\xac\xec\x49\x67\xa4\xb6\x18\x71\x2d\x70\x60\x75\x65\x20\xc2\x9e\xe8\xd9\x22\x0a\xd8\x61\x5c\x4f\xcf\x39\x69\xbd\x3b\x2e\x09\x47\xe1\xf0\xbe\x7e\x2d\x80\xe0\xa6\x14\x80\xc3\x16\x6d\xb5\x58\x22\x18\xbb\x0a\x8b\xe9\x84\x8e\xfd\x41\xb6\xce\x0c\xd7\x95\xc4\x86\xab\xb6\x72\x10\xbe\xb6\x0c\xd0\x78\xb4\x6a\xeb\x7f\x4f\x48\x50\x31\x90\x2b\xcd\x71\x31\xe0\x0b\x70\x35\xaa\x2d\x43\xfe\xe0\x63\xf7\xf3\x0b\xd5\x70\xda\x1d\xbb\x65\xc0\xca\x92\xa4\x81\x26\x32\xe4\x32\x77\x85\x53\xe3\x5e\x85\x6c\xaa\x82\x18\x22\x1f\xd6\x31\x6a\xb0\x86\x91\x73\xb3\x84\x09\xbc\xef\xe6\xd2\xdb\x92\x10\xf9\x02\x41\x73\xb6\x6d\xbb\x92\x67\x7c\xbc\x71\xc8\xa1\xcd\x58\x3f\xa6\xf3\x54\xd3\xc9\x3f\xa8\xb1\x6c\x71\x37\x4f\x25\xa0\x0c\x33\x2f\x85\xa8\xbe\xfd\x54\x03\x88\xfb\x50\xdb\x9f\x5d\x96\xe4\xe4\xe6\x98\x83\x3c\xe3\xd6\x3c\x10\xb8\xee\xc7\x0a\x24\x3b\x90\x15\xdb\x45\x94\x31\xb6\x2f\x56\x68\xbb\xa6\x0f\x07\x04\xf6\xbd\xfe\x95\x46\xea\x47\x5c\xef\x2e\xbc\xcb\xa4\xb7\x68\x08\x48\xe8\x2b\xef\xf5\x85\x4e\x49\xf6\x5b\xb7\x73\xa4\x92\x2e\x90\xf9\xb8\xaf\xc7\xcf\x81\x87\x30\x58\x8e\xd5\xaa\x7b\x39\x98\x26\xaa\xdd\x54\x37\x2f\xcb\x76\x14\x58\xb6\x4d\xe6\x68\x57\xf4\xad\xac\xd4\xc3\x29\x00\xcb\x77\x13\x6a\x53\x5d\x7b\xbb\xb5\x54\x59\x7a\xec\xf3\x9f\xf6\x98\xb4\x5e\x6a\x21\x8d\xf1\xd2\xab\xe6\x15\xeb\x8d\x9e\x18\x24\xc0\xbe\xcc\xe9\x07\x67\x89\x9e\xbf\xd2\xc7\x30\x14\x4b\x32\xc7\x46\x04\xc0\xe5\x3e\x25\x05\xbb\x15\xd2\x80\x07\xa8\x7b\x99\x31\xd6\xee\xc0\xa6\xcb\x5b\x0f\x96\xd3\x19\x4b\x24\x23"}, -{{0xf8,0x20,0xe6,0xf2,0x4a,0x84,0x18,0xb6,0xac,0xda,0x16,0x5f,0x29,0xa3,0x60,0xf7,0x67,0xcd,0xed,0xde,0x8f,0x64,0xd7,0x68,0xb9,0x5f,0xc2,0xa5,0xf3,0xf4,0x04,0xe7,},{0x79,0xc4,0xb2,0x63,0xb2,0xe5,0x8f,0x67,0x86,0x28,0xd4,0xea,0x82,0xb1,0x75,0xac,0xa2,0x30,0xb9,0xa2,0x02,0x85,0xc8,0x28,0xf9,0x4e,0x1f,0xfd,0x63,0xd7,0x5b,0x23,},{0xf9,0xfd,0x72,0xf3,0x21,0xca,0x21,0x33,0xbf,0x85,0x85,0x90,0x8d,0x9c,0xa7,0xb8,0xe3,0x36,0x22,0x7e,0x3f,0xfb,0x37,0x49,0xa1,0xfb,0xe8,0xc9,0xb1,0xe5,0xd5,0x0e,0xf0,0x1f,0x9d,0xb5,0xf0,0xd2,0xa7,0xc7,0xc1,0x39,0x9b,0x97,0xc9,0x04,0x4e,0x1b,0xc1,0xad,0xc3,0x2b,0x8b,0xea,0x46,0xda,0xd7,0xb8,0x10,0x26,0x46,0x96,0x03,0x03,},"\xab\x6b\xd4\x5b\xb0\x6d\xfb\x90\x69\x11\x8f\xf9\x98\xf3\xbd\x39\x3e\xa8\xe9\x44\x97\x9e\x89\xe0\x49\xf2\x50\x5c\xd8\x93\x1b\x93\x08\x6b\x7e\x9d\x8e\xe7\x64\xe9\xb4\x47\xea\x4e\xa1\x21\x38\xbb\x45\x27\x5a\x21\xa1\x98\x43\xf7\x5d\xc5\x42\x1d\x61\xff\xd8\x61\x83\x8e\x58\x33\x82\x5d\x67\x16\x2f\x32\x59\xc2\x64\x47\xbe\x51\xdc\x18\x02\xef\x5a\x04\xba\x73\xb7\x83\x93\x57\x06\xab\xb4\x2c\x51\x3b\x65\xf2\xbb\xc4\x4f\x83\xda\x10\x61\x24\x2f\x2d\x5e\x51\x98\xf3\x8c\x10\x71\x7a\x86\xa3\xa1\x97\xe7\xcd\x90\x34\xf6\x36\x11\x44\x99\x03\x72\x77\xac\xb4\x72\x2c\x06\xa9\x1c\xb2\xf6\x5e\x21\xeb\x8d\x22\xd3\x6a\xd7\x3b\x42\x65\xf7\xa7\x94\x7e\x00\xe7\x22\xbd\xa6\x70\x43\xcd\x12\x81\xbc\xd8\x7e\x76\x3f\xc9\x7b\x54\xc8\xf8\x68\x36\xcd\xbf\x08\xc9\xa1\xf7\x00\xf4\xea\xed\x9e\xa5\x9a\x6f\xc1\xbc\x0d\xf8\xc9\xec\x1f\xc2\x97\x7c\xad\x60\xf9\x78\xab\xc0\xc8\x38\x1a\xa9\xfb\x06\x0e\x3f\x99\x37\x8a\x51\xb2\xd9\xaf\xbe\xf3\x58\xd5\x51\x62\xa3\x89\x22\xeb\xb8\x7d\x2a\x3e\x0f\x0f\x40\x00\xb1\xc3\x9b\x15\x02\xe9\x59\x45\xe8\xac\x9f\x4a\x3e\xa7\xc9\xdd\xb5\x81\xa5\xec\x06\xc0\x0b\xa8\x7a\x73\x70\x84\xb3\x84\xfa\xba\x09\xc8\x48\x71\xdd\xd6\x7d\xc1\xbe\xbb\x2f\x7f\xbd\x94\xa5\x59\x7d\x01\x9f\xe6\x29\xe5\xbf\x12\xbe\xa2\xe3\x3c\xa8\x4c\x68\x0d\xc5\xa3\x98\x9b\xbf\x3a\xf9\xee\xec\xe8\xab\x8f\xc8\x61\xe3\xb8\xbf\xc1\xe6\x7e\x2a\xee\x32\x6b\x37\xfb\x9b\x51\xcf\xa0\xb5\xf5\xfc\x16\x00\x69\xb4\x50\xb7\x04\xe0\xfa\xb7\xfb\x6c\x5a\xb3\xc4\x0b\x8f\x0b\x3d\x09\x30\xb9\x11\x2d\x64\xb9\xda\xca\xb4\xdd\x87\x5f\x29\xd8\xc5\x8c\x5d\x20\x53\xad\x91\x48\xff\xde\x22\xd9\x0b\xc0\xd5\x0f\x5d\xec\xa6\x8d\x3e\xa2\x5c\x5b\x4c\x76\x88\x87\x1c\x0c\x77\xdb\xce\xea\xcb\xd0\xa4\x22\x9f\x49\x70\xec\x87\xb3\x44\x99\xe2\x78\x30\x3c\x06\x69\x4c\x30\xac\x68\x52\x4d\x11\xb1\x72\x79\x4b\x48\x12\x73\xa5\xda\xc4\x61\x22\xd2\x47\x20\x95\xa5\x63\xa4\x35\xd1\x85\xd5\xe9\x1d\xa7\x26\xe7\x45\x92\x99\x9c\xda\xc6\x88\xa3\x3f\x38\xf7\xc0\x35\x58\x8f\x62\x5d\xc6\xac\x73\xd0\x04\x7a\xb3\xd6\xd1\x2f\x1a\xe3\x3d\x8b\x62\xd6\xd6\xc6\xca\xcf\xf0\xbd\xd8\x94\xb5\x7e\x31\x89\x12\xac\x0c\xf4\xa5\x34\x76\x2b\x2f\x6d\x26\x3c\x93\x58\x04\x42\x3e\xd8\x68\xcf\x8c\xfb\xb8\xbe\x8f\x6d\x8a\x71\x4a\x26\x8a\x39\x0e\xdc\x2d\xd5\x09\xd2\xdc\x96\x85\x1d\x1b\xd4\x32\x49\xbd\x0f\x69\xb0\xc4\xcb\x2f\xf4\x08\x0d\x1f\xd5\x62\x2b\xc2\x38\xdd\xa6\xe9\x30\x02\x5d\x8a\x2b\x12\xb9\x72\xf9\xeb\xa1\x74\x21\xd4\xce\xa6\x42\xf4\x0a\xd9\xea\x85\x47\xae\x59\x49\x8c\x3a\xd1\xb9\xa0\xc3\x4e\xd8\xc0\x1a\xae\x3b\xd2\x1a\xc1\x77\x43\xb5\x77\xf9\x51\x5c\xfb\xdd\xe2\x70\x4d\xc5\x7e\x80\xf1\x25\x32\x3d\x55\x10\x0b\x9f\x69\x79\x27\xd4\x31\xdf\xe7\x36\x31\xb5\x8e\x52\xaa\x6a\xeb\x04\x78\xbf\x45\x95\x52\x43\x86\x89\xfb\xeb\x9c\x60\xd8\x7a\xae\x09\x95\x43\x62\xcd\x02\xa2\xb0\xb4\x79\xef\xd3\x8f\x17\x82\x1a\xf3\x9b\x21\x92\x6e\xe0\x2f\x7d\x97\x2a\xd0\xf5\x4e\xa6\x57\x2c\xc3\xeb\xd0\x20\xb1\xee\x26\x88\x25\x33\xbd\x19\x11\x43\x23\x81\x5f\x67\x2e\xc8\xc9\x05\x68\x73\x0a\x58\xe4\xe1\xe3\x5f\x68\x21\x21\x9a\x32\xb8\xa6\xc5\x2c\xed\x6f\x95\x73\xd9\xf3\xbe\xb2\x85\x13\xba\x62\xfb\x20\x1f\x7f\xd4\x1b\xb1\x0c\xa3\x4b\xb1\xc7\x0f\x2f\xd7\xbb\x92\x99\xa7\xc5\xf7\xf2\xe0\xfa\x1d\x1a\xf0\xe9\xae\xf5\xed\xe7\xc1\x69\x50\xe8\x60\xec\xd6\x1f\x18\x42\xa1\xa2\x2c\x98\x31\xc0\xc0\xd4\xed\xa8\x40\xb0\x88\xa5\x45\x20\xc9\xb1\x8c\x76\xeb\xa9\xbe\xbc\xd5\x91\x38\x1c\x18\x0d\x7f\x86\xa0\xe5\x8a\xdd\x92\xb9\xb0\xc8\x07\x6a\x7c\xdc\xab\x60\xde\xa4\xc1\xaf\xb1\x8c\x8b\x94\xb1\xb3\x92\xcc\xfb\x4d\xae\x27\x11\xe7\xd1\x2d\x2b\xc7\xc7\x82\x5f\x63\x99\x2e\xc3\x24\x71\x63\xc2\x83\xb1\x07\x5e\x32\x24\x5f\x69\xcf\x47\x24\x0a\xef\x0d\xb4\x3e\xfa\xe8\x6f\xc1\xfd\x3b\xb9\x9c\xf5\xb7\x89\xf5\xbc\xba\x95\x04\x65\x7d\x9e\x62\x2a\x4a\xa1\x6f\x01\xd4\xd8\x44\x41\x31\x24\x44\x7d\x6d\x1a\x44\x23\xe7\xb5\x5d\xb7\xe6\xa3\x1a\x31\x9f\x4b\xac\xae\x43\x0a\x33\xa9\xbd\xd4\xef\x36\x80"}, -{{0x0a,0x05,0x6b,0xe0,0x39,0xfd,0x55,0xda,0xda,0x44,0x1d,0x03,0x73,0x61,0x27,0x3f,0x20,0x6e,0x00,0x0a,0x74,0xa0,0x5c,0x51,0xc0,0xcb,0xb6,0x27,0x43,0xf1,0xf3,0x40,},{0x73,0x14,0x02,0x17,0xa4,0x93,0xa1,0x78,0x66,0xff,0xf5,0x15,0x48,0x32,0x27,0x3d,0xf7,0x9d,0x58,0x11,0x54,0x3c,0x22,0x2a,0x39,0xd0,0x56,0xb8,0xc9,0x70,0xdb,0xfa,},{0xfa,0xb8,0xe5,0xd9,0x3d,0x7d,0x46,0xc6,0x5e,0xe1,0x17,0xc5,0x37,0x5e,0x73,0xc9,0x70,0x5f,0x87,0x54,0x17,0x7f,0xdd,0x46,0xef,0xed,0x47,0x37,0xc2,0x87,0x68,0xcc,0x4b,0x95,0xa9,0xc8,0x4c,0x52,0x9b,0x4b,0x91,0x6b,0x28,0xda,0xbd,0x87,0x41,0x18,0x31,0x44,0xbc,0xdb,0x48,0x3d,0xf9,0x8a,0xf8,0x9d,0x82,0x40,0xcf,0x09,0x46,0x04,},"\xa5\xab\x14\x76\x84\xe4\xd4\xa7\xbc\xb5\xa9\x6f\xb3\x98\x18\xe2\x3f\x56\xc2\xd8\xa7\x44\xe9\x12\x3d\x62\x08\x39\x30\xab\x1d\x0b\xb5\x32\xe6\x87\x14\xfc\xec\x7e\x6c\x41\x13\x4b\x6b\x19\xdd\xd8\x67\xfe\x63\x5c\x9e\xd6\x53\x93\xee\x39\xc5\xe8\xfa\xb4\x56\xcb\x5b\x32\x79\x78\x83\xf3\xcd\x9a\x09\x02\xb9\x79\x63\x48\xee\x66\xc6\x91\xfb\x4f\x2b\xb1\x47\x64\x41\x06\x57\xc7\x4a\xb3\x64\x56\x78\x79\xb6\xfa\x0a\x6f\x4d\xaf\xd9\x30\xd9\x23\x4c\xd7\x83\x4f\xb9\xd0\xee\xdf\xbb\x5a\x39\x4b\xf0\x84\x6e\xc6\x96\x9c\x2e\xf7\xce\x39\xe3\x85\x38\x95\xff\x5b\x4d\xa3\x1e\x54\x34\x1b\x42\x72\xe4\xa2\x60\x49\x18\x9f\xf2\x82\x41\xce\xef\xfb\x7d\x2e\x1f\xaf\x4f\x77\x9f\xa6\x5c\xac\x0f\x57\x83\xc6\x0a\xe7\x7d\xe3\x0a\xd4\x46\x5f\xdb\x39\x0d\x42\x57\x1e\xff\x4a\x63\x13\x63\x49\x93\x7d\x6c\xae\xef\xcd\xae\x22\x9e\x2f\x28\xce\xa8\xab\xf3\xff\xae\x3c\x3e\xcc\xd9\x06\x70\xa4\x21\x2a\x2b\xee\x1c\xa6\xa5\xb5\x4f\x09\x4f\xc3\x23\x10\x58\xf5\xcb\x9e\xce\xb9\x99\x3b\xe4\x70\x27\xd5\x1c\x18\xde\xca\x41\xcd\xda\xf4\xe8\xbc\x56\xa9\x9f\xd2\x70\x35\x5f\xf4\x59\x71\x95\x0e\x34\x37\xa1\x98\xcc\xc3\x25\x41\x68\xdf\xc1\x57\x40\x80\x80\x2e\xe1\x01\xa6\x17\xfb\x60\x4e\x86\x8f\x8f\xa8\xfb\x30\xda\xeb\x43\x07\x4d\xe1\x1f\x24\x83\xd9\x16\xde\x56\x43\xb7\xca\xc2\x3d\x93\x40\x50\x8a\x3f\xd6\x21\xec\xd2\x50\x04\x35\x6a\x53\x55\x4a\xd3\xad\x7d\x5d\x25\x81\x7a\xd7\xc9\xa6\x10\x00\x8c\x67\xac\x16\xba\x42\x11\xc4\x2f\x5d\xad\xf8\x6c\x2c\x3a\xed\x82\x5c\xf2\xa9\xb5\x23\xbf\xc0\x3d\xd7\xde\x40\x0c\x67\x80\x7e\x13\x9e\xa5\xdb\xce\x4e\xe1\xf7\xd3\x18\x88\x9b\x01\xa9\xf4\x48\x03\xc3\x22\xac\x3b\x61\xe2\x0e\x63\x12\xd0\xa0\x3b\xf9\x92\x7f\xa3\x3f\x04\xed\x7e\x20\x7b\x16\xf2\x65\x02\xc2\x98\x3a\x3a\x96\x1f\x22\x44\x61\xfe\x9b\x64\x92\x3b\x1d\x09\x18\x94\x76\xae\x8d\x00\x1d\x0e\xca\xae\x4d\xf6\x0d\xb3\x5f\x44\x8b\xb6\x12\xf9\x65\x5a\x5f\xb1\x44\xdf\x11\xd8\x3a\xa6\x93\x68\x86\xc3\x04\x94\x9e\x59\xaa\x46\xdf\x65\xc2\x2c\xe7\xbf\x28\x9b\x3c\x77\xc2\x5d\x89\x6b\xe6\xd5\x1d\xee\x10\x74\x82\x61\x68\x8c\x8b\x07\x1c\x85\x6f\x99\x62\xc6\x67\x75\xdd\xf1\x60\x83\xda\xe0\x65\x87\xe3\x2a\x63\x61\x19\x9d\x72\x09\x7e\x38\x3a\xd7\x43\x94\x91\xb5\xa5\x63\xa3\xe6\xd5\x8d\xa3\xd5\xab\xb1\xde\x84\x89\x0a\x36\xb4\x21\xce\x03\xd4\x84\xdf\xd6\x00\x39\x63\x8d\x46\xed\xfb\x60\x65\x9e\x3a\x25\xac\x6e\x9a\x93\x5a\xd6\xda\xd5\x0f\x92\x7b\xcc\x2f\xf9\x9f\x99\x24\xa5\xb7\x99\x5d\xc2\x3c\x8f\x30\x1c\xcc\x77\x69\xf7\x1c\x18\x26\x09\x04\xa3\xdc\xfb\x81\x7d\x2d\x80\x5c\xb1\xf1\x96\xbe\x8b\x6e\xcf\x35\x2b\xc2\x96\xbc\x3f\x76\xea\x91\x35\x3f\x8c\xf3\x5b\xcd\x2b\x57\xeb\x59\x42\x77\x3d\x68\x34\xac\x50\xee\xad\xc7\xe6\x64\x61\xd1\xda\x09\x8c\xce\xc7\x5f\xf7\x20\x52\x15\xf5\x24\x59\xd9\x76\x20\xf9\xf0\x28\x9e\x93\x91\x1d\xb3\x9b\x21\xdf\x81\x8f\xdf\x0b\xed\x45\x50\x92\x44\x63\x3d\xf0\x1c\xdd\xdb\x4b\x75\x97\x2f\xa7\xea\x6f\x73\x28\x1c\xbd\xbb\xd1\xbc\xb0\x0c\x3b\xc1\xb1\x72\x8e\xea\xe0\xbb\xa1\x72\xb1\x31\xf5\xd3\x08\x90\xa3\x41\xe6\xb7\x2f\x7e\x89\xdd\x4b\x6d\xb3\xe7\x9b\x69\x27\x58\x6c\xf2\xc8\xac\x38\xdd\x14\xf3\x74\xd7\xf5\xbb\xa9\xf4\x35\x3d\xef\x10\xdd\xc9\x4d\x3d\x11\x18\xc5\x69\x9e\x38\xb6\xb5\x04\x91\x8e\x58\x9e\xfe\x3f\x7e\x97\x3f\xb4\x0e\x2e\xbd\x05\x7d\xe1\x38\x5e\x39\xd6\x99\xa8\xf6\x83\xb9\x62\xfa\xe4\xf3\x90\x28\x81\xf1\xaf\xbe\xd7\xc7\x83\x82\x35\x58\xc3\x6d\x68\xc6\x87\x5d\x16\x6f\xa2\x43\xeb\x2a\xe1\x4f\x7e\x63\x15\xa6\xd2\xab\x4e\x79\xea\x8e\x16\xe6\x9d\x30\xed\xc7\x08\xf1\xe7\xaf\x7a\xda\xfe\xdc\xd3\x16\x88\x98\xb3\x31\x87\x81\x78\xc4\xba\x88\x33\xd2\x0b\x3c\xac\x9d\x32\xb8\x88\x8c\xc6\x78\x32\x06\x39\x74\x70\xa2\xe7\xcc\x4c\x98\x09\xff\x79\xce\xac\x9d\xc2\x4c\xa1\x43\x8c\x91\x9c\x8a\x41\x5e\x82\xf0\x90\x2b\x4d\x9c\xf4\xcc\xd5\x76\x96\x8d\x5b\xee\x81\xc5\xf1\x9c\x7d\x57\xb9\xba\xda\x8e\xab\x47\x56\xea\x27\x0d\xd2\x61\x29\xe6\x12\x2e\xe2\xd6\x15\x24\x2b\xc7\xfa\xbf\xf4\xf8\x31\x2e\x68\x6c\x8f"}, -{{0x22,0x05,0x24,0x86,0x0c,0xb8,0x9a,0xb2,0x95,0xbd,0x88,0x4f,0x98,0x8a,0x57,0x91,0x18,0x68,0x69,0x3d,0x6b,0x10,0x5a,0x80,0xb2,0x30,0xf2,0x1e,0x57,0x80,0x5a,0x7d,},{0x4a,0xb3,0x2b,0xc1,0x56,0x6a,0x76,0x77,0xe7,0x99,0x73,0x4d,0xc8,0x41,0x81,0xfb,0xb6,0x54,0xb8,0x13,0x37,0x91,0x80,0xf1,0xdd,0x35,0xae,0xf2,0xd3,0x24,0xc1,0x2c,},{0xdb,0x1c,0xc0,0xc5,0xdb,0x77,0x3e,0xc5,0x16,0x89,0xbe,0x28,0x84,0x2f,0xa6,0x79,0x1a,0x7d,0x75,0xe2,0x9c,0x22,0x8a,0xe9,0x59,0x3a,0x58,0x0e,0x08,0x75,0xb1,0x67,0x0f,0x09,0xb0,0x34,0x42,0x92,0x9a,0x18,0xf1,0xe9,0x41,0x4e,0xa3,0x43,0x15,0xff,0x09,0xd9,0x1d,0x92,0x2e,0xe4,0x7f,0x10,0xf7,0x1d,0xa4,0xab,0x13,0xb7,0xd9,0x01,},"\x02\x4a\x54\xac\x5e\x01\x63\xb3\xa4\xfd\xd0\x2f\x59\x36\x88\x8a\xe2\xf9\xb7\x4a\x64\x14\xb5\x3c\x63\x81\x17\x3b\x09\x5a\x4d\xda\xcf\xc3\xa6\x9f\x19\x16\x7d\x0f\x1a\xe0\xc1\x20\xbb\xa7\xe9\xfc\xb7\xcc\xfc\x79\x6d\x89\xea\x46\xef\x80\x58\x86\x6e\xf6\xda\x7d\x01\xa6\xa1\x42\xea\x69\xd7\x20\xc4\xf8\x05\xac\x54\x05\xa8\x01\x2c\x3c\x2a\x82\x63\xb5\x37\x2d\x59\xbf\x7f\x40\x99\x29\x90\x13\xd2\x62\x59\xdf\xd5\x19\x3e\xce\x56\x17\x97\x77\xbe\x51\xb8\x6b\xd1\xce\x5f\x1f\xc9\x15\x6f\x2b\x3a\x32\xc0\x9d\x86\xbc\x61\x32\xde\x57\x61\x02\xe2\xf0\x3c\x71\x6d\xb5\x36\x6c\xcb\xe7\x42\xae\xe3\x55\x2a\xc3\xb3\x9d\x0e\xc7\xd4\xe4\xe9\x62\x6b\xf8\xec\xe0\x31\xd6\x78\xd3\x48\x09\x05\xc0\xe3\x38\xfb\x7c\xc0\x26\xe3\xe7\x9c\xf2\xc2\x78\x1a\xc2\xa5\xa4\x0d\xf4\x28\x4e\x23\x5a\x03\x89\xe9\x28\xfc\x63\x55\x7d\xc6\xf1\x99\xfc\xec\x5f\x36\x1e\xa2\x47\x59\xfa\x7c\x5f\x71\x97\x8c\x0b\xa2\x45\xe4\xb0\x3a\xe4\x35\x94\x1c\x86\xc8\x1a\x51\x43\x0c\x2d\xc9\x92\x7e\x3b\x0f\x4e\xc4\xeb\xa7\xc2\x74\x5b\x49\x39\x87\x15\x4d\x7d\xa8\x5b\x67\xde\x21\xc5\x98\x40\x7f\xb2\xa7\x60\x80\x4a\xd0\x5b\xfd\xfa\x45\xa6\x13\x22\x4b\x22\xa0\x85\x88\xcc\xea\x3c\xbd\xf4\x7a\x19\x8b\xeb\xf8\xcf\xed\x86\x49\xd6\xd5\xf3\xfa\x50\x13\x76\xbd\xfb\xa4\x00\x3d\xac\x22\x37\xdc\xac\xe5\x31\x5b\x7f\xef\xb8\x79\xa8\x9a\x85\xbc\xe6\xda\x52\x6f\xc3\x60\xcb\xb4\xfd\x55\x4e\xf0\x13\xf3\x3b\x73\x84\xcd\x2b\x22\xa8\x85\x77\xf3\xa2\xd3\x66\x42\x2a\xae\x46\x41\x7b\xa9\x16\xe1\x64\x6e\x24\x40\x4a\x88\xb5\xd5\x3f\xf1\xae\xd2\xa4\x7b\xaf\x81\xfc\xb4\x28\x63\x97\x99\x13\x94\xb2\xec\xc3\x96\x67\xac\x46\xc2\xbd\xb6\xd0\x23\xb3\x3d\xb0\x13\x45\x7c\x40\x05\xd8\x39\x01\x5d\x88\x51\xf0\x28\xac\x33\x4f\xb2\x4b\xba\xd2\x90\x2a\x4d\x63\xae\x68\xe0\xec\xa7\xea\xea\x1e\x85\x65\x29\x64\x7b\xaf\x14\x12\x21\x37\x54\xed\x50\xaf\x3f\x43\x6e\x9b\xaf\xc1\x60\x16\x39\xb3\x9d\x3e\x52\xa9\x3a\x89\x8f\xb6\x01\x9f\xd5\xed\x6e\x7d\xfc\x05\x0e\x7c\xe5\xf3\xd3\x5c\xeb\x50\x67\x02\x1c\x0f\xbd\xc7\x08\xd3\xf2\x6b\xd6\x05\x68\xd1\xed\x2b\x61\x2b\x69\x62\x35\xd5\x33\x33\x18\xf9\xa6\xc9\x87\x23\x5a\x7a\x07\xf8\xc6\xa9\x35\x4f\xb8\xe7\x34\x76\x30\x65\xaf\xcd\x4d\x93\x77\x64\xa4\xf0\x37\xcc\x7e\x7e\x2b\x93\x21\x7f\x16\x41\x68\x4f\xa8\x1b\x7f\xf7\x98\x6a\x28\xb3\x8e\x95\xb3\x32\xe7\x46\x49\xe8\x3d\x0d\xed\x79\x5c\x57\xf2\x4c\xf2\x76\xe0\x14\x39\x01\xba\xfe\xf0\xf1\x69\x3f\xe7\xcf\x10\x90\x4f\xb0\xd8\x80\xd7\x2e\x44\x71\x6a\x70\x69\xda\xaa\xe7\x42\xcf\x0f\xf3\xed\x92\xf5\xf7\xd1\xe1\x0e\x04\x9d\x8d\xf0\x43\x63\x1e\xd0\xed\x4c\x4a\xc4\x02\x2d\x84\x03\xcb\x04\x21\xb4\x54\xcb\xfb\x6f\x48\xa3\x0e\x9e\xe1\x60\x9a\xd7\xb6\x82\x11\x97\x7a\xcb\x33\xb9\xc1\xa1\xbe\x73\x58\x14\xc5\x8f\x66\xdb\x5f\x0b\x8a\xc7\x73\xb1\xd5\x8d\x4e\x6b\xc4\x5d\xfd\x48\xa2\x94\xbb\xd2\x5e\x92\x67\x1f\x56\xf3\x02\xf2\x9b\x50\xd8\x04\x31\xc8\xf2\xea\x33\x99\x62\x57\xb2\x08\xe0\x57\xea\x76\x72\xcc\x2d\x1c\xd4\x20\x4b\x85\xb2\xab\x50\x90\x27\x13\x13\x59\xae\xb4\x2e\x3e\xcc\xdb\xae\xcf\xe2\xcd\x3e\x5a\x33\x13\x26\x6e\x76\x11\x94\xff\x69\xca\xe9\xe3\x7e\x51\xcc\x0a\x54\xf0\x86\xdd\xe1\x3c\xb3\x31\x18\xe3\x4f\xe3\x3c\x74\xd7\x35\x58\x27\x52\xd6\x8d\x21\xc7\x9e\x5c\x3a\xae\xa9\x4b\xa1\x07\xcb\x7e\xe8\xa7\x0a\x3f\x9a\x01\xe9\x80\x8c\x0a\xeb\xa6\x66\x53\x15\xb4\x56\x25\x84\x0a\x03\x3a\x6e\x2a\x87\x54\x95\x05\x79\x42\xed\x9b\xb2\xce\x6e\x4e\xe6\x0b\xed\x47\xcd\x9d\x58\x4b\xc2\x45\x24\x39\x7a\x10\x94\x98\xee\x2a\x97\x3a\xad\x6a\x29\xb7\x0a\x1c\xfb\xfe\x9a\xa5\xc7\xcb\x9f\x35\xf0\xfa\x00\x22\x7f\x43\x98\x8d\x07\x61\x9b\x6f\xb2\xf6\xd3\xbe\xe2\x8e\x10\xee\x70\x53\x47\x01\x5a\x92\x2e\x2e\x88\xd3\x4f\xb0\xce\x51\x5b\x08\xdf\x3a\x1b\x63\x4f\xf9\xec\x15\xd0\x59\x41\x82\xc8\x6e\xbb\x0d\xb7\x83\x61\x2a\x7d\x19\xe4\xb2\x2e\x82\x2d\x56\x62\x45\xae\xd7\x2e\x69\x4c\x3d\x10\x1b\xfa\x4c\xa8\x79\x86\x2e\x5f\x99\xc2\x3a\x5d\x66\x08\x3c\xe0\x6d\x87\xf3\x99\xaa\x78\x88\xab\x83\xb8\x66\x44\x72"}, -{{0x4e,0xf6,0x0f,0x06,0x91,0xd7,0x37,0xe6,0x4d,0x43,0x7b,0xfd,0x33,0x98,0x33,0x0e,0x55,0xe3,0xc0,0x94,0xcf,0x41,0xfc,0x55,0x7b,0x0f,0xe0,0xb6,0x43,0x90,0x9a,0xb8,},{0x30,0x6a,0xb1,0x46,0xe5,0xc8,0xcd,0x63,0x0f,0x9b,0x48,0xbf,0x8b,0x68,0x5d,0xb0,0xb6,0xb5,0x53,0xef,0x69,0x68,0x68,0x53,0xb6,0xb5,0x31,0x96,0x01,0x18,0x54,0x8c,},{0xcb,0xf7,0xcf,0x22,0x08,0x1c,0x5f,0x23,0x5d,0xba,0x35,0x63,0x0f,0xb3,0xf0,0x40,0x8f,0xce,0xcc,0xef,0xeb,0x28,0xb9,0x9d,0x74,0xdb,0xd9,0x8c,0x90,0x2c,0x7d,0x99,0xba,0x9c,0xa7,0xfa,0xb3,0x74,0x7c,0x50,0x4c,0xc2,0x19,0xf4,0xdd,0x10,0x10,0x81,0xf5,0x8c,0xe6,0x16,0xe2,0x92,0x80,0xe3,0x62,0x53,0x9f,0xe4,0x9f,0x34,0xd7,0x05,},"\x0a\x18\x8a\xc2\x6f\x3c\x5d\x89\xf3\xd5\x88\x37\x4f\xac\x5e\xcf\x9a\x46\x7e\x21\x65\xb3\x1d\x0b\x0f\x23\x50\x1b\xd2\x2e\x62\xbf\x35\x55\xff\xba\x94\x63\x1d\xe7\x4a\x6a\x3c\x3c\xf6\x3b\x03\xac\x1b\xbb\x37\xd2\x33\xec\xa5\x99\x3b\x09\x70\xa0\x22\x0d\xe8\xd6\xc4\x1a\x97\x03\x07\x30\x9a\x52\xda\x05\x76\xdc\x33\x4d\x80\x64\x47\xaa\x09\xd0\xb2\x45\xea\xcd\x0b\x42\xc4\xe1\x9f\xa3\xd6\xfb\xdc\x22\x94\x30\xeb\x3c\x75\x58\xaf\x53\x31\xc6\xe7\xfc\xc2\xe5\x52\xce\x35\xd5\x79\x07\x3b\x54\x8d\xc1\x15\xbb\xd2\x7e\x5a\x33\xce\x1c\x47\xfc\x84\x61\xe3\x91\xb6\xd7\x67\x95\x34\x87\xcc\x52\xee\x67\x3b\xc4\xbe\x96\x56\x9c\x85\x57\x36\x9e\xbb\x6e\x02\xf7\x92\x38\x10\x8c\x3b\x58\x56\xee\x38\x1a\x79\xff\x46\x4c\x8f\x60\x09\xfd\x47\xe6\x7b\x4c\x80\x20\x1e\x11\xe6\x1a\xb8\xf5\x9b\xa5\xd0\x7b\x15\xac\xe3\xfb\x37\x4c\x64\xb6\xb4\xc3\x45\xe2\xb0\x0e\x91\x51\xab\x8e\x1c\x5c\x98\x56\x8b\xc5\x8d\xd0\x81\x2a\xaa\x3b\xee\xe1\x65\xe7\xea\xe5\x8f\xbd\xe6\x30\x77\x20\x3c\x4f\xd6\xe1\x60\x68\xd7\x6e\x3d\x3a\x13\xf1\xcd\xd7\x32\x88\xbd\x5e\x4d\xa4\x4e\xb1\x19\xa0\x4c\x4d\x32\xef\xa2\xf1\x3e\x74\x26\xa2\xf4\x1c\x56\x23\xc9\xb0\x66\xb1\x30\x36\x39\xb8\xfc\xea\x0d\x87\x74\xcc\x08\x04\x5f\x7e\x34\x63\x65\xff\x31\xd3\xb1\xed\x99\xe9\x7b\xca\x5f\x25\xc9\x2b\x28\x43\xac\x58\x5d\x02\x19\x3a\x2f\xd3\x94\x66\xf7\x3a\xaa\x98\x9b\x1f\xa0\x5b\x9a\x15\x7f\xd0\x27\x7c\x5e\x74\x5d\x25\x8e\x02\x78\x03\xa5\x24\xad\x94\x30\x94\x25\xc3\xf4\xde\xc3\x1c\x0e\xfc\x54\x77\x52\xf4\xc7\x19\x4c\xbb\x27\x2f\x84\x9a\x52\x16\x9c\x6a\x07\x8d\x20\xed\xe1\x43\x20\x16\x52\x84\x77\xb5\x8c\x2b\xdf\x60\x63\xf9\x44\x7e\x33\x83\x7c\xcb\x43\x7d\x8d\x6b\x95\xcf\x4c\x44\xbe\x70\xc8\x19\x3a\xd9\x80\xa1\x05\xf3\xdb\x6f\x99\x30\xba\xb4\x67\x8c\x77\x63\x42\xfa\xf1\x70\xed\xf7\x42\x48\xd3\xb1\xca\x96\xf7\x31\xb9\xd0\x26\xd8\xf0\xf7\xc3\x4e\xd3\x72\xc1\xcd\xe1\x76\xf5\x5f\x55\x86\x75\xcc\x31\x80\xc2\x39\x02\xf4\xba\x95\x08\xd1\xc9\x1c\x3c\x9e\x68\x87\x30\x32\x7f\x3f\x7b\x63\x7a\x8f\xee\x54\x37\x37\x59\xfc\xb1\x7c\x92\x17\xea\x44\xce\x43\x69\x1a\x8f\x64\x63\x64\x0a\x4a\x5e\x15\x1e\x62\x54\xc4\xef\x12\x62\x3b\x49\x39\x4d\xa7\xcc\x79\x45\x26\x93\x81\x7d\x6b\xae\xa9\xa0\xa7\x58\x76\x94\x8b\x1f\x8d\x3b\x71\x7f\x9e\xc3\x67\x53\xf5\x32\x63\x71\x03\x83\xb9\x82\x62\xae\x63\x54\xff\x2a\x22\x83\x22\x0a\xd4\x2c\x5c\xb2\xcb\xbd\xf1\x2c\x87\x95\x13\x71\x0b\x16\xbe\x85\x6f\x3b\x13\x55\xb3\x6f\x4b\x80\xc0\x17\xc2\x1b\xe8\x5e\x96\x05\x3d\xa0\x50\xc4\x03\x12\x10\x0a\xbb\x64\x0b\x87\x3d\x88\xfb\x6e\xe0\xd1\x9e\x9e\x61\xb0\x4c\x97\x0b\xd1\xf0\x60\xdd\x31\x1b\xbb\x9a\x6e\x35\xb9\x85\xfd\xca\x17\xca\xee\x8c\xd5\xdb\x63\x7a\xcd\x90\xcb\x8e\x82\x32\x55\xc0\x56\x01\x8f\xef\x59\x20\xdb\x64\x0d\x22\x01\xc5\xed\xdb\xd8\xa9\xc9\x47\x4d\xa8\xde\xf7\xe1\x32\x5b\x3c\xc4\x36\xc7\x4f\x81\x5d\xb1\xe4\x2b\x42\x1f\xaa\xb6\x26\xa4\x37\x8c\x2d\x84\x26\x1b\xf6\x49\xa5\x3b\x32\x1f\x59\x8c\x44\xbb\xd3\x00\x2b\x06\xcf\x7f\x1f\xde\xf8\x4a\xb3\x5f\x73\xed\x7d\xc6\x50\x96\xcb\x1d\xc0\xcc\x0e\x34\xc5\x61\xc8\xa1\x5c\xf5\x27\x9a\xbb\xed\x9b\x16\xff\x24\xa9\x74\x4e\x3f\x5e\x64\x9c\xc9\xd8\x88\x4f\x89\x1c\x3f\xb7\x89\x02\x03\x1f\xfe\x0e\x01\x21\xc7\x20\x80\xad\x10\xc2\x47\xb7\xc9\x3a\x9e\xbb\x2d\x84\xd4\xf8\x77\x75\x0d\x7b\x34\x16\x39\x3d\x03\x04\x52\x26\xbb\x79\x94\xee\xa5\x8e\x27\x2d\xc1\x8c\x46\xb3\x82\xd1\xf9\x7b\x23\x76\x5f\xda\x7a\x8c\xe2\x1f\xc6\xb9\x8d\x72\x3f\xfc\xcd\x99\xac\x46\x55\xcc\x5d\x10\x10\x5a\x2a\x5b\x7c\x8c\xfb\xfb\x90\xe2\x7a\x9a\x80\x9e\x41\xae\x64\x00\x63\x28\x64\x05\xa9\xbe\x83\xac\x5d\x29\x07\xa4\x5f\x16\x3c\x77\x64\xb0\x9f\x99\xa5\x55\x93\x22\x0d\x69\x01\x29\x2b\x9b\x58\x03\xa0\xfe\x71\xb0\xe4\x44\x1c\xbf\xef\x84\x1c\x33\xce\xbc\x98\x36\x4d\x66\x6e\x5a\x9f\x5e\x7e\x69\xa1\x50\x8e\x43\x80\xed\x36\x13\x45\xb7\x24\x8a\x4c\x1c\x1c\xe0\x87\x69\xbc\x71\x52\xdd\xb3\x32\xfb\xa1\x76\x20\x0f\x5a\xbb\xae\x38\x12\xf4\x06\xda\x72\xdd\xe5\xdb"}, -{{0x19,0x7e,0x15,0xdc,0xe4,0xc4,0x7d,0x73,0x4d,0xbc,0xe4,0x68,0x8a,0x7a,0xd5,0xfe,0x41,0xeb,0xf2,0xaa,0x29,0xa2,0xbd,0xdb,0x2b,0xee,0x62,0x84,0x29,0xc1,0xbc,0x02,},{0x30,0xfa,0xc3,0x23,0x04,0x8b,0x0c,0x78,0x1a,0x9f,0x63,0xc1,0xee,0x69,0xf2,0xb9,0xe7,0x5a,0x27,0x06,0xd2,0x49,0x51,0x2a,0x27,0x39,0x60,0x7f,0x26,0xdb,0x13,0x8f,},{0x2c,0x3c,0x8c,0xd2,0x99,0xc9,0x06,0x0b,0x65,0x99,0x9b,0x03,0xa6,0x57,0x9b,0xc5,0x0e,0xf1,0xfe,0x0d,0x85,0x1f,0x23,0xbe,0x9c,0xb5,0x8f,0x8f,0xb8,0xc6,0x72,0xee,0x08,0x6a,0x53,0x9e,0xad,0x94,0x9e,0x08,0x7d,0xf0,0x91,0x12,0x2d,0x26,0xfa,0xaa,0xd2,0x06,0xa5,0xc5,0x2f,0xcd,0x58,0xb5,0x14,0xd7,0xa9,0x35,0xbe,0x01,0x79,0x08,},"\xfd\x97\x1d\x48\x94\x6b\x51\xff\xed\x7b\x62\xc5\xd0\x99\xc1\xe5\x6b\x13\x58\xb9\x22\x35\xe1\x01\x0e\x3f\x23\x84\x4d\xdb\x73\xbc\xee\x8d\x2e\x1c\x99\x77\x35\x3b\xc9\x6a\x22\x1c\x05\x60\x29\x31\xfa\x16\xcc\xc2\xab\x6d\x0f\x01\xc8\x46\xc2\x92\x0e\x99\xde\x02\x6d\xc2\x89\x7f\x3d\x5f\x3c\xee\x17\x4c\xe7\x51\xd4\xa8\x05\xee\x19\x59\xa3\xc6\x9c\xfd\x42\xd7\xc9\xaf\xd3\x1f\xa9\xb1\xcf\x05\x78\x6d\x8f\x90\x42\xa4\xf9\xf8\x1c\xf7\xac\x9c\x1c\x39\xb3\x6f\x1e\xe9\x5b\x98\xcf\x7e\xe3\xf4\x3e\x2c\x34\x37\x33\xd1\xd8\x2c\xc0\x8b\x2c\xde\xb7\x8d\x98\x20\x34\x08\x5f\xf4\xdc\x65\x36\xcd\x15\x4a\x79\x0c\x85\xc8\x61\x3e\xc4\xe5\xe1\xdc\x37\x7d\x38\xa7\x45\xd9\x38\xcf\xb1\x5c\x8b\x8a\xa8\x61\x21\x83\x5f\x2e\x25\xe9\xe6\xd0\xde\x68\x02\x5d\x81\x0c\x3d\xc9\xdf\x99\x1d\xad\xad\x39\xdc\x69\x81\xfd\xba\xc1\xff\x9b\x7a\x79\x1c\x39\x60\xd8\x56\x43\x66\xe5\xaa\x39\xa9\xe9\xc7\xcb\xf1\xd3\xf0\xf8\x20\xd1\xb9\x01\x08\x75\x1a\xc7\x64\xda\xbe\x05\xc5\x1c\x18\x52\x9d\xa1\xb0\x34\x96\x14\x66\x84\x24\xab\x4e\x93\x64\x40\xc4\xa2\x51\x3b\xe5\x28\x53\x93\x72\xee\xe7\x87\x54\x58\x9d\xbe\x79\x94\xfa\xa1\xf6\x22\x91\x24\xf8\x39\x95\x0e\xd0\x92\x3f\x43\x23\x31\x5a\xc9\x63\xbb\xe4\xc8\xe1\x77\xda\xc5\x16\xe7\x34\x22\x38\xf1\xcd\xf1\x40\xbe\xfc\x8a\xcd\xca\x3d\x00\x2b\x16\xc1\x39\x8d\x86\x86\x00\x30\x4c\x7e\x98\x53\xb2\x3a\x51\xb1\x7d\x9f\xd0\x61\x56\xe1\xd1\xd0\x8a\x28\x46\x09\x09\xfa\x20\x9c\xcc\xcc\x4c\xec\xbd\xb1\xa4\x63\x48\x08\x91\x15\x31\x86\x81\xa9\x5a\xe5\x80\xab\x67\x66\x04\x13\x84\x65\x1c\xc4\xe6\x14\x51\x03\x92\x3b\xdf\x4a\x32\xa9\x3d\x93\xee\xd3\x18\x79\x1f\x20\x80\x5f\x7e\xa8\x4b\x74\x3e\xe1\x1e\xad\x9e\x4c\xa0\x3d\xa7\x6d\xdd\x24\x9f\xd4\x47\x5f\xc1\xa3\x53\xc7\x0a\x83\x38\x9b\xfa\xc5\x20\x98\xdb\x06\x6d\x10\x29\xc4\xef\xfb\xed\x86\x4e\xbe\x7f\x10\x7e\x01\x03\xb3\xa8\xf3\xfd\x1d\x6a\xb4\x36\x0b\x99\xe8\xb1\x40\xc5\xea\x13\x3e\x92\x3c\x39\x2b\x8e\x40\x63\xaa\x6e\x52\x26\x38\xf6\x1d\x7a\x71\xc9\x22\x58\x97\xd9\xf8\xa1\xe1\x6c\xfc\xc8\x01\xe7\xd5\x41\x04\xeb\x10\xe6\x1a\x5a\xe6\x3c\x5c\x85\xa5\xb2\x93\x92\xab\x3a\xb8\xe5\xc0\x39\xf1\x00\xd0\xf4\x60\x0c\x61\x0e\x02\x09\x43\x6e\xf2\xec\xe4\xd0\xbd\xb0\xba\xb4\x37\xb2\xdb\x5f\x37\x08\xfd\xdf\x96\x66\x0f\x6f\xb1\xa9\x0d\x60\x48\xd3\x95\xaf\xaf\xa7\x60\xcc\xaf\x15\xde\xaa\x0e\xff\xeb\x26\xec\x17\x68\x1d\x17\x2c\x13\x30\xf7\x8e\x78\xa8\x73\x6b\x28\x5f\x61\x5f\x15\xd4\xf2\xc3\x13\xd2\x5f\x30\xae\xe9\xd1\xdb\x39\xf5\x35\xfc\xdd\x0e\xbc\x8e\x71\xb8\x9c\xe6\xb3\xfc\xb5\x67\xcd\x0f\xa2\x88\xf4\x8e\xd3\xa7\x59\xbb\x2e\xd2\x00\xfd\xc2\x30\x91\x50\x2f\xd9\xca\x65\x1c\xe5\xe3\x42\x2a\x98\x33\x5a\x81\xd7\x4a\x65\xcc\x15\x00\xe9\x07\x0a\xbb\x60\x9c\x1c\x1f\x68\xfc\x2c\xa9\x4c\xdd\x55\x0f\x99\xbc\xb2\xd0\x92\x41\x6b\x9b\xd3\x88\x41\x0b\x8f\xe7\x48\xfb\x8c\x9a\x5a\xb8\x61\x5f\x2e\xd9\x68\xf8\x5d\xcb\x27\x27\x72\x69\x84\xbe\xad\xa7\xa1\x8a\xfd\xb0\xc7\x2a\xa6\x5d\xe7\xab\xb7\xa8\x6f\x11\x16\x9a\x6e\xad\xf1\xc2\x1d\x61\x4e\x52\xc0\xc8\xf0\x19\x74\x7d\x34\x1a\x05\xd8\x5e\x37\xbf\x58\xd8\x32\x7e\x99\x39\xc2\x38\x7c\x27\x44\xed\xf8\x38\x56\x3c\xb3\x7f\x0b\x16\xe8\xa0\x6f\xc6\x28\xa9\x72\x30\x50\x6f\xa4\x18\x39\x54\xdc\x74\x81\x5f\x3b\xe2\xeb\x2a\xff\x4a\x13\xc0\x65\xf7\x43\xb7\xd8\x5d\xe8\x04\xeb\x28\xef\xe5\x70\xed\x5e\xcc\x71\xab\xa9\x7f\x97\x63\xb4\x36\x17\x32\x47\xf3\x8e\x0c\xf6\x29\x72\x09\xb6\x51\x28\x46\x5a\x38\x26\x64\xce\xd8\x01\x1f\xcc\x3d\x0e\x56\x3f\x15\x5b\xc6\x3c\x94\xdd\xe7\x3c\x7b\x17\x24\x7b\x8c\x3a\x4e\x80\x34\xeb\xd4\x36\x46\x35\x18\x5c\xe9\xc7\x08\x1d\xbd\xbe\x85\x45\xf7\x9d\x01\xaa\x53\x2a\x0d\xc5\x2c\xb7\x90\xa3\x1f\xc2\xff\x41\xac\xeb\xad\x27\xcc\xe9\x24\x45\x54\xdb\x65\x2f\xa2\x87\xba\xe7\xde\xcb\xcc\x8c\xe9\xe0\x1d\x1a\x88\xab\x41\x2b\x6c\x65\x78\x20\x3b\x42\xde\xc9\x82\xb7\xf3\xb8\x23\x14\xdb\x2c\xc7\xc5\xc3\xdc\x1d\x3d\x8b\x17\x14\x4d\xa7\xfe\x60\xe7\xa8\x72\x5f\xd0\xa9\x7c\x61\x06\x07\xcf\x41\x3c\x72"}, -{{0x08,0xb5,0xfd,0x4e,0x41,0x9d,0x23,0x70,0xc0,0xfc,0xd6,0xc3,0xb9,0x2f,0x8d,0xb3,0xaf,0xd4,0x22,0x68,0xf5,0x33,0x08,0x5d,0x9f,0xce,0x32,0xb5,0x22,0x82,0x4e,0x34,},{0xcd,0x0d,0xa6,0x99,0x37,0x9e,0x4f,0x94,0x25,0xe8,0x4b,0x97,0x57,0x30,0x0a,0x51,0xa1,0x63,0xf3,0x58,0x73,0x4c,0xc3,0x7a,0x91,0xff,0x0e,0xa4,0x88,0xd2,0x97,0x79,},{0x42,0xa1,0x37,0x56,0xb7,0x5c,0x67,0x22,0x48,0x5f,0xa3,0xf6,0x94,0x04,0x1b,0x39,0xb7,0xd7,0xc5,0xfd,0x40,0xeb,0xc0,0x6a,0x52,0xe0,0xff,0x34,0xce,0x14,0xd8,0xd4,0x0f,0xa8,0x2a,0x95,0x08,0xb5,0x68,0x53,0x7d,0x26,0xd0,0xdd,0x7c,0x0a,0x31,0xbe,0x71,0x0d,0xa8,0x0a,0xab,0x35,0x19,0x6a,0x03,0x9b,0x60,0x64,0x1d,0xb1,0xe1,0x01,},"\x3c\xee\xee\xa3\x0f\xa4\x01\x56\x3d\xf3\x6b\x19\x8b\x9b\x59\x69\x8c\x10\xe1\x00\xa2\xf3\x0e\x6f\x78\xfe\x62\xb9\x2e\xca\xc9\x89\xe8\xaa\x09\xec\x76\x0e\x89\xca\xc0\xa1\x6b\xde\x3c\xac\x73\x62\x2a\x86\x27\xef\xed\xfa\x4e\xc0\x9b\x87\x3f\x7e\x10\x00\xe7\x69\x82\x91\x0c\xa0\xaa\x4a\xfb\x1f\xf5\xa8\x44\x8b\x76\xf7\xb0\xd2\xa2\xd5\x2a\x7f\x40\xde\xde\xfc\x68\xd6\x0c\xe6\x62\x2c\xa0\x80\xd6\x69\x8e\xa6\xc3\xbd\x72\x10\xb3\xb6\x48\xf5\x32\x52\x29\x14\x94\xb3\x5a\x55\xff\x40\xfa\x1a\x63\x1a\x57\xc5\x10\x01\x1a\x46\xbf\xb9\xe2\x71\xba\xe1\xe7\x8c\xe6\xc6\xea\x60\xc5\x5b\xa0\xcc\xe3\x60\x59\xbf\xb0\x1e\x39\x45\x56\x98\x7f\x74\x4b\x72\xae\xbb\xdb\x4b\x1b\xdb\xb3\xbb\xaa\xee\x1b\x8b\x2f\x31\x74\x50\x6a\x79\x3f\x0a\x51\x1b\x2b\x56\x90\x49\xb3\x0a\x2e\x08\x41\x42\x41\x84\xa4\x8e\xca\x9e\x2d\x83\x78\x3a\xc5\xb6\x1e\xb9\x47\xcb\xd8\xba\xb7\xad\x38\xb0\xc6\x84\x27\xd8\xf9\x4a\xe2\x85\x19\x0d\xbb\x6e\x0c\x6d\x58\x0a\x25\x14\x23\x94\xbe\x94\x81\x58\xd8\xda\x83\xb4\xf3\x4a\x8d\x25\x8b\x97\x07\x56\x32\xb3\xc2\x8b\xfa\xe3\x10\x5e\xd1\x87\x2e\x35\x6e\x43\xae\xd5\x93\x97\xb9\x11\x0b\xbf\x9d\x8c\xa2\xa0\x44\xd5\x27\x1e\x6c\xc3\x61\xe1\x4e\x69\xa9\x32\x51\x76\x83\xec\x81\x81\x8f\x02\xcf\xa0\x29\x5e\x56\x61\xce\xa3\xe5\x86\xaf\xc0\xdb\x41\xba\x95\x55\x3e\xe7\x5b\x20\x0b\x0f\x97\x90\x11\x1d\x37\x57\xa7\x39\xe5\x63\x55\x7a\xff\x9b\x70\xca\x14\xe8\x7b\x79\x54\x37\xba\x91\xa9\x5d\xd0\x7e\xa6\x9a\x11\x35\x9f\x36\xca\x03\x29\x8e\x0b\xfa\x4f\x91\x2f\x64\xa2\x92\x4a\xd9\x01\x97\x5a\x2a\x96\x0b\xa1\xbe\x89\x92\x1b\x1f\x54\x85\x49\x6b\x7e\xa5\xda\x6d\x8a\x69\x37\xac\x10\x5b\xf3\x76\x0e\x48\x76\x99\x0a\x0f\x5c\x5a\x63\x4f\x74\xcb\x57\xdf\x7c\x17\x2c\x8a\x41\x53\x72\xe6\xd9\x03\x29\x87\x17\x49\x96\x16\xf8\x97\x1c\x68\xbb\xec\xe9\x2e\xa8\x78\xa1\x8e\x23\xf3\x27\xc3\x64\x9b\x6a\x85\x2e\xf2\x3b\x7b\x3e\x60\x3c\xdf\x80\x45\x2d\xbf\x1b\xe2\xfb\x77\xe8\x14\xd2\x52\x54\x96\xbb\x31\xfb\x6e\x4e\xd2\x53\x32\x48\xb3\x9d\x5f\xbe\x23\x90\xa9\xb6\xfc\xca\xba\x99\x7e\x8b\x49\xb5\x98\x36\xe3\xe0\x95\x29\xea\x5e\x41\x13\xee\xe4\x51\xc9\xc6\xbb\x26\x74\x1d\x0e\x4c\x58\x6f\x53\xd6\x04\xc6\xea\x0c\x0e\x60\xdb\x02\xe5\x10\x9f\x37\x34\xf5\x1c\xdd\x89\x85\xaf\xeb\x3e\xca\xff\x65\xe0\x59\xe3\x12\xcd\x50\xfa\x34\x9f\xf2\x8b\xdc\x9b\x70\xb7\xf5\x32\xdb\xab\x1d\xf4\x3b\x03\x16\x7c\x1d\x2e\x3f\xa6\xee\x8c\x9b\x17\x4a\x0b\x2c\xf8\xaa\x9f\xfa\x40\x6b\xf5\xbd\x72\x88\x78\x0c\x9c\x4a\x6b\x69\x79\x49\xb4\x86\x38\xd4\x20\x79\xc8\xc6\x6e\x14\xd9\xb5\x72\xa2\x10\xa0\x93\xea\xf1\xd2\xf7\xa7\x03\xb5\xcd\x20\xad\xc4\xf9\x92\x7a\x6e\xa8\xea\x78\xfa\xa6\x1b\xc6\x2b\x3c\x5c\xbd\x3a\x53\x25\x25\x66\xd0\x43\xba\x55\x65\x90\xd9\xa7\x63\xbe\x7f\xea\x4b\x20\xe1\xe9\xcf\xbe\xbf\xae\x15\x43\x9b\x33\x4d\xc5\x39\xb1\x7d\xad\xa2\xe4\x34\xe9\xc8\x32\x25\xb1\xe8\xf6\xbe\xb7\xd5\x56\xb4\x7d\x7f\x69\xf7\xeb\x7d\xf5\xed\xe2\xee\xbd\x84\xe2\x50\xb7\xc9\x46\x8c\x21\xfd\xc0\x17\x0e\xa8\xdf\x66\x2d\x61\x80\x58\x1f\x65\x7f\xe7\x6c\xef\x18\x58\xb6\xb0\x2f\x73\x25\xc7\x21\x96\x43\xfb\xa2\xf7\xe9\x96\x3a\x33\x32\x2d\x65\x04\xab\x91\xbf\x10\xa9\x78\xfa\x07\xb4\x7d\x5d\xb0\xbe\x00\x0d\xcd\x00\x2b\xdd\xaf\x67\x6b\x77\x25\x9c\x9f\x60\xad\x0b\x11\x67\x1c\xd5\x77\x7c\x1e\x80\xb1\x3f\x82\xeb\x0f\xb6\xa1\x80\xb5\x66\x62\x93\xa4\x32\x40\x86\x2f\xbf\xa3\x97\x8d\x95\x31\x19\x71\xaf\xab\x9e\x1c\xc8\xab\x14\xa8\x76\xb6\x57\x2a\xc8\xa4\xb7\xe0\xb4\x0a\xaf\x6b\x52\xa1\xcf\x4c\x1e\xbc\x6c\x1c\x48\x7d\xf5\xa3\xcb\xc4\x00\x5a\x0e\xe3\x29\xca\xbc\x28\x6d\xb1\x0f\x17\xd0\xf1\x78\x2e\x07\xd3\x32\x4f\x0c\x73\xef\xbd\x3c\x2f\xb5\x2b\x71\xf9\x8a\xd9\x5d\xb9\x50\x62\xd9\x14\x25\xe7\x34\x67\xbc\x1e\x4e\x9b\xf5\x52\xe8\xa2\x44\x29\xd9\x7d\xb1\xd6\x6d\xd4\xd9\x95\xe5\xf8\xd2\x4e\x9c\x91\x0b\x2e\xb1\x75\x8e\xf7\x55\x25\xc3\xd6\x5a\x3f\x43\x0a\x02\x73\x48\x82\x0c\xe3\x05\x3b\x6f\x3a\xf4\xec\x96\xd0\x49\x37\x31\xc8\x18\xc6\xb1\xa7\x0c\x25\x0a\xc6\x86\xa4\xfc"}, -{{0x1e,0x85,0xc9,0xe4,0x51,0xb7,0xac,0xf8,0x01,0xd1,0x6b,0xc8,0x26,0x8e,0xb4,0x2a,0xe8,0x5c,0x72,0xc6,0x8e,0x9f,0x90,0x92,0x7a,0xa0,0xf3,0xb5,0x0b,0xef,0xd2,0x29,},{0xa6,0x9d,0x05,0x7f,0x4b,0x74,0x38,0x11,0xe0,0x7a,0xc7,0x45,0x61,0xc2,0x25,0xbe,0x03,0x81,0xc7,0xd5,0x84,0x9e,0x60,0x18,0x79,0x37,0x01,0xa8,0xcb,0x6c,0x99,0xb5,},{0x6c,0x36,0xda,0x9a,0xd6,0xc4,0x56,0x34,0x3c,0xe6,0x42,0xac,0xa4,0x54,0x92,0x3a,0x52,0xa2,0x84,0x4c,0xe5,0xee,0x58,0x94,0x7c,0x8d,0xf7,0xba,0xb2,0xeb,0xe4,0x67,0x82,0x3c,0x56,0x33,0xe5,0x30,0xb1,0x67,0xd7,0x1c,0x47,0xad,0x95,0x49,0xdf,0x05,0x94,0x3f,0x99,0x42,0x1e,0x17,0x47,0x5c,0x4d,0x4f,0x08,0xde,0xdf,0x6f,0x32,0x05,},"\x18\x9e\xa9\xc8\xd9\xed\x14\xb0\xde\x82\xb4\x4c\xbd\xd5\x87\x57\xa2\x7c\x68\x38\x3f\xba\x59\x77\x61\xf9\xe8\x62\xe0\x8d\xe1\x5b\x1e\x44\xc3\xdb\x1b\xad\xbd\xe7\x69\x80\xee\x39\xe6\x99\x62\x9f\x6f\xcf\xef\x32\xd3\x6b\x33\x93\xda\x2c\xa5\xa8\x1f\x95\x9c\x8b\x0f\x1b\x80\x1b\x5f\xa4\xc4\x7c\xa3\x95\x91\xe6\x12\xa2\x43\x5c\x5b\xaf\xd7\x7a\x5c\x7a\xb7\x43\x59\x21\x09\x06\xf4\x75\x33\xb1\x87\x9e\x2a\x5a\xf5\x86\x4d\x96\x1c\x81\x46\xe2\x5d\xac\x77\x25\x55\xe0\x42\xa8\x87\x26\x14\x19\xab\x8c\x9f\x6f\x62\x56\x25\x48\x1d\xa5\xb9\x35\x26\xa1\x31\xf3\x7b\x53\x4a\x00\x50\xa8\xa4\x62\xb3\x3f\x20\xa7\xe9\x4b\x89\x15\x30\xb1\x9b\xf6\x54\xee\x95\x34\xc9\xa8\x36\x1d\x03\x63\x5d\x8d\x27\xd4\x6b\xe7\xbf\x84\x78\x1a\xd0\xd4\x2d\x1e\x7c\x48\x54\xa4\x9b\xa1\xba\x45\x82\x62\xfe\x5e\xa1\x90\x21\xb9\x35\xa6\x94\x94\x92\xd7\x0b\x60\x5e\x15\x19\x89\xef\x26\x41\xb2\xbf\x81\xec\x4b\x92\x02\x0f\xc7\x07\x4c\x2a\x63\x22\x9d\x51\xa9\x44\x18\x6a\x28\x89\x5e\x8e\xa9\x52\x92\xc2\xf8\x72\xbb\x21\xa3\x14\x93\x99\xe2\x3c\xcd\x8e\x2f\xc4\xf1\x7a\x46\xb5\x9c\x28\x2c\x51\xb5\x8d\x00\x26\x6a\x5c\x16\xb1\xce\x35\x0d\x54\x85\xe8\xd8\x01\x6d\xd0\xa5\x0a\x59\x84\xcc\x94\x81\x54\xcd\x5c\xe7\xcd\xa0\xee\x0a\xb1\xd7\x25\x1b\xdc\x70\xa1\x78\x5b\x8e\x91\x03\x91\x7f\x4b\x91\x7a\xb2\xb4\x94\xf3\x48\x33\x89\xa2\xf9\x23\x75\x41\x84\x9e\xd3\xbd\x56\x5c\xff\xac\x9e\x75\x6d\xb5\x6e\xf5\xe2\x34\x95\xbc\x77\x1e\x88\xbf\xfa\x87\x07\xce\xea\x5c\x09\xbe\xca\xdd\x05\x9a\xb8\x89\xd1\xdf\x7e\x88\x7b\x71\xa9\xe6\xc2\x38\x37\x8f\xbe\x0c\x36\x30\x38\x66\x16\x36\x3f\x20\x7b\x16\xc3\x27\x0d\x39\xac\xde\xd5\x11\x52\x99\x92\xf4\xe5\x98\x78\x91\x21\xd3\x16\x13\x58\x10\x63\x6b\xaa\xde\x8a\x28\xed\xc6\x6b\xbf\x5e\xde\x3f\x40\x4a\x70\xb4\x7d\x35\x98\x8b\xe7\x06\xb4\xea\xa0\x30\x23\xa3\x90\x93\xd5\x83\xcd\x4c\xd8\xbf\x4c\x74\x34\x1a\x02\x8c\x19\xd6\x0d\xa3\x1b\x6a\x7a\x03\x4c\x08\x1a\x2b\x03\x0f\xeb\x3c\xd2\xf0\x3d\x0f\xaa\xbf\xfb\x58\xe3\xfc\x36\xc0\x06\xcf\xb9\x29\x47\xa7\xde\x5b\xa8\x74\x76\xc1\xb0\x51\xe1\x82\x83\xc0\x3e\x9c\x6e\x5a\x5c\x3c\x27\x77\xd9\xa0\x75\x73\x72\x37\x96\x64\xe8\x2f\x84\x85\x82\x4f\xed\xb7\x0a\x4b\xc4\xe3\x56\xed\xd1\xb5\xce\x0f\xb6\xe4\x1d\xe0\x17\x16\x21\xb8\x4f\xaf\xa0\x01\x89\xaf\xa8\xa6\xa9\x00\xb1\x4c\x70\x75\x8f\x7a\xa4\xfb\x82\x40\x0e\x0d\x18\xab\x3c\xd7\xe4\x8a\xcf\xd4\x89\xca\xb0\xe7\x2e\x71\x9f\x79\xa0\x7d\x06\x6c\x53\x1a\x89\x1c\x55\x29\x1f\x22\x45\xdb\xbe\xe4\x4e\x52\xb1\xdf\xc8\x72\x7a\xae\x38\x7a\xb9\xe7\x19\x94\xa3\x85\x4e\x1a\xdd\x73\xd9\xa7\x96\x5c\x77\x55\x21\xc2\xf5\x40\x84\x22\x76\xdd\x30\x9e\x2f\x6a\x34\x1e\x7f\x0f\x37\xf2\x2b\xb6\x62\x7b\x6e\x9c\xb2\x5b\xa2\x4c\x6c\x4f\x4e\xb9\xf5\xe7\x62\x2d\x88\xda\x19\x84\xe2\x9c\x5d\xa0\x01\x03\x9c\x44\x04\x2b\x59\x35\x14\x06\xa4\x13\x36\xdd\x77\x2d\x49\x7d\x3f\xc8\xaa\xc4\x11\x72\xeb\x5a\xa6\x41\x7f\xe4\x22\xec\x7c\x15\x0b\x96\xb0\x45\x4e\xe3\x31\x24\x7c\xb1\x53\x8a\xef\xf3\xec\xa2\xd5\x0e\x53\xd6\xd1\x31\x70\xa7\x6a\x00\x49\xea\x0c\x05\x90\x4a\x63\x90\xed\x14\xce\x74\x91\xe9\x7f\x75\x4c\x52\x22\xda\xc4\xb6\x11\x8b\xa3\x81\xf5\x52\xe7\x3e\xa8\x49\x1e\x3b\x7a\xc9\x49\x56\x9b\x56\x9c\xf2\xd2\x9a\x80\x41\x0e\x06\x5b\x5c\xc4\xa4\x66\xbb\x04\xeb\x7a\x15\xf5\x96\x79\x2e\x84\x90\xba\x70\x02\xec\x36\x15\x71\xaf\x5d\x8f\x57\x67\x5c\x95\x64\x49\x47\x0a\x2f\x99\x55\x40\x73\x67\xe4\x09\xa2\x32\x89\x95\x53\x12\x0a\x27\x7d\xb8\x63\xe9\xa8\x2d\xda\xba\xe8\x7b\x78\x91\x45\xba\x89\x8d\xf3\xc2\x8b\x96\xfb\xe3\x01\x4c\xd0\x85\xc6\xe6\x0e\xe8\x83\x17\x01\x03\x6d\x99\xc5\x42\x5d\x58\xe8\xbc\xc9\xfd\x92\x71\xd4\x6a\xec\x1e\xb9\x55\x13\x01\x02\xea\xaa\xb4\x4e\x07\x70\xc3\x0b\x2b\x12\x7e\xfb\x0e\x5f\x8a\x3f\x7a\x0c\xa3\x4e\xc9\x98\x4a\x46\x01\x1b\xc2\x6b\xfd\xe0\xc0\x81\x9b\xb5\x47\x06\xb5\x65\x63\x8b\x75\x42\xdc\x4b\x8b\xf8\x09\x8d\xc0\x1f\x16\x1b\x3b\x12\x96\x18\xb5\x9a\xde\xd3\x3c\xb5\x9c\xe9\x18\x9a\x67\x62\xdb\xae\x5b\x0d\x34\xb7\x1c\x8d\xbf"}, -{{0x51,0xcf,0x86,0x8f,0x82,0x0e,0xed,0xa0,0xdb,0xd1,0x01,0x80,0xf7,0x77,0xe6,0x06,0x5c,0x93,0xa4,0x83,0xc5,0x8a,0x77,0x8b,0x67,0xe7,0xd8,0x42,0x30,0x2f,0xb7,0x67,},{0xab,0x08,0x8f,0x50,0x2f,0xbc,0xf2,0x15,0x0e,0x48,0x46,0xb3,0x4d,0x2c,0x80,0x97,0xff,0x01,0x3c,0x02,0xa8,0xb9,0x7c,0xfc,0xf2,0xb9,0x5a,0x1c,0x72,0xdf,0x3e,0x24,},{0xe1,0x53,0x42,0xa1,0x1c,0xaf,0x89,0x28,0x95,0xe4,0x66,0x22,0x88,0x63,0xd0,0x83,0xb0,0x69,0x2f,0x01,0x06,0x10,0x74,0x8c,0x23,0xdf,0x2f,0x11,0xd2,0x94,0x75,0xba,0xfc,0xe9,0x27,0xca,0xfe,0x7f,0x07,0xef,0xb8,0xc3,0x47,0xed,0x56,0x63,0xe7,0x3b,0xea,0x89,0x53,0x1c,0xed,0xc0,0xc3,0x48,0xe7,0x9b,0x6e,0x58,0xa7,0x57,0x49,0x07,},"\x7c\x2d\x8e\xe8\x2d\x9a\xbf\x8a\xa9\xc7\x24\xc7\x5b\x90\x99\x04\x73\xf1\x31\x76\x3f\xe9\x3b\x30\xcb\x04\x72\x35\x88\x62\x1d\xa2\xa3\x27\x92\x8b\x22\x64\x9f\xa0\x62\xcd\xea\xbd\x77\x76\x15\x38\xb2\x70\x9b\x8f\xb7\xa2\x00\x6e\x50\x35\x09\x13\x4c\x92\x9c\x30\x11\xe1\xd7\x28\xa5\x7a\x4e\x17\x51\x98\x07\x5e\x21\x42\x53\xf3\xf3\x0e\x01\xb6\xe0\x4e\xab\xd4\xde\x06\x78\x95\x58\xe6\x98\xb1\x86\xef\xe3\x4b\x32\x12\x95\x68\xb3\xe8\xd0\xd7\xea\x3f\xf0\x0b\x3f\x25\xa4\x22\x36\x89\x3a\xa8\xa4\x1b\x67\x4a\x0a\xb5\xf4\x1e\x7b\x28\xcf\x5a\x7c\xb7\x65\xe1\x8e\xad\x6d\xe6\xa3\x53\xa7\x82\x4a\x3c\x49\x78\x60\x38\xd6\xf4\x93\x7f\x32\x64\xd6\xcc\xf0\xc0\xa2\x46\x5b\xb6\x93\xe5\x2b\x3d\x1e\x6e\xb9\xae\x4c\xb6\x5d\x09\xcf\xf5\x48\x42\xe8\x53\x62\x85\x7a\x59\xf7\x19\x8a\x68\x8a\x3d\xf3\x85\x13\xcd\xd6\x1e\x21\xdf\xd8\x59\x14\x2c\x83\x44\xa3\xb8\xb2\xa7\xc7\xdb\x17\x0f\x39\xf8\x7c\xa3\xff\x8e\xd4\x27\x96\x2b\x2b\x1a\x14\xd1\x22\xfa\x2d\x5a\xea\x2a\x66\x40\x11\x7d\xd2\x58\xfa\x0f\xc5\x4a\xc6\xe9\x40\xbc\x16\xd2\x11\xec\x9a\xdf\x91\x4a\xb1\x65\x78\xf5\x21\xf6\x55\xd2\x12\x7e\x79\xe8\x71\xbf\x7f\xa7\x54\x47\x19\xd5\x8e\xd8\x47\x85\x0c\xb2\x7b\x99\xeb\x8f\x29\xb1\x6c\xdc\xc2\x8b\x15\xc1\x25\x9a\xb4\xd5\x89\x70\x5a\x40\x66\x88\xf6\x05\xa2\xeb\xf5\x80\x51\xc4\x3a\x77\xc4\xe0\x1f\xd6\xf7\x49\xd3\x2d\xb4\xe8\x9f\x26\x3c\x2c\x16\xde\x18\x1f\x0e\x6b\xdd\x0a\x6a\x64\xff\xe6\xf1\x82\x94\x44\x09\x6d\x9f\x3e\x2b\x67\xe4\xbb\x00\x66\x50\xb5\x92\x9d\x1f\x82\xeb\x11\xbb\xed\x24\xe8\xf1\x01\x8a\x73\x84\x60\x5a\x3c\xf2\x9a\xb5\x98\x33\x79\x39\xc7\x6a\x3b\xe8\x61\xe4\x83\xc5\x80\x5e\xc3\xce\xe4\x5e\x34\x24\x84\x7a\x08\x55\x8d\xcc\x99\x49\x9f\xb9\x38\x2a\xca\xe5\x6c\xdc\x87\xfb\xd5\xb2\x6f\xf9\x4c\x86\xf2\xe1\x08\x79\x43\x83\x50\x1c\x8b\x33\x36\x68\x50\xa7\x6a\x0d\xfc\x0a\x7c\xd7\x89\xa0\x3f\x01\xa3\xe9\xd9\xe9\xae\x39\xfd\x72\x45\xdc\x29\x29\x9d\x24\xf3\xb4\xb1\x67\xca\xcc\xd2\x23\xa9\x9b\x6b\x20\xa3\xb6\x73\xdc\x5f\x74\x66\xd0\xb2\xf8\x15\x09\x8a\x49\x7c\xca\xf8\x04\x20\x16\x8e\xdd\xbf\x4d\xa5\x7b\x86\x66\xe9\xd3\x3c\x48\xeb\x30\x4b\x4c\xfc\xf4\x57\xcd\x76\x59\x54\x3f\x6d\x1e\x66\x18\x90\xf5\x62\xb4\x3b\x8b\x6d\x1c\x4d\xcc\x07\x7b\x60\xbf\xa5\x33\xff\xab\x92\x8d\xbf\xd9\x55\xdc\x51\x16\xd7\x70\x95\x0b\x69\x0e\x21\x06\xad\x52\xd4\x2c\x31\xc2\x2b\x88\x48\x89\x43\x32\xb5\xc6\x99\xe5\xc3\x31\xfb\x38\x1e\x58\x12\xe7\x52\x6f\xdf\x4b\x8a\xa2\xda\xaa\x2c\xa2\xcf\xb9\xc9\x21\x11\xb6\x1c\xbc\x3d\x1e\xef\x6c\x8c\x67\x37\xf0\x55\x88\xf0\x44\x67\xdb\x83\x30\x84\x3a\xcc\x98\xdc\x1a\x16\xfb\xd9\xd9\xd9\x4b\xd8\xbf\xde\x26\xc3\xf7\x1d\xee\x72\xb5\x09\x10\xc3\x6b\x24\x0f\x80\x2a\x61\xca\x16\x37\x2f\x6f\xfa\xad\xb2\xbe\x4e\x85\x3c\x5e\xd6\x9a\x3d\x1f\x6c\x7b\x2d\xe5\x13\xc5\x3a\x3f\xdd\x0a\x67\x6f\x83\xd0\x9d\x5c\x51\x17\x60\x47\xd9\x20\x07\x16\xbf\x22\xba\xe4\x5f\xe0\x1b\x3e\x0c\x2c\x51\xc1\x6e\x46\xad\x06\x37\xf7\x9f\x9b\x4d\x83\x86\x77\x04\xfe\xda\x9f\x22\x78\x31\xde\xa2\x63\x39\x9c\xa2\x77\x1a\x4e\x78\xb4\xdf\x8a\xc0\xde\x6a\x94\x1e\xab\x37\x0b\x1f\xdb\x47\xda\xf6\x64\x2a\xae\xaa\x63\x17\x0f\xa9\xb3\xd1\xe1\x62\x8f\x7c\x4e\x7c\xf0\xea\x8b\x8a\x8e\x51\x8c\xba\xce\xf9\xad\xe8\x4d\xf0\x32\x48\x48\x47\xff\xb6\x1b\xbd\x07\xe8\x72\x7c\xc4\xc2\x5d\xa5\x77\xb2\x64\x51\x9b\x49\x99\xfa\x7c\x0b\xc3\x23\xd4\xf3\xf9\x73\x9f\x78\x0b\x9b\x2c\x23\xc7\x78\x55\xee\x5f\x6d\xcc\x40\x15\x44\xd6\xb6\x4b\x27\x70\x15\x8f\xdc\x6c\x12\xf4\xd8\x9b\xeb\x04\x4e\x0e\x85\xac\x7a\x68\xd4\x29\x17\xb1\x34\x51\x14\xb9\xa6\x72\xd1\x23\x1b\x2c\x6c\x0f\x96\x9f\x20\x35\x31\xe7\x1b\xbb\x40\x05\xb1\x03\xa7\xdc\x3a\x58\xb5\xb8\x24\xa7\xe0\x1b\x6e\xb9\xf4\x96\xdf\xa6\x4d\x64\xd8\xc6\x77\x7f\x53\xaa\x58\xd5\xda\x04\x6d\x72\x6f\x55\x45\x4c\x88\xb6\xd7\xd4\xab\x0d\x21\x98\xa8\x97\x09\xf1\x18\xa6\xb3\x24\x60\xb9\xeb\xce\xff\x3f\xdd\xc6\x05\xda\x77\xef\x3d\x1b\xa3\x0f\xec\xf0\x7b\xe2\xf5\x31\x3f\x4e\xe6\x35\xaf\x5e\x95\x61\xd8\x77\xe9\x9c"}, -{{0x54,0x3d,0x5f,0x1d,0x4a,0x6e,0x10,0x29,0xb1,0x91,0x41,0x38,0xfb,0x1f,0x46,0x59,0xe6,0x94,0x56,0x55,0x72,0x07,0x40,0x66,0x88,0xa2,0x03,0x5c,0xbb,0xb2,0xa6,0x8a,},{0x3c,0x83,0x79,0x0c,0x3b,0x45,0x53,0xde,0xae,0x4f,0x84,0x3b,0x50,0x1d,0x26,0xf6,0x16,0x70,0x93,0xee,0x54,0xe2,0x79,0x75,0x9f,0xfa,0xd8,0xcb,0xc0,0x61,0xe7,0x20,},{0x55,0x20,0x11,0x94,0x02,0x6f,0xd6,0x44,0x8b,0x1d,0x52,0xf8,0x3e,0xd2,0x0a,0xc2,0x84,0xe7,0xe7,0x7f,0xa9,0x2d,0x52,0x95,0xd3,0x38,0x25,0xce,0xa3,0xac,0xa4,0x7e,0xc7,0xaa,0xca,0x2f,0xc0,0x86,0x79,0xf9,0xac,0xfc,0xed,0xb3,0x76,0xfd,0xa4,0x61,0x9b,0xe3,0x27,0x2c,0x74,0x45,0xe8,0x70,0x5c,0x30,0x61,0x41,0xcd,0xe1,0x6c,0x0f,},"\xfe\x00\x57\xf0\x62\xfc\x87\x13\x24\xb8\xbd\x5d\x42\x7e\x9a\x52\x76\x23\x1b\xd3\x09\x90\x7e\x58\x81\xd7\xae\x53\xb1\xf3\x70\xc2\xa4\x33\x02\xa1\x65\x10\xb4\x60\x64\xa3\x07\x36\xba\xc9\x09\x51\xf1\xd9\x88\x1a\xf6\x2c\x70\x14\x83\xeb\xb9\x27\x2a\xd7\x72\x12\xee\xb5\xfc\xbc\x7e\xc2\x28\xd9\x69\xf8\x90\x27\x32\x11\x3b\x98\xe3\xbf\x82\xdf\xea\xdd\x0d\xe5\xe7\x65\xd2\x87\x0b\x12\xd1\xf9\xb5\xa2\x82\x97\xc9\xfd\xd1\x49\x5c\xf8\x77\x89\x19\x6a\x7d\x64\x4e\xec\xd9\x35\x87\xdb\xf2\x0c\x28\xeb\x09\xda\x28\x66\x03\xc5\x82\xd2\x12\x9a\x65\x7d\xb2\xd1\x7a\xdd\x35\x58\xdd\xe0\x29\xce\x27\xb8\x83\x52\xde\x3f\x95\xab\xa1\x7e\x1e\xd1\x91\x37\x22\xdb\x08\xa7\x95\xdf\xbb\x70\xd6\x2a\x88\x02\x72\x4c\xb0\xf5\x35\xf8\x48\xd0\x52\xaa\x3d\xde\x91\x66\x96\x3a\x80\x41\xfc\xcc\x4e\x60\xbf\xb1\x1d\xe2\xbf\x28\x6e\xb6\x02\xa4\xaf\x84\x2f\x4d\x1a\x34\x0d\x78\xbb\xbc\xb2\x85\x7f\x0c\x30\x8f\x44\xbb\x10\x1e\x7b\xc8\xb7\x41\xd5\x06\x09\x4e\x27\xbb\xaf\xa7\x24\x28\xef\x66\x6e\xa6\xea\x16\xf7\x99\xb4\xee\x58\x27\x8f\x04\x59\x74\xd8\x6d\xc7\x2c\xf5\x26\x0d\x96\xf9\xc0\x9b\x2f\x11\x81\xe1\xa4\x50\x0f\x92\x83\xdc\x67\x7f\x38\x4f\xf6\x4e\x51\xe8\x9f\x76\x58\x20\x20\x32\x6c\x38\x8c\x08\xa0\xfd\x00\xde\x73\xd5\xd4\x9c\x06\xc0\xc6\x84\x19\x1a\x26\x4f\xff\x72\x6d\x87\x2d\xc3\xae\x49\x6c\x7b\x47\x8c\xfc\x61\xb5\x17\x14\x19\x2f\x76\x46\x3e\x3d\x0a\xab\x41\x0e\xa1\x15\xe8\xbe\xfe\xdb\x99\x7d\xdd\x16\x99\x21\xb3\x20\x7e\xa6\x6c\x1f\x59\x45\x0b\x76\x23\x12\x9f\xd1\xe2\xdd\x3d\xa8\xf5\x20\x63\x91\x17\x13\x38\xea\x0e\xc8\xef\x3c\x59\xed\x8a\xfc\x69\xf3\x86\x5c\x29\xa0\x72\x3a\x9b\xbe\x95\xa7\x42\x68\x1e\xf9\x85\x7e\x81\xab\xc8\x0c\x92\xd2\xa7\x18\xa8\x04\xf5\x30\x4f\xef\x3c\x63\xd7\x99\xa6\xef\x87\x82\xa7\xdb\x46\x68\x1d\x0d\xe3\x50\x64\x46\x98\x22\x67\xb2\x15\x2b\x0c\x32\x18\x69\xe2\x3c\xce\x8c\x4e\xbe\xbe\xaf\x4a\xa1\xeb\xe9\x28\x3b\x69\x26\x05\x26\x0f\xf6\x21\xb0\x3c\x10\x82\x2a\xa5\xf6\xd0\x3b\xde\xf4\x9c\x46\x2a\x68\xd4\x71\xe8\x49\xe1\x64\xe3\x87\x4f\x6e\x9f\x6c\xb3\xb5\xf2\x93\xeb\x38\xae\x52\x45\xa1\x59\xec\x42\x61\xa9\xbf\x6b\x5f\x7b\x76\x15\xfd\x33\x9e\xa1\x27\x33\x11\x3c\xe7\x67\xf8\x83\xae\x66\x75\x41\x7f\xc7\x70\xb5\x0b\xd6\x0e\x6f\x20\xad\xdb\x29\xc1\xf7\x50\x62\x33\xe3\x2a\x7e\xbf\xad\xab\xff\x98\xcf\xd0\x9b\x2b\x3b\xbd\x3e\xae\x00\x69\x54\x8b\x9d\x89\x87\xaf\x46\xca\x98\xeb\x09\x5b\xac\xbd\x87\x47\x24\xba\x10\xf3\x63\x3a\xa0\x8a\xb6\xec\x26\x49\x4d\xdf\x68\x54\x30\x9b\x55\xd4\x3b\xdb\xd2\x9a\x75\x56\xf1\x2d\xfb\x23\xcd\x0d\xb4\xeb\x39\x37\xa6\x5c\x4a\xed\x96\xe8\x7b\x34\x65\x55\xf9\xfc\x68\x97\x94\x3a\x0f\xae\xe6\x5c\xcf\x39\x4b\xd8\x9b\x38\x1b\xee\xce\x25\xd1\xba\x68\xf8\xfe\x32\xc2\x3b\x33\x54\xf5\xbe\x7e\x3e\xa3\xc0\xde\xc0\xf7\xec\x2d\xd8\x3f\x92\xb7\x30\x58\x89\x2b\x63\x8d\x4c\x3b\x72\x42\xbb\x8f\x55\xbf\x08\x7b\xa4\x5a\x19\x0a\x69\x8b\xae\x67\x5e\x0c\xd5\xe8\x44\x6f\x2b\x21\xae\xb6\x3d\x2c\xae\xa0\xf6\x79\xa8\x37\xe7\x93\x57\x30\x8d\x9f\x0b\x8a\xf3\x1f\x9d\x08\x00\x8c\x39\xee\x8d\x34\x75\x28\x71\x3c\x88\x50\x01\x7a\x7f\x4a\xb9\x8a\x35\xc7\x53\x19\x40\xfa\x76\x21\xe6\x72\x03\xee\x78\x2d\xb3\xa2\xfa\xa3\x0f\x3a\xa8\x50\xa5\xff\x7a\xae\xd8\x4c\x00\xff\xd2\x14\xf2\xc9\x26\x17\x35\xfa\xc3\x25\x9d\x50\xe0\x3c\x26\x52\x50\x52\x79\xd9\x12\x51\x92\x7d\xe5\xe5\x6a\x8b\x90\x64\xcc\xf9\xf4\x5d\xcb\xef\x46\xe1\x18\x9c\xed\x2b\xc7\x9e\x6f\xf6\x52\xe6\x90\x97\xac\xe5\x56\x8b\xb2\xd5\xbe\xf3\xce\x21\xa2\x5b\x3f\x79\xee\x27\x5e\xa3\x4e\x62\x13\x80\x56\x6d\x70\x4c\xd9\x3f\x24\xdd\x90\x20\x93\x2c\xc0\x52\x18\xc2\x3b\x5b\x22\xff\xfa\x7e\x99\xee\x7f\xe4\x57\x87\x6a\x5e\x33\x64\xc9\xa8\xe8\xb0\x49\xcf\xa2\x09\x69\x77\x4f\x50\x6d\x19\x96\xcb\xe6\xef\x5a\x37\x79\x3e\xcd\xb0\x4c\xfd\xea\xed\x7d\xcf\x79\xab\x27\x84\x74\xdd\x77\x08\x22\xd4\xb3\x6f\xc6\x8e\x4b\x2d\xd6\x61\xef\x99\xde\x01\xde\x6e\xec\x57\xfa\x57\x3e\xde\x10\xfb\xbd\x5a\xc6\xfd\x6c\xd8\xbb\x4e\xee\x50\x9d\xbb\x46\x10\x37\x44\x01"}, -{{0xf8,0xd2,0x57,0xfd,0xfc,0xf9,0x97,0x96,0xf8,0xce,0x4d,0x8a,0xad,0xe3,0xb2,0x25,0xa5,0x3c,0x26,0xfe,0xec,0xef,0x39,0x5b,0x95,0x61,0xd9,0xd5,0x87,0xf5,0xa3,0x3c,},{0xf6,0x6b,0xd4,0x87,0x7d,0xf7,0x8a,0xec,0x04,0xca,0x7e,0x77,0x73,0x28,0x99,0xde,0x06,0x77,0x7e,0x69,0x86,0x29,0xf2,0x99,0x69,0xf8,0xfa,0x9c,0x2f,0x47,0xab,0x9e,},{0x92,0x35,0xd4,0x48,0x07,0x86,0x98,0x16,0xe2,0x8e,0x42,0xc8,0x1c,0x80,0x1f,0xfb,0x12,0x1d,0xe8,0x26,0xc0,0xd3,0x3d,0xcc,0x4a,0x4e,0x1c,0x93,0x2d,0x52,0x28,0xb6,0x39,0xbb,0x29,0x4e,0x16,0x09,0x0a,0x93,0xd1,0xf6,0x90,0x4a,0x70,0x04,0x22,0x2f,0xda,0x0a,0x55,0x44,0x6d,0x99,0x01,0xc7,0x23,0x40,0x00,0x7b,0xb4,0x5a,0xe1,0x03,},"\x23\x3e\x1e\xf9\x01\xab\xcb\x69\xfb\x48\x60\x85\xd8\xdb\x02\x33\xff\x78\xf3\x7b\x13\x6f\x0a\xfe\x24\xf7\xda\xc1\x94\x4c\x36\x78\xe7\x4f\xed\x58\xa1\xad\x54\x83\x5b\x7d\xbc\xb4\x6f\xff\x6c\x35\x24\x31\x22\x73\x30\x0b\x6d\x87\x8a\x93\xe0\x60\x8a\x4a\xba\xca\x4e\x31\x94\x72\x2b\xb9\xe2\x3d\x17\x19\x4d\x86\x67\xb8\x4f\x2d\xb0\x38\xc2\x4e\xfb\x8f\x53\x40\x9c\xf5\x59\x4f\xdd\xb8\xbc\xd6\x1f\x74\xcf\x07\x26\xb5\x1c\x65\x1c\xe0\x1e\xb6\x6a\x59\xb4\x55\xf7\xd8\xa7\xd6\x0d\x39\x27\xe0\xc6\xc5\x4b\x13\x8e\x01\x92\x53\x71\xd2\xd9\xd9\x62\xaa\x98\x2f\x5e\x60\x85\x28\x0c\xc0\x5f\x35\x69\x93\x91\x1f\xd2\x03\x9d\xfc\x34\x21\x17\x97\x02\x91\x38\x1d\x82\x02\x7d\xb3\x6c\x79\x91\x00\x05\x7d\x93\x52\xb2\xcd\x87\x9d\x9c\x82\xaf\x73\x4b\x7f\xa2\x97\xd2\x11\x49\xc9\x78\xaa\x5e\x12\x5b\x20\x37\x2a\x9b\x2e\x0e\xd3\x57\x33\x7e\xfa\xea\x13\x91\xf3\xb9\xef\x11\xe3\xe5\x13\x5b\xb7\x0b\xdb\xe3\x2a\x9b\xdb\x7c\x3c\x42\xd5\xd5\x7c\xc8\xda\xb6\x81\x16\x28\xa0\x10\x89\x49\x5c\xb8\xa4\xa7\x6a\x48\x29\x6c\xd8\xdf\xaf\xc0\x05\xad\x49\xd7\x0b\xb1\x9f\xac\xa2\x08\x4a\x1b\x6f\x5e\x48\xd2\x3c\x03\xfb\xcf\x6f\x10\x6d\xb7\x70\xf0\x7c\x33\xe8\xe7\xf4\x75\x7d\xa9\x04\xa4\x4d\xd0\xe7\x38\xf3\xd5\x73\x3a\x32\x93\x75\xce\xd7\x4f\x3c\x42\xbf\xcd\xbb\x91\x01\x00\x45\x5d\x6a\xa7\xd2\xe3\xe3\xaa\xa5\x8a\x82\x96\x30\xd3\x76\xb0\xb4\x66\xdc\x85\xaa\xc4\x8f\xe2\x69\x94\x6a\x7b\xc7\x2d\x91\xeb\x37\xde\xd2\xf4\xa7\x7c\x68\x4b\xe0\x10\x93\xfd\x12\xde\x9d\x9d\x83\x19\x9c\xcc\x50\x95\x9a\x48\xd6\xe9\xa4\x14\x27\x56\x60\x92\xf0\x4a\x0f\x95\xca\x52\x37\x2e\x07\x62\xb9\x66\xce\x62\x32\x05\x5a\x4f\xd7\x57\xc6\x1b\x8b\xad\x83\xba\xef\x91\xa3\xc2\x77\x2f\xb3\x2e\xad\x8f\x59\x1a\xc1\xe0\x2b\xbf\x90\xa7\xf6\xc3\x90\x79\xb8\x6f\xb8\x14\xcc\x24\x2e\x98\x0f\x0b\x8b\x1a\x2c\xec\xb8\xe6\xd4\xe8\xa5\x21\x1b\xf8\xba\xbf\x38\xe8\x29\xab\x98\x83\x60\x8b\xd6\xd5\x9e\xa5\xe8\x36\xa9\xb4\xa4\xfb\xed\xed\x1b\xea\x2f\xfe\x97\x7e\x8c\xf3\x61\x5c\xa4\xa5\x0f\xea\x1f\x05\xf1\xfe\x53\xc8\xea\xc5\x00\x32\x3e\x1f\x52\xa8\x06\x83\x15\x39\x95\x79\x88\xd7\x9a\xcc\x7b\x54\xf7\xd0\x2b\x48\x0c\x46\x9f\xd6\x95\x40\xfe\xa4\xbd\xd6\x8c\xbd\xc6\x8c\xf9\xc7\x87\x2f\xd7\x92\x59\x1b\x01\xe9\xd9\x90\x2d\x8a\x61\x4f\x4c\x21\x82\x3f\x23\x50\x8f\xfd\x49\xff\x21\x8b\xea\x92\x2e\xc1\x41\xef\xf6\x0d\xa1\x77\xcc\xad\x7d\x7b\x9d\x44\x4f\x3b\x03\x45\x81\x15\xf1\x16\xcc\x6e\x37\x62\x5c\x39\xcb\xad\xf0\x93\x62\xf3\x1d\x33\xf4\xc1\x3c\x33\xb6\x29\x20\x07\xf2\xca\xfd\x19\x4f\x62\xc6\x43\xe7\xa2\x55\x71\x56\x4f\xeb\xad\x7d\x33\xe3\x64\xb6\x33\xd0\x08\xb0\x90\xd7\xa0\x91\x35\x8b\xc6\x9c\x56\x7b\x95\x22\xb5\xc1\xcd\x01\x21\x8d\x38\x52\x9a\xeb\xb0\x3d\x9c\x2a\x5e\xb2\x28\x5a\x71\x76\xf9\x8c\x28\x03\x6f\x21\xe1\x9e\x92\xb4\x06\xe9\x48\x95\xfa\x28\x1b\x35\x22\x8f\xbf\x76\xe7\x3e\x17\x58\xaf\x1b\x43\x4a\x4d\xf9\x8e\x8c\xc5\x56\xb9\xd8\x3f\x6b\x0b\x7f\xf5\x2c\x68\x0f\x65\xef\xe4\xe0\x0c\x59\xb4\x6c\xe5\x93\xbf\x98\x89\x98\x05\xd0\x2b\x91\x65\xb7\x42\x98\x49\xe7\x39\x53\x77\x0a\xe3\x93\xe4\xf1\xf9\x7c\xb9\x0c\xd6\x15\x9c\xc9\x39\x52\xae\x8a\x4d\x3d\x56\xa9\xa9\x5d\xf7\xcf\xab\xac\xd4\xd0\x30\xd7\x36\xea\x45\x4d\xfa\x4b\x4a\xed\x1b\xcd\x88\x5d\x2f\xbe\xa5\xff\xa2\xcf\x29\x27\xc1\x37\xc8\x6b\xe4\xfe\x01\x64\x12\x62\x8f\xe7\xa0\xa0\xf0\x2b\x6b\x6a\x9a\x21\x68\x93\x2b\x94\x3f\xf8\xb2\x8d\xd5\x87\xe7\x72\x87\x79\x0a\xaa\xa6\x9a\x98\x50\x6c\x76\x4e\x6f\x5b\xa6\x33\x8c\x09\xf3\x82\xe1\xb9\x87\xd9\x9f\x14\xa3\xe1\x95\x8c\xb6\x2a\xe6\x70\x5a\x57\x7f\x9f\xfc\x67\x30\x64\x01\x12\x87\x41\xa8\xd0\xaf\x03\xc0\xaa\xaf\x6a\xf0\x6b\xd8\x8e\xe4\xb0\xaf\x67\x03\xe0\xea\x60\xb0\x40\x9a\xce\x24\x57\x2f\xb3\x86\xe0\x7e\x9c\x22\xc9\x68\x6b\xdc\x66\xd4\xfc\xf3\xc7\x46\x1d\x38\x33\xa4\xc3\x01\x32\x43\x60\x7d\x4d\x15\x82\x17\x18\x73\x26\xdf\x51\x72\x5a\x6b\xc5\x11\x6e\x99\x0b\xef\x8a\x5a\x95\x79\x60\x02\x07\x20\x6b\xfc\x3a\x6d\xcf\x07\x46\xef\x75\x6f\xd9\x39\xe1\x87\xf6\x68\x75\x07\x16\xc0"}, -{{0x8d,0xa9,0xf5,0x4d,0xa0,0xb6,0xa5,0xa3,0x89,0x85,0xb8,0x8b,0x71,0x33,0x9d,0xc7,0x38,0x4c,0xfd,0x5a,0x60,0xbe,0xe1,0x59,0xc3,0x94,0xc2,0x23,0x63,0xbc,0x7e,0xdd,},{0x1a,0xc1,0xa8,0xed,0xeb,0x21,0x7a,0xe9,0xb3,0xa3,0xde,0x53,0x0d,0x24,0xd8,0x3e,0x11,0xfb,0x65,0x38,0xcc,0x70,0x9b,0x52,0x99,0x4f,0xa9,0xc3,0xf1,0xfa,0xdd,0xc8,},{0xf6,0xdc,0xc2,0xd2,0x7b,0xaf,0x16,0xc4,0xf4,0x81,0x7f,0x87,0x49,0x91,0x57,0xd3,0xac,0x1f,0x84,0xed,0x39,0x8a,0x5e,0x8b,0x0d,0x50,0xf4,0x2e,0xdd,0x73,0x85,0xcf,0x06,0x33,0x7a,0x02,0x36,0x10,0x99,0x70,0xb7,0x9c,0xa0,0x9d,0x7c,0x98,0x31,0xc8,0x76,0xa8,0x02,0x79,0x94,0x21,0xc2,0xab,0xd0,0x75,0x87,0xf5,0xeb,0x66,0x16,0x0f,},"\xbd\x53\xba\xba\x66\x57\xd8\xdb\x8b\xec\xae\x6e\xab\xff\xa5\x2b\x01\x5a\x5a\x05\xfd\xd2\xe0\x70\x64\x7d\xe9\x6f\x9c\xa4\xdd\x21\x9f\xe0\xda\x60\x8f\xa0\x44\x7f\x46\xd1\x7c\x9a\x35\x82\x44\xcd\x54\x08\x59\x65\x82\xcc\xd3\xcd\xd0\x15\x1d\x6f\x09\x23\xe6\x3d\x16\x68\x37\x84\x5f\x27\x3f\xca\x7a\xf6\xc8\x9d\x8d\x52\x46\x17\x5c\x21\x67\xfb\xb9\xc2\xeb\xf6\xa7\x59\x54\x91\xf9\x7a\x97\x13\xb0\x2b\xdf\x41\x3e\x20\x9a\xb2\x2d\xb7\xdd\x2b\x37\xfc\x49\x43\x69\x18\xcc\xeb\xe5\x74\x6b\xc6\x4d\xdd\x6d\xce\x19\xec\x45\x58\xc4\x0e\x08\x96\xe2\x19\x09\x28\x0c\xba\x06\xd1\x6b\x72\xf3\x1d\x98\x76\x85\xd0\x71\xdb\x81\x55\xe9\x9e\xbc\xc6\xc8\x21\xd9\x26\x83\xfd\xce\xe0\x86\x68\xa5\xed\x58\xf8\x39\xd9\xed\xaf\xb9\xf1\x45\x9d\x48\xde\x8e\x1b\xb6\xf7\xce\x84\xda\x0b\xe4\x11\xc8\xf7\xbe\x1b\x9a\x24\xbc\x5d\x0f\xe3\xa9\x6b\x02\x35\x07\x50\xa5\xcb\x25\x0b\x49\x55\x5a\x48\x76\x72\xbd\xff\x3c\x3f\x78\x4e\x3f\xb6\x3c\x1c\x97\xba\x6a\xe4\x3a\x10\xe1\x96\xf1\x88\xdc\xc6\x35\xe2\x14\xe2\x9d\xf5\x09\xe5\x60\x8a\x53\x67\xaa\x28\x00\xc1\xa9\x6a\xd9\x36\xa9\xe2\xa5\x79\xb8\x59\x2e\xc1\x3a\x35\x93\x36\xa6\x27\x88\xc3\xec\x55\xc0\xff\xd6\xa7\xd4\x9e\xcb\x7c\x68\x2e\xfa\x30\x81\x99\xf7\x08\xd7\x9d\x0e\x88\x56\x36\x6d\x26\x9f\xab\x24\xeb\x1a\x07\x5c\x96\xc8\x81\xca\xb8\x97\x08\xce\xd2\x79\x23\x0d\x3f\x1f\x3e\xe1\x73\x67\x22\x83\xeb\x8d\x8a\x82\x40\x38\xf6\x48\xac\x43\x72\x75\xd7\x5a\x0e\x15\xf7\x1c\xe5\x6a\x8a\xeb\x77\x1f\x07\xa7\xf3\x2a\xfc\x9d\x61\x2a\x13\xbd\x83\xb7\xf9\x39\x90\xd3\x8f\xc3\xf4\xf4\xab\x8a\xa9\x43\x0c\x65\x73\x6e\xb6\x4b\x16\x80\x6e\x99\x5c\x1c\xe9\xdc\xf4\xc5\x54\x4e\x7b\x3d\x01\x54\x1c\x57\x21\xbb\x4b\xe4\xcf\x0a\xe3\x82\xa0\xc1\xb1\x69\xd8\xe4\x18\xde\xfd\x55\x94\x42\xac\xea\x14\xb0\x0d\x70\x5b\xcf\xa7\x8b\xe0\x75\x6a\x8f\x37\x7c\xbf\x18\x3b\xf2\x59\x06\x87\x41\x15\xd8\xce\x4c\x3b\xa8\x74\x10\x29\x38\xa4\xea\x16\x03\x6d\x91\xa4\x2c\x5f\x8f\x18\x86\x55\xca\xcb\x00\xc8\x8e\x3a\x68\x50\x88\x16\xe5\xe1\xc3\x1d\x27\x18\x0b\xbb\xa9\x51\x8a\x96\x30\x72\x6d\x7d\x04\x7d\xd8\xd2\xc0\x40\x12\x19\xe1\x4e\x6b\xad\xfc\x9b\x95\xb7\x7a\x6a\xce\x9b\xea\x71\xd1\xb4\x7c\x21\x89\x03\xa1\x15\xad\x02\x9e\x7f\x20\x39\xea\x23\xcf\xd1\xfa\x6a\x44\xd0\x89\xfc\xac\xb6\x78\x15\x3d\x67\x4c\x0e\x08\x17\x64\x99\x55\x95\xcb\x68\x94\x89\x5f\x08\xe2\x5b\x98\x4e\x3a\x69\x4c\x92\xfc\x7c\xbe\x0f\xfc\x46\x97\x23\x0b\xcb\x0c\xa4\x08\xc2\xd7\x08\x5c\x11\xba\xde\xb3\xe6\xc0\xe7\x5e\x6c\x49\x8d\xb1\xbe\xc1\xed\x2a\x3e\x24\x45\xc3\x2b\x19\x13\xa8\x95\x00\xf6\x9e\x7f\x23\xf4\x1d\x62\xe5\xc1\x89\xf3\x9a\x05\x6c\xb9\xfc\x68\xa4\x52\x02\x3a\x33\x3f\x75\x22\x0c\xb9\xb9\x44\x84\xac\xac\x6b\xbc\x67\x1f\x59\xff\xa0\x72\xb7\x1a\x18\x96\xa1\xb3\x06\xe9\xdc\x55\x8d\xa0\xec\x20\xf3\x73\xe4\xc3\x55\xe0\xc5\xec\xcb\xbf\x13\x50\xc8\xc0\x79\x14\x89\x2c\x45\x4d\xef\xce\xfb\x71\x7b\xe3\x4d\x08\x7a\xeb\x24\x4a\x86\xff\x49\xa6\xc4\x70\xaf\xb3\x6b\x40\xfe\x8b\x71\xc5\x05\xa4\xff\x7a\xf2\x98\x4c\x65\x28\x49\x38\xec\x0e\x40\x52\x31\x52\x1f\x48\x10\x14\x7d\xc4\xe3\x73\xfd\xab\x66\x47\xb8\x6f\x79\x82\x75\x02\xfd\x08\x7e\x27\xf3\x10\xd6\xb3\x12\x36\x31\x13\x84\x21\x55\xc5\x7a\x32\xba\x03\xb6\xcf\xf9\x65\x53\x0b\xd7\x95\xfc\x29\x2e\x24\x1c\x9b\x6c\xa0\x85\x14\x00\x32\xef\xe7\x46\xf3\x7d\x57\xe9\x58\x42\x11\x84\xb8\xa4\xc1\xa6\xa1\xe3\x7d\x45\xe0\x77\x31\x98\x33\x06\x8d\xdc\xb8\x9d\x38\xc7\x5b\xeb\xa1\xa6\xe8\xe4\x05\x28\x88\xec\x18\x16\x2d\xd6\xff\x0c\x59\xa2\xfd\x0b\x47\xf3\x11\x91\x95\x68\x0f\xfc\xcd\xdf\x5f\x76\xb3\x5f\x02\x2a\xa6\x6b\xd1\xac\x56\xf1\xae\x33\x3e\x9b\x9d\x04\x6f\x0b\x79\xa8\x92\xec\xc4\xf8\xd2\xf3\x1e\x17\x53\x6c\x4c\x62\xa9\xb5\xe0\x63\xdd\x2d\xce\x37\xd3\xd0\xac\xb4\x20\x23\xeb\x2f\x2e\xa3\x29\xd3\x87\x6c\x23\x86\xa0\x22\x76\xff\xf9\xd3\x08\xab\xba\xdb\x72\x74\x30\x1a\x69\x62\xec\xae\xeb\x20\xbe\xf5\xe3\x6a\xff\xfc\x38\x7c\xa8\xe1\x85\xe5\x62\xb8\x65\xb4\x92\x04\xc1\x7b\x2a\x70\x11\x9b\x06\x1c\x29\xc0\xfe\x90\x04"}, -{{0x7a,0x2e,0xfd,0x39,0x01,0x24,0xd3,0xfb,0xef,0xc5,0x4a,0x57,0x71,0x06,0xe7,0x4b,0x2d,0x1f,0x5d,0xd5,0x04,0xc0,0x50,0xd0,0xd3,0x59,0xe5,0x3c,0x0f,0x5c,0x87,0x2b,},{0xef,0xc3,0x03,0xd9,0x22,0xe8,0x8f,0x70,0xf3,0x8c,0x1a,0x2b,0x92,0x06,0x84,0xef,0x66,0x30,0x34,0xa1,0xb2,0x3a,0xb9,0xd6,0x9b,0x6c,0xe8,0xed,0x87,0x06,0xf7,0xf7,},{0xc2,0x8b,0x34,0x80,0x48,0x05,0xd8,0x1f,0x7a,0xef,0x78,0x49,0x70,0x67,0x0e,0xda,0xa4,0x17,0x23,0x2b,0xcc,0x67,0xda,0x9b,0x51,0xe9,0xc3,0xd7,0x4f,0xc4,0x99,0x1b,0xde,0x97,0xa0,0x6b,0xd5,0x3f,0xa0,0x0b,0xb4,0x40,0xfd,0x56,0x16,0xcd,0x0d,0xe6,0xe9,0xb0,0xd1,0x9f,0x2f,0x68,0xbf,0xaf,0x9d,0x4c,0x51,0x72,0xc4,0xe5,0x20,0x0a,},"\x23\x8f\xbe\x9f\xb3\x5c\x72\x5c\x6c\x1f\x32\x92\x48\x09\x4b\xc7\xda\x1b\x27\x3e\xdc\x76\x99\xa7\xe3\x45\x2b\x57\x88\xd8\x78\x67\xde\xfc\x40\xa0\x05\x90\xe8\x75\x80\xd2\xc0\x27\x5d\xf5\xab\xcc\xe0\xe1\xaa\xa1\x82\x90\xbf\x93\xb4\x4e\x5a\xd9\xd7\x60\xdd\x21\xf1\xaa\xca\x38\x31\x78\xf9\xff\xf9\x13\x0f\x73\x18\x7b\xa9\xd3\x1e\xa3\x60\x4a\x1c\xdf\x39\x11\xe1\x43\x77\xa0\xce\x8b\x44\x18\x9a\xda\xa7\xaa\xc2\x3b\x6c\xdc\x7a\x42\x5b\x7e\xa7\x45\x50\x84\x55\x70\x4f\x9a\xd7\xa8\x95\x27\x18\xc3\x98\xb4\x21\xb6\xe0\x9c\xb7\x8c\xb5\x2a\x18\x14\xee\x2e\x96\x39\xec\x68\xd3\x61\xf0\xa3\x20\x41\xd6\xe7\x42\x5b\x4b\xb3\x3c\x70\x19\x6e\x24\x00\xeb\x81\x2d\xb8\x50\x6c\x9f\x32\x45\xbd\x98\x8f\xbc\x89\x1b\xe2\x0c\xb0\x69\x15\x59\xfc\x91\x6b\x57\xff\x96\xc9\xb1\x44\x89\xe0\x99\x3c\xb7\x39\xa3\x9d\xa2\x46\xd0\x1a\x6e\xbd\x07\x58\x35\x81\xf2\x50\xbf\x48\x0b\xc4\x4b\x2c\x33\x91\x54\x2d\x59\x5e\x4d\x39\x94\x90\x19\x5f\x84\x45\xdf\x63\x8f\x34\x69\x8f\x1a\x96\xed\x27\xb3\x53\x3e\x3e\xb6\x7e\x8f\x86\x58\x65\xfa\x95\x55\xed\x34\xdf\x11\x15\x76\x41\xa0\x0e\x6d\x60\xcf\x62\x3f\xec\x1a\x92\xb8\x7a\x15\xd7\x65\x18\x5f\xd9\x05\x5a\xcb\x38\xd7\x5c\x99\xdb\x4f\xce\x7b\x0e\x39\xfd\xc3\xf8\x51\xda\xf6\x5c\x7a\x33\xf4\x64\x81\x69\x31\x83\x9f\xef\xe8\xe5\x8d\x9a\xb7\x42\xb8\x61\x87\x3f\xd2\x29\x18\x9e\x59\xcd\x4c\xe8\x23\x9f\xc9\x54\x3f\x53\x9d\x2d\x29\x61\x14\x26\x6e\xa8\xc6\xfd\x15\x2a\xc6\xb3\x42\xe5\xd1\xa5\x57\xab\x35\xca\xc5\x1e\x2d\x12\x12\xee\x31\x7c\x4d\x26\x71\x68\x29\xe2\x57\x46\xdf\x17\xd2\xa6\x22\xc2\x43\xf3\xec\xbb\x65\xf5\x7a\xb0\xf4\x27\x0e\x3d\x06\x68\xa9\x62\x50\x22\x45\xb9\x4c\x06\xdf\x0c\x5e\x39\xe3\x53\xaa\x84\x2e\xa0\x80\xcf\x50\x27\x08\xb1\xdd\xa2\xd0\x01\x82\x4d\xe4\x58\xd3\x77\x62\xaf\x2c\xdf\xd5\xa6\xd3\xf3\x5e\x08\xa1\x8e\x14\xaa\x7a\x64\x2c\x51\xe4\x04\x7e\x63\x75\x17\x84\x6d\xf6\x46\xd0\x73\x36\xfb\x17\x24\x34\xe0\x88\x3e\x2b\x77\xd8\xed\x1c\x52\xc9\xcc\x63\x6a\x56\xa1\x9e\x57\xa5\xf1\x61\xb9\x2d\x1d\xcb\xfa\x49\x6f\x34\x4a\xe6\xd4\xdf\xdc\x95\x69\xad\xe4\x57\xa4\x90\x91\x36\x2e\x5a\x0c\xdd\x81\xb3\x75\x32\x43\xfd\xac\x30\xa2\xd2\x7e\xa0\x26\xa5\xe6\x01\x44\x1e\xcd\x55\x37\xa7\x20\x1b\xdc\xb7\xfd\x58\xb2\x40\xd0\x22\x9f\xdd\x9b\xab\xf1\x12\xb5\x69\x48\x12\x25\x0e\x76\x8d\x7c\x0c\xe6\xca\x56\x5a\xd0\x6a\xb8\xf7\x8a\x5c\x99\x50\xee\xf5\x38\x72\x6f\x57\x6c\x4b\xd2\xe0\x75\x5c\x7f\x98\x39\x29\x37\x2a\x5f\xe1\x1c\x73\xf9\xe1\xfa\x45\x3a\xb5\x4b\x58\x17\xaa\xd3\x59\x67\x56\x12\x7d\x84\xe3\x11\x94\x53\xe8\x82\x5b\xb8\x46\x0d\x85\x1f\x1f\x7e\x4a\x28\x38\xa2\xbe\x78\x6b\x23\x35\x04\xa6\x91\xdb\x0f\xa2\x2a\x5f\x41\xfe\x3f\xd3\xc9\xb5\x38\xb0\x4f\x40\x9e\x09\x18\x09\x48\x6b\x28\xad\x0d\xed\xa7\xb3\x8a\x42\xce\xfc\x48\xde\x7d\x86\x79\xc0\x3b\xf8\x77\x23\x85\x11\x82\x0d\x07\x70\xcc\x8d\x7b\x41\x72\x37\x78\x23\xa0\xb9\x91\x49\xab\xb8\x91\x8b\xfb\x66\xd5\xab\xfc\xd1\x00\x60\xb0\x5c\xb4\xf2\x39\xdd\x42\x81\xd9\x34\x83\x50\x4b\x73\x1e\xaf\x5a\xdd\x51\x5f\x1f\x3c\x3b\x52\xb4\xe3\xbd\xaf\x97\x6a\x17\xb3\xc9\xec\x61\xbf\xc8\xe7\x71\x16\x71\x58\x04\x53\x2c\xf2\xdb\xf2\x0b\x7b\xa5\xea\xd8\x5a\xfb\x95\x2b\xee\xc2\xfc\xcf\xf8\x5f\xf5\x07\x2b\xa4\xed\x6b\x54\x38\xab\x15\x20\xc6\xef\x4b\x0b\x26\xf1\x2e\x84\xae\xdd\x65\xce\x5c\x7b\xbe\x6a\xcb\x67\x72\xf5\x93\xa6\xb4\xf8\x1d\xdd\x9d\x50\x27\x46\x50\x50\x47\xc8\x12\xa0\x06\x7a\xfc\xeb\x8d\xc9\xbf\xf3\x0d\x40\x87\xf8\xd5\xa3\x75\xec\xa6\x05\xa0\x62\x27\x84\xd8\xfe\xa2\x78\xcd\x1a\x52\x41\xad\x4b\x3f\x1b\x91\x4f\x74\xf7\x3b\xc3\x6e\xe7\xcc\x82\xd9\x6e\xfd\xa6\x3a\x3b\x67\x99\x73\x0f\x20\x65\x6c\x12\x35\x6c\x79\x06\x9b\x2b\xe6\xf9\xb7\x7b\xe1\x01\x98\x31\x18\x82\x3e\xa6\x6e\x7c\x20\x98\xfb\xc7\x2f\xc9\xc0\x39\xdf\xe3\x0f\x2d\xab\xa1\x3c\x3b\xde\xfb\x8a\x78\x0b\xeb\x5c\xb1\xb6\xc2\x86\xa6\xb3\xef\x48\xfd\x15\xc6\x6c\x04\x5b\xa2\x9f\x09\x70\x41\x3b\x98\x8d\x0e\xa0\x04\xab\x84\xc9\x39\x19\xf0\x4f\x9b\xf8\xca\xf5\x8c\x4e\xb4\x78\xf3\x58\xef\x8b\x68"}, -{{0xef,0x36,0x48,0xcb,0xe7,0x34,0x02,0xab,0x45,0x0c,0xd6,0xec,0x37,0xe5,0x45,0xd0,0xcd,0x2c,0x99,0x9e,0xcc,0x1f,0xa3,0x81,0xa4,0x5c,0x66,0x0e,0x18,0x53,0x30,0x32,},{0x52,0xa1,0xa4,0x52,0x73,0x87,0x26,0x76,0x58,0x2c,0xc7,0x67,0x33,0x99,0x26,0x41,0x4c,0xd5,0xd0,0x3d,0x98,0x0c,0xf6,0x29,0xdd,0xa2,0xd1,0xa2,0x05,0xe9,0x83,0x0a,},{0xf6,0x70,0x79,0x29,0x42,0xec,0x41,0x44,0x28,0x47,0x56,0x38,0x85,0x3c,0x42,0x72,0x8e,0x86,0xba,0x12,0xbb,0xe8,0x59,0x48,0xb3,0x91,0x34,0xcf,0x6e,0x2b,0xd1,0x28,0x13,0xe0,0xd8,0x3e,0x51,0xe6,0x57,0xc9,0x01,0x07,0xad,0x93,0xa4,0x78,0x8a,0xa3,0x83,0x13,0xfa,0x96,0x2f,0x67,0x67,0xa8,0xf7,0x80,0x5b,0xde,0x65,0xca,0x42,0x0d,},"\x6a\x93\x37\x8f\x88\x0c\xf0\xff\xdb\x8e\x07\xd6\x83\xcc\x35\x2e\x2a\x10\x33\xc4\x50\xba\xa0\xe8\xc4\xe1\x62\x05\xfd\x0c\x02\x74\x3b\x0e\xa0\x64\x97\x1d\x91\x1e\x49\x47\x13\xe6\xd9\x4a\x02\x17\x2e\xd0\x14\xd5\x06\x59\x2e\xc6\xc7\x0a\x9c\x97\x85\x52\x46\xbf\x3d\x26\xf3\xcf\x74\xf4\x93\xc1\xb6\x97\xa0\xc4\x14\x16\x0c\x34\x14\x12\x83\x09\x85\x43\x08\x06\xa0\xcb\x3c\x84\x75\xe7\xe5\xa9\x73\x68\x6c\x24\xd5\xef\x1b\xe7\xd0\x06\x50\x96\xfe\xb5\x2e\xab\x26\x0b\x5c\x48\x8a\xf0\x92\x70\xde\x6d\xec\xd3\x3f\xea\x85\x89\xdd\x10\x21\xba\xf4\x1e\x3f\x25\x5f\xb8\xfa\x19\x16\xeb\xd8\x53\x1e\xeb\x2f\x88\x6b\xb3\xb3\xb0\x4f\x9a\xf6\xb2\x76\xc3\x59\x23\xf1\x0d\x3a\x0a\xf1\xe3\xf5\x8b\x0d\x15\xae\xd1\x65\x04\x5f\x20\x6f\x3f\x43\x0a\xbd\xff\x09\x44\x90\x97\xe4\xb2\x6d\x00\xa8\xf9\xf1\xe8\xf7\xa1\x9f\x38\x58\x81\x24\xc3\x28\xec\x43\xa9\xcf\xb4\x3d\x3b\x2c\x6b\xdf\x6a\x3c\x1a\x10\x2e\x0e\x33\x3d\xe1\xac\x21\x4a\x6d\xf7\x6d\xab\x44\xba\x76\xbf\x03\x52\x73\xb7\xff\x62\x38\xec\x82\x48\x3b\x2d\x2d\x9d\x54\x29\x1a\x72\x27\x0f\x88\x93\x3b\x78\x6c\xac\x05\x1d\x99\x0b\x3c\xf7\x40\x84\x5f\xed\x3a\x67\x86\x7d\x7c\x7c\x05\x67\x4e\x7c\xb0\x2c\xa5\xb7\xac\xdf\xba\x38\x52\x80\x3a\x3d\x56\xc4\xd5\xc1\x3b\xb1\xd7\x72\x34\x67\x74\x1e\xac\x1f\x2a\x7a\xcd\x3a\x95\xf3\xa5\x16\x10\xa4\x86\xfc\x53\xa9\x85\x16\x28\xc5\x57\xd3\x6d\x8a\x4c\xd3\x7a\xae\x9c\x41\x74\xdb\xbd\xb6\xbd\x88\x5c\xf4\x0b\x38\x2b\x8d\xed\x24\xa4\x52\x2a\x27\x8f\xef\x76\xc4\x53\x19\x06\x7e\x55\x28\x6e\x7b\x08\xc6\x03\x48\x6e\x38\xa0\xac\xf4\x7e\xde\xf8\x48\xec\xbe\x94\x2e\xce\xad\xb8\x63\x6c\x83\x3f\xeb\x88\x2a\x51\xa4\x59\x5e\x24\xf6\x07\xca\x3c\x9d\xa1\xb2\x40\x4c\xe5\xc7\x47\xe0\x62\x64\x17\x4d\x64\x50\x43\x31\x70\x9b\xef\x30\x05\x5a\x5d\x69\x5e\x09\x53\x7c\x8f\x8c\x1e\x5a\x3a\x5d\xb0\x65\x99\xe3\x19\xdf\xdb\x28\x72\x96\x65\x27\x3b\xf8\x68\x95\x5e\xa5\x64\x27\xf0\x8b\xac\xd7\x77\xf1\x79\xb3\x02\xf3\xf6\x8d\x04\xf3\xf3\x88\x3d\x34\x49\x55\xb6\x55\xdd\xc6\xd5\x28\x2b\x6d\x4d\xf1\xd8\x36\x30\x21\x0e\x69\x91\x78\xe1\x1f\x72\x2e\x9e\x5c\xda\x67\x28\x92\xae\x9b\x23\xe8\x16\x9c\xbb\x54\x80\x93\xb8\x3e\x64\x3e\xb4\x99\xd9\x37\xd2\x8f\x38\x11\x59\x7b\x64\x84\x10\x2f\x0c\x8e\xb8\xc8\x88\x8c\xda\xc2\x29\xae\xbf\x89\x08\x6a\x64\x95\xac\x55\x1f\x3b\xbd\xf2\xd1\xc9\xa9\x3e\xd1\xd3\xa8\x61\xee\xcd\x9e\xb8\x39\x94\x9b\xfb\xe6\xa4\xf6\xe6\x48\x6e\xde\xda\xb5\x22\x9d\x53\x2b\x58\x97\x6d\x67\x51\x2f\x9f\x71\xae\x79\xb4\x14\x5c\xa2\xfa\x49\x7a\x16\x5f\x11\x07\x17\x66\x6c\xa3\x34\x0b\xbd\xa8\xdf\x1f\x82\xb8\xc0\x54\xcf\x76\x54\xc3\x56\x90\x16\x8f\x96\x27\x7d\x41\xc1\xc2\x36\xb6\x81\x98\x17\x3c\x6e\x2b\x0a\x20\x8e\xf8\x3c\x02\xa4\x3e\x47\x3d\x90\x68\x6a\xce\x75\xb5\xbd\x32\x1b\x3f\x54\x28\x13\x27\xa6\x73\xca\xd4\xd4\xad\x30\x40\xd4\x8c\xf4\x93\xea\x23\x1b\x3f\xec\x06\xf3\x99\x32\xd7\xf7\x0a\x38\x42\x8d\xf8\xfe\xe4\x37\x05\x32\xae\x5f\xb1\x12\x05\x9f\x0a\x1d\x4f\xbe\x11\xb5\xa2\x3b\xb8\x76\x35\x42\x9e\xd3\x3a\xd1\xf6\x14\x80\x14\xcb\xc1\x60\xd9\x3c\xa2\x59\x20\x53\xa6\xe9\x53\x78\xd6\xcd\x3f\x50\xdb\x52\xbe\x92\x8e\x40\x92\xfe\x5d\x2b\x70\x95\xa9\x56\x68\x64\xad\xfd\xa5\x9f\xd5\xf2\xfb\x62\x54\xbd\x59\x17\xb7\x0f\xa1\x46\x99\x66\x5a\x37\x29\x7c\x98\x3c\x1b\xb9\xef\xe1\xc6\x7b\x41\x3d\xd1\xa8\x53\x0c\xbf\x22\x72\x97\xa8\xbb\xf9\x3a\x8a\x02\x45\x4e\x8e\x46\x1a\xc2\x12\xb8\x46\xa7\x0d\x5d\x56\xd6\xc3\xa6\xe6\x5a\x03\xbe\x05\x80\x21\x9b\xdd\xec\x88\xd4\x03\x89\x11\xfd\x95\x74\x56\x3f\x33\xe0\xf9\xe6\x04\x46\x88\xd3\xdd\x48\xfa\xc7\x03\x86\x9a\xa0\x9d\x96\xef\xee\x7d\x6c\x68\x07\x1d\x99\x22\xd5\xe8\xed\x8d\xc4\x0f\x1b\x79\x8f\x1c\x58\x0f\x78\x59\xcb\x84\xf1\xe1\x4b\x5e\x74\xdd\xea\x16\xad\x5c\xbe\xea\x4c\x48\xfb\xcf\xfd\x29\x53\x1a\xcc\xc0\x63\x39\x38\xe3\xbc\xb2\x21\x26\x76\xb6\x1e\xf9\x01\xe9\xc8\x31\xa4\x17\x74\xd8\x31\x7e\xf3\x5a\xf7\x69\x90\xbd\x24\x93\x1f\xde\x6d\x40\x7e\x22\xe7\x63\xcf\x6a\x57\x90\xb2\x37\x61\x90\x8e\xee\x60\x96\x37\xa2\xc1\x10\x59"}, -{{0x2c,0x8e,0xe7,0xfa,0x9b,0xa2,0x8c,0xe7,0x04,0x96,0x76,0x08,0x7b,0x11,0x63,0xb2,0x41,0x11,0x8d,0x34,0xcd,0xf5,0x34,0xae,0xbe,0x8b,0xa5,0x92,0x82,0xa6,0x2a,0xc2,},{0x24,0x4c,0x24,0xf5,0xec,0xb2,0xdd,0x1d,0x14,0x63,0x51,0x22,0x21,0x32,0x5d,0x73,0xc8,0x1e,0xe4,0xd8,0xad,0xb8,0xe0,0x1e,0x23,0x34,0x5c,0xaf,0x9c,0xa5,0x35,0x3b,},{0xca,0x0b,0xb6,0xc1,0x23,0x56,0x55,0x5f,0x6e,0x1d,0x8f,0x5c,0x8a,0xa7,0xb5,0xe8,0x0c,0xd2,0x80,0xe8,0xb1,0xb9,0xba,0x2e,0xc9,0x55,0x0f,0x62,0x2f,0x48,0x2c,0x3a,0x9a,0xd3,0xbe,0x03,0xa4,0xc9,0xdf,0xc1,0x0d,0x01,0x12,0xb0,0x18,0x9d,0xe9,0x4b,0xff,0xaf,0xd7,0x03,0x41,0x14,0xe0,0xe0,0xd4,0x2c,0x23,0xf3,0x2d,0xc8,0x18,0x07,},"\x07\x66\x9a\x89\x64\xf0\x63\x80\xd2\xd4\x98\x2c\xb6\x34\x9d\xe5\x50\xb3\x8c\xbc\x35\xdb\x2c\xe5\x72\xde\x88\x7f\x66\x30\x55\x73\x6f\xaa\xc7\xec\x07\xc3\x2d\xf6\x0e\xe2\x59\x84\x22\xbf\x37\xe7\xcf\x31\x9a\xb3\xc9\x05\x56\x08\xca\x0c\x49\x75\x7d\x76\x88\xe2\x01\x3b\x82\x44\xf3\x54\x04\xf4\x5a\xc2\x19\x49\x7f\xe9\x24\xde\x93\xa5\x8d\x0f\x72\x1a\xed\x78\x25\xf6\x3b\x26\x67\x07\x7c\x16\x1e\xb4\xdd\x8b\xf7\xdd\xbd\xbb\xc1\x9a\x9e\xae\x59\x78\x97\x8d\x5a\xeb\x33\xa0\x6d\xde\x18\xe6\x12\xe0\x5b\xdb\xca\xe0\x16\x1a\xa2\x38\x90\x38\x02\x64\x29\x96\x0d\xda\x3a\xa1\x7e\x96\x7d\x10\x77\x3c\xa4\x97\x35\xd8\xec\xd7\x40\x9b\xe1\x65\xc0\x9b\xb0\xb5\x09\x69\x1d\x59\x1c\x18\x5c\x93\xcd\xee\xae\x95\x35\x23\x16\x54\x46\x80\x52\x38\x21\x45\x8c\xac\xcf\x52\x8a\xc0\x45\x4e\x4c\xdd\xc6\xdf\x0d\x1e\xa5\xf1\xf5\xcc\x1e\xee\xe0\x5e\x19\xa2\xad\x0b\x6a\x49\x73\x6e\xd8\x55\x23\x36\xfc\xfc\xad\xbd\x93\x1b\x0b\x8e\x96\x3b\xe0\x5c\x8e\x70\x37\x38\x85\x52\x51\x2b\x68\x23\x58\x3e\x4a\x14\x38\x4c\xef\x50\x29\x23\x2d\x3e\x0b\xaf\xe4\x66\x35\x1b\x4b\xb3\xf5\x67\x54\x5a\xb4\x1f\xa4\x6b\xff\xaf\xa8\x77\xa1\x2b\x38\xa2\x7a\xbd\x64\xf7\x7f\xbb\x4d\xb4\x66\xff\x7f\x70\x65\x04\x14\x1d\x3a\xdd\x0d\x73\x72\xf1\x6f\xe3\xd8\xc6\x9f\x62\x99\xd9\x39\x66\xd6\x24\xa3\x07\x0e\xad\xb8\xb4\x9f\x29\xfa\xb4\x84\x4c\x75\x28\xa2\xa4\x0b\x66\x98\x70\x60\x69\x5c\xaa\x66\xb8\x67\x18\xc5\x10\x49\xac\xf4\xcf\xad\x38\x53\xed\xb4\x92\xe3\x68\xcb\xd0\x73\x96\x8e\xca\xa4\xa1\xee\x60\x46\xb5\xe8\x26\xe9\x01\xf4\xa8\x08\xc0\x42\x7c\x02\x6f\xe2\xf7\xb2\xe1\x96\x86\x67\xb5\x3a\x7d\x36\xd7\x02\xf2\xff\x82\xc6\x42\xd3\x49\x19\xf8\xe9\xaa\xaf\xe4\x62\xa3\xd4\xf9\x26\x92\xde\xac\x75\x2b\xe3\x48\xf5\x4c\xf0\x89\xdd\x9c\xd0\x51\x84\x6b\x04\xb7\x19\x31\xe1\x9e\x89\xd1\x25\x86\x4b\xfa\x89\x48\xac\xe0\xef\xf3\x3c\x45\x11\x05\x69\xa0\xdf\x37\x53\xf4\xc5\x8d\x80\x02\xb5\xbc\x38\x10\x2e\xc2\xec\xf6\x95\xfa\xfa\x89\x16\xda\x90\x02\x38\x7e\x44\xf9\x6d\xab\xf8\xa9\x82\xc5\x3c\x9b\xad\xbc\x37\xbd\xe4\x37\xf1\x46\xf7\x7d\x8f\x7b\xaf\x12\x87\x31\x96\xb0\xc3\x61\x93\xaf\x55\xf5\x42\xd9\x96\x8a\xed\x80\x69\xab\x9f\xbc\xd6\x81\x4e\xc4\x72\x79\x9a\xd0\x9c\x73\x0d\x41\xed\xde\xca\x3b\x62\x69\xd3\x1a\xb5\x23\xb5\x95\x47\x07\x73\x76\x34\x5b\x05\xf2\xae\x69\xb4\xee\x72\x8c\x86\x3d\x1b\xc0\x4e\x9b\x7d\x3d\x0f\xcc\xeb\x35\x9c\xbd\x08\x58\x59\x7a\xf2\xd6\x06\x3e\x25\x3f\xae\x2c\x3f\x25\x03\x4c\x33\xed\x59\xed\xd2\x78\x28\x68\x29\x86\x81\xca\xf5\x64\xdb\x8d\x19\x36\x6f\x34\xea\xe8\x5b\xa7\x3c\x1e\x23\x89\xb0\xdd\x78\xa9\xd2\xca\xa0\xf2\x3c\x9a\xd5\xf6\xcd\x9f\x2c\x4a\xd5\xd5\x89\x46\xad\xb7\x18\xcb\x83\xda\x58\xe2\xfc\xbb\x60\x25\xbe\xf4\x66\x0a\x83\xe0\xaf\x55\xe2\x03\x08\x02\x93\x2f\x2a\x89\x6a\x09\x60\x79\xb7\x54\xc9\x9f\x7b\x64\x23\xb4\x5a\x86\x47\x2e\x67\x23\xef\x88\x96\xc4\x32\x4c\x73\xd3\x4a\xd5\x8a\x4c\x01\xb3\x8a\x97\xc7\x3b\xe5\xaa\x7f\x74\xa2\xfa\x4d\x07\x95\xaf\x6d\xbf\xcd\x6d\x4e\xb4\x42\xa7\xe2\x04\xdb\x4e\xcb\x1f\x8a\x22\x6b\xdf\xa2\x1b\x6e\xb1\x71\xc9\xe5\x9f\x1a\x19\x2e\x23\xa7\x6c\x35\x2b\x04\xd8\xa8\x02\x33\x98\x5b\x77\xa2\x9c\x02\x01\x19\xce\x65\x1c\x7f\x41\x83\xd0\xe9\xc1\x9f\xe1\x8a\xa1\x02\x0c\x25\xe4\x58\x9d\xee\x34\xb9\x01\xbd\xaf\x9f\xf9\x45\x0c\x91\xaf\x3c\x1d\xb6\x70\xb4\x77\xe0\xac\x21\x07\x69\x6c\x9e\xc0\xd3\x1d\x82\x64\x7b\x68\xea\x19\x49\x9f\xe3\x4a\x8e\x2e\x7b\x37\x8d\xc7\xe7\x54\x24\xe8\xc4\x56\x45\xb0\xc2\x81\x8e\x9f\x88\x5a\x1c\x58\x41\x5b\xba\x1c\x3f\x2a\x77\x54\x9b\xdc\x46\x80\xdb\xcd\x16\x50\xc7\x5d\x0f\x45\x2a\x6b\x20\x85\x91\xdf\x0f\xa6\xe1\x81\xda\x2a\xbf\xab\x44\x46\x21\xd5\xf7\x7c\x2c\xd7\x95\x56\x46\x72\x46\x44\x7a\x89\xf0\xaa\xac\xad\x66\x0c\x9a\x92\x5e\xba\xfb\xad\x43\xc4\x78\xa3\xc8\x50\xa2\x7e\x01\x01\x9d\x88\xa5\xb1\xdc\x81\xb5\xd2\xe9\xf7\x40\xa0\x28\xcc\xb7\x2c\x1a\xcf\x89\x7e\xa5\xad\x89\xe0\xf9\x44\x88\x88\xd5\xb1\x5c\xe6\xe4\x29\x77\xf7\xa7\x29\x15\x5a\x28\x4d\x11\x87\x58\xac\x65\xf3\xfb\xb9\x8d\xeb\x65"}, -{{0xdd,0xd8,0xe9,0xff,0x85,0x56,0x79,0x89,0x6a,0x13,0x97,0xb4,0x27,0xdb,0x85,0x43,0xab,0xe8,0xbb,0x5d,0xd1,0x22,0xe3,0xe3,0x02,0xcc,0xfc,0xe5,0xfd,0xc6,0x3e,0x12,},{0x5a,0x9a,0x31,0x2e,0x89,0x2a,0x10,0xb9,0x8d,0x0d,0xcd,0xd2,0x8d,0xb3,0x48,0x1c,0x3c,0x28,0xad,0xd5,0xad,0x0b,0x19,0x46,0x16,0xda,0x4a,0x3d,0xf7,0x66,0x01,0x09,},{0xdf,0x84,0x9b,0x7b,0xd2,0x97,0x45,0xf8,0xbe,0xcd,0xdd,0xf6,0xc9,0xba,0xf0,0x94,0xd7,0xa9,0x8c,0xc9,0x33,0x8c,0x34,0x4e,0xca,0x17,0xfd,0xe0,0x75,0xfd,0xa8,0xd1,0x54,0x32,0x99,0xf6,0x25,0x98,0x23,0x17,0xdb,0x7b,0x3c,0x77,0x3b,0x64,0xf7,0xd1,0xf2,0x86,0x92,0xac,0x45,0x3b,0x81,0xd7,0xec,0x7b,0x7e,0xc3,0x41,0x7a,0xce,0x04,},"\x5e\x8f\xee\xc5\x09\x35\x0d\x2e\xe7\x95\x5b\x6f\x3e\x27\x82\x78\xa4\xcb\x48\xae\x72\xb4\x65\x89\xe4\x78\xbe\x59\x74\x7d\xf5\x39\x4a\x16\x9f\x19\xe1\x0d\xb5\x32\x02\xa6\xa5\x23\x20\xb6\x3a\x9a\x2b\x72\x3f\xd3\x1a\xa2\xdb\x6d\x58\xc5\x73\x32\xda\x31\x78\xbc\xf9\x66\xc5\x3a\xbd\xa3\x5f\x12\xda\xef\x9e\xdc\xf3\x99\xe4\xa8\xc5\xf8\x3d\x36\xf4\x4a\x17\xd7\x98\x46\xbf\xc9\x6c\xe6\x90\x19\x4c\x21\x9a\x29\x89\x2f\x03\x67\xa7\xab\x38\x44\x83\x78\x79\xe3\x81\x8d\xb8\xd7\x0c\x4e\x3f\xba\x4d\x28\x07\x34\x64\xdf\x20\x85\x95\x10\x38\xfe\xa4\x32\x81\xb6\xb6\x06\xdc\x88\x46\xb3\x0b\x07\x63\xf2\xca\x82\xbd\x50\x21\xf9\x11\x70\x35\xa7\x7b\xcd\x10\x75\x47\x7c\x5f\x43\x21\x43\x34\xd4\xd4\xce\xdd\x18\xf7\x38\xd6\x76\xc7\xb5\x1a\x18\x5f\xfa\x8d\x04\x10\x11\x86\xa4\x95\x2b\xbd\x87\x22\xf5\x39\x90\xb6\x06\x37\x04\x1e\x11\x4a\xeb\x8c\xe7\x11\x11\x31\xd4\xdb\x3f\xb4\xd3\x5d\x99\x5a\xd8\xd6\x65\x0c\x0c\x4c\xcd\xce\x9d\xcc\x39\xdb\x18\x8a\x68\x78\x55\x62\x74\x06\x26\xb3\xae\x3e\x02\x3f\x40\x77\x2d\xed\x87\x6a\x45\xcb\xef\x74\xa0\x58\xfd\x78\xc1\xa1\xff\x2c\x24\x51\xe1\x11\xac\x1b\x4b\x7e\xe4\xc8\x1c\xd7\x63\x10\xd4\xd2\x98\xfb\x3c\x49\xf5\xe6\x40\x19\x08\xa6\x30\xfa\x85\xdb\x74\x71\x80\x4f\xe9\x90\x84\x7f\x0f\x75\x94\x72\xf5\x93\xdc\xf0\x2e\x11\x3e\x15\xe5\x64\xd3\x0d\x59\x84\x69\x2d\xa5\x5b\x0b\x7f\x22\x19\xc4\xac\x16\x26\x51\x1a\xcf\x19\x4d\xc7\x02\x6e\xb9\xd3\x67\xa4\xa2\xf1\xdf\xb5\x15\xcb\x2c\x08\xda\x4f\xe5\x95\xc8\x58\x11\x12\x0c\xba\x2a\xe7\xb6\x6e\x67\xc9\x1f\xb8\xfb\xcb\x9d\x99\xf1\x3e\x50\xfd\x67\x46\x4d\x90\xc8\xdc\xf6\x93\x55\x23\xcf\x6d\x13\xfd\xd1\x06\x35\xb9\x23\x2b\x7a\x61\xdc\xec\x9a\x2b\x92\x10\x61\x41\x0d\xf1\xde\x6a\x45\x16\x7f\xb9\xf6\xf1\x09\xdc\xc0\x88\x91\xf2\x03\xb2\x74\xa3\xb6\x82\x71\xb3\xf3\x5e\x74\xf9\x4b\xdc\xed\x0c\x5f\xf8\x63\x71\x73\xa1\x76\xe7\xda\xcc\x81\xf2\xcd\xc4\xfb\x0d\x52\xd1\xdf\xa7\xf2\x7b\x55\x2f\xd8\xd8\x7a\x1c\x55\xd6\x94\x7f\xd9\x2e\xd3\x25\x3f\x95\x94\xdb\x7d\xf1\x7a\x7f\xc6\xa7\x5e\xcf\x4f\xaa\x4d\x1e\x21\xb6\x76\xb3\x72\x7d\x77\xfb\xd4\x3f\xa7\xbe\x76\xbf\xb5\x8f\xc3\x09\xe5\x67\x5f\x0a\x85\x9c\xc4\x7f\x37\xb1\xbf\x45\x59\x32\xd8\x24\xe8\x63\x78\xde\x7a\x7e\x8c\x40\xce\xd2\x20\x90\x04\x4d\xbb\xf9\x1c\x70\xe5\x28\xea\xcd\xef\x37\x85\xba\x3c\x69\xa3\x73\x5a\xf6\x70\x9c\xd7\x6a\xab\x28\xa6\xac\xa6\xe8\x44\x97\x4b\x10\xb3\xfb\x7b\x09\x86\x00\x7a\x72\x7c\x2c\x8f\xc9\x5b\x25\xf3\x1f\x14\x6b\x36\xac\xd4\xc5\x37\x07\x49\x20\xaf\xf2\x47\xde\x0f\x17\x9c\x13\xca\x57\x79\x0a\x6a\x71\xd6\x2e\x23\x32\x1c\xcc\x75\xb7\xf3\xb0\xaf\xa0\xd0\x35\x27\xc9\x11\x4a\x7d\x4e\x30\xc1\xac\xe6\xd7\x71\x20\x13\xde\xe6\x66\x99\xaf\x9c\x56\x1c\x44\xae\x61\x98\xed\x39\x10\x4e\x60\x61\xae\x2c\x45\xa9\xa3\xc7\x4b\x5d\x0f\xbc\x4a\x33\xe8\xdf\xe2\xa8\xac\xc9\x51\x1e\xf7\xe6\x56\x71\x33\xf9\xfe\x35\x54\x28\x4a\x75\xa0\x59\xa6\x49\xdd\x24\xec\x04\xa5\x77\x30\xc6\xd2\xe9\xbf\x11\x4e\xa5\x8a\x89\x94\xab\xdb\x0c\x19\x43\x24\x15\x72\xc7\x9e\xad\x04\x3a\xd1\xc8\xca\xaf\x5c\x9d\xa5\x3d\xd0\x55\x22\xfe\xbc\x40\x33\x54\xd6\x2f\xe3\xff\x93\x88\x2d\xf7\x5f\xb2\x94\x58\xd2\x2e\x69\x96\xc3\x5b\x69\xfa\xae\xf2\xe0\xc4\x16\x38\x86\xcb\x3c\x3d\x0f\x60\xe1\x50\xd3\x63\xd6\xdb\x59\xfe\xfc\x62\x6b\x1b\xbb\x1e\x05\x2a\x62\x41\x4c\x4b\x78\x56\xd7\x20\x93\x43\x2b\x08\xf8\x21\xbc\x78\x4a\x5a\x6b\x0b\xc2\x64\x9c\x2d\xaa\x50\x86\x58\x98\x0d\x80\x22\x91\xe7\x34\xab\xaf\xf0\x6a\xfb\xf2\x79\x5e\x4e\x35\x4d\x52\x21\xdc\x4f\x52\xcc\x96\xd6\xb8\xcf\x18\x08\xb1\xa8\x20\x8d\xb7\xda\xa8\x0a\xb7\x10\xc5\x6a\x8b\x0e\x9c\xb8\x08\x1d\xee\x93\xf5\xf0\x15\xf0\x76\x64\x46\x3a\x3d\xcc\xff\x7c\x8a\xd1\x99\x23\xa9\x7e\x39\x04\x5b\xcc\x4d\xce\x0a\x73\xd4\x9c\x56\xd5\xe9\x37\xbd\x11\xe6\x18\x23\x40\x1c\x06\x62\x06\xe3\x13\xe6\x0b\x47\x53\x7e\x34\x70\x4d\x7d\x35\x15\x55\x9b\xb9\xd0\x53\x2d\x02\x8e\x28\xa5\x7a\x87\x9f\xd6\x17\xcc\x61\xf7\xf7\x76\xbd\x6a\x00\x8c\xd4\xf8\x12\x37\x8e\xd3\x7f\x39\x4b\xb9\x7e\x6e\x75\x6d\xa8\x19"}, -{{0xa8,0x86,0xf4,0xd3,0xf3,0x4e,0x32,0x0e,0xc6,0xd5,0xf4,0xca,0xa8,0x63,0xf8,0x14,0x77,0xdf,0x77,0x2e,0xff,0x97,0xe6,0x4a,0x37,0xa0,0x5f,0x42,0x11,0xd1,0x90,0xa8,},{0xe9,0xbc,0x96,0xc8,0x1e,0x87,0x81,0x10,0x26,0x8b,0x55,0xde,0xf7,0xea,0x40,0x07,0xa4,0xef,0x9f,0x54,0xd3,0x83,0xd5,0xfb,0x0f,0x6d,0x43,0x43,0xe1,0x01,0x0f,0x38,},{0xab,0xf2,0x83,0xdb,0x1f,0x80,0xc5,0x4c,0x58,0x3b,0x49,0x9d,0xbe,0x20,0xaa,0x04,0x24,0x8c,0x1d,0xce,0x12,0x1f,0x39,0x11,0x67,0x78,0x13,0xac,0x3e,0x01,0x1f,0xd1,0x59,0xad,0x0b,0xf7,0x6b,0x1a,0xa7,0xcc,0x7b,0x14,0xd7,0xb5,0x50,0x84,0x86,0x88,0x25,0x2a,0xcc,0x7f,0xec,0xe9,0x04,0x87,0x24,0x0c,0x3d,0x39,0x9d,0xd3,0x43,0x08,},"\x8b\x83\x1b\x87\x7b\xc3\xa9\x9f\x61\x3c\x89\xcd\xa6\x98\xb3\x75\x9d\x64\x38\x22\xb5\xa8\x8f\xaf\x38\x22\xec\xb2\xce\x98\xf6\x71\xd7\x55\x43\x21\xb2\x4b\x74\xb4\xe3\x0a\x66\x3f\x7a\x55\x70\xae\x91\x7f\x47\x9b\xda\x29\x89\x4b\x1a\x8c\x02\x8c\x9d\x19\x3e\x4e\x7a\xc1\x19\x16\xdd\x8e\x9c\x3f\x0e\xc0\xef\x80\xbd\x27\xfd\xfe\xee\x80\xc1\x70\xc7\x81\x40\xb2\x4c\x15\x27\x14\x15\xac\xf7\x5c\x26\x95\x6a\x4d\x4b\xf9\x9d\x40\xe8\x61\xe9\x07\x83\x20\xd0\x97\xe1\x25\x9e\x5e\xc1\x7b\x58\x3a\x95\xe5\x24\x30\xdd\x8c\x00\x8e\xd8\xc7\xdd\x1d\xe1\xbe\xcd\xd1\xe6\xbf\xec\x4b\xf3\x34\x7a\x22\xdd\x24\x9f\x3a\xc3\x07\xa2\x94\x5e\x91\x37\xfa\x4a\x8c\x26\xc8\x02\x10\x77\x23\x9c\xb3\x24\x81\x6a\x8d\xad\x32\xb0\x1e\xe3\x4a\x08\x90\x30\x98\xcb\x9c\x42\x45\x29\x1b\x90\x3c\x96\x27\x07\x40\x95\x24\x9e\x78\x28\x13\x47\x70\x32\xba\x32\xef\x04\x1a\x07\x48\x6e\xb4\x47\x8c\x57\xb9\xd5\x32\x26\x9a\x4a\x47\xcb\x5e\x97\x4d\xf7\xe0\x10\x96\xfb\xe4\xf1\xcc\xd4\xe6\x63\x66\x34\x87\x97\x4c\x62\xcd\xd9\x4d\x77\x71\x6c\x84\x79\xd7\x9f\x6b\x6a\x7d\x9c\x15\x59\x88\xcf\x39\x02\xfb\x69\x74\x24\x96\x3e\xc4\xec\x34\xff\x2a\x35\xd7\x42\xc4\x45\x5a\x59\x3b\xac\xff\xc4\xd9\x69\x9b\xa7\x62\x6c\x76\xcb\x1a\x61\x62\x53\x75\x18\x87\xf6\xff\xe2\xbe\x20\x8c\x71\x3d\xf1\xab\x63\x6d\x72\x2e\xa0\x6c\x1c\x03\xa5\x7f\x2c\xec\x08\x03\x86\x6c\xca\x33\x35\xc2\x8b\xf4\x1c\x7d\xef\x81\xac\xb3\x88\x58\xdc\x10\xe5\x94\x67\x20\x86\x24\x96\x7e\x2e\x22\xd9\xe5\x66\x1b\xb9\x45\xf9\xe0\x51\x76\x87\xdc\x80\xf9\xb8\xfd\xec\xc8\xa9\x76\x00\xb6\xc2\x19\xa3\xb2\x3a\x90\xb6\xd1\x8a\xaa\xce\x2c\x78\x40\x0f\xf3\x8c\x8c\x05\x96\x7f\x54\x4b\x6a\x60\x6c\x71\xac\x19\x9e\xaf\xd0\x7e\xb5\x84\x8d\xf1\x65\x7e\xfb\x23\x3f\xba\xba\xe6\x3a\x05\x63\x81\x91\xa0\xaf\x74\x84\xa1\xba\xe1\x58\x13\x75\x67\x2c\x57\x1e\x26\x4f\x60\x42\x25\x17\x3a\x54\xa3\x8d\xd6\x2a\xe7\x13\x0d\x05\xdd\x29\x1a\xd1\x23\x54\xde\x86\xa6\xe1\x13\xe8\x3f\x6d\x66\x85\x16\x15\x7b\x79\x67\x02\x0d\xc6\x51\x7d\x8c\xf4\x2d\xd7\xb1\xa8\x97\xfe\x1b\x4e\x04\x55\x3c\xe2\x6e\x29\x99\x80\xaa\x5f\x7c\xe0\x17\x9b\xf4\x95\x4f\x01\xc2\xa2\x36\x54\xe5\xe9\x73\x1e\x14\x47\x34\x7f\xa4\x3a\xa8\xb2\xcb\xd6\xd4\xb2\xdf\x93\xfa\x54\xaf\x71\xe5\x02\x8a\x6d\xa8\xc7\x1e\xf3\xc5\x0c\x0d\xe2\x4d\xca\xee\x78\x56\x78\xe9\x2a\xaf\xab\xeb\x23\x3b\x01\x1f\x45\xc1\x06\x49\x65\x08\x5d\x25\x47\x05\x0f\x21\xc6\x52\xaa\x53\x3a\xfe\x91\x8a\xa0\xf9\xbd\xaa\x26\x07\xb8\x73\xcc\xd3\xdb\xd1\xd3\xa8\xcc\x62\x17\x2c\xeb\x43\xb9\x21\xef\x6b\x25\xc0\x6b\x09\x92\xe4\xdf\x2b\x91\xe3\x71\xb0\xef\x2b\x39\x47\x38\x8d\xae\xc8\xec\x6f\x7e\x38\x67\xd1\xf6\x10\x72\xaf\x59\x01\x54\xfa\x61\x9a\x07\xf8\x7e\x02\xbd\xdc\x74\x06\x31\x42\x70\xaf\x1c\x15\xe8\xee\x88\xb3\x9c\x01\xbe\x60\x2e\x4f\x0b\x52\xd9\xa0\x72\x4e\x71\xed\xdd\x7f\xa9\x13\x41\x69\xc5\xfa\xab\x91\x59\x79\xee\xa9\x36\x2d\x0f\x1f\x91\x60\x26\x81\x62\xdd\x38\xdb\x02\xfc\xfb\x41\x35\x0a\xa0\x8e\x1e\x14\x09\xb2\x28\x8d\xb1\xfe\x4a\x0e\x58\x6b\x59\x10\xf4\xde\x89\x4b\xf9\x97\x4f\x6a\x49\x83\x01\x3a\x19\x0e\x7a\x73\x6d\x14\xec\x54\xc3\x64\x4a\x3e\xe9\x58\xa5\xbd\xfb\xcb\x62\x97\xab\xa4\x3a\xf6\xc7\x27\x46\xbb\x13\x54\x10\x50\x7d\x8f\xdd\xe7\x3a\x2a\x48\xb7\x46\xf9\x18\xbe\xf9\xed\x92\xc5\xbe\x62\xdd\x55\x23\xfe\x14\xb1\x6d\x63\x84\xca\x46\xef\x59\xb2\x18\x5f\xe9\x33\x38\x3a\x2c\x7a\x9b\xf0\x2d\xa9\xd0\xfd\x8b\x0c\x7d\x7b\xde\x6b\x43\x9f\x99\x60\x15\x5e\x34\x5d\x68\x5d\x4d\xc3\xc7\x14\x04\xd6\x56\x81\x19\x23\xaa\x3c\x47\xd4\xb0\x9a\x0b\xae\xf0\xa1\x2e\x75\xb6\x43\x9b\xa8\x13\x5d\xb1\x58\x65\x87\x42\x22\xcd\x7a\xa4\x28\xf5\xca\x5c\xe5\x14\x0e\x22\xff\x92\x69\x7f\x37\xfc\x70\xb5\xb4\xc9\x4d\x33\x14\xe6\xaa\x16\xb2\x14\x6b\xca\x4f\xc9\x41\x57\x95\x1f\xc4\x92\x45\xda\x53\xf6\xc4\x3d\x1b\xeb\xd8\x94\xe3\x1a\x13\x49\x88\x4d\x71\x1b\x55\xdb\xe7\x78\xff\xa7\x27\x16\x5c\xf7\xcb\x67\x64\x35\x86\x6c\x2d\x2c\xb8\x39\x74\x5c\xa4\x01\x66\xa2\xf7\xcf\xc7\x7a\x84\x24\x68\xb5\x1a\x8e\x76\x57\x5f\xc9\xdd\xfb\x5f"}, -{{0x49,0x7e,0x3e,0xbd,0x9e,0x4c,0xaa,0x81,0xc5,0xa8,0x97,0x3d,0x52,0xf1,0xd2,0x3f,0x60,0xc1,0x34,0xca,0x53,0xf6,0x2a,0x85,0x3a,0x0a,0xc0,0x43,0xe5,0x1c,0xb5,0x17,},{0x71,0xc0,0xca,0x7c,0xfa,0x05,0xca,0xfa,0xbb,0x14,0x3d,0x84,0xae,0x41,0xde,0x83,0x84,0x6f,0x42,0xc7,0x7c,0xaa,0x7a,0x91,0xa2,0xe3,0x48,0x39,0x7d,0x07,0xd5,0x2f,},{0x12,0x74,0x08,0x39,0xb3,0xc9,0xf1,0xba,0x87,0x98,0x96,0xdf,0xf6,0xd7,0x25,0xe8,0x4e,0x04,0x43,0xef,0x96,0xc3,0x49,0xef,0xf9,0x4d,0xc4,0x83,0x31,0x43,0xe5,0xb4,0x19,0x80,0x4d,0xa9,0xdb,0x11,0x8a,0x95,0x92,0xb1,0xb1,0xca,0x48,0xaf,0x18,0xf7,0x5b,0xef,0x1c,0xa4,0x68,0xa1,0xa5,0xc7,0x4c,0x7a,0xc8,0x13,0xbb,0x2c,0xf3,0x06,},"\xe1\x32\xf9\xd6\x7b\x17\x29\x38\x9b\x82\x8a\x9f\xae\x05\xa6\x7a\xa5\x7f\x0e\xf7\xe7\xd4\xd1\xba\x24\x4d\xec\x87\x04\xdb\x96\x95\x65\xd1\xca\xb8\x09\xe4\x8f\xc0\xab\xf9\x50\xbc\xd4\xa3\x7d\x97\xae\xac\xe6\xda\x54\x6d\x49\x14\xcb\x5b\x86\xd6\xab\x18\x1d\x83\x18\x70\xc3\x09\xbc\xa6\x16\x46\x8f\x2a\x34\xd3\xdf\xaf\xcd\xbb\x75\x80\xb0\xc5\xd9\xff\x98\xe2\xc5\x4e\xc8\x03\xbe\x0d\x3f\xda\x1d\x4b\x8c\x0d\x77\x09\xc8\x9e\x68\x0b\x00\x8b\xf9\xb8\xd9\x03\xb5\xe9\x34\xb0\x19\x70\x5f\xe0\xb0\xc8\xcf\xbc\x3c\x09\x67\x84\x3b\x0a\x1f\xa1\xb3\xf1\x62\x77\x6e\xbe\x96\xb7\x40\xed\xd6\x4a\xd7\xc3\x5b\x3f\xd1\xa0\x85\xc9\x9d\x16\xf5\x41\x67\x82\xde\x17\x35\x85\x87\x47\x0d\xd1\x3b\x51\x94\xf2\x0f\x23\x23\x2b\x2f\x70\x2f\x10\xaa\xfc\xaa\x59\xc7\x06\x6f\x24\xc4\xc4\x71\xe4\x2f\xa8\x6c\x6b\x9c\x5c\x3e\x1e\x8f\x83\x65\xf4\xdd\x75\xac\xb3\x2f\xff\xc0\x53\xc9\xaf\x41\xc6\xfd\x2e\xfa\xc3\x0e\xcf\x6a\x2d\xd0\x08\x5d\xe9\xb1\xd8\xcd\xc5\x0b\x16\x60\xa8\x66\xdf\x77\x67\x19\x8b\xd9\xc8\x73\x70\x61\x5d\x2b\xca\x99\xf7\x7b\x84\xd9\x8d\x7b\x24\xc9\xc2\x0f\xd7\x76\x8f\xd0\x38\x0d\x6b\x37\x36\x03\x40\xd1\x35\x98\x04\x78\x20\xdc\xed\x88\xa8\xd4\x2d\x57\x29\x37\xb6\xef\xa1\x69\x21\xa1\xb2\xb2\xd0\xeb\x93\x16\x73\x07\x08\x38\xe6\x11\xe6\xc0\x23\x29\x0d\x86\xfe\x90\x2f\x14\xac\x3a\xcd\x02\x9e\x33\x97\xfe\xb9\x7b\x17\x16\x62\x45\xab\x40\x7a\x76\x6d\x2e\x09\x04\x42\x4d\x33\xcd\x3d\x6e\x2e\x62\xa5\x2c\x65\xdf\x7c\xf0\x04\xd1\x41\x5c\x0b\x43\x0c\x11\x27\x62\x3d\xab\x27\x2a\x2c\x2e\x2b\x43\xe0\x2b\x48\x1b\xe9\x28\xe8\x99\x54\x27\x28\x32\xbe\x09\x8b\x50\x2b\x8b\x56\x43\xc6\x74\x82\xf5\xde\x44\x03\x03\x25\x81\xf0\x8a\xfb\x0a\xea\x48\x86\x85\x82\x60\x7b\xb3\x91\x98\xc1\xbf\x13\xa8\x69\xb6\x32\x58\xa7\x58\x90\xb6\x94\x45\xff\xd3\x45\x64\x02\x3e\x47\xf8\xb1\x88\x4a\x5e\x49\xb7\xd9\x42\x5f\x28\xd5\x15\x30\x13\xfe\x37\x55\xc6\xcb\x11\x4d\xb1\x80\xe6\x0b\x3d\xc4\xad\xb3\x6a\x21\x42\x81\x28\x00\x5a\x77\x2f\xb5\x71\x89\x34\x55\x65\xbb\xd1\x75\x98\x13\x52\x3b\xad\x62\x85\x5e\x79\x28\xee\xf5\x88\x0d\x3b\xff\xf1\xd0\xec\x65\xc2\x45\x92\x33\x5c\xda\x47\xcf\xcc\x5b\x5f\xa6\x52\xb4\x72\x63\x22\x52\x24\x84\x6a\x20\x9a\x3d\xd7\x76\x66\x61\xfc\xa4\xcc\xca\x59\xc4\x56\xfc\x9c\xc3\xe1\xcf\x80\x42\x55\xaa\x5f\x39\x7b\xab\x19\x98\x04\x33\x6b\xde\x29\xe5\x5c\x6c\x37\x7d\x58\x3f\x08\x2c\xe6\x47\x23\x73\x9e\x4f\x02\x46\x06\xf9\x06\xc1\x10\xd0\xa5\xb6\x10\xe5\xfe\xd9\x6d\xab\x5f\x08\xf4\xcb\x3c\xfc\x40\xa3\x55\x57\xe1\xa7\x40\xb8\xc7\xc0\x1f\x7d\x32\x79\xdd\x9c\x4e\x87\x64\xc9\x0b\xc1\x4f\x41\x61\xdb\x5a\x37\xf0\x98\x9b\x7b\xd8\x03\x5f\x8b\xea\x39\x4e\xa1\xd6\x00\x2c\xe9\xc3\x4f\x1e\x9c\x52\xc6\xa1\x5d\x15\xbc\x5b\x25\xc6\xc1\x5a\xb0\x0d\xfd\x6a\x5b\x1b\xc9\x17\xaf\x0b\x1b\x05\xfd\x10\xd0\x61\xb3\x68\x3d\x75\xb5\xf9\xef\xfb\x22\xae\x72\x08\x5b\xe4\xf6\x79\x7b\x58\xcb\x0c\xab\x56\x18\x44\x12\x1f\x98\xbf\xd9\x58\x3e\x0b\xcc\xb7\x0f\xad\x76\x98\x0a\x7a\x73\xb2\x3c\x70\xb3\xfd\x02\xf7\x75\x7c\x11\xa3\xc2\x1d\x19\xe0\x56\x50\xff\xb8\x2b\x9e\x0d\xf8\xa6\x73\x5d\x48\x01\x56\xf4\x79\x49\xd4\x45\x85\x1b\xae\xaa\x5e\xe2\x38\x14\xa4\x1b\x25\x23\x4f\xb9\x2c\xc0\xdf\x19\x80\xd0\x23\xd5\x1b\x5c\xf4\xc3\x11\x85\xc1\x18\xe3\xee\x3c\x0c\x0a\x46\xe0\xa2\xbe\x6f\x1d\x3a\xe4\x52\xcb\xb6\x6f\x0f\xd9\x19\x71\x34\x2d\xa7\xb1\xb9\x96\x58\x9d\x94\x09\x67\x81\x55\x21\x95\xc4\x33\xca\xf1\x9c\x37\xf9\xf1\x4f\xa0\xae\x15\xae\x0b\x02\xb9\x39\xe4\x02\x03\x4f\xf8\x18\x85\x93\x9d\x94\x4e\x60\x4f\x47\x4f\x21\x52\x43\x89\x39\x0f\xda\xda\x06\xe3\x0d\x69\x06\x8c\x88\x48\xcf\x0a\x95\x1e\xab\x25\xc4\x91\x25\x62\x94\x4f\x40\x24\x68\x18\x7a\x23\x23\x9d\x33\x63\x2f\x29\x12\x3d\x49\xb7\xde\x13\x08\x33\x98\xdb\xa9\x7d\xed\xe1\x2f\x79\x59\xb9\x52\x47\xa0\x8f\xc8\xe4\xb5\x39\x9d\x1c\x03\x5c\x08\x94\xcc\x75\xae\x98\x1c\x2d\xd4\x93\x54\x13\xbb\xeb\x68\x53\xfe\x04\x65\x5c\x77\xd1\x58\xc1\x23\x7b\x3e\x0d\xec\xa5\x63\x6d\x69\xe0\xdb\xc5\xac\xaf\x72\xb6\x0c\x10\xbb\x98\xcc\xdd\x60\x09\x8a\x03"}, -{{0x85,0xb4,0xd7,0x64,0x16,0x91,0x28,0x62,0x6f,0xd9,0xc7,0x82,0xad,0x61,0x16,0x22,0x9e,0xdd,0x77,0x63,0x1c,0x2b,0xc9,0xb8,0xee,0x54,0xb3,0x65,0x42,0xc1,0x49,0xeb,},{0x6a,0x09,0x89,0x7e,0x62,0x9b,0xb4,0x37,0x04,0xde,0xbb,0x67,0x15,0xc9,0xde,0xa5,0xd8,0x92,0xb6,0x34,0x30,0x64,0x40,0x99,0x7c,0x3c,0x9e,0x94,0xbe,0x8a,0xb5,0x47,},{0x4a,0x79,0xc4,0x42,0xa4,0xc3,0x9c,0x62,0x89,0x26,0x17,0xef,0x8e,0x80,0xb4,0x09,0x11,0xc4,0xb9,0xd3,0xff,0x0a,0x56,0x73,0xb5,0x7b,0xdb,0x84,0x54,0xad,0x73,0x67,0x69,0xdf,0x27,0xc7,0x8a,0x4b,0xf7,0xad,0x56,0x60,0x40,0xe7,0x47,0x27,0x8b,0x11,0xeb,0x65,0xcf,0x9e,0xc7,0xeb,0xa8,0x66,0x12,0x0a,0x36,0x54,0xf4,0x71,0x6e,0x00,},"\xb2\xa0\x49\x3d\x47\x1c\x33\x91\xf7\xad\xd1\xe2\xcf\x0b\xfb\x32\xab\x05\xdb\xcb\x14\xf6\xe4\xf5\xf3\x46\x3a\xa8\xd9\x95\x52\xf4\x33\x02\x20\x46\xd2\xf8\xeb\x76\x3c\x01\x71\xfc\xb1\xe7\x4a\x04\x9f\xfe\xb4\xb8\xf0\x10\x0b\x82\x10\xfc\xe8\x56\xb2\xe1\xa8\xe7\x39\xd2\xf9\x36\x73\xef\x8f\x8f\x40\x49\x8b\x30\x81\xfa\x1f\xd7\x85\x19\x8c\x6d\x37\x0e\x16\x2d\x41\xab\xe8\x31\x86\xf2\x32\x97\x83\x40\x8b\x9b\x88\x0d\x00\xf8\x1d\x53\x10\x0b\x42\xd2\x7a\x26\x1f\x20\xcd\xee\xd1\x9c\xc5\x8c\xb8\x63\x12\x81\xd8\x0d\xb1\x92\x53\x10\xe2\x35\xe4\x49\x66\x30\x9b\x87\x9b\xdf\xc2\x32\x22\x14\x33\xba\xe5\xca\xe4\x66\x90\xcb\x52\x7b\x67\x79\xe1\x1f\x1b\xd2\xa5\x6b\x59\xc5\x6e\xd4\xd9\x4f\xdf\x7a\xa8\x9d\xfa\x9b\xf2\x0d\xbf\xa6\xa4\x39\x8b\x98\x38\x45\x17\xe1\xdd\x5d\x2c\xd9\xce\x52\x4a\x47\x36\x2e\xf3\x2a\xc7\x92\x74\x2a\x12\x9c\x9e\x06\x13\x08\x76\xab\x5a\xd5\x51\x8e\xab\xc5\xe8\x0b\x02\x2d\x8f\xa1\x3e\x50\xd5\x5d\xed\x58\x95\x33\xe6\xea\x32\x24\x2c\x1b\x3f\xd7\xe6\x5f\x80\xde\xe7\x20\xb6\xd8\x7d\xcf\xf3\xe3\xdf\x04\xc8\x02\xd2\xe9\x14\xa8\x7a\x36\x29\xc9\x0b\xb6\x9e\x0a\x6f\x8b\xbb\x5e\xe5\x05\xf1\x43\xc9\x97\x73\x75\xad\xb0\x65\xc3\xe3\xd3\x91\xf9\x05\xfa\x3c\x33\x6c\x9d\xa4\x1e\x4a\x23\x20\xbc\xf4\x60\x97\x6f\xc7\xeb\x1f\xb6\xc6\xa3\xc3\x95\xdb\xd1\xd2\x8a\x1b\x09\xcd\xb9\xae\x9f\x9a\xae\xe4\xd9\xc5\x66\xa2\xac\x40\xad\xd8\x70\x47\x9f\xaf\x54\xad\x1b\x76\x97\x71\x0b\x4e\xb6\xf7\x32\x02\x44\xb5\x97\x57\xd1\xea\xc3\xd9\x22\xb7\xa7\x30\xb1\xac\xf0\xde\x9a\x45\xd4\xac\x87\x9d\x21\xfc\x61\x6e\xf3\x96\x5d\x74\x34\x5e\xd7\x07\x79\xeb\x68\x32\x80\xce\xe2\x5b\xf3\x73\x9b\xeb\x6b\x4c\xdf\xa2\x5d\x20\x2d\xa1\x3a\x4a\x67\x30\x40\xd9\x70\x48\x65\x8b\x92\x05\x47\x95\x05\xd0\xbe\xe4\x88\x0a\x73\x99\x7c\x70\x82\x5a\x6e\xc5\xfd\x9f\x95\x2e\x65\xfa\x02\x22\x54\x45\xfc\x3b\xdf\x4a\xde\xa3\xd4\xd2\x25\x51\xcb\xac\xeb\x38\x74\x79\x8d\x6a\x33\xa6\x66\x3f\xe3\x75\x70\x81\xd6\x24\x3d\xfd\x7c\xd2\xee\xbf\x60\xa3\x89\x9f\xa1\xf8\xf6\xc9\x56\xa3\xb1\x83\xf8\x9b\x9e\x7d\x2c\xa3\x64\x48\x58\x4d\x53\xaa\x8b\x44\xe6\x5a\xd3\xe5\x27\xf7\x87\x23\xfa\x6f\x59\x22\x42\x98\xdf\x31\xd5\xe8\xad\xa5\x67\xc8\xd1\xb1\x1f\x3b\x13\x14\x75\x53\x31\xc1\x73\x2d\xc5\x4a\x12\xa4\x35\x6e\xdd\xa4\x7e\x3c\x13\x0b\x32\x52\x82\xa3\x54\xbf\xe1\x5c\x30\x00\xd2\x07\x82\x29\x31\x79\x41\x87\xe0\x97\x3a\xb8\xef\x87\xbf\x89\xc3\x54\xa0\x35\xa8\x1f\x45\x91\x12\x23\x56\x3b\xfd\x99\xf9\x0a\x75\xe5\x3d\x01\x0d\x89\x29\xf4\xf8\x5a\x5a\x5a\x4f\x9f\xcc\x1c\x78\xf0\xa2\xfc\x46\x6f\x5f\x1c\x65\x22\xcf\x62\xa7\xbe\x37\x88\x07\x96\xe9\xb3\xca\x09\x11\xec\xca\x3f\x22\xc3\xb2\x4d\x5d\x9d\xaa\x68\x88\xf8\x9a\x8f\x71\xa1\x58\x59\x35\x9c\xea\x46\x8e\xf2\x38\xec\xf6\x46\x19\x27\x83\xa2\x57\xad\xda\xde\x90\x47\xe1\x3e\xdd\x8b\xcc\x1f\xd4\x17\x7c\xb2\x0f\x88\xd1\x19\x98\xd9\xc7\x26\x2d\x64\x8c\x2b\xf6\x6f\xb2\x27\xb9\xb3\xa9\xed\x46\x96\x2d\x22\x57\xa4\x20\xf6\x4b\xea\xd9\xe2\x86\x57\xb5\x21\xdb\x2e\x22\x16\x52\x87\x79\x1f\x3a\x1b\xec\x4c\x78\x22\xa6\xca\xbd\xe5\xec\x77\x01\x88\xcb\x74\x49\x8a\x4f\x08\xe5\xa3\xa7\x63\x9d\x24\x0a\xe3\xf4\xfd\x03\x53\xc0\xdd\xa8\xae\x41\x0b\x9f\xa7\xf4\x3f\xee\xd1\x3e\x9f\x13\xe6\xc9\x41\x0a\x1d\x24\xcd\xfc\x2c\x8e\x64\xa1\x5a\x12\xf7\x55\x45\xb0\xa5\x75\x71\x35\x23\xd4\xdf\xa1\xa4\x74\x27\xa8\x85\x1b\xa9\xac\xcc\xad\x78\xb4\xef\x6a\x18\x5f\x5c\x3b\x00\x11\x90\xdd\x8f\x37\x08\x8a\x00\x0a\xcc\xf4\x48\xbe\x8d\x49\x37\x1d\x9d\xa2\xe1\xcb\x5f\xfe\x07\xd4\x1a\x5c\x22\xe9\x46\x60\xac\x37\x13\x5a\xc8\x58\xcb\x17\x69\xcb\x66\xe8\x26\x9f\xd5\x33\x58\xec\xac\xf5\xdd\x92\xc7\xeb\x61\x86\xb4\xd4\xd6\x13\x0a\x73\x2d\xc1\x0b\xbb\x2b\xe3\x2f\x9b\x1d\x69\x51\x01\x4a\x63\x5c\x12\xd2\x2f\x0d\xc5\xbd\x5c\x2a\x3f\x96\xae\xc6\x2e\x77\x77\x94\x7e\xaa\x02\x28\x12\xca\xce\xd3\x3a\x5b\xef\x9f\xf8\x83\x5f\x88\x03\x67\xa3\x7b\x0b\x76\xd2\xdd\xe3\x96\xc6\x14\xe1\xa4\x72\x1e\x00\x0c\x00\xf1\x61\x93\x5b\x14\xa7\x38\xa1\xb7\x0f\x6e\xa5\x42\x55\xb7\x95\x18\x69\x64\x62\x12"}, -{{0x33,0xd4,0x77,0x60,0x2f,0x29,0x63,0x05,0xa6,0x71,0x9e,0xa6,0x94,0xc0,0x44,0xe9,0x0d,0x23,0x3c,0x2d,0xea,0x85,0xc4,0x6a,0xbe,0x19,0x20,0xe8,0x8c,0x31,0x78,0x49,},{0xff,0x6f,0xee,0xa0,0x28,0xec,0x34,0x6d,0xd4,0x91,0x07,0xbb,0x71,0x3f,0xdd,0xbb,0x28,0x2e,0xbc,0xd0,0x34,0xe2,0xea,0xfc,0x7c,0xdb,0x1c,0x5a,0xdf,0x92,0x63,0x90,},{0xca,0xa2,0x87,0x98,0x95,0xd4,0xf6,0x20,0xb9,0xeb,0x5f,0xed,0x22,0xb4,0x56,0x2e,0xeb,0x1a,0xd6,0x38,0x22,0x96,0x8f,0x76,0xad,0x91,0x07,0x6b,0x16,0x6c,0x05,0xee,0x20,0x86,0x4d,0x98,0xbb,0xbc,0x6e,0x79,0xdd,0x03,0x62,0xca,0xcf,0x7a,0x21,0xb4,0xcf,0xc2,0x30,0xd6,0x35,0x5d,0x43,0x12,0x0c,0xff,0xfb,0x94,0x8b,0x8f,0x6c,0x0e,},"\xcf\xea\x07\xa7\x79\xf1\x53\x7e\x49\x81\x23\xc6\x76\x29\x05\x73\xef\xcc\x5d\xb7\x02\x45\xd9\x3d\xea\x5c\x05\x72\x6f\x87\x13\xd0\x02\xae\x66\xc1\xc9\x69\x07\x47\xca\x92\x30\xb1\x62\x9d\x36\x62\xab\x73\xd6\x6b\x94\x98\x79\x16\x4b\x21\xa3\x5f\x40\xcf\x37\x99\x04\x19\x08\xed\x6f\x92\x29\xec\xb3\x90\xc5\xf2\x22\x34\xe1\xc5\xf2\x6b\x3a\xb5\xba\x59\xe7\x8c\x64\x96\x98\x71\xb4\x28\xb7\x85\x16\x77\x75\x55\xaf\x4e\x89\xc6\xfb\xc1\x93\xa9\x46\x95\x22\x6c\x6d\x32\x99\x91\xa1\x1b\xd5\x80\xd1\x89\x56\x08\x9b\x58\xa0\xe4\x2c\xa3\x5f\x6c\x6d\x26\x09\xad\xe0\xd0\xb6\x19\xd4\x89\x25\xc6\x8c\xd9\xd2\x25\x0d\xff\x27\xcf\x2f\x0d\x44\x44\x87\x09\xb6\x79\xf3\x5b\xbd\xce\x0f\x49\x6b\x0a\x16\xca\x67\xea\xce\xec\x25\x8b\x1a\xec\x91\x77\x5a\x3a\x2e\xe8\x01\xb1\xc9\xa2\x26\xa6\xb0\x01\x92\x6a\x05\x7a\x06\x30\x67\x27\xee\xda\xe8\xc5\x77\x53\x1d\xf0\x4a\xc0\x9b\x5b\x49\xbc\xde\xab\xde\xb8\xac\x4e\x8e\x82\xcf\x1e\x7a\xf8\x35\xfc\x61\x1c\xa7\xa6\x84\xb8\x35\x26\x04\x24\x15\xb1\xd6\x65\x2e\x86\x34\x31\x1e\x19\x46\x27\xea\xe7\x8d\x01\x1e\x6f\x40\xf6\x45\x79\x4e\x36\x89\x5a\x23\xe1\xbd\x84\x88\x3a\x39\x3e\xcf\xe5\xa2\x48\x02\x6a\xea\x86\x44\x70\x59\xf7\xa4\x29\x36\x8f\x21\xc8\x9e\x01\x45\x20\x79\x78\xb9\x13\xc8\x0a\x22\xd7\xca\xf2\x67\x3f\x7c\x76\xf6\xc2\x6c\xf8\x84\x41\x2e\x17\xd0\xc2\x55\x43\x0f\x50\x2b\xce\x74\xe3\xa3\x10\xd1\x7f\x6f\x4d\x48\x5d\xa2\x80\xed\x5b\x5e\xea\x6c\x49\xba\x74\x8d\x76\x48\x14\xb9\xe3\xda\xf6\xfc\xc2\x18\xc2\x74\x0c\xa7\x70\x18\xf7\x13\x44\x51\x9d\xa8\x2a\xda\x31\xe0\x01\x92\x4f\xc7\x76\x79\xe3\xe9\xff\x9f\xab\x67\xdd\x09\xa6\x19\x24\xc8\x21\xa1\xfd\x99\x9f\x74\xdf\xa3\xf8\x19\xad\xb3\x1d\x15\xe5\xed\x8a\xaa\x52\xc1\xbd\x7c\xca\x26\x67\x11\xa7\x4d\xd6\x21\x04\xef\x3c\x2b\xf7\x37\xfc\xe6\x94\x2b\x34\x8a\x33\xc3\xdf\xd6\xd9\x2a\x72\x4b\x6d\x58\x78\x42\x1a\xeb\x23\x0a\x53\x3f\xe2\x1c\x8b\x2f\xd3\xda\x59\x6a\x61\x80\xa4\x5c\x98\x6d\x7e\xce\x4c\xdc\x8a\xd6\x81\xea\xd6\x90\x64\xbb\xdd\xfc\x20\xf3\xc5\x21\x25\xf8\x33\x95\xbe\xd1\x55\x7f\x67\x18\x2b\x9f\xe9\x91\x38\xaf\x3c\x35\x6c\x5e\x65\x29\x78\xdd\x23\x8b\x76\x1c\x74\x2f\x81\x58\xe2\x31\x4b\x96\x42\x08\x33\x09\x78\xb0\x62\x0a\x13\xa1\x6d\x76\x1d\x52\xf0\x6e\x46\x6a\x40\x94\xb6\x5c\xd6\xf2\x68\x54\xae\xd6\xf9\xa8\xc2\xa8\x84\xa0\xd0\xbf\x4e\xe5\x87\xee\xb8\xb6\x02\x48\x72\x39\xa7\xe5\x81\x72\xc8\x09\x98\x3a\x8d\xb1\xc1\xfc\x7c\xe8\xc4\x8b\xc8\xa6\xfb\x81\x2d\x6a\xa9\xe8\x3a\x3a\xb4\xdd\xf7\xa8\xd4\x0d\x3f\xe0\x0e\xa1\x6e\x04\x06\x2b\x8a\xce\xb9\xc9\x9e\xef\xa4\x1f\x4f\x87\x44\x78\x28\x12\x6d\x0d\x9c\x9f\x86\x05\xe8\x46\x7c\x5e\x4d\x67\x1d\x5c\x6d\x9f\xa7\x0d\x74\x70\x98\xd9\x41\x21\x12\x23\xb9\xbc\xf2\x61\x93\x8d\x67\x04\xa3\x2d\x22\xc6\x1e\x30\xf3\x57\x0a\x1f\x5d\x09\x98\xb4\x79\x10\x80\x88\x2a\xa5\x62\x31\x67\xb6\x3a\x23\xf3\x40\xf0\xe7\xc6\xf9\xa8\x30\xa7\x5b\x74\x63\x1f\xa5\xb5\x7a\xfd\xb1\xe6\xbc\x22\x69\x9b\xb0\x31\x56\x67\x5d\x59\x83\x53\xa5\xd1\xb5\x58\x97\xe4\xc1\x10\x61\xdd\x14\x5f\x23\xe8\x53\x7c\x63\x2f\x75\xc1\x0d\xf0\x5b\x25\x54\x72\x38\x57\x40\x17\xfe\x7b\x64\xb8\xe9\x98\x69\x15\x7f\xee\x35\xf7\xad\x7e\x63\xe9\x95\x93\x30\x29\x29\x50\x3a\x96\x76\x80\x23\xb4\x12\x5a\xd7\x49\xdf\xf4\xb9\x92\xee\x5c\x2b\x4f\x3a\xda\x48\x89\xe4\xae\x62\xec\x15\xd2\xdb\x59\x69\xd7\x30\xdb\x30\x75\x47\xf6\x38\xc3\x18\x50\x32\xb1\x2f\x75\xfb\xb3\x17\xe4\x7d\xf7\xb9\x29\x2a\xe9\xe7\x6a\x2c\x0a\x06\xfc\xad\x10\x8c\xdd\x23\x5f\x6e\x38\xd9\x67\xb6\x37\x95\x11\xff\x69\x65\xc2\x2f\x2c\x66\x80\xa1\x2b\x03\x04\xeb\x2b\x29\x6c\x99\xa7\x6c\x27\x29\xd9\x8e\x0a\x78\x24\xb6\x7f\x3f\xe8\x42\xd6\xf6\xab\x27\x3e\x89\x48\x45\xb3\x2d\xc6\xdd\xfc\x7a\x22\x0f\x76\xbd\x96\x5c\x69\x85\x81\x83\xc8\xf3\x57\x39\x5f\xc5\x7d\xc8\x29\xde\xfa\xac\xb5\x60\x3a\x75\x78\x68\xd5\xe5\x62\xf9\x78\x1e\xe3\x9e\x0e\x94\x68\x8a\xd3\x54\x5b\x32\xdd\x73\x66\xb6\xb0\x47\xe8\xd1\xd3\xd5\x65\x99\x7b\x23\x6e\x7f\x75\x96\xc5\xf8\xd7\xc1\xc1\x1b\xcf\x4a\x24\x46\x20\xcb\xd2\x1d\x55\x9a\x7c\x9b\x3f"}, -{{0x70,0x74,0x56,0x86,0x11,0xa6,0x6d,0xfc,0xa8,0x30,0x7c,0xae,0x60,0x8b,0xb2,0x69,0x95,0x84,0x4d,0xf4,0x35,0xe5,0x30,0x0e,0x5b,0x4d,0x72,0x91,0xcc,0x22,0x90,0x7f,},{0xdd,0xab,0xdd,0xd1,0x5e,0xaf,0x83,0x11,0x5d,0xdd,0x06,0x5d,0x7e,0x22,0x0b,0x1e,0xfc,0x26,0x2a,0x61,0xc5,0x2e,0x91,0x43,0x47,0x44,0x2b,0xde,0x6d,0x00,0x25,0x06,},{0x7f,0x65,0x31,0x34,0xc0,0xb9,0x0f,0x44,0xa4,0x89,0xf0,0xb0,0x5f,0xc4,0x07,0x07,0xad,0x9f,0x13,0x98,0xf3,0x40,0xb4,0x47,0xa3,0xc9,0x86,0x1f,0x51,0x1c,0x9f,0x15,0x68,0x80,0x3b,0x76,0x84,0xa0,0x4a,0x89,0x8c,0x45,0x15,0x4d,0xd4,0x86,0xbd,0x50,0x75,0x89,0x98,0xe1,0x26,0x43,0x93,0x78,0xb3,0xf5,0x9f,0xf3,0x67,0x49,0x2a,0x0a,},"\x6c\x13\x74\x23\xea\xc7\x90\xb8\xe8\xe4\x18\xb2\x90\xe0\x57\x9c\x7b\x86\xb1\x4a\xed\x81\x8d\xe8\xce\x53\xce\xa3\xf3\x40\xa1\xa9\x53\x91\xf9\x84\x96\x8f\x2b\x42\x29\x28\x2a\x81\x61\xc0\x9a\xb1\x49\xcd\xac\xd6\x69\x70\xb4\x01\x3f\x52\xe5\xe6\x8e\xa8\xc9\xdb\x68\x5b\x2c\x53\x07\x35\x00\xe5\xb3\x5e\x29\xea\x0b\xa1\xf4\xd1\x59\xa5\x58\xd3\x61\xb0\x65\x16\x83\x6c\xf7\xb9\xea\x50\x1f\xa0\x50\x6b\x98\x5f\x03\x6a\x82\xd9\xe0\x84\x48\x9d\x3b\xfe\xd3\x40\x93\xe2\xd6\xd9\xed\xf5\x57\x85\xed\x35\xa9\x0c\xe5\x6c\x76\x16\x86\xcc\x3e\xa1\xa2\xc7\x6a\xda\x5e\xc8\xc1\x45\xd8\x18\xb0\x47\xcc\x51\x6e\xec\x5d\x2d\x6a\x93\xa5\x55\x92\xd8\x92\xe3\xd5\xcd\x10\xc2\x50\xc0\x4b\x04\x9b\x38\xfc\x7e\xc0\xf3\x9a\xba\x15\x82\x40\x07\x33\x6c\x2b\x0f\x7f\x81\xd6\x4d\x5c\xa3\xe2\x9d\x6f\xda\x4c\x23\xd9\xba\x65\xd9\xfe\x3c\xb4\xe0\x39\x13\x69\x72\x87\xb4\x6a\x0b\x1f\xcc\xd2\x62\x4e\x39\x7a\xe9\x5c\x52\x54\xbc\xd8\x8d\x2c\x7c\x8f\x70\xfd\xc8\x17\x3f\x64\xc1\xde\x32\x28\x1a\xb4\x18\x46\x93\xb4\x8a\x34\x9e\x67\x82\xbc\x89\x92\xb4\x3c\x7d\xe7\xcb\x9d\x33\x92\x9b\xf9\x53\x06\xc2\xaf\x7e\x93\x8d\x84\x86\xb3\x86\xf9\xfd\x3f\x0f\x71\x61\xe0\xe6\x86\x2d\x4f\x92\x81\x44\x68\x65\xa1\xc9\xbe\x24\x60\xef\xbc\x20\x15\x1b\x06\xe7\x9d\x01\x46\x17\xd0\x30\x0e\x67\x1d\x48\x76\x74\x58\x59\x66\x25\xb7\x6d\xff\xc5\x58\xaa\x9b\x40\x61\x21\x96\xec\x82\x7e\x1c\x6f\xff\x51\x8f\xb7\xad\x4b\xf8\xc4\x6f\xcb\x27\x88\x85\xaa\x49\x1b\x77\xa2\x89\x95\xcf\xb9\xd7\x96\x40\xaa\xd1\x74\xc6\xdf\x43\x93\x8e\x3f\x13\x85\x20\x5c\x54\x59\x5b\x33\xde\xde\x50\x14\x37\x46\xa1\x70\x5e\x7e\x0b\x69\xaf\x4a\x26\xc3\xb7\x65\x15\x05\x18\x92\xb1\x5c\xa6\xe4\x8c\x3d\x91\xfb\xc7\x5e\x8f\xe4\xa0\xfe\x8e\xd2\xc2\x6c\x10\x73\xbe\xb7\x0e\xa3\x8d\x09\x27\x02\x92\x78\x40\x67\x55\xae\x6e\x11\xda\x37\x86\x53\x64\x95\x15\xe0\x08\x5b\x5e\xa7\xdb\x32\x49\x20\x8e\x33\xa6\xc8\xb6\xae\x8c\xd8\x0c\x9b\xd6\xb9\x83\xe7\x3e\x9b\x91\xdb\xec\x09\x1f\xae\x99\x5f\x80\x32\x42\x7e\xde\xc0\x2c\xad\x90\x55\xeb\x8b\x7d\xbc\xfa\x80\xd4\xf6\x4f\x57\x27\xa1\x52\xf1\x1c\x47\xe5\x2d\x75\x3a\x57\xb6\xe5\xfd\xdf\x77\x4c\xea\x4d\xa9\x10\x02\x68\x19\xc4\x1e\x32\xb4\xf1\x99\x72\x7e\x23\xc5\x4a\xb5\xd7\x01\x42\xb8\x54\xa2\x7b\x04\xe6\x4c\xf4\x4a\xf2\xa8\x99\x5e\x12\x00\xbd\x11\x7c\x7a\x16\x74\xed\xef\x59\xbc\x53\xf7\x3a\xda\xf6\x38\xe0\x77\x3b\x85\xb5\x63\x34\xaf\xf6\xe1\x17\x43\xe3\xa3\xd3\x61\x4a\xa8\xa3\x75\xb3\x78\x1e\xc8\x14\xcc\x08\xe7\x1e\xfa\x78\x18\x51\x9c\xb2\x4a\xf8\x2c\x33\x1d\xfd\x6a\xc7\x8e\xc1\x7f\xd7\x17\x4b\x61\x02\x1e\x8c\xf9\x01\xa2\xaa\xa6\xad\xbc\x90\x2a\x91\x6b\x2a\x2f\x4f\x79\xe5\x51\x50\x1f\xbf\x01\xdf\x6b\x85\x18\x50\x4c\x1e\x94\x64\x69\x38\xbe\xd1\xa8\x50\x9c\x2a\x38\xfb\x6a\x79\x8a\x78\x58\xf4\x09\xb0\xf2\xfb\x9b\x3f\x48\x17\xe5\x68\xc5\x2d\x9a\xbf\xe2\x16\x8c\xc3\x65\x0f\xc4\x3e\x0f\x99\x75\xfe\x29\xe3\x3a\xed\x1a\x7b\xf3\x0d\x86\x31\x15\x07\x90\x65\x0a\x3c\xb7\x8c\x36\x8f\x1a\xea\x9a\xc6\x0c\x5e\xeb\x96\x9a\x45\xf8\x4a\xa3\x73\x66\xa8\x39\x77\x19\x0f\x41\xae\x42\x1e\x0c\x46\xfd\xa3\xfa\x01\xb9\x26\xfc\xef\x82\x24\xfd\xa3\x6d\xf4\xf8\xa8\x77\x01\xfe\x79\xfe\x06\x28\xef\x0c\xc0\x2d\xf2\xbd\x78\x32\x07\xc7\xdb\x87\x11\x9a\x03\x69\xfe\x16\xee\xb3\x8f\xdc\x9f\xb3\x5d\x9e\x19\x5f\xe1\x4f\x8c\x10\x38\x20\x8a\xb9\x77\x00\xaf\x79\xf2\xe2\xe0\x54\x96\x83\x02\x07\xc7\xda\x8d\xbe\x8e\x9b\xb7\x3b\xc4\x71\xa4\x3f\x1b\xe6\x50\xfa\x92\x81\x9a\xeb\x5d\xc7\xee\xd7\xee\xd8\x17\x12\x70\xd2\x19\x25\x7d\x19\x61\x0b\x89\xd2\xd6\x2d\x3f\x5b\x64\x8e\x13\x9e\xed\xf1\xff\x74\xbe\x01\xa5\xef\x1d\x95\xf8\x12\x92\x26\x01\xee\x92\x51\x51\x57\xc4\xec\xad\xfa\x3e\xef\x9f\x2a\x67\x7c\x00\x3c\xa4\xab\x9b\x2c\x45\x47\x2c\xe5\x5e\x18\xf4\x0a\x21\xfe\x1b\x0d\x45\xb5\x0b\x50\xc5\x2a\x0b\x1a\x5d\x7c\x37\xd8\xeb\xc1\x5e\x02\x05\x84\xd9\xed\xd7\xb5\x65\x05\xf8\x20\x78\xe0\xf8\x99\x38\x91\x35\x01\x4c\x86\xd1\xe2\xed\x49\xf9\xcd\x31\x90\x76\x94\x35\x53\xa3\x12\xae\x05\xab\x33\x35\x26\xe1\x36\x71\x4f\x09\xa4\x02\xb3\xc8"}, -{{0x7d,0x7c,0xa8,0xe8,0xd3,0xb8,0x43,0x44,0xa5,0xe4,0xde,0xa0,0x8b,0x33,0x8d,0x8f,0xaa,0x5f,0xfc,0x11,0x9c,0xe5,0x66,0xef,0x65,0x6f,0x0f,0x45,0x84,0x77,0x5b,0x21,},{0x0b,0xde,0x34,0xb7,0x46,0xd2,0xc5,0x49,0x08,0x53,0x06,0x4d,0x48,0xc6,0xb4,0xc1,0xcb,0xbc,0x3e,0xe7,0xbe,0xff,0x5e,0x8f,0x68,0x4c,0x12,0x0f,0x31,0x5d,0x7e,0x4e,},{0xd0,0xc3,0xe2,0x48,0xa8,0xcb,0x2d,0xdc,0x7e,0x9f,0x21,0xc9,0xc5,0xb0,0x09,0xf7,0x0e,0xa2,0x9d,0xa6,0x89,0x7c,0xd9,0x2c,0x26,0x0f,0x04,0x7e,0xd6,0x8a,0xa1,0xc8,0xb9,0x65,0x7f,0x9d,0x82,0x6e,0x88,0xf4,0xa5,0x12,0xc5,0x00,0x3b,0xe6,0x40,0x68,0x80,0x74,0x12,0x63,0xae,0x7c,0xe6,0x86,0x0e,0xfe,0x73,0xad,0x54,0xd4,0x82,0x04,},"\x0b\x72\x70\x75\x34\x5d\x61\x9f\x5c\xdc\x7f\xc4\xc4\x3c\xdc\x19\x10\x58\x11\xd9\x5d\x06\x9f\x81\xc0\xa6\x2f\xe1\xe1\x17\x8c\xf1\xc3\x5d\xb0\x5e\x2d\xe8\x7d\x11\xae\x1a\x6f\x53\xef\x38\xb3\x9b\xf4\xed\x8f\xbf\x56\xef\x01\x7a\x1d\x3c\x15\xb6\x4f\xe4\xb2\x61\x0b\xf6\x9b\xd1\x9a\xc7\xaf\xd4\x6a\x2b\x87\xb4\x88\xb6\xc7\x8a\xd4\x56\x81\x1c\x1d\xd6\xbd\x4a\x6b\x5d\xa6\x98\x73\x9f\xd1\xa1\x4c\xeb\x9f\x27\xf1\x24\xb6\x9f\x6b\xd1\x6d\xe5\x53\x7a\xad\x80\x68\x1c\x56\x33\x58\x03\x94\xda\x3b\x84\xe9\xb7\xa5\x5e\xba\xb8\x52\x2d\x2d\x6b\xf1\xaa\x4e\x7b\x15\x9c\xbf\x4e\x20\xb5\x0b\xfe\x9c\x71\x1a\xa0\x47\x11\x9f\x1d\xad\x87\x49\x26\x0b\x87\x63\x9e\x9c\x14\x1d\xef\x62\x02\x6a\x99\x03\x73\xdc\xfd\x99\xf7\x7b\x0f\x5e\xa6\xad\xfd\x8f\x59\x4b\x9c\xe4\x10\x64\xa5\xed\x30\x7b\xf2\xd8\xd1\x73\x70\x49\x8a\xd7\xf4\x5f\x9c\x4d\xd2\x6c\x42\x0f\x45\x0f\x53\x62\x3b\xb6\xd7\xf3\xf4\x6a\x14\x9d\x8f\x13\x5b\xc2\x91\x33\x10\xfb\x8f\x90\x43\xd0\x99\x27\x8b\xbe\xba\x39\x17\x9f\xa3\x67\xb0\x16\x73\xe1\xc9\x53\xef\xfd\x2c\xae\xa7\x31\x1c\x47\xc0\x37\x27\x44\x09\x5b\x1c\x8f\x90\xee\xf5\xf1\x92\x9d\xb1\x99\x6c\xd5\x84\xf6\x15\xd5\x6f\xae\x3a\xec\xac\x3e\xe8\x8b\xd0\xb2\x96\xf4\x49\xcc\x27\x13\xc5\x2d\xa6\x95\x24\x8f\xaa\x8e\x38\x9b\x05\xa0\xbc\xac\x69\xdc\xe9\x71\x97\x23\x19\x4f\x43\x3b\x02\x97\xeb\x08\x59\x01\x9f\x14\x1a\x20\x7c\xe8\xcc\xb5\x98\x82\xca\xa6\xe1\x8f\x0b\x43\xbd\xdd\xb9\x0a\x0a\x85\xff\xd5\x77\xd6\x39\x4a\x1d\x80\x48\x94\x10\xf9\x2a\xfb\x85\xba\x50\x6a\xa9\xf3\xf4\x27\x44\x5d\x21\x22\x4b\x9c\xb0\x46\xc0\x5f\x1b\xac\xd7\xb7\x49\xfb\x7b\x10\x24\xd0\x92\xe4\xee\x4b\x30\xa4\x6e\xdf\x71\x84\x70\xc9\x94\x91\xc6\x8f\x48\x79\xd6\x2b\xfc\xe7\x04\x6d\x81\x38\xcb\xb9\xe7\x21\x29\x99\xa4\x49\x8b\x45\x5f\xc9\x0a\xc2\x83\xe9\x35\xde\x04\xdf\x6f\xc9\x99\xe4\x43\x4b\xe1\x10\x63\xd6\xe4\xee\x9e\x09\x6a\x87\xbc\x71\x6d\x2c\x81\x99\x16\xc3\x7a\x4e\x62\x98\xc4\x99\x45\x36\x6e\xc3\xf5\x00\x72\x0b\x06\xdc\x99\xd3\xd8\xac\x30\x3e\x6c\x26\x4e\x28\xa7\xc2\xd4\x19\xec\x62\x2a\x97\xa7\x11\x54\x4f\xb1\xf4\x73\x5b\x11\xf8\xbb\x1d\x7e\x2c\x81\x6a\x15\x62\x87\xb4\xcc\x0c\x65\xaa\xa2\x80\xb8\x37\x73\x7f\x0a\x84\xe3\x6d\xe2\xdf\x2f\xc3\xa5\x0d\xf9\x80\x91\x8f\xb9\xe5\x83\x4b\x42\xac\x0e\x0c\x72\x78\xd7\xfe\x8d\xb4\xdb\xde\xca\x01\x41\xd5\xfe\xf5\xdc\x61\x51\xf8\x7b\x86\x34\xc2\x41\xa8\xfa\x0a\x82\x71\x78\x99\x77\x3a\xe8\x9f\x53\x78\x90\xb9\x15\x5a\x7a\x05\xbc\xe4\x78\x66\xec\x20\x28\xa4\x78\x98\xd4\x85\x82\x3a\x2e\x99\x23\x19\x68\x0e\xb6\x99\xb0\xdd\x53\x58\xf5\x46\xfc\x53\x7c\x73\xd3\xa4\xb2\x23\xa0\x94\x15\x18\xb6\xd1\xe6\x6b\x27\x67\x6c\x1b\x1f\xc7\x6a\x08\x32\x05\x24\xa7\x2e\x29\x7f\xce\x17\xaa\x80\xd8\xea\x7b\x38\x8a\x55\x16\x8e\x7d\xad\xb8\x36\xe9\xde\xe7\x07\xed\x25\xc0\xee\x4d\xb2\x5b\xee\x3c\x48\x5b\x39\x64\x92\x04\xef\xaf\x28\x20\xb2\x73\x63\x68\xfc\x77\x3c\xe0\x90\xc3\x85\x37\x80\x02\xc4\x71\xb0\x94\x79\x5c\xb2\x66\xd3\x9e\xb7\x58\x0d\x70\x1b\xe4\xc8\x91\x6f\x6b\x38\xbf\xe2\x5f\xdf\x36\xd6\xc4\xad\xaf\xa9\xae\x98\x64\xc5\x7b\xb7\x37\xb4\x95\x06\xed\x38\xd6\x2d\xe6\x0c\xc0\x59\x9e\xc6\xbb\x1a\xcf\x24\xb1\xd3\x7d\x60\xef\xde\xb7\xd9\x42\xc5\x36\x03\xa2\xf0\x47\x6e\x95\x12\xc9\x38\xb2\x8d\x49\x5a\x6f\x26\xa9\x07\xc3\x96\xb8\x41\xae\xdd\x8e\x14\xac\x44\x7b\x49\x5d\xf1\xf6\x76\xda\xcc\xd5\xa7\x40\xc0\x42\xf5\x77\x2b\x7d\xb1\x7f\x4f\x1a\x3a\x1c\x8e\x7c\x48\x83\x70\xe7\x36\xb5\x1e\x69\x0f\xd2\xdd\xcb\x5a\xa6\x19\x57\xa7\xc7\x97\x5a\xcb\x2d\xcb\x91\x5d\x07\x4d\x74\x42\x79\xea\x1c\x41\x69\xf8\x68\x87\x3a\xc5\xc2\x08\x90\x16\x2c\x1d\xf9\x65\x64\x19\x97\x5a\x43\xd3\x19\x8e\x18\xc3\x09\xa1\xeb\x7c\x1d\x87\x87\x3f\xb1\x5c\x6d\xa4\x7f\x54\x8a\x01\xf6\x9b\xda\xb9\xc3\x9e\xf0\x0d\x41\x8a\x6f\x61\x9d\xd7\x3d\x7d\xb4\x5c\xbb\x6a\xd2\x25\xa2\xde\x78\x7b\xa7\x77\xbc\x73\xd2\x8f\xc3\x04\xf1\x00\x09\xf4\x02\x2c\x2c\xf8\x4d\xe0\x08\xd7\x0f\xcd\xc8\xba\x7f\x10\x7c\x36\x98\x59\xe9\xc9\x0c\xa8\xa3\x93\xb5\x53\xf2\x66\x05\xff\xd7\x23\x0c\x92\x14\x90\x70\x0f"}, -{{0xd2,0x1f,0xdd,0x7b,0x10,0xe5,0x4a,0x8b,0x6b,0xe9,0x5a,0x02,0x24,0xad,0x70,0x66,0x4d,0xd9,0x21,0x12,0xe2,0x68,0x3a,0x4f,0xd2,0x79,0xc4,0x07,0xdb,0x38,0x71,0xbb,},{0xf8,0x9c,0x27,0x2e,0x7d,0x1c,0xc9,0x3d,0x69,0xf6,0x94,0xde,0xc9,0xcc,0xe0,0x5a,0xc2,0x47,0x73,0x45,0x04,0x82,0x9c,0x56,0x99,0x74,0x13,0xc8,0x95,0x8b,0x93,0x30,},{0x6d,0x69,0xe8,0x3b,0x3e,0x7e,0xd5,0x5a,0x85,0xf9,0xfc,0x9d,0x25,0x19,0xda,0x0b,0x0a,0x1e,0xb4,0xda,0xae,0xe9,0x91,0xa6,0x65,0x1f,0x5c,0x89,0x19,0x0c,0x0d,0xe7,0x23,0x73,0xcd,0x98,0x9d,0x46,0xbe,0x13,0x67,0xf9,0xda,0xf1,0xb9,0x2f,0xed,0x3b,0x52,0xbb,0xa5,0x4a,0x1e,0x4c,0xca,0x5b,0xc8,0x72,0x6e,0xd0,0x7f,0x30,0x25,0x01,},"\xb8\x64\x4a\xdb\xef\x9c\x7c\xab\x91\x20\xac\xed\xc8\xe7\x5c\x43\x3d\x03\x6f\xfa\xe0\xf9\x55\xbe\x6a\x48\x8f\x1f\x42\x7a\x68\xa8\x90\x2d\x02\x6e\x63\xdd\x6c\x9b\xf9\xd9\x7d\xe7\x86\xb3\x1d\xd4\xf4\xc9\xa4\xf8\xa6\x22\xf1\xff\xc8\x4d\xa6\x96\x7c\xa7\x74\x33\xc3\x98\xf4\xd3\xf1\xc4\x43\x49\x89\xb7\xac\x9d\x0f\x3b\x1b\xe0\xc8\xb3\x52\x82\x4f\x4e\x7a\x08\x3f\x34\x2e\xc1\xbe\x1d\xa8\xfb\x75\x52\x42\xa6\x54\x88\x0e\xf2\x98\xf0\x59\x79\xff\x02\x6d\xdc\xc0\x44\x86\x0e\x67\x57\xa2\x9c\xfa\xa2\x22\xa3\x59\x7e\x38\xf1\x77\x99\x62\xa4\x1a\x4c\x8c\xe6\xa6\x5b\x87\x81\x99\xb4\xd8\x0f\x4a\x03\x90\xca\xc1\x9c\x22\x6e\xea\x4b\x60\x36\xe5\x7a\xd8\x30\xec\xfc\x00\x69\x3e\x26\x13\xd3\xed\xf4\x65\xfc\x8c\x4f\xa2\x93\xfd\x8c\xfc\x36\xdc\x8e\x37\xbc\xeb\xab\xec\x03\x49\xeb\xd8\x84\xe1\xb2\x8b\xce\x82\x4e\x0d\x55\xb6\xd0\x15\x38\x38\x01\x66\x8b\x34\xf5\xba\x72\x3d\x2a\xc0\xa2\x64\xfa\xb2\xc7\x28\x60\x8f\x16\x2d\xe0\x11\x79\x25\x9b\xe2\xcc\xb0\x81\x50\x02\xfd\xed\x8e\x0d\x78\xb0\x28\x07\x31\x3e\x91\x0e\xb3\xa7\x33\x7c\x53\x4e\x84\x6f\x9e\xe1\x55\x42\x6e\x4a\xef\x64\x36\x61\xb0\xed\xb4\x45\x96\xfd\xdc\xd0\xb3\xe8\x14\xc1\x37\x81\x7a\x42\x2b\xaa\x40\xc9\x05\x3d\x03\x86\xc6\xec\xdb\x58\x90\x52\x59\x47\x42\x67\x7c\x48\xdc\xfc\x8c\xd4\xa9\x36\x67\xed\x4d\x87\x64\x60\x01\xed\xa0\x79\xe8\xb9\x9d\x52\xba\x21\xc5\xec\x56\x69\xfe\xdf\x6f\x40\x44\x7a\x7f\xf8\x90\x1d\xb0\xef\x18\x47\xd3\xca\xcf\x01\x98\xa2\xf3\xbd\x7b\xcf\x2d\xd8\x11\xa0\x97\xfc\x5e\x51\x88\xb0\x3f\xdf\x54\xe5\x17\x63\x7a\x14\x50\x10\x00\xd0\xd3\x55\x16\xca\xf0\x69\x94\x02\xb4\x8f\x8d\x8c\xc3\xaf\xb1\x7a\x56\x13\x2d\x08\x23\x70\x35\xa0\xc9\x54\x90\xbf\xe5\xd7\xb7\xfb\x40\x17\x8f\x28\x1e\x4d\x87\x2e\x47\xa0\xe9\x55\xce\x97\x36\xf3\xc3\x33\xa6\xad\xf5\x0a\xd3\x19\x94\xeb\x9f\x45\x32\x7f\xac\xc8\xc5\xd1\x13\xfa\xd4\x71\x3f\xe7\xf1\x98\x01\x0d\x42\x04\x6b\xbf\xe6\x8b\x0d\xaa\x79\xdc\xb8\x75\x59\x29\xbe\x92\xf9\xca\xa1\x50\xdf\xbd\xe3\xfc\x9e\x39\x2b\x2b\x70\x1c\x30\x21\xc2\x40\xe4\x67\x9d\xe4\x11\x24\xb1\x88\x8e\x5d\xb5\xa8\x3d\x05\xce\xaf\x49\xeb\x44\x0d\xc4\x50\x26\xd4\x50\xbc\x98\x4b\x8d\x6f\x02\x85\x0e\xcb\x57\x0e\xee\x0a\x38\x19\xb1\x2b\xc2\x63\x67\xb5\xb9\x8e\x1b\x14\x1c\x9b\x0a\x96\x90\xea\x4a\x37\x00\xda\xd1\x23\x95\xf9\x75\xd1\x1c\xd7\x7f\x96\x36\x88\x31\xf2\x1f\x4e\x96\x8c\xc5\xba\x9e\xf8\x24\x74\x03\x8b\xc7\xaa\x26\x12\x2d\x21\x8b\x74\x30\x41\x50\x6a\xeb\xbd\x1f\x98\x79\x59\xfd\x16\x0d\x6e\xb7\xd5\x8d\x4f\x57\x6f\x8c\x0c\xa8\xaf\x86\x8e\x39\xb5\xea\x87\x20\x39\x37\xe0\x30\x8a\xcb\xea\xe9\x1e\x10\x60\x7e\x44\xe8\xab\x49\x5b\xc0\x1d\xd5\x73\xfb\xad\xc9\x44\x79\xff\x92\x08\x2c\x7b\xb7\x51\x34\x79\xc7\x0f\x04\x07\x76\x90\x25\xd3\x4d\x72\x14\x0c\x25\xd8\x21\xf0\x34\xa3\x98\x51\xa9\x3c\x62\x3b\x71\xc9\x40\x0e\x94\x26\x39\xf2\x8b\xbd\x03\x2e\x1d\x8d\x3c\x05\x9f\x7c\x2c\xd3\x1d\x74\x76\x46\x2d\x27\x76\x03\x5d\x07\x88\x02\x02\xdb\xfe\x9e\x07\xd1\x54\x62\x2d\x7a\xc6\x17\x5a\x5a\xfa\x79\xfe\xd4\xdc\xc1\x37\x12\x62\x0c\x41\x99\x4e\x11\xd9\x24\x30\x8f\xb2\xff\x3a\x1e\xda\x44\xc7\x61\xbc\x73\x6f\x34\x51\x22\xf0\x2a\x40\xae\x6f\x7d\xbd\x03\xd9\xfe\x96\xee\x3d\x7a\x3b\x4a\x5e\xef\xbf\xcc\x56\xdc\x42\xef\x27\xbd\x80\x85\x17\x60\x38\xb9\xeb\xae\x63\xaa\x75\x03\x52\x75\xec\x34\xe4\x18\x57\x39\xd6\x36\x24\x67\x70\xac\xcc\xc6\xdc\x62\x0e\x2f\xc9\x15\x6f\xa9\x48\x3e\x0d\x9c\xae\x0e\x8c\x46\x39\x48\xa3\xd9\x7a\xe8\xdd\xa5\x96\x6c\x88\xf0\x70\x93\x29\x2c\xce\x22\xbb\xda\x06\x2b\xaa\xfa\x7f\xe8\x4d\x0b\xa2\xd2\xdd\x29\x5b\x23\x45\x8b\xca\xeb\x2e\xf7\x42\xa2\xed\x1c\x83\x44\x83\xcd\x70\x93\x85\xaf\xea\xdc\xbc\x0a\x9c\x6a\x4f\x38\x7b\xab\xf7\xe3\xdc\x36\xc8\x10\xdb\x20\x9b\xeb\x66\xc8\x66\x64\x04\xc6\x61\xdf\xe9\xd3\x2c\x4c\x08\xaf\xc6\xf3\xb1\x25\x7d\x64\x84\xa7\x55\xf5\xac\x70\x1e\xb1\x3f\x87\x76\x3f\xee\x33\x0f\xfa\x04\x22\xcd\x80\xa9\x20\x38\xc6\xf4\x52\x92\xbd\xee\x5f\x89\xe9\x4c\x7a\x65\x21\x97\xfc\x19\x06\xb4\x82\x58\x37\x24\x49\xb1\x08\x1c\x6b\x97\x13\x4c\x43\xc8\x9e\xe2"}, -{{0xd3,0x36,0xfd,0x84,0x08,0x19,0x6d,0x22,0xfb,0x69,0x8e,0xb2,0x5b,0x76,0x54,0xfd,0xa4,0x6f,0x5d,0xe4,0xc9,0xb4,0xd0,0x49,0x50,0xc3,0x98,0xb5,0x9a,0x44,0x29,0x0a,},{0xf3,0xcd,0x96,0x34,0x7c,0xea,0x63,0xe5,0x00,0xa4,0xc9,0x2c,0x3b,0xf2,0x15,0x66,0x2d,0xd0,0x40,0x07,0x84,0xdb,0xf8,0xb5,0x95,0xdd,0x3d,0x39,0x5f,0x90,0xcc,0x12,},{0xaf,0x7e,0x2d,0xf7,0x52,0x9f,0xd1,0x8d,0x1b,0x21,0xb8,0xfd,0x4c,0x06,0x81,0x50,0x59,0x18,0xe2,0x51,0x14,0x34,0xfe,0x4e,0x49,0x54,0xe7,0x43,0xc1,0xcf,0xa4,0x5e,0x41,0x09,0xd3,0x6c,0x3e,0xec,0xf2,0xe2,0x5d,0x20,0x9b,0x9b,0x5d,0x25,0xf7,0xcb,0xc3,0x80,0x29,0x6d,0x64,0x77,0x52,0xe3,0x0d,0x3b,0xea,0x3b,0x92,0x9b,0x09,0x03,},"\xfb\x49\xc1\x9b\xc4\x44\x4c\x28\xeb\x26\x25\xf3\x1d\x99\x6d\x5e\x36\xc5\x7f\xa6\xfd\xd7\x72\xe6\x7b\x71\x99\xce\xc6\x7e\xda\x54\x51\x71\x2d\xf7\xa6\x9d\xbb\xd5\x6e\x7c\x39\x87\x96\xb2\x00\x1d\xef\x65\x1c\x4b\x9c\x05\xee\x31\xd9\x56\x79\x53\x5c\x81\x2a\x37\xd3\x1d\xdb\x30\x73\x19\x9c\xd7\x04\xff\x7c\xa2\x98\x1f\x7b\x9c\x92\x7a\x7f\x7d\x77\x6f\xb6\xf6\x09\xf7\x27\xe6\xea\x70\x9c\xe7\xf4\x3a\x60\x79\x35\x04\x16\x9a\x89\x05\xd9\xb2\x31\x09\xf0\xd8\x67\x96\x6a\xa3\xe3\x00\xc7\xe1\x1d\xde\xdb\x9c\xc1\x17\xb9\x04\xf6\x29\x27\xe4\x8e\x4d\x73\xfe\x1a\x6c\xec\xcc\x4c\xeb\x08\xe6\x4a\xb5\x5f\x25\xc9\x82\x16\xce\xc9\x37\x60\x8a\xd7\x93\x14\x69\x98\xf1\x4c\x29\x85\xe6\xc2\x91\x0d\xf7\xb1\x38\x8f\x9d\xd8\x63\xf1\xe4\xd7\xd1\x62\x14\x79\xb8\x51\x2c\xdb\x34\xe6\x73\xeb\x02\xa4\x89\x34\xe3\x9c\x2d\x18\xd7\x0f\x96\x6d\x67\x6a\x2b\xd7\x5d\xb5\x43\xd2\x5c\x5d\xcd\xc3\xef\x3b\x8b\xc8\x20\x18\x48\xc3\x09\x61\xe9\x15\xd9\x68\xbd\xc3\x19\x46\xb0\xd1\x8e\xde\x7c\xb0\x16\x6d\xbe\x1f\xfe\xff\x94\x39\xc9\xc3\x40\x4a\xf6\x01\x6c\x73\xed\xeb\x25\x3d\x93\xf5\x62\xa1\xa6\xcd\xd5\x78\x98\xa9\xb3\x42\x25\x87\xd5\xf5\x6a\xf3\xd0\x6b\x3f\x6c\x25\x75\x1f\x44\x46\x0f\xb3\x29\x96\x56\xdc\x11\x22\x7e\xf4\x83\x7a\xab\xdd\xee\x40\x0f\xa5\x3f\x69\xe5\xce\xd0\x53\xc7\x6d\xce\xcd\xf0\xad\xc9\xef\x80\xf4\xb3\x30\x54\x2f\xf1\xfa\x2d\xf0\xb8\xd4\x3c\xd1\xc3\x11\xb1\xb9\x95\x5c\x63\x2c\x8e\x5f\x04\x91\x93\x1c\x04\xde\x43\x4d\xf8\xf7\xa3\x94\xe5\xfe\xf0\x16\xdb\x2e\xb7\xc8\x7b\x2a\xc7\xa4\xa7\x30\x43\xbd\x7f\x98\xad\x0a\x4d\x45\x3a\xbf\xb0\xbe\x8b\xe4\xcb\x14\x57\x42\xaa\x56\xaa\x5e\xf2\xdf\xf1\x22\x30\xa5\x10\xe3\xb7\xf8\x2f\x78\x47\x70\x0e\xee\xa5\x90\x5b\x02\x89\x69\x6c\x4c\x14\x2b\xf3\x4b\xcf\x81\xa9\x62\xd7\x5b\x8d\x09\x10\x55\x73\x37\x79\x33\x5b\x7f\xd4\x7a\x20\xd1\x7c\x94\x8a\xb7\x32\x94\x78\x32\x67\x43\x71\xe2\x2e\x71\x11\x34\xf5\xc9\x19\x79\x23\x57\xf7\x9b\xf7\x0c\x44\x70\x78\x75\x28\x43\x4f\xc0\xb4\xca\x09\x3e\xe9\x25\x43\x42\x0d\x1c\xa8\x11\x24\xf5\x58\x53\x17\xe2\x50\x82\x1a\x4f\x3d\x8c\xe0\xf9\x19\xde\x9f\xbf\x01\x27\x08\x7e\x67\x69\x03\xf6\xcb\x39\x02\x5b\xcc\x73\xa0\x76\x29\x54\xb7\x2e\x66\xa6\xbe\x9b\x96\xc9\x7b\x6f\x60\x30\xbf\x5c\xa0\xbc\x27\x27\xa9\xa1\x79\xcf\x9d\x94\x05\xf3\xfe\x18\xf3\x49\x23\x89\x07\x9a\x5b\x65\xbc\xb1\x3a\x0d\x5e\xf4\x1c\x2c\xd9\x7e\x70\x2c\xee\x4a\x2f\xeb\x1e\x67\x02\xbd\x4c\x63\xfe\x0a\x4a\xe9\x94\xc4\x28\x7a\x83\x7b\xc3\xf6\x4c\x2d\x89\x88\x57\xcd\xb3\x2a\xcd\x4b\xd1\x33\x67\x6e\x51\xf7\x7b\xc7\x11\x0e\x3c\xe5\x2d\x92\x04\xfd\x26\x91\xa6\xd3\x70\x78\xf6\x8e\x7b\xce\xf3\x0f\xc9\xc4\x83\x98\x58\x22\xb6\x61\x11\x92\x38\xe4\x0f\x9c\xfd\xca\xbe\xf2\xd7\xb1\x6b\x05\x9a\xb2\x4a\xdc\x05\x00\x37\x12\xbb\xb1\x28\x09\x6e\x37\xf9\x1b\xc4\xc5\xc8\x15\x08\xbe\x27\xfa\x0b\x84\x94\x0b\xe3\x6b\xce\xd2\xe6\x5c\xd3\x6b\x39\xfb\xdc\x5e\xa6\x86\x14\x15\x92\x28\xca\x65\xc5\xd8\x40\x7b\xaf\x66\x3b\x52\x8e\x7d\x87\x73\x4c\x7b\xc7\x7d\xc8\x43\x1a\x1d\xd6\x87\x3c\xfd\xdf\xc3\xe7\x57\xd9\xad\x1f\xed\xd3\xc7\x98\xf1\xfe\x60\xe7\x15\xee\x48\xa6\xbc\xbb\x13\xb6\x16\xa8\x9a\x38\xe3\x36\x48\x9d\x3d\x6c\xcb\x72\x69\x14\x11\x2a\x1b\xc5\xd9\x77\xc9\xb2\xa3\xfa\xc1\x07\xad\x09\x4b\x03\x8a\xb7\x54\x68\x26\x3c\x34\xbd\xa8\x17\xc0\x56\xe0\x7a\x6c\x56\x69\x7c\xb6\x4a\x0b\x1f\x96\x6f\x6d\xe0\xbb\x1c\x0a\x71\xc8\xa5\xfe\x13\x3b\xa2\x03\x6d\x24\xda\xcc\xad\x3f\xa0\x3b\x39\xcd\x27\xf8\x32\x75\x27\x51\x05\x5a\x81\x55\x91\x3d\x04\x0f\x51\xda\xe7\x8d\x71\x94\x6c\xa0\x4d\x83\xc7\xc8\x94\xc2\x80\xaa\xec\x28\x55\x43\xe5\xfd\x5e\x32\x7a\xcc\xca\x9a\xbe\xf1\x56\xa1\x3b\x95\x71\x44\x6b\xd8\x00\x7f\xf9\x2d\xbc\x0f\xba\xf2\x3a\x94\x41\xb5\x3c\x1c\xd7\x40\xc3\x4c\x28\x29\x29\x10\x1a\xd2\xea\x8b\x85\xd7\x00\x52\x99\x1b\x77\x4e\x92\xff\x75\xcc\x85\x11\x3e\x09\x00\xb5\x1b\x86\x3e\x1f\x2a\xda\xab\x2d\xbc\xf4\x6a\xf4\x79\xea\x24\x8e\xc2\x88\x9a\xfb\xfe\x73\x74\x08\x39\x3a\x2b\x1b\x33\x01\xf6\x5c\x1f\xac\x8b\x67\x67\x95\xab\x5b\xf4\x47\xf0\x5e\x0d\xaf\x67\x76"}, -{{0x65,0x73,0x22,0x78,0x41,0xf6,0xf9,0x28,0x31,0x14,0x6c,0x44,0xc0,0xe4,0x80,0xcd,0xf5,0x44,0xbb,0x87,0x65,0x52,0xcc,0x5f,0x9d,0x42,0xf1,0x5b,0xdc,0xc0,0x44,0xb8,},{0x19,0x22,0x57,0xa5,0x4c,0xe5,0xd0,0x4c,0x19,0x43,0x9f,0xdc,0x9e,0xde,0x18,0xec,0x85,0x6e,0x29,0x87,0x0e,0x24,0xd3,0x73,0x1f,0xe2,0x22,0x47,0x99,0x94,0x9b,0x7e,},{0x53,0x8e,0xac,0xe4,0x93,0xde,0x53,0x38,0x4b,0x1e,0x98,0x5b,0xb9,0x07,0xc0,0x94,0xf8,0x16,0x84,0x30,0xda,0xb1,0x4d,0x37,0x79,0x1b,0xe6,0xe7,0x8f,0xf3,0xf5,0xa3,0x06,0xec,0x70,0xdc,0xac,0x86,0xd9,0x93,0xa4,0xc1,0xf7,0x58,0x50,0x78,0x6d,0x79,0x5f,0x02,0x2b,0x79,0xbe,0x6a,0x54,0x77,0x69,0xe4,0x15,0x69,0xc5,0xa9,0xa3,0x0a,},"\x6e\x7c\x6b\x12\x2a\xb3\x6b\xd1\x35\xf6\x9e\x2b\x85\xe7\xfc\xce\xfb\x07\x2c\x12\xcf\x08\x8a\x32\x29\xd8\x76\xef\xf5\x32\x38\x9f\x05\x77\x11\x6f\x7a\xf2\x9f\x11\x95\xe3\x82\x88\x39\x38\x13\x80\x46\x71\x78\xb2\x29\xc5\xa1\x8d\x7c\x49\x43\xec\x97\x0d\xd1\x8b\xce\x72\x3b\xd0\xca\x91\xff\xa9\x55\x63\x54\x6a\x32\x4f\xe0\xb9\xbf\x6c\x04\x55\xd4\x27\x60\x39\xe8\xd2\x91\xfc\x72\x76\xaa\x55\xa1\xcd\x3e\xa0\x52\x82\x65\x4a\x7f\x97\x00\xad\xcb\xc7\x80\x77\xc5\xdd\x0f\xc8\x6e\xce\xd4\x8f\x4a\x60\xcc\xb7\x6b\xfb\x8b\x45\x62\xba\xc2\x2a\x02\xd1\x9e\x44\x89\x39\x4a\xb9\x71\x9f\xc1\x44\xf5\xdb\x2e\xf0\x39\xb3\x7f\x3b\x51\xd1\xd6\x57\xa0\xcf\x83\x5d\x71\xf1\xa4\xaf\x01\xeb\x9f\xd8\x85\xc6\x04\xa6\x24\xcb\xe9\x10\xbf\xde\x09\x3a\xd3\xf0\xcb\xfd\x9a\x48\x30\x73\x29\xd4\x42\x34\xbd\x01\x19\x1d\x56\xe5\x22\xd7\x2b\x54\xe1\xfe\x47\x33\xda\x3a\xec\x68\x27\xea\xb3\x55\x48\x98\xe0\x3e\x57\x7b\x4e\x7b\x9d\xd3\xf3\x08\xe6\x16\x80\x8d\x02\x94\x49\x9f\x28\x86\x29\x5e\x54\xc3\x60\x19\x9c\xa8\x3a\x83\xff\x46\x19\x5e\xa3\xc4\x84\xa6\x68\x38\xd5\x1a\xcb\xe9\x61\x1e\xee\x03\x6a\xe2\x81\xc6\x79\x3c\xbd\x45\x1f\x92\x71\xfb\x5d\x25\xea\x7c\x18\x99\xab\x5d\x43\xed\x8b\x9d\x06\x7b\xc5\x6d\x8d\x4a\x15\xf1\xda\xb8\xd8\xd9\x5d\x1b\x17\xaf\x64\xcb\x18\xc1\x14\x75\x51\x14\x7a\xdd\xcb\xdd\x53\xfb\xcc\xd9\x02\x6f\x85\x55\x47\x13\x1b\xee\x95\x07\x16\x39\xf6\x49\xf2\xd0\x35\xa2\x5a\x3e\x42\xe3\x8e\x22\xbb\xf0\x38\x10\x6c\xe8\xbc\x4a\xd6\x76\x8a\xb9\x2c\xd5\x7a\xfa\xcd\x04\xee\x55\xcf\x07\x14\xb7\x68\x95\x2d\xac\x24\x0b\x1e\x9b\x28\x35\xec\xf7\xb0\xd6\xc4\x07\xc8\x25\x24\xa9\x23\xb9\xf5\x4d\x1b\x8f\x12\x56\x4a\x87\x21\x44\xef\xad\x3f\x3a\x7d\x23\x97\xcd\x12\x17\xdc\x5a\x9c\x96\xe4\x3b\x29\x60\xa8\x42\x5e\x97\xe0\x7a\x02\xb0\xda\xc9\x0f\x34\x6b\x91\xa3\x46\xa2\x3e\xd2\xbb\x7f\xe6\x91\x9c\x22\xdf\xf0\x3f\x62\xda\x7d\xba\x17\x6e\x8d\xdb\x22\xf3\xf3\xa6\x68\x89\x1d\x3f\x4e\x69\x54\x8d\x0a\xc4\xe7\x1e\x6d\x28\xed\x5a\x67\xab\x5a\xc6\x11\xd4\x60\xb6\x7a\x20\x1f\x4f\x56\xa5\x00\x3c\xa7\xa7\xd1\xcd\x1d\xb6\xc1\x00\x75\xb0\x92\x27\xcb\x8c\x5d\xc1\x66\x6f\x8b\xe7\x10\xb4\xb7\xbc\x2b\x95\xae\x60\xda\x4f\x64\x17\x9a\x50\xd2\xf8\x87\x44\x36\x15\x91\x67\x1d\x36\xb7\x29\x63\x15\xf6\x99\x64\x39\xad\x79\x82\x1d\xa8\xe7\x72\xdf\xbf\x55\xa9\x0d\x5d\x52\xef\x7d\x76\xb3\x5f\xfe\xbd\x42\xe3\x52\x5f\x45\x30\xc5\x4a\x0f\x23\xb4\xd0\x7c\x5f\x59\x74\x47\x0e\x89\x40\x4d\x17\x6e\xef\xf9\xef\x23\x33\x61\x96\x91\xc5\x9b\x7a\xad\xd4\x2c\x29\x6b\x1d\x0d\x32\x8d\x9a\x3b\xd5\x9a\x54\xbb\xa9\x3a\x0c\x1f\x1d\x62\x41\x8c\x21\x90\xc3\x81\x74\xb6\xab\xea\x02\xdb\x66\xe8\x18\x32\x0e\xc4\xb8\xba\xc1\xc1\x2f\x18\xf3\x0d\xad\xe2\x7e\x63\xc5\x8f\x9e\x7c\xaf\x4b\xf6\x9b\x26\x5a\x2f\x9d\x91\x80\x08\x61\xac\xf4\x79\xe6\x5e\xc1\x7e\x68\x05\x77\xe0\x58\xcb\x16\xc1\x09\xbc\xf9\xb2\x90\x9f\xce\x33\x61\xa2\xc2\x68\x5c\x10\xbe\x85\x40\xa1\x22\x2d\xb5\xec\xf0\xcc\x4d\x53\xa4\x21\x4b\x7b\xf6\x24\x8a\xdc\x3a\x86\x1e\x34\x84\x1a\x37\x79\xc4\x60\x46\xc5\x36\x4f\x1e\xa9\x1a\x78\xc9\x70\x0d\x46\x2e\xcf\xaa\xe3\x6b\xa7\x60\xc1\xbd\x6a\x23\x7c\x96\x1e\xdf\x40\x22\xce\xde\xfe\x5e\x93\x7b\xbe\xd7\x05\x1a\xe6\x1b\x96\xd0\x8b\x04\x87\xce\x05\x68\xff\x0d\x32\x74\x0b\xbd\x49\xad\x0d\xb8\x6e\x09\x10\x2a\xb2\x1a\x91\x56\x16\xe9\xdf\xdd\xc8\x1e\xbf\xb3\x6c\x90\x3e\x07\xa4\x0c\xd2\xdd\x11\x9f\xf4\xa5\x0b\x93\xfc\x6f\xdf\xc0\xf3\x6e\x59\xe0\x14\x8f\xcf\xf3\xfe\x8e\x2c\xd6\xd3\x0a\x9e\x4b\x8f\x01\x55\x67\xd1\x18\xb6\x27\x4e\x1e\xd7\x5b\x22\xe4\x4c\xa9\xd9\xdb\xfc\x16\x07\x42\xcf\xac\x58\x1e\x1a\x0b\xf5\xff\x33\x26\xbc\x5f\x78\x96\xb9\xca\x05\xa8\x11\xd5\x5e\x97\xc8\x34\xd3\x7a\x64\x95\xcc\x26\xcf\x44\x2b\xd2\xd9\x01\x29\x89\x5e\x9c\xc0\xed\x01\xe2\x15\x52\x93\xf4\x7a\x07\xab\x58\x80\xc6\xca\x29\xed\x44\xd9\xcc\xbc\xaa\xda\x7f\x3e\xb6\x04\x02\x18\x14\x88\x65\x4e\x04\x91\x15\x78\xb1\xaa\x9c\xdd\x4b\x86\xb0\xdd\x24\x50\xdf\x3a\x43\x08\x1e\x41\x10\xab\x58\xde\x76\x39\x24\xd3\xc8\x91\x52\xe9\x92\x93\xe6\x38\xf9\xac\xd8\xd7"}, -{{0xa6,0x3c,0x1f,0x54,0xb2,0xca,0x05,0x8f,0xed,0x2e,0xe2,0x50,0x4b,0x98,0x3f,0xf3,0x3d,0x57,0x0a,0x9b,0xab,0xa5,0x83,0xc0,0x86,0xce,0xfe,0x19,0xf4,0x3e,0xc4,0x9d,},{0x32,0x9b,0x86,0x6b,0xca,0x41,0x94,0x29,0x7f,0xc1,0xad,0x5a,0x0e,0xba,0x0d,0xf9,0x56,0x69,0x9c,0x74,0xab,0x7d,0xa5,0xfa,0x54,0x62,0xbd,0x06,0x61,0x47,0x10,0x20,},{0x28,0x33,0x59,0xbe,0x41,0x29,0x0a,0x51,0xe6,0xa7,0xc5,0xd5,0x72,0x5c,0xa4,0xea,0x0a,0x68,0xf1,0x4a,0xca,0x14,0xb0,0xf0,0x25,0x66,0xde,0xe2,0x1f,0x49,0x0d,0xa3,0xc7,0xe9,0x5f,0x7a,0xb7,0x39,0xbc,0x35,0xa7,0xf4,0xf2,0x32,0xe9,0x71,0xaa,0x15,0x76,0x57,0xa6,0x33,0xeb,0xa0,0xe7,0x2d,0xc9,0x7a,0xf3,0x2c,0xdb,0x92,0x87,0x02,},"\x79\x1b\x86\xfd\x58\x77\x13\x47\x8f\x92\x34\xff\x30\xce\xfc\x12\x3c\xd7\xc3\xeb\x12\x5f\xa7\x4e\x4c\x6d\xb6\x4e\x78\x44\xf7\xc8\x5b\x16\x86\xe7\x1e\xd0\x8d\x1a\x6a\x04\xe0\xeb\xbd\xff\x4a\xb1\x60\xc9\x76\xc8\xab\x9b\x50\x5f\x6a\x7e\xb0\xa1\x84\x27\xe9\x99\xa8\x82\x8d\xf1\x06\x84\xf8\xc7\x5b\x6a\x6b\x0a\x64\xc0\xaf\xa4\xbb\x22\xbe\xd1\xcb\x93\x25\x35\x9c\xac\x3b\x8c\x50\x8d\x98\xbc\xb0\xeb\xcd\x74\x8d\xc1\x32\xf1\xd6\xa3\x60\xa4\x45\x0d\x12\x92\xa1\xfe\xfc\x4e\x57\xe4\x10\x7a\x22\x3f\x42\x1e\x7d\x14\xa3\x84\xb8\x5c\x18\x84\x4d\x0b\x9e\xed\x2e\xcb\x81\xbb\x74\xe8\xa1\x26\x52\xd9\x85\x05\x79\x5a\x01\x31\x16\xa7\x07\x6c\xcb\x54\x93\xd6\xa7\x11\xf7\x63\x7e\x97\xa7\x80\xe7\x4d\xa1\xb3\x9b\x15\xcc\x7b\xbd\xe2\xe6\xc4\xd0\xd3\xe8\x30\x05\x97\xc8\x36\xe8\x0b\xcb\x8d\x80\x81\xd9\x74\xe0\x24\x32\xea\xc8\x83\x68\x21\x1d\x3a\xaa\xe8\x9a\x14\x41\x71\x08\xe1\xff\x67\x37\x08\x38\x49\xc6\x25\xb4\x0d\x63\x1f\x6c\x83\x57\x22\x0c\x7f\x37\x38\x0b\x3b\x2c\xc5\xd0\xe2\xdf\x6b\x4d\x11\x96\x57\x9d\xbc\x57\xb6\xc9\xea\x0d\x41\xf4\xfa\x0e\x55\x6f\x94\x3c\x94\x48\xef\x42\xfc\x78\xdf\x59\x96\x64\x8c\xe2\xf3\xde\x04\xd8\xa6\x63\xf9\x67\xf3\xd9\x33\xd4\xf6\x53\x57\xab\x29\xba\x5b\x64\x05\xfb\x16\x29\x72\x57\x8d\xdb\xb2\x36\x7b\xed\x14\x3c\x85\x4c\x10\x88\xde\x92\x1d\x79\xf5\xa9\x2a\x85\x48\x37\xeb\x77\x02\xe1\xba\x92\x5c\x6e\xac\x23\xd1\x34\xba\x1b\xaf\xc5\xd4\x6d\xe2\xa1\x94\x2c\x7f\x36\x6f\x70\x1b\x0a\xfa\xbb\x75\xcb\x1d\x80\x8e\x1a\x1e\x4e\x3a\xe5\xde\x88\xe8\xe9\x98\x97\x57\x45\x8b\xdd\xd8\xa8\x06\xc1\x10\xcc\x3a\x73\x3d\x1d\x4a\xc5\x8a\x40\x5c\x4d\x81\x13\x4f\xbc\x24\xcc\xde\x7d\x5a\xfe\x42\x0f\x9f\x17\x85\xf0\xa5\x02\x0f\xaf\xbb\x22\x61\x22\x25\x08\xaa\x05\x28\xb7\xb4\x8b\x56\x72\x00\x95\x84\x25\xef\xcb\x42\x93\x4a\x88\x0b\x13\x34\x44\xbb\x10\x9f\x2a\x95\x4c\xfa\x35\xa2\xd1\x7c\xb0\x5e\xe3\xf1\x6d\x06\xb3\x21\xa1\x5f\x91\x33\x9a\xbe\xda\x24\x3a\xd6\xc0\x91\x9f\xac\x51\xe9\x07\xe0\x53\xfd\xee\xd1\xcf\x03\x00\x37\x34\x13\x77\x93\x94\x1b\x8a\xdf\x9a\xb6\xaf\x81\x9c\x24\x5d\x6d\x56\xf1\x69\x64\xc8\xa7\x5b\x07\x56\xa8\xcb\x0c\xa8\xc1\x2a\xc6\xe6\xb3\x94\x2e\xeb\xec\x2f\x86\x88\x35\xf8\x1b\x10\x9d\xb4\x98\xa4\xca\x2e\x02\x1f\xa7\x65\x60\x8d\x23\xd8\x03\xde\xdc\x9e\x51\x45\x3f\xc1\xd2\xa6\xa3\x8a\x4a\xab\x25\x7c\x0f\xe7\xd6\x7d\x32\xa5\x41\xe0\x14\xb6\x0e\x10\x13\xa9\x2c\x1b\x3a\xd9\xe6\xf1\x1b\xe2\x93\xb2\x46\xf9\xa0\xc6\x44\x0b\x0b\x54\xfe\xe7\x5f\xed\x2f\xb7\x5c\xc9\x1e\xcb\x32\x73\x8c\x49\x58\x31\x58\x6a\x11\x24\x2d\x87\xdc\xb4\x88\x3e\xdf\x67\x57\xa5\x0b\x18\x84\x37\x59\xb9\x8d\xd0\xce\xf4\xa3\xfe\x10\xd7\x63\x70\xec\xda\x8c\x83\xfa\xb8\x7e\xee\x26\x56\xc5\xf2\x61\xc3\x40\xea\x91\xa5\x60\xd0\xe2\xc6\x42\x89\x26\x7f\x00\x36\xba\x35\x94\x48\x00\xa5\xa0\xae\xf3\xf1\xdf\x83\x9a\x72\x4e\x18\x1d\x79\xb8\xa3\xc1\x6f\x65\xae\x27\x95\x3c\x4a\xae\x8c\xcd\x30\xff\x5a\xcc\x4b\x31\xe4\x76\x5c\x68\xfb\x38\x31\x9f\x10\xac\xf8\x92\x47\xb5\xa3\x9b\x3b\x08\xa1\x91\x75\x4a\x24\xac\xa9\x59\x6a\x1f\x8a\x70\xb6\xe4\xf0\x3a\x20\x04\xa9\x08\x6f\xf6\xed\x07\x65\x2a\x92\x6e\x1e\x2d\xf7\xbd\xcc\xd5\xbe\xc1\x6e\x5c\x4e\x96\x83\x64\xa0\x9a\xbf\x9d\xed\x93\xdf\x5f\xca\x0b\xcc\xa5\xc8\x12\x97\x6e\x5c\xfb\x3c\x34\x93\xfc\x17\x5d\x1d\x92\xee\x8d\x1c\x98\xfb\x33\x82\xb3\xab\x90\xc5\xc0\xe4\xbd\xf6\xa3\xac\x94\x76\x7b\x68\xd4\x7e\x6b\x9c\x24\x42\x65\xe3\xb1\xab\x06\x23\xa8\xf0\x10\x02\x73\xf2\xc6\x07\xde\x89\x61\x2c\x72\xd3\x9b\xe4\xc0\xb4\xd7\x7a\x3c\x61\x36\x8d\xf4\x0b\x36\x08\x65\x29\x89\xd1\xe1\x9c\x0a\xaf\x0e\x3c\x25\x3e\x56\x2c\x64\x09\xfe\x64\x48\x92\x9b\x33\x75\x3d\xe1\x62\xe6\xde\x5b\xd4\x66\xa5\x11\x4f\xc0\xe5\xf5\x71\x02\x75\x5e\x29\x54\x4f\x03\xb2\x8d\x4f\x78\xde\x9a\x02\x4d\xd4\xc4\xe8\xc3\xc2\xd4\x41\x15\xa7\xae\x15\xed\xb4\xf5\x58\xaa\x7d\xba\x64\x26\xe7\xe3\x72\xc5\x4f\x79\x40\xbd\x77\x14\x46\x7f\x8c\x3a\x1a\xdd\x3c\x64\x01\x89\xc3\x16\x60\xd8\xcc\x01\xd3\xc5\x38\x2e\x42\xab\xc1\x04\xc7\x23\xf9\x48\xa8\x04\xca\x85\x30\x47\xb6\xb8\x7b\x5b\x6e\xf4"}, -{{0x5b,0x67,0xa6,0xd7,0xc6,0x50,0xdd,0x92,0xdd,0xd0,0x36,0xce,0x7a,0x30,0x5b,0xc9,0x59,0xa4,0x97,0xc5,0xe5,0x15,0xa6,0x84,0x93,0x03,0x5c,0xb3,0x85,0x0e,0xe0,0x3d,},{0x4c,0x6f,0xc1,0x64,0x05,0x05,0xfb,0x46,0x66,0x9f,0x93,0x04,0x8f,0x8e,0xf5,0x57,0x09,0x9f,0x3f,0xd9,0x2a,0x53,0x06,0x4b,0x16,0x33,0x63,0xa3,0x1b,0x7f,0x00,0xaa,},{0x0f,0x07,0x3c,0x9a,0x58,0x6f,0x6f,0x5e,0x08,0x38,0x9a,0x2a,0x5e,0x18,0x08,0xe2,0x70,0xf0,0xed,0xb6,0xaf,0x10,0x44,0x96,0xf9,0x37,0x57,0x62,0x3f,0xea,0x53,0x13,0x3a,0x73,0x1c,0x44,0x5a,0xc2,0x35,0x78,0xcd,0x56,0xa3,0x88,0x3c,0x08,0x95,0x86,0x68,0x63,0x1f,0xed,0xf1,0x44,0x6c,0xe3,0x4f,0x85,0x7f,0x90,0x82,0x2b,0xa8,0x0a,},"\x62\xcc\xde\x31\x77\x2c\x57\xe4\x85\x3a\xaf\x2a\x81\x81\xfd\xb5\x3f\xb8\x27\x90\xea\x65\x01\xbf\xc8\xf5\xd4\xae\x8d\xbd\x52\xde\x42\xce\x2e\x89\x61\xac\x17\x31\xf4\xbc\x08\x5f\xb5\x61\xef\x09\xa2\x44\x29\x70\xb6\x29\x79\x01\xae\xaa\x2e\xe5\x55\xb7\xd5\xe3\x95\x1c\x7c\x35\x12\x39\xdd\xee\x95\xff\x54\xf9\x24\xda\x95\xca\xe7\xb1\x5b\xa6\xa9\xa1\x33\x7b\x8c\xe4\x92\x1e\xd9\x13\xcd\x79\x1c\x1c\x69\x41\x08\x0e\x54\x8f\x3c\x36\xe8\x45\xac\xbf\xd8\xd8\xce\x35\xe2\xfd\xc2\xa2\xad\x6c\x7e\x24\x61\xbf\xcb\xf1\xaa\xbc\x55\xcf\x0f\xae\x42\x88\x85\xbe\x5e\x86\x53\x33\x08\xc9\x75\x68\x05\x21\x9a\xbd\x7f\xfc\x16\x57\xb6\xf4\x63\x29\x20\xa0\xc1\x0e\x0e\x36\x33\x19\xd9\x00\xfc\xd6\x1e\x7d\xdb\xcd\x6e\x76\x2a\x7d\xb9\x24\x80\xc3\x63\xb2\xc0\x64\x0c\x6b\xf3\x2d\x69\x0d\xd8\x29\xd8\x40\x5f\xa6\x6e\x47\x83\xeb\xe1\xcb\xde\x95\x47\x95\x4a\x90\xba\xad\x9f\x77\x4e\x94\x54\x9a\xbb\xff\x2c\x1f\x5c\xae\xc2\xbf\xd2\x8e\x41\x5d\x36\x42\x9d\x58\x51\x8c\x3e\x17\xe8\x69\x9e\x19\x89\xd4\x7b\x8d\x62\x7e\xf9\xab\x4d\x1e\x7d\x12\x0b\x37\x2c\x21\x41\x30\x4f\x7f\xab\xd0\x26\x5b\x8b\xe4\x1f\x54\x67\xf4\xde\x9e\x65\xc1\x25\xee\x1f\x27\xa2\x89\xc4\xf7\xc9\xa1\xfb\xf2\x5b\xfc\x2f\x8d\x30\x8e\x7f\xf5\x21\x91\xcb\x76\x44\xc6\xaf\x20\x45\x22\xf2\xac\x87\xb5\xf4\x05\x25\xfd\x43\xd3\x08\xc8\xdb\xc6\xa8\x61\xd2\x5d\xb2\x3e\xe2\x76\x67\x8a\x1b\x6e\x8e\x91\x28\x3b\xe0\x24\x70\x48\x2e\xd6\xcc\x9f\x6e\x39\x63\x51\xd1\x1b\x1c\x7e\x22\x32\x9c\x09\x1f\xe7\xd3\x68\xf6\x06\x53\xf9\x3b\x0f\x6a\x3f\x71\x2c\x20\xf9\xd2\xd8\xa9\xa0\x81\x98\x72\xf0\xc7\x1d\x7b\x1c\x0b\xc1\x68\x3a\x15\x2b\x48\x4b\xc2\x1c\xf5\x56\x09\x3a\xb4\xc0\xac\x16\xd3\x22\xff\x0b\xf4\x52\xe5\x58\x1e\x1e\x72\x41\x67\x38\x84\x02\x3c\x7d\x6e\x17\xe2\xde\x80\x59\xf6\x0e\x4c\x18\xe1\x3b\xd5\x5f\xcf\xee\x62\x3f\xd0\x46\x9c\x0d\x09\x11\x61\x1d\x09\x9a\x25\x70\x20\xf2\xf3\x1b\xf5\x07\x8e\x6e\x65\xa1\x35\xd5\xbf\x40\x76\x20\x23\x6d\x6c\xc7\x59\x31\x0f\xa7\x28\xff\x8b\xb5\xec\x56\xab\xbe\x1a\x3c\xd1\x51\x53\xf8\x92\xd9\x58\xd3\x0d\x16\x2d\x01\xee\x66\x5f\x5b\x56\x27\x81\xd8\xdc\xf8\x42\x80\x59\xe5\xfd\x22\x5a\xd7\x8a\x99\xea\x76\x0f\xe5\xd9\xee\x82\x19\xc9\x5a\xcb\x18\xd0\x56\x22\xe1\x0a\x9b\x6c\x67\xf6\xd4\xf6\xed\x11\x63\x5c\x5e\x2e\x0f\x85\xdd\x5d\x3c\xbd\xa6\x5a\xa4\x23\xd5\x94\xa8\x0b\x40\x42\x7b\xc3\x21\xe0\xee\xf9\xaf\xd2\xbc\x87\x46\xab\x73\x99\xff\x6d\x0e\x12\x87\xb6\x61\xdd\xc4\x06\x2d\x07\x20\x18\xf4\xc1\x0e\x86\xcf\xae\xd7\x2d\x9e\x68\x6e\xd0\x9d\x52\x55\xd3\x60\xe3\xee\xa2\xc2\x9b\x9e\xae\xa0\x5f\xc7\x8c\x8c\xdb\x8c\x9d\x4a\xfc\x7a\xdc\x6d\x4a\xa0\x67\xb7\xab\xfb\x0a\x4e\x94\x0a\x77\x58\x0e\xc2\x06\x45\x6c\xb9\xe9\xf9\x5f\x6d\x56\x5d\x53\x6e\x53\x5a\x16\x7e\xde\x8e\x20\xec\x36\x08\x1e\x2f\xc5\x5a\xef\xaf\x24\xd2\x27\xff\xfe\x5e\x6c\xb0\x30\x93\xf4\x43\xb4\xc5\x16\x55\xd9\x1c\xa6\xf2\x75\x95\x9d\x1a\x80\x2a\xde\xab\x44\x70\x1b\x31\xe8\xb0\xfd\x02\x22\xc4\x99\x96\x6c\x72\xd1\x02\x0a\xd9\x37\x0e\x28\x02\xbe\x04\xc9\x93\x3f\x6b\x77\x4f\x6e\x8c\x69\xfc\x0b\xfd\x31\x59\x39\xa1\x27\xb4\xe0\x6d\x0f\x6f\x5e\xde\x67\x1c\xe1\x16\x12\x12\x6b\x51\x87\xb5\x33\x29\xb0\xa9\xcb\x7d\xa3\xb1\xcc\xd6\x7b\x8c\x07\xba\xb9\x9a\x66\x2d\xf8\xce\x85\x1f\x50\x2f\xc4\xe1\xed\x16\x32\xb6\xba\x55\x55\x44\x01\x8f\x75\x27\xe3\x62\xef\xc7\xe3\xb2\xba\x6f\x75\xa1\x25\x4f\x42\x8b\x3b\x7e\x0b\xea\x69\x54\x9e\x7f\x9c\x73\x62\x75\x55\x00\x80\xae\xe3\xaf\x59\x14\xe3\xa3\x4b\xe6\x56\xc7\x7f\x6b\x29\x42\x0e\x54\x33\xf3\xdf\xf3\x81\x1f\x35\x28\x20\x8e\x9d\x85\x0a\xa3\xc2\x9b\x0f\x77\x8a\x24\x27\xd5\xfd\xe3\x07\x32\xdf\xe5\x04\x43\xa9\xc1\xad\x55\xc7\x2a\x08\xab\x26\xff\xaf\x8e\xfb\x90\xbc\xaf\xd3\x72\x6b\x00\xc0\x05\xc8\xc0\xf0\xdb\xf2\xa1\x35\x30\x86\x72\x1e\x44\x65\x45\xb8\x13\x44\x11\x94\xa7\x55\xfd\x26\xb9\x63\xaf\xd9\x77\x27\x8d\x1b\x10\xf0\x90\x01\xc7\xed\x97\x54\x03\xc1\x5c\xbe\x7f\x99\x2a\xb0\x7b\x84\x70\xc9\x39\xf8\x66\xf4\x20\xf7\x7d\xb7\x79\xaf\x83\x97\x00\x32\x9e\x07\x77\xa6\x11\x63\x65\xd7\x6c\x36\xd0\x9d\x86\x04\x72\xa5"}, -{{0x26,0x31,0xc8,0xc3,0x4d,0x29,0x48,0xdd,0xd5,0x99,0x6b,0x41,0x49,0xce,0xfd,0x23,0x8e,0xa7,0x45,0x2e,0xc2,0x2e,0x24,0x61,0x24,0xdf,0xa2,0x79,0xcc,0xc2,0x7d,0xb8,},{0xc3,0x90,0x67,0x86,0xff,0xb8,0xa7,0xc2,0x7c,0x44,0xc2,0x44,0x7f,0x9d,0xde,0x7d,0x66,0x6d,0xfe,0x58,0x8c,0xfc,0x54,0xf2,0xd2,0x50,0x40,0x51,0x2a,0x37,0x1b,0xc1,},{0x0a,0xdc,0x6f,0xa4,0x0f,0xfb,0x81,0xf6,0xef,0x4e,0x41,0x87,0x55,0x49,0x17,0x77,0x5c,0xf4,0x65,0xe7,0xb5,0xe8,0x57,0xf2,0xe1,0xe7,0xf4,0x00,0x97,0x71,0x06,0xd2,0x37,0x7e,0xbc,0x76,0xab,0xb1,0xdb,0x92,0x4c,0x64,0x86,0x7e,0x3c,0x6f,0xe3,0x8c,0x0b,0x4f,0xcb,0x1d,0x0f,0x94,0x68,0xe8,0xfb,0x23,0x50,0x29,0xa8,0x1c,0xe6,0x04,},"\x6f\x9b\xdc\xe1\x44\x3f\x28\x56\xd4\xa2\xf2\x27\x82\x83\x50\x12\xb7\x81\x8a\x0e\x02\x0d\xbc\xc2\x2a\x82\x16\x58\x30\x5f\x13\x42\x34\xd1\x4c\xea\x63\x61\x00\xed\x89\x6c\x2a\x8f\xb0\xe8\x70\x48\xec\x6f\x8b\x31\x48\x4f\x78\xeb\x17\x10\x45\xad\xd7\x2c\x85\x71\x0e\xc9\xf9\xb5\xd4\x36\x23\x41\x7b\x56\x53\xbe\x86\xe7\xfb\xf8\xb4\xff\x91\x11\x0a\x80\x8c\xb4\x1a\xcf\x66\xd4\x36\xe8\x9a\x73\x7f\xae\xa4\xef\xf3\x54\x49\x60\xf1\x14\xb8\x33\xb0\xb4\xeb\xc2\xc1\x40\x70\xb0\xbf\xb7\xb0\x05\x7e\xeb\xb8\x42\xbd\x1c\x1e\xd4\x58\xad\x34\x28\xf8\xf7\x2a\x1d\x1d\xb3\xc4\xcb\x47\x97\xa3\x99\xd4\x7a\x1e\x6d\xb7\x4d\xcb\x2e\xe2\x4a\xe8\x15\x85\xcf\x66\xef\x6d\x9b\xd2\x23\xf0\xf5\x4b\xc8\xc1\xce\xc1\xbb\x44\x60\xbe\xf4\xff\xd3\x2e\xe8\x05\xc3\xca\x5e\xe9\x76\xff\x9c\x14\x55\x9f\x8d\x75\x66\x62\xa2\xbc\x19\xe4\xc5\x98\x54\x06\xa0\x73\x05\xc9\x95\x0d\x86\x6c\x9a\x79\xa3\xe5\xf6\xc5\x96\x97\x53\xa1\x70\xe0\xfc\x4c\xc0\x9c\x6d\x87\xa1\x2b\x44\xcd\xf3\xbe\x16\x23\x15\x9e\x90\xca\xb7\xa8\xa3\xe6\xf0\x1f\x26\x85\x95\xb0\x21\xb1\xef\x7d\x00\x76\x94\x77\x27\x0d\x55\x84\xc9\x12\xe2\x2a\x36\x74\x38\x27\x7f\x59\xdf\x20\xc5\x62\x0d\xd5\xbe\xaa\x9b\xb6\x0b\xee\x47\xf4\xaf\x52\x7d\x89\x29\x57\xb2\xd1\x2b\x67\x8b\x52\x79\xa3\xf8\x32\x64\x65\x4c\x0a\x0f\x8d\x21\xe7\x09\x66\x8f\x30\xfb\x6e\x68\xf0\x47\xd0\xd9\xa7\xc2\xae\x9a\x28\xf7\xcb\x9d\xbf\x18\xf6\x3f\xc1\x66\x1f\x07\xd3\x10\xe5\x40\xc7\x76\x31\xf5\xbd\xac\x58\x24\x68\x5d\x7c\x9a\xba\x0f\xe1\xd0\x94\x07\xa9\x66\x2e\xf1\x8e\xb3\xe2\x8f\xd1\xe8\xbc\x89\x26\x57\xbc\x38\x24\x3a\x2e\x64\x53\xbd\xae\xab\xb2\x79\x1f\xc5\x48\x95\x21\x29\x54\x57\xad\x04\x18\x0c\xa8\x71\xf6\x31\x87\x92\xbd\x15\xfd\x18\x00\xce\x59\xdd\x3e\xcc\x7e\x0b\x72\x97\x92\x67\xd8\x18\x3e\x80\x4f\xdd\x45\xda\xad\x84\xfc\x4c\xaf\xeb\x56\x1e\xa8\xd6\xa7\x4a\x7c\xde\x72\x2d\x96\x25\x3a\xb3\xe7\x5f\x0a\xdd\xe0\x2a\x61\xfd\x5e\x1f\x59\xcb\x1f\x5f\x1b\x2e\x05\x26\x43\x58\x9a\x9e\x4b\xe4\xdd\x6e\xe6\x45\x38\xcb\x0b\x10\x9a\x11\x3f\x30\xa5\x8b\x35\x65\x62\x40\x43\x66\x2a\xbe\x17\xf6\x0e\x31\xe8\x9c\x36\xc9\x95\xe0\x0a\xe0\x7f\x56\xa9\x11\x8a\x31\xae\xc2\x4a\xd5\x44\xbc\x96\x58\x11\x21\x8d\xf8\x27\xc1\x73\x0b\xb9\x04\xbb\x79\xb6\x86\x13\xf6\xc9\x94\x67\x9b\x69\x90\xd7\x75\xb5\xcb\x32\xdb\x97\x19\x4b\xd8\x10\x19\xbe\xa4\x1f\x3a\x7e\xef\x50\x1b\xf8\x49\x1b\x0e\xa8\x59\x38\x84\x52\xe3\xec\xbe\x16\xaa\x7d\x56\x91\x51\x0a\x66\x06\xc4\x93\xe4\xc2\x93\x96\x1b\xf4\x0b\x4c\xd3\x00\xd9\xd2\x2e\xa1\xa7\x72\x4c\x07\x8b\x8b\xab\x1f\xd1\x65\x04\xe9\x89\xb1\x36\xd9\x25\x1a\xc9\xf1\xed\x94\xa5\xe9\xac\xbd\x9c\x04\xf8\x05\x8a\xfe\x03\x04\x9a\xed\x8b\xa2\x9f\xa2\xe8\xfb\x44\xf8\xe8\xc0\x4e\x87\x27\xf3\x99\xe7\x35\xe6\xc1\x49\x6a\x91\xa9\xb2\xcd\x2a\xb0\x2d\x43\xb2\x85\xe9\xd7\x61\x02\x93\xb6\x74\x9d\xf1\x04\x4b\x30\xe2\xda\x99\xa5\x64\x42\x9a\x23\xe6\x8c\x96\xfc\xe9\x2b\x08\xa0\x0b\x7b\x74\x2b\xa9\x7a\x62\xee\x58\x77\x6d\x7d\xd5\x65\xa4\x90\x07\x1d\x4b\x19\xdc\x64\x8e\x03\x32\x9c\xc5\xc8\x25\xd3\x87\xeb\xa4\x9e\x2e\xff\x6c\x43\x41\x86\x5c\x46\x4f\x13\xf1\xbe\xb1\x82\x7a\x7f\x26\x8c\xc1\x5a\x98\x24\x80\xbf\x08\x4f\xe3\x65\x2c\x1b\x0e\x0b\x4a\xd2\x62\x55\x85\x9a\xbf\x1c\x8a\x7f\x9b\x3b\xef\x09\x8a\x94\x07\xfd\xea\x0a\x53\x9e\xb0\x08\xfd\xd7\x49\xfa\x01\x86\xcc\x01\x69\xd9\xd9\xe6\x8f\xe5\xe5\x4c\xac\x32\xce\x57\xb5\xc8\x4c\x2d\x80\x5e\xca\x39\xc2\xdb\xbd\xd2\xe0\x2f\x7d\x22\x88\x26\x71\x2f\xf4\xa6\x14\x11\xca\x0a\xeb\x6f\x01\xa1\xf8\x0e\xf2\x9e\xeb\x07\x1a\x43\x22\x2d\x94\x97\x18\x4b\xd8\x5d\x9e\x44\xb1\x66\xbe\x97\xcf\xd2\xa7\x32\xaf\x4a\x23\x34\x63\xd3\xab\x54\x3a\x7a\x3c\x7a\xec\x55\x56\x56\x56\x88\x40\xf4\xdf\xea\x21\x7f\x65\x53\xaa\x98\xaf\x32\x4c\x12\xb2\xc3\x21\x4e\xe7\x6e\xec\x70\x06\x70\xaf\x68\xc8\xc1\xf3\x69\x46\xef\xd7\xff\x09\x33\xe5\x45\x3f\x12\x8e\x97\x15\xfd\xb3\x34\x4a\xc1\x0c\x4b\xb7\xec\x8f\x10\xdd\xf5\xdb\x71\xf1\xcf\x0e\xfe\x40\xf7\x5e\x5b\x63\x34\xef\x8c\xf8\x42\x9b\x32\x91\xe6\xe4\xce\x37\x9c\x17\x8a\xff\xcb\xc6\x10\x30\xeb\x89\x6d\x74\x4d"}, -{{0x39,0x76,0x9a,0x66,0xf0,0xca,0x12,0x90,0xfd,0xa1,0x43,0x75,0xb3,0x5c,0x66,0x3f,0x6a,0x4b,0x2a,0xb3,0x60,0x71,0x79,0xab,0xd9,0x90,0x63,0xe2,0xef,0xa2,0xc6,0xa8,},{0xf9,0xfd,0x4c,0x19,0x1f,0x38,0xf1,0x21,0x90,0xd3,0x28,0x5e,0x20,0xc6,0xce,0xe5,0x4c,0xfd,0x6f,0xf3,0x15,0x30,0x0a,0x4e,0xfd,0xc8,0xa9,0x0e,0x80,0xaf,0x40,0x83,},{0x14,0x42,0xde,0xa2,0x80,0x7e,0x03,0x11,0x59,0xec,0x6a,0x41,0x2d,0x8e,0x07,0xbb,0x3e,0x29,0x93,0x08,0x09,0x0f,0x21,0x8f,0xa7,0xc1,0x0a,0x9c,0x50,0x68,0xef,0x9b,0x64,0xef,0x11,0xca,0x9f,0xb9,0x2b,0xe1,0xd0,0x21,0x6b,0x99,0x31,0x8f,0xf0,0xf0,0x3c,0xb8,0x71,0xcd,0x7d,0xd6,0x3a,0x38,0xae,0x17,0x02,0x31,0x3e,0x5b,0x25,0x0c,},"\xff\x4d\x89\x87\xe3\xfa\x36\x01\x2b\x75\x86\x73\x6b\x79\x3d\x65\x97\x54\x69\x8c\xd1\x2b\x65\xe5\xba\x9d\x75\x8c\xac\x16\x49\x28\x8d\x20\x22\x43\x77\x28\x3e\xa5\x42\x5d\xec\x10\xab\x99\x17\xd1\x8c\xd1\x3d\x1b\xdf\x4a\x76\x9f\x37\x04\x4c\x84\xfa\xa2\xa4\x49\xc6\x89\xe0\x04\xc1\x4e\x00\x5c\x49\xda\x41\x06\xff\x75\xce\x13\x03\x36\x1c\x6e\x3e\x34\xcc\xfe\xe7\x5e\xe9\xc3\x1c\xbd\x06\xa4\xbc\xdb\xb4\x2f\xd6\x49\xbe\x4d\xfc\xd6\x64\x00\x6d\x6a\x5f\x61\x07\x7c\x04\xa6\xa8\x1d\xb3\x6b\xe8\x6b\xa4\x2c\x29\x51\xf0\x51\xae\xda\x64\xac\xea\x49\x6c\xb9\x24\x98\x2b\x9f\x7d\x23\x4a\xc9\x72\x3f\xef\x98\xa8\xe1\x27\x55\xe3\x26\xa5\x2f\xbe\x35\x85\x1f\x41\x1e\xeb\x86\x76\x06\xd4\x5b\x51\x3f\x54\x52\x63\x91\xc5\x54\x63\x5c\x18\x0b\x8f\xd0\xee\x45\x1a\xfc\x96\xe4\xef\xd3\x60\xb6\x1e\x6b\xaf\x03\xdd\x6d\x19\xba\x51\x5c\x31\xec\x1c\xdd\x3a\xff\xff\xdb\x27\x35\x4e\x3e\x6b\x56\xe9\xe1\xa1\xa1\xb7\xd4\xb5\x7d\x9d\x76\x89\xbb\x2f\xea\x6c\x8d\x3f\x9c\xe0\xdf\x2d\x9e\xe9\x19\xc4\x23\x0a\x1f\x20\xb8\x5d\xfe\xfe\x1e\xa3\xd7\xf7\x7d\xb4\x70\xe4\x02\x24\x29\xef\x60\x9b\x0f\xf4\x49\x46\x44\x0a\xcb\x44\xcd\x13\x44\x5b\xcf\xa3\xf2\x05\x03\xc2\x6c\x2f\xb6\x63\xc8\x90\x65\xfb\x93\x34\xa6\x03\xeb\x9a\xb7\x15\x2e\x62\x62\x92\x33\xc4\x4c\xb0\x0e\x77\x71\x6d\x9b\x72\xc8\x4f\xd1\xb3\x40\x63\x4f\xf1\xce\xa3\x47\x50\x15\x76\x10\x0e\xcb\x0f\xd1\xbb\x76\xae\x0d\xff\x1c\x2b\x09\x48\xeb\x71\xee\x2c\xc3\x1e\x79\xd3\x01\x5d\x72\xdb\xee\x22\x4a\x98\x0e\x0f\x95\xa6\x9f\x79\x3d\xa8\x3a\x2d\xaa\x56\xef\xe5\x7b\x2f\x8c\xea\xac\x9e\x55\xf4\x43\xca\x9e\x73\x2b\x48\xc7\x5f\xac\x21\xc3\x6f\xa7\x72\x73\xc3\xf3\x48\x35\xff\xd8\x3c\x96\xf0\x0a\xc6\xe8\x6c\xff\xed\x08\x15\x36\x46\xc1\xce\xa2\x23\xda\x9c\xa3\x60\xca\xb9\x7e\x03\xb2\xb6\xc8\xfb\xa7\xc1\x95\xa3\x9a\xe5\x2e\xb2\xee\x86\x43\x00\xae\x56\xa1\x0f\x54\x7f\x99\xa3\x16\x98\x72\x24\x9f\x97\x77\x4b\x17\x98\x93\x55\x36\xf2\xf5\xf0\x11\xce\x57\x61\x3a\x94\xfc\xb7\xe7\x28\x6a\x6d\x49\xc1\x0f\xd9\x29\xd7\x67\x1c\xbb\x8c\xf1\x7d\xfc\xad\x4b\x24\x85\xc3\xd8\xfd\x79\x12\x87\x21\xe5\x5d\x84\x80\x87\x63\xc2\xaf\xa9\xc5\x5e\x3b\x0c\xd7\xbf\x2f\x0a\x66\xb5\xe4\x67\xbe\xc5\xee\x89\xad\x57\x0b\x60\xf1\x88\xb3\xf7\xb4\xa5\x11\xff\x85\x93\x12\xde\xd0\x78\xd8\xd0\x09\x11\x34\xfd\x49\xbc\x79\x2d\x2d\x7d\x60\xb3\x04\x94\x1c\x7f\x23\x20\x6f\x99\xe8\x63\xb1\xe2\xd8\xc9\xec\xff\xd2\xff\x0a\x3a\x3c\x75\x49\x85\x61\x5a\x9a\x92\xed\xce\xad\x00\xfe\x0e\x05\x49\x3b\x19\x8d\x1f\x7c\x90\x08\x84\x46\xbb\xa4\x60\x38\xa7\x1f\x32\x65\x3b\x59\x12\xb2\x4f\x43\x13\x77\x48\xb7\x5a\xec\x2c\x15\xfe\x4b\xf5\xa6\xf8\x6b\x8a\x6c\xdd\x9c\x74\x47\xf2\xeb\xb0\xf4\x3b\x01\xca\x15\x23\xe0\xd4\x96\x24\x00\x06\xad\x7f\xff\xfa\xfe\x0d\xf5\x75\x4b\x34\x2c\xaf\xf3\x55\x5d\x72\xa2\x7d\x0b\x92\xca\x16\x67\x66\x5c\xec\x43\xbf\xb5\x83\x07\x7a\x9c\x17\x41\xfa\x49\x2c\xe3\xdc\x2c\x75\x29\xcd\xed\x81\xb8\x28\x1a\x3f\x37\x59\x48\xb8\xa7\xce\xd0\x96\xb2\xfa\xcc\x25\xe3\x90\x29\xe2\x21\xb6\x6a\x53\xd3\x97\x9e\x1f\x40\x5f\xd8\x8a\xfc\x06\xec\x6e\x43\x09\xdc\x85\xe6\x9d\x6e\xf2\xb4\xb4\x92\x66\x16\x4a\x9d\x9d\x1c\x31\xee\x39\x21\x12\x7b\x13\x38\x1b\xfb\x74\x0d\xd3\x8d\xc1\xc7\x31\x59\x21\xf9\xc2\xfe\x58\xb6\x1b\x63\x1a\x7d\x9f\xde\x2d\xd8\xa4\xbe\x3d\xed\x04\x90\xae\x3b\x83\x76\x79\x19\x55\xc1\xc4\xb4\xfe\xd0\x0b\x9f\x4c\x38\xab\x73\x50\xfc\x2e\x37\xa3\x15\x0c\x18\x16\x2b\x1f\xaf\x03\x37\x89\x4b\xc2\x3e\x74\xf5\x95\xe4\xbe\x33\x46\x6d\xea\xb3\x54\x58\xbe\x97\xb4\xf7\x56\x58\x97\xf0\x68\x52\xf7\x1c\x60\xfe\xf9\x10\x1d\x72\x6b\x72\xe0\x10\x2a\x97\xb2\xca\x52\x11\xe3\x80\x68\x34\xb0\xac\x1a\x7d\xf8\x7c\x2a\x07\x8d\xf2\x63\xef\x8b\xa4\x57\xdc\x89\x1b\x7f\x2e\x62\x78\x11\xab\x62\x2b\x99\x46\xf8\xc6\xb7\x31\xf2\x40\x78\xd1\x7b\x06\xb2\x00\xc3\x44\x7f\x80\x32\xaa\x3e\x7a\x24\x3e\xe4\x22\xdd\xa2\xe6\x52\xfd\x75\x71\x3a\xfb\xce\x8a\x59\xef\x85\x36\x65\x3a\x48\xdc\xf4\x2a\x70\xe7\x62\x1f\x9b\x28\x02\x40\x9b\xe1\xc1\xa6\x1f\x32\xe3\x67\x89\xa5\xc5\x05\x5e\x1a\x82\x68\xe9\xdc\x43\x8c\x2e\x15\x27"}, -{{0x0c,0x80,0x8b,0x06,0x6f,0x0c,0x8e,0x8d,0xbb,0x1c,0x23,0xd6,0xc2,0xce,0xdd,0x0b,0xe8,0x66,0xd8,0x42,0x5f,0x24,0x1a,0x92,0x85,0x70,0x0e,0xa5,0x45,0x36,0xcf,0x6d,},{0x44,0xee,0x72,0x90,0x04,0x50,0xc5,0x6a,0xb2,0x1f,0x26,0x86,0xd2,0x95,0x25,0xd0,0x66,0x3e,0x0b,0xdd,0x87,0x72,0x5b,0xea,0xc5,0xd6,0x8b,0xac,0xeb,0x69,0xf1,0xd2,},{0x38,0xc6,0x82,0xce,0xde,0xfb,0x13,0xe4,0x6b,0x11,0xf7,0xb5,0xf8,0x00,0xcc,0x81,0x20,0xd4,0x5a,0x83,0xcd,0x8d,0x8d,0xec,0x10,0xc5,0x77,0xbb,0x01,0x53,0xd5,0x09,0xba,0x4f,0xdf,0x40,0x09,0x98,0x78,0x8b,0x70,0x60,0x07,0xce,0x16,0x2b,0x96,0x94,0x5c,0x71,0x40,0xbe,0xee,0x74,0xe1,0x9d,0x07,0x43,0xaf,0xa4,0xec,0xfd,0x25,0x0a,},"\xc9\x45\x71\x41\x00\x58\x1f\x4e\x24\xda\x11\xfc\x0f\x6c\x6d\x02\x10\x43\x3f\x97\x77\x52\x51\x24\xc5\x5e\xe0\x72\xd8\x5d\x79\x8b\x70\x5f\x9d\x31\xc8\xf9\x77\xdb\x6e\xdf\xb7\xa6\x5c\x78\xad\x2d\x7d\x31\xd6\xb7\xb5\xbe\x40\xff\x11\x78\xd3\x03\xb6\x83\x9b\xb0\xc6\x32\x10\xc1\xd3\x38\xc1\x03\xaf\xa0\xd4\x53\xec\xa1\xbc\xa2\x77\xd9\x30\x77\x8a\xd5\x08\x02\x27\x2f\x03\xdb\xe2\x18\x4f\xc3\x1e\xf8\xea\x6a\xbe\x21\x69\x97\x19\x9f\x7c\x1b\x33\x77\x37\x96\x89\x07\x27\x2a\xa5\x1b\xd4\x9c\x07\x38\x9c\x95\x46\x8c\xef\x4f\xd9\x9a\xe7\x8c\xa4\x54\x2a\x2b\xbc\x0e\x8a\xa9\x52\x14\xad\x1c\xff\xf9\xd5\x08\x5a\x43\x43\x94\x47\x3b\x84\xb7\x4b\xe9\xbf\x2f\x02\x02\xad\x1e\xe4\x61\x66\x04\xca\x1d\xd7\x5f\x4a\x19\x53\x42\xeb\xbf\x8f\xc5\x9f\x3f\x79\x61\x65\x54\xdc\x7b\xfd\xd5\x56\xbe\x43\x72\x21\xc1\x0b\xfa\xd3\x9e\x11\x9e\x06\x04\x5b\xe5\xfe\xd6\x83\xd3\x53\x4f\xb6\xcf\xed\x33\x89\x1c\x96\xf9\xc3\x30\xf2\x8b\x68\x4f\x8f\xba\xd4\x7c\x01\x41\x8e\xab\x6c\xee\xcc\x2e\xd7\x77\xf4\xc2\x18\xa2\x7a\xc2\x25\x82\x39\x23\x15\xc5\x3a\xa7\x30\x9e\xc5\x4c\x61\x75\x23\x6e\x44\x24\xdc\x97\x84\x65\xab\x62\x8d\x95\x44\xb0\xbe\x84\x10\x3e\xb5\x6f\x1b\xaf\xe5\xe5\xea\xed\x04\xc9\x8b\xfe\x2e\x8a\x24\x18\xc6\xc5\x2a\x61\xea\xce\x85\x23\x6b\x66\xc7\xb3\xb8\x70\x7e\xd5\x56\x41\xdd\x9d\x5d\xa9\x7c\x99\xc1\x1c\xbe\xb9\xaa\x2d\xb1\x47\x82\x0d\xc7\x24\x80\x0a\x9d\x80\xf5\x05\xfa\x5a\xf2\x09\x21\xca\xd2\x43\x56\x83\xbb\x4f\xc6\x0b\xdd\xd4\x75\xf8\x63\xe2\xf5\x95\x0d\x23\x63\x99\xd8\xd7\x5b\x40\x4b\x39\x4a\x54\x67\x37\xf9\x3a\x62\x40\x87\x00\xb3\xab\x3c\x1e\x92\x2b\x1a\x85\x9a\x29\x15\xc2\xd3\x53\x68\x81\x5c\xd4\x5b\x85\xb2\xac\x08\x31\x21\xff\x00\x0f\x05\x0d\xcd\xf4\x15\xe5\x27\x5a\x5c\x42\xda\xe3\xb1\x54\x00\xf3\xdd\xaf\x93\x39\xf2\x0a\x12\x61\xa8\x8c\xd9\x02\x05\x63\x97\x63\x21\x11\x52\xdf\x41\x4a\x9a\x6a\x62\x18\xf5\x6b\x35\xa2\xde\x9e\x84\x82\x44\x9f\x6d\xa7\x7c\x9e\x3d\x4a\xf0\x49\x30\x15\xa7\x26\x21\x7f\x82\xac\x58\x95\x4f\xe3\xe2\xe3\x44\x40\x35\x6b\x11\x2e\x06\xa6\xf6\x71\xfb\x5a\x6e\xf4\x61\x9a\x6e\xa7\xb4\xe0\x4d\xb3\x75\x7f\xb6\x64\xc3\x96\xb3\x41\xca\x89\x00\x1d\xc1\x60\x4b\x51\xfa\x91\x53\xf9\x13\x0c\x10\x20\xff\x88\x90\x92\x87\x82\x3a\xb3\x91\x5c\xcc\x85\xc4\xe3\x5d\xf6\xc2\xf8\xe6\xf9\x02\xbe\x82\xba\x21\x29\x7f\xd3\x83\x5a\xff\x5c\xe0\x2f\x3c\x07\xdc\x09\x3f\xcb\x1a\xba\x26\xe0\x6d\xfe\x6f\x02\xdf\x79\x29\x1a\xac\xa0\x69\xec\xab\x93\x81\x40\x4c\x9c\x3e\xa1\xad\x40\x9a\xdf\x29\x2a\x91\xe3\xa5\x82\xd5\xa7\xb6\x8f\xfb\xe1\x0a\x03\x05\x24\x8e\x09\x67\xe6\xdf\x37\x2f\x28\x1b\xd1\x92\xe1\x39\x97\x9c\x98\x66\xca\x8f\xe1\xe1\x0e\x06\x16\xdc\x2d\x4f\x85\xe1\x19\xe0\xcb\x4b\xfe\x8c\xc3\x1d\x9f\x5c\x01\x8b\x65\x40\x85\x24\x00\x0a\x30\x16\xa2\x3d\x99\x14\xd5\x7e\x95\x55\x76\xe2\x66\x0b\x0e\x0d\x96\xc8\x49\x5a\x12\xc3\xd7\x31\x22\xd2\x00\xb0\xf0\xe5\xeb\xd4\x46\x56\x2b\x08\xf4\x79\x34\xab\x49\x9a\x96\x99\x1d\xcf\x99\xc9\x6a\x62\x88\x07\x39\x84\x5d\x29\x82\x01\x50\x55\x3e\xae\x9b\xe0\xbb\x41\xd5\x3d\x3a\xf0\x1d\x98\x67\xbb\x47\x32\xc9\x0b\xf6\xe1\x37\x31\x6e\x3b\x1e\xdc\xc2\x09\xa8\xa0\x9f\xb0\x62\xa6\xef\x05\xf3\x7e\x57\xf2\xc5\xd1\xd0\xca\xba\xf0\x7a\x8e\xd7\xd4\x14\x55\x40\x7b\x09\x67\x54\x18\x0a\xa9\x6d\x3d\x96\x59\x19\x45\xdd\x7a\x10\x40\xa2\xde\x60\xd8\xe1\xc0\x54\xf7\x85\x46\x52\xb7\x32\xe7\xa8\xf5\xb6\x47\x4c\x3b\xaa\x18\x40\xfb\xe8\x1b\x1e\x6b\x54\xe2\x01\xef\x0b\xc8\xd0\xf2\x13\xd7\xce\xc1\xd8\x24\xd2\x22\x09\xac\x72\x52\x5a\x64\xb9\x03\xe7\x73\xb8\x3f\x1b\x68\xf6\x40\x27\x9f\x15\x05\x3d\x21\xec\x15\xce\x2f\xf7\x59\x22\x17\x6b\x75\x84\xa1\x6b\xf1\xa1\xf0\xd6\x36\xb7\x94\x2a\x3d\x61\x86\x2f\x6f\xd1\x30\x99\x72\xd3\x14\x1e\xb7\x69\x31\x4c\xa9\x75\xd0\x20\xbf\x02\xbf\xdd\xf1\x7d\x14\xb6\x0e\xb7\x86\xbf\x9f\x55\x98\x9f\xe4\x73\x32\x0d\x44\x29\x67\x7e\x30\x1c\x68\x26\x33\xf8\x13\xff\x26\xc0\xa3\xda\x92\xf6\xd0\x68\x06\x16\x10\x5b\x04\x25\xaf\x33\x8c\x2e\xa6\x15\x3b\xdd\x52\x16\xfa\xe2\xaf\xe4\x61\xe9\x24\x9c\x05\xe3\x2f\x76\xad\x7c\x42\x9d\x92\x53\x4b\x68\x6d\xd1"}, -{{0x04,0x9d,0xac,0x3c,0x97,0x7d,0x9d,0xf5,0x03,0x49,0x6b,0x43,0xd7,0x6e,0x55,0x40,0xe3,0x15,0x00,0x1a,0xd5,0x7f,0x15,0xea,0x9f,0x08,0x70,0xca,0xd2,0xd4,0xf9,0xe9,},{0xfc,0x6f,0x4b,0x7e,0xb3,0x9a,0x71,0x16,0x80,0xf9,0x66,0xd4,0x68,0xa6,0x1a,0xbb,0x13,0xa9,0xb6,0x44,0x9b,0xb9,0x9f,0xda,0x3d,0x12,0xce,0x1b,0x50,0x6d,0x1b,0x4b,},{0x75,0x32,0xd1,0xa6,0x1a,0x98,0x1f,0x30,0x3d,0x7c,0x24,0x54,0x35,0x4f,0x99,0x54,0x0c,0xd4,0x84,0xcd,0xe9,0xab,0x33,0x7d,0x6f,0x7b,0x51,0xf1,0x79,0x22,0x0f,0x7f,0xa2,0x07,0x34,0x76,0xb4,0x1c,0x71,0x52,0x9f,0x98,0x36,0xdb,0x6b,0x1d,0x0f,0x5a,0x48,0x2b,0xbb,0x4c,0x68,0x36,0x61,0x76,0xed,0x14,0xd4,0xd8,0xee,0xfa,0xde,0x0d,},"\x7f\x31\xe3\x46\xf6\x8d\xa7\x37\x16\xaa\xcb\x16\xee\xa1\x9b\xb2\x41\x42\xdc\x28\x3e\x72\x63\xff\xc3\xf7\x04\xa2\x2a\xe5\x27\x5a\x0e\xf9\x5f\x06\x69\xba\xe5\xa5\x4c\x7f\xeb\x84\xbc\x74\x87\x3c\xca\x0f\x33\x5d\x6c\xff\x3d\x8b\x4a\x20\x05\x6c\x64\xf5\xe8\x82\xcb\xbb\xd2\xac\x74\x20\x76\x76\x46\x7e\x54\x66\xdd\xd5\x6a\xed\xf5\x6e\x09\x7c\x7f\x59\xd9\x45\x91\x5e\xb0\xeb\xd0\xc3\xc8\x3d\x48\x88\x8d\x3e\x9e\xde\x51\xad\x2d\xd8\xa0\xee\x1e\xab\x4c\xf8\x7f\xfa\x78\x63\x5a\xfc\x4d\x6e\xf3\xe8\x7d\xda\x3b\x65\x56\x5c\x29\x85\xa4\xad\x0a\xcf\xdf\xb8\x1c\xb0\xe6\x1c\x67\x82\x6a\x6e\xa0\xbe\xd4\xc0\x8a\xa1\xa5\x41\xde\x60\x45\x87\x04\xac\x21\xca\x12\xf1\xc8\x11\x8b\xb3\x09\x2c\x35\xa4\x0c\x92\x1e\x68\x45\x64\x56\x2c\x2c\x10\x49\xdc\xdc\x2b\x8d\x6a\x97\xe3\x56\x7d\x35\x6b\xff\xb5\x69\x2a\x41\xd8\x9d\xdd\xa0\xec\x35\x52\x15\x2a\x27\x57\x7f\x1c\xce\x57\xd0\x09\x86\xdc\xa7\x7e\xdf\x5e\x25\x18\x15\x82\x00\xad\xf6\x90\xaf\xfb\x31\xaa\xf2\xb5\x74\x83\x68\x39\x44\x09\x99\xf1\x57\x91\xce\xa8\x53\x42\xac\x94\xa9\x6c\x7a\xf7\xa1\x9e\x49\x43\x10\xae\x26\x67\x5f\x43\xc3\x52\x58\xe8\x5b\x68\x40\xb9\x9c\x6b\x09\xcf\xa5\x8d\x19\xf1\xe4\x3a\x77\xe3\x97\xb0\x8c\x0d\xb1\x83\x0b\xca\x67\xb3\x9e\xcd\x87\x52\xda\x61\x1e\x08\x32\xc6\xca\xe7\xbb\x8c\xe7\x4a\x82\xe7\xe7\x33\x0b\xe5\x06\x2e\xd0\x5a\xa5\xc8\x44\x57\xb0\x07\xfb\x5c\xcd\xc2\x0a\x55\xd5\x4d\x8e\x04\x09\xc8\xbd\x83\x88\x3d\x2e\x02\x9d\xff\x26\xea\x5d\xb2\x75\xdc\xe0\x99\xe4\x18\x65\x9a\x04\x00\xf1\x3b\xe9\xff\xdc\x14\xe7\xd6\x45\xa9\x46\x77\xca\x84\x69\x70\xb7\xe6\xac\x52\x7f\xa0\x09\xa3\x59\x45\x4b\x3c\x49\x36\x49\x05\x18\x9f\xb4\x9c\x9b\xac\xb6\x50\xc0\x3c\xd8\x28\x75\x89\x4e\x35\x46\xba\x03\xc3\x2e\x33\x6f\xc6\x51\x6a\x87\x67\x6c\x50\xd5\xb8\x0b\x30\x54\x27\x3b\x15\x7c\x5d\x76\x75\x14\xe5\x45\x74\xb8\xa1\x01\x98\x5a\x8e\x96\x7e\x95\xda\x8f\x92\x98\x00\x26\x0e\x08\x14\x8b\xee\xe2\xd7\x78\x1e\x9e\x85\xd4\x63\xa9\x4f\xfe\xfd\xbb\x75\xc2\x8f\xa8\x89\x80\x15\x68\x09\x99\x42\x9c\xee\x79\x8b\x3f\xd2\xd9\x67\x37\x86\x8a\x26\x3f\xba\x9f\xb6\xf4\xaa\xd5\x6a\x15\xc6\x41\x2f\xf8\x5e\x7d\x37\x52\x10\x2d\xaa\xf2\x5e\x74\x5f\xa5\xf6\xf1\x74\xa2\x31\xfc\xce\x86\x24\xdd\x70\x85\x6f\x9b\xab\xcc\x20\x91\x44\xff\x68\x64\x64\x8d\xea\x0d\x68\x84\x56\x6a\x4c\x39\x14\x78\x05\xbe\x08\x4e\x47\x40\xbc\x50\x93\x09\xbc\xb1\x42\x96\x4b\xb0\xcf\xcf\x67\x26\xa0\xe0\x4b\xbf\x32\xae\x68\x34\x73\x2b\xda\x03\x84\xce\xa8\xf4\xa4\x84\x9b\xba\x0d\x18\x64\x6c\x1c\x34\x47\x18\x96\xb5\xbe\xf1\x49\xf8\xca\xb9\xec\x83\x72\x2b\x0f\xb2\x09\xef\xe8\xa0\x4c\x4a\x23\x5d\xc8\xdd\xb2\x0a\xcd\x92\x76\x5a\xfb\xf3\x05\x87\x40\xea\x70\xb9\xc1\x0d\x9c\x5a\xef\x86\x06\x29\x8f\xe4\x15\x15\x93\xb2\x1f\x79\x7d\x92\xae\x9f\x1e\x08\x81\xb0\xd2\x71\xb0\xd5\xb1\x0c\x6e\xd8\x3c\x34\x9e\xc2\x47\x3f\xbf\x2f\xf7\x80\xdc\xd0\x76\xd8\xcf\x0a\xea\xfa\x71\xfe\x2b\x8c\x51\x28\x01\x5f\x8f\xbb\xcf\xec\xd5\x28\x1c\xd5\xea\xcb\x6f\xe9\xac\x6e\xaa\x6e\x47\xd6\x67\xb9\xad\x4b\x7e\x41\x1e\x6c\xb7\x46\x3d\x56\x76\x07\xaf\xbf\xd0\x41\x8c\x4e\xb0\x6a\xfe\x84\x7f\x5e\x40\xb4\x99\x44\x38\x28\xd5\xa2\x73\xa4\xa8\x7e\x46\xde\xf2\x1a\x91\x9d\x73\x86\x3a\xf0\x05\x4a\x09\x9e\x3a\xdc\x54\x50\xb8\xe3\x2f\x51\xea\x52\xc5\x99\xa4\xa2\xa3\x53\x51\x78\x8a\xf7\xcb\x71\xe5\xc4\x4b\xcb\x8d\xf5\x4a\x60\x1e\x6e\xc2\xc1\x82\x8b\x48\xc4\xb1\xae\x44\x63\x10\x6f\x10\xef\xa5\xca\xf3\x09\x1a\xbf\x99\xaa\xba\x52\x52\xf4\x84\xd3\xbb\xc6\x2b\xfa\x6b\x2a\x80\x6d\x23\xc6\x33\x1a\x62\xfc\x46\xbc\x62\x76\x79\xe7\x3e\xc8\x2d\xcc\x08\xf7\x91\x43\xf4\xb7\x1e\xcf\x35\x7e\xa2\xf0\xd7\x4e\x6d\x30\x58\xe6\x06\x04\x3f\x6e\x8f\xed\x70\x42\x82\xc1\x6b\x1f\x98\x8f\xfa\x36\x5c\xfa\xe9\xa3\xcf\x79\x2e\x0c\x5b\xaa\xd7\x0c\xa7\xe2\x57\x76\x01\x8b\x5e\x7f\x0e\x95\x44\xe1\xd7\x3f\x3e\x5d\x1e\x41\x6a\x5e\x50\xfb\xed\x29\x6d\xc1\xbf\x4b\x29\xa3\xfb\xe3\x2e\xfb\xd7\xe9\x9c\x83\x01\x5d\x27\xf5\x35\xad\xec\xf1\x75\xfc\x36\xc1\xea\x4f\x44\x23\xb3\x6d\xcd\xc0\x54\xba\x99\x32\x78\xe8\x5a\xc3\x62\x2d\x43\x5f\x52\x37\xba\x61\xb4\x9a"}, -{{0xf0,0x7d,0x61,0xb5,0xca,0x1c,0x27,0x00,0xcb,0x50,0xf9,0x00,0xc2,0x6b,0x7c,0x28,0xf6,0xc6,0x94,0x08,0x08,0xc7,0xba,0xff,0xf7,0x4f,0xca,0x4b,0x11,0xf4,0x25,0xd4,},{0xeb,0x24,0x3d,0xfa,0xcc,0x2d,0xc6,0x43,0x57,0x76,0xd5,0x54,0xec,0xed,0x8b,0xf9,0x23,0x90,0x60,0x4b,0x35,0x55,0x7c,0xda,0x51,0xfd,0x20,0x3e,0xdd,0xb4,0x93,0xfa,},{0xc1,0x9b,0x53,0x2b,0x82,0x48,0x56,0x39,0x32,0x63,0x97,0x01,0xbf,0x15,0xbc,0x01,0x5f,0xae,0xbb,0x17,0xbb,0x98,0xd8,0x71,0x61,0x6e,0x10,0x48,0xd6,0x4c,0xa5,0xf9,0x55,0xf5,0x58,0xf6,0x3b,0x53,0x53,0xa1,0x57,0x6f,0xa1,0xac,0xae,0xf3,0x9b,0xcb,0xc9,0x02,0x17,0x56,0xdf,0x5d,0x1a,0xb3,0xbc,0x74,0x1a,0xcc,0xf9,0x05,0x9b,0x04,},"\xc1\xc6\x78\x43\xd6\x9a\x0e\x62\xe7\xbf\x71\xf9\x02\x06\xa3\xd5\x59\x5c\xa3\xc4\x82\xaa\xa7\x67\xe9\x31\xb0\xd6\xc2\xf4\x75\x2a\xb8\x69\x91\xf0\x35\x83\xbb\x13\x8e\x9f\x72\xfa\xb5\x8f\xd6\x02\xa4\xb6\xb2\x96\x02\xcf\x89\x14\x08\xaf\x5a\x1b\xfd\x33\x98\xc0\x17\x8c\x44\x14\x61\xe3\xf4\x9b\xc8\x1d\x64\xc0\xd9\x7f\x5d\xed\x69\x2c\x75\xd4\xd6\x4d\xac\x5d\x80\xd6\x3b\xd4\xdc\x52\x10\xc1\xd9\x35\x0b\x14\x2b\xa6\xe7\x68\xf1\x50\x80\x7a\xb8\xa8\x6c\xac\xdb\x59\xd8\x4d\xdf\x66\x0b\xe5\x62\x03\xc0\x14\xfb\xa1\xe0\xdc\x16\xfa\x6d\x32\x69\x4e\x14\xb1\x28\xed\xd1\xf6\xc6\xab\x44\x5a\x3a\xd3\x41\x74\xfa\x9e\x4b\x01\xf2\x5b\x1d\x5e\x6e\xb7\x69\x83\xb4\x29\x5c\xe4\x91\x4d\x3a\xe4\x8c\x70\x4a\x30\xe5\x54\xfc\x1f\x86\x8b\x62\x72\xef\xf0\x6d\xa2\x4b\xfe\x17\xe4\xe0\xf0\xfa\x46\xbb\x08\xff\xb9\x07\xcb\x61\xbe\xbe\x52\xdf\x31\x1a\x64\xcb\x57\x8b\x30\xfd\x62\x7d\xf1\x12\x21\xae\x40\x03\xa0\xb0\xc6\x8e\x3c\x6f\x95\xa2\x1c\x85\x00\xd4\x1b\x2c\x58\x9c\xc4\x6a\x13\x9c\xac\xff\x57\xdc\xf0\x07\x59\xf5\x2e\x9c\xa3\xda\xbd\xb1\x78\x8a\xb6\xb3\x8a\x50\x48\xf5\x8e\x08\xe0\x5c\x39\x4f\x9d\x3c\x72\x11\x3d\x45\x2b\x70\x84\xc5\x19\xf8\x6c\x16\x89\xff\xdb\xae\x50\x6e\xd8\x45\x05\x22\xcb\xe4\x3d\xe2\x7a\xa3\xbf\xdd\x92\xa9\x1b\x71\xe5\x2a\x3c\xbf\x77\xc1\xbd\x28\x93\xea\xbd\x40\x7a\x57\xfe\x5e\x14\x68\x73\xbf\xb2\x04\x3f\x4a\x61\x47\xdf\x08\x3e\x54\xa2\x20\x8d\x19\x25\x81\x3f\xa4\x04\xe4\xc4\x74\x06\xe7\x72\x86\x43\xeb\xfb\x0b\x10\x14\x2f\x90\x9e\xf8\x56\xfd\x3a\x91\x6b\xc0\x85\x15\x43\xb8\x2a\x55\xf8\xcd\x52\x9b\xd2\x1d\x9e\x29\x09\xd6\xd7\xe7\x7b\xdc\xea\x46\x73\xe5\x45\xff\x4a\x67\xfa\x37\xd6\x5f\x1f\x63\xf1\x1d\x5d\x0d\x55\x97\x4a\x30\xab\xe1\x88\x33\x5d\xb5\xdc\xbd\x35\x66\x58\xf9\xb7\x76\x82\xd9\x6d\xab\xb2\x58\xea\x95\x95\x1a\x05\x59\xae\xa4\x06\x4d\x5e\xa1\x68\x05\x01\xdc\xb4\x22\x8f\x2c\x95\x6f\x81\xd2\x10\x11\x44\xaf\x74\xc7\x16\xbc\x8b\xf4\x29\x6d\xc3\xb8\x31\x72\x5c\xc1\x7d\x3b\xfd\x90\x66\xa2\x99\x53\xb2\xec\xd7\x50\x59\x43\x5b\x49\xa2\x5a\xc5\x25\xb4\xfb\xab\x17\x79\x02\x2d\xfb\x6d\xe5\x25\x14\x9d\xcd\x90\x2a\xc8\xa7\xe2\x1f\x34\x4f\x5f\x01\x01\x48\x06\x92\xd6\x16\x08\x95\x2c\x71\x41\x3e\x30\x03\x79\x45\xe2\x06\xc5\xee\xad\xfc\x3e\xdc\x4b\xae\x0d\x79\x6c\xa0\xc5\xf5\x6d\x6f\xfb\x3f\x09\x69\xdf\x9d\xf8\xa7\x94\xf5\xdc\x83\xa3\xb2\xf5\xc3\xab\x36\xbb\x90\x1b\xcc\x31\x55\x1c\x55\x0c\x63\xfa\x41\xd6\xa8\xd5\x7b\xdb\x9b\x5c\x65\xbc\x61\x0c\x3a\x98\x97\x52\xab\x28\xa0\x15\xe7\xc2\xf6\xb2\xfb\xf1\x99\xa7\x6b\x97\x50\xc0\xd3\xd5\x92\x11\x9c\x8b\x40\x22\xfa\x45\xba\xde\x2f\xbb\x41\x43\x26\x79\xb5\x2a\xcb\x46\x08\xa9\x5c\x34\xaa\x40\xbf\xfe\xc1\x0b\xc9\x8f\x47\x29\xdf\xcc\xb6\x50\xb2\xa0\x52\xdf\xb0\x68\x95\x9e\x64\x8a\x92\xd5\xaa\x4d\xd2\xd1\x7d\xde\x67\xcd\xf2\xe6\x37\x7a\xf0\xd4\xae\x37\x96\x07\x38\x9d\x7e\x35\x96\x44\x1b\x9f\x42\x22\xcf\xf6\xaf\x73\xb3\x30\x02\x70\xce\x54\x80\x0b\xd9\x34\xa9\x10\x9a\x02\x56\x3a\xdc\x56\xae\x46\x58\x44\x51\xcd\xaf\x4a\x77\x53\x81\x57\xe5\x87\x0f\x4a\xe1\x2d\xbc\x81\x87\x0f\x5d\xb4\x1a\x2c\xb5\x5e\x00\xdb\x3d\x22\x31\x62\x8f\x17\x27\xc3\xac\xb9\x9e\xd3\xac\xd8\xb6\x71\x56\xa8\x00\x5a\x4c\xc8\xf3\xd3\x55\x5b\x79\xa0\x37\x73\xa9\x31\xf1\x4e\xeb\xce\x40\xb9\xfe\x46\xed\xe5\xda\x08\x81\xfb\x22\x07\x17\xe4\x18\xe8\xb5\xa0\xfe\x5e\x47\x7e\x72\x85\xc5\x54\xe8\x59\xe1\x64\x41\x67\x2b\x48\x99\x34\xa3\xa9\xee\xb8\x8d\x78\xfc\xc5\xc1\xdb\x2d\x1f\xbd\xde\x39\x27\x73\xf6\xc9\x39\x97\x2e\xe8\xfa\x31\x89\xf4\xe9\x87\x2b\x4a\xbd\xc8\x3b\x37\x9c\x0c\x10\xe8\x18\xdc\xff\x75\xc8\x3d\x68\x70\x72\x92\x84\xce\xd4\x1f\x2f\xf5\x5a\x87\xc9\x60\xe6\x3d\x12\x11\xf0\x80\x71\x29\x3f\x6a\xc6\x3f\x9b\xde\xf3\x8f\xd5\x91\x9c\xa9\x0b\x3f\x5e\x25\xa6\xc0\xc6\x64\xc4\xec\xf8\x31\xc6\x4e\x2d\x4c\x6e\x79\x8a\x98\xa3\xa0\xf7\xbe\x7a\x24\x63\xea\xda\xa6\xa2\xa3\x48\xf9\xa4\x94\x71\x71\x23\xcc\x0a\x28\xc0\xa5\xea\xe3\xf5\xb5\x85\xf2\xcb\x8c\xb2\x60\xc2\xc5\x03\xe4\x15\x78\x57\x3c\xd9\xb7\xcb\xa1\x40\x8d\xca\x9d\x86\x0a\xe4\xf8\xc3\xd3\xf3\x22\xa4\x5b\x58\xa2\xc4"}, -{{0x50,0x86,0x4a,0x75,0xaa,0x0c,0x69,0xb5,0x93,0x50,0x07,0x7c,0x20,0x4b,0x20,0x75,0x7f,0x2b,0x8b,0x68,0x55,0xc3,0x7e,0xd7,0x21,0xb4,0x9f,0x2a,0xc9,0x17,0xd6,0xb2,},{0xcf,0xf3,0xeb,0xd5,0xea,0x0c,0x8b,0x55,0x31,0xd9,0x21,0x1e,0x22,0x19,0xe4,0xcf,0xe5,0xde,0xd9,0x91,0xd8,0xec,0x42,0x4d,0xf5,0x4c,0xf5,0x3c,0x83,0x76,0xf9,0xbd,},{0x17,0x74,0x55,0xa7,0x16,0x94,0xf1,0x2b,0x76,0x2f,0xd1,0x7e,0x08,0xbd,0xf0,0x10,0xa7,0xfc,0x91,0xd1,0x91,0x41,0xd7,0xae,0x23,0x99,0xbd,0x24,0x1a,0x99,0x8a,0x6a,0x50,0xa9,0x72,0x2a,0xc1,0x23,0x2c,0x59,0xe4,0xe2,0xaa,0xa8,0x28,0x07,0x8b,0x2b,0x92,0xf4,0xa5,0x4c,0xdf,0x0e,0xfe,0xbb,0xa2,0xc1,0x6d,0xbe,0xaf,0x07,0x22,0x03,},"\xb3\x65\xf4\x76\xac\x92\xe7\x60\x12\xa7\xff\xd8\x78\x2a\xf1\x5a\x3f\x5e\xe1\x47\xf6\x03\xa3\x67\xad\xf2\xf9\x72\x46\x13\xe8\x76\x5b\x03\x7a\xc0\xeb\x1f\x67\x37\x36\xe1\x13\x63\xe3\x52\xed\x5a\xe9\xeb\x5a\x67\x12\x5e\xd8\x18\x90\x03\x42\xae\x93\x37\x1c\x43\x3b\x91\xf6\x02\x1d\x4b\xe2\xa0\x52\xb0\xda\x43\xb3\x68\x2e\x7f\x74\x0a\xe8\x01\xd0\x54\x10\x57\x85\x8e\xb0\xc9\xc2\x8d\x98\xf0\x3b\x45\xe1\x28\xaa\xa3\x42\xc6\xb6\x02\x77\x67\x92\xaa\x81\x24\x1c\xad\x06\xf1\x33\x8f\xa0\xc7\x17\x57\x18\x0f\x58\x8c\x83\x01\xd9\x1c\x27\x67\x9b\x50\x21\xcd\x75\xd7\xf6\x17\x1e\xe9\xf8\xd5\x6e\x43\x77\x67\x98\x12\xf6\xec\x5e\xd4\x65\x38\xca\xed\x50\x0c\x1d\x15\xf5\xfc\x86\xea\xf9\xed\x9c\xf9\xa0\x60\x6b\x22\x61\x4f\xaf\x67\x64\x62\x13\x4e\x3d\xb3\x58\x23\x32\xb4\x83\xdf\xa5\x4c\xa2\x9a\x5e\xb0\xd6\xba\xe3\x38\x0e\x19\xd0\x60\x11\x34\x53\xf3\x2b\xba\xb7\xe1\x18\x62\x7b\x40\xbc\xab\xf1\x71\x1b\xcf\xea\xb8\x95\x7d\xe3\x39\x43\x6c\x70\x88\xbb\x88\x31\x01\x53\x9a\x09\xd3\xbe\xf0\x88\xfc\x1f\x84\x07\x64\x03\x6f\xfb\xb3\x3d\xec\xd1\x2a\xac\x57\xfd\x26\xf8\x48\x23\xe1\x95\x53\xd4\xd6\x7e\x00\x0e\x94\x36\xca\x32\x3d\xe0\x99\xbc\x1c\xe7\x5e\xbf\x5d\xdc\xcb\x44\x8c\xd7\xa2\xe4\xbb\xd6\xb3\x2e\x3f\x20\x24\xf9\x6c\xc5\xc7\x15\x2b\x8b\xe8\xed\x0b\xd8\xe4\x36\xd3\x24\xd1\xce\x1d\xd3\xcf\xcc\x45\x2a\x28\xc7\x3a\x95\xaf\x84\x82\xaa\x77\x2a\xe5\x3d\x5b\xe1\x29\x2e\x39\xd1\x71\x6b\x43\x75\x8f\xe5\x63\xc8\xaa\x3b\x74\xbb\xa5\xc0\x2d\x04\x77\x8d\x91\xe3\xd4\x3d\xcc\x72\xbb\x7c\x7b\x04\x3c\x05\xc8\x74\x5b\x70\x5e\xe7\x5b\x5a\x4e\xc7\xb9\x5b\x65\x43\x59\xfb\x5e\x85\x33\x38\x21\x98\x51\xd4\x0a\x8a\xfb\xb4\xf9\x1e\xcb\xb4\x1e\xb8\x15\x34\x19\x6c\xc0\xcc\x9d\x3e\xb7\x14\x39\x6c\xaf\x04\x5b\x23\x17\x22\xd4\x48\x65\x03\x64\x04\x19\x98\x84\x80\xa7\x81\x58\x08\xbe\x97\x42\x87\x37\x2c\xfc\x48\x99\x65\xaa\xc5\xb8\x09\x5c\x63\x75\x81\xeb\x91\x0f\x90\x55\xcd\x1c\x0a\x0a\x3b\x0b\x33\xac\xa9\x0f\x7c\x5b\x8e\x6e\xf6\x83\xab\xf0\xce\x53\xae\xba\x51\xbe\xc4\xfc\x7b\x42\x7a\x23\x47\x36\x0f\xca\x86\x36\xd3\xf1\x46\x92\x84\xf2\x69\xa9\xab\xf0\xcb\x1a\x24\x4a\x15\xd6\xb4\x04\x65\xe7\x5c\xf8\x90\x92\x47\x4a\x8b\xed\xa0\x33\x39\x1d\xd3\x11\xc4\x99\x51\x9a\x08\xc4\xf0\x34\xe7\x19\x18\xd7\xca\xd4\x18\x45\x32\x7c\x89\xe7\xb1\xe9\x4a\xfb\x07\x23\x78\x2c\xe5\xc5\x53\xef\x36\x79\x1b\xba\x63\xde\x17\xd7\x46\x49\x18\x94\x01\x2c\xeb\xd8\x7b\x18\x37\xa8\x21\xef\x5c\x62\x4b\xbc\x84\xcc\x50\x35\xf5\xe7\x0c\xd9\xf2\x1b\x42\x21\x9a\x2d\xce\x30\xe0\xe6\x5c\x25\x0d\x0d\x19\x4d\x2b\x52\x48\x6b\x03\xee\x66\x33\x29\x81\xa5\x22\x51\x74\xdb\x17\xe5\xa8\xbb\x4a\x10\xed\x9c\x8a\x44\x5c\x41\x44\x2f\x3b\xcd\xb6\xb4\xf4\x9e\x4e\x1d\xc8\x76\x61\xa7\xb6\xe4\x1f\x35\xf5\x5d\xd6\x7b\xd4\xcb\xc6\xff\x58\xbf\xbf\xfa\xff\xd2\xc3\x82\xfc\xad\x0c\xae\x8f\x0d\xf9\xaf\x6a\xcf\x09\x40\x00\x76\x18\xa5\x4a\xee\x31\xd9\x32\xcb\xd8\xe8\xb4\x1c\xa0\x38\x21\xc4\x28\xa0\xef\x8e\x58\xd2\x43\x5e\xec\xd5\x03\xc5\x4d\xa9\xc1\x62\x8f\x3c\x74\x9b\x77\x05\x19\xf5\x3b\xf2\xd5\x7e\xd7\x12\xd0\x75\xd3\x73\x37\xb7\x7a\x2b\x10\xa7\x2d\x2d\x59\x0c\x20\xd5\xce\xc2\xca\xcc\x6c\x3a\x8d\xc1\x13\xe2\xd1\x6e\xf2\xd1\xb3\x90\xed\x96\xe4\x03\x6a\xcd\x30\x4e\x0c\x7c\xef\x9d\x43\x1f\x88\x21\x8a\xa1\xf8\x38\x28\xdd\xa6\x36\xb9\x4a\xa7\x61\xc7\x31\x7e\xcf\x11\x6c\xbf\xc6\x11\xe5\xba\x6d\x94\xc5\x0e\x99\x46\x93\x02\x3b\xdf\x2d\x24\x8e\xd6\x03\xf8\x5b\xe7\x3a\x00\x08\xb7\x5a\xde\xf9\x51\xdc\xcf\xa3\x0e\x42\xe9\xf5\xbb\x05\x02\x3a\xde\x79\x75\x06\xcb\xf9\x0b\xb6\xdc\xe4\x3c\xf3\xa1\xc3\x14\x1a\x5c\xc5\xfd\x9a\x4f\x3c\xc5\x57\xb9\x0e\x18\x04\x9b\x3c\x13\x0f\x46\x1e\x4f\x32\x29\x9f\xa1\xd1\xcf\x9c\x7f\x2e\xa2\x05\x35\x65\xe8\x16\x0a\x34\x1c\xdd\xf9\x9a\xcd\xdd\x49\x16\x97\xfa\x70\x51\x24\xab\xda\xb4\x2a\x5e\x8f\xcf\x04\x8d\xd9\xf1\x79\x38\x4e\xc9\x2a\x46\x9a\xeb\x11\xe8\xbc\x62\xb6\x9d\xbc\xfc\xec\x66\x81\x75\x47\x57\xe4\xc5\xd0\xfd\xd9\xb9\xcf\xda\x49\xaf\x09\xb8\x3a\x5a\x4a\x10\xae\xd9\xa4\xcf\x7d\xdf\xa2\x89\x20\x9d\x47\x5a\xb3\x31\x8c\xd4\xb9\x65\xe0\x07\xdc\xe1"}, -{{0xe5,0x5f,0x22,0x0f,0xff,0x80,0x79,0x14,0x8b,0x25,0x41,0x89,0xbb,0x29,0x41,0x74,0xf8,0xe2,0xc5,0x75,0xe5,0x7f,0x39,0xd4,0xba,0xc8,0x16,0x5c,0x5e,0x56,0xe7,0x69,},{0x7f,0xd5,0x07,0xd0,0x3f,0xe1,0xd6,0xe3,0xf9,0x11,0xf0,0x59,0x59,0x7b,0x0e,0x29,0x2e,0xa0,0x96,0xf5,0xbc,0x85,0x18,0x52,0x91,0x6b,0xf1,0x21,0x7c,0xaf,0xdc,0x6c,},{0xc1,0x02,0x3a,0x70,0x68,0x74,0x3e,0xc4,0x66,0x8f,0x49,0x5e,0xb7,0xbd,0x4d,0xb5,0x81,0x29,0xc1,0x1e,0x58,0x29,0x9e,0xa8,0x7d,0x6f,0xac,0xd3,0x02,0xbf,0x29,0x6a,0x98,0xe2,0x98,0xfd,0xb4,0x8e,0xdd,0xf9,0xc4,0x4e,0x79,0xae,0x86,0x41,0xf7,0x34,0x50,0x3b,0xb8,0x3d,0xc0,0xb3,0x1f,0x61,0x0d,0xf1,0xd1,0xe9,0xd6,0x19,0xa7,0x05,},"\x1e\x2c\xe8\xbf\x0e\xa7\x87\x5d\xf2\x85\xb1\xdb\xd3\x4b\xbe\x67\x30\x7f\x2e\x8a\xc8\xbc\x14\x2c\x3b\xa3\x14\xc1\x64\x2c\x65\xa2\xd6\x2e\xb2\xc7\x83\xf9\x16\x28\x3c\xa4\xec\x3e\x53\x6d\x3e\xeb\x65\xcf\xdc\xc0\x54\x9a\xc4\xf6\xa4\x5f\x53\x9a\xc5\xdf\x79\xa6\xd5\x76\x82\x19\x73\x9d\x0c\x9a\x0c\xdb\xb3\x12\x42\x29\x6c\x33\x12\xb7\xed\x56\x00\x43\xf5\x36\xcd\x1d\xe9\xa9\xc2\xb2\x89\x64\x1a\x1c\x2d\x84\xf9\xa6\x8b\x7c\x03\xb8\xb8\x56\x7e\x5d\xc7\x13\x8c\x2c\xb9\x67\xc6\x28\xaa\x25\xb2\xea\xb4\x34\xd4\x49\x0b\x23\x50\x74\x09\x71\x7c\xde\x94\xda\x59\xdc\x1d\xc2\x5c\x7b\xe4\x2a\x8a\xa0\x2e\xdc\xf4\xd9\x95\x36\x8e\x6b\xa0\xee\x1f\x95\x36\x00\xdb\x98\xd2\x2d\xe0\xf8\xd2\x57\x02\x0e\x0a\x40\x6e\xe1\x66\x9b\xd5\x27\xb9\xfe\x1c\x61\x1f\x9b\xe5\xa3\xd7\x52\x8e\x8b\x61\x51\x67\x0a\x86\x63\xd2\xed\x1a\x58\xd3\xe3\x69\xbb\x72\x2a\x63\x02\xd7\xc1\x72\xa1\x9b\xda\xf3\x57\xee\xdb\x02\x27\x91\x56\xe3\xb9\x03\x44\x31\xa7\xd6\x8a\x39\x52\x8e\xb4\x02\x35\x87\x57\x3e\xb8\x8f\x30\xf9\x4e\x83\x3e\x8a\x23\xb9\xd0\xac\x7b\x5c\xa8\x78\x24\x59\x6b\xbb\x0a\x3d\x0c\xa1\xb1\x6a\x68\x78\xfd\xf7\xe2\xce\xa3\x4a\x6f\xfb\x95\xa9\xff\x4e\x88\x8a\x97\x59\x37\x35\xb8\x68\xda\x75\xd8\x70\x7b\xbf\xdb\x1d\x93\xeb\x86\xa5\x1e\x2d\x21\x5f\x1d\xd9\xdc\xf7\x83\x88\x72\x9a\x3e\xb0\xf0\x66\xdd\xc9\x41\xe9\x50\xc9\x21\x27\x19\x8b\xce\x63\xa5\x48\x68\xd9\x97\x02\x95\x72\xff\xa6\xf6\xfe\xa1\xd3\xa6\x91\x64\xc9\x99\x69\x53\xdc\x8b\x6f\x9d\xad\x06\x35\xc9\xb0\x81\xf5\x5f\x98\x33\x40\xf0\x81\x4b\xf5\x47\x08\x03\x09\x0e\x79\x97\xf7\xab\x79\x6c\x2b\x15\xad\xaf\x40\x21\xd6\x7c\xff\xaf\x6e\x1e\xf6\x28\x67\x50\x39\x45\xc2\x1a\x32\x96\x64\xe0\x8a\x95\xa4\x15\x82\x30\x0d\xa9\xbe\xd2\x08\x44\x4c\xe6\xaa\x12\xb3\xf8\x67\x79\x5c\x6e\xe4\xc4\xc9\x25\x70\x18\x62\x73\x61\x29\x3b\xd5\x27\x82\x1a\x29\xa3\x39\xb4\x04\xa2\xda\x4b\xd9\x94\x4f\x87\x70\x40\x79\x8b\xb5\x4a\xbd\x2d\x76\xcb\xb1\x8d\xf4\x29\x7f\x4c\xe3\x33\x7f\x64\xd2\x05\x80\xaa\x64\xbd\xec\xac\x37\x6a\x6a\x4f\xf7\x4d\x01\x44\xb2\xfe\x74\xce\xf8\x2d\x50\xa5\xe6\xbd\xd7\x99\xe5\x5f\xf6\x96\x62\xba\xc5\x37\xad\xcb\x68\x81\x22\x8c\xb6\x37\x04\x50\x0c\x14\x3a\x4f\x4d\x1d\xb2\x8d\x45\x56\xbe\xe6\x04\xa3\x99\xff\xd2\x06\x54\x65\x97\xde\xe9\x22\x52\x54\x7f\x6c\x65\x7f\x36\x84\x1a\x87\xd5\x65\xf6\x55\x27\x16\xc2\x5a\x21\x15\x14\x77\xbe\xe9\xef\x96\x18\x55\xfb\x1a\xf2\xda\x80\x68\xf2\x8c\xe9\xff\x70\xd5\x25\x2c\x7a\x63\xa2\xe1\x4d\xed\x6b\x89\x77\xb1\xd7\x69\x1a\x77\xed\x2e\x57\xd2\x2f\xf2\xe1\xfc\x4c\xdb\xce\xb5\xe8\x05\x85\x8d\x90\x38\x96\xea\x67\x07\xe4\x8b\x34\x5f\x60\xe2\x81\x8b\x2f\xce\xc4\xdb\xa4\x8c\xae\xa9\xef\xa3\x82\x79\xfb\x83\xd5\xb0\xf4\x6a\x45\xe4\x2c\x41\x76\x5d\x01\x71\xba\xac\xd8\xd6\xdd\xa7\x99\x13\x14\xb3\x4e\x15\xfd\x36\x12\x7c\x46\x7d\x1d\xe0\x1c\x01\xa3\xa7\x8a\x8c\x1b\x10\x3b\xee\x17\xa7\xa0\xb7\xac\x55\x76\xfd\xc2\x26\xdd\x24\x59\x77\x31\x46\xcf\x38\x26\x14\x17\xca\x19\x13\x5d\xbd\xa9\xbd\xbe\x54\xcd\x17\xaa\x7d\xdd\x38\xfd\xca\xc2\xab\xa3\x96\xb3\x65\xce\xae\x98\x91\x9f\x6c\x51\x77\xfc\x58\x3f\x5b\xee\x3f\x48\x70\x49\x14\x30\x6a\xa1\x9e\xe9\x0e\x3f\xd0\xde\x55\x91\xc6\x69\xff\x35\xab\x16\xfe\xf3\x8d\xee\x18\x7b\xae\x1e\x5a\xaa\x56\x6d\xf1\x05\x44\xb7\xd6\xd4\xeb\x00\xda\x7e\xbe\xb4\xec\xdc\xc4\xd8\xe3\x2b\x49\xcb\xbd\xc6\xe6\x66\x40\xbd\xb0\xf7\x2e\x05\x91\x8a\x05\xc3\x5d\x9b\xff\x7e\x0e\x88\xf2\x41\xd7\xc6\xc8\xcb\x2f\xed\xcc\xdf\x65\x56\x0a\xf0\xe7\x83\x3e\xfe\x34\xaf\x79\x0d\xb6\x31\x89\x02\x2c\xfd\x71\xfc\x8a\xcf\x88\x86\x01\x27\xbd\x4f\xbf\x02\x6b\xcb\xe3\x60\xe3\x3a\x89\x95\xe6\x36\xd0\x3b\xb8\x6d\xfd\x01\x98\xad\xa9\x59\x34\x2d\x8e\x9c\x9e\xd9\x3e\x23\x29\x7d\xa9\x8d\x66\xa0\xd4\xfc\x96\x51\x62\x73\x3b\xc8\x65\x41\xb9\x5a\x6c\x90\x97\xcb\x55\xa9\x73\xc6\xfa\xc1\x94\xe8\xf8\xa1\x64\x27\x4c\x47\x9c\x51\x0e\x62\xd8\xa0\x35\xeb\x75\x11\x81\xb5\x02\xaf\xb6\x14\xd8\xc4\x46\x7b\x54\x45\xc2\x68\xdc\x3d\xd0\xab\xbd\x57\x70\x04\xc0\xbc\x47\xb1\x5f\xcb\x80\x1b\x79\x35\x97\x57\xb5\xea\x89\xcf\x8c\xf7\x7f\xc6\xd1\x60\xe6\xcd\x73\xc4"}, -{{0xd5,0xe3,0xa4,0x06,0x71,0xbd,0x45,0xf0,0x88,0x42,0xdd,0xc7,0x8a,0xbe,0x57,0xde,0x3b,0x9c,0xe5,0x64,0x6b,0x73,0x0d,0x2e,0x59,0xfe,0xcf,0x5a,0x7d,0xf8,0x0f,0x40,},{0x41,0x6c,0x37,0xae,0x1a,0xd1,0x5b,0x63,0x2b,0x0e,0xa4,0x39,0x32,0xc1,0x76,0x37,0x28,0x2c,0xd9,0x1d,0x59,0x79,0x55,0x2e,0x5e,0xeb,0xb9,0x9a,0x41,0x9d,0x5c,0x97,},{0x63,0xde,0x6a,0x98,0x11,0x42,0x36,0x5a,0x3e,0x59,0x26,0x31,0xc8,0x27,0x72,0x37,0x80,0x97,0x39,0xd1,0xc9,0x8f,0x5a,0x1c,0xb2,0xcc,0xcd,0x34,0x06,0x7d,0x1c,0xa5,0xdc,0x8f,0x2f,0xc6,0x3b,0x8a,0xe1,0xa6,0x89,0xdc,0xaa,0x29,0x1b,0xa6,0xb6,0x9b,0x1a,0x67,0x95,0xc5,0x79,0xa5,0xdb,0x6d,0xcc,0xee,0x73,0xf6,0xa4,0x20,0xac,0x0a,},"\x09\xfe\x6f\xfa\x8b\xf0\x94\x2a\x64\x92\x13\x57\x65\x9d\xbc\x6e\x4f\x8b\x63\xca\x3b\x9e\xa4\x75\xea\x39\xd7\x92\x52\x90\xa1\x48\xd8\x7b\xb1\x55\x74\x1d\xfa\x28\xae\x1b\xea\xdc\x1f\x3e\x1a\xb7\x67\x37\xeb\x5d\x5d\xda\xde\xd0\xbb\x38\x2d\x7e\x11\xea\x81\xa5\xe7\x80\x16\x12\x69\x62\x60\xba\x3b\xd0\x9c\x80\xb6\x23\xf6\x36\x38\x0a\xa0\x20\x8f\xee\x0a\xff\x70\x81\x2d\x53\x07\xb2\x71\x83\x83\x23\x43\xde\xba\xa3\x60\x5d\xda\xd1\x7d\xdd\x70\xd6\x11\x40\x0d\xdd\x10\xd6\x38\xaa\x3d\x6c\x68\xa2\x8c\xf0\xe9\x7c\x1d\xed\xf6\xcc\xd9\xc7\x31\xa8\x4f\xf0\x40\x5a\x3a\x22\xdc\xba\x00\xab\x44\xd5\xb2\x18\x44\xf1\x4d\x13\x74\xac\x0c\xb1\xe5\x8d\xf4\xa9\x0c\x41\x25\x63\xcf\xe6\x9d\x88\x2d\x35\x0f\x6a\xaf\xbf\xa6\x4f\xa2\xf9\xff\x82\x60\x32\x32\x67\x80\xae\xcf\x93\x05\xd8\x21\x7c\x17\x9d\xbb\x63\xc1\x51\x54\x12\x32\xeb\x65\x97\x92\x65\xd8\x76\xc4\xbc\x43\x05\xc0\x2f\x40\xbc\x1d\x05\xdb\xaf\x7d\xcf\x4f\x7d\xd9\x23\x2c\x17\xee\x0f\x7a\x05\x55\xf5\x04\xba\x37\x74\x54\x84\x88\x93\x3e\x75\x71\xeb\x3f\x71\xc4\xcb\xb2\x0c\xc4\xe4\xa7\x32\x2f\x35\xac\x0e\x79\xa5\x91\x55\x79\x8d\xd0\xf5\xb3\xc1\x13\x19\xb7\xd8\xf3\xea\x79\xee\x3a\xcc\x68\xbd\xb9\xf3\x7c\x7d\x4c\x8f\x9c\xab\xa1\xeb\xf8\xeb\x7f\x43\xb4\x62\xae\xfd\x38\xe8\xc0\xd4\xc6\x39\x79\xcf\x66\x31\xde\xc3\x1a\xb5\xce\xd3\x93\x7e\xf5\xb2\x36\x2c\xb0\x9c\x71\xdd\x09\x66\x57\x70\x0f\xd9\x6b\xda\x55\x5e\x22\x71\x2f\x71\xae\xc1\x1a\xe5\xe9\x1b\x24\xbd\x16\x49\x49\x8b\x8d\x9f\x86\x7f\xb6\xc4\x1e\x07\x60\x80\xf7\x40\xd0\x74\xc2\xa2\x55\x72\xd3\x4e\x66\x6b\x63\x67\xbf\x7c\xbb\x3d\xd4\x2a\x23\x82\xdc\x19\x73\x96\x12\x68\x60\x53\x96\x81\x0a\x45\x6a\xc0\x81\xbb\xfd\x3a\x54\xb4\x48\x81\xfc\xfc\x45\xb4\x24\x5e\xe7\x24\x65\xb4\x87\xd0\x7f\x2e\xf3\xf7\x4a\xdd\x71\xcd\xfd\xd1\x6e\x92\xfe\x25\x7d\x33\x46\x45\xb0\xa9\xbc\x7d\x07\x26\x13\xfb\x9c\x0c\xde\xa9\xdb\x4c\x72\xbc\x87\x10\x9e\x10\x2d\x7c\xba\xf3\x66\xec\xd6\x7f\xbe\x3d\xed\x32\x74\x73\x07\xa7\xae\xef\x61\x73\x5a\xd3\xaa\x5c\xe9\x5d\xee\xcc\x16\xa1\x6e\xb2\xa0\xbc\xc7\xad\xc0\xa1\x1d\x88\x80\x32\x26\x0e\x7c\x7e\xc9\xe5\x4f\x5a\x25\x31\x70\x2a\x7e\x5d\xfb\x87\xc3\x6c\xe3\x13\xa3\x14\x75\x88\xae\xf9\x62\xc7\x2f\xa9\x66\xd2\x41\x63\x7c\x38\x8b\x83\xdd\xec\x93\x43\xbb\x86\x34\x3e\x92\x0b\x12\xce\x1c\xc9\x15\xc8\x3b\x31\xe9\x98\x62\x69\x06\x74\xea\x49\x35\xa4\x88\x09\xd4\xd2\x79\x05\x41\x37\x54\x63\x92\xad\x9f\x08\xe7\xb8\xde\x61\xae\x73\xe8\x1e\x48\x3d\x3c\x63\xb5\xae\x73\x4e\x18\xe7\xa2\x2f\xee\xd1\x23\x3d\x0c\xa6\x33\x55\xf3\xa4\x8a\x33\x06\x7e\x1a\x0e\x19\x71\xf3\x6a\xa9\x29\xfe\x06\x13\xc2\x1c\x4a\xef\xf9\x41\x84\x29\xc3\xb0\x72\xa5\x98\x49\x59\x28\x7a\x5e\x5c\x40\xbe\x02\xbd\x22\xb9\xa7\x9c\x7f\x3f\x53\x59\xd2\xbb\xe4\x93\xf5\x56\xda\xcb\xb0\xcb\x4c\x29\x3c\x7d\x94\x12\x65\xe7\x77\x39\x2d\x14\x8d\x68\xc0\x7a\x13\xc8\xde\xc8\xe5\xd1\xe1\xc7\xf0\x41\xe8\x98\x3e\xdd\xda\xa4\x64\x9d\xac\x15\x72\xa3\x9a\xe4\xc6\x48\x0c\xa5\x50\xe2\xe4\x46\x2d\xcc\x84\x9c\x1b\xab\x78\x1d\x28\xa3\x55\x2b\x2d\x98\xe0\x2e\x15\x18\xe6\x55\x53\x40\xfb\x76\xd6\x8d\xb5\x89\x16\xd5\x56\xa7\xb8\x15\x63\xab\xa8\x1d\x9a\x57\xae\x50\xf0\x4c\xf5\x68\x60\x21\x84\x7d\x79\xb6\xbb\x3d\xa8\x01\x7a\x60\xb1\xc3\xbe\xef\xd4\x8d\x2b\x3c\xd3\x9c\x6f\x53\xc0\x8b\xcc\x96\x7d\x93\x06\x9f\x56\x2b\xb3\x6e\x0c\x4f\x4c\xa6\xbc\xcc\x5e\x57\xd3\x59\x03\xcd\x80\x0a\x61\x78\x5a\x93\x77\x0e\x37\x7f\x4f\xe8\xe9\xf4\xb6\x66\x80\x98\x49\x68\xf9\x64\x9e\x10\x5e\x7a\x11\x9d\x97\x63\x6f\x3a\x05\xca\xea\xb1\xd7\xea\x0b\xc8\x13\x34\xb4\x2d\x5c\xc0\x80\x83\x0e\xc2\x4d\x36\x9c\xf8\x67\x3a\x49\x0d\x59\xeb\x4c\xb0\x81\x81\xda\x39\xa4\x6d\x96\x6e\x23\xfe\xd8\xd3\x8a\x5f\xab\xc7\xe8\x43\xbc\xfb\x01\x5a\x44\x74\xbf\xd4\x6d\x4a\x43\xff\x4a\x51\xa9\x56\x76\x61\xe2\x69\x6d\xb8\x7c\x37\x58\xd3\xb5\x4c\xe7\x84\x6d\x13\x91\xd7\xf4\x65\x26\xef\x30\x84\x4d\x49\x32\x00\x18\xd7\x49\xb5\xd4\xdf\xd3\x0d\x38\x0c\x6e\x57\x3f\xc4\x14\xd8\xfe\xfc\x5d\x71\x04\x70\x75\x6b\xec\x00\xd8\x8a\xc4\xaf\xc9\x25\xd1\xed\xe3\x7e\xae\xe6\x00\x4a\x23\xea\x0e\xf8\xb6\x0e\x48"}, -{{0x4e,0xd7,0x04,0x8a,0xa1,0x28,0x4d,0xbb,0xcc,0x24,0x89,0x38,0xb4,0x0c,0x35,0x74,0x21,0x93,0x59,0x7a,0xdd,0xaf,0xdd,0xe0,0x64,0x13,0xb8,0xd4,0xcc,0xfb,0xe1,0x37,},{0xbf,0x84,0x1f,0xe4,0x44,0xad,0xd1,0xf7,0xc3,0xea,0xcd,0xfd,0x07,0x84,0xb4,0xe8,0x55,0xd2,0x40,0x5f,0x40,0x21,0xcd,0x9d,0x82,0x66,0x07,0x1c,0x32,0xc8,0xa2,0x73,},{0x10,0x6a,0x9d,0xeb,0x23,0x27,0xf3,0x38,0xcc,0xb7,0x1b,0xcc,0x94,0xe2,0xfe,0x3d,0x2e,0x97,0x3c,0xe6,0xdd,0x8f,0xa7,0xba,0xca,0x80,0x8b,0x41,0x11,0x81,0x3e,0x3b,0xc3,0xb4,0xd8,0x8e,0xfa,0x6a,0x00,0xc4,0x71,0x0b,0xbf,0xe5,0x31,0x96,0xf9,0xab,0x3a,0x15,0x0b,0x16,0x54,0xb9,0x08,0xfe,0xac,0xf9,0xc1,0x3d,0xf2,0xd6,0x38,0x02,},"\xdc\xff\x95\x87\xd6\x04\x6c\x11\x32\xbe\x07\xdf\x26\xdf\x63\x82\xff\x92\xcf\xc8\xeb\x53\x45\xc5\x1d\xd5\x0d\xd1\x88\xee\x76\x9f\x10\xa4\xde\x5e\x88\x83\xd1\x16\x96\x7b\xea\x97\xd3\xb3\x2b\xc8\xae\xbb\x9f\x01\x3d\x6d\xf9\x52\xf2\x51\xc1\xa3\x12\x34\x6e\x72\xce\xe1\x35\xa1\xbf\xd7\x6b\xf3\x08\x0a\x35\xc8\x38\xb4\x4d\x75\x5f\x26\x3d\x21\x03\x10\xfa\x8d\x28\xc4\xca\x52\xf0\x8c\xac\x5b\x83\xa8\xa3\xb1\xdf\xc4\x6d\x9b\x75\x2d\x9f\xc7\x36\x49\xd0\x0b\xb9\xee\x99\x26\x50\x63\x9c\x22\x5d\xea\xc1\xf3\x9b\x9e\x80\x36\x89\xd1\x9e\x6d\x9f\x8e\xf4\xf5\x1f\x1d\x11\x60\x1f\xac\xf4\x10\xdb\x64\x8b\xcc\x82\xbf\x64\x87\x69\xa7\xdd\x59\xc6\xe8\xa2\x37\xdb\x23\x9d\x3f\x66\x1d\x78\x52\xc4\x26\xd3\x94\xa9\x05\x09\x52\x6a\x85\x9b\x47\x64\x59\xde\xdb\xe6\xd8\x99\x36\xc0\xf3\x98\x99\x95\x51\x1d\x4a\x57\x6e\x54\x2c\xce\x5e\x0d\xd7\xee\xef\xeb\x03\x26\xd3\x3f\x25\xc2\x2a\xb6\xe7\x69\x06\x33\xf4\xc9\xed\x2a\xad\xf1\xd2\x4f\x94\x86\x21\x23\xa4\x64\x04\x2c\xea\x19\x3a\x2f\x04\x79\xd3\x9b\xcd\x1b\xbd\x1c\x7a\x0c\xa7\xe6\x25\x8e\xd3\x73\x23\x72\xf5\x4e\x0e\xd5\xe3\xf1\xe2\xe4\xd4\xa0\x4c\x51\x0b\xee\x08\xd1\xc6\xd5\x70\xcf\xd6\x3a\xbf\x14\xb4\xee\xf0\xb9\x6f\x39\xca\x29\xe4\x3c\x52\xf2\xca\x3d\xfd\x46\x0f\x66\xe3\x02\x35\xb1\x59\xaa\xef\x2c\xc1\x56\x01\x29\x69\xfd\x3d\x15\x99\x78\xd6\xca\xa0\xa9\x45\x22\x29\x1f\x79\x89\xd8\xaf\x10\x83\x19\x96\x13\x7b\x68\xd9\x7f\xc1\x7f\x6a\x9b\xc2\x84\x5e\xf3\xdd\x47\xcb\xc3\x86\xe8\x97\x7a\x86\x54\x36\x34\x12\xda\xc3\xac\x51\xc6\x38\x17\xb7\xc0\x51\x87\x8d\xcf\x45\x8a\xb3\x63\x0d\xd7\xae\xf6\x8d\x27\x0f\x8d\xa7\x88\x0a\x46\x7b\x33\x04\xf5\xba\xed\xfb\xa9\x17\x3e\x7e\xfd\x00\x7c\x41\x2d\x17\x20\x9c\x56\xd2\x39\x68\xe3\x40\xb8\xa0\xed\xb4\x1b\x7e\x2a\x40\x88\xbe\xc0\x1b\x53\x2d\xf8\x9b\x52\x15\x81\x31\x31\x10\x7b\x7b\x47\x4f\x03\xc2\xe4\x7d\x43\x17\xf1\x1c\x4f\x51\x60\x90\x43\x04\x99\x7e\x76\xa1\x21\xa9\x56\x02\x35\x20\x8d\x79\xb2\xda\xb4\xf7\xe1\x96\x79\x32\x02\xc0\x90\x2c\xe9\xc4\xbf\xc1\x0b\x8f\xe3\x97\xe3\x5c\xa0\x25\x64\x54\x66\x2a\xe8\x78\xef\xb0\xa0\xa6\x06\xfa\xc0\xa9\x52\xc9\xf6\xba\xae\xb2\xd4\x5b\x25\x8c\x61\x75\x59\xc0\xed\x25\x28\xa8\x8b\x49\xaa\x44\xee\x43\x03\x5b\x0d\x79\x3a\xad\x39\x53\xc1\xa5\xa3\x46\x38\x66\xbc\x81\x5b\x1f\xfc\xe2\xff\x2b\x65\xe0\xfd\x47\xdb\xc1\x5f\x4e\x7a\x06\xbf\xab\xc2\x90\xfc\x62\x09\x0b\xf7\xd9\x48\x53\xf7\x7c\x04\x44\xa9\xb9\x0e\xfe\x77\xd1\xce\xb4\xbd\x39\xe2\x03\xbc\x88\x40\x11\x62\x4e\x68\x46\xe2\xa3\x71\x05\x8d\xab\xa6\x3c\x23\xf8\x6c\x42\xc3\xe3\x1e\xaa\x4b\xd7\xd7\xa4\x2a\xf2\xd5\x24\x89\x6e\x31\xba\xa3\xe2\x07\x63\xf8\x5d\xcf\xd5\x27\x75\xf2\x80\x72\xd8\x9f\x0b\xd4\xfa\xe3\x0d\x0b\x13\x7e\xe3\x7a\xb0\x63\xba\x06\xfe\x9d\x4e\xc6\x2a\xbb\x2f\xea\x0f\x81\xb8\xcb\xee\xfc\x03\x00\x80\xb8\x02\x6a\x58\xfd\x18\x67\xf6\x6b\xe1\x15\x4e\x65\xbf\xea\x7d\xce\xc5\x5f\xe3\x2d\x51\xfb\x0b\x4a\x8a\x5a\x8a\x04\x42\x63\x94\x3d\x6a\xc8\x01\x1c\x6e\x67\x01\xbe\xec\x3a\x88\x65\x58\x40\xc4\x89\x2d\x45\x0d\x31\x2b\x76\x52\xd2\x51\x47\x69\xf2\x3b\xfd\x6e\x70\x46\x46\x7d\xf2\x9a\x28\x7f\xf3\xc4\xc9\xd0\xe6\x4e\x6d\x9e\x4e\xde\xe1\xb9\x35\xd0\x76\x81\xd4\x70\x04\x35\x28\x86\xe8\x47\xb0\xc6\xd5\x76\x2f\xd4\x5a\x81\xa5\x3c\xce\x94\x76\xc8\x87\x22\x1a\xea\x6c\x0c\x82\xbb\xf3\xb2\x97\x93\x2e\x5b\x11\xe5\x38\xa3\x24\x5d\x63\xd7\xb7\xb0\x91\xdf\xa1\xd7\xb9\xa0\xe2\xdb\x66\x98\xa4\xc5\xe9\xfe\x93\x16\x62\xd7\xc6\xec\x6d\x9d\x5b\x92\xbc\x7e\x04\x15\x55\xdf\x4d\xf0\xca\x11\xca\xbc\x48\x5f\x9c\x55\x61\x38\xa7\x17\x45\xf0\x3b\x97\x83\xbb\x20\x0b\x72\xd2\x33\x69\x7e\x8b\xcf\x6b\x41\x17\xee\x67\x63\xd7\x92\xd7\x42\x22\x64\x85\x2f\x4f\x30\xf8\xd1\x89\x0e\x2e\xa0\x80\x98\x04\x0f\x7f\x28\x8e\x4a\xbe\x90\xb6\x3c\xab\x2c\x14\x37\x30\x60\x84\x0e\xf8\x27\xec\xc8\x46\xcd\x56\x0e\x90\xa2\x0b\x83\x05\xf4\x63\xc3\x6e\xa0\x38\x84\xa5\xdf\x4c\x25\xf1\xba\x9e\xa1\x25\x95\x2d\xc0\x91\xb9\x75\x16\xde\x1d\x28\x7c\x0e\x2b\xf5\x29\x77\x5b\xa6\xd2\xf8\xed\xe0\x3c\xb4\x2c\x1e\x40\x0e\xc8\x04\xa9\xdf\x08\xe4\x6f\x44\xb5\x06\x63\x46\xe3\xf7\xc7\xa1\xa8"}, -{{0xc7,0xec,0xa8,0x3e,0x94,0x85,0x76,0xbd,0x9f,0x27,0x8f,0xd7,0xb8,0x28,0x00,0xa4,0x1d,0x92,0xda,0x9b,0x72,0xd5,0xa1,0xcc,0xdb,0xbc,0x65,0x58,0x10,0x52,0x56,0x8b,},{0x07,0x6b,0x83,0x52,0xdc,0xa8,0x03,0x1e,0x85,0x3c,0x8d,0x90,0x99,0xc2,0xef,0x57,0x93,0x37,0xcc,0x7b,0x2b,0x4c,0x75,0xd1,0xa0,0x63,0xea,0x3e,0xc7,0x25,0xb7,0xfd,},{0x86,0x99,0x6a,0x1b,0x8e,0x49,0x5d,0x42,0x52,0x77,0xe9,0x7c,0xc0,0x83,0x05,0x49,0x34,0x9b,0xc2,0xb6,0xf3,0xdc,0xda,0x60,0xf3,0xb7,0xd3,0x50,0x1b,0x8b,0x50,0xb5,0xb4,0x58,0xcd,0xa5,0x8b,0x43,0x6e,0x23,0xc0,0x2c,0xd4,0xa2,0x2b,0x23,0x48,0x13,0xaa,0x9b,0xcc,0x3c,0x61,0xf9,0x83,0xc0,0xb7,0xef,0xec,0xa0,0xf1,0xbe,0xc2,0x0d,},"\x8d\x8c\xef\xd6\x73\x85\x5c\xcd\x8e\xb8\x53\x4c\x31\x2d\x33\x80\x05\xbb\x05\xf5\xb9\x50\x7d\x58\x85\x9e\x1e\x95\x3b\x0a\x4d\x91\x3b\xe7\x59\xd8\xed\xfa\x92\x89\x8c\x6e\x70\xa5\x3f\x81\x95\x4f\xc3\x44\xb4\xad\x62\x46\xb0\x10\x94\x81\xba\x6f\x73\xae\x63\x31\xab\xf2\xdf\x10\x8e\xb2\xe8\x5c\xeb\x08\x7c\x1f\x6f\xcf\xc9\xde\x2c\x1f\x13\x9b\xa1\x77\x1b\x72\x68\x03\x02\xd8\x11\xcc\xd0\xcc\xd4\xe0\xc7\xfe\xb0\x13\x2e\xb2\x0b\x33\x4e\x5a\xab\xe5\xf6\x11\x9f\xd8\x94\x7d\x9e\x88\x52\xe1\xeb\x1b\x74\x10\x7e\x17\x41\x00\xe3\xe6\xdf\x0c\x3a\x68\x13\x0c\xa6\x30\x94\x02\x59\x4b\xb5\x0c\x1c\x8e\x27\x74\xf1\x32\x14\x49\x6a\x7b\x1f\x34\x83\x85\xea\xbf\xbc\xcb\xac\x16\x5a\x5a\x2e\x7d\x9d\xea\x5f\xfd\x58\xb0\xbd\x88\xb4\x9c\xb3\x31\xec\xb7\xf4\xe9\xd6\xba\xe9\x79\x1a\xd7\x88\xe6\xab\x89\x26\xc1\xcc\x16\x15\xde\xaf\x4c\xc4\x00\xc7\x7a\x31\x61\x97\xbc\xa1\x90\x49\x95\xe1\x36\x5d\x1b\x97\x02\x64\x83\x76\x11\x69\x30\xf6\xf9\x11\x66\xe6\x14\x86\x29\xe7\x5b\xe2\xd0\x68\x95\xf6\xa8\xd1\x5d\x5a\x94\xca\x69\xb7\x12\xf3\x3b\xcf\x95\xbe\x0c\x1b\xe6\x90\x2b\xb7\x8b\x8a\x23\x0d\x7a\x85\x60\xc4\xd8\x4e\x23\x89\x55\x2a\x81\x57\x1a\xa6\x65\xc1\x9c\x2e\x93\xb0\xd4\x3e\x8c\x2c\xbd\x9e\x88\x5d\x70\x52\x51\x8b\x77\xc4\x7e\x84\x1d\x11\x9d\xc2\x8b\x65\xa7\x50\x4f\x66\x42\x71\xf0\x6c\x7f\xf3\x93\xf8\x25\xb1\xe5\x93\x0d\x02\xb9\xc7\x00\x35\xe2\x92\x41\x1c\x4a\xed\xf6\x60\x47\x00\x69\x70\xe3\x49\xdf\xca\x7f\xb4\x1c\x10\xfd\x53\x7e\x35\x25\x2e\x10\x9e\x33\x36\xd7\xa8\x2a\x14\xde\x5d\x55\x40\xc6\xfc\x65\x71\xd5\x77\x4f\x39\xb7\xc4\x03\xe7\xb8\x87\x5e\xc2\x15\x87\x7e\xfc\x6c\xc8\xea\x48\xb1\x86\xb4\x68\x21\xea\x5e\xf2\xba\x8b\xac\xd4\x0d\x79\x7e\x6a\xdd\x06\x41\x32\x83\x14\x5b\x60\x46\x2b\x35\x03\xc5\xb8\x81\xd7\x9a\x59\x29\x55\xd1\x8a\xfa\x08\x96\x9e\x31\x45\x7f\x5b\x27\xda\xec\x01\x03\x38\xed\x86\x7f\x30\x08\x78\xfd\x87\xce\x32\x18\x80\xb8\x60\xa0\xc6\x42\x84\xca\x2d\xc1\x5f\x5e\x53\x10\xe1\x0e\x6a\x73\xa7\xea\x65\x0e\xa9\xd3\x73\x69\x4d\xa4\xdd\x42\x9a\xe7\x41\x2e\xf9\xb2\x9c\x83\xb3\xb0\x68\xc7\x47\x69\xf4\x31\xce\x06\x15\xf9\xff\x4f\x82\xba\xac\x47\xb4\xbc\xe9\x04\x49\xec\x41\xc2\xa2\xd5\x73\xd9\x2b\x92\xe0\x56\x31\x48\x61\x65\xbc\x71\x0e\xf5\x84\x0f\x80\xda\xe9\xf9\xdd\x5c\xff\xd4\xeb\xf5\xd1\x07\x46\x51\x0c\x5f\xcb\xfe\x62\xcb\x97\x03\xc0\xb1\x54\xc8\x6f\x10\x81\x66\x72\x49\x76\x70\xa3\xb0\x15\x0b\xb4\xe1\xb0\x3b\x3b\xd5\x44\xc1\x2a\x90\xc3\xed\xcc\xd7\x90\x0e\xbb\x5b\x31\xc9\x11\x17\xcc\x82\x81\xa3\xc4\xed\x04\x99\x8e\x99\xae\xd4\x1b\xb4\x1f\xce\x99\x90\xa4\x06\x48\x5b\x14\xdb\xe3\xbc\x1a\x5f\xcf\x77\x19\x50\x79\x90\xda\x3b\x0b\x3c\x68\xad\x40\xd8\x95\x0c\x0d\x49\xce\xd1\x01\x93\x19\xa3\xf3\x6a\xff\x6c\xaf\x75\xd7\xf9\xa0\x93\x3d\xd3\xab\xdd\x76\x92\xa1\x56\x2f\x06\x13\xfe\x4a\x27\x8d\x5c\xe4\xc8\xda\xfb\xb5\x5b\x2e\xc2\xaf\x2b\x24\xe8\x39\x6f\x58\x7b\x17\x0c\x9c\xa6\x54\x75\x08\xfa\xcd\xe7\x34\x90\xdf\xb0\x1e\xb6\x65\x7e\x3f\x4f\x27\x23\x04\xb7\x0b\xf0\x47\xa4\x3a\x2b\x58\xe5\x56\x8b\xc5\x2b\x2c\x8d\x4c\x03\x21\x9a\x5a\x8b\xd3\xdc\x06\x43\x18\x59\x13\xc0\xaf\x74\x11\xf8\x1b\x77\xbe\x2a\x9b\xfd\x5c\xb2\x69\x77\x11\x3d\x26\x58\xa9\x71\x92\xb4\x1c\xf6\xc7\x01\x1b\x0f\xf6\xa1\x1c\xbf\xf3\x50\x55\x46\x32\x2f\x0b\xef\x60\x97\xe4\x6b\x36\x49\x2b\x01\x6a\x45\x62\xe0\x92\xb6\x7c\x3f\xcc\xc7\x78\x0e\xa2\x74\xd9\x6d\x59\x58\x49\xf7\xe2\xa5\x6d\x79\xed\xcb\x32\xd7\x84\x04\x9f\xc1\x32\x4a\x5b\xee\xfc\x24\x19\x3a\x66\xe1\xca\xc4\xa1\x3a\x81\x1b\x90\x95\x83\xcc\x91\x0c\xf0\x8d\x4b\x10\x4d\xbd\xb8\xa6\xf2\xb2\x1f\xbc\x1d\xb1\x17\x5a\x1a\x23\x56\xa6\x3d\x3e\xea\x9d\xbb\x85\x37\xd2\xc6\x86\x27\x54\x3d\xf0\xd1\xf8\xfd\x8d\x57\xa1\x8b\x0d\xbd\x69\xb9\x20\xcb\x9b\x28\x6e\x3c\x07\xae\x44\xae\x2e\x1b\xee\xc0\x1c\xee\x6b\xa9\x88\xb5\xd1\xaf\xb9\x97\x90\xb1\xdd\x91\x06\x55\xc4\x3d\x7f\x2a\x3e\xd3\x75\x4b\xa4\x65\x16\xd2\x78\x70\x55\x59\xf5\x74\x16\x22\xa9\xab\xb5\xc8\xf2\x3f\xa9\x76\xa9\xd1\x46\x94\x8a\xde\x6b\xa6\x60\x8a\x35\xe4\xe0\xd3\x30\xe8\x2e\x96\xa2\xbe\x6c\x78\xad\x0c\xd4\xd8\x70\x4e\x57\xce\xa1\x46"}, -{{0x7b,0x46,0x9d,0xf9,0xc8,0xf7,0x84,0x89,0xab,0x47,0xcc,0x70,0xa8,0x85,0x03,0xf1,0xb8,0xf3,0xd9,0x29,0xc3,0x3f,0xea,0xb1,0xc5,0x03,0xf0,0x96,0x9a,0x3a,0xc3,0x7b,},{0xa8,0x14,0xc7,0xe3,0x73,0xd0,0x11,0x3b,0x90,0x62,0x4a,0x8a,0xb2,0xbc,0xa5,0xcf,0x53,0xbf,0x52,0x8e,0x39,0xfc,0x3d,0x36,0x7d,0xe1,0x54,0xb9,0x4b,0xb2,0x2f,0x1d,},{0x18,0xfa,0xf8,0x2d,0x08,0xe1,0x06,0x8e,0x9f,0x98,0x3d,0x81,0x2f,0x05,0xfd,0xb6,0x92,0x9d,0x27,0x23,0xdb,0x1f,0x77,0xc4,0x5a,0x74,0xbb,0x09,0xcf,0xf2,0x77,0x73,0xb5,0x4c,0xe8,0xf4,0x3b,0x30,0x15,0x41,0x91,0x12,0xe7,0x25,0xea,0x7a,0xcd,0xa4,0xb2,0x3b,0x81,0x20,0xe7,0xb0,0xcf,0x42,0x01,0x53,0xe5,0xb0,0x3d,0xd0,0x61,0x09,},"\x1c\x0f\xd7\x45\x0e\x29\x67\x5c\x93\x09\x16\x38\xc2\xac\x93\x3c\xa9\x97\x76\x6e\x38\x0e\xc3\x3a\x92\xb8\xa7\xe1\xa1\xed\x98\x21\xc7\x5f\xcc\xb5\xc5\xf3\x76\x0e\x76\xd0\xe8\x81\x03\x11\xdd\xc6\x24\xea\x87\x42\x13\x1c\x1c\x43\x08\xf4\x17\x8e\x04\xd0\x49\x60\x69\x3d\x84\x6c\x1f\x51\xd8\x77\x3b\x6d\xeb\x34\x43\xd8\x74\xb9\xe2\xde\x3b\x77\x78\x51\x85\x51\x8b\x2e\x9e\xe7\x36\xc6\x3a\x39\xc8\x21\x2c\xa8\x66\x9e\x16\x1d\x13\x1b\x1a\xb2\x26\x4f\xdd\x72\xdc\x56\x28\xb1\x1c\x06\xf2\xaf\x9f\x07\x89\x04\x7b\xdd\x4e\xbb\x5d\x55\x89\x9f\x74\xdc\x4e\x12\xe7\x97\x53\x63\xf6\x3a\x8d\xa7\x6b\x55\x85\xc1\x6b\xb6\xd5\x5b\x05\xfa\xde\x87\x13\xd1\x9c\xad\x1a\x21\x16\x40\x26\x26\x91\xaa\xc9\xb4\x37\xa9\xec\xf8\x9a\x92\x46\xec\xdb\xa1\xff\x0b\xea\x78\x49\x4c\xee\x15\x29\x62\x16\xea\x6b\xb8\x82\x47\x9d\x24\x37\xc9\x49\x4a\xc7\xfa\x4f\x30\x15\xd1\xd3\x14\x9d\x55\x64\xd7\xc1\x1a\x7e\x7b\x61\x4f\x7d\x3e\x9d\x45\x4f\x0a\x05\xb0\x40\xa1\xe0\x6f\xe7\x83\x7c\x2a\x9d\xa2\x79\x4d\x91\x8b\xff\xa9\xe6\x1a\x0c\x3f\x08\x9f\x6c\x9f\x7e\xea\xc5\x86\xe3\x4b\xf9\x44\x70\xd9\x13\xda\x41\x37\x1c\xac\xdf\xc7\xee\x8b\xd1\x13\x56\x55\x56\x69\x24\xea\xdf\x09\x6a\xc0\x30\xa6\x59\x02\xc1\x03\xb1\x72\xd1\x2e\x88\xf0\x53\xfc\x56\xee\x73\xf3\x18\x70\x81\x70\x83\xaf\xa8\x02\xf7\x66\x8b\x81\x5e\xe7\x90\xf7\xd4\x0b\x43\x7a\x2e\x6d\xb2\xf0\xfb\x26\x83\x6b\x4b\x23\x31\xeb\xa5\x55\x39\x61\x4c\x0f\xe1\x72\x40\x24\x2d\xd3\xaf\x73\x83\xbc\xff\x7d\x3f\x47\xd6\x54\x4b\x08\x72\x0c\x0a\x52\x44\x1f\x74\x11\x93\x5d\xd4\xa9\x52\xd3\x86\x51\xa8\x00\x05\xfa\x3e\xb0\xea\xec\xc7\x35\xd2\x90\xe8\xbd\x5e\x31\xb7\x40\x14\x0e\x13\x6b\x2c\x00\x25\x23\xd8\xeb\x2a\x0a\xb5\xbd\x68\x70\x02\xb3\xb9\x26\xf7\x5e\xb6\x90\xd1\xda\x73\xad\x23\x58\x92\xf3\xb2\x3a\x75\x6b\x60\x5a\x43\x7c\x00\xe0\x62\x13\x04\xe8\x10\xf9\x9e\x31\x4c\x4d\x63\xe3\x22\xd9\xb6\x98\x15\xf3\x82\xff\xa1\xec\x62\x80\xfc\x0e\x64\x1c\x8a\x6f\x6f\x7f\x61\x98\x5b\xd3\x56\x7e\x0f\x44\x0d\xe9\xf7\x62\x17\x15\xda\xcd\x07\x42\x8c\x00\x90\x15\x4d\x59\xce\x6d\xb4\x01\x69\xc6\x58\xac\x5b\xf4\x4b\x67\x67\x1f\xe1\x9e\x4b\x5b\x38\xaa\xd2\xd3\xd4\xe1\x90\xa5\x50\xaa\xd4\x18\x83\x52\xf7\x98\x1a\x6d\x88\x06\x25\x02\xdf\x86\x79\x13\x50\x39\x2d\x41\xce\xfa\xcb\x24\xe3\x7b\xc7\x00\xcb\x02\x91\x90\xc3\xb1\x82\x14\x77\xe1\x17\xd5\xa4\x62\xfb\x3e\x79\x13\x3b\x10\x73\x59\x89\x66\xf5\x2b\x63\x25\x6d\xbf\x32\x6a\xce\x14\xdb\x0c\x80\x05\x8c\xf0\x0d\x68\x9a\x0a\x58\x11\x1a\xf1\x69\x27\x44\xbf\x79\x1b\xcb\xb4\x27\xa3\x72\x24\x6e\x95\x01\xa8\x5c\xd5\x20\xc6\x1a\x1e\x59\xee\x18\x0e\x8c\x97\x19\x2f\x60\xfa\x5d\x3a\xb0\x5d\xf8\xd8\x55\x1c\x1a\xc6\xca\x0a\x9a\x01\x2f\xfe\xce\xb3\xc1\xf5\x21\x41\x1e\xdb\x65\x09\xbc\x27\x8a\x65\x1e\x12\x9e\x96\xb0\xad\xc7\xae\xd7\x07\x22\x1c\xae\xac\x22\x98\x84\x41\x3d\xaa\x10\x59\x5d\x22\xd1\xdb\x70\x82\x12\x5f\x4f\x96\x95\x00\xa1\xd4\x8d\xac\xda\xe8\x0f\x40\x29\xc1\x63\xdc\xd7\x9d\xdc\x64\x68\xfc\xda\x16\x37\xb8\x7d\xdc\xf2\xa3\xd9\xb4\xd2\x99\xa0\xe5\x39\x4d\xf9\x0e\xd0\x3b\x62\x13\x7b\xa6\x7b\x9f\xea\x8a\xe1\xf0\xd2\x2f\x91\xc6\x3a\x24\xb5\x93\x4f\x74\xc2\x65\xc4\x3f\x1b\x92\x3d\xb9\x80\xad\xfc\xee\x83\x13\xda\x52\x01\x76\x73\x0e\xf9\x73\x6b\x27\xe6\xba\x32\xd1\x7e\xa6\x9d\xca\xc6\xf4\xa0\x16\xed\xfe\x2d\xb5\xa5\xbb\x3b\x64\x93\x2f\x70\x11\xf1\xc4\x53\xbb\xe8\x8b\xba\xc8\xc7\x03\x5f\x93\xfe\x39\xb5\x81\xfc\xaa\x7a\xaf\x08\x2f\xbe\xd0\x04\xfd\x1f\xd5\xa4\xe2\xd9\xc1\x97\x16\x60\x4b\x19\xce\x19\x9e\x21\x69\xa7\xbe\x51\x8d\x5f\xad\xd2\xac\x31\xb9\x54\x78\x08\x2a\xc9\x13\x06\x00\x8d\xe4\xec\x0e\xf4\xc9\xf9\xd6\xf9\x6d\x2f\x66\xd6\x2f\xaf\xc2\x19\x40\x82\x80\x8a\xf0\xd6\x7b\x9f\xba\x0d\x18\x9b\x05\x5f\x06\x1c\xca\xc2\x4b\x27\x61\x0b\xfb\xd5\xa2\x23\x2d\xd6\xf3\xc8\x90\xa9\xb1\x26\x64\x71\xb3\x22\xe9\xe1\xbf\x97\x75\x7b\xef\x72\xab\xce\xe9\x3b\x05\x1f\xc9\x23\xcf\xd4\xe7\x23\xbe\x3e\x17\x14\x3f\x38\xee\xbb\x90\x0b\x5b\xbc\xf7\x30\x47\x32\xb9\xc0\xa1\xc5\xfc\x95\x09\xa6\x93\x58\x0a\xe7\x3a\x4c\xdf\xc5\xfb\xf2\x0c\xe8\x1e\xbc\x83\x5c\x6c\x90\x9d\x83\x11\x41\xb1\x94\xf6"}, -{{0xdf,0xec,0xde,0x7a,0x56,0xa1,0x8c,0x1f,0x19,0xd8,0x0a,0x19,0xa4,0xf1,0xda,0xdd,0xd0,0xbc,0xec,0xb0,0x1e,0xec,0xad,0x6d,0xfc,0xa0,0xf9,0x57,0xa9,0x14,0xed,0x7a,},{0xaf,0xba,0xa6,0xe7,0x3e,0x85,0xb0,0x2b,0x25,0xa4,0xb5,0x87,0xec,0xb8,0xc4,0xdf,0xb7,0x9a,0xa9,0x20,0x27,0x61,0xef,0xa8,0xd1,0xdf,0x2c,0xd0,0xaa,0x63,0x16,0xc4,},{0xb4,0xfd,0xe5,0x5b,0x91,0x6c,0xf6,0x00,0x68,0xf1,0x9b,0x25,0x35,0x1c,0x14,0x10,0xdc,0xf6,0x6b,0xfc,0x40,0xf9,0x6d,0x1b,0xa2,0x36,0x8b,0xc2,0xb9,0x11,0x5a,0xaa,0x5b,0x2d,0x1c,0xf0,0xe3,0xdf,0xca,0x02,0xac,0x90,0x2a,0x94,0x3e,0x24,0x89,0xa5,0x68,0x1b,0xba,0xfe,0xd3,0x9c,0x6e,0x33,0x21,0x1a,0x9c,0xb2,0xff,0x6e,0x54,0x09,},"\xae\x6e\x8f\xf6\x5c\xcd\xe6\xf2\x64\x84\x95\x08\x26\xb4\x36\x23\x05\x8a\x5e\xfe\x02\x0b\xb1\x9b\x7d\x8b\x4e\x25\x76\x8b\x69\x27\x34\xfe\x07\xc9\x13\xb9\xe8\x81\x26\xbe\xcb\xf1\x4a\x0f\xd0\x20\x5b\x39\xfc\xc2\xae\xc3\x73\xf8\xc1\x84\xc6\xa9\xbb\xbb\x84\x44\x9a\x7c\xa3\xb9\x20\xad\xa0\x88\x01\xdf\xc6\x6f\xf1\x9a\xeb\x92\xf2\x55\x53\x99\xa4\x30\x27\x7a\xe2\x2d\x23\x75\x4e\xaa\xce\x3c\x73\x84\x67\x97\x53\x6d\xd7\x1a\x56\xf4\xb5\x84\x2c\x0f\x41\x0d\x19\x89\xac\xac\x5d\x80\x5d\x26\x57\x2c\x0f\x3a\x64\xdd\x20\x71\x66\x22\x12\xd5\x2f\xe9\x9e\x59\xd9\x66\x04\x77\x77\xf9\x03\x0f\xa4\xfd\x2e\xe7\x4b\x7a\x7c\x9f\x7c\x34\xa6\xdc\x7e\x03\x59\x3a\x13\xd6\x4c\xe6\x24\x53\xee\x3c\xa3\x0d\x84\x67\x28\x39\xf1\x9f\x1c\x15\xd0\xc4\x5d\x27\x55\xbb\x39\x4a\xcf\x4d\xcb\x7f\x7f\x07\x11\xac\x40\xea\x46\x61\x2e\xa3\x7a\x76\x07\xad\x32\xe8\x18\x26\x5f\xab\x19\x33\xf5\x09\x4e\x2d\x03\xbc\xfa\xa5\xf6\x16\x67\xf3\xb3\x7f\x00\xc4\xc5\x8d\x9b\x41\xb9\xaf\x39\x00\x48\x2b\x0f\xfb\x4f\xa4\x37\x6a\xa0\x40\x00\x9d\xec\x2f\x45\x25\x79\x9c\xb0\x05\xf3\x9d\x74\xcb\x2d\x8d\xce\x8c\x20\xc2\xc3\xf5\x40\x97\x03\xaf\x15\x6c\xfb\xa2\x8a\x9d\x91\x64\x39\xcb\x29\xf8\x3d\x24\x29\xce\x62\x23\x51\x9e\x75\xe1\x5c\x7c\x7f\xa2\x15\x11\x9e\x07\x3f\xa7\x97\x4d\xb1\x4f\x7a\x01\x09\x3f\xaa\x94\xad\x52\xab\x1e\xad\xce\x1a\x89\x36\x6c\xa1\x3a\xdb\x89\x06\x64\x38\xa2\xbe\xb7\x30\x34\x17\x0a\xa4\x2d\x9c\x2d\xdb\x97\xc1\x4a\x17\xc3\x09\x43\x76\xd2\xa3\xff\xd8\x09\x5f\xc4\x05\x3d\x91\xd1\x6e\x06\xd2\x76\x93\xa1\x31\x0f\x01\xa7\x51\x11\xcf\xed\xa8\x92\xc3\x97\x2a\x13\x3a\x09\xad\xda\xa8\xf7\x41\x45\xf8\x86\x81\xb6\xd2\x77\x96\x4b\xfe\x38\x55\x1a\x2c\x61\x9f\xa3\xca\xe3\x94\xac\xb2\x9c\x94\x10\xb4\x5e\x10\x1b\x17\x40\xe8\xb2\xaa\x6f\xeb\xc3\xa4\x5d\xad\xb9\xd9\x58\x9d\x59\x7e\x57\xcd\x94\x7b\x68\x4c\xc3\x55\x24\x6c\xe6\xc3\x26\xdd\x98\xcf\x92\xb6\xee\xa3\xba\x5a\xb0\x37\x00\x62\x26\x36\x32\x4d\xc1\x22\x2c\xd7\x48\xfa\x07\xbf\xd3\x9a\x1e\x06\x98\x09\xe5\x67\x14\x1a\x61\x3e\x2e\x8b\xe9\xdd\x39\x8a\xb6\xbe\xaa\xfd\x85\xff\x36\x28\xee\x2a\xa3\x2d\x0a\x57\xbb\xac\xf9\x56\x19\x0b\x5c\x42\x42\xeb\x5b\x85\x87\xd2\xfd\xcb\x07\x41\xb9\x41\x6a\x05\xf5\xfe\xcb\x1f\xb2\xd6\x47\x88\xdc\xe7\x83\xc1\xf6\x3e\x60\x64\x1f\xce\x5e\x1d\x2b\x18\xa9\x50\x0c\xd6\xa1\xfd\x33\x5c\xc1\xdb\x46\xef\x04\x75\x2b\x2d\x22\x07\x2e\x6d\xfc\xfc\xfa\x56\x9b\xb2\x5e\x45\x7a\xfe\xb6\x3a\x4f\xbe\xdc\x29\x3a\xd9\xd1\xab\xa4\xe3\x94\xaa\x10\x97\xe1\x2b\x0f\xc9\x0c\x89\xf7\x6d\xf0\xd6\x44\x1f\xa9\x98\x08\xb6\x0b\xe0\x7d\xfc\xc7\xf9\x01\x0b\xbf\x90\x33\x55\x6d\x5e\xe2\xd4\x48\x93\x7b\x78\x34\x93\x92\x0f\x68\x1e\x4d\xa7\x08\x67\x10\x97\xe1\x99\x48\x1b\x8e\xf0\xe0\x15\x0d\x7c\x28\x51\xdf\x44\xc5\x45\x12\x2f\x9b\x0e\x5b\xa2\xee\xff\x2d\x98\x8d\x56\xd9\xbb\xb5\x5d\x98\x96\x11\x11\x51\xa4\x36\xaf\x06\x5e\x0c\xad\x17\x8a\x2c\x9f\xa8\xf6\x97\x4e\xcd\xf0\x9a\xdf\x01\x33\x00\xcf\xfe\xda\xf4\xb8\x79\x1b\x46\x7b\xa7\x93\x3a\xda\x5d\x63\x2d\xb4\x4e\xd6\xdc\xf2\xaa\x64\x89\x17\xbe\x63\x37\xd2\xe2\xd2\x06\x85\x6d\x08\xf9\xee\x7b\x5e\x2f\x14\xdd\xc6\xd3\xac\x42\x92\x15\xa8\x79\x23\xad\x32\xd5\xdc\xfe\xe3\x68\x63\x16\xdd\xd1\xb2\x7b\xb1\x93\xa5\xfc\x05\xc8\x93\xa9\x39\xa5\xb9\x89\x87\x36\x6c\x82\x9e\x39\x2f\x48\x5e\xa1\x5e\x22\xcd\x8f\x85\x7a\x13\x4a\xfa\x98\xf3\x72\x15\x57\x6d\xdc\x5a\xab\x4f\x2d\x10\xca\xaf\x05\x00\x59\xa3\x35\xf2\x4b\xcd\xcb\xac\x81\x9f\x66\xdb\x07\xaa\xbd\xfb\x76\x27\x1d\x17\xbc\xe2\x2c\xba\x46\x3a\x80\xaa\x89\x2d\x0d\x8e\x05\x5f\x94\x8d\xf7\xf6\xe6\xc3\x00\xda\xef\xfd\x3a\x23\x6d\xdd\xcf\x23\x8f\xe1\x06\x66\xa5\x7c\x6e\x3a\xe7\xe3\x67\x3d\x35\x57\x8f\x8b\x8e\xa6\x9d\x3c\x08\xe0\x14\x0a\xfd\x3e\xe0\x30\xb2\x2a\x37\x21\x60\xf9\x08\xa3\x78\xf8\x10\x1b\x5f\x59\x69\xfe\xa3\x10\xee\xd3\x7a\x00\xd9\x73\x02\xd5\xc2\xdb\xe8\xcc\x60\x00\x75\xdc\xcd\x33\xad\x63\xd2\x65\xaa\xf6\x0e\x24\x1c\xe3\x11\xbe\xd7\xdd\x5e\x27\x45\x24\x1a\xe0\x2a\xe5\x32\xd1\x5c\x18\x88\x6e\x81\x81\x38\x75\x1a\xfc\x51\x85\x0e\x50\x6c\x6d\x31\xa8\xee\xf4\x51\xad\xfd\x4b\x3d\x26\x6b\x41\x5a\x7e"}, -{{0x07,0x82,0x8c,0x58,0x0e,0xbf,0x9e,0x1d,0x82,0x5a,0x59,0xc3,0xbf,0x35,0xf0,0x72,0xae,0x12,0x33,0x55,0xbd,0xcc,0x24,0x9e,0xec,0x7f,0x2f,0xc5,0x75,0x5e,0x29,0xb5,},{0x58,0xe5,0xed,0x85,0x10,0x0b,0xbd,0x9b,0x22,0x21,0xaf,0xc9,0xc9,0x31,0x84,0x33,0x0a,0xd5,0x9e,0x13,0x85,0x60,0x62,0x44,0xbf,0x00,0x3b,0x8d,0x20,0x18,0x50,0x1b,},{0xbb,0x09,0x36,0x04,0x39,0xa8,0x2d,0xee,0x5c,0x7d,0x85,0x77,0x9e,0x54,0xc1,0x3f,0x88,0xe0,0x6d,0x38,0xf4,0xb9,0x49,0x60,0xfe,0x17,0xa1,0xeb,0xca,0xa3,0xee,0x2f,0x33,0x0c,0x64,0x91,0x54,0xbb,0xc8,0x75,0xa4,0x07,0x6c,0xf0,0xbb,0xf7,0xee,0xbf,0x7b,0x8d,0x08,0xd5,0xaa,0x4b,0xe7,0x41,0x38,0x81,0x24,0x5f,0xc2,0xd2,0xb6,0x01,},"\x0e\xda\xd5\xca\xe6\xed\x98\x43\xe9\x1c\x50\xd9\x34\xcf\x55\xdd\x65\x8f\x3d\x25\x20\x39\xcd\x6c\x75\xbe\x4f\x6b\x86\x6f\xb7\x5f\x35\xc8\xf9\x8f\x17\x21\xd7\xe6\xd9\xd9\x8a\x22\xe0\xb4\x93\x4d\xcc\x12\x92\x61\xbf\x67\x23\xb2\xfa\x7a\x99\x5e\x35\xc4\xbd\x79\xc5\x81\x6a\x32\x16\x07\xd9\xdc\xce\x39\xfe\xfa\x1d\x55\xde\x4e\x76\x17\x54\x8e\xc3\x85\xc3\xde\x01\xe3\x66\xbf\x50\xc4\x57\xa5\x55\xe9\x32\x07\x0e\x2a\x5a\x01\x97\xb7\x9e\xfb\xe7\x00\x6f\x0c\xec\x78\xb6\x0e\xbb\x8f\xa8\x78\x1d\x8e\xb7\x32\x6e\xdc\x30\xe6\x2d\x32\x97\xa1\xe0\xa1\x11\x71\x08\xc4\x6e\xe5\xdb\xef\xc6\x59\x42\x89\x33\x5e\x78\x0d\x55\xa0\x84\xf5\x52\xda\x3f\x36\xd3\xc4\xc6\x17\x8b\xa7\x4d\x4d\xec\xef\xc5\xa3\xb8\xc4\x7c\x16\xf5\x34\xbd\xb6\x08\x95\xd3\xd5\x4c\xd2\xbb\x26\x6b\x39\x9e\x4d\x4f\xb4\x8d\x7a\x8c\xde\x17\xf4\x24\x12\x56\x07\x37\xd3\xc0\x6e\x29\xdf\x52\x4d\x0c\xbd\x30\x93\xef\xca\x1c\x8f\xed\xca\xa1\x24\xab\xb2\x7a\xbd\xac\x6a\x29\xe0\xe8\x24\x6a\xbd\x6f\x5f\x53\x19\x50\x03\x7f\x76\x32\x3a\xa5\x6c\xc3\xfe\xfa\x60\x30\x41\xd5\x5f\x19\x29\xe2\x77\xe7\x2c\xda\x1f\x96\x54\x1d\x2a\xf3\xe9\x0c\x0f\x0e\x28\xbe\x19\x6d\x8f\x69\x21\xf3\xcd\x57\xa7\x92\x6b\x86\x0a\xa1\xbc\x40\x35\x76\x89\x2a\x96\xb9\x31\x90\xae\x38\x3f\x63\x1b\x72\x80\x26\x58\xb2\xe8\x45\x1d\x52\xa2\xf4\x5d\xb4\xf8\xbc\x3b\x0e\x4e\x50\xb6\xd6\x03\xa5\xbd\xd3\x0c\x23\x42\x00\xad\x7d\xeb\xb9\x63\xf5\x8a\x4f\xa2\x03\x30\xb3\x69\x64\x49\x44\x5a\xa3\x71\x82\x48\x42\xfb\xf3\x26\xd9\x01\xdf\xe3\xbe\x04\x54\x52\xa3\x74\x0d\xd1\x60\xe7\x27\x33\xf6\xe2\x73\x35\x25\xa2\x9a\x86\x5f\x6f\x50\xd5\x3b\xf7\x19\x1c\x59\x9c\x87\x6f\x5c\x9c\xa1\xe3\xfa\xd7\x96\x06\x48\xe0\xd4\x71\xf7\xd5\xc0\x1c\x67\x3f\x42\xd6\x59\xbc\x3d\x98\xdb\xf0\x7d\x8f\xeb\xfb\x99\x5d\x17\xf9\xa0\x2c\xd6\xc3\x9f\x2d\xdc\xd0\xf1\xd2\x22\xb9\xe1\x1f\x2d\xd7\xd3\xc7\x51\x82\x24\xbb\x6b\xfb\x8b\x7c\x58\xfe\x8a\xc1\x05\x40\x59\x03\xa1\xb9\xda\x75\x16\x71\x5b\x7a\xfc\x38\xa5\x55\xe6\xbb\xcd\xba\xd4\x6e\x34\xe5\x76\xfe\xa3\x4c\xe3\x57\x34\xed\x20\xaf\x5d\x88\xee\xb1\x04\x7a\x26\x60\x64\x8b\xbb\x11\x3a\xd9\xdb\x8c\x53\xed\xb6\xed\x98\x71\xa1\xe4\x4c\x9e\xd2\xdf\x56\x56\xfb\x2b\x28\x06\xec\xf0\x3b\x1e\xca\x9e\xab\x50\xa6\xea\xab\x55\xb9\x33\xb2\xdd\x1f\x21\xd4\x50\xde\x9d\x5c\xb2\x23\x2f\x07\xa3\x92\x08\x1b\x0b\x4b\x88\x5d\x54\x78\x9e\x2f\x75\xbf\x2c\x4c\xda\xd8\x78\x98\x9b\x1d\x6d\xab\xd9\xed\x23\xc7\xc5\xb0\x35\x6a\x7d\x9e\x73\x35\x29\x0d\x7c\x85\xb9\x66\xe8\x01\x84\xbd\x07\x99\x86\x02\x88\x6d\x70\x76\x19\x35\x65\xc8\x1c\xcc\xda\x4c\xc7\xd3\x3c\x85\xd9\x05\xb1\xbe\xb6\xe8\xe7\x41\x8e\x8a\xca\xed\xf0\xd9\xa3\x2a\x7d\x29\xd0\x7c\xf4\x4d\x31\x19\xd4\xe7\x89\x68\x20\xb7\x7d\xe6\x4b\x65\x5e\x4f\x14\x88\x00\x43\x4a\xf7\xbd\xb2\xa5\x6b\x25\xeb\x94\xea\x39\xf2\x16\x95\x96\xbb\x2b\x11\x76\x1f\x08\x2b\xae\xc0\x88\x85\xf4\xa0\xeb\x6c\x95\x76\x71\x35\xa7\xf7\xcd\x72\xe7\x43\xd2\xdf\xf1\x44\xdd\x8b\xaf\xb1\xb3\x18\x00\x6e\x58\x76\xf8\xe2\xcb\x44\xaa\x58\x8f\x90\x62\x66\xac\x67\x11\x9c\x17\xf5\xde\x11\x4e\x72\xe4\x2a\x1f\xb3\x99\x44\x32\x1a\x11\x1f\xa7\x95\xff\x70\x17\xf2\xfb\x8c\xaf\x48\x2f\x55\xd7\x7a\x80\x85\x54\x28\xde\xd7\xec\x20\xac\xec\xca\x83\xf8\xd1\xeb\x13\x7b\x58\x8c\xcb\x74\x5c\x10\x5f\x2b\x2c\xa4\x1c\x3a\x9f\x49\xd3\xc6\xe9\xd7\xc6\x48\xb0\x03\xb9\x70\x7c\x90\x64\x62\xed\xad\x61\x7a\x8c\xfb\xf9\xbc\xc6\xc5\xfb\x6f\xa9\x84\x32\x5d\x65\x82\xe2\x8f\x62\x00\x53\x83\xf3\x38\xdf\x5b\x38\xfa\x9d\x19\xc2\x2a\x2a\x7e\xa1\xd6\x8a\x92\xd1\xd9\x3b\x7f\xb0\xb8\xf3\x3b\xc8\x76\x0f\x28\xae\xb1\x43\x9a\x8b\x07\xf3\xda\x58\xdd\xb1\x55\xb4\x98\xcb\x09\xc7\x5a\x55\x96\x83\x8a\x65\x01\x3e\x24\xd5\x64\x0d\x08\x42\xa7\x69\x93\x22\xcf\x3f\xfc\xb5\x70\x3f\x41\x4f\xfd\x16\x88\x60\xba\xd3\xe3\x08\xb2\xb5\xbf\x3c\xdf\x7f\x36\x3b\xf9\xaa\xf4\xb3\xbc\x42\x4c\x14\x6c\x6f\x54\x21\x43\x0f\x9f\x47\x6a\xa3\x4a\x0c\x6e\xe8\x01\x31\xfc\x4d\x4d\x97\x07\x23\xa2\x18\x6a\xe3\x62\x5e\x28\x6d\x17\xdd\xdc\x43\x5c\xcb\x00\x83\x16\x78\xab\xa5\x84\xa6\x2d\xbf\xf0\x02\xbe\xad\x6e\x11\xe2\x3c\x54\xd3\x3c\xf3\xa4\xb2\x31\xa9\x08"}, -{{0xf0,0x8e,0xe8,0xda,0xa7,0x3e,0x1f,0xeb,0x61,0xa8,0x8e,0x06,0x2d,0xfb,0x10,0x03,0xc8,0x57,0x8a,0x0d,0x53,0xbd,0x3b,0xc9,0xe5,0x89,0xef,0xb9,0x2f,0x68,0xbe,0x14,},{0x76,0x69,0x2c,0xe8,0xd1,0x16,0xec,0xcb,0x89,0x70,0x77,0xed,0xca,0xaf,0xdd,0x3e,0xb4,0x4e,0xa1,0xa4,0x86,0xb9,0x0e,0x49,0xe9,0x7f,0x96,0x69,0x01,0x01,0x55,0x02,},{0x66,0xdf,0xa4,0xc1,0x57,0x5b,0xef,0xf2,0xf5,0xa2,0x30,0xb2,0x8c,0x58,0xc3,0xee,0xa0,0x73,0x6d,0xf3,0x79,0xd7,0x55,0x59,0xbc,0x9d,0x37,0xa9,0x57,0x9d,0x12,0x1c,0x05,0xc3,0x73,0xe8,0x48,0x4c,0x97,0x47,0xef,0x44,0x77,0xe8,0x0c,0x4b,0x2c,0xb4,0xdd,0xf1,0x6a,0xe9,0xfd,0xfa,0x08,0xa0,0x75,0x47,0xd1,0x07,0xdc,0xea,0x12,0x03,},"\x64\xde\x90\x04\x4d\x0e\x76\xbc\x02\xfc\xff\xcb\x75\x26\x36\x67\xb3\xbd\x73\x3b\x40\xbf\xb2\x6c\x6c\x52\xfd\xb4\xb0\x78\x22\x78\xca\xba\xe4\x1e\x21\x29\xea\x40\x17\xe9\x4d\xe8\x60\x87\x96\x4f\x66\xd8\x62\x07\x98\x74\x67\xa1\x68\x8f\x9f\xab\x3f\xfb\x2f\x1d\x00\x63\xbf\x62\x6c\x94\x13\x67\xc1\x2e\x31\x9a\xb7\xca\x30\x20\xc9\xb3\xa7\x21\x5a\x19\x30\x3e\x2d\x0e\x89\x88\x79\x1d\xe0\xd8\xe1\x63\x2d\xaa\x38\xc7\xf3\xe7\xf6\xe4\x8c\xe1\x22\x14\x3d\x1e\x2c\xb6\x61\xba\x77\xc6\x9e\x6a\x71\x09\x11\x64\x4b\xc1\x10\xff\x58\xbb\x00\xb5\x29\x08\x20\xce\x30\x97\x0e\x7f\xde\x18\x9e\x14\x0e\x5c\x70\xc7\x83\xee\xd5\x3f\x0e\x2a\xc7\xec\xae\x4f\x27\xdb\x81\xd1\x5b\x86\x46\xfa\xa9\xc5\xa3\xae\x2b\x7f\x47\xcd\x58\x0d\x77\x07\xb0\x02\x49\x9b\x4c\xfe\xb8\xc5\x91\xaf\xdf\x1c\xc6\x2a\xf2\x59\x5c\x18\x4a\xbc\xf0\xb2\x62\x3a\x1b\xae\x60\xaf\x70\x26\xb2\x8d\x05\x40\xb4\x15\x26\xe3\x02\x0f\x81\xb8\x94\xeb\x3f\xe3\x1b\x72\xb2\x1a\x32\x60\xda\xe3\x21\x0c\x4c\xe4\xfd\x69\xe2\xe5\xea\x0c\x86\x32\xa5\x83\x26\x2a\x12\xb3\xa8\xb1\x6c\x9c\x12\x06\xad\x73\x02\x30\x37\xcf\x30\x65\x3c\xb8\x0a\xa7\xdf\x83\x14\xb0\xf5\xbc\x6e\x9d\x5f\xa0\x0b\x00\x9d\x55\x52\xd8\x3b\x79\x70\xb5\xbc\x4b\x99\x84\xf6\x9d\x1c\xca\x9c\xe4\xcb\x74\xdd\xd2\xd8\x79\xd3\x73\x12\xa0\xe1\x59\xd7\xa6\xaf\xb7\x7a\xc5\x85\xe6\xb4\x59\xc5\x51\x30\x4e\x1e\xeb\xfb\xca\xb4\x3a\x10\xb5\x05\x92\x4e\x03\xea\x33\x2f\x5d\x02\x0a\x55\xc7\xaa\x68\x3c\x54\x1d\xcf\x77\x90\xa2\x40\xaf\x07\x9b\xab\xa9\x40\x96\xb4\x60\x60\xfd\x7a\xfe\x90\x56\xca\x99\xe6\x88\xdf\x28\x0a\x9b\xe8\xc8\xc7\x3e\x6e\x6f\xb0\x52\xa3\x3e\xb3\x32\x8a\x7f\x60\x25\x42\xfe\x28\x0c\x89\x0e\x3c\xca\xf2\x2c\x7f\x34\xf8\x7b\x5e\x5b\xa7\x84\xb4\x72\xb1\xe1\xa9\x93\x47\xa9\xe0\xd2\x40\x85\x8d\x12\x77\xa5\xc6\xb3\x49\x38\x3f\xe4\xfd\x55\xcf\x92\xe6\x9f\xaa\xd3\x26\xb8\xd6\xdb\x46\x23\x30\x26\x22\x1e\xe6\xd0\xa1\xc4\x24\x65\x33\xc4\xa0\xe5\xbd\x17\x2e\xb8\x93\x6a\x9c\x0d\x30\x06\x65\x38\xe3\xeb\x4a\xd5\xcb\x98\x77\xfd\x86\x1b\x48\x2b\x30\x15\x0a\x06\x10\x41\x61\x64\x7e\x01\xd0\x04\xd9\x97\x40\x3e\xe0\x67\x26\xcb\x97\xe2\xe2\x5f\x18\xc6\x68\xee\xe4\xc5\xbf\x72\x52\x98\x03\x18\x9e\xe6\xa7\xae\xc2\x38\xd5\x90\x6e\xa5\xae\x10\x72\x2c\x9a\x61\xa7\x8a\xea\x52\xaf\x33\xea\xac\x75\x40\x6b\x1a\x60\xbe\xfb\xaa\xd4\x84\x76\xd9\xff\x88\x7f\xd2\x83\xeb\x16\x55\xbc\xc0\x7c\xf7\x53\x33\x14\x36\xdb\x5b\x3b\x13\x03\x2f\xf9\xc3\xd6\x96\x38\x0e\x9f\x5a\xbf\x50\xd3\x55\x6f\xda\x0d\xf0\xb5\x38\x97\xa7\x37\xac\x7a\x3b\x87\xc2\xa8\x32\xb0\xc7\x27\x3e\xa9\xfc\x54\xa7\x67\xf1\xa8\x12\xbf\x01\x64\xbf\x75\x21\x63\x0b\x81\xb9\xdd\x93\x0d\x92\xee\x2c\xa2\x8e\x32\x03\xb7\x7b\xc0\x82\xce\xb3\x7d\x55\xed\xbc\xb7\x1d\xf0\xb7\x92\x36\x78\x9a\x25\xd4\x18\xcb\xb9\x55\x44\xe2\xce\xf3\x3b\xbd\xeb\x27\xa3\xf7\x90\x9c\x1f\x49\x8f\x47\x13\x5a\xe9\x03\x3a\xdf\x25\x0a\xd4\xf6\x57\x53\x61\xe4\xcf\xcc\x9b\xcf\x4b\x90\xc3\xad\x47\xa3\x44\x22\x97\xa2\x23\xcc\xa8\x43\xd7\x20\x5e\xd0\x8a\x9b\x87\x16\x0a\x6d\x01\xb4\x6a\x7d\x1c\x84\x4e\x8d\x1f\x18\xf6\x18\x68\x2b\xfb\x22\x95\x5f\x39\x5b\x2a\x57\x90\xa5\x1a\x69\x64\x99\xd9\xe7\x1a\x50\x1f\x3f\xa5\x46\xde\x9b\x10\xae\x47\xbc\xee\x42\xba\x7f\x86\x9f\xb9\xce\x4e\xd7\xc6\x45\x33\x26\xc0\x34\xcf\x05\xd9\xf1\xe3\xc2\x00\x70\x1b\xa7\x52\xda\xbb\xd8\x68\x52\x1c\x3d\x8f\x80\x67\x2d\x42\xf6\xcf\x45\x64\xf0\x8c\xd7\xb3\x90\xe6\xd4\x9d\xd9\x00\x90\xaf\xdb\x84\x48\x6f\xfc\xaa\x4e\x84\xd8\x86\x82\x74\x4d\xc0\xa8\x78\xfa\xa7\xcd\x44\x0a\x8b\x27\x67\x10\x90\x20\x81\xf4\xdc\x84\x17\x46\x19\xa6\x6e\xa3\xa3\x71\xf9\x55\x05\x40\x0d\x99\xfa\x99\x90\x17\x71\x0c\x8e\x27\x14\xbe\x60\x94\x9d\x46\x13\x10\xf7\xd4\x3a\x0d\xc1\x23\x51\x6d\x77\xd3\x62\x21\x3f\x9f\x75\xa5\xa1\xc3\x93\xaf\xfc\x49\xea\x15\x1d\x46\xa8\x1f\xfa\xd2\x39\xf2\x8c\x07\xf6\x5f\x59\xea\x07\x7d\x9a\x4d\x9c\x75\x2d\xe4\x9b\x9e\xf3\x6b\xe6\x0d\x11\x2d\x79\x5f\x58\x8b\x00\xef\x6e\x77\x30\xde\xa6\x5e\x10\x16\xda\x0d\xd4\x62\x37\x0e\x0b\xa5\xc6\x60\x00\x1e\x45\x7c\x08\xb4\x36\xda\x29\x03\xb6\x29\x06\x93\x20\x84\x72\x8c\x81\x67\x1c\xbf\xb0\x79\xbb\x29"}, -{{0x27,0x2d,0x64,0xde,0x50,0xb1,0x31,0x2b,0xee,0x23,0xd7,0xf4,0xce,0xa5,0x08,0xa8,0xfc,0xcf,0x3e,0x9b,0x32,0x4e,0x97,0xb1,0xc8,0xe7,0x25,0x02,0xf6,0x1f,0xbf,0x45,},{0x33,0x49,0x8c,0x3b,0x71,0x2a,0xb9,0xc0,0x1e,0xc7,0x6b,0x2e,0xfe,0x2b,0x83,0xad,0xd1,0xe1,0xf2,0xb5,0xeb,0x78,0xf2,0x16,0x92,0x32,0x34,0x51,0x82,0x0c,0xbe,0x10,},{0x33,0x81,0x4c,0x6e,0xf3,0x75,0xab,0x96,0x37,0x69,0xb2,0xde,0x4a,0x25,0xe7,0x02,0x0f,0xcd,0x97,0xf7,0x8f,0x8f,0xc9,0x34,0x55,0xc4,0xb1,0xc2,0xbd,0x45,0xd4,0xb0,0x1e,0x19,0x29,0x00,0xe3,0x12,0x22,0x65,0xfc,0x55,0x2c,0xd5,0xc5,0xf0,0x0e,0x93,0x1e,0x3a,0x18,0x3c,0xca,0x5b,0xa0,0x80,0x2d,0xaf,0xde,0xbb,0x79,0xeb,0xeb,0x03,},"\xd6\x26\x0d\x7e\xec\x5d\x43\x62\x08\xe7\xe7\x37\x65\x5e\x09\x71\x81\x42\x70\x19\x44\x05\xe3\x6e\x39\xf8\xf1\x7b\x64\x9f\xbc\x16\xc0\xf3\xd7\xf2\xbe\xf5\xeb\xc0\x2b\xb1\xc4\xdf\x48\xe8\x47\x0a\x3e\xae\x8a\x3c\xca\xf6\x40\xab\xcc\x09\x4a\xa9\x11\x50\xff\x1a\x8c\xf1\x16\x96\x93\xeb\xf5\xac\x00\x34\xb9\xb9\x19\xec\xf1\x7d\xb7\x91\xdf\xe5\xfe\xdc\x90\x91\x8b\x23\xe5\x4e\x90\x04\xa1\xae\x77\x1c\x21\x3e\xd7\xed\x73\x34\x43\x4e\x5b\xc0\x2c\x0d\xda\x2b\xd1\xa8\x76\xfb\x82\x4a\x19\x7b\xc9\x96\x13\xb1\x40\x9e\x70\x52\x31\x0b\x08\x20\xda\x71\x44\x69\x29\xae\x7c\xfd\x3a\xfb\xa0\x42\xde\x54\x57\x8a\x5b\xfd\x94\xc1\x54\x43\x91\xa3\xd9\xac\xbd\x56\x63\xef\x65\xc6\x92\x0d\x78\x51\x6d\xec\x1c\xd5\x5f\x6e\xb7\x29\x0b\xa0\xaa\xf9\xa1\x71\x65\x82\x00\xb2\x4a\x47\xa0\x71\xb9\x6f\xea\x03\xc6\xca\x7e\xd0\xd6\xfe\x67\x5d\xd6\x37\x61\x83\x3d\x75\xbc\x5e\x58\xa9\x58\x58\x2d\xb0\x2a\x60\xc6\xce\x0a\x63\xf4\x2b\xa8\x37\xae\x77\xc1\x7a\x32\x70\x5f\xd9\xca\xfa\x58\x7b\x55\x5d\xd4\x61\x98\x51\x07\x97\x94\xe2\x4e\xb4\x46\x08\x83\x5a\x6f\x48\x24\x92\x0d\x57\x7a\x27\x03\x96\xc9\x57\x3b\xc7\xd8\x2f\xe2\xaa\x04\x65\x95\x66\x13\xa2\xc5\x08\xcf\x24\x32\x33\x7a\x36\x5e\x6c\x98\x4c\xba\x91\x7f\x0c\xf8\x42\xaf\x12\x2d\xc8\x9d\xea\x95\x8d\x41\x8c\xae\x44\xa6\xe4\xed\x26\x3a\x41\x5f\xf9\x94\xa5\xff\xb2\xff\x13\x91\x3d\xf2\x14\xbb\xfe\x90\xa3\x4b\x24\x7e\x71\xab\x73\xf7\xff\x00\x4c\x23\xac\xfd\x90\xc7\x67\x61\x1a\xa5\x58\x14\xc6\x69\x64\x16\x8e\x56\x8b\xa7\x5b\xf3\x49\x03\x59\x7c\xdc\xac\x78\xc2\x4b\xb9\xf1\x4f\x5c\x86\xa5\x1f\x36\x4f\x9a\xb4\x1e\x46\x4a\xee\x64\xfa\x50\xa1\xc1\x59\xcb\xd8\x50\x83\x2c\x50\x4a\xb4\x2a\x58\x4a\x96\xd5\xae\xe0\x82\xd8\x2c\x1e\xdd\xa1\x93\x38\x16\x0b\x8d\xcf\xa3\x41\x9b\x3a\xf6\x4d\x9c\xfb\x10\x4f\x98\xf9\xd3\x5e\x53\x94\xe2\x32\x28\xe2\x75\xc8\x7d\xb5\x0c\xa8\x67\x54\x0b\x88\x0c\x7a\xf2\x9f\xbf\x53\x42\x94\x58\x1c\x22\x24\x0b\xcd\x4d\x7d\x2c\x20\xff\xc3\x67\x33\xad\xa2\x76\x53\xd3\xae\x1a\x8c\x22\x03\xea\xc6\x26\xe2\xe9\xbb\x4b\x52\xce\x52\x3e\x5a\xdb\x3b\x2c\x10\xdc\xf7\x8c\x2a\x1e\x62\x6a\x16\xeb\xfa\x1b\xdb\x8c\x16\x14\x93\xa5\xaa\xa2\xd8\x4b\xfa\xa0\xf2\x02\x7f\xfe\x4e\x9e\xae\xb3\x32\xeb\xda\x7c\xbb\xb6\x77\x76\x9d\x78\x51\x7a\xdf\x72\xf8\x23\xa7\xf8\x44\x16\x5a\x07\x98\x78\xd2\x58\xfd\x95\x22\x5c\x21\x17\x78\x37\xe6\x9c\x19\x68\x5a\x05\x1c\xa9\x2b\x12\x0b\x7d\x86\xd7\x85\x95\x47\x1f\xfc\x42\xa5\xe6\xe6\x43\x1b\xe7\xb6\x4f\x80\x76\x45\x8b\xac\xd6\xc7\x29\x03\xcc\x34\xfc\x63\xa4\x0c\xf3\xdf\x00\xef\xf9\xd6\xee\x9a\x8f\x39\xd2\x5e\xad\x81\xa8\x12\x88\x88\xb0\xa1\xac\x0e\x5e\x3a\xd9\x27\x71\x2c\x14\x14\x6a\xdf\x82\x87\x70\xff\x95\x87\x09\xeb\x19\x28\x8e\x77\xbb\x70\x73\x48\x81\xe9\xe0\x16\xcd\x29\xe7\xd0\x89\x93\x41\xff\x6b\x29\x7a\xc7\x96\xbb\xde\x48\x6e\xc3\x59\x49\xf6\xa3\x2b\x2c\xa6\x47\x38\x59\x15\xec\xba\x3b\x9f\x02\x25\x08\x71\x45\xc1\x8d\x65\x59\xd3\xa3\x1d\x6f\x22\xfc\x49\xf8\xa6\x31\x5f\x1d\x32\xab\xee\xb7\xcf\x2c\x2c\x77\x6e\xa7\x35\x0f\xd5\xeb\xc0\xe0\xf2\x65\xba\xcc\xc2\x69\x7a\x7c\x8c\xa4\x0c\x13\x5f\x6c\xfc\xb0\xb5\x8a\x61\x43\x19\x60\xff\xa9\x06\x57\x09\xa9\x61\xa6\x33\xd5\x70\xb7\x3f\xb4\x49\x1d\xe5\x2a\xd0\xd7\xb2\x04\xb6\xe9\x97\xb0\x37\xed\xe3\xf7\xec\xa8\x20\xa7\xcd\xb2\xc6\x9a\xc2\x91\x48\xbe\x35\x23\x50\x8a\xe7\xe4\xc3\xd1\xa7\x17\xf5\x5a\x82\x1d\x14\xc3\xb6\x4f\x08\xca\x9a\xe4\x96\x13\xb1\x15\x77\x3e\xf6\x18\xd3\x21\xc9\x08\xbd\x21\x56\x71\x7a\x43\x4e\x50\x89\xa5\x94\x8c\x04\x5c\x8d\xa8\xa4\xbd\x86\xed\x5f\xab\xc6\xb1\x34\x66\xe6\xde\xda\x58\x32\x07\xd2\xad\xa2\xb2\xab\x9c\xb1\x54\x3d\xf7\xa3\x73\x4d\xfb\xc6\xfc\x42\x81\x06\xd4\x84\x47\x24\xa1\x3d\xf4\x2f\xaa\xb1\x8c\xa8\x9d\xb2\x0a\xc9\xbc\x27\xb8\x53\x94\x66\x7c\x5a\x27\x79\xca\x63\xed\x7a\xc2\xb7\xc0\xd4\x12\x23\x91\xee\x46\x02\xd6\x1e\xa0\x38\x17\x64\xfb\x72\xdc\xc2\x24\xe6\x5e\xae\x2b\xc4\x50\x6b\x0f\x09\xe2\x32\x05\xd0\xbb\x21\xc7\x7d\x82\x87\xc1\x65\xe0\xb4\x2c\x55\x15\x79\x77\x8a\xcb\x72\x58\xa2\x47\x9d\x7c\xf2\x5b\x90\x2e\x8d\x0d\xa4\x29\xbd\xe3\x6b\x45\x90\xda\xe9\x6f\x52\x54\x81\xac\x83\x78"}, -{{0x0c,0x9f,0xe5,0x59,0xad,0x1e,0xd3,0xba,0x16,0x4d,0xac,0xea,0xcb,0x02,0x35,0x67,0xb2,0x43,0x03,0x20,0xb6,0x71,0x5d,0xe7,0x32,0xa0,0x3c,0x59,0xc7,0x30,0x31,0x30,},{0xe7,0x0f,0xc4,0x66,0xfb,0x2a,0xcd,0x74,0xe0,0x99,0xc3,0x6e,0x2c,0x22,0xfa,0x51,0x29,0x0b,0xdd,0xe9,0x6d,0xf9,0xc3,0x1b,0x6d,0xfb,0xfd,0xc2,0xe2,0xc1,0x4a,0x40,},{0x6c,0xd8,0xae,0xd9,0x7d,0x9c,0x62,0xd5,0xfd,0xae,0x59,0x7d,0x06,0x1c,0x0c,0x2b,0xc3,0x7e,0x42,0xdf,0x06,0xb8,0x32,0x7a,0x46,0x8f,0x92,0xb3,0xf4,0x38,0xa1,0xe6,0xb6,0xb1,0xef,0x2b,0xe7,0x85,0x49,0xa2,0x89,0xfd,0x3f,0xc1,0xa6,0x29,0x9e,0x5a,0x33,0xd5,0x39,0x6c,0xb4,0xfa,0xc1,0xe8,0xe9,0x98,0x2f,0x0c,0xb3,0xd2,0x0d,0x07,},"\x26\xeb\xc6\x48\xcf\x8c\x79\x65\xec\x6e\xbe\x96\x5d\x9c\x79\x2b\xed\x90\x65\x5a\xd4\x40\x18\x3c\x6d\x70\xea\x64\x67\xbb\x8e\x6f\x04\xec\x84\x3f\x33\x31\x56\x91\x7b\xf4\xc5\x1d\x0e\xd0\xf2\x8b\x7c\xd3\x1b\xc1\x2c\xf8\x40\x68\x6b\x82\xb0\xc2\xc3\x50\xbb\xda\xc8\x05\x33\x37\x25\xd6\xb6\x9c\x2a\xb7\xf3\x4e\xe5\x93\xfa\x1c\xcc\xed\xf3\xf0\x64\x2a\x68\x8f\xcc\x1c\xd9\x8b\x09\x87\xd0\x1f\x71\x3a\x2f\xa6\x41\x6c\x96\x19\x21\xde\x0c\xc2\xc9\xec\x7a\x55\x58\x55\xe7\xfc\xd4\xc7\xdd\xaa\x14\xfd\x91\xec\xb0\x42\x24\xe1\x76\x1b\x7d\x6b\x35\xf4\xaa\x56\x18\xa5\x00\xca\x00\xd1\xca\x24\x51\xb5\xd3\x68\xaf\xde\x3a\x40\x7e\x78\x31\x35\xf3\x90\x19\xa5\xb9\x84\xe8\x2a\xc2\x79\xc0\x5e\x48\xc2\x95\xeb\xd1\x56\x38\x21\xa0\x74\x3c\x52\x24\x6b\x5d\x2b\x20\x34\xe3\xae\xb6\xce\x7c\x5c\xf9\x19\xe7\x4a\x9c\x7b\xbc\x9e\x25\xda\x30\x43\x0e\xb1\x6e\xcf\x38\x37\xeb\x38\xa0\xf5\x59\x79\x2a\x72\x98\x90\xba\x83\x10\x26\x0f\x8a\xeb\x9b\x5a\xf0\x0e\xb6\x33\xc1\x2d\xee\x02\x26\x28\xba\x41\x8d\x75\xcf\x18\xde\x2f\x2e\x65\xe4\x9b\x1a\x69\x68\x4d\x61\x27\xef\x48\x1c\xa8\x61\xec\xbc\xe3\xbe\x86\x49\x7e\x65\xdf\x4c\x5f\xcd\x08\x17\xc9\x71\x6b\x59\xf2\xa2\x63\xd5\xe9\xeb\x60\x68\x39\xf8\x5c\x5a\x36\x58\x37\xb0\xfb\xe2\xc4\x27\x4d\x66\xcb\x2c\x65\xed\x36\x5f\xab\xf5\x8f\x15\xbe\x52\xb5\x1c\xb6\x01\x18\xca\x4f\x73\x0d\x44\x73\x59\xf7\xef\x34\x6b\x75\x02\x17\xd4\x7b\x2e\x79\xc8\x6c\x0c\x62\x81\x6a\x0c\x7c\x18\xa2\xce\x2b\x68\x8e\x0c\xce\x0d\x75\x23\x21\xe7\x9b\x42\x38\x57\xda\xc5\x9f\x8f\xbe\xb0\x94\x11\xe7\x16\x69\xef\x9a\x26\x43\xf2\xe9\x9f\x38\x7a\xc1\x83\xe0\xb0\xac\x72\xc5\x9a\x0c\x3c\x18\xc0\xde\x8b\x01\x08\x78\x07\x4a\xcc\x1a\x2b\x39\xf9\xdf\x99\xd9\xf8\xf8\xb5\x2f\xef\xe4\x94\x3c\x52\x5f\xd4\xd0\x6a\xd8\x78\xe4\x66\x08\xab\xf2\x7a\x54\xbc\x50\x06\xf6\x47\xdb\x72\x48\x51\xdb\x7c\x45\x78\xae\x66\x58\x3d\xc4\xbb\x51\x8e\xf0\x28\x89\x03\x47\xe8\xfc\xe0\x92\x7d\x7d\x9a\xf3\xab\x5d\x0d\x2d\x20\x2a\x40\x26\xaa\x2e\xa7\x48\x79\x62\x67\x6a\x60\x32\x98\xe7\xd2\xe7\xb9\x09\x21\xee\x1b\x52\x80\x6d\x71\xa7\x64\xe0\x3e\x25\xdd\xd6\x84\x8f\x61\xd4\x6f\xad\x3d\x00\x8e\x10\xee\x5c\xd5\xa3\x39\x0f\x9d\x15\x8a\x44\x37\xef\x61\x5f\xc9\x0a\xc5\xbf\x3a\x9d\x68\x2e\x12\xc3\x39\x8a\xc7\x76\x80\xd2\x2c\xd1\xa6\xa5\x6e\xc3\xb2\x5c\xed\xe8\x67\xed\xd3\x83\x15\x9c\x61\x64\xd6\x3e\x9c\xd1\xc9\x56\xac\x72\x35\xff\xfa\xe9\x36\x16\x6c\xcd\x35\x89\x8e\x29\xc9\xb4\xca\x4e\x29\x25\xda\x32\x3b\x6f\xbf\x67\xcf\xd5\x96\xc8\x8a\x1a\x35\xa8\x35\x98\x51\xdd\xcb\xa8\xf6\x13\x4a\x9f\xaa\x24\x4d\xcb\x47\xe6\x91\x27\x6e\xe6\x25\xcc\x20\xad\xce\xc2\x1c\xbe\x77\xa3\xac\xb9\xba\x72\xf0\xc9\xd3\xda\x7e\x9c\xd5\xbe\x3b\x95\x99\x0b\xa5\x4a\x9f\x31\xaf\x17\x1f\x95\xae\xea\xd3\x33\x1c\xb1\x88\xa5\xb2\xc6\xf5\x39\xac\xb4\x8b\x98\xb3\xf7\x34\x1f\x60\x25\x1c\xb6\x04\x29\xcc\xd9\xcf\x32\xf0\x09\x20\x5f\x27\x53\xfb\xbb\x26\xaa\x53\x17\x43\x42\xad\x18\x4d\xab\x68\x70\xc0\xfb\x52\x93\x01\x19\xd9\xf9\x7d\x84\x89\xa6\x00\x76\xaa\xdb\x2e\x96\x05\x4a\xc7\xcb\x7f\x84\xe1\x3c\x75\xbb\xf9\xe4\xd9\x24\xd2\x27\x2a\xfe\xf0\x87\x19\x15\xe2\x43\xce\x66\xfc\x2a\x88\x88\x51\x35\x35\xb1\x0b\xb4\x07\x9c\x80\x6b\xd9\x49\x28\x1e\x28\x28\x35\x23\xd0\xd2\x10\xb3\x1e\xf6\x2a\x95\xdc\xae\x0c\xd2\x52\x90\xc7\xed\xf2\xc2\x4b\x43\x28\x22\xde\xbe\x34\x7f\x1c\xae\x94\x5f\x57\x28\xc7\x1b\x54\x03\xef\x14\xe7\x2c\x3d\x83\x42\xe1\x98\xb3\x62\xee\x20\xf8\x09\xe4\x6a\xca\x01\x5f\x35\x47\x7f\xf8\x9a\xc4\xb3\x7e\x66\x15\x85\x6f\x7e\xa2\x51\xfb\xfe\x13\xf9\x06\x52\x59\xb0\x94\x6a\xae\xf2\x49\x43\x27\x0a\x85\x4d\xe8\x89\x78\x00\x33\xd6\x3d\xda\x54\x47\x99\x8a\x3e\xd7\xe5\x06\xae\xb5\x1e\xa3\x7b\x68\x1a\xc3\x07\x67\x97\xac\xdb\xfc\xc2\x78\x83\x63\x0a\xdb\x72\x26\x0a\x46\xaf\x0a\x60\xd5\x3f\x66\x54\x56\x6e\x20\xd6\x08\x8c\xd4\x8e\x23\xb2\x8d\x81\xf0\xee\xd2\x05\xb9\x2a\xaf\xd9\x61\x64\xd6\xd3\xca\x3f\xc8\xb1\x71\x80\x4e\xe9\xfc\xe7\xab\xae\xd2\xea\x4d\xdf\x9c\xb2\xb3\xae\x73\xa7\x0e\xd6\x3d\xe4\x5e\x14\x10\x14\x28\xd0\xa7\xa2\x26\xdb\x39\xab\x6c\xd0\x43\x74\x08\x0e\x69\x83\xf0\x18\xce\x93\xda\x4c\x89\xac"}, -{{0x15,0xd7,0x5a,0xd8,0xe4,0xaf,0xb1,0x26,0x34,0xcc,0x8e,0x60,0x0f,0x1a,0x42,0x67,0xef,0x95,0x84,0xf4,0xc4,0xac,0x44,0xff,0xfe,0x4b,0x9f,0xcb,0x88,0x5c,0x9d,0x2a,},{0x09,0xd1,0x26,0xf0,0x17,0xe0,0x16,0x97,0x74,0xe8,0xc3,0x7a,0xb3,0x79,0x26,0x3a,0x80,0x75,0x74,0x61,0x27,0xc2,0xd1,0x1e,0xcb,0x0e,0x4c,0xb4,0x54,0x70,0x9f,0xf1,},{0xa8,0xf2,0xf4,0xb9,0xe2,0x07,0x2c,0xa9,0xfa,0xde,0x37,0xfd,0xd6,0x2d,0x8d,0x02,0x42,0xfd,0x4d,0xaa,0x09,0xfd,0x85,0x6e,0x75,0xf4,0xe3,0x43,0xc7,0x26,0x0e,0xa6,0x77,0xf7,0x53,0xa6,0x27,0xae,0xd0,0x8c,0xb9,0x6c,0x44,0x4e,0x29,0xbd,0xb5,0xb5,0x38,0x5d,0x43,0x84,0x3b,0xbe,0x79,0xa3,0xdd,0xa3,0x6e,0x1e,0x11,0x01,0xc5,0x0f,},"\xd1\xce\xa2\xb7\xe9\xaf\xc1\xf0\xfa\xb8\x90\xd2\x70\x0a\x5a\xe4\x1e\x15\xe7\xd3\x4d\x3b\xf1\x9d\x0f\x34\xd9\xf9\xf0\xab\x98\x12\xdc\x7c\x2a\x8d\xc4\x4c\x8e\xe7\xf3\x78\x87\x61\xec\xd9\x88\xee\x72\xc7\x36\xb6\x2a\x7c\xac\x3c\xc9\xb7\x38\xe9\x38\xdf\x77\x87\x37\x7e\xb9\xff\xd1\x20\xd4\xff\x58\xcf\x1c\x06\x75\x63\x3f\x7e\x83\xc4\xb1\x15\x54\x8f\x14\xd2\xf7\x0c\x6d\x48\x22\x11\x44\x3a\x84\x99\x59\x95\x58\xc1\x42\x77\x98\x0f\xa4\x2a\x78\x42\x79\x07\xf7\x3a\x41\xf5\xf6\x69\x3b\x2f\x75\xfe\x5e\x7a\x6f\xf0\xa6\xc3\xa4\xe2\xed\x1d\x0d\x96\x8d\x5c\xc9\xd6\xf1\x3d\x41\xc3\xd2\x91\x39\x6a\xe7\xe4\x34\xe6\x64\xb2\xff\x24\x3e\x7f\x6d\x88\x01\x02\x10\x07\x8c\x39\xb5\xa5\x76\xca\xf4\x09\xbb\x47\x11\xb3\xee\xfc\x48\x6b\x67\xb7\xff\xea\xe0\xcb\xac\x6a\x0f\xbd\xf5\x34\x3f\xb2\xae\x4e\x05\x7e\xdc\x8c\x9d\x2e\xd3\x1e\xae\x9e\xc8\x3d\x2b\xed\xd2\x19\xeb\x98\x9b\x2d\x44\x19\x61\x8c\x2d\x3c\xe4\x49\x0e\x35\xfb\xca\xd4\x32\xb0\x12\x47\x95\xf9\xc5\xcb\xdc\x1e\xb0\xc3\x07\x2b\x4a\xa8\x01\xd2\x6f\xbc\xc7\xb0\x7b\x82\x57\xf5\xfe\x47\xac\xd9\xbc\x58\x7b\x56\x57\xcf\x07\xca\x54\x5b\xb5\x68\xc9\xe4\xe7\x3c\xdd\xf6\x25\x4e\x22\xf7\x8a\xb2\xf8\x06\x45\x19\xf8\xab\xfd\x16\xfc\xfa\x90\xf8\x76\x87\xdb\x0c\x42\x09\xbe\x2c\x6c\x79\xa5\x52\x1f\x44\x18\x96\x78\xd9\x32\xc5\x45\x85\x70\x0a\x24\x37\x70\x2e\x56\xaa\xb5\x88\xa1\x7c\xb2\xcc\x94\xc0\x0e\x87\x57\x0e\xf3\xac\x51\x33\xd7\x53\x03\x8a\xa4\x65\x10\xa2\x60\xc1\xfe\x80\x47\x9b\xc0\x2e\xed\x9a\x8d\x1d\xe9\x93\x54\xac\x26\x48\xb4\x8b\x96\xab\x1b\x80\xcc\xa6\xca\xe1\x87\x7f\x37\xd7\x04\x28\xbb\x50\x85\x0e\x03\x08\xdb\x0b\x42\x30\x87\xbf\x7d\xde\x27\x9e\x09\x67\x66\xf2\xab\x3a\xb2\x38\x5b\x04\x64\xa5\xbe\xd7\xbb\xd8\xd4\x57\xe9\x35\xe2\x00\xaa\xaa\x8d\x95\x15\x70\xe0\x53\x07\x6d\xb1\x8a\x6a\x62\xf7\x2b\x31\x95\x79\x88\x4a\x08\x26\xba\x2b\x43\x63\x71\xdd\x21\x8b\x01\xa0\xc5\xe5\x8d\x0c\xd5\xff\x98\x25\xe4\x46\x6f\xe9\x66\xdf\x05\xcc\x31\xc8\x03\xe5\x21\x21\x83\xdd\xf2\x9c\xef\x7f\xb9\x16\x48\xa4\xf8\xee\x19\xfd\x5f\x8d\xbd\x8a\x56\xbe\x7a\xbf\x33\x65\x9a\x92\x24\xa1\xe2\x7a\x10\x24\xef\xfd\xfb\x88\xe8\x80\x61\x48\xd0\xd1\x78\x09\x06\xaf\x1e\xbe\x3e\x5f\x14\x36\x31\x90\xd8\x8c\xc6\xe5\x08\x94\x44\xf1\x25\xd0\x63\x15\x5d\xcf\x86\xca\x92\x63\xf2\xf5\xf1\x83\xc2\x69\x74\xfe\x00\x0b\x93\x42\xd2\x4c\x78\x1e\x20\x58\x28\x7c\xb6\xf3\xf1\xe3\x27\x0c\x22\xb7\x70\x7b\x83\x23\xa5\xcc\x8d\xb8\x1a\xa9\x06\xbb\x59\xd6\x96\xcb\x97\xcc\x74\xe3\x59\x59\x5f\xfb\x83\x73\xca\xd3\x71\x0e\xa0\x9e\xa9\x74\x4c\x20\xe9\xa1\x2e\x05\xbe\x5a\x95\xf0\x85\xac\x56\x16\x78\xd7\xda\x43\x2e\x4c\x7c\xb5\x3e\x12\x71\xdf\x5c\xd5\xa3\x39\xd2\xd7\x52\x0f\x1c\x18\x48\xd1\x50\x71\xd8\xc6\x98\x46\xb2\x3c\x5d\x24\x32\xc7\x38\x90\xf2\xed\xed\x37\xc3\xd2\x96\x4a\x4b\x5b\x55\x22\x58\x88\xe8\x92\xf5\x26\xd1\xca\xc3\x1e\xac\x35\x6f\x36\x1c\x2b\xf3\x36\xc4\x62\xd6\x0c\x82\xe8\x2b\x61\x6f\x2a\x51\x9c\x2f\x67\xbf\x01\x29\x03\x69\xbe\x9b\x55\xe9\xf5\xc8\xce\xc4\xf2\xe1\xb2\xab\x30\x25\x06\xc9\x03\xdc\x3e\x7b\x9c\x97\x81\x41\xdc\x90\x4b\x01\xb1\xc2\x3d\x25\x00\x43\x99\xbf\x8b\x73\xd6\x9c\xd5\x39\xc7\x9a\xf5\xe9\xa0\xa5\x11\xec\xa2\x21\x07\x8a\x1f\xf7\xb0\xf6\x04\xae\xa8\x42\x46\xc3\xcb\x32\xdb\x93\x81\xbe\x12\x17\x67\xe0\x97\xbe\xa5\x17\xbf\xcd\x82\xdf\xe9\x21\x37\x98\x40\xef\xb4\xb6\xf0\x2a\x48\xec\xda\xf1\x2d\x2c\xd3\x89\x30\xd4\x47\x3a\xdf\x97\xcd\x71\xdc\x4e\xa1\x03\x82\xf4\xf5\xd1\xdd\x75\x62\xcd\x4b\xf5\x11\x59\x32\xf6\xc4\x70\x0a\xa8\xfe\x8d\xec\xa9\xd5\xe7\x27\x79\x02\xb8\xf8\x86\x52\x97\x65\xdb\x24\x86\x07\x4b\x23\xa1\x9f\xd4\xb0\x43\x56\xbf\xa6\x22\x6c\x82\xba\xf6\x9a\x08\x7d\x9c\xa1\x88\x23\xf8\xe3\xe6\x83\x08\xe1\x6b\x80\x4c\x36\x3d\xf5\xb6\x30\x7e\x76\x24\x0d\xb1\xed\x84\x1b\x61\x2d\x65\x54\x8d\xdf\xbe\x83\x67\xda\x60\x77\x2c\x6a\xff\x55\x4d\xc8\x5d\x04\x19\x48\x34\x5e\x56\x7d\xa9\x33\x31\x51\x85\x8f\xdf\x69\x93\x27\x39\x25\xbf\xdc\x71\x81\xb5\xf6\x46\xd0\x63\xa8\xc8\xf3\x10\x56\x9b\x0e\xd0\x93\xbd\x9d\xff\x04\xfe\xbf\x0b\x41\xc6\xdc\x55\x16\x9a\x14\xa3\xc8\x62\xe5\x41\x6f\x1e\x58\x2f\xde\xe8\xfe\x87\xdc"}, -{{0xbf,0x3c,0x0c,0xbb,0xbe,0x20,0xbe,0x2a,0xcf,0xaf,0xb2,0x7a,0x36,0x11,0xb4,0x89,0x21,0xa7,0x28,0xab,0x17,0x33,0x4b,0x8a,0xfd,0xee,0x83,0x05,0x17,0x8f,0x61,0x3b,},{0x45,0x00,0xa0,0x3c,0x3a,0x3f,0xc7,0x8a,0xc7,0x9d,0x0c,0x6e,0x03,0xdf,0xc2,0x7c,0xfc,0x36,0x16,0xa4,0x2e,0xd2,0xc8,0xc1,0x87,0x88,0x6d,0x4e,0x6e,0x0c,0x27,0xfd,},{0x8f,0x87,0x03,0xbc,0xf4,0xc0,0x32,0x94,0x17,0x33,0x9e,0xb0,0x26,0xf2,0xb7,0x2d,0x31,0x4d,0x92,0x2e,0x9a,0xcc,0xb5,0xd8,0xbb,0x7e,0xec,0x87,0xe0,0x7e,0x61,0x38,0x55,0x16,0x72,0xa6,0x13,0x2c,0xb4,0xf8,0x75,0x50,0x8e,0xd3,0x29,0x95,0x67,0xb4,0xa7,0x41,0x34,0xd2,0xbd,0xf0,0xd8,0x57,0xf9,0x80,0x86,0x1d,0x18,0xbe,0x7e,0x01,},"\x8f\x30\xba\x2f\x79\x2e\x9a\x97\xf6\xea\xfe\x29\xf9\x76\xa4\x80\x28\xcb\x88\x57\xb5\xc7\x98\xbc\x2b\x61\x68\xc4\x64\x44\xc0\xce\x69\x60\x70\x37\x4c\x5e\x6a\x40\xc3\xd1\x8a\x5d\xc7\x66\x9f\xc4\x1d\xb9\xa8\x1c\xff\x75\x9b\x8c\xa0\x15\x98\x71\xc3\x44\x2e\x8c\x75\x12\x69\x8f\xa4\x47\xb5\x78\x3e\xe0\x1d\x1b\x61\x14\x49\xab\xad\x23\x71\x62\x92\x2b\x02\xd1\xae\xc5\xde\x1d\x66\x6f\x17\xda\x16\x13\x10\x63\x01\xd3\x05\x86\xd1\x16\xe2\xac\x09\x00\x7d\xd7\x1e\x81\x23\xed\xe4\xc5\xa6\xa9\xac\x07\x7f\xe3\xd9\x39\x09\xda\x62\x8e\x86\x58\x70\xa4\xe2\x5c\xb3\x55\x91\x67\x5a\x06\x90\xbe\xc4\xaf\x02\x81\x71\x4f\xe6\x66\x1b\xd5\xc0\x0a\x27\xd7\x9f\x95\x9f\xb4\xd4\xfb\x16\x36\xa6\xa3\x57\x5f\x4f\x01\x47\x06\x63\x89\x9d\x73\x74\x72\xb0\x96\xbe\x4d\xb7\x23\x71\x53\x67\xa4\x1a\x3a\x4c\x13\xf7\x42\xd9\x08\xf4\xd9\x21\xcf\xdd\x15\x6e\x75\x86\x82\x61\xba\x9c\x10\xd8\x58\x74\xca\x2d\x6c\x0c\x9e\x72\x95\xe5\x66\x2b\xd9\x16\xa3\x63\xc7\xa7\x96\xea\xd6\x17\xc4\x25\x1e\x67\x94\xda\x06\xc3\xd0\x8f\x2f\xdc\x38\x86\x94\x4a\x75\x09\xe6\x40\x9c\x90\x6b\x59\x31\x13\xb4\xb1\xf9\x85\x01\x32\x96\x0d\x9f\x3a\x4e\xeb\x73\x86\xfa\x59\x2f\x61\x93\xbe\xab\x8e\x0f\xf0\xf2\x89\x08\xa0\xd5\x48\xdb\x87\xba\xe9\x78\xb0\x5a\xbb\xca\x9b\x3e\x96\xd8\x79\x5b\x88\x07\x7f\x62\x0f\x21\x24\xe3\x15\x90\xeb\x09\x9e\x94\xe0\xe6\xe3\xcd\x62\x0a\xe6\x29\x0f\x3e\x2d\x01\x46\x7e\x5b\xef\x4f\xab\xde\xf7\x9d\x9a\xb9\x23\x9e\x75\x3e\xc4\xfa\x0b\xb1\x10\xff\x1d\x39\x3f\xca\x02\x24\x35\x02\xd7\xe9\x87\x99\x1e\xb7\x6d\x08\xf8\xbe\x7e\xb2\xb1\xee\x00\xc3\xb6\x8b\xbf\x72\xa6\x23\xba\xa1\x5b\xe8\x96\xb3\x21\x5e\xbe\x8a\x82\x31\x31\x09\xfc\x62\x9b\x0c\xce\x64\x91\xf8\x13\xc2\x49\x70\xe4\xff\xe6\x86\x9e\x40\xb4\x6b\x4e\xd2\x29\x86\xd0\x04\x21\x55\x27\x6c\x23\x0d\xe4\xc0\x5d\x67\x85\x52\xf2\xe8\x51\xca\xcf\x5a\x47\x21\x57\xdb\xb1\xa9\x9a\x2b\x42\xff\x40\x37\xf0\xdc\x63\x80\x67\x29\x21\xc9\x09\x20\x6e\x80\x05\x0e\x61\xa6\xb3\x05\x6b\x17\xe3\xae\x83\x50\x09\xb2\x04\x19\xa3\xb9\x84\x6d\x37\x48\x92\xe7\x19\xf1\xb3\x5b\xc1\x25\x7d\xa9\x3c\xcc\x6d\x8f\x8f\xca\xa8\xe6\x09\xa8\xd2\x04\xdf\x10\x8b\xe7\x19\x34\x67\xe7\xf1\x05\x93\x52\x82\xc3\xfe\x66\x70\xa5\x32\x94\x42\xea\x3e\xdd\xa2\x37\x6a\x03\xa1\xcf\xe8\x72\x3a\x90\x9c\x06\x4d\x30\xfe\x9b\xb0\x21\x2c\x33\xaf\xe2\xbe\xa3\x0c\x91\x43\xc0\x01\xda\x01\xc7\xed\x50\x45\x59\xb9\x7f\xe2\xce\xa0\x9b\xeb\x9d\xb5\x19\x00\xdc\x13\x67\x05\x92\x1e\x20\x29\x78\x45\xba\x72\xa9\x7a\xa7\xc9\x53\x81\x45\x71\xbe\x3f\x08\xce\xf9\x68\x04\x5a\x5a\xc3\x40\x04\xf6\x7f\xbf\xa5\x4e\x99\x6b\x31\x1b\xd8\xdc\x52\x7d\x89\xe1\xd4\xf5\x34\x53\xa6\x71\x37\x20\x10\x1c\x45\xa6\x0e\xe3\xa0\x5c\x2e\xe6\x6f\x13\x4b\x5a\xf4\x0e\x4b\x70\xef\x37\xba\x3f\x0a\xfd\xef\xc0\x39\xf3\x42\xc2\x8a\xf9\x19\x82\x51\x38\x1a\x10\x79\xa5\xdd\x03\x5a\x8c\x28\x97\x6c\x6b\x7f\x4d\xb0\x9e\xa3\x83\xa3\xa8\x7f\x0f\x85\x1f\xd3\x31\xae\xa7\xfa\x4b\xfc\xd9\x56\x31\xd6\x52\xfa\x2f\x50\xf1\xc2\x3f\xf2\xbc\x13\x7a\x06\x04\xe3\xd9\xf3\x9c\xcb\x96\x51\x45\xbc\xa4\x8b\x06\xdc\x8a\x81\x75\x47\xb6\x25\xef\xfa\x79\x6d\x00\x0c\x37\x74\xba\xd1\x98\xdb\x12\x41\xbe\x7a\x2c\x0d\xc4\xa4\x64\x1b\x9a\x8c\xb9\xcb\x8c\x8c\x38\x87\x57\x6f\x52\x72\xc3\x3a\xaf\xfe\x45\x61\x5f\x51\xa9\x6f\xae\x76\xcf\x51\x25\xbc\x69\xad\x0a\x40\x38\x79\x07\x99\xb5\xc2\x62\x44\x21\xa6\x43\x3d\xba\xb3\x9c\xcc\xb0\xb1\x78\x7b\x5b\xce\x28\x95\x94\x48\x9d\x17\xed\xb5\xf9\x31\x03\x74\x80\x7d\x36\xc6\xe6\x73\x47\x26\xbb\x33\x00\x4e\xca\xe8\xbb\x69\x1d\xcd\x38\x76\x01\xf4\xea\x91\x1b\x4b\x90\xeb\xff\x75\x6d\x7d\x8d\x9e\xb4\x22\xcb\xb9\xaa\xf7\xf4\x77\x2e\x0a\x54\x36\x43\x06\x85\xe5\x7b\x69\x74\x54\xe8\x2e\xea\xdc\xe4\xab\xa0\x62\xb7\x76\x82\xcf\x21\x9b\xe1\xfd\x9b\x00\xf1\xcb\x11\x35\xa1\x02\x13\x49\x53\x9a\x4b\x93\xae\x21\x3f\x19\x3d\x29\x32\x73\x8e\xf7\x29\x20\x49\x9b\x7b\xe2\xa8\x1c\x9b\xaa\xed\x17\xc5\x46\x41\xa5\x97\x4d\x27\x22\x32\x41\xe3\xc6\xa0\x95\x22\x6b\xd2\x37\xe0\x59\x1e\x00\x2b\x3a\xf0\x56\x5d\xf3\xe9\x76\x42\x0f\x97\x64\xa0\x9a\xe8\xbf\xa2\x79\x5f\x8f\xad\x7f\xc6\x87\xbd\x2d\xe2\x3d\x14\x88\xf4\x49\xd8"}, -{{0x28,0x7f,0xaf,0xd2,0x13,0x74,0x57,0x2f,0x57,0x81,0x00,0x47,0xd0,0xd9,0x8c,0xb1,0xff,0x3d,0x01,0x20,0xfa,0xa4,0x88,0x61,0x32,0x24,0x57,0x32,0xc1,0xa6,0xab,0x78,},{0xe8,0x25,0x20,0x63,0xf5,0xad,0x7e,0x95,0xbd,0x05,0xc5,0x02,0xa8,0xbc,0x4a,0x17,0x55,0x63,0x60,0x86,0x9b,0x9d,0xe0,0xa3,0xb8,0x58,0x93,0x8e,0x11,0x11,0x76,0x19,},{0x62,0x01,0xe3,0x05,0x91,0xd3,0x6b,0x7b,0x22,0x6e,0x36,0xfd,0xf5,0x64,0x34,0xc4,0x7c,0xd3,0x05,0x18,0x37,0xaf,0x31,0x31,0x3a,0x99,0x17,0xfd,0x02,0xdd,0xed,0x2b,0x5b,0xbb,0x4b,0xbc,0x36,0x8b,0x3b,0xd1,0x5d,0x06,0x20,0x45,0xf1,0x05,0xb6,0xe7,0x34,0x1b,0x15,0x15,0x0d,0x36,0xf9,0x00,0x87,0x59,0x1d,0x83,0x99,0x01,0xb8,0x01,},"\xb3\xc4\x43\xe4\xe5\x89\x9c\x16\xd3\x9e\x81\xb4\xf8\x07\x40\x42\xa9\x04\xa7\x35\x07\x4b\x27\x95\xd9\xac\x06\xb1\x37\x9e\xf7\x61\x8d\x2a\x53\x4b\x6b\xef\x81\x56\x9e\x60\x71\x92\x67\xbf\x29\xcd\x9d\x16\xac\xc9\xa1\x74\xd8\x02\x6b\x14\xb1\x27\xd0\xd2\xd8\xb4\x58\x39\x98\x89\x5a\xd7\xef\x72\xfe\xdc\x53\xb8\xf0\x8a\x22\x50\x10\x0e\x1f\x1f\x0a\xab\x48\xbc\x70\x74\x64\x34\x88\xe6\xb6\x70\xe1\xb0\x72\x7c\x38\x5a\x34\xff\x65\xa0\xd7\xe8\x3b\xa8\x60\x83\xb8\x73\xdf\xf0\x55\x92\x09\xb1\x4b\x2a\xc4\x2b\xf7\xc5\x72\xd0\xc5\x91\x7a\xc4\x2e\x4a\xe4\xda\xe1\xdd\x42\x35\x79\x52\x76\xa0\x76\x13\x2c\xfe\x3e\x0c\x35\x0b\x26\x58\x0f\xbb\x3a\xf8\x17\x77\xb9\x3a\xd9\x5c\xb7\xff\x17\xc2\xd9\x80\xce\x0d\x49\x2f\x6d\x40\xfa\x90\xba\x3f\xca\xa2\x1b\xb6\x87\x35\xee\x1e\xf2\x08\x49\x5e\xbf\x7b\x02\x27\x6f\xfa\x1e\xfc\x08\x16\x58\xbb\x44\xcd\x27\x61\xef\x5e\x3e\x1c\xa6\x0e\xc8\xb5\xd8\x16\xd4\xab\xac\xd0\xbc\xc8\x02\x68\xd8\xf4\xdf\x8b\x3a\x52\x04\x9d\xb0\x15\x7e\x2b\x6e\x81\xac\xd6\xf3\xf2\x89\x47\xc0\x76\x27\x95\x5c\xda\xc9\xea\xa1\xde\x17\xd4\xb9\xda\xa3\x61\xfb\x49\x78\x26\x64\xd7\xd6\xd2\xca\x5c\xec\x6d\x14\x89\x3c\x3e\x80\xb6\xd1\x6d\xaa\xcf\xfc\xc0\xb7\x59\x37\xe8\xbe\xf6\xf9\xe1\x12\xa8\x7f\x4b\x03\x5f\x90\x36\x07\x0a\x2c\xcc\x55\xc2\xaa\xd9\x39\xdf\x67\x4f\x7e\x4e\x12\x68\x5e\x01\x6e\xa0\xe4\x90\x2a\xaa\xaf\xaf\xfe\x38\xdd\xb2\xf9\x0d\x9c\xf7\x85\x37\xf6\x13\x91\x69\x6f\xf0\x33\x0a\xe8\xf7\x9a\x1c\x1e\xd5\xd5\x2b\x4e\xe2\xa6\x2d\x90\xfb\x82\xd9\xa4\x83\x93\xfa\x33\x81\x0b\x40\xd0\x45\x59\x02\xd5\x74\xff\x05\x20\x03\xe0\x16\x0c\x0f\x47\xb5\xe5\x80\xa0\x78\xbc\xee\xf0\x60\x73\xdd\xa8\xb2\xd1\xf1\x04\xa5\x95\xe9\x0b\xb6\xa4\x8e\xdd\xd8\x65\xf1\xca\xe4\xf1\x78\xfe\x22\xe7\x5f\x2f\x61\x24\xa9\xda\x06\x82\x44\x71\x12\xb3\xdb\x5b\xe8\xc4\x24\x72\xb2\x41\xe9\x44\xfd\x23\x70\xc2\xdc\x27\x15\xc0\x5a\x41\xbd\xbc\x89\x0c\x41\xc6\x5f\xb0\x8c\x2f\x59\x31\x74\x39\x1a\xc8\x80\xf3\xcb\x67\xd1\xb7\x4f\xf8\x02\xef\x96\x2a\xfe\xf7\xb9\xf3\xea\x32\x6f\x95\x27\xe7\xfb\xa6\x98\x18\x79\x24\xb6\x4c\xcd\xd0\x86\x62\x48\xc7\x6e\xe6\x4c\x79\x06\x9b\xe0\xa0\x57\xb1\x0a\xe1\x90\xf3\x8f\xf5\xab\xa8\x44\xe3\x93\x31\xcf\x1d\xb1\x3c\x90\x09\x06\xbe\xe0\xd7\xe7\x54\x6e\xf5\x23\x24\xe3\x7c\x59\x06\x75\xf1\x39\xf5\x8f\x57\x3a\x49\x4f\x4a\xe8\x2c\x4e\xc8\x10\x66\xa6\x8e\x2d\x92\x90\x01\x91\xc4\x7d\x30\x62\xf0\xf9\xaa\xed\x19\x11\x37\xcd\xa9\xb8\x3c\xd1\x30\xe8\x26\x29\x60\xe6\x24\x4f\x8f\x6e\xf3\x9f\x15\xa4\xfe\xd1\x3c\xb6\x69\xed\xc1\x9f\x5c\xe1\x62\xce\xb8\xd2\x42\xb9\xad\xdb\xfb\xa8\x77\x2c\xe7\x49\x85\xa5\xf3\x72\x0d\x59\x0a\x92\x0e\x1d\xca\x75\xa8\x79\xb1\xaa\x45\x9f\x74\x62\xff\xf2\xe9\x50\x72\x76\x1b\x20\x92\x54\xfe\x38\xc5\x4d\x83\x3a\x8e\x2c\xb8\xfc\x40\xc5\x98\xf3\xc7\xf7\xd6\xc5\x70\x57\x15\xd0\x30\x8d\xc3\x0e\xaa\x84\x67\x6d\x20\x9d\x7b\x7b\x31\x34\x47\x56\xe6\x9a\x9a\x4c\xb4\xe4\xa2\x51\x81\x7a\x37\x86\xfe\xa6\x72\x8d\xd6\x08\x22\x33\x6b\x45\xae\x5d\x47\xc7\x04\xb4\x5c\x4c\xad\x38\xc1\xe0\x1a\xb9\x3d\x14\x16\x92\xd5\x5d\x12\xfd\xb9\x74\x0f\x1d\x18\x15\x82\xf1\xc4\x8c\xe5\x43\x48\x60\xd9\x30\xf0\xe7\xe7\x0e\xdc\xff\xb8\x55\x60\xa5\x3d\xba\x95\xd5\x7b\x31\xe8\x92\x41\x37\xbc\x2c\x19\xe3\x4b\xb9\xc9\x86\x68\x77\x17\x42\x80\xe8\x0c\x23\x97\x8d\x57\x79\x58\x64\xa7\x37\x4a\xef\x38\x3f\x3b\xf6\x37\x53\x59\xbf\x63\x56\x47\x40\x09\x84\x61\xa6\xc7\x6e\x8f\x23\x89\x13\x28\x87\x69\xa1\xcb\x1c\x95\xb2\x2c\x32\xa9\xeb\xb3\xec\xeb\x04\x8e\xe3\x24\xcf\x0d\x7e\x85\xa3\x89\xb0\x4d\xed\xbb\xcb\xee\xf2\x98\xd0\x52\x78\x16\x08\x5c\x0c\x83\xef\xaa\x29\x85\x46\xe8\x39\x0b\xd1\xbf\xe4\x65\xec\x1b\xaf\xae\x69\xee\x52\x18\xe7\x2c\xae\xdb\x9b\x64\x9c\xf7\x3e\xec\x45\x4a\x2b\x48\x49\x65\x17\x96\x72\xde\xbc\xf9\x44\x13\x63\x99\x5a\x8a\x90\x7d\xe1\x7d\xc0\x68\x4f\x2a\xea\x57\x9a\x2f\xb4\x48\x41\x95\xdb\x41\x15\xca\x32\xe9\x70\x52\x6d\xc0\x0a\x5c\xac\xaf\x58\x87\x11\xdb\xd4\x69\xce\x80\xbd\x29\x7c\x4f\x41\xd6\xfa\x28\xa5\x97\xc6\x37\x2c\x0d\x21\x49\x60\xb5\x45\x98\xcd\x8b\xc8\x49\xeb\xdc\xa3\x6d\x62\x25\xb2\x0d\xec\x0d\x03\x11\x69\xce\xbb\x36\xea\xdc\x3a"}, -{{0x9a,0xd0,0x49,0x10,0x08,0x51,0xd0,0xf7,0x9b,0x71,0x12,0x25,0xc9,0x88,0x47,0x79,0x5a,0xcf,0xc3,0x60,0x1c,0x14,0xb8,0xa9,0x77,0x8d,0x62,0x70,0xcd,0x4c,0x05,0xed,},{0xe7,0xca,0xcf,0x4f,0x37,0x14,0x54,0x3c,0x27,0xa3,0xe9,0xed,0x83,0x3b,0xaf,0x3b,0xde,0x4c,0x09,0x56,0x3b,0xef,0x59,0xe7,0x63,0xfa,0xb7,0x1f,0xb5,0xe4,0xff,0x56,},{0xfe,0xc0,0xaf,0x34,0xcb,0xc5,0xcf,0xfc,0x56,0xe9,0x6d,0xd5,0xed,0x59,0x68,0xe5,0x2c,0xbd,0x42,0x69,0x84,0x4f,0xc3,0x0e,0x3a,0xb0,0xd3,0x47,0x2b,0x5d,0x18,0x0c,0x8d,0x1b,0x76,0x90,0x51,0x8f,0x41,0xf1,0x44,0x38,0xe7,0xf3,0xa8,0x3d,0x5e,0x89,0x76,0xcb,0x9a,0x26,0x15,0x1f,0xc4,0x14,0x9a,0x32,0x98,0xd7,0xe4,0x2c,0x05,0x03,},"\xc2\x84\xbd\xd8\xf8\x27\x5b\x49\xac\x80\x8c\x39\x04\x5e\x50\xe1\xed\x50\xc8\xa1\xaf\xd0\x11\xaf\xe5\xdb\x3d\xda\x62\x0b\xe8\xae\xc3\x7f\x45\x60\x57\x62\xe2\x25\xd0\x41\x11\xf2\x1b\x49\xfc\xef\xca\x3f\x3d\x5f\x81\x3b\x20\x20\xa5\x2c\x49\xf9\x5c\x4a\xd6\x1c\xa2\x14\x61\x8a\xde\x7e\xed\x6c\xd8\xd3\x14\xdc\x4c\x63\x55\x95\x52\x77\xd4\x57\x46\x2f\x03\xb9\xfb\xa2\xe2\x25\xb1\xb5\x37\xcd\x4b\x52\x37\x50\x5c\x90\xd4\x32\x05\xe1\x71\x5c\x39\x63\xcc\xfb\xec\x37\x9e\x6c\x17\x05\xe0\x80\x34\xa3\x1a\xfc\xe6\x46\x72\x7e\x78\xa2\x0e\xed\x88\xae\xb0\xdc\xda\xbc\x5c\x86\xe8\x69\x79\xe6\x3a\x5c\x26\xc3\xe2\x17\x79\x73\xb6\x98\x3c\xeb\xfe\xda\x9f\x31\x47\x93\x61\xb6\x61\x76\x3a\xa7\x26\x1c\x09\x39\xca\xd4\x8b\x71\x90\x8e\xa9\x07\x68\xbb\x6c\x95\x83\xd8\xea\xeb\x9e\x03\x38\x51\x5a\xca\x12\x42\x62\x6d\xc6\xbe\x04\xec\xc4\x42\x9e\x4c\xbb\x4f\xf3\x36\x09\x61\x92\xf7\x50\x1e\xc4\x71\xb5\x96\xa9\x9d\x4c\x02\x75\x82\xcc\x69\xe2\x04\xb6\xfb\xcd\xdf\x59\xf5\xbf\x74\x62\xdd\xcd\x59\x89\x12\x1f\xd1\x0f\x11\xa0\x67\x5b\x6c\x4e\x4f\x65\x20\xd2\x7d\x7c\x61\x43\x1b\xa7\xd1\x74\xf5\x73\x95\xa0\xbf\x72\xd3\x8c\x11\x42\x73\x6d\xed\x6b\x91\xe4\x81\x1c\x0e\x85\x41\xa6\xc0\xd9\x96\xc5\xa1\x7d\xc9\x7d\xb3\x88\xf7\x21\xd2\x35\x7d\x3c\x6a\xf5\xc8\x6b\x1d\x5e\x47\x6e\xa0\xac\x0b\x1c\x11\xd4\x38\x7f\x76\x90\x39\xbd\xf5\x38\xa0\x21\x6e\xdd\x00\x45\xee\x6d\xd8\x9e\xef\x82\xa4\x25\xa8\x3f\xaa\x1b\x12\x80\x70\x38\xca\x19\xeb\xec\x00\x2e\x8b\x3c\x15\x34\x4c\x61\xcf\xd1\xe5\xf0\xe3\xb0\x27\x3d\xeb\x37\x27\x8c\xf1\x97\xd8\xa8\x3b\x13\xd9\x92\x30\x8a\x51\x37\x3e\xb3\x81\x14\xc9\xe4\x5b\x43\x87\x80\x27\x7d\x1e\x32\xf3\x97\x29\x62\xa3\xe1\x4a\x8d\x08\xdb\x9f\x09\xae\xc3\xdd\x32\xa5\xb9\x94\x23\xe6\x1f\x5e\x79\x94\x4a\xb5\x7a\x36\xf6\xec\x07\xcc\x32\x04\xf9\x16\x5e\xe0\x21\xad\xa9\x3e\x6f\xec\xb7\xec\x45\x6a\xa0\x28\x8c\x37\x8a\x75\xaf\xd6\xe9\xda\xd6\xc6\xf8\x8e\x95\x9a\x2c\xf2\x8b\xfe\x56\xd2\xe6\x1b\x2a\xda\xec\xf0\xd8\x6d\xd8\x92\x8b\xce\xda\x26\xb0\x54\x02\x46\xb7\x33\x7f\x5c\xdc\xec\x11\xfb\x0c\x1a\x59\xd6\x31\xfc\xca\x19\x40\x8f\x95\x22\xb6\x8a\x39\xf8\x6e\xf9\x70\xb8\x83\xa0\xf0\xbd\x6b\x7b\x14\x15\xec\x9a\xa0\x43\xb5\x2e\x19\xba\xc1\x76\xd6\x7b\x79\xe2\xa5\xdc\xa8\xbf\xd2\x91\x02\xac\x60\x8e\x47\x3e\x9f\x98\x2c\x3e\xc8\x93\x2d\x8a\xa8\xcd\x56\x52\x84\x49\x1d\xe5\x2f\x51\x6b\x9e\xbf\xb7\xdb\xe1\x29\x95\x11\xae\x73\x2c\x2a\xd1\xee\x49\x92\xb0\x77\xfa\xff\xc6\x5f\x48\x8f\x1b\xa2\x15\xda\x69\x79\x60\x09\x71\x19\x6d\x0f\xf3\xa0\x8a\xd9\xf0\x0e\x82\x9c\x1d\xe1\xaf\xca\x10\xca\x47\x6b\xe6\x64\xaa\xd2\x61\x88\x9b\x0e\xb7\xae\xb6\xed\x86\x37\x61\x89\x00\xac\xf4\x81\xe2\xd2\x24\xec\x64\xa6\xe6\xcf\x4f\xa4\xdf\x73\x1b\x7a\x4f\xee\xff\x25\x80\xc9\x9b\x6d\x75\xb4\xdc\xd0\x97\x69\x65\xcb\x2b\x0b\x56\x35\x22\x78\x42\xd0\x8a\x7d\x90\x7a\xae\xbc\x2f\xde\xd8\x00\x98\x11\xdc\xdd\x73\x35\x49\x21\x75\x3b\xc5\xde\xc0\x17\x68\x93\x35\xf5\x6d\x0f\xb7\xae\x21\x3b\x41\x79\x2b\x1f\x4e\xb1\x4a\x24\x53\x59\x77\xa3\x05\xb1\x9e\xb9\x83\x8d\xc6\xb5\x15\x28\xb9\x8a\x39\xbd\xa0\x60\x10\x71\x7a\x20\x8c\x34\x7a\xa1\x58\xee\xcd\xfd\x9a\x04\x72\xd3\xb8\xd9\x20\xf9\x69\xe1\x2b\x65\x91\x9b\xda\x38\xb4\x61\x94\x98\x50\xcc\x9c\xc1\x8d\x8e\x3b\xaa\x8c\x88\x6d\x93\xcd\x09\x6a\x20\x9d\x54\x3c\xa3\x37\x5f\xc4\xe7\xd6\x51\x03\xcb\x64\x24\xbe\xab\x44\xe8\xbc\x4a\x5b\x62\xc2\x9a\x01\xbc\xf4\x4d\xcc\x61\xe7\x67\x5c\x02\x5d\xec\x07\x24\x20\x01\x94\xbd\xe7\x4d\x72\xc0\x2e\x94\xa9\x46\xa7\x52\xf3\x60\x84\x57\xfd\x91\xf2\x92\x71\x57\x71\x48\x7d\x26\xca\xd4\xe5\xcf\x6e\xf7\xc6\xf7\x16\x27\xa4\xda\xf8\xa4\xc9\xb8\x91\xc1\xee\x8f\x04\xae\xaa\x99\xfe\x0c\x8b\x4e\x83\x3b\x76\x09\x06\x6b\x61\x32\xa9\x68\x89\x0e\x26\x95\xda\x22\xb2\xd8\x57\xc8\xc0\xad\x91\x87\xc9\x60\x69\xe4\x76\xe2\x7e\x46\x32\xc4\x47\xee\x76\x71\x4a\x31\xd1\xe5\x14\x9e\xcb\x33\x7e\xe1\x32\xf3\x55\x2d\xa3\x3a\xb2\xd6\xfa\x9d\x7e\x93\xf6\x8a\x77\xcb\xf1\x91\xcb\x06\xbc\x22\xf3\x47\x0a\xf6\xd7\x58\x1e\x3a\xcc\xbe\xca\x0b\x6f\xeb\x08\xa1\x4b\x9a\x80\xc1\xef\x59\x37\x4c\xcd\xc0\x52\x3c\x36\x84\x50\x4c\x01\x04\xbb\xa2\x2c\x10"}, -{{0xde,0x54,0xe1,0x3f,0x9e,0x2c,0xc7,0x54,0x54,0x6c,0x99,0xb3,0x3b,0x3d,0x72,0xf4,0xd1,0xf7,0x71,0x50,0x38,0xa9,0x65,0x9f,0x33,0x63,0x65,0x77,0xbb,0x52,0x6a,0xdb,},{0x36,0x33,0x8d,0xb3,0x32,0x6b,0x00,0x5e,0x5c,0x61,0xff,0x78,0x2b,0xe2,0xea,0xb1,0x66,0xd4,0xeb,0x72,0x34,0xa9,0x8e,0xa1,0xcd,0x85,0x5e,0x1a,0xd5,0x35,0xe9,0x4c,},{0x37,0xac,0xa8,0xf2,0x48,0x39,0x4a,0x9e,0x04,0xd0,0x6a,0x7d,0xa8,0x4a,0x7d,0xef,0xa3,0x9d,0xe4,0xda,0x2b,0xcb,0x18,0xd5,0xf6,0x4c,0xc3,0x4d,0xb0,0x86,0x51,0xaf,0x4a,0xbb,0x19,0xfa,0x2a,0x92,0xa7,0xdd,0xa5,0x6e,0xc9,0x93,0x0b,0x81,0xae,0xbd,0x23,0x99,0x05,0x11,0xf6,0x84,0xc6,0xd1,0x5b,0xa5,0x95,0xf7,0xd4,0xa2,0x74,0x0e,},"\xdc\x40\x41\xad\x61\x42\x3a\x12\xa0\x41\x13\x18\xa6\xe6\x2a\x5e\xf6\x4a\x19\xab\xe2\xd9\x85\x22\x97\xbe\x2d\x4a\x35\xeb\x86\x70\xca\x36\xc5\x21\x53\x1b\x30\x38\xac\xda\xee\xa2\xea\x01\xa0\xb6\x18\x78\x62\xa4\xe1\xa8\x9d\x4b\x81\xc5\x31\x8e\xd4\xd6\x71\x31\xbc\x38\xf8\x41\xa1\x42\xa2\xf6\xf3\x16\xdf\xf0\x76\x93\x9d\xc0\xeb\x81\xb2\x30\xfe\xa9\x88\x1f\x8f\x0f\xf7\xed\x0b\x29\x3f\x69\xb2\x89\xfe\x77\x08\x81\xfb\x37\x10\x80\x8e\x8e\x59\xe6\x4e\x19\x0c\x1e\x37\x9b\x9d\xd3\x48\xb0\x2c\x23\x47\xd7\xe2\x06\x96\x79\x0b\x62\x77\x6a\x2e\x82\x5b\xed\x69\x17\x03\x7c\xb6\x35\xc9\x2f\xbc\x76\xb4\xc5\x85\x10\x27\xe7\xf1\x38\x52\xee\x7e\x7c\x52\x57\x3a\x90\x30\xb7\x9f\x22\xb6\x0d\x58\x69\xef\xe6\x80\xc0\x16\x64\x92\x9f\xe9\xa0\x6f\xa3\x33\x05\x2b\xe1\xd6\xaf\x3a\x0b\x48\x2c\x33\x2e\x18\x05\x1e\x78\xb3\x33\x83\x9d\x6c\xb9\x3d\x93\xeb\xfb\x27\x7e\x42\x68\xfb\xee\xee\xba\x1e\x8f\x96\xa5\xc9\xe3\x28\xc4\x26\x72\x12\xca\xc2\x51\x21\x5b\xfa\xa7\x8f\xd8\x8a\x87\x41\x7a\x80\x60\x2d\xcd\x88\x28\xe8\x04\x00\xda\x30\x4e\x98\x98\x62\xd1\x32\x01\x08\x2d\xe3\x53\x09\x25\xe0\xed\xc2\xc1\x30\xa9\xa4\x19\x07\x1b\x31\x08\x8d\xa6\xf6\xff\x40\x56\x30\x1c\x12\x9f\xc2\x13\x52\x33\x62\x8d\x16\xd8\xbf\x16\x0f\x6c\xe8\x6d\x83\xcd\x4e\x29\xae\x0c\x73\x84\x3d\x70\xb5\x30\x56\xc5\xaf\x3f\x3d\xc5\x61\x27\x1c\xb5\xaf\xf3\x93\xf0\x80\x3a\xde\x07\x2d\x9c\xeb\x74\x5b\x61\x87\xb2\x8d\x24\x69\x67\x67\xd5\xc2\x1f\x4d\x4a\xc5\x8d\x5b\xb6\x6c\x5c\xad\xfe\xfb\x16\x26\xef\x93\xf7\x14\xc7\x82\xb6\xef\x3c\xcf\x4b\x44\xee\x75\xf0\xbb\x75\x7a\x25\xd9\xb4\x6a\x9d\x93\x1a\x03\x72\x7d\x49\x6a\x22\x81\x0c\x63\x4f\x5c\x1a\xe6\x0c\xbd\xf2\xf1\xea\x29\xb5\x46\x07\xcf\xf5\x0d\x9f\x8e\x03\xa0\xa4\x51\x3c\xf6\x8d\xfb\x61\x97\x73\x41\x1b\x61\x80\x95\x9a\x8a\xac\x30\xb2\xee\xe4\xad\x32\x79\x15\xf6\x0a\xe5\x2b\x90\xe0\x4a\x9b\xce\xf8\xdc\x67\xe7\x1e\xa1\x0a\xca\x55\x3d\xb9\x89\x5c\xd8\x00\x84\x57\xd7\x6f\x02\xce\xb5\x35\x00\x21\x11\x09\xe8\x96\x03\xf3\x04\xd8\x80\xaa\xf0\x28\x61\xfe\x37\xc9\x53\x4a\x9d\x67\x2d\x83\x71\x3c\xd3\x26\xc9\xab\x81\xc3\x53\x76\x4c\xa5\xad\x5a\xc0\xe7\xf1\xff\x88\x0f\xb4\x8a\xcd\x9c\xbb\x94\x90\x64\xe2\x11\x83\xbc\x38\xfb\x1d\x90\xcf\xe6\x19\xa8\xb8\xfb\xf5\x32\x18\x89\xbb\x15\xc0\x2a\x53\xe4\xd3\x67\xfc\x66\x88\x77\xb6\x62\x28\x1c\x4a\x2a\xf6\x78\xf8\x6e\x69\x1d\xaa\x8a\xfd\xca\xc1\xb8\x20\x18\x9f\xe5\xc2\x50\x8c\xe3\x6e\xdd\x9c\x6f\x8f\x51\x57\x50\x71\x83\x94\x39\xa0\x03\x35\x2c\x15\x73\xe1\x27\x68\xdd\x6d\xeb\xdf\x1e\xd4\xf9\x4a\xc7\x9d\xf1\xab\x6a\x0b\xc2\x50\x79\xc0\x93\x54\x77\xd9\x14\x99\x88\xec\x3b\x87\x93\xef\xcd\xa8\x59\xac\xc3\x92\xab\x3f\xa9\x94\x93\xd7\xae\x0a\x65\x75\xb6\x95\xa1\xce\x07\x65\x32\x86\x02\x87\xdd\x49\x89\x67\xc4\x6f\x7a\xdd\x49\x49\x4c\x02\xe7\x44\xc4\x02\x80\x19\x57\x82\xe2\x42\x44\x76\x16\x5e\x72\xce\xe2\x36\x42\xe5\x1c\xec\x43\x21\x91\x11\x6a\xec\x59\xb5\x9f\xcf\x0a\x36\x83\xb9\x5f\x76\x07\x60\xa2\x0b\xd6\x74\x54\xd8\xde\x64\x7c\x0f\x9f\xfc\x4f\x90\xf6\xe4\x5a\xc9\x3d\x80\x2f\x33\x82\x99\xef\x28\x0d\x3b\xb7\xa4\xa8\x9d\xb8\xc5\x9a\x12\x52\x6f\x27\x83\x02\x4c\x8a\xde\x90\x02\xf0\x0e\x3d\x52\x9b\x78\xdc\xdd\x49\x03\xda\xf5\x76\x7a\x2b\xed\x75\x14\x53\x96\xef\xb6\x97\x90\x71\x2d\xe6\xa5\x90\x1e\x6d\x8c\x15\x28\x01\x82\x38\x82\x85\x02\x1d\x0e\x70\x92\x92\x15\xd9\xf2\xb7\x99\xbb\x92\xf2\xca\x56\xf4\x8e\x8c\xbb\xa2\xf1\x9b\x08\x58\x45\x12\x65\x67\xcf\xaf\xa6\x03\xc2\x94\x6e\xa1\xe7\xd2\x74\x55\x4a\x38\xbf\x7d\x86\x51\x1f\x3e\x47\x4f\x9f\xa5\xcb\x11\x10\x5f\xb5\x2f\xc6\x81\x77\xf3\x38\x5f\xe1\x39\x7b\xe5\x84\xa7\x00\x89\xdc\x74\x1b\x4b\x00\x95\xbf\x7e\xb2\x99\x3b\x41\x8d\xf8\x7b\x14\xa1\xf9\x79\x26\xe8\x68\xdf\x6e\x56\x8b\xec\xa2\x21\x5f\x2d\xd7\xce\x8a\x3c\x9e\xe8\x49\xcb\x41\x34\x6c\x68\x4f\x7f\xfe\xf0\xa7\x92\xed\xf4\x33\xca\x99\xef\x34\xc7\x3f\x92\x72\xa7\xeb\x97\x58\x7c\x8f\xce\x4a\x51\x36\x44\x47\x37\x13\x8d\x53\xea\xdf\x3a\x84\xf5\x01\xbb\x10\x45\x6e\x8e\x4a\x40\x47\x08\x2c\x9e\x14\x35\xf5\x76\x52\x6c\x21\x64\x71\x4d\x70\xb3\xd0\xa6\xe9\xc0\x8a\x53\xe3\x23\x84\x0f\x4d\xcf\xe8\xf2\xd1\x9f\x0b\xe2\xc8\x8e"}, -{{0x85,0x04,0xfb,0xca,0xab,0xa6,0x76,0x83,0xf8,0x15,0x49,0x92,0x82,0xb6,0xeb,0xd4,0x97,0xa8,0x1a,0x91,0x56,0xf5,0x3e,0x02,0x5c,0x2d,0x3e,0xce,0xe0,0xdb,0x65,0x59,},{0xe6,0x2d,0xa8,0x64,0x93,0xa0,0xca,0xf5,0x29,0x21,0xd5,0x60,0x2f,0xbd,0xc3,0xdd,0x3a,0x84,0x36,0x94,0x1f,0x6b,0xe2,0x40,0xb3,0x15,0x09,0x68,0x12,0x38,0x74,0x6d,},{0xc0,0xea,0x07,0x4b,0xf9,0xad,0xde,0xe2,0xe3,0x35,0x0a,0x96,0x9e,0x7c,0x56,0x9e,0x3a,0xea,0x1a,0x41,0x88,0xee,0x5a,0xf3,0x4c,0xb7,0x3f,0x38,0x82,0x98,0x65,0x3d,0x29,0x9b,0x5d,0xbd,0x94,0x16,0x3f,0xba,0x20,0x9e,0x8f,0x7d,0xc2,0xe2,0x63,0x4d,0x3a,0x52,0xa0,0x28,0x10,0xa8,0x8c,0x61,0x52,0x94,0x5b,0xc1,0x6b,0xbd,0xfb,0x0c,},"\x6c\x63\xed\xbd\x40\xa0\x38\x74\xec\xae\xf8\x16\x02\xcd\x68\x50\xc0\x9f\x49\x15\xb7\xaa\xf4\x18\x25\x8c\x56\x83\x64\x53\x8e\x83\x92\xa8\xc3\x79\x83\x8b\x0c\x95\x34\x5b\xf6\x4c\x3d\xbc\x17\x58\x53\xfb\x64\x1f\x35\x0f\x0b\x53\xa0\x5a\x8e\xc2\x90\x28\x8c\x03\x26\xd4\x35\xff\x77\x6f\x86\x83\xa2\x73\x33\x3f\x9b\xb2\x80\x21\x84\xec\xc5\x3b\x06\xb2\x8c\x2c\x40\x2a\x54\xbf\x13\x4c\x1a\x23\x29\x97\x49\xa6\xce\x2b\x51\xa7\xba\x22\x23\x21\x48\x79\x7e\x99\x3f\xf2\x58\x28\x6e\x94\x77\x78\xa8\x74\x2d\x3f\x36\xcc\x78\x42\x97\x60\x43\xfc\x23\xda\x8a\x97\xec\xb9\x71\x5f\xc0\x5f\xb0\xf2\x3f\xa7\x32\x1d\xdc\x19\x32\x86\x16\x31\x60\x4e\xba\x2e\xf2\x5d\x8b\x75\x6c\xe4\x73\x36\x56\xbf\xd1\xe1\x47\x08\x92\x3a\xc7\xc6\x0a\x79\x84\x61\x36\xd7\x41\x97\x3b\xa5\x51\x41\x89\x72\x0b\xc0\xf7\x77\x4b\x7b\xd3\x57\x45\x95\xbd\xe2\x51\x50\x31\xb2\x5b\x62\x65\x4b\x16\x10\x35\x77\x80\x70\xac\xe1\x49\x71\xdf\x1f\xe0\xbe\x4e\xa1\xef\x55\xcf\x87\x47\xd3\x71\x6c\x1c\xe7\x07\xb1\xa7\xc8\x52\x0e\x6d\xeb\x33\x4e\xb1\x86\x33\x8f\xc9\x30\x00\x76\x8e\xb2\xbe\x40\xc6\xe0\xdc\x3f\x5d\xf8\x31\xb3\x2c\x3a\x2c\x33\xe2\x88\x98\xd6\x76\x2a\x15\x22\xd3\xd4\x8d\xae\xe5\x6a\x02\x69\xbd\xdf\x6c\xfc\x9d\x73\xf8\xd1\x78\xae\xcc\xbf\xfe\xf7\xce\x16\x4f\x98\xaf\xea\x22\x4a\x9b\x60\xed\xe4\x6a\x95\xfa\xdc\x9f\xc5\xd9\x4d\x20\x9c\x16\x6d\x9b\x8d\xe2\x53\x38\x1e\xa2\x24\x88\x62\x94\x6b\x9c\xf5\x34\x94\x74\x55\xc2\x44\x58\xcf\x56\x68\x3a\x0e\xc4\x7a\x2c\x65\x07\x5c\x69\x4c\x7c\x3d\x6a\xdf\x9a\xe5\xe8\xad\x31\xac\x76\x9f\x83\xaa\x26\xe3\x12\xc5\xb0\x1a\x9a\x09\x40\x4b\x15\xb8\x14\xba\xa7\x66\x6b\x3e\x03\xf0\x6a\x8d\x63\x48\xab\x8c\xcb\x9b\x60\xa4\xa4\xfa\xf8\x6f\x71\x35\xdf\x03\x9d\x95\x5c\x07\xbd\x92\xe7\xb8\xe3\x27\xee\x6c\x1b\x40\x19\x6a\x28\xb4\x44\x6a\xa5\xa9\xb2\xb9\x77\x3a\xb7\x6e\x3c\xe2\x11\x80\xf0\x9d\x6c\x08\xd2\x77\xc6\x77\x1d\x67\xe2\x2d\x84\x54\x0f\xa4\x3b\x38\xf6\x34\xcf\xc4\x6e\x5b\x8c\x33\xf1\x5a\x56\x8a\x77\xe4\x91\x4a\xad\x9a\xb8\xc9\xf7\xfe\xa4\x7f\x76\x77\xc0\x18\x80\xb3\xe8\x5d\x2d\x0e\x3f\xbd\x6d\xc6\xe9\x9e\x43\x7d\xdc\x73\x6f\x92\xb5\xa2\xff\x29\x27\xe0\xb4\x42\x14\x2f\x08\x97\xd0\xb8\xa1\x9a\xc2\x03\x63\x3d\xf4\x13\xfe\xaf\x8e\xf5\x0a\x5f\x76\x7b\xed\xaf\x20\xf1\xc1\x3f\x3b\x89\xd1\xe8\xb7\xbd\x18\xd5\x91\xf9\xde\x11\x6e\xe3\x4f\x98\x24\xe4\xea\xd1\xae\x9d\xa2\xe8\xca\xae\xf8\x8b\x29\x51\x6a\xa9\x42\xde\x77\xa7\x46\x7b\x6f\xb2\x6a\x66\x6f\x30\x64\x8c\x71\x5a\x2e\xe9\xf9\x46\x74\x3b\x54\x3a\x44\x28\xe0\xdf\xd0\x61\x78\xe7\xe9\x3e\xc6\xf2\x6e\x00\x3e\x05\x8b\xec\x14\xa4\xaa\x2e\x3b\x8d\xe1\x12\x95\xa7\x64\xca\xb3\x0b\x31\x3f\xcc\x57\x43\xb2\xfb\x89\x96\x2d\xdc\x5c\xdc\x6a\xa0\xd2\xe4\xa3\x06\xe7\x7a\xf7\x6a\x05\xa5\x98\x92\x3f\x62\x8a\x85\xdf\x1c\xc7\x3a\xd3\xbc\x01\xc4\xb9\x79\xbd\x7c\xb2\x96\x59\x0a\x88\xb0\xa4\x1b\x44\x5d\x50\xa0\x84\x23\xe4\xed\x80\xf1\x76\x3c\x71\x6b\x6c\x45\x7d\x84\x5d\xfa\xa6\x8d\x12\xb0\xd0\x3c\x55\xfd\xe8\xae\x6b\x2b\x92\xbc\x63\x22\x94\x3d\xbe\x54\xc7\x06\xbc\x8e\x5f\xce\xe7\x06\x54\xb2\x6f\x3b\xfd\x87\x7f\x5f\x53\x39\xac\x18\x2d\x54\x17\xbd\x4c\x07\x35\xd8\x25\xbf\x70\xe8\x5e\xab\x82\x16\xed\xda\x63\x2a\xe7\xe2\x2b\x3e\x53\xd0\x78\xa8\xb2\x0b\x5a\x7e\x23\x85\x33\x7c\xf9\x2b\x3c\x16\xb0\x23\x56\x3e\x11\xcb\x50\x43\xb7\x04\xd3\x7e\xb5\xed\x9e\x85\xfc\xdc\x95\xcf\x7a\x6e\xad\xe4\x08\x03\x17\x5a\x00\x8e\xf6\x53\xac\x61\x36\xf1\x61\x29\xab\xae\x11\x37\xc5\x82\x34\x00\x74\x8a\x81\x25\x62\x54\xd3\x17\xcf\xc9\x39\xe2\x6e\xa0\xce\xf9\xf6\x54\x8d\xb4\x28\x90\xc4\x8b\xeb\x04\x79\x10\x3b\xa0\x89\xe5\x14\x11\x80\x38\xb1\xb9\x09\x43\xd7\x16\xf7\xa8\xd4\xcd\xa5\x98\x3a\x67\x4b\x83\xa0\x02\xd8\xac\x9c\x65\x73\x4a\x28\xb7\x7b\x76\x0c\x8e\x38\x03\xf8\x78\x1e\xa9\x19\x9f\x79\x7c\xe7\x29\xe0\x6b\xff\xfe\x8c\x29\xb2\x0b\xc8\x52\x27\xc0\x9c\xc0\x52\x19\xff\x2b\xa3\x8e\x18\x05\x10\x83\x73\x2f\x83\xcb\xfc\xcc\x31\x07\x56\x45\x0b\x26\x1d\x5b\xe1\x83\xd9\xfb\x44\xec\x18\x52\x9f\x2c\xc9\x84\x8c\x40\x11\x9c\x60\x76\x76\xbc\x4d\x90\x15\xfd\x4b\xd2\xfc\x91\x8d\xc8\x03\x1e\xc1\x9a\x05\xff\x36\x2c\x18\x40\x43\xbe\x7f\xe0\x66\x01\x9a\xc5"}, -{{0xea,0xc0,0xf0,0x6c,0x2c,0x14,0xf3,0x7d,0x43,0x4b,0xc9,0x98,0x97,0x22,0x5d,0xd2,0xe3,0xf1,0xed,0x74,0xaa,0x74,0x42,0xc5,0x50,0x33,0x9d,0xf7,0x7d,0x0b,0x7b,0x32,},{0x43,0xe6,0x20,0x55,0xdb,0x6e,0x13,0x49,0xc9,0x4d,0x89,0x02,0x91,0x87,0x88,0x20,0x20,0xcb,0xcf,0x9d,0x75,0xe0,0x3e,0xb6,0x56,0xfa,0x0a,0x15,0xb1,0x90,0x02,0xd7,},{0x45,0xf2,0x80,0x3a,0xfe,0xb0,0xfc,0x44,0xd3,0xaa,0x96,0x5b,0x12,0x65,0x9b,0xf5,0x02,0xe4,0x72,0x95,0x70,0x61,0x84,0xb2,0xa1,0xc6,0xf1,0x6d,0x05,0x06,0x13,0xf5,0x96,0xa2,0x00,0x13,0x94,0xe0,0x0e,0x2a,0x44,0xc4,0x6c,0xf6,0x50,0x5d,0x5c,0xf5,0xb8,0xab,0x84,0x12,0xf0,0x7e,0xda,0x95,0x1a,0x15,0x00,0x5e,0x33,0x8f,0x3c,0x0e,},"\x27\xb7\xfd\x0e\x71\xad\xf1\x94\xcf\x54\x07\xb6\x77\x17\x93\x06\x0d\xe0\xfc\xa7\xca\x0a\xe6\x48\x35\xc4\x31\x87\x40\x8a\x70\x4f\x53\x3d\x5e\xa0\xc8\x3a\x65\x43\x87\xba\x7d\xb1\x6e\xd5\x8e\xc8\x37\x22\x6d\xf5\x7c\x1f\xe6\x38\x2c\x59\x19\xe9\x22\x13\xf6\xf1\x8c\xbb\x57\x35\xd1\x78\xa4\x76\xaf\x35\xd3\x90\xb7\xcd\x25\x56\x21\x7c\x53\x0f\x3a\x1f\x8a\xb2\x33\x9c\x1a\x5e\x8d\x96\x93\x87\xef\xd3\x94\x14\xb5\x6b\xb7\x84\xdf\xd5\xeb\x89\xb8\x59\xe1\xf4\x03\xa2\x38\xec\xa2\xa9\x41\xe6\xdb\x56\xac\x45\x6b\x73\x45\x06\x98\xd1\x45\x5e\xc1\xe9\xb3\x9a\x1e\x90\x7d\x6b\xc7\xe6\xcf\xf4\x24\xa2\x8e\xed\x57\x9a\xf1\x63\x10\x11\x5b\x67\xf5\xfc\xf7\xf8\x34\x6b\x3f\xa0\x26\x0c\x6d\xa2\xe2\x77\x55\xac\xa5\x70\xba\xbb\x3d\x30\x3c\xc8\x32\x46\x0c\x96\x3b\xfd\xd5\xc1\xff\xb2\xfc\x19\x92\x19\x29\xdd\xa2\xa7\x17\xfb\xcb\xeb\x2b\x85\x25\x76\x1b\xd6\x60\xce\x4a\x0f\x76\x85\x28\x5d\x7f\xad\x61\x15\xab\x09\xf8\xe6\x3f\x5f\x77\x39\x14\x49\x4e\x20\xbe\x1b\x51\x2d\x11\x14\xcc\xe3\xf0\xf6\x8c\x7d\x94\xf5\x48\x57\x69\x4f\x22\xaf\x4c\x69\x8d\x78\x2c\xe8\x37\xb0\xc1\x72\x2b\xb7\x31\x3b\xb2\xc4\x1f\x6d\x3d\xd1\xa0\x28\x77\xfb\x42\x96\xd8\x66\x2a\x9e\x86\x25\x98\x4d\xc1\xfd\x1a\x95\x10\xeb\xa9\xd6\x43\xac\x58\xa8\x86\xa0\x45\xcd\x0e\x53\xc0\x56\xa8\x33\xf9\x68\xb3\x5d\x01\x32\x0e\x9c\xc0\xb4\x35\xd3\xf6\xbf\xad\x26\xf9\xeb\x57\x54\xd3\x8d\xdf\x6d\x5c\x4b\xf6\x15\xa7\x64\x4a\x23\xf9\x82\x6b\xcc\x97\x60\x92\xd8\x2d\x81\xd5\x47\x00\x0d\xe0\x08\x1b\x7a\x40\xa9\x3f\xbd\xda\xc1\x3f\x7d\x99\x70\x8c\xcd\xee\xb9\x40\x5c\xd6\x34\xca\x07\x48\xca\xd2\xc1\xd8\xf1\x64\xf5\xd7\x7a\x4f\x36\x4a\xe4\x88\xbe\xdc\xf1\xf2\x0e\xb9\x54\xbc\x8a\x27\x8a\xf8\x14\x32\x41\x78\x56\xa9\x00\xf8\xf1\x52\x92\x1a\xfb\xe1\x79\x14\x22\x9a\x51\x3b\xd7\x1a\xb7\xe6\x61\xcd\xe1\x29\xaf\x93\xe2\x50\x94\xc5\x61\x18\xed\x1f\x22\xdb\x64\x44\x28\xb4\x74\x65\x1f\xe3\x6b\xe8\x2f\xa3\x69\x5c\x41\xfc\x86\x99\x66\x7e\x05\x37\x43\xb0\xa4\x11\x55\xc3\x1f\x1e\x26\x79\xc6\xe8\xcb\x9c\x9d\x1f\x5f\x4b\x40\xa3\x20\xa9\xfd\x9f\x47\xda\x9b\x94\x21\x1b\xa6\x01\xb2\x2a\x11\x52\x10\xd9\xf5\x59\xc4\x49\x6f\x01\x73\x24\x58\xf4\x9a\xc3\x4e\xb3\x86\x63\x6c\x8b\x6c\x68\xc7\xbb\xc0\x07\x8a\xb6\xf3\x98\xa6\x24\xb8\xba\xfb\x1c\x62\x29\x58\x56\x2d\x23\x1d\xff\xd4\xdb\x09\x61\x96\xbb\x87\x47\x9e\x42\xea\x22\xac\xbd\xcd\xe8\xde\xb1\x0e\x31\x16\x32\xf0\x2f\xca\x14\x78\x7f\xd3\x14\x05\x69\xb9\x42\x89\x91\x54\x3e\xc6\xe8\x34\xe1\x0b\x14\x9f\x23\xc7\x4b\xb9\x9a\xc7\xb3\x79\x9a\x20\x96\xd2\x2e\x38\x7a\x71\x2b\x6f\x90\x11\xea\x34\xc5\xbe\x4c\x46\x85\x81\xac\x62\xce\x66\x20\x63\x25\x2e\x06\x6a\x9a\x3b\x15\xc9\x57\x0d\x06\x5d\xc1\x61\x99\x29\xf0\x6b\xc7\x5a\x31\x79\x46\x8b\xc8\xa1\x6e\x3d\xdc\x4f\xe1\x85\xce\xba\x0a\x92\xa5\x46\xb8\x67\x5f\xc1\xad\xe5\x63\x07\x15\x0c\x7e\x4c\x84\x4f\x6a\xa5\xf1\xed\xbf\xb5\x4a\xc6\x32\xca\x2b\x25\x9c\x32\xa3\x3e\xe2\x86\x78\x56\xc3\x39\x0a\x67\x40\x36\x4c\xb0\xdf\xb9\x76\xe5\x3d\x0c\xc6\xc4\x2a\x10\x6a\x1c\x26\x91\x8c\x8a\x6a\x03\x3b\x2a\xa3\xc7\xf2\xe4\x39\x2e\x79\xf8\xec\xa5\xb3\x36\xba\xc5\x06\x1d\x76\x98\xa3\xbf\xe7\xc2\xc2\x92\x89\x25\x54\x03\x0d\xe6\xce\x7c\x0d\x06\xee\xfc\x54\x90\x6f\x81\xe0\x09\x7f\xcf\xf2\x7d\x14\xb9\xb7\x99\x4a\x79\x70\xe1\xa5\xf5\xc6\xb6\x40\x5d\xca\x22\x03\x3d\xff\x0e\xae\x13\x8a\xd8\x99\xf6\xee\x68\x12\x0b\x8f\x22\x74\x4b\x02\x69\xa9\xa8\x98\x9b\x6f\x7e\x08\xaf\xfa\xe7\x7b\xca\x21\x68\xad\xe2\x40\x58\xae\x68\xa7\xf8\x00\xe0\x2e\x7c\x38\x39\x1b\xaf\x56\x5d\xd4\x0b\x55\xfa\x3a\xb3\xc2\x47\xb9\xce\xb4\xd9\x67\x47\x17\x75\xe6\x63\xd6\xa1\xc6\xc7\xe1\x73\x50\xbb\xd6\xb9\xa3\xeb\x1e\x48\x4a\xc2\xe7\xa7\xa5\xc8\x4f\x50\x83\xe5\xac\xe8\x73\x0d\xe8\x9c\x47\xe8\xdc\xf8\x34\x1e\x40\xba\x34\x5d\xbd\x66\xba\xe0\xf7\xf0\x76\xa7\x05\xb1\xbb\x7f\x47\x0e\x3e\xdf\xb2\xb7\x8e\x4d\x63\x59\x41\x3d\x18\xd3\x32\x80\xb4\x54\xa0\xdb\xb8\x81\xd8\x60\x67\x26\xfa\x9b\xea\x27\x24\x75\xe7\x9f\xea\x6a\x54\xcb\x4c\x06\x19\x54\x1b\x4e\x77\xc1\x70\xc8\x61\x68\x74\xb9\x54\xbe\xb8\xd1\x05\xb8\x6b\xd1\x91\x7e\x25\xcf\xba\x92\x67\x18\x7e\xe2\x03\x8b\x3f\x00\x78\xf4\xc3\x18\xb5\x87\xcf\x44"}, -{{0xe6,0x08,0xd5,0xde,0x97,0x97,0x90,0x7d,0xb6,0xd9,0x8e,0x03,0x45,0xd5,0xca,0xf2,0xad,0x33,0xe0,0xed,0xde,0xbf,0x18,0xb8,0x1d,0x61,0xe8,0x37,0x3e,0xcf,0xb4,0x99,},{0x60,0xe0,0xc1,0x6a,0xda,0x58,0x6e,0x36,0x46,0x91,0x2a,0x5f,0x2b,0xb3,0x18,0xfb,0xc3,0xd5,0x0b,0x57,0xd3,0x6f,0xab,0xb6,0x37,0x69,0x6f,0x9d,0x8d,0x4d,0xc7,0x61,},{0x0d,0x8f,0x09,0x5e,0x42,0xa2,0x73,0x0a,0x3c,0x7b,0xed,0xf4,0x2d,0x5c,0x83,0x39,0x8b,0x5c,0x0e,0xe9,0xc7,0x7c,0x5a,0x61,0xd9,0x82,0x29,0x13,0x96,0xa9,0x18,0x2a,0x08,0x02,0xa3,0x7f,0x32,0x4b,0xc4,0xfb,0x5d,0x4a,0xa4,0xed,0x60,0x44,0x4b,0x66,0x14,0x4b,0xac,0xbc,0x86,0x51,0x05,0xd7,0x69,0x0f,0x14,0x06,0x50,0x69,0x1d,0x03,},"\xe6\x10\xfa\x7d\x83\x85\xc0\x9c\x78\x98\x9e\xd5\xef\x7a\x23\x05\x47\xf0\x13\xcb\x7e\x8d\xdf\x31\x74\x9f\xfc\x31\xce\xe1\x0a\xb3\xef\xac\xa3\xf1\x4e\xa1\x94\x51\x0f\x09\x85\xa8\x18\xef\x8b\x04\x0e\x10\xc3\xa5\x11\x4d\xe1\xac\x08\x0f\x14\xc3\xd6\x5d\x3c\x24\x4f\x92\x42\xf7\x54\x92\xca\xba\xe8\x00\xfc\xfc\x9b\xc2\x75\xea\x1f\x27\x72\x8c\x92\x0c\x25\x8f\xe7\xaa\x73\x94\x80\x60\x29\x9c\xb8\x78\x35\x79\x2e\xdc\xc0\x72\x15\x0b\x73\xce\xfe\xb0\xd5\x15\x62\xe5\x3b\x46\x81\x0e\x27\xa4\xd7\xf6\xab\xd3\x2e\x95\x9f\x7d\x73\x1d\xde\x01\xd9\x4b\xc4\x1e\xd8\x35\xef\xcd\x42\xc9\x22\x43\x70\x37\xa8\x7d\xd3\x66\xff\xad\x2e\xec\xab\x6a\xba\xeb\x4f\xcf\x07\x39\x2b\x3a\xb4\x0c\xfa\xef\xea\xa4\x26\x6b\xc5\x37\x67\x16\x93\xc9\x09\x3d\xab\xe8\xa0\x53\x8c\xaf\xd1\x2c\x63\x9a\x04\xbd\x2b\xa8\x0c\xe0\xf2\x9a\xdb\xfc\x66\xbd\x46\x37\xca\x05\x43\xa5\x3b\x0e\x37\x1d\x0e\x2e\x47\x0d\x31\xba\x36\x06\x42\xa4\x5a\xb4\xcf\xe3\xe7\x90\xf5\x87\xf6\xc5\xa5\x58\x3f\xd1\x5b\x18\x99\x78\x38\xa2\x00\x92\x1c\x1c\x39\x9c\x0b\x16\x27\x8b\x7d\xd6\xd3\xaa\xab\x6f\x32\x5b\x16\xaf\xdf\x76\x1a\x1b\xbf\x86\x7d\xe2\xbd\xd4\x86\x15\xf1\x5b\x52\x67\x70\xed\x20\xd7\x9f\x0f\x30\x71\x4b\xee\xed\xa5\x8f\x52\xa3\xcc\x0c\x5a\x61\x83\x15\xe5\x22\xb9\xeb\xe7\xcd\x99\xb6\x5e\xd5\x32\xa6\x2e\x0f\x0d\xf7\x27\x64\xd6\xec\x6d\x6d\x1b\xa4\x0e\xf4\x0e\x05\x42\x63\x60\x79\x5d\x6d\xd8\x5b\xb3\x9f\x73\x21\xd3\xfb\x06\x27\x5d\xe0\x96\xaa\xe4\xa2\xfa\x22\x93\xf3\x1b\x33\xf4\xad\x4d\x7c\x25\x1a\xc1\x3e\x8e\x15\xc2\xbf\xb1\xf9\x8f\x49\x62\xc5\x4b\x6c\xe0\x33\xb0\x8a\xa6\x26\xf2\x90\x5d\x46\x3f\x55\xb7\x1c\xbd\xad\xec\xdb\x3e\x0b\x36\x5d\xae\x07\xb1\x70\x30\x19\x83\xae\xb8\x3b\x1e\x9f\x2f\x28\xcf\x65\x41\x9f\xd6\xb0\xa1\xa9\xc2\x6c\xb5\x4b\x59\x49\xf4\xbc\x01\xa9\x86\x81\x84\x4b\x43\x03\x4c\x37\x2a\x45\x3d\x38\xf0\x47\x3d\x0d\xdc\x70\x9d\x9f\x49\xc8\x75\x3a\x75\xb8\x56\xc7\xe9\x77\x55\x17\xdf\x57\x4a\x09\xa3\x95\x3b\xde\x5d\xae\xdf\x8e\x4a\x8d\xa9\xd7\x73\xa2\x15\x12\x0e\x26\x9f\xa1\x86\x11\x33\xcd\x4c\xea\xeb\x91\xd5\xcc\xa2\x60\x63\x25\x45\x8e\x50\xcb\x96\x6d\x14\x05\x5b\x22\x44\x7e\xb6\x5d\xc1\x01\x18\xda\x08\x31\xdf\x28\xc3\xb4\xee\x8b\x11\xf0\x73\x2f\x15\x21\xbb\x94\x82\xb1\x1f\x5a\x86\xb2\x2f\x18\xe8\x3d\xd1\xd9\x67\xd3\x94\x42\x85\xe5\xd6\x3a\x5a\x98\x98\x17\xab\x24\x18\xbc\x7e\xd8\x91\xa3\x73\x84\x67\x47\xa1\x2b\x52\x7c\x2f\x44\xee\x01\x97\xb9\x46\xc6\x7e\x67\xfa\x4a\xa1\xc2\x9f\x33\x79\xd4\x6f\xe0\x7d\x3a\xab\x83\xda\x17\xf9\xd7\x6b\xed\xd3\x84\x36\xa0\x55\xe3\x4c\xa1\xd3\xaf\x5a\x87\x54\xd3\x8c\x17\xb9\xba\x4e\x64\x19\xcb\xab\x51\x5f\x43\x1a\x25\x95\x95\x4e\x42\x8c\x26\x70\xfa\xe3\xbe\xd6\x2b\x45\x96\x17\x9c\xb5\x9e\x21\x10\x87\x08\xd0\x71\xbc\xf9\xc6\x21\xc6\xdf\xf0\x3d\x3c\xdc\x92\x02\x02\x94\x54\x01\x3b\x9d\x13\x38\x47\xf2\x65\x44\x81\x1c\x01\x69\x77\x0f\xdc\x6f\xe5\x63\x8b\xfd\x7a\x72\x0d\x8b\x38\xf7\xe3\x0a\x7e\x68\x79\x06\x0b\x5f\x28\xc8\xab\x17\xb0\x02\x00\x71\x32\x07\xe8\x63\x7b\xff\x48\x44\xd8\x42\xd9\xca\x78\x83\x91\x34\x01\x98\xa3\xfe\x01\x72\xdf\xa7\x4d\xe1\xe5\x5a\xde\xfb\xc2\xe9\xbc\x7e\x88\x54\x76\xd1\xb9\xc0\x55\x81\x34\x08\xa4\x75\x28\x43\x43\x55\xbf\x03\xfd\xd4\xe2\x7d\x8b\x34\x61\xb0\xfb\x66\xab\x3e\x15\xa8\x79\xa1\x84\x45\x7e\x9e\xd9\xea\x6c\x51\xb6\x63\xb3\x1e\xdc\x8c\x4a\x3c\xd4\x54\xf6\x9d\x9c\xe5\x18\xd1\xb8\x78\x88\xee\x3d\x9d\xd5\x41\x6e\x43\xe1\x14\xac\x05\x72\x13\x52\xdf\xfc\x2c\xa8\x85\x97\x37\x7b\xbc\x41\x40\x09\xb0\xc2\xfd\x36\x9b\xe5\xba\x35\xa6\xdc\xe3\x47\x8b\x6c\x11\xb3\x3c\x0a\x33\x91\x8b\x6e\xe5\xac\x4c\xd4\xc2\xf1\xca\x6b\xd1\x90\xa0\x00\xa8\x38\xda\x38\xf5\x30\x77\x56\x03\x35\x59\x6d\x13\x58\x93\x77\x93\x96\x38\x10\xa7\x9a\x21\xb8\xd4\x61\x40\xe7\x68\x89\x8d\xcd\xa8\x8a\x0f\xaf\x8d\xdd\x0d\x63\x38\x47\xaa\xea\x0e\x03\x0b\xe6\x45\x5b\x41\xe3\xed\xe1\xe2\x87\x37\x30\xeb\x84\x81\xac\xaa\x7a\x51\x9c\xf9\x19\x58\x47\xa8\x6a\xfa\x57\xf9\x07\x1d\x44\xf4\xaf\x4c\xa0\xd3\x43\xc9\x0c\x0d\x22\xd9\x46\x14\x65\x85\xf0\x0e\xf3\xae\xf5\x7f\x0f\x9e\x55\xe8\x18\xc0\x12\x8a\xe2\x55\xdb\xc3\x11\x6c\xf0\xfe\x02\x16\x6d\x54\x85\x9d\xec\xbf\xdc\xcc"}, -{{0x0e,0x86,0x87,0x2c,0x78,0x62,0x0f,0x10,0xcb,0x6d,0xfc,0x46,0x3d,0x2c,0x28,0x72,0xc4,0xda,0x66,0x07,0x48,0xc9,0xcd,0xa0,0x1a,0xb1,0x45,0x69,0x58,0xaf,0xba,0x7f,},{0xde,0x49,0x89,0x98,0x92,0x69,0xca,0xbd,0x8f,0x4f,0x40,0x9c,0xf1,0xa4,0xd9,0x74,0x03,0x8b,0x27,0x55,0x02,0x27,0x35,0x57,0xf3,0x12,0xd5,0x55,0x3f,0xab,0x93,0xc3,},{0x20,0x37,0xe9,0x77,0x41,0xc3,0xe6,0x40,0x9c,0x66,0xfc,0x67,0x82,0xaa,0xb3,0x89,0xc5,0xd7,0x78,0x09,0x7a,0xc7,0x78,0x99,0x9e,0x85,0x76,0xe4,0x9e,0xf4,0xf6,0xa0,0xc7,0x73,0x0b,0xd9,0xe0,0x93,0xdd,0x3c,0x0a,0xe7,0xec,0x76,0x20,0x33,0x80,0xda,0x65,0x71,0x47,0xd3,0x3a,0x8d,0x9d,0xd6,0x5e,0xd0,0x0c,0xf7,0x62,0x24,0xd6,0x01,},"\xa9\x00\xf3\xe9\xc6\x43\xa5\x64\x9b\x07\x6f\xb6\x9c\x3b\x2a\xc0\x84\xd5\x2c\xcb\xaf\xcd\xca\x5a\x9d\xb1\xda\xa7\x05\x00\xde\x99\x33\xd2\x3d\x15\x3f\x74\x95\x4e\x1b\xd5\xf5\x7b\x89\x9f\xe8\xa4\xb1\x34\xc1\x95\x41\x2b\x49\x83\x3b\x6e\x50\x95\xa6\x55\x4e\xaa\x6d\x84\x4b\x11\xf1\x58\x4c\x85\x05\x5b\x87\xf4\x1c\x99\x96\x69\x04\x6c\x71\xae\xb5\xc0\x45\x3f\xd6\xa3\xc4\x37\xf8\x15\xf0\x68\x98\x7c\x38\x68\xcc\x07\xaa\x2a\xf6\x58\x19\x04\x6c\x30\x7b\xaf\xb7\x53\x0d\xe8\x4f\x71\x30\xae\xa7\x8e\xf0\x05\xd5\xff\xf5\x2f\x8d\xea\xf1\xd5\xe9\xc3\x26\xd3\x21\x7f\xc5\x5b\x94\xf6\x28\xaa\x10\x4f\x6a\x24\xa3\x95\xe6\x2d\x1b\x62\xbd\x9c\x0d\x82\x43\x63\x19\xc5\xd7\x3e\x57\x65\x43\x5f\x3b\xa8\x56\xa4\x73\x4f\xd6\x0a\xe6\x17\xf7\xf0\xc3\xba\x57\x22\xa7\x33\x66\xc8\x8a\x6d\xfe\xca\x85\xc4\x44\x63\x9f\x44\x1f\x2c\x55\xfd\xc4\x64\xec\xb2\x99\xee\xe3\x6d\x8e\xae\x06\x3b\xb9\x4b\xb2\x43\x9d\xa0\x4f\xa5\xeb\xc5\x09\x23\x38\xa5\x03\x5e\x48\x0f\x08\x34\xae\xee\x8d\x71\x1f\x28\xc4\x6d\xc9\x60\xde\x1b\xe9\xdf\x30\x7c\x18\xc5\xc1\x78\xb2\x62\x96\xdc\x56\x7f\x15\xbf\x60\x86\x3a\x36\x71\x08\x67\xe9\x2f\xd5\x10\x48\x86\x56\x74\xc2\xaf\x0c\x53\xb2\xe7\xa2\x48\xae\x5b\xd0\x9a\x49\xaa\x03\x06\x18\x49\x5f\x82\x48\x0c\x42\x0a\xe1\x06\x88\x9b\xec\x00\x62\x78\xb9\x22\x72\x07\x57\x09\xfe\xc9\x54\x87\xcf\xb1\x00\x61\xe6\x72\x2b\x93\xee\xbf\xc0\xbc\x58\x7b\xf7\xba\x5f\x66\x92\xb0\x74\xf5\x5a\x98\xd5\xc3\x02\x76\x0b\x1b\xf1\xd0\x9f\x7e\x86\x68\x47\x9c\xa6\xf0\x1e\xed\xa2\xfd\xaf\x58\x4a\xc2\x05\x8f\xbf\x7c\xf3\x10\x0d\x06\xb8\x09\x1b\xfe\xab\x51\xc0\xc0\xb1\xd4\xee\x3a\x82\x57\xf6\x9b\x16\x17\x60\x4f\xce\x95\x3b\xb5\xf7\xf2\x71\xc6\xa1\x88\x0e\xa1\xb3\xf6\x62\x67\xe2\x43\x9f\x34\x58\x06\x28\x91\x78\x77\xc6\x6e\xc0\xfe\xd7\x6e\x44\xe8\xbb\x2b\x91\xa8\x80\x6d\xf4\xba\xca\x6c\xc9\x28\x89\xb8\x80\x50\x70\xc9\xa6\x17\xf8\x07\x15\x75\x30\x75\x1c\xc1\x7c\x47\xb0\x9e\xeb\xa9\x4d\x22\xb4\xe5\x47\xc3\x70\xce\x7a\x49\x6f\xca\xa3\x41\x2a\xff\xff\xb8\xc9\xb4\xde\x89\xb9\xf1\x21\xaa\xec\x5f\x54\x4b\x0c\x72\x5e\xc5\xee\x9d\x4b\x34\x76\xad\xc9\xd0\x50\xed\xb0\xfd\xba\xf0\x2c\xa9\xe3\x8a\xf1\x5f\x51\x50\x15\xa2\x67\x29\x2e\xc9\xaa\x54\x44\xed\x1d\xec\xd9\xcd\x9e\x1e\xad\x64\x87\xa0\xcc\xef\x99\x5b\x1c\x60\x0a\x03\x69\x35\x83\x86\x60\xac\xab\x27\x6d\x8b\x0e\x5b\x07\xd9\xf3\x63\x53\x21\x4b\xf8\x0f\x94\x1a\xc8\x8c\xf4\x0a\x08\xaf\x91\x79\x26\x23\x41\x12\xec\xcd\xaa\x16\x2d\xc9\x9d\xe3\xe2\x5b\xaf\xf6\x5b\xb0\x1e\x49\x89\x89\x86\x33\x2b\xdc\x2d\x70\x5d\x5a\xea\x40\xf9\xbc\x4f\xbb\x28\x06\x89\x44\x96\x03\x8d\xa2\x36\xe9\xdc\x29\x60\x0c\x9c\xed\xea\xc3\xb6\x16\xcc\x56\xd8\x9e\xc2\xfa\x67\x38\x96\x66\xc6\xc4\xfe\x23\x3b\x63\x91\x05\x02\x3e\x10\x1b\x87\x4a\x63\x30\xfe\x57\x3f\x80\xac\xe5\x5d\x03\x7c\xc6\x12\xe6\xdf\xd5\xa6\xe6\x86\xf9\xa8\x30\x54\xfc\x46\xe1\x5b\xb6\xda\x45\x3d\x81\x0c\xf1\x38\xa1\x78\xbf\x03\x9d\x1e\x18\x16\x14\xff\x40\xcb\xe6\xbb\x3b\x47\x36\x63\x75\x2e\xa8\x02\x5f\xf7\xf7\x39\xee\x4b\x67\x11\x0f\x96\x80\x89\xb2\x47\x3c\xd0\x44\xd4\x8b\x00\x9d\x06\x77\xf7\x91\xf5\x4e\x2d\xf6\xaf\xdc\x3a\xcb\x9e\x99\xdd\x69\x58\xa4\x50\xc0\xe1\xb6\xdd\x5e\x97\xa2\xcc\x46\x29\x8b\x4f\x48\xac\x6a\xda\xf0\x13\xd7\x5b\x2c\x42\x07\x2d\x2e\xe1\x3f\x73\x36\x87\xee\x83\xc3\xf7\x0c\x4f\xdd\x97\x20\xfd\x17\x98\xc6\x62\xfe\xf3\xba\x01\x2b\xed\xd4\x45\xc4\x72\x9f\x21\x30\x48\x4f\xe7\x7a\xc1\xb4\xc4\xdd\xeb\x81\xfa\xf6\x0f\x76\xe3\xbd\x7d\x21\xa9\xa6\xc5\x7a\x69\xa9\xcd\x9c\xc2\x03\xfc\x63\xb5\x9e\xe8\x4b\x89\x15\xb3\xc1\x8a\x59\x54\xe2\x27\xc8\x6e\xbb\xb7\xd4\xc4\xc1\xa0\x8d\x0c\x5e\x46\x7c\x68\xa0\x69\x70\x75\x1e\xf5\x84\xbd\xd6\x11\xe1\xdd\x1b\x48\x90\x0a\xb3\x54\xb9\x9c\xec\x6e\x1d\xf3\xbd\x41\x46\xea\x07\x55\x35\x0d\xc1\x1c\x3a\x3f\x60\x0d\x47\x0a\x74\xf4\x75\xe4\xfe\xed\xaf\x08\x65\x27\x6f\xa8\xa9\x77\x13\x47\x1d\x0c\xa9\x95\x5c\x71\x35\x88\x33\x9d\xee\x79\x65\x6e\x56\x7e\x6a\xb1\xdb\xf9\x83\x07\x03\x81\x7a\xe6\x20\x92\x9a\x06\x84\xa5\xca\xf2\x0f\xef\x81\xa8\xee\x89\x7b\xe7\xe5\x05\xad\xe6\x49\x6b\x9a\xef\x02\x72\xbd\x8f\x35\x08\x60\x23\x3b\x33\x8c\x2e\x36\xd3\x13\x8d\xb6\x95\x38"}, -{{0x52,0x03,0x54,0xd8,0x5a,0x87,0xd7,0xc2,0x2c,0xa6,0xf7,0x84,0x71,0x44,0x10,0xec,0x98,0xbf,0x6a,0x65,0xf8,0x03,0xef,0x93,0x79,0xbd,0xc8,0x04,0x35,0x9b,0x23,0x49,},{0xd8,0x51,0x1c,0xea,0xc2,0xfd,0x66,0x1a,0xcb,0xff,0xb0,0x1b,0xa2,0x74,0x1c,0xad,0x88,0x99,0x34,0xde,0x63,0x92,0x96,0x1b,0xde,0xc6,0xfa,0x46,0x12,0x3b,0x7f,0x0f,},{0x75,0x4e,0x60,0xd3,0xf6,0xf4,0xab,0x4f,0x5d,0x0d,0xdb,0xb0,0x01,0x53,0x20,0x09,0x16,0x63,0x88,0x48,0x7f,0x78,0x0b,0x76,0xf6,0x0b,0xd0,0xbc,0x9f,0xef,0xab,0xfa,0xab,0x6b,0xe2,0xae,0x78,0x69,0x57,0x3a,0x64,0x79,0x6e,0xf2,0x84,0x6e,0x85,0xe5,0xcd,0xae,0x52,0xdb,0x10,0x44,0xfe,0xfa,0x79,0x6b,0xac,0xf4,0x8b,0x96,0x8b,0x0d,},"\xa1\xd4\xad\x48\x6e\xbb\x7c\x1a\x0a\xcb\x8f\x11\x70\x13\xe8\xe4\x74\x67\x89\xc6\x24\x4a\x56\xc9\xed\xfb\xf1\xef\x37\xac\x13\x09\xaa\xf5\x1c\x93\x75\xfc\x12\xca\xcd\x68\x97\xa4\x47\x95\x45\xf2\xbf\x39\x0a\xb7\xc0\xc0\xe5\xc5\x92\xf5\x50\x6e\x99\x38\x37\x8a\x11\xb6\x36\xbf\x85\x70\x29\xb9\x68\x54\x7a\xa5\x06\xc4\xa0\x82\x9a\x15\xfd\x39\x95\xfe\xad\x4f\x86\x0f\xd7\xc6\x23\xc6\x3e\x86\x95\x43\x6e\xae\x55\x81\x64\x14\x77\x83\x47\x09\x2f\x5f\x4d\x42\x2b\xb1\xb5\xe5\xa0\x69\x66\x24\x1e\xfe\xc1\x4f\x1e\x4f\xca\x06\x63\x91\x14\x71\x8c\x30\xeb\xca\xdd\x4c\x6d\x8a\xbe\x7f\xe9\x3b\x25\xd1\x71\x73\x53\x39\x54\x18\x8b\x1a\xb0\x3f\xcb\x77\x92\xcb\x63\x5c\xe3\x6e\x9b\xdb\xdd\xe7\xa5\x61\xc5\xf6\x69\x20\xd9\x10\xcb\x26\x9c\x8c\x1c\x3f\x59\x32\x65\x09\x00\x72\xc4\x89\x32\xe6\x92\xa9\xc7\x38\xc7\x04\x89\x74\x89\xa7\x15\xc2\xb3\x94\xd5\xa8\x6f\x70\x36\xa4\xca\xc5\xdc\xb5\xb8\x5c\xfa\x16\x21\x56\xe0\xbc\x6b\xfe\x02\xfb\x4c\x38\x60\x8c\xfb\x23\xc9\x2b\x8b\x6a\x3c\xb4\x6e\x48\x7d\x60\xe0\xdc\x97\xaa\x2e\x33\xe3\xda\xda\x92\x5e\x4e\x66\x12\xcc\x5a\xf1\x25\xe5\xac\xa4\x58\x17\xa2\xfd\x6c\x3f\xf1\x0b\x18\x93\x8b\x44\xbd\x4d\xd2\x0d\x7f\xcc\xf7\xf2\x6b\x40\xa6\x6f\x48\xaa\xff\xc9\xa5\x41\xe6\xd3\x71\x38\xfc\x55\x46\x98\x68\xe2\xd1\x03\x65\xef\xf3\x7f\xac\x36\x0f\xab\x3d\xc5\x54\x37\xac\x2d\x8f\xea\x74\x74\x40\x5f\xb3\x63\x0f\x79\x63\xd2\xd4\x59\x58\xf9\x09\xd1\x48\x30\x28\x6f\xf1\x52\xaa\x75\x2f\x51\x0c\xe9\x80\xbd\x57\x54\xe3\xfa\x32\xc6\x99\x24\xdd\x95\xd5\xc1\x52\xa7\x37\xa8\xfa\xdc\xfd\x0a\x45\x60\xe0\xb1\x14\xf8\xe8\xaa\xa6\x18\xd4\x38\xb9\x87\x71\x11\xda\x17\x40\xef\x81\x7c\x44\x19\x39\xec\xec\x79\x9b\xa1\x6b\x1b\x17\x1c\xa9\xb6\x49\xb7\xd7\x8f\xa0\x52\xd1\x49\x7a\x50\x76\x88\xbe\xde\x49\x00\xab\xc5\x3a\x96\x48\xda\x59\x17\x03\x5c\xef\xfe\x0d\xa2\x1c\x25\xc0\x9b\x06\xd6\x18\x5b\xdd\xa2\xd7\x78\xf7\xed\xe6\x15\x3e\x3e\xaf\xf4\x95\xc9\x79\x6d\x4d\x16\x6d\x2d\x2e\xa4\x18\xe4\xa4\xaa\x6e\x67\x8f\xaf\x06\x96\xe7\x52\xa0\x9e\x02\xea\xad\xe7\x63\x07\x0e\x08\x8e\x99\x64\x91\x9f\xf4\xaa\x4c\x82\xf8\x62\x9a\x3d\x5c\x79\x7c\x2a\x64\x59\x4d\x20\x68\x35\xda\x0b\xfa\x43\xcc\xd9\xdd\xfc\xdb\x6a\xac\x4d\x48\x6e\x03\xc8\x41\x22\x37\x59\x39\xa5\x27\x0b\xc1\x51\x9e\x07\x07\xe5\x1c\x3f\x46\xf1\xe5\xc5\x66\xb3\x3a\x24\x5f\xa0\xc2\x02\x83\x84\x72\x36\x3d\xe9\xf0\xed\xde\x2e\x79\x1d\x82\x29\x30\x95\xf7\x50\xbf\xf5\x45\xe6\xc3\x47\x39\xdc\xc5\x4d\xb0\xa3\x6a\xe2\xe2\xaa\x39\xb0\x7c\xb4\xf6\xa9\x64\x62\x40\xd2\xd3\x14\x88\xf6\x78\x15\xb2\x95\x45\xd2\x20\xbe\x92\x9e\x33\x39\xf8\x28\x1a\x93\x7e\x05\xa8\xc5\xc3\x88\x7e\x06\x04\x8e\xa7\xb1\x8a\x48\xf8\xd9\x1b\x1e\x3a\xf5\xca\xb5\xce\xda\x0e\xbd\x71\xbf\x54\xed\xec\x20\x3d\x37\x16\x5e\x4c\x9f\x9f\x80\x46\x1c\xd2\x9f\xcd\x99\xdd\xea\x43\x96\x93\x94\x1b\x5d\x53\xff\x94\x37\x9c\xf6\x42\x57\x1d\xd5\x59\xa1\x1f\x8f\x38\x3d\x94\x3f\x22\x55\xcf\x71\x58\x00\xaf\x77\x6b\x10\x45\xbf\x19\xa9\xc9\xbb\x09\x51\x55\xdf\xb6\x46\xb6\x5f\x4a\x28\x0f\x2a\x97\xef\x92\x7d\xda\xbe\x24\xa2\xf9\x71\xa8\x17\x0d\xd4\x2a\x08\x92\x76\x82\x5c\xb9\x14\x8c\x01\x5a\xae\x1e\x9d\xad\xf2\x2c\x10\xe7\x54\x8c\x59\xbf\x6b\x86\x8b\x20\xe8\x6c\x83\xa9\xe7\x34\x3a\xec\x27\x54\xee\x62\x25\xf9\xfd\xce\xaf\x8e\x51\xc4\x0e\x95\x5b\xda\x49\xc3\x5d\xed\x38\xfa\x8b\xcc\x1e\x6c\x8f\xc9\xc2\x41\x2e\x91\x04\xc5\xc2\x36\x8b\x1f\x99\x23\xe0\x10\xfa\x2e\xde\x91\x1d\x42\xb1\x39\xf4\x00\x7e\x34\x26\x92\x2f\xfb\x61\x58\xec\xa9\x7b\x47\xcf\xc9\x97\x85\x35\x12\xbb\x9d\x4c\xa2\xf0\x17\xc2\xc2\x63\xdc\x19\x9f\x3b\xf1\xeb\x4f\x15\x08\xef\x82\x8b\x0e\x00\xdb\x21\x00\x27\x36\xa7\xf2\x2e\xc9\x12\x98\x19\x45\x83\x13\x9a\xd7\x5f\x58\xe2\x1b\x51\x8d\xaa\x49\xa4\x07\x6c\x63\x75\xfa\xa6\x08\x91\xa6\x9e\x52\xa6\x56\x69\x9d\x80\x34\xa7\xab\x7f\xcb\xe4\x21\x75\x49\x14\x41\xfe\x61\xb1\x78\x3e\x83\x78\x57\x52\x22\x15\xa5\xfa\xc5\x59\x0b\xed\x2e\x9d\x20\x66\x06\x09\x6d\x3b\xe8\xee\x92\x87\x3b\xfc\x30\xca\xb1\x5c\xe9\xf9\x91\x0d\x01\xa1\x17\xf8\x99\x26\xcc\x3a\xfa\x8d\x10\x4f\x79\x9f\xf3\x80\x98\xde\x28\xb8\xff\x0f\x03\x87\x25\xc2\x90\x3b\x24\xc1\x42\x9c\xea\x49\x25\x24\x9d\x87\x81"}, -{{0x06,0x1b,0xcf,0x1a,0xa6,0xfd,0x98,0x98,0x97,0xb3,0x22,0xe5,0x91,0xcc,0xef,0x54,0x54,0xef,0x4a,0x5a,0xdb,0x1a,0x48,0x00,0xf3,0x26,0x11,0xcf,0xf2,0xb5,0xbc,0x78,},{0x73,0xc8,0x0b,0x73,0x4b,0xfc,0x94,0x17,0xd5,0x76,0x89,0x0c,0x20,0x16,0x6d,0xa5,0xc7,0xfa,0xbd,0x61,0x3f,0x75,0x47,0x4f,0x76,0x49,0x73,0x2e,0x00,0x29,0x5b,0xe2,},{0x5a,0xda,0xa9,0x43,0x30,0xa0,0x35,0x37,0x12,0xa3,0x4d,0xbe,0x97,0x3b,0x75,0x18,0xf9,0xa2,0xc7,0x13,0xf8,0xaa,0xd1,0x00,0x25,0x1b,0x08,0x6a,0xe8,0xde,0x26,0xf6,0xd2,0xb6,0xcc,0xf0,0x52,0x8c,0xc5,0xde,0xdc,0xa3,0x18,0xdf,0x19,0xcc,0x7e,0x45,0xde,0xae,0x28,0x1e,0x13,0x24,0xb9,0x6e,0x32,0xfe,0xf4,0x5a,0xaf,0x60,0xb1,0x0c,},"\xd6\x3b\xb9\x20\x8c\x1f\x4c\x7d\x43\x32\x6c\xf3\x5f\xa5\xd8\x39\x33\x15\x18\x04\xab\x89\x1d\x49\xb0\xbd\xaf\x42\x9e\x4c\x39\xa3\x21\x42\x8e\x0d\x90\xaa\x00\x31\x8b\x97\xe0\x8c\x70\x24\xc9\x12\xcf\x38\x88\x79\xf3\xcf\x97\x4b\xb2\x53\xa1\xe7\xa4\xc8\xee\xc1\x93\xbf\x4c\x14\xaf\x6f\xb9\x79\x4d\xf0\xd4\x97\x85\x0e\xdb\x04\xd5\x74\xc9\x7e\xd7\x6c\x70\x21\x39\x96\x84\x01\xb4\x0e\xb5\x43\x94\xef\x4c\xfa\xa7\xe5\xd3\xcd\x94\x3a\xf1\x21\x92\x53\x8d\xde\xe5\x93\xc2\xa2\x4a\x26\x7a\xfa\x13\x71\xfd\x77\xfe\xee\x20\x71\xf4\x36\x9f\xbe\xf8\x79\x76\xe7\xeb\xd8\x1d\x1e\x5b\x31\xd6\xe0\x9e\x02\xd8\x30\x35\x7d\x36\xbf\xf8\x59\x67\x03\xe4\x14\x6d\x08\x27\xbe\xc9\xc0\xf8\x7b\x26\xf3\x11\x95\xc9\x6c\x93\xb6\xd8\xc4\x67\x67\xec\x1b\xc6\xde\x39\xf0\x00\x8a\x41\xff\x87\x5d\xa0\x50\xa3\xf8\x65\xab\x92\xcb\xf2\x9c\x38\xa2\x80\xf3\xbf\x69\xf6\x8e\x92\xb5\xf4\x30\xcd\xee\x35\x01\x98\x1d\x0b\x3d\x18\x90\x96\xe0\xae\xac\xd6\x4c\x33\x10\x24\x21\x34\x88\x12\x15\x8b\xb6\x1e\x51\xae\x93\x65\x92\xb2\xf8\xf1\xb9\x10\x94\x9e\xf3\x72\x32\x58\xa9\xb4\x4e\x4e\x1b\xda\xdf\x1a\xe2\xcf\xc1\x8e\x37\xd2\xed\x0d\xd1\x73\x44\x04\xb8\xba\xa5\xf3\x93\xcd\x56\x06\x9e\xce\xbf\x7e\xdd\x7c\x06\xcf\x6c\x8a\xa3\xe8\xe1\x2f\xbf\x94\x6d\x7b\x32\xd8\x45\x3b\x6f\xbb\x65\x35\x52\x6c\x8f\xb8\xfc\x1d\x58\x15\x56\x0b\xb3\x1b\x99\x5d\xf2\xad\xbd\x83\x6a\xdd\x92\x9a\x56\xfd\xd9\x3a\x17\x47\xd9\x3a\x40\xc0\x5e\x12\x9e\xb6\xf8\x58\x3c\x29\x21\xcc\x9d\xbd\xda\x42\x25\xe1\x76\xdb\x38\x6a\x02\xec\x40\xaf\x10\x32\xc9\xb6\x2e\x95\x14\x70\x25\xf4\xac\x8d\xd5\x84\x33\xb6\x4a\xc0\x73\x15\x0c\x69\xb9\xc4\x15\x4d\xcb\xb0\x03\x44\xf3\x08\x11\x3c\xd9\x19\x9c\xcf\xb5\x07\x58\x01\xc7\x05\xb8\xfc\x43\xb7\xc8\xbc\x16\x73\x65\xe4\x62\x93\xd0\x6c\x4f\x48\x35\xc6\x4e\xe5\xd5\x38\x3f\x68\x90\xca\x35\xa8\x0a\xf9\x17\x74\x81\x62\xdf\x25\x18\xab\x14\x68\xf1\x53\x62\x98\x99\x40\x6c\xde\x66\xce\x07\xfa\x7d\x29\x93\xda\xbe\x0c\x60\x08\x9c\x91\x89\x24\x88\xf3\xbc\xaa\xec\x40\x8a\x0c\xd0\x8c\x9a\xa9\x8e\x09\x37\xe0\x2c\x41\xad\x52\xd2\x41\xa9\x98\x33\xe3\xb8\x3f\x7d\x3f\x1b\x07\x8c\x31\xd4\x5c\x34\xfa\x01\x75\xab\xbd\x0f\x32\x2b\x8f\xd2\xdc\x83\x49\x1d\xa2\x92\xad\x00\x76\x2e\x3e\x57\x7b\x9e\xee\x0a\xae\x08\x72\x90\x70\xac\x25\xe3\x3b\xc9\x45\x25\xbc\x0d\x2a\xb5\x97\x04\xef\xec\x5c\x01\x48\x42\x1a\x47\x92\x8d\x34\xb1\xe4\x5c\xe7\x21\xee\x64\x47\xfb\x08\x2a\xc4\x00\xb3\xe6\x84\x6d\x20\x4f\x7f\x9d\xb6\xf0\xa3\x2b\x2a\x69\x73\x8b\x3e\xe9\xdd\xbb\x0d\xbd\x7e\x0f\x04\x1d\x7e\xa5\x3a\x5d\x64\x7f\xb5\x0b\x39\xae\x24\xd7\x8c\x8b\x07\xcf\xc4\xe0\x52\x71\x1f\x0d\x46\x39\xe7\x21\xd5\xc3\x6f\x31\xb5\x88\x86\x67\x12\xb7\x57\x10\x8a\x40\xcc\x7a\xbb\xb9\x91\x30\x83\x30\x3a\xae\x05\xa0\xf1\xaf\x0e\xc6\x87\x84\x41\xa2\x5c\xf8\x72\x9a\xba\x42\xa3\xa9\x4c\xe9\xb7\x38\x88\xa0\xf5\xc9\xe4\x0c\x9f\xc4\x54\x10\xf0\x68\x1f\xa7\xf9\x08\x98\x56\x2c\xcb\x4b\xbc\x55\xf0\xab\x1f\xe9\xc7\x0e\xa6\x60\x26\xdd\xa8\xd7\x09\x0f\x7b\x38\xed\xb5\xae\xc1\x55\x7b\x11\x66\x98\x7c\xd4\x1a\x70\x59\xcd\xee\x60\x9b\x74\xd8\xfe\x06\xb7\x05\x9b\x77\x24\xbf\xf5\x30\x07\xf7\xe1\x10\x46\x2f\x06\xad\x14\xd0\x7e\xe1\xb4\xd6\x9a\xc8\x23\xbc\xf5\x76\xd2\xfa\x9e\x2e\x8e\xd7\xf3\x19\x80\x40\xd4\x71\x29\x60\x63\x13\x7c\x98\x1a\xdb\xf3\x64\xcb\x20\xf0\xa1\xad\x20\x54\x47\x2f\x7c\xee\x25\x27\xf9\x98\x09\x61\x5d\x2e\x4b\x73\x4b\x06\xf3\x5d\xee\xcb\xd6\x26\x19\x66\x3d\xde\x81\xd6\xe2\x35\x28\xb0\xc9\x71\x32\xaf\x0a\x23\xba\xd6\x3d\x9c\x08\x14\x2a\x26\xe2\x74\x3f\x86\x18\xec\xfe\x72\x3b\x19\xff\xdd\x0b\x19\xab\xd9\xa3\xf4\xfe\x21\x0b\x1e\x71\xac\xdf\xe3\x8a\xbe\xbe\x23\xf7\xfd\xef\x66\x38\x1c\xbc\x75\xf3\x07\xe5\x57\x72\x35\xb0\x2e\x4c\xd9\xcf\xaa\x15\x03\x08\x68\xed\x14\x53\xda\x58\xf7\x83\xb7\x35\x2b\x04\x65\x68\x44\xc0\x42\x44\x1e\xfe\x6a\x3b\x4f\x8f\xec\x8f\x7d\xe8\x07\x44\x54\x0c\x4f\xc7\xa1\x07\xf4\xe1\xbf\xcb\xd9\x9d\xa2\x5b\x97\x46\x09\x5d\xdf\x01\x25\xd5\x6d\xa7\xe7\xf8\x60\x3f\x04\xd3\x59\xa0\x88\xb4\xc0\x44\xf9\x36\xcc\xb7\xd8\xf8\x9e\xd5\x3c\xc9\x91\xa3\x49\x7c\xa9\x52\x09\x4f\xf3\xc3\x30\x46\xf2\x60\x9d\x07\xb2\x9b\x63\x39\x81\x36\x9c\xb2\xf0\xee\xcd"}, -{{0x2e,0x19,0xcd,0x44,0x2f,0x22,0xa4,0xa9,0x9d,0xff,0xc5,0x5e,0x7b,0xf6,0x25,0xf8,0x9d,0x13,0x44,0xb5,0x63,0xf6,0x78,0x53,0x13,0xa7,0xee,0xe9,0x73,0xb4,0xaa,0x36,},{0xee,0x3d,0xa7,0x6a,0x8f,0xcf,0x40,0x3a,0x29,0x58,0xd4,0x55,0x1d,0xa0,0xa7,0x2b,0x2e,0x73,0x85,0x22,0xb2,0xe6,0xb2,0x0f,0xba,0x6a,0xa2,0x6b,0x32,0x30,0x73,0x57,},{0x28,0x32,0x6b,0x5b,0x97,0x8e,0x0d,0xbd,0xab,0x5d,0xde,0x70,0x37,0x85,0xa6,0x67,0xa7,0xef,0x43,0x9d,0x81,0xea,0x47,0xe0,0x66,0xb0,0x89,0xd1,0x16,0xc2,0x5a,0x34,0xbb,0x63,0x3f,0x26,0x0d,0x55,0xf4,0x5b,0xdf,0x6b,0xcd,0xa7,0x48,0x03,0xd7,0x62,0x4b,0x19,0x27,0xce,0xc1,0x8e,0xb1,0x99,0x22,0x60,0xbe,0xef,0xc3,0x99,0xd9,0x0e,},"\x1b\xfc\x5c\x6a\xa6\xa5\x35\x4f\xbb\x86\x14\x69\x79\x63\x48\xac\x63\x19\x12\x4d\xa3\xf1\x0d\x20\xd5\x0b\xbd\xc7\x15\x9d\x41\xb5\xab\xb1\x36\xc7\x99\x6a\x77\x37\x97\x12\x2b\x52\x5e\x8e\x2d\xca\x19\x54\xf6\x39\x17\x07\x30\x1d\x90\xf2\x10\x1b\x46\xc7\xb0\x86\xef\xa1\x58\x77\xca\xdc\xd0\x58\x12\xdb\x34\xb9\x96\xcb\x4f\x53\x1a\xbc\xd1\xe9\x8d\xb0\x8a\x5c\xf1\x36\x8e\x8f\x4b\x11\x09\x14\x2e\x95\x62\xbd\x00\x85\xff\xae\x5e\x66\x0f\x59\xc9\x30\x79\x3e\xbd\xb6\xe8\x0b\x0a\x2f\x4f\x3f\x59\xbf\x9d\x39\x5c\x48\xd2\x6e\x0a\x72\xa6\x0f\x9d\x1f\xf8\x7f\xd2\xd7\xa3\xf5\x38\x3a\xa9\x02\xad\xed\xed\xeb\xc6\xcd\x1b\xef\xd0\x38\x33\x61\x62\x74\x9d\x91\xa9\x57\xca\x2e\x3d\xd4\x70\x91\xc5\x59\x31\x13\xda\x87\xc3\xd6\x6a\x02\xc8\x0a\x6e\xdd\xb5\x35\xc4\x8c\xa1\xf3\x4a\x97\xfd\x1c\x95\xeb\xc2\xe5\x70\xfc\x8f\xaf\xe6\xe5\xd6\x54\x6d\x1f\x3a\x9b\xa8\xda\xac\x33\x4c\xf4\x7b\xf1\x17\xe1\x28\x0d\x0e\xbd\xf1\x4b\x0f\xcd\xbb\x43\xb8\xd2\x48\xcc\x6b\x61\x32\x0f\xdb\x04\x49\xed\x5f\x5d\xe8\xba\xb1\x21\xaf\x0d\x85\x54\x95\x6e\x6a\x12\x01\x6b\x42\x67\x7b\x44\x36\x78\x92\xc3\xb2\x0a\xfc\xc2\xcb\x9c\xfb\x5b\x10\x0a\x95\xb5\x1e\x8b\x07\xda\x9f\x51\x41\x5f\x4c\xd7\x78\x1a\x31\x37\x65\xe2\x0d\xb2\x7f\x23\x43\xe0\xf7\x19\xec\xea\x9a\xf0\x26\x95\x6f\x33\x87\xe9\xea\x7e\xd0\xa2\x93\x75\x9b\x4a\x26\x22\x02\x80\x7b\x41\x30\x9f\xb8\x0f\x50\x18\x5d\xb6\xa5\xf8\xbd\xca\x17\x88\x41\xbe\xc0\x6a\xdd\xc7\x61\x0d\xf7\x60\x17\xb5\x14\xbc\x41\x42\xf2\x6a\x36\xbf\x5b\xac\xec\xb0\x12\xfa\x41\x71\x0d\xd8\x49\xbe\xf7\xa7\xe4\x51\x43\x28\x36\xfe\x9b\x32\x65\xfd\x5b\x59\xee\x40\xb0\x4d\xad\x85\xcf\x48\xf8\x91\x46\x5a\x84\x2c\xd4\x50\x0a\x10\x24\xee\xfd\xf0\xf5\x54\xf0\xca\x17\xec\x9f\x7b\x71\x52\x56\xa9\xb9\xdb\xe2\x79\x66\x38\x6d\x8a\xc3\x7d\x3c\x51\x58\x96\xde\x0f\x7c\xdf\x7c\xf5\xb3\x20\xff\x7a\x8e\xf6\xb3\x4b\xa8\x20\xab\xa9\x06\x6d\xd2\x53\xc5\xb7\x76\x37\x77\xf9\x4b\x2d\x6a\xd8\xc7\x10\x22\x1e\x11\x37\x53\x5d\xff\x8a\x1b\x75\x65\xec\x81\xbd\x8d\xde\xb5\x02\xe3\xd5\x8f\xf8\xf1\xfe\x6e\x86\xb8\xdc\x15\xa3\xaa\xec\x68\x8b\xbb\xec\xd4\x68\x82\x81\xdb\x0f\x81\x8d\xe0\xf7\x26\x1b\xa9\xcc\x58\xc8\xbc\x0d\x02\xe0\x66\x32\xef\xe7\x28\x7a\xd7\xa8\x43\x31\xa8\x24\xd9\x28\x73\x44\xef\xaa\xa7\x4f\x1f\xc5\x76\xd0\x26\x94\x30\xf8\x56\xa8\x56\x52\x65\xb9\xd6\xef\x71\xfe\x13\x4d\x25\x10\xab\x06\xb6\x0b\xf3\xc1\x53\xb5\x7e\xcf\xd2\xe6\x34\x24\x03\xfe\x67\x8b\x58\x86\xb6\xb7\x34\xb7\xd3\x69\x06\x62\xb6\xc8\xc6\xf6\xe2\x50\xe5\xaf\x6a\x81\x83\x16\x6d\xdc\xd0\xa1\x7f\x0c\xdd\xc8\x63\x6e\xf1\xa6\x84\x98\xbe\x50\xb6\x59\x95\x39\xd4\x6b\x4c\xea\x97\x13\x0e\x08\xf9\x4c\xa5\x3e\x88\x46\x44\xed\xa7\x5d\x23\xcd\x2c\x03\x8a\x5f\x17\xb5\x91\xe2\x13\x69\x37\x8c\xd3\xfb\x57\x62\xd1\xa7\xc3\xe6\x6a\x11\xae\x6e\x91\xcb\xae\x61\x6a\xd0\x55\xe3\x9d\xc4\x1e\x15\x4f\x4f\xce\xd7\xb2\x69\x6d\x9d\xc6\x73\x80\xbb\x8e\xef\x47\x4e\x9a\xa8\x3c\xec\x47\xfa\xfa\xfb\x94\x1d\x62\x65\x64\xb2\x07\x5b\xcc\x08\x56\xda\x8d\x6e\x1b\x0b\x8f\x18\xba\xf7\x51\x3b\xbd\x14\xe4\x91\xed\x51\x79\x68\xc4\xf7\x24\x1a\xf2\x50\x98\xee\x8d\xf1\x30\xb7\xa3\x4d\x59\x73\x6d\x78\x36\xd3\x23\xfe\x3f\x43\xf5\x08\xcd\xcb\x75\x58\x95\xf5\x9a\x00\xc8\x04\xed\x16\x4c\xc3\x39\x92\xf3\xae\xe9\x62\xae\x9e\x99\x0b\x74\x27\x2e\xb9\x87\xb1\x2d\x90\xb2\x73\x14\xd5\x74\x00\xe7\x37\xd1\x34\x3e\x97\x09\x85\xc4\x27\x10\x60\x87\x6a\xbc\xd7\x04\x9e\x7c\x9f\xe2\x44\xff\x3e\xf9\x85\x60\x99\x5b\x74\x82\xd3\x1b\xc7\xc0\x9d\x99\x69\xf7\xcd\x41\xf4\xe4\xe2\x52\x75\x0d\xc1\x6c\xcd\xb2\x9b\x98\x53\x14\xa0\xb6\xe7\x49\xc9\x5f\x9b\xd2\x83\x8d\x5a\xc4\x9e\xe0\x31\xfd\x07\x9b\xec\x30\x28\xdd\x9d\xd0\x7d\xb6\xfa\x62\x2a\xd6\x21\xb3\xb1\xe1\x27\xe8\xfc\xa3\x7b\xd1\x46\xe3\xcf\x70\x3e\x91\x17\x01\xb7\xa1\x6c\x2d\x30\x36\x9c\x94\x64\x8e\xcc\x03\xdf\x10\xd7\xdd\x5c\x05\x58\xfa\x95\x93\x42\x5d\x94\x87\x27\xd6\x86\x0c\x3a\x14\xf8\x11\x24\x51\x06\x61\x6d\x2a\x5f\xa9\x81\xc6\xb7\xf4\x7e\xc9\xde\xf6\x54\x12\xd1\x32\xac\xc6\x91\x9d\xa4\xe8\x85\x97\xaa\x91\x90\xca\x61\x4b\x21\x80\x66\xa0\xf7\xb1\x69\x97\xee\x74\x7c\x5a\x09\x78\x5e\x50\xd0\xa8\x91\xd9\x59\x37\x86\x3d\x61\x3c\xef\xf7"}, -{{0x82,0x10,0x90,0x99,0xd1,0xea,0xfe,0xed,0x5a,0x85,0x20,0x60,0x46,0x49,0x1b,0x34,0xd0,0x6d,0xcd,0xe3,0x3f,0x08,0x09,0x60,0x28,0x7b,0x10,0xfb,0x23,0xff,0x9f,0x78,},{0x08,0x1c,0xfd,0xf2,0xd7,0x58,0x65,0x4c,0x41,0xc4,0x47,0xe1,0xe6,0x27,0x38,0x10,0xf8,0xa7,0x38,0xa7,0x33,0xaf,0xc4,0x22,0x94,0xa2,0xb1,0xbb,0xb7,0x69,0xef,0xce,},{0xb3,0x98,0x7f,0x32,0x4b,0xc7,0xe7,0x76,0xc0,0xf2,0x87,0xfa,0x13,0xad,0x28,0x74,0x16,0x95,0xe2,0xe7,0xbc,0xe8,0xd1,0x43,0xe2,0x9f,0xad,0x5d,0x00,0x99,0x47,0x58,0xe2,0x25,0xfb,0x80,0x21,0x00,0xd2,0x3f,0xd6,0xcc,0xaf,0xee,0x8e,0x0a,0x95,0xbc,0x47,0x9b,0xe8,0xc2,0x3a,0x11,0x31,0x97,0x45,0x76,0x5b,0x7c,0xd4,0x7e,0x70,0x06,},"\x84\xf4\x7d\xd7\x94\x97\x7a\x6c\x15\x05\xac\x8c\x05\x68\x0c\x56\x15\xa2\xd5\xb0\x57\xe3\x9b\x04\xf8\x5e\x3f\x9f\xf0\x49\x60\xe0\xe0\x16\x68\x5a\x86\xee\xbc\xec\xf6\xfb\xce\x5f\xdd\xcd\xac\x1a\x47\x4c\x8a\x0d\x50\x2c\x40\xe1\x0f\x94\x86\x46\xfd\xac\x6c\x81\xf1\xff\xbb\x17\x7a\x2a\x49\x63\xb6\x78\x25\x90\x3c\xde\x65\xb5\xdb\xe0\xd8\x94\x1d\x54\x6c\xff\xa2\xbf\x8a\x8c\xa8\xd6\xc6\x40\x85\x30\xa6\x29\x0f\x5d\x08\x82\xf1\xa1\x67\x2d\xbf\x97\x8e\x10\xc5\xc8\xaf\x5e\x0a\x62\x39\xf0\x65\x5e\xe7\xfd\x9e\x66\x96\x30\x77\xa0\xe8\x47\x13\x73\x97\xd1\xf0\x69\x99\xdc\x6f\x8a\x94\x5c\x60\x03\xea\x4e\xa7\xfd\x58\x37\x8a\xcb\x44\xed\x57\x80\xea\xa3\x67\x79\x6b\xee\xa3\x7d\xdc\x23\x69\x99\xd0\x12\xd6\xa7\x16\xd7\x91\x56\x49\xcc\x28\xe5\x88\x75\x64\x7e\x9f\x5a\xc0\x55\x3c\x0f\x54\x4d\xf5\x64\x69\xc6\x70\x81\xd5\xe3\x03\x95\xf3\xe9\x60\xe6\xa5\x2f\x08\x33\x19\x2c\x54\x8c\xd5\x7c\x92\x6b\x82\xdb\x48\xc3\x61\xbd\xe7\x03\x33\xa3\x70\x08\x3e\xaa\xa0\x68\xdc\x2a\xe4\x52\xd2\x1e\xf1\x33\x1a\xed\x19\x0b\xd3\xe1\x28\x9a\x10\x4c\xf6\x67\x83\x43\x77\xcf\x7b\x5a\x29\x77\x48\x07\xc3\xf1\xea\x9e\x7b\x28\x83\x1d\x0f\x6c\x42\x94\x78\x58\x67\xb1\x37\xb6\x50\x28\xc1\x4f\x93\x2a\x1b\xa8\xe6\xf9\xf5\x96\x24\xfe\x0c\x39\x68\x43\xea\x19\xe4\x6f\xba\x09\x14\x2c\xf9\xd4\x24\x97\x31\x2f\x36\x02\x44\x03\x2f\x1e\x00\xf3\x8d\xd0\xde\x29\xf9\x63\xb5\xcc\xc1\xef\x12\xb2\xcc\x62\x04\xb9\x94\xaf\x1f\x3b\xaf\x19\x6d\x9e\x21\xe8\xfa\x4f\x09\x73\x20\xc6\x44\x04\xd0\xb7\xd5\xab\x38\x56\x0c\xa0\x65\x53\x64\xb0\xb0\x9c\xd6\xdc\x0f\x0e\x05\xb8\xc9\x11\x03\x64\xf1\x42\x4a\x96\x72\xb7\xef\xdf\x7e\x1f\x37\x8e\x23\x45\x50\x56\x6d\xbe\x13\xb0\x15\x78\xb0\x41\x53\xe9\xc3\x7b\x55\x3e\x32\xa4\x44\x1b\xc9\x7e\x29\x53\xbe\xc2\xe4\x14\x55\x51\x0f\x98\x02\xef\x94\x8d\xcb\xf1\x3f\xad\xdd\x72\x2e\xde\x57\x36\x27\xb2\x58\xd5\x5e\x83\xc0\x89\x5b\x22\x91\x9e\x4b\xe5\xce\x8d\x81\x9c\xe6\xad\x84\x3b\x2d\xd0\x9d\xf6\x40\x04\xc8\x26\xc1\xdd\xe7\xce\x64\x80\xa2\x71\xa8\x58\xa1\xdb\x16\x9e\x14\x94\xd4\x46\x90\x32\xbc\xc1\xcc\xd8\x96\x53\x19\x8b\x7c\x07\x3f\x76\xa2\x6a\x29\x99\xb5\x64\x8c\xba\xdc\x15\x74\xc7\x8e\xad\x8e\xec\xe8\x3b\x91\xe1\x29\xc4\x37\xf9\xee\xec\x04\xc8\x07\x45\x90\x02\xe6\x6d\xcc\xa9\xbf\xc2\xca\xed\x9e\x6c\x0b\xa2\x3d\x23\x55\xde\xf7\x56\x65\x74\x94\x30\xee\x92\xc5\x32\xa6\x95\x47\x9f\xec\x92\x91\x74\xf4\x40\xec\xb6\x1a\x5a\xe8\xb2\xb7\xe9\x58\x92\x05\x58\x26\x89\x78\xf7\xfb\x4d\xa1\xb3\x8b\x12\x01\x4f\x5d\x61\xb0\xfd\xd7\xf6\x13\x6b\xa4\x28\x1b\x41\xa3\xa3\xcd\x18\x80\x52\xb6\x98\x76\x5b\x6f\x05\xe4\x1e\x78\x37\x3e\xa8\x30\x46\x97\x87\xa3\x75\x10\x99\x3d\x12\xf9\x3e\x96\xc7\x2d\x72\xf4\x46\x19\x84\xf6\x91\xa4\x1c\x7d\x33\x97\xdd\xd5\xa1\xb3\x92\x37\xd1\x30\x88\x64\xd4\x15\xfc\x6c\x22\xb6\x3f\x37\x6c\xed\xde\x37\xf5\x25\x2b\x51\xec\x72\xe5\x15\x5f\x3b\xdb\x4f\xcd\x54\x12\x49\x8b\xd2\xe0\xc1\xf9\x85\x0b\x3a\x85\xd1\xdf\xd2\x51\x67\xa3\xcd\x77\x1e\x8e\x4c\x9d\x86\x8c\x95\xa7\x17\x5e\x37\x75\xf6\xce\xf1\x7e\x4e\x36\x49\x7c\xe9\xe4\x55\x32\xbd\x7f\x44\xb2\x77\x6e\x40\xf9\x1a\x07\xca\x4f\xa1\xb9\x5d\xbe\x81\xcf\x8f\x49\xe4\x6b\x6c\x82\xa6\xee\x43\x47\x91\x8a\x76\x43\xb0\xd9\xa3\x88\x57\x21\x2c\x69\x3e\xad\xac\xfd\x37\xa5\xf1\xd9\x15\x58\xf5\x45\x4d\xcd\xd0\x59\x35\xf2\x90\xe6\x2d\x7e\x65\x00\x6c\xd5\x49\xf6\x55\x3c\xe7\x41\xdf\x44\xd3\x96\x44\x00\x1e\xb4\x79\xca\x69\x56\x8a\xd1\xf2\x3b\xba\x09\x9a\x41\xa4\x72\x94\xdb\x93\x87\x31\xc5\x30\xaf\x1c\xeb\x92\x17\xd2\x9b\xc2\x70\x56\x13\xc1\xa1\xfe\x9c\x20\x8d\x0b\x01\xba\x6f\x4d\x9b\x4c\x7b\xa8\xf0\x21\xdf\x91\xea\x2d\x57\x8c\xe0\x83\x12\x3e\x83\xba\x4b\x9c\x50\x40\x7f\x66\x66\xfb\xe6\x11\x58\xb0\xd1\xb9\x57\x77\x72\xe3\xea\xff\x8f\xb4\x29\xd0\xf6\xd2\xe3\x84\x12\x61\x30\xf2\x1b\x44\x9f\xb1\xdc\x17\x0d\xb4\x5a\xf5\x05\xbd\x31\x82\x67\x8a\x9b\x5f\x9f\xdf\xf6\x5f\x04\x13\xb6\x72\xc4\x78\x63\x40\xfc\xf2\x52\x2e\xa7\xf3\xd8\xad\xe8\xa0\x59\x52\x96\x49\xdb\xda\x9c\xe5\x1f\xf0\x5a\x2a\x2a\x3d\x66\xd2\x16\x6b\xf2\xc9\xc6\x77\x2b\xa0\xef\x41\x05\xe6\x8c\x05\x5e\x02\x13\xd4\x2c\x1e\xe1\x23\xb3\xc1\x21\x78\x43\xe6\xec\x57\x5d\x75\x4d\xf3\xc9\x0a\x75"}, -{{0x65,0xfc,0xbd,0x62,0x6d,0x00,0x21,0x11,0x33,0x4b,0xaa,0xd4,0xe6,0xa8,0x00,0x6e,0x47,0xa1,0xf9,0x13,0x97,0xbe,0xe6,0xdd,0x6c,0xd7,0xda,0x5a,0x0e,0x02,0x48,0xa4,},{0x20,0x40,0x9a,0x14,0x6b,0x42,0xc9,0x6b,0xea,0xb0,0xb4,0x2e,0xa7,0xf2,0xc2,0x51,0x93,0x11,0x9d,0x0d,0xf4,0x4d,0xc2,0xbf,0x14,0xd1,0x1a,0x32,0xfd,0x73,0x36,0x15,},{0xbc,0x78,0xe1,0x6b,0xa6,0x74,0xe0,0xa7,0xdb,0xa5,0x7a,0x19,0x09,0x4f,0x97,0x33,0xc5,0x5d,0x74,0xb9,0xd1,0x5f,0x8a,0x44,0xd1,0xbb,0xc0,0xa0,0x23,0xf7,0x01,0x55,0xde,0x29,0x77,0x11,0x1a,0x41,0x7e,0xef,0xa8,0xcb,0x30,0xec,0x12,0xab,0xc8,0x38,0x42,0x28,0x16,0x7c,0x70,0x98,0x2a,0x82,0x06,0xb1,0xff,0xb7,0x21,0x74,0xaf,0x01,},"\xe4\xc0\x94\x7f\xc8\xca\x78\xfa\x88\x63\xf4\xd0\x44\x49\x9d\x03\x6e\x2e\x7e\xf8\xc1\x7e\x83\x8f\x2f\xac\x02\x67\x5b\x7b\x53\x81\xe5\xf9\xab\xce\xaf\xd0\xd8\x88\x6a\x92\x9d\x9d\x9b\x49\xfc\xb7\x38\x61\xb2\x9d\x15\x18\xac\x5f\x83\xf7\xf8\xfc\x26\xbd\x1c\xeb\xc2\x2d\x87\x3a\x9a\x08\x23\x14\x06\xfb\x03\x2e\x48\x66\xe5\xf5\x5c\x7c\x04\x41\xc5\x19\x04\x1b\xb2\xcc\x73\xf9\x22\x6d\xd5\xd0\x7e\xce\xb6\x60\xd6\xc9\x67\xdb\x23\x36\x55\x74\xbe\xe8\xfc\x10\x22\x29\x28\x76\x77\x13\x57\x1a\x71\xc9\x3a\x85\x27\x8d\x42\x29\x9a\x70\x59\x9c\xa9\x93\x26\xcc\x86\xf6\xd9\x8d\xaa\xc0\x00\xfd\xfa\x71\x05\x62\xf4\x81\xfa\xa0\x20\xc7\x2a\x76\xe2\x06\x7d\x15\x4c\x23\x5a\x7a\x4f\x29\x70\x8c\xc5\x44\x53\x3b\xd7\x99\xed\x63\x63\xeb\x3b\x56\xaa\x4a\x6d\x0e\x37\x9b\xbf\x07\x60\x05\x95\xc2\x3a\xb1\xf3\xf9\xf1\x70\x8e\x00\x70\x26\x1b\xbb\xf4\xbf\xea\xf6\xd6\xce\xd4\xd7\xff\x72\x2c\x9c\xc5\x2d\x91\x33\xea\x68\xd4\x95\xdc\x94\x89\xc3\xed\xf6\x83\x02\x31\x35\x1f\x65\xcb\x52\x72\xf5\x39\x6e\x2c\x4a\x1a\x5c\x88\x66\x1a\x10\x18\x92\x24\x9e\x23\xd6\xce\x9f\xdb\x6a\x9a\xbf\x74\x27\x2c\x2f\x59\xc3\xd8\xfd\x87\x43\xcc\xe4\x61\x12\x6c\xa0\xa8\xb8\x32\xb4\xb2\x18\x33\x6b\x1a\xe1\x4d\xa6\x77\xba\x7f\x1b\x2c\xc5\xca\x3c\x71\x58\xf7\x27\xa9\xe1\xb8\xfd\xd9\xed\xf5\xc2\x18\x7f\xcb\x83\xdb\x86\x2a\xd0\xc6\xb3\x92\x16\xde\x31\x16\x91\x95\x56\x46\x51\x00\xad\xe0\xa4\x2b\xd6\xba\x10\xd9\x54\x18\xb6\x9a\x3e\x00\x5e\x9f\x10\x45\x89\xea\x59\x48\xb2\xb5\x1b\xc7\xb1\xa9\xa0\x74\x9d\xa8\xf0\x13\x78\x1b\xc0\x5c\x80\x5b\xb5\x1e\x18\x77\x61\xac\x24\xc7\x64\x14\xf6\x68\xeb\x45\xfb\x0a\x50\x24\xdf\xe5\xa5\xca\x06\xf0\x40\x3a\x02\xe3\xb2\xfe\xf7\xa2\xc4\xbc\xfb\x1d\x07\x5d\x31\x0d\x51\x97\xe6\x59\xcd\x14\x02\x3f\xae\xc2\x0e\x04\x5c\xab\xcb\x86\xb2\x21\xa1\xd4\x82\x71\x13\xff\x32\x67\xa6\x4d\xeb\xe9\x93\x90\x04\xca\xba\xc8\x5e\x5c\x74\x61\xe7\xe8\x2a\x97\x5a\xcf\xae\x0b\x6c\x51\x6a\x1c\x60\x53\x74\xcf\xea\x7d\x81\x90\x44\xef\xd6\xd7\x46\x54\x42\x4f\xd5\xc9\x0f\xf2\x57\x4f\xcd\x8e\x00\x77\x40\xd9\x75\x86\x1d\x0d\xf5\x25\x9f\xe4\x3e\x43\x63\x9e\x36\xe5\x28\x95\x43\x9b\xa2\xc2\x7c\x1e\x88\x9c\x93\x09\x41\x04\xfe\x91\x49\x21\xbd\x6f\x25\xd3\x98\x5a\xb1\xf2\x2c\xa5\x57\xb0\xe4\x9a\xfc\x73\x75\x24\x3c\x52\x1c\x6d\x5f\xaf\xe0\x38\x1c\xce\xa8\x28\xe8\x8e\x64\x7f\xd9\x09\x76\xb3\xfb\xec\x19\xfe\x9a\xdb\x11\x3c\x64\x04\xbd\x35\x2b\xfc\x00\x04\x46\xd2\x10\x05\xb5\xf9\x50\xae\x07\xe5\x1c\x76\x8c\xa3\xff\x61\x77\xb2\xea\xc5\x0f\x10\xdd\x2e\x64\x61\x0f\xa8\xab\x57\x88\xfa\xee\xe2\x9d\x12\x90\x09\xd7\xfe\x46\xaa\x3d\xa6\xb9\xd8\x6c\x73\x06\x5e\xb5\x16\x1f\xbd\xbd\xfa\xc5\x77\x7c\x4e\x75\x45\x2e\x6e\x16\xae\x9f\xd6\x6b\xb7\xd9\xaa\xa4\x26\xbc\xb7\xa6\x91\x5f\x0f\xf4\x4a\x1f\x8e\xc7\x13\x94\xe9\x35\x2f\xdf\x20\xe0\x2f\xaf\xe1\xe0\xce\xfe\x50\x74\x4c\x31\x94\x95\x6f\x92\x8f\x82\x53\x37\x55\x37\x38\x38\xdc\xc1\x29\x6a\x89\x1a\xdf\x64\x1c\x73\x82\xd6\x9b\x4f\x5a\x43\xd4\xaf\x77\x72\xa4\xa1\xee\x87\x92\x92\xd7\xa4\xf3\x2a\xc3\x5e\xe1\x21\xc6\xc3\x4c\xa5\xf9\x84\x87\xa9\x41\xfc\xb1\xe6\x5b\x44\xd4\x45\x61\x27\xee\xdb\x2f\xcc\x1c\x3f\x48\xef\xf9\x30\x09\x81\xe5\x2a\xc3\x8b\x49\x6a\xb8\xbb\xce\x14\x4a\x85\xeb\x9c\x07\x63\x8b\x31\xfd\xaa\x78\x17\x44\xbc\xe1\x7e\x8d\x93\xdc\xdc\x60\xaf\xed\xa4\x88\x80\x76\x17\xf8\x8d\x6a\xa5\x44\x22\xfd\x34\x7d\xda\xdd\xef\xf3\x7a\x56\x3d\xbf\x19\x97\x4b\x2a\x23\xbe\x30\x0f\xbf\xa6\xc7\xfc\x41\xf8\x4c\x69\x05\x41\x52\x69\xf1\x95\x99\x0b\x5b\x4d\xe1\x26\x68\xc7\x1c\x87\xb5\x04\xf4\x11\x24\xbf\x94\x43\x6f\x33\x30\x45\x63\x15\x18\x15\x2c\x51\x62\xa2\x47\x5c\x40\xef\xb6\xcb\xda\xaf\x9a\xf4\x28\xfe\xd3\x25\xb3\xa7\xd9\x4c\x17\x52\x0f\xd8\x9e\x00\xdd\xf0\x8b\x22\xad\xf6\x61\xf0\xac\xd7\x23\xb3\x96\x9d\xc6\x43\x4e\xa6\xf9\x2e\xf5\x8e\x8d\xfa\xe5\xb0\xcc\x28\x85\xba\x98\x7e\xa1\xd1\x6c\x39\xb3\x4e\xf6\x50\x23\x00\x9d\x63\x45\xe4\x8e\x36\x91\xa4\x1f\x02\xa7\x7b\x7f\xe1\x33\xea\x9d\xe7\x56\x5f\x15\x7a\x20\x78\xae\x98\x8b\xbb\x26\x6d\x22\xd5\xfa\x91\xa7\xb2\x63\xe9\x8a\xd2\xdc\x07\x31\xfe\x5a\x29\x02\x5a\x0c\xb4\x36\x86\x4a\x5a\x60\xdb\x25\x7f\x1e\x76\xb5\xc6\x08\xf2\x5c\xde\xcc\x87\xea\xe6"}, -{{0xb5,0x00,0x76,0x8a,0x28,0x23,0x91,0x5c,0x4a,0x68,0x48,0xd3,0x5f,0x64,0x87,0xd4,0x3b,0xd7,0x66,0xd2,0xce,0x09,0x45,0xf8,0xa3,0xcc,0xdb,0x8d,0x82,0xa3,0x89,0x2b,},{0xb8,0xce,0xa2,0x15,0xa0,0x12,0x4e,0xed,0x27,0x00,0x57,0x25,0xd8,0x97,0x78,0x1e,0xa0,0x64,0xdc,0xef,0xb2,0x14,0x22,0xc8,0xbd,0x24,0x02,0xc5,0x6a,0x10,0x57,0x1c,},{0xe3,0xdb,0x47,0xa1,0x1e,0x10,0xe7,0x88,0x92,0x5d,0x14,0xb1,0xe2,0x8b,0x54,0xc9,0xfc,0xf9,0xb6,0xac,0xc1,0xdf,0x8c,0x14,0xf6,0x83,0xa5,0x67,0x2f,0xd5,0x04,0xdd,0x4a,0x47,0x5a,0x33,0x93,0xb3,0xef,0x8b,0xce,0xac,0x23,0x61,0xdb,0xba,0x35,0x30,0xaf,0x25,0xc2,0x46,0xc3,0xec,0x4c,0x05,0x89,0x9b,0x51,0x7f,0x6c,0xd3,0x4f,0x0a,},"\x0a\x9f\xda\x8b\x8c\xfc\xa7\xa5\xb0\x5d\x78\x11\x6f\xce\xe1\x9a\xb8\x03\xc1\xc6\x01\x0c\xe1\x1d\xaa\x8e\x93\xa6\x6d\x12\xc1\x2e\x47\x4e\xb9\x1c\x26\x40\xd9\x7a\x81\x3d\x9a\x83\x0d\x26\x88\x68\xeb\x2e\x37\x70\x42\x5f\x10\xc7\x58\x40\x46\x8e\x66\x9d\xc7\xf6\x1d\x3b\xe2\xde\x88\xae\x0e\x54\x2b\xc8\x09\x67\x91\x13\x95\x7a\x14\xda\x4e\xaf\xf5\x49\xbf\xde\x63\x7d\x7c\xaf\xdc\x6a\xa8\x39\x94\x83\x73\x97\xf8\x6e\x4f\xde\x86\xd4\x02\xfa\x9a\xef\x7f\x65\x54\x9a\x21\x43\x73\xe5\x60\xe6\xd7\xa1\xc2\x76\x9e\x0c\x7d\x5a\x01\x71\xe7\xcc\x00\xdf\xf3\x6e\x04\x29\x79\x8b\x53\xaa\x62\x16\x24\xbd\xa7\x4d\x6d\xf0\xbf\xff\xfb\xd8\xfd\x7b\xef\x1a\x64\xf3\x6c\x00\x07\x82\xf6\xed\x03\x1a\xf5\xc2\xa7\x4a\x18\x96\x35\x98\xc9\xba\x06\x23\x92\xde\x96\x02\x03\x67\x94\xb7\xb5\xe6\x8c\x25\xc9\x3f\xe7\xcf\xad\x47\xa7\xc5\xb9\x79\xd4\x76\xcd\x51\x3a\x12\xbf\x03\x07\xcb\x16\x31\x74\x00\x42\xa9\xfb\xf3\xeb\x0b\xe5\x17\x06\x20\xda\xfd\x5f\x16\xed\x89\x34\x2c\x26\x25\xd7\x83\xe7\x4e\xe0\xd7\x84\xbf\x05\x19\x43\x74\x0c\x88\xb0\xbe\xf7\xbc\x85\xe1\xa6\xa4\xa5\x17\xd4\x92\xfb\x73\x7e\x77\x66\x99\x59\x0c\x93\x22\x4c\xd4\xd9\x24\x5d\x4e\x93\x71\xa3\x67\xc0\x71\x2f\x87\x49\x0f\x92\x47\xc4\x9a\xdd\x93\x13\xf2\x77\xa4\xd9\xf2\x6b\x75\xaa\xe4\xde\xd6\xa3\xde\xf8\x5f\x83\xfc\x99\x59\x10\x40\x55\x48\xaf\x67\x0e\xd8\xaa\xa3\x05\x24\xab\x82\x9c\xcb\x56\xa5\x00\x5b\x58\xbc\xe8\x68\xc9\xe8\x07\x4f\x07\xdd\x7f\x38\x18\xf2\x99\xe4\xe0\x86\xbe\xd9\xea\xb9\x02\xcf\x11\xb3\x98\xd5\x31\xb8\x63\x2e\x7d\x52\x3a\x8f\x87\x76\x95\xf4\x6c\xcf\x9c\xe2\x4e\x62\xca\xb2\xc7\xcd\x0a\xae\xe1\x7d\xb5\x26\x76\xa4\xb5\x05\x8e\x9c\x1d\x7c\x47\xbf\xfc\xb6\x41\xb0\xea\x2b\x09\x44\xf3\x9a\x75\x66\x5a\x7e\xf2\x9b\x7f\x02\xa8\x78\xdb\x82\x38\x83\xbd\xac\xfb\x0f\xbe\x5d\xfe\x5a\x9b\xed\x9f\xda\xc7\xe4\x14\x2e\x3e\xb5\x0d\x5e\x84\x0b\xd0\xac\x0b\xec\xf4\xfa\x97\xe1\xfc\x48\x27\xc3\x97\xa5\x24\x65\xd9\x16\x88\x99\x54\xb3\x70\x1b\x0f\xac\x61\x15\x9b\x23\x09\x2f\x46\x85\xf4\x78\x8b\xad\x35\xd0\x0d\xa2\x67\x9e\xcc\x54\x92\x1f\x1a\x86\x47\x10\x16\x57\xab\x49\x47\x74\x20\x56\x7a\xed\x67\xc8\x60\x59\x30\x44\x4b\x5d\x07\x92\x7c\x17\xef\xf1\xf8\x57\x0c\xf2\xaf\x29\xe7\x19\xf8\x5c\xa7\x84\x9b\x89\x55\x49\xf1\x3d\xfe\xca\x68\xbb\xef\x71\xe3\xce\x8b\x6c\xed\xd2\xff\x68\xd3\x2b\x02\xca\xf5\x95\x1a\x0b\x3e\x6b\x0b\xae\x6a\x96\xc0\x20\x58\x19\x1f\x30\x5e\x09\x07\x11\xc4\x6d\xad\xdc\xd5\xae\xee\x76\x9c\x3a\x10\x5e\x9a\x82\x7b\xbd\x19\x5d\x32\x92\x31\xc2\x62\x38\x47\x9a\x9b\xb0\x07\x1a\xfb\x16\x0e\xf9\x55\xe8\x74\xd7\xa4\x20\xc5\x67\x85\xf4\x4a\xe0\xa1\x8c\x52\xd8\x28\x0c\x59\x98\xcf\x38\x88\xfe\xaf\x89\x89\x81\x34\xbc\x8d\x41\x1f\xc9\xf6\xc5\x76\x8e\xa7\xa2\x49\x72\x94\x13\x73\x9e\x53\x2b\x64\x39\x37\x15\x2c\xdf\xb8\xd2\xff\x87\xfd\x48\x08\x4d\xd8\xae\xeb\xea\xf0\xf7\xb1\x0d\x87\xb6\xe4\x42\x32\x28\xc9\xfc\x8d\xc5\xe3\x85\x2a\xa8\xb8\xac\xc5\x45\xd1\x8f\x25\xc5\x5d\x73\xda\x1b\xb8\x2e\x3e\xb3\x76\xf9\xef\x05\xb2\x74\xd7\xec\xb1\x84\x5d\x65\xca\x0c\xd2\x62\x9f\x03\x8a\x2d\x66\x4d\x7a\x69\x78\x1c\x84\xe9\x8d\xe2\xc2\x09\xc4\x6e\xfc\x51\x16\x21\x72\x85\x66\x49\x46\x9e\x67\x33\x08\xdc\xc1\x45\xea\xf7\x83\xf5\xcb\x5b\x4b\xe7\xd9\xfd\x58\xee\x09\x74\xc9\x81\xa3\x8f\xea\x8e\x31\x26\x7a\xbf\xa4\x10\xe6\x9e\x46\x48\x2f\x51\x34\xf3\xda\x1f\xfe\x38\x1b\xd6\x9d\x8d\x0b\x78\xea\x90\x9b\x4a\xf9\x39\x6d\xca\xff\x89\x96\x0a\x04\x9e\xda\x69\x46\x61\x6f\xc2\x7c\xcf\x9a\x9e\x5b\xa1\xa0\x13\x57\x64\xf3\x77\x19\xda\x4d\x28\x07\x81\x85\xd0\x4d\x72\x41\x9c\x2c\x70\xf2\x90\xd9\x7e\x1f\x82\xb8\x79\xf7\x1b\x9e\x19\xd5\x04\xd3\x64\xcd\x3b\xa2\x2c\xf9\x05\x25\x0f\xd3\x7d\x58\xe5\xfe\x40\x20\x9f\x60\x72\xa0\x6d\x8b\x5b\xa7\x01\x96\x23\x05\x77\x87\x7e\xc4\x61\x53\x16\x7a\x7c\x7a\xea\x27\x0f\xa1\x09\x8a\xba\x9e\x3a\x74\xac\xb3\x6a\x11\xb0\x9b\xd0\x7a\x3b\x88\xea\x65\x4e\x26\x83\x65\x62\x5b\x58\x9b\x22\x06\xc7\x10\xd9\x60\xf4\x2e\xa4\x19\xb7\xe4\xe3\xda\x47\x59\xfc\xbc\xa5\x0e\x4b\xf4\xcc\x55\xcf\x88\xf7\x0b\x31\x80\xc8\x05\xa7\x04\x50\x86\xaf\xa0\x4c\x6b\xe2\x32\x23\xec\xae\x5f\x82\xc1\x46\xd5\x43\x11\xd1\x80\x7c\x2e\x4a\x53\xf9\xe0\xa4\x48\x2b\x4e\x1e"}, -{{0x9e,0xb5,0xc9,0xef,0x13,0x53,0x5f,0x80,0x81,0x09,0xf4,0xa4,0x3c,0xfa,0xd5,0x68,0x4f,0x80,0xda,0xf0,0x2e,0xed,0x54,0x10,0xac,0x0b,0x0a,0x09,0xa6,0x08,0x2d,0x69,},{0x36,0x7e,0xea,0x1e,0xcb,0x4e,0x5e,0xec,0xdf,0x7e,0x47,0x1b,0x90,0xbb,0x34,0xf9,0xb7,0x98,0x2c,0x8c,0xd6,0x6d,0x42,0x55,0x5c,0x24,0x0b,0x41,0xcd,0x87,0x39,0xdb,},{0x42,0x9c,0xe1,0xfe,0x84,0x6d,0x25,0x08,0x49,0xec,0xa7,0xd4,0x56,0xf8,0xc5,0x9f,0x86,0x75,0xb1,0xf4,0xc1,0x3f,0x2b,0xe4,0x16,0x88,0xdf,0xb8,0xca,0x2a,0x3b,0x24,0xae,0x29,0xd5,0xb6,0xbf,0x47,0x11,0x57,0xbc,0xb6,0xe2,0xec,0x9d,0x4a,0x26,0xb0,0x38,0xe6,0xec,0x28,0x58,0x4c,0xc2,0x3f,0x2a,0x03,0x55,0x6d,0xbb,0x37,0xe9,0x00,},"\x2d\x7c\xb0\x5e\x61\xdb\xae\x26\x25\x8e\x38\x61\xc6\x39\xef\x0e\x1d\x17\xfc\x71\x1a\x00\xf3\x35\xba\x3c\x02\x71\x37\xe0\x07\x08\xd7\x08\xc1\xff\x45\x7f\xf2\xc6\x51\x12\xf7\xdc\xd7\xd0\x2f\x24\xd5\x6f\x07\x21\x58\xea\x1c\x71\x83\x25\x50\xa5\x83\x66\xfd\x91\x97\x29\x6b\xbe\x61\xaa\x4d\x00\xde\x18\xa4\x53\xef\x91\x74\xfa\x81\x96\x83\x05\xc4\x1c\x34\x55\xf4\x2d\x44\x7a\x92\x34\xf0\x6e\x13\xbf\x8b\xca\xa1\xba\xbb\x11\x69\x5f\xaf\xdc\x08\xf7\xa5\x84\xb2\xea\x1f\x61\xe9\x38\x92\x60\xce\x73\x35\xa0\x7d\xe7\x2c\x89\x11\xa5\x8a\x31\x3f\x10\x88\xdc\xdf\x5c\x8d\x4c\x45\x6c\xba\x2d\xcb\x4f\x2d\x15\x6b\x49\x43\xb9\x5b\xd4\x93\xea\x4f\xe1\xa8\x2d\x4e\x3e\xa0\x2a\xa0\x29\x72\x40\x0b\x5e\xe1\x78\x42\x83\x2d\x59\x97\x9f\xc1\x79\xf8\x43\xc4\x4b\x03\xeb\x3c\x30\x24\x16\xd0\xcd\xaf\x11\xc4\xca\x8a\x66\xcc\xbb\x69\x97\x39\x5e\xdf\x6f\xca\x2e\xa0\x04\xcf\x34\x86\x97\x10\x04\xa4\x20\x42\xaf\x8e\xce\x00\x5b\x94\x46\x1d\x86\xdc\xde\x21\x2a\x2e\xb1\xbe\x3b\x91\x4c\x78\x3e\x48\xac\x1a\xd4\x6c\xac\xd7\x3e\x1e\xb4\x48\x36\x83\x22\xd2\x67\x8e\xfc\xb2\xab\xff\x52\x09\x3d\xb0\xf2\x59\xdc\xe5\xc1\xe1\x9a\x51\x28\x20\xf2\x35\xd6\xae\xaf\x0e\x1a\x72\x3c\x2c\x65\x0c\xff\x1e\xe3\xb6\xb4\xf4\xcc\x98\x9c\x0b\x7d\x6d\xe3\xcd\x7e\x6d\xaa\x39\xbb\x69\x07\x10\xdf\x00\xa7\x19\x4c\x17\x20\x1f\x0e\x81\xbe\x64\xb6\x73\x9e\x1c\x1e\x81\x76\xb7\xe1\x2a\x35\x34\x27\xc0\x67\xc1\x93\x14\xdb\x64\x2e\x5c\x76\x26\x6b\x64\x0e\xb1\xcc\x0c\x73\xf8\x4f\xc0\x22\x7e\x5a\x96\x06\x0d\x81\x40\x71\xcd\xe2\xfe\xd9\x44\x76\x7b\x74\x66\xf9\x00\x1d\xfc\x22\x36\x85\x42\x9b\xc4\xe5\xe4\x8f\x5c\x13\xa6\x3a\x4e\x0d\x82\x61\x33\xad\x92\x0d\x11\x77\x21\x45\xad\x6e\x13\xc9\x38\x97\x39\x8a\x8a\x40\x1f\x93\xdb\xd1\x03\x00\x5c\x7d\xae\x44\x38\x7f\x3e\x80\xb7\x93\x60\x7d\x05\xd2\xd8\xbc\x0d\x03\x51\xa3\xa4\x52\xb8\xce\x75\x9c\x1a\xd4\x8d\xf7\xb9\xba\x9e\x4a\x17\xdf\x61\xfd\xab\xb9\xb5\x77\xb5\xce\xc3\xe9\x46\x1f\xbb\x5e\x12\x81\x55\xa3\xc9\xc8\x9f\x8f\x6b\xeb\xb7\x32\x2a\x16\x67\x8e\x8e\xcb\x98\x95\x3d\x95\x83\x10\xdb\x1b\x06\x34\x48\xc3\x49\xf3\x6e\x16\x8f\xac\x48\x4c\xb3\xc0\xd4\xcb\x2c\x25\x1b\xd9\x2e\xf8\xe9\x26\x2b\x44\x09\x3d\x7e\x65\x0a\x7d\x3b\xed\x37\x91\xfa\x88\x10\x0f\xee\x6e\xf0\xd5\xe2\x3d\x1e\x9a\x80\x99\xcc\x03\x35\x20\x2a\x4f\x10\x6c\x24\x77\x7e\x98\xf8\x1d\x26\xef\xba\x15\xc9\xad\x15\x41\xe0\xad\xbf\x1d\x1d\x76\x07\x6b\x0d\xfd\x7b\x7d\x6c\x8b\x82\xf9\xc0\x93\x46\x8c\xd1\x96\x67\x2d\xc5\x47\x8e\x91\xce\x70\x1c\xdd\x7b\x68\xb3\x53\xc9\x71\x11\xf0\x42\x97\x60\x63\x57\x62\xf8\x68\x3a\xe9\x70\x56\x4b\xce\xba\x91\x20\x51\x76\x42\xe8\xb3\xa2\xba\xaa\x85\xc2\x5b\x54\xa9\x43\x76\x61\x84\x90\x4c\x72\xd9\x29\x63\x4e\xc5\xf0\xc2\x84\x73\x41\x5f\x12\x53\x89\x06\xc6\x78\xfc\xa4\xe6\x82\xdb\x48\x79\x75\x84\x92\x53\x7e\x78\x50\xb9\xbf\xef\x3e\xb9\x05\x3b\x43\x92\x0d\x81\x0e\x55\xbe\x96\x6a\xec\x68\xc9\xdd\x3b\x62\xcc\xf5\x7e\x81\x78\xcb\x5e\xf6\xd1\x6d\x17\x2a\x56\xdd\x92\x4f\x00\xf2\xd3\xb5\xe9\x3a\xaa\x92\xb2\x9f\xb8\x33\x6d\x73\xe2\x9e\x59\xd1\xc4\x7e\xa6\x23\x0c\xda\x1d\x5b\x03\xbb\xa5\xdf\xdb\x33\x1f\xeb\x19\x44\x3f\x12\x3d\x2a\x03\xff\x4f\x10\xec\xa1\x66\xc2\x99\x85\x88\xf1\xe5\x84\xed\x19\x4d\xd6\xf7\x3c\x8a\xca\x84\x66\x31\x90\x4d\x9f\xe4\xa9\x8b\x36\x78\x23\xe4\x6e\xdb\xa2\x88\x51\x29\x87\x9e\x92\x77\xe1\x50\xf0\x29\xb8\xfa\x7b\xd1\x1e\xab\x9c\xe1\x33\x67\x77\xc8\x0b\x56\xb3\xa1\xf0\x81\x1a\xdb\xca\x0f\x5b\x40\x25\xa5\x50\x3c\x81\x96\x66\x1a\xee\x90\x00\x6e\x9c\x85\xbb\xfa\x4c\x5a\x0e\x90\x28\x85\xc8\xce\x51\x21\x2e\xe6\x7f\x0f\xe0\xb6\xaf\xbc\x8b\xad\x45\x37\x27\x54\x3b\x3c\x68\xb8\x90\xdd\xab\xa2\x69\xd2\x5f\xc1\x64\x3f\x54\x83\x51\x36\xa1\xa2\x5b\xa1\x8d\x91\x6c\xed\xd6\xa4\x7f\xc0\x7a\xdf\x6f\xc6\x9f\xa5\x08\x94\x9d\xc1\x0d\x9d\xc5\xe0\x26\x1b\x52\xf3\x65\x71\x70\x38\x4e\xcc\xd9\xc8\x05\x41\x35\x4b\x1c\xe0\xf6\xfb\x5e\xd3\xe8\xd5\x4a\xf0\xb5\xbf\x0a\x92\x83\x51\x25\xc7\xd9\xbc\x4f\x09\x2f\xf3\x80\xe5\xe8\x96\xfb\xf3\x02\x55\x2b\x14\xd5\xb6\x1a\x22\x4d\x86\xe3\x01\xc7\xa6\x6a\x66\xe4\xe4\x32\x9a\xac\x0a\x66\xb1\x56\x77\x23\x74\xdc\x1c\x71\x68\xd5\xb5\x61\x65\x2f\x8f\x43\x87\xe4\xf2\x89\xb6\x36\x6a"}, -{{0xef,0x09,0x48,0xe1,0x32,0x81,0xf3,0xcf,0x35,0x2c,0xbf,0xaf,0x8d,0x89,0xd1,0x17,0x76,0x85,0x52,0xd5,0xa1,0x54,0x8e,0xcb,0xaf,0x37,0x41,0x2e,0x97,0x67,0x0f,0xac,},{0x58,0xc2,0x45,0x7f,0x5a,0x5e,0x3c,0xfb,0xf4,0x71,0x19,0xa8,0x7f,0x2a,0xff,0x19,0x18,0xf1,0xe6,0x7a,0xe6,0xfa,0x91,0x71,0xd3,0xf4,0x1e,0xee,0x07,0xa8,0x68,0x72,},{0xcc,0x12,0xf6,0x9d,0xb6,0x3a,0x67,0x8e,0xc4,0x77,0xa6,0x05,0xa5,0x05,0xc5,0x7d,0xc2,0xb8,0x10,0xef,0x85,0xe3,0xe3,0x45,0x19,0xcb,0x25,0xc5,0x10,0x63,0xaa,0x66,0x35,0x5d,0x3f,0x1e,0x29,0x74,0x69,0x58,0x66,0xed,0xf6,0xf1,0x71,0x71,0xce,0x37,0x84,0x2f,0xba,0xb5,0x07,0x5f,0xc8,0x95,0xd1,0x8e,0xd7,0x43,0xc5,0x46,0x08,0x0c,},"\x7e\xc4\x7f\x2f\x1f\xe3\xb7\x0a\x6d\x1d\x82\xc7\xcd\x92\x4b\x4b\xf9\xb2\x02\x9f\xc1\x2c\x52\xa6\xe1\xcc\x06\xcf\x5a\xbf\xc0\xa4\x42\xe7\xcf\x14\x5c\x15\x42\xb9\xb1\x35\x04\x96\x65\x71\x10\x35\xe3\xc2\x9a\x91\xd4\xfd\xae\xd6\x12\x70\x57\xa8\x12\xc2\x2c\xd7\x5a\xd1\x87\x9b\xe1\xd2\xc6\x11\x0e\x79\xe9\x87\x52\x4e\x4e\x8f\x27\xf1\x6e\xda\x90\xcb\xd4\x73\x3f\x11\x18\x25\xb5\x16\xd1\x06\x7f\x81\xec\xa5\xe6\x94\x85\x76\xd5\xbf\xed\xb3\x27\x7c\x1a\xbc\x1e\x60\xf3\x74\xd0\x70\x1b\x32\xcc\xfd\x6a\x5e\x9c\x8d\x16\x59\xaa\xf3\xd0\x81\x86\x13\x61\x3b\x7e\x28\x8d\x84\x5e\x9a\xaa\xba\x2e\x3e\x9b\x41\x1d\x50\x1d\xff\xe8\x56\xfd\x31\x3e\x9f\xcc\x9e\x74\x30\xb9\x98\x3f\x20\xab\x4e\xbf\x4e\xb6\x16\xbd\x63\xe2\xc5\x77\x43\x65\x89\x95\xed\x0a\x14\x9a\xe6\x20\xa3\x95\x61\x37\x19\xb3\xed\x7c\xed\x45\x88\xd5\x91\x5d\x70\xa2\xf0\xc6\x87\x68\x0e\xc3\x4f\xe3\xe9\xf7\x23\x92\xe1\x89\xe1\x3a\x47\x49\xd5\xca\x9f\xac\x65\x1b\x92\xc0\x84\xc4\x06\x6f\xdf\x98\xa8\x69\x22\x3e\x4e\x0c\x9b\xec\x58\x12\xb5\xc1\x90\x0e\x6e\x60\xd3\xa1\x88\xd4\x8a\x74\xdf\xd4\x15\xb5\xca\xd2\xe9\x1f\xf7\x6d\xf7\x50\x89\xd2\x0a\x75\x5f\x26\x07\x56\xc8\xf1\x38\x2a\x29\xf7\xb9\x37\x26\xe7\x31\x07\x1c\xd4\x77\x45\x8c\x6f\x20\x22\xdf\xad\x7d\x4f\xc7\xab\x23\x80\x54\x18\x64\xf6\xb5\x87\x74\xf9\xae\x8e\x5f\x07\x7c\x1a\x8d\xa0\x73\xc3\x98\x53\xeb\x2f\xd4\x77\x22\x0b\x45\xa3\xd9\x22\x63\xdc\x7e\x14\xd3\xbb\x2b\x36\xfc\xa4\x66\xc7\xef\x8a\x24\x75\x38\x72\x5f\x2f\xce\x5c\x72\x21\xbc\x75\x1c\xde\x13\x94\x60\x4f\x59\x31\xd7\x33\x36\x0c\xcd\x47\xce\x08\x77\x12\x95\x81\x80\xad\x84\xfa\xe7\x13\xb5\x43\xf0\x5e\xef\x6a\xbc\x06\x61\x43\x31\x21\xed\x3b\x45\x06\xa1\x46\x50\x25\x31\x6f\xb8\xf9\xd6\x45\x35\xcc\x45\x38\xac\xd4\x06\x4d\xd5\x76\xb0\x74\x0e\x1b\xeb\x13\xbc\xea\xf1\x55\x54\x3d\xc8\x90\x97\xca\x5c\xa1\xcf\xfa\x0a\xd6\x5a\x10\xbc\xb7\x59\x35\x4e\xab\x8a\x42\xde\x73\x4a\xf9\x09\xc2\xfe\xba\x38\x0d\x66\x40\x9f\x32\x5d\x5f\x17\xaf\x9c\xa7\xf8\xcb\x41\x34\xfd\x6a\x2b\x6a\x52\x8d\x9e\x60\xd9\x61\x2b\x8e\x8b\x40\x62\xf8\xe0\xfa\xd1\xe7\xee\xb9\xcb\xfe\xf6\xe9\x73\x8e\xc7\x97\x3e\x1c\xb2\xba\x23\x27\xde\xca\x4e\xa4\x65\x68\xf3\x1e\x12\xf7\x30\xe2\x47\xc1\xd0\x70\x29\xfd\x44\x22\xb2\x98\xff\x23\x98\x02\x3b\x41\x20\xa3\xa4\x25\xff\xb6\x52\x88\x0c\x19\xea\x69\xf3\x63\x9e\x0f\x6d\xf4\xf0\x08\x76\xcc\x45\x28\xe2\x67\xe8\x1d\x59\x43\x19\x9d\x0f\xeb\x6c\xb4\xe1\xba\xf4\x04\xbb\x6f\x8b\x39\xb1\x2d\xbc\xe9\xfd\xc3\x5d\xc1\x58\x06\x6e\x99\x75\xae\x5b\xd3\xb5\x5f\x2a\x41\xa7\x91\xba\xf3\xe8\x35\x1e\xc6\x04\x94\x47\x90\xa2\x2c\x93\x3c\x80\xb1\x59\x0b\xa1\x97\xa4\x70\x6f\x7f\x51\x28\x68\x2e\xdc\xd7\x4d\xd7\x8d\x43\x5e\x78\x7c\x2b\x76\xa5\x7b\x3f\x4e\x7d\x7b\xe2\xef\xd2\x6d\xa5\xf9\xa8\x29\x11\x9b\x01\x50\x8b\x70\x72\xc7\x69\x9c\xe5\x2b\xb5\x78\xcc\x5b\x1b\x93\x66\x1b\x51\x72\xfb\x84\xda\xf1\xba\x36\x4d\x2c\xbd\x80\xe2\xc9\x9b\xca\x9c\xae\xa8\x73\xcc\x0a\x16\x29\xea\xc3\x84\xe9\xb2\x06\x84\x2a\x6e\x61\x83\x38\x75\x91\xb4\xaa\x34\xa9\x5f\xd8\x9b\x49\xd8\xd1\x5d\x91\xe2\x19\x40\xe1\x7d\xca\xf1\xef\xf8\xa0\xa4\x7a\x0d\x7a\x95\xda\xea\xd8\x2a\xa3\xdf\x82\x04\xa0\xcd\x20\x69\x24\xae\x51\x0f\xec\x8a\x9c\x4e\x8d\x85\xd4\x66\xfd\xb4\xdd\x36\x5d\xc9\x93\x36\xb2\x2c\xe0\xb9\x56\xb5\xee\x00\x17\xf2\x9d\x25\xee\x66\xfb\xdc\xec\xb0\xd9\x96\xff\xb9\x7c\x8d\xef\xde\x40\xa9\xff\x99\x93\x19\x3c\xa8\xf1\x68\x50\x67\xc1\x9c\x52\x6e\x0e\xfe\xd2\x36\xf8\xed\xb8\xde\xf6\xc2\xa0\x3e\x21\x95\x2c\x86\x12\xd6\x24\xe6\x88\x6a\x31\x1f\xfb\x9e\x2f\x15\xda\x44\xab\xe1\x80\xd2\x6a\x14\xb1\x5f\x63\x56\x1e\x09\x7a\x73\x0e\xca\xbb\x79\x2c\x7c\x23\x5f\xdd\x36\x0f\x57\x1f\x27\xef\x68\x67\x7a\x7d\x63\xbe\xb4\x97\x59\x82\xcb\x19\x9a\x56\x0f\x81\x6e\xe1\x29\x89\x44\x5f\x7f\x75\xb8\x3e\xb2\x78\xd6\x28\x25\x94\x7d\x84\x09\x9a\xf2\xa6\xff\x2e\xad\xbb\xf5\x89\xb5\xeb\x2f\x72\xed\x11\x4c\x73\x15\x11\x53\xae\x00\x22\xbc\x95\x64\xd1\x5c\x2d\x5c\xdb\xba\xab\xbe\xf6\x38\xf0\x30\x95\xf5\x3e\xeb\xac\x96\x83\x40\x9a\xd3\x06\x0c\xfb\x7c\x70\x37\xb9\xb0\xbe\xfe\x06\x9c\x92\xa0\x2b\xe9\x53\x38\x8e\x9e\xa4\x5d\x36\xdd\xf4\xf5\xa8\x38\x94\x32\xcc\xf5\x04\xc5\x08\x08\xb0\x7f\x69"}, -{{0x90,0x3f,0x3b,0x53,0x99,0x89,0x2e,0x29,0xcc,0xfa,0xfb,0xaf,0xbd,0x7c,0xc4,0x53,0x3c,0x15,0x4a,0x62,0x56,0x82,0x40,0x6c,0x89,0xbf,0x89,0x4c,0x88,0x9e,0x43,0xf4,},{0x8f,0xa5,0xff,0x5b,0x6b,0x26,0xbd,0x67,0xdf,0x86,0x40,0x46,0x42,0x9d,0xf1,0x24,0xb5,0x23,0x00,0x5d,0xd8,0x94,0x44,0x27,0x5c,0x8a,0xb7,0xeb,0xdd,0xb6,0xf4,0xdb,},{0x49,0x5a,0x8f,0x99,0x19,0x41,0xc6,0x29,0xbd,0x64,0x1a,0x67,0x47,0x1a,0xb8,0x60,0xbf,0xd3,0x9b,0x72,0xf2,0x33,0x55,0xf7,0x27,0x09,0x09,0xd5,0x30,0x7c,0x77,0xb1,0xb9,0x4b,0xae,0x3e,0xd1,0x94,0x50,0x78,0x0e,0x90,0x85,0x30,0x5f,0x31,0xb1,0xe1,0x68,0x3f,0xac,0xf0,0xd1,0xfc,0x88,0x40,0xae,0xc7,0x7d,0xf6,0x7a,0xea,0xb3,0x02,},"\xa2\xc1\x1b\x5f\xb8\x84\xa8\x22\xfa\xe6\x4d\xa8\xdc\xb4\x45\x2c\xfd\x7a\x04\xca\x6d\x7a\x5a\xbc\x8d\x82\x71\xe9\x3f\x93\x44\x9e\x1f\xeb\x8e\x02\x97\x5f\x49\x6b\x90\x34\x40\x0d\x35\x99\xab\x97\xaa\x39\x97\xda\xd1\xc9\xff\xab\x5b\x9f\x8d\xf4\xaa\xa5\xb8\x40\xd9\x0d\x86\x2f\xff\x7f\xf0\xcf\x73\xa6\x0c\x66\x15\x00\x09\xe0\x1c\x93\x7b\xd1\xaf\x68\x07\xb5\xba\x2e\xf6\x12\xee\x13\xd6\xde\xf4\x0b\xb0\x9c\x46\x81\x1a\x2d\x4e\x46\x8e\x03\x8b\x32\x30\x55\xf9\xdf\xbd\x01\x82\x9a\xe2\xf1\xa5\x35\xef\x02\x95\xca\x1e\xd1\x76\xe4\x6d\xe9\x96\xcc\x87\xba\xce\x45\x35\x62\x33\x21\x18\x35\xb6\xf4\x75\x7c\x99\xbd\x52\x7e\x76\x6a\x5f\x0b\x12\x7c\x8c\xff\x8e\x6d\x66\xf8\xba\xb8\x6d\x00\x00\x45\x2c\xd7\xf6\x7b\xe5\x57\x78\x85\x13\xec\x07\x09\xb5\x37\xb0\x07\xb4\x20\x16\xe7\xa8\x96\x83\x46\x9b\xd8\xff\x8d\x21\xeb\x10\xc1\x49\x17\xd4\x7f\x2d\xc4\xf8\x26\x32\x4f\x7c\x01\xb2\x4f\x8d\xcf\xf0\x4a\xa6\xd8\x50\x95\xd9\xab\x15\x4b\xa5\xc3\xbd\x91\x9c\x9d\x72\x8d\xbd\xc9\x90\xd1\x9c\xeb\x23\x7b\x45\x29\x07\xbd\xbe\x21\xf9\xf0\x8c\xdd\xae\x5b\xe4\x79\x27\x67\x09\xb8\xae\x73\xf8\x97\x4c\x4b\x11\x38\x41\xad\x53\x5d\x6f\xf6\x22\x3e\xea\x47\xd1\x85\xc8\xe8\xa6\x5f\xde\xe2\xc2\xd4\x58\x00\xc1\x7c\xb5\x56\xea\xfd\x67\x66\x47\xd9\x96\x8e\x55\xca\x9c\x59\x23\x2b\x97\x70\xad\x10\xf9\x55\xfc\xb5\x85\x8e\xdf\x0b\x74\x83\xad\xc1\x81\x7c\x0f\x8d\x02\x24\x04\x82\xca\xa7\x6f\x43\xc6\xd2\xe9\x6a\x4f\xf9\x59\x1c\xd7\xb8\x78\xea\x61\x9e\xa5\x6d\x1b\x58\x86\x31\xe7\x63\x3c\x5e\xcb\x2b\xa6\x99\x83\x98\xcb\x06\xe3\xcf\x75\xae\xb3\xe0\x8d\xab\x19\x63\x2d\x45\x4f\xf7\xdc\x0e\x2a\x41\xf0\x97\x37\xe8\xee\x82\x3d\x1b\x9e\x24\xdd\xa8\x4a\x2c\xe0\x31\x3c\xb9\xfc\xe3\x1c\xb6\x63\xc5\x5c\x05\x64\x5e\x63\x40\x17\x56\xe8\xad\x38\xf5\x17\x4c\x02\xa6\x63\xd8\x15\xad\x64\x42\x2f\xf7\x72\x7d\x4f\xda\x16\xe4\x8d\x4b\xf8\xf6\x60\x2e\x72\x60\xda\x62\x33\x0e\x68\x78\xc3\x47\x64\xe1\x29\xaf\xbd\x55\x22\x08\xf6\xbe\xd4\xf7\xce\xe9\xb6\x71\xf4\x88\x38\x88\x15\xd7\x4b\x49\x51\xb8\x68\x2c\xe7\x6c\xfe\x31\xe9\x38\xc4\x70\xb8\xf7\xa4\x5f\xd6\x3a\x96\x91\xf4\x26\xa7\x5c\x58\xed\x3d\xbc\xe3\xae\x8f\xd9\xd1\x0a\x83\x52\xe4\x7c\xc1\xb1\x2c\x91\x92\xac\x86\x26\xd1\xb3\x84\xb7\x7a\x18\xb9\x86\xe7\x1a\x99\x86\x46\xc1\x37\x99\x2b\x67\xc4\x81\x7e\x34\x63\x45\xfa\xf5\x0a\x26\x59\xfd\xc5\xca\xd5\xc7\x19\x64\x8e\xfe\xe3\x84\x7c\x0f\xf6\xbd\x70\x95\xc2\x8b\x4c\x51\x95\x96\x7c\x90\xcf\x84\xe1\xef\x68\xa1\xad\xa0\x1f\x62\x74\xed\xe3\x63\xfb\x82\xe0\xb5\x49\xa8\x70\x24\x5d\x60\x8c\xae\x82\x34\xf6\xd8\x4a\xbe\xb6\x1b\x71\x84\x66\x09\x36\x20\xd8\x5c\x58\x4a\xb0\x1e\xed\xa0\x91\xee\x8a\xff\x1c\xf6\x7a\x46\x75\x67\x9a\x1f\x40\x03\xe6\x6a\xaf\x43\x87\x1b\x88\xec\xda\x6a\x16\xdc\x5a\xcb\x05\x39\x5f\x2d\xa9\xdf\x70\xd3\xbd\xb6\x14\x38\xe1\xc3\xd4\x09\x81\xe0\x34\x62\x7d\x02\x6e\xe1\xd2\xe7\x9f\x65\xcb\xb8\x18\x9f\xcb\xb3\xcc\x8b\x5c\x2e\x7e\x79\x6b\x5d\x28\x89\x41\x1d\x56\x41\xfb\x86\x9c\x7b\x0a\x58\x9c\x43\x25\x4f\x8c\x54\x38\xaa\xf5\xac\x42\x38\x32\xf0\x18\xd7\x9a\x51\xb9\x6f\x24\x2e\x2d\xe0\xc8\x51\xcc\x5f\xc2\xb2\x06\xbc\xa4\xb5\xbe\x83\x61\x25\xac\xa1\x44\xbb\xc3\x8c\x8c\x63\x8b\xe0\xd3\xbb\xe0\x25\xa1\xbe\x8b\x3d\x03\xd5\x92\x9b\xaa\x64\x9c\x35\x44\xa3\x2a\x91\x5e\x92\x6a\x38\x79\x1b\x13\x4a\x97\x1b\xc5\x2d\x1b\x6c\xa6\x25\xef\xb7\xc2\xf3\xbb\x47\xab\x51\xd4\x3c\x8e\x37\x4d\x16\xcd\xa8\x82\x20\x4b\x71\xca\xfe\x90\x93\xcb\x60\x78\xef\x2b\xdf\xad\x59\xed\xea\xf3\x6d\x0c\x1a\x4d\xc4\x25\xb9\xe7\x18\xc4\x51\x85\x22\x5a\x9c\x30\x84\xb7\x82\xbf\xe1\x63\x49\x2f\x8e\x84\x82\xec\x9a\xa0\x73\xf6\x90\x1f\xf3\xd1\x11\x7c\xe9\x17\xe1\x91\x22\xfa\x67\x65\x0d\x85\x8f\x8f\x82\xb3\x76\x69\x72\x3c\x22\x6d\x72\x16\x97\xe7\xae\x33\x59\xf5\xa6\xb0\x24\x24\xee\x87\x94\xcb\xea\xa6\x41\xed\xbb\xf7\x53\xb1\x03\xa5\xfe\x15\x8b\xe0\xba\x60\xd8\xa2\x12\xd4\x2f\x8c\x5c\x2a\xf2\x54\xbf\x1b\x9c\x80\xdf\x6f\x1c\xf0\x9d\x70\x79\x3c\xae\x1a\xbb\x46\x27\xb1\x78\x0f\x1b\xce\x7f\x61\x7e\xe5\x0f\x6b\xd4\xb0\x83\xb2\xfc\x7c\xd8\x44\xaf\xb7\x23\x80\xd5\xcb\x6b\x25\x5b\xf4\x7e\xa7\x1c\xad\x6c\x6c\x4d\xf0\x21\xf8\x1b\x54\x8f\x43\x2c\x18\xac\x36\x6c\x6a\xec\xd0\x3b\x6c\x8c\xe2"}, -{{0xee,0x81,0xe0,0xfb,0x05,0x2e,0x23,0xad,0x75,0x9d,0xe6,0xaa,0x98,0x38,0xde,0x98,0xe3,0x6d,0x48,0x20,0xdc,0x0e,0x1b,0x7b,0x3e,0xf1,0x14,0x1a,0xb9,0xde,0x33,0x40,},{0x98,0xf3,0xc9,0x88,0x07,0x94,0xde,0x64,0xfa,0x26,0x9b,0xdf,0x33,0x60,0x95,0xe0,0xe0,0x1b,0x1a,0x3b,0x37,0x5f,0x96,0x5b,0x93,0x70,0x0b,0xbd,0xf4,0xb9,0x68,0x69,},{0xf0,0xd8,0x73,0xbe,0x15,0xcf,0x45,0x4c,0x74,0x34,0xde,0xab,0x71,0xde,0x25,0xcf,0xe9,0x9e,0x81,0xa4,0x8d,0x2d,0xce,0x6a,0x35,0xd1,0x63,0x37,0x14,0xdf,0x0f,0x8b,0x40,0x29,0xe0,0x58,0x25,0x11,0xef,0xc4,0xd0,0x68,0x92,0xf6,0x72,0x85,0x02,0x46,0xbc,0xf0,0x70,0xc4,0x6f,0xad,0xc2,0xfa,0xab,0x44,0xdc,0x43,0x50,0x45,0xde,0x00,},"\x28\xd9\x9e\x95\x18\xb8\x82\x83\xc2\x20\xe7\x6d\xe2\x05\xd7\xb6\x16\x23\x59\xb1\xdf\xec\x1f\xba\xab\x98\xec\x0e\xf1\xdf\x8d\xa4\x0b\x6b\x7a\x77\x5e\x97\x28\x45\x0a\xeb\x23\x51\xfe\x5c\x16\xaf\xda\x3a\xec\x0d\x71\x04\x9d\xa4\xcb\x7d\x4c\x63\x71\x3a\x24\x10\xab\xb0\x22\xf8\x16\x11\xcc\x06\x45\x87\xc8\x04\x7d\x43\x83\xc0\x0c\x3c\x56\x2e\x9c\xee\xa3\x57\x75\x09\x53\x91\xb5\xf3\xdd\xa0\xe3\x73\xc4\xa7\x7f\xf6\x18\xa2\x8e\xf6\x87\x87\xeb\xfc\x3e\xbc\xcc\xc5\xd1\xce\x32\xdd\xf4\x3b\xfc\xe5\x72\x03\xda\x76\xa8\x66\x4b\x3c\x61\x6a\x88\x69\x28\x2d\xb0\xb7\x28\x11\xb5\xfd\x5a\x2a\x03\xa4\xff\x66\x72\x4b\x04\x89\xea\x2e\x10\x73\xd7\x81\xc3\xf1\x89\x11\x5d\x79\xba\x20\xa4\x6d\x1d\xfa\xf5\xb1\xa5\x84\x7b\x2a\x2e\x31\xb2\x80\x87\x37\x56\x9e\x60\xb5\x72\x31\xe6\xa9\x9a\xf2\x6f\x58\xaf\xeb\x15\x77\x08\x10\x47\x48\x12\xfe\x4a\xfa\xcf\x88\x45\x06\xb8\xc3\x14\xbc\x67\x51\xbb\x42\xb4\xbd\x6e\x87\xd2\xe5\xde\x70\xfe\xc5\xf0\x01\x4c\x42\x57\xb1\x34\x72\xa3\xb0\x11\x1a\x7a\x8c\xf8\x3b\x1d\xc0\xcf\x96\x20\x22\xcd\x44\x46\x8a\x3a\xb1\xf0\x01\x6b\x70\xca\xfb\x1d\x02\x46\xac\xd7\x05\x39\x37\xc9\xac\x40\x20\x7c\xf1\x3b\x50\xdd\x15\xe2\xa2\xe1\x5f\x50\xa0\x5b\xca\x2f\x28\xe7\x70\x26\x23\x71\xda\xce\xe0\x2e\x25\xb2\xa5\x96\x58\xed\x90\xc0\x60\x0f\xa2\x65\xb7\xde\x3d\x44\xf8\xef\x07\x21\xbf\x39\xec\x4d\x4e\xca\x58\x88\x52\x7b\x77\x80\x67\xb1\xd6\x59\xc0\x05\x14\xc8\xd7\x05\x62\x73\xa2\x94\xcb\xaf\xe4\x50\x90\xd0\x69\xbb\xd0\x9f\x92\xf4\x61\xe6\x48\xf3\xe6\x82\x88\x2c\x71\x57\x6e\x97\x4d\xeb\xb0\xcb\x7e\x0e\x83\x16\x40\x66\x60\x15\x0d\xab\xb5\x8e\x76\x24\x66\x14\xa2\x91\xc1\x2c\xe9\xe0\x34\x6c\x02\x77\x4d\x4d\x09\xce\xcc\x23\x69\x67\x12\xfe\xe2\x50\xc0\xbb\x5d\xf7\xa2\xa4\xc4\x3a\x55\x63\x33\x1b\xcb\xbf\x84\xbe\x3f\x2e\xeb\x06\x54\x53\x2e\x85\xec\x59\x7b\x53\xb3\x2f\x39\x54\xcc\xaf\x0c\xd4\x26\xde\xf9\x1e\xc4\xb2\x08\x41\x69\x48\xaf\x27\xde\x04\xd8\x32\x70\x58\x97\xa0\x4c\x5e\x24\xa2\xe8\x8b\x20\x04\x0f\xd4\xec\xa3\x08\x9f\xdb\x91\x8a\x92\xe3\x5c\x4d\x31\xda\x26\x85\x0b\x9d\xd3\x41\x18\xc7\x44\x49\xa8\x55\xff\x4b\xc9\xff\xf0\xd1\x44\x78\x39\x65\x4b\x00\x41\x79\x99\xfa\x4e\xb8\x91\x02\x13\x3c\xd3\x20\x40\x91\x53\x58\x49\x57\xc1\x04\x89\xdb\x4b\x72\x44\xc9\x59\x07\x98\x8e\x83\xdc\x82\x12\x71\xdc\x1a\xb6\x43\xd6\x99\x2d\x0f\xd8\x20\x49\x2a\xe6\x42\xe2\x4d\x19\xa1\x79\xfa\x75\xd9\x36\x3b\x32\x16\x62\x60\x6f\xd9\x4a\x47\xfd\xb2\xe6\x8d\x3f\x30\xc0\x46\x73\xf8\x09\xde\x01\x44\x94\x5e\xa4\xd4\x18\x3d\x48\xf1\x75\x07\x9e\xed\x50\x32\x3c\x6b\x19\x2e\x02\x0e\x16\x2a\x35\x03\xaa\x58\x2f\xb0\x8b\x40\x36\x24\xa2\x3e\x35\x7e\xed\xa0\x8d\x90\x43\x86\xf3\x58\xc3\x6c\x64\xd3\x14\xc7\x7c\xd9\xd4\xd2\x3d\x58\x1e\xe5\x3d\x81\xff\x97\xad\xa0\x19\xcf\xcf\x04\xeb\x9d\xcc\x1d\xe9\xb7\x4c\x3d\xb6\xb8\x11\x57\x8b\xd4\xf2\x19\xc5\xca\x48\xef\x4c\x82\x6b\x09\xe6\xc9\x6d\x03\x1f\x65\xdd\x48\xb6\xe7\x3d\x0c\x10\x05\x86\xb2\x1d\xf0\x29\x3a\x03\xd2\xed\x7e\x50\x09\xad\x02\x53\x40\xc2\x1d\x09\x06\x06\x91\xf5\xcd\x8a\xf2\xab\x12\xf9\xb8\x60\xee\x87\x81\x5e\x1a\x9f\x40\x0c\x2a\x6f\x63\x4e\xa8\xf9\xb3\x42\x5a\x08\xd1\x0b\x3c\x81\x53\x67\x38\x8f\x4d\x1b\xe3\x56\x31\x8e\xcf\x90\x35\xd0\xee\x97\x5a\xff\xa8\x59\xca\xac\x28\xeb\xcc\xd0\x59\x9b\xb2\xf6\xf3\x52\x36\x61\xbd\x17\x8f\xc9\xe4\xca\xc3\x78\xbb\x9d\xd4\x71\x6b\xb0\x69\x23\xfd\x2b\xbd\x56\xc9\x59\xc4\x2b\x95\xd5\x01\x93\xf8\xbf\x29\x9f\xcc\xa3\xb2\xee\xa9\x4e\xc5\xf9\x85\x83\x92\x4c\x08\x04\x16\xe2\x8b\x54\xfe\x57\x65\x84\x58\xb0\x55\xce\x4d\xe8\xa7\x5f\xc8\x27\x15\xca\xe9\x1d\x37\x5c\xf6\x92\x81\x37\x80\x51\xbb\x61\xfd\xd7\xbb\x00\x68\xf6\x3e\xfa\x6d\x6e\x83\xd8\xfd\x42\x57\xaf\x80\x97\x0f\x4a\x9e\x69\x24\xb2\xde\x0a\xd9\x66\xdf\xfe\x6f\xa4\xa1\x13\xb0\xe7\x72\xf1\x76\x87\x85\xb3\xb4\x20\x49\xf7\x6c\x48\xad\x80\xf2\xc6\x7f\xb0\xf9\x1a\x5f\xc4\x10\x79\x12\x52\x0d\x8d\x68\x3c\x06\x2c\x3a\x22\x2b\xcd\xa7\xe7\x10\xba\xcd\x47\x8e\xe8\x83\x67\xb6\xa0\x59\xa4\x52\xfd\x26\xf1\x14\xa5\xac\xbd\x69\x79\xba\x01\x9f\x7d\xa6\x8a\xc0\x4a\x19\x30\x26\xbc\x1c\x27\xe4\x83\x7b\x1d\xe2\x9c\xce\x09\x0e\x33\x80\xd5\x05\x1a\x58\x64\x09\xe6\x28\xe3\x14\x56\x65\xbb\x1d\x84\xec\xd8"}, -{{0x69,0xd0,0x1d,0x82,0x91,0x13,0x08,0x1c,0xbf,0x5d,0x0c,0x6e,0xf7,0x7b,0x21,0x77,0x5c,0x8d,0x9b,0x68,0x00,0x00,0x05,0x6f,0x03,0xc7,0x5a,0x7d,0x0a,0x05,0x87,0xd2,},{0xee,0x84,0x69,0xdd,0x61,0xcf,0x5d,0xe4,0x00,0xda,0x7d,0x7a,0x47,0x9a,0x44,0x18,0xe6,0x77,0x2e,0x69,0xff,0x53,0x30,0xce,0x5c,0xa7,0x78,0x59,0xfe,0x27,0x17,0x55,},{0x40,0x8c,0xef,0xcf,0x01,0x41,0x7e,0x2d,0xc6,0xa8,0xa1,0x82,0x84,0xe4,0x11,0x65,0x7f,0x03,0x92,0x50,0xc3,0x12,0x78,0xdb,0x28,0x19,0xf9,0xea,0xea,0x42,0x93,0xfb,0xf6,0x83,0x1a,0x28,0x01,0xfc,0x1e,0xa6,0x87,0x16,0x57,0xb8,0x41,0xe1,0x73,0xf4,0x51,0xb0,0xd5,0x75,0xa9,0x37,0x9e,0x35,0x85,0x7e,0x8c,0x72,0x97,0xfa,0x14,0x04,},"\x0b\x9e\x11\x0f\x29\xd1\x98\x16\xa1\x7b\x2c\x75\x47\x8f\x13\xce\xe9\x53\x81\x1a\x19\x83\x01\x4c\xb7\xeb\x0f\x75\x52\x69\x12\x04\x4c\x3e\xa6\x82\x97\x80\xe6\x57\xf8\x17\xc5\x59\x7d\x46\x61\x08\x0d\x90\x34\xc9\x77\x87\x22\x41\x8f\x2c\x3a\xee\xca\xef\x6b\x69\x0c\x5b\xd3\xb5\x93\x70\x10\x86\x98\x8e\x43\x40\xae\xc3\x4e\x01\x72\x75\x8e\xb2\x40\x87\xd0\x3a\x8f\x76\xe7\xcb\xca\x53\xaa\xaf\xc4\xd2\x15\x5c\x75\x32\xab\x54\xbe\x48\x87\x26\x53\x06\x6f\xa1\xfd\xd5\x4a\xcf\xe9\xda\xae\xca\x35\x6c\x29\x0e\x6b\xe6\x33\x55\xb6\xd9\xfc\x52\xeb\x5e\x4f\xcc\xbb\xc6\x08\x35\x07\x13\x2d\xe4\x85\xbf\xae\x9f\x42\xe1\x97\x12\x23\x2b\x71\x64\x02\xc2\x3f\xea\x74\xef\xa6\x9d\x73\xc8\xc2\xe3\xa8\x66\x2b\x8b\x65\xb0\xfd\x00\x77\x41\x01\x3e\x1f\x6e\x3c\xfe\x43\x45\xd5\xc8\x30\x68\x2f\xe6\x00\x21\xd7\x08\xe1\x0a\x9e\x9f\x40\x52\xff\x7a\x6a\xbf\x28\xac\xb1\xd6\xb5\xfb\x03\x8e\xed\x3f\x72\x51\x3c\x35\x5b\xbf\xd5\xc2\x27\x4f\xa8\x5f\xc4\xf4\x46\x97\x4b\x2d\x1b\xc0\x36\x50\x7a\x1e\xb5\xfc\xf5\x5d\xbd\x44\x21\x0e\x53\x82\x74\xde\x80\x8b\x90\x0b\xf1\xc0\xfc\xc0\x24\x12\x70\xdb\x8d\xbd\xcd\x88\x34\x9d\x67\x22\x4f\x08\x7e\x5f\x07\xf6\x99\xb0\xba\xe6\x8b\x2e\xbc\x9a\x4e\x27\xc7\x0d\x3a\xc7\xd9\x96\xfa\x7d\x4d\xab\xd5\x68\x37\x8e\x3f\x93\x90\x5b\x1c\x89\xc6\x52\xd3\x84\xc1\x6c\x2b\xcb\x1c\x98\x44\xc3\x8f\x71\xbb\x13\xe0\xc6\xa2\xea\x95\xb6\x12\xe3\x90\xc5\xf8\x6d\x24\x8e\xa5\x31\xf2\xec\x6f\x63\x9a\x40\x2d\xfa\xcc\xf3\x72\x17\x00\x53\x44\x03\x07\x45\xd1\xf1\xe5\x20\xcc\x19\x5d\xaf\xdd\x7f\x29\x5f\x37\x7b\x8d\x61\x47\x16\x70\x38\x36\x21\x9b\xb7\xb0\x9f\xea\x7a\xae\x9a\xc3\x3e\x42\xdc\xab\x65\xcc\x61\x42\xfc\xd8\xce\x15\xe9\x77\x17\xfd\xb3\x3e\x95\x38\xc4\x4f\x6c\xd9\xc1\xc6\x5d\xb6\x27\x51\xf5\x52\xf8\x70\xf1\x01\x42\xc9\x6f\x9d\xf1\x85\x5a\xbb\x39\xe4\x27\x06\xa5\x63\xab\x15\x45\x11\xfd\xce\x68\x7c\x95\x76\xf9\xed\xc3\xb4\xba\x55\x34\x6c\xe6\x68\x02\xff\xfe\xf4\xb1\xb5\xe1\x20\x15\xce\x8b\x57\xde\x54\x58\xca\xa0\xda\xf3\x41\x96\x81\x28\x58\x42\x88\xc2\xf2\x7c\xbf\xb7\x6e\xab\x28\x6b\xac\x5f\x66\xaa\xd0\x04\x9e\x0c\xa6\x0a\x90\x14\xe1\x79\x01\xc4\x13\x0e\x83\xce\xae\xb4\xc2\x71\x3e\x97\x1a\x23\x5e\xff\x99\x5a\x81\x3a\xe4\xea\x64\xa5\x83\xff\xde\xfd\xac\x82\xac\x76\xea\xf4\xd4\x7c\x4a\xc8\x25\x0f\xcb\xaf\xd6\xb8\x8f\xae\xb4\x80\x15\xf5\xb4\x2b\x53\x34\xa5\x0b\x31\xd4\x50\x2e\xa4\x91\xda\x90\xdc\xe9\x3c\x08\xfd\x56\xf5\xc5\x8e\xed\xb3\x79\x16\x6a\x23\x76\x2b\xe5\xe4\xad\xea\xa6\xf4\xae\x1c\x24\xe0\xca\xc4\xdd\xca\x03\x83\x45\x85\x60\xcd\xc4\x8b\x8c\xd1\xf4\x2a\x3b\xa2\xf6\xff\xb6\x07\x79\x09\xfc\xb2\x94\xad\x1e\xf4\xa4\x4c\x22\xec\x4b\x39\x87\xdd\xbe\xef\x32\x5b\x98\xce\xd5\x68\x15\xea\x7d\x5f\xcc\xf5\xaf\xdf\xe9\x8e\x0e\x6d\x92\x0f\x7a\xda\x2e\xb5\xc9\x16\x24\xc7\x6c\xbb\xa2\x99\x3a\x9c\x7a\x55\x02\x1d\x12\x7a\x66\x7b\x39\xe2\x35\xdf\x4f\x81\xde\xe7\xdd\x14\x28\x98\x77\x8d\xbd\x92\x13\x5b\x70\xb3\xac\xf5\x9f\x6c\x29\xa2\xc9\xd4\xa7\x00\x6e\xf1\x1a\x91\x8b\x3a\x29\x06\x26\x4a\x15\xd6\xb5\x29\x30\x8c\xbc\x89\xf8\x56\x01\xfc\x1e\xa1\x31\x4d\x67\xf7\x56\x6c\xf1\x09\x16\x5c\x7f\x92\xde\x1a\x18\xd7\x0d\xeb\xe0\x24\x34\x9d\xb3\x56\x0a\x6e\x52\x7e\x2a\xc3\xe0\x67\x89\x46\x87\x04\xe6\xb8\xf1\x87\x1f\x16\xba\xe9\x82\x73\x92\xb4\x18\xf1\x08\x6c\xc4\x97\x08\x6c\xed\x14\xb1\x24\x9d\x6d\x87\x94\xf2\x3b\xb8\x77\x9d\x41\x86\x48\xf2\x15\x56\x56\xa6\xfd\xa7\x44\x0c\x56\x28\x4d\x9b\x21\x88\xfa\x7d\x17\x36\xbc\xcc\x9c\xff\x0b\xe5\xb1\xe1\xf5\x51\xff\x81\x37\xff\x59\x66\xed\x9d\x0f\x7f\x01\xc3\xdf\xf2\x98\xe9\x10\x2f\xfb\xd3\x24\xbf\xca\x5f\xfe\x09\x68\xe6\x6f\x9d\x82\xf4\x87\xd3\x03\x93\x4f\x27\xf7\x8b\x28\x37\x8e\xb7\x2c\x38\x27\x29\x62\xa5\xf7\x35\xd7\x39\x2e\x5d\x33\x3f\xd8\x6d\xe1\x67\x26\x9c\x17\xa1\x65\xb9\x2d\x31\xa4\x88\x0a\x41\xe1\x36\xf7\x18\x96\x0a\x91\x9b\x3d\x7c\x4e\x74\xcb\xd7\x3c\x73\xf9\x21\xbe\x51\x3f\x73\x9a\xff\xb2\xe4\x1f\x80\x42\x6b\xb8\xcf\xb4\x56\x4b\x98\xfc\x4d\xe5\x32\x55\xce\x3f\x98\xb4\xd2\x2a\xe6\xfc\xe9\x19\x0b\x55\xbf\x2c\x93\x86\x1c\x1d\xca\xc1\x01\xb5\xe1\x6c\xf0\x99\x91\xc5\xde\xfa\x33\xf8\xd5\x10\x56\xd9\x34\xbb\x4b\x47\x7b\x65\x20\xd4\xc7\xae\x22\xea\x7f\xb3\x10\x9d\xe7\xf4"}, -{{0x4b,0x8e,0xd2,0x97,0x31,0xf1,0x04,0x79,0x5e,0x97,0xde,0xe7,0xc8,0xb4,0x01,0xa0,0x2a,0xfa,0xa9,0xa7,0x95,0xe6,0x13,0x35,0x3d,0x2b,0x95,0x00,0x17,0x65,0x02,0x7a,},{0xf2,0x22,0x98,0x21,0x0b,0x09,0xfd,0x61,0x7f,0xc8,0xb3,0x50,0x74,0xca,0x18,0x01,0xe6,0x07,0x5d,0xc9,0x2a,0x8f,0x50,0x34,0x4b,0x80,0xe8,0x54,0x05,0xa0,0x38,0xf5,},{0x23,0x45,0x88,0x66,0x86,0xeb,0x39,0xb5,0x19,0x9c,0xaa,0xa9,0x61,0x5b,0xc6,0xb4,0x89,0x6f,0x07,0x6e,0x8b,0xd7,0x36,0xc0,0x03,0x8a,0x65,0x17,0xf9,0xc2,0xb1,0x67,0xe7,0x59,0xf3,0x73,0x72,0x26,0x8a,0x69,0x7e,0x9b,0x78,0x60,0x5f,0x2e,0xd9,0x47,0x25,0xf6,0x90,0x5a,0x79,0x00,0x15,0x3f,0xc9,0xe8,0xbe,0xed,0x31,0xff,0xae,0x05,},"\xcb\xb5\xf1\x3a\x0e\xf2\x83\x7b\x80\x5d\x3b\x78\x51\x09\xf9\xf2\xe0\xd0\xa0\x17\xbf\xe7\x69\x2d\x91\xec\x23\xdd\xab\x78\x17\x33\x0b\xef\x24\x7f\xd9\x1a\xb2\xc7\x7d\xd4\x41\x25\x19\xcb\xd3\x84\x75\xce\x0c\xb3\x9b\x14\x80\x09\x2b\xc7\x38\xd4\x15\x2b\x8a\x6d\x55\x24\x8e\x3b\x9f\x32\xcd\xcd\x15\xec\x5d\x05\x9e\xc3\xc8\x84\x75\x54\xee\x47\x00\x53\x94\x97\x4d\x8e\xb2\x35\x92\xd1\x7f\x5a\x39\x6e\x3c\x19\xf8\xe8\x98\x37\x06\x79\xfe\xf5\x31\x8c\x4d\xd2\x99\xc6\x21\x7d\x6a\xbc\xc9\xb6\x1a\x5b\x2d\x0c\xfe\xf6\x95\xd1\x70\xca\x20\xa8\x3d\x6f\xd3\xc6\x66\xc8\xfd\x1c\x10\xad\x97\x0e\x2f\xa6\xaf\x10\xff\x0e\xd0\xcb\xfe\x75\x22\x46\xd0\x3f\x3a\x3c\x60\x32\xdb\xb3\x19\xbc\xfd\xac\x4d\xaf\xc5\x0b\xc3\xe6\xbf\x59\x5f\x49\x1d\xec\x38\x8b\x34\x41\xb8\xce\xe0\xdf\x91\xf5\x5c\xc7\x80\x7d\x07\xf8\xf5\x41\xed\x73\x22\xff\xc3\x9d\x18\xf8\x95\x60\xe4\x12\x3a\xec\x1d\x77\x96\x9c\xf1\x87\x77\x86\xf4\xcf\x94\xb1\x77\x0b\x10\x90\x65\x5e\x8c\x72\xee\xce\xa4\x57\x2e\x46\xf5\x80\xf9\x63\x96\x6d\xb2\xa1\x08\x5e\xea\xbc\x57\xbf\x4a\x84\x72\x4b\x9c\x85\x99\xa4\x33\xab\xf5\x8b\xca\x80\x40\x91\xd3\xd5\xe6\xe5\x04\x8e\xc2\x7b\xf8\x12\x9b\x67\x0c\xc2\xc8\x8d\x9c\xac\x47\x18\x59\xf4\x69\xb9\x18\xf3\xf6\xd7\x0f\x7d\x66\x63\x50\x1f\xfb\xef\xef\x02\x6d\x79\xea\x70\x92\x7c\xcf\x60\x75\xee\x51\x05\x42\x33\x21\xe1\x1a\xee\x9a\xd1\x6f\x98\x7e\xfb\xdd\x00\xb6\x2a\xff\x69\x8e\x52\x1a\xdf\x92\x03\xb1\x5e\x9f\x0f\x3a\xd0\x7d\xca\xd9\xdd\xcc\xaa\xe9\xb4\x90\x24\x7f\x12\xc3\x11\xde\xe6\xb7\x3b\x8f\x91\x24\xfd\xce\x12\x99\xb4\x7f\xb1\x91\x4c\xee\x7e\x3a\x07\x81\x4e\x31\x2c\x3c\xe5\x69\x27\x67\x2c\x51\xb3\x18\x59\x80\xcd\xe5\x7f\x3a\x75\x9b\x50\xbc\xfc\x4c\xb0\x75\x3b\x95\x4d\x97\x13\x5d\xeb\x2a\x05\x32\xe9\x8b\x66\xf3\x9a\x7c\x08\xcf\x4d\x54\x85\x39\xe2\xeb\x9f\x42\x2f\x66\x49\x65\x88\x93\xa7\xc3\xc2\x5a\x4f\xc9\x01\xf8\xc3\x98\xb8\xc7\x27\x33\x91\x1a\x00\x72\xed\x6b\xd2\xf4\x18\x93\x89\xae\x10\xa8\x14\xf6\x48\xd7\x1f\x69\xc3\x7e\x82\x95\x78\x44\x28\x18\x3b\x93\xc8\x01\x3b\x96\x4a\x9f\xef\x86\xb4\x8f\x48\x93\x16\xbc\x22\x2e\x96\xb3\xbd\x15\xff\x14\x9b\x96\x82\x03\x29\x55\x1c\x15\xe0\xd0\x95\xd1\x56\x9b\x1e\x21\x31\xc7\x87\x51\x56\x5c\x30\x41\xf2\x97\x85\x39\x5b\x97\x15\x13\x17\xf6\x2e\x35\x82\xe4\x07\xb1\x64\x9e\x60\xd0\x3a\x85\x99\x12\x0a\x30\x2a\x46\x95\xfa\x86\x2b\x41\x20\xf9\x4d\x22\xec\xae\x72\x39\x8d\x20\x94\xd1\x08\xad\x2d\xbc\x1b\x95\x97\x35\x90\x21\x42\xaa\x5f\xe6\xe7\x99\x65\x59\xf6\xf6\x01\x44\x8a\xea\x02\xf3\x56\xf8\xdc\xdd\x14\x43\x40\xeb\x36\x19\xf9\x86\x5b\xf7\x67\x2a\xea\x32\x6c\x4e\x93\xc9\x9f\x0e\xd1\xf9\xed\x86\x6b\xe1\x5d\x3a\xf2\x67\x5f\x6d\xd6\xe2\x96\x60\x2c\xa3\x73\xa8\x15\xb0\xbe\x46\xbc\x2a\x3f\xbb\xa0\x6b\x88\x05\xc7\x31\xfe\x08\x00\x7d\xaa\x06\x05\x09\x61\xb2\x4d\x14\x69\x3a\x72\x89\x8c\xcf\xb8\xb8\xfe\xdc\x60\xa4\xee\xf8\xff\x79\xb6\xdd\x75\x92\x59\x18\x33\xb5\x76\xef\x48\x29\x4e\x5e\x04\x85\x94\x2e\x57\xc1\x19\x60\x2e\xdd\xf8\x8b\x1f\xae\xa5\x17\xf2\xfc\x2e\x3d\x14\xd2\x46\xa5\x2c\xbd\x71\xa1\x08\xc6\x6b\x6c\xc4\xf2\xd4\x58\x04\xa2\x82\xec\xed\xb1\xb0\xad\x3d\xc3\xb4\x88\x0a\xb2\xff\x78\xb8\xdd\xde\x48\xf7\x46\x6c\x14\xfe\xd3\x49\xe9\x5b\x50\x53\xab\xf1\xbf\x09\x91\x12\x60\x31\xd9\x75\x47\xd1\x43\xc2\xae\x16\x49\x28\xb6\x1c\x07\x08\xaf\x8c\xa3\xe4\xf5\x51\x54\xd1\x3d\x75\xe9\x7d\xb4\xba\x3e\x69\xd3\x6e\x9b\x37\x08\x23\x68\xc2\xf7\x21\xbd\x3f\x95\x12\x6a\x1e\x00\x4e\xb2\xa1\xbf\x26\x83\x43\xae\x21\xd2\x99\x50\x44\xa2\xca\xdd\x67\xff\xac\x9e\x15\x38\x17\x5b\x3c\xc4\x4d\xb5\xd2\x6f\x1d\x5c\xc8\x9c\xa0\xe1\xc1\xee\x85\x37\xa8\xa9\x1d\x32\x4c\x2e\x02\xe1\x8b\x9f\xb9\x73\x0d\x6d\xda\x55\xf7\x2d\x84\x33\x89\x69\x3e\xbf\xcb\xa7\xfb\xe1\xa0\xbc\xff\xb9\xaa\x28\x4f\x4a\xe6\x6f\x44\xa8\xb8\x93\x02\x98\x3b\x22\x73\x6d\x0c\x72\xd6\xa0\x44\xe4\x29\x16\x24\x24\x3a\x4e\x0c\xe6\x5d\x5e\x53\x46\xd6\x7f\xed\x37\x60\xdd\xb0\xc5\x10\xb5\x0f\xf3\xee\xf0\xa1\x8a\x26\x7d\xe7\x30\x47\x6d\xd8\x2d\xff\x70\x72\xcb\xa0\x98\x48\x25\xa0\x04\xdd\x4b\xcd\x8c\x37\xfd\xaf\x1f\x68\x3d\x1d\x93\x80\xe1\x35\xa9\x5d\x24\xb8\x9f\xad\x0b\xe9\x41\xc5\x48\x25\x1b\xec\x90\xcc\xae\x01\x5b\xc0\x56\x7d\xa8\x4b\x37\x1e\x50"}, -{{0x08,0x0d,0x7f,0x76,0x18,0x2e,0xe6,0xbc,0xea,0x89,0x4b,0x1e,0x00,0x60,0x55,0x8b,0x3b,0x12,0x5a,0x34,0x99,0xdf,0x39,0x73,0xb8,0xdd,0x66,0x93,0x40,0x8e,0xe4,0x69,},{0x41,0x24,0x71,0x3d,0x7c,0x2d,0xf5,0x0f,0x93,0x05,0x57,0x30,0xd1,0xb2,0x81,0xda,0xec,0x30,0x28,0xcf,0x2c,0x1e,0x48,0x58,0xd1,0x28,0x70,0x7a,0x23,0xd6,0xde,0xb0,},{0x18,0x5f,0xb1,0xb6,0xd8,0x6d,0xc4,0x44,0x48,0x10,0xcf,0x5e,0xc6,0xfe,0xf0,0xab,0xda,0xfa,0x2a,0x6f,0xcc,0xb4,0x5d,0x11,0xcf,0xb5,0x4b,0xa1,0x6a,0x68,0x43,0xf2,0x80,0xd3,0x80,0x47,0x10,0x02,0xae,0x0d,0x71,0x50,0x85,0x56,0xc7,0x8e,0xd5,0x41,0x5e,0x42,0x33,0x8c,0x16,0x1f,0x2b,0x62,0x1e,0x74,0xcb,0xa4,0xf6,0xa1,0xd4,0x02,},"\xab\x0a\x6d\xe2\x35\x1b\x9a\x84\x98\xf6\x82\x72\xd9\xa0\xa7\xa0\x57\x36\x5d\x34\xef\xa0\xfd\x34\xcc\x3b\xf8\x62\xe4\x9c\xdc\x30\x2b\x2b\xd5\xa3\x0d\x60\x1a\x13\x0e\xc4\x03\x2f\x54\x1a\xe6\xcb\x7b\xa9\x7f\x84\x18\x3d\x2d\x25\x81\x28\x7c\xa7\x01\xd7\xd7\xa9\xab\xa1\x10\xce\x58\xb9\x46\xac\x08\x24\x30\x5d\xf7\x92\x9f\x3d\xd7\xfc\x9c\x87\x32\x23\x86\x37\xe2\xb1\x81\xd6\xe1\x16\xc7\xf6\x6e\x32\x26\xaa\xe3\xce\xd1\x61\x02\x62\xda\x1a\x0a\x4a\xa5\x0a\x1b\x94\x43\xec\x82\x83\x29\xe4\x73\x4d\x28\xfc\x25\xab\x9c\x1d\xe9\xb8\x98\x7e\x5d\xc0\xc8\x13\x19\x16\xc5\xf1\x89\x28\x70\x4a\x71\xe8\x06\x22\xb1\x49\x2b\xf2\xfe\xc5\xd4\xb6\xdb\xe4\x15\xc8\xaf\x2c\xe3\xef\x10\x9b\x34\xdd\x5e\x64\xd5\x68\x46\xf0\x85\x93\x5a\x4a\x5d\x10\x73\x49\x7f\xb3\xfb\x8f\xb7\x7e\x8f\x5d\x5e\x3f\xd0\x0c\x30\x65\x2e\x3c\x5c\xde\x40\xa3\x35\xd1\x4e\x54\x25\xff\xba\x94\x28\x85\xed\x17\xbd\x36\xdf\x50\x69\x24\x23\x7e\x75\xbe\x84\xda\x82\x19\x50\xb9\x14\x24\xfd\x9f\x16\xc1\xb2\xc7\x83\xe9\x0f\x8c\xc2\xcc\xc7\x98\x0c\xe9\x15\xc7\x69\x6b\x06\xa5\x86\x73\x02\x59\xe6\xd1\x45\x88\x58\x2b\xab\x9d\x2a\x39\xf6\x9e\x98\xe7\xf2\xae\x9b\xc0\xc2\x61\x0d\x7e\x04\x57\xf2\x6a\x5d\x66\x54\x3b\xe1\xd6\x5b\x79\xc4\xb7\xc0\xd8\xee\x73\xd0\xc2\xb6\x7b\xf5\x0d\x80\x82\xf0\x06\xf9\x6d\x11\x95\x05\x87\x31\x93\xdf\xdb\xd4\x32\xbb\x1c\x9e\xe0\xd0\x3e\xe5\x4c\xf9\x5d\x20\xe9\x1f\x7f\x3a\x06\x9b\x62\x56\xf4\x21\x59\xcd\xc1\xe6\x00\xa9\xa1\xc2\xf5\xa8\xe4\x67\xd5\xc2\xa9\xdf\xf8\x73\x0e\x6b\xe8\x26\xfb\x2a\x1e\x64\x48\xbf\xc4\xfc\xaa\xaa\xcd\xaa\x76\x62\x35\x1f\xaa\xdc\x91\xf7\xca\xa7\x73\x7d\xc8\x2e\xc3\xd4\xb2\x19\x36\xbc\xa1\xbd\x7c\xe3\x73\xad\x66\x26\x4a\xf1\x32\x41\x16\x75\x49\x31\x8c\xdd\x78\xe5\x63\x82\x7f\x85\xea\xb2\x0e\x0b\x42\xbc\x55\x4a\x71\x2c\x00\x51\xa5\x01\x0d\xc2\xf2\xc7\xdb\x85\xac\xf6\x54\x9f\x9d\x10\x2c\x90\x3c\x1b\xe5\xa0\x52\x92\xc3\x0f\x21\xab\x1b\x2b\x8a\xbc\xbb\xf1\x04\x72\x3c\x63\xf0\xeb\xc5\x54\xfb\xee\x42\x02\x0c\xcb\x14\xf4\x43\x47\x8d\xf7\x7c\x6a\xa4\x4d\xb9\xa5\x7f\x8f\xd4\x4d\x97\xea\x09\x9e\x47\x74\x82\x3e\xbe\x12\x3f\xcf\x50\x16\xa6\x6e\x83\x7b\x2f\x65\xc1\x84\x5e\x68\x1e\xe2\xa7\x05\x9f\xb1\x29\x0c\xd0\xa9\x33\x12\x98\x55\xcc\x83\xc8\x7e\x0b\x3b\xb6\x1e\x44\x13\x4a\xdd\xd3\x63\x78\x50\x24\x6c\xdc\xda\xa2\x9f\x15\xc4\x1a\x3d\x4d\xd2\xc1\xd7\x60\x06\x21\x24\x33\x31\x24\xcf\x09\x14\x35\xfd\xce\x71\x1f\x52\x31\x63\x68\x99\x9b\xef\xa4\xc8\x0a\x39\xb3\x75\x0e\x4e\x38\x62\x89\xe4\xe2\x85\x5e\x97\xb6\x19\xb0\xa2\x57\x99\x91\x24\x08\xb7\xd5\x8a\x4d\xd9\x81\x95\x71\xe9\x01\x43\x0f\x6d\x55\x55\x29\xdd\x63\x0a\x18\x67\x45\x9b\x80\x22\xd0\xe0\xad\xd6\xab\x4f\x12\xf6\x0b\xaa\xc7\x59\x79\xbb\xff\x7f\x62\x58\xd2\x8d\x67\x60\xb1\xff\x24\x3c\x39\xe4\xbb\xd6\xcf\x9b\xea\x57\x2a\x9c\x08\x2d\x05\xad\xcf\xd4\xcc\xf9\xfa\x02\x6f\x2c\x90\x4b\x6e\x78\x2e\xd7\x09\xdf\x77\x48\xa3\x07\xcd\x2d\xc3\xa0\xfc\x41\x23\xdf\x58\x0c\xbf\x49\xe0\x5c\xee\xab\xc9\xf3\x9e\x57\xb7\xf3\x00\x90\x5d\x8b\x31\x00\x91\xfb\x95\x3f\x3d\xef\x36\xde\xb3\xe8\xbf\x37\x2f\x59\x16\xb5\x15\x97\xdf\x02\x4c\xe8\x5c\xc4\xc3\x6e\xab\xdc\x58\x0b\x5c\xf1\x52\x99\x46\x48\xf1\xd7\xf3\x5f\xed\x5c\xd1\x0f\x6e\x29\x49\x16\x1a\x33\x59\xb3\x03\x4d\x45\x0e\xa6\xf6\x1c\xdf\x1d\x5a\xf7\x6d\x40\x10\x2b\x60\x29\x4f\x4e\x49\x07\x82\x49\x02\x6d\x62\xfe\x35\xfd\xf2\x24\x92\x8b\x0c\x49\xba\x2b\x53\x39\xeb\xb1\x92\xc5\xab\x7f\x05\xcd\xb9\x46\xe3\x7d\x67\x1a\x4a\x5e\xf2\xa5\x82\x72\x20\xb4\x43\x8c\xbd\xa0\x57\x36\x29\x28\x06\x64\x8f\x5b\xdd\x52\x42\x0f\xa7\x6b\x84\xa6\xad\xdb\x12\x63\xeb\x0c\x50\x0e\x81\x56\x6d\x71\x8d\x50\x66\x02\x6d\xa0\x97\x05\x4a\x86\x63\x10\x16\xdd\xfb\x70\x6a\x56\x77\xd5\x02\xef\x84\xaa\x73\xb5\x86\x3b\xc4\x0f\xdc\x42\xcb\x73\x21\xac\x5f\x00\xe2\x92\x8f\xed\x7b\x04\x18\x59\x6d\xb4\xb6\x15\x1d\xd6\xbc\x6e\x81\x8f\x02\x53\x55\x2b\xf1\x37\x41\xe6\x96\x80\xe9\x66\xc9\x2c\x29\x3e\x13\xc9\x0f\x7c\x99\x99\xbd\x1e\xc6\xaf\xe3\xb4\xaf\xfb\x47\x34\x0c\x89\x85\x98\x29\xfe\xb5\x99\xdb\x3a\x8c\x3d\x33\xfc\x8d\x45\xfa\x53\x81\x07\x8a\xe9\xf7\x5d\x85\xc1\x49\x6f\x5f\xb5\xad\xdf\x4e\x40\x09\xb7\x64\xbc\xc9\x11\x8e\x92\x75\xdc\x72\x19\xf2\x81\xd0\xd1\xef\x71\x58"}, -{{0x49,0x84,0x6a,0xda,0x7a,0xe6,0x84,0x97,0x1d,0xd9,0x17,0x10,0x79,0x90,0x90,0xb3,0x7f,0xe5,0xad,0x56,0x1d,0x72,0xa3,0x5f,0x2e,0xfb,0x40,0x5f,0x19,0x6a,0xb0,0xec,},{0x4d,0x37,0x0a,0x81,0x94,0xa3,0x04,0x5b,0x09,0xb3,0xbd,0xaf,0xa2,0x7f,0xb9,0xac,0xd5,0x99,0x43,0xa5,0x4a,0xe1,0x4c,0xba,0xaa,0x22,0x00,0xeb,0x0f,0x3d,0xa7,0x1b,},{0xa5,0xc8,0x09,0xd1,0xca,0x4c,0xfb,0xb3,0xdc,0x70,0xa2,0xa3,0xa1,0xf2,0x67,0xc2,0x73,0x30,0x42,0x07,0x19,0xe3,0x60,0x62,0x18,0xa1,0x47,0x1c,0xac,0x57,0xcb,0x67,0x4b,0x9b,0x42,0x82,0x7c,0x5e,0x9a,0x7b,0x25,0xc8,0x13,0x9c,0x13,0xdf,0xf6,0x0b,0xde,0x6c,0x2d,0xba,0xd3,0xa8,0x36,0x11,0x97,0xc1,0xfb,0x19,0xd2,0xcd,0x52,0x0b,},"\xab\x39\x8d\x94\xf9\x28\xb1\xd4\x21\x02\xa3\xe5\x13\xcc\xd1\xcb\x10\x89\x90\x11\x03\x94\x10\xa8\x88\x8b\xba\x26\xdf\x1a\x03\x72\xbd\xba\x0c\xe8\xd8\x54\xaf\x51\xe9\x33\x0a\x8d\xaa\x93\xc1\x05\x80\x90\x6a\x8a\xc7\x2d\x29\x4a\xeb\x95\x66\xfe\x1c\x78\xba\x84\x71\xc0\x6c\x4a\x8a\x75\x11\x3b\x34\x89\x3f\x62\x76\xed\x81\x32\x92\x05\x3b\x95\x6a\x46\x5d\x84\x7d\x2e\xce\x86\xe2\xda\x8a\x9f\x0f\xe3\xdb\x52\xa5\xaa\xc7\x46\xef\x96\x48\x5e\xf8\x1f\x13\x62\xb5\xa4\x2e\xaa\xee\x1f\xbb\x06\x46\x70\x44\x71\xa2\x1b\xf7\x63\x67\xbe\xaa\x07\x81\x2b\x3d\x32\xad\xcd\xed\xde\xd7\x53\x9e\x3a\x50\x1b\x83\xc0\x5b\x19\xa4\x9b\x52\x0e\xde\xdc\x9a\x78\xa5\xfc\x2d\x50\x12\xf1\xd4\xe3\x81\x84\x4e\x79\x2e\xd9\x0b\x0f\x57\xbc\xe3\x75\xc7\x5a\x65\x8b\x2c\x78\xc6\xff\x7d\x9e\xfc\xd4\xbf\xa3\x5c\x47\x68\xcb\xb1\x95\xe4\x82\x3d\x9b\xbd\x83\x5a\x37\x4f\xa0\x4c\xa1\xea\xae\x9c\x56\x6d\x8f\xd5\xaa\x7c\xa5\xef\xe0\xdf\xc3\x17\xff\xfa\x40\x9e\xf1\x02\x2f\x1c\x3b\x37\x6a\x93\x5a\xf5\x57\x08\x3e\x95\x28\x7b\x07\xa9\x8a\xc6\xc1\xb7\xbd\x8b\xb2\x6b\x60\xfa\x7c\x4b\xc9\x19\x73\xb2\x01\xb2\x99\x22\xb4\xb9\xd0\x3d\xd6\x88\x2a\x0b\xd3\xb7\xd9\xe5\xb8\x1e\xe7\x4c\x36\xbe\xc6\x65\xe4\x34\x3c\x8c\x9a\xd3\x36\xda\x38\x50\xc9\xb2\x69\x7f\xe1\xcc\xe2\x9c\x37\x86\x22\xa3\x3c\x24\x8f\x44\x8c\x88\xf4\x8d\xf0\x26\x01\x43\xb2\xa3\x42\xf1\xdd\xee\x74\xd3\xb9\x7c\xa3\xe1\x16\x6b\x15\x69\x93\xda\xd3\x0c\x49\xd8\x10\xd7\x40\x48\xbc\x6d\x46\x76\x52\x00\x4d\x7e\xdb\x65\xc6\xda\xc3\xa2\xc5\xd3\x00\xb9\x7e\xe3\xa1\x0a\x9e\x14\xb6\x9f\x3c\xad\x67\x59\x72\x96\x2e\x1f\x8e\xd9\x75\x47\xad\xed\xc4\x7d\x1c\xf3\x47\x1e\xf3\xb2\x2f\xdb\xf7\x8e\x34\xf3\x1a\x3b\xb7\x66\x9c\x41\xbd\x92\x92\xc3\x80\xbc\xe9\xa4\x2d\x84\xbc\x27\xac\x92\x8b\x8b\xfc\x3c\x63\xd2\x0c\xcd\xb4\x78\xdf\x7d\xdf\x42\x1f\xb1\xcd\x90\x5f\xfc\x4c\x04\x78\x6f\xd9\xae\xf0\x6b\x89\x38\xab\x8e\xf5\x22\x21\x7b\x2c\x04\x51\x5f\x61\xa1\xc3\x12\xea\x83\x25\x3f\x84\x58\xc0\x91\x8f\xcf\xe8\x74\xe6\xe7\xfb\x11\x27\x5d\xb2\xa2\xec\x79\xa2\xd8\x68\x30\x32\x33\xc1\xb6\x97\x95\x2a\x3b\xfd\x3a\xd0\xa6\xf6\xcd\xd5\xe7\x2c\xc9\x40\x9f\x74\x10\xa4\x0d\x5b\x45\x36\xdd\x46\xeb\x16\x11\xae\x86\x70\x36\x71\xb3\xa0\x51\x5a\x03\x77\xbe\xa1\x56\x54\xba\x0a\x0d\x1e\x4e\x96\x02\x63\x28\x42\xf2\xac\xd4\xef\x99\x32\x36\xe9\x93\xf2\x65\x0d\x59\x92\x3f\x24\xe2\xcd\x30\x93\x2d\x8b\xf8\xae\xec\x64\x44\x72\xba\x46\xa0\x78\x81\x49\x6c\x92\xa0\x13\x5c\x67\x5a\xeb\x0c\xe6\x18\x10\x88\xdb\x8f\x15\x6c\xfe\x74\x35\xca\xc6\xc9\x7d\xa6\x37\xdb\x4a\x89\xf5\x13\x31\xda\x13\x73\x1e\x74\x1f\xcc\xc0\x35\x55\x42\xce\x11\xef\xa6\x9d\x05\x38\xd3\xef\x12\x7a\xa6\x87\x45\xed\x30\x85\xd2\x9d\xa9\x0d\xc5\x83\x70\x1b\x6b\x3a\x70\xa3\xef\x3e\x16\xa9\x24\xb3\x32\x03\xb9\x23\x96\xc4\xb9\x45\xf1\x27\xa7\x88\x8f\xa0\x50\x15\xc0\x60\x30\x07\x56\x67\x29\x23\x7c\xc0\x78\x2b\x30\xc0\x20\xd9\x95\x95\x47\xfe\xec\x9f\x4d\x67\x64\x60\xbf\xe0\xc5\xc1\x9c\xea\xba\xee\x06\x82\xdb\x8b\xe6\x91\x35\x18\x1e\xc0\xfd\xd9\xf7\xa6\x6d\x50\xbd\xc3\x79\xe4\xa2\xc5\x98\x17\x8f\x95\x93\x94\x6a\xca\x64\x05\xb1\x77\xfc\xad\xe0\xf8\x64\x21\x58\x3e\xd6\x7e\xba\x18\x72\x22\xa1\xe4\x44\x95\xb3\xae\x54\x4f\xdc\xa2\x8e\x2c\x14\x48\x5e\xab\x04\x71\xaa\xa8\x03\xc2\x9a\x9d\x8a\x48\x92\x67\x64\xfc\xa1\xdf\x51\x40\x7a\xd3\x3e\xc1\x7e\x94\x1e\x6e\x26\x17\x23\x7a\x84\x30\x98\x73\xdc\x71\x36\x55\x87\xbd\xe4\x27\x4b\x5d\xc3\x27\xcc\xb1\xe1\xe9\xc8\x57\xe0\x42\xcc\xca\x8d\x85\x52\xba\x28\x8c\x97\x8c\xfa\x0a\xf9\x9d\x67\xcd\x03\x40\x60\x62\x8e\x23\x52\x5d\xbc\xa2\x07\x67\x9c\xe2\x96\x90\x87\x84\x48\x55\x3c\xd3\x86\x75\xbc\xe0\x7b\xf9\x7b\x93\x17\xdc\x44\x46\x8b\x76\x8b\x15\x8b\x0c\x11\x1d\x63\xa5\x72\x23\x56\x55\xc4\x0e\x16\x59\x7c\xa0\x59\xf4\x0c\x3d\x8a\xc5\xbd\x61\xa4\x87\xc1\x53\x13\x84\x6a\x70\x4a\x78\x11\xb8\xbc\x0c\xee\x61\xe3\x47\x62\xb6\xc1\xb7\xce\xa1\xc4\x6e\x60\x87\xe9\xa3\x6f\x89\x91\x8a\x25\x8b\x3f\xa7\x76\x20\xbe\x10\xc1\x84\xc3\xfc\x39\x73\x90\x24\xe9\x82\x78\xfd\x65\xb8\x2c\xad\x83\x69\x9f\x3a\xd8\xc6\xec\xcb\xec\x8b\x7b\x1b\xd7\x91\x4d\x3f\x6c\x3d\x02\xbf\x40\x28\x3b\x1c\x1f\x1e\x98\xe3\x08\xbe\xae\xbb\xf8\x94\xb8\xf5\xe9\x1b\xbb\xc6\x25\x35\xf9\x23"}, -{{0x83,0x34,0x3e,0x37,0xad,0x09,0x1a,0x85,0xee,0xc3,0x70,0x70,0x1b,0x81,0xa5,0x8f,0x93,0x70,0xa4,0xb0,0x42,0x3a,0x07,0x0d,0x60,0xf9,0x2d,0x8d,0x18,0x09,0x84,0x4e,},{0x50,0xb6,0x8b,0xf7,0x26,0xea,0xbc,0xa5,0x3a,0xc6,0xc9,0x0d,0x4e,0xac,0x55,0x47,0x03,0x71,0x2d,0x22,0x10,0x55,0x54,0xf0,0x5b,0xf7,0x9f,0x9d,0x08,0xfc,0xc4,0x93,},{0x9c,0x69,0x89,0xcb,0xe1,0x7e,0x16,0xca,0xa2,0x53,0xff,0xb1,0xa6,0x4a,0x10,0x6f,0xb0,0x17,0x82,0xc9,0x9b,0x17,0x22,0xba,0xf1,0xac,0xaa,0x42,0xae,0x5b,0x36,0xb7,0x9b,0x2a,0x2c,0xd8,0xfc,0x91,0xf5,0xad,0x89,0x23,0x81,0x70,0x25,0xa7,0x78,0x25,0xa0,0x5d,0xf8,0xc4,0x17,0xec,0x53,0xc4,0xa3,0xaa,0x1c,0x0e,0xfd,0x5b,0xbe,0x0f,},"\xc7\xda\xdc\xac\x5d\x87\x95\xe1\x74\xb6\x91\x38\x91\x2e\x70\xff\x41\xe7\xa7\x25\xfa\xf3\x85\xb7\x73\xed\x15\x09\x89\x72\xb3\x0d\x9b\x73\x93\x72\xd9\x75\xb4\x80\xcc\xfd\xfc\x58\x0e\x2e\x2d\xdf\x5e\x3c\x27\xee\x79\x12\x79\xab\x95\xe4\x38\x2b\x14\x59\xdd\x8d\x41\xae\x36\x0d\x4a\x87\x88\x46\x69\x29\x24\xfe\xef\x39\x0c\x0d\xbb\xfa\x35\xe4\xb8\x2d\x7c\xbc\x33\xee\x15\x81\xc5\x2b\xd9\x49\x38\x5b\x2e\xe4\x02\x63\xa5\x7d\xa1\x17\x4b\xb4\xac\xad\x37\xcd\x8a\xe2\xa6\xb4\x5f\x7a\x6d\x6b\xbe\xf5\xa7\x98\xce\x85\xb9\xe0\x5e\x76\x47\xe3\x34\xec\xfc\x77\x63\x78\xde\x17\x4c\x49\x7c\x0f\x40\x75\xe6\x25\xaf\x7a\xed\x50\x2c\xd1\xcf\x7f\x58\x8d\x0d\x80\x7f\x02\xe3\x2f\x43\x00\xf2\x28\xa5\x0a\x66\x7b\x5a\xd1\xfb\xbc\x17\xe0\xb3\xc5\x70\x51\xdd\xc6\x02\xf5\x76\x07\x9f\x6f\xc5\x88\x9b\x7f\x29\x00\x71\x13\x34\x42\x0f\xc6\x66\xf6\x6d\xba\xff\x41\x26\x33\x6c\x35\x3f\x1e\x5b\x56\x4a\x66\x45\x37\xf8\x37\x86\xda\x5c\x56\x27\x74\x54\x06\xd7\xb2\xfe\x32\x33\xbf\xd5\x8e\xf4\x64\xa0\x6c\x95\xcf\xd0\xb9\x88\xa7\x6d\x05\x3a\x64\x4b\xcc\x15\x9c\xad\x53\xa7\xc5\xdb\xb4\x0e\xef\x5c\xd0\x47\x05\x6a\x3f\x09\x26\x5b\x13\x25\x69\x9c\x7d\x15\x9d\x5c\x90\x24\x40\x17\x33\x57\xff\xab\x8f\x7a\x5e\x38\x9f\x46\x8c\x33\x3b\x78\x2f\x80\x17\x0a\xe9\x09\x83\xaf\x15\x3f\x2e\x73\xbd\x2b\xef\x12\x5e\x3d\x38\x68\xc2\xab\x9e\xcf\x03\xaf\xf7\x6e\xcb\xeb\x18\x16\x7c\xa2\xf7\x11\xcd\x56\x58\x51\xd7\xf0\x4e\xe9\xd9\xb0\x1b\x6d\x83\xa7\x60\x57\x22\x62\x0d\x28\xc8\x4d\x6c\x1a\xf4\x2f\x6a\x76\x92\x58\xf5\x3c\x1f\x66\xda\x36\x66\x6d\xa5\xca\xa9\xbd\x9e\x8f\xbc\x16\x92\x11\xb1\xae\xd9\xc2\x55\x8f\x6a\xaf\x5b\x14\x5a\xbc\x72\x1a\xbb\x00\x72\x01\x94\xe0\x27\x03\x54\x68\xbd\xe3\xfe\x0b\x88\x88\x4f\x4e\x9b\x26\xe7\x71\xe6\xc7\xa0\xa5\x5e\xa3\x6f\xc5\x0d\xec\x8c\xef\x16\x2f\x9b\xba\x5b\x4b\x16\x10\x5a\xfd\x6e\x37\x4e\x03\x8d\x5c\x85\x87\xcf\xd7\xdd\x88\x29\x0b\x2c\x9c\xab\x45\xa2\x64\xd6\x54\x0e\xa1\x41\x6e\x6e\x4e\x74\xa1\x2f\x45\xa2\xef\x13\xcc\x8a\x36\xe7\xb0\xa2\x6b\x90\x2c\x3d\x96\xe2\xe2\x22\x92\x02\xe2\x57\x65\x69\x4b\x94\x33\x73\xd1\x6e\x60\x0b\xd7\x86\xd9\x55\xa4\xb3\xf1\x02\x16\x40\xc3\x9a\x0b\x6c\x69\x15\x00\x28\x1a\xe0\xd0\x98\xcc\x7f\x38\x5e\x18\xa0\x7e\x62\xfa\x4a\x10\x1e\xf5\xb7\x85\x51\xfa\x29\xbd\x15\xee\x03\x53\xa1\xa5\xef\x9b\x21\x6e\x8b\x0f\xa5\x07\x50\xa3\x41\x62\xb6\x35\xa0\xbc\x5e\x5d\x72\x30\xaa\x19\xaf\xa1\x28\xab\xa6\x42\x2d\x38\xeb\x77\xa3\xf0\xbb\x9d\xd8\xe4\x65\x2f\x12\x07\x0a\x37\x36\x1c\x37\x25\x50\x3c\x9d\x22\xe2\xfa\xce\x2e\xa7\x4a\x70\x02\x40\x62\x47\xdd\x86\x97\x5f\x07\x57\x5c\x9e\x7c\x6f\x41\xb5\x3b\x26\xd5\xcf\x52\xc5\xac\xc2\xc5\xd9\x82\x71\x43\x4e\x9f\xa5\x09\xc6\xdf\xbd\x72\x43\x72\xaa\x5c\x13\x45\x1a\xae\x39\x3d\xe0\xa1\x86\x46\x4f\x5d\x33\x7e\x9f\x62\x7b\x4f\x1c\x29\x09\x46\x70\x65\xe8\x9a\x42\x2e\xc4\x0e\xe1\xd8\x0a\x13\x39\x00\xa6\x2f\x4e\x4f\x7e\x94\xeb\x72\x61\x5e\x7e\xc2\x99\x6c\x6c\x24\x30\xc3\xe9\x57\xce\xae\x21\x05\xa1\xe9\x0e\xae\xac\x0d\x31\xaf\xfa\x9f\x57\x92\x6d\x71\xd9\x72\xa9\xa2\xde\x11\x25\x8c\xc1\xe7\x28\x59\x9c\x9f\xb3\x87\x24\x91\x84\x7e\x10\xc6\x7e\xfa\xef\x6b\x69\x6a\x03\x0f\xf0\x53\x3a\x58\x3b\xea\x1d\x04\xdf\x25\xf7\xee\xf3\xa1\x3b\x8e\x31\xaa\xd1\x33\x85\x7d\xf1\xb4\xe5\xff\xbd\xee\x37\xf4\x0f\x38\xd2\x24\xc7\x0a\xe0\x4e\xf3\x3b\x41\xb0\x2e\x71\x91\xa8\x66\x56\xb0\xd7\x2b\x2c\xbb\x53\xc4\x90\x8c\xa2\x06\xf7\x57\x34\xb2\x77\x08\x15\x4f\xcd\x8a\x97\x42\x9c\xfd\x1f\x2d\xa2\x42\x97\x78\x43\x80\x03\xf5\xb5\xb9\xc2\x1d\x9e\xd2\x3b\x8a\xd8\xa2\x28\xeb\x4f\x65\xc2\x4c\x1c\x59\x69\x9a\x5c\x90\xaf\xf7\x73\xe5\xc6\x76\xdb\x36\x2a\x19\x30\xba\x16\xab\xa7\x6e\xf8\xda\xa4\x2b\x3e\xb2\xcc\xc4\x5c\x93\x4d\x23\xd4\x92\x9a\x7a\xd9\xe3\xef\x46\x8b\x06\xa4\x99\x5c\x80\xdd\x23\x6a\x7b\xcf\x38\x79\xd8\xb7\x94\x67\xf7\x2b\x33\x84\xc1\x60\xcc\x18\x17\x14\xe9\x2f\x20\x35\xe7\xb9\x72\xa2\xcc\x52\x42\xd9\x32\x52\x5e\xae\x7c\x50\xbd\x26\x3b\x0f\xa0\x9c\xbd\x9d\x6f\x98\x4b\x9c\xf6\x15\x2d\x9a\x13\x3c\x27\x84\x32\x02\xd1\xe8\x7f\xa5\xa6\xe1\x23\x5d\x9c\x75\x6b\xb8\xe6\x8b\x05\xb9\x8d\xa5\x41\x95\x22\x3f\xdf\x02\x10\x25\x32\x50\x63\x3c\x11\xc5\xf6\x0b\x5e\x67\xd7\xee\xfc\xaa\x6c\x2d\xaa\x52\x31\x37"}, -{{0xda,0x01,0x32,0x21,0xb2,0xf5,0x88,0xaf,0x40,0xe2,0x11,0xa0,0xf9,0x75,0xd4,0x4f,0x9d,0x65,0x02,0x81,0x60,0x51,0x4c,0x39,0x61,0x89,0xf2,0x7c,0x7b,0x06,0x66,0xea,},{0x07,0x11,0x7c,0x6b,0x0d,0xb5,0xb6,0xfd,0xa1,0xed,0xc4,0x39,0x6c,0x47,0xc2,0x2b,0x54,0xee,0x0c,0xe5,0x37,0x5c,0x3e,0xc6,0x33,0xc8,0x3a,0xfc,0x53,0xad,0x6c,0xe4,},{0x10,0xcb,0x52,0xd6,0x10,0xe4,0xa8,0x1d,0x32,0x86,0x9b,0xff,0xce,0x38,0x07,0xe6,0x39,0x1f,0x78,0x2f,0xcd,0x53,0x8b,0x55,0x4d,0x09,0x03,0x7f,0xda,0x72,0x28,0x5b,0x96,0x62,0xb1,0xb1,0x10,0x7c,0x40,0x81,0x78,0xac,0x00,0x9f,0x05,0x25,0x96,0x73,0x88,0xa7,0xd8,0x5f,0xa1,0x23,0x59,0xd3,0xce,0x38,0x75,0x03,0x7d,0xcf,0x6a,0x04,},"\xbc\x93\xee\x1e\xc4\x72\x8a\xc6\x36\xa6\x24\x8f\xcc\x45\x51\xc9\xd1\x59\x80\xdb\x8e\x5f\x54\xb0\xef\x07\x5a\x71\x97\x0e\x17\x6a\x3c\xb9\x18\x2e\x32\xda\x7a\x8c\x2a\xc0\xcd\x7e\x59\x57\x74\x57\x5f\x9c\x83\x50\x6a\x60\x6f\xac\xe8\x95\x12\x13\x5d\x03\x2a\xb0\x5e\x39\xff\xf9\xc8\xca\x6c\x25\xcd\x5d\x78\xec\xc3\xac\x32\x32\x90\xc9\xc8\x16\x26\x73\x5e\x19\x0e\xb5\xae\x34\x5c\xa7\xa9\x58\x40\x9f\x77\x43\xb0\xb1\x61\x49\x16\x83\x22\x17\xc5\x7e\xee\x1b\x4f\x8e\x62\x2a\xc0\x52\xa9\x3d\xd5\xb3\x9d\x07\x61\xe4\x0e\x9f\xbd\x83\x96\xf6\x0a\x3b\xf6\x66\x0c\x5f\xa9\x9c\xd8\x13\x9f\x68\xcb\xe0\x89\x4e\x5c\x67\xe1\x68\xcc\x74\xb2\x72\x4e\x9d\x91\xd6\x00\x0a\x0c\xec\x58\x7a\x11\x46\x3f\x72\xee\x6e\xd2\x55\xbd\x87\xeb\x30\xfd\x45\x75\x96\xf6\x88\xca\x0e\xa7\x3f\x30\x49\x72\x38\xde\x21\xc9\x3f\xbb\x12\x94\xdb\x61\xe4\xa5\x60\x89\x10\x6d\x1c\xf7\xce\x5a\x65\xec\x3d\x12\x17\x0c\xe7\x84\x0f\x08\x8a\x8d\x0e\x3a\xef\x17\xe5\x31\xde\x47\x80\x03\x57\x02\x58\xe9\x27\xf1\x56\xe7\x96\x10\x65\xaf\xa6\x66\xaf\x38\x58\x2b\x35\x3c\xc4\x77\xba\x77\x5c\xae\x45\x94\x6d\x08\xdb\x75\x21\x59\x14\xda\x32\x61\xb6\x22\x94\xe9\x2a\xfb\x38\x14\x59\xc2\x1d\xda\x4e\xa6\xed\x79\x5f\x79\x25\x7c\x09\x4d\xd6\x08\xdc\x8e\x1b\x7c\x40\xcd\x29\xfe\xa2\x22\x08\x8f\x65\x69\x7e\xa8\x88\x95\xd1\x0a\xce\xa8\x79\x73\x60\xdc\xba\xce\xe2\x69\xc6\x06\x60\x0a\xdf\xfd\xcf\x9c\x7c\x38\x1d\x0a\xd6\x69\x69\x67\xd9\xff\x03\xe6\x1a\x24\x90\x65\x02\xb2\x95\xe7\x6f\x4d\x08\x75\x65\x5b\x01\xe6\xff\xca\xcc\x8e\xf0\x11\x29\xc7\x2a\x58\x46\xb6\x0e\xc8\x00\x17\x37\x4e\x75\xd3\x06\x40\x3d\x9e\xcc\xf2\x64\x95\xd2\x98\x12\x0a\x06\x33\x83\x5c\x5d\x1e\xff\x17\xc9\xc6\x24\x76\xf7\x52\xc8\x97\x10\xad\xfa\x4d\x51\x61\x7b\x59\x18\x17\x3c\xba\x72\x25\x40\xe3\x88\xff\xbf\xfb\x96\x68\x74\xdb\x00\x40\x4d\x06\xb0\xce\x11\x39\xba\x74\x14\x3c\x76\xb8\xf4\xd3\x3b\x21\x16\xe1\xcc\xe1\x75\x17\x3a\x96\xfc\x15\x1e\xa2\x39\xbf\xc2\x0d\x66\xfb\xb6\xf5\x2a\x66\x6c\x0e\x81\xcc\x2b\x80\x20\x91\x06\xe2\x48\x0e\x41\x11\xc7\x0e\x7b\xe4\xaa\xbb\x68\x42\x2f\x0b\x8c\x6b\xa1\x5c\x14\x2f\x82\xe6\xc7\xf3\x78\xd7\x80\x0a\x09\xea\xa4\xda\x25\x3c\x2f\xd9\x1e\x12\x63\xc6\xb6\x55\xbf\x70\x25\x5d\x7e\x3b\xb4\x77\x55\x23\xa0\xa9\xe7\xff\x03\x79\x7e\xe3\xff\xca\x8a\x50\xd1\x0f\x20\xd5\xe5\xa8\x89\xec\x5e\x33\x4e\xf2\x6c\xf7\x99\x8b\x08\x36\xf6\x56\x45\x68\x88\xe1\x37\xf3\x9d\x3e\x43\xe2\xce\x3c\x6e\xf5\x40\xd9\x5d\x9a\x20\xc4\x2c\xb8\xae\x2d\x9d\x0f\x25\xa8\x91\xc3\x63\xea\xd9\xcc\x42\x3f\x9a\x32\x3f\xe2\x32\x28\x1f\xb6\x7f\x5b\xe1\xc0\x78\x43\x61\x46\x04\x68\xa8\x7e\x95\xdf\xa3\x5d\x7f\x0f\xfa\x22\x11\xbe\x6b\x5f\xb3\x2d\x42\xba\x65\x18\xab\x6e\xa9\x37\x80\xf4\x31\xd3\x00\x67\x31\xbe\x44\x40\xe7\x12\x97\x4f\x74\xba\xea\x41\x9f\x40\x22\xfa\x25\x02\xe1\xb2\x39\x8e\x93\x86\x16\x7d\x93\xec\xa9\x2c\xa6\x0d\xd7\xd9\x1f\xe8\x23\x24\xf6\x82\xd9\x4a\xa7\xa8\x6a\xb0\x34\xf8\xa9\xe9\x52\xe8\xfc\x95\xbf\xf4\xdf\xed\x6a\x43\x31\x3a\xbb\x92\x40\x1b\x30\xc3\x3c\x79\xa7\xba\x3e\xfd\xbe\x16\x28\x04\x0f\xba\xf4\x43\xf3\xf9\x80\x84\x6f\xdb\x28\x3d\xcc\xd9\x3f\xab\x09\x70\x8b\x7d\x54\x86\x1d\x74\xb1\xfe\x8f\x10\x70\x1f\x21\x1b\xa3\xd3\x90\xe8\xa6\xae\x40\x77\x39\x64\x6a\x79\xa5\x83\x37\xa7\x17\xa8\x72\x00\x9c\x2d\xf6\x76\x1c\x24\x25\xa3\x2a\x00\x18\xaa\xf9\x64\x64\x70\xcb\xc8\x7c\x3a\x65\xc0\xe0\xef\xfb\xaa\x52\x8f\xe4\x78\x3c\x77\x2a\xb2\x66\xb8\xf2\x82\x68\xcf\x14\xaf\x23\x4b\x15\x81\x6d\x1a\x3a\x49\x1a\xf5\xf2\x97\xe3\x3d\x57\x29\x71\x5d\x51\x2c\x37\x3f\xef\x5e\xcc\x3f\x39\x54\xa6\x0a\x2a\x0f\x64\xd8\x29\x47\x41\x19\xca\x1a\x18\xf1\x05\x78\xd0\x4d\x63\x8d\x5e\xea\xfc\x37\x1a\x94\x6f\x6c\xe7\xef\xbd\x2a\xcc\xe3\x4e\x20\x44\x1c\xde\x9a\x37\xd5\xa8\x7d\xc6\x19\xb0\xa7\x27\x59\x6c\xd1\x2e\x15\xcd\x97\x84\xbb\x91\xf1\x39\x9a\x59\xfc\x0a\x7a\x4a\xf6\x8b\x0d\x57\x5d\x93\x38\x71\x72\x97\x33\x75\xc4\x65\xdf\x5d\x2d\x5e\x06\x1a\x2a\x9b\x23\xb4\x91\x5a\x0a\x8b\x8c\x1f\x09\x42\x09\x4a\xf7\x28\xc8\xc3\x11\x45\xfa\x7a\xaf\x74\xa2\x1a\x3b\x03\x2b\xb0\x9c\x39\x22\x05\xbf\x09\x5b\xda\x98\x6e\x5d\xd6\x62\x7c\x1e\x41\x7f\x65\x03\x26\xdf\xe3\xa9\xc9\x99\x4c\x6e\x0e\x01\x27\x6f\x91\xf2\x98\x7d\x2b\x85\xde\xda\x96\x54\x91"}, -{{0x5a,0x86,0x8f,0xb7,0x5e,0xa0,0x72,0x1f,0x7e,0x86,0xc7,0xbc,0x10,0x6d,0x74,0x13,0xc8,0xcf,0x4d,0x03,0x3c,0xe1,0x40,0x05,0xdf,0x23,0xce,0x4c,0x15,0x5b,0xbd,0x27,},{0x6d,0x1e,0x29,0xf3,0x9d,0xed,0xa2,0xbb,0xfb,0xb5,0x7c,0xb0,0x1c,0xb3,0x9e,0x58,0x80,0x82,0x78,0xe5,0x19,0x6a,0xda,0x1c,0x02,0x76,0x46,0xf2,0x04,0x87,0xd2,0x52,},{0x38,0xc4,0x8d,0xba,0x99,0xa6,0x52,0x4a,0x18,0x8d,0x5c,0xd7,0x8a,0x98,0xe6,0x77,0xdd,0x26,0x3e,0xf6,0xb4,0xdf,0x44,0x6b,0x31,0x0b,0x3d,0xd8,0x9c,0xaf,0xdd,0xb9,0xb1,0x7a,0x65,0xbb,0xa8,0xe1,0x39,0x68,0xbd,0xc2,0x5b,0x1d,0x84,0xb6,0xe2,0x43,0x6e,0xdf,0x31,0xaa,0x75,0x6e,0x3a,0x48,0x72,0x6d,0x6f,0x91,0xc8,0x08,0xee,0x0e,},"\xd5\xaa\x11\x82\x5b\x99\x44\x8c\x80\x63\x06\x23\xd8\xc7\x46\x01\x7c\xfe\x3d\xe6\xfa\x8a\x0c\x6e\xd6\x62\x71\x27\xcf\xc1\xf8\x4d\x4e\x0a\x54\xe6\xa7\xd9\x08\xd3\x71\x9f\x14\x21\xd1\xd4\xc7\x8b\x3c\xdd\x94\x76\x9a\xb6\x03\x3b\xce\x97\x9d\xd9\x0e\x10\x68\x02\xeb\xa9\xa0\x32\x95\xd4\x8f\x9b\x9a\x95\xd5\x7e\xe7\x74\x54\x02\xa4\x80\x23\xbf\x3b\xdd\xd5\xc6\xb9\x1c\x77\x3e\x49\x19\x13\xa3\x8a\xc3\x46\x26\x05\xcf\x28\x2d\xea\xc7\x57\x42\xfb\xd2\x75\x29\x27\x6e\x81\xdc\xce\x8d\xff\x96\x05\x03\x5e\x8c\xf0\x5d\xf6\xa4\x3d\xb1\x51\xf0\x41\x57\x65\xbc\xbd\x1f\x1b\xb6\x68\xad\x62\x73\xb8\x91\xc0\xdc\x4f\x3d\xba\x59\x0e\xa8\x2f\x83\x63\x76\x9b\x9c\x77\x51\x19\x47\x11\x73\x75\xdc\x49\x04\xd4\x8b\x88\xb6\x8a\x25\x5b\x28\x01\x1b\x11\x04\x81\x94\x09\x3e\x98\x20\x7a\xb1\xcf\x75\x6a\xb8\x33\x1f\x8d\x6f\x9d\x5b\xe2\xe1\x19\x05\x73\xe9\x5e\x71\x0f\x2a\x35\x01\xb5\x3a\xa0\x82\x5d\x6c\x12\xdc\xfb\x94\xac\x80\xdc\x10\x82\xcb\x4a\xd2\x62\xe6\xd4\x93\xad\xce\xb6\xbc\x19\x14\x5f\xbf\x73\x8d\xf7\x6f\x21\x34\xfa\x04\xcb\xbe\x44\xff\xc5\x5f\xfe\x5f\x9d\x3e\x9b\xeb\xd1\x59\xa0\x01\xaa\x9b\xf7\x88\x92\xa1\x65\x38\xa5\x20\x82\x3c\xde\x5d\x61\xe2\x9a\x56\xa7\x7a\xb9\x6e\x49\xe3\x00\xd9\x86\x59\x62\xc7\xe7\xfb\x8b\xcf\x5d\xe0\xb9\x38\x29\x7c\x3f\x4d\x6f\x60\x21\xe2\x4d\xfd\xad\x98\x61\x65\x2f\x34\x0f\x42\x1e\x7a\xf2\xc7\x1e\xd9\xa7\x15\x87\xfc\x75\x3b\x11\x55\x49\xb2\xf7\xf7\xcb\x29\x69\x0e\xa2\xb1\x58\xa9\x4c\xd2\xbc\x42\xe7\x06\x3d\x61\x9b\x93\x9d\x52\x3e\x3c\x23\x7e\xb1\xf4\x08\x10\xde\x0b\x44\xaa\x69\x37\x86\x3d\x62\x9e\xdd\x55\x75\xe6\xc0\x47\x52\x61\xb6\x27\x47\x30\x92\x77\x5c\x84\x36\x00\x11\xd5\x7c\x57\x20\x9c\x2e\x87\x5a\x3f\x89\x63\xe8\xb2\x41\xa7\xaa\x75\xef\x30\xc4\xa7\x18\xac\x4d\xd4\x66\xdc\x7a\x3e\x40\xe5\x87\x4f\x15\x7a\x84\x9e\xd3\xa3\xa9\xd4\xae\xb7\xd9\x4d\xf0\x9b\xb5\x5a\x0b\x2b\xc9\xf8\xb6\x95\xc3\x71\x79\x30\x23\x67\x60\x63\x67\xc5\xf3\x24\x82\x8c\xe7\x5a\x94\x4f\x50\x70\x3a\x47\x90\x6a\x80\x88\xf3\xa1\x1c\xfe\x4a\x85\x4e\x01\xf1\x74\x12\x52\xc4\x86\x33\x7d\x06\xb1\xcc\x6c\x6b\x9b\x12\x95\x43\x1e\xe0\x73\x59\x35\x7b\x3a\x78\xef\x50\x75\xb6\x5d\x7f\xed\x5e\xb7\x42\xe5\x10\x15\x98\x44\x4b\x46\x62\x3f\x89\xa3\x03\xac\xc1\x0c\x73\x24\x49\x51\x3b\x70\xdc\x45\x6a\x79\xd3\x7c\x48\xe5\xe7\x26\xc2\xf5\x58\xda\x0a\x1c\x46\xef\xbd\x2d\x92\x03\x26\xa6\x78\xb8\xa2\x2f\x09\x44\xbe\x4a\xf5\x5b\x6c\x71\xf4\x53\xfb\xae\x40\x0e\x6a\xcc\x04\xe0\xe9\x5c\xa2\x00\x16\x7e\x96\xee\x98\xea\x83\x93\x16\xda\x93\xa1\x2c\x2d\x76\xf1\x1a\xee\xbe\xb7\x8e\x65\xea\x48\xf7\xfe\xeb\xbb\x13\x7b\x2a\xc6\x7e\xae\xf0\x2a\x2d\x9e\x64\x71\xdd\x63\x4a\x03\x7d\x4f\x5d\x35\xa2\xf7\x8a\xf4\x1a\x8e\xa5\xaf\x5b\xc8\x15\x0a\x99\xed\x68\xa6\xa0\xcc\xff\x2b\x1d\x79\x65\xd8\xbc\x3e\xf9\x28\x5b\xa6\x42\x1d\x87\xc3\x3a\xad\x81\x03\xa5\x87\xbe\x01\x92\x68\x45\xbf\xbd\xdb\xaf\xc6\x9c\x4b\x92\x52\x88\x67\x20\xd4\x18\x50\x9f\x40\xf3\xdc\xf5\x57\x65\xdc\xcc\x3d\xee\xd8\x27\x72\x15\xe6\x9f\x05\x6b\xa3\x1b\x8a\x30\xb5\x00\x94\xea\x8f\x14\x47\x20\x76\x0c\x8f\x8c\x05\x5c\xf1\xa8\x69\x64\xff\xcb\xb8\xee\x1b\xb2\x18\x12\x76\xea\x99\xa7\xb8\xe7\x10\x67\xfa\x31\x0b\xa4\x47\x1e\x84\x27\x90\x37\xbc\x49\x2a\x55\xde\x20\x55\x48\xe7\x7b\x01\x45\x04\xee\x66\x64\xc4\x98\x8c\xbb\x9e\xd9\x1f\xf3\x2e\x22\x59\xed\x4c\xfd\x61\xa1\x97\xd0\xdb\xc3\x2c\x68\xf6\x54\x9c\x0d\x29\xfc\x45\xf3\x6a\xcb\x26\xb1\x64\xde\x97\xcc\xdc\x37\x90\x0d\x93\xcd\xbc\xf9\x68\x7e\xf5\x3f\x1f\x4d\xa1\xb1\xae\x42\x25\xb8\x84\x20\x9e\x81\xba\x43\x11\x52\x04\x77\xed\x42\x11\xb0\x92\x40\xbd\x7b\x82\x5e\x54\x73\x9f\xe2\x5d\x86\x24\xaf\x04\xb8\x6f\x6d\x11\x06\xd1\x81\x70\xe5\x06\x4d\x1a\x73\xc1\xfb\x1a\x27\xb2\x89\xa9\x48\xd7\x71\xa2\xf6\xb8\xb0\x9a\x63\x5d\xb9\x6c\x62\x51\xc3\x5a\x18\x76\xd3\x69\x62\x66\x99\x41\x6c\x0e\x40\x29\x8a\x68\x1f\xda\xf5\x25\x5f\x58\xc2\x55\x77\x59\xd8\xf5\xdf\x14\x8d\xec\x9d\xbe\x1c\xe6\xdf\x04\x1c\x36\xf8\x3e\x69\xcc\xfb\x4a\xac\xa5\xcb\x48\xfa\x6a\x85\xc8\xff\x66\x06\x15\x24\xd8\xb1\x1b\xd7\xff\xae\xd9\x9d\x0c\xd4\x5c\x42\x01\x0f\x21\xd3\x6c\xc3\x16\xca\x86\x09\x55\x63\x5b\xff\xaa\x7d\x9a\xac\x57\x2d\xcc\xf3\x15\x3d\x42\xee\x8a\x2b\x12\xba\xa5\x7c\x16\x0b\xd0\xad"}, -{{0xc5,0x4b,0xd3,0x43,0x1f,0x26,0x59,0x28,0x1d,0x31,0xe9,0x3b,0x30,0x78,0x76,0x68,0xbc,0xba,0x6e,0x5e,0xe4,0x7d,0xb4,0x6e,0x50,0xde,0xab,0xe3,0xf4,0x8c,0x9e,0xd8,},{0x1e,0xba,0x6e,0xb3,0xf7,0xf2,0x4c,0xdf,0x80,0xab,0xf8,0xa1,0x9d,0x30,0x8c,0x24,0xf1,0xe2,0x5b,0xa1,0x59,0x70,0xed,0xa7,0x11,0x67,0x07,0xb0,0xf1,0x2c,0xf9,0x32,},{0xdf,0x45,0x41,0xdf,0xf1,0xa9,0x79,0x7f,0xeb,0x61,0x7f,0x98,0xe4,0xb5,0x7a,0xa7,0x71,0x41,0x31,0xee,0x8f,0xf5,0x45,0xed,0x50,0x82,0xe3,0x56,0x8e,0xfd,0x1c,0x39,0x9c,0xdc,0x56,0xf5,0x58,0x29,0x91,0xeb,0x87,0x85,0xfb,0x33,0x86,0x4e,0xef,0x7f,0x55,0x3f,0x3e,0x24,0x82,0x62,0xed,0x54,0x8a,0x1a,0x68,0x88,0xf9,0x2e,0x92,0x0e,},"\x6f\x8c\xdd\x75\xe1\xb8\x56\xbb\xbe\x9c\xdc\x25\x53\x7f\xdf\x7e\x82\x36\xcb\x02\x9a\xcd\x39\x84\x49\x21\x10\xd0\xc3\x04\x41\xd4\x21\x84\xb5\xfb\x18\x3d\xa9\xf3\x14\x03\x78\xdf\xa7\xd7\x4c\xcc\x9e\xf5\x00\x19\x3c\xc9\x57\x9f\xff\xa6\x0b\xd2\xa8\xab\x9e\x09\x58\x15\x00\xcf\x06\xcd\x35\xab\xc1\x71\xd9\xd1\x2c\x65\x80\xd9\x68\x2f\x9f\x49\xfe\x36\xd0\xa3\x17\x72\x38\xfa\x50\xe7\xeb\x4c\x27\xe4\x60\xf5\xe4\x58\x0a\x56\x56\x8a\x19\xe0\x3d\x95\xb0\xff\x4f\x4a\x23\x18\x24\xcd\x2f\x34\x42\xe0\xba\x40\x0b\xc1\x1b\x7a\x98\x9d\x50\x1f\x5d\xf3\x5e\x43\x01\x50\x8f\x72\xa8\x52\x01\x4b\xfb\xf4\x00\x1e\x28\x09\x54\x73\xd9\x65\x9e\xed\x60\x67\xba\xf6\x8f\x92\xbe\xf3\x12\xc0\x9b\x19\xaa\xf7\xc4\xfb\xa3\xd9\x02\xb9\xf6\xcf\x95\x2e\xb9\xb9\xa5\x3c\xa8\xbc\xbd\x04\x2d\x84\x2e\x98\x53\xb6\x72\xa1\xd0\x09\xd8\x23\x83\x8b\xeb\xe5\x63\x7c\x4c\x07\xed\x1b\x19\x48\x55\x4b\x23\xb3\x2d\xe1\xd6\xc1\x16\xf9\x33\xb3\x54\xf2\x8b\xbb\x77\x9f\xa6\x54\x8c\x48\x29\x2b\x61\x2c\x7f\x55\x1a\x75\xfb\xc4\x6c\x02\x73\x6b\xf9\x9e\x9c\x8e\xad\x56\xf0\x5a\xb0\x42\x7a\x6e\xc6\x16\xe3\xdc\xc7\x75\x7e\xfd\xb7\x62\x8d\x4e\x96\x32\x5f\xe0\xae\x25\x4c\xef\x5c\xb7\xa7\x04\xb3\x5a\x92\x0c\xb3\xfa\x2a\x03\xe9\x61\xda\xf3\x71\x82\x1b\xe0\xb3\x0f\x19\xae\x49\x52\x44\x1e\x08\xa7\xd2\x2f\x54\x31\x39\x0a\x5b\xe8\x09\x7f\xd5\x79\x7a\x1a\x62\x97\x66\x4d\xa4\x2c\x20\x08\xd0\x32\x10\x60\xeb\xe3\x18\x1e\xb7\x95\xa7\x28\x92\x58\x08\xda\x78\x67\x29\x3b\x72\x08\xf3\x77\xd3\xa7\x71\x18\x5e\x6d\x2c\x1c\x8c\xe1\x83\x76\xfe\x3c\x0c\x14\x58\xc7\xf5\xbe\x34\xf4\x28\xa0\xd5\x75\x93\x10\x74\xc9\x7c\xbf\xce\x8a\xd8\x13\x13\xec\xca\x73\xa9\xf3\xdb\x43\x4f\xba\xd4\xbb\xbf\xf5\x02\xbf\x72\x97\xe1\x7a\x97\xa8\x86\x42\x11\xe6\x78\x9b\xa1\x92\x03\x6e\xa5\x9a\x34\xd8\x4f\xf2\xa1\x11\x07\x4c\x3f\x23\x73\xb1\x01\x11\xb5\xda\xa7\x89\x56\x0c\xb3\x54\x90\x95\x4c\x88\xea\x00\xc4\x10\xdf\x85\x0a\xd0\x0c\xae\x2f\x28\xe7\x19\xfb\x06\x71\x69\x88\xa9\xbb\x0b\xfc\x6c\x98\x9d\x58\x7e\x56\x85\xae\x88\x3c\x2c\x2e\x74\xdd\xbf\x91\x5c\x98\x56\xaa\xe8\xf3\x28\x8f\xc6\x25\xbf\xb2\xfe\x26\x8d\x74\xf5\x9f\x8b\x7d\x83\x63\x74\x97\x69\x16\x90\x07\xd5\xe6\x7b\x7d\x0b\x8c\x8f\x5a\x9d\x9f\x9c\x7b\x74\x5c\x0a\x42\x94\x76\x2c\xbe\xca\x42\xd5\x38\x49\x61\xe9\x21\xa7\xef\xb6\x5d\xa8\xd1\xe0\x3b\x67\x45\xcd\xf3\x08\x09\x7f\xb1\x3d\x64\xfd\x2f\x8c\x10\xfa\x95\x09\xeb\x2d\x91\x38\x7f\x00\x64\x5c\xa7\xd0\x48\x3b\x2c\xd1\x4c\x20\x6b\x8d\x7a\xe0\xa3\xfb\x7c\x09\xbc\x68\x43\xd1\x02\xad\xcd\xa1\x9f\x8b\xbd\x85\x1e\xb6\x83\xc4\x43\x5c\xeb\x4b\x3d\x23\xd3\x8f\x56\xd4\xd1\x11\x4e\xef\x0f\xc6\xf2\x4d\xf5\x27\x70\xd8\xf1\xf3\xf8\x2f\x47\x20\xe8\x92\xb3\x15\x24\x4e\xf5\x6c\x36\xb2\x3f\xcd\x40\x79\x78\x52\x41\x40\x38\x2e\x11\x74\x0f\xd4\x6f\xe4\x29\x99\x23\xf5\x2b\x88\xb4\xa9\xcf\xf4\xb2\xb4\xb2\x3a\x2e\x76\x0a\xd8\x1c\x78\xba\x87\x69\x31\xd9\xaa\xa4\xbe\xed\x40\xfb\x10\xa7\x99\xeb\x30\xd3\x7f\x75\x47\x78\xba\xc8\x5b\xf0\x63\x1d\x85\x2b\xe7\xd7\x4a\x64\x31\xf3\x84\xa4\x02\x5c\x10\x91\x42\x1d\x67\xa4\xe9\xc9\x4c\x1b\xe3\x69\x0c\x6b\xf8\x1d\x06\xbd\xaf\x32\xfe\xab\xba\xf1\xdc\x26\x3f\x27\x3a\x0b\x9e\xd6\x54\x60\xba\xef\xce\xfc\xf6\xac\xcc\xda\x0e\xdd\x23\xdf\x9e\x05\x12\x8e\x29\xd6\x61\xc4\xb4\x4b\xd9\x2d\x64\x0f\xaa\x85\x3a\xfd\x83\x70\xe5\x63\xb4\x0a\xe0\x14\x9a\x14\x28\xe0\x6e\x3d\xd8\xe6\x6b\x79\xda\x21\xcc\x75\x3d\xdc\x47\x6e\x3d\x76\xe2\xf3\x6f\x2b\x6c\x6b\xc1\xb6\x50\x87\xd5\xf8\x6c\x8a\xc3\x54\x71\x1a\x8c\x08\xf3\x48\x6e\x47\x9d\x6a\xe9\x43\xf8\x84\x63\x32\xd4\xe5\xb4\xbb\x2e\x82\x57\xe3\x08\x3d\xf4\xf8\x1d\xd4\xf0\xc1\xee\x1d\x97\x18\x21\x66\x16\x1a\x18\x59\x7e\xe0\xb9\x59\xde\x1c\x45\x59\x1a\xbf\x7c\x51\x03\x3d\x7c\x66\x35\x2d\xee\xb6\x82\xe7\x77\xae\xae\x2f\xa8\xd3\xa7\x7f\x47\x0d\xb7\x8d\xdc\x1b\x1f\xc8\x28\x40\xc4\x06\x57\x76\xd9\xbf\xca\x9d\x39\x2d\x92\x88\xee\x91\x32\xaa\x3e\x4f\x2d\x19\xd0\xd9\x3e\x01\xb6\x66\xf3\x64\x7a\xba\xf2\x25\xc2\x92\x41\x9c\x8a\x82\xeb\xa3\xe1\x1a\xb1\x03\x84\x6f\xcd\x49\x35\xf4\x12\x41\x47\x7c\x0f\x15\x2b\x79\x65\xad\x54\xbb\x72\xbc\x3d\xe2\xe0\xb7\x9d\x62\x25\xe8\xfa\x7a\x62\x86\xb5\xfc\xcb\xb3\x58\x22\xe8\x0c\x8b\xfe\xa7\x4c\xb4\x8a\x22\xd2\x41\x38\x53\x95\xc2"}, -{{0xea,0x60,0xda,0x01,0x79,0xbc,0xaf,0x6b,0x21,0x81,0x42,0xb1,0x11,0x90,0x46,0xff,0xe6,0xd8,0x5a,0x74,0x1b,0x0d,0x16,0x62,0x30,0xbc,0x6d,0xe3,0x30,0x4f,0x67,0x73,},{0x50,0x6b,0x2e,0xbb,0x49,0xbd,0x9b,0x9f,0xf6,0x6e,0x6b,0x7b,0x1f,0xab,0x96,0x68,0xcb,0x18,0x1b,0x4f,0xb5,0xe4,0x34,0x3d,0xdd,0xd3,0xf8,0xa9,0xd7,0x02,0x03,0x1c,},{0x27,0xfb,0x6b,0x5f,0x06,0x52,0x8a,0x64,0x19,0x8a,0x3e,0x7d,0x67,0xc7,0x38,0x84,0x0a,0x8c,0xff,0x4b,0x48,0x2b,0x4d,0x52,0x4b,0x12,0x2d,0x17,0xd2,0xae,0xbc,0xc0,0x38,0x9b,0xe2,0xc6,0xe2,0x8e,0x2c,0xdf,0xc4,0x84,0xc1,0x8d,0xe4,0x25,0xdb,0x56,0xcd,0xfa,0x56,0x1c,0x50,0x7c,0xd9,0x70,0x60,0x2d,0x3a,0x38,0x5d,0x3a,0xea,0x0f,},"\x61\x2d\x6e\xf6\xe4\x34\x9f\xfa\xe5\x16\xe9\x83\xe8\xfa\x7b\x52\xd9\xfd\x13\x42\x82\x24\x0d\x95\x14\x38\x24\xbd\x4a\xae\x03\x23\x4b\x76\xa8\xcd\x6d\x40\x68\xcf\x00\x9e\x48\x1c\x26\x85\x36\x1c\x75\x50\x42\xc4\xe6\xab\x87\x03\xec\xbf\x8f\x02\x0c\xf5\x73\x9a\x4c\x2a\x03\xc3\x73\x1e\x9c\xf7\x5a\xee\x25\x96\x61\x53\xb9\x71\x15\x15\xc6\xc3\x9a\xfa\x95\xf2\x21\xac\x33\x95\xb0\x89\xc9\x7a\xc9\xb5\x14\xe1\x7d\x55\xf7\x96\xa3\xec\xc1\x35\xfa\xaa\xee\x90\x7a\xab\x10\x29\x64\x7b\x48\xac\x81\x74\x9b\xab\x26\x62\x7c\xf7\x09\x5d\x74\xc2\xfc\xee\x35\x67\x1c\x8b\xb4\x60\x53\xf5\x15\x1b\x0c\x2e\x5d\xab\xe0\xf2\xd6\xaa\x20\x41\x33\x05\x02\x0b\x2a\xfd\x9e\xe3\x38\x7b\x2c\x9e\xd0\xbc\x3f\xe2\x90\x2a\xf4\x10\x0c\xec\x23\x32\x7b\x0f\x1e\x4c\xa3\x9e\xf6\xea\xf6\xfd\xf5\xd5\xac\xf9\x3f\xc8\x68\x53\x6d\x8c\xba\x40\x17\x69\x32\x9f\xbe\x93\xef\xfc\x7e\xe6\xbf\x93\xa6\xe5\x88\xbd\x55\x1e\xaa\x51\x28\x53\x95\x2c\x81\xb2\x45\xe5\xd2\x29\xd2\x94\xe4\x13\x70\xb8\x67\x80\x86\x67\x88\x7a\x6f\x9e\xba\x2a\x8d\x56\xa7\xa7\x04\xe6\x6b\x1c\x02\xf9\x6e\x73\x89\x5f\x48\x3e\x44\xa5\xc5\x66\xcb\x1a\xf2\x65\x73\xbf\xe2\xaf\xce\x06\xb1\xfb\x58\x77\xe5\x1e\xf3\x12\x6a\x3f\x21\x0f\xbf\x21\x3e\xd6\x5d\x5c\xa4\x6c\x46\xce\x4a\xa9\x45\xbd\x8c\xa6\x11\xe3\x83\x62\x50\xf5\x64\xf7\xea\x35\x42\x39\x82\xf9\x70\x5f\xcd\x6b\xef\x46\xae\x16\xcb\x0f\x6b\xc9\x12\xc3\xf2\x86\x42\xb8\xd8\x77\x75\xb8\x18\xe4\xe4\xe8\x06\x11\x67\x89\x9b\xd2\x7a\x7e\x2f\xb8\x18\x7e\xe9\x91\x7d\x2d\x58\x6b\xf9\xd4\x99\xe8\xfa\xbc\xa8\x3d\xdf\x58\xc7\x43\x7e\xaa\xce\xc4\xf4\x44\xfb\x2b\xf7\x45\xdc\xcd\x8c\xae\x38\x94\x45\x71\xde\xde\x20\x37\xdc\x41\xf0\x81\x8a\x3d\x91\xe3\x02\x0a\x72\x74\xc6\x67\x42\x47\x87\x60\x83\xd0\xe3\x97\x46\xc9\x68\x40\x61\xbf\x74\xad\x58\x84\x36\xce\x1b\x76\x3d\xbf\x4b\xfc\xf8\xde\x6e\x35\xc5\xa7\x62\x66\x75\xc1\x27\x29\x2b\x21\xdf\x3c\x16\xf8\x10\x63\x32\x2a\x75\xf3\x43\x88\x86\xf1\xf0\xce\xbf\xc1\xa9\x6f\x41\x38\x4c\xbd\xd8\x61\xb0\x4f\x51\x9f\xf6\xa9\x34\x4d\x94\xf3\xd3\xa0\xab\xa8\x40\x9d\xfc\xf1\x8d\x01\xf2\xb5\xb4\x55\x17\x16\x39\xee\xa7\x7d\xee\x70\x6e\xa8\x3d\xcd\x2b\x8b\x1f\xc5\xec\x0d\x74\x07\x61\xa5\xf0\x5f\x7e\xc8\xd8\x7a\xd1\xf2\x92\xa5\x0c\x8b\xae\x0a\xd3\x2b\x03\x41\x9a\x95\x0d\x9f\xe3\xb3\xec\xc4\xd8\xd3\xaa\x95\xe0\x2b\x51\xb1\x83\x1d\x83\xea\xde\xaa\x44\x23\x86\x35\xf9\xc6\x5e\xfe\x2f\x67\x44\xa7\x0b\x9a\xe4\x1e\xf1\x5d\x97\x90\x8c\x05\x33\x93\x44\x12\xf7\x95\x83\xd0\xe9\xb3\xd7\x06\xa1\x28\xe8\x8f\xb5\x1e\xed\xb6\x5e\x46\xd8\xa2\xb3\x8b\xbd\xd6\x45\x55\x54\x96\x7a\x8d\xc0\xc6\x8b\xdd\xfe\xae\x0f\x8f\x72\xf0\xb8\x86\xc3\xc7\x41\xfa\xc4\xf9\x1e\x5c\x49\x1d\xba\xe9\xda\x45\x94\x83\x6c\xf1\xd9\xfb\x6e\xe1\x30\x02\x50\x89\xae\xd3\x50\xef\x24\x7b\xc9\x88\x7a\x20\x50\x15\x9d\xde\xd1\x42\x8f\xfd\x9b\x07\xb9\xec\x2e\x3d\x4b\xbd\xc2\xdd\xb5\x4e\x87\x3b\x63\xf2\x47\x52\x33\xe1\x91\x33\xa1\x4b\x66\x58\x50\x94\x57\x00\x81\x86\xd6\x22\x59\x95\xa9\x67\x26\xb5\x29\xf4\x42\x81\xaa\x24\xfe\xfd\x1c\xff\x8f\x81\x5d\x93\xa5\x98\x69\x31\x66\x22\x90\xb3\xee\x16\x83\x3c\x60\xf0\xaf\xce\xf2\xcb\xc0\x00\x62\x3f\x39\x31\x90\x9c\xa9\x76\xa0\x94\xe2\xb0\xfd\xb7\xdc\xf7\xc4\x85\xe1\x49\x88\xa3\x6f\x19\xb6\x64\x25\x38\x5f\x56\x32\xce\xf6\x5d\x1d\x34\x14\x62\x3a\xe3\xee\x81\x6e\x76\x3a\x5f\x60\x64\x66\x62\x2b\xe6\x60\x21\x14\x50\x29\x51\xcf\x0c\x09\x7c\x16\x48\xa7\x2e\x2c\x43\xd9\xaf\xa9\x68\x9f\x2c\x3c\xfe\x02\x6c\xdc\xe3\xbd\x1b\xf9\xeb\xf7\x77\x56\x2e\xcd\x8f\xf1\xb0\xd7\x75\x30\x6d\x90\x04\x43\xf3\x0a\x84\x33\x10\xb8\xde\x6a\x38\xff\x10\x8b\x72\x39\x13\xd7\x89\x9b\x9f\xbe\x7c\x3d\x76\x6e\xf8\xbd\xfb\x6d\x8b\x0b\x52\x95\x6c\xb1\xce\xc9\x93\x6d\x70\xb4\x87\xc0\x14\x40\xa8\x42\xb2\xfa\xbe\x38\xe7\xb8\x85\x1a\x38\x7d\x35\x8b\xe7\xef\x12\xa7\xe4\xf2\xb5\x27\xe8\x30\x90\xd6\x7e\xb0\x13\xc9\xc2\xcf\xd3\xde\x5a\x1a\x3f\x99\x74\x8a\x41\xf4\x81\x9d\x90\x36\xe5\x00\xc5\x04\xc9\x88\xbf\xd2\x4f\x61\x7d\x6e\xbd\xca\xb2\xdd\xea\xa6\x15\x79\x41\x4f\x36\x0b\x46\x9a\x33\xa6\xde\xd9\x6b\xa1\xd8\xc1\x40\xc4\xff\xc9\x49\x90\xd8\xad\xf7\x8c\xd3\x87\x80\xbd\x68\x66\x3d\x1a\x0e\xe3\x3f\x53\x7c\xdf\x89\x2d\x56\x2e\x82\xdc\xd1\xd9\x12\xca\xd3\x8d\x65\x56\x7d\x29\x14\x06"}, -{{0xb6,0x2c,0x24,0x18,0x78,0x27,0x35,0x13,0xe0,0xbf,0x6f,0x33,0xd2,0x10,0x43,0x65,0xb2,0xce,0x9c,0x5a,0x1b,0x78,0x60,0x58,0xe9,0xc5,0xb4,0xd1,0xd1,0x92,0xf8,0x7f,},{0xbb,0xf6,0xfc,0x51,0x98,0xf3,0xfb,0xa5,0xab,0x00,0x7f,0x8a,0x63,0x2d,0x28,0xd1,0xaf,0x86,0x5d,0x29,0x0f,0xa0,0xa9,0x0f,0xaa,0x9a,0x9b,0x5b,0x9c,0x13,0xf3,0xfb,},{0xc5,0x90,0x39,0x58,0x7b,0x38,0xdc,0x14,0x1e,0x05,0x5a,0x93,0x85,0x01,0x04,0xd6,0x29,0xe3,0x80,0x70,0x5b,0x8f,0xc9,0x18,0x84,0x7c,0x5e,0x2a,0x35,0x2d,0xa3,0xa0,0x2f,0xce,0x7f,0x71,0x99,0xf4,0xae,0x2b,0x1e,0x2a,0x59,0x48,0x34,0x18,0x93,0x2e,0x18,0x5f,0x7e,0x45,0xb5,0x05,0x0c,0x64,0x2c,0xec,0xc7,0xe7,0x81,0x99,0x85,0x07,},"\x26\xa3\xc2\x6a\x5a\x18\x9c\xad\x40\x7c\xba\xa3\xa6\x86\x7a\xc0\xa2\x60\x88\xc7\x5f\x9d\x0f\xa1\x9b\xd5\x02\x74\xce\xc5\x75\x5a\x49\x71\x09\xa4\x73\x28\x4d\x6f\xc8\x1a\xd4\xb9\xec\x29\xfa\x7e\xc9\x76\x4f\xd3\x09\x9f\x06\x0e\x36\x83\x65\x52\xff\x24\x13\xe3\xd5\x09\x5f\xe0\xb1\xa8\xbf\xcf\x67\xee\x06\xaa\x90\x32\xe7\xbb\x32\x49\x69\x80\x47\x71\x4d\x28\x14\x15\x27\x3c\x98\x34\xad\x9e\xb6\x65\xa7\xd9\x72\x20\xe7\x2d\x9c\xa7\x3f\x31\xaf\xa7\x73\x86\x75\xba\x31\x62\xef\xef\xe7\x47\x9a\x5b\xc4\xbc\xe2\xe8\xb7\xaf\x47\x41\xd7\x03\xdc\x9b\xbd\x60\xb4\xcf\x4b\x90\x87\xf6\xcf\x86\xcf\x53\xae\xd0\x2b\xf4\xca\x6a\x18\xf6\x07\xcb\x52\xa3\x03\xd7\x8e\x85\xad\x88\xfd\xfc\x86\xdc\xb7\x18\x77\x27\xb0\x3b\xe2\x27\x74\x5b\xea\x74\x4f\xd0\x06\x52\x5b\xc5\x9a\x4d\xdd\xab\x91\x5c\xef\x40\xa8\xf3\x08\x02\x91\x3b\x79\x13\xea\xf9\x74\x33\x65\x52\xe2\xf1\x45\x6a\xd8\x03\xdc\x58\xc9\xb4\xb1\x8e\xfa\xf7\xf7\xe3\x57\xe2\xcd\x77\xd1\x38\xd9\x00\x80\xe2\x96\xd1\x36\x4a\x2f\x32\x4d\x3e\x0d\x6e\xdc\x20\xb8\xbd\xaa\x9d\x2e\x87\x1f\x5e\x7b\x05\x1f\xb6\xfc\xdb\x55\x95\xf2\x1d\x3f\x8d\xe2\x9f\xb7\x86\x78\xfa\x47\x9e\xaa\x32\x57\x9c\x78\x4d\x51\x3a\xc5\xf8\x36\xd9\x54\xd0\xd3\xfc\x0e\x5f\xc8\xa6\xee\xab\x90\x20\x2b\x4c\x4a\x2b\xec\x24\xcf\x63\xea\x67\xc4\x70\x09\x62\x18\xcd\x43\x1e\x88\x31\x05\xfc\x9c\x27\xf9\xea\x77\xc1\x8e\xda\x69\xbc\x00\xa2\x24\x2b\xd4\x20\xf0\x95\xc9\xb9\xa9\x2d\x95\x6c\xcc\x5a\x85\x72\xb0\x57\xa7\xfe\x17\x3e\xeb\x2a\x31\x66\xcb\x20\x89\xd1\x13\xa8\x16\x46\x2b\x25\x80\x5b\x8a\xba\xff\x5b\x0b\x22\x87\xc5\x08\xec\x2b\x8c\x34\xb2\x19\x5c\x33\x28\x70\xd3\xcc\x39\x60\x17\xa1\x6b\x9e\x0d\xa6\x18\x2d\x07\x1d\x3b\xf3\x63\xd3\xf1\xe7\xb7\xda\x11\xd7\x11\x25\x0a\x58\xaf\xd7\x4e\xd3\xe3\x15\x8d\x47\x18\xba\xd4\xd2\x74\xbb\x34\x44\xcf\xc3\x18\x07\x4b\x53\xbe\xba\x44\xa2\xa3\x4f\xf8\xeb\x72\x6e\x4a\x1d\xaa\x91\x10\x51\x62\x16\x51\x89\x8b\x88\x71\x69\xf6\x2b\x9c\x0f\x40\x20\x48\x3e\xf5\x44\xf8\xf5\x72\xfa\x6a\x66\x40\xa4\xcf\xfc\xe9\x76\xcb\x70\x24\xf8\x47\xbd\xc9\x5d\x1d\x7c\xe6\x53\x50\x5d\xeb\xfc\x69\x88\xed\x28\x9d\xd4\x7a\x9e\xb2\x61\x25\x9e\x3e\x65\xe4\x5f\xc9\xd7\x14\x94\x69\x35\xcd\x8e\xa1\x3b\xc6\xdb\x5e\xaa\xb9\xe8\xb1\x0d\xae\x0f\xdd\x69\x79\xc2\x03\x5c\xfb\x80\x98\x25\x2f\x22\x05\x44\x3b\x80\x88\x16\xbf\x77\x87\xb7\xf1\xe7\x8b\xc9\x8a\x72\x85\xe7\x33\xd4\x5f\xc4\x61\x0c\x20\x97\x7c\xa3\x22\x98\x89\xbb\x8c\xd2\xb6\x94\xce\x9e\x3f\xe7\x83\x03\xaf\x83\xe1\x06\x42\x25\x42\xfb\x79\x61\xd3\x2e\xb1\xd2\xc5\xfb\xe6\x07\x51\x67\x4b\x07\x47\x73\xee\x06\x16\xe0\x29\x73\xf6\xa7\x4a\x3a\xe4\x66\x4a\x26\x50\x91\x5a\x3e\x10\x49\x3b\x9e\x66\xa3\x9f\xa5\xc8\x9c\x61\xd4\x47\x35\xf1\x07\xd3\x37\x57\xae\x67\x9b\x43\xa8\xd4\x3a\x01\x75\x7a\xe1\xf3\x27\x9e\x86\x24\x42\xe1\x50\x71\x55\x50\xee\x82\xe4\x9c\x0d\x49\x43\xfa\xf1\x3f\x22\x79\x1f\x0e\x66\xf2\x4a\xc5\x0a\xb3\xc0\x03\x85\x2b\x21\xe1\x5b\x2f\x00\x6e\xdc\x2c\xd6\xa8\x79\xc4\x76\xab\x5b\x35\x2e\xb1\x09\x9d\xad\x4c\x50\x37\x24\x00\xfa\xa5\x49\x8d\x78\xc6\xb8\x57\x03\x4c\x25\xca\xf7\xb9\x33\xfa\xf6\xbd\x7c\x59\xfa\x3d\xa5\x73\x97\xb6\x03\xde\x9c\xb9\xd8\x0e\x51\xf7\x99\x7b\xaa\x46\x2a\xcd\x53\x7e\x2c\x41\x94\xc7\x6c\x7e\x0b\xe6\x51\x2b\xce\x4d\x63\x66\x0b\x36\xc7\xcc\x46\x63\x1f\xb9\x67\x1a\xd8\xc5\xd2\x8e\x2f\x2e\xe2\xed\xce\x81\x95\x44\x21\xb8\xa3\xd9\xff\x6f\x66\x69\x9f\x4b\xce\x88\xbc\xb8\xef\x19\x2c\x26\x2a\x74\xab\x7e\x19\x1e\xee\x91\x01\xa2\x8d\x4b\x66\x28\x2b\x51\x22\x09\x3d\x14\x1c\x64\x96\xc7\xab\xa4\xd3\x52\xe4\x72\xee\x74\x40\xe0\x5a\xf6\x0d\xa0\xcf\xc9\x3e\x30\x36\x42\xba\x8f\xb8\xe5\xc5\x68\x68\x7a\xbd\x63\xaf\xb3\xed\x6a\x32\xb6\xda\xe5\x6a\x7e\x5d\x73\xde\xba\xf4\x1d\x35\xca\x36\xad\xb9\x7a\x22\xc0\xad\xbe\x71\x8b\xec\x1f\xa5\x19\x98\xde\x9b\x4b\x96\xa7\x9c\x5b\x96\x55\xb0\x16\x5d\x5e\x1b\x9a\x8c\xc5\x52\xe8\xc9\x32\x9e\xde\x58\xdf\x74\xc6\x7b\x2b\xa1\xa8\x42\xfd\x3e\x81\x58\xc1\xfe\xa3\xa9\x9b\x56\xa2\xc2\xa9\x62\x07\x85\x3d\x26\x02\x2c\xec\x17\x0d\x7e\x79\x94\x4d\x2f\x56\xaa\xb1\xf1\x91\xbf\xd4\x8d\x72\x54\x90\xca\x82\xb8\xd9\x06\xf0\x68\x0e\x69\xee\xb9\x57\x57\x74\xfb\x9d\x60\x45\x13\xfb\xc2\x6f\x5d\x30\x3b\x68\x85\xca\xc0\xbf\x8e\xfe\xe0\x53\x8f\x92"}, -{{0x0f,0x77,0xf7,0x7a,0x1c,0x7e,0x04,0xbd,0xa8,0xe5,0x34,0xf4,0xe3,0xef,0xf9,0xa2,0x38,0xcc,0x14,0x87,0x6b,0x7e,0x3e,0xca,0x8b,0xed,0xe1,0x92,0x3a,0x33,0x64,0x06,},{0x10,0x45,0xea,0x9f,0xe2,0x14,0x58,0x3a,0x0c,0xdb,0xc4,0x94,0x93,0x2b,0xc4,0x4a,0xfe,0xeb,0x08,0x0b,0xec,0x48,0x5c,0xc2,0x34,0xfd,0xdc,0xff,0x13,0x9c,0xce,0x00,},{0xb2,0x0b,0x9c,0x42,0x46,0xf0,0xd2,0x97,0x01,0x38,0xaf,0x7d,0xc9,0xaf,0x62,0x9b,0x68,0xfb,0xc3,0x7d,0xf8,0x7a,0xfd,0xca,0xdc,0xb5,0x45,0xc1,0x76,0x83,0x76,0xa0,0x9c,0x3b,0xab,0xc3,0xeb,0x1a,0xf3,0xb7,0x51,0x98,0x52,0xf7,0x5f,0xab,0x1c,0x9c,0x11,0x9c,0x66,0x2c,0x58,0x77,0xfb,0x2f,0x72,0x99,0xca,0xb5,0x7f,0xad,0x3d,0x0e,},"\x0e\xcb\x74\x6d\xbd\xb0\x16\x14\x21\xaf\xeb\x7a\xde\xa7\xa3\x7c\x2e\xa4\x40\x8a\x59\x2c\x9d\x78\x1e\xd6\xac\x6f\x4e\xe5\xcc\x65\xd5\x27\x0e\x4c\xf2\x76\x32\xf7\xc5\xc1\x33\xd4\x39\xb7\x8d\x1f\x71\xaa\x6d\xd8\x07\x13\xd9\x0b\x15\x1e\x19\x12\x1b\xfa\x87\x71\x0e\x84\xa4\x85\x0a\x3b\x5b\x02\x65\xba\x26\x03\xd0\x71\x6e\x9b\x7e\x11\x22\x10\x9c\x39\xc6\xf1\x02\x7f\xce\x18\x79\x8c\xbb\x4f\x6b\xc5\xe4\xd7\xac\xa4\x70\x46\x90\xf5\xc9\x81\x51\x08\x71\xc3\x13\x59\x57\x98\x33\x86\x81\x10\x7f\x2b\x57\x94\xd4\x6f\x6e\x0b\xde\x2c\xd0\x64\xb3\xb1\xfc\x00\xca\x47\x18\x8b\xbb\xc1\xf4\xa0\xce\x30\x5c\xc6\xd8\xa8\x96\x92\x0e\xb9\xeb\xae\x57\x9f\xd3\x38\x5f\x8f\x1f\x35\x97\x62\x88\xf4\xc5\x8f\xfc\x47\x60\xf3\x59\xb0\x03\xc8\x72\xe9\xa2\x40\x55\x35\x5e\xa9\x58\x5e\x95\x10\x69\xdc\xa2\x5f\xd0\xcc\x0b\x9d\xb5\x2a\xae\xaf\x19\xd4\x3f\x2e\xab\x4f\x83\x56\x03\xad\x12\xd2\xdc\x49\xb3\x10\x25\x6b\x94\xbe\xd5\x48\x96\xa1\x6b\x69\xb0\x9c\xb4\xc8\xff\x5c\x23\xcc\xe5\x59\x3d\x87\xad\xe2\xa8\x2a\xda\x50\x85\x9e\x15\x44\xc1\x86\x18\xa6\x5c\x00\x7e\xf4\x24\xc9\x85\x4a\x17\x5b\x6e\x6c\x0e\x64\xb2\xc8\xeb\x8a\xd4\xd2\x8b\x97\x7d\x68\xe7\x81\x69\x91\x51\x98\x97\x53\x94\xd3\xb9\xb2\x69\xca\xb0\xd3\x26\x1b\x2b\x56\xcd\x2c\xc4\xbd\xdb\xd4\xf1\x43\x9e\x0d\xbe\x2c\x9b\x3f\x3f\x75\x14\xed\xac\x5e\xbb\x46\x22\xb9\x2a\x69\xa8\x40\xa9\x02\x85\x50\xb2\x21\xdb\x59\xdd\xfb\x00\x13\x96\xf8\x63\x92\xa1\x7f\x08\xcc\xb1\x94\xcd\x9e\x1a\x00\x81\xd7\xdd\x9c\xca\x23\x57\xfe\xb8\xb7\x95\xe5\x17\x02\x9f\x79\xc8\x2a\x3b\xe6\xf9\xa0\x31\xdd\x1a\xf1\xe7\x9e\x49\x82\xbf\x8e\x76\xb3\x10\xf9\xd3\x55\xef\xcd\x5b\x1e\xfa\x9f\x35\x9c\x17\xcf\x3b\x51\x0d\x51\x3e\x8c\xd5\x78\x6a\x0d\x34\x45\xdc\x59\xa8\x43\x3a\x46\x48\x86\x87\xb0\xf5\x8b\x1b\xd6\x56\x7c\x2a\xf4\x87\x3b\x51\xfc\x84\x5e\x76\x7e\x24\x30\x05\x19\x2f\x8f\x06\x74\xf2\x81\x26\x5a\x55\xd7\x6c\xea\x32\x22\x60\xc9\x32\xce\xa6\x71\x7a\xdb\x98\xa2\xdd\xa8\xc6\x98\xe2\xe8\x92\x55\xfe\xb7\x7d\xa7\x64\x81\x67\xbc\x1e\x58\x87\x7f\xeb\x72\xd1\xd1\x4b\x0c\x30\x4f\x07\x37\x2d\x95\x56\x75\x23\x7c\x49\xf7\xa6\xdb\xc9\x15\xe6\x81\x4a\xba\xe6\xcc\xe4\xca\xf9\xf4\x80\x87\xe9\xdf\xb2\x82\xd8\xf3\x40\x37\x7c\x1e\x29\xc6\x73\x1c\xcc\x26\x67\xda\x66\x95\xb7\x12\xbe\x03\x12\xd8\x65\x11\x19\x34\xf1\x68\xd5\x54\x43\x65\xdd\xae\x27\xab\xc6\x4a\xef\xbc\xb3\x22\xdb\x7d\x97\xd9\x0d\x95\x7a\x63\x7b\xd8\x26\xc2\x27\xe9\xeb\x18\x0b\x45\xa4\x31\x62\x6a\x6f\xd8\x90\xc0\xe5\xf4\xed\x7e\x85\x64\x74\x75\x2f\x80\xb5\xae\xf6\xe7\x3e\xfd\xaa\x6c\x2c\x45\x1b\xd7\x4c\x1e\xf4\x66\xca\x3a\xaa\x25\x73\xbb\x52\xcb\x2b\x1c\xa9\x6a\x1b\x57\x44\x03\xce\xae\x1c\xf0\x5f\xfc\x53\x43\x0e\x1e\x4c\xd5\x59\x3b\xd1\xef\x84\xbc\xbf\xe2\x19\xf0\x81\x60\xd1\x66\xf2\x73\x1d\x99\xb8\xd7\xa3\x2b\x12\x99\x1f\x77\x77\x5a\x26\x7e\xc0\x82\x97\xec\x51\x2d\x7b\x72\x43\x56\x32\x52\x5c\x04\x00\x0f\xb0\x0a\x79\x3f\x8b\x5f\x8f\x37\x47\xb5\x53\x59\xdf\x21\xb7\xe2\xc4\x9f\x2b\x0b\x9a\xe0\x82\xaf\xc7\x0a\x14\x68\x71\x37\x0b\x8d\x50\x08\x6d\xe0\x0f\x94\x48\xbe\x89\x02\x17\x4b\xa2\xcc\x85\x1f\xa3\x79\xdd\x70\x31\xca\x45\x7a\x88\x69\xaf\x4b\x6c\x27\x29\xda\xc5\x19\x55\x6b\x8b\xb4\xab\x51\x9e\xf1\xbb\x02\x4e\xa8\xb7\xf0\x17\x71\xc9\xaa\xb7\x48\xe5\x73\x81\xa0\x19\x2a\x6e\x39\x8c\xbe\x6d\xd9\xf3\x67\xcc\x7b\x33\x54\xf8\x3b\x79\xbc\xda\x46\xb7\x93\xa4\xad\xa8\x55\x49\xc8\xd6\xbd\xd6\x16\x81\x24\x36\x2f\xf9\x08\xaa\x1a\x0c\xb7\x8a\xa3\x30\xc4\x2d\x5a\x5d\x48\x12\x35\xac\xac\x3a\x91\x9b\x96\x9c\x50\x98\x72\x66\xd4\x04\xd1\x5d\x0e\x70\x6f\xd9\x00\x76\x34\xf6\x9e\x13\xc5\x6e\xc4\x71\x33\x88\x4f\xca\xdd\xc1\x6b\xee\xee\xd1\x9e\x0c\xd9\x17\xaa\x49\x63\x67\x86\x7d\xfc\xea\x27\x4e\x1a\x47\xda\x77\x4f\x3c\x93\x63\x02\x1e\x7c\x8d\x6b\xf8\xf0\x00\x53\xfa\xcc\x11\xcb\x68\xa9\xd6\xe1\xfc\x2d\x6d\x19\x17\x5d\x63\x24\xff\x7c\xa6\xc2\x30\x58\xb8\xb6\x93\xd8\xfd\x4e\x0b\x51\xdc\xbb\x11\x35\x43\xf2\xfc\xc0\x45\x2e\xb9\xd9\x67\xac\x0f\xa9\xb2\x3e\x9e\x0b\x1d\xa8\xd8\x3a\x3c\x1f\xc9\xe9\xec\x97\x1f\x0f\x67\xfc\x74\x5b\xb1\x73\x76\xbc\x46\x24\x5f\x52\x8c\xb6\xe5\xfe\xe1\x1b\xcd\xda\x86\x7b\x7f\x79\x01\x9c\xf9\xdb\x59\x18\x58\x23\x0a\xec\xb4\xd1\xe9\x3d\x16\x7c\xd8\x6b\x42\xdd\x87\x9a\x13\xfa\x0e"}, -{{0xc5,0xa5,0x05,0x34,0x77,0xae,0x31,0x15,0x8e,0x74,0x69,0xdd,0x15,0x04,0x86,0x76,0x50,0xd4,0x6f,0x15,0x89,0x06,0x7f,0x5c,0xd8,0x81,0xca,0xf2,0x5c,0x26,0xcb,0x21,},{0x70,0xf8,0x5d,0xb9,0x80,0x7b,0x26,0xfc,0xf3,0xe6,0x69,0x0b,0x91,0x72,0x4f,0x7a,0xe3,0xd2,0x0e,0xc3,0x60,0x4a,0xb7,0xd6,0x30,0x8d,0x90,0x94,0x30,0x8b,0x2d,0x59,},{0xf5,0x19,0x1b,0x44,0xbd,0x6c,0xc3,0xea,0x28,0x17,0x71,0xdf,0x12,0x54,0x9b,0xa2,0xbe,0x22,0x8b,0x51,0xeb,0x79,0x1b,0x9e,0x5e,0xd2,0x81,0x5f,0x86,0x2a,0xa6,0x30,0xb5,0x69,0x67,0xcd,0xef,0x8b,0x6a,0xf0,0xb9,0xd2,0x1a,0xb8,0xc9,0x7a,0x6d,0xff,0x68,0x1c,0xce,0xd9,0xf5,0x01,0x97,0x13,0xd4,0x35,0x7c,0xb3,0xe5,0x4c,0x0d,0x08,},"\x85\x71\xff\x39\x03\x48\x6a\x43\xa6\x12\x6c\x32\x3e\x7b\x3a\x74\x14\x1d\x13\x85\xd4\xbd\x70\x3f\x19\xe2\xd1\xb6\x4b\x50\x28\x1d\x27\x16\x8a\xe3\xe7\x69\xc6\xdd\x9d\xf7\xd9\x78\x64\xfb\x37\x82\x2f\x00\x21\x85\x2e\x31\x68\xab\x7d\x84\x5a\x65\x45\xed\x0c\x37\x7d\x9f\x7c\x04\x8a\x2b\x96\xe8\xdc\xf4\x45\x77\x96\x84\xa0\x58\xc2\xb9\xc2\x1a\xc6\x8a\x0c\x34\x1d\x1d\x6c\x09\x81\x45\x64\x57\x45\x8e\xb7\xce\xbf\x66\x67\x87\x40\x77\x7e\xca\x26\xe0\x1e\x1c\x8f\x53\xb5\xd4\x75\x6c\xc5\xf0\xb9\x0f\x0c\x5d\xb0\x53\x93\xcd\x4b\x8e\x44\xf6\x81\x0c\xaa\x5a\x11\x6a\x33\x57\x77\x24\x39\x5d\x41\x3a\xf6\x19\x63\x2a\x6f\xed\x14\xe2\x15\xc2\xf1\x9d\x10\x5c\xe2\xbf\x14\x98\xe6\xd2\xab\x4f\x65\x0f\x61\xba\x5c\xf6\xd0\xc7\x3b\xbb\xde\x98\xe3\x04\x29\x91\x0a\x4e\x67\xdf\xbc\x71\x7c\xb0\x91\x18\x2d\x59\x70\x58\xb5\xd7\x65\xd0\x97\xe6\x87\x58\x31\xb5\x88\xaa\xeb\x3e\x73\x27\xe8\x56\xb4\x2f\xa9\x83\xfd\x25\x4e\xf1\xf9\x18\xb0\x43\xd1\xdd\x3d\x7b\x7e\x30\xb3\x15\x38\x6e\xec\x91\xe7\xf9\x4d\x59\x8f\x4b\xeb\x3b\x27\xb4\x2f\x4e\xe1\xfb\xf7\xaf\xb4\x86\xbd\xcc\x60\x81\xcc\xb8\x67\xf0\x41\x11\x04\x4f\x4b\xbb\xe3\xc8\x12\x2e\xde\xad\xef\xa9\xd6\x93\x90\x6e\x0d\x6e\x13\x3b\xf6\xf2\xda\x61\x58\xfe\xed\xbd\xa0\x24\x41\x0f\x12\x08\x6e\x7a\xcc\xf1\xc6\x8e\x15\x57\xf0\x0c\x14\xe9\xc7\xea\x76\xa5\xed\x13\x37\xa0\x54\xac\x2c\x94\x9c\x05\x97\x7e\x03\x02\x74\xf6\xa4\xf2\xa6\xb3\x0a\x15\xc5\x70\xec\x94\x33\xf7\x4f\x47\x52\x80\x87\xc9\xce\x9a\x62\x92\x95\x1c\x54\x35\x49\x96\xfb\x28\x3c\x0d\xc4\xcf\x33\xc0\x01\xbc\x96\x87\x5e\xa6\xe1\xf4\x6f\x83\x7f\xf1\x8d\xd9\x54\x5f\xb9\x93\x46\x55\x34\x2b\x12\xc2\x99\x0b\x9f\x1c\x6f\xf4\xd6\x64\x89\xd6\xae\xdc\xe7\x5c\x7c\xb0\x3a\xc1\x34\xbf\xd3\x9b\x18\x1d\xfb\x7f\x9a\x97\xce\x73\x7f\xe5\x70\xad\x5f\x81\x34\x59\x39\xa6\xde\x5a\x40\xa3\x3a\x0e\x44\xbf\x95\x75\x03\xd5\xca\x02\x83\x51\x2e\x57\xfb\xa8\xa3\xa6\xf2\xc3\x90\x68\x7b\x1b\x77\x08\x67\x6e\x0f\xd0\x3b\x7c\x18\x8d\x45\x61\xc1\x87\x91\x63\xea\xf2\xb5\x96\xdd\xd5\xf3\xc1\xf4\xda\xdb\xc1\x39\xc2\x16\x48\x92\x82\x0b\x2f\xe0\x9c\xbc\x3d\x19\x08\x80\x76\x36\x45\x10\x25\x4f\x2b\x6d\x41\x03\x29\xe7\x0f\x2e\x5a\x94\x5b\xba\xcd\x2c\xa8\x9b\xd4\xb6\xe1\xf5\xe2\xe1\xd4\xf4\xed\x2f\xe0\x11\x3b\xcf\x32\x96\x2f\x00\xd5\xc3\x3b\x1d\xf9\x88\x40\x2b\xa0\xdc\x88\x04\xc1\xaf\x66\xcc\xae\x26\x70\xef\xa3\x13\x4c\x67\xfc\x90\xfe\xed\x8d\x8d\xee\xdc\xcf\x6a\x46\xf2\x29\x40\x45\x4a\xf2\xbb\x67\x54\xcf\x23\x5d\xdb\xb0\x00\x1c\x6c\x74\x1b\xf8\x74\xbc\xd8\xd4\x1d\x9d\xba\x81\x62\x58\x1c\x37\x46\xd7\xf3\x0e\x73\xde\xf6\x94\x15\xaf\x51\x81\xc1\x49\x91\x42\x95\x12\x2d\x45\x98\x2f\x94\x94\x3e\x20\xb0\xff\xc7\xfe\x6d\xdf\x19\xa0\x22\xe8\x7a\x52\x13\x33\x57\xa1\xe8\x0f\x37\xf2\x8a\x4c\x4a\x8a\x61\xc1\x48\xdd\x87\x5c\x1e\x8e\xcd\xcd\x84\x0d\xd8\x63\xe4\x4d\x9b\xcb\x16\xb6\xe5\xaf\x01\x47\xb3\x4a\x7a\x90\x52\xc8\xd3\xf4\x52\x01\x3d\x2d\x35\x4f\x68\x03\xf9\xea\xf6\x05\x6f\x3b\x01\x3c\x61\x6e\x47\xf3\x98\x81\x91\x46\x32\x0a\x5e\x3d\xbd\xf1\x68\x43\xea\x29\xde\xf2\x62\xcc\x9a\x34\x36\x72\xcf\x96\xbc\xcc\x6e\x87\xe6\xa6\xba\xf0\x71\x2e\x6e\xe8\x9a\xa6\x04\x89\xf1\x7c\xb7\x2d\xdc\x44\xba\xd1\x61\x58\x7d\x87\xf5\x4d\x67\xcc\x0a\x27\x78\x49\x7d\x83\x10\x88\x31\x5f\xfe\xee\x3d\x26\x8c\x59\xbe\xfe\x88\x4c\x3a\xa0\xe0\xae\x22\x96\xbb\xb6\x0e\xac\x90\x97\xcd\xf8\xdc\x09\x87\xce\xb1\x74\x2b\x05\x86\xdf\xce\x79\xec\x10\x42\x5b\x28\xf4\xe6\x45\x20\xd7\x12\xe3\xf4\x6e\xa8\x3b\xe2\xde\x6a\x15\x74\x07\x3b\xc5\xc7\x55\x7b\x8e\x25\xb6\x41\x11\x84\xea\x28\x3d\x88\x00\x23\x2c\x79\x06\x94\x21\x81\x1f\x88\x3c\x29\x94\xe7\xb7\xe2\xad\x9f\x8d\xc4\x89\xc9\x34\x77\x24\x39\x46\x09\xc9\x89\x09\xa6\xc2\x60\x17\xb5\x0f\x20\xd5\x0c\xca\xcb\xde\x36\xb7\x6b\xa6\x46\xa7\x6d\xc6\xa5\xb0\xf5\x06\x49\xc5\x65\x8b\xbd\xfd\xd3\xb5\xca\xfc\x54\x79\xa2\xf4\x8e\xe5\x15\x42\xf2\x3e\x9f\xc9\x21\x32\x06\x0f\xd6\x35\xef\xf4\x52\x11\x1c\xda\xf3\xef\xbd\xb7\xdb\x9e\x7d\x47\x16\xd0\xd6\x01\x1c\x29\x11\x8a\x55\xd4\xc1\xa4\x36\xab\xe2\x4e\x3c\xbf\x40\x23\x5b\x76\xdd\x19\x23\x50\x3c\x5f\x35\x98\x12\x4e\x2d\xf5\x5a\x2d\x1f\x24\x6e\x90\xde\x4b\x71\x64\x5d\x51\x75\xb6\x1b\x01\x74\xe7\xe5\x7d\xf1\x28\x5c\xcf\x8c\x86\xb8\x38\x2c\x25\x80\x79"}, -{{0x05,0xc7,0x19,0xca,0xe0,0x6e,0x2b,0xb7,0xd8,0x78,0x63,0xab,0x31,0x50,0x27,0x2c,0xb2,0xf8,0xc3,0xaa,0x24,0x21,0x91,0x2d,0x87,0xf9,0x8e,0x75,0x89,0x63,0x8c,0xe9,},{0x90,0x21,0x17,0x96,0xfe,0xd3,0xd5,0x3b,0x81,0xf8,0xfe,0xeb,0x1b,0xad,0x1f,0xfc,0x93,0x3e,0x5f,0x10,0xd3,0xbc,0x1b,0x36,0xdd,0xf2,0x10,0xa4,0x79,0x23,0xdf,0x03,},{0xba,0x6e,0xb7,0x51,0x37,0x1d,0xf7,0x21,0xb7,0x70,0x7a,0x5b,0x33,0x39,0xed,0xb5,0x5f,0x13,0x86,0x40,0xb9,0x7b,0xe6,0x33,0x4d,0x6c,0xda,0x51,0x91,0xa3,0xff,0x63,0x67,0x91,0x17,0x61,0x88,0x2a,0x4a,0x00,0x7f,0x16,0x1b,0x74,0x8c,0xec,0x95,0xb1,0x9e,0x99,0x5f,0x28,0x58,0xc2,0x57,0xcd,0x61,0x69,0x25,0x66,0x62,0x30,0x11,0x02,},"\xec\x24\x19\x18\x41\x8e\x60\x52\x20\x42\xe6\x73\x39\xe6\x64\x94\x99\xf3\x1a\x6c\x7c\xf8\x92\x5f\x1f\x61\xdd\xe8\x94\x60\x36\x02\xae\x8b\xb5\xf5\x88\x09\x82\x1f\x83\x34\x4f\x23\xcd\x31\xe6\x4e\xc9\xff\xe7\x9a\x98\x6b\x7e\x29\xe4\x31\x9a\x63\x41\x43\x16\xbd\x6e\xe2\x0e\x02\xa5\x0d\xa4\x40\x12\xbd\x2d\x6f\x9f\x67\x9e\x88\xed\x0c\x8b\xb1\xe2\xca\xd5\x5e\x56\x57\x89\x88\x33\x45\xb7\x54\x6f\x3d\x54\xb1\xb3\x62\xb1\xc6\x50\x50\x2c\x01\x9d\x73\x13\xaf\xbc\x82\x68\x9b\x23\xa3\xa5\x2d\x8f\x1a\xf9\xf8\x1e\x18\x8d\xbd\xf2\x03\xfb\x53\x00\xb4\x22\x5b\xfb\x67\x73\x33\x7b\xe6\x75\x0b\x3d\xb8\x8c\xe0\x97\x34\x3f\x62\xee\x2c\x11\x85\x74\xef\x15\x0c\xbd\x4c\x62\x76\x0c\x3e\x43\xdc\xbc\x39\x21\x8b\xd6\xd9\x85\x65\xfa\x38\x98\x11\xb1\xa6\x74\xf6\x17\xfd\x75\x67\x33\xdc\xb5\x67\xa9\x2d\xbf\x38\x55\xb5\x7b\x1f\x4a\x46\xd5\xb8\x97\x4b\x39\xac\x0d\x0e\x24\xd9\x9d\x20\x37\xc0\x4f\x60\xd9\x14\x0f\x64\xb0\x7a\x77\xd7\xea\xa1\xce\x8a\x78\xe8\x44\xb1\xdc\xf0\xe3\x74\x24\xf3\xf9\xd2\x53\xa5\x48\x56\x1a\x03\x75\xa8\xd4\x34\x12\x97\xbf\xed\xb7\x04\x8c\x79\x35\xe1\x48\x14\x18\xf9\xbb\xa9\x27\x1f\x9f\xd6\x02\x62\x24\xe7\x8e\x05\x5d\x8a\x09\x39\xfa\x2f\xe1\xdb\xc0\xfc\x7b\x58\x3e\x4c\xff\x34\x90\xe1\xd0\xf6\x10\xb2\x52\xe3\x0d\x84\x97\xd0\x0e\x4a\xac\xb3\x75\xf1\x9a\x47\x19\xf7\x9c\xa1\xea\x58\x3a\x2f\x8b\x14\x06\xa4\xaa\x5c\xb5\x5c\x08\xb6\x59\x3b\x67\x6e\xb5\xc3\x4a\xbe\x89\x39\x2d\x62\xd2\x33\x08\xa3\x34\x8b\x57\xaf\xfb\xba\x77\x39\xcd\xe8\xe1\x90\x9d\x34\x25\xee\xb2\x09\x26\xa9\x77\xd3\xa9\x4a\x86\xe0\xba\x10\xb3\x86\x92\x66\x98\x82\x7e\x86\xb4\xfd\x6c\x61\x80\x04\x7c\x87\xec\x3b\x31\x61\x9d\x05\xa9\xdf\x34\xef\xd3\xd7\x6a\x83\x69\x62\xb2\xef\x60\x4d\x07\xaf\x09\x75\xeb\x8f\x3d\xd2\x25\x94\x32\x38\x02\x56\x4c\x92\x9b\x3f\x65\xda\xcb\x57\x2b\x32\x55\x3d\x69\xb3\x1a\x19\x76\x90\xa9\xbb\x86\x0b\x08\x0a\x77\xcf\xbb\x3c\x17\x5a\xaf\xce\x01\x46\xa8\x2a\x4d\x06\xe8\xc7\x50\x52\x1b\x72\x6e\xf1\xcb\x29\xd0\x21\xe5\x91\x5e\x5e\x84\x62\xed\xe5\x39\x54\x45\x24\x5c\x9a\xe8\x82\xee\xc4\xb1\x74\x5e\x11\x79\x1f\x76\x21\xd3\xfe\x70\x2c\xac\x15\x25\xe1\xf7\xb4\x6e\x11\x05\xcd\xd0\x6d\xa2\xaf\xde\x26\x47\x5d\xc1\xf7\x8d\xf8\xe2\xd7\x2b\x0e\xc3\xef\x7d\xd9\x56\x19\x3c\x99\x68\x42\xa4\x32\x69\x65\x38\xcf\x12\x3d\x76\x87\x21\x1f\xfc\xd0\x90\xb9\x38\x1e\xab\xec\x87\x9f\x76\x9a\xac\x0d\x35\x64\xe1\x6d\xf7\x94\xfa\x24\x72\x8d\x71\x72\xfd\x07\x73\x2e\xab\x07\x7e\xd8\x1c\x22\x08\x4f\x6f\x78\x1b\x62\x6d\xac\x67\x42\x8a\x9d\xdf\x3b\x0d\xb0\x46\x52\x51\x22\x0d\x18\xb8\xbf\x62\x04\x64\xc5\x1a\x57\x8d\xec\xcc\xbb\xab\xa5\x45\xed\x44\x2c\xf1\x2c\x4c\x66\xf6\xcb\x6e\x69\x01\xea\x54\xae\xda\x23\x6e\xc4\x5e\xef\x88\x6a\x7d\xdd\x2c\x04\x1c\xab\xa3\xa6\xce\xe3\x39\x71\x5b\x6c\xe9\x7e\x76\x5e\xc3\x47\x9f\x3d\x52\x82\x4a\x81\x94\xbe\xc2\xa8\x96\x47\xe8\xc6\x3f\xf7\x64\x5f\xf6\xd0\x53\x67\xc7\x67\xbc\x48\xcc\x96\xba\xf0\x5d\x6a\x41\x5b\x2a\x5a\xff\x9b\xfb\x21\x79\x48\xfa\xd3\x57\xb9\x8f\x47\xdf\xed\x62\xff\x12\x85\xeb\x9f\x46\x8f\x0f\x29\xed\xd7\x5a\xdc\x0c\x8c\x2f\xf6\xa5\x65\xed\xb8\xed\xfb\x48\xbe\xa0\x3b\x70\xc4\x47\x36\x9c\x52\xd8\x81\xee\xa0\xee\xdb\x08\xc3\x15\xcd\xf0\xbf\xeb\x97\x9c\x1c\x02\x50\x94\x6b\xb1\x00\xc2\x86\x6b\x41\x69\xb8\xcb\xd4\x4d\x65\x8f\x02\x36\xe1\xe9\xf3\xaa\x13\xbb\x8e\x80\x22\xa3\x8c\xe9\x97\xc9\x4b\x5b\xaf\x97\xe0\xba\x62\x1f\x7e\x09\x67\x1c\xe6\x38\xc2\xa3\x9e\xe6\xc6\xe2\x5a\x68\x80\x19\xdd\x16\x76\x75\xce\xae\xc2\x1c\x6b\x42\xa7\xc8\xc4\x76\xd1\x29\xdc\xc6\x93\xc3\x92\xa0\x2b\xe9\x1b\x87\x43\x7a\x08\xa0\xeb\xf1\xa7\xbd\x97\x6b\xa2\x37\x74\x76\x68\x38\xb8\xd6\x02\x4f\x5b\xb9\xb0\x7f\x3c\x6b\x71\x9b\x4d\xe1\x5b\x72\x44\x80\x48\xab\x70\xdb\x3d\x4b\xea\x77\xba\x35\x9b\x51\xb1\xec\x17\xdb\xe8\x01\x0a\xef\x02\x44\xa8\x07\x9c\xa8\xb9\xa2\xa7\x97\xf3\xb1\xfe\x04\x7c\x8d\xd5\xca\xb7\xfb\x48\x68\x29\x23\x9c\x4e\xf6\xd9\xa3\x83\x70\xd4\x88\xc4\x7b\x7c\x03\x0e\x49\xa5\x50\x0c\x9a\xbb\x39\xa9\xa5\xab\xfe\x72\xe9\x18\xb7\x63\x84\xec\xaa\xfe\x16\x27\x26\x6c\xd1\x4e\x69\x6c\x09\xd2\x51\x2e\x31\x25\x82\xa8\xa9\x11\xe7\xb7\xbf\xa0\x4c\x21\x81\x9a\xf6\x87\xf0\x4c\x5e\x0c\xbe\x9a\x2c\xe2\x4d\x4d\x3f\xd1\x21\x90\xb2\x53\xda\xbc\x12\xc6\x3c\xab\xfa\x94"}, -{{0x53,0x11,0xf3,0xc9,0x61,0x01,0xcb,0x8b,0x7a,0xbc,0x62,0x2b,0xb9,0x32,0x6b,0x8f,0x51,0x3c,0x2b,0x16,0xd2,0x94,0xdf,0x79,0x7f,0x56,0xdf,0xd8,0x20,0x3d,0xda,0x27,},{0x23,0x0b,0x70,0x02,0xf5,0x7c,0x79,0xae,0x2e,0x6b,0xfd,0xb8,0xdf,0x30,0xdb,0x3e,0x90,0x07,0x56,0xb5,0x4a,0xf3,0x96,0x8c,0x67,0x0e,0xe2,0xf3,0x2b,0xb1,0x1e,0x0a,},{0x3c,0xbb,0xb2,0x60,0x88,0x70,0xde,0xa1,0xef,0xee,0xbb,0x3f,0xbf,0x68,0x1e,0x27,0x70,0x5c,0x35,0xe4,0xdd,0xee,0xa8,0x6c,0x1b,0x34,0x2a,0x77,0xdc,0x29,0x6b,0x49,0x84,0x19,0x80,0x8e,0xac,0xbc,0x78,0x85,0x56,0x11,0xff,0xbc,0x92,0x65,0xa7,0x47,0x98,0xe5,0x18,0x27,0xe6,0xe5,0xd8,0x11,0x81,0x6d,0x3c,0xa2,0x1e,0x8b,0x9c,0x06,},"\x61\xb1\x5b\xe3\x7c\x4e\xb3\x97\xd9\xe7\x7e\x00\x15\x1a\x28\xed\x3e\x86\xd5\x0a\x95\x52\xbb\x48\x50\xb6\x21\x76\x3f\x01\x2e\x7e\x77\xbb\x5d\xb8\xf3\xdf\x7d\xcf\x76\x9f\x2d\x1d\x46\xd8\xd6\x0b\xae\x40\xc8\xca\x6e\x25\xc6\x41\x0b\x60\x07\x8a\x93\xfd\x05\x90\x21\x14\xbd\x91\x04\x5c\x06\x19\x2c\x70\xc4\x2c\x9f\x41\xf8\x16\x1c\xa4\x65\x64\xeb\xc2\x1a\x4b\xdd\x81\x90\xeb\xa2\xae\xb3\x09\x82\x30\x72\xec\x2c\x02\x00\xce\x64\x98\xf9\xd7\x2b\x37\xb3\xfb\x46\x67\x74\x32\x6d\xf3\x7a\xd8\x80\xd8\xed\xdb\x32\xaf\x67\x3e\x45\xd8\x8e\xec\x49\xb1\x57\x7b\x43\xb8\x63\x91\x11\xc2\xe0\xb9\x41\x87\xd2\xd4\xe0\x17\x3c\x00\x0f\x4c\x37\xbe\x84\x5d\x68\x81\x0b\x78\x89\xff\x2a\x04\x9f\x3f\x9f\x24\x5e\xc7\x0f\x21\xde\xf9\x77\x80\xb6\x11\x40\x0a\x83\xc3\x1a\x79\xd9\x3a\x8e\x98\xb6\x08\xfd\xcf\x24\x88\xb0\x68\xfe\x1a\xe4\x21\x72\x93\xa9\x36\x7b\xb7\x34\xb5\xbc\x7b\xd8\x81\x9b\x37\x7f\x09\x0b\x4f\x8f\xdb\xff\x50\x79\x9c\x76\x88\x0d\x19\x13\x35\x80\xe1\xdd\xfc\x2b\x9b\xaa\xdd\xba\xb3\x4f\xc6\xfd\xc0\x78\x01\x4b\xd1\xff\x73\x9d\xaa\xfe\x54\x76\xf3\xf7\x9d\x4d\xbe\xc2\x16\xfa\x76\x80\xee\x8e\x84\x00\x2d\xcb\x9d\xdb\xc7\xfc\x1e\x1c\x8e\xf4\xf1\xb2\xa2\x08\x1b\x92\x82\x24\x3d\xa6\x15\x3c\x1f\xce\x09\x05\xcf\x35\xf8\x3a\x68\x4c\x01\xb0\x45\x57\xec\x84\xf7\xe9\xa9\x4f\xc2\x88\x2e\x2f\xf1\x9f\xea\x21\xd2\xce\x61\x67\x86\x1c\xe0\x1d\xf8\xb8\xd3\xc3\xe8\xd2\x55\x61\x0b\x7a\xf2\x59\x6c\xd5\xcf\x00\x16\x73\x49\x42\xcc\x71\x4c\x27\x2c\x05\xfd\xa9\xd3\x47\x23\x62\x66\x46\xa4\x61\x30\x18\x2c\xeb\xcf\x17\x9e\xc0\x0a\x6a\x17\x3b\xd8\x57\x7f\xa8\x45\xc4\x4d\x19\xc6\x99\x79\x44\x75\x5f\x2b\x4e\x46\x85\x63\xa7\x5e\x90\x16\x52\x3b\x87\xdd\xac\x3e\xee\x21\xbc\xbc\xa0\x8f\xcc\x29\x54\x6a\x43\xcb\xe0\xd8\xd1\x0a\x0e\x8d\xdc\xba\x17\x2d\x1d\xed\x15\x03\x78\xe1\x8b\x36\x8c\x77\x63\x91\x3e\x4b\x40\x70\x12\xfd\x76\xa8\x72\xd2\xcb\x04\x93\x0b\x8e\x22\xb3\x08\x24\x3d\x4c\xc2\x78\xfd\xf2\xe1\xf9\x40\xae\x89\xac\x89\x1b\x9e\x06\x61\xae\xe5\x53\x93\x7b\xf3\x50\xb4\x07\x07\x0a\x1b\xdf\xc4\xf7\xa3\x78\x7e\xf3\x99\xd2\xca\xf4\xec\x74\x43\x9c\x58\x73\x76\xc7\x7b\xe0\xc3\xde\x53\x9d\x3a\xc2\x60\x89\x76\x5b\x9b\xe1\x0b\x90\x38\x69\x46\x36\xe2\x62\xd7\xba\xa0\xb3\xa8\x94\x1a\x20\x15\x96\x76\x39\xf6\x04\x4c\x67\xe5\x9b\xc8\x1c\xf2\xfb\xa7\x04\xac\x0d\xf4\x8d\xa6\x03\x74\x05\xa8\xe8\xb8\xa7\xce\x3c\x58\xef\x38\xa8\x83\x53\x8b\x24\x7f\xfe\x18\x09\x7a\xf0\x95\x24\x2b\x05\x8b\xdd\x1e\x3e\x24\x5e\xec\xe0\xa7\x1b\x75\xb9\x7d\x52\xf2\x0d\x6d\x51\xbb\x97\x66\xb0\xda\x0f\xc0\x9c\x8a\xc2\xa3\x0f\xb6\xe7\xb3\x2e\xe0\x6d\xad\xf4\x6d\x73\x59\xcc\x06\x6a\xa9\x47\x85\xd8\xa8\x82\xff\x09\x7d\x78\xa8\x6b\xe2\xd4\x56\x00\xdd\x3d\x30\x60\x12\x5f\x01\xc0\x63\xe4\x88\xd5\xc3\xef\xee\x1b\xca\x1e\x58\x51\x64\x55\xff\xca\xec\x1b\x81\xef\x43\x38\x76\xbf\x09\xff\xa5\x1d\x6f\x50\x18\x58\x52\x24\x57\x9c\xb6\x7b\x56\xce\x1c\x21\x6e\xc0\xa8\x83\xe0\x6c\x8e\x15\x63\x42\x1e\xa7\x2b\x0c\x10\xd4\xbb\x31\xe4\x91\xc2\xae\x2f\xe8\x13\x9f\x24\x9e\xc9\x27\xd8\x06\xba\x08\xdb\x52\xb1\xb5\x06\x66\x90\x47\xf0\xc1\x16\xff\x37\xac\x5b\xa6\xcd\xb1\xea\xaf\x33\xfd\xad\xb0\x70\x5c\x79\x9d\x35\xac\x6d\x9c\x80\xda\x90\xc1\x43\x8b\x58\x5f\xfd\x59\x35\x0a\x26\x86\xb1\xec\x35\x16\x6c\xb9\xb6\x9a\xd0\xf5\x65\x86\xaa\x03\x27\x4d\x78\x2e\x3f\x85\x8d\xb6\x4a\xdf\xbf\x04\xd5\x22\x8a\x7b\x1c\x4a\x20\x48\xbb\xcd\xb9\x41\x15\x3a\x43\x6d\x74\x2c\x38\xb5\x8b\x4d\x7d\x13\xc9\xf1\xd6\x0e\x15\x2a\xa2\x79\x23\x49\xa3\xd9\x4e\x7e\x6b\x11\x04\xaa\x1b\x87\x09\x98\xc1\x8d\xd7\x06\x56\x54\xa8\x52\x81\xbb\x6f\x02\x7f\xaa\xd5\x56\xb1\xf5\x32\xe7\xa1\xe2\x2d\x56\x40\x69\x28\x95\x87\xa0\xef\xc9\xc1\x58\x5d\x13\x5f\x31\x23\x3c\x41\xf4\x40\x46\x6e\x71\xfe\x90\x12\xe5\xf9\xa0\xd7\x4a\x72\x82\xee\x39\x2f\xb0\x16\x5d\xb7\x9f\xf1\xd3\x17\x6e\xd0\x8a\xfe\x1d\xaa\x66\xcf\xbf\x43\x05\xae\x16\xac\x17\x92\x33\x43\x99\xf7\x1b\x19\x17\xdd\xec\x27\x0a\xcf\xf6\x65\xea\x05\xd1\x84\xc2\xc5\xcd\x2c\xcd\x90\x2b\x22\xf9\xb7\x19\x5e\x66\xa6\x55\x56\xca\x88\x4b\xa6\xf5\xda\x04\xdc\xd4\x61\x7f\x33\xdc\x2b\x44\xa0\xea\x74\x2a\xeb\x2b\x93\xf3\xa4\x1d\xf7\x95\x7a\x02\x67\x97\xa5\x85\xce\xee\x81\x4b\x19\x75\xf5\x23\xd2\xdb\x5d\xbb\x9b\xe0\xca\x64\x9d\x1d\x45\xdc\xfd"}, -{{0xd2,0x90,0xff,0xd9,0x33,0x95,0xbd,0x5f,0xc5,0x87,0xd1,0xab,0x51,0x18,0x66,0xe7,0x2b,0x37,0x1a,0x17,0x35,0x73,0x2d,0x9d,0x5c,0x6a,0x18,0xdd,0x46,0x5e,0x93,0x63,},{0xfd,0x4a,0xad,0x73,0xb0,0x32,0x46,0x1c,0xa0,0xaa,0xe8,0x71,0xca,0x70,0x16,0x38,0x3b,0x2b,0xe0,0x16,0x90,0x53,0xfd,0xbf,0x6c,0x59,0x14,0xfd,0xd6,0xdd,0x6f,0x92,},{0x21,0x70,0x4d,0x5e,0x62,0x6d,0xcf,0x6a,0x9d,0xcd,0xef,0x93,0x54,0x29,0xeb,0x7f,0xb5,0xb2,0x57,0xee,0xcd,0x7b,0xf7,0x4a,0xcb,0x0c,0xd3,0x0e,0xcf,0xcf,0x60,0x8d,0x0c,0x5b,0x63,0x3a,0x4a,0x8a,0x9b,0xa2,0xcc,0x82,0xa2,0x1e,0x03,0x35,0x5e,0x01,0xd8,0x5d,0xae,0x7e,0xca,0xc8,0x89,0x6d,0xc1,0x5d,0xae,0x04,0x85,0x70,0x71,0x04,},"\xeb\xd9\x00\xbc\x91\x0c\x5e\xcc\x4d\x97\xda\xf7\xcb\x5e\xbb\x54\x91\x50\x0b\x7a\xd1\x16\xe3\x06\x60\x95\x07\x09\xd8\x08\x4b\xb6\x43\x4c\x5b\xea\x4a\x8c\xcc\x1e\xd5\xa8\x01\xbe\xbb\x1a\x11\x78\x78\xc0\x37\x47\x00\x3e\x14\x8e\xd9\x14\x34\x83\x2e\x89\x66\x24\x1a\x7f\xff\x22\xfe\x1d\x6d\x8c\x3c\x3d\xdd\x72\x15\xa1\xef\xaf\x4b\x07\xaf\xee\x1b\x25\x67\x3a\x14\x39\xea\xac\x32\x4e\x89\x5d\x4b\xe8\x39\xe9\x76\xc0\x3a\xc0\x01\x25\x48\x76\x88\x8c\xca\xaf\x39\x12\x72\x7a\x60\x10\x6a\x87\xbe\x69\x24\x7c\x9e\x43\x8c\x31\xfc\xa8\xd9\xc6\x1b\xae\x36\x8c\x83\xe4\x09\x01\xa9\x97\x00\xdf\xf8\x39\xb5\x13\xba\x8d\xc4\x2d\x93\xce\x09\x87\xa2\x33\x34\x70\xa9\xf9\x83\x31\x3f\x91\x98\x86\x59\xda\x54\x03\x9e\x49\x9c\xd1\xaf\x2b\x8f\xa0\xeb\xe7\x50\xe2\x4d\x55\xc2\xa5\xbd\x1a\xde\x3f\x68\x00\x92\x54\x2b\xd1\xbe\x0b\x97\x35\xba\x39\x3a\xd5\x69\x7d\x24\x1e\x8e\x8b\x28\x64\x6d\xb2\x7d\x2f\xb5\xa9\x40\xe8\xfa\xea\xf0\xb6\xc9\xef\xda\x88\x61\x5d\xec\x89\x1c\xe7\x32\x93\x08\x13\xbf\xbb\xd0\xbc\x5f\x82\x10\xab\xe8\x43\xbe\xb5\xe4\xf0\x28\xf4\x9b\xea\x34\xf1\xe5\xb0\x9e\xac\x4c\x66\x62\xc7\x4f\xba\x39\xde\x4a\x96\x02\xa9\x69\x4a\x85\xc7\xc1\x37\x5f\xda\xdf\xda\x6a\x19\x57\xfc\x5b\x59\x87\xa6\x87\xb0\x39\x95\xe5\x16\x97\xa1\xab\x5b\xb6\xcb\x11\xb6\x63\xc1\x37\x2f\xad\xe4\xc0\xac\xa8\xfb\xeb\xb4\xeb\x54\xce\x7c\xe3\x6c\x69\x04\xea\xf6\xea\xb2\xf3\x4f\xac\xd8\xc7\x68\xc8\xd3\x6d\xa2\x39\x7b\x1a\x02\x73\x5a\xea\x72\xcf\xaa\xd0\x39\x34\x10\xdb\x52\x7a\x8a\xb2\x36\xd4\xcd\xab\xdc\x88\x8f\xac\x6f\x18\x21\x48\xb1\x32\x61\x44\x25\xd3\x90\xff\x03\x6e\x54\x85\x5e\x42\x03\xc5\x12\x03\xc1\xf4\x3e\x37\xbb\xf6\xb9\xbf\x27\xf5\xb7\xe7\xc6\x65\x15\x14\x65\x40\x1a\xc3\x2c\xbe\x9e\x33\x50\x53\x5e\xdf\x48\xa7\xbc\x36\x03\xe2\x23\x2e\x93\x8f\x9a\x81\x5a\xc4\xd1\xde\xec\x99\x1e\xf9\x62\x09\x48\x44\x1f\x7a\x2f\x4a\x46\xe2\xc4\x00\xab\x91\x4c\x4b\xe5\x1d\xca\xad\x8e\xd8\x23\x9c\xbb\xe9\x77\xa9\xf0\x9c\x02\x69\x83\x19\xd9\xfe\x2a\x8c\x6e\xb6\x0b\x79\x9f\x29\xae\x76\x59\x97\x0d\x2e\xbd\xff\x3c\x6c\xf7\x09\xbb\xf6\xf4\xbb\x55\xb9\xdf\x4f\x61\xa2\x41\xde\xc1\x44\xb5\x99\x3f\x08\x7e\x78\x4b\x97\xbe\x1e\x53\x60\x8c\x2e\x81\x7c\xe3\xd9\xaa\xf9\x14\xe6\xb7\x23\xf5\xb4\xaf\xff\xd2\xa6\xb9\xfe\x9d\x2d\x73\x91\x5c\x7a\xd1\xff\xb1\x3e\xfc\xb7\x3c\x56\x23\x81\x95\x64\x52\x03\x98\x4c\x99\xaa\xfd\x02\x35\xf7\x3b\x3f\x88\x2e\x07\x39\x39\xbf\x78\x66\x57\x28\x01\x38\xdb\x05\xb8\x6f\xcc\x94\x60\xb3\x85\xef\x45\x59\x20\x4e\xcd\x81\xe2\xf1\x2f\x5f\x06\x2a\xa4\x48\xdc\xcc\x82\xea\x8d\x89\x46\x6d\xd1\xbe\x46\xf8\x2c\x4f\x87\xbf\x0d\xb2\xb8\x78\xac\xbb\x0d\x91\x12\xc8\xdb\x6f\x51\xd3\x5f\x6d\x42\xf7\x49\x85\x6b\x99\xe5\x50\xb6\xc4\x54\xe9\xe8\xbe\x4d\xa1\x75\xf0\xb5\xe8\x6b\xe6\x6c\x97\x9f\xd8\x78\x23\x7e\x57\xf6\x91\xf0\xd2\xac\xd0\x28\xfb\xff\xa5\xb0\x66\x87\x75\x03\x4d\xb1\xf2\x1d\xdb\xe7\x11\x4e\xe3\xdc\x0b\x44\xda\xca\x64\xc5\xa0\x3a\x2f\xee\xae\xab\xeb\x70\x63\xbf\xcc\xcc\x55\x9b\xaf\x27\xf1\xcc\xb2\x20\x2f\xa4\xd1\xb2\xbf\x44\xc0\x4b\x2c\x2f\x81\xf9\x4e\x28\x1b\x1a\x5a\xdc\x85\x0d\xa1\xb9\x47\x9f\xca\xbd\xda\xde\xa5\x6a\x11\x5b\xb5\xf0\x6c\xc0\x16\xf1\x41\xc0\xfc\xb5\xe8\x3a\xb2\x48\xea\xec\x90\x15\x8d\x8b\xe6\x47\xaf\xf1\x2e\x7e\xeb\x5e\x57\xdb\xcc\x29\x3c\xb3\xb6\xaa\xcb\x55\x23\x6d\x4a\x83\x9a\x06\x20\xf4\x76\x23\x87\xdd\x17\x14\xdf\x5c\x13\x5e\x3d\x9d\x68\x24\xf9\x3b\x7c\x90\xd3\xae\x38\xc5\x18\xd6\x07\x12\x0c\x83\x95\x70\x41\x3b\x46\xb8\xcc\xd7\x37\x04\x92\xd8\xae\x5c\x60\x9e\x00\xcf\x82\x51\xe2\xe7\xdf\x81\xe5\xb4\xf9\xc1\x6a\x5a\x53\x9f\x0a\xfc\xce\x41\xbb\x43\x62\xe5\xea\xa5\xf9\x40\xa1\x70\x6f\x4a\xfb\x6b\x14\x43\x2c\x81\xd4\xba\x1a\x33\xd3\x22\xdb\xf1\x06\x45\xab\x63\x73\x7e\xad\xc8\x6f\xe6\xe0\x97\x6f\x76\x33\x97\xfb\x89\x86\x37\x59\x5d\xfd\x36\x93\x47\x92\xd7\x79\xe2\x4c\x2a\x3f\x0b\xac\xf5\x3e\x04\x73\xc5\xfd\xa9\xc6\x12\x84\xe4\x41\x9b\xdc\x0e\xef\x5d\x22\xf4\xd9\xbf\x42\xe8\xc0\x49\x33\xbb\x93\xb5\x3c\x29\x5d\x7a\xc9\x39\x5a\xbb\x6d\xcb\xd7\x42\xb1\xe1\xbc\x3b\x0e\xa4\x43\x4e\xa2\x1b\x8e\xca\x9a\xe6\x82\xd3\x31\x5a\x41\xe9\xc3\xc3\x37\x18\x40\x76\x1d\xc5\x9c\xac\x45\xda\x7e\x38\x13\xe2\x87\x88\xdc\x89\xde\x35\x5b\x5a\xee\x08\x80\x90\xa3\x8d\xd3\x9d\x83\xe5\xe4"}, -{{0xd7,0xfd,0x73,0xd1,0xd2,0x29,0xa6,0x58,0x94,0x42,0x0e,0x4b,0xa7,0x34,0x27,0x0d,0x5a,0x20,0x75,0x83,0x64,0xde,0x89,0x7d,0x85,0x55,0xe2,0x41,0x97,0x45,0x3c,0x19,},{0x3c,0x22,0x77,0x2a,0xec,0x0a,0x0c,0x15,0x59,0x07,0x7f,0x2c,0xfd,0x1f,0x24,0x65,0xd4,0xb4,0x84,0x95,0xc5,0xd0,0x5f,0x1f,0x83,0x7c,0x31,0x84,0x5f,0x34,0xca,0xd1,},{0x40,0x0c,0x35,0x05,0xf1,0xdf,0xa8,0x0d,0xf4,0xb2,0x6d,0xb2,0x4c,0x02,0x7e,0xb8,0x19,0x77,0xf0,0xfb,0x9b,0x5a,0xca,0x52,0x4a,0xd5,0x12,0x00,0xf4,0xbf,0xb1,0x33,0xdb,0x83,0x48,0x23,0x31,0x41,0x95,0xf4,0xed,0xc2,0x92,0xd5,0xf5,0x30,0xd0,0x85,0x56,0xe7,0x80,0x9c,0xaf,0x23,0x39,0x76,0x8a,0xa3,0x80,0x29,0xfd,0xbc,0x28,0x0f,},"\xc9\x22\x58\x59\xd5\x55\xbc\x42\x01\x1a\xf1\xb4\xf1\x49\x98\xe6\xe9\xb0\xa6\x5e\x21\x72\x71\x3e\x96\x83\x80\xfb\x6c\xee\xdd\xa2\x2e\x02\x2c\x51\x30\x30\x31\xd9\x93\x1c\xce\xf2\xf7\xbc\x70\x5c\x9e\x21\x5c\x1d\x08\x9d\x48\x8d\xad\xda\xee\x15\x5c\x93\x9b\x62\x02\xca\x53\xbf\xc7\xf6\xe8\x8e\x15\x29\xd8\x2f\xb4\x5e\x02\xb5\xd0\x5a\x82\xbb\xb9\xdb\x5f\x41\x5c\x58\xba\x8b\xd5\x6c\xff\xd9\x22\x70\xb2\x47\x49\xe5\x6d\x12\xc9\x9a\xe9\x0c\x78\x00\xf5\x4f\x55\x25\x4e\xa4\x2d\xa5\xdc\xfb\xe0\xe1\xd9\x89\xcd\x2f\x68\x97\xe2\x32\xdf\x04\x70\x7b\x34\xaf\x75\xfa\x7f\xec\x33\xe5\x5e\xd5\x6a\xee\x39\xc2\x2b\x04\x5b\xed\xd1\x61\x08\x3b\xc5\x51\x4c\x1f\x81\xca\x90\x7b\x7c\x76\x03\x17\xa7\xfd\x5a\x5a\x02\xa5\xd4\x0e\x2e\x82\x3e\x24\xad\x96\xae\xf6\xda\x8e\xa9\x82\xb5\x16\x1c\xc3\x9d\x84\xaa\x2f\xfd\x95\x44\xc1\x1b\x63\x40\x37\xab\x0a\x1c\x8e\x36\xac\x63\x01\x9d\xa1\xb2\xd9\x95\xcb\x7b\xd3\xd6\x2f\xe5\x74\xde\xab\xcc\xbd\x0d\x3a\xe7\xa5\x6e\x5b\xec\x91\xe4\xba\x3f\x3d\xb8\xbf\xea\x88\xe6\x7d\xa6\x2e\x88\x27\x8a\x6e\x3b\x41\x8d\xce\xea\x05\x89\xf2\x5f\x7d\xd8\xad\x19\xdd\x84\x50\x89\x41\x9b\x47\x2e\xfc\xcc\x87\x9c\x17\x2b\x32\xee\x4a\x4d\xbc\x2e\x6c\x2e\x86\x5b\xb3\xb8\xca\x0a\xdc\xb7\x1f\xdf\x89\xe1\x97\x39\x10\xef\x24\x29\x15\xf3\x3e\x23\x6d\x2f\x7c\x8e\x9f\x1e\xe5\xb0\x7c\x6e\x3c\x25\x36\x0f\x8c\xb1\x46\x0b\xe8\x7d\xb3\x1a\x29\x1d\x4d\xee\x34\x95\x3e\x75\xc6\x75\xbf\x18\x1b\xb7\xa0\xb7\xb5\xc1\xbe\xfd\xc8\x6a\xda\x07\x2a\x48\xf6\xac\x75\x5d\x49\x9b\xd6\x8d\x62\x5d\x85\x14\x52\x5c\xc3\xab\x8f\x54\xce\x15\xa8\x71\x29\x17\x78\xde\x13\x05\xd2\x21\x93\x61\xaa\x30\xe3\x32\xa2\xe0\x69\x07\x7c\x5c\x53\x45\x75\x20\x37\x9d\x8b\x90\xd2\x4b\xd8\xa3\xa7\x70\x0f\xf7\x66\x23\x1c\xb5\x69\x7f\x9a\xce\x52\x1a\x99\xe8\x96\xda\x54\xc4\x07\x93\xbc\x7c\x1f\xb1\x58\x4b\xb1\xc8\x61\x94\xd2\xfb\x7a\x4b\x80\x2f\x30\x88\x5e\x0e\xe8\xaf\x88\xd6\x88\x6e\x3a\x3a\x4d\x4c\x85\x46\x49\xcc\x01\xab\xdf\x35\x31\x9a\x08\x56\xcc\x65\xd0\x92\xa3\x86\xf8\x86\x96\x25\xcd\x0a\xca\xc0\x87\xe9\x35\x17\x90\xcc\xb4\xa8\x65\xf6\x51\xa8\x81\xc3\xeb\xf1\x09\x07\x27\x74\xf9\x40\xf5\xaa\x98\xa2\xa2\xaa\x3d\xd3\x66\x47\xd0\xde\x83\x00\x1a\xa7\xcd\xc0\x31\xcc\x4a\x4d\x75\xdc\x11\xce\x55\x16\x76\xa2\xad\x43\xa3\xf6\xa1\x6a\x4b\xc5\xae\xe8\x0e\x53\x64\x20\x60\x87\x36\x4e\xb8\xb2\xb1\x5f\xb7\x05\x38\x0a\x07\x2d\x7c\x8b\x51\x99\x59\x43\xaa\x76\x2e\x8d\xeb\x4c\x56\x8c\xda\xa1\x41\x1a\xb6\x8f\x28\x48\x9e\x13\x23\xbb\x61\x56\xce\x25\x00\xb0\x6e\x77\x93\xc5\x10\xa3\xde\x29\x15\x08\x40\xbf\xdb\x0b\x2b\x7b\x21\xc2\xbb\x8a\x77\x46\x16\x7c\x92\x9d\xd0\xad\xad\x44\xfe\xd8\xf3\x6e\x83\x81\xb3\x42\x08\x0b\x2a\x7d\x82\xa3\xf8\x1f\xf7\x26\x30\xcb\x78\xdf\x91\xf7\xb6\x5a\x44\xef\xf6\xed\x64\xd4\x8a\xfe\xd1\x09\xdd\x7a\x69\x3a\x1b\xa8\xc3\x7e\x00\x8f\xcb\x15\x7e\x37\x29\x7d\x32\xeb\xa7\x65\xa6\xc7\x19\x3e\x73\xbd\x97\x64\x79\x85\xb1\x60\x38\xc7\x4a\x08\x4a\x8f\x25\x65\x4c\xd8\xcd\x2c\xdd\x27\xff\x17\x33\x4e\x06\xad\xaa\x05\x82\x64\x01\x7a\x3b\x2d\xa7\x8e\x57\x38\xa2\x7e\x35\x0d\x88\x2f\x5f\xae\x19\x92\x78\xd4\xe5\x0b\x8b\xad\xf5\x7c\x21\x41\xdf\xdc\x3c\xff\x99\xdf\x5d\xe8\x6f\xec\x29\x3c\x76\xcb\x94\xb6\xb1\x9b\xa3\x03\x4e\x46\x0f\x84\xc2\x80\xa2\xe6\x41\x2f\xab\x56\x98\xce\x89\x02\x07\xca\xba\xbc\xa0\xa9\x5b\x5a\xd5\x33\xce\x11\x4b\xf7\x1a\x40\x4a\x87\x59\x0d\x35\xfa\x7c\xed\xba\x43\x13\x1c\x4e\xe9\x23\x44\x83\x9f\x25\xcb\xfa\xeb\x12\xae\xeb\xc8\x04\x08\x93\x95\x1a\x34\x6b\xd2\x8f\xdd\x16\x7b\xd2\x0f\x71\xa1\xe5\x9f\xb6\x0d\x55\xe1\xc5\x67\xf4\x78\xf0\x27\xcf\x67\x9a\x37\xd1\xd9\xdb\x86\x7e\x17\xbf\xdd\x60\xb3\x47\xd8\x9d\x32\x26\x39\xd3\x15\xbb\x7a\x2c\x91\x34\xf0\x0e\xa0\x3a\x36\x7f\x30\x5e\xa4\xd6\x0d\xc9\xd5\x67\xcf\x92\x48\x51\xe4\x69\xea\x95\x4e\xd3\xea\x63\xea\x86\x06\xf7\x9f\x07\x73\x39\xbf\xa2\xb5\x1a\xe4\x9b\xaa\x0f\xb2\x53\x77\x82\x1d\x7c\x11\xef\x9a\xd4\xbb\x4c\x0f\xe4\x89\xac\xba\xb0\xef\x00\x0d\x61\x8c\x7a\xf5\xef\xd2\x05\xd6\x85\x99\xfc\xbd\xd9\x5e\x28\xf8\x36\xe0\x91\x6f\x9f\xf5\x48\xd0\xba\x17\xda\x62\x53\x6e\x74\x64\x68\x01\xee\xb6\x12\x2b\xa3\x2c\x41\x07\x3a\xe0\x4e\x42\xc6\xc1\xd5\xd8\xd2\x29\x76\xa5\x62\x26\xdd\xf4\xb6\xac\x95\x45\x5f\xb5\x30\x99\xf2\x02\x15\xb2\xeb\xc9\x07"}, -{{0xfd,0xa7,0xcb,0x08,0x40,0x16,0xba,0x51,0x3c,0x7c,0x4f,0x8f,0x71,0x80,0x48,0x0b,0xb1,0x81,0xe9,0x56,0x95,0xea,0x68,0x73,0x7f,0xa3,0x4a,0x40,0xec,0xbd,0xf3,0xef,},{0xa2,0xde,0x3a,0x0e,0xf9,0x72,0x98,0xfd,0x71,0x61,0x06,0xe2,0xf3,0xf5,0x45,0x13,0x05,0x7a,0x40,0x07,0x2d,0x23,0x4c,0x35,0x18,0x15,0x4c,0x1b,0xd1,0x2d,0xe0,0x37,},{0x33,0x61,0x4b,0x7a,0x94,0xf7,0x5e,0x03,0x65,0x34,0xd7,0x6e,0x30,0x14,0x7e,0xcc,0xdd,0x2a,0x04,0xe0,0x0c,0xd4,0x70,0x4a,0xb6,0xe8,0x07,0xd6,0xa2,0xac,0xc1,0xe1,0xd9,0x63,0xb8,0xee,0xe0,0x81,0x0d,0x41,0x2d,0x9d,0x56,0xe5,0x45,0x56,0x30,0x2b,0x10,0x73,0x0c,0x15,0xab,0xf8,0x9c,0x29,0xa0,0x27,0x30,0x3e,0xa8,0x8a,0xe7,0x01,},"\xc2\x1b\xb3\xf8\xe3\x7b\xef\xa3\x67\xc9\x13\x67\x31\x01\xba\x30\xd3\xb5\xc7\x4b\xd8\xbd\xb0\x9c\xd2\x86\x40\x01\x2d\xb4\x11\x20\xc2\xbc\xc4\x08\x5d\xe2\xa0\xf9\x5c\x92\x15\xdd\xef\x8c\xb5\xfc\x8d\x8b\x12\x51\xb4\x15\x27\xc6\x7d\xfa\xa3\xf9\x5b\xa3\x57\x83\x91\xea\x5a\x66\x29\xa7\x33\x09\x5f\xd0\xa4\x3f\xdb\xa4\x0f\xfe\x26\x0f\xff\x82\xac\xee\x2e\xbe\x98\x0e\x9e\xce\xcc\xfe\x7e\x10\xb2\xed\x8c\x2e\x6b\x41\x0d\x54\x7a\x12\x86\x57\x1d\xf3\xd7\x01\x17\x4e\x57\x9f\xcf\x19\xd3\xbd\x80\x86\xc0\x42\x3f\x37\x11\x77\x89\xf3\x05\xd9\x67\x0a\xd2\x8c\x99\x67\x4f\x52\xcf\x64\x21\x1a\x08\x1d\x0c\x6c\x30\x96\xda\x2c\x71\xbf\x5f\x57\x99\xa7\x91\x0e\x6f\x38\x10\x4a\x37\xa6\x55\x7c\x2d\xae\xf3\x40\x81\x4a\x1f\x83\x0d\x59\x37\x73\xc6\xcf\x48\xd8\x3e\xa0\x72\x94\xb9\x4e\xb0\x80\xb8\x5d\x69\x70\xe2\x8f\x40\x51\xd5\x06\x6d\xb1\x0e\x96\x19\x73\xa6\x26\xa8\x26\xae\xaf\x8a\x06\xec\x0d\x56\x6b\x7e\x0c\x4e\xf6\x0f\x0c\x56\x78\xfc\xbb\x5b\x2a\xc6\x3f\x7b\xed\x06\x44\x8a\x24\x7b\x3d\x42\x7b\x87\x08\x6d\x33\x57\x3f\xb2\xd7\x22\x8c\x5c\x34\xea\x66\x40\xee\xfa\x95\x64\x48\x5a\x79\x63\x8e\x9c\x97\xc0\xaf\x84\xcf\xee\x7c\xe4\xa7\x39\x22\x0c\x84\x29\xe0\x67\x14\x39\x53\xd5\x50\x66\x8d\xad\xc8\x4e\x7b\xed\x9a\xb0\x70\xa5\x94\x33\x90\xc6\x11\xd7\x5b\x1c\xb1\x28\x73\xa3\x7d\x98\x50\x66\x1a\x00\x77\xbf\xa9\xca\x9b\x8b\x26\x37\x66\xc1\x49\xff\x0e\xe4\xb4\xad\xba\x25\xea\xf7\xd7\xf5\x01\xf3\x62\x45\x42\x56\xbc\x12\x69\x37\x8e\xf3\x35\x9a\x8e\xd6\xb9\x60\xb8\x66\x21\xfa\x3b\x61\x3e\xb1\x32\x12\x2f\x49\xf2\xeb\x2c\xeb\x68\x32\xa3\x99\x1e\x96\x1c\xb0\xe7\x8b\x74\x2e\xf4\xd6\x5e\x8d\xe3\x46\x96\x66\xfe\xc7\xc5\xb8\x74\x78\x95\x71\xc5\xc9\x9a\x2c\x02\xa0\x53\xff\x7d\x2f\xc9\x00\x76\xba\xfe\x1f\x26\x7f\xa8\x1a\x39\x90\xf2\x7f\xf1\x4f\x03\x00\x0a\xf0\x0c\x59\x28\x6c\xb9\xbb\x98\xe2\x04\xe9\x01\x90\xae\x2a\x50\xed\xef\x04\x9e\xa9\x2a\x1f\x78\x50\x88\xf9\x4a\xdf\x65\x88\xfb\x43\xbb\x40\xfb\xe2\x32\x42\x35\xcc\x7e\x16\x8b\x80\x26\x4b\x06\x9f\x94\x4f\x50\x36\x92\xc9\x49\x23\x4d\x5b\x76\xbc\xff\xab\xe2\x9f\xf9\x06\x4b\xd7\xcb\xed\x9e\x00\xe5\xb7\xfd\xda\x43\x12\xeb\x80\x14\x65\xf1\x27\xd0\xca\x68\x83\x2a\x7f\x4e\xd0\xea\xed\x8f\x55\x9c\x16\x31\xcd\x4d\x34\xf0\xdc\x41\x4d\x9f\xcf\xe8\x49\xa9\x1e\x25\xf3\xe0\xff\x01\x3a\x8c\xff\xa8\x06\xed\x8e\x93\xd0\x8a\x1e\x5a\x75\x76\x82\xca\x3d\x26\xab\xc8\x69\xc7\x6f\x1c\x79\x00\x7d\x55\x9d\xfe\x67\xe7\x8d\x8a\xf0\x19\x58\x08\xb0\xe7\x71\xc7\x1e\x64\xb5\x71\x6f\xb3\x63\x09\xc2\x50\x25\xfa\xe6\x41\x4c\x28\xbb\xdb\xd4\xde\x59\x7a\x74\x99\x6c\x9d\xa9\x74\x92\x0d\x59\xe6\xf4\xc2\xed\xfe\x11\x0f\xf8\x17\xfd\x48\x0a\x50\x80\x97\x80\x48\x86\x57\x12\x05\x8c\x5f\xe7\xb5\x60\xb1\x2b\x67\xf7\x37\xea\x6e\x2a\xf9\x24\x2c\xf0\x7a\xd0\xa8\xa6\x79\xf2\x64\x30\x04\x6a\xdc\x3e\x70\x66\x4c\xc9\xc0\xee\x5a\xbc\xef\x6d\x72\x6b\x4e\x04\x17\x60\x48\xb7\x95\xbe\x12\x85\x1b\xdb\x74\x00\x3a\x13\x20\x41\x19\xb8\x68\x64\xd6\x53\x5b\xa0\x95\x04\x0a\x85\xd9\x78\x1c\xf4\xf3\x48\x0a\x30\x4e\x22\x7f\x78\x7a\xd5\x38\xe6\x8f\x4b\xab\x01\x41\x79\xe3\x0d\x3f\xde\xf9\xef\xf1\x1b\xcf\x47\x1f\xa3\xa0\xbc\x74\xb5\x57\x6f\x30\x2d\x3a\x6b\x49\x9f\x11\xf2\xef\x32\x6a\xc0\x26\xc9\x8d\xb1\x0e\x27\x41\x41\x3f\x32\x22\x28\xb3\xcf\xf0\xf3\x37\xba\x2f\x29\x4c\x78\xef\x73\xf0\xe8\x77\x87\x8f\x8f\xc7\xff\x6d\x10\xbc\xe6\x6a\xd6\x28\x43\x79\xb8\x0c\xa8\x93\x27\xd4\xdb\x0b\xf1\x4e\x6d\x8f\x01\xb2\x2a\xb2\x02\xb7\x16\xcc\x07\xe3\xc8\x86\x6d\x16\x8a\x50\x94\xba\xc5\xa4\x95\xe7\x38\x68\xee\xdc\x27\x22\x2e\x64\x44\xf8\x3b\xcf\x65\xac\xdc\x3e\xc8\x91\x20\xbb\x50\xe8\xab\xfc\x28\xb7\x8e\x6d\x98\x0c\x77\x5f\x48\x49\xa0\xe8\xca\xda\x80\x24\x0b\xca\x24\x5e\x39\x96\x6e\x89\xa0\x34\x4d\xf8\x36\x3a\x7d\xcc\x81\xb2\x01\xce\x9c\x75\x3a\xd5\x44\xe1\x12\x4e\x21\x02\x0d\x4c\x62\xde\xda\x9e\xd9\xb9\xd1\xf2\xfb\x7c\x54\xca\x7a\xb0\x9f\x38\x3b\xef\x48\xcf\xc6\x84\x8c\x27\x13\x02\xa1\x0f\xa6\x87\xf5\x6e\x00\xe0\xa7\xd0\x93\xc9\x27\xb4\xfd\xd8\xf1\xbe\xdf\x62\x88\xa0\xe3\x02\x84\x8a\x80\x12\xf1\x27\xa7\x9d\x2d\x30\xa0\x6c\xe1\x7d\x94\xaa\x6f\x7f\x8a\x1e\x6e\xb9\xd0\x68\x1c\x37\x74\xf6\x14\xcc\x6d\xbc\xb2\xa8\x13\xf9\x25\xc6\x30\x6a\x63\x05\x72\xa8\x3e\xc1\x09\xd5\xf5\x33\xc0\x58\x4c\xb4\x21\xd9\x19"}, -{{0xa1,0xac,0x48,0xaa,0x5f,0xfa,0x3d,0x80,0x08,0x19,0xd0,0x3b,0x7f,0x62,0xba,0xbf,0x29,0x1f,0x20,0x90,0x4c,0x11,0xa6,0x40,0x0e,0x4f,0x45,0x20,0x5f,0x10,0x3e,0x38,},{0x08,0x54,0xe0,0x34,0x0f,0x81,0x49,0x85,0xfb,0x12,0x2b,0x78,0x72,0x94,0x79,0xe3,0xfd,0xe8,0x55,0xc2,0x11,0xca,0xde,0xae,0x56,0xf0,0xd4,0xdc,0x08,0x28,0xd5,0xfa,},{0xc5,0x7e,0x3c,0x09,0x1e,0xd2,0x4e,0x5e,0x84,0x66,0x5b,0xd9,0xbb,0x10,0x2d,0xb4,0x97,0x97,0xdf,0x90,0x08,0xf0,0x55,0x57,0xfa,0x0d,0x5a,0xd7,0xa2,0x95,0xe5,0xe4,0xd2,0xa4,0x71,0x6b,0x17,0xf8,0xc9,0x1c,0xb1,0x2f,0x5a,0xbf,0xb1,0xaf,0x02,0x7f,0xb0,0x41,0x11,0x99,0xac,0xc5,0xd2,0x85,0xd8,0x42,0xa4,0xb6,0x5b,0xde,0x49,0x02,},"\xd6\xf1\x24\xed\x75\x20\x21\xc1\x09\x26\x97\x2a\x0c\x26\xf3\xb1\x83\x8b\x3c\x7a\xf2\x47\xc1\x80\x09\xa2\x31\xec\xce\x96\x4b\xf6\x69\x86\x37\x83\x3f\x60\x7d\xca\x83\x6f\x8a\x60\x6c\x72\xae\x3c\xb1\x70\x17\x44\x47\xa2\xcc\xe5\x83\xf6\xe2\x44\xdb\xc1\x63\xe2\x15\xb9\x82\x0d\xe7\x49\x6f\xfc\x5b\x70\x50\xc4\x8f\x28\x30\x24\x66\x78\xcb\xa4\xdc\x5c\xaa\x07\xc1\x45\x85\x63\xaa\x2d\x10\xdc\xb7\x77\x0e\xf8\xfe\xde\x02\x7d\xd7\xf2\x0d\xdc\x8c\xc7\x8c\x3a\x2e\x2e\x95\x8b\xd1\x8c\x00\x06\xcf\x8f\xb8\x2d\x44\xe5\x3e\x1d\xa7\xaa\x80\xfd\x10\x06\xf3\xb2\x30\x0c\x9b\x07\x9d\x8a\x66\xf1\xe4\xa3\xf4\x70\x61\xf9\xe2\xf4\x5d\xae\x35\xdc\x29\x52\x04\xb1\x94\x60\xca\x57\x07\xab\x57\xce\x21\x5a\x24\xc1\x0f\xaa\xb3\xfa\x20\xbc\xcd\x10\x1e\x7a\x7d\x70\x07\x75\x99\xf3\xd6\x72\x57\x07\x55\x21\x29\xca\xd7\x57\xd6\x51\x4c\x1b\x28\x99\x7e\x47\x1f\x94\xb0\xfd\xed\x8f\xbb\xd0\x65\xde\xad\x19\x6d\x2c\x07\xd3\xdf\xa7\xb9\xfb\x3b\xae\x76\x80\xf7\x66\x21\x20\x0d\x09\x9e\xeb\xeb\xbe\xa0\xe8\x95\x7d\xf5\xb5\xe2\x04\xca\x3e\x9e\x29\x52\xb8\xa3\x0f\x0a\x13\x1a\x68\x67\xb1\x38\x1e\x39\x4b\x1b\x44\x43\x10\xf0\x76\x32\x66\x56\xcf\x93\x41\x67\x80\x08\xe9\x52\x51\x47\xd8\xd6\x1c\xe9\x3d\x3b\xf5\x39\x00\xca\xb9\x12\x66\x37\x17\xe0\x98\x72\x93\x83\x3d\x19\x02\xd7\xfb\x04\x7b\x99\x7b\x86\x02\x6c\x46\x7d\x7b\xb1\x7c\xf4\x57\x96\x73\x8f\x7a\x77\x4a\xc1\x26\x76\x4e\xd4\xeb\x45\x12\x43\x09\xf4\x58\x62\x60\x17\x6b\xa4\x65\x91\x8d\x48\x33\x0a\x9c\xc1\x8c\x4e\xce\xa0\xdd\xaf\x38\x94\x6a\xcc\x0e\x36\x1d\xd4\x0a\x7e\x91\x33\xce\xb5\x0e\x1c\x31\x7e\xa4\x2b\xd0\x98\x0a\x72\xb8\xba\x3d\x8a\x6c\x76\x93\xdd\x56\x02\xf3\x74\xf2\x66\x4d\xf4\xba\x56\xdf\x01\xe8\x82\xfc\xa4\x2c\xb4\xdb\x62\x1f\x47\x6c\x76\xe1\xea\x9f\xd1\x05\x91\x1a\x74\xb7\x79\x52\xd9\x91\x4a\x5a\xc0\xf9\x8a\x90\x0c\x1b\x2e\x1a\x56\xc4\xea\x85\x18\xa9\xee\x47\xc4\xed\x14\xd0\xbd\x35\xec\xa5\x60\x31\x9c\x8e\xa2\x47\x55\xd7\x1a\x4e\x03\x08\x50\xbc\x4d\xc6\x03\x89\xf3\x25\x80\x40\x21\x20\x4c\xce\xbc\x25\xfe\xdb\xd3\x2e\xdd\x8d\x84\x46\xaa\x23\xce\x56\xa8\x5f\x77\x9e\x85\x8d\x36\xaf\x7c\x07\x3c\x11\x5e\x34\x1f\x41\x2c\x66\x0f\xab\x80\x0f\xe7\x4c\x50\xe7\x14\xee\x08\x6e\x2f\xbc\x8d\x7a\xbb\xf3\xe9\x8f\xb4\x0c\xa2\x7f\x1f\x01\xa9\xaa\xdd\x8c\xc2\x27\x5c\x2d\xd3\xf7\x6e\x4c\x1d\x81\xc4\xb7\x92\xda\xec\xc9\xfe\x66\x04\x49\x41\xb8\xb2\x91\x84\x86\xdd\x4a\xcb\x56\x2a\x7b\x58\xad\x8c\x60\xc2\x1b\x83\xcf\x48\xae\xfa\x72\x56\xa1\xed\x80\x9e\x66\x98\x11\xf4\x84\x36\x49\x70\xbc\x56\x95\x08\x99\x19\xbc\x32\xd2\x8e\xa7\x52\xe8\xe3\x18\xce\xff\x46\x7f\x77\xae\x19\x77\xc5\xff\xd7\x9c\x17\xc2\xda\x8b\xc7\xf8\x23\xdd\x94\x39\x86\x83\x18\x99\x45\xf8\xb7\x92\x38\xa4\xe8\x15\xb1\x42\xb8\x66\xac\xbd\xbc\xb7\xae\xa7\xf1\x43\xff\xfb\x7c\xc2\xb4\xb5\x4b\xbf\x36\x1a\xfd\xa9\x13\xad\x6d\xf1\xe4\x9d\xfd\x6b\x53\x26\x42\xe6\x3f\x55\xd8\x93\xa4\x70\xd4\x03\x70\x66\x5c\xfb\x74\xef\xd3\xf5\x9c\xb0\xff\x60\x06\x17\x4c\xa3\x5f\x53\xb9\x7c\x54\x3e\x08\xaf\x4b\xf5\xbb\x75\xff\x90\x31\x61\x06\x52\xa3\xf6\xf2\xa0\xcf\xe9\x7e\x7a\x52\x1f\x3d\x2a\x28\x91\x14\xde\xd3\x47\x72\xb0\xe4\x98\x17\xbd\xe1\xcb\x92\x4f\xf5\x14\xe2\x86\x6a\x09\xe3\xed\xe0\x78\x2d\x2c\x0c\x98\xe6\x81\x4b\x8c\x1e\x77\x8c\xf8\x30\x63\x48\xc9\x33\xad\xb2\xe4\x72\xdb\xa0\x9d\xb9\x54\xff\x49\x64\x83\x73\x39\x5a\x2f\x01\x81\x95\x8f\xeb\x1e\xa2\x83\x4c\x99\x53\x28\x73\xdb\x5c\x88\xeb\x52\x89\xc7\x7e\x90\x01\x52\x03\xef\x50\x2a\xc8\xe1\xc4\x8f\xa1\xa0\x6d\xaf\xa6\x51\x9d\x52\xda\xe3\xc5\x56\x75\x70\xdd\x24\x34\xe6\x71\x92\x7c\x66\x36\x3f\x78\x31\x56\x89\x3f\x13\x8a\x84\xc7\x56\x64\xb3\x0a\xe4\x27\x51\x12\x73\x6d\x53\xd4\xf3\x99\xdd\xda\x3d\x23\x06\x7c\x07\x3f\x52\x1a\xfb\xa1\xf7\xbe\x58\x55\x13\xc2\xce\xc9\xc8\xf0\x8d\x2a\x22\xc3\xc8\x53\x92\xcd\x2a\xe5\x0f\x39\x28\x25\x1f\x86\xb3\x10\xc6\x9a\x0f\x8c\x4e\x85\x3a\xb3\xf3\xe8\x12\x9b\x05\x66\xef\x4b\xbb\xe8\x0b\x8c\x02\xc8\x92\x8a\x4d\xe5\x6c\x0d\x11\x9a\x45\xbb\xf5\xaf\x18\x08\xd4\x88\x85\x2d\x8a\x45\xbe\xb0\xd6\x83\x24\x8a\x4d\x65\xde\x15\x26\xb3\xd1\xd2\xff\xc1\xf2\x22\x15\xb6\x08\x46\x8c\xbc\x3b\xd3\x95\x14\xb3\x97\xfc\x0d\xb0\xf1\x13\xdb\xe6\xfc\xe4\x65\x2e\x82\xff\x89\x5b\x2b\x43\x87\xe0\x41\xd7\xe4\xe7\xbd\xe4\x69\x47\x69\x66\x5e\x81"}, -{{0xf5,0xe5,0x76,0x7c,0xf1,0x53,0x31,0x95,0x17,0x63,0x0f,0x22,0x68,0x76,0xb8,0x6c,0x81,0x60,0xcc,0x58,0x3b,0xc0,0x13,0x74,0x4c,0x6b,0xf2,0x55,0xf5,0xcc,0x0e,0xe5,},{0x27,0x81,0x17,0xfc,0x14,0x4c,0x72,0x34,0x0f,0x67,0xd0,0xf2,0x31,0x6e,0x83,0x86,0xce,0xff,0xbf,0x2b,0x24,0x28,0xc9,0xc5,0x1f,0xef,0x7c,0x59,0x7f,0x1d,0x42,0x6e,},{0x0a,0xab,0x4c,0x90,0x05,0x01,0xb3,0xe2,0x4d,0x7c,0xdf,0x46,0x63,0x32,0x6a,0x3a,0x87,0xdf,0x5e,0x48,0x43,0xb2,0xcb,0xdb,0x67,0xcb,0xf6,0xe4,0x60,0xfe,0xc3,0x50,0xaa,0x53,0x71,0xb1,0x50,0x8f,0x9f,0x45,0x28,0xec,0xea,0x23,0xc4,0x36,0xd9,0x4b,0x5e,0x8f,0xcd,0x4f,0x68,0x1e,0x30,0xa6,0xac,0x00,0xa9,0x70,0x4a,0x18,0x8a,0x03,},"\x08\xb8\xb2\xb7\x33\x42\x42\x43\x76\x0f\xe4\x26\xa4\xb5\x49\x08\x63\x21\x10\xa6\x6c\x2f\x65\x91\xea\xbd\x33\x45\xe3\xe4\xeb\x98\xfa\x6e\x26\x4b\xf0\x9e\xfe\x12\xee\x50\xf8\xf5\x4e\x9f\x77\xb1\xe3\x55\xf6\xc5\x05\x44\xe2\x3f\xb1\x43\x3d\xdf\x73\xbe\x84\xd8\x79\xde\x7c\x00\x46\xdc\x49\x96\xd9\xe7\x73\xf4\xbc\x9e\xfe\x57\x38\x82\x9a\xdb\x26\xc8\x1b\x37\xc9\x3a\x1b\x27\x0b\x20\x32\x9d\x65\x86\x75\xfc\x6e\xa5\x34\xe0\x81\x0a\x44\x32\x82\x6b\xf5\x8c\x94\x1e\xfb\x65\xd5\x7a\x33\x8b\xbd\x2e\x26\x64\x0f\x89\xff\xbc\x1a\x85\x8e\xfc\xb8\x55\x0e\xe3\xa5\xe1\x99\x8b\xd1\x77\xe9\x3a\x73\x63\xc3\x44\xfe\x6b\x19\x9e\xe5\xd0\x2e\x82\xd5\x22\xc4\xfe\xba\x15\x45\x2f\x80\x28\x8a\x82\x1a\x57\x91\x16\xec\x6d\xad\x2b\x3b\x31\x0d\xa9\x03\x40\x1a\xa6\x21\x00\xab\x5d\x1a\x36\x55\x3e\x06\x20\x3b\x33\x89\x0c\xc9\xb8\x32\xf7\x9e\xf8\x05\x60\xcc\xb9\xa3\x9c\xe7\x67\x96\x7e\xd6\x28\xc6\xad\x57\x3c\xb1\x16\xdb\xef\xef\xd7\x54\x99\xda\x96\xbd\x68\xa8\xa9\x7b\x92\x8a\x8b\xbc\x10\x3b\x66\x21\xfc\xde\x2b\xec\xa1\x23\x1d\x20\x6b\xe6\xcd\x9e\xc7\xaf\xf6\xf6\xc9\x4f\xcd\x72\x04\xed\x34\x55\xc6\x8c\x83\xf4\xa4\x1d\xa4\xaf\x2b\x74\xef\x5c\x53\xf1\xd8\xac\x70\xbd\xcb\x7e\xd1\x85\xce\x81\xbd\x84\x35\x9d\x44\x25\x4d\x95\x62\x9e\x98\x55\xa9\x4a\x7c\x19\x58\xd1\xf8\xad\xa5\xd0\x53\x2e\xd8\xa5\xaa\x3f\xb2\xd1\x7b\xa7\x0e\xb6\x24\x8e\x59\x4e\x1a\x22\x97\xac\xbb\xb3\x9d\x50\x2f\x1a\x8c\x6e\xb6\xf1\xce\x22\xb3\xde\x1a\x1f\x40\xcc\x24\x55\x41\x19\xa8\x31\xa9\xaa\xd6\x07\x9c\xad\x88\x42\x5d\xe6\xbd\xe1\xa9\x18\x7e\xbb\x60\x92\xcf\x67\xbf\x2b\x13\xfd\x65\xf2\x70\x88\xd7\x8b\x7e\x88\x3c\x87\x59\xd2\xc4\xf5\xc6\x5a\xdb\x75\x53\x87\x8a\xd5\x75\xf9\xfa\xd8\x78\xe8\x0a\x0c\x9b\xa6\x3b\xcb\xcc\x27\x32\xe6\x94\x85\xbb\xc9\xc9\x0b\xfb\xd6\x24\x81\xd9\x08\x9b\xec\xcf\x80\xcf\xe2\xdf\x16\xa2\xcf\x65\xbd\x92\xdd\x59\x7b\x07\x07\xe0\x91\x7a\xf4\x8b\xbb\x75\xfe\xd4\x13\xd2\x38\xf5\x55\x5a\x7a\x56\x9d\x80\xc3\x41\x4a\x8d\x08\x59\xdc\x65\xa4\x61\x28\xba\xb2\x7a\xf8\x7a\x71\x31\x4f\x31\x8c\x78\x2b\x23\xeb\xfe\x80\x8b\x82\xb0\xce\x26\x40\x1d\x2e\x22\xf0\x4d\x83\xd1\x25\x5d\xc5\x1a\xdd\xd3\xb7\x5a\x2b\x1a\xe0\x78\x45\x04\xdf\x54\x3a\xf8\x96\x9b\xe3\xea\x70\x82\xff\x7f\xc9\x88\x8c\x14\x4d\xa2\xaf\x58\x42\x9e\xc9\x60\x31\xdb\xca\xd3\xda\xd9\xaf\x0d\xcb\xaa\xaf\x26\x8c\xb8\xfc\xff\xea\xd9\x4f\x3c\x7c\xa4\x95\xe0\x56\xa9\xb4\x7a\xcd\xb7\x51\xfb\x73\xe6\x66\xc6\xc6\x55\xad\xe8\x29\x72\x97\xd0\x7a\xd1\xba\x5e\x43\xf1\xbc\xa3\x23\x01\x65\x13\x39\xe2\x29\x04\xcc\x8c\x42\xf5\x8c\x30\xc0\x4a\xaf\xdb\x03\x8d\xda\x08\x47\xdd\x98\x8d\xcd\xa6\xf3\xbf\xd1\x5c\x4b\x4c\x45\x25\x00\x4a\xa0\x6e\xef\xf8\xca\x61\x78\x3a\xac\xec\x57\xfb\x3d\x1f\x92\xb0\xfe\x2f\xd1\xa8\x5f\x67\x24\x51\x7b\x65\xe6\x14\xad\x68\x08\xd6\xf6\xee\x34\xdf\xf7\x31\x0f\xdc\x82\xae\xbf\xd9\x04\xb0\x1e\x1d\xc5\x4b\x29\x27\x09\x4b\x2d\xb6\x8d\x6f\x90\x3b\x68\x40\x1a\xde\xbf\x5a\x7e\x08\xd7\x8f\xf4\xef\x5d\x63\x65\x3a\x65\x04\x0c\xf9\xbf\xd4\xac\xa7\x98\x4a\x74\xd3\x71\x45\x98\x67\x80\xfc\x0b\x16\xac\x45\x16\x49\xde\x61\x88\xa7\xdb\xdf\x19\x1f\x64\xb5\xfc\x5e\x2a\xb4\x7b\x57\xf7\xf7\x27\x6c\xd4\x19\xc1\x7a\x3c\xa8\xe1\xb9\x39\xae\x49\xe4\x88\xac\xba\x6b\x96\x56\x10\xb5\x48\x01\x09\xc8\xb1\x7b\x80\xe1\xb7\xb7\x50\xdf\xc7\x59\x8d\x5d\x50\x11\xfd\x2d\xcc\x56\x00\xa3\x2e\xf5\xb5\x2a\x1e\xcc\x82\x0e\x30\x8a\xa3\x42\x72\x1a\xac\x09\x43\xbf\x66\x86\xb6\x4b\x25\x79\x37\x65\x04\xcc\xc4\x93\xd9\x7e\x6a\xed\x3f\xb0\xf9\xcd\x71\xa4\x3d\xd4\x97\xf0\x1f\x17\xc0\xe2\xcb\x37\x97\xaa\x2a\x2f\x25\x66\x56\x16\x8e\x6c\x49\x6a\xfc\x5f\xb9\x32\x46\xf6\xb1\x11\x63\x98\xa3\x46\xf1\xa6\x41\xf3\xb0\x41\xe9\x89\xf7\x91\x4f\x90\xcc\x2c\x7f\xff\x35\x78\x76\xe5\x06\xb5\x0d\x33\x4b\xa7\x7c\x22\x5b\xc3\x07\xba\x53\x71\x52\xf3\xf1\x61\x0e\x4e\xaf\xe5\x95\xf6\xd9\xd9\x0d\x11\xfa\xa9\x33\xa1\x5e\xf1\x36\x95\x46\x86\x8a\x7f\x3a\x45\xa9\x67\x68\xd4\x0f\xd9\xd0\x34\x12\xc0\x91\xc6\x31\x5c\xf4\xfd\xe7\xcb\x68\x60\x69\x37\x38\x0d\xb2\xea\xaa\x70\x7b\x4c\x41\x85\xc3\x2e\xdd\xcd\xd3\x06\x70\x5e\x4d\xc1\xff\xc8\x72\xee\xee\x47\x5a\x64\xdf\xac\x86\xab\xa4\x1c\x06\x18\x98\x3f\x87\x41\xc5\xef\x68\xd3\xa1\x01\xe8\xa3\xb8\xca\xc6\x0c\x90\x5c\x15\xfc\x91\x08\x40\xb9\x4c\x00\xa0\xb9\xd0"}, diff --git a/external/ed25519-donna/test-internals.c b/external/ed25519-donna/test-internals.c deleted file mode 100644 index 3c67df516e..0000000000 --- a/external/ed25519-donna/test-internals.c +++ /dev/null @@ -1,176 +0,0 @@ -#include -#include "ed25519-donna.h" - -static int -test_adds() { -#if defined(HAVE_UINT128) && !defined(ED25519_SSE2) - /* largest result for each limb from a mult or square: all elements except r1 reduced, r1 overflowed as far as possible */ - static const bignum25519 max_bignum = { - 0x7ffffffffffff,0x8000000001230,0x7ffffffffffff,0x7ffffffffffff,0x7ffffffffffff - }; - - /* what max_bignum should fully reduce to */ - static const unsigned char max_bignum_raw[32] = { - 0x12,0x00,0x00,0x00,0x00,0x00,0x88,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 - }; - - /* (max_bignum + max_bignum)^2 */ - static const unsigned char max_bignum2_squared_raw[32] = { - 0x10,0x05,0x00,0x00,0x00,0x00,0x80,0xdc,0x51,0x00,0x00,0x00,0x00,0x61,0xed,0x4a, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - }; - - /* ((max_bignum + max_bignum) + max_bignum)^2 */ - static const unsigned char max_bignum3_squared_raw[32] = { - 0x64,0x0b,0x00,0x00,0x00,0x00,0x20,0x30,0xb8,0x00,0x00,0x00,0x40,0x1a,0x96,0xe8, - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - }; -#else - /* largest result for each limb from a mult or square: all elements except r1 reduced, r1 overflowed as far as possible */ - static const bignum25519 ALIGN(16) max_bignum = { - 0x3ffffff,0x2000300,0x3ffffff,0x1ffffff,0x3ffffff, - 0x1ffffff,0x3ffffff,0x1ffffff,0x3ffffff,0x1ffffff - }; - - /* what max_bignum should fully reduce to */ - static const unsigned char max_bignum2_squared_raw[32] = { - 0x10,0x05,0x00,0x40,0xc2,0x06,0x40,0x80,0x41,0x02,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - }; - - /* (max_bignum * max_bignum) */ - static const unsigned char max_bignum3_squared_raw[32] = { - 0x64,0x0b,0x00,0x10,0x35,0x0f,0x90,0x60,0x13,0x05,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - }; -#endif - unsigned char result[32]; - static const bignum25519 ALIGN(16) zero = {0}; - bignum25519 ALIGN(16) a, b, c; - size_t i; - - /* a = (max_bignum + max_bignum) */ - curve25519_add(a, max_bignum, max_bignum); - - /* b = ((max_bignum + max_bignum) * (max_bignum + max_bignum)) */ - curve25519_mul(b, a, a); - curve25519_contract(result, b); - if (memcmp(result, max_bignum2_squared_raw, 32) != 0) - return -1; - curve25519_square(b, a); - curve25519_contract(result, b); - if (memcmp(result, max_bignum2_squared_raw, 32) != 0) - return -1; - - /* b = (max_bignum + max_bignum + max_bignum) */ - curve25519_add_after_basic(b, a, max_bignum); - - /* a = ((max_bignum + max_bignum + max_bignum) * (max_bignum + max_bignum + max_bignum)) */ - curve25519_mul(a, b, b); - curve25519_contract(result, a); - if (memcmp(result, max_bignum3_squared_raw, 32) != 0) - return -1; - curve25519_square(a, b); - curve25519_contract(result, a); - if (memcmp(result, max_bignum3_squared_raw, 32) != 0) - return -1; - - return 0; -} - -static int -test_subs() { -#if defined(HAVE_UINT128) && !defined(ED25519_SSE2) - /* largest result for each limb from a mult or square: all elements except r1 reduced, r1 overflowed as far as possible */ - static const bignum25519 max_bignum = { - 0x7ffffffffffff,0x8000000001230,0x7ffffffffffff,0x7ffffffffffff,0x7ffffffffffff - }; - - /* what max_bignum should fully reduce to */ - static const unsigned char max_bignum_raw[32] = { - 0x12,0x00,0x00,0x00,0x00,0x00,0x88,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 - }; - - /* (max_bignum * max_bignum) */ - static const unsigned char max_bignum_squared_raw[32] = { - 0x44,0x01,0x00,0x00,0x00,0x00,0x20,0x77,0x14,0x00,0x00,0x00,0x40,0x58,0xbb,0x52, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 - }; -#else - /* largest result for each limb from a mult or square: all elements except r1 reduced, r1 overflowed as far as possible */ - static const bignum25519 ALIGN(16) max_bignum = { - 0x3ffffff,0x2000300,0x3ffffff,0x1ffffff,0x3ffffff, - 0x1ffffff,0x3ffffff,0x1ffffff,0x3ffffff,0x1ffffff - }; - - /* what max_bignum should fully reduce to */ - static const unsigned char max_bignum_raw[32] = { - 0x12,0x00,0x00,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - }; - - /* (max_bignum * max_bignum) */ - static const unsigned char max_bignum_squared_raw[32] = { - 0x44,0x01,0x00,0x90,0xb0,0x01,0x10,0x60,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - }; -#endif - unsigned char result[32]; - static const bignum25519 ALIGN(16) zero = {0}; - bignum25519 ALIGN(16) a, b, c; - size_t i; - - /* a = max_bignum - 0, which expands to 2p + max_bignum - 0 */ - curve25519_sub(a, max_bignum, zero); - curve25519_contract(result, a); - if (memcmp(result, max_bignum_raw, 32) != 0) - return -1; - - /* b = (max_bignum * max_bignum) */ - curve25519_mul(b, a, a); - curve25519_contract(result, b); - if (memcmp(result, max_bignum_squared_raw, 32) != 0) - return -1; - curve25519_square(b, a); - curve25519_contract(result, b); - if (memcmp(result, max_bignum_squared_raw, 32) != 0) - return -1; - - /* b = ((a - 0) - 0) */ - curve25519_sub_after_basic(b, a, zero); - curve25519_contract(result, b); - if (memcmp(result, max_bignum_raw, 32) != 0) - return -1; - - /* a = (max_bignum * max_bignum) */ - curve25519_mul(a, b, b); - curve25519_contract(result, a); - if (memcmp(result, max_bignum_squared_raw, 32) != 0) - return -1; - curve25519_square(a, b); - curve25519_contract(result, a); - if (memcmp(result, max_bignum_squared_raw, 32) != 0) - return -1; - - - return 0; -} - - -int -main() { - int ret = 0; - int single; - single = test_adds(); - if (single) printf("test_adds: FAILED\n"); - ret |= single; - single = test_subs(); - if (single) printf("test_subs: FAILED\n"); - ret |= single; - if (!ret) printf("success\n"); - return ret; -} - - diff --git a/external/ed25519-donna/test-ticks.h b/external/ed25519-donna/test-ticks.h deleted file mode 100644 index 0103e03dde..0000000000 --- a/external/ed25519-donna/test-ticks.h +++ /dev/null @@ -1,50 +0,0 @@ -#include "ed25519-donna-portable-identify.h" - -/* ticks - not tested on anything other than x86 */ -static uint64_t -get_ticks(void) { -#if defined(CPU_X86) || defined(CPU_X86_64) - #if defined(COMPILER_INTEL) - return _rdtsc(); - #elif defined(COMPILER_MSVC) - return __rdtsc(); - #elif defined(COMPILER_GCC) - uint32_t lo, hi; - __asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi)); - return ((uint64_t)lo | ((uint64_t)hi << 32)); - #else - need rdtsc for this compiler - #endif -#elif defined(OS_SOLARIS) - return (uint64_t)gethrtime(); -#elif defined(CPU_SPARC) && !defined(OS_OPENBSD) - uint64_t t; - __asm__ __volatile__("rd %%tick, %0" : "=r" (t)); - return t; -#elif defined(CPU_PPC) - uint32_t lo = 0, hi = 0; - __asm__ __volatile__("mftbu %0; mftb %1" : "=r" (hi), "=r" (lo)); - return ((uint64_t)lo | ((uint64_t)hi << 32)); -#elif defined(CPU_IA64) - uint64_t t; - __asm__ __volatile__("mov %0=ar.itc" : "=r" (t)); - return t; -#elif defined(OS_NIX) - timeval t2; - gettimeofday(&t2, NULL); - t = ((uint64_t)t2.tv_usec << 32) | (uint64_t)t2.tv_sec; - return t; -#else - need ticks for this platform -#endif -} - -#define timeit(x,minvar) \ - ticks = get_ticks(); \ - x; \ - ticks = get_ticks() - ticks; \ - if (ticks < minvar) \ - minvar = ticks; - -#define maxticks 0xffffffffffffffffull - diff --git a/external/ed25519-donna/test.c b/external/ed25519-donna/test.c deleted file mode 100644 index 6154492503..0000000000 --- a/external/ed25519-donna/test.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - Validate ed25519 implementation against the official test vectors from - http://ed25519.cr.yp.to/software.html -*/ - -#include -#include -#include "ed25519.h" - -#include "test-ticks.h" - -static void -edassert(int check, int round, const char *failreason) { - if (check) - return; - printf("round %d, %s\n", round, failreason); - exit(1); -} - -static void -edassert_die(const unsigned char *a, const unsigned char *b, size_t len, int round, const char *failreason) { - size_t i; - if (round > 0) - printf("round %d, %s\n", round, failreason); - else - printf("%s\n", failreason); - printf("want: "); for (i = 0; i < len; i++) printf("%02x,", a[i]); printf("\n"); - printf("got : "); for (i = 0; i < len; i++) printf("%02x,", b[i]); printf("\n"); - printf("diff: "); for (i = 0; i < len; i++) if (a[i] ^ b[i]) printf("%02x,", a[i] ^ b[i]); else printf(" ,"); printf("\n\n"); - exit(1); -} - -static void -edassert_equal(const unsigned char *a, const unsigned char *b, size_t len, const char *failreason) { - if (memcmp(a, b, len) == 0) - return; - edassert_die(a, b, len, -1, failreason); -} - -static void -edassert_equal_round(const unsigned char *a, const unsigned char *b, size_t len, int round, const char *failreason) { - if (memcmp(a, b, len) == 0) - return; - edassert_die(a, b, len, round, failreason); -} - - -/* test data */ -typedef struct test_data_t { - unsigned char sk[32], pk[32], sig[64]; - const char *m; -} test_data; - - -test_data dataset[] = { -#include "regression.h" -}; - -/* result of the curve25519 scalarmult ((|255| * basepoint) * basepoint)... 1024 times */ -const curved25519_key curved25519_expected = { - 0xac,0xce,0x24,0xb1,0xd4,0xa2,0x36,0x21, - 0x15,0xe2,0x3e,0x84,0x3c,0x23,0x2b,0x5f, - 0x95,0x6c,0xc0,0x7b,0x95,0x82,0xd7,0x93, - 0xd5,0x19,0xb6,0xf1,0xfb,0x96,0xd6,0x04 -}; - - -/* from ed25519-donna-batchverify.h */ -extern unsigned char batch_point_buffer[3][32]; - -/* y coordinate of the final point from 'amd64-51-30k' with the same random generator */ -static const unsigned char batch_verify_y[32] = { - 0x51,0xe7,0x68,0xe0,0xf7,0xa1,0x88,0x45, - 0xde,0xa1,0xcb,0xd9,0x37,0xd4,0x78,0x53, - 0x1b,0x95,0xdb,0xbe,0x66,0x59,0x29,0x3b, - 0x94,0x51,0x2f,0xbc,0x0d,0x66,0xba,0x3f -}; - -/* -static const unsigned char batch_verify_y[32] = { - 0x5c,0x63,0x96,0x26,0xca,0xfe,0xfd,0xc4, - 0x2d,0x11,0xa8,0xe4,0xc4,0x46,0x42,0x97, - 0x97,0x92,0xbe,0xe0,0x3c,0xef,0x96,0x01, - 0x50,0xa1,0xcc,0x8f,0x50,0x85,0x76,0x7d -}; - -Introducing the 128 bit r scalars to the heap _before_ the largest scalar -fits in to 128 bits alters the heap shape and produces a different, -yet still neutral/valid y/z value. - -This was the value of introducing the r scalars when the largest scalar fit -in to 135-256 bits. You can produce it with amd64-64-24k / amd64-51-32k -with the random sequence used in the first pass by changing - - unsigned long long hlen=((npoints+1)/2)|1; - -to - - unsigned long long hlen=npoints; - -in ge25519_multi_scalarmult.c - -ed25519-donna-batchverify.h has been modified to match the -default amd64-64-24k / amd64-51-32k behaviour -*/ - - - -/* batch test */ -#define test_batch_count 64 -#define test_batch_rounds 96 - -typedef enum batch_test_t { - batch_no_errors = 0, - batch_wrong_message = 1, - batch_wrong_pk = 2, - batch_wrong_sig = 3 -} batch_test; - -static int -test_batch_instance(batch_test type, uint64_t *ticks) { - ed25519_secret_key sks[test_batch_count]; - ed25519_public_key pks[test_batch_count]; - ed25519_signature sigs[test_batch_count]; - unsigned char messages[test_batch_count][128]; - size_t message_lengths[test_batch_count]; - const unsigned char *message_pointers[test_batch_count]; - const unsigned char *pk_pointers[test_batch_count]; - const unsigned char *sig_pointers[test_batch_count]; - int valid[test_batch_count], ret, validret; - size_t i; - uint64_t t; - - /* generate keys */ - for (i = 0; i < test_batch_count; i++) { - ed25519_randombytes_unsafe(sks[i], sizeof(sks[i])); - ed25519_publickey(sks[i], pks[i]); - pk_pointers[i] = pks[i]; - } - - /* generate messages */ - ed25519_randombytes_unsafe(messages, sizeof(messages)); - for (i = 0; i < test_batch_count; i++) { - message_pointers[i] = messages[i]; - message_lengths[i] = (i & 127) + 1; - } - - /* sign messages */ - for (i = 0; i < test_batch_count; i++) { - ed25519_sign(message_pointers[i], message_lengths[i], sks[i], pks[i], sigs[i]); - sig_pointers[i] = sigs[i]; - } - - validret = 0; - if (type == batch_wrong_message) { - message_pointers[0] = message_pointers[1]; - validret = 1|2; - } else if (type == batch_wrong_pk) { - pk_pointers[0] = pk_pointers[1]; - validret = 1|2; - } else if (type == batch_wrong_sig) { - sig_pointers[0] = sig_pointers[1]; - validret = 1|2; - } - - /* batch verify */ - t = get_ticks(); - ret = ed25519_sign_open_batch(message_pointers, message_lengths, pk_pointers, sig_pointers, test_batch_count, valid); - *ticks = get_ticks() - t; - edassert_equal((unsigned char *)&validret, (unsigned char *)&ret, sizeof(int), "batch return code"); - for (i = 0; i < test_batch_count; i++) { - validret = ((type == batch_no_errors) || (i != 0)) ? 1 : 0; - edassert_equal((unsigned char *)&validret, (unsigned char *)&valid[i], sizeof(int), "individual batch return code"); - } - return ret; -} - -static void -test_batch(void) { - uint64_t dummy_ticks, ticks[test_batch_rounds], best = maxticks, sum; - size_t i, count; - - /* check the first pass for the expected result */ - test_batch_instance(batch_no_errors, &dummy_ticks); - edassert_equal(batch_verify_y, batch_point_buffer[1], 32, "failed to generate expected result"); - - /* make sure ge25519_multi_scalarmult_vartime throws an error on the entire batch with wrong data */ - for (i = 0; i < 4; i++) { - test_batch_instance(batch_wrong_message, &dummy_ticks); - test_batch_instance(batch_wrong_pk, &dummy_ticks); - test_batch_instance(batch_wrong_sig, &dummy_ticks); - } - - /* speed test */ - for (i = 0; i < test_batch_rounds; i++) { - test_batch_instance(batch_no_errors, &ticks[i]); - if (ticks[i] < best) - best = ticks[i]; - } - - /* take anything within 1% of the best time */ - for (i = 0, sum = 0, count = 0; i < test_batch_rounds; i++) { - if (ticks[i] < (best * 1.01)) { - sum += ticks[i]; - count++; - } - } - printf("%.0f ticks/verification\n", (double)sum / (count * test_batch_count)); -} - -static void -test_main(void) { - int i, res; - ed25519_public_key pk; - ed25519_signature sig; - unsigned char forge[1024] = {'x'}; - curved25519_key csk[2] = {{255}}; - uint64_t ticks, pkticks = maxticks, signticks = maxticks, openticks = maxticks, curvedticks = maxticks; - - for (i = 0; i < 1024; i++) { - ed25519_publickey(dataset[i].sk, pk); - edassert_equal_round(dataset[i].pk, pk, sizeof(pk), i, "public key didn't match"); - ed25519_sign((unsigned char *)dataset[i].m, i, dataset[i].sk, pk, sig); - edassert_equal_round(dataset[i].sig, sig, sizeof(sig), i, "signature didn't match"); - edassert(!ed25519_sign_open((unsigned char *)dataset[i].m, i, pk, sig), i, "failed to open message"); - - memcpy(forge, dataset[i].m, i); - if (i) - forge[i - 1] += 1; - - edassert(ed25519_sign_open(forge, (i) ? i : 1, pk, sig), i, "opened forged message"); - } - - for (i = 0; i < 1024; i++) - curved25519_scalarmult_basepoint(csk[(i & 1) ^ 1], csk[i & 1]); - edassert_equal(curved25519_expected, csk[0], sizeof(curved25519_key), "curve25519 failed to generate correct value"); - - for (i = 0; i < 2048; i++) { - timeit(ed25519_publickey(dataset[0].sk, pk), pkticks) - edassert_equal_round(dataset[0].pk, pk, sizeof(pk), i, "public key didn't match"); - timeit(ed25519_sign((unsigned char *)dataset[0].m, 0, dataset[0].sk, pk, sig), signticks) - edassert_equal_round(dataset[0].sig, sig, sizeof(sig), i, "signature didn't match"); - timeit(res = ed25519_sign_open((unsigned char *)dataset[0].m, 0, pk, sig), openticks) - edassert(!res, 0, "failed to open message"); - timeit(curved25519_scalarmult_basepoint(csk[1], csk[0]), curvedticks); - } - - printf("%.0f ticks/public key generation\n", (double)pkticks); - printf("%.0f ticks/signature\n", (double)signticks); - printf("%.0f ticks/signature verification\n", (double)openticks); - printf("%.0f ticks/curve25519 basepoint scalarmult\n", (double)curvedticks); -} - -int -main(void) { - test_main(); - test_batch(); - return 0; -} - From c9f17dd85d6e24e2908083ab6ff3e39478004b55 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 1 Dec 2025 23:16:50 +0530 Subject: [PATCH 027/105] docs: Update CONTRIBUTING.md for XLS submission guidelines (#6065) This change clarifies the status of XLS in the pull request process. --- CONTRIBUTING.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a5e0933d00..760e11bea6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,13 +47,18 @@ choose the next available standard number, and open a discussion with an appropriate title to propose your draft standard. When you submit a pull request, please link the corresponding XLS in the -description. An XLS still in draft status is considered a +description. An XLS still in `Draft` status is considered a work-in-progress and open for discussion. Please allow time for questions, suggestions, and changes to the XLS draft. It is the responsibility of the XLS author to update the draft to match the final implementation when its corresponding pull request is merged, unless the author delegates that responsibility to others. +Any amendment or major RPC change requires either a new XLS or an update +to an existing XLS. Neither change will be released (in an amendment's +case, marked as `Supported::yes`) until the corresponding XLS's status +is `Final`. + ## Before making a pull request (Or marking a draft pull request as ready.) From 6c67f1f525aa902e7c3cc3ff43b501ec5915da59 Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Tue, 2 Dec 2025 11:38:17 -0500 Subject: [PATCH 028/105] Implement Lending Protocol (unsupported) (#5270) - Spec: XLS-66 - Introduces amendment "LendingProtocol", but leaves it UNSUPPORTED to allow for standalone testing, future development work, and potential bug fixes. - AccountInfo RPC will indicate the type of pseudo-account when appropriate. - Refactors and improves several existing classes and functional areas, including Number, STAmount, STObject, json_value, Asset, directory handling, View helper functions, and unit test helpers. --- include/xrpl/basics/Number.h | 32 +- include/xrpl/beast/utility/instrumentation.h | 2 +- include/xrpl/json/json_value.h | 3 + include/xrpl/ledger/ApplyView.h | 39 + include/xrpl/ledger/View.h | 251 +- include/xrpl/protocol/Asset.h | 22 +- include/xrpl/protocol/Indexes.h | 18 + include/xrpl/protocol/LedgerFormats.h | 5 + include/xrpl/protocol/Protocol.h | 135 + include/xrpl/protocol/SField.h | 4 +- include/xrpl/protocol/STAmount.h | 76 +- include/xrpl/protocol/STObject.h | 29 +- include/xrpl/protocol/TxFlags.h | 26 + include/xrpl/protocol/detail/features.macro | 5 + .../xrpl/protocol/detail/ledger_entries.macro | 119 +- include/xrpl/protocol/detail/sfields.macro | 45 +- .../xrpl/protocol/detail/transactions.macro | 133 + include/xrpl/protocol/jss.h | 5 + src/libxrpl/basics/Number.cpp | 158 +- src/libxrpl/json/json_value.cpp | 6 + src/libxrpl/ledger/ApplyView.cpp | 187 +- src/libxrpl/ledger/View.cpp | 842 +- src/libxrpl/protocol/Indexes.cpp | 14 + src/libxrpl/protocol/InnerObjectFormats.cpp | 8 + src/libxrpl/protocol/STAmount.cpp | 35 +- src/libxrpl/protocol/STTx.cpp | 5 +- src/test/app/Batch_test.cpp | 202 + src/test/app/Invariants_test.cpp | 441 +- src/test/app/LoanBroker_test.cpp | 1462 ++++ src/test/app/Loan_test.cpp | 7215 +++++++++++++++++ src/test/app/MPToken_test.cpp | 6 +- src/test/app/Vault_test.cpp | 221 +- src/test/basics/Number_test.cpp | 110 + src/test/jtx.h | 1 + src/test/jtx/Env.h | 4 +- src/test/jtx/JTx.h | 3 + src/test/jtx/TestHelpers.h | 129 + src/test/jtx/amount.h | 34 + src/test/jtx/batch.h | 3 +- src/test/jtx/impl/Env.cpp | 28 +- src/test/jtx/impl/TestHelpers.cpp | 128 + src/test/jtx/impl/mpt.cpp | 266 +- src/test/jtx/impl/testline.cpp | 15 + src/test/jtx/mpt.h | 84 +- src/test/jtx/testline.h | 34 + src/test/protocol/STParsedJSON_test.cpp | 40 +- .../app/ledger/detail/LedgerReplayTask.cpp | 2 +- src/xrpld/app/ledger/detail/OpenLedger.cpp | 5 +- src/xrpld/app/misc/LendingHelpers.h | 444 + src/xrpld/app/misc/NetworkOPs.cpp | 17 +- src/xrpld/app/misc/detail/LendingHelpers.cpp | 2058 +++++ src/xrpld/app/tx/detail/Batch.cpp | 15 +- src/xrpld/app/tx/detail/Batch.h | 18 + src/xrpld/app/tx/detail/Change.cpp | 6 +- src/xrpld/app/tx/detail/InvariantCheck.cpp | 500 +- src/xrpld/app/tx/detail/InvariantCheck.h | 123 +- .../app/tx/detail/LoanBrokerCoverClawback.cpp | 340 + .../app/tx/detail/LoanBrokerCoverClawback.h | 34 + .../app/tx/detail/LoanBrokerCoverDeposit.cpp | 123 + .../app/tx/detail/LoanBrokerCoverDeposit.h | 34 + .../app/tx/detail/LoanBrokerCoverWithdraw.cpp | 173 + .../app/tx/detail/LoanBrokerCoverWithdraw.h | 34 + src/xrpld/app/tx/detail/LoanBrokerDelete.cpp | 197 + src/xrpld/app/tx/detail/LoanBrokerDelete.h | 34 + src/xrpld/app/tx/detail/LoanBrokerSet.cpp | 215 + src/xrpld/app/tx/detail/LoanBrokerSet.h | 34 + src/xrpld/app/tx/detail/LoanDelete.cpp | 133 + src/xrpld/app/tx/detail/LoanDelete.h | 34 + src/xrpld/app/tx/detail/LoanManage.cpp | 420 + src/xrpld/app/tx/detail/LoanManage.h | 66 + src/xrpld/app/tx/detail/LoanPay.cpp | 602 ++ src/xrpld/app/tx/detail/LoanPay.h | 40 + src/xrpld/app/tx/detail/LoanSet.cpp | 632 ++ src/xrpld/app/tx/detail/LoanSet.h | 59 + src/xrpld/app/tx/detail/MPTokenAuthorize.cpp | 9 +- src/xrpld/app/tx/detail/SetTrust.cpp | 4 +- src/xrpld/app/tx/detail/Transactor.cpp | 32 +- src/xrpld/app/tx/detail/Transactor.h | 35 +- src/xrpld/app/tx/detail/VaultCreate.cpp | 7 +- src/xrpld/app/tx/detail/VaultDeposit.cpp | 36 +- src/xrpld/app/tx/detail/VaultSet.cpp | 7 +- src/xrpld/app/tx/detail/VaultWithdraw.cpp | 105 +- src/xrpld/overlay/detail/PeerImp.cpp | 38 +- src/xrpld/rpc/detail/TransactionSign.cpp | 6 +- src/xrpld/rpc/handlers/AccountInfo.cpp | 22 + src/xrpld/rpc/handlers/LedgerEntry.cpp | 40 + 86 files changed, 18810 insertions(+), 553 deletions(-) create mode 100644 src/test/app/LoanBroker_test.cpp create mode 100644 src/test/app/Loan_test.cpp create mode 100644 src/test/jtx/impl/testline.cpp create mode 100644 src/test/jtx/testline.h create mode 100644 src/xrpld/app/misc/LendingHelpers.h create mode 100644 src/xrpld/app/misc/detail/LendingHelpers.cpp create mode 100644 src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp create mode 100644 src/xrpld/app/tx/detail/LoanBrokerCoverClawback.h create mode 100644 src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp create mode 100644 src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.h create mode 100644 src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp create mode 100644 src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h create mode 100644 src/xrpld/app/tx/detail/LoanBrokerDelete.cpp create mode 100644 src/xrpld/app/tx/detail/LoanBrokerDelete.h create mode 100644 src/xrpld/app/tx/detail/LoanBrokerSet.cpp create mode 100644 src/xrpld/app/tx/detail/LoanBrokerSet.h create mode 100644 src/xrpld/app/tx/detail/LoanDelete.cpp create mode 100644 src/xrpld/app/tx/detail/LoanDelete.h create mode 100644 src/xrpld/app/tx/detail/LoanManage.cpp create mode 100644 src/xrpld/app/tx/detail/LoanManage.h create mode 100644 src/xrpld/app/tx/detail/LoanPay.cpp create mode 100644 src/xrpld/app/tx/detail/LoanPay.h create mode 100644 src/xrpld/app/tx/detail/LoanSet.cpp create mode 100644 src/xrpld/app/tx/detail/LoanSet.h diff --git a/include/xrpl/basics/Number.h b/include/xrpl/basics/Number.h index e34cc61b5b..4a4ee1cacb 100644 --- a/include/xrpl/basics/Number.h +++ b/include/xrpl/basics/Number.h @@ -13,6 +13,15 @@ class Number; std::string to_string(Number const& amount); +template +constexpr bool +isPowerOfTen(T value) +{ + while (value >= 10 && value % 10 == 0) + value /= 10; + return value == 1; +} + class Number { using rep = std::int64_t; @@ -22,7 +31,9 @@ class Number public: // The range for the mantissa when normalized constexpr static std::int64_t minMantissa = 1'000'000'000'000'000LL; - constexpr static std::int64_t maxMantissa = 9'999'999'999'999'999LL; + static_assert(isPowerOfTen(minMantissa)); + constexpr static std::int64_t maxMantissa = minMantissa * 10 - 1; + static_assert(maxMantissa == 9'999'999'999'999'999LL); // The range for the exponent when normalized constexpr static int minExponent = -32768; @@ -132,22 +143,7 @@ public: } Number - truncate() const noexcept - { - if (exponent_ >= 0 || mantissa_ == 0) - return *this; - - Number ret = *this; - while (ret.exponent_ < 0 && ret.mantissa_ != 0) - { - ret.exponent_ += 1; - ret.mantissa_ /= rep(10); - } - // We are guaranteed that normalize() will never throw an exception - // because exponent is either negative or zero at this point. - ret.normalize(); - return ret; - } + truncate() const noexcept; friend constexpr bool operator>(Number const& x, Number const& y) noexcept @@ -192,6 +188,8 @@ private: class Guard; }; +constexpr static Number numZero{}; + inline constexpr Number::Number(rep mantissa, int exponent, unchecked) noexcept : mantissa_{mantissa}, exponent_{exponent} { diff --git a/include/xrpl/beast/utility/instrumentation.h b/include/xrpl/beast/utility/instrumentation.h index 1234e3075c..3c364b64e6 100644 --- a/include/xrpl/beast/utility/instrumentation.h +++ b/include/xrpl/beast/utility/instrumentation.h @@ -13,7 +13,7 @@ // The duplication is because Visual Studio 2019 cannot compile that header // even with the option -Zc:__cplusplus added. #define ALWAYS(cond, message, ...) assert((message) && (cond)) -#define ALWAYS_OR_UNREACHABLE(cond, message, ...) assert((message) && (cond)) +#define ALWAYS_OR_UNREACHABLE(cond, message) assert((message) && (cond)) #define SOMETIMES(cond, message, ...) #define REACHABLE(message, ...) #define UNREACHABLE(message, ...) assert((message) && false) diff --git a/include/xrpl/json/json_value.h b/include/xrpl/json/json_value.h index 6b460ecd3b..c14d5d5127 100644 --- a/include/xrpl/json/json_value.h +++ b/include/xrpl/json/json_value.h @@ -381,6 +381,9 @@ public: /// Return true if the object has a member named key. bool isMember(std::string const& key) const; + /// Return true if the object has a member named key. + bool + isMember(StaticString const& key) const; /// \brief Return a list of the member names. /// diff --git a/include/xrpl/ledger/ApplyView.h b/include/xrpl/ledger/ApplyView.h index fc82e94b5c..5e283641da 100644 --- a/include/xrpl/ledger/ApplyView.h +++ b/include/xrpl/ledger/ApplyView.h @@ -368,6 +368,45 @@ public: emptyDirDelete(Keylet const& directory); }; +namespace directory { +/** Helper functions for managing low-level directory operations. + These are not part of the ApplyView interface. + + Don't use them unless you really, really know what you're doing. + Instead use dirAdd, dirInsert, etc. + */ + +std::uint64_t +createRoot( + ApplyView& view, + Keylet const& directory, + uint256 const& key, + std::function const&)> const& describe); + +auto +findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start); + +std::uint64_t +insertKey( + ApplyView& view, + SLE::ref node, + std::uint64_t page, + bool preserveOrder, + STVector256& indexes, + uint256 const& key); + +std::optional +insertPage( + ApplyView& view, + std::uint64_t page, + SLE::pointer node, + std::uint64_t nextPage, + SLE::ref next, + uint256 const& key, + Keylet const& directory, + std::function const&)> const& describe); + +} // namespace directory } // namespace ripple #endif diff --git a/include/xrpl/ledger/View.h b/include/xrpl/ledger/View.h index 9635115f0c..fc16d53e61 100644 --- a/include/xrpl/ledger/View.h +++ b/include/xrpl/ledger/View.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -223,6 +224,80 @@ isDeepFrozen( Currency const& currency, AccountID const& issuer); +[[nodiscard]] inline bool +isDeepFrozen( + ReadView const& view, + AccountID const& account, + Issue const& issue, + int = 0 /*ignored*/) +{ + return isDeepFrozen(view, account, issue.currency, issue.account); +} + +[[nodiscard]] inline bool +isDeepFrozen( + ReadView const& view, + AccountID const& account, + MPTIssue const& mptIssue, + int depth = 0) +{ + // Unlike IOUs, frozen / locked MPTs are not allowed to send or receive + // funds, so checking "deep frozen" is the same as checking "frozen". + return isFrozen(view, account, mptIssue, depth); +} + +/** + * isFrozen check is recursive for MPT shares in a vault, descending to + * assets in the vault, up to maxAssetCheckDepth recursion depth. This is + * purely defensive, as we currently do not allow such vaults to be created. + */ +[[nodiscard]] inline bool +isDeepFrozen( + ReadView const& view, + AccountID const& account, + Asset const& asset, + int depth = 0) +{ + return std::visit( + [&](auto const& issue) { + return isDeepFrozen(view, account, issue, depth); + }, + asset.value()); +} + +[[nodiscard]] inline TER +checkDeepFrozen( + ReadView const& view, + AccountID const& account, + Issue const& issue) +{ + return isDeepFrozen(view, account, issue) ? (TER)tecFROZEN + : (TER)tesSUCCESS; +} + +[[nodiscard]] inline TER +checkDeepFrozen( + ReadView const& view, + AccountID const& account, + MPTIssue const& mptIssue) +{ + return isDeepFrozen(view, account, mptIssue) ? (TER)tecLOCKED + : (TER)tesSUCCESS; +} + +[[nodiscard]] inline TER +checkDeepFrozen( + ReadView const& view, + AccountID const& account, + Asset const& asset) +{ + return std::visit( + [&](auto const& issue) { + return checkDeepFrozen(view, account, issue); + }, + asset.value()); +} + [[nodiscard]] bool isLPTokenFrozen( ReadView const& view, @@ -268,6 +343,49 @@ accountHolds( AuthHandling zeroIfUnauthorized, beast::Journal j); +// Returns the amount an account can spend total. +// +// These functions use accountHolds, but unlike accountHolds: +// * The account can go into debt. +// * If the account is the asset issuer the only limit is defined by the asset / +// issuance. +// +// <-- saAmount: amount of currency held by account. May be negative. +[[nodiscard]] STAmount +accountSpendable( + ReadView const& view, + AccountID const& account, + Currency const& currency, + AccountID const& issuer, + FreezeHandling zeroIfFrozen, + beast::Journal j); + +[[nodiscard]] STAmount +accountSpendable( + ReadView const& view, + AccountID const& account, + Issue const& issue, + FreezeHandling zeroIfFrozen, + beast::Journal j); + +[[nodiscard]] STAmount +accountSpendable( + ReadView const& view, + AccountID const& account, + MPTIssue const& mptIssue, + FreezeHandling zeroIfFrozen, + AuthHandling zeroIfUnauthorized, + beast::Journal j); + +[[nodiscard]] STAmount +accountSpendable( + ReadView const& view, + AccountID const& account, + Asset const& asset, + FreezeHandling zeroIfFrozen, + AuthHandling zeroIfUnauthorized, + beast::Journal j); + // Returns the amount an account can spend of the currency type saDefault, or // returns saDefault if this account is the issuer of the currency in // question. Should be used in favor of accountHolds when questioning how much @@ -514,7 +632,11 @@ dirNext( describeOwnerDir(AccountID const& account); [[nodiscard]] TER -dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr& object); +dirLink( + ApplyView& view, + AccountID const& owner, + std::shared_ptr& object, + SF_UINT64 const& node = sfOwnerNode); AccountID pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey); @@ -533,14 +655,17 @@ createPseudoAccount( uint256 const& pseudoOwnerKey, SField const& ownerField); -// Returns true iff sleAcct is a pseudo-account. +// Returns true iff sleAcct is a pseudo-account or specific +// pseudo-accounts in pseudoFieldFilter. // // Returns false if sleAcct is // * NOT a pseudo-account OR // * NOT a ltACCOUNT_ROOT OR // * null pointer [[nodiscard]] bool -isPseudoAccount(std::shared_ptr sleAcct); +isPseudoAccount( + std::shared_ptr sleAcct, + std::set const& pseudoFieldFilter = {}); // Returns the list of fields that define an ACCOUNT_ROOT as a pseudo-account if // set @@ -554,14 +679,91 @@ isPseudoAccount(std::shared_ptr sleAcct); getPseudoAccountFields(); [[nodiscard]] inline bool -isPseudoAccount(ReadView const& view, AccountID accountId) +isPseudoAccount( + ReadView const& view, + AccountID const& accountId, + std::set const& pseudoFieldFilter = {}) { - return isPseudoAccount(view.read(keylet::account(accountId))); + return isPseudoAccount( + view.read(keylet::account(accountId)), pseudoFieldFilter); } [[nodiscard]] TER canAddHolding(ReadView const& view, Asset const& asset); +/** Validates that the destination SLE and tag are valid + + - Checks that the SLE is not null. + - If the SLE requires a destination tag, checks that there is a tag. +*/ +[[nodiscard]] TER +checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag); + +/** Checks that can withdraw funds from an object to itself or a destination. + * + * The receiver may be either the submitting account (sfAccount) or a different + * destination account (sfDestination). + * + * - Checks that the receiver account exists. + * - If the receiver requires a destination tag, check that one exists, even + * if withdrawing to self. + * - If withdrawing to self, succeed. + * - If not, checks if the receiver requires deposit authorization, and if + * the sender has it. + */ +[[nodiscard]] TER +canWithdraw( + AccountID const& from, + ReadView const& view, + AccountID const& to, + SLE::const_ref toSle, + bool hasDestinationTag); + +/** Checks that can withdraw funds from an object to itself or a destination. + * + * The receiver may be either the submitting account (sfAccount) or a different + * destination account (sfDestination). + * + * - Checks that the receiver account exists. + * - If the receiver requires a destination tag, check that one exists, even + * if withdrawing to self. + * - If withdrawing to self, succeed. + * - If not, checks if the receiver requires deposit authorization, and if + * the sender has it. + */ +[[nodiscard]] TER +canWithdraw( + AccountID const& from, + ReadView const& view, + AccountID const& to, + bool hasDestinationTag); + +/** Checks that can withdraw funds from an object to itself or a destination. + * + * The receiver may be either the submitting account (sfAccount) or a different + * destination account (sfDestination). + * + * - Checks that the receiver account exists. + * - If the receiver requires a destination tag, check that one exists, even + * if withdrawing to self. + * - If withdrawing to self, succeed. + * - If not, checks if the receiver requires deposit authorization, and if + * the sender has it. + */ +[[nodiscard]] TER +canWithdraw(ReadView const& view, STTx const& tx); + +[[nodiscard]] TER +doWithdraw( + ApplyView& view, + STTx const& tx, + AccountID const& senderAcct, + AccountID const& dstAcct, + AccountID const& sourceAcct, + XRPAmount priorBalance, + STAmount const& amount, + beast::Journal j); + /// Any transactors that call addEmptyHolding() in doApply must call /// canAddHolding() in preflight with the same View and Asset [[nodiscard]] TER @@ -731,6 +933,22 @@ accountSend( beast::Journal j, WaiveTransferFee waiveFee = WaiveTransferFee::No); +using MultiplePaymentDestinations = std::vector>; +/** Like accountSend, except one account is sending multiple payments (with the + * same asset!) simultaneously + * + * Calls static accountSendMultiIOU if saAmount represents Issue. + * Calls static accountSendMultiMPT if saAmount represents MPTIssue. + */ +[[nodiscard]] TER +accountSendMulti( + ApplyView& view, + AccountID const& senderID, + Asset const& asset, + MultiplePaymentDestinations const& receivers, + beast::Journal j, + WaiveTransferFee waiveFee = WaiveTransferFee::No); + [[nodiscard]] TER issueIOU( ApplyView& view, @@ -802,7 +1020,8 @@ requireAuth( * purely defensive, as we currently do not allow such vaults to be created. * * If StrongAuth then return tecNO_AUTH if MPToken doesn't exist or - * lsfMPTRequireAuth is set and MPToken is not authorized. + * lsfMPTRequireAuth is set and MPToken is not authorized. Vault and LoanBroker + * pseudo-accounts are implicitly authorized. * * If WeakAuth then return tecNO_AUTH if lsfMPTRequireAuth is set and MPToken * doesn't exist or is not authorized (explicitly or via credentials, if @@ -875,6 +1094,26 @@ canTransfer( AccountID const& from, AccountID const& to); +[[nodiscard]] TER +canTransfer( + ReadView const& view, + Issue const& issue, + AccountID const& from, + AccountID const& to); + +[[nodiscard]] TER inline canTransfer( + ReadView const& view, + Asset const& asset, + AccountID const& from, + AccountID const& to) +{ + return std::visit( + [&](TIss const& issue) -> TER { + return canTransfer(view, issue, from, to); + }, + asset.value()); +} + /** Deleter function prototype. Returns the status of the entry deletion * (if should not be skipped) and if the entry should be skipped. The status * is always tesSUCCESS if the entry should be skipped. diff --git a/include/xrpl/protocol/Asset.h b/include/xrpl/protocol/Asset.h index d0efe814a9..7ad1e70256 100644 --- a/include/xrpl/protocol/Asset.h +++ b/include/xrpl/protocol/Asset.h @@ -81,7 +81,27 @@ public: bool native() const { - return holds() && get().native(); + return std::visit( + [&](TIss const& issue) { + if constexpr (std::is_same_v) + return issue.native(); + if constexpr (std::is_same_v) + return false; + }, + issue_); + } + + bool + integral() const + { + return std::visit( + [&](TIss const& issue) { + if constexpr (std::is_same_v) + return issue.native(); + if constexpr (std::is_same_v) + return true; + }, + issue_); } friend constexpr bool diff --git a/include/xrpl/protocol/Indexes.h b/include/xrpl/protocol/Indexes.h index b48ed64d71..69418fbd25 100644 --- a/include/xrpl/protocol/Indexes.h +++ b/include/xrpl/protocol/Indexes.h @@ -327,6 +327,24 @@ vault(uint256 const& vaultKey) return {ltVAULT, vaultKey}; } +Keylet +loanbroker(AccountID const& owner, std::uint32_t seq) noexcept; + +inline Keylet +loanbroker(uint256 const& key) +{ + return {ltLOAN_BROKER, key}; +} + +Keylet +loan(uint256 const& loanBrokerID, std::uint32_t loanSeq) noexcept; + +inline Keylet +loan(uint256 const& key) +{ + return {ltLOAN, key}; +} + Keylet permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept; diff --git a/include/xrpl/protocol/LedgerFormats.h b/include/xrpl/protocol/LedgerFormats.h index 9e76f3bde7..64ae604f64 100644 --- a/include/xrpl/protocol/LedgerFormats.h +++ b/include/xrpl/protocol/LedgerFormats.h @@ -186,6 +186,11 @@ enum LedgerSpecificFlags { // ltVAULT lsfVaultPrivate = 0x00010000, + + // ltLOAN + lsfLoanDefault = 0x00010000, + lsfLoanImpaired = 0x00020000, + lsfLoanOverpayment = 0x00040000, // True, loan allows overpayments }; //------------------------------------------------------------------------------ diff --git a/include/xrpl/protocol/Protocol.h b/include/xrpl/protocol/Protocol.h index 20b73e90c9..ded16cad6d 100644 --- a/include/xrpl/protocol/Protocol.h +++ b/include/xrpl/protocol/Protocol.h @@ -3,6 +3,7 @@ #include #include +#include #include @@ -65,6 +66,140 @@ std::size_t constexpr maxDeletableTokenOfferEntries = 500; */ std::uint16_t constexpr maxTransferFee = 50000; +/** There are 10,000 basis points (bips) in 100%. + * + * Basis points represent 0.01%. + * + * Given a value X, to find the amount for B bps, + * use X * B / bipsPerUnity + * + * Example: If a loan broker has 999 XRP of debt, and must maintain 1,000 bps of + * that debt as cover (10%), then the minimum cover amount is 999,000,000 drops + * * 1000 / bipsPerUnity = 99,900,00 drops or 99.9 XRP. + * + * Given a percentage P, to find the number of bps that percentage represents, + * use P * bipsPerUnity. + * + * Example: 50% is 0.50 * bipsPerUnity = 5,000 bps. + */ +Bips32 constexpr bipsPerUnity(100 * 100); +static_assert(bipsPerUnity == Bips32{10'000}); +TenthBips32 constexpr tenthBipsPerUnity(bipsPerUnity.value() * 10); +static_assert(tenthBipsPerUnity == TenthBips32(100'000)); + +constexpr Bips32 +percentageToBips(std::uint32_t percentage) +{ + return Bips32(percentage * bipsPerUnity.value() / 100); +} +constexpr TenthBips32 +percentageToTenthBips(std::uint32_t percentage) +{ + return TenthBips32(percentage * tenthBipsPerUnity.value() / 100); +} +template +constexpr T +bipsOfValue(T value, Bips bips) +{ + return value * bips.value() / bipsPerUnity.value(); +} +template +constexpr T +tenthBipsOfValue(T value, TenthBips bips) +{ + return value * bips.value() / tenthBipsPerUnity.value(); +} + +namespace Lending { +/** The maximum management fee rate allowed by a loan broker in 1/10 bips. + + Valid values are between 0 and 10% inclusive. +*/ +TenthBips16 constexpr maxManagementFeeRate( + unsafe_cast(percentageToTenthBips(10).value())); +static_assert(maxManagementFeeRate == TenthBips16(std::uint16_t(10'000u))); + +/** The maximum coverage rate required of a loan broker in 1/10 bips. + + Valid values are between 0 and 100% inclusive. +*/ +TenthBips32 constexpr maxCoverRate = percentageToTenthBips(100); +static_assert(maxCoverRate == TenthBips32(100'000u)); + +/** The maximum overpayment fee on a loan in 1/10 bips. +* + Valid values are between 0 and 100% inclusive. +*/ +TenthBips32 constexpr maxOverpaymentFee = percentageToTenthBips(100); +static_assert(maxOverpaymentFee == TenthBips32(100'000u)); + +/** Annualized interest rate of the Loan in 1/10 bips. + * + * Valid values are between 0 and 100% inclusive. + */ +TenthBips32 constexpr maxInterestRate = percentageToTenthBips(100); +static_assert(maxInterestRate == TenthBips32(100'000u)); + +/** The maximum premium added to the interest rate for late payments on a loan + * in 1/10 bips. + * + * Valid values are between 0 and 100% inclusive. + */ +TenthBips32 constexpr maxLateInterestRate = percentageToTenthBips(100); +static_assert(maxLateInterestRate == TenthBips32(100'000u)); + +/** The maximum close interest rate charged for repaying a loan early in 1/10 + * bips. + * + * Valid values are between 0 and 100% inclusive. + */ +TenthBips32 constexpr maxCloseInterestRate = percentageToTenthBips(100); +static_assert(maxCloseInterestRate == TenthBips32(100'000u)); + +/** The maximum overpayment interest rate charged on loan overpayments in 1/10 + * bips. + * + * Valid values are between 0 and 100% inclusive. + */ +TenthBips32 constexpr maxOverpaymentInterestRate = percentageToTenthBips(100); +static_assert(maxOverpaymentInterestRate == TenthBips32(100'000u)); + +/** LoanPay transaction cost will be one base fee per X combined payments + * + * The number of payments is estimated based on the Amount paid and the Loan's + * Fixed Payment size. Overpayments (indicated with the tfLoanOverpayment flag) + * count as one more payment. + * + * This number was chosen arbitrarily, but should not be changed once released + * without an amendment + */ +static constexpr int loanPaymentsPerFeeIncrement = 5; + +/** Maximum number of combined payments that a LoanPay transaction will process + * + * This limit is enforced during the loan payment process, and thus is not + * estimated. If the limit is hit, no further payments or overpayments will be + * processed, no matter how much of the transation Amount is left, but the + * transaction will succeed with the payments that have been processed up to + * that point. + * + * This limit is independent of loanPaymentsPerFeeIncrement, so a transaction + * could potentially be charged for many more payments than actually get + * processed. Users should take care not to submit a transaction paying more + * than loanMaximumPaymentsPerTransaction * Loan.PeriodicPayment. Because + * overpayments are charged as a payment, if submitting + * loanMaximumPaymentsPerTransaction * Loan.PeriodicPayment, users should not + * set the tfLoanOverpayment flag. + * + * Even though they're independent, loanMaximumPaymentsPerTransaction should be + * a multiple of loanPaymentsPerFeeIncrement. + * + * This number was chosen arbitrarily, but should not be changed once released + * without an amendment + */ +static constexpr int loanMaximumPaymentsPerTransaction = 100; +} // namespace Lending + /** The maximum length of a URI inside an NFT */ std::size_t constexpr maxTokenURILength = 256; diff --git a/include/xrpl/protocol/SField.h b/include/xrpl/protocol/SField.h index ea6b51dbab..82619b1ced 100644 --- a/include/xrpl/protocol/SField.h +++ b/include/xrpl/protocol/SField.h @@ -120,8 +120,8 @@ field_code(int id, int index) SFields are created at compile time. Each SField, once constructed, lives until program termination, and there - is only one instance per fieldType/fieldValue pair which serves the entire - application. + is only one instance per fieldType/fieldValue pair which serves the + entire application. */ class SField { diff --git a/include/xrpl/protocol/STAmount.h b/include/xrpl/protocol/STAmount.h index 83493efcdd..3ea45cc05b 100644 --- a/include/xrpl/protocol/STAmount.h +++ b/include/xrpl/protocol/STAmount.h @@ -47,16 +47,18 @@ public: static int const cMaxOffset = 80; // Maximum native value supported by the code - static std::uint64_t const cMinValue = 1000000000000000ull; - static std::uint64_t const cMaxValue = 9999999999999999ull; - static std::uint64_t const cMaxNative = 9000000000000000000ull; + constexpr static std::uint64_t cMinValue = 1'000'000'000'000'000ull; + static_assert(isPowerOfTen(cMinValue)); + constexpr static std::uint64_t cMaxValue = cMinValue * 10 - 1; + static_assert(cMaxValue == 9'999'999'999'999'999ull); + constexpr static std::uint64_t cMaxNative = 9'000'000'000'000'000'000ull; // Max native value on network. - static std::uint64_t const cMaxNativeN = 100000000000000000ull; - static std::uint64_t const cIssuedCurrency = 0x8000000000000000ull; - static std::uint64_t const cPositive = 0x4000000000000000ull; - static std::uint64_t const cMPToken = 0x2000000000000000ull; - static std::uint64_t const cValueMask = ~(cPositive | cMPToken); + constexpr static std::uint64_t cMaxNativeN = 100'000'000'000'000'000ull; + constexpr static std::uint64_t cIssuedCurrency = 0x8'000'000'000'000'000ull; + constexpr static std::uint64_t cPositive = 0x4'000'000'000'000'000ull; + constexpr static std::uint64_t cMPToken = 0x2'000'000'000'000'000ull; + constexpr static std::uint64_t cValueMask = ~(cPositive | cMPToken); static std::uint64_t const uRateOne; @@ -155,6 +157,9 @@ public: int exponent() const noexcept; + bool + integral() const noexcept; + bool native() const noexcept; @@ -435,6 +440,12 @@ STAmount::exponent() const noexcept return mOffset; } +inline bool +STAmount::integral() const noexcept +{ + return mAsset.integral(); +} + inline bool STAmount::native() const noexcept { @@ -553,7 +564,7 @@ STAmount::clear() { // The -100 is used to allow 0 to sort less than a small positive values // which have a negative exponent. - mOffset = native() ? 0 : -100; + mOffset = integral() ? 0 : -100; mValue = 0; mIsNegative = false; } @@ -676,6 +687,53 @@ divRoundStrict( std::uint64_t getRate(STAmount const& offerOut, STAmount const& offerIn); +/** Round an arbitrary precision Amount to the precision of an STAmount that has + * a given exponent. + * + * This is used to ensure that calculations involving IOU amounts do not collect + * dust beyond the precision of the reference value. + * + * @param value The value to be rounded + * @param scale An exponent value to establish the precision limit of + * `value`. Should be larger than `value.exponent()`. + * @param rounding Optional Number rounding mode + * + */ +STAmount +roundToScale( + STAmount const& value, + std::int32_t scale, + Number::rounding_mode rounding = Number::getround()); + +/** Round an arbitrary precision Number to the precision of a given Asset. + * + * This is used to ensure that calculations do not collect dust beyond the + * precision of the reference value for IOUs, or fractional amounts for the + * integral types XRP and MPT. + * + * @param asset The relevant asset + * @param value The value to be rounded + * @param scale Only relevant to IOU assets. An exponent value to establish the + * precision limit of `value`. Should be larger than `value.exponent()`. + * @param rounding Optional Number rounding mode + */ +template +Number +roundToAsset( + A const& asset, + Number const& value, + std::int32_t scale, + Number::rounding_mode rounding = Number::getround()) +{ + NumberRoundModeGuard mg(rounding); + STAmount const ret{asset, value}; + if (ret.integral()) + return ret; + // Note that the ctor will round integral types (XRP, MPT) via canonicalize, + // so no extra work is needed for those. + return roundToScale(ret, scale); +} + //------------------------------------------------------------------------------ inline bool diff --git a/include/xrpl/protocol/STObject.h b/include/xrpl/protocol/STObject.h index 9b325f06fe..1a553e0fbf 100644 --- a/include/xrpl/protocol/STObject.h +++ b/include/xrpl/protocol/STObject.h @@ -482,6 +482,8 @@ public: value_type operator*() const; + /// Do not use operator->() unless the field is required, or you've checked + /// that it's set. T const* operator->() const; @@ -505,7 +507,26 @@ protected: // Constraint += and -= ValueProxy operators // to value types that support arithmetic operations template -concept IsArithmetic = std::is_arithmetic_v || std::is_same_v; +concept IsArithmeticNumber = std::is_arithmetic_v || + std::is_same_v || std::is_same_v; +template < + typename U, + typename Value = typename U::value_type, + typename Unit = typename U::unit_type> +concept IsArithmeticValueUnit = + std::is_same_v> && + IsArithmeticNumber && std::is_class_v; +template +concept IsArithmeticST = !IsArithmeticValueUnit && IsArithmeticNumber; +template +concept IsArithmetic = + IsArithmeticNumber || IsArithmeticST || IsArithmeticValueUnit; + +template +concept Addable = requires(T t, U u) { t = t + u; }; +template +concept IsArithmeticCompatible = + IsArithmetic && Addable; template class STObject::ValueProxy : public Proxy @@ -525,10 +546,12 @@ public: // Convenience operators for value types supporting // arithmetic operations template + requires IsArithmeticCompatible ValueProxy& operator+=(U const& u); template + requires IsArithmeticCompatible ValueProxy& operator-=(U const& u); @@ -718,6 +741,8 @@ STObject::Proxy::operator*() const -> value_type return this->value(); } +/// Do not use operator->() unless the field is required, or you've checked that +/// it's set. template T const* STObject::Proxy::operator->() const @@ -764,6 +789,7 @@ STObject::ValueProxy::operator=(U&& u) template template + requires IsArithmeticCompatible STObject::ValueProxy& STObject::ValueProxy::operator+=(U const& u) { @@ -773,6 +799,7 @@ STObject::ValueProxy::operator+=(U const& u) template template + requires IsArithmeticCompatible STObject::ValueProxy& STObject::ValueProxy::operator-=(U const& u) { diff --git a/include/xrpl/protocol/TxFlags.h b/include/xrpl/protocol/TxFlags.h index b067e8487b..d4faed192c 100644 --- a/include/xrpl/protocol/TxFlags.h +++ b/include/xrpl/protocol/TxFlags.h @@ -266,6 +266,32 @@ constexpr std::uint32_t tfIndependent = 0x00080000; constexpr std::uint32_t const tfBatchMask = ~(tfUniversal | tfAllOrNothing | tfOnlyOne | tfUntilFailure | tfIndependent) | tfInnerBatchTxn; +// LoanSet and LoanPay flags: +// LoanSet: True, indicates the loan supports overpayments +// LoanPay: True, indicates any excess in this payment can be used +// as an overpayment. False, no overpayments will be taken. +constexpr std::uint32_t const tfLoanOverpayment = 0x00010000; +// LoanPay exclusive flags: +// tfLoanFullPayment: True, indicates that the payment is an early +// full payment. It must pay the entire loan including close +// interest and fees, or it will fail. False: Not a full payment. +constexpr std::uint32_t const tfLoanFullPayment = 0x00020000; +// tfLoanLatePayment: True, indicates that the payment is late, +// and includes late iterest and fees. If the loan is not late, +// it will fail. False: not a late payment. If the current payment +// is overdue, the transaction will fail. +constexpr std::uint32_t const tfLoanLatePayment = 0x00040000; +constexpr std::uint32_t const tfLoanSetMask = ~(tfUniversal | + tfLoanOverpayment); +constexpr std::uint32_t const tfLoanPayMask = ~(tfUniversal | + tfLoanOverpayment | tfLoanFullPayment | tfLoanLatePayment); + +// LoanManage flags: +constexpr std::uint32_t const tfLoanDefault = 0x00010000; +constexpr std::uint32_t const tfLoanImpair = 0x00020000; +constexpr std::uint32_t const tfLoanUnimpair = 0x00040000; +constexpr std::uint32_t const tfLoanManageMask = ~(tfUniversal | tfLoanDefault | tfLoanImpair | tfLoanUnimpair); + // clang-format on } // namespace ripple diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 5f1eca7afe..5c8d2aa198 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -11,9 +11,12 @@ #error "undefined macro: XRPL_RETIRE_FIX" #endif +// clang-format off + // Add new amendments to the top of this list. // Keep it sorted in reverse chronological order. +XRPL_FEATURE(LendingProtocol, Supported::no, VoteBehavior::DefaultNo) XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo) XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (IncludeKeyletFields, Supported::yes, VoteBehavior::DefaultNo) @@ -137,3 +140,5 @@ XRPL_RETIRE_FEATURE(SortedDirectories) XRPL_RETIRE_FEATURE(TicketBatch) XRPL_RETIRE_FEATURE(TickSize) XRPL_RETIRE_FEATURE(TrustSetAuth) + +// clang-format on diff --git a/include/xrpl/protocol/detail/ledger_entries.macro b/include/xrpl/protocol/detail/ledger_entries.macro index 53110f09f5..1034c35895 100644 --- a/include/xrpl/protocol/detail/ledger_entries.macro +++ b/include/xrpl/protocol/detail/ledger_entries.macro @@ -149,6 +149,7 @@ LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({ {sfFirstNFTokenSequence, soeOPTIONAL}, {sfAMMID, soeOPTIONAL}, // pseudo-account designator {sfVaultID, soeOPTIONAL}, // pseudo-account designator + {sfLoanBrokerID, soeOPTIONAL}, // pseudo-account designator })) /** A ledger object which contains a list of object identifiers. @@ -479,10 +480,10 @@ LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, ({ {sfAccount, soeREQUIRED}, {sfData, soeOPTIONAL}, {sfAsset, soeREQUIRED}, - {sfAssetsTotal, soeREQUIRED}, - {sfAssetsAvailable, soeREQUIRED}, + {sfAssetsTotal, soeDEFAULT}, + {sfAssetsAvailable, soeDEFAULT}, {sfAssetsMaximum, soeDEFAULT}, - {sfLossUnrealized, soeREQUIRED}, + {sfLossUnrealized, soeDEFAULT}, {sfShareMPTID, soeREQUIRED}, {sfWithdrawalPolicy, soeREQUIRED}, {sfScale, soeDEFAULT}, @@ -490,5 +491,117 @@ LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, ({ // no PermissionedDomainID ever (use MPTIssuance.sfDomainID) })) +/** Reserve 0x0084-0x0087 for future Vault-related objects. */ + +/** A ledger object representing a loan broker + + \sa keylet::loanbroker + */ +LEDGER_ENTRY(ltLOAN_BROKER, 0x0088, LoanBroker, loan_broker, ({ + {sfPreviousTxnID, soeREQUIRED}, + {sfPreviousTxnLgrSeq, soeREQUIRED}, + {sfSequence, soeREQUIRED}, + {sfOwnerNode, soeREQUIRED}, + {sfVaultNode, soeREQUIRED}, + {sfVaultID, soeREQUIRED}, + {sfAccount, soeREQUIRED}, + {sfOwner, soeREQUIRED}, + {sfLoanSequence, soeREQUIRED}, + {sfData, soeDEFAULT}, + {sfManagementFeeRate, soeDEFAULT}, + {sfOwnerCount, soeDEFAULT}, + {sfDebtTotal, soeDEFAULT}, + {sfDebtMaximum, soeDEFAULT}, + {sfCoverAvailable, soeDEFAULT}, + {sfCoverRateMinimum, soeDEFAULT}, + {sfCoverRateLiquidation, soeDEFAULT}, +})) + +/** A ledger object representing a loan between a Borrower and a Loan Broker + + \sa keylet::loan + */ +LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({ + {sfPreviousTxnID, soeREQUIRED}, + {sfPreviousTxnLgrSeq, soeREQUIRED}, + {sfOwnerNode, soeREQUIRED}, + {sfLoanBrokerNode, soeREQUIRED}, + {sfLoanBrokerID, soeREQUIRED}, + {sfLoanSequence, soeREQUIRED}, + {sfBorrower, soeREQUIRED}, + {sfLoanOriginationFee, soeDEFAULT}, + {sfLoanServiceFee, soeDEFAULT}, + {sfLatePaymentFee, soeDEFAULT}, + {sfClosePaymentFee, soeDEFAULT}, + {sfOverpaymentFee, soeDEFAULT}, + {sfInterestRate, soeDEFAULT}, + {sfLateInterestRate, soeDEFAULT}, + {sfCloseInterestRate, soeDEFAULT}, + {sfOverpaymentInterestRate, soeDEFAULT}, + {sfStartDate, soeREQUIRED}, + {sfPaymentInterval, soeREQUIRED}, + {sfGracePeriod, soeDEFAULT}, + {sfPreviousPaymentDate, soeDEFAULT}, + {sfNextPaymentDueDate, soeDEFAULT}, + // The loan object tracks these values: + // + // - PaymentRemaining: The number of payments left in the loan. When it + // reaches 0, the loan is paid off, and all other relevant values + // must also be 0. + // + // - PeriodicPayment: The fixed, unrounded amount to be paid each + // interval. Stored with as much precision as possible. + // Payment transactions must round this value *UP*. + // + // - TotalValueOutstanding: The rounded total amount owed by the + // borrower to the lender / vault. + // + // - PrincipalOutstanding: The rounded portion of the + // TotalValueOutstanding that is from the principal borrowed. + // + // - ManagementFeeOutstanding: The rounded portion of the + // TotalValueOutstanding that represents management fees + // specifically owed to the broker based on the initial + // loan parameters. + // + // There are additional values that can be computed from these: + // + // - InterestOutstanding = TotalValueOutstanding - PrincipalOutstanding + // The total amount of interest still pending on the loan, + // independent of management fees. + // + // - InterestOwedToVault = InterestOutstanding - ManagementFeeOutstanding + // The amount of the total interest that is owed to the vault, and + // will be sent to it as part of a payment. + // + // - TrueTotalLoanValue = PaymentRemaining * PeriodicPayment + // The unrounded true total value of the loan. + // + // - TrueTotalPrincialOutstanding can be computed using the algorithm + // in the ripple::detail::loanPrincipalFromPeriodicPayment function. + // + // - TrueTotalInterestOutstanding = TrueTotalLoanValue - + // TrueTotalPrincipalOutstanding + // The unrounded true total interest remaining. + // + // - TrueTotalManagementFeeOutstanding = TrueTotalInterestOutstanding * + // LoanBroker.ManagementFeeRate + // The unrounded true total fee still owed to the broker. + // + // Note the the "True" values may differ significantly from the tracked + // rounded values. + {sfPaymentRemaining, soeDEFAULT}, + {sfPeriodicPayment, soeREQUIRED}, + {sfPrincipalOutstanding, soeDEFAULT}, + {sfTotalValueOutstanding, soeDEFAULT}, + {sfManagementFeeOutstanding, soeDEFAULT}, + // Based on the computed total value at creation, used for + // rounding calculated values so they are all on a + // consistent scale - that is, they all have the same + // number of digits after the decimal point (excluding + // trailing zeros). + {sfLoanScale, soeDEFAULT}, +})) + #undef EXPAND #undef LEDGER_ENTRY_DUPLICATE diff --git a/include/xrpl/protocol/detail/sfields.macro b/include/xrpl/protocol/detail/sfields.macro index 6e3c20267c..d5c5d9447f 100644 --- a/include/xrpl/protocol/detail/sfields.macro +++ b/include/xrpl/protocol/detail/sfields.macro @@ -5,6 +5,8 @@ #error "undefined macro: TYPED_SFIELD" #endif +// clang-format off + // untyped UNTYPED_SFIELD(sfLedgerEntry, LEDGERENTRY, 257) UNTYPED_SFIELD(sfTransaction, TRANSACTION, 257) @@ -40,6 +42,7 @@ TYPED_SFIELD(sfHookEmitCount, UINT16, 18) TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19) TYPED_SFIELD(sfHookApiVersion, UINT16, 20) TYPED_SFIELD(sfLedgerFixType, UINT16, 21) +TYPED_SFIELD(sfManagementFeeRate, UINT16, 22) // 1/10 basis points (bips) // 32-bit integers (common) TYPED_SFIELD(sfNetworkID, UINT32, 1) @@ -96,6 +99,21 @@ TYPED_SFIELD(sfFirstNFTokenSequence, UINT32, 50) TYPED_SFIELD(sfOracleDocumentID, UINT32, 51) TYPED_SFIELD(sfPermissionValue, UINT32, 52) TYPED_SFIELD(sfMutableFlags, UINT32, 53) +TYPED_SFIELD(sfStartDate, UINT32, 54) +TYPED_SFIELD(sfPaymentInterval, UINT32, 55) +TYPED_SFIELD(sfGracePeriod, UINT32, 56) +TYPED_SFIELD(sfPreviousPaymentDate, UINT32, 57) +TYPED_SFIELD(sfNextPaymentDueDate, UINT32, 58) +TYPED_SFIELD(sfPaymentRemaining, UINT32, 59) +TYPED_SFIELD(sfPaymentTotal, UINT32, 60) +TYPED_SFIELD(sfLoanSequence, UINT32, 61) +TYPED_SFIELD(sfCoverRateMinimum, UINT32, 62) // 1/10 basis points (bips) +TYPED_SFIELD(sfCoverRateLiquidation, UINT32, 63) // 1/10 basis points (bips) +TYPED_SFIELD(sfOverpaymentFee, UINT32, 64) // 1/10 basis points (bips) +TYPED_SFIELD(sfInterestRate, UINT32, 65) // 1/10 basis points (bips) +TYPED_SFIELD(sfLateInterestRate, UINT32, 66) // 1/10 basis points (bips) +TYPED_SFIELD(sfCloseInterestRate, UINT32, 67) // 1/10 basis points (bips) +TYPED_SFIELD(sfOverpaymentInterestRate, UINT32, 68) // 1/10 basis points (bips) // 64-bit integers (common) TYPED_SFIELD(sfIndexNext, UINT64, 1) @@ -127,6 +145,8 @@ TYPED_SFIELD(sfMPTAmount, UINT64, 26, SField::sMD_BaseTen|SFie TYPED_SFIELD(sfIssuerNode, UINT64, 27) TYPED_SFIELD(sfSubjectNode, UINT64, 28) TYPED_SFIELD(sfLockedAmount, UINT64, 29, SField::sMD_BaseTen|SField::sMD_Default) +TYPED_SFIELD(sfVaultNode, UINT64, 30) +TYPED_SFIELD(sfLoanBrokerNode, UINT64, 31) // 128-bit TYPED_SFIELD(sfEmailHash, UINT128, 1) @@ -181,6 +201,9 @@ TYPED_SFIELD(sfDomainID, UINT256, 34) TYPED_SFIELD(sfVaultID, UINT256, 35, SField::sMD_PseudoAccount | SField::sMD_Default) TYPED_SFIELD(sfParentBatchID, UINT256, 36) +TYPED_SFIELD(sfLoanBrokerID, UINT256, 37, + SField::sMD_PseudoAccount | SField::sMD_Default) +TYPED_SFIELD(sfLoanID, UINT256, 38) // number (common) TYPED_SFIELD(sfNumber, NUMBER, 1) @@ -188,12 +211,21 @@ TYPED_SFIELD(sfAssetsAvailable, NUMBER, 2) TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3) TYPED_SFIELD(sfAssetsTotal, NUMBER, 4) TYPED_SFIELD(sfLossUnrealized, NUMBER, 5) +TYPED_SFIELD(sfDebtTotal, NUMBER, 6) +TYPED_SFIELD(sfDebtMaximum, NUMBER, 7) +TYPED_SFIELD(sfCoverAvailable, NUMBER, 8) +TYPED_SFIELD(sfLoanOriginationFee, NUMBER, 9) +TYPED_SFIELD(sfLoanServiceFee, NUMBER, 10) +TYPED_SFIELD(sfLatePaymentFee, NUMBER, 11) +TYPED_SFIELD(sfClosePaymentFee, NUMBER, 12) +TYPED_SFIELD(sfPrincipalOutstanding, NUMBER, 13) +TYPED_SFIELD(sfPrincipalRequested, NUMBER, 14) +TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15) +TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16) +TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17) // int32 -// NOTE: Do not use `sfDummyInt32`. It's so far the only use of INT32 -// in this file and has been defined here for test only. -// TODO: Replace `sfDummyInt32` with actually useful field. -TYPED_SFIELD(sfDummyInt32, INT32, 1) // for tests only +TYPED_SFIELD(sfLoanScale, INT32, 1) // currency amount (common) TYPED_SFIELD(sfAmount, AMOUNT, 1) @@ -289,6 +321,8 @@ TYPED_SFIELD(sfAttestationRewardAccount, ACCOUNT, 21) TYPED_SFIELD(sfLockingChainDoor, ACCOUNT, 22) TYPED_SFIELD(sfIssuingChainDoor, ACCOUNT, 23) TYPED_SFIELD(sfSubject, ACCOUNT, 24) +TYPED_SFIELD(sfBorrower, ACCOUNT, 25) +TYPED_SFIELD(sfCounterparty, ACCOUNT, 26) // vector of 256-bit TYPED_SFIELD(sfIndexes, VECTOR256, 1, SField::sMD_Never) @@ -352,6 +386,7 @@ UNTYPED_SFIELD(sfCredential, OBJECT, 33) UNTYPED_SFIELD(sfRawTransaction, OBJECT, 34) UNTYPED_SFIELD(sfBatchSigner, OBJECT, 35) UNTYPED_SFIELD(sfBook, OBJECT, 36) +UNTYPED_SFIELD(sfCounterpartySignature, OBJECT, 37, SField::sMD_Default, SField::notSigning) // array of objects (common) // ARRAY/1 is reserved for end of array @@ -386,3 +421,5 @@ UNTYPED_SFIELD(sfAcceptedCredentials, ARRAY, 28) UNTYPED_SFIELD(sfPermissions, ARRAY, 29) UNTYPED_SFIELD(sfRawTransactions, ARRAY, 30) UNTYPED_SFIELD(sfBatchSigners, ARRAY, 31, SField::sMD_Default, SField::notSigning) + +// clang-format on diff --git a/include/xrpl/protocol/detail/transactions.macro b/include/xrpl/protocol/detail/transactions.macro index e551c89e55..6d2d833440 100644 --- a/include/xrpl/protocol/detail/transactions.macro +++ b/include/xrpl/protocol/detail/transactions.macro @@ -925,6 +925,139 @@ TRANSACTION(ttBATCH, 71, Batch, {sfBatchSigners, soeOPTIONAL}, })) +/** Reserve 72-73 for future Vault-related transactions */ + +/** This transaction creates and updates a Loan Broker */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_BROKER_SET, 74, LoanBrokerSet, + Delegation::delegatable, + featureLendingProtocol, + createPseudoAcct | mayAuthorizeMPT, ({ + {sfVaultID, soeREQUIRED}, + {sfLoanBrokerID, soeOPTIONAL}, + {sfData, soeOPTIONAL}, + {sfManagementFeeRate, soeOPTIONAL}, + {sfDebtMaximum, soeOPTIONAL}, + {sfCoverRateMinimum, soeOPTIONAL}, + {sfCoverRateLiquidation, soeOPTIONAL}, +})) + +/** This transaction deletes a Loan Broker */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_BROKER_DELETE, 75, LoanBrokerDelete, + Delegation::delegatable, + featureLendingProtocol, + mustDeleteAcct | mayAuthorizeMPT, ({ + {sfLoanBrokerID, soeREQUIRED}, +})) + +/** This transaction deposits First Loss Capital into a Loan Broker */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_BROKER_COVER_DEPOSIT, 76, LoanBrokerCoverDeposit, + Delegation::delegatable, + featureLendingProtocol, + noPriv, ({ + {sfLoanBrokerID, soeREQUIRED}, + {sfAmount, soeREQUIRED, soeMPTSupported}, +})) + +/** This transaction withdraws First Loss Capital from a Loan Broker */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_BROKER_COVER_WITHDRAW, 77, LoanBrokerCoverWithdraw, + Delegation::delegatable, + featureLendingProtocol, + mayAuthorizeMPT, ({ + {sfLoanBrokerID, soeREQUIRED}, + {sfAmount, soeREQUIRED, soeMPTSupported}, + {sfDestination, soeOPTIONAL}, + {sfDestinationTag, soeOPTIONAL}, +})) + +/** This transaction claws back First Loss Capital from a Loan Broker to + the issuer of the capital */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_BROKER_COVER_CLAWBACK, 78, LoanBrokerCoverClawback, + Delegation::delegatable, + featureLendingProtocol, + noPriv, ({ + {sfLoanBrokerID, soeOPTIONAL}, + {sfAmount, soeOPTIONAL, soeMPTSupported}, +})) + +/** This transaction creates a Loan */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_SET, 80, LoanSet, + Delegation::delegatable, + featureLendingProtocol, + mayAuthorizeMPT | mustModifyVault, ({ + {sfLoanBrokerID, soeREQUIRED}, + {sfData, soeOPTIONAL}, + {sfCounterparty, soeOPTIONAL}, + {sfCounterpartySignature, soeOPTIONAL}, + {sfLoanOriginationFee, soeOPTIONAL}, + {sfLoanServiceFee, soeOPTIONAL}, + {sfLatePaymentFee, soeOPTIONAL}, + {sfClosePaymentFee, soeOPTIONAL}, + {sfOverpaymentFee, soeOPTIONAL}, + {sfInterestRate, soeOPTIONAL}, + {sfLateInterestRate, soeOPTIONAL}, + {sfCloseInterestRate, soeOPTIONAL}, + {sfOverpaymentInterestRate, soeOPTIONAL}, + {sfPrincipalRequested, soeREQUIRED}, + {sfPaymentTotal, soeOPTIONAL}, + {sfPaymentInterval, soeOPTIONAL}, + {sfGracePeriod, soeOPTIONAL}, +})) + +/** This transaction deletes an existing Loan */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_DELETE, 81, LoanDelete, + Delegation::delegatable, + featureLendingProtocol, + noPriv, ({ + {sfLoanID, soeREQUIRED}, +})) + +/** This transaction is used to change the delinquency status of an existing Loan */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_MANAGE, 82, LoanManage, + Delegation::delegatable, + featureLendingProtocol, + // All of the LoanManage options will modify the vault, but the + // transaction can succeed without options, essentially making it + // a noop. + mayModifyVault, ({ + {sfLoanID, soeREQUIRED}, +})) + +/** The Borrower uses this transaction to make a Payment on the Loan. */ +#if TRANSACTION_INCLUDE +# include +#endif +TRANSACTION(ttLOAN_PAY, 84, LoanPay, + Delegation::delegatable, + featureLendingProtocol, + mayAuthorizeMPT | mustModifyVault, ({ + {sfLoanID, soeREQUIRED}, + {sfAmount, soeREQUIRED, soeMPTSupported}, +})) + /** This system-generated transaction type is used to update the status of the various amendments. For details, see: https://xrpl.org/amendments.html diff --git a/include/xrpl/protocol/jss.h b/include/xrpl/protocol/jss.h index 890e979ad4..b9a8945d21 100644 --- a/include/xrpl/protocol/jss.h +++ b/include/xrpl/protocol/jss.h @@ -40,6 +40,8 @@ JSS(BaseAsset); // in: Oracle JSS(BidMax); // in: AMM Bid JSS(BidMin); // in: AMM Bid JSS(ClearFlag); // field. +JSS(Counterparty); // field. +JSS(CounterpartySignature);// field. JSS(DeliverMax); // out: alias to Amount JSS(DeliverMin); // in: TransactionSign JSS(Destination); // in: TransactionSign; field. @@ -373,6 +375,8 @@ JSS(load_factor_local); // out: NetworkOPs JSS(load_factor_net); // out: NetworkOPs JSS(load_factor_server); // out: NetworkOPs JSS(load_fee); // out: LoadFeeTrackImp, NetworkOPs +JSS(loan_broker_id); // in: LedgerEntry +JSS(loan_seq); // in: LedgerEntry JSS(local); // out: resource/Logic.h JSS(local_txs); // out: GetCounts JSS(local_static_keys); // out: ValidatorList @@ -485,6 +489,7 @@ JSS(propose_seq); // out: LedgerPropose JSS(proposers); // out: NetworkOPs, LedgerConsensus JSS(protocol); // out: NetworkOPs, PeerImp JSS(proxied); // out: RPC ping +JSS(pseudo_account); // out: AccountInfo JSS(pubkey_node); // out: NetworkOPs JSS(pubkey_publisher); // out: ValidatorList JSS(pubkey_validator); // out: NetworkOPs, ValidatorList diff --git a/src/libxrpl/basics/Number.cpp b/src/libxrpl/basics/Number.cpp index 89f7937e06..797ca83b67 100644 --- a/src/libxrpl/basics/Number.cpp +++ b/src/libxrpl/basics/Number.cpp @@ -74,6 +74,18 @@ public: // tie, round towards even. int round() noexcept; + + // Modify the result to the correctly rounded value + void + doRoundUp(rep& mantissa, int& exponent, std::string location); + + // Modify the result to the correctly rounded value + void + doRoundDown(rep& mantissa, int& exponent); + + // Modify the result to the correctly rounded value + void + doRound(rep& drops); }; inline void @@ -151,6 +163,61 @@ Number::Guard::round() noexcept return 0; } +void +Number::Guard::doRoundUp(rep& mantissa, int& exponent, std::string location) +{ + auto r = round(); + if (r == 1 || (r == 0 && (mantissa & 1) == 1)) + { + ++mantissa; + if (mantissa > maxMantissa) + { + mantissa /= 10; + ++exponent; + } + } + if (exponent < minExponent) + { + mantissa = 0; + exponent = Number{}.exponent_; + } + if (exponent > maxExponent) + throw std::overflow_error(location); +} + +void +Number::Guard::doRoundDown(rep& mantissa, int& exponent) +{ + auto r = round(); + if (r == 1 || (r == 0 && (mantissa & 1) == 1)) + { + --mantissa; + if (mantissa < minMantissa) + { + mantissa *= 10; + --exponent; + } + } + if (exponent < minExponent) + { + mantissa = 0; + exponent = Number{}.exponent_; + } +} + +// Modify the result to the correctly rounded value +void +Number::Guard::doRound(rep& drops) +{ + auto r = round(); + if (r == 1 || (r == 0 && (drops & 1) == 1)) + { + ++drops; + } + if (is_negative()) + drops = -drops; +} + // Number constexpr Number one{1000000000000000, -15, Number::unchecked{}}; @@ -190,18 +257,7 @@ Number::normalize() return; } - auto r = g.round(); - if (r == 1 || (r == 0 && (mantissa_ & 1) == 1)) - { - ++mantissa_; - if (mantissa_ > maxMantissa) - { - mantissa_ /= 10; - ++exponent_; - } - } - if (exponent_ > maxExponent) - throw std::overflow_error("Number::normalize 2"); + g.doRoundUp(mantissa_, exponent_, "Number::normalize 2"); if (negative) mantissa_ = -mantissa_; @@ -273,18 +329,7 @@ Number::operator+=(Number const& y) xm /= 10; ++xe; } - auto r = g.round(); - if (r == 1 || (r == 0 && (xm & 1) == 1)) - { - ++xm; - if (xm > maxMantissa) - { - xm /= 10; - ++xe; - } - } - if (xe > maxExponent) - throw std::overflow_error("Number::addition overflow"); + g.doRoundUp(xm, xe, "Number::addition overflow"); } else { @@ -304,21 +349,7 @@ Number::operator+=(Number const& y) xm -= g.pop(); --xe; } - auto r = g.round(); - if (r == 1 || (r == 0 && (xm & 1) == 1)) - { - --xm; - if (xm < minMantissa) - { - xm *= 10; - --xe; - } - } - if (xe < minExponent) - { - xm = 0; - xe = Number{}.exponent_; - } + g.doRoundDown(xm, xe); } mantissa_ = xm * xn; exponent_ = xe; @@ -398,25 +429,10 @@ Number::operator*=(Number const& y) } xm = static_cast(zm); xe = ze; - auto r = g.round(); - if (r == 1 || (r == 0 && (xm & 1) == 1)) - { - ++xm; - if (xm > maxMantissa) - { - xm /= 10; - ++xe; - } - } - if (xe < minExponent) - { - xm = 0; - xe = Number{}.exponent_; - } - if (xe > maxExponent) - throw std::overflow_error( - "Number::multiplication overflow : exponent is " + - std::to_string(xe)); + g.doRoundUp( + xm, + xe, + "Number::multiplication overflow : exponent is " + std::to_string(xe)); mantissa_ = xm * zn; exponent_ = xe; XRPL_ASSERT( @@ -481,17 +497,29 @@ Number::operator rep() const throw std::overflow_error("Number::operator rep() overflow"); drops *= 10; } - auto r = g.round(); - if (r == 1 || (r == 0 && (drops & 1) == 1)) - { - ++drops; - } - if (g.is_negative()) - drops = -drops; + g.doRound(drops); } return drops; } +Number +Number::truncate() const noexcept +{ + if (exponent_ >= 0 || mantissa_ == 0) + return *this; + + Number ret = *this; + while (ret.exponent_ < 0 && ret.mantissa_ != 0) + { + ret.exponent_ += 1; + ret.mantissa_ /= rep(10); + } + // We are guaranteed that normalize() will never throw an exception + // because exponent is either negative or zero at this point. + ret.normalize(); + return ret; +} + std::string to_string(Number const& amount) { diff --git a/src/libxrpl/json/json_value.cpp b/src/libxrpl/json/json_value.cpp index a9478f51ab..1580e68255 100644 --- a/src/libxrpl/json/json_value.cpp +++ b/src/libxrpl/json/json_value.cpp @@ -1042,6 +1042,12 @@ Value::isMember(std::string const& key) const return isMember(key.c_str()); } +bool +Value::isMember(StaticString const& key) const +{ + return isMember(key.c_str()); +} + Value::Members Value::getMemberNames() const { diff --git a/src/libxrpl/ledger/ApplyView.cpp b/src/libxrpl/ledger/ApplyView.cpp index 19dfd199f9..911bec1722 100644 --- a/src/libxrpl/ledger/ApplyView.cpp +++ b/src/libxrpl/ledger/ApplyView.cpp @@ -8,73 +8,95 @@ namespace ripple { -std::optional -ApplyView::dirAdd( - bool preserveOrder, +namespace directory { + +std::uint64_t +createRoot( + ApplyView& view, Keylet const& directory, uint256 const& key, std::function const&)> const& describe) { - auto root = peek(directory); + auto newRoot = std::make_shared(directory); + newRoot->setFieldH256(sfRootIndex, directory.key); + describe(newRoot); - if (!root) - { - // No root, make it. - root = std::make_shared(directory); - root->setFieldH256(sfRootIndex, directory.key); - describe(root); + STVector256 v; + v.push_back(key); + newRoot->setFieldV256(sfIndexes, v); - STVector256 v; - v.push_back(key); - root->setFieldV256(sfIndexes, v); + view.insert(newRoot); + return std::uint64_t{0}; +} - insert(root); - return std::uint64_t{0}; - } +auto +findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start) +{ + std::uint64_t page = start->getFieldU64(sfIndexPrevious); - std::uint64_t page = root->getFieldU64(sfIndexPrevious); - - auto node = root; + auto node = start; if (page) { - node = peek(keylet::page(directory, page)); + node = view.peek(keylet::page(directory, page)); if (!node) + { // LCOV_EXCL_START LogicError("Directory chain: root back-pointer broken."); + // LCOV_EXCL_STOP + } } auto indexes = node->getFieldV256(sfIndexes); + return std::make_tuple(page, node, indexes); +} - // If there's space, we use it: - if (indexes.size() < dirNodeMaxEntries) +std::uint64_t +insertKey( + ApplyView& view, + SLE::ref node, + std::uint64_t page, + bool preserveOrder, + STVector256& indexes, + uint256 const& key) +{ + if (preserveOrder) { - if (preserveOrder) - { - if (std::find(indexes.begin(), indexes.end(), key) != indexes.end()) - LogicError("dirInsert: double insertion"); + if (std::find(indexes.begin(), indexes.end(), key) != indexes.end()) + LogicError("dirInsert: double insertion"); // LCOV_EXCL_LINE - indexes.push_back(key); - } - else - { - // We can't be sure if this page is already sorted because - // it may be a legacy page we haven't yet touched. Take - // the time to sort it. - std::sort(indexes.begin(), indexes.end()); + indexes.push_back(key); + } + else + { + // We can't be sure if this page is already sorted because + // it may be a legacy page we haven't yet touched. Take + // the time to sort it. + std::sort(indexes.begin(), indexes.end()); - auto pos = std::lower_bound(indexes.begin(), indexes.end(), key); + auto pos = std::lower_bound(indexes.begin(), indexes.end(), key); - if (pos != indexes.end() && key == *pos) - LogicError("dirInsert: double insertion"); + if (pos != indexes.end() && key == *pos) + LogicError("dirInsert: double insertion"); // LCOV_EXCL_LINE - indexes.insert(pos, key); - } - - node->setFieldV256(sfIndexes, indexes); - update(node); - return page; + indexes.insert(pos, key); } + node->setFieldV256(sfIndexes, indexes); + view.update(node); + return page; +} + +std::optional +insertPage( + ApplyView& view, + std::uint64_t page, + SLE::pointer node, + std::uint64_t nextPage, + SLE::ref next, + uint256 const& key, + Keylet const& directory, + std::function const&)> const& describe) +{ // We rely on modulo arithmetic of unsigned integers (guaranteed in // [basic.fundamental] paragraph 2) to detect page representation overflow. // For signed integers this would be UB, hence static_assert here. @@ -88,20 +110,20 @@ ApplyView::dirAdd( // Check whether we're out of pages. if (page == 0) return std::nullopt; - if (!rules().enabled(fixDirectoryLimit) && + if (!view.rules().enabled(fixDirectoryLimit) && page >= dirNodeMaxPages) // Old pages limit return std::nullopt; // We are about to create a new node; we'll link it to // the chain first: node->setFieldU64(sfIndexNext, page); - update(node); + view.update(node); - root->setFieldU64(sfIndexPrevious, page); - update(root); + next->setFieldU64(sfIndexPrevious, page); + view.update(next); // Insert the new key: - indexes.clear(); + STVector256 indexes; indexes.push_back(key); node = std::make_shared(keylet::page(directory, page)); @@ -112,12 +134,52 @@ ApplyView::dirAdd( // it's the default. if (page != 1) node->setFieldU64(sfIndexPrevious, page - 1); + XRPL_ASSERT_PARTS( + !nextPage, + "ripple::directory::insertPage", + "nextPage has default value"); + /* Reserved for future use when directory pages may be inserted in + * between two other pages instead of only at the end of the chain. + if (nextPage) + node->setFieldU64(sfIndexNext, nextPage); + */ describe(node); - insert(node); + view.insert(node); return page; } +} // namespace directory + +std::optional +ApplyView::dirAdd( + bool preserveOrder, + Keylet const& directory, + uint256 const& key, + std::function const&)> const& describe) +{ + auto root = peek(directory); + + if (!root) + { + // No root, make it. + return directory::createRoot(*this, directory, key, describe); + } + + auto [page, node, indexes] = + directory::findPreviousPage(*this, directory, root); + + // If there's space, we use it: + if (indexes.size() < dirNodeMaxEntries) + { + return directory::insertKey( + *this, node, page, preserveOrder, indexes, key); + } + + return directory::insertPage( + *this, page, node, 0, root, key, directory, describe); +} + bool ApplyView::emptyDirDelete(Keylet const& directory) { @@ -145,10 +207,10 @@ ApplyView::emptyDirDelete(Keylet const& directory) auto nextPage = node->getFieldU64(sfIndexNext); if (nextPage == rootPage && prevPage != rootPage) - LogicError("Directory chain: fwd link broken"); + LogicError("Directory chain: fwd link broken"); // LCOV_EXCL_LINE if (prevPage == rootPage && nextPage != rootPage) - LogicError("Directory chain: rev link broken"); + LogicError("Directory chain: rev link broken"); // LCOV_EXCL_LINE // Older versions of the code would, in some cases, allow the last // page to be empty. Remove such pages: @@ -157,7 +219,10 @@ ApplyView::emptyDirDelete(Keylet const& directory) auto last = peek(keylet::page(directory, nextPage)); if (!last) + { // LCOV_EXCL_START LogicError("Directory chain: fwd link broken."); + // LCOV_EXCL_STOP + } if (!last->getFieldV256(sfIndexes).empty()) return false; @@ -229,10 +294,16 @@ ApplyView::dirRemove( if (page == rootPage) { if (nextPage == page && prevPage != page) + { // LCOV_EXCL_START LogicError("Directory chain: fwd link broken"); + // LCOV_EXCL_STOP + } if (prevPage == page && nextPage != page) + { // LCOV_EXCL_START LogicError("Directory chain: rev link broken"); + // LCOV_EXCL_STOP + } // Older versions of the code would, in some cases, // allow the last page to be empty. Remove such @@ -241,7 +312,10 @@ ApplyView::dirRemove( { auto last = peek(keylet::page(directory, nextPage)); if (!last) + { // LCOV_EXCL_START LogicError("Directory chain: fwd link broken."); + // LCOV_EXCL_STOP + } if (last->getFieldV256(sfIndexes).empty()) { @@ -273,10 +347,10 @@ ApplyView::dirRemove( // This can never happen for nodes other than the root: if (nextPage == page) - LogicError("Directory chain: fwd link broken"); + LogicError("Directory chain: fwd link broken"); // LCOV_EXCL_LINE if (prevPage == page) - LogicError("Directory chain: rev link broken"); + LogicError("Directory chain: rev link broken"); // LCOV_EXCL_LINE // This node isn't the root, so it can either be in the // middle of the list, or at the end. Unlink it first @@ -284,14 +358,14 @@ ApplyView::dirRemove( // root: auto prev = peek(keylet::page(directory, prevPage)); if (!prev) - LogicError("Directory chain: fwd link broken."); + LogicError("Directory chain: fwd link broken."); // LCOV_EXCL_LINE // Fix previous to point to its new next. prev->setFieldU64(sfIndexNext, nextPage); update(prev); auto next = peek(keylet::page(directory, nextPage)); if (!next) - LogicError("Directory chain: rev link broken."); + LogicError("Directory chain: rev link broken."); // LCOV_EXCL_LINE // Fix next to point to its new previous. next->setFieldU64(sfIndexPrevious, prevPage); update(next); @@ -315,7 +389,10 @@ ApplyView::dirRemove( // And the root points to the last page: auto root = peek(keylet::page(directory, rootPage)); if (!root) + { // LCOV_EXCL_START LogicError("Directory chain: root link broken."); + // LCOV_EXCL_STOP + } root->setFieldU64(sfIndexPrevious, prevPage); update(root); diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 6356dd1131..33c6cf69ec 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -364,6 +364,99 @@ isLPTokenFrozen( isFrozen(view, account, asset2.currency, asset2.account); } +static SLE::const_pointer +getLineIfUsable( + ReadView const& view, + AccountID const& account, + Currency const& currency, + AccountID const& issuer, + FreezeHandling zeroIfFrozen, + beast::Journal j) +{ + auto const sle = view.read(keylet::line(account, issuer, currency)); + + if (!sle) + { + return nullptr; + } + + if (zeroIfFrozen == fhZERO_IF_FROZEN) + { + if (isFrozen(view, account, currency, issuer) || + isDeepFrozen(view, account, currency, issuer)) + { + return nullptr; + } + + // when fixFrozenLPTokenTransfer is enabled, if currency is lptoken, + // we need to check if the associated assets have been frozen + if (view.rules().enabled(fixFrozenLPTokenTransfer)) + { + auto const sleIssuer = view.read(keylet::account(issuer)); + if (!sleIssuer) + { + return nullptr; // LCOV_EXCL_LINE + } + else if (sleIssuer->isFieldPresent(sfAMMID)) + { + auto const sleAmm = + view.read(keylet::amm((*sleIssuer)[sfAMMID])); + + if (!sleAmm || + isLPTokenFrozen( + view, + account, + (*sleAmm)[sfAsset].get(), + (*sleAmm)[sfAsset2].get())) + { + return nullptr; + } + } + } + } + + return sle; +} + +static STAmount +getTrustLineBalance( + ReadView const& view, + SLE::const_ref sle, + AccountID const& account, + Currency const& currency, + AccountID const& issuer, + bool includeOppositeLimit, + beast::Journal j) +{ + STAmount amount; + if (sle) + { + amount = sle->getFieldAmount(sfBalance); + bool const accountHigh = account > issuer; + auto const& oppositeField = accountHigh ? sfLowLimit : sfHighLimit; + if (accountHigh) + { + // Put balance in account terms. + amount.negate(); + } + if (includeOppositeLimit) + { + amount += sle->getFieldAmount(oppositeField); + } + amount.setIssuer(issuer); + } + else + { + amount.clear(Issue{currency, issuer}); + } + + JLOG(j.trace()) << "getTrustLineBalance:" + << " account=" << to_string(account) + << " amount=" << amount.getFullText(); + + return view.balanceHook(account, issuer, amount); +} + STAmount accountHolds( ReadView const& view, @@ -380,71 +473,10 @@ accountHolds( } // IOU: Return balance on trust line modulo freeze - auto const sle = view.read(keylet::line(account, issuer, currency)); - auto const allowBalance = [&]() { - if (!sle) - { - return false; - } + SLE::const_pointer const sle = + getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j); - if (zeroIfFrozen == fhZERO_IF_FROZEN) - { - if (isFrozen(view, account, currency, issuer) || - isDeepFrozen(view, account, currency, issuer)) - { - return false; - } - - // when fixFrozenLPTokenTransfer is enabled, if currency is lptoken, - // we need to check if the associated assets have been frozen - if (view.rules().enabled(fixFrozenLPTokenTransfer)) - { - auto const sleIssuer = view.read(keylet::account(issuer)); - if (!sleIssuer) - { - return false; // LCOV_EXCL_LINE - } - else if (sleIssuer->isFieldPresent(sfAMMID)) - { - auto const sleAmm = - view.read(keylet::amm((*sleIssuer)[sfAMMID])); - - if (!sleAmm || - isLPTokenFrozen( - view, - account, - (*sleAmm)[sfAsset].get(), - (*sleAmm)[sfAsset2].get())) - { - return false; - } - } - } - } - - return true; - }(); - - if (allowBalance) - { - amount = sle->getFieldAmount(sfBalance); - if (account > issuer) - { - // Put balance in account terms. - amount.negate(); - } - amount.setIssuer(issuer); - } - else - { - amount.clear(Issue{currency, issuer}); - } - - JLOG(j.trace()) << "accountHolds:" - << " account=" << to_string(account) - << " amount=" << amount.getFullText(); - - return view.balanceHook(account, issuer, amount); + return getTrustLineBalance(view, sle, account, currency, issuer, false, j); } STAmount @@ -531,6 +563,96 @@ accountHolds( asset.value()); } +STAmount +accountSpendable( + ReadView const& view, + AccountID const& account, + Currency const& currency, + AccountID const& issuer, + FreezeHandling zeroIfFrozen, + beast::Journal j) +{ + if (isXRP(currency)) + return accountHolds(view, account, currency, issuer, zeroIfFrozen, j); + + if (account == issuer) + // If the account is the issuer, then their limit is effectively + // infinite + return STAmount{ + Issue{currency, issuer}, STAmount::cMaxValue, STAmount::cMaxOffset}; + + // IOU: Return balance on trust line modulo freeze + SLE::const_pointer const sle = + getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j); + + return getTrustLineBalance(view, sle, account, currency, issuer, true, j); +} + +STAmount +accountSpendable( + ReadView const& view, + AccountID const& account, + Issue const& issue, + FreezeHandling zeroIfFrozen, + beast::Journal j) +{ + return accountSpendable( + view, account, issue.currency, issue.account, zeroIfFrozen, j); +} + +STAmount +accountSpendable( + ReadView const& view, + AccountID const& account, + MPTIssue const& mptIssue, + FreezeHandling zeroIfFrozen, + AuthHandling zeroIfUnauthorized, + beast::Journal j) +{ + if (account == mptIssue.getIssuer()) + { + // if the account is the issuer, and the issuance exists, their limit is + // the issuance limit minus the outstanding value + auto const issuance = + view.read(keylet::mptIssuance(mptIssue.getMptID())); + + if (!issuance) + { + return STAmount{mptIssue}; + } + return STAmount{ + mptIssue, + issuance->at(~sfMaximumAmount).value_or(maxMPTokenAmount) - + issuance->at(sfOutstandingAmount)}; + } + + return accountHolds( + view, account, mptIssue, zeroIfFrozen, zeroIfUnauthorized, j); +} + +[[nodiscard]] STAmount +accountSpendable( + ReadView const& view, + AccountID const& account, + Asset const& asset, + FreezeHandling zeroIfFrozen, + AuthHandling zeroIfUnauthorized, + beast::Journal j) +{ + return std::visit( + [&](auto const& value) { + if constexpr (std::is_same_v< + std::remove_cvref_t, + Issue>) + { + return accountSpendable(view, account, value, zeroIfFrozen, j); + } + return accountSpendable( + view, account, value, zeroIfFrozen, zeroIfUnauthorized, j); + }, + asset.value()); +} + STAmount accountFunds( ReadView const& view, @@ -1036,13 +1158,17 @@ describeOwnerDir(AccountID const& account) } TER -dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr& object) +dirLink( + ApplyView& view, + AccountID const& owner, + std::shared_ptr& object, + SF_UINT64 const& node) { auto const page = view.dirInsert( keylet::ownerDir(owner), object->key(), describeOwnerDir(owner)); if (!page) return tecDIR_FULL; // LCOV_EXCL_LINE - object->setFieldU64(sfOwnerNode, *page); + object->setFieldU64(node, *page); return tesSUCCESS; } @@ -1078,7 +1204,8 @@ getPseudoAccountFields() { // LCOV_EXCL_START LogicError( - "ripple::isPseudoAccount : unable to find account root ledger " + "ripple::getPseudoAccountFields : unable to find account root " + "ledger " "format"); // LCOV_EXCL_STOP } @@ -1096,7 +1223,9 @@ getPseudoAccountFields() } [[nodiscard]] bool -isPseudoAccount(std::shared_ptr sleAcct) +isPseudoAccount( + std::shared_ptr sleAcct, + std::set const& pseudoFieldFilter) { auto const& fields = getPseudoAccountFields(); @@ -1104,8 +1233,12 @@ isPseudoAccount(std::shared_ptr sleAcct) // semantics of true return value clean. return sleAcct && sleAcct->getType() == ltACCOUNT_ROOT && std::count_if( - fields.begin(), fields.end(), [&sleAcct](SField const* sf) -> bool { - return sleAcct->isFieldPresent(*sf); + fields.begin(), + fields.end(), + [&sleAcct, &pseudoFieldFilter](SField const* sf) -> bool { + return sleAcct->isFieldPresent(*sf) && + (pseudoFieldFilter.empty() || + pseudoFieldFilter.contains(sf)); }) > 0; } @@ -1115,7 +1248,8 @@ createPseudoAccount( uint256 const& pseudoOwnerKey, SField const& ownerField) { - [[maybe_unused]] auto const& fields = getPseudoAccountFields(); + [[maybe_unused]] + auto const& fields = getPseudoAccountFields(); XRPL_ASSERT( std::count_if( fields.begin(), @@ -1137,9 +1271,10 @@ createPseudoAccount( // Pseudo-accounts can't submit transactions, so set the sequence number // to 0 to make them easier to spot and verify, and add an extra level // of protection. - std::uint32_t const seqno = // - view.rules().enabled(featureSingleAssetVault) // - ? 0 // + std::uint32_t const seqno = // + view.rules().enabled(featureSingleAssetVault) || // + view.rules().enabled(featureLendingProtocol) // + ? 0 // : view.seq(); account->setFieldU32(sfSequence, seqno); // Ignore reserves requirement, disable the master key, allow default @@ -1193,6 +1328,113 @@ canAddHolding(ReadView const& view, Asset const& asset) asset.value()); } +[[nodiscard]] TER +checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag) +{ + if (toSle == nullptr) + return tecNO_DST; + + // The tag is basically account-specific information we don't + // understand, but we can require someone to fill it in. + if (toSle->isFlag(lsfRequireDestTag) && !hasDestinationTag) + return tecDST_TAG_NEEDED; // Cannot send without a tag + + return tesSUCCESS; +} + +[[nodiscard]] TER +canWithdraw( + AccountID const& from, + ReadView const& view, + AccountID const& to, + SLE::const_ref toSle, + bool hasDestinationTag) +{ + if (auto const ret = checkDestinationAndTag(toSle, hasDestinationTag)) + return ret; + + if (from == to) + return tesSUCCESS; + + if (toSle->isFlag(lsfDepositAuth)) + { + if (!view.exists(keylet::depositPreauth(to, from))) + return tecNO_PERMISSION; + } + + return tesSUCCESS; +} + +[[nodiscard]] TER +canWithdraw( + AccountID const& from, + ReadView const& view, + AccountID const& to, + bool hasDestinationTag) +{ + auto const toSle = view.read(keylet::account(to)); + + return canWithdraw(from, view, to, toSle, hasDestinationTag); +} + +[[nodiscard]] TER +canWithdraw(ReadView const& view, STTx const& tx) +{ + auto const from = tx[sfAccount]; + auto const to = tx[~sfDestination].value_or(from); + + return canWithdraw(from, view, to, tx.isFieldPresent(sfDestinationTag)); +} + +TER +doWithdraw( + ApplyView& view, + STTx const& tx, + AccountID const& senderAcct, + AccountID const& dstAcct, + AccountID const& sourceAcct, + XRPAmount priorBalance, + STAmount const& amount, + beast::Journal j) +{ + // Create trust line or MPToken for the receiving account + if (dstAcct == senderAcct) + { + if (auto const ter = addEmptyHolding( + view, senderAcct, priorBalance, amount.asset(), j); + !isTesSuccess(ter) && ter != tecDUPLICATE) + return ter; + } + else + { + auto dstSle = view.peek(keylet::account(dstAcct)); + if (auto err = + verifyDepositPreauth(tx, view, senderAcct, dstAcct, dstSle, j)) + return err; + } + + // Sanity check + if (accountHolds( + view, + sourceAcct, + amount.asset(), + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + j) < amount) + { + // LCOV_EXCL_START + JLOG(j.error()) << "LoanBrokerCoverWithdraw: negative balance of " + "broker cover assets."; + return tefINTERNAL; + // LCOV_EXCL_STOP + } + + // Move the funds directly from the broker's pseudo-account to the + // dstAcct + return accountSend( + view, sourceAcct, dstAcct, amount, j, WaiveTransferFee::Yes); +} + [[nodiscard]] TER addEmptyHolding( ApplyView& view, @@ -1201,8 +1443,8 @@ addEmptyHolding( Issue const& issue, beast::Journal journal) { - // Every account can hold XRP. - if (issue.native()) + // Every account can hold XRP. An issuer can issue directly. + if (issue.native() || accountID == issue.getIssuer()) return tesSUCCESS; auto const& issuerId = issue.getIssuer(); @@ -1263,6 +1505,8 @@ addEmptyHolding( return tefINTERNAL; // LCOV_EXCL_LINE if (view.peek(keylet::mptoken(mptID, accountID))) return tecDUPLICATE; + if (accountID == mptIssue.getIssuer()) + return tesSUCCESS; return authorizeMPToken(view, priorBalance, mptID, accountID, journal); } @@ -1326,6 +1570,18 @@ authorizeMPToken( if (priorBalance < reserveCreate) return tecINSUFFICIENT_RESERVE; + // Defensive check before we attempt to create MPToken for the issuer + auto const mpt = view.read(keylet::mptIssuance(mptIssuanceID)); + if (!mpt || mpt->getAccountID(sfIssuer) == account) + { + // LCOV_EXCL_START + UNREACHABLE( + "ripple::authorizeMPToken : invalid issuance or issuers token"); + if (view.rules().enabled(featureLendingProtocol)) + return tecINTERNAL; + // LCOV_EXCL_STOP + } + auto const mptokenKey = keylet::mptoken(mptIssuanceID, account); auto mptoken = std::make_shared(mptokenKey); if (auto ter = dirLink(view, account, mptoken)) @@ -1401,6 +1657,14 @@ trustCreate( auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID; auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID; + if (uLowAccountID == uHighAccountID) + { + // LCOV_EXCL_START + UNREACHABLE("ripple::trustCreate : trust line to self"); + if (view.rules().enabled(featureLendingProtocol)) + return tecINTERNAL; + // LCOV_EXCL_STOP + } auto const sleRippleState = std::make_shared(ltRIPPLE_STATE, uIndex); view.insert(sleRippleState); @@ -1515,10 +1779,13 @@ removeEmptyHolding( } // `asset` is an IOU. + // If the account is the issuer, then no line should exist. Check anyway. If + // a line does exist, it will get deleted. If not, return success. + bool const accountIsIssuer = accountID == issue.account; auto const line = view.peek(keylet::line(accountID, issue)); if (!line) - return tecOBJECT_NOT_FOUND; - if (line->at(sfBalance)->iou() != beast::zero) + return accountIsIssuer ? (TER)tesSUCCESS : (TER)tecOBJECT_NOT_FOUND; + if (!accountIsIssuer && line->at(sfBalance)->iou() != beast::zero) return tecHAS_OBLIGATIONS; // Adjust the owner count(s) @@ -1567,10 +1834,18 @@ removeEmptyHolding( MPTIssue const& mptIssue, beast::Journal journal) { + // If the account is the issuer, then no token should exist. MPTs do not + // have the legacy ability to create such a situation, but check anyway. If + // a token does exist, it will get deleted. If not, return success. + bool const accountIsIssuer = accountID == mptIssue.getIssuer(); auto const& mptID = mptIssue.getMptID(); auto const mptoken = view.peek(keylet::mptoken(mptID, accountID)); if (!mptoken) - return tecOBJECT_NOT_FOUND; + return accountIsIssuer ? (TER)tesSUCCESS : (TER)tecOBJECT_NOT_FOUND; + // Unlike a trust line, if the account is the issuer, and the token has a + // balance, it can not just be deleted, because that will throw the issuance + // accounting out of balance, so fail. Since this should be impossible + // anyway, I'm not going to put any effort into it. if (mptoken->at(sfMPTAmount) != 0) return tecHAS_OBLIGATIONS; @@ -1849,7 +2124,7 @@ rippleSendIOU( beast::Journal j, WaiveTransferFee waiveFee) { - auto const issuer = saAmount.getIssuer(); + auto const& issuer = saAmount.getIssuer(); XRPL_ASSERT( !isXRP(uSenderID) && !isXRP(uReceiverID), @@ -1891,6 +2166,87 @@ rippleSendIOU( return terResult; } +// Send regardless of limits. +// --> receivers: Amount/currency/issuer to deliver to receivers. +// <-- saActual: Amount actually cost to sender. Sender pays fees. +static TER +rippleSendMultiIOU( + ApplyView& view, + AccountID const& senderID, + Issue const& issue, + MultiplePaymentDestinations const& receivers, + STAmount& actual, + beast::Journal j, + WaiveTransferFee waiveFee) +{ + auto const& issuer = issue.getIssuer(); + + XRPL_ASSERT( + !isXRP(senderID), "ripple::rippleSendMultiIOU : sender is not XRP"); + + // These may diverge + STAmount takeFromSender{issue}; + actual = takeFromSender; + + // Failures return immediately. + for (auto const& r : receivers) + { + auto const& receiverID = r.first; + STAmount amount{issue, r.second}; + + /* If we aren't sending anything or if the sender is the same as the + * receiver then we don't need to do anything. + */ + if (!amount || (senderID == receiverID)) + continue; + + XRPL_ASSERT( + !isXRP(receiverID), + "ripple::rippleSendMultiIOU : receiver is not XRP"); + + if (senderID == issuer || receiverID == issuer || issuer == noAccount()) + { + // Direct send: redeeming IOUs and/or sending own IOUs. + if (auto const ter = rippleCreditIOU( + view, senderID, receiverID, amount, false, j)) + return ter; + actual += amount; + // Do not add amount to takeFromSender, because rippleCreditIOU took + // it. + + continue; + } + + // Sending 3rd party IOUs: transit. + + // Calculate the amount to transfer accounting + // for any transfer fees if the fee is not waived: + STAmount actualSend = (waiveFee == WaiveTransferFee::Yes) + ? amount + : multiply(amount, transferRate(view, issuer)); + actual += actualSend; + takeFromSender += actualSend; + + JLOG(j.debug()) << "rippleSendMultiIOU> " << to_string(senderID) + << " - > " << to_string(receiverID) + << " : deliver=" << amount.getFullText() + << " cost=" << actual.getFullText(); + + if (TER const terResult = + rippleCreditIOU(view, issuer, receiverID, amount, true, j)) + return terResult; + } + + if (senderID != issuer && takeFromSender) + { + if (TER const terResult = rippleCreditIOU( + view, senderID, issuer, takeFromSender, true, j)) + return terResult; + } + + return tesSUCCESS; +} + static TER accountSendIOU( ApplyView& view, @@ -2015,6 +2371,144 @@ accountSendIOU( return terResult; } +static TER +accountSendMultiIOU( + ApplyView& view, + AccountID const& senderID, + Issue const& issue, + MultiplePaymentDestinations const& receivers, + beast::Journal j, + WaiveTransferFee waiveFee) +{ + XRPL_ASSERT_PARTS( + receivers.size() > 1, + "ripple::accountSendMultiIOU", + "multiple recipients provided"); + + if (!issue.native()) + { + STAmount actual; + JLOG(j.trace()) << "accountSendMultiIOU: " << to_string(senderID) + << " sending " << receivers.size() << " IOUs"; + + return rippleSendMultiIOU( + view, senderID, issue, receivers, actual, j, waiveFee); + } + + /* XRP send which does not check reserve and can do pure adjustment. + * Note that sender or receiver may be null and this not a mistake; this + * setup could be used during pathfinding and it is carefully controlled to + * ensure that transfers are balanced. + */ + + SLE::pointer sender = senderID != beast::zero + ? view.peek(keylet::account(senderID)) + : SLE::pointer(); + + if (auto stream = j.trace()) + { + std::string sender_bal("-"); + + if (sender) + sender_bal = sender->getFieldAmount(sfBalance).getFullText(); + + stream << "accountSendMultiIOU> " << to_string(senderID) << " (" + << sender_bal << ") -> " << receivers.size() << " receivers."; + } + + // Failures return immediately. + STAmount takeFromSender{issue}; + for (auto const& r : receivers) + { + auto const& receiverID = r.first; + STAmount amount{issue, r.second}; + + if (amount < beast::zero) + { + return tecINTERNAL; // LCOV_EXCL_LINE + } + + /* If we aren't sending anything or if the sender is the same as the + * receiver then we don't need to do anything. + */ + if (!amount || (senderID == receiverID)) + continue; + + SLE::pointer receiver = receiverID != beast::zero + ? view.peek(keylet::account(receiverID)) + : SLE::pointer(); + + if (auto stream = j.trace()) + { + std::string receiver_bal("-"); + + if (receiver) + receiver_bal = + receiver->getFieldAmount(sfBalance).getFullText(); + + stream << "accountSendMultiIOU> " << to_string(senderID) << " -> " + << to_string(receiverID) << " (" << receiver_bal + << ") : " << amount.getFullText(); + } + + if (receiver) + { + // Increment XRP balance. + auto const rcvBal = receiver->getFieldAmount(sfBalance); + receiver->setFieldAmount(sfBalance, rcvBal + amount); + view.creditHook(xrpAccount(), receiverID, amount, -rcvBal); + + view.update(receiver); + + // Take what is actually sent + takeFromSender += amount; + } + + if (auto stream = j.trace()) + { + std::string receiver_bal("-"); + + if (receiver) + receiver_bal = + receiver->getFieldAmount(sfBalance).getFullText(); + + stream << "accountSendMultiIOU< " << to_string(senderID) << " -> " + << to_string(receiverID) << " (" << receiver_bal + << ") : " << amount.getFullText(); + } + } + + if (sender) + { + if (sender->getFieldAmount(sfBalance) < takeFromSender) + { + return TER{tecFAILED_PROCESSING}; + } + else + { + auto const sndBal = sender->getFieldAmount(sfBalance); + view.creditHook(senderID, xrpAccount(), takeFromSender, sndBal); + + // Decrement XRP balance. + sender->setFieldAmount(sfBalance, sndBal - takeFromSender); + view.update(sender); + } + } + + if (auto stream = j.trace()) + { + std::string sender_bal("-"); + std::string receiver_bal("-"); + + if (sender) + sender_bal = sender->getFieldAmount(sfBalance).getFullText(); + + stream << "accountSendMultiIOU< " << to_string(senderID) << " (" + << sender_bal << ") -> " << receivers.size() << " receivers."; + } + return tesSUCCESS; +} + static TER rippleCreditMPT( ApplyView& view, @@ -2025,7 +2519,7 @@ rippleCreditMPT( { // Do not check MPT authorization here - it must have been checked earlier auto const mptID = keylet::mptIssuance(saAmount.get().getMptID()); - auto const issuer = saAmount.getIssuer(); + auto const& issuer = saAmount.getIssuer(); auto sleIssuance = view.peek(mptID); if (!sleIssuance) return tecOBJECT_NOT_FOUND; @@ -2092,7 +2586,7 @@ rippleSendMPT( "ripple::rippleSendMPT : sender is not receiver"); // Safe to get MPT since rippleSendMPT is only called by accountSendMPT - auto const issuer = saAmount.getIssuer(); + auto const& issuer = saAmount.getIssuer(); auto const sle = view.read(keylet::mptIssuance(saAmount.get().getMptID())); @@ -2143,6 +2637,102 @@ rippleSendMPT( return rippleCreditMPT(view, uSenderID, issuer, saActual, j); } +static TER +rippleSendMultiMPT( + ApplyView& view, + AccountID const& senderID, + MPTIssue const& mptIssue, + MultiplePaymentDestinations const& receivers, + STAmount& actual, + beast::Journal j, + WaiveTransferFee waiveFee) +{ + // Safe to get MPT since rippleSendMultiMPT is only called by + // accountSendMultiMPT + auto const& issuer = mptIssue.getIssuer(); + + auto const sle = view.read(keylet::mptIssuance(mptIssue.getMptID())); + if (!sle) + return tecOBJECT_NOT_FOUND; + + // These may diverge + STAmount takeFromSender{mptIssue}; + actual = takeFromSender; + + for (auto const& r : receivers) + { + auto const& receiverID = r.first; + STAmount amount{mptIssue, r.second}; + + if (amount < beast::zero) + { + return tecINTERNAL; // LCOV_EXCL_LINE + } + + /* If we aren't sending anything or if the sender is the same as the + * receiver then we don't need to do anything. + */ + if (!amount || (senderID == receiverID)) + continue; + + if (senderID == issuer || receiverID == issuer) + { + // if sender is issuer, check that the new OutstandingAmount will + // not exceed MaximumAmount + if (senderID == issuer) + { + XRPL_ASSERT_PARTS( + takeFromSender == beast::zero, + "rippler::rippleSendMultiMPT", + "sender == issuer, takeFromSender == zero"); + auto const sendAmount = amount.mpt().value(); + auto const maximumAmount = + sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount); + if (sendAmount > maximumAmount || + sle->getFieldU64(sfOutstandingAmount) > + maximumAmount - sendAmount) + return tecPATH_DRY; + } + + // Direct send: redeeming MPTs and/or sending own MPTs. + if (auto const ter = + rippleCreditMPT(view, senderID, receiverID, amount, j)) + return ter; + actual += amount; + // Do not add amount to takeFromSender, because rippleCreditMPT took + // it + + continue; + } + + // Sending 3rd party MPTs: transit. + STAmount actualSend = (waiveFee == WaiveTransferFee::Yes) + ? amount + : multiply( + amount, + transferRate(view, amount.get().getMptID())); + actual += actualSend; + takeFromSender += actualSend; + + JLOG(j.debug()) << "rippleSendMultiMPT> " << to_string(senderID) + << " - > " << to_string(receiverID) + << " : deliver=" << amount.getFullText() + << " cost=" << actualSend.getFullText(); + + if (auto const terResult = + rippleCreditMPT(view, issuer, receiverID, amount, j)) + return terResult; + } + if (senderID != issuer && takeFromSender) + { + if (TER const terResult = + rippleCreditMPT(view, senderID, issuer, takeFromSender, j)) + return terResult; + } + + return tesSUCCESS; +} + static TER accountSendMPT( ApplyView& view, @@ -2168,6 +2758,21 @@ accountSendMPT( view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee); } +static TER +accountSendMultiMPT( + ApplyView& view, + AccountID const& senderID, + MPTIssue const& mptIssue, + MultiplePaymentDestinations const& receivers, + beast::Journal j, + WaiveTransferFee waiveFee) +{ + STAmount actual; + + return rippleSendMultiMPT( + view, senderID, mptIssue, receivers, actual, j, waiveFee); +} + TER accountSend( ApplyView& view, @@ -2189,6 +2794,31 @@ accountSend( saAmount.asset().value()); } +TER +accountSendMulti( + ApplyView& view, + AccountID const& senderID, + Asset const& asset, + MultiplePaymentDestinations const& receivers, + beast::Journal j, + WaiveTransferFee waiveFee) +{ + XRPL_ASSERT_PARTS( + receivers.size() > 1, + "ripple::accountSendMulti", + "multiple recipients provided"); + return std::visit( + [&](TIss const& issue) { + if constexpr (std::is_same_v) + return accountSendMultiIOU( + view, senderID, issue, receivers, j, waiveFee); + else + return accountSendMultiMPT( + view, senderID, issue, receivers, j, waiveFee); + }, + asset.value()); +} + static bool updateTrustLine( ApplyView& view, @@ -2513,7 +3143,10 @@ requireAuth( if (mptIssuer == account) // Issuer won't have MPToken return tesSUCCESS; - if (view.rules().enabled(featureSingleAssetVault)) + bool const featureSAVEnabled = + view.rules().enabled(featureSingleAssetVault); + + if (featureSAVEnabled) { if (depth >= maxAssetCheckDepth) return tecINTERNAL; // LCOV_EXCL_LINE @@ -2572,6 +3205,13 @@ requireAuth( // belong to someone who is explicitly authorized e.g. a vault owner. } + if (featureSAVEnabled) + { + // Implicitly authorize Vault and LoanBroker pseudo-accounts + if (isPseudoAccount(view, account, {&sfVaultID, &sfLoanBrokerID})) + return tesSUCCESS; + } + // mptoken must be authorized if issuance enabled requireAuth if (sleIssuance->isFlag(lsfMPTRequireAuth) && (!sleToken || !sleToken->isFlag(lsfMPTAuthorized))) @@ -2701,6 +3341,42 @@ canTransfer( return tesSUCCESS; } +[[nodiscard]] TER +canTransfer( + ReadView const& view, + Issue const& issue, + AccountID const& from, + AccountID const& to) +{ + if (issue.native()) + return tesSUCCESS; + + auto const& issuerId = issue.getIssuer(); + if (issuerId == from || issuerId == to) + return tesSUCCESS; + auto const sleIssuer = view.read(keylet::account(issuerId)); + if (sleIssuer == nullptr) + return tefINTERNAL; // LCOV_EXCL_LINE + + auto const isRippleDisabled = [&](AccountID account) -> bool { + // Line might not exist, but some transfers can create it. If this + // is the case, just check the default ripple on the issuer account. + auto const line = view.read(keylet::line(account, issue)); + if (line) + { + bool const issuerHigh = issuerId > account; + return line->isFlag(issuerHigh ? lsfHighNoRipple : lsfLowNoRipple); + } + return sleIssuer->isFlag(lsfDefaultRipple) == false; + }; + + // Fail if rippling disabled on both trust lines + if (isRippleDisabled(from) && isRippleDisabled(to)) + return terNO_RIPPLE; + + return tesSUCCESS; +} + TER cleanupOnAccountDelete( ApplyView& view, diff --git a/src/libxrpl/protocol/Indexes.cpp b/src/libxrpl/protocol/Indexes.cpp index fbe591074e..b80f648c98 100644 --- a/src/libxrpl/protocol/Indexes.cpp +++ b/src/libxrpl/protocol/Indexes.cpp @@ -77,6 +77,8 @@ enum class LedgerNameSpace : std::uint16_t { PERMISSIONED_DOMAIN = 'm', DELEGATE = 'E', VAULT = 'V', + LOAN_BROKER = 'l', // lower-case L + LOAN = 'L', // No longer used or supported. Left here to reserve the space // to avoid accidental reuse. @@ -547,6 +549,18 @@ vault(AccountID const& owner, std::uint32_t seq) noexcept return vault(indexHash(LedgerNameSpace::VAULT, owner, seq)); } +Keylet +loanbroker(AccountID const& owner, std::uint32_t seq) noexcept +{ + return loanbroker(indexHash(LedgerNameSpace::LOAN_BROKER, owner, seq)); +} + +Keylet +loan(uint256 const& loanBrokerID, std::uint32_t loanSeq) noexcept +{ + return loan(indexHash(LedgerNameSpace::LOAN, loanBrokerID, loanSeq)); +} + Keylet permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept { diff --git a/src/libxrpl/protocol/InnerObjectFormats.cpp b/src/libxrpl/protocol/InnerObjectFormats.cpp index 60a2f51f44..d720c6c665 100644 --- a/src/libxrpl/protocol/InnerObjectFormats.cpp +++ b/src/libxrpl/protocol/InnerObjectFormats.cpp @@ -153,6 +153,14 @@ InnerObjectFormats::InnerObjectFormats() {sfBookDirectory, soeREQUIRED}, {sfBookNode, soeREQUIRED}, }); + + add(sfCounterpartySignature.jsonName, + sfCounterpartySignature.getCode(), + { + {sfSigningPubKey, soeOPTIONAL}, + {sfTxnSignature, soeOPTIONAL}, + {sfSigners, soeOPTIONAL}, + }); } InnerObjectFormats const& diff --git a/src/libxrpl/protocol/STAmount.cpp b/src/libxrpl/protocol/STAmount.cpp index d659ee0d05..8b714193cc 100644 --- a/src/libxrpl/protocol/STAmount.cpp +++ b/src/libxrpl/protocol/STAmount.cpp @@ -279,7 +279,7 @@ STAmount::xrp() const IOUAmount STAmount::iou() const { - if (native() || !holds()) + if (integral()) Throw("Cannot return non-IOU STAmount as IOUAmount"); auto mantissa = static_cast(mValue); @@ -830,7 +830,7 @@ STAmount::isDefault() const void STAmount::canonicalize() { - if (native() || mAsset.holds()) + if (integral()) { // native and MPT currency amounts should always have an offset of zero // log(2^64,10) ~ 19.2 @@ -859,8 +859,10 @@ STAmount::canonicalize() }; if (native()) set(XRPAmount{num}); - else + else if (mAsset.holds()) set(MPTAmount{num}); + else + Throw("Unknown integral asset type"); mOffset = 0; } else @@ -1461,6 +1463,33 @@ canonicalizeRoundStrict( } } +STAmount +roundToScale( + STAmount const& value, + std::int32_t scale, + Number::rounding_mode rounding) +{ + // Nothing to do for integral types. + if (value.integral()) + return value; + + // If the value's exponent is greater than or equal to the scale, then + // rounding will do nothing, and might even lose precision, so just return + // the value. + if (value.exponent() >= scale) + return value; + + STAmount const referenceValue{ + value.asset(), STAmount::cMinValue, scale, value.negative()}; + + NumberRoundModeGuard mg(rounding); + // With an IOU, the the result of addition will be truncated to the + // precision of the larger value, which in this case is referenceValue. Then + // remove the reference value via subtraction, and we're left with the + // rounded value. + return (value + referenceValue) - referenceValue; +} + namespace { // We need a class that has an interface similar to NumberRoundModeGuard diff --git a/src/libxrpl/protocol/STTx.cpp b/src/libxrpl/protocol/STTx.cpp index b89f337288..d3b3ab4a88 100644 --- a/src/libxrpl/protocol/STTx.cpp +++ b/src/libxrpl/protocol/STTx.cpp @@ -261,15 +261,12 @@ STTx::checkSign(Rules const& rules) const if (auto const ret = checkSign(rules, *this); !ret) return ret; - /* Placeholder for field that will be added by Lending Protocol if (isFieldPresent(sfCounterpartySignature)) { auto const counterSig = getFieldObject(sfCounterpartySignature); - if (auto const ret = checkSign(rules, counterSig); - !ret) + if (auto const ret = checkSign(rules, counterSig); !ret) return Unexpected("Counterparty: " + ret.error()); } - */ return {}; } diff --git a/src/test/app/Batch_test.cpp b/src/test/app/Batch_test.cpp index 9823feaa11..f2fae58a9b 100644 --- a/src/test/app/Batch_test.cpp +++ b/src/test/app/Batch_test.cpp @@ -2535,6 +2535,207 @@ class Batch_test : public beast::unit_test::suite } } + void + testLoan(FeatureBitset features) + { + testcase("loan"); + + bool const lendingBatchEnabled = !std::any_of( + Batch::disabledTxTypes.begin(), + Batch::disabledTxTypes.end(), + [](auto const& disabled) { return disabled == ttLOAN_BROKER_SET; }); + + using namespace test::jtx; + + test::jtx::Env env{ + *this, + envconfig(), + features | featureSingleAssetVault | featureLendingProtocol | + featureMPTokensV1}; + + Account const issuer{"issuer"}; + // For simplicity, lender will be the sole actor for the vault & + // brokers. + Account const lender{"lender"}; + // Borrower only wants to borrow + Account const borrower{"borrower"}; + + // Fund the accounts and trust lines with the same amount so that tests + // can use the same values regardless of the asset. + env.fund(XRP(100'000), issuer, noripple(lender, borrower)); + env.close(); + + // Just use an XRP asset + PrettyAsset const asset{xrpIssue(), 1'000'000}; + + Vault vault{env}; + + auto const deposit = asset(50'000); + auto const debtMaximumValue = asset(25'000).value(); + auto const coverDepositValue = asset(1000).value(); + + auto [tx, vaultKeylet] = + vault.create({.owner = lender, .asset = asset}); + env(tx); + env.close(); + BEAST_EXPECT(env.le(vaultKeylet)); + + env(vault.deposit( + {.depositor = lender, .id = vaultKeylet.key, .amount = deposit})); + env.close(); + + auto const brokerKeylet = + keylet::loanbroker(lender.id(), env.seq(lender)); + + { + using namespace loanBroker; + env(set(lender, vaultKeylet.key), + managementFeeRate(TenthBips16(100)), + debtMaximum(debtMaximumValue), + coverRateMinimum(TenthBips32(percentageToTenthBips(10))), + coverRateLiquidation(TenthBips32(percentageToTenthBips(25)))); + + env(coverDeposit(lender, brokerKeylet.key, coverDepositValue)); + + env.close(); + } + + { + using namespace loan; + using namespace std::chrono_literals; + + auto const lenderSeq = env.seq(lender); + auto const batchFee = batch::calcBatchFee(env, 0, 2); + + auto const loanKeylet = keylet::loan(brokerKeylet.key, 1); + { + auto const [txIDs, batchID] = submitBatch( + env, + lendingBatchEnabled ? temBAD_SIGNATURE + : temINVALID_INNER_BATCH, + batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), + batch::inner( + env.json( + set(lender, brokerKeylet.key, asset(1000).value()), + // Not allowed to include the counterparty signature + sig(sfCounterpartySignature, borrower), + sig(none), + fee(none), + seq(none)), + lenderSeq + 1), + batch::inner( + pay(lender, + loanKeylet.key, + STAmount{asset, asset(500).value()}), + lenderSeq + 2)); + } + { + auto const [txIDs, batchID] = submitBatch( + env, + temINVALID_INNER_BATCH, + batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), + batch::inner( + env.json( + set(lender, brokerKeylet.key, asset(1000).value()), + // Counterparty must be set + sig(none), + fee(none), + seq(none)), + lenderSeq + 1), + batch::inner( + pay(lender, + loanKeylet.key, + STAmount{asset, asset(500).value()}), + lenderSeq + 2)); + } + { + auto const [txIDs, batchID] = submitBatch( + env, + lendingBatchEnabled ? temBAD_SIGNER + : temINVALID_INNER_BATCH, + batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), + batch::inner( + env.json( + set(lender, brokerKeylet.key, asset(1000).value()), + // Counterparty must sign the outer transaction + counterparty(borrower.id()), + sig(none), + fee(none), + seq(none)), + lenderSeq + 1), + batch::inner( + pay(lender, + loanKeylet.key, + STAmount{asset, asset(500).value()}), + lenderSeq + 2)); + } + { + // LoanSet normally charges at least 2x base fee, but since the + // signature check is done by the batch, it only charges the + // base fee. + auto const batchFee = batch::calcBatchFee(env, 1, 2); + auto const [txIDs, batchID] = submitBatch( + env, + lendingBatchEnabled ? TER(tesSUCCESS) + : TER(temINVALID_INNER_BATCH), + batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), + batch::inner( + env.json( + set(lender, brokerKeylet.key, asset(1000).value()), + counterparty(borrower.id()), + sig(none), + fee(none), + seq(none)), + lenderSeq + 1), + batch::inner( + pay( + // However, this inner transaction will fail, + // because the lender is not allowed to draw the + // transaction + lender, + loanKeylet.key, + STAmount{asset, asset(500).value()}), + lenderSeq + 2), + batch::sig(borrower)); + } + env.close(); + BEAST_EXPECT(env.le(brokerKeylet)); + BEAST_EXPECT(!env.le(loanKeylet)); + { + // LoanSet normally charges at least 2x base fee, but since the + // signature check is done by the batch, it only charges the + // base fee. + auto const lenderSeq = env.seq(lender); + auto const batchFee = batch::calcBatchFee(env, 1, 2); + auto const [txIDs, batchID] = submitBatch( + env, + lendingBatchEnabled ? TER(tesSUCCESS) + : TER(temINVALID_INNER_BATCH), + batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), + batch::inner( + env.json( + set(lender, brokerKeylet.key, asset(1000).value()), + counterparty(borrower.id()), + sig(none), + fee(none), + seq(none)), + lenderSeq + 1), + batch::inner( + manage(lender, loanKeylet.key, tfLoanImpair), + lenderSeq + 2), + batch::sig(borrower)); + } + env.close(); + BEAST_EXPECT(env.le(brokerKeylet)); + if (auto const sleLoan = env.le(loanKeylet); lendingBatchEnabled + ? BEAST_EXPECT(sleLoan) + : !BEAST_EXPECT(!sleLoan)) + { + BEAST_EXPECT(sleLoan->isFlag(lsfLoanImpaired)); + } + } + } + void testObjectCreateSequence(FeatureBitset features) { @@ -4128,6 +4329,7 @@ class Batch_test : public beast::unit_test::suite testAccountActivation(features); testAccountSet(features); testAccountDelete(features); + testLoan(features); testObjectCreateSequence(features); testObjectCreateTicket(features); testObjectCreate3rdParty(features); diff --git a/src/test/app/Invariants_test.cpp b/src/test/app/Invariants_test.cpp index 63682dff0d..4e4632e49b 100644 --- a/src/test/app/Invariants_test.cpp +++ b/src/test/app/Invariants_test.cpp @@ -155,9 +155,13 @@ class Invariants_test : public beast::unit_test::suite {{"an account root was deleted"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // remove an account from the view - auto const sle = ac.view().peek(keylet::account(A1.id())); + auto sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; + // Clear the balance so the "account deletion left behind a + // non-zero balance" check doesn't trip earlier than the desired + // check. + sle->at(sfBalance) = beast::zero; ac.view().erase(sle); return true; }); @@ -181,10 +185,15 @@ class Invariants_test : public beast::unit_test::suite {{"account deletion succeeded but deleted multiple accounts"}}, [](Account const& A1, Account const& A2, ApplyContext& ac) { // remove two accounts from the view - auto const sleA1 = ac.view().peek(keylet::account(A1.id())); - auto const sleA2 = ac.view().peek(keylet::account(A2.id())); + auto sleA1 = ac.view().peek(keylet::account(A1.id())); + auto sleA2 = ac.view().peek(keylet::account(A2.id())); if (!sleA1 || !sleA2) return false; + // Clear the balance so the "account deletion left behind a + // non-zero balance" check doesn't trip earlier than the desired + // check. + sleA1->at(sfBalance) = beast::zero; + sleA2->at(sfBalance) = beast::zero; ac.view().erase(sleA1); ac.view().erase(sleA2); return true; @@ -199,6 +208,46 @@ class Invariants_test : public beast::unit_test::suite using namespace test::jtx; testcase << "account root deletion left artifact"; + doInvariantCheck( + {{"account deletion left behind a non-zero balance"}}, + [&](Account const& A1, Account const& A2, ApplyContext& ac) { + // A1 has a balance. Delete A1 + auto const a1 = A1.id(); + auto const sleA1 = ac.view().peek(keylet::account(a1)); + if (!sleA1) + return false; + if (!BEAST_EXPECT(*sleA1->at(sfBalance) != beast::zero)) + return false; + + ac.view().erase(sleA1); + + return true; + }, + XRPAmount{}, + STTx{ttACCOUNT_DELETE, [](STObject& tx) {}}); + + doInvariantCheck( + {{"account deletion left behind a non-zero owner count"}}, + [&](Account const& A1, Account const& A2, ApplyContext& ac) { + // Increment A1's owner count, then delete A1 + auto const a1 = A1.id(); + auto const sleA1 = ac.view().peek(keylet::account(a1)); + if (!sleA1) + return false; + // Clear the balance so the "account deletion left behind a + // non-zero balance" check doesn't trip earlier than the desired + // check. + sleA1->at(sfBalance) = beast::zero; + BEAST_EXPECT(sleA1->at(sfOwnerCount) == 0); + adjustOwnerCount(ac.view(), sleA1, 1, ac.journal); + + ac.view().erase(sleA1); + + return true; + }, + XRPAmount{}, + STTx{ttACCOUNT_DELETE, [](STObject& tx) {}}); + for (auto const& keyletInfo : directAccountKeylets) { // TODO: Use structured binding once LLVM 16 is the minimum @@ -219,29 +268,38 @@ class Invariants_test : public beast::unit_test::suite // Add an object to the ledger for account A1, then delete // A1 auto const a1 = A1.id(); - auto const sleA1 = ac.view().peek(keylet::account(a1)); + auto sleA1 = ac.view().peek(keylet::account(a1)); if (!sleA1) return false; auto const key = std::invoke(keyletfunc, a1); auto const newSLE = std::make_shared(key); ac.view().insert(newSLE); + // Clear the balance so the "account deletion left behind a + // non-zero balance" check doesn't trip earlier than the + // desired check. + sleA1->at(sfBalance) = beast::zero; ac.view().erase(sleA1); return true; }, XRPAmount{}, STTx{ttACCOUNT_DELETE, [](STObject& tx) {}}); - }; + } // NFT special case doInvariantCheck( {{"account deletion left behind a NFTokenPage object"}}, [&](Account const& A1, Account const&, ApplyContext& ac) { // remove an account from the view - auto const sle = ac.view().peek(keylet::account(A1.id())); + auto sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; + // Clear the balance so the "account deletion left behind a + // non-zero balance" check doesn't trip earlier than the desired + // check. + sle->at(sfBalance) = beast::zero; + sle->at(sfOwnerCount) = 0; ac.view().erase(sle); return true; }, @@ -265,13 +323,18 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { // Delete the AMM account without cleaning up the directory or // deleting the AMM object - auto const sle = ac.view().peek(keylet::account(ammAcctID)); + auto sle = ac.view().peek(keylet::account(ammAcctID)); if (!sle) return false; BEAST_EXPECT(sle->at(~sfAMMID)); BEAST_EXPECT(sle->at(~sfAMMID) == ammKey); + // Clear the balance so the "account deletion left behind a + // non-zero balance" check doesn't trip earlier than the desired + // check. + sle->at(sfBalance) = beast::zero; + sle->at(sfOwnerCount) = 0; ac.view().erase(sle); return true; @@ -294,7 +357,7 @@ class Invariants_test : public beast::unit_test::suite // Delete all the AMM's trust lines, remove the AMM from the AMM // account's directory (this deletes the directory), and delete // the AMM account. Do not delete the AMM object. - auto const sle = ac.view().peek(keylet::account(ammAcctID)); + auto sle = ac.view().peek(keylet::account(ammAcctID)); if (!sle) return false; @@ -334,6 +397,11 @@ class Invariants_test : public beast::unit_test::suite !ac.view().exists(ownerDirKeylet) || ac.view().emptyDirDelete(ownerDirKeylet)); + // Clear the balance so the "account deletion left behind a + // non-zero balance" check doesn't trip earlier than the desired + // check. + sle->at(sfBalance) = beast::zero; + sle->at(sfOwnerCount) = 0; ac.view().erase(sle); return true; @@ -1722,6 +1790,359 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tecINVARIANT_FAILED}); } + Keylet + createLoanBroker( + jtx::Account const& a, + jtx::Env& env, + jtx::PrettyAsset const& asset) + { + using namespace jtx; + + // Create vault + uint256 vaultID; + Vault vault{env}; + auto [tx, vKeylet] = vault.create({.owner = a, .asset = asset}); + env(tx); + BEAST_EXPECT(env.le(vKeylet)); + + vaultID = vKeylet.key; + + // Create Loan Broker + using namespace loanBroker; + + auto const loanBrokerKeylet = keylet::loanbroker(a.id(), env.seq(a)); + // Create a Loan Broker with all default values. + env(set(a, vaultID), fee(increment)); + + return loanBrokerKeylet; + }; + + void + testNoModifiedUnmodifiableFields() + { + testcase("no modified unmodifiable fields"); + using namespace jtx; + + // Initialize with a placeholder value because there's no default ctor + Keylet loanBrokerKeylet = keylet::amendments(); + Preclose createLoanBroker = + [&, this](Account const& a, Account const& b, Env& env) { + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + + loanBrokerKeylet = this->createLoanBroker(a, env, xrpAsset); + return BEAST_EXPECT(env.le(loanBrokerKeylet)); + }; + + { + auto const mods = + std::to_array>({ + [](SLE::pointer& sle) { sle->at(sfSequence) += 1; }, + [](SLE::pointer& sle) { sle->at(sfOwnerNode) += 1; }, + [](SLE::pointer& sle) { sle->at(sfVaultNode) += 1; }, + [](SLE::pointer& sle) { sle->at(sfVaultID) = uint256(1u); }, + [](SLE::pointer& sle) { + sle->at(sfAccount) = sle->at(sfOwner); + }, + [](SLE::pointer& sle) { + sle->at(sfOwner) = sle->at(sfAccount); + }, + [](SLE::pointer& sle) { + sle->at(sfManagementFeeRate) += 1; + }, + [](SLE::pointer& sle) { sle->at(sfCoverRateMinimum) += 1; }, + [](SLE::pointer& sle) { + sle->at(sfCoverRateLiquidation) += 1; + }, + [](SLE::pointer& sle) { sle->at(sfLedgerEntryType) += 1; }, + [](SLE::pointer& sle) { + sle->at(sfLedgerIndex) = sle->at(sfVaultID).value(); + }, + }); + + for (auto const& mod : mods) + { + doInvariantCheck( + {{"changed an unchangable field"}}, + [&](Account const& A1, Account const&, ApplyContext& ac) { + auto sle = ac.view().peek(loanBrokerKeylet); + if (!sle) + return false; + mod(sle); + ac.view().update(sle); + return true; + }, + XRPAmount{}, + STTx{ttACCOUNT_SET, [](STObject& tx) {}}, + {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, + createLoanBroker); + } + } + + // TODO: Loan Object + + { + auto const mods = + std::to_array>({ + [](SLE::pointer& sle) { sle->at(sfLedgerEntryType) += 1; }, + [](SLE::pointer& sle) { + sle->at(sfLedgerIndex) = uint256(1u); + }, + }); + + for (auto const& mod : mods) + { + doInvariantCheck( + {{"changed an unchangable field"}}, + [&](Account const& A1, Account const&, ApplyContext& ac) { + auto sle = ac.view().peek(keylet::account(A1.id())); + if (!sle) + return false; + mod(sle); + ac.view().update(sle); + return true; + }); + } + } + } + + void + testValidLoanBroker() + { + testcase << "valid loan broker"; + + using namespace jtx; + + enum class Asset { XRP, IOU, MPT }; + auto const assetTypes = + std::to_array({Asset::XRP, Asset::IOU, Asset::MPT}); + + for (auto const assetType : assetTypes) + { + // Initialize with a placeholder value because there's no default + // ctor + Keylet loanBrokerKeylet = keylet::amendments(); + Preclose createLoanBroker = [&, this]( + Account const& alice, + Account const& issuer, + Env& env) { + PrettyAsset const asset = [&]() { + switch (assetType) + { + case Asset::IOU: { + PrettyAsset const iouAsset = issuer["IOU"]; + env(trust(alice, iouAsset(1000))); + env(pay(issuer, alice, iouAsset(1000))); + env.close(); + return iouAsset; + } + + case Asset::MPT: { + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | + tfMPTCanLock}); + PrettyAsset const mptAsset = mptt.issuanceID(); + mptt.authorize({.account = alice}); + env(pay(issuer, alice, mptAsset(1000))); + env.close(); + return mptAsset; + } + + case Asset::XRP: + default: + return PrettyAsset{xrpIssue(), 1'000'000}; + } + }(); + loanBrokerKeylet = this->createLoanBroker(alice, env, asset); + return BEAST_EXPECT(env.le(loanBrokerKeylet)); + }; + + // Ensure the test scenarios are set up completely. The test cases + // will need to recompute any of these values it needs for itself + // rather than trying to return a bunch of items + auto setupTest = + [&, this](Account const& A1, Account const&, ApplyContext& ac) + -> std::optional> { + if (loanBrokerKeylet.type != ltLOAN_BROKER) + return {}; + auto sleBroker = ac.view().peek(loanBrokerKeylet); + if (!sleBroker) + return {}; + if (!BEAST_EXPECT(sleBroker->at(sfOwnerCount) == 0)) + return {}; + // Need to touch sleBroker so that it is included in the + // modified entries for the invariant to find + ac.view().update(sleBroker); + + // The pseudo-account holds the directory, so get it + auto const pseudoAccountID = sleBroker->at(sfAccount); + auto const pseudoAccountKeylet = + keylet::account(pseudoAccountID); + // Strictly speaking, we don't need to load the + // ACCOUNT_ROOT, but check anyway + auto slePseudo = ac.view().peek(pseudoAccountKeylet); + if (!BEAST_EXPECT(slePseudo)) + return {}; + // Make sure the directory doesn't already exist + auto const dirKeylet = keylet::ownerDir(pseudoAccountID); + auto sleDir = ac.view().peek(dirKeylet); + auto const describe = describeOwnerDir(pseudoAccountID); + if (!sleDir) + { + // Create the directory + BEAST_EXPECT( + ::ripple::directory::createRoot( + ac.view(), + dirKeylet, + loanBrokerKeylet.key, + describe) == 0); + + sleDir = ac.view().peek(dirKeylet); + } + + return std::make_pair(slePseudo, sleDir); + }; + + doInvariantCheck( + {{"Loan Broker with zero OwnerCount has multiple directory " + "pages"}}, + [&setupTest, this]( + Account const& A1, Account const& A2, ApplyContext& ac) { + auto test = setupTest(A1, A2, ac); + if (!test || !test->first || !test->second) + return false; + + auto slePseudo = test->first; + auto sleDir = test->second; + auto const describe = + describeOwnerDir(slePseudo->at(sfAccount)); + + BEAST_EXPECT( + ::ripple::directory::insertPage( + ac.view(), + 0, + sleDir, + 0, + sleDir, + slePseudo->key(), + keylet::page(sleDir->key(), 0), + describe) == 1); + + return true; + }, + XRPAmount{}, + STTx{ttLOAN_BROKER_SET, [](STObject& tx) {}}, + {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, + createLoanBroker); + + doInvariantCheck( + {{"Loan Broker with zero OwnerCount has multiple indexes in " + "the Directory root"}}, + [&setupTest]( + Account const& A1, Account const& A2, ApplyContext& ac) { + auto test = setupTest(A1, A2, ac); + if (!test || !test->first || !test->second) + return false; + + auto slePseudo = test->first; + auto sleDir = test->second; + auto indexes = sleDir->getFieldV256(sfIndexes); + + // Put some extra garbage into the directory + for (auto const& key : {slePseudo->key(), sleDir->key()}) + { + ::ripple::directory::insertKey( + ac.view(), sleDir, 0, false, indexes, key); + } + + return true; + }, + XRPAmount{}, + STTx{ttLOAN_BROKER_SET, [](STObject& tx) {}}, + {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, + createLoanBroker); + + doInvariantCheck( + {{"Loan Broker directory corrupt"}}, + [&setupTest]( + Account const& A1, Account const& A2, ApplyContext& ac) { + auto test = setupTest(A1, A2, ac); + if (!test || !test->first || !test->second) + return false; + + auto slePseudo = test->first; + auto sleDir = test->second; + auto const describe = + describeOwnerDir(slePseudo->at(sfAccount)); + // Empty vector will overwrite the existing entry for the + // holding, if any, avoiding the "has multiple indexes" + // failure. + STVector256 indexes; + + // Put one meaningless key into the directory + auto const key = + keylet::account(Account("random").id()).key; + ::ripple::directory::insertKey( + ac.view(), sleDir, 0, false, indexes, key); + + return true; + }, + XRPAmount{}, + STTx{ttLOAN_BROKER_SET, [](STObject& tx) {}}, + {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, + createLoanBroker); + + doInvariantCheck( + {{"Loan Broker with zero OwnerCount has an unexpected entry in " + "the directory"}}, + [&setupTest]( + Account const& A1, Account const& A2, ApplyContext& ac) { + auto test = setupTest(A1, A2, ac); + if (!test || !test->first || !test->second) + return false; + + auto slePseudo = test->first; + auto sleDir = test->second; + // Empty vector will overwrite the existing entry for the + // holding, if any, avoiding the "has multiple indexes" + // failure. + STVector256 indexes; + + ::ripple::directory::insertKey( + ac.view(), sleDir, 0, false, indexes, slePseudo->key()); + + return true; + }, + XRPAmount{}, + STTx{ttLOAN_BROKER_SET, [](STObject& tx) {}}, + {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, + createLoanBroker); + + doInvariantCheck( + {{"Loan Broker sequence number decreased"}}, + [&](Account const& A1, Account const& A2, ApplyContext& ac) { + if (loanBrokerKeylet.type != ltLOAN_BROKER) + return false; + auto sleBroker = ac.view().peek(loanBrokerKeylet); + if (!sleBroker) + return false; + if (!BEAST_EXPECT(sleBroker->at(sfLoanSequence) > 0)) + return false; + // Need to touch sleBroker so that it is included in the + // modified entries for the invariant to find + ac.view().update(sleBroker); + + sleBroker->at(sfLoanSequence) -= 1; + + return true; + }, + XRPAmount{}, + STTx{ttLOAN_BROKER_SET, [](STObject& tx) {}}, + {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, + createLoanBroker); + } + } + void testVault() { @@ -3485,8 +3906,10 @@ public: testValidNewAccountRoot(); testNFTokenPageInvariants(); testPermissionedDomainInvariants(); - testValidPseudoAccounts(); testPermissionedDEX(); + testNoModifiedUnmodifiableFields(); + testValidPseudoAccounts(); + testValidLoanBroker(); testVault(); } }; diff --git a/src/test/app/LoanBroker_test.cpp b/src/test/app/LoanBroker_test.cpp new file mode 100644 index 0000000000..597e2ea75b --- /dev/null +++ b/src/test/app/LoanBroker_test.cpp @@ -0,0 +1,1462 @@ +#include + +#include + +#include + +namespace ripple { +namespace test { + +class LoanBroker_test : public beast::unit_test::suite +{ + // Ensure that all the features needed for Lending Protocol are included, + // even if they are set to unsupported. + FeatureBitset const all{ + jtx::testable_amendments() | featureMPTokensV1 | + featureSingleAssetVault | featureLendingProtocol}; + + void + testDisabled() + { + testcase("Disabled"); + // Lending Protocol depends on Single Asset Vault (SAV). Test + // combinations of the two amendments. + // Single Asset Vault depends on MPTokensV1, but don't test every combo + // of that. + using namespace jtx; + auto failAll = [this](FeatureBitset features, bool goodVault = false) { + Env env(*this, features); + + Account const alice{"alice"}; + env.fund(XRP(10000), alice); + + // Try to create a vault + PrettyAsset const asset{xrpIssue(), 1'000'000}; + Vault vault{env}; + auto const [tx, keylet] = + vault.create({.owner = alice, .asset = asset}); + env(tx, ter(goodVault ? ter(tesSUCCESS) : ter(temDISABLED))); + env.close(); + BEAST_EXPECT(static_cast(env.le(keylet)) == goodVault); + + using namespace loanBroker; + // Can't create a loan broker regardless of whether the vault exists + env(set(alice, keylet.key), ter(temDISABLED)); + auto const brokerKeylet = + keylet::loanbroker(alice.id(), env.seq(alice)); + // Other LoanBroker transactions are disabled, too. + // 1. LoanBrokerCoverDeposit + env(coverDeposit(alice, brokerKeylet.key, asset(1000)), + ter(temDISABLED)); + // 2. LoanBrokerCoverWithdraw + env(coverWithdraw(alice, brokerKeylet.key, asset(1000)), + ter(temDISABLED)); + // 3. LoanBrokerCoverClawback + env(coverClawback(alice), ter(temDISABLED)); + env(coverClawback(alice), + loanBrokerID(brokerKeylet.key), + ter(temDISABLED)); + env(coverClawback(alice), amount(asset(0)), ter(temDISABLED)); + env(coverClawback(alice), + loanBrokerID(brokerKeylet.key), + amount(asset(1000)), + ter(temDISABLED)); + // 4. LoanBrokerDelete + env(del(alice, brokerKeylet.key), ter(temDISABLED)); + }; + failAll(all - featureMPTokensV1); + failAll(all - featureSingleAssetVault - featureLendingProtocol); + failAll(all - featureSingleAssetVault); + failAll(all - featureLendingProtocol, true); + } + + struct VaultInfo + { + jtx::PrettyAsset asset; + uint256 vaultID; + jtx::Account pseudoAccount; + VaultInfo( + jtx::PrettyAsset const& asset_, + uint256 const& vaultID_, + AccountID const& pseudo) + : asset(asset_), vaultID(vaultID_), pseudoAccount("vault", pseudo) + { + } + }; + + void + lifecycle( + char const* label, + jtx::Env& env, + jtx::Account const& issuer, + jtx::Account const& alice, + jtx::Account const& evan, + jtx::Account const& bystander, + VaultInfo const& vault, + VaultInfo const& badVault, + std::function modifyJTx, + std::function checkBroker, + std::function changeBroker, + std::function checkChangedBroker) + { + { + auto const& asset = vault.asset.raw(); + testcase << "Lifecycle: " + << (asset.native() ? "XRP " + : asset.holds() ? "IOU " + : asset.holds() ? "MPT " + : "Unknown ") + << label; + } + + using namespace jtx; + using namespace loanBroker; + + // Bogus assets to use in test cases + static PrettyAsset const badMptAsset = [&]() { + MPTTester badMptt{env, evan, mptInitNoFund}; + badMptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + env.close(); + return badMptt["BAD"]; + }(); + static PrettyAsset const badIouAsset = evan["BAD"]; + static Account const nonExistent{"NonExistent"}; + static PrettyAsset const ghostIouAsset = nonExistent["GST"]; + PrettyAsset const vaultPseudoIouAsset = vault.pseudoAccount["PSD"]; + + auto const badKeylet = keylet::loanbroker(alice.id(), env.seq(alice)); + env(set(alice, badVault.vaultID)); + env.close(); + auto const badBrokerPseudo = [&]() { + if (auto const le = env.le(badKeylet); BEAST_EXPECT(le)) + { + return Account{"Bad Broker pseudo-account", le->at(sfAccount)}; + } + // Just to make the build work + return vault.pseudoAccount; + }(); + PrettyAsset const badBrokerPseudoIouAsset = badBrokerPseudo["WAT"]; + + auto const keylet = keylet::loanbroker(alice.id(), env.seq(alice)); + { + // Start with default values + auto jtx = env.jt(set(alice, vault.vaultID)); + // Modify as desired + if (modifyJTx) + jtx = modifyJTx(jtx); + // Successfully create a Loan Broker + env(jtx); + } + + env.close(); + if (auto broker = env.le(keylet); BEAST_EXPECT(broker)) + { + // log << "Broker after create: " << to_string(broker->getJson()) + // << std::endl; + BEAST_EXPECT(broker->at(sfVaultID) == vault.vaultID); + BEAST_EXPECT(broker->at(sfAccount) != alice.id()); + BEAST_EXPECT(broker->at(sfOwner) == alice.id()); + BEAST_EXPECT(broker->at(sfFlags) == 0); + BEAST_EXPECT(broker->at(sfSequence) == env.seq(alice) - 1); + BEAST_EXPECT(broker->at(sfOwnerCount) == 0); + BEAST_EXPECT(broker->at(sfLoanSequence) == 1); + BEAST_EXPECT(broker->at(sfDebtTotal) == 0); + BEAST_EXPECT(broker->at(sfCoverAvailable) == 0); + if (checkBroker) + checkBroker(broker); + + // if (auto const vaultSLE = env.le(keylet::vault(vault.vaultID))) + //{ + // log << "Vault: " << to_string(vaultSLE->getJson()) << + // std::endl; + // } + // Load the pseudo-account + Account const pseudoAccount{ + "Broker pseudo-account", broker->at(sfAccount)}; + + auto const pseudoKeylet = keylet::account(pseudoAccount); + if (auto const pseudo = env.le(pseudoKeylet); BEAST_EXPECT(pseudo)) + { + // log << "Pseudo-account after create: " + // << to_string(pseudo->getJson()) << std::endl + // << std::endl; + BEAST_EXPECT( + pseudo->at(sfFlags) == + (lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth)); + BEAST_EXPECT(pseudo->at(sfSequence) == 0); + BEAST_EXPECT(pseudo->at(sfBalance) == beast::zero); + BEAST_EXPECT( + pseudo->at(sfOwnerCount) == + (vault.asset.raw().native() ? 0 : 1)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfAccountTxnID)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfRegularKey)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfEmailHash)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfWalletLocator)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfWalletSize)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfMessageKey)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfTransferRate)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfDomain)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfTickSize)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfTicketCount)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfNFTokenMinter)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfMintedNFTokens)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfBurnedNFTokens)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfFirstNFTokenSequence)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfAMMID)); + BEAST_EXPECT(!pseudo->isFieldPresent(sfVaultID)); + BEAST_EXPECT(pseudo->at(sfLoanBrokerID) == keylet.key); + } + + { + // Get the AccountInfo RPC result for the broker pseudo-account + std::string const pseudoStr = to_string(pseudoAccount.id()); + auto const accountInfo = env.rpc("account_info", pseudoStr); + if (BEAST_EXPECT(accountInfo.isObject())) + { + auto const& accountData = + accountInfo[jss::result][jss::account_data]; + if (BEAST_EXPECT(accountData.isObject())) + { + BEAST_EXPECT(accountData[jss::Account] == pseudoStr); + BEAST_EXPECT( + accountData[sfLoanBrokerID] == + to_string(keylet.key)); + } + auto const& pseudoInfo = + accountInfo[jss::result][jss::pseudo_account]; + if (BEAST_EXPECT(pseudoInfo.isObject())) + { + BEAST_EXPECT(pseudoInfo[jss::type] == "LoanBroker"); + } + } + } + + auto verifyCoverAmount = + [&env, &vault, &pseudoAccount, &broker, &keylet, this](auto n) { + using namespace jtx; + + if (BEAST_EXPECT(broker = env.le(keylet))) + { + auto const amount = vault.asset(n); + BEAST_EXPECT( + broker->at(sfCoverAvailable) == amount.number()); + env.require(balance(pseudoAccount, amount)); + } + }; + + // Test Cover funding before allowing alterations + env(coverDeposit(alice, uint256(0), vault.asset(10)), + ter(temINVALID)); + env(coverDeposit(evan, keylet.key, vault.asset(10)), + ter(tecNO_PERMISSION)); + env(coverDeposit(evan, keylet.key, vault.asset(0)), + ter(temBAD_AMOUNT)); + env(coverDeposit(evan, keylet.key, vault.asset(-10)), + ter(temBAD_AMOUNT)); + env(coverDeposit(alice, vault.vaultID, vault.asset(10)), + ter(tecNO_ENTRY)); + + verifyCoverAmount(0); + + // Test cover clawback failure cases BEFORE depositing any cover + // Need one of brokerID or amount + env(coverClawback(alice), ter(temINVALID)); + env(coverClawback(alice), + loanBrokerID(uint256(0)), + ter(temINVALID)); + env(coverClawback(alice), amount(XRP(1000)), ter(temBAD_AMOUNT)); + env(coverClawback(alice), + amount(vault.asset(-10)), + ter(temBAD_AMOUNT)); + // Clawbacks with an MPT need to specify the broker ID + env(coverClawback(alice), amount(badMptAsset(1)), ter(temINVALID)); + env(coverClawback(evan), + loanBrokerID(vault.vaultID), + ter(tecNO_ENTRY)); + // Only the issuer can clawback + env(coverClawback(alice), + loanBrokerID(keylet.key), + ter(tecNO_PERMISSION)); + if (vault.asset.raw().native()) + { + // Can not clawback XRP under any circumstances + env(coverClawback(issuer), + loanBrokerID(keylet.key), + ter(tecNO_PERMISSION)); + } + else + { + if (vault.asset.raw().holds()) + { + // Clawbacks without a loanBrokerID need to specify an IOU + // with the broker's pseudo-account as the issuer + env(coverClawback(alice), + amount(ghostIouAsset(1)), + ter(tecNO_ENTRY)); + env(coverClawback(alice), + amount(badIouAsset(1)), + ter(tecOBJECT_NOT_FOUND)); + // Pseudo-account is not for a broker + env(coverClawback(alice), + amount(vaultPseudoIouAsset(1)), + ter(tecOBJECT_NOT_FOUND)); + // If we specify a pseudo-account as the IOU amount, it + // needs to match the loan broker + env(coverClawback(issuer), + loanBrokerID(keylet.key), + amount(badBrokerPseudoIouAsset(10)), + ter(tecWRONG_ASSET)); + PrettyAsset const brokerWrongCurrencyAsset = + pseudoAccount["WAT"]; + env(coverClawback(issuer), + loanBrokerID(keylet.key), + amount(brokerWrongCurrencyAsset(10)), + ter(tecWRONG_ASSET)); + } + else + { + // Clawbacks with an MPT need to specify the broker ID, even + // if the asset is valid + BEAST_EXPECT(vault.asset.raw().holds()); + env(coverClawback(alice), + amount(vault.asset(10)), + ter(temINVALID)); + } + // Since no cover has been deposited, there's nothing to claw + // back + env(coverClawback(issuer), + loanBrokerID(keylet.key), + amount(vault.asset(10)), + ter(tecINSUFFICIENT_FUNDS)); + } + env.close(); + + // Fund the cover deposit + env(coverDeposit(alice, keylet.key, vault.asset(10))); + env.close(); + verifyCoverAmount(10); + + // Test withdrawal failure cases + env(coverWithdraw(alice, uint256(0), vault.asset(10)), + ter(temINVALID)); + env(coverWithdraw(evan, keylet.key, vault.asset(10)), + ter(tecNO_PERMISSION)); + env(coverWithdraw(evan, keylet.key, vault.asset(0)), + ter(temBAD_AMOUNT)); + env(coverWithdraw(evan, keylet.key, vault.asset(-10)), + ter(temBAD_AMOUNT)); + env(coverWithdraw(alice, vault.vaultID, vault.asset(10)), + ter(tecNO_ENTRY)); + env(coverWithdraw(alice, keylet.key, vault.asset(900)), + ter(tecINSUFFICIENT_FUNDS)); + + // Skip this test for XRP, because that can always be sent + if (!vault.asset.raw().native()) + { + TER const expected = vault.asset.raw().holds() + ? tecNO_AUTH + : tecNO_LINE; + env(coverWithdraw(alice, keylet.key, vault.asset(1)), + destination(bystander), + ter(expected)); + } + + // Can not withdraw to the zero address + env(coverWithdraw(alice, keylet.key, vault.asset(1)), + destination(AccountID{}), + ter(temMALFORMED)); + + // Withdraw some of the cover amount + env(coverWithdraw(alice, keylet.key, vault.asset(7))); + env.close(); + verifyCoverAmount(3); + + // Add some more cover + env(coverDeposit(alice, keylet.key, vault.asset(5))); + env.close(); + verifyCoverAmount(8); + + // Withdraw some more. Send it to Evan. Very generous, considering + // how much trouble he's been. + env(coverWithdraw(alice, keylet.key, vault.asset(1)), + destination(evan)); + env.close(); + verifyCoverAmount(7); + + // Withdraw some more. Send it to Evan. Very generous, considering + // how much trouble he's been. + env(coverWithdraw(alice, keylet.key, vault.asset(1)), + destination(evan), + dtag(3)); + env.close(); + verifyCoverAmount(6); + + if (!vault.asset.raw().native()) + { + // Issuer claws back some of the cover + env(coverClawback(issuer), + loanBrokerID(keylet.key), + amount(vault.asset(2))); + env.close(); + verifyCoverAmount(4); + + // Deposit some back + env(coverDeposit(alice, keylet.key, vault.asset(5))); + env.close(); + verifyCoverAmount(9); + + // Issuer claws it all back in various different ways + for (auto const& tx : { + // defer autofills until submission time + env.json( + coverClawback(issuer), + loanBrokerID(keylet.key), + fee(none), + seq(none), + sig(none)), + env.json( + coverClawback(issuer), + loanBrokerID(keylet.key), + amount(vault.asset(0)), + fee(none), + seq(none), + sig(none)), + env.json( + coverClawback(issuer), + loanBrokerID(keylet.key), + amount(vault.asset(6)), + fee(none), + seq(none), + sig(none)), + // amount will be truncated to what's available + env.json( + coverClawback(issuer), + loanBrokerID(keylet.key), + amount(vault.asset(100)), + fee(none), + seq(none), + sig(none)), + }) + { + // Issuer claws it all back + env(tx); + env.close(); + verifyCoverAmount(0); + + // Deposit some back + env(coverDeposit(alice, keylet.key, vault.asset(6))); + env.close(); + verifyCoverAmount(6); + } + } + + // no-op + env(set(alice, vault.vaultID), loanBrokerID(keylet.key)); + env.close(); + + // Make modifications to the broker + if (changeBroker) + changeBroker(broker); + + env.close(); + + // Check the results of modifications + if (BEAST_EXPECT(broker = env.le(keylet)) && checkChangedBroker) + checkChangedBroker(broker); + + // Verify that fields get removed when set to default values + // Debt maximum: explicit 0 + // Data: explicit empty + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + debtMaximum(Number(0)), + data("")); + env.close(); + + // Check the updated fields + if (BEAST_EXPECT(broker = env.le(keylet))) + { + BEAST_EXPECT(!broker->isFieldPresent(sfDebtMaximum)); + BEAST_EXPECT(!broker->isFieldPresent(sfData)); + } + + ///////////////////////////////////// + // try to delete the wrong broker object + env(del(alice, vault.vaultID), ter(tecNO_ENTRY)); + // evan tries to delete the broker + env(del(evan, keylet.key), ter(tecNO_PERMISSION)); + + // Get the "bad" broker out of the way + env(del(alice, badKeylet.key)); + env.close(); + + // Note alice's balance of the asset and the broker account's cover + // funds + auto const aliceBalance = env.balance(alice, vault.asset); + auto const coverFunds = env.balance(pseudoAccount, vault.asset); + BEAST_EXPECT(coverFunds.number() == broker->at(sfCoverAvailable)); + BEAST_EXPECT(coverFunds != beast::zero); + verifyCoverAmount(6); + + // delete the broker + // log << "Broker before delete: " << to_string(broker->getJson()) + // << std::endl; + // if (auto const pseudo = env.le(pseudoKeylet); + // BEAST_EXPECT(pseudo)) + //{ + // log << "Pseudo-account before delete: " + // << to_string(pseudo->getJson()) << std::endl + // << std::endl; + //} + + env(del(alice, keylet.key)); + env.close(); + { + broker = env.le(keylet); + BEAST_EXPECT(!broker); + auto pseudo = env.le(pseudoKeylet); + BEAST_EXPECT(!pseudo); + } + auto const expectedBalance = aliceBalance + coverFunds - + (aliceBalance.value().native() + ? STAmount(env.current()->fees().base.value()) + : vault.asset(0)); + env.require(balance(alice, expectedBalance)); + env.require(balance(pseudoAccount, vault.asset(none))); + } + } + + void + testLifecycle() + { + testcase("Lifecycle"); + using namespace jtx; + + // Create 3 loan brokers: one for XRP, one for an IOU, and one for an + // MPT. That'll require three corresponding SAVs. + Env env(*this, all); + + Account issuer{"issuer"}; + // For simplicity, alice will be the sole actor for the vault & brokers. + Account alice{"alice"}; + // Evan will attempt to be naughty + Account evan{"evan"}; + // Bystander doesn't have anything to do with the SAV or Broker, or any + // of the relevant tokens + Account bystander{"bystander"}; + Vault vault{env}; + + // Fund the accounts and trust lines with the same amount so that tests + // can use the same values regardless of the asset. + env.fund(XRP(100'000), issuer, noripple(alice, evan, bystander)); + env.close(); + + env(fset(issuer, asfAllowTrustLineClawback)); + env.close(); + + // Create assets + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + PrettyAsset const iouAsset = issuer["IOU"]; + env(trust(alice, iouAsset(1'000'000))); + env(trust(evan, iouAsset(1'000'000))); + env.close(); + env(pay(issuer, evan, iouAsset(100'000))); + env(pay(issuer, alice, iouAsset(100'000))); + env.close(); + + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + env.close(); + PrettyAsset const mptAsset = mptt["MPT"]; + mptt.authorize({.account = alice}); + mptt.authorize({.account = evan}); + env.close(); + env(pay(issuer, alice, mptAsset(100'000))); + env(pay(issuer, evan, mptAsset(100'000))); + env.close(); + + std::array const assets{xrpAsset, iouAsset, mptAsset}; + + // Create vaults + std::vector vaults; + for (auto const& asset : assets) + { + auto [tx, keylet] = vault.create({.owner = alice, .asset = asset}); + env(tx); + env.close(); + if (auto const le = env.le(keylet); BEAST_EXPECT(env.le(keylet))) + { + vaults.emplace_back(asset, keylet.key, le->at(sfAccount)); + } + + env(vault.deposit( + {.depositor = alice, .id = keylet.key, .amount = asset(50)})); + env.close(); + } + VaultInfo const badVault = [&]() -> VaultInfo { + auto [tx, keylet] = + vault.create({.owner = alice, .asset = iouAsset}); + env(tx); + env.close(); + if (auto const le = env.le(keylet); BEAST_EXPECT(env.le(keylet))) + { + return {iouAsset, keylet.key, le->at(sfAccount)}; + } + // This should never happen + return {iouAsset, keylet.key, evan.id()}; + }(); + + auto const aliceOriginalCount = env.ownerCount(alice); + + // Create and update Loan Brokers + for (auto const& vault : vaults) + { + { + // Get the AccountInfo RPC result for the vault pseudo-account + std::string const pseudoStr = + to_string(vault.pseudoAccount.id()); + auto const accountInfo = env.rpc("account_info", pseudoStr); + if (BEAST_EXPECT(accountInfo.isObject())) + { + auto const& accountData = + accountInfo[jss::result][jss::account_data]; + if (BEAST_EXPECT(accountData.isObject())) + { + BEAST_EXPECT(accountData[jss::Account] == pseudoStr); + BEAST_EXPECT( + accountData[sfVaultID] == to_string(vault.vaultID)); + } + auto const& pseudoInfo = + accountInfo[jss::result][jss::pseudo_account]; + if (BEAST_EXPECT(pseudoInfo.isObject())) + { + BEAST_EXPECT(pseudoInfo[jss::type] == "Vault"); + } + } + } + + using namespace loanBroker; + using namespace ripple::Lending; + + TenthBips32 const tenthBipsZero{0}; + + auto badKeylet = keylet::vault(alice.id(), env.seq(alice)); + // Try some failure cases + // not the vault owner + env(set(evan, vault.vaultID), ter(tecNO_PERMISSION)); + // not a vault + env(set(alice, badKeylet.key), ter(tecNO_ENTRY)); + // flags are checked first + env(set(evan, vault.vaultID, ~tfUniversal), ter(temINVALID_FLAG)); + // field length validation + // sfData: good length, bad account + env(set(evan, vault.vaultID), + data(std::string(maxDataPayloadLength, 'X')), + ter(tecNO_PERMISSION)); + // sfData: too long + env(set(evan, vault.vaultID), + data(std::string(maxDataPayloadLength + 1, 'Y')), + ter(temINVALID)); + // sfManagementFeeRate: good value, bad account + env(set(evan, vault.vaultID), + managementFeeRate(maxManagementFeeRate), + ter(tecNO_PERMISSION)); + // sfManagementFeeRate: too big + env(set(evan, vault.vaultID), + managementFeeRate(maxManagementFeeRate + TenthBips16(10)), + ter(temINVALID)); + // sfCoverRateMinimum and sfCoverRateLiquidation are linked + // Cover: good value, bad account + env(set(evan, vault.vaultID), + coverRateMinimum(maxCoverRate), + coverRateLiquidation(maxCoverRate), + ter(tecNO_PERMISSION)); + // CoverMinimum: too big + env(set(evan, vault.vaultID), + coverRateMinimum(maxCoverRate + 1), + coverRateLiquidation(maxCoverRate + 1), + ter(temINVALID)); + // CoverLiquidation: too big + env(set(evan, vault.vaultID), + coverRateMinimum(maxCoverRate / 2), + coverRateLiquidation(maxCoverRate + 1), + ter(temINVALID)); + // Cover: zero min, non-zero liquidation - implicit and + // explicit zero values. + env(set(evan, vault.vaultID), + coverRateLiquidation(maxCoverRate), + ter(temINVALID)); + env(set(evan, vault.vaultID), + coverRateMinimum(tenthBipsZero), + coverRateLiquidation(maxCoverRate), + ter(temINVALID)); + // Cover: non-zero min, zero liquidation - implicit and + // explicit zero values. + env(set(evan, vault.vaultID), + coverRateMinimum(maxCoverRate), + ter(temINVALID)); + env(set(evan, vault.vaultID), + coverRateMinimum(maxCoverRate), + coverRateLiquidation(tenthBipsZero), + ter(temINVALID)); + // sfDebtMaximum: good value, bad account + env(set(evan, vault.vaultID), + debtMaximum(Number(0)), + ter(tecNO_PERMISSION)); + // sfDebtMaximum: overflow + env(set(evan, vault.vaultID), + debtMaximum(Number(1, 100)), + ter(temINVALID)); + // sfDebtMaximum: negative + env(set(evan, vault.vaultID), + debtMaximum(Number(-1)), + ter(temINVALID)); + + std::string testData; + lifecycle( + "default fields", + env, + issuer, + alice, + evan, + bystander, + vault, + badVault, + // No modifications + {}, + [&](SLE::const_ref broker) { + // Extra checks + BEAST_EXPECT(!broker->isFieldPresent(sfManagementFeeRate)); + BEAST_EXPECT(!broker->isFieldPresent(sfCoverRateMinimum)); + BEAST_EXPECT( + !broker->isFieldPresent(sfCoverRateLiquidation)); + BEAST_EXPECT(!broker->isFieldPresent(sfData)); + BEAST_EXPECT(!broker->isFieldPresent(sfDebtMaximum)); + BEAST_EXPECT(broker->at(sfDebtMaximum) == 0); + BEAST_EXPECT(broker->at(sfCoverRateMinimum) == 0); + BEAST_EXPECT(broker->at(sfCoverRateLiquidation) == 0); + + BEAST_EXPECT( + env.ownerCount(alice) == aliceOriginalCount + 4); + }, + [&](SLE::const_ref broker) { + // Modifications + + // Update the fields + auto const nextKeylet = + keylet::loanbroker(alice.id(), env.seq(alice)); + + // fields that can't be changed + // LoanBrokerID + env(set(alice, vault.vaultID), + loanBrokerID(nextKeylet.key), + ter(tecNO_ENTRY)); + // VaultID + env(set(alice, nextKeylet.key), + loanBrokerID(broker->key()), + ter(tecNO_PERMISSION)); + // Owner + env(set(evan, vault.vaultID), + loanBrokerID(broker->key()), + ter(tecNO_PERMISSION)); + // ManagementFeeRate + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + managementFeeRate(maxManagementFeeRate), + ter(temINVALID)); + // CoverRateMinimum + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + coverRateMinimum(maxManagementFeeRate), + ter(temINVALID)); + // CoverRateLiquidation + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + coverRateLiquidation(maxManagementFeeRate), + ter(temINVALID)); + + // fields that can be changed + testData = "Test Data 1234"; + // Bad data: too long + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + data(std::string(maxDataPayloadLength + 1, 'W')), + ter(temINVALID)); + + // Bad debt maximum + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + debtMaximum(Number(-175, -1)), + ter(temINVALID)); + // Data & Debt maximum + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + data(testData), + debtMaximum(Number(175, -1))); + }, + [&](SLE::const_ref broker) { + // Check the updated fields + BEAST_EXPECT(checkVL(broker->at(sfData), testData)); + BEAST_EXPECT(broker->at(sfDebtMaximum) == Number(175, -1)); + }); + + lifecycle( + "non-default fields", + env, + issuer, + alice, + evan, + bystander, + vault, + badVault, + [&](jtx::JTx const& jv) { + testData = "spam spam spam spam"; + // Finally, create another Loan Broker with none of the + // values at default + return env.jt( + jv, + data(testData), + managementFeeRate(TenthBips16(123)), + debtMaximum(Number(9)), + coverRateMinimum(TenthBips32(100)), + coverRateLiquidation(TenthBips32(200))); + }, + [&](SLE::const_ref broker) { + // Extra checks + BEAST_EXPECT(broker->at(sfManagementFeeRate) == 123); + BEAST_EXPECT(broker->at(sfCoverRateMinimum) == 100); + BEAST_EXPECT(broker->at(sfCoverRateLiquidation) == 200); + BEAST_EXPECT(broker->at(sfDebtMaximum) == Number(9)); + BEAST_EXPECT(checkVL(broker->at(sfData), testData)); + }, + [&](SLE::const_ref broker) { + // Reset Data & Debt maximum to default values + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + data(""), + debtMaximum(Number(0))); + }, + [&](SLE::const_ref broker) { + // Check the updated fields + BEAST_EXPECT(!broker->isFieldPresent(sfData)); + BEAST_EXPECT(!broker->isFieldPresent(sfDebtMaximum)); + }); + } + + BEAST_EXPECT(env.ownerCount(alice) == aliceOriginalCount); + } + + enum LoanBrokerTest { + CoverClawback, + CoverDeposit, + CoverWithdraw, + Delete, + Set + }; + + void + testLoanBroker( + std::function getAsset, + LoanBrokerTest brokerTest) + { + using namespace jtx; + using namespace loanBroker; + Account const issuer{"issuer"}; + Account const alice{"alice"}; + Env env(*this); + Vault vault{env}; + + env.fund(XRP(100'000), issuer, alice); + env.close(); + + PrettyAsset const asset = [&]() { + if (getAsset) + return getAsset(env, issuer, alice); + env(trust(alice, issuer["IOU"](1'000'000)), THISLINE); + env.close(); + return PrettyAsset(issuer["IOU"]); + }(); + + env(pay(issuer, alice, asset(100'000)), THISLINE); + env.close(); + + auto [tx, vaultKeylet] = vault.create({.owner = alice, .asset = asset}); + env(tx, THISLINE); + env.close(); + auto const le = env.le(vaultKeylet); + VaultInfo vaultInfo = [&]() { + if (BEAST_EXPECT(le)) + return VaultInfo{asset, vaultKeylet.key, le->at(sfAccount)}; + return VaultInfo{asset, {}, {}}; + }(); + if (vaultInfo.vaultID == uint256{}) + return; + + env(vault.deposit( + {.depositor = alice, + .id = vaultKeylet.key, + .amount = asset(50)}), + THISLINE); + env.close(); + + auto const brokerKeylet = + keylet::loanbroker(alice.id(), env.seq(alice)); + env(set(alice, vaultInfo.vaultID), THISLINE); + env.close(); + + auto broker = env.le(brokerKeylet); + if (!BEAST_EXPECT(broker)) + return; + + auto testZeroBrokerID = [&](auto&& getTxJv) { + auto jv = getTxJv(); + // empty broker ID + jv[sfLoanBrokerID] = ""; + env(jv, ter(temINVALID), THISLINE); + // zero broker ID + jv[sfLoanBrokerID] = to_string(uint256{}); + // needs a flag to distinguish the parsed STTx from the prior + // test + env(jv, txflags(tfFullyCanonicalSig), ter(temINVALID), THISLINE); + }; + auto testZeroVaultID = [&](auto&& getTxJv) { + auto jv = getTxJv(); + // empty broker ID + jv[sfVaultID] = ""; + env(jv, ter(temINVALID), THISLINE); + // zero broker ID + jv[sfVaultID] = to_string(uint256{}); + // needs a flag to distinguish the parsed STTx from the prior + // test + env(jv, txflags(tfFullyCanonicalSig), ter(temINVALID), THISLINE); + }; + + if (brokerTest == CoverDeposit) + { + // preflight: temINVALID (empty/zero broker id) + testZeroBrokerID([&]() { + return coverDeposit(alice, brokerKeylet.key, asset(10)); + }); + + // preclaim: tecWRONG_ASSET + env(coverDeposit(alice, brokerKeylet.key, issuer["BAD"](10)), + ter(tecWRONG_ASSET), + THISLINE); + + // preclaim: tecINSUFFICIENT_FUNDS + env(pay(alice, issuer, asset(100'000 - 50)), THISLINE); + env.close(); + env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), + ter(tecINSUFFICIENT_FUNDS)); + + // preclaim: tecFROZEN + env(fset(issuer, asfGlobalFreeze), THISLINE); + env.close(); + env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), + ter(tecFROZEN), + THISLINE); + } + else + // Fund the cover deposit + env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), + THISLINE); + env.close(); + + if (brokerTest == CoverWithdraw) + { + // preflight: temINVALID (empty/zero broker id) + testZeroBrokerID([&]() { + return coverWithdraw(alice, brokerKeylet.key, asset(10)); + }); + + // preclaim: tecWRONG_ASSSET + env(coverWithdraw(alice, brokerKeylet.key, issuer["BAD"](10)), + ter(tecWRONG_ASSET), + THISLINE); + + // preclaim: tecNO_DST + Account const bogus{"bogus"}; + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), + destination(bogus), + ter(tecNO_DST), + THISLINE); + + // preclaim: tecDST_TAG_NEEDED + Account const dest{"dest"}; + env.fund(XRP(1'000), dest); + env(fset(dest, asfRequireDest), THISLINE); + env.close(); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), + destination(dest), + ter(tecDST_TAG_NEEDED), + THISLINE); + + // preclaim: tecNO_PERMISSION + env(fclear(dest, asfRequireDest), THISLINE); + env(fset(dest, asfDepositAuth), THISLINE); + env.close(); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), + destination(dest), + ter(tecNO_PERMISSION), + THISLINE); + + // preclaim: tecFROZEN + env(trust(dest, asset(1'000)), THISLINE); + env(fclear(dest, asfDepositAuth), THISLINE); + env(fset(issuer, asfGlobalFreeze), THISLINE); + env.close(); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), + destination(dest), + ter(tecFROZEN), + THISLINE); + + // preclaim:: tecFROZEN (deep frozen) + env(fclear(issuer, asfGlobalFreeze), THISLINE); + env(trust( + issuer, asset(1'000), dest, tfSetFreeze | tfSetDeepFreeze), + THISLINE); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), + destination(dest), + ter(tecFROZEN), + THISLINE); + } + + if (brokerTest == CoverClawback) + { + // preflight: temINVALID (empty/zero broker id) + testZeroBrokerID([&]() { + return env.json( + coverClawback(alice), + loanBrokerID(brokerKeylet.key), + amount(vaultInfo.asset(2))); + }); + + if (asset.holds()) + { + // preclaim: AllowTrustLineClaback is not set + env(coverClawback(issuer), + loanBrokerID(brokerKeylet.key), + amount(vaultInfo.asset(2)), + ter(tecNO_PERMISSION), + THISLINE); + + // preclaim: NoFreeze is set + env(fset(issuer, asfAllowTrustLineClawback | asfNoFreeze), + THISLINE); + env.close(); + env(coverClawback(issuer), + loanBrokerID(brokerKeylet.key), + amount(vaultInfo.asset(2)), + ter(tecNO_PERMISSION), + THISLINE); + } + else + { + // preclaim: MPTCanClawback is not set or MPTCanLock is not set + env(coverClawback(issuer), + loanBrokerID(brokerKeylet.key), + amount(vaultInfo.asset(2)), + ter(tecNO_PERMISSION), + THISLINE); + } + env.close(); + } + + if (brokerTest == Delete) + { + Account const borrower{"borrower"}; + env.fund(XRP(1'000), borrower); + env(loan::set(borrower, brokerKeylet.key, asset(50).value()), + sig(sfCounterpartySignature, alice), + fee(env.current()->fees().base * 2), + THISLINE); + + // preflight: temINVALID (empty/zero broker id) + testZeroBrokerID([&]() { return del(alice, brokerKeylet.key); }); + + // preclaim: tecHAS_OBLIGATIONS + env(del(alice, brokerKeylet.key), + ter(tecHAS_OBLIGATIONS), + THISLINE); + + // Repay and delete the loan + auto const loanKeylet = keylet::loan(brokerKeylet.key, 1); + env(loan::pay(borrower, loanKeylet.key, asset(50).value()), + THISLINE); + env(loan::del(alice, loanKeylet.key), THISLINE); + + env(trust(issuer, asset(0), alice, tfSetFreeze | tfSetDeepFreeze), + THISLINE); + // preclaim: tecFROZEN (deep frozen) + env(del(alice, brokerKeylet.key), ter(tecFROZEN), THISLINE); + env(trust( + issuer, asset(0), alice, tfClearFreeze | tfClearDeepFreeze), + THISLINE); + + // successful delete the loan broker object + env(del(alice, brokerKeylet.key), ter(tesSUCCESS), THISLINE); + } + else + env(del(alice, brokerKeylet.key), THISLINE); + + if (brokerTest == Set) + { + // preflight: temINVALID (empty/zero broker id) + testZeroBrokerID([&]() { + return env.json( + set(alice, vaultInfo.vaultID), + loanBrokerID(brokerKeylet.key)); + }); + // preflight: temINVALID (empty/zero vault id) + testZeroVaultID([&]() { + return env.json( + set(alice, vaultInfo.vaultID), + loanBrokerID(brokerKeylet.key)); + }); + + if (asset.holds()) + { + env(fclear(issuer, asfDefaultRipple), THISLINE); + env.close(); + // preclaim: DefaultRipple is not set + env(set(alice, vaultInfo.vaultID), ter(terNO_RIPPLE), THISLINE); + + env(fset(issuer, asfDefaultRipple), THISLINE); + env.close(); + } + + auto const amt = env.balance(alice) - + env.current()->fees().accountReserve(env.ownerCount(alice)); + env(pay(alice, issuer, amt), THISLINE); + + // preclaim:: tecINSUFFICIENT_RESERVE + env(set(alice, vaultInfo.vaultID), + ter(tecINSUFFICIENT_RESERVE), + THISLINE); + } + } + + void + testInvalidLoanBrokerCoverClawback() + { + testcase("Invalid LoanBrokerCoverClawback"); + using namespace jtx; + using namespace loanBroker; + + // preflight + { + Account const alice{"alice"}; + Account const issuer{"issuer"}; + auto const USD = alice["USD"]; + Env env(*this); + env.fund(XRP(100'000), alice); + env.close(); + + auto jtx = env.jt(coverClawback(alice), amount(USD(100))); + + // holder == account + env(jtx, ter(temINVALID), THISLINE); + + // holder == beast::zero + STAmount bad(Issue{USD.currency, beast::zero}, 100); + jtx.jv[sfAmount] = bad.getJson(); + jtx.stx = env.ust(jtx); + Serializer s; + jtx.stx->add(s); + auto const jrr = env.rpc("submit", strHex(s.slice()))[jss::result]; + // fails in doSubmit() on STTx construction + BEAST_EXPECT(jrr[jss::error] == "invalidTransaction"); + BEAST_EXPECT(jrr[jss::error_exception] == "invalid native account"); + } + + // preclaim + + // Issue: + // AllowTrustLineClawback is not set or NoFreeze is set + testLoanBroker({}, CoverClawback); + + // MPTIssue: + // MPTCanClawback is not set + testLoanBroker( + [&](Env& env, Account const& issuer, Account const& alice) -> MPT { + MPTTester mpt( + {.env = env, .issuer = issuer, .holders = {alice}}); + return mpt; + }, + CoverClawback); + } + + void + testInvalidLoanBrokerCoverDeposit() + { + testcase("Invalid LoanBrokerCoverDeposit"); + using namespace jtx; + + // preclaim: + // tecWRONG_ASSET, tecINSUFFICIENT_FUNDS, frozen asset + testLoanBroker({}, CoverDeposit); + } + + void + testInvalidLoanBrokerCoverWithdraw() + { + testcase("Invalid LoanBrokerCoverWithdraw"); + using namespace jtx; + + /* + preflight: illegal net + isLegalNet() check is probably redundant. STAmount parsing + should throw an exception on deserialize + + preclaim: tecWRONG_ASSET, tecNO_DST, tecDST_TAG_NEEDED, + tecNO_PERMISSION, checkFrozen failure, checkDeepFrozenFailure, + second+third tecINSUFFICIENT_FUNDS (can this happen)? + doApply: tecPATH_DRY (can it happen, funds already checked?) + */ + testLoanBroker({}, CoverWithdraw); + } + + void + testInvalidLoanBrokerDelete() + { + using namespace jtx; + testcase("Invalid LoanBrokerDelete"); + /* + preclaim: tecHAS_OBLIGATIONS + doApply: + accountSend failure, removeEmptyHolding failure, + all tecHAS_OBLIGATIONS (can any of these happen?) + */ + testLoanBroker({}, Delete); + } + + void + testInvalidLoanBrokerSet() + { + using namespace jtx; + testcase("Invalid LoanBrokerSet"); + + /*preclaim: canAddHolding failure (can it happen with MPT? + can't create Vault if CanTransfer is not enabled.) + doApply: + first+second dirLink failure, createPseudoAccount failure, + addEmptyHolding failure + can any of these happen? + */ + testLoanBroker({}, Set); + } + + void + testLoanBrokerCoverDepositNullVault() + { + // This test is lifted directly from + // https://bugs.immunefi.com/dashboard/submission/57808 + using namespace jtx; + Env env(*this); + + Account const alice{"alice"}; + env.fund(XRP(10000), alice); + env.close(); + + // Create a Vault owned by alice with an XRP asset + PrettyAsset const asset{xrpIssue(), 1}; + Vault vault{env}; + auto const [createTx, vaultKeylet] = + vault.create({.owner = alice, .asset = asset}); + env(createTx); + env.close(); + + // Predict LoanBroker key using alice's current sequence BEFORE submit + auto const brokerKeylet = + keylet::loanbroker(alice.id(), env.seq(alice)); + + // Create LoanBroker pointing to the vault + env(loanBroker::set(alice, vaultKeylet.key)); + env.close(); + + // Build the CoverDeposit STTx directly + STTx tx{ttLOAN_BROKER_COVER_DEPOSIT, [](STObject&) {}}; + tx.setAccountID(sfAccount, alice.id()); + tx.setFieldH256(sfLoanBrokerID, brokerKeylet.key); + tx.setFieldAmount(sfAmount, asset(1)); + + // Create a writable view cloned from the current ledger and remove the + // vault SLE + OpenView ov{*env.current()}; + test::StreamSink sink{beast::severities::kWarning}; + beast::Journal jlog{sink}; + ApplyContext ac{ + env.app(), + ov, + tx, + tesSUCCESS, + env.current()->fees().base, + tapNONE, + jlog}; + + if (auto sleBroker = + ac.view().peek(keylet::loanbroker(brokerKeylet.key))) + { + auto const vaultID = (*sleBroker)[sfVaultID]; + if (auto sleVault = ac.view().peek(keylet::vault(vaultID))) + { + ac.view().erase(sleVault); + } + } + + // Invoke preclaim against the mutated (ApplyView) view; triggers + // nullptr deref + PreclaimContext pctx{ + env.app(), ac.view(), tesSUCCESS, tx, tapNONE, jlog}; + (void)LoanBrokerCoverDeposit::preclaim(pctx); + } + + void + testRequireAuth() + { + testcase("Require Auth - Implicit Pseudo-account authorization"); + using namespace jtx; + using namespace loanBroker; + + Account const issuer{"issuer"}; + Account const alice{"alice"}; + Env env(*this); + Vault vault{env}; + + env.fund(XRP(100'000), issuer, alice); + env.close(); + + auto asset = MPTTester({ + .env = env, + .issuer = issuer, + .holders = {alice}, + .flags = MPTDEXFlags | tfMPTRequireAuth | tfMPTCanClawback | + tfMPTCanLock, + .authHolder = true, + }); + + env(pay(issuer, alice, asset(100'000))); + env.close(); + + // Alice is not authorized, can still create the vault + asset.authorize( + {.account = issuer, .holder = alice, .flags = tfMPTUnauthorize}); + auto [tx, vaultKeylet] = vault.create({.owner = alice, .asset = asset}); + env(tx); + env.close(); + + auto const le = env.le(vaultKeylet); + VaultInfo vaultInfo = [&]() { + if (BEAST_EXPECT(le)) + return VaultInfo{asset, vaultKeylet.key, le->at(sfAccount)}; + return VaultInfo{asset, {}, {}}; + }(); + if (vaultInfo.vaultID == uint256{}) + return; + + // Can't unauthorize Vault pseudo-account + asset.authorize( + {.account = issuer, + .holder = vaultInfo.pseudoAccount, + .flags = tfMPTUnauthorize, + .err = tecNO_PERMISSION}); + + auto forUnauthAuth = [&](auto&& doTx) { + for (auto const flag : {tfMPTUnauthorize, 0u}) + { + asset.authorize( + {.account = issuer, .holder = alice, .flags = flag}); + env.close(); + doTx(flag == 0); + env.close(); + } + }; + + // Can't deposit into Vault if the vault owner is not authorized + forUnauthAuth([&](bool authorized) { + auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); + env(vault.deposit( + {.depositor = alice, + .id = vaultKeylet.key, + .amount = asset(51)}), + err); + }); + + // Can't withdraw from Vault if the vault owner is not authorized + forUnauthAuth([&](bool authorized) { + auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); + env(vault.withdraw( + {.depositor = alice, + .id = vaultKeylet.key, + .amount = asset(1)}), + err); + }); + + auto const brokerKeylet = + keylet::loanbroker(alice.id(), env.seq(alice)); + // Can create LoanBroker if the vault owner is not authorized + forUnauthAuth([&](auto) { env(set(alice, vaultInfo.vaultID)); }); + + auto const broker = env.le(brokerKeylet); + if (!BEAST_EXPECT(broker)) + return; + Account brokerPseudo("pseudo", broker->at(sfAccount)); + + // Can't unauthorize LoanBroker pseudo-account + asset.authorize( + {.account = issuer, + .holder = brokerPseudo, + .flags = tfMPTUnauthorize, + .err = tecNO_PERMISSION}); + + // Can't cover deposit into Vault if the vault owner is not authorized + forUnauthAuth([&](bool authorized) { + auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); + env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), + err); + }); + + // Can't cover withdraw from Vault if the vault owner is not authorized + forUnauthAuth([&](bool authorized) { + auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); + env(coverWithdraw(alice, brokerKeylet.key, vaultInfo.asset(5)), + err); + }); + + // Issuer can always cover clawback. The holder authorization is n/a. + forUnauthAuth([&](bool) { + env(coverClawback(issuer), + loanBrokerID(brokerKeylet.key), + amount(vaultInfo.asset(1))); + }); + } + +public: + void + run() override + { + testLoanBrokerCoverDepositNullVault(); + + testDisabled(); + testLifecycle(); + testInvalidLoanBrokerCoverClawback(); + testInvalidLoanBrokerCoverDeposit(); + testInvalidLoanBrokerCoverWithdraw(); + testInvalidLoanBrokerDelete(); + testInvalidLoanBrokerSet(); + testRequireAuth(); + + // TODO: Write clawback failure tests with an issuer / MPT that doesn't + // have the right flags set. + } +}; + +BEAST_DEFINE_TESTSUITE(LoanBroker, tx, ripple); + +} // namespace test +} // namespace ripple diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp new file mode 100644 index 0000000000..b2ad47c2b4 --- /dev/null +++ b/src/test/app/Loan_test.cpp @@ -0,0 +1,7215 @@ +#include +// +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace ripple { +namespace test { + +class Loan_test : public beast::unit_test::suite +{ +protected: + // Ensure that all the features needed for Lending Protocol are included, + // even if they are set to unsupported. + FeatureBitset const all{ + jtx::testable_amendments() | featureMPTokensV1 | + featureSingleAssetVault | featureLendingProtocol}; + + std::string const iouCurrency{"IOU"}; + + void + testDisabled() + { + testcase("Disabled"); + // Lending Protocol depends on Single Asset Vault (SAV). Test + // combinations of the two amendments. + // Single Asset Vault depends on MPTokensV1, but don't test every combo + // of that. + using namespace jtx; + auto failAll = [this](FeatureBitset features) { + Env env(*this, features); + + Account const alice{"alice"}; + Account const bob{"bob"}; + env.fund(XRP(10000), alice, bob); + + auto const keylet = keylet::loanbroker(alice, env.seq(alice)); + + using namespace std::chrono_literals; + using namespace loan; + + // counter party signature is optional on LoanSet. Confirm that by + // sending transaction without one. + auto setTx = + env.jt(set(alice, keylet.key, Number(10000)), ter(temDISABLED)); + env(setTx); + + // All loan transactions are disabled. + // 1. LoanSet + setTx = env.jt( + setTx, sig(sfCounterpartySignature, bob), ter(temDISABLED)); + env(setTx); + // Actual sequence will be based off the loan broker, but we + // obviously don't have one of those if the amendment is disabled + auto const loanKeylet = keylet::loan(keylet.key, env.seq(alice)); + // Other Loan transactions are disabled, too. + // 2. LoanDelete + env(del(alice, loanKeylet.key), ter(temDISABLED)); + // 3. LoanManage + env(manage(alice, loanKeylet.key, tfLoanImpair), ter(temDISABLED)); + // 4. LoanPay + env(pay(alice, loanKeylet.key, XRP(500)), ter(temDISABLED)); + }; + failAll(all - featureMPTokensV1); + failAll(all - featureSingleAssetVault - featureLendingProtocol); + failAll(all - featureSingleAssetVault); + failAll(all - featureLendingProtocol); + } + + struct BrokerParameters + { + Number vaultDeposit = 1'000'000; + Number debtMax = 25'000; + TenthBips32 coverRateMin = percentageToTenthBips(10); + int coverDeposit = 1000; + TenthBips16 managementFeeRate{100}; + TenthBips32 coverRateLiquidation = percentageToTenthBips(25); + std::string data{}; + std::uint32_t flags = 0; + + Number + maxCoveredLoanValue(Number const& currentDebt) const + { + NumberRoundModeGuard mg(Number::downward); + auto debtLimit = + coverDeposit * tenthBipsPerUnity.value() / coverRateMin.value(); + + return debtLimit - currentDebt; + } + + static BrokerParameters const& + defaults() + { + static BrokerParameters const result{}; + return result; + } + + // TODO: create an operator() which returns a transaction similar to + // LoanParameters + }; + + struct BrokerInfo + { + jtx::PrettyAsset asset; + uint256 brokerID; + uint256 vaultID; + BrokerParameters params; + BrokerInfo( + jtx::PrettyAsset const& asset_, + Keylet const& brokerKeylet_, + Keylet const& vaultKeylet_, + BrokerParameters const& p) + : asset(asset_) + , brokerID(brokerKeylet_.key) + , vaultID(vaultKeylet_.key) + , params(p) + { + } + + Keylet + brokerKeylet() const + { + return keylet::loanbroker(brokerID); + } + Keylet + vaultKeylet() const + { + return keylet::vault(vaultID); + } + + int + vaultScale(jtx::Env const& env) const + { + using namespace jtx; + + auto const vaultSle = env.le(keylet::vault(vaultID)); + return getVaultScale(vaultSle); + } + }; + + struct LoanParameters + { + // The account submitting the transaction. May be borrower or broker. + jtx::Account account; + // The counterparty. Should be the other of borrower or broker. + jtx::Account counter; + // Whether the counterparty is specified in the `counterparty` field, or + // only signs. + bool counterpartyExplicit = true; + Number principalRequest; + std::optional setFee{}; + std::optional originationFee{}; + std::optional serviceFee{}; + std::optional lateFee{}; + std::optional closeFee{}; + std::optional overFee{}; + std::optional interest{}; + std::optional lateInterest{}; + std::optional closeInterest{}; + std::optional overpaymentInterest{}; + std::optional payTotal{}; + std::optional payInterval{}; + std::optional gracePd{}; + std::optional flags{}; + + template + jtx::JTx + operator()(jtx::Env& env, BrokerInfo const& broker, FN const&... fN) + const + { + using namespace jtx; + using namespace jtx::loan; + + JTx jt{loan::set( + account, + broker.brokerID, + broker.asset(principalRequest).number(), + flags.value_or(0))}; + + sig(sfCounterpartySignature, counter)(env, jt); + + fee{setFee.value_or(env.current()->fees().base * 2)}(env, jt); + + if (counterpartyExplicit) + counterparty(counter)(env, jt); + if (originationFee) + loanOriginationFee(broker.asset(*originationFee).number())( + env, jt); + if (serviceFee) + loanServiceFee(broker.asset(*serviceFee).number())(env, jt); + if (lateFee) + latePaymentFee(broker.asset(*lateFee).number())(env, jt); + if (closeFee) + closePaymentFee(broker.asset(*closeFee).number())(env, jt); + if (overFee) + overpaymentFee (*overFee)(env, jt); + if (interest) + interestRate (*interest)(env, jt); + if (lateInterest) + lateInterestRate (*lateInterest)(env, jt); + if (closeInterest) + closeInterestRate (*closeInterest)(env, jt); + if (overpaymentInterest) + overpaymentInterestRate (*overpaymentInterest)(env, jt); + if (payTotal) + paymentTotal (*payTotal)(env, jt); + if (payInterval) + paymentInterval (*payInterval)(env, jt); + if (gracePd) + gracePeriod (*gracePd)(env, jt); + + return env.jt(jt, fN...); + } + }; + + struct PaymentParameters + { + Number overpaymentFactor = Number{1}; + std::optional overpaymentExtra = std::nullopt; + std::uint32_t flags = 0; + bool showStepBalances = false; + bool validateBalances = true; + + static PaymentParameters const& + defaults() + { + static PaymentParameters const result{}; + return result; + } + }; + + struct LoanState + { + std::uint32_t previousPaymentDate = 0; + NetClock::time_point startDate = {}; + std::uint32_t nextPaymentDate = 0; + std::uint32_t paymentRemaining = 0; + std::int32_t const loanScale = 0; + Number totalValue = 0; + Number principalOutstanding = 0; + Number managementFeeOutstanding = 0; + Number periodicPayment = 0; + std::uint32_t flags = 0; + std::uint32_t const paymentInterval = 0; + TenthBips32 const interestRate{}; + }; + + /** Helper class to compare the expected state of a loan and loan broker + * against the data in the ledger. + */ + struct VerifyLoanStatus + { + public: + jtx::Env const& env; + BrokerInfo const& broker; + jtx::Account const& pseudoAccount; + Keylet const& loanKeylet; + + VerifyLoanStatus( + jtx::Env const& env_, + BrokerInfo const& broker_, + jtx::Account const& pseudo_, + Keylet const& keylet_) + : env(env_) + , broker(broker_) + , pseudoAccount(pseudo_) + , loanKeylet(keylet_) + { + } + + /** Checks the expected broker state against the ledger + */ + void + checkBroker( + Number const& principalOutstanding, + Number const& interestOwed, + TenthBips32 interestRate, + std::uint32_t paymentInterval, + std::uint32_t paymentsRemaining, + std::uint32_t ownerCount) const + { + using namespace jtx; + if (auto brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + env.test.BEAST_EXPECT(brokerSle)) + { + TenthBips16 const managementFeeRate{ + brokerSle->at(sfManagementFeeRate)}; + auto const brokerDebt = brokerSle->at(sfDebtTotal); + auto const expectedDebt = principalOutstanding + interestOwed; + env.test.BEAST_EXPECT(brokerDebt == expectedDebt); + env.test.BEAST_EXPECT( + env.balance(pseudoAccount, broker.asset).number() == + brokerSle->at(sfCoverAvailable)); + env.test.BEAST_EXPECT( + brokerSle->at(sfOwnerCount) == ownerCount); + + if (auto vaultSle = + env.le(keylet::vault(brokerSle->at(sfVaultID))); + env.test.BEAST_EXPECT(vaultSle)) + { + Account const vaultPseudo{ + "vaultPseudoAccount", vaultSle->at(sfAccount)}; + env.test.BEAST_EXPECT( + vaultSle->at(sfAssetsAvailable) == + env.balance(vaultPseudo, broker.asset).number()); + if (ownerCount == 0) + { + // Allow some slop for rounding IOUs + + // TODO: This needs to be an exact match once all the + // other rounding issues are worked out. + auto const total = vaultSle->at(sfAssetsTotal); + auto const available = vaultSle->at(sfAssetsAvailable); + env.test.BEAST_EXPECT( + total == available || + (!broker.asset.integral() && available != 0 && + ((total - available) / available < + Number(1, -6)))); + env.test.BEAST_EXPECT( + vaultSle->at(sfLossUnrealized) == 0); + } + } + } + } + + void + checkPayment( + std::int32_t loanScale, + jtx::Account const& account, + jtx::PrettyAmount const& balanceBefore, + STAmount const& expectedPayment, + jtx::PrettyAmount const& adjustment) const + { + auto const borrowerScale = + std::max(loanScale, balanceBefore.number().exponent()); + + STAmount const balanceChangeAmount{ + broker.asset, + roundToAsset( + broker.asset, expectedPayment + adjustment, borrowerScale)}; + { + auto const difference = roundToScale( + env.balance(account, broker.asset) - + (balanceBefore - balanceChangeAmount), + borrowerScale); + env.test.BEAST_EXPECT( + roundToScale(difference, loanScale) >= beast::zero); + } + } + + /** Checks both the loan and broker expect states against the ledger */ + void + operator()( + std::uint32_t previousPaymentDate, + std::uint32_t nextPaymentDate, + std::uint32_t paymentRemaining, + Number const& loanScale, + Number const& totalValue, + Number const& principalOutstanding, + Number const& managementFeeOutstanding, + Number const& periodicPayment, + std::uint32_t flags) const + { + using namespace jtx; + if (auto loan = env.le(loanKeylet); env.test.BEAST_EXPECT(loan)) + { + env.test.BEAST_EXPECT( + loan->at(sfPreviousPaymentDate) == previousPaymentDate); + env.test.BEAST_EXPECT( + loan->at(sfPaymentRemaining) == paymentRemaining); + env.test.BEAST_EXPECT( + loan->at(sfNextPaymentDueDate) == nextPaymentDate); + env.test.BEAST_EXPECT(loan->at(sfLoanScale) == loanScale); + env.test.BEAST_EXPECT( + loan->at(sfTotalValueOutstanding) == totalValue); + env.test.BEAST_EXPECT( + loan->at(sfPrincipalOutstanding) == principalOutstanding); + env.test.BEAST_EXPECT( + loan->at(sfManagementFeeOutstanding) == + managementFeeOutstanding); + env.test.BEAST_EXPECT( + loan->at(sfPeriodicPayment) == periodicPayment); + env.test.BEAST_EXPECT(loan->at(sfFlags) == flags); + + auto const ls = constructRoundedLoanState(loan); + + auto const interestRate = TenthBips32{loan->at(sfInterestRate)}; + auto const paymentInterval = loan->at(sfPaymentInterval); + checkBroker( + principalOutstanding, + ls.interestDue, + interestRate, + paymentInterval, + paymentRemaining, + 1); + + if (auto brokerSle = + env.le(keylet::loanbroker(broker.brokerID)); + env.test.BEAST_EXPECT(brokerSle)) + { + if (auto vaultSle = + env.le(keylet::vault(brokerSle->at(sfVaultID))); + env.test.BEAST_EXPECT(vaultSle)) + { + if ((flags & lsfLoanImpaired) && + !(flags & lsfLoanDefault)) + { + env.test.BEAST_EXPECT( + vaultSle->at(sfLossUnrealized) == + totalValue - managementFeeOutstanding); + } + else + { + env.test.BEAST_EXPECT( + vaultSle->at(sfLossUnrealized) == 0); + } + } + } + } + } + + /** Checks both the loan and broker expect states against the ledger */ + void + operator()(LoanState const& state) const + { + operator()( + state.previousPaymentDate, + state.nextPaymentDate, + state.paymentRemaining, + state.loanScale, + state.totalValue, + state.principalOutstanding, + state.managementFeeOutstanding, + state.periodicPayment, + state.flags); + }; + }; + + BrokerInfo + createVaultAndBroker( + jtx::Env& env, + jtx::PrettyAsset const& asset, + jtx::Account const& lender, + BrokerParameters const& params = BrokerParameters::defaults()) + { + using namespace jtx; + + Vault vault{env}; + + auto const deposit = asset(params.vaultDeposit); + auto const debtMaximumValue = asset(params.debtMax).value(); + auto const coverDepositValue = asset(params.coverDeposit).value(); + + auto const coverRateMinValue = params.coverRateMin; + + auto [tx, vaultKeylet] = + vault.create({.owner = lender, .asset = asset}); + env(tx); + env.close(); + BEAST_EXPECT(env.le(vaultKeylet)); + + env(vault.deposit( + {.depositor = lender, .id = vaultKeylet.key, .amount = deposit})); + env.close(); + if (auto const vault = env.le(keylet::vault(vaultKeylet.key)); + BEAST_EXPECT(vault)) + { + BEAST_EXPECT(vault->at(sfAssetsAvailable) == deposit.value()); + } + + auto const keylet = keylet::loanbroker(lender.id(), env.seq(lender)); + + using namespace loanBroker; + env(set(lender, vaultKeylet.key, params.flags), + data(params.data), + managementFeeRate(params.managementFeeRate), + debtMaximum(debtMaximumValue), + coverRateMinimum(coverRateMinValue), + coverRateLiquidation(TenthBips32(params.coverRateLiquidation))); + + if (coverDepositValue != beast::zero) + env(coverDeposit(lender, keylet.key, coverDepositValue)); + + env.close(); + + return {asset, keylet, vaultKeylet, params}; + } + + /// Get the state without checking anything + LoanState + getCurrentState( + jtx::Env const& env, + BrokerInfo const& broker, + Keylet const& loanKeylet) + { + using d = NetClock::duration; + using tp = NetClock::time_point; + + // Lookup the current loan state + if (auto loan = env.le(loanKeylet); BEAST_EXPECT(loan)) + { + return LoanState{ + .previousPaymentDate = loan->at(sfPreviousPaymentDate), + .startDate = tp{d{loan->at(sfStartDate)}}, + .nextPaymentDate = loan->at(sfNextPaymentDueDate), + .paymentRemaining = loan->at(sfPaymentRemaining), + .loanScale = loan->at(sfLoanScale), + .totalValue = loan->at(sfTotalValueOutstanding), + .principalOutstanding = loan->at(sfPrincipalOutstanding), + .managementFeeOutstanding = + loan->at(sfManagementFeeOutstanding), + .periodicPayment = loan->at(sfPeriodicPayment), + .flags = loan->at(sfFlags), + .paymentInterval = loan->at(sfPaymentInterval), + .interestRate = TenthBips32{loan->at(sfInterestRate)}, + }; + } + return LoanState{}; + } + + /// Get the state and check the values against the parameters used in + /// `lifecycle` + LoanState + getCurrentState( + jtx::Env const& env, + BrokerInfo const& broker, + Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) + { + using namespace std::chrono_literals; + using d = NetClock::duration; + using tp = NetClock::time_point; + + auto const state = getCurrentState(env, broker, loanKeylet); + BEAST_EXPECT(state.previousPaymentDate == 0); + BEAST_EXPECT(tp{d{state.nextPaymentDate}} == state.startDate + 600s); + BEAST_EXPECT(state.paymentRemaining == 12); + BEAST_EXPECT(state.principalOutstanding == broker.asset(1000).value()); + BEAST_EXPECT( + state.loanScale >= + (broker.asset.integral() + ? 0 + : std::max( + broker.vaultScale(env), + state.principalOutstanding.exponent()))); + BEAST_EXPECT(state.paymentInterval == 600); + BEAST_EXPECT( + state.totalValue == + roundToAsset( + broker.asset, + state.periodicPayment * state.paymentRemaining, + state.loanScale)); + BEAST_EXPECT( + state.managementFeeOutstanding == + computeManagementFee( + broker.asset, + state.totalValue - state.principalOutstanding, + broker.params.managementFeeRate, + state.loanScale)); + + verifyLoanStatus(state); + + return state; + } + + bool + canImpairLoan( + jtx::Env const& env, + BrokerInfo const& broker, + LoanState const& state) + { + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle)) + { + if (auto const vaultSle = + env.le(keylet::vault(brokerSle->at(sfVaultID))); + BEAST_EXPECT(vaultSle)) + { + // log << vaultSle->getJson() << std::endl; + auto const assetsUnavailable = vaultSle->at(sfAssetsTotal) - + vaultSle->at(sfAssetsAvailable); + auto const unrealizedLoss = vaultSle->at(sfLossUnrealized) + + state.totalValue - state.managementFeeOutstanding; + + if (unrealizedLoss > assetsUnavailable) + { + return false; + } + } + } + return true; + } + + enum class AssetType { XRP = 0, IOU = 1, MPT = 2 }; + + // Specify the accounts as params to allow other accounts to be used + jtx::PrettyAsset + createAsset( + jtx::Env& env, + AssetType assetType, + BrokerParameters const& brokerParams, + jtx::Account const& issuer, + jtx::Account const& lender, + jtx::Account const& borrower) + { + using namespace jtx; + + switch (assetType) + { + case AssetType::XRP: + // TODO: remove the factor, and set up loans in drops + return PrettyAsset{xrpIssue(), 1'000'000}; + + case AssetType::IOU: { + PrettyAsset const asset{issuer[iouCurrency]}; + + auto const limit = asset( + 100 * + (brokerParams.vaultDeposit + brokerParams.coverDeposit)); + if (lender != issuer) + env(trust(lender, limit)); + if (borrower != issuer) + env(trust(borrower, limit)); + + return asset; + } + + case AssetType::MPT: { + // Enough to cover initial fees + if (!env.le(keylet::account(issuer))) + env.fund( + env.current()->fees().accountReserve(10) * 10, issuer); + if (!env.le(keylet::account(lender))) + env.fund( + env.current()->fees().accountReserve(10) * 10, + noripple(lender)); + if (!env.le(keylet::account(borrower))) + env.fund( + env.current()->fees().accountReserve(10) * 10, + noripple(borrower)); + + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = + tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + // Scale the MPT asset so interest is interesting + PrettyAsset const asset{mptt.issuanceID(), 10'000}; + // Need to do the authorization here because mptt isn't + // accessible outside + if (lender != issuer) + mptt.authorize({.account = lender}); + if (borrower != issuer) + mptt.authorize({.account = borrower}); + + env.close(); + + return asset; + } + + default: + throw std::runtime_error("Unknown asset type"); + } + } + + void + describeLoan( + jtx::Env& env, + BrokerParameters const& brokerParams, + LoanParameters const& loanParams, + AssetType assetType, + jtx::Account const& issuer, + jtx::Account const& lender, + jtx::Account const& borrower) + { + using namespace jtx; + + auto const asset = + createAsset(env, assetType, brokerParams, issuer, lender, borrower); + auto const principal = asset(loanParams.principalRequest).number(); + auto const interest = loanParams.interest.value_or(TenthBips32{}); + auto const interval = + loanParams.payInterval.value_or(LoanSet::defaultPaymentInterval); + auto const total = + loanParams.payTotal.value_or(LoanSet::defaultPaymentTotal); + auto const feeRate = brokerParams.managementFeeRate; + auto const props = computeLoanProperties( + asset, + principal, + interest, + interval, + total, + feeRate, + asset(brokerParams.vaultDeposit).number().exponent()); + log << "Loan properties:\n" + << "\tPrincipal: " << principal << std::endl + << "\tInterest rate: " << interest << std::endl + << "\tPayment interval: " << interval << std::endl + << "\tManagement Fee Rate: " << feeRate << std::endl + << "\tTotal Payments: " << total << std::endl + << "\tPeriodic Payment: " << props.periodicPayment << std::endl + << "\tTotal Value: " << props.totalValueOutstanding << std::endl + << "\tManagement Fee: " << props.managementFeeOwedToBroker + << std::endl + << "\tLoan Scale: " << props.loanScale << std::endl + << "\tFirst payment principal: " << props.firstPaymentPrincipal + << std::endl; + + // checkGuards returns a TER, so success is 0 + BEAST_EXPECT(!checkLoanGuards( + asset, + asset(loanParams.principalRequest).number(), + loanParams.interest.value_or(TenthBips32{}) != beast::zero, + loanParams.payTotal.value_or(LoanSet::defaultPaymentTotal), + props, + env.journal)); + } + + std::optional> + createLoan( + jtx::Env& env, + AssetType assetType, + BrokerParameters const& brokerParams, + LoanParameters const& loanParams, + jtx::Account const& issuer, + jtx::Account const& lender, + jtx::Account const& borrower) + { + using namespace jtx; + + // Enough to cover initial fees + env.fund(env.current()->fees().accountReserve(10) * 10, issuer); + if (lender != issuer) + env.fund( + env.current()->fees().accountReserve(10) * 10, + noripple(lender)); + if (borrower != issuer && borrower != lender) + env.fund( + env.current()->fees().accountReserve(10) * 10, + noripple(borrower)); + + describeLoan( + env, brokerParams, loanParams, assetType, issuer, lender, borrower); + + // Make the asset + auto const asset = + createAsset(env, assetType, brokerParams, issuer, lender, borrower); + + env.close(); + if (asset.native() || lender != issuer) + env(pay( + (asset.native() ? env.master : issuer), + lender, + asset(brokerParams.vaultDeposit + brokerParams.coverDeposit))); + // Fund the borrower later once we know the total loan + // size + + BrokerInfo const broker = + createVaultAndBroker(env, asset, lender, brokerParams); + + auto const pseudoAcctOpt = [&]() -> std::optional { + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + if (!BEAST_EXPECT(brokerSle)) + return std::nullopt; + auto const brokerPseudo = brokerSle->at(sfAccount); + return Account("Broker pseudo-account", brokerPseudo); + }(); + if (!pseudoAcctOpt) + return std::nullopt; + Account const& pseudoAcct = *pseudoAcctOpt; + + auto const loanKeyletOpt = [&]() -> std::optional { + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + if (!BEAST_EXPECT(brokerSle)) + return std::nullopt; + + // Broker has no loans + BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 0); + + // The loan keylet is based on the LoanSequence of the + // _LOAN_BROKER_ object. + auto const loanSequence = brokerSle->at(sfLoanSequence); + return keylet::loan(broker.brokerID, loanSequence); + }(); + if (!loanKeyletOpt) + return std::nullopt; + Keylet const& loanKeylet = *loanKeyletOpt; + + env(loanParams(env, broker)); + + env.close(); + + return std::make_tuple(broker, loanKeylet, pseudoAcct); + } + + void + topUpBorrower( + jtx::Env& env, + BrokerInfo const& broker, + jtx::Account const& issuer, + jtx::Account const& borrower, + LoanState const& state, + std::optional const& servFee) + { + using namespace jtx; + + STAmount const serviceFee = broker.asset(servFee.value_or(0)); + + // Ensure the borrower has enough funds to make the payments + // (including tx fees, if necessary) + auto const borrowerBalance = env.balance(borrower, broker.asset); + + auto const baseFee = env.current()->fees().base; + + // Add extra for transaction fees and reserves, if appropriate, or a + // tiny amount for the extra paid in each transaction + auto const totalNeeded = state.totalValue + + (serviceFee * state.paymentRemaining) + + (broker.asset.native() ? Number( + baseFee * state.paymentRemaining + + env.current()->fees().accountReserve( + env.ownerCount(borrower))) + : broker.asset(15).number()); + + auto const shortage = totalNeeded - borrowerBalance.number(); + + if (shortage > beast::zero && + (broker.asset.native() || issuer != borrower)) + env( + pay((broker.asset.native() ? env.master : issuer), + borrower, + STAmount{broker.asset, shortage})); + } + + void + makeLoanPayments( + jtx::Env& env, + BrokerInfo const& broker, + LoanParameters const& loanParams, + Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus, + jtx::Account const& issuer, + jtx::Account const& lender, + jtx::Account const& borrower, + PaymentParameters const& paymentParams = PaymentParameters::defaults()) + { + // Make all the individual payments + using namespace jtx; + using namespace jtx::loan; + using namespace std::chrono_literals; + using d = NetClock::duration; + + // Account const evan{"evan"}; + // Account const alice{"alice"}; + + bool const showStepBalances = paymentParams.showStepBalances; + + auto const currencyLabel = getCurrencyLabel(broker.asset); + + auto const baseFee = env.current()->fees().base; + + env.close(); + auto state = getCurrentState(env, broker, loanKeylet); + + verifyLoanStatus(state); + + STAmount const serviceFee = + broker.asset(loanParams.serviceFee.value_or(0)); + + topUpBorrower( + env, broker, issuer, borrower, state, loanParams.serviceFee); + + // Periodic payment amount will consist of + // 1. principal outstanding (1000) + // 2. interest interest rate (at 12%) + // 3. payment interval (600s) + // 4. loan service fee (2) + // Calculate these values without the helper functions + // to verify they're working correctly The numbers in + // the below BEAST_EXPECTs may not hold across assets. + auto const periodicRate = + loanPeriodicRate(state.interestRate, state.paymentInterval); + STAmount const roundedPeriodicPayment{ + broker.asset, + roundPeriodicPayment( + broker.asset, state.periodicPayment, state.loanScale)}; + + if (!showStepBalances) + log << currencyLabel << " Payment components: " + << "Payments remaining, " + << "rawInterest, rawPrincipal, " + "rawMFee, " + << "trackedValueDelta, trackedPrincipalDelta, " + "trackedInterestDelta, trackedMgmtFeeDelta, special" + << std::endl; + + // Include the service fee + STAmount const totalDue = roundToScale( + roundedPeriodicPayment + serviceFee, + state.loanScale, + Number::upward); + + auto currentRoundedState = constructLoanState( + state.totalValue, + state.principalOutstanding, + state.managementFeeOutstanding); + { + auto const raw = computeRawLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining, + broker.params.managementFeeRate); + + if (showStepBalances) + { + log << currencyLabel << " Starting loan balances: " + << "\n\tTotal value: " + << currentRoundedState.valueOutstanding << "\n\tPrincipal: " + << currentRoundedState.principalOutstanding + << "\n\tInterest: " << currentRoundedState.interestDue + << "\n\tMgmt fee: " << currentRoundedState.managementFeeDue + << "\n\tPayments remaining " << state.paymentRemaining + << std::endl; + } + else + { + log << currencyLabel + << " Loan starting state: " << state.paymentRemaining + << ", " << raw.interestDue << ", " + << raw.principalOutstanding << ", " << raw.managementFeeDue + << ", " << currentRoundedState.valueOutstanding << ", " + << currentRoundedState.principalOutstanding << ", " + << currentRoundedState.interestDue << ", " + << currentRoundedState.managementFeeDue << std::endl; + } + } + + // Try to pay a little extra to show that it's _not_ + // taken + auto const extraAmount = paymentParams.overpaymentExtra + ? broker.asset(*paymentParams.overpaymentExtra).value() + : std::min( + broker.asset(10).value(), + STAmount{broker.asset, totalDue / 20}); + + STAmount const transactionAmount = + STAmount{broker.asset, totalDue * paymentParams.overpaymentFactor} + + extraAmount; + + auto const borrowerInitialBalance = + env.balance(borrower, broker.asset).number(); + auto const initialState = state; + detail::PaymentComponents totalPaid{ + .trackedValueDelta = 0, + .trackedPrincipalDelta = 0, + .trackedManagementFeeDelta = 0}; + Number totalInterestPaid = 0; + Number totalFeesPaid = 0; + std::size_t totalPaymentsMade = 0; + + ripple::LoanState currentTrueState = computeRawLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining, + broker.params.managementFeeRate); + + auto validateBorrowerBalance = [&]() { + if (borrower == issuer || !paymentParams.validateBalances) + return; + auto const totalSpent = + (totalPaid.trackedValueDelta + totalFeesPaid + + (broker.asset.native() ? Number(baseFee) * totalPaymentsMade + : numZero)); + BEAST_EXPECT( + env.balance(borrower, broker.asset).number() == + borrowerInitialBalance - totalSpent); + }; + + auto const defaultRound = broker.asset.integral() ? 3 : 0; + auto truncate = [defaultRound]( + Number const& n, + std::optional places = std::nullopt) { + auto const p = places.value_or(defaultRound); + if (p == 0) + return n; + auto const factor = Number{1, p}; + return (n * factor).truncate() / factor; + }; + while (state.paymentRemaining > 0) + { + validateBorrowerBalance(); + // Compute the expected principal amount + auto const paymentComponents = detail::computePaymentComponents( + broker.asset.raw(), + state.loanScale, + state.totalValue, + state.principalOutstanding, + state.managementFeeOutstanding, + state.periodicPayment, + periodicRate, + state.paymentRemaining, + broker.params.managementFeeRate); + + BEAST_EXPECT( + paymentComponents.trackedValueDelta <= roundedPeriodicPayment || + (paymentComponents.specialCase == + detail::PaymentSpecialCase::final && + paymentComponents.trackedValueDelta >= + roundedPeriodicPayment)); + BEAST_EXPECT( + paymentComponents.trackedValueDelta == + paymentComponents.trackedPrincipalDelta + + paymentComponents.trackedInterestPart() + + paymentComponents.trackedManagementFeeDelta); + + ripple::LoanState const nextTrueState = computeRawLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining - 1, + broker.params.managementFeeRate); + detail::LoanStateDeltas const deltas = + currentTrueState - nextTrueState; + BEAST_EXPECT( + deltas.total() == + deltas.principal + deltas.interest + deltas.managementFee); + BEAST_EXPECT( + paymentComponents.specialCase == + detail::PaymentSpecialCase::final || + deltas.total() == state.periodicPayment || + (state.loanScale - + (deltas.total() - state.periodicPayment).exponent()) > 14); + + if (!showStepBalances) + log << currencyLabel + << " Payment components: " << state.paymentRemaining << ", " + + << deltas.interest << ", " << deltas.principal << ", " + << deltas.managementFee << ", " + << paymentComponents.trackedValueDelta << ", " + << paymentComponents.trackedPrincipalDelta << ", " + << paymentComponents.trackedInterestPart() << ", " + << paymentComponents.trackedManagementFeeDelta << ", " + << (paymentComponents.specialCase == + detail::PaymentSpecialCase::final + ? "final" + : paymentComponents.specialCase == + detail::PaymentSpecialCase::extra + ? "extra" + : "none") + << std::endl; + + auto const totalDueAmount = STAmount{ + broker.asset, paymentComponents.trackedValueDelta + serviceFee}; + + if (paymentParams.validateBalances) + { + // Due to the rounding algorithms to keep the interest and + // principal in sync with "true" values, the computed amount + // may be a little less than the rounded fixed payment + // amount. For integral types, the difference should be < 3 + // (1 unit for each of the interest and management fee). For + // IOUs, the difference should be dust. + Number const diff = totalDue - totalDueAmount; + BEAST_EXPECT( + paymentComponents.specialCase == + detail::PaymentSpecialCase::final || + diff == beast::zero || + (diff > beast::zero && + ((broker.asset.integral() && + (static_cast(diff) < 3)) || + (state.loanScale - diff.exponent() > 13)))); + + BEAST_EXPECT( + paymentComponents.trackedPrincipalDelta >= beast::zero && + paymentComponents.trackedPrincipalDelta <= + state.principalOutstanding); + BEAST_EXPECT( + paymentComponents.specialCase != + detail::PaymentSpecialCase::final || + paymentComponents.trackedPrincipalDelta == + state.principalOutstanding); + } + + auto const borrowerBalanceBeforePayment = + env.balance(borrower, broker.asset); + + // Make the payment + env( + pay(borrower, + loanKeylet.key, + transactionAmount, + paymentParams.flags)); + + env.close(d{state.paymentInterval / 2}); + + if (paymentParams.validateBalances) + { + // Need to account for fees if the loan is in XRP + PrettyAmount adjustment = broker.asset(0); + if (broker.asset.native()) + { + adjustment = env.current()->fees().base; + } + + // Check the result + verifyLoanStatus.checkPayment( + state.loanScale, + borrower, + borrowerBalanceBeforePayment, + totalDueAmount, + adjustment); + } + + if (showStepBalances) + { + auto const loanSle = env.le(loanKeylet); + if (!BEAST_EXPECT(loanSle)) + // No reason for this not to exist + return; + auto const current = constructRoundedLoanState(loanSle); + auto const errors = nextTrueState - current; + log << currencyLabel << " Loan balances: " + << "\n\tAmount taken: " + << paymentComponents.trackedValueDelta + << "\n\tTotal value: " << current.valueOutstanding + << " (true: " << truncate(nextTrueState.valueOutstanding) + << ", error: " << truncate(errors.total()) + << ")\n\tPrincipal: " << current.principalOutstanding + << " (true: " + << truncate(nextTrueState.principalOutstanding) + << ", error: " << truncate(errors.principal) + << ")\n\tInterest: " << current.interestDue + << " (true: " << truncate(nextTrueState.interestDue) + << ", error: " << truncate(errors.interest) + << ")\n\tMgmt fee: " << current.managementFeeDue + << " (true: " << truncate(nextTrueState.managementFeeDue) + << ", error: " << truncate(errors.managementFee) + << ")\n\tPayments remaining " + << loanSle->at(sfPaymentRemaining) << std::endl; + + currentRoundedState = current; + } + + --state.paymentRemaining; + state.previousPaymentDate = state.nextPaymentDate; + if (paymentComponents.specialCase == + detail::PaymentSpecialCase::final) + { + state.paymentRemaining = 0; + state.nextPaymentDate = 0; + } + else + { + state.nextPaymentDate += state.paymentInterval; + } + state.principalOutstanding -= + paymentComponents.trackedPrincipalDelta; + state.managementFeeOutstanding -= + paymentComponents.trackedManagementFeeDelta; + state.totalValue -= paymentComponents.trackedValueDelta; + + if (paymentParams.validateBalances) + verifyLoanStatus(state); + + totalPaid.trackedValueDelta += paymentComponents.trackedValueDelta; + totalPaid.trackedPrincipalDelta += + paymentComponents.trackedPrincipalDelta; + totalPaid.trackedManagementFeeDelta += + paymentComponents.trackedManagementFeeDelta; + totalInterestPaid += paymentComponents.trackedInterestPart(); + totalFeesPaid += serviceFee; + ++totalPaymentsMade; + + currentTrueState = nextTrueState; + } + validateBorrowerBalance(); + + // Loan is paid off + BEAST_EXPECT(state.paymentRemaining == 0); + BEAST_EXPECT(state.principalOutstanding == 0); + + auto const initialInterestDue = initialState.totalValue - + (initialState.principalOutstanding + + initialState.managementFeeOutstanding); + if (paymentParams.validateBalances) + { + // Make sure all the payments add up + BEAST_EXPECT( + totalPaid.trackedValueDelta == initialState.totalValue); + BEAST_EXPECT( + totalPaid.trackedPrincipalDelta == + initialState.principalOutstanding); + BEAST_EXPECT( + totalPaid.trackedManagementFeeDelta == + initialState.managementFeeOutstanding); + // This is almost a tautology given the previous checks, but + // check it anyway for completeness. + BEAST_EXPECT(totalInterestPaid == initialInterestDue); + BEAST_EXPECT(totalPaymentsMade == initialState.paymentRemaining); + } + + if (showStepBalances) + { + auto const loanSle = env.le(loanKeylet); + if (!BEAST_EXPECT(loanSle)) + // No reason for this not to exist + return; + log << currencyLabel << " Total amounts paid: " + << "\n\tTotal value: " << totalPaid.trackedValueDelta + << " (initial: " << truncate(initialState.totalValue) + << ", error: " + << truncate( + initialState.totalValue - totalPaid.trackedValueDelta) + << ")\n\tPrincipal: " << totalPaid.trackedPrincipalDelta + << " (initial: " << truncate(initialState.principalOutstanding) + << ", error: " + << truncate( + initialState.principalOutstanding - + totalPaid.trackedPrincipalDelta) + << ")\n\tInterest: " << totalInterestPaid + << " (initial: " << truncate(initialInterestDue) << ", error: " + << truncate(initialInterestDue - totalInterestPaid) + << ")\n\tMgmt fee: " << totalPaid.trackedManagementFeeDelta + << " (initial: " + << truncate(initialState.managementFeeOutstanding) + << ", error: " + << truncate( + initialState.managementFeeOutstanding - + totalPaid.trackedManagementFeeDelta) + << ")\n\tTotal payments made: " << totalPaymentsMade + << std::endl; + } + } + + void + runLoan( + AssetType assetType, + BrokerParameters const& brokerParams, + LoanParameters const& loanParams) + { + using namespace jtx; + + Account const issuer("issuer"); + Account const lender("lender"); + Account const borrower("borrower"); + + Env env(*this, all); + + auto loanResult = createLoan( + env, assetType, brokerParams, loanParams, issuer, lender, borrower); + if (!BEAST_EXPECT(loanResult)) + return; + + auto broker = std::get(*loanResult); + auto loanKeylet = std::get(*loanResult); + auto pseudoAcct = std::get(*loanResult); + + VerifyLoanStatus verifyLoanStatus(env, broker, pseudoAcct, loanKeylet); + + makeLoanPayments( + env, + broker, + loanParams, + loanKeylet, + verifyLoanStatus, + issuer, + lender, + borrower); + } + + /** Runs through the complete lifecycle of a loan + * + * 1. Create a loan. + * 2. Test a bunch of transaction failure conditions. + * 3. Use the `toEndOfLife` callback to take the loan to 0. How that is done + * depends on the callback. e.g. Default, Early payoff, make all the + * normal payments, etc. + * 4. Delete the loan. The loan will alternate between being deleted by the + * lender and the borrower. + */ + void + lifecycle( + std::string const& caseLabel, + char const* label, + jtx::Env& env, + Number const& loanAmount, + int interestExponent, + jtx::Account const& lender, + jtx::Account const& borrower, + jtx::Account const& evan, + BrokerInfo const& broker, + jtx::Account const& pseudoAcct, + std::uint32_t flags, + // The end of life callback is expected to take the loan to 0 payments + // remaining, one way or another + std::function toEndOfLife) + { + auto const [keylet, loanSequence] = [&]() { + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + if (!BEAST_EXPECT(brokerSle)) + // will be invalid + return std::make_pair( + keylet::loan(broker.brokerID), std::uint32_t(0)); + + // Broker has no loans + BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 0); + + // The loan keylet is based on the LoanSequence of the _LOAN_BROKER_ + // object. + auto const loanSequence = brokerSle->at(sfLoanSequence); + return std::make_pair( + keylet::loan(broker.brokerID, loanSequence), loanSequence); + }(); + + VerifyLoanStatus const verifyLoanStatus( + env, broker, pseudoAcct, keylet); + + // No loans yet + verifyLoanStatus.checkBroker(0, 0, TenthBips32{0}, 1, 0, 0); + + if (!BEAST_EXPECT(loanSequence != 0)) + return; + + testcase << caseLabel << " " << label; + + using namespace jtx; + using namespace loan; + using namespace std::chrono_literals; + + auto applyExponent = [interestExponent, + this](TenthBips32 value) mutable { + BEAST_EXPECT(value > TenthBips32(0)); + while (interestExponent > 0) + { + auto const oldValue = value; + value *= 10; + --interestExponent; + BEAST_EXPECT(value / 10 == oldValue); + } + while (interestExponent < 0) + { + auto const oldValue = value; + value /= 10; + ++interestExponent; + BEAST_EXPECT(value * 10 == oldValue); + } + return value; + }; + + auto const borrowerOwnerCount = env.ownerCount(borrower); + + auto const loanSetFee = env.current()->fees().base * 2; + LoanParameters const loanParams{ + .account = borrower, + .counter = lender, + .counterpartyExplicit = false, + .principalRequest = loanAmount, + .setFee = loanSetFee, + .originationFee = 1, + .serviceFee = 2, + .lateFee = 3, + .closeFee = 4, + .overFee = applyExponent(percentageToTenthBips(5) / 10), + .interest = applyExponent(percentageToTenthBips(12)), + // 2.4% + .lateInterest = applyExponent(percentageToTenthBips(24) / 10), + .closeInterest = applyExponent(percentageToTenthBips(36) / 10), + .overpaymentInterest = + applyExponent(percentageToTenthBips(48) / 10), + .payTotal = 12, + .payInterval = 600, + .gracePd = 60, + .flags = flags, + }; + Number const principalRequestAmount = + broker.asset(loanParams.principalRequest).value(); + auto const originationFeeAmount = + broker.asset(*loanParams.originationFee).value(); + auto const serviceFeeAmount = + broker.asset(*loanParams.serviceFee).value(); + auto const lateFeeAmount = broker.asset(*loanParams.lateFee).value(); + auto const closeFeeAmount = broker.asset(*loanParams.closeFee).value(); + + auto const borrowerStartbalance = env.balance(borrower, broker.asset); + + auto createJtx = loanParams(env, broker); + // Successfully create a Loan + env(createJtx); + + env.close(); + + auto const startDate = + env.current()->info().parentCloseTime.time_since_epoch().count(); + + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle)) + { + BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 1); + } + + { + // Need to account for fees if the loan is in XRP + PrettyAmount adjustment = broker.asset(0); + if (broker.asset.native()) + { + adjustment = 2 * env.current()->fees().base; + } + + BEAST_EXPECT( + env.balance(borrower, broker.asset).value() == + borrowerStartbalance.value() + principalRequestAmount - + originationFeeAmount - adjustment.value()); + } + + auto const loanFlags = createJtx.stx->isFlag(tfLoanOverpayment) + ? lsfLoanOverpayment + : LedgerSpecificFlags(0); + + if (auto loan = env.le(keylet); BEAST_EXPECT(loan)) + { + // log << "loan after create: " << to_string(loan->getJson()) + // << std::endl; + BEAST_EXPECT( + loan->isFlag(lsfLoanOverpayment) == + createJtx.stx->isFlag(tfLoanOverpayment)); + BEAST_EXPECT(loan->at(sfLoanSequence) == loanSequence); + BEAST_EXPECT(loan->at(sfBorrower) == borrower.id()); + BEAST_EXPECT(loan->at(sfLoanBrokerID) == broker.brokerID); + BEAST_EXPECT( + loan->at(sfLoanOriginationFee) == originationFeeAmount); + BEAST_EXPECT(loan->at(sfLoanServiceFee) == serviceFeeAmount); + BEAST_EXPECT(loan->at(sfLatePaymentFee) == lateFeeAmount); + BEAST_EXPECT(loan->at(sfClosePaymentFee) == closeFeeAmount); + BEAST_EXPECT(loan->at(sfOverpaymentFee) == *loanParams.overFee); + BEAST_EXPECT(loan->at(sfInterestRate) == *loanParams.interest); + BEAST_EXPECT( + loan->at(sfLateInterestRate) == *loanParams.lateInterest); + BEAST_EXPECT( + loan->at(sfCloseInterestRate) == *loanParams.closeInterest); + BEAST_EXPECT( + loan->at(sfOverpaymentInterestRate) == + *loanParams.overpaymentInterest); + BEAST_EXPECT(loan->at(sfStartDate) == startDate); + BEAST_EXPECT( + loan->at(sfPaymentInterval) == *loanParams.payInterval); + BEAST_EXPECT(loan->at(sfGracePeriod) == *loanParams.gracePd); + BEAST_EXPECT(loan->at(sfPreviousPaymentDate) == 0); + BEAST_EXPECT( + loan->at(sfNextPaymentDueDate) == + startDate + *loanParams.payInterval); + BEAST_EXPECT(loan->at(sfPaymentRemaining) == *loanParams.payTotal); + BEAST_EXPECT( + loan->at(sfLoanScale) >= + (broker.asset.integral() + ? 0 + : std::max( + broker.vaultScale(env), + principalRequestAmount.exponent()))); + BEAST_EXPECT( + loan->at(sfPrincipalOutstanding) == principalRequestAmount); + } + + auto state = getCurrentState(env, broker, keylet, verifyLoanStatus); + + auto const loanProperties = computeLoanProperties( + broker.asset.raw(), + state.principalOutstanding, + state.interestRate, + state.paymentInterval, + state.paymentRemaining, + broker.params.managementFeeRate, + state.loanScale); + + verifyLoanStatus( + 0, + startDate + *loanParams.payInterval, + *loanParams.payTotal, + state.loanScale, + loanProperties.totalValueOutstanding, + principalRequestAmount, + loanProperties.managementFeeOwedToBroker, + loanProperties.periodicPayment, + loanFlags | 0); + + // Manage the loan + // no-op + env(manage(lender, keylet.key, 0)); + { + // no flags + auto jt = manage(lender, keylet.key, 0); + jt.removeMember(sfFlags.getName()); + env(jt); + } + // Only the lender can manage + env(manage(evan, keylet.key, 0), ter(tecNO_PERMISSION)); + // unknown flags + env(manage(lender, keylet.key, tfLoanManageMask), ter(temINVALID_FLAG)); + // combinations of flags are not allowed + env(manage(lender, keylet.key, tfLoanUnimpair | tfLoanImpair), + ter(temINVALID_FLAG)); + env(manage(lender, keylet.key, tfLoanImpair | tfLoanDefault), + ter(temINVALID_FLAG)); + env(manage(lender, keylet.key, tfLoanUnimpair | tfLoanDefault), + ter(temINVALID_FLAG)); + env(manage( + lender, + keylet.key, + tfLoanUnimpair | tfLoanImpair | tfLoanDefault), + ter(temINVALID_FLAG)); + // invalid loan ID + env(manage(lender, broker.brokerID, tfLoanImpair), ter(tecNO_ENTRY)); + // Loan is unimpaired, can't unimpair it again + env(manage(lender, keylet.key, tfLoanUnimpair), ter(tecNO_PERMISSION)); + // Loan is unimpaired, it can go into default, but only after it's past + // due + env(manage(lender, keylet.key, tfLoanDefault), ter(tecTOO_SOON)); + + // Check the vault + bool const canImpair = canImpairLoan(env, broker, state); + // Impair the loan, if possible + env(manage(lender, keylet.key, tfLoanImpair), + canImpair ? ter(tesSUCCESS) : ter(tecLIMIT_EXCEEDED)); + // Unimpair the loan + env(manage(lender, keylet.key, tfLoanUnimpair), + canImpair ? ter(tesSUCCESS) : ter(tecNO_PERMISSION)); + + auto const nextDueDate = startDate + *loanParams.payInterval; + + env.close(); + + verifyLoanStatus( + 0, + nextDueDate, + *loanParams.payTotal, + loanProperties.loanScale, + loanProperties.totalValueOutstanding, + principalRequestAmount, + loanProperties.managementFeeOwedToBroker, + loanProperties.periodicPayment, + loanFlags | 0); + + // Can't delete the loan yet. It has payments remaining. + env(del(lender, keylet.key), ter(tecHAS_OBLIGATIONS)); + + if (BEAST_EXPECT(toEndOfLife)) + toEndOfLife(keylet, verifyLoanStatus); + env.close(); + + // Verify the loan is at EOL + if (auto loan = env.le(keylet); BEAST_EXPECT(loan)) + { + BEAST_EXPECT(loan->at(sfPaymentRemaining) == 0); + BEAST_EXPECT(loan->at(sfPrincipalOutstanding) == 0); + } + auto const borrowerStartingBalance = + env.balance(borrower, broker.asset); + + // Try to delete the loan broker with an active loan + env(loanBroker::del(lender, broker.brokerID), ter(tecHAS_OBLIGATIONS)); + // Ensure the above tx doesn't get ordered after the LoanDelete and + // delete our broker! + env.close(); + + // Test failure cases + env(del(lender, keylet.key, tfLoanOverpayment), ter(temINVALID_FLAG)); + env(del(evan, keylet.key), ter(tecNO_PERMISSION)); + env(del(lender, broker.brokerID), ter(tecNO_ENTRY)); + + // Delete the loan + // Either the borrower or the lender can delete the loan. Alternate + // between who does it across tests. + static unsigned deleteCounter = 0; + auto const deleter = ++deleteCounter % 2 ? lender : borrower; + env(del(deleter, keylet.key)); + env.close(); + + PrettyAmount adjustment = broker.asset(0); + if (deleter == borrower) + { + // Need to account for fees if the loan is in XRP + if (broker.asset.native()) + { + adjustment = env.current()->fees().base; + } + } + + // No loans left + verifyLoanStatus.checkBroker(0, 0, *loanParams.interest, 1, 0, 0); + + BEAST_EXPECT( + env.balance(borrower, broker.asset).value() == + borrowerStartingBalance.value() - adjustment); + BEAST_EXPECT(env.ownerCount(borrower) == borrowerOwnerCount); + + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle)) + { + BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 0); + } + } + + std::string + getCurrencyLabel(Asset const& asset) + { + return ( + asset.native() ? "XRP" + : asset.holds() ? "IOU" + : asset.holds() ? "MPT" + : "Unknown"); + } + + /** Wrapper to run a series of lifecycle tests for a given asset and loan + * amount + * + * Will be used in the future to vary the loan parameters. For now, it is + * only called once. + * + * Tests a bunch of LoanSet failure conditions before lifecycle. + */ + template + void + testCaseWrapper( + jtx::Env& env, + jtx::MPTTester& mptt, + std::array const& assets, + BrokerInfo const& broker, + Number const& loanAmount, + int interestExponent) + { + using namespace jtx; + using namespace Lending; + + auto const& asset = broker.asset.raw(); + auto const currencyLabel = getCurrencyLabel(asset); + auto const caseLabel = [&]() { + std::stringstream ss; + ss << "Lifecycle: " << loanAmount << " " << currencyLabel + << " Scale interest to: " << interestExponent << " "; + return ss.str(); + }(); + testcase << caseLabel; + + using namespace loan; + using namespace std::chrono_literals; + using d = NetClock::duration; + using tp = NetClock::time_point; + + Account const issuer{"issuer"}; + // For simplicity, lender will be the sole actor for the vault & + // brokers. + Account const lender{"lender"}; + // Borrower only wants to borrow + Account const borrower{"borrower"}; + // Evan will attempt to be naughty + Account const evan{"evan"}; + // Do not fund alice + Account const alice{"alice"}; + + Number const principalRequest = broker.asset(loanAmount).value(); + Number const maxCoveredLoanValue = broker.params.maxCoveredLoanValue(0); + BEAST_EXPECT(maxCoveredLoanValue == 1000 * 100 / 10); + Number const maxCoveredLoanRequest = + broker.asset(maxCoveredLoanValue).value(); + Number const totalVaultRequest = + broker.asset(broker.params.vaultDeposit).value(); + Number const debtMaximumRequest = + broker.asset(broker.params.debtMax).value(); + + auto const loanSetFee = fee(env.current()->fees().base * 2); + + auto const pseudoAcct = [&]() { + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + if (!BEAST_EXPECT(brokerSle)) + return lender; + auto const brokerPseudo = brokerSle->at(sfAccount); + return Account("Broker pseudo-account", brokerPseudo); + }(); + + auto const baseFee = env.current()->fees().base; + + auto badKeylet = keylet::vault(lender.id(), env.seq(lender)); + // Try some failure cases + // flags are checked first + env(set(evan, broker.brokerID, principalRequest, tfLoanSetMask), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(temINVALID_FLAG)); + + // field length validation + // sfData: good length, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + data(std::string(maxDataPayloadLength, 'X')), + loanSetFee, + ter(tefBAD_AUTH)); + // sfData: too long + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + data(std::string(maxDataPayloadLength + 1, 'Y')), + loanSetFee, + ter(temINVALID)); + + // field range validation + // sfOverpaymentFee: good value, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + overpaymentFee(maxOverpaymentFee), + loanSetFee, + ter(tefBAD_AUTH)); + // sfOverpaymentFee: too big + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + overpaymentFee(maxOverpaymentFee + 1), + loanSetFee, + ter(temINVALID)); + + // sfInterestRate: good value, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + interestRate(maxInterestRate), + loanSetFee, + ter(tefBAD_AUTH)); + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + interestRate(TenthBips32(0)), + loanSetFee, + ter(tefBAD_AUTH)); + // sfInterestRate: too big + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + interestRate(maxInterestRate + 1), + loanSetFee, + ter(temINVALID)); + // sfInterestRate: too small + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + interestRate(TenthBips32(-1)), + loanSetFee, + ter(temINVALID)); + + // sfLateInterestRate: good value, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + lateInterestRate(maxLateInterestRate), + loanSetFee, + ter(tefBAD_AUTH)); + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + lateInterestRate(TenthBips32(0)), + loanSetFee, + ter(tefBAD_AUTH)); + // sfLateInterestRate: too big + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + lateInterestRate(maxLateInterestRate + 1), + loanSetFee, + ter(temINVALID)); + // sfLateInterestRate: too small + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + lateInterestRate(TenthBips32(-1)), + loanSetFee, + ter(temINVALID)); + + // sfCloseInterestRate: good value, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + closeInterestRate(maxCloseInterestRate), + loanSetFee, + ter(tefBAD_AUTH)); + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + closeInterestRate(TenthBips32(0)), + loanSetFee, + ter(tefBAD_AUTH)); + // sfCloseInterestRate: too big + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + closeInterestRate(maxCloseInterestRate + 1), + loanSetFee, + ter(temINVALID)); + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + closeInterestRate(TenthBips32(-1)), + loanSetFee, + ter(temINVALID)); + + // sfOverpaymentInterestRate: good value, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + overpaymentInterestRate(maxOverpaymentInterestRate), + loanSetFee, + ter(tefBAD_AUTH)); + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + overpaymentInterestRate(TenthBips32(0)), + loanSetFee, + ter(tefBAD_AUTH)); + // sfOverpaymentInterestRate: too big + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + overpaymentInterestRate(maxOverpaymentInterestRate + 1), + loanSetFee, + ter(temINVALID)); + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + overpaymentInterestRate(TenthBips32(-1)), + loanSetFee, + ter(temINVALID)); + + // sfPaymentTotal: good value, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + paymentTotal(LoanSet::minPaymentTotal), + loanSetFee, + ter(tefBAD_AUTH)); + // sfPaymentTotal: too small (there is no max) + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + paymentTotal(LoanSet::minPaymentTotal - 1), + loanSetFee, + ter(temINVALID)); + + // sfPaymentInterval: good value, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + paymentInterval(LoanSet::minPaymentInterval), + loanSetFee, + ter(tefBAD_AUTH)); + // sfPaymentInterval: too small (there is no max) + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + paymentInterval(LoanSet::minPaymentInterval - 1), + loanSetFee, + ter(temINVALID)); + + // sfGracePeriod: good value, bad account + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, borrower), + paymentInterval(LoanSet::minPaymentInterval * 2), + gracePeriod(LoanSet::minPaymentInterval * 2), + loanSetFee, + ter(tefBAD_AUTH)); + // sfGracePeriod: larger than paymentInterval + env(set(evan, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + paymentInterval(LoanSet::minPaymentInterval * 2), + gracePeriod(LoanSet::minPaymentInterval * 3), + loanSetFee, + ter(temINVALID)); + + // insufficient fee - single sign + env(set(borrower, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + ter(telINSUF_FEE_P)); + // insufficient fee - multisign + env(signers(lender, 2, {{evan, 1}, {borrower, 1}})); + env(signers(borrower, 2, {{evan, 1}, {lender, 1}})); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + msig(evan, lender), + msig(sfCounterpartySignature, evan, borrower), + fee(env.current()->fees().base * 5 - 1), + ter(telINSUF_FEE_P)); + // Bad multisign signatures for borrower (Account) + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + msig(alice, issuer), + msig(sfCounterpartySignature, evan, borrower), + fee(env.current()->fees().base * 5), + ter(tefBAD_SIGNATURE)); + // Bad multisign signatures for issuer (Counterparty) + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + msig(evan, lender), + msig(sfCounterpartySignature, alice, issuer), + fee(env.current()->fees().base * 5 - 1), + ter(tefBAD_SIGNATURE)); + env(signers(lender, none)); + env(signers(borrower, none)); + // multisign sufficient fee, but no signers set up + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + msig(evan, lender), + msig(sfCounterpartySignature, evan, borrower), + fee(env.current()->fees().base * 5), + ter(tefNOT_MULTI_SIGNING)); + // not the broker owner, no counterparty, not signed by broker + // owner + env(set(borrower, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, evan), + loanSetFee, + ter(tefBAD_AUTH)); + // not the broker owner, counterparty is borrower + env(set(evan, broker.brokerID, principalRequest), + counterparty(borrower), + sig(sfCounterpartySignature, borrower), + loanSetFee, + ter(tecNO_PERMISSION)); + // not a LoanBroker object, no counterparty + env(set(lender, badKeylet.key, principalRequest), + sig(sfCounterpartySignature, evan), + loanSetFee, + ter(temBAD_SIGNER)); + // not a LoanBroker object, counterparty is valid + env(set(lender, badKeylet.key, principalRequest), + counterparty(borrower), + sig(sfCounterpartySignature, borrower), + loanSetFee, + ter(tecNO_ENTRY)); + // borrower doesn't exist + env(set(lender, broker.brokerID, principalRequest), + counterparty(alice), + sig(sfCounterpartySignature, alice), + loanSetFee, + ter(terNO_ACCOUNT)); + + // Request more funds than the vault has available + env(set(evan, broker.brokerID, totalVaultRequest + 1), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(tecINSUFFICIENT_FUNDS)); + + // Request more funds than the broker's first-loss capital can + // cover. + env(set(evan, broker.brokerID, maxCoveredLoanRequest + 1), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(tecINSUFFICIENT_FUNDS)); + + // Frozen trust line / locked MPT issuance + // XRP can not be frozen, but run through the loop anyway to test + // the tecLIMIT_EXCEEDED case + { + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + if (!BEAST_EXPECT(brokerSle)) + return; + + auto const vaultPseudo = [&]() { + auto const vaultSle = + env.le(keylet::vault(brokerSle->at(sfVaultID))); + if (!BEAST_EXPECT(vaultSle)) + // This will be wrong, but the test has failed anyway. + return lender; + auto const vaultPseudo = + Account("Vault pseudo-account", vaultSle->at(sfAccount)); + return vaultPseudo; + }(); + + auto const [freeze, deepfreeze, unfreeze, expectedResult] = + [&]() -> std::tuple< + std::function, + std::function, + std::function, + TER> { + // Freeze / lock the asset + std::function empty; + if (broker.asset.native()) + { + // XRP can't be frozen + return std::make_tuple(empty, empty, empty, tesSUCCESS); + } + else if (broker.asset.holds()) + { + auto freeze = [&](Account const& holder) { + env(trust(issuer, holder[iouCurrency](0), tfSetFreeze)); + }; + auto deepfreeze = [&](Account const& holder) { + env(trust( + issuer, + holder[iouCurrency](0), + tfSetFreeze | tfSetDeepFreeze)); + }; + auto unfreeze = [&](Account const& holder) { + env(trust( + issuer, + holder[iouCurrency](0), + tfClearFreeze | tfClearDeepFreeze)); + }; + return std::make_tuple( + freeze, deepfreeze, unfreeze, tecFROZEN); + } + else + { + auto freeze = [&](Account const& holder) { + mptt.set( + {.account = issuer, + .holder = holder, + .flags = tfMPTLock}); + }; + auto unfreeze = [&](Account const& holder) { + mptt.set( + {.account = issuer, + .holder = holder, + .flags = tfMPTUnlock}); + }; + return std::make_tuple(freeze, empty, unfreeze, tecLOCKED); + } + }(); + + // Try freezing the accounts that can't be frozen + if (freeze) + { + for (auto const& account : {vaultPseudo, evan}) + { + // Freeze the account + freeze(account); + + // Try to create a loan with a frozen line + env(set(evan, broker.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(expectedResult)); + + // Unfreeze the account + BEAST_EXPECT(unfreeze); + unfreeze(account); + + // Ensure the line is unfrozen with a request that is fine + // except too it requests more principal than the broker can + // carry + env(set(evan, broker.brokerID, debtMaximumRequest + 1), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(tecLIMIT_EXCEEDED)); + } + } + + // Deep freeze the borrower, which prevents them from receiving + // funds + if (deepfreeze) + { + // Make sure evan has a trust line that so the issuer can + // freeze it. (Don't need to do this for the borrower, + // because LoanSet will create a line to the borrower + // automatically.) + env(trust(evan, issuer[iouCurrency](100'000))); + + for (auto const& account : + {// these accounts can't be frozen, which deep freeze + // implies + vaultPseudo, + evan, + // these accounts can't be deep frozen + lender}) + { + // Freeze evan + deepfreeze(account); + + // Try to create a loan with a deep frozen line + env(set(evan, broker.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(expectedResult)); + + // Unfreeze evan + BEAST_EXPECT(unfreeze); + unfreeze(account); + + // Ensure the line is unfrozen with a request that is fine + // except too it requests more principal than the broker can + // carry + env(set(evan, broker.brokerID, debtMaximumRequest + 1), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(tecLIMIT_EXCEEDED)); + } + } + } + + // Finally! Create a loan + std::string testData; + + auto coverAvailable = + [&env, this](uint256 const& brokerID, Number const& expected) { + if (auto const brokerSle = env.le(keylet::loanbroker(brokerID)); + BEAST_EXPECT(brokerSle)) + { + auto const available = brokerSle->at(sfCoverAvailable); + BEAST_EXPECT(available == expected); + return available; + } + return Number{}; + }; + auto getDefaultInfo = [&env, this]( + LoanState const& state, + BrokerInfo const& broker) { + if (auto const brokerSle = + env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle)) + { + BEAST_EXPECT( + state.loanScale >= + (broker.asset.integral() + ? 0 + : std::max( + broker.vaultScale(env), + state.principalOutstanding.exponent()))); + NumberRoundModeGuard mg(Number::upward); + auto const defaultAmount = roundToAsset( + broker.asset, + std::min( + tenthBipsOfValue( + tenthBipsOfValue( + brokerSle->at(sfDebtTotal), + broker.params.coverRateMin), + broker.params.coverRateLiquidation), + state.totalValue - state.managementFeeOutstanding), + state.loanScale); + return std::make_pair(defaultAmount, brokerSle->at(sfOwner)); + } + return std::make_pair(Number{}, AccountID{}); + }; + auto replenishCover = [&env, &coverAvailable]( + BrokerInfo const& broker, + AccountID const& brokerAcct, + Number const& startingCoverAvailable, + Number const& amountToBeCovered) { + coverAvailable( + broker.brokerID, startingCoverAvailable - amountToBeCovered); + env(loanBroker::coverDeposit( + brokerAcct, + broker.brokerID, + STAmount{broker.asset, amountToBeCovered})); + coverAvailable(broker.brokerID, startingCoverAvailable); + env.close(); + }; + + auto defaultImmediately = [&](std::uint32_t baseFlag, + bool impair = true) { + return [&, impair, baseFlag]( + Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { + // toEndOfLife + // + // Default the loan + + // Initialize values with the current state + auto state = + getCurrentState(env, broker, loanKeylet, verifyLoanStatus); + BEAST_EXPECT(state.flags == baseFlag); + + auto const& broker = verifyLoanStatus.broker; + auto const startingCoverAvailable = coverAvailable( + broker.brokerID, + broker.asset(broker.params.coverDeposit).number()); + + if (impair) + { + // Check the vault + bool const canImpair = canImpairLoan(env, broker, state); + // Impair the loan, if possible + env(manage(lender, loanKeylet.key, tfLoanImpair), + canImpair ? ter(tesSUCCESS) : ter(tecLIMIT_EXCEEDED)); + + if (canImpair) + { + state.flags |= tfLoanImpair; + state.nextPaymentDate = + env.now().time_since_epoch().count(); + + // Once the loan is impaired, it can't be impaired again + env(manage(lender, loanKeylet.key, tfLoanImpair), + ter(tecNO_PERMISSION)); + } + verifyLoanStatus(state); + } + + auto const nextDueDate = tp{d{state.nextPaymentDate}}; + + // Can't default the loan yet. The grace period hasn't + // expired + env(manage(lender, loanKeylet.key, tfLoanDefault), + ter(tecTOO_SOON)); + + // Let some time pass so that the loan can be + // defaulted + env.close(nextDueDate + 60s); + + auto const [amountToBeCovered, brokerAcct] = + getDefaultInfo(state, broker); + + // Default the loan + env(manage(lender, loanKeylet.key, tfLoanDefault)); + env.close(); + + // The LoanBroker just lost some of it's first-loss capital. + // Replenish it. + replenishCover( + broker, + brokerAcct, + startingCoverAvailable, + amountToBeCovered); + + state.flags |= tfLoanDefault; + state.paymentRemaining = 0; + state.totalValue = 0; + state.principalOutstanding = 0; + state.managementFeeOutstanding = 0; + state.nextPaymentDate = 0; + verifyLoanStatus(state); + + // Once a loan is defaulted, it can't be managed + env(manage(lender, loanKeylet.key, tfLoanUnimpair), + ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanImpair), + ter(tecNO_PERMISSION)); + // Can't make a payment on it either + env(pay(borrower, loanKeylet.key, broker.asset(300)), + ter(tecKILLED)); + }; + }; + + auto singlePayment = [&](Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus, + LoanState& state, + STAmount const& payoffAmount, + std::uint32_t numPayments, + std::uint32_t baseFlag, + std::uint32_t txFlags) { + // toEndOfLife + // + verifyLoanStatus(state); + + // Send some bogus pay transactions + env(pay(borrower, + keylet::loan(uint256(0)).key, + broker.asset(10), + txFlags), + ter(temINVALID)); + // broker.asset(80) is less than a single payment, but all these + // checks fail before that matters + env(pay(borrower, loanKeylet.key, broker.asset(-80), txFlags), + ter(temBAD_AMOUNT)); + env(pay(borrower, broker.brokerID, broker.asset(80), txFlags), + ter(tecNO_ENTRY)); + env(pay(evan, loanKeylet.key, broker.asset(80), txFlags), + ter(tecNO_PERMISSION)); + + // TODO: Write a general "isFlag" function? See STObject::isFlag. + // Maybe add a static overloaded member? + if (!(state.flags & lsfLoanOverpayment)) + { + // If the loan does not allow overpayments, send a payment that + // tries to make an overpayment. Do not include `txFlags`, so we + // don't end up duplicating the next test transaction. + env(pay(borrower, + loanKeylet.key, + STAmount{ + broker.asset, + state.periodicPayment * Number{15, -1}}, + tfLoanOverpayment), + fee(XRPAmount{ + baseFee * + (Number{15, -1} / loanPaymentsPerFeeIncrement + 1)}), + ter(temINVALID_FLAG)); + } + // Try to send a payment marked as multiple mutually exclusive + // payment types. Do not include `txFlags`, so we don't duplicate + // the prior test transaction. + env(pay(borrower, + loanKeylet.key, + broker.asset(state.periodicPayment * 2), + tfLoanLatePayment | tfLoanFullPayment), + ter(temINVALID_FLAG)); + env(pay(borrower, + loanKeylet.key, + broker.asset(state.periodicPayment * 2), + tfLoanLatePayment | tfLoanOverpayment), + ter(temINVALID_FLAG)); + env(pay(borrower, + loanKeylet.key, + broker.asset(state.periodicPayment * 2), + tfLoanOverpayment | tfLoanFullPayment), + ter(temINVALID_FLAG)); + env(pay(borrower, + loanKeylet.key, + broker.asset(state.periodicPayment * 2), + tfLoanLatePayment | tfLoanOverpayment | tfLoanFullPayment), + ter(temINVALID_FLAG)); + + { + auto const otherAsset = broker.asset.raw() == assets[0].raw() + ? assets[1] + : assets[0]; + env(pay(borrower, loanKeylet.key, otherAsset(100), txFlags), + ter(tecWRONG_ASSET)); + } + + // Amount doesn't cover a single payment + env(pay(borrower, + loanKeylet.key, + STAmount{broker.asset, 1}, + txFlags), + ter(tecINSUFFICIENT_PAYMENT)); + + // Get the balance after these failed transactions take + // fees + auto const borrowerBalanceBeforePayment = + env.balance(borrower, broker.asset); + + BEAST_EXPECT(payoffAmount > state.principalOutstanding); + // Try to pay a little extra to show that it's _not_ + // taken + auto const transactionAmount = payoffAmount + broker.asset(10); + + // Send a transaction that tries to pay more than the borrowers's + // balance + XRPAmount const badFee{ + baseFee * + (borrowerBalanceBeforePayment.number() * 2 / + state.periodicPayment / loanPaymentsPerFeeIncrement + + 1)}; + env(pay(borrower, + loanKeylet.key, + STAmount{ + broker.asset, + borrowerBalanceBeforePayment.number() * 2}, + txFlags), + fee(badFee), + ter(tecINSUFFICIENT_FUNDS)); + + XRPAmount const goodFee{ + baseFee * (numPayments / loanPaymentsPerFeeIncrement + 1)}; + env(pay(borrower, loanKeylet.key, transactionAmount, txFlags), + fee(goodFee)); + + env.close(); + + // log << env.meta()->getJson() << std::endl; + + // Need to account for fees if the loan is in XRP + PrettyAmount adjustment = broker.asset(0); + if (broker.asset.native()) + { + adjustment = badFee + goodFee; + } + + state.paymentRemaining = 0; + state.principalOutstanding = 0; + state.totalValue = 0; + state.managementFeeOutstanding = 0; + state.previousPaymentDate = state.nextPaymentDate + + state.paymentInterval * (numPayments - 1); + state.nextPaymentDate = 0; + verifyLoanStatus(state); + + verifyLoanStatus.checkPayment( + state.loanScale, + borrower, + borrowerBalanceBeforePayment, + payoffAmount, + adjustment); + + // Can't impair or default a paid off loan + env(manage(lender, loanKeylet.key, tfLoanImpair), + ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanDefault), + ter(tecNO_PERMISSION)); + }; + + auto fullPayment = [&](std::uint32_t baseFlag) { + return [&, baseFlag]( + Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { + // toEndOfLife + // + auto state = + getCurrentState(env, broker, loanKeylet, verifyLoanStatus); + env.close(state.startDate + 20s); + auto const loanAge = (env.now() - state.startDate).count(); + BEAST_EXPECT(loanAge == 30); + + // Full payoff amount will consist of + // 1. principal outstanding (1000) + // 2. accrued interest (at 12%) + // 3. prepayment penalty (closeInterest at 3.6%) + // 4. close payment fee (4) + // Calculate these values without the helper functions + // to verify they're working correctly The numbers in + // the below BEAST_EXPECTs may not hold across assets. + Number const interval = state.paymentInterval; + auto const periodicRate = + interval * Number(12, -2) / secondsInYear; + BEAST_EXPECT( + periodicRate == + Number(2283105022831050, -21, Number::unchecked{})); + STAmount const principalOutstanding{ + broker.asset, state.principalOutstanding}; + STAmount const accruedInterest{ + broker.asset, + state.principalOutstanding * periodicRate * loanAge / + interval}; + BEAST_EXPECT( + accruedInterest == + broker.asset(Number(1141552511415525, -19))); + STAmount const prepaymentPenalty{ + broker.asset, state.principalOutstanding * Number(36, -3)}; + BEAST_EXPECT(prepaymentPenalty == broker.asset(36)); + STAmount const closePaymentFee = broker.asset(4); + auto const payoffAmount = roundToScale( + principalOutstanding + accruedInterest + prepaymentPenalty + + closePaymentFee, + state.loanScale); + BEAST_EXPECT( + payoffAmount == + roundToAsset( + broker.asset, + broker.asset(Number(1040000114155251, -12)).number(), + state.loanScale)); + + // The terms of this loan actually make the early payoff + // more expensive than just making payments + BEAST_EXPECT( + payoffAmount > state.paymentRemaining * + (state.periodicPayment + broker.asset(2).value())); + + singlePayment( + loanKeylet, + verifyLoanStatus, + state, + payoffAmount, + 1, + baseFlag, + tfLoanFullPayment); + }; + }; + + auto combineAllPayments = [&](std::uint32_t baseFlag) { + return [&, baseFlag]( + Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { + // toEndOfLife + // + + auto state = + getCurrentState(env, broker, loanKeylet, verifyLoanStatus); + env.close(); + + // Make all the payments in one transaction + // service fee is 2 + auto const startingPayments = state.paymentRemaining; + auto const rawPayoff = startingPayments * + (state.periodicPayment + broker.asset(2).value()); + STAmount const payoffAmount{broker.asset, rawPayoff}; + BEAST_EXPECT( + payoffAmount == + broker.asset(Number(1024014840139457, -12))); + BEAST_EXPECT(payoffAmount > state.principalOutstanding); + + singlePayment( + loanKeylet, + verifyLoanStatus, + state, + payoffAmount, + state.paymentRemaining, + baseFlag, + 0); + }; + }; + + // There are a lot of fields that can be set on a loan, but most + // of them only affect the "math" when a payment is made. The + // only one that really affects behavior is the + // `tfLoanOverpayment` flag. + lifecycle( + caseLabel, + "Loan overpayment allowed - Impair and Default", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + defaultImmediately(lsfLoanOverpayment)); + + lifecycle( + caseLabel, + "Loan overpayment prohibited - Impair and Default", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + 0, + defaultImmediately(0)); + + lifecycle( + caseLabel, + "Loan overpayment allowed - Default without Impair", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + defaultImmediately(lsfLoanOverpayment, false)); + + lifecycle( + caseLabel, + "Loan overpayment prohibited - Default without Impair", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + 0, + defaultImmediately(0, false)); + + lifecycle( + caseLabel, + "Loan overpayment prohibited - Pay off immediately", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + 0, + fullPayment(0)); + + lifecycle( + caseLabel, + "Loan overpayment allowed - Pay off immediately", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + fullPayment(lsfLoanOverpayment)); + + lifecycle( + caseLabel, + "Loan overpayment prohibited - Combine all payments", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + 0, + combineAllPayments(0)); + + lifecycle( + caseLabel, + "Loan overpayment allowed - Combine all payments", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + combineAllPayments(lsfLoanOverpayment)); + + lifecycle( + caseLabel, + "Loan overpayment prohibited - Make payments", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + 0, + [&](Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { + // toEndOfLife + // + // Draw and make multiple payments + auto state = + getCurrentState(env, broker, loanKeylet, verifyLoanStatus); + BEAST_EXPECT(state.flags == 0); + env.close(); + + verifyLoanStatus(state); + + env.close(state.startDate + 20s); + auto const loanAge = (env.now() - state.startDate).count(); + BEAST_EXPECT(loanAge == 30); + + // Periodic payment amount will consist of + // 1. principal outstanding (1000) + // 2. interest interest rate (at 12%) + // 3. payment interval (600s) + // 4. loan service fee (2) + // Calculate these values without the helper functions + // to verify they're working correctly The numbers in + // the below BEAST_EXPECTs may not hold across assets. + Number const interval = state.paymentInterval; + auto const periodicRate = + interval * Number(12, -2) / secondsInYear; + BEAST_EXPECT( + periodicRate == + Number(2283105022831050, -21, Number::unchecked{})); + STAmount const roundedPeriodicPayment{ + broker.asset, + roundPeriodicPayment( + broker.asset, state.periodicPayment, state.loanScale)}; + + testcase + << currencyLabel << " Payment components: " + << "Payments remaining, rawInterest, rawPrincipal, " + "rawMFee, trackedValueDelta, trackedPrincipalDelta, " + "trackedInterestDelta, trackedMgmtFeeDelta, special"; + + auto const serviceFee = broker.asset(2); + + BEAST_EXPECT( + roundedPeriodicPayment == + roundToScale( + broker.asset( + Number(8333457001162141, -14), Number::upward), + state.loanScale, + Number::upward)); + // 83334570.01162141 + // Include the service fee + STAmount const totalDue = roundToScale( + roundedPeriodicPayment + serviceFee, + state.loanScale, + Number::upward); + // Only check the first payment since the rounding + // may drift as payments are made + BEAST_EXPECT( + totalDue == + roundToScale( + broker.asset( + Number(8533457001162141, -14), Number::upward), + state.loanScale, + Number::upward)); + + { + auto const raw = computeRawLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining, + broker.params.managementFeeRate); + auto const rounded = constructLoanState( + state.totalValue, + state.principalOutstanding, + state.managementFeeOutstanding); + testcase + << currencyLabel + << " Loan starting state: " << state.paymentRemaining + << ", " << raw.interestDue << ", " + << raw.principalOutstanding << ", " + << raw.managementFeeDue << ", " + << rounded.valueOutstanding << ", " + << rounded.principalOutstanding << ", " + << rounded.interestDue << ", " + << rounded.managementFeeDue; + } + + // Try to pay a little extra to show that it's _not_ + // taken + STAmount const transactionAmount = + STAmount{broker.asset, totalDue} + broker.asset(10); + // Only check the first payment since the rounding + // may drift as payments are made + BEAST_EXPECT( + transactionAmount == + roundToScale( + broker.asset( + Number(9533457001162141, -14), Number::upward), + state.loanScale, + Number::upward)); + + auto const initialState = state; + detail::PaymentComponents totalPaid{ + .trackedValueDelta = 0, + .trackedPrincipalDelta = 0, + .trackedManagementFeeDelta = 0}; + Number totalInterestPaid = 0; + std::size_t totalPaymentsMade = 0; + + ripple::LoanState currentTrueState = computeRawLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining, + broker.params.managementFeeRate); + + while (state.paymentRemaining > 0) + { + // Compute the expected principal amount + auto const paymentComponents = + detail::computePaymentComponents( + broker.asset.raw(), + state.loanScale, + state.totalValue, + state.principalOutstanding, + state.managementFeeOutstanding, + state.periodicPayment, + periodicRate, + state.paymentRemaining, + broker.params.managementFeeRate); + + BEAST_EXPECT( + paymentComponents.trackedValueDelta <= + roundedPeriodicPayment); + + ripple::LoanState const nextTrueState = computeRawLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining - 1, + broker.params.managementFeeRate); + detail::LoanStateDeltas const deltas = + currentTrueState - nextTrueState; + + testcase + << currencyLabel + << " Payment components: " << state.paymentRemaining + << ", " << deltas.interest << ", " << deltas.principal + << ", " << deltas.managementFee << ", " + << paymentComponents.trackedValueDelta << ", " + << paymentComponents.trackedPrincipalDelta << ", " + << paymentComponents.trackedInterestPart() << ", " + << paymentComponents.trackedManagementFeeDelta << ", " + << (paymentComponents.specialCase == + detail::PaymentSpecialCase::final + ? "final" + : paymentComponents.specialCase == + detail::PaymentSpecialCase::extra + ? "extra" + : "none"); + + auto const totalDueAmount = STAmount{ + broker.asset, + paymentComponents.trackedValueDelta + + serviceFee.number()}; + + // Due to the rounding algorithms to keep the interest and + // principal in sync with "true" values, the computed amount + // may be a little less than the rounded fixed payment + // amount. For integral types, the difference should be < 3 + // (1 unit for each of the interest and management fee). For + // IOUs, the difference should be after the 8th digit. + Number const diff = totalDue - totalDueAmount; + BEAST_EXPECT( + paymentComponents.specialCase == + detail::PaymentSpecialCase::final || + diff == beast::zero || + (diff > beast::zero && + ((broker.asset.integral() && + (static_cast(diff) < 3)) || + (state.loanScale - diff.exponent() > 13)))); + + BEAST_EXPECT( + paymentComponents.trackedValueDelta == + paymentComponents.trackedPrincipalDelta + + paymentComponents.trackedInterestPart() + + paymentComponents.trackedManagementFeeDelta); + BEAST_EXPECT( + paymentComponents.trackedValueDelta <= + roundedPeriodicPayment); + + BEAST_EXPECT( + state.paymentRemaining < 12 || + roundToAsset( + broker.asset, + deltas.principal, + state.loanScale, + Number::upward) == + roundToScale( + broker.asset( + Number(8333228695260180, -14), + Number::upward), + state.loanScale, + Number::upward)); + BEAST_EXPECT( + paymentComponents.trackedPrincipalDelta >= + beast::zero && + paymentComponents.trackedPrincipalDelta <= + state.principalOutstanding); + BEAST_EXPECT( + paymentComponents.specialCase != + detail::PaymentSpecialCase::final || + paymentComponents.trackedPrincipalDelta == + state.principalOutstanding); + BEAST_EXPECT( + paymentComponents.specialCase == + detail::PaymentSpecialCase::final || + (state.periodicPayment.exponent() - + (deltas.principal + deltas.interest + + deltas.managementFee - state.periodicPayment) + .exponent()) > 14); + + auto const borrowerBalanceBeforePayment = + env.balance(borrower, broker.asset); + + if (canImpairLoan(env, broker, state)) + // Making a payment will unimpair the loan + env(manage(lender, loanKeylet.key, tfLoanImpair)); + + env.close(); + + // Make the payment + env(pay(borrower, loanKeylet.key, transactionAmount)); + + env.close(); + + // Need to account for fees if the loan is in XRP + PrettyAmount adjustment = broker.asset(0); + if (broker.asset.native()) + { + adjustment = env.current()->fees().base; + } + + // Check the result + verifyLoanStatus.checkPayment( + state.loanScale, + borrower, + borrowerBalanceBeforePayment, + totalDueAmount, + adjustment); + + --state.paymentRemaining; + state.previousPaymentDate = state.nextPaymentDate; + if (paymentComponents.specialCase == + detail::PaymentSpecialCase::final) + { + state.paymentRemaining = 0; + state.nextPaymentDate = 0; + } + else + { + state.nextPaymentDate += state.paymentInterval; + } + state.principalOutstanding -= + paymentComponents.trackedPrincipalDelta; + state.managementFeeOutstanding -= + paymentComponents.trackedManagementFeeDelta; + state.totalValue -= paymentComponents.trackedValueDelta; + + verifyLoanStatus(state); + + totalPaid.trackedValueDelta += + paymentComponents.trackedValueDelta; + totalPaid.trackedPrincipalDelta += + paymentComponents.trackedPrincipalDelta; + totalPaid.trackedManagementFeeDelta += + paymentComponents.trackedManagementFeeDelta; + totalInterestPaid += + paymentComponents.trackedInterestPart(); + ++totalPaymentsMade; + + currentTrueState = nextTrueState; + } + + // Loan is paid off + BEAST_EXPECT(state.paymentRemaining == 0); + BEAST_EXPECT(state.principalOutstanding == 0); + + // Make sure all the payments add up + BEAST_EXPECT( + totalPaid.trackedValueDelta == initialState.totalValue); + BEAST_EXPECT( + totalPaid.trackedPrincipalDelta == + initialState.principalOutstanding); + BEAST_EXPECT( + totalPaid.trackedManagementFeeDelta == + initialState.managementFeeOutstanding); + // This is almost a tautology given the previous checks, but + // check it anyway for completeness. + BEAST_EXPECT( + totalInterestPaid == + initialState.totalValue - + (initialState.principalOutstanding + + initialState.managementFeeOutstanding)); + BEAST_EXPECT( + totalPaymentsMade == initialState.paymentRemaining); + + // Can't impair or default a paid off loan + env(manage(lender, loanKeylet.key, tfLoanImpair), + ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanDefault), + ter(tecNO_PERMISSION)); + }); + +#if LOANTODO + // TODO + + /* + LoanPay fails with tecINVARIANT_FAILED error when loan_broker(also + borrower) tries to do the payment. Here's the sceanrio: Create a XRP + loan with loan broker as borrower, loan origination fee and loan service + fee. Loan broker makes the first payment with periodic payment and loan + service fee. + */ + + auto time = [&](std::string label, std::function timed) { + if (!BEAST_EXPECT(timed)) + return; + + using clock_type = std::chrono::steady_clock; + using duration_type = std::chrono::milliseconds; + + auto const start = clock_type::now(); + timed(); + auto const duration = std::chrono::duration_cast( + clock_type::now() - start); + + log << label << " took " << duration.count() << "ms" << std::endl; + + return duration; + }; + + lifecycle( + caseLabel, + "timing", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + [&](Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { + // Estimate optimal values for loanPaymentsPerFeeIncrement and + // loanMaximumPaymentsPerTransaction. + using namespace loan; + + auto const state = + getCurrentState(env, broker, verifyLoanStatus.keylet); + auto const serviceFee = broker.asset(2).value(); + + STAmount const totalDue{ + broker.asset, + roundPeriodicPayment( + broker.asset, + state.periodicPayment + serviceFee, + state.loanScale)}; + + // Make a single payment + time("single payment", [&]() { + env(pay(borrower, loanKeylet.key, totalDue)); + }); + env.close(); + + // Make all but the final payment + auto const numPayments = (state.paymentRemaining - 2); + STAmount const bigPayment{broker.asset, totalDue * numPayments}; + XRPAmount const bigFee{ + baseFee * (numPayments / loanPaymentsPerFeeIncrement + 1)}; + time("ten payments", [&]() { + env(pay(borrower, loanKeylet.key, bigPayment), fee(bigFee)); + }); + env.close(); + + time("final payment", [&]() { + // Make the final payment + env( + pay(borrower, + loanKeylet.key, + totalDue + STAmount{broker.asset, 1})); + }); + env.close(); + }); + + lifecycle( + caseLabel, + "Loan overpayment allowed - Explicit overpayment", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + [&](Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); + + lifecycle( + caseLabel, + "Loan overpayment prohibited - Late payment", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + [&](Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); + + lifecycle( + caseLabel, + "Loan overpayment allowed - Late payment", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + [&](Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); + + lifecycle( + caseLabel, + "Loan overpayment allowed - Late payment and overpayment", + env, + loanAmount, + interestExponent, + lender, + borrower, + evan, + broker, + pseudoAcct, + tfLoanOverpayment, + [&](Keylet const& loanKeylet, + VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); + +#endif + } + + void + testLoanSet() + { + using namespace jtx; + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + struct CaseArgs + { + bool requireAuth = false; + bool authorizeBorrower = false; + int initialXRP = 1'000'000; + }; + + auto const testCase = + [&, this]( + std::function + mptTest, + std::function iouTest, + CaseArgs args = {}) { + Env env(*this, all); + env.fund(XRP(args.initialXRP), issuer, lender, borrower); + env.close(); + if (args.requireAuth) + { + env(fset(issuer, asfRequireAuth)); + env.close(); + } + + // We need two different asset types, MPT and IOU. Prepare MPT + // first + MPTTester mptt{env, issuer, mptInitNoFund}; + + auto const none = LedgerSpecificFlags(0); + mptt.create( + {.flags = tfMPTCanTransfer | tfMPTCanLock | + (args.requireAuth ? tfMPTRequireAuth : none)}); + env.close(); + PrettyAsset mptAsset = mptt.issuanceID(); + mptt.authorize({.account = lender}); + mptt.authorize({.account = borrower}); + env.close(); + if (args.requireAuth) + { + mptt.authorize({.account = issuer, .holder = lender}); + if (args.authorizeBorrower) + mptt.authorize({.account = issuer, .holder = borrower}); + env.close(); + } + + env(pay(issuer, lender, mptAsset(10'000'000))); + env.close(); + + // Prepare IOU + PrettyAsset const iouAsset = issuer[iouCurrency]; + env(trust(lender, iouAsset(10'000'000))); + env(trust(borrower, iouAsset(10'000'000))); + env.close(); + if (args.requireAuth) + { + env(trust(issuer, iouAsset(0), lender, tfSetfAuth)); + env(pay(issuer, lender, iouAsset(10'000'000))); + if (args.authorizeBorrower) + { + env(trust(issuer, iouAsset(0), borrower, tfSetfAuth)); + env(pay(issuer, borrower, iouAsset(10'000))); + } + } + else + { + env(pay(issuer, lender, iouAsset(10'000'000))); + env(pay(issuer, borrower, iouAsset(10'000))); + } + env.close(); + + // Create vaults and loan brokers + std::array const assets{mptAsset, iouAsset}; + std::vector brokers; + for (auto const& asset : assets) + { + brokers.emplace_back( + createVaultAndBroker(env, asset, lender)); + } + + if (mptTest) + (mptTest)(env, brokers[0], mptt); + if (iouTest) + (iouTest)(env, brokers[1]); + }; + + testCase( + [&, this](Env& env, BrokerInfo const& broker, auto&) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("MPT issuer is borrower, issuer submits"); + env(set(issuer, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + + testcase("MPT issuer is borrower, lender submits"); + env(set(lender, broker.brokerID, principalRequest), + counterparty(issuer), + sig(sfCounterpartySignature, issuer), + fee(env.current()->fees().base * 5)); + }, + [&, this](Env& env, BrokerInfo const& broker) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("IOU issuer is borrower, issuer submits"); + env(set(issuer, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + + testcase("IOU issuer is borrower, lender submits"); + env(set(lender, broker.brokerID, principalRequest), + counterparty(issuer), + sig(sfCounterpartySignature, issuer), + fee(env.current()->fees().base * 5)); + }, + CaseArgs{.requireAuth = true}); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, auto&) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("MPT unauthorized borrower, borrower submits"); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + ter{tecNO_AUTH}); + + testcase("MPT unauthorized borrower, lender submits"); + env(set(lender, broker.brokerID, principalRequest), + counterparty(borrower), + sig(sfCounterpartySignature, borrower), + fee(env.current()->fees().base * 5), + ter{tecNO_AUTH}); + }, + [&, this](Env& env, BrokerInfo const& broker) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("IOU unauthorized borrower, borrower submits"); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + ter{tecNO_AUTH}); + + testcase("IOU unauthorized borrower, lender submits"); + env(set(lender, broker.brokerID, principalRequest), + counterparty(borrower), + sig(sfCounterpartySignature, borrower), + fee(env.current()->fees().base * 5), + ter{tecNO_AUTH}); + }, + CaseArgs{.requireAuth = true}); + + auto const [acctReserve, incReserve] = [this]() -> std::pair { + Env env{*this, testable_amendments()}; + return { + env.current()->fees().accountReserve(0).drops() / + DROPS_PER_XRP.drops(), + env.current()->fees().increment.drops() / + DROPS_PER_XRP.drops()}; + }(); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, MPTTester& mptt) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase( + "MPT authorized borrower, borrower submits, borrower has " + "no reserve"); + mptt.authorize( + {.account = borrower, .flags = tfMPTUnauthorize}); + env.close(); + + auto const mptoken = + keylet::mptoken(mptt.issuanceID(), borrower); + auto const sleMPT1 = env.le(mptoken); + BEAST_EXPECT(sleMPT1 == nullptr); + + // Burn some XRP + env(noop(borrower), fee(XRP(acctReserve * 2 + incReserve * 2))); + env.close(); + + // Cannot create loan, not enough reserve to create MPToken + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + ter{tecINSUFFICIENT_RESERVE}); + env.close(); + + // Can create loan now, will implicitly create MPToken + env(pay(issuer, borrower, XRP(incReserve))); + env.close(); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + env.close(); + + auto const sleMPT2 = env.le(mptoken); + BEAST_EXPECT(sleMPT2 != nullptr); + }, + {}, + CaseArgs{.initialXRP = acctReserve * 2 + incReserve * 8 + 1}); + + testCase( + {}, + [&, this](Env& env, BrokerInfo const& broker) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase( + "IOU authorized borrower, borrower submits, borrower has " + "no reserve"); + // Remove trust line from borrower to issuer + env.trust(broker.asset(0), borrower); + env.close(); + + env(pay(borrower, issuer, broker.asset(10'000))); + env.close(); + auto const trustline = + keylet::line(borrower, broker.asset.raw().get()); + auto const sleLine1 = env.le(trustline); + BEAST_EXPECT(sleLine1 == nullptr); + + // Burn some XRP + env(noop(borrower), fee(XRP(acctReserve * 2 + incReserve * 2))); + env.close(); + + // Cannot create loan, not enough reserve to create trust line + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + ter{tecNO_LINE_INSUF_RESERVE}); + env.close(); + + // Can create loan now, will implicitly create trust line + env(pay(issuer, borrower, XRP(incReserve))); + env.close(); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + env.close(); + + auto const sleLine2 = env.le(trustline); + BEAST_EXPECT(sleLine2 != nullptr); + }, + CaseArgs{.initialXRP = acctReserve * 2 + incReserve * 8 + 1}); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, MPTTester& mptt) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase( + "MPT authorized borrower, borrower submits, lender has " + "no reserve"); + auto const mptoken = keylet::mptoken(mptt.issuanceID(), lender); + auto const sleMPT1 = env.le(mptoken); + BEAST_EXPECT(sleMPT1 != nullptr); + + env(pay( + lender, issuer, broker.asset(sleMPT1->at(sfMPTAmount)))); + env.close(); + + mptt.authorize({.account = lender, .flags = tfMPTUnauthorize}); + env.close(); + + auto const sleMPT2 = env.le(mptoken); + BEAST_EXPECT(sleMPT2 == nullptr); + + // Burn some XRP + env(noop(lender), fee(XRP(incReserve))); + env.close(); + + // Cannot create loan, not enough reserve to create MPToken + env(set(borrower, broker.brokerID, principalRequest), + loanOriginationFee(broker.asset(1).value()), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + ter{tecINSUFFICIENT_RESERVE}); + env.close(); + + // Can create loan now, will implicitly create MPToken + env(pay(issuer, lender, XRP(incReserve))); + env.close(); + env(set(borrower, broker.brokerID, principalRequest), + loanOriginationFee(broker.asset(1).value()), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + env.close(); + + auto const sleMPT3 = env.le(mptoken); + BEAST_EXPECT(sleMPT3 != nullptr); + }, + {}, + CaseArgs{.initialXRP = acctReserve * 2 + incReserve * 8 + 1}); + + testCase( + {}, + [&, this](Env& env, BrokerInfo const& broker) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase( + "IOU authorized borrower, borrower submits, lender has no " + "reserve"); + // Remove trust line from lender to issuer + env.trust(broker.asset(0), lender); + env.close(); + + auto const trustline = + keylet::line(lender, broker.asset.raw().get()); + auto const sleLine1 = env.le(trustline); + BEAST_EXPECT(sleLine1 != nullptr); + + env( + pay(lender, + issuer, + broker.asset(abs(sleLine1->at(sfBalance).value())))); + env.close(); + auto const sleLine2 = env.le(trustline); + BEAST_EXPECT(sleLine2 == nullptr); + + // Burn some XRP + env(noop(lender), fee(XRP(incReserve))); + env.close(); + + // Cannot create loan, not enough reserve to create trust line + env(set(borrower, broker.brokerID, principalRequest), + loanOriginationFee(broker.asset(1).value()), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + ter{tecNO_LINE_INSUF_RESERVE}); + env.close(); + + // Can create loan now, will implicitly create trust line + env(pay(issuer, lender, XRP(incReserve))); + env.close(); + env(set(borrower, broker.brokerID, principalRequest), + loanOriginationFee(broker.asset(1).value()), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + env.close(); + + auto const sleLine3 = env.le(trustline); + BEAST_EXPECT(sleLine3 != nullptr); + }, + CaseArgs{.initialXRP = acctReserve * 2 + incReserve * 8 + 1}); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, MPTTester& mptt) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("MPT authorized borrower, unauthorized lender"); + auto const mptoken = keylet::mptoken(mptt.issuanceID(), lender); + auto const sleMPT1 = env.le(mptoken); + BEAST_EXPECT(sleMPT1 != nullptr); + + env(pay( + lender, issuer, broker.asset(sleMPT1->at(sfMPTAmount)))); + env.close(); + + mptt.authorize({.account = lender, .flags = tfMPTUnauthorize}); + env.close(); + + auto const sleMPT2 = env.le(mptoken); + BEAST_EXPECT(sleMPT2 == nullptr); + + // Cannot create loan, lender not authorized to receive fee + env(set(borrower, broker.brokerID, principalRequest), + loanOriginationFee(broker.asset(1).value()), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + ter{tecNO_AUTH}); + env.close(); + + // Can create loan without origination fee + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + env.close(); + + // No MPToken for lender - no authorization and no payment + auto const sleMPT3 = env.le(mptoken); + BEAST_EXPECT(sleMPT3 == nullptr); + }, + {}, + CaseArgs{.requireAuth = true, .authorizeBorrower = true}); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, auto&) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("MPT authorized borrower, borrower submits"); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + }, + [&, this](Env& env, BrokerInfo const& broker) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("IOU authorized borrower, borrower submits"); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5)); + }, + CaseArgs{.requireAuth = true, .authorizeBorrower = true}); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, auto&) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("MPT authorized borrower, lender submits"); + env(set(lender, broker.brokerID, principalRequest), + counterparty(borrower), + sig(sfCounterpartySignature, borrower), + fee(env.current()->fees().base * 5)); + }, + [&, this](Env& env, BrokerInfo const& broker) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + + testcase("IOU authorized borrower, lender submits"); + env(set(lender, broker.brokerID, principalRequest), + counterparty(borrower), + sig(sfCounterpartySignature, borrower), + fee(env.current()->fees().base * 5)); + }, + CaseArgs{.requireAuth = true, .authorizeBorrower = true}); + + jtx::Account const alice{"alice"}; + jtx::Account const bella{"bella"}; + auto const msigSetup = [&](Env& env, Account const& account) { + Json::Value tx1 = signers(account, 2, {{alice, 1}, {bella, 1}}); + env(tx1); + env.close(); + }; + + testCase( + [&, this](Env& env, BrokerInfo const& broker, auto&) { + using namespace loan; + msigSetup(env, lender); + Number const principalRequest = broker.asset(1'000).value(); + + testcase( + "MPT authorized borrower, borrower submits, lender " + "multisign"); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + msig(sfCounterpartySignature, alice, bella), + fee(env.current()->fees().base * 5)); + }, + [&, this](Env& env, BrokerInfo const& broker) { + using namespace loan; + msigSetup(env, lender); + Number const principalRequest = broker.asset(1'000).value(); + + testcase( + "IOU authorized borrower, borrower submits, lender " + "multisign"); + env(set(borrower, broker.brokerID, principalRequest), + counterparty(lender), + msig(sfCounterpartySignature, alice, bella), + fee(env.current()->fees().base * 5)); + }, + CaseArgs{.requireAuth = true, .authorizeBorrower = true}); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, auto&) { + using namespace loan; + msigSetup(env, borrower); + Number const principalRequest = broker.asset(1'000).value(); + + testcase( + "MPT authorized borrower, lender submits, borrower " + "multisign"); + env(set(lender, broker.brokerID, principalRequest), + counterparty(borrower), + msig(sfCounterpartySignature, alice, bella), + fee(env.current()->fees().base * 5)); + }, + [&, this](Env& env, BrokerInfo const& broker) { + using namespace loan; + msigSetup(env, borrower); + Number const principalRequest = broker.asset(1'000).value(); + + testcase( + "IOU authorized borrower, lender submits, borrower " + "multisign"); + env(set(lender, broker.brokerID, principalRequest), + counterparty(borrower), + msig(sfCounterpartySignature, alice, bella), + fee(env.current()->fees().base * 5)); + }, + CaseArgs{.requireAuth = true, .authorizeBorrower = true}); + } + + void + testLifecycle() + { + testcase("Lifecycle"); + using namespace jtx; + + // Create 3 loan brokers: one for XRP, one for an IOU, and one for + // an MPT. That'll require three corresponding SAVs. + Env env(*this, all); + + Account const issuer{"issuer"}; + // For simplicity, lender will be the sole actor for the vault & + // brokers. + Account const lender{"lender"}; + // Borrower only wants to borrow + Account const borrower{"borrower"}; + // Evan will attempt to be naughty + Account const evan{"evan"}; + // Do not fund alice + Account const alice{"alice"}; + + // Fund the accounts and trust lines with the same amount so that + // tests can use the same values regardless of the asset. + env.fund(XRP(100'000'000), issuer, noripple(lender, borrower, evan)); + env.close(); + + // Create assets + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + PrettyAsset const iouAsset = issuer[iouCurrency]; + env(trust(lender, iouAsset(10'000'000))); + env(trust(borrower, iouAsset(10'000'000))); + env(trust(evan, iouAsset(10'000'000))); + env(pay(issuer, evan, iouAsset(1'000'000))); + env(pay(issuer, lender, iouAsset(10'000'000))); + // Fund the borrower with enough to cover interest and fees + env(pay(issuer, borrower, iouAsset(10'000))); + env.close(); + + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + // Scale the MPT asset a little bit so we can get some interest + PrettyAsset const mptAsset{mptt.issuanceID(), 100}; + mptt.authorize({.account = lender}); + mptt.authorize({.account = borrower}); + mptt.authorize({.account = evan}); + env(pay(issuer, lender, mptAsset(10'000'000))); + env(pay(issuer, evan, mptAsset(1'000'000))); + // Fund the borrower with enough to cover interest and fees + env(pay(issuer, borrower, mptAsset(10'000))); + env.close(); + + std::array const assets{xrpAsset, mptAsset, iouAsset}; + + // Create vaults and loan brokers + std::vector brokers; + for (auto const& asset : assets) + { + brokers.emplace_back(createVaultAndBroker( + env, + asset, + lender, + BrokerParameters{.data = "spam spam spam spam"})); + } + + // Create and update Loans + for (auto const& broker : brokers) + { + for (int amountExponent = 3; amountExponent >= 3; --amountExponent) + { + Number const loanAmount{1, amountExponent}; + for (int interestExponent = 0; interestExponent >= 0; + --interestExponent) + { + testCaseWrapper( + env, + mptt, + assets, + broker, + loanAmount, + interestExponent); + } + } + + if (auto brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle)) + { + BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 0); + BEAST_EXPECT(brokerSle->at(sfDebtTotal) == 0); + + auto const coverAvailable = brokerSle->at(sfCoverAvailable); + env(loanBroker::coverWithdraw( + lender, + broker.brokerID, + STAmount(broker.asset, coverAvailable))); + env.close(); + + brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle && brokerSle->at(sfCoverAvailable) == 0); + } + // Verify we can delete the loan broker + env(loanBroker::del(lender, broker.brokerID)); + env.close(); + } + } + + void + testSelfLoan() + { + testcase << "Self Loan"; + + using namespace jtx; + using namespace std::chrono_literals; + // Create 3 loan brokers: one for XRP, one for an IOU, and one for + // an MPT. That'll require three corresponding SAVs. + Env env(*this, all); + + Account const issuer{"issuer"}; + // For simplicity, lender will be the sole actor for the vault & + // brokers. + Account const lender{"lender"}; + + // Fund the accounts and trust lines with the same amount so that + // tests can use the same values regardless of the asset. + env.fund(XRP(100'000'000), issuer, noripple(lender)); + env.close(); + + // Use an XRP asset for simplicity + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + + // Create vaults and loan brokers + BrokerInfo broker{createVaultAndBroker(env, xrpAsset, lender)}; + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{1, 3}; + + // The LoanSet json can be created without a counterparty signature, + // but it will not pass preflight + auto createJson = env.json( + set(lender, + broker.brokerID, + broker.asset(principalRequest).value()), + fee(loanSetFee)); + env(createJson, ter(temBAD_SIGNER)); + + // Adding an empty counterparty signature object also fails, but + // at the RPC level. + createJson = env.json( + createJson, json(sfCounterpartySignature, Json::objectValue)); + env(createJson, ter(telENV_RPC_FAILED)); + + if (auto const jt = env.jt(createJson); BEAST_EXPECT(jt.stx)) + { + Serializer s; + jt.stx->add(s); + auto const jr = env.rpc("submit", strHex(s.slice())); + + BEAST_EXPECT(jr.isMember(jss::result)); + auto const jResult = jr[jss::result]; + BEAST_EXPECT(jResult[jss::error] == "invalidTransaction"); + BEAST_EXPECT( + jResult[jss::error_exception] == + "fails local checks: Transaction has bad signature."); + } + + // Copy the transaction signature into the counterparty signature. + Json::Value counterpartyJson{Json::objectValue}; + counterpartyJson[sfTxnSignature] = createJson[sfTxnSignature]; + counterpartyJson[sfSigningPubKey] = createJson[sfSigningPubKey]; + if (!BEAST_EXPECT(!createJson.isMember(jss::Signers))) + counterpartyJson[sfSigners] = createJson[sfSigners]; + + // The duplicated signature works + createJson = env.json( + createJson, json(sfCounterpartySignature, counterpartyJson)); + env(createJson); + + env.close(); + + auto const startDate = env.current()->info().parentCloseTime; + + // Loan is successfully created + { + auto const res = env.rpc("account_objects", lender.human()); + auto const objects = res[jss::result][jss::account_objects]; + + std::map types; + BEAST_EXPECT(objects.size() == 4); + for (auto const& object : objects) + { + ++types[object[sfLedgerEntryType].asString()]; + } + BEAST_EXPECT(types.size() == 4); + for (std::string const type : + {"MPToken", "Vault", "LoanBroker", "Loan"}) + { + BEAST_EXPECT(types[type] == 1); + } + } + auto const loanID = [&]() { + Json::Value params(Json::objectValue); + params[jss::account] = lender.human(); + params[jss::type] = "Loan"; + auto const res = + env.rpc("json", "account_objects", to_string(params)); + auto const objects = res[jss::result][jss::account_objects]; + + BEAST_EXPECT(objects.size() == 1); + + auto const loan = objects[0u]; + BEAST_EXPECT(loan[sfBorrower] == lender.human()); + // soeDEFAULT fields are not returned if they're in the default + // state + BEAST_EXPECT(!loan.isMember(sfCloseInterestRate)); + BEAST_EXPECT(!loan.isMember(sfClosePaymentFee)); + BEAST_EXPECT(loan[sfFlags] == 0); + BEAST_EXPECT(loan[sfGracePeriod] == 60); + BEAST_EXPECT(!loan.isMember(sfInterestRate)); + BEAST_EXPECT(!loan.isMember(sfLateInterestRate)); + BEAST_EXPECT(!loan.isMember(sfLatePaymentFee)); + BEAST_EXPECT(loan[sfLoanBrokerID] == to_string(broker.brokerID)); + BEAST_EXPECT(!loan.isMember(sfLoanOriginationFee)); + BEAST_EXPECT(loan[sfLoanSequence] == 1); + BEAST_EXPECT(!loan.isMember(sfLoanServiceFee)); + BEAST_EXPECT( + loan[sfNextPaymentDueDate] == loan[sfStartDate].asUInt() + 60); + BEAST_EXPECT(!loan.isMember(sfOverpaymentFee)); + BEAST_EXPECT(!loan.isMember(sfOverpaymentInterestRate)); + BEAST_EXPECT(loan[sfPaymentInterval] == 60); + BEAST_EXPECT(loan[sfPeriodicPayment] == "1000000000"); + BEAST_EXPECT(loan[sfPaymentRemaining] == 1); + BEAST_EXPECT(!loan.isMember(sfPreviousPaymentDate)); + BEAST_EXPECT(loan[sfPrincipalOutstanding] == "1000000000"); + BEAST_EXPECT(loan[sfTotalValueOutstanding] == "1000000000"); + BEAST_EXPECT(!loan.isMember(sfLoanScale)); + BEAST_EXPECT( + loan[sfStartDate].asUInt() == + startDate.time_since_epoch().count()); + + return loan["index"].asString(); + }(); + auto const loanKeylet{keylet::loan(uint256{std::string_view(loanID)})}; + + env.close(startDate); + + // Make a payment + env(pay(lender, loanKeylet.key, broker.asset(1000))); + } + + void + testBatchBypassCounterparty() + { + // From FIND-001 + testcase << "Batch Bypass Counterparty"; + + bool const lendingBatchEnabled = !std::any_of( + Batch::disabledTxTypes.begin(), + Batch::disabledTxTypes.end(), + [](auto const& disabled) { return disabled == ttLOAN_BROKER_SET; }); + + using namespace jtx; + using namespace std::chrono_literals; + Env env(*this, all); + + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + BrokerParameters brokerParams; + env.fund(XRP(brokerParams.vaultDeposit * 100), lender, borrower); + env.close(); + + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + + BrokerInfo broker{ + createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{1, 3}; + + auto forgedLoanSet = + set(borrower, broker.brokerID, principalRequest, 0); + + Json::Value randomData{Json::objectValue}; + randomData[jss::SigningPubKey] = Json::StaticString{"2600"}; + Json::Value sigObject{Json::objectValue}; + sigObject[jss::SigningPubKey] = strHex(lender.pk().slice()); + Serializer ss; + ss.add32(HashPrefix::txSign); + parse(randomData).addWithoutSigningFields(ss); + auto const sig = ripple::sign(borrower.pk(), borrower.sk(), ss.slice()); + sigObject[jss::TxnSignature] = strHex(Slice{sig.data(), sig.size()}); + + forgedLoanSet[Json::StaticString{"CounterpartySignature"}] = sigObject; + + // ? Fails because the lender hasn't signed the tx + env(env.json(forgedLoanSet, fee(loanSetFee)), ter(telENV_RPC_FAILED)); + + auto const seq = env.seq(borrower); + auto const batchFee = batch::calcBatchFee(env, 1, 2); + // ! Should fail because the lender hasn't signed the tx + env(batch::outer(borrower, seq, batchFee, tfAllOrNothing), + batch::inner(forgedLoanSet, seq + 1), + batch::inner(pay(borrower, lender, XRP(1)), seq + 2), + ter(lendingBatchEnabled ? temBAD_SIGNATURE + : temINVALID_INNER_BATCH)); + env.close(); + + // ? Check that the loan was NOT created + { + Json::Value params(Json::objectValue); + params[jss::account] = borrower.human(); + params[jss::type] = "Loan"; + auto const res = + env.rpc("json", "account_objects", to_string(params)); + auto const objects = res[jss::result][jss::account_objects]; + BEAST_EXPECT(objects.size() == 0); + } + } + + void + testWrongMaxDebtBehavior() + { + // From FIND-003 + testcase << "Wrong Max Debt Behavior"; + + using namespace jtx; + using namespace std::chrono_literals; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + + BrokerParameters brokerParams{.debtMax = 0}; + env.fund( + XRP(brokerParams.vaultDeposit * 100), issuer, noripple(lender)); + env.close(); + + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + + BrokerInfo broker{ + createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; + + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle)) + { + BEAST_EXPECT(brokerSle->at(sfDebtMaximum) == 0); + } + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{1, 3}; + + auto createJson = env.json( + set(lender, broker.brokerID, principalRequest), fee(loanSetFee)); + + Json::Value counterpartyJson{Json::objectValue}; + counterpartyJson[sfTxnSignature] = createJson[sfTxnSignature]; + counterpartyJson[sfSigningPubKey] = createJson[sfSigningPubKey]; + if (!BEAST_EXPECT(!createJson.isMember(jss::Signers))) + counterpartyJson[sfSigners] = createJson[sfSigners]; + + createJson = env.json( + createJson, json(sfCounterpartySignature, counterpartyJson)); + env(createJson); + + env.close(); + } + + void + testLoanPayComputePeriodicPaymentValidRateInvariant() + { + // From FIND-012 + testcase << "LoanPay ripple::detail::computePeriodicPayment : " + "valid rate"; + + using namespace jtx; + using namespace std::chrono_literals; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + BrokerParameters brokerParams; + env.fund( + XRP(brokerParams.vaultDeposit * 100), issuer, lender, borrower); + env.close(); + + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + BrokerInfo broker{ + createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{640562, -5}; + + Number const serviceFee{2462611968}; + std::uint32_t const numPayments{4294967295 / 800}; + + auto createJson = env.json( + set(borrower, broker.brokerID, principalRequest), + fee(loanSetFee), + loanServiceFee(serviceFee), + paymentTotal(numPayments), + json(sfCounterpartySignature, Json::objectValue)); + + createJson["CloseInterestRate"] = 55374; + createJson["ClosePaymentFee"] = "3825205248"; + createJson["GracePeriod"] = 0; + createJson["LatePaymentFee"] = "237"; + createJson["LoanOriginationFee"] = "0"; + createJson["OverpaymentFee"] = 35167; + createJson["OverpaymentInterestRate"] = 1360; + createJson["PaymentInterval"] = 727; + + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSequence = brokerStateBefore->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); + // Fails in preclaim because principal requested can't be + // represented as XRP + env(createJson, ter(tecPRECISION_LOSS)); + env.close(); + + BEAST_EXPECT(!env.le(keylet)); + + Number const actualPrincipal{6}; + + createJson[sfPrincipalRequested] = actualPrincipal; + createJson.removeMember(sfSequence.jsonName); + createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); + // Fails in doApply because the payment is too small to be + // represented as XRP. + env(createJson, ter(tecPRECISION_LOSS)); + env.close(); + } + + void + testRPC() + { + // This will expand as more test cases are added. Some functionality + // is tested in other test functions. + testcase("RPC"); + + using namespace jtx; + + Env env(*this, all); + + auto lowerFee = [&]() { + // Run the local fee back down. + while (env.app().getFeeTrack().lowerLocalFee()) + ; + }; + + auto const baseFee = env.current()->fees().base; + + Account const alice{"alice"}; + std::string const borrowerPass = "borrower"; + std::string const borrowerSeed = "ssBRAsLpH4778sLNYC4ik1JBJsBVf"; + Account borrower{borrowerPass, KeyType::ed25519}; + auto const lenderPass = "lender"; + std::string const lenderSeed = "shPTCZGwTEhJrYT8NbcNkeaa8pzPM"; + Account lender{lenderPass, KeyType::ed25519}; + + env.fund(XRP(1'000'000), alice, lender, borrower); + env.close(); + env(noop(lender)); + env(noop(lender)); + env(noop(lender)); + env(noop(lender)); + env(noop(lender)); + env.close(); + + { + testcase("RPC AccountSet"); + Json::Value txJson{Json::objectValue}; + txJson[sfTransactionType] = "AccountSet"; + txJson[sfAccount] = borrower.human(); + + auto const signParams = [&]() { + Json::Value signParams{Json::objectValue}; + signParams[jss::passphrase] = borrowerPass; + signParams[jss::key_type] = "ed25519"; + signParams[jss::tx_json] = txJson; + return signParams; + }(); + auto const jSign = env.rpc("json", "sign", to_string(signParams)); + BEAST_EXPECT( + jSign.isMember(jss::result) && + jSign[jss::result].isMember(jss::tx_json)); + auto txSignResult = jSign[jss::result][jss::tx_json]; + auto txSignBlob = jSign[jss::result][jss::tx_blob].asString(); + txSignResult.removeMember(jss::hash); + + auto const jtx = env.jt(txJson, sig(borrower)); + BEAST_EXPECT(txSignResult == jtx.jv); + + lowerFee(); + auto const jSubmit = env.rpc("submit", txSignBlob); + BEAST_EXPECT( + jSubmit.isMember(jss::result) && + jSubmit[jss::result].isMember(jss::engine_result) && + jSubmit[jss::result][jss::engine_result].asString() == + "tesSUCCESS"); + + lowerFee(); + env(jtx.jv, sig(none), seq(none), fee(none), ter(tefPAST_SEQ)); + } + + { + testcase("RPC LoanSet - illegal signature_target"); + + Json::Value txJson{Json::objectValue}; + txJson[sfTransactionType] = "AccountSet"; + txJson[sfAccount] = borrower.human(); + + auto const borrowerSignParams = [&]() { + Json::Value params{Json::objectValue}; + params[jss::passphrase] = borrowerPass; + params[jss::key_type] = "ed25519"; + params[jss::signature_target] = "Destination"; + params[jss::tx_json] = txJson; + return params; + }(); + auto const jSignBorrower = + env.rpc("json", "sign", to_string(borrowerSignParams)); + BEAST_EXPECT( + jSignBorrower.isMember(jss::result) && + jSignBorrower[jss::result].isMember(jss::error) && + jSignBorrower[jss::result][jss::error] == "invalidParams" && + jSignBorrower[jss::result].isMember(jss::error_message) && + jSignBorrower[jss::result][jss::error_message] == + "Destination"); + } + { + testcase("RPC LoanSet - sign and submit borrower initiated"); + // 1. Borrower creates the transaction + Json::Value txJson{Json::objectValue}; + txJson[sfTransactionType] = "LoanSet"; + txJson[sfAccount] = borrower.human(); + txJson[sfCounterparty] = lender.human(); + txJson[sfLoanBrokerID] = + "FF924CD18A236C2B49CF8E80A351CEAC6A10171DC9F110025646894FEC" + "F83F" + "5C"; + txJson[sfPrincipalRequested] = "100000000"; + txJson[sfPaymentTotal] = 10000; + txJson[sfPaymentInterval] = 3600; + txJson[sfGracePeriod] = 300; + txJson[sfFlags] = 65536; // tfLoanOverpayment + txJson[sfFee] = to_string(24 * baseFee / 10); + + // 2. Borrower signs the transaction + auto const borrowerSignParams = [&]() { + Json::Value params{Json::objectValue}; + params[jss::passphrase] = borrowerPass; + params[jss::key_type] = "ed25519"; + params[jss::tx_json] = txJson; + return params; + }(); + auto const jSignBorrower = + env.rpc("json", "sign", to_string(borrowerSignParams)); + BEAST_EXPECTS( + jSignBorrower.isMember(jss::result) && + jSignBorrower[jss::result].isMember(jss::tx_json), + to_string(jSignBorrower)); + auto const txBorrowerSignResult = + jSignBorrower[jss::result][jss::tx_json]; + auto const txBorrowerSignBlob = + jSignBorrower[jss::result][jss::tx_blob].asString(); + + // 2a. Borrower attempts to submit the transaction. It doesn't + // work + { + lowerFee(); + auto const jSubmitBlob = env.rpc("submit", txBorrowerSignBlob); + BEAST_EXPECT(jSubmitBlob.isMember(jss::result)); + auto const jSubmitBlobResult = jSubmitBlob[jss::result]; + BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json)); + // Transaction fails because the CounterpartySignature is + // missing + BEAST_EXPECT( + jSubmitBlobResult.isMember(jss::engine_result) && + jSubmitBlobResult[jss::engine_result].asString() == + "temBAD_SIGNER"); + } + + // 3. Borrower sends the signed transaction to the lender + // 4. Lender signs the transaction + auto const lenderSignParams = [&]() { + Json::Value params{Json::objectValue}; + params[jss::passphrase] = lenderPass; + params[jss::key_type] = "ed25519"; + params[jss::signature_target] = "CounterpartySignature"; + params[jss::tx_json] = txBorrowerSignResult; + return params; + }(); + auto const jSignLender = + env.rpc("json", "sign", to_string(lenderSignParams)); + BEAST_EXPECT( + jSignLender.isMember(jss::result) && + jSignLender[jss::result].isMember(jss::tx_json)); + auto const txLenderSignResult = + jSignLender[jss::result][jss::tx_json]; + auto const txLenderSignBlob = + jSignLender[jss::result][jss::tx_blob].asString(); + + // 5. Lender submits the signed transaction blob + lowerFee(); + auto const jSubmitBlob = env.rpc("submit", txLenderSignBlob); + BEAST_EXPECT(jSubmitBlob.isMember(jss::result)); + auto const jSubmitBlobResult = jSubmitBlob[jss::result]; + BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json)); + auto const jSubmitBlobTx = jSubmitBlobResult[jss::tx_json]; + // To get far enough to return tecNO_ENTRY means that the + // signatures all validated. Of course the transaction won't + // succeed because no Vault or Broker were created. + BEAST_EXPECTS( + jSubmitBlobResult.isMember(jss::engine_result) && + jSubmitBlobResult[jss::engine_result].asString() == + "tecNO_ENTRY", + to_string(jSubmitBlobResult)); + + BEAST_EXPECT( + !jSubmitBlob.isMember(jss::error) && + !jSubmitBlobResult.isMember(jss::error)); + + // 4-alt. Lender submits the transaction json originally + // received from the Borrower. It gets signed, but is now a + // duplicate, so fails. Borrower could done this instead of + // steps 4 and 5. + lowerFee(); + auto const jSubmitJson = + env.rpc("json", "submit", to_string(lenderSignParams)); + BEAST_EXPECT(jSubmitJson.isMember(jss::result)); + auto const jSubmitJsonResult = jSubmitJson[jss::result]; + BEAST_EXPECT(jSubmitJsonResult.isMember(jss::tx_json)); + auto const jSubmitJsonTx = jSubmitJsonResult[jss::tx_json]; + // Since the previous tx claimed a fee, this duplicate is not + // going anywhere + BEAST_EXPECTS( + jSubmitJsonResult.isMember(jss::engine_result) && + jSubmitJsonResult[jss::engine_result].asString() == + "tefPAST_SEQ", + to_string(jSubmitJsonResult)); + + BEAST_EXPECT( + !jSubmitJson.isMember(jss::error) && + !jSubmitJsonResult.isMember(jss::error)); + + BEAST_EXPECT(jSubmitBlobTx == jSubmitJsonTx); + } + + { + testcase("RPC LoanSet - sign and submit lender initiated"); + // 1. Lender creates the transaction + Json::Value txJson{Json::objectValue}; + txJson[sfTransactionType] = "LoanSet"; + txJson[sfAccount] = lender.human(); + txJson[sfCounterparty] = borrower.human(); + txJson[sfLoanBrokerID] = + "FF924CD18A236C2B49CF8E80A351CEAC6A10171DC9F110025646894FEC" + "F83F" + "5C"; + txJson[sfPrincipalRequested] = "100000000"; + txJson[sfPaymentTotal] = 10000; + txJson[sfPaymentInterval] = 3600; + txJson[sfGracePeriod] = 300; + txJson[sfFlags] = 65536; // tfLoanOverpayment + txJson[sfFee] = to_string(24 * baseFee / 10); + + // 2. Lender signs the transaction + auto const lenderSignParams = [&]() { + Json::Value params{Json::objectValue}; + params[jss::passphrase] = lenderPass; + params[jss::key_type] = "ed25519"; + params[jss::tx_json] = txJson; + return params; + }(); + auto const jSignLender = + env.rpc("json", "sign", to_string(lenderSignParams)); + BEAST_EXPECT( + jSignLender.isMember(jss::result) && + jSignLender[jss::result].isMember(jss::tx_json)); + auto const txLenderSignResult = + jSignLender[jss::result][jss::tx_json]; + auto const txLenderSignBlob = + jSignLender[jss::result][jss::tx_blob].asString(); + + // 2a. Lender attempts to submit the transaction. It doesn't + // work + { + lowerFee(); + auto const jSubmitBlob = env.rpc("submit", txLenderSignBlob); + BEAST_EXPECT(jSubmitBlob.isMember(jss::result)); + auto const jSubmitBlobResult = jSubmitBlob[jss::result]; + BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json)); + // Transaction fails because the CounterpartySignature is + // missing + BEAST_EXPECT( + jSubmitBlobResult.isMember(jss::engine_result) && + jSubmitBlobResult[jss::engine_result].asString() == + "temBAD_SIGNER"); + } + + // 3. Lender sends the signed transaction to the Borrower + // 4. Borrower signs the transaction + auto const borrowerSignParams = [&]() { + Json::Value params{Json::objectValue}; + params[jss::passphrase] = borrowerPass; + params[jss::key_type] = "ed25519"; + params[jss::signature_target] = "CounterpartySignature"; + params[jss::tx_json] = txLenderSignResult; + return params; + }(); + auto const jSignBorrower = + env.rpc("json", "sign", to_string(borrowerSignParams)); + BEAST_EXPECT( + jSignBorrower.isMember(jss::result) && + jSignBorrower[jss::result].isMember(jss::tx_json)); + auto const txBorrowerSignResult = + jSignBorrower[jss::result][jss::tx_json]; + auto const txBorrowerSignBlob = + jSignBorrower[jss::result][jss::tx_blob].asString(); + + // 5. Borrower submits the signed transaction blob + lowerFee(); + auto const jSubmitBlob = env.rpc("submit", txBorrowerSignBlob); + BEAST_EXPECT(jSubmitBlob.isMember(jss::result)); + auto const jSubmitBlobResult = jSubmitBlob[jss::result]; + BEAST_EXPECT(jSubmitBlobResult.isMember(jss::tx_json)); + auto const jSubmitBlobTx = jSubmitBlobResult[jss::tx_json]; + // To get far enough to return tecNO_ENTRY means that the + // signatures all validated. Of course the transaction won't + // succeed because no Vault or Broker were created. + BEAST_EXPECTS( + jSubmitBlobResult.isMember(jss::engine_result) && + jSubmitBlobResult[jss::engine_result].asString() == + "tecNO_ENTRY", + to_string(jSubmitBlobResult)); + + BEAST_EXPECT( + !jSubmitBlob.isMember(jss::error) && + !jSubmitBlobResult.isMember(jss::error)); + + // 4-alt. Borrower submits the transaction json originally + // received from the Lender. It gets signed, but is now a + // duplicate, so fails. Lender could done this instead of steps + // 4 and 5. + lowerFee(); + auto const jSubmitJson = + env.rpc("json", "submit", to_string(borrowerSignParams)); + BEAST_EXPECT(jSubmitJson.isMember(jss::result)); + auto const jSubmitJsonResult = jSubmitJson[jss::result]; + BEAST_EXPECT(jSubmitJsonResult.isMember(jss::tx_json)); + auto const jSubmitJsonTx = jSubmitJsonResult[jss::tx_json]; + // Since the previous tx claimed a fee, this duplicate is not + // going anywhere + BEAST_EXPECTS( + jSubmitJsonResult.isMember(jss::engine_result) && + jSubmitJsonResult[jss::engine_result].asString() == + "tefPAST_SEQ", + to_string(jSubmitJsonResult)); + + BEAST_EXPECT( + !jSubmitJson.isMember(jss::error) && + !jSubmitJsonResult.isMember(jss::error)); + + BEAST_EXPECT(jSubmitBlobTx == jSubmitJsonTx); + } + } + + void + testServiceFeeOnBrokerDeepFreeze() + { + testcase << "Service Fee On Broker Deep Freeze"; + using namespace jtx; + using namespace loan; + Account const issuer("issuer"); + Account const borrower("borrower"); + Account const broker("broker"); + auto const IOU = issuer["IOU"]; + + for (bool const deepFreeze : {true, false}) + { + Env env(*this); + + auto getCoverBalance = [&](BrokerInfo const& brokerInfo, + auto const& accountField) { + if (auto const le = + env.le(keylet::loanbroker(brokerInfo.brokerID)); + BEAST_EXPECT(le)) + { + auto const account = le->at(accountField); + if (auto const sleLine = env.le(keylet::line(account, IOU)); + BEAST_EXPECT(sleLine)) + { + STAmount balance = sleLine->at(sfBalance); + if (account > issuer.id()) + balance.negate(); + return balance; + } + } + return STAmount{IOU}; + }; + + env.fund(XRP(20'000), issuer, broker, borrower); + env.close(); + + env(trust(broker, IOU(20'000'000))); + env(pay(issuer, broker, IOU(10'000'000))); + env.close(); + + auto const brokerInfo = createVaultAndBroker(env, IOU, broker); + + BEAST_EXPECT(getCoverBalance(brokerInfo, sfAccount) == IOU(1'000)); + + auto const keylet = keylet::loan(brokerInfo.brokerID, 1); + + env(set(borrower, brokerInfo.brokerID, 10'000), + sig(sfCounterpartySignature, broker), + loanServiceFee(IOU(100).value()), + paymentInterval(100), + fee(XRP(100))); + env.close(); + + env(trust(borrower, IOU(20'000'000))); + // The borrower increases their limit and acquires some IOU so + // they can pay interest + env(pay(issuer, borrower, IOU(500))); + env.close(); + + if (auto const le = env.le(keylet::loan(keylet.key)); + BEAST_EXPECT(le)) + { + if (deepFreeze) + { + env(trust( + issuer, + broker["IOU"](0), + tfSetFreeze | tfSetDeepFreeze)); + env.close(); + } + + env(pay(borrower, keylet.key, IOU(10'100)), fee(XRP(100))); + env.close(); + + if (deepFreeze) + { + // The fee goes to the broker pseudo-account + BEAST_EXPECT( + getCoverBalance(brokerInfo, sfAccount) == IOU(1'100)); + BEAST_EXPECT( + getCoverBalance(brokerInfo, sfOwner) == IOU(8'999'000)); + } + else + { + // The fee goes to the broker account + BEAST_EXPECT( + getCoverBalance(brokerInfo, sfOwner) == IOU(8'999'100)); + BEAST_EXPECT( + getCoverBalance(brokerInfo, sfAccount) == IOU(1'000)); + } + } + }; + } + + void + testBasicMath() + { + // Test the functions defined in LendingHelpers.h + testcase("Basic Math"); + + pass(); + } + + void + testIssuerLoan() + { + testcase << "Issuer Loan"; + + using namespace jtx; + using namespace loan; + Account const issuer("issuer"); + Account const borrower = issuer; + Account const lender("lender"); + Env env(*this); + + env.fund(XRP(1'000), issuer, lender); + + std::int64_t constexpr issuerBalance = 10'000'000; + MPTTester asset( + {.env = env, + .issuer = issuer, + .holders = {lender}, + .pay = issuerBalance}); + + BrokerParameters const brokerParams{ + .debtMax = 200, + }; + auto const broker = + createVaultAndBroker(env, asset, lender, brokerParams); + auto const loanSetFee = fee(env.current()->fees().base * 2); + // Create Loan + env(set(borrower, broker.brokerID, 200), + sig(sfCounterpartySignature, lender), + loanSetFee); + env.close(); + // Issuer should not create MPToken + BEAST_EXPECT(!env.le(keylet::mptoken(asset.issuanceID(), issuer))); + // Issuer "borrowed" 200, OutstandingAmount decreased by 200 + BEAST_EXPECT(env.balance(issuer, asset) == asset(-issuerBalance + 200)); + // Pay Loan + auto const loanKeylet = keylet::loan(broker.brokerID, 1); + env(pay(borrower, loanKeylet.key, asset(200))); + env.close(); + // Issuer "re-payed" 200, OutstandingAmount increased by 200 + BEAST_EXPECT(env.balance(issuer, asset) == asset(-issuerBalance)); + } + + void + testInvalidLoanDelete() + { + testcase("Invalid LoanDelete"); + using namespace jtx; + using namespace loan; + + // preflight: temINVALID, LoanID == zero + { + Account const alice{"alice"}; + Env env(*this); + env.fund(XRP(1'000), alice); + env.close(); + env(del(alice, beast::zero), ter(temINVALID)); + } + } + + void + testInvalidLoanManage() + { + testcase("Invalid LoanManage"); + using namespace jtx; + using namespace loan; + + // preflight: temINVALID, LoanID == zero + { + Account const alice{"alice"}; + Env env(*this); + env.fund(XRP(1'000), alice); + env.close(); + env(manage(alice, beast::zero, tfLoanDefault), ter(temINVALID)); + } + } + + void + testInvalidLoanPay() + { + testcase("Invalid LoanPay"); + using namespace jtx; + using namespace loan; + Account const lender{"lender"}; + Account const issuer{"issuer"}; + Account const borrower{"borrower"}; + auto const IOU = issuer["IOU"]; + + // preclaim + Env env(*this); + env.fund(XRP(1'000), lender, issuer, borrower); + env(trust(lender, IOU(10'000'000)), THISLINE); + env(pay(issuer, lender, IOU(5'000'000)), THISLINE); + BrokerInfo brokerInfo{createVaultAndBroker(env, issuer["IOU"], lender)}; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + STAmount const debtMaximumRequest = brokerInfo.asset(1'000).value(); + + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + THISLINE); + + env.close(); + + std::uint32_t const loanSequence = 1; + auto const loanKeylet = keylet::loan(brokerInfo.brokerID, loanSequence); + + env(fset(issuer, asfGlobalFreeze), THISLINE); + env.close(); + + // preclaim: tecFROZEN + env(pay(borrower, loanKeylet.key, debtMaximumRequest), + ter(tecFROZEN), + THISLINE); + env.close(); + + env(fclear(issuer, asfGlobalFreeze), THISLINE); + env.close(); + + auto const pseudoBroker = [&]() -> std::optional { + if (auto brokerSle = + env.le(keylet::loanbroker(brokerInfo.brokerID)); + BEAST_EXPECT(brokerSle)) + { + return Account{"pseudo", brokerSle->at(sfAccount)}; + } + else + { + return std::nullopt; + } + }(); + if (!pseudoBroker) + return; + + // Lender and pseudoaccount must both be frozen + env(trust( + issuer, + lender["IOU"](1'000), + lender, + tfSetFreeze | tfSetDeepFreeze), + THISLINE); + env(trust( + issuer, + (*pseudoBroker)["IOU"](1'000), + *pseudoBroker, + tfSetFreeze | tfSetDeepFreeze), + THISLINE); + env.close(); + + // preclaim: tecFROZEN due to deep frozen + env(pay(borrower, loanKeylet.key, debtMaximumRequest), + ter(tecFROZEN), + THISLINE); + env.close(); + + // Only one needs to be unfrozen + env(trust( + issuer, + lender["IOU"](1'000), + tfClearFreeze | tfClearDeepFreeze), + THISLINE); + env.close(); + + // The payment is late by this point + env(pay(borrower, loanKeylet.key, debtMaximumRequest), + ter(tecEXPIRED), + THISLINE); + env.close(); + env(pay(borrower, + loanKeylet.key, + debtMaximumRequest, + tfLoanLatePayment), + THISLINE); + env.close(); + + // preclaim: tecKILLED + // note that tecKILLED in loanMakePayment() + // doesn't happen because of the preclaim check. + env(pay(borrower, loanKeylet.key, debtMaximumRequest), + ter(tecKILLED), + THISLINE); + } + + void + testInvalidLoanSet() + { + testcase("Invalid LoanSet"); + using namespace jtx; + using namespace loan; + Account const lender{"lender"}; + Account const issuer{"issuer"}; + Account const borrower{"borrower"}; + auto const IOU = issuer["IOU"]; + + auto testWrapper = [&](auto&& test) { + Env env(*this); + env.fund(XRP(1'000), lender, issuer, borrower); + env(trust(lender, IOU(10'000'000))); + env(pay(issuer, lender, IOU(5'000'000))); + BrokerInfo brokerInfo{ + createVaultAndBroker(env, issuer["IOU"], lender)}; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const debtMaximumRequest = brokerInfo.asset(1'000).value(); + test(env, brokerInfo, loanSetFee, debtMaximumRequest); + }; + + // preflight: + testWrapper([&](Env& env, + BrokerInfo const& brokerInfo, + jtx::fee const& loanSetFee, + Number const& debtMaximumRequest) { + // first temBAD_SIGNER: TODO + + // empty/zero broker ID + { + auto jv = set(borrower, uint256{}, debtMaximumRequest); + + auto testZeroBrokerID = [&](std::string const& id, + std::uint32_t flags = 0) { + // empty broker ID + jv[sfLoanBrokerID] = id; + env(jv, + sig(sfCounterpartySignature, lender), + loanSetFee, + txflags(flags), + ter(temINVALID)); + }; + // empty broker ID + testZeroBrokerID(std::string("")); + // zero broker ID + // needs a flag to distinguish the parsed STTx from the prior + // test + testZeroBrokerID(to_string(uint256{}), tfFullyCanonicalSig); + } + + // preflightCheckSigningKey() failure: + // can it happen? the signature is checked before transactor + // executes + + JTx tx = env.jt( + set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee); + STTx local = *(tx.stx); + auto counterpartySig = + local.getFieldObject(sfCounterpartySignature); + auto badPubKey = counterpartySig.getFieldVL(sfSigningPubKey); + badPubKey[20] ^= 0xAA; + counterpartySig.setFieldVL(sfSigningPubKey, badPubKey); + local.setFieldObject(sfCounterpartySignature, counterpartySig); + Json::Value jvResult; + jvResult[jss::tx_blob] = strHex(local.getSerializer().slice()); + auto res = env.rpc("json", "submit", to_string(jvResult))["result"]; + BEAST_EXPECT( + res[jss::error] == "invalidTransaction" && + res[jss::error_exception] == + "fails local checks: Counterparty: Invalid signature."); + }); + + // preclaim: + testWrapper([&](Env& env, + BrokerInfo const& brokerInfo, + jtx::fee const& loanSetFee, + Number const& debtMaximumRequest) { + // canAddHoldingFailure (IOU only, if MPT doesn't have + // MPTCanTransfer set, then can't create Vault/LoanBroker, + // and LoanSet will fail with different error + env(fclear(issuer, asfDefaultRipple)); + env.close(); + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(terNO_RIPPLE)); + }); + + // doApply: + testWrapper([&](Env& env, + BrokerInfo const& brokerInfo, + jtx::fee const& loanSetFee, + Number const& debtMaximumRequest) { + auto const amt = env.balance(borrower) - + env.current()->fees().accountReserve(env.ownerCount(borrower)); + env(pay(borrower, issuer, amt)); + + // tecINSUFFICIENT_RESERVE + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(tecINSUFFICIENT_RESERVE)); + + // addEmptyHolding failure + env(pay(issuer, borrower, amt)); + env(fset(issuer, asfGlobalFreeze)); + env.close(); + + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(tecFROZEN)); + }); + } + + void + testAccountSendMptMinAmountInvariant() + { + // (From FIND-006) + testcase << "LoanSet trigger ripple::accountSendMPT : minimum amount " + "and MPT"; + + using namespace jtx; + using namespace std::chrono_literals; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000), issuer, lender, borrower); + env.close(); + + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + PrettyAsset const mptAsset = mptt.issuanceID(); + mptt.authorize({.account = lender}); + mptt.authorize({.account = borrower}); + env(pay(issuer, lender, mptAsset(2'000'000))); + env(pay(issuer, borrower, mptAsset(1'000))); + env.close(); + + BrokerInfo broker{createVaultAndBroker(env, mptAsset, lender)}; + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{1, 3}; + + auto createJson = env.json( + set(borrower, broker.brokerID, principalRequest), + fee(loanSetFee), + json(sfCounterpartySignature, Json::objectValue)); + + createJson["CloseInterestRate"] = 76671; + createJson["ClosePaymentFee"] = "2061925410"; + createJson["GracePeriod"] = 434; + createJson["InterestRate"] = 50302; + createJson["LateInterestRate"] = 30322; + createJson["LatePaymentFee"] = "294427911"; + createJson["LoanOriginationFee"] = "3250635102"; + createJson["LoanServiceFee"] = "9557386"; + createJson["OverpaymentFee"] = 51249; + createJson["OverpaymentInterestRate"] = 14304; + createJson["PaymentInterval"] = 434; + createJson["PaymentTotal"] = "2891743748"; + createJson["PrincipalRequested"] = "8516.98"; + + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + + createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); + env(createJson, ter(temINVALID)); + env.close(); + } + + void + testLoanPayDebtDecreaseInvariant() + { + // From FIND-007 + testcase << "LoanPay ripple::LoanPay::doApply : debtDecrease " + "rounding good"; + + using namespace jtx; + using namespace std::chrono_literals; + using namespace Lending; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000), issuer, lender, borrower); + env.close(); + + PrettyAsset const iouAsset = issuer[iouCurrency]; + auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); + env(trustLenderTx); + auto trustBorrowerTx = + env.json(trust(borrower, iouAsset(1'000'000'000))); + env(trustBorrowerTx); + auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); + env(payLenderTx); + auto payIssuerTx = pay(issuer, borrower, iouAsset(1'000'000)); + env(payIssuerTx); + env.close(); + + BrokerInfo broker{createVaultAndBroker(env, iouAsset, lender)}; + + using namespace loan; + + auto const baseFee = env.current()->fees().base; + auto const loanSetFee = fee(baseFee * 2); + Number const principalRequest{1, 3}; + + auto createJson = env.json( + set(borrower, broker.brokerID, principalRequest), + fee(loanSetFee), + json(sfCounterpartySignature, Json::objectValue)); + + createJson["ClosePaymentFee"] = "0"; + createJson["GracePeriod"] = 60; + createJson["InterestRate"] = 24346; + createJson["LateInterestRate"] = 65535; + createJson["LatePaymentFee"] = "0"; + createJson["LoanOriginationFee"] = "218"; + createJson["LoanServiceFee"] = "0"; + createJson["PaymentInterval"] = 60; + createJson["PaymentTotal"] = 5678; + createJson["PrincipalRequested"] = "9924.81"; + + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSequence = brokerStateBefore->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); + env(createJson, ter(tesSUCCESS)); + env.close(); + + auto const pseudoAcct = [&]() { + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + if (!BEAST_EXPECT(brokerSle)) + return lender; + auto const brokerPseudo = brokerSle->at(sfAccount); + return Account("Broker pseudo-account", brokerPseudo); + }(); + + VerifyLoanStatus verifyLoanStatus(env, broker, pseudoAcct, keylet); + auto const originalState = getCurrentState(env, broker, keylet); + verifyLoanStatus(originalState); + + Number const payment{3'269'349'176'470'588, -12}; + XRPAmount const payFee{ + baseFee * + ((payment / originalState.periodicPayment) / + loanPaymentsPerFeeIncrement + + 1)}; + auto loanPayTx = env.json( + pay(borrower, keylet.key, STAmount{broker.asset, payment}), + fee(payFee)); + BEAST_EXPECT(to_string(payment) == "3269.349176470588"); + env(loanPayTx, ter(tesSUCCESS)); + env.close(); + + auto const newState = getCurrentState(env, broker, keylet); + BEAST_EXPECT(isRounded( + broker.asset, + newState.managementFeeOutstanding, + originalState.loanScale)); + BEAST_EXPECT( + newState.managementFeeOutstanding < + originalState.managementFeeOutstanding); + BEAST_EXPECT(isRounded( + broker.asset, newState.totalValue, originalState.loanScale)); + BEAST_EXPECT(isRounded( + broker.asset, + newState.principalOutstanding, + originalState.loanScale)); + } + + void + testLoanPayComputePeriodicPaymentValidTotalInterestInvariant() + { + // From FIND-010 + testcase << "ripple::loanComputePaymentParts : valid total interest"; + + using namespace jtx; + using namespace std::chrono_literals; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000), issuer, lender, borrower); + env.close(); + + PrettyAsset const iouAsset = issuer[iouCurrency]; + auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); + env(trustLenderTx); + auto trustBorrowerTx = + env.json(trust(borrower, iouAsset(1'000'000'000))); + env(trustBorrowerTx); + auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); + env(payLenderTx); + auto payIssuerTx = pay(issuer, borrower, iouAsset(1'000'000)); + env(payIssuerTx); + env.close(); + + BrokerInfo broker{createVaultAndBroker(env, iouAsset, lender)}; + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{1, 3}; + auto const startDate = env.now() + 60s; + + auto createJson = env.json( + set(borrower, broker.brokerID, principalRequest), + fee(loanSetFee), + json(sfCounterpartySignature, Json::objectValue)); + + createJson["CloseInterestRate"] = 47299; + createJson["ClosePaymentFee"] = "3985819770"; + createJson["GracePeriod"] = 0; + createJson["InterestRate"] = 92; + createJson["LatePaymentFee"] = "3866894865"; + createJson["LoanOriginationFee"] = "0"; + createJson["LoanServiceFee"] = "2348810240"; + createJson["OverpaymentFee"] = 58545; + createJson["PaymentInterval"] = 60; + createJson["PaymentTotal"] = 1; + createJson["PrincipalRequested"] = "0.000763058"; + + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSequence = brokerStateBefore->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); + env(createJson, ter(tecPRECISION_LOSS)); + env.close(startDate); + + auto loanPayTx = env.json( + pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + loanPayTx["Amount"]["value"] = "0.000281284125490196"; + env(loanPayTx, ter(tecNO_ENTRY)); + env.close(); + } + + void + testDosLoanPay() + { + // From FIND-005 + testcase << "DoS LoanPay"; + + using namespace jtx; + using namespace std::chrono_literals; + using namespace Lending; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000), issuer, lender, borrower); + env.close(); + + PrettyAsset const iouAsset = issuer[iouCurrency]; + env(trust(lender, iouAsset(100'000'000))); + env(trust(borrower, iouAsset(100'000'000))); + env(pay(issuer, lender, iouAsset(10'000'000))); + env(pay(issuer, borrower, iouAsset(1'000))); + env.close(); + + BrokerInfo broker{createVaultAndBroker(env, iouAsset, lender)}; + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{1, 3}; + auto const baseFee = env.current()->fees().base; + + auto createJson = env.json( + set(borrower, broker.brokerID, principalRequest), + fee(loanSetFee), + json(sfCounterpartySignature, Json::objectValue)); + + createJson["ClosePaymentFee"] = "0"; + createJson["GracePeriod"] = 60; + createJson["InterestRate"] = 20930; + createJson["LateInterestRate"] = 77049; + createJson["LatePaymentFee"] = "0"; + createJson["LoanServiceFee"] = "0"; + createJson["OverpaymentFee"] = 7; + createJson["OverpaymentInterestRate"] = 66653; + createJson["PaymentInterval"] = 60; + createJson["PaymentTotal"] = 3239184; + createJson["PrincipalRequested"] = "3959.37"; + + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSequence = brokerStateBefore->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); + env(createJson, ter(tesSUCCESS)); + env.close(); + + auto const stateBefore = getCurrentState(env, broker, keylet); + BEAST_EXPECT(stateBefore.paymentRemaining == 3239184); + BEAST_EXPECT( + stateBefore.paymentRemaining > loanMaximumPaymentsPerTransaction); + + auto loanPayTx = env.json( + pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + Number const amount{395937, -2}; + loanPayTx["Amount"]["value"] = to_string(amount); + XRPAmount const payFee{ + baseFee * + std::int64_t( + amount / stateBefore.periodicPayment / + loanPaymentsPerFeeIncrement + + 1)}; + env(loanPayTx, ter(tesSUCCESS), fee(payFee)); + env.close(); + + auto const stateAfter = getCurrentState(env, broker, keylet); + BEAST_EXPECT( + stateAfter.paymentRemaining == + stateBefore.paymentRemaining - loanMaximumPaymentsPerTransaction); + } + + void + testLoanPayComputePeriodicPaymentValidTotalPrincipalPaidInvariant() + { + // From FIND-009 + testcase << "ripple::loanComputePaymentParts : totalPrincipalPaid " + "rounded"; + + using namespace jtx; + using namespace std::chrono_literals; + using namespace Lending; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000), issuer, lender, borrower); + env.close(); + + PrettyAsset const iouAsset = issuer[iouCurrency]; + auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); + env(trustLenderTx); + auto trustBorrowerTx = + env.json(trust(borrower, iouAsset(1'000'000'000))); + env(trustBorrowerTx); + auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); + env(payLenderTx); + auto payIssuerTx = pay(issuer, borrower, iouAsset(1'000'000)); + env(payIssuerTx); + env.close(); + + BrokerInfo broker{createVaultAndBroker(env, iouAsset, lender)}; + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{1, 3}; + + auto createJson = env.json( + set(borrower, broker.brokerID, principalRequest), + fee(loanSetFee), + json(sfCounterpartySignature, Json::objectValue)); + + createJson["ClosePaymentFee"] = "0"; + createJson["GracePeriod"] = 0; + createJson["InterestRate"] = 24346; + createJson["LateInterestRate"] = 65535; + createJson["LatePaymentFee"] = "0"; + createJson["LoanOriginationFee"] = "218"; + createJson["LoanServiceFee"] = "0"; + createJson["PaymentInterval"] = 60; + createJson["PaymentTotal"] = 5678; + createJson["PrincipalRequested"] = "9924.81"; + + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSequence = brokerStateBefore->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); + env(createJson, ter(tesSUCCESS)); + env.close(); + + auto const baseFee = env.current()->fees().base; + + auto const stateBefore = getCurrentState(env, broker, keylet); + + { + auto loanPayTx = env.json( + pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + Number const amount{3074'745'058'823'529, -12}; + BEAST_EXPECT(to_string(amount) == "3074.745058823529"); + XRPAmount const payFee{ + baseFee * + (amount / stateBefore.periodicPayment / + loanPaymentsPerFeeIncrement + + 1)}; + loanPayTx["Amount"]["value"] = to_string(amount); + env(loanPayTx, fee(payFee), ter(tesSUCCESS)); + env.close(); + } + + { + auto loanPayTx = env.json( + pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + Number const amount{6732'118'170'944'051, -12}; + BEAST_EXPECT(to_string(amount) == "6732.118170944051"); + XRPAmount const payFee{ + baseFee * + (amount / stateBefore.periodicPayment / + loanPaymentsPerFeeIncrement + + 1)}; + loanPayTx["Amount"]["value"] = to_string(amount); + env(loanPayTx, fee(payFee), ter(tesSUCCESS)); + env.close(); + } + + auto const stateAfter = getCurrentState(env, broker, keylet); + // Total interest outstanding is non-negative + BEAST_EXPECT(stateAfter.totalValue >= stateAfter.principalOutstanding); + // Principal paid is non-negative + BEAST_EXPECT( + stateBefore.principalOutstanding >= + stateAfter.principalOutstanding); + // Total value change is non-negative + BEAST_EXPECT(stateBefore.totalValue >= stateAfter.totalValue); + // Value delta is larger or same as principal delta (meaning + // non-negative interest paid) + BEAST_EXPECT( + (stateBefore.totalValue - stateAfter.totalValue) >= + (stateBefore.principalOutstanding - + stateAfter.principalOutstanding)); + } + + void + testLoanPayComputePeriodicPaymentValidTotalInterestPaidInvariant() + { + // From FIND-008 + testcase << "ripple::loanComputePaymentParts : loanValueChange rounded"; + + using namespace jtx; + using namespace std::chrono_literals; + using namespace Lending; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000), issuer, lender, borrower); + env.close(); + + PrettyAsset const iouAsset = issuer[iouCurrency]; + auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); + env(trustLenderTx); + auto trustBorrowerTx = + env.json(trust(borrower, iouAsset(1'000'000'000))); + env(trustBorrowerTx); + auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); + env(payLenderTx); + auto payIssuerTx = pay(issuer, borrower, iouAsset(10'000'000)); + env(payIssuerTx); + env.close(); + + BrokerInfo broker{createVaultAndBroker(env, iouAsset, lender)}; + { + auto const coverDepositValue = + broker.asset(broker.params.coverDeposit * 10).value(); + env(loanBroker::coverDeposit( + lender, broker.brokerID, coverDepositValue)); + env.close(); + } + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest{1, 3}; + + auto createJson = env.json( + set(borrower, broker.brokerID, principalRequest), + fee(loanSetFee), + json(sfCounterpartySignature, Json::objectValue)); + + createJson["ClosePaymentFee"] = "0"; + createJson["GracePeriod"] = 0; + createJson["InterestRate"] = 12833; + createJson["LateInterestRate"] = 77048; + createJson["LatePaymentFee"] = "0"; + createJson["LoanOriginationFee"] = "218"; + createJson["LoanServiceFee"] = "0"; + createJson["PaymentInterval"] = 752; + createJson["PaymentTotal"] = 5678; + createJson["PrincipalRequested"] = "9924.81"; + + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSequence = brokerStateBefore->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); + env(createJson, ter(tesSUCCESS)); + env.close(); + + auto const baseFee = env.current()->fees().base; + + auto const stateBefore = getCurrentState(env, broker, keylet); + BEAST_EXPECT(stateBefore.paymentRemaining == 5678); + BEAST_EXPECT( + stateBefore.paymentRemaining > loanMaximumPaymentsPerTransaction); + + auto loanPayTx = env.json( + pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + Number const amount{9924'81, -2}; + BEAST_EXPECT(to_string(amount) == "9924.81"); + XRPAmount const payFee{ + baseFee * + (amount / stateBefore.periodicPayment / + loanPaymentsPerFeeIncrement + + 1)}; + loanPayTx["Amount"]["value"] = to_string(amount); + env(loanPayTx, fee(payFee), ter(tesSUCCESS)); + env.close(); + + auto const stateAfter = getCurrentState(env, broker, keylet); + BEAST_EXPECT( + stateAfter.paymentRemaining == + stateBefore.paymentRemaining - loanMaximumPaymentsPerTransaction); + } + + void + testLoanNextPaymentDueDateOverflow() + { + // For FIND-013 + testcase << "Prevent nextPaymentDueDate overflow"; + + using namespace jtx; + using namespace std::chrono_literals; + using namespace Lending; + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000), issuer, lender, borrower); + env.close(); + + PrettyAsset const iouAsset = issuer[iouCurrency]; + auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); + env(trustLenderTx); + auto trustBorrowerTx = + env.json(trust(borrower, iouAsset(1'000'000'000))); + env(trustBorrowerTx); + auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); + env(payLenderTx); + auto payIssuerTx = pay(issuer, borrower, iouAsset(10'000'000)); + env(payIssuerTx); + env.close(); + + BrokerParameters const brokerParams{ + .debtMax = Number{0}, .coverRateMin = TenthBips32{1}}; + BrokerInfo broker{ + createVaultAndBroker(env, iouAsset, lender, brokerParams)}; + + using namespace loan; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + + using timeType = decltype(sfNextPaymentDueDate)::type::value_type; + static_assert(std::is_same_v); + timeType constexpr maxTime = std::numeric_limits::max(); + static_assert(maxTime == 4'294'967'295); + + auto const baseJson = [&]() { + auto createJson = env.json( + set(borrower, broker.brokerID, Number{55524'81, -2}), + fee(loanSetFee), + closePaymentFee(0), + gracePeriod(0), + interestRate(TenthBips32(12833)), + lateInterestRate(TenthBips32(77048)), + latePaymentFee(0), + loanOriginationFee(218), + json(sfCounterpartySignature, Json::objectValue)); + + createJson.removeMember(sfSequence.getJsonName()); + + return createJson; + }(); + + auto const baseFee = env.current()->fees().base; + + auto parentCloseTime = [&]() { + return env.current()->parentCloseTime().time_since_epoch().count(); + }; + auto maxLoanTime = [&]() { + auto const startDate = parentCloseTime(); + + BEAST_EXPECT(startDate >= 50); + + return maxTime - startDate; + }; + + { + // straight-up overflow: interval + auto const interval = maxLoanTime() + 1; + auto const total = 1; + auto createJson = env.json( + baseJson, paymentInterval(interval), paymentTotal(total)); + + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tecKILLED)); + env.close(); + } + { + // straight-up overflow: total + // min interval is 60 + auto const interval = 60; + auto const total = maxLoanTime() + 1; + auto createJson = env.json( + baseJson, paymentInterval(interval), paymentTotal(total)); + + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tecKILLED)); + env.close(); + } + { + // straight-up overflow: grace period + // min interval is 60 + auto const interval = maxLoanTime() + 1; + auto const total = 1; + auto const grace = interval; + auto createJson = env.json( + baseJson, + paymentInterval(interval), + paymentTotal(total), + gracePeriod(grace)); + + // The grace period can't be larger than the interval. + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tecKILLED)); + env.close(); + } + { + // Overflow with multiplication of a few large intervals + auto const interval = 1'000'000'000; + auto const total = 10; + auto createJson = env.json( + baseJson, paymentInterval(interval), paymentTotal(total)); + + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tecKILLED)); + env.close(); + } + { + // Overflow with multiplication of many small payments + // min interval is 60 + auto const interval = 60; + auto const total = 1'000'000'000; + auto createJson = env.json( + baseJson, paymentInterval(interval), paymentTotal(total)); + + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tecKILLED)); + env.close(); + } + { + // Overflow with an absurdly large grace period + // min interval is 60 + auto const total = 60; + auto const interval = (maxLoanTime() - total) / total; + auto const grace = interval; + auto createJson = env.json( + baseJson, + paymentInterval(interval), + paymentTotal(total), + gracePeriod(grace)); + + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tecKILLED)); + env.close(); + } + { + // Start date when the ledger is closed will be larger + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSequence = brokerStateBefore->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + auto const grace = 100; + auto const interval = maxLoanTime() - grace; + auto const total = 1; + auto createJson = env.json( + baseJson, + paymentInterval(interval), + paymentTotal(total), + gracePeriod(grace)); + + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tesSUCCESS)); + env.close(); + + // The transaction is killed in the closed ledger + auto const meta = env.meta(); + if (BEAST_EXPECT(meta)) + { + BEAST_EXPECT(meta->at(sfTransactionResult) == tecKILLED); + } + + // If the transaction had succeeded, the loan would exist + auto const loanSle = env.le(keylet); + // but it doesn't + BEAST_EXPECT(!loanSle); + } + { + // Start date when the ledger is closed will be larger + auto const brokerStateBefore = + env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSequence = brokerStateBefore->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + auto const closeStartDate = (parentCloseTime() / 10 + 1) * 10; + auto const grace = 5'000; + auto const interval = maxTime - closeStartDate - grace; + auto const total = 1; + auto createJson = env.json( + baseJson, + paymentInterval(interval), + paymentTotal(total), + gracePeriod(grace)); + + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tesSUCCESS)); + env.close(); + + // The transaction succeeds in the closed ledger + auto const meta = env.meta(); + if (BEAST_EXPECT(meta)) + { + BEAST_EXPECT(meta->at(sfTransactionResult) == tesSUCCESS); + } + + // This loan exists + auto const afterState = getCurrentState(env, broker, keylet); + BEAST_EXPECT(afterState.nextPaymentDate == maxTime - grace); + BEAST_EXPECT(afterState.previousPaymentDate == 0); + BEAST_EXPECT(afterState.paymentRemaining == 1); + } + + { + // Ensure the borrower has funds to pay back the loan + env(pay(issuer, borrower, iouAsset(Number{1'055'524'81, -2}))); + + // Start date when the ledger is closed will be larger + auto const closeStartDate = (parentCloseTime() / 10 + 1) * 10; + auto const grace = 5'000; + auto const maxLoanTime = maxTime - closeStartDate - grace; + auto const total = [&]() { + if (maxLoanTime % 5 == 0) + return 5; + if (maxLoanTime % 3 == 0) + return 3; + if (maxLoanTime % 2 == 0) + return 2; + return 0; + }(); + if (!BEAST_EXPECT(total != 0)) + return; + + auto const brokerState = + env.le(keylet::loanbroker(broker.brokerID)); + // Intentionally shadow the outer values + auto const loanSequence = brokerState->at(sfLoanSequence); + auto const keylet = keylet::loan(broker.brokerID, loanSequence); + + auto const interval = maxLoanTime / total; + auto createJson = env.json( + baseJson, + paymentInterval(interval), + paymentTotal(total), + gracePeriod(grace)); + + env(createJson, + sig(sfCounterpartySignature, lender), + ter(tesSUCCESS)); + env.close(); + + // This loan exists + auto const beforeState = getCurrentState(env, broker, keylet); + BEAST_EXPECT( + beforeState.nextPaymentDate == closeStartDate + interval); + BEAST_EXPECT(beforeState.previousPaymentDate == 0); + BEAST_EXPECT(beforeState.paymentRemaining == total); + BEAST_EXPECT(beforeState.periodicPayment > 0); + + // pay all but the last payment + Number const payment = beforeState.periodicPayment * (total - 1); + XRPAmount const payFee{ + baseFee * ((total - 1) / loanPaymentsPerFeeIncrement + 1)}; + auto loanPayTx = env.json( + pay(borrower, keylet.key, STAmount{broker.asset, payment}), + fee(payFee)); + env(loanPayTx, ter(tesSUCCESS)); + env.close(); + + // The loan is on the last payment + auto const afterState = getCurrentState(env, broker, keylet); + BEAST_EXPECT(afterState.nextPaymentDate == maxTime - grace); + BEAST_EXPECT( + afterState.previousPaymentDate == maxTime - grace - interval); + BEAST_EXPECT(afterState.paymentRemaining == 1); + } + } + + void + testRequireAuth() + { + testcase("Require Auth - Implicit Pseudo-account authorization"); + using namespace jtx; + using namespace loan; + Account const lender{"lender"}; + Account const issuer{"issuer"}; + Account const borrower{"borrower"}; + Env env(*this); + + env.fund(XRP(100'000), issuer, lender, borrower); + env.close(); + + auto asset = MPTTester({ + .env = env, + .issuer = issuer, + .holders = {lender, borrower}, + .flags = MPTDEXFlags | tfMPTRequireAuth | tfMPTCanClawback | + tfMPTCanLock, + .authHolder = true, + }); + + env(pay(issuer, lender, asset(5'000'000))); + BrokerInfo brokerInfo{createVaultAndBroker(env, asset, lender)}; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + STAmount const debtMaximumRequest = brokerInfo.asset(1'000).value(); + + auto forUnauthAuth = [&](auto&& doTx) { + for (auto const flag : {tfMPTUnauthorize, 0u}) + { + asset.authorize( + {.account = issuer, .holder = borrower, .flags = flag}); + env.close(); + doTx(flag == 0); + env.close(); + } + }; + + // Can't create a loan if the borrower is not authorized + forUnauthAuth([&](bool authorized) { + auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + err); + }); + + std::uint32_t constexpr loanSequence = 1; + auto const loanKeylet = keylet::loan(brokerInfo.brokerID, loanSequence); + + // Can't loan pay if the borrower is not authorized + forUnauthAuth([&](bool authorized) { + auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); + env(pay(borrower, loanKeylet.key, debtMaximumRequest), err); + }); + } + + void + testCoverDepositWithdrawNonTransferableMPT() + { + testcase( + "CoverDeposit and CoverWithdraw reject MPT without CanTransfer"); + using namespace jtx; + using namespace loanBroker; + + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const alice{"alice"}; + + env.fund(XRP(100'000), issuer, alice); + env.close(); + + MPTTester mpt{env, issuer, mptInitNoFund}; + + mpt.create( + {.flags = tfMPTCanTransfer, + .mutableFlags = tmfMPTCanMutateCanTransfer}); + + env.close(); + + PrettyAsset const asset = mpt["MPT"]; + mpt.authorize({.account = alice}); + env.close(); + + // Issuer can fund the holder even if CanTransfer is not set. + env(pay(issuer, alice, asset(100))); + env.close(); + + Vault vault{env}; + auto const [createTx, vaultKeylet] = + vault.create({.owner = alice, .asset = asset}); + env(createTx); + env.close(); + + auto const brokerKeylet = + keylet::loanbroker(alice.id(), env.seq(alice)); + env(set(alice, vaultKeylet.key)); + env.close(); + + auto const brokerSle = env.le(brokerKeylet); + if (!BEAST_EXPECT(brokerSle)) + return; + + Account const pseudoAccount{ + "Loan Broker pseudo-account", brokerSle->at(sfAccount)}; + + // Remove CanTransfer after the broker is set up. + mpt.set({.mutableFlags = tmfMPTClearCanTransfer}); + env.close(); + + // Standard Payment path should forbid third-party transfers. + env(pay(alice, pseudoAccount, asset(1)), ter(tecNO_AUTH)); + env.close(); + + // Cover cannot be transferred to broker account + auto const depositAmount = asset(1); + env(coverDeposit(alice, brokerKeylet.key, depositAmount), + ter{tecNO_AUTH}); + env.close(); + + if (auto const refreshed = env.le(brokerKeylet); + BEAST_EXPECT(refreshed)) + { + BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 0); + env.require(balance(pseudoAccount, asset(0))); + } + + // Set CanTransfer again and transfer some deposit + mpt.set({.mutableFlags = tmfMPTSetCanTransfer}); + env.close(); + + env(coverDeposit(alice, brokerKeylet.key, depositAmount)); + env.close(); + + if (auto const refreshed = env.le(brokerKeylet); + BEAST_EXPECT(refreshed)) + { + BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 1); + env.require(balance(pseudoAccount, depositAmount)); + } + + // Remove CanTransfer after the deposit + mpt.set({.mutableFlags = tmfMPTClearCanTransfer}); + env.close(); + + // Cover cannot be transferred from broker account + env(coverWithdraw(alice, brokerKeylet.key, depositAmount), + ter{tecNO_AUTH}); + env.close(); + + // Set CanTransfer again and withdraw + mpt.set({.mutableFlags = tmfMPTSetCanTransfer}); + env.close(); + + env(coverWithdraw(alice, brokerKeylet.key, depositAmount)); + env.close(); + + if (auto const refreshed = env.le(brokerKeylet); + BEAST_EXPECT(refreshed)) + { + BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 0); + env.require(balance(pseudoAccount, asset(0))); + } + } + +#if LOANTODO + void + testLoanPayLateFullPaymentBypassesPenalties() + { + testcase("LoanPay full payment skips late penalties"); + using namespace jtx; + using namespace loan; + using namespace std::chrono_literals; + + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000), issuer, lender, borrower); + env.close(); + + PrettyAsset const asset = issuer[iouCurrency]; + env(trust(lender, asset(100'000'000))); + env(trust(borrower, asset(100'000'000))); + env(pay(issuer, lender, asset(50'000'000))); + env(pay(issuer, borrower, asset(5'000'000))); + env.close(); + + BrokerInfo broker{createVaultAndBroker(env, asset, lender)}; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + + auto const brokerPreLoan = env.le(keylet::loanbroker(broker.brokerID)); + if (!BEAST_EXPECT(brokerPreLoan)) + return; + + auto const loanSequence = brokerPreLoan->at(sfLoanSequence); + auto const loanKeylet = keylet::loan(broker.brokerID, loanSequence); + + Number const principal = asset(1'000).value(); + Number const serviceFee = asset(2).value(); + Number const lateFee = asset(5).value(); + Number const closeFee = asset(4).value(); + + env(set(borrower, broker.brokerID, principal), + sig(sfCounterpartySignature, lender), + loanServiceFee(serviceFee), + latePaymentFee(lateFee), + closePaymentFee(closeFee), + interestRate(percentageToTenthBips(12)), + lateInterestRate(percentageToTenthBips(24) / 10), + closeInterestRate(percentageToTenthBips(5)), + paymentTotal(12), + paymentInterval(600), + gracePeriod(0), + fee(loanSetFee)); + env.close(); + + auto state1 = getCurrentState(env, broker, loanKeylet); + if (!BEAST_EXPECT(state1.paymentRemaining > 1)) + return; + + using d = NetClock::duration; + using tp = NetClock::time_point; + auto const overdueClose = + tp{d{state1.nextPaymentDate + state1.paymentInterval}}; + env.close(overdueClose); + + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + auto const loanSle = env.le(loanKeylet); + if (!BEAST_EXPECT(brokerSle && loanSle)) + return; + + auto state = getCurrentState(env, broker, loanKeylet); + + TenthBips16 const managementFeeRate{brokerSle->at(sfManagementFeeRate)}; + TenthBips32 const interestRateValue{loanSle->at(sfInterestRate)}; + TenthBips32 const lateInterestRateValue{ + loanSle->at(sfLateInterestRate)}; + TenthBips32 const closeInterestRateValue{ + loanSle->at(sfCloseInterestRate)}; + + Number const closePaymentFeeRounded = roundToAsset( + broker.asset, loanSle->at(sfClosePaymentFee), state.loanScale); + Number const latePaymentFeeRounded = roundToAsset( + broker.asset, loanSle->at(sfLatePaymentFee), state.loanScale); + + auto const roundedLoanState = constructLoanState( + state.totalValue, + state.principalOutstanding, + state.managementFeeOutstanding); + Number const totalInterestOutstanding = roundedLoanState.interestDue; + + auto const periodicRate = + loanPeriodicRate(interestRateValue, state.paymentInterval); + auto const rawLoanState = computeRawLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining, + managementFeeRate); + + auto const parentCloseTime = env.current()->parentCloseTime(); + auto const startDateSeconds = static_cast( + state.startDate.time_since_epoch().count()); + + Number const fullPaymentInterest = computeFullPaymentInterest( + rawLoanState.principalOutstanding, + periodicRate, + parentCloseTime, + state.paymentInterval, + state.previousPaymentDate, + startDateSeconds, + closeInterestRateValue); + + Number const roundedFullInterestAmount = + roundToAsset(broker.asset, fullPaymentInterest, state.loanScale); + Number const roundedFullManagementFee = computeManagementFee( + broker.asset, + roundedFullInterestAmount, + managementFeeRate, + state.loanScale); + Number const roundedFullInterest = + roundedFullInterestAmount - roundedFullManagementFee; + + Number const trackedValueDelta = state.principalOutstanding + + totalInterestOutstanding + state.managementFeeOutstanding; + Number const untrackedManagementFee = closePaymentFeeRounded + + roundedFullManagementFee - state.managementFeeOutstanding; + Number const untrackedInterest = + roundedFullInterest - totalInterestOutstanding; + + Number const baseFullDue = + trackedValueDelta + untrackedInterest + untrackedManagementFee; + BEAST_EXPECT( + baseFullDue == + roundToAsset(broker.asset, baseFullDue, state.loanScale)); + + auto const overdueSeconds = + parentCloseTime.time_since_epoch().count() - state.nextPaymentDate; + if (!BEAST_EXPECT(overdueSeconds > 0)) + return; + + Number const overdueRate = + loanPeriodicRate(lateInterestRateValue, overdueSeconds); + Number const lateInterestRaw = state.principalOutstanding * overdueRate; + Number const lateInterestRounded = + roundToAsset(broker.asset, lateInterestRaw, state.loanScale); + Number const lateManagementFeeRounded = computeManagementFee( + broker.asset, + lateInterestRounded, + managementFeeRate, + state.loanScale); + Number const penaltyDue = lateInterestRounded + + lateManagementFeeRounded + latePaymentFeeRounded; + BEAST_EXPECT(penaltyDue > Number{}); + + auto const balanceBefore = env.balance(borrower, broker.asset).number(); + + STAmount const paymentAmount{broker.asset.raw(), baseFullDue}; + env(pay(borrower, loanKeylet.key, paymentAmount, tfLoanFullPayment)); + env.close(); + + if (auto const meta = env.meta(); BEAST_EXPECT(meta)) + BEAST_EXPECT(meta->at(sfTransactionResult) == tesSUCCESS); + + auto const balanceAfter = env.balance(borrower, broker.asset).number(); + Number const actualPaid = balanceBefore - balanceAfter; + BEAST_EXPECT(actualPaid == baseFullDue); + + Number const expectedWithPenalty = baseFullDue + penaltyDue; + BEAST_EXPECT(expectedWithPenalty > actualPaid); + BEAST_EXPECT(expectedWithPenalty - actualPaid == penaltyDue); + } + + void + testLoanCoverMinimumRoundingExploit() + { + auto testLoanCoverMinimumRoundingExploit = + [&, this](Number const& principalRequest) { + testcase << "LoanBrokerCoverClawback drains cover via rounding" + << " principalRequested=" + << to_string(principalRequest); + + using namespace jtx; + using namespace loan; + using namespace loanBroker; + + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(1'000'000'000), issuer, lender, borrower); + env.close(); + + env(fset(issuer, asfAllowTrustLineClawback)); + env.close(); + + PrettyAsset const asset = issuer[iouCurrency]; + env(trust(lender, asset(2'000'0000))); + env(trust(borrower, asset(2'000'0000))); + env.close(); + + env(pay(issuer, lender, asset(2'000'0000))); + env.close(); + + BrokerParameters brokerParams{ + .debtMax = 0, .coverRateMin = TenthBips32{10'000}}; + BrokerInfo broker{ + createVaultAndBroker(env, asset, lender, brokerParams)}; + + auto const loanSetFee = fee(env.current()->fees().base * 2); + auto createTx = env.jt( + set(borrower, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + paymentInterval(600), + paymentTotal(1), + gracePeriod(60)); + env(createTx); + env.close(); + + auto const brokerBefore = + env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerBefore); + if (!brokerBefore) + return; + + Number const debtOutstanding = brokerBefore->at(sfDebtTotal); + Number const coverAvailableBefore = + brokerBefore->at(sfCoverAvailable); + + BEAST_EXPECT(debtOutstanding > Number{}); + BEAST_EXPECT(coverAvailableBefore > Number{}); + + log << "debt=" << to_string(debtOutstanding) + << " cover_available=" << to_string(coverAvailableBefore); + + env(coverClawback(issuer, 0), loanBrokerID(broker.brokerID)); + env.close(); + + auto const brokerAfter = + env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerAfter); + if (!brokerAfter) + return; + + Number const debtAfter = brokerAfter->at(sfDebtTotal); + // the debt has not changed + BEAST_EXPECT(debtAfter == debtOutstanding); + + Number const coverAvailableAfter = + brokerAfter->at(sfCoverAvailable); + + // since the cover rate min != 0, the cover available should not + // be zero + BEAST_EXPECT(coverAvailableAfter != Number{}); + }; + + // Call the lambda with different principal values + testLoanCoverMinimumRoundingExploit(Number{1, -30}); // 1e-30 units + testLoanCoverMinimumRoundingExploit(Number{1, -20}); // 1e-20 units + testLoanCoverMinimumRoundingExploit(Number{1, -10}); // 1e-10 units + testLoanCoverMinimumRoundingExploit(Number{1, 1}); // 1e-10 units + } +#endif + + void + testPoC_UnsignedUnderflowOnFullPayAfterEarlyPeriodic() + { + // --- PoC Summary ---------------------------------------------------- + // Scenario: Borrower makes one periodic payment early (before next due) + // so doPayment sets sfPreviousPaymentDate to the (future) + // sfNextPaymentDueDate and advances sfNextPaymentDueDate by one + // interval. Borrower then immediately performs a full-payment + // (tfLoanFullPayment). Why it matters: Full-payment interest accrual + // uses + // delta = now - max(prevPaymentDate, startDate) + // with an unsigned clock representation (uint32). If prevPaymentDate is + // in the future, the subtraction underflows to a very large positive + // number. This inflates roundedFullInterest and total full-close due, + // and LoanPay applies the inflated valueChange to the vault + // (sfAssetsTotal), increasing NAV. + // -------------------------------------------------------------------- + testcase( + "PoC: Unsigned-underflow full-pay accrual after early periodic"); + + using namespace jtx; + using namespace loan; + using namespace std::chrono_literals; + + Env env(*this, all); + + Account const lender{"poc_lender4"}; + Account const borrower{"poc_borrower4"}; + env.fund(XRP(3'000'000), lender, borrower); + env.close(); + + PrettyAsset const asset{xrpIssue(), 1'000'000}; + BrokerParameters brokerParams{}; + auto const broker = + createVaultAndBroker(env, asset, lender, brokerParams); + + // Create a 3-payment loan so full-payment path is enabled after 1 + // periodic payment. + auto const loanSetFee = fee(env.current()->fees().base * 2); + Number const principalRequest = asset(1000).value(); + auto const originationFee = asset(0).value(); + auto const serviceFee = asset(1).value(); + auto const serviceFeePA = asset(1); + auto const lateFee = asset(0).value(); + auto const closeFee = asset(0).value(); + auto const interest = percentageToTenthBips(12); + auto const lateInterest = percentageToTenthBips(12) / 10; + auto const closeInterest = percentageToTenthBips(12) / 10; + auto const overpaymentInterest = percentageToTenthBips(12) / 10; + auto const total = 3u; + auto const interval = 600u; + auto const grace = 60u; + + auto createJtx = env.jt( + set(borrower, broker.brokerID, principalRequest, 0), + sig(sfCounterpartySignature, lender), + loanOriginationFee(originationFee), + loanServiceFee(serviceFee), + latePaymentFee(lateFee), + closePaymentFee(closeFee), + overpaymentFee(percentageToTenthBips(5) / 10), + interestRate(interest), + lateInterestRate(lateInterest), + closeInterestRate(closeInterest), + overpaymentInterestRate(overpaymentInterest), + paymentTotal(total), + paymentInterval(interval), + gracePeriod(grace), + fee(loanSetFee)); + + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle); + auto const loanSequence = brokerSle ? brokerSle->at(sfLoanSequence) : 0; + auto const loanKeylet = keylet::loan(broker.brokerID, loanSequence); + + env(createJtx); + env.close(); + + // Compute a regular periodic due and pay it early (before next due). + auto state = getCurrentState(env, broker, loanKeylet); + Number const periodicRate = + loanPeriodicRate(state.interestRate, state.paymentInterval); + auto const components = detail::computePaymentComponents( + asset.raw(), + state.loanScale, + state.totalValue, + state.principalOutstanding, + state.managementFeeOutstanding, + state.periodicPayment, + periodicRate, + state.paymentRemaining, + brokerParams.managementFeeRate); + STAmount const regularDue{ + asset, components.trackedValueDelta + serviceFeePA.number()}; + // now < nextDue immediately after creation, so this is an early pay. + env(pay(borrower, loanKeylet.key, regularDue)); + env.close(); + + // Immediately attempt a full payoff. Compute the exact full-payment + // due to ensure the tx applies. + auto after = getCurrentState(env, broker, loanKeylet); + auto const loanSle = env.le(loanKeylet); + BEAST_EXPECT(loanSle); + auto const brokerSle2 = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerSle2); + + auto const closePaymentFee = + loanSle ? loanSle->at(sfClosePaymentFee) : Number{}; + auto const closeInterestRate = loanSle + ? TenthBips32{loanSle->at(sfCloseInterestRate)} + : TenthBips32{}; + auto const managementFeeRate = brokerSle2 + ? TenthBips16{brokerSle2->at(sfManagementFeeRate)} + : TenthBips16{}; + + Number const periodicRate2 = + loanPeriodicRate(after.interestRate, after.paymentInterval); + // Accrued + prepayment-penalty interest based on current periodic + // schedule + auto const fullPaymentInterest = computeFullPaymentInterest( + after.periodicPayment, + periodicRate2, + after.paymentRemaining, + env.current()->parentCloseTime(), + after.paymentInterval, + after.previousPaymentDate, + static_cast( + after.startDate.time_since_epoch().count()), + closeInterestRate); + // Round to asset scale and split interest/fee parts + auto const roundedInterest = + roundToAsset(asset.raw(), fullPaymentInterest, after.loanScale); + Number const roundedFullMgmtFee = computeManagementFee( + asset.raw(), roundedInterest, managementFeeRate, after.loanScale); + Number const roundedFullInterest = roundedInterest - roundedFullMgmtFee; + + // Show both signed and unsigned deltas to highlight the underflow. + auto const nowSecs = static_cast( + env.current()->parentCloseTime().time_since_epoch().count()); + auto const startSecs = static_cast( + after.startDate.time_since_epoch().count()); + auto const lastPaymentDate = + std::max(after.previousPaymentDate, startSecs); + auto const signedDelta = static_cast(nowSecs) - + static_cast(lastPaymentDate); + auto const unsignedDelta = + static_cast(nowSecs - lastPaymentDate); + log << "PoC window: prev=" << after.previousPaymentDate + << " start=" << startSecs << " now=" << nowSecs + << " signedDelta=" << signedDelta + << " unsignedDelta=" << unsignedDelta << std::endl; + + // Reference (clamped) computation: emulate a non-negative accrual + // window by clamping prevPaymentDate to 'now' for the full-pay path. + auto const prevClamped = std::min(after.previousPaymentDate, nowSecs); + auto const fullPaymentInterestClamped = computeFullPaymentInterest( + after.periodicPayment, + periodicRate2, + after.paymentRemaining, + env.current()->parentCloseTime(), + after.paymentInterval, + prevClamped, + startSecs, + closeInterestRate); + auto const roundedInterestClamped = roundToAsset( + asset.raw(), fullPaymentInterestClamped, after.loanScale); + Number const roundedFullMgmtFeeClamped = computeManagementFee( + asset.raw(), + roundedInterestClamped, + managementFeeRate, + after.loanScale); + Number const roundedFullInterestClamped = + roundedInterestClamped - roundedFullMgmtFeeClamped; + STAmount const fullDueClamped{ + asset, + after.principalOutstanding + roundedFullInterestClamped + + roundedFullMgmtFeeClamped + closePaymentFee}; + + // Collect vault NAV before closing payment + auto const vaultId2 = + brokerSle2 ? brokerSle2->at(sfVaultID) : uint256{}; + auto const vaultKey2 = keylet::vault(vaultId2); + auto const vaultBefore = env.le(vaultKey2); + BEAST_EXPECT(vaultBefore); + Number const assetsTotalBefore = + vaultBefore ? vaultBefore->at(sfAssetsTotal) : Number{}; + + STAmount const fullDue{ + asset, + after.principalOutstanding + roundedFullInterest + + roundedFullMgmtFee + closePaymentFee}; + + log << "PoC payoff: principalOutstanding=" << after.principalOutstanding + << " roundedFullInterest=" << roundedFullInterest + << " roundedFullMgmtFee=" << roundedFullMgmtFee + << " closeFee=" << closePaymentFee + << " fullDue=" << to_string(fullDue.getJson()) << std::endl; + log << "PoC reference (clamped): roundedFullInterestClamped=" + << roundedFullInterestClamped + << " roundedFullMgmtFeeClamped=" << roundedFullMgmtFeeClamped + << " fullDueClamped=" << to_string(fullDueClamped.getJson()) + << std::endl; + + env(pay(borrower, loanKeylet.key, fullDue), txflags(tfLoanFullPayment)); + env.close(); + + // Sanity: underflow present (unsigned delta very large relative to + // interval) + BEAST_EXPECT(unsignedDelta > after.paymentInterval); + + // Compare vault NAV before/after the full close + auto const vaultAfter = env.le(vaultKey2); + BEAST_EXPECT(vaultAfter); + if (vaultAfter) + { + auto const assetsTotalAfter = vaultAfter->at(sfAssetsTotal); + log << "PoC NAV: assetsTotalBefore=" << assetsTotalBefore + << " assetsTotalAfter=" << assetsTotalAfter + << " delta=" << (assetsTotalAfter - assetsTotalBefore) + << std::endl; + + // Value-based proof: underflowed window yields a payoff larger than + // the clamped (non-underflow) reference. + BEAST_EXPECT(fullDue == fullDueClamped); + if (fullDue > fullDueClamped) + log << "PoC delta: overcharge (fullDue > clamped)" << std::endl; + } + + // Loan should be paid off + auto const finalLoan = env.le(loanKeylet); + BEAST_EXPECT(finalLoan); + if (finalLoan) + { + BEAST_EXPECT(finalLoan->at(sfPaymentRemaining) == 0); + BEAST_EXPECT(finalLoan->at(sfPrincipalOutstanding) == 0); + } + } + + void + testDustManipulation() + { + testcase("Dust manipulation"); + + using namespace jtx; + using namespace std::chrono_literals; + Env env(*this, all); + + // Setup: Create accounts + Account issuer{"issuer"}; + Account lender{"lender"}; + Account borrower{"borrower"}; + Account victim{"victim"}; + + env.fund(XRP(1'000'000'00), issuer, lender, borrower, victim); + env.close(); + + // Step 1: Create vault with IOU asset + auto asset = issuer["USD"]; + env(trust(lender, asset(100000))); + env(trust(borrower, asset(100000))); + env(trust(victim, asset(100000))); + env(pay(issuer, lender, asset(50000))); + env(pay(issuer, borrower, asset(50000))); + env(pay(issuer, victim, asset(50000))); + env.close(); + + BrokerParameters brokerParams{ + .vaultDeposit = 10000, + .debtMax = Number{0}, + .coverRateMin = TenthBips32{1000}, + .coverRateLiquidation = TenthBips32{2500}}; + + auto broker = createVaultAndBroker(env, asset, lender, brokerParams); + + auto const loanKeyletOpt = [&]() -> std::optional { + auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); + if (!BEAST_EXPECT(brokerSle)) + return std::nullopt; + + // Broker has no loans + BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 0); + + // The loan keylet is based on the LoanSequence of the + // _LOAN_BROKER_ object. + auto const loanSequence = brokerSle->at(sfLoanSequence); + return keylet::loan(broker.brokerID, loanSequence); + }(); + if (!loanKeyletOpt) + return; + + auto const& vaultKeylet = broker.vaultKeylet(); + + { + auto const vaultSle = env.le(vaultKeylet); + Number assetsTotal = vaultSle->at(sfAssetsTotal); + Number assetsAvail = vaultSle->at(sfAssetsAvailable); + + log << "Before loan creation:" << std::endl; + log << " AssetsTotal: " << assetsTotal << std::endl; + log << " AssetsAvailable: " << assetsAvail << std::endl; + log << " Difference: " << (assetsTotal - assetsAvail) << std::endl; + + // before the loan the assets total and available should be equal + BEAST_EXPECT(assetsAvail == assetsTotal); + BEAST_EXPECT( + assetsAvail == + broker.asset(brokerParams.vaultDeposit).number()); + } + + Keylet const& loanKeylet = *loanKeyletOpt; + + LoanParameters const loanParams{ + .account = lender, + .counter = borrower, + .principalRequest = Number{100}, + .interest = TenthBips32{1922}, + .payTotal = 5816, + .payInterval = 86400 * 6, + .gracePd = 86400 * 5, + }; + + env(loanParams(env, broker)); + env.close(); + + // Wait for loan to be late enough to default + env.close(std::chrono::seconds(86400 * 40)); // 40 days + + { + auto const vaultSle = env.le(vaultKeylet); + Number assetsTotal = vaultSle->at(sfAssetsTotal); + Number assetsAvail = vaultSle->at(sfAssetsAvailable); + + log << "After loan creation:" << std::endl; + log << " AssetsTotal: " << assetsTotal << std::endl; + log << " AssetsAvailable: " << assetsAvail << std::endl; + log << " Difference: " << (assetsTotal - assetsAvail) << std::endl; + + auto const loanSle = env.le(loanKeylet); + if (!BEAST_EXPECT(loanSle)) + return; + auto const state = constructRoundedLoanState(loanSle); + + log << "Loan state:" << std::endl; + log << " ValueOutstanding: " << state.valueOutstanding + << std::endl; + log << " PrincipalOutstanding: " << state.principalOutstanding + << std::endl; + log << " InterestOutstanding: " << state.interestOutstanding() + << std::endl; + log << " InterestDue: " << state.interestDue << std::endl; + log << " FeeDue: " << state.managementFeeDue << std::endl; + + // after loan creation the assets total and available should + // reflect the value of the loan + BEAST_EXPECT(assetsAvail < assetsTotal); + BEAST_EXPECT( + assetsAvail == + broker + .asset( + brokerParams.vaultDeposit - loanParams.principalRequest) + .number()); + BEAST_EXPECT( + assetsTotal == + broker.asset(brokerParams.vaultDeposit + state.interestDue) + .number()); + } + + // Step 7: Trigger default (dust adjustment will occur) + env(jtx::loan::manage(lender, loanKeylet.key, tfLoanDefault)); + env.close(); + + // Step 8: Verify phantom assets created + { + auto const vaultSle2 = env.le(vaultKeylet); + Number assetsTotal2 = vaultSle2->at(sfAssetsTotal); + Number assetsAvail2 = vaultSle2->at(sfAssetsAvailable); + + log << "After default:" << std::endl; + log << " AssetsTotal: " << assetsTotal2 << std::endl; + log << " AssetsAvailable: " << assetsAvail2 << std::endl; + log << " Difference: " << (assetsTotal2 - assetsAvail2) + << std::endl; + + // after a default the assets total and available should be equal + BEAST_EXPECT(assetsAvail2 == assetsTotal2); + } + } + + void + testRIPD3831() + { + using namespace jtx; + + testcase("RIPD-3831"); + + Account const issuer("issuer"); + Account const lender("lender"); + Account const borrower("borrower"); + + BrokerParameters const brokerParams{ + .vaultDeposit = 100000, + .debtMax = 0, + .coverRateMin = TenthBips32{0}, + // .managementFeeRate = TenthBips16{5919}, + .coverRateLiquidation = TenthBips32{0}}; + LoanParameters const loanParams{ + .account = lender, + .counter = borrower, + .principalRequest = Number{200'000, -6}, + .lateFee = Number{200, -6}, + .interest = TenthBips32{50'000}, + .payTotal = 10, + .payInterval = 150, + .gracePd = 0}; + + auto const assetType = AssetType::XRP; + + Env env(*this, all); + + auto loanResult = createLoan( + env, assetType, brokerParams, loanParams, issuer, lender, borrower); + + if (!BEAST_EXPECT(loanResult)) + return; + + auto broker = std::get(*loanResult); + auto loanKeylet = std::get(*loanResult); + + using tp = NetClock::time_point; + using d = NetClock::duration; + + auto state = getCurrentState(env, broker, loanKeylet); + if (auto loan = env.le(loanKeylet); BEAST_EXPECT(loan)) + { + // log << "loan after create: " << to_string(loan->getJson()) + // << std::endl; + + env.close(tp{d{ + loan->at(sfNextPaymentDueDate) + loan->at(sfGracePeriod) + 1}}); + } + + topUpBorrower( + env, broker, issuer, borrower, state, loanParams.serviceFee); + + using namespace jtx::loan; + + auto jv = + pay(borrower, loanKeylet.key, drops(XRPAmount(state.totalValue))); + + { + auto const submitParam = to_string(jv); + // log << "about to submit: " << submitParam << std::endl; + auto const jr = env.rpc("submit", borrower.name(), submitParam); + + // log << jr << std::endl; + BEAST_EXPECT(jr.isMember(jss::result)); + auto const jResult = jr[jss::result]; + // BEAST_EXPECT(jResult[jss::error] == "invalidTransaction"); + // BEAST_EXPECT( + // jResult[jss::error_exception] == + // "fails local checks: Transaction has bad signature."); + } + + env.close(); + + // Make sure the system keeps responding + env(noop(borrower)); + env.close(); + env(noop(issuer)); + env.close(); + env(noop(lender)); + env.close(); + } + + void + testRIPD3459() + { + testcase("RIPD-3459 - LoanBroker incorrect debt total"); + + using namespace jtx; + + Account const issuer("issuer"); + Account const lender("lender"); + Account const borrower("borrower"); + + BrokerParameters const brokerParams{ + .vaultDeposit = 200'000, + .debtMax = 0, + .coverRateMin = TenthBips32{0}, + .managementFeeRate = TenthBips16{500}, + .coverRateLiquidation = TenthBips32{0}}; + LoanParameters const loanParams{ + .account = lender, + .counter = borrower, + .principalRequest = Number{100'000, -4}, + .interest = TenthBips32{100'000}, + .payTotal = 10, + .gracePd = 0}; + + auto const assetType = AssetType::MPT; + + Env env(*this, all); + + auto loanResult = createLoan( + env, assetType, brokerParams, loanParams, issuer, lender, borrower); + + if (!BEAST_EXPECT(loanResult)) + return; + + auto broker = std::get(*loanResult); + auto loanKeylet = std::get(*loanResult); + auto pseudoAcct = std::get(*loanResult); + + VerifyLoanStatus verifyLoanStatus(env, broker, pseudoAcct, loanKeylet); + + if (auto const brokerSle = env.le(broker.brokerKeylet()); + BEAST_EXPECT(brokerSle)) + { + if (auto const loanSle = env.le(loanKeylet); BEAST_EXPECT(loanSle)) + { + BEAST_EXPECT( + brokerSle->at(sfDebtTotal) == + loanSle->at(sfTotalValueOutstanding)); + } + } + + makeLoanPayments( + env, + broker, + loanParams, + loanKeylet, + verifyLoanStatus, + issuer, + lender, + borrower, + PaymentParameters{.showStepBalances = true}); + + if (auto const brokerSle = env.le(broker.brokerKeylet()); + BEAST_EXPECT(brokerSle)) + { + if (auto const loanSle = env.le(loanKeylet); BEAST_EXPECT(loanSle)) + { + BEAST_EXPECT( + brokerSle->at(sfDebtTotal) == + loanSle->at(sfTotalValueOutstanding)); + BEAST_EXPECT(brokerSle->at(sfDebtTotal) == beast::zero); + } + } + } + + void + testRIPD3901() + { + testcase("Crash with tfLoanOverpayment"); + using namespace jtx; + using namespace loan; + Account const lender{"lender"}; + Account const issuer{"issuer"}; + Account const borrower{"borrower"}; + Account const depositor{"depositor"}; + auto const txfee = fee(XRP(100)); + + Env env(*this); + Vault vault(env); + + env.fund(XRP(10'000), lender, issuer, borrower, depositor); + env.close(); + + auto [tx, vaultKeyLet] = + vault.create({.owner = lender, .asset = xrpIssue()}); + env(tx, txfee); + env.close(); + + env(vault.deposit( + {.depositor = depositor, + .id = vaultKeyLet.key, + .amount = XRP(1'000)}), + txfee); + env.close(); + + auto const brokerKeyLet = + keylet::loanbroker(lender.id(), env.seq(lender)); + + env(loanBroker::set(lender, vaultKeyLet.key), txfee); + env.close(); + + // BrokerInfo brokerInfo{xrpIssue(), keylet, vaultKeyLet, {}}; + + STAmount const debtMaximumRequest = XRPAmount(200'000); + + env(set(borrower, brokerKeyLet.key, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + interestRate(TenthBips32(50'000)), + paymentTotal(2), + paymentInterval(150), + txflags(tfLoanOverpayment), + txfee); + env.close(); + + std::uint32_t const loanSequence = 1; + auto const loanKeylet = keylet::loan(brokerKeyLet.key, loanSequence); + + if (auto loan = env.le(loanKeylet); env.test.BEAST_EXPECT(loan)) + { + env(loan::pay(borrower, loanKeylet.key, XRPAmount(150'001)), + txflags(tfLoanOverpayment), + txfee); + env.close(); + } + } + + void + testRoundingAllowsUndercoverage() + { + testcase("Minimum cover rounding allows undercoverage (XRP)"); + + using namespace jtx; + using namespace loanBroker; + + Env env(*this, all); + + Account const lender{"lender"}; + Account const borrower{"borrower"}; + + env.fund(XRP(200'000), lender, borrower); + env.close(); + + // Vault with XRP asset + Vault vault{env}; + auto [vaultCreate, vaultKeylet] = + vault.create({.owner = lender, .asset = xrpIssue()}); + env(vaultCreate); + env.close(); + BEAST_EXPECT(env.le(vaultKeylet)); + + // Seed the vault with XRP so it can fund the loan principal + PrettyAsset const xrpAsset{xrpIssue(), 1}; + + BrokerParameters const brokerParams{ + .vaultDeposit = 1'000, + .debtMax = Number{0}, + .coverRateMin = TenthBips32{10'000}, + .coverDeposit = 82, + }; + + auto const brokerInfo = + createVaultAndBroker(env, xrpAsset, lender, brokerParams); + // Create a loan with principal 804 XRP and 0% interest (so + // DebtTotal increases by exactly 804) + env(loan::set(borrower, brokerInfo.brokerID, xrpAsset(804).value()), + loan::interestRate(TenthBips32(0)), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 2)); + BEAST_EXPECT(env.ter() == tesSUCCESS); + env.close(); + + // Verify DebtTotal is exactly 804 + if (auto const brokerSle = + env.le(keylet::loanbroker(brokerInfo.brokerID)); + BEAST_EXPECT(brokerSle)) + { + log << *brokerSle << std::endl; + BEAST_EXPECT(brokerSle->at(sfDebtTotal) == Number(804)); + } + + // Attempt to withdraw 2 XRP to self, leaving 80 XRP CoverAvailable. + // The minimum is 80.4 XRP, which rounds up to 81 XRP, so this fails. + env(coverWithdraw(lender, brokerInfo.brokerID, xrpAsset(2).value()), + ter(tecINSUFFICIENT_FUNDS)); + BEAST_EXPECT(env.ter() == tecINSUFFICIENT_FUNDS); + env.close(); + + // Attempt to withdraw 1 XRP to self, leaving 81 XRP CoverAvailable. + // because that leaves sufficient cover, this succeeds + env(coverWithdraw(lender, brokerInfo.brokerID, xrpAsset(1).value())); + BEAST_EXPECT(env.ter() == tesSUCCESS); + env.close(); + + // Validate CoverAvailable == 80 XRP and DebtTotal remains 804 + if (auto const brokerSle = + env.le(keylet::loanbroker(brokerInfo.brokerID)); + BEAST_EXPECT(brokerSle)) + { + log << *brokerSle << std::endl; + BEAST_EXPECT( + brokerSle->at(sfCoverAvailable) == xrpAsset(81).value()); + BEAST_EXPECT(brokerSle->at(sfDebtTotal) == Number(804)); + + // Also demonstrate that the true minimum (804 * 10%) exceeds 80 + auto const theoreticalMin = + tenthBipsOfValue(Number(804), TenthBips32(10'000)); + log << "Theoretical min cover: " << theoreticalMin << std::endl; + BEAST_EXPECT(Number(804, -1) == theoreticalMin); + } + } + + void + testRIPD3902() + { + testcase("RIPD-3902 - 1 IOU loan payments"); + + using namespace jtx; + + Account const issuer("issuer"); + Account const lender("lender"); + Account const borrower("borrower"); + + BrokerParameters const brokerParams{ + .vaultDeposit = 10, + .debtMax = 0, + .coverRateMin = TenthBips32{0}, + .managementFeeRate = TenthBips16{0}, + .coverRateLiquidation = TenthBips32{0}}; + LoanParameters const loanParams{ + .account = lender, + .counter = borrower, + .principalRequest = Number{1, 0}, + .interest = TenthBips32{100'000}, + .payTotal = 5, + .payInterval = 150, + .gracePd = 60}; + + auto const assetType = AssetType::IOU; + + Env env(*this, all); + + auto loanResult = createLoan( + env, assetType, brokerParams, loanParams, issuer, lender, borrower); + + if (!BEAST_EXPECT(loanResult)) + return; + + auto broker = std::get(*loanResult); + auto loanKeylet = std::get(*loanResult); + auto pseudoAcct = std::get(*loanResult); + + VerifyLoanStatus verifyLoanStatus(env, broker, pseudoAcct, loanKeylet); + + makeLoanPayments( + env, + broker, + loanParams, + loanKeylet, + verifyLoanStatus, + issuer, + lender, + borrower, + PaymentParameters{.showStepBalances = true}); + } + + void + testBorrowerIsBroker() + { + testcase("Test Borrower is Broker"); + using namespace jtx; + using namespace loan; + Account const broker{"broker"}; + Account const issuer{"issuer"}; + Account const borrower_{"borrower"}; + Account const depositor{"depositor"}; + + auto testLoanAsset = [&](auto&& getMaxDebt, auto const& borrower) { + Env env(*this); + Vault vault(env); + + if (borrower == broker) + env.fund(XRP(10'000), broker, issuer, depositor); + else + env.fund(XRP(10'000), broker, borrower, issuer, depositor); + env.close(); + + auto const xrpFee = XRP(100); + auto const txFee = fee(xrpFee); + + STAmount const debtMaximumRequest = getMaxDebt(env); + + auto const& asset = debtMaximumRequest.asset(); + auto const initialVault = asset(debtMaximumRequest * 100); + + auto [tx, vaultKeylet] = + vault.create({.owner = broker, .asset = asset}); + env(tx, txFee); + env.close(); + + env(vault.deposit( + {.depositor = depositor, + .id = vaultKeylet.key, + .amount = initialVault}), + txFee); + env.close(); + + auto const brokerKeylet = + keylet::loanbroker(broker.id(), env.seq(broker)); + + env(loanBroker::set(broker, vaultKeylet.key), txFee); + env.close(); + + auto const serviceFee = 101; + + env(set(broker, brokerKeylet.key, debtMaximumRequest), + counterparty(borrower), + sig(sfCounterpartySignature, borrower), + loanServiceFee(serviceFee), + paymentTotal(10), + txFee); + env.close(); + + std::uint32_t const loanSequence = 1; + auto const loanKeylet = + keylet::loan(brokerKeylet.key, loanSequence); + + auto const brokerBalanceBefore = env.balance(broker, asset); + + if (auto const loanSle = env.le(loanKeylet); + env.test.BEAST_EXPECT(loanSle)) + { + auto const payment = loanSle->at(sfPeriodicPayment); + auto const totalPayment = payment + serviceFee; + env(loan::pay(borrower, loanKeylet.key, asset(totalPayment)), + txFee); + env.close(); + if (auto const vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle)) + { + auto const expected = [&]() { + // The service fee is transferred to the broker if + // a borrower is not the broker + if (borrower != broker) + return brokerBalanceBefore.number() + serviceFee; + // Since a borrower is the broker, the payment is + // transferred to the Vault from the broker but not + // the service fee. + // If the asset is XRP then the broker pays the txfee. + if (asset.native()) + return brokerBalanceBefore.number() - payment - + xrpFee.number(); + return brokerBalanceBefore.number() - payment; + }(); + BEAST_EXPECT( + env.balance(broker, asset).value() == + asset(expected).value()); + } + } + }; + // Test when a borrower is the broker and is not to verify correct + // service fee transfer in both cases. + for (auto const& borrowerAcct : {broker, borrower_}) + { + testLoanAsset( + [&](Env&) -> STAmount { return STAmount{XRPAmount{200'000}}; }, + borrowerAcct); + testLoanAsset( + [&](Env& env) -> STAmount { + auto const IOU = issuer["USD"]; + env(trust(broker, IOU(1'000'000'000))); + env(trust(depositor, IOU(1'000'000'000))); + env(pay(issuer, broker, IOU(100'000'000))); + env(pay(issuer, depositor, IOU(100'000'000))); + env.close(); + return IOU(200'000); + }, + borrowerAcct); + testLoanAsset( + [&](Env& env) -> STAmount { + MPTTester mpt( + {.env = env, + .issuer = issuer, + .holders = {broker, depositor}, + .pay = 100'000'000}); + return mpt(200'000); + }, + borrowerAcct); + } + } + + void + testIssuerIsBorrower() + { + testcase("RIPD-4096 - Issuer as borrower"); + + using namespace jtx; + + Account const issuer("issuer"); + Account const lender("lender"); + + BrokerParameters const brokerParams{ + .vaultDeposit = 100'000, + .debtMax = 0, + .coverRateMin = TenthBips32{0}, + .managementFeeRate = TenthBips16{0}, + .coverRateLiquidation = TenthBips32{0}}; + LoanParameters const loanParams{ + .account = lender, + .counter = issuer, + .principalRequest = Number{10000}}; + + auto const assetType = AssetType::IOU; + + Env env(*this, all); + + auto loanResult = createLoan( + env, assetType, brokerParams, loanParams, issuer, lender, issuer); + + if (!BEAST_EXPECT(loanResult)) + return; + + auto broker = std::get(*loanResult); + auto loanKeylet = std::get(*loanResult); + auto pseudoAcct = std::get(*loanResult); + + VerifyLoanStatus verifyLoanStatus(env, broker, pseudoAcct, loanKeylet); + + makeLoanPayments( + env, + broker, + loanParams, + loanKeylet, + verifyLoanStatus, + issuer, + lender, + issuer, + PaymentParameters{.showStepBalances = true}); + } + + void + testLimitExceeded() + { + testcase("RIPD-4125 - overpayment"); + + using namespace jtx; + + Account const issuer("issuer"); + Account const lender("lender"); + Account const borrower("borrower"); + + BrokerParameters const brokerParams{ + .vaultDeposit = 100'000, + .debtMax = 0, + .coverRateMin = TenthBips32{0}, + .managementFeeRate = TenthBips16{0}, + .coverRateLiquidation = TenthBips32{0}}; + LoanParameters const loanParams{ + .account = lender, + .counter = borrower, + .principalRequest = Number{200000, -6}, + .interest = TenthBips32{50000}, + .payTotal = 3, + .payInterval = 200, + .gracePd = 60, + .flags = tfLoanOverpayment, + }; + + auto const assetType = AssetType::XRP; + + Env env( + *this, + makeConfig(), + all, + nullptr, + beast::severities::Severity::kWarning); + + auto loanResult = createLoan( + env, assetType, brokerParams, loanParams, issuer, lender, borrower); + + if (!BEAST_EXPECT(loanResult)) + return; + + auto broker = std::get(*loanResult); + auto loanKeylet = std::get(*loanResult); + auto pseudoAcct = std::get(*loanResult); + + VerifyLoanStatus verifyLoanStatus(env, broker, pseudoAcct, loanKeylet); + + auto const state = getCurrentState(env, broker, loanKeylet); + + env(loan::pay( + borrower, + loanKeylet.key, + STAmount{broker.asset, state.periodicPayment * 3 / 2 + 1}, + tfLoanOverpayment)); + env.close(); + + PaymentParameters paymentParams{ + //.overpaymentFactor = Number{15, -1}, + //.overpaymentExtra = Number{1, -6}, + //.flags = tfLoanOverpayment, + .showStepBalances = true, + //.validateBalances = false, + }; + + makeLoanPayments( + env, + broker, + loanParams, + loanKeylet, + verifyLoanStatus, + issuer, + lender, + borrower, + paymentParams); + } + +public: + void + run() override + { +#if LOANTODO + testLoanPayLateFullPaymentBypassesPenalties(); + testLoanCoverMinimumRoundingExploit(); +#endif + testCoverDepositWithdrawNonTransferableMPT(); + testPoC_UnsignedUnderflowOnFullPayAfterEarlyPeriodic(); + + testDisabled(); + testSelfLoan(); + testIssuerLoan(); + testLoanSet(); + testLifecycle(); + testServiceFeeOnBrokerDeepFreeze(); + + testRPC(); + testBasicMath(); + + testInvalidLoanDelete(); + testInvalidLoanManage(); + testInvalidLoanPay(); + testInvalidLoanSet(); + + testBatchBypassCounterparty(); + testLoanPayComputePeriodicPaymentValidRateInvariant(); + testAccountSendMptMinAmountInvariant(); + testLoanPayDebtDecreaseInvariant(); + testWrongMaxDebtBehavior(); + testLoanPayComputePeriodicPaymentValidTotalInterestInvariant(); + testDosLoanPay(); + testLoanPayComputePeriodicPaymentValidTotalPrincipalPaidInvariant(); + testLoanPayComputePeriodicPaymentValidTotalInterestPaidInvariant(); + testLoanNextPaymentDueDateOverflow(); + + testRequireAuth(); + testDustManipulation(); + + testRIPD3831(); + testRIPD3459(); + testRIPD3901(); + testRIPD3902(); + testRoundingAllowsUndercoverage(); + testBorrowerIsBroker(); + testIssuerIsBorrower(); + testLimitExceeded(); + } +}; + +class LoanBatch_test : public Loan_test +{ +protected: + beast::xor_shift_engine engine_; + + std::uniform_int_distribution<> assetDist{0, 2}; + std::uniform_int_distribution principalDist{ + 100'000, + 1'000'000'000}; + std::uniform_int_distribution interestRateDist{0, 10000}; + std::uniform_int_distribution<> paymentTotalDist{12, 10000}; + std::uniform_int_distribution<> paymentIntervalDist{60, 3600 * 24 * 30}; + std::uniform_int_distribution managementFeeRateDist{ + 0, + 10'000}; + std::uniform_int_distribution<> serviceFeeDist{0, 20}; + /* + # Generate parameters that are more likely to be valid + principal = Decimal(str(rand.randint(100000, + 100'000'000))).quantize(ROUND_TARGET) + + interest_rate = Decimal(rand.randint(1, 10000)) / + Decimal(100000) + + payment_total = rand.randint(12, 10000) + + payment_interval = Decimal(str(rand.randint(60, 2629746))) + + interest_fee = Decimal(rand.randint(0, 100000)) / + Decimal(100000) +*/ + + void + testRandomLoan() + { + using namespace jtx; + + Account const issuer("issuer"); + Account const lender("lender"); + Account const borrower("borrower"); + + // Determine all the random parameters at once + AssetType assetType = static_cast(assetDist(engine_)); + auto const principalRequest = principalDist(engine_); + TenthBips16 managementFeeRate{managementFeeRateDist(engine_)}; + auto const serviceFee = serviceFeeDist(engine_); + TenthBips32 interest{interestRateDist(engine_)}; + auto const payTotal = paymentTotalDist(engine_); + auto const payInterval = paymentIntervalDist(engine_); + + BrokerParameters brokerParams{ + .vaultDeposit = principalRequest * 10, + .debtMax = 0, + .coverRateMin = TenthBips32{0}, + .managementFeeRate = managementFeeRate}; + LoanParameters loanParams{ + .account = lender, + .counter = borrower, + .principalRequest = principalRequest, + .serviceFee = serviceFee, + .interest = interest, + .payTotal = payTotal, + .payInterval = payInterval, + }; + + runLoan(assetType, brokerParams, loanParams); + } + +public: + void + run() override + { + auto const argument = arg(); + auto const numIterations = [s = arg()]() -> int { + int defaultNum = 5; + if (s.empty()) + return defaultNum; + try + { + std::size_t pos; + auto const r = stoi(s, &pos); + if (pos != s.size()) + return defaultNum; + return r; + } + catch (...) + { + return defaultNum; + } + }(); + + using namespace jtx; + + auto const updateInterval = std::min(numIterations / 5, 100); + + for (int i = 0; i < numIterations; ++i) + { + if (i % updateInterval == 0) + testcase << "Random Loan Test iteration " << (i + 1) << "/" + << numIterations; + testRandomLoan(); + } + } +}; + +class LoanArbitrary_test : public LoanBatch_test +{ + void + run() override + { + using namespace jtx; + + BrokerParameters const brokerParams{ + .vaultDeposit = 10000, + .debtMax = 0, + .coverRateMin = TenthBips32{0}, + // .managementFeeRate = TenthBips16{5919}, + .coverRateLiquidation = TenthBips32{0}}; + LoanParameters const loanParams{ + .account = Account("lender"), + .counter = Account("borrower"), + .principalRequest = Number{10000, 0}, + // .interest = TenthBips32{0}, + // .payTotal = 5816, + .payInterval = 150}; + + runLoan(AssetType::XRP, brokerParams, loanParams); + } +}; + +BEAST_DEFINE_TESTSUITE(Loan, tx, ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(LoanBatch, tx, ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(LoanArbitrary, tx, ripple); + +} // namespace test +} // namespace ripple diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index f7c93d3c62..7d0126bd65 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -1152,7 +1152,7 @@ class MPToken_test : public beast::unit_test::suite env(credentials::accept(bob, credIssuer1, credType)); env.close(); - MPTTester mptAlice(env, alice, {}); + MPTTester mptAlice(env, alice); env.close(); mptAlice.create({ @@ -1194,7 +1194,7 @@ class MPToken_test : public beast::unit_test::suite env(credentials::accept(bob, credIssuer1, credType)); env.close(); - MPTTester mptAlice(env, alice, {}); + MPTTester mptAlice(env, alice); env.close(); mptAlice.create({ @@ -1274,7 +1274,7 @@ class MPToken_test : public beast::unit_test::suite env(credentials::accept(carol, credIssuer2, credType)); env.close(); - MPTTester mptAlice(env, alice, {}); + MPTTester mptAlice(env, alice); env.close(); mptAlice.create({ diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index 4097b93786..ce76e06912 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include @@ -69,14 +71,14 @@ class Vault_test : public beast::unit_test::suite this]() -> std::tuple { auto const vault = env.le(keylet); BEAST_EXPECT(vault != nullptr); - if (asset.raw().holds() && !asset.raw().native()) + if (!asset.integral()) BEAST_EXPECT(vault->at(sfScale) == 6); else BEAST_EXPECT(vault->at(sfScale) == 0); auto const shares = env.le(keylet::mptIssuance(vault->at(sfShareMPTID))); BEAST_EXPECT(shares != nullptr); - if (asset.raw().holds() && !asset.raw().native()) + if (!asset.integral()) BEAST_EXPECT(shares->at(sfAssetScale) == 6); else BEAST_EXPECT(shares->at(sfAssetScale) == 0); @@ -502,7 +504,7 @@ class Vault_test : public beast::unit_test::suite } } - if (!asset.raw().native() && asset.raw().holds()) + if (!asset.integral()) { testcase(prefix + " temporary authorization for 3rd party"); env(trust(erin, asset(1000))); @@ -670,12 +672,13 @@ class Vault_test : public beast::unit_test::suite test(env, issuer, owner, asset, vault); }; - testCase( - [&](Env& env, - Account const& issuer, - Account const& owner, - Asset const& asset, - Vault& vault) { + auto testDisabled = [&](TER resultAfterCreate = temDISABLED) { + return [&, resultAfterCreate]( + Env& env, + Account const& issuer, + Account const& owner, + Asset const& asset, + Vault& vault) { testcase("disabled single asset vault"); auto [tx, keylet] = @@ -684,7 +687,7 @@ class Vault_test : public beast::unit_test::suite { auto tx = vault.set({.owner = owner, .id = keylet.key}); - env(tx, ter{temDISABLED}); + env(tx, data("test"), ter{resultAfterCreate}); } { @@ -692,7 +695,7 @@ class Vault_test : public beast::unit_test::suite {.depositor = owner, .id = keylet.key, .amount = asset(10)}); - env(tx, ter{temDISABLED}); + env(tx, ter{resultAfterCreate}); } { @@ -700,7 +703,7 @@ class Vault_test : public beast::unit_test::suite {.depositor = owner, .id = keylet.key, .amount = asset(10)}); - env(tx, ter{temDISABLED}); + env(tx, ter{resultAfterCreate}); } { @@ -709,15 +712,49 @@ class Vault_test : public beast::unit_test::suite .id = keylet.key, .holder = owner, .amount = asset(10)}); - env(tx, ter{temDISABLED}); + env(tx, ter{resultAfterCreate}); } { auto tx = vault.del({.owner = owner, .id = keylet.key}); + env(tx, ter{resultAfterCreate}); + } + }; + }; + + testCase( + testDisabled(), + {.features = testable_amendments() - featureSingleAssetVault}); + + testCase( + testDisabled(tecNO_ENTRY), + {.features = testable_amendments() - featureMPTokensV1}); + + testCase( + [&](Env& env, + Account const& issuer, + Account const& owner, + Asset const& asset, + Vault& vault) { + testcase("disabled permissioned domains"); + + auto [tx, keylet] = + vault.create({.owner = owner, .asset = asset}); + env(tx); + + tx[sfFlags] = tx[sfFlags].asUInt() | tfVaultPrivate; + tx[sfDomainID] = to_string(base_uint<256>(42ul)); + env(tx, ter{temDISABLED}); + + { + auto tx = vault.set({.owner = owner, .id = keylet.key}); + env(tx, data("Test")); + + tx[sfDomainID] = to_string(base_uint<256>(13ul)); env(tx, ter{temDISABLED}); } }, - {.features = testable_amendments() - featureSingleAssetVault}); + {.features = testable_amendments() - featurePermissionedDomains}); testCase([&](Env& env, Account const& issuer, @@ -1730,7 +1767,8 @@ class Vault_test : public beast::unit_test::suite mptt.create( {.flags = tfMPTCanTransfer | tfMPTCanLock | (args.enableClawback ? tfMPTCanClawback : none) | - (args.requireAuth ? tfMPTRequireAuth : none)}); + (args.requireAuth ? tfMPTRequireAuth : none), + .mutableFlags = tmfMPTCanMutateCanTransfer}); PrettyAsset asset = mptt.issuanceID(); mptt.authorize({.account = owner}); mptt.authorize({.account = depositor}); @@ -2448,6 +2486,53 @@ class Vault_test : public beast::unit_test::suite env(tx2, ter{tecWRONG_ASSET}); env.close(); } + + testCase([this]( + Env& env, + Account const&, + Account const& owner, + Account const& depositor, + PrettyAsset const& asset, + Vault& vault, + MPTTester& mptt) { + testcase("MPT non-transferable"); + + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); + env(tx); + env.close(); + + tx = vault.deposit( + {.depositor = depositor, + .id = keylet.key, + .amount = asset(100)}); + env(tx); + env.close(); + + // Remove CanTransfer + mptt.set({.mutableFlags = tmfMPTClearCanTransfer}); + env.close(); + + env(tx, ter{tecNO_AUTH}); + env.close(); + + tx = vault.withdraw( + {.depositor = depositor, + .id = keylet.key, + .amount = asset(100)}); + + env(tx, ter{tecNO_AUTH}); + env.close(); + + // Restore CanTransfer + mptt.set({.mutableFlags = tmfMPTSetCanTransfer}); + env.close(); + + env(tx); + env.close(); + + // Delete vault with zero balance + env(vault.del({.owner = owner, .id = keylet.key})); + }); } void @@ -2460,6 +2545,7 @@ class Vault_test : public beast::unit_test::suite int initialXRP = 1000; Number initialIOU = 200; double transferRate = 1.0; + bool charlieRipple = true; }; auto testCase = @@ -2485,8 +2571,21 @@ class Vault_test : public beast::unit_test::suite PrettyAsset const asset = issuer["IOU"]; env.trust(asset(1000), owner); - env.trust(asset(1000), charlie); env(pay(issuer, owner, asset(args.initialIOU))); + env.close(); + if (!args.charlieRipple) + { + env(fset(issuer, 0, asfDefaultRipple)); + env.close(); + env.trust(asset(1000), charlie); + env.close(); + env(pay(issuer, charlie, asset(args.initialIOU))); + env.close(); + env(fset(issuer, asfDefaultRipple)); + } + else + env.trust(asset(1000), charlie); + env.close(); env(rate(issuer, args.transferRate)); env.close(); @@ -2864,6 +2963,94 @@ class Vault_test : public beast::unit_test::suite env(tx1); }); + testCase( + [&, this]( + Env& env, + Account const& owner, + Account const& issuer, + Account const& charlie, + auto vaultAccount, + Vault& vault, + PrettyAsset const& asset, + std::function issuanceId) { + testcase("IOU non-transferable"); + + auto [tx, keylet] = + vault.create({.owner = owner, .asset = asset}); + tx[sfScale] = 0; + env(tx); + env.close(); + + // Turn on noripple on the pseudo account's trust line. + // Charlie's is already set. + env(trust(issuer, vaultAccount(keylet)["IOU"], tfSetNoRipple), + THISLINE); + + { + // Charlie cannot deposit + auto tx = vault.deposit( + {.depositor = charlie, + .id = keylet.key, + .amount = asset(100)}); + env(tx, ter{terNO_RIPPLE}, THISLINE); + env.close(); + } + + { + PrettyAsset shares = issuanceId(keylet); + auto tx1 = vault.deposit( + {.depositor = owner, + .id = keylet.key, + .amount = asset(100)}); + env(tx1, THISLINE); + env.close(); + + // Charlie cannot receive funds + auto tx2 = vault.withdraw( + {.depositor = owner, + .id = keylet.key, + .amount = shares(100)}); + tx2[sfDestination] = charlie.human(); + env(tx2, ter{terNO_RIPPLE}, THISLINE); + env.close(); + + { + // Create MPToken for shares held by Charlie + Json::Value tx{Json::objectValue}; + tx[sfAccount] = charlie.human(); + tx[sfMPTokenIssuanceID] = + to_string(shares.raw().get().getMptID()); + tx[sfTransactionType] = jss::MPTokenAuthorize; + env(tx); + env.close(); + } + env(pay(owner, charlie, shares(100)), THISLINE); + env.close(); + + // Charlie cannot withdraw + auto tx3 = vault.withdraw( + {.depositor = charlie, + .id = keylet.key, + .amount = shares(100)}); + env(tx3, ter{terNO_RIPPLE}); + env.close(); + + env(pay(charlie, owner, shares(100)), THISLINE); + env.close(); + } + + tx = vault.withdraw( + {.depositor = owner, + .id = keylet.key, + .amount = asset(100)}); + env(tx, THISLINE); + env.close(); + + // Delete vault with zero balance + env(vault.del({.owner = owner, .id = keylet.key}), THISLINE); + }, + {.charlieRipple = false}); + testCase( [&, this]( Env& env, @@ -4525,7 +4712,7 @@ class Vault_test : public beast::unit_test::suite BEAST_EXPECT(checkString(vault, sfAssetsAvailable, "50")); BEAST_EXPECT(checkString(vault, sfAssetsMaximum, "1000")); BEAST_EXPECT(checkString(vault, sfAssetsTotal, "50")); - BEAST_EXPECT(checkString(vault, sfLossUnrealized, "0")); + BEAST_EXPECT(!vault.isMember(sfLossUnrealized.getJsonName())); auto const strShareID = strHex(sle->at(sfShareMPTID)); BEAST_EXPECT(checkString(vault, sfShareMPTID, strShareID)); diff --git a/src/test/basics/Number_test.cpp b/src/test/basics/Number_test.cpp index 06203a4c2a..bb5262d028 100644 --- a/src/test/basics/Number_test.cpp +++ b/src/test/basics/Number_test.cpp @@ -725,6 +725,115 @@ public: BEAST_EXPECT(Number(-100, -30000).truncate() == Number(0, 0)); } + void + testRounding() + { + // Test that rounding works as expected. + testcase("Rounding"); + + using NumberRoundings = std::map; + + std::map const expected{ + // Positive numbers + {Number{13, -1}, + {{Number::to_nearest, 1}, + {Number::towards_zero, 1}, + {Number::downward, 1}, + {Number::upward, 2}}}, + {Number{23, -1}, + {{Number::to_nearest, 2}, + {Number::towards_zero, 2}, + {Number::downward, 2}, + {Number::upward, 3}}}, + {Number{15, -1}, + {{Number::to_nearest, 2}, + {Number::towards_zero, 1}, + {Number::downward, 1}, + {Number::upward, 2}}}, + {Number{25, -1}, + {{Number::to_nearest, 2}, + {Number::towards_zero, 2}, + {Number::downward, 2}, + {Number::upward, 3}}}, + {Number{152, -2}, + {{Number::to_nearest, 2}, + {Number::towards_zero, 1}, + {Number::downward, 1}, + {Number::upward, 2}}}, + {Number{252, -2}, + {{Number::to_nearest, 3}, + {Number::towards_zero, 2}, + {Number::downward, 2}, + {Number::upward, 3}}}, + {Number{17, -1}, + {{Number::to_nearest, 2}, + {Number::towards_zero, 1}, + {Number::downward, 1}, + {Number::upward, 2}}}, + {Number{27, -1}, + {{Number::to_nearest, 3}, + {Number::towards_zero, 2}, + {Number::downward, 2}, + {Number::upward, 3}}}, + + // Negative numbers + {Number{-13, -1}, + {{Number::to_nearest, -1}, + {Number::towards_zero, -1}, + {Number::downward, -2}, + {Number::upward, -1}}}, + {Number{-23, -1}, + {{Number::to_nearest, -2}, + {Number::towards_zero, -2}, + {Number::downward, -3}, + {Number::upward, -2}}}, + {Number{-15, -1}, + {{Number::to_nearest, -2}, + {Number::towards_zero, -1}, + {Number::downward, -2}, + {Number::upward, -1}}}, + {Number{-25, -1}, + {{Number::to_nearest, -2}, + {Number::towards_zero, -2}, + {Number::downward, -3}, + {Number::upward, -2}}}, + {Number{-152, -2}, + {{Number::to_nearest, -2}, + {Number::towards_zero, -1}, + {Number::downward, -2}, + {Number::upward, -1}}}, + {Number{-252, -2}, + {{Number::to_nearest, -3}, + {Number::towards_zero, -2}, + {Number::downward, -3}, + {Number::upward, -2}}}, + {Number{-17, -1}, + {{Number::to_nearest, -2}, + {Number::towards_zero, -1}, + {Number::downward, -2}, + {Number::upward, -1}}}, + {Number{-27, -1}, + {{Number::to_nearest, -3}, + {Number::towards_zero, -2}, + {Number::downward, -3}, + {Number::upward, -2}}}, + }; + + for (auto const& [num, roundings] : expected) + { + for (auto const& [mode, val] : roundings) + { + NumberRoundModeGuard g{mode}; + auto const res = static_cast(num); + BEAST_EXPECTS( + res == val, + to_string(num) + " with mode " + std::to_string(mode) + + " expected " + std::to_string(val) + " got " + + std::to_string(res)); + } + } + } + void run() override { @@ -746,6 +855,7 @@ public: test_inc_dec(); test_toSTAmount(); test_truncate(); + testRounding(); } }; diff --git a/src/test/jtx.h b/src/test/jtx.h index 4c33495ad8..1d7f38ff54 100644 --- a/src/test/jtx.h +++ b/src/test/jtx.h @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include diff --git a/src/test/jtx/Env.h b/src/test/jtx/Env.h index 8bf579cdda..9858e17078 100644 --- a/src/test/jtx/Env.h +++ b/src/test/jtx/Env.h @@ -232,7 +232,9 @@ public: * * @param suite_ the current unit_test::suite */ - Env(beast::unit_test::suite& suite_) : Env(suite_, envconfig()) + Env(beast::unit_test::suite& suite_, + beast::severities::Severity thresh = beast::severities::kError) + : Env(suite_, envconfig(), nullptr, thresh) { } diff --git a/src/test/jtx/JTx.h b/src/test/jtx/JTx.h index d1160b0f34..2baaf8cd10 100644 --- a/src/test/jtx/JTx.h +++ b/src/test/jtx/JTx.h @@ -40,6 +40,9 @@ struct JTx // Functions that sign something else after the mainSigners, such as // sfCounterpartySignature std::vector> postSigners; + // Metadata about the unit test itself + // The line where the JTx was constructed + std::optional testLine = std::nullopt; JTx() = default; JTx(JTx const&) = default; diff --git a/src/test/jtx/TestHelpers.h b/src/test/jtx/TestHelpers.h index 82a01d2e59..5ae44acaac 100644 --- a/src/test/jtx/TestHelpers.h +++ b/src/test/jtx/TestHelpers.h @@ -160,6 +160,29 @@ public: } }; +struct stAmountField : public JTxField +{ + using SF = SF_AMOUNT; + using SV = STAmount; + using OV = Json::Value; + using base = JTxField; + +protected: + using base::value_; + +public: + explicit stAmountField(SF const& sfield, SV const& value) + : JTxField(sfield, value) + { + } + + OV + value() const override + { + return value_.getJson(JsonOptions::none); + } +}; + struct blobField : public JTxField { using SF = SF_VL; @@ -275,6 +298,8 @@ using simpleField = JTxFieldWrapper>; */ auto const data = JTxFieldWrapper(sfData); +auto const amount = JTxFieldWrapper(sfAmount); + // TODO We only need this long "requires" clause as polyfill, for C++20 // implementations which are missing header. Replace with // `std::ranges::range`, and accordingly use std::ranges::begin/end @@ -697,6 +722,110 @@ checkMetrics( line); } +/* LoanBroker */ +/******************************************************************************/ + +namespace loanBroker { + +Json::Value +set(AccountID const& account, uint256 const& vaultId, std::uint32_t flags = 0); + +// Use "del" because "delete" is a reserved word in C++. +Json::Value +del(AccountID const& account, uint256 const& brokerID, std::uint32_t flags = 0); + +Json::Value +coverDeposit( + AccountID const& account, + uint256 const& brokerID, + STAmount const& amount, + std::uint32_t flags = 0); + +Json::Value +coverWithdraw( + AccountID const& account, + uint256 const& brokerID, + STAmount const& amount, + std::uint32_t flags = 0); + +// Must specify at least one of loanBrokerID or amount. +Json::Value +coverClawback(AccountID const& account, std::uint32_t flags = 0); + +auto const loanBrokerID = JTxFieldWrapper(sfLoanBrokerID); + +auto const managementFeeRate = + valueUnitWrapper(sfManagementFeeRate); + +auto const debtMaximum = simpleField(sfDebtMaximum); + +auto const coverRateMinimum = + valueUnitWrapper(sfCoverRateMinimum); + +auto const coverRateLiquidation = + valueUnitWrapper(sfCoverRateLiquidation); + +auto const destination = JTxFieldWrapper(sfDestination); + +} // namespace loanBroker + +/* Loan */ +/******************************************************************************/ +namespace loan { + +Json::Value +set(AccountID const& account, + uint256 const& loanBrokerID, + Number principalRequested, + std::uint32_t flags = 0); + +auto const counterparty = JTxFieldWrapper(sfCounterparty); + +// For `CounterPartySignature`, use `sig(sfCounterpartySignature, ...)` + +auto const loanOriginationFee = simpleField(sfLoanOriginationFee); + +auto const loanServiceFee = simpleField(sfLoanServiceFee); + +auto const latePaymentFee = simpleField(sfLatePaymentFee); + +auto const closePaymentFee = simpleField(sfClosePaymentFee); + +auto const overpaymentFee = + valueUnitWrapper(sfOverpaymentFee); + +auto const interestRate = + valueUnitWrapper(sfInterestRate); + +auto const lateInterestRate = + valueUnitWrapper(sfLateInterestRate); + +auto const closeInterestRate = + valueUnitWrapper(sfCloseInterestRate); + +auto const overpaymentInterestRate = + valueUnitWrapper(sfOverpaymentInterestRate); + +auto const paymentTotal = simpleField(sfPaymentTotal); + +auto const paymentInterval = simpleField(sfPaymentInterval); + +auto const gracePeriod = simpleField(sfGracePeriod); + +Json::Value +manage(AccountID const& account, uint256 const& loanID, std::uint32_t flags); + +Json::Value +del(AccountID const& account, uint256 const& loanID, std::uint32_t flags = 0); + +Json::Value +pay(AccountID const& account, + uint256 const& loanID, + STAmount const& amount, + std::uint32_t flags = 0); + +} // namespace loan + } // namespace jtx } // namespace test } // namespace ripple diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index a5a73c59e8..ed0fa57cbf 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -213,6 +213,25 @@ public: { return {asset_}; } + + bool + integral() const + { + return asset_.integral(); + } + + bool + native() const + { + return asset_.native(); + } + + template + bool + holds() const + { + return asset_.holds(); + } }; //------------------------------------------------------------------------------ @@ -257,6 +276,21 @@ struct XRP_t return {TOut{v} * dropsPerXRP}; } + /** Returns an amount of XRP as PrettyAmount, + which is trivially convertable to STAmount + + @param v The Number of XRP (not drops). May be fractional. + */ + PrettyAmount + operator()(Number v) const + { + auto const c = dropsPerXRP.drops(); + auto const d = std::int64_t(v * c); + if (Number(d) / c != v) + Throw("unrepresentable"); + return {d}; + } + PrettyAmount operator()(double v) const { diff --git a/src/test/jtx/batch.h b/src/test/jtx/batch.h index 4c90c28a50..14122e3c01 100644 --- a/src/test/jtx/batch.h +++ b/src/test/jtx/batch.h @@ -49,8 +49,7 @@ public: inner( Json::Value const& txn, std::uint32_t const& sequence, - std::optional const& ticket = std::nullopt, - std::optional const& fee = std::nullopt) + std::optional const& ticket = std::nullopt) : txn_(txn), seq_(sequence), ticket_(ticket) { txn_[jss::SigningPubKey] = ""; diff --git a/src/test/jtx/impl/Env.cpp b/src/test/jtx/impl/Env.cpp index 2ef7879c97..9ce76d01c9 100644 --- a/src/test/jtx/impl/Env.cpp +++ b/src/test/jtx/impl/Env.cpp @@ -427,14 +427,16 @@ Env::postconditions( ParsedResult const& parsed, Json::Value const& jr) { - bool bad = !test.expect(parsed.ter, "apply: No ter result!"); + auto const line = jt.testLine ? " (" + to_string(*jt.testLine) + ")" : ""; + bool bad = !test.expect(parsed.ter, "apply: No ter result!" + line); bad = (jt.ter && parsed.ter && !test.expect( *parsed.ter == *jt.ter, "apply: Got " + transToken(*parsed.ter) + " (" + transHuman(*parsed.ter) + "); Expected " + - transToken(*jt.ter) + " (" + transHuman(*jt.ter) + ")")); + transToken(*jt.ter) + " (" + transHuman(*jt.ter) + ")" + + line)); using namespace std::string_literals; bad = (jt.rpcCode && !test.expect( @@ -446,21 +448,21 @@ Env::postconditions( : "NO RESULT") + " (" + parsed.rpcMessage + "); Expected " + RPC::get_error_info(jt.rpcCode->first).token.c_str() + " (" + - jt.rpcCode->second + ")")) || + jt.rpcCode->second + ")" + line)) || bad; // If we have an rpcCode (just checked), then the rpcException check is // optional - the 'error' field may not be defined, but if it is, it must // match rpcError. - bad = - (jt.rpcException && - !test.expect( - (jt.rpcCode && parsed.rpcError.empty()) || - (parsed.rpcError == jt.rpcException->first && - (!jt.rpcException->second || - parsed.rpcException == *jt.rpcException->second)), - "apply: Got RPC result "s + parsed.rpcError + " (" + - parsed.rpcException + "); Expected " + jt.rpcException->first + - " (" + jt.rpcException->second.value_or("n/a") + ")")) || + bad = (jt.rpcException && + !test.expect( + (jt.rpcCode && parsed.rpcError.empty()) || + (parsed.rpcError == jt.rpcException->first && + (!jt.rpcException->second || + parsed.rpcException == *jt.rpcException->second)), + "apply: Got RPC result "s + parsed.rpcError + " (" + + parsed.rpcException + "); Expected " + + jt.rpcException->first + " (" + + jt.rpcException->second.value_or("n/a") + ")" + line)) || bad; if (bad) { diff --git a/src/test/jtx/impl/TestHelpers.cpp b/src/test/jtx/impl/TestHelpers.cpp index 9ea3e8fb03..4dfc5fb7b1 100644 --- a/src/test/jtx/impl/TestHelpers.cpp +++ b/src/test/jtx/impl/TestHelpers.cpp @@ -356,6 +356,134 @@ allpe(AccountID const& a, Issue const& iss) iss.account); }; +/* LoanBroker */ +/******************************************************************************/ + +namespace loanBroker { + +Json::Value +set(AccountID const& account, uint256 const& vaultId, uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanBrokerSet; + jv[sfAccount] = to_string(account); + jv[sfVaultID] = to_string(vaultId); + jv[sfFlags] = flags; + return jv; +} + +Json::Value +del(AccountID const& account, uint256 const& brokerID, uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanBrokerDelete; + jv[sfAccount] = to_string(account); + jv[sfLoanBrokerID] = to_string(brokerID); + jv[sfFlags] = flags; + return jv; +} + +Json::Value +coverDeposit( + AccountID const& account, + uint256 const& brokerID, + STAmount const& amount, + uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanBrokerCoverDeposit; + jv[sfAccount] = to_string(account); + jv[sfLoanBrokerID] = to_string(brokerID); + jv[sfAmount] = amount.getJson(JsonOptions::none); + jv[sfFlags] = flags; + return jv; +} + +Json::Value +coverWithdraw( + AccountID const& account, + uint256 const& brokerID, + STAmount const& amount, + uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanBrokerCoverWithdraw; + jv[sfAccount] = to_string(account); + jv[sfLoanBrokerID] = to_string(brokerID); + jv[sfAmount] = amount.getJson(JsonOptions::none); + jv[sfFlags] = flags; + return jv; +} + +Json::Value +coverClawback(AccountID const& account, std::uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanBrokerCoverClawback; + jv[sfAccount] = to_string(account); + jv[sfFlags] = flags; + return jv; +} + +} // namespace loanBroker + +/* Loan */ +/******************************************************************************/ +namespace loan { + +Json::Value +set(AccountID const& account, + uint256 const& loanBrokerID, + Number principalRequested, + std::uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanSet; + jv[sfAccount] = to_string(account); + jv[sfLoanBrokerID] = to_string(loanBrokerID); + jv[sfPrincipalRequested] = to_string(principalRequested); + jv[sfFlags] = flags; + return jv; +} + +Json::Value +manage(AccountID const& account, uint256 const& loanID, std::uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanManage; + jv[sfAccount] = to_string(account); + jv[sfLoanID] = to_string(loanID); + jv[sfFlags] = flags; + return jv; +} + +Json::Value +del(AccountID const& account, uint256 const& loanID, std::uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanDelete; + jv[sfAccount] = to_string(account); + jv[sfLoanID] = to_string(loanID); + jv[sfFlags] = flags; + return jv; +} + +Json::Value +pay(AccountID const& account, + uint256 const& loanID, + STAmount const& amount, + std::uint32_t flags) +{ + Json::Value jv; + jv[sfTransactionType] = jss::LoanPay; + jv[sfAccount] = to_string(account); + jv[sfLoanID] = to_string(loanID); + jv[sfAmount] = amount.getJson(); + jv[sfFlags] = flags; + return jv; +} + +} // namespace loan } // namespace jtx } // namespace test } // namespace ripple diff --git a/src/test/jtx/impl/mpt.cpp b/src/test/jtx/impl/mpt.cpp index ca6c4c6cd5..fc831790f1 100644 --- a/src/test/jtx/impl/mpt.cpp +++ b/src/test/jtx/impl/mpt.cpp @@ -62,17 +62,67 @@ MPTTester::MPTTester(Env& env, Account const& issuer, MPTInit const& arg) env_.require(owners(it.second, 0)); } } + if (arg.create) + create(*arg.create); } -void -MPTTester::create(MPTCreate const& arg) +MPTTester::MPTTester( + Env& env, + Account const& issuer, + MPTID const& id, + std::vector const& holders, + bool close) + : env_(env) + , issuer_(issuer) + , holders_(makeHolders(holders)) + , id_(id) + , close_(close) { - if (id_) - Throw("MPT can't be reused"); - id_ = makeMptID(env_.seq(issuer_), issuer_); +} + +static MPTCreate +makeMPTCreate(MPTInitDef const& arg) +{ + if (arg.pay) + return { + .maxAmt = arg.maxAmt, + .transferFee = arg.transferFee, + .pay = {{arg.holders, *arg.pay}}, + .flags = arg.flags, + .authHolder = arg.authHolder}; + return { + .maxAmt = arg.maxAmt, + .transferFee = arg.transferFee, + .authorize = arg.holders, + .flags = arg.flags, + .authHolder = arg.authHolder}; +} + +MPTTester::MPTTester(MPTInitDef const& arg) + : MPTTester{ + arg.env, + arg.issuer, + MPTInit{ + .fund = arg.fund, + .close = arg.close, + .create = makeMPTCreate(arg)}} +{ +} + +MPTTester::operator MPT() const +{ + if (!id_) + Throw("MPT has not been created"); + return MPT("", *id_); +} + +Json::Value +MPTTester::createjv(MPTCreate const& arg) +{ + if (!arg.issuer) + Throw("MPTTester::createjv: issuer is not set"); Json::Value jv; - jv[sfAccount] = issuer_.human(); - jv[sfTransactionType] = jss::MPTokenIssuanceCreate; + jv[sfAccount] = arg.issuer->human(); if (arg.assetScale) jv[sfAssetScale] = *arg.assetScale; if (arg.transferFee) @@ -85,6 +135,25 @@ MPTTester::create(MPTCreate const& arg) jv[sfDomainID] = to_string(*arg.domainID); if (arg.mutableFlags) jv[sfMutableFlags] = *arg.mutableFlags; + jv[sfTransactionType] = jss::MPTokenIssuanceCreate; + + return jv; +} + +void +MPTTester::create(MPTCreate const& arg) +{ + if (id_) + Throw("MPT can't be reused"); + id_ = makeMptID(env_.seq(issuer_), issuer_); + Json::Value jv = createjv( + {.issuer = issuer_, + .maxAmt = arg.maxAmt, + .assetScale = arg.assetScale, + .transferFee = arg.transferFee, + .metadata = arg.metadata, + .mutableFlags = arg.mutableFlags, + .domainID = arg.domainID}); if (submit(arg, jv) != tesSUCCESS) { // Verify issuance doesn't exist @@ -95,26 +164,62 @@ MPTTester::create(MPTCreate const& arg) id_.reset(); } else + { env_.require(mptflags(*this, arg.flags.value_or(0))); + auto authAndPay = [&](auto const& accts, auto const&& getAcct) { + for (auto const& it : accts) + { + authorize({.account = getAcct(it)}); + if ((arg.flags.value_or(0) & tfMPTRequireAuth) && + arg.authHolder) + authorize({.account = issuer_, .holder = getAcct(it)}); + if (arg.pay && arg.pay->first.empty()) + pay(issuer_, getAcct(it), arg.pay->second); + } + if (arg.pay) + { + for (auto const& p : arg.pay->first) + pay(issuer_, p, arg.pay->second); + } + }; + if (arg.authorize) + { + if (arg.authorize->empty()) + authAndPay(holders_, [](auto const& it) { return it.second; }); + else + authAndPay(*arg.authorize, [](auto const& it) { return it; }); + } + else if (arg.pay) + { + if (arg.pay->first.empty()) + authAndPay(holders_, [](auto const& it) { return it.second; }); + else + authAndPay(arg.pay->first, [](auto const& it) { return it; }); + } + } +} + +Json::Value +MPTTester::destroyjv(MPTDestroy const& arg) +{ + Json::Value jv; + if (!arg.issuer || !arg.id) + Throw("MPTTester::destroyjv: issuer/id is not set"); + jv[sfAccount] = arg.issuer->human(); + jv[sfMPTokenIssuanceID] = to_string(*arg.id); + jv[sfTransactionType] = jss::MPTokenIssuanceDestroy; + + return jv; } void MPTTester::destroy(MPTDestroy const& arg) { - Json::Value jv; - if (arg.issuer) - jv[sfAccount] = arg.issuer->human(); - else - jv[sfAccount] = issuer_.human(); - if (arg.id) - jv[sfMPTokenIssuanceID] = to_string(*arg.id); - else - { - if (!id_) - Throw("MPT has not been created"); - jv[sfMPTokenIssuanceID] = to_string(*id_); - } - jv[sfTransactionType] = jss::MPTokenIssuanceDestroy; + if (!arg.id && !id_) + Throw("MPT has not been created"); + Json::Value jv = destroyjv( + {.issuer = arg.issuer ? arg.issuer : issuer_, + .id = arg.id ? arg.id : id_}); submit(arg, jv); } @@ -127,25 +232,32 @@ MPTTester::holder(std::string const& holder_) const return it->second; } +Json::Value +MPTTester::authorizejv(MPTAuthorize const& arg) +{ + Json::Value jv; + if (!arg.account || !arg.id) + Throw( + "MPTTester::authorizejv: issuer/id is not set"); + jv[sfAccount] = arg.account->human(); + jv[sfMPTokenIssuanceID] = to_string(*arg.id); + if (arg.holder) + jv[sfHolder] = arg.holder->human(); + jv[sfTransactionType] = jss::MPTokenAuthorize; + + return jv; +} + void MPTTester::authorize(MPTAuthorize const& arg) { - Json::Value jv; - if (arg.account) - jv[sfAccount] = arg.account->human(); - else - jv[sfAccount] = issuer_.human(); - jv[sfTransactionType] = jss::MPTokenAuthorize; - if (arg.id) - jv[sfMPTokenIssuanceID] = to_string(*arg.id); - else - { - if (!id_) - Throw("MPT has not been created"); - jv[sfMPTokenIssuanceID] = to_string(*id_); - } - if (arg.holder) - jv[sfHolder] = arg.holder->human(); + if (!arg.id && !id_) + Throw("MPT has not been created"); + Json::Value jv = authorizejv({ + .account = arg.account ? arg.account : issuer_, + .holder = arg.holder, + .id = arg.id ? arg.id : id_, + }); if (auto const result = submit(arg, jv); result == tesSUCCESS) { // Issuer authorizes @@ -201,24 +313,34 @@ MPTTester::authorize(MPTAuthorize const& arg) } void -MPTTester::set(MPTSet const& arg) +MPTTester::authorizeHolders(Holders const& holders) +{ + for (auto const& holder : holders) + { + authorize({.account = holder}); + } +} + +Json::Value +MPTTester::setjv(MPTSet const& arg) { Json::Value jv; - if (arg.account) - jv[sfAccount] = arg.account->human(); - else - jv[sfAccount] = issuer_.human(); - jv[sfTransactionType] = jss::MPTokenIssuanceSet; - if (arg.id) - jv[sfMPTokenIssuanceID] = to_string(*arg.id); - else - { - if (!id_) - Throw("MPT has not been created"); - jv[sfMPTokenIssuanceID] = to_string(*id_); - } + if (!arg.account || !arg.id) + Throw("MPTTester::setjv: issuer/id is not set"); + jv[sfAccount] = arg.account->human(); + jv[sfMPTokenIssuanceID] = to_string(*arg.id); if (arg.holder) - jv[sfHolder] = arg.holder->human(); + { + std::visit( + [&jv](T const& holder) { + if constexpr (std::is_same_v) + jv[sfHolder] = holder.human(); + else if constexpr (std::is_same_v) + jv[sfHolder] = toBase58(holder); + }, + *arg.holder); + } + if (arg.delegate) jv[sfDelegate] = arg.delegate->human(); if (arg.domainID) @@ -229,7 +351,27 @@ MPTTester::set(MPTSet const& arg) jv[sfTransferFee] = *arg.transferFee; if (arg.metadata) jv[sfMPTokenMetadata] = strHex(*arg.metadata); - if (submit(arg, jv) == tesSUCCESS && (arg.flags || arg.mutableFlags)) + jv[sfTransactionType] = jss::MPTokenIssuanceSet; + + return jv; +} + +void +MPTTester::set(MPTSet const& arg) +{ + if (!arg.id && !id_) + Throw("MPT has not been created"); + Json::Value jv = setjv( + {.account = arg.account ? arg.account : issuer_, + .holder = arg.holder, + .id = arg.id ? arg.id : id_, + .mutableFlags = arg.mutableFlags, + .transferFee = arg.transferFee, + .metadata = arg.metadata, + .delegate = arg.delegate, + .domainID = arg.domainID}); + if (submit(arg, jv) == tesSUCCESS && + (arg.flags.value_or(0) || arg.mutableFlags)) { auto require = [&](std::optional const& holder, bool unchanged) { @@ -281,8 +423,9 @@ MPTTester::set(MPTSet const& arg) }; if (arg.account) require(std::nullopt, arg.holder.has_value()); - if (arg.holder) - require(*arg.holder, false); + if (auto const account = + (arg.holder ? std::get_if(&(*arg.holder)) : nullptr)) + require(*account, false); } } @@ -455,6 +598,13 @@ MPTTester::mpt(std::int64_t amount) const return ripple::test::jtx::MPT(issuer_.name(), *id_)(amount); } +MPTTester::operator Asset() const +{ + if (!id_) + Throw("MPT has not been created"); + return Asset(*id_); +} + std::int64_t MPTTester::getBalance(Account const& account) const { @@ -493,6 +643,12 @@ MPTTester::operator[](std::string const& name) const return MPT(name, issuanceID()); } +PrettyAmount +MPTTester::operator()(std::uint64_t amount) const +{ + return MPT("", issuanceID())(amount); +} + } // namespace jtx } // namespace test } // namespace ripple diff --git a/src/test/jtx/impl/testline.cpp b/src/test/jtx/impl/testline.cpp new file mode 100644 index 0000000000..722dc33bff --- /dev/null +++ b/src/test/jtx/impl/testline.cpp @@ -0,0 +1,15 @@ +#include + +namespace ripple { +namespace test { +namespace jtx { + +void +testline::operator()(Env&, JTx& jt) const +{ + jt.testLine = line_; +} + +} // namespace jtx +} // namespace test +} // namespace ripple diff --git a/src/test/jtx/mpt.h b/src/test/jtx/mpt.h index 85c842737c..f9c58ebc9e 100644 --- a/src/test/jtx/mpt.h +++ b/src/test/jtx/mpt.h @@ -14,6 +14,8 @@ namespace jtx { class MPTTester; +auto const MPTDEXFlags = tfMPTCanTrade | tfMPTCanTransfer; + // Check flags settings on MPT create class mptflags { @@ -67,31 +69,59 @@ public: operator()(Env& env) const; }; -struct MPTInit -{ - std::vector holders = {}; - PrettyAmount const xrp = XRP(10'000); - PrettyAmount const xrpHolders = XRP(10'000); - bool fund = true; - bool close = true; -}; -static MPTInit const mptInitNoFund{.fund = false}; +using Holders = std::vector; struct MPTCreate { + static inline std::vector AllHolders = {}; + std::optional issuer = std::nullopt; std::optional maxAmt = std::nullopt; std::optional assetScale = std::nullopt; std::optional transferFee = std::nullopt; std::optional metadata = std::nullopt; std::optional ownerCount = std::nullopt; std::optional holderCount = std::nullopt; - bool fund = true; + // authorize if seated. + // if empty vector then authorize all holders + std::optional> authorize = std::nullopt; + // pay if seated. if authorize is not seated then authorize. + // if empty vector then pay to either authorize or all holders. + std::optional, std::uint64_t>> pay = + std::nullopt; std::optional flags = {0}; std::optional mutableFlags = std::nullopt; + bool authHolder = false; std::optional domainID = std::nullopt; std::optional err = std::nullopt; }; +struct MPTInit +{ + Holders holders = {}; + PrettyAmount const xrp = XRP(10'000); + PrettyAmount const xrpHolders = XRP(10'000); + bool fund = true; + bool close = true; + // create MPTIssuanceID if seated and follow rules for MPTCreate args + std::optional create = std::nullopt; +}; +static MPTInit const mptInitNoFund{.fund = false}; + +struct MPTInitDef +{ + Env& env; + Account issuer; + Holders holders = {}; + std::uint16_t transferFee = 0; + std::optional pay = std::nullopt; + std::uint32_t flags = MPTDEXFlags; + bool authHolder = false; + bool fund = false; + bool close = true; + std::optional maxAmt = std::nullopt; + std::optional err = std::nullopt; +}; + struct MPTDestroy { std::optional issuer = std::nullopt; @@ -116,7 +146,7 @@ struct MPTAuthorize struct MPTSet { std::optional account = std::nullopt; - std::optional holder = std::nullopt; + std::optional> holder = std::nullopt; std::optional id = std::nullopt; std::optional ownerCount = std::nullopt; std::optional holderCount = std::nullopt; @@ -132,26 +162,49 @@ struct MPTSet class MPTTester { Env& env_; - Account const& issuer_; + Account const issuer_; std::unordered_map const holders_; std::optional id_; bool close_; public: MPTTester(Env& env, Account const& issuer, MPTInit const& constr = {}); + MPTTester(MPTInitDef const& constr); + MPTTester( + Env& env, + Account const& issuer, + MPTID const& id, + std::vector const& holders = {}, + bool close = true); + operator MPT() const; void create(MPTCreate const& arg = MPTCreate{}); + static Json::Value + createjv(MPTCreate const& arg = MPTCreate{}); + void destroy(MPTDestroy const& arg = MPTDestroy{}); + static Json::Value + destroyjv(MPTDestroy const& arg = MPTDestroy{}); + void authorize(MPTAuthorize const& arg = MPTAuthorize{}); + static Json::Value + authorizejv(MPTAuthorize const& arg = MPTAuthorize{}); + + void + authorizeHolders(Holders const& holders); + void set(MPTSet const& set = {}); + static Json::Value + setjv(MPTSet const& set = {}); + [[nodiscard]] bool checkDomainID(std::optional expected) const; @@ -218,8 +271,13 @@ public: MPT operator[](std::string const& name) const; + PrettyAmount + operator()(std::uint64_t amount) const; + + operator Asset() const; + private: - using SLEP = std::shared_ptr; + using SLEP = SLE::const_pointer; bool forObject( std::function const& cb, diff --git a/src/test/jtx/testline.h b/src/test/jtx/testline.h new file mode 100644 index 0000000000..65dd3b7d92 --- /dev/null +++ b/src/test/jtx/testline.h @@ -0,0 +1,34 @@ +#ifndef XRPL_TEST_JTX_TESTLINE_H_INCLUDED +#define XRPL_TEST_JTX_TESTLINE_H_INCLUDED + +#include + +namespace ripple { +namespace test { +namespace jtx { + +/** Store the line number of the current test in a JTx. + + Intended to help debug failing transaction submission tests. +*/ +class testline +{ +private: + int line_; + +public: + explicit testline(int line) : line_(line) + { + } + + void + operator()(Env&, JTx& jt) const; +}; + +#define THISLINE testline(__LINE__) + +} // namespace jtx +} // namespace test +} // namespace ripple + +#endif diff --git a/src/test/protocol/STParsedJSON_test.cpp b/src/test/protocol/STParsedJSON_test.cpp index 7ad7e36097..13983444da 100644 --- a/src/test/protocol/STParsedJSON_test.cpp +++ b/src/test/protocol/STParsedJSON_test.cpp @@ -724,63 +724,63 @@ class STParsedJSON_test : public beast::unit_test::suite { Json::Value j; int const minInt32 = -2147483648; - j[sfDummyInt32] = minInt32; + j[sfLoanScale] = minInt32; STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); - if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32))) - BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == minInt32); + if (BEAST_EXPECT(obj.object->isFieldPresent(sfLoanScale))) + BEAST_EXPECT(obj.object->getFieldI32(sfLoanScale) == minInt32); } // max value { Json::Value j; int const maxInt32 = 2147483647; - j[sfDummyInt32] = maxInt32; + j[sfLoanScale] = maxInt32; STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); - if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32))) - BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == maxInt32); + if (BEAST_EXPECT(obj.object->isFieldPresent(sfLoanScale))) + BEAST_EXPECT(obj.object->getFieldI32(sfLoanScale) == maxInt32); } // max uint value { Json::Value j; unsigned int const maxUInt32 = 2147483647u; - j[sfDummyInt32] = maxUInt32; + j[sfLoanScale] = maxUInt32; STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); - if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32))) + if (BEAST_EXPECT(obj.object->isFieldPresent(sfLoanScale))) BEAST_EXPECT( - obj.object->getFieldI32(sfDummyInt32) == + obj.object->getFieldI32(sfLoanScale) == static_cast(maxUInt32)); } // Test with string value { Json::Value j; - j[sfDummyInt32] = "2147483647"; + j[sfLoanScale] = "2147483647"; STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); - if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32))) + if (BEAST_EXPECT(obj.object->isFieldPresent(sfLoanScale))) BEAST_EXPECT( - obj.object->getFieldI32(sfDummyInt32) == 2147483647u); + obj.object->getFieldI32(sfLoanScale) == 2147483647u); } // Test with string negative value { Json::Value j; int value = -2147483648; - j[sfDummyInt32] = std::to_string(value); + j[sfLoanScale] = std::to_string(value); STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); - if (BEAST_EXPECT(obj.object->isFieldPresent(sfDummyInt32))) - BEAST_EXPECT(obj.object->getFieldI32(sfDummyInt32) == value); + if (BEAST_EXPECT(obj.object->isFieldPresent(sfLoanScale))) + BEAST_EXPECT(obj.object->getFieldI32(sfLoanScale) == value); } // Test out of range value for int32 (negative) { Json::Value j; - j[sfDummyInt32] = "-2147483649"; + j[sfLoanScale] = "-2147483649"; STParsedJSONObject obj("Test", j); BEAST_EXPECT(!obj.object.has_value()); } @@ -788,7 +788,7 @@ class STParsedJSON_test : public beast::unit_test::suite // Test out of range value for int32 (positive) { Json::Value j; - j[sfDummyInt32] = 2147483648u; + j[sfLoanScale] = 2147483648u; STParsedJSONObject obj("Test", j); BEAST_EXPECT(!obj.object.has_value()); } @@ -796,7 +796,7 @@ class STParsedJSON_test : public beast::unit_test::suite // Test string value out of range { Json::Value j; - j[sfDummyInt32] = "2147483648"; + j[sfLoanScale] = "2147483648"; STParsedJSONObject obj("Test", j); BEAST_EXPECT(!obj.object.has_value()); } @@ -804,7 +804,7 @@ class STParsedJSON_test : public beast::unit_test::suite // Test bad_type (arrayValue) { Json::Value j; - j[sfDummyInt32] = Json::Value(Json::arrayValue); + j[sfLoanScale] = Json::Value(Json::arrayValue); STParsedJSONObject obj("Test", j); BEAST_EXPECT(!obj.object.has_value()); } @@ -812,7 +812,7 @@ class STParsedJSON_test : public beast::unit_test::suite // Test bad_type (objectValue) { Json::Value j; - j[sfDummyInt32] = Json::Value(Json::objectValue); + j[sfLoanScale] = Json::Value(Json::objectValue); STParsedJSONObject obj("Test", j); BEAST_EXPECT(!obj.object.has_value()); } diff --git a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp index bee90346b4..4b068882c9 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp @@ -280,7 +280,7 @@ LedgerReplayTask::addDelta(std::shared_ptr const& delta) deltas_.empty() || deltas_.back()->ledgerSeq_ + 1 == delta->ledgerSeq_, "ripple::LedgerReplayTask::addDelta : no deltas or consecutive " - "sequence", ); + "sequence"); deltas_.push_back(delta); } } diff --git a/src/xrpld/app/ledger/detail/OpenLedger.cpp b/src/xrpld/app/ledger/detail/OpenLedger.cpp index 1a009c91c7..14db13aad4 100644 --- a/src/xrpld/app/ledger/detail/OpenLedger.cpp +++ b/src/xrpld/app/ledger/detail/OpenLedger.cpp @@ -105,8 +105,11 @@ OpenLedger::accept( auto const txId = tx->getTransactionID(); // skip batch txns + // The flag should only be settable if Batch feature is enabled. If + // Batch is not enabled, the flag is always invalid, so don't relay it + // regardless. // LCOV_EXCL_START - if (tx->isFlag(tfInnerBatchTxn) && rules.enabled(featureBatch)) + if (tx->isFlag(tfInnerBatchTxn)) { XRPL_ASSERT( txpair.second && txpair.second->isFieldPresent(sfParentBatchID), diff --git a/src/xrpld/app/misc/LendingHelpers.h b/src/xrpld/app/misc/LendingHelpers.h new file mode 100644 index 0000000000..559af28a47 --- /dev/null +++ b/src/xrpld/app/misc/LendingHelpers.h @@ -0,0 +1,444 @@ +#ifndef XRPL_APP_MISC_LENDINGHELPERS_H_INCLUDED +#define XRPL_APP_MISC_LENDINGHELPERS_H_INCLUDED + +#include +#include + +namespace ripple { + +struct PreflightContext; + +// Lending protocol has dependencies, so capture them here. +bool +checkLendingProtocolDependencies(PreflightContext const& ctx); + +static constexpr std::uint32_t secondsInYear = 365 * 24 * 60 * 60; + +Number +loanPeriodicRate(TenthBips32 interestRate, std::uint32_t paymentInterval); + +/// Ensure the periodic payment is always rounded consistently +inline Number +roundPeriodicPayment( + Asset const& asset, + Number const& periodicPayment, + std::int32_t scale) +{ + return roundToAsset(asset, periodicPayment, scale, Number::upward); +} + +/* Represents the breakdown of amounts to be paid and changes applied to the + * Loan object while processing a loan payment. + * + * This structure is returned after processing a loan payment transaction and + * captures the amounts that need to be paid. The actual ledger entry changes + * are made in LoanPay based on this structure values. + * + * The sum of principalPaid, interestPaid, and feePaid represents the total + * amount to be deducted from the borrower's account. The valueChange field + * tracks whether the loan's total value increased or decreased beyond normal + * amortization. + * + * This structure is explained in the XLS-66 spec, section 3.2.4.2 (Payment + * Processing). + */ +struct LoanPaymentParts +{ + // The amount of principal paid that reduces the loan balance. + // This amount is subtracted from sfPrincipalOutstanding in the Loan object + // and paid to the Vault + Number principalPaid = numZero; + + // The total amount of interest paid to the Vault. + // This includes: + // - Tracked interest from the amortization schedule + // - Untracked interest (e.g., late payment penalty interest) + // This value is always non-negative. + Number interestPaid = numZero; + + // The change in the loan's total value outstanding. + // - If valueChange < 0: Loan value decreased + // - If valueChange > 0: Loan value increased + // - If valueChange = 0: No value adjustment + // + // For regular on-time payments, this is always 0. Non-zero values occur + // when: + // - Overpayments reduce the loan balance beyond the scheduled amount + // - Late payments add penalty interest to the loan value + // - Early full payment may increase or decrease the loan value based on + // terms + Number valueChange = numZero; + + /* The total amount of fees paid to the Broker. + * This includes: + * - Tracked management fees from the amortization schedule + * - Untracked fees (e.g., late payment fees, service fees, origination + * fees) This value is always non-negative. + */ + Number feePaid = numZero; + + LoanPaymentParts& + operator+=(LoanPaymentParts const& other); + + bool + operator==(LoanPaymentParts const& other) const; +}; + +/* Describes the initial computed properties of a loan. + * + * This structure contains the fundamental calculated values that define a + * loan's payment structure and amortization schedule. These properties are + * computed: + * - At loan creation (LoanSet transaction) + * - When loan terms change (e.g., after an overpayment that reduces the loan + * balance) + */ +struct LoanProperties +{ + // The unrounded amount to be paid at each regular payment period. + // Calculated using the standard amortization formula based on principal, + // interest rate, and number of payments. + // The actual amount paid in the LoanPay transaction must be rounded up to + // the precision of the asset and loan. + Number periodicPayment; + + // The total amount the borrower will pay over the life of the loan. + // Equal to periodicPayment * paymentsRemaining. + // This includes principal, interest, and management fees. + Number totalValueOutstanding; + + // The total management fee that will be paid to the broker over the + // loan's lifetime. This is a percentage of the total interest (gross) + // as specified by the broker's management fee rate. + Number managementFeeOwedToBroker; + + // The scale (decimal places) used for rounding all loan amounts. + // This is the maximum of: + // - The asset's native scale + // - A minimum scale required to represent the periodic payment accurately + // All loan state values (principal, interest, fees) are rounded to this + // scale. + std::int32_t loanScale; + + // The principal portion of the first payment. + Number firstPaymentPrincipal; +}; + +/** This structure captures the parts of a loan state. + * + * Whether the values are raw (unrounded) or rounded will depend on how it was + * computed. + * + * Many of the fields can be derived from each other, but they're all provided + * here to reduce code duplication and possible mistakes. + * e.g. + * * interestOutstanding = valueOutstanding - principalOutstanding + * * interestDue = interestOutstanding - managementFeeDue + */ +struct LoanState +{ + // Total value still due to be paid by the borrower. + Number valueOutstanding; + // Principal still due to be paid by the borrower. + Number principalOutstanding; + // Interest still due to be paid to the Vault. + // This is a portion of interestOutstanding + Number interestDue; + // Management fee still due to be paid to the broker. + // This is a portion of interestOutstanding + Number managementFeeDue; + + // Interest still due to be paid by the borrower. + Number + interestOutstanding() const + { + XRPL_ASSERT_PARTS( + interestDue + managementFeeDue == + valueOutstanding - principalOutstanding, + "ripple::LoanState::interestOutstanding", + "other values add up correctly"); + return interestDue + managementFeeDue; + } +}; + +// Some values get re-rounded to the vault scale any time they are adjusted. In +// addition, they are prevented from ever going below zero. This helps avoid +// accumulated rounding errors and leftover dust amounts. +template +void +adjustImpreciseNumber( + NumberProxy value, + Number const& adjustment, + Asset const& asset, + int vaultScale) +{ + value = roundToAsset(asset, value + adjustment, vaultScale); + + if (*value < beast::zero) + value = 0; +} + +inline int +getVaultScale(SLE::const_ref vaultSle) +{ + if (!vaultSle) + return Number::minExponent - 1; // LCOV_EXCL_LINE + return vaultSle->at(sfAssetsTotal).exponent(); +} + +TER +checkLoanGuards( + Asset const& vaultAsset, + Number const& principalRequested, + bool expectInterest, + std::uint32_t paymentTotal, + LoanProperties const& properties, + beast::Journal j); + +LoanState +computeRawLoanState( + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t const paymentRemaining, + TenthBips32 const managementFeeRate); + +LoanState +computeRawLoanState( + Number const& periodicPayment, + TenthBips32 interestRate, + std::uint32_t paymentInterval, + std::uint32_t const paymentRemaining, + TenthBips32 const managementFeeRate); + +// Constructs a valid LoanState object from arbitrary inputs +LoanState +constructLoanState( + Number const& totalValueOutstanding, + Number const& principalOutstanding, + Number const& managementFeeOutstanding); + +// Constructs a valid LoanState object from a Loan object, which always has +// rounded values +LoanState +constructRoundedLoanState(SLE::const_ref loan); + +Number +computeManagementFee( + Asset const& asset, + Number const& interest, + TenthBips32 managementFeeRate, + std::int32_t scale); + +Number +computeFullPaymentInterest( + Number const& rawPrincipalOutstanding, + Number const& periodicRate, + NetClock::time_point parentCloseTime, + std::uint32_t paymentInterval, + std::uint32_t prevPaymentDate, + std::uint32_t startDate, + TenthBips32 closeInterestRate); + +Number +computeFullPaymentInterest( + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t paymentRemaining, + NetClock::time_point parentCloseTime, + std::uint32_t paymentInterval, + std::uint32_t prevPaymentDate, + std::uint32_t startDate, + TenthBips32 closeInterestRate); + +namespace detail { +// These classes and functions should only be accessed by LendingHelper +// functions and unit tests + +enum class PaymentSpecialCase { none, final, extra }; + +/* Represents a single loan payment component parts. + +* This structure captures the "delta" (change) values that will be applied to +* the tracked fields in the Loan ledger object when a payment is processed. +* +* These are called "deltas" because they represent the amount by which each +* corresponding field in the Loan object will be reduced. +* They are "tracked" as they change tracked loan values. +*/ +struct PaymentComponents +{ + // The change in total value outstanding for this payment. + // This amount will be subtracted from sfTotalValueOutstanding in the Loan + // object. Equal to the sum of trackedPrincipalDelta, + // trackedInterestPart(), and trackedManagementFeeDelta. + Number trackedValueDelta; + + // The change in principal outstanding for this payment. + // This amount will be subtracted from sfPrincipalOutstanding in the Loan + // object, representing the portion of the payment that reduces the + // original loan amount. + Number trackedPrincipalDelta; + + // The change in management fee outstanding for this payment. + // This amount will be subtracted from sfManagementFeeOutstanding in the + // Loan object. This represents only the tracked management fees from the + // amortization schedule and does not include additional untracked fees + // (such as late payment fees) that go directly to the broker. + Number trackedManagementFeeDelta; + + // Indicates if this payment has special handling requirements. + // - none: Regular scheduled payment + // - final: The last payment that closes out the loan + // - extra: An additional payment beyond the regular schedule (overpayment) + PaymentSpecialCase specialCase = PaymentSpecialCase::none; + + // Calculates the tracked interest portion of this payment. + // This is derived from the other components as: + // trackedValueDelta - trackedPrincipalDelta - trackedManagementFeeDelta + // + // @return The amount of tracked interest included in this payment that + // will be paid to the vault. + Number + trackedInterestPart() const; +}; + +/* Extends PaymentComponents with untracked payment amounts. + * + * This structure adds untracked fees and interest to the base + * PaymentComponents, representing amounts that don't affect the Loan object's + * tracked state but are still part of the total payment due from the borrower. + * + * Untracked amounts include: + * - Late payment fees that go directly to the Broker + * - Late payment penalty interest that goes directly to the Vault + * - Service fees + * + * The key distinction is that tracked amounts reduce the Loan object's state + * (sfTotalValueOutstanding, sfPrincipalOutstanding, + * sfManagementFeeOutstanding), while untracked amounts are paid directly to the + * recipient without affecting the loan's amortization schedule. + */ +struct ExtendedPaymentComponents : public PaymentComponents +{ + // Additional management fees that go directly to the Broker. + // This includes fees not part of the standard amortization schedule + // (e.g., late fees, service fees, origination fees). + // This value may be negative, though the final value returned in + // LoanPaymentParts.feePaid will never be negative. + Number untrackedManagementFee; + + // Additional interest that goes directly to the Vault. + // This includes interest not part of the standard amortization schedule + // (e.g., late payment penalty interest). + // This value may be negative, though the final value returned in + // LoanPaymentParts.interestPaid will never be negative. + Number untrackedInterest; + + // The complete amount due from the borrower for this payment. + // Calculated as: trackedValueDelta + untrackedInterest + + // untrackedManagementFee + // + // This value is used to validate that the payment amount provided by the + // borrower is sufficient to cover all components of the payment. + Number totalDue; + + ExtendedPaymentComponents( + PaymentComponents const& p, + Number fee, + Number interest = numZero) + : PaymentComponents(p) + , untrackedManagementFee(fee) + , untrackedInterest(interest) + , totalDue( + trackedValueDelta + untrackedInterest + untrackedManagementFee) + { + } +}; + +/* Represents the differences between two loan states. + * + * This structure is used to capture the change in each component of a loan's + * state, typically when computing the difference between two LoanState objects + * (e.g., before and after a payment). It is a convenient way to capture changes + * in each component. How that difference is used depends on the context. + */ +struct LoanStateDeltas +{ + // The difference in principal outstanding between two loan states. + Number principal; + + // The difference in interest due between two loan states. + Number interest; + + // The difference in management fee outstanding between two loan states. + Number managementFee; + + /* Calculates the total change across all components. + * @return The sum of principal, interest, and management fee deltas. + */ + Number + total() const + { + return principal + interest + managementFee; + } + + // Ensures all delta values are non-negative. + void + nonNegative(); +}; + +PaymentComponents +computePaymentComponents( + Asset const& asset, + std::int32_t scale, + Number const& totalValueOutstanding, + Number const& principalOutstanding, + Number const& managementFeeOutstanding, + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t paymentRemaining, + TenthBips16 managementFeeRate); + +} // namespace detail + +detail::LoanStateDeltas +operator-(LoanState const& lhs, LoanState const& rhs); + +LoanState +operator-(LoanState const& lhs, detail::LoanStateDeltas const& rhs); + +LoanState +operator+(LoanState const& lhs, detail::LoanStateDeltas const& rhs); + +LoanProperties +computeLoanProperties( + Asset const& asset, + Number principalOutstanding, + TenthBips32 interestRate, + std::uint32_t paymentInterval, + std::uint32_t paymentsRemaining, + TenthBips32 managementFeeRate, + std::int32_t minimumScale); + +bool +isRounded(Asset const& asset, Number const& value, std::int32_t scale); + +// Indicates what type of payment is being made. +// regular, late, and full are mutually exclusive. +// overpayment is an "add on" to a regular payment, and follows that path with +// potential extra work at the end. +enum class LoanPaymentType { regular = 0, late, full, overpayment }; + +Expected +loanMakePayment( + Asset const& asset, + ApplyView& view, + SLE::ref loan, + SLE::const_ref brokerSle, + STAmount const& amount, + LoanPaymentType const paymentType, + beast::Journal j); + +} // namespace ripple + +#endif // XRPL_APP_MISC_LENDINGHELPERS_H_INCLUDED diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index 963f3dc3ea..157de028e5 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -1677,10 +1677,11 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) app_.getHashRouter().shouldRelay(e.transaction->getID()); if (auto const sttx = *(e.transaction->getSTransaction()); toSkip && - // Skip relaying if it's an inner batch txn and batch - // feature is enabled - !(sttx.isFlag(tfInnerBatchTxn) && - newOL->rules().enabled(featureBatch))) + // Skip relaying if it's an inner batch txn. The flag should + // only be set if the Batch feature is enabled. If Batch is + // not enabled, the flag is always invalid, so don't relay + // it regardless. + !sttx.isFlag(tfInnerBatchTxn)) { protocol::TMTransaction tx; Serializer s; @@ -3040,9 +3041,11 @@ NetworkOPsImp::pubProposedTransaction( std::shared_ptr const& transaction, TER result) { - // never publish an inner txn inside a batch txn - if (transaction->isFlag(tfInnerBatchTxn) && - ledger->rules().enabled(featureBatch)) + // never publish an inner txn inside a batch txn. The flag should + // only be set if the Batch feature is enabled. If Batch is not + // enabled, the flag is always invalid, so don't publish it + // regardless. + if (transaction->isFlag(tfInnerBatchTxn)) return; MultiApiJson jvObj = diff --git a/src/xrpld/app/misc/detail/LendingHelpers.cpp b/src/xrpld/app/misc/detail/LendingHelpers.cpp new file mode 100644 index 0000000000..8020b47ba9 --- /dev/null +++ b/src/xrpld/app/misc/detail/LendingHelpers.cpp @@ -0,0 +1,2058 @@ +#include +// DO NOT REMOVE forces header file include to sort first +#include + +namespace ripple { + +bool +checkLendingProtocolDependencies(PreflightContext const& ctx) +{ + return ctx.rules.enabled(featureSingleAssetVault) && + VaultCreate::checkExtraFeatures(ctx); +} + +LoanPaymentParts& +LoanPaymentParts::operator+=(LoanPaymentParts const& other) +{ + XRPL_ASSERT( + + other.principalPaid >= beast::zero, + "ripple::LoanPaymentParts::operator+= : other principal " + "non-negative"); + XRPL_ASSERT( + other.interestPaid >= beast::zero, + "ripple::LoanPaymentParts::operator+= : other interest paid " + "non-negative"); + XRPL_ASSERT( + other.feePaid >= beast::zero, + "ripple::LoanPaymentParts::operator+= : other fee paid " + "non-negative"); + + principalPaid += other.principalPaid; + interestPaid += other.interestPaid; + valueChange += other.valueChange; + feePaid += other.feePaid; + return *this; +} + +bool +LoanPaymentParts::operator==(LoanPaymentParts const& other) const +{ + return principalPaid == other.principalPaid && + interestPaid == other.interestPaid && + valueChange == other.valueChange && feePaid == other.feePaid; +} + +/* Converts annualized interest rate to per-payment-period rate. + * The rate is prorated based on the payment interval in seconds. + * + * Equation (1) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +loanPeriodicRate(TenthBips32 interestRate, std::uint32_t paymentInterval) +{ + // Need floating point math, since we're dividing by a large number + return tenthBipsOfValue(Number(paymentInterval), interestRate) / + secondsInYear; +} + +/* Checks if a value is already rounded to the specified scale. + * Returns true if rounding down and rounding up produce the same result, + * indicating no further precision exists beyond the scale. + */ +bool +isRounded(Asset const& asset, Number const& value, std::int32_t scale) +{ + return roundToAsset(asset, value, scale, Number::downward) == + roundToAsset(asset, value, scale, Number::upward); +} + +namespace detail { + +void +LoanStateDeltas::nonNegative() +{ + if (principal < beast::zero) + principal = numZero; + if (interest < beast::zero) + interest = numZero; + if (managementFee < beast::zero) + managementFee = numZero; +} + +/* Computes (1 + periodicRate)^paymentsRemaining for amortization calculations. + * + * Equation (5) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +computeRaisedRate(Number const& periodicRate, std::uint32_t paymentsRemaining) +{ + return power(1 + periodicRate, paymentsRemaining); +} + +/* Computes the payment factor used in standard amortization formulas. + * This factor converts principal to periodic payment amount. + * + * Equation (6) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +computePaymentFactor( + Number const& periodicRate, + std::uint32_t paymentsRemaining) +{ + // For zero interest, payment factor is simply 1/paymentsRemaining + if (periodicRate == beast::zero) + return Number{1} / paymentsRemaining; + + Number const raisedRate = + computeRaisedRate(periodicRate, paymentsRemaining); + + return (periodicRate * raisedRate) / (raisedRate - 1); +} + +/* Calculates the periodic payment amount using standard amortization formula. + * For interest-free loans, returns principal divided equally across payments. + * + * Equation (7) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +loanPeriodicPayment( + Number const& principalOutstanding, + Number const& periodicRate, + std::uint32_t paymentsRemaining) +{ + if (principalOutstanding == 0 || paymentsRemaining == 0) + return 0; + + // Interest-free loans: equal principal payments + if (periodicRate == beast::zero) + return principalOutstanding / paymentsRemaining; + + return principalOutstanding * + computePaymentFactor(periodicRate, paymentsRemaining); +} + +/* Calculates the periodic payment amount from annualized interest rate. + * Converts the annual rate to periodic rate before computing payment. + * + * Equation (7) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +loanPeriodicPayment( + Number const& principalOutstanding, + TenthBips32 interestRate, + std::uint32_t paymentInterval, + std::uint32_t paymentsRemaining) +{ + if (principalOutstanding == 0 || paymentsRemaining == 0) + return 0; + + Number const periodicRate = loanPeriodicRate(interestRate, paymentInterval); + + return loanPeriodicPayment( + principalOutstanding, periodicRate, paymentsRemaining); +} + +/* Reverse-calculates principal from periodic payment amount. + * Used to determine theoretical principal at any point in the schedule. + * + * Equation (10) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +loanPrincipalFromPeriodicPayment( + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t paymentsRemaining) +{ + if (periodicRate == 0) + return periodicPayment * paymentsRemaining; + + return periodicPayment / + computePaymentFactor(periodicRate, paymentsRemaining); +} + +/* Splits gross interest into net interest (to vault) and management fee (to + * broker). Returns pair of (net interest, management fee). + * + * Equation (33) from XLS-66 spec, Section A-2 Equation Glossary + */ +std::pair +computeInterestAndFeeParts( + Number const& interest, + TenthBips16 managementFeeRate) +{ + auto const fee = tenthBipsOfValue(interest, managementFeeRate); + + return std::make_pair(interest - fee, fee); +} + +/* + * Computes the interest and management fee parts from interest amount. + * + * Equation (33) from XLS-66 spec, Section A-2 Equation Glossary + */ +std::pair +computeInterestAndFeeParts( + Asset const& asset, + Number const& interest, + TenthBips16 managementFeeRate, + std::int32_t loanScale) +{ + auto const fee = + computeManagementFee(asset, interest, managementFeeRate, loanScale); + + return std::make_pair(interest - fee, fee); +} + +/* Calculates penalty interest accrued on overdue payments. + * Returns 0 if payment is not late. + * + * Equation (16) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +loanLatePaymentInterest( + Number const& principalOutstanding, + TenthBips32 lateInterestRate, + NetClock::time_point parentCloseTime, + std::uint32_t nextPaymentDueDate) +{ + auto const now = parentCloseTime.time_since_epoch().count(); + + // If the payment is not late by any amount of time, then there's no late + // interest + if (now <= nextPaymentDueDate) + return 0; + + // Equation (3) from XLS-66 spec, Section A-2 Equation Glossary + auto const secondsOverdue = now - nextPaymentDueDate; + + auto const rate = loanPeriodicRate(lateInterestRate, secondsOverdue); + + return principalOutstanding * rate; +} + +/* Calculates interest accrued since the last payment based on time elapsed. + * Returns 0 if loan is paid ahead of schedule. + * + * Equation (27) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +loanAccruedInterest( + Number const& principalOutstanding, + Number const& periodicRate, + NetClock::time_point parentCloseTime, + std::uint32_t startDate, + std::uint32_t prevPaymentDate, + std::uint32_t paymentInterval) +{ + if (periodicRate == beast::zero) + return numZero; + + auto const lastPaymentDate = std::max(prevPaymentDate, startDate); + auto const now = parentCloseTime.time_since_epoch().count(); + + // If the loan has been paid ahead, then "lastPaymentDate" is in the future, + // and no interest has accrued. + if (now <= lastPaymentDate) + return numZero; + + // Equation (4) from XLS-66 spec, Section A-2 Equation Glossary + auto const secondsSinceLastPayment = now - lastPaymentDate; + + // Division is more likely to introduce rounding errors, which will then get + // amplified by multiplication. Therefore, we first multiply, and only then + // divide. + return principalOutstanding * periodicRate * secondsSinceLastPayment / + paymentInterval; +} + +/* Applies a payment to the loan state and returns the breakdown of amounts + * paid. + * + * This is the core function that updates the Loan ledger object fields based on + * a computed payment. + + * The function is templated to work with both direct Number/uint32_t values + * (for testing/simulation) and ValueProxy types (for actual ledger updates). + */ +template +LoanPaymentParts +doPayment( + ExtendedPaymentComponents const& payment, + NumberProxy& totalValueOutstandingProxy, + NumberProxy& principalOutstandingProxy, + NumberProxy& managementFeeOutstandingProxy, + UInt32Proxy& paymentRemainingProxy, + UInt32Proxy& prevPaymentDateProxy, + UInt32OptionalProxy& nextDueDateProxy, + std::uint32_t paymentInterval) +{ + XRPL_ASSERT_PARTS( + nextDueDateProxy, + "ripple::detail::doPayment", + "Next due date proxy set"); + + if (payment.specialCase == PaymentSpecialCase::final) + { + XRPL_ASSERT_PARTS( + principalOutstandingProxy == payment.trackedPrincipalDelta, + "ripple::detail::doPayment", + "Full principal payment"); + XRPL_ASSERT_PARTS( + totalValueOutstandingProxy == payment.trackedValueDelta, + "ripple::detail::doPayment", + "Full value payment"); + XRPL_ASSERT_PARTS( + managementFeeOutstandingProxy == payment.trackedManagementFeeDelta, + "ripple::detail::doPayment", + "Full management fee payment"); + + // Mark the loan as complete + paymentRemainingProxy = 0; + + // Record when the final payment was made + prevPaymentDateProxy = *nextDueDateProxy; + + // Clear the next due date. Setting it to 0 causes + // it to be removed from the Loan ledger object, saving space. + nextDueDateProxy = 0; + + // Zero out all tracked loan balances to mark the loan as paid off. + // These will be removed from the Loan object since they're default + // values. + principalOutstandingProxy = 0; + totalValueOutstandingProxy = 0; + managementFeeOutstandingProxy = 0; + } + else + { + // For regular payments (not overpayments), advance the payment schedule + if (payment.specialCase != PaymentSpecialCase::extra) + { + paymentRemainingProxy -= 1; + + prevPaymentDateProxy = nextDueDateProxy; + nextDueDateProxy += paymentInterval; + } + XRPL_ASSERT_PARTS( + principalOutstandingProxy > payment.trackedPrincipalDelta, + "ripple::detail::doPayment", + "Partial principal payment"); + XRPL_ASSERT_PARTS( + totalValueOutstandingProxy > payment.trackedValueDelta, + "ripple::detail::doPayment", + "Partial value payment"); + // Management fees are expected to be relatively small, and could get to + // zero before the loan is paid off + XRPL_ASSERT_PARTS( + managementFeeOutstandingProxy >= payment.trackedManagementFeeDelta, + "ripple::detail::doPayment", + "Valid management fee"); + + // Apply the payment deltas to reduce the outstanding balances + principalOutstandingProxy -= payment.trackedPrincipalDelta; + totalValueOutstandingProxy -= payment.trackedValueDelta; + managementFeeOutstandingProxy -= payment.trackedManagementFeeDelta; + } + + // Principal can never exceed total value (principal is part of total value) + XRPL_ASSERT_PARTS( + // Use an explicit cast because the template parameter can be + // ValueProxy or Number + static_cast(principalOutstandingProxy) <= + static_cast(totalValueOutstandingProxy), + "ripple::detail::doPayment", + "principal does not exceed total"); + + XRPL_ASSERT_PARTS( + // Use an explicit cast because the template parameter can be + // ValueProxy or Number + static_cast(managementFeeOutstandingProxy) >= beast::zero, + "ripple::detail::doPayment", + "fee outstanding stays valid"); + + return LoanPaymentParts{ + // Principal paid is straightforward - it's the tracked delta + .principalPaid = payment.trackedPrincipalDelta, + + // Interest paid combines: + // 1. Tracked interest from the amortization schedule + // (derived from the tracked deltas) + // 2. Untracked interest (e.g., late payment penalties) + .interestPaid = + payment.trackedInterestPart() + payment.untrackedInterest, + + // Value change represents how the loan's total value changed beyond + // normal amortization. + .valueChange = payment.untrackedInterest, + + // Fee paid combines: + // 1. Tracked management fees from the amortization schedule + // 2. Untracked fees (e.g., late payment fees, service fees) + .feePaid = + payment.trackedManagementFeeDelta + payment.untrackedManagementFee}; +} + +/* Simulates an overpayment to validate it won't break the loan's amortization. + * + * When a borrower pays more than the scheduled amount, the loan needs to be + * re-amortized with a lower principal. This function performs that calculation + * in a "sandbox" using temporary variables, allowing the caller to validate + * the result before committing changes to the actual ledger. + * + * The function preserves accumulated rounding errors across the re-amortization + * to ensure the loan state remains consistent with its payment history. + */ +Expected +tryOverpayment( + Asset const& asset, + std::int32_t loanScale, + ExtendedPaymentComponents const& overpaymentComponents, + Number& totalValueOutstanding, + Number& principalOutstanding, + Number& managementFeeOutstanding, + Number& periodicPayment, + TenthBips32 interestRate, + std::uint32_t paymentInterval, + Number const& periodicRate, + std::uint32_t paymentRemaining, + std::uint32_t prevPaymentDate, + std::optional nextDueDate, + TenthBips16 const managementFeeRate, + beast::Journal j) +{ + // Calculate what the loan state SHOULD be theoretically (at full precision) + auto const raw = computeRawLoanState( + periodicPayment, periodicRate, paymentRemaining, managementFeeRate); + + // Get the actual loan state (with accumulated rounding from past payments) + auto const rounded = constructLoanState( + totalValueOutstanding, principalOutstanding, managementFeeOutstanding); + + // Calculate the accumulated rounding errors. These need to be preserved + // across the re-amortization to maintain consistency with the loan's + // payment history. Without preserving these errors, the loan could end + // up with a different total value than what the borrower has actually paid. + auto const errors = rounded - raw; + + // Compute the new principal by applying the overpayment to the raw + // (theoretical) principal. Use max with 0 to ensure we never go negative. + auto const newRawPrincipal = std::max( + raw.principalOutstanding - overpaymentComponents.trackedPrincipalDelta, + Number{0}); + + // Compute new loan properties based on the reduced principal. This + // recalculates the periodic payment, total value, and management fees + // for the remaining payment schedule. + auto newLoanProperties = computeLoanProperties( + asset, + newRawPrincipal, + interestRate, + paymentInterval, + paymentRemaining, + managementFeeRate, + loanScale); + + JLOG(j.debug()) << "new periodic payment: " + << newLoanProperties.periodicPayment + << ", new total value: " + << newLoanProperties.totalValueOutstanding + << ", first payment principal: " + << newLoanProperties.firstPaymentPrincipal; + + // Calculate what the new loan state should be with the new periodic payment + auto const newRaw = computeRawLoanState( + newLoanProperties.periodicPayment, + periodicRate, + paymentRemaining, + managementFeeRate) + + errors; + + JLOG(j.debug()) << "new raw value: " << newRaw.valueOutstanding + << ", principal: " << newRaw.principalOutstanding + << ", interest gross: " << newRaw.interestOutstanding(); + // Update the loan state variables with the new values PLUS the preserved + // rounding errors. This ensures the loan's tracked state remains + // consistent with its payment history. + + principalOutstanding = std::clamp( + roundToAsset( + asset, newRaw.principalOutstanding, loanScale, Number::upward), + numZero, + rounded.principalOutstanding); + totalValueOutstanding = std::clamp( + roundToAsset( + asset, + principalOutstanding + newRaw.interestOutstanding(), + loanScale, + Number::upward), + numZero, + rounded.valueOutstanding); + managementFeeOutstanding = std::clamp( + roundToAsset(asset, newRaw.managementFeeDue, loanScale), + numZero, + rounded.managementFeeDue); + + auto const newRounded = constructLoanState( + totalValueOutstanding, principalOutstanding, managementFeeOutstanding); + + // Update newLoanProperties so that checkLoanGuards can make an accurate + // evaluation. + newLoanProperties.totalValueOutstanding = newRounded.valueOutstanding; + + JLOG(j.debug()) << "new rounded value: " << newRounded.valueOutstanding + << ", principal: " << newRounded.principalOutstanding + << ", interest gross: " << newRounded.interestOutstanding(); + + // Update the periodic payment to reflect the re-amortized schedule + periodicPayment = newLoanProperties.periodicPayment; + + // check that the loan is still valid + if (auto const ter = checkLoanGuards( + asset, + principalOutstanding, + // The loan may have been created with interest, but for + // small interest amounts, that may have already been paid + // off. Check what's still outstanding. This should + // guarantee that the interest checks pass. + newRounded.interestOutstanding() != beast::zero, + paymentRemaining, + newLoanProperties, + j)) + { + JLOG(j.warn()) << "Principal overpayment would cause the loan to be in " + "an invalid state. Ignore the overpayment"; + + return Unexpected(tesSUCCESS); + } + + // Validate that all computed properties are reasonable. These checks should + // never fail under normal circumstances, but we validate defensively. + if (newLoanProperties.periodicPayment <= 0 || + newLoanProperties.totalValueOutstanding <= 0 || + newLoanProperties.managementFeeOwedToBroker < 0) + { + // LCOV_EXCL_START + JLOG(j.warn()) << "Overpayment not allowed: Computed loan " + "properties are invalid. Does " + "not compute. TotalValueOutstanding: " + << newLoanProperties.totalValueOutstanding + << ", PeriodicPayment : " + << newLoanProperties.periodicPayment + << ", ManagementFeeOwedToBroker: " + << newLoanProperties.managementFeeOwedToBroker; + return Unexpected(tesSUCCESS); + // LCOV_EXCL_STOP + } + + auto const deltas = rounded - newRounded; + + auto const hypotheticalValueOutstanding = + rounded.valueOutstanding - deltas.principal; + + // Calculate how the loan's value changed due to the overpayment. + // This should be negative (value decreased) or zero. A principal + // overpayment should never increase the loan's value. + auto const valueChange = + newRounded.valueOutstanding - hypotheticalValueOutstanding; + if (valueChange > 0) + { + JLOG(j.warn()) << "Principal overpayment would increase the value of " + "the loan. Ignore the overpayment"; + return Unexpected(tesSUCCESS); + } + + return LoanPaymentParts{ + // Principal paid is the reduction in principal outstanding + .principalPaid = deltas.principal, + // Interest paid is the reduction in interest due + .interestPaid = + deltas.interest + overpaymentComponents.untrackedInterest, + // Value change includes both the reduction from paying down principal + // (negative) and any untracked interest penalties (positive, e.g., if + // the overpayment itself incurs a fee) + .valueChange = + valueChange + overpaymentComponents.trackedInterestPart(), + // Fee paid includes both the reduction in tracked management fees and + // any untracked fees on the overpayment itself + .feePaid = deltas.managementFee + + overpaymentComponents.untrackedManagementFee}; +} + +/* Validates and applies an overpayment to the loan state. + * + * This function acts as a wrapper around tryOverpayment(), performing the + * re-amortization calculation in a sandbox (using temporary copies of the + * loan state), then validating the results before committing them to the + * actual ledger via the proxy objects. + * + * The two-step process (try in sandbox, then commit) ensures that if the + * overpayment would leave the loan in an invalid state, we can reject it + * gracefully without corrupting the ledger data. + */ +template +Expected +doOverpayment( + Asset const& asset, + std::int32_t loanScale, + ExtendedPaymentComponents const& overpaymentComponents, + NumberProxy& totalValueOutstandingProxy, + NumberProxy& principalOutstandingProxy, + NumberProxy& managementFeeOutstandingProxy, + NumberProxy& periodicPaymentProxy, + TenthBips32 const interestRate, + std::uint32_t const paymentInterval, + Number const& periodicRate, + std::uint32_t const paymentRemaining, + std::uint32_t const prevPaymentDate, + std::optional const nextDueDate, + TenthBips16 const managementFeeRate, + beast::Journal j) +{ + // Create temporary copies of the loan state that can be safely modified + // and discarded if the overpayment doesn't work out. This prevents + // corrupting the actual ledger data if validation fails. + Number totalValueOutstanding = totalValueOutstandingProxy; + Number principalOutstanding = principalOutstandingProxy; + Number managementFeeOutstanding = managementFeeOutstandingProxy; + Number periodicPayment = periodicPaymentProxy; + + JLOG(j.debug()) + << "overpayment components:" + << ", totalValue before: " << *totalValueOutstandingProxy + << ", valueDelta: " << overpaymentComponents.trackedValueDelta + << ", principalDelta: " << overpaymentComponents.trackedPrincipalDelta + << ", managementFeeDelta: " + << overpaymentComponents.trackedManagementFeeDelta + << ", interestPart: " << overpaymentComponents.trackedInterestPart() + << ", untrackedInterest: " << overpaymentComponents.untrackedInterest + << ", totalDue: " << overpaymentComponents.totalDue + << ", payments remaining :" << paymentRemaining; + + // Attempt to re-amortize the loan with the overpayment applied. + // This modifies the temporary copies, leaving the proxies unchanged. + auto const ret = tryOverpayment( + asset, + loanScale, + overpaymentComponents, + totalValueOutstanding, + principalOutstanding, + managementFeeOutstanding, + periodicPayment, + interestRate, + paymentInterval, + periodicRate, + paymentRemaining, + prevPaymentDate, + nextDueDate, + managementFeeRate, + j); + if (!ret) + return Unexpected(ret.error()); + + auto const& loanPaymentParts = *ret; + + // Safety check: the principal must have decreased. If it didn't (or + // increased!), something went wrong in the calculation and we should + // reject the overpayment. + if (principalOutstandingProxy <= principalOutstanding) + { + // LCOV_EXCL_START + JLOG(j.warn()) << "Overpayment not allowed: principal " + << "outstanding did not decrease. Before: " + << *principalOutstandingProxy + << ". After: " << principalOutstanding; + return Unexpected(tesSUCCESS); + // LCOV_EXCL_STOP + } + + // The proxies still hold the original (pre-overpayment) values, which + // allows us to compute deltas and verify they match what we expect + // from the overpaymentComponents and loanPaymentParts. + + XRPL_ASSERT_PARTS( + overpaymentComponents.trackedPrincipalDelta == + principalOutstandingProxy - principalOutstanding, + "ripple::detail::doOverpayment", + "principal change agrees"); + + XRPL_ASSERT_PARTS( + overpaymentComponents.trackedManagementFeeDelta == + managementFeeOutstandingProxy - managementFeeOutstanding, + "ripple::detail::doOverpayment", + "no fee change"); + + // I'm not 100% sure the following asserts are correct. If in doubt, and + // everything else works, remove any that cause trouble. + + JLOG(j.debug()) << "valueChange: " << loanPaymentParts.valueChange + << ", totalValue before: " << *totalValueOutstandingProxy + << ", totalValue after: " << totalValueOutstanding + << ", totalValue delta: " + << (totalValueOutstandingProxy - totalValueOutstanding) + << ", principalDelta: " + << overpaymentComponents.trackedPrincipalDelta + << ", principalPaid: " << loanPaymentParts.principalPaid + << ", Computed difference: " + << overpaymentComponents.trackedPrincipalDelta - + (totalValueOutstandingProxy - totalValueOutstanding); + + XRPL_ASSERT_PARTS( + loanPaymentParts.valueChange == + totalValueOutstanding - + (totalValueOutstandingProxy - + overpaymentComponents.trackedPrincipalDelta) + + overpaymentComponents.trackedInterestPart(), + "ripple::detail::doOverpayment", + "interest paid agrees"); + + XRPL_ASSERT_PARTS( + overpaymentComponents.trackedPrincipalDelta == + loanPaymentParts.principalPaid, + "ripple::detail::doOverpayment", + "principal payment matches"); + + XRPL_ASSERT_PARTS( + loanPaymentParts.feePaid == + overpaymentComponents.untrackedManagementFee + + overpaymentComponents.trackedManagementFeeDelta, + "ripple::detail::doOverpayment", + "fee payment matches"); + + // All validations passed, so update the proxy objects (which will + // modify the actual Loan ledger object) + totalValueOutstandingProxy = totalValueOutstanding; + principalOutstandingProxy = principalOutstanding; + managementFeeOutstandingProxy = managementFeeOutstanding; + periodicPaymentProxy = periodicPayment; + + return loanPaymentParts; +} + +/* Computes the payment components for a late payment. + * + * A late payment is made after the grace period has expired and includes: + * 1. All components of a regular periodic payment + * 2. Late payment penalty interest (accrued since the due date) + * 3. Late payment fee charged by the broker + * + * The late penalty interest increases the loan's total value (the borrower + * owes more than scheduled), while the regular payment components follow + * the normal amortization schedule. + * + * Implements equation (15) from XLS-66 spec, Section A-2 Equation Glossary + */ +Expected +computeLatePayment( + Asset const& asset, + ApplyView const& view, + Number const& principalOutstanding, + std::int32_t nextDueDate, + ExtendedPaymentComponents const& periodic, + TenthBips32 lateInterestRate, + std::int32_t loanScale, + Number const& latePaymentFee, + STAmount const& amount, + TenthBips16 managementFeeRate, + beast::Journal j) +{ + // Check if the due date has passed. If not, reject the payment as + // being too soon + if (!hasExpired(view, nextDueDate)) + return Unexpected(tecTOO_SOON); + + // Calculate the penalty interest based on how long the payment is overdue. + auto const latePaymentInterest = loanLatePaymentInterest( + principalOutstanding, + lateInterestRate, + view.parentCloseTime(), + nextDueDate); + + // Round the late interest and split it between the vault (net interest) + // and the broker (management fee portion). This lambda ensures we + // round before splitting to maintain precision. + auto const [roundedLateInterest, roundedLateManagementFee] = [&]() { + auto const interest = + roundToAsset(asset, latePaymentInterest, loanScale); + return computeInterestAndFeeParts( + asset, interest, managementFeeRate, loanScale); + }(); + + XRPL_ASSERT( + roundedLateInterest >= 0, + "ripple::detail::computeLatePayment : valid late interest"); + XRPL_ASSERT_PARTS( + periodic.specialCase != PaymentSpecialCase::extra, + "ripple::detail::computeLatePayment", + "no extra parts to this payment"); + + // Create the late payment components by copying the regular periodic + // payment and adding the late penalties. We use a lambda to construct + // this to keep the logic clear. This preserves all the other fields without + // having to enumerate them. + + ExtendedPaymentComponents const late = [&]() { + auto inner = periodic; + + return ExtendedPaymentComponents{ + inner, + // Untracked management fee includes: + // 1. Regular service fee (from periodic.untrackedManagementFee) + // 2. Late payment fee (fixed penalty) + // 3. Management fee portion of late interest + periodic.untrackedManagementFee + latePaymentFee + + roundedLateManagementFee, + + // Untracked interest includes: + // 1. Any untracked interest from the regular payment (usually 0) + // 2. Late penalty interest (increases loan value) + // This positive value indicates the loan's value increased due + // to the late payment. + periodic.untrackedInterest + roundedLateInterest}; + }(); + + XRPL_ASSERT_PARTS( + isRounded(asset, late.totalDue, loanScale), + "ripple::detail::computeLatePayment", + "total due is rounded"); + + // Check that the borrower provided enough funds to cover the late payment. + // The late payment is more expensive than a regular payment due to the + // penalties. + if (amount < late.totalDue) + { + JLOG(j.warn()) << "Late loan payment amount is insufficient. Due: " + << late.totalDue << ", paid: " << amount; + return Unexpected(tecINSUFFICIENT_PAYMENT); + } + + return late; +} + +/* Computes payment components for paying off a loan early (before final + * payment). + * + * A full payment closes the loan immediately, paying off all outstanding + * balances plus a prepayment penalty and any accrued interest since the last + * payment. This is different from the final scheduled payment, which has no + * prepayment penalty. + * + * The function calculates: + * - Accrued interest since last payment (time-based) + * - Prepayment penalty (percentage of remaining principal) + * - Close payment fee (fixed fee for early closure) + * - All remaining principal and outstanding fees + * + * The loan's value may increase or decrease depending on whether the prepayment + * penalty exceeds the scheduled interest that would have been paid. + * + * Implements equation (26) from XLS-66 spec, Section A-2 Equation Glossary + */ +Expected +computeFullPayment( + Asset const& asset, + ApplyView& view, + Number const& principalOutstanding, + Number const& managementFeeOutstanding, + Number const& periodicPayment, + std::uint32_t paymentRemaining, + std::uint32_t prevPaymentDate, + std::uint32_t const startDate, + std::uint32_t const paymentInterval, + TenthBips32 const closeInterestRate, + std::int32_t loanScale, + Number const& totalInterestOutstanding, + Number const& periodicRate, + Number const& closePaymentFee, + STAmount const& amount, + TenthBips16 managementFeeRate, + beast::Journal j) +{ + // Full payment must be made before the final scheduled payment. + if (paymentRemaining <= 1) + { + // If this is the last payment, it has to be a regular payment + JLOG(j.warn()) << "Last payment cannot be a full payment."; + return Unexpected(tecKILLED); + } + + // Calculate the theoretical principal based on the payment schedule. + // This raw (unrounded) value is used to compute interest and penalties + // accurately. + Number const rawPrincipalOutstanding = loanPrincipalFromPeriodicPayment( + periodicPayment, periodicRate, paymentRemaining); + + // Full payment interest includes both accrued interest (time since last + // payment) and prepayment penalty (for closing early). + auto const fullPaymentInterest = computeFullPaymentInterest( + rawPrincipalOutstanding, + periodicRate, + view.parentCloseTime(), + paymentInterval, + prevPaymentDate, + startDate, + closeInterestRate); + + // Split the full payment interest into net interest (to vault) and + // management fee (to broker), applying proper rounding. + auto const [roundedFullInterest, roundedFullManagementFee] = [&]() { + auto const interest = roundToAsset( + asset, fullPaymentInterest, loanScale, Number::downward); + auto const parts = computeInterestAndFeeParts( + asset, interest, managementFeeRate, loanScale); + return std::make_tuple(parts.first, parts.second); + }(); + + ExtendedPaymentComponents const full{ + PaymentComponents{ + // Pay off all tracked outstanding balances: principal, interest, + // and fees. + // This marks the loan as complete (final payment). + .trackedValueDelta = principalOutstanding + + totalInterestOutstanding + managementFeeOutstanding, + .trackedPrincipalDelta = principalOutstanding, + + // All outstanding management fees are paid. This zeroes out the + // tracked fee balance. + .trackedManagementFeeDelta = managementFeeOutstanding, + .specialCase = PaymentSpecialCase::final, + }, + + // Untracked management fee includes: + // 1. Close payment fee (fixed fee for early closure) + // 2. Management fee on the full payment interest + // 3. Minus the outstanding tracked fee (already accounted for above) + // This can be negative because the outstanding fee is subtracted, but + // it gets combined with trackedManagementFeeDelta in the final + // accounting. + closePaymentFee + roundedFullManagementFee - managementFeeOutstanding, + + // Value change represents the difference between what the loan was + // expected to earn (totalInterestOutstanding) and what it actually + // earns (roundedFullInterest with prepayment penalty). + // - Positive: Prepayment penalty exceeds scheduled interest (loan value + // increases) + // - Negative: Prepayment penalty is less than scheduled interest (loan + // value decreases) + roundedFullInterest - totalInterestOutstanding, + }; + + XRPL_ASSERT_PARTS( + isRounded(asset, full.totalDue, loanScale), + "ripple::detail::computeFullPayment", + "total due is rounded"); + + JLOG(j.trace()) << "computeFullPayment result: periodicPayment: " + << periodicPayment << ", periodicRate: " << periodicRate + << ", paymentRemaining: " << paymentRemaining + << ", rawPrincipalOutstanding: " << rawPrincipalOutstanding + << ", fullPaymentInterest: " << fullPaymentInterest + << ", roundedFullInterest: " << roundedFullInterest + << ", roundedFullManagementFee: " + << roundedFullManagementFee + << ", untrackedInterest: " << full.untrackedInterest; + + if (amount < full.totalDue) + // If the payment is less than the full payment amount, it's not + // sufficient to be a full payment. + return Unexpected(tecINSUFFICIENT_PAYMENT); + + return full; +} + +Number +PaymentComponents::trackedInterestPart() const +{ + return trackedValueDelta - + (trackedPrincipalDelta + trackedManagementFeeDelta); +} + +/* Computes the breakdown of a regular periodic payment into principal, + * interest, and management fee components. + * + * This function determines how a single scheduled payment should be split among + * the three tracked loan components. The calculation accounts for accumulated + * rounding errors. + * + * The algorithm: + * 1. Calculate what the loan state SHOULD be after this payment (target) + * 2. Compare current state to target to get deltas + * 3. Adjust deltas to handle rounding artifacts and edge cases + * 4. Ensure deltas don't exceed available balances or payment amount + * + * Special handling for the final payment: all remaining balances are paid off + * regardless of the periodic payment amount. + */ +PaymentComponents +computePaymentComponents( + Asset const& asset, + std::int32_t scale, + Number const& totalValueOutstanding, + Number const& principalOutstanding, + Number const& managementFeeOutstanding, + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t paymentRemaining, + TenthBips16 managementFeeRate) +{ + XRPL_ASSERT_PARTS( + isRounded(asset, totalValueOutstanding, scale) && + isRounded(asset, principalOutstanding, scale) && + isRounded(asset, managementFeeOutstanding, scale), + "ripple::detail::computePaymentComponents", + "Outstanding values are rounded"); + XRPL_ASSERT_PARTS( + paymentRemaining > 0, + "ripple::detail::computePaymentComponents", + "some payments remaining"); + + auto const roundedPeriodicPayment = + roundPeriodicPayment(asset, periodicPayment, scale); + + // Final payment: pay off everything remaining, ignoring the normal + // periodic payment amount. This ensures the loan completes cleanly. + if (paymentRemaining == 1 || + totalValueOutstanding <= roundedPeriodicPayment) + { + // If there's only one payment left, we need to pay off each of the loan + // parts. + return PaymentComponents{ + .trackedValueDelta = totalValueOutstanding, + .trackedPrincipalDelta = principalOutstanding, + .trackedManagementFeeDelta = managementFeeOutstanding, + .specialCase = PaymentSpecialCase::final}; + } + + // Calculate what the loan state SHOULD be after this payment (the target). + // This is computed at full precision using the theoretical amortization. + LoanState const trueTarget = computeRawLoanState( + periodicPayment, periodicRate, paymentRemaining - 1, managementFeeRate); + + // Round the target to the loan's scale to match how actual loan values + // are stored. + LoanState const roundedTarget = LoanState{ + .valueOutstanding = + roundToAsset(asset, trueTarget.valueOutstanding, scale), + .principalOutstanding = + roundToAsset(asset, trueTarget.principalOutstanding, scale), + .interestDue = roundToAsset(asset, trueTarget.interestDue, scale), + .managementFeeDue = + roundToAsset(asset, trueTarget.managementFeeDue, scale)}; + + // Get the current actual loan state from the ledger values + LoanState const currentLedgerState = constructLoanState( + totalValueOutstanding, principalOutstanding, managementFeeOutstanding); + + // The difference between current and target states gives us the payment + // components. Any discrepancies from accumulated rounding are captured + // here. + + LoanStateDeltas deltas = currentLedgerState - roundedTarget; + + // Rounding can occasionally produce negative deltas. Zero them out. + deltas.nonNegative(); + + XRPL_ASSERT_PARTS( + deltas.principal <= currentLedgerState.principalOutstanding, + "ripple::detail::computePaymentComponents", + "principal delta not greater than outstanding"); + + // Cap each component to never exceed what's actually outstanding + deltas.principal = + std::min(deltas.principal, currentLedgerState.principalOutstanding); + + XRPL_ASSERT_PARTS( + deltas.interest <= currentLedgerState.interestDue, + "ripple::detail::computePaymentComponents", + "interest due delta not greater than outstanding"); + + // Cap interest to both the outstanding amount AND what's left of the + // periodic payment after principal is paid + deltas.interest = std::min( + {deltas.interest, + std::max(numZero, roundedPeriodicPayment - deltas.principal), + currentLedgerState.interestDue}); + + XRPL_ASSERT_PARTS( + deltas.managementFee <= currentLedgerState.managementFeeDue, + "ripple::detail::computePaymentComponents", + "management fee due delta not greater than outstanding"); + + // Cap management fee to both the outstanding amount AND what's left of the + // periodic payment after principal and interest are paid + deltas.managementFee = std::min( + {deltas.managementFee, + roundedPeriodicPayment - (deltas.principal + deltas.interest), + currentLedgerState.managementFeeDue}); + + // The shortage must never be negative, which indicates that the parts are + // trying to take more than the whole payment. The excess can be positive, + // which indicates that we're not going to take the whole payment amount, + // but if so, it must be small. + auto takeFrom = [](Number& component, Number& excess) { + if (excess > beast::zero) + { + auto part = std::min(component, excess); + component -= part; + excess -= part; + } + XRPL_ASSERT_PARTS( + excess >= beast::zero, + "ripple::detail::computePaymentComponents", + "excess non-negative"); + }; + // Helper to reduce deltas when they collectively exceed a limit. + // Order matters: we prefer to reduce interest first (most flexible), + // then management fee, then principal (least flexible). + auto addressExcess = [&takeFrom](LoanStateDeltas& deltas, Number& excess) { + // This order is based on where errors are the least problematic + takeFrom(deltas.interest, excess); + takeFrom(deltas.managementFee, excess); + takeFrom(deltas.principal, excess); + }; + + // Check if deltas exceed the total outstanding value. This should never + // happen due to earlier caps, but handle it defensively. + Number totalOverpayment = + deltas.total() - currentLedgerState.valueOutstanding; + + if (totalOverpayment > beast::zero) + { + // LCOV_EXCL_START + UNREACHABLE( + "ripple::detail::computePaymentComponents : payment exceeded loan " + "state"); + addressExcess(deltas, totalOverpayment); + // LCOV_EXCL_STOP + } + + // Check if deltas exceed the periodic payment amount. Reduce if needed. + Number shortage = roundedPeriodicPayment - deltas.total(); + + XRPL_ASSERT_PARTS( + isRounded(asset, shortage, scale), + "ripple::detail::computePaymentComponents", + "shortage is rounded"); + + if (shortage < beast::zero) + { + // Deltas exceed payment amount - reduce them proportionally + Number excess = -shortage; + addressExcess(deltas, excess); + shortage = -excess; + } + + // At this point, shortage >= 0 means we're paying less than the full + // periodic payment (due to rounding or component caps). + // shortage < 0 would mean we're trying to pay more than allowed (bug). + XRPL_ASSERT_PARTS( + shortage >= beast::zero, + "ripple::detail::computePaymentComponents", + "no shortage or excess"); + + // Final validation that all components are valid + XRPL_ASSERT_PARTS( + deltas.total() == + deltas.principal + deltas.interest + deltas.managementFee, + "ripple::detail::computePaymentComponents", + "total value adds up"); + + XRPL_ASSERT_PARTS( + deltas.principal >= beast::zero && + deltas.principal <= currentLedgerState.principalOutstanding, + "ripple::detail::computePaymentComponents", + "valid principal result"); + XRPL_ASSERT_PARTS( + deltas.interest >= beast::zero && + deltas.interest <= currentLedgerState.interestDue, + "ripple::detail::computePaymentComponents", + "valid interest result"); + XRPL_ASSERT_PARTS( + deltas.managementFee >= beast::zero && + deltas.managementFee <= currentLedgerState.managementFeeDue, + "ripple::detail::computePaymentComponents", + "valid fee result"); + + XRPL_ASSERT_PARTS( + deltas.principal + deltas.interest + deltas.managementFee > beast::zero, + "ripple::detail::computePaymentComponents", + "payment parts add to payment"); + + // Final safety clamp to ensure no value exceeds its outstanding balance + return PaymentComponents{ + .trackedValueDelta = std::clamp( + deltas.total(), numZero, currentLedgerState.valueOutstanding), + .trackedPrincipalDelta = std::clamp( + deltas.principal, numZero, currentLedgerState.principalOutstanding), + .trackedManagementFeeDelta = std::clamp( + deltas.managementFee, numZero, currentLedgerState.managementFeeDue), + }; +} + +/* Computes payment components for an overpayment scenario. + * + * An overpayment occurs when a borrower pays more than the scheduled periodic + * payment amount. The overpayment is treated as extra principal reduction, + * but incurs a fee and potentially a penalty interest charge. + * + * The calculation (Section 3.2.4.2.3 from XLS-66 spec): + * 1. Calculate gross penalty interest on the overpayment amount + * 2. Split the gross interest into net interest and management fee + * 3. Calculate the penalty fee + * 4. Determine the principal portion by subtracting the interest (gross) and + * management fee from the overpayment amount + * + * Unlike regular payments which follow the amortization schedule, overpayments + * apply to principal, reducing the loan balance and future interest costs. + * + * Equations (20), (21) and (22) from XLS-66 spec, Section A-2 Equation Glossary + */ +ExtendedPaymentComponents +computeOverpaymentComponents( + Asset const& asset, + int32_t const loanScale, + Number const& overpayment, + TenthBips32 const overpaymentInterestRate, + TenthBips32 const overpaymentFeeRate, + TenthBips16 const managementFeeRate) +{ + XRPL_ASSERT( + overpayment > 0 && isRounded(asset, overpayment, loanScale), + "ripple::detail::computeOverpaymentComponents : valid overpayment " + "amount"); + + // First, deduct the fixed overpayment fee from the total amount. + // This reduces the effective payment that will be applied to the loan. + // Equation (22) from XLS-66 spec, Section A-2 Equation Glossary + Number const overpaymentFee = roundToAsset( + asset, tenthBipsOfValue(overpayment, overpaymentFeeRate), loanScale); + + // Calculate the penalty interest on the effective payment amount. + // This interest doesn't follow the normal amortization schedule - it's + // a one-time charge for paying early. + // Equation (20) and (21) from XLS-66 spec, Section A-2 Equation Glossary + auto const [rawOverpaymentInterest, _] = [&]() { + Number const interest = + tenthBipsOfValue(overpayment, overpaymentInterestRate); + return detail::computeInterestAndFeeParts(interest, managementFeeRate); + }(); + + // Round the penalty interest components to the loan scale + auto const [roundedOverpaymentInterest, roundedOverpaymentManagementFee] = + [&]() { + Number const interest = + roundToAsset(asset, rawOverpaymentInterest, loanScale); + return detail::computeInterestAndFeeParts( + asset, interest, managementFeeRate, loanScale); + }(); + + auto const result = detail::ExtendedPaymentComponents{ + // Build the payment components, after fees and penalty + // interest are deducted, the remainder goes entirely to principal + // reduction. + detail::PaymentComponents{ + .trackedValueDelta = overpayment - overpaymentFee, + .trackedPrincipalDelta = overpayment - roundedOverpaymentInterest - + roundedOverpaymentManagementFee - overpaymentFee, + .trackedManagementFeeDelta = roundedOverpaymentManagementFee, + .specialCase = detail::PaymentSpecialCase::extra}, + // Untracked management fee is the fixed overpayment fee + overpaymentFee, + // Untracked interest is the penalty interest charged for + // overpaying. + // This is positive, representing a one-time cost, but it's + // typically + // much smaller than the interest savings from reducing + // principal. + roundedOverpaymentInterest}; + XRPL_ASSERT_PARTS( + result.trackedInterestPart() == roundedOverpaymentInterest, + "ripple::detail::computeOverpaymentComponents", + "valid interest computation"); + return result; +} + +} // namespace detail + +detail::LoanStateDeltas +operator-(LoanState const& lhs, LoanState const& rhs) +{ + detail::LoanStateDeltas result{ + .principal = lhs.principalOutstanding - rhs.principalOutstanding, + .interest = lhs.interestDue - rhs.interestDue, + .managementFee = lhs.managementFeeDue - rhs.managementFeeDue, + }; + + return result; +} + +LoanState +operator-(LoanState const& lhs, detail::LoanStateDeltas const& rhs) +{ + LoanState result{ + .valueOutstanding = lhs.valueOutstanding - rhs.total(), + .principalOutstanding = lhs.principalOutstanding - rhs.principal, + .interestDue = lhs.interestDue - rhs.interest, + .managementFeeDue = lhs.managementFeeDue - rhs.managementFee, + }; + + return result; +} + +LoanState +operator+(LoanState const& lhs, detail::LoanStateDeltas const& rhs) +{ + LoanState result{ + .valueOutstanding = lhs.valueOutstanding + rhs.total(), + .principalOutstanding = lhs.principalOutstanding + rhs.principal, + .interestDue = lhs.interestDue + rhs.interest, + .managementFeeDue = lhs.managementFeeDue + rhs.managementFee, + }; + + return result; +} + +TER +checkLoanGuards( + Asset const& vaultAsset, + Number const& principalRequested, + bool expectInterest, + std::uint32_t paymentTotal, + LoanProperties const& properties, + beast::Journal j) +{ + auto const totalInterestOutstanding = + properties.totalValueOutstanding - principalRequested; + // Guard 1: if there is no computed total interest over the life of the + // loan for a non-zero interest rate, we cannot properly amortize the + // loan + if (expectInterest && totalInterestOutstanding <= 0) + { + // Unless this is a zero-interest loan, there must be some interest + // due on the loan, even if it's (measurable) dust + JLOG(j.warn()) << "Loan for " << principalRequested + << " with interest has no interest due"; + return tecPRECISION_LOSS; + } + // Guard 1a: If there is any interest computed over the life of the + // loan, for a zero interest rate, something went sideways. + if (!expectInterest && totalInterestOutstanding > 0) + { + // LCOV_EXCL_START + JLOG(j.warn()) << "Loan for " << principalRequested + << " with no interest has interest due"; + return tecINTERNAL; + // LCOV_EXCL_STOP + } + + // Guard 2: if the principal portion of the first periodic payment is + // too small to be accurately represented with the given rounding mode, + // raise an error + if (properties.firstPaymentPrincipal <= 0) + { + // Check that some true (unrounded) principal is paid each period. + // Since the first payment pays the least principal, if it's good, + // they'll all be good. Note that the outstanding principal is + // rounded, and may not change right away. + JLOG(j.warn()) << "Loan is unable to pay principal."; + return tecPRECISION_LOSS; + } + + // Guard 3: If the periodic payment is so small that it can't even be + // rounded to a representable value, then the loan can't be paid. Also, + // avoids dividing by 0. + auto const roundedPayment = roundPeriodicPayment( + vaultAsset, properties.periodicPayment, properties.loanScale); + if (roundedPayment == beast::zero) + { + JLOG(j.warn()) << "Loan Periodic payment (" + << properties.periodicPayment << ") rounds to 0. "; + return tecPRECISION_LOSS; + } + + // Guard 4: if the rounded periodic payment is large enough that the + // loan can't be amortized in the specified number of payments, raise an + // error + { + NumberRoundModeGuard mg(Number::upward); + + if (std::int64_t const computedPayments{ + properties.totalValueOutstanding / roundedPayment}; + computedPayments != paymentTotal) + { + JLOG(j.warn()) << "Loan Periodic payment (" + << properties.periodicPayment << ") rounding (" + << roundedPayment << ") on a total value of " + << properties.totalValueOutstanding + << " can not complete the loan in the specified " + "number of payments (" + << computedPayments << " != " << paymentTotal << ")"; + return tecPRECISION_LOSS; + } + } + return tesSUCCESS; +} + +/* + * This function calculates the full payment interest accrued since the last + * payment, plus any prepayment penalty. + * + * Equations (27) and (28) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +computeFullPaymentInterest( + Number const& rawPrincipalOutstanding, + Number const& periodicRate, + NetClock::time_point parentCloseTime, + std::uint32_t paymentInterval, + std::uint32_t prevPaymentDate, + std::uint32_t startDate, + TenthBips32 closeInterestRate) +{ + auto const accruedInterest = detail::loanAccruedInterest( + rawPrincipalOutstanding, + periodicRate, + parentCloseTime, + startDate, + prevPaymentDate, + paymentInterval); + XRPL_ASSERT( + accruedInterest >= 0, + "ripple::detail::computeFullPaymentInterest : valid accrued " + "interest"); + + // Equation (28) from XLS-66 spec, Section A-2 Equation Glossary + auto const prepaymentPenalty = closeInterestRate == beast::zero + ? Number{} + : tenthBipsOfValue(rawPrincipalOutstanding, closeInterestRate); + + XRPL_ASSERT( + prepaymentPenalty >= 0, + "ripple::detail::computeFullPaymentInterest : valid prepayment " + "interest"); + + // Part of equation (27) from XLS-66 spec, Section A-2 Equation Glossary + return accruedInterest + prepaymentPenalty; +} + +Number +computeFullPaymentInterest( + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t paymentRemaining, + NetClock::time_point parentCloseTime, + std::uint32_t paymentInterval, + std::uint32_t prevPaymentDate, + std::uint32_t startDate, + TenthBips32 closeInterestRate) +{ + Number const rawPrincipalOutstanding = + detail::loanPrincipalFromPeriodicPayment( + periodicPayment, periodicRate, paymentRemaining); + + return computeFullPaymentInterest( + rawPrincipalOutstanding, + periodicRate, + parentCloseTime, + paymentInterval, + prevPaymentDate, + startDate, + closeInterestRate); +} + +/* Calculates the theoretical loan state at maximum precision for a given point + * in the amortization schedule. + * + * This function computes what the loan's outstanding balances should be based + * on the periodic payment amount and number of payments remaining, + * without considering any rounding that may have been applied to the actual + * Loan object's state. This "raw" (unrounded) state is used as a target for + * computing payment components and validating that the loan's tracked state + * hasn't drifted too far from the theoretical values. + * + * The raw state serves several purposes: + * 1. Computing the expected payment breakdown (principal, interest, fees) + * 2. Detecting and correcting rounding errors that accumulate over time + * 3. Validating that overpayments are calculated correctly + * 4. Ensuring the loan will be fully paid off at the end of its term + * + * If paymentRemaining is 0, returns a fully zeroed-out LoanState, + * representing a completely paid-off loan. + */ +LoanState +computeRawLoanState( + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t const paymentRemaining, + TenthBips32 const managementFeeRate) +{ + if (paymentRemaining == 0) + { + return LoanState{ + .valueOutstanding = 0, + .principalOutstanding = 0, + .interestDue = 0, + .managementFeeDue = 0}; + } + + // Equation (30) from XLS-66 spec, Section A-2 Equation Glossary + Number const rawTotalValueOutstanding = periodicPayment * paymentRemaining; + + Number const rawPrincipalOutstanding = + detail::loanPrincipalFromPeriodicPayment( + periodicPayment, periodicRate, paymentRemaining); + + // Equation (31) from XLS-66 spec, Section A-2 Equation Glossary + Number const rawInterestOutstandingGross = + rawTotalValueOutstanding - rawPrincipalOutstanding; + + // Equation (32) from XLS-66 spec, Section A-2 Equation Glossary + Number const rawManagementFeeOutstanding = + tenthBipsOfValue(rawInterestOutstandingGross, managementFeeRate); + + // Equation (33) from XLS-66 spec, Section A-2 Equation Glossary + Number const rawInterestOutstandingNet = + rawInterestOutstandingGross - rawManagementFeeOutstanding; + + return LoanState{ + .valueOutstanding = rawTotalValueOutstanding, + .principalOutstanding = rawPrincipalOutstanding, + .interestDue = rawInterestOutstandingNet, + .managementFeeDue = rawManagementFeeOutstanding}; +}; + +LoanState +computeRawLoanState( + Number const& periodicPayment, + TenthBips32 interestRate, + std::uint32_t paymentInterval, + std::uint32_t const paymentRemaining, + TenthBips32 const managementFeeRate) +{ + return computeRawLoanState( + periodicPayment, + loanPeriodicRate(interestRate, paymentInterval), + paymentRemaining, + managementFeeRate); +} + +/* Constructs a LoanState from rounded Loan ledger object values. + * + * This function creates a LoanState structure from the three tracked values + * stored in a Loan ledger object. Unlike calculateRawLoanState(), which + * computes theoretical unrounded values, this function works with values + * that have already been rounded to the loan's scale. + * + * The key difference from calculateRawLoanState(): + * - calculateRawLoanState: Computes theoretical values at full precision + * - constructRoundedLoanState: Builds state from actual rounded ledger values + * + * The interestDue field is derived from the other three values rather than + * stored directly, since it can be calculated as: + * interestDue = totalValueOutstanding - principalOutstanding - + * managementFeeOutstanding + * + * This ensures consistency across the codebase and prevents copy-paste errors + * when creating LoanState objects from Loan ledger data. + */ +LoanState +constructLoanState( + Number const& totalValueOutstanding, + Number const& principalOutstanding, + Number const& managementFeeOutstanding) +{ + // This implementation is pretty trivial, but ensures the calculations + // are consistent everywhere, and reduces copy/paste errors. + return LoanState{ + .valueOutstanding = totalValueOutstanding, + .principalOutstanding = principalOutstanding, + .interestDue = totalValueOutstanding - principalOutstanding - + managementFeeOutstanding, + .managementFeeDue = managementFeeOutstanding}; +} + +LoanState +constructRoundedLoanState(SLE::const_ref loan) +{ + return constructLoanState( + loan->at(sfTotalValueOutstanding), + loan->at(sfPrincipalOutstanding), + loan->at(sfManagementFeeOutstanding)); +} + +/* + * This function calculates the fee owed to the broker based on the asset, + * value, and management fee rate. + * + * Equation (32) from XLS-66 spec, Section A-2 Equation Glossary + */ +Number +computeManagementFee( + Asset const& asset, + Number const& value, + TenthBips32 managementFeeRate, + std::int32_t scale) +{ + return roundToAsset( + asset, + tenthBipsOfValue(value, managementFeeRate), + scale, + Number::downward); +} + +/* + * Given the loan parameters, compute the derived properties of the loan. + */ +LoanProperties +computeLoanProperties( + Asset const& asset, + Number principalOutstanding, + TenthBips32 interestRate, + std::uint32_t paymentInterval, + std::uint32_t paymentsRemaining, + TenthBips32 managementFeeRate, + std::int32_t minimumScale) +{ + auto const periodicRate = loanPeriodicRate(interestRate, paymentInterval); + XRPL_ASSERT( + interestRate == 0 || periodicRate > 0, + "ripple::computeLoanProperties : valid rate"); + + auto const periodicPayment = detail::loanPeriodicPayment( + principalOutstanding, periodicRate, paymentsRemaining); + + auto const [totalValueOutstanding, loanScale] = [&]() { + NumberRoundModeGuard mg(Number::to_nearest); + // Use STAmount's internal rounding instead of roundToAsset, because + // we're going to use this result to determine the scale for all the + // other rounding. + + // Equation (30) from XLS-66 spec, Section A-2 Equation Glossary + STAmount amount{asset, periodicPayment * paymentsRemaining}; + + // Base the loan scale on the total value, since that's going to be + // the biggest number involved (barring unusual parameters for late, + // full, or over payments) + auto const loanScale = std::max(minimumScale, amount.exponent()); + XRPL_ASSERT_PARTS( + (amount.integral() && loanScale == 0) || + (!amount.integral() && + loanScale >= static_cast(amount).exponent()), + "ripple::computeLoanProperties", + "loanScale value fits expectations"); + + // We may need to truncate the total value because of the minimum + // scale + amount = roundToAsset(asset, amount, loanScale, Number::to_nearest); + + return std::make_pair(amount, loanScale); + }(); + + // Since we just figured out the loan scale, we haven't been able to + // validate that the principal fits in it, so to allow this function to + // succeed, round it here, and let the caller do the validation. + principalOutstanding = roundToAsset( + asset, principalOutstanding, loanScale, Number::to_nearest); + + // E +loanMakePayment( + Asset const& asset, + ApplyView& view, + SLE::ref loan, + SLE::const_ref brokerSle, + STAmount const& amount, + LoanPaymentType const paymentType, + beast::Journal j) +{ + using namespace Lending; + + auto principalOutstandingProxy = loan->at(sfPrincipalOutstanding); + auto paymentRemainingProxy = loan->at(sfPaymentRemaining); + + if (paymentRemainingProxy == 0 || principalOutstandingProxy == 0) + { + // Loan complete this is already checked in LoanPay::preclaim() + // LCOV_EXCL_START + JLOG(j.warn()) << "Loan is already paid off."; + return Unexpected(tecKILLED); + // LCOV_EXCL_STOP + } + + auto totalValueOutstandingProxy = loan->at(sfTotalValueOutstanding); + auto managementFeeOutstandingProxy = loan->at(sfManagementFeeOutstanding); + + // Next payment due date must be set unless the loan is complete + auto nextDueDateProxy = loan->at(sfNextPaymentDueDate); + if (*nextDueDateProxy == 0) + { + JLOG(j.warn()) << "Loan next payment due date is not set."; + return Unexpected(tecINTERNAL); + } + + std::int32_t const loanScale = loan->at(sfLoanScale); + + TenthBips32 const interestRate{loan->at(sfInterestRate)}; + + Number const serviceFee = loan->at(sfLoanServiceFee); + TenthBips16 const managementFeeRate{brokerSle->at(sfManagementFeeRate)}; + + Number const periodicPayment = loan->at(sfPeriodicPayment); + + auto prevPaymentDateProxy = loan->at(sfPreviousPaymentDate); + std::uint32_t const startDate = loan->at(sfStartDate); + + std::uint32_t const paymentInterval = loan->at(sfPaymentInterval); + + // Compute the periodic rate that will be used for calculations + // throughout + Number const periodicRate = loanPeriodicRate(interestRate, paymentInterval); + XRPL_ASSERT( + interestRate == 0 || periodicRate > 0, + "ripple::loanMakePayment : valid rate"); + + XRPL_ASSERT( + *totalValueOutstandingProxy > 0, + "ripple::loanMakePayment : valid total value"); + + view.update(loan); + + // ------------------------------------------------------------- + // A late payment not flagged as late overrides all other options. + if (paymentType != LoanPaymentType::late && + hasExpired(view, nextDueDateProxy)) + { + // If the payment is late, and the late flag was not set, it's not + // valid + JLOG(j.warn()) << "Loan payment is overdue. Use the tfLoanLatePayment " + "transaction " + "flag to make a late payment. Loan was created on " + << startDate << ", prev payment due date is " + << prevPaymentDateProxy << ", next payment due date is " + << nextDueDateProxy << ", ledger time is " + << view.parentCloseTime().time_since_epoch().count(); + return Unexpected(tecEXPIRED); + } + + // ------------------------------------------------------------- + // full payment handling + if (paymentType == LoanPaymentType::full) + { + TenthBips32 const closeInterestRate{loan->at(sfCloseInterestRate)}; + Number const closePaymentFee = + roundToAsset(asset, loan->at(sfClosePaymentFee), loanScale); + + LoanState const roundedLoanState = constructLoanState( + totalValueOutstandingProxy, + principalOutstandingProxy, + managementFeeOutstandingProxy); + + if (auto const fullPaymentComponents = detail::computeFullPayment( + asset, + view, + principalOutstandingProxy, + managementFeeOutstandingProxy, + periodicPayment, + paymentRemainingProxy, + prevPaymentDateProxy, + startDate, + paymentInterval, + closeInterestRate, + loanScale, + roundedLoanState.interestDue, + periodicRate, + closePaymentFee, + amount, + managementFeeRate, + j)) + { + return doPayment( + *fullPaymentComponents, + totalValueOutstandingProxy, + principalOutstandingProxy, + managementFeeOutstandingProxy, + paymentRemainingProxy, + prevPaymentDateProxy, + nextDueDateProxy, + paymentInterval); + } + else if (fullPaymentComponents.error()) + // error() will be the TER returned if a payment is not made. It + // will only evaluate to true if it's unsuccessful. Otherwise, + // tesSUCCESS means nothing was done, so continue. + return Unexpected(fullPaymentComponents.error()); + + // LCOV_EXCL_START + UNREACHABLE("ripple::loanMakePayment : invalid full payment result"); + JLOG(j.error()) << "Full payment computation failed unexpectedly."; + return Unexpected(tecINTERNAL); + // LCOV_EXCL_STOP + } + + // ------------------------------------------------------------- + // compute the periodic payment info that will be needed whether the + // payment is late or regular + detail::ExtendedPaymentComponents periodic{ + detail::computePaymentComponents( + asset, + loanScale, + totalValueOutstandingProxy, + principalOutstandingProxy, + managementFeeOutstandingProxy, + periodicPayment, + periodicRate, + paymentRemainingProxy, + managementFeeRate), + serviceFee}; + XRPL_ASSERT_PARTS( + periodic.trackedPrincipalDelta >= 0, + "ripple::loanMakePayment", + "regular payment valid principal"); + + // ------------------------------------------------------------- + // late payment handling + if (paymentType == LoanPaymentType::late) + { + TenthBips32 const lateInterestRate{loan->at(sfLateInterestRate)}; + Number const latePaymentFee = loan->at(sfLatePaymentFee); + + if (auto const latePaymentComponents = detail::computeLatePayment( + asset, + view, + principalOutstandingProxy, + nextDueDateProxy, + periodic, + lateInterestRate, + loanScale, + latePaymentFee, + amount, + managementFeeRate, + j)) + { + return doPayment( + *latePaymentComponents, + totalValueOutstandingProxy, + principalOutstandingProxy, + managementFeeOutstandingProxy, + paymentRemainingProxy, + prevPaymentDateProxy, + nextDueDateProxy, + paymentInterval); + } + else if (latePaymentComponents.error()) + { + // error() will be the TER returned if a payment is not made. It + // will only evaluate to true if it's unsuccessful. + return Unexpected(latePaymentComponents.error()); + } + + // LCOV_EXCL_START + UNREACHABLE("ripple::loanMakePayment : invalid late payment result"); + JLOG(j.error()) << "Late payment computation failed unexpectedly."; + return Unexpected(tecINTERNAL); + // LCOV_EXCL_STOP + } + + // ------------------------------------------------------------- + // regular periodic payment handling + + XRPL_ASSERT_PARTS( + paymentType == LoanPaymentType::regular || + paymentType == LoanPaymentType::overpayment, + "ripple::loanMakePayment", + "regular payment type"); + + // Keep a running total of the actual parts paid + LoanPaymentParts totalParts; + Number totalPaid; + std::size_t numPayments = 0; + + while ((amount >= (totalPaid + periodic.totalDue)) && + paymentRemainingProxy > 0 && + numPayments < loanMaximumPaymentsPerTransaction) + { + // Try to make more payments + XRPL_ASSERT_PARTS( + periodic.trackedPrincipalDelta >= 0, + "ripple::loanMakePayment", + "payment pays non-negative principal"); + + totalPaid += periodic.totalDue; + totalParts += detail::doPayment( + periodic, + totalValueOutstandingProxy, + principalOutstandingProxy, + managementFeeOutstandingProxy, + paymentRemainingProxy, + prevPaymentDateProxy, + nextDueDateProxy, + paymentInterval); + ++numPayments; + + XRPL_ASSERT_PARTS( + (periodic.specialCase == detail::PaymentSpecialCase::final) == + (paymentRemainingProxy == 0), + "ripple::loanMakePayment", + "final payment is the final payment"); + + // Don't compute the next payment if this was the last payment + if (periodic.specialCase == detail::PaymentSpecialCase::final) + break; + + periodic = detail::ExtendedPaymentComponents{ + detail::computePaymentComponents( + asset, + loanScale, + totalValueOutstandingProxy, + principalOutstandingProxy, + managementFeeOutstandingProxy, + periodicPayment, + periodicRate, + paymentRemainingProxy, + managementFeeRate), + serviceFee}; + } + + if (numPayments == 0) + { + JLOG(j.warn()) << "Regular loan payment amount is insufficient. Due: " + << periodic.totalDue << ", paid: " << amount; + return Unexpected(tecINSUFFICIENT_PAYMENT); + } + + XRPL_ASSERT_PARTS( + totalParts.principalPaid + totalParts.interestPaid + + totalParts.feePaid == + totalPaid, + "ripple::loanMakePayment", + "payment parts add up"); + XRPL_ASSERT_PARTS( + totalParts.valueChange == 0, + "ripple::loanMakePayment", + "no value change"); + + // ------------------------------------------------------------- + // overpayment handling + if (paymentType == LoanPaymentType::overpayment && + loan->isFlag(lsfLoanOverpayment) && paymentRemainingProxy > 0 && + totalPaid < amount && numPayments < loanMaximumPaymentsPerTransaction) + { + TenthBips32 const overpaymentInterestRate{ + loan->at(sfOverpaymentInterestRate)}; + TenthBips32 const overpaymentFeeRate{loan->at(sfOverpaymentFee)}; + + // It shouldn't be possible for the overpayment to be greater than + // totalValueOutstanding, because that would have been processed as + // another normal payment. But cap it just in case. + Number const overpayment = + std::min(amount - totalPaid, *totalValueOutstandingProxy); + + detail::ExtendedPaymentComponents const overpaymentComponents = + detail::computeOverpaymentComponents( + asset, + loanScale, + overpayment, + overpaymentInterestRate, + overpaymentFeeRate, + managementFeeRate); + + // Don't process an overpayment if the whole amount (or more!) + // gets eaten by fees and interest. + if (overpaymentComponents.trackedPrincipalDelta > 0) + { + XRPL_ASSERT_PARTS( + overpaymentComponents.untrackedInterest >= beast::zero, + "ripple::loanMakePayment", + "overpayment penalty did not reduce value of loan"); + // Can't just use `periodicPayment` here, because it might + // change + auto periodicPaymentProxy = loan->at(sfPeriodicPayment); + if (auto const overResult = detail::doOverpayment( + asset, + loanScale, + overpaymentComponents, + totalValueOutstandingProxy, + principalOutstandingProxy, + managementFeeOutstandingProxy, + periodicPaymentProxy, + interestRate, + paymentInterval, + periodicRate, + paymentRemainingProxy, + prevPaymentDateProxy, + nextDueDateProxy, + managementFeeRate, + j)) + totalParts += *overResult; + else if (overResult.error()) + // error() will be the TER returned if a payment is not + // made. It will only evaluate to true if it's unsuccessful. + // Otherwise, tesSUCCESS means nothing was done, so + // continue. + return Unexpected(overResult.error()); + } + } + + // Check the final results are rounded, to double-check that the + // intermediate steps were rounded. + XRPL_ASSERT( + isRounded(asset, totalParts.principalPaid, loanScale) && + totalParts.principalPaid >= beast::zero, + "ripple::loanMakePayment : total principal paid is valid"); + XRPL_ASSERT( + isRounded(asset, totalParts.interestPaid, loanScale) && + totalParts.interestPaid >= beast::zero, + "ripple::loanMakePayment : total interest paid is valid"); + XRPL_ASSERT( + isRounded(asset, totalParts.valueChange, loanScale), + "ripple::loanMakePayment : loan value change is valid"); + XRPL_ASSERT( + isRounded(asset, totalParts.feePaid, loanScale) && + totalParts.feePaid >= beast::zero, + "ripple::loanMakePayment : fee paid is valid"); + return totalParts; +} +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/Batch.cpp b/src/xrpld/app/tx/detail/Batch.cpp index b233249170..8bf0c7fe02 100644 --- a/src/xrpld/app/tx/detail/Batch.cpp +++ b/src/xrpld/app/tx/detail/Batch.cpp @@ -263,7 +263,8 @@ Batch::preflight(PreflightContext const& ctx) return temREDUNDANT; } - if (stx.getFieldU16(sfTransactionType) == ttBATCH) + auto const txType = stx.getFieldU16(sfTransactionType); + if (txType == ttBATCH) { JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: " << "batch cannot have an inner batch txn. " @@ -271,6 +272,14 @@ Batch::preflight(PreflightContext const& ctx) return temINVALID; } + if (std::any_of( + disabledTxTypes.begin(), + disabledTxTypes.end(), + [txType](auto const& disabled) { return txType == disabled; })) + { + return temINVALID_INNER_BATCH; + } + if (!(stx.getFlags() & tfInnerBatchTxn)) { JLOG(ctx.j.debug()) @@ -283,7 +292,6 @@ Batch::preflight(PreflightContext const& ctx) if (auto const ret = checkSignatureFields(stx, hash)) return ret; - /* Placeholder for field that will be added by Lending Protocol // Note that the CounterpartySignature is optional, and should not be // included, but if it is, ensure it doesn't contain a signature. if (stx.isFieldPresent(sfCounterpartySignature)) @@ -296,7 +304,6 @@ Batch::preflight(PreflightContext const& ctx) return ret; } } - */ auto const innerAccount = stx.getAccountID(sfAccount); if (auto const preflightResult = ripple::preflight( @@ -393,13 +400,11 @@ Batch::preflightSigValidated(PreflightContext const& ctx) // inner account to the required signers set. if (innerAccount != outerAccount) requiredSigners.insert(innerAccount); - /* Placeholder for field that will be added by Lending Protocol // Some transactions have a Counterparty, who must also sign the // transaction if they are not the outer account if (auto const counterparty = rb.at(~sfCounterparty); counterparty && counterparty != outerAccount) requiredSigners.insert(*counterparty); - */ } // Validation Batch Signers diff --git a/src/xrpld/app/tx/detail/Batch.h b/src/xrpld/app/tx/detail/Batch.h index 1b1d7614d5..7889e91bdc 100644 --- a/src/xrpld/app/tx/detail/Batch.h +++ b/src/xrpld/app/tx/detail/Batch.h @@ -35,6 +35,24 @@ public: TER doApply() override; + + static constexpr auto disabledTxTypes = std::to_array({ + ttVAULT_CREATE, + ttVAULT_SET, + ttVAULT_DELETE, + ttVAULT_DEPOSIT, + ttVAULT_WITHDRAW, + ttVAULT_CLAWBACK, + ttLOAN_BROKER_SET, + ttLOAN_BROKER_DELETE, + ttLOAN_BROKER_COVER_DEPOSIT, + ttLOAN_BROKER_COVER_WITHDRAW, + ttLOAN_BROKER_COVER_CLAWBACK, + ttLOAN_SET, + ttLOAN_DELETE, + ttLOAN_MANAGE, + ttLOAN_PAY, + }); }; } // namespace ripple diff --git a/src/xrpld/app/tx/detail/Change.cpp b/src/xrpld/app/tx/detail/Change.cpp index 43db9ae13c..43c6f7c619 100644 --- a/src/xrpld/app/tx/detail/Change.cpp +++ b/src/xrpld/app/tx/detail/Change.cpp @@ -19,7 +19,11 @@ NotTEC Transactor::invokePreflight(PreflightContext const& ctx) { // 0 means "Allow any flags" - if (auto const ret = preflight0(ctx, 0)) + // The check for tfChangeMask is gated by LendingProtocol because that + // feature introduced this parameter, and it's not worth adding another + // amendment just for this. + if (auto const ret = preflight0( + ctx, ctx.rules.enabled(featureLendingProtocol) ? tfChangeMask : 0)) return ret; auto account = ctx.tx.getAccountID(sfAccount); diff --git a/src/xrpld/app/tx/detail/InvariantCheck.cpp b/src/xrpld/app/tx/detail/InvariantCheck.cpp index 80c41f4d2b..27c87e074c 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.cpp +++ b/src/xrpld/app/tx/detail/InvariantCheck.cpp @@ -70,6 +70,8 @@ enum Privilege { 0x0400, // The transaction MAY delete an MPT object. May not create. mustModifyVault = 0x0800, // The transaction must modify, delete or create, a vault + mayModifyVault = + 0x1000, // The transaction MAY modify, delete or create, a vault }; constexpr Privilege operator|(Privilege lhs, Privilege rhs) @@ -479,10 +481,10 @@ void AccountRootsDeletedClean::visitEntry( bool isDelete, std::shared_ptr const& before, - std::shared_ptr const&) + std::shared_ptr const& after) { if (isDelete && before && before->getType() == ltACCOUNT_ROOT) - accountsDeleted_.emplace_back(before); + accountsDeleted_.emplace_back(before, after); } bool @@ -499,7 +501,8 @@ AccountRootsDeletedClean::finalize( // be logged [[maybe_unused]] bool const enforce = view.rules().enabled(featureInvariantsV1_1) || - view.rules().enabled(featureSingleAssetVault); + view.rules().enabled(featureSingleAssetVault) || + view.rules().enabled(featureLendingProtocol); auto const objectExists = [&view, enforce, &j](auto const& keylet) { (void)enforce; @@ -529,9 +532,33 @@ AccountRootsDeletedClean::finalize( return false; }; - for (auto const& accountSLE : accountsDeleted_) + for (auto const& [before, after] : accountsDeleted_) { - auto const accountID = accountSLE->getAccountID(sfAccount); + auto const accountID = before->getAccountID(sfAccount); + // An account should not be deleted with a balance + if (after->at(sfBalance) != beast::zero) + { + JLOG(j.fatal()) << "Invariant failed: account deletion left " + "behind a non-zero balance"; + XRPL_ASSERT( + enforce, + "ripple::AccountRootsDeletedClean::finalize : " + "deleted account has zero balance"); + if (enforce) + return false; + } + // An account should not be deleted with a non-zero owner count + if (after->at(sfOwnerCount) != 0) + { + JLOG(j.fatal()) << "Invariant failed: account deletion left " + "behind a non-zero owner count"; + XRPL_ASSERT( + enforce, + "ripple::AccountRootsDeletedClean::finalize : " + "deleted account has zero owner count"); + if (enforce) + return false; + } // Simple types for (auto const& [keyletfunc, _, __] : directAccountKeylets) { @@ -558,9 +585,9 @@ AccountRootsDeletedClean::finalize( // also be deleted. e.g. AMM, Vault, etc. for (auto const& field : getPseudoAccountFields()) { - if (accountSLE->isFieldPresent(*field)) + if (before->isFieldPresent(*field)) { - auto const key = accountSLE->getFieldH256(*field); + auto const key = before->getFieldH256(*field); if (objectExists(keylet::unchecked(key)) && enforce) return false; } @@ -1019,7 +1046,9 @@ ValidNewAccountRoot::finalize( if (hasPrivilege(tx, createAcct | createPseudoAcct) && result == tesSUCCESS) { bool const pseudoAccount = - (pseudoAccount_ && view.rules().enabled(featureSingleAssetVault)); + (pseudoAccount_ && + (view.rules().enabled(featureSingleAssetVault) || + view.rules().enabled(featureLendingProtocol))); if (pseudoAccount && !hasPrivilege(tx, createPseudoAcct)) { @@ -1426,7 +1455,12 @@ ValidMPTIssuance::visitEntry( if (isDelete) mptokensDeleted_++; else if (!before) + { mptokensCreated_++; + MPTIssue const mptIssue{after->at(sfMPTokenIssuanceID)}; + if (mptIssue.getIssuer() == after->at(sfAccount)) + mptCreatedByIssuer_ = true; + } } } @@ -1440,6 +1474,25 @@ ValidMPTIssuance::finalize( { if (result == tesSUCCESS) { + auto const& rules = view.rules(); + [[maybe_unused]] + bool enforceCreatedByIssuer = rules.enabled(featureSingleAssetVault) || + rules.enabled(featureLendingProtocol); + if (mptCreatedByIssuer_) + { + JLOG(j.fatal()) + << "Invariant failed: MPToken created for the MPT issuer"; + // The comment above starting with "assert(enforce)" explains this + // assert. + XRPL_ASSERT_PARTS( + enforceCreatedByIssuer, + "ripple::ValidMPTIssuance::finalize", + "no issuer MPToken"); + if (enforceCreatedByIssuer) + return false; + } + + auto const txnType = tx.getTxnType(); if (hasPrivilege(tx, createMPTIssuance)) { if (mptIssuancesCreated_ == 0) @@ -1482,15 +1535,14 @@ ValidMPTIssuance::finalize( return mptIssuancesCreated_ == 0 && mptIssuancesDeleted_ == 1; } + bool const lendingProtocolEnabled = + view.rules().enabled(featureLendingProtocol); // ttESCROW_FINISH may authorize an MPT, but it can't have the // mayAuthorizeMPT privilege, because that may cause // non-amendment-gated side effects. - bool const enforceEscrowFinish = (tx.getTxnType() == ttESCROW_FINISH) && - (view.rules().enabled(featureSingleAssetVault) - /* - TODO: Uncomment when LendingProtocol is defined - || view.rules().enabled(featureLendingProtocol)*/ - ); + bool const enforceEscrowFinish = (txnType == ttESCROW_FINISH) && + (view.rules().enabled(featureSingleAssetVault) || + lendingProtocolEnabled); if (hasPrivilege(tx, mustAuthorizeMPT | mayAuthorizeMPT) || enforceEscrowFinish) { @@ -1508,6 +1560,14 @@ ValidMPTIssuance::finalize( "succeeded but deleted issuances"; return false; } + else if ( + lendingProtocolEnabled && + mptokensCreated_ + mptokensDeleted_ > 1) + { + JLOG(j.fatal()) << "Invariant failed: MPT authorize succeeded " + "but created/deleted bad number mptokens"; + return false; + } else if ( submittedByIssuer && (mptokensCreated_ > 0 || mptokensDeleted_ > 0)) @@ -1531,7 +1591,7 @@ ValidMPTIssuance::finalize( return true; } - if (tx.getTxnType() == ttESCROW_FINISH) + if (txnType == ttESCROW_FINISH) { // ttESCROW_FINISH may authorize an MPT, but it can't have the // mayAuthorizeMPT privilege, because that may cause @@ -1749,8 +1809,6 @@ ValidPseudoAccounts::finalize( beast::Journal const& j) { bool const enforce = view.rules().enabled(featureSingleAssetVault); - - // The comment above starting with "assert(enforce)" explains this assert. XRPL_ASSERT( errors_.empty() || enforce, "ripple::ValidPseudoAccounts::finalize : no bad " @@ -2159,6 +2217,401 @@ ValidAMM::finalize( //------------------------------------------------------------------------------ +void +NoModifiedUnmodifiableFields::visitEntry( + bool isDelete, + std::shared_ptr const& before, + std::shared_ptr const& after) +{ + if (isDelete || !before) + // Creation and deletion are ignored + return; + + changedEntries_.emplace(before, after); +} + +bool +NoModifiedUnmodifiableFields::finalize( + STTx const& tx, + TER const, + XRPAmount const, + ReadView const& view, + beast::Journal const& j) +{ + static auto const fieldChanged = + [](auto const& before, auto const& after, auto const& field) { + bool const beforeField = before->isFieldPresent(field); + bool const afterField = after->isFieldPresent(field); + return beforeField != afterField || + (afterField && before->at(field) != after->at(field)); + }; + for (auto const& slePair : changedEntries_) + { + auto const& before = slePair.first; + auto const& after = slePair.second; + auto const type = after->getType(); + bool bad = false; + [[maybe_unused]] bool enforce = false; + switch (type) + { + case ltLOAN_BROKER: + /* + * We check this invariant regardless of lending protocol + * amendment status, allowing for detection and logging of + * potential issues even when the amendment is disabled. + */ + enforce = view.rules().enabled(featureLendingProtocol); + bad = fieldChanged(before, after, sfLedgerEntryType) || + fieldChanged(before, after, sfLedgerIndex) || + fieldChanged(before, after, sfSequence) || + fieldChanged(before, after, sfOwnerNode) || + fieldChanged(before, after, sfVaultNode) || + fieldChanged(before, after, sfVaultID) || + fieldChanged(before, after, sfAccount) || + fieldChanged(before, after, sfOwner) || + fieldChanged(before, after, sfManagementFeeRate) || + fieldChanged(before, after, sfCoverRateMinimum) || + fieldChanged(before, after, sfCoverRateLiquidation); + break; + case ltLOAN: + /* + * We check this invariant regardless of lending protocol + * amendment status, allowing for detection and logging of + * potential issues even when the amendment is disabled. + */ + enforce = view.rules().enabled(featureLendingProtocol); + bad = fieldChanged(before, after, sfLedgerEntryType) || + fieldChanged(before, after, sfLedgerIndex) || + fieldChanged(before, after, sfSequence) || + fieldChanged(before, after, sfOwnerNode) || + fieldChanged(before, after, sfLoanBrokerNode) || + fieldChanged(before, after, sfLoanBrokerID) || + fieldChanged(before, after, sfBorrower) || + fieldChanged(before, after, sfLoanOriginationFee) || + fieldChanged(before, after, sfLoanServiceFee) || + fieldChanged(before, after, sfLatePaymentFee) || + fieldChanged(before, after, sfClosePaymentFee) || + fieldChanged(before, after, sfOverpaymentFee) || + fieldChanged(before, after, sfInterestRate) || + fieldChanged(before, after, sfLateInterestRate) || + fieldChanged(before, after, sfCloseInterestRate) || + fieldChanged(before, after, sfOverpaymentInterestRate) || + fieldChanged(before, after, sfStartDate) || + fieldChanged(before, after, sfPaymentInterval) || + fieldChanged(before, after, sfGracePeriod) || + fieldChanged(before, after, sfLoanScale); + break; + default: + /* + * We check this invariant regardless of lending protocol + * amendment status, allowing for detection and logging of + * potential issues even when the amendment is disabled. + * + * We use the lending protocol as a gate, even though + * all transactions are affected because that's when it + * was added. + */ + enforce = view.rules().enabled(featureLendingProtocol); + bad = fieldChanged(before, after, sfLedgerEntryType) || + fieldChanged(before, after, sfLedgerIndex); + } + XRPL_ASSERT( + !bad || enforce, + "ripple::NoModifiedUnmodifiableFields::finalize : no bad " + "changes or enforce invariant"); + if (bad) + { + JLOG(j.fatal()) + << "Invariant failed: changed an unchangable field for " + << tx.getTransactionID(); + if (enforce) + return false; + } + } + return true; +} + +//------------------------------------------------------------------------------ + +void +ValidLoanBroker::visitEntry( + bool isDelete, + std::shared_ptr const& before, + std::shared_ptr const& after) +{ + if (after) + { + if (after->getType() == ltLOAN_BROKER) + { + auto& broker = brokers_[after->key()]; + broker.brokerBefore = before; + broker.brokerAfter = after; + } + else if ( + after->getType() == ltACCOUNT_ROOT && + after->isFieldPresent(sfLoanBrokerID)) + { + auto const& loanBrokerID = after->at(sfLoanBrokerID); + // create an entry if one doesn't already exist + brokers_.emplace(loanBrokerID, BrokerInfo{}); + } + else if (after->getType() == ltRIPPLE_STATE) + { + lines_.emplace_back(after); + } + else if (after->getType() == ltMPTOKEN) + { + mpts_.emplace_back(after); + } + } +} + +bool +ValidLoanBroker::goodZeroDirectory( + ReadView const& view, + SLE::const_ref dir, + beast::Journal const& j) const +{ + auto const next = dir->at(~sfIndexNext); + auto const prev = dir->at(~sfIndexPrevious); + if ((prev && *prev) || (next && *next)) + { + JLOG(j.fatal()) << "Invariant failed: Loan Broker with zero " + "OwnerCount has multiple directory pages"; + return false; + } + auto indexes = dir->getFieldV256(sfIndexes); + if (indexes.size() > 1) + { + JLOG(j.fatal()) + << "Invariant failed: Loan Broker with zero " + "OwnerCount has multiple indexes in the Directory root"; + return false; + } + if (indexes.size() == 1) + { + auto const index = indexes.value().front(); + auto const sle = view.read(keylet::unchecked(index)); + if (!sle) + { + JLOG(j.fatal()) + << "Invariant failed: Loan Broker directory corrupt"; + return false; + } + if (sle->getType() != ltRIPPLE_STATE && sle->getType() != ltMPTOKEN) + { + JLOG(j.fatal()) + << "Invariant failed: Loan Broker with zero " + "OwnerCount has an unexpected entry in the directory"; + return false; + } + } + + return true; +} + +bool +ValidLoanBroker::finalize( + STTx const& tx, + TER const, + XRPAmount const, + ReadView const& view, + beast::Journal const& j) +{ + // Loan Brokers will not exist on ledger if the Lending Protocol amendment + // is not enabled, so there's no need to check it. + + for (auto const& line : lines_) + { + for (auto const& field : {&sfLowLimit, &sfHighLimit}) + { + auto const account = + view.read(keylet::account(line->at(*field).getIssuer())); + // This Invariant doesn't know about the rules for Trust Lines, so + // if the account is missing, don't treat it as an error. This + // loop is only concerned with finding Broker pseudo-accounts + if (account && account->isFieldPresent(sfLoanBrokerID)) + { + auto const& loanBrokerID = account->at(sfLoanBrokerID); + // create an entry if one doesn't already exist + brokers_.emplace(loanBrokerID, BrokerInfo{}); + } + } + } + for (auto const& mpt : mpts_) + { + auto const account = view.read(keylet::account(mpt->at(sfAccount))); + // This Invariant doesn't know about the rules for MPTokens, so + // if the account is missing, don't treat is as an error. This + // loop is only concerned with finding Broker pseudo-accounts + if (account && account->isFieldPresent(sfLoanBrokerID)) + { + auto const& loanBrokerID = account->at(sfLoanBrokerID); + // create an entry if one doesn't already exist + brokers_.emplace(loanBrokerID, BrokerInfo{}); + } + } + + for (auto const& [brokerID, broker] : brokers_) + { + auto const& after = broker.brokerAfter + ? broker.brokerAfter + : view.read(keylet::loanbroker(brokerID)); + + if (!after) + { + JLOG(j.fatal()) << "Invariant failed: Loan Broker missing"; + return false; + } + + auto const& before = broker.brokerBefore; + + // https://github.com/Tapanito/XRPL-Standards/blob/xls-66-lending-protocol/XLS-0066d-lending-protocol/README.md#3123-invariants + // If `LoanBroker.OwnerCount = 0` the `DirectoryNode` will have at most + // one node (the root), which will only hold entries for `RippleState` + // or `MPToken` objects. + if (after->at(sfOwnerCount) == 0) + { + auto const dir = view.read(keylet::ownerDir(after->at(sfAccount))); + if (dir) + { + if (!goodZeroDirectory(view, dir, j)) + { + return false; + } + } + } + if (before && before->at(sfLoanSequence) > after->at(sfLoanSequence)) + { + JLOG(j.fatal()) << "Invariant failed: Loan Broker sequence number " + "decreased"; + return false; + } + if (after->at(sfDebtTotal) < 0) + { + JLOG(j.fatal()) + << "Invariant failed: Loan Broker debt total is negative"; + return false; + } + if (after->at(sfCoverAvailable) < 0) + { + JLOG(j.fatal()) + << "Invariant failed: Loan Broker cover available is negative"; + return false; + } + auto const vault = view.read(keylet::vault(after->at(sfVaultID))); + if (!vault) + { + JLOG(j.fatal()) + << "Invariant failed: Loan Broker vault ID is invalid"; + return false; + } + auto const& vaultAsset = vault->at(sfAsset); + if (after->at(sfCoverAvailable) < accountHolds( + view, + after->at(sfAccount), + vaultAsset, + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + j)) + { + JLOG(j.fatal()) << "Invariant failed: Loan Broker cover available " + "is less than pseudo-account asset balance"; + return false; + } + } + return true; +} + +//------------------------------------------------------------------------------ + +void +ValidLoan::visitEntry( + bool isDelete, + std::shared_ptr const& before, + std::shared_ptr const& after) +{ + if (after && after->getType() == ltLOAN) + { + loans_.emplace_back(before, after); + } +} + +bool +ValidLoan::finalize( + STTx const& tx, + TER const, + XRPAmount const, + ReadView const& view, + beast::Journal const& j) +{ + // Loans will not exist on ledger if the Lending Protocol amendment + // is not enabled, so there's no need to check it. + + for (auto const& [before, after] : loans_) + { + // https://github.com/Tapanito/XRPL-Standards/blob/xls-66-lending-protocol/XLS-0066d-lending-protocol/README.md#3223-invariants + // If `Loan.PaymentRemaining = 0` then the loan MUST be fully paid off + if (after->at(sfPaymentRemaining) == 0 && + (after->at(sfTotalValueOutstanding) != beast::zero || + after->at(sfPrincipalOutstanding) != beast::zero || + after->at(sfManagementFeeOutstanding) != beast::zero)) + { + JLOG(j.fatal()) << "Invariant failed: Loan with zero payments " + "remaining has not been paid off"; + return false; + } + // If `Loan.PaymentRemaining != 0` then the loan MUST NOT be fully paid + // off + if (after->at(sfPaymentRemaining) != 0 && + after->at(sfTotalValueOutstanding) == beast::zero && + after->at(sfPrincipalOutstanding) == beast::zero && + after->at(sfManagementFeeOutstanding) == beast::zero) + { + JLOG(j.fatal()) << "Invariant failed: Loan with zero payments " + "remaining has not been paid off"; + return false; + } + if (before && + (before->isFlag(lsfLoanOverpayment) != + after->isFlag(lsfLoanOverpayment))) + { + JLOG(j.fatal()) + << "Invariant failed: Loan Overpayment flag changed"; + return false; + } + // Must not be negative - STNumber + for (auto const field : + {&sfLoanServiceFee, + &sfLatePaymentFee, + &sfClosePaymentFee, + &sfPrincipalOutstanding, + &sfTotalValueOutstanding, + &sfManagementFeeOutstanding}) + { + if (after->at(*field) < 0) + { + JLOG(j.fatal()) << "Invariant failed: " << field->getName() + << " is negative "; + return false; + } + } + // Must be positive - STNumber + for (auto const field : { + &sfPeriodicPayment, + }) + { + if (after->at(*field) <= 0) + { + JLOG(j.fatal()) << "Invariant failed: " << field->getName() + << " is zero or negative "; + return false; + } + } + } + return true; +} + ValidVault::Vault ValidVault::Vault::make(SLE const& from) { @@ -2308,7 +2761,8 @@ ValidVault::finalize( return true; // Not a vault operation } - else if (!hasPrivilege(tx, mustModifyVault)) // TODO: mayModifyVault + else if (!(hasPrivilege(tx, mustModifyVault) || + hasPrivilege(tx, mayModifyVault))) { JLOG(j.fatal()) << // "Invariant failed: vault updated by a wrong transaction type"; @@ -2523,7 +2977,8 @@ ValidVault::finalize( } if (!beforeVault_.empty() && - afterVault.lossUnrealized != beforeVault_[0].lossUnrealized) + afterVault.lossUnrealized != beforeVault_[0].lossUnrealized && + txnType != ttLOAN_MANAGE && txnType != ttLOAN_PAY) { JLOG(j.fatal()) << // "Invariant failed: vault transaction must not change loss " @@ -3071,6 +3526,13 @@ ValidVault::finalize( return result; } + case ttLOAN_SET: + case ttLOAN_MANAGE: + case ttLOAN_PAY: { + // TBD + return true; + } + default: // LCOV_EXCL_START UNREACHABLE( diff --git a/src/xrpld/app/tx/detail/InvariantCheck.h b/src/xrpld/app/tx/detail/InvariantCheck.h index f9b37f03ed..09a84b1ab4 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.h +++ b/src/xrpld/app/tx/detail/InvariantCheck.h @@ -158,7 +158,14 @@ public: */ class AccountRootsDeletedClean { - std::vector> accountsDeleted_; + // Pair is . Before is used for most of the checks, so that + // if, for example, an object ID field is cleared, but the object is not + // deleted, it can still be found. After is used specifically for any checks + // that are expected as part of the deletion, such as zeroing out the + // balance. + std::vector< + std::pair, std::shared_ptr>> + accountsDeleted_; public: void @@ -550,6 +557,9 @@ class ValidMPTIssuance std::uint32_t mptokensCreated_ = 0; std::uint32_t mptokensDeleted_ = 0; + // non-MPT transactions may attempt to create + // MPToken by an issuer + bool mptCreatedByIssuer_ = false; public: void @@ -716,6 +726,114 @@ private: }; /** + * @brief Invariants: Some fields are unmodifiable + * + * Check that any fields specified as unmodifiable are not modified when the + * object is modified. Creation and deletion are ignored. + * + */ +class NoModifiedUnmodifiableFields +{ + // Pair is . + std::set> changedEntries_; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; + +/** + * @brief Invariants: Loan brokers are internally consistent + * + * 1. If `LoanBroker.OwnerCount = 0` the `DirectoryNode` will have at most one + * node (the root), which will only hold entries for `RippleState` or + * `MPToken` objects. + * + */ +class ValidLoanBroker +{ + // Not all of these elements will necessarily be populated. Remaining items + // will be looked up as needed. + struct BrokerInfo + { + SLE::const_pointer brokerBefore = nullptr; + // After is used for most of the checks, except + // those that check changed values. + SLE::const_pointer brokerAfter = nullptr; + }; + // Collect all the LoanBrokers found directly or indirectly through + // pseudo-accounts. Key is the brokerID / index. It will be used to find the + // LoanBroker object if brokerBefore and brokerAfter are nullptr + std::map brokers_; + // Collect all the modified trust lines. Their high and low accounts will be + // loaded to look for LoanBroker pseudo-accounts. + std::vector lines_; + // Collect all the modified MPTokens. Their accounts will be loaded to look + // for LoanBroker pseudo-accounts. + std::vector mpts_; + + bool + goodZeroDirectory( + ReadView const& view, + SLE::const_ref dir, + beast::Journal const& j) const; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; + +/** + * @brief Invariants: Loans are internally consistent + * + * 1. If `Loan.PaymentRemaining = 0` then `Loan.PrincipalOutstanding = 0` + * + */ +class ValidLoan +{ + // Pair is . After is used for most of the checks, except + // those that check changed values. + std::vector> loans_; + +public: + void + visitEntry( + bool, + std::shared_ptr const&, + std::shared_ptr const&); + + bool + finalize( + STTx const&, + TER const, + XRPAmount const, + ReadView const&, + beast::Journal const&); +}; + +/* * @brief Invariants: Vault object and MPTokenIssuance for vault shares * * - vault deleted and vault created is empty @@ -805,7 +923,10 @@ using InvariantChecks = std::tuple< ValidPermissionedDomain, ValidPermissionedDEX, ValidAMM, + NoModifiedUnmodifiableFields, ValidPseudoAccounts, + ValidLoanBroker, + ValidLoan, ValidVault>; /** diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp new file mode 100644 index 0000000000..26e978697c --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp @@ -0,0 +1,340 @@ +#include +// +#include + +namespace ripple { + +bool +LoanBrokerCoverClawback::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +NotTEC +LoanBrokerCoverClawback::preflight(PreflightContext const& ctx) +{ + auto const brokerID = ctx.tx[~sfLoanBrokerID]; + auto const amount = ctx.tx[~sfAmount]; + + if (!brokerID && !amount) + return temINVALID; + + if (brokerID && *brokerID == beast::zero) + return temINVALID; + + if (amount) + { + // XRP has no counterparty, and thus nobody can claw it back + if (amount->native()) + return temBAD_AMOUNT; + + // Zero is OK, and indicates "take it all" (down to the minimum cover) + if (*amount < beast::zero) + return temBAD_AMOUNT; + + // This should be redundant + if (!isLegalNet(*amount)) + return temBAD_AMOUNT; // LCOV_EXCL_LINE + + if (!brokerID) + { + if (amount->holds()) + return temINVALID; + + auto const account = ctx.tx[sfAccount]; + // Since we don't have a LoanBrokerID, holder _should_ be the loan + // broker's pseudo-account, but we don't know yet whether it is, so + // use a generic placeholder name. + auto const holder = amount->getIssuer(); + if (holder == account || holder == beast::zero) + return temINVALID; + } + } + + return tesSUCCESS; +} + +Expected +determineBrokerID(ReadView const& view, STTx const& tx) +{ + // If the broker ID was provided in the transaction, that's all we + // need. + if (auto const brokerID = tx[~sfLoanBrokerID]) + return *brokerID; + + // If the broker ID was not provided, and the amount is either + // absent or holds a non-IOU - including MPT, something went wrong, + // because that should have been rejected in preflight(). + auto const dstAmount = tx[~sfAmount]; + if (!dstAmount || !dstAmount->holds()) + return Unexpected{tecINTERNAL}; // LCOV_EXCL_LINE + + // Every trust line is bidirectional. Both sides are simultaneously + // issuer and holder. For this transaction, the Account is acting as + // a holder, and clawing back funds from the LoanBroker + // Pseudo-account acting as holder. If the Amount is an IOU, and the + // `issuer` field specified in that Amount is a LoanBroker + // Pseudo-account, we can get the LoanBrokerID from there. + // + // Thus, Amount.issuer _should_ be the loan broker's + // pseudo-account, but we don't know yet whether it is. + auto const maybePseudo = dstAmount->getIssuer(); + auto const sle = view.read(keylet::account(maybePseudo)); + + // If the account was not found, the transaction can't go further. + if (!sle) + return Unexpected{tecNO_ENTRY}; + + // If the account was found, and has a LoanBrokerID (and therefore + // is a pseudo-account), that's the + // answer we need. + if (auto const brokerID = sle->at(~sfLoanBrokerID)) + return *brokerID; + + // If the account does not have a LoanBrokerID, the transaction + // can't go further, even if it's a different type of Pseudo-account. + return Unexpected{tecOBJECT_NOT_FOUND}; + // Or tecWRONG_ASSET? +} + +Expected +determineAsset( + ReadView const& view, + AccountID const& account, + AccountID const& brokerPseudoAccountID, + STAmount const& amount) +{ + if (amount.holds()) + return amount.asset(); + + // An IOU has an issue, which could be either end of the trust line. + // This check only applies to IOUs + auto const holder = amount.getIssuer(); + + // holder can be the submitting account (the issuer of the asset) if a + // LoanBrokerID was provided in the transaction. + if (holder == account) + { + return amount.asset(); + } + else if (holder == brokerPseudoAccountID) + { + // We want the asset to match the vault asset, so use the account as the + // issuer + return Issue{amount.getCurrency(), account}; + } + else + return Unexpected(tecWRONG_ASSET); +} + +Expected +determineClawAmount( + SLE const& sleBroker, + Asset const& vaultAsset, + std::optional const& amount) +{ + auto const maxClawAmount = [&]() { + // Always round the minimum required up + NumberRoundModeGuard mg1(Number::upward); + auto const minRequiredCover = tenthBipsOfValue( + sleBroker[sfDebtTotal], TenthBips32(sleBroker[sfCoverRateMinimum])); + // The subtraction probably won't round, but round down if it does. + NumberRoundModeGuard mg2(Number::downward); + return sleBroker[sfCoverAvailable] - minRequiredCover; + }(); + if (maxClawAmount <= beast::zero) + return Unexpected(tecINSUFFICIENT_FUNDS); + + // Use the vaultAsset here, because it will be the right type in all + // circumstances. The amount may be an IOU indicating the pseudo-account's + // asset, which is correct, but not what is needed here. + if (!amount || *amount == beast::zero) + return STAmount{vaultAsset, maxClawAmount}; + Number const magnitude{*amount}; + if (magnitude > maxClawAmount) + return STAmount{vaultAsset, maxClawAmount}; + return STAmount{vaultAsset, magnitude}; +} + +template +static TER +preclaimHelper( + PreclaimContext const& ctx, + SLE const& sleIssuer, + STAmount const& clawAmount); + +template <> +TER +preclaimHelper( + PreclaimContext const& ctx, + SLE const& sleIssuer, + STAmount const& clawAmount) +{ + // If AllowTrustLineClawback is not set or NoFreeze is set, return no + // permission + if (!(sleIssuer.isFlag(lsfAllowTrustLineClawback)) || + (sleIssuer.isFlag(lsfNoFreeze))) + return tecNO_PERMISSION; + + return tesSUCCESS; +} + +template <> +TER +preclaimHelper( + PreclaimContext const& ctx, + SLE const& sleIssuer, + STAmount const& clawAmount) +{ + auto const issuanceKey = + keylet::mptIssuance(clawAmount.get().getMptID()); + auto const sleIssuance = ctx.view.read(issuanceKey); + if (!sleIssuance) + return tecOBJECT_NOT_FOUND; + + if (!sleIssuance->isFlag(lsfMPTCanClawback)) + return tecNO_PERMISSION; + + // With all the checking already done, this should be impossible + if (sleIssuance->at(sfIssuer) != sleIssuer[sfAccount]) + return tecINTERNAL; // LCOV_EXCL_LINE + + return tesSUCCESS; +} + +TER +LoanBrokerCoverClawback::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + auto const account = tx[sfAccount]; + auto const findBrokerID = determineBrokerID(ctx.view, tx); + if (!findBrokerID) + return findBrokerID.error(); + auto const brokerID = *findBrokerID; + auto const amount = tx[~sfAmount]; + + auto const sleBroker = ctx.view.read(keylet::loanbroker(brokerID)); + if (!sleBroker) + { + JLOG(ctx.j.warn()) << "LoanBroker does not exist."; + return tecNO_ENTRY; + } + + auto const brokerPseudoAccountID = sleBroker->at(sfAccount); + + auto const vault = ctx.view.read(keylet::vault(sleBroker->at(sfVaultID))); + if (!vault) + { + // LCOV_EXCL_START + JLOG(ctx.j.fatal()) << "Vault is missing for Broker " << brokerID; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + + auto const vaultAsset = vault->at(sfAsset); + + if (vaultAsset.native()) + { + JLOG(ctx.j.warn()) << "Cannot clawback native asset."; + return tecNO_PERMISSION; + } + + // Only the issuer of the vault asset can claw it back from the broker's + // cover funds. + if (vaultAsset.getIssuer() != account) + { + JLOG(ctx.j.warn()) << "Account is not the issuer of the vault asset."; + return tecNO_PERMISSION; + } + + if (amount) + { + auto const findAsset = + determineAsset(ctx.view, account, brokerPseudoAccountID, *amount); + if (!findAsset) + return findAsset.error(); + auto const txAsset = *findAsset; + if (txAsset != vaultAsset) + { + JLOG(ctx.j.warn()) << "Account is the correct issuer, but trying " + "to clawback the wrong asset from LoanBroker"; + return tecWRONG_ASSET; + } + } + + auto const findClawAmount = + determineClawAmount(*sleBroker, vaultAsset, amount); + if (!findClawAmount) + { + JLOG(ctx.j.warn()) << "LoanBroker cover is already at minimum."; + return findClawAmount.error(); + } + STAmount const clawAmount = *findClawAmount; + + // Explicitly check the balance of the trust line / MPT to make sure the + // balance is actually there. It should always match `sfCoverAvailable`, so + // if there isn't, this is an internal error. + if (accountHolds( + ctx.view, + brokerPseudoAccountID, + vaultAsset, + fhIGNORE_FREEZE, + ahIGNORE_AUTH, + ctx.j) < clawAmount) + return tecINTERNAL; // tecINSUFFICIENT_FUNDS; LCOV_EXCL_LINE + + // Check if the vault asset issuer has the correct flags + auto const sleIssuer = + ctx.view.read(keylet::account(vaultAsset.getIssuer())); + return std::visit( + [&](T const&) { + return preclaimHelper(ctx, *sleIssuer, clawAmount); + }, + vaultAsset.value()); +} + +TER +LoanBrokerCoverClawback::doApply() +{ + auto const& tx = ctx_.tx; + auto const account = tx[sfAccount]; + auto const findBrokerID = determineBrokerID(view(), tx); + if (!findBrokerID) + return tecINTERNAL; // LCOV_EXCL_LINE + auto const brokerID = *findBrokerID; + auto const amount = tx[~sfAmount]; + + auto sleBroker = view().peek(keylet::loanbroker(brokerID)); + if (!sleBroker) + return tecINTERNAL; // LCOV_EXCL_LINE + + auto const brokerPseudoID = *sleBroker->at(sfAccount); + + auto const vault = view().read(keylet::vault(sleBroker->at(sfVaultID))); + if (!vault) + return tecINTERNAL; // LCOV_EXCL_LINE + + auto const vaultAsset = vault->at(sfAsset); + + auto const findClawAmount = + determineClawAmount(*sleBroker, vaultAsset, amount); + if (!findClawAmount) + return tecINTERNAL; // LCOV_EXCL_LINE + STAmount const clawAmount = *findClawAmount; + // Just for paranoia's sake + if (clawAmount.native()) + return tecINTERNAL; // LCOV_EXCL_LINE + + // Decrease the LoanBroker's CoverAvailable by Amount + sleBroker->at(sfCoverAvailable) -= clawAmount; + view().update(sleBroker); + + // Transfer assets from pseudo-account to depositor. + return accountSend( + view(), brokerPseudoID, account, clawAmount, j_, WaiveTransferFee::Yes); +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.h b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.h new file mode 100644 index 0000000000..183d3c4479 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.h @@ -0,0 +1,34 @@ +#ifndef XRPL_TX_LOANBROKERCOVERCLAWBACK_H_INCLUDED +#define XRPL_TX_LOANBROKERCOVERCLAWBACK_H_INCLUDED + +#include + +namespace ripple { + +class LoanBrokerCoverClawback : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanBrokerCoverClawback(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static TER + preclaim(PreclaimContext const& ctx); + + TER + doApply() override; +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp new file mode 100644 index 0000000000..4e9e0e9c05 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp @@ -0,0 +1,123 @@ +#include +// +#include + +namespace ripple { + +bool +LoanBrokerCoverDeposit::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +NotTEC +LoanBrokerCoverDeposit::preflight(PreflightContext const& ctx) +{ + if (ctx.tx[sfLoanBrokerID] == beast::zero) + return temINVALID; + + auto const dstAmount = ctx.tx[sfAmount]; + if (dstAmount <= beast::zero) + return temBAD_AMOUNT; + + if (!isLegalNet(dstAmount)) + return temBAD_AMOUNT; + + return tesSUCCESS; +} + +TER +LoanBrokerCoverDeposit::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + auto const account = tx[sfAccount]; + auto const brokerID = tx[sfLoanBrokerID]; + auto const amount = tx[sfAmount]; + + auto const sleBroker = ctx.view.read(keylet::loanbroker(brokerID)); + if (!sleBroker) + { + JLOG(ctx.j.warn()) << "LoanBroker does not exist."; + return tecNO_ENTRY; + } + if (account != sleBroker->at(sfOwner)) + { + JLOG(ctx.j.warn()) << "Account is not the owner of the LoanBroker."; + return tecNO_PERMISSION; + } + auto const vault = ctx.view.read(keylet::vault(sleBroker->at(sfVaultID))); + if (!vault) + { + // LCOV_EXCL_START + JLOG(ctx.j.fatal()) << "Vault is missing for Broker " << brokerID; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + + auto const vaultAsset = vault->at(sfAsset); + if (amount.asset() != vaultAsset) + return tecWRONG_ASSET; + + auto const pseudoAccountID = sleBroker->at(sfAccount); + // Cannot transfer a non-transferable Asset + if (auto const ret = + canTransfer(ctx.view, vaultAsset, account, pseudoAccountID)) + return ret; + // Cannot transfer a frozen Asset + if (auto const ret = checkFrozen(ctx.view, account, vaultAsset)) + return ret; + // Pseudo-account cannot receive if asset is deep frozen + if (auto const ret = checkDeepFrozen(ctx.view, pseudoAccountID, vaultAsset)) + return ret; + // Cannot transfer unauthorized asset + if (auto const ret = + requireAuth(ctx.view, vaultAsset, account, AuthType::StrongAuth)) + return ret; + + if (accountHolds( + ctx.view, + account, + vaultAsset, + FreezeHandling::fhZERO_IF_FROZEN, + AuthHandling::ahZERO_IF_UNAUTHORIZED, + ctx.j) < amount) + return tecINSUFFICIENT_FUNDS; + + return tesSUCCESS; +} + +TER +LoanBrokerCoverDeposit::doApply() +{ + auto const& tx = ctx_.tx; + + auto const brokerID = tx[sfLoanBrokerID]; + auto const amount = tx[sfAmount]; + + auto broker = view().peek(keylet::loanbroker(brokerID)); + if (!broker) + return tecINTERNAL; // LCOV_EXCL_LINE + + auto const brokerPseudoID = broker->at(sfAccount); + + // Transfer assets from depositor to pseudo-account. + if (auto ter = accountSend( + view(), + account_, + brokerPseudoID, + amount, + j_, + WaiveTransferFee::Yes)) + return ter; + + // Increase the LoanBroker's CoverAvailable by Amount + broker->at(sfCoverAvailable) += amount; + view().update(broker); + + return tesSUCCESS; +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.h b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.h new file mode 100644 index 0000000000..23863b479c --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.h @@ -0,0 +1,34 @@ +#ifndef XRPL_TX_LOANBROKERCOVERDEPOSIT_H_INCLUDED +#define XRPL_TX_LOANBROKERCOVERDEPOSIT_H_INCLUDED + +#include + +namespace ripple { + +class LoanBrokerCoverDeposit : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanBrokerCoverDeposit(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static TER + preclaim(PreclaimContext const& ctx); + + TER + doApply() override; +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp new file mode 100644 index 0000000000..1fd5a1a471 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp @@ -0,0 +1,173 @@ +#include +// +#include +#include + +#include + +namespace ripple { + +bool +LoanBrokerCoverWithdraw::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +NotTEC +LoanBrokerCoverWithdraw::preflight(PreflightContext const& ctx) +{ + if (ctx.tx[sfLoanBrokerID] == beast::zero) + return temINVALID; + + auto const dstAmount = ctx.tx[sfAmount]; + if (dstAmount <= beast::zero) + return temBAD_AMOUNT; + + if (!isLegalNet(dstAmount)) + return temBAD_AMOUNT; + + if (auto const destination = ctx.tx[~sfDestination]) + { + if (*destination == beast::zero) + { + return temMALFORMED; + } + } + + return tesSUCCESS; +} + +TER +LoanBrokerCoverWithdraw::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + auto const account = tx[sfAccount]; + auto const brokerID = tx[sfLoanBrokerID]; + auto const amount = tx[sfAmount]; + + auto const dstAcct = tx[~sfDestination].value_or(account); + + auto const sleBroker = ctx.view.read(keylet::loanbroker(brokerID)); + if (!sleBroker) + { + JLOG(ctx.j.warn()) << "LoanBroker does not exist."; + return tecNO_ENTRY; + } + if (account != sleBroker->at(sfOwner)) + { + JLOG(ctx.j.warn()) << "Account is not the owner of the LoanBroker."; + return tecNO_PERMISSION; + } + auto const vault = ctx.view.read(keylet::vault(sleBroker->at(sfVaultID))); + if (!vault) + { + // LCOV_EXCL_START + JLOG(ctx.j.fatal()) << "Vault is missing for Broker " << brokerID; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + + auto const vaultAsset = vault->at(sfAsset); + if (amount.asset() != vaultAsset) + return tecWRONG_ASSET; + + // The broker's pseudo-account is the source of funds. + auto const pseudoAccountID = sleBroker->at(sfAccount); + // Cannot transfer a non-transferable Asset + if (auto const ret = + canTransfer(ctx.view, vaultAsset, pseudoAccountID, dstAcct)) + return ret; + + // Withdrawal to a 3rd party destination account is essentially a transfer. + // Enforce all the usual asset transfer checks. + AuthType authType = AuthType::WeakAuth; + if (account != dstAcct) + { + if (auto const ret = canWithdraw(ctx.view, tx)) + return ret; + + // The destination account must have consented to receive the asset by + // creating a RippleState or MPToken + authType = AuthType::StrongAuth; + } + + // Destination MPToken must exist (if asset is an MPT) + if (auto const ter = requireAuth(ctx.view, vaultAsset, dstAcct, authType)) + return ter; + + // Check for freezes, unless sending directly to the issuer + if (dstAcct != vaultAsset.getIssuer()) + { + // Cannot send a frozen Asset + if (auto const ret = checkFrozen(ctx.view, pseudoAccountID, vaultAsset)) + return ret; + // Destination account cannot receive if asset is deep frozen + if (auto const ret = checkDeepFrozen(ctx.view, dstAcct, vaultAsset)) + return ret; + } + + auto const coverAvail = sleBroker->at(sfCoverAvailable); + // Cover Rate is in 1/10 bips units + auto const currentDebtTotal = sleBroker->at(sfDebtTotal); + auto const minimumCover = [&]() { + // Always round the minimum required up. + // Applies to `tenthBipsOfValue` as well as `roundToAsset`. + NumberRoundModeGuard mg(Number::upward); + return roundToAsset( + vaultAsset, + tenthBipsOfValue( + currentDebtTotal, + TenthBips32(sleBroker->at(sfCoverRateMinimum))), + currentDebtTotal.exponent()); + }(); + if (coverAvail < amount) + return tecINSUFFICIENT_FUNDS; + if ((coverAvail - amount) < minimumCover) + return tecINSUFFICIENT_FUNDS; + + if (accountHolds( + ctx.view, + pseudoAccountID, + vaultAsset, + FreezeHandling::fhZERO_IF_FROZEN, + AuthHandling::ahZERO_IF_UNAUTHORIZED, + ctx.j) < amount) + return tecINSUFFICIENT_FUNDS; + + return tesSUCCESS; +} + +TER +LoanBrokerCoverWithdraw::doApply() +{ + auto const& tx = ctx_.tx; + + auto const brokerID = tx[sfLoanBrokerID]; + auto const amount = tx[sfAmount]; + auto const dstAcct = tx[~sfDestination].value_or(account_); + + auto broker = view().peek(keylet::loanbroker(brokerID)); + if (!broker) + return tecINTERNAL; // LCOV_EXCL_LINE + + auto const brokerPseudoID = *broker->at(sfAccount); + + // Decrease the LoanBroker's CoverAvailable by Amount + broker->at(sfCoverAvailable) -= amount; + view().update(broker); + + return doWithdraw( + view(), + tx, + account_, + dstAcct, + brokerPseudoID, + mPriorBalance, + amount, + j_); +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h new file mode 100644 index 0000000000..eab2c9e60f --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h @@ -0,0 +1,34 @@ +#ifndef XRPL_TX_LOANBROKERCOVERWITHDRAW_H_INCLUDED +#define XRPL_TX_LOANBROKERCOVERWITHDRAW_H_INCLUDED + +#include + +namespace ripple { + +class LoanBrokerCoverWithdraw : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanBrokerCoverWithdraw(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static TER + preclaim(PreclaimContext const& ctx); + + TER + doApply() override; +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp b/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp new file mode 100644 index 0000000000..f3dd781bb5 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp @@ -0,0 +1,197 @@ +#include +// +#include + +namespace ripple { + +bool +LoanBrokerDelete::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +NotTEC +LoanBrokerDelete::preflight(PreflightContext const& ctx) +{ + if (ctx.tx[sfLoanBrokerID] == beast::zero) + return temINVALID; + + return tesSUCCESS; +} + +TER +LoanBrokerDelete::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + auto const account = tx[sfAccount]; + auto const brokerID = tx[sfLoanBrokerID]; + + auto const sleBroker = ctx.view.read(keylet::loanbroker(brokerID)); + if (!sleBroker) + { + JLOG(ctx.j.warn()) << "LoanBroker does not exist."; + return tecNO_ENTRY; + } + + auto const brokerOwner = sleBroker->at(sfOwner); + + if (account != brokerOwner) + { + JLOG(ctx.j.warn()) << "Account is not the owner of the LoanBroker."; + return tecNO_PERMISSION; + } + if (auto const ownerCount = sleBroker->at(sfOwnerCount); ownerCount != 0) + { + JLOG(ctx.j.warn()) << "LoanBrokerDelete: Owner count is " << ownerCount; + return tecHAS_OBLIGATIONS; + } + if (auto const debtTotal = sleBroker->at(sfDebtTotal); + debtTotal != beast::zero) + { + // Any remaining debt should have been wiped out by the last Loan + // Delete. This check is purely defensive. + auto const vault = + ctx.view.read(keylet::vault(sleBroker->at(sfVaultID))); + if (!vault) + return tefINTERNAL; // LCOV_EXCL_LINE + auto const asset = vault->at(sfAsset); + auto const scale = getVaultScale(vault); + + auto const rounded = + roundToAsset(asset, debtTotal, scale, Number::towards_zero); + + if (rounded != beast::zero) + { + // LCOV_EXCL_START + JLOG(ctx.j.warn()) << "LoanBrokerDelete: Debt total is " + << debtTotal << ", which rounds to " << rounded; + return tecHAS_OBLIGATIONS; + // LCOV_EXCL_START + } + } + + auto const vault = ctx.view.read(keylet::vault(sleBroker->at(sfVaultID))); + if (!vault) + { + // LCOV_EXCL_START + JLOG(ctx.j.fatal()) << "Vault is missing for Broker " << brokerID; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + + Asset const asset = vault->at(sfAsset); + + auto const coverAvailable = + STAmount{asset, sleBroker->at(sfCoverAvailable)}; + // If there are assets in the cover, broker will receive them on deletion. + // So we need to check if the broker owner is deep frozen for that asset. + if (coverAvailable > beast::zero) + { + if (auto const ret = checkDeepFrozen(ctx.view, brokerOwner, asset)) + { + JLOG(ctx.j.warn()) << "Broker owner account is frozen."; + return ret; + } + } + + return tesSUCCESS; +} + +TER +LoanBrokerDelete::doApply() +{ + auto const& tx = ctx_.tx; + + auto const brokerID = tx[sfLoanBrokerID]; + + // Delete the loan broker + auto broker = view().peek(keylet::loanbroker(brokerID)); + if (!broker) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const vaultID = broker->at(sfVaultID); + auto const sleVault = view().read(keylet::vault(vaultID)); + if (!sleVault) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const vaultPseudoID = sleVault->at(sfAccount); + auto const vaultAsset = sleVault->at(sfAsset); + + auto const brokerPseudoID = broker->at(sfAccount); + + if (!view().dirRemove( + keylet::ownerDir(account_), + broker->at(sfOwnerNode), + broker->key(), + false)) + { + return tefBAD_LEDGER; // LCOV_EXCL_LINE + } + if (!view().dirRemove( + keylet::ownerDir(vaultPseudoID), + broker->at(sfVaultNode), + broker->key(), + false)) + { + return tefBAD_LEDGER; // LCOV_EXCL_LINE + } + + { + auto const coverAvailable = + STAmount{vaultAsset, broker->at(sfCoverAvailable)}; + if (auto const ter = accountSend( + view(), + brokerPseudoID, + account_, + coverAvailable, + j_, + WaiveTransferFee::Yes)) + return ter; + } + + if (auto ter = removeEmptyHolding(view(), brokerPseudoID, vaultAsset, j_)) + return ter; + + auto brokerPseudoSLE = view().peek(keylet::account(brokerPseudoID)); + if (!brokerPseudoSLE) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + // Making the payment and removing the empty holding should have deleted any + // obligations associated with the broker or broker pseudo-account. + if (*brokerPseudoSLE->at(sfBalance)) + { + JLOG(j_.warn()) << "LoanBrokerDelete: Pseudo-account has a balance"; + return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE + } + if (brokerPseudoSLE->at(sfOwnerCount) != 0) + { + JLOG(j_.warn()) + << "LoanBrokerDelete: Pseudo-account still owns objects"; + return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE + } + if (auto const directory = keylet::ownerDir(brokerPseudoID); + view().read(directory)) + { + JLOG(j_.warn()) << "LoanBrokerDelete: Pseudo-account has a directory"; + return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE + } + + view().erase(brokerPseudoSLE); + + view().erase(broker); + + { + auto owner = view().peek(keylet::account(account_)); + if (!owner) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + // Decreases the owner count by two: one for the LoanBroker object, and + // one for the pseudo-account. + adjustOwnerCount(view(), owner, -2, j_); + } + + return tesSUCCESS; +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanBrokerDelete.h b/src/xrpld/app/tx/detail/LoanBrokerDelete.h new file mode 100644 index 0000000000..8466fe4f95 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerDelete.h @@ -0,0 +1,34 @@ +#ifndef XRPL_TX_LOANBROKERDELETE_H_INCLUDED +#define XRPL_TX_LOANBROKERDELETE_H_INCLUDED + +#include + +namespace ripple { + +class LoanBrokerDelete : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanBrokerDelete(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static TER + preclaim(PreclaimContext const& ctx); + + TER + doApply() override; +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerSet.cpp b/src/xrpld/app/tx/detail/LoanBrokerSet.cpp new file mode 100644 index 0000000000..c2e6effd7a --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerSet.cpp @@ -0,0 +1,215 @@ +#include +// +#include + +namespace ripple { + +bool +LoanBrokerSet::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +NotTEC +LoanBrokerSet::preflight(PreflightContext const& ctx) +{ + using namespace Lending; + + auto const& tx = ctx.tx; + if (auto const data = tx[~sfData]; data && !data->empty() && + !validDataLength(tx[~sfData], maxDataPayloadLength)) + return temINVALID; + if (!validNumericRange(tx[~sfManagementFeeRate], maxManagementFeeRate)) + return temINVALID; + if (!validNumericRange(tx[~sfCoverRateMinimum], maxCoverRate)) + return temINVALID; + if (!validNumericRange(tx[~sfCoverRateLiquidation], maxCoverRate)) + return temINVALID; + if (!validNumericRange( + tx[~sfDebtMaximum], Number(maxMPTokenAmount), Number(0))) + return temINVALID; + + if (tx.isFieldPresent(sfLoanBrokerID)) + { + // Fixed fields can not be specified if we're modifying an existing + // LoanBroker Object + if (tx.isFieldPresent(sfManagementFeeRate) || + tx.isFieldPresent(sfCoverRateMinimum) || + tx.isFieldPresent(sfCoverRateLiquidation)) + return temINVALID; + + if (tx[sfLoanBrokerID] == beast::zero) + return temINVALID; + } + + if (auto const vaultID = tx.at(~sfVaultID)) + { + if (*vaultID == beast::zero) + return temINVALID; + } + + { + auto const minimumZero = tx[~sfCoverRateMinimum].value_or(0) == 0; + auto const liquidationZero = + tx[~sfCoverRateLiquidation].value_or(0) == 0; + // Both must be zero or non-zero. + if (minimumZero != liquidationZero) + { + return temINVALID; + } + } + + return tesSUCCESS; +} + +TER +LoanBrokerSet::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + auto const account = tx[sfAccount]; + auto const vaultID = tx[sfVaultID]; + + if (auto const brokerID = tx[~sfLoanBrokerID]) + { + auto const sleBroker = ctx.view.read(keylet::loanbroker(*brokerID)); + if (!sleBroker) + { + JLOG(ctx.j.warn()) << "LoanBroker does not exist."; + return tecNO_ENTRY; + } + if (vaultID != sleBroker->at(sfVaultID)) + { + JLOG(ctx.j.warn()) + << "Can not change VaultID on an existing LoanBroker."; + return tecNO_PERMISSION; + } + if (account != sleBroker->at(sfOwner)) + { + JLOG(ctx.j.warn()) << "Account is not the owner of the LoanBroker."; + return tecNO_PERMISSION; + } + } + else + { + auto const sleVault = ctx.view.read(keylet::vault(vaultID)); + if (!sleVault) + { + JLOG(ctx.j.warn()) << "Vault does not exist."; + return tecNO_ENTRY; + } + if (account != sleVault->at(sfOwner)) + { + JLOG(ctx.j.warn()) << "Account is not the owner of the Vault."; + return tecNO_PERMISSION; + } + if (auto const ter = canAddHolding(ctx.view, sleVault->at(sfAsset))) + return ter; + } + return tesSUCCESS; +} + +TER +LoanBrokerSet::doApply() +{ + auto const& tx = ctx_.tx; + auto& view = ctx_.view(); + + if (auto const brokerID = tx[~sfLoanBrokerID]) + { + // Modify an existing LoanBroker + auto broker = view.peek(keylet::loanbroker(*brokerID)); + if (!broker) + { + // This should be impossible + // LCOV_EXCL_START + JLOG(j_.fatal()) << "LoanBroker does not exist."; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + + if (auto const data = tx[~sfData]) + broker->at(sfData) = *data; + if (auto const debtMax = tx[~sfDebtMaximum]) + broker->at(sfDebtMaximum) = *debtMax; + + view.update(broker); + } + else + { + // Create a new LoanBroker pointing back to the given Vault + auto const vaultID = tx[sfVaultID]; + auto const sleVault = view.read(keylet::vault(vaultID)); + if (!sleVault) + { + // This should be impossible + // LCOV_EXCL_START + JLOG(j_.fatal()) << "Vault does not exist."; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + auto const vaultPseudoID = sleVault->at(sfAccount); + auto const sequence = tx.getSeqValue(); + + auto owner = view.peek(keylet::account(account_)); + if (!owner) + { + // This should be impossible + // LCOV_EXCL_START + JLOG(j_.fatal()) << "Account does not exist."; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + auto broker = + std::make_shared(keylet::loanbroker(account_, sequence)); + + if (auto const ter = dirLink(view, account_, broker)) + return ter; // LCOV_EXCL_LINE + if (auto const ter = dirLink(view, vaultPseudoID, broker, sfVaultNode)) + return ter; // LCOV_EXCL_LINE + + // Increases the owner count by two: one for the LoanBroker object, and + // one for the pseudo-account. + adjustOwnerCount(view, owner, 2, j_); + auto const ownerCount = owner->at(sfOwnerCount); + if (mPriorBalance < view.fees().accountReserve(ownerCount)) + return tecINSUFFICIENT_RESERVE; + + auto maybePseudo = + createPseudoAccount(view, broker->key(), sfLoanBrokerID); + if (!maybePseudo) + return maybePseudo.error(); // LCOV_EXCL_LINE + auto& pseudo = *maybePseudo; + auto pseudoId = pseudo->at(sfAccount); + + if (auto ter = addEmptyHolding( + view, pseudoId, mPriorBalance, sleVault->at(sfAsset), j_)) + return ter; + + // Initialize data fields: + broker->at(sfSequence) = sequence; + broker->at(sfVaultID) = vaultID; + broker->at(sfOwner) = account_; + broker->at(sfAccount) = pseudoId; + // The LoanSequence indexes loans created by this broker, starting at 1 + broker->at(sfLoanSequence) = 1; + if (auto const data = tx[~sfData]) + broker->at(sfData) = *data; + if (auto const rate = tx[~sfManagementFeeRate]) + broker->at(sfManagementFeeRate) = *rate; + if (auto const debtMax = tx[~sfDebtMaximum]) + broker->at(sfDebtMaximum) = *debtMax; + if (auto const coverMin = tx[~sfCoverRateMinimum]) + broker->at(sfCoverRateMinimum) = *coverMin; + if (auto const coverLiq = tx[~sfCoverRateLiquidation]) + broker->at(sfCoverRateLiquidation) = *coverLiq; + + view.insert(broker); + } + + return tesSUCCESS; +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanBrokerSet.h b/src/xrpld/app/tx/detail/LoanBrokerSet.h new file mode 100644 index 0000000000..39ed9bcd61 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanBrokerSet.h @@ -0,0 +1,34 @@ +#ifndef XRPL_TX_LOANBROKERSET_H_INCLUDED +#define XRPL_TX_LOANBROKERSET_H_INCLUDED + +#include + +namespace ripple { + +class LoanBrokerSet : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanBrokerSet(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static TER + preclaim(PreclaimContext const& ctx); + + TER + doApply() override; +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/LoanDelete.cpp b/src/xrpld/app/tx/detail/LoanDelete.cpp new file mode 100644 index 0000000000..87ff4d594b --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanDelete.cpp @@ -0,0 +1,133 @@ +#include +// +#include + +namespace ripple { + +bool +LoanDelete::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +NotTEC +LoanDelete::preflight(PreflightContext const& ctx) +{ + if (ctx.tx[sfLoanID] == beast::zero) + return temINVALID; + + return tesSUCCESS; +} + +TER +LoanDelete::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + auto const account = tx[sfAccount]; + auto const loanID = tx[sfLoanID]; + + auto const loanSle = ctx.view.read(keylet::loan(loanID)); + if (!loanSle) + { + JLOG(ctx.j.warn()) << "Loan does not exist."; + return tecNO_ENTRY; + } + if (loanSle->at(sfPaymentRemaining) > 0) + { + JLOG(ctx.j.warn()) << "Active loan can not be deleted."; + return tecHAS_OBLIGATIONS; + } + + auto const loanBrokerID = loanSle->at(sfLoanBrokerID); + auto const loanBrokerSle = ctx.view.read(keylet::loanbroker(loanBrokerID)); + if (!loanBrokerSle) + { + // should be impossible + return tecINTERNAL; // LCOV_EXCL_LINE + } + if (loanBrokerSle->at(sfOwner) != account && + loanSle->at(sfBorrower) != account) + { + JLOG(ctx.j.warn()) + << "Account is not Loan Broker Owner or Loan Borrower."; + return tecNO_PERMISSION; + } + + return tesSUCCESS; +} + +TER +LoanDelete::doApply() +{ + auto const& tx = ctx_.tx; + auto& view = ctx_.view(); + + auto const loanID = tx[sfLoanID]; + auto const loanSle = view.peek(keylet::loan(loanID)); + if (!loanSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const borrower = loanSle->at(sfBorrower); + auto const borrowerSle = view.peek(keylet::account(borrower)); + if (!borrowerSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + auto const brokerID = loanSle->at(sfLoanBrokerID); + auto const brokerSle = view.peek(keylet::loanbroker(brokerID)); + if (!brokerSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const brokerPseudoAccount = brokerSle->at(sfAccount); + + auto const vaultSle = view.peek(keylet ::vault(brokerSle->at(sfVaultID))); + if (!vaultSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + // Remove LoanID from Directory of the LoanBroker pseudo-account. + if (!view.dirRemove( + keylet::ownerDir(brokerPseudoAccount), + loanSle->at(sfLoanBrokerNode), + loanID, + false)) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + // Remove LoanID from Directory of the Borrower. + if (!view.dirRemove( + keylet::ownerDir(borrower), + loanSle->at(sfOwnerNode), + loanID, + false)) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + // Delete the Loan object + view.erase(loanSle); + + // Decrement the LoanBroker's owner count. + // The broker's owner count is solely for the number of outstanding loans, + // and is distinct from the broker's pseudo-account's owner count + adjustOwnerCount(view, brokerSle, -1, j_); + // If there are no loans left, then any remaining debt must be forgiven, + // because there is no other way to pay it back. + if (brokerSle->at(sfOwnerCount) == 0) + { + auto debtTotalProxy = brokerSle->at(sfDebtTotal); + if (*debtTotalProxy != beast::zero) + { + XRPL_ASSERT_PARTS( + roundToAsset( + vaultSle->at(sfAsset), + debtTotalProxy, + getVaultScale(vaultSle), + Number::towards_zero) == beast::zero, + "ripple::LoanDelete::doApply", + "last loan, remaining debt rounds to zero"); + debtTotalProxy = 0; + } + } + // Decrement the borrower's owner count + adjustOwnerCount(view, borrowerSle, -1, j_); + + return tesSUCCESS; +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanDelete.h b/src/xrpld/app/tx/detail/LoanDelete.h new file mode 100644 index 0000000000..cbc37dec14 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanDelete.h @@ -0,0 +1,34 @@ +#ifndef XRPL_TX_LOANDELETE_H_INCLUDED +#define XRPL_TX_LOANDELETE_H_INCLUDED + +#include + +namespace ripple { + +class LoanDelete : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanDelete(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static TER + preclaim(PreclaimContext const& ctx); + + TER + doApply() override; +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/LoanManage.cpp b/src/xrpld/app/tx/detail/LoanManage.cpp new file mode 100644 index 0000000000..adf08d71bf --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanManage.cpp @@ -0,0 +1,420 @@ +#include +// +#include + +#include + +namespace ripple { + +bool +LoanManage::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +std::uint32_t +LoanManage::getFlagsMask(PreflightContext const& ctx) +{ + return tfLoanManageMask; +} + +NotTEC +LoanManage::preflight(PreflightContext const& ctx) +{ + if (ctx.tx[sfLoanID] == beast::zero) + return temINVALID; + + // Flags are mutually exclusive + if (auto const flagField = ctx.tx[~sfFlags]; flagField && *flagField) + { + auto const flags = *flagField & tfUniversalMask; + if ((flags & (flags - 1)) != 0) + { + JLOG(ctx.j.warn()) + << "LoanManage: Only one of tfLoanDefault, tfLoanImpair, or " + "tfLoanUnimpair can be set."; + return temINVALID_FLAG; + } + } + + return tesSUCCESS; +} + +TER +LoanManage::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + auto const account = tx[sfAccount]; + auto const loanID = tx[sfLoanID]; + + auto const loanSle = ctx.view.read(keylet::loan(loanID)); + if (!loanSle) + { + JLOG(ctx.j.warn()) << "Loan does not exist."; + return tecNO_ENTRY; + } + // Impairment only allows certain transitions. + // 1. Once it's in default, it can't be changed. + // 2. It can get worse: unimpaired -> impaired -> default + // or unimpaired -> default + // 3. It can get better: impaired -> unimpaired + // 4. If it's in a state, it can't be put in that state again. + if (loanSle->isFlag(lsfLoanDefault)) + { + JLOG(ctx.j.warn()) + << "Loan is in default. A defaulted loan can not be modified."; + return tecNO_PERMISSION; + } + if (loanSle->isFlag(lsfLoanImpaired) && tx.isFlag(tfLoanImpair)) + { + JLOG(ctx.j.warn()) + << "Loan is impaired. A loan can not be impaired twice."; + return tecNO_PERMISSION; + } + if (!(loanSle->isFlag(lsfLoanImpaired) || + loanSle->isFlag(lsfLoanDefault)) && + (tx.isFlag(tfLoanUnimpair))) + { + JLOG(ctx.j.warn()) + << "Loan is unimpaired. Can not be unimpaired again."; + return tecNO_PERMISSION; + } + if (loanSle->at(sfPaymentRemaining) == 0) + { + JLOG(ctx.j.warn()) << "Loan is fully paid. A loan can not be modified " + "after it is fully paid."; + return tecNO_PERMISSION; + } + if (tx.isFlag(tfLoanDefault) && + !hasExpired( + ctx.view, + loanSle->at(sfNextPaymentDueDate) + loanSle->at(sfGracePeriod))) + { + JLOG(ctx.j.warn()) + << "A loan can not be defaulted before the next payment due date."; + return tecTOO_SOON; + } + + auto const loanBrokerID = loanSle->at(sfLoanBrokerID); + auto const loanBrokerSle = ctx.view.read(keylet::loanbroker(loanBrokerID)); + if (!loanBrokerSle) + { + // should be impossible + return tecINTERNAL; // LCOV_EXCL_LINE + } + if (loanBrokerSle->at(sfOwner) != account) + { + JLOG(ctx.j.warn()) + << "LoanBroker for Loan does not belong to the account. LoanModify " + "can only be submitted by the Loan Broker."; + return tecNO_PERMISSION; + } + + return tesSUCCESS; +} + +static Number +owedToVault(SLE::ref loanSle) +{ + // Spec section 3.2.3.2, defines the default amount as + // + // DefaultAmount = (Loan.PrincipalOutstanding + Loan.InterestOutstanding) + // + // Loan.InterestOutstanding is not stored directly on ledger. + // It is computed as + // + // Loan.TotalValueOutstanding - Loan.PrincipalOutstanding - + // Loan.ManagementFeeOutstanding + // + // Add that to the original formula, and you get this: + return loanSle->at(sfTotalValueOutstanding) - + loanSle->at(sfManagementFeeOutstanding); +} + +TER +LoanManage::defaultLoan( + ApplyView& view, + SLE::ref loanSle, + SLE::ref brokerSle, + SLE::ref vaultSle, + Asset const& vaultAsset, + beast::Journal j) +{ + // Calculate the amount of the Default that First-Loss Capital covers: + + std::int32_t const loanScale = loanSle->at(sfLoanScale); + auto brokerDebtTotalProxy = brokerSle->at(sfDebtTotal); + + Number const totalDefaultAmount = owedToVault(loanSle); + + // Apply the First-Loss Capital to the Default Amount + TenthBips32 const coverRateMinimum{brokerSle->at(sfCoverRateMinimum)}; + TenthBips32 const coverRateLiquidation{ + brokerSle->at(sfCoverRateLiquidation)}; + auto const defaultCovered = [&]() { + // Always round the minimum required up. + NumberRoundModeGuard mg(Number::upward); + auto const minimumCover = + tenthBipsOfValue(brokerDebtTotalProxy.value(), coverRateMinimum); + // Round the liquidation amount up, too + return roundToAsset( + vaultAsset, + /* + * This formula is from the XLS-66 spec, section 3.2.3.2 (State + * Changes), specifically "if the `tfLoanDefault` flag is set" / + * "Apply the First-Loss Capital to the Default Amount" + */ + std::min( + tenthBipsOfValue(minimumCover, coverRateLiquidation), + totalDefaultAmount), + loanScale); + }(); + + auto const vaultDefaultAmount = totalDefaultAmount - defaultCovered; + + // Update the Vault object: + + // The vault may be at a different scale than the loan. Reduce rounding + // errors during the accounting by rounding some of the values to that + // scale. + auto const vaultScale = getVaultScale(vaultSle); + + { + // Decrease the Total Value of the Vault: + auto vaultTotalProxy = vaultSle->at(sfAssetsTotal); + auto vaultAvailableProxy = vaultSle->at(sfAssetsAvailable); + + if (vaultTotalProxy < vaultDefaultAmount) + { + // LCOV_EXCL_START + JLOG(j.warn()) + << "Vault total assets is less than the vault default amount"; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + + auto const vaultDefaultRounded = roundToAsset( + vaultAsset, vaultDefaultAmount, vaultScale, Number::downward); + vaultTotalProxy -= vaultDefaultRounded; + // Increase the Asset Available of the Vault by liquidated First-Loss + // Capital and any unclaimed funds amount: + vaultAvailableProxy += defaultCovered; + if (*vaultAvailableProxy > *vaultTotalProxy && !vaultAsset.integral()) + { + auto const difference = vaultAvailableProxy - vaultTotalProxy; + JLOG(j.debug()) + << "Vault assets available: " << *vaultAvailableProxy << "(" + << vaultAvailableProxy.value().exponent() + << "), Total: " << *vaultTotalProxy << "(" + << vaultTotalProxy.value().exponent() + << "), Difference: " << difference << "(" + << difference.exponent() << ")"; + if (vaultAvailableProxy.value().exponent() - difference.exponent() > + 13) + { + // If the difference is dust, bring the total up to match + // the available + JLOG(j.debug()) + << "Difference between vault assets available and total is " + "dust. Set both to the larger value."; + vaultTotalProxy = vaultAvailableProxy; + } + } + if (*vaultAvailableProxy > *vaultTotalProxy) + { + JLOG(j.warn()) << "Vault assets available must not be greater " + "than assets outstanding. Available: " + << *vaultAvailableProxy + << ", Total: " << *vaultTotalProxy; + return tecLIMIT_EXCEEDED; + } + + // The loss has been realized + if (loanSle->isFlag(lsfLoanImpaired)) + { + auto vaultLossUnrealizedProxy = vaultSle->at(sfLossUnrealized); + if (vaultLossUnrealizedProxy < totalDefaultAmount) + { + // LCOV_EXCL_START + JLOG(j.warn()) + << "Vault unrealized loss is less than the default amount"; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + vaultLossUnrealizedProxy -= totalDefaultAmount; + } + view.update(vaultSle); + } + + // Update the LoanBroker object: + + { + auto const asset = *vaultSle->at(sfAsset); + + // Decrease the Debt of the LoanBroker: + adjustImpreciseNumber( + brokerDebtTotalProxy, -totalDefaultAmount, asset, vaultScale); + // Decrease the First-Loss Capital Cover Available: + auto coverAvailableProxy = brokerSle->at(sfCoverAvailable); + if (coverAvailableProxy < defaultCovered) + { + // LCOV_EXCL_START + JLOG(j.warn()) + << "LoanBroker cover available is less than amount covered"; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + coverAvailableProxy -= defaultCovered; + view.update(brokerSle); + } + + // Update the Loan object: + loanSle->setFlag(lsfLoanDefault); + + loanSle->at(sfTotalValueOutstanding) = 0; + loanSle->at(sfPaymentRemaining) = 0; + loanSle->at(sfPrincipalOutstanding) = 0; + loanSle->at(sfManagementFeeOutstanding) = 0; + // Zero out the next due date. Since it's default, it'll be removed from + // the object. + loanSle->at(sfNextPaymentDueDate) = 0; + view.update(loanSle); + + // Return funds from the LoanBroker pseudo-account to the + // Vault pseudo-account: + return accountSend( + view, + brokerSle->at(sfAccount), + vaultSle->at(sfAccount), + STAmount{vaultAsset, defaultCovered}, + j, + WaiveTransferFee::Yes); +} + +TER +LoanManage::impairLoan( + ApplyView& view, + SLE::ref loanSle, + SLE::ref vaultSle, + beast::Journal j) +{ + Number const lossUnrealized = owedToVault(loanSle); + + // Update the Vault object(set "paper loss") + auto vaultLossUnrealizedProxy = vaultSle->at(sfLossUnrealized); + vaultLossUnrealizedProxy += lossUnrealized; + if (vaultLossUnrealizedProxy > + vaultSle->at(sfAssetsTotal) - vaultSle->at(sfAssetsAvailable)) + { + // Having a loss greater than the vault's unavailable assets + // will leave the vault in an invalid / inconsistent state. + JLOG(j.warn()) << "Vault unrealized loss is too large, and will " + "corrupt the vault."; + return tecLIMIT_EXCEEDED; + } + view.update(vaultSle); + + // Update the Loan object + loanSle->setFlag(lsfLoanImpaired); + auto loanNextDueProxy = loanSle->at(sfNextPaymentDueDate); + if (!hasExpired(view, loanNextDueProxy)) + { + // loan payment is not yet late - + // move the next payment due date to now + loanNextDueProxy = view.parentCloseTime().time_since_epoch().count(); + } + view.update(loanSle); + + return tesSUCCESS; +} + +TER +LoanManage::unimpairLoan( + ApplyView& view, + SLE::ref loanSle, + SLE::ref vaultSle, + beast::Journal j) +{ + // Update the Vault object(clear "paper loss") + auto vaultLossUnrealizedProxy = vaultSle->at(sfLossUnrealized); + Number const lossReversed = owedToVault(loanSle); + if (vaultLossUnrealizedProxy < lossReversed) + { + // LCOV_EXCL_START + JLOG(j.warn()) + << "Vault unrealized loss is less than the amount to be cleared"; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + vaultLossUnrealizedProxy -= lossReversed; + view.update(vaultSle); + + // Update the Loan object + loanSle->clearFlag(lsfLoanImpaired); + auto const paymentInterval = loanSle->at(sfPaymentInterval); + auto const normalPaymentDueDate = + std::max(loanSle->at(sfPreviousPaymentDate), loanSle->at(sfStartDate)) + + paymentInterval; + if (!hasExpired(view, normalPaymentDueDate)) + { + // loan was unimpaired within the payment interval + loanSle->at(sfNextPaymentDueDate) = normalPaymentDueDate; + } + else + { + // loan was unimpaired after the original payment due date + loanSle->at(sfNextPaymentDueDate) = + view.parentCloseTime().time_since_epoch().count() + paymentInterval; + } + view.update(loanSle); + + return tesSUCCESS; +} + +TER +LoanManage::doApply() +{ + auto const& tx = ctx_.tx; + auto& view = ctx_.view(); + + auto const loanID = tx[sfLoanID]; + auto const loanSle = view.peek(keylet::loan(loanID)); + if (!loanSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + auto const brokerID = loanSle->at(sfLoanBrokerID); + auto const brokerSle = view.peek(keylet::loanbroker(brokerID)); + if (!brokerSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + auto const vaultSle = view.peek(keylet ::vault(brokerSle->at(sfVaultID))); + if (!vaultSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const vaultAsset = vaultSle->at(sfAsset); + + // Valid flag combinations are checked in preflight. No flags is valid - + // just a noop. + if (tx.isFlag(tfLoanDefault)) + { + if (auto const ter = + defaultLoan(view, loanSle, brokerSle, vaultSle, vaultAsset, j_)) + return ter; + } + else if (tx.isFlag(tfLoanImpair)) + { + if (auto const ter = impairLoan(view, loanSle, vaultSle, j_)) + return ter; + } + else if (tx.isFlag(tfLoanUnimpair)) + { + if (auto const ter = unimpairLoan(view, loanSle, vaultSle, j_)) + return ter; + } + + return tesSUCCESS; +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanManage.h b/src/xrpld/app/tx/detail/LoanManage.h new file mode 100644 index 0000000000..dde1023cad --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanManage.h @@ -0,0 +1,66 @@ +#ifndef XRPL_TX_LOANMANAGE_H_INCLUDED +#define XRPL_TX_LOANMANAGE_H_INCLUDED + +#include + +namespace ripple { + +class LoanManage : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanManage(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static std::uint32_t + getFlagsMask(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static TER + preclaim(PreclaimContext const& ctx); + + /** Helper function that might be needed by other transactors + */ + static TER + defaultLoan( + ApplyView& view, + SLE::ref loanSle, + SLE::ref brokerSle, + SLE::ref vaultSle, + Asset const& vaultAsset, + beast::Journal j); + + /** Helper function that might be needed by other transactors + */ + static TER + impairLoan( + ApplyView& view, + SLE::ref loanSle, + SLE::ref vaultSle, + beast::Journal j); + + /** Helper function that might be needed by other transactors + */ + static TER + unimpairLoan( + ApplyView& view, + SLE::ref loanSle, + SLE::ref vaultSle, + beast::Journal j); + + TER + doApply() override; +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/LoanPay.cpp b/src/xrpld/app/tx/detail/LoanPay.cpp new file mode 100644 index 0000000000..43f19743a7 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanPay.cpp @@ -0,0 +1,602 @@ +#include +// +#include +#include + +#include +#include +#include + +#include + +namespace ripple { + +bool +LoanPay::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +std::uint32_t +LoanPay::getFlagsMask(PreflightContext const& ctx) +{ + return tfLoanPayMask; +} + +NotTEC +LoanPay::preflight(PreflightContext const& ctx) +{ + if (ctx.tx[sfLoanID] == beast::zero) + return temINVALID; + + if (ctx.tx[sfAmount] <= beast::zero) + return temBAD_AMOUNT; + + // The loan payment flags are all mutually exclusive. If more than one is + // set, the tx is malformed. + static_assert( + (tfLoanLatePayment | tfLoanFullPayment | tfLoanOverpayment) == + ~(tfLoanPayMask | tfUniversal)); + auto const flagsSet = ctx.tx.getFlags() & ~(tfLoanPayMask | tfUniversal); + if (std::popcount(flagsSet) > 1) + { + JLOG(ctx.j.warn()) << "Only one LoanPay flag can be set per tx. " + << flagsSet << " is too many."; + return temINVALID_FLAG; + } + + return tesSUCCESS; +} + +XRPAmount +LoanPay::calculateBaseFee(ReadView const& view, STTx const& tx) +{ + using namespace Lending; + + auto const normalCost = Transactor::calculateBaseFee(view, tx); + + if (tx.isFlag(tfLoanFullPayment) || tx.isFlag(tfLoanLatePayment)) + // The loan will be making one set of calculations for one full or late + // payment + return normalCost; + + // The fee is based on the potential number of payments, unless the loan is + // being fully paid off. + auto const amount = tx[sfAmount]; + auto const loanID = tx[sfLoanID]; + + auto const loanSle = view.read(keylet::loan(loanID)); + if (!loanSle) + // Let preclaim worry about the error for this + return normalCost; + + if (loanSle->at(sfPaymentRemaining) <= loanPaymentsPerFeeIncrement) + { + // If there are fewer than loanPaymentsPerFeeIncrement payments left to + // pay, we can skip the computations. + return normalCost; + } + + if (hasExpired(view, loanSle->at(sfNextPaymentDueDate))) + // If the payment is late, and the late payment flag is not set, it'll + // fail + return normalCost; + + auto const brokerSle = + view.read(keylet::loanbroker(loanSle->at(sfLoanBrokerID))); + if (!brokerSle) + // Let preclaim worry about the error for this + return normalCost; + auto const vaultSle = view.read(keylet::vault(brokerSle->at(sfVaultID))); + if (!vaultSle) + // Let preclaim worry about the error for this + return normalCost; + + auto const asset = vaultSle->at(sfAsset); + + if (asset != amount.asset()) + // Let preclaim worry about the error for this + return normalCost; + + auto const scale = loanSle->at(sfLoanScale); + + auto const regularPayment = + roundPeriodicPayment(asset, loanSle->at(sfPeriodicPayment), scale) + + loanSle->at(sfLoanServiceFee); + + // If making an overpayment, count it as a full payment because it will do + // about the same amount of work, if not more. + NumberRoundModeGuard mg( + tx.isFlag(tfLoanOverpayment) ? Number::upward : Number::downward); + // Estimate how many payments will be made + Number const numPaymentEstimate = + static_cast(amount / regularPayment); + + // Charge one base fee per paymentsPerFeeIncrement payments, rounding up. + Number::setround(Number::upward); + auto const feeIncrements = std::max( + std::int64_t(1), + static_cast( + numPaymentEstimate / loanPaymentsPerFeeIncrement)); + + return feeIncrements * normalCost; +} + +TER +LoanPay::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + auto const account = tx[sfAccount]; + auto const loanID = tx[sfLoanID]; + auto const amount = tx[sfAmount]; + + auto const loanSle = ctx.view.read(keylet::loan(loanID)); + if (!loanSle) + { + JLOG(ctx.j.warn()) << "Loan does not exist."; + return tecNO_ENTRY; + } + + if (loanSle->at(sfBorrower) != account) + { + JLOG(ctx.j.warn()) << "Loan does not belong to the account."; + return tecNO_PERMISSION; + } + + if (tx.isFlag(tfLoanOverpayment) && !loanSle->isFlag(lsfLoanOverpayment)) + { + JLOG(ctx.j.warn()) + << "Requested overpayment on a loan that doesn't allow it"; + return temINVALID_FLAG; + } + + auto const principalOutstanding = loanSle->at(sfPrincipalOutstanding); + TenthBips32 const interestRate{loanSle->at(sfInterestRate)}; + auto const paymentRemaining = loanSle->at(sfPaymentRemaining); + TenthBips32 const lateInterestRate{loanSle->at(sfLateInterestRate)}; + + if (paymentRemaining == 0 || principalOutstanding == 0) + { + JLOG(ctx.j.warn()) << "Loan is already paid off."; + return tecKILLED; + } + + auto const loanBrokerID = loanSle->at(sfLoanBrokerID); + auto const loanBrokerSle = ctx.view.read(keylet::loanbroker(loanBrokerID)); + if (!loanBrokerSle) + { + // This should be impossible + // LCOV_EXCL_START + JLOG(ctx.j.fatal()) << "LoanBroker does not exist."; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + auto const vaultID = loanBrokerSle->at(sfVaultID); + auto const vaultSle = ctx.view.read(keylet::vault(vaultID)); + if (!vaultSle) + { + // This should be impossible + // LCOV_EXCL_START + JLOG(ctx.j.fatal()) << "Vault does not exist."; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + auto const asset = vaultSle->at(sfAsset); + auto const vaultPseudoAccount = vaultSle->at(sfAccount); + + if (amount.asset() != asset) + { + JLOG(ctx.j.warn()) << "Loan amount does not match the Vault asset."; + return tecWRONG_ASSET; + } + + if (auto const ret = checkFrozen(ctx.view, account, asset)) + { + JLOG(ctx.j.warn()) << "Borrower account is frozen."; + return ret; + } + if (auto const ret = checkDeepFrozen(ctx.view, vaultPseudoAccount, asset)) + { + JLOG(ctx.j.warn()) + << "Vault pseudo-account can not receive funds (deep frozen)."; + return ret; + } + if (auto const ret = requireAuth(ctx.view, asset, account)) + { + JLOG(ctx.j.warn()) << "Borrower account is not authorized."; + return ret; + } + // Make sure the borrower has enough funds to make the payment! + // Do not support "partial payments" - if the transaction says to pay X, + // then the account must have X available, even if the loan payment takes + // less. + if (auto const balance = accountSpendable( + ctx.view, + account, + asset, + fhZERO_IF_FROZEN, + ahZERO_IF_UNAUTHORIZED, + ctx.j); + balance < amount) + { + JLOG(ctx.j.warn()) << "Payment amount too large. Amount: " + << to_string(amount.getJson()) + << ". Balance: " << to_string(balance.getJson()); + return tecINSUFFICIENT_FUNDS; + } + + return tesSUCCESS; +} + +TER +LoanPay::doApply() +{ + auto const& tx = ctx_.tx; + auto& view = ctx_.view(); + + auto const amount = tx[sfAmount]; + + auto const loanID = tx[sfLoanID]; + auto const loanSle = view.peek(keylet::loan(loanID)); + if (!loanSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + std::int32_t const loanScale = loanSle->at(sfLoanScale); + + auto const brokerID = loanSle->at(sfLoanBrokerID); + auto const brokerSle = view.peek(keylet::loanbroker(brokerID)); + if (!brokerSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const brokerOwner = brokerSle->at(sfOwner); + auto const brokerPseudoAccount = brokerSle->at(sfAccount); + auto const vaultID = brokerSle->at(sfVaultID); + auto const vaultSle = view.peek(keylet::vault(vaultID)); + if (!vaultSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const vaultPseudoAccount = vaultSle->at(sfAccount); + auto const asset = *vaultSle->at(sfAsset); + + // Determine where to send the broker's fee + auto coverAvailableProxy = brokerSle->at(sfCoverAvailable); + TenthBips32 const coverRateMinimum{brokerSle->at(sfCoverRateMinimum)}; + auto debtTotalProxy = brokerSle->at(sfDebtTotal); + + // Send the broker fee to the owner if they have sufficient cover available, + // _and_ if the owner can receive funds. If not, so as not to block the + // payment, add it to the cover balance (send it to the broker pseudo + // account). + // + // Normally freeze status is checked in preflight, but we do it here to + // avoid duplicating the check. It'll claim a fee either way. + bool const sendBrokerFeeToOwner = [&]() { + // Round the minimum required cover up to be conservative. This ensures + // CoverAvailable never drops below the theoretical minimum, protecting + // the broker's solvency. + NumberRoundModeGuard mg(Number::upward); + return coverAvailableProxy >= + roundToAsset( + asset, + tenthBipsOfValue(debtTotalProxy.value(), coverRateMinimum), + loanScale) && + !isDeepFrozen(view, brokerOwner, asset); + }(); + + auto const brokerPayee = + sendBrokerFeeToOwner ? brokerOwner : brokerPseudoAccount; + auto const brokerPayeeSle = view.peek(keylet::account(brokerPayee)); + if (!sendBrokerFeeToOwner) + { + // If we can't send the fee to the owner, and the pseudo-account is + // frozen, then we have to fail the payment. + if (auto const ret = checkDeepFrozen(view, brokerPayee, asset)) + { + JLOG(j_.warn()) + << "Both Loan Broker and Loan Broker pseudo-account " + "can not receive funds (deep frozen)."; + return ret; + } + } + + //------------------------------------------------------ + // Loan object state changes + + // Unimpair the loan if it was impaired. Do this before the payment is + // attempted, so the original values can be used. If the payment fails, this + // change will be discarded. + if (loanSle->isFlag(lsfLoanImpaired)) + { + LoanManage::unimpairLoan(view, loanSle, vaultSle, j_); + } + + LoanPaymentType const paymentType = [&tx]() { + // preflight already checked that at most one flag is set. + if (tx.isFlag(tfLoanLatePayment)) + return LoanPaymentType::late; + if (tx.isFlag(tfLoanFullPayment)) + return LoanPaymentType::full; + if (tx.isFlag(tfLoanOverpayment)) + return LoanPaymentType::overpayment; + return LoanPaymentType::regular; + }(); + + Expected const paymentParts = loanMakePayment( + asset, view, loanSle, brokerSle, amount, paymentType, j_); + + if (!paymentParts) + { + XRPL_ASSERT_PARTS( + paymentParts.error(), + "ripple::LoanPay::doApply", + "payment error is an error"); + return paymentParts.error(); + } + + // If the payment computation completed without error, the loanSle object + // has been modified. + view.update(loanSle); + + XRPL_ASSERT_PARTS( + // It is possible to pay 0 principal + paymentParts->principalPaid >= 0, + "ripple::LoanPay::doApply", + "valid principal paid"); + XRPL_ASSERT_PARTS( + // It is possible to pay 0 interest + paymentParts->interestPaid >= 0, + "ripple::LoanPay::doApply", + "valid interest paid"); + XRPL_ASSERT_PARTS( + // It should not be possible to pay 0 total + paymentParts->principalPaid + paymentParts->interestPaid > 0, + "ripple::LoanPay::doApply", + "valid total paid"); + XRPL_ASSERT_PARTS( + paymentParts->feePaid >= 0, + "ripple::LoanPay::doApply", + "valid fee paid"); + + if (paymentParts->principalPaid < 0 || paymentParts->interestPaid < 0 || + paymentParts->feePaid < 0) + { + // LCOV_EXCL_START + JLOG(j_.fatal()) << "Loan payment computation returned invalid values."; + return tecLIMIT_EXCEEDED; + // LCOV_EXCL_STOP + } + + JLOG(j_.debug()) << "Loan Pay: principal paid: " + << paymentParts->principalPaid + << ", interest paid: " << paymentParts->interestPaid + << ", fee paid: " << paymentParts->feePaid + << ", value change: " << paymentParts->valueChange; + + //------------------------------------------------------ + // LoanBroker object state changes + view.update(brokerSle); + + auto assetsAvailableProxy = vaultSle->at(sfAssetsAvailable); + auto assetsTotalProxy = vaultSle->at(sfAssetsTotal); + + // The vault may be at a different scale than the loan. Reduce rounding + // errors during the payment by rounding some of the values to that scale. + auto const vaultScale = assetsTotalProxy.value().exponent(); + + auto const totalPaidToVaultRaw = + paymentParts->principalPaid + paymentParts->interestPaid; + auto const totalPaidToVaultRounded = + roundToAsset(asset, totalPaidToVaultRaw, vaultScale, Number::downward); + XRPL_ASSERT_PARTS( + !asset.integral() || totalPaidToVaultRaw == totalPaidToVaultRounded, + "ripple::LoanPay::doApply", + "rounding does nothing for integral asset"); + // Account for value changes when reducing the broker's debt: + // - Positive value change (from full/late/overpayments): Subtract from the + // amount credited toward debt to avoid over-reducing the debt. + // - Negative value change (from full/overpayments): Add to the amount + // credited toward debt,effectively increasing the debt reduction. + auto const totalPaidToVaultForDebt = + totalPaidToVaultRaw - paymentParts->valueChange; + + auto const totalPaidToBroker = paymentParts->feePaid; + + XRPL_ASSERT_PARTS( + (totalPaidToVaultRaw + totalPaidToBroker) == + (paymentParts->principalPaid + paymentParts->interestPaid + + paymentParts->feePaid), + "ripple::LoanPay::doApply", + "payments add up"); + + // Decrease LoanBroker Debt by the amount paid, add the Loan value change + // (which might be negative). totalPaidToVaultForDebt may be negative, + // increasing the debt + XRPL_ASSERT_PARTS( + isRounded(asset, totalPaidToVaultForDebt, loanScale), + "ripple::LoanPay::doApply", + "totalPaidToVaultForDebt rounding good"); + // Despite our best efforts, it's possible for rounding errors to accumulate + // in the loan broker's debt total. This is because the broker may have more + // than one loan with significantly different scales. + adjustImpreciseNumber( + debtTotalProxy, -totalPaidToVaultForDebt, asset, vaultScale); + + //------------------------------------------------------ + // Vault object state changes + view.update(vaultSle); + + Number const assetsAvailableBefore = *assetsAvailableProxy; + Number const pseudoAccountBalanceBefore = accountHolds( + view, + vaultPseudoAccount, + asset, + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + j_); + + { + XRPL_ASSERT_PARTS( + assetsAvailableBefore == pseudoAccountBalanceBefore, + "ripple::LoanPay::doApply", + "vault pseudo balance agrees before"); + + assetsAvailableProxy += totalPaidToVaultRounded; + assetsTotalProxy += paymentParts->valueChange; + + XRPL_ASSERT_PARTS( + *assetsAvailableProxy <= *assetsTotalProxy, + "ripple::LoanPay::doApply", + "assets available must not be greater than assets outstanding"); + + if (*assetsAvailableProxy > *assetsTotalProxy) + { + // LCOV_EXCL_START + return tecINTERNAL; + // LCOV_EXCL_STOP + } + } + + JLOG(j_.debug()) << "total paid to vault raw: " << totalPaidToVaultRaw + << ", total paid to vault rounded: " + << totalPaidToVaultRounded + << ", total paid to broker: " << totalPaidToBroker + << ", amount from transaction: " << amount; + + // Move funds + XRPL_ASSERT_PARTS( + totalPaidToVaultRounded + totalPaidToBroker <= amount, + "ripple::LoanPay::doApply", + "amount is sufficient"); + + if (!sendBrokerFeeToOwner) + { + // If there is not enough first-loss capital, add the fee to First Loss + // Cover Pool. Note that this moves the entire fee - it does not attempt + // to split it. The broker can Withdraw it later if they want, or leave + // it for future needs. + coverAvailableProxy += totalPaidToBroker; + } + +#if !NDEBUG + auto const accountBalanceBefore = accountSpendable( + view, account_, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_); + auto const vaultBalanceBefore = account_ == vaultPseudoAccount + ? STAmount{asset, 0} + : accountSpendable( + view, + vaultPseudoAccount, + asset, + fhIGNORE_FREEZE, + ahIGNORE_AUTH, + j_); + auto const brokerBalanceBefore = account_ == brokerPayee + ? STAmount{asset, 0} + : accountSpendable( + view, brokerPayee, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_); +#endif + + if (totalPaidToVaultRounded != beast::zero) + { + if (auto const ter = requireAuth( + view, asset, vaultPseudoAccount, AuthType::StrongAuth)) + return ter; + } + + if (totalPaidToBroker != beast::zero) + { + if (brokerPayee == account_) + { + // The broker may have deleted their holding. Recreate it if needed + if (auto const ter = addEmptyHolding( + view, + brokerPayee, + brokerPayeeSle->at(sfBalance).value().xrp(), + asset, + j_); + ter && ter != tecDUPLICATE) + // ignore tecDUPLICATE. That means the holding already exists, + // and is fine here + return ter; + } + if (auto const ter = + requireAuth(view, asset, brokerPayee, AuthType::StrongAuth)) + return ter; + } + + if (auto const ter = accountSendMulti( + view, + account_, + asset, + {{vaultPseudoAccount, totalPaidToVaultRounded}, + {brokerPayee, totalPaidToBroker}}, + j_, + WaiveTransferFee::Yes)) + return ter; + + Number const assetsAvailableAfter = *assetsAvailableProxy; + Number const pseudoAccountBalanceAfter = accountHolds( + view, + vaultPseudoAccount, + asset, + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + j_); + XRPL_ASSERT_PARTS( + assetsAvailableAfter == pseudoAccountBalanceAfter, + "ripple::LoanPay::doApply", + "vault pseudo balance agrees after"); + +#if !NDEBUG + auto const accountBalanceAfter = accountSpendable( + view, account_, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_); + auto const vaultBalanceAfter = account_ == vaultPseudoAccount + ? STAmount{asset, 0} + : accountSpendable( + view, + vaultPseudoAccount, + asset, + fhIGNORE_FREEZE, + ahIGNORE_AUTH, + j_); + auto const brokerBalanceAfter = account_ == brokerPayee + ? STAmount{asset, 0} + : accountSpendable( + view, brokerPayee, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_); + + XRPL_ASSERT_PARTS( + accountBalanceBefore + vaultBalanceBefore + brokerBalanceBefore == + accountBalanceAfter + vaultBalanceAfter + brokerBalanceAfter, + "ripple::LoanPay::doApply", + "funds are conserved (with rounding)"); + XRPL_ASSERT_PARTS( + accountBalanceAfter >= beast::zero, + "ripple::LoanPay::doApply", + "positive account balance"); + XRPL_ASSERT_PARTS( + accountBalanceAfter < accountBalanceBefore || + account_ == asset.getIssuer(), + "ripple::LoanPay::doApply", + "account balance decreased"); + XRPL_ASSERT_PARTS( + vaultBalanceAfter >= beast::zero && brokerBalanceAfter >= beast::zero, + "ripple::LoanPay::doApply", + "positive vault and broker balances"); + XRPL_ASSERT_PARTS( + vaultBalanceAfter >= vaultBalanceBefore, + "ripple::LoanPay::doApply", + "vault balance did not decrease"); + XRPL_ASSERT_PARTS( + brokerBalanceAfter >= brokerBalanceBefore, + "ripple::LoanPay::doApply", + "broker balance did not decrease"); + XRPL_ASSERT_PARTS( + vaultBalanceAfter > vaultBalanceBefore || + brokerBalanceAfter > brokerBalanceBefore, + "ripple::LoanPay::doApply", + "vault and/or broker balance increased"); +#endif + + return tesSUCCESS; +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanPay.h b/src/xrpld/app/tx/detail/LoanPay.h new file mode 100644 index 0000000000..3f8eb16d04 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanPay.h @@ -0,0 +1,40 @@ +#ifndef XRPL_TX_LOANPAY_H_INCLUDED +#define XRPL_TX_LOANPAY_H_INCLUDED + +#include + +namespace ripple { + +class LoanPay : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanPay(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static std::uint32_t + getFlagsMask(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static XRPAmount + calculateBaseFee(ReadView const& view, STTx const& tx); + + static TER + preclaim(PreclaimContext const& ctx); + + TER + doApply() override; +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/LoanSet.cpp b/src/xrpld/app/tx/detail/LoanSet.cpp new file mode 100644 index 0000000000..838e774cae --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanSet.cpp @@ -0,0 +1,632 @@ +#include +// +#include + +#include + +namespace ripple { + +bool +LoanSet::checkExtraFeatures(PreflightContext const& ctx) +{ + return checkLendingProtocolDependencies(ctx); +} + +std::uint32_t +LoanSet::getFlagsMask(PreflightContext const& ctx) +{ + return tfLoanSetMask; +} + +NotTEC +LoanSet::preflight(PreflightContext const& ctx) +{ + using namespace Lending; + + auto const& tx = ctx.tx; + + // Special case for Batch inner transactions + if (tx.isFlag(tfInnerBatchTxn) && ctx.rules.enabled(featureBatch) && + !tx.isFieldPresent(sfCounterparty)) + { + auto const parentBatchId = ctx.parentBatchId.value_or(uint256{0}); + JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: " + << "no Counterparty for inner LoanSet transaction."; + return temBAD_SIGNER; + } + + // These extra hoops are because STObjects cannot be Proxy'd from STObject. + auto const counterPartySig = [&tx]() -> std::optional { + if (tx.isFieldPresent(sfCounterpartySignature)) + return tx.getFieldObject(sfCounterpartySignature); + return std::nullopt; + }(); + if (!tx.isFlag(tfInnerBatchTxn) && !counterPartySig) + { + JLOG(ctx.j.warn()) + << "LoanSet transaction must have a CounterpartySignature."; + return temBAD_SIGNER; + } + + if (counterPartySig) + { + if (auto const ret = ripple::detail::preflightCheckSigningKey( + *counterPartySig, ctx.j)) + return ret; + } + + if (auto const data = tx[~sfData]; data && !data->empty() && + !validDataLength(tx[~sfData], maxDataPayloadLength)) + return temINVALID; + for (auto const& field : + {&sfLoanServiceFee, &sfLatePaymentFee, &sfClosePaymentFee}) + { + if (!validNumericMinimum(tx[~*field])) + return temINVALID; + } + // Principal Requested is required + if (auto const p = tx[sfPrincipalRequested]; p <= 0) + return temINVALID; + else if (!validNumericRange(tx[~sfLoanOriginationFee], p)) + return temINVALID; + if (!validNumericRange(tx[~sfInterestRate], maxInterestRate)) + return temINVALID; + if (!validNumericRange(tx[~sfOverpaymentFee], maxOverpaymentFee)) + return temINVALID; + if (!validNumericRange(tx[~sfLateInterestRate], maxLateInterestRate)) + return temINVALID; + if (!validNumericRange(tx[~sfCloseInterestRate], maxCloseInterestRate)) + return temINVALID; + if (!validNumericRange( + tx[~sfOverpaymentInterestRate], maxOverpaymentInterestRate)) + return temINVALID; + + if (auto const paymentTotal = tx[~sfPaymentTotal]; + paymentTotal && *paymentTotal <= 0) + return temINVALID; + + if (auto const paymentInterval = tx[~sfPaymentInterval]; + !validNumericMinimum(paymentInterval, LoanSet::minPaymentInterval)) + return temINVALID; + + else if (!validNumericRange( + tx[~sfGracePeriod], + paymentInterval.value_or(LoanSet::defaultPaymentInterval))) + return temINVALID; + + // Copied from preflight2 + if (counterPartySig) + { + if (auto const ret = ripple::detail::preflightCheckSimulateKeys( + ctx.flags, *counterPartySig, ctx.j)) + return *ret; + } + + if (auto const brokerID = ctx.tx[~sfLoanBrokerID]; + brokerID && *brokerID == beast::zero) + return temINVALID; + + return tesSUCCESS; +} + +NotTEC +LoanSet::checkSign(PreclaimContext const& ctx) +{ + if (auto ret = Transactor::checkSign(ctx)) + return ret; + + // Counter signer is optional. If it's not specified, it's assumed to be + // `LoanBroker.Owner`. Note that we have not checked whether the + // loanbroker exists at this point. + auto const counterSigner = [&]() -> std::optional { + if (auto const c = ctx.tx.at(~sfCounterparty)) + return c; + + if (auto const broker = + ctx.view.read(keylet::loanbroker(ctx.tx[sfLoanBrokerID]))) + return broker->at(sfOwner); + return std::nullopt; + }(); + if (!counterSigner) + return temBAD_SIGNER; + + // Counterparty signature is optional. Presence is checked in preflight. + if (!ctx.tx.isFieldPresent(sfCounterpartySignature)) + return tesSUCCESS; + auto const counterSig = ctx.tx.getFieldObject(sfCounterpartySignature); + return Transactor::checkSign( + ctx.view, + ctx.flags, + ctx.parentBatchId, + *counterSigner, + counterSig, + ctx.j); +} + +XRPAmount +LoanSet::calculateBaseFee(ReadView const& view, STTx const& tx) +{ + auto const normalCost = Transactor::calculateBaseFee(view, tx); + + // Compute the additional cost of each signature in the + // CounterpartySignature, whether a single signature or a multisignature + XRPAmount const baseFee = view.fees().base; + + // Counterparty signature is optional, but getFieldObject will return an + // empty object if it's not present. + auto const counterSig = tx.getFieldObject(sfCounterpartySignature); + // Each signer adds one more baseFee to the minimum required fee + // for the transaction. Note that unlike the base class, the single signer + // is counted if present. It will only be absent in a batch inner + // transaction. + std::size_t const signerCount = [&counterSig]() { + // Compute defensively. Assure that "tx" cannot be accessed and cause + // confusion or miscalculations. + return counterSig.isFieldPresent(sfSigners) + ? counterSig.getFieldArray(sfSigners).size() + : (counterSig.isFieldPresent(sfTxnSignature) ? 1 : 0); + }(); + + return normalCost + (signerCount * baseFee); +} + +std::vector> const& +LoanSet::getValueFields() +{ + static std::vector> const valueFields{ + ~sfPrincipalRequested, + ~sfLoanOriginationFee, + ~sfLoanServiceFee, + ~sfLatePaymentFee, + ~sfClosePaymentFee + // Overpayment fee is really a rate. Don't check it here. + }; + + return valueFields; +} + +static std::uint32_t +getStartDate(ReadView const& view) +{ + return view.info().closeTime.time_since_epoch().count(); +} + +TER +LoanSet::preclaim(PreclaimContext const& ctx) +{ + auto const& tx = ctx.tx; + + { + // Check for numeric overflow of the schedule before we load any + // objects. The Grace Period for the last payment ends at: + // startDate + (paymentInterval * paymentTotal) + gracePeriod. + // If that value is larger than "maxTime", the value + // overflows, and we kill the transaction. + using timeType = decltype(sfNextPaymentDueDate)::type::value_type; + static_assert(std::is_same_v); + timeType constexpr maxTime = std::numeric_limits::max(); + static_assert(maxTime == 4'294'967'295); + + auto const timeAvailable = maxTime - getStartDate(ctx.view); + + auto const interval = + ctx.tx.at(~sfPaymentInterval).value_or(defaultPaymentInterval); + auto const total = + ctx.tx.at(~sfPaymentTotal).value_or(defaultPaymentTotal); + auto const grace = + ctx.tx.at(~sfGracePeriod).value_or(defaultGracePeriod); + + // The grace period can't be larger than the interval. Check it first, + // mostly so that unit tests can test that specific case. + if (grace > timeAvailable) + { + JLOG(ctx.j.warn()) << "Grace period exceeds protocol time limit."; + return tecKILLED; + } + + if (interval > timeAvailable) + { + JLOG(ctx.j.warn()) + << "Payment interval exceeds protocol time limit."; + return tecKILLED; + } + + if (total > timeAvailable) + { + JLOG(ctx.j.warn()) << "Payment total exceeds protocol time limit."; + return tecKILLED; + } + + auto const timeLastPayment = timeAvailable - grace; + + if (timeLastPayment / interval < total) + { + JLOG(ctx.j.warn()) << "Last payment due date, or grace period for " + "last payment exceeds protocol time limit."; + return tecKILLED; + } + } + + auto const account = tx[sfAccount]; + auto const brokerID = tx[sfLoanBrokerID]; + + auto const brokerSle = ctx.view.read(keylet::loanbroker(brokerID)); + if (!brokerSle) + { + // This can only be hit if there's a counterparty specified, otherwise + // it'll fail in the signature check + JLOG(ctx.j.warn()) << "LoanBroker does not exist."; + return tecNO_ENTRY; + } + auto const brokerOwner = brokerSle->at(sfOwner); + auto const counterparty = tx[~sfCounterparty].value_or(brokerOwner); + if (account != brokerOwner && counterparty != brokerOwner) + { + JLOG(ctx.j.warn()) << "Neither Account nor Counterparty are the owner " + "of the LoanBroker."; + return tecNO_PERMISSION; + } + auto const brokerPseudo = brokerSle->at(sfAccount); + + auto const borrower = counterparty == brokerOwner ? account : counterparty; + if (auto const borrowerSle = ctx.view.read(keylet::account(borrower)); + !borrowerSle) + { + // It may not be possible to hit this case, because it'll fail the + // signature check with terNO_ACCOUNT. + JLOG(ctx.j.warn()) << "Borrower does not exist."; + return terNO_ACCOUNT; + } + + auto const vault = ctx.view.read(keylet::vault(brokerSle->at(sfVaultID))); + if (!vault) + // Should be impossible + return tefBAD_LEDGER; // LCOV_EXCL_LINE + Asset const asset = vault->at(sfAsset); + + auto const vaultPseudo = vault->at(sfAccount); + + // Check that relevant values can be represented as the vault asset type. + // This check is almost duplicated in doApply, but that check is done after + // the overall loan scale is known. This is mostly only relevant for + // integral (non-IOU) types + { + for (auto const& field : getValueFields()) + { + if (auto const value = tx[field]; + value && STAmount{asset, *value} != *value) + { + JLOG(ctx.j.warn()) << field.f->getName() << " (" << *value + << ") can not be represented as a(n) " + << to_string(asset) << "."; + return tecPRECISION_LOSS; + } + } + } + + if (auto const ter = canAddHolding(ctx.view, asset)) + return ter; + + // vaultPseudo is going to send funds, so it can't be frozen. + if (auto const ret = checkFrozen(ctx.view, vaultPseudo, asset)) + { + JLOG(ctx.j.warn()) << "Vault pseudo-account is frozen."; + return ret; + } + + // brokerPseudo is the fallback account to receive LoanPay fees, even if the + // broker owner is unable to accept them. Don't create the loan if it is + // deep frozen. + if (auto const ret = checkDeepFrozen(ctx.view, brokerPseudo, asset)) + { + JLOG(ctx.j.warn()) << "Broker pseudo-account is frozen."; + return ret; + } + + // borrower is eventually going to have to pay back the loan, so it can't be + // frozen now. It is also going to receive funds, so it can't be deep + // frozen, but being frozen is a prerequisite for being deep frozen, so + // checking the one is sufficient. + if (auto const ret = checkFrozen(ctx.view, borrower, asset)) + { + JLOG(ctx.j.warn()) << "Borrower account is frozen."; + return ret; + } + // brokerOwner is going to receive funds if there's an origination fee, so + // it can't be deep frozen + if (auto const ret = checkDeepFrozen(ctx.view, brokerOwner, asset)) + { + JLOG(ctx.j.warn()) << "Broker owner account is frozen."; + return ret; + } + + return tesSUCCESS; +} + +TER +LoanSet::doApply() +{ + auto const& tx = ctx_.tx; + auto& view = ctx_.view(); + + auto const brokerID = tx[sfLoanBrokerID]; + + auto const brokerSle = view.peek(keylet::loanbroker(brokerID)); + if (!brokerSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const brokerOwner = brokerSle->at(sfOwner); + auto const brokerOwnerSle = view.peek(keylet::account(brokerOwner)); + if (!brokerOwnerSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + + auto const vaultSle = view.peek(keylet ::vault(brokerSle->at(sfVaultID))); + if (!vaultSle) + return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const vaultPseudo = vaultSle->at(sfAccount); + Asset const vaultAsset = vaultSle->at(sfAsset); + + auto const counterparty = tx[~sfCounterparty].value_or(brokerOwner); + auto const borrower = counterparty == brokerOwner ? account_ : counterparty; + auto const borrowerSle = view.peek(keylet::account(borrower)); + if (!borrowerSle) + { + return tefBAD_LEDGER; // LCOV_EXCL_LINE + } + + auto const brokerPseudo = brokerSle->at(sfAccount); + auto const brokerPseudoSle = view.peek(keylet::account(brokerPseudo)); + if (!brokerPseudoSle) + { + return tefBAD_LEDGER; // LCOV_EXCL_LINE + } + auto const principalRequested = tx[sfPrincipalRequested]; + + auto vaultAvailableProxy = vaultSle->at(sfAssetsAvailable); + auto vaultTotalProxy = vaultSle->at(sfAssetsTotal); + auto const vaultScale = getVaultScale(vaultSle); + if (vaultAvailableProxy < principalRequested) + { + JLOG(j_.warn()) + << "Insufficient assets available in the Vault to fund the loan."; + return tecINSUFFICIENT_FUNDS; + } + + TenthBips32 const interestRate{tx[~sfInterestRate].value_or(0)}; + + auto const paymentInterval = + tx[~sfPaymentInterval].value_or(defaultPaymentInterval); + auto const paymentTotal = tx[~sfPaymentTotal].value_or(defaultPaymentTotal); + + auto const properties = computeLoanProperties( + vaultAsset, + principalRequested, + interestRate, + paymentInterval, + paymentTotal, + TenthBips16{brokerSle->at(sfManagementFeeRate)}, + vaultScale); + + // Check that relevant values won't lose precision. This is mostly only + // relevant for IOU assets. + { + for (auto const& field : getValueFields()) + { + if (auto const value = tx[field]; + value && !isRounded(vaultAsset, *value, properties.loanScale)) + { + JLOG(j_.warn()) + << field.f->getName() << " (" << *value + << ") has too much precision. Total loan value is " + << properties.totalValueOutstanding << " with a scale of " + << properties.loanScale; + return tecPRECISION_LOSS; + } + } + } + + if (auto const ret = checkLoanGuards( + vaultAsset, + principalRequested, + interestRate != beast::zero, + paymentTotal, + properties, + j_)) + return ret; + + // Check that the other computed values are valid + if (properties.managementFeeOwedToBroker < 0 || + properties.totalValueOutstanding <= 0 || + properties.periodicPayment <= 0) + { + // LCOV_EXCL_START + JLOG(j_.warn()) + << "Computed loan properties are invalid. Does not compute."; + return tecINTERNAL; + // LCOV_EXCL_STOP + } + + LoanState const state = constructLoanState( + properties.totalValueOutstanding, + principalRequested, + properties.managementFeeOwedToBroker); + + auto const originationFee = tx[~sfLoanOriginationFee].value_or(Number{}); + + auto const loanAssetsToBorrower = principalRequested - originationFee; + + auto const newDebtDelta = principalRequested + state.interestDue; + auto const newDebtTotal = brokerSle->at(sfDebtTotal) + newDebtDelta; + if (auto const debtMaximum = brokerSle->at(sfDebtMaximum); + debtMaximum != 0 && debtMaximum < newDebtTotal) + { + JLOG(j_.warn()) + << "Loan would exceed the maximum debt limit of the LoanBroker."; + return tecLIMIT_EXCEEDED; + } + TenthBips32 const coverRateMinimum{brokerSle->at(sfCoverRateMinimum)}; + { + // Round the minimum required cover up to be conservative. This ensures + // CoverAvailable never drops below the theoretical minimum, protecting + // the broker's solvency. + NumberRoundModeGuard mg(Number::upward); + if (brokerSle->at(sfCoverAvailable) < + tenthBipsOfValue(newDebtTotal, coverRateMinimum)) + { + JLOG(j_.warn()) + << "Insufficient first-loss capital to cover the loan."; + return tecINSUFFICIENT_FUNDS; + } + } + + adjustOwnerCount(view, borrowerSle, 1, j_); + { + auto const ownerCount = borrowerSle->at(sfOwnerCount); + auto const balance = account_ == borrower + ? mPriorBalance + : borrowerSle->at(sfBalance).value().xrp(); + if (balance < view.fees().accountReserve(ownerCount)) + return tecINSUFFICIENT_RESERVE; + } + + // Account for the origination fee using two payments + // + // 1. Transfer loanAssetsAvailable (principalRequested - originationFee) + // from vault pseudo-account to the borrower. + // Create a holding for the borrower if one does not already exist. + + XRPL_ASSERT_PARTS( + borrower == account_ || borrower == counterparty, + "ripple::LoanSet::doApply", + "borrower signed transaction"); + if (auto const ter = addEmptyHolding( + view, + borrower, + borrowerSle->at(sfBalance).value().xrp(), + vaultAsset, + j_); + ter && ter != tecDUPLICATE) + // ignore tecDUPLICATE. That means the holding already exists, and + // is fine here + return ter; + + if (auto const ter = + requireAuth(view, vaultAsset, borrower, AuthType::StrongAuth)) + return ter; + + // 2. Transfer originationFee, if any, from vault pseudo-account to + // LoanBroker owner. + if (originationFee != beast::zero) + { + // Create the holding if it doesn't already exist (necessary for MPTs). + // The owner may have deleted their MPT / line at some point. + XRPL_ASSERT_PARTS( + brokerOwner == account_ || brokerOwner == counterparty, + "ripple::LoanSet::doApply", + "broker owner signed transaction"); + + if (auto const ter = addEmptyHolding( + view, + brokerOwner, + brokerOwnerSle->at(sfBalance).value().xrp(), + vaultAsset, + j_); + ter && ter != tecDUPLICATE) + // ignore tecDUPLICATE. That means the holding already exists, + // and is fine here + return ter; + + if (auto const ter = requireAuth( + view, vaultAsset, brokerOwner, AuthType::StrongAuth)) + return ter; + } + + if (auto const ter = accountSendMulti( + view, + vaultPseudo, + vaultAsset, + {{borrower, loanAssetsToBorrower}, {brokerOwner, originationFee}}, + j_, + WaiveTransferFee::Yes)) + return ter; + + // Get shortcuts to the loan property values + auto const startDate = getStartDate(view); + auto loanSequenceProxy = brokerSle->at(sfLoanSequence); + + // Create the loan + auto loan = + std::make_shared(keylet::loan(brokerID, *loanSequenceProxy)); + + // Prevent copy/paste errors + auto setLoanField = + [&loan, &tx](auto const& field, std::uint32_t const defValue = 0) { + // at() is smart enough to unseat a default field set to the default + // value + loan->at(field) = tx[field].value_or(defValue); + }; + + // Set required and fixed tx fields + loan->at(sfLoanScale) = properties.loanScale; + loan->at(sfStartDate) = startDate; + loan->at(sfPaymentInterval) = paymentInterval; + loan->at(sfLoanSequence) = *loanSequenceProxy; + loan->at(sfLoanBrokerID) = brokerID; + loan->at(sfBorrower) = borrower; + // Set all other transaction fields directly from the transaction + if (tx.isFlag(tfLoanOverpayment)) + loan->setFlag(lsfLoanOverpayment); + setLoanField(~sfLoanOriginationFee); + setLoanField(~sfLoanServiceFee); + setLoanField(~sfLatePaymentFee); + setLoanField(~sfClosePaymentFee); + setLoanField(~sfOverpaymentFee); + setLoanField(~sfInterestRate); + setLoanField(~sfLateInterestRate); + setLoanField(~sfCloseInterestRate); + setLoanField(~sfOverpaymentInterestRate); + setLoanField(~sfGracePeriod, defaultGracePeriod); + // Set dynamic / computed fields to their initial values + loan->at(sfPrincipalOutstanding) = principalRequested; + loan->at(sfPeriodicPayment) = properties.periodicPayment; + loan->at(sfTotalValueOutstanding) = properties.totalValueOutstanding; + loan->at(sfManagementFeeOutstanding) = properties.managementFeeOwedToBroker; + loan->at(sfPreviousPaymentDate) = 0; + loan->at(sfNextPaymentDueDate) = startDate + paymentInterval; + loan->at(sfPaymentRemaining) = paymentTotal; + view.insert(loan); + + // Update the balances in the vault + vaultAvailableProxy -= principalRequested; + vaultTotalProxy += state.interestDue; + XRPL_ASSERT_PARTS( + *vaultAvailableProxy <= *vaultTotalProxy, + "ripple::LoanSet::doApply", + "assets available must not be greater than assets outstanding"); + view.update(vaultSle); + + // Update the balances in the loan broker + adjustImpreciseNumber( + brokerSle->at(sfDebtTotal), newDebtDelta, vaultAsset, vaultScale); + // The broker's owner count is solely for the number of outstanding loans, + // and is distinct from the broker's pseudo-account's owner count + adjustOwnerCount(view, brokerSle, 1, j_); + loanSequenceProxy += 1; + // The sequence should be extremely unlikely to roll over, but fail if it + // does + if (loanSequenceProxy == 0) + return tecMAX_SEQUENCE_REACHED; + view.update(brokerSle); + + // Put the loan into the pseudo-account's directory + if (auto const ter = dirLink(view, brokerPseudo, loan, sfLoanBrokerNode)) + return ter; + // Borrower is the owner of the loan + if (auto const ter = dirLink(view, borrower, loan, sfOwnerNode)) + return ter; + + return tesSUCCESS; +} + +//------------------------------------------------------------------------------ + +} // namespace ripple diff --git a/src/xrpld/app/tx/detail/LoanSet.h b/src/xrpld/app/tx/detail/LoanSet.h new file mode 100644 index 0000000000..91f3960891 --- /dev/null +++ b/src/xrpld/app/tx/detail/LoanSet.h @@ -0,0 +1,59 @@ +#ifndef XRPL_TX_LOANSET_H_INCLUDED +#define XRPL_TX_LOANSET_H_INCLUDED + +#include +#include + +namespace ripple { + +class LoanSet : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit LoanSet(ApplyContext& ctx) : Transactor(ctx) + { + } + + static bool + checkExtraFeatures(PreflightContext const& ctx); + + static std::uint32_t + getFlagsMask(PreflightContext const& ctx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static NotTEC + checkSign(PreclaimContext const& ctx); + + static XRPAmount + calculateBaseFee(ReadView const& view, STTx const& tx); + + static std::vector> const& + getValueFields(); + + static TER + preclaim(PreclaimContext const& ctx); + + TER + doApply() override; + +public: + static std::uint32_t constexpr minPaymentTotal = 1; + static std::uint32_t constexpr defaultPaymentTotal = 1; + static_assert(defaultPaymentTotal >= minPaymentTotal); + + static std::uint32_t constexpr minPaymentInterval = 60; + static std::uint32_t constexpr defaultPaymentInterval = 60; + static_assert(defaultPaymentInterval >= minPaymentInterval); + + static std::uint32_t constexpr defaultGracePeriod = 60; + static_assert(defaultGracePeriod >= minPaymentInterval); +}; + +//------------------------------------------------------------------------------ + +} // namespace ripple + +#endif diff --git a/src/xrpld/app/tx/detail/MPTokenAuthorize.cpp b/src/xrpld/app/tx/detail/MPTokenAuthorize.cpp index 858fd6d0d6..b6eaacb372 100644 --- a/src/xrpld/app/tx/detail/MPTokenAuthorize.cpp +++ b/src/xrpld/app/tx/detail/MPTokenAuthorize.cpp @@ -94,7 +94,8 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) return tesSUCCESS; } - if (!ctx.view.exists(keylet::account(*holderID))) + auto const sleHolder = ctx.view.read(keylet::account(*holderID)); + if (!sleHolder) return tecNO_DST; auto const sleMptIssuance = @@ -124,6 +125,12 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) keylet::mptoken(ctx.tx[sfMPTokenIssuanceID], *holderID))) return tecOBJECT_NOT_FOUND; + // Can't unauthorize the pseudo-accounts because they are implicitly + // always authorized. No need to amendment gate since Vault and LoanBroker + // can only be created if the Vault amendment is enabled. + if (isPseudoAccount(ctx.view, *holderID, {&sfVaultID, &sfLoanBrokerID})) + return tecNO_PERMISSION; + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/SetTrust.cpp b/src/xrpld/app/tx/detail/SetTrust.cpp index 37ecdf2386..4e8f20f3ae 100644 --- a/src/xrpld/app/tx/detail/SetTrust.cpp +++ b/src/xrpld/app/tx/detail/SetTrust.cpp @@ -251,7 +251,9 @@ SetTrust::preclaim(PreclaimContext const& ctx) else return tecINTERNAL; // LCOV_EXCL_LINE } - else if (sleDst->isFieldPresent(sfVaultID)) + else if ( + sleDst->isFieldPresent(sfVaultID) || + sleDst->isFieldPresent(sfLoanBrokerID)) { if (!ctx.view.exists(keylet::line(id, uDstAccountID, currency))) return tecNO_PERMISSION; diff --git a/src/xrpld/app/tx/detail/Transactor.cpp b/src/xrpld/app/tx/detail/Transactor.cpp index 9d84abe12e..2ddef72c39 100644 --- a/src/xrpld/app/tx/detail/Transactor.cpp +++ b/src/xrpld/app/tx/detail/Transactor.cpp @@ -204,13 +204,24 @@ Transactor::preflight2(PreflightContext const& ctx) // regardless of success or failure return *ret; + // Skip signature check on batch inner transactions + if (ctx.tx.isFlag(tfInnerBatchTxn) && !ctx.rules.enabled(featureBatch)) + return tesSUCCESS; + // Do not add any checks after this point that are relevant for + // batch inner transactions. They will be skipped. + auto const sigValid = checkValidity( ctx.app.getHashRouter(), ctx.tx, ctx.rules, ctx.app.config()); if (sigValid.first == Validity::SigBad) - { + { // LCOV_EXCL_START JLOG(ctx.j.debug()) << "preflight2: bad signature. " << sigValid.second; - return temINVALID; // LCOV_EXCL_LINE + return temINVALID; + // LCOV_EXCL_STOP } + + // Do not add any checks after this point that are relevant for + // batch inner transactions. They will be skipped. + return tesSUCCESS; } @@ -642,13 +653,25 @@ NotTEC Transactor::checkSign( ReadView const& view, ApplyFlags flags, + std::optional const& parentBatchId, AccountID const& idAccount, STObject const& sigObject, beast::Journal const j) { + { + auto const sle = view.read(keylet::account(idAccount)); + + if (view.rules().enabled(featureLendingProtocol) && + isPseudoAccount(sle)) + // Pseudo-accounts can't sign transactions. This check is gated on + // the Lending Protocol amendment because that's the project it was + // added under, and it doesn't justify another amendment + return tefBAD_AUTH; + } + auto const pkSigner = sigObject.getFieldVL(sfSigningPubKey); // Ignore signature check on batch inner transactions - if (sigObject.isFlag(tfInnerBatchTxn) && view.rules().enabled(featureBatch)) + if (parentBatchId && view.rules().enabled(featureBatch)) { // Defensive Check: These values are also checked in Batch::preflight if (sigObject.isFieldPresent(sfTxnSignature) || !pkSigner.empty() || @@ -701,7 +724,8 @@ Transactor::checkSign(PreclaimContext const& ctx) auto const idAccount = ctx.tx.isFieldPresent(sfDelegate) ? ctx.tx.getAccountID(sfDelegate) : ctx.tx.getAccountID(sfAccount); - return checkSign(ctx.view, ctx.flags, idAccount, ctx.tx, ctx.j); + return checkSign( + ctx.view, ctx.flags, ctx.parentBatchId, idAccount, ctx.tx, ctx.j); } NotTEC diff --git a/src/xrpld/app/tx/detail/Transactor.h b/src/xrpld/app/tx/detail/Transactor.h index 2195ef0a85..ea3479ee6f 100644 --- a/src/xrpld/app/tx/detail/Transactor.h +++ b/src/xrpld/app/tx/detail/Transactor.h @@ -266,6 +266,7 @@ protected: checkSign( ReadView const& view, ApplyFlags flags, + std::optional const& parentBatchId, AccountID const& idAccount, STObject const& sigObject, beast::Journal const j); @@ -287,14 +288,26 @@ protected: template static bool - validNumericRange(std::optional value, T max, T min = {}); + validNumericRange(std::optional value, T max, T min = T{}); template static bool validNumericRange( std::optional value, unit::ValueUnit max, - unit::ValueUnit min = {}); + unit::ValueUnit min = unit::ValueUnit{}); + + /// Minimum will usually be zero. + template + static bool + validNumericMinimum(std::optional value, T min = T{}); + + /// Minimum will usually be zero. + template + static bool + validNumericMinimum( + std::optional value, + unit::ValueUnit min = unit::ValueUnit{}); private: std::pair @@ -421,6 +434,24 @@ Transactor::validNumericRange( return validNumericRange(value, max.value(), min.value()); } +template +bool +Transactor::validNumericMinimum(std::optional value, T min) +{ + if (!value) + return true; + return value >= min; +} + +template +bool +Transactor::validNumericMinimum( + std::optional value, + unit::ValueUnit min) +{ + return validNumericMinimum(value, min.value()); +} + } // namespace ripple #endif diff --git a/src/xrpld/app/tx/detail/VaultCreate.cpp b/src/xrpld/app/tx/detail/VaultCreate.cpp index 393faa35f8..d8a2e7bc3b 100644 --- a/src/xrpld/app/tx/detail/VaultCreate.cpp +++ b/src/xrpld/app/tx/detail/VaultCreate.cpp @@ -22,8 +22,11 @@ VaultCreate::checkExtraFeatures(PreflightContext const& ctx) if (!ctx.rules.enabled(featureMPTokensV1)) return false; - return !ctx.tx.isFieldPresent(sfDomainID) || - ctx.rules.enabled(featurePermissionedDomains); + if (ctx.tx.isFieldPresent(sfDomainID) && + !ctx.rules.enabled(featurePermissionedDomains)) + return false; + + return true; } std::uint32_t diff --git a/src/xrpld/app/tx/detail/VaultDeposit.cpp b/src/xrpld/app/tx/detail/VaultDeposit.cpp index 3e5ae741e3..aeaf890126 100644 --- a/src/xrpld/app/tx/detail/VaultDeposit.cpp +++ b/src/xrpld/app/tx/detail/VaultDeposit.cpp @@ -36,41 +36,19 @@ VaultDeposit::preclaim(PreclaimContext const& ctx) if (!vault) return tecNO_ENTRY; - auto const account = ctx.tx[sfAccount]; + auto const& account = ctx.tx[sfAccount]; auto const assets = ctx.tx[sfAmount]; auto const vaultAsset = vault->at(sfAsset); if (assets.asset() != vaultAsset) return tecWRONG_ASSET; - if (vaultAsset.native()) - ; // No special checks for XRP - else if (vaultAsset.holds()) + auto const& vaultAccount = vault->at(sfAccount); + if (auto ter = canTransfer(ctx.view, vaultAsset, account, vaultAccount); + !isTesSuccess(ter)) { - auto mptID = vaultAsset.get().getMptID(); - auto issuance = ctx.view.read(keylet::mptIssuance(mptID)); - if (!issuance) - return tecOBJECT_NOT_FOUND; - if (!issuance->isFlag(lsfMPTCanTransfer)) - { - // LCOV_EXCL_START - JLOG(ctx.j.error()) - << "VaultDeposit: vault assets are non-transferable."; - return tecNO_AUTH; - // LCOV_EXCL_STOP - } - } - else if (vaultAsset.holds()) - { - auto const issuer = - ctx.view.read(keylet::account(vaultAsset.getIssuer())); - if (!issuer) - { - // LCOV_EXCL_START - JLOG(ctx.j.error()) - << "VaultDeposit: missing issuer of vault assets."; - return tefINTERNAL; - // LCOV_EXCL_STOP - } + JLOG(ctx.j.debug()) + << "VaultDeposit: vault assets are non-transferable."; + return ter; } auto const mptIssuanceID = vault->at(sfShareMPTID); diff --git a/src/xrpld/app/tx/detail/VaultSet.cpp b/src/xrpld/app/tx/detail/VaultSet.cpp index 38ab6296ef..97522dad12 100644 --- a/src/xrpld/app/tx/detail/VaultSet.cpp +++ b/src/xrpld/app/tx/detail/VaultSet.cpp @@ -14,8 +14,11 @@ namespace ripple { bool VaultSet::checkExtraFeatures(PreflightContext const& ctx) { - return !ctx.tx.isFieldPresent(sfDomainID) || - ctx.rules.enabled(featurePermissionedDomains); + if (ctx.tx.isFieldPresent(sfDomainID) && + !ctx.rules.enabled(featurePermissionedDomains)) + return false; + + return true; } NotTEC diff --git a/src/xrpld/app/tx/detail/VaultWithdraw.cpp b/src/xrpld/app/tx/detail/VaultWithdraw.cpp index 7777f2257f..a3bef88d49 100644 --- a/src/xrpld/app/tx/detail/VaultWithdraw.cpp +++ b/src/xrpld/app/tx/detail/VaultWithdraw.cpp @@ -23,13 +23,10 @@ VaultWithdraw::preflight(PreflightContext const& ctx) if (ctx.tx[sfAmount] <= beast::zero) return temBAD_AMOUNT; - if (auto const destination = ctx.tx[~sfDestination]; - destination.has_value()) + if (auto const destination = ctx.tx[~sfDestination]) { if (*destination == beast::zero) { - JLOG(ctx.j.debug()) - << "VaultWithdraw: zero/empty destination account."; return temMALFORMED; } } @@ -50,35 +47,15 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx) if (assets.asset() != vaultAsset && assets.asset() != vaultShare) return tecWRONG_ASSET; - if (vaultAsset.native()) - ; // No special checks for XRP - else if (vaultAsset.holds()) + auto const& vaultAccount = vault->at(sfAccount); + auto const& account = ctx.tx[sfAccount]; + auto const& dstAcct = ctx.tx[~sfDestination].value_or(account); + if (auto ter = canTransfer(ctx.view, vaultAsset, vaultAccount, dstAcct); + !isTesSuccess(ter)) { - auto mptID = vaultAsset.get().getMptID(); - auto issuance = ctx.view.read(keylet::mptIssuance(mptID)); - if (!issuance) - return tecOBJECT_NOT_FOUND; - if (!issuance->isFlag(lsfMPTCanTransfer)) - { - // LCOV_EXCL_START - JLOG(ctx.j.error()) - << "VaultWithdraw: vault assets are non-transferable."; - return tecNO_AUTH; - // LCOV_EXCL_STOP - } - } - else if (vaultAsset.holds()) - { - auto const issuer = - ctx.view.read(keylet::account(vaultAsset.getIssuer())); - if (!issuer) - { - // LCOV_EXCL_START - JLOG(ctx.j.error()) - << "VaultWithdraw: missing issuer of vault assets."; - return tefINTERNAL; - // LCOV_EXCL_STOP - } + JLOG(ctx.j.debug()) + << "VaultWithdraw: vault assets are non-transferable."; + return ter; } // Enforce valid withdrawal policy @@ -90,23 +67,8 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } - auto const account = ctx.tx[sfAccount]; - auto const dstAcct = ctx.tx[~sfDestination].value_or(account); - auto const sleDst = ctx.view.read(keylet::account(dstAcct)); - if (sleDst == nullptr) - return account == dstAcct ? tecINTERNAL : tecNO_DST; - - if (sleDst->isFlag(lsfRequireDestTag) && - !ctx.tx.isFieldPresent(sfDestinationTag)) - return tecDST_TAG_NEEDED; // Cannot send without a tag - - // Withdrawal to a 3rd party destination account is essentially a transfer, - // via shares in the vault. Enforce all the usual asset transfer checks. - if (account != dstAcct && sleDst->isFlag(lsfDepositAuth)) - { - if (!ctx.view.exists(keylet::depositPreauth(dstAcct, account))) - return tecNO_PERMISSION; - } + if (auto const ret = canWithdraw(ctx.view, ctx.tx)) + return ret; // If sending to Account (i.e. not a transfer), we will also create (only // if authorized) a trust line or MPToken as needed, in doApply(). @@ -276,43 +238,16 @@ VaultWithdraw::doApply() } auto const dstAcct = ctx_.tx[~sfDestination].value_or(account_); - if (!vaultAsset.native() && // - dstAcct != vaultAsset.getIssuer() && // - dstAcct == account_) - { - if (auto const ter = addEmptyHolding( - view(), account_, mPriorBalance, vaultAsset, j_); - !isTesSuccess(ter) && ter != tecDUPLICATE) - return ter; - } - // Transfer assets from vault to depositor or destination account. - if (auto const ter = accountSend( - view(), - vaultAccount, - dstAcct, - assetsWithdrawn, - j_, - WaiveTransferFee::Yes); - !isTesSuccess(ter)) - return ter; - - // Sanity check - if (accountHolds( - view(), - vaultAccount, - assetsWithdrawn.asset(), - FreezeHandling::fhIGNORE_FREEZE, - AuthHandling::ahIGNORE_AUTH, - j_) < beast::zero) - { - // LCOV_EXCL_START - JLOG(j_.error()) << "VaultWithdraw: negative balance of vault assets."; - return tefINTERNAL; - // LCOV_EXCL_STOP - } - - return tesSUCCESS; + return doWithdraw( + view(), + ctx_.tx, + account_, + dstAcct, + vaultAccount, + mPriorBalance, + assetsWithdrawn, + j_); } } // namespace ripple diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index b85536c6f1..0a973a9218 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -1365,8 +1365,23 @@ PeerImp::handleTransaction( // Charge strongly for attempting to relay a txn with tfInnerBatchTxn // LCOV_EXCL_START - if (stx->isFlag(tfInnerBatchTxn) && - getCurrentTransactionRules()->enabled(featureBatch)) + /* + There is no need to check whether the featureBatch amendment is + enabled. + + * If the `tfInnerBatchTxn` flag is set, and the amendment is + enabled, then it's an invalid transaction because inner batch + transactions should not be relayed. + * If the `tfInnerBatchTxn` flag is set, and the amendment is *not* + enabled, then the transaction is malformed because it's using an + "unknown" flag. There's no need to waste the resources to send it + to the transaction engine. + + We don't normally check transaction validity at this level, but + since we _need_ to check it when the amendment is enabled, we may as + well drop it if the flag is set regardless. + */ + if (stx->isFlag(tfInnerBatchTxn)) { JLOG(p_journal_.warn()) << "Ignoring Network relayed Tx containing " "tfInnerBatchTxn (handleTransaction)."; @@ -2924,8 +2939,23 @@ PeerImp::checkTransaction( { // charge strongly for relaying batch txns // LCOV_EXCL_START - if (stx->isFlag(tfInnerBatchTxn) && - getCurrentTransactionRules()->enabled(featureBatch)) + /* + There is no need to check whether the featureBatch amendment is + enabled. + + * If the `tfInnerBatchTxn` flag is set, and the amendment is + enabled, then it's an invalid transaction because inner batch + transactions should not be relayed. + * If the `tfInnerBatchTxn` flag is set, and the amendment is *not* + enabled, then the transaction is malformed because it's using an + "unknown" flag. There's no need to waste the resources to send it + to the transaction engine. + + We don't normally check transaction validity at this level, but + since we _need_ to check it when the amendment is enabled, we may as + well drop it if the flag is set regardless. + */ + if (stx->isFlag(tfInnerBatchTxn)) { JLOG(p_journal_.warn()) << "Ignoring Network relayed Tx containing " "tfInnerBatchTxn (checkSignature)."; diff --git a/src/xrpld/rpc/detail/TransactionSign.cpp b/src/xrpld/rpc/detail/TransactionSign.cpp index 5e9e2d9cc4..8ca58d671e 100644 --- a/src/xrpld/rpc/detail/TransactionSign.cpp +++ b/src/xrpld/rpc/detail/TransactionSign.cpp @@ -1078,7 +1078,11 @@ checkMultiSignFields(Json::Value const& jvRequest) if (!tx_json.isMember(sfSigningPubKey.getJsonName())) return RPC::missing_field_error("tx_json.SigningPubKey"); - if (!tx_json[sfSigningPubKey.getJsonName()].asString().empty()) + // Multi-signing into a signature_target object field is fine, + // because it means the signature is not for the transaction + // Account. + if (!jvRequest.isMember(jss::signature_target) && + !tx_json[sfSigningPubKey.getJsonName()].asString().empty()) return RPC::make_error( rpcINVALID_PARAMS, "When multi-signing 'tx_json.SigningPubKey' must be empty."); diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index 7365ccc6ef..e9f95d450b 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -129,6 +129,28 @@ doAccountInfo(RPC::JsonContext& context) result[jss::account_flags] = std::move(acctFlags); + auto const pseudoFields = getPseudoAccountFields(); + for (auto const& pseudoField : pseudoFields) + { + if (sleAccepted->isFieldPresent(*pseudoField)) + { + std::string name = pseudoField->fieldName; + if (name.ends_with("ID")) + { + // Remove the ID suffix from the field name. + name = name.substr(0, name.size() - 2); + XRPL_ASSERT_PARTS( + !name.empty(), + "ripple::doAccountInfo", + "name is not empty"); + } + // ValidPseudoAccounts invariant guarantees that only one field + // can be set + result[jss::pseudo_account][jss::type] = name; + break; + } + } + // The document[https://xrpl.org/account_info.html#account_info] states // that signer_lists is a bool, however assigning any string value // works. Do not allow this. This check is for api Version 2 onwards diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index bf8a4a5b80..5a1dfb4ace 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -395,6 +395,46 @@ parseLedgerHashes(Json::Value const& params, Json::StaticString const fieldName) return parseObjectID(params, fieldName, "hex string"); } +static Expected +parseLoanBroker(Json::Value const& params, Json::StaticString const fieldName) +{ + if (!params.isObject()) + { + return parseObjectID(params, fieldName, "hex string"); + } + + auto const id = LedgerEntryHelpers::requiredAccountID( + params, jss::owner, "malformedOwner"); + if (!id) + return Unexpected(id.error()); + auto const seq = + LedgerEntryHelpers::requiredUInt32(params, jss::seq, "malformedSeq"); + if (!seq) + return Unexpected(seq.error()); + + return keylet::loanbroker(*id, *seq).key; +} + +static Expected +parseLoan(Json::Value const& params, Json::StaticString const fieldName) +{ + if (!params.isObject()) + { + return parseObjectID(params, fieldName, "hex string"); + } + + auto const id = LedgerEntryHelpers::requiredUInt256( + params, jss::loan_broker_id, "malformedOwner"); + if (!id) + return Unexpected(id.error()); + auto const seq = LedgerEntryHelpers::requiredUInt32( + params, jss::loan_seq, "malformedSeq"); + if (!seq) + return Unexpected(seq.error()); + + return keylet::loan(*id, *seq).key; +} + static Expected parseMPToken(Json::Value const& params, Json::StaticString const fieldName) { From 813bc4d9491b078bb950f8255f93b02f71320478 Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 4 Dec 2025 08:32:45 -0500 Subject: [PATCH 029/105] refactor: Replaces secp256k1 source by Conan package (#6089) This change substitutes the secp256k1 source code copy by the Conan recipe added in XRPLF/conan-center-index#24, which updates the version of the library to 0.7.0. --- .github/workflows/on-pr.yml | 2 +- BUILD.md | 2 + CMakeLists.txt | 10 +- conan.lock | 1 + conanfile.py | 4 + external/README.md | 1 - external/secp256k1/.cirrus.yml | 101 - external/secp256k1/.gitattributes | 2 - external/secp256k1/.gitignore | 67 - external/secp256k1/CHANGELOG.md | 174 - external/secp256k1/CMakeLists.txt | 405 - external/secp256k1/CMakePresets.json | 19 - external/secp256k1/CONTRIBUTING.md | 108 - external/secp256k1/COPYING | 19 - external/secp256k1/Makefile.am | 302 - external/secp256k1/README.md | 142 - external/secp256k1/SECURITY.md | 15 - external/secp256k1/autogen.sh | 3 - .../secp256k1/build-aux/m4/bitcoin_secp.m4 | 91 - external/secp256k1/ci/ci.sh | 149 - external/secp256k1/ci/linux-debian.Dockerfile | 79 - .../secp256k1/cmake/CheckArm32Assembly.cmake | 6 - .../cmake/CheckMemorySanitizer.cmake | 18 - .../cmake/CheckStringOptionValue.cmake | 10 - .../secp256k1/cmake/CheckX86_64Assembly.cmake | 14 - external/secp256k1/cmake/FindValgrind.cmake | 41 - .../cmake/GeneratePkgConfigFile.cmake | 8 - .../secp256k1/cmake/TryAppendCFlags.cmake | 24 - .../cmake/arm-linux-gnueabihf.toolchain.cmake | 3 - external/secp256k1/cmake/config.cmake.in | 5 - external/secp256k1/cmake/source_arm32.s | 9 - .../cmake/x86_64-w64-mingw32.toolchain.cmake | 3 - external/secp256k1/configure.ac | 517 - external/secp256k1/contrib/lax_der_parsing.c | 148 - external/secp256k1/contrib/lax_der_parsing.h | 97 - .../contrib/lax_der_privatekey_parsing.c | 112 - .../contrib/lax_der_privatekey_parsing.h | 95 - external/secp256k1/doc/ellswift.md | 483 - external/secp256k1/doc/musig.md | 54 - external/secp256k1/doc/release-process.md | 94 - .../secp256k1/doc/safegcd_implementation.md | 819 - external/secp256k1/examples/CMakeLists.txt | 31 - external/secp256k1/examples/EXAMPLES_COPYING | 121 - external/secp256k1/examples/ecdh.c | 120 - external/secp256k1/examples/ecdsa.c | 137 - external/secp256k1/examples/ellswift.c | 121 - external/secp256k1/examples/examples_util.h | 108 - external/secp256k1/examples/musig.c | 260 - external/secp256k1/examples/schnorr.c | 153 - external/secp256k1/include/secp256k1.h | 899 - external/secp256k1/include/secp256k1_ecdh.h | 63 - .../secp256k1/include/secp256k1_ellswift.h | 200 - .../secp256k1/include/secp256k1_extrakeys.h | 250 - external/secp256k1/include/secp256k1_musig.h | 588 - .../include/secp256k1_preallocated.h | 134 - .../secp256k1/include/secp256k1_recovery.h | 113 - .../secp256k1/include/secp256k1_schnorrsig.h | 190 - external/secp256k1/libsecp256k1.pc.in | 12 - .../secp256k1/sage/gen_exhaustive_groups.sage | 156 - .../sage/gen_split_lambda_constants.sage | 114 - external/secp256k1/sage/group_prover.sage | 353 - .../sage/prove_group_implementations.sage | 285 - external/secp256k1/sage/secp256k1_params.sage | 39 - .../secp256k1/sage/weierstrass_prover.sage | 275 - external/secp256k1/src/CMakeLists.txt | 176 - external/secp256k1/src/asm/field_10x26_arm.s | 916 - external/secp256k1/src/assumptions.h | 87 - external/secp256k1/src/bench.c | 279 - external/secp256k1/src/bench.h | 188 - external/secp256k1/src/bench_ecmult.c | 367 - external/secp256k1/src/bench_internal.c | 436 - external/secp256k1/src/checkmem.h | 102 - external/secp256k1/src/ctime_tests.c | 266 - external/secp256k1/src/ecdsa.h | 21 - external/secp256k1/src/ecdsa_impl.h | 304 - external/secp256k1/src/eckey.h | 25 - external/secp256k1/src/eckey_impl.h | 92 - external/secp256k1/src/ecmult.h | 61 - external/secp256k1/src/ecmult_compute_table.h | 16 - .../secp256k1/src/ecmult_compute_table_impl.h | 49 - external/secp256k1/src/ecmult_const.h | 38 - external/secp256k1/src/ecmult_const_impl.h | 399 - external/secp256k1/src/ecmult_gen.h | 143 - .../secp256k1/src/ecmult_gen_compute_table.h | 14 - .../src/ecmult_gen_compute_table_impl.h | 108 - external/secp256k1/src/ecmult_gen_impl.h | 341 - external/secp256k1/src/ecmult_impl.h | 853 - external/secp256k1/src/field.h | 350 - external/secp256k1/src/field_10x26.h | 57 - external/secp256k1/src/field_10x26_impl.h | 1232 -- external/secp256k1/src/field_5x52.h | 62 - external/secp256k1/src/field_5x52_impl.h | 522 - .../secp256k1/src/field_5x52_int128_impl.h | 274 - external/secp256k1/src/field_impl.h | 457 - external/secp256k1/src/group.h | 212 - external/secp256k1/src/group_impl.h | 974 - external/secp256k1/src/hash.h | 44 - external/secp256k1/src/hash_impl.h | 299 - external/secp256k1/src/hsort.h | 33 - external/secp256k1/src/hsort_impl.h | 125 - external/secp256k1/src/int128.h | 90 - external/secp256k1/src/int128_impl.h | 18 - external/secp256k1/src/int128_native.h | 19 - external/secp256k1/src/int128_native_impl.h | 94 - external/secp256k1/src/int128_struct.h | 14 - external/secp256k1/src/int128_struct_impl.h | 205 - external/secp256k1/src/modinv32.h | 43 - external/secp256k1/src/modinv32_impl.h | 725 - external/secp256k1/src/modinv64.h | 47 - external/secp256k1/src/modinv64_impl.h | 780 - .../src/modules/ecdh/Makefile.am.include | 4 - .../secp256k1/src/modules/ecdh/bench_impl.h | 57 - .../secp256k1/src/modules/ecdh/main_impl.h | 74 - .../secp256k1/src/modules/ecdh/tests_impl.h | 152 - .../src/modules/ellswift/Makefile.am.include | 5 - .../src/modules/ellswift/bench_impl.h | 106 - .../src/modules/ellswift/main_impl.h | 592 - .../modules/ellswift/tests_exhaustive_impl.h | 39 - .../src/modules/ellswift/tests_impl.h | 436 - .../src/modules/extrakeys/Makefile.am.include | 4 - .../src/modules/extrakeys/main_impl.h | 285 - .../modules/extrakeys/tests_exhaustive_impl.h | 68 - .../src/modules/extrakeys/tests_impl.h | 483 - .../src/modules/musig/Makefile.am.include | 8 - external/secp256k1/src/modules/musig/keyagg.h | 32 - .../secp256k1/src/modules/musig/keyagg_impl.h | 291 - .../secp256k1/src/modules/musig/main_impl.h | 12 - .../secp256k1/src/modules/musig/session.h | 24 - .../src/modules/musig/session_impl.h | 816 - .../secp256k1/src/modules/musig/tests_impl.h | 1143 -- .../secp256k1/src/modules/musig/vectors.h | 346 - .../src/modules/recovery/Makefile.am.include | 5 - .../src/modules/recovery/bench_impl.h | 62 - .../src/modules/recovery/main_impl.h | 159 - .../modules/recovery/tests_exhaustive_impl.h | 148 - .../src/modules/recovery/tests_impl.h | 338 - .../modules/schnorrsig/Makefile.am.include | 5 - .../src/modules/schnorrsig/bench_impl.h | 104 - .../src/modules/schnorrsig/main_impl.h | 269 - .../schnorrsig/tests_exhaustive_impl.h | 214 - .../src/modules/schnorrsig/tests_impl.h | 982 - external/secp256k1/src/precompute_ecmult.c | 90 - .../secp256k1/src/precompute_ecmult_gen.c | 100 - external/secp256k1/src/precomputed_ecmult.c | 16456 ---------------- external/secp256k1/src/precomputed_ecmult.h | 38 - .../secp256k1/src/precomputed_ecmult_gen.c | 1779 -- .../secp256k1/src/precomputed_ecmult_gen.h | 26 - external/secp256k1/src/scalar.h | 105 - external/secp256k1/src/scalar_4x64.h | 19 - external/secp256k1/src/scalar_4x64_impl.h | 1000 - external/secp256k1/src/scalar_8x32.h | 19 - external/secp256k1/src/scalar_8x32_impl.h | 816 - external/secp256k1/src/scalar_impl.h | 321 - external/secp256k1/src/scalar_low.h | 24 - external/secp256k1/src/scalar_low_impl.h | 206 - external/secp256k1/src/scratch.h | 44 - external/secp256k1/src/scratch_impl.h | 99 - external/secp256k1/src/secp256k1.c | 831 - external/secp256k1/src/selftest.h | 32 - external/secp256k1/src/testrand.h | 48 - external/secp256k1/src/testrand_impl.h | 167 - external/secp256k1/src/tests.c | 7841 -------- external/secp256k1/src/tests_exhaustive.c | 466 - external/secp256k1/src/testutil.h | 148 - external/secp256k1/src/util.h | 451 - .../src/wycheproof/WYCHEPROOF_COPYING | 212 - .../ecdsa_secp256k1_sha256_bitcoin_test.h | 1564 -- .../ecdsa_secp256k1_sha256_bitcoin_test.json | 6360 ------ external/secp256k1/tools/check-abi.sh | 74 - .../tools/test_vectors_musig2_generate.py | 656 - .../tools/tests_wycheproof_generate.py | 115 - include/xrpl/protocol/detail/secp256k1.h | 1 + src/libxrpl/protocol/PublicKey.cpp | 1 - src/libxrpl/protocol/SecretKey.cpp | 1 - 174 files changed, 11 insertions(+), 68297 deletions(-) delete mode 100644 external/secp256k1/.cirrus.yml delete mode 100644 external/secp256k1/.gitattributes delete mode 100644 external/secp256k1/.gitignore delete mode 100644 external/secp256k1/CHANGELOG.md delete mode 100644 external/secp256k1/CMakeLists.txt delete mode 100644 external/secp256k1/CMakePresets.json delete mode 100644 external/secp256k1/CONTRIBUTING.md delete mode 100644 external/secp256k1/COPYING delete mode 100644 external/secp256k1/Makefile.am delete mode 100644 external/secp256k1/README.md delete mode 100644 external/secp256k1/SECURITY.md delete mode 100755 external/secp256k1/autogen.sh delete mode 100644 external/secp256k1/build-aux/m4/bitcoin_secp.m4 delete mode 100755 external/secp256k1/ci/ci.sh delete mode 100644 external/secp256k1/ci/linux-debian.Dockerfile delete mode 100644 external/secp256k1/cmake/CheckArm32Assembly.cmake delete mode 100644 external/secp256k1/cmake/CheckMemorySanitizer.cmake delete mode 100644 external/secp256k1/cmake/CheckStringOptionValue.cmake delete mode 100644 external/secp256k1/cmake/CheckX86_64Assembly.cmake delete mode 100644 external/secp256k1/cmake/FindValgrind.cmake delete mode 100644 external/secp256k1/cmake/GeneratePkgConfigFile.cmake delete mode 100644 external/secp256k1/cmake/TryAppendCFlags.cmake delete mode 100644 external/secp256k1/cmake/arm-linux-gnueabihf.toolchain.cmake delete mode 100644 external/secp256k1/cmake/config.cmake.in delete mode 100644 external/secp256k1/cmake/source_arm32.s delete mode 100644 external/secp256k1/cmake/x86_64-w64-mingw32.toolchain.cmake delete mode 100644 external/secp256k1/configure.ac delete mode 100644 external/secp256k1/contrib/lax_der_parsing.c delete mode 100644 external/secp256k1/contrib/lax_der_parsing.h delete mode 100644 external/secp256k1/contrib/lax_der_privatekey_parsing.c delete mode 100644 external/secp256k1/contrib/lax_der_privatekey_parsing.h delete mode 100644 external/secp256k1/doc/ellswift.md delete mode 100644 external/secp256k1/doc/musig.md delete mode 100644 external/secp256k1/doc/release-process.md delete mode 100644 external/secp256k1/doc/safegcd_implementation.md delete mode 100644 external/secp256k1/examples/CMakeLists.txt delete mode 100644 external/secp256k1/examples/EXAMPLES_COPYING delete mode 100644 external/secp256k1/examples/ecdh.c delete mode 100644 external/secp256k1/examples/ecdsa.c delete mode 100644 external/secp256k1/examples/ellswift.c delete mode 100644 external/secp256k1/examples/examples_util.h delete mode 100644 external/secp256k1/examples/musig.c delete mode 100644 external/secp256k1/examples/schnorr.c delete mode 100644 external/secp256k1/include/secp256k1.h delete mode 100644 external/secp256k1/include/secp256k1_ecdh.h delete mode 100644 external/secp256k1/include/secp256k1_ellswift.h delete mode 100644 external/secp256k1/include/secp256k1_extrakeys.h delete mode 100644 external/secp256k1/include/secp256k1_musig.h delete mode 100644 external/secp256k1/include/secp256k1_preallocated.h delete mode 100644 external/secp256k1/include/secp256k1_recovery.h delete mode 100644 external/secp256k1/include/secp256k1_schnorrsig.h delete mode 100644 external/secp256k1/libsecp256k1.pc.in delete mode 100644 external/secp256k1/sage/gen_exhaustive_groups.sage delete mode 100644 external/secp256k1/sage/gen_split_lambda_constants.sage delete mode 100644 external/secp256k1/sage/group_prover.sage delete mode 100644 external/secp256k1/sage/prove_group_implementations.sage delete mode 100644 external/secp256k1/sage/secp256k1_params.sage delete mode 100644 external/secp256k1/sage/weierstrass_prover.sage delete mode 100644 external/secp256k1/src/CMakeLists.txt delete mode 100644 external/secp256k1/src/asm/field_10x26_arm.s delete mode 100644 external/secp256k1/src/assumptions.h delete mode 100644 external/secp256k1/src/bench.c delete mode 100644 external/secp256k1/src/bench.h delete mode 100644 external/secp256k1/src/bench_ecmult.c delete mode 100644 external/secp256k1/src/bench_internal.c delete mode 100644 external/secp256k1/src/checkmem.h delete mode 100644 external/secp256k1/src/ctime_tests.c delete mode 100644 external/secp256k1/src/ecdsa.h delete mode 100644 external/secp256k1/src/ecdsa_impl.h delete mode 100644 external/secp256k1/src/eckey.h delete mode 100644 external/secp256k1/src/eckey_impl.h delete mode 100644 external/secp256k1/src/ecmult.h delete mode 100644 external/secp256k1/src/ecmult_compute_table.h delete mode 100644 external/secp256k1/src/ecmult_compute_table_impl.h delete mode 100644 external/secp256k1/src/ecmult_const.h delete mode 100644 external/secp256k1/src/ecmult_const_impl.h delete mode 100644 external/secp256k1/src/ecmult_gen.h delete mode 100644 external/secp256k1/src/ecmult_gen_compute_table.h delete mode 100644 external/secp256k1/src/ecmult_gen_compute_table_impl.h delete mode 100644 external/secp256k1/src/ecmult_gen_impl.h delete mode 100644 external/secp256k1/src/ecmult_impl.h delete mode 100644 external/secp256k1/src/field.h delete mode 100644 external/secp256k1/src/field_10x26.h delete mode 100644 external/secp256k1/src/field_10x26_impl.h delete mode 100644 external/secp256k1/src/field_5x52.h delete mode 100644 external/secp256k1/src/field_5x52_impl.h delete mode 100644 external/secp256k1/src/field_5x52_int128_impl.h delete mode 100644 external/secp256k1/src/field_impl.h delete mode 100644 external/secp256k1/src/group.h delete mode 100644 external/secp256k1/src/group_impl.h delete mode 100644 external/secp256k1/src/hash.h delete mode 100644 external/secp256k1/src/hash_impl.h delete mode 100644 external/secp256k1/src/hsort.h delete mode 100644 external/secp256k1/src/hsort_impl.h delete mode 100644 external/secp256k1/src/int128.h delete mode 100644 external/secp256k1/src/int128_impl.h delete mode 100644 external/secp256k1/src/int128_native.h delete mode 100644 external/secp256k1/src/int128_native_impl.h delete mode 100644 external/secp256k1/src/int128_struct.h delete mode 100644 external/secp256k1/src/int128_struct_impl.h delete mode 100644 external/secp256k1/src/modinv32.h delete mode 100644 external/secp256k1/src/modinv32_impl.h delete mode 100644 external/secp256k1/src/modinv64.h delete mode 100644 external/secp256k1/src/modinv64_impl.h delete mode 100644 external/secp256k1/src/modules/ecdh/Makefile.am.include delete mode 100644 external/secp256k1/src/modules/ecdh/bench_impl.h delete mode 100644 external/secp256k1/src/modules/ecdh/main_impl.h delete mode 100644 external/secp256k1/src/modules/ecdh/tests_impl.h delete mode 100644 external/secp256k1/src/modules/ellswift/Makefile.am.include delete mode 100644 external/secp256k1/src/modules/ellswift/bench_impl.h delete mode 100644 external/secp256k1/src/modules/ellswift/main_impl.h delete mode 100644 external/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h delete mode 100644 external/secp256k1/src/modules/ellswift/tests_impl.h delete mode 100644 external/secp256k1/src/modules/extrakeys/Makefile.am.include delete mode 100644 external/secp256k1/src/modules/extrakeys/main_impl.h delete mode 100644 external/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h delete mode 100644 external/secp256k1/src/modules/extrakeys/tests_impl.h delete mode 100644 external/secp256k1/src/modules/musig/Makefile.am.include delete mode 100644 external/secp256k1/src/modules/musig/keyagg.h delete mode 100644 external/secp256k1/src/modules/musig/keyagg_impl.h delete mode 100644 external/secp256k1/src/modules/musig/main_impl.h delete mode 100644 external/secp256k1/src/modules/musig/session.h delete mode 100644 external/secp256k1/src/modules/musig/session_impl.h delete mode 100644 external/secp256k1/src/modules/musig/tests_impl.h delete mode 100644 external/secp256k1/src/modules/musig/vectors.h delete mode 100644 external/secp256k1/src/modules/recovery/Makefile.am.include delete mode 100644 external/secp256k1/src/modules/recovery/bench_impl.h delete mode 100644 external/secp256k1/src/modules/recovery/main_impl.h delete mode 100644 external/secp256k1/src/modules/recovery/tests_exhaustive_impl.h delete mode 100644 external/secp256k1/src/modules/recovery/tests_impl.h delete mode 100644 external/secp256k1/src/modules/schnorrsig/Makefile.am.include delete mode 100644 external/secp256k1/src/modules/schnorrsig/bench_impl.h delete mode 100644 external/secp256k1/src/modules/schnorrsig/main_impl.h delete mode 100644 external/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h delete mode 100644 external/secp256k1/src/modules/schnorrsig/tests_impl.h delete mode 100644 external/secp256k1/src/precompute_ecmult.c delete mode 100644 external/secp256k1/src/precompute_ecmult_gen.c delete mode 100644 external/secp256k1/src/precomputed_ecmult.c delete mode 100644 external/secp256k1/src/precomputed_ecmult.h delete mode 100644 external/secp256k1/src/precomputed_ecmult_gen.c delete mode 100644 external/secp256k1/src/precomputed_ecmult_gen.h delete mode 100644 external/secp256k1/src/scalar.h delete mode 100644 external/secp256k1/src/scalar_4x64.h delete mode 100644 external/secp256k1/src/scalar_4x64_impl.h delete mode 100644 external/secp256k1/src/scalar_8x32.h delete mode 100644 external/secp256k1/src/scalar_8x32_impl.h delete mode 100644 external/secp256k1/src/scalar_impl.h delete mode 100644 external/secp256k1/src/scalar_low.h delete mode 100644 external/secp256k1/src/scalar_low_impl.h delete mode 100644 external/secp256k1/src/scratch.h delete mode 100644 external/secp256k1/src/scratch_impl.h delete mode 100644 external/secp256k1/src/secp256k1.c delete mode 100644 external/secp256k1/src/selftest.h delete mode 100644 external/secp256k1/src/testrand.h delete mode 100644 external/secp256k1/src/testrand_impl.h delete mode 100644 external/secp256k1/src/tests.c delete mode 100644 external/secp256k1/src/tests_exhaustive.c delete mode 100644 external/secp256k1/src/testutil.h delete mode 100644 external/secp256k1/src/util.h delete mode 100644 external/secp256k1/src/wycheproof/WYCHEPROOF_COPYING delete mode 100644 external/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h delete mode 100644 external/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json delete mode 100755 external/secp256k1/tools/check-abi.sh delete mode 100755 external/secp256k1/tools/test_vectors_musig2_generate.py delete mode 100755 external/secp256k1/tools/tests_wycheproof_generate.py diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index ff3d25812a..9204cef5e8 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -112,7 +112,7 @@ jobs: strategy: fail-fast: false matrix: - os: [linux, macos, windows] + os: [windows] with: os: ${{ matrix.os }} secrets: diff --git a/BUILD.md b/BUILD.md index 5d8eb9b064..a497db417a 100644 --- a/BUILD.md +++ b/BUILD.md @@ -146,11 +146,13 @@ git init git remote add origin git@github.com:XRPLF/conan-center-index.git git sparse-checkout init git sparse-checkout set recipes/ed25519 +git sparse-checkout add recipes/secp256k1 git sparse-checkout add recipes/snappy git sparse-checkout add recipes/soci git fetch origin master git checkout master conan export --version 2015.03 recipes/ed25519/all +conan export --version 0.7.0 recipes/secp256k1/all conan export --version 1.1.10 recipes/snappy/all conan export --version 4.0.3 recipes/soci/all rm -rf .git diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cfd627afb..ade9c2f995 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,14 +89,7 @@ find_package(OpenSSL 1.1.1 REQUIRED) set_target_properties(OpenSSL::SSL PROPERTIES INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2 ) -set(SECP256K1_INSTALL TRUE) -set(SECP256K1_BUILD_BENCHMARK FALSE) -set(SECP256K1_BUILD_TESTS FALSE) -set(SECP256K1_BUILD_EXHAUSTIVE_TESTS FALSE) -set(SECP256K1_BUILD_CTIME_TESTS FALSE) -set(SECP256K1_BUILD_EXAMPLES FALSE) -add_subdirectory(external/secp256k1) -add_library(secp256k1::secp256k1 ALIAS secp256k1) + add_subdirectory(external/antithesis-sdk) find_package(gRPC REQUIRED) find_package(lz4 REQUIRED) @@ -119,6 +112,7 @@ endif() find_package(date REQUIRED) find_package(ed25519 REQUIRED) find_package(nudb REQUIRED) +find_package(secp256k1 REQUIRED) find_package(xxHash REQUIRED) target_link_libraries(xrpl_libs INTERFACE diff --git a/conan.lock b/conan.lock index 2d76558fd2..d235e8d41a 100644 --- a/conan.lock +++ b/conan.lock @@ -6,6 +6,7 @@ "sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869", "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318", "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246", + "secp256k1/0.7.0#9210e4c655d0a665400378a663960d17%1764261276.764", "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1762797952.535", "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1764175362.029", "protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456", diff --git a/conanfile.py b/conanfile.py index ebc5af1446..2d3e090fa3 100644 --- a/conanfile.py +++ b/conanfile.py @@ -33,6 +33,7 @@ class Xrpl(ConanFile): "libarchive/3.8.1", "nudb/2.0.9", "openssl/3.5.4", + "secp256k1/0.7.0", "soci/4.0.3", "zlib/1.3.1", ] @@ -57,6 +58,7 @@ class Xrpl(ConanFile): "unity": False, "xrpld": False, "date/*:header_only": True, + "ed25519/*:shared": False, "grpc/*:shared": False, "grpc/*:secure": True, "libarchive/*:shared": False, @@ -85,6 +87,7 @@ class Xrpl(ConanFile): "rocksdb/*:with_jemalloc": False, "rocksdb/*:with_lz4": True, "rocksdb/*:with_snappy": True, + "secp256k1/*:shared": False, "snappy/*:shared": False, "soci/*:shared": False, "soci/*:with_sqlite3": True, @@ -197,6 +200,7 @@ class Xrpl(ConanFile): "openssl::crypto", "protobuf::libprotobuf", "soci::soci", + "secp256k1::secp256k1", "sqlite3::sqlite", "xxhash::xxhash", "zlib::zlib", diff --git a/external/README.md b/external/README.md index 9d720faf74..f6e9f77d2d 100644 --- a/external/README.md +++ b/external/README.md @@ -5,4 +5,3 @@ The subdirectories in this directory contain external libraries used by rippled. | Folder | Upstream | Description | | :--------------- | :------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | | `antithesis-sdk` | [Project](https://github.com/antithesishq/antithesis-sdk-cpp/) | [Antithesis](https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html) SDK for C++ | -| `secp256k1` | [Project](https://github.com/bitcoin-core/secp256k1) | ECDSA digital signatures using the **secp256k1** curve | diff --git a/external/secp256k1/.cirrus.yml b/external/secp256k1/.cirrus.yml deleted file mode 100644 index 81a4f04328..0000000000 --- a/external/secp256k1/.cirrus.yml +++ /dev/null @@ -1,101 +0,0 @@ -env: - ### cirrus config - CIRRUS_CLONE_DEPTH: 1 - ### compiler options - HOST: - WRAPPER_CMD: - # Specific warnings can be disabled with -Wno-error=foo. - # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual. - WERROR_CFLAGS: -Werror -pedantic-errors - MAKEFLAGS: -j4 - BUILD: check - ### secp256k1 config - ECMULTWINDOW: 15 - ECMULTGENKB: 22 - ASM: no - WIDEMUL: auto - WITH_VALGRIND: yes - EXTRAFLAGS: - ### secp256k1 modules - EXPERIMENTAL: no - ECDH: no - RECOVERY: no - EXTRAKEYS: no - SCHNORRSIG: no - MUSIG: no - ELLSWIFT: no - ### test options - SECP256K1_TEST_ITERS: 64 - BENCH: yes - SECP256K1_BENCH_ITERS: 2 - CTIMETESTS: yes - # Compile and run the tests - EXAMPLES: yes - -cat_logs_snippet: &CAT_LOGS - always: - cat_tests_log_script: - - cat tests.log || true - cat_noverify_tests_log_script: - - cat noverify_tests.log || true - cat_exhaustive_tests_log_script: - - cat exhaustive_tests.log || true - cat_ctime_tests_log_script: - - cat ctime_tests.log || true - cat_bench_log_script: - - cat bench.log || true - cat_config_log_script: - - cat config.log || true - cat_test_env_script: - - cat test_env.log || true - cat_ci_env_script: - - env - -linux_arm64_container_snippet: &LINUX_ARM64_CONTAINER - env_script: - - env | tee /tmp/env - build_script: - - DOCKER_BUILDKIT=1 docker build --file "ci/linux-debian.Dockerfile" --tag="ci_secp256k1_arm" - - docker image prune --force # Cleanup stale layers - test_script: - - docker run --rm --mount "type=bind,src=./,dst=/ci_secp256k1" --env-file /tmp/env --replace --name "ci_secp256k1_arm" "ci_secp256k1_arm" bash -c "cd /ci_secp256k1/ && ./ci/ci.sh" - -task: - name: "ARM64: Linux (Debian stable)" - persistent_worker: - labels: - type: arm64 - env: - ECDH: yes - RECOVERY: yes - EXTRAKEYS: yes - SCHNORRSIG: yes - MUSIG: yes - ELLSWIFT: yes - matrix: - # Currently only gcc-snapshot, the other compilers are tested on GHA with QEMU - - env: { CC: 'gcc-snapshot' } - << : *LINUX_ARM64_CONTAINER - << : *CAT_LOGS - -task: - name: "ARM64: Linux (Debian stable), Valgrind" - persistent_worker: - labels: - type: arm64 - env: - ECDH: yes - RECOVERY: yes - EXTRAKEYS: yes - SCHNORRSIG: yes - MUSIG: yes - ELLSWIFT: yes - WRAPPER_CMD: 'valgrind --error-exitcode=42' - SECP256K1_TEST_ITERS: 2 - matrix: - - env: { CC: 'gcc' } - - env: { CC: 'clang' } - - env: { CC: 'gcc-snapshot' } - - env: { CC: 'clang-snapshot' } - << : *LINUX_ARM64_CONTAINER - << : *CAT_LOGS diff --git a/external/secp256k1/.gitattributes b/external/secp256k1/.gitattributes deleted file mode 100644 index 30efb2244f..0000000000 --- a/external/secp256k1/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -src/precomputed_ecmult.c linguist-generated -src/precomputed_ecmult_gen.c linguist-generated diff --git a/external/secp256k1/.gitignore b/external/secp256k1/.gitignore deleted file mode 100644 index bffba8cb2c..0000000000 --- a/external/secp256k1/.gitignore +++ /dev/null @@ -1,67 +0,0 @@ -bench -bench_ecmult -bench_internal -noverify_tests -tests -exhaustive_tests -precompute_ecmult_gen -precompute_ecmult -ctime_tests -ecdh_example -ecdsa_example -schnorr_example -ellswift_example -musig_example -*.exe -*.so -*.a -*.csv -*.log -*.trs -*.sage.py - -Makefile -configure -.libs/ -Makefile.in -aclocal.m4 -autom4te.cache/ -config.log -config.status -conftest* -*.tar.gz -*.la -libtool -.deps/ -.dirstamp -*.lo -*.o -*~ - -coverage/ -coverage.html -coverage.*.html -*.gcda -*.gcno -*.gcov - -build-aux/ar-lib -build-aux/config.guess -build-aux/config.sub -build-aux/depcomp -build-aux/install-sh -build-aux/ltmain.sh -build-aux/m4/libtool.m4 -build-aux/m4/lt~obsolete.m4 -build-aux/m4/ltoptions.m4 -build-aux/m4/ltsugar.m4 -build-aux/m4/ltversion.m4 -build-aux/missing -build-aux/compile -build-aux/test-driver -libsecp256k1.pc - -### CMake -/CMakeUserPresets.json -# Default CMake build directory. -/build diff --git a/external/secp256k1/CHANGELOG.md b/external/secp256k1/CHANGELOG.md deleted file mode 100644 index ee447c0c1c..0000000000 --- a/external/secp256k1/CHANGELOG.md +++ /dev/null @@ -1,174 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [0.6.0] - 2024-11-04 - -#### Added - - New module `musig` implements the MuSig2 multisignature scheme according to the [BIP 327 specification](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki). See: - - Header file `include/secp256k1_musig.h` which defines the new API. - - Document `doc/musig.md` for further notes on API usage. - - Usage example `examples/musig.c`. - - New CMake variable `SECP256K1_APPEND_LDFLAGS` for appending linker flags to the build command. - -#### Changed - - API functions now use a significantly more robust method to clear secrets from the stack before returning. However, secret clearing remains a best-effort security measure and cannot guarantee complete removal. - - Any type `secp256k1_foo` can now be forward-declared using `typedef struct secp256k1_foo secp256k1_foo;` (or also `struct secp256k1_foo;` in C++). - - Organized CMake build artifacts into dedicated directories (`bin/` for executables, `lib/` for libraries) to improve build output structure and Windows shared library compatibility. - -#### Removed - - Removed the `secp256k1_scratch_space` struct and its associated functions `secp256k1_scratch_space_create` and `secp256k1_scratch_space_destroy` because the scratch space was unused in the API. - -#### ABI Compatibility -The symbols `secp256k1_scratch_space_create` and `secp256k1_scratch_space_destroy` were removed. -Otherwise, the library maintains backward compatibility with versions 0.3.x through 0.5.x. - -## [0.5.1] - 2024-08-01 - -#### Added - - Added usage example for an ElligatorSwift key exchange. - -#### Changed - - The default size of the precomputed table for signing was changed from 22 KiB to 86 KiB. The size can be changed with the configure option `--ecmult-gen-kb` (`SECP256K1_ECMULT_GEN_KB` for CMake). - - "auto" is no longer an accepted value for the `--with-ecmult-window` and `--with-ecmult-gen-kb` configure options (this also applies to `SECP256K1_ECMULT_WINDOW_SIZE` and `SECP256K1_ECMULT_GEN_KB` in CMake). To achieve the same configuration as previously provided by the "auto" value, omit setting the configure option explicitly. - -#### Fixed - - Fixed compilation when the extrakeys module is disabled. - -#### ABI Compatibility -The ABI is backward compatible with versions 0.5.0, 0.4.x and 0.3.x. - -## [0.5.0] - 2024-05-06 - -#### Added - - New function `secp256k1_ec_pubkey_sort` that sorts public keys using lexicographic (of compressed serialization) order. - -#### Changed - - The implementation of the point multiplication algorithm used for signing and public key generation was changed, resulting in improved performance for those operations. - - The related configure option `--ecmult-gen-precision` was replaced with `--ecmult-gen-kb` (`SECP256K1_ECMULT_GEN_KB` for CMake). - - This changes the supported precomputed table sizes for these operations. The new supported sizes are 2 KiB, 22 KiB, or 86 KiB (while the old supported sizes were 32 KiB, 64 KiB, or 512 KiB). - -#### ABI Compatibility -The ABI is backward compatible with versions 0.4.x and 0.3.x. - -## [0.4.1] - 2023-12-21 - -#### Changed - - The point multiplication algorithm used for ECDH operations (module `ecdh`) was replaced with a slightly faster one. - - Optional handwritten x86_64 assembly for field operations was removed because modern C compilers are able to output more efficient assembly. This change results in a significant speedup of some library functions when handwritten x86_64 assembly is enabled (`--with-asm=x86_64` in GNU Autotools, `-DSECP256K1_ASM=x86_64` in CMake), which is the default on x86_64. Benchmarks with GCC 10.5.0 show a 10% speedup for `secp256k1_ecdsa_verify` and `secp256k1_schnorrsig_verify`. - -#### ABI Compatibility -The ABI is backward compatible with versions 0.4.0 and 0.3.x. - -## [0.4.0] - 2023-09-04 - -#### Added - - New module `ellswift` implements ElligatorSwift encoding for public keys and x-only Diffie-Hellman key exchange for them. - ElligatorSwift permits representing secp256k1 public keys as 64-byte arrays which cannot be distinguished from uniformly random. See: - - Header file `include/secp256k1_ellswift.h` which defines the new API. - - Document `doc/ellswift.md` which explains the mathematical background of the scheme. - - The [paper](https://eprint.iacr.org/2022/759) on which the scheme is based. - - We now test the library with unreleased development snapshots of GCC and Clang. This gives us an early chance to catch miscompilations and constant-time issues introduced by the compiler (such as those that led to the previous two releases). - -#### Fixed - - Fixed symbol visibility in Windows DLL builds, where three internal library symbols were wrongly exported. - -#### Changed - - When consuming libsecp256k1 as a static library on Windows, the user must now define the `SECP256K1_STATIC` macro before including `secp256k1.h`. - -#### ABI Compatibility -This release is backward compatible with the ABI of 0.3.0, 0.3.1, and 0.3.2. Symbol visibility is now believed to be handled properly on supported platforms and is now considered to be part of the ABI. Please report any improperly exported symbols as a bug. - -## [0.3.2] - 2023-05-13 -We strongly recommend updating to 0.3.2 if you use or plan to use GCC >=13 to compile libsecp256k1. When in doubt, check the GCC version using `gcc -v`. - -#### Security - - Module `ecdh`: Fix "constant-timeness" issue with GCC 13.1 (and potentially future versions of GCC) that could leave applications using libsecp256k1's ECDH module vulnerable to a timing side-channel attack. The fix avoids secret-dependent control flow during ECDH computations when libsecp256k1 is compiled with GCC 13.1. - -#### Fixed - - Fixed an old bug that permitted compilers to potentially output bad assembly code on x86_64. In theory, it could lead to a crash or a read of unrelated memory, but this has never been observed on any compilers so far. - -#### Changed - - Various improvements and changes to CMake builds. CMake builds remain experimental. - - Made API versioning consistent with GNU Autotools builds. - - Switched to `BUILD_SHARED_LIBS` variable for controlling whether to build a static or a shared library. - - Added `SECP256K1_INSTALL` variable for the controlling whether to install the build artefacts. - - Renamed asm build option `arm` to `arm32`. Use `--with-asm=arm32` instead of `--with-asm=arm` (GNU Autotools), and `-DSECP256K1_ASM=arm32` instead of `-DSECP256K1_ASM=arm` (CMake). - -#### ABI Compatibility -The ABI is compatible with versions 0.3.0 and 0.3.1. - -## [0.3.1] - 2023-04-10 -We strongly recommend updating to 0.3.1 if you use or plan to use Clang >=14 to compile libsecp256k1, e.g., Xcode >=14 on macOS has Clang >=14. When in doubt, check the Clang version using `clang -v`. - -#### Security - - Fix "constant-timeness" issue with Clang >=14 that could leave applications using libsecp256k1 vulnerable to a timing side-channel attack. The fix avoids secret-dependent control flow and secret-dependent memory accesses in conditional moves of memory objects when libsecp256k1 is compiled with Clang >=14. - -#### Added - - Added tests against [Project Wycheproof's](https://github.com/google/wycheproof/) set of ECDSA test vectors (Bitcoin "low-S" variant), a fixed set of test cases designed to trigger various edge cases. - -#### Changed - - Increased minimum required CMake version to 3.13. CMake builds remain experimental. - -#### ABI Compatibility -The ABI is compatible with version 0.3.0. - -## [0.3.0] - 2023-03-08 - -#### Added - - Added experimental support for CMake builds. Traditional GNU Autotools builds (`./configure` and `make`) remain fully supported. - - Usage examples: Added a recommended method for securely clearing sensitive data, e.g., secret keys, from memory. - - Tests: Added a new test binary `noverify_tests`. This binary runs the tests without some additional checks present in the ordinary `tests` binary and is thereby closer to production binaries. The `noverify_tests` binary is automatically run as part of the `make check` target. - -#### Fixed - - Fixed declarations of API variables for MSVC (`__declspec(dllimport)`). This fixes MSVC builds of programs which link against a libsecp256k1 DLL dynamically and use API variables (and not only API functions). Unfortunately, the MSVC linker now will emit warning `LNK4217` when trying to link against libsecp256k1 statically. Pass `/ignore:4217` to the linker to suppress this warning. - -#### Changed - - Forbade cloning or destroying `secp256k1_context_static`. Create a new context instead of cloning the static context. (If this change breaks your code, your code is probably wrong.) - - Forbade randomizing (copies of) `secp256k1_context_static`. Randomizing a copy of `secp256k1_context_static` did not have any effect and did not provide defense-in-depth protection against side-channel attacks. Create a new context if you want to benefit from randomization. - -#### Removed - - Removed the configuration header `src/libsecp256k1-config.h`. We recommend passing flags to `./configure` or `cmake` to set configuration options (see `./configure --help` or `cmake -LH`). If you cannot or do not want to use one of the supported build systems, pass configuration flags such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG` manually to the compiler (see the file `configure.ac` for supported flags). - -#### ABI Compatibility -Due to changes in the API regarding `secp256k1_context_static` described above, the ABI is *not* compatible with previous versions. - -## [0.2.0] - 2022-12-12 - -#### Added - - Added usage examples for common use cases in a new `examples/` directory. - - Added `secp256k1_selftest`, to be used in conjunction with `secp256k1_context_static`. - - Added support for 128-bit wide multiplication on MSVC for x86_64 and arm64, giving roughly a 20% speedup on those platforms. - -#### Changed - - Enabled modules `schnorrsig`, `extrakeys` and `ecdh` by default in `./configure`. - - The `secp256k1_nonce_function_rfc6979` nonce function, used by default by `secp256k1_ecdsa_sign`, now reduces the message hash modulo the group order to match the specification. This only affects improper use of ECDSA signing API. - -#### Deprecated - - Deprecated context flags `SECP256K1_CONTEXT_VERIFY` and `SECP256K1_CONTEXT_SIGN`. Use `SECP256K1_CONTEXT_NONE` instead. - - Renamed `secp256k1_context_no_precomp` to `secp256k1_context_static`. - - Module `schnorrsig`: renamed `secp256k1_schnorrsig_sign` to `secp256k1_schnorrsig_sign32`. - -#### ABI Compatibility -Since this is the first release, we do not compare application binary interfaces. -However, there are earlier unreleased versions of libsecp256k1 that are *not* ABI compatible with this version. - -## [0.1.0] - 2013-03-05 to 2021-12-25 - -This version was in fact never released. -The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). -Therefore, this version number does not uniquely identify a set of source files. - -[0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0 -[0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 -[0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 -[0.4.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.0...v0.4.1 -[0.4.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.2...v0.4.0 -[0.3.2]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.1...v0.3.2 -[0.3.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...v0.3.1 -[0.3.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.2.0...v0.3.0 -[0.2.0]: https://github.com/bitcoin-core/secp256k1/compare/423b6d19d373f1224fd671a982584d7e7900bc93..v0.2.0 -[0.1.0]: https://github.com/bitcoin-core/secp256k1/commit/423b6d19d373f1224fd671a982584d7e7900bc93 diff --git a/external/secp256k1/CMakeLists.txt b/external/secp256k1/CMakeLists.txt deleted file mode 100644 index 041bfa3dca..0000000000 --- a/external/secp256k1/CMakeLists.txt +++ /dev/null @@ -1,405 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -#============================= -# Project / Package metadata -#============================= -project(libsecp256k1 - # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of - # the API. All changes in experimental modules are treated as - # backwards-compatible and therefore at most increase the minor version. - VERSION 0.6.0 - DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." - HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" - LANGUAGES C -) -enable_testing() -list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) - -if(CMAKE_VERSION VERSION_LESS 3.21) - # Emulates CMake 3.21+ behavior. - if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) - set(PROJECT_IS_TOP_LEVEL ON) - set(${PROJECT_NAME}_IS_TOP_LEVEL ON) - else() - set(PROJECT_IS_TOP_LEVEL OFF) - set(${PROJECT_NAME}_IS_TOP_LEVEL OFF) - endif() -endif() - -# The library version is based on libtool versioning of the ABI. The set of -# rules for updating the version can be found here: -# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -# All changes in experimental modules are treated as if they don't affect the -# interface and therefore only increase the revision. -set(${PROJECT_NAME}_LIB_VERSION_CURRENT 5) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) -set(${PROJECT_NAME}_LIB_VERSION_AGE 0) - -#============================= -# Language setup -#============================= -set(CMAKE_C_STANDARD 90) -set(CMAKE_C_EXTENSIONS OFF) - -#============================= -# Configurable options -#============================= -option(BUILD_SHARED_LIBS "Build shared libraries." ON) -option(SECP256K1_DISABLE_SHARED "Disable shared library. Overrides BUILD_SHARED_LIBS." OFF) -if(SECP256K1_DISABLE_SHARED) - set(BUILD_SHARED_LIBS OFF) -endif() - -option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL}) - -## Modules - -# We declare all options before processing them, to make sure we can express -# dependendencies while processing. -option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON) -option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF) -option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON) -option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON) -option(SECP256K1_ENABLE_MODULE_MUSIG "Enable musig module." ON) -option(SECP256K1_ENABLE_MODULE_ELLSWIFT "Enable ElligatorSwift module." ON) - -# Processing must be done in a topological sorting of the dependency graph -# (dependent module first). -if(SECP256K1_ENABLE_MODULE_ELLSWIFT) - add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) -endif() - -if(SECP256K1_ENABLE_MODULE_MUSIG) - if(DEFINED SECP256K1_ENABLE_MODULE_SCHNORRSIG AND NOT SECP256K1_ENABLE_MODULE_SCHNORRSIG) - message(FATAL_ERROR "Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the musig module.") - endif() - set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON) - add_compile_definitions(ENABLE_MODULE_MUSIG=1) -endif() - -if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) - if(DEFINED SECP256K1_ENABLE_MODULE_EXTRAKEYS AND NOT SECP256K1_ENABLE_MODULE_EXTRAKEYS) - message(FATAL_ERROR "Module dependency error: You have disabled the extrakeys module explicitly, but it is required by the schnorrsig module.") - endif() - set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON) - add_compile_definitions(ENABLE_MODULE_SCHNORRSIG=1) -endif() - -if(SECP256K1_ENABLE_MODULE_EXTRAKEYS) - add_compile_definitions(ENABLE_MODULE_EXTRAKEYS=1) -endif() - -if(SECP256K1_ENABLE_MODULE_RECOVERY) - add_compile_definitions(ENABLE_MODULE_RECOVERY=1) -endif() - -if(SECP256K1_ENABLE_MODULE_ECDH) - add_compile_definitions(ENABLE_MODULE_ECDH=1) -endif() - -option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF) -if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS) - add_compile_definitions(USE_EXTERNAL_DEFAULT_CALLBACKS=1) -endif() - -set(SECP256K1_ECMULT_WINDOW_SIZE 15 CACHE STRING "Window size for ecmult precomputation for verification, specified as integer in range [2..24]. The default value is a reasonable setting for desktop machines (currently 15). [default=15]") -set_property(CACHE SECP256K1_ECMULT_WINDOW_SIZE PROPERTY STRINGS 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24) -include(CheckStringOptionValue) -check_string_option_value(SECP256K1_ECMULT_WINDOW_SIZE) -add_compile_definitions(ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE}) - -set(SECP256K1_ECMULT_GEN_KB 86 CACHE STRING "The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms). Larger values result in possibly better signing or key generation performance at the cost of a larger table. Valid choices are 2, 22, 86. The default value is a reasonable setting for desktop machines (currently 86). [default=86]") -set_property(CACHE SECP256K1_ECMULT_GEN_KB PROPERTY STRINGS 2 22 86) -check_string_option_value(SECP256K1_ECMULT_GEN_KB) -if(SECP256K1_ECMULT_GEN_KB EQUAL 2) - add_compile_definitions(COMB_BLOCKS=2) - add_compile_definitions(COMB_TEETH=5) -elseif(SECP256K1_ECMULT_GEN_KB EQUAL 22) - add_compile_definitions(COMB_BLOCKS=11) - add_compile_definitions(COMB_TEETH=6) -elseif(SECP256K1_ECMULT_GEN_KB EQUAL 86) - add_compile_definitions(COMB_BLOCKS=43) - add_compile_definitions(COMB_TEETH=6) -endif() - -set(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY "OFF" CACHE STRING "Test-only override of the (autodetected by the C code) \"widemul\" setting. Legal values are: \"OFF\", \"int128_struct\", \"int128\" or \"int64\". [default=OFF]") -set_property(CACHE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY PROPERTY STRINGS "OFF" "int128_struct" "int128" "int64") -check_string_option_value(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY) -if(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY) - string(TOUPPER "${SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY}" widemul_upper_value) - add_compile_definitions(USE_FORCE_WIDEMUL_${widemul_upper_value}=1) -endif() -mark_as_advanced(FORCE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY) - -set(SECP256K1_ASM "AUTO" CACHE STRING "Assembly to use: \"AUTO\", \"OFF\", \"x86_64\" or \"arm32\" (experimental). [default=AUTO]") -set_property(CACHE SECP256K1_ASM PROPERTY STRINGS "AUTO" "OFF" "x86_64" "arm32") -check_string_option_value(SECP256K1_ASM) -if(SECP256K1_ASM STREQUAL "arm32") - enable_language(ASM) - include(CheckArm32Assembly) - check_arm32_assembly() - if(HAVE_ARM32_ASM) - add_compile_definitions(USE_EXTERNAL_ASM=1) - else() - message(FATAL_ERROR "ARM32 assembly requested but not available.") - endif() -elseif(SECP256K1_ASM) - include(CheckX86_64Assembly) - check_x86_64_assembly() - if(HAVE_X86_64_ASM) - set(SECP256K1_ASM "x86_64") - add_compile_definitions(USE_ASM_X86_64=1) - elseif(SECP256K1_ASM STREQUAL "AUTO") - set(SECP256K1_ASM "OFF") - else() - message(FATAL_ERROR "x86_64 assembly requested but not available.") - endif() -endif() - -option(SECP256K1_EXPERIMENTAL "Allow experimental configuration options." OFF) -if(NOT SECP256K1_EXPERIMENTAL) - if(SECP256K1_ASM STREQUAL "arm32") - message(FATAL_ERROR "ARM32 assembly is experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow.") - endif() -endif() - -set(SECP256K1_VALGRIND "AUTO" CACHE STRING "Build with extra checks for running inside Valgrind. [default=AUTO]") -set_property(CACHE SECP256K1_VALGRIND PROPERTY STRINGS "AUTO" "OFF" "ON") -check_string_option_value(SECP256K1_VALGRIND) -if(SECP256K1_VALGRIND) - find_package(Valgrind MODULE) - if(Valgrind_FOUND) - set(SECP256K1_VALGRIND ON) - include_directories(${Valgrind_INCLUDE_DIR}) - add_compile_definitions(VALGRIND) - elseif(SECP256K1_VALGRIND STREQUAL "AUTO") - set(SECP256K1_VALGRIND OFF) - else() - message(FATAL_ERROR "Valgrind support requested but valgrind/memcheck.h header not available.") - endif() -endif() - -option(SECP256K1_BUILD_BENCHMARK "Build benchmarks." ON) -option(SECP256K1_BUILD_TESTS "Build tests." ON) -option(SECP256K1_BUILD_EXHAUSTIVE_TESTS "Build exhaustive tests." ON) -option(SECP256K1_BUILD_CTIME_TESTS "Build constant-time tests." ${SECP256K1_VALGRIND}) -option(SECP256K1_BUILD_EXAMPLES "Build examples." OFF) - -# Redefine configuration flags. -# We leave assertions on, because they are only used in the examples, and we want them always on there. -if(MSVC) - string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") - string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") -else() - string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") - string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") - string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") - # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.) - string(REGEX REPLACE "-O3( |$)" "-O2\\1" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") -endif() - -# Define custom "Coverage" build type. -set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O0 -DCOVERAGE=1 --coverage" CACHE STRING - "Flags used by the C compiler during \"Coverage\" builds." - FORCE -) -set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} --coverage" CACHE STRING - "Flags used for linking binaries during \"Coverage\" builds." - FORCE -) -set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} --coverage" CACHE STRING - "Flags used by the shared libraries linker during \"Coverage\" builds." - FORCE -) -mark_as_advanced( - CMAKE_C_FLAGS_COVERAGE - CMAKE_EXE_LINKER_FLAGS_COVERAGE - CMAKE_SHARED_LINKER_FLAGS_COVERAGE -) - -if(PROJECT_IS_TOP_LEVEL) - get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - set(default_build_type "RelWithDebInfo") - if(is_multi_config) - set(CMAKE_CONFIGURATION_TYPES "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" CACHE STRING - "Supported configuration types." - FORCE - ) - else() - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY - STRINGS "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" - ) - if(NOT CMAKE_BUILD_TYPE) - message(STATUS "Setting build type to \"${default_build_type}\" as none was specified") - set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING - "Choose the type of build." - FORCE - ) - endif() - endif() -endif() - -include(TryAppendCFlags) -if(MSVC) - # Keep the following commands ordered lexicographically. - try_append_c_flags(/W3) # Production quality warning level. - try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". - try_append_c_flags(/wd4244) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". - try_append_c_flags(/wd4267) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data". - # Eliminate deprecation warnings for the older, less secure functions. - add_compile_definitions(_CRT_SECURE_NO_WARNINGS) -else() - # Keep the following commands ordered lexicographically. - try_append_c_flags(-pedantic) - try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers. - try_append_c_flags(-Wcast-align) # GCC >= 2.95. - try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0. - try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only. - try_append_c_flags(-Wextra) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions. - try_append_c_flags(-Wnested-externs) - try_append_c_flags(-Wno-long-long) # GCC >= 3.0, -Wlong-long is implied by -pedantic. - try_append_c_flags(-Wno-overlength-strings) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic. - try_append_c_flags(-Wno-unused-function) # GCC >= 3.0, -Wunused-function is implied by -Wall. - try_append_c_flags(-Wreserved-identifier) # Clang >= 13.0 only. - try_append_c_flags(-Wshadow) - try_append_c_flags(-Wstrict-prototypes) - try_append_c_flags(-Wundef) -endif() - -set(CMAKE_C_VISIBILITY_PRESET hidden) - -set(print_msan_notice) -if(SECP256K1_BUILD_CTIME_TESTS) - include(CheckMemorySanitizer) - check_memory_sanitizer(msan_enabled) - if(msan_enabled) - try_append_c_flags(-fno-sanitize-memory-param-retval) - set(print_msan_notice YES) - endif() - unset(msan_enabled) -endif() - -set(SECP256K1_APPEND_CFLAGS "" CACHE STRING "Compiler flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.") -if(SECP256K1_APPEND_CFLAGS) - # Appending to this low-level rule variable is the only way to - # guarantee that the flags appear at the end of the command line. - string(APPEND CMAKE_C_COMPILE_OBJECT " ${SECP256K1_APPEND_CFLAGS}") -endif() - -set(SECP256K1_APPEND_LDFLAGS "" CACHE STRING "Linker flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.") -if(SECP256K1_APPEND_LDFLAGS) - # Appending to this low-level rule variable is the only way to - # guarantee that the flags appear at the end of the command line. - string(APPEND CMAKE_C_CREATE_SHARED_LIBRARY " ${SECP256K1_APPEND_LDFLAGS}") - string(APPEND CMAKE_C_LINK_EXECUTABLE " ${SECP256K1_APPEND_LDFLAGS}") -endif() - -if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) -endif() -if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) -endif() -if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) -endif() -add_subdirectory(src) -if(SECP256K1_BUILD_EXAMPLES) - add_subdirectory(examples) -endif() - -message("\n") -message("secp256k1 configure summary") -message("===========================") -message("Build artifacts:") -if(BUILD_SHARED_LIBS) - set(library_type "Shared") -else() - set(library_type "Static") -endif() - -message(" library type ........................ ${library_type}") -message("Optional modules:") -message(" ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH}") -message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}") -message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRAKEYS}") -message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}") -message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}") -message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}") -message("Parameters:") -message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}") -message(" ecmult gen table size ............... ${SECP256K1_ECMULT_GEN_KB} KiB") -message("Optional features:") -message(" assembly ............................ ${SECP256K1_ASM}") -message(" external callbacks .................. ${SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS}") -if(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY) - message(" wide multiplication (test-only) ..... ${SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY}") -endif() -message("Optional binaries:") -message(" benchmark ........................... ${SECP256K1_BUILD_BENCHMARK}") -message(" noverify_tests ...................... ${SECP256K1_BUILD_TESTS}") -set(tests_status "${SECP256K1_BUILD_TESTS}") -if(CMAKE_BUILD_TYPE STREQUAL "Coverage") - set(tests_status OFF) -endif() -message(" tests ............................... ${tests_status}") -message(" exhaustive tests .................... ${SECP256K1_BUILD_EXHAUSTIVE_TESTS}") -message(" ctime_tests ......................... ${SECP256K1_BUILD_CTIME_TESTS}") -message(" examples ............................ ${SECP256K1_BUILD_EXAMPLES}") -message("") -if(CMAKE_CROSSCOMPILING) - set(cross_status "TRUE, for ${CMAKE_SYSTEM_NAME}, ${CMAKE_SYSTEM_PROCESSOR}") -else() - set(cross_status "FALSE") -endif() -message("Cross compiling ....................... ${cross_status}") -message("Valgrind .............................. ${SECP256K1_VALGRIND}") -get_directory_property(definitions COMPILE_DEFINITIONS) -string(REPLACE ";" " " definitions "${definitions}") -message("Preprocessor defined macros ........... ${definitions}") -message("C compiler ............................ ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}, ${CMAKE_C_COMPILER}") -message("CFLAGS ................................ ${CMAKE_C_FLAGS}") -get_directory_property(compile_options COMPILE_OPTIONS) -string(REPLACE ";" " " compile_options "${compile_options}") -message("Compile options ....................... " ${compile_options}) -if(NOT is_multi_config) - message("Build type:") - message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}") - string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) - message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_${build_type}}") - message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${build_type}}") - message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${build_type}}") -else() - message("Supported configurations .............. ${CMAKE_CONFIGURATION_TYPES}") - message("RelWithDebInfo configuration:") - message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_RELWITHDEBINFO}") - message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}") - message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}") - message("Debug configuration:") - message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_DEBUG}") - message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_DEBUG}") - message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") -endif() -if(SECP256K1_APPEND_CFLAGS) - message("SECP256K1_APPEND_CFLAGS ............... ${SECP256K1_APPEND_CFLAGS}") -endif() -if(SECP256K1_APPEND_LDFLAGS) - message("SECP256K1_APPEND_LDFLAGS .............. ${SECP256K1_APPEND_LDFLAGS}") -endif() -message("") -if(print_msan_notice) - message( - "Note:\n" - " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to compile options\n" - " to avoid false positives in ctime_tests. Pass -DSECP256K1_BUILD_CTIME_TESTS=OFF to avoid this.\n" - ) -endif() -if(SECP256K1_EXPERIMENTAL) - message( - " ******\n" - " WARNING: experimental build\n" - " Experimental features do not have stable APIs or properties, and may not be safe for production use.\n" - " ******\n" - ) -endif() diff --git a/external/secp256k1/CMakePresets.json b/external/secp256k1/CMakePresets.json deleted file mode 100644 index b35cd80579..0000000000 --- a/external/secp256k1/CMakePresets.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "cmakeMinimumRequired": {"major": 3, "minor": 21, "patch": 0}, - "version": 3, - "configurePresets": [ - { - "name": "dev-mode", - "displayName": "Development mode (intended only for developers of the library)", - "cacheVariables": { - "SECP256K1_EXPERIMENTAL": "ON", - "SECP256K1_ENABLE_MODULE_RECOVERY": "ON", - "SECP256K1_BUILD_EXAMPLES": "ON" - }, - "warnings": { - "dev": true, - "uninitialized": true - } - } - ] -} diff --git a/external/secp256k1/CONTRIBUTING.md b/external/secp256k1/CONTRIBUTING.md deleted file mode 100644 index a366d38b0e..0000000000 --- a/external/secp256k1/CONTRIBUTING.md +++ /dev/null @@ -1,108 +0,0 @@ -# Contributing to libsecp256k1 - -## Scope - -libsecp256k1 is a library for elliptic curve cryptography on the curve secp256k1, not a general-purpose cryptography library. -The library primarily serves the needs of the Bitcoin Core project but provides additional functionality for the benefit of the wider Bitcoin ecosystem. - -## Adding new functionality or modules - -The libsecp256k1 project welcomes contributions in the form of new functionality or modules, provided they are within the project's scope. - -It is the responsibility of the contributors to convince the maintainers that the proposed functionality is within the project's scope, high-quality and maintainable. -Contributors are recommended to provide the following in addition to the new code: - -* **Specification:** - A specification can help significantly in reviewing the new code as it provides documentation and context. - It may justify various design decisions, give a motivation and outline security goals. - If the specification contains pseudocode, a reference implementation or test vectors, these can be used to compare with the proposed libsecp256k1 code. -* **Security Arguments:** - In addition to a defining the security goals, it should be argued that the new functionality meets these goals. - Depending on the nature of the new functionality, a wide range of security arguments are acceptable, ranging from being "obviously secure" to rigorous proofs of security. -* **Relevance Arguments:** - The relevance of the new functionality for the Bitcoin ecosystem should be argued by outlining clear use cases. - -These are not the only factors taken into account when considering to add new functionality. -The proposed new libsecp256k1 code must be of high quality, including API documentation and tests, as well as featuring a misuse-resistant API design. - -We recommend reaching out to other contributors (see [Communication Channels](#communication-channels)) and get feedback before implementing new functionality. - -## Communication channels - -Most communication about libsecp256k1 occurs on the GitHub repository: in issues, pull request or on the discussion board. - -Additionally, there is an IRC channel dedicated to libsecp256k1, with biweekly meetings (see channel topic). -The channel is `#secp256k1` on Libera Chat. -The easiest way to participate on IRC is with the web client, [web.libera.chat](https://web.libera.chat/#secp256k1). -Chat history logs can be found at https://gnusha.org/secp256k1/. - -## Contributor workflow & peer review - -The Contributor Workflow & Peer Review in libsecp256k1 are similar to Bitcoin Core's workflow and review processes described in its [CONTRIBUTING.md](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md). - -### Coding conventions - -In addition, libsecp256k1 tries to maintain the following coding conventions: - -* No runtime heap allocation (e.g., no `malloc`) unless explicitly requested by the caller (via `secp256k1_context_create` or `secp256k1_scratch_space_create`, for example). Moreover, it should be possible to use the library without any heap allocations. -* The tests should cover all lines and branches of the library (see [Test coverage](#coverage)). -* Operations involving secret data should be tested for being constant time with respect to the secrets (see [src/ctime_tests.c](src/ctime_tests.c)). -* Local variables containing secret data should be cleared explicitly to try to delete secrets from memory. -* Use `secp256k1_memcmp_var` instead of `memcmp` (see [#823](https://github.com/bitcoin-core/secp256k1/issues/823)). -* As a rule of thumb, the default values for configuration options should target standard desktop machines and align with Bitcoin Core's defaults, and the tests should mostly exercise the default configuration (see [#1549](https://github.com/bitcoin-core/secp256k1/issues/1549#issuecomment-2200559257)). - -#### Style conventions - -* Commits should be atomic and diffs should be easy to read. For this reason, do not mix any formatting fixes or code moves with actual code changes. Make sure each individual commit is hygienic: that it builds successfully on its own without warnings, errors, regressions, or test failures. -* New code should adhere to the style of existing, in particular surrounding, code. Other than that, we do not enforce strict rules for code formatting. -* The code conforms to C89. Most notably, that means that only `/* ... */` comments are allowed (no `//` line comments). Moreover, any declarations in a `{ ... }` block (e.g., a function) must appear at the beginning of the block before any statements. When you would like to declare a variable in the middle of a block, you can open a new block: - ```C - void secp256k_foo(void) { - unsigned int x; /* declaration */ - int y = 2*x; /* declaration */ - x = 17; /* statement */ - { - int a, b; /* declaration */ - a = x + y; /* statement */ - secp256k_bar(x, &b); /* statement */ - } - } - ``` -* Use `unsigned int` instead of just `unsigned`. -* Use `void *ptr` instead of `void* ptr`. -* Arguments of the publicly-facing API must have a specific order defined in [include/secp256k1.h](include/secp256k1.h). -* User-facing comment lines in headers should be limited to 80 chars if possible. -* All identifiers in file scope should start with `secp256k1_`. -* Avoid trailing whitespace. - -### Tests - -#### Coverage - -This library aims to have full coverage of reachable lines and branches. - -To create a test coverage report, configure with `--enable-coverage` (use of GCC is necessary): - - $ ./configure --enable-coverage - -Run the tests: - - $ make check - -To create a report, `gcovr` is recommended, as it includes branch coverage reporting: - - $ gcovr --exclude 'src/bench*' --print-summary - -To create a HTML report with coloured and annotated source code: - - $ mkdir -p coverage - $ gcovr --exclude 'src/bench*' --html --html-details -o coverage/coverage.html - -#### Exhaustive tests - -There are tests of several functions in which a small group replaces secp256k1. -These tests are *exhaustive* since they provide all elements and scalars of the small group as input arguments (see [src/tests_exhaustive.c](src/tests_exhaustive.c)). - -### Benchmarks - -See `src/bench*.c` for examples of benchmarks. diff --git a/external/secp256k1/COPYING b/external/secp256k1/COPYING deleted file mode 100644 index 4522a5990e..0000000000 --- a/external/secp256k1/COPYING +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013 Pieter Wuille - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/external/secp256k1/Makefile.am b/external/secp256k1/Makefile.am deleted file mode 100644 index a95b4809d4..0000000000 --- a/external/secp256k1/Makefile.am +++ /dev/null @@ -1,302 +0,0 @@ -ACLOCAL_AMFLAGS = -I build-aux/m4 - -# AM_CFLAGS will be automatically prepended to CFLAGS by Automake when compiling some foo -# which does not have an explicit foo_CFLAGS variable set. -AM_CFLAGS = $(SECP_CFLAGS) - -lib_LTLIBRARIES = libsecp256k1.la -include_HEADERS = include/secp256k1.h -include_HEADERS += include/secp256k1_preallocated.h -noinst_HEADERS = -noinst_HEADERS += src/scalar.h -noinst_HEADERS += src/scalar_4x64.h -noinst_HEADERS += src/scalar_8x32.h -noinst_HEADERS += src/scalar_low.h -noinst_HEADERS += src/scalar_impl.h -noinst_HEADERS += src/scalar_4x64_impl.h -noinst_HEADERS += src/scalar_8x32_impl.h -noinst_HEADERS += src/scalar_low_impl.h -noinst_HEADERS += src/group.h -noinst_HEADERS += src/group_impl.h -noinst_HEADERS += src/ecdsa.h -noinst_HEADERS += src/ecdsa_impl.h -noinst_HEADERS += src/eckey.h -noinst_HEADERS += src/eckey_impl.h -noinst_HEADERS += src/ecmult.h -noinst_HEADERS += src/ecmult_impl.h -noinst_HEADERS += src/ecmult_compute_table.h -noinst_HEADERS += src/ecmult_compute_table_impl.h -noinst_HEADERS += src/ecmult_const.h -noinst_HEADERS += src/ecmult_const_impl.h -noinst_HEADERS += src/ecmult_gen.h -noinst_HEADERS += src/ecmult_gen_impl.h -noinst_HEADERS += src/ecmult_gen_compute_table.h -noinst_HEADERS += src/ecmult_gen_compute_table_impl.h -noinst_HEADERS += src/field_10x26.h -noinst_HEADERS += src/field_10x26_impl.h -noinst_HEADERS += src/field_5x52.h -noinst_HEADERS += src/field_5x52_impl.h -noinst_HEADERS += src/field_5x52_int128_impl.h -noinst_HEADERS += src/modinv32.h -noinst_HEADERS += src/modinv32_impl.h -noinst_HEADERS += src/modinv64.h -noinst_HEADERS += src/modinv64_impl.h -noinst_HEADERS += src/precomputed_ecmult.h -noinst_HEADERS += src/precomputed_ecmult_gen.h -noinst_HEADERS += src/assumptions.h -noinst_HEADERS += src/checkmem.h -noinst_HEADERS += src/testutil.h -noinst_HEADERS += src/util.h -noinst_HEADERS += src/int128.h -noinst_HEADERS += src/int128_impl.h -noinst_HEADERS += src/int128_native.h -noinst_HEADERS += src/int128_native_impl.h -noinst_HEADERS += src/int128_struct.h -noinst_HEADERS += src/int128_struct_impl.h -noinst_HEADERS += src/scratch.h -noinst_HEADERS += src/scratch_impl.h -noinst_HEADERS += src/selftest.h -noinst_HEADERS += src/testrand.h -noinst_HEADERS += src/testrand_impl.h -noinst_HEADERS += src/hash.h -noinst_HEADERS += src/hash_impl.h -noinst_HEADERS += src/field.h -noinst_HEADERS += src/field_impl.h -noinst_HEADERS += src/bench.h -noinst_HEADERS += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h -noinst_HEADERS += src/hsort.h -noinst_HEADERS += src/hsort_impl.h -noinst_HEADERS += contrib/lax_der_parsing.h -noinst_HEADERS += contrib/lax_der_parsing.c -noinst_HEADERS += contrib/lax_der_privatekey_parsing.h -noinst_HEADERS += contrib/lax_der_privatekey_parsing.c -noinst_HEADERS += examples/examples_util.h - -PRECOMPUTED_LIB = libsecp256k1_precomputed.la -noinst_LTLIBRARIES = $(PRECOMPUTED_LIB) -libsecp256k1_precomputed_la_SOURCES = src/precomputed_ecmult.c src/precomputed_ecmult_gen.c -# We need `-I$(top_srcdir)/src` in VPATH builds if libsecp256k1_precomputed_la_SOURCES have been recreated in the build tree. -# This helps users and packagers who insist on recreating the precomputed files (e.g., Gentoo). -libsecp256k1_precomputed_la_CPPFLAGS = -I$(top_srcdir)/src $(SECP_CONFIG_DEFINES) - -if USE_EXTERNAL_ASM -COMMON_LIB = libsecp256k1_common.la -else -COMMON_LIB = -endif -noinst_LTLIBRARIES += $(COMMON_LIB) - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libsecp256k1.pc - -if USE_EXTERNAL_ASM -if USE_ASM_ARM -libsecp256k1_common_la_SOURCES = src/asm/field_10x26_arm.s -endif -endif - -libsecp256k1_la_SOURCES = src/secp256k1.c -libsecp256k1_la_CPPFLAGS = $(SECP_CONFIG_DEFINES) -libsecp256k1_la_LIBADD = $(COMMON_LIB) $(PRECOMPUTED_LIB) -libsecp256k1_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE) - -noinst_PROGRAMS = -if USE_BENCHMARK -noinst_PROGRAMS += bench bench_internal bench_ecmult -bench_SOURCES = src/bench.c -bench_LDADD = libsecp256k1.la -bench_CPPFLAGS = $(SECP_CONFIG_DEFINES) -bench_internal_SOURCES = src/bench_internal.c -bench_internal_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB) -bench_internal_CPPFLAGS = $(SECP_CONFIG_DEFINES) -bench_ecmult_SOURCES = src/bench_ecmult.c -bench_ecmult_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB) -bench_ecmult_CPPFLAGS = $(SECP_CONFIG_DEFINES) -endif - -TESTS = -if USE_TESTS -TESTS += noverify_tests -noinst_PROGRAMS += noverify_tests -noverify_tests_SOURCES = src/tests.c -noverify_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES) -noverify_tests_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB) -noverify_tests_LDFLAGS = -static -if !ENABLE_COVERAGE -TESTS += tests -noinst_PROGRAMS += tests -tests_SOURCES = $(noverify_tests_SOURCES) -tests_CPPFLAGS = $(noverify_tests_CPPFLAGS) -DVERIFY -tests_LDADD = $(noverify_tests_LDADD) -tests_LDFLAGS = $(noverify_tests_LDFLAGS) -endif -endif - -if USE_CTIME_TESTS -noinst_PROGRAMS += ctime_tests -ctime_tests_SOURCES = src/ctime_tests.c -ctime_tests_LDADD = libsecp256k1.la -ctime_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES) -endif - -if USE_EXHAUSTIVE_TESTS -noinst_PROGRAMS += exhaustive_tests -exhaustive_tests_SOURCES = src/tests_exhaustive.c -exhaustive_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES) -if !ENABLE_COVERAGE -exhaustive_tests_CPPFLAGS += -DVERIFY -endif -# Note: do not include $(PRECOMPUTED_LIB) in exhaustive_tests (it uses runtime-generated tables). -exhaustive_tests_LDADD = $(COMMON_LIB) -exhaustive_tests_LDFLAGS = -static -TESTS += exhaustive_tests -endif - -if USE_EXAMPLES -noinst_PROGRAMS += ecdsa_example -ecdsa_example_SOURCES = examples/ecdsa.c -ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC -ecdsa_example_LDADD = libsecp256k1.la -ecdsa_example_LDFLAGS = -static -if BUILD_WINDOWS -ecdsa_example_LDFLAGS += -lbcrypt -endif -TESTS += ecdsa_example -if ENABLE_MODULE_ECDH -noinst_PROGRAMS += ecdh_example -ecdh_example_SOURCES = examples/ecdh.c -ecdh_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC -ecdh_example_LDADD = libsecp256k1.la -ecdh_example_LDFLAGS = -static -if BUILD_WINDOWS -ecdh_example_LDFLAGS += -lbcrypt -endif -TESTS += ecdh_example -endif -if ENABLE_MODULE_SCHNORRSIG -noinst_PROGRAMS += schnorr_example -schnorr_example_SOURCES = examples/schnorr.c -schnorr_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC -schnorr_example_LDADD = libsecp256k1.la -schnorr_example_LDFLAGS = -static -if BUILD_WINDOWS -schnorr_example_LDFLAGS += -lbcrypt -endif -TESTS += schnorr_example -endif -if ENABLE_MODULE_ELLSWIFT -noinst_PROGRAMS += ellswift_example -ellswift_example_SOURCES = examples/ellswift.c -ellswift_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC -ellswift_example_LDADD = libsecp256k1.la -ellswift_example_LDFLAGS = -static -if BUILD_WINDOWS -ellswift_example_LDFLAGS += -lbcrypt -endif -TESTS += ellswift_example -endif -if ENABLE_MODULE_MUSIG -noinst_PROGRAMS += musig_example -musig_example_SOURCES = examples/musig.c -musig_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC -musig_example_LDADD = libsecp256k1.la -musig_example_LDFLAGS = -static -if BUILD_WINDOWS -musig_example_LDFLAGS += -lbcrypt -endif -TESTS += musig_example -endif -endif - -### Precomputed tables -EXTRA_PROGRAMS = precompute_ecmult precompute_ecmult_gen -CLEANFILES = $(EXTRA_PROGRAMS) - -precompute_ecmult_SOURCES = src/precompute_ecmult.c -precompute_ecmult_CPPFLAGS = $(SECP_CONFIG_DEFINES) -DVERIFY -precompute_ecmult_LDADD = $(COMMON_LIB) - -precompute_ecmult_gen_SOURCES = src/precompute_ecmult_gen.c -precompute_ecmult_gen_CPPFLAGS = $(SECP_CONFIG_DEFINES) -DVERIFY -precompute_ecmult_gen_LDADD = $(COMMON_LIB) - -# See Automake manual, Section "Errors with distclean". -# We don't list any dependencies for the prebuilt files here because -# otherwise make's decision whether to rebuild them (even in the first -# build by a normal user) depends on mtimes, and thus is very fragile. -# This means that rebuilds of the prebuilt files always need to be -# forced by deleting them. -src/precomputed_ecmult.c: - $(MAKE) $(AM_MAKEFLAGS) precompute_ecmult$(EXEEXT) - ./precompute_ecmult$(EXEEXT) -src/precomputed_ecmult_gen.c: - $(MAKE) $(AM_MAKEFLAGS) precompute_ecmult_gen$(EXEEXT) - ./precompute_ecmult_gen$(EXEEXT) - -PRECOMP = src/precomputed_ecmult_gen.c src/precomputed_ecmult.c -precomp: $(PRECOMP) - -# Ensure the prebuilt files will be build first (only if they don't exist, -# e.g., after `make maintainer-clean`). -BUILT_SOURCES = $(PRECOMP) - -.PHONY: clean-precomp -clean-precomp: - rm -f $(PRECOMP) -maintainer-clean-local: clean-precomp - -### Pregenerated test vectors -### (see the comments in the previous section for detailed rationale) -TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h - -src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h: - mkdir -p $(@D) - python3 $(top_srcdir)/tools/tests_wycheproof_generate.py $(top_srcdir)/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@ - -testvectors: $(TESTVECTORS) - -BUILT_SOURCES += $(TESTVECTORS) - -.PHONY: clean-testvectors -clean-testvectors: - rm -f $(TESTVECTORS) -maintainer-clean-local: clean-testvectors - -### Additional files to distribute -EXTRA_DIST = autogen.sh CHANGELOG.md SECURITY.md -EXTRA_DIST += doc/release-process.md doc/safegcd_implementation.md -EXTRA_DIST += doc/ellswift.md doc/musig.md -EXTRA_DIST += examples/EXAMPLES_COPYING -EXTRA_DIST += sage/gen_exhaustive_groups.sage -EXTRA_DIST += sage/gen_split_lambda_constants.sage -EXTRA_DIST += sage/group_prover.sage -EXTRA_DIST += sage/prove_group_implementations.sage -EXTRA_DIST += sage/secp256k1_params.sage -EXTRA_DIST += sage/weierstrass_prover.sage -EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING -EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json -EXTRA_DIST += tools/tests_wycheproof_generate.py - -if ENABLE_MODULE_ECDH -include src/modules/ecdh/Makefile.am.include -endif - -if ENABLE_MODULE_RECOVERY -include src/modules/recovery/Makefile.am.include -endif - -if ENABLE_MODULE_EXTRAKEYS -include src/modules/extrakeys/Makefile.am.include -endif - -if ENABLE_MODULE_SCHNORRSIG -include src/modules/schnorrsig/Makefile.am.include -endif - -if ENABLE_MODULE_MUSIG -include src/modules/musig/Makefile.am.include -endif - -if ENABLE_MODULE_ELLSWIFT -include src/modules/ellswift/Makefile.am.include -endif diff --git a/external/secp256k1/README.md b/external/secp256k1/README.md deleted file mode 100644 index 222e5fb768..0000000000 --- a/external/secp256k1/README.md +++ /dev/null @@ -1,142 +0,0 @@ -libsecp256k1 -============ - -![Dependencies: None](https://img.shields.io/badge/dependencies-none-success) -[![irc.libera.chat #secp256k1](https://img.shields.io/badge/irc.libera.chat-%23secp256k1-success)](https://web.libera.chat/#secp256k1) - -High-performance high-assurance C library for digital signatures and other cryptographic primitives on the secp256k1 elliptic curve. - -This library is intended to be the highest quality publicly available library for cryptography on the secp256k1 curve. However, the primary focus of its development has been for usage in the Bitcoin system and usage unlike Bitcoin's may be less well tested, verified, or suffer from a less well thought out interface. Correct usage requires some care and consideration that the library is fit for your application's purpose. - -Features: -* secp256k1 ECDSA signing/verification and key generation. -* Additive and multiplicative tweaking of secret/public keys. -* Serialization/parsing of secret keys, public keys, signatures. -* Constant time, constant memory access signing and public key generation. -* Derandomized ECDSA (via RFC6979 or with a caller provided function.) -* Very efficient implementation. -* Suitable for embedded systems. -* No runtime dependencies. -* Optional module for public key recovery. -* Optional module for ECDH key exchange. -* Optional module for Schnorr signatures according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). -* Optional module for ElligatorSwift key exchange according to [BIP-324](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki). -* Optional module for MuSig2 Schnorr multi-signatures according to [BIP-327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki). - -Implementation details ----------------------- - -* General - * No runtime heap allocation. - * Extensive testing infrastructure. - * Structured to facilitate review and analysis. - * Intended to be portable to any system with a C89 compiler and uint64_t support. - * No use of floating types. - * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.") -* Field operations - * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). - * Using 5 52-bit limbs - * Using 10 26-bit limbs (including hand-optimized assembly for 32-bit ARM, by Wladimir J. van der Laan). - * This is an experimental feature that has not received enough scrutiny to satisfy the standard of quality of this library but is made available for testing and review by the community. -* Scalar operations - * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. - * Using 4 64-bit limbs (relying on __int128 support in the compiler). - * Using 8 32-bit limbs. -* Modular inverses (both field elements and scalars) based on [safegcd](https://gcd.cr.yp.to/index.html) with some modifications, and a variable-time variant (by Peter Dettman). -* Group operations - * Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7). - * Use addition between points in Jacobian and affine coordinates where possible. - * Use a unified addition/doubling formula where necessary to avoid data-dependent branches. - * Point/x comparison without a field inversion by comparison in the Jacobian coordinate space. -* Point multiplication for verification (a*P + b*G). - * Use wNAF notation for point multiplicands. - * Use a much larger window for multiples of G, using precomputed multiples. - * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. - * Use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. -* Point multiplication for signing - * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. - * Intended to be completely free of timing sidechannels for secret-key operations (on reasonable hardware/toolchains) - * Access the table with branch-free conditional moves so memory access is uniform. - * No data-dependent branches - * Optional runtime blinding which attempts to frustrate differential power analysis. - * The precomputed tables add and eventually subtract points for which no known scalar (secret key) is known, preventing even an attacker with control over the secret key used to control the data internally. - -Building with Autotools ------------------------ - - $ ./autogen.sh - $ ./configure - $ make - $ make check # run the test suite - $ sudo make install # optional - -To compile optional modules (such as Schnorr signatures), you need to run `./configure` with additional flags (such as `--enable-module-schnorrsig`). Run `./configure --help` to see the full list of available flags. - -Building with CMake (experimental) ----------------------------------- - -To maintain a pristine source tree, CMake encourages to perform an out-of-source build by using a separate dedicated build tree. - -### Building on POSIX systems - - $ mkdir build && cd build - $ cmake .. - $ cmake --build . - $ ctest # run the test suite - $ sudo cmake --install . # optional - -To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake .. -LH` to see the full list of available flags. - -### Cross compiling - -To alleviate issues with cross compiling, preconfigured toolchain files are available in the `cmake` directory. -For example, to cross compile for Windows: - - $ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-w64-mingw32.toolchain.cmake - -To cross compile for Android with [NDK](https://developer.android.com/ndk/guides/cmake) (using NDK's toolchain file, and assuming the `ANDROID_NDK_ROOT` environment variable has been set): - - $ cmake .. -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 - -### Building on Windows - -To build on Windows with Visual Studio, a proper [generator](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators) must be specified for a new build tree. - -The following example assumes using of Visual Studio 2022 and CMake v3.21+. - -In "Developer Command Prompt for VS 2022": - - >cmake -G "Visual Studio 17 2022" -A x64 -S . -B build - >cmake --build build --config RelWithDebInfo - -Usage examples ------------ -Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`. - * [ECDSA example](examples/ecdsa.c) - * [Schnorr signatures example](examples/schnorr.c) - * [Deriving a shared secret (ECDH) example](examples/ecdh.c) - * [ElligatorSwift key exchange example](examples/ellswift.c) - -To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`. - -Benchmark ------------- -If configured with `--enable-benchmark` (which is the default), binaries for benchmarking the libsecp256k1 functions will be present in the root directory after the build. - -To print the benchmark result to the command line: - - $ ./bench_name - -To create a CSV file for the benchmark result : - - $ ./bench_name | sed '2d;s/ \{1,\}//g' > bench_name.csv - -Reporting a vulnerability ------------- - -See [SECURITY.md](SECURITY.md) - -Contributing to libsecp256k1 ------------- - -See [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/external/secp256k1/SECURITY.md b/external/secp256k1/SECURITY.md deleted file mode 100644 index b515cc1c8e..0000000000 --- a/external/secp256k1/SECURITY.md +++ /dev/null @@ -1,15 +0,0 @@ -# Security Policy - -## Reporting a Vulnerability - -To report security issues send an email to secp256k1-security@bitcoincore.org (not for support). - -The following keys may be used to communicate sensitive information to developers: - -| Name | Fingerprint | -|------|-------------| -| Pieter Wuille | 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 | -| Jonas Nick | 36C7 1A37 C9D9 88BD E825 08D9 B1A7 0E4F 8DCD 0366 | -| Tim Ruffing | 09E0 3F87 1092 E40E 106E 902B 33BC 86AB 80FF 5516 | - -You can import a key by running the following command with that individual’s fingerprint: `gpg --keyserver hkps://keys.openpgp.org --recv-keys ""` Ensure that you put quotes around fingerprints containing spaces. diff --git a/external/secp256k1/autogen.sh b/external/secp256k1/autogen.sh deleted file mode 100755 index 65286b9353..0000000000 --- a/external/secp256k1/autogen.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -set -e -autoreconf -if --warnings=all diff --git a/external/secp256k1/build-aux/m4/bitcoin_secp.m4 b/external/secp256k1/build-aux/m4/bitcoin_secp.m4 deleted file mode 100644 index 048267fa6e..0000000000 --- a/external/secp256k1/build-aux/m4/bitcoin_secp.m4 +++ /dev/null @@ -1,91 +0,0 @@ -dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. -AC_DEFUN([SECP_X86_64_ASM_CHECK],[ -AC_MSG_CHECKING(for x86_64 assembly availability) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ - #include ]],[[ - uint64_t a = 11, tmp; - __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); - ]])], [has_x86_64_asm=yes], [has_x86_64_asm=no]) -AC_MSG_RESULT([$has_x86_64_asm]) -]) - -AC_DEFUN([SECP_ARM32_ASM_CHECK], [ - AC_MSG_CHECKING(for ARM32 assembly availability) - SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS="$CFLAGS" - CFLAGS="-x assembler" - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - .syntax unified - .eabi_attribute 24, 1 - .eabi_attribute 25, 1 - .text - .global main - main: - ldr r0, =0x002A - mov r7, #1 - swi 0 - ]])], [has_arm32_asm=yes], [has_arm32_asm=no]) - AC_MSG_RESULT([$has_arm32_asm]) - CFLAGS="$SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS" -]) - -AC_DEFUN([SECP_VALGRIND_CHECK],[ -AC_MSG_CHECKING([for valgrind support]) -if test x"$has_valgrind" != x"yes"; then - CPPFLAGS_TEMP="$CPPFLAGS" - CPPFLAGS="$VALGRIND_CPPFLAGS $CPPFLAGS" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #include - ]], [[ - #if defined(NVALGRIND) - # error "Valgrind does not support this platform." - #endif - ]])], [has_valgrind=yes]) - CPPFLAGS="$CPPFLAGS_TEMP" -fi -AC_MSG_RESULT($has_valgrind) -]) - -AC_DEFUN([SECP_MSAN_CHECK], [ -AC_MSG_CHECKING(whether MemorySanitizer is enabled) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ - #if defined(__has_feature) - # if __has_feature(memory_sanitizer) - /* MemorySanitizer is enabled. */ - # elif - # error "MemorySanitizer is disabled." - # endif - #else - # error "__has_feature is not defined." - #endif - ]])], [msan_enabled=yes], [msan_enabled=no]) -AC_MSG_RESULT([$msan_enabled]) -]) - -dnl SECP_TRY_APPEND_CFLAGS(flags, VAR) -dnl Append flags to VAR if CC accepts them. -AC_DEFUN([SECP_TRY_APPEND_CFLAGS], [ - AC_MSG_CHECKING([if ${CC} supports $1]) - SECP_TRY_APPEND_CFLAGS_saved_CFLAGS="$CFLAGS" - CFLAGS="$1 $CFLAGS" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], [flag_works=yes], [flag_works=no]) - AC_MSG_RESULT($flag_works) - CFLAGS="$SECP_TRY_APPEND_CFLAGS_saved_CFLAGS" - if test x"$flag_works" = x"yes"; then - $2="$$2 $1" - fi - unset flag_works - AC_SUBST($2) -]) - -dnl SECP_SET_DEFAULT(VAR, default, default-dev-mode) -dnl Set VAR to default or default-dev-mode, depending on whether dev mode is enabled -AC_DEFUN([SECP_SET_DEFAULT], [ - if test "${enable_dev_mode+set}" != set; then - AC_MSG_ERROR([[Set enable_dev_mode before calling SECP_SET_DEFAULT]]) - fi - if test x"$enable_dev_mode" = x"yes"; then - $1="$3" - else - $1="$2" - fi -]) diff --git a/external/secp256k1/ci/ci.sh b/external/secp256k1/ci/ci.sh deleted file mode 100755 index 3636deafa1..0000000000 --- a/external/secp256k1/ci/ci.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/sh - -set -eux - -export LC_ALL=C - -# Print commit and relevant CI environment to allow reproducing the job outside of CI. -git show --no-patch -print_environment() { - # Turn off -x because it messes up the output - set +x - # There are many ways to print variable names and their content. This one - # does not rely on bash. - for var in WERROR_CFLAGS MAKEFLAGS BUILD \ - ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ - EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT \ - SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\ - EXAMPLES \ - HOST WRAPPER_CMD \ - CC CFLAGS CPPFLAGS AR NM \ - UBSAN_OPTIONS ASAN_OPTIONS LSAN_OPTIONS - do - eval "isset=\${$var+x}" - if [ -n "$isset" ]; then - eval "val=\${$var}" - # shellcheck disable=SC2154 - printf '%s="%s" ' "$var" "$val" - fi - done - echo "$0" - set -x -} -print_environment - -env >> test_env.log - -# If gcc is requested, assert that it's in fact gcc (and not some symlinked Apple clang). -case "${CC:-undefined}" in - *gcc*) - $CC -v 2>&1 | grep -q "gcc version" || exit 1; - ;; -esac - -if [ -n "${CC+x}" ]; then - # The MSVC compiler "cl" doesn't understand "-v" - $CC -v || true -fi -if [ "$WITH_VALGRIND" = "yes" ]; then - valgrind --version -fi -if [ -n "$WRAPPER_CMD" ]; then - $WRAPPER_CMD --version -fi - -# Workaround for https://bugs.kde.org/show_bug.cgi?id=452758 (fixed in valgrind 3.20.0). -case "${CC:-undefined}" in - clang*) - if [ "$CTIMETESTS" = "yes" ] && [ "$WITH_VALGRIND" = "yes" ] - then - export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4" - else - case "$WRAPPER_CMD" in - valgrind*) - export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4" - ;; - esac - fi - ;; -esac - -./autogen.sh - -./configure \ - --enable-experimental="$EXPERIMENTAL" \ - --with-test-override-wide-multiply="$WIDEMUL" --with-asm="$ASM" \ - --with-ecmult-window="$ECMULTWINDOW" \ - --with-ecmult-gen-kb="$ECMULTGENKB" \ - --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \ - --enable-module-ellswift="$ELLSWIFT" \ - --enable-module-extrakeys="$EXTRAKEYS" \ - --enable-module-schnorrsig="$SCHNORRSIG" \ - --enable-module-musig="$MUSIG" \ - --enable-examples="$EXAMPLES" \ - --enable-ctime-tests="$CTIMETESTS" \ - --with-valgrind="$WITH_VALGRIND" \ - --host="$HOST" $EXTRAFLAGS - -# We have set "-j" in MAKEFLAGS. -build_exit_code=0 -make > make.log 2>&1 || build_exit_code=$? -cat make.log -if [ $build_exit_code -ne 0 ]; then - case "${CC:-undefined}" in - *snapshot*) - # Ignore internal compiler errors in gcc-snapshot and clang-snapshot - grep -e "internal compiler error:" -e "PLEASE submit a bug report" make.log - return $?; - ;; - *) - return 1; - ;; - esac -fi - -# Print information about binaries so that we can see that the architecture is correct -file *tests* || true -file bench* || true -file .libs/* || true - -# This tells `make check` to wrap test invocations. -export LOG_COMPILER="$WRAPPER_CMD" - -make "$BUILD" - -# Using the local `libtool` because on macOS the system's libtool has nothing to do with GNU libtool -EXEC='./libtool --mode=execute' -if [ -n "$WRAPPER_CMD" ] -then - EXEC="$EXEC $WRAPPER_CMD" -fi - -if [ "$BENCH" = "yes" ] -then - { - $EXEC ./bench_ecmult - $EXEC ./bench_internal - $EXEC ./bench - } >> bench.log 2>&1 -fi - -if [ "$CTIMETESTS" = "yes" ] -then - if [ "$WITH_VALGRIND" = "yes" ]; then - ./libtool --mode=execute valgrind --error-exitcode=42 ./ctime_tests > ctime_tests.log 2>&1 - else - $EXEC ./ctime_tests > ctime_tests.log 2>&1 - fi -fi - -# Rebuild precomputed files (if not cross-compiling). -if [ -z "$HOST" ] -then - make clean-precomp clean-testvectors - make precomp testvectors -fi - -# Check that no repo files have been modified by the build. -# (This fails for example if the precomp files need to be updated in the repo.) -git diff --exit-code diff --git a/external/secp256k1/ci/linux-debian.Dockerfile b/external/secp256k1/ci/linux-debian.Dockerfile deleted file mode 100644 index 241bfa9719..0000000000 --- a/external/secp256k1/ci/linux-debian.Dockerfile +++ /dev/null @@ -1,79 +0,0 @@ -FROM debian:stable-slim - -SHELL ["/bin/bash", "-c"] - -WORKDIR /root - -# A too high maximum number of file descriptors (with the default value -# inherited from the docker host) can cause issues with some of our tools: -# - sanitizers hanging: https://github.com/google/sanitizers/issues/1662 -# - valgrind crashing: https://stackoverflow.com/a/75293014 -# This is not be a problem on our CI hosts, but developers who run the image -# on their machines may run into this (e.g., on Arch Linux), so warn them. -# (Note that .bashrc is only executed in interactive bash shells.) -RUN echo 'if [[ $(ulimit -n) -gt 200000 ]]; then echo "WARNING: Very high value reported by \"ulimit -n\". Consider passing \"--ulimit nofile=32768\" to \"docker run\"."; fi' >> /root/.bashrc - -RUN dpkg --add-architecture i386 && \ - dpkg --add-architecture s390x && \ - dpkg --add-architecture armhf && \ - dpkg --add-architecture arm64 && \ - dpkg --add-architecture ppc64el - -# dkpg-dev: to make pkg-config work in cross-builds -# llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces -RUN apt-get update && apt-get install --no-install-recommends -y \ - git ca-certificates \ - make automake libtool pkg-config dpkg-dev valgrind qemu-user \ - gcc clang llvm libclang-rt-dev libc6-dbg \ - g++ \ - gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan8:i386 \ - gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \ - gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \ - gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross libc6-dbg:ppc64el \ - gcc-mingw-w64-x86-64-win32 wine64 wine \ - gcc-mingw-w64-i686-win32 wine32 \ - python3 && \ - if ! ( dpkg --print-architecture | grep --quiet "arm64" ) ; then \ - apt-get install --no-install-recommends -y \ - gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 ;\ - fi && \ - apt-get clean && rm -rf /var/lib/apt/lists/* - -# Build and install gcc snapshot -ARG GCC_SNAPSHOT_MAJOR=15 -RUN apt-get update && apt-get install --no-install-recommends -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ - mkdir gcc && cd gcc && \ - wget --progress=dot:giga --https-only --recursive --accept '*.tar.xz' --level 1 --no-directories "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}" && \ - wget "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}/sha512.sum" && \ - sha512sum --check --ignore-missing sha512.sum && \ - # We should have downloaded exactly one tar.xz file - ls && \ - [ $(ls *.tar.xz | wc -l) -eq "1" ] && \ - tar xf *.tar.xz && \ - mkdir gcc-build && cd gcc-build && \ - ../*/configure --prefix=/opt/gcc-snapshot --enable-languages=c --disable-bootstrap --disable-multilib --without-isl && \ - make -j $(nproc) && \ - make install && \ - cd ../.. && rm -rf gcc && \ - ln -s /opt/gcc-snapshot/bin/gcc /usr/bin/gcc-snapshot && \ - apt-get autoremove -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ - apt-get clean && rm -rf /var/lib/apt/lists/* - -# Install clang snapshot, see https://apt.llvm.org/ -RUN \ - # Setup GPG keys of LLVM repository - apt-get update && apt-get install --no-install-recommends -y wget && \ - wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ - # Add repository for this Debian release - . /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \ - apt-get update && \ - # Determine the version number of the LLVM development branch - LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ - # Install - apt-get install --no-install-recommends -y "clang-${LLVM_VERSION}" && \ - # Create symlink - ln -s "/usr/bin/clang-${LLVM_VERSION}" /usr/bin/clang-snapshot && \ - # Clean up - apt-get autoremove -y wget && \ - apt-get clean && rm -rf /var/lib/apt/lists/* - diff --git a/external/secp256k1/cmake/CheckArm32Assembly.cmake b/external/secp256k1/cmake/CheckArm32Assembly.cmake deleted file mode 100644 index baeeff0292..0000000000 --- a/external/secp256k1/cmake/CheckArm32Assembly.cmake +++ /dev/null @@ -1,6 +0,0 @@ -function(check_arm32_assembly) - try_compile(HAVE_ARM32_ASM - ${PROJECT_BINARY_DIR}/check_arm32_assembly - SOURCES ${PROJECT_SOURCE_DIR}/cmake/source_arm32.s - ) -endfunction() diff --git a/external/secp256k1/cmake/CheckMemorySanitizer.cmake b/external/secp256k1/cmake/CheckMemorySanitizer.cmake deleted file mode 100644 index d9ef681e65..0000000000 --- a/external/secp256k1/cmake/CheckMemorySanitizer.cmake +++ /dev/null @@ -1,18 +0,0 @@ -include_guard(GLOBAL) -include(CheckCSourceCompiles) - -function(check_memory_sanitizer output) - set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) - check_c_source_compiles(" - #if defined(__has_feature) - # if __has_feature(memory_sanitizer) - /* MemorySanitizer is enabled. */ - # elif - # error \"MemorySanitizer is disabled.\" - # endif - #else - # error \"__has_feature is not defined.\" - #endif - " HAVE_MSAN) - set(${output} ${HAVE_MSAN} PARENT_SCOPE) -endfunction() diff --git a/external/secp256k1/cmake/CheckStringOptionValue.cmake b/external/secp256k1/cmake/CheckStringOptionValue.cmake deleted file mode 100644 index 5a4d939b9e..0000000000 --- a/external/secp256k1/cmake/CheckStringOptionValue.cmake +++ /dev/null @@ -1,10 +0,0 @@ -function(check_string_option_value option) - get_property(expected_values CACHE ${option} PROPERTY STRINGS) - if(expected_values) - if(${option} IN_LIST expected_values) - return() - endif() - message(FATAL_ERROR "${option} value is \"${${option}}\", but must be one of ${expected_values}.") - endif() - message(AUTHOR_WARNING "The STRINGS property must be set before invoking `check_string_option_value' function.") -endfunction() diff --git a/external/secp256k1/cmake/CheckX86_64Assembly.cmake b/external/secp256k1/cmake/CheckX86_64Assembly.cmake deleted file mode 100644 index ae82cd476e..0000000000 --- a/external/secp256k1/cmake/CheckX86_64Assembly.cmake +++ /dev/null @@ -1,14 +0,0 @@ -include(CheckCSourceCompiles) - -function(check_x86_64_assembly) - check_c_source_compiles(" - #include - - int main() - { - uint64_t a = 11, tmp; - __asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\"); - } - " HAVE_X86_64_ASM) - set(HAVE_X86_64_ASM ${HAVE_X86_64_ASM} PARENT_SCOPE) -endfunction() diff --git a/external/secp256k1/cmake/FindValgrind.cmake b/external/secp256k1/cmake/FindValgrind.cmake deleted file mode 100644 index 3af5e691e4..0000000000 --- a/external/secp256k1/cmake/FindValgrind.cmake +++ /dev/null @@ -1,41 +0,0 @@ -if(CMAKE_HOST_APPLE) - find_program(BREW_COMMAND brew) - execute_process( - COMMAND ${BREW_COMMAND} --prefix valgrind - OUTPUT_VARIABLE valgrind_brew_prefix - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -endif() - -set(hints_paths) -if(valgrind_brew_prefix) - set(hints_paths ${valgrind_brew_prefix}/include) -endif() - -find_path(Valgrind_INCLUDE_DIR - NAMES valgrind/memcheck.h - HINTS ${hints_paths} -) - -if(Valgrind_INCLUDE_DIR) - include(CheckCSourceCompiles) - set(CMAKE_REQUIRED_INCLUDES ${Valgrind_INCLUDE_DIR}) - check_c_source_compiles(" - #include - #if defined(NVALGRIND) - # error \"Valgrind does not support this platform.\" - #endif - - int main() {} - " Valgrind_WORKS) -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Valgrind - REQUIRED_VARS Valgrind_INCLUDE_DIR Valgrind_WORKS -) - -mark_as_advanced( - Valgrind_INCLUDE_DIR -) diff --git a/external/secp256k1/cmake/GeneratePkgConfigFile.cmake b/external/secp256k1/cmake/GeneratePkgConfigFile.cmake deleted file mode 100644 index 9c1d7f1ddd..0000000000 --- a/external/secp256k1/cmake/GeneratePkgConfigFile.cmake +++ /dev/null @@ -1,8 +0,0 @@ -function(generate_pkg_config_file in_file) - set(prefix ${CMAKE_INSTALL_PREFIX}) - set(exec_prefix \${prefix}) - set(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR}) - set(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR}) - set(PACKAGE_VERSION ${PROJECT_VERSION}) - configure_file(${in_file} ${PROJECT_NAME}.pc @ONLY) -endfunction() diff --git a/external/secp256k1/cmake/TryAppendCFlags.cmake b/external/secp256k1/cmake/TryAppendCFlags.cmake deleted file mode 100644 index 1d81a9317a..0000000000 --- a/external/secp256k1/cmake/TryAppendCFlags.cmake +++ /dev/null @@ -1,24 +0,0 @@ -include(CheckCCompilerFlag) - -function(secp256k1_check_c_flags_internal flags output) - string(MAKE_C_IDENTIFIER "${flags}" result) - string(TOUPPER "${result}" result) - set(result "C_SUPPORTS_${result}") - if(NOT MSVC) - set(CMAKE_REQUIRED_FLAGS "-Werror") - endif() - - # This avoids running a linker. - set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) - check_c_compiler_flag("${flags}" ${result}) - - set(${output} ${${result}} PARENT_SCOPE) -endfunction() - -# Append flags to the COMPILE_OPTIONS directory property if CC accepts them. -macro(try_append_c_flags) - secp256k1_check_c_flags_internal("${ARGV}" result) - if(result) - add_compile_options(${ARGV}) - endif() -endmacro() diff --git a/external/secp256k1/cmake/arm-linux-gnueabihf.toolchain.cmake b/external/secp256k1/cmake/arm-linux-gnueabihf.toolchain.cmake deleted file mode 100644 index 0d91912b6d..0000000000 --- a/external/secp256k1/cmake/arm-linux-gnueabihf.toolchain.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR arm) -set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) diff --git a/external/secp256k1/cmake/config.cmake.in b/external/secp256k1/cmake/config.cmake.in deleted file mode 100644 index 46b180ab19..0000000000 --- a/external/secp256k1/cmake/config.cmake.in +++ /dev/null @@ -1,5 +0,0 @@ -@PACKAGE_INIT@ - -include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") - -check_required_components(@PROJECT_NAME@) diff --git a/external/secp256k1/cmake/source_arm32.s b/external/secp256k1/cmake/source_arm32.s deleted file mode 100644 index d3d9347057..0000000000 --- a/external/secp256k1/cmake/source_arm32.s +++ /dev/null @@ -1,9 +0,0 @@ -.syntax unified -.eabi_attribute 24, 1 -.eabi_attribute 25, 1 -.text -.global main -main: - ldr r0, =0x002A - mov r7, #1 - swi 0 diff --git a/external/secp256k1/cmake/x86_64-w64-mingw32.toolchain.cmake b/external/secp256k1/cmake/x86_64-w64-mingw32.toolchain.cmake deleted file mode 100644 index 96119b72d1..0000000000 --- a/external/secp256k1/cmake/x86_64-w64-mingw32.toolchain.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(CMAKE_SYSTEM_NAME Windows) -set(CMAKE_SYSTEM_PROCESSOR x86_64) -set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) diff --git a/external/secp256k1/configure.ac b/external/secp256k1/configure.ac deleted file mode 100644 index f880a3578d..0000000000 --- a/external/secp256k1/configure.ac +++ /dev/null @@ -1,517 +0,0 @@ -AC_PREREQ([2.60]) - -# The package (a.k.a. release) version is based on semantic versioning 2.0.0 of -# the API. All changes in experimental modules are treated as -# backwards-compatible and therefore at most increase the minor version. -define(_PKG_VERSION_MAJOR, 0) -define(_PKG_VERSION_MINOR, 6) -define(_PKG_VERSION_PATCH, 0) -define(_PKG_VERSION_IS_RELEASE, true) - -# The library version is based on libtool versioning of the ABI. The set of -# rules for updating the version can be found here: -# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -# All changes in experimental modules are treated as if they don't affect the -# interface and therefore only increase the revision. -define(_LIB_VERSION_CURRENT, 5) -define(_LIB_VERSION_REVISION, 0) -define(_LIB_VERSION_AGE, 0) - -AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) - -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) -AC_CANONICAL_HOST - -# Require Automake 1.11.2 for AM_PROG_AR -AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects]) - -# Make the compilation flags quiet unless V=1 is used. -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -if test "${CFLAGS+set}" = "set"; then - CFLAGS_overridden=yes -else - CFLAGS_overridden=no -fi -AC_PROG_CC -AM_PROG_AS -AM_PROG_AR - -# Clear some cache variables as a workaround for a bug that appears due to a bad -# interaction between AM_PROG_AR and LT_INIT when combining MSVC's archiver lib.exe. -# https://debbugs.gnu.org/cgi/bugreport.cgi?bug=54421 -AS_UNSET(ac_cv_prog_AR) -AS_UNSET(ac_cv_prog_ac_ct_AR) -LT_INIT([win32-dll]) - -build_windows=no - -case $host_os in - *darwin*) - if test x$cross_compiling != xyes; then - AC_CHECK_PROG([BREW], brew, brew) - if test x$BREW = xbrew; then - # These Homebrew packages may be keg-only, meaning that they won't be found - # in expected paths because they may conflict with system files. Ask - # Homebrew where each one is located, then adjust paths accordingly. - if $BREW list --versions valgrind >/dev/null; then - valgrind_prefix=$($BREW --prefix valgrind 2>/dev/null) - VALGRIND_CPPFLAGS="-I$valgrind_prefix/include" - fi - else - AC_CHECK_PROG([PORT], port, port) - # If homebrew isn't installed and macports is, add the macports default paths - # as a last resort. - if test x$PORT = xport; then - CPPFLAGS="$CPPFLAGS -isystem /opt/local/include" - LDFLAGS="$LDFLAGS -L/opt/local/lib" - fi - fi - fi - ;; - cygwin*|mingw*) - build_windows=yes - ;; -esac - -# Try if some desirable compiler flags are supported and append them to SECP_CFLAGS. -# -# These are our own flags, so we append them to our own SECP_CFLAGS variable (instead of CFLAGS) as -# recommended in the automake manual (Section "Flag Variables Ordering"). CFLAGS belongs to the user -# and we are not supposed to touch it. In the Makefile, we will need to ensure that SECP_CFLAGS -# is prepended to CFLAGS when invoking the compiler so that the user always has the last word (flag). -# -# Another advantage of not touching CFLAGS is that the contents of CFLAGS will be picked up by -# libtool for compiling helper executables. For example, when compiling for Windows, libtool will -# generate entire wrapper executables (instead of simple wrapper scripts as on Unix) to ensure -# proper operation of uninstalled programs linked by libtool against the uninstalled shared library. -# These executables are compiled from C source file for which our flags may not be appropriate, -# e.g., -std=c89 flag has lead to undesirable warnings in the past. -# -# TODO We should analogously not touch CPPFLAGS and LDFLAGS but currently there are no issues. -AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [ - # GCC and compatible (incl. clang) - if test "x$GCC" = "xyes"; then - # Try to append -Werror to CFLAGS temporarily. Otherwise checks for some unsupported - # flags will succeed. - # Note that failure to append -Werror does not necessarily mean that -Werror is not - # supported. The compiler may already be warning about something unrelated, for example - # about some path issue. If that is the case, -Werror cannot be used because all - # of those warnings would be turned into errors. - SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS="$CFLAGS" - SECP_TRY_APPEND_CFLAGS([-Werror], CFLAGS) - - SECP_TRY_APPEND_CFLAGS([-std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef], $1) # GCC >= 3.0, -Wlong-long is implied by -pedantic. - SECP_TRY_APPEND_CFLAGS([-Wno-overlength-strings], $1) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic. - SECP_TRY_APPEND_CFLAGS([-Wall], $1) # GCC >= 2.95 and probably many other compilers - SECP_TRY_APPEND_CFLAGS([-Wno-unused-function], $1) # GCC >= 3.0, -Wunused-function is implied by -Wall. - SECP_TRY_APPEND_CFLAGS([-Wextra], $1) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions. - SECP_TRY_APPEND_CFLAGS([-Wcast-align], $1) # GCC >= 2.95 - SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0 - SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only - SECP_TRY_APPEND_CFLAGS([-Wreserved-identifier], $1) # Clang >= 13.0 only - SECP_TRY_APPEND_CFLAGS([-fvisibility=hidden], $1) # GCC >= 4.0 - - CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS" - fi - - # MSVC - # Assume MSVC if we're building for Windows but not with GCC or compatible; - # libtool makes the same assumption internally. - # Note that "/opt" and "-opt" are equivalent for MSVC; we use "-opt" because "/opt" looks like a path. - if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then - SECP_TRY_APPEND_CFLAGS([-W3], $1) # Production quality warning level. - SECP_TRY_APPEND_CFLAGS([-wd4146], $1) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". - SECP_TRY_APPEND_CFLAGS([-wd4244], $1) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". - SECP_TRY_APPEND_CFLAGS([-wd4267], $1) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data". - # Eliminate deprecation warnings for the older, less secure functions. - CPPFLAGS="-D_CRT_SECURE_NO_WARNINGS $CPPFLAGS" - fi -]) -SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS) - -### -### Define config arguments -### - -# In dev mode, we enable all binaries and modules by default but individual options can still be overridden explicitly. -# Check for dev mode first because SECP_SET_DEFAULT needs enable_dev_mode set. -AC_ARG_ENABLE(dev_mode, [], [], - [enable_dev_mode=no]) - -AC_ARG_ENABLE(benchmark, - AS_HELP_STRING([--enable-benchmark],[compile benchmark [default=yes]]), [], - [SECP_SET_DEFAULT([enable_benchmark], [yes], [yes])]) - -AC_ARG_ENABLE(coverage, - AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis [default=no]]), [], - [SECP_SET_DEFAULT([enable_coverage], [no], [no])]) - -AC_ARG_ENABLE(tests, - AS_HELP_STRING([--enable-tests],[compile tests [default=yes]]), [], - [SECP_SET_DEFAULT([enable_tests], [yes], [yes])]) - -AC_ARG_ENABLE(ctime_tests, - AS_HELP_STRING([--enable-ctime-tests],[compile constant-time tests [default=yes if valgrind enabled]]), [], - [SECP_SET_DEFAULT([enable_ctime_tests], [auto], [auto])]) - -AC_ARG_ENABLE(experimental, - AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]), [], - [SECP_SET_DEFAULT([enable_experimental], [no], [yes])]) - -AC_ARG_ENABLE(exhaustive_tests, - AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests [default=yes]]), [], - [SECP_SET_DEFAULT([enable_exhaustive_tests], [yes], [yes])]) - -AC_ARG_ENABLE(examples, - AS_HELP_STRING([--enable-examples],[compile the examples [default=no]]), [], - [SECP_SET_DEFAULT([enable_examples], [no], [yes])]) - -AC_ARG_ENABLE(module_ecdh, - AS_HELP_STRING([--enable-module-ecdh],[enable ECDH module [default=yes]]), [], - [SECP_SET_DEFAULT([enable_module_ecdh], [yes], [yes])]) - -AC_ARG_ENABLE(module_recovery, - AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]), [], - [SECP_SET_DEFAULT([enable_module_recovery], [no], [yes])]) - -AC_ARG_ENABLE(module_extrakeys, - AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module [default=yes]]), [], - [SECP_SET_DEFAULT([enable_module_extrakeys], [yes], [yes])]) - -AC_ARG_ENABLE(module_schnorrsig, - AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=yes]]), [], - [SECP_SET_DEFAULT([enable_module_schnorrsig], [yes], [yes])]) - -AC_ARG_ENABLE(module_musig, - AS_HELP_STRING([--enable-module-musig],[enable MuSig2 module [default=yes]]), [], - [SECP_SET_DEFAULT([enable_module_musig], [yes], [yes])]) - -AC_ARG_ENABLE(module_ellswift, - AS_HELP_STRING([--enable-module-ellswift],[enable ElligatorSwift module [default=yes]]), [], - [SECP_SET_DEFAULT([enable_module_ellswift], [yes], [yes])]) - -AC_ARG_ENABLE(external_default_callbacks, - AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), [], - [SECP_SET_DEFAULT([enable_external_default_callbacks], [no], [no])]) - -# Test-only override of the (autodetected by the C code) "widemul" setting. -# Legal values are: -# * int64 (for [u]int64_t), -# * int128 (for [unsigned] __int128), -# * int128_struct (for int128 implemented as a structure), -# * and auto (the default). -AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto]) - -AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm32|no|auto], -[assembly to use (experimental: arm32) [default=auto]])],[req_asm=$withval], [req_asm=auto]) - -AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE], -[window size for ecmult precomputation for verification, specified as integer in range [2..24].] -[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.] -[The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.] -[A window size larger than 15 will require you delete the prebuilt precomputed_ecmult.c file so that it can be rebuilt.] -[For very large window sizes, use "make -j 1" to reduce memory use during compilation.] -[The default value is a reasonable setting for desktop machines (currently 15). [default=15]] -)], -[set_ecmult_window=$withval], [set_ecmult_window=15]) - -AC_ARG_WITH([ecmult-gen-kb], [AS_HELP_STRING([--with-ecmult-gen-kb=2|22|86], -[The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms).] -[Larger values result in possibly better signing/keygeneration performance at the cost of a larger table.] -[The default value is a reasonable setting for desktop machines (currently 86). [default=86]] -)], -[set_ecmult_gen_kb=$withval], [set_ecmult_gen_kb=86]) - -AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind=yes|no|auto], -[Build with extra checks for running inside Valgrind [default=auto]] -)], -[req_valgrind=$withval], [req_valgrind=auto]) - -### -### Handle config options (except for modules) -### - -if test x"$req_valgrind" = x"no"; then - enable_valgrind=no -else - SECP_VALGRIND_CHECK - if test x"$has_valgrind" != x"yes"; then - if test x"$req_valgrind" = x"yes"; then - AC_MSG_ERROR([Valgrind support explicitly requested but valgrind/memcheck.h header not available]) - fi - enable_valgrind=no - else - enable_valgrind=yes - fi -fi - -if test x"$enable_ctime_tests" = x"auto"; then - enable_ctime_tests=$enable_valgrind -fi - -print_msan_notice=no -if test x"$enable_ctime_tests" = x"yes"; then - SECP_MSAN_CHECK - # MSan on Clang >=16 reports unitialized memory in function parameters and return values, even if - # the uninitalized variable is never actually "used". This is called "eager" checking, and it's - # sounds like good idea for normal use of MSan. However, it yields many false positives in the - # ctime_tests because many return values depend on secret (i.e., "uninitialized") values, and - # we're only interested in detecting branches (which count as "uses") on secret data. - if test x"$msan_enabled" = x"yes"; then - SECP_TRY_APPEND_CFLAGS([-fno-sanitize-memory-param-retval], SECP_CFLAGS) - print_msan_notice=yes - fi -fi - -if test x"$enable_coverage" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOVERAGE=1" - SECP_CFLAGS="-O0 --coverage $SECP_CFLAGS" - # If coverage is enabled, and the user has not overridden CFLAGS, - # override Autoconf's value "-g -O2" with "-g". Otherwise we'd end up - # with "-O0 --coverage -g -O2". - if test "$CFLAGS_overridden" = "no"; then - CFLAGS="-g" - fi - LDFLAGS="--coverage $LDFLAGS" -else - # Most likely the CFLAGS already contain -O2 because that is autoconf's default. - # We still add it here because passing it twice is not an issue, and handling - # this case would just add unnecessary complexity (see #896). - SECP_CFLAGS="-O2 $SECP_CFLAGS" -fi - -if test x"$req_asm" = x"auto"; then - SECP_X86_64_ASM_CHECK - if test x"$has_x86_64_asm" = x"yes"; then - set_asm=x86_64 - fi - if test x"$set_asm" = x; then - set_asm=no - fi -else - set_asm=$req_asm - case $set_asm in - x86_64) - SECP_X86_64_ASM_CHECK - if test x"$has_x86_64_asm" != x"yes"; then - AC_MSG_ERROR([x86_64 assembly requested but not available]) - fi - ;; - arm32) - SECP_ARM32_ASM_CHECK - if test x"$has_arm32_asm" != x"yes"; then - AC_MSG_ERROR([ARM32 assembly requested but not available]) - fi - ;; - no) - ;; - *) - AC_MSG_ERROR([invalid assembly selection]) - ;; - esac -fi - -# Select assembly -enable_external_asm=no - -case $set_asm in -x86_64) - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_ASM_X86_64=1" - ;; -arm32) - enable_external_asm=yes - ;; -no) - ;; -*) - AC_MSG_ERROR([invalid assembly selection]) - ;; -esac - -if test x"$enable_external_asm" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_EXTERNAL_ASM=1" -fi - - -# Select wide multiplication implementation -case $set_widemul in -int128_struct) - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_FORCE_WIDEMUL_INT128_STRUCT=1" - ;; -int128) - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_FORCE_WIDEMUL_INT128=1" - ;; -int64) - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_FORCE_WIDEMUL_INT64=1" - ;; -auto) - ;; -*) - AC_MSG_ERROR([invalid wide multiplication implementation]) - ;; -esac - -error_window_size=['window size for ecmult precomputation not an integer in range [2..24]'] -case $set_ecmult_window in -''|*[[!0-9]]*) - # no valid integer - AC_MSG_ERROR($error_window_size) - ;; -*) - if test "$set_ecmult_window" -lt 2 -o "$set_ecmult_window" -gt 24 ; then - # not in range - AC_MSG_ERROR($error_window_size) - fi - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DECMULT_WINDOW_SIZE=$set_ecmult_window" - ;; -esac - -case $set_ecmult_gen_kb in -2) - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOMB_BLOCKS=2 -DCOMB_TEETH=5" - ;; -22) - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOMB_BLOCKS=11 -DCOMB_TEETH=6" - ;; -86) - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOMB_BLOCKS=43 -DCOMB_TEETH=6" - ;; -*) - AC_MSG_ERROR(['ecmult gen table size not 2, 22 or 86']) - ;; -esac - -if test x"$enable_valgrind" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES $VALGRIND_CPPFLAGS -DVALGRIND" -fi - -# Add -Werror and similar flags passed from the outside (for testing, e.g., in CI). -# We don't want to set the user variable CFLAGS in CI because this would disable -# autoconf's logic for setting default CFLAGS, which we would like to test in CI. -SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS" - -### -### Handle module options -### - -# Processing must be done in a reverse topological sorting of the dependency graph -# (dependent module first). -if test x"$enable_module_ellswift" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1" -fi - -if test x"$enable_module_musig" = x"yes"; then - if test x"$enable_module_schnorrsig" = x"no"; then - AC_MSG_ERROR([Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the musig module.]) - fi - enable_module_schnorrsig=yes - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_MUSIG=1" -fi - -if test x"$enable_module_schnorrsig" = x"yes"; then - if test x"$enable_module_extrakeys" = x"no"; then - AC_MSG_ERROR([Module dependency error: You have disabled the extrakeys module explicitly, but it is required by the schnorrsig module.]) - fi - enable_module_extrakeys=yes - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_SCHNORRSIG=1" -fi - -if test x"$enable_module_extrakeys" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_EXTRAKEYS=1" -fi - -if test x"$enable_module_recovery" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_RECOVERY=1" -fi - -if test x"$enable_module_ecdh" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ECDH=1" -fi - -if test x"$enable_external_default_callbacks" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_EXTERNAL_DEFAULT_CALLBACKS=1" -fi - -### -### Check for --enable-experimental if necessary -### - -if test x"$enable_experimental" = x"no"; then - if test x"$set_asm" = x"arm32"; then - AC_MSG_ERROR([ARM32 assembly is experimental. Use --enable-experimental to allow.]) - fi -fi - -### -### Generate output -### - -AC_CONFIG_FILES([Makefile libsecp256k1.pc]) -AC_SUBST(SECP_CFLAGS) -AC_SUBST(SECP_CONFIG_DEFINES) -AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) -AM_CONDITIONAL([USE_TESTS], [test x"$enable_tests" != x"no"]) -AM_CONDITIONAL([USE_CTIME_TESTS], [test x"$enable_ctime_tests" = x"yes"]) -AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$enable_exhaustive_tests" != x"no"]) -AM_CONDITIONAL([USE_EXAMPLES], [test x"$enable_examples" != x"no"]) -AM_CONDITIONAL([USE_BENCHMARK], [test x"$enable_benchmark" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_MUSIG], [test x"$enable_module_musig" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"]) -AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"]) -AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"]) -AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"]) -AC_SUBST(LIB_VERSION_CURRENT, _LIB_VERSION_CURRENT) -AC_SUBST(LIB_VERSION_REVISION, _LIB_VERSION_REVISION) -AC_SUBST(LIB_VERSION_AGE, _LIB_VERSION_AGE) - -AC_OUTPUT - -echo -echo "Build Options:" -echo " with external callbacks = $enable_external_default_callbacks" -echo " with benchmarks = $enable_benchmark" -echo " with tests = $enable_tests" -echo " with ctime tests = $enable_ctime_tests" -echo " with coverage = $enable_coverage" -echo " with examples = $enable_examples" -echo " module ecdh = $enable_module_ecdh" -echo " module recovery = $enable_module_recovery" -echo " module extrakeys = $enable_module_extrakeys" -echo " module schnorrsig = $enable_module_schnorrsig" -echo " module musig = $enable_module_musig" -echo " module ellswift = $enable_module_ellswift" -echo -echo " asm = $set_asm" -echo " ecmult window size = $set_ecmult_window" -echo " ecmult gen table size = $set_ecmult_gen_kb KiB" -# Hide test-only options unless they're used. -if test x"$set_widemul" != xauto; then -echo " wide multiplication = $set_widemul" -fi -echo -echo " valgrind = $enable_valgrind" -echo " CC = $CC" -echo " CPPFLAGS = $CPPFLAGS" -echo " SECP_CFLAGS = $SECP_CFLAGS" -echo " CFLAGS = $CFLAGS" -echo " LDFLAGS = $LDFLAGS" - -if test x"$print_msan_notice" = x"yes"; then - echo - echo "Note:" - echo " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to SECP_CFLAGS" - echo " to avoid false positives in ctime_tests. Pass --disable-ctime-tests to avoid this." -fi - -if test x"$enable_experimental" = x"yes"; then - echo - echo "WARNING: Experimental build" - echo " Experimental features do not have stable APIs or properties, and may not be safe for" - echo " production use." -fi diff --git a/external/secp256k1/contrib/lax_der_parsing.c b/external/secp256k1/contrib/lax_der_parsing.c deleted file mode 100644 index bf562303ed..0000000000 --- a/external/secp256k1/contrib/lax_der_parsing.c +++ /dev/null @@ -1,148 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#include - -#include "lax_der_parsing.h" - -int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { - size_t rpos, rlen, spos, slen; - size_t pos = 0; - size_t lenbyte; - unsigned char tmpsig[64] = {0}; - int overflow = 0; - - /* Hack to initialize sig with a correctly-parsed but invalid signature. */ - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - - /* Sequence tag byte */ - if (pos == inputlen || input[pos] != 0x30) { - return 0; - } - pos++; - - /* Sequence length bytes */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (lenbyte > inputlen - pos) { - return 0; - } - pos += lenbyte; - } - - /* Integer tag byte for R */ - if (pos == inputlen || input[pos] != 0x02) { - return 0; - } - pos++; - - /* Integer length for R */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (lenbyte > inputlen - pos) { - return 0; - } - while (lenbyte > 0 && input[pos] == 0) { - pos++; - lenbyte--; - } - if (lenbyte >= sizeof(size_t)) { - return 0; - } - rlen = 0; - while (lenbyte > 0) { - rlen = (rlen << 8) + input[pos]; - pos++; - lenbyte--; - } - } else { - rlen = lenbyte; - } - if (rlen > inputlen - pos) { - return 0; - } - rpos = pos; - pos += rlen; - - /* Integer tag byte for S */ - if (pos == inputlen || input[pos] != 0x02) { - return 0; - } - pos++; - - /* Integer length for S */ - if (pos == inputlen) { - return 0; - } - lenbyte = input[pos++]; - if (lenbyte & 0x80) { - lenbyte -= 0x80; - if (lenbyte > inputlen - pos) { - return 0; - } - while (lenbyte > 0 && input[pos] == 0) { - pos++; - lenbyte--; - } - if (lenbyte >= sizeof(size_t)) { - return 0; - } - slen = 0; - while (lenbyte > 0) { - slen = (slen << 8) + input[pos]; - pos++; - lenbyte--; - } - } else { - slen = lenbyte; - } - if (slen > inputlen - pos) { - return 0; - } - spos = pos; - - /* Ignore leading zeroes in R */ - while (rlen > 0 && input[rpos] == 0) { - rlen--; - rpos++; - } - /* Copy R value */ - if (rlen > 32) { - overflow = 1; - } else if (rlen) { - memcpy(tmpsig + 32 - rlen, input + rpos, rlen); - } - - /* Ignore leading zeroes in S */ - while (slen > 0 && input[spos] == 0) { - slen--; - spos++; - } - /* Copy S value */ - if (slen > 32) { - overflow = 1; - } else if (slen) { - memcpy(tmpsig + 64 - slen, input + spos, slen); - } - - if (!overflow) { - overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - } - if (overflow) { - memset(tmpsig, 0, 64); - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); - } - return 1; -} - diff --git a/external/secp256k1/contrib/lax_der_parsing.h b/external/secp256k1/contrib/lax_der_parsing.h deleted file mode 100644 index 37c8c691f2..0000000000 --- a/external/secp256k1/contrib/lax_der_parsing.h +++ /dev/null @@ -1,97 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -/**** - * Please do not link this file directly. It is not part of the libsecp256k1 - * project and does not promise any stability in its API, functionality or - * presence. Projects which use this code should instead copy this header - * and its accompanying .c file directly into their codebase. - ****/ - -/* This file defines a function that parses DER with various errors and - * violations. This is not a part of the library itself, because the allowed - * violations are chosen arbitrarily and do not follow or establish any - * standard. - * - * In many places it matters that different implementations do not only accept - * the same set of valid signatures, but also reject the same set of signatures. - * The only means to accomplish that is by strictly obeying a standard, and not - * accepting anything else. - * - * Nonetheless, sometimes there is a need for compatibility with systems that - * use signatures which do not strictly obey DER. The snippet below shows how - * certain violations are easily supported. You may need to adapt it. - * - * Do not use this for new systems. Use well-defined DER or compact signatures - * instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and - * secp256k1_ecdsa_signature_parse_compact). - * - * The supported violations are: - * - All numbers are parsed as nonnegative integers, even though X.609-0207 - * section 8.3.3 specifies that integers are always encoded as two's - * complement. - * - Integers can have length 0, even though section 8.3.1 says they can't. - * - Integers with overly long padding are accepted, violation section - * 8.3.2. - * - 127-byte long length descriptors are accepted, even though section - * 8.1.3.5.c says that they are not. - * - Trailing garbage data inside or after the signature is ignored. - * - The length descriptor of the sequence is ignored. - * - * Compared to for example OpenSSL, many violations are NOT supported: - * - Using overly long tag descriptors for the sequence or integers inside, - * violating section 8.1.2.2. - * - Encoding primitive integers as constructed values, violating section - * 8.3.1. - */ - -#ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H -#define SECP256K1_CONTRIB_LAX_DER_PARSING_H - -/* #include secp256k1.h only when it hasn't been included yet. - This enables this file to be #included directly in other project - files (such as tests.c) without the need to set an explicit -I flag, - which would be necessary to locate secp256k1.h. */ -#ifndef SECP256K1_H -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** Parse a signature in "lax DER" format - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: pointer to a signature object - * In: input: pointer to the signature to be parsed - * inputlen: the length of the array pointed to be input - * - * This function will accept any valid DER encoded signature, even if the - * encoded numbers are out of range. In addition, it will accept signatures - * which violate the DER spec in various ways. Its purpose is to allow - * validation of the Bitcoin blockchain, which includes non-DER signatures - * from before the network rules were updated to enforce DER. Note that - * the set of supported violations is a strict subset of what OpenSSL will - * accept. - * - * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature validation with it is - * guaranteed to fail for every message and public key. - */ -int ecdsa_signature_parse_der_lax( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */ diff --git a/external/secp256k1/contrib/lax_der_privatekey_parsing.c b/external/secp256k1/contrib/lax_der_privatekey_parsing.c deleted file mode 100644 index a1b8200079..0000000000 --- a/external/secp256k1/contrib/lax_der_privatekey_parsing.c +++ /dev/null @@ -1,112 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014, 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#include - -#include "lax_der_privatekey_parsing.h" - -int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { - const unsigned char *end = privkey + privkeylen; - int lenb = 0; - int len = 0; - memset(out32, 0, 32); - /* sequence header */ - if (end < privkey+1 || *privkey != 0x30) { - return 0; - } - privkey++; - /* sequence length constructor */ - if (end < privkey+1 || !(*privkey & 0x80)) { - return 0; - } - lenb = *privkey & ~0x80; privkey++; - if (lenb < 1 || lenb > 2) { - return 0; - } - if (end < privkey+lenb) { - return 0; - } - /* sequence length */ - len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); - privkey += lenb; - if (end < privkey+len) { - return 0; - } - /* sequence element 0: version number (=1) */ - if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { - return 0; - } - privkey += 3; - /* sequence element 1: octet string, up to 32 bytes */ - if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { - return 0; - } - if (privkey[1]) memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); - if (!secp256k1_ec_seckey_verify(ctx, out32)) { - memset(out32, 0, 32); - return 0; - } - return 1; -} - -int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { - secp256k1_pubkey pubkey; - size_t pubkeylen = 0; - if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { - *privkeylen = 0; - return 0; - } - if (compressed) { - static const unsigned char begin[] = { - 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 - }; - static const unsigned char middle[] = { - 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, - 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, - 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, - 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 - }; - unsigned char *ptr = privkey; - memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - memcpy(ptr, key32, 32); ptr += 32; - memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = 33; - secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); - ptr += pubkeylen; - *privkeylen = ptr - privkey; - } else { - static const unsigned char begin[] = { - 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 - }; - static const unsigned char middle[] = { - 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, - 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, - 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, - 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, - 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, - 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, - 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 - }; - unsigned char *ptr = privkey; - memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - memcpy(ptr, key32, 32); ptr += 32; - memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); - pubkeylen = 65; - secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); - ptr += pubkeylen; - *privkeylen = ptr - privkey; - } - return 1; -} diff --git a/external/secp256k1/contrib/lax_der_privatekey_parsing.h b/external/secp256k1/contrib/lax_der_privatekey_parsing.h deleted file mode 100644 index 3749e418fe..0000000000 --- a/external/secp256k1/contrib/lax_der_privatekey_parsing.h +++ /dev/null @@ -1,95 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014, 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -/**** - * Please do not link this file directly. It is not part of the libsecp256k1 - * project and does not promise any stability in its API, functionality or - * presence. Projects which use this code should instead copy this header - * and its accompanying .c file directly into their codebase. - ****/ - -/* This file contains code snippets that parse DER private keys with - * various errors and violations. This is not a part of the library - * itself, because the allowed violations are chosen arbitrarily and - * do not follow or establish any standard. - * - * It also contains code to serialize private keys in a compatible - * manner. - * - * These functions are meant for compatibility with applications - * that require BER encoded keys. When working with secp256k1-specific - * code, the simple 32-byte private keys normally used by the - * library are sufficient. - */ - -#ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H -#define SECP256K1_CONTRIB_BER_PRIVATEKEY_H - -/* #include secp256k1.h only when it hasn't been included yet. - This enables this file to be #included directly in other project - files (such as tests.c) without the need to set an explicit -I flag, - which would be necessary to locate secp256k1.h. */ -#ifndef SECP256K1_H -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** Export a private key in DER format. - * - * Returns: 1 if the private key was valid. - * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: privkey: pointer to an array for storing the private key in BER. - * Should have space for 279 bytes, and cannot be NULL. - * privkeylen: Pointer to an int where the length of the private key in - * privkey will be stored. - * In: seckey: pointer to a 32-byte secret key to export. - * compressed: 1 if the key should be exported in - * compressed format, 0 otherwise - * - * This function is purely meant for compatibility with applications that - * require BER encoded keys. When working with secp256k1-specific code, the - * simple 32-byte private keys are sufficient. - * - * Note that this function does not guarantee correct DER output. It is - * guaranteed to be parsable by secp256k1_ec_privkey_import_der - */ -SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( - const secp256k1_context* ctx, - unsigned char *privkey, - size_t *privkeylen, - const unsigned char *seckey, - int compressed -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Import a private key in DER format. - * Returns: 1 if a private key was extracted. - * Args: ctx: pointer to a context object (cannot be NULL). - * Out: seckey: pointer to a 32-byte array for storing the private key. - * (cannot be NULL). - * In: privkey: pointer to a private key in DER format (cannot be NULL). - * privkeylen: length of the DER private key pointed to be privkey. - * - * This function will accept more than just strict DER, and even allow some BER - * violations. The public key stored inside the DER-encoded private key is not - * verified for correctness, nor are the curve parameters. Use this function - * only if you know in advance it is supposed to contain a secp256k1 private - * key. - */ -SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( - const secp256k1_context* ctx, - unsigned char *seckey, - const unsigned char *privkey, - size_t privkeylen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */ diff --git a/external/secp256k1/doc/ellswift.md b/external/secp256k1/doc/ellswift.md deleted file mode 100644 index 9d60e6be0b..0000000000 --- a/external/secp256k1/doc/ellswift.md +++ /dev/null @@ -1,483 +0,0 @@ -# ElligatorSwift for secp256k1 explained - -In this document we explain how the `ellswift` module implementation is related to the -construction in the -["SwiftEC: Shallue–van de Woestijne Indifferentiable Function To Elliptic Curves"](https://eprint.iacr.org/2022/759) -paper by Jorge Chávez-Saab, Francisco Rodríguez-Henríquez, and Mehdi Tibouchi. - -* [1. Introduction](#1-introduction) -* [2. The decoding function](#2-the-decoding-function) - + [2.1 Decoding for `secp256k1`](#21-decoding-for-secp256k1) -* [3. The encoding function](#3-the-encoding-function) - + [3.1 Switching to *v, w* coordinates](#31-switching-to-v-w-coordinates) - + [3.2 Avoiding computing all inverses](#32-avoiding-computing-all-inverses) - + [3.3 Finding the inverse](#33-finding-the-inverse) - + [3.4 Dealing with special cases](#34-dealing-with-special-cases) - + [3.5 Encoding for `secp256k1`](#35-encoding-for-secp256k1) -* [4. Encoding and decoding full *(x, y)* coordinates](#4-encoding-and-decoding-full-x-y-coordinates) - + [4.1 Full *(x, y)* coordinates for `secp256k1`](#41-full-x-y-coordinates-for-secp256k1) - -## 1. Introduction - -The `ellswift` module effectively introduces a new 64-byte public key format, with the property -that (uniformly random) public keys can be encoded as 64-byte arrays which are computationally -indistinguishable from uniform byte arrays. The module provides functions to convert public keys -from and to this format, as well as convenience functions for key generation and ECDH that operate -directly on ellswift-encoded keys. - -The encoding consists of the concatenation of two (32-byte big endian) encoded field elements $u$ -and $t.$ Together they encode an x-coordinate on the curve $x$, or (see further) a full point $(x, y)$ on -the curve. - -**Decoding** consists of decoding the field elements $u$ and $t$ (values above the field size $p$ -are taken modulo $p$), and then evaluating $F_u(t)$, which for every $u$ and $t$ results in a valid -x-coordinate on the curve. The functions $F_u$ will be defined in [Section 2](#2-the-decoding-function). - -**Encoding** a given $x$ coordinate is conceptually done as follows: -* Loop: - * Pick a uniformly random field element $u.$ - * Compute the set $L = F_u^{-1}(x)$ of $t$ values for which $F_u(t) = x$, which may have up to *8* elements. - * With probability $1 - \dfrac{\\#L}{8}$, restart the loop. - * Select a uniformly random $t \in L$ and return $(u, t).$ - -This is the *ElligatorSwift* algorithm, here given for just x-coordinates. An extension to full -$(x, y)$ points will be given in [Section 4](#4-encoding-and-decoding-full-x-y-coordinates). -The algorithm finds a uniformly random $(u, t)$ among (almost all) those -for which $F_u(t) = x.$ Section 3.2 in the paper proves that the number of such encodings for -almost all x-coordinates on the curve (all but at most 39) is close to two times the field size -(specifically, it lies in the range $2q \pm (22\sqrt{q} + O(1))$, where $q$ is the size of the field). - -## 2. The decoding function - -First some definitions: -* $\mathbb{F}$ is the finite field of size $q$, of characteristic 5 or more, and $q \equiv 1 \mod 3.$ - * For `secp256k1`, $q = 2^{256} - 2^{32} - 977$, which satisfies that requirement. -* Let $E$ be the elliptic curve of points $(x, y) \in \mathbb{F}^2$ for which $y^2 = x^3 + ax + b$, with $a$ and $b$ - public constants, for which $\Delta_E = -16(4a^3 + 27b^2)$ is a square, and at least one of $(-b \pm \sqrt{-3 \Delta_E} / 36)/2$ is a square. - This implies that the order of $E$ is either odd, or a multiple of *4*. - If $a=0$, this condition is always fulfilled. - * For `secp256k1`, $a=0$ and $b=7.$ -* Let the function $g(x) = x^3 + ax + b$, so the $E$ curve equation is also $y^2 = g(x).$ -* Let the function $h(x) = 3x^3 + 4a.$ -* Define $V$ as the set of solutions $(x_1, x_2, x_3, z)$ to $z^2 = g(x_1)g(x_2)g(x_3).$ -* Define $S_u$ as the set of solutions $(X, Y)$ to $X^2 + h(u)Y^2 = -g(u)$ and $Y \neq 0.$ -* $P_u$ is a function from $\mathbb{F}$ to $S_u$ that will be defined below. -* $\psi_u$ is a function from $S_u$ to $V$ that will be defined below. - -**Note**: In the paper: -* $F_u$ corresponds to $F_{0,u}$ there. -* $P_u(t)$ is called $P$ there. -* All $S_u$ sets together correspond to $S$ there. -* All $\psi_u$ functions together (operating on elements of $S$) correspond to $\psi$ there. - -Note that for $V$, the left hand side of the equation $z^2$ is square, and thus the right -hand must also be square. As multiplying non-squares results in a square in $\mathbb{F}$, -out of the three right-hand side factors an even number must be non-squares. -This implies that exactly *1* or exactly *3* out of -$\\{g(x_1), g(x_2), g(x_3)\\}$ must be square, and thus that for any $(x_1,x_2,x_3,z) \in V$, -at least one of $\\{x_1, x_2, x_3\\}$ must be a valid x-coordinate on $E.$ There is one exception -to this, namely when $z=0$, but even then one of the three values is a valid x-coordinate. - -**Define** the decoding function $F_u(t)$ as: -* Let $(x_1, x_2, x_3, z) = \psi_u(P_u(t)).$ -* Return the first element $x$ of $(x_3, x_2, x_1)$ which is a valid x-coordinate on $E$ (i.e., $g(x)$ is square). - -$P_u(t) = (X(u, t), Y(u, t))$, where: - -$$ -\begin{array}{lcl} -X(u, t) & = & \left\\{\begin{array}{ll} - \dfrac{g(u) - t^2}{2t} & a = 0 \\ - \dfrac{g(u) + h(u)(Y_0(u) - X_0(u)t)^2}{X_0(u)(1 + h(u)t^2)} & a \neq 0 -\end{array}\right. \\ -Y(u, t) & = & \left\\{\begin{array}{ll} - \dfrac{X(u, t) + t}{u \sqrt{-3}} = \dfrac{g(u) + t^2}{2tu\sqrt{-3}} & a = 0 \\ - Y_0(u) + t(X(u, t) - X_0(u)) & a \neq 0 -\end{array}\right. -\end{array} -$$ - -$P_u(t)$ is defined: -* For $a=0$, unless: - * $u = 0$ or $t = 0$ (division by zero) - * $g(u) = -t^2$ (would give $Y=0$). -* For $a \neq 0$, unless: - * $X_0(u) = 0$ or $h(u)t^2 = -1$ (division by zero) - * $Y_0(u) (1 - h(u)t^2) = 2X_0(u)t$ (would give $Y=0$). - -The functions $X_0(u)$ and $Y_0(u)$ are defined in Appendix A of the paper, and depend on various properties of $E.$ - -The function $\psi_u$ is the same for all curves: $\psi_u(X, Y) = (x_1, x_2, x_3, z)$, where: - -$$ -\begin{array}{lcl} - x_1 & = & \dfrac{X}{2Y} - \dfrac{u}{2} && \\ - x_2 & = & -\dfrac{X}{2Y} - \dfrac{u}{2} && \\ - x_3 & = & u + 4Y^2 && \\ - z & = & \dfrac{g(x_3)}{2Y}(u^2 + ux_1 + x_1^2 + a) = \dfrac{-g(u)g(x_3)}{8Y^3} -\end{array} -$$ - -### 2.1 Decoding for `secp256k1` - -Put together and specialized for $a=0$ curves, decoding $(u, t)$ to an x-coordinate is: - -**Define** $F_u(t)$ as: -* Let $X = \dfrac{u^3 + b - t^2}{2t}.$ -* Let $Y = \dfrac{X + t}{u\sqrt{-3}}.$ -* Return the first $x$ in $(u + 4Y^2, \dfrac{-X}{2Y} - \dfrac{u}{2}, \dfrac{X}{2Y} - \dfrac{u}{2})$ for which $g(x)$ is square. - -To make sure that every input decodes to a valid x-coordinate, we remap the inputs in case -$P_u$ is not defined (when $u=0$, $t=0$, or $g(u) = -t^2$): - -**Define** $F_u(t)$ as: -* Let $u'=u$ if $u \neq 0$; $1$ otherwise (guaranteeing $u' \neq 0$). -* Let $t'=t$ if $t \neq 0$; $1$ otherwise (guaranteeing $t' \neq 0$). -* Let $t''=t'$ if $g(u') \neq -t'^2$; $2t'$ otherwise (guaranteeing $t'' \neq 0$ and $g(u') \neq -t''^2$). -* Let $X = \dfrac{u'^3 + b - t''^2}{2t''}.$ -* Let $Y = \dfrac{X + t''}{u'\sqrt{-3}}.$ -* Return the first $x$ in $(u' + 4Y^2, \dfrac{-X}{2Y} - \dfrac{u'}{2}, \dfrac{X}{2Y} - \dfrac{u'}{2})$ for which $x^3 + b$ is square. - -The choices here are not strictly necessary. Just returning a fixed constant in any of the undefined cases would suffice, -but the approach here is simple enough and gives fairly uniform output even in these cases. - -**Note**: in the paper these conditions result in $\infty$ as output, due to the use of projective coordinates there. -We wish to avoid the need for callers to deal with this special case. - -This is implemented in `secp256k1_ellswift_xswiftec_frac_var` (which decodes to an x-coordinate represented as a fraction), and -in `secp256k1_ellswift_xswiftec_var` (which outputs the actual x-coordinate). - -## 3. The encoding function - -To implement $F_u^{-1}(x)$, the function to find the set of inverses $t$ for which $F_u(t) = x$, we have to reverse the process: -* Find all the $(X, Y) \in S_u$ that could have given rise to $x$, through the $x_1$, $x_2$, or $x_3$ formulas in $\psi_u.$ -* Map those $(X, Y)$ solutions to $t$ values using $P_u^{-1}(X, Y).$ -* For each of the found $t$ values, verify that $F_u(t) = x.$ -* Return the remaining $t$ values. - -The function $P_u^{-1}$, which finds $t$ given $(X, Y) \in S_u$, is significantly simpler than $P_u:$ - -$$ -P_u^{-1}(X, Y) = \left\\{\begin{array}{ll} -Yu\sqrt{-3} - X & a = 0 \\ -\dfrac{Y-Y_0(u)}{X-X_0(u)} & a \neq 0 \land X \neq X_0(u) \\ -\dfrac{-X_0(u)}{h(u)Y_0(u)} & a \neq 0 \land X = X_0(u) \land Y = Y_0(u) -\end{array}\right. -$$ - -The third step above, verifying that $F_u(t) = x$, is necessary because for the $(X, Y)$ values found through the $x_1$ and $x_2$ expressions, -it is possible that decoding through $\psi_u(X, Y)$ yields a valid $x_3$ on the curve, which would take precedence over the -$x_1$ or $x_2$ decoding. These $(X, Y)$ solutions must be rejected. - -Since we know that exactly one or exactly three out of $\\{x_1, x_2, x_3\\}$ are valid x-coordinates for any $t$, -the case where either $x_1$ or $x_2$ is valid and in addition also $x_3$ is valid must mean that all three are valid. -This means that instead of checking whether $x_3$ is on the curve, it is also possible to check whether the other one out of -$x_1$ and $x_2$ is on the curve. This is significantly simpler, as it turns out. - -Observe that $\psi_u$ guarantees that $x_1 + x_2 = -u.$ So given either $x = x_1$ or $x = x_2$, the other one of the two can be computed as -$-u - x.$ Thus, when encoding $x$ through the $x_1$ or $x_2$ expressions, one can simply check whether $g(-u-x)$ is a square, -and if so, not include the corresponding $t$ values in the returned set. As this does not need $X$, $Y$, or $t$, this condition can be determined -before those values are computed. - -It is not possible that an encoding found through the $x_1$ expression decodes to a different valid x-coordinate using $x_2$ (which would -take precedence), for the same reason: if both $x_1$ and $x_2$ decodings were valid, $x_3$ would be valid as well, and thus take -precedence over both. Because of this, the $g(-u-x)$ being square test for $x_1$ and $x_2$ is the only test necessary to guarantee the found $t$ -values round-trip back to the input $x$ correctly. This is the reason for choosing the $(x_3, x_2, x_1)$ precedence order in the decoder; -any order which does not place $x_3$ first requires more complicated round-trip checks in the encoder. - -### 3.1 Switching to *v, w* coordinates - -Before working out the formulas for all this, we switch to different variables for $S_u.$ Let $v = (X/Y - u)/2$, and -$w = 2Y.$ Or in the other direction, $X = w(u/2 + v)$ and $Y = w/2:$ -* $S_u'$ becomes the set of $(v, w)$ for which $w^2 (u^2 + uv + v^2 + a) = -g(u)$ and $w \neq 0.$ -* For $a=0$ curves, $P_u^{-1}$ can be stated for $(v,w)$ as $P_u^{'-1}(v, w) = w\left(\frac{\sqrt{-3}-1}{2}u - v\right).$ -* $\psi_u$ can be stated for $(v, w)$ as $\psi_u'(v, w) = (x_1, x_2, x_3, z)$, where - -$$ -\begin{array}{lcl} - x_1 & = & v \\ - x_2 & = & -u - v \\ - x_3 & = & u + w^2 \\ - z & = & \dfrac{g(x_3)}{w}(u^2 + uv + v^2 + a) = \dfrac{-g(u)g(x_3)}{w^3} -\end{array} -$$ - -We can now write the expressions for finding $(v, w)$ given $x$ explicitly, by solving each of the $\\{x_1, x_2, x_3\\}$ -expressions for $v$ or $w$, and using the $S_u'$ equation to find the other variable: -* Assuming $x = x_1$, we find $v = x$ and $w = \pm\sqrt{-g(u)/(u^2 + uv + v^2 + a)}$ (two solutions). -* Assuming $x = x_2$, we find $v = -u-x$ and $w = \pm\sqrt{-g(u)/(u^2 + uv + v^2 + a)}$ (two solutions). -* Assuming $x = x_3$, we find $w = \pm\sqrt{x-u}$ and $v = -u/2 \pm \sqrt{-w^2(4g(u) + w^2h(u))}/(2w^2)$ (four solutions). - -### 3.2 Avoiding computing all inverses - -The *ElligatorSwift* algorithm as stated in Section 1 requires the computation of $L = F_u^{-1}(x)$ (the -set of all $t$ such that $(u, t)$ decode to $x$) in full. This is unnecessary. - -Observe that the procedure of restarting with probability $(1 - \frac{\\#L}{8})$ and otherwise returning a -uniformly random element from $L$ is actually equivalent to always padding $L$ with $\bot$ values up to length 8, -picking a uniformly random element from that, restarting whenever $\bot$ is picked: - -**Define** *ElligatorSwift(x)* as: -* Loop: - * Pick a uniformly random field element $u.$ - * Compute the set $L = F_u^{-1}(x).$ - * Let $T$ be the 8-element vector consisting of the elements of $L$, plus $8 - \\#L$ times $\\{\bot\\}.$ - * Select a uniformly random $t \in T.$ - * If $t \neq \bot$, return $(u, t)$; restart loop otherwise. - -Now notice that the order of elements in $T$ does not matter, as all we do is pick a uniformly -random element in it, so we do not need to have all $\bot$ values at the end. -As we have 8 distinct formulas for finding $(v, w)$ (taking the variants due to $\pm$ into account), -we can associate every index in $T$ with exactly one of those formulas, making sure that: -* Formulas that yield no solutions (due to division by zero or non-existing square roots) or invalid solutions are made to return $\bot.$ -* For the $x_1$ and $x_2$ cases, if $g(-u-x)$ is a square, $\bot$ is returned instead (the round-trip check). -* In case multiple formulas would return the same non- $\bot$ result, all but one of those must be turned into $\bot$ to avoid biasing those. - -The last condition above only occurs with negligible probability for cryptographically-sized curves, but is interesting -to take into account as it allows exhaustive testing in small groups. See [Section 3.4](#34-dealing-with-special-cases) -for an analysis of all the negligible cases. - -If we define $T = (G_{0,u}(x), G_{1,u}(x), \ldots, G_{7,u}(x))$, with each $G_{i,u}$ matching one of the formulas, -the loop can be simplified to only compute one of the inverses instead of all of them: - -**Define** *ElligatorSwift(x)* as: -* Loop: - * Pick a uniformly random field element $u.$ - * Pick a uniformly random integer $c$ in $[0,8).$ - * Let $t = G_{c,u}(x).$ - * If $t \neq \bot$, return $(u, t)$; restart loop otherwise. - -This is implemented in `secp256k1_ellswift_xelligatorswift_var`. - -### 3.3 Finding the inverse - -To implement $G_{c,u}$, we map $c=0$ to the $x_1$ formula, $c=1$ to the $x_2$ formula, and $c=2$ and $c=3$ to the $x_3$ formula. -Those are then repeated as $c=4$ through $c=7$ for the other sign of $w$ (noting that in each formula, $w$ is a square root of some expression). -Ignoring the negligible cases, we get: - -**Define** $G_{c,u}(x)$ as: -* If $c \in \\{0, 1, 4, 5\\}$ (for $x_1$ and $x_2$ formulas): - * If $g(-u-x)$ is square, return $\bot$ (as $x_3$ would be valid and take precedence). - * If $c \in \\{0, 4\\}$ (the $x_1$ formula) let $v = x$, otherwise let $v = -u-x$ (the $x_2$ formula) - * Let $s = -g(u)/(u^2 + uv + v^2 + a)$ (using $s = w^2$ in what follows). -* Otherwise, when $c \in \\{2, 3, 6, 7\\}$ (for $x_3$ formulas): - * Let $s = x-u.$ - * Let $r = \sqrt{-s(4g(u) + sh(u))}.$ - * Let $v = (r/s - u)/2$ if $c \in \\{3, 7\\}$; $(-r/s - u)/2$ otherwise. -* Let $w = \sqrt{s}.$ -* Depending on $c:$ - * If $c \in \\{0, 1, 2, 3\\}:$ return $P_u^{'-1}(v, w).$ - * If $c \in \\{4, 5, 6, 7\\}:$ return $P_u^{'-1}(v, -w).$ - -Whenever a square root of a non-square is taken, $\bot$ is returned; for both square roots this happens with roughly -50% on random inputs. Similarly, when a division by 0 would occur, $\bot$ is returned as well; this will only happen -with negligible probability. A division by 0 in the first branch in fact cannot occur at all, because $u^2 + uv + v^2 + a = 0$ -implies $g(-u-x) = g(x)$ which would mean the $g(-u-x)$ is square condition has triggered -and $\bot$ would have been returned already. - -**Note**: In the paper, the $case$ variable corresponds roughly to the $c$ above, but only takes on 4 possible values (1 to 4). -The conditional negation of $w$ at the end is done randomly, which is equivalent, but makes testing harder. We choose to -have the $G_{c,u}$ be deterministic, and capture all choices in $c.$ - -Now observe that the $c \in \\{1, 5\\}$ and $c \in \\{3, 7\\}$ conditions effectively perform the same $v \rightarrow -u-v$ -transformation. Furthermore, that transformation has no effect on $s$ in the first branch -as $u^2 + ux + x^2 + a = u^2 + u(-u-x) + (-u-x)^2 + a.$ Thus we can extract it out and move it down: - -**Define** $G_{c,u}(x)$ as: -* If $c \in \\{0, 1, 4, 5\\}:$ - * If $g(-u-x)$ is square, return $\bot.$ - * Let $s = -g(u)/(u^2 + ux + x^2 + a).$ - * Let $v = x.$ -* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$ - * Let $s = x-u.$ - * Let $r = \sqrt{-s(4g(u) + sh(u))}.$ - * Let $v = (r/s - u)/2.$ -* Let $w = \sqrt{s}.$ -* Depending on $c:$ - * If $c \in \\{0, 2\\}:$ return $P_u^{'-1}(v, w).$ - * If $c \in \\{1, 3\\}:$ return $P_u^{'-1}(-u-v, w).$ - * If $c \in \\{4, 6\\}:$ return $P_u^{'-1}(v, -w).$ - * If $c \in \\{5, 7\\}:$ return $P_u^{'-1}(-u-v, -w).$ - -This shows there will always be exactly 0, 4, or 8 $t$ values for a given $(u, x)$ input. -There can be 0, 1, or 2 $(v, w)$ pairs before invoking $P_u^{'-1}$, and each results in 4 distinct $t$ values. - -### 3.4 Dealing with special cases - -As mentioned before there are a few cases to deal with which only happen in a negligibly small subset of inputs. -For cryptographically sized fields, if only random inputs are going to be considered, it is unnecessary to deal with these. Still, for completeness -we analyse them here. They generally fall into two categories: cases in which the encoder would produce $t$ values that -do not decode back to $x$ (or at least cannot guarantee that they do), and cases in which the encoder might produce the same -$t$ value for multiple $c$ inputs (thereby biasing that encoding): - -* In the branch for $x_1$ and $x_2$ (where $c \in \\{0, 1, 4, 5\\}$): - * When $g(u) = 0$, we would have $s=w=Y=0$, which is not on $S_u.$ This is only possible on even-ordered curves. - Excluding this also removes the one condition under which the simplified check for $x_3$ on the curve - fails (namely when $g(x_1)=g(x_2)=0$ but $g(x_3)$ is not square). - This does exclude some valid encodings: when both $g(u)=0$ and $u^2+ux+x^2+a=0$ (also implying $g(x)=0$), - the $S_u'$ equation degenerates to $0 = 0$, and many valid $t$ values may exist. Yet, these cannot be targeted uniformly by the - encoder anyway as there will generally be more than 8. - * When $g(x) = 0$, the same $t$ would be produced as in the $x_3$ branch (where $c \in \\{2, 3, 6, 7\\}$) which we give precedence - as it can deal with $g(u)=0$. - This is again only possible on even-ordered curves. -* In the branch for $x_3$ (where $c \in \\{2, 3, 6, 7\\}$): - * When $s=0$, a division by zero would occur. - * When $v = -u-v$ and $c \in \\{3, 7\\}$, the same $t$ would be returned as in the $c \in \\{2, 6\\}$ cases. - It is equivalent to checking whether $r=0$. - This cannot occur in the $x_1$ or $x_2$ branches, as it would trigger the $g(-u-x)$ is square condition. - A similar concern for $w = -w$ does not exist, as $w=0$ is already impossible in both branches: in the first - it requires $g(u)=0$ which is already outlawed on even-ordered curves and impossible on others; in the second it would trigger division by zero. -* Curve-specific special cases also exist that need to be rejected, because they result in $(u,t)$ which is invalid to the decoder, or because of division by zero in the encoder: - * For $a=0$ curves, when $u=0$ or when $t=0$. The latter can only be reached by the encoder when $g(u)=0$, which requires an even-ordered curve. - * For $a \neq 0$ curves, when $X_0(u)=0$, when $h(u)t^2 = -1$, or when $w(u + 2v) = 2X_0(u)$ while also either $w \neq 2Y_0(u)$ or $h(u)=0$. - -**Define** a version of $G_{c,u}(x)$ which deals with all these cases: -* If $a=0$ and $u=0$, return $\bot.$ -* If $a \neq 0$ and $X_0(u)=0$, return $\bot.$ -* If $c \in \\{0, 1, 4, 5\\}:$ - * If $g(u) = 0$ or $g(x) = 0$, return $\bot$ (even curves only). - * If $g(-u-x)$ is square, return $\bot.$ - * Let $s = -g(u)/(u^2 + ux + x^2 + a)$ (cannot cause division by zero). - * Let $v = x.$ -* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$ - * Let $s = x-u.$ - * Let $r = \sqrt{-s(4g(u) + sh(u))}$; return $\bot$ if not square. - * If $c \in \\{3, 7\\}$ and $r=0$, return $\bot.$ - * If $s = 0$, return $\bot.$ - * Let $v = (r/s - u)/2.$ -* Let $w = \sqrt{s}$; return $\bot$ if not square. -* If $a \neq 0$ and $w(u+2v) = 2X_0(u)$ and either $w \neq 2Y_0(u)$ or $h(u) = 0$, return $\bot.$ -* Depending on $c:$ - * If $c \in \\{0, 2\\}$, let $t = P_u^{'-1}(v, w).$ - * If $c \in \\{1, 3\\}$, let $t = P_u^{'-1}(-u-v, w).$ - * If $c \in \\{4, 6\\}$, let $t = P_u^{'-1}(v, -w).$ - * If $c \in \\{5, 7\\}$, let $t = P_u^{'-1}(-u-v, -w).$ -* If $a=0$ and $t=0$, return $\bot$ (even curves only). -* If $a \neq 0$ and $h(u)t^2 = -1$, return $\bot.$ -* Return $t.$ - -Given any $u$, using this algorithm over all $x$ and $c$ values, every $t$ value will be reached exactly once, -for an $x$ for which $F_u(t) = x$ holds, except for these cases that will not be reached: -* All cases where $P_u(t)$ is not defined: - * For $a=0$ curves, when $u=0$, $t=0$, or $g(u) = -t^2.$ - * For $a \neq 0$ curves, when $h(u)t^2 = -1$, $X_0(u) = 0$, or $Y_0(u) (1 - h(u) t^2) = 2X_0(u)t.$ -* When $g(u)=0$, the potentially many $t$ values that decode to an $x$ satisfying $g(x)=0$ using the $x_2$ formula. These were excluded by the $g(u)=0$ condition in the $c \in \\{0, 1, 4, 5\\}$ branch. - -These cases form a negligible subset of all $(u, t)$ for cryptographically sized curves. - -### 3.5 Encoding for `secp256k1` - -Specialized for odd-ordered $a=0$ curves: - -**Define** $G_{c,u}(x)$ as: -* If $u=0$, return $\bot.$ -* If $c \in \\{0, 1, 4, 5\\}:$ - * If $(-u-x)^3 + b$ is square, return $\bot$ - * Let $s = -(u^3 + b)/(u^2 + ux + x^2)$ (cannot cause division by 0). - * Let $v = x.$ -* Otherwise, when $c \in \\{2, 3, 6, 7\\}:$ - * Let $s = x-u.$ - * Let $r = \sqrt{-s(4(u^3 + b) + 3su^2)}$; return $\bot$ if not square. - * If $c \in \\{3, 7\\}$ and $r=0$, return $\bot.$ - * If $s = 0$, return $\bot.$ - * Let $v = (r/s - u)/2.$ -* Let $w = \sqrt{s}$; return $\bot$ if not square. -* Depending on $c:$ - * If $c \in \\{0, 2\\}:$ return $w(\frac{\sqrt{-3}-1}{2}u - v).$ - * If $c \in \\{1, 3\\}:$ return $w(\frac{\sqrt{-3}+1}{2}u + v).$ - * If $c \in \\{4, 6\\}:$ return $w(\frac{-\sqrt{-3}+1}{2}u + v).$ - * If $c \in \\{5, 7\\}:$ return $w(\frac{-\sqrt{-3}-1}{2}u - v).$ - -This is implemented in `secp256k1_ellswift_xswiftec_inv_var`. - -And the x-only ElligatorSwift encoding algorithm is still: - -**Define** *ElligatorSwift(x)* as: -* Loop: - * Pick a uniformly random field element $u.$ - * Pick a uniformly random integer $c$ in $[0,8).$ - * Let $t = G_{c,u}(x).$ - * If $t \neq \bot$, return $(u, t)$; restart loop otherwise. - -Note that this logic does not take the remapped $u=0$, $t=0$, and $g(u) = -t^2$ cases into account; it just avoids them. -While it is not impossible to make the encoder target them, this would increase the maximum number of $t$ values for a given $(u, x)$ -combination beyond 8, and thereby slow down the ElligatorSwift loop proportionally, for a negligible gain in uniformity. - -## 4. Encoding and decoding full *(x, y)* coordinates - -So far we have only addressed encoding and decoding x-coordinates, but in some cases an encoding -for full points with $(x, y)$ coordinates is desirable. It is possible to encode this information -in $t$ as well. - -Note that for any $(X, Y) \in S_u$, $(\pm X, \pm Y)$ are all on $S_u.$ Moreover, all of these are -mapped to the same x-coordinate. Negating $X$ or negating $Y$ just results in $x_1$ and $x_2$ -being swapped, and does not affect $x_3.$ This will not change the outcome x-coordinate as the order -of $x_1$ and $x_2$ only matters if both were to be valid, and in that case $x_3$ would be used instead. - -Still, these four $(X, Y)$ combinations all correspond to distinct $t$ values, so we can encode -the sign of the y-coordinate in the sign of $X$ or the sign of $Y.$ They correspond to the -four distinct $P_u^{'-1}$ calls in the definition of $G_{u,c}.$ - -**Note**: In the paper, the sign of the y coordinate is encoded in a separately-coded bit. - -To encode the sign of $y$ in the sign of $Y:$ - -**Define** *Decode(u, t)* for full $(x, y)$ as: -* Let $(X, Y) = P_u(t).$ -* Let $x$ be the first value in $(u + 4Y^2, \frac{-X}{2Y} - \frac{u}{2}, \frac{X}{2Y} - \frac{u}{2})$ for which $g(x)$ is square. -* Let $y = \sqrt{g(x)}.$ -* If $sign(y) = sign(Y)$, return $(x, y)$; otherwise return $(x, -y).$ - -And encoding would be done using a $G_{c,u}(x, y)$ function defined as: - -**Define** $G_{c,u}(x, y)$ as: -* If $c \in \\{0, 1\\}:$ - * If $g(u) = 0$ or $g(x) = 0$, return $\bot$ (even curves only). - * If $g(-u-x)$ is square, return $\bot.$ - * Let $s = -g(u)/(u^2 + ux + x^2 + a)$ (cannot cause division by zero). - * Let $v = x.$ -* Otherwise, when $c \in \\{2, 3\\}:$ - * Let $s = x-u.$ - * Let $r = \sqrt{-s(4g(u) + sh(u))}$; return $\bot$ if not square. - * If $c = 3$ and $r = 0$, return $\bot.$ - * Let $v = (r/s - u)/2.$ -* Let $w = \sqrt{s}$; return $\bot$ if not square. -* Let $w' = w$ if $sign(w/2) = sign(y)$; $-w$ otherwise. -* Depending on $c:$ - * If $c \in \\{0, 2\\}:$ return $P_u^{'-1}(v, w').$ - * If $c \in \\{1, 3\\}:$ return $P_u^{'-1}(-u-v, w').$ - -Note that $c$ now only ranges $[0,4)$, as the sign of $w'$ is decided based on that of $y$, rather than on $c.$ -This change makes some valid encodings unreachable: when $y = 0$ and $sign(Y) \neq sign(0)$. - -In the above logic, $sign$ can be implemented in several ways, such as parity of the integer representation -of the input field element (for prime-sized fields) or the quadratic residuosity (for fields where -$-1$ is not square). The choice does not matter, as long as it only takes on two possible values, and for $x \neq 0$ it holds that $sign(x) \neq sign(-x)$. - -### 4.1 Full *(x, y)* coordinates for `secp256k1` - -For $a=0$ curves, there is another option. Note that for those, -the $P_u(t)$ function translates negations of $t$ to negations of (both) $X$ and $Y.$ Thus, we can use $sign(t)$ to -encode the y-coordinate directly. Combined with the earlier remapping to guarantee all inputs land on the curve, we get -as decoder: - -**Define** *Decode(u, t)* as: -* Let $u'=u$ if $u \neq 0$; $1$ otherwise. -* Let $t'=t$ if $t \neq 0$; $1$ otherwise. -* Let $t''=t'$ if $u'^3 + b + t'^2 \neq 0$; $2t'$ otherwise. -* Let $X = \dfrac{u'^3 + b - t''^2}{2t''}.$ -* Let $Y = \dfrac{X + t''}{u'\sqrt{-3}}.$ -* Let $x$ be the first element of $(u' + 4Y^2, \frac{-X}{2Y} - \frac{u'}{2}, \frac{X}{2Y} - \frac{u'}{2})$ for which $g(x)$ is square. -* Let $y = \sqrt{g(x)}.$ -* Return $(x, y)$ if $sign(y) = sign(t)$; $(x, -y)$ otherwise. - -This is implemented in `secp256k1_ellswift_swiftec_var`. The used $sign(x)$ function is the parity of $x$ when represented as in integer in $[0,q).$ - -The corresponding encoder would invoke the x-only one, but negating the output $t$ if $sign(t) \neq sign(y).$ - -This is implemented in `secp256k1_ellswift_elligatorswift_var`. - -Note that this is only intended for encoding points where both the x-coordinate and y-coordinate are unpredictable. When encoding x-only points -where the y-coordinate is implicitly even (or implicitly square, or implicitly in $[0,q/2]$), the encoder in -[Section 3.5](#35-encoding-for-secp256k1) must be used, or a bias is reintroduced that undoes all the benefit of using ElligatorSwift -in the first place. diff --git a/external/secp256k1/doc/musig.md b/external/secp256k1/doc/musig.md deleted file mode 100644 index ae21f9b131..0000000000 --- a/external/secp256k1/doc/musig.md +++ /dev/null @@ -1,54 +0,0 @@ -Notes on the musig module API -=========================== - -The following sections contain additional notes on the API of the musig module (`include/secp256k1_musig.h`). -A usage example can be found in `examples/musig.c`. - -## API misuse - -The musig API is designed with a focus on misuse resistance. -However, due to the interactive nature of the MuSig protocol, there are additional failure modes that are not present in regular (single-party) Schnorr signature creation. -While the results can be catastrophic (e.g. leaking of the secret key), it is unfortunately not possible for the musig implementation to prevent all such failure modes. - -Therefore, users of the musig module must take great care to make sure of the following: - -1. A unique nonce per signing session is generated in `secp256k1_musig_nonce_gen`. - See the corresponding comment in `include/secp256k1_musig.h` for how to ensure that. -2. The `secp256k1_musig_secnonce` structure is never copied or serialized. - See also the comment on `secp256k1_musig_secnonce` in `include/secp256k1_musig.h`. -3. Opaque data structures are never written to or read from directly. - Instead, only the provided accessor functions are used. - -## Key Aggregation and (Taproot) Tweaking - -Given a set of public keys, the aggregate public key is computed with `secp256k1_musig_pubkey_agg`. -A plain tweak can be added to the resulting public key with `secp256k1_ec_pubkey_tweak_add` by setting the `tweak32` argument to the hash defined in BIP 32. Similarly, a Taproot tweak can be added with `secp256k1_xonly_pubkey_tweak_add` by setting the `tweak32` argument to the TapTweak hash defined in BIP 341. -Both types of tweaking can be combined and invoked multiple times if the specific application requires it. - -## Signing - -This is covered by `examples/musig.c`. -Essentially, the protocol proceeds in the following steps: - -1. Generate a keypair with `secp256k1_keypair_create` and obtain the public key with `secp256k1_keypair_pub`. -2. Call `secp256k1_musig_pubkey_agg` with the pubkeys of all participants. -3. Optionally add a (Taproot) tweak with `secp256k1_musig_pubkey_xonly_tweak_add` and a plain tweak with `secp256k1_musig_pubkey_ec_tweak_add`. -4. Generate a pair of secret and public nonce with `secp256k1_musig_nonce_gen` and send the public nonce to the other signers. -5. Someone (not necessarily the signer) aggregates the public nonces with `secp256k1_musig_nonce_agg` and sends it to the signers. -6. Process the aggregate nonce with `secp256k1_musig_nonce_process`. -7. Create a partial signature with `secp256k1_musig_partial_sign`. -8. Verify the partial signatures (optional in some scenarios) with `secp256k1_musig_partial_sig_verify`. -9. Someone (not necessarily the signer) obtains all partial signatures and aggregates them into the final Schnorr signature using `secp256k1_musig_partial_sig_agg`. - -The aggregate signature can be verified with `secp256k1_schnorrsig_verify`. - -Steps 1 through 5 above can occur before or after the signers are aware of the message to be signed. -Whenever possible, it is recommended to generate the nonces only after the message is known. -This provides enhanced defense-in-depth measures, protecting against potential API misuse in certain scenarios. -However, it does require two rounds of communication during the signing process. -The alternative, generating the nonces in a pre-processing step before the message is known, eliminates these additional protective measures but allows for non-interactive signing. -Similarly, the API supports an alternative protocol flow where generating the aggregate key (steps 1 to 3) is allowed to happen after exchanging nonces (steps 4 to 5). - -## Verification - -A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7. diff --git a/external/secp256k1/doc/release-process.md b/external/secp256k1/doc/release-process.md deleted file mode 100644 index a64bae0f0d..0000000000 --- a/external/secp256k1/doc/release-process.md +++ /dev/null @@ -1,94 +0,0 @@ -# Release process - -This document outlines the process for releasing versions of the form `$MAJOR.$MINOR.$PATCH`. - -We distinguish between two types of releases: *regular* and *maintenance* releases. -Regular releases are releases of a new major or minor version as well as patches of the most recent release. -Maintenance releases, on the other hand, are required for patches of older releases. - -You should coordinate with the other maintainers on the release date, if possible. -This date will be part of the release entry in [CHANGELOG.md](../CHANGELOG.md) and it should match the dates of the remaining steps in the release process (including the date of the tag and the GitHub release). -It is best if the maintainers are present during the release, so they can help ensure that the process is followed correctly and, in the case of a regular release, they are aware that they should not modify the master branch between merging the PR in step 1 and the PR in step 3. - -This process also assumes that there will be no minor releases for old major releases. - -We aim to cut a regular release every 3-4 months, approximately twice as frequent as major Bitcoin Core releases. Every second release should be published one month before the feature freeze of the next major Bitcoin Core release, allowing sufficient time to update the library in Core. - -## Sanity checks -Perform these checks when reviewing the release PR (see below): - -1. Ensure `make distcheck` doesn't fail. - ```shell - ./autogen.sh && ./configure --enable-dev-mode && make distcheck - ``` -2. Check installation with autotools: - ```shell - dir=$(mktemp -d) - ./autogen.sh && ./configure --prefix=$dir && make clean && make install && ls -RlAh $dir - gcc -o ecdsa examples/ecdsa.c $(PKG_CONFIG_PATH=$dir/lib/pkgconfig pkg-config --cflags --libs libsecp256k1) -Wl,-rpath,"$dir/lib" && ./ecdsa - ``` -3. Check installation with CMake: - ```shell - dir=$(mktemp -d) - build=$(mktemp -d) - cmake -B $build -DCMAKE_INSTALL_PREFIX=$dir && cmake --build $build && cmake --install $build && ls -RlAh $dir - gcc -o ecdsa examples/ecdsa.c -I $dir/include -L $dir/lib*/ -l secp256k1 -Wl,-rpath,"$dir/lib",-rpath,"$dir/lib64" && ./ecdsa - ``` -4. Use the [`check-abi.sh`](/tools/check-abi.sh) tool to verify that there are no unexpected ABI incompatibilities and that the version number and the release notes accurately reflect all potential ABI changes. To run this tool, the `abi-dumper` and `abi-compliance-checker` packages are required. - ```shell - tools/check-abi.sh - ``` - -## Regular release - -1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that - * finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) by - * adding a section for the release (make sure that the version number is a link to a diff between the previous and new version), - * removing the `[Unreleased]` section header, - * ensuring that the release notes are not missing entries (check the `needs-changelog` label on github), and - * including an entry for `### ABI Compatibility` if it doesn't exist, - * sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and, - * if this is not a patch release, - * updates `_PKG_VERSION_*` and `_LIB_VERSION_*` in `configure.ac`, and - * updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`. -2. Perform the [sanity checks](#sanity-checks) on the PR branch. -3. After the PR is merged, tag the commit, and push the tag: - ``` - RELEASE_COMMIT= - git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH" $RELEASE_COMMIT - git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH - ``` -4. Open a PR to the master branch with a commit (using message `"release cleanup: bump version after $MAJOR.$MINOR.$PATCH"`, for example) that - * sets `_PKG_VERSION_IS_RELEASE` to `false` and increments `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac`, - * increments the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt`, and - * adds an `[Unreleased]` section header to the [CHANGELOG.md](../CHANGELOG.md). - - If other maintainers are not present to approve the PR, it can be merged without ACKs. -5. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). -6. Send an announcement email to the bitcoin-dev mailing list. - -## Maintenance release - -Note that bug fixes need to be backported only to releases for which no compatible release without the bug exists. - -1. If there's no maintenance branch `$MAJOR.$MINOR`, create one: - ``` - git checkout -b $MAJOR.$MINOR v$MAJOR.$MINOR.$((PATCH - 1)) - git push git@github.com:bitcoin-core/secp256k1.git $MAJOR.$MINOR - ``` -2. Open a pull request to the `$MAJOR.$MINOR` branch that - * includes the bug fixes, - * finalizes the release notes similar to a regular release, - * increments `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac` - and the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt` - (with commit message `"release: bump versions for $MAJOR.$MINOR.$PATCH"`, for example). -3. Perform the [sanity checks](#sanity-checks) on the PR branch. -4. After the PRs are merged, update the release branch, tag the commit, and push the tag: - ``` - git checkout $MAJOR.$MINOR && git pull - git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH" - git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH - ``` -6. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). -7. Send an announcement email to the bitcoin-dev mailing list. -8. Open PR to the master branch that includes a commit (with commit message `"release notes: add $MAJOR.$MINOR.$PATCH"`, for example) that adds release notes to [CHANGELOG.md](../CHANGELOG.md). diff --git a/external/secp256k1/doc/safegcd_implementation.md b/external/secp256k1/doc/safegcd_implementation.md deleted file mode 100644 index 5dbbb7bbd2..0000000000 --- a/external/secp256k1/doc/safegcd_implementation.md +++ /dev/null @@ -1,819 +0,0 @@ -# The safegcd implementation in libsecp256k1 explained - -This document explains the modular inverse and Jacobi symbol implementations in the `src/modinv*.h` files. -It is based on the paper -["Fast constant-time gcd computation and modular inversion"](https://gcd.cr.yp.to/papers.html#safegcd) -by Daniel J. Bernstein and Bo-Yin Yang. The references below are for the Date: 2019.04.13 version. - -The actual implementation is in C of course, but for demonstration purposes Python3 is used here. -Most implementation aspects and optimizations are explained, except those that depend on the specific -number representation used in the C code. - -## 1. Computing the Greatest Common Divisor (GCD) using divsteps - -The algorithm from the paper (section 11), at a very high level, is this: - -```python -def gcd(f, g): - """Compute the GCD of an odd integer f and another integer g.""" - assert f & 1 # require f to be odd - delta = 1 # additional state variable - while g != 0: - assert f & 1 # f will be odd in every iteration - if delta > 0 and g & 1: - delta, f, g = 1 - delta, g, (g - f) // 2 - elif g & 1: - delta, f, g = 1 + delta, f, (g + f) // 2 - else: - delta, f, g = 1 + delta, f, (g ) // 2 - return abs(f) -``` - -It computes the greatest common divisor of an odd integer *f* and any integer *g*. Its inner loop -keeps rewriting the variables *f* and *g* alongside a state variable *δ* that starts at *1*, until -*g=0* is reached. At that point, *|f|* gives the GCD. Each of the transitions in the loop is called a -"division step" (referred to as divstep in what follows). - -For example, *gcd(21, 14)* would be computed as: -- Start with *δ=1 f=21 g=14* -- Take the third branch: *δ=2 f=21 g=7* -- Take the first branch: *δ=-1 f=7 g=-7* -- Take the second branch: *δ=0 f=7 g=0* -- The answer *|f| = 7*. - -Why it works: -- Divsteps can be decomposed into two steps (see paragraph 8.2 in the paper): - - (a) If *g* is odd, replace *(f,g)* with *(g,g-f)* or (f,g+f), resulting in an even *g*. - - (b) Replace *(f,g)* with *(f,g/2)* (where *g* is guaranteed to be even). -- Neither of those two operations change the GCD: - - For (a), assume *gcd(f,g)=c*, then it must be the case that *f=a c* and *g=b c* for some integers *a* - and *b*. As *(g,g-f)=(b c,(b-a)c)* and *(f,f+g)=(a c,(a+b)c)*, the result clearly still has - common factor *c*. Reasoning in the other direction shows that no common factor can be added by - doing so either. - - For (b), we know that *f* is odd, so *gcd(f,g)* clearly has no factor *2*, and we can remove - it from *g*. -- The algorithm will eventually converge to *g=0*. This is proven in the paper (see theorem G.3). -- It follows that eventually we find a final value *f'* for which *gcd(f,g) = gcd(f',0)*. As the - gcd of *f'* and *0* is *|f'|* by definition, that is our answer. - -Compared to more [traditional GCD algorithms](https://en.wikipedia.org/wiki/Euclidean_algorithm), this one has the property of only ever looking at -the low-order bits of the variables to decide the next steps, and being easy to make -constant-time (in more low-level languages than Python). The *δ* parameter is necessary to -guide the algorithm towards shrinking the numbers' magnitudes without explicitly needing to look -at high order bits. - -Properties that will become important later: -- Performing more divsteps than needed is not a problem, as *f* does not change anymore after *g=0*. -- Only even numbers are divided by *2*. This means that when reasoning about it algebraically we - do not need to worry about rounding. -- At every point during the algorithm's execution the next *N* steps only depend on the bottom *N* - bits of *f* and *g*, and on *δ*. - - -## 2. From GCDs to modular inverses - -We want an algorithm to compute the inverse *a* of *x* modulo *M*, i.e. the number a such that *a x=1 -mod M*. This inverse only exists if the GCD of *x* and *M* is *1*, but that is always the case if *M* is -prime and *0 < x < M*. In what follows, assume that the modular inverse exists. -It turns out this inverse can be computed as a side effect of computing the GCD by keeping track -of how the internal variables can be written as linear combinations of the inputs at every step -(see the [extended Euclidean algorithm](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm)). -Since the GCD is *1*, such an algorithm will compute numbers *a* and *b* such that a x + b M = 1*. -Taking that expression *mod M* gives *a x mod M = 1*, and we see that *a* is the modular inverse of *x -mod M*. - -A similar approach can be used to calculate modular inverses using the divsteps-based GCD -algorithm shown above, if the modulus *M* is odd. To do so, compute *gcd(f=M,g=x)*, while keeping -track of extra variables *d* and *e*, for which at every step *d = f/x (mod M)* and *e = g/x (mod M)*. -*f/x* here means the number which multiplied with *x* gives *f mod M*. As *f* and *g* are initialized to *M* -and *x* respectively, *d* and *e* just start off being *0* (*M/x mod M = 0/x mod M = 0*) and *1* (*x/x mod M -= 1*). - -```python -def div2(M, x): - """Helper routine to compute x/2 mod M (where M is odd).""" - assert M & 1 - if x & 1: # If x is odd, make it even by adding M. - x += M - # x must be even now, so a clean division by 2 is possible. - return x // 2 - -def modinv(M, x): - """Compute the inverse of x mod M (given that it exists, and M is odd).""" - assert M & 1 - delta, f, g, d, e = 1, M, x, 0, 1 - while g != 0: - # Note that while division by two for f and g is only ever done on even inputs, this is - # not true for d and e, so we need the div2 helper function. - if delta > 0 and g & 1: - delta, f, g, d, e = 1 - delta, g, (g - f) // 2, e, div2(M, e - d) - elif g & 1: - delta, f, g, d, e = 1 + delta, f, (g + f) // 2, d, div2(M, e + d) - else: - delta, f, g, d, e = 1 + delta, f, (g ) // 2, d, div2(M, e ) - # Verify that the invariants d=f/x mod M, e=g/x mod M are maintained. - assert f % M == (d * x) % M - assert g % M == (e * x) % M - assert f == 1 or f == -1 # |f| is the GCD, it must be 1 - # Because of invariant d = f/x (mod M), 1/x = d/f (mod M). As |f|=1, d/f = d*f. - return (d * f) % M -``` - -Also note that this approach to track *d* and *e* throughout the computation to determine the inverse -is different from the paper. There (see paragraph 12.1 in the paper) a transition matrix for the -entire computation is determined (see section 3 below) and the inverse is computed from that. -The approach here avoids the need for 2x2 matrix multiplications of various sizes, and appears to -be faster at the level of optimization we're able to do in C. - - -## 3. Batching multiple divsteps - -Every divstep can be expressed as a matrix multiplication, applying a transition matrix *(1/2 t)* -to both vectors *[f, g]* and *[d, e]* (see paragraph 8.1 in the paper): - -``` - t = [ u, v ] - [ q, r ] - - [ out_f ] = (1/2 * t) * [ in_f ] - [ out_g ] = [ in_g ] - - [ out_d ] = (1/2 * t) * [ in_d ] (mod M) - [ out_e ] [ in_e ] -``` - -where *(u, v, q, r)* is *(0, 2, -1, 1)*, *(2, 0, 1, 1)*, or *(2, 0, 0, 1)*, depending on which branch is -taken. As above, the resulting *f* and *g* are always integers. - -Performing multiple divsteps corresponds to a multiplication with the product of all the -individual divsteps' transition matrices. As each transition matrix consists of integers -divided by *2*, the product of these matrices will consist of integers divided by *2N* (see also -theorem 9.2 in the paper). These divisions are expensive when updating *d* and *e*, so we delay -them: we compute the integer coefficients of the combined transition matrix scaled by *2N*, and -do one division by *2N* as a final step: - -```python -def divsteps_n_matrix(delta, f, g): - """Compute delta and transition matrix t after N divsteps (multiplied by 2^N).""" - u, v, q, r = 1, 0, 0, 1 # start with identity matrix - for _ in range(N): - if delta > 0 and g & 1: - delta, f, g, u, v, q, r = 1 - delta, g, (g - f) // 2, 2*q, 2*r, q-u, r-v - elif g & 1: - delta, f, g, u, v, q, r = 1 + delta, f, (g + f) // 2, 2*u, 2*v, q+u, r+v - else: - delta, f, g, u, v, q, r = 1 + delta, f, (g ) // 2, 2*u, 2*v, q , r - return delta, (u, v, q, r) -``` - -As the branches in the divsteps are completely determined by the bottom *N* bits of *f* and *g*, this -function to compute the transition matrix only needs to see those bottom bits. Furthermore all -intermediate results and outputs fit in *(N+1)*-bit numbers (unsigned for *f* and *g*; signed for *u*, *v*, -*q*, and *r*) (see also paragraph 8.3 in the paper). This means that an implementation using 64-bit -integers could set *N=62* and compute the full transition matrix for 62 steps at once without any -big integer arithmetic at all. This is the reason why this algorithm is efficient: it only needs -to update the full-size *f*, *g*, *d*, and *e* numbers once every *N* steps. - -We still need functions to compute: - -``` - [ out_f ] = (1/2^N * [ u, v ]) * [ in_f ] - [ out_g ] ( [ q, r ]) [ in_g ] - - [ out_d ] = (1/2^N * [ u, v ]) * [ in_d ] (mod M) - [ out_e ] ( [ q, r ]) [ in_e ] -``` - -Because the divsteps transformation only ever divides even numbers by two, the result of *t [f,g]* is always even. When *t* is a composition of *N* divsteps, it follows that the resulting *f* -and *g* will be multiple of *2N*, and division by *2N* is simply shifting them down: - -```python -def update_fg(f, g, t): - """Multiply matrix t/2^N with [f, g].""" - u, v, q, r = t - cf, cg = u*f + v*g, q*f + r*g - # (t / 2^N) should cleanly apply to [f,g] so the result of t*[f,g] should have N zero - # bottom bits. - assert cf % 2**N == 0 - assert cg % 2**N == 0 - return cf >> N, cg >> N -``` - -The same is not true for *d* and *e*, and we need an equivalent of the `div2` function for division by *2N mod M*. -This is easy if we have precomputed *1/M mod 2N* (which always exists for odd *M*): - -```python -def div2n(M, Mi, x): - """Compute x/2^N mod M, given Mi = 1/M mod 2^N.""" - assert (M * Mi) % 2**N == 1 - # Find a factor m such that m*M has the same bottom N bits as x. We want: - # (m * M) mod 2^N = x mod 2^N - # <=> m mod 2^N = (x / M) mod 2^N - # <=> m mod 2^N = (x * Mi) mod 2^N - m = (Mi * x) % 2**N - # Subtract that multiple from x, cancelling its bottom N bits. - x -= m * M - # Now a clean division by 2^N is possible. - assert x % 2**N == 0 - return (x >> N) % M - -def update_de(d, e, t, M, Mi): - """Multiply matrix t/2^N with [d, e], modulo M.""" - u, v, q, r = t - cd, ce = u*d + v*e, q*d + r*e - return div2n(M, Mi, cd), div2n(M, Mi, ce) -``` - -With all of those, we can write a version of `modinv` that performs *N* divsteps at once: - -```python3 -def modinv(M, Mi, x): - """Compute the modular inverse of x mod M, given Mi=1/M mod 2^N.""" - assert M & 1 - delta, f, g, d, e = 1, M, x, 0, 1 - while g != 0: - # Compute the delta and transition matrix t for the next N divsteps (this only needs - # (N+1)-bit signed integer arithmetic). - delta, t = divsteps_n_matrix(delta, f % 2**N, g % 2**N) - # Apply the transition matrix t to [f, g]: - f, g = update_fg(f, g, t) - # Apply the transition matrix t to [d, e]: - d, e = update_de(d, e, t, M, Mi) - return (d * f) % M -``` - -This means that in practice we'll always perform a multiple of *N* divsteps. This is not a problem -because once *g=0*, further divsteps do not affect *f*, *g*, *d*, or *e* anymore (only *δ* keeps -increasing). For variable time code such excess iterations will be mostly optimized away in later -sections. - - -## 4. Avoiding modulus operations - -So far, there are two places where we compute a remainder of big numbers modulo *M*: at the end of -`div2n` in every `update_de`, and at the very end of `modinv` after potentially negating *d* due to the -sign of *f*. These are relatively expensive operations when done generically. - -To deal with the modulus operation in `div2n`, we simply stop requiring *d* and *e* to be in range -*[0,M)* all the time. Let's start by inlining `div2n` into `update_de`, and dropping the modulus -operation at the end: - -```python -def update_de(d, e, t, M, Mi): - """Multiply matrix t/2^N with [d, e] mod M, given Mi=1/M mod 2^N.""" - u, v, q, r = t - cd, ce = u*d + v*e, q*d + r*e - # Cancel out bottom N bits of cd and ce. - md = -((Mi * cd) % 2**N) - me = -((Mi * ce) % 2**N) - cd += md * M - ce += me * M - # And cleanly divide by 2**N. - return cd >> N, ce >> N -``` - -Let's look at bounds on the ranges of these numbers. It can be shown that *|u|+|v|* and *|q|+|r|* -never exceed *2N* (see paragraph 8.3 in the paper), and thus a multiplication with *t* will have -outputs whose absolute values are at most *2N* times the maximum absolute input value. In case the -inputs *d* and *e* are in *(-M,M)*, which is certainly true for the initial values *d=0* and *e=1* assuming -*M > 1*, the multiplication results in numbers in range *(-2NM,2NM)*. Subtracting less than *2N* -times *M* to cancel out *N* bits brings that up to *(-2N+1M,2NM)*, and -dividing by *2N* at the end takes it to *(-2M,M)*. Another application of `update_de` would take that -to *(-3M,2M)*, and so forth. This progressive expansion of the variables' ranges can be -counteracted by incrementing *d* and *e* by *M* whenever they're negative: - -```python - ... - if d < 0: - d += M - if e < 0: - e += M - cd, ce = u*d + v*e, q*d + r*e - # Cancel out bottom N bits of cd and ce. - ... -``` - -With inputs in *(-2M,M)*, they will first be shifted into range *(-M,M)*, which means that the -output will again be in *(-2M,M)*, and this remains the case regardless of how many `update_de` -invocations there are. In what follows, we will try to make this more efficient. - -Note that increasing *d* by *M* is equal to incrementing *cd* by *u M* and *ce* by *q M*. Similarly, -increasing *e* by *M* is equal to incrementing *cd* by *v M* and *ce* by *r M*. So we could instead write: - -```python - ... - cd, ce = u*d + v*e, q*d + r*e - # Perform the equivalent of incrementing d, e by M when they're negative. - if d < 0: - cd += u*M - ce += q*M - if e < 0: - cd += v*M - ce += r*M - # Cancel out bottom N bits of cd and ce. - md = -((Mi * cd) % 2**N) - me = -((Mi * ce) % 2**N) - cd += md * M - ce += me * M - ... -``` - -Now note that we have two steps of corrections to *cd* and *ce* that add multiples of *M*: this -increment, and the decrement that cancels out bottom bits. The second one depends on the first -one, but they can still be efficiently combined by only computing the bottom bits of *cd* and *ce* -at first, and using that to compute the final *md*, *me* values: - -```python -def update_de(d, e, t, M, Mi): - """Multiply matrix t/2^N with [d, e], modulo M.""" - u, v, q, r = t - md, me = 0, 0 - # Compute what multiples of M to add to cd and ce. - if d < 0: - md += u - me += q - if e < 0: - md += v - me += r - # Compute bottom N bits of t*[d,e] + M*[md,me]. - cd, ce = (u*d + v*e + md*M) % 2**N, (q*d + r*e + me*M) % 2**N - # Correct md and me such that the bottom N bits of t*[d,e] + M*[md,me] are zero. - md -= (Mi * cd) % 2**N - me -= (Mi * ce) % 2**N - # Do the full computation. - cd, ce = u*d + v*e + md*M, q*d + r*e + me*M - # And cleanly divide by 2**N. - return cd >> N, ce >> N -``` - -One last optimization: we can avoid the *md M* and *me M* multiplications in the bottom bits of *cd* -and *ce* by moving them to the *md* and *me* correction: - -```python - ... - # Compute bottom N bits of t*[d,e]. - cd, ce = (u*d + v*e) % 2**N, (q*d + r*e) % 2**N - # Correct md and me such that the bottom N bits of t*[d,e]+M*[md,me] are zero. - # Note that this is not the same as {md = (-Mi * cd) % 2**N} etc. That would also result in N - # zero bottom bits, but isn't guaranteed to be a reduction of [0,2^N) compared to the - # previous md and me values, and thus would violate our bounds analysis. - md -= (Mi*cd + md) % 2**N - me -= (Mi*ce + me) % 2**N - ... -``` - -The resulting function takes *d* and *e* in range *(-2M,M)* as inputs, and outputs values in the same -range. That also means that the *d* value at the end of `modinv` will be in that range, while we want -a result in *[0,M)*. To do that, we need a normalization function. It's easy to integrate the -conditional negation of *d* (based on the sign of *f*) into it as well: - -```python -def normalize(sign, v, M): - """Compute sign*v mod M, where v is in range (-2*M,M); output in [0,M).""" - assert sign == 1 or sign == -1 - # v in (-2*M,M) - if v < 0: - v += M - # v in (-M,M). Now multiply v with sign (which can only be 1 or -1). - if sign == -1: - v = -v - # v in (-M,M) - if v < 0: - v += M - # v in [0,M) - return v -``` - -And calling it in `modinv` is simply: - -```python - ... - return normalize(f, d, M) -``` - - -## 5. Constant-time operation - -The primary selling point of the algorithm is fast constant-time operation. What code flow still -depends on the input data so far? - -- the number of iterations of the while *g ≠ 0* loop in `modinv` -- the branches inside `divsteps_n_matrix` -- the sign checks in `update_de` -- the sign checks in `normalize` - -To make the while loop in `modinv` constant time it can be replaced with a constant number of -iterations. The paper proves (Theorem 11.2) that *741* divsteps are sufficient for any *256*-bit -inputs, and [safegcd-bounds](https://github.com/sipa/safegcd-bounds) shows that the slightly better bound *724* is -sufficient even. Given that every loop iteration performs *N* divsteps, it will run a total of -*⌈724/N⌉* times. - -To deal with the branches in `divsteps_n_matrix` we will replace them with constant-time bitwise -operations (and hope the C compiler isn't smart enough to turn them back into branches; see -`ctime_tests.c` for automated tests that this isn't the case). To do so, observe that a -divstep can be written instead as (compare to the inner loop of `gcd` in section 1). - -```python - x = -f if delta > 0 else f # set x equal to (input) -f or f - if g & 1: - g += x # set g to (input) g-f or g+f - if delta > 0: - delta = -delta - f += g # set f to (input) g (note that g was set to g-f before) - delta += 1 - g >>= 1 -``` - -To convert the above to bitwise operations, we rely on a trick to negate conditionally: per the -definition of negative numbers in two's complement, (*-v == ~v + 1*) holds for every number *v*. As -*-1* in two's complement is all *1* bits, bitflipping can be expressed as xor with *-1*. It follows -that *-v == (v ^ -1) - (-1)*. Thus, if we have a variable *c* that takes on values *0* or *-1*, then -*(v ^ c) - c* is *v* if *c=0* and *-v* if *c=-1*. - -Using this we can write: - -```python - x = -f if delta > 0 else f -``` - -in constant-time form as: - -```python - c1 = (-delta) >> 63 - # Conditionally negate f based on c1: - x = (f ^ c1) - c1 -``` - -To use that trick, we need a helper mask variable *c1* that resolves the condition *δ>0* to *-1* -(if true) or *0* (if false). We compute *c1* using right shifting, which is equivalent to dividing by -the specified power of *2* and rounding down (in Python, and also in C under the assumption of a typical two's complement system; see -`assumptions.h` for tests that this is the case). Right shifting by *63* thus maps all -numbers in range *[-263,0)* to *-1*, and numbers in range *[0,263)* to *0*. - -Using the facts that *x&0=0* and *x&(-1)=x* (on two's complement systems again), we can write: - -```python - if g & 1: - g += x -``` - -as: - -```python - # Compute c2=0 if g is even and c2=-1 if g is odd. - c2 = -(g & 1) - # This masks out x if g is even, and leaves x be if g is odd. - g += x & c2 -``` - -Using the conditional negation trick again we can write: - -```python - if g & 1: - if delta > 0: - delta = -delta -``` - -as: - -```python - # Compute c3=-1 if g is odd and delta>0, and 0 otherwise. - c3 = c1 & c2 - # Conditionally negate delta based on c3: - delta = (delta ^ c3) - c3 -``` - -Finally: - -```python - if g & 1: - if delta > 0: - f += g -``` - -becomes: - -```python - f += g & c3 -``` - -It turns out that this can be implemented more efficiently by applying the substitution -*η=-δ*. In this representation, negating *δ* corresponds to negating *η*, and incrementing -*δ* corresponds to decrementing *η*. This allows us to remove the negation in the *c1* -computation: - -```python - # Compute a mask c1 for eta < 0, and compute the conditional negation x of f: - c1 = eta >> 63 - x = (f ^ c1) - c1 - # Compute a mask c2 for odd g, and conditionally add x to g: - c2 = -(g & 1) - g += x & c2 - # Compute a mask c for (eta < 0) and odd (input) g, and use it to conditionally negate eta, - # and add g to f: - c3 = c1 & c2 - eta = (eta ^ c3) - c3 - f += g & c3 - # Incrementing delta corresponds to decrementing eta. - eta -= 1 - g >>= 1 -``` - -A variant of divsteps with better worst-case performance can be used instead: starting *δ* at -*1/2* instead of *1*. This reduces the worst case number of iterations to *590* for *256*-bit inputs -(which can be shown using convex hull analysis). In this case, the substitution *ζ=-(δ+1/2)* -is used instead to keep the variable integral. Incrementing *δ* by *1* still translates to -decrementing *ζ* by *1*, but negating *δ* now corresponds to going from *ζ* to *-(ζ+1)*, or -*~ζ*. Doing that conditionally based on *c3* is simply: - -```python - ... - c3 = c1 & c2 - zeta ^= c3 - ... -``` - -By replacing the loop in `divsteps_n_matrix` with a variant of the divstep code above (extended to -also apply all *f* operations to *u*, *v* and all *g* operations to *q*, *r*), a constant-time version of -`divsteps_n_matrix` is obtained. The full code will be in section 7. - -These bit fiddling tricks can also be used to make the conditional negations and additions in -`update_de` and `normalize` constant-time. - - -## 6. Variable-time optimizations - -In section 5, we modified the `divsteps_n_matrix` function (and a few others) to be constant time. -Constant time operations are only necessary when computing modular inverses of secret data. In -other cases, it slows down calculations unnecessarily. In this section, we will construct a -faster non-constant time `divsteps_n_matrix` function. - -To do so, first consider yet another way of writing the inner loop of divstep operations in -`gcd` from section 1. This decomposition is also explained in the paper in section 8.2. We use -the original version with initial *δ=1* and *η=-δ* here. - -```python -for _ in range(N): - if g & 1 and eta < 0: - eta, f, g = -eta, g, -f - if g & 1: - g += f - eta -= 1 - g >>= 1 -``` - -Whenever *g* is even, the loop only shifts *g* down and decreases *η*. When *g* ends in multiple zero -bits, these iterations can be consolidated into one step. This requires counting the bottom zero -bits efficiently, which is possible on most platforms; it is abstracted here as the function -`count_trailing_zeros`. - -```python -def count_trailing_zeros(v): - """ - When v is zero, consider all N zero bits as "trailing". - For a non-zero value v, find z such that v=(d<>= zeros - i -= zeros - if i == 0: - break - # We know g is odd now - if eta < 0: - eta, f, g = -eta, g, -f - g += f - # g is even now, and the eta decrement and g shift will happen in the next loop. -``` - -We can now remove multiple bottom *0* bits from *g* at once, but still need a full iteration whenever -there is a bottom *1* bit. In what follows, we will get rid of multiple *1* bits simultaneously as -well. - -Observe that as long as *η ≥ 0*, the loop does not modify *f*. Instead, it cancels out bottom -bits of *g* and shifts them out, and decreases *η* and *i* accordingly - interrupting only when *η* -becomes negative, or when *i* reaches *0*. Combined, this is equivalent to adding a multiple of *f* to -*g* to cancel out multiple bottom bits, and then shifting them out. - -It is easy to find what that multiple is: we want a number *w* such that *g+w f* has a few bottom -zero bits. If that number of bits is *L*, we want *g+w f mod 2L = 0*, or *w = -g/f mod 2L*. Since *f* -is odd, such a *w* exists for any *L*. *L* cannot be more than *i* steps (as we'd finish the loop before -doing more) or more than *η+1* steps (as we'd run `eta, f, g = -eta, g, -f` at that point), but -apart from that, we're only limited by the complexity of computing *w*. - -This code demonstrates how to cancel up to 4 bits per step: - -```python -NEGINV16 = [15, 5, 3, 9, 7, 13, 11, 1] # NEGINV16[n//2] = (-n)^-1 mod 16, for odd n -i = N -while True: - zeros = min(i, count_trailing_zeros(g)) - eta -= zeros - g >>= zeros - i -= zeros - if i == 0: - break - # We know g is odd now - if eta < 0: - eta, f, g = -eta, g, -f - # Compute limit on number of bits to cancel - limit = min(min(eta + 1, i), 4) - # Compute w = -g/f mod 2**limit, using the table value for -1/f mod 2**4. Note that f is - # always odd, so its inverse modulo a power of two always exists. - w = (g * NEGINV16[(f & 15) // 2]) % (2**limit) - # As w = -g/f mod (2**limit), g+w*f mod 2**limit = 0 mod 2**limit. - g += w * f - assert g % (2**limit) == 0 - # The next iteration will now shift out at least limit bottom zero bits from g. -``` - -By using a bigger table more bits can be cancelled at once. The table can also be implemented -as a formula. Several formulas are known for computing modular inverses modulo powers of two; -some can be found in Hacker's Delight second edition by Henry S. Warren, Jr. pages 245-247. -Here we need the negated modular inverse, which is a simple transformation of those: - -- Instead of a 3-bit table: - - *-f* or *f ^ 6* -- Instead of a 4-bit table: - - *1 - f(f + 1)* - - *-(f + (((f + 1) & 4) << 1))* -- For larger tables the following technique can be used: if *w=-1/f mod 2L*, then *w(w f+2)* is - *-1/f mod 22L*. This allows extending the previous formulas (or tables). In particular we - have this 6-bit function (based on the 3-bit function above): - - *f(f2 - 2)* - -This loop, again extended to also handle *u*, *v*, *q*, and *r* alongside *f* and *g*, placed in -`divsteps_n_matrix`, gives a significantly faster, but non-constant time version. - - -## 7. Final Python version - -All together we need the following functions: - -- A way to compute the transition matrix in constant time, using the `divsteps_n_matrix` function - from section 2, but with its loop replaced by a variant of the constant-time divstep from - section 5, extended to handle *u*, *v*, *q*, *r*: - -```python -def divsteps_n_matrix(zeta, f, g): - """Compute zeta and transition matrix t after N divsteps (multiplied by 2^N).""" - u, v, q, r = 1, 0, 0, 1 # start with identity matrix - for _ in range(N): - c1 = zeta >> 63 - # Compute x, y, z as conditionally-negated versions of f, u, v. - x, y, z = (f ^ c1) - c1, (u ^ c1) - c1, (v ^ c1) - c1 - c2 = -(g & 1) - # Conditionally add x, y, z to g, q, r. - g, q, r = g + (x & c2), q + (y & c2), r + (z & c2) - c1 &= c2 # reusing c1 here for the earlier c3 variable - zeta = (zeta ^ c1) - 1 # inlining the unconditional zeta decrement here - # Conditionally add g, q, r to f, u, v. - f, u, v = f + (g & c1), u + (q & c1), v + (r & c1) - # When shifting g down, don't shift q, r, as we construct a transition matrix multiplied - # by 2^N. Instead, shift f's coefficients u and v up. - g, u, v = g >> 1, u << 1, v << 1 - return zeta, (u, v, q, r) -``` - -- The functions to update *f* and *g*, and *d* and *e*, from section 2 and section 4, with the constant-time - changes to `update_de` from section 5: - -```python -def update_fg(f, g, t): - """Multiply matrix t/2^N with [f, g].""" - u, v, q, r = t - cf, cg = u*f + v*g, q*f + r*g - return cf >> N, cg >> N - -def update_de(d, e, t, M, Mi): - """Multiply matrix t/2^N with [d, e], modulo M.""" - u, v, q, r = t - d_sign, e_sign = d >> 257, e >> 257 - md, me = (u & d_sign) + (v & e_sign), (q & d_sign) + (r & e_sign) - cd, ce = (u*d + v*e) % 2**N, (q*d + r*e) % 2**N - md -= (Mi*cd + md) % 2**N - me -= (Mi*ce + me) % 2**N - cd, ce = u*d + v*e + M*md, q*d + r*e + M*me - return cd >> N, ce >> N -``` - -- The `normalize` function from section 4, made constant time as well: - -```python -def normalize(sign, v, M): - """Compute sign*v mod M, where v in (-2*M,M); output in [0,M).""" - v_sign = v >> 257 - # Conditionally add M to v. - v += M & v_sign - c = (sign - 1) >> 1 - # Conditionally negate v. - v = (v ^ c) - c - v_sign = v >> 257 - # Conditionally add M to v again. - v += M & v_sign - return v -``` - -- And finally the `modinv` function too, adapted to use *ζ* instead of *δ*, and using the fixed - iteration count from section 5: - -```python -def modinv(M, Mi, x): - """Compute the modular inverse of x mod M, given Mi=1/M mod 2^N.""" - zeta, f, g, d, e = -1, M, x, 0, 1 - for _ in range((590 + N - 1) // N): - zeta, t = divsteps_n_matrix(zeta, f % 2**N, g % 2**N) - f, g = update_fg(f, g, t) - d, e = update_de(d, e, t, M, Mi) - return normalize(f, d, M) -``` - -- To get a variable time version, replace the `divsteps_n_matrix` function with one that uses the - divsteps loop from section 5, and a `modinv` version that calls it without the fixed iteration - count: - -```python -NEGINV16 = [15, 5, 3, 9, 7, 13, 11, 1] # NEGINV16[n//2] = (-n)^-1 mod 16, for odd n -def divsteps_n_matrix_var(eta, f, g): - """Compute eta and transition matrix t after N divsteps (multiplied by 2^N).""" - u, v, q, r = 1, 0, 0, 1 - i = N - while True: - zeros = min(i, count_trailing_zeros(g)) - eta, i = eta - zeros, i - zeros - g, u, v = g >> zeros, u << zeros, v << zeros - if i == 0: - break - if eta < 0: - eta, f, u, v, g, q, r = -eta, g, q, r, -f, -u, -v - limit = min(min(eta + 1, i), 4) - w = (g * NEGINV16[(f & 15) // 2]) % (2**limit) - g, q, r = g + w*f, q + w*u, r + w*v - return eta, (u, v, q, r) - -def modinv_var(M, Mi, x): - """Compute the modular inverse of x mod M, given Mi = 1/M mod 2^N.""" - eta, f, g, d, e = -1, M, x, 0, 1 - while g != 0: - eta, t = divsteps_n_matrix_var(eta, f % 2**N, g % 2**N) - f, g = update_fg(f, g, t) - d, e = update_de(d, e, t, M, Mi) - return normalize(f, d, Mi) -``` - -## 8. From GCDs to Jacobi symbol - -We can also use a similar approach to calculate Jacobi symbol *(x | M)* by keeping track of an -extra variable *j*, for which at every step *(x | M) = j (g | f)*. As we update *f* and *g*, we -make corresponding updates to *j* using -[properties of the Jacobi symbol](https://en.wikipedia.org/wiki/Jacobi_symbol#Properties): -* *((g/2) | f)* is either *(g | f)* or *-(g | f)*, depending on the value of *f mod 8* (negating if it's *3* or *5*). -* *(f | g)* is either *(g | f)* or *-(g | f)*, depending on *f mod 4* and *g mod 4* (negating if both are *3*). - -These updates depend only on the values of *f* and *g* modulo *4* or *8*, and can thus be applied -very quickly, as long as we keep track of a few additional bits of *f* and *g*. Overall, this -calculation is slightly simpler than the one for the modular inverse because we no longer need to -keep track of *d* and *e*. - -However, one difficulty of this approach is that the Jacobi symbol *(a | n)* is only defined for -positive odd integers *n*, whereas in the original safegcd algorithm, *f, g* can take negative -values. We resolve this by using the following modified steps: - -```python - # Before - if delta > 0 and g & 1: - delta, f, g = 1 - delta, g, (g - f) // 2 - - # After - if delta > 0 and g & 1: - delta, f, g = 1 - delta, g, (g + f) // 2 -``` - -The algorithm is still correct, since the changed divstep, called a "posdivstep" (see section 8.4 -and E.5 in the paper) preserves *gcd(f, g)*. However, there's no proof that the modified algorithm -will converge. The justification for posdivsteps is completely empirical: in practice, it appears -that the vast majority of nonzero inputs converge to *f=g=gcd(f0, g0)* in a -number of steps proportional to their logarithm. - -Note that: -- We require inputs to satisfy *gcd(x, M) = 1*, as otherwise *f=1* is not reached. -- We require inputs *x &neq; 0*, because applying posdivstep with *g=0* has no effect. -- We need to update the termination condition from *g=0* to *f=1*. - -We account for the possibility of nonconvergence by only performing a bounded number of -posdivsteps, and then falling back to square-root based Jacobi calculation if a solution has not -yet been found. - -The optimizations in sections 3-7 above are described in the context of the original divsteps, but -in the C implementation we also adapt most of them (not including "avoiding modulus operations", -since it's not necessary to track *d, e*, and "constant-time operation", since we never calculate -Jacobi symbols for secret data) to the posdivsteps version. diff --git a/external/secp256k1/examples/CMakeLists.txt b/external/secp256k1/examples/CMakeLists.txt deleted file mode 100644 index c9da9de6be..0000000000 --- a/external/secp256k1/examples/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -function(add_example name) - set(target_name ${name}_example) - add_executable(${target_name} ${name}.c) - target_include_directories(${target_name} PRIVATE - ${PROJECT_SOURCE_DIR}/include - ) - target_link_libraries(${target_name} - secp256k1 - $<$:bcrypt> - ) - set(test_name ${name}_example) - add_test(NAME secp256k1_${test_name} COMMAND ${target_name}) -endfunction() - -add_example(ecdsa) - -if(SECP256K1_ENABLE_MODULE_ECDH) - add_example(ecdh) -endif() - -if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) - add_example(schnorr) -endif() - -if(SECP256K1_ENABLE_MODULE_ELLSWIFT) - add_example(ellswift) -endif() - -if(SECP256K1_ENABLE_MODULE_MUSIG) - add_example(musig) -endif() diff --git a/external/secp256k1/examples/EXAMPLES_COPYING b/external/secp256k1/examples/EXAMPLES_COPYING deleted file mode 100644 index 0e259d42c9..0000000000 --- a/external/secp256k1/examples/EXAMPLES_COPYING +++ /dev/null @@ -1,121 +0,0 @@ -Creative Commons Legal Code - -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. diff --git a/external/secp256k1/examples/ecdh.c b/external/secp256k1/examples/ecdh.c deleted file mode 100644 index 13aa760b2d..0000000000 --- a/external/secp256k1/examples/ecdh.c +++ /dev/null @@ -1,120 +0,0 @@ -/************************************************************************* - * Written in 2020-2022 by Elichai Turkel * - * To the extent possible under law, the author(s) have dedicated all * - * copyright and related and neighboring rights to the software in this * - * file to the public domain worldwide. This software is distributed * - * without any warranty. For the CC0 Public Domain Dedication, see * - * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * - *************************************************************************/ - -#include -#include -#include - -#include -#include - -#include "examples_util.h" - -int main(void) { - unsigned char seckey1[32]; - unsigned char seckey2[32]; - unsigned char compressed_pubkey1[33]; - unsigned char compressed_pubkey2[33]; - unsigned char shared_secret1[32]; - unsigned char shared_secret2[32]; - unsigned char randomize[32]; - int return_val; - size_t len; - secp256k1_pubkey pubkey1; - secp256k1_pubkey pubkey2; - - /* Before we can call actual API functions, we need to create a "context". */ - secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - if (!fill_random(randomize, sizeof(randomize))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* Randomizing the context is recommended to protect against side-channel - * leakage See `secp256k1_context_randomize` in secp256k1.h for more - * information about it. This should never fail. */ - return_val = secp256k1_context_randomize(ctx, randomize); - assert(return_val); - - /*** Key Generation ***/ - if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* If the secret key is zero or out of range (greater than secp256k1's - * order), we fail. Note that the probability of this occurring is negligible - * with a properly functioning random number generator. */ - if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { - printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; - } - - /* Public key creation using a valid context with a verified secret key should never fail */ - return_val = secp256k1_ec_pubkey_create(ctx, &pubkey1, seckey1); - assert(return_val); - return_val = secp256k1_ec_pubkey_create(ctx, &pubkey2, seckey2); - assert(return_val); - - /* Serialize pubkey1 in a compressed form (33 bytes), should always return 1 */ - len = sizeof(compressed_pubkey1); - return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey1, &len, &pubkey1, SECP256K1_EC_COMPRESSED); - assert(return_val); - /* Should be the same size as the size of the output, because we passed a 33 byte array. */ - assert(len == sizeof(compressed_pubkey1)); - - /* Serialize pubkey2 in a compressed form (33 bytes) */ - len = sizeof(compressed_pubkey2); - return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey2, &len, &pubkey2, SECP256K1_EC_COMPRESSED); - assert(return_val); - /* Should be the same size as the size of the output, because we passed a 33 byte array. */ - assert(len == sizeof(compressed_pubkey2)); - - /*** Creating the shared secret ***/ - - /* Perform ECDH with seckey1 and pubkey2. Should never fail with a verified - * seckey and valid pubkey */ - return_val = secp256k1_ecdh(ctx, shared_secret1, &pubkey2, seckey1, NULL, NULL); - assert(return_val); - - /* Perform ECDH with seckey2 and pubkey1. Should never fail with a verified - * seckey and valid pubkey */ - return_val = secp256k1_ecdh(ctx, shared_secret2, &pubkey1, seckey2, NULL, NULL); - assert(return_val); - - /* Both parties should end up with the same shared secret */ - return_val = memcmp(shared_secret1, shared_secret2, sizeof(shared_secret1)); - assert(return_val == 0); - - printf("Secret Key1: "); - print_hex(seckey1, sizeof(seckey1)); - printf("Compressed Pubkey1: "); - print_hex(compressed_pubkey1, sizeof(compressed_pubkey1)); - printf("\nSecret Key2: "); - print_hex(seckey2, sizeof(seckey2)); - printf("Compressed Pubkey2: "); - print_hex(compressed_pubkey2, sizeof(compressed_pubkey2)); - printf("\nShared Secret: "); - print_hex(shared_secret1, sizeof(shared_secret1)); - - /* This will clear everything from the context and free the memory */ - secp256k1_context_destroy(ctx); - - /* It's best practice to try to clear secrets from memory after using them. - * This is done because some bugs can allow an attacker to leak memory, for - * example through "out of bounds" array access (see Heartbleed), or the OS - * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. - * - * Here we are preventing these writes from being optimized out, as any good compiler - * will remove any writes that aren't used. */ - secure_erase(seckey1, sizeof(seckey1)); - secure_erase(seckey2, sizeof(seckey2)); - secure_erase(shared_secret1, sizeof(shared_secret1)); - secure_erase(shared_secret2, sizeof(shared_secret2)); - - return 0; -} diff --git a/external/secp256k1/examples/ecdsa.c b/external/secp256k1/examples/ecdsa.c deleted file mode 100644 index 80ae9d46c5..0000000000 --- a/external/secp256k1/examples/ecdsa.c +++ /dev/null @@ -1,137 +0,0 @@ -/************************************************************************* - * Written in 2020-2022 by Elichai Turkel * - * To the extent possible under law, the author(s) have dedicated all * - * copyright and related and neighboring rights to the software in this * - * file to the public domain worldwide. This software is distributed * - * without any warranty. For the CC0 Public Domain Dedication, see * - * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * - *************************************************************************/ - -#include -#include -#include - -#include - -#include "examples_util.h" - -int main(void) { - /* Instead of signing the message directly, we must sign a 32-byte hash. - * Here the message is "Hello, world!" and the hash function was SHA-256. - * An actual implementation should just call SHA-256, but this example - * hardcodes the output to avoid depending on an additional library. - * See https://bitcoin.stackexchange.com/questions/81115/if-someone-wanted-to-pretend-to-be-satoshi-by-posting-a-fake-signature-to-defrau/81116#81116 */ - unsigned char msg_hash[32] = { - 0x31, 0x5F, 0x5B, 0xDB, 0x76, 0xD0, 0x78, 0xC4, - 0x3B, 0x8A, 0xC0, 0x06, 0x4E, 0x4A, 0x01, 0x64, - 0x61, 0x2B, 0x1F, 0xCE, 0x77, 0xC8, 0x69, 0x34, - 0x5B, 0xFC, 0x94, 0xC7, 0x58, 0x94, 0xED, 0xD3, - }; - unsigned char seckey[32]; - unsigned char randomize[32]; - unsigned char compressed_pubkey[33]; - unsigned char serialized_signature[64]; - size_t len; - int is_signature_valid, is_signature_valid2; - int return_val; - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - /* Before we can call actual API functions, we need to create a "context". */ - secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - if (!fill_random(randomize, sizeof(randomize))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* Randomizing the context is recommended to protect against side-channel - * leakage See `secp256k1_context_randomize` in secp256k1.h for more - * information about it. This should never fail. */ - return_val = secp256k1_context_randomize(ctx, randomize); - assert(return_val); - - /*** Key Generation ***/ - if (!fill_random(seckey, sizeof(seckey))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* If the secret key is zero or out of range (greater than secp256k1's - * order), we fail. Note that the probability of this occurring is negligible - * with a properly functioning random number generator. */ - if (!secp256k1_ec_seckey_verify(ctx, seckey)) { - printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; - } - - /* Public key creation using a valid context with a verified secret key should never fail */ - return_val = secp256k1_ec_pubkey_create(ctx, &pubkey, seckey); - assert(return_val); - - /* Serialize the pubkey in a compressed form(33 bytes). Should always return 1. */ - len = sizeof(compressed_pubkey); - return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey, &len, &pubkey, SECP256K1_EC_COMPRESSED); - assert(return_val); - /* Should be the same size as the size of the output, because we passed a 33 byte array. */ - assert(len == sizeof(compressed_pubkey)); - - /*** Signing ***/ - - /* Generate an ECDSA signature `noncefp` and `ndata` allows you to pass a - * custom nonce function, passing `NULL` will use the RFC-6979 safe default. - * Signing with a valid context, verified secret key - * and the default nonce function should never fail. */ - return_val = secp256k1_ecdsa_sign(ctx, &sig, msg_hash, seckey, NULL, NULL); - assert(return_val); - - /* Serialize the signature in a compact form. Should always return 1 - * according to the documentation in secp256k1.h. */ - return_val = secp256k1_ecdsa_signature_serialize_compact(ctx, serialized_signature, &sig); - assert(return_val); - - - /*** Verification ***/ - - /* Deserialize the signature. This will return 0 if the signature can't be parsed correctly. */ - if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, serialized_signature)) { - printf("Failed parsing the signature\n"); - return 1; - } - - /* Deserialize the public key. This will return 0 if the public key can't be parsed correctly. */ - if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, compressed_pubkey, sizeof(compressed_pubkey))) { - printf("Failed parsing the public key\n"); - return 1; - } - - /* Verify a signature. This will return 1 if it's valid and 0 if it's not. */ - is_signature_valid = secp256k1_ecdsa_verify(ctx, &sig, msg_hash, &pubkey); - - printf("Is the signature valid? %s\n", is_signature_valid ? "true" : "false"); - printf("Secret Key: "); - print_hex(seckey, sizeof(seckey)); - printf("Public Key: "); - print_hex(compressed_pubkey, sizeof(compressed_pubkey)); - printf("Signature: "); - print_hex(serialized_signature, sizeof(serialized_signature)); - - /* This will clear everything from the context and free the memory */ - secp256k1_context_destroy(ctx); - - /* Bonus example: if all we need is signature verification (and no key - generation or signing), we don't need to use a context created via - secp256k1_context_create(). We can simply use the static (i.e., global) - context secp256k1_context_static. See its description in - include/secp256k1.h for details. */ - is_signature_valid2 = secp256k1_ecdsa_verify(secp256k1_context_static, - &sig, msg_hash, &pubkey); - assert(is_signature_valid2 == is_signature_valid); - - /* It's best practice to try to clear secrets from memory after using them. - * This is done because some bugs can allow an attacker to leak memory, for - * example through "out of bounds" array access (see Heartbleed), or the OS - * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. - * - * Here we are preventing these writes from being optimized out, as any good compiler - * will remove any writes that aren't used. */ - secure_erase(seckey, sizeof(seckey)); - - return 0; -} diff --git a/external/secp256k1/examples/ellswift.c b/external/secp256k1/examples/ellswift.c deleted file mode 100644 index afb2fee40b..0000000000 --- a/external/secp256k1/examples/ellswift.c +++ /dev/null @@ -1,121 +0,0 @@ -/************************************************************************* - * Written in 2024 by Sebastian Falbesoner * - * To the extent possible under law, the author(s) have dedicated all * - * copyright and related and neighboring rights to the software in this * - * file to the public domain worldwide. This software is distributed * - * without any warranty. For the CC0 Public Domain Dedication, see * - * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * - *************************************************************************/ - -/** This file demonstrates how to use the ElligatorSwift module to perform - * a key exchange according to BIP 324. Additionally, see the documentation - * in include/secp256k1_ellswift.h and doc/ellswift.md. - */ - -#include -#include -#include - -#include -#include - -#include "examples_util.h" - -int main(void) { - secp256k1_context* ctx; - unsigned char randomize[32]; - unsigned char auxrand1[32]; - unsigned char auxrand2[32]; - unsigned char seckey1[32]; - unsigned char seckey2[32]; - unsigned char ellswift_pubkey1[64]; - unsigned char ellswift_pubkey2[64]; - unsigned char shared_secret1[32]; - unsigned char shared_secret2[32]; - int return_val; - - /* Create a secp256k1 context */ - ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - if (!fill_random(randomize, sizeof(randomize))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* Randomizing the context is recommended to protect against side-channel - * leakage. See `secp256k1_context_randomize` in secp256k1.h for more - * information about it. This should never fail. */ - return_val = secp256k1_context_randomize(ctx, randomize); - assert(return_val); - - /*** Generate secret keys ***/ - if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* If the secret key is zero or out of range (greater than secp256k1's - * order), we fail. Note that the probability of this occurring is negligible - * with a properly functioning random number generator. */ - if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { - printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; - } - - /* Generate ElligatorSwift public keys. This should never fail with valid context and - verified secret keys. Note that providing additional randomness (fourth parameter) is - optional, but recommended. */ - if (!fill_random(auxrand1, sizeof(auxrand1)) || !fill_random(auxrand2, sizeof(auxrand2))) { - printf("Failed to generate randomness\n"); - return 1; - } - return_val = secp256k1_ellswift_create(ctx, ellswift_pubkey1, seckey1, auxrand1); - assert(return_val); - return_val = secp256k1_ellswift_create(ctx, ellswift_pubkey2, seckey2, auxrand2); - assert(return_val); - - /*** Create the shared secret on each side ***/ - - /* Perform x-only ECDH with seckey1 and ellswift_pubkey2. Should never fail - * with a verified seckey and valid pubkey. Note that both parties pass both - * EllSwift pubkeys in the same order; the pubkey of the calling party is - * determined by the "party" boolean (sixth parameter). */ - return_val = secp256k1_ellswift_xdh(ctx, shared_secret1, ellswift_pubkey1, ellswift_pubkey2, - seckey1, 0, secp256k1_ellswift_xdh_hash_function_bip324, NULL); - assert(return_val); - - /* Perform x-only ECDH with seckey2 and ellswift_pubkey1. Should never fail - * with a verified seckey and valid pubkey. */ - return_val = secp256k1_ellswift_xdh(ctx, shared_secret2, ellswift_pubkey1, ellswift_pubkey2, - seckey2, 1, secp256k1_ellswift_xdh_hash_function_bip324, NULL); - assert(return_val); - - /* Both parties should end up with the same shared secret */ - return_val = memcmp(shared_secret1, shared_secret2, sizeof(shared_secret1)); - assert(return_val == 0); - - printf( " Secret Key1: "); - print_hex(seckey1, sizeof(seckey1)); - printf( "EllSwift Pubkey1: "); - print_hex(ellswift_pubkey1, sizeof(ellswift_pubkey1)); - printf("\n Secret Key2: "); - print_hex(seckey2, sizeof(seckey2)); - printf( "EllSwift Pubkey2: "); - print_hex(ellswift_pubkey2, sizeof(ellswift_pubkey2)); - printf("\n Shared Secret: "); - print_hex(shared_secret1, sizeof(shared_secret1)); - - /* This will clear everything from the context and free the memory */ - secp256k1_context_destroy(ctx); - - /* It's best practice to try to clear secrets from memory after using them. - * This is done because some bugs can allow an attacker to leak memory, for - * example through "out of bounds" array access (see Heartbleed), or the OS - * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. - * - * Here we are preventing these writes from being optimized out, as any good compiler - * will remove any writes that aren't used. */ - secure_erase(seckey1, sizeof(seckey1)); - secure_erase(seckey2, sizeof(seckey2)); - secure_erase(shared_secret1, sizeof(shared_secret1)); - secure_erase(shared_secret2, sizeof(shared_secret2)); - - return 0; -} diff --git a/external/secp256k1/examples/examples_util.h b/external/secp256k1/examples/examples_util.h deleted file mode 100644 index 3293b64032..0000000000 --- a/external/secp256k1/examples/examples_util.h +++ /dev/null @@ -1,108 +0,0 @@ -/************************************************************************* - * Copyright (c) 2020-2021 Elichai Turkel * - * Distributed under the CC0 software license, see the accompanying file * - * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * - *************************************************************************/ - -/* - * This file is an attempt at collecting best practice methods for obtaining randomness with different operating systems. - * It may be out-of-date. Consult the documentation of the operating system before considering to use the methods below. - * - * Platform randomness sources: - * Linux -> `getrandom(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. http://man7.org/linux/man-pages/man2/getrandom.2.html, https://linux.die.net/man/4/urandom - * macOS -> `getentropy(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. https://www.unix.com/man-page/mojave/2/getentropy, https://opensource.apple.com/source/xnu/xnu-517.12.7/bsd/man/man4/random.4.auto.html - * FreeBSD -> `getrandom(2)`(`sys/random.h`), if not available `kern.arandom` should be used. https://www.freebsd.org/cgi/man.cgi?query=getrandom, https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4 - * OpenBSD -> `getentropy(2)`(`unistd.h`), if not available `/dev/urandom` should be used. https://man.openbsd.org/getentropy, https://man.openbsd.org/urandom - * Windows -> `BCryptGenRandom`(`bcrypt.h`). https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom - */ - -#if defined(_WIN32) -/* - * The defined WIN32_NO_STATUS macro disables return code definitions in - * windows.h, which avoids "macro redefinition" MSVC warnings in ntstatus.h. - */ -#define WIN32_NO_STATUS -#include -#undef WIN32_NO_STATUS -#include -#include -#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) -#include -#elif defined(__OpenBSD__) -#include -#else -#error "Couldn't identify the OS" -#endif - -#include -#include -#include - - -/* Returns 1 on success, and 0 on failure. */ -static int fill_random(unsigned char* data, size_t size) { -#if defined(_WIN32) - NTSTATUS res = BCryptGenRandom(NULL, data, size, BCRYPT_USE_SYSTEM_PREFERRED_RNG); - if (res != STATUS_SUCCESS || size > ULONG_MAX) { - return 0; - } else { - return 1; - } -#elif defined(__linux__) || defined(__FreeBSD__) - /* If `getrandom(2)` is not available you should fallback to /dev/urandom */ - ssize_t res = getrandom(data, size, 0); - if (res < 0 || (size_t)res != size ) { - return 0; - } else { - return 1; - } -#elif defined(__APPLE__) || defined(__OpenBSD__) - /* If `getentropy(2)` is not available you should fallback to either - * `SecRandomCopyBytes` or /dev/urandom */ - int res = getentropy(data, size); - if (res == 0) { - return 1; - } else { - return 0; - } -#endif - return 0; -} - -static void print_hex(unsigned char* data, size_t size) { - size_t i; - printf("0x"); - for (i = 0; i < size; i++) { - printf("%02x", data[i]); - } - printf("\n"); -} - -#if defined(_MSC_VER) -// For SecureZeroMemory -#include -#endif -/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ -static void secure_erase(void *ptr, size_t len) { -#if defined(_MSC_VER) - /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */ - SecureZeroMemory(ptr, len); -#elif defined(__GNUC__) - /* We use a memory barrier that scares the compiler away from optimizing out the memset. - * - * Quoting Adam Langley in commit ad1907fe73334d6c696c8539646c21b11178f20f - * in BoringSSL (ISC License): - * As best as we can tell, this is sufficient to break any optimisations that - * might try to eliminate "superfluous" memsets. - * This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is - * pretty efficient, because the compiler can still implement the memset() efficiently, - * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by - * Yang et al. (USENIX Security 2017) for more background. - */ - memset(ptr, 0, len); - __asm__ __volatile__("" : : "r"(ptr) : "memory"); -#else - void *(*volatile const volatile_memset)(void *, int, size_t) = memset; - volatile_memset(ptr, 0, len); -#endif -} diff --git a/external/secp256k1/examples/musig.c b/external/secp256k1/examples/musig.c deleted file mode 100644 index 0352dc40f3..0000000000 --- a/external/secp256k1/examples/musig.c +++ /dev/null @@ -1,260 +0,0 @@ -/************************************************************************* - * To the extent possible under law, the author(s) have dedicated all * - * copyright and related and neighboring rights to the software in this * - * file to the public domain worldwide. This software is distributed * - * without any warranty. For the CC0 Public Domain Dedication, see * - * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * - *************************************************************************/ - -/** This file demonstrates how to use the MuSig module to create a - * 3-of-3 multisignature. Additionally, see the documentation in - * include/secp256k1_musig.h and doc/musig.md. - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include "examples_util.h" - -struct signer_secrets { - secp256k1_keypair keypair; - secp256k1_musig_secnonce secnonce; -}; - -struct signer { - secp256k1_pubkey pubkey; - secp256k1_musig_pubnonce pubnonce; - secp256k1_musig_partial_sig partial_sig; -}; - - /* Number of public keys involved in creating the aggregate signature */ -#define N_SIGNERS 3 -/* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */ -static int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) { - unsigned char seckey[32]; - - if (!fill_random(seckey, sizeof(seckey))) { - printf("Failed to generate randomness\n"); - return 0; - } - /* Try to create a keypair with a valid context. This only fails if the - * secret key is zero or out of range (greater than secp256k1's order). Note - * that the probability of this occurring is negligible with a properly - * functioning random number generator. */ - if (!secp256k1_keypair_create(ctx, &signer_secrets->keypair, seckey)) { - return 0; - } - if (!secp256k1_keypair_pub(ctx, &signer->pubkey, &signer_secrets->keypair)) { - return 0; - } - - secure_erase(seckey, sizeof(seckey)); - return 1; -} - -/* Tweak the pubkey corresponding to the provided keyagg cache, update the cache - * and return the tweaked aggregate pk. */ -static int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache) { - secp256k1_pubkey output_pk; - /* For BIP 32 tweaking the plain_tweak is set to a hash as defined in BIP - * 32. */ - unsigned char plain_tweak[32] = "this could be a BIP32 tweak...."; - /* For Taproot tweaking the xonly_tweak is set to the TapTweak hash as - * defined in BIP 341 */ - unsigned char xonly_tweak[32] = "this could be a Taproot tweak.."; - - - /* Plain tweaking which, for example, allows deriving multiple child - * public keys from a single aggregate key using BIP32 */ - if (!secp256k1_musig_pubkey_ec_tweak_add(ctx, NULL, cache, plain_tweak)) { - return 0; - } - /* Note that we did not provide an output_pk argument, because the - * resulting pk is also saved in the cache and so if one is just interested - * in signing, the output_pk argument is unnecessary. On the other hand, if - * one is not interested in signing, the same output_pk can be obtained by - * calling `secp256k1_musig_pubkey_get` right after key aggregation to get - * the full pubkey and then call `secp256k1_ec_pubkey_tweak_add`. */ - - /* Xonly tweaking which, for example, allows creating Taproot commitments */ - if (!secp256k1_musig_pubkey_xonly_tweak_add(ctx, &output_pk, cache, xonly_tweak)) { - return 0; - } - /* Note that if we wouldn't care about signing, we can arrive at the same - * output_pk by providing the untweaked public key to - * `secp256k1_xonly_pubkey_tweak_add` (after converting it to an xonly pubkey - * if necessary with `secp256k1_xonly_pubkey_from_pubkey`). */ - - /* Now we convert the output_pk to an xonly pubkey to allow to later verify - * the Schnorr signature against it. For this purpose we can ignore the - * `pk_parity` output argument; we would need it if we would have to open - * the Taproot commitment. */ - if (!secp256k1_xonly_pubkey_from_pubkey(ctx, agg_pk, NULL, &output_pk)) { - return 0; - } - return 1; -} - -/* Sign a message hash with the given key pairs and store the result in sig */ -static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) { - int i; - const secp256k1_musig_pubnonce *pubnonces[N_SIGNERS]; - const secp256k1_musig_partial_sig *partial_sigs[N_SIGNERS]; - /* The same for all signers */ - secp256k1_musig_session session; - secp256k1_musig_aggnonce agg_pubnonce; - - for (i = 0; i < N_SIGNERS; i++) { - unsigned char seckey[32]; - unsigned char session_secrand[32]; - /* Create random session ID. It is absolutely necessary that the session ID - * is unique for every call of secp256k1_musig_nonce_gen. Otherwise - * it's trivial for an attacker to extract the secret key! */ - if (!fill_random(session_secrand, sizeof(session_secrand))) { - return 0; - } - if (!secp256k1_keypair_sec(ctx, seckey, &signer_secrets[i].keypair)) { - return 0; - } - /* Initialize session and create secret nonce for signing and public - * nonce to send to the other signers. */ - if (!secp256k1_musig_nonce_gen(ctx, &signer_secrets[i].secnonce, &signer[i].pubnonce, session_secrand, seckey, &signer[i].pubkey, msg32, NULL, NULL)) { - return 0; - } - pubnonces[i] = &signer[i].pubnonce; - - secure_erase(seckey, sizeof(seckey)); - } - - /* Communication round 1: Every signer sends their pubnonce to the - * coordinator. The coordinator runs secp256k1_musig_nonce_agg and sends - * agg_pubnonce to each signer */ - if (!secp256k1_musig_nonce_agg(ctx, &agg_pubnonce, pubnonces, N_SIGNERS)) { - return 0; - } - - /* Every signer creates a partial signature */ - for (i = 0; i < N_SIGNERS; i++) { - /* Initialize the signing session by processing the aggregate nonce */ - if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, cache)) { - return 0; - } - /* partial_sign will clear the secnonce by setting it to 0. That's because - * you must _never_ reuse the secnonce (or use the same session_secrand to - * create a secnonce). If you do, you effectively reuse the nonce and - * leak the secret key. */ - if (!secp256k1_musig_partial_sign(ctx, &signer[i].partial_sig, &signer_secrets[i].secnonce, &signer_secrets[i].keypair, cache, &session)) { - return 0; - } - partial_sigs[i] = &signer[i].partial_sig; - } - /* Communication round 2: Every signer sends their partial signature to the - * coordinator, who verifies the partial signatures and aggregates them. */ - for (i = 0; i < N_SIGNERS; i++) { - /* To check whether signing was successful, it suffices to either verify - * the aggregate signature with the aggregate public key using - * secp256k1_schnorrsig_verify, or verify all partial signatures of all - * signers individually. Verifying the aggregate signature is cheaper but - * verifying the individual partial signatures has the advantage that it - * can be used to determine which of the partial signatures are invalid - * (if any), i.e., which of the partial signatures cause the aggregate - * signature to be invalid and thus the protocol run to fail. It's also - * fine to first verify the aggregate sig, and only verify the individual - * sigs if it does not work. - */ - if (!secp256k1_musig_partial_sig_verify(ctx, &signer[i].partial_sig, &signer[i].pubnonce, &signer[i].pubkey, cache, &session)) { - return 0; - } - } - return secp256k1_musig_partial_sig_agg(ctx, sig64, &session, partial_sigs, N_SIGNERS); -} - -int main(void) { - secp256k1_context* ctx; - int i; - struct signer_secrets signer_secrets[N_SIGNERS]; - struct signer signers[N_SIGNERS]; - const secp256k1_pubkey *pubkeys_ptr[N_SIGNERS]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_musig_keyagg_cache cache; - unsigned char msg[32] = "this_could_be_the_hash_of_a_msg"; - unsigned char sig[64]; - - /* Create a secp256k1 context */ - ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - printf("Creating key pairs......"); - fflush(stdout); - for (i = 0; i < N_SIGNERS; i++) { - if (!create_keypair(ctx, &signer_secrets[i], &signers[i])) { - printf("FAILED\n"); - return 1; - } - pubkeys_ptr[i] = &signers[i].pubkey; - } - printf("ok\n"); - - /* The aggregate public key produced by secp256k1_musig_pubkey_agg depends - * on the order of the provided public keys. If there is no canonical order - * of the signers, the individual public keys can optionally be sorted with - * secp256k1_ec_pubkey_sort to ensure that the aggregate public key is - * independent of the order of signers. */ - printf("Sorting public keys....."); - fflush(stdout); - if (!secp256k1_ec_pubkey_sort(ctx, pubkeys_ptr, N_SIGNERS)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - - printf("Combining public keys..."); - fflush(stdout); - /* If you just want to aggregate and not sign, you can call - * secp256k1_musig_pubkey_agg with the keyagg_cache argument set to NULL - * while providing a non-NULL agg_pk argument. */ - if (!secp256k1_musig_pubkey_agg(ctx, NULL, &cache, pubkeys_ptr, N_SIGNERS)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - printf("Tweaking................"); - fflush(stdout); - /* Optionally tweak the aggregate key */ - if (!tweak(ctx, &agg_pk, &cache)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - printf("Signing message........."); - fflush(stdout); - if (!sign(ctx, signer_secrets, signers, &cache, msg, sig)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - printf("Verifying signature....."); - fflush(stdout); - if (!secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &agg_pk)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - - /* It's best practice to try to clear secrets from memory after using them. - * This is done because some bugs can allow an attacker to leak memory, for - * example through "out of bounds" array access (see Heartbleed), or the OS - * swapping them to disk. Hence, we overwrite secret key material with zeros. - * - * Here we are preventing these writes from being optimized out, as any good compiler - * will remove any writes that aren't used. */ - for (i = 0; i < N_SIGNERS; i++) { - secure_erase(&signer_secrets[i], sizeof(signer_secrets[i])); - } - secp256k1_context_destroy(ctx); - return 0; -} diff --git a/external/secp256k1/examples/schnorr.c b/external/secp256k1/examples/schnorr.c deleted file mode 100644 index 909fcaa1f3..0000000000 --- a/external/secp256k1/examples/schnorr.c +++ /dev/null @@ -1,153 +0,0 @@ -/************************************************************************* - * Written in 2020-2022 by Elichai Turkel * - * To the extent possible under law, the author(s) have dedicated all * - * copyright and related and neighboring rights to the software in this * - * file to the public domain worldwide. This software is distributed * - * without any warranty. For the CC0 Public Domain Dedication, see * - * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * - *************************************************************************/ - -#include -#include -#include - -#include -#include -#include - -#include "examples_util.h" - -int main(void) { - unsigned char msg[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'}; - unsigned char msg_hash[32]; - unsigned char tag[] = {'m', 'y', '_', 'f', 'a', 'n', 'c', 'y', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l'}; - unsigned char seckey[32]; - unsigned char randomize[32]; - unsigned char auxiliary_rand[32]; - unsigned char serialized_pubkey[32]; - unsigned char signature[64]; - int is_signature_valid, is_signature_valid2; - int return_val; - secp256k1_xonly_pubkey pubkey; - secp256k1_keypair keypair; - /* Before we can call actual API functions, we need to create a "context". */ - secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - if (!fill_random(randomize, sizeof(randomize))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* Randomizing the context is recommended to protect against side-channel - * leakage See `secp256k1_context_randomize` in secp256k1.h for more - * information about it. This should never fail. */ - return_val = secp256k1_context_randomize(ctx, randomize); - assert(return_val); - - /*** Key Generation ***/ - if (!fill_random(seckey, sizeof(seckey))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* Try to create a keypair with a valid context. This only fails if the - * secret key is zero or out of range (greater than secp256k1's order). Note - * that the probability of this occurring is negligible with a properly - * functioning random number generator. */ - if (!secp256k1_keypair_create(ctx, &keypair, seckey)) { - printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; - } - - /* Extract the X-only public key from the keypair. We pass NULL for - * `pk_parity` as the parity isn't needed for signing or verification. - * `secp256k1_keypair_xonly_pub` supports returning the parity for - * other use cases such as tests or verifying Taproot tweaks. - * This should never fail with a valid context and public key. */ - return_val = secp256k1_keypair_xonly_pub(ctx, &pubkey, NULL, &keypair); - assert(return_val); - - /* Serialize the public key. Should always return 1 for a valid public key. */ - return_val = secp256k1_xonly_pubkey_serialize(ctx, serialized_pubkey, &pubkey); - assert(return_val); - - /*** Signing ***/ - - /* Instead of signing (possibly very long) messages directly, we sign a - * 32-byte hash of the message in this example. - * - * We use secp256k1_tagged_sha256 to create this hash. This function expects - * a context-specific "tag", which restricts the context in which the signed - * messages should be considered valid. For example, if protocol A mandates - * to use the tag "my_fancy_protocol" and protocol B mandates to use the tag - * "my_boring_protocol", then signed messages from protocol A will never be - * valid in protocol B (and vice versa), even if keys are reused across - * protocols. This implements "domain separation", which is considered good - * practice. It avoids attacks in which users are tricked into signing a - * message that has intended consequences in the intended context (e.g., - * protocol A) but would have unintended consequences if it were valid in - * some other context (e.g., protocol B). */ - return_val = secp256k1_tagged_sha256(ctx, msg_hash, tag, sizeof(tag), msg, sizeof(msg)); - assert(return_val); - - /* Generate 32 bytes of randomness to use with BIP-340 schnorr signing. */ - if (!fill_random(auxiliary_rand, sizeof(auxiliary_rand))) { - printf("Failed to generate randomness\n"); - return 1; - } - - /* Generate a Schnorr signature. - * - * We use the secp256k1_schnorrsig_sign32 function that provides a simple - * interface for signing 32-byte messages (which in our case is a hash of - * the actual message). BIP-340 recommends passing 32 bytes of randomness - * to the signing function to improve security against side-channel attacks. - * Signing with a valid context, a 32-byte message, a verified keypair, and - * any 32 bytes of auxiliary random data should never fail. */ - return_val = secp256k1_schnorrsig_sign32(ctx, signature, msg_hash, &keypair, auxiliary_rand); - assert(return_val); - - /*** Verification ***/ - - /* Deserialize the public key. This will return 0 if the public key can't - * be parsed correctly */ - if (!secp256k1_xonly_pubkey_parse(ctx, &pubkey, serialized_pubkey)) { - printf("Failed parsing the public key\n"); - return 1; - } - - /* Compute the tagged hash on the received messages using the same tag as the signer. */ - return_val = secp256k1_tagged_sha256(ctx, msg_hash, tag, sizeof(tag), msg, sizeof(msg)); - assert(return_val); - - /* Verify a signature. This will return 1 if it's valid and 0 if it's not. */ - is_signature_valid = secp256k1_schnorrsig_verify(ctx, signature, msg_hash, 32, &pubkey); - - - printf("Is the signature valid? %s\n", is_signature_valid ? "true" : "false"); - printf("Secret Key: "); - print_hex(seckey, sizeof(seckey)); - printf("Public Key: "); - print_hex(serialized_pubkey, sizeof(serialized_pubkey)); - printf("Signature: "); - print_hex(signature, sizeof(signature)); - - /* This will clear everything from the context and free the memory */ - secp256k1_context_destroy(ctx); - - /* Bonus example: if all we need is signature verification (and no key - generation or signing), we don't need to use a context created via - secp256k1_context_create(). We can simply use the static (i.e., global) - context secp256k1_context_static. See its description in - include/secp256k1.h for details. */ - is_signature_valid2 = secp256k1_schnorrsig_verify(secp256k1_context_static, - signature, msg_hash, 32, &pubkey); - assert(is_signature_valid2 == is_signature_valid); - - /* It's best practice to try to clear secrets from memory after using them. - * This is done because some bugs can allow an attacker to leak memory, for - * example through "out of bounds" array access (see Heartbleed), or the OS - * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. - * - * Here we are preventing these writes from being optimized out, as any good compiler - * will remove any writes that aren't used. */ - secure_erase(seckey, sizeof(seckey)); - return 0; -} diff --git a/external/secp256k1/include/secp256k1.h b/external/secp256k1/include/secp256k1.h deleted file mode 100644 index e562cd00e8..0000000000 --- a/external/secp256k1/include/secp256k1.h +++ /dev/null @@ -1,899 +0,0 @@ -#ifndef SECP256K1_H -#define SECP256K1_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** Unless explicitly stated all pointer arguments must not be NULL. - * - * The following rules specify the order of arguments in API calls: - * - * 1. Context pointers go first, followed by output arguments, combined - * output/input arguments, and finally input-only arguments. - * 2. Array lengths always immediately follow the argument whose length - * they describe, even if this violates rule 1. - * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated - * later go first. This means: signatures, public nonces, secret nonces, - * messages, public keys, secret keys, tweaks. - * 4. Arguments that are not data pointers go last, from more complex to less - * complex: function pointers, algorithm names, messages, void pointers, - * counts, flags, booleans. - * 5. Opaque data pointers follow the function pointer they are to be passed to. - */ - -/** Opaque data structure that holds context information - * - * The primary purpose of context objects is to store randomization data for - * enhanced protection against side-channel leakage. This protection is only - * effective if the context is randomized after its creation. See - * secp256k1_context_create for creation of contexts and - * secp256k1_context_randomize for randomization. - * - * A secondary purpose of context objects is to store pointers to callback - * functions that the library will call when certain error states arise. See - * secp256k1_context_set_error_callback as well as - * secp256k1_context_set_illegal_callback for details. Future library versions - * may use context objects for additional purposes. - * - * A constructed context can safely be used from multiple threads - * simultaneously, but API calls that take a non-const pointer to a context - * need exclusive access to it. In particular this is the case for - * secp256k1_context_destroy, secp256k1_context_preallocated_destroy, - * and secp256k1_context_randomize. - * - * Regarding randomization, either do it once at creation time (in which case - * you do not need any locking for the other calls), or use a read-write lock. - */ -typedef struct secp256k1_context_struct secp256k1_context; - -/** Opaque data structure that holds a parsed and valid public key. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage or transmission, - * use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. To - * compare keys, use secp256k1_ec_pubkey_cmp. - */ -typedef struct secp256k1_pubkey { - unsigned char data[64]; -} secp256k1_pubkey; - -/** Opaque data structure that holds a parsed ECDSA signature. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage, transmission, or - * comparison, use the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_parse_* functions. - */ -typedef struct secp256k1_ecdsa_signature { - unsigned char data[64]; -} secp256k1_ecdsa_signature; - -/** A pointer to a function to deterministically generate a nonce. - * - * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. - * Out: nonce32: pointer to a 32-byte array to be filled by the function. - * In: msg32: the 32-byte message hash being verified (will not be NULL) - * key32: pointer to a 32-byte secret key (will not be NULL) - * algo16: pointer to a 16-byte array describing the signature - * algorithm (will be NULL for ECDSA for compatibility). - * data: Arbitrary data pointer that is passed through. - * attempt: how many iterations we have tried to find a nonce. - * This will almost always be 0, but different attempt values - * are required to result in a different nonce. - * - * Except for test cases, this function should compute some cryptographic hash of - * the message, the algorithm, the key and the attempt. - */ -typedef int (*secp256k1_nonce_function)( - unsigned char *nonce32, - const unsigned char *msg32, - const unsigned char *key32, - const unsigned char *algo16, - void *data, - unsigned int attempt -); - -# if !defined(SECP256K1_GNUC_PREREQ) -# if defined(__GNUC__)&&defined(__GNUC_MINOR__) -# define SECP256K1_GNUC_PREREQ(_maj,_min) \ - ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) -# else -# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 -# endif -# endif - -/* When this header is used at build-time the SECP256K1_BUILD define needs to be set - * to correctly setup export attributes and nullness checks. This is normally done - * by secp256k1.c but to guard against this header being included before secp256k1.c - * has had a chance to set the define (e.g. via test harnesses that just includes - * secp256k1.c) we set SECP256K1_NO_BUILD when this header is processed without the - * BUILD define so this condition can be caught. - */ -#ifndef SECP256K1_BUILD -# define SECP256K1_NO_BUILD -#endif - -/* Symbol visibility. */ -#if defined(_WIN32) - /* GCC for Windows (e.g., MinGW) accepts the __declspec syntax - * for MSVC compatibility. A __declspec declaration implies (but is not - * exactly equivalent to) __attribute__ ((visibility("default"))), and so we - * actually want __declspec even on GCC, see "Microsoft Windows Function - * Attributes" in the GCC manual and the recommendations in - * https://gcc.gnu.org/wiki/Visibility. */ -# if defined(SECP256K1_BUILD) -# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT) - /* Building libsecp256k1 as a DLL. - * 1. If using Libtool, it defines DLL_EXPORT automatically. - * 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */ -# define SECP256K1_API extern __declspec (dllexport) -# else - /* Building libsecp256k1 as a static library on Windows. - * No declspec is needed, and so we would want the non-Windows-specific - * logic below take care of this case. However, this may result in setting - * __attribute__ ((visibility("default"))), which is supposed to be a noop - * on Windows but may trigger warnings when compiling with -flto due to a - * bug in GCC, see - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */ -# define SECP256K1_API extern -# endif - /* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static - * library on Windows. */ -# elif !defined(SECP256K1_STATIC) - /* Consuming libsecp256k1 as a DLL. */ -# define SECP256K1_API extern __declspec (dllimport) -# endif -#endif -#ifndef SECP256K1_API -/* All cases not captured by the Windows-specific logic. */ -# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD) - /* Building libsecp256k1 using GCC or compatible. */ -# define SECP256K1_API extern __attribute__ ((visibility ("default"))) -# else - /* Fall back to standard C's extern. */ -# define SECP256K1_API extern -# endif -#endif - -/* Warning attributes - * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out - * some paranoid null checks. */ -# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) -# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) -# else -# define SECP256K1_WARN_UNUSED_RESULT -# endif -# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) -# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) -# else -# define SECP256K1_ARG_NONNULL(_x) -# endif - -/* Attribute for marking functions, types, and variables as deprecated */ -#if !defined(SECP256K1_BUILD) && defined(__has_attribute) -# if __has_attribute(__deprecated__) -# define SECP256K1_DEPRECATED(_msg) __attribute__ ((__deprecated__(_msg))) -# else -# define SECP256K1_DEPRECATED(_msg) -# endif -#else -# define SECP256K1_DEPRECATED(_msg) -#endif - -/* All flags' lower 8 bits indicate what they're for. Do not use directly. */ -#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) -#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) -#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) -/* The higher bits contain the actual data. Do not use directly. */ -#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) -#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) -#define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10) -#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) - -/** Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and - * secp256k1_context_preallocated_create. */ -#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) - -/** Deprecated context flags. These flags are treated equivalent to SECP256K1_CONTEXT_NONE. */ -#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) -#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) - -/* Testing flag. Do not use. */ -#define SECP256K1_CONTEXT_DECLASSIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY) - -/** Flag to pass to secp256k1_ec_pubkey_serialize. */ -#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) -#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) - -/** Prefix byte used to tag various encoded curvepoints for specific purposes */ -#define SECP256K1_TAG_PUBKEY_EVEN 0x02 -#define SECP256K1_TAG_PUBKEY_ODD 0x03 -#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04 -#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 -#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 - -/** A built-in constant secp256k1 context object with static storage duration, to be - * used in conjunction with secp256k1_selftest. - * - * This context object offers *only limited functionality* , i.e., it cannot be used - * for API functions that perform computations involving secret keys, e.g., signing - * and public key generation. If this restriction applies to a specific API function, - * it is mentioned in its documentation. See secp256k1_context_create if you need a - * full context object that supports all functionality offered by the library. - * - * It is highly recommended to call secp256k1_selftest before using this context. - */ -SECP256K1_API const secp256k1_context *secp256k1_context_static; - -/** Deprecated alias for secp256k1_context_static. */ -SECP256K1_API const secp256k1_context *secp256k1_context_no_precomp -SECP256K1_DEPRECATED("Use secp256k1_context_static instead"); - -/** Perform basic self tests (to be used in conjunction with secp256k1_context_static) - * - * This function performs self tests that detect some serious usage errors and - * similar conditions, e.g., when the library is compiled for the wrong endianness. - * This is a last resort measure to be used in production. The performed tests are - * very rudimentary and are not intended as a replacement for running the test - * binaries. - * - * It is highly recommended to call this before using secp256k1_context_static. - * It is not necessary to call this function before using a context created with - * secp256k1_context_create (or secp256k1_context_preallocated_create), which will - * take care of performing the self tests. - * - * If the tests fail, this function will call the default error handler to abort the - * program (see secp256k1_context_set_error_callback). - */ -SECP256K1_API void secp256k1_selftest(void); - - -/** Create a secp256k1 context object (in dynamically allocated memory). - * - * This function uses malloc to allocate memory. It is guaranteed that malloc is - * called at most once for every call of this function. If you need to avoid dynamic - * memory allocation entirely, see secp256k1_context_static and the functions in - * secp256k1_preallocated.h. - * - * Returns: pointer to a newly created context object. - * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below). - * - * The only valid non-deprecated flag in recent library versions is - * SECP256K1_CONTEXT_NONE, which will create a context sufficient for all functionality - * offered by the library. All other (deprecated) flags will be treated as equivalent - * to the SECP256K1_CONTEXT_NONE flag. Though the flags parameter primarily exists for - * historical reasons, future versions of the library may introduce new flags. - * - * If the context is intended to be used for API functions that perform computations - * involving secret keys, e.g., signing and public key generation, then it is highly - * recommended to call secp256k1_context_randomize on the context before calling - * those API functions. This will provide enhanced protection against side-channel - * leakage, see secp256k1_context_randomize for details. - * - * Do not create a new context object for each operation, as construction and - * randomization can take non-negligible time. - */ -SECP256K1_API secp256k1_context *secp256k1_context_create( - unsigned int flags -) SECP256K1_WARN_UNUSED_RESULT; - -/** Copy a secp256k1 context object (into dynamically allocated memory). - * - * This function uses malloc to allocate memory. It is guaranteed that malloc is - * called at most once for every call of this function. If you need to avoid dynamic - * memory allocation entirely, see the functions in secp256k1_preallocated.h. - * - * Cloning secp256k1_context_static is not possible, and should not be emulated by - * the caller (e.g., using memcpy). Create a new context instead. - * - * Returns: pointer to a newly created context object. - * Args: ctx: pointer to a context to copy (not secp256k1_context_static). - */ -SECP256K1_API secp256k1_context *secp256k1_context_clone( - const secp256k1_context *ctx -) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; - -/** Destroy a secp256k1 context object (created in dynamically allocated memory). - * - * The context pointer may not be used afterwards. - * - * The context to destroy must have been created using secp256k1_context_create - * or secp256k1_context_clone. If the context has instead been created using - * secp256k1_context_preallocated_create or secp256k1_context_preallocated_clone, the - * behaviour is undefined. In that case, secp256k1_context_preallocated_destroy must - * be used instead. - * - * Args: ctx: pointer to a context to destroy, constructed using - * secp256k1_context_create or secp256k1_context_clone - * (i.e., not secp256k1_context_static). - */ -SECP256K1_API void secp256k1_context_destroy( - secp256k1_context *ctx -) SECP256K1_ARG_NONNULL(1); - -/** Set a callback function to be called when an illegal argument is passed to - * an API call. It will only trigger for violations that are mentioned - * explicitly in the header. - * - * The philosophy is that these shouldn't be dealt with through a - * specific return value, as calling code should not have branches to deal with - * the case that this code itself is broken. - * - * On the other hand, during debug stage, one would want to be informed about - * such mistakes, and the default (crashing) may be inadvisable. - * When this callback is triggered, the API function called is guaranteed not - * to cause a crash, though its return value and output arguments are - * undefined. - * - * When this function has not been called (or called with fn==NULL), then the - * default handler will be used. The library provides a default handler which - * writes the message to stderr and calls abort. This default handler can be - * replaced at link time if the preprocessor macro - * USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build - * has been configured with --enable-external-default-callbacks. Then the - * following two symbols must be provided to link against: - * - void secp256k1_default_illegal_callback_fn(const char *message, void *data); - * - void secp256k1_default_error_callback_fn(const char *message, void *data); - * The library can call these default handlers even before a proper callback data - * pointer could have been set using secp256k1_context_set_illegal_callback or - * secp256k1_context_set_error_callback, e.g., when the creation of a context - * fails. In this case, the corresponding default handler will be called with - * the data pointer argument set to NULL. - * - * Args: ctx: pointer to a context object. - * In: fun: pointer to a function to call when an illegal argument is - * passed to the API, taking a message and an opaque pointer. - * (NULL restores the default handler.) - * data: the opaque pointer to pass to fun above, must be NULL for the default handler. - * - * See also secp256k1_context_set_error_callback. - */ -SECP256K1_API void secp256k1_context_set_illegal_callback( - secp256k1_context *ctx, - void (*fun)(const char *message, void *data), - const void *data -) SECP256K1_ARG_NONNULL(1); - -/** Set a callback function to be called when an internal consistency check - * fails. - * - * The default callback writes an error message to stderr and calls abort - * to abort the program. - * - * This can only trigger in case of a hardware failure, miscompilation, - * memory corruption, serious bug in the library, or other error would can - * otherwise result in undefined behaviour. It will not trigger due to mere - * incorrect usage of the API (see secp256k1_context_set_illegal_callback - * for that). After this callback returns, anything may happen, including - * crashing. - * - * Args: ctx: pointer to a context object. - * In: fun: pointer to a function to call when an internal error occurs, - * taking a message and an opaque pointer (NULL restores the - * default handler, see secp256k1_context_set_illegal_callback - * for details). - * data: the opaque pointer to pass to fun above, must be NULL for the default handler. - * - * See also secp256k1_context_set_illegal_callback. - */ -SECP256K1_API void secp256k1_context_set_error_callback( - secp256k1_context *ctx, - void (*fun)(const char *message, void *data), - const void *data -) SECP256K1_ARG_NONNULL(1); - -/** Parse a variable-length public key into the pubkey object. - * - * Returns: 1 if the public key was fully valid. - * 0 if the public key could not be parsed or is invalid. - * Args: ctx: pointer to a context object. - * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a - * parsed version of input. If not, its value is undefined. - * In: input: pointer to a serialized public key - * inputlen: length of the array pointed to by input - * - * This function supports parsing compressed (33 bytes, header byte 0x02 or - * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header - * byte 0x06 or 0x07) format public keys. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( - const secp256k1_context *ctx, - secp256k1_pubkey *pubkey, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize a pubkey object into a serialized byte sequence. - * - * Returns: 1 always. - * Args: ctx: pointer to a context object. - * Out: output: pointer to a 65-byte (if compressed==0) or 33-byte (if - * compressed==1) byte array to place the serialized key - * in. - * In/Out: outputlen: pointer to an integer which is initially set to the - * size of output, and is overwritten with the written - * size. - * In: pubkey: pointer to a secp256k1_pubkey containing an - * initialized public key. - * flags: SECP256K1_EC_COMPRESSED if serialization should be in - * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. - */ -SECP256K1_API int secp256k1_ec_pubkey_serialize( - const secp256k1_context *ctx, - unsigned char *output, - size_t *outputlen, - const secp256k1_pubkey *pubkey, - unsigned int flags -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Compare two public keys using lexicographic (of compressed serialization) order - * - * Returns: <0 if the first public key is less than the second - * >0 if the first public key is greater than the second - * 0 if the two public keys are equal - * Args: ctx: pointer to a context object - * In: pubkey1: first public key to compare - * pubkey2: second public key to compare - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_cmp( - const secp256k1_context *ctx, - const secp256k1_pubkey *pubkey1, - const secp256k1_pubkey *pubkey2 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Sort public keys using lexicographic (of compressed serialization) order - * - * Returns: 0 if the arguments are invalid. 1 otherwise. - * - * Args: ctx: pointer to a context object - * In: pubkeys: array of pointers to pubkeys to sort - * n_pubkeys: number of elements in the pubkeys array - */ -SECP256K1_API int secp256k1_ec_pubkey_sort( - const secp256k1_context *ctx, - const secp256k1_pubkey **pubkeys, - size_t n_pubkeys -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - -/** Parse an ECDSA signature in compact (64 bytes) format. - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: pointer to a context object - * Out: sig: pointer to a signature object - * In: input64: pointer to the 64-byte array to parse - * - * The signature must consist of a 32-byte big endian R value, followed by a - * 32-byte big endian S value. If R or S fall outside of [0..order-1], the - * encoding is invalid. R and S with value 0 are allowed in the encoding. - * - * After the call, sig will always be initialized. If parsing failed or R or - * S are zero, the resulting sig value is guaranteed to fail verification for - * any message and public key. - */ -SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( - const secp256k1_context *ctx, - secp256k1_ecdsa_signature *sig, - const unsigned char *input64 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Parse a DER ECDSA signature. - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: pointer to a context object - * Out: sig: pointer to a signature object - * In: input: pointer to the signature to be parsed - * inputlen: the length of the array pointed to be input - * - * This function will accept any valid DER encoded signature, even if the - * encoded numbers are out of range. - * - * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature verification with it is - * guaranteed to fail for every message and public key. - */ -SECP256K1_API int secp256k1_ecdsa_signature_parse_der( - const secp256k1_context *ctx, - secp256k1_ecdsa_signature *sig, - const unsigned char *input, - size_t inputlen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an ECDSA signature in DER format. - * - * Returns: 1 if enough space was available to serialize, 0 otherwise - * Args: ctx: pointer to a context object - * Out: output: pointer to an array to store the DER serialization - * In/Out: outputlen: pointer to a length integer. Initially, this integer - * should be set to the length of output. After the call - * it will be set to the length of the serialization (even - * if 0 was returned). - * In: sig: pointer to an initialized signature object - */ -SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( - const secp256k1_context *ctx, - unsigned char *output, - size_t *outputlen, - const secp256k1_ecdsa_signature *sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Serialize an ECDSA signature in compact (64 byte) format. - * - * Returns: 1 - * Args: ctx: pointer to a context object - * Out: output64: pointer to a 64-byte array to store the compact serialization - * In: sig: pointer to an initialized signature object - * - * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. - */ -SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( - const secp256k1_context *ctx, - unsigned char *output64, - const secp256k1_ecdsa_signature *sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Verify an ECDSA signature. - * - * Returns: 1: correct signature - * 0: incorrect or unparsable signature - * Args: ctx: pointer to a context object - * In: sig: the signature being verified. - * msghash32: the 32-byte message hash being verified. - * The verifier must make sure to apply a cryptographic - * hash function to the message by itself and not accept an - * msghash32 value directly. Otherwise, it would be easy to - * create a "valid" signature without knowledge of the - * secret key. See also - * https://bitcoin.stackexchange.com/a/81116/35586 for more - * background on this topic. - * pubkey: pointer to an initialized public key to verify with. - * - * To avoid accepting malleable signatures, only ECDSA signatures in lower-S - * form are accepted. - * - * If you need to accept ECDSA signatures from sources that do not obey this - * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to - * verification, but be aware that doing so results in malleable signatures. - * - * For details, see the comments for that function. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( - const secp256k1_context *ctx, - const secp256k1_ecdsa_signature *sig, - const unsigned char *msghash32, - const secp256k1_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Convert a signature to a normalized lower-S form. - * - * Returns: 1 if sigin was not normalized, 0 if it already was. - * Args: ctx: pointer to a context object - * Out: sigout: pointer to a signature to fill with the normalized form, - * or copy if the input was already normalized. (can be NULL if - * you're only interested in whether the input was already - * normalized). - * In: sigin: pointer to a signature to check/normalize (can be identical to sigout) - * - * With ECDSA a third-party can forge a second distinct signature of the same - * message, given a single initial signature, but without knowing the key. This - * is done by negating the S value modulo the order of the curve, 'flipping' - * the sign of the random point R which is not included in the signature. - * - * Forgery of the same message isn't universally problematic, but in systems - * where message malleability or uniqueness of signatures is important this can - * cause issues. This forgery can be blocked by all verifiers forcing signers - * to use a normalized form. - * - * The lower-S form reduces the size of signatures slightly on average when - * variable length encodings (such as DER) are used and is cheap to verify, - * making it a good choice. Security of always using lower-S is assured because - * anyone can trivially modify a signature after the fact to enforce this - * property anyway. - * - * The lower S value is always between 0x1 and - * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, - * inclusive. - * - * No other forms of ECDSA malleability are known and none seem likely, but - * there is no formal proof that ECDSA, even with this additional restriction, - * is free of other malleability. Commonly used serialization schemes will also - * accept various non-unique encodings, so care should be taken when this - * property is required for an application. - * - * The secp256k1_ecdsa_sign function will by default create signatures in the - * lower-S form, and secp256k1_ecdsa_verify will not accept others. In case - * signatures come from a system that cannot enforce this property, - * secp256k1_ecdsa_signature_normalize must be called before verification. - */ -SECP256K1_API int secp256k1_ecdsa_signature_normalize( - const secp256k1_context *ctx, - secp256k1_ecdsa_signature *sigout, - const secp256k1_ecdsa_signature *sigin -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); - -/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. - * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of - * extra entropy. - */ -SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; - -/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ -SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default; - -/** Create an ECDSA signature. - * - * Returns: 1: signature created - * 0: the nonce generation function failed, or the secret key was invalid. - * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: sig: pointer to an array where the signature will be placed. - * In: msghash32: the 32-byte message hash being signed. - * seckey: pointer to a 32-byte secret key. - * noncefp: pointer to a nonce generation function. If NULL, - * secp256k1_nonce_function_default is used. - * ndata: pointer to arbitrary data used by the nonce generation function - * (can be NULL). If it is non-NULL and - * secp256k1_nonce_function_default is used, then ndata must be a - * pointer to 32-bytes of additional data. - * - * The created signature is always in lower-S form. See - * secp256k1_ecdsa_signature_normalize for more details. - */ -SECP256K1_API int secp256k1_ecdsa_sign( - const secp256k1_context *ctx, - secp256k1_ecdsa_signature *sig, - const unsigned char *msghash32, - const unsigned char *seckey, - secp256k1_nonce_function noncefp, - const void *ndata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Verify an elliptic curve secret key. - * - * A secret key is valid if it is not 0 and less than the secp256k1 curve order - * when interpreted as an integer (most significant byte first). The - * probability of choosing a 32-byte string uniformly at random which is an - * invalid secret key is negligible. However, if it does happen it should - * be assumed that the randomness source is severely broken and there should - * be no retry. - * - * Returns: 1: secret key is valid - * 0: secret key is invalid - * Args: ctx: pointer to a context object. - * In: seckey: pointer to a 32-byte secret key. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( - const secp256k1_context *ctx, - const unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - -/** Compute the public key for a secret key. - * - * Returns: 1: secret was valid, public key stores. - * 0: secret was invalid, try again. - * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: pubkey: pointer to the created public key. - * In: seckey: pointer to a 32-byte secret key. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( - const secp256k1_context *ctx, - secp256k1_pubkey *pubkey, - const unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Negates a secret key in place. - * - * Returns: 0 if the given secret key is invalid according to - * secp256k1_ec_seckey_verify. 1 otherwise - * Args: ctx: pointer to a context object - * In/Out: seckey: pointer to the 32-byte secret key to be negated. If the - * secret key is invalid according to - * secp256k1_ec_seckey_verify, this function returns 0 and - * seckey will be set to some unspecified value. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_negate( - const secp256k1_context *ctx, - unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - -/** Same as secp256k1_ec_seckey_negate, but DEPRECATED. Will be removed in - * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate( - const secp256k1_context *ctx, - unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) - SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_negate instead"); - -/** Negates a public key in place. - * - * Returns: 1 always - * Args: ctx: pointer to a context object - * In/Out: pubkey: pointer to the public key to be negated. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate( - const secp256k1_context *ctx, - secp256k1_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - -/** Tweak a secret key by adding tweak to it. - * - * Returns: 0 if the arguments are invalid or the resulting secret key would be - * invalid (only when the tweak is the negation of the secret key). 1 - * otherwise. - * Args: ctx: pointer to a context object. - * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is - * invalid according to secp256k1_ec_seckey_verify, this - * function returns 0. seckey will be set to some unspecified - * value if this function returns 0. - * In: tweak32: pointer to a 32-byte tweak, which must be valid according to - * secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly - * random 32-byte tweaks, the chance of being invalid is - * negligible (around 1 in 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add( - const secp256k1_context *ctx, - unsigned char *seckey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Same as secp256k1_ec_seckey_tweak_add, but DEPRECATED. Will be removed in - * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( - const secp256k1_context *ctx, - unsigned char *seckey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) - SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_tweak_add instead"); - -/** Tweak a public key by adding tweak times the generator to it. - * - * Returns: 0 if the arguments are invalid or the resulting public key would be - * invalid (only when the tweak is the negation of the corresponding - * secret key). 1 otherwise. - * Args: ctx: pointer to a context object. - * In/Out: pubkey: pointer to a public key object. pubkey will be set to an - * invalid value if this function returns 0. - * In: tweak32: pointer to a 32-byte tweak, which must be valid according to - * secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly - * random 32-byte tweaks, the chance of being invalid is - * negligible (around 1 in 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( - const secp256k1_context *ctx, - secp256k1_pubkey *pubkey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Tweak a secret key by multiplying it by a tweak. - * - * Returns: 0 if the arguments are invalid. 1 otherwise. - * Args: ctx: pointer to a context object. - * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is - * invalid according to secp256k1_ec_seckey_verify, this - * function returns 0. seckey will be set to some unspecified - * value if this function returns 0. - * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to - * secp256k1_ec_seckey_verify, this function returns 0. For - * uniformly random 32-byte arrays the chance of being invalid - * is negligible (around 1 in 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_mul( - const secp256k1_context *ctx, - unsigned char *seckey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Same as secp256k1_ec_seckey_tweak_mul, but DEPRECATED. Will be removed in - * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( - const secp256k1_context *ctx, - unsigned char *seckey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) - SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_tweak_mul instead"); - -/** Tweak a public key by multiplying it by a tweak value. - * - * Returns: 0 if the arguments are invalid. 1 otherwise. - * Args: ctx: pointer to a context object. - * In/Out: pubkey: pointer to a public key object. pubkey will be set to an - * invalid value if this function returns 0. - * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to - * secp256k1_ec_seckey_verify, this function returns 0. For - * uniformly random 32-byte arrays the chance of being invalid - * is negligible (around 1 in 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( - const secp256k1_context *ctx, - secp256k1_pubkey *pubkey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Randomizes the context to provide enhanced protection against side-channel leakage. - * - * Returns: 1: randomization successful - * 0: error - * Args: ctx: pointer to a context object (not secp256k1_context_static). - * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state). - * - * While secp256k1 code is written and tested to be constant-time no matter what - * secret values are, it is possible that a compiler may output code which is not, - * and also that the CPU may not emit the same radio frequencies or draw the same - * amount of power for all values. Randomization of the context shields against - * side-channel observations which aim to exploit secret-dependent behaviour in - * certain computations which involve secret keys. - * - * It is highly recommended to call this function on contexts returned from - * secp256k1_context_create or secp256k1_context_clone (or from the corresponding - * functions in secp256k1_preallocated.h) before using these contexts to call API - * functions that perform computations involving secret keys, e.g., signing and - * public key generation. It is possible to call this function more than once on - * the same context, and doing so before every few computations involving secret - * keys is recommended as a defense-in-depth measure. Randomization of the static - * context secp256k1_context_static is not supported. - * - * Currently, the random seed is mainly used for blinding multiplications of a - * secret scalar with the elliptic curve base point. Multiplications of this - * kind are performed by exactly those API functions which are documented to - * require a context that is not secp256k1_context_static. As a rule of thumb, - * these are all functions which take a secret key (or a keypair) as an input. - * A notable exception to that rule is the ECDH module, which relies on a different - * kind of elliptic curve point multiplication and thus does not benefit from - * enhanced protection against side-channel leakage currently. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( - secp256k1_context *ctx, - const unsigned char *seed32 -) SECP256K1_ARG_NONNULL(1); - -/** Add a number of public keys together. - * - * Returns: 1: the sum of the public keys is valid. - * 0: the sum of the public keys is not valid. - * Args: ctx: pointer to a context object. - * Out: out: pointer to a public key object for placing the resulting public key. - * In: ins: pointer to array of pointers to public keys. - * n: the number of public keys to add together (must be at least 1). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( - const secp256k1_context *ctx, - secp256k1_pubkey *out, - const secp256k1_pubkey * const *ins, - size_t n -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Compute a tagged hash as defined in BIP-340. - * - * This is useful for creating a message hash and achieving domain separation - * through an application-specific tag. This function returns - * SHA256(SHA256(tag)||SHA256(tag)||msg). Therefore, tagged hash - * implementations optimized for a specific tag can precompute the SHA256 state - * after hashing the tag hashes. - * - * Returns: 1 always. - * Args: ctx: pointer to a context object - * Out: hash32: pointer to a 32-byte array to store the resulting hash - * In: tag: pointer to an array containing the tag - * taglen: length of the tag array - * msg: pointer to an array containing the message - * msglen: length of the message array - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_tagged_sha256( - const secp256k1_context *ctx, - unsigned char *hash32, - const unsigned char *tag, - size_t taglen, - const unsigned char *msg, - size_t msglen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_H */ diff --git a/external/secp256k1/include/secp256k1_ecdh.h b/external/secp256k1/include/secp256k1_ecdh.h deleted file mode 100644 index 4d9da3461d..0000000000 --- a/external/secp256k1/include/secp256k1_ecdh.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef SECP256K1_ECDH_H -#define SECP256K1_ECDH_H - -#include "secp256k1.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** A pointer to a function that hashes an EC point to obtain an ECDH secret - * - * Returns: 1 if the point was successfully hashed. - * 0 will cause secp256k1_ecdh to fail and return 0. - * Other return values are not allowed, and the behaviour of - * secp256k1_ecdh is undefined for other return values. - * Out: output: pointer to an array to be filled by the function - * In: x32: pointer to a 32-byte x coordinate - * y32: pointer to a 32-byte y coordinate - * data: arbitrary data pointer that is passed through - */ -typedef int (*secp256k1_ecdh_hash_function)( - unsigned char *output, - const unsigned char *x32, - const unsigned char *y32, - void *data -); - -/** An implementation of SHA256 hash function that applies to compressed public key. - * Populates the output parameter with 32 bytes. */ -SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256; - -/** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256). - * Populates the output parameter with 32 bytes. */ -SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default; - -/** Compute an EC Diffie-Hellman secret in constant time - * - * Returns: 1: exponentiation was successful - * 0: scalar was invalid (zero or overflow) or hashfp returned 0 - * Args: ctx: pointer to a context object. - * Out: output: pointer to an array to be filled by hashfp. - * In: pubkey: pointer to a secp256k1_pubkey containing an initialized public key. - * seckey: a 32-byte scalar with which to multiply the point. - * hashfp: pointer to a hash function. If NULL, - * secp256k1_ecdh_hash_function_sha256 is used - * (in which case, 32 bytes will be written to output). - * data: arbitrary data pointer that is passed through to hashfp - * (can be NULL for secp256k1_ecdh_hash_function_sha256). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( - const secp256k1_context *ctx, - unsigned char *output, - const secp256k1_pubkey *pubkey, - const unsigned char *seckey, - secp256k1_ecdh_hash_function hashfp, - void *data -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_ECDH_H */ diff --git a/external/secp256k1/include/secp256k1_ellswift.h b/external/secp256k1/include/secp256k1_ellswift.h deleted file mode 100644 index 0d1293e94f..0000000000 --- a/external/secp256k1/include/secp256k1_ellswift.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef SECP256K1_ELLSWIFT_H -#define SECP256K1_ELLSWIFT_H - -#include "secp256k1.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* This module provides an implementation of ElligatorSwift as well as a - * version of x-only ECDH using it (including compatibility with BIP324). - * - * ElligatorSwift is described in https://eprint.iacr.org/2022/759 by - * Chavez-Saab, Rodriguez-Henriquez, and Tibouchi. It permits encoding - * uniformly chosen public keys as 64-byte arrays which are indistinguishable - * from uniformly random arrays. - * - * Let f be the function from pairs of field elements to point X coordinates, - * defined as follows (all operations modulo p = 2^256 - 2^32 - 977) - * f(u,t): - * - Let C = 0xa2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f852, - * a square root of -3. - * - If u=0, set u=1 instead. - * - If t=0, set t=1 instead. - * - If u^3 + t^2 + 7 = 0, multiply t by 2. - * - Let X = (u^3 + 7 - t^2) / (2 * t) - * - Let Y = (X + t) / (C * u) - * - Return the first in [u + 4 * Y^2, (-X/Y - u) / 2, (X/Y - u) / 2] that is an - * X coordinate on the curve (at least one of them is, for any u and t). - * - * Then an ElligatorSwift encoding of x consists of the 32-byte big-endian - * encodings of field elements u and t concatenated, where f(u,t) = x. - * The encoding algorithm is described in the paper, and effectively picks a - * uniformly random pair (u,t) among those which encode x. - * - * If the Y coordinate is relevant, it is given the same parity as t. - * - * Changes w.r.t. the paper: - * - The u=0, t=0, and u^3+t^2+7=0 conditions result in decoding to the point - * at infinity in the paper. Here they are remapped to finite points. - * - The paper uses an additional encoding bit for the parity of y. Here the - * parity of t is used (negating t does not affect the decoded x coordinate, - * so this is possible). - * - * For mathematical background about the scheme, see the doc/ellswift.md file. - */ - -/** A pointer to a function used by secp256k1_ellswift_xdh to hash the shared X - * coordinate along with the encoded public keys to a uniform shared secret. - * - * Returns: 1 if a shared secret was successfully computed. - * 0 will cause secp256k1_ellswift_xdh to fail and return 0. - * Other return values are not allowed, and the behaviour of - * secp256k1_ellswift_xdh is undefined for other return values. - * Out: output: pointer to an array to be filled by the function - * In: x32: pointer to the 32-byte serialized X coordinate - * of the resulting shared point (will not be NULL) - * ell_a64: pointer to the 64-byte encoded public key of party A - * (will not be NULL) - * ell_b64: pointer to the 64-byte encoded public key of party B - * (will not be NULL) - * data: arbitrary data pointer that is passed through - */ -typedef int (*secp256k1_ellswift_xdh_hash_function)( - unsigned char *output, - const unsigned char *x32, - const unsigned char *ell_a64, - const unsigned char *ell_b64, - void *data -); - -/** An implementation of an secp256k1_ellswift_xdh_hash_function which uses - * SHA256(prefix64 || ell_a64 || ell_b64 || x32), where prefix64 is the 64-byte - * array pointed to by data. */ -SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix; - -/** An implementation of an secp256k1_ellswift_xdh_hash_function compatible with - * BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the - * BIP340 tagged hash function with tag "bip324_ellswift_xonly_ecdh". Equivalent - * to secp256k1_ellswift_xdh_hash_function_prefix with prefix64 set to - * SHA256("bip324_ellswift_xonly_ecdh")||SHA256("bip324_ellswift_xonly_ecdh"). - * The data argument is ignored. */ -SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324; - -/** Construct a 64-byte ElligatorSwift encoding of a given pubkey. - * - * Returns: 1 always. - * Args: ctx: pointer to a context object - * Out: ell64: pointer to a 64-byte array to be filled - * In: pubkey: pointer to a secp256k1_pubkey containing an - * initialized public key - * rnd32: pointer to 32 bytes of randomness - * - * It is recommended that rnd32 consists of 32 uniformly random bytes, not - * known to any adversary trying to detect whether public keys are being - * encoded, though 16 bytes of randomness (padded to an array of 32 bytes, - * e.g., with zeros) suffice to make the result indistinguishable from - * uniform. The randomness in rnd32 must not be a deterministic function of - * the pubkey (it can be derived from the private key, though). - * - * It is not guaranteed that the computed encoding is stable across versions - * of the library, even if all arguments to this function (including rnd32) - * are the same. - * - * This function runs in variable time. - */ -SECP256K1_API int secp256k1_ellswift_encode( - const secp256k1_context *ctx, - unsigned char *ell64, - const secp256k1_pubkey *pubkey, - const unsigned char *rnd32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Decode a 64-bytes ElligatorSwift encoded public key. - * - * Returns: always 1 - * Args: ctx: pointer to a context object - * Out: pubkey: pointer to a secp256k1_pubkey that will be filled - * In: ell64: pointer to a 64-byte array to decode - * - * This function runs in variable time. - */ -SECP256K1_API int secp256k1_ellswift_decode( - const secp256k1_context *ctx, - secp256k1_pubkey *pubkey, - const unsigned char *ell64 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Compute an ElligatorSwift public key for a secret key. - * - * Returns: 1: secret was valid, public key was stored. - * 0: secret was invalid, try again. - * Args: ctx: pointer to a context object - * Out: ell64: pointer to a 64-byte array to receive the ElligatorSwift - * public key - * In: seckey32: pointer to a 32-byte secret key - * auxrnd32: (optional) pointer to 32 bytes of randomness - * - * Constant time in seckey and auxrnd32, but not in the resulting public key. - * - * It is recommended that auxrnd32 contains 32 uniformly random bytes, though - * it is optional (and does result in encodings that are indistinguishable from - * uniform even without any auxrnd32). It differs from the (mandatory) rnd32 - * argument to secp256k1_ellswift_encode in this regard. - * - * This function can be used instead of calling secp256k1_ec_pubkey_create - * followed by secp256k1_ellswift_encode. It is safer, as it uses the secret - * key as entropy for the encoding (supplemented with auxrnd32, if provided). - * - * Like secp256k1_ellswift_encode, this function does not guarantee that the - * computed encoding is stable across versions of the library, even if all - * arguments (including auxrnd32) are the same. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_create( - const secp256k1_context *ctx, - unsigned char *ell64, - const unsigned char *seckey32, - const unsigned char *auxrnd32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Given a private key, and ElligatorSwift public keys sent in both directions, - * compute a shared secret using x-only Elliptic Curve Diffie-Hellman (ECDH). - * - * Returns: 1: shared secret was successfully computed - * 0: secret was invalid or hashfp returned 0 - * Args: ctx: pointer to a context object. - * Out: output: pointer to an array to be filled by hashfp. - * In: ell_a64: pointer to the 64-byte encoded public key of party A - * (will not be NULL) - * ell_b64: pointer to the 64-byte encoded public key of party B - * (will not be NULL) - * seckey32: pointer to our 32-byte secret key - * party: boolean indicating which party we are: zero if we are - * party A, non-zero if we are party B. seckey32 must be - * the private key corresponding to that party's ell_?64. - * This correspondence is not checked. - * hashfp: pointer to a hash function. - * data: arbitrary data pointer passed through to hashfp. - * - * Constant time in seckey32. - * - * This function is more efficient than decoding the public keys, and performing - * ECDH on them. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_xdh( - const secp256k1_context *ctx, - unsigned char *output, - const unsigned char *ell_a64, - const unsigned char *ell_b64, - const unsigned char *seckey32, - int party, - secp256k1_ellswift_xdh_hash_function hashfp, - void *data -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(7); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_ELLSWIFT_H */ diff --git a/external/secp256k1/include/secp256k1_extrakeys.h b/external/secp256k1/include/secp256k1_extrakeys.h deleted file mode 100644 index 48c98693cf..0000000000 --- a/external/secp256k1/include/secp256k1_extrakeys.h +++ /dev/null @@ -1,250 +0,0 @@ -#ifndef SECP256K1_EXTRAKEYS_H -#define SECP256K1_EXTRAKEYS_H - -#include "secp256k1.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Opaque data structure that holds a parsed and valid "x-only" public key. - * An x-only pubkey encodes a point whose Y coordinate is even. It is - * serialized using only its X coordinate (32 bytes). See BIP-340 for more - * information about x-only pubkeys. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage, transmission, use - * use secp256k1_xonly_pubkey_serialize and secp256k1_xonly_pubkey_parse. To - * compare keys, use secp256k1_xonly_pubkey_cmp. - */ -typedef struct secp256k1_xonly_pubkey { - unsigned char data[64]; -} secp256k1_xonly_pubkey; - -/** Opaque data structure that holds a keypair consisting of a secret and a - * public key. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 96 bytes in size, and can be safely copied/moved. - */ -typedef struct secp256k1_keypair { - unsigned char data[96]; -} secp256k1_keypair; - -/** Parse a 32-byte sequence into a xonly_pubkey object. - * - * Returns: 1 if the public key was fully valid. - * 0 if the public key could not be parsed or is invalid. - * - * Args: ctx: pointer to a context object. - * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a - * parsed version of input. If not, it's set to an invalid value. - * In: input32: pointer to a serialized xonly_pubkey. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse( - const secp256k1_context *ctx, - secp256k1_xonly_pubkey *pubkey, - const unsigned char *input32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an xonly_pubkey object into a 32-byte sequence. - * - * Returns: 1 always. - * - * Args: ctx: pointer to a context object. - * Out: output32: pointer to a 32-byte array to place the serialized key in. - * In: pubkey: pointer to a secp256k1_xonly_pubkey containing an initialized public key. - */ -SECP256K1_API int secp256k1_xonly_pubkey_serialize( - const secp256k1_context *ctx, - unsigned char *output32, - const secp256k1_xonly_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Compare two x-only public keys using lexicographic order - * - * Returns: <0 if the first public key is less than the second - * >0 if the first public key is greater than the second - * 0 if the two public keys are equal - * Args: ctx: pointer to a context object. - * In: pubkey1: first public key to compare - * pubkey2: second public key to compare - */ -SECP256K1_API int secp256k1_xonly_pubkey_cmp( - const secp256k1_context *ctx, - const secp256k1_xonly_pubkey *pk1, - const secp256k1_xonly_pubkey *pk2 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Converts a secp256k1_pubkey into a secp256k1_xonly_pubkey. - * - * Returns: 1 always. - * - * Args: ctx: pointer to a context object. - * Out: xonly_pubkey: pointer to an x-only public key object for placing the converted public key. - * pk_parity: Ignored if NULL. Otherwise, pointer to an integer that - * will be set to 1 if the point encoded by xonly_pubkey is - * the negation of the pubkey and set to 0 otherwise. - * In: pubkey: pointer to a public key that is converted. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey( - const secp256k1_context *ctx, - secp256k1_xonly_pubkey *xonly_pubkey, - int *pk_parity, - const secp256k1_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); - -/** Tweak an x-only public key by adding the generator multiplied with tweak32 - * to it. - * - * Note that the resulting point can not in general be represented by an x-only - * pubkey because it may have an odd Y coordinate. Instead, the output_pubkey - * is a normal secp256k1_pubkey. - * - * Returns: 0 if the arguments are invalid or the resulting public key would be - * invalid (only when the tweak is the negation of the corresponding - * secret key). 1 otherwise. - * - * Args: ctx: pointer to a context object. - * Out: output_pubkey: pointer to a public key to store the result. Will be set - * to an invalid value if this function returns 0. - * In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to. - * tweak32: pointer to a 32-byte tweak, which must be valid - * according to secp256k1_ec_seckey_verify or 32 zero - * bytes. For uniformly random 32-byte tweaks, the chance of - * being invalid is negligible (around 1 in 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add( - const secp256k1_context *ctx, - secp256k1_pubkey *output_pubkey, - const secp256k1_xonly_pubkey *internal_pubkey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Checks that a tweaked pubkey is the result of calling - * secp256k1_xonly_pubkey_tweak_add with internal_pubkey and tweak32. - * - * The tweaked pubkey is represented by its 32-byte x-only serialization and - * its pk_parity, which can both be obtained by converting the result of - * tweak_add to a secp256k1_xonly_pubkey. - * - * Note that this alone does _not_ verify that the tweaked pubkey is a - * commitment. If the tweak is not chosen in a specific way, the tweaked pubkey - * can easily be the result of a different internal_pubkey and tweak. - * - * Returns: 0 if the arguments are invalid or the tweaked pubkey is not the - * result of tweaking the internal_pubkey with tweak32. 1 otherwise. - * Args: ctx: pointer to a context object. - * In: tweaked_pubkey32: pointer to a serialized xonly_pubkey. - * tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization - * is passed in as tweaked_pubkey32). This must match the - * pk_parity value that is returned when calling - * secp256k1_xonly_pubkey with the tweaked pubkey, or - * this function will fail. - * internal_pubkey: pointer to an x-only public key object to apply the tweak to. - * tweak32: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_check( - const secp256k1_context *ctx, - const unsigned char *tweaked_pubkey32, - int tweaked_pk_parity, - const secp256k1_xonly_pubkey *internal_pubkey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); - -/** Compute the keypair for a valid secret key. - * - * See the documentation of `secp256k1_ec_seckey_verify` for more information - * about the validity of secret keys. - * - * Returns: 1: secret key is valid - * 0: secret key is invalid - * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: keypair: pointer to the created keypair. - * In: seckey: pointer to a 32-byte secret key. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create( - const secp256k1_context *ctx, - secp256k1_keypair *keypair, - const unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Get the secret key from a keypair. - * - * Returns: 1 always. - * Args: ctx: pointer to a context object. - * Out: seckey: pointer to a 32-byte buffer for the secret key. - * In: keypair: pointer to a keypair. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec( - const secp256k1_context *ctx, - unsigned char *seckey, - const secp256k1_keypair *keypair -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Get the public key from a keypair. - * - * Returns: 1 always. - * Args: ctx: pointer to a context object. - * Out: pubkey: pointer to a pubkey object, set to the keypair public key. - * In: keypair: pointer to a keypair. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub( - const secp256k1_context *ctx, - secp256k1_pubkey *pubkey, - const secp256k1_keypair *keypair -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Get the x-only public key from a keypair. - * - * This is the same as calling secp256k1_keypair_pub and then - * secp256k1_xonly_pubkey_from_pubkey. - * - * Returns: 1 always. - * Args: ctx: pointer to a context object. - * Out: pubkey: pointer to an xonly_pubkey object, set to the keypair - * public key after converting it to an xonly_pubkey. - * pk_parity: Ignored if NULL. Otherwise, pointer to an integer that will be set to the - * pk_parity argument of secp256k1_xonly_pubkey_from_pubkey. - * In: keypair: pointer to a keypair. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub( - const secp256k1_context *ctx, - secp256k1_xonly_pubkey *pubkey, - int *pk_parity, - const secp256k1_keypair *keypair -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); - -/** Tweak a keypair by adding tweak32 to the secret key and updating the public - * key accordingly. - * - * Calling this function and then secp256k1_keypair_pub results in the same - * public key as calling secp256k1_keypair_xonly_pub and then - * secp256k1_xonly_pubkey_tweak_add. - * - * Returns: 0 if the arguments are invalid or the resulting keypair would be - * invalid (only when the tweak is the negation of the keypair's - * secret key). 1 otherwise. - * - * Args: ctx: pointer to a context object. - * In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to - * an invalid value if this function returns 0. - * In: tweak32: pointer to a 32-byte tweak, which must be valid according to - * secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly - * random 32-byte tweaks, the chance of being invalid is - * negligible (around 1 in 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add( - const secp256k1_context *ctx, - secp256k1_keypair *keypair, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_EXTRAKEYS_H */ diff --git a/external/secp256k1/include/secp256k1_musig.h b/external/secp256k1/include/secp256k1_musig.h deleted file mode 100644 index 11b8f08c88..0000000000 --- a/external/secp256k1/include/secp256k1_musig.h +++ /dev/null @@ -1,588 +0,0 @@ -#ifndef SECP256K1_MUSIG_H -#define SECP256K1_MUSIG_H - -#include "secp256k1_extrakeys.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** This module implements BIP 327 "MuSig2 for BIP340-compatible - * Multi-Signatures" - * (https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki) - * v1.0.0. You can find an example demonstrating the musig module in - * examples/musig.c. - * - * The module also supports BIP 341 ("Taproot") public key tweaking. - * - * It is recommended to read the documentation in this include file carefully. - * Further notes on API usage can be found in doc/musig.md - * - * Since the first version of MuSig is essentially replaced by MuSig2, we use - * MuSig, musig and MuSig2 synonymously unless noted otherwise. - */ - -/** Opaque data structures - * - * The exact representation of data inside the opaque data structures is - * implementation defined and not guaranteed to be portable between different - * platforms or versions. With the exception of `secp256k1_musig_secnonce`, the - * data structures can be safely copied/moved. If you need to convert to a - * format suitable for storage, transmission, or comparison, use the - * corresponding serialization and parsing functions. - */ - -/** Opaque data structure that caches information about public key aggregation. - * - * Guaranteed to be 197 bytes in size. No serialization and parsing functions - * (yet). - */ -typedef struct secp256k1_musig_keyagg_cache { - unsigned char data[197]; -} secp256k1_musig_keyagg_cache; - -/** Opaque data structure that holds a signer's _secret_ nonce. - * - * Guaranteed to be 132 bytes in size. - * - * WARNING: This structure MUST NOT be copied or read or written to directly. A - * signer who is online throughout the whole process and can keep this - * structure in memory can use the provided API functions for a safe standard - * workflow. - * - * Copying this data structure can result in nonce reuse which will leak the - * secret signing key. - */ -typedef struct secp256k1_musig_secnonce { - unsigned char data[132]; -} secp256k1_musig_secnonce; - -/** Opaque data structure that holds a signer's public nonce. - * - * Guaranteed to be 132 bytes in size. Serialized and parsed with - * `musig_pubnonce_serialize` and `musig_pubnonce_parse`. - */ -typedef struct secp256k1_musig_pubnonce { - unsigned char data[132]; -} secp256k1_musig_pubnonce; - -/** Opaque data structure that holds an aggregate public nonce. - * - * Guaranteed to be 132 bytes in size. Serialized and parsed with - * `musig_aggnonce_serialize` and `musig_aggnonce_parse`. - */ -typedef struct secp256k1_musig_aggnonce { - unsigned char data[132]; -} secp256k1_musig_aggnonce; - -/** Opaque data structure that holds a MuSig session. - * - * This structure is not required to be kept secret for the signing protocol to - * be secure. Guaranteed to be 133 bytes in size. No serialization and parsing - * functions (yet). - */ -typedef struct secp256k1_musig_session { - unsigned char data[133]; -} secp256k1_musig_session; - -/** Opaque data structure that holds a partial MuSig signature. - * - * Guaranteed to be 36 bytes in size. Serialized and parsed with - * `musig_partial_sig_serialize` and `musig_partial_sig_parse`. - */ -typedef struct secp256k1_musig_partial_sig { - unsigned char data[36]; -} secp256k1_musig_partial_sig; - -/** Parse a signer's public nonce. - * - * Returns: 1 when the nonce could be parsed, 0 otherwise. - * Args: ctx: pointer to a context object - * Out: nonce: pointer to a nonce object - * In: in66: pointer to the 66-byte nonce to be parsed - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubnonce_parse( - const secp256k1_context *ctx, - secp256k1_musig_pubnonce *nonce, - const unsigned char *in66 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize a signer's public nonce - * - * Returns: 1 always - * Args: ctx: pointer to a context object - * Out: out66: pointer to a 66-byte array to store the serialized nonce - * In: nonce: pointer to the nonce - */ -SECP256K1_API int secp256k1_musig_pubnonce_serialize( - const secp256k1_context *ctx, - unsigned char *out66, - const secp256k1_musig_pubnonce *nonce -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Parse an aggregate public nonce. - * - * Returns: 1 when the nonce could be parsed, 0 otherwise. - * Args: ctx: pointer to a context object - * Out: nonce: pointer to a nonce object - * In: in66: pointer to the 66-byte nonce to be parsed - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_aggnonce_parse( - const secp256k1_context *ctx, - secp256k1_musig_aggnonce *nonce, - const unsigned char *in66 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an aggregate public nonce - * - * Returns: 1 always - * Args: ctx: pointer to a context object - * Out: out66: pointer to a 66-byte array to store the serialized nonce - * In: nonce: pointer to the nonce - */ -SECP256K1_API int secp256k1_musig_aggnonce_serialize( - const secp256k1_context *ctx, - unsigned char *out66, - const secp256k1_musig_aggnonce *nonce -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Parse a MuSig partial signature. - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: pointer to a context object - * Out: sig: pointer to a signature object - * In: in32: pointer to the 32-byte signature to be parsed - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_parse( - const secp256k1_context *ctx, - secp256k1_musig_partial_sig *sig, - const unsigned char *in32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize a MuSig partial signature - * - * Returns: 1 always - * Args: ctx: pointer to a context object - * Out: out32: pointer to a 32-byte array to store the serialized signature - * In: sig: pointer to the signature - */ -SECP256K1_API int secp256k1_musig_partial_sig_serialize( - const secp256k1_context *ctx, - unsigned char *out32, - const secp256k1_musig_partial_sig *sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Computes an aggregate public key and uses it to initialize a keyagg_cache - * - * Different orders of `pubkeys` result in different `agg_pk`s. - * - * Before aggregating, the pubkeys can be sorted with `secp256k1_ec_pubkey_sort` - * which ensures the same `agg_pk` result for the same multiset of pubkeys. - * This is useful to do before `pubkey_agg`, such that the order of pubkeys - * does not affect the aggregate public key. - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: agg_pk: the MuSig-aggregated x-only public key. If you do not need it, - * this arg can be NULL. - * keyagg_cache: if non-NULL, pointer to a musig_keyagg_cache struct that - * is required for signing (or observing the signing session - * and verifying partial signatures). - * In: pubkeys: input array of pointers to public keys to aggregate. The order - * is important; a different order will result in a different - * aggregate public key. - * n_pubkeys: length of pubkeys array. Must be greater than 0. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_agg( - const secp256k1_context *ctx, - secp256k1_xonly_pubkey *agg_pk, - secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_pubkey * const *pubkeys, - size_t n_pubkeys -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(4); - -/** Obtain the aggregate public key from a keyagg_cache. - * - * This is only useful if you need the non-xonly public key, in particular for - * plain (non-xonly) tweaking or batch-verifying multiple key aggregations - * (not implemented). - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: agg_pk: the MuSig-aggregated public key. - * In: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by - * `musig_pubkey_agg` - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_get( - const secp256k1_context *ctx, - secp256k1_pubkey *agg_pk, - const secp256k1_musig_keyagg_cache *keyagg_cache -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Apply plain "EC" tweaking to a public key in a given keyagg_cache by adding - * the generator multiplied with `tweak32` to it. This is useful for deriving - * child keys from an aggregate public key via BIP 32 where `tweak32` is set to - * a hash as defined in BIP 32. - * - * Callers are responsible for deriving `tweak32` in a way that does not reduce - * the security of MuSig (for example, by following BIP 32). - * - * The tweaking method is the same as `secp256k1_ec_pubkey_tweak_add`. So after - * the following pseudocode buf and buf2 have identical contents (absent - * earlier failures). - * - * secp256k1_musig_pubkey_agg(..., keyagg_cache, pubkeys, ...) - * secp256k1_musig_pubkey_get(..., agg_pk, keyagg_cache) - * secp256k1_musig_pubkey_ec_tweak_add(..., output_pk, tweak32, keyagg_cache) - * secp256k1_ec_pubkey_serialize(..., buf, ..., output_pk, ...) - * secp256k1_ec_pubkey_tweak_add(..., agg_pk, tweak32) - * secp256k1_ec_pubkey_serialize(..., buf2, ..., agg_pk, ...) - * - * This function is required if you want to _sign_ for a tweaked aggregate key. - * If you are only computing a public key but not intending to create a - * signature for it, use `secp256k1_ec_pubkey_tweak_add` instead. - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: output_pubkey: pointer to a public key to store the result. Will be set - * to an invalid value if this function returns 0. If you - * do not need it, this arg can be NULL. - * In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by - * `musig_pubkey_agg` - * In: tweak32: pointer to a 32-byte tweak. The tweak is valid if it passes - * `secp256k1_ec_seckey_verify` and is not equal to the - * secret key corresponding to the public key represented - * by keyagg_cache or its negation. For uniformly random - * 32-byte arrays the chance of being invalid is - * negligible (around 1 in 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_ec_tweak_add( - const secp256k1_context *ctx, - secp256k1_pubkey *output_pubkey, - secp256k1_musig_keyagg_cache *keyagg_cache, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Apply x-only tweaking to a public key in a given keyagg_cache by adding the - * generator multiplied with `tweak32` to it. This is useful for creating - * Taproot outputs where `tweak32` is set to a TapTweak hash as defined in BIP - * 341. - * - * Callers are responsible for deriving `tweak32` in a way that does not reduce - * the security of MuSig (for example, by following Taproot BIP 341). - * - * The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in - * the following pseudocode xonly_pubkey_tweak_add_check (absent earlier - * failures) returns 1. - * - * secp256k1_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...) - * secp256k1_musig_pubkey_xonly_tweak_add(..., output_pk, keyagg_cache, tweak32) - * secp256k1_xonly_pubkey_serialize(..., buf, output_pk) - * secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32) - * - * This function is required if you want to _sign_ for a tweaked aggregate key. - * If you are only computing a public key but not intending to create a - * signature for it, use `secp256k1_xonly_pubkey_tweak_add` instead. - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: output_pubkey: pointer to a public key to store the result. Will be set - * to an invalid value if this function returns 0. If you - * do not need it, this arg can be NULL. - * In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by - * `musig_pubkey_agg` - * In: tweak32: pointer to a 32-byte tweak. The tweak is valid if it passes - * `secp256k1_ec_seckey_verify` and is not equal to the - * secret key corresponding to the public key represented - * by keyagg_cache or its negation. For uniformly random - * 32-byte arrays the chance of being invalid is - * negligible (around 1 in 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_tweak_add( - const secp256k1_context *ctx, - secp256k1_pubkey *output_pubkey, - secp256k1_musig_keyagg_cache *keyagg_cache, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Starts a signing session by generating a nonce - * - * This function outputs a secret nonce that will be required for signing and a - * corresponding public nonce that is intended to be sent to other signers. - * - * MuSig differs from regular Schnorr signing in that implementers _must_ take - * special care to not reuse a nonce. This can be ensured by following these rules: - * - * 1. Each call to this function must have a UNIQUE session_secrand32 that must - * NOT BE REUSED in subsequent calls to this function and must be KEPT - * SECRET (even from other signers). - * 2. If you already know the seckey, message or aggregate public key - * cache, they can be optionally provided to derive the nonce and increase - * misuse-resistance. The extra_input32 argument can be used to provide - * additional data that does not repeat in normal scenarios, such as the - * current time. - * 3. Avoid copying (or serializing) the secnonce. This reduces the possibility - * that it is used more than once for signing. - * - * If you don't have access to good randomness for session_secrand32, but you - * have access to a non-repeating counter, then see - * secp256k1_musig_nonce_gen_counter. - * - * Remember that nonce reuse will leak the secret key! - * Note that using the same seckey for multiple MuSig sessions is fine. - * - * Returns: 0 if the arguments are invalid and 1 otherwise - * Args: ctx: pointer to a context object (not secp256k1_context_static) - * Out: secnonce: pointer to a structure to store the secret nonce - * pubnonce: pointer to a structure to store the public nonce - * In/Out: - * session_secrand32: a 32-byte session_secrand32 as explained above. Must be unique to this - * call to secp256k1_musig_nonce_gen and must be uniformly - * random. If the function call is successful, the - * session_secrand32 buffer is invalidated to prevent reuse. - * In: - * seckey: the 32-byte secret key that will later be used for signing, if - * already known (can be NULL) - * pubkey: public key of the signer creating the nonce. The secnonce - * output of this function cannot be used to sign for any - * other public key. While the public key should correspond - * to the provided seckey, a mismatch will not cause the - * function to return 0. - * msg32: the 32-byte message that will later be signed, if already known - * (can be NULL) - * keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate - * (and potentially tweaked) public key if already known - * (can be NULL) - * extra_input32: an optional 32-byte array that is input to the nonce - * derivation function (can be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_gen( - const secp256k1_context *ctx, - secp256k1_musig_secnonce *secnonce, - secp256k1_musig_pubnonce *pubnonce, - unsigned char *session_secrand32, - const unsigned char *seckey, - const secp256k1_pubkey *pubkey, - const unsigned char *msg32, - const secp256k1_musig_keyagg_cache *keyagg_cache, - const unsigned char *extra_input32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6); - - -/** Alternative way to generate a nonce and start a signing session - * - * This function outputs a secret nonce that will be required for signing and a - * corresponding public nonce that is intended to be sent to other signers. - * - * This function differs from `secp256k1_musig_nonce_gen` by accepting a - * non-repeating counter value instead of a secret random value. This requires - * that a secret key is provided to `secp256k1_musig_nonce_gen_counter` - * (through the keypair argument), as opposed to `secp256k1_musig_nonce_gen` - * where the seckey argument is optional. - * - * MuSig differs from regular Schnorr signing in that implementers _must_ take - * special care to not reuse a nonce. This can be ensured by following these rules: - * - * 1. The nonrepeating_cnt argument must be a counter value that never repeats, - * i.e., you must never call `secp256k1_musig_nonce_gen_counter` twice with - * the same keypair and nonrepeating_cnt value. For example, this implies - * that if the same keypair is used with `secp256k1_musig_nonce_gen_counter` - * on multiple devices, none of the devices should have the same counter - * value as any other device. - * 2. If the seckey, message or aggregate public key cache is already available - * at this stage, any of these can be optionally provided, in which case - * they will be used in the derivation of the nonce and increase - * misuse-resistance. The extra_input32 argument can be used to provide - * additional data that does not repeat in normal scenarios, such as the - * current time. - * 3. Avoid copying (or serializing) the secnonce. This reduces the possibility - * that it is used more than once for signing. - * - * Remember that nonce reuse will leak the secret key! - * Note that using the same keypair for multiple MuSig sessions is fine. - * - * Returns: 0 if the arguments are invalid and 1 otherwise - * Args: ctx: pointer to a context object (not secp256k1_context_static) - * Out: secnonce: pointer to a structure to store the secret nonce - * pubnonce: pointer to a structure to store the public nonce - * In: - * nonrepeating_cnt: the value of a counter as explained above. Must be - * unique to this call to secp256k1_musig_nonce_gen. - * keypair: keypair of the signer creating the nonce. The secnonce - * output of this function cannot be used to sign for any - * other keypair. - * msg32: the 32-byte message that will later be signed, if already known - * (can be NULL) - * keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate - * (and potentially tweaked) public key if already known - * (can be NULL) - * extra_input32: an optional 32-byte array that is input to the nonce - * derivation function (can be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_gen_counter( - const secp256k1_context *ctx, - secp256k1_musig_secnonce *secnonce, - secp256k1_musig_pubnonce *pubnonce, - uint64_t nonrepeating_cnt, - const secp256k1_keypair *keypair, - const unsigned char *msg32, - const secp256k1_musig_keyagg_cache *keyagg_cache, - const unsigned char *extra_input32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); - -/** Aggregates the nonces of all signers into a single nonce - * - * This can be done by an untrusted party to reduce the communication - * between signers. Instead of everyone sending nonces to everyone else, there - * can be one party receiving all nonces, aggregating the nonces with this - * function and then sending only the aggregate nonce back to the signers. - * - * If the aggregator does not compute the aggregate nonce correctly, the final - * signature will be invalid. - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: aggnonce: pointer to an aggregate public nonce object for - * musig_nonce_process - * In: pubnonces: array of pointers to public nonces sent by the - * signers - * n_pubnonces: number of elements in the pubnonces array. Must be - * greater than 0. - */ -SECP256K1_API int secp256k1_musig_nonce_agg( - const secp256k1_context *ctx, - secp256k1_musig_aggnonce *aggnonce, - const secp256k1_musig_pubnonce * const *pubnonces, - size_t n_pubnonces -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Takes the aggregate nonce and creates a session that is required for signing - * and verification of partial signatures. - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: session: pointer to a struct to store the session - * In: aggnonce: pointer to an aggregate public nonce object that is the - * output of musig_nonce_agg - * msg32: the 32-byte message to sign - * keyagg_cache: pointer to the keyagg_cache that was used to create the - * aggregate (and potentially tweaked) pubkey - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process( - const secp256k1_context *ctx, - secp256k1_musig_session *session, - const secp256k1_musig_aggnonce *aggnonce, - const unsigned char *msg32, - const secp256k1_musig_keyagg_cache *keyagg_cache -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); - -/** Produces a partial signature - * - * This function overwrites the given secnonce with zeros and will abort if given a - * secnonce that is all zeros. This is a best effort attempt to protect against nonce - * reuse. However, this is of course easily defeated if the secnonce has been - * copied (or serialized). Remember that nonce reuse will leak the secret key! - * - * For signing to succeed, the secnonce provided to this function must have - * been generated for the provided keypair. This means that when signing for a - * keypair consisting of a seckey and pubkey, the secnonce must have been - * created by calling musig_nonce_gen with that pubkey. Otherwise, the - * illegal_callback is called. - * - * This function does not verify the output partial signature, deviating from - * the BIP 327 specification. It is recommended to verify the output partial - * signature with `secp256k1_musig_partial_sig_verify` to prevent random or - * adversarially provoked computation errors. - * - * Returns: 0 if the arguments are invalid or the provided secnonce has already - * been used for signing, 1 otherwise - * Args: ctx: pointer to a context object - * Out: partial_sig: pointer to struct to store the partial signature - * In/Out: secnonce: pointer to the secnonce struct created in - * musig_nonce_gen that has been never used in a - * partial_sign call before and has been created for the - * keypair - * In: keypair: pointer to keypair to sign the message with - * keyagg_cache: pointer to the keyagg_cache that was output when the - * aggregate public key for this session - * session: pointer to the session that was created with - * musig_nonce_process - */ -SECP256K1_API int secp256k1_musig_partial_sign( - const secp256k1_context *ctx, - secp256k1_musig_partial_sig *partial_sig, - secp256k1_musig_secnonce *secnonce, - const secp256k1_keypair *keypair, - const secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_musig_session *session -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); - -/** Verifies an individual signer's partial signature - * - * The signature is verified for a specific signing session. In order to avoid - * accidentally verifying a signature from a different or non-existing signing - * session, you must ensure the following: - * 1. The `keyagg_cache` argument is identical to the one used to create the - * `session` with `musig_nonce_process`. - * 2. The `pubkey` argument must be identical to the one sent by the signer - * before aggregating it with `musig_pubkey_agg` to create the - * `keyagg_cache`. - * 3. The `pubnonce` argument must be identical to the one sent by the signer - * before aggregating it with `musig_nonce_agg` and using the result to - * create the `session` with `musig_nonce_process`. - * - * It is not required to call this function in regular MuSig sessions, because - * if any partial signature does not verify, the final signature will not - * verify either, so the problem will be caught. However, this function - * provides the ability to identify which specific partial signature fails - * verification. - * - * Returns: 0 if the arguments are invalid or the partial signature does not - * verify, 1 otherwise - * Args ctx: pointer to a context object - * In: partial_sig: pointer to partial signature to verify, sent by - * the signer associated with `pubnonce` and `pubkey` - * pubnonce: public nonce of the signer in the signing session - * pubkey: public key of the signer in the signing session - * keyagg_cache: pointer to the keyagg_cache that was output when the - * aggregate public key for this signing session - * session: pointer to the session that was created with - * `musig_nonce_process` - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verify( - const secp256k1_context *ctx, - const secp256k1_musig_partial_sig *partial_sig, - const secp256k1_musig_pubnonce *pubnonce, - const secp256k1_pubkey *pubkey, - const secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_musig_session *session -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); - -/** Aggregates partial signatures - * - * Returns: 0 if the arguments are invalid, 1 otherwise (which does NOT mean - * the resulting signature verifies). - * Args: ctx: pointer to a context object - * Out: sig64: complete (but possibly invalid) Schnorr signature - * In: session: pointer to the session that was created with - * musig_nonce_process - * partial_sigs: array of pointers to partial signatures to aggregate - * n_sigs: number of elements in the partial_sigs array. Must be - * greater than 0. - */ -SECP256K1_API int secp256k1_musig_partial_sig_agg( - const secp256k1_context *ctx, - unsigned char *sig64, - const secp256k1_musig_session *session, - const secp256k1_musig_partial_sig * const *partial_sigs, - size_t n_sigs -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/external/secp256k1/include/secp256k1_preallocated.h b/external/secp256k1/include/secp256k1_preallocated.h deleted file mode 100644 index f2d95c245e..0000000000 --- a/external/secp256k1/include/secp256k1_preallocated.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef SECP256K1_PREALLOCATED_H -#define SECP256K1_PREALLOCATED_H - -#include "secp256k1.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* The module provided by this header file is intended for settings in which it - * is not possible or desirable to rely on dynamic memory allocation. It provides - * functions for creating, cloning, and destroying secp256k1 context objects in a - * contiguous fixed-size block of memory provided by the caller. - * - * Context objects created by functions in this module can be used like contexts - * objects created by functions in secp256k1.h, i.e., they can be passed to any - * API function that expects a context object (see secp256k1.h for details). The - * only exception is that context objects created by functions in this module - * must be destroyed using secp256k1_context_preallocated_destroy (in this - * module) instead of secp256k1_context_destroy (in secp256k1.h). - * - * It is guaranteed that functions in this module will not call malloc or its - * friends realloc, calloc, and free. - */ - -/** Determine the memory size of a secp256k1 context object to be created in - * caller-provided memory. - * - * The purpose of this function is to determine how much memory must be provided - * to secp256k1_context_preallocated_create. - * - * Returns: the required size of the caller-provided memory block - * In: flags: which parts of the context to initialize. - */ -SECP256K1_API size_t secp256k1_context_preallocated_size( - unsigned int flags -) SECP256K1_WARN_UNUSED_RESULT; - -/** Create a secp256k1 context object in caller-provided memory. - * - * The caller must provide a pointer to a rewritable contiguous block of memory - * of size at least secp256k1_context_preallocated_size(flags) bytes, suitably - * aligned to hold an object of any type. - * - * The block of memory is exclusively owned by the created context object during - * the lifetime of this context object, which begins with the call to this - * function and ends when a call to secp256k1_context_preallocated_destroy - * (which destroys the context object again) returns. During the lifetime of the - * context object, the caller is obligated not to access this block of memory, - * i.e., the caller may not read or write the memory, e.g., by copying the memory - * contents to a different location or trying to create a second context object - * in the memory. In simpler words, the prealloc pointer (or any pointer derived - * from it) should not be used during the lifetime of the context object. - * - * Returns: pointer to newly created context object. - * In: prealloc: pointer to a rewritable contiguous block of memory of - * size at least secp256k1_context_preallocated_size(flags) - * bytes, as detailed above. - * flags: which parts of the context to initialize. - * - * See secp256k1_context_create (in secp256k1.h) for further details. - * - * See also secp256k1_context_randomize (in secp256k1.h) - * and secp256k1_context_preallocated_destroy. - */ -SECP256K1_API secp256k1_context *secp256k1_context_preallocated_create( - void *prealloc, - unsigned int flags -) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; - -/** Determine the memory size of a secp256k1 context object to be copied into - * caller-provided memory. - * - * Returns: the required size of the caller-provided memory block. - * In: ctx: pointer to a context to copy. - */ -SECP256K1_API size_t secp256k1_context_preallocated_clone_size( - const secp256k1_context *ctx -) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; - -/** Copy a secp256k1 context object into caller-provided memory. - * - * The caller must provide a pointer to a rewritable contiguous block of memory - * of size at least secp256k1_context_preallocated_size(flags) bytes, suitably - * aligned to hold an object of any type. - * - * The block of memory is exclusively owned by the created context object during - * the lifetime of this context object, see the description of - * secp256k1_context_preallocated_create for details. - * - * Cloning secp256k1_context_static is not possible, and should not be emulated by - * the caller (e.g., using memcpy). Create a new context instead. - * - * Returns: pointer to a newly created context object. - * Args: ctx: pointer to a context to copy (not secp256k1_context_static). - * In: prealloc: pointer to a rewritable contiguous block of memory of - * size at least secp256k1_context_preallocated_size(flags) - * bytes, as detailed above. - */ -SECP256K1_API secp256k1_context *secp256k1_context_preallocated_clone( - const secp256k1_context *ctx, - void *prealloc -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_WARN_UNUSED_RESULT; - -/** Destroy a secp256k1 context object that has been created in - * caller-provided memory. - * - * The context pointer may not be used afterwards. - * - * The context to destroy must have been created using - * secp256k1_context_preallocated_create or secp256k1_context_preallocated_clone. - * If the context has instead been created using secp256k1_context_create or - * secp256k1_context_clone, the behaviour is undefined. In that case, - * secp256k1_context_destroy must be used instead. - * - * If required, it is the responsibility of the caller to deallocate the block - * of memory properly after this function returns, e.g., by calling free on the - * preallocated pointer given to secp256k1_context_preallocated_create or - * secp256k1_context_preallocated_clone. - * - * Args: ctx: pointer to a context to destroy, constructed using - * secp256k1_context_preallocated_create or - * secp256k1_context_preallocated_clone - * (i.e., not secp256k1_context_static). - */ -SECP256K1_API void secp256k1_context_preallocated_destroy( - secp256k1_context *ctx -) SECP256K1_ARG_NONNULL(1); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_PREALLOCATED_H */ diff --git a/external/secp256k1/include/secp256k1_recovery.h b/external/secp256k1/include/secp256k1_recovery.h deleted file mode 100644 index 93a2e4ccbd..0000000000 --- a/external/secp256k1/include/secp256k1_recovery.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef SECP256K1_RECOVERY_H -#define SECP256K1_RECOVERY_H - -#include "secp256k1.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Opaque data structure that holds a parsed ECDSA signature, - * supporting pubkey recovery. - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. It is - * however guaranteed to be 65 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage or transmission, use - * the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_parse_* functions. - * - * Furthermore, it is guaranteed that identical signatures (including their - * recoverability) will have identical representation, so they can be - * memcmp'ed. - */ -typedef struct secp256k1_ecdsa_recoverable_signature { - unsigned char data[65]; -} secp256k1_ecdsa_recoverable_signature; - -/** Parse a compact ECDSA signature (64 bytes + recovery id). - * - * Returns: 1 when the signature could be parsed, 0 otherwise - * Args: ctx: pointer to a context object - * Out: sig: pointer to a signature object - * In: input64: pointer to a 64-byte compact signature - * recid: the recovery id (0, 1, 2 or 3) - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( - const secp256k1_context *ctx, - secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *input64, - int recid -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Convert a recoverable signature into a normal signature. - * - * Returns: 1 - * Args: ctx: pointer to a context object. - * Out: sig: pointer to a normal signature. - * In: sigin: pointer to a recoverable signature. - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( - const secp256k1_context *ctx, - secp256k1_ecdsa_signature *sig, - const secp256k1_ecdsa_recoverable_signature *sigin -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an ECDSA signature in compact format (64 bytes + recovery id). - * - * Returns: 1 - * Args: ctx: pointer to a context object. - * Out: output64: pointer to a 64-byte array of the compact signature. - * recid: pointer to an integer to hold the recovery id. - * In: sig: pointer to an initialized signature object. - */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( - const secp256k1_context *ctx, - unsigned char *output64, - int *recid, - const secp256k1_ecdsa_recoverable_signature *sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Create a recoverable ECDSA signature. - * - * Returns: 1: signature created - * 0: the nonce generation function failed, or the secret key was invalid. - * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: sig: pointer to an array where the signature will be placed. - * In: msghash32: the 32-byte message hash being signed. - * seckey: pointer to a 32-byte secret key. - * noncefp: pointer to a nonce generation function. If NULL, - * secp256k1_nonce_function_default is used. - * ndata: pointer to arbitrary data used by the nonce generation function - * (can be NULL for secp256k1_nonce_function_default). - */ -SECP256K1_API int secp256k1_ecdsa_sign_recoverable( - const secp256k1_context *ctx, - secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msghash32, - const unsigned char *seckey, - secp256k1_nonce_function noncefp, - const void *ndata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Recover an ECDSA public key from a signature. - * - * Returns: 1: public key successfully recovered (which guarantees a correct signature). - * 0: otherwise. - * Args: ctx: pointer to a context object. - * Out: pubkey: pointer to the recovered public key. - * In: sig: pointer to initialized signature that supports pubkey recovery. - * msghash32: the 32-byte message hash assumed to be signed. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( - const secp256k1_context *ctx, - secp256k1_pubkey *pubkey, - const secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msghash32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_RECOVERY_H */ diff --git a/external/secp256k1/include/secp256k1_schnorrsig.h b/external/secp256k1/include/secp256k1_schnorrsig.h deleted file mode 100644 index 013d4ee73d..0000000000 --- a/external/secp256k1/include/secp256k1_schnorrsig.h +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef SECP256K1_SCHNORRSIG_H -#define SECP256K1_SCHNORRSIG_H - -#include "secp256k1.h" -#include "secp256k1_extrakeys.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** This module implements a variant of Schnorr signatures compliant with - * Bitcoin Improvement Proposal 340 "Schnorr Signatures for secp256k1" - * (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). - */ - -/** A pointer to a function to deterministically generate a nonce. - * - * Same as secp256k1_nonce function with the exception of accepting an - * additional pubkey argument and not requiring an attempt argument. The pubkey - * argument can protect signature schemes with key-prefixed challenge hash - * inputs against reusing the nonce when signing with the wrong precomputed - * pubkey. - * - * Returns: 1 if a nonce was successfully generated. 0 will cause signing to - * return an error. - * Out: nonce32: pointer to a 32-byte array to be filled by the function - * In: msg: the message being verified. Is NULL if and only if msglen - * is 0. - * msglen: the length of the message - * key32: pointer to a 32-byte secret key (will not be NULL) - * xonly_pk32: the 32-byte serialized xonly pubkey corresponding to key32 - * (will not be NULL) - * algo: pointer to an array describing the signature - * algorithm (will not be NULL) - * algolen: the length of the algo array - * data: arbitrary data pointer that is passed through - * - * Except for test cases, this function should compute some cryptographic hash of - * the message, the key, the pubkey, the algorithm description, and data. - */ -typedef int (*secp256k1_nonce_function_hardened)( - unsigned char *nonce32, - const unsigned char *msg, - size_t msglen, - const unsigned char *key32, - const unsigned char *xonly_pk32, - const unsigned char *algo, - size_t algolen, - void *data -); - -/** An implementation of the nonce generation function as defined in Bitcoin - * Improvement Proposal 340 "Schnorr Signatures for secp256k1" - * (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). - * - * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of - * auxiliary random data as defined in BIP-340. If the data pointer is NULL, - * the nonce derivation procedure follows BIP-340 by setting the auxiliary - * random data to zero. The algo argument must be non-NULL, otherwise the - * function will fail and return 0. The hash will be tagged with algo. - * Therefore, to create BIP-340 compliant signatures, algo must be set to - * "BIP0340/nonce" and algolen to 13. - */ -SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340; - -/** Data structure that contains additional arguments for schnorrsig_sign_custom. - * - * A schnorrsig_extraparams structure object can be initialized correctly by - * setting it to SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT. - * - * Members: - * magic: set to SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC at initialization - * and has no other function than making sure the object is - * initialized. - * noncefp: pointer to a nonce generation function. If NULL, - * secp256k1_nonce_function_bip340 is used - * ndata: pointer to arbitrary data used by the nonce generation function - * (can be NULL). If it is non-NULL and - * secp256k1_nonce_function_bip340 is used, then ndata must be a - * pointer to 32-byte auxiliary randomness as per BIP-340. - */ -typedef struct secp256k1_schnorrsig_extraparams { - unsigned char magic[4]; - secp256k1_nonce_function_hardened noncefp; - void *ndata; -} secp256k1_schnorrsig_extraparams; - -#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC { 0xda, 0x6f, 0xb3, 0x8c } -#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT {\ - SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,\ - NULL,\ - NULL\ -} - -/** Create a Schnorr signature. - * - * Does _not_ strictly follow BIP-340 because it does not verify the resulting - * signature. Instead, you can manually use secp256k1_schnorrsig_verify and - * abort if it fails. - * - * This function only signs 32-byte messages. If you have messages of a - * different size (or the same size but without a context-specific tag - * prefix), it is recommended to create a 32-byte message hash with - * secp256k1_tagged_sha256 and then sign the hash. Tagged hashing allows - * providing an context-specific tag for domain separation. This prevents - * signatures from being valid in multiple contexts by accident. - * - * Returns 1 on success, 0 on failure. - * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: sig64: pointer to a 64-byte array to store the serialized signature. - * In: msg32: the 32-byte message being signed. - * keypair: pointer to an initialized keypair. - * aux_rand32: 32 bytes of fresh randomness. While recommended to provide - * this, it is only supplemental to security and can be NULL. A - * NULL argument is treated the same as an all-zero one. See - * BIP-340 "Default Signing" for a full explanation of this - * argument and for guidance if randomness is expensive. - */ -SECP256K1_API int secp256k1_schnorrsig_sign32( - const secp256k1_context *ctx, - unsigned char *sig64, - const unsigned char *msg32, - const secp256k1_keypair *keypair, - const unsigned char *aux_rand32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Same as secp256k1_schnorrsig_sign32, but DEPRECATED. Will be removed in - * future versions. */ -SECP256K1_API int secp256k1_schnorrsig_sign( - const secp256k1_context *ctx, - unsigned char *sig64, - const unsigned char *msg32, - const secp256k1_keypair *keypair, - const unsigned char *aux_rand32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) - SECP256K1_DEPRECATED("Use secp256k1_schnorrsig_sign32 instead"); - -/** Create a Schnorr signature with a more flexible API. - * - * Same arguments as secp256k1_schnorrsig_sign except that it allows signing - * variable length messages and accepts a pointer to an extraparams object that - * allows customizing signing by passing additional arguments. - * - * Equivalent to secp256k1_schnorrsig_sign32(..., aux_rand32) if msglen is 32 - * and extraparams is initialized as follows: - * ``` - * secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; - * extraparams.ndata = (unsigned char*)aux_rand32; - * ``` - * - * Returns 1 on success, 0 on failure. - * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: sig64: pointer to a 64-byte array to store the serialized signature. - * In: msg: the message being signed. Can only be NULL if msglen is 0. - * msglen: length of the message. - * keypair: pointer to an initialized keypair. - * extraparams: pointer to an extraparams object (can be NULL). - */ -SECP256K1_API int secp256k1_schnorrsig_sign_custom( - const secp256k1_context *ctx, - unsigned char *sig64, - const unsigned char *msg, - size_t msglen, - const secp256k1_keypair *keypair, - secp256k1_schnorrsig_extraparams *extraparams -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5); - -/** Verify a Schnorr signature. - * - * Returns: 1: correct signature - * 0: incorrect signature - * Args: ctx: pointer to a context object. - * In: sig64: pointer to the 64-byte signature to verify. - * msg: the message being verified. Can only be NULL if msglen is 0. - * msglen: length of the message - * pubkey: pointer to an x-only public key to verify with - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorrsig_verify( - const secp256k1_context *ctx, - const unsigned char *sig64, - const unsigned char *msg, - size_t msglen, - const secp256k1_xonly_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5); - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_SCHNORRSIG_H */ diff --git a/external/secp256k1/libsecp256k1.pc.in b/external/secp256k1/libsecp256k1.pc.in deleted file mode 100644 index 0fb6f48a6c..0000000000 --- a/external/secp256k1/libsecp256k1.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libsecp256k1 -Description: Optimized C library for EC operations on curve secp256k1 -URL: https://github.com/bitcoin-core/secp256k1 -Version: @PACKAGE_VERSION@ -Cflags: -I${includedir} -Libs: -L${libdir} -lsecp256k1 - diff --git a/external/secp256k1/sage/gen_exhaustive_groups.sage b/external/secp256k1/sage/gen_exhaustive_groups.sage deleted file mode 100644 index 070bc1285f..0000000000 --- a/external/secp256k1/sage/gen_exhaustive_groups.sage +++ /dev/null @@ -1,156 +0,0 @@ -load("secp256k1_params.sage") - -MAX_ORDER = 1000 - -# Set of (curve) orders we have encountered so far. -orders_done = set() - -# Map from (subgroup) orders to [b, int(gen.x), int(gen.y), gen, lambda] for those subgroups. -solutions = {} - -# Iterate over curves of the form y^2 = x^3 + B. -for b in range(1, P): - # There are only 6 curves (up to isomorphism) of the form y^2 = x^3 + B. Stop once we have tried all. - if len(orders_done) == 6: - break - - E = EllipticCurve(F, [0, b]) - print("Analyzing curve y^2 = x^3 + %i" % b) - n = E.order() - - # Skip curves with an order we've already tried - if n in orders_done: - print("- Isomorphic to earlier curve") - print() - continue - orders_done.add(n) - - # Skip curves isomorphic to the real secp256k1 - if n.is_pseudoprime(): - assert E.is_isomorphic(C) - print("- Isomorphic to secp256k1") - print() - continue - - print("- Finding prime subgroups") - - # Map from group_order to a set of independent generators for that order. - curve_gens = {} - - for g in E.gens(): - # Find what prime subgroups of group generated by g exist. - g_order = g.order() - for f, _ in g.order().factor(): - # Skip subgroups that have bad size. - if f < 4: - print(f" - Subgroup of size {f}: too small") - continue - if f > MAX_ORDER: - print(f" - Subgroup of size {f}: too large") - continue - - # Construct a generator for that subgroup. - gen = g * (g_order // f) - assert(gen.order() == f) - - # Add to set the minimal multiple of gen. - curve_gens.setdefault(f, set()).add(min([j*gen for j in range(1, f)])) - print(f" - Subgroup of size {f}: ok") - - for f in sorted(curve_gens.keys()): - print(f"- Constructing group of order {f}") - cbrts = sorted([int(c) for c in Integers(f)(1).nth_root(3, all=true) if c != 1]) - gens = list(curve_gens[f]) - sol_count = 0 - no_endo_count = 0 - - # Consider all non-zero linear combinations of the independent generators. - for j in range(1, f**len(gens)): - gen = sum(gens[k] * ((j // f**k) % f) for k in range(len(gens))) - assert not gen.is_zero() - assert (f*gen).is_zero() - - # Find lambda for endomorphism. Skip if none can be found. - lam = None - for l in cbrts: - if l*gen == E(BETA*gen[0], gen[1]): - lam = l - break - - if lam is None: - no_endo_count += 1 - else: - sol_count += 1 - solutions.setdefault(f, []).append((b, int(gen[0]), int(gen[1]), gen, lam)) - - print(f" - Found {sol_count} generators (plus {no_endo_count} without endomorphism)") - - print() - -def output_generator(g, name): - print(f"#define {name} SECP256K1_GE_CONST(\\") - print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[0]) >> (32 * (7 - i))) & 0xffffffff for i in range(4))) - print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[0]) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8))) - print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x,\\" % tuple((int(g[1]) >> (32 * (7 - i))) & 0xffffffff for i in range(4))) - print(" 0x%08x, 0x%08x, 0x%08x, 0x%08x\\" % tuple((int(g[1]) >> (32 * (7 - i))) & 0xffffffff for i in range(4, 8))) - print(")") - -def output_b(b): - print(f"#define SECP256K1_B {int(b)}") - -print() -print("To be put in src/group_impl.h:") -print() -print("/* Begin of section generated by sage/gen_exhaustive_groups.sage. */") -for f in sorted(solutions.keys()): - # Use as generator/2 the one with lowest b, and lowest (x, y) generator (interpreted as non-negative integers). - b, _, _, HALF_G, lam = min(solutions[f]) - output_generator(2 * HALF_G, f"SECP256K1_G_ORDER_{f}") -print("/** Generator for secp256k1, value 'g' defined in") -print(" * \"Standards for Efficient Cryptography\" (SEC2) 2.7.1.") -print(" */") -output_generator(G, "SECP256K1_G") -print("/* These exhaustive group test orders and generators are chosen such that:") -print(" * - The field size is equal to that of secp256k1, so field code is the same.") -print(" * - The curve equation is of the form y^2=x^3+B for some small constant B.") -print(" * - The subgroup has a generator 2*P, where P.x is as small as possible.") -print(f" * - The subgroup has size less than {MAX_ORDER} to permit exhaustive testing.") -print(" * - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y).") -print(" */") -print("#if defined(EXHAUSTIVE_TEST_ORDER)") -first = True -for f in sorted(solutions.keys()): - b, _, _, _, lam = min(solutions[f]) - print(f"# {'if' if first else 'elif'} EXHAUSTIVE_TEST_ORDER == {f}") - first = False - print() - print(f"static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_{f};") - output_b(b) - print() -print("# else") -print("# error No known generator for the specified exhaustive test group order.") -print("# endif") -print("#else") -print() -print("static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;") -output_b(7) -print() -print("#endif") -print("/* End of section generated by sage/gen_exhaustive_groups.sage. */") - - -print() -print() -print("To be put in src/scalar_impl.h:") -print() -print("/* Begin of section generated by sage/gen_exhaustive_groups.sage. */") -first = True -for f in sorted(solutions.keys()): - _, _, _, _, lam = min(solutions[f]) - print("# %s EXHAUSTIVE_TEST_ORDER == %i" % ("if" if first else "elif", f)) - first = False - print("# define EXHAUSTIVE_TEST_LAMBDA %i" % lam) -print("# else") -print("# error No known lambda for the specified exhaustive test group order.") -print("# endif") -print("/* End of section generated by sage/gen_exhaustive_groups.sage. */") diff --git a/external/secp256k1/sage/gen_split_lambda_constants.sage b/external/secp256k1/sage/gen_split_lambda_constants.sage deleted file mode 100644 index 7d4359e0f6..0000000000 --- a/external/secp256k1/sage/gen_split_lambda_constants.sage +++ /dev/null @@ -1,114 +0,0 @@ -""" Generates the constants used in secp256k1_scalar_split_lambda. - -See the comments for secp256k1_scalar_split_lambda in src/scalar_impl.h for detailed explanations. -""" - -load("secp256k1_params.sage") - -def inf_norm(v): - """Returns the infinity norm of a vector.""" - return max(map(abs, v)) - -def gauss_reduction(i1, i2): - v1, v2 = i1.copy(), i2.copy() - while True: - if inf_norm(v2) < inf_norm(v1): - v1, v2 = v2, v1 - # This is essentially - # m = round((v1[0]*v2[0] + v1[1]*v2[1]) / (inf_norm(v1)**2)) - # (rounding to the nearest integer) without relying on floating point arithmetic. - m = ((v1[0]*v2[0] + v1[1]*v2[1]) + (inf_norm(v1)**2) // 2) // (inf_norm(v1)**2) - if m == 0: - return v1, v2 - v2[0] -= m*v1[0] - v2[1] -= m*v1[1] - -def find_split_constants_gauss(): - """Find constants for secp256k1_scalar_split_lamdba using gauss reduction.""" - (v11, v12), (v21, v22) = gauss_reduction([0, N], [1, int(LAMBDA)]) - - # We use related vectors in secp256k1_scalar_split_lambda. - A1, B1 = -v21, -v11 - A2, B2 = v22, -v21 - - return A1, B1, A2, B2 - -def find_split_constants_explicit_tof(): - """Find constants for secp256k1_scalar_split_lamdba using the trace of Frobenius. - - See Benjamin Smith: "Easy scalar decompositions for efficient scalar multiplication on - elliptic curves and genus 2 Jacobians" (https://eprint.iacr.org/2013/672), Example 2 - """ - assert P % 3 == 1 # The paper says P % 3 == 2 but that appears to be a mistake, see [10]. - assert C.j_invariant() == 0 - - t = C.trace_of_frobenius() - - c = Integer(sqrt((4*P - t**2)/3)) - A1 = Integer((t - c)/2 - 1) - B1 = c - - A2 = Integer((t + c)/2 - 1) - B2 = Integer(1 - (t - c)/2) - - # We use a negated b values in secp256k1_scalar_split_lambda. - B1, B2 = -B1, -B2 - - return A1, B1, A2, B2 - -A1, B1, A2, B2 = find_split_constants_explicit_tof() - -# For extra fun, use an independent method to recompute the constants. -assert (A1, B1, A2, B2) == find_split_constants_gauss() - -# PHI : Z[l] -> Z_n where phi(a + b*l) == a + b*lambda mod n. -def PHI(a,b): - return Z(a + LAMBDA*b) - -# Check that (A1, B1) and (A2, B2) are in the kernel of PHI. -assert PHI(A1, B1) == Z(0) -assert PHI(A2, B2) == Z(0) - -# Check that the parallelogram generated by (A1, A2) and (B1, B2) -# is a fundamental domain by containing exactly N points. -# Since the LHS is the determinant and N != 0, this also checks that -# (A1, A2) and (B1, B2) are linearly independent. By the previous -# assertions, (A1, A2) and (B1, B2) are a basis of the kernel. -assert A1*B2 - B1*A2 == N - -# Check that their components are short enough. -assert (A1 + A2)/2 < sqrt(N) -assert B1 < sqrt(N) -assert B2 < sqrt(N) - -G1 = round((2**384)*B2/N) -G2 = round((2**384)*(-B1)/N) - -def rnddiv2(v): - if v & 1: - v += 1 - return v >> 1 - -def scalar_lambda_split(k): - """Equivalent to secp256k1_scalar_lambda_split().""" - c1 = rnddiv2((k * G1) >> 383) - c2 = rnddiv2((k * G2) >> 383) - c1 = (c1 * -B1) % N - c2 = (c2 * -B2) % N - r2 = (c1 + c2) % N - r1 = (k + r2 * -LAMBDA) % N - return (r1, r2) - -# The result of scalar_lambda_split can depend on the representation of k (mod n). -SPECIAL = (2**383) // G2 + 1 -assert scalar_lambda_split(SPECIAL) != scalar_lambda_split(SPECIAL + N) - -print(' A1 =', hex(A1)) -print(' -B1 =', hex(-B1)) -print(' A2 =', hex(A2)) -print(' -B2 =', hex(-B2)) -print(' =', hex(Z(-B2))) -print(' -LAMBDA =', hex(-LAMBDA)) - -print(' G1 =', hex(G1)) -print(' G2 =', hex(G2)) diff --git a/external/secp256k1/sage/group_prover.sage b/external/secp256k1/sage/group_prover.sage deleted file mode 100644 index bb09295369..0000000000 --- a/external/secp256k1/sage/group_prover.sage +++ /dev/null @@ -1,353 +0,0 @@ -# This code supports verifying group implementations which have branches -# or conditional statements (like cmovs), by allowing each execution path -# to independently set assumptions on input or intermediary variables. -# -# The general approach is: -# * A constraint is a tuple of two sets of symbolic expressions: -# the first of which are required to evaluate to zero, the second of which -# are required to evaluate to nonzero. -# - A constraint is said to be conflicting if any of its nonzero expressions -# is in the ideal with basis the zero expressions (in other words: when the -# zero expressions imply that one of the nonzero expressions are zero). -# * There is a list of laws that describe the intended behaviour, including -# laws for addition and doubling. Each law is called with the symbolic point -# coordinates as arguments, and returns: -# - A constraint describing the assumptions under which it is applicable, -# called "assumeLaw" -# - A constraint describing the requirements of the law, called "require" -# * Implementations are transliterated into functions that operate as well on -# algebraic input points, and are called once per combination of branches -# executed. Each execution returns: -# - A constraint describing the assumptions this implementation requires -# (such as Z1=1), called "assumeFormula" -# - A constraint describing the assumptions this specific branch requires, -# but which is by construction guaranteed to cover the entire space by -# merging the results from all branches, called "assumeBranch" -# - The result of the computation -# * All combinations of laws with implementation branches are tried, and: -# - If the combination of assumeLaw, assumeFormula, and assumeBranch results -# in a conflict, it means this law does not apply to this branch, and it is -# skipped. -# - For others, we try to prove the require constraints hold, assuming the -# information in assumeLaw + assumeFormula + assumeBranch, and if this does -# not succeed, we fail. -# + To prove an expression is zero, we check whether it belongs to the -# ideal with the assumed zero expressions as basis. This test is exact. -# + To prove an expression is nonzero, we check whether each of its -# factors is contained in the set of nonzero assumptions' factors. -# This test is not exact, so various combinations of original and -# reduced expressions' factors are tried. -# - If we succeed, we print out the assumptions from assumeFormula that -# weren't implied by assumeLaw already. Those from assumeBranch are skipped, -# as we assume that all constraints in it are complementary with each other. -# -# Based on the sage verification scripts used in the Explicit-Formulas Database -# by Tanja Lange and others, see https://hyperelliptic.org/EFD - -class fastfrac: - """Fractions over rings.""" - - def __init__(self,R,top,bot=1): - """Construct a fractional, given a ring, a numerator, and denominator.""" - self.R = R - if parent(top) == ZZ or parent(top) == R: - self.top = R(top) - self.bot = R(bot) - elif top.__class__ == fastfrac: - self.top = top.top - self.bot = top.bot * bot - else: - self.top = R(numerator(top)) - self.bot = R(denominator(top)) * bot - - def iszero(self,I): - """Return whether this fraction is zero given an ideal.""" - return self.top in I and self.bot not in I - - def reduce(self,assumeZero): - zero = self.R.ideal(list(map(numerator, assumeZero))) - return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot)) - - def __add__(self,other): - """Add two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top + self.bot * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot + self.bot * other.top,self.bot * other.bot) - return NotImplemented - - def __sub__(self,other): - """Subtract two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top - self.bot * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot - self.bot * other.top,self.bot * other.bot) - return NotImplemented - - def __neg__(self): - """Return the negation of a fraction.""" - return fastfrac(self.R,-self.top,self.bot) - - def __mul__(self,other): - """Multiply two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top * other,self.bot) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.top,self.bot * other.bot) - return NotImplemented - - def __rmul__(self,other): - """Multiply something else with a fraction.""" - return self.__mul__(other) - - def __truediv__(self,other): - """Divide two fractions.""" - if parent(other) == ZZ: - return fastfrac(self.R,self.top,self.bot * other) - if other.__class__ == fastfrac: - return fastfrac(self.R,self.top * other.bot,self.bot * other.top) - return NotImplemented - - # Compatibility wrapper for Sage versions based on Python 2 - def __div__(self,other): - """Divide two fractions.""" - return self.__truediv__(other) - - def __pow__(self,other): - """Compute a power of a fraction.""" - if parent(other) == ZZ: - if other < 0: - # Negative powers require flipping top and bottom - return fastfrac(self.R,self.bot ^ (-other),self.top ^ (-other)) - else: - return fastfrac(self.R,self.top ^ other,self.bot ^ other) - return NotImplemented - - def __str__(self): - return "fastfrac((" + str(self.top) + ") / (" + str(self.bot) + "))" - def __repr__(self): - return "%s" % self - - def numerator(self): - return self.top - -class constraints: - """A set of constraints, consisting of zero and nonzero expressions. - - Constraints can either be used to express knowledge or a requirement. - - Both the fields zero and nonzero are maps from expressions to description - strings. The expressions that are the keys in zero are required to be zero, - and the expressions that are the keys in nonzero are required to be nonzero. - - Note that (a != 0) and (b != 0) is the same as (a*b != 0), so all keys in - nonzero could be multiplied into a single key. This is often much less - efficient to work with though, so we keep them separate inside the - constraints. This allows higher-level code to do fast checks on the individual - nonzero elements, or combine them if needed for stronger checks. - - We can't multiply the different zero elements, as it would suffice for one of - the factors to be zero, instead of all of them. Instead, the zero elements are - typically combined into an ideal first. - """ - - def __init__(self, **kwargs): - if 'zero' in kwargs: - self.zero = dict(kwargs['zero']) - else: - self.zero = dict() - if 'nonzero' in kwargs: - self.nonzero = dict(kwargs['nonzero']) - else: - self.nonzero = dict() - - def negate(self): - return constraints(zero=self.nonzero, nonzero=self.zero) - - def map(self, fun): - return constraints(zero={fun(k): v for k, v in self.zero.items()}, nonzero={fun(k): v for k, v in self.nonzero.items()}) - - def __add__(self, other): - zero = self.zero.copy() - zero.update(other.zero) - nonzero = self.nonzero.copy() - nonzero.update(other.nonzero) - return constraints(zero=zero, nonzero=nonzero) - - def __str__(self): - return "constraints(zero=%s,nonzero=%s)" % (self.zero, self.nonzero) - - def __repr__(self): - return "%s" % self - -def normalize_factor(p): - """Normalizes the sign of primitive polynomials (as returned by factor()) - - This function ensures that the polynomial has a positive leading coefficient. - - This is necessary because recent sage versions (starting with v9.3 or v9.4, - we don't know) are inconsistent about the placement of the minus sign in - polynomial factorizations: - ``` - sage: R. = PolynomialRing(QQ,8,order='invlex') - sage: R((-2 * (bx - ax)) ^ 1).factor() - (-2) * (bx - ax) - sage: R((-2 * (bx - ax)) ^ 2).factor() - (4) * (-bx + ax)^2 - sage: R((-2 * (bx - ax)) ^ 3).factor() - (8) * (-bx + ax)^3 - ``` - """ - # Assert p is not 0 and that its non-zero coefficients are coprime. - # (We could just work with the primitive part p/p.content() but we want to be - # aware if factor() does not return a primitive part in future sage versions.) - assert p.content() == 1 - # Ensure that the first non-zero coefficient is positive. - return p if p.lc() > 0 else -p - -def conflicts(R, con): - """Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" - zero = R.ideal(list(map(numerator, con.zero))) - if 1 in zero: - return True - # First a cheap check whether any of the individual nonzero terms conflict on - # their own. - for nonzero in con.nonzero: - if nonzero.iszero(zero): - return True - # It can be the case that entries in the nonzero set do not individually - # conflict with the zero set, but their combination does. For example, knowing - # that either x or y is zero is equivalent to having x*y in the zero set. - # Having x or y individually in the nonzero set is not a conflict, but both - # simultaneously is, so that is the right thing to check for. - if reduce(lambda a,b: a * b, con.nonzero, fastfrac(R, 1)).iszero(zero): - return True - return False - - -def get_nonzero_set(R, assume): - """Calculate a simple set of nonzero expressions""" - zero = R.ideal(list(map(numerator, assume.zero))) - nonzero = set() - for nz in map(numerator, assume.nonzero): - for (f,n) in nz.factor(): - nonzero.add(normalize_factor(f)) - rnz = zero.reduce(nz) - for (f,n) in rnz.factor(): - nonzero.add(normalize_factor(f)) - return nonzero - - -def prove_nonzero(R, exprs, assume): - """Check whether an expression is provably nonzero, given assumptions""" - zero = R.ideal(list(map(numerator, assume.zero))) - nonzero = get_nonzero_set(R, assume) - expl = set() - ok = True - for expr in exprs: - if numerator(expr) in zero: - return (False, [exprs[expr]]) - allexprs = reduce(lambda a,b: numerator(a)*numerator(b), exprs, 1) - for (f, n) in allexprs.factor(): - if normalize_factor(f) not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for (f, n) in zero.reduce(allexprs).factor(): - if normalize_factor(f) not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for expr in exprs: - for (f,n) in numerator(expr).factor(): - if normalize_factor(f) not in nonzero: - ok = False - if ok: - return (True, None) - ok = True - for expr in exprs: - for (f,n) in zero.reduce(numerator(expr)).factor(): - if normalize_factor(f) not in nonzero: - expl.add(exprs[expr]) - if expl: - return (False, list(expl)) - else: - return (True, None) - - -def prove_zero(R, exprs, assume): - """Check whether all of the passed expressions are provably zero, given assumptions""" - r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) - if not r: - return (False, list(map(lambda x: "Possibly zero denominator: %s" % x, e))) - zero = R.ideal(list(map(numerator, assume.zero))) - nonzero = prod(x for x in assume.nonzero) - expl = [] - for expr in exprs: - if not expr.iszero(zero): - expl.append(exprs[expr]) - if not expl: - return (True, None) - return (False, expl) - - -def describe_extra(R, assume, assumeExtra): - """Describe what assumptions are added, given existing assumptions""" - zerox = assume.zero.copy() - zerox.update(assumeExtra.zero) - zero = R.ideal(list(map(numerator, assume.zero))) - zeroextra = R.ideal(list(map(numerator, zerox))) - nonzero = get_nonzero_set(R, assume) - ret = set() - # Iterate over the extra zero expressions - for base in assumeExtra.zero: - if base not in zero: - add = [] - for (f, n) in numerator(base).factor(): - if normalize_factor(f) not in nonzero: - add += ["%s" % normalize_factor(f)] - if add: - ret.add((" * ".join(add)) + " = 0 [%s]" % assumeExtra.zero[base]) - # Iterate over the extra nonzero expressions - for nz in assumeExtra.nonzero: - nzr = zeroextra.reduce(numerator(nz)) - if nzr not in zeroextra: - for (f,n) in nzr.factor(): - if normalize_factor(zeroextra.reduce(f)) not in nonzero: - ret.add("%s != 0" % normalize_factor(zeroextra.reduce(f))) - return ", ".join(x for x in ret) - - -def check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require): - """Check a set of zero and nonzero requirements, given a set of zero and nonzero assumptions""" - assume = assumeLaw + assumeAssert + assumeBranch - - if conflicts(R, assume): - # This formula does not apply - return (True, None) - - describe = describe_extra(R, assumeLaw + assumeBranch, assumeAssert) - if describe != "": - describe = " (assuming " + describe + ")" - - ok, msg = prove_zero(R, require.zero, assume) - if not ok: - return (False, "FAIL, %s fails%s" % (str(msg), describe)) - - res, expl = prove_nonzero(R, require.nonzero, assume) - if not res: - return (False, "FAIL, %s fails%s" % (str(expl), describe)) - - return (True, "OK%s" % describe) - - -def concrete_verify(c): - for k in c.zero: - if k != 0: - return (False, c.zero[k]) - for k in c.nonzero: - if k == 0: - return (False, c.nonzero[k]) - return (True, None) diff --git a/external/secp256k1/sage/prove_group_implementations.sage b/external/secp256k1/sage/prove_group_implementations.sage deleted file mode 100644 index 23799be52b..0000000000 --- a/external/secp256k1/sage/prove_group_implementations.sage +++ /dev/null @@ -1,285 +0,0 @@ -# Test libsecp256k1' group operation implementations using prover.sage - -import sys - -load("group_prover.sage") -load("weierstrass_prover.sage") - -def formula_secp256k1_gej_double_var(a): - """libsecp256k1's secp256k1_gej_double_var, used by various addition functions""" - rz = a.Z * a.Y - s = a.Y^2 - l = a.X^2 - l = l * 3 - l = l / 2 - t = -s - t = t * a.X - rx = l^2 - rx = rx + t - rx = rx + t - s = s^2 - t = t + rx - ry = t * l - ry = ry + s - ry = -ry - return jacobianpoint(rx, ry, rz) - -def formula_secp256k1_gej_add_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_var""" - if branch == 0: - return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b) - if branch == 1: - return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) - z22 = b.Z^2 - z12 = a.Z^2 - u1 = a.X * z22 - u2 = b.X * z12 - s1 = a.Y * z22 - s1 = s1 * b.Z - s2 = b.Y * z12 - s2 = s2 * a.Z - h = -u1 - h = h + u2 - i = -s2 - i = i + s1 - if branch == 2: - r = formula_secp256k1_gej_double_var(a) - return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r) - if branch == 3: - return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity()) - t = h * b.Z - rz = a.Z * t - h2 = h^2 - h2 = -h2 - h3 = h2 * h - t = u1 * h2 - rx = i^2 - rx = rx + h3 - rx = rx + t - rx = rx + t - t = t + rx - ry = t * i - h3 = h3 * s1 - ry = ry + h3 - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_ge_var, which assume bz==1""" - if branch == 0: - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b) - if branch == 1: - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) - z12 = a.Z^2 - u1 = a.X - u2 = b.X * z12 - s1 = a.Y - s2 = b.Y * z12 - s2 = s2 * a.Z - h = -u1 - h = h + u2 - i = -s2 - i = i + s1 - if (branch == 2): - r = formula_secp256k1_gej_double_var(a) - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) - if (branch == 3): - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) - rz = a.Z * h - h2 = h^2 - h2 = -h2 - h3 = h2 * h - t = u1 * h2 - rx = i^2 - rx = rx + h3 - rx = rx + t - rx = rx + t - t = t + rx - ry = t * i - h3 = h3 * s1 - ry = ry + h3 - return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_zinv_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_zinv_var""" - bzinv = b.Z^(-1) - if branch == 0: - rinf = b.Infinity - bzinv2 = bzinv^2 - bzinv3 = bzinv2 * bzinv - rx = b.X * bzinv2 - ry = b.Y * bzinv3 - rz = 1 - return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), jacobianpoint(rx, ry, rz, rinf)) - if branch == 1: - return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) - azz = a.Z * bzinv - z12 = azz^2 - u1 = a.X - u2 = b.X * z12 - s1 = a.Y - s2 = b.Y * z12 - s2 = s2 * azz - h = -u1 - h = h + u2 - i = -s2 - i = i + s1 - if branch == 2: - r = formula_secp256k1_gej_double_var(a) - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) - if branch == 3: - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) - rz = a.Z * h - h2 = h^2 - h2 = -h2 - h3 = h2 * h - t = u1 * h2 - rx = i^2 - rx = rx + h3 - rx = rx + t - rx = rx + t - t = t + rx - ry = t * i - h3 = h3 * s1 - ry = ry + h3 - return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge(branch, a, b): - """libsecp256k1's secp256k1_gej_add_ge""" - zeroes = {} - nonzeroes = {} - a_infinity = False - if (branch & 2) != 0: - nonzeroes.update({a.Infinity : 'a_infinite'}) - a_infinity = True - else: - zeroes.update({a.Infinity : 'a_finite'}) - zz = a.Z^2 - u1 = a.X - u2 = b.X * zz - s1 = a.Y - s2 = b.Y * zz - s2 = s2 * a.Z - t = u1 - t = t + u2 - m = s1 - m = m + s2 - rr = t^2 - m_alt = -u2 - tt = u1 * m_alt - rr = rr + tt - degenerate = (branch & 1) != 0 - if degenerate: - zeroes.update({m : 'm_zero'}) - else: - nonzeroes.update({m : 'm_nonzero'}) - rr_alt = s1 - rr_alt = rr_alt * 2 - m_alt = m_alt + u1 - if not degenerate: - rr_alt = rr - m_alt = m - n = m_alt^2 - q = -t - q = q * n - n = n^2 - if degenerate: - n = m - t = rr_alt^2 - rz = a.Z * m_alt - t = t + q - rx = t - t = t * 2 - t = t + q - t = t * rr_alt - t = t + n - ry = -t - ry = ry / 2 - if a_infinity: - rx = b.X - ry = b.Y - rz = 1 - if (branch & 4) != 0: - zeroes.update({rz : 'r.z = 0'}) - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity()) - else: - nonzeroes.update({rz : 'r.z != 0'}) - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) - -def formula_secp256k1_gej_add_ge_old(branch, a, b): - """libsecp256k1's old secp256k1_gej_add_ge, which fails when ay+by=0 but ax!=bx""" - a_infinity = (branch & 1) != 0 - zero = {} - nonzero = {} - if a_infinity: - nonzero.update({a.Infinity : 'a_infinite'}) - else: - zero.update({a.Infinity : 'a_finite'}) - zz = a.Z^2 - u1 = a.X - u2 = b.X * zz - s1 = a.Y - s2 = b.Y * zz - s2 = s2 * a.Z - z = a.Z - t = u1 - t = t + u2 - m = s1 - m = m + s2 - n = m^2 - q = n * t - n = n^2 - rr = t^2 - t = u1 * u2 - t = -t - rr = rr + t - t = rr^2 - rz = m * z - infinity = False - if (branch & 2) != 0: - if not a_infinity: - infinity = True - else: - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(nonzero={z : 'conflict_a'}, zero={z : 'conflict_b'}), point_at_infinity()) - zero.update({rz : 'r.z=0'}) - else: - nonzero.update({rz : 'r.z!=0'}) - rz = rz * (0 if a_infinity else 2) - rx = t - q = -q - rx = rx + q - q = q * 3 - t = t * 2 - t = t + q - t = t * rr - t = t + n - ry = -t - rx = rx * (0 if a_infinity else 4) - ry = ry * (0 if a_infinity else 4) - t = b.X - t = t * (1 if a_infinity else 0) - rx = rx + t - t = b.Y - t = t * (1 if a_infinity else 0) - ry = ry + t - t = (1 if a_infinity else 0) - rz = rz + t - if infinity: - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), point_at_infinity()) - return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz)) - -if __name__ == "__main__": - success = True - success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) - success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) - success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) - success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 8, formula_secp256k1_gej_add_ge) - success = success & (not check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old)) - - if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": - success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) - success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) - success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) - success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 8, formula_secp256k1_gej_add_ge, 43) - success = success & (not check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43)) - - sys.exit(int(not success)) diff --git a/external/secp256k1/sage/secp256k1_params.sage b/external/secp256k1/sage/secp256k1_params.sage deleted file mode 100644 index 68f95adec4..0000000000 --- a/external/secp256k1/sage/secp256k1_params.sage +++ /dev/null @@ -1,39 +0,0 @@ -"""Prime order of finite field underlying secp256k1 (2^256 - 2^32 - 977)""" -P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F - -"""Finite field underlying secp256k1""" -F = FiniteField(P) - -"""Elliptic curve secp256k1: y^2 = x^3 + 7""" -C = EllipticCurve([F(0), F(7)]) - -"""Base point of secp256k1""" -G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) -if int(G[1]) & 1: - # G.y is even - G = -G - -"""Prime order of secp256k1""" -N = C.order() - -"""Finite field of scalars of secp256k1""" -Z = FiniteField(N) - -""" Beta value of secp256k1 non-trivial endomorphism: lambda * (x, y) = (beta * x, y)""" -BETA = F(2)^((P-1)/3) - -""" Lambda value of secp256k1 non-trivial endomorphism: lambda * (x, y) = (beta * x, y)""" -LAMBDA = Z(3)^((N-1)/3) - -assert is_prime(P) -assert is_prime(N) - -assert BETA != F(1) -assert BETA^3 == F(1) -assert BETA^2 + BETA + 1 == 0 - -assert LAMBDA != Z(1) -assert LAMBDA^3 == Z(1) -assert LAMBDA^2 + LAMBDA + 1 == 0 - -assert Integer(LAMBDA)*G == C(BETA*G[0], G[1]) diff --git a/external/secp256k1/sage/weierstrass_prover.sage b/external/secp256k1/sage/weierstrass_prover.sage deleted file mode 100644 index be9cfd4c76..0000000000 --- a/external/secp256k1/sage/weierstrass_prover.sage +++ /dev/null @@ -1,275 +0,0 @@ -# Prover implementation for Weierstrass curves of the form -# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws -# operating on affine and Jacobian coordinates, including the point at infinity -# represented by a 4th variable in coordinates. - -load("group_prover.sage") - - -class affinepoint: - def __init__(self, x, y, infinity=0): - self.x = x - self.y = y - self.infinity = infinity - def __str__(self): - return "affinepoint(x=%s,y=%s,inf=%s)" % (self.x, self.y, self.infinity) - - -class jacobianpoint: - def __init__(self, x, y, z, infinity=0): - self.X = x - self.Y = y - self.Z = z - self.Infinity = infinity - def __str__(self): - return "jacobianpoint(X=%s,Y=%s,Z=%s,inf=%s)" % (self.X, self.Y, self.Z, self.Infinity) - - -def point_at_infinity(): - return jacobianpoint(1, 1, 1, 1) - - -def negate(p): - if p.__class__ == affinepoint: - return affinepoint(p.x, -p.y) - if p.__class__ == jacobianpoint: - return jacobianpoint(p.X, -p.Y, p.Z) - assert(False) - - -def on_weierstrass_curve(A, B, p): - """Return a set of zero-expressions for an affine point to be on the curve""" - return constraints(zero={p.x^3 + A*p.x + B - p.y^2: 'on_curve'}) - - -def tangential_to_weierstrass_curve(A, B, p12, p3): - """Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)""" - return constraints(zero={ - (p12.y - p3.y) * (p12.y * 2) - (p12.x^2 * 3 + A) * (p12.x - p3.x): 'tangential_to_curve' - }) - - -def colinear(p1, p2, p3): - """Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear""" - return constraints(zero={ - (p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x): 'colinear_1', - (p2.y - p3.y) * (p2.x - p1.x) - (p2.y - p1.y) * (p2.x - p3.x): 'colinear_2', - (p3.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p3.x - p1.x): 'colinear_3' - }) - - -def good_affine_point(p): - return constraints(nonzero={p.x : 'nonzero_x', p.y : 'nonzero_y'}) - - -def good_jacobian_point(p): - return constraints(nonzero={p.X : 'nonzero_X', p.Y : 'nonzero_Y', p.Z^6 : 'nonzero_Z'}) - - -def good_point(p): - return constraints(nonzero={p.Z^6 : 'nonzero_X'}) - - -def finite(p, *affine_fns): - con = good_point(p) + constraints(zero={p.Infinity : 'finite_point'}) - if p.Z != 0: - return con + reduce(lambda a, b: a + b, (f(affinepoint(p.X / p.Z^2, p.Y / p.Z^3)) for f in affine_fns), con) - else: - return con - -def infinite(p): - return constraints(nonzero={p.Infinity : 'infinite_point'}) - - -def law_jacobian_weierstrass_add(A, B, pa, pb, pA, pB, pC): - """Check whether the passed set of coordinates is a valid Jacobian add, given assumptions""" - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(nonzero={pa.x - pb.x : 'different_x'})) - require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + - colinear(pa, pb, negate(pc)))) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_double(A, B, pa, pb, pA, pB, pC): - """Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions""" - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(zero={pa.x - pb.x : 'equal_x', pa.y - pb.y : 'equal_y'})) - require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + - tangential_to_weierstrass_curve(A, B, pa, negate(pc)))) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_opposites(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - on_weierstrass_curve(A, B, pb) + - finite(pA) + - finite(pB) + - constraints(zero={pa.x - pb.x : 'equal_x', pa.y + pb.y : 'opposite_y'})) - require = infinite(pC) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_a(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pb) + - infinite(pA) + - finite(pB)) - require = finite(pC, lambda pc: constraints(zero={pc.x - pb.x : 'c.x=b.x', pc.y - pb.y : 'c.y=b.y'})) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_b(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - on_weierstrass_curve(A, B, pa) + - infinite(pB) + - finite(pA)) - require = finite(pC, lambda pc: constraints(zero={pc.x - pa.x : 'c.x=a.x', pc.y - pa.y : 'c.y=a.y'})) - return (assumeLaw, require) - - -def law_jacobian_weierstrass_add_infinite_ab(A, B, pa, pb, pA, pB, pC): - assumeLaw = (good_affine_point(pa) + - good_affine_point(pb) + - good_jacobian_point(pA) + - good_jacobian_point(pB) + - infinite(pA) + - infinite(pB)) - require = infinite(pC) - return (assumeLaw, require) - - -laws_jacobian_weierstrass = { - 'add': law_jacobian_weierstrass_add, - 'double': law_jacobian_weierstrass_double, - 'add_opposite': law_jacobian_weierstrass_add_opposites, - 'add_infinite_a': law_jacobian_weierstrass_add_infinite_a, - 'add_infinite_b': law_jacobian_weierstrass_add_infinite_b, - 'add_infinite_ab': law_jacobian_weierstrass_add_infinite_ab -} - - -def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): - """Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field""" - F = Integers(p) - print("Formula %s on Z%i:" % (name, p)) - points = [] - for x in range(0, p): - for y in range(0, p): - point = affinepoint(F(x), F(y)) - r, e = concrete_verify(on_weierstrass_curve(A, B, point)) - if r: - points.append(point) - - ret = True - for za in range(1, p): - for zb in range(1, p): - for pa in points: - for pb in points: - for ia in range(2): - for ib in range(2): - pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia) - pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib) - for branch in range(0, branches): - assumeAssert, assumeBranch, pC = formula(branch, pA, pB) - pC.X = F(pC.X) - pC.Y = F(pC.Y) - pC.Z = F(pC.Z) - pC.Infinity = F(pC.Infinity) - r, e = concrete_verify(assumeAssert + assumeBranch) - if r: - match = False - for key in laws_jacobian_weierstrass: - assumeLaw, require = laws_jacobian_weierstrass[key](A, B, pa, pb, pA, pB, pC) - r, e = concrete_verify(assumeLaw) - if r: - if match: - print(" multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity)) - else: - match = True - r, e = concrete_verify(require) - if not r: - ret = False - print(" failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e)) - - print() - return ret - - -def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC): - assumeLaw, require = f(A, B, pa, pb, pA, pB, pC) - return check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require) - -def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula): - """Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically""" - R. = PolynomialRing(QQ,8,order='invlex') - lift = lambda x: fastfrac(R,x) - ax = lift(ax) - ay = lift(ay) - Az = lift(Az) - bx = lift(bx) - by = lift(by) - Bz = lift(Bz) - Ai = lift(Ai) - Bi = lift(Bi) - - pa = affinepoint(ax, ay, Ai) - pb = affinepoint(bx, by, Bi) - pA = jacobianpoint(ax * Az^2, ay * Az^3, Az, Ai) - pB = jacobianpoint(bx * Bz^2, by * Bz^3, Bz, Bi) - - res = {} - - for key in laws_jacobian_weierstrass: - res[key] = [] - - print("Formula " + name + ":") - count = 0 - ret = True - for branch in range(branches): - assumeFormula, assumeBranch, pC = formula(branch, pA, pB) - assumeBranch = assumeBranch.map(lift) - assumeFormula = assumeFormula.map(lift) - pC.X = lift(pC.X) - pC.Y = lift(pC.Y) - pC.Z = lift(pC.Z) - pC.Infinity = lift(pC.Infinity) - - for key in laws_jacobian_weierstrass: - success, msg = check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC) - if not success: - ret = False - res[key].append((msg, branch)) - - for key in res: - print(" %s:" % key) - val = res[key] - for x in val: - if x[0] is not None: - print(" branch %i: %s" % (x[1], x[0])) - - print() - return ret diff --git a/external/secp256k1/src/CMakeLists.txt b/external/secp256k1/src/CMakeLists.txt deleted file mode 100644 index f31b8c8f55..0000000000 --- a/external/secp256k1/src/CMakeLists.txt +++ /dev/null @@ -1,176 +0,0 @@ -# Must be included before CMAKE_INSTALL_INCLUDEDIR is used. -include(GNUInstallDirs) - -add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL - precomputed_ecmult.c - precomputed_ecmult_gen.c -) - -# Add objects explicitly rather than linking to the object libs to keep them -# from being exported. -add_library(secp256k1 secp256k1.c $) - -add_library(secp256k1_asm INTERFACE) -if(SECP256K1_ASM STREQUAL "arm32") - add_library(secp256k1_asm_arm OBJECT EXCLUDE_FROM_ALL) - target_sources(secp256k1_asm_arm PUBLIC - asm/field_10x26_arm.s - ) - target_sources(secp256k1 PRIVATE $) - target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm) -endif() - -if(WIN32) - # Define our export symbol only for shared libs. - set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL SECP256K1_DLL_EXPORT) - target_compile_definitions(secp256k1 INTERFACE $<$>:SECP256K1_STATIC>) -endif() - -# Object libs don't know if they're being built for a shared or static lib. -# Grab the PIC property from secp256k1 which knows. -get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE) -set_target_properties(secp256k1_precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic}) - -target_include_directories(secp256k1 INTERFACE - # Add the include path for parent projects so that they don't have to manually add it. - $>:${PROJECT_SOURCE_DIR}/include>> - $ -) - -# This emulates Libtool to make sure Libtool and CMake agree on the ABI version, -# see below "Calculate the version variables" in build-aux/ltmain.sh. -math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${${PROJECT_NAME}_LIB_VERSION_AGE}") -set_target_properties(secp256k1 PROPERTIES - SOVERSION ${${PROJECT_NAME}_soversion} -) -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set_target_properties(secp256k1 PROPERTIES - VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION} - ) -elseif(APPLE) - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17) - math(EXPR ${PROJECT_NAME}_compatibility_version "${${PROJECT_NAME}_LIB_VERSION_CURRENT} + 1") - set_target_properties(secp256k1 PROPERTIES - MACHO_COMPATIBILITY_VERSION ${${PROJECT_NAME}_compatibility_version} - MACHO_CURRENT_VERSION ${${PROJECT_NAME}_compatibility_version}.${${PROJECT_NAME}_LIB_VERSION_REVISION} - ) - unset(${PROJECT_NAME}_compatibility_version) - elseif(BUILD_SHARED_LIBS) - message(WARNING - "The 'compatibility version' and 'current version' values of the DYLIB " - "will diverge from the values set by the GNU Libtool. To ensure " - "compatibility, it is recommended to upgrade CMake to at least version 3.17." - ) - endif() -elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") - set(${PROJECT_NAME}_windows "secp256k1") - if(MSVC) - set(${PROJECT_NAME}_windows "${PROJECT_NAME}") - endif() - set_target_properties(secp256k1 PROPERTIES - ARCHIVE_OUTPUT_NAME "${${PROJECT_NAME}_windows}" - RUNTIME_OUTPUT_NAME "${${PROJECT_NAME}_windows}-${${PROJECT_NAME}_soversion}" - ) - unset(${PROJECT_NAME}_windows) -endif() -unset(${PROJECT_NAME}_soversion) - -if(SECP256K1_BUILD_BENCHMARK) - add_executable(bench bench.c) - target_link_libraries(bench secp256k1) - add_executable(bench_internal bench_internal.c) - target_link_libraries(bench_internal secp256k1_precomputed secp256k1_asm) - add_executable(bench_ecmult bench_ecmult.c) - target_link_libraries(bench_ecmult secp256k1_precomputed secp256k1_asm) -endif() - -if(SECP256K1_BUILD_TESTS) - add_executable(noverify_tests tests.c) - target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm) - add_test(NAME secp256k1_noverify_tests COMMAND noverify_tests) - if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage") - add_executable(tests tests.c) - target_compile_definitions(tests PRIVATE VERIFY) - target_link_libraries(tests secp256k1_precomputed secp256k1_asm) - add_test(NAME secp256k1_tests COMMAND tests) - endif() -endif() - -if(SECP256K1_BUILD_EXHAUSTIVE_TESTS) - # Note: do not include secp256k1_precomputed in exhaustive_tests (it uses runtime-generated tables). - add_executable(exhaustive_tests tests_exhaustive.c) - target_link_libraries(exhaustive_tests secp256k1_asm) - target_compile_definitions(exhaustive_tests PRIVATE $<$>:VERIFY>) - add_test(NAME secp256k1_exhaustive_tests COMMAND exhaustive_tests) -endif() - -if(SECP256K1_BUILD_CTIME_TESTS) - add_executable(ctime_tests ctime_tests.c) - target_link_libraries(ctime_tests secp256k1) -endif() - -if(SECP256K1_INSTALL) - install(TARGETS secp256k1 - EXPORT ${PROJECT_NAME}-targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) - set(${PROJECT_NAME}_headers - "${PROJECT_SOURCE_DIR}/include/secp256k1.h" - "${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h" - ) - if(SECP256K1_ENABLE_MODULE_ECDH) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h") - endif() - if(SECP256K1_ENABLE_MODULE_RECOVERY) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h") - endif() - if(SECP256K1_ENABLE_MODULE_EXTRAKEYS) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h") - endif() - if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h") - endif() - if(SECP256K1_ENABLE_MODULE_MUSIG) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_musig.h") - endif() - if(SECP256K1_ENABLE_MODULE_ELLSWIFT) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ellswift.h") - endif() - install(FILES ${${PROJECT_NAME}_headers} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) - - install(EXPORT ${PROJECT_NAME}-targets - FILE ${PROJECT_NAME}-targets.cmake - NAMESPACE ${PROJECT_NAME}:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} - ) - - include(CMakePackageConfigHelpers) - configure_package_config_file( - ${PROJECT_SOURCE_DIR}/cmake/config.cmake.in - ${PROJECT_NAME}-config.cmake - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} - NO_SET_AND_CHECK_MACRO - ) - write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake - COMPATIBILITY SameMinorVersion - ) - - install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} - ) - - include(GeneratePkgConfigFile) - generate_pkg_config_file(${PROJECT_SOURCE_DIR}/libsecp256k1.pc.in) - install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc - DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig - ) -endif() diff --git a/external/secp256k1/src/asm/field_10x26_arm.s b/external/secp256k1/src/asm/field_10x26_arm.s deleted file mode 100644 index 664b921400..0000000000 --- a/external/secp256k1/src/asm/field_10x26_arm.s +++ /dev/null @@ -1,916 +0,0 @@ -@ vim: set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab syntax=armasm: -/*********************************************************************** - * Copyright (c) 2014 Wladimir J. van der Laan * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ -/* -ARM implementation of field_10x26 inner loops. - -Note: - -- To avoid unnecessary loads and make use of available registers, two - 'passes' have every time been interleaved, with the odd passes accumulating c' and d' - which will be added to c and d respectively in the even passes - -*/ - - .syntax unified - @ eabi attributes - see readelf -A - .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte - .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP - .text - - @ Field constants - .set field_R0, 0x3d10 - .set field_R1, 0x400 - .set field_not_M, 0xfc000000 @ ~M = ~0x3ffffff - - .align 2 - .global secp256k1_fe_mul_inner - .type secp256k1_fe_mul_inner, %function - .hidden secp256k1_fe_mul_inner - @ Arguments: - @ r0 r Restrict: can overlap with a, not with b - @ r1 a - @ r2 b - @ Stack (total 4+10*4 = 44) - @ sp + #0 saved 'r' pointer - @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 -secp256k1_fe_mul_inner: - stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} - sub sp, sp, #48 @ frame=44 + alignment - str r0, [sp, #0] @ save result address, we need it only at the end - - /****************************************** - * Main computation code. - ****************************************** - - Allocation: - r0,r14,r7,r8 scratch - r1 a (pointer) - r2 b (pointer) - r3:r4 c - r5:r6 d - r11:r12 c' - r9:r10 d' - - Note: do not write to r[] here, it may overlap with a[] - */ - - /* A - interleaved with B */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #9*4] @ b[9] - ldr r0, [r1, #1*4] @ a[1] - umull r5, r6, r7, r8 @ d = a[0] * b[9] - ldr r14, [r2, #8*4] @ b[8] - umull r9, r10, r0, r8 @ d' = a[1] * b[9] - ldr r7, [r1, #2*4] @ a[2] - umlal r5, r6, r0, r14 @ d += a[1] * b[8] - ldr r8, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r14 @ d' += a[2] * b[8] - ldr r0, [r1, #3*4] @ a[3] - umlal r5, r6, r7, r8 @ d += a[2] * b[7] - ldr r14, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r8 @ d' += a[3] * b[7] - ldr r7, [r1, #4*4] @ a[4] - umlal r5, r6, r0, r14 @ d += a[3] * b[6] - ldr r8, [r2, #5*4] @ b[5] - umlal r9, r10, r7, r14 @ d' += a[4] * b[6] - ldr r0, [r1, #5*4] @ a[5] - umlal r5, r6, r7, r8 @ d += a[4] * b[5] - ldr r14, [r2, #4*4] @ b[4] - umlal r9, r10, r0, r8 @ d' += a[5] * b[5] - ldr r7, [r1, #6*4] @ a[6] - umlal r5, r6, r0, r14 @ d += a[5] * b[4] - ldr r8, [r2, #3*4] @ b[3] - umlal r9, r10, r7, r14 @ d' += a[6] * b[4] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r8 @ d += a[6] * b[3] - ldr r14, [r2, #2*4] @ b[2] - umlal r9, r10, r0, r8 @ d' += a[7] * b[3] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r14 @ d += a[7] * b[2] - ldr r8, [r2, #1*4] @ b[1] - umlal r9, r10, r7, r14 @ d' += a[8] * b[2] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r8 @ d += a[8] * b[1] - ldr r14, [r2, #0*4] @ b[0] - umlal r9, r10, r0, r8 @ d' += a[9] * b[1] - ldr r7, [r1, #0*4] @ a[0] - umlal r5, r6, r0, r14 @ d += a[9] * b[0] - @ r7,r14 used in B - - bic r0, r5, field_not_M @ t9 = d & M - str r0, [sp, #4 + 4*9] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - /* B */ - umull r3, r4, r7, r14 @ c = a[0] * b[0] - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u0 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u0 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t0 = c & M - str r14, [sp, #4 + 0*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u0 * R1 - umlal r3, r4, r0, r14 - - /* C - interleaved with D */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #2*4] @ b[2] - ldr r14, [r2, #1*4] @ b[1] - umull r11, r12, r7, r8 @ c' = a[0] * b[2] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[1] * b[1] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[2] * b[0] - ldr r0, [r1, #3*4] @ a[3] - umlal r5, r6, r7, r14 @ d += a[2] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[3] * b[9] - ldr r7, [r1, #4*4] @ a[4] - umlal r5, r6, r0, r8 @ d += a[3] * b[8] - ldr r14, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r8 @ d' += a[4] * b[8] - ldr r0, [r1, #5*4] @ a[5] - umlal r5, r6, r7, r14 @ d += a[4] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r14 @ d' += a[5] * b[7] - ldr r7, [r1, #6*4] @ a[6] - umlal r5, r6, r0, r8 @ d += a[5] * b[6] - ldr r14, [r2, #5*4] @ b[5] - umlal r9, r10, r7, r8 @ d' += a[6] * b[6] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r14 @ d += a[6] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r9, r10, r0, r14 @ d' += a[7] * b[5] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r8 @ d += a[7] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r9, r10, r7, r8 @ d' += a[8] * b[4] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r9, r10, r0, r14 @ d' += a[9] * b[3] - umlal r5, r6, r0, r8 @ d += a[9] * b[2] - - bic r0, r5, field_not_M @ u1 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u1 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t1 = c & M - str r14, [sp, #4 + 1*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u1 * R1 - umlal r3, r4, r0, r14 - - /* D */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u2 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u2 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t2 = c & M - str r14, [sp, #4 + 2*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u2 * R1 - umlal r3, r4, r0, r14 - - /* E - interleaved with F */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #4*4] @ b[4] - umull r11, r12, r7, r8 @ c' = a[0] * b[4] - ldr r8, [r2, #3*4] @ b[3] - umlal r3, r4, r7, r8 @ c += a[0] * b[3] - ldr r7, [r1, #1*4] @ a[1] - umlal r11, r12, r7, r8 @ c' += a[1] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r3, r4, r7, r8 @ c += a[1] * b[2] - ldr r7, [r1, #2*4] @ a[2] - umlal r11, r12, r7, r8 @ c' += a[2] * b[2] - ldr r8, [r2, #1*4] @ b[1] - umlal r3, r4, r7, r8 @ c += a[2] * b[1] - ldr r7, [r1, #3*4] @ a[3] - umlal r11, r12, r7, r8 @ c' += a[3] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r3, r4, r7, r8 @ c += a[3] * b[0] - ldr r7, [r1, #4*4] @ a[4] - umlal r11, r12, r7, r8 @ c' += a[4] * b[0] - ldr r8, [r2, #9*4] @ b[9] - umlal r5, r6, r7, r8 @ d += a[4] * b[9] - ldr r7, [r1, #5*4] @ a[5] - umull r9, r10, r7, r8 @ d' = a[5] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umlal r5, r6, r7, r8 @ d += a[5] * b[8] - ldr r7, [r1, #6*4] @ a[6] - umlal r9, r10, r7, r8 @ d' += a[6] * b[8] - ldr r8, [r2, #7*4] @ b[7] - umlal r5, r6, r7, r8 @ d += a[6] * b[7] - ldr r7, [r1, #7*4] @ a[7] - umlal r9, r10, r7, r8 @ d' += a[7] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r5, r6, r7, r8 @ d += a[7] * b[6] - ldr r7, [r1, #8*4] @ a[8] - umlal r9, r10, r7, r8 @ d' += a[8] * b[6] - ldr r8, [r2, #5*4] @ b[5] - umlal r5, r6, r7, r8 @ d += a[8] * b[5] - ldr r7, [r1, #9*4] @ a[9] - umlal r9, r10, r7, r8 @ d' += a[9] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r5, r6, r7, r8 @ d += a[9] * b[4] - - bic r0, r5, field_not_M @ u3 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u3 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t3 = c & M - str r14, [sp, #4 + 3*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u3 * R1 - umlal r3, r4, r0, r14 - - /* F */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u4 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u4 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t4 = c & M - str r14, [sp, #4 + 4*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u4 * R1 - umlal r3, r4, r0, r14 - - /* G - interleaved with H */ - ldr r7, [r1, #0*4] @ a[0] - ldr r8, [r2, #6*4] @ b[6] - ldr r14, [r2, #5*4] @ b[5] - umull r11, r12, r7, r8 @ c' = a[0] * b[6] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r11, r12, r0, r14 @ c' += a[1] * b[5] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r11, r12, r7, r8 @ c' += a[2] * b[4] - ldr r0, [r1, #3*4] @ a[3] - umlal r3, r4, r7, r14 @ c += a[2] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r11, r12, r0, r14 @ c' += a[3] * b[3] - ldr r7, [r1, #4*4] @ a[4] - umlal r3, r4, r0, r8 @ c += a[3] * b[2] - ldr r14, [r2, #1*4] @ b[1] - umlal r11, r12, r7, r8 @ c' += a[4] * b[2] - ldr r0, [r1, #5*4] @ a[5] - umlal r3, r4, r7, r14 @ c += a[4] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[5] * b[1] - ldr r7, [r1, #6*4] @ a[6] - umlal r3, r4, r0, r8 @ c += a[5] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[6] * b[0] - ldr r0, [r1, #7*4] @ a[7] - umlal r5, r6, r7, r14 @ d += a[6] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[7] * b[9] - ldr r7, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r8 @ d += a[7] * b[8] - ldr r14, [r2, #7*4] @ b[7] - umlal r9, r10, r7, r8 @ d' += a[8] * b[8] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r9, r10, r0, r14 @ d' += a[9] * b[7] - umlal r5, r6, r0, r8 @ d += a[9] * b[6] - - bic r0, r5, field_not_M @ u5 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u5 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t5 = c & M - str r14, [sp, #4 + 5*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u5 * R1 - umlal r3, r4, r0, r14 - - /* H */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u6 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u6 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t6 = c & M - str r14, [sp, #4 + 6*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u6 * R1 - umlal r3, r4, r0, r14 - - /* I - interleaved with J */ - ldr r8, [r2, #8*4] @ b[8] - ldr r7, [r1, #0*4] @ a[0] - ldr r14, [r2, #7*4] @ b[7] - umull r11, r12, r7, r8 @ c' = a[0] * b[8] - ldr r0, [r1, #1*4] @ a[1] - umlal r3, r4, r7, r14 @ c += a[0] * b[7] - ldr r8, [r2, #6*4] @ b[6] - umlal r11, r12, r0, r14 @ c' += a[1] * b[7] - ldr r7, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r8 @ c += a[1] * b[6] - ldr r14, [r2, #5*4] @ b[5] - umlal r11, r12, r7, r8 @ c' += a[2] * b[6] - ldr r0, [r1, #3*4] @ a[3] - umlal r3, r4, r7, r14 @ c += a[2] * b[5] - ldr r8, [r2, #4*4] @ b[4] - umlal r11, r12, r0, r14 @ c' += a[3] * b[5] - ldr r7, [r1, #4*4] @ a[4] - umlal r3, r4, r0, r8 @ c += a[3] * b[4] - ldr r14, [r2, #3*4] @ b[3] - umlal r11, r12, r7, r8 @ c' += a[4] * b[4] - ldr r0, [r1, #5*4] @ a[5] - umlal r3, r4, r7, r14 @ c += a[4] * b[3] - ldr r8, [r2, #2*4] @ b[2] - umlal r11, r12, r0, r14 @ c' += a[5] * b[3] - ldr r7, [r1, #6*4] @ a[6] - umlal r3, r4, r0, r8 @ c += a[5] * b[2] - ldr r14, [r2, #1*4] @ b[1] - umlal r11, r12, r7, r8 @ c' += a[6] * b[2] - ldr r0, [r1, #7*4] @ a[7] - umlal r3, r4, r7, r14 @ c += a[6] * b[1] - ldr r8, [r2, #0*4] @ b[0] - umlal r11, r12, r0, r14 @ c' += a[7] * b[1] - ldr r7, [r1, #8*4] @ a[8] - umlal r3, r4, r0, r8 @ c += a[7] * b[0] - ldr r14, [r2, #9*4] @ b[9] - umlal r11, r12, r7, r8 @ c' += a[8] * b[0] - ldr r0, [r1, #9*4] @ a[9] - umlal r5, r6, r7, r14 @ d += a[8] * b[9] - ldr r8, [r2, #8*4] @ b[8] - umull r9, r10, r0, r14 @ d' = a[9] * b[9] - umlal r5, r6, r0, r8 @ d += a[9] * b[8] - - bic r0, r5, field_not_M @ u7 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u7 * R0 - umlal r3, r4, r0, r14 - - bic r14, r3, field_not_M @ t7 = c & M - str r14, [sp, #4 + 7*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u7 * R1 - umlal r3, r4, r0, r14 - - /* J */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u8 = d & M - str r0, [sp, #4 + 8*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u8 * R0 - umlal r3, r4, r0, r14 - - /****************************************** - * compute and write back result - ****************************************** - Allocation: - r0 r - r3:r4 c - r5:r6 d - r7 t0 - r8 t1 - r9 t2 - r11 u8 - r12 t9 - r1,r2,r10,r14 scratch - - Note: do not read from a[] after here, it may overlap with r[] - */ - ldr r0, [sp, #0] - add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 - ldmia r1, {r2,r7,r8,r9,r10,r11,r12} - add r1, r0, #3*4 - stmia r1, {r2,r7,r8,r9,r10} - - bic r2, r3, field_not_M @ r[8] = c & M - str r2, [r0, #8*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u8 * R1 - umlal r3, r4, r11, r14 - movw r14, field_R0 @ c += d * R0 - umlal r3, r4, r5, r14 - adds r3, r3, r12 @ c += t9 - adc r4, r4, #0 - - add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 - ldmia r1, {r7,r8,r9} - - ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) - str r2, [r0, #9*4] - mov r3, r3, lsr #22 @ c >>= 22 - orr r3, r3, r4, asl #10 - mov r4, r4, lsr #22 - movw r14, field_R1 << 4 @ c += d * (R1 << 4) - umlal r3, r4, r5, r14 - - movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) - umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) - adds r5, r5, r7 @ d.lo += t0 - mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) - adc r6, r6, 0 @ d.hi += carry - - bic r2, r5, field_not_M @ r[0] = d & M - str r2, [r0, #0*4] - - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) - umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) - adds r5, r5, r8 @ d.lo += t1 - adc r6, r6, #0 @ d.hi += carry - adds r5, r5, r1 @ d.lo += tmp.lo - mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) - adc r6, r6, r2 @ d.hi += carry + tmp.hi - - bic r2, r5, field_not_M @ r[1] = d & M - str r2, [r0, #1*4] - mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) - orr r5, r5, r6, asl #6 - - add r5, r5, r9 @ d += t2 - str r5, [r0, #2*4] @ r[2] = d - - add sp, sp, #48 - ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} - .size secp256k1_fe_mul_inner, .-secp256k1_fe_mul_inner - - .align 2 - .global secp256k1_fe_sqr_inner - .type secp256k1_fe_sqr_inner, %function - .hidden secp256k1_fe_sqr_inner - @ Arguments: - @ r0 r Can overlap with a - @ r1 a - @ Stack (total 4+10*4 = 44) - @ sp + #0 saved 'r' pointer - @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 -secp256k1_fe_sqr_inner: - stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} - sub sp, sp, #48 @ frame=44 + alignment - str r0, [sp, #0] @ save result address, we need it only at the end - /****************************************** - * Main computation code. - ****************************************** - - Allocation: - r0,r14,r2,r7,r8 scratch - r1 a (pointer) - r3:r4 c - r5:r6 d - r11:r12 c' - r9:r10 d' - - Note: do not write to r[] here, it may overlap with a[] - */ - /* A interleaved with B */ - ldr r0, [r1, #1*4] @ a[1]*2 - ldr r7, [r1, #0*4] @ a[0] - mov r0, r0, asl #1 - ldr r14, [r1, #9*4] @ a[9] - umull r3, r4, r7, r7 @ c = a[0] * a[0] - ldr r8, [r1, #8*4] @ a[8] - mov r7, r7, asl #1 - umull r5, r6, r7, r14 @ d = a[0]*2 * a[9] - ldr r7, [r1, #2*4] @ a[2]*2 - umull r9, r10, r0, r14 @ d' = a[1]*2 * a[9] - ldr r14, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r8 @ d += a[1]*2 * a[8] - mov r7, r7, asl #1 - ldr r0, [r1, #3*4] @ a[3]*2 - umlal r9, r10, r7, r8 @ d' += a[2]*2 * a[8] - ldr r8, [r1, #6*4] @ a[6] - umlal r5, r6, r7, r14 @ d += a[2]*2 * a[7] - mov r0, r0, asl #1 - ldr r7, [r1, #4*4] @ a[4]*2 - umlal r9, r10, r0, r14 @ d' += a[3]*2 * a[7] - ldr r14, [r1, #5*4] @ a[5] - mov r7, r7, asl #1 - umlal r5, r6, r0, r8 @ d += a[3]*2 * a[6] - umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[6] - umlal r5, r6, r7, r14 @ d += a[4]*2 * a[5] - umlal r9, r10, r14, r14 @ d' += a[5] * a[5] - - bic r0, r5, field_not_M @ t9 = d & M - str r0, [sp, #4 + 9*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - /* B */ - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u0 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u0 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t0 = c & M - str r14, [sp, #4 + 0*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u0 * R1 - umlal r3, r4, r0, r14 - - /* C interleaved with D */ - ldr r0, [r1, #0*4] @ a[0]*2 - ldr r14, [r1, #1*4] @ a[1] - mov r0, r0, asl #1 - ldr r8, [r1, #2*4] @ a[2] - umlal r3, r4, r0, r14 @ c += a[0]*2 * a[1] - mov r7, r8, asl #1 @ a[2]*2 - umull r11, r12, r14, r14 @ c' = a[1] * a[1] - ldr r14, [r1, #9*4] @ a[9] - umlal r11, r12, r0, r8 @ c' += a[0]*2 * a[2] - ldr r0, [r1, #3*4] @ a[3]*2 - ldr r8, [r1, #8*4] @ a[8] - umlal r5, r6, r7, r14 @ d += a[2]*2 * a[9] - mov r0, r0, asl #1 - ldr r7, [r1, #4*4] @ a[4]*2 - umull r9, r10, r0, r14 @ d' = a[3]*2 * a[9] - ldr r14, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r8 @ d += a[3]*2 * a[8] - mov r7, r7, asl #1 - ldr r0, [r1, #5*4] @ a[5]*2 - umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[8] - ldr r8, [r1, #6*4] @ a[6] - mov r0, r0, asl #1 - umlal r5, r6, r7, r14 @ d += a[4]*2 * a[7] - umlal r9, r10, r0, r14 @ d' += a[5]*2 * a[7] - umlal r5, r6, r0, r8 @ d += a[5]*2 * a[6] - umlal r9, r10, r8, r8 @ d' += a[6] * a[6] - - bic r0, r5, field_not_M @ u1 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u1 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t1 = c & M - str r14, [sp, #4 + 1*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u1 * R1 - umlal r3, r4, r0, r14 - - /* D */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u2 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u2 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t2 = c & M - str r14, [sp, #4 + 2*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u2 * R1 - umlal r3, r4, r0, r14 - - /* E interleaved with F */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - ldr r14, [r1, #2*4] @ a[2] - mov r7, r7, asl #1 - ldr r8, [r1, #3*4] @ a[3] - ldr r2, [r1, #4*4] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[3] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[4] - mov r2, r2, asl #1 @ a[4]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[3] - ldr r8, [r1, #9*4] @ a[9] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[2] - ldr r0, [r1, #5*4] @ a[5]*2 - umlal r11, r12, r14, r14 @ c' += a[2] * a[2] - ldr r14, [r1, #8*4] @ a[8] - mov r0, r0, asl #1 - umlal r5, r6, r2, r8 @ d += a[4]*2 * a[9] - ldr r7, [r1, #6*4] @ a[6]*2 - umull r9, r10, r0, r8 @ d' = a[5]*2 * a[9] - mov r7, r7, asl #1 - ldr r8, [r1, #7*4] @ a[7] - umlal r5, r6, r0, r14 @ d += a[5]*2 * a[8] - umlal r9, r10, r7, r14 @ d' += a[6]*2 * a[8] - umlal r5, r6, r7, r8 @ d += a[6]*2 * a[7] - umlal r9, r10, r8, r8 @ d' += a[7] * a[7] - - bic r0, r5, field_not_M @ u3 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u3 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t3 = c & M - str r14, [sp, #4 + 3*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u3 * R1 - umlal r3, r4, r0, r14 - - /* F */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u4 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u4 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t4 = c & M - str r14, [sp, #4 + 4*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u4 * R1 - umlal r3, r4, r0, r14 - - /* G interleaved with H */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - mov r7, r7, asl #1 - ldr r8, [r1, #5*4] @ a[5] - ldr r2, [r1, #6*4] @ a[6] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[5] - ldr r14, [r1, #4*4] @ a[4] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[6] - ldr r7, [r1, #2*4] @ a[2]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[5] - mov r7, r7, asl #1 - ldr r8, [r1, #3*4] @ a[3] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[4] - mov r0, r2, asl #1 @ a[6]*2 - umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[4] - ldr r14, [r1, #9*4] @ a[9] - umlal r3, r4, r7, r8 @ c += a[2]*2 * a[3] - ldr r7, [r1, #7*4] @ a[7]*2 - umlal r11, r12, r8, r8 @ c' += a[3] * a[3] - mov r7, r7, asl #1 - ldr r8, [r1, #8*4] @ a[8] - umlal r5, r6, r0, r14 @ d += a[6]*2 * a[9] - umull r9, r10, r7, r14 @ d' = a[7]*2 * a[9] - umlal r5, r6, r7, r8 @ d += a[7]*2 * a[8] - umlal r9, r10, r8, r8 @ d' += a[8] * a[8] - - bic r0, r5, field_not_M @ u5 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u5 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t5 = c & M - str r14, [sp, #4 + 5*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u5 * R1 - umlal r3, r4, r0, r14 - - /* H */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - adds r5, r5, r9 @ d += d' - adc r6, r6, r10 - - bic r0, r5, field_not_M @ u6 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u6 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t6 = c & M - str r14, [sp, #4 + 6*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u6 * R1 - umlal r3, r4, r0, r14 - - /* I interleaved with J */ - ldr r7, [r1, #0*4] @ a[0]*2 - ldr r0, [r1, #1*4] @ a[1]*2 - mov r7, r7, asl #1 - ldr r8, [r1, #7*4] @ a[7] - ldr r2, [r1, #8*4] @ a[8] - umlal r3, r4, r7, r8 @ c += a[0]*2 * a[7] - ldr r14, [r1, #6*4] @ a[6] - mov r0, r0, asl #1 - umull r11, r12, r7, r2 @ c' = a[0]*2 * a[8] - ldr r7, [r1, #2*4] @ a[2]*2 - umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[7] - ldr r8, [r1, #5*4] @ a[5] - umlal r3, r4, r0, r14 @ c += a[1]*2 * a[6] - ldr r0, [r1, #3*4] @ a[3]*2 - mov r7, r7, asl #1 - umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[6] - ldr r14, [r1, #4*4] @ a[4] - mov r0, r0, asl #1 - umlal r3, r4, r7, r8 @ c += a[2]*2 * a[5] - mov r2, r2, asl #1 @ a[8]*2 - umlal r11, r12, r0, r8 @ c' += a[3]*2 * a[5] - umlal r3, r4, r0, r14 @ c += a[3]*2 * a[4] - umlal r11, r12, r14, r14 @ c' += a[4] * a[4] - ldr r8, [r1, #9*4] @ a[9] - umlal r5, r6, r2, r8 @ d += a[8]*2 * a[9] - @ r8 will be used in J - - bic r0, r5, field_not_M @ u7 = d & M - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u7 * R0 - umlal r3, r4, r0, r14 - bic r14, r3, field_not_M @ t7 = c & M - str r14, [sp, #4 + 7*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u7 * R1 - umlal r3, r4, r0, r14 - - /* J */ - adds r3, r3, r11 @ c += c' - adc r4, r4, r12 - umlal r5, r6, r8, r8 @ d += a[9] * a[9] - - bic r0, r5, field_not_M @ u8 = d & M - str r0, [sp, #4 + 8*4] - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - movw r14, field_R0 @ c += u8 * R0 - umlal r3, r4, r0, r14 - - /****************************************** - * compute and write back result - ****************************************** - Allocation: - r0 r - r3:r4 c - r5:r6 d - r7 t0 - r8 t1 - r9 t2 - r11 u8 - r12 t9 - r1,r2,r10,r14 scratch - - Note: do not read from a[] after here, it may overlap with r[] - */ - ldr r0, [sp, #0] - add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 - ldmia r1, {r2,r7,r8,r9,r10,r11,r12} - add r1, r0, #3*4 - stmia r1, {r2,r7,r8,r9,r10} - - bic r2, r3, field_not_M @ r[8] = c & M - str r2, [r0, #8*4] - mov r3, r3, lsr #26 @ c >>= 26 - orr r3, r3, r4, asl #6 - mov r4, r4, lsr #26 - mov r14, field_R1 @ c += u8 * R1 - umlal r3, r4, r11, r14 - movw r14, field_R0 @ c += d * R0 - umlal r3, r4, r5, r14 - adds r3, r3, r12 @ c += t9 - adc r4, r4, #0 - - add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 - ldmia r1, {r7,r8,r9} - - ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) - str r2, [r0, #9*4] - mov r3, r3, lsr #22 @ c >>= 22 - orr r3, r3, r4, asl #10 - mov r4, r4, lsr #22 - movw r14, field_R1 << 4 @ c += d * (R1 << 4) - umlal r3, r4, r5, r14 - - movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) - umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) - adds r5, r5, r7 @ d.lo += t0 - mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) - adc r6, r6, 0 @ d.hi += carry - - bic r2, r5, field_not_M @ r[0] = d & M - str r2, [r0, #0*4] - - mov r5, r5, lsr #26 @ d >>= 26 - orr r5, r5, r6, asl #6 - mov r6, r6, lsr #26 - - movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) - umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) - adds r5, r5, r8 @ d.lo += t1 - adc r6, r6, #0 @ d.hi += carry - adds r5, r5, r1 @ d.lo += tmp.lo - mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) - adc r6, r6, r2 @ d.hi += carry + tmp.hi - - bic r2, r5, field_not_M @ r[1] = d & M - str r2, [r0, #1*4] - mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) - orr r5, r5, r6, asl #6 - - add r5, r5, r9 @ d += t2 - str r5, [r0, #2*4] @ r[2] = d - - add sp, sp, #48 - ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} - .size secp256k1_fe_sqr_inner, .-secp256k1_fe_sqr_inner - - .section .note.GNU-stack,"",%progbits diff --git a/external/secp256k1/src/assumptions.h b/external/secp256k1/src/assumptions.h deleted file mode 100644 index 7961005350..0000000000 --- a/external/secp256k1/src/assumptions.h +++ /dev/null @@ -1,87 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ASSUMPTIONS_H -#define SECP256K1_ASSUMPTIONS_H - -#include - -#include "util.h" -#if defined(SECP256K1_INT128_NATIVE) -#include "int128_native.h" -#endif - -/* This library, like most software, relies on a number of compiler implementation defined (but not undefined) - behaviours. Although the behaviours we require are essentially universal we test them specifically here to - reduce the odds of experiencing an unwelcome surprise. -*/ - -#if defined(__has_attribute) -# if __has_attribute(__unavailable__) -__attribute__((__unavailable__("Don't call this function. It only exists because STATIC_ASSERT cannot be used outside a function."))) -# endif -#endif -static void secp256k1_assumption_checker(void) { - /* Bytes are 8 bits. */ - STATIC_ASSERT(CHAR_BIT == 8); - - /* No integer promotion for uint32_t. This ensures that we can multiply uintXX_t values where XX >= 32 - without signed overflow, which would be undefined behaviour. */ - STATIC_ASSERT(UINT_MAX <= UINT32_MAX); - - /* Conversions from unsigned to signed outside of the bounds of the signed type are - implementation-defined. Verify that they function as reinterpreting the lower - bits of the input in two's complement notation. Do this for conversions: - - from uint(N)_t to int(N)_t with negative result - - from uint(2N)_t to int(N)_t with negative result - - from int(2N)_t to int(N)_t with negative result - - from int(2N)_t to int(N)_t with positive result */ - - /* To int8_t. */ - STATIC_ASSERT(((int8_t)(uint8_t)0xAB == (int8_t)-(int8_t)0x55)); - STATIC_ASSERT((int8_t)(uint16_t)0xABCD == (int8_t)-(int8_t)0x33); - STATIC_ASSERT((int8_t)(int16_t)(uint16_t)0xCDEF == (int8_t)(uint8_t)0xEF); - STATIC_ASSERT((int8_t)(int16_t)(uint16_t)0x9234 == (int8_t)(uint8_t)0x34); - - /* To int16_t. */ - STATIC_ASSERT((int16_t)(uint16_t)0xBCDE == (int16_t)-(int16_t)0x4322); - STATIC_ASSERT((int16_t)(uint32_t)0xA1B2C3D4 == (int16_t)-(int16_t)0x3C2C); - STATIC_ASSERT((int16_t)(int32_t)(uint32_t)0xC1D2E3F4 == (int16_t)(uint16_t)0xE3F4); - STATIC_ASSERT((int16_t)(int32_t)(uint32_t)0x92345678 == (int16_t)(uint16_t)0x5678); - - /* To int32_t. */ - STATIC_ASSERT((int32_t)(uint32_t)0xB2C3D4E5 == (int32_t)-(int32_t)0x4D3C2B1B); - STATIC_ASSERT((int32_t)(uint64_t)0xA123B456C789D012ULL == (int32_t)-(int32_t)0x38762FEE); - STATIC_ASSERT((int32_t)(int64_t)(uint64_t)0xC1D2E3F4A5B6C7D8ULL == (int32_t)(uint32_t)0xA5B6C7D8); - STATIC_ASSERT((int32_t)(int64_t)(uint64_t)0xABCDEF0123456789ULL == (int32_t)(uint32_t)0x23456789); - - /* To int64_t. */ - STATIC_ASSERT((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL); -#if defined(SECP256K1_INT128_NATIVE) - STATIC_ASSERT((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL); - STATIC_ASSERT(((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL); - STATIC_ASSERT(((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL); - - /* To int128_t. */ - STATIC_ASSERT((int128_t)(((uint128_t)0xB1234567C8901234ULL << 64) + 0xD5678901E2345678ULL) == (int128_t)(-(int128_t)0x8E1648B3F50E80DCULL * 0x8E1648B3F50E80DDULL + 0x5EA688D5482F9464ULL)); -#endif - - /* Right shift on negative signed values is implementation defined. Verify that it - acts as a right shift in two's complement with sign extension (i.e duplicating - the top bit into newly added bits). */ - STATIC_ASSERT((((int8_t)0xE8) >> 2) == (int8_t)(uint8_t)0xFA); - STATIC_ASSERT((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A); - STATIC_ASSERT((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48); - STATIC_ASSERT((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL); -#if defined(SECP256K1_INT128_NATIVE) - STATIC_ASSERT((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)); -#endif - - /* This function is not supposed to be called. */ - VERIFY_CHECK(0); -} - -#endif /* SECP256K1_ASSUMPTIONS_H */ diff --git a/external/secp256k1/src/bench.c b/external/secp256k1/src/bench.c deleted file mode 100644 index 1127df67ae..0000000000 --- a/external/secp256k1/src/bench.c +++ /dev/null @@ -1,279 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#include -#include - -#include "../include/secp256k1.h" -#include "util.h" -#include "bench.h" - -static void help(int default_iters) { - printf("Benchmarks the following algorithms:\n"); - printf(" - ECDSA signing/verification\n"); - -#ifdef ENABLE_MODULE_ECDH - printf(" - ECDH key exchange (optional module)\n"); -#endif - -#ifdef ENABLE_MODULE_RECOVERY - printf(" - Public key recovery (optional module)\n"); -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG - printf(" - Schnorr signatures (optional module)\n"); -#endif - - printf("\n"); - printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); - printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); - printf("\n"); - printf("Usage: ./bench [args]\n"); - printf("By default, all benchmarks will be run.\n"); - printf("args:\n"); - printf(" help : display this help and exit\n"); - printf(" ecdsa : all ECDSA algorithms--sign, verify, recovery (if enabled)\n"); - printf(" ecdsa_sign : ECDSA siging algorithm\n"); - printf(" ecdsa_verify : ECDSA verification algorithm\n"); - printf(" ec : all EC public key algorithms (keygen)\n"); - printf(" ec_keygen : EC public key generation\n"); - -#ifdef ENABLE_MODULE_RECOVERY - printf(" ecdsa_recover : ECDSA public key recovery algorithm\n"); -#endif - -#ifdef ENABLE_MODULE_ECDH - printf(" ecdh : ECDH key exchange algorithm\n"); -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG - printf(" schnorrsig : all Schnorr signature algorithms (sign, verify)\n"); - printf(" schnorrsig_sign : Schnorr sigining algorithm\n"); - printf(" schnorrsig_verify : Schnorr verification algorithm\n"); -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT - printf(" ellswift : all ElligatorSwift benchmarks (encode, decode, keygen, ecdh)\n"); - printf(" ellswift_encode : ElligatorSwift encoding\n"); - printf(" ellswift_decode : ElligatorSwift decoding\n"); - printf(" ellswift_keygen : ElligatorSwift key generation\n"); - printf(" ellswift_ecdh : ECDH on ElligatorSwift keys\n"); -#endif - - printf("\n"); -} - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - unsigned char key[32]; - unsigned char sig[72]; - size_t siglen; - unsigned char pubkey[33]; - size_t pubkeylen; -} bench_data; - -static void bench_verify(void* arg, int iters) { - int i; - bench_data* data = (bench_data*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); - CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0)); - data->sig[data->siglen - 1] ^= (i & 0xFF); - data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); - data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - } -} - -static void bench_sign_setup(void* arg) { - int i; - bench_data *data = (bench_data*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = i + 1; - } - for (i = 0; i < 32; i++) { - data->key[i] = i + 65; - } -} - -static void bench_sign_run(void* arg, int iters) { - int i; - bench_data *data = (bench_data*)arg; - - unsigned char sig[74]; - for (i = 0; i < iters; i++) { - size_t siglen = 74; - int j; - secp256k1_ecdsa_signature signature; - CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); - CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature)); - for (j = 0; j < 32; j++) { - data->msg[j] = sig[j]; - data->key[j] = sig[j + 32]; - } - } -} - -static void bench_keygen_setup(void* arg) { - int i; - bench_data *data = (bench_data*)arg; - - for (i = 0; i < 32; i++) { - data->key[i] = i + 65; - } -} - -static void bench_keygen_run(void *arg, int iters) { - int i; - bench_data *data = (bench_data*)arg; - - for (i = 0; i < iters; i++) { - unsigned char pub33[33]; - size_t len = 33; - secp256k1_pubkey pubkey; - CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->key)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pub33, &len, &pubkey, SECP256K1_EC_COMPRESSED)); - memcpy(data->key, pub33 + 1, 32); - } -} - - -#ifdef ENABLE_MODULE_ECDH -# include "modules/ecdh/bench_impl.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "modules/recovery/bench_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG -# include "modules/schnorrsig/bench_impl.h" -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT -# include "modules/ellswift/bench_impl.h" -#endif - -int main(int argc, char** argv) { - int i; - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; - bench_data data; - - int d = argc == 1; - int default_iters = 20000; - int iters = get_iters(default_iters); - - /* Check for invalid user arguments */ - char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover", - "ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec", - "keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode", - "ellswift_decode", "ellswift_keygen", "ellswift_ecdh"}; - size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]); - int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size); - - if (argc > 1) { - if (have_flag(argc, argv, "-h") - || have_flag(argc, argv, "--help") - || have_flag(argc, argv, "help")) { - help(default_iters); - return 0; - } else if (invalid_args) { - fprintf(stderr, "./bench: unrecognized argument.\n\n"); - help(default_iters); - return 1; - } - } - -/* Check if the user tries to benchmark optional module without building it */ -#ifndef ENABLE_MODULE_ECDH - if (have_flag(argc, argv, "ecdh")) { - fprintf(stderr, "./bench: ECDH module not enabled.\n"); - fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n"); - return 1; - } -#endif - -#ifndef ENABLE_MODULE_RECOVERY - if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) { - fprintf(stderr, "./bench: Public key recovery module not enabled.\n"); - fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n"); - return 1; - } -#endif - -#ifndef ENABLE_MODULE_SCHNORRSIG - if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) { - fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n"); - fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n"); - return 1; - } -#endif - -#ifndef ENABLE_MODULE_ELLSWIFT - if (have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ellswift_encode") || have_flag(argc, argv, "ellswift_decode") || - have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") || - have_flag(argc, argv, "ellswift_ecdh")) { - fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n"); - fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n"); - return 1; - } -#endif - - /* ECDSA benchmark */ - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - - for (i = 0; i < 32; i++) { - data.msg[i] = 1 + i; - } - for (i = 0; i < 32; i++) { - data.key[i] = 33 + i; - } - data.siglen = 72; - CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); - CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); - CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); - data.pubkeylen = 33; - CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - - print_output_table_header_row(); - if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "ecdsa_verify")) run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters); - - if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "ecdsa_sign")) run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "ec") || have_flag(argc, argv, "keygen") || have_flag(argc, argv, "ec_keygen")) run_benchmark("ec_keygen", bench_keygen_run, bench_keygen_setup, NULL, &data, 10, iters); - - secp256k1_context_destroy(data.ctx); - -#ifdef ENABLE_MODULE_ECDH - /* ECDH benchmarks */ - run_ecdh_bench(iters, argc, argv); -#endif - -#ifdef ENABLE_MODULE_RECOVERY - /* ECDSA recovery benchmarks */ - run_recovery_bench(iters, argc, argv); -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG - /* Schnorr signature benchmarks */ - run_schnorrsig_bench(iters, argc, argv); -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT - /* ElligatorSwift benchmarks */ - run_ellswift_bench(iters, argc, argv); -#endif - - return 0; -} diff --git a/external/secp256k1/src/bench.h b/external/secp256k1/src/bench.h deleted file mode 100644 index 1564b1a176..0000000000 --- a/external/secp256k1/src/bench.h +++ /dev/null @@ -1,188 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_BENCH_H -#define SECP256K1_BENCH_H - -#include -#include -#include -#include - -#if (defined(_MSC_VER) && _MSC_VER >= 1900) -# include -#else -# include -#endif - -static int64_t gettime_i64(void) { -#if (defined(_MSC_VER) && _MSC_VER >= 1900) - /* C11 way to get wallclock time */ - struct timespec tv; - if (!timespec_get(&tv, TIME_UTC)) { - fputs("timespec_get failed!", stderr); - exit(1); - } - return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL; -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL; -#endif -} - -#define FP_EXP (6) -#define FP_MULT (1000000LL) - -/* Format fixed point number. */ -static void print_number(const int64_t x) { - int64_t x_abs, y; - int c, i, rounding, g; /* g = integer part size, c = fractional part size */ - size_t ptr; - char buffer[30]; - - if (x == INT64_MIN) { - /* Prevent UB. */ - printf("ERR"); - return; - } - x_abs = x < 0 ? -x : x; - - /* Determine how many decimals we want to show (more than FP_EXP makes no - * sense). */ - y = x_abs; - c = 0; - while (y > 0LL && y < 100LL * FP_MULT && c < FP_EXP) { - y *= 10LL; - c++; - } - - /* Round to 'c' decimals. */ - y = x_abs; - rounding = 0; - for (i = c; i < FP_EXP; ++i) { - rounding = (y % 10) >= 5; - y /= 10; - } - y += rounding; - - /* Format and print the number. */ - ptr = sizeof(buffer) - 1; - buffer[ptr] = 0; - g = 0; - if (c != 0) { /* non zero fractional part */ - for (i = 0; i < c; ++i) { - buffer[--ptr] = '0' + (y % 10); - y /= 10; - } - } else if (c == 0) { /* fractional part is 0 */ - buffer[--ptr] = '0'; - } - buffer[--ptr] = '.'; - do { - buffer[--ptr] = '0' + (y % 10); - y /= 10; - g++; - } while (y != 0); - if (x < 0) { - buffer[--ptr] = '-'; - g++; - } - printf("%5.*s", g, &buffer[ptr]); /* Prints integer part */ - printf("%-*s", FP_EXP, &buffer[ptr + g]); /* Prints fractional part */ -} - -static void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void*), void (*teardown)(void*, int), void* data, int count, int iter) { - int i; - int64_t min = INT64_MAX; - int64_t sum = 0; - int64_t max = 0; - for (i = 0; i < count; i++) { - int64_t begin, total; - if (setup != NULL) { - setup(data); - } - begin = gettime_i64(); - benchmark(data, iter); - total = gettime_i64() - begin; - if (teardown != NULL) { - teardown(data, iter); - } - if (total < min) { - min = total; - } - if (total > max) { - max = total; - } - sum += total; - } - /* ',' is used as a column delimiter */ - printf("%-30s, ", name); - print_number(min * FP_MULT / iter); - printf(" , "); - print_number(((sum * FP_MULT) / count) / iter); - printf(" , "); - print_number(max * FP_MULT / iter); - printf("\n"); -} - -static int have_flag(int argc, char** argv, char *flag) { - char** argm = argv + argc; - argv++; - while (argv != argm) { - if (strcmp(*argv, flag) == 0) { - return 1; - } - argv++; - } - return 0; -} - -/* takes an array containing the arguments that the user is allowed to enter on the command-line - returns: - - 1 if the user entered an invalid argument - - 0 if all the user entered arguments are valid */ -static int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) { - size_t i; - int found_valid; - char** argm = argv + argc; - argv++; - - while (argv != argm) { - found_valid = 0; - for (i = 0; i < n; i++) { - if (strcmp(*argv, valid_args[i]) == 0) { - found_valid = 1; /* user entered a valid arg from the list */ - break; - } - } - if (found_valid == 0) { - return 1; /* invalid arg found */ - } - argv++; - } - return 0; -} - -static int get_iters(int default_iters) { - char* env = getenv("SECP256K1_BENCH_ITERS"); - if (env) { - return strtol(env, NULL, 0); - } else { - return default_iters; - } -} - -static void print_output_table_header_row(void) { - char* bench_str = "Benchmark"; /* left justified */ - char* min_str = " Min(us) "; /* center alignment */ - char* avg_str = " Avg(us) "; - char* max_str = " Max(us) "; - printf("%-30s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str); - printf("\n"); -} - -#endif /* SECP256K1_BENCH_H */ diff --git a/external/secp256k1/src/bench_ecmult.c b/external/secp256k1/src/bench_ecmult.c deleted file mode 100644 index 3974af75f4..0000000000 --- a/external/secp256k1/src/bench_ecmult.c +++ /dev/null @@ -1,367 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2017 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ -#include - -#include "secp256k1.c" -#include "../include/secp256k1.h" - -#include "util.h" -#include "hash_impl.h" -#include "field_impl.h" -#include "group_impl.h" -#include "scalar_impl.h" -#include "ecmult_impl.h" -#include "bench.h" - -#define POINTS 32768 - -static void help(char **argv) { - printf("Benchmark EC multiplication algorithms\n"); - printf("\n"); - printf("Usage: %s \n", argv[0]); - printf("The output shows the number of multiplied and summed points right after the\n"); - printf("function name. The letter 'g' indicates that one of the points is the generator.\n"); - printf("The benchmarks are divided by the number of points.\n"); - printf("\n"); - printf("default (ecmult_multi): picks pippenger_wnaf or strauss_wnaf depending on the\n"); - printf(" batch size\n"); - printf("pippenger_wnaf: for all batch sizes\n"); - printf("strauss_wnaf: for all batch sizes\n"); - printf("simple: multiply and sum each point individually\n"); -} - -typedef struct { - /* Setup once in advance */ - secp256k1_context* ctx; - secp256k1_scratch_space* scratch; - secp256k1_scalar* scalars; - secp256k1_ge* pubkeys; - secp256k1_gej* pubkeys_gej; - secp256k1_scalar* seckeys; - secp256k1_gej* expected_output; - secp256k1_ecmult_multi_func ecmult_multi; - - /* Changes per benchmark */ - size_t count; - int includes_g; - - /* Changes per benchmark iteration, used to pick different scalars and pubkeys - * in each run. */ - size_t offset1; - size_t offset2; - - /* Benchmark output. */ - secp256k1_gej* output; -} bench_data; - -/* Hashes x into [0, POINTS) twice and store the result in offset1 and offset2. */ -static void hash_into_offset(bench_data* data, size_t x) { - data->offset1 = (x * 0x537b7f6f + 0x8f66a481) % POINTS; - data->offset2 = (x * 0x7f6f537b + 0x6a1a8f49) % POINTS; -} - -/* Check correctness of the benchmark by computing - * sum(outputs) ?= (sum(scalars_gen) + sum(seckeys)*sum(scalars))*G */ -static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset, size_t* scalar_offset, size_t* scalar_gen_offset, int iters) { - int i; - secp256k1_gej sum_output, tmp; - secp256k1_scalar sum_scalars; - - secp256k1_gej_set_infinity(&sum_output); - secp256k1_scalar_set_int(&sum_scalars, 0); - for (i = 0; i < iters; ++i) { - secp256k1_gej_add_var(&sum_output, &sum_output, &data->output[i], NULL); - if (scalar_gen_offset != NULL) { - secp256k1_scalar_add(&sum_scalars, &sum_scalars, &data->scalars[(*scalar_gen_offset+i) % POINTS]); - } - if (seckey_offset != NULL) { - secp256k1_scalar s = data->seckeys[(*seckey_offset+i) % POINTS]; - secp256k1_scalar_mul(&s, &s, &data->scalars[(*scalar_offset+i) % POINTS]); - secp256k1_scalar_add(&sum_scalars, &sum_scalars, &s); - } - } - secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars); - CHECK(secp256k1_gej_eq_var(&tmp, &sum_output)); -} - -static void bench_ecmult_setup(void* arg) { - bench_data* data = (bench_data*)arg; - /* Re-randomize offset to ensure that we're using different scalars and - * group elements in each run. */ - hash_into_offset(data, data->offset1); -} - -static void bench_ecmult_gen(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - int i; - - for (i = 0; i < iters; ++i) { - secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &data->output[i], &data->scalars[(data->offset1+i) % POINTS]); - } -} - -static void bench_ecmult_gen_teardown(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - bench_ecmult_teardown_helper(data, NULL, NULL, &data->offset1, iters); -} - -static void bench_ecmult_const(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - int i; - - for (i = 0; i < iters; ++i) { - secp256k1_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS]); - } -} - -static void bench_ecmult_const_teardown(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - bench_ecmult_teardown_helper(data, &data->offset1, &data->offset2, NULL, iters); -} - -static void bench_ecmult_1p(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - int i; - - for (i = 0; i < iters; ++i) { - secp256k1_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL); - } -} - -static void bench_ecmult_1p_teardown(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - bench_ecmult_teardown_helper(data, &data->offset1, &data->offset2, NULL, iters); -} - -static void bench_ecmult_0p_g(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - int i; - - for (i = 0; i < iters; ++i) { - secp256k1_ecmult(&data->output[i], NULL, &secp256k1_scalar_zero, &data->scalars[(data->offset1+i) % POINTS]); - } -} - -static void bench_ecmult_0p_g_teardown(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - bench_ecmult_teardown_helper(data, NULL, NULL, &data->offset1, iters); -} - -static void bench_ecmult_1p_g(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - int i; - - for (i = 0; i < iters/2; ++i) { - secp256k1_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]); - } -} - -static void bench_ecmult_1p_g_teardown(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - bench_ecmult_teardown_helper(data, &data->offset1, &data->offset2, &data->offset1, iters/2); -} - -static void run_ecmult_bench(bench_data* data, int iters) { - char str[32]; - sprintf(str, "ecmult_gen"); - run_benchmark(str, bench_ecmult_gen, bench_ecmult_setup, bench_ecmult_gen_teardown, data, 10, iters); - sprintf(str, "ecmult_const"); - run_benchmark(str, bench_ecmult_const, bench_ecmult_setup, bench_ecmult_const_teardown, data, 10, iters); - /* ecmult with non generator point */ - sprintf(str, "ecmult_1p"); - run_benchmark(str, bench_ecmult_1p, bench_ecmult_setup, bench_ecmult_1p_teardown, data, 10, iters); - /* ecmult with generator point */ - sprintf(str, "ecmult_0p_g"); - run_benchmark(str, bench_ecmult_0p_g, bench_ecmult_setup, bench_ecmult_0p_g_teardown, data, 10, iters); - /* ecmult with generator and non-generator point. The reported time is per point. */ - sprintf(str, "ecmult_1p_g"); - run_benchmark(str, bench_ecmult_1p_g, bench_ecmult_setup, bench_ecmult_1p_g_teardown, data, 10, 2*iters); -} - -static int bench_ecmult_multi_callback(secp256k1_scalar* sc, secp256k1_ge* ge, size_t idx, void* arg) { - bench_data* data = (bench_data*)arg; - if (data->includes_g) ++idx; - if (idx == 0) { - *sc = data->scalars[data->offset1]; - *ge = secp256k1_ge_const_g; - } else { - *sc = data->scalars[(data->offset1 + idx) % POINTS]; - *ge = data->pubkeys[(data->offset2 + idx - 1) % POINTS]; - } - return 1; -} - -static void bench_ecmult_multi(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - - int includes_g = data->includes_g; - int iter; - int count = data->count; - iters = iters / data->count; - - for (iter = 0; iter < iters; ++iter) { - data->ecmult_multi(&data->ctx->error_callback, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_ecmult_multi_callback, arg, count - includes_g); - data->offset1 = (data->offset1 + count) % POINTS; - data->offset2 = (data->offset2 + count - 1) % POINTS; - } -} - -static void bench_ecmult_multi_setup(void* arg) { - bench_data* data = (bench_data*)arg; - hash_into_offset(data, data->count); -} - -static void bench_ecmult_multi_teardown(void* arg, int iters) { - bench_data* data = (bench_data*)arg; - int iter; - iters = iters / data->count; - /* Verify the results in teardown, to avoid doing comparisons while benchmarking. */ - for (iter = 0; iter < iters; ++iter) { - secp256k1_gej tmp; - secp256k1_gej_add_var(&tmp, &data->output[iter], &data->expected_output[iter], NULL); - CHECK(secp256k1_gej_is_infinity(&tmp)); - } -} - -static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) { - secp256k1_sha256 sha256; - unsigned char c[10] = {'e', 'c', 'm', 'u', 'l', 't', 0, 0, 0, 0}; - unsigned char buf[32]; - int overflow = 0; - c[6] = num; - c[7] = num >> 8; - c[8] = num >> 16; - c[9] = num >> 24; - secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, c, sizeof(c)); - secp256k1_sha256_finalize(&sha256, buf); - secp256k1_scalar_set_b32(scalar, buf, &overflow); - CHECK(!overflow); -} - -static void run_ecmult_multi_bench(bench_data* data, size_t count, int includes_g, int num_iters) { - char str[32]; - size_t iters = 1 + num_iters / count; - size_t iter; - - data->count = count; - data->includes_g = includes_g; - - /* Compute (the negation of) the expected results directly. */ - hash_into_offset(data, data->count); - for (iter = 0; iter < iters; ++iter) { - secp256k1_scalar tmp; - secp256k1_scalar total = data->scalars[(data->offset1++) % POINTS]; - size_t i = 0; - for (i = 0; i + 1 < count; ++i) { - secp256k1_scalar_mul(&tmp, &data->seckeys[(data->offset2++) % POINTS], &data->scalars[(data->offset1++) % POINTS]); - secp256k1_scalar_add(&total, &total, &tmp); - } - secp256k1_scalar_negate(&total, &total); - secp256k1_ecmult(&data->expected_output[iter], NULL, &secp256k1_scalar_zero, &total); - } - - /* Run the benchmark. */ - if (includes_g) { - sprintf(str, "ecmult_multi_%ip_g", (int)count - 1); - } else { - sprintf(str, "ecmult_multi_%ip", (int)count); - } - run_benchmark(str, bench_ecmult_multi, bench_ecmult_multi_setup, bench_ecmult_multi_teardown, data, 10, count * iters); -} - -int main(int argc, char **argv) { - bench_data data; - int i, p; - size_t scratch_size; - - int iters = get_iters(10000); - - data.ecmult_multi = secp256k1_ecmult_multi_var; - - if (argc > 1) { - if(have_flag(argc, argv, "-h") - || have_flag(argc, argv, "--help") - || have_flag(argc, argv, "help")) { - help(argv); - return 0; - } else if(have_flag(argc, argv, "pippenger_wnaf")) { - printf("Using pippenger_wnaf:\n"); - data.ecmult_multi = secp256k1_ecmult_pippenger_batch_single; - } else if(have_flag(argc, argv, "strauss_wnaf")) { - printf("Using strauss_wnaf:\n"); - data.ecmult_multi = secp256k1_ecmult_strauss_batch_single; - } else if(have_flag(argc, argv, "simple")) { - printf("Using simple algorithm:\n"); - } else { - fprintf(stderr, "%s: unrecognized argument '%s'.\n\n", argv[0], argv[1]); - help(argv); - return 1; - } - } - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; - if (!have_flag(argc, argv, "simple")) { - data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size); - } else { - data.scratch = NULL; - } - - /* Allocate stuff */ - data.scalars = malloc(sizeof(secp256k1_scalar) * POINTS); - data.seckeys = malloc(sizeof(secp256k1_scalar) * POINTS); - data.pubkeys = malloc(sizeof(secp256k1_ge) * POINTS); - data.pubkeys_gej = malloc(sizeof(secp256k1_gej) * POINTS); - data.expected_output = malloc(sizeof(secp256k1_gej) * (iters + 1)); - data.output = malloc(sizeof(secp256k1_gej) * (iters + 1)); - - /* Generate a set of scalars, and private/public keypairs. */ - secp256k1_gej_set_ge(&data.pubkeys_gej[0], &secp256k1_ge_const_g); - secp256k1_scalar_set_int(&data.seckeys[0], 1); - for (i = 0; i < POINTS; ++i) { - generate_scalar(i, &data.scalars[i]); - if (i) { - secp256k1_gej_double_var(&data.pubkeys_gej[i], &data.pubkeys_gej[i - 1], NULL); - secp256k1_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]); - } - } - secp256k1_ge_set_all_gej_var(data.pubkeys, data.pubkeys_gej, POINTS); - - - print_output_table_header_row(); - /* Initialize offset1 and offset2 */ - hash_into_offset(&data, 0); - run_ecmult_bench(&data, iters); - - for (i = 1; i <= 8; ++i) { - run_ecmult_multi_bench(&data, i, 1, iters); - } - - /* This is disabled with low count of iterations because the loop runs 77 times even with iters=1 - * and the higher it goes the longer the computation takes(more points) - * So we don't run this benchmark with low iterations to prevent slow down */ - if (iters > 2) { - for (p = 0; p <= 11; ++p) { - for (i = 9; i <= 16; ++i) { - run_ecmult_multi_bench(&data, i << p, 1, iters); - } - } - } - - if (data.scratch != NULL) { - secp256k1_scratch_space_destroy(data.ctx, data.scratch); - } - secp256k1_context_destroy(data.ctx); - free(data.scalars); - free(data.pubkeys); - free(data.pubkeys_gej); - free(data.seckeys); - free(data.output); - free(data.expected_output); - - return(0); -} diff --git a/external/secp256k1/src/bench_internal.c b/external/secp256k1/src/bench_internal.c deleted file mode 100644 index a700684922..0000000000 --- a/external/secp256k1/src/bench_internal.c +++ /dev/null @@ -1,436 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ -#include - -#include "secp256k1.c" -#include "../include/secp256k1.h" - -#include "assumptions.h" -#include "util.h" -#include "hash_impl.h" -#include "field_impl.h" -#include "group_impl.h" -#include "scalar_impl.h" -#include "ecmult_impl.h" -#include "bench.h" - -static void help(int default_iters) { - printf("Benchmarks various internal routines.\n"); - printf("\n"); - printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); - printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); - printf("\n"); - printf("Usage: ./bench_internal [args]\n"); - printf("By default, all benchmarks will be run.\n"); - printf("args:\n"); - printf(" help : display this help and exit\n"); - printf(" scalar : all scalar operations (add, half, inverse, mul, negate, split)\n"); - printf(" field : all field operations (half, inverse, issquare, mul, normalize, sqr, sqrt)\n"); - printf(" group : all group operations (add, double, to_affine)\n"); - printf(" ecmult : all point multiplication operations (ecmult_wnaf) \n"); - printf(" hash : all hash algorithms (hmac, rng6979, sha256)\n"); - printf(" context : all context object operations (context_create)\n"); - printf("\n"); -} - -typedef struct { - secp256k1_scalar scalar[2]; - secp256k1_fe fe[4]; - secp256k1_ge ge[2]; - secp256k1_gej gej[2]; - unsigned char data[64]; - int wnaf[256]; -} bench_inv; - -static void bench_setup(void* arg) { - bench_inv *data = (bench_inv*)arg; - - static const unsigned char init[4][32] = { - /* Initializer for scalar[0], fe[0], first half of data, the X coordinate of ge[0], - and the (implied affine) X coordinate of gej[0]. */ - { - 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, - 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, - 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, - 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83 - }, - /* Initializer for scalar[1], fe[1], first half of data, the X coordinate of ge[1], - and the (implied affine) X coordinate of gej[1]. */ - { - 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83, - 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5, - 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9, - 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3 - }, - /* Initializer for fe[2] and the Z coordinate of gej[0]. */ - { - 0x3d, 0x2d, 0xef, 0xf4, 0x25, 0x98, 0x4f, 0x5d, - 0xe2, 0xca, 0x5f, 0x41, 0x3f, 0x3f, 0xce, 0x44, - 0xaa, 0x2c, 0x53, 0x8a, 0xc6, 0x59, 0x1f, 0x38, - 0x38, 0x23, 0xe4, 0x11, 0x27, 0xc6, 0xa0, 0xe7 - }, - /* Initializer for fe[3] and the Z coordinate of gej[1]. */ - { - 0xbd, 0x21, 0xa5, 0xe1, 0x13, 0x50, 0x73, 0x2e, - 0x52, 0x98, 0xc8, 0x9e, 0xab, 0x00, 0xa2, 0x68, - 0x43, 0xf5, 0xd7, 0x49, 0x80, 0x72, 0xa7, 0xf3, - 0xd7, 0x60, 0xe6, 0xab, 0x90, 0x92, 0xdf, 0xc5 - } - }; - - secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL); - secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL); - secp256k1_fe_set_b32_limit(&data->fe[0], init[0]); - secp256k1_fe_set_b32_limit(&data->fe[1], init[1]); - secp256k1_fe_set_b32_limit(&data->fe[2], init[2]); - secp256k1_fe_set_b32_limit(&data->fe[3], init[3]); - CHECK(secp256k1_ge_set_xo_var(&data->ge[0], &data->fe[0], 0)); - CHECK(secp256k1_ge_set_xo_var(&data->ge[1], &data->fe[1], 1)); - secp256k1_gej_set_ge(&data->gej[0], &data->ge[0]); - secp256k1_gej_rescale(&data->gej[0], &data->fe[2]); - secp256k1_gej_set_ge(&data->gej[1], &data->ge[1]); - secp256k1_gej_rescale(&data->gej[1], &data->fe[3]); - memcpy(data->data, init[0], 32); - memcpy(data->data + 32, init[1], 32); -} - -static void bench_scalar_add(void* arg, int iters) { - int i, j = 0; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); - } - CHECK(j <= iters); -} - -static void bench_scalar_negate(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_scalar_negate(&data->scalar[0], &data->scalar[0]); - } -} - -static void bench_scalar_half(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - secp256k1_scalar s = data->scalar[0]; - - for (i = 0; i < iters; i++) { - secp256k1_scalar_half(&s, &s); - } - - data->scalar[0] = s; -} - -static void bench_scalar_mul(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_scalar_mul(&data->scalar[0], &data->scalar[0], &data->scalar[1]); - } -} - -static void bench_scalar_split(void* arg, int iters) { - int i, j = 0; - bench_inv *data = (bench_inv*)arg; - secp256k1_scalar tmp; - - for (i = 0; i < iters; i++) { - secp256k1_scalar_split_lambda(&tmp, &data->scalar[1], &data->scalar[0]); - j += secp256k1_scalar_add(&data->scalar[0], &tmp, &data->scalar[1]); - } - CHECK(j <= iters); -} - -static void bench_scalar_inverse(void* arg, int iters) { - int i, j = 0; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_scalar_inverse(&data->scalar[0], &data->scalar[0]); - j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); - } - CHECK(j <= iters); -} - -static void bench_scalar_inverse_var(void* arg, int iters) { - int i, j = 0; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_scalar_inverse_var(&data->scalar[0], &data->scalar[0]); - j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); - } - CHECK(j <= iters); -} - -static void bench_field_half(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_fe_half(&data->fe[0]); - } -} - -static void bench_field_normalize(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_fe_normalize(&data->fe[0]); - } -} - -static void bench_field_normalize_weak(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_fe_normalize_weak(&data->fe[0]); - } -} - -static void bench_field_mul(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_fe_mul(&data->fe[0], &data->fe[0], &data->fe[1]); - } -} - -static void bench_field_sqr(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_fe_sqr(&data->fe[0], &data->fe[0]); - } -} - -static void bench_field_inverse(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_fe_inv(&data->fe[0], &data->fe[0]); - secp256k1_fe_add(&data->fe[0], &data->fe[1]); - } -} - -static void bench_field_inverse_var(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_fe_inv_var(&data->fe[0], &data->fe[0]); - secp256k1_fe_add(&data->fe[0], &data->fe[1]); - } -} - -static void bench_field_sqrt(void* arg, int iters) { - int i, j = 0; - bench_inv *data = (bench_inv*)arg; - secp256k1_fe t; - - for (i = 0; i < iters; i++) { - t = data->fe[0]; - j += secp256k1_fe_sqrt(&data->fe[0], &t); - secp256k1_fe_add(&data->fe[0], &data->fe[1]); - } - CHECK(j <= iters); -} - -static void bench_field_is_square_var(void* arg, int iters) { - int i, j = 0; - bench_inv *data = (bench_inv*)arg; - secp256k1_fe t = data->fe[0]; - - for (i = 0; i < iters; i++) { - j += secp256k1_fe_is_square_var(&t); - secp256k1_fe_add(&t, &data->fe[1]); - secp256k1_fe_normalize_var(&t); - } - CHECK(j <= iters); -} - -static void bench_group_double_var(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_gej_double_var(&data->gej[0], &data->gej[0], NULL); - } -} - -static void bench_group_add_var(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_gej_add_var(&data->gej[0], &data->gej[0], &data->gej[1], NULL); - } -} - -static void bench_group_add_affine(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_gej_add_ge(&data->gej[0], &data->gej[0], &data->ge[1]); - } -} - -static void bench_group_add_affine_var(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_gej_add_ge_var(&data->gej[0], &data->gej[0], &data->ge[1], NULL); - } -} - -static void bench_group_add_zinv_var(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - secp256k1_gej_add_zinv_var(&data->gej[0], &data->gej[0], &data->ge[1], &data->gej[0].y); - } -} - -static void bench_group_to_affine_var(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; ++i) { - secp256k1_ge_set_gej_var(&data->ge[1], &data->gej[0]); - /* Use the output affine X/Y coordinates to vary the input X/Y/Z coordinates. - Note that the resulting coordinates will generally not correspond to a point - on the curve, but this is not a problem for the code being benchmarked here. - Adding and normalizing have less overhead than EC operations (which could - guarantee the point remains on the curve). */ - secp256k1_fe_add(&data->gej[0].x, &data->ge[1].y); - secp256k1_fe_add(&data->gej[0].y, &data->fe[2]); - secp256k1_fe_add(&data->gej[0].z, &data->ge[1].x); - secp256k1_fe_normalize_var(&data->gej[0].x); - secp256k1_fe_normalize_var(&data->gej[0].y); - secp256k1_fe_normalize_var(&data->gej[0].z); - } -} - -static void bench_ecmult_wnaf(void* arg, int iters) { - int i, bits = 0, overflow = 0; - bench_inv *data = (bench_inv*)arg; - - for (i = 0; i < iters; i++) { - bits += secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar[0], WINDOW_A); - overflow += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); - } - CHECK(overflow >= 0); - CHECK(bits <= 256*iters); -} - -static void bench_sha256(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - secp256k1_sha256 sha; - - for (i = 0; i < iters; i++) { - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, data->data, 32); - secp256k1_sha256_finalize(&sha, data->data); - } -} - -static void bench_hmac_sha256(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - secp256k1_hmac_sha256 hmac; - - for (i = 0; i < iters; i++) { - secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); - secp256k1_hmac_sha256_write(&hmac, data->data, 32); - secp256k1_hmac_sha256_finalize(&hmac, data->data); - } -} - -static void bench_rfc6979_hmac_sha256(void* arg, int iters) { - int i; - bench_inv *data = (bench_inv*)arg; - secp256k1_rfc6979_hmac_sha256 rng; - - for (i = 0; i < iters; i++) { - secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); - secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); - } -} - -static void bench_context(void* arg, int iters) { - int i; - (void)arg; - for (i = 0; i < iters; i++) { - secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_NONE)); - } -} - -int main(int argc, char **argv) { - bench_inv data; - int default_iters = 20000; - int iters = get_iters(default_iters); - int d = argc == 1; /* default */ - - if (argc > 1) { - if (have_flag(argc, argv, "-h") - || have_flag(argc, argv, "--help") - || have_flag(argc, argv, "help")) { - help(default_iters); - return 0; - } - } - - print_output_table_header_row(); - - if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "half")) run_benchmark("scalar_half", bench_scalar_half, bench_setup, NULL, &data, 10, iters*100); - if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, iters*100); - if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, iters*100); - if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, iters*10); - if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, iters); - - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "half")) run_benchmark("field_half", bench_field_half, bench_setup, NULL, &data, 10, iters*100); - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, iters*100); - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, iters*100); - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, iters*10); - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, iters*10); - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "issquare")) run_benchmark("field_is_square_var", bench_field_is_square_var, bench_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, iters); - - if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, iters*10); - if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, iters*10); - if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, iters*10); - if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, iters*10); - if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_zinv_var", bench_group_add_zinv_var, bench_setup, NULL, &data, 10, iters*10); - if (d || have_flag(argc, argv, "group") || have_flag(argc, argv, "to_affine")) run_benchmark("group_to_affine_var", bench_group_to_affine_var, bench_setup, NULL, &data, 10, iters); - - if (d || have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, iters); - - if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, iters); - - if (d || have_flag(argc, argv, "context")) run_benchmark("context_create", bench_context, bench_setup, NULL, &data, 10, iters); - - return 0; -} diff --git a/external/secp256k1/src/checkmem.h b/external/secp256k1/src/checkmem.h deleted file mode 100644 index 7e333ce5f3..0000000000 --- a/external/secp256k1/src/checkmem.h +++ /dev/null @@ -1,102 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2022 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -/* The code here is inspired by Kris Kwiatkowski's approach in - * https://github.com/kriskwiatkowski/pqc/blob/main/src/common/ct_check.h - * to provide a general interface for memory-checking mechanisms, primarily - * for constant-time checking. - */ - -/* These macros are defined by this header file: - * - * - SECP256K1_CHECKMEM_ENABLED: - * - 1 if memory-checking integration is available, 0 otherwise. - * This is just a compile-time macro. Use the next macro to check it is actually - * available at runtime. - * - SECP256K1_CHECKMEM_RUNNING(): - * - Acts like a function call, returning 1 if memory checking is available - * at runtime. - * - SECP256K1_CHECKMEM_CHECK(p, len): - * - Assert or otherwise fail in case the len-byte memory block pointed to by p is - * not considered entirely defined. - * - SECP256K1_CHECKMEM_CHECK_VERIFY(p, len): - * - Like SECP256K1_CHECKMEM_CHECK, but only works in VERIFY mode. - * - SECP256K1_CHECKMEM_UNDEFINE(p, len): - * - marks the len-byte memory block pointed to by p as undefined data (secret data, - * in the context of constant-time checking). - * - SECP256K1_CHECKMEM_DEFINE(p, len): - * - marks the len-byte memory pointed to by p as defined data (public data, in the - * context of constant-time checking). - * - SECP256K1_CHECKMEM_MSAN_DEFINE(p, len): - * - Like SECP256K1_CHECKMEM_DEFINE, but applies only to memory_sanitizer. - * - */ - -#ifndef SECP256K1_CHECKMEM_H -#define SECP256K1_CHECKMEM_H - -/* Define a statement-like macro that ignores the arguments. */ -#define SECP256K1_CHECKMEM_NOOP(p, len) do { (void)(p); (void)(len); } while(0) - -/* If compiling under msan, map the SECP256K1_CHECKMEM_* functionality to msan. - * Choose this preferentially, even when VALGRIND is defined, as msan-compiled - * binaries can't be run under valgrind anyway. */ -#if defined(__has_feature) -# if __has_feature(memory_sanitizer) -# include -# define SECP256K1_CHECKMEM_ENABLED 1 -# define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len)) -# define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len)) -# define SECP256K1_CHECKMEM_MSAN_DEFINE(p, len) __msan_unpoison((p), (len)) -# define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len)) -# define SECP256K1_CHECKMEM_RUNNING() (1) -# endif -#endif - -#if !defined SECP256K1_CHECKMEM_MSAN_DEFINE -# define SECP256K1_CHECKMEM_MSAN_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) -#endif - -/* If valgrind integration is desired (through the VALGRIND define), implement the - * SECP256K1_CHECKMEM_* macros using valgrind. */ -#if !defined SECP256K1_CHECKMEM_ENABLED -# if defined VALGRIND -# include -# if defined(__clang__) && defined(__APPLE__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wreserved-identifier" -# endif -# include -# if defined(__clang__) && defined(__APPLE__) -# pragma clang diagnostic pop -# endif -# define SECP256K1_CHECKMEM_ENABLED 1 -# define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len)) -# define SECP256K1_CHECKMEM_DEFINE(p, len) VALGRIND_MAKE_MEM_DEFINED((p), (len)) -# define SECP256K1_CHECKMEM_CHECK(p, len) VALGRIND_CHECK_MEM_IS_DEFINED((p), (len)) - /* VALGRIND_MAKE_MEM_DEFINED returns 0 iff not running on memcheck. - * This is more precise than the RUNNING_ON_VALGRIND macro, which - * checks for valgrind in general instead of memcheck specifically. */ -# define SECP256K1_CHECKMEM_RUNNING() (VALGRIND_MAKE_MEM_DEFINED(NULL, 0) != 0) -# endif -#endif - -/* As a fall-back, map these macros to dummy statements. */ -#if !defined SECP256K1_CHECKMEM_ENABLED -# define SECP256K1_CHECKMEM_ENABLED 0 -# define SECP256K1_CHECKMEM_UNDEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) -# define SECP256K1_CHECKMEM_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) -# define SECP256K1_CHECKMEM_CHECK(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) -# define SECP256K1_CHECKMEM_RUNNING() (0) -#endif - -#if defined VERIFY -#define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_CHECK((p), (len)) -#else -#define SECP256K1_CHECKMEM_CHECK_VERIFY(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) -#endif - -#endif /* SECP256K1_CHECKMEM_H */ diff --git a/external/secp256k1/src/ctime_tests.c b/external/secp256k1/src/ctime_tests.c deleted file mode 100644 index bbde863d96..0000000000 --- a/external/secp256k1/src/ctime_tests.c +++ /dev/null @@ -1,266 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#include -#include - -#include "../include/secp256k1.h" -#include "assumptions.h" -#include "checkmem.h" - -#if !SECP256K1_CHECKMEM_ENABLED -# error "This tool cannot be compiled without memory-checking interface (valgrind or msan)" -#endif - -#ifdef ENABLE_MODULE_ECDH -# include "../include/secp256k1_ecdh.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "../include/secp256k1_recovery.h" -#endif - -#ifdef ENABLE_MODULE_EXTRAKEYS -# include "../include/secp256k1_extrakeys.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG -#include "../include/secp256k1_schnorrsig.h" -#endif - -#ifdef ENABLE_MODULE_MUSIG -#include "../include/secp256k1_musig.h" -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT -#include "../include/secp256k1_ellswift.h" -#endif - -static void run_tests(secp256k1_context *ctx, unsigned char *key); - -int main(void) { - secp256k1_context* ctx; - unsigned char key[32]; - int ret, i; - - if (!SECP256K1_CHECKMEM_RUNNING()) { - fprintf(stderr, "This test can only usefully be run inside valgrind because it was not compiled under msan.\n"); - fprintf(stderr, "Usage: libtool --mode=execute valgrind ./ctime_tests\n"); - return 1; - } - ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY); - /** In theory, testing with a single secret input should be sufficient: - * If control flow depended on secrets the tool would generate an error. - */ - for (i = 0; i < 32; i++) { - key[i] = i + 65; - } - - run_tests(ctx, key); - - /* Test context randomisation. Do this last because it leaves the context - * tainted. */ - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_context_randomize(ctx, key); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret); - - secp256k1_context_destroy(ctx); - return 0; -} - -static void run_tests(secp256k1_context *ctx, unsigned char *key) { - secp256k1_ecdsa_signature signature; - secp256k1_pubkey pubkey; - size_t siglen = 74; - size_t outputlen = 33; - int i; - int ret; - unsigned char msg[32]; - unsigned char sig[74]; - unsigned char spubkey[33]; -#ifdef ENABLE_MODULE_RECOVERY - secp256k1_ecdsa_recoverable_signature recoverable_signature; - int recid; -#endif -#ifdef ENABLE_MODULE_EXTRAKEYS - secp256k1_keypair keypair; -#endif -#ifdef ENABLE_MODULE_ELLSWIFT - unsigned char ellswift[64]; - static const unsigned char prefix[64] = {'t', 'e', 's', 't'}; -#endif - - for (i = 0; i < 32; i++) { - msg[i] = i + 1; - } - - /* Test keygen. */ - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_ec_pubkey_create(ctx, &pubkey, key); - SECP256K1_CHECKMEM_DEFINE(&pubkey, sizeof(secp256k1_pubkey)); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret); - CHECK(secp256k1_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - - /* Test signing. */ - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_ecdsa_sign(ctx, &signature, msg, key, NULL, NULL); - SECP256K1_CHECKMEM_DEFINE(&signature, sizeof(secp256k1_ecdsa_signature)); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature)); - -#ifdef ENABLE_MODULE_ECDH - /* Test ECDH. */ - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_ecdh(ctx, msg, &pubkey, key, NULL, NULL); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); -#endif - -#ifdef ENABLE_MODULE_RECOVERY - /* Test signing a recoverable signature. */ - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_ecdsa_sign_recoverable(ctx, &recoverable_signature, msg, key, NULL, NULL); - SECP256K1_CHECKMEM_DEFINE(&recoverable_signature, sizeof(recoverable_signature)); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recoverable_signature)); - CHECK(recid >= 0 && recid <= 3); -#endif - - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_ec_seckey_verify(ctx, key); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_ec_seckey_negate(ctx, key); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - SECP256K1_CHECKMEM_UNDEFINE(msg, 32); - ret = secp256k1_ec_seckey_tweak_add(ctx, key, msg); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - SECP256K1_CHECKMEM_UNDEFINE(msg, 32); - ret = secp256k1_ec_seckey_tweak_mul(ctx, key, msg); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - /* Test keypair_create and keypair_xonly_tweak_add. */ -#ifdef ENABLE_MODULE_EXTRAKEYS - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_keypair_create(ctx, &keypair, key); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - /* The tweak is not treated as a secret in keypair_tweak_add */ - SECP256K1_CHECKMEM_DEFINE(msg, 32); - ret = secp256k1_keypair_xonly_tweak_add(ctx, &keypair, msg); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - SECP256K1_CHECKMEM_UNDEFINE(&keypair, sizeof(keypair)); - ret = secp256k1_keypair_sec(ctx, key, &keypair); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_keypair_create(ctx, &keypair, key); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - ret = secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); -#endif - -#ifdef ENABLE_MODULE_MUSIG - { - secp256k1_pubkey pk; - const secp256k1_pubkey *pk_ptr[1]; - secp256k1_xonly_pubkey agg_pk; - unsigned char session_secrand[32]; - uint64_t nonrepeating_cnt = 0; - secp256k1_musig_secnonce secnonce; - secp256k1_musig_pubnonce pubnonce; - const secp256k1_musig_pubnonce *pubnonce_ptr[1]; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_keyagg_cache cache; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - unsigned char extra_input[32]; - - pk_ptr[0] = &pk; - pubnonce_ptr[0] = &pubnonce; - SECP256K1_CHECKMEM_DEFINE(key, 32); - memcpy(session_secrand, key, sizeof(session_secrand)); - session_secrand[0] = session_secrand[0] + 1; - memcpy(extra_input, key, sizeof(extra_input)); - extra_input[0] = extra_input[0] + 2; - - CHECK(secp256k1_keypair_create(ctx, &keypair, key)); - CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair)); - CHECK(secp256k1_musig_pubkey_agg(ctx, &agg_pk, &cache, pk_ptr, 1)); - - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - SECP256K1_CHECKMEM_UNDEFINE(session_secrand, sizeof(session_secrand)); - SECP256K1_CHECKMEM_UNDEFINE(extra_input, sizeof(extra_input)); - ret = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_secrand, key, &pk, msg, &cache, extra_input); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - ret = secp256k1_musig_nonce_gen_counter(ctx, &secnonce, &pubnonce, nonrepeating_cnt, &keypair, msg, &cache, extra_input); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - CHECK(secp256k1_musig_nonce_agg(ctx, &aggnonce, pubnonce_ptr, 1)); - /* Make sure that previous tests don't undefine msg. It's not used as a secret here. */ - SECP256K1_CHECKMEM_DEFINE(msg, sizeof(msg)); - CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache) == 1); - - ret = secp256k1_keypair_create(ctx, &keypair, key); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - ret = secp256k1_musig_partial_sign(ctx, &partial_sig, &secnonce, &keypair, &cache, &session); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - } -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_ellswift_create(ctx, ellswift, key, NULL); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = secp256k1_ellswift_create(ctx, ellswift, key, ellswift); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - for (i = 0; i < 2; i++) { - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - SECP256K1_CHECKMEM_DEFINE(&ellswift, sizeof(ellswift)); - ret = secp256k1_ellswift_xdh(ctx, msg, ellswift, ellswift, key, i, secp256k1_ellswift_xdh_hash_function_bip324, NULL); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - SECP256K1_CHECKMEM_DEFINE(&ellswift, sizeof(ellswift)); - ret = secp256k1_ellswift_xdh(ctx, msg, ellswift, ellswift, key, i, secp256k1_ellswift_xdh_hash_function_prefix, (void *)prefix); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - } - -#endif -} diff --git a/external/secp256k1/src/ecdsa.h b/external/secp256k1/src/ecdsa.h deleted file mode 100644 index 4441b08398..0000000000 --- a/external/secp256k1/src/ecdsa.h +++ /dev/null @@ -1,21 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECDSA_H -#define SECP256K1_ECDSA_H - -#include - -#include "scalar.h" -#include "group.h" -#include "ecmult.h" - -static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); -static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); -static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); -static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); - -#endif /* SECP256K1_ECDSA_H */ diff --git a/external/secp256k1/src/ecdsa_impl.h b/external/secp256k1/src/ecdsa_impl.h deleted file mode 100644 index ce36e85e6a..0000000000 --- a/external/secp256k1/src/ecdsa_impl.h +++ /dev/null @@ -1,304 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - - -#ifndef SECP256K1_ECDSA_IMPL_H -#define SECP256K1_ECDSA_IMPL_H - -#include "scalar.h" -#include "field.h" -#include "group.h" -#include "ecmult.h" -#include "ecmult_gen.h" -#include "ecdsa.h" - -/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1 - * $ sage -c 'load("secp256k1_params.sage"); print(hex(N))' - * 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 - */ -static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, - 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL -); - -/** Difference between field and order, values 'p' and 'n' values defined in - * "Standards for Efficient Cryptography" (SEC2) 2.7.1. - * $ sage -c 'load("secp256k1_params.sage"); print(hex(P-N))' - * 0x14551231950b75fc4402da1722fc9baee - */ -static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( - 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL -); - -static int secp256k1_der_read_len(size_t *len, const unsigned char **sigp, const unsigned char *sigend) { - size_t lenleft; - unsigned char b1; - VERIFY_CHECK(len != NULL); - *len = 0; - if (*sigp >= sigend) { - return 0; - } - b1 = *((*sigp)++); - if (b1 == 0xFF) { - /* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */ - return 0; - } - if ((b1 & 0x80) == 0) { - /* X.690-0207 8.1.3.4 short form length octets */ - *len = b1; - return 1; - } - if (b1 == 0x80) { - /* Indefinite length is not allowed in DER. */ - return 0; - } - /* X.690-207 8.1.3.5 long form length octets */ - lenleft = b1 & 0x7F; /* lenleft is at least 1 */ - if (lenleft > (size_t)(sigend - *sigp)) { - return 0; - } - if (**sigp == 0) { - /* Not the shortest possible length encoding. */ - return 0; - } - if (lenleft > sizeof(size_t)) { - /* The resulting length would exceed the range of a size_t, so - * it is certainly longer than the passed array size. */ - return 0; - } - while (lenleft > 0) { - *len = (*len << 8) | **sigp; - (*sigp)++; - lenleft--; - } - if (*len > (size_t)(sigend - *sigp)) { - /* Result exceeds the length of the passed array. - (Checking this is the responsibility of the caller but it - can't hurt do it here, too.) */ - return 0; - } - if (*len < 128) { - /* Not the shortest possible length encoding. */ - return 0; - } - return 1; -} - -static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) { - int overflow = 0; - unsigned char ra[32] = {0}; - size_t rlen; - - if (*sig == sigend || **sig != 0x02) { - /* Not a primitive integer (X.690-0207 8.3.1). */ - return 0; - } - (*sig)++; - if (secp256k1_der_read_len(&rlen, sig, sigend) == 0) { - return 0; - } - if (rlen == 0 || rlen > (size_t)(sigend - *sig)) { - /* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */ - return 0; - } - if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) { - /* Excessive 0x00 padding. */ - return 0; - } - if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) { - /* Excessive 0xFF padding. */ - return 0; - } - if ((**sig & 0x80) == 0x80) { - /* Negative. */ - overflow = 1; - } - /* There is at most one leading zero byte: - * if there were two leading zero bytes, we would have failed and returned 0 - * because of excessive 0x00 padding already. */ - if (rlen > 0 && **sig == 0) { - /* Skip leading zero byte */ - rlen--; - (*sig)++; - } - if (rlen > 32) { - overflow = 1; - } - if (!overflow) { - if (rlen) memcpy(ra + 32 - rlen, *sig, rlen); - secp256k1_scalar_set_b32(r, ra, &overflow); - } - if (overflow) { - secp256k1_scalar_set_int(r, 0); - } - (*sig) += rlen; - return 1; -} - -static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) { - const unsigned char *sigend = sig + size; - size_t rlen; - if (sig == sigend || *(sig++) != 0x30) { - /* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */ - return 0; - } - if (secp256k1_der_read_len(&rlen, &sig, sigend) == 0) { - return 0; - } - if (rlen != (size_t)(sigend - sig)) { - /* Tuple exceeds bounds or garage after tuple. */ - return 0; - } - - if (!secp256k1_der_parse_integer(rr, &sig, sigend)) { - return 0; - } - if (!secp256k1_der_parse_integer(rs, &sig, sigend)) { - return 0; - } - - if (sig != sigend) { - /* Trailing garbage inside tuple. */ - return 0; - } - - return 1; -} - -static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) { - unsigned char r[33] = {0}, s[33] = {0}; - unsigned char *rp = r, *sp = s; - size_t lenR = 33, lenS = 33; - secp256k1_scalar_get_b32(&r[1], ar); - secp256k1_scalar_get_b32(&s[1], as); - while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } - while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } - if (*size < 6+lenS+lenR) { - *size = 6 + lenS + lenR; - return 0; - } - *size = 6 + lenS + lenR; - sig[0] = 0x30; - sig[1] = 4 + lenS + lenR; - sig[2] = 0x02; - sig[3] = lenR; - memcpy(sig+4, rp, lenR); - sig[4+lenR] = 0x02; - sig[5+lenR] = lenS; - memcpy(sig+lenR+6, sp, lenS); - return 1; -} - -static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { - unsigned char c[32]; - secp256k1_scalar sn, u1, u2; -#if !defined(EXHAUSTIVE_TEST_ORDER) - secp256k1_fe xr; -#endif - secp256k1_gej pubkeyj; - secp256k1_gej pr; - - if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { - return 0; - } - - secp256k1_scalar_inverse_var(&sn, sigs); - secp256k1_scalar_mul(&u1, &sn, message); - secp256k1_scalar_mul(&u2, &sn, sigr); - secp256k1_gej_set_ge(&pubkeyj, pubkey); - secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1); - if (secp256k1_gej_is_infinity(&pr)) { - return 0; - } - -#if defined(EXHAUSTIVE_TEST_ORDER) -{ - secp256k1_scalar computed_r; - secp256k1_ge pr_ge; - secp256k1_ge_set_gej(&pr_ge, &pr); - secp256k1_fe_normalize(&pr_ge.x); - - secp256k1_fe_get_b32(c, &pr_ge.x); - secp256k1_scalar_set_b32(&computed_r, c, NULL); - return secp256k1_scalar_eq(sigr, &computed_r); -} -#else - secp256k1_scalar_get_b32(c, sigr); - /* we can ignore the fe_set_b32_limit return value, because we know the input is in range */ - (void)secp256k1_fe_set_b32_limit(&xr, c); - - /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n) - * in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p), - * compute the remainder modulo n, and compare it to xr. However: - * - * xr == X(pr) mod n - * <=> exists h. (xr + h * n < p && xr + h * n == X(pr)) - * [Since 2 * n > p, h can only be 0 or 1] - * <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr)) - * [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p] - * <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p) - * [Multiplying both sides of the equations by pr.z^2 mod p] - * <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x) - * - * Thus, we can avoid the inversion, but we have to check both cases separately. - * secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. - */ - if (secp256k1_gej_eq_x_var(&xr, &pr)) { - /* xr * pr.z^2 mod p == pr.x, so the signature is valid. */ - return 1; - } - if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) { - /* xr + n >= p, so we can skip testing the second case. */ - return 0; - } - secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe); - if (secp256k1_gej_eq_x_var(&xr, &pr)) { - /* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */ - return 1; - } - return 0; -#endif -} - -static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { - unsigned char b[32]; - secp256k1_gej rp; - secp256k1_ge r; - secp256k1_scalar n; - int overflow = 0; - int high; - - secp256k1_ecmult_gen(ctx, &rp, nonce); - secp256k1_ge_set_gej(&r, &rp); - secp256k1_fe_normalize(&r.x); - secp256k1_fe_normalize(&r.y); - secp256k1_fe_get_b32(b, &r.x); - secp256k1_scalar_set_b32(sigr, b, &overflow); - if (recid) { - /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log - * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. - */ - *recid = (overflow << 1) | secp256k1_fe_is_odd(&r.y); - } - secp256k1_scalar_mul(&n, sigr, seckey); - secp256k1_scalar_add(&n, &n, message); - secp256k1_scalar_inverse(sigs, nonce); - secp256k1_scalar_mul(sigs, sigs, &n); - secp256k1_scalar_clear(&n); - secp256k1_gej_clear(&rp); - secp256k1_ge_clear(&r); - high = secp256k1_scalar_is_high(sigs); - secp256k1_scalar_cond_negate(sigs, high); - if (recid) { - *recid ^= high; - } - /* P.x = order is on the curve, so technically sig->r could end up being zero, which would be an invalid signature. - * This is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. - */ - return (int)(!secp256k1_scalar_is_zero(sigr)) & (int)(!secp256k1_scalar_is_zero(sigs)); -} - -#endif /* SECP256K1_ECDSA_IMPL_H */ diff --git a/external/secp256k1/src/eckey.h b/external/secp256k1/src/eckey.h deleted file mode 100644 index d54d44c997..0000000000 --- a/external/secp256k1/src/eckey.h +++ /dev/null @@ -1,25 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECKEY_H -#define SECP256K1_ECKEY_H - -#include - -#include "group.h" -#include "scalar.h" -#include "ecmult.h" -#include "ecmult_gen.h" - -static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); - -static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); -static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak); - -#endif /* SECP256K1_ECKEY_H */ diff --git a/external/secp256k1/src/eckey_impl.h b/external/secp256k1/src/eckey_impl.h deleted file mode 100644 index 121966f8b5..0000000000 --- a/external/secp256k1/src/eckey_impl.h +++ /dev/null @@ -1,92 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECKEY_IMPL_H -#define SECP256K1_ECKEY_IMPL_H - -#include "eckey.h" - -#include "scalar.h" -#include "field.h" -#include "group.h" -#include "ecmult_gen.h" - -static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { - if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { - secp256k1_fe x; - return secp256k1_fe_set_b32_limit(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD); - } else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { - secp256k1_fe x, y; - if (!secp256k1_fe_set_b32_limit(&x, pub+1) || !secp256k1_fe_set_b32_limit(&y, pub+33)) { - return 0; - } - secp256k1_ge_set_xy(elem, &x, &y); - if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && - secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { - return 0; - } - return secp256k1_ge_is_valid_var(elem); - } else { - return 0; - } -} - -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { - if (secp256k1_ge_is_infinity(elem)) { - return 0; - } - secp256k1_fe_normalize_var(&elem->x); - secp256k1_fe_normalize_var(&elem->y); - secp256k1_fe_get_b32(&pub[1], &elem->x); - if (compressed) { - *size = 33; - pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; - } else { - *size = 65; - pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; - secp256k1_fe_get_b32(&pub[33], &elem->y); - } - return 1; -} - -static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { - secp256k1_scalar_add(key, key, tweak); - return !secp256k1_scalar_is_zero(key); -} - -static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak) { - secp256k1_gej pt; - secp256k1_gej_set_ge(&pt, key); - secp256k1_ecmult(&pt, &pt, &secp256k1_scalar_one, tweak); - - if (secp256k1_gej_is_infinity(&pt)) { - return 0; - } - secp256k1_ge_set_gej(key, &pt); - return 1; -} - -static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) { - int ret; - ret = !secp256k1_scalar_is_zero(tweak); - - secp256k1_scalar_mul(key, key, tweak); - return ret; -} - -static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_scalar *tweak) { - secp256k1_gej pt; - if (secp256k1_scalar_is_zero(tweak)) { - return 0; - } - - secp256k1_gej_set_ge(&pt, key); - secp256k1_ecmult(&pt, &pt, tweak, &secp256k1_scalar_zero); - secp256k1_ge_set_gej(key, &pt); - return 1; -} - -#endif /* SECP256K1_ECKEY_IMPL_H */ diff --git a/external/secp256k1/src/ecmult.h b/external/secp256k1/src/ecmult.h deleted file mode 100644 index 326a5eeb43..0000000000 --- a/external/secp256k1/src/ecmult.h +++ /dev/null @@ -1,61 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECMULT_H -#define SECP256K1_ECMULT_H - -#include "group.h" -#include "scalar.h" -#include "scratch.h" - -#ifndef ECMULT_WINDOW_SIZE -# define ECMULT_WINDOW_SIZE 15 -# ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_MSG("ECMULT_WINDOW_SIZE undefined, assuming default value") -# endif -#endif - -#ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_DEF(ECMULT_WINDOW_SIZE) -#endif - -/* No one will ever need more than a window size of 24. The code might - * be correct for larger values of ECMULT_WINDOW_SIZE but this is not - * tested. - * - * The following limitations are known, and there are probably more: - * If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect - * because the size of the memory object that we allocate (in bytes) - * will not fit in a size_t. - * If WINDOW_G > 31 and int has 32 bits, then the code is incorrect - * because certain expressions will overflow. - */ -#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24 -# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24]. -#endif - -/** The number of entries a table with precomputed multiples needs to have. */ -#define ECMULT_TABLE_SIZE(w) (1L << ((w)-2)) - -/** Double multiply: R = na*A + ng*G */ -static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); - -typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data); - -/** - * Multi-multiply: R = inp_g_sc * G + sum_i ni * Ai. - * Chooses the right algorithm for a given number of points and scratch space - * size. Resets and overwrites the given scratch space. If the points do not - * fit in the scratch space the algorithm is repeatedly run with batches of - * points. If no scratch space is given then a simple algorithm is used that - * simply multiplies the points with the corresponding scalars and adds them up. - * Returns: 1 on success (including when inp_g_sc is NULL and n is 0) - * 0 if there is not enough scratch space for a single point or - * callback returns 0 - */ -static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n); - -#endif /* SECP256K1_ECMULT_H */ diff --git a/external/secp256k1/src/ecmult_compute_table.h b/external/secp256k1/src/ecmult_compute_table.h deleted file mode 100644 index 665f87ff3d..0000000000 --- a/external/secp256k1/src/ecmult_compute_table.h +++ /dev/null @@ -1,16 +0,0 @@ -/***************************************************************************************************** - * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php. * - *****************************************************************************************************/ - -#ifndef SECP256K1_ECMULT_COMPUTE_TABLE_H -#define SECP256K1_ECMULT_COMPUTE_TABLE_H - -/* Construct table of all odd multiples of gen in range 1..(2**(window_g-1)-1). */ -static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen); - -/* Like secp256k1_ecmult_compute_table, but one for both gen and gen*2^128. */ -static void secp256k1_ecmult_compute_two_tables(secp256k1_ge_storage* table, secp256k1_ge_storage* table_128, int window_g, const secp256k1_ge* gen); - -#endif /* SECP256K1_ECMULT_COMPUTE_TABLE_H */ diff --git a/external/secp256k1/src/ecmult_compute_table_impl.h b/external/secp256k1/src/ecmult_compute_table_impl.h deleted file mode 100644 index 69d59ce595..0000000000 --- a/external/secp256k1/src/ecmult_compute_table_impl.h +++ /dev/null @@ -1,49 +0,0 @@ -/***************************************************************************************************** - * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php. * - *****************************************************************************************************/ - -#ifndef SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H -#define SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H - -#include "ecmult_compute_table.h" -#include "group_impl.h" -#include "field_impl.h" -#include "ecmult.h" -#include "util.h" - -static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen) { - secp256k1_gej gj; - secp256k1_ge ge, dgen; - int j; - - gj = *gen; - secp256k1_ge_set_gej_var(&ge, &gj); - secp256k1_ge_to_storage(&table[0], &ge); - - secp256k1_gej_double_var(&gj, gen, NULL); - secp256k1_ge_set_gej_var(&dgen, &gj); - - for (j = 1; j < ECMULT_TABLE_SIZE(window_g); ++j) { - secp256k1_gej_set_ge(&gj, &ge); - secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL); - secp256k1_ge_set_gej_var(&ge, &gj); - secp256k1_ge_to_storage(&table[j], &ge); - } -} - -/* Like secp256k1_ecmult_compute_table, but one for both gen and gen*2^128. */ -static void secp256k1_ecmult_compute_two_tables(secp256k1_ge_storage* table, secp256k1_ge_storage* table_128, int window_g, const secp256k1_ge* gen) { - secp256k1_gej gj; - int i; - - secp256k1_gej_set_ge(&gj, gen); - secp256k1_ecmult_compute_table(table, window_g, &gj); - for (i = 0; i < 128; ++i) { - secp256k1_gej_double_var(&gj, &gj, NULL); - } - secp256k1_ecmult_compute_table(table_128, window_g, &gj); -} - -#endif /* SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H */ diff --git a/external/secp256k1/src/ecmult_const.h b/external/secp256k1/src/ecmult_const.h deleted file mode 100644 index 080e04bc88..0000000000 --- a/external/secp256k1/src/ecmult_const.h +++ /dev/null @@ -1,38 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECMULT_CONST_H -#define SECP256K1_ECMULT_CONST_H - -#include "scalar.h" -#include "group.h" - -/** - * Multiply: R = q*A (in constant-time for q) - */ -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); - -/** - * Same as secp256k1_ecmult_const, but takes in an x coordinate of the base point - * only, specified as fraction n/d (numerator/denominator). Only the x coordinate of the result is - * returned. - * - * If known_on_curve is 0, a verification is performed that n/d is a valid X - * coordinate, and 0 is returned if not. Otherwise, 1 is returned. - * - * d being NULL is interpreted as d=1. If non-NULL, d must not be zero. q must not be zero. - * - * Constant time in the value of q, but not any other inputs. - */ -static int secp256k1_ecmult_const_xonly( - secp256k1_fe *r, - const secp256k1_fe *n, - const secp256k1_fe *d, - const secp256k1_scalar *q, - int known_on_curve -); - -#endif /* SECP256K1_ECMULT_CONST_H */ diff --git a/external/secp256k1/src/ecmult_const_impl.h b/external/secp256k1/src/ecmult_const_impl.h deleted file mode 100644 index 0d78f7c3ce..0000000000 --- a/external/secp256k1/src/ecmult_const_impl.h +++ /dev/null @@ -1,399 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015, 2022 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECMULT_CONST_IMPL_H -#define SECP256K1_ECMULT_CONST_IMPL_H - -#include "scalar.h" -#include "group.h" -#include "ecmult_const.h" -#include "ecmult_impl.h" - -#if defined(EXHAUSTIVE_TEST_ORDER) -/* We need 2^ECMULT_CONST_GROUP_SIZE - 1 to be less than EXHAUSTIVE_TEST_ORDER, because - * the tables cannot have infinities in them (this breaks the effective-affine technique's - * z-ratio tracking) */ -# if EXHAUSTIVE_TEST_ORDER == 199 -# define ECMULT_CONST_GROUP_SIZE 4 -# elif EXHAUSTIVE_TEST_ORDER == 13 -# define ECMULT_CONST_GROUP_SIZE 3 -# elif EXHAUSTIVE_TEST_ORDER == 7 -# define ECMULT_CONST_GROUP_SIZE 2 -# else -# error "Unknown EXHAUSTIVE_TEST_ORDER" -# endif -#else -/* Group size 4 or 5 appears optimal. */ -# define ECMULT_CONST_GROUP_SIZE 5 -#endif - -#define ECMULT_CONST_TABLE_SIZE (1L << (ECMULT_CONST_GROUP_SIZE - 1)) -#define ECMULT_CONST_GROUPS ((129 + ECMULT_CONST_GROUP_SIZE - 1) / ECMULT_CONST_GROUP_SIZE) -#define ECMULT_CONST_BITS (ECMULT_CONST_GROUPS * ECMULT_CONST_GROUP_SIZE) - -/** Fill a table 'pre' with precomputed odd multiples of a. - * - * The resulting point set is brought to a single constant Z denominator, stores the X and Y - * coordinates as ge points in pre, and stores the global Z in globalz. - * - * 'pre' must be an array of size ECMULT_CONST_TABLE_SIZE. - */ -static void secp256k1_ecmult_const_odd_multiples_table_globalz(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { - secp256k1_fe zr[ECMULT_CONST_TABLE_SIZE]; - - secp256k1_ecmult_odd_multiples_table(ECMULT_CONST_TABLE_SIZE, pre, zr, globalz, a); - secp256k1_ge_table_set_globalz(ECMULT_CONST_TABLE_SIZE, pre, zr); -} - -/* Given a table 'pre' with odd multiples of a point, put in r the signed-bit multiplication of n with that point. - * - * For example, if ECMULT_CONST_GROUP_SIZE is 4, then pre is expected to contain 8 entries: - * [1*P, 3*P, 5*P, 7*P, 9*P, 11*P, 13*P, 15*P]. n is then expected to be a 4-bit integer (range 0-15), and its - * bits are interpreted as signs of powers of two to look up. - * - * For example, if n=4, which is 0100 in binary, which is interpreted as [- + - -], so the looked up value is - * [ -(2^3) + (2^2) - (2^1) - (2^0) ]*P = -7*P. Every valid n translates to an odd number in range [-15,15], - * which means we just need to look up one of the precomputed values, and optionally negate it. - */ -#define ECMULT_CONST_TABLE_GET_GE(r,pre,n) do { \ - unsigned int m = 0; \ - /* If the top bit of n is 0, we want the negation. */ \ - volatile unsigned int negative = ((n) >> (ECMULT_CONST_GROUP_SIZE - 1)) ^ 1; \ - /* Let n[i] be the i-th bit of n, then the index is - * sum(cnot(n[i]) * 2^i, i=0..l-2) - * where cnot(b) = b if n[l-1] = 1 and 1 - b otherwise. - * For example, if n = 4, in binary 0100, the index is 3, in binary 011. - * - * Proof: - * Let - * x = sum((2*n[i] - 1)*2^i, i=0..l-1) - * = 2*sum(n[i] * 2^i, i=0..l-1) - 2^l + 1 - * be the value represented by n. - * The index is (x - 1)/2 if x > 0 and -(x + 1)/2 otherwise. - * Case x > 0: - * n[l-1] = 1 - * index = sum(n[i] * 2^i, i=0..l-1) - 2^(l-1) - * = sum(n[i] * 2^i, i=0..l-2) - * Case x <= 0: - * n[l-1] = 0 - * index = -(2*sum(n[i] * 2^i, i=0..l-1) - 2^l + 2)/2 - * = 2^(l-1) - 1 - sum(n[i] * 2^i, i=0..l-1) - * = sum((1 - n[i]) * 2^i, i=0..l-2) - */ \ - unsigned int index = ((unsigned int)(-negative) ^ n) & ((1U << (ECMULT_CONST_GROUP_SIZE - 1)) - 1U); \ - secp256k1_fe neg_y; \ - VERIFY_CHECK((n) < (1U << ECMULT_CONST_GROUP_SIZE)); \ - VERIFY_CHECK(index < (1U << (ECMULT_CONST_GROUP_SIZE - 1))); \ - /* Unconditionally set r->x = (pre)[m].x. r->y = (pre)[m].y. because it's either the correct one - * or will get replaced in the later iterations, this is needed to make sure `r` is initialized. */ \ - (r)->x = (pre)[m].x; \ - (r)->y = (pre)[m].y; \ - for (m = 1; m < ECMULT_CONST_TABLE_SIZE; m++) { \ - /* This loop is used to avoid secret data in array indices. See - * the comment in ecmult_gen_impl.h for rationale. */ \ - secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == index); \ - secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == index); \ - } \ - (r)->infinity = 0; \ - secp256k1_fe_negate(&neg_y, &(r)->y, 1); \ - secp256k1_fe_cmov(&(r)->y, &neg_y, negative); \ -} while(0) - -/* For K as defined in the comment of secp256k1_ecmult_const, we have several precomputed - * formulas/constants. - * - in exhaustive test mode, we give an explicit expression to compute it at compile time: */ -#ifdef EXHAUSTIVE_TEST_ORDER -static const secp256k1_scalar secp256k1_ecmult_const_K = ((SECP256K1_SCALAR_CONST(0, 0, 0, (1U << (ECMULT_CONST_BITS - 128)) - 2U, 0, 0, 0, 0) + EXHAUSTIVE_TEST_ORDER - 1U) * (1U + EXHAUSTIVE_TEST_LAMBDA)) % EXHAUSTIVE_TEST_ORDER; -/* - for the real secp256k1 group we have constants for various ECMULT_CONST_BITS values. */ -#elif ECMULT_CONST_BITS == 129 -/* For GROUP_SIZE = 1,3. */ -static const secp256k1_scalar secp256k1_ecmult_const_K = SECP256K1_SCALAR_CONST(0xac9c52b3ul, 0x3fa3cf1ful, 0x5ad9e3fdul, 0x77ed9ba4ul, 0xa880b9fcul, 0x8ec739c2ul, 0xe0cfc810ul, 0xb51283ceul); -#elif ECMULT_CONST_BITS == 130 -/* For GROUP_SIZE = 2,5. */ -static const secp256k1_scalar secp256k1_ecmult_const_K = SECP256K1_SCALAR_CONST(0xa4e88a7dul, 0xcb13034eul, 0xc2bdd6bful, 0x7c118d6bul, 0x589ae848ul, 0x26ba29e4ul, 0xb5c2c1dcul, 0xde9798d9ul); -#elif ECMULT_CONST_BITS == 132 -/* For GROUP_SIZE = 4,6 */ -static const secp256k1_scalar secp256k1_ecmult_const_K = SECP256K1_SCALAR_CONST(0x76b1d93dul, 0x0fae3c6bul, 0x3215874bul, 0x94e93813ul, 0x7937fe0dul, 0xb66bcaaful, 0xb3749ca5ul, 0xd7b6171bul); -#else -# error "Unknown ECMULT_CONST_BITS" -#endif - -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q) { - /* The approach below combines the signed-digit logic from Mike Hamburg's - * "Fast and compact elliptic-curve cryptography" (https://eprint.iacr.org/2012/309) - * Section 3.3, with the GLV endomorphism. - * - * The idea there is to interpret the bits of a scalar as signs (1 = +, 0 = -), and compute a - * point multiplication in that fashion. Let v be an n-bit non-negative integer (0 <= v < 2^n), - * and v[i] its i'th bit (so v = sum(v[i] * 2^i, i=0..n-1)). Then define: - * - * C_l(v, A) = sum((2*v[i] - 1) * 2^i*A, i=0..l-1) - * - * Then it holds that C_l(v, A) = sum((2*v[i] - 1) * 2^i*A, i=0..l-1) - * = (2*sum(v[i] * 2^i, i=0..l-1) + 1 - 2^l) * A - * = (2*v + 1 - 2^l) * A - * - * Thus, one can compute q*A as C_256((q + 2^256 - 1) / 2, A). This is the basis for the - * paper's signed-digit multi-comb algorithm for multiplication using a precomputed table. - * - * It is appealing to try to combine this with the GLV optimization: the idea that a scalar - * s can be written as s1 + lambda*s2, where lambda is a curve-specific constant such that - * lambda*A is easy to compute, and where s1 and s2 are small. In particular we have the - * secp256k1_scalar_split_lambda function which performs such a split with the resulting s1 - * and s2 in range (-2^128, 2^128) mod n. This does work, but is uninteresting: - * - * To compute q*A: - * - Let s1, s2 = split_lambda(q) - * - Let R1 = C_256((s1 + 2^256 - 1) / 2, A) - * - Let R2 = C_256((s2 + 2^256 - 1) / 2, lambda*A) - * - Return R1 + R2 - * - * The issue is that while s1 and s2 are small-range numbers, (s1 + 2^256 - 1) / 2 (mod n) - * and (s2 + 2^256 - 1) / 2 (mod n) are not, undoing the benefit of the splitting. - * - * To make it work, we want to modify the input scalar q first, before splitting, and then only - * add a 2^128 offset of the split results (so that they end up in the single 129-bit range - * [0,2^129]). A slightly smaller offset would work due to the bounds on the split, but we pick - * 2^128 for simplicity. Let s be the scalar fed to split_lambda, and f(q) the function to - * compute it from q: - * - * To compute q*A: - * - Compute s = f(q) - * - Let s1, s2 = split_lambda(s) - * - Let v1 = s1 + 2^128 (mod n) - * - Let v2 = s2 + 2^128 (mod n) - * - Let R1 = C_l(v1, A) - * - Let R2 = C_l(v2, lambda*A) - * - Return R1 + R2 - * - * l will thus need to be at least 129, but we may overshoot by a few bits (see - * further), so keep it as a variable. - * - * To solve for s, we reason: - * q*A = R1 + R2 - * <=> q*A = C_l(s1 + 2^128, A) + C_l(s2 + 2^128, lambda*A) - * <=> q*A = (2*(s1 + 2^128) + 1 - 2^l) * A + (2*(s2 + 2^128) + 1 - 2^l) * lambda*A - * <=> q*A = (2*(s1 + s2*lambda) + (2^129 + 1 - 2^l) * (1 + lambda)) * A - * <=> q = 2*(s1 + s2*lambda) + (2^129 + 1 - 2^l) * (1 + lambda) (mod n) - * <=> q = 2*s + (2^129 + 1 - 2^l) * (1 + lambda) (mod n) - * <=> s = (q + (2^l - 2^129 - 1) * (1 + lambda)) / 2 (mod n) - * <=> f(q) = (q + K) / 2 (mod n) - * where K = (2^l - 2^129 - 1)*(1 + lambda) (mod n) - * - * We will process the computation of C_l(v1, A) and C_l(v2, lambda*A) in groups of - * ECMULT_CONST_GROUP_SIZE, so we set l to the smallest multiple of ECMULT_CONST_GROUP_SIZE - * that is not less than 129; this equals ECMULT_CONST_BITS. - */ - - /* The offset to add to s1 and s2 to make them non-negative. Equal to 2^128. */ - static const secp256k1_scalar S_OFFSET = SECP256K1_SCALAR_CONST(0, 0, 0, 1, 0, 0, 0, 0); - secp256k1_scalar s, v1, v2; - secp256k1_ge pre_a[ECMULT_CONST_TABLE_SIZE]; - secp256k1_ge pre_a_lam[ECMULT_CONST_TABLE_SIZE]; - secp256k1_fe global_z; - int group, i; - - /* We're allowed to be non-constant time in the point, and the code below (in particular, - * secp256k1_ecmult_const_odd_multiples_table_globalz) cannot deal with infinity in a - * constant-time manner anyway. */ - if (secp256k1_ge_is_infinity(a)) { - secp256k1_gej_set_infinity(r); - return; - } - - /* Compute v1 and v2. */ - secp256k1_scalar_add(&s, q, &secp256k1_ecmult_const_K); - secp256k1_scalar_half(&s, &s); - secp256k1_scalar_split_lambda(&v1, &v2, &s); - secp256k1_scalar_add(&v1, &v1, &S_OFFSET); - secp256k1_scalar_add(&v2, &v2, &S_OFFSET); - -#ifdef VERIFY - /* Verify that v1 and v2 are in range [0, 2^129-1]. */ - for (i = 129; i < 256; ++i) { - VERIFY_CHECK(secp256k1_scalar_get_bits_limb32(&v1, i, 1) == 0); - VERIFY_CHECK(secp256k1_scalar_get_bits_limb32(&v2, i, 1) == 0); - } -#endif - - /* Calculate odd multiples of A and A*lambda. - * All multiples are brought to the same Z 'denominator', which is stored - * in global_z. Due to secp256k1' isomorphism we can do all operations pretending - * that the Z coordinate was 1, use affine addition formulae, and correct - * the Z coordinate of the result once at the end. - */ - secp256k1_gej_set_ge(r, a); - secp256k1_ecmult_const_odd_multiples_table_globalz(pre_a, &global_z, r); - for (i = 0; i < ECMULT_CONST_TABLE_SIZE; i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); - } - - /* Next, we compute r = C_l(v1, A) + C_l(v2, lambda*A). - * - * We proceed in groups of ECMULT_CONST_GROUP_SIZE bits, operating on that many bits - * at a time, from high in v1, v2 to low. Call these bits1 (from v1) and bits2 (from v2). - * - * Now note that ECMULT_CONST_TABLE_GET_GE(&t, pre_a, bits1) loads into t a point equal - * to C_{ECMULT_CONST_GROUP_SIZE}(bits1, A), and analogously for pre_lam_a / bits2. - * This means that all we need to do is add these looked up values together, multiplied - * by 2^(ECMULT_GROUP_SIZE * group). - */ - for (group = ECMULT_CONST_GROUPS - 1; group >= 0; --group) { - /* Using the _var get_bits function is ok here, since it's only variable in offset and count, not in the scalar. */ - unsigned int bits1 = secp256k1_scalar_get_bits_var(&v1, group * ECMULT_CONST_GROUP_SIZE, ECMULT_CONST_GROUP_SIZE); - unsigned int bits2 = secp256k1_scalar_get_bits_var(&v2, group * ECMULT_CONST_GROUP_SIZE, ECMULT_CONST_GROUP_SIZE); - secp256k1_ge t; - int j; - - ECMULT_CONST_TABLE_GET_GE(&t, pre_a, bits1); - if (group == ECMULT_CONST_GROUPS - 1) { - /* Directly set r in the first iteration. */ - secp256k1_gej_set_ge(r, &t); - } else { - /* Shift the result so far up. */ - for (j = 0; j < ECMULT_CONST_GROUP_SIZE; ++j) { - secp256k1_gej_double(r, r); - } - secp256k1_gej_add_ge(r, r, &t); - } - ECMULT_CONST_TABLE_GET_GE(&t, pre_a_lam, bits2); - secp256k1_gej_add_ge(r, r, &t); - } - - /* Map the result back to the secp256k1 curve from the isomorphic curve. */ - secp256k1_fe_mul(&r->z, &r->z, &global_z); -} - -static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, const secp256k1_fe *d, const secp256k1_scalar *q, int known_on_curve) { - - /* This algorithm is a generalization of Peter Dettman's technique for - * avoiding the square root in a random-basepoint x-only multiplication - * on a Weierstrass curve: - * https://mailarchive.ietf.org/arch/msg/cfrg/7DyYY6gg32wDgHAhgSb6XxMDlJA/ - * - * - * === Background: the effective affine technique === - * - * Let phi_u be the isomorphism that maps (x, y) on secp256k1 curve y^2 = x^3 + 7 to - * x' = u^2*x, y' = u^3*y on curve y'^2 = x'^3 + u^6*7. This new curve has the same order as - * the original (it is isomorphic), but moreover, has the same addition/doubling formulas, as - * the curve b=7 coefficient does not appear in those formulas (or at least does not appear in - * the formulas implemented in this codebase, both affine and Jacobian). See also Example 9.5.2 - * in https://www.math.auckland.ac.nz/~sgal018/crypto-book/ch9.pdf. - * - * This means any linear combination of secp256k1 points can be computed by applying phi_u - * (with non-zero u) on all input points (including the generator, if used), computing the - * linear combination on the isomorphic curve (using the same group laws), and then applying - * phi_u^{-1} to get back to secp256k1. - * - * Switching to Jacobian coordinates, note that phi_u applied to (X, Y, Z) is simply - * (X, Y, Z/u). Thus, if we want to compute (X1, Y1, Z) + (X2, Y2, Z), with identical Z - * coordinates, we can use phi_Z to transform it to (X1, Y1, 1) + (X2, Y2, 1) on an isomorphic - * curve where the affine addition formula can be used instead. - * If (X3, Y3, Z3) = (X1, Y1) + (X2, Y2) on that curve, then our answer on secp256k1 is - * (X3, Y3, Z3*Z). - * - * This is the effective affine technique: if we have a linear combination of group elements - * to compute, and all those group elements have the same Z coordinate, we can simply pretend - * that all those Z coordinates are 1, perform the computation that way, and then multiply the - * original Z coordinate back in. - * - * The technique works on any a=0 short Weierstrass curve. It is possible to generalize it to - * other curves too, but there the isomorphic curves will have different 'a' coefficients, - * which typically does affect the group laws. - * - * - * === Avoiding the square root for x-only point multiplication === - * - * In this function, we want to compute the X coordinate of q*(n/d, y), for - * y = sqrt((n/d)^3 + 7). Its negation would also be a valid Y coordinate, but by convention - * we pick whatever sqrt returns (which we assume to be a deterministic function). - * - * Let g = y^2*d^3 = n^3 + 7*d^3. This also means y = sqrt(g/d^3). - * Further let v = sqrt(d*g), which must exist as d*g = y^2*d^4 = (y*d^2)^2. - * - * The input point (n/d, y) also has Jacobian coordinates: - * - * (n/d, y, 1) - * = (n/d * v^2, y * v^3, v) - * = (n/d * d*g, y * sqrt(d^3*g^3), v) - * = (n/d * d*g, sqrt(y^2 * d^3*g^3), v) - * = (n*g, sqrt(g/d^3 * d^3*g^3), v) - * = (n*g, sqrt(g^4), v) - * = (n*g, g^2, v) - * - * It is easy to verify that both (n*g, g^2, v) and its negation (n*g, -g^2, v) have affine X - * coordinate n/d, and this holds even when the square root function doesn't have a - * deterministic sign. We choose the (n*g, g^2, v) version. - * - * Now switch to the effective affine curve using phi_v, where the input point has coordinates - * (n*g, g^2). Compute (X, Y, Z) = q * (n*g, g^2) there. - * - * Back on secp256k1, that means q * (n*g, g^2, v) = (X, Y, v*Z). This last point has affine X - * coordinate X / (v^2*Z^2) = X / (d*g*Z^2). Determining the affine Y coordinate would involve - * a square root, but as long as we only care about the resulting X coordinate, no square root - * is needed anywhere in this computation. - */ - - secp256k1_fe g, i; - secp256k1_ge p; - secp256k1_gej rj; - - /* Compute g = (n^3 + B*d^3). */ - secp256k1_fe_sqr(&g, n); - secp256k1_fe_mul(&g, &g, n); - if (d) { - secp256k1_fe b; - VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero(d)); - secp256k1_fe_sqr(&b, d); - VERIFY_CHECK(SECP256K1_B <= 8); /* magnitude of b will be <= 8 after the next call */ - secp256k1_fe_mul_int(&b, SECP256K1_B); - secp256k1_fe_mul(&b, &b, d); - secp256k1_fe_add(&g, &b); - if (!known_on_curve) { - /* We need to determine whether (n/d)^3 + 7 is square. - * - * is_square((n/d)^3 + 7) - * <=> is_square(((n/d)^3 + 7) * d^4) - * <=> is_square((n^3 + 7*d^3) * d) - * <=> is_square(g * d) - */ - secp256k1_fe c; - secp256k1_fe_mul(&c, &g, d); - if (!secp256k1_fe_is_square_var(&c)) return 0; - } - } else { - secp256k1_fe_add_int(&g, SECP256K1_B); - if (!known_on_curve) { - /* g at this point equals x^3 + 7. Test if it is square. */ - if (!secp256k1_fe_is_square_var(&g)) return 0; - } - } - - /* Compute base point P = (n*g, g^2), the effective affine version of (n*g, g^2, v), which has - * corresponding affine X coordinate n/d. */ - secp256k1_fe_mul(&p.x, &g, n); - secp256k1_fe_sqr(&p.y, &g); - p.infinity = 0; - - /* Perform x-only EC multiplication of P with q. */ - VERIFY_CHECK(!secp256k1_scalar_is_zero(q)); - secp256k1_ecmult_const(&rj, &p, q); - VERIFY_CHECK(!secp256k1_gej_is_infinity(&rj)); - - /* The resulting (X, Y, Z) point on the effective-affine isomorphic curve corresponds to - * (X, Y, Z*v) on the secp256k1 curve. The affine version of that has X coordinate - * (X / (Z^2*d*g)). */ - secp256k1_fe_sqr(&i, &rj.z); - secp256k1_fe_mul(&i, &i, &g); - if (d) secp256k1_fe_mul(&i, &i, d); - secp256k1_fe_inv(&i, &i); - secp256k1_fe_mul(r, &rj.x, &i); - - return 1; -} - -#endif /* SECP256K1_ECMULT_CONST_IMPL_H */ diff --git a/external/secp256k1/src/ecmult_gen.h b/external/secp256k1/src/ecmult_gen.h deleted file mode 100644 index 43dd10c38d..0000000000 --- a/external/secp256k1/src/ecmult_gen.h +++ /dev/null @@ -1,143 +0,0 @@ -/*********************************************************************** - * Copyright (c) Pieter Wuille, Peter Dettman * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECMULT_GEN_H -#define SECP256K1_ECMULT_GEN_H - -#include "scalar.h" -#include "group.h" - - -/* Configuration parameters for the signed-digit multi-comb algorithm: - * - * - COMB_BLOCKS is the number of blocks the input is split into. Each - * has a corresponding table. - * - COMB_TEETH is the number of bits simultaneously covered by one table. - * - COMB_RANGE is the number of bits in supported scalars. For production - * purposes, only 256 is reasonable, but smaller numbers are supported for - * exhaustive test mode. - * - * The comb's spacing (COMB_SPACING), or the distance between the teeth, - * is defined as ceil(COMB_RANGE / (COMB_BLOCKS * COMB_TEETH)). Each block covers - * COMB_SPACING * COMB_TEETH consecutive bits in the input. - * - * The size of the precomputed table is COMB_BLOCKS * (1 << (COMB_TEETH - 1)) - * secp256k1_ge_storages. - * - * The number of point additions equals COMB_BLOCKS * COMB_SPACING. Each point - * addition involves a cmov from (1 << (COMB_TEETH - 1)) table entries and a - * conditional negation. - * - * The number of point doublings is COMB_SPACING - 1. */ - -#if defined(EXHAUSTIVE_TEST_ORDER) -/* We need to control these values for exhaustive tests because - * the table cannot have infinities in them (secp256k1_ge_storage - * doesn't support infinities) */ -# undef COMB_BLOCKS -# undef COMB_TEETH -# if EXHAUSTIVE_TEST_ORDER == 7 -# define COMB_RANGE 3 -# define COMB_BLOCKS 1 -# define COMB_TEETH 2 -# elif EXHAUSTIVE_TEST_ORDER == 13 -# define COMB_RANGE 4 -# define COMB_BLOCKS 1 -# define COMB_TEETH 2 -# elif EXHAUSTIVE_TEST_ORDER == 199 -# define COMB_RANGE 8 -# define COMB_BLOCKS 2 -# define COMB_TEETH 3 -# else -# error "Unknown exhaustive test order" -# endif -# if (COMB_RANGE >= 32) || ((EXHAUSTIVE_TEST_ORDER >> (COMB_RANGE - 1)) != 1) -# error "COMB_RANGE != ceil(log2(EXHAUSTIVE_TEST_ORDER+1))" -# endif -#else /* !defined(EXHAUSTIVE_TEST_ORDER) */ -# define COMB_RANGE 256 -#endif /* defined(EXHAUSTIVE_TEST_ORDER) */ - -/* Use (11, 6) as default configuration, which results in a 22 kB table. */ -#ifndef COMB_BLOCKS -# define COMB_BLOCKS 11 -# ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_MSG("COMB_BLOCKS undefined, assuming default value") -# endif -#endif -#ifndef COMB_TEETH -# define COMB_TEETH 6 -# ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_MSG("COMB_TEETH undefined, assuming default value") -# endif -#endif -/* Use ceil(COMB_RANGE / (COMB_BLOCKS * COMB_TEETH)) as COMB_SPACING. */ -#define COMB_SPACING CEIL_DIV(COMB_RANGE, COMB_BLOCKS * COMB_TEETH) - -/* Range checks on the parameters. */ - -/* The remaining COMB_* parameters are derived values, don't modify these. */ -/* - The number of bits covered by all the blocks; must be at least COMB_RANGE. */ -#define COMB_BITS (COMB_BLOCKS * COMB_TEETH * COMB_SPACING) -/* - The number of entries per table. */ -#define COMB_POINTS (1 << (COMB_TEETH - 1)) - -/* Sanity checks. */ -#if !(1 <= COMB_BLOCKS && COMB_BLOCKS <= 256) -# error "COMB_BLOCKS must be in the range [1, 256]" -#endif -#if !(1 <= COMB_TEETH && COMB_TEETH <= 8) -# error "COMB_TEETH must be in the range [1, 8]" -#endif -#if COMB_BITS < COMB_RANGE -# error "COMB_BLOCKS * COMB_TEETH * COMB_SPACING is too low" -#endif - -/* These last 2 checks are not strictly required, but prevent gratuitously inefficient - * configurations. Note that they compare with 256 rather than COMB_RANGE, so they do - * permit somewhat excessive values for the exhaustive test case, where testing with - * suboptimal parameters may be desirable. */ -#if (COMB_BLOCKS - 1) * COMB_TEETH * COMB_SPACING >= 256 -# error "COMB_BLOCKS can be reduced" -#endif -#if COMB_BLOCKS * (COMB_TEETH - 1) * COMB_SPACING >= 256 -# error "COMB_TEETH can be reduced" -#endif - -#ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_DEF(COMB_RANGE) -# pragma message DEBUG_CONFIG_DEF(COMB_BLOCKS) -# pragma message DEBUG_CONFIG_DEF(COMB_TEETH) -# pragma message DEBUG_CONFIG_DEF(COMB_SPACING) -#endif - -typedef struct { - /* Whether the context has been built. */ - int built; - - /* Values chosen such that - * - * n*G == comb(n + scalar_offset, G/2) + ge_offset. - * - * This expression lets us use scalar blinding and optimize the comb precomputation. See - * ecmult_gen_impl.h for more details. */ - secp256k1_scalar scalar_offset; - secp256k1_ge ge_offset; - - /* Factor used for projective blinding. This value is used to rescale the Z - * coordinate of the first table lookup. */ - secp256k1_fe proj_blind; -} secp256k1_ecmult_gen_context; - -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx); -static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); - -/** Multiply with the generator: R = a*G */ -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); - -static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); - -#endif /* SECP256K1_ECMULT_GEN_H */ diff --git a/external/secp256k1/src/ecmult_gen_compute_table.h b/external/secp256k1/src/ecmult_gen_compute_table.h deleted file mode 100644 index bd41803a87..0000000000 --- a/external/secp256k1/src/ecmult_gen_compute_table.h +++ /dev/null @@ -1,14 +0,0 @@ -/*********************************************************************** - * Copyright (c) Pieter Wuille, Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H -#define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H - -#include "ecmult_gen.h" - -static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing); - -#endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */ diff --git a/external/secp256k1/src/ecmult_gen_compute_table_impl.h b/external/secp256k1/src/ecmult_gen_compute_table_impl.h deleted file mode 100644 index 6aa8d84082..0000000000 --- a/external/secp256k1/src/ecmult_gen_compute_table_impl.h +++ /dev/null @@ -1,108 +0,0 @@ -/*********************************************************************** - * Copyright (c) Pieter Wuille, Gregory Maxwell, Peter Dettman * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H -#define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H - -#include "ecmult_gen_compute_table.h" -#include "group_impl.h" -#include "field_impl.h" -#include "scalar_impl.h" -#include "ecmult_gen.h" -#include "util.h" - -static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing) { - size_t points = ((size_t)1) << (teeth - 1); - size_t points_total = points * blocks; - secp256k1_ge* prec = checked_malloc(&default_error_callback, points_total * sizeof(*prec)); - secp256k1_gej* ds = checked_malloc(&default_error_callback, teeth * sizeof(*ds)); - secp256k1_gej* vs = checked_malloc(&default_error_callback, points_total * sizeof(*vs)); - secp256k1_gej u; - size_t vs_pos = 0; - secp256k1_scalar half; - int block, i; - - VERIFY_CHECK(points_total > 0); - - /* u is the running power of two times gen we're working with, initially gen/2. */ - secp256k1_scalar_half(&half, &secp256k1_scalar_one); - secp256k1_gej_set_infinity(&u); - for (i = 255; i >= 0; --i) { - /* Use a very simple multiplication ladder to avoid dependency on ecmult. */ - secp256k1_gej_double_var(&u, &u, NULL); - if (secp256k1_scalar_get_bits_limb32(&half, i, 1)) { - secp256k1_gej_add_ge_var(&u, &u, gen, NULL); - } - } -#ifdef VERIFY - { - /* Verify that u*2 = gen. */ - secp256k1_gej double_u; - secp256k1_gej_double_var(&double_u, &u, NULL); - VERIFY_CHECK(secp256k1_gej_eq_ge_var(&double_u, gen)); - } -#endif - - for (block = 0; block < blocks; ++block) { - int tooth; - /* Here u = 2^(block*teeth*spacing) * gen/2. */ - secp256k1_gej sum; - secp256k1_gej_set_infinity(&sum); - for (tooth = 0; tooth < teeth; ++tooth) { - /* Here u = 2^((block*teeth + tooth)*spacing) * gen/2. */ - /* Make sum = sum(2^((block*teeth + t)*spacing), t=0..tooth) * gen/2. */ - secp256k1_gej_add_var(&sum, &sum, &u, NULL); - /* Make u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ - secp256k1_gej_double_var(&u, &u, NULL); - /* Make ds[tooth] = u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ - ds[tooth] = u; - /* Make u = 2^((block*teeth + tooth + 1)*spacing) * gen/2, unless at the end. */ - if (block + tooth != blocks + teeth - 2) { - int bit_off; - for (bit_off = 1; bit_off < spacing; ++bit_off) { - secp256k1_gej_double_var(&u, &u, NULL); - } - } - } - /* Now u = 2^((block*teeth + teeth)*spacing) * gen/2 - * = 2^((block+1)*teeth*spacing) * gen/2 */ - - /* Next, compute the table entries for block number block in Jacobian coordinates. - * The entries will occupy vs[block*points + i] for i=0..points-1. - * We start by computing the first (i=0) value corresponding to all summed - * powers of two times G being negative. */ - secp256k1_gej_neg(&vs[vs_pos++], &sum); - /* And then teeth-1 times "double" the range of i values for which the table - * is computed: in each iteration, double the table by taking an existing - * table entry and adding ds[tooth]. */ - for (tooth = 0; tooth < teeth - 1; ++tooth) { - size_t stride = ((size_t)1) << tooth; - size_t index; - for (index = 0; index < stride; ++index, ++vs_pos) { - secp256k1_gej_add_var(&vs[vs_pos], &vs[vs_pos - stride], &ds[tooth], NULL); - } - } - } - VERIFY_CHECK(vs_pos == points_total); - - /* Convert all points simultaneously from secp256k1_gej to secp256k1_ge. */ - secp256k1_ge_set_all_gej_var(prec, vs, points_total); - /* Convert all points from secp256k1_ge to secp256k1_ge_storage output. */ - for (block = 0; block < blocks; ++block) { - size_t index; - for (index = 0; index < points; ++index) { - VERIFY_CHECK(!secp256k1_ge_is_infinity(&prec[block * points + index])); - secp256k1_ge_to_storage(&table[block * points + index], &prec[block * points + index]); - } - } - - /* Free memory. */ - free(vs); - free(ds); - free(prec); -} - -#endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H */ diff --git a/external/secp256k1/src/ecmult_gen_impl.h b/external/secp256k1/src/ecmult_gen_impl.h deleted file mode 100644 index 070a121308..0000000000 --- a/external/secp256k1/src/ecmult_gen_impl.h +++ /dev/null @@ -1,341 +0,0 @@ -/*********************************************************************** - * Copyright (c) Pieter Wuille, Gregory Maxwell, Peter Dettman * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_ECMULT_GEN_IMPL_H -#define SECP256K1_ECMULT_GEN_IMPL_H - -#include "util.h" -#include "scalar.h" -#include "group.h" -#include "ecmult_gen.h" -#include "hash_impl.h" -#include "precomputed_ecmult_gen.h" - -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx) { - secp256k1_ecmult_gen_blind(ctx, NULL); - ctx->built = 1; -} - -static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) { - return ctx->built; -} - -static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { - ctx->built = 0; - secp256k1_scalar_clear(&ctx->scalar_offset); - secp256k1_ge_clear(&ctx->ge_offset); - secp256k1_fe_clear(&ctx->proj_blind); -} - -/* Compute the scalar (2^COMB_BITS - 1) / 2, the difference between the gn argument to - * secp256k1_ecmult_gen, and the scalar whose encoding the table lookup bits are drawn - * from (before applying blinding). */ -static void secp256k1_ecmult_gen_scalar_diff(secp256k1_scalar* diff) { - int i; - - /* Compute scalar -1/2. */ - secp256k1_scalar neghalf; - secp256k1_scalar_half(&neghalf, &secp256k1_scalar_one); - secp256k1_scalar_negate(&neghalf, &neghalf); - - /* Compute offset = 2^(COMB_BITS - 1). */ - *diff = secp256k1_scalar_one; - for (i = 0; i < COMB_BITS - 1; ++i) { - secp256k1_scalar_add(diff, diff, diff); - } - - /* The result is the sum 2^(COMB_BITS - 1) + (-1/2). */ - secp256k1_scalar_add(diff, diff, &neghalf); -} - -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { - uint32_t comb_off; - secp256k1_ge add; - secp256k1_fe neg; - secp256k1_ge_storage adds; - secp256k1_scalar d; - /* Array of uint32_t values large enough to store COMB_BITS bits. Only the bottom - * 8 are ever nonzero, but having the zero padding at the end if COMB_BITS>256 - * avoids the need to deal with out-of-bounds reads from a scalar. */ - uint32_t recoded[(COMB_BITS + 31) >> 5] = {0}; - int first = 1, i; - - memset(&adds, 0, sizeof(adds)); - - /* We want to compute R = gn*G. - * - * To blind the scalar used in the computation, we rewrite this to be - * R = (gn - b)*G + b*G, with a blinding value b determined by the context. - * - * The multiplication (gn-b)*G will be performed using a signed-digit multi-comb (see Section - * 3.3 of "Fast and compact elliptic-curve cryptography" by Mike Hamburg, - * https://eprint.iacr.org/2012/309). - * - * Let comb(s, P) = sum((2*s[i]-1)*2^i*P for i=0..COMB_BITS-1), where s[i] is the i'th bit of - * the binary representation of scalar s. So the s[i] values determine whether -2^i*P (s[i]=0) - * or +2^i*P (s[i]=1) are added together. COMB_BITS is at least 256, so all bits of s are - * covered. By manipulating: - * - * comb(s, P) = sum((2*s[i]-1)*2^i*P for i=0..COMB_BITS-1) - * <=> comb(s, P) = sum((2*s[i]-1)*2^i for i=0..COMB_BITS-1) * P - * <=> comb(s, P) = (2*sum(s[i]*2^i for i=0..COMB_BITS-1) - sum(2^i for i=0..COMB_BITS-1)) * P - * <=> comb(s, P) = (2*s - (2^COMB_BITS - 1)) * P - * - * If we wanted to compute (gn-b)*G as comb(s, G), it would need to hold that - * - * (gn - b) * G = (2*s - (2^COMB_BITS - 1)) * G - * <=> s = (gn - b + (2^COMB_BITS - 1))/2 (mod order) - * - * We use an alternative here that avoids the modular division by two: instead we compute - * (gn-b)*G as comb(d, G/2). For that to hold it must be the case that - * - * (gn - b) * G = (2*d - (2^COMB_BITS - 1)) * (G/2) - * <=> d = gn - b + (2^COMB_BITS - 1)/2 (mod order) - * - * Adding precomputation, our final equations become: - * - * ctx->scalar_offset = (2^COMB_BITS - 1)/2 - b (mod order) - * ctx->ge_offset = b*G - * d = gn + ctx->scalar_offset (mod order) - * R = comb(d, G/2) + ctx->ge_offset - * - * comb(d, G/2) function is then computed by summing + or - 2^(i-1)*G, for i=0..COMB_BITS-1, - * depending on the value of the bits d[i] of the binary representation of scalar d. - */ - - /* Compute the scalar d = (gn + ctx->scalar_offset). */ - secp256k1_scalar_add(&d, &ctx->scalar_offset, gn); - /* Convert to recoded array. */ - for (i = 0; i < 8 && i < ((COMB_BITS + 31) >> 5); ++i) { - recoded[i] = secp256k1_scalar_get_bits_limb32(&d, 32 * i, 32); - } - secp256k1_scalar_clear(&d); - - /* In secp256k1_ecmult_gen_prec_table we have precomputed sums of the - * (2*d[i]-1) * 2^(i-1) * G points, for various combinations of i positions. - * We rewrite our equation in terms of these table entries. - * - * Let mask(b) = sum(2^((b*COMB_TEETH + t)*COMB_SPACING) for t=0..COMB_TEETH-1), - * with b ranging from 0 to COMB_BLOCKS-1. So for example with COMB_BLOCKS=11, - * COMB_TEETH=6, COMB_SPACING=4, we would have: - * mask(0) = 2^0 + 2^4 + 2^8 + 2^12 + 2^16 + 2^20, - * mask(1) = 2^24 + 2^28 + 2^32 + 2^36 + 2^40 + 2^44, - * mask(2) = 2^48 + 2^52 + 2^56 + 2^60 + 2^64 + 2^68, - * ... - * mask(10) = 2^240 + 2^244 + 2^248 + 2^252 + 2^256 + 2^260 - * - * We will split up the bits d[i] using these masks. Specifically, each mask is - * used COMB_SPACING times, with different shifts: - * - * d = (d & mask(0)<<0) + (d & mask(1)<<0) + ... + (d & mask(COMB_BLOCKS-1)<<0) + - * (d & mask(0)<<1) + (d & mask(1)<<1) + ... + (d & mask(COMB_BLOCKS-1)<<1) + - * ... - * (d & mask(0)<<(COMB_SPACING-1)) + ... - * - * Now define table(b, m) = (m - mask(b)/2) * G, and we will precompute these values for - * b=0..COMB_BLOCKS-1, and for all values m which (d & mask(b)) can take (so m can take on - * 2^COMB_TEETH distinct values). - * - * If m=(d & mask(b)), then table(b, m) is the sum of 2^i * (2*d[i]-1) * G/2, with i - * iterating over the set bits in mask(b). In our example, table(2, 2^48 + 2^56 + 2^68) - * would equal (2^48 - 2^52 + 2^56 - 2^60 - 2^64 + 2^68) * G/2. - * - * With that, we can rewrite comb(d, G/2) as: - * - * 2^0 * (table(0, d>>0 & mask(0)) + ... + table(COMB_BLOCKS-1, d>>0 & mask(COMP_BLOCKS-1))) - * + 2^1 * (table(0, d>>1 & mask(0)) + ... + table(COMB_BLOCKS-1, d>>1 & mask(COMP_BLOCKS-1))) - * + 2^2 * (table(0, d>>2 & mask(0)) + ... + table(COMB_BLOCKS-1, d>>2 & mask(COMP_BLOCKS-1))) - * + ... - * + 2^(COMB_SPACING-1) * (table(0, d>>(COMB_SPACING-1) & mask(0)) + ...) - * - * Or more generically as - * - * sum(2^i * sum(table(b, d>>i & mask(b)), b=0..COMB_BLOCKS-1), i=0..COMB_SPACING-1) - * - * This is implemented using an outer loop that runs in reverse order over the lines of this - * equation, which in each iteration runs an inner loop that adds the terms of that line and - * then doubles the result before proceeding to the next line. - * - * In pseudocode: - * c = infinity - * for comb_off in range(COMB_SPACING - 1, -1, -1): - * for block in range(COMB_BLOCKS): - * c += table(block, (d >> comb_off) & mask(block)) - * if comb_off > 0: - * c = 2*c - * return c - * - * This computes c = comb(d, G/2), and thus finally R = c + ctx->ge_offset. Note that it would - * be possible to apply an initial offset instead of a final offset (moving ge_offset to take - * the place of infinity above), but the chosen approach allows using (in a future improvement) - * an incomplete addition formula for most of the multiplication. - * - * The last question is how to implement the table(b, m) function. For any value of b, - * m=(d & mask(b)) can only take on at most 2^COMB_TEETH possible values (the last one may have - * fewer as there mask(b) may exceed the curve order). So we could create COMB_BLOCK tables - * which contain a value for each such m value. - * - * Now note that if m=(d & mask(b)), then flipping the relevant bits of m results in negating - * the result of table(b, m). This is because table(b,m XOR mask(b)) = table(b, mask(b) - m) = - * (mask(b) - m - mask(b)/2)*G = (-m + mask(b)/2)*G = -(m - mask(b)/2)*G = -table(b, m). - * Because of this it suffices to only store the first half of the m values for every b. If an - * entry from the second half is needed, we look up its bit-flipped version instead, and negate - * it. - * - * secp256k1_ecmult_gen_prec_table[b][index] stores the table(b, m) entries. Index - * is the relevant mask(b) bits of m packed together without gaps. */ - - /* Outer loop: iterate over comb_off from COMB_SPACING - 1 down to 0. */ - comb_off = COMB_SPACING - 1; - while (1) { - uint32_t block; - uint32_t bit_pos = comb_off; - /* Inner loop: for each block, add table entries to the result. */ - for (block = 0; block < COMB_BLOCKS; ++block) { - /* Gather the mask(block)-selected bits of d into bits. They're packed: - * bits[tooth] = d[(block*COMB_TEETH + tooth)*COMB_SPACING + comb_off]. */ - uint32_t bits = 0, sign, abs, index, tooth; - /* Instead of reading individual bits here to construct the bits variable, - * build up the result by xoring rotated reads together. In every iteration, - * one additional bit is made correct, starting at the bottom. The bits - * above that contain junk. This reduces leakage by avoiding computations - * on variables that can have only a low number of possible values (e.g., - * just two values when reading a single bit into a variable.) See: - * https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-alam.pdf - */ - for (tooth = 0; tooth < COMB_TEETH; ++tooth) { - /* Construct bitdata s.t. the bottom bit is the bit we'd like to read. - * - * We could just set bitdata = recoded[bit_pos >> 5] >> (bit_pos & 0x1f) - * but this would simply discard the bits that fall off at the bottom, - * and thus, for example, bitdata could still have only two values if we - * happen to shift by exactly 31 positions. We use a rotation instead, - * which ensures that bitdata doesn't loose entropy. This relies on the - * rotation being atomic, i.e., the compiler emitting an actual rot - * instruction. */ - uint32_t bitdata = secp256k1_rotr32(recoded[bit_pos >> 5], bit_pos & 0x1f); - - /* Clear the bit at position tooth, but sssh, don't tell clang. */ - uint32_t volatile vmask = ~(1 << tooth); - bits &= vmask; - - /* Write the bit into position tooth (and junk into higher bits). */ - bits ^= bitdata << tooth; - bit_pos += COMB_SPACING; - } - - /* If the top bit of bits is 1, flip them all (corresponding to looking up - * the negated table value), and remember to negate the result in sign. */ - sign = (bits >> (COMB_TEETH - 1)) & 1; - abs = (bits ^ -sign) & (COMB_POINTS - 1); - VERIFY_CHECK(sign == 0 || sign == 1); - VERIFY_CHECK(abs < COMB_POINTS); - - /** This uses a conditional move to avoid any secret data in array indexes. - * _Any_ use of secret indexes has been demonstrated to result in timing - * sidechannels, even when the cache-line access patterns are uniform. - * See also: - * "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe - * (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and - * "Cache Attacks and Countermeasures: the Case of AES", RSA 2006, - * by Dag Arne Osvik, Adi Shamir, and Eran Tromer - * (https://www.tau.ac.il/~tromer/papers/cache.pdf) - */ - for (index = 0; index < COMB_POINTS; ++index) { - secp256k1_ge_storage_cmov(&adds, &secp256k1_ecmult_gen_prec_table[block][index], index == abs); - } - - /* Set add=adds or add=-adds, in constant time, based on sign. */ - secp256k1_ge_from_storage(&add, &adds); - secp256k1_fe_negate(&neg, &add.y, 1); - secp256k1_fe_cmov(&add.y, &neg, sign); - - /* Add the looked up and conditionally negated value to r. */ - if (EXPECT(first, 0)) { - /* If this is the first table lookup, we can skip addition. */ - secp256k1_gej_set_ge(r, &add); - /* Give the entry a random Z coordinate to blind intermediary results. */ - secp256k1_gej_rescale(r, &ctx->proj_blind); - first = 0; - } else { - secp256k1_gej_add_ge(r, r, &add); - } - } - - /* Double the result, except in the last iteration. */ - if (comb_off-- == 0) break; - secp256k1_gej_double(r, r); - } - - /* Correct for the scalar_offset added at the start (ge_offset = b*G, while b was - * subtracted from the input scalar gn). */ - secp256k1_gej_add_ge(r, r, &ctx->ge_offset); - - /* Cleanup. */ - secp256k1_fe_clear(&neg); - secp256k1_ge_clear(&add); - secp256k1_memclear(&adds, sizeof(adds)); - secp256k1_memclear(&recoded, sizeof(recoded)); -} - -/* Setup blinding values for secp256k1_ecmult_gen. */ -static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { - secp256k1_scalar b; - secp256k1_scalar diff; - secp256k1_gej gb; - secp256k1_fe f; - unsigned char nonce32[32]; - secp256k1_rfc6979_hmac_sha256 rng; - unsigned char keydata[64]; - - /* Compute the (2^COMB_BITS - 1)/2 term once. */ - secp256k1_ecmult_gen_scalar_diff(&diff); - - if (seed32 == NULL) { - /* When seed is NULL, reset the final point and blinding value. */ - secp256k1_ge_neg(&ctx->ge_offset, &secp256k1_ge_const_g); - secp256k1_scalar_add(&ctx->scalar_offset, &secp256k1_scalar_one, &diff); - ctx->proj_blind = secp256k1_fe_one; - return; - } - /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ - secp256k1_scalar_get_b32(keydata, &ctx->scalar_offset); - /** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, - * and guards against weak or adversarial seeds. This is a simpler and safer interface than - * asking the caller for blinding values directly and expecting them to retry on failure. - */ - VERIFY_CHECK(seed32 != NULL); - memcpy(keydata + 32, seed32, 32); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); - secp256k1_memclear(keydata, sizeof(keydata)); - - /* Compute projective blinding factor (cannot be 0). */ - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - secp256k1_fe_set_b32_mod(&f, nonce32); - secp256k1_fe_cmov(&f, &secp256k1_fe_one, secp256k1_fe_normalizes_to_zero(&f)); - ctx->proj_blind = f; - - /* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */ - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - secp256k1_scalar_set_b32(&b, nonce32, NULL); - /* The blinding value cannot be zero, as that would mean ge_offset = infinity, - * which secp256k1_gej_add_ge cannot handle. */ - secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b)); - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_ecmult_gen(ctx, &gb, &b); - secp256k1_scalar_negate(&b, &b); - secp256k1_scalar_add(&ctx->scalar_offset, &b, &diff); - secp256k1_ge_set_gej(&ctx->ge_offset, &gb); - - /* Clean up. */ - secp256k1_memclear(nonce32, sizeof(nonce32)); - secp256k1_scalar_clear(&b); - secp256k1_gej_clear(&gb); - secp256k1_fe_clear(&f); - secp256k1_rfc6979_hmac_sha256_clear(&rng); -} - -#endif /* SECP256K1_ECMULT_GEN_IMPL_H */ diff --git a/external/secp256k1/src/ecmult_impl.h b/external/secp256k1/src/ecmult_impl.h deleted file mode 100644 index 0b53b3fcb9..0000000000 --- a/external/secp256k1/src/ecmult_impl.h +++ /dev/null @@ -1,853 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php. * - ******************************************************************************/ - -#ifndef SECP256K1_ECMULT_IMPL_H -#define SECP256K1_ECMULT_IMPL_H - -#include -#include - -#include "util.h" -#include "group.h" -#include "scalar.h" -#include "ecmult.h" -#include "precomputed_ecmult.h" - -#if defined(EXHAUSTIVE_TEST_ORDER) -/* We need to lower these values for exhaustive tests because - * the tables cannot have infinities in them (this breaks the - * affine-isomorphism stuff which tracks z-ratios) */ -# if EXHAUSTIVE_TEST_ORDER > 128 -# define WINDOW_A 5 -# elif EXHAUSTIVE_TEST_ORDER > 8 -# define WINDOW_A 4 -# else -# define WINDOW_A 2 -# endif -#else -/* optimal for 128-bit and 256-bit exponents. */ -# define WINDOW_A 5 -/** Larger values for ECMULT_WINDOW_SIZE result in possibly better - * performance at the cost of an exponentially larger precomputed - * table. The exact table size is - * (1 << (WINDOW_G - 2)) * sizeof(secp256k1_ge_storage) bytes, - * where sizeof(secp256k1_ge_storage) is typically 64 bytes but can - * be larger due to platform-specific padding and alignment. - * Two tables of this size are used (due to the endomorphism - * optimization). - */ -#endif - -#define WNAF_BITS 128 -#define WNAF_SIZE_BITS(bits, w) CEIL_DIV(bits, w) -#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w) - -/* The number of objects allocated on the scratch space for ecmult_multi algorithms */ -#define PIPPENGER_SCRATCH_OBJECTS 6 -#define STRAUSS_SCRATCH_OBJECTS 5 - -#define PIPPENGER_MAX_BUCKET_WINDOW 12 - -/* Minimum number of points for which pippenger_wnaf is faster than strauss wnaf */ -#define ECMULT_PIPPENGER_THRESHOLD 88 - -#define ECMULT_MAX_POINTS_PER_BATCH 5000000 - -/** Fill a table 'pre_a' with precomputed odd multiples of a. - * pre_a will contain [1*a,3*a,...,(2*n-1)*a], so it needs space for n group elements. - * zr needs space for n field elements. - * - * Although pre_a is an array of _ge rather than _gej, it actually represents elements - * in Jacobian coordinates with their z coordinates omitted. The omitted z-coordinates - * can be recovered using z and zr. Using the notation z(b) to represent the omitted - * z coordinate of b: - * - z(pre_a[n-1]) = 'z' - * - z(pre_a[i-1]) = z(pre_a[i]) / zr[i] for n > i > 0 - * - * Lastly the zr[0] value, which isn't used above, is set so that: - * - a.z = z(pre_a[0]) / zr[0] - */ -static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_ge *pre_a, secp256k1_fe *zr, secp256k1_fe *z, const secp256k1_gej *a) { - secp256k1_gej d, ai; - secp256k1_ge d_ge; - int i; - - VERIFY_CHECK(!a->infinity); - - secp256k1_gej_double_var(&d, a, NULL); - - /* - * Perform the additions using an isomorphic curve Y^2 = X^3 + 7*C^6 where C := d.z. - * The isomorphism, phi, maps a secp256k1 point (x, y) to the point (x*C^2, y*C^3) on the other curve. - * In Jacobian coordinates phi maps (x, y, z) to (x*C^2, y*C^3, z) or, equivalently to (x, y, z/C). - * - * phi(x, y, z) = (x*C^2, y*C^3, z) = (x, y, z/C) - * d_ge := phi(d) = (d.x, d.y, 1) - * ai := phi(a) = (a.x*C^2, a.y*C^3, a.z) - * - * The group addition functions work correctly on these isomorphic curves. - * In particular phi(d) is easy to represent in affine coordinates under this isomorphism. - * This lets us use the faster secp256k1_gej_add_ge_var group addition function that we wouldn't be able to use otherwise. - */ - secp256k1_ge_set_xy(&d_ge, &d.x, &d.y); - secp256k1_ge_set_gej_zinv(&pre_a[0], a, &d.z); - secp256k1_gej_set_ge(&ai, &pre_a[0]); - ai.z = a->z; - - /* pre_a[0] is the point (a.x*C^2, a.y*C^3, a.z*C) which is equivalent to a. - * Set zr[0] to C, which is the ratio between the omitted z(pre_a[0]) value and a.z. - */ - zr[0] = d.z; - - for (i = 1; i < n; i++) { - secp256k1_gej_add_ge_var(&ai, &ai, &d_ge, &zr[i]); - secp256k1_ge_set_xy(&pre_a[i], &ai.x, &ai.y); - } - - /* Multiply the last z-coordinate by C to undo the isomorphism. - * Since the z-coordinates of the pre_a values are implied by the zr array of z-coordinate ratios, - * undoing the isomorphism here undoes the isomorphism for all pre_a values. - */ - secp256k1_fe_mul(z, &ai.z, &d.z); -} - -SECP256K1_INLINE static void secp256k1_ecmult_table_verify(int n, int w) { - (void)n; - (void)w; - VERIFY_CHECK(((n) & 1) == 1); - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); -} - -SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge(secp256k1_ge *r, const secp256k1_ge *pre, int n, int w) { - secp256k1_ecmult_table_verify(n,w); - if (n > 0) { - *r = pre[(n-1)/2]; - } else { - *r = pre[(-n-1)/2]; - secp256k1_fe_negate(&(r->y), &(r->y), 1); - } -} - -SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge_lambda(secp256k1_ge *r, const secp256k1_ge *pre, const secp256k1_fe *x, int n, int w) { - secp256k1_ecmult_table_verify(n,w); - if (n > 0) { - secp256k1_ge_set_xy(r, &x[(n-1)/2], &pre[(n-1)/2].y); - } else { - secp256k1_ge_set_xy(r, &x[(-n-1)/2], &pre[(-n-1)/2].y); - secp256k1_fe_negate(&(r->y), &(r->y), 1); - } -} - -SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge_storage(secp256k1_ge *r, const secp256k1_ge_storage *pre, int n, int w) { - secp256k1_ecmult_table_verify(n,w); - if (n > 0) { - secp256k1_ge_from_storage(r, &pre[(n-1)/2]); - } else { - secp256k1_ge_from_storage(r, &pre[(-n-1)/2]); - secp256k1_fe_negate(&(r->y), &(r->y), 1); - } -} - -/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), - * with the following guarantees: - * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) - * - two non-zero entries in wnaf are separated by at least w-1 zeroes. - * - the number of set values in wnaf is returned. This number is at most 256, and at most one more - * than the number of bits in the (absolute value) of the input. - */ -static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) { - secp256k1_scalar s; - int last_set_bit = -1; - int bit = 0; - int sign = 1; - int carry = 0; - - VERIFY_CHECK(wnaf != NULL); - VERIFY_CHECK(0 <= len && len <= 256); - VERIFY_CHECK(a != NULL); - VERIFY_CHECK(2 <= w && w <= 31); - - for (bit = 0; bit < len; bit++) { - wnaf[bit] = 0; - } - - s = *a; - if (secp256k1_scalar_get_bits_limb32(&s, 255, 1)) { - secp256k1_scalar_negate(&s, &s); - sign = -1; - } - - bit = 0; - while (bit < len) { - int now; - int word; - if (secp256k1_scalar_get_bits_limb32(&s, bit, 1) == (unsigned int)carry) { - bit++; - continue; - } - - now = w; - if (now > len - bit) { - now = len - bit; - } - - word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; - - carry = (word >> (w-1)) & 1; - word -= carry << w; - - wnaf[bit] = sign * word; - last_set_bit = bit; - - bit += now; - } -#ifdef VERIFY - { - int verify_bit = bit; - - VERIFY_CHECK(carry == 0); - - while (verify_bit < 256) { - VERIFY_CHECK(secp256k1_scalar_get_bits_limb32(&s, verify_bit, 1) == 0); - verify_bit++; - } - } -#endif - return last_set_bit + 1; -} - -struct secp256k1_strauss_point_state { - int wnaf_na_1[129]; - int wnaf_na_lam[129]; - int bits_na_1; - int bits_na_lam; -}; - -struct secp256k1_strauss_state { - /* aux is used to hold z-ratios, and then used to hold pre_a[i].x * BETA values. */ - secp256k1_fe* aux; - secp256k1_ge* pre_a; - struct secp256k1_strauss_point_state* ps; -}; - -static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { - secp256k1_ge tmpa; - secp256k1_fe Z; - /* Split G factors. */ - secp256k1_scalar ng_1, ng_128; - int wnaf_ng_1[129]; - int bits_ng_1 = 0; - int wnaf_ng_128[129]; - int bits_ng_128 = 0; - int i; - int bits = 0; - size_t np; - size_t no = 0; - - secp256k1_fe_set_int(&Z, 1); - for (np = 0; np < num; ++np) { - secp256k1_gej tmp; - secp256k1_scalar na_1, na_lam; - if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) { - continue; - } - /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&na_1, &na_lam, &na[np]); - - /* build wnaf representation for na_1 and na_lam. */ - state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &na_1, WINDOW_A); - state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 129, &na_lam, WINDOW_A); - VERIFY_CHECK(state->ps[no].bits_na_1 <= 129); - VERIFY_CHECK(state->ps[no].bits_na_lam <= 129); - if (state->ps[no].bits_na_1 > bits) { - bits = state->ps[no].bits_na_1; - } - if (state->ps[no].bits_na_lam > bits) { - bits = state->ps[no].bits_na_lam; - } - - /* Calculate odd multiples of a. - * All multiples are brought to the same Z 'denominator', which is stored - * in Z. Due to secp256k1' isomorphism we can do all operations pretending - * that the Z coordinate was 1, use affine addition formulae, and correct - * the Z coordinate of the result once at the end. - * The exception is the precomputed G table points, which are actually - * affine. Compared to the base used for other points, they have a Z ratio - * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same - * isomorphism to efficiently add with a known Z inverse. - */ - tmp = a[np]; - if (no) { - secp256k1_gej_rescale(&tmp, &Z); - } - secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &Z, &tmp); - if (no) secp256k1_fe_mul(state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &(a[np].z)); - - ++no; - } - - /* Bring them to the same Z denominator. */ - if (no) { - secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux); - } - - for (np = 0; np < no; ++np) { - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_fe_mul(&state->aux[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i].x, &secp256k1_const_beta); - } - } - - if (ng) { - /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ - secp256k1_scalar_split_128(&ng_1, &ng_128, ng); - - /* Build wnaf representation for ng_1 and ng_128 */ - bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); - bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); - if (bits_ng_1 > bits) { - bits = bits_ng_1; - } - if (bits_ng_128 > bits) { - bits = bits_ng_128; - } - } - - secp256k1_gej_set_infinity(r); - - for (i = bits - 1; i >= 0; i--) { - int n; - secp256k1_gej_double_var(r, r, NULL); - for (np = 0; np < no; ++np) { - if (i < state->ps[np].bits_na_1 && (n = state->ps[np].wnaf_na_1[i])) { - secp256k1_ecmult_table_get_ge(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < state->ps[np].bits_na_lam && (n = state->ps[np].wnaf_na_lam[i])) { - secp256k1_ecmult_table_get_ge_lambda(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - } - if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { - secp256k1_ecmult_table_get_ge_storage(&tmpa, secp256k1_pre_g, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } - if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { - secp256k1_ecmult_table_get_ge_storage(&tmpa, secp256k1_pre_g_128, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } - } - - if (!r->infinity) { - secp256k1_fe_mul(&r->z, &r->z, &Z); - } -} - -static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { - secp256k1_fe aux[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - struct secp256k1_strauss_point_state ps[1]; - struct secp256k1_strauss_state state; - - state.aux = aux; - state.pre_a = pre_a; - state.ps = ps; - secp256k1_ecmult_strauss_wnaf(&state, r, 1, a, na, ng); -} - -static size_t secp256k1_strauss_scratch_size(size_t n_points) { - static const size_t point_size = (sizeof(secp256k1_ge) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar); - return n_points*point_size; -} - -static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { - secp256k1_gej* points; - secp256k1_scalar* scalars; - struct secp256k1_strauss_state state; - size_t i; - const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch); - - secp256k1_gej_set_infinity(r); - if (inp_g_sc == NULL && n_points == 0) { - return 1; - } - - /* We allocate STRAUSS_SCRATCH_OBJECTS objects on the scratch space. If these - * allocations change, make sure to update the STRAUSS_SCRATCH_OBJECTS - * constant and strauss_scratch_size accordingly. */ - points = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_gej)); - scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar)); - state.aux = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe)); - state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge)); - state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(struct secp256k1_strauss_point_state)); - - if (points == NULL || scalars == NULL || state.aux == NULL || state.pre_a == NULL || state.ps == NULL) { - secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); - return 0; - } - - for (i = 0; i < n_points; i++) { - secp256k1_ge point; - if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) { - secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); - return 0; - } - secp256k1_gej_set_ge(&points[i], &point); - } - secp256k1_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc); - secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); - return 1; -} - -/* Wrapper for secp256k1_ecmult_multi_func interface */ -static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { - return secp256k1_ecmult_strauss_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0); -} - -static size_t secp256k1_strauss_max_points(const secp256k1_callback* error_callback, secp256k1_scratch *scratch) { - return secp256k1_scratch_max_allocation(error_callback, scratch, STRAUSS_SCRATCH_OBJECTS) / secp256k1_strauss_scratch_size(1); -} - -/** Convert a number to WNAF notation. - * The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val. - * It has the following guarantees: - * - each wnaf[i] is either 0 or an odd integer between -(1 << w) and (1 << w) - * - the number of words set is always WNAF_SIZE(w) - * - the returned skew is 0 or 1 - */ -static int secp256k1_wnaf_fixed(int *wnaf, const secp256k1_scalar *s, int w) { - int skew = 0; - int pos; - int max_pos; - int last_w; - const secp256k1_scalar *work = s; - - if (secp256k1_scalar_is_zero(s)) { - for (pos = 0; pos < WNAF_SIZE(w); pos++) { - wnaf[pos] = 0; - } - return 0; - } - - if (secp256k1_scalar_is_even(s)) { - skew = 1; - } - - wnaf[0] = secp256k1_scalar_get_bits_var(work, 0, w) + skew; - /* Compute last window size. Relevant when window size doesn't divide the - * number of bits in the scalar */ - last_w = WNAF_BITS - (WNAF_SIZE(w) - 1) * w; - - /* Store the position of the first nonzero word in max_pos to allow - * skipping leading zeros when calculating the wnaf. */ - for (pos = WNAF_SIZE(w) - 1; pos > 0; pos--) { - int val = secp256k1_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w); - if(val != 0) { - break; - } - wnaf[pos] = 0; - } - max_pos = pos; - pos = 1; - - while (pos <= max_pos) { - int val = secp256k1_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w); - if ((val & 1) == 0) { - wnaf[pos - 1] -= (1 << w); - wnaf[pos] = (val + 1); - } else { - wnaf[pos] = val; - } - /* Set a coefficient to zero if it is 1 or -1 and the proceeding digit - * is strictly negative or strictly positive respectively. Only change - * coefficients at previous positions because above code assumes that - * wnaf[pos - 1] is odd. - */ - if (pos >= 2 && ((wnaf[pos - 1] == 1 && wnaf[pos - 2] < 0) || (wnaf[pos - 1] == -1 && wnaf[pos - 2] > 0))) { - if (wnaf[pos - 1] == 1) { - wnaf[pos - 2] += 1 << w; - } else { - wnaf[pos - 2] -= 1 << w; - } - wnaf[pos - 1] = 0; - } - ++pos; - } - - return skew; -} - -struct secp256k1_pippenger_point_state { - int skew_na; - size_t input_pos; -}; - -struct secp256k1_pippenger_state { - int *wnaf_na; - struct secp256k1_pippenger_point_state* ps; -}; - -/* - * pippenger_wnaf computes the result of a multi-point multiplication as - * follows: The scalars are brought into wnaf with n_wnaf elements each. Then - * for every i < n_wnaf, first each point is added to a "bucket" corresponding - * to the point's wnaf[i]. Second, the buckets are added together such that - * r += 1*bucket[0] + 3*bucket[1] + 5*bucket[2] + ... - */ -static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *r, const secp256k1_scalar *sc, const secp256k1_ge *pt, size_t num) { - size_t n_wnaf = WNAF_SIZE(bucket_window+1); - size_t np; - size_t no = 0; - int i; - int j; - - for (np = 0; np < num; ++np) { - if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) { - continue; - } - state->ps[no].input_pos = np; - state->ps[no].skew_na = secp256k1_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1); - no++; - } - secp256k1_gej_set_infinity(r); - - if (no == 0) { - return 1; - } - - for (i = n_wnaf - 1; i >= 0; i--) { - secp256k1_gej running_sum; - - for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) { - secp256k1_gej_set_infinity(&buckets[j]); - } - - for (np = 0; np < no; ++np) { - int n = state->wnaf_na[np*n_wnaf + i]; - struct secp256k1_pippenger_point_state point_state = state->ps[np]; - secp256k1_ge tmp; - int idx; - - if (i == 0) { - /* correct for wnaf skew */ - int skew = point_state.skew_na; - if (skew) { - secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); - secp256k1_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL); - } - } - if (n > 0) { - idx = (n - 1)/2; - secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); - } else if (n < 0) { - idx = -(n + 1)/2; - secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); - secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); - } - } - - for(j = 0; j < bucket_window; j++) { - secp256k1_gej_double_var(r, r, NULL); - } - - secp256k1_gej_set_infinity(&running_sum); - /* Accumulate the sum: bucket[0] + 3*bucket[1] + 5*bucket[2] + 7*bucket[3] + ... - * = bucket[0] + bucket[1] + bucket[2] + bucket[3] + ... - * + 2 * (bucket[1] + 2*bucket[2] + 3*bucket[3] + ...) - * using an intermediate running sum: - * running_sum = bucket[0] + bucket[1] + bucket[2] + ... - * - * The doubling is done implicitly by deferring the final window doubling (of 'r'). - */ - for(j = ECMULT_TABLE_SIZE(bucket_window+2) - 1; j > 0; j--) { - secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); - secp256k1_gej_add_var(r, r, &running_sum, NULL); - } - - secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL); - secp256k1_gej_double_var(r, r, NULL); - secp256k1_gej_add_var(r, r, &running_sum, NULL); - } - return 1; -} - -/** - * Returns optimal bucket_window (number of bits of a scalar represented by a - * set of buckets) for a given number of points. - */ -static int secp256k1_pippenger_bucket_window(size_t n) { - if (n <= 1) { - return 1; - } else if (n <= 4) { - return 2; - } else if (n <= 20) { - return 3; - } else if (n <= 57) { - return 4; - } else if (n <= 136) { - return 5; - } else if (n <= 235) { - return 6; - } else if (n <= 1260) { - return 7; - } else if (n <= 4420) { - return 9; - } else if (n <= 7880) { - return 10; - } else if (n <= 16050) { - return 11; - } else { - return PIPPENGER_MAX_BUCKET_WINDOW; - } -} - -/** - * Returns the maximum optimal number of points for a bucket_window. - */ -static size_t secp256k1_pippenger_bucket_window_inv(int bucket_window) { - switch(bucket_window) { - case 1: return 1; - case 2: return 4; - case 3: return 20; - case 4: return 57; - case 5: return 136; - case 6: return 235; - case 7: return 1260; - case 8: return 1260; - case 9: return 4420; - case 10: return 7880; - case 11: return 16050; - case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX; - } - return 0; -} - - -SECP256K1_INLINE static void secp256k1_ecmult_endo_split(secp256k1_scalar *s1, secp256k1_scalar *s2, secp256k1_ge *p1, secp256k1_ge *p2) { - secp256k1_scalar tmp = *s1; - secp256k1_scalar_split_lambda(s1, s2, &tmp); - secp256k1_ge_mul_lambda(p2, p1); - - if (secp256k1_scalar_is_high(s1)) { - secp256k1_scalar_negate(s1, s1); - secp256k1_ge_neg(p1, p1); - } - if (secp256k1_scalar_is_high(s2)) { - secp256k1_scalar_negate(s2, s2); - secp256k1_ge_neg(p2, p2); - } -} - -/** - * Returns the scratch size required for a given number of points (excluding - * base point G) without considering alignment. - */ -static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_window) { - size_t entries = 2*n_points + 2; - size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); - return (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size; -} - -static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { - const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch); - /* Use 2(n+1) with the endomorphism, when calculating batch - * sizes. The reason for +1 is that we add the G scalar to the list of - * other scalars. */ - size_t entries = 2*n_points + 2; - secp256k1_ge *points; - secp256k1_scalar *scalars; - secp256k1_gej *buckets; - struct secp256k1_pippenger_state *state_space; - size_t idx = 0; - size_t point_idx = 0; - int bucket_window; - - secp256k1_gej_set_infinity(r); - if (inp_g_sc == NULL && n_points == 0) { - return 1; - } - bucket_window = secp256k1_pippenger_bucket_window(n_points); - - /* We allocate PIPPENGER_SCRATCH_OBJECTS objects on the scratch space. If - * these allocations change, make sure to update the - * PIPPENGER_SCRATCH_OBJECTS constant and pippenger_scratch_size - * accordingly. */ - points = (secp256k1_ge *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*points)); - scalars = (secp256k1_scalar *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*scalars)); - state_space = (struct secp256k1_pippenger_state *) secp256k1_scratch_alloc(error_callback, scratch, sizeof(*state_space)); - if (points == NULL || scalars == NULL || state_space == NULL) { - secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); - return 0; - } - state_space->ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps)); - state_space->wnaf_na = (int *) secp256k1_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int)); - buckets = (secp256k1_gej *) secp256k1_scratch_alloc(error_callback, scratch, ((size_t)1 << bucket_window) * sizeof(*buckets)); - if (state_space->ps == NULL || state_space->wnaf_na == NULL || buckets == NULL) { - secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); - return 0; - } - - if (inp_g_sc != NULL) { - scalars[0] = *inp_g_sc; - points[0] = secp256k1_ge_const_g; - idx++; - secp256k1_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]); - idx++; - } - - while (point_idx < n_points) { - if (!cb(&scalars[idx], &points[idx], point_idx + cb_offset, cbdata)) { - secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); - return 0; - } - idx++; - secp256k1_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]); - idx++; - point_idx++; - } - - secp256k1_ecmult_pippenger_wnaf(buckets, bucket_window, state_space, r, scalars, points, idx); - secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); - return 1; -} - -/* Wrapper for secp256k1_ecmult_multi_func interface */ -static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { - return secp256k1_ecmult_pippenger_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0); -} - -/** - * Returns the maximum number of points in addition to G that can be used with - * a given scratch space. The function ensures that fewer points may also be - * used. - */ -static size_t secp256k1_pippenger_max_points(const secp256k1_callback* error_callback, secp256k1_scratch *scratch) { - size_t max_alloc = secp256k1_scratch_max_allocation(error_callback, scratch, PIPPENGER_SCRATCH_OBJECTS); - int bucket_window; - size_t res = 0; - - for (bucket_window = 1; bucket_window <= PIPPENGER_MAX_BUCKET_WINDOW; bucket_window++) { - size_t n_points; - size_t max_points = secp256k1_pippenger_bucket_window_inv(bucket_window); - size_t space_for_points; - size_t space_overhead; - size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); - - entry_size = 2*entry_size; - space_overhead = (sizeof(secp256k1_gej) << bucket_window) + entry_size + sizeof(struct secp256k1_pippenger_state); - if (space_overhead > max_alloc) { - break; - } - space_for_points = max_alloc - space_overhead; - - n_points = space_for_points/entry_size; - n_points = n_points > max_points ? max_points : n_points; - if (n_points > res) { - res = n_points; - } - if (n_points < max_points) { - /* A larger bucket_window may support even more points. But if we - * would choose that then the caller couldn't safely use any number - * smaller than what this function returns */ - break; - } - } - return res; -} - -/* Computes ecmult_multi by simply multiplying and adding each point. Does not - * require a scratch space */ -static int secp256k1_ecmult_multi_simple_var(secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) { - size_t point_idx; - secp256k1_gej tmpj; - - secp256k1_gej_set_infinity(r); - secp256k1_gej_set_infinity(&tmpj); - /* r = inp_g_sc*G */ - secp256k1_ecmult(r, &tmpj, &secp256k1_scalar_zero, inp_g_sc); - for (point_idx = 0; point_idx < n_points; point_idx++) { - secp256k1_ge point; - secp256k1_gej pointj; - secp256k1_scalar scalar; - if (!cb(&scalar, &point, point_idx, cbdata)) { - return 0; - } - /* r += scalar*point */ - secp256k1_gej_set_ge(&pointj, &point); - secp256k1_ecmult(&tmpj, &pointj, &scalar, NULL); - secp256k1_gej_add_var(r, r, &tmpj, NULL); - } - return 1; -} - -/* Compute the number of batches and the batch size given the maximum batch size and the - * total number of points */ -static int secp256k1_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n_batch_points, size_t max_n_batch_points, size_t n) { - if (max_n_batch_points == 0) { - return 0; - } - if (max_n_batch_points > ECMULT_MAX_POINTS_PER_BATCH) { - max_n_batch_points = ECMULT_MAX_POINTS_PER_BATCH; - } - if (n == 0) { - *n_batches = 0; - *n_batch_points = 0; - return 1; - } - /* Compute ceil(n/max_n_batch_points) and ceil(n/n_batches) */ - *n_batches = CEIL_DIV(n, max_n_batch_points); - *n_batch_points = CEIL_DIV(n, *n_batches); - return 1; -} - -typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t); -static int secp256k1_ecmult_multi_var(const secp256k1_callback* error_callback, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) { - size_t i; - - int (*f)(const secp256k1_callback* error_callback, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t); - size_t n_batches; - size_t n_batch_points; - - secp256k1_gej_set_infinity(r); - if (inp_g_sc == NULL && n == 0) { - return 1; - } else if (n == 0) { - secp256k1_ecmult(r, r, &secp256k1_scalar_zero, inp_g_sc); - return 1; - } - if (scratch == NULL) { - return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); - } - - /* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than - * a threshold use Pippenger's algorithm. Otherwise use Strauss' algorithm. - * As a first step check if there's enough space for Pippenger's algo (which requires less space - * than Strauss' algo) and if not, use the simple algorithm. */ - if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_pippenger_max_points(error_callback, scratch), n)) { - return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); - } - if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) { - f = secp256k1_ecmult_pippenger_batch; - } else { - if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_strauss_max_points(error_callback, scratch), n)) { - return secp256k1_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); - } - f = secp256k1_ecmult_strauss_batch; - } - for(i = 0; i < n_batches; i++) { - size_t nbp = n < n_batch_points ? n : n_batch_points; - size_t offset = n_batch_points*i; - secp256k1_gej tmp; - if (!f(error_callback, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) { - return 0; - } - secp256k1_gej_add_var(r, r, &tmp, NULL); - n -= nbp; - } - return 1; -} - -#endif /* SECP256K1_ECMULT_IMPL_H */ diff --git a/external/secp256k1/src/field.h b/external/secp256k1/src/field.h deleted file mode 100644 index 1f6ba7460f..0000000000 --- a/external/secp256k1/src/field.h +++ /dev/null @@ -1,350 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_FIELD_H -#define SECP256K1_FIELD_H - -#include "util.h" - -/* This file defines the generic interface for working with secp256k1_fe - * objects, which represent field elements (integers modulo 2^256 - 2^32 - 977). - * - * The actual definition of the secp256k1_fe type depends on the chosen field - * implementation; see the field_5x52.h and field_10x26.h files for details. - * - * All secp256k1_fe objects have implicit properties that determine what - * operations are permitted on it. These are purely a function of what - * secp256k1_fe_ operations are applied on it, generally (implicitly) fixed at - * compile time, and do not depend on the chosen field implementation. Despite - * that, what these properties actually entail for the field representation - * values depends on the chosen field implementation. These properties are: - * - magnitude: an integer in [0,32] - * - normalized: 0 or 1; normalized=1 implies magnitude <= 1. - * - * In VERIFY mode, they are materialized explicitly as fields in the struct, - * allowing run-time verification of these properties. In that case, the field - * implementation also provides a secp256k1_fe_verify routine to verify that - * these fields match the run-time value and perform internal consistency - * checks. */ -#ifdef VERIFY -# define SECP256K1_FE_VERIFY_FIELDS \ - int magnitude; \ - int normalized; -#else -# define SECP256K1_FE_VERIFY_FIELDS -#endif - -#if defined(SECP256K1_WIDEMUL_INT128) -#include "field_5x52.h" -#elif defined(SECP256K1_WIDEMUL_INT64) -#include "field_10x26.h" -#else -#error "Please select wide multiplication implementation" -#endif - -#ifdef VERIFY -/* Magnitude and normalized value for constants. */ -#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0) \ - /* Magnitude is 0 for constant 0; 1 otherwise. */ \ - , (((d7) | (d6) | (d5) | (d4) | (d3) | (d2) | (d1) | (d0)) != 0) \ - /* Normalized is 1 unless sum(d_i<<(32*i) for i=0..7) exceeds field modulus. */ \ - , (!(((d7) & (d6) & (d5) & (d4) & (d3) & (d2)) == 0xfffffffful && ((d1) == 0xfffffffful || ((d1) == 0xfffffffe && (d0 >= 0xfffffc2f))))) -#else -#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0) -#endif - -/** This expands to an initializer for a secp256k1_fe valued sum((i*32) * d_i, i=0..7) mod p. - * - * It has magnitude 1, unless d_i are all 0, in which case the magnitude is 0. - * It is normalized, unless sum(2^(i*32) * d_i, i=0..7) >= p. - * - * SECP256K1_FE_CONST_INNER is provided by the implementation. - */ -#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) SECP256K1_FE_VERIFY_CONST((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) } - -static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); -static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST( - 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, - 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul -); - -#ifndef VERIFY -/* In non-VERIFY mode, we #define the fe operations to be identical to their - * internal field implementation, to avoid the potential overhead of a - * function call (even though presumably inlinable). */ -# define secp256k1_fe_normalize secp256k1_fe_impl_normalize -# define secp256k1_fe_normalize_weak secp256k1_fe_impl_normalize_weak -# define secp256k1_fe_normalize_var secp256k1_fe_impl_normalize_var -# define secp256k1_fe_normalizes_to_zero secp256k1_fe_impl_normalizes_to_zero -# define secp256k1_fe_normalizes_to_zero_var secp256k1_fe_impl_normalizes_to_zero_var -# define secp256k1_fe_set_int secp256k1_fe_impl_set_int -# define secp256k1_fe_is_zero secp256k1_fe_impl_is_zero -# define secp256k1_fe_is_odd secp256k1_fe_impl_is_odd -# define secp256k1_fe_cmp_var secp256k1_fe_impl_cmp_var -# define secp256k1_fe_set_b32_mod secp256k1_fe_impl_set_b32_mod -# define secp256k1_fe_set_b32_limit secp256k1_fe_impl_set_b32_limit -# define secp256k1_fe_get_b32 secp256k1_fe_impl_get_b32 -# define secp256k1_fe_negate_unchecked secp256k1_fe_impl_negate_unchecked -# define secp256k1_fe_mul_int_unchecked secp256k1_fe_impl_mul_int_unchecked -# define secp256k1_fe_add secp256k1_fe_impl_add -# define secp256k1_fe_mul secp256k1_fe_impl_mul -# define secp256k1_fe_sqr secp256k1_fe_impl_sqr -# define secp256k1_fe_cmov secp256k1_fe_impl_cmov -# define secp256k1_fe_to_storage secp256k1_fe_impl_to_storage -# define secp256k1_fe_from_storage secp256k1_fe_impl_from_storage -# define secp256k1_fe_inv secp256k1_fe_impl_inv -# define secp256k1_fe_inv_var secp256k1_fe_impl_inv_var -# define secp256k1_fe_get_bounds secp256k1_fe_impl_get_bounds -# define secp256k1_fe_half secp256k1_fe_impl_half -# define secp256k1_fe_add_int secp256k1_fe_impl_add_int -# define secp256k1_fe_is_square_var secp256k1_fe_impl_is_square_var -#endif /* !defined(VERIFY) */ - -/** Normalize a field element. - * - * On input, r must be a valid field element. - * On output, r represents the same value but has normalized=1 and magnitude=1. - */ -static void secp256k1_fe_normalize(secp256k1_fe *r); - -/** Give a field element magnitude 1. - * - * On input, r must be a valid field element. - * On output, r represents the same value but has magnitude=1. Normalized is unchanged. - */ -static void secp256k1_fe_normalize_weak(secp256k1_fe *r); - -/** Normalize a field element, without constant-time guarantee. - * - * Identical in behavior to secp256k1_fe_normalize, but not constant time in r. - */ -static void secp256k1_fe_normalize_var(secp256k1_fe *r); - -/** Determine whether r represents field element 0. - * - * On input, r must be a valid field element. - * Returns whether r = 0 (mod p). - */ -static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r); - -/** Determine whether r represents field element 0, without constant-time guarantee. - * - * Identical in behavior to secp256k1_normalizes_to_zero, but not constant time in r. - */ -static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r); - -/** Set a field element to an integer in range [0,0x7FFF]. - * - * On input, r does not need to be initialized, a must be in [0,0x7FFF]. - * On output, r represents value a, is normalized and has magnitude (a!=0). - */ -static void secp256k1_fe_set_int(secp256k1_fe *r, int a); - -/** Clear a field element to prevent leaking sensitive information. */ -static void secp256k1_fe_clear(secp256k1_fe *a); - -/** Determine whether a represents field element 0. - * - * On input, a must be a valid normalized field element. - * Returns whether a = 0 (mod p). - * - * This behaves identical to secp256k1_normalizes_to_zero{,_var}, but requires - * normalized input (and is much faster). - */ -static int secp256k1_fe_is_zero(const secp256k1_fe *a); - -/** Determine whether a (mod p) is odd. - * - * On input, a must be a valid normalized field element. - * Returns (int(a) mod p) & 1. - */ -static int secp256k1_fe_is_odd(const secp256k1_fe *a); - -/** Determine whether two field elements are equal. - * - * On input, a and b must be valid field elements with magnitudes not exceeding - * 1 and 31, respectively. - * Returns a = b (mod p). - */ -static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b); - -/** Compare the values represented by 2 field elements, without constant-time guarantee. - * - * On input, a and b must be valid normalized field elements. - * Returns 1 if a > b, -1 if a < b, and 0 if a = b (comparisons are done as integers - * in range 0..p-1). - */ -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); - -/** Set a field element equal to the element represented by a provided 32-byte big endian value - * interpreted modulo p. - * - * On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array. - * On output, r = a (mod p). It will have magnitude 1, and not be normalized. - */ -static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a); - -/** Set a field element equal to a provided 32-byte big endian value, checking for overflow. - * - * On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array. - * On output, r = a if (a < p), it will be normalized with magnitude 1, and 1 is returned. - * If a >= p, 0 is returned, and r will be made invalid (and must not be used without overwriting). - */ -static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a); - -/** Convert a field element to 32-byte big endian byte array. - * On input, a must be a valid normalized field element, and r a pointer to a 32-byte array. - * On output, r = a (mod p). - */ -static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a); - -/** Negate a field element. - * - * On input, r does not need to be initialized. a must be a valid field element with - * magnitude not exceeding m. m must be an integer constant expression in [0,31]. - * Performs {r = -a}. - * On output, r will not be normalized, and will have magnitude m+1. - */ -#define secp256k1_fe_negate(r, a, m) ASSERT_INT_CONST_AND_DO(m, secp256k1_fe_negate_unchecked(r, a, m)) - -/** Like secp256k1_fe_negate_unchecked but m is not checked to be an integer constant expression. - * - * Should not be called directly outside of tests. - */ -static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m); - -/** Add a small integer to a field element. - * - * Performs {r += a}. The magnitude of r increases by 1, and normalized is cleared. - * a must be in range [0,0x7FFF]. - */ -static void secp256k1_fe_add_int(secp256k1_fe *r, int a); - -/** Multiply a field element with a small integer. - * - * On input, r must be a valid field element. a must be an integer constant expression in [0,32]. - * The magnitude of r times a must not exceed 32. - * Performs {r *= a}. - * On output, r's magnitude is multiplied by a, and r will not be normalized. - */ -#define secp256k1_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, secp256k1_fe_mul_int_unchecked(r, a)) - -/** Like secp256k1_fe_mul_int but a is not checked to be an integer constant expression. - * - * Should not be called directly outside of tests. - */ -static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a); - -/** Increment a field element by another. - * - * On input, r and a must be valid field elements, not necessarily normalized. - * The sum of their magnitudes must not exceed 32. - * Performs {r += a}. - * On output, r will not be normalized, and will have magnitude incremented by a's. - */ -static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a); - -/** Multiply two field elements. - * - * On input, a and b must be valid field elements; r does not need to be initialized. - * r and a may point to the same object, but neither may point to the object pointed - * to by b. The magnitudes of a and b must not exceed 8. - * Performs {r = a * b} - * On output, r will have magnitude 1, but won't be normalized. - */ -static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); - -/** Square a field element. - * - * On input, a must be a valid field element; r does not need to be initialized. The magnitude - * of a must not exceed 8. - * Performs {r = a**2} - * On output, r will have magnitude 1, but won't be normalized. - */ -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a); - -/** Compute a square root of a field element. - * - * On input, a must be a valid field element with magnitude<=8; r need not be initialized. - * If sqrt(a) exists, performs {r = sqrt(a)} and returns 1. - * Otherwise, sqrt(-a) exists. The function performs {r = sqrt(-a)} and returns 0. - * The resulting value represented by r will be a square itself. - * Variables r and a must not point to the same object. - * On output, r will have magnitude 1 but will not be normalized. - */ -static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a); - -/** Compute the modular inverse of a field element. - * - * On input, a must be a valid field element; r need not be initialized. - * Performs {r = a**(p-2)} (which maps 0 to 0, and every other element to its - * inverse). - * On output, r will have magnitude (a.magnitude != 0) and be normalized. - */ -static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a); - -/** Compute the modular inverse of a field element, without constant-time guarantee. - * - * Behaves identically to secp256k1_fe_inv, but is not constant-time in a. - */ -static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a); - -/** Convert a field element to secp256k1_fe_storage. - * - * On input, a must be a valid normalized field element. - * Performs {r = a}. - */ -static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a); - -/** Convert a field element back from secp256k1_fe_storage. - * - * On input, r need not be initialized. - * Performs {r = a}. - * On output, r will be normalized and will have magnitude 1. - */ -static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ -static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag); - -/** Conditionally move a field element in constant time. - * - * On input, both r and a must be valid field elements. Flag must be 0 or 1. - * Performs {r = flag ? a : r}. - * - * On output, r's magnitude will be the maximum of both input magnitudes. - * It will be normalized if and only if both inputs were normalized. - */ -static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); - -/** Halve the value of a field element modulo the field prime in constant-time. - * - * On input, r must be a valid field element. - * On output, r will be normalized and have magnitude floor(m/2) + 1 where m is - * the magnitude of r on input. - */ -static void secp256k1_fe_half(secp256k1_fe *r); - -/** Sets r to a field element with magnitude m, normalized if (and only if) m==0. - * The value is chosen so that it is likely to trigger edge cases related to - * internal overflows. */ -static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m); - -/** Determine whether a is a square (modulo p). - * - * On input, a must be a valid field element. - */ -static int secp256k1_fe_is_square_var(const secp256k1_fe *a); - -/** Check invariants on a field element (no-op unless VERIFY is enabled). */ -static void secp256k1_fe_verify(const secp256k1_fe *a); -#define SECP256K1_FE_VERIFY(a) secp256k1_fe_verify(a) - -/** Check that magnitude of a is at most m (no-op unless VERIFY is enabled). */ -static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m); -#define SECP256K1_FE_VERIFY_MAGNITUDE(a, m) secp256k1_fe_verify_magnitude(a, m) - -#endif /* SECP256K1_FIELD_H */ diff --git a/external/secp256k1/src/field_10x26.h b/external/secp256k1/src/field_10x26.h deleted file mode 100644 index 203c10167c..0000000000 --- a/external/secp256k1/src/field_10x26.h +++ /dev/null @@ -1,57 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_FIELD_REPR_H -#define SECP256K1_FIELD_REPR_H - -#include - -/** This field implementation represents the value as 10 uint32_t limbs in base - * 2^26. */ -typedef struct { - /* A field element f represents the sum(i=0..9, f.n[i] << (i*26)) mod p, - * where p is the field modulus, 2^256 - 2^32 - 977. - * - * The individual limbs f.n[i] can exceed 2^26; the field's magnitude roughly - * corresponds to how much excess is allowed. The value - * sum(i=0..9, f.n[i] << (i*26)) may exceed p, unless the field element is - * normalized. */ - uint32_t n[10]; - /* - * Magnitude m requires: - * n[i] <= 2 * m * (2^26 - 1) for i=0..8 - * n[9] <= 2 * m * (2^22 - 1) - * - * Normalized requires: - * n[i] <= (2^26 - 1) for i=0..8 - * sum(i=0..9, n[i] << (i*26)) < p - * (together these imply n[9] <= 2^22 - 1) - */ - SECP256K1_FE_VERIFY_FIELDS -} secp256k1_fe; - -/* Unpacks a constant into a overlapping multi-limbed FE element. */ -#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ - (d0) & 0x3FFFFFFUL, \ - (((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \ - (((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \ - (((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \ - (((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \ - (((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \ - (((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \ - (((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \ - (((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \ - (((uint32_t)d7) >> 10) \ -} - -typedef struct { - uint32_t n[8]; -} secp256k1_fe_storage; - -#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} -#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] - -#endif /* SECP256K1_FIELD_REPR_H */ diff --git a/external/secp256k1/src/field_10x26_impl.h b/external/secp256k1/src/field_10x26_impl.h deleted file mode 100644 index ea14c27318..0000000000 --- a/external/secp256k1/src/field_10x26_impl.h +++ /dev/null @@ -1,1232 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_FIELD_REPR_IMPL_H -#define SECP256K1_FIELD_REPR_IMPL_H - -#include "checkmem.h" -#include "util.h" -#include "field.h" -#include "modinv32_impl.h" - -#ifdef VERIFY -static void secp256k1_fe_impl_verify(const secp256k1_fe *a) { - const uint32_t *d = a->n; - int m = a->normalized ? 1 : 2 * a->magnitude; - VERIFY_CHECK(d[0] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[1] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[2] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[3] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[4] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[5] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[6] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[7] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[8] <= 0x3FFFFFFUL * m); - VERIFY_CHECK(d[9] <= 0x03FFFFFUL * m); - if (a->normalized) { - if (d[9] == 0x03FFFFFUL) { - uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2]; - if (mid == 0x3FFFFFFUL) { - VERIFY_CHECK((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL); - } - } - } -} -#endif - -static void secp256k1_fe_impl_get_bounds(secp256k1_fe *r, int m) { - r->n[0] = 0x3FFFFFFUL * 2 * m; - r->n[1] = 0x3FFFFFFUL * 2 * m; - r->n[2] = 0x3FFFFFFUL * 2 * m; - r->n[3] = 0x3FFFFFFUL * 2 * m; - r->n[4] = 0x3FFFFFFUL * 2 * m; - r->n[5] = 0x3FFFFFFUL * 2 * m; - r->n[6] = 0x3FFFFFFUL * 2 * m; - r->n[7] = 0x3FFFFFFUL * 2 * m; - r->n[8] = 0x3FFFFFFUL * 2 * m; - r->n[9] = 0x03FFFFFUL * 2 * m; -} - -static void secp256k1_fe_impl_normalize(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t m; - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) - & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); - - /* Apply the final reduction (for constant-time behaviour, we do it always) */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ - VERIFY_CHECK(t9 >> 22 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t9 &= 0x03FFFFFUL; - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; -} - -static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; -} - -static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t m; - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) - & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); - - if (x) { - t0 += 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; - - /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ - VERIFY_CHECK(t9 >> 22 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t9 &= 0x03FFFFFUL; - } - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; - r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; -} - -static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - uint32_t z0, z1; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; t1 += (x << 6); - t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL; - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; - z0 |= t9; z1 &= t9 ^ 0x3C00000UL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - return (z0 == 0) | (z1 == 0x3FFFFFFUL); -} - -static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r) { - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t z0, z1; - uint32_t x; - - t0 = r->n[0]; - t9 = r->n[9]; - - /* Reduce t9 at the start so there will be at most a single carry from the first pass */ - x = t9 >> 22; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x3D1UL; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - z0 = t0 & 0x3FFFFFFUL; - z1 = z0 ^ 0x3D0UL; - - /* Fast return path should catch the majority of cases */ - if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL)) { - return 0; - } - - t1 = r->n[1]; - t2 = r->n[2]; - t3 = r->n[3]; - t4 = r->n[4]; - t5 = r->n[5]; - t6 = r->n[6]; - t7 = r->n[7]; - t8 = r->n[8]; - - t9 &= 0x03FFFFFUL; - t1 += (x << 6); - - t1 += (t0 >> 26); - t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; - t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; - t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; - t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; - t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; - t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; - t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; - z0 |= t9; z1 &= t9 ^ 0x3C00000UL; - - /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t9 >> 23 == 0); - - return (z0 == 0) | (z1 == 0x3FFFFFFUL); -} - -SECP256K1_INLINE static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a) { - r->n[0] = a; - r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; -} - -SECP256K1_INLINE static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a) { - const uint32_t *t = a->n; - return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0; -} - -SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) { - return a->n[0] & 1; -} - -static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { - int i; - for (i = 9; i >= 0; i--) { - if (a->n[i] > b->n[i]) { - return 1; - } - if (a->n[i] < b->n[i]) { - return -1; - } - } - return 0; -} - -static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a) { - r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24); - r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22); - r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20); - r->n[3] = (uint32_t)((a[22] >> 6) & 0x3) | ((uint32_t)a[21] << 2) | ((uint32_t)a[20] << 10) | ((uint32_t)a[19] << 18); - r->n[4] = (uint32_t)a[18] | ((uint32_t)a[17] << 8) | ((uint32_t)a[16] << 16) | ((uint32_t)(a[15] & 0x3) << 24); - r->n[5] = (uint32_t)((a[15] >> 2) & 0x3f) | ((uint32_t)a[14] << 6) | ((uint32_t)a[13] << 14) | ((uint32_t)(a[12] & 0xf) << 22); - r->n[6] = (uint32_t)((a[12] >> 4) & 0xf) | ((uint32_t)a[11] << 4) | ((uint32_t)a[10] << 12) | ((uint32_t)(a[9] & 0x3f) << 20); - r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18); - r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24); - r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14); -} - -static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a) { - secp256k1_fe_impl_set_b32_mod(r, a); - return !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); -} - -/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) { - r[0] = (a->n[9] >> 14) & 0xff; - r[1] = (a->n[9] >> 6) & 0xff; - r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3); - r[3] = (a->n[8] >> 16) & 0xff; - r[4] = (a->n[8] >> 8) & 0xff; - r[5] = a->n[8] & 0xff; - r[6] = (a->n[7] >> 18) & 0xff; - r[7] = (a->n[7] >> 10) & 0xff; - r[8] = (a->n[7] >> 2) & 0xff; - r[9] = ((a->n[7] & 0x3) << 6) | ((a->n[6] >> 20) & 0x3f); - r[10] = (a->n[6] >> 12) & 0xff; - r[11] = (a->n[6] >> 4) & 0xff; - r[12] = ((a->n[6] & 0xf) << 4) | ((a->n[5] >> 22) & 0xf); - r[13] = (a->n[5] >> 14) & 0xff; - r[14] = (a->n[5] >> 6) & 0xff; - r[15] = ((a->n[5] & 0x3f) << 2) | ((a->n[4] >> 24) & 0x3); - r[16] = (a->n[4] >> 16) & 0xff; - r[17] = (a->n[4] >> 8) & 0xff; - r[18] = a->n[4] & 0xff; - r[19] = (a->n[3] >> 18) & 0xff; - r[20] = (a->n[3] >> 10) & 0xff; - r[21] = (a->n[3] >> 2) & 0xff; - r[22] = ((a->n[3] & 0x3) << 6) | ((a->n[2] >> 20) & 0x3f); - r[23] = (a->n[2] >> 12) & 0xff; - r[24] = (a->n[2] >> 4) & 0xff; - r[25] = ((a->n[2] & 0xf) << 4) | ((a->n[1] >> 22) & 0xf); - r[26] = (a->n[1] >> 14) & 0xff; - r[27] = (a->n[1] >> 6) & 0xff; - r[28] = ((a->n[1] & 0x3f) << 2) | ((a->n[0] >> 24) & 0x3); - r[29] = (a->n[0] >> 16) & 0xff; - r[30] = (a->n[0] >> 8) & 0xff; - r[31] = a->n[0] & 0xff; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) { - /* For all legal values of m (0..31), the following properties hold: */ - VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m); - VERIFY_CHECK(0x3FFFFBFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m); - VERIFY_CHECK(0x3FFFFFFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m); - VERIFY_CHECK(0x03FFFFFUL * 2 * (m + 1) >= 0x03FFFFFUL * 2 * m); - - /* Due to the properties above, the left hand in the subtractions below is never less than - * the right hand. */ - r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0]; - r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1]; - r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2]; - r->n[3] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[3]; - r->n[4] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[4]; - r->n[5] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[5]; - r->n[6] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[6]; - r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7]; - r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8]; - r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a) { - r->n[0] *= a; - r->n[1] *= a; - r->n[2] *= a; - r->n[3] *= a; - r->n[4] *= a; - r->n[5] *= a; - r->n[6] *= a; - r->n[7] *= a; - r->n[8] *= a; - r->n[9] *= a; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a) { - r->n[0] += a->n[0]; - r->n[1] += a->n[1]; - r->n[2] += a->n[2]; - r->n[3] += a->n[3]; - r->n[4] += a->n[4]; - r->n[5] += a->n[5]; - r->n[6] += a->n[6]; - r->n[7] += a->n[7]; - r->n[8] += a->n[8]; - r->n[9] += a->n[9]; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a) { - r->n[0] += a; -} - -#if defined(USE_EXTERNAL_ASM) - -/* External assembler implementation */ -void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); -void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a); - -#else - -#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) - -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) { - uint64_t c, d; - uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; - uint32_t t9, t1, t0, t2, t3, t4, t5, t6, t7; - const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; - - VERIFY_BITS(a[0], 30); - VERIFY_BITS(a[1], 30); - VERIFY_BITS(a[2], 30); - VERIFY_BITS(a[3], 30); - VERIFY_BITS(a[4], 30); - VERIFY_BITS(a[5], 30); - VERIFY_BITS(a[6], 30); - VERIFY_BITS(a[7], 30); - VERIFY_BITS(a[8], 30); - VERIFY_BITS(a[9], 26); - VERIFY_BITS(b[0], 30); - VERIFY_BITS(b[1], 30); - VERIFY_BITS(b[2], 30); - VERIFY_BITS(b[3], 30); - VERIFY_BITS(b[4], 30); - VERIFY_BITS(b[5], 30); - VERIFY_BITS(b[6], 30); - VERIFY_BITS(b[7], 30); - VERIFY_BITS(b[8], 30); - VERIFY_BITS(b[9], 26); - - /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. - * for 0 <= x <= 9, px is a shorthand for sum(a[i]*b[x-i], i=0..x). - * for 9 <= x <= 18, px is a shorthand for sum(a[i]*b[x-i], i=(x-9)..9) - * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. - */ - - d = (uint64_t)a[0] * b[9] - + (uint64_t)a[1] * b[8] - + (uint64_t)a[2] * b[7] - + (uint64_t)a[3] * b[6] - + (uint64_t)a[4] * b[5] - + (uint64_t)a[5] * b[4] - + (uint64_t)a[6] * b[3] - + (uint64_t)a[7] * b[2] - + (uint64_t)a[8] * b[1] - + (uint64_t)a[9] * b[0]; - /* VERIFY_BITS(d, 64); */ - /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - t9 = d & M; d >>= 26; - VERIFY_BITS(t9, 26); - VERIFY_BITS(d, 38); - /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - - c = (uint64_t)a[0] * b[0]; - VERIFY_BITS(c, 60); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ - d += (uint64_t)a[1] * b[9] - + (uint64_t)a[2] * b[8] - + (uint64_t)a[3] * b[7] - + (uint64_t)a[4] * b[6] - + (uint64_t)a[5] * b[5] - + (uint64_t)a[6] * b[4] - + (uint64_t)a[7] * b[3] - + (uint64_t)a[8] * b[2] - + (uint64_t)a[9] * b[1]; - VERIFY_BITS(d, 63); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - u0 = d & M; d >>= 26; c += u0 * R0; - VERIFY_BITS(u0, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 61); - /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - t0 = c & M; c >>= 26; c += u0 * R1; - VERIFY_BITS(t0, 26); - VERIFY_BITS(c, 37); - /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - - c += (uint64_t)a[0] * b[1] - + (uint64_t)a[1] * b[0]; - VERIFY_BITS(c, 62); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ - d += (uint64_t)a[2] * b[9] - + (uint64_t)a[3] * b[8] - + (uint64_t)a[4] * b[7] - + (uint64_t)a[5] * b[6] - + (uint64_t)a[6] * b[5] - + (uint64_t)a[7] * b[4] - + (uint64_t)a[8] * b[3] - + (uint64_t)a[9] * b[2]; - VERIFY_BITS(d, 63); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - u1 = d & M; d >>= 26; c += u1 * R0; - VERIFY_BITS(u1, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - t1 = c & M; c >>= 26; c += u1 * R1; - VERIFY_BITS(t1, 26); - VERIFY_BITS(c, 38); - /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - - c += (uint64_t)a[0] * b[2] - + (uint64_t)a[1] * b[1] - + (uint64_t)a[2] * b[0]; - VERIFY_BITS(c, 62); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - d += (uint64_t)a[3] * b[9] - + (uint64_t)a[4] * b[8] - + (uint64_t)a[5] * b[7] - + (uint64_t)a[6] * b[6] - + (uint64_t)a[7] * b[5] - + (uint64_t)a[8] * b[4] - + (uint64_t)a[9] * b[3]; - VERIFY_BITS(d, 63); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - u2 = d & M; d >>= 26; c += u2 * R0; - VERIFY_BITS(u2, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - t2 = c & M; c >>= 26; c += u2 * R1; - VERIFY_BITS(t2, 26); - VERIFY_BITS(c, 38); - /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[3] - + (uint64_t)a[1] * b[2] - + (uint64_t)a[2] * b[1] - + (uint64_t)a[3] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - d += (uint64_t)a[4] * b[9] - + (uint64_t)a[5] * b[8] - + (uint64_t)a[6] * b[7] - + (uint64_t)a[7] * b[6] - + (uint64_t)a[8] * b[5] - + (uint64_t)a[9] * b[4]; - VERIFY_BITS(d, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - u3 = d & M; d >>= 26; c += u3 * R0; - VERIFY_BITS(u3, 26); - VERIFY_BITS(d, 37); - /* VERIFY_BITS(c, 64); */ - /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - t3 = c & M; c >>= 26; c += u3 * R1; - VERIFY_BITS(t3, 26); - VERIFY_BITS(c, 39); - /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[4] - + (uint64_t)a[1] * b[3] - + (uint64_t)a[2] * b[2] - + (uint64_t)a[3] * b[1] - + (uint64_t)a[4] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[5] * b[9] - + (uint64_t)a[6] * b[8] - + (uint64_t)a[7] * b[7] - + (uint64_t)a[8] * b[6] - + (uint64_t)a[9] * b[5]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - u4 = d & M; d >>= 26; c += u4 * R0; - VERIFY_BITS(u4, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - t4 = c & M; c >>= 26; c += u4 * R1; - VERIFY_BITS(t4, 26); - VERIFY_BITS(c, 39); - /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[5] - + (uint64_t)a[1] * b[4] - + (uint64_t)a[2] * b[3] - + (uint64_t)a[3] * b[2] - + (uint64_t)a[4] * b[1] - + (uint64_t)a[5] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[6] * b[9] - + (uint64_t)a[7] * b[8] - + (uint64_t)a[8] * b[7] - + (uint64_t)a[9] * b[6]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - u5 = d & M; d >>= 26; c += u5 * R0; - VERIFY_BITS(u5, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - t5 = c & M; c >>= 26; c += u5 * R1; - VERIFY_BITS(t5, 26); - VERIFY_BITS(c, 39); - /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[6] - + (uint64_t)a[1] * b[5] - + (uint64_t)a[2] * b[4] - + (uint64_t)a[3] * b[3] - + (uint64_t)a[4] * b[2] - + (uint64_t)a[5] * b[1] - + (uint64_t)a[6] * b[0]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[7] * b[9] - + (uint64_t)a[8] * b[8] - + (uint64_t)a[9] * b[7]; - VERIFY_BITS(d, 61); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - u6 = d & M; d >>= 26; c += u6 * R0; - VERIFY_BITS(u6, 26); - VERIFY_BITS(d, 35); - /* VERIFY_BITS(c, 64); */ - /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - t6 = c & M; c >>= 26; c += u6 * R1; - VERIFY_BITS(t6, 26); - VERIFY_BITS(c, 39); - /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[7] - + (uint64_t)a[1] * b[6] - + (uint64_t)a[2] * b[5] - + (uint64_t)a[3] * b[4] - + (uint64_t)a[4] * b[3] - + (uint64_t)a[5] * b[2] - + (uint64_t)a[6] * b[1] - + (uint64_t)a[7] * b[0]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x8000007C00000007ULL); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[8] * b[9] - + (uint64_t)a[9] * b[8]; - VERIFY_BITS(d, 58); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - u7 = d & M; d >>= 26; c += u7 * R0; - VERIFY_BITS(u7, 26); - VERIFY_BITS(d, 32); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); - /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - t7 = c & M; c >>= 26; c += u7 * R1; - VERIFY_BITS(t7, 26); - VERIFY_BITS(c, 38); - /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)a[0] * b[8] - + (uint64_t)a[1] * b[7] - + (uint64_t)a[2] * b[6] - + (uint64_t)a[3] * b[5] - + (uint64_t)a[4] * b[4] - + (uint64_t)a[5] * b[3] - + (uint64_t)a[6] * b[2] - + (uint64_t)a[7] * b[1] - + (uint64_t)a[8] * b[0]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000007B80000008ULL); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[9] * b[9]; - VERIFY_BITS(d, 57); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - u8 = d & M; d >>= 26; c += u8 * R0; - VERIFY_BITS(u8, 26); - VERIFY_BITS(d, 31); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[3] = t3; - VERIFY_BITS(r[3], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = t4; - VERIFY_BITS(r[4], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[5] = t5; - VERIFY_BITS(r[5], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[6] = t6; - VERIFY_BITS(r[6], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[7] = t7; - VERIFY_BITS(r[7], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[8] = c & M; c >>= 26; c += u8 * R1; - VERIFY_BITS(r[8], 26); - VERIFY_BITS(c, 39); - /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R0 + t9; - VERIFY_BITS(c, 45); - /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); - VERIFY_BITS(r[9], 22); - VERIFY_BITS(c, 46); - /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - d = c * (R0 >> 4) + t0; - VERIFY_BITS(d, 56); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[0] = d & M; d >>= 26; - VERIFY_BITS(r[0], 26); - VERIFY_BITS(d, 30); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += c * (R1 >> 4) + t1; - VERIFY_BITS(d, 53); - VERIFY_CHECK(d <= 0x10000003FFFFBFULL); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[1] = d & M; d >>= 26; - VERIFY_BITS(r[1], 26); - VERIFY_BITS(d, 27); - VERIFY_CHECK(d <= 0x4000000ULL); - /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += t2; - VERIFY_BITS(d, 27); - /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = d; - VERIFY_BITS(r[2], 27); - /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a) { - uint64_t c, d; - uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; - uint32_t t9, t0, t1, t2, t3, t4, t5, t6, t7; - const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; - - VERIFY_BITS(a[0], 30); - VERIFY_BITS(a[1], 30); - VERIFY_BITS(a[2], 30); - VERIFY_BITS(a[3], 30); - VERIFY_BITS(a[4], 30); - VERIFY_BITS(a[5], 30); - VERIFY_BITS(a[6], 30); - VERIFY_BITS(a[7], 30); - VERIFY_BITS(a[8], 30); - VERIFY_BITS(a[9], 26); - - /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. - * px is a shorthand for sum(a[i]*a[x-i], i=0..x). - * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. - */ - - d = (uint64_t)(a[0]*2) * a[9] - + (uint64_t)(a[1]*2) * a[8] - + (uint64_t)(a[2]*2) * a[7] - + (uint64_t)(a[3]*2) * a[6] - + (uint64_t)(a[4]*2) * a[5]; - /* VERIFY_BITS(d, 64); */ - /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - t9 = d & M; d >>= 26; - VERIFY_BITS(t9, 26); - VERIFY_BITS(d, 38); - /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ - - c = (uint64_t)a[0] * a[0]; - VERIFY_BITS(c, 60); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ - d += (uint64_t)(a[1]*2) * a[9] - + (uint64_t)(a[2]*2) * a[8] - + (uint64_t)(a[3]*2) * a[7] - + (uint64_t)(a[4]*2) * a[6] - + (uint64_t)a[5] * a[5]; - VERIFY_BITS(d, 63); - /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - u0 = d & M; d >>= 26; c += u0 * R0; - VERIFY_BITS(u0, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 61); - /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - t0 = c & M; c >>= 26; c += u0 * R1; - VERIFY_BITS(t0, 26); - VERIFY_BITS(c, 37); - /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ - - c += (uint64_t)(a[0]*2) * a[1]; - VERIFY_BITS(c, 62); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ - d += (uint64_t)(a[2]*2) * a[9] - + (uint64_t)(a[3]*2) * a[8] - + (uint64_t)(a[4]*2) * a[7] - + (uint64_t)(a[5]*2) * a[6]; - VERIFY_BITS(d, 63); - /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - u1 = d & M; d >>= 26; c += u1 * R0; - VERIFY_BITS(u1, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - t1 = c & M; c >>= 26; c += u1 * R1; - VERIFY_BITS(t1, 26); - VERIFY_BITS(c, 38); - /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[2] - + (uint64_t)a[1] * a[1]; - VERIFY_BITS(c, 62); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - d += (uint64_t)(a[3]*2) * a[9] - + (uint64_t)(a[4]*2) * a[8] - + (uint64_t)(a[5]*2) * a[7] - + (uint64_t)a[6] * a[6]; - VERIFY_BITS(d, 63); - /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - u2 = d & M; d >>= 26; c += u2 * R0; - VERIFY_BITS(u2, 26); - VERIFY_BITS(d, 37); - VERIFY_BITS(c, 63); - /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - t2 = c & M; c >>= 26; c += u2 * R1; - VERIFY_BITS(t2, 26); - VERIFY_BITS(c, 38); - /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[3] - + (uint64_t)(a[1]*2) * a[2]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - d += (uint64_t)(a[4]*2) * a[9] - + (uint64_t)(a[5]*2) * a[8] - + (uint64_t)(a[6]*2) * a[7]; - VERIFY_BITS(d, 63); - /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - u3 = d & M; d >>= 26; c += u3 * R0; - VERIFY_BITS(u3, 26); - VERIFY_BITS(d, 37); - /* VERIFY_BITS(c, 64); */ - /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - t3 = c & M; c >>= 26; c += u3 * R1; - VERIFY_BITS(t3, 26); - VERIFY_BITS(c, 39); - /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[4] - + (uint64_t)(a[1]*2) * a[3] - + (uint64_t)a[2] * a[2]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[5]*2) * a[9] - + (uint64_t)(a[6]*2) * a[8] - + (uint64_t)a[7] * a[7]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - u4 = d & M; d >>= 26; c += u4 * R0; - VERIFY_BITS(u4, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - t4 = c & M; c >>= 26; c += u4 * R1; - VERIFY_BITS(t4, 26); - VERIFY_BITS(c, 39); - /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[5] - + (uint64_t)(a[1]*2) * a[4] - + (uint64_t)(a[2]*2) * a[3]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[6]*2) * a[9] - + (uint64_t)(a[7]*2) * a[8]; - VERIFY_BITS(d, 62); - /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - u5 = d & M; d >>= 26; c += u5 * R0; - VERIFY_BITS(u5, 26); - VERIFY_BITS(d, 36); - /* VERIFY_BITS(c, 64); */ - /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - t5 = c & M; c >>= 26; c += u5 * R1; - VERIFY_BITS(t5, 26); - VERIFY_BITS(c, 39); - /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[6] - + (uint64_t)(a[1]*2) * a[5] - + (uint64_t)(a[2]*2) * a[4] - + (uint64_t)a[3] * a[3]; - VERIFY_BITS(c, 63); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[7]*2) * a[9] - + (uint64_t)a[8] * a[8]; - VERIFY_BITS(d, 61); - /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - u6 = d & M; d >>= 26; c += u6 * R0; - VERIFY_BITS(u6, 26); - VERIFY_BITS(d, 35); - /* VERIFY_BITS(c, 64); */ - /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - t6 = c & M; c >>= 26; c += u6 * R1; - VERIFY_BITS(t6, 26); - VERIFY_BITS(c, 39); - /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[7] - + (uint64_t)(a[1]*2) * a[6] - + (uint64_t)(a[2]*2) * a[5] - + (uint64_t)(a[3]*2) * a[4]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x8000007C00000007ULL); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)(a[8]*2) * a[9]; - VERIFY_BITS(d, 58); - /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - u7 = d & M; d >>= 26; c += u7 * R0; - VERIFY_BITS(u7, 26); - VERIFY_BITS(d, 32); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); - /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - t7 = c & M; c >>= 26; c += u7 * R1; - VERIFY_BITS(t7, 26); - VERIFY_BITS(c, 38); - /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ - - c += (uint64_t)(a[0]*2) * a[8] - + (uint64_t)(a[1]*2) * a[7] - + (uint64_t)(a[2]*2) * a[6] - + (uint64_t)(a[3]*2) * a[5] - + (uint64_t)a[4] * a[4]; - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000007B80000008ULL); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += (uint64_t)a[9] * a[9]; - VERIFY_BITS(d, 57); - /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - u8 = d & M; d >>= 26; c += u8 * R0; - VERIFY_BITS(u8, 26); - VERIFY_BITS(d, 31); - /* VERIFY_BITS(c, 64); */ - VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[3] = t3; - VERIFY_BITS(r[3], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = t4; - VERIFY_BITS(r[4], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[5] = t5; - VERIFY_BITS(r[5], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[6] = t6; - VERIFY_BITS(r[6], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[7] = t7; - VERIFY_BITS(r[7], 26); - /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[8] = c & M; c >>= 26; c += u8 * R1; - VERIFY_BITS(r[8], 26); - VERIFY_BITS(c, 39); - /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - c += d * R0 + t9; - VERIFY_BITS(c, 45); - /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); - VERIFY_BITS(r[9], 22); - VERIFY_BITS(c, 46); - /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - d = c * (R0 >> 4) + t0; - VERIFY_BITS(d, 56); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[0] = d & M; d >>= 26; - VERIFY_BITS(r[0], 26); - VERIFY_BITS(d, 30); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += c * (R1 >> 4) + t1; - VERIFY_BITS(d, 53); - VERIFY_CHECK(d <= 0x10000003FFFFBFULL); - /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[1] = d & M; d >>= 26; - VERIFY_BITS(r[1], 26); - VERIFY_BITS(d, 27); - VERIFY_CHECK(d <= 0x4000000ULL); - /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - d += t2; - VERIFY_BITS(d, 27); - /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = d; - VERIFY_BITS(r[2], 27); - /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} -#endif - -SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { - secp256k1_fe_mul_inner(r->n, a->n, b->n); -} - -SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) { - secp256k1_fe_sqr_inner(r->n, a->n); -} - -SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { - uint32_t mask0, mask1; - volatile int vflag = flag; - SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); - mask0 = vflag + ~((uint32_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); - r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); - r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); - r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); - r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1); - r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1); -} - -static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) { - uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], - t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; - uint32_t one = (uint32_t)1; - uint32_t mask = -(t0 & one) >> 6; - - /* Bounds analysis (over the rationals). - * - * Let m = r->magnitude - * C = 0x3FFFFFFUL * 2 - * D = 0x03FFFFFUL * 2 - * - * Initial bounds: t0..t8 <= C * m - * t9 <= D * m - */ - - t0 += 0x3FFFC2FUL & mask; - t1 += 0x3FFFFBFUL & mask; - t2 += mask; - t3 += mask; - t4 += mask; - t5 += mask; - t6 += mask; - t7 += mask; - t8 += mask; - t9 += mask >> 4; - - VERIFY_CHECK((t0 & one) == 0); - - /* t0..t8: added <= C/2 - * t9: added <= D/2 - * - * Current bounds: t0..t8 <= C * (m + 1/2) - * t9 <= D * (m + 1/2) - */ - - r->n[0] = (t0 >> 1) + ((t1 & one) << 25); - r->n[1] = (t1 >> 1) + ((t2 & one) << 25); - r->n[2] = (t2 >> 1) + ((t3 & one) << 25); - r->n[3] = (t3 >> 1) + ((t4 & one) << 25); - r->n[4] = (t4 >> 1) + ((t5 & one) << 25); - r->n[5] = (t5 >> 1) + ((t6 & one) << 25); - r->n[6] = (t6 >> 1) + ((t7 & one) << 25); - r->n[7] = (t7 >> 1) + ((t8 & one) << 25); - r->n[8] = (t8 >> 1) + ((t9 & one) << 25); - r->n[9] = (t9 >> 1); - - /* t0..t8: shifted right and added <= C/4 + 1/2 - * t9: shifted right - * - * Current bounds: t0..t8 <= C * (m/2 + 1/2) - * t9 <= D * (m/2 + 1/4) - * - * Therefore the output magnitude (M) has to be set such that: - * t0..t8: C * M >= C * (m/2 + 1/2) - * t9: D * M >= D * (m/2 + 1/4) - * - * It suffices for all limbs that, for any input magnitude m: - * M >= m/2 + 1/2 - * - * and since we want the smallest such integer value for M: - * M == floor(m/2) + 1 - */ -} - -static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { - uint32_t mask0, mask1; - volatile int vflag = flag; - SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); - mask0 = vflag + ~((uint32_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); - r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); - r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); - r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); -} - -static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { - r->n[0] = a->n[0] | a->n[1] << 26; - r->n[1] = a->n[1] >> 6 | a->n[2] << 20; - r->n[2] = a->n[2] >> 12 | a->n[3] << 14; - r->n[3] = a->n[3] >> 18 | a->n[4] << 8; - r->n[4] = a->n[4] >> 24 | a->n[5] << 2 | a->n[6] << 28; - r->n[5] = a->n[6] >> 4 | a->n[7] << 22; - r->n[6] = a->n[7] >> 10 | a->n[8] << 16; - r->n[7] = a->n[8] >> 16 | a->n[9] << 10; -} - -static SECP256K1_INLINE void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { - r->n[0] = a->n[0] & 0x3FFFFFFUL; - r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL); - r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL); - r->n[3] = a->n[2] >> 14 | ((a->n[3] << 18) & 0x3FFFFFFUL); - r->n[4] = a->n[3] >> 8 | ((a->n[4] << 24) & 0x3FFFFFFUL); - r->n[5] = (a->n[4] >> 2) & 0x3FFFFFFUL; - r->n[6] = a->n[4] >> 28 | ((a->n[5] << 4) & 0x3FFFFFFUL); - r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL); - r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL); - r->n[9] = a->n[7] >> 10; -} - -static void secp256k1_fe_from_signed30(secp256k1_fe *r, const secp256k1_modinv32_signed30 *a) { - const uint32_t M26 = UINT32_MAX >> 6; - const uint32_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4], - a5 = a->v[5], a6 = a->v[6], a7 = a->v[7], a8 = a->v[8]; - - /* The output from secp256k1_modinv32{_var} should be normalized to range [0,modulus), and - * have limbs in [0,2^30). The modulus is < 2^256, so the top limb must be below 2^(256-30*8). - */ - VERIFY_CHECK(a0 >> 30 == 0); - VERIFY_CHECK(a1 >> 30 == 0); - VERIFY_CHECK(a2 >> 30 == 0); - VERIFY_CHECK(a3 >> 30 == 0); - VERIFY_CHECK(a4 >> 30 == 0); - VERIFY_CHECK(a5 >> 30 == 0); - VERIFY_CHECK(a6 >> 30 == 0); - VERIFY_CHECK(a7 >> 30 == 0); - VERIFY_CHECK(a8 >> 16 == 0); - - r->n[0] = a0 & M26; - r->n[1] = (a0 >> 26 | a1 << 4) & M26; - r->n[2] = (a1 >> 22 | a2 << 8) & M26; - r->n[3] = (a2 >> 18 | a3 << 12) & M26; - r->n[4] = (a3 >> 14 | a4 << 16) & M26; - r->n[5] = (a4 >> 10 | a5 << 20) & M26; - r->n[6] = (a5 >> 6 | a6 << 24) & M26; - r->n[7] = (a6 >> 2 ) & M26; - r->n[8] = (a6 >> 28 | a7 << 2) & M26; - r->n[9] = (a7 >> 24 | a8 << 6); -} - -static void secp256k1_fe_to_signed30(secp256k1_modinv32_signed30 *r, const secp256k1_fe *a) { - const uint32_t M30 = UINT32_MAX >> 2; - const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4], - a5 = a->n[5], a6 = a->n[6], a7 = a->n[7], a8 = a->n[8], a9 = a->n[9]; - - r->v[0] = (a0 | a1 << 26) & M30; - r->v[1] = (a1 >> 4 | a2 << 22) & M30; - r->v[2] = (a2 >> 8 | a3 << 18) & M30; - r->v[3] = (a3 >> 12 | a4 << 14) & M30; - r->v[4] = (a4 >> 16 | a5 << 10) & M30; - r->v[5] = (a5 >> 20 | a6 << 6) & M30; - r->v[6] = (a6 >> 24 | a7 << 2 - | a8 << 28) & M30; - r->v[7] = (a8 >> 2 | a9 << 24) & M30; - r->v[8] = a9 >> 6; -} - -static const secp256k1_modinv32_modinfo secp256k1_const_modinfo_fe = { - {{-0x3D1, -4, 0, 0, 0, 0, 0, 0, 65536}}, - 0x2DDACACFL -}; - -static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x) { - secp256k1_fe tmp = *x; - secp256k1_modinv32_signed30 s; - - secp256k1_fe_normalize(&tmp); - secp256k1_fe_to_signed30(&s, &tmp); - secp256k1_modinv32(&s, &secp256k1_const_modinfo_fe); - secp256k1_fe_from_signed30(r, &s); -} - -static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x) { - secp256k1_fe tmp = *x; - secp256k1_modinv32_signed30 s; - - secp256k1_fe_normalize_var(&tmp); - secp256k1_fe_to_signed30(&s, &tmp); - secp256k1_modinv32_var(&s, &secp256k1_const_modinfo_fe); - secp256k1_fe_from_signed30(r, &s); -} - -static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x) { - secp256k1_fe tmp; - secp256k1_modinv32_signed30 s; - int jac, ret; - - tmp = *x; - secp256k1_fe_normalize_var(&tmp); - /* secp256k1_jacobi32_maybe_var cannot deal with input 0. */ - if (secp256k1_fe_is_zero(&tmp)) return 1; - secp256k1_fe_to_signed30(&s, &tmp); - jac = secp256k1_jacobi32_maybe_var(&s, &secp256k1_const_modinfo_fe); - if (jac == 0) { - /* secp256k1_jacobi32_maybe_var failed to compute the Jacobi symbol. Fall back - * to computing a square root. This should be extremely rare with random - * input (except in VERIFY mode, where a lower iteration count is used). */ - secp256k1_fe dummy; - ret = secp256k1_fe_sqrt(&dummy, &tmp); - } else { - ret = jac >= 0; - } - return ret; -} - -#endif /* SECP256K1_FIELD_REPR_IMPL_H */ diff --git a/external/secp256k1/src/field_5x52.h b/external/secp256k1/src/field_5x52.h deleted file mode 100644 index f20c246fdd..0000000000 --- a/external/secp256k1/src/field_5x52.h +++ /dev/null @@ -1,62 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_FIELD_REPR_H -#define SECP256K1_FIELD_REPR_H - -#include - -/** This field implementation represents the value as 5 uint64_t limbs in base - * 2^52. */ -typedef struct { - /* A field element f represents the sum(i=0..4, f.n[i] << (i*52)) mod p, - * where p is the field modulus, 2^256 - 2^32 - 977. - * - * The individual limbs f.n[i] can exceed 2^52; the field's magnitude roughly - * corresponds to how much excess is allowed. The value - * sum(i=0..4, f.n[i] << (i*52)) may exceed p, unless the field element is - * normalized. */ - uint64_t n[5]; - /* - * Magnitude m requires: - * n[i] <= 2 * m * (2^52 - 1) for i=0..3 - * n[4] <= 2 * m * (2^48 - 1) - * - * Normalized requires: - * n[i] <= (2^52 - 1) for i=0..3 - * sum(i=0..4, n[i] << (i*52)) < p - * (together these imply n[4] <= 2^48 - 1) - */ - SECP256K1_FE_VERIFY_FIELDS -} secp256k1_fe; - -/* Unpacks a constant into a overlapping multi-limbed FE element. */ -#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ - (d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \ - ((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \ - ((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \ - ((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \ - ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \ -} - -typedef struct { - uint64_t n[4]; -} secp256k1_fe_storage; - -#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ - (d0) | (((uint64_t)(d1)) << 32), \ - (d2) | (((uint64_t)(d3)) << 32), \ - (d4) | (((uint64_t)(d5)) << 32), \ - (d6) | (((uint64_t)(d7)) << 32) \ -}} - -#define SECP256K1_FE_STORAGE_CONST_GET(d) \ - (uint32_t)(d.n[3] >> 32), (uint32_t)d.n[3], \ - (uint32_t)(d.n[2] >> 32), (uint32_t)d.n[2], \ - (uint32_t)(d.n[1] >> 32), (uint32_t)d.n[1], \ - (uint32_t)(d.n[0] >> 32), (uint32_t)d.n[0] - -#endif /* SECP256K1_FIELD_REPR_H */ diff --git a/external/secp256k1/src/field_5x52_impl.h b/external/secp256k1/src/field_5x52_impl.h deleted file mode 100644 index 46dca6b981..0000000000 --- a/external/secp256k1/src/field_5x52_impl.h +++ /dev/null @@ -1,522 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_FIELD_REPR_IMPL_H -#define SECP256K1_FIELD_REPR_IMPL_H - -#include "checkmem.h" -#include "util.h" -#include "field.h" -#include "modinv64_impl.h" - -#include "field_5x52_int128_impl.h" - -#ifdef VERIFY -static void secp256k1_fe_impl_verify(const secp256k1_fe *a) { - const uint64_t *d = a->n; - int m = a->normalized ? 1 : 2 * a->magnitude; - /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ - VERIFY_CHECK(d[0] <= 0xFFFFFFFFFFFFFULL * m); - VERIFY_CHECK(d[1] <= 0xFFFFFFFFFFFFFULL * m); - VERIFY_CHECK(d[2] <= 0xFFFFFFFFFFFFFULL * m); - VERIFY_CHECK(d[3] <= 0xFFFFFFFFFFFFFULL * m); - VERIFY_CHECK(d[4] <= 0x0FFFFFFFFFFFFULL * m); - if (a->normalized) { - if ((d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { - VERIFY_CHECK(d[0] < 0xFFFFEFFFFFC2FULL); - } - } -} -#endif - -static void secp256k1_fe_impl_get_bounds(secp256k1_fe *r, int m) { - r->n[0] = 0xFFFFFFFFFFFFFULL * 2 * m; - r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * m; - r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * m; - r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * m; - r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * m; -} - -static void secp256k1_fe_impl_normalize(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t m; - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) - & (t0 >= 0xFFFFEFFFFFC2FULL)); - - /* Apply the final reduction (for constant-time behaviour, we do it always) */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ - VERIFY_CHECK(t4 >> 48 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t4 &= 0x0FFFFFFFFFFFFULL; - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; -} - -static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; -} - -static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t m; - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - /* At most a single final reduction is needed; check if the value is >= the field characteristic */ - x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) - & (t0 >= 0xFFFFEFFFFFC2FULL)); - - if (x) { - t0 += 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; - - /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ - VERIFY_CHECK(t4 >> 48 == x); - - /* Mask off the possible multiple of 2^256 from the final reduction */ - t4 &= 0x0FFFFFFFFFFFFULL; - } - - r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; -} - -static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - uint64_t z0, z1; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL; - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; - z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); -} - -static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r) { - uint64_t t0, t1, t2, t3, t4; - uint64_t z0, z1; - uint64_t x; - - t0 = r->n[0]; - t4 = r->n[4]; - - /* Reduce t4 at the start so there will be at most a single carry from the first pass */ - x = t4 >> 48; - - /* The first pass ensures the magnitude is 1, ... */ - t0 += x * 0x1000003D1ULL; - - /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ - z0 = t0 & 0xFFFFFFFFFFFFFULL; - z1 = z0 ^ 0x1000003D0ULL; - - /* Fast return path should catch the majority of cases */ - if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) { - return 0; - } - - t1 = r->n[1]; - t2 = r->n[2]; - t3 = r->n[3]; - - t4 &= 0x0FFFFFFFFFFFFULL; - - t1 += (t0 >> 52); - t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; - t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; - t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; - z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; - - /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ - VERIFY_CHECK(t4 >> 49 == 0); - - return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); -} - -SECP256K1_INLINE static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a) { - r->n[0] = a; - r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; -} - -SECP256K1_INLINE static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a) { - const uint64_t *t = a->n; - return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; -} - -SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) { - return a->n[0] & 1; -} - -static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { - int i; - for (i = 4; i >= 0; i--) { - if (a->n[i] > b->n[i]) { - return 1; - } - if (a->n[i] < b->n[i]) { - return -1; - } - } - return 0; -} - -static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a) { - r->n[0] = (uint64_t)a[31] - | ((uint64_t)a[30] << 8) - | ((uint64_t)a[29] << 16) - | ((uint64_t)a[28] << 24) - | ((uint64_t)a[27] << 32) - | ((uint64_t)a[26] << 40) - | ((uint64_t)(a[25] & 0xF) << 48); - r->n[1] = (uint64_t)((a[25] >> 4) & 0xF) - | ((uint64_t)a[24] << 4) - | ((uint64_t)a[23] << 12) - | ((uint64_t)a[22] << 20) - | ((uint64_t)a[21] << 28) - | ((uint64_t)a[20] << 36) - | ((uint64_t)a[19] << 44); - r->n[2] = (uint64_t)a[18] - | ((uint64_t)a[17] << 8) - | ((uint64_t)a[16] << 16) - | ((uint64_t)a[15] << 24) - | ((uint64_t)a[14] << 32) - | ((uint64_t)a[13] << 40) - | ((uint64_t)(a[12] & 0xF) << 48); - r->n[3] = (uint64_t)((a[12] >> 4) & 0xF) - | ((uint64_t)a[11] << 4) - | ((uint64_t)a[10] << 12) - | ((uint64_t)a[9] << 20) - | ((uint64_t)a[8] << 28) - | ((uint64_t)a[7] << 36) - | ((uint64_t)a[6] << 44); - r->n[4] = (uint64_t)a[5] - | ((uint64_t)a[4] << 8) - | ((uint64_t)a[3] << 16) - | ((uint64_t)a[2] << 24) - | ((uint64_t)a[1] << 32) - | ((uint64_t)a[0] << 40); -} - -static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a) { - secp256k1_fe_impl_set_b32_mod(r, a); - return !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL)); -} - -/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) { - r[0] = (a->n[4] >> 40) & 0xFF; - r[1] = (a->n[4] >> 32) & 0xFF; - r[2] = (a->n[4] >> 24) & 0xFF; - r[3] = (a->n[4] >> 16) & 0xFF; - r[4] = (a->n[4] >> 8) & 0xFF; - r[5] = a->n[4] & 0xFF; - r[6] = (a->n[3] >> 44) & 0xFF; - r[7] = (a->n[3] >> 36) & 0xFF; - r[8] = (a->n[3] >> 28) & 0xFF; - r[9] = (a->n[3] >> 20) & 0xFF; - r[10] = (a->n[3] >> 12) & 0xFF; - r[11] = (a->n[3] >> 4) & 0xFF; - r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4); - r[13] = (a->n[2] >> 40) & 0xFF; - r[14] = (a->n[2] >> 32) & 0xFF; - r[15] = (a->n[2] >> 24) & 0xFF; - r[16] = (a->n[2] >> 16) & 0xFF; - r[17] = (a->n[2] >> 8) & 0xFF; - r[18] = a->n[2] & 0xFF; - r[19] = (a->n[1] >> 44) & 0xFF; - r[20] = (a->n[1] >> 36) & 0xFF; - r[21] = (a->n[1] >> 28) & 0xFF; - r[22] = (a->n[1] >> 20) & 0xFF; - r[23] = (a->n[1] >> 12) & 0xFF; - r[24] = (a->n[1] >> 4) & 0xFF; - r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4); - r[26] = (a->n[0] >> 40) & 0xFF; - r[27] = (a->n[0] >> 32) & 0xFF; - r[28] = (a->n[0] >> 24) & 0xFF; - r[29] = (a->n[0] >> 16) & 0xFF; - r[30] = (a->n[0] >> 8) & 0xFF; - r[31] = a->n[0] & 0xFF; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) { - /* For all legal values of m (0..31), the following properties hold: */ - VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m); - VERIFY_CHECK(0xFFFFFFFFFFFFFULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m); - VERIFY_CHECK(0x0FFFFFFFFFFFFULL * 2 * (m + 1) >= 0x0FFFFFFFFFFFFULL * 2 * m); - - /* Due to the properties above, the left hand in the subtractions below is never less than - * the right hand. */ - r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; - r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; - r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2]; - r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3]; - r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a) { - r->n[0] *= a; - r->n[1] *= a; - r->n[2] *= a; - r->n[3] *= a; - r->n[4] *= a; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a) { - r->n[0] += a; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a) { - r->n[0] += a->n[0]; - r->n[1] += a->n[1]; - r->n[2] += a->n[2]; - r->n[3] += a->n[3]; - r->n[4] += a->n[4]; -} - -SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { - secp256k1_fe_mul_inner(r->n, a->n, b->n); -} - -SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) { - secp256k1_fe_sqr_inner(r->n, a->n); -} - -SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { - uint64_t mask0, mask1; - volatile int vflag = flag; - SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); - mask0 = vflag + ~((uint64_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); - r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); -} - -static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) { - uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; - uint64_t one = (uint64_t)1; - uint64_t mask = -(t0 & one) >> 12; - - /* Bounds analysis (over the rationals). - * - * Let m = r->magnitude - * C = 0xFFFFFFFFFFFFFULL * 2 - * D = 0x0FFFFFFFFFFFFULL * 2 - * - * Initial bounds: t0..t3 <= C * m - * t4 <= D * m - */ - - t0 += 0xFFFFEFFFFFC2FULL & mask; - t1 += mask; - t2 += mask; - t3 += mask; - t4 += mask >> 4; - - VERIFY_CHECK((t0 & one) == 0); - - /* t0..t3: added <= C/2 - * t4: added <= D/2 - * - * Current bounds: t0..t3 <= C * (m + 1/2) - * t4 <= D * (m + 1/2) - */ - - r->n[0] = (t0 >> 1) + ((t1 & one) << 51); - r->n[1] = (t1 >> 1) + ((t2 & one) << 51); - r->n[2] = (t2 >> 1) + ((t3 & one) << 51); - r->n[3] = (t3 >> 1) + ((t4 & one) << 51); - r->n[4] = (t4 >> 1); - - /* t0..t3: shifted right and added <= C/4 + 1/2 - * t4: shifted right - * - * Current bounds: t0..t3 <= C * (m/2 + 1/2) - * t4 <= D * (m/2 + 1/4) - * - * Therefore the output magnitude (M) has to be set such that: - * t0..t3: C * M >= C * (m/2 + 1/2) - * t4: D * M >= D * (m/2 + 1/4) - * - * It suffices for all limbs that, for any input magnitude m: - * M >= m/2 + 1/2 - * - * and since we want the smallest such integer value for M: - * M == floor(m/2) + 1 - */ -} - -static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { - uint64_t mask0, mask1; - volatile int vflag = flag; - SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); - mask0 = vflag + ~((uint64_t)0); - mask1 = ~mask0; - r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); - r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); - r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); - r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); -} - -static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { - r->n[0] = a->n[0] | a->n[1] << 52; - r->n[1] = a->n[1] >> 12 | a->n[2] << 40; - r->n[2] = a->n[2] >> 24 | a->n[3] << 28; - r->n[3] = a->n[3] >> 36 | a->n[4] << 16; -} - -static SECP256K1_INLINE void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { - r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL; - r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL); - r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL); - r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL); - r->n[4] = a->n[3] >> 16; -} - -static void secp256k1_fe_from_signed62(secp256k1_fe *r, const secp256k1_modinv64_signed62 *a) { - const uint64_t M52 = UINT64_MAX >> 12; - const uint64_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4]; - - /* The output from secp256k1_modinv64{_var} should be normalized to range [0,modulus), and - * have limbs in [0,2^62). The modulus is < 2^256, so the top limb must be below 2^(256-62*4). - */ - VERIFY_CHECK(a0 >> 62 == 0); - VERIFY_CHECK(a1 >> 62 == 0); - VERIFY_CHECK(a2 >> 62 == 0); - VERIFY_CHECK(a3 >> 62 == 0); - VERIFY_CHECK(a4 >> 8 == 0); - - r->n[0] = a0 & M52; - r->n[1] = (a0 >> 52 | a1 << 10) & M52; - r->n[2] = (a1 >> 42 | a2 << 20) & M52; - r->n[3] = (a2 >> 32 | a3 << 30) & M52; - r->n[4] = (a3 >> 22 | a4 << 40); -} - -static void secp256k1_fe_to_signed62(secp256k1_modinv64_signed62 *r, const secp256k1_fe *a) { - const uint64_t M62 = UINT64_MAX >> 2; - const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4]; - - r->v[0] = (a0 | a1 << 52) & M62; - r->v[1] = (a1 >> 10 | a2 << 42) & M62; - r->v[2] = (a2 >> 20 | a3 << 32) & M62; - r->v[3] = (a3 >> 30 | a4 << 22) & M62; - r->v[4] = a4 >> 40; -} - -static const secp256k1_modinv64_modinfo secp256k1_const_modinfo_fe = { - {{-0x1000003D1LL, 0, 0, 0, 256}}, - 0x27C7F6E22DDACACFLL -}; - -static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x) { - secp256k1_fe tmp = *x; - secp256k1_modinv64_signed62 s; - - secp256k1_fe_normalize(&tmp); - secp256k1_fe_to_signed62(&s, &tmp); - secp256k1_modinv64(&s, &secp256k1_const_modinfo_fe); - secp256k1_fe_from_signed62(r, &s); -} - -static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x) { - secp256k1_fe tmp = *x; - secp256k1_modinv64_signed62 s; - - secp256k1_fe_normalize_var(&tmp); - secp256k1_fe_to_signed62(&s, &tmp); - secp256k1_modinv64_var(&s, &secp256k1_const_modinfo_fe); - secp256k1_fe_from_signed62(r, &s); -} - -static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x) { - secp256k1_fe tmp; - secp256k1_modinv64_signed62 s; - int jac, ret; - - tmp = *x; - secp256k1_fe_normalize_var(&tmp); - /* secp256k1_jacobi64_maybe_var cannot deal with input 0. */ - if (secp256k1_fe_is_zero(&tmp)) return 1; - secp256k1_fe_to_signed62(&s, &tmp); - jac = secp256k1_jacobi64_maybe_var(&s, &secp256k1_const_modinfo_fe); - if (jac == 0) { - /* secp256k1_jacobi64_maybe_var failed to compute the Jacobi symbol. Fall back - * to computing a square root. This should be extremely rare with random - * input (except in VERIFY mode, where a lower iteration count is used). */ - secp256k1_fe dummy; - ret = secp256k1_fe_sqrt(&dummy, &tmp); - } else { - ret = jac >= 0; - } - return ret; -} - -#endif /* SECP256K1_FIELD_REPR_IMPL_H */ diff --git a/external/secp256k1/src/field_5x52_int128_impl.h b/external/secp256k1/src/field_5x52_int128_impl.h deleted file mode 100644 index f23f8ee1c4..0000000000 --- a/external/secp256k1/src/field_5x52_int128_impl.h +++ /dev/null @@ -1,274 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H -#define SECP256K1_FIELD_INNER5X52_IMPL_H - -#include - -#include "int128.h" -#include "util.h" - -#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) -#define VERIFY_BITS_128(x, n) VERIFY_CHECK(secp256k1_u128_check_bits((x), (n))) - -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { - secp256k1_uint128 c, d; - uint64_t t3, t4, tx, u0; - uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; - const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; - - VERIFY_BITS(a[0], 56); - VERIFY_BITS(a[1], 56); - VERIFY_BITS(a[2], 56); - VERIFY_BITS(a[3], 56); - VERIFY_BITS(a[4], 52); - VERIFY_BITS(b[0], 56); - VERIFY_BITS(b[1], 56); - VERIFY_BITS(b[2], 56); - VERIFY_BITS(b[3], 56); - VERIFY_BITS(b[4], 52); - VERIFY_CHECK(r != b); - VERIFY_CHECK(a != b); - - /* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. - * for 0 <= x <= 4, px is a shorthand for sum(a[i]*b[x-i], i=0..x). - * for 4 <= x <= 8, px is a shorthand for sum(a[i]*b[x-i], i=(x-4)..4) - * Note that [x 0 0 0 0 0] = [x*R]. - */ - - secp256k1_u128_mul(&d, a0, b[3]); - secp256k1_u128_accum_mul(&d, a1, b[2]); - secp256k1_u128_accum_mul(&d, a2, b[1]); - secp256k1_u128_accum_mul(&d, a3, b[0]); - VERIFY_BITS_128(&d, 114); - /* [d 0 0 0] = [p3 0 0 0] */ - secp256k1_u128_mul(&c, a4, b[4]); - VERIFY_BITS_128(&c, 112); - /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - secp256k1_u128_accum_mul(&d, R, secp256k1_u128_to_u64(&c)); secp256k1_u128_rshift(&c, 64); - VERIFY_BITS_128(&d, 115); - VERIFY_BITS_128(&c, 48); - /* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - t3 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52); - VERIFY_BITS(t3, 52); - VERIFY_BITS_128(&d, 63); - /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - - secp256k1_u128_accum_mul(&d, a0, b[4]); - secp256k1_u128_accum_mul(&d, a1, b[3]); - secp256k1_u128_accum_mul(&d, a2, b[2]); - secp256k1_u128_accum_mul(&d, a3, b[1]); - secp256k1_u128_accum_mul(&d, a4, b[0]); - VERIFY_BITS_128(&d, 115); - /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - secp256k1_u128_accum_mul(&d, R << 12, secp256k1_u128_to_u64(&c)); - VERIFY_BITS_128(&d, 116); - /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - t4 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52); - VERIFY_BITS(t4, 52); - VERIFY_BITS_128(&d, 64); - /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - tx = (t4 >> 48); t4 &= (M >> 4); - VERIFY_BITS(tx, 4); - VERIFY_BITS(t4, 48); - /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - - secp256k1_u128_mul(&c, a0, b[0]); - VERIFY_BITS_128(&c, 112); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ - secp256k1_u128_accum_mul(&d, a1, b[4]); - secp256k1_u128_accum_mul(&d, a2, b[3]); - secp256k1_u128_accum_mul(&d, a3, b[2]); - secp256k1_u128_accum_mul(&d, a4, b[1]); - VERIFY_BITS_128(&d, 114); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52); - VERIFY_BITS(u0, 52); - VERIFY_BITS_128(&d, 62); - /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = (u0 << 4) | tx; - VERIFY_BITS(u0, 56); - /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - secp256k1_u128_accum_mul(&c, u0, R >> 4); - VERIFY_BITS_128(&c, 113); - /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - r[0] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52); - VERIFY_BITS(r[0], 52); - VERIFY_BITS_128(&c, 61); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ - - secp256k1_u128_accum_mul(&c, a0, b[1]); - secp256k1_u128_accum_mul(&c, a1, b[0]); - VERIFY_BITS_128(&c, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ - secp256k1_u128_accum_mul(&d, a2, b[4]); - secp256k1_u128_accum_mul(&d, a3, b[3]); - secp256k1_u128_accum_mul(&d, a4, b[2]); - VERIFY_BITS_128(&d, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - secp256k1_u128_accum_mul(&c, secp256k1_u128_to_u64(&d) & M, R); secp256k1_u128_rshift(&d, 52); - VERIFY_BITS_128(&c, 115); - VERIFY_BITS_128(&d, 62); - /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - r[1] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52); - VERIFY_BITS(r[1], 52); - VERIFY_BITS_128(&c, 63); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - - secp256k1_u128_accum_mul(&c, a0, b[2]); - secp256k1_u128_accum_mul(&c, a1, b[1]); - secp256k1_u128_accum_mul(&c, a2, b[0]); - VERIFY_BITS_128(&c, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ - secp256k1_u128_accum_mul(&d, a3, b[4]); - secp256k1_u128_accum_mul(&d, a4, b[3]); - VERIFY_BITS_128(&d, 114); - /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - secp256k1_u128_accum_mul(&c, R, secp256k1_u128_to_u64(&d)); secp256k1_u128_rshift(&d, 64); - VERIFY_BITS_128(&c, 115); - VERIFY_BITS_128(&d, 50); - /* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - r[2] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52); - VERIFY_BITS(r[2], 52); - VERIFY_BITS_128(&c, 63); - /* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - secp256k1_u128_accum_mul(&c, R << 12, secp256k1_u128_to_u64(&d)); - secp256k1_u128_accum_u64(&c, t3); - VERIFY_BITS_128(&c, 100); - /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[3] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52); - VERIFY_BITS(r[3], 52); - VERIFY_BITS_128(&c, 48); - /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = secp256k1_u128_to_u64(&c) + t4; - VERIFY_BITS(r[4], 49); - /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { - secp256k1_uint128 c, d; - uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; - uint64_t t3, t4, tx, u0; - const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; - - VERIFY_BITS(a[0], 56); - VERIFY_BITS(a[1], 56); - VERIFY_BITS(a[2], 56); - VERIFY_BITS(a[3], 56); - VERIFY_BITS(a[4], 52); - - /** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. - * px is a shorthand for sum(a[i]*a[x-i], i=0..x). - * Note that [x 0 0 0 0 0] = [x*R]. - */ - - secp256k1_u128_mul(&d, a0*2, a3); - secp256k1_u128_accum_mul(&d, a1*2, a2); - VERIFY_BITS_128(&d, 114); - /* [d 0 0 0] = [p3 0 0 0] */ - secp256k1_u128_mul(&c, a4, a4); - VERIFY_BITS_128(&c, 112); - /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - secp256k1_u128_accum_mul(&d, R, secp256k1_u128_to_u64(&c)); secp256k1_u128_rshift(&c, 64); - VERIFY_BITS_128(&d, 115); - VERIFY_BITS_128(&c, 48); - /* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - t3 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52); - VERIFY_BITS(t3, 52); - VERIFY_BITS_128(&d, 63); - /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - - a4 *= 2; - secp256k1_u128_accum_mul(&d, a0, a4); - secp256k1_u128_accum_mul(&d, a1*2, a3); - secp256k1_u128_accum_mul(&d, a2, a2); - VERIFY_BITS_128(&d, 115); - /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - secp256k1_u128_accum_mul(&d, R << 12, secp256k1_u128_to_u64(&c)); - VERIFY_BITS_128(&d, 116); - /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - t4 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52); - VERIFY_BITS(t4, 52); - VERIFY_BITS_128(&d, 64); - /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - tx = (t4 >> 48); t4 &= (M >> 4); - VERIFY_BITS(tx, 4); - VERIFY_BITS(t4, 48); - /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - - secp256k1_u128_mul(&c, a0, a0); - VERIFY_BITS_128(&c, 112); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ - secp256k1_u128_accum_mul(&d, a1, a4); - secp256k1_u128_accum_mul(&d, a2*2, a3); - VERIFY_BITS_128(&d, 114); - /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52); - VERIFY_BITS(u0, 52); - VERIFY_BITS_128(&d, 62); - /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = (u0 << 4) | tx; - VERIFY_BITS(u0, 56); - /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - secp256k1_u128_accum_mul(&c, u0, R >> 4); - VERIFY_BITS_128(&c, 113); - /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - r[0] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52); - VERIFY_BITS(r[0], 52); - VERIFY_BITS_128(&c, 61); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ - - a0 *= 2; - secp256k1_u128_accum_mul(&c, a0, a1); - VERIFY_BITS_128(&c, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ - secp256k1_u128_accum_mul(&d, a2, a4); - secp256k1_u128_accum_mul(&d, a3, a3); - VERIFY_BITS_128(&d, 114); - /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - secp256k1_u128_accum_mul(&c, secp256k1_u128_to_u64(&d) & M, R); secp256k1_u128_rshift(&d, 52); - VERIFY_BITS_128(&c, 115); - VERIFY_BITS_128(&d, 62); - /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - r[1] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52); - VERIFY_BITS(r[1], 52); - VERIFY_BITS_128(&c, 63); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - - secp256k1_u128_accum_mul(&c, a0, a2); - secp256k1_u128_accum_mul(&c, a1, a1); - VERIFY_BITS_128(&c, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ - secp256k1_u128_accum_mul(&d, a3, a4); - VERIFY_BITS_128(&d, 114); - /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - secp256k1_u128_accum_mul(&c, R, secp256k1_u128_to_u64(&d)); secp256k1_u128_rshift(&d, 64); - VERIFY_BITS_128(&c, 115); - VERIFY_BITS_128(&d, 50); - /* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52); - VERIFY_BITS(r[2], 52); - VERIFY_BITS_128(&c, 63); - /* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - - secp256k1_u128_accum_mul(&c, R << 12, secp256k1_u128_to_u64(&d)); - secp256k1_u128_accum_u64(&c, t3); - VERIFY_BITS_128(&c, 100); - /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[3] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52); - VERIFY_BITS(r[3], 52); - VERIFY_BITS_128(&c, 48); - /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = secp256k1_u128_to_u64(&c) + t4; - VERIFY_BITS(r[4], 49); - /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ -} - -#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ diff --git a/external/secp256k1/src/field_impl.h b/external/secp256k1/src/field_impl.h deleted file mode 100644 index 896507a3a4..0000000000 --- a/external/secp256k1/src/field_impl.h +++ /dev/null @@ -1,457 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_FIELD_IMPL_H -#define SECP256K1_FIELD_IMPL_H - -#include "field.h" -#include "util.h" - -#if defined(SECP256K1_WIDEMUL_INT128) -#include "field_5x52_impl.h" -#elif defined(SECP256K1_WIDEMUL_INT64) -#include "field_10x26_impl.h" -#else -#error "Please select wide multiplication implementation" -#endif - -SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { - secp256k1_memclear(a, sizeof(secp256k1_fe)); -} - -SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe na; - SECP256K1_FE_VERIFY(a); - SECP256K1_FE_VERIFY(b); - SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); - SECP256K1_FE_VERIFY_MAGNITUDE(b, 31); - - secp256k1_fe_negate(&na, a, 1); - secp256k1_fe_add(&na, b); - return secp256k1_fe_normalizes_to_zero(&na); -} - -static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a) { - /** Given that p is congruent to 3 mod 4, we can compute the square root of - * a mod p as the (p+1)/4'th power of a. - * - * As (p+1)/4 is an even number, it will have the same result for a and for - * (-a). Only one of these two numbers actually has a square root however, - * so we test at the end by squaring and comparing to the input. - * Also because (p+1)/4 is an even number, the computed square root is - * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). - */ - secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; - int j, ret; - - VERIFY_CHECK(r != a); - SECP256K1_FE_VERIFY(a); - SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); - - /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in - * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: - * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] - */ - - secp256k1_fe_sqr(&x2, a); - secp256k1_fe_mul(&x2, &x2, a); - - secp256k1_fe_sqr(&x3, &x2); - secp256k1_fe_mul(&x3, &x3, a); - - x6 = x3; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x6, &x6); - } - secp256k1_fe_mul(&x6, &x6, &x3); - - x9 = x6; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x9, &x9); - } - secp256k1_fe_mul(&x9, &x9, &x3); - - x11 = x9; - for (j=0; j<2; j++) { - secp256k1_fe_sqr(&x11, &x11); - } - secp256k1_fe_mul(&x11, &x11, &x2); - - x22 = x11; - for (j=0; j<11; j++) { - secp256k1_fe_sqr(&x22, &x22); - } - secp256k1_fe_mul(&x22, &x22, &x11); - - x44 = x22; - for (j=0; j<22; j++) { - secp256k1_fe_sqr(&x44, &x44); - } - secp256k1_fe_mul(&x44, &x44, &x22); - - x88 = x44; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x88, &x88); - } - secp256k1_fe_mul(&x88, &x88, &x44); - - x176 = x88; - for (j=0; j<88; j++) { - secp256k1_fe_sqr(&x176, &x176); - } - secp256k1_fe_mul(&x176, &x176, &x88); - - x220 = x176; - for (j=0; j<44; j++) { - secp256k1_fe_sqr(&x220, &x220); - } - secp256k1_fe_mul(&x220, &x220, &x44); - - x223 = x220; - for (j=0; j<3; j++) { - secp256k1_fe_sqr(&x223, &x223); - } - secp256k1_fe_mul(&x223, &x223, &x3); - - /* The final result is then assembled using a sliding window over the blocks. */ - - t1 = x223; - for (j=0; j<23; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x22); - for (j=0; j<6; j++) { - secp256k1_fe_sqr(&t1, &t1); - } - secp256k1_fe_mul(&t1, &t1, &x2); - secp256k1_fe_sqr(&t1, &t1); - secp256k1_fe_sqr(r, &t1); - - /* Check that a square root was actually calculated */ - - secp256k1_fe_sqr(&t1, r); - ret = secp256k1_fe_equal(&t1, a); - -#ifdef VERIFY - if (!ret) { - secp256k1_fe_negate(&t1, &t1, 1); - secp256k1_fe_normalize_var(&t1); - VERIFY_CHECK(secp256k1_fe_equal(&t1, a)); - } -#endif - return ret; -} - -#ifndef VERIFY -static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; } -static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) { (void)a; (void)m; } -#else -static void secp256k1_fe_impl_verify(const secp256k1_fe *a); -static void secp256k1_fe_verify(const secp256k1_fe *a) { - /* Magnitude between 0 and 32. */ - SECP256K1_FE_VERIFY_MAGNITUDE(a, 32); - /* Normalized is 0 or 1. */ - VERIFY_CHECK((a->normalized == 0) || (a->normalized == 1)); - /* If normalized, magnitude must be 0 or 1. */ - if (a->normalized) SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); - /* Invoke implementation-specific checks. */ - secp256k1_fe_impl_verify(a); -} - -static void secp256k1_fe_verify_magnitude(const secp256k1_fe *a, int m) { - VERIFY_CHECK(m >= 0); - VERIFY_CHECK(m <= 32); - VERIFY_CHECK(a->magnitude <= m); -} - -static void secp256k1_fe_impl_normalize(secp256k1_fe *r); -SECP256K1_INLINE static void secp256k1_fe_normalize(secp256k1_fe *r) { - SECP256K1_FE_VERIFY(r); - - secp256k1_fe_impl_normalize(r); - r->magnitude = 1; - r->normalized = 1; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r); -SECP256K1_INLINE static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { - SECP256K1_FE_VERIFY(r); - - secp256k1_fe_impl_normalize_weak(r); - r->magnitude = 1; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r); -SECP256K1_INLINE static void secp256k1_fe_normalize_var(secp256k1_fe *r) { - SECP256K1_FE_VERIFY(r); - - secp256k1_fe_impl_normalize_var(r); - r->magnitude = 1; - r->normalized = 1; - - SECP256K1_FE_VERIFY(r); -} - -static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r); -SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) { - SECP256K1_FE_VERIFY(r); - - return secp256k1_fe_impl_normalizes_to_zero(r); -} - -static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r); -SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) { - SECP256K1_FE_VERIFY(r); - - return secp256k1_fe_impl_normalizes_to_zero_var(r); -} - -static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a); -SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { - VERIFY_CHECK(0 <= a && a <= 0x7FFF); - - secp256k1_fe_impl_set_int(r, a); - r->magnitude = (a != 0); - r->normalized = 1; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a); -SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { - VERIFY_CHECK(0 <= a && a <= 0x7FFF); - SECP256K1_FE_VERIFY(r); - - secp256k1_fe_impl_add_int(r, a); - r->magnitude += 1; - r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a); -SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { - SECP256K1_FE_VERIFY(a); - VERIFY_CHECK(a->normalized); - - return secp256k1_fe_impl_is_zero(a); -} - -static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a); -SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { - SECP256K1_FE_VERIFY(a); - VERIFY_CHECK(a->normalized); - - return secp256k1_fe_impl_is_odd(a); -} - -static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); -SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { - SECP256K1_FE_VERIFY(a); - SECP256K1_FE_VERIFY(b); - VERIFY_CHECK(a->normalized); - VERIFY_CHECK(b->normalized); - - return secp256k1_fe_impl_cmp_var(a, b); -} - -static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a); -SECP256K1_INLINE static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a) { - secp256k1_fe_impl_set_b32_mod(r, a); - r->magnitude = 1; - r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a); -SECP256K1_INLINE static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a) { - if (secp256k1_fe_impl_set_b32_limit(r, a)) { - r->magnitude = 1; - r->normalized = 1; - SECP256K1_FE_VERIFY(r); - return 1; - } else { - /* Mark the output field element as invalid. */ - r->magnitude = -1; - return 0; - } -} - -static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a); -SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - SECP256K1_FE_VERIFY(a); - VERIFY_CHECK(a->normalized); - - secp256k1_fe_impl_get_b32(r, a); -} - -static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m); -SECP256K1_INLINE static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) { - SECP256K1_FE_VERIFY(a); - VERIFY_CHECK(m >= 0 && m <= 31); - SECP256K1_FE_VERIFY_MAGNITUDE(a, m); - - secp256k1_fe_impl_negate_unchecked(r, a, m); - r->magnitude = m + 1; - r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a); -SECP256K1_INLINE static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a) { - SECP256K1_FE_VERIFY(r); - - VERIFY_CHECK(a >= 0 && a <= 32); - VERIFY_CHECK(a*r->magnitude <= 32); - secp256k1_fe_impl_mul_int_unchecked(r, a); - r->magnitude *= a; - r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a); -SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { - SECP256K1_FE_VERIFY(r); - SECP256K1_FE_VERIFY(a); - VERIFY_CHECK(r->magnitude + a->magnitude <= 32); - - secp256k1_fe_impl_add(r, a); - r->magnitude += a->magnitude; - r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); -SECP256K1_INLINE static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { - SECP256K1_FE_VERIFY(a); - SECP256K1_FE_VERIFY(b); - SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); - SECP256K1_FE_VERIFY_MAGNITUDE(b, 8); - VERIFY_CHECK(r != b); - VERIFY_CHECK(a != b); - - secp256k1_fe_impl_mul(r, a, b); - r->magnitude = 1; - r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a); -SECP256K1_INLINE static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { - SECP256K1_FE_VERIFY(a); - SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); - - secp256k1_fe_impl_sqr(r, a); - r->magnitude = 1; - r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); -SECP256K1_INLINE static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { - VERIFY_CHECK(flag == 0 || flag == 1); - SECP256K1_FE_VERIFY(a); - SECP256K1_FE_VERIFY(r); - - secp256k1_fe_impl_cmov(r, a, flag); - if (a->magnitude > r->magnitude) r->magnitude = a->magnitude; - if (!a->normalized) r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a); -SECP256K1_INLINE static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { - SECP256K1_FE_VERIFY(a); - VERIFY_CHECK(a->normalized); - - secp256k1_fe_impl_to_storage(r, a); -} - -static void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); -SECP256K1_INLINE static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { - secp256k1_fe_impl_from_storage(r, a); - r->magnitude = 1; - r->normalized = 1; - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x); -SECP256K1_INLINE static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) { - int input_is_zero = secp256k1_fe_normalizes_to_zero(x); - SECP256K1_FE_VERIFY(x); - - secp256k1_fe_impl_inv(r, x); - r->magnitude = x->magnitude > 0; - r->normalized = 1; - - VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero); - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x); -SECP256K1_INLINE static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) { - int input_is_zero = secp256k1_fe_normalizes_to_zero(x); - SECP256K1_FE_VERIFY(x); - - secp256k1_fe_impl_inv_var(r, x); - r->magnitude = x->magnitude > 0; - r->normalized = 1; - - VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero); - SECP256K1_FE_VERIFY(r); -} - -static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x); -SECP256K1_INLINE static int secp256k1_fe_is_square_var(const secp256k1_fe *x) { - int ret; - secp256k1_fe tmp = *x, sqrt; - SECP256K1_FE_VERIFY(x); - - ret = secp256k1_fe_impl_is_square_var(x); - secp256k1_fe_normalize_weak(&tmp); - VERIFY_CHECK(ret == secp256k1_fe_sqrt(&sqrt, &tmp)); - return ret; -} - -static void secp256k1_fe_impl_get_bounds(secp256k1_fe* r, int m); -SECP256K1_INLINE static void secp256k1_fe_get_bounds(secp256k1_fe* r, int m) { - VERIFY_CHECK(m >= 0); - VERIFY_CHECK(m <= 32); - - secp256k1_fe_impl_get_bounds(r, m); - r->magnitude = m; - r->normalized = (m == 0); - - SECP256K1_FE_VERIFY(r); -} - -static void secp256k1_fe_impl_half(secp256k1_fe *r); -SECP256K1_INLINE static void secp256k1_fe_half(secp256k1_fe *r) { - SECP256K1_FE_VERIFY(r); - SECP256K1_FE_VERIFY_MAGNITUDE(r, 31); - - secp256k1_fe_impl_half(r); - r->magnitude = (r->magnitude >> 1) + 1; - r->normalized = 0; - - SECP256K1_FE_VERIFY(r); -} - -#endif /* defined(VERIFY) */ - -#endif /* SECP256K1_FIELD_IMPL_H */ diff --git a/external/secp256k1/src/group.h b/external/secp256k1/src/group.h deleted file mode 100644 index 992ff5c98c..0000000000 --- a/external/secp256k1/src/group.h +++ /dev/null @@ -1,212 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_GROUP_H -#define SECP256K1_GROUP_H - -#include "field.h" - -/** A group element in affine coordinates on the secp256k1 curve, - * or occasionally on an isomorphic curve of the form y^2 = x^3 + 7*t^6. - * Note: For exhaustive test mode, secp256k1 is replaced by a small subgroup of a different curve. - */ -typedef struct { - secp256k1_fe x; - secp256k1_fe y; - int infinity; /* whether this represents the point at infinity */ -} secp256k1_ge; - -#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} -#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} - -/** A group element of the secp256k1 curve, in jacobian coordinates. - * Note: For exhastive test mode, secp256k1 is replaced by a small subgroup of a different curve. - */ -typedef struct { - secp256k1_fe x; /* actual X: x/z^2 */ - secp256k1_fe y; /* actual Y: y/z^3 */ - secp256k1_fe z; - int infinity; /* whether this represents the point at infinity */ -} secp256k1_gej; - -#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} -#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} - -typedef struct { - secp256k1_fe_storage x; - secp256k1_fe_storage y; -} secp256k1_ge_storage; - -#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} - -#define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) - -/** Maximum allowed magnitudes for group element coordinates - * in affine (x, y) and jacobian (x, y, z) representation. */ -#define SECP256K1_GE_X_MAGNITUDE_MAX 4 -#define SECP256K1_GE_Y_MAGNITUDE_MAX 3 -#define SECP256K1_GEJ_X_MAGNITUDE_MAX 4 -#define SECP256K1_GEJ_Y_MAGNITUDE_MAX 4 -#define SECP256K1_GEJ_Z_MAGNITUDE_MAX 1 - -/** Set a group element equal to the point with given X and Y coordinates */ -static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y); - -/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness - * for Y. Return value indicates whether the result is valid. */ -static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd); - -/** Determine whether x is a valid X coordinate on the curve. */ -static int secp256k1_ge_x_on_curve_var(const secp256k1_fe *x); - -/** Determine whether fraction xn/xd is a valid X coordinate on the curve (xd != 0). */ -static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp256k1_fe *xd); - -/** Check whether a group element is the point at infinity. */ -static int secp256k1_ge_is_infinity(const secp256k1_ge *a); - -/** Check whether a group element is valid (i.e., on the curve). */ -static int secp256k1_ge_is_valid_var(const secp256k1_ge *a); - -/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ -static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); - -/** Set a group element equal to another which is given in jacobian coordinates. Constant time. */ -static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); - -/** Set a group element equal to another which is given in jacobian coordinates. */ -static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a); - -/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ -static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len); - -/** Bring a batch of inputs to the same global z "denominator", based on ratios between - * (omitted) z coordinates of adjacent elements. - * - * Although the elements a[i] are _ge rather than _gej, they actually represent elements - * in Jacobian coordinates with their z coordinates omitted. - * - * Using the notation z(b) to represent the omitted z coordinate of b, the array zr of - * z coordinate ratios must satisfy zr[i] == z(a[i]) / z(a[i-1]) for 0 < 'i' < len. - * The zr[0] value is unused. - * - * This function adjusts the coordinates of 'a' in place so that for all 'i', z(a[i]) == z(a[len-1]). - * In other words, the initial value of z(a[len-1]) becomes the global z "denominator". Only the - * a[i].x and a[i].y coordinates are explicitly modified; the adjustment of the omitted z coordinate is - * implicit. - * - * The coordinates of the final element a[len-1] are not changed. - */ -static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const secp256k1_fe *zr); - -/** Check two group elements (affine) for equality in variable time. */ -static int secp256k1_ge_eq_var(const secp256k1_ge *a, const secp256k1_ge *b); - -/** Set a group element (affine) equal to the point at infinity. */ -static void secp256k1_ge_set_infinity(secp256k1_ge *r); - -/** Set a group element (jacobian) equal to the point at infinity. */ -static void secp256k1_gej_set_infinity(secp256k1_gej *r); - -/** Set a group element (jacobian) equal to another which is given in affine coordinates. */ -static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); - -/** Check two group elements (jacobian) for equality in variable time. */ -static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b); - -/** Check two group elements (jacobian and affine) for equality in variable time. */ -static int secp256k1_gej_eq_ge_var(const secp256k1_gej *a, const secp256k1_ge *b); - -/** Compare the X coordinate of a group element (jacobian). - * The magnitude of the group element's X coordinate must not exceed 31. */ -static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); - -/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ -static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a); - -/** Check whether a group element is the point at infinity. */ -static int secp256k1_gej_is_infinity(const secp256k1_gej *a); - -/** Set r equal to the double of a. Constant time. */ -static void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a); - -/** Set r equal to the double of a. If rzr is not-NULL this sets *rzr such that r->z == a->z * *rzr (where infinity means an implicit z = 0). */ -static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b. If rzr is non-NULL this sets *rzr such that r->z == a->z * *rzr (a cannot be infinity in that case). */ -static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ -static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b); - -/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient - than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time - guarantee, and b is allowed to be infinity. If rzr is non-NULL this sets *rzr such that r->z == a->z * *rzr (a cannot be infinity in that case). */ -static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr); - -/** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ -static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv); - -/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ -static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); - -/** Clear a secp256k1_gej to prevent leaking sensitive information. */ -static void secp256k1_gej_clear(secp256k1_gej *r); - -/** Clear a secp256k1_ge to prevent leaking sensitive information. */ -static void secp256k1_ge_clear(secp256k1_ge *r); - -/** Convert a group element to the storage type. */ -static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a); - -/** Convert a group element back from the storage type. */ -static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ -static void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ -static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); - -/** Rescale a jacobian point by b which must be non-zero. Constant-time. */ -static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); - -/** Convert a group element that is not infinity to a 64-byte array. The output - * array is platform-dependent. */ -static void secp256k1_ge_to_bytes(unsigned char *buf, const secp256k1_ge *a); - -/** Convert a 64-byte array into group element. This function assumes that the - * provided buffer correctly encodes a group element. */ -static void secp256k1_ge_from_bytes(secp256k1_ge *r, const unsigned char *buf); - -/** Convert a group element (that is allowed to be infinity) to a 64-byte - * array. The output array is platform-dependent. */ -static void secp256k1_ge_to_bytes_ext(unsigned char *data, const secp256k1_ge *ge); - -/** Convert a 64-byte array into a group element. This function assumes that the - * provided buffer is the output of secp256k1_ge_to_bytes_ext. */ -static void secp256k1_ge_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data); - -/** Determine if a point (which is assumed to be on the curve) is in the correct (sub)group of the curve. - * - * In normal mode, the used group is secp256k1, which has cofactor=1 meaning that every point on the curve is in the - * group, and this function returns always true. - * - * When compiling in exhaustive test mode, a slightly different curve equation is used, leading to a group with a - * (very) small subgroup, and that subgroup is what is used for all cryptographic operations. In that mode, this - * function checks whether a point that is on the curve is in fact also in that subgroup. - */ -static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge); - -/** Check invariants on an affine group element (no-op unless VERIFY is enabled). */ -static void secp256k1_ge_verify(const secp256k1_ge *a); -#define SECP256K1_GE_VERIFY(a) secp256k1_ge_verify(a) - -/** Check invariants on a Jacobian group element (no-op unless VERIFY is enabled). */ -static void secp256k1_gej_verify(const secp256k1_gej *a); -#define SECP256K1_GEJ_VERIFY(a) secp256k1_gej_verify(a) - -#endif /* SECP256K1_GROUP_H */ diff --git a/external/secp256k1/src/group_impl.h b/external/secp256k1/src/group_impl.h deleted file mode 100644 index c668fb2401..0000000000 --- a/external/secp256k1/src/group_impl.h +++ /dev/null @@ -1,974 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_GROUP_IMPL_H -#define SECP256K1_GROUP_IMPL_H - -#include - -#include "field.h" -#include "group.h" -#include "util.h" - -/* Begin of section generated by sage/gen_exhaustive_groups.sage. */ -#define SECP256K1_G_ORDER_7 SECP256K1_GE_CONST(\ - 0x66625d13, 0x317ffe44, 0x63d32cff, 0x1ca02b9b,\ - 0xe5c6d070, 0x50b4b05e, 0x81cc30db, 0xf5166f0a,\ - 0x1e60e897, 0xa7c00c7c, 0x2df53eb6, 0x98274ff4,\ - 0x64252f42, 0x8ca44e17, 0x3b25418c, 0xff4ab0cf\ -) -#define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\ - 0xa2482ff8, 0x4bf34edf, 0xa51262fd, 0xe57921db,\ - 0xe0dd2cb7, 0xa5914790, 0xbc71631f, 0xc09704fb,\ - 0x942536cb, 0xa3e49492, 0x3a701cc3, 0xee3e443f,\ - 0xdf182aa9, 0x15b8aa6a, 0x166d3b19, 0xba84b045\ -) -#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\ - 0x7fb07b5c, 0xd07c3bda, 0x553902e2, 0x7a87ea2c,\ - 0x35108a7f, 0x051f41e5, 0xb76abad5, 0x1f2703ad,\ - 0x0a251539, 0x5b4c4438, 0x952a634f, 0xac10dd4d,\ - 0x6d6f4745, 0x98990c27, 0x3a4f3116, 0xd32ff969\ -) -/** Generator for secp256k1, value 'g' defined in - * "Standards for Efficient Cryptography" (SEC2) 2.7.1. - */ -#define SECP256K1_G SECP256K1_GE_CONST(\ - 0x79be667e, 0xf9dcbbac, 0x55a06295, 0xce870b07,\ - 0x029bfcdb, 0x2dce28d9, 0x59f2815b, 0x16f81798,\ - 0x483ada77, 0x26a3c465, 0x5da4fbfc, 0x0e1108a8,\ - 0xfd17b448, 0xa6855419, 0x9c47d08f, 0xfb10d4b8\ -) -/* These exhaustive group test orders and generators are chosen such that: - * - The field size is equal to that of secp256k1, so field code is the same. - * - The curve equation is of the form y^2=x^3+B for some small constant B. - * - The subgroup has a generator 2*P, where P.x is as small as possible. - * - The subgroup has size less than 1000 to permit exhaustive testing. - * - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y). - */ -#if defined(EXHAUSTIVE_TEST_ORDER) -# if EXHAUSTIVE_TEST_ORDER == 7 - -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_7; -#define SECP256K1_B 6 - -# elif EXHAUSTIVE_TEST_ORDER == 13 - -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13; -#define SECP256K1_B 2 - -# elif EXHAUSTIVE_TEST_ORDER == 199 - -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199; -#define SECP256K1_B 4 - -# else -# error No known generator for the specified exhaustive test group order. -# endif -#else - -static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G; -#define SECP256K1_B 7 - -#endif -/* End of section generated by sage/gen_exhaustive_groups.sage. */ - -static void secp256k1_ge_verify(const secp256k1_ge *a) { - SECP256K1_FE_VERIFY(&a->x); - SECP256K1_FE_VERIFY(&a->y); - SECP256K1_FE_VERIFY_MAGNITUDE(&a->x, SECP256K1_GE_X_MAGNITUDE_MAX); - SECP256K1_FE_VERIFY_MAGNITUDE(&a->y, SECP256K1_GE_Y_MAGNITUDE_MAX); - VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); - (void)a; -} - -static void secp256k1_gej_verify(const secp256k1_gej *a) { - SECP256K1_FE_VERIFY(&a->x); - SECP256K1_FE_VERIFY(&a->y); - SECP256K1_FE_VERIFY(&a->z); - SECP256K1_FE_VERIFY_MAGNITUDE(&a->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); - SECP256K1_FE_VERIFY_MAGNITUDE(&a->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); - SECP256K1_FE_VERIFY_MAGNITUDE(&a->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); - VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); - (void)a; -} - -/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */ -static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { - secp256k1_fe zi2; - secp256k1_fe zi3; - SECP256K1_GEJ_VERIFY(a); - SECP256K1_FE_VERIFY(zi); - VERIFY_CHECK(!a->infinity); - - secp256k1_fe_sqr(&zi2, zi); - secp256k1_fe_mul(&zi3, &zi2, zi); - secp256k1_fe_mul(&r->x, &a->x, &zi2); - secp256k1_fe_mul(&r->y, &a->y, &zi3); - r->infinity = a->infinity; - - SECP256K1_GE_VERIFY(r); -} - -/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */ -static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi) { - secp256k1_fe zi2; - secp256k1_fe zi3; - SECP256K1_GE_VERIFY(a); - SECP256K1_FE_VERIFY(zi); - VERIFY_CHECK(!a->infinity); - - secp256k1_fe_sqr(&zi2, zi); - secp256k1_fe_mul(&zi3, &zi2, zi); - secp256k1_fe_mul(&r->x, &a->x, &zi2); - secp256k1_fe_mul(&r->y, &a->y, &zi3); - r->infinity = a->infinity; - - SECP256K1_GE_VERIFY(r); -} - -static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { - SECP256K1_FE_VERIFY(x); - SECP256K1_FE_VERIFY(y); - - r->infinity = 0; - r->x = *x; - r->y = *y; - - SECP256K1_GE_VERIFY(r); -} - -static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { - SECP256K1_GE_VERIFY(a); - - return a->infinity; -} - -static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { - SECP256K1_GE_VERIFY(a); - - *r = *a; - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_negate(&r->y, &r->y, 1); - - SECP256K1_GE_VERIFY(r); -} - -static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { - secp256k1_fe z2, z3; - SECP256K1_GEJ_VERIFY(a); - - r->infinity = a->infinity; - secp256k1_fe_inv(&a->z, &a->z); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_mul(&z3, &a->z, &z2); - secp256k1_fe_mul(&a->x, &a->x, &z2); - secp256k1_fe_mul(&a->y, &a->y, &z3); - secp256k1_fe_set_int(&a->z, 1); - r->x = a->x; - r->y = a->y; - - SECP256K1_GEJ_VERIFY(a); - SECP256K1_GE_VERIFY(r); -} - -static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { - secp256k1_fe z2, z3; - SECP256K1_GEJ_VERIFY(a); - - if (secp256k1_gej_is_infinity(a)) { - secp256k1_ge_set_infinity(r); - return; - } - r->infinity = 0; - secp256k1_fe_inv_var(&a->z, &a->z); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_mul(&z3, &a->z, &z2); - secp256k1_fe_mul(&a->x, &a->x, &z2); - secp256k1_fe_mul(&a->y, &a->y, &z3); - secp256k1_fe_set_int(&a->z, 1); - secp256k1_ge_set_xy(r, &a->x, &a->y); - - SECP256K1_GEJ_VERIFY(a); - SECP256K1_GE_VERIFY(r); -} - -static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { - secp256k1_fe u; - size_t i; - size_t last_i = SIZE_MAX; -#ifdef VERIFY - for (i = 0; i < len; i++) { - SECP256K1_GEJ_VERIFY(&a[i]); - } -#endif - - for (i = 0; i < len; i++) { - if (a[i].infinity) { - secp256k1_ge_set_infinity(&r[i]); - } else { - /* Use destination's x coordinates as scratch space */ - if (last_i == SIZE_MAX) { - r[i].x = a[i].z; - } else { - secp256k1_fe_mul(&r[i].x, &r[last_i].x, &a[i].z); - } - last_i = i; - } - } - if (last_i == SIZE_MAX) { - return; - } - secp256k1_fe_inv_var(&u, &r[last_i].x); - - i = last_i; - while (i > 0) { - i--; - if (!a[i].infinity) { - secp256k1_fe_mul(&r[last_i].x, &r[i].x, &u); - secp256k1_fe_mul(&u, &u, &a[last_i].z); - last_i = i; - } - } - VERIFY_CHECK(!a[last_i].infinity); - r[last_i].x = u; - - for (i = 0; i < len; i++) { - if (!a[i].infinity) { - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); - } - } - -#ifdef VERIFY - for (i = 0; i < len; i++) { - SECP256K1_GE_VERIFY(&r[i]); - } -#endif -} - -static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const secp256k1_fe *zr) { - size_t i; - secp256k1_fe zs; -#ifdef VERIFY - for (i = 0; i < len; i++) { - SECP256K1_GE_VERIFY(&a[i]); - SECP256K1_FE_VERIFY(&zr[i]); - } -#endif - - if (len > 0) { - i = len - 1; - /* Ensure all y values are in weak normal form for fast negation of points */ - secp256k1_fe_normalize_weak(&a[i].y); - zs = zr[i]; - - /* Work our way backwards, using the z-ratios to scale the x/y values. */ - while (i > 0) { - if (i != len - 1) { - secp256k1_fe_mul(&zs, &zs, &zr[i]); - } - i--; - secp256k1_ge_set_ge_zinv(&a[i], &a[i], &zs); - } - } - -#ifdef VERIFY - for (i = 0; i < len; i++) { - SECP256K1_GE_VERIFY(&a[i]); - } -#endif -} - -static void secp256k1_gej_set_infinity(secp256k1_gej *r) { - r->infinity = 1; - secp256k1_fe_set_int(&r->x, 0); - secp256k1_fe_set_int(&r->y, 0); - secp256k1_fe_set_int(&r->z, 0); - - SECP256K1_GEJ_VERIFY(r); -} - -static void secp256k1_ge_set_infinity(secp256k1_ge *r) { - r->infinity = 1; - secp256k1_fe_set_int(&r->x, 0); - secp256k1_fe_set_int(&r->y, 0); - - SECP256K1_GE_VERIFY(r); -} - -static void secp256k1_gej_clear(secp256k1_gej *r) { - secp256k1_memclear(r, sizeof(secp256k1_gej)); -} - -static void secp256k1_ge_clear(secp256k1_ge *r) { - secp256k1_memclear(r, sizeof(secp256k1_ge)); -} - -static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { - secp256k1_fe x2, x3; - int ret; - SECP256K1_FE_VERIFY(x); - - r->x = *x; - secp256k1_fe_sqr(&x2, x); - secp256k1_fe_mul(&x3, x, &x2); - r->infinity = 0; - secp256k1_fe_add_int(&x3, SECP256K1_B); - ret = secp256k1_fe_sqrt(&r->y, &x3); - secp256k1_fe_normalize_var(&r->y); - if (secp256k1_fe_is_odd(&r->y) != odd) { - secp256k1_fe_negate(&r->y, &r->y, 1); - } - - SECP256K1_GE_VERIFY(r); - return ret; -} - -static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { - SECP256K1_GE_VERIFY(a); - - r->infinity = a->infinity; - r->x = a->x; - r->y = a->y; - secp256k1_fe_set_int(&r->z, 1); - - SECP256K1_GEJ_VERIFY(r); -} - -static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) { - secp256k1_gej tmp; - SECP256K1_GEJ_VERIFY(b); - SECP256K1_GEJ_VERIFY(a); - - secp256k1_gej_neg(&tmp, a); - secp256k1_gej_add_var(&tmp, &tmp, b, NULL); - return secp256k1_gej_is_infinity(&tmp); -} - -static int secp256k1_gej_eq_ge_var(const secp256k1_gej *a, const secp256k1_ge *b) { - secp256k1_gej tmp; - SECP256K1_GEJ_VERIFY(a); - SECP256K1_GE_VERIFY(b); - - secp256k1_gej_neg(&tmp, a); - secp256k1_gej_add_ge_var(&tmp, &tmp, b, NULL); - return secp256k1_gej_is_infinity(&tmp); -} - -static int secp256k1_ge_eq_var(const secp256k1_ge *a, const secp256k1_ge *b) { - secp256k1_fe tmp; - SECP256K1_GE_VERIFY(a); - SECP256K1_GE_VERIFY(b); - - if (a->infinity != b->infinity) return 0; - if (a->infinity) return 1; - - tmp = a->x; - secp256k1_fe_normalize_weak(&tmp); - if (!secp256k1_fe_equal(&tmp, &b->x)) return 0; - - tmp = a->y; - secp256k1_fe_normalize_weak(&tmp); - if (!secp256k1_fe_equal(&tmp, &b->y)) return 0; - - return 1; -} - -static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { - secp256k1_fe r; - SECP256K1_FE_VERIFY(x); - SECP256K1_GEJ_VERIFY(a); - VERIFY_CHECK(!a->infinity); - - secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); - return secp256k1_fe_equal(&r, &a->x); -} - -static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { - SECP256K1_GEJ_VERIFY(a); - - r->infinity = a->infinity; - r->x = a->x; - r->y = a->y; - r->z = a->z; - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_negate(&r->y, &r->y, 1); - - SECP256K1_GEJ_VERIFY(r); -} - -static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { - SECP256K1_GEJ_VERIFY(a); - - return a->infinity; -} - -static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { - secp256k1_fe y2, x3; - SECP256K1_GE_VERIFY(a); - - if (a->infinity) { - return 0; - } - /* y^2 = x^3 + 7 */ - secp256k1_fe_sqr(&y2, &a->y); - secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_add_int(&x3, SECP256K1_B); - return secp256k1_fe_equal(&y2, &x3); -} - -static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a) { - /* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */ - secp256k1_fe l, s, t; - SECP256K1_GEJ_VERIFY(a); - - r->infinity = a->infinity; - - /* Formula used: - * L = (3/2) * X1^2 - * S = Y1^2 - * T = -X1*S - * X3 = L^2 + 2*T - * Y3 = -(L*(X3 + T) + S^2) - * Z3 = Y1*Z1 - */ - - secp256k1_fe_mul(&r->z, &a->z, &a->y); /* Z3 = Y1*Z1 (1) */ - secp256k1_fe_sqr(&s, &a->y); /* S = Y1^2 (1) */ - secp256k1_fe_sqr(&l, &a->x); /* L = X1^2 (1) */ - secp256k1_fe_mul_int(&l, 3); /* L = 3*X1^2 (3) */ - secp256k1_fe_half(&l); /* L = 3/2*X1^2 (2) */ - secp256k1_fe_negate(&t, &s, 1); /* T = -S (2) */ - secp256k1_fe_mul(&t, &t, &a->x); /* T = -X1*S (1) */ - secp256k1_fe_sqr(&r->x, &l); /* X3 = L^2 (1) */ - secp256k1_fe_add(&r->x, &t); /* X3 = L^2 + T (2) */ - secp256k1_fe_add(&r->x, &t); /* X3 = L^2 + 2*T (3) */ - secp256k1_fe_sqr(&s, &s); /* S' = S^2 (1) */ - secp256k1_fe_add(&t, &r->x); /* T' = X3 + T (4) */ - secp256k1_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */ - secp256k1_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */ - secp256k1_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */ - - SECP256K1_GEJ_VERIFY(r); -} - -static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { - SECP256K1_GEJ_VERIFY(a); - - /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, - * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have - * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. - * - * Having said this, if this function receives a point on a sextic twist, e.g. by - * a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6, - * since -6 does have a cube root mod p. For this point, this function will not set - * the infinity flag even though the point doubles to infinity, and the result - * point will be gibberish (z = 0 but infinity = 0). - */ - if (a->infinity) { - secp256k1_gej_set_infinity(r); - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - return; - } - - if (rzr != NULL) { - *rzr = a->y; - secp256k1_fe_normalize_weak(rzr); - } - - secp256k1_gej_double(r, a); - - SECP256K1_GEJ_VERIFY(r); -} - -static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { - /* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ - secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t; - SECP256K1_GEJ_VERIFY(a); - SECP256K1_GEJ_VERIFY(b); - - if (a->infinity) { - VERIFY_CHECK(rzr == NULL); - *r = *b; - return; - } - if (b->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - *r = *a; - return; - } - - secp256k1_fe_sqr(&z22, &b->z); - secp256k1_fe_sqr(&z12, &a->z); - secp256k1_fe_mul(&u1, &a->x, &z22); - secp256k1_fe_mul(&u2, &b->x, &z12); - secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s2, 1); secp256k1_fe_add(&i, &s1); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, rzr); - } else { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 0); - } - secp256k1_gej_set_infinity(r); - } - return; - } - - r->infinity = 0; - secp256k1_fe_mul(&t, &h, &b->z); - if (rzr != NULL) { - *rzr = t; - } - secp256k1_fe_mul(&r->z, &a->z, &t); - - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_negate(&h2, &h2, 1); - secp256k1_fe_mul(&h3, &h2, &h); - secp256k1_fe_mul(&t, &u1, &h2); - - secp256k1_fe_sqr(&r->x, &i); - secp256k1_fe_add(&r->x, &h3); - secp256k1_fe_add(&r->x, &t); - secp256k1_fe_add(&r->x, &t); - - secp256k1_fe_add(&t, &r->x); - secp256k1_fe_mul(&r->y, &t, &i); - secp256k1_fe_mul(&h3, &h3, &s1); - secp256k1_fe_add(&r->y, &h3); - - SECP256K1_GEJ_VERIFY(r); -} - -static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { - /* Operations: 8 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ - secp256k1_fe z12, u1, u2, s1, s2, h, i, h2, h3, t; - SECP256K1_GEJ_VERIFY(a); - SECP256K1_GE_VERIFY(b); - - if (a->infinity) { - VERIFY_CHECK(rzr == NULL); - secp256k1_gej_set_ge(r, b); - return; - } - if (b->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - *r = *a; - return; - } - - secp256k1_fe_sqr(&z12, &a->z); - u1 = a->x; - secp256k1_fe_mul(&u2, &b->x, &z12); - s1 = a->y; - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); - secp256k1_fe_negate(&h, &u1, SECP256K1_GEJ_X_MAGNITUDE_MAX); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s2, 1); secp256k1_fe_add(&i, &s1); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, rzr); - } else { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 0); - } - secp256k1_gej_set_infinity(r); - } - return; - } - - r->infinity = 0; - if (rzr != NULL) { - *rzr = h; - } - secp256k1_fe_mul(&r->z, &a->z, &h); - - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_negate(&h2, &h2, 1); - secp256k1_fe_mul(&h3, &h2, &h); - secp256k1_fe_mul(&t, &u1, &h2); - - secp256k1_fe_sqr(&r->x, &i); - secp256k1_fe_add(&r->x, &h3); - secp256k1_fe_add(&r->x, &t); - secp256k1_fe_add(&r->x, &t); - - secp256k1_fe_add(&t, &r->x); - secp256k1_fe_mul(&r->y, &t, &i); - secp256k1_fe_mul(&h3, &h3, &s1); - secp256k1_fe_add(&r->y, &h3); - - SECP256K1_GEJ_VERIFY(r); - if (rzr != NULL) SECP256K1_FE_VERIFY(rzr); -} - -static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { - /* Operations: 9 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ - secp256k1_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t; - SECP256K1_GEJ_VERIFY(a); - SECP256K1_GE_VERIFY(b); - SECP256K1_FE_VERIFY(bzinv); - - if (a->infinity) { - secp256k1_fe bzinv2, bzinv3; - r->infinity = b->infinity; - secp256k1_fe_sqr(&bzinv2, bzinv); - secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv); - secp256k1_fe_mul(&r->x, &b->x, &bzinv2); - secp256k1_fe_mul(&r->y, &b->y, &bzinv3); - secp256k1_fe_set_int(&r->z, 1); - SECP256K1_GEJ_VERIFY(r); - return; - } - if (b->infinity) { - *r = *a; - return; - } - - /** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to - * secp256k1's isomorphism we can multiply the Z coordinates on both sides - * by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1). - * This means that (rx,ry,rz) can be calculated as - * (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz. - * The variable az below holds the modified Z coordinate for a, which is used - * for the computation of rx and ry, but not for rz. - */ - secp256k1_fe_mul(&az, &a->z, bzinv); - - secp256k1_fe_sqr(&z12, &az); - u1 = a->x; - secp256k1_fe_mul(&u2, &b->x, &z12); - s1 = a->y; - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az); - secp256k1_fe_negate(&h, &u1, SECP256K1_GEJ_X_MAGNITUDE_MAX); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s2, 1); secp256k1_fe_add(&i, &s1); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, NULL); - } else { - secp256k1_gej_set_infinity(r); - } - return; - } - - r->infinity = 0; - secp256k1_fe_mul(&r->z, &a->z, &h); - - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_negate(&h2, &h2, 1); - secp256k1_fe_mul(&h3, &h2, &h); - secp256k1_fe_mul(&t, &u1, &h2); - - secp256k1_fe_sqr(&r->x, &i); - secp256k1_fe_add(&r->x, &h3); - secp256k1_fe_add(&r->x, &t); - secp256k1_fe_add(&r->x, &t); - - secp256k1_fe_add(&t, &r->x); - secp256k1_fe_mul(&r->y, &t, &i); - secp256k1_fe_mul(&h3, &h3, &s1); - secp256k1_fe_add(&r->y, &h3); - - SECP256K1_GEJ_VERIFY(r); -} - - -static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) { - /* Operations: 7 mul, 5 sqr, 21 add/cmov/half/mul_int/negate/normalizes_to_zero */ - secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; - secp256k1_fe m_alt, rr_alt; - int degenerate; - SECP256K1_GEJ_VERIFY(a); - SECP256K1_GE_VERIFY(b); - VERIFY_CHECK(!b->infinity); - - /* In: - * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. - * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. - * we find as solution for a unified addition/doubling formula: - * lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. - * x3 = lambda^2 - (x1 + x2) - * 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). - * - * Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: - * U1 = X1*Z2^2, U2 = X2*Z1^2 - * S1 = Y1*Z2^3, S2 = Y2*Z1^3 - * Z = Z1*Z2 - * T = U1+U2 - * M = S1+S2 - * Q = -T*M^2 - * R = T^2-U1*U2 - * X3 = R^2+Q - * Y3 = -(R*(2*X3+Q)+M^4)/2 - * Z3 = M*Z - * (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) - * - * This formula has the benefit of being the same for both addition - * of distinct points and doubling. However, it breaks down in the - * case that either point is infinity, or that y1 = -y2. We handle - * these cases in the following ways: - * - * - If b is infinity we simply bail by means of a VERIFY_CHECK. - * - * - If a is infinity, we detect this, and at the end of the - * computation replace the result (which will be meaningless, - * but we compute to be constant-time) with b.x : b.y : 1. - * - * - If a = -b, we have y1 = -y2, which is a degenerate case. - * But here the answer is infinity, so we simply set the - * infinity flag of the result, overriding the computed values - * without even needing to cmov. - * - * - If y1 = -y2 but x1 != x2, which does occur thanks to certain - * properties of our curve (specifically, 1 has nontrivial cube - * roots in our field, and the curve equation has no x coefficient) - * then the answer is not infinity but also not given by the above - * equation. In this case, we cmov in place an alternate expression - * for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these - * expressions for lambda are defined, they are equal, and can be - * obtained from each other by multiplication by (y1 + y2)/(y1 + y2) - * then substitution of x^3 + 7 for y^2 (using the curve equation). - * For all pairs of nonzero points (a, b) at least one is defined, - * so this covers everything. - */ - - secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ - u1 = a->x; /* u1 = U1 = X1*Z2^2 (GEJ_X_M) */ - secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ - s1 = a->y; /* s1 = S1 = Y1*Z2^3 (GEJ_Y_M) */ - secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ - secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ - t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (GEJ_X_M+1) */ - m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (GEJ_Y_M+1) */ - secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ - secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 (2) */ - secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (1) */ - secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (2) */ - /* If lambda = R/M = R/0 we have a problem (except in the "trivial" - * case that Z = z1z2 = 0, and this is special-cased later on). */ - degenerate = secp256k1_fe_normalizes_to_zero(&m); - /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. - * This means either x1 == beta*x2 or beta*x1 == x2, where beta is - * a nontrivial cube root of one. In either case, an alternate - * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), - * so we set R/M equal to this. */ - rr_alt = s1; - secp256k1_fe_mul_int(&rr_alt, 2); /* rr_alt = Y1*Z2^3 - Y2*Z1^3 (GEJ_Y_M*2) */ - secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 (GEJ_X_M+2) */ - - secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); /* rr_alt (GEJ_Y_M*2) */ - secp256k1_fe_cmov(&m_alt, &m, !degenerate); /* m_alt (GEJ_X_M+2) */ - /* Now Ralt / Malt = lambda and is guaranteed not to be Ralt / 0. - * From here on out Ralt and Malt represent the numerator - * and denominator of lambda; R and M represent the explicit - * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ - secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ - secp256k1_fe_negate(&q, &t, - SECP256K1_GEJ_X_MAGNITUDE_MAX + 1); /* q = -T (GEJ_X_M+2) */ - secp256k1_fe_mul(&q, &q, &n); /* q = Q = -T*Malt^2 (1) */ - /* These two lines use the observation that either M == Malt or M == 0, - * so M^3 * Malt is either Malt^4 (which is computed by squaring), or - * zero (which is "computed" by cmov). So the cost is one squaring - * versus two multiplications. */ - secp256k1_fe_sqr(&n, &n); /* n = Malt^4 (1) */ - secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (GEJ_Y_M+1) */ - secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ - secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Z3 = Malt*Z (1) */ - secp256k1_fe_add(&t, &q); /* t = Ralt^2 + Q (2) */ - r->x = t; /* r->x = X3 = Ralt^2 + Q (2) */ - secp256k1_fe_mul_int(&t, 2); /* t = 2*X3 (4) */ - secp256k1_fe_add(&t, &q); /* t = 2*X3 + Q (5) */ - secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*X3 + Q) (1) */ - secp256k1_fe_add(&t, &n); /* t = Ralt*(2*X3 + Q) + M^3*Malt (GEJ_Y_M+2) */ - secp256k1_fe_negate(&r->y, &t, - SECP256K1_GEJ_Y_MAGNITUDE_MAX + 2); /* r->y = -(Ralt*(2*X3 + Q) + M^3*Malt) (GEJ_Y_M+3) */ - secp256k1_fe_half(&r->y); /* r->y = Y3 = -(Ralt*(2*X3 + Q) + M^3*Malt)/2 ((GEJ_Y_M+3)/2 + 1) */ - - /* In case a->infinity == 1, replace r with (b->x, b->y, 1). */ - secp256k1_fe_cmov(&r->x, &b->x, a->infinity); - secp256k1_fe_cmov(&r->y, &b->y, a->infinity); - secp256k1_fe_cmov(&r->z, &secp256k1_fe_one, a->infinity); - - /* Set r->infinity if r->z is 0. - * - * If a->infinity is set, then r->infinity = (r->z == 0) = (1 == 0) = false, - * which is correct because the function assumes that b is not infinity. - * - * Now assume !a->infinity. This implies Z = Z1 != 0. - * - * Case y1 = -y2: - * In this case we could have a = -b, namely if x1 = x2. - * We have degenerate = true, r->z = (x1 - x2) * Z. - * Then r->infinity = ((x1 - x2)Z == 0) = (x1 == x2) = (a == -b). - * - * Case y1 != -y2: - * In this case, we can't have a = -b. - * We have degenerate = false, r->z = (y1 + y2) * Z. - * Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */ - r->infinity = secp256k1_fe_normalizes_to_zero(&r->z); - - SECP256K1_GEJ_VERIFY(r); -} - -static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { - /* Operations: 4 mul, 1 sqr */ - secp256k1_fe zz; - SECP256K1_GEJ_VERIFY(r); - SECP256K1_FE_VERIFY(s); - VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(s)); - - secp256k1_fe_sqr(&zz, s); - secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ - secp256k1_fe_mul(&r->y, &r->y, &zz); - secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ - secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ - - SECP256K1_GEJ_VERIFY(r); -} - -static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { - secp256k1_fe x, y; - SECP256K1_GE_VERIFY(a); - VERIFY_CHECK(!a->infinity); - - x = a->x; - secp256k1_fe_normalize(&x); - y = a->y; - secp256k1_fe_normalize(&y); - secp256k1_fe_to_storage(&r->x, &x); - secp256k1_fe_to_storage(&r->y, &y); -} - -static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) { - secp256k1_fe_from_storage(&r->x, &a->x); - secp256k1_fe_from_storage(&r->y, &a->y); - r->infinity = 0; - - SECP256K1_GE_VERIFY(r); -} - -static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) { - SECP256K1_GEJ_VERIFY(r); - SECP256K1_GEJ_VERIFY(a); - - secp256k1_fe_cmov(&r->x, &a->x, flag); - secp256k1_fe_cmov(&r->y, &a->y, flag); - secp256k1_fe_cmov(&r->z, &a->z, flag); - r->infinity ^= (r->infinity ^ a->infinity) & flag; - - SECP256K1_GEJ_VERIFY(r); -} - -static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { - secp256k1_fe_storage_cmov(&r->x, &a->x, flag); - secp256k1_fe_storage_cmov(&r->y, &a->y, flag); -} - -static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { - SECP256K1_GE_VERIFY(a); - - *r = *a; - secp256k1_fe_mul(&r->x, &r->x, &secp256k1_const_beta); - - SECP256K1_GE_VERIFY(r); -} - -static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) { -#ifdef EXHAUSTIVE_TEST_ORDER - secp256k1_gej out; - int i; - SECP256K1_GE_VERIFY(ge); - - /* A very simple EC multiplication ladder that avoids a dependency on ecmult. */ - secp256k1_gej_set_infinity(&out); - for (i = 0; i < 32; ++i) { - secp256k1_gej_double_var(&out, &out, NULL); - if ((((uint32_t)EXHAUSTIVE_TEST_ORDER) >> (31 - i)) & 1) { - secp256k1_gej_add_ge_var(&out, &out, ge, NULL); - } - } - return secp256k1_gej_is_infinity(&out); -#else - SECP256K1_GE_VERIFY(ge); - - (void)ge; - /* The real secp256k1 group has cofactor 1, so the subgroup is the entire curve. */ - return 1; -#endif -} - -static int secp256k1_ge_x_on_curve_var(const secp256k1_fe *x) { - secp256k1_fe c; - secp256k1_fe_sqr(&c, x); - secp256k1_fe_mul(&c, &c, x); - secp256k1_fe_add_int(&c, SECP256K1_B); - return secp256k1_fe_is_square_var(&c); -} - -static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp256k1_fe *xd) { - /* We want to determine whether (xn/xd) is on the curve. - * - * (xn/xd)^3 + 7 is square <=> xd*xn^3 + 7*xd^4 is square (multiplying by xd^4, a square). - */ - secp256k1_fe r, t; - VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(xd)); - - secp256k1_fe_mul(&r, xd, xn); /* r = xd*xn */ - secp256k1_fe_sqr(&t, xn); /* t = xn^2 */ - secp256k1_fe_mul(&r, &r, &t); /* r = xd*xn^3 */ - secp256k1_fe_sqr(&t, xd); /* t = xd^2 */ - secp256k1_fe_sqr(&t, &t); /* t = xd^4 */ - VERIFY_CHECK(SECP256K1_B <= 31); - secp256k1_fe_mul_int(&t, SECP256K1_B); /* t = 7*xd^4 */ - secp256k1_fe_add(&r, &t); /* r = xd*xn^3 + 7*xd^4 */ - return secp256k1_fe_is_square_var(&r); -} - -static void secp256k1_ge_to_bytes(unsigned char *buf, const secp256k1_ge *a) { - secp256k1_ge_storage s; - - /* We require that the secp256k1_ge_storage type is exactly 64 bytes. - * This is formally not guaranteed by the C standard, but should hold on any - * sane compiler in the real world. */ - STATIC_ASSERT(sizeof(secp256k1_ge_storage) == 64); - VERIFY_CHECK(!secp256k1_ge_is_infinity(a)); - secp256k1_ge_to_storage(&s, a); - memcpy(buf, &s, 64); -} - -static void secp256k1_ge_from_bytes(secp256k1_ge *r, const unsigned char *buf) { - secp256k1_ge_storage s; - - STATIC_ASSERT(sizeof(secp256k1_ge_storage) == 64); - memcpy(&s, buf, 64); - secp256k1_ge_from_storage(r, &s); -} - -static void secp256k1_ge_to_bytes_ext(unsigned char *data, const secp256k1_ge *ge) { - if (secp256k1_ge_is_infinity(ge)) { - memset(data, 0, 64); - } else { - secp256k1_ge_to_bytes(data, ge); - } -} - -static void secp256k1_ge_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data) { - static const unsigned char zeros[64] = { 0 }; - if (secp256k1_memcmp_var(data, zeros, sizeof(zeros)) == 0) { - secp256k1_ge_set_infinity(ge); - } else { - secp256k1_ge_from_bytes(ge, data); - } -} - -#endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/external/secp256k1/src/hash.h b/external/secp256k1/src/hash.h deleted file mode 100644 index 6d903ca7e0..0000000000 --- a/external/secp256k1/src/hash.h +++ /dev/null @@ -1,44 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_HASH_H -#define SECP256K1_HASH_H - -#include -#include - -typedef struct { - uint32_t s[8]; - unsigned char buf[64]; - uint64_t bytes; -} secp256k1_sha256; - -static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); -static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); -static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); -static void secp256k1_sha256_clear(secp256k1_sha256 *hash); - -typedef struct { - secp256k1_sha256 inner, outer; -} secp256k1_hmac_sha256; - -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); -static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash); - -typedef struct { - unsigned char v[32]; - unsigned char k[32]; - int retry; -} secp256k1_rfc6979_hmac_sha256; - -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); -static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng); - -#endif /* SECP256K1_HASH_H */ diff --git a/external/secp256k1/src/hash_impl.h b/external/secp256k1/src/hash_impl.h deleted file mode 100644 index 956e0ea48b..0000000000 --- a/external/secp256k1/src/hash_impl.h +++ /dev/null @@ -1,299 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_HASH_IMPL_H -#define SECP256K1_HASH_IMPL_H - -#include "hash.h" -#include "util.h" - -#include -#include -#include - -#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) -#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) -#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) -#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) -#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) - -#define Round(a,b,c,d,e,f,g,h,k,w) do { \ - uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ - uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ - (d) += t1; \ - (h) = t1 + t2; \ -} while(0) - -static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { - hash->s[0] = 0x6a09e667ul; - hash->s[1] = 0xbb67ae85ul; - hash->s[2] = 0x3c6ef372ul; - hash->s[3] = 0xa54ff53aul; - hash->s[4] = 0x510e527ful; - hash->s[5] = 0x9b05688cul; - hash->s[6] = 0x1f83d9abul; - hash->s[7] = 0x5be0cd19ul; - hash->bytes = 0; -} - -/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ -static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) { - uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; - uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = secp256k1_read_be32(&buf[0])); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = secp256k1_read_be32(&buf[4])); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = secp256k1_read_be32(&buf[8])); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = secp256k1_read_be32(&buf[12])); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = secp256k1_read_be32(&buf[16])); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = secp256k1_read_be32(&buf[20])); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = secp256k1_read_be32(&buf[24])); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = secp256k1_read_be32(&buf[28])); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = secp256k1_read_be32(&buf[32])); - Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = secp256k1_read_be32(&buf[36])); - Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = secp256k1_read_be32(&buf[40])); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = secp256k1_read_be32(&buf[44])); - Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = secp256k1_read_be32(&buf[48])); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = secp256k1_read_be32(&buf[52])); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = secp256k1_read_be32(&buf[56])); - Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = secp256k1_read_be32(&buf[60])); - - Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); - - s[0] += a; - s[1] += b; - s[2] += c; - s[3] += d; - s[4] += e; - s[5] += f; - s[6] += g; - s[7] += h; -} - -static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { - size_t bufsize = hash->bytes & 0x3F; - hash->bytes += len; - VERIFY_CHECK(hash->bytes >= len); - while (len >= 64 - bufsize) { - /* Fill the buffer, and process it. */ - size_t chunk_len = 64 - bufsize; - memcpy(hash->buf + bufsize, data, chunk_len); - data += chunk_len; - len -= chunk_len; - secp256k1_sha256_transform(hash->s, hash->buf); - bufsize = 0; - } - if (len) { - /* Fill the buffer with what remains. */ - memcpy(hash->buf + bufsize, data, len); - } -} - -static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) { - static const unsigned char pad[64] = {0x80}; - unsigned char sizedesc[8]; - int i; - /* The maximum message size of SHA256 is 2^64-1 bits. */ - VERIFY_CHECK(hash->bytes < ((uint64_t)1 << 61)); - secp256k1_write_be32(&sizedesc[0], hash->bytes >> 29); - secp256k1_write_be32(&sizedesc[4], hash->bytes << 3); - secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); - secp256k1_sha256_write(hash, sizedesc, 8); - for (i = 0; i < 8; i++) { - secp256k1_write_be32(&out32[4*i], hash->s[i]); - hash->s[i] = 0; - } -} - -/* Initializes a sha256 struct and writes the 64 byte string - * SHA256(tag)||SHA256(tag) into it. */ -static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen) { - unsigned char buf[32]; - secp256k1_sha256_initialize(hash); - secp256k1_sha256_write(hash, tag, taglen); - secp256k1_sha256_finalize(hash, buf); - - secp256k1_sha256_initialize(hash); - secp256k1_sha256_write(hash, buf, 32); - secp256k1_sha256_write(hash, buf, 32); -} - -static void secp256k1_sha256_clear(secp256k1_sha256 *hash) { - secp256k1_memclear(hash, sizeof(*hash)); -} - -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { - size_t n; - unsigned char rkey[64]; - if (keylen <= sizeof(rkey)) { - memcpy(rkey, key, keylen); - memset(rkey + keylen, 0, sizeof(rkey) - keylen); - } else { - secp256k1_sha256 sha256; - secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, key, keylen); - secp256k1_sha256_finalize(&sha256, rkey); - memset(rkey + 32, 0, 32); - } - - secp256k1_sha256_initialize(&hash->outer); - for (n = 0; n < sizeof(rkey); n++) { - rkey[n] ^= 0x5c; - } - secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey)); - - secp256k1_sha256_initialize(&hash->inner); - for (n = 0; n < sizeof(rkey); n++) { - rkey[n] ^= 0x5c ^ 0x36; - } - secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); - secp256k1_memclear(rkey, sizeof(rkey)); -} - -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { - secp256k1_sha256_write(&hash->inner, data, size); -} - -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) { - unsigned char temp[32]; - secp256k1_sha256_finalize(&hash->inner, temp); - secp256k1_sha256_write(&hash->outer, temp, 32); - secp256k1_memclear(temp, sizeof(temp)); - secp256k1_sha256_finalize(&hash->outer, out32); -} - -static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash) { - secp256k1_memclear(hash, sizeof(*hash)); -} - -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { - secp256k1_hmac_sha256 hmac; - static const unsigned char zero[1] = {0x00}; - static const unsigned char one[1] = {0x01}; - - memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */ - memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ - - /* RFC6979 3.2.d. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, zero, 1); - secp256k1_hmac_sha256_write(&hmac, key, keylen); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - - /* RFC6979 3.2.f. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, one, 1); - secp256k1_hmac_sha256_write(&hmac, key, keylen); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - rng->retry = 0; -} - -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { - /* RFC6979 3.2.h. */ - static const unsigned char zero[1] = {0x00}; - if (rng->retry) { - secp256k1_hmac_sha256 hmac; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, zero, 1); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - } - - while (outlen > 0) { - secp256k1_hmac_sha256 hmac; - int now = outlen; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); - if (now > 32) { - now = 32; - } - memcpy(out, rng->v, now); - out += now; - outlen -= now; - } - - rng->retry = 1; -} - -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) { - (void) rng; -} - -static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng) { - secp256k1_memclear(rng, sizeof(*rng)); -} - -#undef Round -#undef sigma1 -#undef sigma0 -#undef Sigma1 -#undef Sigma0 -#undef Maj -#undef Ch - -#endif /* SECP256K1_HASH_IMPL_H */ diff --git a/external/secp256k1/src/hsort.h b/external/secp256k1/src/hsort.h deleted file mode 100644 index d54995caad..0000000000 --- a/external/secp256k1/src/hsort.h +++ /dev/null @@ -1,33 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Russell O'Connor, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_HSORT_H -#define SECP256K1_HSORT_H - -#include -#include - -/* In-place, iterative heapsort with an interface matching glibc's qsort_r. This - * is preferred over standard library implementations because they generally - * make no guarantee about being fast for malicious inputs. - * Remember that heapsort is unstable. - * - * In/Out: ptr: pointer to the array to sort. The contents of the array are - * sorted in ascending order according to the comparison function. - * In: count: number of elements in the array. - * size: size in bytes of each element. - * cmp: pointer to a comparison function that is called with two - * arguments that point to the objects being compared. The cmp_data - * argument of secp256k1_hsort is passed as third argument. The - * function must return an integer less than, equal to, or greater - * than zero if the first argument is considered to be respectively - * less than, equal to, or greater than the second. - * cmp_data: pointer passed as third argument to cmp. - */ -static void secp256k1_hsort(void *ptr, size_t count, size_t size, - int (*cmp)(const void *, const void *, void *), - void *cmp_data); -#endif diff --git a/external/secp256k1/src/hsort_impl.h b/external/secp256k1/src/hsort_impl.h deleted file mode 100644 index 1c674ff1c4..0000000000 --- a/external/secp256k1/src/hsort_impl.h +++ /dev/null @@ -1,125 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Russell O'Connor, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_HSORT_IMPL_H -#define SECP256K1_HSORT_IMPL_H - -#include "hsort.h" - -/* An array is a heap when, for all non-zero indexes i, the element at index i - * compares as less than or equal to the element at index parent(i) = (i-1)/2. - */ - -static SECP256K1_INLINE size_t secp256k1_heap_child1(size_t i) { - VERIFY_CHECK(i <= (SIZE_MAX - 1)/2); - return 2*i + 1; -} - -static SECP256K1_INLINE size_t secp256k1_heap_child2(size_t i) { - VERIFY_CHECK(i <= SIZE_MAX/2 - 1); - return secp256k1_heap_child1(i)+1; -} - -static SECP256K1_INLINE void secp256k1_heap_swap64(unsigned char *a, unsigned char *b, size_t len) { - unsigned char tmp[64]; - VERIFY_CHECK(len <= 64); - memcpy(tmp, a, len); - memmove(a, b, len); - memcpy(b, tmp, len); -} - -static SECP256K1_INLINE void secp256k1_heap_swap(unsigned char *arr, size_t i, size_t j, size_t stride) { - unsigned char *a = arr + i*stride; - unsigned char *b = arr + j*stride; - size_t len = stride; - while (64 < len) { - secp256k1_heap_swap64(a + (len - 64), b + (len - 64), 64); - len -= 64; - } - secp256k1_heap_swap64(a, b, len); -} - -/* This function accepts an array arr containing heap_size elements, each of - * size stride. The elements in the array at indices >i satisfy the max-heap - * property, i.e., for any element at index j (where j > i), all of its children - * are smaller than the element itself. The purpose of the function is to update - * the array so that all elements at indices >=i satisfy the max-heap - * property. */ -static SECP256K1_INLINE void secp256k1_heap_down(unsigned char *arr, size_t i, size_t heap_size, size_t stride, - int (*cmp)(const void *, const void *, void *), void *cmp_data) { - while (i < heap_size/2) { - VERIFY_CHECK(i <= SIZE_MAX/2 - 1); - /* Proof: - * i < heap_size/2 - * i + 1 <= heap_size/2 - * 2*i + 2 <= heap_size <= SIZE_MAX - * 2*i <= SIZE_MAX - 2 - */ - - VERIFY_CHECK(secp256k1_heap_child1(i) < heap_size); - /* Proof: - * i < heap_size/2 - * i + 1 <= heap_size/2 - * 2*i + 2 <= heap_size - * 2*i + 1 < heap_size - * child1(i) < heap_size - */ - - /* Let [x] be notation for the contents at arr[x*stride]. - * - * If [child1(i)] > [i] and [child2(i)] > [i], - * swap [i] with the larger child to ensure the new parent is larger - * than both children. When [child1(i)] == [child2(i)], swap [i] with - * [child2(i)]. - * Else if [child1(i)] > [i], swap [i] with [child1(i)]. - * Else if [child2(i)] > [i], swap [i] with [child2(i)]. - */ - if (secp256k1_heap_child2(i) < heap_size - && 0 <= cmp(arr + secp256k1_heap_child2(i)*stride, arr + secp256k1_heap_child1(i)*stride, cmp_data)) { - if (0 < cmp(arr + secp256k1_heap_child2(i)*stride, arr + i*stride, cmp_data)) { - secp256k1_heap_swap(arr, i, secp256k1_heap_child2(i), stride); - i = secp256k1_heap_child2(i); - } else { - /* At this point we have [child2(i)] >= [child1(i)] and we have - * [child2(i)] <= [i], and thus [child1(i)] <= [i] which means - * that the next comparison can be skipped. */ - return; - } - } else if (0 < cmp(arr + secp256k1_heap_child1(i)*stride, arr + i*stride, cmp_data)) { - secp256k1_heap_swap(arr, i, secp256k1_heap_child1(i), stride); - i = secp256k1_heap_child1(i); - } else { - return; - } - } - /* heap_size/2 <= i - * heap_size/2 < i + 1 - * heap_size < 2*i + 2 - * heap_size <= 2*i + 1 - * heap_size <= child1(i) - * Thus child1(i) and child2(i) are now out of bounds and we are at a leaf. - */ -} - -/* In-place heap sort. */ -static void secp256k1_hsort(void *ptr, size_t count, size_t size, - int (*cmp)(const void *, const void *, void *), - void *cmp_data) { - size_t i; - - for (i = count/2; 0 < i; --i) { - secp256k1_heap_down(ptr, i-1, count, size, cmp, cmp_data); - } - for (i = count; 1 < i; --i) { - /* Extract the largest value from the heap */ - secp256k1_heap_swap(ptr, 0, i-1, size); - - /* Repair the heap condition */ - secp256k1_heap_down(ptr, 0, i-1, size, cmp, cmp_data); - } -} - -#endif diff --git a/external/secp256k1/src/int128.h b/external/secp256k1/src/int128.h deleted file mode 100644 index 5355fbfae0..0000000000 --- a/external/secp256k1/src/int128.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef SECP256K1_INT128_H -#define SECP256K1_INT128_H - -#include "util.h" - -#if defined(SECP256K1_WIDEMUL_INT128) -# if defined(SECP256K1_INT128_NATIVE) -# include "int128_native.h" -# elif defined(SECP256K1_INT128_STRUCT) -# include "int128_struct.h" -# else -# error "Please select int128 implementation" -# endif - -/* Construct an unsigned 128-bit value from a high and a low 64-bit value. */ -static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo); - -/* Multiply two unsigned 64-bit values a and b and write the result to r. */ -static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b); - -/* Multiply two unsigned 64-bit values a and b and add the result to r. - * The final result is taken modulo 2^128. - */ -static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b); - -/* Add an unsigned 64-bit value a to r. - * The final result is taken modulo 2^128. - */ -static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a); - -/* Unsigned (logical) right shift. - * Non-constant time in n. - */ -static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n); - -/* Return the low 64-bits of a 128-bit value as an unsigned 64-bit value. */ -static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a); - -/* Return the high 64-bits of a 128-bit value as an unsigned 64-bit value. */ -static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a); - -/* Write an unsigned 64-bit value to r. */ -static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a); - -/* Tests if r is strictly less than to 2^n. - * n must be strictly less than 128. - */ -static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n); - -/* Construct an signed 128-bit value from a high and a low 64-bit value. */ -static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo); - -/* Multiply two signed 64-bit values a and b and write the result to r. */ -static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b); - -/* Multiply two signed 64-bit values a and b and add the result to r. - * Overflow or underflow from the addition is undefined behaviour. - */ -static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b); - -/* Compute a*d - b*c from signed 64-bit values and write the result to r. */ -static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d); - -/* Signed (arithmetic) right shift. - * Non-constant time in b. - */ -static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int b); - -/* Return the input value modulo 2^64. */ -static SECP256K1_INLINE uint64_t secp256k1_i128_to_u64(const secp256k1_int128 *a); - -/* Return the value as a signed 64-bit value. - * Requires the input to be between INT64_MIN and INT64_MAX. - */ -static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a); - -/* Write a signed 64-bit value to r. */ -static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a); - -/* Compare two 128-bit values for equality. */ -static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b); - -/* Tests if r is equal to sign*2^n (sign must be 1 or -1). - * n must be strictly less than 127. - */ -static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign); - -#endif - -#endif diff --git a/external/secp256k1/src/int128_impl.h b/external/secp256k1/src/int128_impl.h deleted file mode 100644 index cfc573408a..0000000000 --- a/external/secp256k1/src/int128_impl.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef SECP256K1_INT128_IMPL_H -#define SECP256K1_INT128_IMPL_H - -#include "util.h" - -#include "int128.h" - -#if defined(SECP256K1_WIDEMUL_INT128) -# if defined(SECP256K1_INT128_NATIVE) -# include "int128_native_impl.h" -# elif defined(SECP256K1_INT128_STRUCT) -# include "int128_struct_impl.h" -# else -# error "Please select int128 implementation" -# endif -#endif - -#endif diff --git a/external/secp256k1/src/int128_native.h b/external/secp256k1/src/int128_native.h deleted file mode 100644 index 7c97aafc74..0000000000 --- a/external/secp256k1/src/int128_native.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SECP256K1_INT128_NATIVE_H -#define SECP256K1_INT128_NATIVE_H - -#include -#include "util.h" - -#if !defined(UINT128_MAX) && defined(__SIZEOF_INT128__) -SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; -SECP256K1_GNUC_EXT typedef __int128 int128_t; -# define UINT128_MAX ((uint128_t)(-1)) -# define INT128_MAX ((int128_t)(UINT128_MAX >> 1)) -# define INT128_MIN (-INT128_MAX - 1) -/* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */ -#endif - -typedef uint128_t secp256k1_uint128; -typedef int128_t secp256k1_int128; - -#endif diff --git a/external/secp256k1/src/int128_native_impl.h b/external/secp256k1/src/int128_native_impl.h deleted file mode 100644 index 7f02e1590b..0000000000 --- a/external/secp256k1/src/int128_native_impl.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef SECP256K1_INT128_NATIVE_IMPL_H -#define SECP256K1_INT128_NATIVE_IMPL_H - -#include "int128.h" -#include "util.h" - -static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) { - *r = (((uint128_t)hi) << 64) + lo; -} - -static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) { - *r = (uint128_t)a * b; -} - -static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) { - *r += (uint128_t)a * b; -} - -static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) { - *r += a; -} - -static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n) { - VERIFY_CHECK(n < 128); - *r >>= n; -} - -static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) { - return (uint64_t)(*a); -} - -static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a) { - return (uint64_t)(*a >> 64); -} - -static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) { - *r = a; -} - -static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n) { - VERIFY_CHECK(n < 128); - return (*r >> n == 0); -} - -static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo) { - *r = (((uint128_t)(uint64_t)hi) << 64) + lo; -} - -static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) { - *r = (int128_t)a * b; -} - -static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) { - int128_t ab = (int128_t)a * b; - VERIFY_CHECK(0 <= ab ? *r <= INT128_MAX - ab : INT128_MIN - ab <= *r); - *r += ab; -} - -static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) { - int128_t ad = (int128_t)a * d; - int128_t bc = (int128_t)b * c; - VERIFY_CHECK(0 <= bc ? INT128_MIN + bc <= ad : ad <= INT128_MAX + bc); - *r = ad - bc; -} - -static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int n) { - VERIFY_CHECK(n < 128); - *r >>= n; -} - -static SECP256K1_INLINE uint64_t secp256k1_i128_to_u64(const secp256k1_int128 *a) { - return (uint64_t)*a; -} - -static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) { - VERIFY_CHECK(INT64_MIN <= *a && *a <= INT64_MAX); - return *a; -} - -static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) { - *r = a; -} - -static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b) { - return *a == *b; -} - -static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) { - VERIFY_CHECK(n < 127); - VERIFY_CHECK(sign == 1 || sign == -1); - return (*r == (int128_t)((uint128_t)sign << n)); -} - -#endif diff --git a/external/secp256k1/src/int128_struct.h b/external/secp256k1/src/int128_struct.h deleted file mode 100644 index 6156f82cc2..0000000000 --- a/external/secp256k1/src/int128_struct.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SECP256K1_INT128_STRUCT_H -#define SECP256K1_INT128_STRUCT_H - -#include -#include "util.h" - -typedef struct { - uint64_t lo; - uint64_t hi; -} secp256k1_uint128; - -typedef secp256k1_uint128 secp256k1_int128; - -#endif diff --git a/external/secp256k1/src/int128_struct_impl.h b/external/secp256k1/src/int128_struct_impl.h deleted file mode 100644 index 962a71d13b..0000000000 --- a/external/secp256k1/src/int128_struct_impl.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef SECP256K1_INT128_STRUCT_IMPL_H -#define SECP256K1_INT128_STRUCT_IMPL_H - -#include "int128.h" -#include "util.h" - -#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) /* MSVC */ -# include -# if defined(_M_ARM64) || defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE) -/* On ARM64 MSVC, use __(u)mulh for the upper half of 64x64 multiplications. - (Define SECP256K1_MSVC_MULH_TEST_OVERRIDE to test this code path on X64, - which supports both __(u)mulh and _umul128.) */ -# if defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE) -# pragma message(__FILE__ ": SECP256K1_MSVC_MULH_TEST_OVERRIDE is defined, forcing use of __(u)mulh.") -# endif -static SECP256K1_INLINE uint64_t secp256k1_umul128(uint64_t a, uint64_t b, uint64_t* hi) { - *hi = __umulh(a, b); - return a * b; -} - -static SECP256K1_INLINE int64_t secp256k1_mul128(int64_t a, int64_t b, int64_t* hi) { - *hi = __mulh(a, b); - return (uint64_t)a * (uint64_t)b; -} -# else -/* On x84_64 MSVC, use native _(u)mul128 for 64x64->128 multiplications. */ -# define secp256k1_umul128 _umul128 -# define secp256k1_mul128 _mul128 -# endif -#else -/* On other systems, emulate 64x64->128 multiplications using 32x32->64 multiplications. */ -static SECP256K1_INLINE uint64_t secp256k1_umul128(uint64_t a, uint64_t b, uint64_t* hi) { - uint64_t ll = (uint64_t)(uint32_t)a * (uint32_t)b; - uint64_t lh = (uint32_t)a * (b >> 32); - uint64_t hl = (a >> 32) * (uint32_t)b; - uint64_t hh = (a >> 32) * (b >> 32); - uint64_t mid34 = (ll >> 32) + (uint32_t)lh + (uint32_t)hl; - *hi = hh + (lh >> 32) + (hl >> 32) + (mid34 >> 32); - return (mid34 << 32) + (uint32_t)ll; -} - -static SECP256K1_INLINE int64_t secp256k1_mul128(int64_t a, int64_t b, int64_t* hi) { - uint64_t ll = (uint64_t)(uint32_t)a * (uint32_t)b; - int64_t lh = (uint32_t)a * (b >> 32); - int64_t hl = (a >> 32) * (uint32_t)b; - int64_t hh = (a >> 32) * (b >> 32); - uint64_t mid34 = (ll >> 32) + (uint32_t)lh + (uint32_t)hl; - *hi = hh + (lh >> 32) + (hl >> 32) + (mid34 >> 32); - return (mid34 << 32) + (uint32_t)ll; -} -#endif - -static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) { - r->hi = hi; - r->lo = lo; -} - -static SECP256K1_INLINE void secp256k1_u128_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) { - r->lo = secp256k1_umul128(a, b, &r->hi); -} - -static SECP256K1_INLINE void secp256k1_u128_accum_mul(secp256k1_uint128 *r, uint64_t a, uint64_t b) { - uint64_t lo, hi; - lo = secp256k1_umul128(a, b, &hi); - r->lo += lo; - r->hi += hi + (r->lo < lo); -} - -static SECP256K1_INLINE void secp256k1_u128_accum_u64(secp256k1_uint128 *r, uint64_t a) { - r->lo += a; - r->hi += r->lo < a; -} - -/* Unsigned (logical) right shift. - * Non-constant time in n. - */ -static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigned int n) { - VERIFY_CHECK(n < 128); - if (n >= 64) { - r->lo = r->hi >> (n-64); - r->hi = 0; - } else if (n > 0) { -#if defined(_MSC_VER) && defined(_M_X64) - VERIFY_CHECK(n < 64); - r->lo = __shiftright128(r->lo, r->hi, n); -#else - r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n; -#endif - r->hi >>= n; - } -} - -static SECP256K1_INLINE uint64_t secp256k1_u128_to_u64(const secp256k1_uint128 *a) { - return a->lo; -} - -static SECP256K1_INLINE uint64_t secp256k1_u128_hi_u64(const secp256k1_uint128 *a) { - return a->hi; -} - -static SECP256K1_INLINE void secp256k1_u128_from_u64(secp256k1_uint128 *r, uint64_t a) { - r->hi = 0; - r->lo = a; -} - -static SECP256K1_INLINE int secp256k1_u128_check_bits(const secp256k1_uint128 *r, unsigned int n) { - VERIFY_CHECK(n < 128); - return n >= 64 ? r->hi >> (n - 64) == 0 - : r->hi == 0 && r->lo >> n == 0; -} - -static SECP256K1_INLINE void secp256k1_i128_load(secp256k1_int128 *r, int64_t hi, uint64_t lo) { - r->hi = hi; - r->lo = lo; -} - -static SECP256K1_INLINE void secp256k1_i128_mul(secp256k1_int128 *r, int64_t a, int64_t b) { - int64_t hi; - r->lo = (uint64_t)secp256k1_mul128(a, b, &hi); - r->hi = (uint64_t)hi; -} - -static SECP256K1_INLINE void secp256k1_i128_accum_mul(secp256k1_int128 *r, int64_t a, int64_t b) { - int64_t hi; - uint64_t lo = (uint64_t)secp256k1_mul128(a, b, &hi); - r->lo += lo; - hi += r->lo < lo; - /* Verify no overflow. - * If r represents a positive value (the sign bit is not set) and the value we are adding is a positive value (the sign bit is not set), - * then we require that the resulting value also be positive (the sign bit is not set). - * Note that (X <= Y) means (X implies Y) when X and Y are boolean values (i.e. 0 or 1). - */ - VERIFY_CHECK((r->hi <= 0x7fffffffffffffffu && (uint64_t)hi <= 0x7fffffffffffffffu) <= (r->hi + (uint64_t)hi <= 0x7fffffffffffffffu)); - /* Verify no underflow. - * If r represents a negative value (the sign bit is set) and the value we are adding is a negative value (the sign bit is set), - * then we require that the resulting value also be negative (the sign bit is set). - */ - VERIFY_CHECK((r->hi > 0x7fffffffffffffffu && (uint64_t)hi > 0x7fffffffffffffffu) <= (r->hi + (uint64_t)hi > 0x7fffffffffffffffu)); - r->hi += hi; -} - -static SECP256K1_INLINE void secp256k1_i128_dissip_mul(secp256k1_int128 *r, int64_t a, int64_t b) { - int64_t hi; - uint64_t lo = (uint64_t)secp256k1_mul128(a, b, &hi); - hi += r->lo < lo; - /* Verify no overflow. - * If r represents a positive value (the sign bit is not set) and the value we are subtracting is a negative value (the sign bit is set), - * then we require that the resulting value also be positive (the sign bit is not set). - */ - VERIFY_CHECK((r->hi <= 0x7fffffffffffffffu && (uint64_t)hi > 0x7fffffffffffffffu) <= (r->hi - (uint64_t)hi <= 0x7fffffffffffffffu)); - /* Verify no underflow. - * If r represents a negative value (the sign bit is set) and the value we are subtracting is a positive value (the sign sign bit is not set), - * then we require that the resulting value also be negative (the sign bit is set). - */ - VERIFY_CHECK((r->hi > 0x7fffffffffffffffu && (uint64_t)hi <= 0x7fffffffffffffffu) <= (r->hi - (uint64_t)hi > 0x7fffffffffffffffu)); - r->hi -= hi; - r->lo -= lo; -} - -static SECP256K1_INLINE void secp256k1_i128_det(secp256k1_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) { - secp256k1_i128_mul(r, a, d); - secp256k1_i128_dissip_mul(r, b, c); -} - -/* Signed (arithmetic) right shift. - * Non-constant time in n. - */ -static SECP256K1_INLINE void secp256k1_i128_rshift(secp256k1_int128 *r, unsigned int n) { - VERIFY_CHECK(n < 128); - if (n >= 64) { - r->lo = (uint64_t)((int64_t)(r->hi) >> (n-64)); - r->hi = (uint64_t)((int64_t)(r->hi) >> 63); - } else if (n > 0) { - r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n; - r->hi = (uint64_t)((int64_t)(r->hi) >> n); - } -} - -static SECP256K1_INLINE uint64_t secp256k1_i128_to_u64(const secp256k1_int128 *a) { - return a->lo; -} - -static SECP256K1_INLINE int64_t secp256k1_i128_to_i64(const secp256k1_int128 *a) { - /* Verify that a represents a 64 bit signed value by checking that the high bits are a sign extension of the low bits. */ - VERIFY_CHECK(a->hi == -(a->lo >> 63)); - return (int64_t)secp256k1_i128_to_u64(a); -} - -static SECP256K1_INLINE void secp256k1_i128_from_i64(secp256k1_int128 *r, int64_t a) { - r->hi = (uint64_t)(a >> 63); - r->lo = (uint64_t)a; -} - -static SECP256K1_INLINE int secp256k1_i128_eq_var(const secp256k1_int128 *a, const secp256k1_int128 *b) { - return a->hi == b->hi && a->lo == b->lo; -} - -static SECP256K1_INLINE int secp256k1_i128_check_pow2(const secp256k1_int128 *r, unsigned int n, int sign) { - VERIFY_CHECK(n < 127); - VERIFY_CHECK(sign == 1 || sign == -1); - return n >= 64 ? r->hi == (uint64_t)sign << (n - 64) && r->lo == 0 - : r->hi == (uint64_t)(sign >> 1) && r->lo == (uint64_t)sign << n; -} - -#endif diff --git a/external/secp256k1/src/modinv32.h b/external/secp256k1/src/modinv32.h deleted file mode 100644 index 846c642f8c..0000000000 --- a/external/secp256k1/src/modinv32.h +++ /dev/null @@ -1,43 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Peter Dettman * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef SECP256K1_MODINV32_H -#define SECP256K1_MODINV32_H - -#include "util.h" - -/* A signed 30-bit limb representation of integers. - * - * Its value is sum(v[i] * 2^(30*i), i=0..8). */ -typedef struct { - int32_t v[9]; -} secp256k1_modinv32_signed30; - -typedef struct { - /* The modulus in signed30 notation, must be odd and in [3, 2^256]. */ - secp256k1_modinv32_signed30 modulus; - - /* modulus^{-1} mod 2^30 */ - uint32_t modulus_inv30; -} secp256k1_modinv32_modinfo; - -/* Replace x with its modular inverse mod modinfo->modulus. x must be in range [0, modulus). - * If x is zero, the result will be zero as well. If not, the inverse must exist (i.e., the gcd of - * x and modulus must be 1). These rules are automatically satisfied if the modulus is prime. - * - * On output, all of x's limbs will be in [0, 2^30). - */ -static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); - -/* Same as secp256k1_modinv32_var, but constant time in x (not in the modulus). */ -static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); - -/* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus - * cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result - * cannot be computed. */ -static int secp256k1_jacobi32_maybe_var(const secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo); - -#endif /* SECP256K1_MODINV32_H */ diff --git a/external/secp256k1/src/modinv32_impl.h b/external/secp256k1/src/modinv32_impl.h deleted file mode 100644 index 981d2abc6d..0000000000 --- a/external/secp256k1/src/modinv32_impl.h +++ /dev/null @@ -1,725 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Peter Dettman * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef SECP256K1_MODINV32_IMPL_H -#define SECP256K1_MODINV32_IMPL_H - -#include "modinv32.h" - -#include "util.h" - -#include - -/* This file implements modular inversion based on the paper "Fast constant-time gcd computation and - * modular inversion" by Daniel J. Bernstein and Bo-Yin Yang. - * - * For an explanation of the algorithm, see doc/safegcd_implementation.md. This file contains an - * implementation for N=30, using 30-bit signed limbs represented as int32_t. - */ - -#ifdef VERIFY -static const secp256k1_modinv32_signed30 SECP256K1_SIGNED30_ONE = {{1}}; - -/* Compute a*factor and put it in r. All but the top limb in r will be in range [0,2^30). */ -static void secp256k1_modinv32_mul_30(secp256k1_modinv32_signed30 *r, const secp256k1_modinv32_signed30 *a, int alen, int32_t factor) { - const int32_t M30 = (int32_t)(UINT32_MAX >> 2); - int64_t c = 0; - int i; - for (i = 0; i < 8; ++i) { - if (i < alen) c += (int64_t)a->v[i] * factor; - r->v[i] = (int32_t)c & M30; c >>= 30; - } - if (8 < alen) c += (int64_t)a->v[8] * factor; - VERIFY_CHECK(c == (int32_t)c); - r->v[8] = (int32_t)c; -} - -/* Return -1 for ab*factor. A consists of alen limbs; b has 9. */ -static int secp256k1_modinv32_mul_cmp_30(const secp256k1_modinv32_signed30 *a, int alen, const secp256k1_modinv32_signed30 *b, int32_t factor) { - int i; - secp256k1_modinv32_signed30 am, bm; - secp256k1_modinv32_mul_30(&am, a, alen, 1); /* Normalize all but the top limb of a. */ - secp256k1_modinv32_mul_30(&bm, b, 9, factor); - for (i = 0; i < 8; ++i) { - /* Verify that all but the top limb of a and b are normalized. */ - VERIFY_CHECK(am.v[i] >> 30 == 0); - VERIFY_CHECK(bm.v[i] >> 30 == 0); - } - for (i = 8; i >= 0; --i) { - if (am.v[i] < bm.v[i]) return -1; - if (am.v[i] > bm.v[i]) return 1; - } - return 0; -} -#endif - -/* Take as input a signed30 number in range (-2*modulus,modulus), and add a multiple of the modulus - * to it to bring it to range [0,modulus). If sign < 0, the input will also be negated in the - * process. The input must have limbs in range (-2^30,2^30). The output will have limbs in range - * [0,2^30). */ -static void secp256k1_modinv32_normalize_30(secp256k1_modinv32_signed30 *r, int32_t sign, const secp256k1_modinv32_modinfo *modinfo) { - const int32_t M30 = (int32_t)(UINT32_MAX >> 2); - int32_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4], - r5 = r->v[5], r6 = r->v[6], r7 = r->v[7], r8 = r->v[8]; - volatile int32_t cond_add, cond_negate; - -#ifdef VERIFY - /* Verify that all limbs are in range (-2^30,2^30). */ - int i; - for (i = 0; i < 9; ++i) { - VERIFY_CHECK(r->v[i] >= -M30); - VERIFY_CHECK(r->v[i] <= M30); - } - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, -2) > 0); /* r > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 1) < 0); /* r < modulus */ -#endif - - /* In a first step, add the modulus if the input is negative, and then negate if requested. - * This brings r from range (-2*modulus,modulus) to range (-modulus,modulus). As all input - * limbs are in range (-2^30,2^30), this cannot overflow an int32_t. Note that the right - * shifts below are signed sign-extending shifts (see assumptions.h for tests that that is - * indeed the behavior of the right shift operator). */ - cond_add = r8 >> 31; - r0 += modinfo->modulus.v[0] & cond_add; - r1 += modinfo->modulus.v[1] & cond_add; - r2 += modinfo->modulus.v[2] & cond_add; - r3 += modinfo->modulus.v[3] & cond_add; - r4 += modinfo->modulus.v[4] & cond_add; - r5 += modinfo->modulus.v[5] & cond_add; - r6 += modinfo->modulus.v[6] & cond_add; - r7 += modinfo->modulus.v[7] & cond_add; - r8 += modinfo->modulus.v[8] & cond_add; - cond_negate = sign >> 31; - r0 = (r0 ^ cond_negate) - cond_negate; - r1 = (r1 ^ cond_negate) - cond_negate; - r2 = (r2 ^ cond_negate) - cond_negate; - r3 = (r3 ^ cond_negate) - cond_negate; - r4 = (r4 ^ cond_negate) - cond_negate; - r5 = (r5 ^ cond_negate) - cond_negate; - r6 = (r6 ^ cond_negate) - cond_negate; - r7 = (r7 ^ cond_negate) - cond_negate; - r8 = (r8 ^ cond_negate) - cond_negate; - /* Propagate the top bits, to bring limbs back to range (-2^30,2^30). */ - r1 += r0 >> 30; r0 &= M30; - r2 += r1 >> 30; r1 &= M30; - r3 += r2 >> 30; r2 &= M30; - r4 += r3 >> 30; r3 &= M30; - r5 += r4 >> 30; r4 &= M30; - r6 += r5 >> 30; r5 &= M30; - r7 += r6 >> 30; r6 &= M30; - r8 += r7 >> 30; r7 &= M30; - - /* In a second step add the modulus again if the result is still negative, bringing r to range - * [0,modulus). */ - cond_add = r8 >> 31; - r0 += modinfo->modulus.v[0] & cond_add; - r1 += modinfo->modulus.v[1] & cond_add; - r2 += modinfo->modulus.v[2] & cond_add; - r3 += modinfo->modulus.v[3] & cond_add; - r4 += modinfo->modulus.v[4] & cond_add; - r5 += modinfo->modulus.v[5] & cond_add; - r6 += modinfo->modulus.v[6] & cond_add; - r7 += modinfo->modulus.v[7] & cond_add; - r8 += modinfo->modulus.v[8] & cond_add; - /* And propagate again. */ - r1 += r0 >> 30; r0 &= M30; - r2 += r1 >> 30; r1 &= M30; - r3 += r2 >> 30; r2 &= M30; - r4 += r3 >> 30; r3 &= M30; - r5 += r4 >> 30; r4 &= M30; - r6 += r5 >> 30; r5 &= M30; - r7 += r6 >> 30; r6 &= M30; - r8 += r7 >> 30; r7 &= M30; - - r->v[0] = r0; - r->v[1] = r1; - r->v[2] = r2; - r->v[3] = r3; - r->v[4] = r4; - r->v[5] = r5; - r->v[6] = r6; - r->v[7] = r7; - r->v[8] = r8; - - VERIFY_CHECK(r0 >> 30 == 0); - VERIFY_CHECK(r1 >> 30 == 0); - VERIFY_CHECK(r2 >> 30 == 0); - VERIFY_CHECK(r3 >> 30 == 0); - VERIFY_CHECK(r4 >> 30 == 0); - VERIFY_CHECK(r5 >> 30 == 0); - VERIFY_CHECK(r6 >> 30 == 0); - VERIFY_CHECK(r7 >> 30 == 0); - VERIFY_CHECK(r8 >> 30 == 0); - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 0) >= 0); /* r >= 0 */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 1) < 0); /* r < modulus */ -} - -/* Data type for transition matrices (see section 3 of explanation). - * - * t = [ u v ] - * [ q r ] - */ -typedef struct { - int32_t u, v, q, r; -} secp256k1_modinv32_trans2x2; - -/* Compute the transition matrix and zeta for 30 divsteps. - * - * Input: zeta: initial zeta - * f0: bottom limb of initial f - * g0: bottom limb of initial g - * Output: t: transition matrix - * Return: final zeta - * - * Implements the divsteps_n_matrix function from the explanation. - */ -static int32_t secp256k1_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_t g0, secp256k1_modinv32_trans2x2 *t) { - /* u,v,q,r are the elements of the transformation matrix being built up, - * starting with the identity matrix. Semantically they are signed integers - * in range [-2^30,2^30], but here represented as unsigned mod 2^32. This - * permits left shifting (which is UB for negative numbers). The range - * being inside [-2^31,2^31) means that casting to signed works correctly. - */ - uint32_t u = 1, v = 0, q = 0, r = 1; - volatile uint32_t c1, c2; - uint32_t mask1, mask2, f = f0, g = g0, x, y, z; - int i; - - for (i = 0; i < 30; ++i) { - VERIFY_CHECK((f & 1) == 1); /* f must always be odd */ - VERIFY_CHECK((u * f0 + v * g0) == f << i); - VERIFY_CHECK((q * f0 + r * g0) == g << i); - /* Compute conditional masks for (zeta < 0) and for (g & 1). */ - c1 = zeta >> 31; - mask1 = c1; - c2 = g & 1; - mask2 = -c2; - /* Compute x,y,z, conditionally negated versions of f,u,v. */ - x = (f ^ mask1) - mask1; - y = (u ^ mask1) - mask1; - z = (v ^ mask1) - mask1; - /* Conditionally add x,y,z to g,q,r. */ - g += x & mask2; - q += y & mask2; - r += z & mask2; - /* In what follows, mask1 is a condition mask for (zeta < 0) and (g & 1). */ - mask1 &= mask2; - /* Conditionally change zeta into -zeta-2 or zeta-1. */ - zeta = (zeta ^ mask1) - 1; - /* Conditionally add g,q,r to f,u,v. */ - f += g & mask1; - u += q & mask1; - v += r & mask1; - /* Shifts */ - g >>= 1; - u <<= 1; - v <<= 1; - /* Bounds on zeta that follow from the bounds on iteration count (max 20*30 divsteps). */ - VERIFY_CHECK(zeta >= -601 && zeta <= 601); - } - /* Return data in t and return value. */ - t->u = (int32_t)u; - t->v = (int32_t)v; - t->q = (int32_t)q; - t->r = (int32_t)r; - /* The determinant of t must be a power of two. This guarantees that multiplication with t - * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which - * will be divided out again). As each divstep's individual matrix has determinant 2, the - * aggregate of 30 of them will have determinant 2^30. */ - VERIFY_CHECK((int64_t)t->u * t->r - (int64_t)t->v * t->q == ((int64_t)1) << 30); - return zeta; -} - -/* secp256k1_modinv32_inv256[i] = -(2*i+1)^-1 (mod 256) */ -static const uint8_t secp256k1_modinv32_inv256[128] = { - 0xFF, 0x55, 0x33, 0x49, 0xC7, 0x5D, 0x3B, 0x11, 0x0F, 0xE5, 0xC3, 0x59, - 0xD7, 0xED, 0xCB, 0x21, 0x1F, 0x75, 0x53, 0x69, 0xE7, 0x7D, 0x5B, 0x31, - 0x2F, 0x05, 0xE3, 0x79, 0xF7, 0x0D, 0xEB, 0x41, 0x3F, 0x95, 0x73, 0x89, - 0x07, 0x9D, 0x7B, 0x51, 0x4F, 0x25, 0x03, 0x99, 0x17, 0x2D, 0x0B, 0x61, - 0x5F, 0xB5, 0x93, 0xA9, 0x27, 0xBD, 0x9B, 0x71, 0x6F, 0x45, 0x23, 0xB9, - 0x37, 0x4D, 0x2B, 0x81, 0x7F, 0xD5, 0xB3, 0xC9, 0x47, 0xDD, 0xBB, 0x91, - 0x8F, 0x65, 0x43, 0xD9, 0x57, 0x6D, 0x4B, 0xA1, 0x9F, 0xF5, 0xD3, 0xE9, - 0x67, 0xFD, 0xDB, 0xB1, 0xAF, 0x85, 0x63, 0xF9, 0x77, 0x8D, 0x6B, 0xC1, - 0xBF, 0x15, 0xF3, 0x09, 0x87, 0x1D, 0xFB, 0xD1, 0xCF, 0xA5, 0x83, 0x19, - 0x97, 0xAD, 0x8B, 0xE1, 0xDF, 0x35, 0x13, 0x29, 0xA7, 0x3D, 0x1B, 0xF1, - 0xEF, 0xC5, 0xA3, 0x39, 0xB7, 0xCD, 0xAB, 0x01 -}; - -/* Compute the transition matrix and eta for 30 divsteps (variable time). - * - * Input: eta: initial eta - * f0: bottom limb of initial f - * g0: bottom limb of initial g - * Output: t: transition matrix - * Return: final eta - * - * Implements the divsteps_n_matrix_var function from the explanation. - */ -static int32_t secp256k1_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, secp256k1_modinv32_trans2x2 *t) { - /* Transformation matrix; see comments in secp256k1_modinv32_divsteps_30. */ - uint32_t u = 1, v = 0, q = 0, r = 1; - uint32_t f = f0, g = g0, m; - uint16_t w; - int i = 30, limit, zeros; - - for (;;) { - /* Use a sentinel bit to count zeros only up to i. */ - zeros = secp256k1_ctz32_var(g | (UINT32_MAX << i)); - /* Perform zeros divsteps at once; they all just divide g by two. */ - g >>= zeros; - u <<= zeros; - v <<= zeros; - eta -= zeros; - i -= zeros; - /* We're done once we've done 30 divsteps. */ - if (i == 0) break; - VERIFY_CHECK((f & 1) == 1); - VERIFY_CHECK((g & 1) == 1); - VERIFY_CHECK((u * f0 + v * g0) == f << (30 - i)); - VERIFY_CHECK((q * f0 + r * g0) == g << (30 - i)); - /* Bounds on eta that follow from the bounds on iteration count (max 25*30 divsteps). */ - VERIFY_CHECK(eta >= -751 && eta <= 751); - /* If eta is negative, negate it and replace f,g with g,-f. */ - if (eta < 0) { - uint32_t tmp; - eta = -eta; - tmp = f; f = g; g = -tmp; - tmp = u; u = q; q = -tmp; - tmp = v; v = r; r = -tmp; - } - /* eta is now >= 0. In what follows we're going to cancel out the bottom bits of g. No more - * than i can be cancelled out (as we'd be done before that point), and no more than eta+1 - * can be done as its sign will flip once that happens. */ - limit = ((int)eta + 1) > i ? i : ((int)eta + 1); - /* m is a mask for the bottom min(limit, 8) bits (our table only supports 8 bits). */ - VERIFY_CHECK(limit > 0 && limit <= 30); - m = (UINT32_MAX >> (32 - limit)) & 255U; - /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */ - w = (g * secp256k1_modinv32_inv256[(f >> 1) & 127]) & m; - /* Do so. */ - g += f * w; - q += u * w; - r += v * w; - VERIFY_CHECK((g & m) == 0); - } - /* Return data in t and return value. */ - t->u = (int32_t)u; - t->v = (int32_t)v; - t->q = (int32_t)q; - t->r = (int32_t)r; - /* The determinant of t must be a power of two. This guarantees that multiplication with t - * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which - * will be divided out again). As each divstep's individual matrix has determinant 2, the - * aggregate of 30 of them will have determinant 2^30. */ - VERIFY_CHECK((int64_t)t->u * t->r - (int64_t)t->v * t->q == ((int64_t)1) << 30); - return eta; -} - -/* Compute the transition matrix and eta for 30 posdivsteps (variable time, eta=-delta), and keeps track - * of the Jacobi symbol along the way. f0 and g0 must be f and g mod 2^32 rather than 2^30, because - * Jacobi tracking requires knowing (f mod 8) rather than just (f mod 2). - * - * Input: eta: initial eta - * f0: bottom limb of initial f - * g0: bottom limb of initial g - * Output: t: transition matrix - * Input/Output: (*jacp & 1) is bitflipped if and only if the Jacobi symbol of (f | g) changes sign - * by applying the returned transformation matrix to it. The other bits of *jacp may - * change, but are meaningless. - * Return: final eta - */ -static int32_t secp256k1_modinv32_posdivsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, secp256k1_modinv32_trans2x2 *t, int *jacp) { - /* Transformation matrix. */ - uint32_t u = 1, v = 0, q = 0, r = 1; - uint32_t f = f0, g = g0, m; - uint16_t w; - int i = 30, limit, zeros; - int jac = *jacp; - - for (;;) { - /* Use a sentinel bit to count zeros only up to i. */ - zeros = secp256k1_ctz32_var(g | (UINT32_MAX << i)); - /* Perform zeros divsteps at once; they all just divide g by two. */ - g >>= zeros; - u <<= zeros; - v <<= zeros; - eta -= zeros; - i -= zeros; - /* Update the bottom bit of jac: when dividing g by an odd power of 2, - * if (f mod 8) is 3 or 5, the Jacobi symbol changes sign. */ - jac ^= (zeros & ((f >> 1) ^ (f >> 2))); - /* We're done once we've done 30 posdivsteps. */ - if (i == 0) break; - VERIFY_CHECK((f & 1) == 1); - VERIFY_CHECK((g & 1) == 1); - VERIFY_CHECK((u * f0 + v * g0) == f << (30 - i)); - VERIFY_CHECK((q * f0 + r * g0) == g << (30 - i)); - /* If eta is negative, negate it and replace f,g with g,f. */ - if (eta < 0) { - uint32_t tmp; - eta = -eta; - /* Update bottom bit of jac: when swapping f and g, the Jacobi symbol changes sign - * if both f and g are 3 mod 4. */ - jac ^= ((f & g) >> 1); - tmp = f; f = g; g = tmp; - tmp = u; u = q; q = tmp; - tmp = v; v = r; r = tmp; - } - /* eta is now >= 0. In what follows we're going to cancel out the bottom bits of g. No more - * than i can be cancelled out (as we'd be done before that point), and no more than eta+1 - * can be done as its sign will flip once that happens. */ - limit = ((int)eta + 1) > i ? i : ((int)eta + 1); - /* m is a mask for the bottom min(limit, 8) bits (our table only supports 8 bits). */ - VERIFY_CHECK(limit > 0 && limit <= 30); - m = (UINT32_MAX >> (32 - limit)) & 255U; - /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */ - w = (g * secp256k1_modinv32_inv256[(f >> 1) & 127]) & m; - /* Do so. */ - g += f * w; - q += u * w; - r += v * w; - VERIFY_CHECK((g & m) == 0); - } - /* Return data in t and return value. */ - t->u = (int32_t)u; - t->v = (int32_t)v; - t->q = (int32_t)q; - t->r = (int32_t)r; - /* The determinant of t must be a power of two. This guarantees that multiplication with t - * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which - * will be divided out again). As each divstep's individual matrix has determinant 2 or -2, - * the aggregate of 30 of them will have determinant 2^30 or -2^30. */ - VERIFY_CHECK((int64_t)t->u * t->r - (int64_t)t->v * t->q == ((int64_t)1) << 30 || - (int64_t)t->u * t->r - (int64_t)t->v * t->q == -(((int64_t)1) << 30)); - *jacp = jac; - return eta; -} - -/* Compute (t/2^30) * [d, e] mod modulus, where t is a transition matrix for 30 divsteps. - * - * On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be in range - * (-2^30,2^30). - * - * This implements the update_de function from the explanation. - */ -static void secp256k1_modinv32_update_de_30(secp256k1_modinv32_signed30 *d, secp256k1_modinv32_signed30 *e, const secp256k1_modinv32_trans2x2 *t, const secp256k1_modinv32_modinfo* modinfo) { - const int32_t M30 = (int32_t)(UINT32_MAX >> 2); - const int32_t u = t->u, v = t->v, q = t->q, r = t->r; - int32_t di, ei, md, me, sd, se; - int64_t cd, ce; - int i; - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, 1) < 0); /* d < modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, 1) < 0); /* e < modulus */ - VERIFY_CHECK(labs(u) <= (M30 + 1 - labs(v))); /* |u|+|v| <= 2^30 */ - VERIFY_CHECK(labs(q) <= (M30 + 1 - labs(r))); /* |q|+|r| <= 2^30 */ - - /* [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative. */ - sd = d->v[8] >> 31; - se = e->v[8] >> 31; - md = (u & sd) + (v & se); - me = (q & sd) + (r & se); - /* Begin computing t*[d,e]. */ - di = d->v[0]; - ei = e->v[0]; - cd = (int64_t)u * di + (int64_t)v * ei; - ce = (int64_t)q * di + (int64_t)r * ei; - /* Correct md,me so that t*[d,e]+modulus*[md,me] has 30 zero bottom bits. */ - md -= (modinfo->modulus_inv30 * (uint32_t)cd + md) & M30; - me -= (modinfo->modulus_inv30 * (uint32_t)ce + me) & M30; - /* Update the beginning of computation for t*[d,e]+modulus*[md,me] now md,me are known. */ - cd += (int64_t)modinfo->modulus.v[0] * md; - ce += (int64_t)modinfo->modulus.v[0] * me; - /* Verify that the low 30 bits of the computation are indeed zero, and then throw them away. */ - VERIFY_CHECK(((int32_t)cd & M30) == 0); cd >>= 30; - VERIFY_CHECK(((int32_t)ce & M30) == 0); ce >>= 30; - /* Now iteratively compute limb i=1..8 of t*[d,e]+modulus*[md,me], and store them in output - * limb i-1 (shifting down by 30 bits). */ - for (i = 1; i < 9; ++i) { - di = d->v[i]; - ei = e->v[i]; - cd += (int64_t)u * di + (int64_t)v * ei; - ce += (int64_t)q * di + (int64_t)r * ei; - cd += (int64_t)modinfo->modulus.v[i] * md; - ce += (int64_t)modinfo->modulus.v[i] * me; - d->v[i - 1] = (int32_t)cd & M30; cd >>= 30; - e->v[i - 1] = (int32_t)ce & M30; ce >>= 30; - } - /* What remains is limb 9 of t*[d,e]+modulus*[md,me]; store it as output limb 8. */ - d->v[8] = (int32_t)cd; - e->v[8] = (int32_t)ce; - - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, 1) < 0); /* d < modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, 1) < 0); /* e < modulus */ -} - -/* Compute (t/2^30) * [f, g], where t is a transition matrix for 30 divsteps. - * - * This implements the update_fg function from the explanation. - */ -static void secp256k1_modinv32_update_fg_30(secp256k1_modinv32_signed30 *f, secp256k1_modinv32_signed30 *g, const secp256k1_modinv32_trans2x2 *t) { - const int32_t M30 = (int32_t)(UINT32_MAX >> 2); - const int32_t u = t->u, v = t->v, q = t->q, r = t->r; - int32_t fi, gi; - int64_t cf, cg; - int i; - /* Start computing t*[f,g]. */ - fi = f->v[0]; - gi = g->v[0]; - cf = (int64_t)u * fi + (int64_t)v * gi; - cg = (int64_t)q * fi + (int64_t)r * gi; - /* Verify that the bottom 30 bits of the result are zero, and then throw them away. */ - VERIFY_CHECK(((int32_t)cf & M30) == 0); cf >>= 30; - VERIFY_CHECK(((int32_t)cg & M30) == 0); cg >>= 30; - /* Now iteratively compute limb i=1..8 of t*[f,g], and store them in output limb i-1 (shifting - * down by 30 bits). */ - for (i = 1; i < 9; ++i) { - fi = f->v[i]; - gi = g->v[i]; - cf += (int64_t)u * fi + (int64_t)v * gi; - cg += (int64_t)q * fi + (int64_t)r * gi; - f->v[i - 1] = (int32_t)cf & M30; cf >>= 30; - g->v[i - 1] = (int32_t)cg & M30; cg >>= 30; - } - /* What remains is limb 9 of t*[f,g]; store it as output limb 8. */ - f->v[8] = (int32_t)cf; - g->v[8] = (int32_t)cg; -} - -/* Compute (t/2^30) * [f, g], where t is a transition matrix for 30 divsteps. - * - * Version that operates on a variable number of limbs in f and g. - * - * This implements the update_fg function from the explanation in modinv64_impl.h. - */ -static void secp256k1_modinv32_update_fg_30_var(int len, secp256k1_modinv32_signed30 *f, secp256k1_modinv32_signed30 *g, const secp256k1_modinv32_trans2x2 *t) { - const int32_t M30 = (int32_t)(UINT32_MAX >> 2); - const int32_t u = t->u, v = t->v, q = t->q, r = t->r; - int32_t fi, gi; - int64_t cf, cg; - int i; - VERIFY_CHECK(len > 0); - /* Start computing t*[f,g]. */ - fi = f->v[0]; - gi = g->v[0]; - cf = (int64_t)u * fi + (int64_t)v * gi; - cg = (int64_t)q * fi + (int64_t)r * gi; - /* Verify that the bottom 62 bits of the result are zero, and then throw them away. */ - VERIFY_CHECK(((int32_t)cf & M30) == 0); cf >>= 30; - VERIFY_CHECK(((int32_t)cg & M30) == 0); cg >>= 30; - /* Now iteratively compute limb i=1..len of t*[f,g], and store them in output limb i-1 (shifting - * down by 30 bits). */ - for (i = 1; i < len; ++i) { - fi = f->v[i]; - gi = g->v[i]; - cf += (int64_t)u * fi + (int64_t)v * gi; - cg += (int64_t)q * fi + (int64_t)r * gi; - f->v[i - 1] = (int32_t)cf & M30; cf >>= 30; - g->v[i - 1] = (int32_t)cg & M30; cg >>= 30; - } - /* What remains is limb (len) of t*[f,g]; store it as output limb (len-1). */ - f->v[len - 1] = (int32_t)cf; - g->v[len - 1] = (int32_t)cg; -} - -/* Compute the inverse of x modulo modinfo->modulus, and replace x with it (constant time in x). */ -static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo) { - /* Start with d=0, e=1, f=modulus, g=x, zeta=-1. */ - secp256k1_modinv32_signed30 d = {{0}}; - secp256k1_modinv32_signed30 e = {{1}}; - secp256k1_modinv32_signed30 f = modinfo->modulus; - secp256k1_modinv32_signed30 g = *x; - int i; - int32_t zeta = -1; /* zeta = -(delta+1/2); delta is initially 1/2. */ - - /* Do 20 iterations of 30 divsteps each = 600 divsteps. 590 suffices for 256-bit inputs. */ - for (i = 0; i < 20; ++i) { - /* Compute transition matrix and new zeta after 30 divsteps. */ - secp256k1_modinv32_trans2x2 t; - zeta = secp256k1_modinv32_divsteps_30(zeta, f.v[0], g.v[0], &t); - /* Update d,e using that transition matrix. */ - secp256k1_modinv32_update_de_30(&d, &e, &t, modinfo); - /* Update f,g using that transition matrix. */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, 1) < 0); /* g < modulus */ - - secp256k1_modinv32_update_fg_30(&f, &g, &t); - - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, 1) < 0); /* g < modulus */ - } - - /* At this point sufficient iterations have been performed that g must have reached 0 - * and (if g was not originally 0) f must now equal +/- GCD of the initial f, g - * values i.e. +/- 1, and d now contains +/- the modular inverse. */ - - /* g == 0 */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, 9, &SECP256K1_SIGNED30_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, 9, &SECP256K1_SIGNED30_ONE, -1) == 0 || - secp256k1_modinv32_mul_cmp_30(&f, 9, &SECP256K1_SIGNED30_ONE, 1) == 0 || - (secp256k1_modinv32_mul_cmp_30(x, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - secp256k1_modinv32_mul_cmp_30(&d, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - secp256k1_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) == 0)); - - /* Optionally negate d, normalize to [0,modulus), and return it. */ - secp256k1_modinv32_normalize_30(&d, f.v[8], modinfo); - *x = d; -} - -/* Compute the inverse of x modulo modinfo->modulus, and replace x with it (variable time). */ -static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo) { - /* Start with d=0, e=1, f=modulus, g=x, eta=-1. */ - secp256k1_modinv32_signed30 d = {{0, 0, 0, 0, 0, 0, 0, 0, 0}}; - secp256k1_modinv32_signed30 e = {{1, 0, 0, 0, 0, 0, 0, 0, 0}}; - secp256k1_modinv32_signed30 f = modinfo->modulus; - secp256k1_modinv32_signed30 g = *x; -#ifdef VERIFY - int i = 0; -#endif - int j, len = 9; - int32_t eta = -1; /* eta = -delta; delta is initially 1 (faster for the variable-time code) */ - int32_t cond, fn, gn; - - /* Do iterations of 30 divsteps each until g=0. */ - while (1) { - /* Compute transition matrix and new eta after 30 divsteps. */ - secp256k1_modinv32_trans2x2 t; - eta = secp256k1_modinv32_divsteps_30_var(eta, f.v[0], g.v[0], &t); - /* Update d,e using that transition matrix. */ - secp256k1_modinv32_update_de_30(&d, &e, &t, modinfo); - /* Update f,g using that transition matrix. */ - - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - - secp256k1_modinv32_update_fg_30_var(len, &f, &g, &t); - /* If the bottom limb of g is 0, there is a chance g=0. */ - if (g.v[0] == 0) { - cond = 0; - /* Check if all other limbs are also 0. */ - for (j = 1; j < len; ++j) { - cond |= g.v[j]; - } - /* If so, we're done. */ - if (cond == 0) break; - } - - /* Determine if len>1 and limb (len-1) of both f and g is 0 or -1. */ - fn = f.v[len - 1]; - gn = g.v[len - 1]; - cond = ((int32_t)len - 2) >> 31; - cond |= fn ^ (fn >> 31); - cond |= gn ^ (gn >> 31); - /* If so, reduce length, propagating the sign of f and g's top limb into the one below. */ - if (cond == 0) { - f.v[len - 2] |= (uint32_t)fn << 30; - g.v[len - 2] |= (uint32_t)gn << 30; - --len; - } - - VERIFY_CHECK(++i < 25); /* We should never need more than 25*30 = 750 divsteps */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - } - - /* At this point g is 0 and (if g was not originally 0) f must now equal +/- GCD of - * the initial f, g values i.e. +/- 1, and d now contains +/- the modular inverse. */ - - /* g == 0 */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &SECP256K1_SIGNED30_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &SECP256K1_SIGNED30_ONE, -1) == 0 || - secp256k1_modinv32_mul_cmp_30(&f, len, &SECP256K1_SIGNED30_ONE, 1) == 0 || - (secp256k1_modinv32_mul_cmp_30(x, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - secp256k1_modinv32_mul_cmp_30(&d, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) == 0)); - - /* Optionally negate d, normalize to [0,modulus), and return it. */ - secp256k1_modinv32_normalize_30(&d, f.v[len - 1], modinfo); - *x = d; -} - -/* Do up to 50 iterations of 30 posdivsteps (up to 1500 steps; more is extremely rare) each until f=1. - * In VERIFY mode use a lower number of iterations (750, close to the median 756), so failure actually occurs. */ -#ifdef VERIFY -#define JACOBI32_ITERATIONS 25 -#else -#define JACOBI32_ITERATIONS 50 -#endif - -/* Compute the Jacobi symbol of x modulo modinfo->modulus (variable time). gcd(x,modulus) must be 1. */ -static int secp256k1_jacobi32_maybe_var(const secp256k1_modinv32_signed30 *x, const secp256k1_modinv32_modinfo *modinfo) { - /* Start with f=modulus, g=x, eta=-1. */ - secp256k1_modinv32_signed30 f = modinfo->modulus; - secp256k1_modinv32_signed30 g = *x; - int j, len = 9; - int32_t eta = -1; /* eta = -delta; delta is initially 1 */ - int32_t cond, fn, gn; - int jac = 0; - int count; - - /* The input limbs must all be non-negative. */ - VERIFY_CHECK(g.v[0] >= 0 && g.v[1] >= 0 && g.v[2] >= 0 && g.v[3] >= 0 && g.v[4] >= 0 && g.v[5] >= 0 && g.v[6] >= 0 && g.v[7] >= 0 && g.v[8] >= 0); - - /* If x > 0, then if the loop below converges, it converges to f=g=gcd(x,modulus). Since we - * require that gcd(x,modulus)=1 and modulus>=3, x cannot be 0. Thus, we must reach f=1 (or - * time out). */ - VERIFY_CHECK((g.v[0] | g.v[1] | g.v[2] | g.v[3] | g.v[4] | g.v[5] | g.v[6] | g.v[7] | g.v[8]) != 0); - - for (count = 0; count < JACOBI32_ITERATIONS; ++count) { - /* Compute transition matrix and new eta after 30 posdivsteps. */ - secp256k1_modinv32_trans2x2 t; - eta = secp256k1_modinv32_posdivsteps_30_var(eta, f.v[0] | ((uint32_t)f.v[1] << 30), g.v[0] | ((uint32_t)g.v[1] << 30), &t, &jac); - /* Update f,g using that transition matrix. */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - - secp256k1_modinv32_update_fg_30_var(len, &f, &g, &t); - /* If the bottom limb of f is 1, there is a chance that f=1. */ - if (f.v[0] == 1) { - cond = 0; - /* Check if the other limbs are also 0. */ - for (j = 1; j < len; ++j) { - cond |= f.v[j]; - } - /* If so, we're done. If f=1, the Jacobi symbol (g | f)=1. */ - if (cond == 0) return 1 - 2*(jac & 1); - } - - /* Determine if len>1 and limb (len-1) of both f and g is 0. */ - fn = f.v[len - 1]; - gn = g.v[len - 1]; - cond = ((int32_t)len - 2) >> 31; - cond |= fn; - cond |= gn; - /* If so, reduce length. */ - if (cond == 0) --len; - - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ - VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - } - - /* The loop failed to converge to f=g after 1500 iterations. Return 0, indicating unknown result. */ - return 0; -} - -#endif /* SECP256K1_MODINV32_IMPL_H */ diff --git a/external/secp256k1/src/modinv64.h b/external/secp256k1/src/modinv64.h deleted file mode 100644 index f4208e6c23..0000000000 --- a/external/secp256k1/src/modinv64.h +++ /dev/null @@ -1,47 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Peter Dettman * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef SECP256K1_MODINV64_H -#define SECP256K1_MODINV64_H - -#include "util.h" - -#ifndef SECP256K1_WIDEMUL_INT128 -#error "modinv64 requires 128-bit wide multiplication support" -#endif - -/* A signed 62-bit limb representation of integers. - * - * Its value is sum(v[i] * 2^(62*i), i=0..4). */ -typedef struct { - int64_t v[5]; -} secp256k1_modinv64_signed62; - -typedef struct { - /* The modulus in signed62 notation, must be odd and in [3, 2^256]. */ - secp256k1_modinv64_signed62 modulus; - - /* modulus^{-1} mod 2^62 */ - uint64_t modulus_inv62; -} secp256k1_modinv64_modinfo; - -/* Replace x with its modular inverse mod modinfo->modulus. x must be in range [0, modulus). - * If x is zero, the result will be zero as well. If not, the inverse must exist (i.e., the gcd of - * x and modulus must be 1). These rules are automatically satisfied if the modulus is prime. - * - * On output, all of x's limbs will be in [0, 2^62). - */ -static void secp256k1_modinv64_var(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); - -/* Same as secp256k1_modinv64_var, but constant time in x (not in the modulus). */ -static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); - -/* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus - * cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result - * cannot be computed. */ -static int secp256k1_jacobi64_maybe_var(const secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo); - -#endif /* SECP256K1_MODINV64_H */ diff --git a/external/secp256k1/src/modinv64_impl.h b/external/secp256k1/src/modinv64_impl.h deleted file mode 100644 index 548787bedf..0000000000 --- a/external/secp256k1/src/modinv64_impl.h +++ /dev/null @@ -1,780 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Peter Dettman * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef SECP256K1_MODINV64_IMPL_H -#define SECP256K1_MODINV64_IMPL_H - -#include "int128.h" -#include "modinv64.h" - -/* This file implements modular inversion based on the paper "Fast constant-time gcd computation and - * modular inversion" by Daniel J. Bernstein and Bo-Yin Yang. - * - * For an explanation of the algorithm, see doc/safegcd_implementation.md. This file contains an - * implementation for N=62, using 62-bit signed limbs represented as int64_t. - */ - -/* Data type for transition matrices (see section 3 of explanation). - * - * t = [ u v ] - * [ q r ] - */ -typedef struct { - int64_t u, v, q, r; -} secp256k1_modinv64_trans2x2; - -#ifdef VERIFY -/* Helper function to compute the absolute value of an int64_t. - * (we don't use abs/labs/llabs as it depends on the int sizes). */ -static int64_t secp256k1_modinv64_abs(int64_t v) { - VERIFY_CHECK(v > INT64_MIN); - if (v < 0) return -v; - return v; -} - -static const secp256k1_modinv64_signed62 SECP256K1_SIGNED62_ONE = {{1}}; - -/* Compute a*factor and put it in r. All but the top limb in r will be in range [0,2^62). */ -static void secp256k1_modinv64_mul_62(secp256k1_modinv64_signed62 *r, const secp256k1_modinv64_signed62 *a, int alen, int64_t factor) { - const uint64_t M62 = UINT64_MAX >> 2; - secp256k1_int128 c, d; - int i; - secp256k1_i128_from_i64(&c, 0); - for (i = 0; i < 4; ++i) { - if (i < alen) secp256k1_i128_accum_mul(&c, a->v[i], factor); - r->v[i] = secp256k1_i128_to_u64(&c) & M62; secp256k1_i128_rshift(&c, 62); - } - if (4 < alen) secp256k1_i128_accum_mul(&c, a->v[4], factor); - secp256k1_i128_from_i64(&d, secp256k1_i128_to_i64(&c)); - VERIFY_CHECK(secp256k1_i128_eq_var(&c, &d)); - r->v[4] = secp256k1_i128_to_i64(&c); -} - -/* Return -1 for ab*factor. A has alen limbs; b has 5. */ -static int secp256k1_modinv64_mul_cmp_62(const secp256k1_modinv64_signed62 *a, int alen, const secp256k1_modinv64_signed62 *b, int64_t factor) { - int i; - secp256k1_modinv64_signed62 am, bm; - secp256k1_modinv64_mul_62(&am, a, alen, 1); /* Normalize all but the top limb of a. */ - secp256k1_modinv64_mul_62(&bm, b, 5, factor); - for (i = 0; i < 4; ++i) { - /* Verify that all but the top limb of a and b are normalized. */ - VERIFY_CHECK(am.v[i] >> 62 == 0); - VERIFY_CHECK(bm.v[i] >> 62 == 0); - } - for (i = 4; i >= 0; --i) { - if (am.v[i] < bm.v[i]) return -1; - if (am.v[i] > bm.v[i]) return 1; - } - return 0; -} - -/* Check if the determinant of t is equal to 1 << n. If abs, check if |det t| == 1 << n. */ -static int secp256k1_modinv64_det_check_pow2(const secp256k1_modinv64_trans2x2 *t, unsigned int n, int abs) { - secp256k1_int128 a; - secp256k1_i128_det(&a, t->u, t->v, t->q, t->r); - if (secp256k1_i128_check_pow2(&a, n, 1)) return 1; - if (abs && secp256k1_i128_check_pow2(&a, n, -1)) return 1; - return 0; -} -#endif - -/* Take as input a signed62 number in range (-2*modulus,modulus), and add a multiple of the modulus - * to it to bring it to range [0,modulus). If sign < 0, the input will also be negated in the - * process. The input must have limbs in range (-2^62,2^62). The output will have limbs in range - * [0,2^62). */ -static void secp256k1_modinv64_normalize_62(secp256k1_modinv64_signed62 *r, int64_t sign, const secp256k1_modinv64_modinfo *modinfo) { - const int64_t M62 = (int64_t)(UINT64_MAX >> 2); - int64_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4]; - volatile int64_t cond_add, cond_negate; - -#ifdef VERIFY - /* Verify that all limbs are in range (-2^62,2^62). */ - int i; - for (i = 0; i < 5; ++i) { - VERIFY_CHECK(r->v[i] >= -M62); - VERIFY_CHECK(r->v[i] <= M62); - } - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, -2) > 0); /* r > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 1) < 0); /* r < modulus */ -#endif - - /* In a first step, add the modulus if the input is negative, and then negate if requested. - * This brings r from range (-2*modulus,modulus) to range (-modulus,modulus). As all input - * limbs are in range (-2^62,2^62), this cannot overflow an int64_t. Note that the right - * shifts below are signed sign-extending shifts (see assumptions.h for tests that that is - * indeed the behavior of the right shift operator). */ - cond_add = r4 >> 63; - r0 += modinfo->modulus.v[0] & cond_add; - r1 += modinfo->modulus.v[1] & cond_add; - r2 += modinfo->modulus.v[2] & cond_add; - r3 += modinfo->modulus.v[3] & cond_add; - r4 += modinfo->modulus.v[4] & cond_add; - cond_negate = sign >> 63; - r0 = (r0 ^ cond_negate) - cond_negate; - r1 = (r1 ^ cond_negate) - cond_negate; - r2 = (r2 ^ cond_negate) - cond_negate; - r3 = (r3 ^ cond_negate) - cond_negate; - r4 = (r4 ^ cond_negate) - cond_negate; - /* Propagate the top bits, to bring limbs back to range (-2^62,2^62). */ - r1 += r0 >> 62; r0 &= M62; - r2 += r1 >> 62; r1 &= M62; - r3 += r2 >> 62; r2 &= M62; - r4 += r3 >> 62; r3 &= M62; - - /* In a second step add the modulus again if the result is still negative, bringing - * r to range [0,modulus). */ - cond_add = r4 >> 63; - r0 += modinfo->modulus.v[0] & cond_add; - r1 += modinfo->modulus.v[1] & cond_add; - r2 += modinfo->modulus.v[2] & cond_add; - r3 += modinfo->modulus.v[3] & cond_add; - r4 += modinfo->modulus.v[4] & cond_add; - /* And propagate again. */ - r1 += r0 >> 62; r0 &= M62; - r2 += r1 >> 62; r1 &= M62; - r3 += r2 >> 62; r2 &= M62; - r4 += r3 >> 62; r3 &= M62; - - r->v[0] = r0; - r->v[1] = r1; - r->v[2] = r2; - r->v[3] = r3; - r->v[4] = r4; - - VERIFY_CHECK(r0 >> 62 == 0); - VERIFY_CHECK(r1 >> 62 == 0); - VERIFY_CHECK(r2 >> 62 == 0); - VERIFY_CHECK(r3 >> 62 == 0); - VERIFY_CHECK(r4 >> 62 == 0); - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 0) >= 0); /* r >= 0 */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 1) < 0); /* r < modulus */ -} - -/* Compute the transition matrix and eta for 59 divsteps (where zeta=-(delta+1/2)). - * Note that the transformation matrix is scaled by 2^62 and not 2^59. - * - * Input: zeta: initial zeta - * f0: bottom limb of initial f - * g0: bottom limb of initial g - * Output: t: transition matrix - * Return: final zeta - * - * Implements the divsteps_n_matrix function from the explanation. - */ -static int64_t secp256k1_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_t g0, secp256k1_modinv64_trans2x2 *t) { - /* u,v,q,r are the elements of the transformation matrix being built up, - * starting with the identity matrix times 8 (because the caller expects - * a result scaled by 2^62). Semantically they are signed integers - * in range [-2^62,2^62], but here represented as unsigned mod 2^64. This - * permits left shifting (which is UB for negative numbers). The range - * being inside [-2^63,2^63) means that casting to signed works correctly. - */ - uint64_t u = 8, v = 0, q = 0, r = 8; - volatile uint64_t c1, c2; - uint64_t mask1, mask2, f = f0, g = g0, x, y, z; - int i; - - for (i = 3; i < 62; ++i) { - VERIFY_CHECK((f & 1) == 1); /* f must always be odd */ - VERIFY_CHECK((u * f0 + v * g0) == f << i); - VERIFY_CHECK((q * f0 + r * g0) == g << i); - /* Compute conditional masks for (zeta < 0) and for (g & 1). */ - c1 = zeta >> 63; - mask1 = c1; - c2 = g & 1; - mask2 = -c2; - /* Compute x,y,z, conditionally negated versions of f,u,v. */ - x = (f ^ mask1) - mask1; - y = (u ^ mask1) - mask1; - z = (v ^ mask1) - mask1; - /* Conditionally add x,y,z to g,q,r. */ - g += x & mask2; - q += y & mask2; - r += z & mask2; - /* In what follows, c1 is a condition mask for (zeta < 0) and (g & 1). */ - mask1 &= mask2; - /* Conditionally change zeta into -zeta-2 or zeta-1. */ - zeta = (zeta ^ mask1) - 1; - /* Conditionally add g,q,r to f,u,v. */ - f += g & mask1; - u += q & mask1; - v += r & mask1; - /* Shifts */ - g >>= 1; - u <<= 1; - v <<= 1; - /* Bounds on zeta that follow from the bounds on iteration count (max 10*59 divsteps). */ - VERIFY_CHECK(zeta >= -591 && zeta <= 591); - } - /* Return data in t and return value. */ - t->u = (int64_t)u; - t->v = (int64_t)v; - t->q = (int64_t)q; - t->r = (int64_t)r; - - /* The determinant of t must be a power of two. This guarantees that multiplication with t - * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which - * will be divided out again). As each divstep's individual matrix has determinant 2, the - * aggregate of 59 of them will have determinant 2^59. Multiplying with the initial - * 8*identity (which has determinant 2^6) means the overall outputs has determinant - * 2^65. */ - VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 65, 0)); - - return zeta; -} - -/* Compute the transition matrix and eta for 62 divsteps (variable time, eta=-delta). - * - * Input: eta: initial eta - * f0: bottom limb of initial f - * g0: bottom limb of initial g - * Output: t: transition matrix - * Return: final eta - * - * Implements the divsteps_n_matrix_var function from the explanation. - */ -static int64_t secp256k1_modinv64_divsteps_62_var(int64_t eta, uint64_t f0, uint64_t g0, secp256k1_modinv64_trans2x2 *t) { - /* Transformation matrix; see comments in secp256k1_modinv64_divsteps_62. */ - uint64_t u = 1, v = 0, q = 0, r = 1; - uint64_t f = f0, g = g0, m; - uint32_t w; - int i = 62, limit, zeros; - - for (;;) { - /* Use a sentinel bit to count zeros only up to i. */ - zeros = secp256k1_ctz64_var(g | (UINT64_MAX << i)); - /* Perform zeros divsteps at once; they all just divide g by two. */ - g >>= zeros; - u <<= zeros; - v <<= zeros; - eta -= zeros; - i -= zeros; - /* We're done once we've done 62 divsteps. */ - if (i == 0) break; - VERIFY_CHECK((f & 1) == 1); - VERIFY_CHECK((g & 1) == 1); - VERIFY_CHECK((u * f0 + v * g0) == f << (62 - i)); - VERIFY_CHECK((q * f0 + r * g0) == g << (62 - i)); - /* Bounds on eta that follow from the bounds on iteration count (max 12*62 divsteps). */ - VERIFY_CHECK(eta >= -745 && eta <= 745); - /* If eta is negative, negate it and replace f,g with g,-f. */ - if (eta < 0) { - uint64_t tmp; - eta = -eta; - tmp = f; f = g; g = -tmp; - tmp = u; u = q; q = -tmp; - tmp = v; v = r; r = -tmp; - /* Use a formula to cancel out up to 6 bits of g. Also, no more than i can be cancelled - * out (as we'd be done before that point), and no more than eta+1 can be done as its - * sign will flip again once that happens. */ - limit = ((int)eta + 1) > i ? i : ((int)eta + 1); - VERIFY_CHECK(limit > 0 && limit <= 62); - /* m is a mask for the bottom min(limit, 6) bits. */ - m = (UINT64_MAX >> (64 - limit)) & 63U; - /* Find what multiple of f must be added to g to cancel its bottom min(limit, 6) - * bits. */ - w = (f * g * (f * f - 2)) & m; - } else { - /* In this branch, use a simpler formula that only lets us cancel up to 4 bits of g, as - * eta tends to be smaller here. */ - limit = ((int)eta + 1) > i ? i : ((int)eta + 1); - VERIFY_CHECK(limit > 0 && limit <= 62); - /* m is a mask for the bottom min(limit, 4) bits. */ - m = (UINT64_MAX >> (64 - limit)) & 15U; - /* Find what multiple of f must be added to g to cancel its bottom min(limit, 4) - * bits. */ - w = f + (((f + 1) & 4) << 1); - w = (-w * g) & m; - } - g += f * w; - q += u * w; - r += v * w; - VERIFY_CHECK((g & m) == 0); - } - /* Return data in t and return value. */ - t->u = (int64_t)u; - t->v = (int64_t)v; - t->q = (int64_t)q; - t->r = (int64_t)r; - - /* The determinant of t must be a power of two. This guarantees that multiplication with t - * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which - * will be divided out again). As each divstep's individual matrix has determinant 2, the - * aggregate of 62 of them will have determinant 2^62. */ - VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 62, 0)); - - return eta; -} - -/* Compute the transition matrix and eta for 62 posdivsteps (variable time, eta=-delta), and keeps track - * of the Jacobi symbol along the way. f0 and g0 must be f and g mod 2^64 rather than 2^62, because - * Jacobi tracking requires knowing (f mod 8) rather than just (f mod 2). - * - * Input: eta: initial eta - * f0: bottom limb of initial f - * g0: bottom limb of initial g - * Output: t: transition matrix - * Input/Output: (*jacp & 1) is bitflipped if and only if the Jacobi symbol of (f | g) changes sign - * by applying the returned transformation matrix to it. The other bits of *jacp may - * change, but are meaningless. - * Return: final eta - */ -static int64_t secp256k1_modinv64_posdivsteps_62_var(int64_t eta, uint64_t f0, uint64_t g0, secp256k1_modinv64_trans2x2 *t, int *jacp) { - /* Transformation matrix; see comments in secp256k1_modinv64_divsteps_62. */ - uint64_t u = 1, v = 0, q = 0, r = 1; - uint64_t f = f0, g = g0, m; - uint32_t w; - int i = 62, limit, zeros; - int jac = *jacp; - - for (;;) { - /* Use a sentinel bit to count zeros only up to i. */ - zeros = secp256k1_ctz64_var(g | (UINT64_MAX << i)); - /* Perform zeros divsteps at once; they all just divide g by two. */ - g >>= zeros; - u <<= zeros; - v <<= zeros; - eta -= zeros; - i -= zeros; - /* Update the bottom bit of jac: when dividing g by an odd power of 2, - * if (f mod 8) is 3 or 5, the Jacobi symbol changes sign. */ - jac ^= (zeros & ((f >> 1) ^ (f >> 2))); - /* We're done once we've done 62 posdivsteps. */ - if (i == 0) break; - VERIFY_CHECK((f & 1) == 1); - VERIFY_CHECK((g & 1) == 1); - VERIFY_CHECK((u * f0 + v * g0) == f << (62 - i)); - VERIFY_CHECK((q * f0 + r * g0) == g << (62 - i)); - /* If eta is negative, negate it and replace f,g with g,f. */ - if (eta < 0) { - uint64_t tmp; - eta = -eta; - tmp = f; f = g; g = tmp; - tmp = u; u = q; q = tmp; - tmp = v; v = r; r = tmp; - /* Update bottom bit of jac: when swapping f and g, the Jacobi symbol changes sign - * if both f and g are 3 mod 4. */ - jac ^= ((f & g) >> 1); - /* Use a formula to cancel out up to 6 bits of g. Also, no more than i can be cancelled - * out (as we'd be done before that point), and no more than eta+1 can be done as its - * sign will flip again once that happens. */ - limit = ((int)eta + 1) > i ? i : ((int)eta + 1); - VERIFY_CHECK(limit > 0 && limit <= 62); - /* m is a mask for the bottom min(limit, 6) bits. */ - m = (UINT64_MAX >> (64 - limit)) & 63U; - /* Find what multiple of f must be added to g to cancel its bottom min(limit, 6) - * bits. */ - w = (f * g * (f * f - 2)) & m; - } else { - /* In this branch, use a simpler formula that only lets us cancel up to 4 bits of g, as - * eta tends to be smaller here. */ - limit = ((int)eta + 1) > i ? i : ((int)eta + 1); - VERIFY_CHECK(limit > 0 && limit <= 62); - /* m is a mask for the bottom min(limit, 4) bits. */ - m = (UINT64_MAX >> (64 - limit)) & 15U; - /* Find what multiple of f must be added to g to cancel its bottom min(limit, 4) - * bits. */ - w = f + (((f + 1) & 4) << 1); - w = (-w * g) & m; - } - g += f * w; - q += u * w; - r += v * w; - VERIFY_CHECK((g & m) == 0); - } - /* Return data in t and return value. */ - t->u = (int64_t)u; - t->v = (int64_t)v; - t->q = (int64_t)q; - t->r = (int64_t)r; - - /* The determinant of t must be a power of two. This guarantees that multiplication with t - * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which - * will be divided out again). As each divstep's individual matrix has determinant 2 or -2, - * the aggregate of 62 of them will have determinant 2^62 or -2^62. */ - VERIFY_CHECK(secp256k1_modinv64_det_check_pow2(t, 62, 1)); - - *jacp = jac; - return eta; -} - -/* Compute (t/2^62) * [d, e] mod modulus, where t is a transition matrix scaled by 2^62. - * - * On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be in range - * (-2^62,2^62). - * - * This implements the update_de function from the explanation. - */ -static void secp256k1_modinv64_update_de_62(secp256k1_modinv64_signed62 *d, secp256k1_modinv64_signed62 *e, const secp256k1_modinv64_trans2x2 *t, const secp256k1_modinv64_modinfo* modinfo) { - const uint64_t M62 = UINT64_MAX >> 2; - const int64_t d0 = d->v[0], d1 = d->v[1], d2 = d->v[2], d3 = d->v[3], d4 = d->v[4]; - const int64_t e0 = e->v[0], e1 = e->v[1], e2 = e->v[2], e3 = e->v[3], e4 = e->v[4]; - const int64_t u = t->u, v = t->v, q = t->q, r = t->r; - int64_t md, me, sd, se; - secp256k1_int128 cd, ce; - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, 1) < 0); /* e < modulus */ - VERIFY_CHECK(secp256k1_modinv64_abs(u) <= (((int64_t)1 << 62) - secp256k1_modinv64_abs(v))); /* |u|+|v| <= 2^62 */ - VERIFY_CHECK(secp256k1_modinv64_abs(q) <= (((int64_t)1 << 62) - secp256k1_modinv64_abs(r))); /* |q|+|r| <= 2^62 */ - - /* [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative. */ - sd = d4 >> 63; - se = e4 >> 63; - md = (u & sd) + (v & se); - me = (q & sd) + (r & se); - /* Begin computing t*[d,e]. */ - secp256k1_i128_mul(&cd, u, d0); - secp256k1_i128_accum_mul(&cd, v, e0); - secp256k1_i128_mul(&ce, q, d0); - secp256k1_i128_accum_mul(&ce, r, e0); - /* Correct md,me so that t*[d,e]+modulus*[md,me] has 62 zero bottom bits. */ - md -= (modinfo->modulus_inv62 * secp256k1_i128_to_u64(&cd) + md) & M62; - me -= (modinfo->modulus_inv62 * secp256k1_i128_to_u64(&ce) + me) & M62; - /* Update the beginning of computation for t*[d,e]+modulus*[md,me] now md,me are known. */ - secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[0], md); - secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[0], me); - /* Verify that the low 62 bits of the computation are indeed zero, and then throw them away. */ - VERIFY_CHECK((secp256k1_i128_to_u64(&cd) & M62) == 0); secp256k1_i128_rshift(&cd, 62); - VERIFY_CHECK((secp256k1_i128_to_u64(&ce) & M62) == 0); secp256k1_i128_rshift(&ce, 62); - /* Compute limb 1 of t*[d,e]+modulus*[md,me], and store it as output limb 0 (= down shift). */ - secp256k1_i128_accum_mul(&cd, u, d1); - secp256k1_i128_accum_mul(&cd, v, e1); - secp256k1_i128_accum_mul(&ce, q, d1); - secp256k1_i128_accum_mul(&ce, r, e1); - if (modinfo->modulus.v[1]) { /* Optimize for the case where limb of modulus is zero. */ - secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[1], md); - secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[1], me); - } - d->v[0] = secp256k1_i128_to_u64(&cd) & M62; secp256k1_i128_rshift(&cd, 62); - e->v[0] = secp256k1_i128_to_u64(&ce) & M62; secp256k1_i128_rshift(&ce, 62); - /* Compute limb 2 of t*[d,e]+modulus*[md,me], and store it as output limb 1. */ - secp256k1_i128_accum_mul(&cd, u, d2); - secp256k1_i128_accum_mul(&cd, v, e2); - secp256k1_i128_accum_mul(&ce, q, d2); - secp256k1_i128_accum_mul(&ce, r, e2); - if (modinfo->modulus.v[2]) { /* Optimize for the case where limb of modulus is zero. */ - secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[2], md); - secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[2], me); - } - d->v[1] = secp256k1_i128_to_u64(&cd) & M62; secp256k1_i128_rshift(&cd, 62); - e->v[1] = secp256k1_i128_to_u64(&ce) & M62; secp256k1_i128_rshift(&ce, 62); - /* Compute limb 3 of t*[d,e]+modulus*[md,me], and store it as output limb 2. */ - secp256k1_i128_accum_mul(&cd, u, d3); - secp256k1_i128_accum_mul(&cd, v, e3); - secp256k1_i128_accum_mul(&ce, q, d3); - secp256k1_i128_accum_mul(&ce, r, e3); - if (modinfo->modulus.v[3]) { /* Optimize for the case where limb of modulus is zero. */ - secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[3], md); - secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[3], me); - } - d->v[2] = secp256k1_i128_to_u64(&cd) & M62; secp256k1_i128_rshift(&cd, 62); - e->v[2] = secp256k1_i128_to_u64(&ce) & M62; secp256k1_i128_rshift(&ce, 62); - /* Compute limb 4 of t*[d,e]+modulus*[md,me], and store it as output limb 3. */ - secp256k1_i128_accum_mul(&cd, u, d4); - secp256k1_i128_accum_mul(&cd, v, e4); - secp256k1_i128_accum_mul(&ce, q, d4); - secp256k1_i128_accum_mul(&ce, r, e4); - secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[4], md); - secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[4], me); - d->v[3] = secp256k1_i128_to_u64(&cd) & M62; secp256k1_i128_rshift(&cd, 62); - e->v[3] = secp256k1_i128_to_u64(&ce) & M62; secp256k1_i128_rshift(&ce, 62); - /* What remains is limb 5 of t*[d,e]+modulus*[md,me]; store it as output limb 4. */ - d->v[4] = secp256k1_i128_to_i64(&cd); - e->v[4] = secp256k1_i128_to_i64(&ce); - - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, 1) < 0); /* e < modulus */ -} - -/* Compute (t/2^62) * [f, g], where t is a transition matrix scaled by 2^62. - * - * This implements the update_fg function from the explanation. - */ -static void secp256k1_modinv64_update_fg_62(secp256k1_modinv64_signed62 *f, secp256k1_modinv64_signed62 *g, const secp256k1_modinv64_trans2x2 *t) { - const uint64_t M62 = UINT64_MAX >> 2; - const int64_t f0 = f->v[0], f1 = f->v[1], f2 = f->v[2], f3 = f->v[3], f4 = f->v[4]; - const int64_t g0 = g->v[0], g1 = g->v[1], g2 = g->v[2], g3 = g->v[3], g4 = g->v[4]; - const int64_t u = t->u, v = t->v, q = t->q, r = t->r; - secp256k1_int128 cf, cg; - /* Start computing t*[f,g]. */ - secp256k1_i128_mul(&cf, u, f0); - secp256k1_i128_accum_mul(&cf, v, g0); - secp256k1_i128_mul(&cg, q, f0); - secp256k1_i128_accum_mul(&cg, r, g0); - /* Verify that the bottom 62 bits of the result are zero, and then throw them away. */ - VERIFY_CHECK((secp256k1_i128_to_u64(&cf) & M62) == 0); secp256k1_i128_rshift(&cf, 62); - VERIFY_CHECK((secp256k1_i128_to_u64(&cg) & M62) == 0); secp256k1_i128_rshift(&cg, 62); - /* Compute limb 1 of t*[f,g], and store it as output limb 0 (= down shift). */ - secp256k1_i128_accum_mul(&cf, u, f1); - secp256k1_i128_accum_mul(&cf, v, g1); - secp256k1_i128_accum_mul(&cg, q, f1); - secp256k1_i128_accum_mul(&cg, r, g1); - f->v[0] = secp256k1_i128_to_u64(&cf) & M62; secp256k1_i128_rshift(&cf, 62); - g->v[0] = secp256k1_i128_to_u64(&cg) & M62; secp256k1_i128_rshift(&cg, 62); - /* Compute limb 2 of t*[f,g], and store it as output limb 1. */ - secp256k1_i128_accum_mul(&cf, u, f2); - secp256k1_i128_accum_mul(&cf, v, g2); - secp256k1_i128_accum_mul(&cg, q, f2); - secp256k1_i128_accum_mul(&cg, r, g2); - f->v[1] = secp256k1_i128_to_u64(&cf) & M62; secp256k1_i128_rshift(&cf, 62); - g->v[1] = secp256k1_i128_to_u64(&cg) & M62; secp256k1_i128_rshift(&cg, 62); - /* Compute limb 3 of t*[f,g], and store it as output limb 2. */ - secp256k1_i128_accum_mul(&cf, u, f3); - secp256k1_i128_accum_mul(&cf, v, g3); - secp256k1_i128_accum_mul(&cg, q, f3); - secp256k1_i128_accum_mul(&cg, r, g3); - f->v[2] = secp256k1_i128_to_u64(&cf) & M62; secp256k1_i128_rshift(&cf, 62); - g->v[2] = secp256k1_i128_to_u64(&cg) & M62; secp256k1_i128_rshift(&cg, 62); - /* Compute limb 4 of t*[f,g], and store it as output limb 3. */ - secp256k1_i128_accum_mul(&cf, u, f4); - secp256k1_i128_accum_mul(&cf, v, g4); - secp256k1_i128_accum_mul(&cg, q, f4); - secp256k1_i128_accum_mul(&cg, r, g4); - f->v[3] = secp256k1_i128_to_u64(&cf) & M62; secp256k1_i128_rshift(&cf, 62); - g->v[3] = secp256k1_i128_to_u64(&cg) & M62; secp256k1_i128_rshift(&cg, 62); - /* What remains is limb 5 of t*[f,g]; store it as output limb 4. */ - f->v[4] = secp256k1_i128_to_i64(&cf); - g->v[4] = secp256k1_i128_to_i64(&cg); -} - -/* Compute (t/2^62) * [f, g], where t is a transition matrix for 62 divsteps. - * - * Version that operates on a variable number of limbs in f and g. - * - * This implements the update_fg function from the explanation. - */ -static void secp256k1_modinv64_update_fg_62_var(int len, secp256k1_modinv64_signed62 *f, secp256k1_modinv64_signed62 *g, const secp256k1_modinv64_trans2x2 *t) { - const uint64_t M62 = UINT64_MAX >> 2; - const int64_t u = t->u, v = t->v, q = t->q, r = t->r; - int64_t fi, gi; - secp256k1_int128 cf, cg; - int i; - VERIFY_CHECK(len > 0); - /* Start computing t*[f,g]. */ - fi = f->v[0]; - gi = g->v[0]; - secp256k1_i128_mul(&cf, u, fi); - secp256k1_i128_accum_mul(&cf, v, gi); - secp256k1_i128_mul(&cg, q, fi); - secp256k1_i128_accum_mul(&cg, r, gi); - /* Verify that the bottom 62 bits of the result are zero, and then throw them away. */ - VERIFY_CHECK((secp256k1_i128_to_u64(&cf) & M62) == 0); secp256k1_i128_rshift(&cf, 62); - VERIFY_CHECK((secp256k1_i128_to_u64(&cg) & M62) == 0); secp256k1_i128_rshift(&cg, 62); - /* Now iteratively compute limb i=1..len of t*[f,g], and store them in output limb i-1 (shifting - * down by 62 bits). */ - for (i = 1; i < len; ++i) { - fi = f->v[i]; - gi = g->v[i]; - secp256k1_i128_accum_mul(&cf, u, fi); - secp256k1_i128_accum_mul(&cf, v, gi); - secp256k1_i128_accum_mul(&cg, q, fi); - secp256k1_i128_accum_mul(&cg, r, gi); - f->v[i - 1] = secp256k1_i128_to_u64(&cf) & M62; secp256k1_i128_rshift(&cf, 62); - g->v[i - 1] = secp256k1_i128_to_u64(&cg) & M62; secp256k1_i128_rshift(&cg, 62); - } - /* What remains is limb (len) of t*[f,g]; store it as output limb (len-1). */ - f->v[len - 1] = secp256k1_i128_to_i64(&cf); - g->v[len - 1] = secp256k1_i128_to_i64(&cg); -} - -/* Compute the inverse of x modulo modinfo->modulus, and replace x with it (constant time in x). */ -static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo) { - /* Start with d=0, e=1, f=modulus, g=x, zeta=-1. */ - secp256k1_modinv64_signed62 d = {{0, 0, 0, 0, 0}}; - secp256k1_modinv64_signed62 e = {{1, 0, 0, 0, 0}}; - secp256k1_modinv64_signed62 f = modinfo->modulus; - secp256k1_modinv64_signed62 g = *x; - int i; - int64_t zeta = -1; /* zeta = -(delta+1/2); delta starts at 1/2. */ - - /* Do 10 iterations of 59 divsteps each = 590 divsteps. This suffices for 256-bit inputs. */ - for (i = 0; i < 10; ++i) { - /* Compute transition matrix and new zeta after 59 divsteps. */ - secp256k1_modinv64_trans2x2 t; - zeta = secp256k1_modinv64_divsteps_59(zeta, f.v[0], g.v[0], &t); - /* Update d,e using that transition matrix. */ - secp256k1_modinv64_update_de_62(&d, &e, &t, modinfo); - /* Update f,g using that transition matrix. */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, 1) < 0); /* g < modulus */ - - secp256k1_modinv64_update_fg_62(&f, &g, &t); - - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, 1) < 0); /* g < modulus */ - } - - /* At this point sufficient iterations have been performed that g must have reached 0 - * and (if g was not originally 0) f must now equal +/- GCD of the initial f, g - * values i.e. +/- 1, and d now contains +/- the modular inverse. */ - - /* g == 0 */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, 5, &SECP256K1_SIGNED62_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, 5, &SECP256K1_SIGNED62_ONE, -1) == 0 || - secp256k1_modinv64_mul_cmp_62(&f, 5, &SECP256K1_SIGNED62_ONE, 1) == 0 || - (secp256k1_modinv64_mul_cmp_62(x, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - secp256k1_modinv64_mul_cmp_62(&d, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - secp256k1_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) == 0)); - - /* Optionally negate d, normalize to [0,modulus), and return it. */ - secp256k1_modinv64_normalize_62(&d, f.v[4], modinfo); - *x = d; -} - -/* Compute the inverse of x modulo modinfo->modulus, and replace x with it (variable time). */ -static void secp256k1_modinv64_var(secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo) { - /* Start with d=0, e=1, f=modulus, g=x, eta=-1. */ - secp256k1_modinv64_signed62 d = {{0, 0, 0, 0, 0}}; - secp256k1_modinv64_signed62 e = {{1, 0, 0, 0, 0}}; - secp256k1_modinv64_signed62 f = modinfo->modulus; - secp256k1_modinv64_signed62 g = *x; -#ifdef VERIFY - int i = 0; -#endif - int j, len = 5; - int64_t eta = -1; /* eta = -delta; delta is initially 1 */ - int64_t cond, fn, gn; - - /* Do iterations of 62 divsteps each until g=0. */ - while (1) { - /* Compute transition matrix and new eta after 62 divsteps. */ - secp256k1_modinv64_trans2x2 t; - eta = secp256k1_modinv64_divsteps_62_var(eta, f.v[0], g.v[0], &t); - /* Update d,e using that transition matrix. */ - secp256k1_modinv64_update_de_62(&d, &e, &t, modinfo); - /* Update f,g using that transition matrix. */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - - secp256k1_modinv64_update_fg_62_var(len, &f, &g, &t); - /* If the bottom limb of g is zero, there is a chance that g=0. */ - if (g.v[0] == 0) { - cond = 0; - /* Check if the other limbs are also 0. */ - for (j = 1; j < len; ++j) { - cond |= g.v[j]; - } - /* If so, we're done. */ - if (cond == 0) break; - } - - /* Determine if len>1 and limb (len-1) of both f and g is 0 or -1. */ - fn = f.v[len - 1]; - gn = g.v[len - 1]; - cond = ((int64_t)len - 2) >> 63; - cond |= fn ^ (fn >> 63); - cond |= gn ^ (gn >> 63); - /* If so, reduce length, propagating the sign of f and g's top limb into the one below. */ - if (cond == 0) { - f.v[len - 2] |= (uint64_t)fn << 62; - g.v[len - 2] |= (uint64_t)gn << 62; - --len; - } - - VERIFY_CHECK(++i < 12); /* We should never need more than 12*62 = 744 divsteps */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - } - - /* At this point g is 0 and (if g was not originally 0) f must now equal +/- GCD of - * the initial f, g values i.e. +/- 1, and d now contains +/- the modular inverse. */ - - /* g == 0 */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &SECP256K1_SIGNED62_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &SECP256K1_SIGNED62_ONE, -1) == 0 || - secp256k1_modinv64_mul_cmp_62(&f, len, &SECP256K1_SIGNED62_ONE, 1) == 0 || - (secp256k1_modinv64_mul_cmp_62(x, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - secp256k1_modinv64_mul_cmp_62(&d, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) == 0)); - - /* Optionally negate d, normalize to [0,modulus), and return it. */ - secp256k1_modinv64_normalize_62(&d, f.v[len - 1], modinfo); - *x = d; -} - -/* Do up to 25 iterations of 62 posdivsteps (up to 1550 steps; more is extremely rare) each until f=1. - * In VERIFY mode use a lower number of iterations (744, close to the median 756), so failure actually occurs. */ -#ifdef VERIFY -#define JACOBI64_ITERATIONS 12 -#else -#define JACOBI64_ITERATIONS 25 -#endif - -/* Compute the Jacobi symbol of x modulo modinfo->modulus (variable time). gcd(x,modulus) must be 1. */ -static int secp256k1_jacobi64_maybe_var(const secp256k1_modinv64_signed62 *x, const secp256k1_modinv64_modinfo *modinfo) { - /* Start with f=modulus, g=x, eta=-1. */ - secp256k1_modinv64_signed62 f = modinfo->modulus; - secp256k1_modinv64_signed62 g = *x; - int j, len = 5; - int64_t eta = -1; /* eta = -delta; delta is initially 1 */ - int64_t cond, fn, gn; - int jac = 0; - int count; - - /* The input limbs must all be non-negative. */ - VERIFY_CHECK(g.v[0] >= 0 && g.v[1] >= 0 && g.v[2] >= 0 && g.v[3] >= 0 && g.v[4] >= 0); - - /* If x > 0, then if the loop below converges, it converges to f=g=gcd(x,modulus). Since we - * require that gcd(x,modulus)=1 and modulus>=3, x cannot be 0. Thus, we must reach f=1 (or - * time out). */ - VERIFY_CHECK((g.v[0] | g.v[1] | g.v[2] | g.v[3] | g.v[4]) != 0); - - for (count = 0; count < JACOBI64_ITERATIONS; ++count) { - /* Compute transition matrix and new eta after 62 posdivsteps. */ - secp256k1_modinv64_trans2x2 t; - eta = secp256k1_modinv64_posdivsteps_62_var(eta, f.v[0] | ((uint64_t)f.v[1] << 62), g.v[0] | ((uint64_t)g.v[1] << 62), &t, &jac); - /* Update f,g using that transition matrix. */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - - secp256k1_modinv64_update_fg_62_var(len, &f, &g, &t); - /* If the bottom limb of f is 1, there is a chance that f=1. */ - if (f.v[0] == 1) { - cond = 0; - /* Check if the other limbs are also 0. */ - for (j = 1; j < len; ++j) { - cond |= f.v[j]; - } - /* If so, we're done. When f=1, the Jacobi symbol (g | f)=1. */ - if (cond == 0) return 1 - 2*(jac & 1); - } - - /* Determine if len>1 and limb (len-1) of both f and g is 0. */ - fn = f.v[len - 1]; - gn = g.v[len - 1]; - cond = ((int64_t)len - 2) >> 63; - cond |= fn; - cond |= gn; - /* If so, reduce length. */ - if (cond == 0) --len; - - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ - VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - } - - /* The loop failed to converge to f=g after 1550 iterations. Return 0, indicating unknown result. */ - return 0; -} - -#endif /* SECP256K1_MODINV64_IMPL_H */ diff --git a/external/secp256k1/src/modules/ecdh/Makefile.am.include b/external/secp256k1/src/modules/ecdh/Makefile.am.include deleted file mode 100644 index 7f7f95f1fd..0000000000 --- a/external/secp256k1/src/modules/ecdh/Makefile.am.include +++ /dev/null @@ -1,4 +0,0 @@ -include_HEADERS += include/secp256k1_ecdh.h -noinst_HEADERS += src/modules/ecdh/main_impl.h -noinst_HEADERS += src/modules/ecdh/tests_impl.h -noinst_HEADERS += src/modules/ecdh/bench_impl.h diff --git a/external/secp256k1/src/modules/ecdh/bench_impl.h b/external/secp256k1/src/modules/ecdh/bench_impl.h deleted file mode 100644 index c23aaa94d1..0000000000 --- a/external/secp256k1/src/modules/ecdh/bench_impl.h +++ /dev/null @@ -1,57 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_ECDH_BENCH_H -#define SECP256K1_MODULE_ECDH_BENCH_H - -#include "../../../include/secp256k1_ecdh.h" - -typedef struct { - secp256k1_context *ctx; - secp256k1_pubkey point; - unsigned char scalar[32]; -} bench_ecdh_data; - -static void bench_ecdh_setup(void* arg) { - int i; - bench_ecdh_data *data = (bench_ecdh_data*)arg; - const unsigned char point[] = { - 0x03, - 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, - 0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, - 0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, - 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f - }; - - for (i = 0; i < 32; i++) { - data->scalar[i] = i + 1; - } - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); -} - -static void bench_ecdh(void* arg, int iters) { - int i; - unsigned char res[32]; - bench_ecdh_data *data = (bench_ecdh_data*)arg; - - for (i = 0; i < iters; i++) { - CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar, NULL, NULL) == 1); - } -} - -static void run_ecdh_bench(int iters, int argc, char** argv) { - bench_ecdh_data data; - int d = argc == 1; - - /* create a context with no capabilities */ - data.ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); - - if (d || have_flag(argc, argv, "ecdh")) run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters); - - secp256k1_context_destroy(data.ctx); -} - -#endif /* SECP256K1_MODULE_ECDH_BENCH_H */ diff --git a/external/secp256k1/src/modules/ecdh/main_impl.h b/external/secp256k1/src/modules/ecdh/main_impl.h deleted file mode 100644 index 842b5359e3..0000000000 --- a/external/secp256k1/src/modules/ecdh/main_impl.h +++ /dev/null @@ -1,74 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_ECDH_MAIN_H -#define SECP256K1_MODULE_ECDH_MAIN_H - -#include "../../../include/secp256k1_ecdh.h" -#include "../../ecmult_const_impl.h" - -static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { - unsigned char version = (y32[31] & 0x01) | 0x02; - secp256k1_sha256 sha; - (void)data; - - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, &version, 1); - secp256k1_sha256_write(&sha, x32, 32); - secp256k1_sha256_finalize(&sha, output); - secp256k1_sha256_clear(&sha); - - return 1; -} - -const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256 = ecdh_hash_function_sha256; -const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default = ecdh_hash_function_sha256; - -int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pubkey *point, const unsigned char *scalar, secp256k1_ecdh_hash_function hashfp, void *data) { - int ret = 0; - int overflow = 0; - secp256k1_gej res; - secp256k1_ge pt; - secp256k1_scalar s; - unsigned char x[32]; - unsigned char y[32]; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output != NULL); - ARG_CHECK(point != NULL); - ARG_CHECK(scalar != NULL); - - if (hashfp == NULL) { - hashfp = secp256k1_ecdh_hash_function_default; - } - - secp256k1_pubkey_load(ctx, &pt, point); - secp256k1_scalar_set_b32(&s, scalar, &overflow); - - overflow |= secp256k1_scalar_is_zero(&s); - secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow); - - secp256k1_ecmult_const(&res, &pt, &s); - secp256k1_ge_set_gej(&pt, &res); - - /* Compute a hash of the point */ - secp256k1_fe_normalize(&pt.x); - secp256k1_fe_normalize(&pt.y); - secp256k1_fe_get_b32(x, &pt.x); - secp256k1_fe_get_b32(y, &pt.y); - - ret = hashfp(output, x, y, data); - - secp256k1_memclear(x, sizeof(x)); - secp256k1_memclear(y, sizeof(y)); - secp256k1_scalar_clear(&s); - secp256k1_ge_clear(&pt); - secp256k1_gej_clear(&res); - - return !!ret & !overflow; -} - -#endif /* SECP256K1_MODULE_ECDH_MAIN_H */ diff --git a/external/secp256k1/src/modules/ecdh/tests_impl.h b/external/secp256k1/src/modules/ecdh/tests_impl.h deleted file mode 100644 index 3c3acdaf8c..0000000000 --- a/external/secp256k1/src/modules/ecdh/tests_impl.h +++ /dev/null @@ -1,152 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_ECDH_TESTS_H -#define SECP256K1_MODULE_ECDH_TESTS_H - -static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { - (void)output; - (void)x; - (void)y; - (void)data; - return 0; -} - -static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { - (void)data; - /* Save x and y as uncompressed public key */ - output[0] = 0x04; - memcpy(output + 1, x, 32); - memcpy(output + 33, y, 32); - return 1; -} - -static void test_ecdh_api(void) { - secp256k1_pubkey point; - unsigned char res[32]; - unsigned char s_one[32] = { 0 }; - s_one[31] = 1; - - CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_one) == 1); - - /* Check all NULLs are detected */ - CHECK(secp256k1_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, NULL, &point, s_one, NULL, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, res, NULL, s_one, NULL, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, res, &point, NULL, NULL, NULL)); - CHECK(secp256k1_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1); -} - -static void test_ecdh_generator_basepoint(void) { - unsigned char s_one[32] = { 0 }; - secp256k1_pubkey point[2]; - int i; - - s_one[31] = 1; - /* Check against pubkey creation when the basepoint is the generator */ - for (i = 0; i < 2 * COUNT; ++i) { - secp256k1_sha256 sha; - unsigned char s_b32[32]; - unsigned char output_ecdh[65]; - unsigned char output_ser[32]; - unsigned char point_ser[65]; - size_t point_ser_len = sizeof(point_ser); - secp256k1_scalar s; - - testutil_random_scalar_order(&s); - secp256k1_scalar_get_b32(s_b32, &s); - - CHECK(secp256k1_ec_pubkey_create(CTX, &point[0], s_one) == 1); - CHECK(secp256k1_ec_pubkey_create(CTX, &point[1], s_b32) == 1); - - /* compute using ECDH function with custom hash function */ - CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1); - /* compute "explicitly" */ - CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1); - /* compare */ - CHECK(secp256k1_memcmp_var(output_ecdh, point_ser, 65) == 0); - - /* compute using ECDH function with default hash function */ - CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, NULL, NULL) == 1); - /* compute "explicitly" */ - CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, point_ser, point_ser_len); - secp256k1_sha256_finalize(&sha, output_ser); - /* compare */ - CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0); - } -} - -static void test_bad_scalar(void) { - unsigned char s_zero[32] = { 0 }; - unsigned char s_overflow[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 - }; - unsigned char s_rand[32] = { 0 }; - unsigned char output[32]; - secp256k1_scalar rand; - secp256k1_pubkey point; - - /* Create random point */ - testutil_random_scalar_order(&rand); - secp256k1_scalar_get_b32(s_rand, &rand); - CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_rand) == 1); - - /* Try to multiply it by bad values */ - CHECK(secp256k1_ecdh(CTX, output, &point, s_zero, NULL, NULL) == 0); - CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 0); - /* ...and a good one */ - s_overflow[31] -= 1; - CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 1); - - /* Hash function failure results in ecdh failure */ - CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0); -} - -/** Test that ECDH(sG, 1/s) == ECDH((1/s)G, s) == ECDH(G, 1) for a few random s. */ -static void test_result_basepoint(void) { - secp256k1_pubkey point; - secp256k1_scalar rand; - unsigned char s[32]; - unsigned char s_inv[32]; - unsigned char out[32]; - unsigned char out_inv[32]; - unsigned char out_base[32]; - int i; - - unsigned char s_one[32] = { 0 }; - s_one[31] = 1; - CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_one) == 1); - CHECK(secp256k1_ecdh(CTX, out_base, &point, s_one, NULL, NULL) == 1); - - for (i = 0; i < 2 * COUNT; i++) { - testutil_random_scalar_order(&rand); - secp256k1_scalar_get_b32(s, &rand); - secp256k1_scalar_inverse(&rand, &rand); - secp256k1_scalar_get_b32(s_inv, &rand); - - CHECK(secp256k1_ec_pubkey_create(CTX, &point, s) == 1); - CHECK(secp256k1_ecdh(CTX, out, &point, s_inv, NULL, NULL) == 1); - CHECK(secp256k1_memcmp_var(out, out_base, 32) == 0); - - CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_inv) == 1); - CHECK(secp256k1_ecdh(CTX, out_inv, &point, s, NULL, NULL) == 1); - CHECK(secp256k1_memcmp_var(out_inv, out_base, 32) == 0); - } -} - -static void run_ecdh_tests(void) { - test_ecdh_api(); - test_ecdh_generator_basepoint(); - test_bad_scalar(); - test_result_basepoint(); -} - -#endif /* SECP256K1_MODULE_ECDH_TESTS_H */ diff --git a/external/secp256k1/src/modules/ellswift/Makefile.am.include b/external/secp256k1/src/modules/ellswift/Makefile.am.include deleted file mode 100644 index 8251231ea3..0000000000 --- a/external/secp256k1/src/modules/ellswift/Makefile.am.include +++ /dev/null @@ -1,5 +0,0 @@ -include_HEADERS += include/secp256k1_ellswift.h -noinst_HEADERS += src/modules/ellswift/bench_impl.h -noinst_HEADERS += src/modules/ellswift/main_impl.h -noinst_HEADERS += src/modules/ellswift/tests_impl.h -noinst_HEADERS += src/modules/ellswift/tests_exhaustive_impl.h diff --git a/external/secp256k1/src/modules/ellswift/bench_impl.h b/external/secp256k1/src/modules/ellswift/bench_impl.h deleted file mode 100644 index b16a3a3687..0000000000 --- a/external/secp256k1/src/modules/ellswift/bench_impl.h +++ /dev/null @@ -1,106 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_ELLSWIFT_BENCH_H -#define SECP256K1_MODULE_ELLSWIFT_BENCH_H - -#include "../../../include/secp256k1_ellswift.h" - -typedef struct { - secp256k1_context *ctx; - secp256k1_pubkey point[256]; - unsigned char rnd64[64]; -} bench_ellswift_data; - -static void bench_ellswift_setup(void *arg) { - int i; - bench_ellswift_data *data = (bench_ellswift_data*)arg; - static const unsigned char init[64] = { - 0x78, 0x1f, 0xb7, 0xd4, 0x67, 0x7f, 0x08, 0x68, - 0xdb, 0xe3, 0x1d, 0x7f, 0x1b, 0xb0, 0xf6, 0x9e, - 0x0a, 0x64, 0xca, 0x32, 0x9e, 0xc6, 0x20, 0x79, - 0x03, 0xf3, 0xd0, 0x46, 0x7a, 0x0f, 0xd2, 0x21, - 0xb0, 0x2c, 0x46, 0xd8, 0xba, 0xca, 0x26, 0x4f, - 0x8f, 0x8c, 0xd4, 0xdd, 0x2d, 0x04, 0xbe, 0x30, - 0x48, 0x51, 0x1e, 0xd4, 0x16, 0xfd, 0x42, 0x85, - 0x62, 0xc9, 0x02, 0xf9, 0x89, 0x84, 0xff, 0xdc - }; - memcpy(data->rnd64, init, 64); - for (i = 0; i < 256; ++i) { - int j; - CHECK(secp256k1_ellswift_decode(data->ctx, &data->point[i], data->rnd64)); - for (j = 0; j < 64; ++j) { - data->rnd64[j] += 1; - } - } - CHECK(secp256k1_ellswift_encode(data->ctx, data->rnd64, &data->point[255], init + 16)); -} - -static void bench_ellswift_encode(void *arg, int iters) { - int i; - bench_ellswift_data *data = (bench_ellswift_data*)arg; - - for (i = 0; i < iters; i++) { - CHECK(secp256k1_ellswift_encode(data->ctx, data->rnd64, &data->point[i & 255], data->rnd64 + 16)); - } -} - -static void bench_ellswift_create(void *arg, int iters) { - int i; - bench_ellswift_data *data = (bench_ellswift_data*)arg; - - for (i = 0; i < iters; i++) { - unsigned char buf[64]; - CHECK(secp256k1_ellswift_create(data->ctx, buf, data->rnd64, data->rnd64 + 32)); - memcpy(data->rnd64, buf, 64); - } -} - -static void bench_ellswift_decode(void *arg, int iters) { - int i; - secp256k1_pubkey out; - size_t len; - bench_ellswift_data *data = (bench_ellswift_data*)arg; - - for (i = 0; i < iters; i++) { - CHECK(secp256k1_ellswift_decode(data->ctx, &out, data->rnd64) == 1); - len = 33; - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->rnd64 + (i % 32), &len, &out, SECP256K1_EC_COMPRESSED)); - } -} - -static void bench_ellswift_xdh(void *arg, int iters) { - int i; - bench_ellswift_data *data = (bench_ellswift_data*)arg; - - for (i = 0; i < iters; i++) { - int party = i & 1; - CHECK(secp256k1_ellswift_xdh(data->ctx, - data->rnd64 + (i % 33), - data->rnd64, - data->rnd64, - data->rnd64 + ((i + 16) % 33), - party, - secp256k1_ellswift_xdh_hash_function_bip324, - NULL) == 1); - } -} - -void run_ellswift_bench(int iters, int argc, char **argv) { - bench_ellswift_data data; - int d = argc == 1; - - /* create a context with signing capabilities */ - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - - if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "encode") || have_flag(argc, argv, "ellswift_encode")) run_benchmark("ellswift_encode", bench_ellswift_encode, bench_ellswift_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_decode")) run_benchmark("ellswift_decode", bench_ellswift_decode, bench_ellswift_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "keygen") || have_flag(argc, argv, "ellswift_keygen")) run_benchmark("ellswift_keygen", bench_ellswift_create, bench_ellswift_setup, NULL, &data, 10, iters); - if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ecdh") || have_flag(argc, argv, "ellswift_ecdh")) run_benchmark("ellswift_ecdh", bench_ellswift_xdh, bench_ellswift_setup, NULL, &data, 10, iters); - - secp256k1_context_destroy(data.ctx); -} - -#endif diff --git a/external/secp256k1/src/modules/ellswift/main_impl.h b/external/secp256k1/src/modules/ellswift/main_impl.h deleted file mode 100644 index 745a969139..0000000000 --- a/external/secp256k1/src/modules/ellswift/main_impl.h +++ /dev/null @@ -1,592 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_ELLSWIFT_MAIN_H -#define SECP256K1_MODULE_ELLSWIFT_MAIN_H - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_ellswift.h" -#include "../../eckey.h" -#include "../../hash.h" - -/** c1 = (sqrt(-3)-1)/2 */ -static const secp256k1_fe secp256k1_ellswift_c1 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40); -/** c2 = (-sqrt(-3)-1)/2 = -(c1+1) */ -static const secp256k1_fe secp256k1_ellswift_c2 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ee); -/** c3 = (-sqrt(-3)+1)/2 = -c1 = c2+1 */ -static const secp256k1_fe secp256k1_ellswift_c3 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ef); -/** c4 = (sqrt(-3)+1)/2 = -c2 = c1+1 */ -static const secp256k1_fe secp256k1_ellswift_c4 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa41); - -/** Decode ElligatorSwift encoding (u, t) to a fraction xn/xd representing a curve X coordinate. */ -static void secp256k1_ellswift_xswiftec_frac_var(secp256k1_fe *xn, secp256k1_fe *xd, const secp256k1_fe *u, const secp256k1_fe *t) { - /* The implemented algorithm is the following (all operations in GF(p)): - * - * - Let c0 = sqrt(-3) = 0xa2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f852. - * - If u = 0, set u = 1. - * - If t = 0, set t = 1. - * - If u^3+7+t^2 = 0, set t = 2*t. - * - Let X = (u^3+7-t^2)/(2*t). - * - Let Y = (X+t)/(c0*u). - * - If x3 = u+4*Y^2 is a valid x coordinate, return it. - * - If x2 = (-X/Y-u)/2 is a valid x coordinate, return it. - * - Return x1 = (X/Y-u)/2 (which is now guaranteed to be a valid x coordinate). - * - * Introducing s=t^2, g=u^3+7, and simplifying x1=-(x2+u) we get: - * - * - Let c0 = ... - * - If u = 0, set u = 1. - * - If t = 0, set t = 1. - * - Let s = t^2 - * - Let g = u^3+7 - * - If g+s = 0, set t = 2*t, s = 4*s - * - Let X = (g-s)/(2*t). - * - Let Y = (X+t)/(c0*u) = (g+s)/(2*c0*t*u). - * - If x3 = u+4*Y^2 is a valid x coordinate, return it. - * - If x2 = (-X/Y-u)/2 is a valid x coordinate, return it. - * - Return x1 = -(x2+u). - * - * Now substitute Y^2 = -(g+s)^2/(12*s*u^2) and X/Y = c0*u*(g-s)/(g+s). This - * means X and Y do not need to be evaluated explicitly anymore. - * - * - ... - * - If g+s = 0, set s = 4*s. - * - If x3 = u-(g+s)^2/(3*s*u^2) is a valid x coordinate, return it. - * - If x2 = (-c0*u*(g-s)/(g+s)-u)/2 is a valid x coordinate, return it. - * - Return x1 = -(x2+u). - * - * Simplifying x2 using 2 additional constants: - * - * - Let c1 = (c0-1)/2 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40. - * - Let c2 = (-c0-1)/2 = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee. - * - ... - * - If x2 = u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it. - * - ... - * - * Writing x3 as a fraction: - * - * - ... - * - If x3 = (3*s*u^3-(g+s)^2)/(3*s*u^2) ... - * - ... - - * Overall, we get: - * - * - Let c1 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40. - * - Let c2 = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee. - * - If u = 0, set u = 1. - * - If t = 0, set s = 1, else set s = t^2. - * - Let g = u^3+7. - * - If g+s = 0, set s = 4*s. - * - If x3 = (3*s*u^3-(g+s)^2)/(3*s*u^2) is a valid x coordinate, return it. - * - If x2 = u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it. - * - Return x1 = -(x2+u). - */ - secp256k1_fe u1, s, g, p, d, n, l; - u1 = *u; - if (EXPECT(secp256k1_fe_normalizes_to_zero_var(&u1), 0)) u1 = secp256k1_fe_one; - secp256k1_fe_sqr(&s, t); - if (EXPECT(secp256k1_fe_normalizes_to_zero_var(t), 0)) s = secp256k1_fe_one; - secp256k1_fe_sqr(&l, &u1); /* l = u^2 */ - secp256k1_fe_mul(&g, &l, &u1); /* g = u^3 */ - secp256k1_fe_add_int(&g, SECP256K1_B); /* g = u^3 + 7 */ - p = g; /* p = g */ - secp256k1_fe_add(&p, &s); /* p = g+s */ - if (EXPECT(secp256k1_fe_normalizes_to_zero_var(&p), 0)) { - secp256k1_fe_mul_int(&s, 4); - /* Recompute p = g+s */ - p = g; /* p = g */ - secp256k1_fe_add(&p, &s); /* p = g+s */ - } - secp256k1_fe_mul(&d, &s, &l); /* d = s*u^2 */ - secp256k1_fe_mul_int(&d, 3); /* d = 3*s*u^2 */ - secp256k1_fe_sqr(&l, &p); /* l = (g+s)^2 */ - secp256k1_fe_negate(&l, &l, 1); /* l = -(g+s)^2 */ - secp256k1_fe_mul(&n, &d, &u1); /* n = 3*s*u^3 */ - secp256k1_fe_add(&n, &l); /* n = 3*s*u^3-(g+s)^2 */ - if (secp256k1_ge_x_frac_on_curve_var(&n, &d)) { - /* Return x3 = n/d = (3*s*u^3-(g+s)^2)/(3*s*u^2) */ - *xn = n; - *xd = d; - return; - } - *xd = p; - secp256k1_fe_mul(&l, &secp256k1_ellswift_c1, &s); /* l = c1*s */ - secp256k1_fe_mul(&n, &secp256k1_ellswift_c2, &g); /* n = c2*g */ - secp256k1_fe_add(&n, &l); /* n = c1*s+c2*g */ - secp256k1_fe_mul(&n, &n, &u1); /* n = u*(c1*s+c2*g) */ - /* Possible optimization: in the invocation below, p^2 = (g+s)^2 is computed, - * which we already have computed above. This could be deduplicated. */ - if (secp256k1_ge_x_frac_on_curve_var(&n, &p)) { - /* Return x2 = n/p = u*(c1*s+c2*g)/(g+s) */ - *xn = n; - return; - } - secp256k1_fe_mul(&l, &p, &u1); /* l = u*(g+s) */ - secp256k1_fe_add(&n, &l); /* n = u*(c1*s+c2*g)+u*(g+s) */ - secp256k1_fe_negate(xn, &n, 2); /* n = -u*(c1*s+c2*g)-u*(g+s) */ - - VERIFY_CHECK(secp256k1_ge_x_frac_on_curve_var(xn, &p)); - /* Return x3 = n/p = -(u*(c1*s+c2*g)/(g+s)+u) */ -} - -/** Decode ElligatorSwift encoding (u, t) to X coordinate. */ -static void secp256k1_ellswift_xswiftec_var(secp256k1_fe *x, const secp256k1_fe *u, const secp256k1_fe *t) { - secp256k1_fe xn, xd; - secp256k1_ellswift_xswiftec_frac_var(&xn, &xd, u, t); - secp256k1_fe_inv_var(&xd, &xd); - secp256k1_fe_mul(x, &xn, &xd); -} - -/** Decode ElligatorSwift encoding (u, t) to point P. */ -static void secp256k1_ellswift_swiftec_var(secp256k1_ge *p, const secp256k1_fe *u, const secp256k1_fe *t) { - secp256k1_fe x; - secp256k1_ellswift_xswiftec_var(&x, u, t); - secp256k1_ge_set_xo_var(p, &x, secp256k1_fe_is_odd(t)); -} - -/* Try to complete an ElligatorSwift encoding (u, t) for X coordinate x, given u and x. - * - * There may be up to 8 distinct t values such that (u, t) decodes back to x, but also - * fewer, or none at all. Each such partial inverse can be accessed individually using a - * distinct input argument c (in range 0-7), and some or all of these may return failure. - * The following guarantees exist: - * - Given (x, u), no two distinct c values give the same successful result t. - * - Every successful result maps back to x through secp256k1_ellswift_xswiftec_var. - * - Given (x, u), all t values that map back to x can be reached by combining the - * successful results from this function over all c values, with the exception of: - * - this function cannot be called with u=0 - * - no result with t=0 will be returned - * - no result for which u^3 + t^2 + 7 = 0 will be returned. - * - * The rather unusual encoding of bits in c (a large "if" based on the middle bit, and then - * using the low and high bits to pick signs of square roots) is to match the paper's - * encoding more closely: c=0 through c=3 match branches 1..4 in the paper, while c=4 through - * c=7 are copies of those with an additional negation of sqrt(w). - */ -static int secp256k1_ellswift_xswiftec_inv_var(secp256k1_fe *t, const secp256k1_fe *x_in, const secp256k1_fe *u_in, int c) { - /* The implemented algorithm is this (all arithmetic, except involving c, is mod p): - * - * - If (c & 2) = 0: - * - If (-x-u) is a valid X coordinate, fail. - * - Let s=-(u^3+7)/(u^2+u*x+x^2). - * - If s is not square, fail. - * - Let v=x. - * - If (c & 2) = 2: - * - Let s=x-u. - * - If s is not square, fail. - * - Let r=sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist. - * - If (c & 1) = 1 and r = 0, fail. - * - If s=0, fail. - * - Let v=(r/s-u)/2. - * - Let w=sqrt(s). - * - If (c & 5) = 0: return -w*(c3*u + v). - * - If (c & 5) = 1: return w*(c4*u + v). - * - If (c & 5) = 4: return w*(c3*u + v). - * - If (c & 5) = 5: return -w*(c4*u + v). - */ - secp256k1_fe x = *x_in, u = *u_in, g, v, s, m, r, q; - int ret; - - secp256k1_fe_normalize_weak(&x); - secp256k1_fe_normalize_weak(&u); - - VERIFY_CHECK(c >= 0 && c < 8); - VERIFY_CHECK(secp256k1_ge_x_on_curve_var(&x)); - - if (!(c & 2)) { - /* c is in {0, 1, 4, 5}. In this case we look for an inverse under the x1 (if c=0 or - * c=4) formula, or x2 (if c=1 or c=5) formula. */ - - /* If -u-x is a valid X coordinate, fail. This would yield an encoding that roundtrips - * back under the x3 formula instead (which has priority over x1 and x2, so the decoding - * would not match x). */ - m = x; /* m = x */ - secp256k1_fe_add(&m, &u); /* m = u+x */ - secp256k1_fe_negate(&m, &m, 2); /* m = -u-x */ - /* Test if (-u-x) is a valid X coordinate. If so, fail. */ - if (secp256k1_ge_x_on_curve_var(&m)) return 0; - - /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [first part] */ - secp256k1_fe_sqr(&s, &m); /* s = (u+x)^2 */ - secp256k1_fe_negate(&s, &s, 1); /* s = -(u+x)^2 */ - secp256k1_fe_mul(&m, &u, &x); /* m = u*x */ - secp256k1_fe_add(&s, &m); /* s = -(u^2 + u*x + x^2) */ - - /* Note that at this point, s = 0 is impossible. If it were the case: - * s = -(u^2 + u*x + x^2) = 0 - * => u^2 + u*x + x^2 = 0 - * => (u + 2*x) * (u^2 + u*x + x^2) = 0 - * => 2*x^3 + 3*x^2*u + 3*x*u^2 + u^3 = 0 - * => (x + u)^3 + x^3 = 0 - * => x^3 = -(x + u)^3 - * => x^3 + B = (-u - x)^3 + B - * - * However, we know x^3 + B is square (because x is on the curve) and - * that (-u-x)^3 + B is not square (the secp256k1_ge_x_on_curve_var(&m) - * test above would have failed). This is a contradiction, and thus the - * assumption s=0 is false. */ - VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(&s)); - - /* If s is not square, fail. We have not fully computed s yet, but s is square iff - * -(u^3+7)*(u^2+u*x+x^2) is square (because a/b is square iff a*b is square and b is - * nonzero). */ - secp256k1_fe_sqr(&g, &u); /* g = u^2 */ - secp256k1_fe_mul(&g, &g, &u); /* g = u^3 */ - secp256k1_fe_add_int(&g, SECP256K1_B); /* g = u^3+7 */ - secp256k1_fe_mul(&m, &s, &g); /* m = -(u^3 + 7)*(u^2 + u*x + x^2) */ - if (!secp256k1_fe_is_square_var(&m)) return 0; - - /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [second part] */ - secp256k1_fe_inv_var(&s, &s); /* s = -1/(u^2 + u*x + x^2) [no div by 0] */ - secp256k1_fe_mul(&s, &s, &g); /* s = -(u^3 + 7)/(u^2 + u*x + x^2) */ - - /* Let v = x. */ - v = x; - } else { - /* c is in {2, 3, 6, 7}. In this case we look for an inverse under the x3 formula. */ - - /* Let s = x-u. */ - secp256k1_fe_negate(&m, &u, 1); /* m = -u */ - s = m; /* s = -u */ - secp256k1_fe_add(&s, &x); /* s = x-u */ - - /* If s is not square, fail. */ - if (!secp256k1_fe_is_square_var(&s)) return 0; - - /* Let r = sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist. */ - secp256k1_fe_sqr(&g, &u); /* g = u^2 */ - secp256k1_fe_mul(&q, &s, &g); /* q = s*u^2 */ - secp256k1_fe_mul_int(&q, 3); /* q = 3*s*u^2 */ - secp256k1_fe_mul(&g, &g, &u); /* g = u^3 */ - secp256k1_fe_mul_int(&g, 4); /* g = 4*u^3 */ - secp256k1_fe_add_int(&g, 4 * SECP256K1_B); /* g = 4*(u^3+7) */ - secp256k1_fe_add(&q, &g); /* q = 4*(u^3+7)+3*s*u^2 */ - secp256k1_fe_mul(&q, &q, &s); /* q = s*(4*(u^3+7)+3*u^2*s) */ - secp256k1_fe_negate(&q, &q, 1); /* q = -s*(4*(u^3+7)+3*u^2*s) */ - if (!secp256k1_fe_is_square_var(&q)) return 0; - ret = secp256k1_fe_sqrt(&r, &q); /* r = sqrt(-s*(4*(u^3+7)+3*u^2*s)) */ -#ifdef VERIFY - VERIFY_CHECK(ret); -#else - (void)ret; -#endif - - /* If (c & 1) = 1 and r = 0, fail. */ - if (EXPECT((c & 1) && secp256k1_fe_normalizes_to_zero_var(&r), 0)) return 0; - - /* If s = 0, fail. */ - if (EXPECT(secp256k1_fe_normalizes_to_zero_var(&s), 0)) return 0; - - /* Let v = (r/s-u)/2. */ - secp256k1_fe_inv_var(&v, &s); /* v = 1/s [no div by 0] */ - secp256k1_fe_mul(&v, &v, &r); /* v = r/s */ - secp256k1_fe_add(&v, &m); /* v = r/s-u */ - secp256k1_fe_half(&v); /* v = (r/s-u)/2 */ - } - - /* Let w = sqrt(s). */ - ret = secp256k1_fe_sqrt(&m, &s); /* m = sqrt(s) = w */ - VERIFY_CHECK(ret); - - /* Return logic. */ - if ((c & 5) == 0 || (c & 5) == 5) { - secp256k1_fe_negate(&m, &m, 1); /* m = -w */ - } - /* Now m = {-w if c&5=0 or c&5=5; w otherwise}. */ - secp256k1_fe_mul(&u, &u, c&1 ? &secp256k1_ellswift_c4 : &secp256k1_ellswift_c3); - /* u = {c4 if c&1=1; c3 otherwise}*u */ - secp256k1_fe_add(&u, &v); /* u = {c4 if c&1=1; c3 otherwise}*u + v */ - secp256k1_fe_mul(t, &m, &u); - return 1; -} - -/** Use SHA256 as a PRNG, returning SHA256(hasher || cnt). - * - * hasher is a SHA256 object to which an incrementing 4-byte counter is written to generate randomness. - * Writing 13 bytes (4 bytes for counter, plus 9 bytes for the SHA256 padding) cannot cross a - * 64-byte block size boundary (to make sure it only triggers a single SHA256 compression). */ -static void secp256k1_ellswift_prng(unsigned char* out32, const secp256k1_sha256 *hasher, uint32_t cnt) { - secp256k1_sha256 hash = *hasher; - unsigned char buf4[4]; -#ifdef VERIFY - size_t blocks = hash.bytes >> 6; -#endif - buf4[0] = cnt; - buf4[1] = cnt >> 8; - buf4[2] = cnt >> 16; - buf4[3] = cnt >> 24; - secp256k1_sha256_write(&hash, buf4, 4); - secp256k1_sha256_finalize(&hash, out32); - - /* Writing and finalizing together should trigger exactly one SHA256 compression. */ - VERIFY_CHECK(((hash.bytes) >> 6) == (blocks + 1)); -} - -/** Find an ElligatorSwift encoding (u, t) for X coordinate x, and random Y coordinate. - * - * u32 is the 32-byte big endian encoding of u; t is the output field element t that still - * needs encoding. - * - * hasher is a hasher in the secp256k1_ellswift_prng sense, with the same restrictions. */ -static void secp256k1_ellswift_xelligatorswift_var(unsigned char *u32, secp256k1_fe *t, const secp256k1_fe *x, const secp256k1_sha256 *hasher) { - /* Pool of 3-bit branch values. */ - unsigned char branch_hash[32]; - /* Number of 3-bit values in branch_hash left. */ - int branches_left = 0; - /* Field elements u and branch values are extracted from RNG based on hasher for consecutive - * values of cnt. cnt==0 is first used to populate a pool of 64 4-bit branch values. The 64 - * cnt values that follow are used to generate field elements u. cnt==65 (and multiples - * thereof) are used to repopulate the pool and start over, if that were ever necessary. - * On average, 4 iterations are needed. */ - uint32_t cnt = 0; - while (1) { - int branch; - secp256k1_fe u; - /* If the pool of branch values is empty, populate it. */ - if (branches_left == 0) { - secp256k1_ellswift_prng(branch_hash, hasher, cnt++); - branches_left = 64; - } - /* Take a 3-bit branch value from the branch pool (top bit is discarded). */ - --branches_left; - branch = (branch_hash[branches_left >> 1] >> ((branches_left & 1) << 2)) & 7; - /* Compute a new u value by hashing. */ - secp256k1_ellswift_prng(u32, hasher, cnt++); - /* overflow is not a problem (we prefer uniform u32 over uniform u). */ - secp256k1_fe_set_b32_mod(&u, u32); - /* Since u is the output of a hash, it should practically never be 0. We could apply the - * u=0 to u=1 correction here too to deal with that case still, but it's such a low - * probability event that we do not bother. */ - VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(&u)); - - /* Find a remainder t, and return it if found. */ - if (EXPECT(secp256k1_ellswift_xswiftec_inv_var(t, x, &u, branch), 0)) break; - } -} - -/** Find an ElligatorSwift encoding (u, t) for point P. - * - * This is similar secp256k1_ellswift_xelligatorswift_var, except it takes a full group element p - * as input, and returns an encoding that matches the provided Y coordinate rather than a random - * one. - */ -static void secp256k1_ellswift_elligatorswift_var(unsigned char *u32, secp256k1_fe *t, const secp256k1_ge *p, const secp256k1_sha256 *hasher) { - secp256k1_ellswift_xelligatorswift_var(u32, t, &p->x, hasher); - secp256k1_fe_normalize_var(t); - if (secp256k1_fe_is_odd(t) != secp256k1_fe_is_odd(&p->y)) { - secp256k1_fe_negate(t, t, 1); - secp256k1_fe_normalize_var(t); - } -} - -/** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_encode". */ -static void secp256k1_ellswift_sha256_init_encode(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0xd1a6524bul; - hash->s[1] = 0x028594b3ul; - hash->s[2] = 0x96e42f4eul; - hash->s[3] = 0x1037a177ul; - hash->s[4] = 0x1b8fcb8bul; - hash->s[5] = 0x56023885ul; - hash->s[6] = 0x2560ede1ul; - hash->s[7] = 0xd626b715ul; - - hash->bytes = 64; -} - -int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64, const secp256k1_pubkey *pubkey, const unsigned char *rnd32) { - secp256k1_ge p; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(ell64 != NULL); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(rnd32 != NULL); - - if (secp256k1_pubkey_load(ctx, &p, pubkey)) { - secp256k1_fe t; - unsigned char p64[64] = {0}; - size_t ser_size; - int ser_ret; - secp256k1_sha256 hash; - - /* Set up hasher state; the used RNG is H(pubkey || "\x00"*31 || rnd32 || cnt++), using - * BIP340 tagged hash with tag "secp256k1_ellswift_encode". */ - secp256k1_ellswift_sha256_init_encode(&hash); - ser_ret = secp256k1_eckey_pubkey_serialize(&p, p64, &ser_size, 1); -#ifdef VERIFY - VERIFY_CHECK(ser_ret && ser_size == 33); -#else - (void)ser_ret; -#endif - secp256k1_sha256_write(&hash, p64, sizeof(p64)); - secp256k1_sha256_write(&hash, rnd32, 32); - - /* Compute ElligatorSwift encoding and construct output. */ - secp256k1_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ - secp256k1_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ - return 1; - } - /* Only reached in case the provided pubkey is invalid. */ - memset(ell64, 0, 64); - return 0; -} - -/** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_create". */ -static void secp256k1_ellswift_sha256_init_create(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0xd29e1bf5ul; - hash->s[1] = 0xf7025f42ul; - hash->s[2] = 0x9b024773ul; - hash->s[3] = 0x094cb7d5ul; - hash->s[4] = 0xe59ed789ul; - hash->s[5] = 0x03bc9786ul; - hash->s[6] = 0x68335b35ul; - hash->s[7] = 0x4e363b53ul; - - hash->bytes = 64; -} - -int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32) { - secp256k1_ge p; - secp256k1_fe t; - secp256k1_sha256 hash; - secp256k1_scalar seckey_scalar; - int ret; - static const unsigned char zero32[32] = {0}; - - /* Sanity check inputs. */ - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(ell64 != NULL); - memset(ell64, 0, 64); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(seckey32 != NULL); - - /* Compute (affine) public key */ - ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey32); - secp256k1_declassify(ctx, &p, sizeof(p)); /* not constant time in produced pubkey */ - secp256k1_fe_normalize_var(&p.x); - secp256k1_fe_normalize_var(&p.y); - - /* Set up hasher state. The used RNG is H(privkey || "\x00"*32 [|| auxrnd32] || cnt++), - * using BIP340 tagged hash with tag "secp256k1_ellswift_create". */ - secp256k1_ellswift_sha256_init_create(&hash); - secp256k1_sha256_write(&hash, seckey32, 32); - secp256k1_sha256_write(&hash, zero32, sizeof(zero32)); - secp256k1_declassify(ctx, &hash, sizeof(hash)); /* private key is hashed now */ - if (auxrnd32) secp256k1_sha256_write(&hash, auxrnd32, 32); - - /* Compute ElligatorSwift encoding and construct output. */ - secp256k1_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ - secp256k1_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ - - secp256k1_memczero(ell64, 64, !ret); - secp256k1_scalar_clear(&seckey_scalar); - - return ret; -} - -int secp256k1_ellswift_decode(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *ell64) { - secp256k1_fe u, t; - secp256k1_ge p; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(ell64 != NULL); - - secp256k1_fe_set_b32_mod(&u, ell64); - secp256k1_fe_set_b32_mod(&t, ell64 + 32); - secp256k1_fe_normalize_var(&t); - secp256k1_ellswift_swiftec_var(&p, &u, &t); - secp256k1_pubkey_save(pubkey, &p); - return 1; -} - -static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { - secp256k1_sha256 sha; - - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, data, 64); - secp256k1_sha256_write(&sha, ell_a64, 64); - secp256k1_sha256_write(&sha, ell_b64, 64); - secp256k1_sha256_write(&sha, x32, 32); - secp256k1_sha256_finalize(&sha, output); - secp256k1_sha256_clear(&sha); - - return 1; -} - -/** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */ -static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0x8c12d730ul; - hash->s[1] = 0x827bd392ul; - hash->s[2] = 0x9e4fb2eeul; - hash->s[3] = 0x207b373eul; - hash->s[4] = 0x2292bd7aul; - hash->s[5] = 0xaa5441bcul; - hash->s[6] = 0x15c3779ful; - hash->s[7] = 0xcfb52549ul; - - hash->bytes = 64; -} - -static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { - secp256k1_sha256 sha; - - (void)data; - - secp256k1_ellswift_sha256_init_bip324(&sha); - secp256k1_sha256_write(&sha, ell_a64, 64); - secp256k1_sha256_write(&sha, ell_b64, 64); - secp256k1_sha256_write(&sha, x32, 32); - secp256k1_sha256_finalize(&sha, output); - secp256k1_sha256_clear(&sha); - - return 1; -} - -const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix = ellswift_xdh_hash_function_prefix; -const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324 = ellswift_xdh_hash_function_bip324; - -int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, const unsigned char *ell_a64, const unsigned char *ell_b64, const unsigned char *seckey32, int party, secp256k1_ellswift_xdh_hash_function hashfp, void *data) { - int ret = 0; - int overflow; - secp256k1_scalar s; - secp256k1_fe xn, xd, px, u, t; - unsigned char sx[32]; - const unsigned char* theirs64; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output != NULL); - ARG_CHECK(ell_a64 != NULL); - ARG_CHECK(ell_b64 != NULL); - ARG_CHECK(seckey32 != NULL); - ARG_CHECK(hashfp != NULL); - - /* Load remote public key (as fraction). */ - theirs64 = party ? ell_a64 : ell_b64; - secp256k1_fe_set_b32_mod(&u, theirs64); - secp256k1_fe_set_b32_mod(&t, theirs64 + 32); - secp256k1_ellswift_xswiftec_frac_var(&xn, &xd, &u, &t); - - /* Load private key (using one if invalid). */ - secp256k1_scalar_set_b32(&s, seckey32, &overflow); - overflow = secp256k1_scalar_is_zero(&s); - secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow); - - /* Compute shared X coordinate. */ - secp256k1_ecmult_const_xonly(&px, &xn, &xd, &s, 1); - secp256k1_fe_normalize(&px); - secp256k1_fe_get_b32(sx, &px); - - /* Invoke hasher */ - ret = hashfp(output, sx, ell_a64, ell_b64, data); - - secp256k1_memclear(sx, sizeof(sx)); - secp256k1_fe_clear(&px); - secp256k1_scalar_clear(&s); - - return !!ret & !overflow; -} - -#endif diff --git a/external/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h b/external/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h deleted file mode 100644 index 839c24aee4..0000000000 --- a/external/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h +++ /dev/null @@ -1,39 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H -#define SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H - -#include "../../../include/secp256k1_ellswift.h" -#include "main_impl.h" - -static void test_exhaustive_ellswift(const secp256k1_context *ctx, const secp256k1_ge *group) { - int i; - - /* Note that SwiftEC/ElligatorSwift are inherently curve operations, not - * group operations, and this test only checks the curve points which are in - * a tiny subgroup. In that sense it can't be really seen as exhaustive as - * it doesn't (and for computational reasons obviously cannot) test the - * entire domain ellswift operates under. */ - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - secp256k1_scalar scalar_i; - unsigned char sec32[32]; - unsigned char ell64[64]; - secp256k1_pubkey pub_decoded; - secp256k1_ge ge_decoded; - - /* Construct ellswift pubkey from exhaustive loop scalar i. */ - secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_scalar_get_b32(sec32, &scalar_i); - CHECK(secp256k1_ellswift_create(ctx, ell64, sec32, NULL)); - - /* Decode ellswift pubkey and check that it matches the precomputed group element. */ - secp256k1_ellswift_decode(ctx, &pub_decoded, ell64); - secp256k1_pubkey_load(ctx, &ge_decoded, &pub_decoded); - CHECK(secp256k1_ge_eq_var(&ge_decoded, &group[i])); - } -} - -#endif diff --git a/external/secp256k1/src/modules/ellswift/tests_impl.h b/external/secp256k1/src/modules/ellswift/tests_impl.h deleted file mode 100644 index 3c314c9b50..0000000000 --- a/external/secp256k1/src/modules/ellswift/tests_impl.h +++ /dev/null @@ -1,436 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_ELLSWIFT_TESTS_H -#define SECP256K1_MODULE_ELLSWIFT_TESTS_H - -#include "../../../include/secp256k1_ellswift.h" - -struct ellswift_xswiftec_inv_test { - int enc_bitmap; - secp256k1_fe u; - secp256k1_fe x; - secp256k1_fe encs[8]; -}; - -struct ellswift_decode_test { - unsigned char enc[64]; - secp256k1_fe x; - int odd_y; -}; - -struct ellswift_xdh_test { - unsigned char priv_ours[32]; - unsigned char ellswift_ours[64]; - unsigned char ellswift_theirs[64]; - int initiating; - unsigned char shared_secret[32]; -}; - -/* Set of (point, encodings) test vectors, selected to maximize branch coverage, part of the BIP324 - * test vectors. Created using an independent implementation, and tested decoding against paper - * authors' code. */ -static const struct ellswift_xswiftec_inv_test ellswift_xswiftec_inv_tests[] = { - {0xcc, SECP256K1_FE_CONST(0x05ff6bda, 0xd900fc32, 0x61bc7fe3, 0x4e2fb0f5, 0x69f06e09, 0x1ae437d3, 0xa52e9da0, 0xcbfb9590), SECP256K1_FE_CONST(0x80cdf637, 0x74ec7022, 0xc89a5a85, 0x58e373a2, 0x79170285, 0xe0ab2741, 0x2dbce510, 0xbdfe23fc), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x45654798, 0xece071ba, 0x79286d04, 0xf7f3eb1c, 0x3f1d17dd, 0x883610f2, 0xad2efd82, 0xa287466b), SECP256K1_FE_CONST(0x0aeaa886, 0xf6b76c71, 0x58452418, 0xcbf5033a, 0xdc5747e9, 0xe9b5d3b2, 0x303db969, 0x36528557), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xba9ab867, 0x131f8e45, 0x86d792fb, 0x080c14e3, 0xc0e2e822, 0x77c9ef0d, 0x52d1027c, 0x5d78b5c4), SECP256K1_FE_CONST(0xf5155779, 0x0948938e, 0xa7badbe7, 0x340afcc5, 0x23a8b816, 0x164a2c4d, 0xcfc24695, 0xc9ad76d8)}}, - {0x33, SECP256K1_FE_CONST(0x1737a85f, 0x4c8d146c, 0xec96e3ff, 0xdca76d99, 0x03dcf3bd, 0x53061868, 0xd478c78c, 0x63c2aa9e), SECP256K1_FE_CONST(0x39e48dd1, 0x50d2f429, 0xbe088dfd, 0x5b61882e, 0x7e840748, 0x3702ae9a, 0x5ab35927, 0xb15f85ea), {SECP256K1_FE_CONST(0x1be8cc0b, 0x04be0c68, 0x1d0c6a68, 0xf733f82c, 0x6c896e0c, 0x8a262fcd, 0x392918e3, 0x03a7abf4), SECP256K1_FE_CONST(0x605b5814, 0xbf9b8cb0, 0x66667c9e, 0x5480d22d, 0xc5b6c92f, 0x14b4af3e, 0xe0a9eb83, 0xb03685e3), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xe41733f4, 0xfb41f397, 0xe2f39597, 0x08cc07d3, 0x937691f3, 0x75d9d032, 0xc6d6e71b, 0xfc58503b), SECP256K1_FE_CONST(0x9fa4a7eb, 0x4064734f, 0x99998361, 0xab7f2dd2, 0x3a4936d0, 0xeb4b50c1, 0x1f56147b, 0x4fc9764c), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x00, SECP256K1_FE_CONST(0x1aaa1cce, 0xbf9c7241, 0x91033df3, 0x66b36f69, 0x1c4d902c, 0x228033ff, 0x4516d122, 0xb2564f68), SECP256K1_FE_CONST(0xc7554125, 0x9d3ba98f, 0x207eaa30, 0xc69634d1, 0x87d0b6da, 0x594e719e, 0x420f4898, 0x638fc5b0), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x33, SECP256K1_FE_CONST(0x2323a1d0, 0x79b0fd72, 0xfc8bb62e, 0xc34230a8, 0x15cb0596, 0xc2bfac99, 0x8bd6b842, 0x60f5dc26), SECP256K1_FE_CONST(0x239342df, 0xb675500a, 0x34a19631, 0x0b8d87d5, 0x4f49dcac, 0x9da50c17, 0x43ceab41, 0xa7b249ff), {SECP256K1_FE_CONST(0xf63580b8, 0xaa49c484, 0x6de56e39, 0xe1b3e73f, 0x171e881e, 0xba8c66f6, 0x14e67e5c, 0x975dfc07), SECP256K1_FE_CONST(0xb6307b33, 0x2e699f1c, 0xf77841d9, 0x0af25365, 0x404deb7f, 0xed5edb30, 0x90db49e6, 0x42a156b6), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x09ca7f47, 0x55b63b7b, 0x921a91c6, 0x1e4c18c0, 0xe8e177e1, 0x45739909, 0xeb1981a2, 0x68a20028), SECP256K1_FE_CONST(0x49cf84cc, 0xd19660e3, 0x0887be26, 0xf50dac9a, 0xbfb21480, 0x12a124cf, 0x6f24b618, 0xbd5ea579), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x33, SECP256K1_FE_CONST(0x2dc90e64, 0x0cb646ae, 0x9164c0b5, 0xa9ef0169, 0xfebe34dc, 0x4437d6e4, 0x6acb0e27, 0xe219d1e8), SECP256K1_FE_CONST(0xd236f19b, 0xf349b951, 0x6e9b3f4a, 0x5610fe96, 0x0141cb23, 0xbbc8291b, 0x9534f1d7, 0x1de62a47), {SECP256K1_FE_CONST(0xe69df7d9, 0xc026c366, 0x00ebdf58, 0x80726758, 0x47c0c431, 0xc8eb7306, 0x82533e96, 0x4b6252c9), SECP256K1_FE_CONST(0x4f18bbdf, 0x7c2d6c5f, 0x818c1880, 0x2fa35cd0, 0x69eaa79f, 0xff74e4fc, 0x837c80d9, 0x3fece2f8), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x19620826, 0x3fd93c99, 0xff1420a7, 0x7f8d98a7, 0xb83f3bce, 0x37148cf9, 0x7dacc168, 0xb49da966), SECP256K1_FE_CONST(0xb0e74420, 0x83d293a0, 0x7e73e77f, 0xd05ca32f, 0x96155860, 0x008b1b03, 0x7c837f25, 0xc0131937), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0xcc, SECP256K1_FE_CONST(0x3edd7b39, 0x80e2f2f3, 0x4d1409a2, 0x07069f88, 0x1fda5f96, 0xf08027ac, 0x4465b63d, 0xc278d672), SECP256K1_FE_CONST(0x053a98de, 0x4a27b196, 0x1155822b, 0x3a3121f0, 0x3b2a1445, 0x8bd80eb4, 0xa560c4c7, 0xa85c149c), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xb3dae4b7, 0xdcf858e4, 0xc6968057, 0xcef2b156, 0x46543152, 0x6538199c, 0xf52dc1b2, 0xd62fda30), SECP256K1_FE_CONST(0x4aa77dd5, 0x5d6b6d3c, 0xfa10cc9d, 0x0fe42f79, 0x232e4575, 0x661049ae, 0x36779c1d, 0x0c666d88), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x4c251b48, 0x2307a71b, 0x39697fa8, 0x310d4ea9, 0xb9abcead, 0x9ac7e663, 0x0ad23e4c, 0x29d021ff), SECP256K1_FE_CONST(0xb558822a, 0xa29492c3, 0x05ef3362, 0xf01bd086, 0xdcd1ba8a, 0x99efb651, 0xc98863e1, 0xf3998ea7)}}, - {0x00, SECP256K1_FE_CONST(0x4295737e, 0xfcb1da6f, 0xb1d96b9c, 0xa7dcd1e3, 0x20024b37, 0xa736c494, 0x8b625981, 0x73069f70), SECP256K1_FE_CONST(0xfa7ffe4f, 0x25f88362, 0x831c087a, 0xfe2e8a9b, 0x0713e2ca, 0xc1ddca6a, 0x383205a2, 0x66f14307), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0xff, SECP256K1_FE_CONST(0x587c1a0c, 0xee91939e, 0x7f784d23, 0xb963004a, 0x3bf44f5d, 0x4e32a008, 0x1995ba20, 0xb0fca59e), SECP256K1_FE_CONST(0x2ea98853, 0x0715e8d1, 0x0363907f, 0xf2512452, 0x4d471ba2, 0x454d5ce3, 0xbe3f0419, 0x4dfd3a3c), {SECP256K1_FE_CONST(0xcfd5a094, 0xaa0b9b88, 0x91b76c6a, 0xb9438f66, 0xaa1c095a, 0x65f9f701, 0x35e81712, 0x92245e74), SECP256K1_FE_CONST(0xa89057d7, 0xc6563f0d, 0x6efa19ae, 0x84412b8a, 0x7b47e791, 0xa191ecdf, 0xdf2af84f, 0xd97bc339), SECP256K1_FE_CONST(0x475d0ae9, 0xef46920d, 0xf07b3411, 0x7be5a081, 0x7de1023e, 0x3cc32689, 0xe9be145b, 0x406b0aef), SECP256K1_FE_CONST(0xa0759178, 0xad802324, 0x54f827ef, 0x05ea3e72, 0xad8d7541, 0x8e6d4cc1, 0xcd4f5306, 0xc5e7c453), SECP256K1_FE_CONST(0x302a5f6b, 0x55f46477, 0x6e489395, 0x46bc7099, 0x55e3f6a5, 0x9a0608fe, 0xca17e8ec, 0x6ddb9dbb), SECP256K1_FE_CONST(0x576fa828, 0x39a9c0f2, 0x9105e651, 0x7bbed475, 0x84b8186e, 0x5e6e1320, 0x20d507af, 0x268438f6), SECP256K1_FE_CONST(0xb8a2f516, 0x10b96df2, 0x0f84cbee, 0x841a5f7e, 0x821efdc1, 0xc33cd976, 0x1641eba3, 0xbf94f140), SECP256K1_FE_CONST(0x5f8a6e87, 0x527fdcdb, 0xab07d810, 0xfa15c18d, 0x52728abe, 0x7192b33e, 0x32b0acf8, 0x3a1837dc)}}, - {0xcc, SECP256K1_FE_CONST(0x5fa88b33, 0x65a635cb, 0xbcee003c, 0xce9ef51d, 0xd1a310de, 0x277e441a, 0xbccdb7be, 0x1e4ba249), SECP256K1_FE_CONST(0x79461ff6, 0x2bfcbcac, 0x4249ba84, 0xdd040f2c, 0xec3c63f7, 0x25204dc7, 0xf464c16b, 0xf0ff3170), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x6bb700e1, 0xf4d7e236, 0xe8d193ff, 0x4a76c1b3, 0xbcd4e2b2, 0x5acac3d5, 0x1c8dac65, 0x3fe909a0), SECP256K1_FE_CONST(0xf4c73410, 0x633da7f6, 0x3a4f1d55, 0xaec6dd32, 0xc4c6d89e, 0xe74075ed, 0xb5515ed9, 0x0da9e683), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x9448ff1e, 0x0b281dc9, 0x172e6c00, 0xb5893e4c, 0x432b1d4d, 0xa5353c2a, 0xe3725399, 0xc016f28f), SECP256K1_FE_CONST(0x0b38cbef, 0x9cc25809, 0xc5b0e2aa, 0x513922cd, 0x3b392761, 0x18bf8a12, 0x4aaea125, 0xf25615ac)}}, - {0xcc, SECP256K1_FE_CONST(0x6fb31c75, 0x31f03130, 0xb42b155b, 0x952779ef, 0xbb46087d, 0xd9807d24, 0x1a48eac6, 0x3c3d96d6), SECP256K1_FE_CONST(0x56f81be7, 0x53e8d4ae, 0x4940ea6f, 0x46f6ec9f, 0xda66a6f9, 0x6cc95f50, 0x6cb2b574, 0x90e94260), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x59059774, 0x795bdb7a, 0x837fbe11, 0x40a5fa59, 0x984f48af, 0x8df95d57, 0xdd6d1c05, 0x437dcec1), SECP256K1_FE_CONST(0x22a644db, 0x79376ad4, 0xe7b3a009, 0xe58b3f13, 0x137c54fd, 0xf911122c, 0xc93667c4, 0x7077d784), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xa6fa688b, 0x86a42485, 0x7c8041ee, 0xbf5a05a6, 0x67b0b750, 0x7206a2a8, 0x2292e3f9, 0xbc822d6e), SECP256K1_FE_CONST(0xdd59bb24, 0x86c8952b, 0x184c5ff6, 0x1a74c0ec, 0xec83ab02, 0x06eeedd3, 0x36c9983a, 0x8f8824ab)}}, - {0x00, SECP256K1_FE_CONST(0x704cd226, 0xe71cb682, 0x6a590e80, 0xdac90f2d, 0x2f5830f0, 0xfdf135a3, 0xeae3965b, 0xff25ff12), SECP256K1_FE_CONST(0x138e0afa, 0x68936ee6, 0x70bd2b8d, 0xb53aedbb, 0x7bea2a85, 0x97388b24, 0xd0518edd, 0x22ad66ec), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x33, SECP256K1_FE_CONST(0x725e9147, 0x92cb8c89, 0x49e7e116, 0x8b7cdd8a, 0x8094c91c, 0x6ec2202c, 0xcd53a6a1, 0x8771edeb), SECP256K1_FE_CONST(0x8da16eb8, 0x6d347376, 0xb6181ee9, 0x74832275, 0x7f6b36e3, 0x913ddfd3, 0x32ac595d, 0x788e0e44), {SECP256K1_FE_CONST(0xdd357786, 0xb9f68733, 0x30391aa5, 0x62580965, 0x4e43116e, 0x82a5a5d8, 0x2ffd1d66, 0x24101fc4), SECP256K1_FE_CONST(0xa0b7efca, 0x01814594, 0xc59c9aae, 0x8e497001, 0x86ca5d95, 0xe88bcc80, 0x399044d9, 0xc2d8613d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x22ca8879, 0x460978cc, 0xcfc6e55a, 0x9da7f69a, 0xb1bcee91, 0x7d5a5a27, 0xd002e298, 0xdbefdc6b), SECP256K1_FE_CONST(0x5f481035, 0xfe7eba6b, 0x3a636551, 0x71b68ffe, 0x7935a26a, 0x1774337f, 0xc66fbb25, 0x3d279af2), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x00, SECP256K1_FE_CONST(0x78fe6b71, 0x7f2ea4a3, 0x2708d79c, 0x151bf503, 0xa5312a18, 0xc0963437, 0xe865cc6e, 0xd3f6ae97), SECP256K1_FE_CONST(0x8701948e, 0x80d15b5c, 0xd8f72863, 0xeae40afc, 0x5aced5e7, 0x3f69cbc8, 0x179a3390, 0x2c094d98), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x44, SECP256K1_FE_CONST(0x7c37bb9c, 0x5061dc07, 0x413f11ac, 0xd5a34006, 0xe64c5c45, 0x7fdb9a43, 0x8f217255, 0xa961f50d), SECP256K1_FE_CONST(0x5c1a76b4, 0x4568eb59, 0xd6789a74, 0x42d9ed7c, 0xdc6226b7, 0x752b4ff8, 0xeaf8e1a9, 0x5736e507), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xb94d30cd, 0x7dbff60b, 0x64620c17, 0xca0fafaa, 0x40b3d1f5, 0x2d077a60, 0xa2e0cafd, 0x145086c2), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x46b2cf32, 0x824009f4, 0x9b9df3e8, 0x35f05055, 0xbf4c2e0a, 0xd2f8859f, 0x5d1f3501, 0xebaf756d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x00, SECP256K1_FE_CONST(0x82388888, 0x967f82a6, 0xb444438a, 0x7d44838e, 0x13c0d478, 0xb9ca060d, 0xa95a41fb, 0x94303de6), SECP256K1_FE_CONST(0x29e96541, 0x70628fec, 0x8b497289, 0x8b113cf9, 0x8807f460, 0x9274f4f3, 0x140d0674, 0x157c90a0), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x33, SECP256K1_FE_CONST(0x91298f57, 0x70af7a27, 0xf0a47188, 0xd24c3b7b, 0xf98ab299, 0x0d84b0b8, 0x98507e3c, 0x561d6472), SECP256K1_FE_CONST(0x144f4ccb, 0xd9a74698, 0xa88cbf6f, 0xd00ad886, 0xd339d29e, 0xa19448f2, 0xc572cac0, 0xa07d5562), {SECP256K1_FE_CONST(0xe6a0ffa3, 0x807f09da, 0xdbe71e0f, 0x4be4725f, 0x2832e76c, 0xad8dc1d9, 0x43ce8393, 0x75eff248), SECP256K1_FE_CONST(0x837b8e68, 0xd4917544, 0x764ad090, 0x3cb11f86, 0x15d2823c, 0xefbb06d8, 0x9049dbab, 0xc69befda), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x195f005c, 0x7f80f625, 0x2418e1f0, 0xb41b8da0, 0xd7cd1893, 0x52723e26, 0xbc317c6b, 0x8a1009e7), SECP256K1_FE_CONST(0x7c847197, 0x2b6e8abb, 0x89b52f6f, 0xc34ee079, 0xea2d7dc3, 0x1044f927, 0x6fb62453, 0x39640c55), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x00, SECP256K1_FE_CONST(0xb682f3d0, 0x3bbb5dee, 0x4f54b5eb, 0xfba931b4, 0xf52f6a19, 0x1e5c2f48, 0x3c73c66e, 0x9ace97e1), SECP256K1_FE_CONST(0x904717bf, 0x0bc0cb78, 0x73fcdc38, 0xaa97f19e, 0x3a626309, 0x72acff92, 0xb24cc6dd, 0xa197cb96), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x77, SECP256K1_FE_CONST(0xc17ec69e, 0x665f0fb0, 0xdbab48d9, 0xc2f94d12, 0xec8a9d7e, 0xacb58084, 0x83309180, 0x1eb0b80b), SECP256K1_FE_CONST(0x147756e6, 0x6d96e31c, 0x426d3cc8, 0x5ed0c4cf, 0xbef6341d, 0xd8b28558, 0x5aa574ea, 0x0204b55e), {SECP256K1_FE_CONST(0x6f4aea43, 0x1a0043bd, 0xd03134d6, 0xd9159119, 0xce034b88, 0xc32e50e8, 0xe36c4ee4, 0x5eac7ae9), SECP256K1_FE_CONST(0xfd5be16d, 0x4ffa2690, 0x126c67c3, 0xef7cb9d2, 0x9b74d397, 0xc78b06b3, 0x605fda34, 0xdc9696a6), SECP256K1_FE_CONST(0x5e9c6079, 0x2a2f000e, 0x45c6250f, 0x296f875e, 0x174efc0e, 0x9703e628, 0x706103a9, 0xdd2d82c7), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x90b515bc, 0xe5ffbc42, 0x2fcecb29, 0x26ea6ee6, 0x31fcb477, 0x3cd1af17, 0x1c93b11a, 0xa1538146), SECP256K1_FE_CONST(0x02a41e92, 0xb005d96f, 0xed93983c, 0x1083462d, 0x648b2c68, 0x3874f94c, 0x9fa025ca, 0x23696589), SECP256K1_FE_CONST(0xa1639f86, 0xd5d0fff1, 0xba39daf0, 0xd69078a1, 0xe8b103f1, 0x68fc19d7, 0x8f9efc55, 0x22d27968), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0xcc, SECP256K1_FE_CONST(0xc25172fc, 0x3f29b6fc, 0x4a1155b8, 0x57523315, 0x5486b274, 0x64b74b8b, 0x260b499a, 0x3f53cb14), SECP256K1_FE_CONST(0x1ea9cbdb, 0x35cf6e03, 0x29aa31b0, 0xbb0a702a, 0x65123ed0, 0x08655a93, 0xb7dcd528, 0x0e52e1ab), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x7422edc7, 0x843136af, 0x0053bb88, 0x54448a82, 0x99994f9d, 0xdcefd3a9, 0xa92d4546, 0x2c59298a), SECP256K1_FE_CONST(0x78c7774a, 0x266f8b97, 0xea23d05d, 0x064f033c, 0x77319f92, 0x3f6b78bc, 0xe4e20bf0, 0x5fa5398d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x8bdd1238, 0x7bcec950, 0xffac4477, 0xabbb757d, 0x6666b062, 0x23102c56, 0x56d2bab8, 0xd3a6d2a5), SECP256K1_FE_CONST(0x873888b5, 0xd9907468, 0x15dc2fa2, 0xf9b0fcc3, 0x88ce606d, 0xc0948743, 0x1b1df40e, 0xa05ac2a2)}}, - {0x00, SECP256K1_FE_CONST(0xcab6626f, 0x832a4b12, 0x80ba7add, 0x2fc5322f, 0xf011caed, 0xedf7ff4d, 0xb6735d50, 0x26dc0367), SECP256K1_FE_CONST(0x2b2bef08, 0x52c6f7c9, 0x5d72ac99, 0xa23802b8, 0x75029cd5, 0x73b248d1, 0xf1b3fc80, 0x33788eb6), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x33, SECP256K1_FE_CONST(0xd8621b4f, 0xfc85b9ed, 0x56e99d8d, 0xd1dd24ae, 0xdcecb147, 0x63b861a1, 0x7112dc77, 0x1a104fd2), SECP256K1_FE_CONST(0x812cabe9, 0x72a22aa6, 0x7c7da0c9, 0x4d8a9362, 0x96eb9949, 0xd70c37cb, 0x2b248757, 0x4cb3ce58), {SECP256K1_FE_CONST(0xfbc5febc, 0x6fdbc9ae, 0x3eb88a93, 0xb982196e, 0x8b6275a6, 0xd5a73c17, 0x387e000c, 0x711bd0e3), SECP256K1_FE_CONST(0x8724c96b, 0xd4e5527f, 0x2dd195a5, 0x1c468d2d, 0x211ba2fa, 0xc7cbe0b4, 0xb3434253, 0x409fb42d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x043a0143, 0x90243651, 0xc147756c, 0x467de691, 0x749d8a59, 0x2a58c3e8, 0xc781fff2, 0x8ee42b4c), SECP256K1_FE_CONST(0x78db3694, 0x2b1aad80, 0xd22e6a5a, 0xe3b972d2, 0xdee45d05, 0x38341f4b, 0x4cbcbdab, 0xbf604802), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x00, SECP256K1_FE_CONST(0xda463164, 0xc6f4bf71, 0x29ee5f0e, 0xc00f65a6, 0x75a8adf1, 0xbd931b39, 0xb64806af, 0xdcda9a22), SECP256K1_FE_CONST(0x25b9ce9b, 0x390b408e, 0xd611a0f1, 0x3ff09a59, 0x8a57520e, 0x426ce4c6, 0x49b7f94f, 0x2325620d), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0xcc, SECP256K1_FE_CONST(0xdafc971e, 0x4a3a7b6d, 0xcfb42a08, 0xd9692d82, 0xad9e7838, 0x523fcbda, 0x1d4827e1, 0x4481ae2d), SECP256K1_FE_CONST(0x250368e1, 0xb5c58492, 0x304bd5f7, 0x2696d27d, 0x526187c7, 0xadc03425, 0xe2b7d81d, 0xbb7e4e02), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x370c28f1, 0xbe665efa, 0xcde6aa43, 0x6bf86fe2, 0x1e6e314c, 0x1e53dd04, 0x0e6c73a4, 0x6b4c8c49), SECP256K1_FE_CONST(0xcd8acee9, 0x8ffe5653, 0x1a84d7eb, 0x3e48fa40, 0x34206ce8, 0x25ace907, 0xd0edf0ea, 0xeb5e9ca2), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xc8f3d70e, 0x4199a105, 0x321955bc, 0x9407901d, 0xe191ceb3, 0xe1ac22fb, 0xf1938c5a, 0x94b36fe6), SECP256K1_FE_CONST(0x32753116, 0x7001a9ac, 0xe57b2814, 0xc1b705bf, 0xcbdf9317, 0xda5316f8, 0x2f120f14, 0x14a15f8d)}}, - {0x44, SECP256K1_FE_CONST(0xe0294c8b, 0xc1a36b41, 0x66ee92bf, 0xa70a5c34, 0x976fa982, 0x9405efea, 0x8f9cd54d, 0xcb29b99e), SECP256K1_FE_CONST(0xae9690d1, 0x3b8d20a0, 0xfbbf37be, 0xd8474f67, 0xa04e142f, 0x56efd787, 0x70a76b35, 0x9165d8a1), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xdcd45d93, 0x5613916a, 0xf167b029, 0x058ba3a7, 0x00d37150, 0xb9df3472, 0x8cb05412, 0xc16d4182), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x232ba26c, 0xa9ec6e95, 0x0e984fd6, 0xfa745c58, 0xff2c8eaf, 0x4620cb8d, 0x734fabec, 0x3e92baad), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0x00, SECP256K1_FE_CONST(0xe148441c, 0xd7b92b8b, 0x0e4fa3bd, 0x68712cfd, 0x0d709ad1, 0x98cace61, 0x1493c10e, 0x97f5394e), SECP256K1_FE_CONST(0x164a6397, 0x94d74c53, 0xafc4d329, 0x4e79cdb3, 0xcd25f99f, 0x6df45c00, 0x0f758aba, 0x54d699c0), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0xff, SECP256K1_FE_CONST(0xe4b00ec9, 0x7aadcca9, 0x7644d3b0, 0xc8a931b1, 0x4ce7bcf7, 0xbc877954, 0x6d6e35aa, 0x5937381c), SECP256K1_FE_CONST(0x94e9588d, 0x41647b3f, 0xcc772dc8, 0xd83c67ce, 0x3be00353, 0x8517c834, 0x103d2cd4, 0x9d62ef4d), {SECP256K1_FE_CONST(0xc88d25f4, 0x1407376b, 0xb2c03a7f, 0xffeb3ec7, 0x811cc434, 0x91a0c3aa, 0xc0378cdc, 0x78357bee), SECP256K1_FE_CONST(0x51c02636, 0xce00c234, 0x5ecd89ad, 0xb6089fe4, 0xd5e18ac9, 0x24e3145e, 0x6669501c, 0xd37a00d4), SECP256K1_FE_CONST(0x205b3512, 0xdb40521c, 0xb200952e, 0x67b46f67, 0xe09e7839, 0xe0de4400, 0x4138329e, 0xbd9138c5), SECP256K1_FE_CONST(0x58aab390, 0xab6fb55c, 0x1d1b8089, 0x7a207ce9, 0x4a78fa5b, 0x4aa61a33, 0x398bcae9, 0xadb20d3e), SECP256K1_FE_CONST(0x3772da0b, 0xebf8c894, 0x4d3fc580, 0x0014c138, 0x7ee33bcb, 0x6e5f3c55, 0x3fc87322, 0x87ca8041), SECP256K1_FE_CONST(0xae3fd9c9, 0x31ff3dcb, 0xa1327652, 0x49f7601b, 0x2a1e7536, 0xdb1ceba1, 0x9996afe2, 0x2c85fb5b), SECP256K1_FE_CONST(0xdfa4caed, 0x24bfade3, 0x4dff6ad1, 0x984b9098, 0x1f6187c6, 0x1f21bbff, 0xbec7cd60, 0x426ec36a), SECP256K1_FE_CONST(0xa7554c6f, 0x54904aa3, 0xe2e47f76, 0x85df8316, 0xb58705a4, 0xb559e5cc, 0xc6743515, 0x524deef1)}}, - {0x00, SECP256K1_FE_CONST(0xe5bbb9ef, 0x360d0a50, 0x1618f006, 0x7d36dceb, 0x75f5be9a, 0x620232aa, 0x9fd5139d, 0x0863fde5), SECP256K1_FE_CONST(0xe5bbb9ef, 0x360d0a50, 0x1618f006, 0x7d36dceb, 0x75f5be9a, 0x620232aa, 0x9fd5139d, 0x0863fde5), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0xff, SECP256K1_FE_CONST(0xe6bcb5c3, 0xd63467d4, 0x90bfa54f, 0xbbc6092a, 0x7248c25e, 0x11b248dc, 0x2964a6e1, 0x5edb1457), SECP256K1_FE_CONST(0x19434a3c, 0x29cb982b, 0x6f405ab0, 0x4439f6d5, 0x8db73da1, 0xee4db723, 0xd69b591d, 0xa124e7d8), {SECP256K1_FE_CONST(0x67119877, 0x832ab8f4, 0x59a82165, 0x6d8261f5, 0x44a553b8, 0x9ae4f25c, 0x52a97134, 0xb70f3426), SECP256K1_FE_CONST(0xffee02f5, 0xe649c07f, 0x0560eff1, 0x867ec7b3, 0x2d0e595e, 0x9b1c0ea6, 0xe2a4fc70, 0xc97cd71f), SECP256K1_FE_CONST(0xb5e0c189, 0xeb5b4bac, 0xd025b744, 0x4d74178b, 0xe8d5246c, 0xfa4a9a20, 0x7964a057, 0xee969992), SECP256K1_FE_CONST(0x5746e459, 0x1bf7f4c3, 0x044609ea, 0x372e9086, 0x03975d27, 0x9fdef834, 0x9f0b08d3, 0x2f07619d), SECP256K1_FE_CONST(0x98ee6788, 0x7cd5470b, 0xa657de9a, 0x927d9e0a, 0xbb5aac47, 0x651b0da3, 0xad568eca, 0x48f0c809), SECP256K1_FE_CONST(0x0011fd0a, 0x19b63f80, 0xfa9f100e, 0x7981384c, 0xd2f1a6a1, 0x64e3f159, 0x1d5b038e, 0x36832510), SECP256K1_FE_CONST(0x4a1f3e76, 0x14a4b453, 0x2fda48bb, 0xb28be874, 0x172adb93, 0x05b565df, 0x869b5fa7, 0x1169629d), SECP256K1_FE_CONST(0xa8b91ba6, 0xe4080b3c, 0xfbb9f615, 0xc8d16f79, 0xfc68a2d8, 0x602107cb, 0x60f4f72b, 0xd0f89a92)}}, - {0x33, SECP256K1_FE_CONST(0xf28fba64, 0xaf766845, 0xeb2f4302, 0x456e2b9f, 0x8d80affe, 0x57e7aae4, 0x2738d7cd, 0xdb1c2ce6), SECP256K1_FE_CONST(0xf28fba64, 0xaf766845, 0xeb2f4302, 0x456e2b9f, 0x8d80affe, 0x57e7aae4, 0x2738d7cd, 0xdb1c2ce6), {SECP256K1_FE_CONST(0x4f867ad8, 0xbb3d8404, 0x09d26b67, 0x307e6210, 0x0153273f, 0x72fa4b74, 0x84becfa1, 0x4ebe7408), SECP256K1_FE_CONST(0x5bbc4f59, 0xe452cc5f, 0x22a99144, 0xb10ce898, 0x9a89a995, 0xec3cea1c, 0x91ae10e8, 0xf721bb5d), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xb0798527, 0x44c27bfb, 0xf62d9498, 0xcf819def, 0xfeacd8c0, 0x8d05b48b, 0x7b41305d, 0xb1418827), SECP256K1_FE_CONST(0xa443b0a6, 0x1bad33a0, 0xdd566ebb, 0x4ef31767, 0x6576566a, 0x13c315e3, 0x6e51ef16, 0x08de40d2), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, - {0xcc, SECP256K1_FE_CONST(0xf455605b, 0xc85bf48e, 0x3a908c31, 0x023faf98, 0x381504c6, 0xc6d3aeb9, 0xede55f8d, 0xd528924d), SECP256K1_FE_CONST(0xd31fbcd5, 0xcdb798f6, 0xc00db669, 0x2f8fe896, 0x7fa9c79d, 0xd10958f4, 0xa194f013, 0x74905e99), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0x0c00c571, 0x5b56fe63, 0x2d814ad8, 0xa77f8e66, 0x628ea47a, 0x6116834f, 0x8c1218f3, 0xa03cbd50), SECP256K1_FE_CONST(0xdf88e44f, 0xac84fa52, 0xdf4d59f4, 0x8819f18f, 0x6a8cd415, 0x1d162afa, 0xf773166f, 0x57c7ff46), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0xf3ff3a8e, 0xa4a9019c, 0xd27eb527, 0x58807199, 0x9d715b85, 0x9ee97cb0, 0x73ede70b, 0x5fc33edf), SECP256K1_FE_CONST(0x20771bb0, 0x537b05ad, 0x20b2a60b, 0x77e60e70, 0x95732bea, 0xe2e9d505, 0x088ce98f, 0xa837fce9)}}, - {0xff, SECP256K1_FE_CONST(0xf58cd4d9, 0x830bad32, 0x2699035e, 0x8246007d, 0x4be27e19, 0xb6f53621, 0x317b4f30, 0x9b3daa9d), SECP256K1_FE_CONST(0x78ec2b3d, 0xc0948de5, 0x60148bbc, 0x7c6dc963, 0x3ad5df70, 0xa5a5750c, 0xbed72180, 0x4f082a3b), {SECP256K1_FE_CONST(0x6c4c580b, 0x76c75940, 0x43569f9d, 0xae16dc28, 0x01c16a1f, 0xbe128608, 0x81b75f8e, 0xf929bce5), SECP256K1_FE_CONST(0x94231355, 0xe7385c5f, 0x25ca436a, 0xa6419147, 0x1aea4393, 0xd6e86ab7, 0xa35fe2af, 0xacaefd0d), SECP256K1_FE_CONST(0xdff2a195, 0x1ada6db5, 0x74df8340, 0x48149da3, 0x397a75b8, 0x29abf58c, 0x7e69db1b, 0x41ac0989), SECP256K1_FE_CONST(0xa52b66d3, 0xc9070355, 0x48028bf8, 0x04711bf4, 0x22aba95f, 0x1a666fc8, 0x6f4648e0, 0x5f29caae), SECP256K1_FE_CONST(0x93b3a7f4, 0x8938a6bf, 0xbca96062, 0x51e923d7, 0xfe3e95e0, 0x41ed79f7, 0x7e48a070, 0x06d63f4a), SECP256K1_FE_CONST(0x6bdcecaa, 0x18c7a3a0, 0xda35bc95, 0x59be6eb8, 0xe515bc6c, 0x29179548, 0x5ca01d4f, 0x5350ff22), SECP256K1_FE_CONST(0x200d5e6a, 0xe525924a, 0x8b207cbf, 0xb7eb625c, 0xc6858a47, 0xd6540a73, 0x819624e3, 0xbe53f2a6), SECP256K1_FE_CONST(0x5ad4992c, 0x36f8fcaa, 0xb7fd7407, 0xfb8ee40b, 0xdd5456a0, 0xe5999037, 0x90b9b71e, 0xa0d63181)}}, - {0x00, SECP256K1_FE_CONST(0xfd7d912a, 0x40f182a3, 0x588800d6, 0x9ebfb504, 0x8766da20, 0x6fd7ebc8, 0xd2436c81, 0xcbef6421), SECP256K1_FE_CONST(0x8d37c862, 0x054debe7, 0x31694536, 0xff46b273, 0xec122b35, 0xa9bf1445, 0xac3c4ff9, 0xf262c952), {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}}, -}; - -/* Set of (encoding, xcoord) test vectors, selected to maximize branch coverage, part of the BIP324 - * test vectors. Created using an independent implementation, and tested decoding against the paper - * authors' code. */ -static const struct ellswift_decode_test ellswift_decode_tests[] = { - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c), 0}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x47, 0x5b, 0xf7, 0x65, 0x5b, 0x0f, 0xb2, 0xd8, 0x52, 0x92, 0x10, 0x35, 0xb2, 0xef, 0x60, 0x7f, 0x49, 0x06, 0x9b, 0x97, 0x45, 0x4e, 0x67, 0x95, 0x25, 0x10, 0x62, 0x74, 0x17, 0x71}, SECP256K1_FE_CONST(0xb5da00b7, 0x3cd65605, 0x20e7c364, 0x086e7cd2, 0x3a34bf60, 0xd0e707be, 0x9fc34d4c, 0xd5fdfa2c), 1}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x27, 0x7c, 0x4a, 0x71, 0xf9, 0xd2, 0x2e, 0x66, 0xec, 0xe5, 0x23, 0xf8, 0xfa, 0x08, 0x74, 0x1a, 0x7c, 0x09, 0x12, 0xc6, 0x6a, 0x69, 0xce, 0x68, 0x51, 0x4b, 0xfd, 0x35, 0x15, 0xb4, 0x9f}, SECP256K1_FE_CONST(0xf482f2e2, 0x41753ad0, 0xfb89150d, 0x8491dc1e, 0x34ff0b8a, 0xcfbb442c, 0xfe999e2e, 0x5e6fd1d2), 1}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x21, 0xcc, 0x93, 0x0e, 0x77, 0xc9, 0xf5, 0x14, 0xb6, 0x91, 0x5c, 0x3d, 0xbe, 0x2a, 0x94, 0xc6, 0xd8, 0xf6, 0x90, 0xb5, 0xb7, 0x39, 0x86, 0x4b, 0xa6, 0x78, 0x9f, 0xb8, 0xa5, 0x5d, 0xd0}, SECP256K1_FE_CONST(0x9f59c402, 0x75f5085a, 0x006f05da, 0xe77eb98c, 0x6fd0db1a, 0xb4a72ac4, 0x7eae90a4, 0xfc9e57e0), 0}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41}, SECP256K1_FE_CONST(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaa9, 0xfffffd6b), 1}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x9c, 0x18, 0x2d, 0x27, 0x59, 0xcd, 0x99, 0x82, 0x42, 0x28, 0xd9, 0x47, 0x99, 0xf8, 0xc6, 0x55, 0x7c, 0x38, 0xa1, 0xc0, 0xd6, 0x77, 0x9b, 0x9d, 0x4b, 0x72, 0x9c, 0x6f, 0x1c, 0xcc, 0x42}, SECP256K1_FE_CONST(0x70720db7, 0xe238d041, 0x21f5b1af, 0xd8cc5ad9, 0xd18944c6, 0xbdc94881, 0xf502b7a3, 0xaf3aecff), 0}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c), 0}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x64, 0xbb, 0xd5}, SECP256K1_FE_CONST(0x50873db3, 0x1badcc71, 0x890e4f67, 0x753a6575, 0x7f97aaa7, 0xdd5f1e82, 0xb753ace3, 0x2219064b), 0}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x28, 0xde, 0x7d}, SECP256K1_FE_CONST(0x1eea9cc5, 0x9cfcf2fa, 0x151ac6c2, 0x74eea411, 0x0feb4f7b, 0x68c59657, 0x32e9992e, 0x976ef68e), 0}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xcf, 0xb7, 0xe7}, SECP256K1_FE_CONST(0x12303941, 0xaedc2088, 0x80735b1f, 0x1795c8e5, 0x5be520ea, 0x93e10335, 0x7b5d2adb, 0x7ed59b8e), 0}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x11, 0x3a, 0xd9}, SECP256K1_FE_CONST(0x7eed6b70, 0xe7b0767c, 0x7d7feac0, 0x4e57aa2a, 0x12fef5e0, 0xf48f878f, 0xcbb88b3b, 0x6b5e0783), 0}, - {{0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x532167c1, 0x1200b08c, 0x0e84a354, 0xe74dcc40, 0xf8b25f4f, 0xe686e308, 0x69526366, 0x278a0688), 0}, - {{0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x532167c1, 0x1200b08c, 0x0e84a354, 0xe74dcc40, 0xf8b25f4f, 0xe686e308, 0x69526366, 0x278a0688), 0}, - {{0x0f, 0xfd, 0xe9, 0xca, 0x81, 0xd7, 0x51, 0xe9, 0xcd, 0xaf, 0xfc, 0x1a, 0x50, 0x77, 0x92, 0x45, 0x32, 0x0b, 0x28, 0x99, 0x6d, 0xba, 0xf3, 0x2f, 0x82, 0x2f, 0x20, 0x11, 0x7c, 0x22, 0xfb, 0xd6, 0xc7, 0x4d, 0x99, 0xef, 0xce, 0xaa, 0x55, 0x0f, 0x1a, 0xd1, 0xc0, 0xf4, 0x3f, 0x46, 0xe7, 0xff, 0x1e, 0xe3, 0xbd, 0x01, 0x62, 0xb7, 0xbf, 0x55, 0xf2, 0x96, 0x5d, 0xa9, 0xc3, 0x45, 0x06, 0x46}, SECP256K1_FE_CONST(0x74e880b3, 0xffd18fe3, 0xcddf7902, 0x522551dd, 0xf97fa4a3, 0x5a3cfda8, 0x197f9470, 0x81a57b8f), 0}, - {{0x0f, 0xfd, 0xe9, 0xca, 0x81, 0xd7, 0x51, 0xe9, 0xcd, 0xaf, 0xfc, 0x1a, 0x50, 0x77, 0x92, 0x45, 0x32, 0x0b, 0x28, 0x99, 0x6d, 0xba, 0xf3, 0x2f, 0x82, 0x2f, 0x20, 0x11, 0x7c, 0x22, 0xfb, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x6c, 0xa8, 0x96}, SECP256K1_FE_CONST(0x377b643f, 0xce2271f6, 0x4e5c8101, 0x566107c1, 0xbe498074, 0x50917838, 0x04f65478, 0x1ac9217c), 1}, - {{0x12, 0x36, 0x58, 0x44, 0x4f, 0x32, 0xbe, 0x8f, 0x02, 0xea, 0x20, 0x34, 0xaf, 0xa7, 0xef, 0x4b, 0xbe, 0x8a, 0xdc, 0x91, 0x8c, 0xeb, 0x49, 0xb1, 0x27, 0x73, 0xb6, 0x25, 0xf4, 0x90, 0xb3, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8d, 0xc5, 0xfe, 0x11}, SECP256K1_FE_CONST(0xed16d65c, 0xf3a9538f, 0xcb2c139f, 0x1ecbc143, 0xee148271, 0x20cbc265, 0x9e667256, 0x800b8142), 0}, - {{0x14, 0x6f, 0x92, 0x46, 0x4d, 0x15, 0xd3, 0x6e, 0x35, 0x38, 0x2b, 0xd3, 0xca, 0x5b, 0x0f, 0x97, 0x6c, 0x95, 0xcb, 0x08, 0xac, 0xdc, 0xf2, 0xd5, 0xb3, 0x57, 0x06, 0x17, 0x99, 0x08, 0x39, 0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x45, 0xe9, 0x3b}, SECP256K1_FE_CONST(0x0d5cd840, 0x427f941f, 0x65193079, 0xab8e2e83, 0x024ef2ee, 0x7ca558d8, 0x8879ffd8, 0x79fb6657), 0}, - {{0x15, 0xfd, 0xf5, 0xcf, 0x09, 0xc9, 0x07, 0x59, 0xad, 0xd2, 0x27, 0x2d, 0x57, 0x4d, 0x2b, 0xb5, 0xfe, 0x14, 0x29, 0xf9, 0xf3, 0xc1, 0x4c, 0x65, 0xe3, 0x19, 0x4b, 0xf6, 0x1b, 0x82, 0xaa, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0xcf, 0xd9, 0x06}, SECP256K1_FE_CONST(0x16d0e439, 0x46aec93f, 0x62d57eb8, 0xcde68951, 0xaf136cf4, 0xb307938d, 0xd1447411, 0xe07bffe1), 1}, - {{0x1f, 0x67, 0xed, 0xf7, 0x79, 0xa8, 0xa6, 0x49, 0xd6, 0xde, 0xf6, 0x00, 0x35, 0xf2, 0xfa, 0x22, 0xd0, 0x22, 0xdd, 0x35, 0x90, 0x79, 0xa1, 0xa1, 0x44, 0x07, 0x3d, 0x84, 0xf1, 0x9b, 0x92, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x025661f9, 0xaba9d15c, 0x3118456b, 0xbe980e3e, 0x1b8ba2e0, 0x47c737a4, 0xeb48a040, 0xbb566f6c), 0}, - {{0x1f, 0x67, 0xed, 0xf7, 0x79, 0xa8, 0xa6, 0x49, 0xd6, 0xde, 0xf6, 0x00, 0x35, 0xf2, 0xfa, 0x22, 0xd0, 0x22, 0xdd, 0x35, 0x90, 0x79, 0xa1, 0xa1, 0x44, 0x07, 0x3d, 0x84, 0xf1, 0x9b, 0x92, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x025661f9, 0xaba9d15c, 0x3118456b, 0xbe980e3e, 0x1b8ba2e0, 0x47c737a4, 0xeb48a040, 0xbb566f6c), 0}, - {{0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x98bec3b2, 0xa351fa96, 0xcfd191c1, 0x77835193, 0x1b9e9ba9, 0xad1149f6, 0xd9eadca8, 0x0981b801), 0}, - {{0x40, 0x56, 0xa3, 0x4a, 0x21, 0x0e, 0xec, 0x78, 0x92, 0xe8, 0x82, 0x06, 0x75, 0xc8, 0x60, 0x09, 0x9f, 0x85, 0x7b, 0x26, 0xaa, 0xd8, 0x54, 0x70, 0xee, 0x6d, 0x3c, 0xf1, 0x30, 0x4a, 0x9d, 0xcf, 0x37, 0x5e, 0x70, 0x37, 0x42, 0x71, 0xf2, 0x0b, 0x13, 0xc9, 0x98, 0x6e, 0xd7, 0xd3, 0xc1, 0x77, 0x99, 0x69, 0x8c, 0xfc, 0x43, 0x5d, 0xbe, 0xd3, 0xa9, 0xf3, 0x4b, 0x38, 0xc8, 0x23, 0xc2, 0xb4}, SECP256K1_FE_CONST(0x868aac20, 0x03b29dbc, 0xad1a3e80, 0x3855e078, 0xa89d1654, 0x3ac64392, 0xd1224172, 0x98cec76e), 0}, - {{0x41, 0x97, 0xec, 0x37, 0x23, 0xc6, 0x54, 0xcf, 0xdd, 0x32, 0xab, 0x07, 0x55, 0x06, 0x64, 0x8b, 0x2f, 0xf5, 0x07, 0x03, 0x62, 0xd0, 0x1a, 0x4f, 0xff, 0x14, 0xb3, 0x36, 0xb7, 0x8f, 0x96, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb3, 0xab, 0x1e, 0x95}, SECP256K1_FE_CONST(0xba5a6314, 0x502a8952, 0xb8f456e0, 0x85928105, 0xf665377a, 0x8ce27726, 0xa5b0eb7e, 0xc1ac0286), 0}, - {{0x47, 0xeb, 0x3e, 0x20, 0x8f, 0xed, 0xcd, 0xf8, 0x23, 0x4c, 0x94, 0x21, 0xe9, 0xcd, 0x9a, 0x7a, 0xe8, 0x73, 0xbf, 0xbd, 0xbc, 0x39, 0x37, 0x23, 0xd1, 0xba, 0x1e, 0x1e, 0x6a, 0x8e, 0x6b, 0x24, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xd1, 0x2c, 0xb1}, SECP256K1_FE_CONST(0xd192d520, 0x07e541c9, 0x807006ed, 0x0468df77, 0xfd214af0, 0xa795fe11, 0x9359666f, 0xdcf08f7c), 0}, - {{0x5e, 0xb9, 0x69, 0x6a, 0x23, 0x36, 0xfe, 0x2c, 0x3c, 0x66, 0x6b, 0x02, 0xc7, 0x55, 0xdb, 0x4c, 0x0c, 0xfd, 0x62, 0x82, 0x5c, 0x7b, 0x58, 0x9a, 0x7b, 0x7b, 0xb4, 0x42, 0xe1, 0x41, 0xc1, 0xd6, 0x93, 0x41, 0x3f, 0x00, 0x52, 0xd4, 0x9e, 0x64, 0xab, 0xec, 0x6d, 0x58, 0x31, 0xd6, 0x6c, 0x43, 0x61, 0x28, 0x30, 0xa1, 0x7d, 0xf1, 0xfe, 0x43, 0x83, 0xdb, 0x89, 0x64, 0x68, 0x10, 0x02, 0x21}, SECP256K1_FE_CONST(0xef6e1da6, 0xd6c7627e, 0x80f7a723, 0x4cb08a02, 0x2c1ee1cf, 0x29e4d0f9, 0x642ae924, 0xcef9eb38), 1}, - {{0x7b, 0xf9, 0x6b, 0x7b, 0x6d, 0xa1, 0x5d, 0x34, 0x76, 0xa2, 0xb1, 0x95, 0x93, 0x4b, 0x69, 0x0a, 0x3a, 0x3d, 0xe3, 0xe8, 0xab, 0x84, 0x74, 0x85, 0x68, 0x63, 0xb0, 0xde, 0x3a, 0xf9, 0x0b, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x50851dfc, 0x9f418c31, 0x4a437295, 0xb24feeea, 0x27af3d0c, 0xd2308348, 0xfda6e21c, 0x463e46ff), 0}, - {{0x7b, 0xf9, 0x6b, 0x7b, 0x6d, 0xa1, 0x5d, 0x34, 0x76, 0xa2, 0xb1, 0x95, 0x93, 0x4b, 0x69, 0x0a, 0x3a, 0x3d, 0xe3, 0xe8, 0xab, 0x84, 0x74, 0x85, 0x68, 0x63, 0xb0, 0xde, 0x3a, 0xf9, 0x0b, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x50851dfc, 0x9f418c31, 0x4a437295, 0xb24feeea, 0x27af3d0c, 0xd2308348, 0xfda6e21c, 0x463e46ff), 0}, - {{0x85, 0x1b, 0x1c, 0xa9, 0x45, 0x49, 0x37, 0x1c, 0x4f, 0x1f, 0x71, 0x87, 0x32, 0x1d, 0x39, 0xbf, 0x51, 0xc6, 0xb7, 0xfb, 0x61, 0xf7, 0xcb, 0xf0, 0x27, 0xc9, 0xda, 0x62, 0x02, 0x1b, 0x7a, 0x65, 0xfc, 0x54, 0xc9, 0x68, 0x37, 0xfb, 0x22, 0xb3, 0x62, 0xed, 0xa6, 0x3e, 0xc5, 0x2e, 0xc8, 0x3d, 0x81, 0xbe, 0xdd, 0x16, 0x0c, 0x11, 0xb2, 0x2d, 0x96, 0x5d, 0x9f, 0x4a, 0x6d, 0x64, 0xd2, 0x51}, SECP256K1_FE_CONST(0x3e731051, 0xe12d3323, 0x7eb324f2, 0xaa5b16bb, 0x868eb49a, 0x1aa1fadc, 0x19b6e876, 0x1b5a5f7b), 1}, - {{0x94, 0x3c, 0x2f, 0x77, 0x51, 0x08, 0xb7, 0x37, 0xfe, 0x65, 0xa9, 0x53, 0x1e, 0x19, 0xf2, 0xfc, 0x2a, 0x19, 0x7f, 0x56, 0x03, 0xe3, 0xa2, 0x88, 0x1d, 0x1d, 0x83, 0xe4, 0x00, 0x8f, 0x91, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x311c61f0, 0xab2f32b7, 0xb1f0223f, 0xa72f0a78, 0x752b8146, 0xe46107f8, 0x876dd9c4, 0xf92b2942), 0}, - {{0x94, 0x3c, 0x2f, 0x77, 0x51, 0x08, 0xb7, 0x37, 0xfe, 0x65, 0xa9, 0x53, 0x1e, 0x19, 0xf2, 0xfc, 0x2a, 0x19, 0x7f, 0x56, 0x03, 0xe3, 0xa2, 0x88, 0x1d, 0x1d, 0x83, 0xe4, 0x00, 0x8f, 0x91, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x311c61f0, 0xab2f32b7, 0xb1f0223f, 0xa72f0a78, 0x752b8146, 0xe46107f8, 0x876dd9c4, 0xf92b2942), 0}, - {{0xa0, 0xf1, 0x84, 0x92, 0x18, 0x3e, 0x61, 0xe8, 0x06, 0x3e, 0x57, 0x36, 0x06, 0x59, 0x14, 0x21, 0xb0, 0x6b, 0xc3, 0x51, 0x36, 0x31, 0x57, 0x8a, 0x73, 0xa3, 0x9c, 0x1c, 0x33, 0x06, 0x23, 0x9f, 0x2f, 0x32, 0x90, 0x4f, 0x0d, 0x2a, 0x33, 0xec, 0xca, 0x8a, 0x54, 0x51, 0x70, 0x5b, 0xb5, 0x37, 0xd3, 0xbf, 0x44, 0xe0, 0x71, 0x22, 0x60, 0x25, 0xcd, 0xbf, 0xd2, 0x49, 0xfe, 0x0f, 0x7a, 0xd6}, SECP256K1_FE_CONST(0x97a09cf1, 0xa2eae7c4, 0x94df3c6f, 0x8a9445bf, 0xb8c09d60, 0x832f9b0b, 0x9d5eabe2, 0x5fbd14b9), 0}, - {{0xa1, 0xed, 0x0a, 0x0b, 0xd7, 0x9d, 0x8a, 0x23, 0xcf, 0xe4, 0xec, 0x5f, 0xef, 0x5b, 0xa5, 0xcc, 0xcf, 0xd8, 0x44, 0xe4, 0xff, 0x5c, 0xb4, 0xb0, 0xf2, 0xe7, 0x16, 0x27, 0x34, 0x1f, 0x1c, 0x5b, 0x17, 0xc4, 0x99, 0x24, 0x9e, 0x0a, 0xc0, 0x8d, 0x5d, 0x11, 0xea, 0x1c, 0x2c, 0x8c, 0xa7, 0x00, 0x16, 0x16, 0x55, 0x9a, 0x79, 0x94, 0xea, 0xde, 0xc9, 0xca, 0x10, 0xfb, 0x4b, 0x85, 0x16, 0xdc}, SECP256K1_FE_CONST(0x65a89640, 0x744192cd, 0xac64b2d2, 0x1ddf989c, 0xdac75007, 0x25b645be, 0xf8e2200a, 0xe39691f2), 0}, - {{0xba, 0x94, 0x59, 0x4a, 0x43, 0x27, 0x21, 0xaa, 0x35, 0x80, 0xb8, 0x4c, 0x16, 0x1d, 0x0d, 0x13, 0x4b, 0xc3, 0x54, 0xb6, 0x90, 0x40, 0x4d, 0x7c, 0xd4, 0xec, 0x57, 0xc1, 0x6d, 0x3f, 0xbe, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0x50, 0x7d, 0xd7}, SECP256K1_FE_CONST(0x5e0d7656, 0x4aae92cb, 0x347e01a6, 0x2afd389a, 0x9aa401c7, 0x6c8dd227, 0x543dc9cd, 0x0efe685a), 0}, - {{0xbc, 0xaf, 0x72, 0x19, 0xf2, 0xf6, 0xfb, 0xf5, 0x5f, 0xe5, 0xe0, 0x62, 0xdc, 0xe0, 0xe4, 0x8c, 0x18, 0xf6, 0x81, 0x03, 0xf1, 0x0b, 0x81, 0x98, 0xe9, 0x74, 0xc1, 0x84, 0x75, 0x0e, 0x1b, 0xe3, 0x93, 0x20, 0x16, 0xcb, 0xf6, 0x9c, 0x44, 0x71, 0xbd, 0x1f, 0x65, 0x6c, 0x6a, 0x10, 0x7f, 0x19, 0x73, 0xde, 0x4a, 0xf7, 0x08, 0x6d, 0xb8, 0x97, 0x27, 0x70, 0x60, 0xe2, 0x56, 0x77, 0xf1, 0x9a}, SECP256K1_FE_CONST(0x2d97f96c, 0xac882dfe, 0x73dc44db, 0x6ce0f1d3, 0x1d624135, 0x8dd5d74e, 0xb3d3b500, 0x03d24c2b), 0}, - {{0xbc, 0xaf, 0x72, 0x19, 0xf2, 0xf6, 0xfb, 0xf5, 0x5f, 0xe5, 0xe0, 0x62, 0xdc, 0xe0, 0xe4, 0x8c, 0x18, 0xf6, 0x81, 0x03, 0xf1, 0x0b, 0x81, 0x98, 0xe9, 0x74, 0xc1, 0x84, 0x75, 0x0e, 0x1b, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x65, 0x07, 0xd0, 0x9a}, SECP256K1_FE_CONST(0xe7008afe, 0x6e8cbd50, 0x55df120b, 0xd748757c, 0x686dadb4, 0x1cce75e4, 0xaddcc5e0, 0x2ec02b44), 1}, - {{0xc5, 0x98, 0x1b, 0xae, 0x27, 0xfd, 0x84, 0x40, 0x1c, 0x72, 0xa1, 0x55, 0xe5, 0x70, 0x7f, 0xbb, 0x81, 0x1b, 0x2b, 0x62, 0x06, 0x45, 0xd1, 0x02, 0x8e, 0xa2, 0x70, 0xcb, 0xe0, 0xee, 0x22, 0x5d, 0x4b, 0x62, 0xaa, 0x4d, 0xca, 0x65, 0x06, 0xc1, 0xac, 0xdb, 0xec, 0xc0, 0x55, 0x25, 0x69, 0xb4, 0xb2, 0x14, 0x36, 0xa5, 0x69, 0x2e, 0x25, 0xd9, 0x0d, 0x3b, 0xc2, 0xeb, 0x7c, 0xe2, 0x40, 0x78}, SECP256K1_FE_CONST(0x948b40e7, 0x181713bc, 0x018ec170, 0x2d3d054d, 0x15746c59, 0xa7020730, 0xdd13ecf9, 0x85a010d7), 0}, - {{0xc8, 0x94, 0xce, 0x48, 0xbf, 0xec, 0x43, 0x30, 0x14, 0xb9, 0x31, 0xa6, 0xad, 0x42, 0x26, 0xd7, 0xdb, 0xd8, 0xea, 0xa7, 0xb6, 0xe3, 0xfa, 0xa8, 0xd0, 0xef, 0x94, 0x05, 0x2b, 0xcf, 0x8c, 0xff, 0x33, 0x6e, 0xeb, 0x39, 0x19, 0xe2, 0xb4, 0xef, 0xb7, 0x46, 0xc7, 0xf7, 0x1b, 0xbc, 0xa7, 0xe9, 0x38, 0x32, 0x30, 0xfb, 0xbc, 0x48, 0xff, 0xaf, 0xe7, 0x7e, 0x8b, 0xcc, 0x69, 0x54, 0x24, 0x71}, SECP256K1_FE_CONST(0xf1c91acd, 0xc2525330, 0xf9b53158, 0x434a4d43, 0xa1c547cf, 0xf29f1550, 0x6f5da4eb, 0x4fe8fa5a), 1}, - {{0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x872d81ed, 0x8831d999, 0x8b67cb71, 0x05243edb, 0xf86c10ed, 0xfebb786c, 0x110b02d0, 0x7b2e67cd), 0}, - {{0xd9, 0x17, 0xb7, 0x86, 0xda, 0xc3, 0x56, 0x70, 0xc3, 0x30, 0xc9, 0xc5, 0xae, 0x59, 0x71, 0xdf, 0xb4, 0x95, 0xc8, 0xae, 0x52, 0x3e, 0xd9, 0x7e, 0xe2, 0x42, 0x01, 0x17, 0xb1, 0x71, 0xf4, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x20, 0x01, 0xf6, 0xf6}, SECP256K1_FE_CONST(0xe45b71e1, 0x10b831f2, 0xbdad8651, 0x994526e5, 0x8393fde4, 0x328b1ec0, 0x4d598971, 0x42584691), 1}, - {{0xe2, 0x8b, 0xd8, 0xf5, 0x92, 0x9b, 0x46, 0x7e, 0xb7, 0x0e, 0x04, 0x33, 0x23, 0x74, 0xff, 0xb7, 0xe7, 0x18, 0x02, 0x18, 0xad, 0x16, 0xea, 0xa4, 0x6b, 0x71, 0x61, 0xaa, 0x67, 0x9e, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x66b8c980, 0xa75c72e5, 0x98d383a3, 0x5a62879f, 0x844242ad, 0x1e73ff12, 0xedaa59f4, 0xe58632b5), 0}, - {{0xe2, 0x8b, 0xd8, 0xf5, 0x92, 0x9b, 0x46, 0x7e, 0xb7, 0x0e, 0x04, 0x33, 0x23, 0x74, 0xff, 0xb7, 0xe7, 0x18, 0x02, 0x18, 0xad, 0x16, 0xea, 0xa4, 0x6b, 0x71, 0x61, 0xaa, 0x67, 0x9e, 0xb4, 0x26, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x66b8c980, 0xa75c72e5, 0x98d383a3, 0x5a62879f, 0x844242ad, 0x1e73ff12, 0xedaa59f4, 0xe58632b5), 0}, - {{0xe7, 0xee, 0x58, 0x14, 0xc1, 0x70, 0x6b, 0xf8, 0xa8, 0x93, 0x96, 0xa9, 0xb0, 0x32, 0xbc, 0x01, 0x4c, 0x2c, 0xac, 0x9c, 0x12, 0x11, 0x27, 0xdb, 0xf6, 0xc9, 0x92, 0x78, 0xf8, 0xbb, 0x53, 0xd1, 0xdf, 0xd0, 0x4d, 0xbc, 0xda, 0x8e, 0x35, 0x24, 0x66, 0xb6, 0xfc, 0xd5, 0xf2, 0xde, 0xa3, 0xe1, 0x7d, 0x5e, 0x13, 0x31, 0x15, 0x88, 0x6e, 0xda, 0x20, 0xdb, 0x8a, 0x12, 0xb5, 0x4d, 0xe7, 0x1b}, SECP256K1_FE_CONST(0xe842c6e3, 0x529b2342, 0x70a5e977, 0x44edc34a, 0x04d7ba94, 0xe44b6d25, 0x23c9cf01, 0x95730a50), 1}, - {{0xf2, 0x92, 0xe4, 0x68, 0x25, 0xf9, 0x22, 0x5a, 0xd2, 0x3d, 0xc0, 0x57, 0xc1, 0xd9, 0x1c, 0x4f, 0x57, 0xfc, 0xb1, 0x38, 0x6f, 0x29, 0xef, 0x10, 0x48, 0x1c, 0xb1, 0xd2, 0x25, 0x18, 0x59, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x11, 0xc9, 0x89}, SECP256K1_FE_CONST(0x3cea2c53, 0xb8b01701, 0x66ac7da6, 0x7194694a, 0xdacc84d5, 0x6389225e, 0x330134da, 0xb85a4d55), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x01, 0xd3, 0x47, 0x5b, 0xf7, 0x65, 0x5b, 0x0f, 0xb2, 0xd8, 0x52, 0x92, 0x10, 0x35, 0xb2, 0xef, 0x60, 0x7f, 0x49, 0x06, 0x9b, 0x97, 0x45, 0x4e, 0x67, 0x95, 0x25, 0x10, 0x62, 0x74, 0x17, 0x71}, SECP256K1_FE_CONST(0xb5da00b7, 0x3cd65605, 0x20e7c364, 0x086e7cd2, 0x3a34bf60, 0xd0e707be, 0x9fc34d4c, 0xd5fdfa2c), 1}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee}, SECP256K1_FE_CONST(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaa9, 0xfffffd6b), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x82, 0x27, 0x7c, 0x4a, 0x71, 0xf9, 0xd2, 0x2e, 0x66, 0xec, 0xe5, 0x23, 0xf8, 0xfa, 0x08, 0x74, 0x1a, 0x7c, 0x09, 0x12, 0xc6, 0x6a, 0x69, 0xce, 0x68, 0x51, 0x4b, 0xfd, 0x35, 0x15, 0xb4, 0x9f}, SECP256K1_FE_CONST(0xf482f2e2, 0x41753ad0, 0xfb89150d, 0x8491dc1e, 0x34ff0b8a, 0xcfbb442c, 0xfe999e2e, 0x5e6fd1d2), 1}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x84, 0x21, 0xcc, 0x93, 0x0e, 0x77, 0xc9, 0xf5, 0x14, 0xb6, 0x91, 0x5c, 0x3d, 0xbe, 0x2a, 0x94, 0xc6, 0xd8, 0xf6, 0x90, 0xb5, 0xb7, 0x39, 0x86, 0x4b, 0xa6, 0x78, 0x9f, 0xb8, 0xa5, 0x5d, 0xd0}, SECP256K1_FE_CONST(0x9f59c402, 0x75f5085a, 0x006f05da, 0xe77eb98c, 0x6fd0db1a, 0xb4a72ac4, 0x7eae90a4, 0xfc9e57e0), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xd1, 0x9c, 0x18, 0x2d, 0x27, 0x59, 0xcd, 0x99, 0x82, 0x42, 0x28, 0xd9, 0x47, 0x99, 0xf8, 0xc6, 0x55, 0x7c, 0x38, 0xa1, 0xc0, 0xd6, 0x77, 0x9b, 0x9d, 0x4b, 0x72, 0x9c, 0x6f, 0x1c, 0xcc, 0x42}, SECP256K1_FE_CONST(0x70720db7, 0xe238d041, 0x21f5b1af, 0xd8cc5ad9, 0xd18944c6, 0xbdc94881, 0xf502b7a3, 0xaf3aecff), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0xedd1fd3e, 0x327ce90c, 0xc7a35426, 0x14289aee, 0x9682003e, 0x9cf7dcc9, 0xcf2ca974, 0x3be5aa0c), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x64, 0xbb, 0xd5}, SECP256K1_FE_CONST(0x50873db3, 0x1badcc71, 0x890e4f67, 0x753a6575, 0x7f97aaa7, 0xdd5f1e82, 0xb753ace3, 0x2219064b), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x28, 0xde, 0x7d}, SECP256K1_FE_CONST(0x1eea9cc5, 0x9cfcf2fa, 0x151ac6c2, 0x74eea411, 0x0feb4f7b, 0x68c59657, 0x32e9992e, 0x976ef68e), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xcf, 0xb7, 0xe7}, SECP256K1_FE_CONST(0x12303941, 0xaedc2088, 0x80735b1f, 0x1795c8e5, 0x5be520ea, 0x93e10335, 0x7b5d2adb, 0x7ed59b8e), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x11, 0x3a, 0xd9}, SECP256K1_FE_CONST(0x7eed6b70, 0xe7b0767c, 0x7d7feac0, 0x4e57aa2a, 0x12fef5e0, 0xf48f878f, 0xcbb88b3b, 0x6b5e0783), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0xce, 0xa4, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x64998443, 0x5b62b4a2, 0x5d40c613, 0x3e8d9ab8, 0xc53d4b05, 0x9ee8a154, 0xa3be0fcf, 0x4e892edb), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x13, 0xce, 0xa4, 0xa7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x64998443, 0x5b62b4a2, 0x5d40c613, 0x3e8d9ab8, 0xc53d4b05, 0x9ee8a154, 0xa3be0fcf, 0x4e892edb), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x02, 0x8c, 0x59, 0x00, 0x63, 0xf6, 0x4d, 0x5a, 0x7f, 0x1c, 0x14, 0x91, 0x5c, 0xd6, 0x1e, 0xac, 0x88, 0x6a, 0xb2, 0x95, 0xbe, 0xbd, 0x91, 0x99, 0x25, 0x04, 0xcf, 0x77, 0xed, 0xb0, 0x28, 0xbd, 0xd6, 0x26, 0x7f}, SECP256K1_FE_CONST(0x3fde5713, 0xf8282eea, 0xd7d39d42, 0x01f44a7c, 0x85a5ac8a, 0x0681f35e, 0x54085c6b, 0x69543374), 1}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x27, 0x15, 0xde, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x3524f77f, 0xa3a6eb43, 0x89c3cb5d, 0x27f1f914, 0x62086429, 0xcd6c0cb0, 0xdf43ea8f, 0x1e7b3fb4), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x27, 0x15, 0xde, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x3524f77f, 0xa3a6eb43, 0x89c3cb5d, 0x27f1f914, 0x62086429, 0xcd6c0cb0, 0xdf43ea8f, 0x1e7b3fb4), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2c, 0x2c, 0x57, 0x09, 0xe7, 0x15, 0x6c, 0x41, 0x77, 0x17, 0xf2, 0xfe, 0xab, 0x14, 0x71, 0x41, 0xec, 0x3d, 0xa1, 0x9f, 0xb7, 0x59, 0x57, 0x5c, 0xc6, 0xe3, 0x7b, 0x2e, 0xa5, 0xac, 0x93, 0x09, 0xf2, 0x6f, 0x0f, 0x66}, SECP256K1_FE_CONST(0xd2469ab3, 0xe04acbb2, 0x1c65a180, 0x9f39caaf, 0xe7a77c13, 0xd10f9dd3, 0x8f391c01, 0xdc499c52), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3a, 0x08, 0xcc, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x60, 0xe9, 0xf0}, SECP256K1_FE_CONST(0x38e2a5ce, 0x6a93e795, 0xe16d2c39, 0x8bc99f03, 0x69202ce2, 0x1e8f09d5, 0x6777b40f, 0xc512bccc), 1}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0x91, 0x25, 0x7d, 0x93, 0x20, 0x16, 0xcb, 0xf6, 0x9c, 0x44, 0x71, 0xbd, 0x1f, 0x65, 0x6c, 0x6a, 0x10, 0x7f, 0x19, 0x73, 0xde, 0x4a, 0xf7, 0x08, 0x6d, 0xb8, 0x97, 0x27, 0x70, 0x60, 0xe2, 0x56, 0x77, 0xf1, 0x9a}, SECP256K1_FE_CONST(0x864b3dc9, 0x02c37670, 0x9c10a93a, 0xd4bbe29f, 0xce0012f3, 0xdc8672c6, 0x286bba28, 0xd7d6d6fc), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79, 0x5d, 0x6c, 0x1c, 0x32, 0x2c, 0xad, 0xf5, 0x99, 0xdb, 0xb8, 0x64, 0x81, 0x52, 0x2b, 0x3c, 0xc5, 0x5f, 0x15, 0xa6, 0x79, 0x32, 0xdb, 0x2a, 0xfa, 0x01, 0x11, 0xd9, 0xed, 0x69, 0x81, 0xbc, 0xd1, 0x24, 0xbf, 0x44}, SECP256K1_FE_CONST(0x766dfe4a, 0x700d9bee, 0x288b903a, 0xd58870e3, 0xd4fe2f0e, 0xf780bcac, 0x5c823f32, 0x0d9a9bef), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0x42, 0x6f, 0x03, 0x92, 0x38, 0x90, 0x78, 0xc1, 0x2b, 0x1a, 0x89, 0xe9, 0x54, 0x2f, 0x05, 0x93, 0xbc, 0x96, 0xb6, 0xbf, 0xde, 0x82, 0x24, 0xf8, 0x65, 0x4e, 0xf5, 0xd5, 0xcd, 0xa9, 0x35, 0xa3, 0x58, 0x21, 0x94}, SECP256K1_FE_CONST(0xfaec7bc1, 0x987b6323, 0x3fbc5f95, 0x6edbf37d, 0x54404e74, 0x61c58ab8, 0x631bc68e, 0x451a0478), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x91, 0x19, 0x21, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x45, 0xf0, 0xf1, 0xeb}, SECP256K1_FE_CONST(0xec29a50b, 0xae138dbf, 0x7d8e2482, 0x5006bb5f, 0xc1a2cc12, 0x43ba335b, 0xc6116fb9, 0xe498ec1f), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x98, 0xeb, 0x9a, 0xb7, 0x6e, 0x84, 0x49, 0x9c, 0x48, 0x3b, 0x3b, 0xf0, 0x62, 0x14, 0xab, 0xfe, 0x06, 0x5d, 0xdd, 0xf4, 0x3b, 0x86, 0x01, 0xde, 0x59, 0x6d, 0x63, 0xb9, 0xe4, 0x5a, 0x16, 0x6a, 0x58, 0x05, 0x41, 0xfe}, SECP256K1_FE_CONST(0x1e0ff2de, 0xe9b09b13, 0x6292a9e9, 0x10f0d6ac, 0x3e552a64, 0x4bba39e6, 0x4e9dd3e3, 0xbbd3d4d4), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x77, 0xb7, 0xf2, 0xc7, 0x4d, 0x99, 0xef, 0xce, 0xaa, 0x55, 0x0f, 0x1a, 0xd1, 0xc0, 0xf4, 0x3f, 0x46, 0xe7, 0xff, 0x1e, 0xe3, 0xbd, 0x01, 0x62, 0xb7, 0xbf, 0x55, 0xf2, 0x96, 0x5d, 0xa9, 0xc3, 0x45, 0x06, 0x46}, SECP256K1_FE_CONST(0x8b7dd5c3, 0xedba9ee9, 0x7b70eff4, 0x38f22dca, 0x9849c825, 0x4a2f3345, 0xa0a572ff, 0xeaae0928), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b, 0x77, 0xb7, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x15, 0x6c, 0xa8, 0x96}, SECP256K1_FE_CONST(0x0881950c, 0x8f51d6b9, 0xa6387465, 0xd5f12609, 0xef1bb254, 0x12a08a74, 0xcb2dfb20, 0x0c74bfbf), 1}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa2, 0xf5, 0xcd, 0x83, 0x88, 0x16, 0xc1, 0x6c, 0x4f, 0xe8, 0xa1, 0x66, 0x1d, 0x60, 0x6f, 0xdb, 0x13, 0xcf, 0x9a, 0xf0, 0x4b, 0x97, 0x9a, 0x2e, 0x15, 0x9a, 0x09, 0x40, 0x9e, 0xbc, 0x86, 0x45, 0xd5, 0x8f, 0xde, 0x02}, SECP256K1_FE_CONST(0x2f083207, 0xb9fd9b55, 0x0063c31c, 0xd62b8746, 0xbd543bdc, 0x5bbf10e3, 0xa35563e9, 0x27f440c8), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x3f, 0x75, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x4f51e0be, 0x078e0cdd, 0xab274215, 0x6adba7e7, 0xa148e731, 0x57072fd6, 0x18cd6094, 0x2b146bd0), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x3f, 0x75, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x4f51e0be, 0x078e0cdd, 0xab274215, 0x6adba7e7, 0xa148e731, 0x57072fd6, 0x18cd6094, 0x2b146bd0), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xbc, 0x1f, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SECP256K1_FE_CONST(0x16c2ccb5, 0x4352ff4b, 0xd794f6ef, 0xd613c721, 0x97ab7082, 0xda5b563b, 0xdf9cb3ed, 0xaafe74c2), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xbc, 0x1f, 0x8d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f}, SECP256K1_FE_CONST(0x16c2ccb5, 0x4352ff4b, 0xd794f6ef, 0xd613c721, 0x97ab7082, 0xda5b563b, 0xdf9cb3ed, 0xaafe74c2), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x64, 0xd1, 0x62, 0x75, 0x05, 0x46, 0xce, 0x42, 0xb0, 0x43, 0x13, 0x61, 0xe5, 0x2d, 0x4f, 0x52, 0x42, 0xd8, 0xf2, 0x4f, 0x33, 0xe6, 0xb1, 0xf9, 0x9b, 0x59, 0x16, 0x47, 0xcb, 0xc8, 0x08, 0xf4, 0x62, 0xaf, 0x51}, SECP256K1_FE_CONST(0xd41244d1, 0x1ca4f652, 0x40687759, 0xf95ca9ef, 0xbab767ed, 0xedb38fd1, 0x8c36e18c, 0xd3b6f6a9), 1}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe5, 0xbe, 0x52, 0x37, 0x2d, 0xd6, 0xe8, 0x94, 0xb2, 0xa3, 0x26, 0xfc, 0x36, 0x05, 0xa6, 0xe8, 0xf3, 0xc6, 0x9c, 0x71, 0x0b, 0xf2, 0x7d, 0x63, 0x0d, 0xfe, 0x20, 0x04, 0x98, 0x8b, 0x78, 0xeb, 0x6e, 0xab, 0x36}, SECP256K1_FE_CONST(0x64bf84dd, 0x5e03670f, 0xdb24c0f5, 0xd3c2c365, 0x736f51db, 0x6c92d950, 0x10716ad2, 0xd36134c8), 0}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfb, 0xb9, 0x82, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xd6, 0xdb, 0x1f}, SECP256K1_FE_CONST(0x1c92ccdf, 0xcf4ac550, 0xc28db57c, 0xff0c8515, 0xcb26936c, 0x786584a7, 0x0114008d, 0x6c33a34b), 0}, -}; - -/* Set of expected ellswift_xdh BIP324 shared secrets, given private key, encodings, initiating, - * taken from the BIP324 test vectors. Created using an independent implementation, and tested - * against the paper authors' decoding code. */ -static const struct ellswift_xdh_test ellswift_xdh_tests_bip324[] = { - {{0x61, 0x06, 0x2e, 0xa5, 0x07, 0x1d, 0x80, 0x0b, 0xbf, 0xd5, 0x9e, 0x2e, 0x8b, 0x53, 0xd4, 0x7d, 0x19, 0x4b, 0x09, 0x5a, 0xe5, 0xa4, 0xdf, 0x04, 0x93, 0x6b, 0x49, 0x77, 0x2e, 0xf0, 0xd4, 0xd7}, {0xec, 0x0a, 0xdf, 0xf2, 0x57, 0xbb, 0xfe, 0x50, 0x0c, 0x18, 0x8c, 0x80, 0xb4, 0xfd, 0xd6, 0x40, 0xf6, 0xb4, 0x5a, 0x48, 0x2b, 0xbc, 0x15, 0xfc, 0x7c, 0xef, 0x59, 0x31, 0xde, 0xff, 0x0a, 0xa1, 0x86, 0xf6, 0xeb, 0x9b, 0xba, 0x7b, 0x85, 0xdc, 0x4d, 0xcc, 0x28, 0xb2, 0x87, 0x22, 0xde, 0x1e, 0x3d, 0x91, 0x08, 0xb9, 0x85, 0xe2, 0x96, 0x70, 0x45, 0x66, 0x8f, 0x66, 0x09, 0x8e, 0x47, 0x5b}, {0xa4, 0xa9, 0x4d, 0xfc, 0xe6, 0x9b, 0x4a, 0x2a, 0x0a, 0x09, 0x93, 0x13, 0xd1, 0x0f, 0x9f, 0x7e, 0x7d, 0x64, 0x9d, 0x60, 0x50, 0x1c, 0x9e, 0x1d, 0x27, 0x4c, 0x30, 0x0e, 0x0d, 0x89, 0xaa, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xaf, 0x88, 0xd5}, 1, {0xc6, 0x99, 0x2a, 0x11, 0x7f, 0x5e, 0xdb, 0xea, 0x70, 0xc3, 0xf5, 0x11, 0xd3, 0x2d, 0x26, 0xb9, 0x79, 0x8b, 0xe4, 0xb8, 0x1a, 0x62, 0xea, 0xee, 0x1a, 0x5a, 0xca, 0xa8, 0x45, 0x9a, 0x35, 0x92}}, - {{0x1f, 0x9c, 0x58, 0x1b, 0x35, 0x23, 0x18, 0x38, 0xf0, 0xf1, 0x7c, 0xf0, 0xc9, 0x79, 0x83, 0x5b, 0xac, 0xcb, 0x7f, 0x3a, 0xbb, 0xbb, 0x96, 0xff, 0xcc, 0x31, 0x8a, 0xb7, 0x1e, 0x6e, 0x12, 0x6f}, {0xa1, 0x85, 0x5e, 0x10, 0xe9, 0x4e, 0x00, 0xba, 0xa2, 0x30, 0x41, 0xd9, 0x16, 0xe2, 0x59, 0xf7, 0x04, 0x4e, 0x49, 0x1d, 0xa6, 0x17, 0x12, 0x69, 0x69, 0x47, 0x63, 0xf0, 0x18, 0xc7, 0xe6, 0x36, 0x93, 0xd2, 0x95, 0x75, 0xdc, 0xb4, 0x64, 0xac, 0x81, 0x6b, 0xaa, 0x1b, 0xe3, 0x53, 0xba, 0x12, 0xe3, 0x87, 0x6c, 0xba, 0x76, 0x28, 0xbd, 0x0b, 0xd8, 0xe7, 0x55, 0xe7, 0x21, 0xeb, 0x01, 0x40}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, {0xa0, 0x13, 0x8f, 0x56, 0x4f, 0x74, 0xd0, 0xad, 0x70, 0xbc, 0x33, 0x7d, 0xac, 0xc9, 0xd0, 0xbf, 0x1d, 0x23, 0x49, 0x36, 0x4c, 0xaf, 0x11, 0x88, 0xa1, 0xe6, 0xe8, 0xdd, 0xb3, 0xb7, 0xb1, 0x84}}, - {{0x02, 0x86, 0xc4, 0x1c, 0xd3, 0x09, 0x13, 0xdb, 0x0f, 0xdf, 0xf7, 0xa6, 0x4e, 0xbd, 0xa5, 0xc8, 0xe3, 0xe7, 0xce, 0xf1, 0x0f, 0x2a, 0xeb, 0xc0, 0x0a, 0x76, 0x50, 0x44, 0x3c, 0xf4, 0xc6, 0x0d}, {0xd1, 0xee, 0x8a, 0x93, 0xa0, 0x11, 0x30, 0xcb, 0xf2, 0x99, 0x24, 0x9a, 0x25, 0x8f, 0x94, 0xfe, 0xb5, 0xf4, 0x69, 0xe7, 0xd0, 0xf2, 0xf2, 0x8f, 0x69, 0xee, 0x5e, 0x9a, 0xa8, 0xf9, 0xb5, 0x4a, 0x60, 0xf2, 0xc3, 0xff, 0x2d, 0x02, 0x36, 0x34, 0xec, 0x7f, 0x41, 0x27, 0xa9, 0x6c, 0xc1, 0x16, 0x62, 0xe4, 0x02, 0x89, 0x4c, 0xf1, 0xf6, 0x94, 0xfb, 0x9a, 0x7e, 0xaa, 0x5f, 0x1d, 0x92, 0x44}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x22, 0xd5, 0xe4, 0x41, 0x52, 0x4d, 0x57, 0x1a, 0x52, 0xb3, 0xde, 0xf1, 0x26, 0x18, 0x9d, 0x3f, 0x41, 0x68, 0x90, 0xa9, 0x9d, 0x4d, 0xa6, 0xed, 0xe2, 0xb0, 0xcd, 0xe1, 0x76, 0x0c, 0xe2, 0xc3, 0xf9, 0x84, 0x57, 0xae}, 1, {0x25, 0x0b, 0x93, 0x57, 0x0d, 0x41, 0x11, 0x49, 0x10, 0x5a, 0xb8, 0xcb, 0x0b, 0xc5, 0x07, 0x99, 0x14, 0x90, 0x63, 0x06, 0x36, 0x8c, 0x23, 0xe9, 0xd7, 0x7c, 0x2a, 0x33, 0x26, 0x5b, 0x99, 0x4c}}, - {{0x6c, 0x77, 0x43, 0x2d, 0x1f, 0xda, 0x31, 0xe9, 0xf9, 0x42, 0xf8, 0xaf, 0x44, 0x60, 0x7e, 0x10, 0xf3, 0xad, 0x38, 0xa6, 0x5f, 0x8a, 0x4b, 0xdd, 0xae, 0x82, 0x3e, 0x5e, 0xff, 0x90, 0xdc, 0x38}, {0xd2, 0x68, 0x50, 0x70, 0xc1, 0xe6, 0x37, 0x6e, 0x63, 0x3e, 0x82, 0x52, 0x96, 0x63, 0x4f, 0xd4, 0x61, 0xfa, 0x9e, 0x5b, 0xdf, 0x21, 0x09, 0xbc, 0xeb, 0xd7, 0x35, 0xe5, 0xa9, 0x1f, 0x3e, 0x58, 0x7c, 0x5c, 0xb7, 0x82, 0xab, 0xb7, 0x97, 0xfb, 0xf6, 0xbb, 0x50, 0x74, 0xfd, 0x15, 0x42, 0xa4, 0x74, 0xf2, 0xa4, 0x5b, 0x67, 0x37, 0x63, 0xec, 0x2d, 0xb7, 0xfb, 0x99, 0xb7, 0x37, 0xbb, 0xb9}, {0x56, 0xbd, 0x0c, 0x06, 0xf1, 0x03, 0x52, 0xc3, 0xa1, 0xa9, 0xf4, 0xb4, 0xc9, 0x2f, 0x6f, 0xa2, 0xb2, 0x6d, 0xf1, 0x24, 0xb5, 0x78, 0x78, 0x35, 0x3c, 0x1f, 0xc6, 0x91, 0xc5, 0x1a, 0xbe, 0xa7, 0x7c, 0x88, 0x17, 0xda, 0xee, 0xb9, 0xfa, 0x54, 0x6b, 0x77, 0xc8, 0xda, 0xf7, 0x9d, 0x89, 0xb2, 0x2b, 0x0e, 0x1b, 0x87, 0x57, 0x4e, 0xce, 0x42, 0x37, 0x1f, 0x00, 0x23, 0x7a, 0xa9, 0xd8, 0x3a}, 0, {0x19, 0x18, 0xb7, 0x41, 0xef, 0x5f, 0x9d, 0x1d, 0x76, 0x70, 0xb0, 0x50, 0xc1, 0x52, 0xb4, 0xa4, 0xea, 0xd2, 0xc3, 0x1b, 0xe9, 0xae, 0xcb, 0x06, 0x81, 0xc0, 0xcd, 0x43, 0x24, 0x15, 0x08, 0x53}}, - {{0xa6, 0xec, 0x25, 0x12, 0x7c, 0xa1, 0xaa, 0x4c, 0xf1, 0x6b, 0x20, 0x08, 0x4b, 0xa1, 0xe6, 0x51, 0x6b, 0xaa, 0xe4, 0xd3, 0x24, 0x22, 0x28, 0x8e, 0x9b, 0x36, 0xd8, 0xbd, 0xdd, 0x2d, 0xe3, 0x5a}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x3d, 0x7e, 0xcc, 0xa5, 0x3e, 0x33, 0xe1, 0x85, 0xa8, 0xb9, 0xbe, 0x4e, 0x76, 0x99, 0xa9, 0x7c, 0x6f, 0xf4, 0xc7, 0x95, 0x52, 0x2e, 0x59, 0x18, 0xab, 0x7c, 0xd6, 0xb6, 0x88, 0x4f, 0x67, 0xe6, 0x83, 0xf3, 0xdc}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0x73, 0x0b, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 1, {0xdd, 0x21, 0x0a, 0xa6, 0x62, 0x9f, 0x20, 0xbb, 0x32, 0x8e, 0x5d, 0x89, 0xda, 0xa6, 0xeb, 0x2a, 0xc3, 0xd1, 0xc6, 0x58, 0xa7, 0x25, 0x53, 0x6f, 0xf1, 0x54, 0xf3, 0x1b, 0x53, 0x6c, 0x23, 0xb2}}, - {{0x0a, 0xf9, 0x52, 0x65, 0x9e, 0xd7, 0x6f, 0x80, 0xf5, 0x85, 0x96, 0x6b, 0x95, 0xab, 0x6e, 0x6f, 0xd6, 0x86, 0x54, 0x67, 0x28, 0x27, 0x87, 0x86, 0x84, 0xc8, 0xb5, 0x47, 0xb1, 0xb9, 0x4f, 0x5a}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x10, 0x17, 0xfd, 0x92, 0xfd, 0x31, 0x63, 0x7c, 0x26, 0xc9, 0x06, 0xb4, 0x20, 0x92, 0xe1, 0x1c, 0xc0, 0xd3, 0xaf, 0xae, 0x8d, 0x90, 0x19, 0xd2, 0x57, 0x8a, 0xf2, 0x27, 0x35, 0xce, 0x7b, 0xc4, 0x69, 0xc7, 0x2d}, {0x96, 0x52, 0xd7, 0x8b, 0xae, 0xfc, 0x02, 0x8c, 0xd3, 0x7a, 0x6a, 0x92, 0x62, 0x5b, 0x8b, 0x8f, 0x85, 0xfd, 0xe1, 0xe4, 0xc9, 0x44, 0xad, 0x3f, 0x20, 0xe1, 0x98, 0xbe, 0xf8, 0xc0, 0x2f, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xe9, 0x18, 0x70}, 0, {0x35, 0x68, 0xf2, 0xae, 0xa2, 0xe1, 0x4e, 0xf4, 0xee, 0x4a, 0x3c, 0x2a, 0x8b, 0x8d, 0x31, 0xbc, 0x5e, 0x31, 0x87, 0xba, 0x86, 0xdb, 0x10, 0x73, 0x9b, 0x4f, 0xf8, 0xec, 0x92, 0xff, 0x66, 0x55}}, - {{0xf9, 0x0e, 0x08, 0x0c, 0x64, 0xb0, 0x58, 0x24, 0xc5, 0xa2, 0x4b, 0x25, 0x01, 0xd5, 0xae, 0xaf, 0x08, 0xaf, 0x38, 0x72, 0xee, 0x86, 0x0a, 0xa8, 0x0b, 0xdc, 0xd4, 0x30, 0xf7, 0xb6, 0x34, 0x94}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x51, 0x73, 0x76, 0x5d, 0xc2, 0x02, 0xcf, 0x02, 0x9a, 0xd3, 0xf1, 0x54, 0x79, 0x73, 0x5d, 0x57, 0x69, 0x7a, 0xf1, 0x2b, 0x01, 0x31, 0xdd, 0x21, 0x43, 0x0d, 0x57, 0x72, 0xe4, 0xef, 0x11, 0x47, 0x4d, 0x58, 0xb9}, {0x12, 0xa5, 0x0f, 0x3f, 0xaf, 0xea, 0x7c, 0x1e, 0xea, 0xda, 0x4c, 0xf8, 0xd3, 0x37, 0x77, 0x70, 0x4b, 0x77, 0x36, 0x14, 0x53, 0xaf, 0xc8, 0x3b, 0xda, 0x91, 0xee, 0xf3, 0x49, 0xae, 0x04, 0x4d, 0x20, 0x12, 0x6c, 0x62, 0x00, 0x54, 0x7e, 0xa5, 0xa6, 0x91, 0x17, 0x76, 0xc0, 0x5d, 0xee, 0x2a, 0x7f, 0x1a, 0x9b, 0xa7, 0xdf, 0xba, 0xbb, 0xbd, 0x27, 0x3c, 0x3e, 0xf2, 0x9e, 0xf4, 0x6e, 0x46}, 1, {0xe2, 0x54, 0x61, 0xfb, 0x0e, 0x4c, 0x16, 0x2e, 0x18, 0x12, 0x3e, 0xcd, 0xe8, 0x83, 0x42, 0xd5, 0x4d, 0x44, 0x96, 0x31, 0xe9, 0xb7, 0x5a, 0x26, 0x6f, 0xd9, 0x26, 0x0c, 0x2b, 0xb2, 0xf4, 0x1d}}, -}; - -/** This is a hasher for ellswift_xdh which just returns the shared X coordinate. - * - * This is generally a bad idea as it means changes to the encoding of the - * exchanged public keys do not affect the shared secret. However, it's used here - * in tests to be able to verify the X coordinate through other means. - */ -static int ellswift_xdh_hash_x32(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { - (void)ell_a64; - (void)ell_b64; - (void)data; - memcpy(output, x32, 32); - return 1; -} - -void run_ellswift_tests(void) { - int i = 0; - /* Test vectors. */ - for (i = 0; (unsigned)i < sizeof(ellswift_xswiftec_inv_tests) / sizeof(ellswift_xswiftec_inv_tests[0]); ++i) { - const struct ellswift_xswiftec_inv_test *testcase = &ellswift_xswiftec_inv_tests[i]; - int c; - for (c = 0; c < 8; ++c) { - secp256k1_fe t; - int ret = secp256k1_ellswift_xswiftec_inv_var(&t, &testcase->x, &testcase->u, c); - CHECK(ret == ((testcase->enc_bitmap >> c) & 1)); - if (ret) { - secp256k1_fe x2; - CHECK(fe_equal(&t, &testcase->encs[c])); - secp256k1_ellswift_xswiftec_var(&x2, &testcase->u, &testcase->encs[c]); - CHECK(fe_equal(&testcase->x, &x2)); - } - } - } - for (i = 0; (unsigned)i < sizeof(ellswift_decode_tests) / sizeof(ellswift_decode_tests[0]); ++i) { - const struct ellswift_decode_test *testcase = &ellswift_decode_tests[i]; - secp256k1_pubkey pubkey; - secp256k1_ge ge; - int ret; - ret = secp256k1_ellswift_decode(CTX, &pubkey, testcase->enc); - CHECK(ret); - ret = secp256k1_pubkey_load(CTX, &ge, &pubkey); - CHECK(ret); - CHECK(fe_equal(&testcase->x, &ge.x)); - CHECK(secp256k1_fe_is_odd(&ge.y) == testcase->odd_y); - } - for (i = 0; (unsigned)i < sizeof(ellswift_xdh_tests_bip324) / sizeof(ellswift_xdh_tests_bip324[0]); ++i) { - const struct ellswift_xdh_test *test = &ellswift_xdh_tests_bip324[i]; - unsigned char shared_secret[32]; - int ret; - int party = !test->initiating; - const unsigned char* ell_a64 = party ? test->ellswift_theirs : test->ellswift_ours; - const unsigned char* ell_b64 = party ? test->ellswift_ours : test->ellswift_theirs; - ret = secp256k1_ellswift_xdh(CTX, shared_secret, - ell_a64, ell_b64, - test->priv_ours, - party, - secp256k1_ellswift_xdh_hash_function_bip324, - NULL); - CHECK(ret); - CHECK(secp256k1_memcmp_var(shared_secret, test->shared_secret, 32) == 0); - } - /* Verify that secp256k1_ellswift_encode + decode roundtrips. */ - for (i = 0; i < 1000 * COUNT; i++) { - unsigned char rnd32[32]; - unsigned char ell64[64]; - secp256k1_ge g, g2; - secp256k1_pubkey pubkey, pubkey2; - /* Generate random public key and random randomizer. */ - testutil_random_ge_test(&g); - secp256k1_pubkey_save(&pubkey, &g); - testrand256(rnd32); - /* Convert the public key to ElligatorSwift and back. */ - secp256k1_ellswift_encode(CTX, ell64, &pubkey, rnd32); - secp256k1_ellswift_decode(CTX, &pubkey2, ell64); - secp256k1_pubkey_load(CTX, &g2, &pubkey2); - /* Compare with original. */ - CHECK(secp256k1_ge_eq_var(&g, &g2)); - } - /* Verify the behavior of secp256k1_ellswift_create */ - for (i = 0; i < 400 * COUNT; i++) { - unsigned char auxrnd32[32], sec32[32]; - secp256k1_scalar sec; - secp256k1_gej res; - secp256k1_ge dec; - secp256k1_pubkey pub; - unsigned char ell64[64]; - int ret; - /* Generate random secret key and random randomizer. */ - if (i & 1) testrand256_test(auxrnd32); - testutil_random_scalar_order_test(&sec); - secp256k1_scalar_get_b32(sec32, &sec); - /* Construct ElligatorSwift-encoded public keys for that key. */ - ret = secp256k1_ellswift_create(CTX, ell64, sec32, (i & 1) ? auxrnd32 : NULL); - CHECK(ret); - /* Decode it, and compare with traditionally-computed public key. */ - secp256k1_ellswift_decode(CTX, &pub, ell64); - secp256k1_pubkey_load(CTX, &dec, &pub); - secp256k1_ecmult(&res, NULL, &secp256k1_scalar_zero, &sec); - CHECK(secp256k1_gej_eq_ge_var(&res, &dec)); - } - /* Verify that secp256k1_ellswift_xdh computes the right shared X coordinate. */ - for (i = 0; i < 800 * COUNT; i++) { - unsigned char ell64[64], sec32[32], share32[32]; - secp256k1_scalar sec; - secp256k1_ge dec, res; - secp256k1_fe share_x; - secp256k1_gej decj, resj; - secp256k1_pubkey pub; - int ret; - /* Generate random secret key. */ - testutil_random_scalar_order_test(&sec); - secp256k1_scalar_get_b32(sec32, &sec); - /* Generate random ElligatorSwift encoding for the remote key and decode it. */ - testrand256_test(ell64); - testrand256_test(ell64 + 32); - secp256k1_ellswift_decode(CTX, &pub, ell64); - secp256k1_pubkey_load(CTX, &dec, &pub); - secp256k1_gej_set_ge(&decj, &dec); - /* Compute the X coordinate of seckey*pubkey using ellswift_xdh. Note that we - * pass ell64 as claimed (but incorrect) encoding for sec32 here; this works - * because the "hasher" function we use here ignores the ell64 arguments. */ - ret = secp256k1_ellswift_xdh(CTX, share32, ell64, ell64, sec32, i & 1, &ellswift_xdh_hash_x32, NULL); - CHECK(ret); - (void)secp256k1_fe_set_b32_limit(&share_x, share32); /* no overflow is possible */ - SECP256K1_FE_VERIFY(&share_x); - /* Compute seckey*pubkey directly. */ - secp256k1_ecmult(&resj, &decj, &sec, NULL); - secp256k1_ge_set_gej(&res, &resj); - /* Compare. */ - CHECK(fe_equal(&res.x, &share_x)); - } - /* Verify the joint behavior of secp256k1_ellswift_xdh */ - for (i = 0; i < 200 * COUNT; i++) { - unsigned char auxrnd32a[32], auxrnd32b[32], auxrnd32a_bad[32], auxrnd32b_bad[32]; - unsigned char sec32a[32], sec32b[32], sec32a_bad[32], sec32b_bad[32]; - secp256k1_scalar seca, secb; - unsigned char ell64a[64], ell64b[64], ell64a_bad[64], ell64b_bad[64]; - unsigned char share32a[32], share32b[32], share32_bad[32]; - unsigned char prefix64[64]; - secp256k1_ellswift_xdh_hash_function hash_function; - void* data; - int ret; - - /* Pick hasher to use. */ - if ((i % 3) == 0) { - hash_function = ellswift_xdh_hash_x32; - data = NULL; - } else if ((i % 3) == 1) { - hash_function = secp256k1_ellswift_xdh_hash_function_bip324; - data = NULL; - } else { - hash_function = secp256k1_ellswift_xdh_hash_function_prefix; - testrand256_test(prefix64); - testrand256_test(prefix64 + 32); - data = prefix64; - } - - /* Generate random secret keys and random randomizers. */ - testrand256_test(auxrnd32a); - testrand256_test(auxrnd32b); - testutil_random_scalar_order_test(&seca); - /* Draw secb uniformly at random to make sure that the secret keys - * differ */ - testutil_random_scalar_order(&secb); - secp256k1_scalar_get_b32(sec32a, &seca); - secp256k1_scalar_get_b32(sec32b, &secb); - - /* Construct ElligatorSwift-encoded public keys for those keys. */ - /* For A: */ - ret = secp256k1_ellswift_create(CTX, ell64a, sec32a, auxrnd32a); - CHECK(ret); - /* For B: */ - ret = secp256k1_ellswift_create(CTX, ell64b, sec32b, auxrnd32b); - CHECK(ret); - - /* Compute the shared secret both ways and compare with each other. */ - /* For A: */ - ret = secp256k1_ellswift_xdh(CTX, share32a, ell64a, ell64b, sec32a, 0, hash_function, data); - CHECK(ret); - /* For B: */ - ret = secp256k1_ellswift_xdh(CTX, share32b, ell64a, ell64b, sec32b, 1, hash_function, data); - CHECK(ret); - /* And compare: */ - CHECK(secp256k1_memcmp_var(share32a, share32b, 32) == 0); - - /* Verify that the shared secret doesn't match if other side's public key is incorrect. */ - /* For A (using a bad public key for B): */ - memcpy(ell64b_bad, ell64b, sizeof(ell64a_bad)); - testrand_flip(ell64b_bad, sizeof(ell64b_bad)); - ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); - CHECK(ret); /* Mismatching encodings don't get detected by secp256k1_ellswift_xdh. */ - CHECK(secp256k1_memcmp_var(share32_bad, share32a, 32) != 0); - /* For B (using a bad public key for A): */ - memcpy(ell64a_bad, ell64a, sizeof(ell64a_bad)); - testrand_flip(ell64a_bad, sizeof(ell64a_bad)); - ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); - CHECK(ret); - CHECK(secp256k1_memcmp_var(share32_bad, share32b, 32) != 0); - - /* Verify that the shared secret doesn't match if the private key is incorrect. */ - /* For A: */ - memcpy(sec32a_bad, sec32a, sizeof(sec32a_bad)); - testrand_flip(sec32a_bad, sizeof(sec32a_bad)); - ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a_bad, 0, hash_function, data); - CHECK(!ret || secp256k1_memcmp_var(share32_bad, share32a, 32) != 0); - /* For B: */ - memcpy(sec32b_bad, sec32b, sizeof(sec32b_bad)); - testrand_flip(sec32b_bad, sizeof(sec32b_bad)); - ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b_bad, 1, hash_function, data); - CHECK(!ret || secp256k1_memcmp_var(share32_bad, share32b, 32) != 0); - - if (hash_function != ellswift_xdh_hash_x32) { - /* Verify that the shared secret doesn't match when a different encoding of the same public key is used. */ - /* For A (changing B's public key): */ - memcpy(auxrnd32b_bad, auxrnd32b, sizeof(auxrnd32b_bad)); - testrand_flip(auxrnd32b_bad, sizeof(auxrnd32b_bad)); - ret = secp256k1_ellswift_create(CTX, ell64b_bad, sec32b, auxrnd32b_bad); - CHECK(ret); - ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); - CHECK(ret); - CHECK(secp256k1_memcmp_var(share32_bad, share32a, 32) != 0); - /* For B (changing A's public key): */ - memcpy(auxrnd32a_bad, auxrnd32a, sizeof(auxrnd32a_bad)); - testrand_flip(auxrnd32a_bad, sizeof(auxrnd32a_bad)); - ret = secp256k1_ellswift_create(CTX, ell64a_bad, sec32a, auxrnd32a_bad); - CHECK(ret); - ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); - CHECK(ret); - CHECK(secp256k1_memcmp_var(share32_bad, share32b, 32) != 0); - - /* Verify that swapping sides changes the shared secret. */ - /* For A (claiming to be B): */ - ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a, 1, hash_function, data); - CHECK(ret); - CHECK(secp256k1_memcmp_var(share32_bad, share32a, 32) != 0); - /* For B (claiming to be A): */ - ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b, 0, hash_function, data); - CHECK(ret); - CHECK(secp256k1_memcmp_var(share32_bad, share32b, 32) != 0); - } - } - - /* Test hash initializers. */ - { - secp256k1_sha256 sha, sha_optimized; - static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'}; - static const unsigned char create_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'c', 'r', 'e', 'a', 't', 'e'}; - static const unsigned char bip324_tag[] = {'b', 'i', 'p', '3', '2', '4', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'x', 'o', 'n', 'l', 'y', '_', 'e', 'c', 'd', 'h'}; - - /* Check that hash initialized by - * secp256k1_ellswift_sha256_init_encode has the expected - * state. */ - secp256k1_sha256_initialize_tagged(&sha, encode_tag, sizeof(encode_tag)); - secp256k1_ellswift_sha256_init_encode(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); - - /* Check that hash initialized by - * secp256k1_ellswift_sha256_init_create has the expected - * state. */ - secp256k1_sha256_initialize_tagged(&sha, create_tag, sizeof(create_tag)); - secp256k1_ellswift_sha256_init_create(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); - - /* Check that hash initialized by - * secp256k1_ellswift_sha256_init_bip324 has the expected - * state. */ - secp256k1_sha256_initialize_tagged(&sha, bip324_tag, sizeof(bip324_tag)); - secp256k1_ellswift_sha256_init_bip324(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); - } -} - -#endif diff --git a/external/secp256k1/src/modules/extrakeys/Makefile.am.include b/external/secp256k1/src/modules/extrakeys/Makefile.am.include deleted file mode 100644 index 0d901ec1f4..0000000000 --- a/external/secp256k1/src/modules/extrakeys/Makefile.am.include +++ /dev/null @@ -1,4 +0,0 @@ -include_HEADERS += include/secp256k1_extrakeys.h -noinst_HEADERS += src/modules/extrakeys/tests_impl.h -noinst_HEADERS += src/modules/extrakeys/tests_exhaustive_impl.h -noinst_HEADERS += src/modules/extrakeys/main_impl.h diff --git a/external/secp256k1/src/modules/extrakeys/main_impl.h b/external/secp256k1/src/modules/extrakeys/main_impl.h deleted file mode 100644 index 0c7e266777..0000000000 --- a/external/secp256k1/src/modules/extrakeys/main_impl.h +++ /dev/null @@ -1,285 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_EXTRAKEYS_MAIN_H -#define SECP256K1_MODULE_EXTRAKEYS_MAIN_H - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_extrakeys.h" -#include "../../util.h" - -static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) { - return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey); -} - -static SECP256K1_INLINE void secp256k1_xonly_pubkey_save(secp256k1_xonly_pubkey *pubkey, secp256k1_ge *ge) { - secp256k1_pubkey_save((secp256k1_pubkey *) pubkey, ge); -} - -int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, const unsigned char *input32) { - secp256k1_ge pk; - secp256k1_fe x; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(input32 != NULL); - - if (!secp256k1_fe_set_b32_limit(&x, input32)) { - return 0; - } - if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) { - return 0; - } - if (!secp256k1_ge_is_in_correct_subgroup(&pk)) { - return 0; - } - secp256k1_xonly_pubkey_save(pubkey, &pk); - return 1; -} - -int secp256k1_xonly_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output32, const secp256k1_xonly_pubkey *pubkey) { - secp256k1_ge pk; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output32 != NULL); - memset(output32, 0, 32); - ARG_CHECK(pubkey != NULL); - - if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) { - return 0; - } - secp256k1_fe_get_b32(output32, &pk.x); - return 1; -} - -int secp256k1_xonly_pubkey_cmp(const secp256k1_context* ctx, const secp256k1_xonly_pubkey* pk0, const secp256k1_xonly_pubkey* pk1) { - unsigned char out[2][32]; - const secp256k1_xonly_pubkey* pk[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - pk[0] = pk0; pk[1] = pk1; - for (i = 0; i < 2; i++) { - /* If the public key is NULL or invalid, xonly_pubkey_serialize will - * call the illegal_callback and return 0. In that case we will - * serialize the key as all zeros which is less than any valid public - * key. This results in consistent comparisons even if NULL or invalid - * pubkeys are involved and prevents edge cases such as sorting - * algorithms that use this function and do not terminate as a - * result. */ - if (!secp256k1_xonly_pubkey_serialize(ctx, out[i], pk[i])) { - /* Note that xonly_pubkey_serialize should already set the output to - * zero in that case, but it's not guaranteed by the API, we can't - * test it and writing a VERIFY_CHECK is more complex than - * explicitly memsetting (again). */ - memset(out[i], 0, sizeof(out[i])); - } - } - return secp256k1_memcmp_var(out[0], out[1], sizeof(out[1])); -} - -/** Keeps a group element as is if it has an even Y and otherwise negates it. - * y_parity is set to 0 in the former case and to 1 in the latter case. - * Requires that the coordinates of r are normalized. */ -static int secp256k1_extrakeys_ge_even_y(secp256k1_ge *r) { - int y_parity = 0; - VERIFY_CHECK(!secp256k1_ge_is_infinity(r)); - - if (secp256k1_fe_is_odd(&r->y)) { - secp256k1_fe_negate(&r->y, &r->y, 1); - y_parity = 1; - } - return y_parity; -} - -int secp256k1_xonly_pubkey_from_pubkey(const secp256k1_context* ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, const secp256k1_pubkey *pubkey) { - secp256k1_ge pk; - int tmp; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(xonly_pubkey != NULL); - ARG_CHECK(pubkey != NULL); - - if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { - return 0; - } - tmp = secp256k1_extrakeys_ge_even_y(&pk); - if (pk_parity != NULL) { - *pk_parity = tmp; - } - secp256k1_xonly_pubkey_save(xonly_pubkey, &pk); - return 1; -} - -int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { - secp256k1_ge pk; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output_pubkey != NULL); - memset(output_pubkey, 0, sizeof(*output_pubkey)); - ARG_CHECK(internal_pubkey != NULL); - ARG_CHECK(tweak32 != NULL); - - if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) - || !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) { - return 0; - } - secp256k1_pubkey_save(output_pubkey, &pk); - return 1; -} - -int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { - secp256k1_ge pk; - unsigned char pk_expected32[32]; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(internal_pubkey != NULL); - ARG_CHECK(tweaked_pubkey32 != NULL); - ARG_CHECK(tweak32 != NULL); - - if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) - || !secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32)) { - return 0; - } - secp256k1_fe_normalize_var(&pk.x); - secp256k1_fe_normalize_var(&pk.y); - secp256k1_fe_get_b32(pk_expected32, &pk.x); - - return secp256k1_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0 - && secp256k1_fe_is_odd(&pk.y) == tweaked_pk_parity; -} - -static void secp256k1_keypair_save(secp256k1_keypair *keypair, const secp256k1_scalar *sk, secp256k1_ge *pk) { - secp256k1_scalar_get_b32(&keypair->data[0], sk); - secp256k1_pubkey_save((secp256k1_pubkey *)&keypair->data[32], pk); -} - - -static int secp256k1_keypair_seckey_load(const secp256k1_context* ctx, secp256k1_scalar *sk, const secp256k1_keypair *keypair) { - int ret; - - ret = secp256k1_scalar_set_b32_seckey(sk, &keypair->data[0]); - /* We can declassify ret here because sk is only zero if a keypair function - * failed (which zeroes the keypair) and its return value is ignored. */ - secp256k1_declassify(ctx, &ret, sizeof(ret)); - ARG_CHECK(ret); - return ret; -} - -/* Load a keypair into pk and sk (if non-NULL). This function declassifies pk - * and ARG_CHECKs that the keypair is not invalid. It always initializes sk and - * pk with dummy values. */ -static int secp256k1_keypair_load(const secp256k1_context* ctx, secp256k1_scalar *sk, secp256k1_ge *pk, const secp256k1_keypair *keypair) { - int ret; - const secp256k1_pubkey *pubkey = (const secp256k1_pubkey *)&keypair->data[32]; - - /* Need to declassify the pubkey because pubkey_load ARG_CHECKs if it's - * invalid. */ - secp256k1_declassify(ctx, pubkey, sizeof(*pubkey)); - ret = secp256k1_pubkey_load(ctx, pk, pubkey); - if (sk != NULL) { - ret = ret && secp256k1_keypair_seckey_load(ctx, sk, keypair); - } - if (!ret) { - *pk = secp256k1_ge_const_g; - if (sk != NULL) { - *sk = secp256k1_scalar_one; - } - } - return ret; -} - -int secp256k1_keypair_create(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *seckey32) { - secp256k1_scalar sk; - secp256k1_ge pk; - int ret = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(keypair != NULL); - memset(keypair, 0, sizeof(*keypair)); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(seckey32 != NULL); - - ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32); - secp256k1_keypair_save(keypair, &sk, &pk); - secp256k1_memczero(keypair, sizeof(*keypair), !ret); - - secp256k1_scalar_clear(&sk); - return ret; -} - -int secp256k1_keypair_sec(const secp256k1_context* ctx, unsigned char *seckey, const secp256k1_keypair *keypair) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - memset(seckey, 0, 32); - ARG_CHECK(keypair != NULL); - - memcpy(seckey, &keypair->data[0], 32); - return 1; -} - -int secp256k1_keypair_pub(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_keypair *keypair) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(keypair != NULL); - - memcpy(pubkey->data, &keypair->data[32], sizeof(*pubkey)); - return 1; -} - -int secp256k1_keypair_xonly_pub(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair) { - secp256k1_ge pk; - int tmp; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(keypair != NULL); - - if (!secp256k1_keypair_load(ctx, NULL, &pk, keypair)) { - return 0; - } - tmp = secp256k1_extrakeys_ge_even_y(&pk); - if (pk_parity != NULL) { - *pk_parity = tmp; - } - secp256k1_xonly_pubkey_save(pubkey, &pk); - - return 1; -} - -int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *tweak32) { - secp256k1_ge pk; - secp256k1_scalar sk; - int y_parity; - int ret; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(keypair != NULL); - ARG_CHECK(tweak32 != NULL); - - ret = secp256k1_keypair_load(ctx, &sk, &pk, keypair); - memset(keypair, 0, sizeof(*keypair)); - - y_parity = secp256k1_extrakeys_ge_even_y(&pk); - if (y_parity == 1) { - secp256k1_scalar_negate(&sk, &sk); - } - - ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32); - ret &= secp256k1_ec_pubkey_tweak_add_helper(&pk, tweak32); - - secp256k1_declassify(ctx, &ret, sizeof(ret)); - if (ret) { - secp256k1_keypair_save(keypair, &sk, &pk); - } - - secp256k1_scalar_clear(&sk); - return ret; -} - -#endif diff --git a/external/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h b/external/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h deleted file mode 100644 index 645bae2d47..0000000000 --- a/external/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h +++ /dev/null @@ -1,68 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H -#define SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H - -#include "../../../include/secp256k1_extrakeys.h" -#include "main_impl.h" - -static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp256k1_ge* group) { - secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; - secp256k1_pubkey pubkey[EXHAUSTIVE_TEST_ORDER - 1]; - secp256k1_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; - int parities[EXHAUSTIVE_TEST_ORDER - 1]; - unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; - int i; - - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - secp256k1_fe fe; - secp256k1_scalar scalar_i; - unsigned char buf[33]; - int parity; - - secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_scalar_get_b32(buf, &scalar_i); - - /* Construct pubkey and keypair. */ - CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey[i - 1], buf)); - - /* Construct serialized xonly_pubkey from keypair. */ - CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parities[i - 1], &keypair[i - 1])); - CHECK(secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); - - /* Parse the xonly_pubkey back and verify it matches the previously serialized value. */ - CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1])); - CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); - CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); - - /* Construct the xonly_pubkey from the pubkey, and verify it matches the same. */ - CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1])); - CHECK(parity == parities[i - 1]); - CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); - CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); - - /* Compare the xonly_pubkey bytes against the precomputed group. */ - secp256k1_fe_set_b32_mod(&fe, xonly_pubkey_bytes[i - 1]); - CHECK(secp256k1_fe_equal(&fe, &group[i].x)); - - /* Check the parity against the precomputed group. */ - fe = group[i].y; - secp256k1_fe_normalize_var(&fe); - CHECK(secp256k1_fe_is_odd(&fe) == parities[i - 1]); - - /* Verify that the higher half is identical to the lower half mirrored. */ - if (i > EXHAUSTIVE_TEST_ORDER / 2) { - CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0); - CHECK(parities[i - 1] == 1 - parities[EXHAUSTIVE_TEST_ORDER - i - 1]); - } - } - - /* TODO: keypair/xonly_pubkey tweak tests */ -} - -#endif diff --git a/external/secp256k1/src/modules/extrakeys/tests_impl.h b/external/secp256k1/src/modules/extrakeys/tests_impl.h deleted file mode 100644 index ab4ef4a74b..0000000000 --- a/external/secp256k1/src/modules/extrakeys/tests_impl.h +++ /dev/null @@ -1,483 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_H -#define SECP256K1_MODULE_EXTRAKEYS_TESTS_H - -#include "../../../include/secp256k1_extrakeys.h" - -static void test_xonly_pubkey(void) { - secp256k1_pubkey pk; - secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; - secp256k1_ge pk1; - secp256k1_ge pk2; - secp256k1_fe y; - unsigned char sk[32]; - unsigned char xy_sk[32]; - unsigned char buf32[32]; - unsigned char ones32[32]; - unsigned char zeros64[64] = { 0 }; - int pk_parity; - int i; - - testrand256(sk); - memset(ones32, 0xFF, 32); - testrand256(xy_sk); - CHECK(secp256k1_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - - /* Test xonly_pubkey_from_pubkey */ - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_from_pubkey(CTX, NULL, &pk_parity, &pk)); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk) == 1); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, NULL)); - memset(&pk, 0, sizeof(pk)); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk)); - - /* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */ - memset(sk, 0, sizeof(sk)); - sk[0] = 1; - CHECK(secp256k1_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - CHECK(secp256k1_memcmp_var(&pk, &xonly_pk, sizeof(pk)) == 0); - CHECK(pk_parity == 0); - - /* Choose a secret key such that pubkey and xonly_pubkey are each others - * negation. */ - sk[0] = 2; - CHECK(secp256k1_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - CHECK(secp256k1_memcmp_var(&xonly_pk, &pk, sizeof(xonly_pk)) != 0); - CHECK(pk_parity == 1); - secp256k1_pubkey_load(CTX, &pk1, &pk); - secp256k1_pubkey_load(CTX, &pk2, (secp256k1_pubkey *) &xonly_pk); - CHECK(secp256k1_fe_equal(&pk1.x, &pk2.x) == 1); - secp256k1_fe_negate(&y, &pk2.y, 1); - CHECK(secp256k1_fe_equal(&pk1.y, &y) == 1); - - /* Test xonly_pubkey_serialize and xonly_pubkey_parse */ - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_serialize(CTX, NULL, &xonly_pk)); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_serialize(CTX, buf32, NULL)); - CHECK(secp256k1_memcmp_var(buf32, zeros64, 32) == 0); - { - /* A pubkey filled with 0s will fail to serialize due to pubkey_load - * special casing. */ - secp256k1_xonly_pubkey pk_tmp; - memset(&pk_tmp, 0, sizeof(pk_tmp)); - /* pubkey_load calls illegal callback */ - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_serialize(CTX, buf32, &pk_tmp)); - } - - CHECK(secp256k1_xonly_pubkey_serialize(CTX, buf32, &xonly_pk) == 1); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_parse(CTX, NULL, buf32)); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_parse(CTX, &xonly_pk, NULL)); - - /* Serialization and parse roundtrip */ - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk) == 1); - CHECK(secp256k1_xonly_pubkey_serialize(CTX, buf32, &xonly_pk) == 1); - CHECK(secp256k1_xonly_pubkey_parse(CTX, &xonly_pk_tmp, buf32) == 1); - CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0); - - /* Test parsing invalid field elements */ - memset(&xonly_pk, 1, sizeof(xonly_pk)); - /* Overflowing field element */ - CHECK(secp256k1_xonly_pubkey_parse(CTX, &xonly_pk, ones32) == 0); - CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); - memset(&xonly_pk, 1, sizeof(xonly_pk)); - /* There's no point with x-coordinate 0 on secp256k1 */ - CHECK(secp256k1_xonly_pubkey_parse(CTX, &xonly_pk, zeros64) == 0); - CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); - /* If a random 32-byte string can not be parsed with ec_pubkey_parse - * (because interpreted as X coordinate it does not correspond to a point on - * the curve) then xonly_pubkey_parse should fail as well. */ - for (i = 0; i < COUNT; i++) { - unsigned char rand33[33]; - testrand256(&rand33[1]); - rand33[0] = SECP256K1_TAG_PUBKEY_EVEN; - if (!secp256k1_ec_pubkey_parse(CTX, &pk, rand33, 33)) { - memset(&xonly_pk, 1, sizeof(xonly_pk)); - CHECK(secp256k1_xonly_pubkey_parse(CTX, &xonly_pk, &rand33[1]) == 0); - CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); - } else { - CHECK(secp256k1_xonly_pubkey_parse(CTX, &xonly_pk, &rand33[1]) == 1); - } - } -} - -static void test_xonly_pubkey_comparison(void) { - unsigned char pk1_ser[32] = { - 0x58, 0x84, 0xb3, 0xa2, 0x4b, 0x97, 0x37, 0x88, 0x92, 0x38, 0xa6, 0x26, 0x62, 0x52, 0x35, 0x11, - 0xd0, 0x9a, 0xa1, 0x1b, 0x80, 0x0b, 0x5e, 0x93, 0x80, 0x26, 0x11, 0xef, 0x67, 0x4b, 0xd9, 0x23 - }; - const unsigned char pk2_ser[32] = { - 0xde, 0x36, 0x0e, 0x87, 0x59, 0x8f, 0x3c, 0x01, 0x36, 0x2a, 0x2a, 0xb8, 0xc6, 0xf4, 0x5e, 0x4d, - 0xb2, 0xc2, 0xd5, 0x03, 0xa7, 0xf9, 0xf1, 0x4f, 0xa8, 0xfa, 0x95, 0xa8, 0xe9, 0x69, 0x76, 0x1c - }; - secp256k1_xonly_pubkey pk1; - secp256k1_xonly_pubkey pk2; - - CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk1, pk1_ser) == 1); - CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk2, pk2_ser) == 1); - - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_xonly_pubkey_cmp(CTX, NULL, &pk2) < 0)); - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_xonly_pubkey_cmp(CTX, &pk1, NULL) > 0)); - CHECK(secp256k1_xonly_pubkey_cmp(CTX, &pk1, &pk2) < 0); - CHECK(secp256k1_xonly_pubkey_cmp(CTX, &pk2, &pk1) > 0); - CHECK(secp256k1_xonly_pubkey_cmp(CTX, &pk1, &pk1) == 0); - CHECK(secp256k1_xonly_pubkey_cmp(CTX, &pk2, &pk2) == 0); - memset(&pk1, 0, sizeof(pk1)); /* illegal pubkey */ - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_xonly_pubkey_cmp(CTX, &pk1, &pk2) < 0)); - { - int32_t ecount = 0; - secp256k1_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); - CHECK(secp256k1_xonly_pubkey_cmp(CTX, &pk1, &pk1) == 0); - CHECK(ecount == 2); - secp256k1_context_set_illegal_callback(CTX, NULL, NULL); - } - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_xonly_pubkey_cmp(CTX, &pk2, &pk1) > 0)); -} - -static void test_xonly_pubkey_tweak(void) { - unsigned char zeros64[64] = { 0 }; - unsigned char overflows[32]; - unsigned char sk[32]; - secp256k1_pubkey internal_pk; - secp256k1_xonly_pubkey internal_xonly_pk; - secp256k1_pubkey output_pk; - int pk_parity; - unsigned char tweak[32]; - int i; - - memset(overflows, 0xff, sizeof(overflows)); - testrand256(tweak); - testrand256(sk); - CHECK(secp256k1_ec_pubkey_create(CTX, &internal_pk, sk) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); - - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_tweak_add(CTX, NULL, &internal_xonly_pk, tweak)); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, NULL, tweak)); - /* NULL internal_xonly_pk zeroes the output_pk */ - CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, NULL)); - /* NULL tweak zeroes the output_pk */ - CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); - - /* Invalid tweak zeroes the output_pk */ - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, overflows) == 0); - CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); - - /* A zero tweak is fine */ - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, zeros64) == 1); - - /* Fails if the resulting key was infinity */ - for (i = 0; i < COUNT; i++) { - secp256k1_scalar scalar_tweak; - /* Because sk may be negated before adding, we need to try with tweak = - * sk as well as tweak = -sk. */ - secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); - secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); - secp256k1_scalar_get_b32(tweak, &scalar_tweak); - CHECK((secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, sk) == 0) - || (secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 0)); - CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); - } - - /* Invalid pk with a valid tweak */ - memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk)); - testrand256(tweak); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak)); - CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); -} - -static void test_xonly_pubkey_tweak_check(void) { - unsigned char zeros64[64] = { 0 }; - unsigned char overflows[32]; - unsigned char sk[32]; - secp256k1_pubkey internal_pk; - secp256k1_xonly_pubkey internal_xonly_pk; - secp256k1_pubkey output_pk; - secp256k1_xonly_pubkey output_xonly_pk; - unsigned char output_pk32[32]; - unsigned char buf32[32]; - int pk_parity; - unsigned char tweak[32]; - - memset(overflows, 0xff, sizeof(overflows)); - testrand256(tweak); - testrand256(sk); - CHECK(secp256k1_ec_pubkey_create(CTX, &internal_pk, sk) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); - - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &output_xonly_pk, &pk_parity, &output_pk) == 1); - CHECK(secp256k1_xonly_pubkey_serialize(CTX, buf32, &output_xonly_pk) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_tweak_add_check(CTX, NULL, pk_parity, &internal_xonly_pk, tweak)); - /* invalid pk_parity value */ - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, buf32, 2, &internal_xonly_pk, tweak) == 0); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, NULL, tweak)); - CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, NULL)); - - memset(tweak, 1, sizeof(tweak)); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, NULL, &internal_pk) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &output_xonly_pk, &pk_parity, &output_pk) == 1); - CHECK(secp256k1_xonly_pubkey_serialize(CTX, output_pk32, &output_xonly_pk) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, output_pk32, pk_parity, &internal_xonly_pk, tweak) == 1); - - /* Wrong pk_parity */ - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, output_pk32, !pk_parity, &internal_xonly_pk, tweak) == 0); - /* Wrong public key */ - CHECK(secp256k1_xonly_pubkey_serialize(CTX, buf32, &internal_xonly_pk) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); - - /* Overflowing tweak not allowed */ - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, overflows) == 0); - CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); -} - -/* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1 - * additional pubkeys by calling tweak_add. Then verifies every tweak starting - * from the last pubkey. */ -#define N_PUBKEYS 32 -static void test_xonly_pubkey_tweak_recursive(void) { - unsigned char sk[32]; - secp256k1_pubkey pk[N_PUBKEYS]; - unsigned char pk_serialized[32]; - unsigned char tweak[N_PUBKEYS - 1][32]; - int i; - - testrand256(sk); - CHECK(secp256k1_ec_pubkey_create(CTX, &pk[0], sk) == 1); - /* Add tweaks */ - for (i = 0; i < N_PUBKEYS - 1; i++) { - secp256k1_xonly_pubkey xonly_pk; - memset(tweak[i], i + 1, sizeof(tweak[i])); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk[i]) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &pk[i + 1], &xonly_pk, tweak[i]) == 1); - } - - /* Verify tweaks */ - for (i = N_PUBKEYS - 1; i > 0; i--) { - secp256k1_xonly_pubkey xonly_pk; - int pk_parity; - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk[i]) == 1); - CHECK(secp256k1_xonly_pubkey_serialize(CTX, pk_serialized, &xonly_pk) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk[i - 1]) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, pk_serialized, pk_parity, &xonly_pk, tweak[i - 1]) == 1); - } -} -#undef N_PUBKEYS - -static void test_keypair(void) { - unsigned char sk[32]; - unsigned char sk_tmp[32]; - unsigned char zeros96[96] = { 0 }; - unsigned char overflows[32]; - secp256k1_keypair keypair; - secp256k1_pubkey pk, pk_tmp; - secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; - int pk_parity, pk_parity_tmp; - - CHECK(sizeof(zeros96) == sizeof(keypair)); - memset(overflows, 0xFF, sizeof(overflows)); - - /* Test keypair_create */ - testrand256(sk); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0); - CHECK_ILLEGAL(CTX, secp256k1_keypair_create(CTX, NULL, sk)); - CHECK_ILLEGAL(CTX, secp256k1_keypair_create(CTX, &keypair, NULL)); - CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_keypair_create(STATIC_CTX, &keypair, sk)); - CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); - - /* Invalid secret key */ - CHECK(secp256k1_keypair_create(CTX, &keypair, zeros96) == 0); - CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); - CHECK(secp256k1_keypair_create(CTX, &keypair, overflows) == 0); - CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); - - /* Test keypair_pub */ - testrand256(sk); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_pub(CTX, &pk, &keypair) == 1); - CHECK_ILLEGAL(CTX, secp256k1_keypair_pub(CTX, NULL, &keypair)); - CHECK_ILLEGAL(CTX, secp256k1_keypair_pub(CTX, &pk, NULL)); - CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); - - /* Using an invalid keypair is fine for keypair_pub */ - memset(&keypair, 0, sizeof(keypair)); - CHECK(secp256k1_keypair_pub(CTX, &pk, &keypair) == 1); - CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); - - /* keypair holds the same pubkey as pubkey_create */ - CHECK(secp256k1_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_pub(CTX, &pk_tmp, &keypair) == 1); - CHECK(secp256k1_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0); - - /** Test keypair_xonly_pub **/ - testrand256(sk); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair) == 1); - CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_pub(CTX, NULL, &pk_parity, &keypair)); - CHECK(secp256k1_keypair_xonly_pub(CTX, &xonly_pk, NULL, &keypair) == 1); - CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, NULL)); - CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); - /* Using an invalid keypair will set the xonly_pk to 0 (first reset - * xonly_pk). */ - CHECK(secp256k1_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair) == 1); - memset(&keypair, 0, sizeof(keypair)); - CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair)); - CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); - - /** keypair holds the same xonly pubkey as pubkey_create **/ - CHECK(secp256k1_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_xonly_pub(CTX, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1); - CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0); - CHECK(pk_parity == pk_parity_tmp); - - /* Test keypair_seckey */ - testrand256(sk); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_sec(CTX, sk_tmp, &keypair) == 1); - CHECK_ILLEGAL(CTX, secp256k1_keypair_sec(CTX, NULL, &keypair)); - CHECK_ILLEGAL(CTX, secp256k1_keypair_sec(CTX, sk_tmp, NULL)); - CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); - - /* keypair returns the same seckey it got */ - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_sec(CTX, sk_tmp, &keypair) == 1); - CHECK(secp256k1_memcmp_var(sk, sk_tmp, sizeof(sk_tmp)) == 0); - - - /* Using an invalid keypair is fine for keypair_seckey */ - memset(&keypair, 0, sizeof(keypair)); - CHECK(secp256k1_keypair_sec(CTX, sk_tmp, &keypair) == 1); - CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); -} - -static void test_keypair_add(void) { - unsigned char sk[32]; - secp256k1_keypair keypair; - unsigned char overflows[32]; - unsigned char zeros96[96] = { 0 }; - unsigned char tweak[32]; - int i; - - CHECK(sizeof(zeros96) == sizeof(keypair)); - testrand256(sk); - testrand256(tweak); - memset(overflows, 0xFF, 32); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - - CHECK(secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK(secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK(secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_tweak_add(CTX, NULL, tweak)); - CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_tweak_add(CTX, &keypair, NULL)); - /* This does not set the keypair to zeroes */ - CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0); - - /* Invalid tweak zeroes the keypair */ - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_xonly_tweak_add(CTX, &keypair, overflows) == 0); - CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); - - /* A zero tweak is fine */ - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_xonly_tweak_add(CTX, &keypair, zeros96) == 1); - - /* Fails if the resulting keypair was (sk=0, pk=infinity) */ - for (i = 0; i < COUNT; i++) { - secp256k1_scalar scalar_tweak; - secp256k1_keypair keypair_tmp; - testrand256(sk); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - memcpy(&keypair_tmp, &keypair, sizeof(keypair)); - /* Because sk may be negated before adding, we need to try with tweak = - * sk as well as tweak = -sk. */ - secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); - secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); - secp256k1_scalar_get_b32(tweak, &scalar_tweak); - CHECK((secp256k1_keypair_xonly_tweak_add(CTX, &keypair, sk) == 0) - || (secp256k1_keypair_xonly_tweak_add(CTX, &keypair_tmp, tweak) == 0)); - CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0 - || secp256k1_memcmp_var(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0); - } - - /* Invalid keypair with a valid tweak */ - memset(&keypair, 0, sizeof(keypair)); - testrand256(tweak); - CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak)); - CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); - /* Only seckey part of keypair invalid */ - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - memset(&keypair, 0, 32); - CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak)); - /* Only pubkey part of keypair invalid */ - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - memset(&keypair.data[32], 0, 64); - CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak)); - - /* Check that the keypair_tweak_add implementation is correct */ - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - for (i = 0; i < COUNT; i++) { - secp256k1_xonly_pubkey internal_pk; - secp256k1_xonly_pubkey output_pk; - secp256k1_pubkey output_pk_xy; - secp256k1_pubkey output_pk_expected; - unsigned char pk32[32]; - unsigned char sk32[32]; - int pk_parity; - - testrand256(tweak); - CHECK(secp256k1_keypair_xonly_pub(CTX, &internal_pk, NULL, &keypair) == 1); - CHECK(secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK(secp256k1_keypair_xonly_pub(CTX, &output_pk, &pk_parity, &keypair) == 1); - - /* Check that it passes xonly_pubkey_tweak_add_check */ - CHECK(secp256k1_xonly_pubkey_serialize(CTX, pk32, &output_pk) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, pk32, pk_parity, &internal_pk, tweak) == 1); - - /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */ - CHECK(secp256k1_keypair_pub(CTX, &output_pk_xy, &keypair) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk_expected, &internal_pk, tweak) == 1); - CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); - - /* Check that the secret key in the keypair is tweaked correctly */ - CHECK(secp256k1_keypair_sec(CTX, sk32, &keypair) == 1); - CHECK(secp256k1_ec_pubkey_create(CTX, &output_pk_expected, sk32) == 1); - CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); - } -} - -static void run_extrakeys_tests(void) { - /* xonly key test cases */ - test_xonly_pubkey(); - test_xonly_pubkey_tweak(); - test_xonly_pubkey_tweak_check(); - test_xonly_pubkey_tweak_recursive(); - test_xonly_pubkey_comparison(); - - /* keypair tests */ - test_keypair(); - test_keypair_add(); -} - -#endif diff --git a/external/secp256k1/src/modules/musig/Makefile.am.include b/external/secp256k1/src/modules/musig/Makefile.am.include deleted file mode 100644 index 796443c93b..0000000000 --- a/external/secp256k1/src/modules/musig/Makefile.am.include +++ /dev/null @@ -1,8 +0,0 @@ -include_HEADERS += include/secp256k1_musig.h -noinst_HEADERS += src/modules/musig/main_impl.h -noinst_HEADERS += src/modules/musig/keyagg.h -noinst_HEADERS += src/modules/musig/keyagg_impl.h -noinst_HEADERS += src/modules/musig/session.h -noinst_HEADERS += src/modules/musig/session_impl.h -noinst_HEADERS += src/modules/musig/tests_impl.h -noinst_HEADERS += src/modules/musig/vectors.h diff --git a/external/secp256k1/src/modules/musig/keyagg.h b/external/secp256k1/src/modules/musig/keyagg.h deleted file mode 100644 index a0b37252f8..0000000000 --- a/external/secp256k1/src/modules/musig/keyagg.h +++ /dev/null @@ -1,32 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_KEYAGG_H -#define SECP256K1_MODULE_MUSIG_KEYAGG_H - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_musig.h" - -#include "../../group.h" -#include "../../scalar.h" - -typedef struct { - secp256k1_ge pk; - /* If there is no "second" public key, second_pk is set to the point at - * infinity */ - secp256k1_ge second_pk; - unsigned char pks_hash[32]; - /* tweak is identical to value tacc[v] in the specification. */ - secp256k1_scalar tweak; - /* parity_acc corresponds to (1 - gacc[v])/2 in the spec. So if gacc[v] is - * -1, parity_acc is 1. Otherwise, parity_acc is 0. */ - int parity_acc; -} secp256k1_keyagg_cache_internal; - -static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache); - -static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); - -#endif diff --git a/external/secp256k1/src/modules/musig/keyagg_impl.h b/external/secp256k1/src/modules/musig/keyagg_impl.h deleted file mode 100644 index 0db4fce859..0000000000 --- a/external/secp256k1/src/modules/musig/keyagg_impl.h +++ /dev/null @@ -1,291 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H -#define SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H - -#include - -#include "keyagg.h" -#include "../../eckey.h" -#include "../../ecmult.h" -#include "../../field.h" -#include "../../group.h" -#include "../../hash.h" -#include "../../util.h" - -static const unsigned char secp256k1_musig_keyagg_cache_magic[4] = { 0xf4, 0xad, 0xbb, 0xdf }; - -/* A keyagg cache consists of - * - 4 byte magic set during initialization to allow detecting an uninitialized - * object. - * - 64 byte aggregate (and potentially tweaked) public key - * - 64 byte "second" public key (set to the point at infinity if not present) - * - 32 byte hash of all public keys - * - 1 byte the parity of the internal key (if tweaked, otherwise 0) - * - 32 byte tweak - */ -/* Requires that cache_i->pk is not infinity. */ -static void secp256k1_keyagg_cache_save(secp256k1_musig_keyagg_cache *cache, const secp256k1_keyagg_cache_internal *cache_i) { - unsigned char *ptr = cache->data; - memcpy(ptr, secp256k1_musig_keyagg_cache_magic, 4); - ptr += 4; - secp256k1_ge_to_bytes(ptr, &cache_i->pk); - ptr += 64; - secp256k1_ge_to_bytes_ext(ptr, &cache_i->second_pk); - ptr += 64; - memcpy(ptr, cache_i->pks_hash, 32); - ptr += 32; - *ptr = cache_i->parity_acc; - ptr += 1; - secp256k1_scalar_get_b32(ptr, &cache_i->tweak); -} - -static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache) { - const unsigned char *ptr = cache->data; - ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_keyagg_cache_magic, 4) == 0); - ptr += 4; - secp256k1_ge_from_bytes(&cache_i->pk, ptr); - ptr += 64; - secp256k1_ge_from_bytes_ext(&cache_i->second_pk, ptr); - ptr += 64; - memcpy(cache_i->pks_hash, ptr, 32); - ptr += 32; - cache_i->parity_acc = *ptr & 1; - ptr += 1; - secp256k1_scalar_set_b32(&cache_i->tweak, ptr, NULL); - return 1; -} - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */ -static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - - sha->s[0] = 0xb399d5e0ul; - sha->s[1] = 0xc8fff302ul; - sha->s[2] = 0x6badac71ul; - sha->s[3] = 0x07c5b7f1ul; - sha->s[4] = 0x9701e2eful; - sha->s[5] = 0x2a72ecf8ul; - sha->s[6] = 0x201a4c7bul; - sha->s[7] = 0xab148a38ul; - sha->bytes = 64; -} - -/* Computes pks_hash = tagged_hash(pk[0], ..., pk[np-1]) */ -static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsigned char *pks_hash, const secp256k1_pubkey * const* pks, size_t np) { - secp256k1_sha256 sha; - size_t i; - - secp256k1_musig_keyagglist_sha256(&sha); - for (i = 0; i < np; i++) { - unsigned char ser[33]; - size_t ser_len = sizeof(ser); - if (!secp256k1_ec_pubkey_serialize(ctx, ser, &ser_len, pks[i], SECP256K1_EC_COMPRESSED)) { - return 0; - } - VERIFY_CHECK(ser_len == sizeof(ser)); - secp256k1_sha256_write(&sha, ser, sizeof(ser)); - } - secp256k1_sha256_finalize(&sha, pks_hash); - return 1; -} - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */ -static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - - sha->s[0] = 0x6ef02c5aul; - sha->s[1] = 0x06a480deul; - sha->s[2] = 0x1f298665ul; - sha->s[3] = 0x1d1134f2ul; - sha->s[4] = 0x56a0b063ul; - sha->s[5] = 0x52da4147ul; - sha->s[6] = 0xf280d9d4ul; - sha->s[7] = 0x4484be15ul; - sha->bytes = 64; -} - -/* Compute KeyAgg coefficient which is constant 1 for the second pubkey and - * otherwise tagged_hash(pks_hash, pk) where pks_hash is the hash of public keys. - * second_pk is the point at infinity in case there is no second_pk. Assumes - * that pk is not the point at infinity and that the Y-coordinates of pk and - * second_pk are normalized. */ -static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsigned char *pks_hash, secp256k1_ge *pk, const secp256k1_ge *second_pk) { - VERIFY_CHECK(!secp256k1_ge_is_infinity(pk)); - - if (!secp256k1_ge_is_infinity(second_pk) - && secp256k1_ge_eq_var(pk, second_pk)) { - secp256k1_scalar_set_int(r, 1); - } else { - secp256k1_sha256 sha; - unsigned char buf[33]; - size_t buflen = sizeof(buf); - int ret; - secp256k1_musig_keyaggcoef_sha256(&sha); - secp256k1_sha256_write(&sha, pks_hash, 32); - ret = secp256k1_eckey_pubkey_serialize(pk, buf, &buflen, 1); -#ifdef VERIFY - /* Serialization does not fail since the pk is not the point at infinity - * (according to this function's precondition). */ - VERIFY_CHECK(ret && buflen == sizeof(buf)); -#else - (void) ret; -#endif - secp256k1_sha256_write(&sha, buf, sizeof(buf)); - secp256k1_sha256_finalize(&sha, buf); - secp256k1_scalar_set_b32(r, buf, NULL); - } -} - -/* Assumes that pk is not the point at infinity and that the Y-coordinates of pk - * and cache_i->second_pk are normalized. */ -static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk) { - secp256k1_musig_keyaggcoef_internal(r, cache_i->pks_hash, pk, &cache_i->second_pk); -} - -typedef struct { - const secp256k1_context *ctx; - /* pks_hash is the hash of the public keys */ - unsigned char pks_hash[32]; - const secp256k1_pubkey * const* pks; - secp256k1_ge second_pk; -} secp256k1_musig_pubkey_agg_ecmult_data; - -/* Callback for batch EC multiplication to compute keyaggcoef_0*P0 + keyaggcoef_1*P1 + ... */ -static int secp256k1_musig_pubkey_agg_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) { - secp256k1_musig_pubkey_agg_ecmult_data *ctx = (secp256k1_musig_pubkey_agg_ecmult_data *) data; - int ret; - ret = secp256k1_pubkey_load(ctx->ctx, pt, ctx->pks[idx]); -#ifdef VERIFY - /* pubkey_load can't fail because the same pks have already been loaded in - * `musig_compute_pks_hash` (and we test this). */ - VERIFY_CHECK(ret); -#else - (void) ret; -#endif - secp256k1_musig_keyaggcoef_internal(sc, ctx->pks_hash, pt, &ctx->second_pk); - return 1; -} - -int secp256k1_musig_pubkey_agg(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_pubkey * const* pubkeys, size_t n_pubkeys) { - secp256k1_musig_pubkey_agg_ecmult_data ecmult_data; - secp256k1_gej pkj; - secp256k1_ge pkp; - size_t i; - - VERIFY_CHECK(ctx != NULL); - if (agg_pk != NULL) { - memset(agg_pk, 0, sizeof(*agg_pk)); - } - ARG_CHECK(pubkeys != NULL); - ARG_CHECK(n_pubkeys > 0); - - ecmult_data.ctx = ctx; - ecmult_data.pks = pubkeys; - - secp256k1_ge_set_infinity(&ecmult_data.second_pk); - for (i = 1; i < n_pubkeys; i++) { - if (secp256k1_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) { - secp256k1_ge pk; - if (!secp256k1_pubkey_load(ctx, &pk, pubkeys[i])) { - return 0; - } - ecmult_data.second_pk = pk; - break; - } - } - - if (!secp256k1_musig_compute_pks_hash(ctx, ecmult_data.pks_hash, pubkeys, n_pubkeys)) { - return 0; - } - /* TODO: actually use optimized ecmult_multi algorithms by providing a - * scratch space */ - if (!secp256k1_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, secp256k1_musig_pubkey_agg_callback, (void *) &ecmult_data, n_pubkeys)) { - /* In order to reach this line with the current implementation of - * ecmult_multi_var one would need to provide a callback that can - * fail. */ - return 0; - } - secp256k1_ge_set_gej(&pkp, &pkj); - secp256k1_fe_normalize_var(&pkp.y); - /* The resulting public key is infinity with negligible probability */ - VERIFY_CHECK(!secp256k1_ge_is_infinity(&pkp)); - if (keyagg_cache != NULL) { - secp256k1_keyagg_cache_internal cache_i = { 0 }; - cache_i.pk = pkp; - cache_i.second_pk = ecmult_data.second_pk; - memcpy(cache_i.pks_hash, ecmult_data.pks_hash, sizeof(cache_i.pks_hash)); - secp256k1_keyagg_cache_save(keyagg_cache, &cache_i); - } - - if (agg_pk != NULL) { - secp256k1_extrakeys_ge_even_y(&pkp); - secp256k1_xonly_pubkey_save(agg_pk, &pkp); - } - return 1; -} - -int secp256k1_musig_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *agg_pk, const secp256k1_musig_keyagg_cache *keyagg_cache) { - secp256k1_keyagg_cache_internal cache_i; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(agg_pk != NULL); - memset(agg_pk, 0, sizeof(*agg_pk)); - ARG_CHECK(keyagg_cache != NULL); - - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - secp256k1_pubkey_save(agg_pk, &cache_i.pk); - return 1; -} - -static int secp256k1_musig_pubkey_tweak_add_internal(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32, int xonly) { - secp256k1_keyagg_cache_internal cache_i; - int overflow = 0; - secp256k1_scalar tweak; - - VERIFY_CHECK(ctx != NULL); - if (output_pubkey != NULL) { - memset(output_pubkey, 0, sizeof(*output_pubkey)); - } - ARG_CHECK(keyagg_cache != NULL); - ARG_CHECK(tweak32 != NULL); - - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - secp256k1_scalar_set_b32(&tweak, tweak32, &overflow); - if (overflow) { - return 0; - } - if (xonly && secp256k1_extrakeys_ge_even_y(&cache_i.pk)) { - cache_i.parity_acc ^= 1; - secp256k1_scalar_negate(&cache_i.tweak, &cache_i.tweak); - } - secp256k1_scalar_add(&cache_i.tweak, &cache_i.tweak, &tweak); - if (!secp256k1_eckey_pubkey_tweak_add(&cache_i.pk, &tweak)) { - return 0; - } - /* eckey_pubkey_tweak_add fails if cache_i.pk is infinity */ - VERIFY_CHECK(!secp256k1_ge_is_infinity(&cache_i.pk)); - secp256k1_keyagg_cache_save(keyagg_cache, &cache_i); - if (output_pubkey != NULL) { - secp256k1_pubkey_save(output_pubkey, &cache_i.pk); - } - return 1; -} - -int secp256k1_musig_pubkey_ec_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) { - return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 0); -} - -int secp256k1_musig_pubkey_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) { - return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 1); -} - -#endif diff --git a/external/secp256k1/src/modules/musig/main_impl.h b/external/secp256k1/src/modules/musig/main_impl.h deleted file mode 100644 index a1311e4191..0000000000 --- a/external/secp256k1/src/modules/musig/main_impl.h +++ /dev/null @@ -1,12 +0,0 @@ -/********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_MAIN_H -#define SECP256K1_MODULE_MUSIG_MAIN_H - -#include "keyagg_impl.h" -#include "session_impl.h" - -#endif diff --git a/external/secp256k1/src/modules/musig/session.h b/external/secp256k1/src/modules/musig/session.h deleted file mode 100644 index d6d76bc6c1..0000000000 --- a/external/secp256k1/src/modules/musig/session.h +++ /dev/null @@ -1,24 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_SESSION_H -#define SECP256K1_MODULE_MUSIG_SESSION_H - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_musig.h" - -#include "../../scalar.h" - -typedef struct { - int fin_nonce_parity; - unsigned char fin_nonce[32]; - secp256k1_scalar noncecoef; - secp256k1_scalar challenge; - secp256k1_scalar s_part; -} secp256k1_musig_session_internal; - -static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session); - -#endif diff --git a/external/secp256k1/src/modules/musig/session_impl.h b/external/secp256k1/src/modules/musig/session_impl.h deleted file mode 100644 index dde3808582..0000000000 --- a/external/secp256k1/src/modules/musig/session_impl.h +++ /dev/null @@ -1,816 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_SESSION_IMPL_H -#define SECP256K1_MODULE_MUSIG_SESSION_IMPL_H - -#include - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_extrakeys.h" -#include "../../../include/secp256k1_musig.h" - -#include "keyagg.h" -#include "session.h" -#include "../../eckey.h" -#include "../../hash.h" -#include "../../scalar.h" -#include "../../util.h" - -/* Outputs 33 zero bytes if the given group element is the point at infinity and - * otherwise outputs the compressed serialization */ -static void secp256k1_musig_ge_serialize_ext(unsigned char *out33, secp256k1_ge* ge) { - if (secp256k1_ge_is_infinity(ge)) { - memset(out33, 0, 33); - } else { - int ret; - size_t size = 33; - ret = secp256k1_eckey_pubkey_serialize(ge, out33, &size, 1); -#ifdef VERIFY - /* Serialize must succeed because the point is not at infinity */ - VERIFY_CHECK(ret && size == 33); -#else - (void) ret; -#endif - } -} - -/* Outputs the point at infinity if the given byte array is all zero, otherwise - * attempts to parse compressed point serialization. */ -static int secp256k1_musig_ge_parse_ext(secp256k1_ge* ge, const unsigned char *in33) { - unsigned char zeros[33] = { 0 }; - - if (secp256k1_memcmp_var(in33, zeros, sizeof(zeros)) == 0) { - secp256k1_ge_set_infinity(ge); - return 1; - } - if (!secp256k1_eckey_pubkey_parse(ge, in33, 33)) { - return 0; - } - return secp256k1_ge_is_in_correct_subgroup(ge); -} - -static const unsigned char secp256k1_musig_secnonce_magic[4] = { 0x22, 0x0e, 0xdc, 0xf1 }; - -static void secp256k1_musig_secnonce_save(secp256k1_musig_secnonce *secnonce, const secp256k1_scalar *k, const secp256k1_ge *pk) { - memcpy(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4); - secp256k1_scalar_get_b32(&secnonce->data[4], &k[0]); - secp256k1_scalar_get_b32(&secnonce->data[36], &k[1]); - secp256k1_ge_to_bytes(&secnonce->data[68], pk); -} - -static int secp256k1_musig_secnonce_load(const secp256k1_context* ctx, secp256k1_scalar *k, secp256k1_ge *pk, const secp256k1_musig_secnonce *secnonce) { - int is_zero; - ARG_CHECK(secp256k1_memcmp_var(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4) == 0); - /* We make very sure that the nonce isn't invalidated by checking the values - * in addition to the magic. */ - is_zero = secp256k1_is_zero_array(&secnonce->data[4], 2 * 32); - secp256k1_declassify(ctx, &is_zero, sizeof(is_zero)); - ARG_CHECK(!is_zero); - - secp256k1_scalar_set_b32(&k[0], &secnonce->data[4], NULL); - secp256k1_scalar_set_b32(&k[1], &secnonce->data[36], NULL); - secp256k1_ge_from_bytes(pk, &secnonce->data[68]); - return 1; -} - -/* If flag is true, invalidate the secnonce; otherwise leave it. Constant-time. */ -static void secp256k1_musig_secnonce_invalidate(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, int flag) { - secp256k1_memczero(secnonce->data, sizeof(secnonce->data), flag); - /* The flag argument is usually classified. So, the line above makes the - * magic and public key classified. However, we need both to be - * declassified. Note that we don't declassify the entire object, because if - * flag is 0, then k[0] and k[1] have not been zeroed. */ - secp256k1_declassify(ctx, secnonce->data, sizeof(secp256k1_musig_secnonce_magic)); - secp256k1_declassify(ctx, &secnonce->data[68], 64); -} - -static const unsigned char secp256k1_musig_pubnonce_magic[4] = { 0xf5, 0x7a, 0x3d, 0xa0 }; - -/* Saves two group elements into a pubnonce. Requires that none of the provided - * group elements is infinity. */ -static void secp256k1_musig_pubnonce_save(secp256k1_musig_pubnonce* nonce, const secp256k1_ge* ges) { - int i; - memcpy(&nonce->data[0], secp256k1_musig_pubnonce_magic, 4); - for (i = 0; i < 2; i++) { - secp256k1_ge_to_bytes(nonce->data + 4+64*i, &ges[i]); - } -} - -/* Loads two group elements from a pubnonce. Returns 1 unless the nonce wasn't - * properly initialized */ -static int secp256k1_musig_pubnonce_load(const secp256k1_context* ctx, secp256k1_ge* ges, const secp256k1_musig_pubnonce* nonce) { - int i; - - ARG_CHECK(secp256k1_memcmp_var(&nonce->data[0], secp256k1_musig_pubnonce_magic, 4) == 0); - for (i = 0; i < 2; i++) { - secp256k1_ge_from_bytes(&ges[i], nonce->data + 4 + 64*i); - } - return 1; -} - -static const unsigned char secp256k1_musig_aggnonce_magic[4] = { 0xa8, 0xb7, 0xe4, 0x67 }; - -static void secp256k1_musig_aggnonce_save(secp256k1_musig_aggnonce* nonce, const secp256k1_ge* ges) { - int i; - memcpy(&nonce->data[0], secp256k1_musig_aggnonce_magic, 4); - for (i = 0; i < 2; i++) { - secp256k1_ge_to_bytes_ext(&nonce->data[4 + 64*i], &ges[i]); - } -} - -static int secp256k1_musig_aggnonce_load(const secp256k1_context* ctx, secp256k1_ge* ges, const secp256k1_musig_aggnonce* nonce) { - int i; - - ARG_CHECK(secp256k1_memcmp_var(&nonce->data[0], secp256k1_musig_aggnonce_magic, 4) == 0); - for (i = 0; i < 2; i++) { - secp256k1_ge_from_bytes_ext(&ges[i], &nonce->data[4 + 64*i]); - } - return 1; -} - -static const unsigned char secp256k1_musig_session_cache_magic[4] = { 0x9d, 0xed, 0xe9, 0x17 }; - -/* A session consists of - * - 4 byte session cache magic - * - 1 byte the parity of the final nonce - * - 32 byte serialized x-only final nonce - * - 32 byte nonce coefficient b - * - 32 byte signature challenge hash e - * - 32 byte scalar s that is added to the partial signatures of the signers - */ -static void secp256k1_musig_session_save(secp256k1_musig_session *session, const secp256k1_musig_session_internal *session_i) { - unsigned char *ptr = session->data; - - memcpy(ptr, secp256k1_musig_session_cache_magic, 4); - ptr += 4; - *ptr = session_i->fin_nonce_parity; - ptr += 1; - memcpy(ptr, session_i->fin_nonce, 32); - ptr += 32; - secp256k1_scalar_get_b32(ptr, &session_i->noncecoef); - ptr += 32; - secp256k1_scalar_get_b32(ptr, &session_i->challenge); - ptr += 32; - secp256k1_scalar_get_b32(ptr, &session_i->s_part); -} - -static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session) { - const unsigned char *ptr = session->data; - - ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_session_cache_magic, 4) == 0); - ptr += 4; - session_i->fin_nonce_parity = *ptr; - ptr += 1; - memcpy(session_i->fin_nonce, ptr, 32); - ptr += 32; - secp256k1_scalar_set_b32(&session_i->noncecoef, ptr, NULL); - ptr += 32; - secp256k1_scalar_set_b32(&session_i->challenge, ptr, NULL); - ptr += 32; - secp256k1_scalar_set_b32(&session_i->s_part, ptr, NULL); - return 1; -} - -static const unsigned char secp256k1_musig_partial_sig_magic[4] = { 0xeb, 0xfb, 0x1a, 0x32 }; - -static void secp256k1_musig_partial_sig_save(secp256k1_musig_partial_sig* sig, secp256k1_scalar *s) { - memcpy(&sig->data[0], secp256k1_musig_partial_sig_magic, 4); - secp256k1_scalar_get_b32(&sig->data[4], s); -} - -static int secp256k1_musig_partial_sig_load(const secp256k1_context* ctx, secp256k1_scalar *s, const secp256k1_musig_partial_sig* sig) { - int overflow; - - ARG_CHECK(secp256k1_memcmp_var(&sig->data[0], secp256k1_musig_partial_sig_magic, 4) == 0); - secp256k1_scalar_set_b32(s, &sig->data[4], &overflow); - /* Parsed signatures can not overflow */ - VERIFY_CHECK(!overflow); - return 1; -} - -int secp256k1_musig_pubnonce_parse(const secp256k1_context* ctx, secp256k1_musig_pubnonce* nonce, const unsigned char *in66) { - secp256k1_ge ges[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(nonce != NULL); - ARG_CHECK(in66 != NULL); - - for (i = 0; i < 2; i++) { - if (!secp256k1_eckey_pubkey_parse(&ges[i], &in66[33*i], 33)) { - return 0; - } - if (!secp256k1_ge_is_in_correct_subgroup(&ges[i])) { - return 0; - } - } - secp256k1_musig_pubnonce_save(nonce, ges); - return 1; -} - -int secp256k1_musig_pubnonce_serialize(const secp256k1_context* ctx, unsigned char *out66, const secp256k1_musig_pubnonce* nonce) { - secp256k1_ge ges[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(out66 != NULL); - memset(out66, 0, 66); - ARG_CHECK(nonce != NULL); - - if (!secp256k1_musig_pubnonce_load(ctx, ges, nonce)) { - return 0; - } - for (i = 0; i < 2; i++) { - int ret; - size_t size = 33; - ret = secp256k1_eckey_pubkey_serialize(&ges[i], &out66[33*i], &size, 1); -#ifdef VERIFY - /* serialize must succeed because the point was just loaded */ - VERIFY_CHECK(ret && size == 33); -#else - (void) ret; -#endif - } - return 1; -} - -int secp256k1_musig_aggnonce_parse(const secp256k1_context* ctx, secp256k1_musig_aggnonce* nonce, const unsigned char *in66) { - secp256k1_ge ges[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(nonce != NULL); - ARG_CHECK(in66 != NULL); - - for (i = 0; i < 2; i++) { - if (!secp256k1_musig_ge_parse_ext(&ges[i], &in66[33*i])) { - return 0; - } - } - secp256k1_musig_aggnonce_save(nonce, ges); - return 1; -} - -int secp256k1_musig_aggnonce_serialize(const secp256k1_context* ctx, unsigned char *out66, const secp256k1_musig_aggnonce* nonce) { - secp256k1_ge ges[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(out66 != NULL); - memset(out66, 0, 66); - ARG_CHECK(nonce != NULL); - - if (!secp256k1_musig_aggnonce_load(ctx, ges, nonce)) { - return 0; - } - for (i = 0; i < 2; i++) { - secp256k1_musig_ge_serialize_ext(&out66[33*i], &ges[i]); - } - return 1; -} - -int secp256k1_musig_partial_sig_parse(const secp256k1_context* ctx, secp256k1_musig_partial_sig* sig, const unsigned char *in32) { - secp256k1_scalar tmp; - int overflow; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(in32 != NULL); - - /* Ensure that using the signature will fail if parsing fails (and the user - * doesn't check the return value). */ - memset(sig, 0, sizeof(*sig)); - - secp256k1_scalar_set_b32(&tmp, in32, &overflow); - if (overflow) { - return 0; - } - secp256k1_musig_partial_sig_save(sig, &tmp); - return 1; -} - -int secp256k1_musig_partial_sig_serialize(const secp256k1_context* ctx, unsigned char *out32, const secp256k1_musig_partial_sig* sig) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(out32 != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(secp256k1_memcmp_var(&sig->data[0], secp256k1_musig_partial_sig_magic, 4) == 0); - - memcpy(out32, &sig->data[4], 32); - return 1; -} - -/* Write optional inputs into the hash */ -static void secp256k1_nonce_function_musig_helper(secp256k1_sha256 *sha, unsigned int prefix_size, const unsigned char *data, unsigned char len) { - unsigned char zero[7] = { 0 }; - /* The spec requires length prefixes to be between 1 and 8 bytes - * (inclusive) */ - VERIFY_CHECK(prefix_size >= 1 && prefix_size <= 8); - /* Since the length of all input data fits in a byte, we can always pad the - * length prefix with prefix_size - 1 zero bytes. */ - secp256k1_sha256_write(sha, zero, prefix_size - 1); - if (data != NULL) { - secp256k1_sha256_write(sha, &len, 1); - secp256k1_sha256_write(sha, data, len); - } else { - len = 0; - secp256k1_sha256_write(sha, &len, 1); - } -} - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("MuSig/aux")||SHA256("MuSig/aux"). */ -static void secp256k1_nonce_function_musig_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0xa19e884bul; - sha->s[1] = 0xf463fe7eul; - sha->s[2] = 0x2f18f9a2ul; - sha->s[3] = 0xbeb0f9fful; - sha->s[4] = 0x0f37e8b0ul; - sha->s[5] = 0x06ebd26ful; - sha->s[6] = 0xe3b243d2ul; - sha->s[7] = 0x522fb150ul; - sha->bytes = 64; -} - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("MuSig/nonce")||SHA256("MuSig/nonce"). */ -static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x07101b64ul; - sha->s[1] = 0x18003414ul; - sha->s[2] = 0x0391bc43ul; - sha->s[3] = 0x0e6258eeul; - sha->s[4] = 0x29d26b72ul; - sha->s[5] = 0x8343937eul; - sha->s[6] = 0xb7a0a4fbul; - sha->s[7] = 0xff568a30ul; - sha->bytes = 64; -} - -static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { - secp256k1_sha256 sha; - unsigned char rand[32]; - unsigned char i; - unsigned char msg_present; - - if (seckey32 != NULL) { - secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); - secp256k1_sha256_write(&sha, session_secrand, 32); - secp256k1_sha256_finalize(&sha, rand); - for (i = 0; i < 32; i++) { - rand[i] ^= seckey32[i]; - } - } else { - memcpy(rand, session_secrand, sizeof(rand)); - } - - secp256k1_nonce_function_musig_sha256_tagged(&sha); - secp256k1_sha256_write(&sha, rand, sizeof(rand)); - secp256k1_nonce_function_musig_helper(&sha, 1, pk33, 33); - secp256k1_nonce_function_musig_helper(&sha, 1, agg_pk32, 32); - msg_present = msg32 != NULL; - secp256k1_sha256_write(&sha, &msg_present, 1); - if (msg_present) { - secp256k1_nonce_function_musig_helper(&sha, 8, msg32, 32); - } - secp256k1_nonce_function_musig_helper(&sha, 4, extra_input32, 32); - - for (i = 0; i < 2; i++) { - unsigned char buf[32]; - secp256k1_sha256 sha_tmp = sha; - secp256k1_sha256_write(&sha_tmp, &i, 1); - secp256k1_sha256_finalize(&sha_tmp, buf); - secp256k1_scalar_set_b32(&k[i], buf, NULL); - - /* Attempt to erase secret data */ - secp256k1_memclear(buf, sizeof(buf)); - secp256k1_sha256_clear(&sha_tmp); - } - secp256k1_memclear(rand, sizeof(rand)); - secp256k1_sha256_clear(&sha); -} - -static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { - secp256k1_scalar k[2]; - secp256k1_ge nonce_pts[2]; - int i; - unsigned char pk_ser[33]; - size_t pk_ser_len = sizeof(pk_ser); - unsigned char aggpk_ser[32]; - unsigned char *aggpk_ser_ptr = NULL; - secp256k1_ge pk; - int pk_serialize_success; - int ret = 1; - - ARG_CHECK(pubnonce != NULL); - memset(pubnonce, 0, sizeof(*pubnonce)); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - - /* Check that the seckey is valid to be able to sign for it later. */ - if (seckey != NULL) { - secp256k1_scalar sk; - ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey); - secp256k1_scalar_clear(&sk); - } - - if (keyagg_cache != NULL) { - secp256k1_keyagg_cache_internal cache_i; - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - /* The loaded point cache_i.pk can not be the point at infinity. */ - secp256k1_fe_get_b32(aggpk_ser, &cache_i.pk.x); - aggpk_ser_ptr = aggpk_ser; - } - if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { - return 0; - } - pk_serialize_success = secp256k1_eckey_pubkey_serialize(&pk, pk_ser, &pk_ser_len, 1); - -#ifdef VERIFY - /* A pubkey cannot be the point at infinity */ - VERIFY_CHECK(pk_serialize_success); - VERIFY_CHECK(pk_ser_len == sizeof(pk_ser)); -#else - (void) pk_serialize_success; -#endif - - secp256k1_nonce_function_musig(k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); - VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0])); - VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1])); - secp256k1_musig_secnonce_save(secnonce, k, &pk); - secp256k1_musig_secnonce_invalidate(ctx, secnonce, !ret); - - for (i = 0; i < 2; i++) { - secp256k1_gej nonce_ptj; - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj, &k[i]); - secp256k1_ge_set_gej(&nonce_pts[i], &nonce_ptj); - secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts[i])); - secp256k1_scalar_clear(&k[i]); - secp256k1_gej_clear(&nonce_ptj); - } - /* None of the nonce_pts will be infinity because k != 0 with overwhelming - * probability */ - secp256k1_musig_pubnonce_save(pubnonce, nonce_pts); - return ret; -} - -int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, unsigned char *session_secrand32, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { - int ret = 1; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secnonce != NULL); - memset(secnonce, 0, sizeof(*secnonce)); - ARG_CHECK(session_secrand32 != NULL); - - /* Check in constant time that the session_secrand32 is not 0 as a - * defense-in-depth measure that may protect against a faulty RNG. */ - ret &= !secp256k1_is_zero_array(session_secrand32, 32); - - /* We can declassify because branching on ret is only relevant when this - * function called with an invalid session_secrand32 argument */ - secp256k1_declassify(ctx, &ret, sizeof(ret)); - if (ret == 0) { - secp256k1_musig_secnonce_invalidate(ctx, secnonce, 1); - return 0; - } - - ret &= secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, session_secrand32, seckey, pubkey, msg32, keyagg_cache, extra_input32); - - /* Set the session_secrand32 buffer to zero to prevent the caller from using - * nonce_gen multiple times with the same buffer. */ - secp256k1_memczero(session_secrand32, 32, ret); - return ret; -} - -int secp256k1_musig_nonce_gen_counter(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, uint64_t nonrepeating_cnt, const secp256k1_keypair *keypair, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { - unsigned char buf[32] = { 0 }; - unsigned char seckey[32]; - secp256k1_pubkey pubkey; - int ret; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secnonce != NULL); - memset(secnonce, 0, sizeof(*secnonce)); - ARG_CHECK(keypair != NULL); - - secp256k1_write_be64(buf, nonrepeating_cnt); - /* keypair_sec and keypair_pub do not fail if the arguments are not NULL */ - ret = secp256k1_keypair_sec(ctx, seckey, keypair); - VERIFY_CHECK(ret); - ret = secp256k1_keypair_pub(ctx, &pubkey, keypair); - VERIFY_CHECK(ret); -#ifndef VERIFY - (void) ret; -#endif - - if (!secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32)) { - return 0; - } - secp256k1_memclear(seckey, sizeof(seckey)); - return 1; -} - -static int secp256k1_musig_sum_pubnonces(const secp256k1_context* ctx, secp256k1_gej *summed_pubnonces, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { - size_t i; - int j; - - secp256k1_gej_set_infinity(&summed_pubnonces[0]); - secp256k1_gej_set_infinity(&summed_pubnonces[1]); - - for (i = 0; i < n_pubnonces; i++) { - secp256k1_ge nonce_pts[2]; - if (!secp256k1_musig_pubnonce_load(ctx, nonce_pts, pubnonces[i])) { - return 0; - } - for (j = 0; j < 2; j++) { - secp256k1_gej_add_ge_var(&summed_pubnonces[j], &summed_pubnonces[j], &nonce_pts[j], NULL); - } - } - return 1; -} - -int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggnonce *aggnonce, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { - secp256k1_gej aggnonce_ptsj[2]; - secp256k1_ge aggnonce_pts[2]; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(aggnonce != NULL); - ARG_CHECK(pubnonces != NULL); - ARG_CHECK(n_pubnonces > 0); - - if (!secp256k1_musig_sum_pubnonces(ctx, aggnonce_ptsj, pubnonces, n_pubnonces)) { - return 0; - } - secp256k1_ge_set_all_gej_var(aggnonce_pts, aggnonce_ptsj, 2); - secp256k1_musig_aggnonce_save(aggnonce, aggnonce_pts); - return 1; -} - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("MuSig/noncecoef")||SHA256("MuSig/noncecoef"). */ -static void secp256k1_musig_compute_noncehash_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x2c7d5a45ul; - sha->s[1] = 0x06bf7e53ul; - sha->s[2] = 0x89be68a6ul; - sha->s[3] = 0x971254c0ul; - sha->s[4] = 0x60ac12d2ul; - sha->s[5] = 0x72846dcdul; - sha->s[6] = 0x6c81212ful; - sha->s[7] = 0xde7a2500ul; - sha->bytes = 64; -} - -/* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */ -static void secp256k1_musig_compute_noncehash(unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) { - unsigned char buf[33]; - secp256k1_sha256 sha; - int i; - - secp256k1_musig_compute_noncehash_sha256_tagged(&sha); - for (i = 0; i < 2; i++) { - secp256k1_musig_ge_serialize_ext(buf, &aggnonce[i]); - secp256k1_sha256_write(&sha, buf, sizeof(buf)); - } - secp256k1_sha256_write(&sha, agg_pk32, 32); - secp256k1_sha256_write(&sha, msg, 32); - secp256k1_sha256_finalize(&sha, noncehash); -} - -/* out_nonce = nonce_pts[0] + b*nonce_pts[1] */ -static void secp256k1_effective_nonce(secp256k1_gej *out_nonce, const secp256k1_ge *nonce_pts, const secp256k1_scalar *b) { - secp256k1_gej tmp; - - secp256k1_gej_set_ge(&tmp, &nonce_pts[1]); - secp256k1_ecmult(out_nonce, &tmp, b, NULL); - secp256k1_gej_add_ge_var(out_nonce, out_nonce, &nonce_pts[0], NULL); -} - -static void secp256k1_musig_nonce_process_internal(int *fin_nonce_parity, unsigned char *fin_nonce, secp256k1_scalar *b, secp256k1_ge *aggnonce_pts, const unsigned char *agg_pk32, const unsigned char *msg) { - unsigned char noncehash[32]; - secp256k1_ge fin_nonce_pt; - secp256k1_gej fin_nonce_ptj; - - secp256k1_musig_compute_noncehash(noncehash, aggnonce_pts, agg_pk32, msg); - secp256k1_scalar_set_b32(b, noncehash, NULL); - /* fin_nonce = aggnonce_pts[0] + b*aggnonce_pts[1] */ - secp256k1_effective_nonce(&fin_nonce_ptj, aggnonce_pts, b); - secp256k1_ge_set_gej(&fin_nonce_pt, &fin_nonce_ptj); - if (secp256k1_ge_is_infinity(&fin_nonce_pt)) { - fin_nonce_pt = secp256k1_ge_const_g; - } - /* fin_nonce_pt is not the point at infinity */ - secp256k1_fe_normalize_var(&fin_nonce_pt.x); - secp256k1_fe_get_b32(fin_nonce, &fin_nonce_pt.x); - secp256k1_fe_normalize_var(&fin_nonce_pt.y); - *fin_nonce_parity = secp256k1_fe_is_odd(&fin_nonce_pt.y); -} - -int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache) { - secp256k1_keyagg_cache_internal cache_i; - secp256k1_ge aggnonce_pts[2]; - unsigned char fin_nonce[32]; - secp256k1_musig_session_internal session_i; - unsigned char agg_pk32[32]; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(session != NULL); - ARG_CHECK(aggnonce != NULL); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(keyagg_cache != NULL); - - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - secp256k1_fe_get_b32(agg_pk32, &cache_i.pk.x); - - if (!secp256k1_musig_aggnonce_load(ctx, aggnonce_pts, aggnonce)) { - return 0; - } - - secp256k1_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); - secp256k1_schnorrsig_challenge(&session_i.challenge, fin_nonce, msg32, 32, agg_pk32); - - /* If there is a tweak then set `challenge` times `tweak` to the `s`-part.*/ - secp256k1_scalar_set_int(&session_i.s_part, 0); - if (!secp256k1_scalar_is_zero(&cache_i.tweak)) { - secp256k1_scalar e_tmp; - secp256k1_scalar_mul(&e_tmp, &session_i.challenge, &cache_i.tweak); - if (secp256k1_fe_is_odd(&cache_i.pk.y)) { - secp256k1_scalar_negate(&e_tmp, &e_tmp); - } - session_i.s_part = e_tmp; - } - memcpy(session_i.fin_nonce, fin_nonce, sizeof(session_i.fin_nonce)); - secp256k1_musig_session_save(session, &session_i); - return 1; -} - -static void secp256k1_musig_partial_sign_clear(secp256k1_scalar *sk, secp256k1_scalar *k) { - secp256k1_scalar_clear(sk); - secp256k1_scalar_clear(&k[0]); - secp256k1_scalar_clear(&k[1]); -} - -int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_partial_sig *partial_sig, secp256k1_musig_secnonce *secnonce, const secp256k1_keypair *keypair, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) { - secp256k1_scalar sk; - secp256k1_ge pk, keypair_pk; - secp256k1_scalar k[2]; - secp256k1_scalar mu, s; - secp256k1_keyagg_cache_internal cache_i; - secp256k1_musig_session_internal session_i; - int ret; - - VERIFY_CHECK(ctx != NULL); - - ARG_CHECK(secnonce != NULL); - /* Fails if the magic doesn't match */ - ret = secp256k1_musig_secnonce_load(ctx, k, &pk, secnonce); - /* Set nonce to zero to avoid nonce reuse. This will cause subsequent calls - * of this function to fail */ - memset(secnonce, 0, sizeof(*secnonce)); - if (!ret) { - secp256k1_musig_partial_sign_clear(&sk, k); - return 0; - } - - ARG_CHECK(partial_sig != NULL); - ARG_CHECK(keypair != NULL); - ARG_CHECK(keyagg_cache != NULL); - ARG_CHECK(session != NULL); - - if (!secp256k1_keypair_load(ctx, &sk, &keypair_pk, keypair)) { - secp256k1_musig_partial_sign_clear(&sk, k); - return 0; - } - ARG_CHECK(secp256k1_fe_equal(&pk.x, &keypair_pk.x) - && secp256k1_fe_equal(&pk.y, &keypair_pk.y)); - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - secp256k1_musig_partial_sign_clear(&sk, k); - return 0; - } - - /* Negate sk if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. - * This corresponds to the line "Let d = gâ‹…gaccâ‹…d' mod n" in the - * specification. */ - if ((secp256k1_fe_is_odd(&cache_i.pk.y) - != cache_i.parity_acc)) { - secp256k1_scalar_negate(&sk, &sk); - } - - /* Multiply KeyAgg coefficient */ - secp256k1_musig_keyaggcoef(&mu, &cache_i, &pk); - secp256k1_scalar_mul(&sk, &sk, &mu); - - if (!secp256k1_musig_session_load(ctx, &session_i, session)) { - secp256k1_musig_partial_sign_clear(&sk, k); - return 0; - } - - if (session_i.fin_nonce_parity) { - secp256k1_scalar_negate(&k[0], &k[0]); - secp256k1_scalar_negate(&k[1], &k[1]); - } - - /* Sign */ - secp256k1_scalar_mul(&s, &session_i.challenge, &sk); - secp256k1_scalar_mul(&k[1], &session_i.noncecoef, &k[1]); - secp256k1_scalar_add(&k[0], &k[0], &k[1]); - secp256k1_scalar_add(&s, &s, &k[0]); - secp256k1_musig_partial_sig_save(partial_sig, &s); - secp256k1_musig_partial_sign_clear(&sk, k); - return 1; -} - -int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp256k1_musig_partial_sig *partial_sig, const secp256k1_musig_pubnonce *pubnonce, const secp256k1_pubkey *pubkey, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) { - secp256k1_keyagg_cache_internal cache_i; - secp256k1_musig_session_internal session_i; - secp256k1_scalar mu, e, s; - secp256k1_gej pkj; - secp256k1_ge nonce_pts[2]; - secp256k1_gej rj; - secp256k1_gej tmp; - secp256k1_ge pkp; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(partial_sig != NULL); - ARG_CHECK(pubnonce != NULL); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(keyagg_cache != NULL); - ARG_CHECK(session != NULL); - - if (!secp256k1_musig_session_load(ctx, &session_i, session)) { - return 0; - } - - if (!secp256k1_musig_pubnonce_load(ctx, nonce_pts, pubnonce)) { - return 0; - } - /* Compute "effective" nonce rj = nonce_pts[0] + b*nonce_pts[1] */ - /* TODO: use multiexp to compute -s*G + e*mu*pubkey + nonce_pts[0] + b*nonce_pts[1] */ - secp256k1_effective_nonce(&rj, nonce_pts, &session_i.noncecoef); - - if (!secp256k1_pubkey_load(ctx, &pkp, pubkey)) { - return 0; - } - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - /* Multiplying the challenge by the KeyAgg coefficient is equivalent - * to multiplying the signer's public key by the coefficient, except - * much easier to do. */ - secp256k1_musig_keyaggcoef(&mu, &cache_i, &pkp); - secp256k1_scalar_mul(&e, &session_i.challenge, &mu); - - /* Negate e if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. - * This corresponds to the line "Let g' = gâ‹…gacc mod n" and the multiplication "g'â‹…e" - * in the specification. */ - if (secp256k1_fe_is_odd(&cache_i.pk.y) - != cache_i.parity_acc) { - secp256k1_scalar_negate(&e, &e); - } - - if (!secp256k1_musig_partial_sig_load(ctx, &s, partial_sig)) { - return 0; - } - /* Compute -s*G + e*pkj + rj (e already includes the keyagg coefficient mu) */ - secp256k1_scalar_negate(&s, &s); - secp256k1_gej_set_ge(&pkj, &pkp); - secp256k1_ecmult(&tmp, &pkj, &e, &s); - if (session_i.fin_nonce_parity) { - secp256k1_gej_neg(&rj, &rj); - } - secp256k1_gej_add_var(&tmp, &tmp, &rj, NULL); - - return secp256k1_gej_is_infinity(&tmp); -} - -int secp256k1_musig_partial_sig_agg(const secp256k1_context* ctx, unsigned char *sig64, const secp256k1_musig_session *session, const secp256k1_musig_partial_sig * const* partial_sigs, size_t n_sigs) { - size_t i; - secp256k1_musig_session_internal session_i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(session != NULL); - ARG_CHECK(partial_sigs != NULL); - ARG_CHECK(n_sigs > 0); - - if (!secp256k1_musig_session_load(ctx, &session_i, session)) { - return 0; - } - for (i = 0; i < n_sigs; i++) { - secp256k1_scalar term; - if (!secp256k1_musig_partial_sig_load(ctx, &term, partial_sigs[i])) { - return 0; - } - secp256k1_scalar_add(&session_i.s_part, &session_i.s_part, &term); - } - secp256k1_scalar_get_b32(&sig64[32], &session_i.s_part); - memcpy(&sig64[0], session_i.fin_nonce, 32); - return 1; -} - -#endif diff --git a/external/secp256k1/src/modules/musig/tests_impl.h b/external/secp256k1/src/modules/musig/tests_impl.h deleted file mode 100644 index ce6ae1784d..0000000000 --- a/external/secp256k1/src/modules/musig/tests_impl.h +++ /dev/null @@ -1,1143 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_TESTS_IMPL_H -#define SECP256K1_MODULE_MUSIG_TESTS_IMPL_H - -#include -#include - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_extrakeys.h" -#include "../../../include/secp256k1_musig.h" - -#include "session.h" -#include "keyagg.h" -#include "../../scalar.h" -#include "../../field.h" -#include "../../group.h" -#include "../../hash.h" -#include "../../util.h" - -#include "vectors.h" - -static int create_keypair_and_pk(secp256k1_keypair *keypair, secp256k1_pubkey *pk, const unsigned char *sk) { - int ret; - secp256k1_keypair keypair_tmp; - ret = secp256k1_keypair_create(CTX, &keypair_tmp, sk); - ret &= secp256k1_keypair_pub(CTX, pk, &keypair_tmp); - if (keypair != NULL) { - *keypair = keypair_tmp; - } - return ret; -} - -/* Just a simple (non-tweaked) 2-of-2 MuSig aggregate, sign, verify - * test. */ -static void musig_simple_test(void) { - unsigned char sk[2][32]; - secp256k1_keypair keypair[2]; - secp256k1_musig_pubnonce pubnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - secp256k1_musig_aggnonce aggnonce; - unsigned char msg[32]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_musig_keyagg_cache keyagg_cache; - unsigned char session_secrand[2][32]; - secp256k1_musig_secnonce secnonce[2]; - secp256k1_pubkey pk[2]; - const secp256k1_pubkey *pk_ptr[2]; - secp256k1_musig_partial_sig partial_sig[2]; - const secp256k1_musig_partial_sig *partial_sig_ptr[2]; - unsigned char final_sig[64]; - secp256k1_musig_session session; - int i; - - testrand256(msg); - for (i = 0; i < 2; i++) { - testrand256(sk[i]); - pk_ptr[i] = &pk[i]; - pubnonce_ptr[i] = &pubnonce[i]; - partial_sig_ptr[i] = &partial_sig[i]; - - CHECK(create_keypair_and_pk(&keypair[i], &pk[i], sk[i])); - if (i == 0) { - testrand256(session_secrand[i]); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[i], &pubnonce[i], session_secrand[i], sk[i], &pk[i], NULL, NULL, NULL) == 1); - } else { - uint64_t nonrepeating_cnt = 0; - CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[i], &pubnonce[i], nonrepeating_cnt, &keypair[i], NULL, NULL, NULL) == 1); - } - } - - CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); - - for (i = 0; i < 2; i++) { - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[i], &secnonce[i], &keypair[i], &keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[i], &pubnonce[i], &pk[i], &keyagg_cache, &session) == 1); - } - - CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 2) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); -} - -/* Generate two pubnonces such that both group elements of their sum (calculated - * with secp256k1_musig_sum_pubnonces) are infinity. */ -static void pubnonce_summing_to_inf(secp256k1_musig_pubnonce *pubnonce) { - secp256k1_ge ge[2]; - int i; - secp256k1_gej summed_pubnonces[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - - testutil_random_ge_test(&ge[0]); - testutil_random_ge_test(&ge[1]); - - for (i = 0; i < 2; i++) { - secp256k1_musig_pubnonce_save(&pubnonce[i], ge); - pubnonce_ptr[i] = &pubnonce[i]; - secp256k1_ge_neg(&ge[0], &ge[0]); - secp256k1_ge_neg(&ge[1], &ge[1]); - } - - secp256k1_musig_sum_pubnonces(CTX, summed_pubnonces, pubnonce_ptr, 2); - CHECK(secp256k1_gej_is_infinity(&summed_pubnonces[0])); - CHECK(secp256k1_gej_is_infinity(&summed_pubnonces[1])); -} - -int memcmp_and_randomize(unsigned char *value, const unsigned char *expected, size_t len) { - int ret; - size_t i; - ret = secp256k1_memcmp_var(value, expected, len); - for (i = 0; i < len; i++) { - value[i] = testrand_bits(8); - } - return ret; -} - -static void musig_api_tests(void) { - secp256k1_musig_partial_sig partial_sig[2]; - const secp256k1_musig_partial_sig *partial_sig_ptr[2]; - secp256k1_musig_partial_sig invalid_partial_sig; - const secp256k1_musig_partial_sig *invalid_partial_sig_ptr[2]; - unsigned char pre_sig[64]; - unsigned char buf[32]; - unsigned char sk[2][32]; - secp256k1_keypair keypair[2]; - secp256k1_keypair invalid_keypair; - unsigned char max64[64]; - unsigned char zeros132[132] = { 0 }; - unsigned char session_secrand[2][32]; - unsigned char nonrepeating_cnt = 0; - secp256k1_musig_secnonce secnonce[2]; - secp256k1_musig_secnonce secnonce_tmp; - secp256k1_musig_secnonce invalid_secnonce; - secp256k1_musig_pubnonce pubnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - unsigned char pubnonce_ser[66]; - secp256k1_musig_pubnonce inf_pubnonce[2]; - const secp256k1_musig_pubnonce *inf_pubnonce_ptr[2]; - secp256k1_musig_pubnonce invalid_pubnonce; - const secp256k1_musig_pubnonce *invalid_pubnonce_ptr[1]; - secp256k1_musig_aggnonce aggnonce; - unsigned char aggnonce_ser[66]; - unsigned char msg[32]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_pubkey full_agg_pk; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_keyagg_cache invalid_keyagg_cache; - secp256k1_musig_session session; - secp256k1_musig_session invalid_session; - secp256k1_pubkey pk[2]; - const secp256k1_pubkey *pk_ptr[2]; - secp256k1_pubkey invalid_pk; - const secp256k1_pubkey *invalid_pk_ptr2[2]; - const secp256k1_pubkey *invalid_pk_ptr3[3]; - unsigned char tweak[32]; - int i; - - /** setup **/ - memset(max64, 0xff, sizeof(max64)); - memset(&invalid_keypair, 0, sizeof(invalid_keypair)); - memset(&invalid_pk, 0, sizeof(invalid_pk)); - memset(&invalid_secnonce, 0, sizeof(invalid_secnonce)); - memset(&invalid_partial_sig, 0, sizeof(invalid_partial_sig)); - pubnonce_summing_to_inf(inf_pubnonce); - /* Simulate structs being uninitialized by setting it to 0s. We don't want - * to produce undefined behavior by actually providing uninitialized - * structs. */ - memset(&invalid_keyagg_cache, 0, sizeof(invalid_keyagg_cache)); - memset(&invalid_pk, 0, sizeof(invalid_pk)); - memset(&invalid_pubnonce, 0, sizeof(invalid_pubnonce)); - memset(&invalid_session, 0, sizeof(invalid_session)); - - testrand256(msg); - testrand256(tweak); - for (i = 0; i < 2; i++) { - pk_ptr[i] = &pk[i]; - invalid_pk_ptr2[i] = &invalid_pk; - invalid_pk_ptr3[i] = &pk[i]; - pubnonce_ptr[i] = &pubnonce[i]; - inf_pubnonce_ptr[i] = &inf_pubnonce[i]; - partial_sig_ptr[i] = &partial_sig[i]; - invalid_partial_sig_ptr[i] = &partial_sig[i]; - testrand256(session_secrand[i]); - testrand256(sk[i]); - CHECK(create_keypair_and_pk(&keypair[i], &pk[i], sk[i])); - } - invalid_pubnonce_ptr[0] = &invalid_pubnonce; - invalid_partial_sig_ptr[0] = &invalid_partial_sig; - /* invalid_pk_ptr3 has two valid, one invalid pk, which is important to test - * musig_pubkey_agg */ - invalid_pk_ptr3[2] = &invalid_pk; - - /** main test body **/ - - /** Key aggregation **/ - CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); - CHECK(secp256k1_musig_pubkey_agg(CTX, NULL, &keyagg_cache, pk_ptr, 2) == 1); - CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, NULL, pk_ptr, 2) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, NULL, 2)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, invalid_pk_ptr2, 2)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, invalid_pk_ptr3, 3)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 0)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, NULL, 0)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - - CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); - - /* pubkey_get */ - CHECK(secp256k1_musig_pubkey_get(CTX, &full_agg_pk, &keyagg_cache) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_get(CTX, NULL, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_get(CTX, &full_agg_pk, NULL)); - CHECK(secp256k1_memcmp_var(&full_agg_pk, zeros132, sizeof(full_agg_pk)) == 0); - - /** Tweaking **/ - { - int (*tweak_func[2]) (const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32); - tweak_func[0] = secp256k1_musig_pubkey_ec_tweak_add; - tweak_func[1] = secp256k1_musig_pubkey_xonly_tweak_add; - for (i = 0; i < 2; i++) { - secp256k1_pubkey tmp_output_pk; - secp256k1_musig_keyagg_cache tmp_keyagg_cache = keyagg_cache; - CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1); - /* Reset keyagg_cache */ - tmp_keyagg_cache = keyagg_cache; - CHECK((*tweak_func[i])(CTX, NULL, &tmp_keyagg_cache, tweak) == 1); - tmp_keyagg_cache = keyagg_cache; - CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, NULL, tweak)); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); - tmp_keyagg_cache = keyagg_cache; - CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, NULL)); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); - tmp_keyagg_cache = keyagg_cache; - CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, max64) == 0); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); - tmp_keyagg_cache = keyagg_cache; - /* Uninitialized keyagg_cache */ - CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &invalid_keyagg_cache, tweak)); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); - } - } - - /** Session creation with nonce_gen **/ - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64) == 1); - /* nonce_gen, if successful, sets session_secrand to the zero array, which - * makes subsequent nonce_gen calls with the same session_secrand fail. So - * check that session_secrand is indeed the zero array and fill it with - * random values again. */ - CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); - - CHECK_ILLEGAL(STATIC_CTX, secp256k1_musig_nonce_gen(STATIC_CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, NULL, &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); - - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], NULL, session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], NULL, sk[0], &pk[0], msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - - /* session_secrand = 0 is disallowed because it indicates a faulty RNG */ - memcpy(&session_secrand[0], zeros132, sizeof(session_secrand[0])); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], zeros132, sk[0], &pk[0], msg, &keyagg_cache, max64) == 0); - CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], NULL, &pk[0], msg, &keyagg_cache, max64) == 1); - CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); - - /* invalid seckey */ - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], max64, &pk[0], msg, &keyagg_cache, max64) == 0); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], NULL, msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &invalid_pk, msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], NULL, &keyagg_cache, max64) == 1); - CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); - - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, NULL, max64) == 1); - CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); - - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &invalid_keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, NULL) == 1); - CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); - - /* Every in-argument except session_secrand and pubkey can be NULL */ - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], NULL, &pk[0], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_secrand[1], sk[1], &pk[1], NULL, NULL, NULL) == 1); - - /** Session creation with nonce_gen_counter **/ - CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64) == 1); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_musig_nonce_gen_counter(STATIC_CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, NULL, &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], NULL, nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - /* using nonce_gen_counter requires keypair */ - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, NULL, msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - /* invalid keypair */ - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &invalid_keypair, msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], NULL, &keyagg_cache, max64) == 1); - CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, NULL, max64) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &invalid_keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt,&keypair[0], msg, &keyagg_cache, NULL) == 1); - - /* Every in-argument except nonrepeating_cnt and keypair can be NULL */ - CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[1], &pubnonce[1], nonrepeating_cnt, &keypair[1], NULL, NULL, NULL) == 1); - - - /** Serialize and parse public nonces **/ - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, NULL, &pubnonce[0])); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, NULL)); - CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &invalid_pubnonce)); - CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); - CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &pubnonce[0]) == 1); - - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], pubnonce_ser) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_parse(CTX, NULL, pubnonce_ser)); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], NULL)); - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], zeros132) == 0); - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], pubnonce_ser) == 1); - - { - /* Check that serialize and parse results in the same value */ - secp256k1_musig_pubnonce tmp; - CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &pubnonce[0]) == 1); - CHECK(secp256k1_musig_pubnonce_parse(CTX, &tmp, pubnonce_ser) == 1); - CHECK(secp256k1_memcmp_var(&tmp, &pubnonce[0], sizeof(tmp)) == 0); - } - - /** Receive nonces and aggregate **/ - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, NULL, pubnonce_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, NULL, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 0)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, invalid_pubnonce_ptr, 1)); - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, inf_pubnonce_ptr, 2) == 1); - { - /* Check that the aggnonce encodes two points at infinity */ - secp256k1_ge aggnonce_pt[2]; - secp256k1_musig_aggnonce_load(CTX, aggnonce_pt, &aggnonce); - for (i = 0; i < 2; i++) { - secp256k1_ge_is_infinity(&aggnonce_pt[i]); - } - } - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - - /** Serialize and parse aggregate nonces **/ - CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, NULL, &aggnonce)); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, NULL)); - CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, (secp256k1_musig_aggnonce*) &invalid_pubnonce)); - CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); - CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); - - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, aggnonce_ser) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_parse(CTX, NULL, aggnonce_ser)); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_parse(CTX, &aggnonce, NULL)); - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, zeros132) == 1); - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, aggnonce_ser) == 1); - - { - /* Check that serialize and parse results in the same value */ - secp256k1_musig_aggnonce tmp; - CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); - CHECK(secp256k1_musig_aggnonce_parse(CTX, &tmp, aggnonce_ser) == 1); - CHECK(secp256k1_memcmp_var(&tmp, &aggnonce, sizeof(tmp)) == 0); - } - - /** Process nonces **/ - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, NULL, &aggnonce, msg, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, NULL, msg, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, (secp256k1_musig_aggnonce*) &invalid_pubnonce, msg, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, NULL, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &invalid_keyagg_cache)); - - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); - - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session) == 1); - /* The secnonce is set to 0 and subsequent signing attempts fail */ - CHECK(secp256k1_memcmp_var(&secnonce_tmp, zeros132, sizeof(secnonce_tmp)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, NULL, &secnonce_tmp, &keypair[0], &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], NULL, &keypair[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &invalid_secnonce, &keypair[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, NULL, &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &invalid_keypair, &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - { - unsigned char sk_tmp[32]; - secp256k1_keypair keypair_tmp; - testrand256(sk_tmp); - CHECK(secp256k1_keypair_create(CTX, &keypair_tmp, sk_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair_tmp, &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - } - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], NULL, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &invalid_keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, NULL)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &invalid_session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], &keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], &keyagg_cache, &session) == 1); - - CHECK(secp256k1_musig_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_serialize(CTX, NULL, &partial_sig[0])); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_serialize(CTX, buf, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_serialize(CTX, buf, &invalid_partial_sig)); - CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[0], buf) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_parse(CTX, NULL, buf)); - { - /* Check that parsing failure results in an invalid sig */ - secp256k1_musig_partial_sig tmp; - CHECK(secp256k1_musig_partial_sig_parse(CTX, &tmp, max64) == 0); - CHECK(secp256k1_memcmp_var(&tmp, zeros132, sizeof(partial_sig[0])) == 0); - } - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_parse(CTX, &partial_sig[0], NULL)); - - { - /* Check that serialize and parse results in the same value */ - secp256k1_musig_partial_sig tmp; - CHECK(secp256k1_musig_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); - CHECK(secp256k1_musig_partial_sig_parse(CTX, &tmp, buf) == 1); - CHECK(secp256k1_memcmp_var(&tmp, &partial_sig[0], sizeof(tmp)) == 0); - } - - /** Partial signature verification */ - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, NULL, &pubnonce[0], &pk[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &invalid_partial_sig, &pubnonce[0], &pk[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], NULL, &pk[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &invalid_pubnonce, &pk[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], NULL, &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &invalid_pk, &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], NULL, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &invalid_keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &invalid_session)); - - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pk[1], &keyagg_cache, &session) == 1); - - /** Signature aggregation and verification */ - CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, NULL, &session, partial_sig_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, NULL, partial_sig_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &invalid_session, partial_sig_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, NULL, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, invalid_partial_sig_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 0)); - CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 1) == 1); - CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); -} - -static void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { - secp256k1_scalar k1[2], k2[2]; - - secp256k1_nonce_function_musig(k1, args[0], args[1], args[2], args[3], args[4], args[5]); - testrand_flip(args[n_flip], n_bytes); - secp256k1_nonce_function_musig(k2, args[0], args[1], args[2], args[3], args[4], args[5]); - CHECK(secp256k1_scalar_eq(&k1[0], &k2[0]) == 0); - CHECK(secp256k1_scalar_eq(&k1[1], &k2[1]) == 0); -} - -static void musig_nonce_test(void) { - unsigned char *args[6]; - unsigned char session_secrand[32]; - unsigned char sk[32]; - unsigned char pk[33]; - unsigned char msg[32]; - unsigned char agg_pk[32]; - unsigned char extra_input[32]; - int i, j; - secp256k1_scalar k[6][2]; - - testrand_bytes_test(session_secrand, sizeof(session_secrand)); - testrand_bytes_test(sk, sizeof(sk)); - testrand_bytes_test(pk, sizeof(pk)); - testrand_bytes_test(msg, sizeof(msg)); - testrand_bytes_test(agg_pk, sizeof(agg_pk)); - testrand_bytes_test(extra_input, sizeof(extra_input)); - - /* Check that a bitflip in an argument results in different nonces. */ - args[0] = session_secrand; - args[1] = msg; - args[2] = sk; - args[3] = pk; - args[4] = agg_pk; - args[5] = extra_input; - for (i = 0; i < COUNT; i++) { - musig_nonce_bitflip(args, 0, sizeof(session_secrand)); - musig_nonce_bitflip(args, 1, sizeof(msg)); - musig_nonce_bitflip(args, 2, sizeof(sk)); - musig_nonce_bitflip(args, 3, sizeof(pk)); - musig_nonce_bitflip(args, 4, sizeof(agg_pk)); - musig_nonce_bitflip(args, 5, sizeof(extra_input)); - } - /* Check that if any argument is NULL, a different nonce is produced than if - * any other argument is NULL. */ - memcpy(msg, session_secrand, sizeof(msg)); - memcpy(sk, session_secrand, sizeof(sk)); - memcpy(pk, session_secrand, sizeof(session_secrand)); - memcpy(agg_pk, session_secrand, sizeof(agg_pk)); - memcpy(extra_input, session_secrand, sizeof(extra_input)); - secp256k1_nonce_function_musig(k[0], args[0], args[1], args[2], args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[1], args[0], NULL, args[2], args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[2], args[0], args[1], NULL, args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[3], args[0], args[1], args[2], NULL, args[4], args[5]); - secp256k1_nonce_function_musig(k[4], args[0], args[1], args[2], args[3], NULL, args[5]); - secp256k1_nonce_function_musig(k[5], args[0], args[1], args[2], args[3], args[4], NULL); - for (i = 0; i < 6; i++) { - CHECK(!secp256k1_scalar_eq(&k[i][0], &k[i][1])); - for (j = i+1; j < 6; j++) { - CHECK(!secp256k1_scalar_eq(&k[i][0], &k[j][0])); - CHECK(!secp256k1_scalar_eq(&k[i][1], &k[j][1])); - } - } -} - -static void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) { - secp256k1_sha256 sha; - secp256k1_sha256_initialize_tagged(&sha, tag, taglen); - test_sha256_eq(&sha, sha_tagged); -} - -/* Checks that the initialized tagged hashes have the expected - * state. */ -static void sha256_tag_test(void) { - secp256k1_sha256 sha; - { - char tag[] = "KeyAgg list"; - secp256k1_musig_keyagglist_sha256(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); - } - { - char tag[] = "KeyAgg coefficient"; - secp256k1_musig_keyaggcoef_sha256(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); - } - { - unsigned char tag[] = "MuSig/aux"; - secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); - } - { - unsigned char tag[] = "MuSig/nonce"; - secp256k1_nonce_function_musig_sha256_tagged(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); - } - { - unsigned char tag[] = "MuSig/noncecoef"; - secp256k1_musig_compute_noncehash_sha256_tagged(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); - } -} - -/* Attempts to create a signature for the aggregate public key using given secret - * keys and keyagg_cache. */ -static void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const unsigned char *sk0, const unsigned char *sk1, secp256k1_musig_keyagg_cache *keyagg_cache) { - secp256k1_pubkey pk[2]; - unsigned char session_secrand[2][32]; - unsigned char msg[32]; - secp256k1_musig_secnonce secnonce[2]; - secp256k1_musig_pubnonce pubnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - secp256k1_musig_aggnonce aggnonce; - secp256k1_keypair keypair[2]; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig[2]; - const secp256k1_musig_partial_sig *partial_sig_ptr[2]; - unsigned char final_sig[64]; - int i; - - for (i = 0; i < 2; i++) { - pubnonce_ptr[i] = &pubnonce[i]; - partial_sig_ptr[i] = &partial_sig[i]; - - testrand256(session_secrand[i]); - } - CHECK(create_keypair_and_pk(&keypair[0], &pk[0], sk0) == 1); - CHECK(create_keypair_and_pk(&keypair[1], &pk[1], sk1) == 1); - testrand256(msg); - - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk0, &pk[0], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_secrand[1], sk1, &pk[1], NULL, NULL, NULL) == 1); - - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, keyagg_cache) == 1); - - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], keyagg_cache, &session) == 1); - - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pk[1], keyagg_cache, &session) == 1); - - CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 2) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), agg_pk) == 1); -} - -/* Create aggregate public key P[0], tweak multiple times (using xonly and - * plain tweaking) and test signing. */ -static void musig_tweak_test(void) { - unsigned char sk[2][32]; - secp256k1_pubkey pk[2]; - const secp256k1_pubkey *pk_ptr[2]; - secp256k1_musig_keyagg_cache keyagg_cache; - enum { N_TWEAKS = 8 }; - secp256k1_pubkey P[N_TWEAKS + 1]; - secp256k1_xonly_pubkey P_xonly[N_TWEAKS + 1]; - int i; - - /* Key Setup */ - for (i = 0; i < 2; i++) { - pk_ptr[i] = &pk[i]; - testrand256(sk[i]); - CHECK(create_keypair_and_pk(NULL, &pk[i], sk[i]) == 1); - } - /* Compute P0 = keyagg(pk0, pk1) and test signing for it */ - CHECK(secp256k1_musig_pubkey_agg(CTX, &P_xonly[0], &keyagg_cache, pk_ptr, 2) == 1); - musig_tweak_test_helper(&P_xonly[0], sk[0], sk[1], &keyagg_cache); - CHECK(secp256k1_musig_pubkey_get(CTX, &P[0], &keyagg_cache)); - - /* Compute Pi = f(Pj) + tweaki*G where where j = i-1 and try signing for - * that key. If xonly is set to true, the function f normalizes the input - * point to have an even X-coordinate ("xonly-tweaking"). - * Otherwise, the function f is the identity function. */ - for (i = 1; i <= N_TWEAKS; i++) { - unsigned char tweak[32]; - int P_parity; - int xonly = testrand_bits(1); - - testrand256(tweak); - if (xonly) { - CHECK(secp256k1_musig_pubkey_xonly_tweak_add(CTX, &P[i], &keyagg_cache, tweak) == 1); - } else { - CHECK(secp256k1_musig_pubkey_ec_tweak_add(CTX, &P[i], &keyagg_cache, tweak) == 1); - } - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &P_xonly[i], &P_parity, &P[i])); - /* Check that musig_pubkey_tweak_add produces same result as - * xonly_pubkey_tweak_add or ec_pubkey_tweak_add. */ - if (xonly) { - unsigned char P_serialized[32]; - CHECK(secp256k1_xonly_pubkey_serialize(CTX, P_serialized, &P_xonly[i])); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, P_serialized, P_parity, &P_xonly[i-1], tweak) == 1); - } else { - secp256k1_pubkey tmp_key = P[i-1]; - CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &tmp_key, tweak)); - CHECK(secp256k1_memcmp_var(&tmp_key, &P[i], sizeof(tmp_key)) == 0); - } - /* Test signing for P[i] */ - musig_tweak_test_helper(&P_xonly[i], sk[0], sk[1], &keyagg_cache); - } -} - -int musig_vectors_keyagg_and_tweak(enum MUSIG_ERROR *error, - secp256k1_musig_keyagg_cache *keyagg_cache, - unsigned char *agg_pk_ser, - const unsigned char pubkeys33[][33], - const unsigned char tweaks32[][32], - size_t key_indices_len, - const size_t *key_indices, - size_t tweak_indices_len, - const size_t *tweak_indices, - const int *is_xonly) { - secp256k1_pubkey pubkeys[MUSIG_VECTORS_MAX_PUBKEYS]; - const secp256k1_pubkey *pk_ptr[MUSIG_VECTORS_MAX_PUBKEYS]; - int i; - secp256k1_pubkey agg_pk; - secp256k1_xonly_pubkey agg_pk_xonly; - - for (i = 0; i < (int)key_indices_len; i++) { - if (!secp256k1_ec_pubkey_parse(CTX, &pubkeys[i], pubkeys33[key_indices[i]], 33)) { - *error = MUSIG_PUBKEY; - return 0; - } - pk_ptr[i] = &pubkeys[i]; - } - if (!secp256k1_musig_pubkey_agg(CTX, NULL, keyagg_cache, pk_ptr, key_indices_len)) { - *error = MUSIG_OTHER; - return 0; - } - - for (i = 0; i < (int)tweak_indices_len; i++) { - if (is_xonly[i]) { - if (!secp256k1_musig_pubkey_xonly_tweak_add(CTX, NULL, keyagg_cache, tweaks32[tweak_indices[i]])) { - *error = MUSIG_TWEAK; - return 0; - } - } else { - if (!secp256k1_musig_pubkey_ec_tweak_add(CTX, NULL, keyagg_cache, tweaks32[tweak_indices[i]])) { - *error = MUSIG_TWEAK; - return 0; - } - } - } - if (!secp256k1_musig_pubkey_get(CTX, &agg_pk, keyagg_cache)) { - *error = MUSIG_OTHER; - return 0; - } - - if (!secp256k1_xonly_pubkey_from_pubkey(CTX, &agg_pk_xonly, NULL, &agg_pk)) { - *error = MUSIG_OTHER; - return 0; - } - - if (agg_pk_ser != NULL) { - if (!secp256k1_xonly_pubkey_serialize(CTX, agg_pk_ser, &agg_pk_xonly)) { - *error = MUSIG_OTHER; - return 0; - } - } - - return 1; -} - -static void musig_test_vectors_keyagg(void) { - size_t i; - const struct musig_key_agg_vector *vector = &musig_key_agg_vector; - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_key_agg_valid_test_case *c = &vector->valid_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - unsigned char agg_pk[32]; - - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - CHECK(secp256k1_memcmp_var(agg_pk, c->expected, sizeof(agg_pk)) == 0); - } - - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { - const struct musig_key_agg_error_test_case *c = &vector->error_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - - CHECK(!musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - CHECK(c->error == error); - } -} - -static void musig_test_vectors_noncegen(void) { - size_t i; - const struct musig_nonce_gen_vector *vector = &musig_nonce_gen_vector; - - for (i = 0; i < sizeof(vector->test_case)/sizeof(vector->test_case[0]); i++) { - const struct musig_nonce_gen_test_case *c = &vector->test_case[i]; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_keyagg_cache *keyagg_cache_ptr = NULL; - unsigned char session_secrand32[32]; - secp256k1_musig_secnonce secnonce; - secp256k1_musig_pubnonce pubnonce; - const unsigned char *sk = NULL; - const unsigned char *msg = NULL; - const unsigned char *extra_in = NULL; - secp256k1_pubkey pk; - unsigned char pubnonce66[66]; - - memcpy(session_secrand32, c->rand_, 32); - if (c->has_sk) { - sk = c->sk; - } - if (c->has_aggpk) { - /* Create keyagg_cache from aggpk */ - secp256k1_keyagg_cache_internal cache_i; - secp256k1_xonly_pubkey aggpk; - memset(&cache_i, 0, sizeof(cache_i)); - CHECK(secp256k1_xonly_pubkey_parse(CTX, &aggpk, c->aggpk)); - CHECK(secp256k1_xonly_pubkey_load(CTX, &cache_i.pk, &aggpk)); - secp256k1_keyagg_cache_save(&keyagg_cache, &cache_i); - keyagg_cache_ptr = &keyagg_cache; - } - if (c->has_msg) { - msg = c->msg; - } - if (c->has_extra_in) { - extra_in = c->extra_in; - } - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pk, c->pk, sizeof(c->pk))); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce, &pubnonce, session_secrand32, sk, &pk, msg, keyagg_cache_ptr, extra_in) == 1); - CHECK(secp256k1_memcmp_var(&secnonce.data[4], c->expected_secnonce, 2*32) == 0); - /* The last element of the secnonce is the public key (uncompressed in - * secp256k1_musig_secnonce, compressed in the test vector secnonce). */ - CHECK(secp256k1_memcmp_var(&secnonce.data[4+2*32], &pk, sizeof(pk)) == 0); - CHECK(secp256k1_memcmp_var(&c->expected_secnonce[2*32], c->pk, sizeof(c->pk)) == 0); - - CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce66, &pubnonce) == 1); - CHECK(sizeof(c->expected_pubnonce) == sizeof(pubnonce66)); - CHECK(secp256k1_memcmp_var(pubnonce66, c->expected_pubnonce, sizeof(pubnonce66)) == 0); - } -} - - -static void musig_test_vectors_nonceagg(void) { - size_t i; - int j; - const struct musig_nonce_agg_vector *vector = &musig_nonce_agg_vector; - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_nonce_agg_test_case *c = &vector->valid_case[i]; - secp256k1_musig_pubnonce pubnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - secp256k1_musig_aggnonce aggnonce; - unsigned char aggnonce66[66]; - - for (j = 0; j < 2; j++) { - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pnonces[c->pnonce_indices[j]]) == 1); - pubnonce_ptr[j] = &pubnonce[j]; - } - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2)); - CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce66, &aggnonce)); - CHECK(secp256k1_memcmp_var(aggnonce66, c->expected, 33) == 0); - } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { - const struct musig_nonce_agg_test_case *c = &vector->error_case[i]; - secp256k1_musig_pubnonce pubnonce[2]; - for (j = 0; j < 2; j++) { - int expected = c->invalid_nonce_idx != j; - CHECK(expected == secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pnonces[c->pnonce_indices[j]])); - } - } -} - -static void musig_test_set_secnonce(secp256k1_musig_secnonce *secnonce, const unsigned char *secnonce64, const secp256k1_pubkey *pubkey) { - secp256k1_ge pk; - secp256k1_scalar k[2]; - - secp256k1_scalar_set_b32(&k[0], &secnonce64[0], NULL); - secp256k1_scalar_set_b32(&k[1], &secnonce64[32], NULL); - CHECK(secp256k1_pubkey_load(CTX, &pk, pubkey)); - secp256k1_musig_secnonce_save(secnonce, k, &pk); -} - -static void musig_test_vectors_signverify(void) { - size_t i; - const struct musig_sign_verify_vector *vector = &musig_sign_verify_vector; - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_valid_case *c = &vector->valid_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_pubkey pubkey; - secp256k1_musig_pubnonce pubnonce; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - secp256k1_musig_secnonce secnonce; - secp256k1_keypair keypair; - unsigned char partial_sig32[32]; - - CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - musig_test_set_secnonce(&secnonce, vector->secnonces[0], &pubkey); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - CHECK(secp256k1_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); - CHECK(secp256k1_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); - - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[0])); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); - } - for (i = 0; i < sizeof(vector->sign_error_case)/sizeof(vector->sign_error_case[0]); i++) { - const struct musig_sign_error_case *c = &vector->sign_error_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_pubkey pubkey; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - secp256k1_musig_secnonce secnonce; - secp256k1_keypair keypair; - int expected; - - if (i == 0) { - /* Skip this vector since the implementation does not error out when - * the signing key does not belong to any pubkey. */ - continue; - } - expected = c->error != MUSIG_PUBKEY; - CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - CHECK(expected || c->error == error); - if (!expected) { - continue; - } - - expected = c->error != MUSIG_AGGNONCE; - CHECK(expected == secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); - if (!expected) { - continue; - } - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); - expected = c->error != MUSIG_SECNONCE; - if (expected) { - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - } else { - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - } - } - for (i = 0; i < sizeof(vector->verify_fail_case)/sizeof(vector->verify_fail_case[0]); i++) { - const struct musig_verify_fail_error_case *c = &vector->verify_fail_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - enum { NUM_PUBNONCES = 3 }; - secp256k1_musig_pubnonce pubnonce[NUM_PUBNONCES]; - const secp256k1_musig_pubnonce *pubnonce_ptr[NUM_PUBNONCES]; - secp256k1_pubkey pubkey; - int expected; - size_t j; - - CHECK(NUM_PUBNONCES <= c->nonce_indices_len); - for (j = 0; j < c->nonce_indices_len; j++) { - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pubnonces[c->nonce_indices[j]])); - pubnonce_ptr[j] = &pubnonce[j]; - } - - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, c->nonce_indices_len) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[c->signer_index], sizeof(vector->pubkeys[0]))); - - expected = c->error != MUSIG_SIG; - CHECK(expected == secp256k1_musig_partial_sig_parse(CTX, &partial_sig, c->sig)); - if (!expected) { - continue; - } - expected = c->error != MUSIG_SIG_VERIFY; - CHECK(expected == secp256k1_musig_partial_sig_verify(CTX, &partial_sig, pubnonce, &pubkey, &keyagg_cache, &session)); - } - for (i = 0; i < sizeof(vector->verify_error_case)/sizeof(vector->verify_error_case[0]); i++) { - const struct musig_verify_fail_error_case *c = &vector->verify_error_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_pubnonce pubnonce; - int expected; - - expected = c->error != MUSIG_PUBKEY; - CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - CHECK(expected || c->error == error); - if (!expected) { - continue; - } - expected = c->error != MUSIG_PUBNONCE; - CHECK(expected == secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[c->nonce_indices[c->signer_index]])); - } -} - -static void musig_test_vectors_tweak(void) { - size_t i; - const struct musig_tweak_vector *vector = &musig_tweak_vector; - secp256k1_pubkey pubkey; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_secnonce secnonce; - - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonce)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_tweak_case *c = &vector->valid_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_pubnonce pubnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - secp256k1_keypair keypair; - unsigned char partial_sig32[32]; - - musig_test_set_secnonce(&secnonce, vector->secnonce, &pubkey); - - CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache)); - - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - CHECK(secp256k1_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); - CHECK(secp256k1_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); - - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[c->nonce_indices[c->signer_index]])); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); - } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { - const struct musig_tweak_case *c = &vector->error_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - CHECK(!musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - CHECK(error == MUSIG_TWEAK); - } -} - -static void musig_test_vectors_sigagg(void) { - size_t i, j; - const struct musig_sig_agg_vector *vector = &musig_sig_agg_vector; - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_sig_agg_case *c = &vector->valid_case[i]; - enum MUSIG_ERROR error; - unsigned char final_sig[64]; - secp256k1_musig_keyagg_cache keyagg_cache; - unsigned char agg_pk32[32]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; - const secp256k1_musig_partial_sig *partial_sig_ptr[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; - - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk32, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, c->aggnonce)); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache)); - for (j = 0; j < c->psig_indices_len; j++) { - CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); - partial_sig_ptr[j] = &partial_sig[j]; - } - - CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, c->psig_indices_len) == 1); - CHECK(secp256k1_memcmp_var(final_sig, c->expected, sizeof(final_sig)) == 0); - - CHECK(secp256k1_xonly_pubkey_parse(CTX, &agg_pk, agg_pk32)); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, vector->msg, sizeof(vector->msg), &agg_pk) == 1); - } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { - const struct musig_sig_agg_case *c = &vector->error_case[i]; - secp256k1_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; - for (j = 0; j < c->psig_indices_len; j++) { - int expected = c->invalid_sig_idx != (int)j; - CHECK(expected == secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); - } - } -} - -/* Since the BIP doesn't provide static test vectors for nonce_gen_counter, we - * define a static test here */ -static void musig_test_static_nonce_gen_counter(void) { - secp256k1_musig_secnonce secnonce; - secp256k1_musig_pubnonce pubnonce; - unsigned char pubnonce66[66]; - secp256k1_pubkey pk; - secp256k1_keypair keypair; - uint64_t nonrepeating_cnt = 0; - unsigned char sk[32] = { - 0xEE, 0xC1, 0xCB, 0x7D, 0x1B, 0x72, 0x54, 0xC5, - 0xCA, 0xB0, 0xD9, 0xC6, 0x1A, 0xB0, 0x2E, 0x64, - 0x3D, 0x46, 0x4A, 0x59, 0xFE, 0x6C, 0x96, 0xA7, - 0xEF, 0xE8, 0x71, 0xF0, 0x7C, 0x5A, 0xEF, 0x54, - }; - unsigned char expected_secnonce[64] = { - 0x84, 0x2F, 0x13, 0x80, 0xCD, 0x17, 0xA1, 0x98, - 0xFC, 0x3D, 0xAD, 0x3B, 0x7D, 0xA7, 0x49, 0x29, - 0x41, 0xF4, 0x69, 0x76, 0xF2, 0x70, 0x2F, 0xF7, - 0xC6, 0x6F, 0x24, 0xF4, 0x72, 0x03, 0x6A, 0xF1, - 0xDA, 0x3F, 0x95, 0x2D, 0xDE, 0x4A, 0x2D, 0xA6, - 0xB6, 0x32, 0x57, 0x07, 0xCE, 0x87, 0xA4, 0xE3, - 0x61, 0x6D, 0x06, 0xFC, 0x5F, 0x81, 0xA9, 0xC9, - 0x93, 0x86, 0xD2, 0x0A, 0x99, 0xCE, 0xCF, 0x99, - }; - unsigned char expected_pubnonce[66] = { - 0x03, 0xA5, 0xB9, 0xB6, 0x90, 0x79, 0x42, 0xEA, - 0xCD, 0xDA, 0x49, 0xA3, 0x66, 0x01, 0x6E, 0xC2, - 0xE6, 0x24, 0x04, 0xA1, 0xBF, 0x4A, 0xB6, 0xD4, - 0xDB, 0x82, 0x06, 0x7B, 0xC3, 0xAD, 0xF0, 0x86, - 0xD7, 0x03, 0x32, 0x05, 0xDB, 0x9E, 0xB3, 0x4D, - 0x5C, 0x7C, 0xE0, 0x28, 0x48, 0xCA, 0xC6, 0x8A, - 0x83, 0xED, 0x73, 0xE3, 0x88, 0x34, 0x77, 0xF5, - 0x63, 0xF2, 0x3C, 0xE9, 0xA1, 0x1A, 0x77, 0x21, - 0xEC, 0x64, - }; - - CHECK(secp256k1_keypair_create(CTX, &keypair, sk)); - CHECK(secp256k1_keypair_pub(CTX, &pk, &keypair)); - CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce, &pubnonce, nonrepeating_cnt, &keypair, NULL, NULL, NULL) == 1); - - CHECK(secp256k1_memcmp_var(&secnonce.data[4], expected_secnonce, 2*32) == 0); - CHECK(secp256k1_memcmp_var(&secnonce.data[4+2*32], &pk, sizeof(pk)) == 0); - - CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce66, &pubnonce) == 1); - CHECK(secp256k1_memcmp_var(pubnonce66, expected_pubnonce, sizeof(pubnonce66)) == 0); -} - -static void run_musig_tests(void) { - int i; - - for (i = 0; i < COUNT; i++) { - musig_simple_test(); - } - musig_api_tests(); - musig_nonce_test(); - for (i = 0; i < COUNT; i++) { - /* Run multiple times to ensure that pk and nonce have different y - * parities */ - musig_tweak_test(); - } - sha256_tag_test(); - musig_test_vectors_keyagg(); - musig_test_vectors_noncegen(); - musig_test_vectors_nonceagg(); - musig_test_vectors_signverify(); - musig_test_vectors_tweak(); - musig_test_vectors_sigagg(); - - musig_test_static_nonce_gen_counter(); -} - -#endif diff --git a/external/secp256k1/src/modules/musig/vectors.h b/external/secp256k1/src/modules/musig/vectors.h deleted file mode 100644 index 8407c2a69a..0000000000 --- a/external/secp256k1/src/modules/musig/vectors.h +++ /dev/null @@ -1,346 +0,0 @@ -/** - * Automatically generated by ./tools/test_vectors_musig2_generate.py. - * - * The test vectors for the KeySort function are included in this file. They can - * be found in src/modules/extrakeys/tests_impl.h. */ - -enum MUSIG_ERROR { - MUSIG_PUBKEY, - MUSIG_TWEAK, - MUSIG_PUBNONCE, - MUSIG_AGGNONCE, - MUSIG_SECNONCE, - MUSIG_SIG, - MUSIG_SIG_VERIFY, - MUSIG_OTHER -}; - -struct musig_key_agg_valid_test_case { - size_t key_indices_len; - size_t key_indices[4]; - unsigned char expected[32]; -}; - -struct musig_key_agg_error_test_case { - size_t key_indices_len; - size_t key_indices[4]; - size_t tweak_indices_len; - size_t tweak_indices[1]; - int is_xonly[1]; - enum MUSIG_ERROR error; -}; - -struct musig_key_agg_vector { - unsigned char pubkeys[7][33]; - unsigned char tweaks[2][32]; - struct musig_key_agg_valid_test_case valid_case[4]; - struct musig_key_agg_error_test_case error_case[5]; -}; - -static const struct musig_key_agg_vector musig_key_agg_vector = { - { - { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x03, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }, - { 0x02, 0x35, 0x90, 0xA9, 0x4E, 0x76, 0x8F, 0x8E, 0x18, 0x15, 0xC2, 0xF2, 0x4B, 0x4D, 0x80, 0xA8, 0xE3, 0x14, 0x93, 0x16, 0xC3, 0x51, 0x8C, 0xE7, 0xB7, 0xAD, 0x33, 0x83, 0x68, 0xD0, 0x38, 0xCA, 0x66 }, - { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 }, - { 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 }, - { 0x04, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 } - }, - { - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 }, - { 0x25, 0x2E, 0x4B, 0xD6, 0x74, 0x10, 0xA7, 0x6C, 0xDF, 0x93, 0x3D, 0x30, 0xEA, 0xA1, 0x60, 0x82, 0x14, 0x03, 0x7F, 0x1B, 0x10, 0x5A, 0x01, 0x3E, 0xCC, 0xD3, 0xC5, 0xC1, 0x84, 0xA6, 0x11, 0x0B } - }, - { - { 3, { 0, 1, 2 }, { 0x90, 0x53, 0x9E, 0xED, 0xE5, 0x65, 0xF5, 0xD0, 0x54, 0xF3, 0x2C, 0xC0, 0xC2, 0x20, 0x12, 0x68, 0x89, 0xED, 0x1E, 0x5D, 0x19, 0x3B, 0xAF, 0x15, 0xAE, 0xF3, 0x44, 0xFE, 0x59, 0xD4, 0x61, 0x0C }}, - { 3, { 2, 1, 0 }, { 0x62, 0x04, 0xDE, 0x8B, 0x08, 0x34, 0x26, 0xDC, 0x6E, 0xAF, 0x95, 0x02, 0xD2, 0x70, 0x24, 0xD5, 0x3F, 0xC8, 0x26, 0xBF, 0x7D, 0x20, 0x12, 0x14, 0x8A, 0x05, 0x75, 0x43, 0x5D, 0xF5, 0x4B, 0x2B }}, - { 3, { 0, 0, 0 }, { 0xB4, 0x36, 0xE3, 0xBA, 0xD6, 0x2B, 0x8C, 0xD4, 0x09, 0x96, 0x9A, 0x22, 0x47, 0x31, 0xC1, 0x93, 0xD0, 0x51, 0x16, 0x2D, 0x8C, 0x5A, 0xE8, 0xB1, 0x09, 0x30, 0x61, 0x27, 0xDA, 0x3A, 0xA9, 0x35 }}, - { 4, { 0, 0, 1, 1 }, { 0x69, 0xBC, 0x22, 0xBF, 0xA5, 0xD1, 0x06, 0x30, 0x6E, 0x48, 0xA2, 0x06, 0x79, 0xDE, 0x1D, 0x73, 0x89, 0x38, 0x61, 0x24, 0xD0, 0x75, 0x71, 0xD0, 0xD8, 0x72, 0x68, 0x60, 0x28, 0xC2, 0x6A, 0x3E }}, - }, - { - { 2, { 0, 3 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, - { 2, { 0, 4 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, - { 2, { 5, 0 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, - { 2, { 0, 1 }, 1, { 0 }, { 1 }, MUSIG_TWEAK }, - { 1, { 6 }, 1, { 1 }, { 0 }, MUSIG_TWEAK }, - }, -}; - -struct musig_nonce_gen_test_case { - unsigned char rand_[32]; - int has_sk; - unsigned char sk[32]; - unsigned char pk[33]; - int has_aggpk; - unsigned char aggpk[32]; - int has_msg; - unsigned char msg[32]; - int has_extra_in; - unsigned char extra_in[32]; - unsigned char expected_secnonce[97]; - unsigned char expected_pubnonce[66]; -}; - -struct musig_nonce_gen_vector { - struct musig_nonce_gen_test_case test_case[2]; -}; - -static const struct musig_nonce_gen_vector musig_nonce_gen_vector = { - { - { { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }, 1 , { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }, { 0x02, 0x4D, 0x4B, 0x6C, 0xD1, 0x36, 0x10, 0x32, 0xCA, 0x9B, 0xD2, 0xAE, 0xB9, 0xD9, 0x00, 0xAA, 0x4D, 0x45, 0xD9, 0xEA, 0xD8, 0x0A, 0xC9, 0x42, 0x33, 0x74, 0xC4, 0x51, 0xA7, 0x25, 0x4D, 0x07, 0x66 }, 1 , { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 }, 1 , { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, 1 , { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, { 0xB1, 0x14, 0xE5, 0x02, 0xBE, 0xAA, 0x4E, 0x30, 0x1D, 0xD0, 0x8A, 0x50, 0x26, 0x41, 0x72, 0xC8, 0x4E, 0x41, 0x65, 0x0E, 0x6C, 0xB7, 0x26, 0xB4, 0x10, 0xC0, 0x69, 0x4D, 0x59, 0xEF, 0xFB, 0x64, 0x95, 0xB5, 0xCA, 0xF2, 0x8D, 0x04, 0x5B, 0x97, 0x3D, 0x63, 0xE3, 0xC9, 0x9A, 0x44, 0xB8, 0x07, 0xBD, 0xE3, 0x75, 0xFD, 0x6C, 0xB3, 0x9E, 0x46, 0xDC, 0x4A, 0x51, 0x17, 0x08, 0xD0, 0xE9, 0xD2, 0x02, 0x4D, 0x4B, 0x6C, 0xD1, 0x36, 0x10, 0x32, 0xCA, 0x9B, 0xD2, 0xAE, 0xB9, 0xD9, 0x00, 0xAA, 0x4D, 0x45, 0xD9, 0xEA, 0xD8, 0x0A, 0xC9, 0x42, 0x33, 0x74, 0xC4, 0x51, 0xA7, 0x25, 0x4D, 0x07, 0x66 }, { 0x02, 0xF7, 0xBE, 0x70, 0x89, 0xE8, 0x37, 0x6E, 0xB3, 0x55, 0x27, 0x23, 0x68, 0x76, 0x6B, 0x17, 0xE8, 0x8E, 0x7D, 0xB7, 0x20, 0x47, 0xD0, 0x5E, 0x56, 0xAA, 0x88, 0x1E, 0xA5, 0x2B, 0x3B, 0x35, 0xDF, 0x02, 0xC2, 0x9C, 0x80, 0x46, 0xFD, 0xD0, 0xDE, 0xD4, 0xC7, 0xE5, 0x58, 0x69, 0x13, 0x72, 0x00, 0xFB, 0xDB, 0xFE, 0x2E, 0xB6, 0x54, 0x26, 0x7B, 0x6D, 0x70, 0x13, 0x60, 0x2C, 0xAE, 0xD3, 0x11, 0x5A } }, - { { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }, 0 , { 0 }, { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, 0 , { 0 }, 0 , { 0 }, 0 , { 0 }, { 0x89, 0xBD, 0xD7, 0x87, 0xD0, 0x28, 0x4E, 0x5E, 0x4D, 0x5F, 0xC5, 0x72, 0xE4, 0x9E, 0x31, 0x6B, 0xAB, 0x7E, 0x21, 0xE3, 0xB1, 0x83, 0x0D, 0xE3, 0x7D, 0xFE, 0x80, 0x15, 0x6F, 0xA4, 0x1A, 0x6D, 0x0B, 0x17, 0xAE, 0x8D, 0x02, 0x4C, 0x53, 0x67, 0x96, 0x99, 0xA6, 0xFD, 0x79, 0x44, 0xD9, 0xC4, 0xA3, 0x66, 0xB5, 0x14, 0xBA, 0xF4, 0x30, 0x88, 0xE0, 0x70, 0x8B, 0x10, 0x23, 0xDD, 0x28, 0x97, 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, { 0x02, 0xC9, 0x6E, 0x7C, 0xB1, 0xE8, 0xAA, 0x5D, 0xAC, 0x64, 0xD8, 0x72, 0x94, 0x79, 0x14, 0x19, 0x8F, 0x60, 0x7D, 0x90, 0xEC, 0xDE, 0x52, 0x00, 0xDE, 0x52, 0x97, 0x8A, 0xD5, 0xDE, 0xD6, 0x3C, 0x00, 0x02, 0x99, 0xEC, 0x51, 0x17, 0xC2, 0xD2, 0x9E, 0xDE, 0xE8, 0xA2, 0x09, 0x25, 0x87, 0xC3, 0x90, 0x9B, 0xE6, 0x94, 0xD5, 0xCF, 0xF0, 0x66, 0x7D, 0x6C, 0x02, 0xEA, 0x40, 0x59, 0xF7, 0xCD, 0x97, 0x86 } }, - }, -}; - -struct musig_nonce_agg_test_case { - size_t pnonce_indices[2]; - /* if valid case */ - unsigned char expected[66]; - /* if error case */ - int invalid_nonce_idx; -}; - -struct musig_nonce_agg_vector { - unsigned char pnonces[7][66]; - struct musig_nonce_agg_test_case valid_case[2]; - struct musig_nonce_agg_test_case error_case[3]; -}; - -static const struct musig_nonce_agg_vector musig_nonce_agg_vector = { - { - { 0x02, 0x01, 0x51, 0xC8, 0x0F, 0x43, 0x56, 0x48, 0xDF, 0x67, 0xA2, 0x2B, 0x74, 0x9C, 0xD7, 0x98, 0xCE, 0x54, 0xE0, 0x32, 0x1D, 0x03, 0x4B, 0x92, 0xB7, 0x09, 0xB5, 0x67, 0xD6, 0x0A, 0x42, 0xE6, 0x66, 0x03, 0xBA, 0x47, 0xFB, 0xC1, 0x83, 0x44, 0x37, 0xB3, 0x21, 0x2E, 0x89, 0xA8, 0x4D, 0x84, 0x25, 0xE7, 0xBF, 0x12, 0xE0, 0x24, 0x5D, 0x98, 0x26, 0x22, 0x68, 0xEB, 0xDC, 0xB3, 0x85, 0xD5, 0x06, 0x41 }, - { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x33 }, - { 0x02, 0x01, 0x51, 0xC8, 0x0F, 0x43, 0x56, 0x48, 0xDF, 0x67, 0xA2, 0x2B, 0x74, 0x9C, 0xD7, 0x98, 0xCE, 0x54, 0xE0, 0x32, 0x1D, 0x03, 0x4B, 0x92, 0xB7, 0x09, 0xB5, 0x67, 0xD6, 0x0A, 0x42, 0xE6, 0x66, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, - { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x03, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, - { 0x04, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x33 }, - { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x31 }, - { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 } - }, - { - { { 0, 1 }, { 0x03, 0x5F, 0xE1, 0x87, 0x3B, 0x4F, 0x29, 0x67, 0xF5, 0x2F, 0xEA, 0x4A, 0x06, 0xAD, 0x5A, 0x8E, 0xCC, 0xBE, 0x9D, 0x0F, 0xD7, 0x30, 0x68, 0x01, 0x2C, 0x89, 0x4E, 0x2E, 0x87, 0xCC, 0xB5, 0x80, 0x4B, 0x02, 0x47, 0x25, 0x37, 0x73, 0x45, 0xBD, 0xE0, 0xE9, 0xC3, 0x3A, 0xF3, 0xC4, 0x3C, 0x0A, 0x29, 0xA9, 0x24, 0x9F, 0x2F, 0x29, 0x56, 0xFA, 0x8C, 0xFE, 0xB5, 0x5C, 0x85, 0x73, 0xD0, 0x26, 0x2D, 0xC8 }, 0 }, - { { 2, 3 }, { 0x03, 0x5F, 0xE1, 0x87, 0x3B, 0x4F, 0x29, 0x67, 0xF5, 0x2F, 0xEA, 0x4A, 0x06, 0xAD, 0x5A, 0x8E, 0xCC, 0xBE, 0x9D, 0x0F, 0xD7, 0x30, 0x68, 0x01, 0x2C, 0x89, 0x4E, 0x2E, 0x87, 0xCC, 0xB5, 0x80, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0 }, - }, - { - { { 0, 4 }, { 0 }, 1 }, - { { 5, 1 }, { 0 }, 0 }, - { { 6, 1 }, { 0 }, 0 }, - }, -}; - -/* Omit pubnonces in the test vectors because our partial signature verification - * implementation is able to accept the aggnonce directly. */ -struct musig_valid_case { - size_t key_indices_len; - size_t key_indices[3]; - size_t aggnonce_index; - size_t msg_index; - size_t signer_index; - unsigned char expected[32]; -}; - -struct musig_sign_error_case { - size_t key_indices_len; - size_t key_indices[3]; - size_t aggnonce_index; - size_t msg_index; - size_t secnonce_index; - enum MUSIG_ERROR error; -}; - -struct musig_verify_fail_error_case { - unsigned char sig[32]; - size_t key_indices_len; - size_t key_indices[3]; - size_t nonce_indices_len; - size_t nonce_indices[3]; - size_t msg_index; - size_t signer_index; - enum MUSIG_ERROR error; -}; - -struct musig_sign_verify_vector { - unsigned char sk[32]; - unsigned char pubkeys[4][33]; - unsigned char secnonces[2][194]; - unsigned char pubnonces[5][194]; - unsigned char aggnonces[5][66]; - unsigned char msgs[1][32]; - struct musig_valid_case valid_case[4]; - struct musig_sign_error_case sign_error_case[6]; - struct musig_verify_fail_error_case verify_fail_case[3]; - struct musig_verify_fail_error_case verify_error_case[2]; -}; - -static const struct musig_sign_verify_vector musig_sign_verify_vector = { - { 0x7F, 0xB9, 0xE0, 0xE6, 0x87, 0xAD, 0xA1, 0xEE, 0xBF, 0x7E, 0xCF, 0xE2, 0xF2, 0x1E, 0x73, 0xEB, 0xDB, 0x51, 0xA7, 0xD4, 0x50, 0x94, 0x8D, 0xFE, 0x8D, 0x76, 0xD7, 0xF2, 0xD1, 0x00, 0x76, 0x71 }, - { - { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x61 }, - { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 } - }, - { - { 0x50, 0x8B, 0x81, 0xA6, 0x11, 0xF1, 0x00, 0xA6, 0xB2, 0xB6, 0xB2, 0x96, 0x56, 0x59, 0x08, 0x98, 0xAF, 0x48, 0x8B, 0xCF, 0x2E, 0x1F, 0x55, 0xCF, 0x22, 0xE5, 0xCF, 0xB8, 0x44, 0x21, 0xFE, 0x61, 0xFA, 0x27, 0xFD, 0x49, 0xB1, 0xD5, 0x00, 0x85, 0xB4, 0x81, 0x28, 0x5E, 0x1C, 0xA2, 0x05, 0xD5, 0x5C, 0x82, 0xCC, 0x1B, 0x31, 0xFF, 0x5C, 0xD5, 0x4A, 0x48, 0x98, 0x29, 0x35, 0x59, 0x01, 0xF7, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 } - }, - { - { 0x03, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, - { 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, - { 0x03, 0x2D, 0xE2, 0x66, 0x26, 0x28, 0xC9, 0x0B, 0x03, 0xF5, 0xE7, 0x20, 0x28, 0x4E, 0xB5, 0x2F, 0xF7, 0xD7, 0x1F, 0x42, 0x84, 0xF6, 0x27, 0xB6, 0x8A, 0x85, 0x3D, 0x78, 0xC7, 0x8E, 0x1F, 0xFE, 0x93, 0x03, 0xE4, 0xC5, 0x52, 0x4E, 0x83, 0xFF, 0xE1, 0x49, 0x3B, 0x90, 0x77, 0xCF, 0x1C, 0xA6, 0xBE, 0xB2, 0x09, 0x0C, 0x93, 0xD9, 0x30, 0x32, 0x10, 0x71, 0xAD, 0x40, 0xB2, 0xF4, 0x4E, 0x59, 0x90, 0x46 }, - { 0x02, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x03, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, - { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 } - }, - { - { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x04, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, - { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }, - { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 } - }, - { - { 0xF9, 0x54, 0x66, 0xD0, 0x86, 0x77, 0x0E, 0x68, 0x99, 0x64, 0x66, 0x42, 0x19, 0x26, 0x6F, 0xE5, 0xED, 0x21, 0x5C, 0x92, 0xAE, 0x20, 0xBA, 0xB5, 0xC9, 0xD7, 0x9A, 0xDD, 0xDD, 0xF3, 0xC0, 0xCF } - }, - { - { 3, { 0, 1, 2 }, 0, 0, 0, { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }}, - { 3, { 1, 0, 2 }, 0, 0, 1, { 0x9F, 0xF2, 0xF7, 0xAA, 0xA8, 0x56, 0x15, 0x0C, 0xC8, 0x81, 0x92, 0x54, 0x21, 0x8D, 0x3A, 0xDE, 0xEB, 0x05, 0x35, 0x26, 0x90, 0x51, 0x89, 0x77, 0x24, 0xF9, 0xDB, 0x37, 0x89, 0x51, 0x3A, 0x52 }}, - { 3, { 1, 2, 0 }, 0, 0, 2, { 0xFA, 0x23, 0xC3, 0x59, 0xF6, 0xFA, 0xC4, 0xE7, 0x79, 0x6B, 0xB9, 0x3B, 0xC9, 0xF0, 0x53, 0x2A, 0x95, 0x46, 0x8C, 0x53, 0x9B, 0xA2, 0x0F, 0xF8, 0x6D, 0x7C, 0x76, 0xED, 0x92, 0x22, 0x79, 0x00 }}, - { 2, { 0, 1 }, 1, 0, 0, { 0xAE, 0x38, 0x60, 0x64, 0xB2, 0x61, 0x05, 0x40, 0x47, 0x98, 0xF7, 0x5D, 0xE2, 0xEB, 0x9A, 0xF5, 0xED, 0xA5, 0x38, 0x7B, 0x06, 0x4B, 0x83, 0xD0, 0x49, 0xCB, 0x7C, 0x5E, 0x08, 0x87, 0x95, 0x31 }}, - }, - { - { 2, { 1, 2 }, 0, 0, 0, MUSIG_PUBKEY }, - { 3, { 1, 0, 3 }, 0, 0, 0, MUSIG_PUBKEY }, - { 3, { 1, 2, 0 }, 2, 0, 0, MUSIG_AGGNONCE }, - { 3, { 1, 2, 0 }, 3, 0, 0, MUSIG_AGGNONCE }, - { 3, { 1, 2, 0 }, 4, 0, 0, MUSIG_AGGNONCE }, - { 3, { 0, 1, 2 }, 0, 0, 1, MUSIG_SECNONCE }, - }, - { - { { 0xFE, 0xD5, 0x44, 0x34, 0xAD, 0x4C, 0xFE, 0x95, 0x3F, 0xC5, 0x27, 0xDC, 0x6A, 0x5E, 0x5B, 0xE8, 0xF6, 0x23, 0x49, 0x07, 0xB7, 0xC1, 0x87, 0x55, 0x95, 0x57, 0xCE, 0x87, 0xA0, 0x54, 0x1C, 0x46 }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_SIG_VERIFY }, - { { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 1, MUSIG_SIG_VERIFY }, - { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_SIG }, - }, - { - { { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }, 3, { 0, 1, 2 }, 3, { 4, 1, 2 }, 0, 0, MUSIG_PUBNONCE }, - { { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }, 3, { 3, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_PUBKEY }, - }, -}; - -struct musig_tweak_case { - size_t key_indices_len; - size_t key_indices[3]; - size_t nonce_indices_len; - size_t nonce_indices[3]; - size_t tweak_indices_len; - size_t tweak_indices[4]; - int is_xonly[4]; - size_t signer_index; - unsigned char expected[32]; -}; - -struct musig_tweak_vector { - unsigned char sk[32]; - unsigned char secnonce[97]; - unsigned char aggnonce[66]; - unsigned char msg[32]; - unsigned char pubkeys[3][33]; - unsigned char pubnonces[3][194]; - unsigned char tweaks[5][32]; - struct musig_tweak_case valid_case[5]; - struct musig_tweak_case error_case[1]; -}; - -static const struct musig_tweak_vector musig_tweak_vector = { - { 0x7F, 0xB9, 0xE0, 0xE6, 0x87, 0xAD, 0xA1, 0xEE, 0xBF, 0x7E, 0xCF, 0xE2, 0xF2, 0x1E, 0x73, 0xEB, 0xDB, 0x51, 0xA7, 0xD4, 0x50, 0x94, 0x8D, 0xFE, 0x8D, 0x76, 0xD7, 0xF2, 0xD1, 0x00, 0x76, 0x71 }, - { 0x50, 0x8B, 0x81, 0xA6, 0x11, 0xF1, 0x00, 0xA6, 0xB2, 0xB6, 0xB2, 0x96, 0x56, 0x59, 0x08, 0x98, 0xAF, 0x48, 0x8B, 0xCF, 0x2E, 0x1F, 0x55, 0xCF, 0x22, 0xE5, 0xCF, 0xB8, 0x44, 0x21, 0xFE, 0x61, 0xFA, 0x27, 0xFD, 0x49, 0xB1, 0xD5, 0x00, 0x85, 0xB4, 0x81, 0x28, 0x5E, 0x1C, 0xA2, 0x05, 0xD5, 0x5C, 0x82, 0xCC, 0x1B, 0x31, 0xFF, 0x5C, 0xD5, 0x4A, 0x48, 0x98, 0x29, 0x35, 0x59, 0x01, 0xF7, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, - { 0xF9, 0x54, 0x66, 0xD0, 0x86, 0x77, 0x0E, 0x68, 0x99, 0x64, 0x66, 0x42, 0x19, 0x26, 0x6F, 0xE5, 0xED, 0x21, 0x5C, 0x92, 0xAE, 0x20, 0xBA, 0xB5, 0xC9, 0xD7, 0x9A, 0xDD, 0xDD, 0xF3, 0xC0, 0xCF }, - { - { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 } - }, - { - { 0x03, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, - { 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, - { 0x03, 0x2D, 0xE2, 0x66, 0x26, 0x28, 0xC9, 0x0B, 0x03, 0xF5, 0xE7, 0x20, 0x28, 0x4E, 0xB5, 0x2F, 0xF7, 0xD7, 0x1F, 0x42, 0x84, 0xF6, 0x27, 0xB6, 0x8A, 0x85, 0x3D, 0x78, 0xC7, 0x8E, 0x1F, 0xFE, 0x93, 0x03, 0xE4, 0xC5, 0x52, 0x4E, 0x83, 0xFF, 0xE1, 0x49, 0x3B, 0x90, 0x77, 0xCF, 0x1C, 0xA6, 0xBE, 0xB2, 0x09, 0x0C, 0x93, 0xD9, 0x30, 0x32, 0x10, 0x71, 0xAD, 0x40, 0xB2, 0xF4, 0x4E, 0x59, 0x90, 0x46 } - }, - { - { 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB }, - { 0xAE, 0x2E, 0xA7, 0x97, 0xCC, 0x0F, 0xE7, 0x2A, 0xC5, 0xB9, 0x7B, 0x97, 0xF3, 0xC6, 0x95, 0x7D, 0x7E, 0x41, 0x99, 0xA1, 0x67, 0xA5, 0x8E, 0xB0, 0x8B, 0xCA, 0xFF, 0xDA, 0x70, 0xAC, 0x04, 0x55 }, - { 0xF5, 0x2E, 0xCB, 0xC5, 0x65, 0xB3, 0xD8, 0xBE, 0xA2, 0xDF, 0xD5, 0xB7, 0x5A, 0x4F, 0x45, 0x7E, 0x54, 0x36, 0x98, 0x09, 0x32, 0x2E, 0x41, 0x20, 0x83, 0x16, 0x26, 0xF2, 0x90, 0xFA, 0x87, 0xE0 }, - { 0x19, 0x69, 0xAD, 0x73, 0xCC, 0x17, 0x7F, 0xA0, 0xB4, 0xFC, 0xED, 0x6D, 0xF1, 0xF7, 0xBF, 0x99, 0x07, 0xE6, 0x65, 0xFD, 0xE9, 0xBA, 0x19, 0x6A, 0x74, 0xFE, 0xD0, 0xA3, 0xCF, 0x5A, 0xEF, 0x9D }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 } - }, - { - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 0 }, { 1 }, 2, { 0xE2, 0x8A, 0x5C, 0x66, 0xE6, 0x1E, 0x17, 0x8C, 0x2B, 0xA1, 0x9D, 0xB7, 0x7B, 0x6C, 0xF9, 0xF7, 0xE2, 0xF0, 0xF5, 0x6C, 0x17, 0x91, 0x8C, 0xD1, 0x31, 0x35, 0xE6, 0x0C, 0xC8, 0x48, 0xFE, 0x91 }}, - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 0 }, { 0 }, 2, { 0x38, 0xB0, 0x76, 0x77, 0x98, 0x25, 0x2F, 0x21, 0xBF, 0x57, 0x02, 0xC4, 0x80, 0x28, 0xB0, 0x95, 0x42, 0x83, 0x20, 0xF7, 0x3A, 0x4B, 0x14, 0xDB, 0x1E, 0x25, 0xDE, 0x58, 0x54, 0x3D, 0x2D, 0x2D }}, - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 2, { 0, 1 }, { 0, 1 }, 2, { 0x40, 0x8A, 0x0A, 0x21, 0xC4, 0xA0, 0xF5, 0xDA, 0xCA, 0xF9, 0x64, 0x6A, 0xD6, 0xEB, 0x6F, 0xEC, 0xD7, 0xF7, 0xA1, 0x1F, 0x03, 0xED, 0x1F, 0x48, 0xDF, 0xFF, 0x21, 0x85, 0xBC, 0x2C, 0x24, 0x08 }}, - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 4, { 0, 1, 2, 3 }, { 0, 0, 1, 1 }, 2, { 0x45, 0xAB, 0xD2, 0x06, 0xE6, 0x1E, 0x3D, 0xF2, 0xEC, 0x9E, 0x26, 0x4A, 0x6F, 0xEC, 0x82, 0x92, 0x14, 0x1A, 0x63, 0x3C, 0x28, 0x58, 0x63, 0x88, 0x23, 0x55, 0x41, 0xF9, 0xAD, 0xE7, 0x54, 0x35 }}, - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 4, { 0, 1, 2, 3 }, { 1, 0, 1, 0 }, 2, { 0xB2, 0x55, 0xFD, 0xCA, 0xC2, 0x7B, 0x40, 0xC7, 0xCE, 0x78, 0x48, 0xE2, 0xD3, 0xB7, 0xBF, 0x5E, 0xA0, 0xED, 0x75, 0x6D, 0xA8, 0x15, 0x65, 0xAC, 0x80, 0x4C, 0xCC, 0xA3, 0xE1, 0xD5, 0xD2, 0x39 }}, - }, - { - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 4 }, { 0 }, 2, { 0 }}, - }, -}; - -/* Omit pubnonces in the test vectors because they're only needed for - * implementations that do not directly accept an aggnonce. */ -struct musig_sig_agg_case { - size_t key_indices_len; - size_t key_indices[2]; - size_t tweak_indices_len; - size_t tweak_indices[3]; - int is_xonly[3]; - unsigned char aggnonce[66]; - size_t psig_indices_len; - size_t psig_indices[2]; - /* if valid case */ - unsigned char expected[64]; - /* if error case */ - int invalid_sig_idx; -}; - -struct musig_sig_agg_vector { - unsigned char pubkeys[4][33]; - unsigned char tweaks[3][32]; - unsigned char psigs[9][32]; - unsigned char msg[32]; - struct musig_sig_agg_case valid_case[4]; - struct musig_sig_agg_case error_case[1]; -}; - -static const struct musig_sig_agg_vector musig_sig_agg_vector = { - { - { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x02, 0xD2, 0xDC, 0x6F, 0x5D, 0xF7, 0xC5, 0x6A, 0xCF, 0x38, 0xC7, 0xFA, 0x0A, 0xE7, 0xA7, 0x59, 0xAE, 0x30, 0xE1, 0x9B, 0x37, 0x35, 0x9D, 0xFD, 0xE0, 0x15, 0x87, 0x23, 0x24, 0xC7, 0xEF, 0x6E, 0x05 }, - { 0x03, 0xC7, 0xFB, 0x10, 0x1D, 0x97, 0xFF, 0x93, 0x0A, 0xCD, 0x0C, 0x67, 0x60, 0x85, 0x2E, 0xF6, 0x4E, 0x69, 0x08, 0x3D, 0xE0, 0xB0, 0x6A, 0xC6, 0x33, 0x57, 0x24, 0x75, 0x4B, 0xB4, 0xB0, 0x52, 0x2C }, - { 0x02, 0x35, 0x24, 0x33, 0xB2, 0x1E, 0x7E, 0x05, 0xD3, 0xB4, 0x52, 0xB8, 0x1C, 0xAE, 0x56, 0x6E, 0x06, 0xD2, 0xE0, 0x03, 0xEC, 0xE1, 0x6D, 0x10, 0x74, 0xAA, 0xBA, 0x42, 0x89, 0xE0, 0xE3, 0xD5, 0x81 } - }, - { - { 0xB5, 0x11, 0xDA, 0x49, 0x21, 0x82, 0xA9, 0x1B, 0x0F, 0xFB, 0x9A, 0x98, 0x02, 0x0D, 0x55, 0xF2, 0x60, 0xAE, 0x86, 0xD7, 0xEC, 0xBD, 0x03, 0x99, 0xC7, 0x38, 0x3D, 0x59, 0xA5, 0xF2, 0xAF, 0x7C }, - { 0xA8, 0x15, 0xFE, 0x04, 0x9E, 0xE3, 0xC5, 0xAA, 0xB6, 0x63, 0x10, 0x47, 0x7F, 0xBC, 0x8B, 0xCC, 0xCA, 0xC2, 0xF3, 0x39, 0x5F, 0x59, 0xF9, 0x21, 0xC3, 0x64, 0xAC, 0xD7, 0x8A, 0x2F, 0x48, 0xDC }, - { 0x75, 0x44, 0x8A, 0x87, 0x27, 0x4B, 0x05, 0x64, 0x68, 0xB9, 0x77, 0xBE, 0x06, 0xEB, 0x1E, 0x9F, 0x65, 0x75, 0x77, 0xB7, 0x32, 0x0B, 0x0A, 0x33, 0x76, 0xEA, 0x51, 0xFD, 0x42, 0x0D, 0x18, 0xA8 } - }, - { - { 0xB1, 0x5D, 0x2C, 0xD3, 0xC3, 0xD2, 0x2B, 0x04, 0xDA, 0xE4, 0x38, 0xCE, 0x65, 0x3F, 0x6B, 0x4E, 0xCF, 0x04, 0x2F, 0x42, 0xCF, 0xDE, 0xD7, 0xC4, 0x1B, 0x64, 0xAA, 0xF9, 0xB4, 0xAF, 0x53, 0xFB }, - { 0x61, 0x93, 0xD6, 0xAC, 0x61, 0xB3, 0x54, 0xE9, 0x10, 0x5B, 0xBD, 0xC8, 0x93, 0x7A, 0x34, 0x54, 0xA6, 0xD7, 0x05, 0xB6, 0xD5, 0x73, 0x22, 0xA5, 0xA4, 0x72, 0xA0, 0x2C, 0xE9, 0x9F, 0xCB, 0x64 }, - { 0x9A, 0x87, 0xD3, 0xB7, 0x9E, 0xC6, 0x72, 0x28, 0xCB, 0x97, 0x87, 0x8B, 0x76, 0x04, 0x9B, 0x15, 0xDB, 0xD0, 0x5B, 0x81, 0x58, 0xD1, 0x7B, 0x5B, 0x91, 0x14, 0xD3, 0xC2, 0x26, 0x88, 0x75, 0x05 }, - { 0x66, 0xF8, 0x2E, 0xA9, 0x09, 0x23, 0x68, 0x9B, 0x85, 0x5D, 0x36, 0xC6, 0xB7, 0xE0, 0x32, 0xFB, 0x99, 0x70, 0x30, 0x14, 0x81, 0xB9, 0x9E, 0x01, 0xCD, 0xB4, 0xD6, 0xAC, 0x7C, 0x34, 0x7A, 0x15 }, - { 0x4F, 0x5A, 0xEE, 0x41, 0x51, 0x08, 0x48, 0xA6, 0x44, 0x7D, 0xCD, 0x1B, 0xBC, 0x78, 0x45, 0x7E, 0xF6, 0x90, 0x24, 0x94, 0x4C, 0x87, 0xF4, 0x02, 0x50, 0xD3, 0xEF, 0x2C, 0x25, 0xD3, 0x3E, 0xFE }, - { 0xDD, 0xEF, 0x42, 0x7B, 0xBB, 0x84, 0x7C, 0xC0, 0x27, 0xBE, 0xFF, 0x4E, 0xDB, 0x01, 0x03, 0x81, 0x48, 0x91, 0x78, 0x32, 0x25, 0x3E, 0xBC, 0x35, 0x5F, 0xC3, 0x3F, 0x4A, 0x8E, 0x2F, 0xCC, 0xE4 }, - { 0x97, 0xB8, 0x90, 0xA2, 0x6C, 0x98, 0x1D, 0xA8, 0x10, 0x2D, 0x3B, 0xC2, 0x94, 0x15, 0x9D, 0x17, 0x1D, 0x72, 0x81, 0x0F, 0xDF, 0x7C, 0x6A, 0x69, 0x1D, 0xEF, 0x02, 0xF0, 0xF7, 0xAF, 0x3F, 0xDC }, - { 0x53, 0xFA, 0x9E, 0x08, 0xBA, 0x52, 0x43, 0xCB, 0xCB, 0x0D, 0x79, 0x7C, 0x5E, 0xE8, 0x3B, 0xC6, 0x72, 0x8E, 0x53, 0x9E, 0xB7, 0x6C, 0x2D, 0x0B, 0xF0, 0xF9, 0x71, 0xEE, 0x4E, 0x90, 0x99, 0x71 }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 } - }, - { 0x59, 0x9C, 0x67, 0xEA, 0x41, 0x0D, 0x00, 0x5B, 0x9D, 0xA9, 0x08, 0x17, 0xCF, 0x03, 0xED, 0x3B, 0x1C, 0x86, 0x8E, 0x4D, 0xA4, 0xED, 0xF0, 0x0A, 0x58, 0x80, 0xB0, 0x08, 0x2C, 0x23, 0x78, 0x69 }, - { - { 2, { 0, 1 }, 0, { 0 }, { 0 }, { 0x03, 0x41, 0x43, 0x27, 0x22, 0xC5, 0xCD, 0x02, 0x68, 0xD8, 0x29, 0xC7, 0x02, 0xCF, 0x0D, 0x1C, 0xBC, 0xE5, 0x70, 0x33, 0xEE, 0xD2, 0x01, 0xFD, 0x33, 0x51, 0x91, 0x38, 0x52, 0x27, 0xC3, 0x21, 0x0C, 0x03, 0xD3, 0x77, 0xF2, 0xD2, 0x58, 0xB6, 0x4A, 0xAD, 0xC0, 0xE1, 0x6F, 0x26, 0x46, 0x23, 0x23, 0xD7, 0x01, 0xD2, 0x86, 0x04, 0x6A, 0x2E, 0xA9, 0x33, 0x65, 0x65, 0x6A, 0xFD, 0x98, 0x75, 0x98, 0x2B }, 2, { 0, 1 }, { 0x04, 0x1D, 0xA2, 0x22, 0x23, 0xCE, 0x65, 0xC9, 0x2C, 0x9A, 0x0D, 0x6C, 0x2C, 0xAC, 0x82, 0x8A, 0xAF, 0x1E, 0xEE, 0x56, 0x30, 0x4F, 0xEC, 0x37, 0x1D, 0xDF, 0x91, 0xEB, 0xB2, 0xB9, 0xEF, 0x09, 0x12, 0xF1, 0x03, 0x80, 0x25, 0x85, 0x7F, 0xED, 0xEB, 0x3F, 0xF6, 0x96, 0xF8, 0xB9, 0x9F, 0xA4, 0xBB, 0x2C, 0x58, 0x12, 0xF6, 0x09, 0x5A, 0x2E, 0x00, 0x04, 0xEC, 0x99, 0xCE, 0x18, 0xDE, 0x1E }, 0 }, - { 2, { 0, 2 }, 0, { 0 }, { 0 }, { 0x02, 0x24, 0xAF, 0xD3, 0x6C, 0x90, 0x20, 0x84, 0x05, 0x8B, 0x51, 0xB5, 0xD3, 0x66, 0x76, 0xBB, 0xA4, 0xDC, 0x97, 0xC7, 0x75, 0x87, 0x37, 0x68, 0xE5, 0x88, 0x22, 0xF8, 0x7F, 0xE4, 0x37, 0xD7, 0x92, 0x02, 0x8C, 0xB1, 0x59, 0x29, 0x09, 0x9E, 0xEE, 0x2F, 0x5D, 0xAE, 0x40, 0x4C, 0xD3, 0x93, 0x57, 0x59, 0x1B, 0xA3, 0x2E, 0x9A, 0xF4, 0xE1, 0x62, 0xB8, 0xD3, 0xE7, 0xCB, 0x5E, 0xFE, 0x31, 0xCB, 0x20 }, 2, { 2, 3 }, { 0x10, 0x69, 0xB6, 0x7E, 0xC3, 0xD2, 0xF3, 0xC7, 0xC0, 0x82, 0x91, 0xAC, 0xCB, 0x17, 0xA9, 0xC9, 0xB8, 0xF2, 0x81, 0x9A, 0x52, 0xEB, 0x5D, 0xF8, 0x72, 0x6E, 0x17, 0xE7, 0xD6, 0xB5, 0x2E, 0x9F, 0x01, 0x80, 0x02, 0x60, 0xA7, 0xE9, 0xDA, 0xC4, 0x50, 0xF4, 0xBE, 0x52, 0x2D, 0xE4, 0xCE, 0x12, 0xBA, 0x91, 0xAE, 0xAF, 0x2B, 0x42, 0x79, 0x21, 0x9E, 0xF7, 0x4B, 0xE1, 0xD2, 0x86, 0xAD, 0xD9 }, 0 }, - { 2, { 0, 2 }, 1, { 0 }, { 0 }, { 0x02, 0x08, 0xC5, 0xC4, 0x38, 0xC7, 0x10, 0xF4, 0xF9, 0x6A, 0x61, 0xE9, 0xFF, 0x3C, 0x37, 0x75, 0x88, 0x14, 0xB8, 0xC3, 0xAE, 0x12, 0xBF, 0xEA, 0x0E, 0xD2, 0xC8, 0x7F, 0xF6, 0x95, 0x4F, 0xF1, 0x86, 0x02, 0x0B, 0x18, 0x16, 0xEA, 0x10, 0x4B, 0x4F, 0xCA, 0x2D, 0x30, 0x4D, 0x73, 0x3E, 0x0E, 0x19, 0xCE, 0xAD, 0x51, 0x30, 0x3F, 0xF6, 0x42, 0x0B, 0xFD, 0x22, 0x23, 0x35, 0xCA, 0xA4, 0x02, 0x91, 0x6D }, 2, { 4, 5 }, { 0x5C, 0x55, 0x8E, 0x1D, 0xCA, 0xDE, 0x86, 0xDA, 0x0B, 0x2F, 0x02, 0x62, 0x6A, 0x51, 0x2E, 0x30, 0xA2, 0x2C, 0xF5, 0x25, 0x5C, 0xAE, 0xA7, 0xEE, 0x32, 0xC3, 0x8E, 0x9A, 0x71, 0xA0, 0xE9, 0x14, 0x8B, 0xA6, 0xC0, 0xE6, 0xEC, 0x76, 0x83, 0xB6, 0x42, 0x20, 0xF0, 0x29, 0x86, 0x96, 0xF1, 0xB8, 0x78, 0xCD, 0x47, 0xB1, 0x07, 0xB8, 0x1F, 0x71, 0x88, 0x81, 0x2D, 0x59, 0x39, 0x71, 0xE0, 0xCC }, 0 }, - { 2, { 0, 3 }, 3, { 0, 1, 2 }, { 1, 0, 1 }, { 0x02, 0xB5, 0xAD, 0x07, 0xAF, 0xCD, 0x99, 0xB6, 0xD9, 0x2C, 0xB4, 0x33, 0xFB, 0xD2, 0xA2, 0x8F, 0xDE, 0xB9, 0x8E, 0xAE, 0x2E, 0xB0, 0x9B, 0x60, 0x14, 0xEF, 0x0F, 0x81, 0x97, 0xCD, 0x58, 0x40, 0x33, 0x02, 0xE8, 0x61, 0x69, 0x10, 0xF9, 0x29, 0x3C, 0xF6, 0x92, 0xC4, 0x9F, 0x35, 0x1D, 0xB8, 0x6B, 0x25, 0xE3, 0x52, 0x90, 0x1F, 0x0E, 0x23, 0x7B, 0xAF, 0xDA, 0x11, 0xF1, 0xC1, 0xCE, 0xF2, 0x9F, 0xFD }, 2, { 6, 7 }, { 0x83, 0x9B, 0x08, 0x82, 0x0B, 0x68, 0x1D, 0xBA, 0x8D, 0xAF, 0x4C, 0xC7, 0xB1, 0x04, 0xE8, 0xF2, 0x63, 0x8F, 0x93, 0x88, 0xF8, 0xD7, 0xA5, 0x55, 0xDC, 0x17, 0xB6, 0xE6, 0x97, 0x1D, 0x74, 0x26, 0xCE, 0x07, 0xBF, 0x6A, 0xB0, 0x1F, 0x1D, 0xB5, 0x0E, 0x4E, 0x33, 0x71, 0x92, 0x95, 0xF4, 0x09, 0x45, 0x72, 0xB7, 0x98, 0x68, 0xE4, 0x40, 0xFB, 0x3D, 0xEF, 0xD3, 0xFA, 0xC1, 0xDB, 0x58, 0x9E }, 0 }, - }, - { - { 2, { 0, 3 }, 3, { 0, 1, 2 }, { 1, 0, 1 }, { 0x02, 0xB5, 0xAD, 0x07, 0xAF, 0xCD, 0x99, 0xB6, 0xD9, 0x2C, 0xB4, 0x33, 0xFB, 0xD2, 0xA2, 0x8F, 0xDE, 0xB9, 0x8E, 0xAE, 0x2E, 0xB0, 0x9B, 0x60, 0x14, 0xEF, 0x0F, 0x81, 0x97, 0xCD, 0x58, 0x40, 0x33, 0x02, 0xE8, 0x61, 0x69, 0x10, 0xF9, 0x29, 0x3C, 0xF6, 0x92, 0xC4, 0x9F, 0x35, 0x1D, 0xB8, 0x6B, 0x25, 0xE3, 0x52, 0x90, 0x1F, 0x0E, 0x23, 0x7B, 0xAF, 0xDA, 0x11, 0xF1, 0xC1, 0xCE, 0xF2, 0x9F, 0xFD }, 2, { 7, 8 }, { 0 }, 1 }, - }, -}; -enum { MUSIG_VECTORS_MAX_PUBKEYS = 7 }; diff --git a/external/secp256k1/src/modules/recovery/Makefile.am.include b/external/secp256k1/src/modules/recovery/Makefile.am.include deleted file mode 100644 index 156ea690fa..0000000000 --- a/external/secp256k1/src/modules/recovery/Makefile.am.include +++ /dev/null @@ -1,5 +0,0 @@ -include_HEADERS += include/secp256k1_recovery.h -noinst_HEADERS += src/modules/recovery/main_impl.h -noinst_HEADERS += src/modules/recovery/tests_impl.h -noinst_HEADERS += src/modules/recovery/tests_exhaustive_impl.h -noinst_HEADERS += src/modules/recovery/bench_impl.h diff --git a/external/secp256k1/src/modules/recovery/bench_impl.h b/external/secp256k1/src/modules/recovery/bench_impl.h deleted file mode 100644 index 57108d4524..0000000000 --- a/external/secp256k1/src/modules/recovery/bench_impl.h +++ /dev/null @@ -1,62 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_RECOVERY_BENCH_H -#define SECP256K1_MODULE_RECOVERY_BENCH_H - -#include "../../../include/secp256k1_recovery.h" - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - unsigned char sig[64]; -} bench_recover_data; - -static void bench_recover(void* arg, int iters) { - int i; - bench_recover_data *data = (bench_recover_data*)arg; - secp256k1_pubkey pubkey; - unsigned char pubkeyc[33]; - - for (i = 0; i < iters; i++) { - int j; - size_t pubkeylen = 33; - secp256k1_ecdsa_recoverable_signature sig; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); - CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); - for (j = 0; j < 32; j++) { - data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ - data->msg[j] = data->sig[j]; /* Move former R to message. */ - data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ - } - } -} - -static void bench_recover_setup(void* arg) { - int i; - bench_recover_data *data = (bench_recover_data*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = 1 + i; - } - for (i = 0; i < 64; i++) { - data->sig[i] = 65 + i; - } -} - -static void run_recovery_bench(int iters, int argc, char** argv) { - bench_recover_data data; - int d = argc == 1; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - - if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters); - - secp256k1_context_destroy(data.ctx); -} - -#endif /* SECP256K1_MODULE_RECOVERY_BENCH_H */ diff --git a/external/secp256k1/src/modules/recovery/main_impl.h b/external/secp256k1/src/modules/recovery/main_impl.h deleted file mode 100644 index 76a005e017..0000000000 --- a/external/secp256k1/src/modules/recovery/main_impl.h +++ /dev/null @@ -1,159 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_RECOVERY_MAIN_H -#define SECP256K1_MODULE_RECOVERY_MAIN_H - -#include "../../../include/secp256k1_recovery.h" - -static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const secp256k1_ecdsa_recoverable_signature* sig) { - (void)ctx; - if (sizeof(secp256k1_scalar) == 32) { - /* When the secp256k1_scalar type is exactly 32 byte, use its - * representation inside secp256k1_ecdsa_signature, as conversion is very fast. - * Note that secp256k1_ecdsa_signature_save must use the same representation. */ - memcpy(r, &sig->data[0], 32); - memcpy(s, &sig->data[32], 32); - } else { - secp256k1_scalar_set_b32(r, &sig->data[0], NULL); - secp256k1_scalar_set_b32(s, &sig->data[32], NULL); - } - *recid = sig->data[64]; -} - -static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s, int recid) { - if (sizeof(secp256k1_scalar) == 32) { - memcpy(&sig->data[0], r, 32); - memcpy(&sig->data[32], s, 32); - } else { - secp256k1_scalar_get_b32(&sig->data[0], r); - secp256k1_scalar_get_b32(&sig->data[32], s); - } - sig->data[64] = recid; -} - -int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { - secp256k1_scalar r, s; - int ret = 1; - int overflow = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(input64 != NULL); - ARG_CHECK(recid >= 0 && recid <= 3); - - secp256k1_scalar_set_b32(&r, &input64[0], &overflow); - ret &= !overflow; - secp256k1_scalar_set_b32(&s, &input64[32], &overflow); - ret &= !overflow; - if (ret) { - secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); - } else { - memset(sig, 0, sizeof(*sig)); - } - return ret; -} - -int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output64 != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(recid != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); - secp256k1_scalar_get_b32(&output64[0], &r); - secp256k1_scalar_get_b32(&output64[32], &s); - return 1; -} - -int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const secp256k1_ecdsa_recoverable_signature* sigin) { - secp256k1_scalar r, s; - int recid; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(sigin != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); - secp256k1_ecdsa_signature_save(sig, &r, &s); - return 1; -} - -static int secp256k1_ecdsa_sig_recover(const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) { - unsigned char brx[32]; - secp256k1_fe fx; - secp256k1_ge x; - secp256k1_gej xj; - secp256k1_scalar rn, u1, u2; - secp256k1_gej qj; - int r; - - if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { - return 0; - } - - secp256k1_scalar_get_b32(brx, sigr); - r = secp256k1_fe_set_b32_limit(&fx, brx); - (void)r; - VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */ - if (recid & 2) { - if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) { - return 0; - } - secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe); - } - if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) { - return 0; - } - secp256k1_gej_set_ge(&xj, &x); - secp256k1_scalar_inverse_var(&rn, sigr); - secp256k1_scalar_mul(&u1, &rn, message); - secp256k1_scalar_negate(&u1, &u1); - secp256k1_scalar_mul(&u2, &rn, sigs); - secp256k1_ecmult(&qj, &xj, &u2, &u1); - secp256k1_ge_set_gej_var(pubkey, &qj); - return !secp256k1_gej_is_infinity(&qj); -} - -int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar r, s; - int ret, recid; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msghash32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(seckey != NULL); - - ret = secp256k1_ecdsa_sign_inner(ctx, &r, &s, &recid, msghash32, seckey, noncefp, noncedata); - secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); - return ret; -} - -int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msghash32) { - secp256k1_ge q; - secp256k1_scalar r, s; - secp256k1_scalar m; - int recid; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(msghash32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); - VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ - secp256k1_scalar_set_b32(&m, msghash32, NULL); - if (secp256k1_ecdsa_sig_recover(&r, &s, &q, &m, recid)) { - secp256k1_pubkey_save(pubkey, &q); - return 1; - } else { - memset(pubkey, 0, sizeof(*pubkey)); - return 0; - } -} - -#endif /* SECP256K1_MODULE_RECOVERY_MAIN_H */ diff --git a/external/secp256k1/src/modules/recovery/tests_exhaustive_impl.h b/external/secp256k1/src/modules/recovery/tests_exhaustive_impl.h deleted file mode 100644 index 6bbc02b9a8..0000000000 --- a/external/secp256k1/src/modules/recovery/tests_exhaustive_impl.h +++ /dev/null @@ -1,148 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2016 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H -#define SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H - -#include "main_impl.h" -#include "../../../include/secp256k1_recovery.h" - -static void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group) { - int i, j, k; - uint64_t iter = 0; - - /* Loop */ - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { /* message */ - for (j = 1; j < EXHAUSTIVE_TEST_ORDER; j++) { /* key */ - if (skip_section(&iter)) continue; - for (k = 1; k < EXHAUSTIVE_TEST_ORDER; k++) { /* nonce */ - const int starting_k = k; - secp256k1_fe r_dot_y_normalized; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - secp256k1_scalar sk, msg, r, s, expected_r; - unsigned char sk32[32], msg32[32]; - int expected_recid; - int recid; - int overflow; - secp256k1_scalar_set_int(&msg, i); - secp256k1_scalar_set_int(&sk, j); - secp256k1_scalar_get_b32(sk32, &sk); - secp256k1_scalar_get_b32(msg32, &msg); - - secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); - - /* Check directly */ - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); - r_from_k(&expected_r, group, k, &overflow); - CHECK(r == expected_r); - CHECK((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER); - /* The recid's second bit is for conveying overflow (R.x value >= group order). - * In the actual secp256k1 this is an astronomically unlikely event, but in the - * small group used here, it will almost certainly be the case for all points. - * Note that this isn't actually useful; full recovery would need to convey - * floor(R.x / group_order), but only one bit is used as that is sufficient - * in the real group. */ - expected_recid = overflow ? 2 : 0; - r_dot_y_normalized = group[k].y; - secp256k1_fe_normalize(&r_dot_y_normalized); - /* Also the recovery id is flipped depending if we hit the low-s branch */ - if ((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER) { - expected_recid |= secp256k1_fe_is_odd(&r_dot_y_normalized); - } else { - expected_recid |= !secp256k1_fe_is_odd(&r_dot_y_normalized); - } - CHECK(recid == expected_recid); - - /* Convert to a standard sig then check */ - secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); - /* Note that we compute expected_r *after* signing -- this is important - * because our nonce-computing function function might change k during - * signing. */ - r_from_k(&expected_r, group, k, NULL); - CHECK(r == expected_r); - CHECK((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER); - - /* Overflow means we've tried every possible nonce */ - if (k < starting_k) { - break; - } - } - } - } -} - -static void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group) { - /* This is essentially a copy of test_exhaustive_verify, with recovery added */ - int s, r, msg, key; - uint64_t iter = 0; - for (s = 1; s < EXHAUSTIVE_TEST_ORDER; s++) { - for (r = 1; r < EXHAUSTIVE_TEST_ORDER; r++) { - for (msg = 1; msg < EXHAUSTIVE_TEST_ORDER; msg++) { - for (key = 1; key < EXHAUSTIVE_TEST_ORDER; key++) { - secp256k1_ge nonconst_ge; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pk; - secp256k1_scalar sk_s, msg_s, r_s, s_s; - secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; - int recid = 0; - int k, should_verify; - unsigned char msg32[32]; - - if (skip_section(&iter)) continue; - - secp256k1_scalar_set_int(&s_s, s); - secp256k1_scalar_set_int(&r_s, r); - secp256k1_scalar_set_int(&msg_s, msg); - secp256k1_scalar_set_int(&sk_s, key); - secp256k1_scalar_get_b32(msg32, &msg_s); - - /* Verify by hand */ - /* Run through every k value that gives us this r and check that *one* works. - * Note there could be none, there could be multiple, ECDSA is weird. */ - should_verify = 0; - for (k = 0; k < EXHAUSTIVE_TEST_ORDER; k++) { - secp256k1_scalar check_x_s; - r_from_k(&check_x_s, group, k, NULL); - if (r_s == check_x_s) { - secp256k1_scalar_set_int(&s_times_k_s, k); - secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); - } - } - /* nb we have a "high s" rule */ - should_verify &= !secp256k1_scalar_is_high(&s_s); - - /* We would like to try recovering the pubkey and checking that it matches, - * but pubkey recovery is impossible in the exhaustive tests (the reason - * being that there are 12 nonzero r values, 12 nonzero points, and no - * overlap between the sets, so there are no valid signatures). */ - - /* Verify by converting to a standard signature and calling verify */ - secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); - secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - secp256k1_pubkey_save(&pk, &nonconst_ge); - CHECK(should_verify == - secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); - } - } - } - } -} - -static void test_exhaustive_recovery(const secp256k1_context *ctx, const secp256k1_ge *group) { - test_exhaustive_recovery_sign(ctx, group); - test_exhaustive_recovery_verify(ctx, group); -} - -#endif /* SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H */ diff --git a/external/secp256k1/src/modules/recovery/tests_impl.h b/external/secp256k1/src/modules/recovery/tests_impl.h deleted file mode 100644 index 7a28a3ce65..0000000000 --- a/external/secp256k1/src/modules/recovery/tests_impl.h +++ /dev/null @@ -1,338 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_RECOVERY_TESTS_H -#define SECP256K1_MODULE_RECOVERY_TESTS_H - -static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - (void) msg32; - (void) key32; - (void) algo16; - (void) data; - - /* On the first run, return 0 to force a second run */ - if (counter == 0) { - memset(nonce32, 0, 32); - return 1; - } - /* On the second run, return an overflow to force a third run */ - if (counter == 1) { - memset(nonce32, 0xff, 32); - return 1; - } - /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ - memset(nonce32, 1, 32); - return testrand_bits(1); -} - -static void test_ecdsa_recovery_api(void) { - /* Setup contexts that just count errors */ - secp256k1_pubkey pubkey; - secp256k1_pubkey recpubkey; - secp256k1_ecdsa_signature normal_sig; - secp256k1_ecdsa_recoverable_signature recsig; - unsigned char privkey[32] = { 1 }; - unsigned char message[32] = { 2 }; - int recid = 0; - unsigned char sig[74]; - unsigned char zero_privkey[32] = { 0 }; - unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(CTX, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, privkey) == 1); - - /* Check bad contexts and NULLs for signing */ - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_sign_recoverable(CTX, NULL, message, privkey, NULL, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_sign_recoverable(CTX, &recsig, NULL, privkey, NULL, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_sign_recoverable(CTX, &recsig, message, NULL, NULL, NULL)); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_ecdsa_sign_recoverable(STATIC_CTX, &recsig, message, privkey, NULL, NULL)); - /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ - secp256k1_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, recovery_test_nonce_function, NULL); - /* These will all fail, but not in ARG_CHECK way */ - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &recsig, message, zero_privkey, NULL, NULL) == 0); - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &recsig, message, over_privkey, NULL, NULL) == 0); - /* This one will succeed. */ - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); - - /* Check signing with a goofy nonce function */ - - /* Check bad contexts and NULLs for recovery */ - CHECK(secp256k1_ecdsa_recover(CTX, &recpubkey, &recsig, message) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recover(CTX, NULL, &recsig, message)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recover(CTX, &recpubkey, NULL, message)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recover(CTX, &recpubkey, &recsig, NULL)); - - /* Check NULLs for conversion */ - CHECK(secp256k1_ecdsa_sign(CTX, &normal_sig, message, privkey, NULL, NULL) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_convert(CTX, NULL, &recsig)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_convert(CTX, &normal_sig, NULL)); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(CTX, &normal_sig, &recsig) == 1); - - /* Check NULLs for de/serialization */ - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_serialize_compact(CTX, NULL, &recid, &recsig)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_serialize_compact(CTX, sig, NULL, &recsig)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, NULL)); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &recsig) == 1); - - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, NULL, sig, recid)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, NULL, recid)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, -1)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, 5)); - /* overflow in signature will not result in calling illegal_callback */ - memcpy(sig, over_privkey, 32); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, recid) == 0); -} - -static void test_ecdsa_recovery_end_to_end(void) { - unsigned char extra[32] = {0x00}; - unsigned char privkey[32]; - unsigned char message[32]; - secp256k1_ecdsa_signature signature[5]; - secp256k1_ecdsa_recoverable_signature rsignature[5]; - unsigned char sig[74]; - secp256k1_pubkey pubkey; - secp256k1_pubkey recpubkey; - int recid = 0; - - /* Generate a random key and message. */ - { - secp256k1_scalar msg, key; - testutil_random_scalar_order_test(&msg); - testutil_random_scalar_order_test(&key); - secp256k1_scalar_get_b32(privkey, &key); - secp256k1_scalar_get_b32(message, &msg); - } - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(CTX, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, privkey) == 1); - - /* Serialize/parse compact and verify/recover. */ - extra[0] = 0; - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &rsignature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(CTX, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &rsignature[4], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &rsignature[1], message, privkey, NULL, extra) == 1); - extra[31] = 1; - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &rsignature[2], message, privkey, NULL, extra) == 1); - extra[31] = 0; - extra[0] = 1; - CHECK(secp256k1_ecdsa_sign_recoverable(CTX, &rsignature[3], message, privkey, NULL, extra) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); - CHECK(secp256k1_memcmp_var(&signature[4], &signature[0], 64) == 0); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 1); - memset(&rsignature[4], 0, sizeof(rsignature[4])); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 1); - /* Parse compact (with recovery id) and recover. */ - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recover(CTX, &recpubkey, &rsignature[4], message) == 1); - CHECK(secp256k1_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) == 0); - /* Serialize/destroy/parse signature and verify again. */ - CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1); - sig[testrand_bits(6)] += 1 + testrand_int(255); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); - CHECK(secp256k1_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 0); - /* Recover again */ - CHECK(secp256k1_ecdsa_recover(CTX, &recpubkey, &rsignature[4], message) == 0 || - secp256k1_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) != 0); -} - -/* Tests several edge cases. */ -static void test_ecdsa_recovery_edge_cases(void) { - const unsigned char msg32[32] = { - 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', - 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', - 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', - 's', 's', 'a', 'g', 'e', '.', '.', '.' - }; - const unsigned char sig64[64] = { - /* Generated by signing the above message with nonce 'This is the nonce we will use...' - * and secret key 0 (which is not valid), resulting in recid 1. */ - 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, - 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, - 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, - 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, - 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, - 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, - 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, - 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 - }; - secp256k1_pubkey pubkey; - /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ - const unsigned char sigb64[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - secp256k1_pubkey pubkeyb; - secp256k1_ecdsa_recoverable_signature rsig; - secp256k1_ecdsa_signature sig; - int recid; - - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 0)); - CHECK(!secp256k1_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 1)); - CHECK(secp256k1_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 2)); - CHECK(!secp256k1_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 3)); - CHECK(!secp256k1_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); - - for (recid = 0; recid < 4; recid++) { - int i; - int recid2; - /* (4,4) encoded in DER. */ - unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; - unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01}; - unsigned char sigcder_zs[7] = {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x00}; - unsigned char sigbderalt1[39] = { - 0x30, 0x25, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, - }; - unsigned char sigbderalt2[39] = { - 0x30, 0x25, 0x02, 0x01, 0x04, 0x02, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - unsigned char sigbderalt3[40] = { - 0x30, 0x26, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04, - }; - unsigned char sigbderalt4[40] = { - 0x30, 0x26, 0x02, 0x01, 0x04, 0x02, 0x21, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - }; - /* (order + r,4) encoded in DER. */ - unsigned char sigbderlong[40] = { - 0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, - 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, - 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 - }; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigb64, recid) == 1); - CHECK(secp256k1_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 1); - for (recid2 = 0; recid2 < 4; recid2++) { - secp256k1_pubkey pubkey2b; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigb64, recid2) == 1); - CHECK(secp256k1_ecdsa_recover(CTX, &pubkey2b, &rsig, msg32) == 1); - /* Verifying with (order + r,4) should always fail. */ - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbderlong, sizeof(sigbderlong)) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); - } - /* DER parsing tests. */ - /* Zero length r/s. */ - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); - /* Leading zeros. */ - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); - sigbderalt3[4] = 1; - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); - sigbderalt4[7] = 1; - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); - /* Damage signature. */ - sigbder[7]++; - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); - sigbder[7]--; - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbder, 6) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder) - 1) == 0); - for(i = 0; i < 8; i++) { - int c; - unsigned char orig = sigbder[i]; - /*Try every single-byte change.*/ - for (c = 0; c < 256; c++) { - if (c == orig ) { - continue; - } - sigbder[i] = c; - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); - } - sigbder[i] = orig; - } - } - - /* Test r/s equal to zero */ - { - /* (1,1) encoded in DER. */ - unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01}; - unsigned char sigc64[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - secp256k1_pubkey pubkeyc; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(CTX, &pubkeyc, &rsig, msg32) == 1); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 1); - sigcder[4] = 0; - sigc64[31] = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 0); - sigcder[4] = 1; - sigcder[7] = 0; - sigc64[31] = 1; - sigc64[63] = 0; - CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 0); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 0); - } -} - -static void run_recovery_tests(void) { - int i; - for (i = 0; i < COUNT; i++) { - test_ecdsa_recovery_api(); - } - for (i = 0; i < 64*COUNT; i++) { - test_ecdsa_recovery_end_to_end(); - } - test_ecdsa_recovery_edge_cases(); -} - -#endif /* SECP256K1_MODULE_RECOVERY_TESTS_H */ diff --git a/external/secp256k1/src/modules/schnorrsig/Makefile.am.include b/external/secp256k1/src/modules/schnorrsig/Makefile.am.include deleted file mode 100644 index 654fa2e5ae..0000000000 --- a/external/secp256k1/src/modules/schnorrsig/Makefile.am.include +++ /dev/null @@ -1,5 +0,0 @@ -include_HEADERS += include/secp256k1_schnorrsig.h -noinst_HEADERS += src/modules/schnorrsig/main_impl.h -noinst_HEADERS += src/modules/schnorrsig/tests_impl.h -noinst_HEADERS += src/modules/schnorrsig/tests_exhaustive_impl.h -noinst_HEADERS += src/modules/schnorrsig/bench_impl.h diff --git a/external/secp256k1/src/modules/schnorrsig/bench_impl.h b/external/secp256k1/src/modules/schnorrsig/bench_impl.h deleted file mode 100644 index 93a878ede3..0000000000 --- a/external/secp256k1/src/modules/schnorrsig/bench_impl.h +++ /dev/null @@ -1,104 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_SCHNORRSIG_BENCH_H -#define SECP256K1_MODULE_SCHNORRSIG_BENCH_H - -#include "../../../include/secp256k1_schnorrsig.h" - -#define MSGLEN 32 - -typedef struct { - secp256k1_context *ctx; - int n; - - const secp256k1_keypair **keypairs; - const unsigned char **pk; - const unsigned char **sigs; - const unsigned char **msgs; -} bench_schnorrsig_data; - -static void bench_schnorrsig_sign(void* arg, int iters) { - bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; - int i; - unsigned char msg[MSGLEN] = {0}; - unsigned char sig[64]; - - for (i = 0; i < iters; i++) { - msg[0] = i; - msg[1] = i >> 8; - CHECK(secp256k1_schnorrsig_sign_custom(data->ctx, sig, msg, MSGLEN, data->keypairs[i], NULL)); - } -} - -static void bench_schnorrsig_verify(void* arg, int iters) { - bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; - int i; - - for (i = 0; i < iters; i++) { - secp256k1_xonly_pubkey pk; - CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pk[i]) == 1); - CHECK(secp256k1_schnorrsig_verify(data->ctx, data->sigs[i], data->msgs[i], MSGLEN, &pk)); - } -} - -static void run_schnorrsig_bench(int iters, int argc, char** argv) { - int i; - bench_schnorrsig_data data; - int d = argc == 1; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *)); - data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); - data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); - data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); - - CHECK(MSGLEN >= 4); - for (i = 0; i < iters; i++) { - unsigned char sk[32]; - unsigned char *msg = (unsigned char *)malloc(MSGLEN); - unsigned char *sig = (unsigned char *)malloc(64); - secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair)); - unsigned char *pk_char = (unsigned char *)malloc(32); - secp256k1_xonly_pubkey pk; - msg[0] = sk[0] = i; - msg[1] = sk[1] = i >> 8; - msg[2] = sk[2] = i >> 16; - msg[3] = sk[3] = i >> 24; - memset(&msg[4], 'm', MSGLEN - 4); - memset(&sk[4], 's', 28); - - data.keypairs[i] = keypair; - data.pk[i] = pk_char; - data.msgs[i] = msg; - data.sigs[i] = sig; - - CHECK(secp256k1_keypair_create(data.ctx, keypair, sk)); - CHECK(secp256k1_schnorrsig_sign_custom(data.ctx, sig, msg, MSGLEN, keypair, NULL)); - CHECK(secp256k1_keypair_xonly_pub(data.ctx, &pk, NULL, keypair)); - CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1); - } - - if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "schnorrsig_sign")) run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters); - if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "schnorrsig_verify")) run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters); - - for (i = 0; i < iters; i++) { - free((void *)data.keypairs[i]); - free((void *)data.pk[i]); - free((void *)data.msgs[i]); - free((void *)data.sigs[i]); - } - - /* Casting to (void *) avoids a stupid warning in MSVC. */ - free((void *)data.keypairs); - free((void *)data.pk); - free((void *)data.msgs); - free((void *)data.sigs); - - secp256k1_context_destroy(data.ctx); -} - -#endif diff --git a/external/secp256k1/src/modules/schnorrsig/main_impl.h b/external/secp256k1/src/modules/schnorrsig/main_impl.h deleted file mode 100644 index 82bba2f597..0000000000 --- a/external/secp256k1/src/modules/schnorrsig/main_impl.h +++ /dev/null @@ -1,269 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_SCHNORRSIG_MAIN_H -#define SECP256K1_MODULE_SCHNORRSIG_MAIN_H - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_schnorrsig.h" -#include "../../hash.h" - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */ -static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x46615b35ul; - sha->s[1] = 0xf4bfbff7ul; - sha->s[2] = 0x9f8dc671ul; - sha->s[3] = 0x83627ab3ul; - sha->s[4] = 0x60217180ul; - sha->s[5] = 0x57358661ul; - sha->s[6] = 0x21a29e54ul; - sha->s[7] = 0x68b07b4cul; - - sha->bytes = 64; -} - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */ -static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x24dd3219ul; - sha->s[1] = 0x4eba7e70ul; - sha->s[2] = 0xca0fabb9ul; - sha->s[3] = 0x0fa3166dul; - sha->s[4] = 0x3afbe4b1ul; - sha->s[5] = 0x4c44df97ul; - sha->s[6] = 0x4aac2739ul; - sha->s[7] = 0x249e850aul; - - sha->bytes = 64; -} - -/* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340 - * by using the correct tagged hash function. */ -static const unsigned char bip340_algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; - -static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC; - -static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { - secp256k1_sha256 sha; - unsigned char masked_key[32]; - int i; - - if (algo == NULL) { - return 0; - } - - if (data != NULL) { - secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha); - secp256k1_sha256_write(&sha, data, 32); - secp256k1_sha256_finalize(&sha, masked_key); - for (i = 0; i < 32; i++) { - masked_key[i] ^= key32[i]; - } - } else { - /* Precomputed TaggedHash("BIP0340/aux", 0x0000...00); */ - static const unsigned char ZERO_MASK[32] = { - 84, 241, 105, 207, 201, 226, 229, 114, - 116, 128, 68, 31, 144, 186, 37, 196, - 136, 244, 97, 199, 11, 94, 165, 220, - 170, 247, 175, 105, 39, 10, 165, 20 - }; - for (i = 0; i < 32; i++) { - masked_key[i] = key32[i] ^ ZERO_MASK[i]; - } - } - - /* Tag the hash with algo which is important to avoid nonce reuse across - * algorithms. If this nonce function is used in BIP-340 signing as defined - * in the spec, an optimized tagging implementation is used. */ - if (algolen == sizeof(bip340_algo) - && secp256k1_memcmp_var(algo, bip340_algo, algolen) == 0) { - secp256k1_nonce_function_bip340_sha256_tagged(&sha); - } else { - secp256k1_sha256_initialize_tagged(&sha, algo, algolen); - } - - /* Hash masked-key||pk||msg using the tagged hash as per the spec */ - secp256k1_sha256_write(&sha, masked_key, 32); - secp256k1_sha256_write(&sha, xonly_pk32, 32); - secp256k1_sha256_write(&sha, msg, msglen); - secp256k1_sha256_finalize(&sha, nonce32); - secp256k1_sha256_clear(&sha); - return 1; -} - -const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_function_bip340; - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */ -static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x9cecba11ul; - sha->s[1] = 0x23925381ul; - sha->s[2] = 0x11679112ul; - sha->s[3] = 0xd1627e0ful; - sha->s[4] = 0x97c87550ul; - sha->s[5] = 0x003cc765ul; - sha->s[6] = 0x90f61164ul; - sha->s[7] = 0x33e9b66aul; - sha->bytes = 64; -} - -static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) -{ - unsigned char buf[32]; - secp256k1_sha256 sha; - - /* tagged hash(r.x, pk.x, msg) */ - secp256k1_schnorrsig_sha256_tagged(&sha); - secp256k1_sha256_write(&sha, r32, 32); - secp256k1_sha256_write(&sha, pubkey32, 32); - secp256k1_sha256_write(&sha, msg, msglen); - secp256k1_sha256_finalize(&sha, buf); - /* Set scalar e to the challenge hash modulo the curve order as per - * BIP340. */ - secp256k1_scalar_set_b32(e, buf, NULL); -} - -static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) { - secp256k1_scalar sk; - secp256k1_scalar e; - secp256k1_scalar k; - secp256k1_gej rj; - secp256k1_ge pk; - secp256k1_ge r; - unsigned char buf[32] = { 0 }; - unsigned char pk_buf[32]; - unsigned char seckey[32]; - int ret = 1; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(msg != NULL || msglen == 0); - ARG_CHECK(keypair != NULL); - - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_bip340; - } - - ret &= secp256k1_keypair_load(ctx, &sk, &pk, keypair); - /* Because we are signing for a x-only pubkey, the secret key is negated - * before signing if the point corresponding to the secret key does not - * have an even Y. */ - if (secp256k1_fe_is_odd(&pk.y)) { - secp256k1_scalar_negate(&sk, &sk); - } - - secp256k1_scalar_get_b32(seckey, &sk); - secp256k1_fe_get_b32(pk_buf, &pk.x); - ret &= !!noncefp(buf, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); - secp256k1_scalar_set_b32(&k, buf, NULL); - ret &= !secp256k1_scalar_is_zero(&k); - secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); - - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k); - secp256k1_ge_set_gej(&r, &rj); - - /* We declassify r to allow using it as a branch point. This is fine - * because r is not a secret. */ - secp256k1_declassify(ctx, &r, sizeof(r)); - secp256k1_fe_normalize_var(&r.y); - if (secp256k1_fe_is_odd(&r.y)) { - secp256k1_scalar_negate(&k, &k); - } - secp256k1_fe_normalize_var(&r.x); - secp256k1_fe_get_b32(&sig64[0], &r.x); - - secp256k1_schnorrsig_challenge(&e, &sig64[0], msg, msglen, pk_buf); - secp256k1_scalar_mul(&e, &e, &sk); - secp256k1_scalar_add(&e, &e, &k); - secp256k1_scalar_get_b32(&sig64[32], &e); - - secp256k1_memczero(sig64, 64, !ret); - secp256k1_scalar_clear(&k); - secp256k1_scalar_clear(&sk); - secp256k1_memclear(seckey, sizeof(seckey)); - secp256k1_gej_clear(&rj); - - return ret; -} - -int secp256k1_schnorrsig_sign32(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) { - /* We cast away const from the passed aux_rand32 argument since we know the default nonce function does not modify it. */ - return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, secp256k1_nonce_function_bip340, (unsigned char*)aux_rand32); -} - -int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) { - return secp256k1_schnorrsig_sign32(ctx, sig64, msg32, keypair, aux_rand32); -} - -int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_schnorrsig_extraparams *extraparams) { - secp256k1_nonce_function_hardened noncefp = NULL; - void *ndata = NULL; - VERIFY_CHECK(ctx != NULL); - - if (extraparams != NULL) { - ARG_CHECK(secp256k1_memcmp_var(extraparams->magic, - schnorrsig_extraparams_magic, - sizeof(extraparams->magic)) == 0); - noncefp = extraparams->noncefp; - ndata = extraparams->ndata; - } - return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata); -} - -int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_xonly_pubkey *pubkey) { - secp256k1_scalar s; - secp256k1_scalar e; - secp256k1_gej rj; - secp256k1_ge pk; - secp256k1_gej pkj; - secp256k1_fe rx; - secp256k1_ge r; - unsigned char buf[32]; - int overflow; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(msg != NULL || msglen == 0); - ARG_CHECK(pubkey != NULL); - - if (!secp256k1_fe_set_b32_limit(&rx, &sig64[0])) { - return 0; - } - - secp256k1_scalar_set_b32(&s, &sig64[32], &overflow); - if (overflow) { - return 0; - } - - if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) { - return 0; - } - - /* Compute e. */ - secp256k1_fe_get_b32(buf, &pk.x); - secp256k1_schnorrsig_challenge(&e, &sig64[0], msg, msglen, buf); - - /* Compute rj = s*G + (-e)*pkj */ - secp256k1_scalar_negate(&e, &e); - secp256k1_gej_set_ge(&pkj, &pk); - secp256k1_ecmult(&rj, &pkj, &e, &s); - - secp256k1_ge_set_gej_var(&r, &rj); - if (secp256k1_ge_is_infinity(&r)) { - return 0; - } - - secp256k1_fe_normalize_var(&r.y); - return !secp256k1_fe_is_odd(&r.y) && - secp256k1_fe_equal(&rx, &r.x); -} - -#endif diff --git a/external/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h b/external/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h deleted file mode 100644 index 601b54975d..0000000000 --- a/external/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h +++ /dev/null @@ -1,214 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_H -#define SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_H - -#include "../../../include/secp256k1_schnorrsig.h" -#include "main_impl.h" - -static const unsigned char invalid_pubkey_bytes[][32] = { - /* 0 */ - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }, - /* 2 */ - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 - }, - /* order */ - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 24) & 0xFF, - ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 16) & 0xFF, - ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 8) & 0xFF, - (EXHAUSTIVE_TEST_ORDER + 0UL) & 0xFF - }, - /* order + 1 */ - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 24) & 0xFF, - ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 16) & 0xFF, - ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 8) & 0xFF, - (EXHAUSTIVE_TEST_ORDER + 1UL) & 0xFF - }, - /* field size */ - { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F - }, - /* field size + 1 (note that 1 is legal) */ - { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 - }, - /* 2^256 - 1 */ - { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF - } -}; - -#define NUM_INVALID_KEYS (sizeof(invalid_pubkey_bytes) / sizeof(invalid_pubkey_bytes[0])) - -static int secp256k1_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg, - size_t msglen, - const unsigned char *key32, const unsigned char *xonly_pk32, - const unsigned char *algo, size_t algolen, - void* data) { - secp256k1_scalar s; - int *idata = data; - (void)msg; - (void)msglen; - (void)key32; - (void)xonly_pk32; - (void)algo; - (void)algolen; - secp256k1_scalar_set_int(&s, *idata); - secp256k1_scalar_get_b32(nonce32, &s); - return 1; -} - -static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, const secp256k1_xonly_pubkey* pubkeys, unsigned char (*xonly_pubkey_bytes)[32], const int* parities) { - int d; - uint64_t iter = 0; - /* Iterate over the possible public keys to verify against (through their corresponding DL d). */ - for (d = 1; d <= EXHAUSTIVE_TEST_ORDER / 2; ++d) { - int actual_d; - unsigned k; - unsigned char pk32[32]; - memcpy(pk32, xonly_pubkey_bytes[d - 1], 32); - actual_d = parities[d - 1] ? EXHAUSTIVE_TEST_ORDER - d : d; - /* Iterate over the possible valid first 32 bytes in the signature, through their corresponding DL k. - Values above EXHAUSTIVE_TEST_ORDER/2 refer to the entries in invalid_pubkey_bytes. */ - for (k = 1; k <= EXHAUSTIVE_TEST_ORDER / 2 + NUM_INVALID_KEYS; ++k) { - unsigned char sig64[64]; - int actual_k = -1; - int e_done[EXHAUSTIVE_TEST_ORDER] = {0}; - int e_count_done = 0; - if (skip_section(&iter)) continue; - if (k <= EXHAUSTIVE_TEST_ORDER / 2) { - memcpy(sig64, xonly_pubkey_bytes[k - 1], 32); - actual_k = parities[k - 1] ? EXHAUSTIVE_TEST_ORDER - k : k; - } else { - memcpy(sig64, invalid_pubkey_bytes[k - 1 - EXHAUSTIVE_TEST_ORDER / 2], 32); - } - /* Randomly generate messages until all challenges have been hit. */ - while (e_count_done < EXHAUSTIVE_TEST_ORDER) { - secp256k1_scalar e; - unsigned char msg32[32]; - testrand256(msg32); - secp256k1_schnorrsig_challenge(&e, sig64, msg32, sizeof(msg32), pk32); - /* Only do work if we hit a challenge we haven't tried before. */ - if (!e_done[e]) { - /* Iterate over the possible valid last 32 bytes in the signature. - 0..order=that s value; order+1=random bytes */ - int count_valid = 0; - unsigned int s; - for (s = 0; s <= EXHAUSTIVE_TEST_ORDER + 1; ++s) { - int expect_valid, valid; - if (s <= EXHAUSTIVE_TEST_ORDER) { - memset(sig64 + 32, 0, 32); - secp256k1_write_be32(sig64 + 60, s); - expect_valid = actual_k != -1 && s != EXHAUSTIVE_TEST_ORDER && - (s == (actual_k + actual_d * e) % EXHAUSTIVE_TEST_ORDER); - } else { - testrand256(sig64 + 32); - expect_valid = 0; - } - valid = secp256k1_schnorrsig_verify(ctx, sig64, msg32, sizeof(msg32), &pubkeys[d - 1]); - CHECK(valid == expect_valid); - count_valid += valid; - } - /* Exactly one s value must verify, unless R is illegal. */ - CHECK(count_valid == (actual_k != -1)); - /* Don't retry other messages that result in the same challenge. */ - e_done[e] = 1; - ++e_count_done; - } - } - } - } -} - -static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const secp256k1_keypair* keypairs, const int* parities) { - int d, k; - uint64_t iter = 0; - secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; - - /* Loop over keys. */ - for (d = 1; d < EXHAUSTIVE_TEST_ORDER; ++d) { - int actual_d = d; - if (parities[d - 1]) actual_d = EXHAUSTIVE_TEST_ORDER - d; - /* Loop over nonces. */ - for (k = 1; k < EXHAUSTIVE_TEST_ORDER; ++k) { - int e_done[EXHAUSTIVE_TEST_ORDER] = {0}; - int e_count_done = 0; - unsigned char msg32[32]; - unsigned char sig64[64]; - int actual_k = k; - if (skip_section(&iter)) continue; - extraparams.noncefp = secp256k1_hardened_nonce_function_smallint; - extraparams.ndata = &k; - if (parities[k - 1]) actual_k = EXHAUSTIVE_TEST_ORDER - k; - /* Generate random messages until all challenges have been tried. */ - while (e_count_done < EXHAUSTIVE_TEST_ORDER) { - secp256k1_scalar e; - testrand256(msg32); - secp256k1_schnorrsig_challenge(&e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]); - /* Only do work if we hit a challenge we haven't tried before. */ - if (!e_done[e]) { - secp256k1_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER; - unsigned char expected_s_bytes[32]; - secp256k1_scalar_get_b32(expected_s_bytes, &expected_s); - /* Invoke the real function to construct a signature. */ - CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig64, msg32, sizeof(msg32), &keypairs[d - 1], &extraparams)); - /* The first 32 bytes must match the xonly pubkey for the specified k. */ - CHECK(secp256k1_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0); - /* The last 32 bytes must match the expected s value. */ - CHECK(secp256k1_memcmp_var(sig64 + 32, expected_s_bytes, 32) == 0); - /* Don't retry other messages that result in the same challenge. */ - e_done[e] = 1; - ++e_count_done; - } - } - } - } -} - -static void test_exhaustive_schnorrsig(const secp256k1_context *ctx) { - secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; - secp256k1_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; - int parity[EXHAUSTIVE_TEST_ORDER - 1]; - unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; - unsigned i; - - /* Verify that all invalid_pubkey_bytes are actually invalid. */ - for (i = 0; i < NUM_INVALID_KEYS; ++i) { - secp256k1_xonly_pubkey pk; - CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk, invalid_pubkey_bytes[i])); - } - - /* Construct keypairs and xonly-pubkeys for the entire group. */ - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; ++i) { - secp256k1_scalar scalar_i; - unsigned char buf[32]; - secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_scalar_get_b32(buf, &scalar_i); - CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf)); - CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parity[i - 1], &keypair[i - 1])); - CHECK(secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); - } - - test_exhaustive_schnorrsig_sign(ctx, xonly_pubkey_bytes, keypair, parity); - test_exhaustive_schnorrsig_verify(ctx, xonly_pubkey, xonly_pubkey_bytes, parity); -} - -#endif diff --git a/external/secp256k1/src/modules/schnorrsig/tests_impl.h b/external/secp256k1/src/modules/schnorrsig/tests_impl.h deleted file mode 100644 index 2d716a01f8..0000000000 --- a/external/secp256k1/src/modules/schnorrsig/tests_impl.h +++ /dev/null @@ -1,982 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_SCHNORRSIG_TESTS_H -#define SECP256K1_MODULE_SCHNORRSIG_TESTS_H - -#include "../../../include/secp256k1_schnorrsig.h" - -/* Checks that a bit flip in the n_flip-th argument (that has n_bytes many - * bytes) changes the hash function - */ -static void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t msglen, size_t algolen) { - unsigned char nonces[2][32]; - CHECK(nonce_function_bip340(nonces[0], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); - testrand_flip(args[n_flip], n_bytes); - CHECK(nonce_function_bip340(nonces[1], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); - CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0); -} - -static void run_nonce_function_bip340_tests(void) { - unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; - unsigned char aux_tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'a', 'u', 'x'}; - unsigned char algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; - size_t algolen = sizeof(algo); - secp256k1_sha256 sha; - secp256k1_sha256 sha_optimized; - unsigned char nonce[32], nonce_z[32]; - unsigned char msg[32]; - size_t msglen = sizeof(msg); - unsigned char key[32]; - unsigned char pk[32]; - unsigned char aux_rand[32]; - unsigned char *args[5]; - int i; - - /* Check that hash initialized by - * secp256k1_nonce_function_bip340_sha256_tagged has the expected - * state. */ - secp256k1_sha256_initialize_tagged(&sha, tag, sizeof(tag)); - secp256k1_nonce_function_bip340_sha256_tagged(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); - - /* Check that hash initialized by - * secp256k1_nonce_function_bip340_sha256_tagged_aux has the expected - * state. */ - secp256k1_sha256_initialize_tagged(&sha, aux_tag, sizeof(aux_tag)); - secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); - - testrand256(msg); - testrand256(key); - testrand256(pk); - testrand256(aux_rand); - - /* Check that a bitflip in an argument results in different nonces. */ - args[0] = msg; - args[1] = key; - args[2] = pk; - args[3] = algo; - args[4] = aux_rand; - for (i = 0; i < COUNT; i++) { - nonce_function_bip340_bitflip(args, 0, 32, msglen, algolen); - nonce_function_bip340_bitflip(args, 1, 32, msglen, algolen); - nonce_function_bip340_bitflip(args, 2, 32, msglen, algolen); - /* Flip algo special case "BIP0340/nonce" */ - nonce_function_bip340_bitflip(args, 3, algolen, msglen, algolen); - /* Flip algo again */ - nonce_function_bip340_bitflip(args, 3, algolen, msglen, algolen); - nonce_function_bip340_bitflip(args, 4, 32, msglen, algolen); - } - - /* NULL algo is disallowed */ - CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, NULL, 0, NULL) == 0); - CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); - /* Other algo is fine */ - testrand_bytes_test(algo, algolen); - CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); - - for (i = 0; i < COUNT; i++) { - unsigned char nonce2[32]; - uint32_t offset = testrand_int(msglen - 1); - size_t msglen_tmp = (msglen + offset) % msglen; - size_t algolen_tmp; - - /* Different msglen gives different nonce */ - CHECK(nonce_function_bip340(nonce2, msg, msglen_tmp, key, pk, algo, algolen, NULL) == 1); - CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); - - /* Different algolen gives different nonce */ - offset = testrand_int(algolen - 1); - algolen_tmp = (algolen + offset) % algolen; - CHECK(nonce_function_bip340(nonce2, msg, msglen, key, pk, algo, algolen_tmp, NULL) == 1); - CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); - } - - /* NULL aux_rand argument is allowed, and identical to passing all zero aux_rand. */ - memset(aux_rand, 0, 32); - CHECK(nonce_function_bip340(nonce_z, msg, msglen, key, pk, algo, algolen, &aux_rand) == 1); - CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); - CHECK(secp256k1_memcmp_var(nonce_z, nonce, 32) == 0); -} - -static void test_schnorrsig_api(void) { - unsigned char sk1[32]; - unsigned char sk2[32]; - unsigned char sk3[32]; - unsigned char msg[32]; - secp256k1_keypair keypairs[3]; - secp256k1_keypair invalid_keypair = {{ 0 }}; - secp256k1_xonly_pubkey pk[3]; - secp256k1_xonly_pubkey zero_pk; - unsigned char sig[64]; - secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; - secp256k1_schnorrsig_extraparams invalid_extraparams = {{ 0 }, NULL, NULL}; - - testrand256(sk1); - testrand256(sk2); - testrand256(sk3); - testrand256(msg); - CHECK(secp256k1_keypair_create(CTX, &keypairs[0], sk1) == 1); - CHECK(secp256k1_keypair_create(CTX, &keypairs[1], sk2) == 1); - CHECK(secp256k1_keypair_create(CTX, &keypairs[2], sk3) == 1); - CHECK(secp256k1_keypair_xonly_pub(CTX, &pk[0], NULL, &keypairs[0]) == 1); - CHECK(secp256k1_keypair_xonly_pub(CTX, &pk[1], NULL, &keypairs[1]) == 1); - CHECK(secp256k1_keypair_xonly_pub(CTX, &pk[2], NULL, &keypairs[2]) == 1); - memset(&zero_pk, 0, sizeof(zero_pk)); - - /** main test body **/ - CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypairs[0], NULL) == 1); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign32(CTX, NULL, msg, &keypairs[0], NULL)); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign32(CTX, sig, NULL, &keypairs[0], NULL)); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign32(CTX, sig, msg, NULL, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign32(CTX, sig, msg, &invalid_keypair, NULL)); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_schnorrsig_sign32(STATIC_CTX, sig, msg, &keypairs[0], NULL)); - - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign_custom(CTX, NULL, msg, sizeof(msg), &keypairs[0], &extraparams)); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign_custom(CTX, sig, NULL, sizeof(msg), &keypairs[0], &extraparams)); - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, NULL, 0, &keypairs[0], &extraparams) == 1); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), NULL, &extraparams)); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &invalid_keypair, &extraparams)); - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams)); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_schnorrsig_sign_custom(STATIC_CTX, sig, msg, sizeof(msg), &keypairs[0], &extraparams)); - - CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypairs[0], NULL) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk[0]) == 1); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_verify(CTX, NULL, msg, sizeof(msg), &pk[0])); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_verify(CTX, sig, NULL, sizeof(msg), &pk[0])); - CHECK(secp256k1_schnorrsig_verify(CTX, sig, NULL, 0, &pk[0]) == 0); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), NULL)); - CHECK_ILLEGAL(CTX, secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &zero_pk)); -} - -/* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the - * expected state. */ -static void test_schnorrsig_sha256_tagged(void) { - unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; - secp256k1_sha256 sha; - secp256k1_sha256 sha_optimized; - - secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag)); - secp256k1_schnorrsig_sha256_tagged(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); -} - -/* Helper function for schnorrsig_bip_vectors - * Signs the message and checks that it's the same as expected_sig. */ -static void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *aux_rand, const unsigned char *msg, size_t msglen, const unsigned char *expected_sig) { - unsigned char sig[64]; - secp256k1_keypair keypair; - secp256k1_xonly_pubkey pk, pk_expected; - - secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; - extraparams.ndata = (unsigned char*)aux_rand; - - CHECK(secp256k1_keypair_create(CTX, &keypair, sk)); - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, msglen, &keypair, &extraparams)); - CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0); - if (msglen == 32) { - memset(sig, 0, 64); - CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypair, aux_rand)); - CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0); - } - - CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk_expected, pk_serialized)); - CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); - CHECK(secp256k1_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0); - CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, msglen, &pk)); -} - -/* Helper function for schnorrsig_bip_vectors - * Checks that both verify and verify_batch (TODO) return the same value as expected. */ -static void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg, size_t msglen, const unsigned char *sig, int expected) { - secp256k1_xonly_pubkey pk; - - CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk, pk_serialized)); - CHECK(expected == secp256k1_schnorrsig_verify(CTX, sig, msg, msglen, &pk)); -} - -/* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See - * https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv. */ -static void test_schnorrsig_bip_vectors(void) { - { - /* Test vector 0 */ - const unsigned char sk[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 - }; - const unsigned char pk[32] = { - 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, - 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, - 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, - 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 - }; - const unsigned char aux_rand[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - const unsigned char msg[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - const unsigned char sig[64] = { - 0xE9, 0x07, 0x83, 0x1F, 0x80, 0x84, 0x8D, 0x10, - 0x69, 0xA5, 0x37, 0x1B, 0x40, 0x24, 0x10, 0x36, - 0x4B, 0xDF, 0x1C, 0x5F, 0x83, 0x07, 0xB0, 0x08, - 0x4C, 0x55, 0xF1, 0xCE, 0x2D, 0xCA, 0x82, 0x15, - 0x25, 0xF6, 0x6A, 0x4A, 0x85, 0xEA, 0x8B, 0x71, - 0xE4, 0x82, 0xA7, 0x4F, 0x38, 0x2D, 0x2C, 0xE5, - 0xEB, 0xEE, 0xE8, 0xFD, 0xB2, 0x17, 0x2F, 0x47, - 0x7D, 0xF4, 0x90, 0x0D, 0x31, 0x05, 0x36, 0xC0 - }; - test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig); - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1); - } - { - /* Test vector 1 */ - const unsigned char sk[32] = { - 0xB7, 0xE1, 0x51, 0x62, 0x8A, 0xED, 0x2A, 0x6A, - 0xBF, 0x71, 0x58, 0x80, 0x9C, 0xF4, 0xF3, 0xC7, - 0x62, 0xE7, 0x16, 0x0F, 0x38, 0xB4, 0xDA, 0x56, - 0xA7, 0x84, 0xD9, 0x04, 0x51, 0x90, 0xCF, 0xEF - }; - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char aux_rand[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0x68, 0x96, 0xBD, 0x60, 0xEE, 0xAE, 0x29, 0x6D, - 0xB4, 0x8A, 0x22, 0x9F, 0xF7, 0x1D, 0xFE, 0x07, - 0x1B, 0xDE, 0x41, 0x3E, 0x6D, 0x43, 0xF9, 0x17, - 0xDC, 0x8D, 0xCF, 0x8C, 0x78, 0xDE, 0x33, 0x41, - 0x89, 0x06, 0xD1, 0x1A, 0xC9, 0x76, 0xAB, 0xCC, - 0xB2, 0x0B, 0x09, 0x12, 0x92, 0xBF, 0xF4, 0xEA, - 0x89, 0x7E, 0xFC, 0xB6, 0x39, 0xEA, 0x87, 0x1C, - 0xFA, 0x95, 0xF6, 0xDE, 0x33, 0x9E, 0x4B, 0x0A - }; - test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig); - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1); - } - { - /* Test vector 2 */ - const unsigned char sk[32] = { - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x14, 0xE5, 0xC9 - }; - const unsigned char pk[32] = { - 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, - 0x12, 0x1F, 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, - 0x01, 0x39, 0x71, 0x53, 0x09, 0xB0, 0x86, 0xC9, - 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 - }; - const unsigned char aux_rand[32] = { - 0xC8, 0x7A, 0xA5, 0x38, 0x24, 0xB4, 0xD7, 0xAE, - 0x2E, 0xB0, 0x35, 0xA2, 0xB5, 0xBB, 0xBC, 0xCC, - 0x08, 0x0E, 0x76, 0xCD, 0xC6, 0xD1, 0x69, 0x2C, - 0x4B, 0x0B, 0x62, 0xD7, 0x98, 0xE6, 0xD9, 0x06 - }; - const unsigned char msg[32] = { - 0x7E, 0x2D, 0x58, 0xD8, 0xB3, 0xBC, 0xDF, 0x1A, - 0xBA, 0xDE, 0xC7, 0x82, 0x90, 0x54, 0xF9, 0x0D, - 0xDA, 0x98, 0x05, 0xAA, 0xB5, 0x6C, 0x77, 0x33, - 0x30, 0x24, 0xB9, 0xD0, 0xA5, 0x08, 0xB7, 0x5C - }; - const unsigned char sig[64] = { - 0x58, 0x31, 0xAA, 0xEE, 0xD7, 0xB4, 0x4B, 0xB7, - 0x4E, 0x5E, 0xAB, 0x94, 0xBA, 0x9D, 0x42, 0x94, - 0xC4, 0x9B, 0xCF, 0x2A, 0x60, 0x72, 0x8D, 0x8B, - 0x4C, 0x20, 0x0F, 0x50, 0xDD, 0x31, 0x3C, 0x1B, - 0xAB, 0x74, 0x58, 0x79, 0xA5, 0xAD, 0x95, 0x4A, - 0x72, 0xC4, 0x5A, 0x91, 0xC3, 0xA5, 0x1D, 0x3C, - 0x7A, 0xDE, 0xA9, 0x8D, 0x82, 0xF8, 0x48, 0x1E, - 0x0E, 0x1E, 0x03, 0x67, 0x4A, 0x6F, 0x3F, 0xB7 - }; - test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig); - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1); - } - { - /* Test vector 3 */ - const unsigned char sk[32] = { - 0x0B, 0x43, 0x2B, 0x26, 0x77, 0x93, 0x73, 0x81, - 0xAE, 0xF0, 0x5B, 0xB0, 0x2A, 0x66, 0xEC, 0xD0, - 0x12, 0x77, 0x30, 0x62, 0xCF, 0x3F, 0xA2, 0x54, - 0x9E, 0x44, 0xF5, 0x8E, 0xD2, 0x40, 0x17, 0x10 - }; - const unsigned char pk[32] = { - 0x25, 0xD1, 0xDF, 0xF9, 0x51, 0x05, 0xF5, 0x25, - 0x3C, 0x40, 0x22, 0xF6, 0x28, 0xA9, 0x96, 0xAD, - 0x3A, 0x0D, 0x95, 0xFB, 0xF2, 0x1D, 0x46, 0x8A, - 0x1B, 0x33, 0xF8, 0xC1, 0x60, 0xD8, 0xF5, 0x17 - }; - const unsigned char aux_rand[32] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF - }; - const unsigned char msg[32] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF - }; - const unsigned char sig[64] = { - 0x7E, 0xB0, 0x50, 0x97, 0x57, 0xE2, 0x46, 0xF1, - 0x94, 0x49, 0x88, 0x56, 0x51, 0x61, 0x1C, 0xB9, - 0x65, 0xEC, 0xC1, 0xA1, 0x87, 0xDD, 0x51, 0xB6, - 0x4F, 0xDA, 0x1E, 0xDC, 0x96, 0x37, 0xD5, 0xEC, - 0x97, 0x58, 0x2B, 0x9C, 0xB1, 0x3D, 0xB3, 0x93, - 0x37, 0x05, 0xB3, 0x2B, 0xA9, 0x82, 0xAF, 0x5A, - 0xF2, 0x5F, 0xD7, 0x88, 0x81, 0xEB, 0xB3, 0x27, - 0x71, 0xFC, 0x59, 0x22, 0xEF, 0xC6, 0x6E, 0xA3 - }; - test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig); - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1); - } - { - /* Test vector 4 */ - const unsigned char pk[32] = { - 0xD6, 0x9C, 0x35, 0x09, 0xBB, 0x99, 0xE4, 0x12, - 0xE6, 0x8B, 0x0F, 0xE8, 0x54, 0x4E, 0x72, 0x83, - 0x7D, 0xFA, 0x30, 0x74, 0x6D, 0x8B, 0xE2, 0xAA, - 0x65, 0x97, 0x5F, 0x29, 0xD2, 0x2D, 0xC7, 0xB9 - }; - const unsigned char msg[32] = { - 0x4D, 0xF3, 0xC3, 0xF6, 0x8F, 0xCC, 0x83, 0xB2, - 0x7E, 0x9D, 0x42, 0xC9, 0x04, 0x31, 0xA7, 0x24, - 0x99, 0xF1, 0x78, 0x75, 0xC8, 0x1A, 0x59, 0x9B, - 0x56, 0x6C, 0x98, 0x89, 0xB9, 0x69, 0x67, 0x03 - }; - const unsigned char sig[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3B, 0x78, 0xCE, 0x56, 0x3F, - 0x89, 0xA0, 0xED, 0x94, 0x14, 0xF5, 0xAA, 0x28, - 0xAD, 0x0D, 0x96, 0xD6, 0x79, 0x5F, 0x9C, 0x63, - 0x76, 0xAF, 0xB1, 0x54, 0x8A, 0xF6, 0x03, 0xB3, - 0xEB, 0x45, 0xC9, 0xF8, 0x20, 0x7D, 0xEE, 0x10, - 0x60, 0xCB, 0x71, 0xC0, 0x4E, 0x80, 0xF5, 0x93, - 0x06, 0x0B, 0x07, 0xD2, 0x83, 0x08, 0xD7, 0xF4 - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1); - } - { - /* Test vector 5 */ - const unsigned char pk[32] = { - 0xEE, 0xFD, 0xEA, 0x4C, 0xDB, 0x67, 0x77, 0x50, - 0xA4, 0x20, 0xFE, 0xE8, 0x07, 0xEA, 0xCF, 0x21, - 0xEB, 0x98, 0x98, 0xAE, 0x79, 0xB9, 0x76, 0x87, - 0x66, 0xE4, 0xFA, 0xA0, 0x4A, 0x2D, 0x4A, 0x34 - }; - secp256k1_xonly_pubkey pk_parsed; - /* No need to check the signature of the test vector as parsing the pubkey already fails */ - CHECK(!secp256k1_xonly_pubkey_parse(CTX, &pk_parsed, pk)); - } - { - /* Test vector 6 */ - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0xFF, 0xF9, 0x7B, 0xD5, 0x75, 0x5E, 0xEE, 0xA4, - 0x20, 0x45, 0x3A, 0x14, 0x35, 0x52, 0x35, 0xD3, - 0x82, 0xF6, 0x47, 0x2F, 0x85, 0x68, 0xA1, 0x8B, - 0x2F, 0x05, 0x7A, 0x14, 0x60, 0x29, 0x75, 0x56, - 0x3C, 0xC2, 0x79, 0x44, 0x64, 0x0A, 0xC6, 0x07, - 0xCD, 0x10, 0x7A, 0xE1, 0x09, 0x23, 0xD9, 0xEF, - 0x7A, 0x73, 0xC6, 0x43, 0xE1, 0x66, 0xBE, 0x5E, - 0xBE, 0xAF, 0xA3, 0x4B, 0x1A, 0xC5, 0x53, 0xE2 - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0); - } - { - /* Test vector 7 */ - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0x1F, 0xA6, 0x2E, 0x33, 0x1E, 0xDB, 0xC2, 0x1C, - 0x39, 0x47, 0x92, 0xD2, 0xAB, 0x11, 0x00, 0xA7, - 0xB4, 0x32, 0xB0, 0x13, 0xDF, 0x3F, 0x6F, 0xF4, - 0xF9, 0x9F, 0xCB, 0x33, 0xE0, 0xE1, 0x51, 0x5F, - 0x28, 0x89, 0x0B, 0x3E, 0xDB, 0x6E, 0x71, 0x89, - 0xB6, 0x30, 0x44, 0x8B, 0x51, 0x5C, 0xE4, 0xF8, - 0x62, 0x2A, 0x95, 0x4C, 0xFE, 0x54, 0x57, 0x35, - 0xAA, 0xEA, 0x51, 0x34, 0xFC, 0xCD, 0xB2, 0xBD - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0); - } - { - /* Test vector 8 */ - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0x6C, 0xFF, 0x5C, 0x3B, 0xA8, 0x6C, 0x69, 0xEA, - 0x4B, 0x73, 0x76, 0xF3, 0x1A, 0x9B, 0xCB, 0x4F, - 0x74, 0xC1, 0x97, 0x60, 0x89, 0xB2, 0xD9, 0x96, - 0x3D, 0xA2, 0xE5, 0x54, 0x3E, 0x17, 0x77, 0x69, - 0x96, 0x17, 0x64, 0xB3, 0xAA, 0x9B, 0x2F, 0xFC, - 0xB6, 0xEF, 0x94, 0x7B, 0x68, 0x87, 0xA2, 0x26, - 0xE8, 0xD7, 0xC9, 0x3E, 0x00, 0xC5, 0xED, 0x0C, - 0x18, 0x34, 0xFF, 0x0D, 0x0C, 0x2E, 0x6D, 0xA6 - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0); - } - { - /* Test vector 9 */ - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x12, 0x3D, 0xDA, 0x83, 0x28, 0xAF, 0x9C, 0x23, - 0xA9, 0x4C, 0x1F, 0xEE, 0xCF, 0xD1, 0x23, 0xBA, - 0x4F, 0xB7, 0x34, 0x76, 0xF0, 0xD5, 0x94, 0xDC, - 0xB6, 0x5C, 0x64, 0x25, 0xBD, 0x18, 0x60, 0x51 - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0); - } - { - /* Test vector 10 */ - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x76, 0x15, 0xFB, 0xAF, 0x5A, 0xE2, 0x88, 0x64, - 0x01, 0x3C, 0x09, 0x97, 0x42, 0xDE, 0xAD, 0xB4, - 0xDB, 0xA8, 0x7F, 0x11, 0xAC, 0x67, 0x54, 0xF9, - 0x37, 0x80, 0xD5, 0xA1, 0x83, 0x7C, 0xF1, 0x97 - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0); - } - { - /* Test vector 11 */ - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0x4A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, - 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, - 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, - 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, - 0x69, 0xE8, 0x9B, 0x4C, 0x55, 0x64, 0xD0, 0x03, - 0x49, 0x10, 0x6B, 0x84, 0x97, 0x78, 0x5D, 0xD7, - 0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F, - 0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0); - } - { - /* Test vector 12 */ - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, - 0x69, 0xE8, 0x9B, 0x4C, 0x55, 0x64, 0xD0, 0x03, - 0x49, 0x10, 0x6B, 0x84, 0x97, 0x78, 0x5D, 0xD7, - 0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F, - 0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0); - } - { - /* Test vector 13 */ - const unsigned char pk[32] = { - 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, - 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, - 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, - 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 - }; - const unsigned char msg[32] = { - 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, - 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, - 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, - 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 - }; - const unsigned char sig[64] = { - 0x6C, 0xFF, 0x5C, 0x3B, 0xA8, 0x6C, 0x69, 0xEA, - 0x4B, 0x73, 0x76, 0xF3, 0x1A, 0x9B, 0xCB, 0x4F, - 0x74, 0xC1, 0x97, 0x60, 0x89, 0xB2, 0xD9, 0x96, - 0x3D, 0xA2, 0xE5, 0x54, 0x3E, 0x17, 0x77, 0x69, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, - 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 - }; - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0); - } - { - /* Test vector 14 */ - const unsigned char pk[32] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 - }; - secp256k1_xonly_pubkey pk_parsed; - /* No need to check the signature of the test vector as parsing the pubkey already fails */ - CHECK(!secp256k1_xonly_pubkey_parse(CTX, &pk_parsed, pk)); - } - { - /* Test vector 15 */ - const unsigned char sk[32] = { - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - }; - const unsigned char pk[32] = { - 0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4, - 0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22, - 0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23, - 0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17, - }; - const unsigned char aux_rand[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - /* const unsigned char msg[0] = {}; */ - const unsigned char sig[64] = { - 0x71, 0x53, 0x5D, 0xB1, 0x65, 0xEC, 0xD9, 0xFB, - 0xBC, 0x04, 0x6E, 0x5F, 0xFA, 0xEA, 0x61, 0x18, - 0x6B, 0xB6, 0xAD, 0x43, 0x67, 0x32, 0xFC, 0xCC, - 0x25, 0x29, 0x1A, 0x55, 0x89, 0x54, 0x64, 0xCF, - 0x60, 0x69, 0xCE, 0x26, 0xBF, 0x03, 0x46, 0x62, - 0x28, 0xF1, 0x9A, 0x3A, 0x62, 0xDB, 0x8A, 0x64, - 0x9F, 0x2D, 0x56, 0x0F, 0xAC, 0x65, 0x28, 0x27, - 0xD1, 0xAF, 0x05, 0x74, 0xE4, 0x27, 0xAB, 0x63, - }; - test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, NULL, 0, sig); - test_schnorrsig_bip_vectors_check_verify(pk, NULL, 0, sig, 1); - } - { - /* Test vector 16 */ - const unsigned char sk[32] = { - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - }; - const unsigned char pk[32] = { - 0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4, - 0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22, - 0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23, - 0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17, - }; - const unsigned char aux_rand[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - const unsigned char msg[] = { 0x11 }; - const unsigned char sig[64] = { - 0x08, 0xA2, 0x0A, 0x0A, 0xFE, 0xF6, 0x41, 0x24, - 0x64, 0x92, 0x32, 0xE0, 0x69, 0x3C, 0x58, 0x3A, - 0xB1, 0xB9, 0x93, 0x4A, 0xE6, 0x3B, 0x4C, 0x35, - 0x11, 0xF3, 0xAE, 0x11, 0x34, 0xC6, 0xA3, 0x03, - 0xEA, 0x31, 0x73, 0xBF, 0xEA, 0x66, 0x83, 0xBD, - 0x10, 0x1F, 0xA5, 0xAA, 0x5D, 0xBC, 0x19, 0x96, - 0xFE, 0x7C, 0xAC, 0xFC, 0x5A, 0x57, 0x7D, 0x33, - 0xEC, 0x14, 0x56, 0x4C, 0xEC, 0x2B, 0xAC, 0xBF, - }; - test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig); - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1); - } - { - /* Test vector 17 */ - const unsigned char sk[32] = { - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - }; - const unsigned char pk[32] = { - 0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4, - 0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22, - 0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23, - 0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17, - }; - const unsigned char aux_rand[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - const unsigned char msg[] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - 0x11, - }; - const unsigned char sig[64] = { - 0x51, 0x30, 0xF3, 0x9A, 0x40, 0x59, 0xB4, 0x3B, - 0xC7, 0xCA, 0xC0, 0x9A, 0x19, 0xEC, 0xE5, 0x2B, - 0x5D, 0x86, 0x99, 0xD1, 0xA7, 0x1E, 0x3C, 0x52, - 0xDA, 0x9A, 0xFD, 0xB6, 0xB5, 0x0A, 0xC3, 0x70, - 0xC4, 0xA4, 0x82, 0xB7, 0x7B, 0xF9, 0x60, 0xF8, - 0x68, 0x15, 0x40, 0xE2, 0x5B, 0x67, 0x71, 0xEC, - 0xE1, 0xE5, 0xA3, 0x7F, 0xD8, 0x0E, 0x5A, 0x51, - 0x89, 0x7C, 0x55, 0x66, 0xA9, 0x7E, 0xA5, 0xA5, - }; - test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig); - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1); - } - { - /* Test vector 18 */ - const unsigned char sk[32] = { - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, - }; - const unsigned char pk[32] = { - 0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4, - 0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22, - 0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23, - 0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17, - }; - const unsigned char aux_rand[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - const unsigned char sig[64] = { - 0x40, 0x3B, 0x12, 0xB0, 0xD8, 0x55, 0x5A, 0x34, - 0x41, 0x75, 0xEA, 0x7E, 0xC7, 0x46, 0x56, 0x63, - 0x03, 0x32, 0x1E, 0x5D, 0xBF, 0xA8, 0xBE, 0x6F, - 0x09, 0x16, 0x35, 0x16, 0x3E, 0xCA, 0x79, 0xA8, - 0x58, 0x5E, 0xD3, 0xE3, 0x17, 0x08, 0x07, 0xE7, - 0xC0, 0x3B, 0x72, 0x0F, 0xC5, 0x4C, 0x7B, 0x23, - 0x89, 0x7F, 0xCB, 0xA0, 0xE9, 0xD0, 0xB4, 0xA0, - 0x68, 0x94, 0xCF, 0xD2, 0x49, 0xF2, 0x23, 0x67, - }; - unsigned char msg[100]; - memset(msg, 0x99, sizeof(msg)); - test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig); - test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1); - } -} - -/* Nonce function that returns constant 0 */ -static int nonce_function_failing(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { - (void) msg; - (void) msglen; - (void) key32; - (void) xonly_pk32; - (void) algo; - (void) algolen; - (void) data; - (void) nonce32; - return 0; -} - -/* Nonce function that sets nonce to 0 */ -static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { - (void) msg; - (void) msglen; - (void) key32; - (void) xonly_pk32; - (void) algo; - (void) algolen; - (void) data; - - memset(nonce32, 0, 32); - return 1; -} - -/* Nonce function that sets nonce to 0xFF...0xFF */ -static int nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { - (void) msg; - (void) msglen; - (void) key32; - (void) xonly_pk32; - (void) algo; - (void) algolen; - (void) data; - - memset(nonce32, 0xFF, 32); - return 1; -} - -static void test_schnorrsig_sign(void) { - unsigned char sk[32]; - secp256k1_xonly_pubkey pk; - secp256k1_keypair keypair; - const unsigned char msg[] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 'm', 's', 'g', ' ', 'f', 'o', 'r', ' ', 'a', ' ', 's', 'c', 'h', 'n', 'o', 'r', 'r', 's', 'i', 'g', '.', '.'}; - unsigned char sig[64]; - unsigned char sig2[64]; - unsigned char zeros64[64] = { 0 }; - secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; - unsigned char aux_rand[32]; - - testrand256(sk); - testrand256(aux_rand); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk)); - CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); - CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); - /* Check that deprecated alias gives the same result */ - CHECK(secp256k1_schnorrsig_sign(CTX, sig2, msg, &keypair, NULL) == 1); - CHECK(secp256k1_memcmp_var(sig, sig2, sizeof(sig)) == 0); - - /* Test different nonce functions */ - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); - memset(sig, 1, sizeof(sig)); - extraparams.noncefp = nonce_function_failing; - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 0); - CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0); - memset(&sig, 1, sizeof(sig)); - extraparams.noncefp = nonce_function_0; - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 0); - CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0); - memset(&sig, 1, sizeof(sig)); - extraparams.noncefp = nonce_function_overflowing; - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); - - /* When using the default nonce function, schnorrsig_sign_custom produces - * the same result as schnorrsig_sign with aux_rand = extraparams.ndata */ - extraparams.noncefp = NULL; - extraparams.ndata = aux_rand; - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); - CHECK(secp256k1_schnorrsig_sign32(CTX, sig2, msg, &keypair, extraparams.ndata) == 1); - CHECK(secp256k1_memcmp_var(sig, sig2, sizeof(sig)) == 0); -} - -#define N_SIGS 3 -/* Creates N_SIGS valid signatures and verifies them with verify and - * verify_batch (TODO). Then flips some bits and checks that verification now - * fails. */ -static void test_schnorrsig_sign_verify(void) { - unsigned char sk[32]; - unsigned char msg[N_SIGS][32]; - unsigned char sig[N_SIGS][64]; - size_t i; - secp256k1_keypair keypair; - secp256k1_xonly_pubkey pk; - secp256k1_scalar s; - - testrand256(sk); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk)); - CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); - - for (i = 0; i < N_SIGS; i++) { - testrand256(msg[i]); - CHECK(secp256k1_schnorrsig_sign32(CTX, sig[i], msg[i], &keypair, NULL)); - CHECK(secp256k1_schnorrsig_verify(CTX, sig[i], msg[i], sizeof(msg[i]), &pk)); - } - - { - /* Flip a few bits in the signature and in the message and check that - * verify and verify_batch (TODO) fail */ - size_t sig_idx = testrand_int(N_SIGS); - size_t byte_idx = testrand_bits(5); - unsigned char xorbyte = testrand_int(254)+1; - sig[sig_idx][byte_idx] ^= xorbyte; - CHECK(!secp256k1_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); - sig[sig_idx][byte_idx] ^= xorbyte; - - byte_idx = testrand_bits(5); - sig[sig_idx][32+byte_idx] ^= xorbyte; - CHECK(!secp256k1_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); - sig[sig_idx][32+byte_idx] ^= xorbyte; - - byte_idx = testrand_bits(5); - msg[sig_idx][byte_idx] ^= xorbyte; - CHECK(!secp256k1_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); - msg[sig_idx][byte_idx] ^= xorbyte; - - /* Check that above bitflips have been reversed correctly */ - CHECK(secp256k1_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); - } - - /* Test overflowing s */ - CHECK(secp256k1_schnorrsig_sign32(CTX, sig[0], msg[0], &keypair, NULL)); - CHECK(secp256k1_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); - memset(&sig[0][32], 0xFF, 32); - CHECK(!secp256k1_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); - - /* Test negative s */ - CHECK(secp256k1_schnorrsig_sign32(CTX, sig[0], msg[0], &keypair, NULL)); - CHECK(secp256k1_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); - secp256k1_scalar_set_b32(&s, &sig[0][32], NULL); - secp256k1_scalar_negate(&s, &s); - secp256k1_scalar_get_b32(&sig[0][32], &s); - CHECK(!secp256k1_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); - - /* The empty message can be signed & verified */ - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig[0], NULL, 0, &keypair, NULL) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, sig[0], NULL, 0, &pk) == 1); - - { - /* Test varying message lengths */ - unsigned char msg_large[32 * 8]; - uint32_t msglen = testrand_int(sizeof(msg_large)); - for (i = 0; i < sizeof(msg_large); i += 32) { - testrand256(&msg_large[i]); - } - CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig[0], msg_large, msglen, &keypair, NULL) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, sig[0], msg_large, msglen, &pk) == 1); - /* Verification for a random wrong message length fails */ - msglen = (msglen + (sizeof(msg_large) - 1)) % sizeof(msg_large); - CHECK(secp256k1_schnorrsig_verify(CTX, sig[0], msg_large, msglen, &pk) == 0); - } -} -#undef N_SIGS - -static void test_schnorrsig_taproot(void) { - unsigned char sk[32]; - secp256k1_keypair keypair; - secp256k1_xonly_pubkey internal_pk; - unsigned char internal_pk_bytes[32]; - secp256k1_xonly_pubkey output_pk; - unsigned char output_pk_bytes[32]; - unsigned char tweak[32]; - int pk_parity; - unsigned char msg[32]; - unsigned char sig[64]; - - /* Create output key */ - testrand256(sk); - CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); - CHECK(secp256k1_keypair_xonly_pub(CTX, &internal_pk, NULL, &keypair) == 1); - /* In actual taproot the tweak would be hash of internal_pk */ - CHECK(secp256k1_xonly_pubkey_serialize(CTX, tweak, &internal_pk) == 1); - CHECK(secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK(secp256k1_keypair_xonly_pub(CTX, &output_pk, &pk_parity, &keypair) == 1); - CHECK(secp256k1_xonly_pubkey_serialize(CTX, output_pk_bytes, &output_pk) == 1); - - /* Key spend */ - testrand256(msg); - CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1); - /* Verify key spend */ - CHECK(secp256k1_xonly_pubkey_parse(CTX, &output_pk, output_pk_bytes) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &output_pk) == 1); - - /* Script spend */ - CHECK(secp256k1_xonly_pubkey_serialize(CTX, internal_pk_bytes, &internal_pk) == 1); - /* Verify script spend */ - CHECK(secp256k1_xonly_pubkey_parse(CTX, &internal_pk, internal_pk_bytes) == 1); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1); -} - -static void run_schnorrsig_tests(void) { - int i; - run_nonce_function_bip340_tests(); - - test_schnorrsig_api(); - test_schnorrsig_sha256_tagged(); - test_schnorrsig_bip_vectors(); - for (i = 0; i < COUNT; i++) { - test_schnorrsig_sign(); - test_schnorrsig_sign_verify(); - } - test_schnorrsig_taproot(); -} - -#endif diff --git a/external/secp256k1/src/precompute_ecmult.c b/external/secp256k1/src/precompute_ecmult.c deleted file mode 100644 index 5ef198a770..0000000000 --- a/external/secp256k1/src/precompute_ecmult.c +++ /dev/null @@ -1,90 +0,0 @@ -/***************************************************************************************************** - * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php. * - *****************************************************************************************************/ - -#include -#include - -#include "../include/secp256k1.h" - -#include "assumptions.h" -#include "util.h" - -#include "field_impl.h" -#include "group_impl.h" -#include "int128_impl.h" -#include "ecmult.h" -#include "ecmult_compute_table_impl.h" - -static void print_table(FILE *fp, const char *name, int window_g, const secp256k1_ge_storage* table) { - int j; - int i; - - fprintf(fp, "const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name); - fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 - ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n", - SECP256K1_GE_STORAGE_CONST_GET(table[0])); - - j = 1; - for(i = 3; i <= window_g; ++i) { - fprintf(fp, "#if WINDOW_G > %d\n", i-1); - for(;j < ECMULT_TABLE_SIZE(i); ++j) { - fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 - ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n", - SECP256K1_GE_STORAGE_CONST_GET(table[j])); - } - fprintf(fp, "#endif\n"); - } - fprintf(fp, "};\n"); -} - -static void print_two_tables(FILE *fp, int window_g) { - secp256k1_ge_storage* table = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(secp256k1_ge_storage)); - secp256k1_ge_storage* table_128 = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(secp256k1_ge_storage)); - - secp256k1_ecmult_compute_two_tables(table, table_128, window_g, &secp256k1_ge_const_g); - - print_table(fp, "secp256k1_pre_g", window_g, table); - print_table(fp, "secp256k1_pre_g_128", window_g, table_128); - - free(table); - free(table_128); -} - -int main(void) { - /* Always compute all tables for window sizes up to 15. */ - int window_g = (ECMULT_WINDOW_SIZE < 15) ? 15 : ECMULT_WINDOW_SIZE; - const char outfile[] = "src/precomputed_ecmult.c"; - FILE* fp; - - fp = fopen(outfile, "w"); - if (fp == NULL) { - fprintf(stderr, "Could not open %s for writing!\n", outfile); - return -1; - } - - fprintf(fp, "/* This file was automatically generated by precompute_ecmult. */\n"); - fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n"); - fprintf(fp, " * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n"); - fprintf(fp, " */\n"); - fprintf(fp, "#include \"group.h\"\n"); - fprintf(fp, "#include \"ecmult.h\"\n"); - fprintf(fp, "#include \"precomputed_ecmult.h\"\n"); - fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); - fprintf(fp, "#if ECMULT_WINDOW_SIZE > %d\n", window_g); - fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting precomputed_ecmult.c before the build.\n"); - fprintf(fp, "#endif\n"); - fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n"); - fprintf(fp, "# error Cannot compile precomputed_ecmult.c in exhaustive test mode\n"); - fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); - fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n"); - - print_two_tables(fp, window_g); - - fprintf(fp, "#undef S\n"); - fclose(fp); - - return 0; -} diff --git a/external/secp256k1/src/precompute_ecmult_gen.c b/external/secp256k1/src/precompute_ecmult_gen.c deleted file mode 100644 index 4d153a6574..0000000000 --- a/external/secp256k1/src/precompute_ecmult_gen.c +++ /dev/null @@ -1,100 +0,0 @@ -/********************************************************************************* - * Copyright (c) 2013, 2014, 2015, 2021 Thomas Daede, Cory Fields, Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php. * - *********************************************************************************/ - -#include -#include - -#include "../include/secp256k1.h" - -#include "assumptions.h" -#include "util.h" - -#include "group.h" -#include "int128_impl.h" -#include "ecmult_gen.h" -#include "ecmult_gen_compute_table_impl.h" - -static const int CONFIGS[][2] = { - {2, 5}, - {11, 6}, - {43, 6} -}; - -static void print_table(FILE* fp, int blocks, int teeth) { - int spacing = CEIL_DIV(256, blocks * teeth); - size_t points = ((size_t)1) << (teeth - 1); - int outer; - size_t inner; - - secp256k1_ge_storage* table = checked_malloc(&default_error_callback, blocks * points * sizeof(secp256k1_ge_storage)); - secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, blocks, teeth, spacing); - - fprintf(fp, "#elif (COMB_BLOCKS == %d) && (COMB_TEETH == %d) && (COMB_SPACING == %d)\n", blocks, teeth, spacing); - for (outer = 0; outer != blocks; outer++) { - fprintf(fp,"{"); - for (inner = 0; inner != points; inner++) { - fprintf(fp, "S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 - ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")", - SECP256K1_GE_STORAGE_CONST_GET(table[outer * points + inner])); - if (inner != points - 1) { - fprintf(fp,",\n"); - } - } - if (outer != blocks - 1) { - fprintf(fp,"},\n"); - } else { - fprintf(fp,"}\n"); - } - } - free(table); -} - -int main(int argc, char **argv) { - const char outfile[] = "src/precomputed_ecmult_gen.c"; - FILE* fp; - size_t config; - int did_current_config = 0; - - (void)argc; - (void)argv; - - fp = fopen(outfile, "w"); - if (fp == NULL) { - fprintf(stderr, "Could not open %s for writing!\n", outfile); - return -1; - } - - fprintf(fp, "/* This file was automatically generated by precompute_ecmult_gen. */\n"); - fprintf(fp, "/* See ecmult_gen_impl.h for details about the contents of this file. */\n"); - fprintf(fp, "#include \"group.h\"\n"); - fprintf(fp, "#include \"ecmult_gen.h\"\n"); - fprintf(fp, "#include \"precomputed_ecmult_gen.h\"\n"); - fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n"); - fprintf(fp, "# error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode\n"); - fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); - fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); - - fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = {\n"); - fprintf(fp, "#if 0\n"); - for (config = 0; config < sizeof(CONFIGS) / sizeof(*CONFIGS); ++config) { - print_table(fp, CONFIGS[config][0], CONFIGS[config][1]); - if (CONFIGS[config][0] == COMB_BLOCKS && CONFIGS[config][1] == COMB_TEETH) { - did_current_config = 1; - } - } - if (!did_current_config) { - print_table(fp, COMB_BLOCKS, COMB_TEETH); - } - fprintf(fp, "#else\n"); - fprintf(fp, "# error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build.\n"); - fprintf(fp, "#endif\n"); - - fprintf(fp, "};\n"); - fprintf(fp, "#undef S\n"); - fclose(fp); - - return 0; -} diff --git a/external/secp256k1/src/precomputed_ecmult.c b/external/secp256k1/src/precomputed_ecmult.c deleted file mode 100644 index cbd030ce50..0000000000 --- a/external/secp256k1/src/precomputed_ecmult.c +++ /dev/null @@ -1,16456 +0,0 @@ -/* This file was automatically generated by precompute_ecmult. */ -/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and - * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G. - */ -#include "group.h" -#include "ecmult.h" -#include "precomputed_ecmult.h" -#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u) -#if ECMULT_WINDOW_SIZE > 15 - #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting precomputed_ecmult.c before the build. -#endif -#ifdef EXHAUSTIVE_TEST_ORDER -# error Cannot compile precomputed_ecmult.c in exhaustive test mode -#endif /* EXHAUSTIVE_TEST_ORDER */ -#define WINDOW_G ECMULT_WINDOW_SIZE -const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] = { - S(79be667e,f9dcbbac,55a06295,ce870b07,29bfcdb,2dce28d9,59f2815b,16f81798,483ada77,26a3c465,5da4fbfc,e1108a8,fd17b448,a6855419,9c47d08f,fb10d4b8) -#if WINDOW_G > 2 -,S(f9308a01,9258c310,49344f85,f89d5229,b531c845,836f99b0,8601f113,bce036f9,388f7b0f,632de814,fe337e6,2a37f356,6500a999,34c2231b,6cb9fd75,84b8e672) -#endif -#if WINDOW_G > 3 -,S(2f8bde4d,1a072093,55b4a725,a5c5128,e88b84bd,dc619ab7,cba8d569,b240efe4,d8ac2226,36e5e3d6,d4dba9dd,a6c9c426,f788271b,ab0d6840,dca87d3a,a6ac62d6) -,S(5cbdf064,6e5db4ea,a398f365,f2ea7a0e,3d419b7e,330e39c,e92bdded,cac4f9bc,6aebca40,ba255960,a3178d6d,861a54db,a813d0b8,13fde7b5,a5082628,87264da) -#endif -#if WINDOW_G > 4 -,S(acd484e2,f0c7f653,9ad178a,9f559abd,e0979697,4c57e714,c35f110d,fc27ccbe,cc338921,b0a7d9fd,64380971,763b61e9,add888a4,375f8e0f,5cc262a,c64f9c37) -,S(774ae7f8,58a9411e,5ef4246b,70c65aac,5649980b,e5c17891,bbec1789,5da008cb,d984a032,eb6b5e19,243dd56,d7b7b365,372db1e2,dff9d6a8,301d74c9,c953c61b) -,S(f28773c2,d975288b,c7d1d205,c3748651,b075fbc6,610e58cd,deeddf8f,19405aa8,ab0902e,8d880a89,758212eb,65cdaf47,3a1a06da,521fa91f,29b5cb52,db03ed81) -,S(d7924d4f,7d43ea96,5a465ae3,95ff411,31e5946f,3c85f79e,44adbcf8,e27e080e,581e2872,a86c72a6,83842ec2,28cc6def,ea40af2b,d896d3a5,c504dc9f,f6a26b58) -#endif -#if WINDOW_G > 5 -,S(defdea4c,db677750,a420fee8,7eacf21,eb9898ae,79b97687,66e4faa0,4a2d4a34,4211ab06,94635168,e997b0ea,d2a93dae,ced1f4a0,4a95c0f6,cfb199f6,9e56eb77) -,S(2b4ea0a7,97a443d2,93ef5cff,444f4979,f06acfeb,d7e86d27,74756561,38385b6c,85e89bc0,37945d93,b343083b,5a1c8613,1a01f60c,50269763,b570c854,e5c09b7a) -,S(352bbf4a,4cdd1256,4f93fa33,2ce33330,1d9ad402,71f81071,81340aef,25be59d5,321eb407,5348f534,d59c1825,9dda3e1f,4a1b3b2e,71b1039c,67bd3d8b,cf81998c) -,S(2fa2104d,6b38d11b,2300105,59879124,e42ab8df,eff5ff29,dc9cdadd,4ecacc3f,2de1068,295dd865,b6456933,5bd5dd80,181d70ec,fc882648,423ba76b,532b7d67) -,S(9248279b,9b4d68d,ab21a9b0,66edda83,263c3d84,e09572e2,69ca0cd7,f5453714,73016f7b,f234aade,5d1aa71b,dea2b1ff,3fc0de2a,887912ff,e54a32ce,97cb3402) -,S(daed4f2b,e3a8bf27,8e70132f,b0beb752,2f570e14,4bf615c0,7e996d44,3dee8729,a69dce4a,7d6c98e8,d4a1aca8,7ef8d700,3f83c230,f3afa726,ab40e522,90be1c55) -,S(c44d12c7,65d812e,8acf28d7,cbb19f90,11ecd9e9,fdf281b0,e6a3b5e8,7d22e7db,2119a460,ce326cdc,76c45926,c982fdac,e106e86,1edf61c5,a039063f,e0e6482) -,S(6a245bf6,dc698504,c89a20cf,ded60853,152b6953,36c28063,b61c65cb,d269e6b4,e022cf42,c2bd4a70,8b3f5126,f16a24ad,8b33ba48,d0423b6e,fd5e6348,100d8a82) -#endif -#if WINDOW_G > 6 -,S(1697ffa6,fd9de627,c077e3d2,fe541084,ce13300b,bec1146,f95ae57f,d0bd6a5,b9c398f1,86806f5d,27561506,e4557433,a2cf1500,9e498ae7,adee9d63,d01b2396) -,S(605bdb01,9981718b,986d0f07,e834cb0d,9deb8360,ffb7f61d,f982345e,f27a7479,2972d2d,e4f8d206,81a78d93,ec96fe23,c26bfae8,4fb14db4,3b01e1e9,56b8c49) -,S(62d14dab,4150bf49,7402fdc4,5a215e10,dcb01c35,4959b10c,fe31c7e9,d87ff33d,80fc06bd,8cc5b010,98088a19,50eed0db,1aa1329,67ab4722,35f56424,83b25eaf) -,S(80c60ad0,40f27da,de5b4b06,c408e56b,2c50e9f5,6b9b8b42,5e555c2f,86308b6f,1c38303f,1cc5c30f,26e66bad,7fe72f70,a65eed4c,be7024eb,1aa01f56,430bd57a) -,S(7a9375ad,6167ad54,aa74c634,8cc54d34,4cc5dc94,87d84704,9d5eabb0,fa03c8fb,d0e3fa9,eca87269,9559e0d,79269046,bdc59ea1,c70ce2b,2d499ec,224dc7f7) -,S(d528ecd9,b696b54c,907a9ed0,45447a79,bb408ec3,9b68df50,4bb51f45,9bc3ffc9,eecf4125,3136e5f9,9966f218,81fd656e,bc434540,5c520dbc,63465b5,21409933) -,S(49370a4,b5f43412,ea25f514,e8ecdad0,5266115e,4a7ecb13,87231808,f8b45963,758f3f41,afd6ed42,8b3081b0,512fd62a,54c3f3af,bb5b6764,b653052a,12949c9a) -,S(77f23093,6ee88cbb,d73df930,d64702ef,881d811e,e1498e2,f1c13eb1,fc345d74,958ef42a,7886b640,a08266e,9ba1b378,96c95330,d97077cb,be8eb3c7,671c60d6) -,S(f2dac991,cc4ce4b9,ea44887e,5c7c0bce,58c80074,ab9d4dba,eb28531b,7739f530,e0dedc9b,3b2f8dad,4da1f32d,ec2531df,9eb5fbeb,598e4fd,1a117dba,703a3c37) -,S(463b3d9f,662621fb,1b4be8fb,be252012,5a216cdf,c9dae3de,bcba4850,c690d45b,5ed430d7,8c296c35,43114306,dd8622d7,c622e27c,970a1de3,1cb377b0,1af7307e) -,S(f16f8042,44e46e2a,9232d4a,ff3b5997,6b98fac1,4328a2d1,a32496b4,9998f247,cedabd9b,82203f7e,13d206fc,df4e33d9,2a6c53c2,6e5cce26,d6579962,c4e31df6) -,S(caf75427,2dc84563,b0352b7a,14311af5,5d245315,ace27c65,369e15f7,151d41d1,cb474660,ef35f5f2,a41b643f,a5e46057,5f4fa9b7,962232a5,c32f9083,18a04476) -,S(2600ca4b,282cb986,f85d0f17,9979d8b,44a09c07,cb86d7c1,24497bc8,6f082120,4119b887,53c15bd6,a693b03f,cddbb45d,5ac6be74,ab5f0ef4,4b0be947,5a7e4b40) -,S(7635ca72,d7e8432c,338ec53c,d12220bc,1c48685,e24f7dc8,c602a774,6998e435,91b6496,9489d61,3d1d5e59,f78e6d7,4ecfc061,d57048ba,d9e76f30,2c5b9c61) -,S(754e3239,f325570c,dbbf4a87,deee8a66,b7f2b334,79d468fb,c1a50743,bf56cc18,673fb86,e5bda30f,b3cd0ed3,4ea49a0,23ee33d0,197a695d,c5d9809,3c536683) -,S(e3e6bd10,71a1e96a,ff57859c,82d570f0,33080066,1d1c952f,9fe26946,91d9b9e8,59c9e0bb,a394e76f,40c0aa58,379a3cb6,a5a22839,93e90c41,67002af4,920e37f5) -#endif -#if WINDOW_G > 7 -,S(186b483d,56a0338,26ae73d8,8f732985,c4ccb1f3,2ba35f4b,4cc47fdc,f04aa6eb,3b952d32,c67cf77e,2e17446e,204180ab,21fb8090,895138b4,a4a797f8,6e80888b) -,S(df9d70a6,b9876ce5,44c98561,f4be4f72,5442e6d2,b737d9c9,1a832172,4ce0963f,55eb2daf,d84d6ccd,5f862b78,5dc39d4a,b1572227,20ef9da2,17b8c45c,f2ba2417) -,S(5edd5cc2,3c51e87a,497ca815,d5dce0f8,ab52554f,849ed899,5de64c5f,34ce7143,efae9c8d,bc141306,61e8cec0,30c89ad0,c13c66c0,d17a2905,cdc706ab,7399a868) -,S(290798c2,b6476830,da12fe02,287e9e77,7aa3fba1,c355b17a,722d362f,84614fba,e38da76d,cd440621,988d00bc,f79af25d,5b29c094,db2a2314,6d003afd,41943e7a) -,S(af3c423a,95d9f5b3,54754ef,a150ac39,cd29552f,e3602573,62dfdece,f4053b45,f98a3fd8,31eb2b74,9a93b0e6,f35cfb40,c8cd5aa6,67a15581,bc2feded,498fd9c6) -,S(766dbb24,d134e745,cccaa28c,99bf2749,6bb66b2,6dcf98df,8d2fed50,d884249a,744b1152,eacbe5e3,8dcc8879,80da38b8,97584a65,fa06cedd,2c924f97,cbac5996) -,S(59dbf46f,8c94759b,a21277c3,3784f416,45f7b44f,6c596a58,ce92e666,191abe3e,c534ad44,175fbc30,f4ea6ce,648309a0,42ce739a,7919798c,d85e216c,4a307f6e) -,S(f13ada95,103c4537,305e691e,74e9a4a8,dd647e71,1a95e73c,b62dc601,8cfd87b8,e13817b4,4ee14de6,63bf4bc8,8341f32,6949e21a,6a75c257,778419b,daf5733d) -,S(7754b4fa,e8aced0,6d4167a2,c59cca4c,da1869c0,6ebadfb6,48855001,5a88522c,30e93e86,4e669d82,224b967c,3020b8fa,8d1e4e35,b6cbcc5,37a48b57,841163a2) -,S(948dcadf,5990e048,aa3874d4,6abef9d7,1858f95,de8041d2,a6828c99,e2262519,e491a425,37f6e597,d5d28a32,24b1bc25,df9154ef,bd2ef1d2,cbba2cae,5347d57e) -,S(79624144,50c76c16,89c7b48f,8202ec37,fb224cf5,ac0bfa15,70328a8a,3d7c77ab,100b610e,c4ffb476,d5c1fc1,33ef6f6b,12507a05,1f04ac57,60afa5b2,9db83437) -,S(35140878,34964b54,b15b1606,44d91548,5a169772,25b8847b,b0dd0851,37ec47ca,ef0afbb2,5620544,8e1652c4,8e8127fc,6039e77c,15c2378b,7e7d15a0,de293311) -,S(d3cc30ad,6b483e4b,c79ce2c9,dd8bc549,93e947eb,8df787b4,42943d3f,7b527eaf,8b378a22,d827278d,89c5e9be,8f9508ae,3c2ad462,90358630,afb34db0,4eede0a4) -,S(1624d847,80732860,ce1c78fc,bfefe08b,2b29823d,b913f649,3975ba0f,f4847610,68651cf9,b6da903e,914448c,6cd9d4ca,896878f5,282be4c8,cc06e2a4,4078575) -,S(733ce80d,a955a8a2,6902c956,33e62a98,5192474b,5af207da,6df7b4fd,5fc61cd4,f5435a2b,d2badf7d,485a4d8b,8db9fcce,3e1ef8e0,201e4578,c54673bc,1dc5ea1d) -,S(15d94412,54945064,cf1a1c33,bbd3b49f,8966c509,2171e699,ef258dfa,b81c045c,d56eb30b,69463e72,34f5137b,73b84177,434800ba,cebfc685,fc37bbe9,efe4070d) -,S(a1d0fcf2,ec9de675,b612136e,5ce70d27,1c21417c,9d2b8aaa,ac138599,d0717940,edd77f50,bcb5a3ca,b2e90737,309667f2,641462a5,4070f3d5,19212d39,c197a629) -,S(e22fbe15,c0af8ccc,5780c073,5f84dbe9,a790bade,e8245c06,c7ca3733,1cb36980,a855bab,ad5cd60c,88b430a6,9f53a1a7,a3828915,4964799b,e43d06d7,7d31da06) -,S(311091dd,9860e8e2,ee13473,c1155f5f,69635e39,4704eaa7,40094522,46cfa9b3,66db656f,87d1f04f,ffd1f047,88c06830,871ec5a6,4feee685,bd80f0b1,286d8374) -,S(34c1fd04,d301be89,b31c0442,d3e6ac24,883928b4,5a934078,1867d423,2ec2dbdf,9414685,e97b1b59,54bd46f7,30174136,d57f1cee,b487443d,c5321857,ba73abee) -,S(f219ea5d,6b54701c,1c14de5b,557eb42a,8d13f3ab,bcd08aff,cc2a5e6b,49b8d63,4cb95957,e83d40b0,f73af454,4cccf6b1,f4b08d3c,7b27fb8,d8c2962a,400766d1) -,S(d7b8740f,74a8fbaa,b1f683db,8f45de26,543a5490,bca62708,72369124,69a0b448,fa779681,28d9c92e,e1010f33,7ad4717e,ff15db5e,d3c049b3,411e0315,eaa4593b) -,S(32d31c22,2f8f6f0e,f86f7c98,d3a3335e,ad5bcd32,abdd9428,9fe4d309,1aa824bf,5f3032f5,892156e3,9ccd3d79,15b9e1da,2e6dac9e,6f26e961,118d14b8,462e1661) -,S(7461f371,914ab326,71045a15,5d9831ea,8793d77c,d59592c4,340f86cb,c18347b5,8ec0ba23,8b96bec0,cbdddcae,aa44254,2eee1ff5,c986ea6,b39847b3,cc092ff6) -,S(ee079adb,1df18600,74356a25,aa38206a,6d716b2c,3e67453d,287698ba,d7b2b2d6,8dc2412a,afe3be5c,4c5f37e0,ecc5f9f6,a446989a,f04c4e25,ebaac479,ec1c8c1e) -,S(16ec93e4,47ec83f0,467b1830,2ee620f7,e65de331,874c9dc7,2bfd8616,ba9da6b5,5e463115,e62fb40,d0e8c2a7,ca5804a3,9d58186a,50e49713,9626778e,25b0674d) -,S(eaa5f980,c245f6f0,38978290,afa70b6b,d8855897,f98b6aa4,85b96065,d537bd99,f65f5d3e,292c2e08,19a52839,1c994624,d784869d,7e6ea67f,b1804102,4edc07dc) -,S(78c9407,544ac132,692ee191,a024399,58ae0487,7151342e,a96c4b6b,35a49f51,f3e03191,69eb9b85,d5404795,539a5e68,fa1fbd58,3c064d24,62b675f1,94a3ddb4) -,S(494f4be2,19a1a770,16dcd838,431aea00,1cdc8ae,7a6fc688,726578d9,702857a5,42242a96,9283a5f3,39ba7f07,5e36ba2a,f925ce30,d767ed6e,55f4b031,880d562c) -,S(a598a803,da6d86c,6bc7f2f5,144ea549,d28211ea,58faa70e,bf4c1e66,5c1fe9b5,204b5d6f,84822c30,7e4b4a71,40737aec,23fc63b6,5b35f86a,10026dbd,2d864e6b) -,S(c4191636,5abb2b5d,9192f5f,2dbeafec,208f020f,12570a18,4dbadc3e,58595997,4f14351,d0087efa,49d245b3,28984989,d5caf945,f34bfc0,ed16e96b,58fa9913) -,S(841d6063,a586fa47,5a724604,da03bc5b,92a2e0d2,e0a36acf,e4c73a55,14742881,73867f5,9c0659e8,1904f9a1,c7543698,e62562d6,744c169c,e7a36de0,1a8d6154) -#endif -#if WINDOW_G > 8 -,S(5e95bb39,9a6971d3,76026947,f89bde2f,282b3381,928be4d,ed112ac4,d70e20d5,39f23f36,6809085b,eebfc711,81313775,a99c9aed,7d8ba38b,161384c7,46012865) -,S(36e4641a,53948fd4,76c39f8a,99fd974e,5ec07564,b5315d8b,f99471bc,a0ef2f66,d2424b1b,1abe4eb8,164227b0,85c9aa94,56ea1349,3fd563e0,6fd51cf5,694c78fc) -,S(336581e,a7bfbbb2,90c191a2,f507a41c,f5643842,170e914f,aeab27c2,c579f726,ead12168,595fe1be,99252129,b6e56b33,91f7ab14,10cd1e0e,f3dcdcab,d2fda224) -,S(8ab89816,dadfd6b6,a1f2634f,cf00ec84,3781025,ed6890c4,84974270,6bd43ede,6fdcef09,f2f6d0a0,44e654ae,f624136f,503d459c,3e898458,58a47a91,29cdd24e) -,S(1e33f1a7,46c9c577,8133344d,9299fcaa,20b0938e,8acff254,4bb40284,b8c5fb94,6066025,7dd11b3a,a9c8ed61,8d24edff,2306d320,f1d03010,e33a7d20,57f3b3b6) -,S(85b7c1dc,b3cec1b7,ee7f30de,d79dd20a,ed1f4cc,18cbcfcf,a410361f,d8f08f31,3d98a9cd,d026dd43,f39048f2,5a8847f4,fcafad18,95d7a633,c6fed3c3,5e999511) -,S(29df9fbd,8d9e4650,9275f4b1,25d6d45d,7fbe9a3b,878a7af8,72a28006,61ac5f51,b4c4fe9,9c775a60,6e2d8862,179139ff,da61dc86,1c019e55,cd2876eb,2a27d84b) -,S(a0b1cae0,6b0a847a,3fea6e67,1aaf8adf,dfe58ca2,f768105c,8082b2e4,49fce252,ae434102,edde0958,ec4b19d9,17a6a28e,6b72da18,34aff0e6,50f04950,3a296cf2) -,S(4e8ceaf,b9b3e9a1,36dc7ff6,7e840295,b499dfb3,b2133e4b,a113f2e4,c0e121e5,cf217411,8c8b6d7a,4b48f6d5,34ce5c79,422c086a,63460502,b827ce62,a326683c) -,S(d24a44e0,47e19b6f,5afb81c7,ca2f6908,a507668,9a010919,f42725c2,b789a33b,6fb8d559,1b466f8f,c63db50f,1c0f1c69,13f9968,87b8244d,2cdec417,afea8fa3) -,S(ea01606a,7a6c9cdd,249fdfcf,acb99584,1edd28,abbab77b,5104e98e,8e3b35d4,322af490,8c7312b0,cfbfe369,f7a7b3cd,b7d4494b,c2823700,cfd65218,8a3ea98d) -,S(af8addbf,2b661c8a,6c632865,5eb96651,252007d8,c5ea31be,4ad196de,8ce2131f,6749e67c,29b85f5,2a034eaf,d096836b,25208186,80e26ac8,f3dfbcdb,71749700) -,S(e3ae19,74566ca0,6cc516d4,7e0fb165,a674a3da,bcfca15e,722f0e34,50f45889,2aeabe7e,45315101,16217f07,bf4d0730,de97e48,74f81f53,3420a72e,eb0bd6a4) -,S(591ee355,313d9972,1cf6993f,fed1e3e3,1993ff3,ed258802,75ea8ce,d397e246,b0ea558a,113c30be,a60fc477,5460c790,1ff0b053,d25ca2bd,eee98f1a,4be5d196) -,S(11396d55,fda54c49,f19aa973,18d8da61,fa8584e4,7b084945,77cf032,55b52984,998c74a8,cd45ac01,289d5833,a7beb474,4ff536b0,1b257be4,c5767bea,93ea57a4) -,S(3c5d2a1b,a39c5a17,90000738,c9e0c40b,8dcdfd54,68754b64,5540157,e017aa7a,b2284279,995a34e2,f9d4de73,96fc18b8,f9b8b9f,dd270f66,61f79ca4,c81bd257) -,S(cc8704b8,a60a0def,a3a99a72,99f2e9c3,fbc395af,b04ac078,425ef8a1,793cc030,bdd46039,feed1788,1d1e0862,db347f8c,f395b74f,c4bcdc4e,940b74e3,ac1f1b13) -,S(c533e4f7,ea8555aa,cd9777ac,5cad29b9,7dd4defc,cc53ee7e,a204119b,2889b197,6f0a256b,c5efdf42,9a2fb624,2f1a43a2,d9b925bb,4a4b3a26,bb8e0f45,eb596096) -,S(c14f8f2,ccb27d6f,109f6d08,d03cc96a,69ba8c34,eec07bbc,f566d48e,33da6593,c359d692,3bb398f7,fd4473e1,6fe1c284,75b740dd,98075e6,c0e86491,13dc3a38) -,S(a6cbc304,6bc6a450,bac24789,fa17115a,4c9739ed,75f8f21c,e441f72e,b90e6ef,21ae7f4,680e889b,b130619e,2c0f95a3,60ceb573,c7060313,9862afd6,17fa9b9f) -,S(347d6d9a,2c48927,ebfb86c1,359b1caf,130a3c02,67d11ce6,344b39f9,9d43cc38,60ea7f61,a353524d,1c987f6e,cec92f08,6d565ab6,87870cb1,2689ff1e,31c74448) -,S(da6545d2,181db8d9,83f7dcb3,75ef5866,d47c67b1,bf31c8cf,855ef743,7b72656a,49b96715,ab6878a7,9e78f07c,e5680c5d,6673051b,4935bd89,7fea824b,77dc208a) -,S(c40747cc,9d012cb1,a13b8148,309c6de7,ec25d694,5d657146,b9d5994b,8feb1111,5ca56075,3be2a12f,c6de6caf,2cb48956,5db93615,6b9514e1,bb5e8303,7e0fa2d4) -,S(4e42c8ec,82c99798,ccf3a610,be870e78,338c7f71,3348bd34,c8203ef4,37f3502,7571d74e,e5e0fb92,a7a8b33a,7783341,a5492144,cc54bcc4,a944736,93606437) -,S(3775ab70,89bc6af8,23aba2e1,af70b236,d251cadb,c867432,87522a1b,3b0dedea,be52d107,bcfa09d8,bcb9736a,828cfa7f,ac8db17b,f7a76a2c,42ad9614,9018cf7) -,S(cee31cbf,7e34ec37,9d94fb81,4d3d775a,d954595d,1314ba88,46959e3e,82f74e26,8fd64a14,c06b589c,26b947ae,2bcf6bfa,149ef0b,e14ed4d8,f448a01,c43b1c6d) -,S(b4f9eaea,9b69176,19f6ea6a,4eb5464e,fddb58fd,45b1ebef,cdc1a01d,8b47986,39e5c992,5b5a54b0,7433a4f1,8c61726f,8bb131c0,12ca542e,b24a8ac0,7200682a) -,S(d4263dfc,3d2df923,a0179a48,966d30ce,84e2515a,fc3dccc1,b7790779,2ebcc60e,62dfaf07,a0f78feb,30e30d62,95853ce1,89e12776,ad6cf7f,ae164e12,2a208d54) -,S(48457524,820fa65a,4f8d35eb,6930857c,32acc0,a4a2de42,2233eeda,897612c4,25a748ab,367979d9,8733c38a,1fa1c2e7,dc6cc07d,b2d60a9a,e7a76aaa,49bd0f77) -,S(dfeeef18,81101f2c,b11644f3,a2afdfc2,45e1991,9152923f,367a1767,c11cceda,ecfb7056,cf1de042,f9420bab,396793c0,c390bde7,4b4bbdff,16a83ae0,9a9a7517) -,S(6d7ef6b1,7543f837,3c573f44,e1f38983,5d89bcbc,6062ced3,6c82df83,b8fae859,cd450ec3,35438986,dfefa10c,57fea9bc,c521a095,9b2d80bb,f74b190d,ca712d10) -,S(e75605d5,9102a5a2,684500d3,b991f2e3,f3c88b93,22554703,5af25af6,6e04541f,f5c54754,a8f71ee5,40b9b487,28473e31,4f729ac5,308b0693,8360990e,2bfad125) -,S(eb98660f,4c4dfaa0,6a2be453,d5020bc9,9a0c2e60,abe38845,7dd43fef,b1ed620c,6cb9a887,6d9cb852,609af3a,dd26cd20,a0a7cd8a,9411131c,e85f4410,99223e) -,S(13e87b02,7d8514d3,5939f2e6,892b1992,21545969,41888336,dc3563e3,b8dba942,fef5a3c6,8059a6de,c5d62411,4bf1e91a,ac2b9da5,68d6abeb,2570d556,46b8adf1) -,S(ee163026,e9fd6fe0,17c38f06,a5be6fc1,25424b37,1ce2708e,7bf44916,91e5764a,1acb250f,255dd61c,43d94ccc,670d0f58,f49ae3fa,15b96623,e5430da0,ad6c62b2) -,S(b268f5ef,9ad51e4d,78de3a75,c2dc89b,1e626d43,50586799,9932e5db,33af3d80,5f310d4b,3c99b9eb,b19f77d4,1c1dee01,8cf0d34f,d4191614,3e945a,1216e423) -,S(ff07f311,8a9df035,e9fad85e,b6c7bfe4,2b02f01c,a99ceea3,bf7ffdba,93c4750d,438136d6,3e858a3,a5c440c3,8eccbadd,c1d29421,14e2eddd,4740d098,ced1f0d8) -,S(8d8b9855,c7c052a3,4146fd20,ffb658be,a4b9f69e,d825ebe,c16e8c3c,e2b526a1,cdb559ee,dc2d79f9,26baf44f,b84ea4d4,4bcf50fe,e51d7ceb,30e2e7f4,63036758) -,S(52db0b53,84dfbf05,bfa9d472,d7ae26df,e4b851ce,ca91b1eb,a5426318,da32b63,c3b997d,50ee5d4,23ebaf66,a6db9f57,b3180c90,2875679d,e924b69d,84a7b375) -,S(e62f9490,d3d51da6,395efd24,e80919cc,7d0f29c3,f3fa48c6,fff543be,cbd43352,6d89ad7b,a4876b0b,22c2ca28,c682862,f342c859,1f1daf51,70e07bfd,9ccafa7d) -,S(7f30ea24,76b399b4,957509c8,8f77d019,1afa2ff5,cb7b14fd,6d8e7d65,aaab1193,ca5ef7d4,b231c94c,3b15389a,5f6311e9,daff7bb6,7b103e98,80ef4bff,637acaec) -,S(5098ff1e,1d9f14fb,46a210fa,da6c903f,ef0fb7b4,a1dd1d9a,c60a0361,800b7a00,9731141,d81fc8f8,84d37c6,e7542006,b3ee1b40,d60dfe53,62a5b132,fd17ddc0) -,S(32b78c7d,e9ee512a,72895be6,b9cbefa6,e2f3c4cc,ce445c96,b9f2c81e,2778ad58,ee1849f5,13df71e3,2efc3896,ee28260c,73bb8054,7ae2275b,a4972377,94c8753c) -,S(e2cb74fd,dc8e9fbc,d076eef2,a7c72b0c,e37d50f0,8269dfc0,74b58155,547a4f7,d3aa2ed7,1c9dd224,7a62df06,2736eb0b,addea9e3,6122d2be,8641abcb,5cc4a4) -,S(84384475,66d4d7be,dadc2994,96ab3574,26009a35,f235cb14,1be0d99c,d10ae3a8,c4e10209,16980a4d,a5d01ac5,e6ad3307,34ef0d79,6631c4f,2390426b,2edd791f) -,S(4162d488,b8940203,9b584c6f,c6c30887,587d9c4,6f660b87,8ab65c82,c711d67e,67163e90,3236289f,776f22c2,5fb8a3af,c1732f2b,84b4e95d,bda47ae5,a0852649) -,S(3fad3fa8,4caf0f34,f0f89bfd,2dcf54fc,175d767a,ec3e5068,4f3ba4a4,bf5f683d,cd1bc7c,b6cc407b,b2f0ca64,7c718a73,cf71872,e7d0d2a5,3fa20efc,dfe61826) -,S(674f2600,a3007a00,568c1a7c,e05d0816,c1fb84bf,1370798f,1c69532f,aeb1a86b,299d21f9,413f33b3,edf43b25,7004580b,70db57da,b182259,e09eecc6,9e0d38a5) -,S(d32f4da5,4ade74ab,b81b815a,d1fb3b26,3d82d6c6,92714bcf,f87d29bd,5ee9f08f,f9429e73,8b8e53b9,68e99016,c0597077,82e14f45,35359d58,2fc41691,b3eea87) -,S(30e4e670,43538555,6e593657,135845d3,6fbb6931,f72b08cb,1ed954f1,e3ce3ff6,462f9bce,61989863,84993501,13bbc9b1,a878d35,da70740d,c695a559,eb88db7b) -,S(be206200,3c51cc30,4682904,330e4dee,7f3dcd10,b01e580b,f1971b04,d4cad297,62188bc4,9d61e542,8573d48a,74e1c655,b1c61090,905682a0,d5558ed7,2dccb9bc) -,S(93144423,ace3451e,d29e0fb9,ac2af211,cb6e84a6,1df5993,c419859f,ff5df04a,7c10dfb1,64c3425f,5c71a3f9,d7992038,f1065224,f72bb9d1,d902a6d1,3037b47c) -,S(b015f804,4f5fcbdc,f21ca26d,6c34fb81,97829205,c7b7d2a7,cb66418c,157b112c,ab8c1e08,6d04e813,744a655b,2df8d5f8,3b3cdc6f,aa3088c1,d3aea145,4e3a1d5f) -,S(d5e9e1da,649d97d8,9e486811,7a465a3a,4f8a18de,57a140d3,6b3f2af3,41a21b52,4cb04437,f391ed73,111a13cc,1d4dd0db,1693465c,2240480d,8955e859,2f27447a) -,S(d3ae4104,7dd7ca06,5dbf8ed7,7b992439,983005cd,72e16d6f,996a5316,d36966bb,bd1aeb21,ad22ebb2,2a10f030,3417c6d9,64f8cdd7,df0aca61,4b10dc14,d125ac46) -,S(463e2763,d885f958,fc66cdd2,2800f0a4,87197d0a,82e377b4,9f80af87,c897b065,bfefacdb,e5d0fd7,df3a311a,94de062b,26b80c61,fbc97508,b7999267,1ef7ca7f) -,S(7985fdfd,127c0567,c6f53ec1,bb63ec31,58e597c4,bfe747c,83cddfc9,10641917,603c12da,f3d9862e,f2b25fe1,de289aed,24ed291e,ec67087,3a5bd56,7f32ed03) -,S(74a1ad6b,5f76e39d,b2dd2494,10eac7f9,9e74c59c,b83d2d0e,d5ff1543,da7703e9,cc6157ef,18c9c63c,d6193d83,631bbea0,93e0968,942e8c33,d5737fd7,90e0db08) -,S(30682a50,703375f6,2d41666,4ba19b7f,c9bab42c,72747463,a71d0896,b22f6da3,553e04f6,b018b4fa,6c8f39e7,f311d317,6290d0e0,f19ca73f,17714d99,77a22ff8) -,S(9e2158f0,d7c0d5f2,6c3791ef,efa79597,654e7a2b,2464f52b,1ee6c134,7769ef57,712fcdd,1b9053f0,9003a348,1fa7762e,9ffd7c8e,f35a3850,9e2fbf26,29008373) -,S(176e2698,9a43c9cf,eba4029c,202538c2,8172e566,e3c4fce7,322857f3,be327d66,ed8cc9d0,4b29eb87,7d270b48,78dc43c1,9aefd31f,4eee09ee,7b47834c,1fa4b1c3) -,S(75d46efe,a3771e6e,68abb89a,13ad747e,cf189239,3dfc4f1b,7004788c,50374da8,9852390a,99507679,fd0b86fd,2b39a868,d7efc221,51346e1a,3ca47265,86a6bed8) -,S(809a20c6,7d64900f,fb698c4c,825f6d5f,2310fb04,51c86934,5b7319f6,45605721,9e994980,d9917e22,b76b0619,27fa0414,3d096ccc,54963e6a,5ebfa5f3,f8e286c1) -,S(1b38903a,43f7f114,ed4500b4,eac7083f,defece1c,f29c6352,8d563446,f972c180,4036edc9,31a60ae8,89353f77,fd53de4a,2708b26b,6f5da72a,d3394119,daf408f9) -#endif -#if WINDOW_G > 9 -,S(90a80db6,eb294b9e,ab0b4e8d,dfa3efe7,263458ce,2d07566d,f4e6c588,68feef23,753c8b9f,9754f18d,87f21145,d9e2936b,5ee050b2,7bbd9681,442c76e9,2fcf91e6) -,S(c2c80f84,4b705998,12d62546,f60340e,3e6f3605,4a14546e,6dc25d47,376bea9b,86ca160d,68f4d4e7,18b495b8,91d3b1b5,73b871a7,2b4cf61,23abd448,3aa79c64) -,S(9cf60674,4cf4b5f3,fdf989d3,f19fb265,2d00cfe1,d5fcd692,a323ce11,a28e7553,8147cbf7,b973fcc1,5b57b6a3,cfad6863,edd0f30e,3c45b85d,c300c513,c247759d) -,S(57488fa2,8742c6b2,5a493fd6,60d936e,a6280b0c,742005ab,ce98f585,5ad82208,31b3ca45,5073bea5,58adbe56,c27b470b,af949ae6,50213921,dc287844,f1a29574) -,S(f1133cbe,6be8bbc8,dc8df2b8,d75963c2,d40ed616,c758cdc8,4edbc5eb,4899447d,57fc2447,2225b23f,5714626d,8d67d561,10bd3a60,dd7a1687,cbbb893,f652f50f) -,S(95083e75,3301bd78,7f8989c7,9065bb81,3f3d69bf,f3e42505,f4e0417,5bbe89c0,844adb5c,e7d10de9,4617c73c,a77040e4,ee4e92e0,156b3c70,cc593fa4,94b33482) -,S(1a908355,cbb75675,5e576ed2,9c99af63,8668c7b3,63c8d973,62100443,bc5c75c6,d765466c,6e556e35,2f778722,25627d80,a7353807,4b44ff27,57ad22e,2f2454a2) -,S(c5922f74,bd343d5,aa867308,fad97f9f,8a2d1f63,c5f31db4,f04df3be,f349b648,77b1f068,7cfcdbe8,812605e5,d8b752c,da811844,236a4c43,77f53c94,6e7bd648) -,S(64e1b196,9f910297,7691a404,31b0b672,55dcf31,163897d9,96434420,e6c95dc9,c16f60c7,c11fc3c9,eb27fa26,a9035b66,9bfb77d2,1cef371d,dce94e32,9222550c) -,S(33b2e76,687744ed,6c521bad,3333dd37,c602f8a7,549e9ce7,808fb7ea,7ce08de,e1bcfe7f,c8ed8ae9,5cf6c243,7fdd94bf,d742e8ca,a6de7811,4c25112a,86988efd) -,S(20f18f4c,866d8a1c,c2a31033,17b4ac31,89fbf30f,f294a75c,951473be,45e4f294,8d6857c9,d08ef7b4,fd888336,3d37bee7,fe8529f,7173f589,43fcae81,d2d0ea0e) -,S(4d1623c9,44c9c716,a0eb4c68,5e2a8b9d,2df34653,54643bef,d1444176,d7b69a8b,ddf1b9fe,8744ad03,f996bf6b,96ec3496,2b601bd5,ed952f78,54f58388,8917be80) -,S(a901b0db,e8ab292d,280d6b36,85894785,4faad0a4,dd0da7e2,d4ad0ff5,3db079e0,3f27e7e1,834f1a61,af6f04dc,61e7ae64,716bc5e0,a6b063b3,1d0e60e,47298a9d) -,S(7e0af071,30218ffd,50bd66f4,484645b1,2f42a24f,7c80889b,3031c9a6,ebfc9a70,50bc23f3,926cd0c4,9f53fbb2,35eb1e89,d579517,f5bdc3ab,2416db78,5aaedb3f) -,S(7ba8187e,1a7b25a2,c185d335,440a9038,b47f0528,546e9da4,ef82aab0,5aebf20d,6e6aee6c,9625370a,f866c25c,7ca5dd78,527efbc,e7d8b3a3,9ab24930,9a185187) -,S(8c050fc3,4d83b279,b6000816,e18fca38,9767b796,e926772,55b84a39,d93a6807,986314ef,75b68fb2,827c2965,4198139,5d699fcd,81cf23ce,7019bc41,35174870) -,S(53b7849a,78e4df86,25860583,a5249948,9d7201a2,cbf50620,2a7b8b1b,c99c2ec9,4e31ea12,ac607d07,5de4b22d,e1be2c52,e0a44d25,4728d2c5,44d2ddf9,e3e469c0) -,S(9bdf9e67,a5d0c995,6a075a01,fe762be,b6335004,31dee78e,febc527e,53313b33,94264621,a5960e0e,e24c2792,6f16cad2,907f2636,762e8d5a,17e94afd,8e9d2bb0) -,S(7caa72b3,7a8ab3bd,bac031a,47606f89,17d9f42c,6ec2d2fb,429fd990,4a381f34,5b5853ab,7ee5de8d,34e3d6be,b201094f,ff8fbd1e,682f7f1,ef87ddd6,5d7303c9) -,S(2ef29b9f,9827975,79c0295f,c3f48db7,925d62c7,5532493d,de16b97e,3993d81a,496c944d,d9875ba6,a537ef9,6bf4c714,a0afff24,387d95e8,9b42337a,33110753) -,S(df157cad,95b07875,573c1860,ae5d02c6,4029e952,ec354e6a,9e5c34be,97317ff8,f2eccac7,75922b50,899c979a,2b3cc30,b629e62e,85693ba4,70f6ee38,1284c162) -,S(dd55c150,a29ca526,b6182e64,3b9eb544,e651d236,b71920e7,b15a9870,16454b1d,44c757a5,42f4ea2e,b39605d4,268c2510,ac685aab,d77a8f5c,4d95e23f,4c2e9368) -,S(16886cf4,6ed42c79,19147763,63d3256,c4d5d393,87f01723,25b9e4b8,98227f27,7421a220,7ee73299,d46192fc,93ca03de,c824ed8d,e2f48367,ec538317,a17fffb) -,S(6ff180fc,daa30618,8e8b306,d6f0acff,27968c22,484ff45e,56aeaa7b,2b60732f,7d16d654,f0c2aff0,fc254dad,63761a2,6c8d4022,ea85b8cc,22f3ea1e,f69961a9) -,S(3ea4511,a00dc2a0,3eb4f51f,40ee677c,aa912b55,39f685c4,f8bcc8ea,dc395e36,6c9ed1f1,528b0215,93a39839,340ddb53,a2f2e36,5290c498,24b035c6,73c9259d) -,S(b82cd70,dc3de9ea,b38742d8,f32dfb8d,53e4150a,835e54b6,3c7cca20,f253081d,e8bcbfe,1f7f6e75,d32e2049,9329765f,2effc56,a922f268,60d4bc0a,add0e24d) -,S(fe2fc3e0,748745,84ee23bf,105a69a6,6d056f0,17327d49,b7b38b57,a196c77f,3e18941c,c3c6d297,cc9a32f6,95807b1c,7da8561d,e4fde71d,4f9bbdb6,e9bf3916) -,S(4b90176,cdaa3693,47e8778b,12db9d6e,e8b00114,46ea35ec,845dbf57,4bb7858b,f60547ab,6e9c5fd3,eca6e349,b85880c6,1fdad0fc,2f7ab155,295caaec,b973c154) -,S(35f38251,1d34600b,4b8c86a9,f0dbc9ed,defc4272,f59528a0,cd3ec10a,5944c6d2,29a835f6,ef7fa1e5,f6f37a80,cf96ca98,43762bb1,b12a0dae,ae83234b,d0b5ccd5) -,S(1d74b297,311b7ff,a1027e26,587d3f5b,e1d0e9ac,3f0111cd,f3cc2371,722cb94a,5c7bcf8b,57f114e0,b73bcfb8,10f5c60d,35dc99ae,9dc7f0e2,606cc1f7,28c2071e) -,S(50a094f3,9c6f956,b020737,b9ec722e,4f75d1b7,c41593e6,f934a68a,98450428,a286e222,dfe10cfd,9689eaba,6a81f044,89c86db6,869aa1b5,54a90f1e,83778eee) -,S(9b65bb81,2129157c,dfecf12e,275ec38c,282dbcd9,14b48105,99b0a6d6,27c63db7,c582db1a,3f0f2242,1913b2e9,51e98a78,660b4c40,ad08fd65,528593bc,18223188) -,S(8b4544fc,1fdfa06e,456c1115,a1dc831c,85e7f1c5,e620eca5,1c20802d,36a4bc6b,e3e77c41,288f2602,e722af7f,4b70e64d,e4116fb9,955b03b0,6ea8b19f,7a20350d) -,S(6c709880,b959eb7c,5179b29c,c5578fdc,6cb2ae13,ddcede29,d5f81d95,de0ab4aa,c9e33fae,bd8eba42,6736c0c7,6f3deaba,ee2b59c5,953fb43,c2dcc513,9e7c4bdc) -,S(77760b51,37ba6a71,95d891f7,94a087a0,76fc9d67,802b81e7,85b5677,3d537806,f5202cf5,aaeea58b,f4f58c7e,df4417be,1b87ffde,e68e77f0,d7e81abe,158e3a25) -,S(1a8bd783,6a0b0c82,e9a904a8,a8c91a67,e23cd4f8,efd625d0,df4c426e,7e163102,61fe64ca,b0952cae,3c574f28,2f74a87d,c2a96316,b7009f2e,4e9c5fcc,12285844) -,S(fe217db6,59079913,fb1e453e,d24d91d6,a3fb3099,e69471d7,53db5390,864abc30,5dcf9abb,a9625ed6,80b0f20f,b1f047d5,93a0c61c,53969253,8cdf6b03,4d730b58) -,S(2504d637,54afd5eb,c38f58b6,5ead696d,7e3abd7,48cb6c5f,212aed49,f5b33b91,79a6bf43,75f1469c,4f5321c6,c72fbbf4,ba7cec10,5675f437,b5e013ad,7b5d75d4) -,S(b06f702,f47b22d7,89a9bd3f,687105c3,6160abbf,5cc8976b,7fbddcaf,db197b5c,7669bbd4,19a4d491,f592a35b,6aa3dfe4,5bd2fe7f,d179c778,1cd5f918,d732f63d) -,S(803b203b,b31f9cf9,4034eeb9,31b54480,a6f3f99e,bd23d0ac,bc2128a6,d044e23,308abc8d,f271f759,59b20c5c,7fa62baf,bfc9ccbf,49b946a9,54e5381c,1728d1c7) -,S(266a9cb4,c5f5cead,bb50e5bd,a03a7312,e52de1de,8e95a8dc,d57289fe,302749a,9eea970b,a856b2fa,a3e82877,cc84ed4f,3dc0efba,1e7c3baa,8b386ffc,46e0ae7e) -,S(fd8a9d95,d80c7ad5,2599a7ab,98163df3,64c4c141,e9abea35,5d7360bc,f84eba94,a9fb1702,100953b3,59b2e268,8ae7fd33,a30377da,47bfda71,3e2d7d73,dfb1030c) -,S(a7322df3,9f28f23,59fc339a,8b2c80be,6e84acc5,b7b0b8f8,f2cb6f26,f9db0a7d,22f6fe9d,21749501,7fdb7f5b,2f12fa57,95f40e1,31714885,c12a2ea1,6edb6be6) -,S(82a8c10f,336a6649,63a104dd,bf7f0f18,bd4c461a,ea569ffc,82c3c7e4,cb052d36,737ceca2,c0ef7227,8b90501c,cb71b671,5e5c31d4,cd0478c1,18fe1287,95f1dd0c) -,S(9b50d1b6,8e3bf795,7cd12f,5a60c26,6c4ef2b7,5ba5c516,c54784a9,4f15d6df,2afc8d09,b79176d8,d003fd2a,4f18d526,403fff27,2d47e778,7376feb7,cbddd8fd) -,S(3f9083dd,c8b423fe,7de3a822,81d3056a,b8dcb9d7,ee82cb80,6718595f,bae08d32,cb13c152,fd511d91,a9e0ed90,afa021a0,81f77f6d,20cc1376,e2195ffc,f28fa758) -,S(c75c85c1,ee17c1a2,56eff6bd,592666cb,c9231706,59d50bfa,dbd1074e,f2167faf,1ab4eabe,5e09409d,75cca892,2647f48d,bd698a16,d4f7cc85,96daf169,40023a52) -,S(c5341fea,f8a0f5d3,b4d0cf0d,2f7aad7c,60ea8e2b,3d4b7fb9,5c68d576,98656045,95f9f4e9,7e5b9f,a48fa422,a26ab982,dc48a4d5,4d712398,6e6d3ab9,74e88915) -,S(83acda3e,2a8997e0,d52bd4c6,8705dd22,220852b7,752d67fd,8967a032,60c2d89b,dce1bae1,d655ba51,7f5b5580,99711757,a77cd3b,dd4b8e8e,330e9779,1bc31df0) -,S(5b819146,8b299074,5b9c4164,e29d594c,f1c0d571,6c5d3962,5bd279b3,25237b,cc3636a0,3fddddfa,bed88daa,b081f359,1c48d2ca,71ba34fc,f6989f4a,f7625d8e) -,S(64778122,214e38ef,f8041796,166104e7,32f5f664,d38d7721,9b89045e,2c3b0e6c,329cf049,7e15eec7,b8eafc4a,b8a7d1c,d8b63203,8d4aef81,974cf984,4611a32d) -,S(ed4d826a,fe5762f4,79509909,9aee8664,2b475a9d,6da1017c,43d0cb9f,1af12323,8c6f81be,3fafa5ee,c8296f92,8ac7919d,c4d88c9a,59442274,d0531b7b,f7e48e78) -,S(38b42924,419aecc3,acd6f551,346fd61a,4d82ac2b,55f7afe9,7a06eb40,cd109c4a,7f42c096,2feb2f73,b2b0965a,1f359a6a,de49d768,a2ce6b07,b5acb92b,73e05583) -,S(c3cad4a8,d8bb94a7,b434cf70,183e8615,bb2a8f62,24f216e3,446ac2e9,82138911,f649be27,8cad9764,20742ce3,82dce3a1,420e372e,f1b25b27,59a8ed38,7282765e) -,S(2d408ff4,d3d236fd,54fae40d,ce3ea9ec,d9212e57,36591a9e,55588e4a,54bd6538,d596adf0,e8692a06,bc6284bf,299bef6,85e2a171,585aa132,4b9a05b5,ce815b7) -,S(ee7adf6d,247f25fb,76e90cf8,13f888eb,d67423a3,a3c6fdae,bafb7eaa,7a33c854,e077184b,4ae8f705,6c10dd9e,f541689d,143f6871,789e1801,deaefc1d,527a8fb4) -,S(2f9457c8,a9ffaca1,3d91151d,c4c5e89d,dd5d37a3,7c9a864b,7c811f3e,1144b34,eb4c9848,9093d573,a295407e,1d6fc48a,787120ce,b3d3dcfb,b40634e0,e75e221d) -,S(d3f332b8,a0f11582,1ce3478c,efe18de3,60120483,ef531c27,7b30c46e,b7fec294,ea75b9b2,5d717861,d1af1c01,9c372941,c8968b90,ef134f9f,323215e1,bb0b2155) -,S(183408d3,38b05aad,3521fcd8,6ef36dd7,5f3ddb86,66b52f7e,9a4cdf1f,8e152b91,66998520,6edf4ac6,f39be21f,20c98824,210e204c,e4499809,5de35537,1641218c) -,S(283fec5d,b1145e53,ba8f1f0f,f9cf89a7,21faffd6,c2534686,3d395609,5f40374e,70b01237,74af550e,68e68e5f,65ca6e98,8846e03,cf39af77,8511be82,bc32fefe) -,S(ce7570a,4f943cfa,413bd249,d8e7dbfc,ebc73579,770fd6da,f54a0dfb,dd52fa62,e115b14b,ef4695cf,fb85bdf9,8ba3985c,bd5e5b89,83e05390,7c36f9ce,8b75d41d) -,S(7e9c4f19,c8f4ec3f,1269f648,cd919525,df790315,74cbeb15,37794a4c,838fd470,e9d9dbfe,8cf5f5cc,a855d6cc,bd11f480,60fafa8d,ad6bd3e9,c86df5ce,b0fa5270) -,S(e2a9bbe6,d5d5bfe,a7c7f919,df2309f9,ba04f4c,722a3ec2,3bf451b4,64cb001b,e4177ce1,c3cd6ac7,78925bd6,7e72cb77,d1925b91,d06a7f16,98411a47,86393fb0) -,S(504512a4,3e17ef50,e43bf37d,42a94990,f55e641b,1558c265,e7099002,75271012,954a5fd8,57ba3acf,2d4b1f41,e8e1f2cd,1f21c4b9,6899781b,742a49d2,e61ed18b) -,S(81d1f013,a6bb325f,4b2d1d51,ba72c721,859945d8,a17b3411,cd5cbe87,285f850d,2d5d2fb1,f0c30855,3b1fe249,298b2059,259d3d49,d4d7071a,dce4bcc5,dc937193) -,S(5b66c2df,c1d28266,18a87276,7e66c33d,d90dd514,14a3b87c,a733383d,1d895022,9bd0178e,38189569,2217267b,7407e987,27fcaeda,12d8cf54,49eb5472,d554e0ff) -,S(aeb5f70e,98ec5e38,dbd2d544,bdbff8ab,99b583d9,af58c597,afaf8688,20381186,618bd6b0,d25ca70d,f08b7692,9336e421,691b0973,f2f5a05,2e7adc17,3584427b) -,S(b289eff,e841943b,84761e3c,67a9c02a,557679ca,76ad753a,707a9821,2505052e,7a981f0,c21862a8,53b4f895,dc62482c,530ed738,5e5d1e33,cfb9d0f,e879992c) -,S(abae3945,8b12199e,6b0c8360,cfd28288,3f585917,e44e1200,f81bd356,f619291c,adb23bcd,b3d069c5,e83be30b,2469b068,b2a81b7,b667e934,233b75ef,b5753f28) -,S(4a9583a6,485b5a5a,81ac224a,518eb29d,1e0f658c,8d91b013,9419c809,55fbacaa,d8003c9e,e3c842f5,ede375a8,a7768db4,803ecf11,9b7b37de,cea15631,b4e8dbca) -,S(d52f630e,dba6f7cb,65fcf465,44ab0d9e,ea236ac1,460f17ae,3a210102,10ebc169,21155748,9fa93b88,3e5bea50,da005c53,68e21a0c,41bc83d9,145c13e1,370d26d0) -,S(bdc5237,82c75858,f5c50fc0,52e4c1e9,c74a2a63,35bca9bf,8d10e120,9add6a4d,abb1d9f8,74637668,e214efba,fbf529d3,12ff023b,c1d5723e,58540436,6834f189) -,S(44770a33,8bf0aab8,3bb64e47,6eb6167a,88156d16,8f13ce86,26ee0912,e59ad087,5b5930f1,2e9c40bc,b3393a89,5c2d6457,6a3abd23,b7291b99,c965c33d,ef60a55c) -,S(b15e7b32,2e404aee,319ac203,23e36672,6503108d,8ee8e1c8,3e32d924,515e1679,5246a819,bbfb291,5f82ed56,50796f50,5ced5c25,87347d57,a873ceaf,3d997e7a) -,S(a1ed7557,5225cd0,f2c50f75,8a1c1df9,665ae108,d5e04190,27bbd9ae,ddb00f22,3c83145d,ad9f8748,7b97e746,4850ed02,d71dbd04,93281a1,3d212776,6a791ee2) -,S(e8aaf361,6a1bc60f,d9bfc43c,2c60580f,479e9ec9,c23a37a2,3cf8afb3,1d918af5,6ce693b6,4a37c672,7e141041,ab9a0d58,9ab9c303,a5ac3d3e,c89b6f27,9e79827c) -,S(5dc6f8cd,2c855e63,52a4a4ef,6187a6d6,759c043,38a3db76,c5a3aa37,54c20a3,f602c342,8593a9a8,d671d1bc,7c1d8834,fe9f5f5,2e6a7f0f,bb870146,4e6f4838) -,S(63327311,67bed8af,68a063ef,22aa489c,f6563620,461af26a,5f1a07cb,6b42f3a6,b8f7c3b2,20701320,f20ca036,761d3e56,bf94a700,9a919f1a,3ea0cb81,b74424a6) -,S(8a40d925,9a393b38,2305c201,7e8654db,ad66e50a,d798a0d3,535230f9,48080263,afb6a74d,9849454e,dd7f703a,5c6616d1,43f9cbcc,9a9a5d6f,6a7b5d1f,9d9fcaff) -,S(e7147107,27c7420a,f517fd3f,9a05b7de,a6a02c8b,cc20b17d,cdfdeaf8,2078645a,da7d67cb,c1ede9d4,fedd5dcd,c96b04f9,a3561ba0,2581b055,eaa144eb,4217daca) -,S(6131291c,d95fb878,1e42a68,553952c2,9922bce8,91c026c0,cae1f69c,9661c82d,160e1c1c,13342fd4,59d4f989,8ae632b8,42b89479,13733b89,384fc104,2d30bf01) -,S(4bc4f845,b6764692,d0a9bfa8,1788809e,fc5e2aa9,da5003bf,b782bcf1,d1ca4951,87092dcb,b9c3d254,e3b055ff,3a76ec05,64c4a7c5,7fb1783c,efdc40fc,10b751f0) -,S(45a880a2,7bbee9df,29f9bff5,c985f364,52865b5d,582a201f,698e6eca,a2be67df,fe49a6a8,b5e46bf1,ef679714,dabd590e,a831d46b,8ee94eb6,13132ba3,7855fabb) -,S(6a826a38,317c0c86,64d6847a,220145d1,877e5495,b21500d3,f21f1a0d,4af4f2a4,4521954e,fcc98263,df2f14e0,e6e6b47a,f6b83f0b,bc20722c,15445f87,e05f4513) -,S(15356506,f255f7e9,6cc8aa1b,9dce572,8bd860de,7c6cc75f,613e8a34,366a23a9,cd15abbc,d744d485,d5e401f,1f89a5df,122f37b4,e362b4ce,e3e53b1c,110bf3) -,S(f3bc12ae,f53d9f5f,6b865178,2dac2ec,cacff3a5,cca6443a,2b5e1ca0,f2b89b91,cfd4d36b,eb2e11f2,41fd0f36,7a0737ad,303e915f,f247f131,368ca509,18e00957) -,S(7e3c8c6d,fa04a536,f7a26ef1,8b387649,22320bef,58453373,6f728297,335c0fd4,72ea16b5,32a7336d,3332400b,303c0236,b6a1294d,88ce7fe9,15571284,d1f7c189) -,S(198cbfcf,a0575fc2,c161c696,d85155fe,6943ab9b,d6e17223,d8844608,ad0369d8,d5e6268b,30952422,be59fe0e,fe7ba2e7,3215994,827a46c2,f2972b26,153cf7ae) -,S(1e056e89,b68cf35a,22183c08,9089b90d,5a147caa,780b1fd6,3aeb1350,afb0e5e8,b8241453,abc44c57,ddad6ff3,86d416f4,3e258a39,c6f8837,9f80472b,943f32b9) -,S(dc7ff974,8d827e7e,a6173b2f,1a646d47,d8108144,ce7f98fb,3fac729e,72faaa21,c1fdac5a,ef4c6f0f,fcb8e1c5,c4417c71,3e3d5f07,146daa1a,aaf2e7fe,e70c4914) -,S(71b95efc,c4981e07,5354bc1,1cdfbc48,36b2eff0,bf8f8ec2,9a99da1b,2fd28e79,fd5a3197,6fad6aee,c304752c,c3ebbc51,1f3695b0,9a737fa3,af42cc6,efd684cc) -,S(43854caf,29dc2bd6,c9f3e8ff,a25bba83,f6b96121,897044ae,6876883a,de542b3a,56365176,897632f,8dde3167,7a24f558,34c5c9a5,5c1cbf36,fd8b4480,3c9c6c81) -,S(2adfe17,90e9f9c,708c9b73,d5fd084,b6eff990,fb877961,45c2ecf2,d427b222,b5ce3160,5d6dd9c6,22cae425,ccd28912,c4439820,c06950cd,4c86d9b4,53abd7ed) -,S(a123452c,2b7eaf31,15b3a534,3b3ff31a,9f70c54,ae33c620,471e3e82,27a9d6f9,933d3483,78a71f44,3788194a,afc545e7,f53e37a6,f779f96e,8fa14ccd,ede3b4eb) -,S(9b89a3c2,ca995a81,86c15217,61348737,aab166ae,7decca60,3d06e32c,cec0a6ab,2a7d3701,a8724b12,bd7c4830,224ac083,cbea83d0,543b5414,80ba8c8a,e7731232) -,S(64dd7457,e7d9d739,8e2b9a0,dc45272b,384b0433,9ed8b2ed,c9079646,11e9e9b2,ea90f8aa,e214ee16,ed608a72,36699899,4e311dc7,780ef885,b29290c3,823c470e) -,S(59227431,be607c6b,d327fd71,4eb71c87,20abba42,1c7f550a,6b35767d,6fa2176c,cb7571c4,71c5527,65bd289e,a3cf3f38,796da2b1,2c953d0b,8705125c,4861d598) -,S(53d765cd,adb26e9e,1c80ddf1,99374363,843b7d08,a7237bdc,8c5106ef,795fe2c2,7bbbb198,eb39973b,76d87f81,94d45150,a66d4f3b,128a40be,c989a405,ad7c287b) -,S(e507de9e,c16b3bf3,523a989c,f5ff6c1,452ee90,9b66ffc1,6d7b519a,57bb66af,a2f2f02a,8272de6e,3dc8b395,8959ad2,51b6d3d0,4c81952,59a501e2,8ff7892a) -,S(16f48c6,eb84fb2,81903b8c,b9f60b7a,65601d76,e2a57983,5569c983,39b4a6f2,8613bb84,8398681d,66f1e75d,5b6ef44f,d827b629,f4956a4,41d8f503,dd32b289) -,S(650471ae,774265e3,270b5132,33d12d85,bb98e38,2a3b3af9,cab6339,e1446056,838e7793,34aa6fe6,cae90a62,d359c339,187b4032,15d97cda,4e62724a,a5a50306) -,S(15dea416,fa34584f,cc90e19d,69825fae,348d1ba1,fd7ac821,559aac2a,bc21dda8,1fcabf2,1e19ce68,ee12a3d2,84bd1304,10fa5f5,d45f9c15,d4070243,a8433047) -,S(b42b2495,4f1f70ed,3db90087,8357ba46,ee9d6a07,b4f7c751,dc5cba07,b05b46e2,e15723eb,e0bdbe6,d6f28d6d,a0443c63,4851f5b4,c551bec6,9f9196a0,969ed71) -,S(8e9e4f5,c6aeac31,1dab1125,dec9b460,6ab10b7e,8e250960,a17fc57f,c0230f83,ffb0e211,c79fbb79,78bd4e53,a05a267f,f1e32c34,d6287dee,64576d31,ab959ab2) -,S(87be7323,73bd4b73,8627fb63,bd4d50bf,d6f2bb81,f804b528,29549fe9,3fe1ac2e,f6a9186f,f147b9b5,ffc844b2,ec0e255a,1ae5537d,75624288,ce8421f8,7e94e1a4) -,S(43601d61,c8363874,85e9514a,b5c8924d,d2cfd466,af34ac95,2727e1,659d60f7,8791c000,7c09c94d,b328034b,88c5bbbc,11333536,6679eb09,9a5e75b5,83bc2c2a) -,S(341b1580,f83071c5,365f0bcb,ba66af96,6902e394,2a2560ac,a0daafa3,2ab49d0d,4b985b13,c5499026,7ff564d2,d4649c6f,7e8fdbe1,ba101d94,1c034e14,64877b20) -,S(175e7cb3,ce4a3a43,7c7181e2,c79fb154,33ac1aa8,e56492eb,57627171,f14dad95,31ce61a8,7834f52e,fcf8703f,93696f42,58130155,63ca5d9c,e92d8fc2,81135b0d) -,S(5ad430cc,64e61c61,e3b3c848,2ca3ecac,89c1e495,4c80ba98,249e45c1,307165ad,bea2a060,505c13bc,317ca083,c5a8b85c,9ead5f6e,1ac23fbe,ac7cecea,9251c791) -,S(41dce0d9,6dace318,988602df,7fa84c1,80f0ce3,dd7d09f2,8aefefa6,db8b837,74962c3f,ed9a6e9c,896635ea,855323b6,8850091,f84dee33,3cdff8d0,d2827928) -,S(a5ef4498,87104dda,103c1dc2,52067643,9aed2d5e,432fe5b,a23cc142,39961bcc,1cbcf83e,a363e0d9,3e6ecc32,8653ba7a,a165c526,765b09f0,696b0d61,f122db3a) -,S(4da26ece,9ad46003,38bdf68b,852a2cbe,18225f2e,2d6d5e62,6db57235,fb3a9d45,d10b5a63,7ab546bf,cc610e2d,1c3d61f4,61b0a806,e7ba29c7,3d3de909,e9fae659) -,S(6e621e6f,53d2408e,488d8eb1,6a19a4f7,e9d95585,11e69111,29dedc69,f98f4763,7b148ef2,73e1b131,341ad477,9342c7bc,7b945a2c,b52c448e,4bb5fd50,3cea1a19) -,S(ebaf5764,5bed7469,9b57ea75,8a395a90,66bae20a,8f082ab6,da4554d5,278be83b,5847f4e0,6c653033,5e29ea94,389ee3e6,d916314a,60126028,650ab9e0,bfcfbba7) -,S(c0f88a71,711b632d,24b55dbf,52b15d2,faa38ca1,1438c17a,6a6ff635,3310182f,2cbfad4d,16c07021,86611eec,408082fb,fb2e9898,141a5248,1c59e44e,cd0676ff) -,S(5d9b6c18,84b79498,c6244fbf,262922c6,dc1cddb7,3cf70ae0,1b5287b0,5b5c6350,328e831d,2f2b162c,4abe1644,bb54cc85,18db178c,5b6ae97e,5e85110c,7d7fdf1d) -,S(d1d1360f,37ed6e69,d4f214c6,323a53b7,e57d7595,55904016,654c49f0,4e02e21c,627eea93,c6c9b53f,94559414,40a8b100,6eba68d4,6c922b6a,1521f394,6dd15e4e) -,S(efc987cb,f1023af5,58acfa18,97b1b2b2,ace29a83,65674703,e4969ccb,ee411731,195a6a65,d3790bec,71642986,3bcef432,e38242fc,9f565dbb,e159bc42,f5740c69) -,S(f3026b97,163df3bd,61b88b78,73864480,968d1d7b,83ef6b01,31090faa,18284ff0,177c3a61,682363ab,bf281615,d59f06ff,5f87644c,84d670e9,a6c56ac1,b611509b) -,S(5d34ff5f,123b5b69,92ac92c6,8c9cff46,deeecf9,68ff830b,5622090d,682c5873,2d1a0b9c,8eaba065,43204df1,48eb1618,25443efa,80f8aff3,d49b6626,c5955ac8) -,S(cbf9ba17,94a95247,c39da065,84308cc8,e0ee591d,31a9b0bb,dac67280,468447f4,549b18c3,10feaea1,225fade,934112d3,4058101d,74f00538,1b82796a,d0461736) -,S(920975ba,9e2261b,bf5982a6,b57a7344,8e7747b8,368d7a53,79acacd4,c7dcd31f,e95e0508,81af550d,9221f5a,e9541031,6367d24b,d545bdcb,434e7638,acb46dbd) -,S(815b2ae4,6fdcb55d,926cdce8,2b4f25d0,39132312,3bc180ff,33fcf132,7eeca64,62f637c6,7d886374,8f1e2e26,865118b9,99285b87,55f25512,c968b4fe,49b8c971) -,S(1bb9a6c2,8e28d4ba,30ea8639,7a4d387e,27ca8025,da231926,de3c454,f7e0b16e,a0cbc016,5e32171c,8184265e,ac7e0147,206349d5,41035a94,f56efc49,dcd7ab93) -,S(6f0153fe,dffd83ea,b099d29d,dde278f1,9c05a4ba,78eb4c3d,34d337c6,da68bc22,a532d00d,35013f85,9f4041d3,aa231f2b,9fc49967,e0e2f82,4d5051f9,e7f0c626) -,S(3454f73b,3bee77a4,d00d384,71bf555a,ed23e5e6,c6dae855,2e9cb7a9,1b20258a,92c20846,cfdf1e8f,3fe5bcaa,6bdedc3,9926833a,3f40d28f,23a8f952,d8d18dde) -,S(367807c9,a3606b4e,1b8c2616,ad528030,1dfcf686,40eddf02,fc59317c,230e9a86,1f023f2f,a2bbece7,3dba14c,124095cb,fdc4f92f,281a14,8304a412,c16ecae6) -,S(8ec4fdc3,9891f6af,1374e06f,c44b815,1b82541,75fc4909,acba5941,201af62b,2dc6cae5,cac2d887,83dca0e5,3c798f8,fe067bcf,5fc29751,13756cf7,ef4e5f1b) -#endif -#if WINDOW_G > 10 -,S(5cc24a6d,4c5b24f9,14542f91,e5fa937f,ffa08551,51b8b842,8729b06a,9178a263,b1da8635,81531a1f,bfb38a4e,419fa1fe,ca8d55a8,3ddbcb98,da19d5cf,fb7da472) -,S(83905926,c03905c3,a9644a6c,da810dd2,92602a50,50c52a21,9134fc4d,e3599e9f,4293260f,e8af6792,a20b115e,aa837638,9094298b,21d9de16,cf20e0c5,7a46089a) -,S(944b097e,4721e9dd,f8204ac3,d3878fa,e8fa6c14,34ae4822,481b2985,6589b6c7,5fc47565,30e9b095,f8b79643,1e745b99,1525bd4c,4764e8e,e8af4b96,9bd6ddf6) -,S(ab0b4a3f,cfb7c134,e1caaf04,a63a7331,17327a1e,5fa90301,7b5ebbf,3423b73d,e1e79263,a5bbba8a,cd78c92c,faeccd3a,b84944d3,785c0781,3763bf1a,ce96c9da) -,S(57a344b5,220f2b0e,f7bf7fbf,5a2e4e7,1aa2c3d8,7bf090bc,f803dfee,fe8b85f,f82b7d0e,8ef9620,e48c9f13,53a72a95,a9e11a3c,1678cf10,576e639b,b1a7d04e) -,S(6e053e1a,800b7c4c,51f8c4c9,5cf0f4ff,3608e396,ec46188d,a1a9263f,c8d81ac5,86389e98,e3c823c9,e1b5384f,fce428c3,62e36579,7202fdba,dc3d8c49,395e7473) -,S(62d76406,1804717f,b30d4a7c,7567b545,48a289ec,7f083f1c,59deae25,ce485cb7,f1d6314b,661d1f8d,8531d57b,9470fb53,d1509b2d,a626a0fc,4cafc941,b668be84) -,S(e5db28f2,219fb2aa,830cf108,bd2449a,5c4d0800,82d34658,9e347f31,dd29250f,c296e646,32f97dd5,ba3b7012,ead44b6f,324fcfd2,f35f8b24,8e58fe68,888bd453) -,S(4725b3e9,a3d00de4,8a53177c,9fff831f,733ec89b,c2994ab2,3fe815f1,9b32729,ac3b7747,de38c00f,145fdb74,1482bb52,324127cd,2979ee12,d4a9e689,b9f8e778) -,S(d0d3afb6,492c72e7,394ed918,7013e347,b036b65e,a76e0569,bbe9e346,41d72b3e,2dd3a45b,94aafe07,53061caa,a28560,bd952b0b,2f63f13,96f42fb7,8e02fef3) -,S(7853e735,d717c857,97b85654,a24acff3,104143ed,cf4b4b4c,7869068f,c304632c,a873d9,e70fd14a,c2777a8f,b5a02922,bae3a31a,14938e69,cb535355,de1efadd) -,S(6db26b3,7d4fdc59,13a1a01a,14c92356,ee44e2c9,7f9d72ca,7789de33,8ee904a4,14fe2225,bf2ba0cc,28c1c409,e9849c4a,d8adf792,63869b68,54a28ae9,631941fb) -,S(b52f0869,bb98af3c,b2f7f5c,669fa43e,538e400f,63a9cce6,99aa2ef8,eb2848df,24566b24,55bc454a,e7b378cc,a0e57b6a,8b821c8c,a76fb858,bb616e17,8907be5a) -,S(8614dde1,1ee6af03,eb34a9e9,970fa7c3,234152c0,1384f7e4,c1e1f93a,197b448,2a1125a2,ac996870,2ba22b5a,d230c40e,4e5c7e55,d8ba6ba1,5e54d3cc,7b72f3cc) -,S(982a37ae,625f6e5b,78e71c18,f20bdd0,8b3308eb,59d0cab2,dbc20937,938c1cfa,671fe16f,a65128,591249e2,b5070bf,2a689e2b,dd6c57dc,18e5309a,b6a40d0c) -,S(6bea9305,26b4829c,ec99742f,c9231c00,627a09af,22ca9d9b,4081a2fd,4c3e703a,aec5402a,54517b4c,1f344d14,b1943e69,d7541f10,c45bd483,2b02b059,499a6cc1) -,S(b5724781,8694487e,7cc188b3,36d116b0,54016a99,20731920,ba7bd29,96583edb,5cbbd186,1f80a4bd,3d58262d,ebc58ffd,1d278fb3,b4d7fec6,208f6286,77845cdc) -,S(de1ade62,7ba00e91,786f4f53,18ac5392,4df5a534,704edbb6,2e0e9e2d,997c5412,7ef486c5,bf23bfb,fc6dc15a,41c0673f,a9d003e6,e1d09a8e,4bffee9d,ae2021e0) -,S(3738a57c,b1721c41,9f9e465d,fb80e1d7,33720398,bc01166d,d476d36f,3398c0a0,e1f25bb2,1662b16d,6d28a629,ad84385a,43df566c,52924bfd,11854a78,b70c22f5) -,S(4cae21c1,6b2a1239,a85575f1,2ddf6daa,1955feb8,b7502e37,6940006e,7a81885d,2affe855,388660d8,27671e89,c82832b2,25fa2c9b,29d559e2,37af565c,b4dc99c3) -,S(4c511a1f,ba8a0be3,6e37cf55,85bcc3a7,97bfa7ee,1baa6039,5732faf8,dcc2bd7b,ea69f794,5c6babff,23400fd4,a95d6833,abb27269,887c372d,8a6a45ca,b25651af) -,S(d811d8c4,323b4370,2607c25a,de936c0a,c2e4a44b,2ba51f83,20c5179e,745a7e29,6ff970a2,17bf47f8,da0aeab,cb490e3b,46c6df3f,69f9e93c,3c4dd94a,e7c05345) -,S(101eb5d3,b5e5aaff,e39bbafd,f13b5ffa,33db68ae,1fb09b0b,1cae25e6,16c43eee,9d6a5514,9867725a,607a1c96,eb03120c,a4970939,34e0cf4a,1631a63a,bac5ddb3) -,S(89eb1152,b8dde45f,e141f21f,62fead1,ecdc7f70,eff8f968,de21cf8b,72480519,f8a337c4,3181e3d5,69ec99d7,f2bc4770,cb6703a8,63fbd95b,41fdb07c,b697b447) -,S(53d633f3,f48ea44d,273d8f1e,455019a9,49d95eeb,68de70cd,bd1e964d,9ad0dc16,1b26ed76,964dcf1b,3f7fe6f3,2e6db7e6,8e8ff4ee,48fe63af,48ffd33b,cd1645fe) -,S(de106910,49891106,59a94d26,b9cedb64,6ce3db4b,8398ad1a,92f8f95f,d8d9be6a,87640b41,dbd99d16,578a3d06,d23d4088,8768a4e6,dcf83e7b,5b9d9133,5eb43d32) -,S(40ed1e6f,b9ee245,ac189a9a,7809da10,cc6daa7b,41a163ca,f761773c,6af5bea2,ffed1501,7298fb9a,78eb7bdf,1430ac04,82bae82e,a7197adb,50bcc1e1,fc217b2e) -,S(55faaaee,59a20b9a,3784d171,9ea529cc,1b7ab3a3,29f26dfa,a3b11bd6,67ba15c1,a9f8939b,52ac53e3,5ed4771d,8e47065c,d7f2805,a7e5475c,37353ddf,182f4a65) -,S(b51de64e,21cf88af,2180ca17,24956d10,a95ac607,f034fccb,a53bd02b,fa8af3fb,175d9b70,1c652ebf,46b99f1f,6e66c4a6,9b840019,a48b1ac4,878b386c,3b7f81e) -,S(5156b0dc,bcd91e82,4bb235be,9367cf40,7b8927e8,cd874171,556f997b,7b07b143,1d457c0f,a29d4c3f,e65ded19,1127016d,d40ada90,cbb0d8de,c2af4bf8,20cc91dc) -,S(3bf51d72,60b4973,161fac55,88e441a7,f1993c06,791b6bcd,e11d8e,96dd63d,7bc6b470,90a7afdb,fc63905d,df698499,73e1e4e2,af74f126,63eae8a4,f4722d49) -,S(d2971091,20088102,1154f4d3,ba6f2da1,22fa74c6,4faae05a,d76db7b0,9ad61fe5,7350ebaa,f2ccf3c8,f940cc14,151c23c2,bc33cb73,65528156,92648f6b,628e3fc8) -,S(c2ee47ca,8e17112f,a255a520,21ffd30b,6d7a3b7e,2341526c,559b60a9,c768013d,2e6e8b6b,d83b7f5b,1dc8e83b,edb3b23a,80d9ff08,2029831a,45305016,2bece448) -,S(559998d6,9ddcce0d,9e0da39e,96cc4c00,c5ef444b,561dbaaa,e475adbd,3e70b6cf,c49c2a00,95aeee5b,8deb5e8c,db4d21e4,cf0f3173,1af2fac5,25c534c2,34ffb328) -,S(4b4b02c3,e4c8badd,e45305c3,9721a98d,7c1955dd,90dcb2f9,e9d54901,6bbaf363,a0b67b7e,be8f59b3,c25d546e,3dc304d,d22a6a64,615bcfb9,25b685e3,18d43468) -,S(fbafe7fd,7836b427,51cf897c,5d42897c,7650ade8,ee1ed01f,e0d7dd2c,aac549c5,2f511943,52d07e51,7b7841f5,8eda5225,229a7e28,9a453aeb,5e70110e,12668436) -,S(ccd306f9,c65b8a0,7884e620,b73ac4e6,81b21bd0,2a4b219f,954de1b6,7076c06c,823fa47f,a7b0b50c,907056dc,73e04574,3f68a7,5a4c8566,8ab5f5b1,5657510b) -,S(bafbd838,995a691d,3b5a870a,7847452d,9124155d,d89a9980,820b8d56,18195a3b,8df4c9fa,c94829ee,fb0e7f52,1020b5b0,4f05f4d5,839c8687,4e893e7d,8ad92a3) -,S(d125cc3a,8073156e,a166af8,ff940a64,713d8f37,b86919fb,157cc380,224f458f,a030e8b6,ac4e37a7,df01054a,ea23a78e,1bb7a22e,f26052a3,a034ecbc,bc35abde) -,S(7d491f28,1b5ddaba,ef2c6433,be22e42d,f2d1bbfd,8a7e8866,8cbf278e,cb8187c2,ca18161d,70360966,ca381ea3,f760b2fe,28b040c7,ebc82af9,bea27ba6,f4dfe8ed) -,S(31ccda33,9f29123a,86c2995c,6a9f4979,6d70a595,5079b961,6015f07b,cdf8c39e,aeb27d0b,edf61fac,99528a9f,f060d1f2,376626b0,bc807a19,561c2e4f,e8b49f65) -,S(79e64c7,f45f9189,6c92073e,71b76fb1,e5ec912f,de11ba7,d7439f4a,297807ba,57d93436,b354963c,5891abe3,825d89b4,d17685bc,c9632e7e,fe85ded7,5823c921) -,S(d6232edf,fccb3868,71ef057b,60bda43f,69f422d2,debce06c,78a31f6a,8c42274e,13daefa0,b2e2e09d,36f472f2,29b5f7d1,58a18f63,ac3dc4d6,d62cc7d7,ec0ef826) -,S(21c0f298,b2d6e3a5,3738fc00,c8289458,722d78d2,48a33ea6,a7ebb667,446e368e,867553ec,17d2fd95,b895eede,15da569e,cbb3f25a,e5f334a2,b20660df,df062383) -,S(1d1a3d01,dcbf799,d551621c,54f74720,eaa2311c,3fd9b1d0,f4f2caee,4c3196c8,d5a7a115,9900f90c,879b1a30,13945d8c,5453bf1c,7e5e33d,6f8faeae,439734eb) -,S(57488680,8fa99ede,ca97d1,8582a151,62e26d5c,7753a561,4f4bb1dc,28e76735,debda859,7117ede0,dcc0ecc5,4ec1a494,b3bbee34,95db2b1e,ebaa1db9,2fc17c6f) -,S(b6dd34d3,4ce1dffa,4e1e820c,4c8bde9f,607194d3,1c1ce07c,9f6fadc8,9791715a,8bf48868,e405d533,2adc0ec9,49bc7cf,1487e554,3a043200,71786521,8a39cc9d) -,S(90f9ded5,69088772,ca2bc887,1522df9b,5821df6c,9e20b160,f3504bd,4a91d0de,d17e64a,dd534a6e,fdd0af26,b4494339,f76b3c1b,126397f9,a2beba76,eaf902ac) -,S(c55f34e8,58d19353,9106e4a0,c3002873,db07b239,9b10299d,260acc65,6b2cfa59,7d9f38d4,74b5a22e,72949f7f,e2cefb34,9a8fe1fb,c16b8dda,11f162de,30e50f5b) -,S(6ae44192,d38981c5,9b3f8452,c4a2b627,f39c16d2,b6f52575,c5f1722,56b8ecad,9bbba8dd,7c49204a,9edc4b91,e38e4973,fa61de1c,eda6ad61,603d9715,7f0b099d) -,S(33a7d639,423e1b36,6a93ad99,eab6444c,bd0c251f,6cd8b79a,e0344eef,6fdcffbc,c26112cc,6dca2a,fa52684f,c9ed22d3,2f067891,d5bac2c0,2bb86e3b,9411c61e) -,S(48471331,eac48670,28fa6642,a76ca6c5,3380c1d9,f52a4b2,ea640d47,f159af0a,b4ea8546,93fde01c,fb903a31,18bb61f5,c5047b94,705a714d,5b586d47,a0142704) -,S(565ac39,9ae731c0,4cffaab7,43d24b71,72defd79,beb8ce86,d46012a5,c2587917,deb56aa5,d45031ea,fc411fec,e09a9646,14664989,fd4f40d7,79c02981,98bbab48) -,S(964838b5,3b6c2b7d,6a8d017d,c5a32fc,99549094,6dcbf773,eaa7085c,98314c0b,2daf9f3c,ec44034f,c8a71ee0,ee76bd77,ac6fdc9e,fa042a2f,6caf9c5e,fd130b97) -,S(bc00da90,7b8d078b,9d83522d,ae548b14,6f9bff0d,2ef887c,4aae2f1e,c4eb88d5,6bd0fd11,f9e2db73,65f21dd1,34cb29f6,fef4d7f,b419abef,eafe15a4,20ddb152) -,S(1a59f855,f89f0c,f13dd8ae,9f5e550c,a2082bb3,27fb111d,75455ab,dba7bea4,7ea2fb40,d460adff,c9e25c53,a65c508,e77e6e76,e2e435c2,150c870a,7600c823) -,S(7a3b611b,d3bffc6a,d4508162,45695024,452706a3,279a6fda,d88598a5,4eccc764,16e09589,68066e52,c873d6ef,e549d3aa,83d30bd6,a1d730d3,68aa1ad2,32233145) -,S(2fed5577,9cbe0a5a,786fa95b,5c56e27a,a0a1cc28,51112bef,4cd5e1b7,15d6d91,7eeacc27,b2297fb5,63d691fa,36dc650a,f66fd3e6,6fe5e637,9959d46e,2d4bddfa) -,S(267ad217,952edf65,673efaea,6bebb44b,18326dd,f1b36d02,f0154a0d,774a9558,77593cc0,7e9d5e5e,688a7b33,bf54a01,703cc9b7,a0485e6d,907515bb,11a13fef) -,S(eb6ed62c,239b99c8,6978ccec,a5f32145,e0d341b,ca7eab10,6fa05ee1,7f6687e8,ad899e22,50f6a8e8,ce29b225,83ad8755,2a6e6ab8,9061d33b,6629fbfc,52c0a241) -,S(ca5cf17c,e03d214f,b4ef33c,41686c4f,5087a59b,f88ca7b1,891094d,430a9e5b,17e44eeb,473f75ba,cffae683,c8ea0299,e1935180,7257803e,f9963ad3,d0989ce9) -,S(4c7bc29c,acf0642e,63f035ec,a93e6b6c,c82f21cf,46623a2f,e4c7215e,51e82f7c,7c55e76e,8756796c,143f64e7,e40a402b,eb537be4,f1f5322,e59d2be2,82776875) -,S(57cab8e9,b42289f0,503e5013,acf4dd7,79783184,2389fd20,80b61bc3,671058e3,78225318,6671273d,a7b0b884,e72e9bee,2b048c45,9430d2ca,7c398aaa,9fd9e2bc) -,S(3c2bf23d,f1120c34,de813a82,a56843f5,abf3d272,ed2e6c27,53ff6310,9bc4823e,1759db63,88aed233,ce0c5b47,ec9dcb88,76740928,e12fe9d0,d08eb759,2d3f1990) -,S(c010a9ac,83e0742a,d3348dc,3dcfddd2,34170aa2,28d36856,d8581b1a,eab38d2,634c97ed,644a68f,e1f1da1f,190cf920,2b2dc810,446b78ea,9cd27684,3c76aafd) -,S(a4abd9ee,548ba468,e4cb632,b3d9c8a9,4f1b773f,ba3a9660,5504593a,92071994,3a14266a,ba263297,fc6ab00a,8403565d,c9390b48,ebffcb61,11b5e8ef,c8f87182) -,S(dc02c852,efc115f1,c5c08540,deceffe5,d68b82e5,99b78711,5a7a333d,e8dda172,e4e6593a,8e1ae842,ca7f4eae,d8cccaa2,8a35f8dc,cb8549ba,2367faf5,5f6c29c6) -,S(ee4769e8,223822ff,c28a5a4b,5f29fd7c,a54fc81,72175cac,1b6db5a2,91ec57c8,fca2c6bc,4076c8eb,a0978b9a,2b0158c4,33890514,28094619,38413fe6,c020385f) -,S(f3006c1d,34910c0f,d435a6de,cf088c38,2cf990cf,3124f2ab,b11d2727,d93ef066,7629f5,aa367f51,a29ebaf1,235cf267,f8016a6c,88dfcd9b,82d36904,c949eae2) -,S(7cfb203d,7bf5669,129f0a3e,325c3fd6,b1b9c804,4932f0f3,794b9357,1e7313b7,4f76b9fd,24339c38,c88c4217,387b016d,e4ae08fe,67182d39,82a45bb4,e82bc60f) -,S(cca3ce0,36e00993,9d30be8,e70455ad,efeabe71,83aeb206,a324d0eb,32312c0a,9674ae58,fe947c6d,34c63725,2058c88c,91b437dd,98da58b2,efd7e8d,1615b9e5) -,S(9fb64148,81cd5c27,82da071c,1f98d71,d9815fd2,2389d212,c66ace66,ab0d9c8,4c25454,1a513742,5f75e515,c04f1c73,d11d5047,9c76b09b,ce23c13e,d1813251) -,S(1dbbebf,3e3d459,10d39de2,32560b4d,eb5d2ad8,6aa1542,c2c070b6,51558b25,ec68e71c,2e94e490,4194753f,d7484ca1,940eae51,69831876,877b9ce7,2d0b9db1) -,S(7751d219,92f47421,7742856b,4c84d41,5a890ee9,24185e21,5a210a3f,a46bb5f7,2915a9c5,b770c86c,edd32749,3f698c17,6371f6a1,4cac5a22,73a3c648,1b237fef) -,S(39a849a0,5b189c3e,20782983,ecf664b1,e7b89c96,4e11d737,70797fca,ecf36a2d,d3e6f8f1,6191db06,be2274d1,56685895,48e69253,54f41114,f43b5ed1,13690c5) -,S(67e56125,b29ced20,f9f95522,d412d67c,80e3d628,b8bfddea,768117cb,e79b25bb,608dfc15,7e3c23f4,4aa0fd88,3d02d293,3c83edcf,66ea57f,9167b712,8d03da21) -,S(a51aeda,2f7d59d,d31eec20,e95839f6,ecdd01ef,529327bb,5cb229b7,b78f1525,704967df,93fb862b,3d38b18f,4c6818ab,6621c7d0,80d92cdd,1f0092c0,d7847903) -,S(c980693e,73a1cb46,f5eb71b7,73b00389,f8bcb36f,fb489e7a,aae64c23,6ac1745d,bf3b808e,fe6b7efb,771853e5,6fbba6e8,b3b21fef,706bd4,274cc058,b6fae474) -,S(c78df930,bcf54c1c,28e27aab,2975e9f3,94167bd2,948d4713,6b17a374,a1391a9,9a424f36,6d3a79be,55bb5e9a,283be1e0,163bfe22,1bc65e5e,318f0de,304d9ae7) -,S(9a75f7bc,c6d2f3a9,e6168ebc,8f7f1e50,a998b1e4,e67316e5,fb242fc4,6d284089,cb478e6,dff8b9aa,3ad06c6e,8fc7e35a,39bf6ec3,787977bf,d40f3159,bf169e01) -,S(76b2131a,db0bb3e7,db48277d,95ce73e4,7eba1e7c,b6f801c0,d20b71a3,8b6e6224,32e3cda,ef60e55b,a9e36e6,cd287737,196c5af8,120c47b2,f79d2492,9979263a) -,S(21898361,4ec5971d,f55f96c9,3da89483,cdcc4c46,deb8de68,f32a42b3,5c1384e1,2c396c50,44a4953a,b22a2d22,47769741,c5eda54a,d9c9ac97,d6486b5f,126dac3e) -,S(ac0b0a49,4e9d180d,101dbe1c,a528fecb,a08449a6,cf5d82a9,aa14f875,e3db8adc,26d1d412,25a1b583,2dd53b9c,56a6a8e8,371dd19f,31462dd9,b2aefe3e,70412554) -,S(f869b58c,851a65f,bd6d3329,75f596a2,9d1a78cd,bbf04a1b,6dca6c27,30e04625,40dee344,fc6f5c72,c18b1603,e149949c,a0cfb31b,b8b91b09,c3cbabb0,c6a5bff0) -,S(f74f02db,2406250f,8984a5f2,273c63ed,a640a43a,8e7d72aa,ecf78d6e,b9544c3a,882e3a6d,cacc1e92,8a3c1a61,85f2bcf1,5e364f7a,1eeeaaea,1c0af593,cf86185b) -,S(c0613eb6,1d6755eb,2ebc9284,a0aa69d2,88c39050,4b7e869f,f3d943aa,67ea65d,72f61ae5,27b5c82e,4afa8966,55d9289d,29931c1b,f0d36c09,fe4213c5,27848cba) -,S(eb66ff98,60ba08a6,3c0fd8c4,7117aeb0,ae0dbf63,524307a7,eb739f08,f31285db,c3142ca,54bcf2ae,8b05dfb9,4e40f4ba,7d3662f3,774e616,55c7515a,87ddc5d5) -,S(3a7108e6,a1256061,fc25d58b,ca534602,e41c6b15,156c15b8,71a516f0,ec4a861d,daae2d02,41cabb2,191b5be,c17e7e88,957bfcd7,66df1226,a183064e,3c4393a6) -,S(d17e3a58,c83169d1,33ee7371,7b205f2c,ea1a2ff3,4e744958,949e9403,b8f89d5f,98c35f7d,69e5d98b,920ffafa,6d15d349,2d75fcb9,81ca5022,5ac7ff32,618b1a20) -,S(d6e32892,cefbb8ed,14350cbf,2618e2fe,98caf6d4,f7679385,fff36bab,bf6541c,7175462e,be0f5ec0,7872b55,356f2498,976196bc,edbe021e,8081ebd,b2636298) -,S(318d49ff,60e900ae,6e8e2182,f38ec006,82ddc8ae,93aa6291,86d5ddf8,affef75,6e97ec27,dd7d614d,c1ed4fd8,fdf6aa70,8dcc3eb,be288831,a9888166,66333b2) -,S(fd6f9e30,1772db8b,a68ea5ae,b585abbd,c075e72b,68d6f67c,5a2f8144,98cf6346,dadd16e7,64775bd5,ca5c5f51,35843556,d7608230,aaff4125,4d4eab38,1d28d2c0) -,S(8fe25b38,a2c74761,a90ed08d,4bce768c,f074282a,e9560d31,566ae43a,182ddd36,6ee1e84a,77c6ab78,a2cda1b3,2fbdfe2e,51d66843,271d15c7,3f8e1a82,1e4c23a2) -,S(37cf0ed2,88ed8fef,4ae17bcf,f6bfb815,3e12bab2,a46d7e5d,2e6feb99,9793bef8,92e7a57,18eb0751,c99254f4,ddb5c278,e17a417b,21793339,119a146d,bbe3e0d3) -,S(688c2061,6b9d0c8,76deb812,b60000e8,eca0e04f,531ed1e0,9158442,7bf403c,bab4b2ba,41ba4d53,df512e76,32200bdc,11d8583,f2ceb5bd,a8b7eb14,5ccc01fe) -,S(4b4caaaa,f5399535,d822371d,63965216,d1b53584,d89a84e9,d868395a,70b3d804,3ddd27af,cd18049a,3b01d043,7761e4ea,652fbd91,115c470a,e4c7bd40,51ee73d2) -,S(6f5acbc4,4135da60,758ed9a5,18b39b5f,47cca398,24e20e56,1444dd52,e2fa1d2e,5dc9d46,e5f6d94d,48af2efc,2f197a2,f729f1d7,335fa569,524d37c,4acd58c4) -,S(79d2d449,3dffcb91,6fda527b,f8b6b622,661d6f23,738288c6,ce94313d,c267fc42,b2683bf1,3fa8f7fc,be302823,dfbc9153,8d902791,d5d6dde1,d2805f37,a0c08db) -,S(33a8e87e,246b7b9c,9c77a6b0,7cc67d41,f3915dbc,2180118,c0800b33,f9f95524,baa8244c,584fd05f,2655e36b,e2e5c459,207d30ef,dcdb2294,70b34333,9d16ff8f) -,S(9a169132,f3887df8,20561a7a,e4bd5461,3235ddb2,fba7a19,3f4daaba,79868e95,686fc317,995446c4,42945216,1a96595a,a233b100,e5f8bbc0,71990229,44630bcd) -,S(790b74f4,8405ce3f,9abdc7e9,439f2f5,c859989e,2ca5e6fc,29046104,8783ac42,8961c913,562385ca,990593a3,77111a5d,1dc6762b,b1a928a6,6ebb304b,8a24a701) -,S(e2a3d0cf,ae1fc2d9,87caaeb6,9f32fcd6,95471785,f524e438,b5487aa3,72f9e49c,9cc24205,ecf2708c,357edb54,308ce452,11f7dc03,98fb48db,4982d337,14c93046) -,S(cb30c43,5992c195,76d372b1,96f2ae68,cfd2653e,63e3ba7a,2b3c21ec,960bcbea,f65735b9,708338c9,acc9cba1,4b491b8a,fb683058,266a483d,4987cdd3,89ccd0b4) -,S(1faedc95,d6310bee,6298ffb1,6fb3e6a3,296ca66b,7c995d2d,fe924381,10e8b46a,35039e3f,8201e904,e5378d03,2bd8b766,26d9f0ce,4425d2ce,e7bbd24f,b8725089) -,S(a646cf5a,2be8c1d1,3f05410c,ed51b3f5,8e93ea53,1e28bf31,8f6c750b,52b3e8f9,58c58ecb,7727a920,b47a7e78,e1e51d11,e427d7e4,465429bd,a01f4650,a4c102bb) -,S(32734727,18537d38,e9b8c397,a5cc322d,1c77c0c6,15eded39,dcebc020,debe2205,c2debc89,58c3f60b,d4c7b072,d475a7d5,c1ea784b,c3e532bb,72c02490,9a42d65) -,S(16a1a718,855a212,c068c095,d930a270,9906dd22,e7db3f4d,4ce2f393,d572827e,d389d64b,b30ba9eb,6ce80335,cbe8f7dd,b1ef3016,a8b74660,2196b724,d115605c) -,S(b4bf4d14,5de25571,33694b86,76166e90,eeb1ebf8,4a7402e9,a61af4cf,23687596,49db20a4,d82397e5,6318640a,6b605e96,37d38961,a58ae3db,fac2fc11,bbd11242) -,S(d4ed67a9,ccf4665e,418a0de0,8d9380cb,fc311413,e90a964b,bf367b9b,b892630,8ff7e57c,e79a0883,1fe8a972,92493764,7472b77,61b055fa,37105d18,b51df131) -,S(8ad256f1,9f413ef2,eae906f,c1c2ca4,44d5dfdc,f916d366,b32f1f47,f54fe70d,bdeeeb41,8d2c4dc5,82547f65,91c97219,34778f5e,d25eff4,94e243ed,a6d34da7) -,S(8dd3e2fa,fe55b5f1,f13723e0,1a5587b9,c67d22ee,21f1f62f,7f62a15,31f17f8e,aa23d2a4,7d6b717e,55d7c6b6,5d9c46c6,8f2db41c,ba66960b,4b4bf93f,5fc88cb0) -,S(44fd9e28,2a8e30af,ac34db01,a7b0e939,3c13917,554d9a67,8e577a5d,4b3d0f6,cb079061,353319b3,a1669d59,295bdbe2,18927d06,ccb1290e,4840cc16,911a61d0) -,S(5d249a02,4464ed65,831d2aa9,c9645f46,2db7c9f4,e5a46477,746b1a71,88b7aa42,2bff7386,527d6b5c,2c595f80,e08b4d20,23bb8dfb,f294da12,b54f8b14,77281d0) -,S(d98eb458,1edcd51d,465e123c,d891c481,ddd18b54,b9408ca,85ac47c8,e10fb23,15bfd3be,d3756ac6,f2f1f9e6,f254c9b,2b153717,1b265081,6a2cc21b,78b4dcf2) -,S(2f12c369,19a2aeb6,2132134d,2e85150f,6edb486e,9d672eb5,876804d6,44db6082,c0111edd,3b4d28c4,edd264b8,dc2bd0e3,20834dc7,bda82dd0,827133c5,7f8cf73b) -,S(4d949684,7099c9f8,421d35df,ebce57aa,71326034,8f07e3e6,f03017c3,144b4624,9afb5a57,d71369c7,28db308f,b8b07da0,b91f954d,b182eadb,126b1fff,ddb673da) -,S(cf1db910,5e95f1c8,e360b39a,752ab17e,fca8f24,d9ddc8b2,a9768700,e2af2466,e7c99f66,c49c8674,a6c1b94b,4b964019,5e645ca7,b3d2e004,ad8dc73,f647ca5f) -,S(e71eb425,7d2ffa8a,b79d63a2,42c67585,d4b1747f,5b27f22,a9ee4284,6aa62b85,a906aeec,f901a376,7d721f45,da53e342,3bc0a779,870e33c3,d10f6426,6a2c8865) -,S(bcd987d3,b2575f4,3bc5c3e1,b4a299bf,21c58b6c,a27ebb21,8f9882ab,30559887,403804c9,4339ae27,2bafd894,e63a4eb4,690c1b4c,9289db00,761e9b3a,1d483f65) -,S(b74d5cf7,48af7162,395d2d5e,8a69f740,7a2bebba,69564042,ea9c7e34,b1f8cab0,b5c5fddb,332bfb59,835e9a23,4afa4543,5728dfaa,7dcfca3e,a3c57deb,e849b336) -,S(46f3def5,9835c9ae,1a7b3b13,a920bea9,e9bc12ee,633b3edc,57251b72,3560837d,587b2e1f,2e8eb9cb,37aa6977,870214ec,818fb71c,1035eeca,91d53e68,150ce67b) -,S(8d3418fd,eb3f0968,de51f4d7,cbb60299,a50ceba4,1915d8b6,5774cfb7,7667d572,cee79910,16a28462,aa9da7c0,f67b4c7,e8b3dd38,f4b2203,9d05115a,ac661db8) -,S(98cb0f09,4510695d,78a0a672,eb67253a,30f4327b,7864fbcf,529cf212,ad6f7c10,25952dac,4e1b5035,9b47e9b5,52852d1f,300fde75,a6bd532f,9fd56af,2a0ab333) -,S(96045e4c,ca075fc,4a5383f3,f03de105,a34c7c4c,b030ceff,b58b98e1,2b39a3cf,f527b8fd,92234151,ba11f24f,7bd5dfed,6ebd03e3,a5048c6e,8f2d5231,7201bafe) -,S(f262e891,42addef8,cba26a9c,ad779761,c3f4b3e5,5990a93e,703bf56a,99cc6030,275cc764,86c86a90,f597dd6,7092ecff,5382c7b7,33939ca1,d1f3218d,6f0b594b) -,S(cd79c02,ee175336,5f9f7900,be51bb2b,ad75ef81,3c6c5634,7cc717db,156d17fe,b5ebe8ff,b30de5bd,a5326044,16abbae1,4ff9198e,b491794a,c4500031,947a985d) -,S(28b4bf22,5b1d40dd,e0122e03,e630830a,d9ba4629,cc51c9d2,80a225f9,48f858f4,24756189,98bb414d,4a534c6b,e300297b,aadf4ffc,b10e6795,4ea36e25,2cf3cac0) -,S(f018f206,7dd55df3,9c53344b,c6128a5f,cc765c36,c7b0bea0,16c8465c,c6ed2ff7,d9fc5ab2,cd619d4a,c66c1cd2,251504cc,cda34a76,86c5661a,960a00f8,e4aa7e66) -,S(496968cf,8086d02,9a5dd5c7,4f47cbda,7f661ef1,488b3942,18ed886c,424a7a13,d7d8df98,442060e0,f17a363,579c6600,360b5124,2774e2df,c8d4b787,1e1874e7) -,S(242d4c59,e9113b77,68e48574,93600da7,b984355c,a1d07949,8921016b,22efedab,470dcfd7,b0c8c2ed,63a28074,a505573b,42f50920,6b0ae577,27a8b796,7a0f42b1) -,S(b6b804cc,1a1a59d3,84c4afac,c5e5050f,466280bc,d5ab1586,1d20f4dd,1385e8c7,2f789346,2a636a9,9ba2a1d2,32829f41,39b57967,bb26d0c,898798bb,6521d439) -,S(dc30a3d0,7ecc5fdd,38b8048a,f281024b,46904b2d,2a4c51ca,d1b49b7,1d918a4e,326409b0,70550e97,58f53698,7936a54a,b701f7b6,78a7d10f,ebb511a6,c18cc917) -,S(e1fe434d,345bf330,83abb628,f4f44ac,5fb22934,977813c2,c015f2b,43d3fab8,1b251ca5,2af897ac,4c08df48,ce3d1607,d3b31b2c,2dcd7f7a,59a95b07,774c4d83) -,S(a8ed88da,e08ac5e2,afbe4a40,ee775645,82c2f513,cfd72060,bd1fd5d1,76fb8d08,f4fb60b0,74419630,fbaf5b53,717b2a6f,5cc2d98f,1d29481b,77b1f9f3,84175729) -,S(b52cf828,de1e9cd7,c95c083e,ec50d228,8e770713,a0e2543f,76fa5790,2c7c6481,635a3953,46fbbf,903dc729,d3e3b52b,43eebdc5,3748ed83,3c95eaf7,1b75790f) -,S(702079ae,f76d9bfd,ccb957a9,4aad93fc,b1297c54,d634978e,4dc78292,161d5e83,4983c08b,f2d81c52,d3b3a202,e0c6ddb9,32a43a45,c4b95f82,c8c10642,5a783b52) -,S(4638d4d1,8e9de1ce,ef4fe8cb,db4378e2,3ed3dcb9,513cc9a0,dd73ee2e,be57bbf5,561ee032,45cc3066,968853f7,51fa36be,cb50740,a5951e87,cf77ef20,cb27e110) -,S(eeb34eb7,5facadde,d561dc5e,e3d0a039,d98e4880,910439cb,ecfb22d9,3b386bfc,f2b23cff,5ebdc8c,558db8c,1c311a94,e9d8f63a,d1cf4af4,c21c2349,a6e57c4c) -,S(7f2c6e5,becf3213,c1d07df0,cfbe8e39,f70a8c64,3df7575e,5c56859e,c52c45ca,950499c0,19719dae,fda0424,8d851e52,cf9d66ee,b211d89a,77be40de,22b6c89d) -,S(6ec76722,1ec5d27c,f7e11064,d4f8b016,3cea090f,6a950f81,85623303,23e53647,9b03c757,9704e839,c8eec7d0,f063c4fd,d0aa7ba0,5ad75254,984b1703,ae69a3d6) -,S(98f6f69d,320d5eca,1f184b0,378f67cd,b44a707a,c5b2af54,99e9f8a4,524dea7e,26ef6b3d,7b037663,979333fe,56bc33a,ca54a3dd,78c9244d,79ef5426,f2b69a02) -,S(cf1ef445,58b82c76,5d77ac99,8c0170c9,2d308668,2d9ed7af,2961cf05,5b47e390,8bcc1d05,fb880ec7,8762d8f3,f5afefe8,f4345bd8,36397d23,befdf446,498511c3) -,S(10e01651,efa26f2e,f88cc5c1,594f378,9ab62b82,5a0875aa,37c280a1,8c6f07e8,2e6a15e1,1f776335,30fb2cdb,788aaa98,83105da3,7e28c0a,8fad503e,b9779df2) -,S(b94e2fe0,41ce209b,6efd77d7,44983130,af90945,120b9a58,5427966,e93eee4a,8f7abf1,103e92f5,5dcb1dde,746df10d,a86bfb8d,2776a0f0,1d07142d,c9bca443) -,S(cf9e7d02,c671a9ea,145d233e,244d8af6,6d71cc34,e17f2ccc,1225d2b3,16d41154,82eeb8a1,f0b966f,bbc3858a,3878f969,a853e2bb,e1b60c4e,e13eff85,d2d2ca7) -,S(da3a3c29,94ad3b91,319d18eb,dcf4b934,df8e4f2b,e052f436,6d539aff,4bd48bb2,28f9d653,c4042478,831ccfe7,bec86663,5e0d32ed,f6db4f54,25669a91,d1dc0193) -,S(ab812818,2b80378b,d914c9fc,d2831f30,a0a095c9,d0e52450,d4ba27b0,f1eec101,5abc582,274876d6,3dce366a,fbb1d80a,2286dc2a,dc0c078f,1424d45e,26666b3) -,S(ea5b82a2,bf02caa5,d5d64391,c0965c53,f0edd967,f8df94ab,831408f7,e5c4977a,81fe8299,f320837,acddd504,7b888e6,2518d53e,897dacac,5d28bce8,ff3d9339) -,S(50605c0b,ab201d7d,3dd618b,e3da2d29,318aeac1,7df58d2c,a95b8fbc,fbe70fa2,e50b1e,7b5693,c4ecc160,d928cd6e,d4c978fc,6c2a68af,c03f397d,72a60383) -,S(f76c50b6,6d7dcace,f45409d8,854f79b6,51356661,108b7168,31b58b25,ea1191dd,7d055b74,b0195140,bc0e2e93,a97f07b3,a3040148,7720df86,d3bd1810,6df3cc72) -,S(de5053ba,d716047c,cc2367db,272e4e11,41312690,2bd79b32,f6d3d959,93260e7d,1c54a2d3,9c34b0db,deb61b5,b5f46033,b1e4c581,5113bf3,d3f38de1,c97cc7e2) -,S(ad3e719f,180e946b,1b98a332,bde18e54,437f1a24,949d712,1aff7c8d,fa06499d,b458d7f1,390fa4d7,d2473863,abedc063,ef310adf,7ca2f2c8,82bcad3e,2f1b554) -,S(270a0234,5560af6b,6310c867,332f8b79,839a3ae7,6e2666ec,b46c840c,c36bae4b,8daab84b,92157d16,ca0f160,99877a1,ef7ef072,1bdb5bc6,89d16a19,4ebedeaf) -,S(eb5ed17e,3027c9c4,c87ffdb2,94a84ff7,25ba2b5b,2bf72d30,f98334ee,68624621,39fffcb3,8f74d471,9be8d1a2,14c61ad3,df4a91bf,d599c3ae,3b54b4ec,860a942) -,S(b9c11df2,8a0b98cc,623f4e80,75acd469,fb1f6621,a7572d6a,7bac135c,2ce0a5dd,5bfa8a78,d42b95ef,327eb0c3,692b3ba9,5eb506a2,4e2fca1e,391ec545,40a76278) -,S(eed17043,80abe259,fe661106,6eda0408,f60f1399,3c49a21c,a8a6310c,ebe74b5c,6dcb6276,cbe37b91,162a243f,57afcd9a,8cc2c661,652c324a,567d5db7,22a0d750) -,S(8e4b0f6f,5f5b9cf4,68e5524a,4adf62b6,8c68e310,5ee374c2,5265000c,53aa97a7,d1f880ae,c18d0191,b74578c1,6d0418f6,c7e59f2d,157c0d56,e25137ec,c1b7f74a) -,S(77ae21bd,fc6596b9,ae85ce9c,93112b1d,a7f393da,1238d76e,90cf59c8,caa5ebbe,f4484581,1e3266cd,f4625390,e729154f,51694717,3206ef9b,9106c547,ff4a21d1) -,S(1d379ca8,71c02ef4,59a8bd35,f5066265,92922533,f0503999,e16d6b07,dbd2346f,c0550b9a,72899a7b,42197cfe,d195c704,a6333d5e,178d91c1,d50b772,4140cad0) -,S(625017f3,28fc16ae,99367199,5f02772a,5c7ea721,7d47c296,cbad670c,3fef1ccc,1b44e253,af3b214f,edbeb4ac,50110df6,d7056d06,617c2bf3,6189a74d,64450603) -,S(c7a4fe49,6bdc3509,3ae3f508,d43877e8,d1019d16,740a5eb7,8eaa72b8,638412d,1b5b12a8,95fb7130,e8792406,74b8f735,6730938b,675996fb,a30a9744,960febef) -,S(cff9f83c,e8f9c4ef,3e80102c,bc48c409,b65c6166,b74f052f,a5628348,b2441d3f,4cc418f8,2180207e,fc846a41,ed6973f2,814ceb07,a8bd252e,338e32cd,e352ee6f) -,S(84027710,45b8c295,c938ae98,a9ea11dc,2fd23ae5,7ade6ef8,2c604721,66700541,72946592,d3c11404,881b972c,eba81d4f,f3f80dcd,40b15da5,f56e0723,841e4f99) -,S(f7ab1330,e00cb9ec,61a346b,d8f5522d,5e304a4e,a94f84af,b5c70614,d2e0d2c,5d4ac851,89350a54,af58def4,6f3f3d69,2ef0f6a3,9dd4ef86,6bb1101b,df5e6144) -,S(a7c84e19,2303b778,8c1a4d5b,786c9829,d0da4ddc,c13f692c,7851884c,6fd4e618,56e32e5b,8fc2db2f,21d64bad,35e3f115,65928533,a829d744,939ba456,bb1774fe) -,S(b8b0c884,a680dac0,363bc55a,fa677a72,c65f4139,7f5cdcc,f199d80d,ac98c43a,43e4188a,c92606c1,cd6bec5b,a4edb045,6569f87a,625db932,d0f8e71e,516b8127) -,S(816ec443,d0576135,5a3bc33c,1db4a179,c5bef98e,943af8dd,ac250482,a65e0df6,89a7b2c9,e9f3588d,990f6fa1,96e366b6,54f9a30,1218a2a9,c9b87c48,55f0b360) -,S(8ded2103,823d07d5,33fba24f,7fccc47c,b101960f,3b717fd2,af39d49a,a91e28a0,3f03ed1f,be1a661e,f43ef9f7,d753eaad,e3e1a391,2a682ad4,fb19526c,c0011728) -,S(b1c4b39c,e874d478,bfbdf9e3,ce8c3165,ff4f7c4,bee20c87,4849aeaa,d0d6260b,38af8b61,30701881,fbbfe724,5396adc9,32c25b84,dfbc4dbd,a54bd236,c04b4fde) -,S(7d5bce3b,e5953eb3,a17f657c,fabc8209,f011bcf2,7e10b90d,e75dad9,fab2c971,7380d686,5f5fd782,b0708b3b,62c39e49,864b2ba7,4066167c,bbcede2a,b0f84787) -,S(2af5111a,422af2cd,14e7717f,bc7171c4,96af178,8b229497,a54d2b87,4c00f285,4468bf1b,ee43f100,7e800b68,b7b3b243,2f3445c5,c8aca59f,7534beae,bb771f41) -,S(b46e29c0,6dc8ddef,f8bdfb65,f4043b61,fe010dae,a2d0955d,c81a7b49,637af766,62777495,ae16314f,d7d0cef8,24a27a9f,748c5c9b,9c51645,9c1ec9dd,9d7b59f5) -,S(105786d3,f44ea40f,71eb3bd5,339cd514,aef6d8fa,5923b4a5,89b219c,fba6b1ea,2a4ea7da,c87522cb,7d92c450,8e86d0b9,39fad024,9fc2cf15,1ba005cd,b743d0bc) -,S(1f3c0c81,be856e30,18934573,892ceb22,d2d2d8ef,f08b7857,5c624f48,16adb23f,7321690,de24499c,f52f4840,89c4d7b4,11158d52,d32731c9,faaea567,8bf6072b) -,S(16dcbae3,a95a95fa,912484f,f833ba0e,e437876b,f16f9c9f,5abf46aa,468bd2b3,56727c07,247b12d6,c1ade473,3c691700,30e5582a,cde14034,3449f241,59ffa44d) -,S(114be56c,d6723c8f,924ff3c0,f5edabc6,e42314a6,49edbfff,1c794438,dae70726,984dd72,855cdeae,7c580046,b32cfa7a,45b61b75,944735e1,d5fd9065,268ac521) -,S(8d0cb2e6,1f98472,e169dbac,7f5babff,51766b3a,8d74e17d,747b7eac,d903fdaf,d1593bf5,b9e793f7,25cea368,2ceabb11,f06b36ab,899e160a,f1f736a,80bc9b92) -,S(5b420754,188c82e4,db72f3a2,c8049691,34e3b43e,484b45ca,ab4727f5,31714db3,4a89307d,27d7f360,7acd1643,719be148,1c7eed5c,77598883,8bf6cc13,a4723d9f) -,S(91e3761d,95761d96,8d856a72,800fe0b5,9f01c62e,1cc446ed,18c1b58f,88cbf74b,b5ab61e3,96f88376,28f3389e,9999ef55,b73a58c0,d33debc7,25812530,2b96c772) -,S(31380b83,dc77e5f2,9c2f5548,abe052a,16e0f1f,2d8aad3,5b05d29c,5c1a4655,23ccafae,cc84ea72,3c434342,b839cd0a,b42173bc,1aa1db20,1073fe26,6593403d) -,S(ae40198c,bcd54264,904b44c7,c9019553,8f3f3727,a0c9639a,764cda80,b21edd27,3a57f08,ffecccfc,cd9a0e7c,827d98a2,ffceea9a,6c39d200,5cfae623,34eeba8f) -,S(f4729787,abeac0f1,249b1d3a,c19bb025,5764a854,727b415f,73e24c88,a8a981c8,e31161a5,68d81328,c7f9783f,de146d07,b51aae15,bfe719d,ab4e9e,ae65d172) -,S(f92f02b8,34148934,f7059b61,7e84d0a6,f52d3b8c,a7d7b69,ce4c8175,7ed5884a,faed7ef8,82733020,888eb530,5c6dea4b,cacd208f,fbb66b7,6f3cf41,a8864080) -,S(a2bed8aa,e93bd682,be8cc4d,d1f84fc2,9efe4022,b2b0dec4,9ed3ce17,7cc93363,287ab9c9,62126fb7,e0340f29,9edeb89e,7bf235b3,b3f08213,d630c9df,198ada1d) -,S(5a42cfcd,3d1811d1,99b09dc8,9308134,cf6219e2,e029598e,899418f9,b7af4724,95ce721c,39929d76,b0ea83b1,80bf25c2,e301413d,60fb8717,2e0ee8f0,593f8423) -,S(1d27ab05,67e8bf19,323f1eca,44175085,2e768a6b,a1436789,40ba2b94,5b0e530f,18439939,496d29a1,58a532be,76b04932,a23e3ddd,d51a1b07,c6c33e6a,11e1afa8) -,S(592bf859,22c05bf4,4b42fcf6,e4cdf3fd,bbbf8088,b7263d31,9bc74914,6eab4326,84cbd8c3,8dccf0ef,de3946f3,ba2eac25,3aaab976,8f7f601e,7d95bc74,4c7f65) -,S(66730a70,5ae3dab8,bfc01f4a,deeadc41,d4df156,d03c4fcf,1dd9e16f,9359d5,c04c7cc4,4ea1d8b2,273b9170,19b9efb3,6e8f422c,4863f718,582f57a0,778273ee) -,S(3d002600,532420ac,9fb246d,84e48560,1ce6897b,979491ae,7c5914e,dbb7fe83,5bd73264,2f16d4e7,7bcc4855,72494523,c221fa1d,321c552a,53241dd7,94c7d98e) -,S(d42ae36,2b5dd22f,d2089d37,d22e2c2a,750395ad,710aa1c0,61ed4275,43a24487,84439e00,1571e1ea,53bcc24b,a11b6f7c,ded0a649,b2a12fc9,c2a618fe,cb39ada7) -,S(37c761ca,486fabfd,b306d,c18e9074,409e101e,5bdd1670,edef1253,aa253743,e53840e3,1110db1,89ec241a,e7b2cb89,29669da9,5c07f3d0,6277f667,b90cad12) -,S(4e672ef8,bbafbc8e,eb819f37,15ac0d6c,2afa9781,a197345b,2889ed0a,f3b0e788,9c10f0db,bb16d807,4680133f,e62e0eab,130cb0b9,51937852,4afcf4c,38814061) -,S(c1f2943b,23c07929,e9c635ae,66f62949,8e1df12,f35aba68,ed8791d6,8fd51fec,3376b6c8,93ad5ec5,991f7ef9,6a6b1105,2f2262c6,680045fd,fc4d4bfe,ea64ae75) -,S(3df2461e,739cd984,72cf10cd,f663e651,351e826d,7afdcffc,e17602ae,c0370be6,5e48fcb3,3ed9c0ec,3594eeb0,81adaaa,bd5ec5a5,7eeaf01f,c9f00d02,c692cb06) -,S(d4d3d528,f98b92d5,f4c4ecfb,ab60fd85,50f12327,5b63b3fd,5518c1f3,d62a82b7,64496d50,85435de6,991a838e,d984bc09,2554053b,54b05a2e,490d2ce,da7d5b76) -,S(ecd8399b,4aa3368f,1a7a4113,63ff03a7,ad644847,e225108,b3ee7d02,1209236b,2e1209fb,a7921c29,e351e61,73c02cb5,c629d88f,4ca51af,30f37123,75355213) -,S(d5990be5,7e6a0da9,333354a,fb344d59,416d1a70,785cdae3,8c332e09,cdf78722,b2a2cd8b,73f76f3d,1079198d,34441008,278f73c8,93979ece,eefc5911,7ba17814) -,S(7598ab65,1d8ced00,af3d5978,661d801e,b57e9089,287bd74f,85ef042a,90374b1b,589fc426,9466b1ff,b9c0cbd4,b022e9ee,7edaae87,8f4cc240,b60db60d,6c28f04f) -,S(fd071417,b12d2d31,852048b7,61c5301b,be088cfd,98ebce7d,7e0922cf,41f694e7,2d9c53f1,ee63b93,2adf679d,96b548d8,d47d8f74,58ef8b45,9664da23,be32c363) -,S(5a5b4990,e290868a,d1d571ac,8e9347f2,b1e513bf,cbc2b8d1,5e56ce01,2b72ca0e,c76852f5,7159524,541569f6,3c4c9c7d,424285e7,e83145d5,e5161998,efebf968) -,S(93deec24,3cd4f146,42f5a415,f6ea6f36,25c90081,5f3d20f5,9728c056,fde7f2bd,88f919be,b9993a16,61f78145,f54149f4,6abfa859,1907736d,d5e85f25,bf2dc7cb) -,S(9224d17b,a65ad967,969104c9,3068d439,9c9bec7e,7613a602,f5c9917e,46df82b6,346c98e3,2bc2a4e8,c7689e54,eeb1064c,1b5691fb,cf5a4710,55cefbcf,18a32f65) -,S(851acc91,24ddff9c,14cf054b,87347a71,cfc91637,6e559189,f055143,3b79c38e,d959bdf0,58d21cc3,430527e8,cc49dc56,2dd20bf1,30f0e13a,55cc69cc,1e116f35) -,S(ff6c1303,b7c111c5,87e01ef,44829510,eff0a612,931f9212,2b71075f,2cea4d96,24f09bbf,7bcf50aa,ca239be,b925505e,7e99d0ff,5a959574,5370eea1,7b4841f6) -,S(f23bd9f0,55e7bd1d,433fb51e,c8b6ecb6,fd5014f,4f4ca9d0,6a4bc636,435fdac0,9652b458,9d269ad9,68ee7012,aee47447,25ba917d,f120bda6,9d2194ee,a56d7b60) -,S(9d622c56,ea6d5d19,7b823e60,1bbd4af0,1fe070f9,391bb564,2a05527a,49f46ff7,8061bb94,d6485fe,d9fbd557,66db3dca,c648c7c4,2e025494,e6c3a91c,fd5c609e) -,S(9494efe4,cff5d5e7,6394b67c,407b9961,2915afde,56933b80,370d0adf,2f020c13,ab0c7e38,c85ee1cc,27964b2,de42372f,fd86ecb8,fd3f0a81,84f5af38,58a7e4ea) -,S(a8e4d7ba,ffbc52fc,a8cb6c,2938a01c,e028c259,97403268,dbe1600a,952e1a86,8d5b83d,dc3022c,4f79723,c6f16722,cc7eeeb9,c964496f,c9f67c29,351a0bed) -,S(83841f64,938e460f,eff191ad,4d72d7a5,203c01af,1519cdf1,f17c3bb5,e4927ac5,f5868f2,c2e87249,21373397,40415c4a,ecb1f30d,b204fe41,80e01d79,eb536800) -,S(ee8974d9,5ef03f8a,860dcba6,7b597fb2,af2a2df6,950aeacb,d623c883,20612f6,5cf10d74,3085dd7,cc695145,3f9f763d,6596abfa,eb7cf216,34ee07f8,a4f141ac) -,S(68e88d8c,23616ca3,b136e5fa,3427628d,a92dde6b,2691d857,b2d01a60,b6579606,5a9090,3766d6eb,c58c5d60,9b6a5675,e5ec7b73,86a17c41,2574d179,a0fd5450) -,S(fe34dd8a,c62ec8b6,20dbea79,44ccca40,cfe6ab5a,ce3b2e7c,50ac589a,9522345b,88cf0055,adf1e122,535611d7,bd3e00a7,30c9edd5,898d25bf,f0abb9bf,6bd6c8c0) -,S(423a7a9c,c0f81489,aaa62479,c1317368,9989366,fd18bff7,f6a5f235,8251bc1f,c926b3dd,519241d,2e776ea,16112e41,259ce896,472ce71f,de4261bd,29c678ee) -,S(7fa60bf9,7cbf54ff,e61bb840,b2e08d91,ffb0eb4,727c0e73,ed4f157,ad0b98f4,d5b1aadf,84d387b8,fddc7b26,a7f736a6,7e296fed,7978e81f,6e7b3b09,e94d733) -,S(9e53cb0e,f1eddebc,77edf8a6,6917f915,8294815d,eef898c,f1e77433,60153a66,5358daf2,60fea2a1,b9a4c6f1,b8bebe09,4983499c,fe5577a2,ed8f817f,46b41ccf) -,S(adf93641,c616c677,99b44ad5,354332c0,1404718e,8ec91e96,31e69552,3ad6f119,da3c66af,e4cfb3df,f55f6761,5c6ac42a,8dc17241,5ad38619,dfe2a13b,7e42ff9e) -,S(701e3ec,485db367,b0687ddb,2be15f4b,5b6242c4,396f6f0c,9726ecb6,474e4ca8,1098fa76,13dce1c5,29f7fea,30740377,691aa3cf,3d13cf94,6f2d8191,2d3b9e83) -,S(d8fc5ba5,d3ecaa05,9e9a7e04,2c52500a,d513645e,6149e84,aac0d910,f8ccfefc,72724b4d,eec94da,7494b4d9,83a2df06,df96ee83,e578d920,c2597089,7b4b3d8a) -,S(7bc88f9a,8279ffb7,658a186,faaa5f0c,c900cb9d,4a33b8dc,c9eea83e,ff71398e,cdcd21df,e5ed8151,1a2d8c77,e08b76f7,4939d39f,1f5581b0,aa956066,fa14a7c) -,S(8578d531,bc79e1f,6e219bc7,7f2172a3,e5fb92a5,efbf9919,f46ea11,6f5ef0e5,fcd1b2ac,39c262c6,94eef5e0,52338f9c,cac2d04d,ed17c290,768759cd,13b7d550) -,S(98bc22d7,3ea2661b,545eb5f4,37e1cc0a,d4124020,44bb9093,5cdde758,a8020a62,143c7dde,d33ba5b,c2ac8d83,cc462f94,2607bff2,a1aa32d9,f32e14c2,82232226) -,S(7fcf821e,95d2176d,d088106c,a5bf0855,9980f265,ea3c401a,aca44b0a,d5e8ee10,27c341ae,87e7afee,f8af4598,e8e27cab,c127b054,1b389cfb,266ec9d2,fe400284) -,S(898a39b9,d440ef05,f87e195b,6a334f93,67acd67a,1fc76ca8,316292ea,216a5f1,eb642fbb,fe3274e5,2fd1cae9,744fabfa,c0db80e6,2bd4f7c3,fc2ca43b,18ce52ef) -,S(3ee974a2,8918c216,a962480,1f18bf9a,87d6a627,83323e3c,bf138bf4,3f2192a4,f5b386df,ac71eb35,499d5b2a,960fd20e,fde39fc,10dd5c63,dc50b55b,cd660d9c) -,S(bdd10d2f,de76df34,9ab753ee,d06c1251,9766bbf4,2fb610a5,7ddc3f36,4047c14a,504532ed,34f97eb9,b8b27664,ab440032,2b8b47f6,9c403bbd,6bc74330,16923dec) -,S(2c179437,39784124,4ff9a4a0,eb9ff292,477a5148,c4176b23,c000a1ce,3bedd63d,a367b584,4f9b7b2b,a82fccca,b9a12a8c,2c1ca5f7,3e630173,e37e600f,f2fcfb6) -,S(282ef30e,f2d61d13,6f71e6df,6ee97ebd,a83036a3,2d3cd841,36289798,b3e71580,90b0cd33,c350ea2e,54c25264,7a3fc91f,5b4f9dc3,1f58e86f,c47825dc,e3d0f43a) -,S(a42b4d55,42acfa7c,b54ab3d5,ee0bebd,85bf6ea,db138ef7,1ea38c73,899eff23,17e38880,f10b9927,764c4997,326b0b9f,63d0e03a,fd2f0bd,b1ff3cca,1f566bb7) -,S(b23acc64,c5b00c8f,4b580d47,49589559,a06fcea5,75f3d38b,1a02251e,ff7ef00e,66bb180a,7eaa64d8,4bfe6a17,d457f5e7,73964ac,ff908729,3bc540aa,1cb6464f) -,S(942dce6,96aeb063,4681ce7a,407516e9,89df029c,ecc77023,411a628f,75885ea7,e208be8a,88be7b3f,6b6b06ce,a3aafb45,c439f0ba,d517a784,ba13f80b,707caf14) -,S(b8a6a2b9,52194ec0,8238e4db,e71eb948,23e64a94,e10ea0e1,610465ab,88392d16,f8029f31,b8e5ee3f,77a758ae,343be258,34c7bef4,c1b555c7,4cb63d51,cba5fec1) -,S(a36d3369,a1ee05f7,b1fdb083,ea614cb6,f15feac4,17a416d9,cc83fc2,868fc20,e4abd7f9,fe40f27d,5b7b7651,6a9fd714,aacd2ae0,5f0a1f10,e94327e3,76f0af52) -,S(4ea30108,3d711ae6,ffccc89b,9d6fd4d5,6f03bd68,f4508cc0,ebef5e43,88dda1d,81e9997a,8b1c5949,6554bcf,154166d3,40f9ea5f,ce55ec83,eed793d5,5ca3e513) -,S(20228716,1c1c89c7,64742e62,e427b712,fee118f,406a175e,ce2f424e,2affdc55,7837965e,cf26a7f3,428d2864,41e1d09a,91eaff0c,5ecd2c28,bc817766,67fa35b1) -,S(d3c072fc,8e4bf160,5790d429,61206123,95be9092,f166784c,f5adb7e8,6070d20c,72688262,594c75bb,bb55c0fa,af7991c8,f412e0eb,afd1c0c,f5bcab82,d8daf31a) -,S(294dac7c,e307fa7c,cf0e8f34,28a354d2,94003dbd,ca763dad,3e6df60e,530ec82,479fc222,a7bcaa62,aee807c4,ba6309e6,cfbcc783,afd49ecc,fb9b45f,cf84673d) -,S(3956ca5c,c09fe8d9,e4042a8d,67b276fe,225de609,ea24575c,7075d9ac,4e732fae,1c965fe7,a8219052,9d25ee0c,e1fd62f3,7196431d,7bd78302,e287a26a,2eeaa23e) -,S(24d2e396,da144b48,e736eb06,84940175,4f4109d6,6d87a9e6,97ee82bf,91fb3def,bb79e772,24b02fcf,dd1e3c9c,edbad212,ea875c75,1fe7c81e,76d7d0d9,a372236e) -,S(638d4042,f16e5c07,fcbf9619,dd9c2f91,18852889,3e12cd3a,b49e2b9b,99a2aa5e,d0d97842,4f0010a4,df9eb8b,8e5d8147,f618da43,74b8a4db,222e4ab2,b32b3d92) -,S(f91ad5b,a99972ba,bb323a1f,d3032e1d,94202d88,63680c5c,d7d67828,8f0d866c,60b66d45,a693175a,3a38bb4f,efb32dac,1cb558e1,b0d13571,e24a14d5,9452bdc0) -,S(3154137d,779c25f1,4ff1fb88,a6d0370b,9e6af48d,88e7fc39,c6417272,eaa69b7c,eb3bd91e,9c09178a,398e112a,9264484e,c1980c19,b1993b13,560d39fb,92295f7a) -,S(f8821e1f,dfdf9fc8,1e3acb3c,1d1d7a65,f710be2d,94a19355,721cb93,61549597,bb507868,c1e05282,51b635b9,dcf28e5a,c5770c05,c7afc2a3,f4b4c45b,7d8993ec) -,S(8409463a,521404a5,a2d8aa90,50e3ad8,ec5d6faf,870333b0,6dd4f63e,8354a655,cc99452b,85092ca5,39cc1b66,83b7ab37,1b8a6525,269a1ecf,91b857be,e1db3bd4) -,S(96802411,12d370b5,6da22eb5,35745d9e,314380e5,68229e09,f7241066,3bc471,ddac2d37,7f03c201,ffa0419d,6596d103,27d6c703,13bb492f,f495f946,285d8f38) -,S(9d1abaec,9f5715a1,5c762824,4170951e,f85e87f,68ca5393,d3f9fc3f,a23a69c8,f21ee700,50dbb61c,238c89e6,29423538,71b010e7,98867bdd,149ad28b,3f28cadf) -,S(1fb96691,8db3af46,c37234b6,a4b04371,9886d6a0,5859ba32,f72742d6,141f7ae6,8bc13ecc,207efd91,f7f4c442,6e9a425a,a17b5578,20404eca,b09d5582,d41f7379) -,S(22d9e364,b9274dab,98bcb23,e0428e8a,416d54f0,5a781281,ee221db6,9e1ec7b8,5dc23258,f93d7db5,e5799195,b74e9519,4c300a91,28f924c1,c1e4865e,2d8407d) -,S(625fa450,aed083fb,30166766,d5874131,adb168c0,247cbff8,3987297b,f873e45d,720a8104,473dc904,65585ed2,1a0244f0,fbb5a286,5b8e5117,5a21f644,8776bb7b) -,S(24acb1c1,9b6dfc25,defb01c2,e2681ae8,2deacc0f,f21ae8ff,1f82f37,a6a2147f,f729d335,210e8061,8a8abdcd,b71aabe1,93f50ada,dfaf7d52,783991dd,d3ca5d4b) -,S(d2856803,a99d30d4,f3a328e3,bbf7db3b,6c6d1896,ba5b339f,33c1302c,f75ab555,9649994d,64705b87,62c98bbf,1b41b725,2b814a89,3e780fdf,5689c9da,692d6ff) -,S(80529e65,9d196884,b15e95ef,871e5fd8,8fb5298f,3bc7831b,50a0bc98,4cb5fe0a,868b3e4f,9ae4bea8,efde50bf,c5a5b268,b74b4a8,74e86de6,e9ae476f,10b3b778) -,S(7f9199aa,3b8201ed,5d288e49,49c43277,e0bb316,953f1dde,d0674d7e,8728e183,1aba673,d0372029,546c174a,3a72268c,ee9d7e41,dd97de2f,fcbe1f9f,1a5288b9) -,S(7d32c885,8e959f6,48c4674c,dcccb191,29b4566d,644d2fb7,6d0c8966,2c29ecbc,d90e94ec,b50bfee8,c951afb8,e65c7386,875ea99e,31f553e8,66e00342,6d39698) -,S(f2b961c0,9291ecc8,576ce67e,bbd1bf01,1f1727ff,ad9eb74c,bf8819e3,2d1abfbf,ebfe5849,5a1e6a36,46c38220,8656f638,ed0aec0a,d40c0524,1707102,3126f795) -,S(d9a0c689,95283291,972d6a72,897181b2,6b4ae317,4e98a676,f75bbfbf,81be876e,d36ae886,a0acbc9a,d1564d97,4d3f0309,e9039b93,bb350d92,2b7f8c7a,c6bfa042) -,S(c7a36324,6aeb7c8c,991b2aa7,10abdf5c,fff29912,30b3a69f,be2dd481,7c7c3e0a,1298fdd7,e448d2d,79986302,6b4b2d49,2b32148,d6d1e5f8,15f5b0c0,5c9e21f) -#endif -#if WINDOW_G > 11 -,S(635cd7a0,5064d3bc,66535a0,4dbf563a,640d2464,c7fe0ac4,8304214f,e4985a86,e40265,913e77f6,46735cfc,af9e2f30,e8d5f047,f3281a4c,e0453e27,e9e3ae1f) -,S(5da624f,38edea25,37f5b632,695b481a,eca54bb7,2169cadc,c5b91e10,989ee5f5,d3ea6dba,a1080300,fffaeeb2,43a5256e,48c28822,37b16505,a220d771,ca721779) -,S(aa4f64a2,b19775ec,92c1f687,1fe4b6d5,ce05278c,2976c80e,fe19284f,e87d4d5e,f39f117e,95fce0fb,6976e949,9583a66c,224ea028,8396518e,293793dc,3ed4f240) -,S(9b6518ea,99ff1b42,22a93f26,62e05551,d60969ec,ebe378c1,477b5c36,427e0641,2e9f1655,8650fb3b,43aea9dd,30532ff9,bebdf7c5,1d421656,27b7487d,8f93165a) -,S(6c9b9aa2,b5972e0f,a1e01138,1ddcbeb8,6547f47f,fb101159,4b193d00,ae97b562,af09d91c,8d4c71d2,be523d0f,9d205bda,a6e78eb2,67476d3b,1624a038,6275e27d) -,S(a2a1c880,3cdc95c5,5e636541,c7112a0,cf80aec6,a37e5f71,f5366612,db467cbe,c4cf570f,3638f040,ffe5410d,50d4b175,802e2e1a,c422fc2,73eb9b2d,4e23fc09) -,S(63d3750,c961ccd6,34a5af10,48897366,13102bae,20f2c8a9,ca8437e5,ab650427,87415332,74b39a76,72de90dc,698742a1,f21125f0,71393fa0,6d670045,8e339248) -,S(8d070e66,e4428255,a53e8fb,5845d14c,bcc97dbf,19b6930e,1f5160b2,52bdd04a,4bc98c82,4f2b4f04,c9884099,f173cd22,48cdef90,ceef4bb2,497da8dd,99487ecd) -,S(f1fe56a7,2e5f008b,b5014395,cc1658f,e3f3d4df,7b361456,175bfd2b,4a91c8bd,be5ffebe,e57a7da5,d01e302a,d3688567,a19caa5f,fe8a57b2,be2c866e,f5f275f2) -,S(802c9adb,d2eb969e,9ba71a95,675bcc7,b412399d,5aecd635,7476a1fe,73554b21,42132026,f547ce69,66e6527d,370f9c0e,cc3344c9,be1047ef,b7422e13,6772bc5e) -,S(95b1b6c0,9d6ced22,f0a5cd,abc7a594,9d24cda4,f178a745,c718204b,1493db56,bc143681,53033d16,ac8ce5e9,a6cf240d,27b2331d,36cb23dd,f69009d4,b6adb01d) -,S(eaed529,1f94eae,183b2aa4,e17022f1,7b79a06e,d76b169d,2d6483a6,a6ede35d,53d5b276,91c5899c,ddac1efa,3ad6baf0,bc6e377c,99ac7f8f,9cb27fb9,5dd559b3) -,S(77c44fe5,9f6f448c,72eb485b,6ef3f7f3,906d690e,367beabe,ac7b7359,9c27d770,bcd75022,6c440f80,2ccf0360,4e3d6b38,e6629c9f,facc49d3,83322eeb,fb1102fd) -,S(e863b2e2,f00f0a46,b6752002,cd936a88,11b6279,5411944e,fadae5fb,e40a0306,b5c79ba3,6da29f17,5b9caff,631e8ead,c2ed937d,66008358,b36fe044,67243a5f) -,S(226f5bef,93df71d0,b2feedda,4ada3098,3883adb4,f3dcedec,2721e72e,eef8f191,a09204b5,2bcebc14,8a0a08fb,e8458618,f966078b,d75ccfbc,c13233ce,741707c3) -,S(aa222fb0,8c1e7c53,9f3a82b3,9c6f08de,c33beda4,aff7c46e,3a4e9036,83467184,41105cf,21cafd39,821a7c3a,a6dff931,c1653d29,906b5d4a,c5dd6431,7c1c3765) -,S(1879c2cd,26ef4ed3,dc5220bb,397b1501,f94482cc,1236da82,239754f1,e1fec96a,912d5f35,75eade14,91fb1609,21d63042,4fc68951,cb73d351,464725b7,71f0d67d) -,S(be39e4a4,e7eed88b,f4a4cfc5,970d4b7e,6df6211e,bdc2bb76,7657ecb1,ac9902e0,d8b1e4f1,13fca7b7,6306d9a2,b4cf5a49,32ae54a4,5615c899,f94cc476,7e27cb4e) -,S(1ea72fce,33378c3d,d0302836,86c3f8a8,1c2912e4,7cf44631,d3fbdc2f,752d5786,e20f4558,fe1cdd14,ccff261a,fe506b78,cb6e2b0,807fc7c9,aed0b888,3748906e) -,S(56e33dd,67bff57d,e8c638e6,f32bc396,2d0ca011,b74db242,3ac662fa,da036806,4039c0cc,165e7130,9317d4e,41de57bf,50d78ecf,3e14ee2e,fbb3b93f,c393f461) -,S(51981691,a5f1d8df,1cafb95a,738b9e3e,d036ce54,f10a7447,c470cc2,e80f37ad,9fb9047,67cf2a99,766e3c2,6e97f045,d03fabdc,471ef664,d31aa662,c5972261) -,S(ef3a5685,77a59783,6b0be7f9,5f927996,b90db9b9,bcd57f30,16ec5979,98869dbd,51cfe457,ff22749e,949782c6,ae1f4783,fabe1136,4bb524d3,72ac3d8c,1b7c5e07) -,S(efc652a1,8c3a85ba,7ee9e0b1,6e3c6433,79a66882,5304a22,523c060d,af196415,8a656c14,cef91af3,1db2498,f5987083,8fcee71c,98c09d49,737447b3,54f7b2a5) -,S(cdda1fef,f4d5ce2c,d9802198,389880f1,8adc7962,c04a95de,f07370a1,884bbf82,8bc26ffc,b0c9dc05,d799174b,4a478162,4417f9ab,8536235a,e55c9b0,49e31d6c) -,S(6f3f3985,3454aa13,134b76d7,77dedd40,d46bb6ac,dc3a3a3f,93886847,b96cf0d4,a8ba499c,4f7ca1b5,ae7e5192,ea408344,b6e32491,e5649637,e4eec5c9,2cadba81) -,S(e52d11af,91abfb83,ea842065,ed8d804f,a2a3627d,85149ee8,61cd5df,e54b13e4,59f3106d,619e5672,cb21f6ed,4e73285d,2e132a3d,e3ed069,46838e12,a9cfff97) -,S(89fec736,f0de1cb6,45654d13,b32b3cab,8fb91869,c30e2ac0,66c0cfa3,9e7256ff,f9417ae8,4d3e1a6d,b6ab938d,9dfde62d,73e708db,b58f5ded,46b455ae,7e44274) -,S(5140f56,91b10553,ce86ce73,3028749f,52261520,a8903f75,31bdac09,22b70b29,91a1962b,9e02c23d,61f4ce,21c0ce90,ad0acf0b,fa250afd,dd67d72,aa2dc024) -,S(3c16130,93109917,1075e199,ed32f94b,579d0eb,85520d09,c0f90fc8,7d267b5c,d50d04df,e4040db9,3aa0010,7693ac01,e9f156ca,5e800e51,a5f7d36b,78ac64c3) -,S(fd87690e,63a50237,258b8a58,f0240552,a2d0b952,911d1fa8,be13eeb8,9be8bac9,406dc1ac,ccb968f5,6fa3ee35,247fc66b,b40f04e3,ac512474,58e4fea4,8a1b9225) -,S(8e4d1de,17e78f3,2ce8ad59,973b328e,99005ce0,6a8d9347,ebc7434b,d5a12a81,c6348f3e,744ca65d,744c843b,4bbf0d8a,992bafa8,8c31b6da,42919401,b1a2a8ae) -,S(382c7bcf,ea62c678,173b6eeb,ba58caaa,f4988104,1677bff6,ea739a0c,6c7743c2,190a5da,77e64243,53df7f27,e01c0f6a,67e9addc,afcd3523,7cf5539a,69c5eb7d) -,S(f56a8b4e,74b84807,539fa471,bea50795,25b0dac9,53bf5d29,e87d90d5,f914ed0f,5456d908,da57e612,3ab881c6,56a6ea24,8f9f201c,13915a48,c50151fb,c096db8b) -,S(908e9ffb,6a5e557a,1fef8ea2,b16b80c4,3af3652c,55f12a04,4ecfdb06,17965b80,beae28c9,d1b14cf0,f8182ca0,7ebc3137,b9c01094,ed6b6043,562de75a,878bc2ce) -,S(a6c30718,433381fd,16b22533,52934eb,3fad254b,99d41e78,7ef2e6e9,bec86ef4,47a9a286,a60d5102,4d129e4,e0309c72,9e266f82,5ee26f4,4bf90057,623fb818) -,S(948bad86,6c3e2c26,2d46163,52be20ae,30a652e3,4a299361,4766eb7,98b3e903,30d30622,ad478a2b,99c43b0f,915de0c,4321da4a,76a18d33,95b4c484,d9c35164) -,S(d6c92b9d,cb8a17ae,77788125,18782d36,9d536edc,f96d2c9f,c9e84d2,1cf6a3f2,dd9367a0,93518377,97b0ae88,1aec5d4b,ed68624,8ec2207b,9e0104af,2ade09b9) -,S(f9ff3d7b,7d8b13d6,46c641ca,64df802f,7b082209,a75ae328,54cef0fd,65566abd,ac58619e,1f192095,f7223022,43d811d1,b9269d28,a18711c8,c84e5960,32deec98) -,S(3dae1dba,3a70e0f7,209a920,42837ed5,7f4e767f,834d14e1,c3528f6e,92c8d5e0,7ae2468d,6ea1f2cf,e1fcdfad,3ffe87c9,5c7816d9,ea99332e,8b4d055,280f797f) -,S(27045105,6fcc937c,9cbffe13,f2aaeb0,8ffd227e,dbbc7ca,d0b4b01d,19b49937,11766a54,6c24fdfe,220d3724,661d6c75,bbd801f5,c4286ad4,d08a698f,1ffa4397) -,S(f9d95ff9,6c3260ee,cd434075,262fba81,2024c556,649c4865,bb90d65e,20defd22,37cbf7fd,8f741411,80a632ba,8304730b,a89d54a,1a5b1dda,24b026bc,17a13c2d) -,S(4e8df18,f90f67e9,fed8c6d5,b66cfbe6,ff0a86bb,db990214,48ab57c5,c5a7021f,7e69f8c5,ccf56413,453a2b1b,3b34843c,e9badfd,3a83729e,a2293fda,f2a621f5) -,S(8c2a4d2a,710a7fb2,1ba78383,63c66458,ab3d32bd,3be35821,c8a5b779,d2ffef9f,d532447d,27e42583,46171515,71bd6577,f82d8f91,ff39d205,caa5aac6,365511d6) -,S(28b7f3a0,19749cce,6fc677af,a8fae72e,c10e811e,d4b04e19,63143cef,87654b75,30471eb,3245ab39,1597c881,e71f4a1d,e241ba31,a678fe39,2ced5a63,845ec782) -,S(cb474d0f,fcb8e72c,257b5acb,999ec8e,d89f6494,cf4b008,8f6d7db,59be416b,ff7cd0ce,fc293cbb,8ab9a950,8759f856,9a0e59b3,effc00c7,e3a3051a,a16622fd) -,S(c33e6982,5dbebc40,265567fb,ede2a4a5,1a180034,2e9963f5,bd57b35f,4055b36c,22ff3ff5,7ce265ce,253b5061,599ab066,82c0cb5,91a51e0d,b798ec2c,c546be18) -,S(84bfc106,44d37123,71a441a8,4444a9ab,257e0745,b3d0ca0e,ee341838,19bd2237,7cbe56d5,7b7af706,c33d13ff,b3e4197b,afd7f421,1ece235a,e1c2187b,289ef6f1) -,S(9c312ec,d53b244e,fd40f003,f7e0835f,6063028a,5b0488dc,73599653,f97b713a,11bcbd0f,58fc77ef,854d0b16,188b4e8,59698ba5,fee41fe6,165449b1,4eb76d14) -,S(5c06af59,a22d6f2d,cd83bf4,e3bbcf21,d474f61a,e01d0433,2d0a82dc,af15cefc,476b4be9,f1c265fd,a8c6d70d,6c669aaf,41fbefb1,425e2be2,9048165a,4322aae8) -,S(777259c6,81a3ed43,b4c0eb54,7af39ebb,f44f0d71,c84602bf,2d6d45b3,f1b6bdcf,8a9d3753,5481858a,eec44851,4c834667,d6742b9c,f563ebba,22fde187,fb3bf754) -,S(b370601e,ae1fc1d3,14e4328b,4d0244de,174b8c4,766283c,e3820c50,41266842,8ef05079,2174c3b0,752a9abc,8d980ee3,eda7b5aa,4042a932,3e136834,bc125ac0) -,S(5af94ac0,7f8d6492,a472ad40,67097206,78086856,b01528bf,8248ac8e,dafe6584,8a54c7ce,57eade51,1d5f32ef,cef5f56c,b40dffd7,8cfe5655,2a9c3966,e62daf1a) -,S(8fe3c19c,e2e87055,385d4f23,c5832f37,4f84b41f,3f945945,81acb8e7,5b0586c6,f923099f,d16f44c3,a4314d49,1af193c9,2f5e2017,156f860,674f5ac,91728c28) -,S(d580961d,2642bd1e,5f9211b3,9b65eb5,e531d17f,a37bafc3,b5f288fc,13ac9a71,500c0554,337e8b43,36e50a6e,b12fa86,d9678cdc,5b38f650,e4f897e9,1b4185cb) -,S(255dced,529fa623,49e46033,86790c32,234e7967,5a9c5405,256cfbf1,4295e82b,7eeda9c4,7f3e1c7b,fc3253d3,faa46317,5dfba7cd,94f6cb10,c8f4b4a,7d799815) -,S(4b7ebfa7,9240451f,ab8476a4,ae48e55f,1a27c338,a8dd8458,bdbe422,ec891557,dfb260e9,f89135f6,fca23cf,ad7ed812,c12622d7,e4285284,8c63d83e,85b59085) -,S(919d0780,9e6092a9,a3b5819e,c67719d,3119569d,3bd14c7d,8f47f555,1f2fbf28,ca0b6af8,76d70f2c,ecbb2fa5,98d6118,c204d3d4,a30e24fd,cbcaf283,843d8094) -,S(466867a9,de89a944,5bed73bd,5ae342a4,9b8c896b,59eebf42,393dd536,8c70ee78,2a5d9707,b3e15823,79bd6ca,e8b7ed09,9cbb9f93,4ee96029,385d5678,aae042e1) -,S(71274d08,c8784517,8921526f,cf71258d,fc740d5b,be655f3c,d985cba2,c1db3f7b,e0af0130,a5be1434,f8d652bc,4406177b,3cdd2ca6,6abe7f56,d848def,fb4b25e0) -,S(a46e9048,2d25241d,13c693c1,f4e6068f,b6e8256d,1fb3111f,a0ae0e37,7ebe2bcd,7567700c,f22aab69,8126e7ac,961726ad,fdd708bf,d5ae5111,40f921be,94474eda) -,S(f7590b91,f2431126,85873b0f,77be6851,10ea918b,a26d3b5b,aec02bfa,a5e84abd,481848f8,594c94d0,c9b5d6cc,858dcbc8,2d25128d,5ea28e2e,ded935a4,62708999) -,S(2d7aa8e5,1282e1da,dad39d64,398f0790,4f966edf,aff5e3bc,9a22edde,428c2edf,12b2133c,42032099,eb33ea24,f1755f9d,a30b4da1,708cdfb5,7635b61a,335d9d79) -,S(91313f40,3302c47f,d9f113a5,581f135c,82280927,5f658607,99550fa9,7236d0e3,f8b6ec07,5e7804bf,461daee9,1f21285b,aa9e96c2,2e0cff27,c323f627,90838a77) -,S(da248119,9d385a7,8468e86e,1b146fbd,e0be031c,3a19d0de,2f44a1d5,6c6743cb,c07c897b,5f76f6ee,f2c62511,19b37c47,5d418b6,1d2cda66,6d39ef67,40348cbf) -,S(95e36a24,b1bc2e3,fb5e6082,de9ed432,760ec3f9,6f01dbd6,2e820268,dde82220,be6990d7,3abc4a3a,8f03b209,dcb4202b,52a74a87,1e1e3d01,7665e9d1,1ce1cb63) -,S(8b05b060,3abd75b0,c57489e4,51f811e1,afe54a87,15045cdf,4888333f,3ebc6e8b,1d10f881,45db40fb,889e2ddc,e81bda7c,27f5b615,acd6179d,bb30f4fe,7f40fb39) -,S(ffabca3b,764a327a,750bbb2b,a1cb8329,d43ec0b7,dcd8f728,55a9d30c,f3020f54,93970a65,c90ba260,5b2fb393,a4e994b4,c791965c,b60a1302,cf585443,6dd0f05a) -,S(b3a85aef,ef35e4a9,8f0f05fa,9752998a,d3514868,b133e7c0,a18fb053,b866c72,30115ee1,c21e5b9e,3d6b36c,54e700e8,9ee78c7,e88a2752,38f46d1f,5b6005e2) -,S(a4f1fd5f,4c233cf2,b9c5659,f666d51,5b78fc32,ebcb52d5,d155250c,c95b7ab5,91d19f85,726a1258,444419fe,c5219c7,33754325,89d92d52,c363d61c,81faa0da) -,S(97b84b4b,7baecf13,94bf3923,2b58b5ed,9eb14637,d29b3c98,bec3e624,15bbb0a,497db4af,be8e7b3a,13493d73,ca92b4b6,5eac7f30,d86dbbf4,8b86f495,2d162435) -,S(2ceba0d9,203e3666,75e78e96,51b5b57b,a9de5f82,3cc8569a,1c274d19,946312b3,d4c2fe86,f042cfde,41f0a88a,6d77c188,b7805db6,c6ab440a,488a75c3,8ed2b437) -,S(ab8b1930,6cddaca2,8be57b78,b4836998,912391cb,c6a41e10,e91b86a2,3f2b7009,fdbbabdc,79fba1ae,9d8472a1,7a648206,7abed651,36892a03,35128650,374172cf) -,S(2763029,1ff140b1,57eac2b5,9938f26b,c149705d,aa2dacd,6bb0d305,1a15b394,c2b6b32a,38dcb9e2,f4640838,c52f5ca0,55359479,86ecd875,a91504ac,49374ee6) -,S(22d1edbd,1cc1514c,7f91d793,3e9dd124,9e703fd0,8c65ed8e,6cc79eb5,cafc78c5,7453e7ee,a53ae741,13024fca,208a3816,a93942c1,2378ff7a,5e65678,c0a85efe) -,S(70d869c0,c5729e94,270fa559,bdb3fb8,b6146527,5ecedb7c,c8e7c9bd,acffe222,4bfcad32,8ce78fb4,617baec8,48c2c3a8,f8d41474,9c131657,115dcbb8,f6ec30c5) -,S(a25b45de,da8d5782,64f60dcc,da97bd28,ed9039c0,6bb7c97d,d4a24eb8,791b1647,8fd84983,fd2ad956,32376555,4c43a664,f306f11e,2f030c7d,fe1c68d8,aa43db8f) -,S(823fcd6c,9b237c0d,5aa38336,6737066f,3e77fa14,b975a5cf,39ca8a74,3b1024b8,e691a44d,29a4f2dd,e99c2ba3,bb6d4345,d1433e4b,d1c65d72,198f16b5,4424dde0) -,S(39a5a63,8244aef6,432b1247,d394d305,ee594bd2,6ed2433a,3a96c4ce,5a158d0c,147ced39,dd8b8494,d57ff37e,a24cb108,ee4b9f43,50c556cd,32df8b27,626a8023) -,S(8f9febb5,b85bb2dc,74aaf7b,81b27796,2a18f6bb,4879f5f8,de94aa56,b3206487,48daebd6,d4175a00,e37dbde,c2b57b3d,dc7474f2,ab6a093c,32a86acb,f610c2a2) -,S(fc16fb14,2f500856,4509158a,5f6b4e35,6a08db53,36e9d3f8,4f7a03d,9143f60c,8e9326f2,7e02b73a,10f4ada5,9db85fe7,4027584e,6b32aeaf,58bcf804,dc1f7a36) -,S(7db09ea7,17446f6e,9115d8f0,987eba83,eaecae01,f4201d78,8e292486,85c5a281,b4469cee,426d455d,f736b2ad,c12fd17e,79fd2167,c5a6f864,2733e327,c215742b) -,S(d45d1bf5,28baef1c,3ea56fda,b1f8d3c6,3df7caf5,c7ecb0b8,564fbc94,a4d9a57e,91e26984,64830e89,1cd21d3d,81ad7000,ad0c84d1,3c05a191,c1a172e1,16aeccc1) -,S(3faf0b75,1b6f85d8,550a9ffa,a7a26bb1,6a4d9c99,ae97678a,d43a1a91,75f03901,8a5d062a,a4e43cf6,5caaa39f,6386311c,be775d14,3b8d9368,b555c436,1844328f) -,S(54608cbe,8e08a472,79cc5e39,c65e1ec0,1eefdba3,3b127107,4926b06c,76efd121,a7695bc,40def81e,48ec5f91,cc98fc2b,9bdc2776,71d05afd,cb789e20,c540f038) -,S(559a0d89,50dfcd4,364e6955,23b56972,e8a201da,4e196d46,64dd580d,909823ec,7bf8e1ad,d6528b90,cedb8d5c,87f5953,5641e32b,6a6a7b4,c46e8052,e8dc71c3) -,S(166e8858,b5e2b9f2,b1648c34,41e5fc28,bb305ea9,b0679c3,1a996b94,acf467a8,9c9b306d,ff82fb42,acd8a6b9,108f9994,dc1b7c37,dd0c9d2a,f64205a3,92e5bdb2) -,S(40e29e8c,e66e83ba,a94ec5fc,3ae438ee,e5284f94,c5efe5a8,d41da738,38fe1941,7c71f71c,c01e7868,1cf154e2,73a23d0b,84ae684f,b0e709c3,9551884d,39acb2dc) -,S(6829c8f9,eb659ce6,7f87fc76,4661b400,6aeb8b3d,bf674408,1a844380,72d4ee7e,1d35530a,8332dc05,54e82522,5e9ff30b,6647fcb3,304fd908,ea506945,ca22913b) -,S(4a3fe05a,322e9fd3,93393b13,6e2af237,e25a2540,42d10e7a,dbb35d41,13658196,859a41f8,d4527641,a93c40d9,ef0ab175,78dbdc45,7edeaea1,f147018c,7901574c) -,S(de5817c9,a675eb2e,c1567ad5,a6467cc2,9e9ddec2,177f382,25a5e101,9aa44f94,4050ebd0,5413311c,df17e625,6d4bf102,71b45e17,4c8fcaf5,ec36567a,ccf723a4) -,S(fde29245,4f07f411,abdf1a2,6f3d8f38,daa7b9b3,1b51fe7a,155da5eb,5662a108,f2a4e6d3,7b39e929,ccf347a3,ac6c719f,f09d1756,e407371e,d98dfdc8,b727808a) -,S(f28d3cfb,6eb98ba1,76fc536d,6a772861,b0917415,d08c22e8,a43a90ed,eff42436,4508be2b,b328250d,e043dc82,d8894aa4,1971fe8c,42e6cb61,e9d02735,1279d1bf) -,S(c7655c30,4d1cb5b7,d0992afb,119a6df7,7bb65496,420f78c7,117b951,7f16e3ee,898162c2,cdb730dc,4b986b1c,b0de79c1,a348b0be,51b9070d,2e427e2d,e71dfdfd) -,S(e57d97c7,2fa3ee66,71d67936,eb62f4d8,53ffba74,f2158d0d,7ae3eca0,7b4b147,b1e3012c,a3d92975,91ab80b9,a668ca13,1ed42660,47c34958,c07c720f,e1fecd64) -,S(eada8642,155025bf,c0644f92,fe014ccb,6cd3d37b,76686a44,bccdf8c1,e22b0c01,89035d7d,71d71bb0,117c37c5,540f82a5,7152aac,af79fe91,6aed7d2,9dfeeed) -,S(3e76267e,3f172198,9f9d7e8e,11fa3ff,62dbf8f9,77503e27,5567ec84,e60d0e25,a1835790,9631c6db,a453001e,c7e3973a,416f8bc7,e2fe0871,82d8a236,6e1160b6) -,S(a11d97d8,9c262f35,2279e69,2d66be7e,5de7235,18e6750c,6972d250,91a3df70,d18df8a3,dd6fb016,df2e48fe,ab889165,44768d77,e9488b71,fd31c6db,d52a69dd) -,S(b16e3f75,cefec06e,edd54bf8,dae7cc29,a5ab5208,fd58d787,922f4221,f5f20651,57fbfeb4,5a6e32ed,74fc1989,16909891,233ae90,c539b81d,a758761a,a6d0eb2d) -,S(37de800a,3f73ea6e,9eb564c2,faf147a4,837339b3,44a33d9f,beb25784,c74628b2,59339259,9da55803,196b7e5,3596aad7,e33fc96c,fa2ae0a0,2f41ec13,e6254050) -,S(6f68412d,65b3abaf,6fcb781d,8b6e6baa,4ae57fb0,9325a1f1,9beec438,cbd68055,884fd59d,406171bc,b31042,21abb5d,27dc1433,ef49af08,ec031543,2f8d3bcc) -,S(91479a9e,6bc5e261,24cf0ce2,b52f070f,980f1f9a,f60bca79,572902d6,cb6e4366,2304f70a,22de4435,99f6025d,4b13be27,47932524,112f64a,ef935d1a,9c2f5288) -,S(8ba6b0df,36ac8708,8c1e7c1e,4177dcc9,4cceabc7,4a6c7701,8358c194,4d19bd8a,e96b720e,e9d515e2,922abe8a,177ac755,989dff1b,789a85ba,ad17f859,62ab9ed4) -,S(ab152195,871f3fcc,58f59a8c,a35514f0,f11b8a69,54e4ec9e,f4aacb7b,29d567cc,c1ddad48,623ebda1,42899ad1,75f88ff1,965ec1ca,651b419c,3c8ea037,f267fb4) -,S(7eb23f48,5eb92bd0,1c0e6448,e19adc22,6ca45c46,d4d5c756,e552ce7d,551600c5,953e9b12,4278b939,7b3de07,63e30c55,a300ef97,a8587328,b3dc27b1,a7c57ac5) -,S(b23f4c2b,a4b2700d,c7520a92,25890491,e0212fb7,eeb1f0a,2f624905,4e21ee17,a38b6772,9e95b3af,2cc7d5a5,c10386c2,8a2c287e,6349f811,457ae0dd,8b598530) -,S(85d2e723,387e55b6,a2c1a02b,96cfad64,67a6c12e,b75424a9,a10ab77,2769c2a4,727abdac,223898af,1b077fb,7d481434,ded380cf,21a131d0,db845150,c8e4d303) -,S(27c1715e,8dba4cc,41383d59,e669f66a,54ae6901,88a794be,9fd8da6c,9b09273d,2767ca54,306e6ca2,3517d884,1e7f30f3,e16e22c5,cf2bbf9d,998d5cd4,b5b1a266) -,S(e70b8cd3,7f9a5e8e,9e0c4fb5,6f85a6ab,42cf4042,4080350f,4465cf8b,95eed89,2e3d8c58,94788d1b,9734e93c,7508cad,faacdf06,319854fe,5ec4b0fe,6b0cb31a) -,S(e23dd455,24058396,98c81a39,f3f076ae,93932c61,d0e7f65e,e2c2013c,dde956b9,6c53cbd0,cd8ab8,bf5cef85,a8aa0b64,52b57e79,cb53315b,1dcdb68b,78cf77c9) -,S(5e923f81,ccc49813,11a09f2c,47677cbb,9aaf0832,10c683b7,d7a07399,4d919c9f,604d7112,e64cad06,fe0e64a8,af7054fe,7059667c,fb5159f7,738b97f4,38306873) -,S(23d9f253,1a9fa278,e02b71d7,113fde6b,1380e543,633286a5,60037ab7,70142507,55dc8247,b6eb6119,a6ef49f6,bb4e85e3,a9fd201,4f696564,42d3372b,fe44a9ac) -,S(eeb23095,ad2551ef,15dbb281,5ef6d252,886c79ef,12c7318a,50f5d89,d73b8f24,d1a71b94,b9810ce8,eb0c3896,3e7cfb90,56a80f82,9d384eac,67d9859b,11ba1ddb) -,S(64a6de7b,57bdf7e2,54beee53,6efeea9b,899a8436,e421e3c0,e7a2682b,54b7c21b,6427936e,2e344fca,c402e2d,2902fc6f,181ad190,e3f0d537,cf40c96f,27b4755b) -,S(9e4676ce,d76daf3f,1c1aad5e,51e700b8,8207fd45,3cec846d,779f02c2,cc270073,5685c781,1d7610ad,4655019,5d8a844b,6ffc4acc,eb458c38,d9d74f4b,cbdc9e42) -,S(95ee1228,80616ba1,76e0ee23,14428c7b,1d83c635,6ec843e5,d134b359,8d645473,7be34c64,41914c07,58081278,9b254c71,49a60d13,c6ee3a3,7d12e29e,a3bf4054) -,S(e53ffeef,d92081a2,f91df506,6453cbdf,d0b1089a,c598da9,94fe4c03,fc6516ad,560f02c1,4a600d02,a2e70b28,5164618f,5dcd1b67,ac071929,ecc1d891,e4c59c2f) -,S(9c332744,7c75488c,5a14f1ad,fa3d9974,90d4eb10,63afba83,fafcc3ea,62a7b68,9cc759fb,9a7fc3b,4d0ff7d2,24d0cc54,cacfb78f,5590eb8a,d689b6ee,19791c63) -,S(e826d500,2f4315ff,77eb22b0,c8b74142,f1d1037e,81e3c58e,4ea39430,973d3c45,3a466e58,82f971f4,3ab9316d,fc7d53a4,e8ab16e0,2ae75045,5d8d1999,bc8b65de) -,S(ced4df0e,af93b5c4,8dcf196c,6e9b16bc,dd38a87b,3fd67512,d387b388,115e13c7,fe08a63b,dd149dca,b4f2c930,99cd11e1,8c754271,cedd597e,910462c6,d68b74cc) -,S(b056ed27,88ea50df,2b220182,df38f54f,8065e36d,e0218b27,ee8c5416,db7eb33d,97338375,cef457f9,ebe43aa8,28e9a1e9,8d514d9f,fc300a6b,a1a83db,dacf6409) -,S(35dec74,2fef94a,7fe60b66,7341f6a3,eba030c0,4061d156,1c9ee288,5b7830df,2599121,39c810fd,e7f02fe6,eb6e9221,3eb8be6e,4d8f045c,aba1f058,789b933e) -,S(3f23cc8,7733213f,d2e15cb9,942af44f,d7981e97,37c5af1f,81addfb,324e020b,24e8ccc0,d43ccde3,4e392455,dcdec100,7ffc0c61,3b5f865a,c8afc051,756e8f83) -,S(9ba96c76,c0805cea,d7ecfa43,dba0d86f,c8471dcc,8bce9bc1,e06537ef,2bbabbdb,c1a3c433,1c2ae04d,be2f8e3a,8f4f07b1,622d9820,607ee3ae,e93bc37,f943def3) -,S(83c1479a,31475395,8d510396,5decc9ce,1d414f41,610e2ac5,c2e887d7,d16a3815,84d4d018,1354cd46,e5f39bbf,f9fffbba,c123d470,d07c292c,7f085740,289b5b7a) -,S(bacf627a,2db11d88,76e6714a,2857db8,a8d7010d,7b349ab1,fcb5ebc7,efe0a32d,a287dc0d,a44c448e,68b777b7,36ace20a,14b3e586,bab7ef5e,d57ae303,e8c83129) -,S(73063c55,30129f79,10bfd2d3,a0147167,4ca888d1,d64d24d4,619c5cff,2776ebd7,d57941d9,44ccf8c8,2fab0362,b14986c5,9d71906c,d28584ea,368c4bb2,2c159489) -,S(4ee8632,df55ad15,12ba4ce3,4ddb403e,a3f51a12,d445a011,4d08a00b,3b5d6637,c29f7199,dc30275a,39ff01a3,19723d19,91687901,9616fd81,88ae6c45,92b14820) -,S(fc46e66d,68bbd41f,98b18a16,a23efaca,8f5345ef,b567786c,cd42afe7,d7e7ef28,8b42a2df,abf8849d,53daf38a,4a4c28b9,a0238231,ec8f69d5,d702715,a643c18a) -,S(a71ad1b0,158d7978,7eece5e,2a3907b1,3f9b6b98,aefc7963,8a9de618,b3a7dc13,6fd7e86d,a956c464,e538a864,41b9b7d2,ccfc5c44,e80a66ea,4375e6a1,ef08bf90) -,S(602185f3,6075a67f,d7bb9957,60c6af59,61a7c553,d51d828d,ed37768,f1860a3a,90d312db,706b835e,647a027c,e7a89d39,2265cd4,dd52e802,165c32bd,4d10b2e7) -,S(db0fca83,76729191,b9d9976d,37dc62c3,36b4437f,943706b5,98e7b7df,607a77ca,23dedd6e,8eba7ebf,e0c9f0b3,2a1802fa,78699a68,99507dd9,c4f4841d,82efc29d) -,S(6919b861,598d4f09,2a159909,fff8de82,237d0aec,339d884,7618f257,a4a54939,ab9f82fe,1fa53aa3,b85c0784,59a4e191,27a1a214,392c3ff2,f3e1cbdb,6f34b90c) -,S(f4a7d2e9,f1f51ba7,c3cf0a5d,5d53a00e,877ec118,f7e39e39,299efb2e,8074bd59,9f050900,6aa6ace2,da4e6380,cbce7983,c9bea9d,99741be0,ef17e190,2c5bd257) -,S(8a5d7210,d4f1de13,1091ae23,2fffbd96,3927317e,54197656,366b2e35,cd453da3,9aff8a1b,5b71da0e,a6558a05,a9306adb,4cae1004,e532aa98,abcd1644,b0580a54) -,S(99eb23dc,e40d7159,b0a0406b,ea04b87a,2c9195c2,2afd79f3,f938018e,b8e86f16,2ef21938,a66efdec,7ff6cdda,a79fcabf,b1f17fde,9e80db37,82b47d41,64ecff66) -,S(3bf16e84,1a874418,ac7f0d0b,9abbe781,611ad0e4,7acbe904,a99ba65a,b4d37472,1d3cb9f4,e1948cb2,fc88c0f1,9277437c,7d1138b2,8aef4355,1fb35121,a3e714ad) -,S(a3ef83ff,19eb394e,b87c133,36388a86,561811ce,5449895a,f459fe4f,e7f01f3e,1955dd39,8bdcaccb,cdc7ddb4,711d08e1,9d687ccd,d335a4a1,45d13a4,8178cbab) -,S(26816f51,da9b4e81,3edc024c,223dd6b4,5a344d11,f5ade552,63ef17e,70b1af90,46278e1d,1d6b67a3,57280967,6604e897,65611b7f,bbccfd30,22007a60,294aabd6) -,S(5e1653c0,d640f148,ecbb14f6,97940b0f,1d47dcc9,48e7525a,909e8444,afdea823,9b8b81ed,e7cb8350,ecfaef22,92bdc528,8e499cc9,6feedc86,cd45cccf,4cb092c7) -,S(1bd88e45,b0d3694,56348c23,125b12b6,b7725d6f,addc08f2,47fe9dbd,e828de9e,182939e3,2d8bddda,577dae7c,a1d40164,9f6faf68,69808fe2,98dba2f,b8a95db0) -,S(4b03fe06,3adc4e40,315e754f,bebb7802,b80ab716,d4201fbd,31b12c5f,d9b73c02,a864d0a8,e2c5e519,ced537,e03f98e3,a5623c31,ea4a430e,73e8cf54,1c80fb06) -,S(e20a515,7818f33,1ed927f1,3c46f3b5,2146860f,d085e68c,5884f1e8,45d35f61,a1c12002,1a79d6c5,89e466c4,3fd48f66,a924e9a0,a3d20db0,484875e6,96bcf328) -,S(e3d11a4e,74a1e1cd,8be24d87,4885e1eb,4aaecea1,c802ba73,2db925c7,f81e37be,8f1ec01e,a1ef01f,63806787,b8831d4b,22b0a9c,7b44bc7f,73d2a3b6,861645f5) -,S(8a233215,57fe0dbe,e8e92b58,4729b163,da71fa32,f400617,d1e2a081,3e37f6e5,af5e471a,bb8c7505,aea1ed74,bd7798cb,267dbd29,61c35f5e,93889056,aecce950) -,S(3bbc0a2c,b43f4683,151070e0,7015cd6,997e8dfa,99685cbe,99f9a76d,6851d20d,9a1dfb8e,a5f14c40,b9968e88,b6083111,fd140843,96fa8278,bb0e351b,7cb4f97d) -,S(8c04d781,82d83ab,e8c59dac,9407b4b9,65380f38,39431184,811e133c,911d1deb,4d74e493,fdb22316,fcf21340,88039534,c0a3e098,7198ceab,4a65260b,4c0a3db4) -,S(467d4d0e,72312cde,df0aa7c4,62e03644,1ed9f915,c9e7e8c8,5770a4d6,d6a0291f,83db40a9,d7c2954a,30c624dd,f11d565a,f117e240,183a81fc,d4dda1d,70a1ce32) -,S(b62f60cd,8e55a101,ab060186,941cbd52,ce73ae2d,e19ac195,d55f498c,45a3dc8c,59da48b0,7c6d2562,eeb0ed09,158cd20b,4a5108b8,fbf6fcef,428cc301,b314ef41) -,S(6b5d6210,f98aee61,df36d7f1,9546efe9,166e88cc,6492183,379dd1b5,cb9e681f,dbfb1748,59c88a6b,72c8afca,830045c2,7c6de87a,c47228e7,7f246e6f,698a0d76) -,S(88744d04,e8c7842b,68d2cc9e,f58977cc,548768db,48d3c286,49ecd0a,22300c97,84573aa5,1ea3c51e,5a0b0e42,5c7c90b6,149d2993,91085bc0,393f58a2,8fb9c38c) -,S(fdf2c824,40f2ac58,19b06571,216ad938,d0218ba5,be4d3d4b,ada80e32,c32e37c8,c2abc4b5,9e961ffb,e48c6f20,58602dfd,9172031a,740668b5,5876d5aa,5d538f74) -,S(4d2fdf64,1f5a883b,322273bd,24755405,15178ce0,9b4ce8a9,36648957,ef777559,22ba1d01,210bf31c,6421b89b,9b3217ae,b2837f01,c344a9fa,bed0b385,4aa41b11) -,S(ec7cbca1,e743bfdf,81af3fae,a5c64a8f,5a54dccc,2afca269,9c461592,34ddc633,9f193da9,ea76a050,7b528c05,e5a10107,dc5263e4,98fcee29,5f57816e,4eab0917) -,S(ff2fa113,771998b8,b801e779,3cb804c,da9cd6df,9d371943,c7fabbc0,44b44fdf,962127f2,1ac57670,c79d966d,b8cd6f0a,2aec6824,22cac54,23746bcb,2df6093c) -,S(6d1b406b,2dfb02d2,34ec21be,c436d6af,4fd418c9,29f175ee,6475e77a,8a57580,b8945668,9dba8e2f,8f0693d6,d3e7b602,f157efe5,38b9ef07,b2dea23d,bce895eb) -,S(4abb9dfb,449e00ce,46476727,dc6b96,317bff7,74c21df5,87bef539,644d7963,6086f2b7,c016c69b,2ad80786,89af1c98,4d6dbba8,7545d8e4,9c2c58bd,f86e6407) -,S(db0c51cc,634a4096,374b0b89,5584a3ca,2fb3bea4,fd0ee236,1f8db63a,650fcee6,7ec0bd2b,aea1ae18,4bd16fd3,97b0e64d,5d28257f,85836486,367fe33c,c5b6e6a0) -,S(ae6f6dbc,d0664919,a65e02ed,646de704,6996a382,21aa8e74,4954d22c,37fdb287,abe70eae,f8ae7404,11931379,19f9102e,c5bbb2f5,f5fefd1b,b76fb6a1,c3f2f201) -,S(aea3eb97,cb321f30,bd0771a9,17fc9770,f4079a62,fac51fda,63dd3ac8,d35f6227,b6a53416,398515c5,e9133704,a287dfdf,878145a1,4416b525,6f1ae46,6abf39b6) -,S(90c9f8cf,711d50de,81f7234e,f6c13af8,39355c06,3e891ded,51bca1c,852233be,8d95778,18f19649,f2d3d452,81358783,17d2c32e,aa01551e,d7fe21c8,3421bff5) -,S(5ad7ece5,ab1d0344,5528dcde,34b48efe,fd954aab,920260e2,1495ed8c,86d976e0,2df2163b,2c3c63ab,bef274e9,3c46b6e0,62ac9444,b17843d8,70014b03,f78569b0) -,S(b6ba2e2c,8e942ef0,16e6d3ee,13ab0cac,1d80ae7d,588a831c,b7844e8e,3bd28d9a,41180a35,f923dfdf,501b6b06,7d241160,a2ebf453,d00b501d,855ddb7,1bef7fb4) -,S(7e409bc9,bba26c7d,fabdd450,bc84589c,799555a9,c6809cc4,13a4c674,7ff5f37d,c518961,9cc5afe2,e41c4260,481d8fdf,6066b034,19fe030c,e423dee7,79c9e6b1) -,S(9486cd14,70b2f2ee,28d01060,6c7c4c22,2c72636a,a50b64e0,3008516e,de4f602c,886ccb8c,fc5b006f,df931785,f732367e,c062e9a3,49f452ce,aacfb74b,deb467af) -,S(e7c11d7b,c8b07205,1e1af6d8,745ba05e,94b1ee9c,5482d83b,1af9ed8b,21338d2a,fdc4d293,828cab1e,fc9062aa,192f35a9,6ad4683d,797fcf79,c74852de,d75c8e50) -,S(dfe627b,ff315cb0,1b1b67b2,776ded35,19b1a85d,8e802217,c98000f0,93d50bcd,993c55eb,bb65087b,6fdd2480,c9d68e6b,ea0f69d1,b95efc28,5f32a8ee,55f9e773) -,S(a0f0cc17,fd00a2cb,5fc7c981,860f02f3,eb31c26d,54841dde,189eac65,a446f516,bfae884c,31d58a3b,f11077a7,d3edd37e,14bbe4ea,bd30fa74,ff5c295e,4b3b8969) -,S(c1dbb6bc,bc14286e,d6eef926,c946b52b,d37e7f53,91fe1dd9,dd7b72ba,a3e37338,67b02d87,bd336882,f4b6fdc8,1a3a88d7,aa5e2735,139e1bd0,e793e6a6,12df7bf0) -,S(20b9065b,c7d495c4,c92cb1f0,6eedf5ef,7025511,10343eeb,e82505bc,bb4bebb2,a6987316,5c231d92,bd21a4f9,60242d9,4fec71a7,4b24fbd,55d51246,10756835) -,S(7bedfdd0,c4d8c38,dda9544d,38fc8786,55ab9a66,4f8dbf2e,3c54810,eda69190,9994f0b0,d4f52de,6ead0049,172fee05,365556e5,3c9d4591,690715a6,f8af77a1) -,S(26762eaf,997983f6,ac63815b,720e97cb,5adcadd2,419d368,df4d385e,6b5918e0,81f5448c,e11b4dbc,24be2e9,be5620fd,25f0c0d6,76aae549,2792188d,5a27e6be) -,S(7148cae7,ee18e152,c3354ff5,dda86e13,ea14f175,92d0d3d9,a944f4cd,f387bb79,bdb35fa,f6f86e90,41465efe,dac6bc0e,ffd42a0b,eee83365,93dcb4de,2310b18d) -,S(27e45dd9,33ae2c33,a69ae00b,156845b5,bb4d8f06,593c2723,5038ce17,87bdbc90,a2bce33f,a93579a3,f8d9c75c,9271a2b1,7dfe36a0,590f2db1,f7cabfd6,51801ac9) -,S(af0c7215,5b28ae8c,2a2d79c7,d81e603c,d0539c11,fed2aa98,fa2bf2b2,d7d6b7d7,ae6bdfcf,a25109c0,b80bfc,71cfac3e,3b5b26e1,e4f2c856,40d2c69a,a7ac41f9) -,S(7b63c408,d4f8d34f,314e609b,21e8e372,de0f5a19,1accabec,7ecfe02a,63cbabf4,aa08009a,78fa96bd,8ceb6f65,e88859b6,236925d0,bccba7c,e0db29be,94f16327) -,S(ab768853,14f3e88b,d63cffb6,8f4f3232,4f4b4801,41aeff93,94d58f9b,85c6890c,1a71c833,d6d96bc1,c33610e,d7ff1481,c9ff9841,157c59e0,5d3a036f,cf7f192c) -,S(641437f0,7ad75112,f8375487,cc0ed859,ccd308da,4b25e5a9,953e351c,9e3bd32e,3c58f7e6,b255346a,f50f1ba8,3f008662,7d2ec950,84c326b0,ccc3a388,81a9b131) -,S(f532fd2d,600ed478,c1dcceaf,fd01ae87,60f7ecc8,7739580b,9b4a7649,67a082cb,7393514c,71117d7f,7cdbb4d6,c803c9f3,221847ad,697c945e,440bcfa1,1285fa96) -,S(33679959,2c4bab44,d89e6f60,8f882938,db73dbd4,75f0dc3e,e1fbd075,b1c7631,4c1f8004,6fe89cf3,6d078251,5ff57cde,17125d62,5cf675aa,1fd70163,49694fbc) -,S(e184c16d,2a34ca57,b06b5396,28cac285,6f18b7e0,32970a5b,e2221a07,be56c9cb,7dffc17b,51ef9c4d,f16ab068,8c66df57,d646cd34,46b509c7,7f85e03d,e2c5bf73) -,S(f8a97d16,2fb49d55,bb8de990,9a20c1e3,4f6ce6d6,efb8c68f,e26c884,6415d419,3cd3cc53,4dbfca01,9492e161,61f2e86c,5f20a83a,866874a7,ded4c2e4,42061146) -,S(9eb6aa2f,6c6ad821,d46dd612,38d3dc53,28cfc406,ad71964e,b32de0ea,12475781,14501a83,79d32e09,3664ce34,1a419b28,53dfe3e8,fbc204af,cb33e347,6c45c299) -,S(ebc2566a,68e68955,e1e42740,323fd401,7c40315f,ceba7642,5f887a3c,3602668a,75e8109,96ff56e2,655f9f85,ae9ec9a5,fab3bdc1,42ef063a,a06931e4,d4c7ea39) -,S(55646438,a966ce5c,2fa5b29d,ba4840cb,ab9c5e4b,4074a9fd,674b7eb2,f52bc392,34631a86,76034a89,cfc3f68a,45cd52e6,2987d80c,e9a8e28f,a37020f,981c8d66) -,S(b87f8309,befb81f3,313257b8,c7dd914c,82eff5d,6729f2e7,eceb0337,7b16575e,bea66832,59e4002d,6fbdf03f,b80bec1b,eda5e1c2,cc55c630,deedb7fd,a96ea298) -,S(45957585,b440d63e,acf598b2,16e435e,24b6cf15,2892c8d7,953471df,70a0a93e,f4cb6260,776a4f4f,23ac366a,565067fb,b29739fc,233493a0,b3eaaea,c4b71427) -,S(2c90f64c,8d9c42bb,1824c821,8f9cc057,3fe8d648,b960ee11,1487bbe4,9648ca87,829bcd57,ac643cb6,9f000a9,f22fcf57,69bebf7d,6b1d8ab4,da21be41,d3c25a8a) -,S(eb327ac7,779c9abd,9546a3fc,c7731729,2e753912,2ba9f7be,36db0548,144b5efe,21ac2c85,8d2fcd38,8c32c594,d6e74803,2cbbf365,238565a0,8c439190,518c9435) -,S(95ec7e2,272ccca7,aa2b07fd,d37d0f08,daa35418,1ae30e6a,dba0cb1d,2c6d007d,733786ef,59df6050,552ac913,c10b8890,2d589e7e,4f740f33,75f78fc5,2ba12b5f) -,S(4b7a6698,8b4fa080,f27c845d,7ff17371,91104a29,2c6195f5,fc367c69,fc0cbbd1,8b043bd0,a3605612,87b38fd4,d99b29e4,8e52494d,8241207c,9284581b,63a85b8f) -,S(89b2c58b,6df581df,352ab28a,619027c0,a9233792,fc6525e7,47dabd31,a342e6b2,300b1b34,d459e65b,e265edea,203b74bc,9b053feb,888e81f4,10045a10,d7f53a2b) -,S(41099b5d,9f6a28d0,e4a7ff0d,b75ec487,1c926327,89f0c800,7ada8114,9bc43cf1,2a0aba96,2e2b92b6,e949253b,e06588d1,3e07919a,3594b26,995c15b7,7a62cae5) -,S(bcb0fc64,9ec508c3,507396b2,9a663555,8825ea9c,1389c817,af7fd616,7229be4,168c7992,cf3bf5ab,6c3a12ae,922e647,13664db9,2d7bfe5c,2c746933,3a07d606) -,S(7a3fc958,5a6256af,9e314ca7,55a8096,9cd3b3d6,f70349a5,ec719cd,ed8b762e,fe8b280c,29cd0716,35288526,b7179d90,dadecd78,39128f22,17d445cb,d3df1346) -,S(377093e1,b968a35e,e0f229e1,e656da9a,7583c1e6,d06fe1,c89e3f06,61a8176a,e7c0860d,f6c9f461,7e6a4dd0,b8c0d800,6aba8e88,20aeb82,e6e0f8a0,c2c601d9) -,S(c5eff3da,f4a5cccc,f1f27a93,361301a1,919b1dd2,5a98ea37,5ba63f14,4aafecd8,34e11634,26f983dc,18c8a02c,2222c2fd,a94129f,4e3f1d67,f424964c,dcb97a1c) -,S(fc7919,eb560d33,44230f72,8368afcb,3c0fa6f1,52ec54e9,84ea9ccb,e63ffb27,1c7d3782,af766ff9,bc1cb838,8e4a7dd0,a04bc4ce,adad3fa9,4132842a,9859a6b3) -,S(2783d7fb,49386d72,54434cd6,edc6f46f,b3118322,43d381c6,287d8b24,861ca5bd,a3aaf271,b806ac0,e3c45026,28f89c79,e4c68574,81710111,a9316e38,c7fa5c70) -,S(7407a478,68d4e0d0,f77f8949,5e5bbf95,88f54a6f,fd35d229,8ad4b30f,2d8a02f3,1250d562,96e18cb0,aa5b393e,a933297e,debf3d94,59ac1ce,24cc11b5,87fdec9c) -,S(c2d2cce3,2940ecda,77ac108e,71544079,c5899fa4,f8461df6,cc54dd21,a861a321,f0beb1fa,40bb8071,928b05e3,ecc8545b,a919eaa,e830db72,9e6de85b,f05a1909) -,S(8cf6b189,c5051956,6a94e1f5,ab5e9530,d459a935,4cb13eb,349fac3e,ade8a56f,bf6a9d70,32e52886,ce6d06d3,b22d47a8,327aa788,1621338c,1606054b,cfcf9c96) -,S(d6b07586,ed9f8471,f96ac5f,53277d1e,2deeaa2b,7fd09d51,ece6766d,29a94968,dab4d4b4,ce5655cf,4aef0d0d,5e3fa292,2f79041e,d2e23c9c,75be83f5,f09c5326) -,S(a720b733,60a03edf,f33a0921,90795834,9e661d33,44da800f,b857227b,ef4d647,1f213c6a,721c2d82,6037e3a5,a0f4867f,13d79dff,bd44f5b1,1bb5c0b5,4884ea63) -,S(558a5698,3b03c6c6,717db862,e59dd075,b39f9ba2,ca01b0ac,95a69cec,1f3a5ff7,7e07c752,db21b68b,21738458,a045fc60,fe3ae869,887fd557,92ecc6c7,d4ffb1a4) -,S(b927dfc3,278668a8,c5329941,f11d0e0a,a7c2d9d7,f8d6c263,9cab5550,10e14ca4,3ce83725,9954227b,b420e35f,77705225,72f4d854,999af552,4b8795c2,b723388c) -,S(2b70d499,1085aff5,88e23ed5,ab55a374,3c35f71c,651c0165,13f98ecc,4f0e6da8,df413b4d,aa1e5c9c,a2398469,7d82762f,a701413,1cae25cd,1a94f02a,506a8b06) -,S(b8836cdc,f72f6e00,99a9181d,94ba77e9,e1368e54,a62e1144,1421f2ef,2daefe56,9ad452f,e31f26d,cad7014b,68ceaeb6,1beecaa,5394c359,afa52209,e50427ce) -,S(252b297b,65f0e23a,9788b48,f33809a,ec66b445,cd90db00,4dcb6a80,c4af93a7,8cc4e0c4,3c346211,736a3bcf,c24a58bf,9f77c7d0,c53350e8,6cb0de2,60916838) -,S(9f3d30ca,1c15cc66,8efd5fa0,3d6b7bdb,d34f2704,cd729892,aad9171c,debe6330,448b6434,f95ee7a,bc056974,f1476171,353d9b98,4e22057b,38662327,b23211b0) -,S(8225e16e,5bc9add9,ff8a771b,5bc7bce1,653b545e,4e54b9e6,6e2d2985,2fd35e49,6254c5e3,aaefa2c1,6ca4e1de,87f09d94,df836b9d,d100612c,7174aa75,7d0570fa) -,S(a7dcee48,4d6e99b1,b72a80b7,4de255b1,74f4767,4d3c5799,4669ca6,aad02ebe,1d6f0cfa,76a2901f,4861f541,bef7a948,78586178,8c7c42a4,2db583ba,1c170a7) -,S(a91445a8,5d4ce90e,98d3372f,d2c664b8,9a6baa2b,a396fd1e,210e315e,809976b4,adc4c68b,99b072b1,b51d1512,cd94007c,72deacf9,4e7c5449,f1d83876,78b1d100) -,S(7462c9ce,907c9655,75c41096,3510e00f,6f6ea6ad,886cdc79,ed685ee2,2a7ce1f1,4ffa41c5,f02c2299,c42df5ac,79cc4140,47a854e8,332f8f2a,e67ffa20,bb71c7df) -,S(d42895f3,dea495bd,af8e36bb,6a79f234,dfd85544,965a8506,5d38ca86,28cd4f40,2fedeb18,13a11c42,e7869b20,7bb8486c,9821710f,a80d9bbd,59c92ae0,b50d9cf5) -,S(ef9b6b62,ce85588a,f13434b2,7ef53d12,e8291e6d,76a65669,c29d99a1,4d388adc,159f5fcf,9af0c962,ed907955,e91407ca,80261255,45b6938a,db18aee0,9bbf912f) -,S(4003f1a0,bc659daf,df5fb7bd,bc96afff,92877c7e,2a693f39,2afb06c8,fdbc9f32,ebffcaa1,7458f0b0,28ff1dcb,74be865d,7faeafa6,c2707cc9,ea685eb5,7961fef9) -,S(4390488b,6b03d851,648786f0,7486f5cd,aa9ae1d9,4867de,bed7036a,6ac09a8b,78329de5,a10db56b,1c35b88a,21ddf393,452001c1,29a0bd6e,5dd76a63,8682f07a) -,S(ae6da0d2,9ea3fb66,b6006c56,5dff8b41,6074ee16,f9ff86b9,60574067,abfadea1,74caaa63,dd012a63,e76f0916,f370614e,29e3f01e,b88b49c0,5ca33234,c11cdac7) -,S(78f879df,98614721,b7c65652,4e806f6,35942e0,950514fb,2fad8a86,bbcfc72a,4194e58c,478ae80b,fab661b7,ffb85cc7,2318aad3,88d61c68,a755296d,38281ac6) -,S(80684365,4f41b0c6,d6cd51cc,838355dc,352e028,7b1c1d1d,edd2f96e,5fc97e01,8b0c223f,13c61b4e,1e141a0d,35f29a7,7546bc7e,3b1e5c45,262033eb,92b62461) -,S(29509d9f,4fd975f4,6efd1169,1d97d0aa,f83b5934,9c797010,5cb3908,4b87466c,1477eb75,69a0af96,c9cfccbe,135e3c86,a33de585,2ead38da,8a0eba6a,6d0da81) -,S(191d1443,3d9c722f,c1532fe,33c63a9c,4e3d5741,6ebf799c,2d8ffeae,df1dfa4a,5bd00409,b6b571ad,745ecf83,91884eed,a5e3c7b6,65ec9706,eae4b4dd,703a2cd8) -,S(2843d42e,d2738168,5eed65af,eea82bf2,a50f0e1e,3db201e1,ebf8b159,1b0155a8,807cea66,c0fa9f53,b47e6e2c,232cb225,77edafb8,99a6f98,ff87d091,bbc63ee8) -,S(5568b7b0,9656d36f,5347514b,8e8212f8,e96ed02d,4516c018,4d653bd1,2bc8f644,5b44eba6,54836dc4,3fbda30d,7ea36406,4960459b,a4128911,8b2d8638,50e60d87) -,S(5b84e0e0,809e44a6,9e8d81ab,595b32f8,4a7dd421,c073fd6e,5f38ec5e,b145e803,1a65a2d0,fa791ced,72fa1522,ae431155,7e6109c0,fe934243,cb43d3ef,ad13d398) -,S(ef42c56b,dd241071,47e1519a,18d32910,675ba842,92cc8ede,900a64ea,bedfa672,70151747,33359977,611e0c25,4addbf6b,26a618a2,31474e3c,c9e7bcd3,8bff75ac) -,S(48dff2dc,b50d4a56,4be6ed00,3b1415b4,adc653ec,87eae94c,92b7c129,5656eb63,a9be97fb,53afecf6,f0bc59e9,8bfad542,fa29e63d,f701f6b5,f0f66081,8d643928) -,S(672e90f5,246ad174,10c9a2df,c22b098c,d1923bd4,19fdc337,f881e4fb,4ae938d4,73fd3380,1fda6db6,883e678b,31e5f09e,f331b624,5617ec9e,97aa28b9,a1781f19) -,S(59cdb9b1,71fb819c,909e094a,95dc15de,dbfe5521,4a7cb723,ee7cb761,4b315cde,55ac212,670b4a63,ecf3f8e7,3082009d,7f2d38d9,e490ca18,7a6db01b,e88351a2) -,S(5ce38d0a,357a58ab,134db879,b99994c4,6b827f82,8e1ce8f0,43108de,ad2ddb18,5e816202,d9c1d86e,c2f84b33,ddbcc51b,94748c67,1089c9c1,745a14d9,3b97f716) -,S(c982196a,7466fbbb,b0e27a94,b6af926,c1a74d5a,d07128c8,2824a11b,5398afda,7a91f9ea,e64438af,b9ce6448,a1c133db,2d8fb925,4e4546b6,f001637d,50901f55) -,S(383cb084,79e61bec,dca81d29,7796d00f,60bfbcc2,83c83d31,725f5329,839ec818,26e26fa2,49008933,8bde0498,15f34d9,bbc3426,ad8644ff,db1a190f,79dec91e) -,S(e6945731,2ad4f14a,71917b52,448011df,28b88c9b,6ac84550,248ca4fd,102f612b,30ed2082,51fc701e,5ebeddda,c9eb0b44,c81cc86f,9706889c,1b1c3386,4d76f53d) -,S(2d0071ba,8f799352,212168d2,1262a729,250809f2,24fa58a7,f283c4c6,bb9976f7,cdca6901,4e4873f1,16945544,800079d,ccc118f1,a5709b03,c872b017,5f1dfd8b) -,S(c82b9457,65b74fbf,91cf35f0,679877b9,da35c2b0,8437d789,8d748f22,1e927e,2e504dd1,bb06bfc,7e057dae,9aac8f07,b57a0f2a,39b1533d,9313d9f2,45fd6a2) -,S(9c1a4c2e,7eac21a9,fed135ed,e737dd19,2654eda2,fb3a4227,63cb6328,75bbf0a6,f3134b6c,12f71c58,226c9128,9b7b5a06,80eb6646,e9da2e60,20008efe,10e9197f) -,S(971d3d9b,bc693222,ed8bd645,e80b7cf9,9b170a36,2d57753b,6a2ac27e,8d6c9b28,d63d49a,e296dc2c,6c4a73af,7fc5e86d,e2039433,f3858980,80a36f7f,91d22e2e) -,S(f5493a73,86bc1151,23f29f2a,e0619e05,660a317a,bf5ac23f,a67802fa,8b917d2b,e6adbccb,8b780530,2b305157,b427b8b5,38455e02,80133e23,9642306e,65e0f1d7) -,S(831f123e,500e0a0a,e497a321,5ebde2ad,763244fd,40b386da,dde05537,99b6e014,35616862,2ff588ac,552fa508,ceef5ef9,ac04af0a,9db6b950,f44719c8,cb221d6c) -,S(9b8ce06d,18474c,3394c334,2ef385d6,7a338c22,98e92975,f1728c87,897cfb35,76940220,b8dc3e04,7cda50c4,c1f53747,7ce8757,a4a3731d,712cea05,42a40d72) -,S(f70a916b,a98d2bc9,60172410,42bf3e14,14f06cad,dffa7cb,1e8137a7,3fc5b855,f1b8c1f4,70d7896f,f39a3fbe,997a88f3,b5426d84,43c4023f,ff98fffb,280275a2) -,S(2d2ab7bb,c44e7fe4,ab283661,2f621d05,a64d6909,fd94e599,92d52afa,c0763d56,53450e00,2a6991c8,68fe044e,8b61c2d3,c5fec8af,3605728a,e57d32cc,c55328e8) -,S(8178deb8,c516978c,ea25423f,3a913157,321ff7c5,5d8058f3,dc9b9d46,f4d10005,16a71b2b,46c9d303,f4ae6a28,235249bd,f9c00146,a26b6bfb,5983bfb6,8d6ff4bc) -,S(b470bb76,d012ba7e,67ef9c32,add59940,1f700ca,16003011,26e6a692,36b56a64,f7d093e0,7d179861,871f36f1,58d26987,1775f082,a2fbfa69,27cc2272,614fd95c) -,S(164f2aba,837cac12,19b48eb3,30f02141,d3a89921,1cdb3f78,fe17133f,e2de29ce,3bc05608,95f7d034,4a9ec79e,b821c06,c2837c50,66925197,2c076374,871d28dc) -,S(c77a3a04,2a86d2e,f512268b,35cbb89d,e6a210ea,883e2283,ec59fec5,12e725f4,2ebcd56b,edf1a07f,e587e592,8ed602b3,6d1db4e2,5b49e914,8dc9eedc,131cfba2) -,S(e2defa1,f714cf71,557a3f1d,71c6abe8,11df5504,da38e9f,60ad335,3b11349,5ed64303,7a53bbc7,2f41912e,a657d944,c5107da,3b9ab54b,d88b545a,e045f229) -,S(ee2d12cb,b4cd9e4c,163fca1e,5a4330af,35280ce9,cc1d57b2,d2112443,b6313e3c,e28b1dc1,a4377c65,838ecafa,bfffb696,4057fb6f,dd4baf08,49f9223a,ee153262) -,S(4392c96,73e6deca,f3c39c34,f5be7c3d,a2109b45,2271467c,78f256d6,7d9e28bd,7fe4c183,ae352533,b049edd5,343a6bb4,747d63d7,d0f406fd,5902a886,110c50) -,S(5972e2ee,167374ad,93a655f1,6008f49a,f5586b2,f81197a6,712ff31c,a0d6960,6d70fc55,d0a57c74,8a2e485a,d903bd72,779343fc,7c090847,bc3dec1a,6f7c71d6) -,S(a85d800a,fc2c0315,889f1faa,29e5766a,a180f31a,400e3c19,85589af0,302c78aa,7429d7f4,903c76a0,a4437b41,92865b7a,ff5aca7a,52dd32a5,8f8b00d,b97ec85e) -,S(c9836b0f,d594fcc,9a89e85d,7d506386,ccee3f38,72759cdc,9548569f,a5f1c245,9f0b1926,93b7fed6,2f1a7d06,fd716727,bed1c2c5,9bb431ed,943b7082,d094fac0) -,S(ca2184fd,b2b84654,d0348e5f,6d963193,75f2c441,ae64622b,588cae7f,d202bd3b,d1222820,3d657aac,493dbb2,fe9729b9,e2563cc8,1f671626,83c4f0fd,726a4de9) -,S(9e0515c6,3c9b9664,8762704,80605d56,b5dea0cc,c7a4c66b,44a2e605,36941fd8,29de3224,a2eb2d86,afef789e,2dba061e,95f0b762,117ede50,6d4b21c9,54be831a) -,S(42042c25,33203a7f,c22cf7a,fa5f3d79,8a3447da,51d66f60,53a8f000,af5dc1cc,f075a67a,6d6c3872,315420d5,bc13d13,c54f3c1d,61f73d9d,ff688da7,f5e6c05a) -,S(6645a1bd,4eab02be,45884ffd,288955fe,3f5a68ca,9ae431bc,cd3967c7,12295b96,231f79f9,1d264ed4,28ed4b30,f0e92c4c,bf902865,24050b67,30cccd12,bb84cfad) -,S(4e281e6d,2c316e88,231482ab,1587de37,6898f3a8,870f475f,30bd1ee8,d4b32f9f,f48cadc8,1c119edd,e5f78062,cddc3416,c3f708d5,f37e4910,11ef7581,c065602c) -,S(77236414,96e41e9f,f13c7ffb,c7a66203,4fbaf7d3,e432ce02,fcd54ef0,4aaf5136,222e0174,d6cc01e,fb4b4bf2,9000f697,98bec7a0,657f328c,80083074,242dd218) -,S(3f2b704c,8d467859,ada6070c,b1221840,18ab009f,f7b5ebdd,af31d977,dd45860,a47167a5,146aeb5e,8c38dd21,5d61a2df,e2b6ab8b,fd05ea9f,b59faea8,3b4dd88a) -,S(794ec130,d243d811,2ebb70f0,35f983db,84b3acd0,ae4c5b51,640b9e92,ecad4146,49edecbe,95c25c7c,eeca537f,937aef5c,658f2dd5,d8c0de71,c80777aa,d07be84d) -,S(750ff9ec,e363e12b,79b04cf4,a7b1c0b1,49c554cd,6e9fe3ba,808c9614,95a96aa3,5a28269d,d1c5a3ed,f4e70f14,9a060b42,2d4474bf,1e4c6dfb,2de1502f,7a1d59a9) -,S(d65c05d7,df6668ec,b96c9ec1,fd129462,263b082c,9b7f4169,6335fb2a,b66272cf,d7728c5,1c10d42d,242cc5b7,fc77fdad,7e48be06,6b2f7c37,891ba4f0,de188839) -,S(d3804cb6,8cb2e9e9,b5b9d270,db9a172,aecffe39,72a3d2f6,1225bef5,595190c3,11fb350c,9568648b,30af4131,46053428,2879023e,6ff0d613,482c2471,b5e30d5e) -,S(f762de26,35c6349f,6cc95c61,9ecf8d37,6a938241,1106db3d,b34e9e84,70351bf6,dc67f9e0,c8a50f9e,e753352d,a99112e4,ccfe22d,3e88410b,1cadc0ba,bc9fd814) -,S(ab18b4bf,a827ff4b,17ee163e,d17e3927,d7dcecee,ba87ce7d,ac5e5767,53b87a71,6db83bd5,73e40926,c882bc09,c4d07f72,29706d1c,d2b1ded5,b57ea9b9,2b0da919) -,S(f754c248,fec21ae8,da343a87,459622a,b12478ad,8f63ad8b,f5c66695,198c95e,2cfb76a2,5f9c8776,b848d8e6,7f544774,e056ca7a,32bbae52,93b27992,6052b1bd) -,S(f8d9473e,3c3f0798,f893ecdb,716bca16,103516c3,1341c8e2,c2462d4f,9a46c51c,55f0065f,a422fe3a,26b314da,c7547835,5c53bd3b,e11b4686,9e05be92,d7924e02) -,S(8639942,d294cbc8,9a75fa22,5b29fda9,2f7c5ab4,bfbc4395,352d050d,754eb741,3913ea2a,445de35a,36d79abd,db3ed7cf,741da883,4cb81c29,6779d8a9,e7d11e4d) -,S(2a588c6c,706a388b,f1719230,b5a71b4a,6857282,83aec61,794d1a78,bb95d5c2,af25ed77,1a56f6d9,6407f07e,a7e11f97,61f458ae,bfbb1b00,96842c4b,6cc47592) -,S(137bd1ee,8931b9a8,b26dba4a,d9a5edb0,a5459717,22e1fe3,37ee8d54,20a0cb6,cde9fb7b,8197c77d,273e9f0e,e87d76a1,eaea105e,21154b7f,f5848a30,17ceea62) -,S(46580345,c686313c,97152371,13af2c2a,f9b5fea,a1e0bb48,d21bbe32,d2de2bbf,75bc5d7b,b6329ffb,2bfbc79d,b66f4c2a,7edade8e,a16bb051,a3a8ee9,ec92ef64) -,S(4a149252,afaf5acd,982fc491,c26af545,2ef93d6,1b282a85,56d5ef64,391bd233,fbc100bc,10b55b60,96656ea3,863f5d4b,bb9e83fc,5a25e59a,3b53d78f,60cfe285) -,S(894ebda6,fc0bcf8f,e025131,3475d64b,95bdf089,7d9753fa,ad0f92f2,15a01f18,b25f3150,155772cf,c69d0251,97d37ae0,1e4ede02,e2994377,9fae26cf,5f5ec056) -,S(e70d8a93,a91b891,30def1b2,bfd720ac,2deedca6,f9e5a85a,3c2a6eae,45eb032e,bd3aee53,a3b0ff6b,45fb96ea,4911cb02,fe102681,878a1b0a,693fdf11,4cd9f9cc) -,S(7cb1fdc3,e5ccb1dd,4a16765b,f9546b6a,1189883f,135d447e,eb245fbb,4eb36852,90ee0d6,becf5ff7,b80edbe1,75dbf258,d1889008,a8fed4e0,1968e2ca,8fca582d) -,S(51278ad8,331da17,8fc90a21,432b9058,b39f57d0,31210685,bf9bfbc2,87b9bfc1,5aaf547,f39ce678,8c3ad759,b25db3e5,7bc1f9e1,f75bc040,536ddce9,d3a66b6f) -,S(f0eeaa1f,c52b3068,48b56308,22fcf0f3,fee5008,54e276ce,e9fe9904,54f59cdd,90ff89b,944d70bd,eb5e5e01,6afbeb30,d51cf7fa,81182e63,ab3bb2c9,f2124f02) -,S(36fc9bf2,8bf90fd2,613670c2,27b51c00,df5b4caf,252b5df6,648ddb6b,3aeea71,887c3876,f1ac6c28,606c8161,4ddbbbe7,d975ecc6,9fd9075e,13d0e3a3,e7836683) -,S(6e31e26b,cf9436c,e14d2d04,1c29f62e,135c549d,5e65bacd,ba4df2a8,9b91b68b,2389684,9e63bdaa,b5f7d9f7,7a778b31,94c1af87,d09a9a85,85896188,acd0e7ae) -,S(c5044649,a4b1c2bf,ac6a8a1c,ead33aa0,3da9fad8,4f742eac,35792672,1d98e864,6d2602d2,83e696bb,717d1327,cc1143b,45fdc84d,b8d400af,537b201d,a7a1027b) -,S(a933e71,f13c44d5,bda8e963,b5a007bb,b9b2e84c,c45211e6,eca804ec,6a99ca28,931bf3bc,ec45e2f6,e6571207,31d42fdc,c3ce0279,542114f5,c1c0f659,f6200faa) -,S(9003f61d,840c2d62,1ba98884,e117038b,b8559d0,b132a1aa,83adf65d,f8e4a58b,50c75124,f72b3952,9feb7ece,cba26854,1388a1ac,73631532,b67f56dc,e8d30895) -,S(fc807c18,3cb370cc,8638abdf,c17281a6,914e21a9,e9f3e2c5,33fb7c37,caa0a886,3ac79d3e,75ac1d5b,a9af7263,9d564256,1ccf6fd0,6b8d2cde,e9d24a1b,e8af00ba) -,S(3d072ae4,aca4ac23,b43b608f,150bcd4b,cd780dae,7e4073c1,86293cce,dfee9cbd,6d9e443,f721c9f8,a98fc563,8d7627,f9c60414,67da3857,92fd55d2,7e65d9b6) -,S(d0cb8594,7061b4a7,d2bc5eed,522faf8b,ba6e26bc,7acb1d3d,106aabd9,a7f80dc0,fbfd0f26,e9d0dcc1,a0107b82,d1a9876b,8d7562f1,41f0892c,9b739e47,7b012e0a) -,S(e4edc0ab,6416c644,1e59f46c,c7221cc0,267aadac,242cee32,41a6d25b,635bc9fd,f41c3ae9,cea7b4c4,4834482,980807d1,c496fd4e,bb06964,b84c1fc3,4fcdc71e) -,S(6233b50b,2d3d9101,8f5a83c8,84be0f5e,ffb80641,1b0b5271,557d32ab,dd7eb4b2,8dfaad24,ffdd2ac2,5770f21e,328588b1,34a3a2b,dda40399,7911ef19,855dbcc5) -,S(6ca00162,e27265e2,27b4e544,7e981f6b,c427e65e,bde295df,9434b7dc,52a19ab5,d33f5f63,a8f227e0,a43fe297,babb3a07,223e8916,e153a5c,e0f57e65,1154cce1) -,S(c01205aa,5d2a8d5d,c0d328ae,7ce7cb16,d6c9d992,8b6105b3,cd68666e,36fefcfc,b65e5f99,c4f48095,e1bd6f6f,6af8ba7e,cf2988ab,ffa9bb45,3ad01859,e831d3e) -,S(e3965393,e6268cb,61d6fb19,58050f39,7b8a597,4a6c4abb,4e0b78d2,dae0e155,1f78ad46,2ed6e1d9,18004892,85383b2c,3f971fa5,cda0c828,a2f289bf,80731737) -,S(27bfd0f3,702a9d43,50c1a6,9fd990fd,3dc03af8,50bd84f8,1248222,6cb099ce,22e16b60,e8caaebd,19b0c0bc,e40be7c0,c49fd3f0,d9094f39,fec1b1c,bc643de8) -,S(8210fbc0,23319565,9eec1777,12997a89,2a37172c,6f75e3c6,cbf080a0,6f96a2f0,1ddd7792,101166cb,bb11d552,85e1eeb3,bfacbb25,6d1a5097,16dea91e,46afee8d) -,S(15cc66b6,5fcbbd80,df15298a,25e2ff80,ae4d5065,f8befab0,89cd21a7,4e347b5e,944b47e9,35748296,deb324c9,f5616d28,7b225b34,488fb34b,6ddacd32,7937c97) -,S(eb7b7aa2,45960169,1ea1a482,a9e6c35e,c7bb08fc,726c2c4b,ff801ae0,94c97976,4d2e9570,cc187791,fcbd20e9,3f0656a,f5596f4e,104c3f2,27c23f82,2ed1b1f6) -,S(4598fafc,ed29e844,c22436e0,996a8469,18e7c106,b40a5ea1,5fb0e7df,5e9ba12c,e73d96b6,d292ea2c,39779dfe,7f716609,978a8555,e5b09629,7dce228f,f35e6093) -,S(49835a86,3612e594,572a2591,76f90e18,e57d4dfc,1910c705,8e37eeb3,1a8600f7,3b7613a,fbd2cc1,cc23b147,e0e80d36,464c08a2,e488d7b9,8250ed37,dfcfa531) -,S(3a6d6fed,1fcc8067,32a3177b,4dbdc33,3cbfe0b7,d19305b9,965916f7,ce335351,cc3f3d8a,314d617f,148a6706,d7f10641,11eb2b56,1bd1dd0d,f2986925,5a6624ea) -,S(21208586,6860fe30,ce92d2ef,b2035b74,f672a024,ee7baa78,fb0d6c7b,3ad7a9f5,aaf145be,51b1ec,3fee8be1,1f6e9d73,96ff0ce3,41f25d7c,e1074a09,78bebbb7) -,S(f819132a,c9bb2f09,663d609c,51cb11b9,833ac082,6ceffcc8,67cda04d,266e4e06,b1fde638,ec6a305c,aaffd1a0,6404aeec,c52f48ef,7646abb3,7e227239,4c891de5) -,S(536c05d8,8786640c,43734d72,aed62d9,168385a1,213c4428,423a9437,c2ec009d,7f4be100,d827de18,68bc2b43,c83a08c5,fd84ddee,1fa9ef13,4b489325,db6df0d5) -,S(4328123e,c4c6db76,37ee3ed3,42c8a859,9de2fb1,a39a24bd,650b73ba,a1df722b,81c002ea,1277753,e6a22fa7,1b4f86f5,4ee11f10,f5d5b15,94c9d7e9,63a40857) -,S(f3e156fe,f8529951,86a9e536,f985c1,6a85fc32,d50e9a08,1550da68,112a5f17,91ffd66b,56ff0e6f,65d67e83,c362b853,a2f441ce,7418d091,5d5dd09a,b48892d2) -,S(32ba7359,84e13f42,d2e8a716,a54c40ac,6645a1af,eaf030e6,8242a8d8,8b456cc9,67ffcf1e,1c32b150,a82ab317,8ef24c93,f055765c,9e7e6200,f868b183,bcb4c6f5) -,S(cb9c2b3a,43d105e,518674cf,64d8b4aa,9c868b93,18abbddd,ccabc0ac,59829311,1fc67ef2,233f076b,ded3ac47,99c859d1,834bea5f,bd2bd5db,242607ee,842b691f) -,S(e14f2858,b7bf7070,32349695,e09bcd3b,5effa957,abc19e85,6efa31bd,2e9234f0,3e04e49d,d3f3fd39,883cbc25,80d5ff06,cf8cbf0d,4a895761,f3cd15e4,dce08bdb) -,S(156beb7b,1c27b8e3,cc78113,c97ff026,74810dec,58409e01,d7b7388,87550d82,c711730a,80216ec8,352adf2f,d5939991,3a8e92c6,c16c17b,16e27a91,90bc5371) -,S(de5ea7e6,b9b46864,4b80e495,9a2ddaa1,a24a3399,f8039355,7b798b5b,2c55d600,8901a027,e6a823d2,dc0a9d24,e182cd52,b9b1de67,22b7f7d5,3a03c615,8cd48ee8) -,S(8eddd368,8bfaed46,25b7312e,7b2bf0ec,aea07414,a1281ade,b79b9e3f,ec17c3c7,2db43af9,26171d34,d5ca48a8,9223e57b,59b885b1,5c4f7231,6d8edb6c,7955da7b) -,S(5c971b6a,665ad1de,8fa489ae,22237ed9,87872e0f,ef95eb85,fb2ad3d7,f0b1d4e3,4d71f598,37c2af6f,af32ff7,42ba01d9,aa8d4d7b,302d39a6,c4fc693a,5f8b1f66) -,S(edfb253c,28212b6a,d5b66589,a2a8f1cd,bd3586ef,34254768,85cfb70a,46b9e228,3e5b6608,b7e81f69,b8cb26b8,4f306292,594e42e0,25134c1d,7f7b2a24,b2616c00) -,S(4395f24a,e127772c,db163dd4,e22574bb,d2373cc6,b2c67384,737c56b7,dd525c13,bac6e725,4c800c2c,64896913,df739574,676581dc,1b4447a,819be64c,10103526) -,S(81100ad5,73a766b7,f8913b64,b5f5a87f,8c782353,5f62a3eb,182f0ff1,946866f5,52cac16e,325b0899,9d068f7d,51dd9d5,c6afb8ba,9870a9c9,d28b4170,e9a00c73) -,S(fd3a0551,41168146,6ae358c3,aa14216d,dee3a05e,e5ddee40,7f72347b,eb95120f,2af2f30d,45ceb12a,b89b7b88,b7e04b20,11a3c607,58ce7250,e4c7bcd3,da8ee5b7) -,S(17a55b58,a7eceefa,3ff05b6d,fa17d6c2,76d1a032,abd198fa,4e3fc3ef,e6435ff9,d7273958,a3ad67c1,fdcee72,e71f0536,418f35a4,57e06240,bc99bf71,b9574d4f) -,S(870cb7b8,e2ca5ea0,8c5c73ae,e15e8b22,793fd005,5ed7003b,c49b4089,3b789b6d,c33c8b40,7b701caf,26d7a9bc,e22644a9,4badbec,ad509cc6,a7b0ee04,1be67aa3) -,S(f951c5fc,dc46ef00,adc53c89,a50ca0a7,ffbf7c36,d80e4897,5452cc1b,4e71f8a7,6ae2f821,7849cc24,30864d7d,24df9e59,c1705b92,5792e648,75120738,c792c95f) -,S(aeb8077f,3b92c676,ae11bb06,a18ada3f,6cbd832a,1637ed61,31e4902c,96a0caf1,29f41d1d,f5d4a430,94e75fb9,8bf317ff,6c8a6d7d,b37ccfd,e0232e1e,afcc1e35) -,S(d46f4d97,5d2f2e58,6d18a7e,5d8587c3,8482b78b,595de60c,b9d2035f,313b78f9,95d781aa,3bdc1176,396154ef,31fee42,f704e199,4316e33c,1053491a,e86392f0) -,S(6afb44,4b4bd89f,2e21b54a,c49b9ec3,af810b97,73c76eaf,4f3a5f1c,7a29b201,3502901f,d7d3b4ce,134ed90d,1388ab37,64db460d,bed334e,af061822,6ebf932f) -,S(5f02e582,a38b1703,a7bf6086,9587af5d,e6634954,cfaf8394,932f7ed,ebd86976,a0487cde,92f3a796,b24b06bf,740b8fe2,ccfa5d0c,a2b68a7d,ef46a005,2d7afec2) -,S(26427482,60432ced,5a07b885,f354667f,ad70eb75,9c556e33,c6652d3a,a0599fe,119238fe,2560382f,d76ea737,9340453b,a63867cf,6e044c62,949f858e,b828ce85) -,S(6b2a3e5a,d327adda,52b19a7d,d5e837ed,4f03a5a7,e1e5b7ff,2cd66660,469f91dc,2f9f4526,6b482fa,f336560,1da9e945,354ed265,e8d7e57a,22f04bce,8a54c6d9) -,S(2588b88b,7e214fba,ab10934d,def13e8a,e5fbaf77,d7497dc4,fcc0345c,435daa79,3e5cf90b,d3ba6d4c,8d7f142c,ef1a51da,61ca644f,acba35e1,51ebc114,c5435bbf) -,S(d9484146,92852eef,fa8178b4,a01404a,e4e3d846,c20c3fcb,cff5cff9,de551a93,d5b0fd7f,e628c427,434a1219,6ad99862,13ea0abd,969864cc,dbb8258b,96a6d5a4) -,S(5cf81fdc,3a2f2087,cb64b1c,9b6f4754,5ccc1e78,67cee5eb,9fe9c4ea,3b0de2ff,e0b0ab1c,f6bb8e5d,f7ddc700,5ec73471,e7ff3125,daf113,1b78fb8c,15bc0d7d) -,S(41b4ef7e,b719fdb5,704b3f17,4132c694,f8ed2471,1677a320,3b866660,dbe879a7,a6fe65b1,cbae2235,cda8b459,eeac19a4,9f44c2aa,1c8a881a,e12093b8,3621c85f) -,S(43ed572c,41f691e2,a8dd1691,86404ec8,7a4c0a3f,406f3bdc,5c2709a9,bb117af7,b7b9e1b8,90b40334,6bacbbab,7be4d477,90a2b093,dafbac3,fd4d2073,fa481da3) -,S(4e010a19,223086a6,314bb526,2f1955e,81722b41,e85fae42,1c338e46,1b397de3,f0d3f11c,3475ed8,44876e7b,3bd0bb8c,283b44e3,70c46ec4,a6159a27,eba65fa2) -,S(b3609cbb,7fc86bcc,4dbc385e,81edcd84,45e15d2a,7d355e22,41dd442f,ee11f36b,8607e5ac,a3df34ff,804017dc,977bba88,c308911a,aa1698e2,e6190c8,dc9c5f68) -,S(445e60b2,543fbd3,7bd68cdf,6db1125e,d1bdd6b6,b27249d1,df96e43e,df965b4e,a5fa458a,8c4ab47a,bebfdc7c,f922e713,c65f8b52,287a65b0,b5dcf0b,c7715fd1) -,S(709f8227,9264c99f,86b59a7b,ef14c189,be875b49,e00cb64c,f9dbb643,10f50fc9,168027f0,cd28d2be,8a69064b,468e4de5,3d4903ff,faaaf628,83f15031,58960d10) -,S(62aa200d,cbd1240b,a252e725,a333f21c,8a2e9d5e,fbf18cdb,e1567ff9,29fb4ba3,19aafd6c,7017bdbc,4b906b46,843e41ac,1ec3282b,12dee1b7,b18e3f28,9e0a1347) -,S(2ba73958,8ed54646,fa9f2389,802e2ab9,e123987f,c881ae11,f38f10ac,b882c09e,f37daa1c,9c0a98ae,f86cc45d,34801353,d8f8a193,77518423,721f3e12,375a25a6) -,S(8672b9cc,e8fbb69a,ae5c0f54,9b59dfe1,e266e9e0,3592a397,7314e6f,79005de8,20d8476a,efb61c79,adcaac68,fbf9eae,c411e875,a66b5aa3,99a97a86,9b05af65) -,S(334cb002,84202999,79fdbac1,5ee5c17,1f32bee6,133300ed,a26571e8,bdab6ab5,8827d99f,3da7878f,46b45bfd,579c5cb8,e4e972b6,49d6438d,96e5a188,5aa574d4) -,S(32b30e07,d260ec07,354cad6a,2f64f81c,e9f25f4e,47bf1afe,602f229a,35ac6d4d,71ffcf0d,64ee9078,6f290418,1126c44e,5c5e3688,f3063941,85660874,3c3c0427) -,S(e5099658,7a4b4e63,43e401ff,299e9bfb,3b5ce402,5c38fa05,761e600,a39a8451,7b0382a8,65429a86,94eacccf,5c6b3380,683a3916,70fc7241,f132c465,b3bb2ece) -,S(b3872c4c,2bf539bc,e0aea035,3b3d786d,ca684121,29db66ab,d316e930,e5d6477d,7ce04af,e4c8c86f,3b37ed1f,a9dd4161,59391c71,22d0f4f9,2424d090,901e285) -,S(d2b56fdf,9156e3ab,2e414d96,49f4c418,6095e74,a2df8908,f3b406de,9935d07b,443c2c1b,67668c56,a84b4925,946a8e5f,b06a33af,371552aa,adc3b500,efe3b23f) -,S(f69867e,1074c765,923f32e1,ec9f41b3,4e8288fd,62b0a081,15db15a9,f37fbacb,fd6c6e25,2a11a516,9ce04c6e,d719c22b,68709be7,6fdd0e58,cd0505c6,413fca16) -,S(bc1830b4,a9ab11c1,ad8778c8,688fccec,cae23898,555b6579,62670d8a,b9e64988,b6244089,f3c46133,1979a0fa,f3d0c8f2,8e95cdcb,12db9ea5,b6d95ac4,c22e3c81) -,S(fabaae21,dc729fda,98c4bbe8,3cd5fb92,126cfa1e,a21f43b7,445e4b47,f38dbafc,1b569775,64465832,c73513b3,ed6aed9f,177ce1ba,b2c09fbc,c4c33600,582d8cdc) -,S(93386101,4d5d4c3d,f912497e,a248d8e3,bcd3fc03,216dd57b,5473d96d,791f8bd4,3d8fc96a,c141163c,4ff3add5,44a6ad71,9e57f22b,8e806d95,1d630fa3,6c936725) -,S(c5312d5f,85c42820,59546b8e,ec6b186e,da0a4324,d30147f2,94a83fe,a6fd07f8,f8ae6e2a,79ba0756,523be12c,8d544734,332898e8,b35b651b,edaf806c,45d2992f) -,S(a08f2496,52c52f40,6db75c4d,da022f41,b73b1128,11aa7388,558480b5,f203b057,a396c7de,9ab5e1d9,5e9aa925,1ecfe3ca,191d7a25,37c4cccc,845dc745,2f3eb2e5) -,S(93d5330f,e8df6fa6,a74b34f,a251a6,a036e0b5,89b8a05b,c525e4bd,40f634df,ca15faea,10f424e5,5d6774f7,7c87da28,c4df567,7d153a08,f5ac560b,71838756) -,S(4622bcc,dfcab72b,e850a994,1f652110,5c35b813,f05a4f6,17055f92,aab51fa2,d960702d,31eeb256,d25cd245,695b53c8,e883d2a4,60965a8c,d29b41e9,d7ca2d4f) -,S(a326036c,7dd885d9,94ba5872,8138c30d,fb6c83e,d17c8d88,7aee086,e0ef9fe5,b465ce69,3719a155,31caafcd,e7689a17,456a6ce1,c75e5a53,4893cd67,32cb9bf7) -,S(2354417e,19637e79,71b0c887,bfa5c553,f3d5e7a9,84a6c946,b1d20b5a,7eef77a5,815a9721,b6ead3cb,b254fbf9,9f34f409,ea740053,3cf4ed4d,2169f48b,29f4bd4b) -,S(9d346d6d,fc53174f,5cda746b,23810d7,3a407819,ddd5df9f,2b07cc8b,b7ce6fca,9b6cc06b,64293e5c,a55a8ff9,f1e90551,4a199b03,df08e9b9,8512b357,9776c806) -,S(73c82b8e,c643a7b7,f95f000a,debe210f,bba638b4,5508564,bb5a3330,fd48dd01,fff15699,a0885c61,fe35f61b,84cb2bda,7d2acf5c,df0d6f07,5fff1369,805b614) -,S(902469d5,a0b2d5d1,cf931672,88506b95,f2d29bf,6ca291af,c9b39cbf,fc798ac8,356d011,d71c769d,342378bf,fcafe4ff,cd78addb,abe8b0d4,fa63de89,1fc3ade4) -,S(e670a0fb,3a0c86f0,53523afb,819b8944,dc4013e9,fd500371,b1efe23e,1f110637,869136b,cd13dcb2,157db5a3,d07e59ef,272557e0,9dcb250a,9bf659df,260b31b8) -,S(f3fef06d,526581e6,b0f68e27,cfb9cc9,b57f11e5,849545fc,b9ad3d5b,8a05c395,32b2e997,144420ec,c4c45176,efa5fbbd,570752d1,4b092f4,ff375544,19b8f553) -,S(72a37663,3958d844,560fc28a,8cc19d88,f942c09c,471d2cac,70ca5d39,396a05bd,de9b1b0e,6e121070,f684b3b8,402e8d8d,729ce846,d2f7ba8,503f4548,735ee1ad) -,S(38b78ad9,c43b7def,4119c3a8,190cde68,4172894f,a84cdae2,2b637bd8,805300b0,a181567,6c4f5f51,87204f17,5bff32e9,de7cc69,dc851c84,23de74a8,b3d01e6f) -,S(db968ac8,1d2e7c53,6c66fac9,e194fb23,540e2e89,8cbd3af,68e158ff,2b34752e,4d5c57ab,79d9972b,ac6b4af0,a6347271,4179e8e,fd14c769,a24e5a73,aab48a0a) -,S(2ace1679,2d3a4d83,71114f28,c1ed35b2,505dd4f9,97c72435,a145d367,a8aad318,5314312a,246874e4,cec63b87,f685f6d1,405b0ef,a1ae3539,cc88e73f,3626f625) -,S(32d80e69,c390ded,db8a4600,862727c4,bb1fda18,2563277e,852f93af,3dbae108,3c7d96f,ea89d06a,6d3cb3f8,181f7cdb,bc1c3e12,3d9f1d08,cbd557a9,60dc7c07) -,S(3ef49e8a,e7fe6b40,628e61a2,945db3cb,f1bf050d,e525d521,d8e8a408,76ee3908,4381c75c,62f45fb2,4d431b54,d63115af,3ff72d27,58c3c92b,d3d1de08,1a123f2) -,S(853808d5,cdb82cd0,39b517d4,1c88d7b0,e280ee6,59e5c640,5aa27542,3c9722da,c1677c44,9b2a9626,698a652f,81722242,3ed18d03,92d4200f,b4dc229f,5f7e8f5e) -,S(572fd483,490c05fe,857520bd,8861fccb,306ee4f3,29adef49,58c1db78,1fc8584f,82acc906,10392302,cf0107c0,6b3b6194,d38e9155,b31ebca0,be300036,3413f4a5) -,S(b1cbabb2,9aa8ca31,75aa9a2d,d4d956e4,fa771344,d4592481,38c93583,376e1386,888cc0f1,7f9afdf0,6ba1de03,41409c1,265cb2f6,c015fc,bc58d2dd,66292ec9) -,S(f856cb92,42393134,7580a65a,149a6e81,2c5c960d,670701a1,6ddbbb98,2f6bab20,c33511ba,192c00e9,991f580f,65c111df,77d9d6c2,d5d63869,c5595011,48536674) -,S(e1601cd4,773e129e,2c042887,b56bbb3b,9eed92fb,6c128e23,fffc3a7,ee73920e,180748c8,a38c7796,ee247c71,49ba1fcc,a78648c,a0508ec9,6f4a016f,301054ca) -,S(98ee20d4,5ffb6177,5ca206a5,b0cbf1d8,e8b37cab,97489534,a98928e3,367c7e72,2df4ace1,ea42db51,68ab5e6e,88fc405d,854b70e0,4521bc30,6978e465,6273c610) -,S(4796ca57,acde905a,31dcfe95,bedd1e13,5417bc41,f5acc246,ec0ad4ee,ddfe179f,7413f522,395a3802,b37637e5,9564c239,5bc565a3,463f815f,8ff962a1,f0a367a8) -,S(b367c864,38adb0b8,d5b627fd,56c7df9f,cfd55536,9abbdd40,6c68bdd,1a341200,c0364744,b99e816,7982f365,72268702,b4986cf5,c9c5749d,fd22499e,2e8fba51) -,S(db36884b,723ddecf,7e2244c0,20de844,e740760a,4f27d386,a747f4a7,88914d29,8ae487cc,2a743a3c,2a1e0750,7def0f2b,fef90e24,fda0e3b4,e5f3333,7d79e023) -,S(65971818,f71c212b,a8e45821,31eef4f9,76b4732e,6c6c3123,ccf5c6a0,99a316c4,415f6791,353350d3,3b087f39,13761119,526a2831,c70375db,4cd07754,e13604db) -,S(f2f4eb3a,13a8f4b2,42182a63,97eb6cd9,9053903f,961a1338,fcbccac7,60ebd65a,a575d67b,667e94d7,20adc8b7,4eab8ebc,18811b3f,3a3bcb6e,7950cafe,8ef9ca8) -,S(a24e7a0d,a058f0c6,3328fa51,fd3c927f,884b3f77,cc068a47,e8c6b4d3,1d113a49,be8db830,79aca569,9eb2fe3f,829719d5,bcee615,645e4c81,a9a7212f,450ef78b) -,S(e59a3ccb,77e11797,7db6cc32,5ebd5981,42212da7,48f0a4b8,981db72,41efad5a,a8e07545,fdda2668,cc0a10a2,2389a2d8,d6903416,a4a05299,9d4c2d4e,4a800d9) -,S(3191b263,a3c70be5,bec721f9,3dabe9c9,fc6c1a75,aaa94e9f,daf6060,fe4b8f32,339192cc,1c7a9bc7,2a9a87c4,ea3cbab0,c7af7b27,53e74491,717b1f99,5df38a96) -,S(63dd5fc6,4f9ddb0,8fd47e27,5e839b20,12f408e5,3c139463,8b97874f,9187023a,1af048b4,2e8b7e6,d456cccf,d12ef7ef,67e0910,4162239b,84f35cbc,8504bd9a) -,S(a92e457,cd8312ec,cb87229b,7f751c4b,2e1d8640,c2b8e5c1,2d3dbf4b,671bcf13,d7aedb56,5447eb5d,18449241,3a07d672,be46ab4f,3d5b4b3f,551f292e,5ffba768) -,S(1ee6b970,b9e09d22,2b20f02,14f00bb4,4789f55e,585f35ba,6c0dd6f8,39b10495,7c910fec,eff9eef5,d1a3c8a0,46252885,9dcf73bb,d4a0b2be,3f8d10e0,dc9e9462) -,S(b19c23b9,c2ac1957,5328d7c,43d04870,1abe9e97,30285ceb,e4fd1659,8f06a76a,79a811be,c07c8b70,6f380f8c,fe369e45,c605607c,d08c8a49,2745b283,37a38398) -,S(3c20db9f,9ed35fc2,7c0888f5,e266a455,4f3fbf98,b8b2a016,b1e9aef3,14f49a5,bb3ac294,3f29e63a,f610815a,4a1e5a12,9327c1b5,ccf489ea,7d8950e3,5bfbc4d5) -,S(fd1ccdba,b4746e9e,44eb5904,d338244,efa29ffc,8ce8014,f6b922c5,2eea4389,e1065546,52146f90,fa52439f,c43ce4eb,73961a52,10f6c040,97a82032,9a8df06e) -,S(e30fd18e,abdeb8a6,ef252dc7,3c2b0d75,83641a29,8db37ab5,1e2da099,9b64020c,49663672,1824f481,962bcab8,6716eb41,8e195d29,6afe9704,cfbc24c1,28dce88b) -,S(4bc1f789,26ddf930,e1aea784,83a9dc09,5cd72300,5540548,e6e217e7,515bda37,966b32b6,95dc1b00,8dcbfa2e,734bd9ab,36d8a26c,2a52c471,63a4cfcd,d200ca69) -,S(23d3e27b,9c864b8b,40f0f7d2,6ece9bc4,9004f98e,d46b539a,affffea1,54f036d4,be4617eb,f680a27c,cc4143d6,ac150d51,b3dfefbb,2892a6c7,1b36c794,8ac0b05d) -,S(28adcbd0,14cd3b70,f46e0a89,477b5cc0,4a513091,cb6c1aab,56de4894,3e6009c0,7c49a838,75204cca,38f250b4,608cfe4c,25040dc7,3ded4fda,f4a92cce,fce31601) -,S(776084b8,a86f0823,a5044ab8,70d84f60,ea52ec7b,a545ea0c,c86f219f,1ca29d08,60bbbecb,1048d250,b410bc38,49e567db,def17272,58570b2c,d0834532,581c60db) -,S(45df2e0f,fd32ef48,95d9667b,c6044951,e3db94b9,ed6af5fb,d4fe1e7d,228f2350,a732464b,1a8cfe06,69e4076e,d4164b98,4de155cb,68bb3994,73fd7918,63eaf095) -,S(6904976b,46a5fd1f,a74bff80,c493a2fc,8ae9bbe8,783cfebe,7f69f0e1,be7dd7ea,19d071b8,df9d1436,6241a22,1a00b340,30f1df45,5e66fcfd,5ad621ae,ca2c3e64) -,S(849d8728,f977d075,a8de805c,8e80980f,e01def35,1ee80f0b,ef528e85,29aef659,d84955c4,6c886283,b9d7adad,bc069d0d,8042dd9a,ec7246ff,edf31594,ae5bf428) -,S(e3d64b4c,234506e6,e7facec,8d7534ac,54588dc7,ea685281,e27c6746,472d58eb,4a32ad3c,cf822a84,74447baf,68aea598,11a9c839,4c9970ef,bc61f363,ae5a36eb) -,S(f41c7928,57d15a31,19b6f132,3b67639a,889877aa,e9213ece,c787d53,5463bbaa,73cfcd0e,c84c55,4d007594,152d9ddc,630c458e,7ea456d0,7cc60503,794d9328) -,S(e1d21747,47ab84c,e47a4a02,caed939f,e0cba1c,41e7b21d,67f52fd7,79186079,17b0b628,aa4bc0a3,ed9728a3,e24a8101,fb26da66,9ac92f63,af81aafe,7db2b668) -,S(a8a0018a,f8f86795,3189da2d,d52b4db0,5d7ddb4b,8d290c80,95a8e7dc,d86ef1d8,8bb9606c,84b88a1e,df980c7e,9360823e,25b927d7,9cab4c17,fc8aba7d,6826518b) -,S(7383c671,6ee05e44,daba57c0,50ebda60,e4e0c0e1,3df338f4,cd8d627f,736fffed,3bdcb946,5f164a74,638cb973,fc77daaf,38eafd48,9521cba0,4ad896c,8e89f0e0) -,S(61fa7e1c,8bc8ac97,96be6431,20858063,1ca36af4,520cc1e,858f90b,ad372dfd,3f0d6768,36c3e694,32287909,c8841de0,a5f646b0,94b0c207,8d634486,c3eba33d) -,S(86029e2b,ca0ac601,99092def,cf4882a8,b4f14349,43bf116d,3cb310a3,b2c4a740,b8be906e,cd9056f0,f3261cff,d12216c8,ef5f1553,dd708480,15463b7d,241c2f7c) -,S(e172f7e5,912aa487,589d6c4c,d0d6b9ab,48c4a6b0,5fc5f90e,2f6474c0,4fad95cc,edbd23c1,2b0a0ed3,b899920c,e8b64d7d,d7bfd79,5009c290,ea0673dc,8acc401) -,S(7986ba8d,322efc24,8b7b22ab,f838de93,2d931c78,cd6a8616,d1f37dbe,32873494,693eab22,4c750592,319b7544,d29fe0c,2420a5d3,d3b7e01e,e6ebc968,12a13634) -,S(ba594138,4a727673,7600a6d8,8d36b133,400bb5d3,6a8a9d46,3e8c65c,e1e00383,746f4e28,bc1b812b,227fc953,531058bf,d9c68545,2f6219bd,86799dbf,3c2ce557) -,S(45ff41c9,92d6b117,c86eeb77,bb17789f,6bf96cd7,2cf0c6b9,802af869,20476c8f,9324f5bf,6422e3ae,2010c9e1,27167d8,4f522e86,87fc95cb,ec3d6972,2002b59f) -,S(bad79e35,487a4da0,7171c282,e8666ed4,d00bada4,d9576a7d,9a93ecc3,c16ed68f,19397a2e,efb184a4,31a02e12,91db0cd4,5b153517,9038a920,7a6d50dc,787b57d2) -,S(ddfe2107,2d8875ec,60c4d583,59755bfc,22cf890d,d3665b79,cfa403bc,9e3c8a41,c62bd917,491d0a8a,9215674c,28c28872,8dbe0d3f,87c10d90,ce22b608,473f62e7) -,S(925f6a53,c07f923f,968ccadf,bef9d95c,d7594269,a3d9fa64,b1180edb,667eb299,1080e8ff,1f918e6,6f08b26b,7f9cee48,58f00038,b8ca50b7,b2939960,b1e7809c) -,S(c28e49dd,a75f0283,38e5d2c7,d1f03af0,12768bd0,6b0e0d0d,87878ba8,2720dd80,670f8989,c941a49b,cc512c5b,4987e167,ec5ae6b4,d7f68a98,331845ab,5d0db12b) -,S(7a9053e,95035be8,8188c196,d5e8e05a,b21dae48,d59406f3,7b9f86ca,2c837cbb,40ee088e,8e7694b7,994774e7,9d097d76,6de026f6,f7fbe352,e7f2bd0f,443a7e1c) -,S(33af78ea,bfbb00c5,4d88ef81,e9661b16,e0b32c85,a1b61b95,6c6a79fd,e036aa2,713e7aaf,537a796,c4d79644,c855d0b,15331988,5ef4629,d8048c69,d3cfd3c0) -,S(c588d014,5a3f3d33,29695573,96d674c3,1326dfa4,797d63d,f9a0c720,49583bd0,b5c0cfd1,6c67cdad,ababaa8f,cfd2cd76,7f747024,8caf60d7,37531c66,ac53cdfa) -,S(96b3d5ed,b93742c6,7c48ef12,c649341b,97223f22,1f0edd5a,2f2ab523,8038d29e,db475caa,38a3a05d,3719a2e6,4ce7b4ed,bf25fe57,4b28d6aa,9961ec0c,b0e44c4e) -,S(412f4b6e,3d894ee6,fb0cb00b,14662a9c,1eea3a42,5a286782,a62da77f,5644f0c7,a84ef636,ab9bc805,bffde813,93874429,a8503e89,8c03f1d6,f139af86,f6a676fe) -,S(25f0a785,c7b43028,52f1421d,a32c418d,32fdfdc4,89c39049,3794e1fa,e4563252,efeb090d,457190b5,89c953a3,aebef406,da716af5,1dc6e334,a0226883,6004e4bc) -,S(50fd4ab7,f367faf4,acb4403a,49ea3e7f,f02fed58,4327acfd,e0bd58a4,ed741c6f,78abc1a7,3c9dcd48,6520cb52,adb1c3a,2d08abcf,a079607e,a56307c6,3d46dd5f) -,S(157583d4,cfaf7f79,33b8fa66,430f107e,c357621f,4b94f313,bbcfbed1,46a477a,9aa6b235,ce8cd1fe,60cd4355,c46d4859,fe35ed8d,659d2aaf,fc09cdea,297e8db5) -,S(3c44bb62,5d262603,e44affc1,65b35976,f2edcedf,8be6b494,f4b3bc4a,5b3300be,88b1c561,67973ab8,5ecd4594,90598152,1ef0e8c7,1ff707b9,79ec2bf,3cbc2535) -,S(31d4264d,e1606b97,f2f71d19,33f23cc4,8fc5d9c6,e087dd93,5ee25b8f,ba298958,460609c0,a3aa1d26,2865180c,98555b98,c8e41db6,2e62b2c4,4ae01190,718251cb) -,S(1f551f0a,8ff14724,60ab206d,3dc1834b,352d1d1d,80a8fb78,a87247ae,5d03ad2f,24253c06,a4c8b148,db944f81,802bee34,fcb97ab6,50957b32,eccea33e,c116a6e3) -,S(de2c4e1d,27f08407,31334311,9ff5a8c4,206a1f73,2aaec3a8,7aab6bb5,c1cf333e,dc813ba1,40fecd3a,31ff4a8e,41fa498d,9226ca2a,cb2d5a71,c5a5cfe2,8195170d) -,S(6fdc5db2,adf54ac8,132c4a22,c382c2f0,c1f54bd1,8aed5620,a54bc4c1,18a95612,db3fa4e5,f318e94d,c0c11053,61d21643,cf60b0ca,a6dc4d26,944e8915,970e221e) -,S(c7eb76c6,ea0e1c51,a3aea6f4,dd7eba10,bb76650d,85df0fc,7fd77b73,53680603,5ae1c1d7,b788092a,3c41c3d,7bc32ef2,a4f4a39,a82b53e0,e6f47712,df5bf655) -,S(c81505a2,b7e78b5b,64ce048e,6312bfba,1a52c7b7,8219d857,b4813a98,c8aa89ed,46db2842,6d6ce211,5e1e49be,459f033d,c222be7f,96b247fa,87d5dfc0,df096806) -,S(cad75255,15f9c3d5,8705ff0d,83ac3508,f7dec312,bdc71c9,a17eb9e,78503bf8,32b36a02,76cfdb97,ecd2ddc7,638e4d61,6231be5,25b6b4c5,2d19c12c,6e6bd719) -,S(94d22144,e22b7e30,56eca8a4,7d6b15d8,f17f3c65,82533fab,c70e900d,be4cdd25,12c0760d,5fef2f85,d89dfbbd,bd0124cb,828bf72d,79b4ae5f,6121a84d,47d93bf9) -,S(325c5c23,ef00601f,ddf52040,7721bde2,13cba19f,c0f2e225,3b112b8b,916731a3,59d3cb98,c09c1643,993f3dd3,64c7d29,5cb38cb2,45d8f70e,9628e5ee,d62498e0) -,S(9c907089,544b8316,4a251516,81bdfda6,7d187438,3e7f4a7c,da96d861,91ee2318,f639dee7,e7010630,364539eb,5c225059,547117de,9fbe4911,d9718e6f,8372d20d) -,S(34f14807,ede9c06c,4cb2a1d8,97a4fb81,ec5544dc,eac1bfc0,f32f9835,302b7a82,78437a8c,ec6aa228,f5f18813,a68bde68,3c54c367,5d6be482,8d01f2a4,96d9c57) -,S(9498d30b,3f080828,e03d459a,fcb81fdd,490b47ff,c344d75,3887b600,1639788b,7a5c8305,b97abe3e,b241627d,c5187a9c,677865b3,567cfd2e,ce136852,e42522f7) -,S(eba08f6f,efd36e37,aa53ec32,d3cef88e,5d4f36ff,ebb978c8,76d452f5,7754f226,fe0e66b5,43aa54ca,7afeade9,b38cbe0b,39e17178,4d029470,608c7e38,bd2015c1) -,S(555d4bc2,bd21729,f6119b77,ae8c9bce,c8ef49bd,992cde50,4c794484,7240091b,cccebdb8,69521e33,2ca86941,593eb4a7,6c9052ff,a54f8315,d30119cc,7f437b54) -,S(33729b9c,19da3474,42f33833,d1723d45,3f3060ec,c692d823,679f087b,ffe8872,a94b6a4f,283af604,eb885405,6bfb8044,fac2f007,d7ebc800,b4abd64c,5c34fc30) -,S(2a1a889f,afe64678,647b060a,73ab92cf,78124ee0,d44c7c32,d8ae15e0,df1dc11,626f963d,3bf11f8e,686ba46b,e6dbbf0e,75aba0d0,7ef91218,98605ff3,fc8b75d8) -,S(4702854c,a303e6fc,ffc62f70,258bb2f5,639148b3,4e3927ff,f2dbcb0b,7c197d6f,7da261b2,8513257c,d1475c2d,e059372e,2da76eb3,f3b2c51,95c44447,d71e1156) -,S(7002edc5,a0cc23a0,65015cae,6e49e7b,51d90cfd,7da04e03,4857c596,cd319c5b,6f2845bd,6b7aa58,7ad2d2ae,19fd6115,78c47b56,84fc6975,db63e230,c3db73bb) -,S(273294d4,483d610d,b2169f05,71d5450f,f4cc5bc8,725d8ae6,7c1adf0b,6f48d485,99b241a2,ffec9e0,a039a003,18239aa2,a71e3cc1,1cfbb6d3,7268874b,67d942b1) -,S(1beccf82,3055b440,fad26a53,5a852a5d,710c72a,c4d28e83,b0335e8f,e98c9a69,f3ab566,ac0eee20,7c8ce0a4,d471eac,2c5db716,5e24b489,e2fde03f,7b8aecfc) -,S(dbe4eecf,4f033d53,5d949cae,c8fe672c,a1902323,77892197,fae8e192,53128160,b3f50bc7,927f0e5b,56241c72,24960fc5,896fc806,1c0a8a1f,5fd3d47c,d5aa566f) -,S(6643fc75,bed80c69,4591887a,5dc573ff,caf7f484,b0ae2631,133ecf4a,39bd1e20,4701285,f7ac7c93,bac1875f,dc4a26e3,8ec1e69c,293c3b7a,1f8b5c5f,878d58e5) -,S(99f90bde,cf1dcd5e,7158280,53f820e7,ef19d936,bca63f14,516342fe,5422a21,a04dfd30,6dfc615b,5390a86,8bebead6,5cfd7719,33f91e2a,180d2d79,b99cd4fd) -,S(54e7ce48,3184b7fe,45fb4e35,192b5678,bcf71f7e,49c033e,aad1dd32,86e33433,cac2833b,65ba9cb7,83a8b85c,b7f4e4e2,4d4f8546,3c6a2c3c,4decec88,14c0e8ef) -,S(cf864a4f,fb60993e,444f4e7b,8f4a9973,4705aa16,295627d3,1f7686b8,4bf02e08,7a98d20f,b736eb4d,465db874,ce98bdf1,6b8a1951,7744aa51,af276c7c,db6f1bde) -,S(6ff160d6,516fff91,5ae2cd45,7a98afe2,a2569345,60a7f26,c9e07212,6d59d1ae,5d1f1355,bf1410ac,e4f8b415,350f9c75,7db5d5ed,1f34de,aff5c197,b4eedc4a) -,S(9adba62,aefd2690,1d77f2a2,c6287da9,a56fe35b,3702da46,f231fe4c,9f5dfcc9,ba58ec45,cb4a359b,7126af,fd2c4bdd,2e708d43,41d96e7e,4825f153,abb04161) -,S(204ea41e,bbdcdc48,cd4ea945,72c10dfe,b5d90060,e9dcf5d6,52c0e2aa,14a2402d,7b2889ac,a1952f3c,b2c5db8a,9924a6fa,fb0b9e32,3ec09809,789f780b,ac36ae38) -,S(f7d6c669,364d3114,225a6826,c20d26ba,a4b4f190,e842696a,82aace97,5fc8ba22,15abb177,b42538c5,67d160,cb3c761b,1ff47cf4,4b0cbd16,36f67a5c,879d3470) -,S(7bc4d30a,87dd28c7,8b066e00,c02bd221,e50a7e64,45b57f0d,cb466f27,7d352587,f4ed4854,2e7e0164,da66e0c9,fcb04a1e,6efbc9c1,206b552e,c68cab96,d0c294d4) -,S(55442584,b046bee6,c245dfb9,59f20629,c200eb21,b42509d7,8564943b,1e316ef1,2e2aa971,c8111ed9,6666353a,103f2e4e,a29c4162,d19da280,905031a9,48580d82) -,S(8e7df8c0,de88903e,71224c97,3a8ca65a,923f872,841f2dcc,bcd69e64,b1dce1eb,e4153083,9ae86d51,e7147873,f1fba8db,c31205e2,34c94662,52ae43c1,25d2a0cc) -,S(672321dc,69d8aa18,25569d06,65fae079,b84a9bc9,35bda491,5d546f51,c651de8f,8ad6430b,8708897d,be809ab1,803a6eee,f977b1f1,6b34c188,d333d6f6,e7ef005f) -,S(f4e2bbc1,43e99b00,52032718,285d7698,1b8beb9a,f693dbfc,2d20f472,89ac3abc,e54990f5,dc330eab,2e722b7f,70cd426f,6d80e93e,205eba89,7eabf0b1,5d651a2a) -,S(5aa3aa5f,c6d2258c,907c7275,805c160a,72694f46,6b5fdad8,9134f1,d39ffff,22d72170,617eafa5,b843e82b,5f670cc2,3146aa98,cb07644a,7f4c0600,48ea9531) -,S(34752ff9,d2bf499a,c6b3acbd,1b78633c,9e9a31ea,45c34383,be3eb008,7be2e7ef,b53ea374,2cf3d886,51f7d076,3f67c8bb,39d73ca9,8306bedd,91a6db47,2c1104f8) -,S(d6502624,2ea44f7,d9b4c9b,5069e1c5,88977062,db2bad6b,51735366,27047327,52f5c99a,f2f2a8be,c034db3f,b573757e,d8014321,86db2c28,8c7151fc,4ab16f2d) -,S(52b3aec6,553d025f,d164a0e0,b1f39abd,915d4a9,ed5db2ac,b4593c30,11f4cc9,51547402,1c17b2bb,9d401683,931b25d7,77af18bc,e0e7bba2,432a7717,f4e2f8c9) -,S(8cbb677e,f7979224,12728418,68b79c12,eaa0ec6e,ba4f9b17,4d99547e,827ef9ca,a32809b8,b07e1312,b6a40ec6,411b60be,92974f98,bfedce19,ae590f98,40183f2) -,S(d8f55de0,e2eef17d,e94b1564,d74734b9,3f89f2d6,c317a248,7f1724e3,d531d47b,e9fd46f5,da576370,e0416f71,f271e64c,fa7dc64c,5e086930,523e92c,9ab7d770) -,S(fa6fc9bb,faa2b31f,f9d57301,4777169f,a4ddb8ed,ed4bab79,d0f4cf62,356b6fdb,b6ff57cd,dfdd790c,7aefd1e4,d4b111d8,43a2adcf,9f781b33,1b4420e0,f57d494) -,S(239f028c,e748edd9,69f752d9,abad0498,f9359017,653e6ae6,bb93f09d,61b58e9a,17dffeb7,8831f6ba,7ba463b7,bb7b142d,d55c8aa2,91bdaf7c,644e8ec,14f8b516) -,S(2ef6cbfb,728d976f,99c71db0,5389bba4,ecad3c14,8f2597bd,99af8f74,965e4f3b,19a27ba7,a382078c,3f1ebe8c,1d93a37b,deeef542,cf174273,b411b60f,79b0fd00) -,S(972d732b,9af8315e,88f042f1,3377871e,1a429247,d8537436,98b975d9,33064a0e,308153ba,ba4c3b87,40a380fe,e4bcbba2,a5c2ae3f,25fde1d4,f40af4db,aa4fd28b) -,S(3d378b34,ba4998f1,833aa295,185414be,e788bced,af422ed3,3c4f2747,6e062a4c,46a4559c,9217f919,80887b50,29f75c01,3c3d5238,d3758170,93eda1a8,f2c4c8a3) -,S(fbb2003b,1fc1b3aa,fd32b289,abe3b362,b13d70f2,7d6451e3,76bf882d,395c3087,97c866a5,c462362a,4ceb96bb,9c17db03,f28e5b1d,4e418a81,653a315c,4dfdabd) -,S(28fa94e,8eeab1fa,bd27a9,258e26c4,295efdb7,afb5a47e,6e14de8f,877a0471,f7619d0a,f2eee8f3,c0c7b5e2,8ce9d0f,62221919,4d1762a5,5145a909,9d23276) -,S(4708a285,7eb9c115,71627ede,6fa8fe29,4be27233,8798f25,c12cca0e,f9308ae9,f35f9964,2e773990,b2e0ab60,1a92cf56,85403466,87a8c35,50e36b91,ca4fa449) -,S(93408097,6ff4b874,d88903dc,b3ceed6e,a82427cb,36b62c6a,6364f2f8,9848a62f,e25a6962,d4e26764,9ab2d4fe,a0babf7,daf64d48,98bc60ae,ff3cfb63,e95f3c6f) -,S(f4a42ba0,818201ca,e3195da9,3a566623,9e0d24dd,256cbcac,3959dbc,720ddf9a,8fd26fcc,be3eff0,75d194af,e7391285,10bd4c8e,7230f96a,60fd27e0,a000f86) -,S(c5ada616,e65bcd40,cf39ef6,197e0a97,791cacef,b41b0991,9c51b166,e3a6240c,e4c65d68,fe41c62d,c85b0b32,39106ae9,cc26787a,60d351a0,4a7008a7,f96eb8c3) -,S(7c193ec3,d3f1d91b,cbd7c62e,5061a5a5,e8b1fa48,561102ba,ca2ae100,80c640e7,cc7cf895,511408f3,e400ff31,8a53685,3b8e068,1d4b333a,26b59cad,97873ccd) -,S(77542543,8e7cf128,32165629,3e6a1c19,22b76355,1ec716f1,d96002b0,ad1bd3c3,3747169d,212c37be,1906eec2,8860af9,edf7d932,c187c4,debbf800,8bd2137f) -,S(92dd5399,fa75e786,fa5c0f7f,90abd1a8,bb48ff43,e54dac5a,3b9990f6,27d90992,5cb1be8e,f93783e0,c2e5c824,ac6c5348,ee493231,9932e9a4,6e54921,3f11b7ba) -,S(c1770828,468eeb90,10b55053,2a532fe0,4f66e7a7,b7a1cb37,6eb6ddef,d693157d,da5643d,a0147d47,fd29e262,f61ae4a2,70e5e9a,77a76bc2,d2e7d24a,819a2e11) -,S(1372e116,e90ae522,4649a534,111392fd,a8baabe5,be8a8ad5,33cfddcc,af6378c8,5efbd4a2,695775bb,dc38c2aa,f8da6f45,1d0a1cf3,2bc584d6,e9b2b6e5,c8346af9) -,S(2bbdf21e,9fa1a2b2,bcd52009,7f30929d,5e2b7fa,e1038c00,8f32d86a,65dda936,51b78998,6008bddc,616c0dcd,2a883361,1806ebcc,5843b64c,b0ba02c9,339d45ec) -,S(36694ca4,d0495ed7,78230d49,e6f21217,9b63cc7c,26ee3f7f,6a7438bd,753005e1,2e49e3f3,bbdcb133,3ff1e17d,b18d5267,a87f48b6,95b5f907,5f5aa0d1,70bc0af8) -,S(243d84b1,dc9ce143,a6913bf8,d13c4aaf,6fbc1373,6bb8a7e8,5e648958,32013b8,39317ad,b6bec71d,ffe3c2dc,6dec5e10,21a3dd83,2dffeb91,108abd5b,6e7f28bf) -,S(1d888387,5255f3f6,838eab82,1a12a8fe,ba6dfde,f190585d,e039542b,2d91ec92,a9d38be2,e919f815,5d633538,d2f0aef3,9ccabdad,dbd912bc,46c2037f,3324b489) -,S(39a21f75,4c0d3376,f7560e2a,a743751d,5512d628,7a480955,6456f9ac,b1be3765,3cf324a5,2a7fd79e,3bc188c4,d55bb449,ef4950b1,3a4531bd,e0b2ea9d,4035e005) -,S(a10ff60c,d8e25df2,a1d394a9,52c67f6d,18ab0a1f,a56569e9,48d9278e,b42e21c8,b45f2d63,3ce82ef8,1dc0c0bd,4f891473,89fd2b35,f02cb237,bfd4f502,df9e991) -,S(bc269792,d5042f7,1051f7a6,46b971f9,bb801acd,dc24a2b2,5bbc459e,b7bcbcb1,b70445fc,1c032061,61b01530,c9205d7e,c7fab6de,1d83f1f4,78b35bd7,71235665) -,S(3d7279fe,fd5a3682,a82a7f95,d1db4442,5f0ef448,f6bccda9,9a61c240,9037cb95,df5226ca,e6365b7e,22b42cca,2ba2494d,9a2ea193,cd92162,2de6602f,70159740) -,S(e0c56d30,ef92af00,b936c2bd,951b3d51,bc439ad0,e4216e2f,d552c2d5,e8dbe588,c2bd177d,2a75c44,40dbd186,27669a0f,f35189c7,a4873e0f,6484b3b,68555fee) -,S(9bf960e5,2b7bbf52,fd839830,634baf1c,f0d6e332,4272bc15,d9999ae2,7873315b,b28719d,20e01dcc,b0016cb1,6a453739,551862f7,d9cc81c9,6662387,1d8d0405) -,S(20df196b,e60ba71a,e617a6b1,44757e0e,87fffb45,d447d9dc,d5480a0,34351198,9c722d43,c0d071b,a07d4953,9ad0abaa,f12ba358,42fee0ae,9960ce1f,26eb07d8) -,S(843c136,208b40b,9459693d,8154980,455a5f71,23b5f633,a26661d,ca9bac17,d5b5bd8d,9095fc40,d2d1820d,31dba542,d0c74f23,86770ede,c9b4df46,f2f12078) -,S(9109b4df,702c1ea0,dea4ee0c,ab46d6ef,708a3fcb,72f9dc03,e05bc722,408d11a0,75baa2c1,8be5801c,b5315195,4c2c3024,7348e9c7,913bb242,cf4ecc8b,96dc507a) -,S(f10cd1f5,c960a9bb,12adff03,c203c59d,8e51552e,3727edb2,329eef3c,5991113c,a84ac8e1,6f65daa6,16574689,8fee662c,9d2e03c6,4796151b,8f3f0bf1,5e8c465a) -,S(9f07713c,ffd3602f,ad077b69,a8a5f539,ae0d6d0,df58ba07,1eafe6ad,10e747a8,adfcc873,42b59083,cdc3d735,782f8ec1,cbb4ea3a,57970afe,58cd5e5c,8fee867b) -,S(6d1d9d0e,32905734,13b2b870,fff8978c,5ce9ec6c,b120d9f3,64063342,cd95801a,650be4a8,95d3b602,4d745f7c,23bbdce3,25a3f597,922e50ef,ba154f8c,6831018f) -,S(497185a5,6b3acc94,7a27791c,7e1fb149,5c649f99,dc767fa7,12820cc6,6cdcbd82,7d511b7c,11dae1b1,7e4078b2,fe7565a0,f33ce5bf,74181c3d,f5b6a951,fe6568c) -,S(fff738f9,848eeb9c,4ddb8bc7,52cd87c1,9a35f7be,14a470a2,c3154ff3,100a743f,106b8a55,cd913c97,76837cdc,f45c58a0,211b979a,17085df5,7bdff373,2f2c38ec) -,S(320391a4,8d3546cb,4466876a,37d60015,41899ef4,5dfc8e38,ccb9021b,981b4830,46f63030,b4559411,e742f303,25707b4b,23fa2d7d,e633800f,9c71205,6651b102) -,S(be44ce40,a925e88d,26937f7f,b7631f18,55879106,122813f9,adf16e00,5d85fe9e,1755ade7,d22e6dc6,7e6806d4,bf44b6e2,ca6948ca,9a418893,24db0266,2b6e1dc4) -,S(8d3f06b1,58ddd609,f83b0531,466fc2a3,da6aa80b,433a92dd,eeb20435,cf33ddae,2d554a99,efde513b,b8b6e5f4,dbd2e942,f1d0a641,98c3df2c,4c74705d,4b37af63) -,S(f814a79c,f258f553,255c1cb3,a054fcc0,d0c71d74,742b6627,210ea846,91596729,119fc95,be48b4b2,23c80c42,fd1f3d45,271ce8a,edeb82dc,31813f75,a32d867d) -,S(95e8fd46,1c37f1db,5da62bfb,ee2ad305,d77e57fb,ef917ec8,109e6425,e942fb60,ddc28b1e,dfdbcda1,aa5ace31,60b458b9,d3d5b1fe,306b4d09,a030302a,8e2db93) -,S(c06543fc,47e18816,bc720604,cfc20826,6f4e5cc0,f436e149,e2dab0e8,a7981e77,22070465,f3a4a7c2,1134819a,c194cc9d,28185431,17ec634e,e6634831,97021441) -,S(4983d95b,3716aefa,4a14d116,bded84e1,fd5b050,bd6001ca,a2b97086,b4d5c68e,1373426d,a2efcd14,333d47bc,ebd3befc,f5e609a6,6fac1b02,80cdae2c,7f0a279) -,S(a2bd5cc6,92e84b97,3ba2cd09,25e0850f,ad8054ed,e6b73ef6,1fdcc958,3eafe6ab,cca6e78a,f9141b1e,6159011b,99f8024d,33d8d797,9795aa4e,4f0b2767,e6a5ce2b) -,S(61c99231,a18f4e73,95076281,b367d084,b8f85226,3117ab60,bf698d4f,6b6d741a,82314b97,9e7f1d30,64861609,a08c019,af886db0,67d49929,9d340814,6e6cbfe5) -,S(4a5acfef,32c55299,3a7114fc,7913321a,d4072a2f,6c6bcdb7,3ed60bfd,6ab34304,7295a29,c06859b2,69bf9f29,64b26dbf,1323e89,4affa4da,9f61b056,9a0c03c9) -,S(e0467755,866f494c,2b36dcb6,c65ecac6,604e5013,4216ad48,7d4f5b68,bb7f4023,dead03c5,974dfa1b,f532f955,826189ad,ae945975,28ece029,d9e5a42c,30b336b3) -,S(686fdf05,c9265fdf,5b54ca74,b5b1e231,c4e8be60,20844596,40dc0d2b,bb215ea7,f4d43e1c,edf9b974,aef950e,bff3677b,c93723f2,c5901710,b6561e53,d57ea7da) -,S(12476985,f9b20c,ea62b7d7,b0d96d2f,e2bcd924,d1f15cb9,fce5ecbb,8bd21253,d3437cb3,9e904fc6,43a7b356,b4389c0b,3f1950f2,43dd7842,e32de16d,2b522004) -,S(656bdcec,9a87c9b2,e5b32291,9f657b,b5eb1e1e,d2fa724e,45388026,2ad17b1b,c7748d0c,47b6e4f7,f63f704b,3fdc08ff,cdfc830,d17c1d11,6aa3dce2,f92fa64d) -,S(5b7f710e,f721612,ca79b24,483ced12,7a3d403e,60ebc04c,3aebeb96,b483e4b5,1b5157a7,f0688aee,634196e8,de5a9eec,11db4b72,bd96b86b,698f7284,bfb08080) -,S(bfca66d0,552ba6f5,5795bf18,40f90d85,2545213d,81d2cdea,bc8d3d04,a1e6b4da,4910b0cc,290d4257,c04c4638,30cb3a10,223043a0,bddd8690,84b6dd1a,f1754e75) -,S(663fa68f,b79dcbbe,4798f8ef,2057bd14,1447c11b,cec70924,7f566032,88496f16,3ace2efa,1f3bbd23,d885598a,91d1f420,a42597a2,ab30f951,f2b27aa6,83c41786) -,S(27cce333,8a3db8f2,1fef2f86,ede68a25,7c1675ae,80cf004,6085f1de,495c4321,7156bd8c,8babe472,eb144a00,263d4fdf,7aefa69f,da2a9c29,4b16a82b,24d373ae) -,S(d49c06c4,52ec5c09,be27940e,13c575ef,b727be4b,1c0e8ce3,5aa5bc4d,64bd9560,2c653518,b298100a,72a66469,f9a03635,5d7ad789,546df3c2,f5175238,e78d18b0) -,S(6960807e,bd028026,d3cecd25,140d3bd6,3d7bf4fd,10afd129,cfa017f7,544ad08a,a785044f,28befae7,2b7cb546,5bda6bdf,6f9a6383,aa9abf4c,f7baeac0,920e7c7c) -,S(8382bf36,54b63a71,a3b75abe,ba57dbae,fc9263c5,5a54faa1,edeb5325,3df8faa1,e05eb9dc,c319cb53,4461da26,9627661e,dc9bef3d,945766dc,b6d0fcf1,849b011) -,S(803b9379,30ec876e,78c8cca9,fa932f22,b7e7059a,f605379a,cc45a3d1,4ab0bffb,7db2341c,5202d1c2,c6fec7d0,b7869471,cb90d1dd,17cd1152,b52af046,55e5790f) -,S(cb4db129,ab6ae9f,11165ff4,f73fab02,cb78fb0e,89647e08,f998ba11,d2c5292c,ccaef9a,1776384b,b5a80ad6,5bb366fe,745c2408,d754ee9e,f6154188,d7d1c9c2) -,S(fab28757,50e9f672,3838be8a,fc070fc7,8fd6af7b,84c9579a,a8152acd,ecd115a2,d59fe028,89cd562d,5397d3b8,3ae85303,764ee931,d9c6e495,6c311490,c0b3f065) -,S(dd879eba,f870ee3d,f6e3f03,60833e12,fbdf844c,d6a5b76c,19802485,6649bbc1,e7bb04c3,a99a5c11,dd7a324c,1d5696c8,b041a12a,c6a538f7,3094716c,9943c55a) -,S(7aa4afbe,29b06a1e,da9319d5,72572b13,1df68f74,1b5f8d8e,d00ccc04,80f8016e,15f79a9f,b77b8587,7f02e3c1,3202b972,423fd00d,937c0d2d,c9d94b17,53fe7130) -#endif -#if WINDOW_G > 12 -,S(9145f3f5,876a3265,5d7fee64,f2d6e660,c34354e9,1571d68b,a19e4cc5,8c39f890,45e0a95d,cf369fd0,5bc9ba7f,da108d6f,37650c1d,5766b6c9,98ecda28,b285d8ff) -,S(5450b752,36fb010d,1ef37afa,2077f3dc,a5a7f6c8,91a21317,13df740f,4511ac9e,a7c7ed57,62bef86d,4de1084d,3ded2d7b,13ff563a,67109ef0,8b6f0180,fe6ba175) -,S(ba6c0d72,5e48de2c,cb8256d6,7417d075,bbf2766f,d13501b8,4c32cf88,c0666a0f,cd2a9132,7137299f,50eda669,3a599032,bdecd64b,91bcc640,5ed186f3,e525e442) -,S(b94821ff,1feeebb4,6fd1006b,798fbdf5,d25a649d,aad58b05,53adb7b3,9605c921,21589ba0,79bb92a2,c7c3d950,c574afcd,f45ccfae,eec4365a,72dc58ab,f9077c05) -,S(46436446,497f7c76,b70e0d7a,5a963cc8,432f14de,93d61f81,98f8879f,da0681d,29344a4e,90c4d810,10da8aab,5ea25e5f,48c367e5,b3ec9239,8a3e608d,49c83a5f) -,S(bd8e5ac6,a2e210be,4959185b,7bcb0cf1,bd3be917,5baa0d08,2bb0b38,e4c1ae1d,6b381be4,6dcc9755,da7773a5,eec888a6,69c6f71a,7c3ec0a9,4edf08aa,2db1fa19) -,S(c27c1e1a,c428a7a5,f4c3405,58ace76d,7fb64593,b3942319,74cd18ff,99f22493,fc95d661,c12f7b3a,1cb1884c,fa9f5994,25108af3,c05e04a4,9544f919,c59cf57c) -,S(a1765561,837e4ca5,5268168e,ed90466c,44c17c01,4040fc02,9e53af22,77eb30d5,8a2dede2,b8d488bf,cd655d0b,30e6e2f7,3032c775,d0fa15ae,cfc8b66c,b6c28eb5) -,S(2bf6930d,35cacc91,87e9279f,678ba368,e9eea737,8300ef93,b03e98c1,81ddbea9,8a2d4d43,3aaa8bb0,3ffee538,38ca8e16,d0f3f930,c35d0db4,6e2fa069,e625209d) -,S(766a7725,9cc5aefd,90f005f4,d6755924,a36d085a,3a5856a,6a066a70,6877c8d7,db3fac97,4fd9e2e7,f05bfad1,5e938ef0,90b46d04,bf40bdc4,171c1e33,48049190) -,S(d25a60cd,953f21d4,5fcc333c,97329da,134196e3,9a913242,88792ff9,18461268,89bf2be8,bd04835f,dbb874e7,12352980,a07ad598,9035270f,397f24ce,790c7863) -,S(c7b28e9e,8b7125b2,6721f467,b665eafd,9bf56986,8ca180b3,60dfe429,cad95d68,ac28d58,b3a7b61a,71f947ed,8bca4768,9ec7bf34,7646a167,b37c3aa7,9e95c398) -,S(e2a5208a,c61f8c29,ada2d7a7,4cfce985,20c29160,f1f7a97,ce8b34dd,7c59bc24,de8ba14,49708a04,ccb4483b,4e90e383,a152ce27,777fce4a,880d9f5b,3dc70830) -,S(e1e8e4cd,2e8df95,d3b2b152,a540967d,6976e001,88287ca5,3e844adf,12e205b1,a5dbc6f9,cdc7547b,cb3f0091,8233723e,d34aa97,f546a491,a77d8cef,43bfc9e2) -,S(b20f0a51,4a684e55,2b228480,3f3b1c2a,3c3143b3,b895f75b,ea454bf0,9d2b6512,bc3db380,676d0d14,9c0b0c3,1941a07c,f7c95585,cd44ec31,e0edda96,e80d02c9) -,S(b71a6923,b1adbf77,94cd9d8d,407ac96f,9582cbc9,b9748949,9cfa696a,c29d3ec,75182389,9d59558f,b93113c8,d38c72d2,7b6d75ee,7679fb1c,89bfce1a,64b4f151) -,S(ca47adac,68ba38d1,8ccef76c,7565788,a82f415f,d9dda65,2004d5c6,a7d3bb3f,bd598ab,1b783382,44035385,e165fd5a,ccd8454c,3969d378,42fad050,4a8701df) -,S(5fade148,aceee9ee,9fb4eeec,edd5e4c9,4fb989c4,d99f65ee,a45f99d0,2d40e441,ba6fca3a,e82e5581,ac5104ca,c8dd2c00,15afd1cb,3943f1cb,5e61dd4c,d73831f0) -,S(767dc9d2,14fccf00,900ba01,a1cf30fa,e834c851,e633849e,8adada63,fe5f84e9,8c650911,aca30e56,2d6b97a5,2fd7cbfd,1a5bcd1,9ae197d6,9ee3215e,64404639) -,S(27f8f961,445e2a20,5daa7648,fc3c06d9,523544d7,477e686b,91d7178b,7e4f06d9,39110b27,82cd7be9,75596bce,6b79e5de,37933242,21be8172,427cdfd,82a73a60) -,S(8de0485b,343b5e4b,ada4070b,f79dde48,8a1b2889,839735bc,6a403165,3f3de668,90305767,6f43e0f7,d7d1c1a4,4c59124a,12fbba72,8302e143,1c2cfae2,ed5729d) -,S(5e43db6c,8770e8ae,8ab8d318,8e700c28,5b6af8a1,eec95fe1,b68e5cc5,952df0ff,6882628d,d85fbcfe,3a2a1091,15e59c78,9aeebb3d,37075f90,ae02a439,506c7aa6) -,S(7db2baab,4bf4300d,e7caf4e3,52df1423,6102863c,edfeb7a0,89311f42,59a4ed54,387561a2,fbbb44be,303fbbcd,685909cd,e553a84c,a3d4c0cb,d33026fe,178e8a84) -,S(96da8525,39106887,d1fdf9e8,232db3e4,cdbefdcc,abb90bbe,fc04d10d,b996c6f1,65271a31,49127341,9fb5d651,3dc33287,45948c92,b7fcc509,4023d300,9bf9edcc) -,S(84eff1cb,14eb1284,f5ba51fa,838b485e,64cd4c0f,acb97b00,81ba7848,add50613,926c9c8,a6540a8d,7b1e602b,6ce818c7,609f4511,32f284fc,7f578c52,a6febd9e) -,S(1eb96371,8e2a2a0f,f5ee6000,7bf94a00,416e6a92,25d59705,7fe19941,e2adfbbe,4870aad8,9635ddfa,dc3d4011,500639aa,d3cf0523,cff0dbb0,9c9f6a1,3005b855) -,S(2994a36a,6ea3f307,1bda8696,baf193df,c75fd4a1,f7683fd8,d454dcb8,77bdc098,e465e8ee,a7273d4c,d786bd0b,e96fd3e8,9969bf03,1b76aeb3,fc82c4c4,bf856766) -,S(25e7fb70,f3d357a2,c29b115b,5e2d97d9,d2b68fcb,b7f2fc00,237758d5,9d26c414,4959a370,a3bb895e,bf530fa0,13a86ab8,206b7330,efaca631,fed26773,f356c4f2) -,S(fc387f98,80bf6bbe,19f0481a,2d66bc5b,c3945c52,588860ea,dfd5893,347c0623,89d7b80e,83caf032,9c9d07af,734604aa,7ba33274,c1081ff,16e663eb,b49d67c4) -,S(c50af368,c25fc9fe,10220fa8,2f177720,ef5c00b4,85fa99,e2f03294,fe01e1d4,c3777b26,41983094,912b80d,9e94af7b,27d9f10f,978c931b,a4294cb6,b97579fb) -,S(a0f9d109,d524d9ba,a2e00362,941a5f20,d7015c48,554f5bea,7c97617e,10041f94,28c51c02,daa5e108,3e77ff2,c64560e1,2eae923a,3a699f1,daf3c62a,710e9ad0) -,S(41d12627,58b708,58727138,908004b3,2138bc23,cbcdfa28,5da862a3,48316de1,6277029,153bcec9,5c95f451,3d515d90,341d90a4,90eb2999,d29df4f0,7c1b9673) -,S(944c58ce,fe6cf543,d93afb77,e33adb3a,5774448c,d61d621c,fb80f856,6e99ca87,c071ec1c,9b7fc717,ca91c557,66bcb222,3294958a,b7d7b056,e7473170,284d66b5) -,S(3307ab12,e06d71ce,9c029bf1,88eebb58,9a27be59,17290635,f2babebf,be437145,889c3cb9,28cf9091,4748dd9b,f89e9809,4a6966d0,97d854c3,c6b6a949,c861d213) -,S(42baf011,1eb2224e,4ca03abd,24307b6,72b74572,2db6a8ac,dee1b7f3,45cb9ae6,bf32e128,d608dea2,4b564bec,38d22c5e,879515d2,7379cb11,25695faa,2e12ee06) -,S(856baabb,be7b4bd0,49fbe898,110d1175,166c69c0,a2bc86bf,e734c854,c402c621,24a323c9,b6d31fd3,cd424161,be229e89,1f825197,9ed4721b,943d7418,4912ac0c) -,S(38dbc18e,d998143d,874c224e,de83834d,95aeeadc,805cac1c,3216d830,d24a9cd4,273ec126,f7e85778,ea38e2ea,a90ab5c5,271c6eee,7f934a03,570891e5,167eae4a) -,S(359dc85b,ffcd2329,3166bb20,c8374af1,5e24c065,a5f48d92,c981eb81,4988dc59,de5dedf7,deef588b,90237d06,e437bdfe,c4a05703,f77b584a,e58162fa,bfbf39c6) -,S(e1068065,e2e91c88,3de2f73a,6a5f3da7,1d872a74,9d7f283b,b1ca35b7,c63666ea,810c3a52,b5df0851,87928afa,a7685035,a7e155fa,c8dd4523,c5ed1f01,73752cd9) -,S(50767f71,37e7c9a6,6e317183,cddfdfc,b564956d,cbd5f3c7,fd8506d,dbb19d83,e1c2dd5f,5e9d5fed,807d24dd,3f2e0ae2,393b6167,563db9fa,5e338664,a0d4fff8) -,S(44cecbf0,cdf88355,f1216d0d,efcea137,5e01275f,f53d8a72,5a0b5980,e6e65864,469568e,5094e9b9,ee290550,e67bc636,e8e3f022,f15c8d2e,25c3ad6,f51cd40e) -,S(1830c8ea,43cbb07e,fa2fe597,6afca2bb,87ed8a92,602e05e8,86ce3447,96aa18b3,df551328,e064aee7,67f56203,7fa31c11,3c8ce2fa,b5445d65,8bf1dd84,2f1da49d) -,S(58d54b7a,473a7ab2,51c33417,a41f4ee4,708245ea,c4f8eb79,9bf90aa4,bd9326c6,a191f338,15e2e07c,ca4c331b,fb1cb2ca,a1692093,faf5e789,1ce45a2e,c49b2a85) -,S(f0dce604,9507812e,603af104,42fc9861,70a18b6e,44e81af7,ba192b55,12c6792c,c221a221,b5e86ed6,23e48df5,5cf0f560,4cc60eb4,c54d95ce,3ada7b09,bbb966e4) -,S(42fb09e5,72c0302b,286aaa04,644b26ae,e4b958cf,ae5293d4,d7ba505,59dd2ab5,79c10573,a00e6888,fbc7ec76,983e7d17,f46e1ba8,27494099,43781bd5,19f2299f) -,S(7adf1551,ddae0c9a,8628db25,e0dad10c,935465bc,88b005de,ea2d0412,f3502ecb,657c0ba2,143cea92,c9ef5c3,69d110a1,2e031e67,9d945a9b,b3c5886f,29acfd20) -,S(dd5a48b9,56fdf6a6,d6271310,afc2f5bd,3a7bfdc9,28125345,4dffd91c,282c7a5a,7390d037,2e067f36,fab52107,29590464,2ac6b0cd,91a161e3,85df7cc1,7ca52657) -,S(631850b5,15374594,be1c783b,104d2ce0,13ac763b,1d36301d,2936c2d8,8a1466fe,2490ce1e,a9b67e44,a9241416,c5729ace,2016d202,b77efa85,78bf3228,c590882e) -,S(332e39e4,d6732229,aed85cd5,83a3ccc4,24466869,bdc6a8e0,741b0e06,f3a0bca5,90840f03,60db52ae,a58b1b4,74ad65c,b66ac30d,f4d465aa,60244d48,5d7578e7) -,S(de019556,f0c7e1c1,6567224e,826532f1,d72c0eb2,91e70980,de7513a4,362f0c97,39a3d79d,1cc98840,4162227a,66382529,d75fa5bd,64977e47,9af0aed8,68411ea3) -,S(4c44c0c8,e675da80,c6ffbf2,61b82e46,4f81b76c,a3f902a6,8094a2cb,24ed859f,59e1ee88,1ecc45de,d8ff2800,243ab8ac,c5497897,1a3a2246,63b2b593,e45ac34) -,S(e60339b8,481e19e,5c1f4d1a,85ddcec6,a4e0dcbe,113e7d28,2793654f,309286a2,9a1eeacc,a607941f,b51c7998,ed2a5a98,bc58e3f9,4737f72d,1b08a706,a49d9d59) -,S(10f42ee3,e7292f3,9f4bc472,708ffec5,c6ad955,c5285be0,d44d02c3,d8a25e66,6f365f0,53ebe28f,db9d5f2b,c967cf14,183e130d,f01a5106,34a975c,ec916a25) -,S(7e0931ca,d1286687,7d2fb0f3,1c58d74b,703af3ae,593a9548,b6d53d86,6729c445,5e4b9fc,75eab41d,663caf7e,8056f4c8,a9c34af9,22773ffb,f5a12174,1f6b0b0b) -,S(36313f7e,f9613c6c,ff14cd1a,78362f7d,b7f1acc0,db278f1c,6a011435,57963f22,1e6946ab,2a94231,4ac6627f,5494205c,33960a91,ba663a69,8641bab4,43d7edc2) -,S(223eeed8,8eedc265,b2e18a63,ceaa2e9e,83f9ba59,2fc8f3bb,55cec574,2869fe01,72122173,4ae29bfc,f3632cc8,92d72d10,5593f7b8,d687e5ff,eff21095,c1bbd71c) -,S(b6bd5ec9,33302c5e,3fb9b32,18795a11,60dbb2bc,f9a9b5fc,31b7a5a6,28b3ec20,fb9f87f2,98a8e5fe,b15f051d,63b48bac,34f373f3,9b42a42c,d0f1d2d9,c99dd495) -,S(a365a760,3b1c24fb,157f69ce,8fd57ae,5a802dbf,3b8f92c9,8f0a8b01,4ce24668,73e6422b,7746abda,2a38cc7,298180e6,578005b4,1b0d3760,6f2bec3f,5c0a89f9) -,S(e86f8fac,43e436f6,f4adba30,9d446a07,e24bac1e,d379e13a,a235ca1e,d7cebe6e,1e7bb4ef,aa75a9bd,713a592c,42a01134,930b7402,77cc1cd4,a913d6db,f4a166af) -,S(f5a57dfa,d2b25571,dad09304,cfde1da2,5cab3e2,e85895cc,9933e868,eb9bd5ac,d265de5e,8fc90e41,d518dad2,68997a24,8eb90906,becba9b0,c768c5e9,877c1ff6) -,S(e1dcd17a,7259374,7e6fd8ca,b2464a9d,6656607c,a2bf10f1,45c45947,75f76c7b,efa2c310,23f86d2,6489feb6,1232bd44,dff819ce,6b95678a,130de640,4af9a20e) -,S(83f8abdd,84996ad,1be74b80,a05da9ab,cb3774fd,cca40c3b,afd386cd,cfa801ff,267ebd64,329fb10e,56ee792d,966868d8,1c85ff37,6aa24287,3d37c63a,4bc3f63d) -,S(54cc9d79,6ca85a90,27487c71,6511485b,ca324b1a,f34fe454,ea9ba54b,4f259fae,18c39071,ef0b861d,7d016e9e,deb6e83a,3c6ce8c1,517ce0f2,e201da0b,fab2da2a) -,S(9d12a52a,e0091654,e2875ac1,b11f8744,1c3f65ac,940e6a51,6351c219,31402ba4,5ffbb334,276219af,418d17f3,9f5fad63,c6d7e42d,d53f6e52,bbee2f01,38e81d2e) -,S(659bfdb7,66821a91,cd030917,ff21aea4,488007f0,b7ef3824,4f23b665,e6496998,2ad708bc,4506e85a,341ef96b,78bc247f,d7321a8e,bc21f9db,8444e7ca,254784e0) -,S(e2cc4e33,d4a08374,4866a253,81549a6a,76ba1b4f,57312413,d601296e,5eb4670b,528b2b25,347e7f34,7b79780e,a64c3718,80497f0b,a3b28e18,79714089,a4672476) -,S(529c0b9c,9e21c36c,9b2164c0,fa505601,e8dbbac4,cfcac131,e248e103,e6edec68,7fa44821,72a0ca01,33669e6a,bd2e0386,6cb74f5f,9cbb7e4,96770129,567125f4) -,S(289d6baf,be6a7d1c,154d6532,a80fb65b,3d89e57b,eb2f1dda,654d3553,683b63a1,801f4863,d3ce8d61,60e2c62c,55267877,db149ff0,c3cdbb53,38893168,7d005400) -,S(d16a84c9,e3b36660,7c005bb3,425ab432,2eab9b58,58d1899e,51f2ecf0,790f14a1,2c6f5dab,10715328,f9ffc5ea,4ad6e0f1,46ec79cf,19cb2313,79bb5198,5156dd07) -,S(d03cac39,4fdabfbf,440a6893,e410dab2,a7062df3,ecbe1aff,d30703b1,6b6348f1,152313ce,f530b317,70d85c08,7de95b1b,5dc4a86d,38e4040a,e5d1ba34,449d19f9) -,S(b66b3c6c,a673c4a9,77ca7d85,1f969858,d4c4b604,bc497101,c89207b5,a863379b,54ba2563,771c6aac,482c63cb,7156961c,4b00faff,187f0560,9a470b06,31624da4) -,S(be684644,11c47cd7,dfd3127f,4e7d7308,2a43fb68,79c5e86,236e4516,a98c8c45,79290f83,c61d368c,2e395aae,b9cc50e9,7d78ddc2,fdee9f19,a15fae85,826733da) -,S(478ac3a0,9f34f463,4d61de70,9ee01878,4ca421f,91d20e0c,5c62bfb7,afcbde9b,f752f3b2,ccbc1096,1ae7526f,5574b5f6,e4bc7d4b,f77edc34,f6e37655,7b0988bf) -,S(745f355a,f2ed71a9,9d4d7de9,c9bd4a13,7271a2a0,c077c796,e7064179,8f3dcfc8,18ea61f4,6b0c87f0,9ed05816,c31e1992,d4fe8826,630c5f6e,67242063,86e288b9) -,S(54e7bd6f,9878a8b0,909aede5,9286427c,a3157a8e,38ab94b2,18db520e,86760ce0,d7b7d80d,c1eab448,d1f3c638,675dc0b4,e04bdba5,340d3f2d,dc1d24f3,dfb8e49) -,S(ff56afb6,55eb431e,f3c6f5c7,fcc6febf,99b018ae,3dc95208,27e4a01f,a07d510e,9bfabdb8,42d7b1c7,9f4388b4,49a28d6,ec723210,ea27509,655e9b44,2591e371) -,S(c2bcc099,ed298fc8,679d0250,6d8ea790,ea511b41,5ff3ebe3,82d39d21,fe9cda72,6c7bf2c4,35ecf773,5b6c31a5,82fd38c4,825de4f0,58efb070,aa1ecb58,530f971f) -,S(2383f144,9811331e,6c54b9a1,19c681fe,c8549e36,890b80f5,99a80187,8e2ec4e,13ab411f,d846b6b5,938a999a,704470f0,d8fff03e,9dd35cb1,44860a0e,3533a1f9) -,S(2f2271c0,d4fa1d8b,f8a44584,ba4f5266,9953f72,89de16b8,17d6bf0c,6e096048,646ef05d,b40e50e8,b6f32c22,63ef553f,a957173d,a6f14ab5,7cd60b60,2fb42fc4) -,S(b7b49b1b,f067a27,eedbe55c,bb011eeb,809e7ada,ada5d08,9bf1f26a,25e951c7,fec760ac,a8160525,ad6ec95c,7cb0329,4a9b7f20,45907331,5b2dee2c,7f7c33ed) -,S(36c8e1ca,d9933e5c,971866eb,12daf81e,7765d4cb,9f0af557,94181aa5,e5409223,895eb6d0,a0252282,d71cc730,9116ea95,22f2e35f,52498853,e291932a,dc8b8fdf) -,S(3cbe9127,63283592,13173e01,8cc2b0e0,fa5b8a11,5684cd6a,6ee7bde3,bc1ed523,7b2d3dc9,22f96c9b,9970aa9d,c75f1e15,c5149ab3,d0993055,e4df30cf,ce44dc81) -,S(76e94d41,c4639419,23448d38,8b239e6,fe0aec99,314ed16,4e67e97b,6247213c,8ee4a6c3,2f010749,103460bf,d75fa38f,f9efe4e4,bf283cb5,a3bc186b,21fa1278) -,S(493925cb,12c0e7e7,a15749e0,7fe9dba,5b265d27,8eec0c08,506f3433,4b1851ec,70900c6b,3960a465,6cab318f,9f730a66,e4a2400e,d819da9a,1f5b16bc,4c62b193) -,S(b37fdaba,d1a1393d,79820eb4,a4823d38,3873306a,a9f5e6b7,51173aed,c43cdcbf,8506f0de,57fad139,e20df67b,e30a75a7,dfd325f2,9e35652f,28fec608,f27030a) -,S(4451960c,48e95c49,32b0c90e,9f90724,8f2b7023,9c6c703,3c29f4a5,b0a5e8c1,83553a18,d9ce9f66,961c9e1a,47766a4e,28bc404f,bef524de,53b1b687,d4d7490c) -,S(9b0ac1a8,697c69b9,80cab20e,b3f98718,7857721b,c869c704,caf63b80,dfea3449,210e4c53,bf1bbf3f,71e32a58,22809853,61b61723,72e845d,65b5661d,fa7e60e9) -,S(e6697355,ccae4f7e,122d62de,1c00dcc5,32eca4fa,7dbd1ceb,e92684b4,781e0851,1f122cff,dbe5ef3c,944353f7,18806a82,9d3ded91,427bdda1,736ba236,e9bdc3cb) -,S(ffa890f1,1a1aa4ca,1f26f86,1288bac7,ad480a4e,1cc47f2a,fe39f260,f167201e,1688dfc4,1716fc3d,473c4149,77d0ee8c,ac569cda,b01ab5d,69d449ca,85439cb4) -,S(9088d4f2,6ce238cf,63eb09b1,5c04a04c,c41fcc57,946c6c14,cd3b1b4f,54b6bf47,9e380417,bc61004e,3d5c9943,b3d359db,2ae4ec81,2b70e909,bfe265d5,e4d2c2b9) -,S(a3395dda,c1e760e0,fe7f7e5f,e3296bc2,99949ca2,2c034707,67c08ffc,d9576a91,4f8a879a,54036d17,16f07016,23dfcfba,3141850c,de003870,6ee940e7,452393d3) -,S(11e54d64,54aac1e0,58cef234,51f686a9,1a77300d,75330ecb,d208678b,2b8ad651,749b2960,5a8419f9,c5521dfe,f552a24d,aaa53f45,908d2679,6e08b396,c9c020f2) -,S(c8f13cdf,7b41e822,ab6d5a70,7c701d29,98f5f0da,8e4c9746,75e808fc,64327f30,489a69df,17c09c1c,dec329d6,a1f34f60,445d7aad,d609d94d,44168947,c3199404) -,S(9175e6dc,cf674838,a94c628c,3e1a9dc2,9487f394,8a25e50c,d463cf6e,92d84442,8705713f,ed377125,51e37e51,78ca7a7,c13e193b,1b83c729,8cb08186,8fde1c22) -,S(8eed492f,b6d5f0e9,ee78f6b8,953ac0a0,5df8b9ec,db17a09d,22863bf4,3620099b,23a45742,17672e98,d9cf8b94,62439ec8,82e1acfd,40db9d9,9ece889d,1e0ff1bf) -,S(cb95ce23,dbac06ef,79793f54,3105f5d7,5cde90bc,651b7756,bebfa367,d5c2dd9,9612a6ba,c023b0c0,73b5ed99,271ddeb4,57d22d74,f7ecea4f,c618be5e,164a9a48) -,S(667218c8,bbd3ff37,d42a8ebf,8b5a7791,d8fdd493,9ce447c9,15dac906,67a3c980,dd401179,9e19afdd,46b44aab,1055b554,452a21e7,6750f2a,ce98083c,8cec26c0) -,S(884799c6,ded4851,ce53e855,dc429698,c7627b5,a0ed3852,19b59af8,32f76e5f,238d75ed,84e6408c,79cd2d37,152cde78,22e34377,fccf05ac,3afda662,c21c4a6b) -,S(8d98f36b,5fc0082c,597a05ba,e24ea6d2,2cc8bb90,3a6bf96a,256eeead,6911d143,26e8ad1a,fc902a6d,505b2fcf,80168177,de7df931,b1dc1516,f2ad7b38,e0ab3cd3) -,S(ba9062ca,c0ddc6d3,27f2cbc2,8d2efb1f,d1db2388,c86741ae,7403f4b8,3fd70ad2,473b335b,3036e754,d9d71ccd,53814455,674539fd,7b73d9f7,8f24bb0a,668b38c2) -,S(4a2d36d7,3bf0e609,7a69be67,55621051,7453ca53,11e288f0,1ff1dc03,acdca29,ff691e7,a90331cd,44e83ac6,c298f5fa,9d694a81,48db01d8,595a4386,b2ca8f83) -,S(e868f28f,d99c4b16,b64fb0d9,32c325c8,6b365136,e0055c4f,cd362e1d,cf37d0c4,ad3346c1,83401034,8e8e0440,e889109a,40e5fa11,37d94bca,2742adec,4cd4a9eb) -,S(6c5e8689,830a6ca5,12d77e56,62239833,ea77e696,da40feea,99da3519,2babbf3b,c29e05f1,5fd00b60,7bdc333d,d753647f,56b9830d,46a597c1,2bee9465,ad779540) -,S(b3a172a5,6ebf2dff,aeb91cc8,6b9d5a91,c317adc6,250ae210,e1a25bec,1c046344,28f6dd79,9ae40d6d,bd31fff9,9a4c2fa,f06401c0,de7a5d11,9fc5faf8,3b4ac3d5) -,S(198f05d2,e2f9d779,a50aed67,39468a8c,ac4a22ec,71a3ab80,91a94e2,100d8f47,cc6a183f,c9813173,caee3baa,f3fcb223,39708968,360c02b3,cbf899e0,b7cd0414) -,S(78b2178f,a943a791,4bc7703a,e850b07b,41ae77db,79fc39d8,9f0f50aa,b077f48e,85fd3e34,f2cbb092,8bb89004,e1801be1,d78fceec,c29eabeb,11b9cb15,625274e7) -,S(6f70df00,1d4c5175,f997a795,170e28a4,23828ef9,d5f72dcc,cec43fb8,d9943f3e,26315213,b77183e4,5979c34b,e730e2a6,956a66c2,a8dfbee5,f0f1eedc,ce8315ce) -,S(ab813144,3c946d29,d05509e3,b45b5926,e3964b2d,1cd0fbd0,9cfc359d,b5a9dccc,aebdf315,c1273af,a0c5e587,6c6c6132,16b7710b,3f505062,6336ca9,4f5c5ac) -,S(e72b3791,dd751127,23723e62,77e5e6ed,6b94569e,ba3321a2,a3e883e,5473ad3,131b3074,2dbcaaa0,fd3109ab,5e3a2847,9c2091ac,8830b19f,d4df4c82,9b28a3d8) -,S(ca5a3296,ecdd5e50,38fdf77a,fcc507da,bb525d7c,56b50c74,61928432,ce3ded63,8bdb6794,b7e177ba,9027258e,42b365bc,5a14209d,2bdce54b,3f865fc6,ffc4ab9e) -,S(eaa3be9f,26ae8cff,cedbe59d,cc03b202,e7d2e815,a7269819,c881a700,e31a9222,1b5a2cd7,a367d34c,60ef8026,51df2d3b,36ac2816,7cd7eacc,735e45c1,9524ec1c) -,S(ebba882d,3ab4ff6a,e162076d,56791554,35a011e6,74872206,582b03de,e8e97728,94222a05,3d8dd2cd,cdaf2ac7,69ed8c65,8a004c58,7bdfd0ed,355be474,65be16ac) -,S(ca0d97ea,537a5dd1,147cb784,eda20601,ba88e0d1,68e8df44,6d8923c8,353aba86,874ac858,89eb86f1,88ebb979,a4490e65,96c97892,874b5b68,167ca99,f68fba1f) -,S(51de2965,34807454,7e798f98,c5fc19c5,84a90a0b,e1dda24,7718cfb3,ebb797e1,81374e3a,ad04e6b9,55c1952b,fcdf9a7,ace0ee4b,99e487bf,87ceff58,3f7c54d) -,S(69d611f,3136be2,cce39bd,a1d48fb6,87b52135,365b8df5,151c6ec8,c1387509,75e2d820,563b64ca,c4d127e1,a5c29720,fb84c0aa,6b271fa7,e9da2c22,3195bde0) -,S(31163083,558660f,23220456,1dcde218,6fa4a4c0,de450a9c,b2f57de1,3a8aa135,25d6d496,b1341688,3008c636,ae1d8b76,29e14207,e5fbb817,539ddbf6,ff46eae2) -,S(84e342aa,efa9cd4d,4d82e5b4,4d0ad9a9,11f4623d,8684c274,cc3cd561,2c7ac334,fb90dbff,260f9997,c84f0a32,4fe5d2f6,f552affb,50aed654,fb8f660,2a92a70e) -,S(95efc402,969db115,22446814,3d4e3aa0,fa812aac,8867a5bc,64d66692,67bf6562,315bcc31,6149252c,56f3f00d,445255fa,e4567d9f,d77ab4b3,e82c1359,9f371883) -,S(5223623c,f87e9da0,bd289993,a55bb9be,55b40149,bb501507,e3d5c9e8,d78d07fe,6bfd0a21,dd2df437,9b1c16,b0076f88,832e921,db3cbdef,fa5808fc,ac613b56) -,S(f212d199,a6b707e,61d87ab3,109e1178,ea180f19,66b0a55d,f5f4cb97,c0cb0a4f,3280446c,7edbb64e,e47c3142,7c0ea113,7f511422,19ec3824,12f6b069,a0f7c84b) -,S(6b55063f,f25d76f8,2154431b,20058f96,e1e19ce2,210e1b50,835cf58c,31cfe8c9,5427dd62,36450762,46e99707,6f60ffed,558a82a3,dd7e31c6,492088da,9069f8bf) -,S(2539e5cf,a09690c0,12ae0c12,9e6f8b27,c9388d41,a82e1e96,47219d57,9b23045,94cb83f6,1e26a4dc,d1b93000,e5113347,31d804b4,a259e24a,77c457ad,d9021ac3) -,S(aa9b6ad3,4aaf1c30,71aed31e,8f28c3f7,9106421e,f0e53fb6,297fae54,a47d51d,dc0958e4,9fe4ae00,98b4e7db,10ab4d99,58cbd87e,ca443d3e,d1c9de77,83544c47) -,S(a850a313,aad224fb,f5ed6e63,5a3f6b0f,e08964e5,e9ca262f,780532f6,13487ad,7e476ad5,4cbc55c2,3b9708ca,eef3479,d9a5e570,26f15a4c,43b83363,ed4ccbe7) -,S(314fec33,f4fd0c96,d04889fa,b18e29d2,5da44132,6477b28c,7418d4ae,5fa09c1a,a2c9513,a98ffb7,9b5dd4f5,49534fdc,d9b4b8d3,1aa6a4a9,76b7b94f,ebd25f42) -,S(6e7dc3c8,9ec57e79,ae1581ae,1afbdcef,183998b8,cf52dc85,329afa35,4f3d0963,6b636805,6d5a8e9f,9651e3a8,2598ab1b,8f057830,fccac964,a83515f8,9d9f87d8) -,S(596df693,fc4ba2d5,20497a50,7d1841c4,38b6cfc0,58c274ad,9557d400,573337c5,6609ede9,1c97b09b,3a171723,e9ec5cfe,74b75c33,d5ccb3c6,bd03fd04,b37f4ff5) -,S(235f8dd4,10de7800,58550e8e,77bd42d4,ee3ba259,97bcb4ee,13cf0a12,14e8afb7,bf6e0ccd,b8e8e136,800f8d59,510a4455,53b72c33,824b71bd,189e158b,6cfa6712) -,S(a9d8ba97,b259e91f,125fbb28,c80e81f0,3f03906a,ef692279,4c9cc23,13db8b47,e668b954,19b580f2,67472afe,221f5895,5e6ce6f6,45ba737b,f14754ac,ec048656) -,S(53b44dc6,4f74c170,142bc629,51349b88,c4e2cc35,b7d9a7f4,827b07e8,4a288e5c,4aff13e1,404562c4,d8f006ea,dfee7b5a,32216187,d8c96c7e,5896e157,97075d4) -,S(76e6e038,a6baf9f7,1acb56ca,1494486a,a9187279,486f62f,947b5a02,580af1a0,51a5d110,66884076,44c18348,be045910,3b57e0d7,2266ffd4,465e6b4d,e1f0f0fa) -,S(7761ff19,2fc70129,10eda284,dde864bc,1c45b4c7,1bec7870,2bcf53bf,9bc1e6b5,80980f70,a82f7196,61f7e1fd,fc3e7d37,e0bb75cb,b1ab47c1,d947dac4,296e11b2) -,S(8199c9d6,1224f51f,e6dcdc33,3869d860,95c0bd8e,210d2d7f,8fed2804,a89aadf9,be89724f,5cbd2384,ae9bbd73,f030dc74,a158ee7d,2a9d292d,daae3057,4b1ec89b) -,S(15c279fc,760a2556,bbd62680,3bd779d8,8bd4dcb,e508b3b7,99d27405,91c55c0e,fd5038bf,ed80c963,4915d352,bca040fd,ea0b9b0,67215dee,3373e4d3,53390c39) -,S(fb3f8d06,b2804047,6f7b46a3,ecc2e7ed,9724ace4,14831a8,3c111615,f8a39b46,f9250cb6,ff851b61,3b3fd70c,63c1bd72,3177ed50,ac991185,4fbfb3cf,6bd2154e) -,S(39b2b547,3c964125,da2723e3,97c3fde,f9faf415,db0b389b,5eac9a6e,ba012edb,8ac1c2a5,a586f413,bd68aedf,1f65f231,6bce7bae,ddf9564,2882f2,1bfb7547) -,S(42d5dffa,e476151a,1d3f6d0b,bb24e8cd,bf72d73e,ac87e848,20cff44a,47f1552b,631d9645,d941c001,627ebe3a,f403bcf6,663f6e46,17d86ee2,922fadb4,b8847ee4) -,S(84dc96c6,24ecabf0,a5edd071,1e922d9a,630a0bd2,6d9c6158,e311fb7a,e6e0bd8f,40af318a,16b7324d,2acff10a,8bd2fc25,c795cc71,c0aa5a8,2cc8eae3,ef8703c6) -,S(636e760a,797bceee,11b812af,37bf7cbb,4663ba02,c36d93bf,1873983,4bbf505e,ed5c5e4b,6cc8cf76,436dab98,104b9458,69924f40,57d92ff,d74f703a,65f724d2) -,S(137fd025,4bb5ee78,669ca6f4,ae278064,7d32bc0f,f6175090,d4ff7580,98d06ae4,282d6aa2,25eaaaa0,e9b186a3,36e92e7,e07ec23d,e9ce4bc8,8fb7f09,328d0fd4) -,S(218ab848,39e49256,b55bc7a5,cb250fc0,df781f60,17abcb61,1b6734d2,12459e92,7eb14f56,b53fb0dc,430c49c8,d32f39f0,1a7212fc,701ca444,c994b3ce,4d0e1599) -,S(6b3f7ba0,106f22f8,df69e3a7,8f137605,1b2f0a99,ebb4f4fb,61915495,5f8eda65,c5788c4,4c946bef,86d9a4ab,481e8873,6c831000,5d36d3b7,aaafb7b7,2330d299) -,S(9b414ecb,a2de1195,196fdf19,62eb5b86,131ad1ca,f7fefd08,c5de31fd,d9e8ceca,38e6f31f,9550df40,80db0626,9da9f4e6,51e94e85,95e74797,639225e,a725a637) -,S(436b07a1,857425e1,86933af0,d1d444d6,156a4a8e,f3f2df8e,cbaf661b,26940653,94a52f35,f124ebde,ca642713,724fcc63,c6822dd1,bce4c53a,ce155b31,443f2d44) -,S(cc0a9338,9b25f82,33419bd1,87b5e290,b8d76f28,2099b4d1,fff32cd5,128fbc6b,cc7e86d,ec7ac7a9,448cb627,875500e0,e713ad7a,430ee9ec,220bfe87,6e3f458e) -,S(5a1b316e,aaf877af,cc7b1907,eaf8dcab,7ea684ea,72fbf888,8f21fe83,c3a19858,4af0339a,da08846a,6b6b3466,da69412e,74411094,22dbc450,cf7424ce,cd81e7e1) -,S(faf89165,74444bb2,1fe1e411,40398b25,ac4a5725,2f9ff274,e7d409,6d6c53ee,cfa7795f,af75547f,5dcb6426,3b16c9c5,d87984ac,81083cb3,99714f6c,99a43100) -,S(39e5fd8a,ca141623,1840c68c,6c6cb028,c94cd22d,49619e33,aa9e4dea,d174f248,f8121f65,7083da65,74013e78,88f66276,a8d3686,528aa105,61d10a6f,8c3c1ff1) -,S(20a135ec,147d0cf2,ccd3cddf,6fbe1356,a64b8ed4,219bc0e9,25743098,325cbc1,b17514ab,ea1a3725,4c101fd2,675d30a9,fa1d170a,811f06a7,15622ae6,ee82c013) -,S(a181a1b8,af48f73f,a13d69e2,ac75b13b,9903ca11,8a8851fa,b461c2b4,2c72320a,c96c8467,3f487e62,3d72c432,ad5887a0,a66fbd3a,c43aa5a,219c84b2,97a6df20) -,S(395fc031,720a5da2,faf5d76a,9516de8d,eb462695,5eb87fc2,752462c7,7db3ee4f,4aebc86b,53783895,ab4e14e7,c3ec449c,962ac869,9b340523,1288bf41,c759ad6a) -,S(a36de9ec,f6df2b96,87d632a6,1bb6337d,3fffce5,71b9fd17,4246b33d,1b64fa6f,784e4c4f,a133d140,1b212e14,77deb40d,620fe29f,d0f05ea9,cdbdc862,651999f4) -,S(8cb5a899,ecee4430,f7381820,4535f57,e55a3ab8,3dbdc359,d04746e2,9840ba8c,12a7282a,e9c3a3c1,2c1df0ec,c3d28b4d,731dedb1,ef02cb2c,b92da5de,17ff59a) -,S(de441e1,4d9c9ba1,90e37201,22fd1fbc,4cee72d8,b26b1f29,9c450b66,60b60985,add1a30e,d12ddd33,d4f740d4,427fbeb6,2927b3c6,75032110,508e2114,271b63e) -,S(88e38b56,b5e5544a,f2f3c1b,7128d118,520646c3,97295067,4078207a,9b9fbab7,8833208e,d44e9656,e5bac529,cbdaf184,dc8ea020,a2d8f4b7,8101d8e6,1000e5e3) -,S(a4f0f992,f5616420,b9ffa3d1,58d2d729,3ee217c9,60f5266c,6c5f3374,f4640a7,da6741a8,437a86bc,40ec9188,a1af42fd,b131a8e,81289e71,3d80e201,f82e6ddb) -,S(5f00a8cf,f2d1aaae,604a40be,e451d8d2,86899fbf,37f96ad7,efe52407,1c5c945b,135fc8b6,9ea76d6e,39d1549f,b4692d5b,b48ead3,ae6c662a,424b63d2,b59deb12) -,S(59351a0e,bfd6fca2,ee04c799,838ddb8f,9d168967,a9e6cda0,b416ce31,88f99218,6e01a267,3184f4a8,28e27b6d,4291e7c8,fc4159d,73a465b6,4fe3d4e9,d50fdb34) -,S(175ee35,f5c533b3,de87387a,5f263d0c,6705ef73,e77f39f7,2c796f91,2cb1aecf,a3792715,4540e426,1e0d40fc,4c5fbd60,5fca3b63,3cd7b506,a80d0280,b9d9513f) -,S(75189b41,597b18ac,9ab6362f,a7905ad4,5655951d,fad033b0,2047dfbb,f347b8fe,f536fd21,ffa10ea,57c023de,256a59ed,aa246842,845afed5,b0177b77,21b2527e) -,S(91af9ec3,2522d65c,70bd2a31,57efd23a,43885573,6b5a1c72,49a414,a19bd4ae,312007c3,8462b858,6b44898e,d0b4419b,31c9cc19,a2ca6d6e,6436bb08,741a32de) -,S(ddb2fc8d,41fad5d0,5d109443,2f283c5c,732273a4,1a14db04,712a1d84,a4565c27,4f7e30c5,2cec6f4,201673a0,9893d092,8f6ac9b6,d7f2da38,d63ba2fa,d69c1d0a) -,S(9ce65d22,d7240dc3,50144936,ea412539,ad40a907,f2b04f96,f7ddc1df,f63641a6,af93e587,7f25bc64,2460b425,76062f54,c3037e43,80542340,cf927609,79d97c8c) -,S(7dc0d0d4,1fedec58,91c3932e,b0bf492d,5489f1b0,1e7f95f5,4936d76f,776e9a2b,d55a279e,760c3c13,bfa1c7a4,93831a14,1e9bbcf5,a535934f,a5269995,b107c47a) -,S(d01215c,b6b4d728,9dd8d351,f3e4aa7e,f190d40f,3281c8c1,63d03a95,4c0e5ead,ef98344b,ccbd7eee,723ce7fe,641854d,c68be6c6,99eea25,48b2c881,b0fdc662) -,S(d4d1c31,a9faef8f,5991b0d2,9bdff3d4,bb6498c6,2933eaf3,e1d06767,8d7cb92f,98f3a848,ac6b91fa,85bccd42,f2185e46,715faedb,a4f6590a,4df5f862,ae6a4831) -,S(cc659ecf,42abf24c,3da2d83c,84b1e32,3d718f0c,41a1b5a4,9fad2f24,c6080839,7bbdfd55,4d843399,b6edf249,ae795758,c7aef094,3f84ccbb,f0f2761a,c81f963c) -,S(19ba1567,d5cff385,9d074e94,478bef34,f0eb4775,6708d04e,594d1641,71ea4b04,34ea281b,d536b02e,da858311,4e59c110,30555c91,c8b90ed5,d4f53485,4a820f9a) -,S(3f0f02e3,1a6e5907,631960e5,fd52d2da,e825d8e7,529586a5,437798f5,d7bbc30f,b93e27c3,3aecd4da,59079ddc,be2cd6a5,62a3bf29,7b40519a,3509061,e3e63c3b) -,S(9884c48f,35f63fd9,5a9dd895,b0f382b4,8d0fb096,e5fab23e,df07924,149ab12,5688c266,7070437c,3d5e321f,58b6f41b,e011545e,989feaa0,13f241fb,4180eb44) -,S(940f2a93,79bc9c55,3082e85a,c2f83e5a,bb4a6fe0,2b23cb47,4489bb7c,c46c7b4d,b4b82380,77ba9d8f,51e7c735,cbc6a784,2aa7429d,2cae2284,700c0e2c,7f21fd9d) -,S(a9a7699c,e5353d9f,41afeccb,b5343ea4,5f4beb03,42f9001c,e0742eb,58b782f0,3c759eaa,b3e18cf1,a4341f77,8a601ac9,b0536fbc,5fb498b4,c7ca9597,9587c994) -,S(a21e348a,9cdb00,56e36cc2,82d0112a,93f4da1d,23f274af,b1522263,b218913,141543fa,652f9506,6ecb8e28,a701e663,c70b1873,b1e778da,588c1f4c,7ebe89ed) -,S(d6d54d95,1121e118,52b298d6,18ce738,e8142906,306a5ca4,1f048fb3,5a5fd383,897dccb8,de891fe2,304fe9d0,38d8eed2,8f76c8f3,535a2912,41253445,828a7a83) -,S(7e0a635d,c937eafb,488c7f7b,5efb12fa,6232b464,a3a47ebe,21cc0f1d,c31e6cda,d2d1d4a,75525e1d,2ce5b34e,3adcbf36,74489c86,ced61e82,2d63ac63,8de921e2) -,S(4ce2080f,66a21c68,428870e8,36b3fae9,55bafa14,fac200d3,afea00b8,d451a659,29e1fa26,565b02fd,318d0f3e,f0df93ae,f0ca1b92,73e31b1d,891f055f,6c7da4c4) -,S(dab86b87,b633bf65,59cd5caf,1b89e815,e6d4b7b4,d8f58f7f,c091f542,712bad2e,8e49b109,d79a55f3,8d8159d7,f55bd930,4506a634,7e57bbdf,8fd15eb3,53c85b5e) -,S(c6a14ac2,90fa32e4,e8b5386e,a7672d39,ba16224a,152897a5,6ae29001,b365aca9,42aadcd6,dcc588fe,2421967a,42ff615e,45cd5f2d,fa258164,b2c0eac7,735dbc67) -,S(2599fa40,880b108f,28f24400,4f3458f6,63510bac,c8a1041d,e694e214,ea450a27,54792ad,4ae1cdf4,6a7a973a,1a02bfd2,a424c46e,548c13e6,951d94c8,7ba57a01) -,S(f6ab0cb4,a6afa8f7,aaed8fe9,e79ec43d,31265533,6fa4553b,bf3d7476,8ed9f9ff,4ea12589,c4ba0090,48c1a476,1907fcd6,82e913bc,57af13f9,73fd9746,845026ef) -,S(f51bd48b,ab8f020e,2d97ecdb,d3ff4da7,72738ff2,bc71dbeb,dfdd48b2,707f1dfc,6b168ba0,947f47fa,8a7fe7bc,e7ef90f9,b361c752,248bde43,8c93f3f,4a697c40) -,S(b601f114,6c9ca90c,af798f2b,1d0bf7d2,a50b286,53521362,5c898f0a,4a2a3443,a6ca3041,36b6b675,5f317a11,59f0f110,6877fed0,fcc167ed,f0cf2391,c61f87dd) -,S(792dd67a,e5957c04,76f0511f,c5b7191,5be6a158,f2871ccb,37e90651,f85f974b,9b7f5cb9,bec59f69,3a44774d,d2f463e1,1a4c1c5c,84ac3bcb,94175809,4b1dd44b) -,S(7d884669,33b6f4ad,b3700eb4,f02514ac,4c29c420,33c34377,93101302,8bb093f9,2fc8c35e,674500db,5287ead3,5e46c306,2ebeb5f8,a5134885,a2f9461f,b5e2cb3b) -,S(9c76eb91,6d0f860b,21b82038,77089435,ead4bc41,df82c249,10edb80,692a5351,72badbf3,38800156,1e235a6d,a8c7769f,e51d1e0,d6de06b0,d9998290,f5c88b62) -,S(a49b5638,3d8a93e1,55e52a2a,a1e47c33,8fef18d8,2dafc24e,cf5bb0f3,1fd807f9,1bc271b3,9bf34c4c,ee4b0760,bc934646,9dc392e6,1fce976d,bee58e8d,901d3ae0) -,S(4d3135a,675bb0b0,ca9d5cc9,68f1c72e,a704c9fe,77aea9e0,a4d6247c,dc634460,ae5d7cbe,72f5f4bc,f2f1ffea,cf02b13a,cb74bcef,68cced38,395a76ee,280cfc4e) -,S(59572fbe,17dd6e38,fc0421b9,b42f192c,eff95583,a9204e37,11f33089,9e53f588,57134640,a8cb3f9e,6a1ab805,1d60a047,a01c8f2f,9b72782a,39c45421,de1c7c24) -,S(73cccc6d,49b4780e,caaa1c61,228d2e9a,a5fff08,f5605a5,cb5ea1e6,712d9511,463a8d74,f986c8f1,1c12ea8b,59b158d3,6a52c06d,6a85b08e,dbb2cd4f,e3752cf4) -,S(b6c8ebfd,db620aa9,476f7280,e8fdcf6e,ae3885f1,87683d1e,e503c2a3,8c4c1e46,9a6faed9,f0210048,be575c2a,c8194a5e,76a25d55,f3215dde,b4091060,e7d39802) -,S(b4162e0f,92de5493,da996c53,93067de3,b9cc4a8d,4c21df7e,b507fc9c,4c5e392e,ccce10d0,c9211d36,46397873,3060d982,eecf2217,7b8ed120,a4052561,6a3b385b) -,S(46bf2566,ca4235d7,abe91955,2a0b8d40,a581008d,6544d9b7,a2a469d7,8d2b33a2,6f66fd6b,b8278841,92d82e39,cd0bc9d5,285b5cf0,2171ef1,b77c87f,c6785040) -,S(78446da4,e869a9cf,8badfcd1,b89c135d,b5422a68,2a9ef6b7,419a914e,3d59ab2f,4215b131,db7e46c1,9e03c051,f33bebde,3f5f31bf,2d428983,27d2b586,5a8c9ce3) -,S(86886a05,511080cd,42bdc762,95eb8edb,fa2b01ca,5cbd1d1f,4bebf001,5605f3b7,c71b69f3,5579c0dc,7078854a,83add404,f9b753ed,597a77d7,67507e77,f7914466) -,S(a02e675e,37f8fc43,fd38675a,744406e0,36d5fafc,b28a7371,e16d94bc,83713388,d6f9a541,835c80d4,eae16251,277e9eac,4ee66bd5,a1899c36,de3173de,fc41239e) -,S(a16b6aa8,432c6ced,cd110096,697bc04c,9b299777,ee287f14,ea4cc889,8492bf26,5c11a70,ef9e42ac,d0ed644,6ea7e14e,1e734da1,89ef1ace,d2fd7241,4e0db298) -,S(66a3f2fe,775fe5e5,d0ba1205,f7b81fca,12d7fc2b,f8685c5c,97114b98,e0f45b5a,5059bd14,a49ad49d,550daad0,30b4eb21,e626e2,95ed01c8,c1823050,5e5e3eaf) -,S(9a47a3ce,bf9a04c6,755c6321,61150ba,a1f09460,ea855785,96213784,5314b3a1,22da5ece,8f387e6a,f37c7045,b9296927,efd3a3f2,2b95eacb,c6cefc0e,ec40a80a) -,S(1c014014,9027b9a1,e3ce3c28,8f18fa87,12b25a53,49f9ac6f,97af6273,5b6628c5,672190fc,d048d3d6,b78bc34f,f160f978,87b49934,5753bd35,3a456c96,e448a4f) -,S(c2d9670a,1de5e876,5ac965cd,497e0765,8d137400,9e4ea31d,57effe5,2e8d84cc,ff818647,a6ddfbb1,3ab56b58,52956d08,b97a2e8c,f852379,cc7a7271,f13ccdf1) -,S(1a9fec47,16fd6a69,70ce094c,4141d68f,d21339e5,5396a691,e01b1e5,c996ec1d,e38eb2eb,6c8373fe,94f7639b,595de291,d29b8738,11f5d40c,24006d8b,93f8557e) -,S(b7df52ed,15e91a6d,40e9e500,6b1ab26c,53a51466,98d63bae,77856afb,1d8c464,ea60f1bf,d915fd8f,99d0706f,ff180d51,705c360d,a5fdac1,162ec530,b6e21254) -,S(2f95cca,bd092e2f,bdc86a53,40353350,918ba7f8,8488b9d1,295f9959,d7db6b5f,31456814,fe6ced86,59ea9c3d,f09bf38d,d5b0f893,8db1ea7b,5234648d,a1693ad2) -,S(763926c8,64dfe4db,6a1a432c,a37e4022,3b6ae1a3,7def3fea,883a6612,bd8a7c1c,f34d5b72,4378d10e,bb4b3e63,d80f1f98,a3e741e5,b9e4fa41,bd3f0a5,c361bd1f) -,S(2e43be7a,12916cf6,f312a513,fcb6c98b,708ce2dd,18dc4ebf,72a807c9,c8a31b0d,db919224,ce1b7e57,16e57b6c,ed514cd0,a3a9dc09,8cb59c5,971e99d0,dc24acfa) -,S(7d65e48f,1a867d28,76731984,afc6873c,2d1acdfb,13a5adf9,a56960c1,cd4a5561,9c73b955,f0957ad2,ff0e2d4b,caf795d8,bc992436,be7e69da,7b97ccbe,d983ebfc) -,S(1c6becc0,3131b772,cae166f0,4d715390,6b132c87,c5c76b7c,10b94a71,7819d725,2c3c64ff,94998533,97dd26c,dafdf608,41b84a22,cfb4906e,318c4d24,b23280ad) -,S(f5042a5d,5d118102,32ac83c7,d7edf079,aff339b0,7e9d20f8,198b2a64,13347675,19c10fbc,e644fc6d,2f238802,a045052,b2723f57,5a8bdd20,b597dffd,79a3e4c8) -,S(7c387866,c2c0353e,6e00c887,240e084f,e0ee9f0,2de12539,b4833588,bd4be300,ccc66f94,587fc58d,42fc49c6,d074800f,56f08855,6caf4ab4,c37b43,ef2b8f79) -,S(ece8ad23,d33adc2b,6ce38194,58ba2ede,104b35d1,1691f4e0,b7b206e4,eab3c140,eec976c0,7fa1d3f5,f3c245a1,2c9b728f,1c7e672f,53665e7c,5c6a408f,7c0c0a88) -,S(822b0926,a274dc38,c9eefecc,7d021774,b951cf19,3e2cbc56,a1baf58f,19d12b9d,48bcb10a,f9cac375,8314d2c4,9fcf0512,3638f008,510fe63f,1be0c2de,44118313) -,S(d26a3a03,6ef5f428,fa058d25,7ce62fe3,401dfe47,80c468a8,5cd2e77b,f85b8c3,98c39762,3a644329,7d5c6759,a308c2db,62f1bbcf,9bae4ba0,10fb1175,126a6fa7) -,S(7febb81d,8aa0cbbd,3002ab6,ca247d1d,24c8fcdf,bb1664be,b5b3c346,93019090,ee625bcb,12ca6da7,544ca6c0,2a84b9bf,966dc923,d8b23b44,6cfa4604,a6c3ec26) -,S(839e44e7,2d43b6bb,e6f63a75,cc3644ba,b7aa002a,6de2c087,33df2b0e,51d3473c,8368f635,26f41422,a563806,d775bf68,2d876d98,542b3da4,3e591e31,340fb9a9) -,S(52e947da,1c96e07c,9e2c84f3,23f2eed9,7e049b97,86d21135,ea958eac,db0d7afe,6bcfdec9,e0c70d3d,39de19a9,9fa72ba,bdbbe50e,dc44897d,9fa670e6,d473a831) -,S(72ec5426,5e4a743,1d7f6dd7,1c8e9e4c,c8b22074,cfcb00ce,db18c6b4,c67f3603,ddb9360b,7f9def94,f5ea6d71,51eed4ba,49455cf8,15bc9023,6156d4fa,786b5ee5) -,S(370a3f15,59a55689,16bf9ba,f2863d11,2ac051e9,d6a90f36,af39add3,1406c849,854cbda6,8517cee6,95ab5d3,20b1067b,ee80d993,235d1dda,ba3a0ec6,1f005840) -,S(12e57888,60d2fbdb,cb3af527,577ef6a1,41d1cf0c,f719ac6a,714f9a39,9bef5dc2,f5af7aca,5dd8126f,7dbb79ea,d5a4b475,a094969c,64adc821,ab46c5c1,86bd9ea2) -,S(b494abcd,b2fa5de,17b1abad,757bf9d2,8b7905c8,aca0a5bd,fe2ad8c3,30a2b722,c397ffd6,dad8619d,9ff8d8ae,e401a4f8,cbacf710,c6409adf,bf991d72,9294cb87) -,S(2957692d,900d0b94,b208245c,f71bdcb,118ea6e4,499dea83,1064605e,8ab9d89c,a3c55447,9284afea,37e94,fc24d50,f129342b,7ebbaa91,857d655a,40444a7b) -,S(61101879,f325e072,bca13642,dc14a5e7,1969aed3,2e49ccda,39cbf723,a1bd20eb,4e199c82,4816e4bb,d5b67269,e9d8eb0b,e5c2483e,d66757a9,c1d59847,e443b3) -,S(9eea48b2,99f3474f,8aa8c648,c2721fbe,c65f6ad4,990ab4e4,29a9c41a,ba55ab18,13954697,35ced1bc,7e857049,7f2b5a1f,b6802892,fbee0654,c1d7d89c,1f234443) -,S(dbb054d7,8ba7b707,ca475982,6a36808d,3fff42b6,31f1bc5c,c9df403b,518bd97a,396ef6c0,96343a55,dd404885,427e781f,a55a1f8,1ab95d4a,89d87975,611b923a) -,S(dba95bd5,7fdd2ef4,9dbcc0ea,35c14dc9,b2f62541,5b08e75c,d70f3caa,b61bbcf1,2af0965e,b7a17e46,18b6dba8,415159ba,b8f76ac,ae9384cc,64a90e32,d20a3d) -,S(6c312c9,7979bb0f,e72d8feb,c3c755db,bf1a132,722f6ef5,297beafb,8ad0e5be,36366388,db74739d,df78d5ea,3d8fab54,6c435961,71f78643,8be00718,8202c6ea) -,S(65eb7057,a494bc8f,549b8638,e18cd717,ad987030,aa3161e5,b9fe31b6,dc8825cd,458202a1,67f285e0,9196b4ac,f87068e2,160b7b42,2095bc92,7656694c,2fa80312) -,S(a0696917,b0e868da,ed5db7cb,d2aebd1e,c1117426,d842c0d6,b567e2b9,4effa7f6,c874d20d,a1bb4dc8,f01cb828,be8bda8b,c797ec3e,37feb0f5,ba55675c,41ecba78) -,S(4191bb82,19372a13,2dd37830,1086b64d,10874479,1d3b7879,3b27c65,782cced2,c74907c9,8ce4d218,d1ee52bf,82e130bc,49335279,2497b4a,34892fca,67dc3f2c) -,S(75f37d33,721293ee,5923b9b2,b95c958f,945e3f2,909c38f,3c3e7f5c,79b218c3,ac041f8e,c6b222a7,a2f28e18,1cf11aa2,a7d2fda1,1f402a33,9afdeace,a5928be7) -,S(cbc3173a,b58b2f29,20b3bef,6f18a84a,6004d1f7,1dd6c65,78571afb,96fb154e,c413a0b7,6f264414,2d3c166d,e9577ee1,b8f36ec9,618e8892,26de4de0,f9fd5c37) -,S(64e56b09,a139fa59,69688832,419cd1bd,64f212f4,5bf4cdd9,2a5e4370,dae226cc,a9194eee,f2429016,4b41eb3d,b429415,d10915a8,62a02fa7,671bc19e,50fbbbe) -,S(e33795c5,e2886cf2,9a22c2fb,8e02f913,34e13350,9cfc14f,73bcfb49,355285a6,7890fd21,f33d48c7,24e580cb,7b4bb065,f7c575d0,c6cdf5e1,5c2d6423,1afb304) -,S(7975e6b,7a73d0a0,d1543d2c,76c79233,6e6a0994,35eb7699,8f25ce75,a6b0b6dc,10b160ae,c68993ed,d5e48d5f,7562bc24,8f16eb10,a27f7115,121ce2f,f63eb06f) -,S(6d0d13cb,f9c13967,92e093d0,801f441b,c1ca4484,92ce3ce0,2ad71cdd,d1580f6f,17ae4238,84caf022,bbddcfe3,37a44309,4bdb25d4,71da56f1,bae4bf2c,ebb45746) -,S(2195f14a,23af2b59,c9fd3f90,42608037,60d39867,3fbd0856,a974a20,1bdf0154,fc05b38c,9a44ef01,f4db3a10,b500a372,5ff1aa58,86ff6111,da53ee14,f8136a8d) -,S(47679c73,60acf8b9,d1b54e16,7d1dd1a2,1f558288,3844fc4d,ac2a7fdf,8b713628,82a02225,f3b8e81d,e4d4bbde,94f7cd97,7ca0180a,ff3a4751,a93f6ca,17803ea7) -,S(b0bd02f5,1636a69b,23ffe514,cc2166bf,8cb4ff2e,2f7c8655,ac9aa7c9,de30831a,73fad62,48bacbc5,2a7ffc51,fbeba3d8,f4843b3f,ba6c8814,48add0d0,8fd5f518) -,S(dfaeffd6,bfe9f81f,ed3f81af,adbec5b8,aab5f15,23cb7452,c689b01,a3660158,3f54d105,c3ef4814,e6ca4bf9,ccb5b54f,30c4bf80,10d7b24d,f3b5f3da,c9240583) -,S(eb016abb,da661e49,8f53d2e7,96fd6be4,80dffae3,eb7e4ba7,46ae06b,f40d42ed,310d6dbb,aa7659a9,6cd4d50a,dc2e5e85,10f005ed,6d29d1f5,18bf83a2,7af895be) -,S(989e1bc4,3c0880b3,6d35b5eb,137f8e61,7263784c,d2f35173,e517afb0,c99fb2ed,4c4ceb5f,110cccc5,3a35963d,11df77d8,999b3bb4,c2cd92fe,b53b7476,9dfaa1d8) -,S(beb0170,be4a7bbf,1f65bd40,776d5efc,dd801d6f,909250bb,fbee1198,c2033811,1356b98a,1d329a38,57a99820,26d3ce6c,f52349d,fcc59644,ff4dcc13,8486461f) -,S(2d90bc1,986f9a4d,6f75e596,96c4296a,ea9bc55d,5b60d12e,337cb42a,ffc0b145,7d57cf64,734d1997,bf84b721,e67eafb6,b377ccbe,d2ef3b5b,48dc9f06,f71a0c4c) -,S(6b7a6a54,c9608062,de196848,dc3673bd,59fd53f3,fee72481,e829ca77,789f51bf,6a9ee208,157b8a69,f0879f30,c58afbe3,dd4dc42b,43cbf21a,5795224e,6c09af23) -,S(c99244c7,32cbdfe7,68df8fa8,7b7e7eeb,16faf0e8,8870fa8b,f4abcb68,368e8393,20ad1b55,53ba2ad2,40563453,b2dae2e8,58cc9b8c,c6a49951,bc0c0fc2,875620ae) -,S(553fc07b,402a8dc5,5f1cf4fc,609a01fd,350fef26,9c1f93f6,d2871f94,70f01b6b,3b518c75,39616def,fa7cd0dc,7d7d53ab,9b310217,7e470290,9c199137,34e5a824) -,S(c5930378,6ed8a7c,b3cdfc80,a34c85bb,721fa927,9492e369,a4e4bec0,c0fe2f69,3699e469,8a3e9129,3796dea6,213fd702,d7580e67,9f446300,1e1c7a53,3717c149) -,S(cb6f1118,f4d59964,b8f4613d,8c349d74,8cda0e7f,f1d11c6a,79dbecc8,911e7eb5,62b0ae88,98b0d5cf,723cc88f,48257c47,ca0fe3d,7de676f4,cf4835c8,fdde20ee) -,S(da2cab8f,8c26668d,d9722ae6,1decb99c,78b5d48c,966889a9,46fc522a,31a26db9,6a03377e,234f949,4a614cb7,c93b131,1808496b,12485ad8,fc21e1a7,6d0c7e98) -,S(fc6a4d42,3f9be3c7,fe337411,f03eef,fa595b83,9a6eca82,b228d5e6,b43b7d86,6c089544,eb8fbe1a,3dc78fdd,ac253fa8,27dfbd6e,269196f5,bb476865,a298beff) -,S(73c9a91a,b9c6e0d0,773258e8,3ca9460c,3d09fb49,9426fe09,db73756d,e3dee882,8b314327,efc0508a,d5a90259,c9ed876b,52040a10,45d06224,78cd635f,e571d2b3) -,S(a69f061,45b8cd1c,343e6127,14b80996,2bc02848,ae976762,933744ca,3b4516d3,87518d90,b4503741,ec16caf0,18615e27,96b6d91b,47f649ae,a86da209,d70ebe3d) -,S(1cbe4a25,70df40b7,1cddfb2a,c15ba441,376a430f,446a2572,fc95235f,28ed9691,12554ecc,f262e1aa,cf2a2d10,ab3953ee,c8ac69f3,99c5380b,6ef5d202,5613de85) -,S(8dea49c7,406dccfb,4305ac85,ba08b191,4ee2f11a,8827852f,d13c837d,b788e27d,c73d61a8,3b517c3e,bab8b15a,b7a0506c,2b6071e5,697b4056,d902957b,cfe9d9b0) -,S(de926377,b175cc3b,1ecab5af,81d38d6a,5e4b717d,55bc94f,6e4c43a4,86d0ade5,29d5f3e7,9169d974,d4289115,d8d4b8b1,6be387ac,e60d1cb9,73c387d5,17d0e11f) -,S(6e76eaa7,aeb37ab4,ab455a2f,3d525140,f6e8a9cc,5eb18fa3,8a9a25b0,d3b41497,7e3cc5a,78909d15,bbffb936,a47aabd9,44c40a3c,d690908a,89f193e4,95e066fa) -,S(37131ecf,22d57f0d,a662b03f,c9891f99,4678539d,37f5ff8f,9eed0f8,bc607574,c03b2d21,69d42968,f611d596,e173d4b9,281323aa,6abae6ac,c177a1c9,1249f3b3) -,S(72088814,82c89957,28e76633,bcdf0ebb,65155c8f,4979a4e7,66713f37,4a5d8152,6783c59f,8c0adc8b,da8e26f8,1990a00c,588a7974,b48aee92,d2a762e5,c974eedc) -,S(1b8263df,baca44b2,a7fa7a7a,dbf9d3ce,d4567fcd,144d9e8a,db712365,d3241864,1fc7e3e,24f01143,1944b98d,b2dac036,edf36680,80196785,783a41be,d788606d) -,S(7a372de,27ca7f2b,8199714d,bd583edf,ea41bae0,5a1313df,f1a8c260,cef5fd43,a0e3216b,b32c5785,b5c60f22,f5e4ed5,a5d3ab64,ba0eb2e2,916f1b9,b6281142) -,S(71815daa,55254491,c8bb9432,755ac1f0,c30f22fd,79d4232a,72bec0ea,8cd02300,8b341392,8de15c16,5fafcc68,84ebe3c0,3ade0918,4c463804,876f1600,c76471b4) -,S(1a54b7a,d3cfcc64,b62d866a,9f2056e,5535d4c,12c89c78,5d1c5c53,ff654d2b,b7c77ae3,9f4b87bd,22c77395,a91ec307,e9f5aef9,dd2892e8,41d8390b,47a12f19) -,S(85cb4457,1fc973e5,dcb0b695,3d75a2ec,22cd2820,74039987,7262b7ed,999c44a6,efdd1df3,bd13fe66,c0d4ef02,8e142093,58037a7a,bd06ed53,280d3318,9d0f6aa5) -,S(98e8649c,64a010c9,424b305a,2407a36a,cd72df8e,138df962,c35bdf75,fcfd4e4e,a804c569,34395d7c,549f7770,4c3faed1,624a8cf6,fcce08ef,cd3aa486,d5a6c60b) -,S(1eac47e6,a297e5a8,8f433895,874fac8b,5019a164,69c6a881,7e500b94,74a5a72b,8b7daa6b,784ddeae,f380bb1f,fe64b9ed,43a10a2,95c30325,f519e4ae,da11105) -,S(f079ac65,91f27363,17e9e0ab,6a723e25,e29950c7,a02a66bc,96c4ae68,44f42f5,ea87d1bf,c99f4374,4acc3ca0,214a1ef7,490186d0,3d924562,24981469,c432dfc5) -,S(d6d09d79,bf1f30e0,f011c3ad,a077b1d8,fa0d94e8,8683186e,ba471caa,32539643,8770bc64,fac8f541,f730494d,cdad2d48,ef510037,466bc049,876f5cc9,7caa8adf) -,S(376e4bd9,f8963368,7059565,68313f89,d6416ca6,b1e4e91e,3aff3ba0,b8351f65,ba436de5,67248f1d,5e99e8b9,6447cb28,497deea,47fae95b,78a5378d,e65f13f1) -,S(270f3a18,4b42c799,a2193dae,c96f834c,b17cb53,bba1610c,6578c741,b9f20d7,ccceb12b,9ab98bbb,a0fb0d0,1673377e,3a7054a9,f4a3b000,21b67328,57e7e5bc) -,S(ae271b64,1a1e5348,29e47a8a,93b496d0,b055d2b7,fa98ade2,f505a5d,ec1a599,14e9552f,39b481f2,522a9a23,f87afa9d,5847908a,53c1581e,45dfb244,7fc2bdd3) -,S(569eacfb,177d8a74,a9288ad6,4ee5390e,db36a93a,943fd6a2,5ec869b5,a7f28c8c,1cf62c32,9127642b,99a7508a,a6f4f136,bfda9af5,45f52844,cb9c71b,5f732f7c) -,S(77c7f27f,fdc4e7ba,a326a246,89790f8c,41bfb5ed,6d365e46,f277cf81,5f15b558,4d3440dc,138be5d9,566a6828,852c2ec0,e0f970eb,4501a43,25af933b,821c3007) -,S(d66292db,f1730306,a87f67e9,b044fef9,7d46761e,7b8301ed,132ed7d8,94adbb25,ceef7755,8ceca4ed,92145f23,8bfcb32b,3d36db14,6fc50209,cb0e58f6,2c8b83c5) -,S(1c42832e,12ea6f44,b77927ef,7ebb1f3,8769e3bb,f5507a49,25e8565e,a77ed0d6,8b9383a4,b31b4f5d,a717917d,9e1e41da,786a62a3,327be11e,280e538a,9c29d5ee) -,S(63e57eff,942262a8,cc362911,fb98cf30,60832435,3cd394cc,5d6abf77,b21f7968,9e3c1e2d,fb9083f2,4c344e7d,322ea530,146062e2,a25fb6b0,4502ea35,59b009be) -,S(be233fa1,86f38a5c,72c88e59,19094ea8,cf3ed3a9,b4ea3f9b,2a51489,97b83c90,402eb2b3,362fadb2,6e389ef9,edc537bd,40bd48ea,6296956f,efd19d0d,eddba564) -,S(636ddb80,4e7c74fa,9c5f4d06,5a730fce,f2cc6956,4a24b579,aaa0c3f1,61844b78,6a4a3569,583212c6,22feb59,897eac8a,6aa31ffb,916262e7,deef47eb,e6a2496c) -,S(d251c1d1,7250d87f,f7b5af1e,ee2f2566,215ae7c2,b6e69e60,5bdd6c2c,dee1c5e7,245accf5,7df52fa8,cab5c986,2b96658c,5de60d06,c84584cb,f554b518,7fb4ae78) -,S(405d4cb8,c62f133b,7051cbe0,54b06f42,9055f917,3ba8248c,c3bdc744,198ed407,8463df10,a8963cb4,298e8031,bd2bc3ed,523553fc,60746720,1a9abba7,305deb54) -,S(97f05aee,9ab33a07,e14a0314,4fda5be4,ab329394,1ce8f003,546ed8e3,9be983b8,59e62a26,7fd9138b,c4c70b15,533782cb,d321f120,1e3d1a7c,3be4ad5b,eb849261) -,S(3388161,18e125c0,6a9060f2,6b9ad691,c99fdf8d,4309553d,ea160749,eb91ac8,583e918b,5b8e1a68,c053af0d,245a9902,a571788f,dbdc0c88,7281767d,9404384b) -,S(ddd20c46,6bbe6a25,9f706b1a,ddc3b607,8cf65366,3369fc31,dc8f7fd3,3d17a9f9,b2df7b29,b4ea9868,bbaadcf4,6621ccf1,7833e159,acb43daa,7cf78e89,c1de5a99) -,S(923c6d2f,71ae0ee5,596c26bc,31389cbc,eecd0712,e8df91cf,dfe00172,3bdfc9f7,6fdb28ad,27c41243,6a41ae96,99a03d40,5ff2ed87,3207f082,414a4370,34be948) -,S(6d42a6bd,28d57e87,66a12461,b8a7d111,a448876c,149071a7,fde9df18,dca09e65,4df07ab8,1dbe97c,3585554d,f0226234,dcdd2826,747f2775,640bed6b,95fd28bf) -,S(7fd42961,59f9f259,d3c3610d,8539ece1,70efe104,31c9a3f0,4b9630ec,21d761ae,fd695441,b8ce2bf5,1037d00c,4d50e640,e85b6001,6d5d26dc,787f1df1,25d7e280) -,S(48c1050b,128d97df,e7900a01,70559990,944045dd,f408d8a7,5b59bb25,ea6770b5,8f7ceda0,4b6e319c,1cc61b31,53538a09,d450e49f,8863061e,f9b017c1,6cf66559) -,S(54462d9d,a12d62dc,96abaa1b,4883c67c,b3214c40,de5a4a09,689658f7,dee2a686,7673ad6f,916011d7,fd33bb5,eee819e,6a3f0016,d51ae37,bcfec2e,59ccd957) -,S(698534c4,e4e11d89,82a5a46e,44b771f0,95c5fe47,54d7a261,44373982,1e6435e8,36d602ac,b2720c71,8d619a8a,5e7d6873,9faba099,f71c1137,6a8f41d4,e1cbba18) -,S(4493f759,51c681c3,bb376b0d,7c88ecd9,d0bc2a21,26fd341a,d8c4832a,be77ecc,e553e21d,d4d99aad,97f15857,4bfd54be,df7143f4,e829c12a,39109892,c120351e) -,S(b054daa9,330080e1,89784cf5,f917c024,6c06325e,687e6ec8,cf8be248,ccf8313b,51f04715,5c9ce55a,c755f2a4,602420d,4ed52a5a,1dee9a83,b0688b1d,b767d866) -,S(4b4272a4,fa996b1f,9ffe6796,e6519db2,c1f8cfc9,606fbc57,1fe03713,c029583e,9526f2d0,dce7c53d,5cb36f8c,fcbc517b,cecde833,4384d10c,f5fc80a6,ff0edb83) -,S(d61eb681,c69de82e,caed8e64,7d1a3948,6cf63f83,f1f04bff,46a04aa3,63e29604,9b5a92fb,156d7b8f,37c6d9a4,30ae28eb,f62fdf5d,5bf441df,aa386259,721f08b8) -,S(bf8f002,57f979c0,9f973c8f,3dc15eb8,8349e340,efd8d57d,5763e4e0,c2bf507f,561d862f,1041e670,fdc265a8,36d363a3,43346739,f4f177d9,f66414a0,820614fe) -,S(63b254e2,a7a6fad6,4d9ca03f,7293a86f,b471fd45,51ec72d5,eb03e289,774cb498,f4145111,3a4ce922,dc7b3819,a2de49cd,f5be7d53,6befd880,837bbe7,51948c8b) -,S(bae6facd,e1da6ed8,63491f33,c4c9efe7,50fdd908,6b93c09a,e0418a29,d3968725,7c7dc955,e483176,f6bdf74c,6654e6a2,e4ca46c5,2526349b,b4d66090,6ea30533) -,S(f56285f8,ea15aa08,f3ed8139,59c660b0,d30a6317,5380429b,59584623,aceb34af,110033c1,a202194a,40703c9d,ea2dcb9a,d9a0f6da,7b99b8ee,31eb1ce9,55a9eb9) -,S(876c7c95,3de3d451,edb9191c,60e8e36a,eafbad2,198ec6a5,40d72633,8151d87a,95efff74,72ce0c6c,4010d17,7e52a859,cf55011d,1005bd27,df54e25e,972279b8) -,S(e956c7ed,77c7bd5,68096902,4ab1c758,a024d86d,ba3f30e3,fbfd83ac,940a6d30,1b5dfca6,f0d19ab7,7a57a9da,259a564a,5aa5759,ce6826b,45c71771,7aad9da) -,S(f53fde61,abdb4543,1456e9c0,65048cd7,ab743b5a,81a468bd,8fe2ffaa,99dd3f16,1d28b539,47ea22b5,178e86b,ab3561bd,a65ac78e,e0e2a6bc,1a26b64e,d790222f) -,S(b91a8681,52eb435d,475b9103,936a7c62,5e49b0b4,f7bcc3b5,f5d36449,c8043ad9,c758d17,56939bc0,61696f3d,11dd1bd5,722dc90d,1e8be88b,b3430062,a13aaa75) -,S(5a87bc70,23e32927,db4c55d0,abc97536,61f5adcb,b24c2897,b16f08cf,8d8f8cc7,9ceaae4b,aa6a0d5c,46d2120,fbff74b4,9d1ac32d,88a89b2c,3d2aa6e0,6f731e54) -,S(ac0b1b43,e54eb354,3bca80b9,efc5cdb1,215622a8,66b66e80,de979f79,71ceb034,a891575e,5731e152,17bc2b87,197da9b5,439477fb,d2bf07f6,9bd13f3,f4638d8d) -,S(d3c41ebc,2017cd82,76f4d6f3,f6ba2370,e84f1949,df3abdc1,45073467,e85ca915,52ab1d52,8be55945,1f6b1e91,610fcf35,bc1e9576,3ba3ece6,9da5e4d,8cdcf7b7) -,S(68cffc57,f4c82cc6,f7900d00,fe1b0f36,ab842e4f,49ee9063,4d1ebe95,47923b02,729955bf,aac10741,c3fda281,c18a306b,367ba904,baed26b2,6fe6a485,9ab1d8e2) -,S(7e0f58e1,246299ee,e08566b3,35324a66,579dc765,343f874c,d30f2553,8c177d9c,39652583,587293f0,809af7b,5d366740,86b9015,6a05928d,cd340196,8821447c) -,S(c72abbdb,d1816498,eb53d4bf,1b325fd6,5dc45086,73257bbb,97a15eb8,e4c9b542,3c8fafa5,5df5f3d2,88441ed3,e46cd318,841a068c,b681b782,88e77afb,2b25a7b9) -,S(74747f5d,3eb09144,1f64d76c,ef690378,943654ca,73fe15a1,b720abb5,d2363d0d,12c6724,bc7e8f7,321f993a,5caf0547,bf54c1a6,41f959b9,746fad7c,1c443649) -,S(f2a702d1,ab1de7c4,34cb5d71,dad689a9,29db862c,d1fb06e1,212ffc8f,91b67067,5b91e2c,c730ac9a,cb7452bc,7fb4dcfb,1d5ec11a,bd146429,62c7bd16,37afd854) -,S(a92d4f08,14e76b46,5fda87b6,201c46e8,c2535b3d,4be91e1b,530b5634,d00d9340,4d829a8f,3c02fb40,569fd9bf,e754dad8,38d96dbc,2350f0be,6f4ba065,5cd0277) -,S(79e30cb1,ac06c3b3,f90ea320,60a80fba,df5ea142,84a15746,2aaf917a,26f205a1,ad220a0a,81459495,5ac8a79e,d0cba974,7f17364a,9f6168d5,3521f276,c8d5c82f) -,S(6d55dc53,d412577f,463252b,e240fa32,88c8d6a3,babd6ff3,20231b6,8c9401d1,83a41c96,aa3b32c0,59155345,2679f056,c98e17c8,a0a5e154,d732fd3,7b006eb3) -,S(cf9c9f1f,604eb909,b37ea5eb,4cb8a0c2,11ef14e2,d3e2f48,7c83b56a,49b3f20a,2b90b9f6,4e649988,77260b5b,ecb441de,da24eaf9,df56ff93,dd3d1c8b,a247dff8) -,S(60d4299f,29ed994a,b3367780,9ef6fcac,e30f435b,ba9a8346,a2fd925e,186b35dd,df69b88,b8aab4c5,8ff86ddd,2d8e424b,40d51a4,9d189437,37b23695,4760331e) -,S(d93a6edd,1b674a60,6b6bbb85,4114a3bf,7de3be59,82cd2122,887c5376,d9493540,87da37d7,dc79197b,c0159006,4f921ae7,acfdb08c,447ed230,423c51bf,f9e5f7ff) -,S(cf8c3d37,7e108d98,b72bb6b3,1cb7b5f5,fd5869da,1a06fc60,25d9191a,bd652962,6f5cd02,bb96ad02,db42b034,321b3cae,fc54271a,879edc93,afc9c8b1,34128fbb) -,S(6ca99247,4637ecf9,827ab65a,c7b9ca0c,715b9048,f24c42a6,90847e68,8cdf29eb,51378da5,fefa454e,d96a446e,dab57c3e,8bb6160d,d015c1f6,d93983e4,feb55439) -,S(6f7d2c04,3cb813d5,dea67758,cacf2e3f,3cc3064d,7b9f08c5,58ed686d,28d17afd,4794e278,13ecec48,33f9106c,17c5e161,b590a5f2,ac293c8,c65a6cc6,5233bc6f) -,S(f8aee0d0,bc9883f,ab6a82b0,184e9199,e818d01a,7d99f475,d2ca8a24,e924f3e1,acf9cb2b,69135df0,9426bfa,c6b1b3de,44f1055e,5cd21b8a,b526f34a,839442b5) -,S(8b00fcbf,c1a203f4,4bf123fc,7f4c91c1,a85c8ea,e9187f9d,22242b46,ce781c,61e9e58a,3e81e690,ec026428,ee5442a,a8de699,dadfbcac,478985cc,89d35bc9) -,S(fbacbb07,8e84a2b2,c201ebbc,1cc3212c,a7278523,e984bc1a,b0eb7fa1,39d6dd4d,2c6c9dd6,f5eb0899,797df675,ccbbaa25,4e557d5f,d16c6083,3aa84a7e,4c3a0f52) -,S(1556875c,2f32f053,8d28f993,53ba2804,5ba601bb,3df8a175,bfa33dac,ac5c0611,53623050,c3da9464,8e9fb540,5888e387,d2eb783a,10e45cf8,ebaafe84,a4e240b7) -,S(b602b095,7f5b5e98,ce3e690e,c683f803,49a8ced0,5985f79e,2e972bb0,2d93d77,78868390,ddd6b821,e30046ac,b1bb7b31,ff358838,af5b89d9,60d39b4e,85435227) -,S(2a110165,23a5244e,89d66f8,a06f0553,7a846216,75fe4377,24f51501,da2dd17a,24d3b525,e1ca62e9,b02de498,30737f3a,b881d078,7d2c2bff,938c53a1,b8825159) -,S(7314759,1148f9a9,ce326a8e,4f43d2d9,a13edb92,56fc9d38,35a35da6,457efce0,b195cc94,80d0aa04,d3ac7cfa,45766472,1ad5adf0,3060b790,c7fb0ff7,77b2d8b3) -,S(a36e4fe4,c7e23d7,16362979,c5a9d8e0,525d864,37d96e3d,b2f45edd,b36206fc,56ace785,a428db4,a8a70de8,708339a4,346699f,697a6707,c745635e,66844751) -,S(97864be7,a2c54118,5d61b61d,5a2494f4,85b877d7,e8864402,3444d778,f43cac9a,43332a78,a85b8391,551dcd90,e93e71c,3a6c5428,71b980ab,138eda2,b9f2ff69) -,S(34a52dbf,2449eea6,da2c92c8,45dcd47f,daa7ca41,5ff02458,b74eb996,8519893e,add41829,900f26c9,f7ba8d55,21f3bb23,b3545a35,699d41b9,4270547f,e303ece4) -,S(e250aba9,94eea617,5fb7b2b4,8631f5bb,d8bdbbb,799f6fcf,5afde8a6,2ff3d629,803f34f5,9db0fa86,bcb6fae,689530fa,2e92c4ec,bff1757,409bd836,8143b0ea) -,S(18356a6d,b5946e2,1149347a,4558e116,7953042e,e3b2a372,869ae29,b871ae00,56ef0971,6b176f81,e1f98ec8,dca127c4,ba6de23,ba8c1f08,f19e9abb,995385cb) -,S(35a8ebf5,e5306084,365ef3f,30c29e56,ca5932d6,f73d688e,ed3cf2a9,10205533,9eae5d95,42954de,23d41032,5ada759e,20d30fd5,c2d058c4,53a18520,7f259958) -,S(37e06f5,25ea8fe9,ea862b92,53a965f,7b3dbe90,9ca487bd,a705041f,e6a4e1b9,83919fd3,5e489bea,23f13b60,41a19940,3f2f6568,fdcf60d7,3f57fb6,1fceb97c) -,S(abbbe697,ac6c002f,11062947,6e4a6ffd,48316646,718d8713,1a4dec19,5e131c27,b2c926cb,9d5122ff,7f8d8a24,a20eaf4e,fd704944,9aa48300,92971572,b12f9dcb) -,S(4df36acb,1484dcc3,f7c29c8b,78915315,5a1a3636,aeaca043,68a585a4,69b05878,fe16fe6f,c08af026,3fc417fb,19564534,aa059f4b,b7fced09,d4fc20de,6a41c41d) -,S(5ff14ee3,10256a0a,889570e5,ebdaf6af,c8f49c60,dc7c4731,23a7d29b,e799d0d7,96ff1538,55eb2fac,8f2a923e,ead9851a,95382d6c,56cfd0d8,9891d2bc,f7e65d7b) -,S(16a12c52,c1d422f4,791281a1,b7ab7186,a24dbac8,36af6810,4f62dea2,855d119a,7a6ef272,f67356de,46996cb3,8bbaaba9,d36a4bf4,60e3b2a,b3a81723,24c17478) -,S(8f4c9c33,83688920,a48b3d15,4fd567e4,5fcdbac,bea44eda,60600ffa,a1489ef5,2bb5bc4d,e06444c7,b2bc0082,d629e2e5,a4b0abd4,8cbb9b4e,37d564ca,db885717) -,S(498bf39b,7547010,854ca399,e50399ca,19236d2f,d05f5777,6abd6d2a,aab83310,8e2debff,cb58e36,bcc7beb5,8a45d4ba,b5edcd46,2c355d0c,4dde51a6,6afd691c) -,S(78147e0a,2978d396,b22247d1,74958336,2ba51d90,11e89c11,71e6e136,eefb5996,a66b7b0c,a73b661b,e71bf0fb,2eb4410c,4c75bff5,b8b05fd4,1d830d27,ff85989) -,S(351298d9,fb236c7e,5477aea1,d2df0048,47e112a2,e16adf66,3f4d77dd,828d4927,6c9c91af,8b6f23a9,d15c3884,e618ae51,241094d4,5878ff20,67f2ac81,dcfe00f9) -,S(fb5ffc0c,88fb609c,24cffc14,848549ad,c1814668,9e5f8a67,a342bcbe,16399d10,a995e13f,9ced94cb,90feff32,8e92e978,88cf5791,c885ca09,46f46e5f,b8229ab3) -,S(8352b7c4,4cc09c5d,717bd197,40dcaaa0,89565e94,77cd76b3,6c7a4fa0,4832097b,9507c998,fa25d9,758ca78,6774ae68,f91c8fab,694c5e23,6f8af6c7,7d0fe6bc) -,S(1be65c0f,273a2746,d6d014d7,6bb1c595,5d5ed1db,62ad940b,d8204115,85919f4a,dac98f30,2a38f839,a3d470a8,3ef83ae8,f044e93c,80b23552,da3da359,5c09a3f2) -,S(7107f3a5,2f4be227,eeb65037,ae800f64,8de14d89,ebf743a7,ed65f98c,b58418e,bfcf1c09,bd1af327,d14e429d,18eeae45,927b2df2,aa15ce60,69f6a74a,69fca7a4) -,S(117284b,e8edae5b,1ce54a13,3b1f9d98,983389cc,a4ccff,9dd04973,97312e3e,91e48c1e,724fed49,8bf51999,4c84d0b8,84e3af77,86e61539,638b45c3,8212b03d) -,S(a08d86de,b1ff9ab4,651f1cd0,d89b6714,41c243b6,c7e655de,d31b44a7,b00de54e,4d0fe7f6,344d39d1,57764fee,f74cc949,a72ed8d4,c2dbc12c,ec2629c,830f0d2f) -,S(9c44c1ce,df67418a,eef2cbf3,68d48a08,98cfc633,de711550,3f78ecb5,a4e8c25f,3cda2020,86d3f096,31da959b,9f9870c3,de3d3c6d,e4c1b35f,81f64dbe,31e743fa) -,S(d933e475,5215c065,bab118da,6f24d714,f8597949,a52ae319,250338b2,2339f149,5fb0f28e,313af04d,de3abfa6,4981287,e277e39,d2f19dcb,547d6fc,88baec45) -,S(7fe1f197,ddd0532c,a2010528,9f243bc6,4c2f9e53,65aad5ff,63c0f1d3,188a42cb,813b133f,a1869218,ee361828,6561e75d,a9ec6bac,6ba2ac7c,d3f5678f,fe472af7) -,S(e3568521,89612102,7ad0789c,72dc6d57,7ba412ae,b3d7551a,96aab952,c507f79c,7645c505,8e2ca8ac,ae5fe225,eddf4d45,7d820114,cd5e69a8,4966465a,423e3a30) -,S(c56afd46,8a5644a2,abebcefc,3b6a9da0,c667a183,b822780d,146ecf82,b6ebece4,9e41c655,a80e2844,89fc587c,b686549a,2915ba14,1c691e75,cc635f9,54f1a8d4) -,S(b242eb39,60e6a8f0,73b6042e,1095f0e1,440f9f8f,d1abed56,ad1f26,a1589345,944da76d,f063f0a0,3602decb,696f2a34,378579ad,e8469ca4,bb5041e5,876dfde0) -,S(3a52fd66,6d2e2e2e,888a43f2,fce68703,78f835a6,b5c3bd42,af57b107,323bb827,12e51177,a7b37a46,2755cea0,18f4f29e,96c7d6,d0e434cc,4874da99,a7af91c7) -,S(b77d5615,c8831ad1,147072d2,598a8c6b,4a71c0fe,967a6cf,70877aea,24d28f53,25d5b7cf,a068a665,deadf83d,5f793605,f5cff2c3,36a8d176,d18c634,9ebf3132) -,S(e4420c3b,61e435a8,53784728,8426aa27,f23d224f,4ff7a14d,79898369,c08530dc,422b04b4,857984b9,9bebd74e,1588ad96,9b3c67a9,89b119a7,f7cd2c84,ecca8572) -,S(888bfdbf,c6ab299e,3ba0fadd,a614fb01,236e3c44,98ad07ce,cae08105,630aaaea,86e7253d,58cfe580,628fb94a,a1a8f40b,7ada97c9,d8713453,f06f4773,3770eb3c) -,S(f74d258b,f7d78b30,ddbde398,a1398164,d850f2d,48616cce,8ef4c436,10ef419c,d13d49af,1e6dadfc,94332213,cbb12d32,5d60eb6,d48cec9d,fcaa7ff2,53029204) -,S(a8b33e90,98d60483,a7009786,11b92257,65cea0d4,b7ac0ae0,67914110,5cda6df0,58cc238c,c08d957b,1172598e,96ff4762,1182b6c0,652c9ddc,650f3b51,3521c553) -,S(5af8b154,7477fad9,8e5dbbe3,d4a1a15e,7a4a6cb6,5ae13cb8,9699470a,1a3ef1ff,525ed201,d0c61832,36c8fac1,366e8173,3c0a8c15,b6ef7672,cc84b1a3,7d6f25bf) -,S(155c454,6d4c5c4a,21d14383,3df8662a,fa71e665,ab7ff0bc,8119f29e,3bec21c,20e99f67,2f641185,cdceaefe,8fd7247f,63842282,edeff6d0,378966bf,50411aae) -,S(53918586,ee182d66,e7c22aea,5a663770,c8fd7f0c,6738d473,1010660c,7425a56e,c7fea092,3052ec1d,7e2564a1,e70b8924,cdbf727a,7212052f,abc58d9d,1856152e) -,S(f7964dd9,a0fab716,74804abb,a7740f4d,cc52d7f2,8d5acd4f,67998bba,3bad6414,6a989f64,aba0f60c,e7bdc5c2,aec11de6,d469a122,f1bbfccb,31cac834,89f62c59) -,S(741c8c8a,f514f2de,7880a909,b327c6ee,ffd72ee2,b5b1658e,72059edb,cd663183,f35d276d,e5de1460,dc53532d,48afe736,e40b6b31,fb6fdb49,1224544,a487b2ae) -,S(de8c69bf,6cc2a28a,fc6ea9f1,26ef4f22,606e55f1,312177e9,b2ef8835,8b47945a,8de62853,6900d614,780e2fec,b4ff7066,70d84742,3b1c852c,8b85ca4b,40a48a02) -,S(81e16f39,619bb41c,d8a523b2,d3dd0135,d6a8d5fd,9a8446af,cd058ea3,6f57c537,6786fc73,7cd2ecca,d146de9b,951deec4,375c434d,7dbac32f,2395c265,bbf4b31e) -,S(459e9589,d079b22e,8c5625b8,a725b30a,e70f7f04,8ab21a20,f0123aae,7a6f988d,a56ede93,5b71a292,c4ad26ac,cc3506cc,915de21a,4557512e,e767e8c4,33f38e08) -,S(b079d755,4faba7ff,20818806,a70b4ead,f2e5bb51,d1abb758,2284f385,868ebddd,495ddc2d,552f174b,210f6577,3e434fa9,20b6c0c4,574601dc,fcf5b701,fe74dffe) -,S(75391bbb,5983fb21,41580de1,dd5b10b4,bb30af17,3f05c100,569abd2c,674f288b,57c7a6ba,c9154ab9,eb66032f,2135a52a,b319f534,d1f1c80d,b58a4af7,de958d67) -,S(71436957,f2848f75,fc461069,e4fc691f,5bda94f7,32fcbe7d,5a89e136,41524db4,1287f852,ef4fadd5,65a2813c,51b93c81,95658a5a,5cef224f,e92511db,df3f0007) -,S(b9038b33,fa75d097,dcc74c9,e25970ec,94ad076b,7279f785,3b7c98f1,41543f9c,a28c3169,69295ed0,3fbc1bf4,8e39c8d6,af59cef3,d6f66660,73470ab0,dbcf838e) -,S(b2c63c28,a9fbd900,fbc664e6,36dbe0cb,f259bdb9,d67c34b0,83b8af17,a5f86196,a8f050fc,69c63c4,67308421,89510ca5,b7920723,6f5c12b0,ee7103ee,cd49ebdd) -,S(cdd2a5be,a32b2195,f4a7edfa,dfb7c785,d06bf346,f38e928a,5c92cc7a,2417f39c,ab66e78,ac421c36,3203ee7,22b380ae,2133864c,83829f04,d2daddd6,b7fa621b) -,S(825d0864,b079a737,acef03a8,28838ec5,a27d740c,724f9c39,780cfa61,9f3db80f,bf3ee8b7,749e44a6,7f27e427,fe05eba5,c2154fad,bc2e2b43,a877219b,461071d3) -,S(37b79e3c,bf6bf402,c96930a8,79f4ce3d,d0c36477,f0b0e218,608b890f,bf5e24c7,d97142c7,cec5630b,a090ff4c,9213c2f0,c32a5bb2,f7b0ee29,2045ad03,10f66f1d) -,S(fba64ad0,678ea75d,409105bf,5b452ebf,89560b0e,fbb079d8,aed22c33,552b6135,e665362d,e4e637a8,a85dd844,1a806ad7,5c628f19,7d6dbe3b,df63c0b2,d1f938c) -,S(76787b8e,77ed36f,9d84897d,e84c476f,d3bd490d,184327a8,59ea3f97,ecd9cf72,cf79f14,1a3f38c3,cc126011,d1d78dfc,e3ba228b,33d64158,210cd942,3980a9b3) -,S(26babdd0,ffb3a334,85e6ba1c,5661a551,f16a129e,42f9fe8a,3691a50d,157b31,1b3a4ae2,b1cf1a46,fb666e33,a20370b2,e66a6c71,27edc8ee,e4c4072d,8c2c530d) -,S(15aedbb7,7a2fa1e9,7a6aa864,7729f28,7ca4d3f2,36046008,c1b031d6,9f76307a,3342a142,bf8b2360,6a574643,9c05f36b,f9408878,5354c788,a6dcfd96,ff073649) -,S(98ece0a3,9bb7cd4f,df4d5767,c6ef4cc1,c2b072a0,dfde5fb3,de100f57,466fe467,c4e924a8,218c93e7,eb829d0f,839556c6,1e679d29,6a0a6bba,6f4f463e,ab227e28) -,S(7d867505,fc213eed,4cdffafa,b067bb71,8a48cda2,fb323304,1989b6a8,3ff373a9,5df51ff0,3c212078,197c417e,f4a4014c,96e167f8,8cea0c1b,9199ef75,7c97d47c) -,S(f24f19d7,43578e1f,be3ece8b,7b00d5e2,bf269a48,9d76d17f,410b73a2,95b3001f,644a43ff,55448b66,7b048bbb,b34f4c79,16d2b547,5148020d,53e53627,623631f) -,S(93853304,5c22296e,1e911281,ed4bea22,1fd1061d,2039a27b,923dd3bc,800efd59,22988cf6,cd2d15,f799bbf,e4cc905e,2607da21,e9fad162,8c2fe699,8beb7040) -,S(f090c705,39834f16,253b14ee,8e4d2685,b91ff4ec,9897df0d,af1531c9,46319743,c1171885,1d30271d,a8a08391,f53a02b6,28c59c8c,9af3ad2a,bf158341,280bd522) -,S(e8fc8ec,ab5bf3b7,4a0234ae,b2a8eafc,df9bb08,a90078e6,7fb6cd3e,fea78c6e,b08165,34ce9bb7,46efcd71,362e0a75,a8397c0b,490e75c2,9b007b28,26ddabe5) -,S(46258cd1,87cb43e7,3003cef6,94af37e3,c7426dba,c8033aa0,9b0a0d71,9f126785,846141a7,5f060822,764dd82e,2c369821,75576ebf,7082c6d4,601ad237,55ad4fc4) -,S(e7f38b3b,db3887ef,529d27c3,f433410b,94109bf3,45f9b7a1,e65bee6a,cca3e430,f52440f1,5eaec702,90adec0c,b07e8ac,ab1fafb7,adbc8f81,9fac349,2acd589f) -,S(2d29e833,1472798d,75fd5b75,1f569da,fa9a0167,f73fc62e,da5b03a5,2f537aec,52d3dd1a,b117b9fa,a17c58cf,c0593603,d9e2f55f,5a230001,d18976e9,792d2be6) -,S(a3b2ec9c,abf7a7b7,77fb44c9,c7552dd8,f47609a4,6f943c7c,8ac97d1c,3891ffb6,6ce38c70,f091381f,53093385,22a5ad66,4d528061,5b01b417,d559cbbf,3cfc19de) -,S(afcb3c1e,7582a56c,e6504dd,ab3d1a8e,6cefe762,58543015,a21f65d3,3100f473,6baf1f9d,fbeb8499,8a6afc61,8e193103,67edbd87,57b2c4a3,8e5a76c6,8b171af8) -,S(88b2f212,dc899567,bf62bbea,9466a8c2,6650f74a,490b86ec,cdd35625,d90e2ac8,73fd757b,def6153f,d7f6d4f5,da1723e2,6ecd6c42,d994a08e,7e458a64,d18c30a5) -,S(bfdea9f,4ca32916,651c971d,7da6a2a7,395c5945,5c4940d4,93d991be,1dadef3c,82747044,7ef3f684,4200adea,5b8077cc,4166bc65,1f6d4a17,578b64d8,21bc20d8) -,S(5d45cb81,aa765d69,ca52e386,9491ecf0,e8fdf6a6,3d64e65b,5213647e,e4973ae5,a4a4a32b,51a76d77,773517e7,c103a7dc,fdab36fe,3cafa2bd,b17f82b1,2fd019db) -,S(f3a503ce,e14e9994,aa34fa53,1c43e5db,6d6fe092,45d2f3ae,87d06753,7ae7109d,2b1714c0,a24d50b4,20722daa,d1951b63,568aa5ba,7325785,ac555e55,f3ec49e8) -,S(94c3a76d,6f812ed2,454c225e,ab8e6b8a,4261953,37d1d2d9,b666ade3,88cbeeb5,bb89cee6,aa406746,dd4893b9,5bf1818a,3d1351fa,d66e104c,bc8d63a1,efa953e3) -,S(23dbfe81,5232403,39d5a662,51fda5bd,b9a2d3d1,181dea3c,c0c908c8,f0f4c050,caef3a71,229f10ef,488f8385,c79ed0e4,b5c16899,d40ab679,4e45b84b,4deae6b2) -,S(3907e3d1,20ef8619,c11dc69d,c57935f5,d2dcbeca,1b4bbb88,e4629ec6,acbbf1d2,438f96b7,d74e2b9d,cc17b0a6,c936844,e6aad1bc,58a20055,ba298446,1415e853) -,S(c140b19,3eeb04fd,80aa6a37,3407f591,651c944b,33788b71,e6f05e1,672b7d9c,949bfd15,59e24543,9d5fef6b,70763b63,899450ef,430d2e64,1f7077b9,29e44072) -,S(977cf05b,c96a39c8,1dd2fe26,930f75e4,2563c3b6,b06e28d1,740a547e,f2ea56c,3802e3a,8508164c,36e95e23,46ca468b,7e15878,36a9edc0,e70c0e6b,9aa10d52) -,S(1069c0d6,3995e0d4,cad51e5a,9e4e57f6,795a7bb3,9ee3c376,1e827b20,d8a034e3,e1aa1487,9c0e4c65,581d89c4,7abb5e48,47963aac,788fe804,1d2c194c,5a7fe33b) -,S(ff78c680,c3414181,ff3ab10c,74e2a755,42419af5,3527a45b,ba3825b3,c93e3682,eeb70adb,f05390f3,76b2382e,20b2dbed,86c8c574,df2f256e,1fc4a376,24d3615e) -,S(5ec9eb03,3acd3d6a,9c04c3ff,5838a6a0,2b0cb26b,d5c37d05,9056afd9,86bcddc7,92a287f6,eed0df0,17c0bed1,ed9445c3,e39d92b4,8c3a9c8b,9ae26749,732aff03) -,S(eaa206ba,792dd34b,7ee67e14,d8dbc7e8,bef0a54d,a7dc7ee9,339d8ec8,471b37d1,5577e65e,be719ca0,7fef2530,c40c1617,55e00d21,1d78e5e2,695107c6,8d1ee92e) -,S(26d062f5,6034012a,3d76789d,455cefa2,689ef08e,d3d87f54,af952afd,ceb3ed7,5eff1dac,ef6f5877,99c340c5,f0d1f6dd,dbe6faa2,5ace9109,4e7b5836,d1323424) -,S(800d415a,e50db62a,4f49e449,d11eda8e,1a2413f9,c341bbd1,492f2271,1e602d48,569cad6d,5d19b5d,2299ec5c,fd12d9f3,d5c8cb0e,756036fb,dc5957f5,7c02eb50) -,S(6c01a352,bc16dc19,973aaca5,f1a21676,e1531fbe,f8586bb,9853c627,9c9a1c90,833dd742,c9596a0f,2767226a,b2548139,a39a17d2,d64d6765,4c073b18,f8cc04e7) -,S(3accc922,f1b3ff0c,504e7c4d,4738d1ad,f0b914b8,d08ef8e8,a54e431,37742c26,aa9cd483,27d60b34,304dee26,c52b2979,52a2d118,82e10b17,86a09acb,3cb0ad7) -,S(a0df5c72,828b73f2,a380f75,3f8e6352,f8d978c1,ee6ebedf,2ec70ff1,d0f8ec72,b230adbe,f1e0bd13,1e622689,379e7232,b1327db6,eb0ee306,80d7a89f,a4ac6670) -,S(9d5f0d94,9776ec98,607a8dbb,d54865c6,d4bbc970,d3ff85a4,49d57b97,33b52c73,ff08efba,f4893add,54b8a056,ff60d345,ad7faf15,7d11acf2,2cea0f2,afc1a8) -,S(def5d92d,9ea1822e,dea5b293,58a51ec8,228f54b5,a6738917,fb7f2108,6dd3d84e,b6c740d,b94aebc3,138d3ad0,202bff37,9d5bc20a,d7c0307a,479599ee,8b3129) -,S(fa90b105,cdc8d74e,3f87136c,f4d075f,643fb0f1,ba6eb832,73642e65,84df33de,3e6b28c3,73f58eba,49e9e852,f0f0e244,3a180d92,52624c27,3c079dea,50bba36d) -,S(8212e821,ff2f7b90,c01c8461,3d4d9df9,ce077cb2,9706a349,575b8cd1,a3d0eb52,d59c05db,2fa3e756,fda56e8f,33540639,d24bb5ed,2c8aeb5b,8f8e43ff,703185f0) -,S(ee340cc8,1d1f71d7,4b1a641e,101d15e5,24f155b7,2afb4e49,f9cd8b20,ec61220d,915d833f,25355fd7,f1efa796,4a8e8b04,86f8141e,f5811438,f0083382,ae286f37) -,S(2c535525,dd2e3d83,740b257f,bb7223e2,302b5009,7f8366b5,aa26f65,442afee1,1cd4514e,f945b668,4f38f966,2f3b5402,92d43a79,7f73f947,67272713,b61cf765) -,S(df7763cf,8b57a288,cf4a9083,a2a5f977,404b9e1d,6e814f2b,aae9ad45,fa67d94d,4f7dc336,31fdb48c,612276bd,d388ee9d,bf05295c,1a92709c,b4fc33ac,b1580ce2) -,S(3514c240,d6d0f218,11374b92,8cd6d063,8ff99b8f,4d5e4da1,8fd126a0,ecdcee60,2a0d1f4a,1a1baf80,3c98421c,7777ed1a,ac17abb2,720975ce,e530a5c6,4197fca2) -,S(3de75d9,e58bcb81,94dde551,ab541d54,237a1b58,d935f60a,b54bd3c,6ae40a27,9ada14db,be2db058,c6bad8c4,86f25037,3ec422da,fdd5bddc,455b2b8d,25d97c75) -,S(a728ce0b,1804355b,c5c144f8,1d5eb1c2,90ad3d52,f502c5dd,ae28a08a,6de0420f,4387cca8,f72b51a0,cfb4893f,a85491fd,42cce3b9,ec3344f7,ac93d001,47ddad3d) -,S(ec3c9a8a,5b844c0,947b22e0,2503a815,1d8234ab,aa94032e,16c1d874,5551c39b,7b08bcef,45f0fa93,660845ca,44edfae8,c8ac51ce,e836b043,3825e410,8ebd7fa6) -,S(b0173d56,24945acb,3bab7e6c,617532cf,e619e7cc,e9872e93,26a8ec55,a24761db,78d27b5f,3e9a0761,d0feff12,198dcb11,72a81df3,1320f10d,44591ae3,5f1b381) -,S(d9eb3bf3,cd43dc8b,977c3890,ed3a4b8f,4e04bd11,f95963a7,970d9600,40cd73f6,98196b5c,c42e808a,3f1db718,98c50048,510b9e4,c9b69c41,e7f5b2fd,63b23044) -,S(fbda51af,8a40230a,c7602606,21f92b38,29bbf1b0,1c027f10,7ca54c08,65a84e74,64833994,aa453bd5,4c8729e4,e9010fcb,8fd427ba,3bbe7c71,e812513b,fcd6ccf5) -,S(ae4b9a7,51be1966,f564661,61262faf,472b14c5,f0532cf8,8af872f,ba583f9d,8b2c248b,aa9d7e5a,6f0c6eed,9ad3ab5f,e2bd4078,da4fa281,f4b672e4,9695ee5e) -,S(58040152,6088026,1668c6a2,e462845c,f29764e0,31edf6dd,a40b6e0c,4ccf6ff5,d2f96ae6,4a83c04d,a072f9a4,e39976d8,a2e5f88f,fed070cd,5fb1a701,db329485) -,S(4c28d686,57380f81,639abbd9,fafcf47f,cf477e26,1c46a03b,57ca7326,4c7e029e,694b8a9c,4fa75e14,56a67e8,acfac16,3122a941,150da022,59fb024e,ced8a70) -,S(de205ab3,9e005587,f23b51a7,3d806f81,6984fc77,7179a6b9,465a92c,ff25c9a4,ed84325e,12efc1c2,db42cf1f,eacc12c,48f68e42,9aec9135,5af5c327,c5273d83) -,S(5ea82868,c2cb0a7,4b658dd5,721e6571,b968f589,6d22a5f1,b3ec6b69,594273f4,88d10eb0,8db264f8,13adecce,636f6c58,e1828539,1e538ad,6e2237d2,384a9499) -,S(189cf7c8,64497416,420bd98a,3e3db4e7,c3b0dd46,d7b9bc9c,37f2d036,324998ba,bb3409ce,d46dff28,36601b1c,f7dd606d,7422118d,723f7da2,4d25802,1edaa083) -,S(70a17187,38f50d43,8868026,58100245,3c3c41d7,8ee5e14d,3cf536f9,bc82789f,15c95120,e112537e,41f33870,18f09d1e,101dc445,a9f36296,2b9462d7,bc27c1d6) -,S(578ac0ff,622adb6e,8c20eed,f3011085,8e4271aa,46833865,cff46b9b,fb3a368,f711a1dd,f5f3172d,2b9b2f7d,9d50818a,6b0ceaf5,1d67e15f,1f01ca5b,bbd7f851) -,S(dc9fbc03,476aa747,d64738ba,ddce8a5b,5887f177,fa6cdaea,3e3b05e2,8d840071,c0f6752c,8087dd25,f8d94a19,d294e550,8bd26774,cf4e7ab9,515f0a4e,89eee1b4) -,S(9749acff,a348cd5f,2e84dec0,b3d73151,4bb817dc,4596d78f,e0295215,47b0294d,df667dea,35e54810,daeec20b,e0e7d203,d89856c9,94501167,23de84e0,5781a1c6) -,S(e39fbdcf,2fd2730d,c3359f21,fa815478,ae8e7a98,d6b132e8,e92d343e,32657d85,bafe9881,70a78596,76a6ae3e,364885a2,62441578,8c31c283,20a06b0b,e5b5e01c) -,S(6009014e,27f13712,c00bda4,dc913516,e04b692a,ea32b89,e0fab8bf,91402c09,34910894,f6bd1cd2,cb796f58,8ddba661,eb4006a8,6cec32e5,7086099d,42359f6b) -,S(bf04f247,d02e46d8,2fb9bec4,f76b3eef,b644c92d,43622162,d419488e,87f2f773,d646f4e8,bb3c2e4c,f19ab00,4674e354,302e125b,c1ed684d,32b1cebc,7c2172f6) -,S(9609f7ec,b122b353,85871efd,915c6d99,3e5468ab,c30e9acf,f5b4dfaa,31e5e3c3,106bc52e,b933f0b8,71578ac7,74e2ad89,ebb4d9f9,eeb95592,5d6b50dd,988f9a27) -,S(b690cc3a,e1ebe25,a07440fb,5cbdf56f,f5ae581d,4dec7366,8da2ad62,bab9abe,83cd0023,fd3a3ddb,2cda9603,2b6c1657,35e5f9f6,249a535f,b9666a97,e049dbd1) -,S(72da508c,ed507744,1aa2bc11,4a9098d8,2c947948,395bf38d,6cd00977,91d326d4,165baa93,3433ea2b,e978036,4fec922e,e5d743db,b8117e09,5eafb467,3f668457) -,S(e0fd116e,540a3009,2954322f,5125a72d,1133201b,985d1017,29b1c9b7,a9851c37,c6bc7276,48aa707e,549e899d,630d3155,a516a06b,777997ac,8509045e,e5b88a92) -,S(9d4b8bea,85d4e412,ee0d6389,e883f9db,297f01c,d0695c13,abe2b682,94c10af1,5e2280d7,3f7c0832,d9ae62fd,6a884973,5bb66ebb,e68a38d3,8a95258a,97556181) -,S(eef84395,aa4b6e04,ddc56123,cd5eb31d,69f1255,1c216d25,5057a2d4,388e08ff,45098aa4,34e14364,40d8b26c,73179c48,87797e6d,59963928,b1d6b61,d62d2376) -,S(66fe5c7d,56e38e48,6134371e,76ef427,b4652daf,6e60cde7,39aa1165,c90d7654,2d72926b,b6edc93b,7e40ad43,3cbb6c4d,96d4c384,966ca582,a108a84d,c11a2fba) -,S(5135f9cc,1818caec,cc55a304,aa983c98,82f9e1c2,939f27af,dc2c6df2,c08ea2ed,5a526dd2,7dfe1750,4f8baf4e,115ae1b4,2619b5e1,47986954,27ca3621,e03f22d6) -,S(1a37c089,af7f4a9c,2ffa2bc,c22a3e29,82e3318a,ce1ae29c,3fdf9b62,3e6487ca,d389c033,8522230b,a96b33d2,373672cf,509b0312,35d2ec18,3c955ff0,3d2464a5) -,S(49f7a5ff,15daaf40,913c68df,c9016f95,ed1edb22,22fb1576,e4a11848,47a248a0,f9b55b01,3d637bc9,e9794246,fa6bbef4,d5ebec82,1a5d7f61,1a18c7a7,b9abd8fd) -,S(8247845e,5d9ef839,207f0f1e,26eb0470,3b87f835,ac3af130,253aaf88,1e641ed7,577d790c,1a23984e,7f1b1947,4cb42ad7,b4409c8f,23f391de,3e2440a9,e53c5f1e) -,S(8295984e,cd160241,ace92ef6,10853e8e,57b7823e,25eea4fb,8f118593,d90e0749,635321a6,6798d5f7,39a450e7,67b1c38a,2c5dac96,780c83c1,4c38dbc8,c0ac8353) -,S(d4c32bf6,d8fcf5ff,be0ba34e,770c68b5,fb5db412,b1341537,7b2e9c80,3dd75461,b3c73602,e23845b3,2c44272b,4eda70b9,a1a71e51,66d13353,74153f66,4485f93d) -,S(1a08e32d,4a968e6,a44703af,6b526a32,3babe7ca,6882cd84,9fd3f769,6cc897ff,46ed98bd,b77bed4a,25c2e19b,e2b14a8d,3fdc8209,70344b39,9a6b2a8e,afad4141) -,S(8559be0e,96723f04,4b05965,da8c9777,6b40e1ee,ce49de82,e7cfdc34,354f4af7,63e24b88,854e20d1,2c3f049b,2dd0906a,ba4db6de,aba42dc0,5af03dd4,91333ef6) -,S(e0e0b223,fc7a478a,849c0ee3,f2ef2a6,edd0f08d,e8ccc8c5,5e28bdc6,5e211e8,ca38832c,3aaffac1,206d38e1,25b8847a,6609a5e,d1288d1a,511d6037,9fca60fc) -,S(a237be98,2d8ed250,75801eaa,5917582c,265c3424,5679b4e2,34539ce,68e40a19,f4cd227,976a3780,454d5de4,7026d668,dc1bfc32,9003c87c,f48982a5,5a231318) -,S(28a84882,1eb08d07,f03fe770,5a16f2bc,5edbd0d6,b4367ef2,474f9b60,1205ccf2,9067d3e9,e7d77628,ba0526b1,71d23da9,162551bd,f00fa301,eecb5fc3,f856a17c) -,S(142fe8d5,42bd6b5d,325b8fdc,3820de5b,cc83e2ee,13d59d16,f4c69adc,98c1d5e8,2973f278,32533b9,559d1421,38d7fa60,1b66d106,1bf9c453,9c8310a1,dc75b150) -,S(5b3b611c,5d20649d,19bb00a,11b4b928,8f3d5ffb,700fb6b9,9c97b012,98ad87d2,849059c8,cde0e12,cdfa7621,9ed70bb4,192ead87,5a22c58f,8ebcb58a,f2519182) -,S(248a2249,5d4905a3,f61f74c3,5f35f6f5,2edbdc63,9454cf6b,192c7ce,50beb8af,b5a6f3ff,b707c108,1cd97b24,38867a1d,61eaf73e,9b89b5c3,b1136ac7,bbfd4c83) -,S(8a474a2a,292b50e9,d4d1fa99,a229023e,31ea2093,2d3a5d2,875384d3,dbff075c,7745285c,7d5341b1,e5c39289,16cf8fd2,45b5f045,d30d5dc8,721d6b65,ef804dd9) -,S(3fa01255,7fc042ea,67cbe4ea,86637313,826d10d2,48d5bb22,8ca8d113,5015ffec,10b9d325,f59b4b8e,ecbdca5a,58c48e18,162d436c,a3228b25,e3f75f27,26a937b3) -,S(b77b5c0e,7b94f1a4,dd88f007,1af049b3,6b778d5f,c8a828c0,46ac2195,9fd65648,31246bc0,6722bbea,8c9d5722,26edd609,e2b65d2e,9df6c21a,d54cb157,faaeccc5) -,S(2635f482,67e82b97,6c2ccad7,89bd4bb4,5671846e,d5d1d8e0,8f2c41ff,8535b44a,7edc804e,956091fb,667f9e4d,47b7353d,d2ce39c,b53234d,afb6d5a7,a72b8def) -,S(2306b52d,ae0952c9,c6b6f39b,6d1ea36b,ed0012da,18d77238,4a4e0866,361b474d,438250b8,8d7b8f6b,9a63688b,b2cefcf4,bd767472,bcd21221,582b56cf,325486c0) -,S(caa866b8,dde8284,8f586f9e,ed5a1d1f,aa5604ee,a8c0016e,248d897b,a9f74b4c,2818f140,349f78c4,572834ce,b805a424,e33746a7,d58fb8f2,9954a55f,dc09c341) -,S(818def5a,a0793d50,5f5e9cc4,29c01ed3,fb5e577b,b25277cb,b74c70fe,88bb1641,da9eee80,f7621031,80e2d54d,796367d1,f48ea2b4,93a1445f,bddb3ee2,ee4f276d) -,S(2c62cdfa,568d412f,cd764ed0,1bcac5bb,c36e11c3,5a295bf0,8b12df92,447bf736,e8b8e025,58117062,705ef985,9aba6418,ee73eabf,195325a8,f82c051a,3ec31979) -,S(28ab54d9,9db06e8c,d4a2f7cd,517d049,4e477f1a,b6eb3416,59bce807,e1f04adb,993b5319,a5cb9602,be656276,bf3e7d84,4fb00304,1ecbfb08,72aa29e6,7494541c) -,S(493e7c16,2254a40c,54b4eca4,223a8241,d6c2abf5,f15ebbb6,3ea4814c,512b6061,56387f7b,588d9d4c,fee36b59,7ae8f21e,5fcf817b,f097ec89,7def80ba,3ceed628) -,S(672e11be,e7439165,4fe118dd,a2c5d389,8922a68e,222c9bce,902d2062,b9c51d4f,3555134a,2382a9d,b4bcfbca,45e9d62b,db6bbfa,bfce7c5f,c5102dc3,23dc36e1) -,S(8f8d0f6e,e3b86889,8de86c06,b59f8e5c,27524b2c,2959e701,38b2c3,8eda550a,e7def281,9e27abc5,9940fed6,687bcb3b,f364296c,26bf1fd4,5d417103,49212f34) -,S(da8c5783,4a11f0a5,797cf4c7,9179f30b,118f2802,1205d495,e8213fb5,78b293e3,6ecfe35c,6f663975,86bb1c3,ab5dc518,7c7a0ce1,b6338d28,a2c01df3,89c35f91) -,S(4953e0f5,3b1965ff,3efec2d6,fa99ba0c,fbce09b3,83e20ef4,2657faa1,49681955,c210c78d,9d1635b2,3e468324,7980766,3c28fa97,18d0ca39,fc09b541,975541c6) -,S(5491fdaf,48a0e1e1,be21f7fd,be910bd6,5cd3e0c8,16da38db,6c742042,3775f293,65273688,5d1c5338,a3be9b29,9b51f4f3,9c82de96,318643e,3d34ecd2,fc7ffae7) -,S(b9c4afa8,42363b9,fb583885,8f17d1b6,b0a8529,43c907f0,af3ec9b5,abc168d1,ebd3106b,1b75ebed,5d013aa1,eca7d8d5,e24d511b,6d4178e,514fe156,4b550d9a) -,S(918da36c,444847a1,b5f9826d,eab809d5,d6802e73,3abca386,24237683,92d2bd62,6e6237af,d7cc87e6,15e14113,ab38989e,889d5e6e,6166eeca,abf1ddc,8a53e218) -,S(777d2994,da1f514a,800240e,59b743cc,748eb42f,4572ac93,a2e42e37,1d3392a,6193d7,e9eb3195,2cab96f4,14e1d24f,9d92505a,9d21f864,5e6dd3a3,8a9680c6) -,S(108e6ea0,9a08c5c5,e27b8b3e,af24ef55,3988c650,34ef954c,4d17f232,5723bf3d,1a8b974b,86db6bb4,7c314ebf,f811937a,b8a0dd76,e824dbe2,88fde1bf,fc13b2eb) -,S(36d9dadb,65a54d49,1198a486,8deae1fd,3c2dcef4,4a682839,b5dac54a,456bf185,25e84356,d93b5d86,25eec306,565bef19,1edd9bf8,347dcd8d,785024b,2147bbf7) -,S(3e0ebab1,43ece776,729d8a9e,302726ce,aab89654,23292fe3,ab2e71d3,66531fa7,6e7b2608,556d6236,8948f32b,2fb04b34,8e38eae1,3d9abd5c,691383d9,958d41cd) -,S(923dc76a,f315f31a,a1de9521,a13ee9ab,ab08ab42,157f483,2babdb5c,18fa3728,7a8f17b6,7439857b,3141bfca,6d89e649,7facf685,6331003e,f6bee07c,ed3ae47) -,S(f87fff32,2dfeae3,4ce9cb81,51ce2e17,6bee02a9,37baac6d,e85c4ea0,3d6a6618,74e49037,aa726e0a,357ace25,603cdbfe,7c14a4cc,2e1e4e13,c7176121,585a03e0) -,S(1388065d,dd7f69a0,11dec106,b539f7e9,e00b5aff,7568820,e33f9c1,18881ed,acab1d8f,140661dd,422f72a5,5ab4242c,65d1a932,23fe732c,92b32317,4d13408e) -,S(e5476b1e,a99b6a08,83731542,7a3751b8,3d685b34,acc5201e,59e9b623,ac4b6941,57d5b2f1,c4dd795a,323c794c,aa8fa754,bc86dd67,3cc8577b,b418b2e9,5f3b4e21) -,S(f938ff60,f1e8ebea,4c229d89,4c98418e,90c14981,4ed7909c,3dd47cb0,15cd1f15,d7172212,1a0cc646,a0576e29,372bfbd6,37fe2c5,b6ed6821,4da50318,eebb13e1) -,S(b31bd410,7c4a5108,1795544d,5854f9bd,180b494f,a08878ad,8ad5a3bd,98a30aa3,94261097,6bd58962,5e941aff,a007eab3,d33828f0,e12b31c1,8fb6f5c0,50519e82) -,S(b3ed87ba,83210d01,1a2df141,b9a6c6d3,33abd692,55da3af7,b4447d03,f4c1cb2f,949dd379,29c757e1,a970273c,b6341e66,b90be71b,347e747a,be0914aa,4dd632b3) -,S(60e6c240,1ea790d8,4bb95e78,731bca08,89a57c0e,38b87f46,668ee16d,31221e17,f247bf35,c722098f,2a5c800a,571eaf0,36738704,4050d98c,c03bd146,ca9465c2) -,S(2ae806b0,4cc8d047,e7dd8d37,713cd71,eaf3e16a,f74c3b87,994afaf1,c3750a80,a8d978ac,b29771b5,1a87fafe,605ca0ee,6facf6a2,41aa135a,e38de4eb,b2e2e954) -,S(9af178a4,bbba2d29,e7a0bb15,51f6f3a9,d2384386,3779f439,58a424c2,29bb5c47,c1031fba,a0238857,a487ac85,72fbb3d1,4052a4ba,adcdf259,78101a21,ae79abd3) -,S(9dd6a721,e9cb27af,2e7da097,c9e8a250,fd78a531,330ecb2c,3a116d99,6008f523,e6837b7d,647309c9,4712adb1,4bc65787,fc4e975d,f4e82173,57dc9d3f,e7f36080) -,S(cf5f16be,d7a1a1e5,3b3e3f1d,e44efbb7,fcb717b6,9a28bf0f,e31a1da,a5e91c52,9549ebd5,4d87207b,c63912c9,99920cf4,b0c80a0d,8a69d4b1,4852834a,c4487497) -,S(c6794890,810954d0,782466a3,c52a0149,de577cfb,3a2001af,d45e905e,dfa64722,4a4fdf51,deb64031,bfca5fbd,5c827829,8621b625,1be69187,fcc2460d,f75ca468) -,S(a25fffcb,bee9e0ff,1659c1ea,41406aa,b03b4920,fe1a63e4,442d5241,30599713,176b9e06,5a821189,ac3fc28a,fb72a1ba,40fab791,4de987e2,1236f244,bf41486a) -,S(6079a722,fd5d923b,16acfafc,7248e329,128cab6a,cae9e5ec,dca49774,e0c5bf71,c09972de,99ca5a45,c4f6f1d9,10337efe,23f5292,bd5ecc45,df0f7aeb,d18c4bcc) -,S(188cb43d,9d4078e7,18fffc42,8b16723e,f64b950f,cab7582c,8139dcb9,2b66b403,a038fa37,ec9ea240,9a2879,9556916d,fcc8c2f3,358ab14c,140f7f1a,23af5404) -,S(e310fc40,cb575c68,f5792506,65567ec8,c445ca34,68cfd02c,d781b27e,f819bb30,31328a65,5ba312ee,5e901def,66e7b946,e0c18336,a0f1784d,df66b89e,2abe625e) -,S(dd86485d,1c8245dd,d940bdeb,1f462cc8,f15693df,246c3c8e,52b574bf,77dea4ac,cd6bb7c2,56c9a270,4c690175,ba298a09,8963a8b4,7e743b48,33fc09c6,9966ce2) -,S(1b7ed20c,f81567b8,6f7dc67c,ab69e197,dba77399,9b36097b,de85d02a,7019aef,f814e92a,d1cb4386,550d89b5,9a4bc378,df428d54,d314d531,be6fc35e,f0e3d1bb) -,S(a15587b,2d528338,ed146a03,670b3f1d,9b41cd0c,a0645897,a0f719a7,b5ded284,2aefe34b,5aba1a4e,e30d225c,c4023ee7,12fc1522,ad6b452b,fe6ea727,122e925d) -,S(57bb9f9,c99da691,98cfcf20,9a0940ce,8d19463,9e4d1054,484953e,936a5484,63d0fba8,d90226e8,2c7be5e4,1d77bf0f,700dc57b,d8d3079e,9a6a47c8,331660e4) -,S(224295b3,7fa1b4a0,d7d7f7a1,2113b21,291f84fb,8fa4b746,bab925d5,93bd262c,d60ac40,b1e4b0da,7563eb74,c222660a,46ed388e,c4517ddc,ea2962b9,38195796) -,S(2434eae6,a34ec53e,7c031b2,9e74354e,d6101ca0,f228055e,53b39a6b,5453b0e3,2ff5ed61,d57a04bb,138f3956,33a20e60,8b04f775,6476d0ed,6ce7a382,743ce23d) -,S(448de592,907c1113,bdb04c64,9fb22b05,ef2e6ab6,36d0a03b,700a5871,89885ce9,d7aacffd,6ab35068,debe6dea,25b02930,63af8b10,d4592880,3d0421cc,a879eabc) -,S(8405cf73,5aef7674,7feb92e7,1aa3ba0,defc0a1c,c1da698f,7c2a3718,6393dd76,5795d006,49cd10a0,4a661c78,3f4a8711,89c9ef2f,ba86853f,c7955258,e6c407f2) -,S(698974c1,e5c1487d,fe9349aa,371eb86,9318accd,72c66d5,581211cd,6e08efc9,37c2238c,dc8f4bf5,1f76536c,2ab9af61,bcec872a,bb84ce15,90bc1c0f,ef84509c) -,S(8a37857a,be3cabc6,7197781d,f315f78b,e6548c61,1b846d8d,ce2e5732,643fee05,29882f68,9154cd0,7e455e4d,9e3866d4,5e28e99b,21dde0b7,8b87698b,4cf674ed) -,S(a871b34f,5cdd39fe,13104c96,87a8a717,25ec8cdf,fa60846,793bce03,2397eaef,84f96417,9de103c0,9f7e2dc6,86c9213c,642312de,8de6cc5d,f3ffd7a2,c387cb28) -,S(49bcafb8,9f78a7f5,a8857905,e99e74ac,9ec66ec7,aeab8fb4,fd964ce6,8286f44a,e7db8ccb,5641ab74,a791d2ca,7bd193ea,71124a61,2716d94f,4eae407c,ed9eff6f) -,S(d5c7d92f,2f05c9e5,8f586289,dffe8499,40d9b84b,79feb686,c3f71300,f68b6df6,a68b2a5c,219ea38e,a04b272c,e1cf42bb,6fcb2b2b,fce36043,4f1802af,1d51c08e) -,S(2ac2fe3c,fea4cd7b,9c74a249,cb0c8ed0,6a825cbe,2826c56c,fe4a8db5,3b286696,7d90a659,b008a51e,ca2f6031,c6ca6078,505bb46c,f00a3834,a67e7804,b60f43f) -,S(7c09acbc,62827ecf,4f63a85f,5a0eda7a,5b0069ef,b03b51d9,2f61c5aa,10a39234,e07d2539,c29128c5,685f8641,45fdc318,854b56f2,962b001,5a96c688,69624836) -,S(e886dd56,7e1b42e7,69941ae7,13b2fad3,3bb4ff02,34a27a7f,2c496bbf,6ffbf9f0,d4b2277b,abeef80f,371c097f,df4e5de,5a4666f3,c630b010,81d1172d,c667a877) -,S(edf65cc8,e83983,c5a178f0,ff60bb1b,8ca8a6e5,85344464,73a199d,59c2dc,a2426713,f0c5309f,84a4710a,2de1cdfb,118a4db,1070d23a,92c76244,89ab2d5e) -,S(29c12f04,b78a6ebb,9356dbbe,5b152323,435ad7bb,a3d2d036,a746af6e,d26d17f8,8399275,bf6211aa,78ea211f,39ec451a,b3336d27,fa059935,8b7fcece,216eae4a) -,S(d5db8b8c,280e9914,f0a034ac,3e0f9fcf,169f2046,4a618789,994f8a79,6663c3e2,41163c3a,85a0039,f5e5635a,819941f7,98f27078,aa65ecbb,eb60d577,c263412b) -,S(990a4fa5,630eb00d,958e57ac,8bb4f7fe,10e1055a,c547d165,7000a17c,d9135f8d,f25ee025,491fa289,446a0364,68c71217,eb252414,f8fcf291,2ecb23d7,4bc9653b) -,S(d784ecf0,1c7849dc,ec901c3b,3315cf53,4e3049ec,c68d71b7,41637b57,9e9c0935,5de98d22,cc382aed,d8c82a84,1ec6fd46,30672008,8567dde,6b2d64fb,6b4205ce) -,S(6576cd0,58850cbb,aaf53b67,bdf3c19d,9b4d38e5,19c99338,3204cd35,6ce38193,a329993e,92d1e56e,31c1fbeb,27648fe3,d984960e,30bf3420,658f74c6,5710eaca) -,S(957788e5,f675c0c6,4649a808,1c4549ff,20ccb177,3d26e4d8,bb94844e,bc35efce,7ea4431c,dc4bee37,d95c3948,615e17cf,1d32906,9bc10a8c,515aa0e,521d9b5b) -,S(8af7ca80,5053b537,ec501abd,78c13ff0,da5549f3,b045096b,1452c05,e39e4a2e,25e86225,aac042e4,cfb235e6,da40543,6a436206,e9d67fb8,e1b5836a,2d7e8402) -,S(49bf0393,e16e634e,202ff642,ad79c179,e6eb7456,637b2ba2,623937d0,e215236c,8590613f,401de0d4,1cc0ce1e,e9a13441,41e5f80c,179ac722,d603e697,a431a85d) -,S(c82e2a25,2572863,527b6858,18c9b6dd,df3653ed,a264b5af,dc5ebd19,d4192063,3b86f800,cd87c1bd,3d70af04,47f9e939,c2717ff7,376f91c7,b2675e3e,39a6de8c) -,S(9ce43920,2b9a8f7c,3aefc9c3,fe4d227d,42ec1355,158b2041,a3712dfd,d8eedbf3,dbbb5b05,859aedd3,faef15d5,9a939ff9,53a54bb3,dc2ee6e2,6d5a20c9,ff5b52f6) -,S(e07009e,49de05ca,52d20221,3ecab4b8,baa707ad,96ef24a,168bdb6b,16fe6227,6a35b0bf,e752ba26,81b865b0,ade8d4eb,2583833c,a1523b2e,4178f9ce,6cbc33c9) -,S(eb4dcdb4,7e09af61,e4694814,79612715,d588615f,f4c23fab,65015bd,821da888,63e38168,584602fa,1e06536a,d4c8115c,86305c,41040083,4a55d153,e9661b8f) -,S(be5f8681,2bf20113,1d257015,dd29dacf,a2c65907,26078f7b,f864f339,10e49db6,d0f420e4,56174aff,5995a92d,a73fa511,43c4f1b8,c40e9f30,8f04011d,956d9da7) -,S(3b32dc39,10e75f9d,98fa1318,edd7e8ef,db214a5c,b31d5ed7,4a61f881,355b99a8,1a12de86,19c2e9e5,9fddf756,e752e54b,6e4e0aac,572fbc42,18baf1a2,a3a18bc5) -,S(95ac5dce,5c06e885,65d2922e,a3f386b7,dde10735,169729d0,a3c3e7a4,86e04db1,1a22cd87,ab1b1821,e3c49e85,616b7b49,680edb77,251969fd,e77b5b27,3ef39838) -,S(6e4ed0fb,a4b0f13e,335d1b74,a5ed295e,7dad591e,a8dc5cc,d301836d,7ce708eb,9056166a,c61c4e09,ed988e6e,59cd9ab0,16a2ef99,e99c1a54,ac37f152,a34b931) -,S(8b7c3394,208e0ee1,374925e1,7827d849,ea8d9a79,91d2d859,898eba2c,23a42e10,b6ab9237,96720bcc,910e6440,75ef3ff,2c8bebf6,2f21ad0d,3abeb2,7043d193) -,S(fda7b47,f6690d73,884965b9,8b6f5dca,dd48ab4d,8f96edcc,8e20584b,b0f871c6,9b402435,a272cc6d,28b487e8,b54b473c,30929222,55e47560,e18b8e6b,ca926c5d) -,S(f15da0f5,395a5a1a,ef8beb53,4c0e9aa3,6e63018b,cc91a55d,ad6106a3,3dbcb217,28cf69ea,bb3b0151,917571ac,48609723,80be252f,bcf98f6d,db6ebf76,578a8f1c) -,S(c6e266dd,2c7817e0,c92378e6,38709a97,d9a208b8,7fa832f4,abfd881b,bcaf9253,2af100c1,fa9bb3a3,c8e95e3,5d0bef58,5ffa7adc,93232082,84291ee7,cb769626) -,S(4bf8aa02,fdd201e,488c21a8,33925687,7f5a727a,4fdab13f,d133d08,b6e28753,58812658,ad9c4d59,a15c6bd7,9e6c622,d8fe5f05,95cbdd88,f39be9d3,cd5fc8b8) -,S(aa985f28,6dd485a,5589fc39,da77fb95,5cda673,db61e48b,972fc129,7cd0a6d3,abb0f897,2f1163b3,29a5a92d,a1ff02e0,7c277710,10e24a04,e1e5f60d,1e4b75b2) -,S(8174d101,ec13a1cf,4eb9f88d,88c14121,6c2fa04b,ced197c,8e1732ec,61c41c9d,c6765dc2,31b02e7f,eaf7a662,5a639b00,c6e5d94b,1a791bbb,46f6a758,8fd79aa7) -,S(f9f64ea9,d6039297,b728fe09,85a9a3a2,92573aac,fdbe6cbb,8702f04f,6df3d876,4146c7c1,406067d0,160950f2,1172e879,188069fb,d87eef9b,1a67d2c9,9a4ca01a) -,S(3e643a70,5a6885eb,3d34454a,2a5de925,f8067cbc,1ca92951,d8865ecc,a8f1b3b4,2deca704,5525534e,de9d54d1,d777a996,8b5e5882,7162ef11,b0fe08b7,e2fb0355) -,S(444df411,fcc3ac07,7e95d200,d6f76d03,caae45d2,b87a882e,4c0966f3,376c63c5,b4566598,643d964a,a7cd1a4d,f2decf3d,ec520c93,ac6e32bc,64350aa5,5416cc23) -,S(12a2f61f,58be35fe,314a7beb,1a6810a4,19cdaa6a,8424d465,bbb7a87a,646946a0,9a7bdf44,94c2cc8f,f1953946,1a69fbca,48410b31,95d79069,8dfd535d,290ba47d) -,S(bdd72692,462573c7,3d48af94,b687bd22,511b2b7a,93f48793,3d52b2b7,e264cb9f,56e6c4e,b794fab0,bd5ac992,3f7469aa,858e6df7,dc40f4ed,955c0df7,a2123874) -,S(e1bd5558,77c3f55d,12b4f156,ea4da9ef,c974bd29,d7d043d6,ec7fe56,a4066bdd,8dcd9b99,fbe7436a,2382bea5,6c5a32f7,789cbf1b,1c44433f,f5a95075,c3233170) -,S(a7c68de4,781c8294,bea46609,f4a1f550,fc064eb8,b071985d,804351d2,60132ad9,a08278b6,3d9efeb5,1062b240,d45989ba,6f6bbf9b,ebfa0766,8428862b,adb42c32) -,S(4f3a8769,b4c6e369,cbdeb90f,5137d07a,5fa0d66,3d8ca79a,56b3c70d,2a9aa855,f6c051c,5f701e15,348ed9f2,c4707584,b9d6db2c,b62bf93e,35b6486e,ea6ea169) -,S(deaabc1c,8089ebfd,841cac66,d8a6bb58,36fd047f,cb435a8d,74463dde,f444f232,fb7cc4ba,49c26e7a,a826e654,7c8a6d64,ccd14a49,62a6d4f9,f50c293,c228e8a1) -,S(c411af61,547b1b38,12551e1f,4ef2b32e,fd7f33ab,7cfce378,8b5b8f93,319c0695,d2bee7d7,3d50f82a,e9266d21,2fcfbb76,294ace4e,f6222ab4,797bbf88,558cb66b) -,S(d0ff6a94,485bdda8,d0c28494,5b9dddc4,4a35f101,d0a89637,8210bdea,909ec5e7,ab3f60fd,2923a8f2,d02b7e83,d8f953c4,cb1910ff,83a92a65,e2121f22,364f620f) -,S(a0d05cc,9555ed92,2851baea,35ad6cb1,6f2744,b3fe424,98235aa7,1f08c0f1,843b1105,237158a7,bd7e67c,a20b2705,50afe2ad,318077dc,4714c7c9,d6339948) -,S(bea08445,eb295fba,5c83ef6,7d909978,7d599642,893fb9d0,568e5920,1e3f5d32,2a81a7ff,b3f7f453,d78bb2bb,41d12ed1,e26594d6,bd4f5cc7,908f322a,6cce10e3) -,S(e8ebcc4c,431be689,9eb5aea6,f6ab9700,551c3098,c5acece3,e822c7de,e6f0d5f0,ef99a461,760ae4f5,8fbd511f,59a2ae79,6d65db64,eaa0d61e,97d0a3b,31fa902e) -,S(4948606c,dd73dc44,ecf1db77,c796d8b6,806bab5,85877cd1,d9630bce,966e8fd2,3c67333f,786c8c67,841630aa,639446a8,cb8c13ed,f3db9123,bc64b925,beb95f80) -,S(4f259b32,40d9efba,4e3e40cc,a66cd494,fb5a19a6,5b5c8a16,5c18792e,9ea778c2,fdd88087,78c26999,c4a00605,49f4ea2c,b1590f7f,4748cefb,1b68eaae,4d17446d) -,S(f303a493,e14d7f52,f276e2b4,3e118eeb,1e7e918d,e7aa7f33,7e350fa4,7adfcc29,c49fa46d,befe53f,5f5bc49d,aa6ad265,453f7977,c5fe4163,cfa1bd4b,69141b57) -,S(e00c4b17,f4c0800e,c1b11859,c40a560d,58b9fdfc,29df5a41,ea4b2f53,c1df595d,62441a66,c3ec4d29,d18d0d95,7b4ccd18,a72a1003,d34832fb,8c81fb75,9763b99d) -,S(484b8486,1af6af52,a47603bd,2b754be7,ca16bef2,21581171,4cfb2301,db72ce70,36f84ff5,a0ac79a3,fe696865,2a0a6759,cf72e5c5,8c76359,d477e72c,4d32fbc7) -,S(88be58ea,d8b51f44,a1be6a8a,7cbc149b,ca07fece,11a7adab,210467b8,4cd93f14,94c10caf,7037fbc1,71cd6cd6,a0697b19,8ebbebf4,9f00c67d,4d46ebca,92687fdc) -,S(abf6ceaf,9fddd7ef,44a75e11,b10119b7,7372a3d4,7c163b77,384de944,47da781b,5cadb30c,6320c67a,e9dfe2f3,b9bb4ef5,41718392,81c4a59a,7960eccc,6795d290) -,S(e8c26522,9ef665b2,67fcf10a,17c6c3cd,4e221e0d,95663deb,74f8384e,b89d173a,9a69fbad,f9b050ef,d231965b,30d91646,bec7ba26,9fcd0934,35ae11f,ca2aeeb3) -,S(66652bd8,bf72ecb9,5e670a24,e8683155,e031f3ea,91fff58d,f60fa4ff,d9c6c23e,4844ec08,3f182b73,22c2fbb6,6f6630a6,5fa6901,52dcfb3b,4b65a3a9,30be994e) -,S(207880c2,d8421040,dc8202c4,45bf6d58,75cac841,532aaf0b,adf252dd,4c2c0964,2b1819d7,3eb24de1,ae4ef316,7c92a7b1,a562d93,80fdc54,e916d1f0,c1860cfd) -,S(46b9bde4,53d0692e,ec933485,ed0dff68,7e8f262c,7d9270cc,763fd959,2013f581,58af9be6,3ae599c0,f499b0d6,3085b7d5,394cc786,9f2fe225,6ecabd2c,a14f9bf7) -,S(5d9b2574,dbebe5d0,9756e2f,29af3aa,a2fa2555,d629a78b,82b1d679,75ea3e11,ed9f40ac,aa6ac68f,cee3dd50,7629758f,f3a64190,1658f0f0,2b87b645,ee59263) -,S(ecb5ad82,8b986425,9a76a649,1774338b,dc598fd7,77cfec52,d086c172,6e590e4f,2b78936,73c6d87e,a954b5bf,52f8212f,65d33ea7,ccc4b4e3,1d98df2,c9887886) -,S(b32b64c1,5e711b8a,1d174725,de55c,ddd62e99,fc90e96e,8f3ca532,3924ea67,af5d61d3,6dceadf2,34a7a94d,e7e4be1a,4d81b84d,e0fe16a5,403b0c24,a6ac2083) -,S(5137f71b,71582334,a6d57aa1,5cf6ab3c,8b7f6842,a800b4ab,1c308fc5,820cd364,f7ea5fec,c9b17dab,c6a248d,49757711,e4a3b38,95658381,efa652a4,4df1eab4) -,S(b9bb0e1a,390b5889,3e113a89,801c3f5c,25f94e65,63161539,e7c56297,ce9ea866,d8db3c90,3c3d35fb,ae4e14ec,e81e4e31,247f60a8,2539880e,6b66951f,8324a11) -,S(3f091967,6da40ec2,4691c21,1c42f47b,88cc1192,ec1827d3,17beb468,924fe9af,f1b44826,3e882c1f,18ae6a81,238d0724,ba4c04bd,d3fcd395,8775df5c,16bb8de9) -,S(b5fa25f1,dad4600e,8d55e7af,c70a1b2c,3767da47,d625ced8,d55ac88,d893b4fe,7575f661,f2ba296c,7ed3a190,8a49d099,83e49503,ba17a70e,1d6939b2,8ad22347) -,S(a0371ce2,dc6a025b,78db797e,90373069,e4ca06ea,6b1cc018,3d4c6f7d,680d17b0,92b5a8a8,9a5005ce,e851c521,4599b774,24f0ff74,5c4af6bc,6937c432,e859919d) -,S(5aae6e90,a49107,78863967,d7d42020,cd0a9828,da25ac8c,7b19942a,1ee2f210,ed9cc20,82a54f3f,fd7218f7,b79ec399,7e82fdc4,cd783957,5760e4f7,b7ee8fd7) -,S(54e7daec,f4a9b6f4,b100f964,850deb65,64efddb2,e6ce7b05,3fed2a28,1a0841a0,d9ada32a,54773a81,d5a857ad,8b34d96,70d46785,70943dae,cc83deca,97c9c63d) -,S(e9b29910,d8bcef46,b48d8be0,c7649b84,383ed752,391ecd7a,bdb454c8,8fbf44e8,eb268094,f669e91f,a5173965,50e4c40b,d7a26792,9a8df3de,b84c703c,261d6b69) -,S(43f95222,f254a513,1977c589,577d1d9d,3f537a1c,9fe14ef6,384e1779,da546a97,d7d3c653,43345c47,f245b305,b662a2df,eef80b3,97b3f5e1,4b0eceb5,71cb18cc) -,S(9fb45fd5,3999fb92,830bc090,216ae485,6723385c,7224b1d,cc91294b,a6c3b103,5b47081b,dbfd82d3,90d7bf7f,39a494bb,6731b506,b827213a,277f7ac9,febdf451) -,S(dd92282b,835529cd,3295919b,2eb466f5,9ca840e,20ad87f2,3cbc824b,b71dcce9,ec45f6e7,bc59d668,b1ef4a29,d1e23bcd,f3796268,3b58fb7a,d58a9e1c,5f726371) -,S(7482f012,9fbdd7,bf99def4,f3de23c5,fe29036f,c1ad5c38,686c05da,dc16348d,a43c4a0d,5497f6f0,bf2b2a20,b65bad11,73fc0dba,c24e65f8,db1663a6,b840abd1) -,S(fa4cfd95,97fd6278,1dd2f587,a5b03195,537fca30,f7a9a377,a69a6869,70ebd9a5,4568b6c9,9ddbf778,bd31d269,be18a8fd,e2a35031,a30505c,1b8ebe1d,c7ae823a) -,S(51e0d3da,e7763e8e,81905e1b,4f1ffebe,2f1078d3,27944c53,d9b7d110,3fa60b9e,118da0c4,ab572fac,cf9f20b9,2108ed0,1da673a5,2395f3f7,bfa2ff2a,36da6740) -,S(7d8e567c,c0552335,38c3b857,289e96f4,502fc674,f40ebf86,c482a668,dbc9530,76c3fc46,c6446a,4b9fe552,ba8b2614,7484581c,585c8ad7,600c2ea6,8eb37571) -,S(d924c6d3,b400196f,dd1f216f,dfa18c79,1c316d67,9ef4c0ed,8d12b94a,cd1dfb1f,ec33cee,881c04b8,b11eb3f2,88dd9b92,90b9d119,26c692e5,9d82aa80,4febcea8) -,S(8dcb330b,6f629c8,d18d28b9,7a99d82b,3965cb1a,bf953b8f,33074457,5e93c0db,3d8a2d19,8323902d,1b129b57,313f81a8,b58b7340,f6f7c97a,b6d74f37,a46857a3) -,S(dd1c4a3b,94b06378,8cf86797,ddaeb671,57910f1d,35a32e80,d3f749f6,bea5d2b5,efbec0c7,5a69583d,643e5be9,ab78cb78,3d2afebc,73d7c64c,869bede,b3230777) -,S(2b03de34,1dfad7f7,395f6ec4,84d292c1,ec0275f2,bc762dab,7658a885,37f5e772,3235e8fb,3818582c,55bd48bb,49f78e5e,803d7d1,ae49bbdf,97166a76,c3c0d0e3) -,S(3a795b0f,ba145bc9,7e7a80ef,a6b77132,677f06bd,4c3e7f39,47978c83,1428dde2,f4125b9d,df038a26,37cbc9e1,eed40aec,81af644e,a3f1352b,526df579,44914691) -,S(ecf813b,a133d6cb,9c46c081,b0a851db,121f5c21,788d1e59,ef8c0588,684fcbbf,69e0daf2,a7b7b473,7f2becd0,789529c2,597e3915,ebe12093,ecd7738,13e53560) -,S(637c4982,c14163e4,1037191d,d4e09d3f,74383245,5368cc33,57669186,d6217d5a,da5a2ab8,fd83d2e3,25baaa5c,a378318,f6fb3747,5ac64b77,a74da573,deecb410) -,S(19fe73a2,d8875b57,dcff5fac,20530da0,54255658,1251f7c6,b198b3e3,71b90e87,3b03ac18,2ccc2518,c367a77a,1fe5e8b9,a3264681,28fc1ad3,5a39f7a0,d8151ca0) -,S(16ea62a,d4cdc00,9d151b3,b6680b0,c68b4cbd,f144c234,71d55b7f,3bb7ebb2,8cac4a1c,53672e59,338612a8,995980c1,35f02060,2e3b9f6a,8fffce9d,e53fa629) -,S(6b9d68b5,454c6d21,678e5413,279f9a28,e1eed485,fbf512e8,49f35394,22a40970,b63f5044,98ebe37d,af9e6969,da888eb7,907f8565,4b05d472,fa4b1b27,ae365482) -,S(1fa20c8c,8f0812c,2e7dc948,afb7ec92,32c3c27d,23165d05,868dd127,b5ed3e6,c5257f4d,82133642,7df68606,2c229fea,6cd16857,280a60cf,ed84deb6,29838076) -,S(73a83c92,7daeb4de,1cf1df6b,31d8f536,af15bb38,be506263,e8e8a6a1,bf6acc86,a08acbe4,cd6c30b,82b4e24d,e8c9b891,26a21dab,e4df40ab,2fb7ad6a,82eb8adc) -,S(3a995664,924e2dee,ca278cf9,3ce265e2,85ba90ce,fd2a55a4,8e1761ee,7588bdbe,f3221adc,99eb33d3,52465d93,91caf18e,d011a1bd,3b7cf39,dd48d45c,44cbbb0e) -,S(7c65ee19,b032f5cc,1d45cd9b,9c160e86,5ca516fa,b4f88596,5e07f269,3d429c26,47c7faf9,e3df277,d31076ae,4be2224d,8cc54a5e,3743e287,ff9572a4,23704c5) -,S(c010694c,6750dbbd,bd953118,dccb8d03,2f05e6d9,65db8fb0,3dc00b22,e4d397dc,3b4914c6,dd6c5441,59dfde10,a196f132,5a5e6101,52d41be2,39583b80,6c8e730c) -,S(e255848e,d28d8b6d,6f95a12b,92136131,a33dcb2c,a723fae7,5e317cf6,62519d57,62f7d5aa,1757dad7,98207dcd,18183b24,377c9ac0,1e106fe4,d36d9264,3fcfb7b6) -,S(f31418e5,73232992,3a878dfb,f1de30d1,a9669da7,76effc45,bd1a56d0,2c236ed9,e62ab884,dce0d946,55e34c8a,630b5aef,16a1eff6,1f889552,af7234b8,ae56b84c) -,S(9adb945,b876313b,ac9c290d,47c1e6aa,1f3f3c9a,e8c67770,61512c2b,bd703181,b21fc142,b4632616,4820b82b,edddf2b2,51531d0e,df0f0f86,50f74d1e,9f0908fd) -,S(c4682b2b,9d4a63a1,855132e9,b35b390b,ca04b846,b83bf36,1726c3c5,808da322,f25a906a,7100ba32,1b659762,23e36f04,14e9075a,835ce5a2,6eeb5d03,d35f6972) -,S(ebb0fd6d,60f49c47,8167c405,597c765e,559159f3,ae04003d,a99a1066,ea80d63a,eb37d160,667ac862,1da2ffcf,28b431c8,c4202f67,706f4350,afdc868e,6aa0b0f7) -,S(78f12d20,70d8bcb4,267cbb,bff637f1,65ffb098,95f5734e,3551bcbc,9a5597a,42976ab3,36621756,1bb574d2,c87d99cb,7419a3e3,39973740,7de17090,2bbb78f8) -,S(3dffc4a,f6214b63,9839fbc2,b949621a,35ae41bb,e7679eee,5798afbe,85919f69,58174b6b,1b4021ae,22dd15a4,29d97502,a13480fe,902860e9,36fead8,57f2c456) -,S(410c9393,a4ed42ca,2115198f,4db76eb8,bd16bf0d,324528bf,55d5d745,b55a15cc,404ff4b1,df71b89b,c14c2cf9,bca25176,83c2981a,731fc3d7,59faa0a,5ed58306) -,S(6b4d5156,87d6b079,3df36632,6fe6977c,b93e6569,66797196,6c16c495,be4e3649,647a4894,bbac207f,5d2a0315,2db1760c,1a25560a,95511c81,5d6c11a5,e969f4e3) -,S(58ffad7a,e87d5986,f0bccfd8,5005d9c1,6f0d8724,6be4dfd9,4a771c5b,a5f34247,ad8b7ad8,f9ab15fa,f50d6f93,ec8629c3,b33fba6b,ee36ace5,e505cf00,f0069817) -,S(e6d3e41d,1835fade,af27738,23e883b4,adb95669,72892c72,b310eacf,a6a757fd,a136c88c,b580ece7,cef03e42,5dbdb8ef,d6395cab,b427ae61,45a0ef0,21359c15) -,S(fc47c62b,43aaa030,ac104479,21bc1026,3b561b42,a2d32a5,573ae947,d953b35,5d318d1d,65fc7806,732b5810,40a1f511,62723626,b393b29,50230600,246224f0) -,S(ceae2867,cbcb37bb,8e78da9,3553866,d0a1b8a2,933cb1ca,36bacb7c,6fdb251b,48bf2c7e,c163aa95,79417b37,343727b7,956cc629,3a188c16,d4c2d1dd,abb3dfd) -,S(abb12378,c84735b5,c23408d8,2516d887,9195fb74,c8972d78,daa8243e,1befeab0,5a0bf64b,da5a465,d9d0be91,3c8a56d9,ce901c36,67041a02,abb591b3,3f66698e) -,S(d7781e39,8330c7c9,2185302b,e116316,1a576ce9,43a4824f,274ea700,3159eeaf,6341a432,4e07c5c7,3ee7398d,d1be3d7d,261aed99,96f6f310,fbb464af,d06651a) -,S(a6918dcd,46ec2045,72d71646,d2a21df1,6f3ad133,dfd41a6d,be5b7684,7e4c760c,c0e51aba,378d498d,9a70e4b5,3521397c,1d6c7cfb,2f6634e5,1f056e7d,932fa9c) -,S(413a4ee4,fbb5de60,392b340a,65fd9706,7785e2e0,248d2770,6ef044ca,83d1a204,a0362506,c18a8f34,3bebc668,d1b08fd1,6595a674,51db27c3,43af172f,8a3dd197) -,S(e1a7bc24,de8b0920,f6c4aa08,2fbd1126,87fd8766,237311a8,9681581c,5e04001c,3e3ba9fd,d0a2873d,149aeea2,61a55c65,3a3d90b1,efa8e49b,29bab100,1a6bed16) -,S(ff9292a0,a147ccc4,b5ae077f,8a337e05,ab1dde9b,1795942d,8a9a0fc3,dd333a75,e50f027c,5f7a3463,7654b412,25ad5dfe,b555ea2b,8305c7a4,3b6f5b78,7a23a166) -,S(eae56623,437c9dd3,9dc7a36b,45c2d3,afe849c6,1980140d,900039d4,4ccb9c0c,f1b8c9e9,92847436,dcab5a9b,22fe7e78,55e62e40,372d77be,39f68974,dd32e043) -,S(7dd20cbe,3467a3df,e1eda0f3,48c39e5,7f9c6004,bcc89227,3d002cb5,54bd5282,ec4d2f23,f035d2d5,4cf4c3f8,31772a46,ee922582,8ddfd4c6,4eb6a689,7c1485d0) -,S(359811cc,5acf1291,547b8870,33bda3c3,e4e245eb,db0dbfc7,3a02da3f,12a877eb,ed2f5087,8b97a3de,6ff916f,511c3a27,7702d1be,2b683a59,bb6acd98,e908a792) -,S(fb33e89c,f2bcca4e,4ead57ea,1a24d1b,5a6c76ca,bc605a2,c031102e,49a71c24,c75e02f5,ca602705,7ab5b958,42a9272f,d7fca940,c26e980e,192861d,2f1c9f45) -,S(a1cd33e,5eed74a0,1534f836,b05a5129,b7b2970e,f293b606,9d1ebb56,e5f687aa,f90d1ab9,ccfc345,3b2b60cc,1e4380e9,bdefc37a,896a1abc,c9978d08,1ec4a6b0) -,S(461696b9,3643b7a,bfb383cf,ced8ac92,5d9f169e,1db30999,b8553504,c4213614,674f5c77,5f300fa0,c8f40a85,9aebffd3,ee91c4ce,695998d6,de0d59a,3033bc72) -,S(6c6aaa22,1b589f6b,ccc885ae,93f7e8aa,1fd5cdf2,27471727,f390d5bd,e14ab025,a77c5e03,40e1b90d,1ad64483,fb50fa76,aeb84417,88ca415c,9f8d2cbb,aa077538) -,S(c918d391,927f3310,d032c7ee,6e729e6d,792eff1a,72acc268,3874fcd7,4e61c38b,58fd746c,346048f8,eda1bed0,e5b6cb58,fce24a72,6e27f965,74243c80,780dfb5b) -,S(48679e16,1ca0a3f5,e4ac2654,213c494d,9240c3f0,33fbe2c2,142ec589,6dea5918,556f93fe,300cafe3,e93a2966,767840e3,b2a19fe7,9cf204a9,a30d1f1e,3e1d1a41) -,S(c68c05a9,e46b6440,a72d6eed,eaac085a,5e945659,ac46a584,69968a30,c6e7b858,b8b4b5dc,35d4ff80,be3d64a1,d036a117,c768746a,4d2bf2b6,1b126460,15de450d) -,S(d133ef10,6358489f,8f976dc4,b6c54699,21e3dfe3,6f326dc9,f0538757,9d444e6a,2c66abc4,db690d2c,272b0f57,afd66a6e,327ec3eb,e32b45be,cbf3c502,baf968cb) -,S(53544f59,8d759dea,b10766dc,48a7e2da,61ca0a60,a201d193,92dad05b,3df976ae,449a205e,61cb7aef,204e3f0,3a199ad7,993d711,537e17e8,79a42bfe,2869cd47) -,S(3108a074,fda5133,39e26385,14b6b7c0,9254c65d,ee374a62,2fe34acb,83b8b331,42edc90d,54263fea,8b1a473d,ac2f2244,d6fc05d1,f59e115b,5d930132,268b6243) -,S(1666c40d,52c1c04,d9e95099,aeb55861,2ee58ac0,6b22f962,154cd8ca,7cb4b23c,5065bb41,ae046638,aab55923,e0752954,abafc247,d201e84f,b6c444b1,93a82fb9) -,S(c96d07eb,d3eee6a8,f001290d,f76b2d82,ed80fa90,bbd5ead5,3a572457,ee47722e,d3d69c04,447fb7e9,a3416af1,798b749d,13ba06e4,78a432c8,d00dc2cc,7e20baf3) -,S(a9ffc39,b11b5b05,78769a9e,8ce7542c,647fa7bd,7b2c3479,fce84d91,1d81b49d,bec21248,82e928f7,e98894dc,25840712,80a64449,38e53747,375d2122,68bcbee7) -,S(52ca128c,cd4c9380,8e55d3f5,29320fd3,e825787f,1a600f27,37fc5fbb,f7af0632,846e8a80,95a98cb7,b4ebab01,4d9dbfb9,37ffa493,83676ec3,70f42cde,3135f7c4) -,S(ff92aac1,77fd9927,7b8abc41,e49f7c94,698525,2329b9ae,8e0fa34e,a9407c20,af0d8cdd,5aaf5273,ebbbf2a9,b7230373,dafd9a93,42a47331,a3379f45,8ffdcfb5) -,S(a692a73e,d3c10a3c,38163c97,314d02fa,5fb653b1,d729ff09,a541d01b,27991e0c,722f55a,3e5bd3e8,d863d00,6b82415a,aa05c949,9a537809,cff9be69,e468b905) -,S(d9e59c3f,7a629a93,e32fc4cd,2c98d480,6b813ba6,315ce4e2,e2fc7fed,4120aefd,24ce2594,23073119,4f5bf658,909a47fd,3234be39,13aa8d30,eb08e14f,af0214bb) -,S(74e5270f,7771b109,64991ef7,9abcf05b,4dde8d5a,605ab587,14b8e534,4a0f6ff,2ad861a3,a4a83f09,687a285f,1356b1e3,71ced066,69154887,14bb0461,b3b1670f) -,S(b9169230,1c43f7e7,61a85615,7957c3a2,744668a4,8587ff58,7a201f59,31d4420c,bd36065b,c1268280,4cd818e0,c6515a5b,659ea423,f5b23e5b,ebe1f74e,5819536f) -,S(37faf253,864568da,972d7211,505b7fb2,cd01fdc9,5953bcd8,79239d90,364d51ee,b69ae2ce,749db3e7,e6aea736,a3bc961,d8c12523,6f7be823,65749ead,3bc15f85) -,S(e194114c,4a1c138b,34882477,f0dcd065,1c379f98,c198614b,43b087bb,a20cf8d2,7a3afb4b,b90ae22e,3b182cf0,6514a998,889f2ad3,d71d4d67,89e3758a,e898a93b) -,S(2ce2db01,d3fb451,7388e4b3,c81588d1,1c8b13ef,917333c,ca054379,fa17ddaa,9232da9d,af0e76a9,85e1529a,ed1a5568,74285cb3,8010c922,e2c30d77,367bbbc0) -,S(c292ec48,4bdb7045,3dce2e82,1fea7688,bd66c6e,59635f49,98618f9f,3d6f051f,210a74f0,6b81e69c,4d0af49b,fd153247,12b77736,126f4887,2b119ec8,97b57d6d) -,S(15bcc9c0,97618aef,697b423c,cd83ad3e,933db83,d77b42ad,3e132036,a5acfeee,e9fc7ef1,1bb996fd,bfb3c490,14912ca1,a1bb98a9,e9611c,1a83a806,b88a7a33) -,S(46119caf,50f13bd7,97be45fe,55f2d298,848639c6,99d5b113,fd24cb24,6e1e7785,6a203f91,f4c56eb9,7762cf8f,9ef932b4,ba301501,5aeb1215,b1327a93,842ea3b) -,S(f3a17794,3e4df182,a9549a3d,2da1f9fd,cf141094,5e6b3a64,9d9df885,b6f9ecf4,b34eb7cc,5e82ad39,fc2b6619,859f8328,444a1dff,c82ee115,c80cec10,6ecf7e8f) -,S(cef90a74,84a7f468,db9cbd45,f5b9a0c5,fa98bdfa,50297d67,536075c6,b7913fe4,d090eead,2a43fbc2,86702946,52507875,fb79a555,e5c55737,30fa40a2,6a301815) -,S(21d8a214,987aa938,ec4b88b2,4bfa5661,26c528b6,b9060b06,833c6ed2,a35702ce,c354340d,5b65a23b,c628167c,8a2830,f736dfe9,a501fc8e,94b66f26,d84579e4) -,S(6b18ff27,9049be4a,62a04f6c,f82dbd24,e19196fa,46e0761d,5d139518,3a1ca53e,ef806f0c,52c01367,8f81e9b2,6698fa32,6343f0d7,2522f8d8,6cacfdb2,c5ffa3b7) -,S(7d8ef4f2,452cc04,d5332afb,ea3e673c,bab07c36,c081a0ee,850ae31d,cb466e6f,32461667,55a2ceef,273367d0,df10f6c9,d224da47,f19117bc,137a6244,2cfa0c0d) -,S(c7de1821,55d15649,f5bb6327,65ac74a2,3413560,b1d31afd,6994b488,20d12cab,d9965856,c5fb2c0f,c93b8659,5c3240d8,7fbe0136,11d7e844,48252ce7,96eaa23a) -,S(4cecb33a,915e2c3b,189eb6ee,45fa4eb3,eddeff09,729945c6,f893bd,4381b294,cf17f112,b5e61cb8,44625035,7b700cd7,3534d6e1,3310b6ff,d1bbbd8e,1ea3aeb1) -,S(826cf464,bfce606b,b4c3ab5d,4cf00fe4,1c9bc72b,285c8c10,204aa658,66255749,6ba3b431,527d285b,5156fabf,b150aa2f,6d7ca564,b18011cb,b878e235,7b6849c4) -,S(c812dac6,f497d245,5192ba92,2d6fc10d,de51d608,d82e828e,b2187e7,648f8f62,d02e8c7,73630680,8126ee1a,efaf53fc,2be94dd8,7773e8f6,1ba6b4ab,b08b317e) -,S(5269550e,bd967f47,e45eaa8b,c9f14ebb,aa45926b,6e38cd1e,3c6d5d3f,e0ff8851,a1597d20,26e3eced,443422ff,cd1b3fd1,b45963d0,3086a95a,38b8661f,99a7455b) -,S(7fcfcb29,80e652cf,bc42721f,cdc40ba8,c7c2ae6d,54a51e9b,af1afee7,e84d7676,abf72d90,4a408e34,ec6bcbaa,ac8f19d6,a4d044f5,66a9cce9,f95debf8,882cfcdd) -,S(85f01aa0,4597e104,848e18a2,132a6a07,3d5f25eb,8baa857c,79dc4b6,64a9f451,f7463ceb,8a058187,7bbb71ab,35bcf456,5398cec1,cb4e0132,4b4ec47,e5f081af) -,S(95b4a1a,7dcd860f,ac3fee1d,10febeec,dc1a5fbc,224035fd,a01f8dff,92885628,2a0cdf9c,5bd94467,efa9dfa6,94c6ee3e,1f80bced,23738d97,f70406ec,bef7f772) -,S(4f624a6,24dddd0b,b254b38c,e37753d8,8cd95cac,ec4709f0,49b90ecd,7f6c51c5,874a9a83,2efecd9,2a20dcd,8ccfd454,668de4eb,1b976bd0,70ce584b,c77a4fa5) -,S(39e06912,e18b537b,ce440f58,545e9c6e,a2914d85,698d4043,437dd66d,7506b48d,eff20e0a,16e93096,abc80153,c128aa12,f06c6d,4695bef1,8db7a167,6f352e0) -,S(52edc132,66d67831,74ff4f59,cadb979,4c1d41b6,5efb9310,7a717b46,78f1ace9,e569e202,c6781e3f,e32c0bf4,9684d7d3,cb07cf55,8f46927c,3af6bbc1,c4d402d1) -,S(e3764b48,964b8107,3e287f07,c915fc8d,e4e9458d,6f2a8d3a,1dfa43f3,4328465f,bde2a64b,fb13e0ba,351b460f,6d0d7574,5b7261aa,53a79b6c,3ad5c8f3,4cfdb023) -,S(80efe507,7c77698e,3ec38768,ef81732b,e1c81aad,9c42cebe,75627eff,bcf513e6,690c671b,c54391e9,695e6059,953d3d9e,a9df2e17,5aed4bc3,483f104a,388b709) -,S(484ac7d5,ebcc497,a2f2bcac,87cd23ef,19b0bf7e,93f8e728,5173f70f,c908b641,1d9570e6,f3b17236,9f2b8551,653f3271,5bc8c995,14c2aeb6,1b44ea5e,90ef371e) -,S(9c989e3f,bf1fbdd8,4dfca53e,4415cdfa,adf26c26,3801ff65,36b8fb5f,77e3d124,a34ae61f,5755163b,964b3b80,28fee3ac,2993c442,d7f16dd4,c79aab0c,88212a38) -,S(8b8fb0f,601afe7f,6456570f,19e37f80,32846dd2,97b0d8e0,9308c57d,75a5066b,7858afe,ffc4e6c9,b2e32f10,fd67a1,d6166c72,26f03b3c,240b29e0,e848c9e7) -,S(e37d0e74,ee1d79a,981baa79,e0a5d807,bce0953a,211c00ef,451d9d60,7ee78177,d28a1285,2ad25f4,df1b5625,bfe59875,a07d0593,aab4ee6f,4bd23ebf,b09f8f9c) -,S(80c8577e,9a003683,ad658e75,47657b1f,281052d5,54cd0e19,4b2a9e70,1325c147,b3fd0cd,7ca3a2ea,ec7ba8a0,d7297347,fe2baf99,bcfbbfe4,32a6346f,564d945c) -,S(e7045d6d,34121e5,536f7902,67ae01a9,50f6ba8d,2d05349a,ddeb3833,3ea8c6a1,7306a8db,326994df,e15571d9,c2a5dd24,60b37c2f,e97559e4,e7d88ab8,8a181fba) -,S(55d2da4b,850a47fb,6b3af0b1,3c03889a,d87554f7,cb346980,4f2978c8,652e0d71,6ac0f982,c861d0f6,cd20b7b4,f22eee5d,189a56d,5cc46780,72361e79,dfe16e7c) -,S(ce562e09,55a22f7f,c83a5ff2,11500c03,a1e86d1c,404019f5,5bd1cdb0,b1a38d2f,91de004d,b4aac47b,c6b0a165,edc5f82e,47407032,6f1ced31,4bd6d96b,521bb865) -,S(74e00e1f,596af05,7f91bd64,53107f1d,cd0eb8,6b93b6fe,cc7592e3,7854773b,11ca88a3,38e52a53,eb311867,b10a146d,6fa9f015,11791374,e13fb749,d8e1d217) -,S(ae8f0b6b,c194f6c9,1d83e400,ac92ed97,68214d39,95868530,a2e99f9e,2104eb48,e973fc42,dc0a930,36127de9,eb57cbf8,d4aa8f73,14646362,c855ceec,d7ce4cf2) -,S(40a8c06c,8df83675,e108e0c0,565f33d3,7854e722,6f76b674,1582fdcd,ef891ae7,16ba7850,b5116afd,3d29e0b0,40faabed,b8ff9c09,83af624e,a100555d,887bf7ed) -,S(61ea9e54,5c57f6fa,a2ab410f,861f1fff,926795b0,4d240e48,7f6df1bc,6df83b33,c69ec12a,e0b217c3,72e1791f,7d4529f2,b9063e67,38a8c03c,49071581,da79ed15) -,S(1c889cd4,440caaa4,fcdf55f7,2145fc17,d73e25ec,264831cc,30a0cb5e,c1d37632,41b5246,131fa67c,7314a223,7db5e4b0,574f5b86,11560166,ee55bc94,22d72fdf) -,S(ff295890,791d87e7,982a99d3,ab50bfa5,c58e0d06,25392abb,4ab166a1,8e49525d,a09664de,19951364,19649baf,88806fbe,c370879f,efbe4a58,e619a01a,19454570) -,S(5eb2eabf,cfca1fd0,7c939e5,b8f890cd,74e399ae,d9bdf785,7bca8767,84e95f99,4c42e970,1c9a783c,201aff12,16265d8,1f46f25,fe110f63,31fb8fb,f72c9871) -,S(43e5508c,dbccc93b,5b3f8ce1,7a071c1b,3b17bf4d,8153f61f,cfc7b6b4,f6cbaf91,b5ed8f78,438ba71e,509ec388,d09a5307,c853bb73,db240638,15a07343,9bdfdcfc) -,S(f5d16930,23cb20df,c8607261,cafe533c,eb513f87,7f6e2c99,5b0c0f75,fdb56f53,e539b168,1528332,f7fc4bf8,73e2965c,2557dd40,6eb2c8f4,92ce0dc2,126ece68) -,S(db9d66d1,5dc5a918,46180a62,d662a2eb,72313c6f,ba511eb6,c7fe0c0f,78aba2a1,c96de8a3,61f0dc5a,9e2762d9,2257857c,3cfb46b5,81c3f0b1,f89a20f2,a1517227) -,S(e760d3d8,46fd63bc,4f565bfe,7bf5133b,56ffce08,27b99ab6,833a64b8,868ecdf2,60ee6685,8be2eb4,1821cc82,54062e01,2c1c1e12,285c8381,e60e5d4,12f102ce) -,S(2bdb2299,caca7ab,d22533e7,12e37004,e3a956b0,31da4d99,1351d790,5c33e026,64675cdf,c2738105,dac3e877,e27d00e7,80193286,24cbbf82,a784713f,b6e44731) -,S(1cce0bfd,5992134,b7813773,9fd6c844,7be48d20,e001bbbf,c3c87b9a,8166bee4,2d4a8ee5,1ed7fe30,c3a1253c,4cd9e83e,b5eeb73e,c166f4cc,42788bbd,cad37057) -,S(6d6be3c3,7f5dae7b,ff5b5bd8,ec6b8c65,ec8405c5,bb6575bd,6ebf89a5,77641075,4fd3cc1f,5c6fd3bc,6011507f,7c4eaf4b,24d1938d,35159b80,39246ccf,ac9c2c7f) -,S(d82c180,d96e781d,783fb1ca,8758fa1d,b3c67f2f,143e836c,c6007d8b,bdb22351,3802f669,952aada8,93b3e9a9,74a43218,37415af6,7964b1e1,51a7b8e2,7ad0c7d9) -,S(4ec61edd,7e03fd34,f91dfed1,b546f1b8,fbf9fcee,8c73e343,b228ce18,3db3cd71,e1199709,b5b2e2ec,8af90340,de9ec3c6,db7d948f,aa941cff,b1984856,b03ba9a9) -,S(31aad469,73aea11b,a54744d7,bead13ee,a8df7a8f,8e735643,add781e9,e17a034b,64676f41,3e49f606,3f68bdf5,7ced7486,a94680f8,e60e2913,f13b674f,84b37adb) -,S(a9842189,2fccdb8e,f6515903,b589ea62,1f946bd,97e2931a,5eb1ce4d,4d173e02,50be76ac,3b2dd7a3,a3370e13,3cd6fb37,7ea266d,a566049,abe488a4,89a3908b) -,S(822b54f3,3ec00433,7a6cfa09,277540ce,fee79b08,a50695e3,f8fe0ece,b7bef099,393623c6,20d3f604,7343ddce,d8805bf0,7405d336,fda8c712,8d044851,236bf7f6) -,S(100f6b55,fe3d7000,c5f8de14,ebfc5d7e,15793d10,e99dea3d,33adf25c,15065e0b,d1bb44f7,58c4dde2,7c928267,6d6c1114,a352ffd0,dcec8e51,9b2cd74a,4eecb4c2) -,S(ca5d8318,6a09c227,481aa6ec,d195d094,6a54257c,5adb71bb,2d4e8836,d6142f7f,d890847f,b9747a0a,f3ba0c38,84ae057f,878d8d31,fc73933d,e014f4d9,2677b42d) -,S(e91c25f4,2234d20e,2931a352,f98ff610,e8ffe53f,101b56ca,fa5da12e,24bfbf14,b1ec15e5,441ec52b,c71740f6,d60e99a7,7a26bcf5,143ceb41,872b4a22,964dbb86) -,S(57a8c8dc,310902d8,8569b290,22e99ae7,acb54547,2ccf7065,9e9d42c,1ae34445,85224541,442e09d,f4e92db5,64866aee,50e7cc3f,b8c20acc,b9c6161e,30ab1fb7) -,S(232b8c67,2502d16d,badd0d41,28c02b6f,55a8531d,a6fe87d9,581045b0,7104500f,38110a0e,9e7d8587,227c476f,6549492f,4f5255d9,e618cf39,9a7a40f5,85f93fb9) -,S(7d0be68a,d71f69b3,4f5d4876,319f7e7a,750d5c7,e3dc876,187627fe,77004fec,3e72a050,7d0af3e6,1d6f5402,8a5b971e,a12b1d18,2ca45e67,ca09efcd,45124633) -,S(4dd85f0b,77c2a271,c95fa436,90c43485,b70b02c4,9a46cd83,6ba7a2d2,7af93292,843642e5,c9554d98,48ab6ff8,5dada7a0,f139e64d,2081978e,8c9e3bf5,1c11d597) -,S(537a93f5,88f02004,70b531a1,74ba9a7a,3eb2e5c1,eb767214,9e264e2f,712e52f8,b0d9b3a0,dc009266,8e25f06,71895af3,94efa1f9,78257ebb,3f839b61,340e161f) -,S(13faf471,325b1e57,98ce60a4,6f82bfd1,ab346590,82588ae8,b972b331,9ee48684,a6720384,e84eb529,e22f2585,79b2201a,dce7ba18,845b8bfa,49a21ade,7634f743) -,S(691e24ed,5861b344,e015dbea,809dede7,ca17c482,22d9e06b,e1be4405,cfe8acb8,e3564adc,c197b0f,cc520d90,9d9c6347,5ad00294,3d0f3f96,6f49b76b,91c529ab) -,S(36543b91,aaaea850,15aa394f,fb334923,b754b3f8,9047f73f,423c15dc,7d3d7ea2,73b4693,b79b800e,8e48c838,9218094b,9dff44fe,5a1fafd5,2d68a2f1,bbbe5799) -,S(ff25abe0,394180cb,1e045045,5320ea80,e007bb0,fe3bc8a2,24f20b07,8433f05b,a512b109,26dfe650,e6dbd678,ad9db412,938f69e0,8aee6c2,f903631e,530b7e51) -,S(1dec07b,5faafdaf,51051f57,cd0247ac,cc607bc1,70c53222,72d389a1,7d87e443,7e77e937,382b2bc0,5a2207a9,2598dad4,d870ce67,d0e138d3,bb35094b,9fa9a325) -,S(2f10f776,f62f8632,ea20147e,d14e0919,485ab78d,fc636236,29c2994,9f413c32,3b2c5fc6,e760462e,b9d8c8b,5aa6b1f6,35c23668,33e7ef5a,d25269ec,68d2184a) -,S(7974f394,e61c2cdb,acf09681,4bcafb4a,ade31943,cc180188,31160022,dabd73ca,e1b34da0,3bc1aa66,87df854e,813ba451,2be4cde8,310e4056,73c83600,89e98309) -,S(54c5f39,3c5cc416,56577469,84aa3695,32af1ede,3a51b14,436748cf,1701c332,3dc67b49,49769cc5,22b0626a,eeab6ba,ddbde8ac,ef78a0cd,800c1b6a,5043e4e) -,S(199aa296,f047c7eb,1d8a972a,318585ae,8092e905,e555915d,81c1a3b,425f3783,f5823679,64d17a96,b4ca7946,dfd3a266,585154e1,cee02e2,b87e8fc7,eb46c262) -,S(d15d39d6,fb616dfa,6c292a3b,a1fc58e7,cbcdf0be,7976be87,9a7f088a,9bb7f299,4c8ae97c,4e37f837,bdbd4912,f43bfc79,679dd418,b57d061,f705ba60,2bd7a900) -,S(76d65134,880e7dfc,81a332c6,a04b82bd,bff26eca,9a5aedf5,a6f6683f,364ef58b,b71ae708,bbd22d83,a1ec9048,6975b9a2,7b4aa5bc,5bf1246a,6464406b,401507e7) -,S(1eb4d2a5,d4dffe36,30ae9ead,792ffa9b,452ef0e1,94c06a02,a0308143,dcae51b7,88d978c1,e6ab8e79,9a286af4,58cb3eda,7cc94b67,589b144c,9a55cdbd,6ff47b0b) -,S(dee03251,35708790,361c3451,6710623d,e474bdd2,4513562f,95512f0c,dddf571d,d22dbcfd,cbf6d809,2c68a28d,c118ffec,496d9623,b20667c3,7fc487a,1690f565) -,S(2eb0272d,c98ac6bd,ff68f0d5,5f13f509,bf1dbd9d,f36385ae,ef02356e,56d4760a,f80d4355,4aaf4eba,27aa1832,90573687,5c69ad44,7211f746,111ca02b,26a04277) -,S(eaf62e69,7509672d,8ff6ff7f,c7788822,b75853ea,27636b5,c39b0321,ab0eabf3,442e56aa,1c8fe22d,71b88b96,90733f1c,8614e160,35070095,6effdedb,2e0a3b7c) -,S(2059070a,13d96fd9,6bdc442c,236ef463,cbc70185,b8799d3b,15ef72ae,4592858,bc9042e8,3f259ae8,f6221d7f,46ae56d8,f426fbfe,901b94a2,80da34bd,14961ec8) -,S(ff2ef7fd,9e7f3e7e,6f7b4cee,a44ec281,4b8b4a44,208c462a,f925d27,ad2f52fe,6ace74fb,fa6f72b4,8156cb52,a67f5137,956a447,6b69fe3b,233ce4f3,df0a5e24) -,S(e3e5cef6,fc4553fb,d337a7b0,4357ff1d,d8fd0de6,4df17bf6,20f7f9d8,9d14d83,acddfda1,baa7b60f,d0d1863f,769a475f,e667b6fe,8a047365,1b84f44d,238f0460) -,S(97a8726a,41c02880,e9942341,a66b9c21,a0c64577,bde3c54e,c11119cd,bf57a6c3,b5f37cae,27023d07,78cc5c7,26d845e1,fe160aff,3459d164,681cc38d,8b67b4e8) -,S(ab01e6e9,4862f943,8639484a,119eadb4,12fd9002,1d7781c4,1b020450,9dcc81e6,6ae50c32,101b5c3a,51fab05,2ed79e5,48853cf4,15a30043,6b11ee05,7483b14b) -,S(c464410,da2dcf6b,2e6ba5a,c8d8479e,58ed9a4c,a8c2b0d,5a2ea15f,7673668f,3698c590,62392c7d,e597f333,cd3ce45b,eadee944,5209d361,adbbc386,b499945) -,S(17eacc68,5f721f3e,2013b0e6,76c10795,ee49d524,26edbd86,48f098f4,17867534,cc3116e9,cb19f49,bbf7214b,b3ab76fb,fec0f856,e994a01b,d6b63ece,189ef300) -,S(c040dd40,2908ef17,539b77bd,5befd53d,3ed2e8bc,d7d3608f,2b114dea,d4c00d73,7a6384ae,55ec2580,4d1403d8,45113dce,b2053ecb,6ce0d3d7,427835b4,15279c00) -,S(a5963498,3658f70c,2ec25fed,6659a290,41bf2ba2,ba92db93,41b03e39,2ebddb42,dc114caf,260ec4a7,a8e8bf4,1695785d,1ce7c2d2,82359600,a950ade4,d79f4872) -,S(44fe22d4,51dcf63f,c7e33d09,533836c7,66382372,339de279,9897cea1,1b29aa0d,1718c4e7,3d4bd434,929e9ffa,e2496f79,4f3bf80f,ae805a9e,53b577cc,4c4279b3) -,S(8bd718aa,1358c15e,fa3b246d,e244bfd8,4fc6b5f3,ed5ec91c,ff466a11,2c71647b,172f1a88,ba6c11f0,1b7deb8d,e4002793,65a0a3c8,443b2fa5,f406dfe8,4bd737fa) -,S(8ebdcc25,bbe6aa23,809aa53c,3ff3a7a5,d7ad4cd5,5dcf3cfc,d9ff8ce1,738680d1,5c563b26,af86adfa,c3728c,f886d83c,5be64766,78ac5872,cd798875,45e5641a) -,S(5cf54e1f,688faabc,99742fb8,be896cfa,b469e5d2,feb72f4e,9dbc67e0,e91713d2,d82d6590,d06330d8,2f86393e,190155b3,4920e8a8,86324b18,5694786b,e4fd09c5) -,S(6c0d96e4,3f01a1a7,2ec16ff4,e04571ed,387185c1,4c8a2f8c,db4c187a,85845f1a,f399a14b,763ec2ec,f3415c1b,b9bb6f70,abcf013a,3117ddd6,e55a96a6,b0798c08) -,S(eae928fe,fb6a2fdc,d05f1515,5726a133,9a15ef0b,ea716ad6,90d32dc3,92b74046,bdf87ad9,f086339d,cbfda797,8d6ed40e,f6fd4626,60d6db09,84ecc577,14c76bc) -,S(e5e5e30c,bbe72fde,d9f0dbbd,e08dda,b61d5cb3,1aa688f0,d572008e,447b3a21,9fb4adb8,f80b6e67,47c6ec03,d5171ce8,5de65682,a105435c,5610065a,85b248ae) -,S(711212ac,c9e26bb7,c5ace176,26b300bc,78df6b0c,a79a0b79,7dbcca,138223ee,dc68858,4ef44ddd,9e6b343b,c4c73fe3,6b873239,18e11cbb,dc3aa72a,ef027757) -,S(3b52ebb3,531aa4f6,ddbb9ea3,fb5e5784,c4cf11b2,a4c67d50,6b6340f0,21c5e22c,3da3eebd,dc0046a1,3facf02e,46818640,b698c8a6,3c5fb9de,55a9996b,b190938a) -,S(30f28481,110345e2,7dee7292,fe1c7a56,45294a17,e96cadf9,1eb76bdc,cf56b78b,70c610fc,26ece34b,f047864d,25116fac,3c149164,a1deb08,8e6d702b,77abb049) -,S(4a844a8,12c55b6,4e4d37b6,1ca4a1f1,5cfef527,699d5ab5,edf1564d,e930ff58,49874548,508de6e4,dbbe6bd3,8d0a9ff6,5826f9c0,63274cd3,f3189d59,683dfa3c) -,S(a5ca561e,a7c8484a,642e0fd9,a999e14c,5ce2b5d,edc51026,4519e6c6,7868b06f,cc917942,a5e2eeea,ac09b00e,affa7f6b,7abe386a,241de5a4,7a7c43a3,85afa7ed) -,S(f61b7ed3,1e16c456,c3851a68,e10f614a,1fa547c6,456e57ef,3c1f8ee4,dfd6e72c,cb26d0b7,fc401865,91f5fbdb,4d17bfa6,a0c5a811,4d099a54,734a3280,5f622f2b) -,S(f8e4d462,889700c4,b52859f9,e766fbe6,55976866,a22207fc,aee56185,15f678b2,30bb039f,c1b16fb0,aa09c271,bfbb76b1,6791e95,9dd51ae,6f01aa4e,bac77554) -,S(89cafc1a,5d25915,b2f6f71,71814a2f,d5d97a06,a717a91c,a392909d,332ab653,1a24a0ab,b4e4858,d29c0055,714f34e1,5eac02da,60e87ce1,6fe2f144,257ab76e) -,S(d285370b,d04f5dcf,caa01dca,7a2ad510,33c5b555,6aea60bb,4a48d97d,477c4f20,d4b427b7,32e885d0,13a2adf8,ec705145,c61386b2,c6981b41,6c44d202,4693b9d4) -,S(3c532f2,d9bdbfb3,219dc90d,17aba269,fd335066,e1fd4974,9026f66a,4df217c0,86fd5e7c,a6c97fd0,2c33c7b4,28413977,2791a6f9,f8c80576,75b3e306,66ac5d59) -,S(24d1950b,fc35706a,21b17a16,53037226,2984453e,37e26924,b730314c,cc8ac1ee,4d22a45d,6a31a90,bb247c68,59ae9a75,b05bb9e0,8b57ded8,4b9c1ea9,c9f918ac) -,S(cc6ab0f3,6227b1ab,149f8ace,ea036fc2,d8505341,ab67d44,59582b36,4e7615a9,f9ad93cc,40b1258,67c806b1,20fa6f21,bac918af,54a0f7d7,107680a3,83761cb8) -,S(de24a954,f36e94b6,ca816bcf,f730b99d,6320f20d,9b141cde,f08ff71b,25318cf,3e34b1d9,1ac24a49,b982d235,44afd62f,8475c35e,a48394d9,67904a41,db899933) -,S(77ab04c3,4900aba9,d83a12c,7953cfbd,5f8243db,48fab618,f83ff252,5a1ffec7,6265ac27,3bcd77ff,496265af,75a8db31,231c871a,30a32bd,ae873efe,bcac2f00) -,S(a47af706,5f4699e5,e0079885,d19580a2,51ff8dee,1dab741e,ce84ad51,16e78209,393cbbfd,f1b1f78b,a563f7cb,3465ab97,5b786088,3daffabf,bb8f34b9,7a257440) -,S(a9f5f9fd,c55c7b7,4dd170fb,d0322026,93d709e1,d52a37ea,8a545e9e,9cd7016d,98717925,4badf22e,8fd847b2,e9e80ab2,54f0d327,f6b6162b,8734b105,f1d5e0e1) -,S(d57e9ebc,96b938a2,8fa200c4,e586e7e1,ba866864,a947b71,6cc7cd63,4e18ec38,9aa0d2ef,68239110,5b4c8b7c,b412df87,25de16ea,f28596a3,62a6aac,d1b6bd36) -,S(7463a8d8,fb4dc14d,5618e66c,aa85d73a,e27ccc1c,ab820611,9f506829,faa58e9,82fd6ab2,275af504,aa0645a2,8438db86,ae7990c4,b4c389f,569aad0,68d4829f) -,S(2e7a708a,29c44831,9a02d03e,4eb331b1,3927ae64,534db2fc,a3c6e7cf,d53bf412,84f3f199,73500cdc,aeae0073,f39b3b2b,ebdf6824,ec018160,fd2e3b3d,4b1e11d1) -,S(8707b0bf,540bc058,faf2f3c2,e8ba304e,180d094b,b7fa8dda,414d30c4,d9dd5e03,70b61175,fb791033,50c6bd25,aa0594d7,18db5ee9,9667c25d,fbb49c20,f100b915) -,S(3fdb370c,3ce6cd02,886070a7,28e66749,22f67dce,1b6c08b9,613aa2d6,53ca842d,163518f2,474a0344,a5c4c5ec,10b1efef,5d3a5ef9,94010063,17a486b0,c8e0dafc) -,S(c37da302,412cd549,a01411e7,6f58d4b,33077960,94b31af,2a283d89,48472f62,aa08f287,16c642f4,8702d1da,aa0a82bd,ca849000,b8ad1d26,801c6fe1,3a21f92a) -,S(3eba0550,381ab0f9,251f923b,5c7a339,60ade9ec,2b0b47cf,25726fc7,a5e08a1c,1427b0eb,b681dd3a,88639652,5afc4e00,492a1ad9,a0c5a396,55741a5f,cf0fa7d9) -,S(96723ea1,8ce5d5d4,bf64628f,7754fa0e,e43f20a7,85356e01,94eaf8e6,bb50cee8,5ad09fbb,b9bbbf10,e86eef51,2d448aed,6cf51b5b,b28c8e8a,713066a5,81f49bdd) -,S(d7645211,7ecfb6cd,3a09d346,55d5c58,ab822892,67910f13,29f8d604,a3663748,ab7cc104,d20fde08,2c889dbe,2baaa9cf,bf2c9b10,c225da46,eebb8031,c28540f7) -,S(1f6b23dc,7e0ab136,20d907af,ad4bc944,8c866065,b4ac7e43,4dca8906,d0ada5e6,8c37b25d,6bc639da,ad092040,5daa9eb1,56041440,e48f6602,398ec256,763e247c) -,S(46ff04bb,aa06a168,79479e64,bc0e8ed7,6abb5a12,8afd1f9d,9bd80d50,75459945,b1104ec2,6af2ba0e,39133bb9,e47a61ab,e7e9d229,41d71764,91ef9da4,f51bcd4a) -,S(ca1b3c25,38888069,3b076e54,58bb0451,3bcdffb3,d824af86,f3f4a883,2a597ce2,f02916fb,dd1b6dc4,76109d11,bd9e81ed,dfc9d6f5,79847622,51bfe2,a1e0285a) -,S(c961e9a,adb69ec4,8efec7fe,dcdbdfb0,5fad1277,2b801763,ee747a10,99ece6b4,469a6c33,e0b253e5,270bb70a,d16c4b70,56bb9b3c,35f0a2a9,84e2f269,9d8fb6e4) -,S(3a2ea279,1418cc94,d3f81708,9d44e777,7b3132f5,b9b67393,ea4f28bf,939d99dc,15805143,c035d921,be217dc7,18d13e2e,b981bf8e,6525f88,31a96c65,6bf164be) -,S(416dcdf,b3a1f0be,1a3fd6ad,52fb1c03,4e24d48c,cf34d189,e7dedea6,b65a7a4a,76909ec2,bbc93359,ac177781,2132db31,47e90a0a,3c6ca35b,ebadd113,60c204c3) -,S(b397c245,9aefc175,8ba5177,2d4b3ed3,2ed9d1c4,85d2a2b1,7318545b,93c63eb3,a106a360,30763676,ab418ffc,692043ee,22813574,e3117a7e,4471ccb6,f5e71748) -,S(75c5589b,efd61646,329dbb75,5e809b2a,c1bdb8c0,d29a3065,32ef3909,d40637df,26f3e1e5,1492105c,90ea19dd,81fce6bb,95e60295,a1fe347d,cba27adf,a3e6f631) -,S(2eeecd12,a3517432,17d5158c,439a9046,e4b0dc80,119e58b6,620e6f08,969135a5,e1deebd0,48c58ed3,1b53d753,9c4c5791,13606467,14147707,806f491d,2daaba4c) -,S(a981f091,5d39d650,66b1d52e,5addda67,8cab860a,c75ac124,aa100593,9cbe65d1,4cb09fcb,7ab60293,2d98b23c,96e5109,88d4f149,4f334e7b,66c60040,7d3ed069) -,S(1a19fae3,a7e81d02,a1260c9,a759e79e,545cd869,2666b31a,9aa4c0a0,9bd4ef62,2807d657,8af25c69,e29bf7bf,d877dc7b,79714df0,68ae0707,89c5b72a,b0937902) -,S(cff8696c,1ee7d196,d76f139,2662e776,9b0f4314,99d30567,1952813d,2420c61a,8497e013,8a399690,25c04b1a,136bb816,3581f122,b62b70c1,47fc52c5,e6d16df8) -,S(6817a420,4a8b3479,caaa9582,4d48eb04,9669115a,9e5a5cd6,6cc905e2,1e27ce8c,9585468b,c3377a5c,98725465,35c8385e,8182a0c2,763226fd,95e72937,7b3052ad) -,S(9ceffc84,6e0ecc26,af13eb99,579478f3,7d114b19,59253233,bcd33d6c,8dd9d58e,e01aca1a,5cf8fa1b,67c4d4a,fef1c7ec,51060234,3ea64426,856d0aa8,fa5d2582) -,S(6a6e1dc6,f203f7fd,d9796589,2301e5fb,995a3731,8c410543,835f0edc,d3456c49,2a072b98,98b93e9e,b05f9ad8,6a97546d,83b579bf,6efd3482,f93baca1,3784496b) -,S(7e7bae1a,588d761b,5158b4f0,fb9186e8,8ba3a521,89ac36d2,4dd31d7c,d2a9129b,5198f63b,37995cc7,289e60e5,7d0f8738,17e6bbbc,d40d29d,cc4856fa,ab3dbdd6) -,S(13fc3a8,63deab2b,ed54966f,fa85e553,ffa15863,ee12f9f8,5dc5b35,6bd253,e31c3245,91275056,ffca59e7,6e76a957,a8b77c82,702e5d58,b3b5b577,73821459) -,S(ffe28deb,3f39d917,f6b6dbed,ae89ea4b,e5650326,d148ccb,becbc6d1,16e9c167,8d8a52b3,b878444d,e5385760,4e02b3fd,383c4be1,128c5b2c,262aaed6,9dbb988a) -,S(28ed423,9bf26de7,d0379a88,30fa0ecc,481c4354,1dcbc3cd,44483b0f,5cc57be,192122e2,ea018e67,4520d860,b4b8d859,2d560872,19bd0ac3,7bc0405b,10ce126e) -,S(7bf3827c,7be8c484,52acc00,eee769da,5aa4ca38,2f806d72,76c72c8b,bf8a708,925f3eee,e505529b,45c601fa,1d71d706,24a75d07,1ad29172,6bb243e8,a559eebe) -,S(cf1a7e99,21a01c3,f8ede862,71f7b6bd,2acb5aab,330a17a4,a7be1380,6fce7000,21365a83,7b3ba611,16a3e740,33a3463,5f1e70a3,f38a878a,7c3a155d,59d3d673) -,S(e779ea37,d1517cc4,e36c812,1bd0a986,af3bdd67,52626944,afcbcae9,11bb29c7,32c635ac,4b19775a,a04e2c6c,29c6f42,6472bb6d,45c1bf81,e8ac8015,d78a8a2f) -,S(10309d2b,76b54210,1599785d,6c381d52,f9697728,8e0182a1,638b7f68,f26c2a92,21edf83,4c859870,efb9b37,7f931316,f3abceac,c19b6a1a,438d020,658265a9) -,S(79927b09,701e46d4,2eb2240d,e9132036,f2b6b311,a7140701,813e721a,533a27f9,fb7c6513,a81886c1,a4c75640,36136104,8a0f47ee,b8d2b905,3b3d84ed,3b58920f) -,S(743b4e33,77da3429,9f593e68,3ce24e3f,85b1de0,4a3dd37e,fdd8c73,1528849e,37900069,b5ee63ec,7b3f178c,aae73281,fbba7de6,849e14f1,8164d6b6,742f3216) -,S(d73cd2e1,ce1bb7f,1aacd9b4,9951fe6a,e46064fb,a73acbf,49868605,c4f04da,e6a762e4,4cc6e71f,f5887fcd,6a33ff1c,cae7f84e,2f22a096,14b7f4ad,b253dde8) -,S(3e1c00d3,f563246b,3ff318a1,77b3ebf1,ba632481,47c073e8,ed32d697,95f6fa68,df2b60cf,87d5c129,1036aecb,80e381d,18ce2e00,c23fcef6,b4a72f0d,2d0776d3) -,S(96e07f90,92da1653,e5cf10e6,87526db4,ed90c2e4,c629b221,a32fdc6c,d968053c,d65c1c3b,b8a2ea6b,9ee20ea5,bfad3b9a,1f8517fe,2e5e3616,4ab20787,4dc2bd66) -,S(6d230440,26b1ee02,531cc124,b2e0796a,d27a7652,33862854,d8e177aa,afe1debb,f3a8f995,faa14689,50fbde47,1e4ec008,e3dc6228,a8cfd2c2,5983bc09,ed79bbd3) -,S(8dda9f5c,1f949dc0,314e43c4,9e716138,ad7d4511,a4b06d9d,c76fcef1,e5707781,d0563faa,7585b0a5,12b674f5,db737435,ad9d9bef,ae5ba77,5c78a582,6801310d) -,S(5070613f,98667363,f5eda369,fffda417,b4bf17fa,b4c276c4,e5aa357b,bbde97cd,b20eff,4fe77ea3,4185751f,9b16db86,eb40e47e,486a4817,8a0cf09b,dc34ebc2) -,S(3a4a70f0,bfab1456,b9b8838e,ac1aa188,4986d74,6a9b3a8e,fc792eb0,af16bce7,e4524a93,19168eda,a1832980,c04e8423,843b3e89,82381e24,8bdf5a3c,adc4f3e5) -,S(2cdcf892,183159a9,da9a82f5,4630773e,db5fba99,3bcdda38,b5291230,aab33532,c88ea6ea,c9113f32,85e299e7,42abce8d,fd95692,32292044,e0a35870,757677b9) -,S(1a85928d,f8f15f61,12e0cd6,f33199ea,2b7fed02,98c203d,781a2dde,28955c99,1b3986b2,821c76a3,fe13a6b0,30725c29,534a124,51ebe945,5682ce39,74db4299) -,S(86d14da1,d6b03065,a1520663,41b9f010,dde01966,3e622c1a,6b66b84f,1da1d388,679514ec,764f5cc9,e884a6f9,f38042cd,cfe5683e,1f6e5055,fd1380c2,8399b2de) -,S(e41f754f,bdfc879,43334341,5a5078e3,30045999,7c245441,565d0357,16201cc2,dd059641,c21d191e,dfef119f,492ee9b4,743f5e0,bb3cee47,dcbb0fdd,790e8e8e) -,S(b7ec9268,45b5bec4,79668d8f,4e444643,2946e17a,8338e2fc,756996d3,4475cae4,ab4a18b,b7539e90,10e210f5,779476b4,d945e350,978ec2cb,7cc62e71,4fdda53b) -,S(240fd9dc,f1eade19,1662554a,a25850b,bf3ecfbc,83249d4,56b769d4,b7518912,af03fa5e,e0ba3908,853a3a62,eaa6a804,5318a897,31352207,76a06b08,d104515b) -,S(353c4ec,ee7d3114,979e39d2,88cc3faa,2b88aadf,8f1cc129,a5c57237,875bb769,9fa7ec40,90af4e12,e940118b,ad70ab8e,28e607b8,5ae33cf0,2a0da4fc,d12d147e) -,S(f4eed58a,a8556688,11606ae1,1628fd1b,89340988,cbe0482d,39e80376,2bd933de,4278cf64,fe74e070,d071969c,a8ceb40d,18b40bfa,52d7feb9,1606f0f8,df3b3d44) -,S(698ffae2,e2d02660,434c17d5,b5552d4,b284f0a,736bc0fa,1a1290e,266ef1ce,1966cc8d,7845b74,1da7e53a,496fc12f,8bd50cff,b0bd143f,ab608198,e1ffc970) -,S(b53b596d,5c88c140,d6e0587d,417c8945,22d884a0,4fb596b,5957121a,65314098,ddff60b9,9befe76,c87de485,76c32eec,25deeb70,4cc19a56,77197ae8,8f2c745a) -,S(97604b21,d4393bf9,d6e4cba6,7e9f2768,79151865,9f626d65,52712fb7,1a13066a,e7aef384,e1cf7f7c,65c5b0d1,7357f266,7d871c54,fa027616,36062623,4a8d17f8) -,S(7a35c9ba,6edaee60,312b234c,1062f7bd,3b38760e,da1d47ed,b63484e9,51bb8623,33897a7b,a4546761,6ae92b58,6ef704a0,769f3a57,86ef8245,7ebd6a42,4d84a5b1) -,S(86d40c75,f989115d,ca26e0cc,9263010e,c9638b17,86707e01,b6a20d95,d1e2804,759bd762,4ffd8c1e,e71dcc8,a846b5c9,dddf2842,c4170410,c0f38742,ec315ca3) -,S(603bff47,9a4bb79f,663ddea4,93b90e5d,fc77f6e9,b2a401ce,3e8deb31,609badb7,62879fc,65281aaa,6aeeefff,cd33a02f,358c86dd,dc03720e,e1e23998,9da4f4b4) -,S(5c8b8f3,c7dc7a7d,721e0bbf,8a75a36c,fa13ebdc,14987d7b,5dee68b1,32203ed,6b601f38,2bc4c6bd,7d9d304d,88fcd6e5,3faa43ca,141bd90c,e7749340,ce08e7d3) -,S(313c1ec5,a91694c2,41e7a55f,f83b7378,25a6f27e,90090505,a7963ce8,7544fb05,9c3153ff,9a4365fa,fb644699,bc4462c5,1ed858e,24752e59,82566037,103c6384) -,S(51aca51,4616aefb,30268cb2,968e0fa0,150b4bd5,a79746bf,98b01543,a9d923bd,7c51f9b4,73a7747,bfd63ca4,f4e2b361,a0a66ec4,31df41cc,203457a7,4ee028b4) -,S(4ae8d399,27ea0648,4936d3f9,2bbe97a9,353071d6,7743ca12,2ab7b6c3,2619677d,f9dc519b,c251bce8,38ea332b,9110538,f350f5e,4352e7c9,19e677d4,3c8a47a3) -,S(6bd1c95d,3f9cb5a0,8c1a054a,884d4bbf,b100c289,c4af257b,aa0784de,a256dcca,7936283b,de39b12f,6f71fc40,1b07de78,80192357,a8887e71,39654ef8,6b803b5b) -,S(e2278a29,4642caad,ae370a62,e07fbbcb,5737f700,9ef9e8ce,19bdd283,aa49480e,43122fcd,f3943ce7,35b570b7,ed82f61d,87bc8b5,83d64f77,b36f143b,4837dd01) -,S(68537cd5,9f9469fd,d104bb01,93335830,8d24fb2c,b22471f,feef4ac4,fe96c644,765360ef,41107a51,dbf99ff3,26e3b19c,4003ab45,979de4a7,32063c81,8400050e) -,S(5ec9ffc6,69c99f9f,8f8a0735,fc088824,70be08ef,3f81bb54,b1290a07,765af330,abb54008,e76f8716,78c3229,56b47c0,1f4f1cdc,dd1cbb38,1a421397,1163b222) -,S(4e00188e,5d4930fb,a9471aba,465154a1,1a330f6,15cae31d,b2399874,704dfae9,7e76f30,282436aa,73f656dd,35b40209,5ed3fe29,d2086bba,57fbb81d,4d317868) -,S(4ae347a4,d480152e,ffd39ede,b4c2f3fb,a2659ce4,bd3b6e3c,8aaddfd5,f15ed984,383e2f46,d44cfdf,4fab8ba7,ba72c635,65bb6ac1,f35c7307,ca2c5c3,62d4e523) -,S(32cade24,a8d3ac0e,f96d90fc,86509a5e,35fd09c4,d8f7719c,603ce1b8,9c6665ef,87273873,5c63b137,5b63c5aa,6ca89f9a,266939f2,e0c936af,55c10d0a,fb8bea36) -,S(8e4ef195,60147576,6ace6891,f87c22f,20c703c3,d4f7204f,5f422444,51cfcbee,2fa72e3,89d97c1b,79eda0af,c00fbcfe,cd5b9d0c,c949c666,459706e,6ed47af) -,S(35fd575c,4adc03f6,c4d54991,18607a01,559d7316,9efc2509,aae7e7ff,a4a2c30a,f9a5779d,274881e7,cb700926,dcd10ac7,dbf3eecd,9c948aa1,3474add1,ca48e000) -,S(932e4c50,7fd02595,148929a5,2c4126c7,efc12f5f,5f5db287,3c635fed,c90a9cf6,ce6bca21,bbaca19c,29f6b1b2,4d1982c0,9e84effb,cdbf1f28,75f61ef9,ba8ba783) -,S(cad8de44,22a051c1,be36a37f,2f459707,55d3e2ad,35debfb2,11a45d73,49fbea11,48b0df1d,4f6669f2,80a41c90,34f86f11,308eebd7,8a9fd3e0,53323a66,f01c347a) -,S(9fc7d304,c847fae7,d016aa64,6cb36383,1919ffc8,fceb757b,462fbe90,6c9594d6,dd17c0e1,3bc6a187,cda9dd38,a7afdca4,1963676c,e4d4bc9e,516e3a45,d9860ff) -,S(41ba6cdf,10d4a05d,c6865453,894debb8,8300e4f7,4c17c0b4,c8935761,988b5849,7eb62b15,8c3f0965,e571e278,b2833321,ece57e84,cf153ac5,9309841f,e47ad4c5) -,S(1ff9fe5a,aef36ae6,a2d74248,cefb8693,d5bbf30d,f057e884,b227ba44,11c7377b,6ba24b6c,585c0038,49c9cf41,fcb55f09,50690850,5be64692,16520575,f1e74278) -,S(299d7c44,d706d29,e6d9d070,4856c272,6d134814,1f8f7ebd,893f38c6,cbf5d660,e4a74f3,4d0374e0,ca9b4887,76de9acc,62f7d1ff,9b494040,fc85eea,2d03ff32) -,S(a0333ed9,ec1c987,6e318ceb,83d6e93a,b607c2d,cea512d6,9f7b2bfd,72e3a67d,da7dd365,5f51769d,35b37393,21fe7b50,19f83e3b,b6b8941e,d685919,fba0539e) -,S(5a4412a2,2e52a330,534093d0,ba96865f,2821cf01,564ea0d2,e75b84fa,404251e0,6a4788e0,7e6c570e,8390bc0a,b06d293b,3675ab27,54eb700c,7cd4078d,8f0e4313) -,S(d772ec4c,3b141dc6,e534ea6,a69f9b65,783351d,c2fe7cdc,3e823cf6,32b7b0b5,bd93400d,1036487e,7090979d,ddab3821,c9ccd92f,db89bcfd,da929be6,689ac0df) -,S(949782d2,c7694c3b,ffb3e1cd,6e40f807,d4452fa4,eca1321c,d04a2367,6df89336,e7c5e67f,b8ba22b5,4372e5db,bcd63c55,9f4e2c14,c97bc930,b68d459c,bad436dc) -,S(7ee7d5f5,75e6f59f,3e0a9e4d,4c49c71f,6d9ca0c8,6177470e,2334f616,a457e6de,4462da9c,76123e66,c9074add,76fa310a,9cbbbe02,d6a07d01,97e732ee,d7d9f3ee) -,S(7a4b630a,e08d47b5,b785ba7c,15417951,8a554847,bb8320b,50faebb7,b13f843e,ca24e44f,b86801e9,7163a524,db4980de,69a3b219,7f9e5dc,6b5d7076,9d937c00) -,S(d2d90a42,428ac40a,40aa5503,2bb623c1,3a18eef3,2994f793,9c31c6cb,1aa82b96,75852e33,2367d59f,30039e06,40b1e0e1,394a3b6e,582dfb66,7464d5a3,f234972a) -,S(d92499ab,6206dfb3,da1b5606,62ed4f2f,a4809b5c,48349b91,340e0b16,e95d13e0,423544ed,26a4fe1a,8f940074,993aba60,fa4dfc64,be002941,11f29b2a,b271be38) -,S(ec0c1ec2,58875e66,d24e2d31,5b7ff87a,bba6f2be,6c6bf4dc,8d5830f5,c5d09a23,e526a7f1,648abd18,1c49a237,e608bf79,8b798c98,75804d7a,ee8ba416,28591421) -,S(69380968,835b5989,885b4805,290ea050,3a6ae508,17798c2e,f30e1009,6bba8863,71bea39d,80f0ba63,45297137,a14d07c7,7522df75,8192f345,a6170f5e,2f11e5f4) -,S(d66b1da1,9fd1637e,44cfe8d2,e1ff2fed,15a40a5d,f596c62b,ebbadc8d,fca9ab23,68cf64eb,bd2b4bb7,1ca17c4e,607b3315,5cc5d91d,26583b68,78a69476,586b9946) -,S(9dd98ca2,c6fa62cb,92750d70,c9931641,5036475c,a6b59695,a510dc88,3298c95f,55a88bb8,53b99cd6,f8d278b7,e63b31db,40750905,d98ffc81,87a0e07d,acfbe821) -,S(1b66bc2c,842cf1bb,ea4ecccd,c1e2d71,4efd848c,db7a9b92,5b9a9ade,d141bfa2,fe0b4701,55fe82b8,af43d88b,68423cb6,402b3501,8831ca89,ddb9a70,83673bea) -,S(b280dc4,8a9231de,d396a61c,2922e003,c7d2d5c9,f0e8312,c1c075ca,c8eb688a,81b745a6,a2f8be66,b32cb3ad,62babaf0,498c8261,531cfff7,da9ce306,d2738a74) -,S(7bc5951c,9eb3ba1c,828125ad,510e2e92,413e906c,f015680f,8cf1cdc5,f18a6b5d,41b905d8,480ba8bd,b8a6fc7f,49adc6d4,fbda2f0,ee229a1c,d43af5a6,98352a07) -,S(69ff74d1,2318548d,76a53095,25ca8695,11647908,dc4f2ea3,4ed2c53b,f6eabfc1,f3a3e628,8eb99f78,12eaca1e,b3adf5fd,1d617397,dcc95bde,d4be775,afde2419) -,S(5fe6dd3f,1f6d3a5,9fa8f8cd,de7f689a,ffa46098,aa0f03b9,2c552e1a,c84af209,9eeae901,acb8d022,4ed197a9,15510eaf,f356cc16,274a1aac,d6dbc74f,60dbfb55) -,S(469e9122,cb0475db,7469fafe,9c53f911,d3b52bc7,8cce23b1,21d22e59,c505f5f0,fe7487a8,38b2ba6b,f5a5825f,a4d22c26,80d8a580,9db637e,cb84e2fc,1058d812) -,S(1f4a3ebf,6b62923,b2df816e,8b30f8e4,72a5e718,70c1cc1c,6d63b4d,9160e6ab,98da1295,7602ae19,89938bd4,298a67d,1ebeebde,88706d39,b77c6a61,4dc89e2f) -,S(d8ea95fe,1c12ff0c,cec226ac,26f510a0,4117222d,d0fa4773,c2f78ebd,53b86b0f,155bef9e,dde6f293,b88bebb3,ce92c249,f154b59b,a01d7f5b,25fef472,8c6288d9) -,S(1ad8a3c7,97b38071,2214b2cf,87045300,2bb36f5d,dc7f2527,1797bd4f,1227cac6,680a77aa,3755237f,15418957,6fcf51ed,58398c5d,4d56a1c,cfa3c05f,4857814c) -,S(ffea7104,5d1d26e,d942646,9f0b0f88,355540b2,c32aa92a,3fdec318,24fa7d66,eca244e2,2d8da06c,44ec8db7,5702edd4,81f67af,2ca64ed4,cb5d04c2,2434eac8) -,S(4ac55ba3,f7fc8898,54a141c8,cfd6f675,d3abe9ba,55d90f3f,c1764ac8,b959d8ab,9c7b2b91,f135fb7b,fd252d14,118b104b,714821b4,1bd879ce,15bbc93b,f8be2bd2) -,S(5f814467,7aa9a4ce,f29de0eb,865b8a02,bc7061a9,ca525536,fe27af50,bb718ac4,bda965dc,4062b26f,e6434071,6301fb02,2b8cb894,73e39b36,69acf101,90d9c042) -,S(f372cb04,37917498,4b29f213,5981f32,da5f96a4,d1acb903,88beb154,75dd88bb,82d68f5c,1e62d500,1a0a0ea0,7694194c,7ceda2ec,e32c4efc,b2a0ab46,1a367d89) -,S(fb12bc5,45760478,36313375,3fbfa4b2,878ec6f2,243e2692,7a3c5320,bb59b128,3f820118,67dae1b5,bb5ac0cb,a24ca681,96193077,fd7bfe17,a926be5c,4953aef5) -,S(3d9759ac,918a4a34,f4307560,17a9747f,4adafea1,b0a92447,316ff819,60c0ea07,cd9dbcf,6d6a330a,b671d5dd,aa96497c,caa317a6,77bebecc,6fca559a,56018aaa) -,S(eae0aab3,699c521c,3fb49be4,669bc7dd,9f476fdf,58e42909,84455c82,fe3e00ce,badce8dd,450ee7c2,99b77b56,25e808a3,62c7ef1e,11e30bdd,9777fae1,4f17259e) -,S(fed252ee,c2c0ceaa,57625d0e,925ee5d3,43718a7d,24ca3384,55e0abed,451eb851,66bbb6ae,56ceefcc,21d66b27,70756f64,dd07211c,5cf0bb4c,457a5a8a,e82c648f) -,S(da639ebd,22ac3c1,417fb04d,3bab0b22,2362af2f,9d3013c9,bc08793a,2d7f9dbd,83f27620,55f1e9f2,fa74ed0d,536bbe54,3627aaea,3e7a031c,10aa7b4e,822466d5) -,S(524d24de,d77345af,4d4d3ac6,7c71df91,32ced2a6,acae682c,e097cfc2,7eab90dd,e4cf5cf7,c6927c5c,31b6f55c,90fe7cff,2d010a00,887b3b01,b2f7a074,fab7f5c2) -,S(7dac2ed5,fb52b60c,35c7cde0,c28617b4,28672da4,5fbc21c4,b24c5268,54ae4f94,cc6acc7a,e9168866,70b5c4a2,bd2466c2,f6cc11b6,d282b09e,a578ee0f,e7794038) -,S(5f46b64d,da61f59f,6b99d10d,e9291a,887e5d9c,a3893ea6,f7c51cbe,e56083ae,6043d055,da252655,506dcfb9,c5572929,9bfa6ba,7e1b582e,5ee1f3d9,e283a8ae) -,S(8863ec33,b6a25f21,6e641ec2,b8c5df0f,48ef0fc2,38a7f635,175961a1,7de14aa3,9d6618f3,1e52581c,2f829277,7490655b,45b2a583,da0ff7a1,17dcb12b,eb42541) -,S(85403446,3ac459ce,6d8184c7,ef26f91f,b377f3f7,3e92ea03,a1bd6a68,33a2f9f4,2d1f1296,8ac56499,b252a5b1,8313fe35,8f7719f2,3b0c9430,438f7278,c5b399cb) -,S(bf6b3f6,217e412b,fe651dbc,362266b4,6a325d27,5eb7f201,379cadd6,5e223c7f,a1160954,c14aa455,fb041e7d,ceee3ded,ebfad90d,6af1beaf,a9b1aef,97ba748b) -,S(4b20202d,3c186135,4aa079ea,409aa4cf,860ca219,8ba1bffc,77124e5a,bed9e59d,9f684503,c107c0b0,ba5d858f,2f11d904,7703eb45,510602ba,b555e8a9,f5b8873) -,S(4087f880,6d679a4b,3a24f533,127b5931,99c050f2,627cbe28,2686a5aa,6421dd2,4838ad84,b3d9d488,33c8c883,698f5a59,69880041,589f921b,5a5707d2,bd88e8b9) -,S(15a79287,cb2e7406,a2db91e0,5a4fc34,53877504,c790eac7,66d9131a,fe97b79c,9f4ef322,76572e3,d3fce497,c2c6160f,1bd597cf,b96a83fa,df2a41a6,b94a238a) -,S(1c4fa063,c0524bc4,ff233d61,bcb3d40a,404fb10a,7e222812,2739b343,e3bcecbe,2a8561ec,a2d82eeb,97209e9e,bd730b2b,d39c90b2,bf4d0353,3aa8c73d,62d48bd6) -,S(a0708ba7,43c1b2c5,267936c1,85312f2a,bb50b8a6,d4886c26,56d163b5,adf2a636,958f45f1,916988cc,6c9b8155,12e1d2c,7dc66a62,359a4324,5845e94d,371a20ea) -,S(d7960b4d,f01a42e6,e109d71f,2e33ffd,9b79754,b129a858,c213793c,e8acad7d,8caf19aa,5a841d2b,61c3d0e1,dc65730a,33566193,63118707,d81c1e19,dbdeb920) -,S(7a03dc6b,f8ba70d5,96e25ba3,8fca1b32,a7c4506e,6e8a3789,daac3240,bf8ba611,70f19e22,292d6856,5a63e378,b773e170,48a3681,d096b881,fcb84a4f,7f7d9028) -,S(53a9a662,a8fa3411,c3989850,c6c83aa5,da516ca0,726fddba,c2f38f25,c7443b97,5deac250,6179c31b,f313279e,844d1e5e,2adcfdc5,b803036e,140ff59e,3945e25) -,S(86b946b6,3dbb0d86,ffe69af6,3c1bbaa9,b7ee99b2,876836f2,a450d9c,feb2cdf7,44407783,d3d0e2a6,cb18ea1b,a1e4f133,7cbc39c0,19997a62,ed74b598,f74b1fa) -,S(ce81cf5,cb884b46,f6956726,20d2423f,6b28c8ff,ba71d9ba,bef152e6,ef752d8e,75afd973,8120644c,349bf924,c04c1aaa,979177ff,2890c926,2d0b5404,5ea9248c) -,S(41106e41,3a464d2d,9f86cb9e,47d57d47,7b791d43,133a2b8f,bc6ce92d,e1172ed9,e2ca44c2,30e920b8,5601a2,773a0f88,2ce4e42a,7379b374,d2ec6fa1,f76741c6) -,S(e9c1f2a0,4e830a12,e546541e,c7ac6f6b,bca3f1ca,2052c152,4e141b4a,20b49777,51df3843,8dd12c2,29973fcd,516712c8,5ca73721,f5d50308,86b91f9b,32a58124) -,S(8bb9e12d,c5e8ff3e,4ba25775,f1552e3b,9be21f27,4250d511,fce5cf15,e73bbf2c,8a822b7a,273c3730,1c24fcf5,c19c4de,b4d0968a,bc23962f,91ef11a8,d00d1152) -,S(b0058ef1,da227791,e4694c3e,ef66e031,697f3f3e,297d139,9ad597a7,acb6bd0f,7f5bab4a,5793814,d8c0bee6,8ffe8025,e5deb644,7d2ba978,c805b2f0,be205a2a) -,S(1dedd42d,8df5fdd6,52e02b78,4dfcab0,6dfc3557,4b8725c8,db95368c,ac2522a5,3055a449,23730d25,18ff4a8f,983b61b8,24b918de,f357654f,5b46559e,b6bca540) -,S(761a5248,c6794ba9,3f45b0b5,12bc39db,e471813d,9d5c5f7d,a46f2ef4,380ea544,185ded30,c4f5ceac,5e18d0a3,95ba8ed6,9f703408,5fad1fc5,c60d10b0,832c1292) -,S(f1d5b60,e515d0cc,8dc20982,a13c1b5b,a1749687,501a4f2f,fefab898,e3aa5caf,55fd766c,395fd8c2,173a9e4,8eb63f07,ee6f9ab7,54994708,e42ed9cf,78a0d91d) -,S(569cb44c,9b7900aa,576ba0bf,61c4455a,fb09ff4b,c30242d7,fba993fd,bb37425f,dfdeb8d2,ff1ae3d4,1e78f646,ac7dda3d,c1131de8,e2566d0,d3340272,cc350b1) -,S(3e59b69a,d99839e8,51947a78,7d8f850b,9c2dda11,7dcd0776,d22c787c,ba1851eb,732cd2a4,8bfeb030,6bdd9358,37ec4f27,7050745e,b2c9f6d4,34cd8834,592e20b3) -,S(a46d6621,7b45682,98250240,3fc0886d,81acec57,32c3087b,e6ea4c4,95296967,140cccf4,29a5b062,24097a73,f9a8208d,46147884,e6127464,51acef,b9763d33) -,S(b920e59c,f25c53ba,7c00c427,d1575c9c,4ad70efe,daeb7927,74d16c46,5079ab1c,606160f1,d4ba888d,1d5435a6,1656b937,9201ec5f,37f585c9,d43197c1,f045b67f) -,S(12cf1ae1,e7d837b9,eafda1ef,db270db6,3b88b6d9,8d05c713,896e06b7,f8bfa8c5,e0d66613,181b934b,9f23d7b,e9cfd8b3,c4c1d66d,485075d9,1e8cca69,39c99c0f) -,S(6aad27ae,a4eaca2,e60620e5,a328154e,eb93a900,be13a302,87ff39d3,8dc0ec1f,932155c5,caa21539,e27e8cd2,dc57fd7a,d4681474,342c0811,2fe626bb,94a1f46a) -,S(134cd94e,7cb166be,82b48916,6c06c1b8,8d168bf9,21f75c36,ce9343ec,acf870a0,42a673c5,e956fd45,e82a51cf,ff09a399,2f7c8fe7,e73d14c0,fab88c3b,9453236) -,S(d5dcd58c,7b7cc786,8c42971f,a1c85cee,429b1d18,dca68e2c,56d9f5b5,5a3989ee,e0ca4130,ef1bcae4,ecda0529,7a338bc7,45bedd0a,f0bb75c5,e316624e,21208100) -,S(951d6534,c344908b,905fa4cd,b691f33b,3e3567bd,1538a861,f66ac9d0,e0d8c8e,eef35922,eb847928,6681a990,345255f6,95a5f691,9a7d79f9,d575f306,ed7046f1) -,S(cedba44b,25f7964d,76d84c9c,9b521156,690af0ba,966ede27,b33665cf,c1cdd0fc,806a9049,cb8e9af1,d187b6b6,493316b6,187e7124,91a8f7d9,4c21b79a,87c79e7e) -,S(4ff03660,d1306bee,29abd39d,32beca15,d1c7d2d1,14492a20,49c6f4aa,d8a10b54,c2c75e69,8fd89951,e36e8bc8,be71f689,4990f25d,d2ff1893,d99e2773,6d1e574) -,S(c08bd508,8dbd6465,e87b7702,dfb7200,c78061a2,683b9824,389042ce,ce2e0ca7,562019d6,1343497a,b1640884,23a9f171,1db329b6,8c63e78,41793255,f88d7307) -,S(48dfdcaa,6fd2ceb2,3b85cdd2,28bac318,955bdda8,274a1e3a,7afd5db,4bf9857d,2a46622e,896167ba,5154e76f,ce429554,af60f4b5,1431d171,d55ffa2,ea0287ce) -,S(40420900,d81af883,cbf76b47,17025382,802c1479,a33a3cee,bbfacff3,16a1f236,866044e0,dbbcb53b,308f50fa,2b54255c,7831e96e,f19e1b4b,e4168d1b,7b85e3f7) -,S(96a3747b,23b667c7,70ec2018,4e99208e,ec1e3142,3b1156f,8b12f37e,322bdc42,67b0b3c8,df8c4647,3310b04b,ad325d6f,dc7545f4,a4a07af7,98c7cd86,3cf22ab2) -,S(cf07017d,e4037969,24361f0c,b151484b,f1db3e91,a8d16784,5039132b,c8460182,b7a1b107,62f29e30,d0f6e762,f6940638,e2eb60c9,e65ad067,99b1bb39,3797939d) -,S(12b5b8b2,5b0bb6f7,ad1b90de,d75fdd5b,93507aa3,dd7276dc,805cf5a,218beb15,5d3d4767,8cefa19b,80ed6368,d40ca199,5a5bc165,b3609ae,e89b56ed,b78933da) -,S(879b449c,e866e6d9,3998b9ac,e18b6f19,77ecd299,bd9b727d,cd99c37a,13a46765,b0c480eb,758cfb12,acf50c4e,91a8d9e5,f0c45215,f03e6bae,c6c13a83,63781c63) -,S(2ec48783,e9d3a01d,d1fa401d,d3fef249,e502280c,cb36d21d,d2b7b90a,cc7dead,fb029124,78f9e2ca,1a5e6150,5eb469a2,83fd8f81,6798703,ca2f0c7e,85a67fce) -,S(79cca258,27bedb07,39fe8fcd,2145956a,5b7878fb,bd873a83,aee22093,437c3ce7,ff488a93,d82e8750,14cb7c48,3eb74b30,bee990b2,2c1915a8,d3381cea,9cac467e) -,S(c444a4ca,3d2b8b7a,826b9eed,40616aa6,8e146a80,d49a9cd9,3e93cdd5,5adbd207,4d1368a9,63d504c2,541ae338,1ded0684,ac00ad0f,b8fc3231,9d1fc273,92d0f18) -,S(3ee47c50,cc0e44b2,5864e205,835e8d6,dbed328a,60493c26,7ee5529b,cff3e7a8,fa555339,56ea87b,c3249640,145e243c,b6229a30,3d1b91f,84e1ca9e,90a5f095) -,S(e963c987,3036bb7f,422251a2,9f9b0f47,8e69e2d9,2d1920a8,1c012d7d,c809980c,ff95bb0,779bbf2f,1242bfa4,880b173e,140f92d6,c7f8e5e6,18027a3c,55c52fd6) -,S(aaf6075b,b6a1b8b9,afe4b747,a46fa394,23738e50,e686c8bd,3f711cc6,548fc07d,4cdb0aec,6d11ca1c,1e85bd16,2eb411ea,53ab326e,bbdf898b,1bbd5219,aaf2b0cb) -,S(691e4817,d8e9756d,8e174a18,d5d708aa,842b44d5,ea921298,6e4c7585,4157ac0f,9eaeba0b,3bfa7ad7,80d0eb15,72f92873,4bb9a8df,29f508c2,d1ff4076,a0c0c222) -,S(c3e6fdbb,45af4a48,941c9d4c,583dad8c,c77dbfb3,1caf3fd8,1d9e087f,e744996a,ca998d1e,65ab29b8,fee07bfd,1ac4e979,b869474,b5498a73,e642bc9,608366f2) -,S(edbd6320,a55d25cf,21f2630b,e7c5c996,923eadf8,333d386,8cec00b3,940701f,d65192e7,afcef5e4,c88cd12b,fe28f94a,5e3d3d50,f6b2c3e3,f7a14243,4de4889e) -,S(c959ed83,a80ae0b8,ac2fd249,43c37412,b29684ed,9d4d85da,d7cb4c34,ea95d336,80c1dabb,8dccf252,ad8b0e97,25970c1,4de5f58e,12f7e5f,8b59a2e1,a72b168b) -,S(778cc574,471004e9,d88c9022,4d2d5cfa,2c5bc6ed,da64a312,74e3df83,3eed9237,eea23d31,6b2a1c02,7b92e502,db921d9d,675720fe,51cc3609,46b2dc93,92916c17) -,S(a1f87438,8c3656af,43f299f8,1d98d2c0,173e7e46,d3fbed9a,5c2afc96,63b42055,10bc8443,820d6c5,b3150e79,b9936785,5d874afe,dc72a84e,abb987a7,d56f4afc) -,S(c8ad7f0b,2d5f8b8a,cd9a1839,c3d043ee,8f7fa583,7540f6a3,d002091f,68224a5d,3018b580,eebe5b9a,2d1507cf,18a7fe4a,2a1cd4b5,1157dec3,8e65f191,c7aebf8b) -,S(c25d5264,b93fd7b,b7e4e426,1ae767f7,1ecf3840,a2a7ad20,bea810db,4820055f,fa15c8c7,6e3f2b0f,a29fffbc,eb48ed32,bf331aec,3a147524,c349e8e2,465ad684) -,S(d0b972eb,7e4cbfad,baf224dc,cb2d873b,28316877,88b5f2f2,ccc62bf5,e978f92b,ef5d3ca1,606a5852,aafbcb4c,f23e787a,75610b31,8420bf56,e94e420d,f7ab8e3b) -,S(f8b44c83,58564479,6448791a,b98132b6,d393e851,bbc294ab,56c8042b,1b0a2d07,c28242bf,42040be,e9851362,fc8e764e,2dbe0c01,d5bb0ed0,b8e1edfe,e870a27c) -,S(e7cb8901,6f72aade,39410adc,12fd1234,5d942419,51a6d36,8acb7c83,da5666b7,de367522,46b6d9d7,efd4ee6c,53a1656f,f0c87e80,cb0f8f63,95341c35,d6b21697) -,S(8b2128f,14e3f4aa,92e89478,64c5eaf5,f40f93e4,95cce167,fb2c7424,c279d87f,e7ed384a,f469b4b1,1812068,a830303e,699926d5,b8304c11,cbeb0e49,cf5d246) -,S(f34db5db,3cbcd586,38b6a5f3,ab5b31f4,1f3f631d,785e8317,658408f5,93b4afb,dfce7372,bb2c8466,fa31a1c7,4ffc1ac4,5bf11263,4c98ef2d,56e30fd5,c3dd3d9) -,S(c3689e09,a445d685,daca48ea,bca533b9,10b4fee4,dd251c86,a965d5c2,ecaabdb8,7804d05a,6a263fbb,c33efbe4,f4075d1f,d62e187e,3a5917a1,55c1f22f,1679e3f4) -,S(7ff995ec,f776a10d,7a66d62,6095892f,f1e47d4a,2b47ca78,d708a0cb,3f005cbc,edcdc774,5f17e430,cdca4d11,56d08288,e3911d0,e92999f5,cd5c5eac,ca6ea90d) -,S(3662a262,62234bf9,69b18351,2423ebb5,db78bd6,1cfca8e4,1c0253ec,427d4d27,88a62042,f07e69c,f40f671,ccaca36b,d550ef9b,79b4999f,c41cabac,1c2e1b09) -,S(2c127c2e,6d9c42e,970e66ee,24a07388,b6b4ebe9,1614b951,1763b414,3f54e8d1,a4773eb8,dacbadfa,afa26c8f,f4adae30,856be023,6022d93a,aae59c9d,fdd6629) -,S(c420ffa6,116f161f,fd94863a,9fe30b7e,b7dfcb0b,8cf9acb3,7f6d6515,4ac17802,e6cc469c,25c68f6c,8499e9cf,95eda8c1,7fd76d97,2ee8fbc0,79b143b,e50a028c) -,S(77896743,220343dd,58c2f06f,d3217468,34d386a7,e7fc969b,50c77847,eae3de0d,4350d59e,4408dcd9,710bcd7d,629e92a8,cd906759,627921f8,57054a4d,21fd9369) -,S(cf7ea42c,1a14dcb4,3334f9b,636ff0f7,7147688f,19133c83,dc127139,349f5827,b9c02c80,166bf9dd,139c2846,895e4aa6,ad1a689,66460a29,f8e951dd,d99e6d9d) -,S(d1793439,ab1fabdd,ada8ab1b,33c9f96e,417b1c84,7f753630,9d815fa5,a673a91f,ac13d659,3b5941b2,3b19f6f7,f9a67d0f,b429add2,5a40d05f,9bc0d1cf,ced3b3e0) -,S(bb1568d6,727dde70,c52f5863,133dc9e,54722577,4a74026b,e9864f02,9e92b420,b5654756,268d74c6,cc6adf80,ceee29c0,9e137d2b,e15aafe7,b170c95,22af3992) -,S(732912d7,83e8a5a3,a7468177,231ba93f,ce07c42d,778dc205,35cdea7a,db877dcc,d34b8388,1b128d23,e68ffd7c,29c7a945,1664f5d3,fed3dbab,6f78c8e,77df80a2) -,S(c74f0f71,fb8532e8,2c3e1865,1684d3b7,4927b6dd,22504afa,9084688c,7297074c,9da5ea61,c0bd178e,8bfe5a92,dd040c6e,35984bd4,1102806a,53a9f1a7,bd006ac1) -,S(bd4fa939,8bda5a0c,5a4e9e49,43060d9b,1785a613,3c970aac,91fcbc68,9e3283b0,631d4fed,b6614b49,459be1ca,ccbac0d6,e79cfdbb,f14de95c,5d2a5cda,30e433a) -,S(9fa65462,733f13d3,2483e0c8,15cb6bd3,e9bc2d79,7b89ba72,f2465c64,a341cc8f,7051fc5b,afc5b18d,748ada32,c4a27151,443505fc,2f14f130,10fa02e2,6a12db04) -,S(eaea6f7d,ab3dbf1e,816434a9,ddbe53bf,715168fe,2c1ebd4a,6cd40744,c35e31aa,b96962c2,4f202b96,c2080619,ff4ba905,a594b9b0,1f709e6a,76a1a7ab,9784d61d) -,S(b3df7ab6,3b947504,f33e6d5b,7b8e2553,9a117c8a,497f8751,6b97bfc5,3b17a2fc,72df7500,a35ae6ce,d6fa6265,1a759dd,f11f00ea,9152a5b5,ec51bbc4,9d758b9b) -,S(ef875ecc,46da48ae,45619be9,950e294f,4341df09,726417fa,3a8d1ac6,c3281bbf,7ab9e204,af4c05b6,d6d0eb6e,8306c987,51ced2c2,b9e8dbc2,8a642bb3,7f1c72f5) -,S(74c3c446,576a8a3a,5082f234,afca508b,3d748757,4cbf14e7,fc26f36c,70024fdc,73d57916,4ddb6fa8,72dd2afb,f9d8a307,b6ccac9c,94a4eae8,8c4fe8e1,dc136506) -,S(959c4b2c,409f2e3e,6c020493,33ba2f18,c06b7182,5a664e1a,cf33846d,cf39274,17cab35c,7401629f,b73cd398,dc5bedd,d319919f,1a3995d9,45f42f68,2c9aad47) -,S(404f0dd6,94195313,1953b53c,67fdfab7,f67c24bc,92fb4d69,a9479a9b,6c9175fb,857c75e7,f40a48d3,ab156085,1d42b037,7e7d3e79,86efd570,147917bd,f24d87b3) -,S(3e040511,233b0f5a,53df4d5a,b0854137,2db4ecef,170b566,807c4923,6ce82075,f9337271,dd443843,77a35ebf,56753b22,1fda08e0,1b790e02,b9603827,600df3d3) -,S(942ea853,10dfdc3e,1f7993e7,47bdac04,ecc8692b,94847bd3,e044cdf2,2cd77e6e,bbf2f7c8,e688b6e9,b4510bbe,58c41b1d,f33e9afa,5428ce51,e02e624b,9ea155e5) -,S(1e577a74,9883a5fb,85593809,7d0180a1,dce21791,e10b2c0a,3fe6cea1,cd03b532,a147662f,856f5e15,dba53000,7278e878,7b575612,d5dcd790,19417ec3,ac41c003) -,S(ebc9d95a,8a237b64,212e9dfa,607fe4a3,7a05fbfe,7c5594c8,ae472c4f,6ffeaa5a,39406dc0,e311a47c,cf15fb45,8f8b48d3,8fec2fd8,6b4afc05,b1747957,e7f1162a) -,S(c78eaf60,1afdfc20,2123d228,8496189,b9081637,1fb2c475,2773faf0,63cac063,95325b1,e0c22dc5,df6e84c5,16d396f9,bacb42cf,6c1fe9c7,6df83b3f,3eb42de7) -,S(b5918719,a1d504d2,b44a3d0e,117c2798,4f2e536a,3571db8,752685cf,df6d34a0,9b01e8cb,585cb7c8,fa29828a,ac899050,16beacb2,5e62ea35,6d54e9a6,18184abe) -,S(8706a73e,b59fc9d1,92907dfd,cc6f75b6,454f1045,4a5e9584,bdac978e,8e0042cd,8b1b5f56,6f1f78d6,f528405a,2b6a87e8,4265e2dd,1e34c1ce,7109286d,5bdc3a49) -,S(93e9256e,4ddb4bfb,6f4a9289,6e2ad04,793e5642,3a22230a,e645529d,712d6ca,83b242db,d9b3dfec,3640ea62,f0e3989b,d874f247,90a75cd6,9756a8ed,6eafdcea) -,S(2dad49af,8702f39b,cb353956,a1d5601b,a24fffbf,58ab527f,e9ac6ff9,ea2ac295,b5af68b8,e6040762,55c0704e,2cace8c0,ed403611,40dc02fe,2773a625,27e4675b) -,S(5ffc1899,4da42fa4,54962719,5ebe332c,86a2c364,f43b14f7,59710c54,4f6950a0,22eac0a8,79815faa,220e6141,9db053cd,4542ad2f,9ba9f63f,4331ad5,c2c9bb88) -,S(71be09bb,1832a799,c4e21bb8,a2bb5ad0,324c639c,e6e62b6e,69fa60bf,d41c51ba,c5227fc5,719a5b8f,28c40767,b54eb249,950588dc,c15e1656,e4ff238d,54dda472) -,S(4f94305,f92799f0,a64a3cb3,7df2bac4,56d661d6,44568277,bac0ed6,6a587212,4c48691f,bd8683d6,b94ddc7c,ad8d1d7e,6baf796d,6d00f344,511fc13,13c054ab) -,S(55ef868b,6fc2923e,e624fc09,65f61852,b3aeb38c,e2c6b3bc,54b86b3a,60f0ab81,ec198aea,ab16b4cc,5354d0ad,c66051fb,76cff6df,22dc1a0e,72ce6e79,1622efab) -,S(26ad5590,46e19dbf,e60953e,d40a3958,a357f6bc,23642279,cbcc355,74fdab68,af6fc5ef,906721c0,553c6a74,60bc6894,e5bb77e7,4dbc25e2,184fb3f0,fa795508) -,S(739fb43a,b1b07155,39c0b0ae,43901bf2,bc051a69,8ee8d503,84fcc1f0,ec37312a,c1223704,3c882226,2d4abe33,1de6ab4d,ff90d6b8,4c0b59e7,a193e763,6c6b7e28) -,S(2144649d,508cf5da,a7b422f8,22e9125f,d5a10965,a9d32c6c,c299bad4,6616771d,1153178c,e33c445,f03ef96b,35067ceb,76ddeaca,d9ddba1a,74acd229,d01ca76e) -,S(62cc463c,16ee8e8f,16ea8517,5508278d,4d5577e3,556d3580,ec8d90e3,bbb97072,cd294843,e299c500,846a6c91,c913395b,56b48efa,2f9ab3fc,b81863fe,8a6a891e) -,S(1196301,33edf190,d14fdb00,640f74cc,4317e1dd,b9dff1c9,707eac33,53ef9c21,f16ab4e5,e3a3ee6d,74385187,6da07034,caa4f519,6106a0c8,3136d21,5420494c) -,S(b250bf86,3fdaf93f,28f15bae,d9555287,777d4e34,2673c16,2b4a6319,2289adcd,295c05be,de343d28,87d3543f,6b40d5f9,da1e06ef,39fad6f8,28ad5ac1,39b3d2c1) -,S(93a40bbc,ae584739,9f10945a,72c199b1,27ef008,14e87e69,6f4f46f6,483e7c6c,81ed70c0,29809674,f5f289a4,5926864b,f088e2e0,af66173,89fe8cbc,aa858a09) -,S(b9e6761b,4e909d75,b17e76b3,4e9825e0,19ff7ddd,4faa9f90,eff8c0c0,f60978cc,640c1503,5fb91270,8881b70f,bf2c8575,65c75e3b,c98d211b,76279090,7b5aa117) -,S(4dc22812,fe3d9ba4,687e260c,f5b2dc08,ae454751,b022b9be,ebf4360d,10cfec24,9c35ef4a,56858135,552e986d,a4d68056,27f0822e,43031c43,5b2df5f,7f9a90d1) -,S(431276b3,1127f9c2,406b94ba,683d2d3b,e198e225,23663540,9348286c,4c9deadf,2265ed84,c7f1df86,4b46280d,ddc8cbee,c26d39c8,ddd5b743,13938c4a,e01efb3e) -,S(75c5b6c3,c99058f4,2b4b81d7,6cfaa917,328f1736,b8788360,aa810acb,3683632a,549f009f,def17b7f,70a309ef,49a890f1,4a5aaa1b,a80f0464,affdb5c5,a8f719d) -,S(3c900027,205af742,976b1a37,7a4801df,26d4d4e9,12ea757c,815ef99d,cea827d7,e28cff3,37eca7de,2387fa7c,339dab2,7a2446,fe7184c,83c578b1,8649cc0) -,S(5660f31a,3676b95f,9fa8ab0,d5c23f30,c89637bd,3a8ea97f,3a87aeab,3310d9ff,d6069cd6,6bc4ca0a,7d892ff3,e4d9aff3,955bb76c,2ba3f839,efbd786c,b11c568b) -,S(2b8b68a4,1b45dc86,7f7979ce,5b71d778,e6733cd4,79af6f61,8cd786ff,5f3babe9,7c831244,d5441b33,c20923f6,3ad9a093,840f89c4,6c1421ab,40ac52c5,8de4097a) -,S(8635004d,b817bcdc,4b357886,96b3fca0,1d369d4b,303e9290,44229cea,89c18610,2472da40,2bd46e6b,e2f84cc0,5158da1c,7e9f3512,1fc4b00c,4c3ec329,6eb909e2) -,S(6c991a6b,6eeb4f97,9b7afbde,46e1eccd,b0d39d03,dc64fb69,3a56a234,88cb28d0,1e5df74f,c2cd6350,50277188,d3eb4473,e0b753e,4cd41372,2bc119ef,65c95620) -,S(acdac19d,4283cc91,b9698ed7,e92288b8,554569a4,962ffa0c,a52a197e,9f41570c,fa536d87,523c8541,f530c6bf,e71742ba,451d41a6,f97d9afe,ea03a520,c6d7b66e) -,S(b1496ba3,f696cbb9,548b107c,3d28a7cb,85bba7f0,aeb50abb,a3e2a596,465fc6c0,77fb6cd5,727a4a6e,e0fc8f8e,ae807827,487740bb,ff5cc57a,8572ef3d,c86318ad) -,S(3fd97db5,6098e9ca,fccab31,d6d128e6,c2c9f878,adb07ec9,4d854034,d9b09126,1bd77c36,1494e374,fc45127,38b246f7,24e37d4b,27e14a2,2c0401f3,222b4578) -,S(5e8df855,f2a468ed,5476d5c4,409c7cfa,eb174cff,ad793338,8982ae2e,c2aefce9,52e73a82,3bb8ca88,a0977184,38701841,d50da8ec,c46f357a,17eb8cb1,36a6845f) -,S(99f106eb,1417cb69,e95e6fb0,a0fb932c,62021a1d,b940c661,3f814086,c64672bd,9e7fb038,e1e70011,6a926e6,a1c27fe5,e484d843,d184d533,7e9825ff,f7a6501d) -,S(686fc498,5526d87f,fd11d686,4ff0e208,68bb14fd,4a5c71f7,ac43063a,7e51ef8c,1d28f532,d793af85,bc96dd6b,2e0f23fe,4137dc5f,5b3d6244,22f60919,44588e5b) -,S(cfa5df56,cc450bca,914f3a85,b370f864,e4c83600,560bfb20,93df96bc,bff6b83d,cefb9a46,bab7ffc9,1b1d96c7,48f81706,61cf56f0,264e203f,78b05f3b,8d37604b) -,S(991b6b4c,3fbb9693,f7641eed,534e7cbe,8937606a,962a83e8,b39089e4,713e404e,3ffeba6b,be556688,d3b8a0a2,f4b92b8a,98dab79,d5847c71,13bb60ee,be3f8d3e) -,S(d104c5d3,b9b0121c,58a1fa14,f226c513,2955c4e3,56938bcd,6891bb92,13c8c0d7,8c8399a,814d7cfd,32cea21,85c77738,91ddb00,a091196a,3d90d056,b0caa6e9) -,S(76192853,a45c3648,749c9a40,719424eb,415a06f7,c74b31bc,ad93194b,e355dfce,31139287,3cbb5012,d7ebc934,52613c62,b5517b37,91475ecf,84ef3745,324ad2fc) -,S(173304a8,509c1f4,c05b1de5,c51093b2,10c7f9b9,81a7d6c8,8059fb1a,e5070725,43bfbd98,c8e08394,543db2e9,c692297a,800cdc8b,398c13d5,f9e21f89,341d353e) -,S(aca057e1,d28c5514,107f5b6a,9e46fc95,9eaccaa8,b14d4c4,6b7ae515,bda104a,e17f1717,70bd76ff,18095be9,a4b72b8c,cb00e6cd,23f6d702,4dcba433,e6bf6ce8) -,S(fb202550,e0098fb1,c30a7385,900a7dc3,85b2945f,60e6eb04,b7e8489d,3476dbaa,1aaf8420,3f72c68d,bd3bc98c,77f473cf,cedda922,dfc3c996,45e4f565,ef9a0f28) -,S(e95b710c,a0227ab8,e5b66c66,c2958be3,af1aa298,422c501c,8f879bc,e11ae7ac,e645f4e1,ab5cf4b7,da909022,cedd01f8,c745a968,d9ca30a2,c5525d50,9f97cf19) -,S(6db4525c,3589bff9,605cf203,cced45ff,ab136c6c,ce77ea15,14766f3d,e844770a,e6b7f403,f5f7584b,2331d295,82c0698b,799cd7bb,3c59c903,eb5d6848,72658c81) -,S(8893aa9e,49daeae7,15fc2959,e4db9c45,1690438a,6964a2c8,fbe73133,35085eb3,70fbd83e,ae803f3b,6377a4b0,265f62c9,bd15cec5,baec8c10,d01c7094,e5987cdd) -,S(be57f6cf,ac6e8cda,871e3ece,8aa78bc9,2cd9e2c4,8f3adfd5,6e39414d,8e0207a0,78170872,99abf89c,fdcd141d,899aa7ba,8893eedd,36bb3aa1,58120f2b,ee93d5f2) -,S(77fa6d2,85a01129,c5e05ddd,8d02b5d4,a2f69bf4,5a9e7562,6718cb54,20b34925,315bb23c,13a3d218,ce886288,ec0edfeb,37a2da99,e017b97,ce04db45,326455cc) -,S(2fed7bfe,8414dc33,62c834ca,767ffb0e,61094ad,978ddd00,b2ea09b8,d1f4dc03,14e5e8f7,aa0b3d31,565e434f,11c61b,63332a60,b6c4cff2,a6de2c5,98117e01) -,S(9f4c2cd0,5a871ba1,fcb43df2,bf03ee3f,7f8af242,ce8ee6a1,1aeac89,b4d66c6,eb421f52,f2427887,8ff8a2ab,dc384e23,d0fd7df5,fc341acf,83bc5940,be922920) -,S(53c0e0b6,824a04cc,b7203ef6,e37383f0,15f0a48b,bbc1d3ce,7c8fa7ca,5dbea647,6a9b598d,9246ca1a,539729f9,be809397,13c59d5e,105a8e91,836fd3a1,4d618cf9) -,S(dbc0cc82,d7906b84,b6b7bba5,433d68eb,bb20fdbf,7b4eefd5,c0a3ad8a,ad17d714,5ebc1f86,23ff2c3a,6f81b090,4e5e6338,8aee42e2,85306e37,a4fc7676,2dcd7211) -,S(7862af32,a3c08e04,7b1a8cbb,8131d55e,ca93a478,40c52165,af20aa6d,248f5f0b,bb5f6607,6b10353c,8a367a64,587b3bf9,7e8c272e,8da92684,f1efdc33,8bfc15d8) -,S(d3571fc,800158b7,6ed2bad8,15c93b1,f8238fc9,b8753752,4e44c0ca,931049ee,162dc9e8,3e6630aa,9d0872fa,915af449,70a9e6f9,526bf15f,4d26bc74,82a44bc3) -,S(a851c894,cebbc758,642b98e5,5df3584f,b9f531da,88faea26,e908b0b7,88589d9b,74702d5c,adfac1ef,71df3898,3ae433ad,1e1af1f9,b5fae0e1,151258e3,b375b422) -,S(a92e43f4,12effaa,e0978a08,cdb2e885,2d9af1f9,1f0931e,972016ce,da58012d,d8f5a09d,5560170e,b35d7bd1,28252096,535c687b,23bc13c6,bb903b95,d02fb668) -,S(75cafe44,8b4369c8,42e658c6,4760ecda,bb29e129,d283c24c,9007fb5,f3cff6bb,ca0e12e2,43c73553,1e2affab,51d4738a,db1ea5a2,fba215f5,3c9477b1,b55dc39) -,S(ab0066,4db959ec,2f17a233,78023b5a,c48c4177,7b6e6b56,a2148453,8c41d006,8cf9e2fc,35545169,f46762fb,940758ad,e3d3387d,eb72e9b7,b5d37175,9f5d8b31) -,S(27510ef8,2e4b2134,180855bf,469d1f0,f89b9afd,573f2781,4a1bea50,9db7ecb7,20fe00e8,86b54c06,1fe07355,5be99fd3,b0a1b20c,dec68aeb,90055c34,acfb87e1) -,S(773ff5a8,d388277b,7921405c,99c9c207,f4a6c2ee,3b59ac1d,7452c8ca,4db16d3a,cf45e631,f51cc65b,afc806bd,87318e3a,f75caf,3e734284,8d7435be,f8a52f8e) -,S(2f8f2c98,e69ebfc3,b7277e35,9da1a8ef,4293fc37,2e24386f,e14cc455,1ef45746,f85d23ec,c4dcaba0,23c3e406,604aaae8,8150a6c8,feea2c36,42ccad40,9968ec06) -,S(1878acda,ab8dd0e2,a0884952,26356ce5,74575678,64da41c0,61a83de9,6277f67f,412c868d,64e092c,ade96f05,bfa48af3,ecbcc128,e6d09bb,9684565a,d5477020) -,S(8cf281a,eac4e4e2,7ec4f3cd,d1373f62,c5a17b0f,49cf69c4,cad8c4bc,4f5618c1,2f17f995,29c9ea27,cda3911e,de33029a,7dbf09db,64ffa625,cd9fd86f,29ed5973) -,S(3a597c9f,f165369e,5d90d191,3dc2aefe,a0957936,717f1ec3,9ea20698,d08939f9,8c2203b2,90c9a2de,5b464b0,988e07,a7b48c86,f5891926,da462b4e,b00a14d4) -,S(cbe3205,96f10ff,5de9c861,55290393,b9ceec90,bbac68ac,5054facb,950ca15e,446cb06a,b76aba12,c32b4855,716001cb,9bf7c72c,ade16bd0,5472b947,4fee27f4) -,S(4313c9cf,8224e70,18413b09,e6544731,1cde7100,5ee60bd5,3a8db041,56fed594,dfaf359d,d3045a8c,b181021f,9a025208,e80bbd4,abc4a331,7ab9d735,1b329a96) -,S(cead2b51,f8d8adec,2d89651b,2da5ffa5,1f5cbfab,19fb7688,2bdf0faa,bf73c60e,ab2a2480,6992f0e8,c73e7932,2bf144ae,6dd3bda7,ed2d221b,f8451ca4,56a25897) -,S(9ce75c8d,848762f,645164b8,45ee6eee,98e34dad,9f8be0e5,2d8f27ae,4a7b79a0,e0556d4f,e11ba906,6b97c04c,8b742a26,9f627559,b9163571,d0a29dbc,9aa30a05) -,S(6024489c,621de255,f92106bf,8c23847b,10214b83,1d653a9,6ba00889,326741d7,950eb24,80a90200,ec932621,6b82e5e,abf63e08,6626faa9,b1fd8e2e,104ea858) -,S(d3c746f0,108f6bcd,406c2638,c07255fd,1f55e1a3,c6845e11,546d22ed,5f08e51d,d124dbe5,d349c739,e641a776,c57ef3db,35ed4e1a,6ffc165e,25d0bcce,438dfab6) -,S(a1eb5f5c,d85dc222,f97b9e11,e08594dd,a69c69f9,bcfa4c63,52cf2717,136514b8,46ed3d35,a393e017,76247ddd,7dda3ba0,ff5e3f76,30253b68,750a7c,f8a15fff) -,S(2b24a357,fa3ac2cb,faa5f1c6,1c14147c,e4406556,b82c7639,721f7561,485a8736,d67219bd,707aad55,1a8fd7ae,d5721d45,ad192a5f,5d0b643c,18330cd,1bd73ade) -,S(9901a1ab,9dc60159,63cc9cfb,42ecb41a,ab6a623e,62e9f306,126a4f6c,fd87b2ec,8f766594,17cd7f2,fff7a3df,6cb414e7,eb5950c1,ee265730,633ccd8f,f0339317) -,S(311e8445,5890e2f1,e1d8e600,37d58c83,28a2a4e1,b21c3763,4aeb9965,8477e8da,cf593f67,6cc75762,a1b0dd00,f6703bc1,e017e927,1e61c829,a0459056,ecce030c) -,S(905f72e3,97140f6e,298ad8b8,c8faf66f,122d27e4,6fee88b3,67a8ecc7,9e83bb77,c03f155d,bde9c265,d90b94fc,1b5b253a,2d98528a,a12e19b4,698714a6,f1b65257) -,S(61df77a5,d5940001,2fcc2f02,199cbb4c,39eafd33,27dc85e,4a3f55b,a339350c,27c88b7d,de9b3f,73b0603f,2d6e40f5,f3664020,8d6dc05f,684626a2,d9049161) -,S(e1f8e199,886d4b1d,5dd6af90,6eec06c7,de36dd4,ef026129,5bc42bac,5df18c28,502c12e9,b956eaf1,2865bc4b,ae7e6348,56a98db5,4c65a5e2,9ecf8ab7,51ca45a8) -,S(ade2f5b8,3804a21c,7dfe6a7,7044cf96,9180e154,79a4aac1,9b686076,fbb8565a,d0d65e1d,7c8168c,308985d6,f5d267e5,98a9e6f6,45715eee,3751bc26,ef066aca) -,S(c55820bb,154f972,ac345dd5,c62880b8,9f7f6b85,a1755b88,ea5821de,6f268187,911b0fea,1e6ca659,263b698c,8a17488d,4dc35f5a,d817e7a2,1241e56b,cc613086) -,S(ea20966e,321020f4,53964352,b8ccc2d2,1285888c,152ddd08,9f7039c6,6c7778b5,c942f591,cdc81e52,6abdc9bd,643429c1,66f5476c,dde18d39,59e29f26,9f4fc18c) -,S(3c57552d,9c2dfe5a,67301bbd,3e1ef84a,220c908a,8e80c707,9f9f4df4,607e2bf5,d49fa0ff,bc4a6397,3e71a0a1,7265ff65,6fd34754,ed508522,b9f0200b,e71f39e3) -,S(f188ccc6,e1043ec0,59e8e133,94ada165,a3fd5c0b,cf7f071f,eb5a0951,9bd4e1c3,5f1f371f,e53e79d0,2d6fb190,8207649b,db045c41,a2fe1cf,94486053,7bfdbe4) -,S(a0145fd2,7e72232e,8055a146,aa7bfb49,447112a2,d1ca53ca,d4835e42,c11c8c6a,7bc018a0,e5e70ccc,c4bb675,f0709cb0,ceb874bf,22c7ecc5,243e49c,3de679cc) -,S(53400de8,c221153,1fb85706,b558185,c17b7bd8,b17416bd,9c93df80,f16ff48e,e1228e47,3ba565f1,e50840b6,a36ea970,2df87320,8a66a44c,89cd33da,41a6cc6f) -,S(82115d2d,9d37e3,50ce3482,1d59af85,cc8960b4,52b99904,8c6c6674,ce64b1ac,98deaa09,659a0c24,4aadab0,3b9d1881,bffc1b3d,e9226f05,e75fb9ef,b61eb048) -,S(273d8c18,53d86f1c,c49e6e9d,450dce26,8669cb7c,3083968,1fc17894,59fe7c3c,6c5531aa,8ad026c8,174c25a2,51efbadb,14974e1f,7f7f88af,2e16d101,c2ea00) -,S(616e16,a7e38191,70e33f4f,bf428fcc,41e68ccb,5b059bfe,4036751b,ba5ee319,7dbcad21,182a3efd,b99173f5,cca99374,7c7dc3c7,3e8af2ea,ba84b0e4,f506748a) -,S(6761896a,76a39812,1f773402,d033f210,dc566610,275f6774,52c37c01,60b82812,7fdd01cf,1b40939f,8091184c,8e2c8ce5,11848df1,a23607eb,e760782e,67302c9b) -,S(77f7abaa,e97605da,12535bd9,e177b6b0,bd6eb020,92345fe6,dd4a6d4f,89e508b9,fb04996c,cc7b830d,fcf5fd19,bb7c9332,dbf20fa,10d61231,889e4b65,cc7f0b9e) -,S(c12f6717,3a2e2bba,3da97378,501f9cf1,bc4b4a8a,67b0c5a4,a0d8caa3,98bce311,de930986,44d31401,510012aa,3b6cb541,97cd133,6e583853,a330319f,779a47a8) -,S(6553a2de,19c7552c,8db9d268,ddf3a034,4afe8ffa,a76bb304,ee77ef95,c18e66aa,91a72010,7c180bb7,2af4dbb7,752d374d,69f95bce,c9bbb7f5,37377060,70edb93c) -,S(f54b4be,353f4185,22e2e936,3400caa9,bba98023,e6a3d3ee,c1fc5046,b7b834e3,96be786c,bdd5f1f0,a835afde,219745ab,ab6f78b4,577d3a5,1246437c,8e96f17e) -,S(c2d317c2,a0fa6522,bbc806e,45b4dc8b,f86be37c,4b677c64,c0d5b4b4,eadbb2a,c5710969,bd68cabb,718cb16d,fc9994a7,100f078d,4a3aeaf5,8e8eb35e,d313ab6a) -,S(52a567c6,a5b8a64f,dc74b9c9,57f5d472,cc43e143,4136fcce,fe1ff313,1b89f384,332631bf,a314298a,dd45f7d6,b8192956,d7de27e9,7d835d48,5c16f7a2,9c9e8f53) -,S(f7dc086c,891a4412,88543527,831247bd,3530f0f1,99b4c5e9,8d24a207,1dba4e20,734ed712,452e59ae,b0ef5f75,10485860,da055003,ff1067e7,b82de345,b74444aa) -,S(954f9fa9,7bb6dbc0,cbed8d8c,de6f8f75,b3f2ae51,e512cd3e,90520d8b,22ec06c6,b65b43bb,8bd9660f,4bdb3017,bb4f8214,5426f614,8f04378b,f65c39db,185dd9bb) -,S(20e69b98,41416588,20b66947,f775cd96,6def2dbe,416b545e,8188db14,2604e87e,e6514659,bd12b9b,35ae45a3,d43f6023,dcce04d,87df1f51,caa67f89,28632539) -,S(5cde5b82,2dc42f04,44187fb5,33029577,71bed484,2ab39dc3,709e7c57,c72ed1c,a0f7bad8,64e405b5,94416e7,53fd6137,cea3dcbe,7625fe41,b4929299,a9a0ea9f) -,S(b586cb4c,6ba6b0dc,2aafd03f,49d4d6e8,45b20460,5de71c34,6e73b131,fb26421f,ced613e7,c26ea3b2,a31de623,506afb86,6767b469,98bb116d,2b4ac9ab,58948744) -,S(7d3f6170,35803a82,c8e13dbf,a8d601c5,4e192a54,377e4a8b,2a2a5de6,90ba6ede,138e810e,62f413c2,fb56477,80c0bcbd,77eaf84b,e78e900f,1969f4d5,2ec6cb15) -,S(e7a314be,fc4af863,e7fe6713,5304ab81,c9fa32dd,80fa9b41,d8577ec2,8f7eb925,cd978600,f0e04acf,fa99b6d0,7da970c1,13ec94ce,c50808fb,91a44f4,80f3eb1f) -,S(179c3be4,9f41902e,e21cd8e8,10f0dfc8,ba5fc0ad,9e454231,ec090263,d3c6a577,75f9f60e,fb9b9aa0,29eb03f5,a50b7e4e,64021689,a4e889dc,5b9ff0cb,4c9cf184) -,S(10a55871,464bc182,b957808e,25754fa5,8d76269,5cf8c6f,e50610b0,91e6401f,d36493b9,6d2bda2c,e305c679,f906ba9e,99a787f2,aa8cb8b3,29516a3,41b56ff4) -,S(4a903722,5e858c84,15508d45,b31ec7f6,585827a2,f3a9c99f,96af3e9a,e88e555e,da4d45a7,fb9e44d0,cc52463f,20fcde14,31c9a477,d02c464c,70c7d132,3247d145) -,S(6d109d8c,2505808f,7b4052d6,b170ec80,c68373bb,e02f2b62,1cd29773,a96acb3e,c8dea0de,511f6e40,5141088e,cb023bff,200c870b,9cb952ad,c5038b28,eadc9a57) -,S(9c219898,6d202467,c055c734,73557505,6105b3e,2874dbf2,8f7f0c39,66e1af88,8637496c,8eddff12,f9dd4146,36565e0f,efddf5cd,52d48455,ec9fb2d,8dd0914a) -#endif -#if WINDOW_G > 13 -,S(22ca5039,e660f60,1036dd75,2bb973b,dcd104b5,dcb8f2e7,4de8edc6,c292b03a,86fd4471,1ef6b81e,4416449a,708fa0c9,cb6731ba,c403e58e,da5e915f,646b11e8) -,S(cfc18f02,cc004640,f2116fdd,1f6ca202,2e39be25,df75e27c,80bde842,e6b6f938,d62b58df,4f79d0e5,97ba2923,f708cbe5,c09236a4,d9d01398,6451d684,6290df7d) -,S(3388bcc2,3425458e,991f46ca,6235c50a,57490556,becbaf25,9d3c14f9,9a80a087,7d4aa2f8,6f65783,1c22316,6958fbf3,6c3dca5,d4ac413b,3102e13e,a645c016) -,S(d26bd013,1b8c12de,3dd8fefc,136d9f95,44ac963d,4cbcbaa8,2ba941e,f0b46a19,66f89ea3,31b6795c,6b694872,4cab492a,d045a7d,a6780653,cb10ac25,b68d3a99) -,S(dcd3370c,db67e8f2,163960ed,fef5f66b,465a03d4,d447f5ca,1d99d29e,57d1fdb9,8b93747a,320abf87,2cf8d448,393bf732,8a9eb4bd,9b64ded9,922616a7,347084ef) -,S(74074d05,e602ad56,337105af,59c63819,21d449bb,3fe0806f,80589f3f,4f8d8e7a,1a4d4bd4,adee80ad,44fd515,a1dd5236,bf0dd8f6,c44782cf,e19b8414,b03d574d) -,S(a89cc81,f3a23ebb,6a8df438,a78092a9,97120394,d6bb4dd,732373a8,2f05c174,4b6f83dd,676df063,4e5ddc9f,db979dec,326a9ce7,5707fd77,873a9644,a3c4fda4) -,S(8f1a10ba,fa913f0e,1902ae36,b07f964a,6443c540,b60ace03,7dda380f,6616424c,1028d644,45c177c3,24416ad4,e740f31d,14e3a462,d5a0326e,86998555,5de5525f) -,S(ad8fda79,14f9a236,a7957268,ada499ad,9154a2f8,478fa6d6,f4c74048,89e27b51,9ca1d2ab,1f7da6c6,f76deffc,5c3c933,703b74f0,26063834,6174e4be,320e82ae) -,S(6c6e990a,797b2970,4408cc24,6f238e2f,2192700f,e4fb3c87,4d15e32c,fd67fbe7,1ffc1798,f355659,9fa5b32c,c040da31,39811b87,93d4d9e1,be83061a,3f91dac1) -,S(202b13ea,31ad2abd,9635351d,e09f237b,9f86f75c,a340a47c,edc1f9a3,25118969,c52fb505,a14e37f4,d5111184,ebc81873,868a4521,700004c0,fe3cc535,181bcba0) -,S(5355f0a1,25142fa,b0dc7c7c,f9855953,34053c6,12326f5f,d2284291,d7b748a5,75bbe36a,553501f6,c1c8ff9d,e60ee3ef,9cddd36a,781c518f,4b1ccf17,7e281949) -,S(b8852d78,eacbdec9,d1cf1664,4a83aec2,79a39ab1,34706235,f913aeac,c29829d7,763bab50,52b3c61f,ae42735d,2e89ec3b,8d51eed0,f729e0fa,eb431613,df183156) -,S(cab2e44b,294df78e,1c17d4d6,a09ecd0d,696d18e8,b0f188b,eecced5b,7057ae2,f351b09a,501a499a,ced49607,c55b506e,de28bfad,5b20ed5,4059a068,19ff2f43) -,S(1400b9c9,9c6d555a,2bd2355e,b54b756b,b16f9f36,b9b86658,9d46853c,57056b31,8b290816,62f41167,a0a6993b,3d4211df,5709b91f,96f24436,e569c32a,dfa077a8) -,S(52ae372e,973e9c1c,687ae7a9,a111446b,b3d31b19,5588d8a5,fbec6e6,bfd9141e,f982b40d,e6d0e42d,b9638721,a4590db4,1f87cfcc,d8ece56b,71ebfe0d,82351ccb) -,S(3d14ffbd,40824625,be241e14,850dc030,1139b708,b937f2e0,fe5f65db,61899c24,b10a64fa,477ee047,4d9cf16b,8d2213a2,799882ef,d3766872,981fc761,88a1dfb7) -,S(c6f52adf,54e0c197,a8bbc270,d4c987b,e7ab3fd1,a95fe46e,82415ecd,baa48930,7524c06f,b53873b4,9050281c,99fa44b,b9ef9193,2adeba8f,77e5afd9,3856811d) -,S(90089264,bdc47cb6,7a3c838a,4c79c1c0,5f2d1dd8,6d18f55,9fe60a3e,c944c1aa,18963846,d70b3226,6a9d582c,c430e4b6,ca140bcb,91de7064,eea0fb39,d2ee04de) -,S(e27c24ea,478b37c1,6275b2d4,ce8212a5,2db74166,96f3c6eb,c1bf7091,efda0662,27ec5279,c3a267cb,fad532bb,5031791b,bb99f4da,fc3b7b7d,8537cf09,12783de3) -,S(ca5daa12,9cf1d6eb,70025d85,7955d3bf,2549b8ee,6064092b,917eff84,c40a3eb2,682d4905,500f6f7d,33e7c7c2,7d420b4b,7c4aa5f2,77b89e9e,f6a84259,de7a9811) -,S(9069ec0f,2b2ac688,46623fb5,c89d1424,6c98ac5b,4250c170,4871699e,fc877f55,cc500ec4,eff83712,16c0617e,e2407dfe,a6c3c3a8,c8b80266,975d3a56,e71fb05e) -,S(5fe1feeb,bd5ee1b,6ba742d3,c5e8aba0,536393c,592650f,b8cb1391,c3bda16c,db11b327,1ac64ed,3425ba06,8072f76f,ea02ae6a,4375daf5,3bf942b7,9865a34b) -,S(a4a91a5,f168f883,49035b6c,f90e4e0a,6bf2602a,85e0ccb8,31866c4a,ac1b2c34,5bfeea8,fe36ed1d,18af2ff8,e2b898aa,ff7265a9,c08f4857,ce082030,7f837596) -,S(f4135f36,f0c35b52,4a870505,4eaabe4d,43f5366e,d3c7d9e3,5f06f746,fa884849,1c6707f1,b8b6c078,b4d9d0ea,43075d75,ba1a5d30,c3a9c52d,d55fc4b2,650c526b) -,S(d5a8998a,9363fbae,d2b44992,883e84b8,14a504d,92b41e0f,dcc3a9f3,94380203,96016b03,6fddc805,8bb8ae7c,6d46cd7f,2f20c5af,a62abd4b,bf9b3da,ea60e9fb) -,S(8804ca34,4b30dbd,a07fb62,210c1938,d50297e7,9910dfa8,cc38b9be,4bf3d176,5b64bee5,79927c63,7788c55f,f3871631,eb65db50,b11cac91,24caede7,57d37b0d) -,S(8691c1fc,440c21b6,bc48e78e,78bda5a5,c947c74,7d098e74,ac5dbf6,2b811021,fd8ec1c5,35f51181,556c330a,f02a7110,682f4539,f66c1c09,3d48bca,d7b1787e) -,S(445fc1f6,343be2e1,fdebfe3f,894e9293,c3ee5fab,b0ed01eb,58a40637,ef093229,857f17fe,6737f853,d04aa1b7,3eded13b,c3c087f3,48da90af,32907bdb,7d85b605) -,S(5c397fde,a657d1b0,b2e3aaf9,5b88c4d6,af1a5555,a1dcf966,7d1c5001,a76493b4,9ce74820,7b6f3c75,2d736aee,6a9fc54f,ce5cb52c,f487fd32,de79a06f,df0aff0a) -,S(9b5565cb,28d7e028,361d2bc5,bdfe1912,d9f53584,372d30c1,d7e36fa4,c7fc1b7e,7d5cfa8d,2de2a832,58a57f05,4e3f6c6d,a23af075,d98b062d,82799b11,63879eea) -,S(afbdec63,1bbf870d,3971b165,71bb195a,a5229a9f,1012bb4b,89654da3,c9194f1d,cfcba749,b9492525,f9874ad1,bbb0a267,83fe5714,1f54316a,773c2453,8f27e296) -,S(7712abcb,ca3a5347,5cbc6160,5e9e9ec7,a7cc11c6,2c4b3f4d,e01d688,acad916b,7b91c9bc,eb12555,ad2b43af,8c3bd332,b57cbbfd,1ffefead,c68f0a2,6a4b82fb) -,S(3c452346,f2935e41,2e5fe506,fdf5066b,11b43a11,66e75c9f,7a2d38b,1ca2b7e2,fd3f6de1,27f96829,3af532f8,d4811fd9,e02038a,352b6696,2c608c7f,f59cd800) -,S(bd8582f,b4dbda3f,c7da53d6,70c994b8,e04eda44,ddf0b054,7d182db0,aa48b7be,799e2769,c18268bb,8c16b282,ee7d0828,ef0dc4b7,9767033a,d6de8c63,45285c68) -,S(c41010a7,8dd9dd40,62bfb71c,1691338f,befe03ea,d99eb719,74dce6cf,b2c84112,5008c39d,e71ebc22,3b1c5dbc,f824a63c,f270f807,3143e08d,29b162da,42a2ff83) -,S(e89e807e,6cf4ba27,6586a6,a509bc8f,f786bc5d,dedb5f4a,1b6253cc,2521d311,aadecb79,7c4948de,9379fcfc,4c040029,2228f9c1,c099117a,ad6d9949,f2fea2cc) -,S(363df1b3,be2dbf90,64137919,51218c34,84091f73,866f3fdb,dca1b90f,dcb08577,aefd04e,5634e36c,49621493,f7e76f20,f9ea5b64,6309a605,7e3bdf0f,75848bae) -,S(5c8d1638,83d2824e,48121322,85cc44bb,ca8fe33a,34d5c3be,cd4a3c8b,c78ea16e,f66f91d9,c7ce66c0,89500591,49f7525a,355347df,8f31a685,872aebae,1ac0456f) -,S(10ac6676,83583ed,d837789e,ed9254da,4181dd58,be75dff4,8085e87,eacbe126,6d3eaade,23f3e7bb,7465acb,c6b25af,72e0dba0,1815ea1a,1f57ebe,bb17d22d) -,S(1e79a1ea,7bb65540,44567796,2208ea3e,974c4c0f,9b61f7da,8dba697a,8c153048,b63e3d79,20a34888,68987406,4a8008eb,e07d35be,33a055dd,394ef2a5,f0787fc4) -,S(db0d1c73,97b0a23f,508df2ab,b00ff13e,11699118,11d6476a,7bebcd09,53fa9a5b,1c9d0877,3ca74f1e,d1972431,2b5c8eef,2f85fd41,6629cdc9,d0b9e328,4900dfe8) -,S(e1fdd7b3,481ece8d,266bdc22,92e775bf,96904223,e620f622,3a03ed,cb385f27,3cfab39f,28953ff7,d6dee65,83fdc6a7,d9b31f93,e2103e6d,9e4066a,970a4c77) -,S(96797134,2b69bb8f,3d6701c9,22130c8f,9ed85fe5,bf189880,3b2df11a,a223ffd3,2d43343f,630b6f9f,7c4b6d93,cd29a3e6,632c0dc6,c095794e,5997e47,e631d31) -,S(dfb40218,6e27d494,c69d2a0f,399dd480,ec0a776d,9a99fba8,cba81417,d9c33efc,332d91dc,e9f93273,15e45bcb,79603050,9bd8501c,17820f48,61f7b12b,5d37796e) -,S(6b65c5eb,ed13dca4,51608da7,b5c1a331,171de004,7fbe35e5,189b8468,c27681ec,afd0ee8,e0aebc0b,2f246b51,f6fd4f85,3e71fc4d,f5bb9f43,e2679c8e,89a34f62) -,S(bc1c3da1,60b03965,e26396aa,5d426df3,21e5c22,fdfcd004,80a390f5,28c4b619,fd657174,65e4fea9,ad7862c,422c11b,86ad94cd,35acbbc8,76ed464,aca31640) -,S(589b1d17,96d6ca35,53f8a6a8,cbc587e1,9026406,c2c6f8e2,de613dfa,8c05913a,e655d5ec,ac254f46,e279365d,e3bba2a4,3c7b6469,da45ec87,9742cbae,503fb3e0) -,S(9e726385,6d1e6c2a,94dc2ef5,c92d94bd,6ada63cf,cea75677,6125bf98,78ae4ed5,8c238df5,1e5b38f8,b628a48e,dc7aa2b,a83bc40,43c91896,69f5341,60e304dd) -,S(12269d78,14e0f74f,ba40c551,b2080e00,4f9bd3af,255218d5,7eab5dbd,c6764263,f0f70bd,6584975c,106febcd,bbd16920,daee58c7,c22dda70,4a95f864,e385b3d6) -,S(d3212f2f,cc509014,e0c48cdd,6273effc,5c73fdbf,1676faa3,15e9173b,573088a6,39af39f1,673f51f,362618c8,49c6934c,ff59b6ea,853fafc0,9db64084,4832df82) -,S(c535f72b,9bcc0bad,44014e72,4f649623,4ef288fd,9f42adcc,dae45a20,84250052,3f79985b,6fb7631b,62814a17,f7ce829a,88447302,293000a7,4655c7ee,4a271022) -,S(4f5b7126,9b169fa5,8602bb18,60ed0df7,271e3912,ec0d7c12,1c80fad3,93399605,b60fc104,7f2a58ea,9102c6cd,b97c932a,576f63f2,6204fb5,dbe41363,cdcfd0a7) -,S(cb459b3b,244c38b1,af2c2863,e0029c14,ec70e7d,737a7851,de9c8f1b,b7d5d065,7b67b15d,3c0376c8,2f646241,1e890b3a,a888bd15,692c90ea,53a74a4f,1957fbd0) -,S(787d61c7,ebde0c5,18f121bb,7f434196,d389f563,d1a46597,ea72a1fa,4e19054e,5baf56f2,5fcf8cb8,c271cf39,6b3d150b,f42e9ebb,d72b54ba,4b93bcbe,ae72a658) -,S(c38afc2a,31d0b0c9,4b77d97c,bd639082,3373538a,602352ba,cc93b6eb,c5f6115c,b925dfca,b138fcc2,4b9a26a4,c645f8d5,875e098b,d2e58469,d842688,43ee529f) -,S(37661e3b,8e606e95,b9dc6ad5,e5b9b25f,39a5dd0b,8ab7a82a,d6ec879a,ff406d0a,ab735e5d,430d8fce,1317e07b,d6cf9441,60d8bc39,132382a4,df1b1638,a7e9b977) -,S(e5127851,b8c22b47,c3d8e934,8dc0c677,88ea5ad9,f64e6062,abd68a16,51e256ba,5847f77e,349eb7,90b4b7dc,5537ffa,5b1e7d4d,b87044b3,f947f387,270405c6) -,S(f3c7f45d,a6b8a8a1,3713e7cb,7380fe06,127a3698,520bb41,955647b9,ad7382e9,2acf9a11,eb1b9d31,f71decd0,90093677,4b469301,719d4a51,ddfe5fbd,f63e7c87) -,S(86de4047,e8d5b252,523733a1,848a990a,79125f95,3bb0e4de,ff4b2f0,84d745ba,71e6a472,dac005d,2b284cf7,d5de92d3,56921105,1a9ee007,4279a746,71bc969a) -,S(c6115c30,72259d66,d960cd96,3f3aa16a,3029d9ca,c0c5ec63,5e2875c2,f3f57504,18d690d0,b33fdd78,d797f56c,23c821a1,ced02401,3443c770,50d12850,9f7a712f) -,S(cb545099,8b43473b,91838cbd,76929b05,8bfae0f1,e2bfbc6a,c61d3674,42f53c5b,4119d74d,79e34f08,cd7684b4,f9b9df55,c00ba8ba,7bfb4ddf,de38db78,91572bbf) -,S(d0dce704,b9362bb4,fb1771e2,660a98a2,a333b73,c6d09372,5a752f28,52922d2a,f92c3b70,7947ce0d,f1f3891a,259cc2ee,124d3f54,a4c518ff,de5a3915,96e37e47) -,S(db93e238,e5aa5986,38eab857,655cc53,d4270259,e7d73a96,249a19bf,216b20a4,8d19dc8b,670e8eb6,50b4f60c,d26ef657,3ab17895,c62fc94c,815d7eb5,fbbcc7c5) -,S(c387c37f,d8cebef8,29e07e54,b0796129,4d6c6cfc,bbf11835,ba85d4ef,68c3f486,852580d9,ae7eb300,6ca0f7d7,f12d7fe7,c8e3ae0d,b6258897,994fe78e,11ddeda9) -,S(ebb58d34,f04de551,37c01b5b,192bb4b6,4d3b22dd,23ad9092,f943749c,7606c232,1b979d05,9c99f9d4,db1d3e82,905abc9b,d92ae72c,509c912b,c59488fc,ddd1ae16) -,S(7891cc66,acfda29b,765810b1,730cad13,2f13178a,fbf238d8,2525ce42,96e38e6b,22193729,20188c6c,462987ad,7ecaec3,a21ff6e7,db00adb9,72facf65,367caaf1) -,S(c0b02542,e4bc1e8d,2c2578a5,3793fd8c,acec800,c0a311f4,72c50de3,5814d081,24bdc71,f5917c0,1ae6bb5,71c09197,76b1a884,ebffd673,13698bc1,b57f8371) -,S(ea15d574,b8704507,f12fd9a3,e40ea603,c2000cf4,4eb3d4b2,f07a36b5,c426d2dd,b6596d4f,4d8ca39f,4e0faf58,ab7e3894,c5cdc16c,589a524b,6ca25a51,8a30944e) -,S(77d387df,c35a6af7,b88d5726,a249d34e,70877698,1358c672,6e51b779,cf9604de,e5daeecd,2d70a962,d2d3c235,14fa2b1d,45916506,de017249,93fcd9a4,f08b4a87) -,S(a92742cb,7d1a24fb,c1a4dc2f,9d6fefbb,1064f9d4,c3152db8,3296a9dc,9dccd7ec,665a9cf9,8cdaf0a4,ec346df6,823f3c6,66d4f163,b3e7225a,d9d18e42,31679f76) -,S(253e54f7,9f0c393d,5d34053d,37b55304,f62de9da,29e0eb6f,36cb105f,a6316a46,54e168cd,ed78ec0c,32a9417a,c5b27ef0,67c8577f,8fe0bfd7,b2ae33eb,ce7155e0) -,S(d13048e0,e9c38720,6179586f,9e38029a,55fc01c7,b33d8443,4ee45cc0,3fbf2,7c4466db,94502477,85490689,7b251c39,af257840,b9bc61e3,64075080,84743f37) -,S(e9234110,387c2122,2887d079,7bdbc9aa,a632b237,2a5632c8,8e604653,70a284a2,2b98b08c,4ca3521b,4ffb3afe,66f98ed9,839a2651,f740f63a,e80b0cfb,6f6523c4) -,S(302e03a7,ab6978ef,73891a5a,7bb25764,7428341c,94f8a713,32ba9dad,83a29be5,4abe0adb,210c35be,b2ee850d,2e56bb3f,e8430db,644082ee,a98a2f83,5710120b) -,S(53701389,44400f30,dca0571e,eb0f8c7a,4fea8bdc,31d68859,8d7cd156,11665368,ca345664,39c1f221,a5731bbe,5a9a36e1,a712e2db,f16a6d19,71b1a74f,eaa97cbe) -,S(8c0e8186,645d7cb8,fad2b6f7,a5a2d399,656aaadd,5423cff4,9579529a,f28383cd,2ef275ea,14c44981,9307319d,18fbb482,63c6d24e,c94e18ff,cdcd7757,4c48d27f) -,S(64a70831,26baa3c9,a11615c4,5ff8ca99,adddc512,c697901d,afc43d7a,5fad8af5,ba43c48b,59a65f6a,c3a45c35,4bb17968,148efe4a,288f742c,43253e70,aafe29d5) -,S(fdbd066e,82ff8e24,b2f785e2,e166245f,63559acf,b4f56680,51db47aa,5d438e06,60dadcf,a19ed8c2,376a5d38,28b9499e,875731d5,b2417def,144e2a84,12973d63) -,S(b287ccb8,1ff90731,19ddba01,d9461512,82cf15cf,2dcb3e0a,f1b26f41,eead174f,6ff15339,7a9a0bee,4b38a463,5db66ed2,36d1beab,c0039bd1,acfbdc09,fb74e090) -,S(18047a48,b65234a4,fa5f2188,8b3032fb,3b3f8457,1bdec3c,962d5cd7,fd068116,13627669,18198832,306c5444,6cea5681,80134209,101a117b,1f34e15a,624574b) -,S(f1d3b54f,be4e2ce5,88a2dd32,8a41e136,6b74ffe9,5bd4aaae,ce7e7a8,235f914,37c25d41,300e817e,b4ae1471,e8486232,c0c21165,97efe33b,e86d6277,a8a3981a) -,S(9b0da9e9,5046dfab,7ff509a6,10ad56d,9770da36,c5e22a83,9ce3a36d,853bec4a,27d60345,30c25a36,e80bbc3f,f43829cf,df757c19,1a2924d9,6da77503,38135faa) -,S(d0833bd9,5155d18b,be55d40,3717568e,2d3e4d24,f2eb65f9,f13d8d65,d899c5cc,e509aec3,b5044ab5,11fb1e4c,56db7146,ffeefb82,ec4e9de1,3c473bc9,964741e8) -,S(8c41627c,185f17e4,28a01b40,27980e6b,ed62ad62,17c9f8a6,26c329e2,2fc37117,75ca226c,3316a552,37e8a1e7,483f73ee,a36da441,c732dca7,7d95b7b9,3a3662f7) -,S(371f0105,e43aaa30,5cc7099e,9a13b97c,2d75c26e,5b50b11e,7cc6283b,27728d27,c969dbe7,d0976d68,8cc64312,4538ead,b1194426,cedf149b,293b80c,6ab3ce99) -,S(5102f59a,4238a358,f8b4d3a1,85d864c2,d94aeb83,7a8f3e03,541ffbdc,2ccb1710,9e14c4f9,adb63c3f,4cd30606,cd41cabd,bbffdc3,89e996ce,91522093,85ef1445) -,S(ca21b6c,fd40403c,78353c7,836162f0,a7f57eaf,bd4a8cc2,6df2baa7,1ff08beb,108a3c46,47eba55b,3fd9f2ef,751edb0f,d6b68482,1424bffe,e6ae3e58,1f7f12f9) -,S(d9cd44b3,ff40d19c,e8368bc8,200e3dc9,7ec3642c,acc40769,7c94e68a,31d775d9,b6b6fb6c,683ef701,d4cf7101,79de4af,fd7c4a1b,5babf3cb,85c95eb,485f0901) -,S(9a1354b2,cbcb6888,bb564426,71bd4904,510da508,3fcc61e1,4fbdf44,15a10360,3f5f5291,707c48b4,4da3a2a8,93e24037,bc4927f3,81dd9b9b,710e8b82,874f953a) -,S(c5e55e0f,271a81c4,ae7deb0b,ceb0fdbe,20fc60c5,38692941,bd50ab9d,ad0fdf79,138a0f35,eab49301,7a53e7c,c62ae93a,85ed9e7d,708a00ae,cb10776f,fdc83a63) -,S(5ebc2f64,7f66bd3d,2290e4dc,6cc5f662,7c67ea72,599d2c6,9a004aed,9060f919,68f7dbce,df2085e2,27cf7920,65369637,3ec1e860,b10c8f1e,56e996d6,854659c) -,S(4f28eb9c,7d060dd0,5051a5a7,9a79c960,161d7081,d3a58b2d,a421075c,cf966e03,ec378861,5434741,bb2aeb8e,4a2afe78,44849f3d,2cf12a6c,2eff3e05,d267fafc) -,S(f50e20d1,ce113e09,850c7a9a,10b347c9,9fa039ee,57ec85c0,efe15b4a,1a83fe8f,4db7c231,90df41a2,8218595f,61407f20,cee46478,27d54aa9,4db9bfc3,fae975be) -,S(cce6b2d0,1adeab95,dd78cdf2,b55882bc,79de945c,d4249e76,ab2841a3,abeff5ef,1d690674,1312140a,fdf764bb,560b1bd5,bab1dbaf,9fa26bd5,604427e5,34626e52) -,S(55a65174,fb10557d,2ecc7312,15afcec1,e4830be5,2d34bbbf,bc80ed6e,9f2d8475,c69795f1,de1e537a,970dd412,65493806,3f0623d4,e7353eec,611c8917,278012c0) -,S(78221cfa,7b4db3dc,7e22779e,97ac8d46,d0c1d819,76594ab0,267ed28a,6127f290,8ddcd5ed,fd8e8c62,4883a158,2eab5652,ace0660c,2e358b66,3ad53e90,cbc46a54) -,S(9b985039,441ee434,ed4da39d,6010782c,9006cce2,8f92ff96,2b2d6fa,986ed178,e1cf85c8,7b537b2b,78bf67d2,2d9388c2,8a50dae1,73f003bb,85fe5f9c,12c6cfa4) -,S(9aa2ffb1,4a9e48de,57db9d78,d9b6757a,6c27e7b0,291dc4f3,8ae9f204,f7edf20,771c7be3,78e0f794,fe0066ef,8592952d,8f80d7d5,2772ca11,5ff8b7f6,377d1040) -,S(d1059083,66a0b463,17c510cb,40922a0c,949de251,6d80ec02,1e359a89,c6937e1f,84053a25,c9ea4414,a897155c,c45e0da,e5e6f2f,aec780ac,99c41545,fac8630e) -,S(1f3ecacf,7456984a,fedc2d81,2a81f7f,1ac58ad9,c70ba7c2,3e7a2ff1,f9c5d066,c6add8fa,2bfd24f1,73f4539e,f21681f8,15f1f362,e0f98d94,cd435d80,71a23e54) -,S(a312c709,a16d0cad,25551ece,86c8f947,5e504d06,eb3524fe,569cdca0,da2c4371,865ecc2a,ea04c5da,2089ea2c,66b5bb84,8c1fc29,ac7bf969,c778039,b3ae7b03) -,S(f21c4675,e829ba78,fbcf6410,9c2eed38,8c3493db,1017d69d,953f32f6,744197af,fd2c673e,43377caf,5db0ee06,1a37b03d,43d9373,482d3ef2,b37f74ad,98b2f57) -,S(116174ea,2a029a02,fbcb2eb6,1851ab31,f4836933,a73bd426,8feed7c0,18865692,2123d027,e1cead9d,b5fca2a2,d6f5d1d5,25cf3855,44b64352,ee772d4d,d70aaefd) -,S(358e77d0,919e4c6c,f64a2117,357e72d6,2334fcd0,f5e7e60a,962335fa,73f9d663,7ef8d620,6f99f403,10781985,988ac7cf,dcf5cdaf,a086a0cb,8b5b6eb6,7837bc08) -,S(509f7e0d,9e81f146,39157e20,3165faac,8056deb3,a813460d,b86c6daa,baa33fa9,55148e1a,340eb6c4,e6a8645f,93f1ad3b,fd12165f,c3bff090,a095b8d2,a0db6ea9) -,S(358e325c,185f0e26,1e9e30c4,9346f21c,a15c95bd,438020b9,ad9c7e6a,d2a4ed09,5fcc074,c97715b2,812ef690,3b3d6185,54aa11bd,34789b3d,97f9b65f,2d18c4b8) -,S(1e1c712d,bc00af2d,37f37e4e,a2589e02,e314c310,47890d26,8d36be3,dda2fc4c,4898f9a,e3136bbe,36798cf5,ad30b38b,974e7e75,42d4c14,5bfb1f6a,490655dc) -,S(a6516f9a,aa3f79b0,ff3b794d,c80a9590,64e31720,7361b918,bd797b57,23ffcd1d,c5934c6b,59f3b830,53f77b07,47c7c312,812373dc,ebdbcf9b,ed550300,3a54f5d4) -,S(e46b48d8,8b1e1b84,b9fab824,3044469,50cb5633,da599b79,295011b8,b1098155,43e9ba24,4a339976,e342e551,25974350,3e7c8a80,cd950a80,a5d79365,b0c94f51) -,S(ca7a5099,97a9c2e0,625105b,1df9e714,e1cc2d40,1227400,e583370d,3f65aa0b,dd8ca4e4,d2eecd1a,20d994fc,ef7cb0ef,19c61844,cd2ce039,b7a1eafe,66e1f071) -,S(326b5ec0,d29b576f,111352d4,b7786c40,8486599e,ec01ed0d,a390d586,96313f08,f4a3f171,a4ac654b,e7aa6063,3d5b2a0d,c2d5d3a0,3da4d264,95e828a8,1011d384) -,S(b762982,54f5c75a,a557038d,bfe9bad9,7c5bf8ee,e512fe2b,39293228,e70d306d,8b808f9f,b36e3e86,2c75bb2d,d7de8be,cc85c75,398496fb,f92db3db,143606c5) -,S(8bd624e1,2b1d36ff,dde50a09,6f1a811b,ae66f1a5,790654f5,ef79a21b,872286ca,6687ea2e,f4538961,b6731c74,744234af,8bf6a2a2,170544d0,fe9b8057,ad1f02df) -,S(ed25eac7,2a9f9290,bd414cc,cf846c65,509d1c33,d5573da4,2d78d25d,5de48a9,556fa9ed,2710fd03,b6d1583c,682cd7bd,8705a9d0,1f73a8b9,8f3a1eb5,d89eaa) -,S(f1943b6c,9ed76a84,9c67bc94,c755fb30,e8facc1,de280060,df4b9e7,8bc02bf,98c7ba08,85dc4e0f,6acbb646,42cb876f,a3156232,df1f84b0,4818ca56,882a40a7) -,S(c5b60b14,2de3ab8f,b0c24276,dcedae7b,83422821,6ac8ef39,1d351832,a5e9e5d3,ce86e4da,1174e609,f55e10d9,14d4a5e,33259578,e07c1260,e912acdf,9eb5cd69) -,S(b06638e,706cfe63,3359647b,253f99e1,c7778200,c168d4f5,92e2c409,493755ab,e6401fab,1b4d5229,136e2493,39f95357,e16dd37b,87e7f69d,3e88a383,cb44bbd5) -,S(cef8c1b5,486dacfd,29650ea5,432fa563,f0ec5fe4,6814bcd8,9f539b7d,264b14cf,80cc2c1,8d0b0be3,939ea,761d7281,5ed4fd2a,b252d66c,9316aac1,1a5a2fcf) -,S(f616904d,f868f2a1,5fcdccac,4198b1c1,62defb40,269754f3,8e546da2,4b85d7ce,fb971012,344024c9,f0bb93e0,b73b31cf,de8b4d37,aaeae3e4,7f62633a,7b8255b3) -,S(97386144,bc7e4a7b,33a51697,902fef4d,1613d8e5,ed80a599,a59f62c3,f98632e3,bd12d584,58429939,2dd834a9,5431af27,8e56065,ba79bb6a,5a806d36,cfc16b4) -,S(946f130c,7a70fa00,f403a56f,6656b279,1eb08ddc,561311b,551ce437,bb0200c8,acd698f6,a5037e60,7f5a923f,3af05784,186d9794,a7bf7105,7a66949,e1945b8d) -,S(ee0cf184,72c453b0,c38c064,fc0d2589,d5f1afc3,3423687d,91740bdc,c3929230,d817775a,7fecd397,e954db12,fca24990,8c773c28,b36e991f,79c78264,9fff8dc8) -,S(f335f7fe,9542a587,9d48b4f,4ab1287f,ef007289,4d93bc21,23463a77,7d535d7b,336e49a3,2465d29,35389c06,d8eafb4d,7639dae9,a6b19bf7,45518502,e3350283) -,S(55bf8179,4fb37f8d,dcc200d7,b76a9040,b1326d6c,559d7f06,f0eb0e0f,c97e7739,ca33cf00,79155cc1,e902ade6,f7d703ed,3053f6a4,f49d0866,32e930a2,afe69bfc) -,S(dffccf81,6143da46,5ee2195f,abb6d943,1033b901,2fe0c623,49b7d6f6,29de29b0,9bfdf3f6,e1dc4ae7,dc29fc06,f85e1588,c04bc39d,5fded90b,bfe75b9c,74f0aff7) -,S(b9748c94,25fc6fa2,fe5c1395,b556bb12,c435bc11,2e8f577f,3c5e7d82,3539dec3,f5238bb2,b995d23b,5e96b233,6d5141ec,f76d31bc,63aa96e3,dfaca8a8,c94007a2) -,S(92c43c54,e951b157,38f29e33,5f52ad9a,2c5349e5,fa6a39a3,fb615878,ae97f7ca,7c7a6b73,dedd1bca,308924fc,6364b62a,bdc4ae79,d68a62bf,71bb0195,612b4a17) -,S(b1937ea,25995e55,ee1ef139,d7a58923,5677afe9,f4726d96,40b66b0,d21eb272,d0f95a57,544ac7cf,e6c3e0ca,5e44494c,5585c503,a8ea9919,5a993180,cf043dd6) -,S(2c1cd64d,bd7ee24b,2bc5a6b7,2009b788,e2a5047a,8d10dfc9,4a46d807,c133f457,fe8a63df,ce7d7a4b,e7c31a1f,5e68826,7a9449fa,9e9ce30c,fd8684b7,660aabe3) -,S(4ff10a78,be6ea8a2,b6830649,b0a403d6,6d544368,6cc854ed,447f53fc,45004834,b3cb30c3,56d50596,2e81cf5b,f4e2db0d,e43384d7,28f5d8bd,b362d287,e58765d8) -,S(33f55b66,6c90665a,b60a7c2a,c714591,f877e8c8,517344d,9da03558,f43d28de,399848ab,6aa95ed5,8ae0ea80,c93931a2,af146754,385edce0,8c2a4f64,2d5163f6) -,S(b9712359,5a7237eb,18b7cc15,ff2d6be,408da66d,5885a636,20887ab,340d3e04,a283a3bd,643ac5a4,1b3f0ab8,fc693146,dd125f88,fa87cead,817788b3,be72363a) -,S(d20f9067,6efa9435,f602c1e9,fff7338f,5a4204a5,4d984dcc,f0ba5fc1,60a1035b,ac3a3c7a,452003f8,7244406c,ea315175,ca1af26f,6645486f,3faae77b,8f404139) -,S(322d6ea3,157c9f0d,444b2d0b,d072e192,81d8b3e0,3ee2ef5,4e294b53,fef41f2d,838147f1,9dc12dde,676a9e67,6a638c42,6e096df6,ea62ba97,ec359b4d,f92936b3) -,S(95925c08,68341b6,b7564ea7,bae00b0d,1d2bfacb,94aae4cf,8f29ed9e,fa0c26d5,c63edb9,13152232,c255557b,2207c2ec,edf14cfc,bdd246d0,2b46f7f8,76b92130) -,S(7592aab5,d43618dd,a13fba71,e3993cd7,517a712d,3da49664,c06ee1bd,3d1f70af,554ee877,af74284d,5ac0aef1,ccfa8ab2,7a9222ae,977a1b45,7d79d386,16eaa410) -,S(ed9d298b,e13eb71f,8631ad31,1b391680,8062574a,6053f503,671d9a59,1209e0eb,97a9abc0,dab8886d,9a07caa3,f40d87d,7b479efc,d500eb6f,e54ba1b8,9d85c3cb) -,S(cdfef636,a5900bc3,bd28daf3,308d469b,78ae69a2,ffc39fcb,9f8e4942,fa355fad,f8338fcc,54c0ef4e,a46a1c25,591607aa,f4f6c7c5,378f2d51,79f80e46,520db6d7) -,S(f638cf22,ca3bd6a,ca7a8fc4,26d9f5db,dbc0943d,6a587584,8ca52e6a,7949db49,56a267dd,8309eab7,90b49003,9d595141,653a7926,9fd1f732,f3691e0a,41675295) -,S(4340fef2,9b1e43f5,3c76cab,163920b3,7a66163a,bc942e1e,6387a2b1,8f14bd1c,2d5a782d,6889d353,c6c908f0,b6f7a9dd,59ff2f15,8bbb9eb6,ad62bc2b,832210a0) -,S(78af8680,5e3db13,cd2c01f,beeb826c,1aa83296,c6ed1a30,bf2822f1,a9b80991,19c7ca36,37a6ce91,2680d95b,6b94f835,ec458cdd,86206a2a,49d41af6,248c3725) -,S(d87e590f,e6a4bef7,54a831c0,13b3d561,72064279,38b96d49,58a2ae11,c9c41ef4,3928a93a,c9b43489,f1fff97f,f8ed4ebf,53b97aa1,b50896b3,e30b40b9,be1d1dc6) -,S(b59d19f3,69c547e9,4155cfd0,a0b9076e,85ea8569,195b8a7f,630a8446,ddc54c32,b8f5588a,ffe7abe0,e2b83d55,28162c5f,2d50827e,c44a4357,f81ff085,da661865) -,S(34f643da,7cd59b00,3aa64cd,81c143ab,662726bd,5eaf543a,6d83d30c,60f3ee78,41574cf2,91a7f573,5a0bd29b,3ee5a36,91906c1e,3fa47b22,d5204446,f4501ee8) -,S(56ef37d0,583e9de4,33f78757,dc31c968,fd007bf5,6b05db4e,cac395d6,233dbbf3,a140e01a,b5c898f9,10ae2807,53ba14ea,ba8cb5df,b9e9629a,92c14b9a,df5c9286) -,S(1e43f34,815b568b,1139ca5c,b3a5dd42,fc54dd76,78454fc8,7e3dd00a,edc957d7,5cc38274,ac96ee20,78a82d9e,64dc2bdc,8e947afa,d043302c,85d724f7,7e334cc8) -,S(ce79e49,35d2db7c,d9a9046d,3d81b7dd,f8b06c82,98f78eab,ad93062f,c339a952,fc2f6eee,1b90626a,5ad8c494,3bc3cf5b,8765c8f5,fdc05dc7,fffa08a1,b84f9686) -,S(b4144804,ca862c26,70cc3365,e1a00cf8,f6766cc3,4b3dce2c,76c40c31,86fe4fd9,e4368a1f,ca9b6e00,a3f752f0,3a00fd4,29cbdaab,5e2a04b8,7175b9ad,51b2219c) -,S(eaa29724,7406f824,8e79cf65,ced49d39,5416341e,c1bc46a7,b71d422,1f4fd39f,68e7f81b,e3b75cc3,de4d9932,85e21842,d0d4b6cf,38a1d46,248dd28b,a97c14a6) -,S(4e2d10ff,1f7288bc,3b8c6caa,3dcbfc72,eb7371c9,f42c6999,e7a2ec50,30f5b6a5,68da3c5c,df2a4fb0,a93515ca,3e417d00,6ba793f5,eb678f82,be88200f,a5a8774) -,S(834f21e1,114dec96,2a8a4b45,c67c2894,7d073b94,457c1adc,e009dda2,230659f1,e9fa61b6,edb5a0a0,2f7acb27,d04a67c3,39263adb,6320ca6e,f78ac7fb,25adc89c) -,S(a84b44ac,a0a64455,a97268d7,cd3d68fd,c43caed9,f9bdc381,ece7139e,30c7d0c7,2f903f3b,74e702bb,d2fbde43,f919af7b,d1267879,3882cd6d,a05af259,bbf6b74) -,S(21219e06,98bcb977,47b1df66,f9e0fa6e,600cbe7c,bb432cbd,d413481f,241d6789,7a4388d3,c8961874,a897d968,8b5d3266,2e6970be,324bb736,aefd1892,70954055) -,S(fa514e1f,93bfccf6,88b4bbdb,e4f49879,7b946549,82a27562,6867b22f,9baeafd4,ccd48215,52572b4a,9e087b51,8c930e09,2c2f6156,c26a730a,478f257d,a4f91b74) -,S(b60afbf1,643099f0,c0533a4a,99bd8c2d,2204d4f5,3f2fdffa,4cafa02c,79451ffb,fed8f90,1a029926,cd4b3bd2,76bda6e9,d321e006,3eef3f43,886eef8b,4b21294b) -,S(f29cf9a3,196ce34a,86efcca6,554694e8,17c2b765,39c6cdef,c74850e8,a7ed76cd,5130863a,f7c333cf,b37f1bf6,2db5bacc,994b2977,9951e8f6,2471129f,88c9c5f7) -,S(9cd9e23a,cb00bfc5,1a3af34b,3e23f1d,d8fe314a,322254ed,563b9275,c5084e4d,ecf0235c,c66ea710,151d6c1a,17b31705,4f31bd4c,f8d2a77d,4d36fc4e,1298e1d5) -,S(56f889b0,2cfa048a,f96d99a6,be56a282,18ed6691,ab2b25bf,f3d3b6f5,f6e5d65c,352b20ea,4a2372af,f674f824,8dc8fca1,bb8ecc29,ea0c8d92,1b7ea07b,241fe4bc) -,S(de32beb7,f8fad8fc,16d69a7d,d3def556,8e2366e5,246bfdea,16c936ab,5dff2a08,d731f11c,93a71c22,46c2bd06,fe265fab,eaa216cc,b0de1acb,a7c004d4,249e145f) -,S(85ec7dc1,dc1729d8,c03dfa58,fefaacdb,7d12dc3a,f984a693,968895e,2a6ba256,523038af,8e9aabcb,f98c73b5,afba31dd,89e4b9f2,ba1a841b,194b0b45,9a4a747c) -,S(f7948995,60528ec1,ed7f5efe,42db8bf6,e223280e,2b26d4ab,e23a5caf,41e2e141,9f7594e2,96ed1f98,86837e9f,da8d6d9e,58871e56,16cdd2fc,dd6fcb7b,80c6ff98) -,S(588d6fd3,b4208825,3d76e8ee,f01a93be,866bd53a,e228c137,62199ce0,f3454f10,a5fc9653,3e41208b,ba3f29ad,e31b7e32,6320b81,ad0ded2c,6d922a4b,b42af573) -,S(186fe08d,bbe5c8a7,56f87d4e,8976777b,b01db294,e834659c,bf423de,1ccc7443,d99ded39,a46f7820,3437a93a,435fd0ca,29f12e26,a6449bdc,a256f99e,9bdfbdc0) -,S(e549cb08,3055abf3,3b7eac38,cee13336,2af22e98,2f576bb,5a06d5de,59bd3d25,cdf37f20,e7b51483,6641c7f7,afc35ae5,5ababde4,34a945fd,4fe0325c,7d332381) -,S(a4e42afb,fd7f5158,5c86108f,cfe84b58,b930df79,f53a86e1,8ac93389,224422b,e9f8e1b,3963102,b58d6177,f915d7ac,541e551c,bbea3e2f,1ea47960,ce1e30) -,S(5f7ed844,42022f42,6b09e9cf,b7750fa4,4755fba9,7199fd4e,d09efdca,d803dadb,91d5ded,d06a8eb0,9c9592fc,c9096f1c,e852d9c3,9bfcdadd,ccbe1bdd,2b76ffad) -,S(3fac4743,32f064e1,b33fa22,3f67bd15,91dcf7f9,afa38f1,868e180e,c2938d66,45744e67,6b203799,3386d10a,b11730bb,eebf270f,9ea65920,6f93da61,e2aabe5c) -,S(5fb983ff,f058d214,2e4d13df,97d8e784,d4b10e0f,6a18c6b1,90e64bdf,fb7a7aa9,33394601,8dc540cd,eb73f73,a9733d74,ec581181,8a6d58e8,3460f1a6,8ddabd6f) -,S(baf35c3,fa939a2,db15eec1,ab083664,9c6e941e,19d3e0e0,43e0f5e6,df41f88a,42583cd3,e53fa1bc,4eebdc3f,e3b8b069,9de41445,54fed966,214108d2,f68e9201) -,S(97641f5a,a51e7ff0,f1d86183,a3fb3d60,4266c4d9,acdb9f9a,c704a05,809a8602,134ffa32,aa9fbdbe,d8d82fc9,1cfa78f,1ab169fd,459da39b,5b0d3287,ad9517dd) -,S(96a3711e,acdaf6dc,5adaa8fb,4be05c37,f59febca,1a876a5e,e23c6b55,2727292e,8fb0cfb9,681ebb7b,5e1fce0e,67ad5d81,34be9123,56100e96,b82ecd3f,a5da4392) -,S(ae64428b,8e540c6d,28d38892,6136320a,9f9f16b0,3e9d5e2a,14faadef,4f154b0a,db202e5e,b9bf73cd,b9ed5193,b0ff59e7,cc68aded,6fe6c2e4,d5b79493,fc118aeb) -,S(2c5932df,65c0c2c1,14b532cf,15b48433,e16424ff,ba87438d,42229075,6cc984fb,161ef8c4,b908a056,d395deec,38b9ff4d,1c643628,2ceb1e47,f59a2c24,c7d29130) -,S(76e21c78,6937ba69,18252d56,3ebfcbfe,2415389d,bc692071,f9c48f55,7aecca3e,de7786fe,9db47d61,e3b61d0d,49309fe9,ca634d28,8d71aa77,a3fa4efd,4533c8e6) -,S(7170dcef,ca8a138d,1d20b346,6afc6a46,99df363,fc964a36,eaa70805,b267900f,196bfd39,476f1455,98f89f7b,f870f8f8,440562e4,623fb203,3b36d5d,d8c0bb8d) -,S(98eddeb0,75bdd245,aa1fb466,ed1e89f7,61a95662,e35836f2,e6907c5b,691b6ccd,af3fb5f6,b59124b8,c9c2ddc2,108a3a2c,bdbcdc99,ab296814,731a841f,570c91be) -,S(bf42f806,59ae606f,a5e36fc5,c58379c1,8dd1c34e,fa98e67,68bf6da8,ba8e8849,d343fb70,6e4adb94,46f49578,26bae8c4,ca74a0d1,21cee98f,26be68f8,7555b8af) -,S(40c1c4a5,891e8dc6,29075c36,56249fc2,c42fd65c,8c338a0,d82df955,4662e1cd,667223d0,e68ef6c3,7195d819,2bcc12b3,f2025327,3a05703a,e5aa10e9,cc689ec3) -,S(162dd310,c8e3fe4,8384cf1b,1a0a2d6f,bfd3ef3c,5492fc92,b921133e,8f883dc1,1f2311d5,c82f02b9,f7197685,cf490e1c,3d0ebf4e,86ea0e21,a653c8e0,db5cff0) -,S(ff0f8146,89eaae3c,f3f302e5,1089ec58,5d63c4fd,5157bb3d,bdfc7e40,cc6331cb,4dc1fdb9,4eb529e3,bae54973,778d1daa,f8814cdf,5a3b0c2d,ac2b5647,551bf2e) -,S(143ae674,b011b557,2f472b22,44c6d9ab,14b3e641,54f4a033,c3ea3917,4607b78e,1528d582,faefba2,6018820c,a03dfd7,ca20298a,e199c99f,db9cb421,3601c35c) -,S(f3adce28,8fffd45f,96fa0efd,32974d98,4115a80e,cd6b86f3,5e17b017,8d9009a3,20202f00,96329bb0,69a0915e,494a586b,805580a4,eabd4ba7,2d20665b,4916a20e) -,S(d2270829,e2730d0e,2c8e6bc6,fa4c2247,4904ad22,f44fb2f8,5ad07558,c4d8cccf,d5a6b4ac,9d5bf669,5989741d,f262e412,27c66c7a,ae067a93,c6302f5e,8879a3bc) -,S(26d17eb6,7d9bf2a8,45c57a94,82bb2f3d,8347538a,65c9f567,56ecadf4,352964a6,954af3d4,7d67c345,bcfc4a52,a49aa70,b8703d1a,fcd21c6b,7f7719c1,e2068fb2) -,S(e4437f8b,e104c899,5cd1618c,e5ee7d10,36a52d99,31346476,bf68f21,e7fac74b,d6c156d5,b8256e6c,1a820dbe,3b56fc8c,f9b015bd,b81c756e,27b70db8,d995cb81) -,S(8932e04e,96db6079,662b63ed,29b5a39d,ac5bb51c,d1ec70,851474ef,a2d3c1d4,5437e77f,e030225d,53f5166,8c3551c9,fc912a0d,a3bd336e,c0587544,77e58541) -,S(fe776976,465b86c0,5b2003c7,36c8141c,933ed0e4,5c6dfd0,c7c82517,16617b26,b279dc5f,d576d506,d302b0af,359ddd50,94364d3e,255102aa,472e6d9c,c52aac39) -,S(6c60a4ff,b2a29224,5c84ecbe,1633817d,f69eb73c,a6b9f72c,b86fc91c,535b45f1,278dee6f,814bcc1c,70301a51,f9c7853,6489af2b,d23d6223,1b55cd29,2a2a0a2c) -,S(3132e58f,625f902a,98d556c5,ec9e8617,a955beb4,6e9c2a81,e121e473,9c9af04d,a5880964,a2443c5e,14db9220,446904c5,cf0a957c,945c5006,9438d869,45a9e461) -,S(b05cee36,361a9bf6,eb9003fd,c8d38587,640e180a,9de822dc,57e5012e,34903f6f,fb473886,29519a28,b745ce16,d625d85d,26fe21a2,30d798c5,305d8e82,545c9a5a) -,S(e202120f,5659e580,7a14e68d,e3aad7cc,23cd2f6c,abd86739,3a05f16,12005e83,49928b05,b66af992,d937cb4d,c05fbaf2,a70e8fac,7c081544,849d55e,fada136) -,S(57a91d89,2e5409e0,b07e68f0,450614cb,9a9bf0cd,8c5b3459,2f198633,c7a796b,47905cce,59018fa8,baa612c3,124b1192,1dbf7706,c5d8d16b,bd5c1e9f,8498e7fc) -,S(e092c40a,3ba465c2,d59e7c5,8265ddde,91c0468d,67428ee1,dd153b64,a5a7e8da,83f4e2b4,bdfc4248,2d4ab1d3,13b097f7,baa51411,134eb042,feb26f71,5bffd39b) -,S(73a3306e,7baa4fc4,a081a9c2,c335d3df,7c1ee84f,f5a46554,f78a6009,1de0ab38,1f68c8f9,2022c326,e37a7043,9552191a,3d93f684,3af0a235,bce893d,eda1f938) -,S(7c7a79f8,6e904961,73552caf,4a1401db,e99883c5,a39e493a,6a6eabbe,5f3a4434,85ceb252,e4883931,96c8ce8a,c0b596cc,a2670981,2c293554,15e17f8e,26e869bb) -,S(6a9df561,ce4ff772,b37054fa,e513657f,19f03086,eda93918,623a1c47,84a37788,bcf0274a,d9b3bf58,331ba398,a6611fed,fe719867,106eadb4,2b25b623,fdb65280) -,S(fe7bb24d,47b3adff,1c545d2d,ad2c6aff,81934cb5,bf2299ee,f3f8c53b,ff91c950,7fe65f86,9d2623c,930c27d6,f0a292cf,a881738b,4af0c5b,efde5c40,8a574e7f) -,S(26d1d2f2,7944b77c,290ba60e,17d05347,82ce2b64,ae815453,1da42907,30407d3d,ec3c5024,3106000b,d0b2372,53581384,51b768d1,d5aa206f,4d1055b4,b4f0f495) -,S(f00e51f9,38f91573,4ac563ff,8ea44de3,fb85cf4d,8f034806,e6c096d,8e73e2b8,7b7bffed,3a39a491,d3ab6a13,6fd88e0a,5854081d,21380c70,3c596771,a22c727b) -,S(73e15472,f42f8750,93abe811,a4d4bca8,8bd179d1,4e3e3b30,9e011e27,37cfc4d8,392ef4ae,58321768,1106426c,9b00b4a9,c53c826b,84bcda34,b5d0609,f85b9231) -,S(ed4667a9,aff30464,c851d86e,479df8e4,d29d2348,edaf8333,a7faf560,a9568092,77367875,6892d42d,469a9ab5,ff577e0,6d9f4fda,679882e4,3dadc7e6,3d49bb0c) -,S(d6ec16ab,10811cbd,dcc346a2,64dbfe0f,51066f2c,79034d74,af5b0ef2,541dde26,981f1cab,7ac7be22,9a91b733,6c0b89bf,4763b01e,4a1b715e,f4857e9e,4ad0527e) -,S(284ef47e,691931ac,8241d92d,2ee5b717,3f762ef2,bd1f48e6,8dca4b53,ab4c593f,ab739ee1,e6a7be47,83e1288,7ffe1b6b,b53a4d2e,3bfad3e1,c7ac5415,1bcf5e82) -,S(530f9e7,5a267d0a,fc3ba53a,c49018ef,44b490bc,835774f6,c6cc3f87,8d505c3,630c481e,44e5e9cb,cf6d7fba,8f7fded4,bee9fa70,4b88a8d3,6e2b3bc3,4e85e3f1) -,S(66a9b4fd,81d0165b,6737a4b3,8025d2da,ef9c4d20,3c49a2bc,1ba4d59c,eaa905f8,2770c44e,6a4dead9,7dd7311c,195d3051,12c86bca,257955f1,21b7b1cd,4e525e8c) -,S(25812e7e,dca47b64,9b18d739,7474de25,39bb7898,96ddb94f,60192135,23a289be,4bba3d83,72aa76e,6ba76f7f,18cb8644,788d3ab8,b58d0e5c,795c6213,6f17e2da) -,S(3c81be70,af162448,170f88b5,8fbf587e,df1a0e8a,3576cfd7,24acba77,dfb29608,ab16e48e,da59f480,7a0b5250,7102e9ba,ed9dc9fa,e0de8700,27bd5ff4,2aee13d4) -,S(ab626dcd,a5142933,ece82c8d,125aada8,39626e90,85c57525,2fb24f76,e0d6e39d,8add774b,34fa4b1b,d571f2a3,4d8ebfc2,bb7be73d,dab73cf,e7eedc01,764abff6) -,S(47f25106,120720ff,8cad6532,1a3e2873,aaaaed57,98e3933d,e1ccfe0b,f36bd85d,f6d472e,729512e4,ecb74ea3,f96583ac,cb44e013,ecd0bc60,c38b16f9,20585b60) -,S(6fd30299,f7398f1b,3c538d59,71b8bb0,e1640926,752d0842,36148b9f,23c26b1b,3b8d6166,a79ce235,1a2e9c4d,c5c89ff5,7810bef0,277f3d33,372e05bb,ba6799da) -,S(dd5b07c,784e1cd6,58c51ab7,45c4a09d,49db1287,dd7871e3,f449bd66,4a02e040,b26dad8a,62a491b8,dcced2a7,c0feed9b,6a04597c,d8a0f857,a4731078,d68d8659) -,S(3cf5836,104b4227,aa275e5f,16b84bca,15b61a8a,700b56b7,dff2adf2,167fcdad,1cc6f65a,2cb579fd,f6812340,88018dc9,445af726,2db43b5c,e9e49e4a,ce00c9fb) -,S(683b5455,8b9421c,c3aea163,d74c043d,d4cd804d,23857f41,3e01d28d,4919bb58,1bbe4576,2cd5c056,8add6943,8111cfed,691e2369,55022da,17cfddbe,79a11f0a) -,S(d78661b7,897a40dc,5f42f7ec,4202ae53,e83ff0e0,d73ce7d2,19503279,e43b724c,465299b0,e3f478ec,fc3db82a,61d5f290,aeead2fe,d0ec4a02,6652b29d,cad20b21) -,S(1258c664,fc15e794,e64dbb87,b4eebf1b,32e89e7d,50ec114a,1afa5506,19e15a21,327c4a92,81a73880,70d1a7de,c2a0e5c7,28c5997,bbc21571,94b0521a,141be0b1) -,S(f2d04fb5,1cffe2bd,c6e43cdf,ae7314c5,387f4dd2,4bf7fbb1,a6ccd627,86e8be00,89af3f8d,435f2152,8d32ee47,a86a2ae1,78d3a7da,c27ceb37,93250a8c,27061c9e) -,S(b67bbec1,4ab23ad8,e52cc402,def0083b,d21551a1,92a9df6b,b335481e,3f0dfb08,d6ca6bd1,93838993,5284528,56587554,3757cc13,fee01fe6,698b30f8,10a64a23) -,S(1baef1b9,fa401fd6,a053ce90,f2d661b8,8a466584,83a8489d,90d48312,2b79235e,28a19a14,a2f7817d,922b3872,cba558ad,bc1a69c6,c0b65ee8,3352494,a31699d7) -,S(6c0f066b,23623a48,b2b6a746,801baa85,f58de56c,e5287c79,c3c10ff1,b851aa8e,ec837256,84cb0f8,e528bd94,e1c86327,2347a479,2059f357,4ccdbb93,15ff0868) -,S(fbd5bb09,65bb9d22,bea6d6cb,7aebcf28,a0c815d6,18b79c0d,94913dd9,f63619d7,3303574d,5e605e5b,fe298f77,e20f3f6c,60ccc063,37a29c7e,6612dfca,3f00b924) -,S(2246042a,c4b22334,af6c81ac,8106bd1a,f8bd5f2,8dad88fe,7e568fa0,b35b1739,1da0d8eb,9c10116f,ce29bd9,61f92e36,9e538282,345a4f79,7cdabc70,5aff6e7c) -,S(470a914f,2fff2d37,835b3caf,542cf50b,9606cf6d,fd294c51,5632d9f3,4182bc4a,6b3805a8,d2c74856,a5be3cc9,e9c6a8eb,4398c606,81ce12db,b3a58660,1d426e) -,S(4e03f50b,ffb6d933,4282153b,a3f909d0,44bb7a11,50300c1e,cc8027b0,321b4be0,596c58ae,963e71ec,f1fe8f9c,b4de8cbc,9149b125,31e83e0,95f6e5a,b08c504c) -,S(5a6c4fea,b806bb76,191567e9,139dde28,188a26b4,a1803b7,d999278,fc57455e,6e81d07c,6505366b,c28ea476,a718e5f7,353d73c4,2f551459,d59a7d7,82e6ce49) -,S(ed73c9b2,9adf52e2,1280bb1b,ef63dd4d,74f4e09d,1be56c3,a246dc37,9b29bd5f,e9917b6,19ebe0ac,c7d1fa5b,7c4b7c52,e272ad9f,2df62161,59dc87b3,f913828b) -,S(68c6145b,38cbf9ed,4af10608,503ca13f,710dd34c,2386fa99,bdf93b69,c01c04bd,c963585e,607d9eac,5016f884,df535a9e,e7cb74d2,2e0c1e9d,e928d7ca,3fedc73a) -,S(1b651863,927317bc,1dc6094c,3f5c91cc,92269a12,59879b6,a8439a77,b0454126,31c6125f,8ac3d09b,d8c1fe92,c31bf13,c42b1915,e7147cf9,1371dc01,e8f5009f) -,S(45593ccc,dadbde3d,456b74f7,a3b705de,7229ff20,90a0df0d,38166d4e,6a09c52c,13d6657d,89fd0205,3c2b9a31,1ee964cd,e14634dd,20d85866,a43a4ea9,bc0bd737) -,S(1409c06e,d6f2fa2f,cd532983,d28c2109,e4dd7c1a,4ce77960,566d3eb4,37927da5,dc05f98d,4206fdba,e3b69836,e694b71e,fbeda304,537bc623,90edcad1,460984e4) -,S(d9e08c6b,c307b056,d4323921,5426febe,5d6e5cc8,4eb73707,4e2f00dc,e85f4580,a23c1647,c6b47a43,a3ab52ad,da32605d,172f4de4,201834f9,15d5a4b6,292c632d) -,S(7df319f3,d3c2b6b7,3533a916,64d5fa26,5ac0f18b,bbd5e8ee,1aa15dba,bd62fb32,9120f6af,e023bb98,1d6d8d96,31de0814,a9bd169b,a91af0b7,9c3db58d,2bc9f8c0) -,S(1a94e587,38b9fd1f,93146232,e2165798,11d74244,9bad3711,a373445,6986d7a5,332a27b3,17eee7ae,fb4604b,197f2db2,fc32549,ad86765a,74820428,abe4352e) -,S(dfa2cb4d,6db266db,2a82ef8d,fc0cf871,4aefff41,895ff691,fa0781f9,1b619a47,c5e5dbab,3a28a6c1,8cf20fef,4cba62f9,d2a1a0f7,6ea7056e,45acfe4c,49ad8b19) -,S(c2201007,be6bf76b,5e82c135,2a6e053b,acf4e2eb,c10a417b,f35e4c79,3a876730,92408aec,b9ae4d74,3af97c15,9c387343,9a735de8,90d1abe7,c8d14dd,fbefa581) -,S(d45632d2,ab087f0f,9d0d4d85,26730742,2f25c794,efa3815e,33e8285a,1bd7edc3,b7ce3697,c4994fa8,2479e99f,9c9e4b1d,814e7258,da7ba569,5543d6ef,8d5ff44f) -,S(8cef362b,cdc292b4,885f34ca,923a171a,df6c25b8,f6b7cded,c9003b71,cf5df93f,b3910f34,ed8b7fa2,bfa4f1c1,9d41d99a,d702e13b,5dab6bdf,2608186d,d09aaf5e) -,S(247f7be1,874c2831,17d60431,8184878d,3a415ae5,59595bfc,7f17583b,3cbf9838,90e235e6,a779b4fc,f9521da,65f65091,efd513e8,df338464,2f8a7cc8,f1f30eb8) -,S(b8c0cef1,c8703adf,411dd0b0,acaa2b82,f2609348,e36aac56,b0148ad8,981cf568,a0419411,47019aa1,4b8e74a8,1d49a97b,45e7aaa4,54c0f916,a33472ae,1275f14) -,S(8e55776e,6e1c791,2aa6b43a,4dd1bd17,a35ab0d,aad792c0,ab51bd86,8208cf09,dfe4ccc3,a025abbf,c2d12bc,6d462e6a,cec7307f,6daa9c01,2c8a7ad8,70822d56) -,S(f1cf6d3,fc9d9824,4e122790,de390241,db813b70,c48b667c,5f05846a,c3ad1ad,4925c6ab,3952d1b2,35ef1ec7,7ae7a84d,75006993,b173a6f6,c8b969af,c3984799) -,S(b49dbf88,dce5ee49,2b4495ab,9db762c3,81164147,cacbc00a,9e56670a,edb9ea31,c0f92f17,ab5797c7,758d703e,fd288a46,8971f7c2,de8923fe,b8b7acfa,ffa9ef2a) -,S(d6afe2ad,257b57ed,15573c50,a25f7dcc,399e2643,9e64acab,9a8c9f75,d8ca362,5df236b8,6919b56b,17140249,16282b11,38d355a3,561c5b42,b47ac6f3,8d35749d) -,S(bb0284c5,f23365fa,5972a439,fcee4b4b,45b48a9e,6844a44b,53e12004,1ae8e89f,684bcc0d,e09e5932,79018fb2,aed55329,53221dca,6f14f493,6ae76099,ba265300) -,S(57e95714,8a409697,1b8be621,98a04177,c4779627,ab5a77e4,6e82d847,e64467ec,714bd1b1,14ce2580,7c6d3a8,f12a5375,fd8e7cd2,5e854c12,6bb519f2,cd443f13) -,S(b0c82f60,b33c3b47,523ef2a3,de804521,a1e14478,eb637757,d17526d9,1e713094,cfc8d1b9,d763f52e,6522f70a,c93f7fd9,23d163d6,5a82b2ee,ac1af994,a2cea63c) -,S(2ba76170,404785bd,5932c185,c6d98ed0,667d8324,ff7f85a3,5c24a4bd,553e1ee3,1810790,74262af5,607167d6,b55164d1,e56aef19,f3e2f307,205d5603,eeea35b9) -,S(5bd54e13,d508b920,fb1d15c8,27e0ca59,3eb1c85,a7228895,b5c9235c,6ed3e88c,d65d35fd,5607e193,ea70ab1e,4ac7d822,878017ac,ef3bd6fc,2b1933af,660cf0c9) -,S(b0bbc2d2,753bd89a,b2bf1664,e6cf212c,a590d65f,5664e694,7ccdf977,3ea8d09a,9057b6c1,a1078bab,a1419065,4cc67052,7225741,1f34d47e,47f09bdc,8f993c23) -,S(c1701203,3cca38ac,ddc0fe41,95452129,b38b4630,20e8c459,224e9dc6,cd3133a8,c495d87b,1cfb6f67,46c07188,86c08616,624f78b5,ebf4fb14,fb6b636a,f5557e9a) -,S(1e0bd20e,5f1e49ff,32287961,7fbc28c4,7c9fa4dd,d93532ea,74930a24,5fa21bda,2d407400,e98f15d,e5da681b,2472fa11,b2a5869c,66be1cd5,7038e160,43dd6177) -,S(5cfc223f,ec4c6618,ff12a974,8533a70,f39defa3,bc05f88b,3a1b158,317ec15f,7d928bd4,89e3719e,6386ec22,6c738b09,eb4468f7,b6718cf9,3da33544,aff21411) -,S(f506560a,bebd668e,57e514e,bad47a84,5da345ce,50ac0e88,1cccc2c,81efa67d,e2ff0bf7,c9c2a99a,bc3580ad,17f64a26,63111fd8,15bdcd63,9d9a7d3a,ca0fc7e9) -,S(8448fe98,ec887485,45a46e4c,449d0168,1d00dcae,5bf96ef8,306e7bd8,26c54f45,d0f07229,17500322,2dda8271,33481376,85b20045,f69d656a,66aeedab,ea6f0407) -,S(c9a6857f,db037c2e,36d5ca71,32942f34,2480cf28,a98644f5,6bc455ba,97cffc55,a69e08b9,8f678e61,6c0b8326,ced6f97d,f742d974,b68cd1c6,b798e367,8faa149f) -,S(b5d13f5,c611eb3b,c82f7db2,d89ab19f,b8fc286d,8e4699d5,3dc664d,bac4011d,27eb1650,7cdc0fdf,5b92493f,f2487d0a,ef2692d8,9c702bb6,259808b1,324b7adc) -,S(bf9ec5f3,2e0ed4ac,c001b887,18c29c6e,90218471,d7f1afad,75abb34e,da35ce44,13846488,892b4065,b79224ed,368c47a4,a1734f68,7386546b,dd837a80,467ef2d1) -,S(2c3812be,4d3b1c13,aed1f6bd,1ca6f5b8,893c5a87,ad6a8f2e,d6d92ac1,3a526e19,366b82f1,45d551e0,b7bcf877,db340bcb,1b11edad,1466baf3,24a94cef,3433aece) -,S(77bdef28,dc8ef6c8,7fcd0a13,c08a26e5,9fd17253,8d8bd3a6,f21c5c86,ca33f572,da66b0c7,bf3bd49b,ec1fec,aa580a51,6977ba8a,83f957ef,8167f69,ea3c3a1b) -,S(bc4a799d,3185877b,cd86503e,3f34c606,8693bac0,654eeb15,4effd116,8b71afe5,53fcd7f8,99a8190e,a7159c99,e261525b,f59abf6b,d331be66,4f7f7757,7255569e) -,S(301fd884,733dce05,6190e4c7,d0375078,6fccdb6f,2e13f9dc,e275c188,2efcd040,79e4f9d5,185b9f51,fd835cef,64be607c,312c910c,e25cb73,5de2c88a,51e25cb6) -,S(241b4a9b,be5e7e54,214d0bda,13719c42,133f8377,e50db2f3,87b6018a,814adb70,c66edc08,fa4fd22e,1f76bca2,7fcc00cb,a8ce2100,248b3959,3c164847,b410bdb0) -,S(be6f1639,68191289,3c5c1351,d633d51d,dcd28c16,f3294981,56ea1602,d8c79585,6f674a7e,1a65539e,a7f8a966,8f5fe5e6,1ade5da0,a543335a,5f7a71e5,fbafff21) -,S(c8b5008f,79c69e2a,7e209ef6,a2d14b9,b3f7bfba,b7fcb285,e237cb31,3dd3a283,1dc79348,6c3cf7e0,bc36dd7,46efcb36,3cea15ca,a63008f5,2d83ec0a,6bb54bb9) -,S(5014af9e,aad5ed62,4e997ec3,a796ad1e,b038edac,77cf27d4,eeda7ff4,c06c0998,e01d786f,b8faa1c5,2d44a77a,987b4b6d,91143953,34977151,1a488602,3189dd7d) -,S(6ffefde6,2c40643e,da2d4f28,4f28fcdd,b0845ec0,8d882d2b,45dadd8c,a7bb989a,8e2b183c,782d3a9e,2229e4bd,9a2becbd,ff0a5480,6a6f4471,7fb6fe5c,8411cc0e) -,S(ac762bbf,190e1374,d32a7e5d,b4c0c36,ad0140f,c1e92290,4aaff1f1,487d463f,ccd79f18,31016b40,a381bfec,5db6b12f,bc34d850,ed81aa7e,435a513e,5f3adefe) -,S(973496d6,3ec05c75,93244e7,b737b1db,d791a5cd,e828f342,7968eae0,e811cb24,4b2c9bc0,44e3351,f637ff52,5c3f34f3,d7420b65,2f57bb7a,bf573e67,25647533) -,S(a9d89166,5f77bc30,74357753,9ea39e36,c39ce300,6fa03429,1a799b34,84a15d32,d09c3a17,fdedb8fc,f4f9ce98,20635a50,56dd884f,ccfaa96b,8d0813b8,4b80e213) -,S(108a8ffd,aa2b544d,8b8a7419,f2421bae,cbab636f,60d6ef76,9eca9a20,a0c5710b,ad3e9fc,ab04ad58,a265776a,75f0e389,cebbb273,9df328d7,b125665c,d4e0249d) -,S(ef969d7b,c8843c57,bfc0ac6d,f5e4495f,9543878d,95120a36,de8c5bed,727c5fb5,5ab81bb2,26738036,b145d81a,1deaada5,d1d4d653,7b80b02a,fc1cf85c,361f16fb) -,S(ab825bc2,4d505453,f12dafb2,8f70b245,d74200f2,410f5162,b0ba3096,43c39b62,789e7df2,23774415,da7e31da,277a81c9,708098b8,d455594c,6f9cb065,b1281a1d) -,S(4984a4e5,2c173c02,ec79198c,f8496972,eeed4e39,9933bac0,59856bb0,48bf2622,4596b67b,79be2e61,a0887a9c,2cc3ccf6,f199e924,3991f434,8e7cf897,acc5df3f) -,S(285c6ff4,93c1be13,f4f60d0d,8aa7cb24,4bf0f76a,23f3efbc,cfa4a132,625f7272,39dfe9a5,cf9cef28,d5cfd998,49db9b23,c4caace5,e8a27c12,12d7b3d9,d3ed49d3) -,S(1e14b1d1,7e721971,e9266717,13100aa9,9bc6e506,c278ac7b,348b708f,843db340,63a239d,d705f627,347fe464,c4d4143c,394d7dfc,5f79ea11,64d05f04,4ce41cee) -,S(b8f73b9,ed71cd1e,f61dcf30,9cd48587,3b1394c0,4cf318fc,10140bb5,be17c8aa,8af5dae0,bd66ec85,2ff4823a,a1be65ed,745676a,5ac42ec5,827107e6,776f665c) -,S(7e0c7297,e878fcf6,cb636776,d15afd0,49c995d3,1cd49d15,e624bf6e,8714540a,df5795f7,4c512043,f48b7568,bb271a00,ffd59530,a0280e5,8aaaf0fd,aeddd658) -,S(9f0ed1d,465bed9f,a2b51133,fcddfe48,10999011,b754acba,de5fd027,6b798545,7005ec9c,73bb0e00,64badde0,12aa99d9,d85b6c38,e63256e9,21799990,14a8459f) -,S(2d556f5e,b5c5af0,160608d,80e23cef,cc8e4000,b1e35b12,5a0a51aa,9c8e12bf,7600144,25bc3baf,1dc7f6fc,1fd86f41,d24d4488,f80ab8a9,4e4422ca,15f12000) -,S(2617667d,7637e02c,b479524,d9c7dcc1,2cc14ce5,4149928e,e8d81bcc,835ed3f2,521573ba,2cd809eb,8f5496be,478ca639,7a2c4e16,1b299ba,bc6ae419,4780884b) -,S(6247916c,5b519a64,7b76e10f,8810a3f3,4cae40cf,ed05a492,ba1b061f,d9aac10,ffd02570,535ba978,906a193c,500da1d4,602b0969,c3e9f4ca,f2d33026,eee7f098) -,S(c40b27e0,8ed50a88,60017e78,ececfb9,ea14c64a,95137db4,fa55d4cf,9a3c52af,2415cb8c,7d025b84,fd9d1e97,7105aa54,c4149fb8,30ea801b,a86f1acd,e07b6493) -,S(ba5aec8a,54a3a56f,cd1bf17b,ceba9c4f,ad7103ab,f0666974,8b66578d,3e0de12,348dab11,abecc4bf,3c7474d2,8ea5ba60,a705de60,39f9b70d,c49d58b0,6d57ffbd) -,S(ba14e658,f8dd294e,1331262c,ffb3f31a,c1e9e504,e55c7f67,5c002248,94076268,ced74905,fc43e55e,c70cb36c,66dd9a10,c221b0e3,a326e365,9b96de4a,c81aa1dd) -,S(3375af69,8880c7fa,29e718cb,4139ab30,f9c1d00e,a1c22d4,cfbdfa16,a7f4aff4,cfa8b491,a83be5b1,b66fa0b8,5e26c68e,8d27db79,ce55d726,ddde67ee,ce295a27) -,S(68d2614b,306cfdfa,e9fa109a,2c4b276f,5b9a8ee2,f7d502d5,efc94aa4,bd9f01fe,148c36bc,f04365ed,7ddf54e8,4d40fb59,ef9e1d48,8408c8f3,661386c8,5f48550e) -,S(93facea5,597703b0,ad2990d7,1d63387b,900ece6b,6c3677b,7fc47b7f,1c533edd,3c801bfa,8fa114e8,b5c19985,39a1f6c1,c20bbe44,d8ee7179,7454797c,942ad5f4) -,S(f11dd4a6,72f73118,95775ae1,76c90b2a,5a0a61f1,6ca205d6,eef6c275,75054277,bc06a16d,2ef2ac0f,7ea2083c,ac18d0d0,6c307d45,51e0a0e8,3f59b568,b9556ef6) -,S(42ebcc5d,710ba454,fd29a94e,f83c8004,b71fe85,9725c010,f10ca39c,864204f7,f8aa84eb,643101ed,4c7d5cdb,271d067c,e633c17c,dc698e40,279064d2,d65f223b) -,S(d40877dc,d96d5a94,87b6fbc,e89d19a0,549e96da,13f1fb2e,67e9e3e1,85c80e52,be9bb9b3,85f20fcb,8e57b59a,ffc01442,c0be8306,f5d9087c,837e234c,5e789444) -,S(c18b2c98,cd2110ab,888ec934,239240a7,aa40c1bb,ab8d7e39,8fa74358,2562931f,d9621034,9147d74c,75df18cd,1066c40b,b83f189c,937c01cb,24c2ce97,155773f8) -,S(154d6b22,1a44f841,1cf4fa0c,4bb4debf,6fe94658,c648f9e4,d14f88e3,e05c0bd1,df0bc307,c705332f,328bbb6a,dd94e63f,7c1074f3,ebc55976,de552a59,5875559a) -,S(a38259e5,629f93b1,a397d228,59842dbc,24485d59,c3ab86e0,a9326a35,e1a26f15,69b5accc,2fe52a63,b3874932,e8a79b8c,1713274f,f435d892,367bb9ea,91f783fb) -,S(9d729eee,e91e3493,9925a7d5,2eeded18,14827029,6f822013,d4db2a3c,763fcd19,6d832154,3cc8621,166f731f,2d874fb0,9cadc09e,4e330339,657aa2f0,e3e89a1f) -,S(2674f008,86307c7e,576cede7,944a9f9b,46398c93,8a0f8b39,b25701b3,67751e3a,3e9eb42,6ac9d1ef,837638d0,7b0f1f4e,e31bdec7,a9d22fa2,12a666b8,193f83cf) -,S(b2a06d5e,adb1b856,dd28e9fd,bb626c0f,b7c1642c,6f70c2c2,743f3451,4e237f41,5d4caf8b,8673b268,227baed4,481ad60b,de579a98,4d005f5f,f3bcead6,3bf664d3) -,S(20b27d64,d61debdc,ec3e4ec9,2040f05d,2b278c0f,1415ba60,f0bf23e1,222d713d,481d85e7,ff5c2df3,5cd26488,6056750e,c8c5c809,bb3afffb,41e447b7,a4e516a3) -,S(4f4a610c,450eaa25,f60d7c15,20c551f7,5270930f,45a7c51b,fc7cd5c5,3ce3f2e5,df1e8e11,db416228,672d8d8e,f9d68ed,e824234e,fd7de39c,2b32fd90,3a47f328) -,S(9b375ed8,504358,25570b4b,e359bc07,bc06c989,14659e9e,776fba36,a8aceaa9,3d056593,385c0069,915de5b1,f59c3483,22683440,86dcdf26,d1e6ae22,35e90927) -,S(43640804,5d432c87,31f865e7,2390b7ff,c13aff87,37fcfba4,60c0192,2ec9d1be,e2338eaf,6fc73fe1,e3df2aac,54bb4fbe,5aff2a92,5b8b16eb,2346b220,6070cbeb) -,S(a6e59c4f,24461172,4161f35c,fbe88d4e,59287f2e,f2b9ea39,4c476127,f41e0b66,75c70747,f5dd75f9,41cfa470,c4cf718a,57a8ae2b,2e7ab277,5f5ec5fe,7d9f334d) -,S(ff639617,ae7351fd,977bf1e8,46a6d33a,5293a959,74b296ed,7c9a007b,25322d51,e6123dab,fa2355f7,653f81ff,ee798353,e21dca71,ef40639f,79d73116,53dac457) -,S(77914840,1710d8e6,8a37cbc,5ad5e284,c254dfee,1c8b043,5f8ddbe9,4ef4faf3,d97f44e9,9ef3d4c7,4075dc3,894d2a6a,623be446,32c98eca,a54b8ed8,e0611414) -,S(f68910aa,29254aa,10551c00,adc135c4,947cf1fc,6dd8ee5,d42579fb,79484aad,40bdfbdb,33a56d63,ad587ea,fc9784de,69f9f5c4,3f5c7c94,1b9b59e4,c052c1fc) -,S(15be8f81,473d4cef,719c7501,1d560d84,f2d4d8d2,def1d696,29f62464,1b6e0fd3,7e66f926,fc991b41,c451ead0,6d93267,64b85ea8,849047bb,1d28eeee,70fd9a2a) -,S(e113d5a,2e22302e,f4327297,7c41c8b,d0c5c26f,9a0bd9db,9091abdd,8a84e9ca,2e4862d8,34c6dc45,17a6b70b,2f1b2c5b,b54941d1,cb803530,26a257ca,f5574dc0) -,S(96b10770,485bba67,7f620d9d,ec0d1be2,2c94dab0,57d6d595,aa78dfe7,47bea688,e060aaae,222726a,c1a1bd58,fc779d9a,ff854ac2,4a4996a5,2259e9f1,bbdbf30b) -,S(81742f00,5555954e,17e5e899,d2cfd8c,57f6f7c7,5a38e183,de878934,2405545d,a1763fc2,e5f705f2,e6f2fbb0,73578fb0,a8d742c6,8f92236e,df1ee03d,2ed2fc0e) -,S(17c19f13,96988f62,77cb72ea,f90d37bb,86bc7a0b,e16c1c17,fcc481ff,bb78a480,cb1290d5,210164eb,621c2642,ae3e51b9,3f430e60,718f9fd9,c5ec3bb6,53c78833) -,S(7b0f06,e8746ec9,c6648b2b,bb861548,bfeee507,63c01c3f,40319beb,a2497a3c,c6949378,84297d8e,308b318f,1caa0c7b,1634b758,9d6e8c6a,2fdb778e,d6a70020) -,S(715c2b06,2414183f,9a67d8c2,8a89b754,55a80517,cb1b8134,5f56e91,12c5e8b3,f89b89c8,9a795dc7,1e2d4cca,7f84b4d5,23167f03,97787b33,9205773f,2520370b) -,S(e0d0ce00,f974fc78,76777662,efe5dbf5,57aed09,dd89a4c7,8f1f40dc,8f74d3b6,acc5be65,ed704847,94bc7f05,c4c5511f,c253befe,7cb3c0d3,e85704e2,e3e3eb56) -,S(37553289,76fbb8b7,9a5aaf75,ecd9d2a1,bdba9a87,5bad6222,e770ab1f,d26432a2,6dbbe233,1b7e064b,d80bc7d0,12b2a088,1087e7c,2c5c1d77,eb016108,c2ced92d) -,S(2e95c3ef,51ea9036,8683f6b0,8b2afb04,f46ca651,2abdc699,446ab3a0,6fe3d3ff,905ea87,b1d8dfe0,48463b94,c61dbc62,1556c66,b2b498,39cb40c3,299b554a) -,S(25310e1e,721f3245,7f35c67f,b73553f6,6467580d,b5916cf4,fe7d75a,c4ff8eb5,9c5e52f9,be42eeb5,425a359b,87dcab1d,46ecd662,c17eb041,16b5430,786b4ace) -,S(25932b1b,2b24fc2d,d7877911,7d7cb506,27a23b7d,7faf53b0,cf707f51,b7830b7b,7e8e23b4,acdb26b0,1d7969a6,ddf3a2ae,2215e206,109cf3e,4e32d91,df536765) -,S(7d232af6,251f7667,ba69ba44,397f5b8a,892e135e,b09b684e,22b16a44,73c5ed3e,a3e8f638,c8a589b5,8cfdea61,d9824f1c,131b9045,9509b92c,1cd26571,a6d8356e) -,S(4d56caa0,1b65ea87,ba3e05b0,a4495606,6afc8645,4847633,cb9e9755,c8c720f9,14c34678,36e65197,ca3f1ada,936f0348,7c1eaee1,977ae08f,50f41771,77537330) -,S(71abd165,ca6ff8bb,775c81f4,2c722ed7,2615b503,3727dc2c,122efbd9,c500a88b,79ba2467,7284f86,2fb1c46a,e11ac4b9,a5969352,64224eb9,c39ab884,492620f1) -,S(8462fccc,c3810519,cc449634,5c5d9e56,30215e74,c41179f4,2002e906,56a48965,535a966,cd7fb998,bc548a7e,29fc4640,f0eb75a7,5c3c05cb,64d09048,a7787d4b) -,S(f68eac93,fed751d0,b578b5c,665684a8,b9c2b104,6fe45ae3,286e9351,36c09826,98e0c32b,98b0a8a2,8f119ff2,fa50e54b,66f7d8d5,732a1831,7334fc45,fd48bff5) -,S(61447250,9a8d935,9c0e4014,f6ff569a,43467dc7,e4940b16,15f442b2,d9f72041,fb7177f,c7f57ee7,deea7108,dfbea888,fa58f209,2aeb2d2e,b2f33141,7ac8f807) -,S(ea69ee11,4ffa1bd2,e2259a26,e2d88cf1,c9846ac9,379a1497,fc28ecc5,4b15614f,589b81b5,1dd6d750,91014108,3dd6cf3d,63183d1b,809b62c9,b17b768c,5ce4e2de) -,S(34727b24,3404de96,641a1ce0,d7ff150b,38e6aa15,c51fab78,1464c660,4e5d5263,9198326b,cf56ca77,35b9baad,dc0069d3,1920bff2,d5bbf804,435289d4,d827d4f2) -,S(952452ae,613778dc,29e2d275,6e98b4f0,eeebf4d9,526cead9,52f8d0d9,9e217461,c08b3a28,c195fb5a,f9a50eb1,1b1411b,c17f6582,dc14b5ff,797175b,2ad486a8) -,S(fbca3f18,dc4a8bc7,7e9afeba,66610306,401b8342,bde2dbfd,2d4a156a,e78e49ff,2b829d6d,6027b2de,eda0db7b,c76b924f,4cf75573,bb9329b6,c7b7e443,f94129c9) -,S(c7ddf11d,7ddc643a,957dff64,a08a4a70,5302bfff,b940882b,57bc4c15,5bd8c141,e9ca11f1,ac93b018,3fe8146,839be79b,b3711ee1,8a3daa88,89d55669,6e708e20) -,S(71043a30,86e3063e,b831f7e4,4e682181,1b3f2353,9cb6efa2,cd0ee4a6,70ce31b8,4db3f338,ef9fd273,4aa9cc92,55e2984d,9334c164,5320b411,ebcb7cb4,89322c9d) -,S(6de4ea40,15347cbb,d9349d36,80fa375c,5d70f044,799134c3,dbb6a776,48602585,3b76588,65ab52db,eea8d839,47025cf2,458a3243,38c73d70,f1d77df2,7f960418) -,S(29faa79f,467cecb7,ea17e23b,6f7ba03d,db9a0cc0,e1fa6215,bc425696,ba4fecbe,e5aa691f,c42fbc29,c1f027d0,46bdf106,64a2245e,d2ff1154,e50ffa1b,48f34838) -,S(ff880bfc,25ae5b22,78e5f15a,2bf8f5b,d750f8b8,74910f79,c8c42f93,16aafc99,9535f70a,728f79,37825bd8,1bb502db,60e7a166,bc8a0b10,5eeeee82,3a5747df) -,S(b781b6a0,3837f6f5,8520c566,352e8c09,60eff0b2,42524eee,f6a6bd2f,a4a2a378,acd7b7d4,6c683dd9,43722ee7,3c12b69d,cbf8389e,62755e4f,c44fffbf,4cdbbb62) -,S(6d976593,e8bac5d0,da732c64,82e4ac2b,b3f19062,59045990,ee540a3b,467406db,30c353e4,af6d8161,6c0bb9c0,f2a4aaed,6cbc1825,9a8b9658,3bd7e9c1,2f2a8b6b) -,S(18ed676a,4dd3e0db,46212112,9fad1e13,683ec782,2a6d9401,5d0866bd,6cdc3032,c86b06e1,5dbfa82a,5f7b9762,65e03670,6f9a6e7,7ee319bb,8ef26b16,a51bd5) -,S(3138e38,e9440ffc,c2cbce4d,aefd4b8d,d1e859d3,b951d18c,eb3540ca,db5ce2a1,df8ab1b2,a11a8667,dd660a13,490c6e6f,fef4bc40,94efa9a3,430e28c9,6895c241) -,S(757df4ac,2025c9aa,b8ab1e76,149a9762,163ce608,f4903c3a,91571cf,e8b00c95,ff0af5fe,ab36c5d8,47d15ab7,65000765,c56bd7cb,4d0fd8c4,a37d4ecc,dfa03430) -,S(8a697a52,7156589b,d13319a0,81e3b2f2,ce09de8,450b95cc,9aa70409,884c27e1,9eeb93c,b6029e9e,37f2815a,d332d5d9,5a5edde6,bbf03ca1,3df09f86,ad51f39d) -,S(b0bb6987,36f9e0b1,6cfc2198,e37a84d5,d35eb89b,d4f4c0b1,650d60e3,e58c721b,33d5b200,ce25b501,6f09808f,b38e82d,b855615,2f48c1eb,b3b6363b,ed6e00dc) -,S(1ca0edde,5dde4634,2637882a,d2f8ff7,ef6d6f5e,906ae2d8,d9f1b545,c837efed,19efb5ae,4cff683d,a7d5d4c0,f5eb9f3e,4c4d3a4f,ac58ee41,acb9ebda,a82863bc) -,S(780e5b0e,b9a4e57d,66a84931,1e1b765,d59ad11a,de4e921e,d90fc422,4d474aa7,5ebd9ccc,58cc5f21,2da579f4,c79aa3a4,1d8f34ff,418516a3,d339320c,133ab811) -,S(f7e92ce9,39808505,2d2af620,cdf210a7,30ec079a,54bf1468,edf686da,34eb4c9d,2c559dcf,e113a961,58fd54c0,32f14ada,57c23496,7a88b585,7b1f7ab9,78f93666) -,S(3c3afa20,75bb20a7,8f9ff809,20d80d61,3a5688a4,269336f5,4bc7da5c,4a89f938,7ef38308,1dd235d6,e563a9f5,46435f22,3bd836d9,3f1d132b,978f3f9c,7b888c8d) -,S(71d6f01d,ee60f9b5,75dec59e,7e56123,89fb9edc,3019115,af4fb155,f22097ee,e1ccc245,4a31a35c,52854091,fb414321,38da4fd2,eaf1680,2ef0470e,1c80bfee) -,S(9726660f,5705ec80,908a77b2,8e6257de,b107fc31,c58ab6ea,1f5f75b9,38c4fa2d,94cc07ae,3102d1e9,6118c213,b6db0c65,d3636fe7,8ea40c6,90c86949,b48cd4c1) -,S(ace5d0c7,54b2a1af,691a1a2,97e8b632,297fad12,ec1fc4b8,7fd02ac2,b2802719,924f9f24,8d3e725c,eba491f0,5f188d6a,7fc843ca,d24d0858,1f4c9485,8b9f85eb) -,S(fa51306b,34800ff0,ccd778f2,838a4a2a,8200eafd,622e98b8,8fa566b3,85943f64,b60ee616,6b144873,a1cee030,fc92b50d,4b67757,ad34d5c8,5f05c871,4296e293) -,S(85df9018,329d25a6,79c097ee,458eafcc,b716a59,611730f1,7c19d584,2dbea60a,c555d5b6,46d211c,e99ad7c0,9e787774,b7bc64c6,f2f6980a,e62e8911,897ab0fa) -,S(2f77c00d,c2024467,ab461b52,ae634a99,337ff5f4,780637f3,efb989ce,24af5e3a,c7f4a678,ebcbfabd,870c52b0,be7efba6,c5d28e7,aef2b253,3f0e7fa,905e3e39) -,S(52d8a23a,720050d6,ff6a499,7b802bf5,1f238df5,b0ef6001,58fc48c2,228bb34e,98ae81a7,861b8e1a,162d29b5,1c30c786,cebb1812,c91780f2,ccd302db,803d9136) -,S(a7f3e479,eaca0049,22fb8320,47555b5c,701daf22,407462fd,37b0edb1,7212b211,80f6190c,8c4ca7c1,7ba68498,d1bac039,3e33767c,c476fae8,e926500b,9fbdaada) -,S(31ef3150,e67bd326,61bbf4d7,942382af,73db5799,8f4880,ea04607c,a2356103,7db8f5d6,655d28d1,93b50bb5,14b16ed5,bc03c46a,e3d2c954,631834b1,a8a9a8ee) -,S(ee82f155,469c0299,39ad1ee3,52edea30,599b0cd3,868131fc,eabee245,3b8b058d,fd0c0d4e,2d77c2c4,2add9ed6,cadb898c,32de9398,f0394400,eed2ff30,5092b10c) -,S(dec7c7a,bfcedd6f,a9f7d45,8a071575,27354990,b456873e,206d1f7e,556b4586,af841ab4,cad597f4,186f0912,b79fe320,2c7626c7,b85cb276,73c18010,747200c4) -,S(c28e3370,48cd6fe9,7591ba40,5519bd80,2bf34f12,ee48762e,526b34d1,f4d2369d,e00abdd,da456731,7f486dba,6976ba13,b8640f52,39325a64,7d50eb17,f0636e8b) -,S(47157ca9,2c275f65,c29e9d,b0f23531,37027731,1cf05a93,7145123,df222195,648b17fa,c911fd25,af87e9ed,441cc874,9fefeb72,b34f8dc4,f430e0ce,89cbef6e) -,S(84d11702,745c53ce,d81b5503,79ff1947,9a0a9253,a7ab3868,f5471a64,6ca73241,4f16b6a2,c3c087a,4efb1353,644e64cd,fc593ec1,d8d656b6,2c0e0bc2,25f858c5) -,S(3bba3022,196060b8,6b2b2f28,ea8811c7,c74e8128,8e91adcc,b7fbe2d7,97d63fc9,7f34054a,f0945373,a77c5aa1,2ea4f54c,879d3f98,b6e7ef3a,9d73d2a2,a734e286) -,S(85637f4,7a2c6143,2437485a,b3d40e70,b9f74606,aa8538f4,425e8a06,98651c6b,bc6a95d5,6fb42b1e,67b07576,83a5036,f76e8531,a30d0096,c3500ad9,93396054) -,S(25302e98,5e75019a,21ed1605,dd3c543e,e8021a42,a40a967d,8ea6ed31,4dbbd123,849ccbe0,23097591,d46f9b4b,a13713f9,c0220639,11fdd0f3,267a4d8e,66797a83) -,S(e59a30bf,88e393e3,c08d73da,ba720ae3,485fde0f,b6b85f8e,4117f5e4,f43bea40,6fd7824f,e222cb37,1a0fa6bd,33e4bf83,83ebbb64,87872fb4,42284498,6197dfd5) -,S(c5902df6,97981a60,589e9bc3,b935de2e,de05331d,2c1365bd,a83f8183,f6247e4e,c67eb14f,5af551ef,1ab5ecb5,8feb7ce1,21d0736e,b93dac91,f865ac7d,2d75fe3c) -,S(df8bdac7,fe27127e,c679a9b4,74e3c809,b8b6409c,2e6c4c1b,277ab4e6,d5e66ad,3ff26fe4,9f0b3896,54d802ed,72eb4708,2738256f,c0266dc7,645b1027,717d43e1) -,S(1d55404e,9c7cb8ca,c39c7c02,b810d5f0,9eff9125,9166cf3,f1e8cf76,2c65a82c,c1787023,f6a1c8a3,5c499f64,a2fc4d23,e5a760ea,9a04707,c24bb9bd,b2a7632f) -,S(35f390c9,b035fdfb,68506073,d585e450,2d040e96,67a1b4ef,804ee088,df43b44,6a85cd88,86aad8b7,7dc36fec,50eb9754,4c3cad2a,da43d038,3c55da38,bff512a2) -,S(fbb0840d,ee888fa6,f26d7005,b2449cfd,1d22786e,d43d06d5,88f744c4,c5e059b0,6460514f,d89a70f2,3a4ffa21,9f651bae,203b05f4,bd3d45a6,508d2b25,cdb8d3bf) -,S(24056cf0,1c2275dc,44608ac4,66931e91,61fa0ae1,3353cac9,ce481271,a34d78d7,43ebd3c6,7e7381d1,bf03088f,434a5275,965a3fa0,d86a51bf,7dda1b63,cbc7751f) -,S(3b1043df,e8447c78,8e07c938,cd72f6b3,54f9f745,d7e71297,e7791972,70f9cd78,28e028c4,abf0d511,126c29d4,b2b185c7,b67ba361,e16c50c,34af129a,5e40d6fc) -,S(aef909d1,41793638,80d75b23,6635805c,8088b08f,5c577a81,a5bedd20,69a040e6,cbb4c6f,de26b6c,5d0c2b43,df40a3fa,93350cc0,1c497382,d8a1bb7c,8600dc51) -,S(c8d494f7,386331cb,6ff59aef,5f229bc7,913367b8,10f407ac,2c9f9d3,ca833f28,cb2c76f9,4b6285d4,d39afdac,bd3ef114,c7b85027,8d62da67,e70aa74b,b10de4d2) -,S(25afcff7,af14ca32,3dc74443,71de7b5f,c1b52e17,6fe5f3f5,f4f39139,34f75b28,d867a4a4,7f9d7e97,6cb1f57f,8d505a66,5010cdfb,4af4b781,75271722,6942b789) -,S(2436c86,f773930d,872c220d,c8bd72e5,d407682d,7708e2f8,19ad9632,3d32e2c7,6e396dea,92af663c,c44de690,24e1407f,20a95887,37f01662,bc89cdea,88ab67a5) -,S(61ceebd5,9e5733c7,910bcb86,e19159ee,57638bb8,7f3cc56b,d0f4d25,147f349d,2a850545,e9b0ed08,fb63082e,741a30ea,7d85218f,86282aef,3e74b15c,f2fadb9e) -,S(5a1133b5,d45d0071,42b91a73,79e2a46f,dcbfee6,e102d16d,d77e817e,b4b6c187,2ffd96ae,afd6d9c4,3c9c0517,133a4b7d,34c1c2e8,f398f81f,f6f0305,28d492e1) -,S(b74a3849,8b701b41,29eb5abe,8dcb13b9,fff0f191,314dd293,9c38d0f,4563c8ac,9d844e57,e50a20fd,864d6f7c,5a677855,689be528,f8431186,ffa96679,9cb9014f) -,S(c35c9cd0,4afb20b4,3fd1c337,5a952ad4,8e9a806c,a64aa4b7,52fcb204,5f89d26c,b041c6aa,4a83efcb,dee79d84,19e195b2,48c765c3,f069d5a4,b7e87792,79a9c65a) -,S(9a85aa58,753868b3,f04b2af4,479141d7,11703dde,e5b6e5e8,fea8ad37,d0b82b96,465c70ab,aa16f03b,d24b8075,233ec626,4e062041,3bf485f2,551d9952,7bd75d27) -,S(3ec71bcc,e051f3e5,12d83c14,cbd23f49,b3e825a3,cfa4c61b,d12eb057,5c86fe14,f198c21d,e2daa56a,55294c5a,b033f1aa,45caba3a,9a950007,db35f05e,e9915bdc) -,S(ee1cbe22,939e1ede,9010e23,535bf33f,6b09e579,3737db45,aea48f00,b359ae63,bf604026,d4444df6,27f7d297,1dab6a91,acecb6d9,de53228d,47178017,921b90a5) -,S(ebcbf3e1,71de3a62,ef47677d,1ff4d027,5a8cd92b,bc889ee7,8dcf0c99,6746073e,878d63c7,bc9c7224,914a3f3,2dadeb9,95c6d890,a3823f98,5c3f574,9ef6ebe8) -,S(e4e92ee4,ce72ef15,b87c57d5,259520d9,b6066430,c090dae5,6e81b2fd,ab9db797,3faac465,4a03a753,559f47db,f5877452,6d21838c,9c1f8217,ebef6965,655f944c) -,S(fc1ce758,8e292b03,7b4ef743,12eb1f67,cf275fc6,7c1e3d63,5bc42dd0,deac1cc1,176b79bf,44f7d9af,7f7c791e,8cafcb7a,495bc392,c23899b4,2fe7963d,e65186d7) -,S(f1f5bfff,179e6a6c,692a86b2,1c95ef85,49482b3a,b97a491f,9e9c7056,ba94fc56,389257a8,a2cd3bc3,fb4f0620,5c2aae70,67041512,10c62093,13a2584f,8a39e143) -,S(980e7414,61c3e001,ba6bfef8,d175a141,2c7aaa2e,748c3323,ac744fd6,ab793eb9,6e37ddae,29e05e83,b3cdde28,d4286005,34cbb33a,636c4259,c7fa7625,1b31826c) -,S(f519cff7,686a5257,71986dc,7e6c1955,adb7faa6,a6f7a07f,66a257ed,a1b1c179,3e803eb0,8c765c98,7941d008,a93b8503,174ed4ed,1c31e97f,9eeb8f2,a55a807) -,S(2dd8d9ea,3851fea9,1ba9bafd,bcc5cc0,9011d939,10edceee,144e2755,ba8f8061,6147f1af,d4224689,37cd058b,4ef52618,7adfdea9,ce970dc1,365fe04d,1da52ae3) -,S(860c4262,9483537,47ac0c41,5aa00f63,2854f88c,d7d09b35,edefd780,1454a4ae,a2a7a22a,7d826d25,8e7dfc56,1eef0d85,d15378a2,80535cef,95ce6e2e,d73392f4) -,S(e76b20ec,17d82c3d,987d4ea,20535209,e0697f90,2c964b28,ae97ad0b,aed732a6,c97844b6,85f6613b,fdb7cec9,cc47f701,32bc1137,d997f8f4,ad182492,67f54bf0) -,S(26731d0d,12fba582,636862b1,62a417b7,718ec9cd,e3d047a6,50455efd,910ab88,3c10efb3,b464a61,6e2023b,b0736d6e,8d298609,47ba5714,3b1a71fc,9b542192) -,S(50cb4878,52db811a,87fe46f5,ed014db0,3fc4570e,8b2d8ea8,9865df9d,a224dcde,bb8488a8,7937ae89,88f572a0,c100e450,c69db48d,303d06f9,5d54bd83,8b39621d) -,S(fb69453b,1d67ffdb,670f9fb9,2b3fae5f,64b0c4d,cb28ba0e,7ebeeb21,ffb02a60,b0fdef36,92d881b6,3ebb1387,984120f8,d1ba17af,477364ca,41e303ee,a4fd2c39) -,S(a8f1280b,4b720226,19faec4f,ea3f784d,3f4061a,56dbbb99,38c7706d,8bb249b4,ebb3b571,ac505913,4572e501,4be7be33,a97e12b9,bc1fd9d4,484703f4,6e39b8cc) -,S(4292ce09,df305790,f17cb3be,30996016,420f83c1,bc19abb8,78b49027,6eacaa98,1b14d94c,bf2b1d1d,82cf1873,3461b76c,f32c8d5b,6746e2f9,aa2aa248,1c745d36) -,S(ac241177,f16f747f,b796750,49c83f8f,8e1a062c,9796b05b,8c5a5587,a4c9464f,dd057503,8261d044,ec84eb03,73065687,266b695c,ef5cb41d,1cba3b5d,9176cf58) -,S(692eca73,26bf2da5,7fd9d640,acf7f846,78e75c9b,86b18e7d,d7fd2545,751823d3,17d6d462,548ea78a,18557320,289d61da,14c3850,4ff03347,8f17fdd3,71c8e97f) -,S(d01b1a44,55ef5011,e4ecf946,ec02e6f5,d0e129d4,d2f59889,e823cc5b,6f10e216,84a4d89e,55e33edd,d54f38f2,1649f5fd,807879e3,388df988,34556ae6,57f91a0f) -,S(1eba61f2,96a788d8,9273a67,18f2a0cf,fb0798c2,393330f1,2f890bc7,9bfc1e9b,89f298cb,e8471046,2df0a6a6,b6c4b6af,505da2c0,9ee13266,bc47cd5d,2ddc9661) -,S(26dff8da,94603121,4649fe1f,721edcc1,a2300ca,b1a6d548,9c9b68d7,415980ea,d8264a21,55e1bbdf,c3b65862,efb9548f,3c4a0a5f,97f5b713,9d3da15c,90004e60) -,S(4e642b51,425e1822,1275f64f,283e9eb1,a3116adc,a6e25047,cee3bc0f,323fe676,f28b7d65,9125468c,4951db0a,bc35d4dd,65b9c5a0,ed27d742,47a68a23,89eafbb2) -,S(354aff5c,ee9a27db,37e7c97b,4cea476b,b4f3700c,e9c26b21,e94d2e1a,78f448a2,8d6907d1,624b79e5,6392d008,2f6a794e,99b4c4d1,6ca78dd5,97709c86,2930fcdb) -,S(5286d074,949369fe,8f69f020,c0b65f75,e76995ee,5f49b9dc,d570b956,8ffbdc3d,255ef2e5,3dd2c40c,1e462a45,27e6ee00,e0a23d3e,b16b05e2,2781de6,879703ab) -,S(b84a8346,c86e2299,9acc8ff9,1a893592,6bddeeb8,6fde121c,266d5f60,3268add7,31179a8c,79f40238,e1b80c87,81e46597,29f5c8d3,d8bea0a3,f65b403b,ef20789f) -,S(1e7bd5e6,63fc9a50,2258b9f1,14fc51c3,1b9dfc27,9022c67e,fde7872,dd12bb94,6287a9b4,555b146,7d250f11,e77ee8b5,7accefe,6d91cb6b,927611f2,c2c1b84) -,S(7ee68a21,37289ebe,7a5cfde6,be672ca6,9d28acc4,54d6b8da,9c96b2ad,37d2bc81,3ec34064,a6c3ca,f2a8aeee,9b24e023,3d7dcbe,b7acddcc,8a53db84,c570c83e) -,S(29d4b10c,f4be3bfa,a9d07fdd,da6ba7ae,f3adef75,67c3c33f,8d4d914c,f8ce570e,b6a74385,96a4f40a,40d03c25,2c7070da,2ec79e08,dbef71f2,422392ce,1058bf4c) -,S(7907c5d9,5c5cd647,e312a43b,42c3f053,50218f10,da6279c9,895516d7,328c359e,6c65a9e1,ec062a1b,f2abca52,fdeeac18,26888378,58f985d4,c8f1c987,64d6a625) -,S(cc436eae,ce11bbc3,36014fe7,bc68fcfa,e5bc2c55,c53430ad,fc994b8d,959d31b1,16160de7,d6ffbf64,d644e608,96052985,6b2bd539,66d7edb3,a50c924b,fa9706a2) -,S(cf023d5d,278d4201,ae659d55,6239dfa2,1b5fb30b,14adbea,7351b620,150ec1f0,d6007395,ffcec07a,6e71c26e,7575cdb4,34c473b7,57d4574,9e5154e4,d4990741) -,S(1a2a093,f718c59b,d4d35b73,2c547b61,12b6a257,e807a38d,71b04125,e7746a21,2674b542,652fa39a,1a2cadcc,3924796e,16c0f8b0,5d83f919,f8b93547,98fd4c95) -,S(534ed420,4b8ac51,7518fdff,224ffae,f712e4c7,6a84215,fac925b7,eeb799d7,35e5852,3ea6199f,b9fe497f,576dfae8,fa30782f,d24cd439,c0708118,dbd82155) -,S(8d31e4ad,9e6f30ae,6c78ff18,8f4b0457,e9ba646b,3a26138c,f11d84c1,4a00d08e,f0dbefc1,909396c1,3a1e36a4,844b2a87,e4b0b1cd,4b30e996,47839bcd,4dd5feb2) -,S(81748452,267405a,bf664379,16ff7f73,c418439f,86b73159,54c15fd2,2d2b3412,13d1209b,435b50b,1409389,9961f5ae,9f6f95fd,280beba7,cb3f3f5d,a0f19bbc) -,S(bca87f72,e604e885,64552b,edf380ca,45842270,57efe12a,6cc23847,658aaa3,ee508af5,28b77125,72c123c6,276ba23f,af26538d,5752d84b,54ee82ba,df9e3d0e) -,S(de2baa9,a19652f6,c0c0365c,d6e78cb9,d527e546,1240fc52,e8c59183,7fcd3fb2,aeb418ef,466c32fd,4cb5f2be,571672dd,86573941,a9cf9bd,73377aca,1ed38905) -,S(7b8ce1e9,14df7919,b54a0591,c077135e,556f6cab,c7665e5a,c0004390,22acca9e,a60a3ff3,9cd8ad49,c100b72,4338a54,d06a96a9,f3fdc7c2,fb8ae598,c0b40628) -,S(cd71c179,13fe7443,19bc80f8,205d7617,4d6d44fd,a6ac3d1b,402279b,eca50e75,9f1e73bf,cf3438d0,1f01d1a9,3f633929,ae385812,528ad211,967bf38c,71419064) -,S(42cad02e,32dc8dc3,4ba36161,d0816af1,619b70e,117da444,f4f1e454,73ca8fe4,97cb2134,5a259cff,8870823d,fe11031a,79e59d7e,dd2593c6,65128a8c,36e75568) -,S(98a89130,4f0652c6,2986644a,62a1dfab,48331756,c8b9e1f6,d473c03c,b98ff8c7,c130f2ce,cc506903,9ca49b3e,534ad484,b277e0ad,7b2a8733,98864000,e9a824e8) -,S(23c45c76,84762aa,7bfd39ff,284403b0,d7a4a128,6bd7b455,22c09d2e,df8a4328,f4ab7317,95c46f47,c3d46dc7,cb0d43de,d57cb274,ff0c350a,f0d79548,bb303cde) -,S(8b700037,d584c4f2,f65416f2,dbd37c35,9e6a7b83,108dad34,3a6c4d0c,6a21d856,8371ec03,9ed0066d,4e8e7d86,69169f9a,5a172cf6,c324c2b,ecdfc76a,c365ca35) -,S(da6164a8,d0fb4111,ca1d78f2,83e8180,4f4ae8,50ae8596,cdb97d9a,a30f8a7b,f9a8463,717e4f17,a77caf4e,10c11101,1cc0b5a1,c788307f,c7aba482,2a9a342d) -,S(49f37d65,a9d1a54d,1929b9c2,6db7d7e,c45924e2,9e6010fa,2202d47d,eb5fd6b7,f9b9b785,28f62629,7bd0dbba,9340c142,1e64895,b1befa94,ca677de7,686aa51e) -,S(8755f088,e26859a0,1a56b78,ba1898ab,12d80837,308677cc,b38e9c53,e36efa10,5d67013d,1eec7a88,215b4768,f55f83f6,434906a9,f2f6a9a9,de5df75f,6ef7e478) -,S(35321796,b7aba6dd,873550fc,5a35e081,a4e6d134,a127c534,69ff777,c609045c,47ff0f43,efa93f4e,f197a680,4f1e1133,c5c8301c,b49de8ba,6fe10167,f0a1e832) -,S(3abedd2b,644bd2bb,e77ab5ea,2823b42,83479fec,df2b3421,56fe9ace,612559b3,4269b08e,6c13b818,131824ba,11e3369a,87bbccfa,330e408f,17985b21,e5e32b06) -,S(e30112a2,2c23462a,a803dc53,e3277d7,c14b62cc,92787f77,5be98ffc,7c956de8,d0c7e3d0,dbb10e8b,7a9f4e0f,f93e7581,99d90f6d,d869368a,8d2ad369,4898da40) -,S(6250858,439c4b4f,30d47f6c,b9259103,bcdf497b,f09d3762,f1073f5b,973cd06b,3437f5e4,84ce4258,5584407a,fb0e4383,87e4c930,2fcc902e,cd26b721,5075328e) -,S(77ad4485,b8c94cfa,4e904bc3,90e93e3f,66838d50,fb16e09b,dcb39ad6,88f826ea,4dbc505a,9798879e,137c8444,750ec3c3,34c2ecb5,485bab73,6b0b9bbf,806001d4) -,S(5dcd3e92,e413601d,b9dce337,7a8e67e4,3852b8cf,ac41066c,ad579199,3ac0b7db,acccd081,35efb43a,306760ed,ec278f7f,36996ed0,d6367f85,417754cb,a4e997c9) -,S(3a26663b,adce051f,c41d2e6b,9b931851,e65ca385,15f59737,fc8c27f5,caff788d,2d647eab,af01d846,70110e,7272cb4,9b9db0b8,88a8113,bab5f89b,90abc2bb) -,S(f57cceb9,51dc98fc,712fe9c2,c024031f,4e3b0f02,5067ac4,b8bb0096,e4b1aec0,696093eb,7a8aebed,a751455,782f99fb,ddb2c66d,438a7bca,9c4df301,b7a1ea25) -,S(a89a4778,bca06e14,bdbd46c,948ccd36,df47c83a,2dbba9b0,93589406,be9b4a0c,f4224dd6,9d08262d,22b98e2e,4e781e6e,939d69ed,d59f30d1,d23f9ea1,6ef366cf) -,S(64738381,84fe8247,2b463f4c,7ff04a6f,6a3be92f,ba295d72,adf065b8,10b962a9,bcd100c0,d09f6e93,4fe9d58d,d58004d0,9ba164fa,324010bb,c973709a,2ce32de) -,S(4a683a38,21261e28,2e0196ba,d9f8727a,f7bcaa4c,afd5e686,6c7cffaa,3adc7774,b5aba4d0,ec3d9aa4,39b37f0b,15f40fed,913af371,b1b94f20,2cc93378,954ff3b0) -,S(1025e16e,fdaeccd4,436cfd9e,b8ee1614,53fee046,e420296f,53cc2e5a,bb5cb3c7,f806b96b,67ce92a3,e159b807,58f38f73,704e4d8,3bd611c2,25314400,f0c48f3b) -,S(6149d809,675a5353,6fe2217b,7f6777c7,60039cb3,5a0840e4,552e2ac6,db6650d2,e4ae636c,9a9808aa,4f49b03f,bd12f786,c72f07f2,9e397a11,68154505,b1a96ca9) -,S(ba24112,43888342,54ee8327,4bb03dd3,2fff3edb,4d607047,d8c141d4,c3fec47f,8a6bf123,29c3fcdd,38e6a18d,ed28c8a1,3717e997,9d0c366d,aa640dd,bad5c35e) -,S(c20df096,3c7cac7e,9dbaa259,538af550,35c00550,94ad4993,2190688e,7856a961,491e995d,16cf7ae9,85b8dd8d,6a5890b8,fb4f2c42,aea7c33b,ad84835f,b245d40a) -,S(6f53d8ca,4dbb4d72,d9ef3dcb,93dd2ec1,aac9f38b,1b4cb2a5,c76449d,4faf0c50,6784a02d,f449beb7,24156de2,486753c0,77bbecc3,27caee12,f7888687,4e7ae24a) -,S(e57e78bd,71a08f60,51c8a046,184757eb,6364ae0f,8eca86b3,51317712,737bdda3,a0623c7e,8a535f66,57116c82,da77554e,31a1d263,28ec0e8f,116976d0,f4385342) -,S(f52f6f29,aad496ab,9e0abd0e,a7cb53a7,7853e8e1,a6e5ffff,285e97c4,f7ab099a,3df7c1fc,6d5c5e81,8b5de4b7,66f2995d,c361511c,198a68e0,b7196204,559d55a3) -,S(da74f5fb,5c0a6d09,6fb26268,b33d9c86,ec5cf08d,8bd65fe2,59f836a7,3efb0dc3,7e50e989,de5e2847,7e31c816,42a51edd,8d0ea031,35423f3e,ffea07a9,48a62c47) -,S(2a2c9aa8,7bd45217,f341d35,9a9d2de8,35d14414,cfd3eed8,a2337a64,e051f4ff,bf9efdeb,99335f68,a01fd7e5,d8aec9f9,49688221,59d18bf8,a466c6ef,9648a1ce) -,S(2a3440b1,91dc5314,c6d0da7d,b07e2cf3,7d13bcef,1ebfd23b,492ad632,92022266,bdec24f5,c993a020,2f2fda24,e8707947,e4c1e9f2,2c34efc6,dd1e62d3,e2ae2b40) -,S(a3a9bd74,3d1d36ad,fad36e8b,d5544500,e0accea,d53d081c,28740109,e10942a2,cc33decf,f8cae7d8,dedab1fc,ea1b4c16,2cb71104,ff75c16b,66db334f,ec794ca0) -,S(5b83d48f,70a2f212,93dc724,77f4d87f,80db7eac,2b08d70d,308953d1,88804950,f78c0488,a10c66c2,e11368d7,690fcc4d,982ecdb4,7ed539c3,30d4b14,4248b545) -,S(dd5b46a5,6e3e4a22,39e210,a871db8e,d901ab96,3c6fec29,4140d77b,be9736a,d9b76eba,ebdd45ac,35c52268,ccd35df8,9e7136ef,879848ce,ae647c13,d421d46b) -,S(2f74db5a,25486127,6236bc5b,22214097,d1ff781f,3798f64,62cc6dcb,3f61a6d3,b6d635ed,256f6d2f,a91b868e,a3014db3,64647147,ac89248e,ca983c09,53149c1c) -,S(32adc0c4,1f7c939a,58640b8b,fde1c8ba,119bff26,dfe4b0be,c5058ddf,23ab2e09,cf317248,7f0bb297,d7d7772d,2a01d917,40beed83,3a35a293,66bbb0dd,3946ae3f) -,S(4fe53ca7,172da8,272a152e,d74c07ed,4e336cb5,85cb2ae9,36f9f301,87c6cdce,81f6d1c4,bd711c16,21cc2986,916578c6,baf42870,58b84843,27e46e98,81e3a8ce) -,S(601934f5,577fa2a6,702f316e,b4dfed9a,3b08dc06,5d3e58ae,63f8548d,9fb2569f,6df7d882,4360fd7f,b5f96f68,93b1f1de,55e19690,f6acf954,362074d0,30f714cc) -,S(79da708,8ff4806c,64492ee5,2e9dda2f,e1bec3c6,79fa3129,8173c0f7,aa79d321,2b1eca29,76f2884a,35167e8a,bd2055af,44be734b,b0e0847f,f90abe8b,17f9a47) -,S(602b8209,c39f299c,bc208b51,ca8bf691,5b8d4fc8,d8399186,7e589dce,79262974,f8b6cda,5d7ca83,6aac43f9,4791a5d8,a5ed1f05,af90f5f2,267cd9da,567f5555) -,S(57a4f368,868a8a6d,572991e4,84e66481,ff14c05,c0fa0232,75251151,fe0e53d1,d6cc87c,5bc29b83,368e1786,9e964f2f,53d52ea3,aa3e5a9e,fa1fa578,123a0c6d) -,S(4f9b48f0,ae9df110,70c4c5ae,2b012cd6,4599063e,5bd32b54,43548b78,6a06db2a,d5a7a0fe,3cafc78f,66f563eb,f6fe42ae,980cd621,bf18aa15,7bdeded7,dd5ea016) -,S(e46a5308,4b11349f,44661589,38bb663d,e1910aad,35de0708,5a053b5f,6c5e7375,da46da88,9583632d,fbf923be,9f07ace2,cb8c3d2b,fa6bfc47,9e1a7d32,e1183ce9) -,S(3643d766,b94b161e,323e64de,3c925040,d62f2ad6,2b60a674,15c8b962,1c071ea,faf69af1,1f2b9e05,db29dcff,a020f6d4,80835d4f,83d35a96,7aff1b5b,9f16fa98) -,S(96769694,c026152,1bbe1b48,544e05dc,e6bea57b,7fa31478,f6ff1b1b,bf497dca,4eb5a6fd,7d0dae14,9673b033,bd97c08f,8210fd12,c759293c,40782702,b3e30b03) -,S(2e41def,2c479931,89be0ff4,b4110e28,7f80fda6,f4134ef6,5c867e66,59a24d07,26a14d7b,b8388b12,a3ba1f50,e56ffb3a,69bde3c1,17441f52,158531d,c874c313) -,S(f39d941a,f6eafe0e,9a44fbf7,71eb63e4,db94cbf0,854a837d,b7f284c5,ac03c29b,1ffed770,dac4d12,2241f8b5,507e04b0,72cd5934,c03b0183,d8b62e73,8cbd7b73) -,S(90900d34,4576beea,911f8dc,c2d90625,1cdac045,28017d1c,59576449,50136419,60d38bbb,2a338102,da044498,a2b2c5c,1457cee6,eb34d666,b0c0956a,48161ad6) -,S(3a5e4627,1007f4a6,2e744226,f1d2b782,44a523e3,97b6509e,e3e1a513,d8ac2e06,50f01fc1,74cfc3f,256dee2,fa415f35,bcdfcfe,57b79d90,f75226ba,e8202449) -,S(f66ea256,f6d711e4,1ea5492e,f6f6e46a,b13ac258,a8f0eb87,a06b6c3f,13e24355,fb8a1c47,980ea6c,87ec2401,4c0f6d2a,8f32a2a0,6f3fd0b5,7fa00307,26243841) -,S(cada0520,19a16ccc,fbb6d4ed,6c7436d0,c946a485,ab3362a8,5c62580b,d3038fa0,e249940a,34804324,ac706963,91ae7393,421de971,af0f203,2b5f2d21,7d32ae6) -,S(d16f5b5e,820b7295,96bd5192,9dd830b2,ce208413,5c2db712,2c4e75fa,cb759cf1,70edb084,cfbebcd7,ddd36380,75e05147,6ecdd585,e228749c,e61e3784,6a448ed8) -,S(bbccce8d,dc6bae0d,cb6e5149,8c666f31,3dc31ac9,d4d949a4,84751134,d5f71535,4da772fc,63ff92be,5271b479,68e7bbf5,c8941f68,989fa6e,a23ce5ad,23f91eed) -,S(515f28f5,cd8b75c4,325e940d,6821eba,e7d5d2f8,e836b291,5f606152,ed4243fe,a13143cc,f5d2b8fe,14a09f46,68229258,e1855a82,6f7db2a2,4ba2f1c4,63668b47) -,S(bd2f46ae,a78c462d,8691ed6f,9d381278,68d356b5,b8fd7f79,df6ed845,21233837,8f645ed3,f3cc803f,7eb32f70,ed7d6fe2,84ddd9ae,62ab8324,b92bd7c8,79c4af11) -,S(8576f13c,c3d32122,69e10b51,2011a450,4f8d7d3,92e0f133,47d7d65d,f9e37dfa,fbbf2048,3fa0e131,2309eb8c,19eede8b,86ff9028,45b66195,8d19d903,f68b1a4f) -,S(70be1e91,8fdf4e47,d73f262a,bf2361fd,763a83f2,d31cf41a,23b8c9f3,8309db4a,82f80575,e4246ef4,c13fa48,8892943b,a1897ac9,dc3ef188,29f3f708,428bc573) -,S(bb8a093d,1d586b53,9bf54a46,1a353af9,173529a,12312361,c8064e91,4b41180f,460e0ed7,8456a251,cd68d66b,ccf5de7e,28707540,d221d65e,72334d85,af478269) -,S(7817ae4f,34d9194c,f4b30628,7071fa1e,7b976a84,754c1860,6dc4a124,bc5c2e69,25f4ec56,c4e3b1b5,bc6ed346,e4f8b340,6afe1c0c,f84ad7b,481be5dd,2cd55cbc) -,S(85c760dc,411f59fa,6feed8e2,a0e5bb5f,e72af5f1,2734c9a5,bccfed11,bf66abcc,92583db0,b57c9c71,bf0f1248,23a67e5b,89a8910e,6500e8ad,10666b26,cbcb8cc4) -,S(20d80d35,4d9d762f,f2c739e3,b1e7377b,d9ee7123,47ea979a,d4c81abc,5d5086c3,6e191d7b,8017a675,e8123b7f,1f1351b5,ef6ed6b,1b225cf7,48941df7,62f0efe5) -,S(3306922d,43f2c4b0,65f6d9c8,d1289804,ec26cefc,97090fde,86dc3e0,fdba5657,98a8cc9f,c93dd7ac,7079f76e,fa1c4065,86f0e941,9f87cd88,1b865c30,13c7efc4) -,S(b35c7597,54d37f12,440f7703,39223681,8a1b9aac,b085fc1,8acde6c7,3b2fb001,484b90,69b08485,95c58ffb,df5968e,2ea789b4,6f93d660,a7af6b75,13cd649d) -,S(9bd41b53,7f8bc303,6cc9d010,45922b1a,5c647f8,e90fd587,86ef0975,474e1f33,590afbf6,55ece125,da486bfe,1ff389a5,8b866776,8d2013ae,c25d03bc,bf0274ac) -,S(2a3a672c,a9b3aef0,bce89703,a38e0dcb,6950d93a,7359420e,5278f160,541ded42,4c3a94b6,13f3383d,b908ebef,6b62bab2,c95f850c,f88aea5f,c6af3b89,c2693d8e) -,S(31ba6af2,a2d94f8,d4df3800,353806dc,c8db945f,16dc5bf6,93794382,58f74d3d,ad19dd02,b290eb1c,ba5d915e,f60344c5,fc1e6a82,c5427f4a,236238cc,2329df5a) -,S(fa2199bd,74b014f0,5df0f9b8,ebf44a98,587c0251,e9c49bb0,5bb12952,bc869720,4328917d,6efdf5f4,b0f5c483,860e1e9b,41ab6ee,b1f5631a,66d2d213,b163f45e) -,S(417b9046,c7f53c0f,5ccf2847,692ab63d,8aaac02,e3bfd99f,30a469a9,8be22d52,78c15e65,5f309788,dff6eae6,91706e00,7aede9a8,3bdb08e0,d495d6a4,863b82c0) -,S(56ac91f2,47d51fd8,8a0e6eca,67a69ffa,6158f498,1714964,f33e43d5,6f18bc2a,351b7d5c,9e1b1a4b,717c518b,37b81c64,429beeae,26e7a740,c54b1a66,dd0680c7) -,S(aeba32f8,83307ef3,152d835a,a0babec9,e164ae70,10c90250,68507d65,37215f8a,8d747d39,35cf5f2e,6ff16557,7ccef843,7ce7e3c6,a41cc40f,dcde2ae8,582c4e21) -,S(42c7b219,9af00c97,693d6bcc,256ed047,79ee10eb,e4dbe63,d47d681d,21db5813,a15fb708,1fb1c7cb,2ce44a4d,f8958432,a5fd875d,1fcf7c75,c3c4865b,b219378f) -,S(4337b297,ecf365a8,88bfe19d,1bcd5fe,25e0dba2,9c39e2c,36ca116d,a24e5d98,49c723ab,c6541edb,cbc83348,5e06db73,28d1ef8b,c9cd9722,915415bb,2242b7ad) -,S(18998c76,1481932c,e968af0c,eb84b250,aeefbf25,27e4ef84,a2519a1d,b7f857bf,455ebc85,64518443,5cac9ae7,7f3289d0,91133054,d0bf9ba3,9b7c8128,26c97fa2) -,S(64c76320,fa24572a,590516f,1bfd8b4f,87767b64,1e65588e,69cb895b,6a49b2b,a39a2a5,c4795095,a03ae76f,86825ec1,78366c8a,8799d395,d39fe8cf,74b9603f) -,S(41657405,e35eb87c,a5ba5f2d,3c6f12a6,dea917a3,3b3b44e1,ebbd3bf4,812b0ad7,8e2169ae,36f1452b,4577fe78,7adccb53,4d0ed75c,2096b491,6b68dd6f,95ff815d) -,S(aa200fa3,768a4b89,16e110c8,f4a6315,7bfd4a11,2c10cb6,8b76e30d,c0391f6e,567bd959,28b21555,dfec898b,d7d198a8,c49b79d4,6905afde,7fb3534e,a584695b) -,S(7aa78328,841d2f54,b843ba48,c8c9c623,eb529bd6,9e584966,555f9bba,77131599,6b4a2715,e4b8478b,24da7e7a,64e2f6f1,32711246,29a583ba,1bb44af3,69f698ed) -,S(94b1a7bd,6a2767ff,459234f,c78fbbbe,48446b4f,64bbdfdf,dae34475,396969a1,8f3065ef,2273a871,dd29320a,8b9aa41e,e77e2178,e8b8854f,df1e88cf,991cc33d) -,S(6b957ba7,1bfeebf5,294c8cb2,7681e0c0,5407df71,37a34710,35fd98ce,d526573a,67e4808d,3fc1853c,5e5cd4ff,6efb5092,35c6df0e,c0a5f7f4,583fdb88,7a2724a0) -,S(8b274330,ea34100,3be93892,ab1fcb2b,f9a6dfb6,80bd9cb2,b8aa6916,43717f7f,54fa2abb,77855883,e627f828,49c71389,4ed141aa,9c9cda3,c99afaf1,7998db90) -,S(d3f64f9b,67362339,491274de,77ac665f,3b686372,499a12e7,5d145e26,7b58db05,c06116c8,52bd15f4,145284f4,3899faa8,9bea5850,4018310e,5c82a050,c9a52449) -,S(198926f8,ce0e4329,1bb9280,390f795e,870d071e,801b4d4b,c4aeb555,f237ba79,76125bd9,5b8d07e7,5e27658f,a0dcf10f,5d6c10d0,4548dd76,a833f206,d2b3d34e) -,S(1bbd4d,595152f8,39746cfb,6ddc2584,ee4358fc,6f878309,9adca58b,cf01a13f,18f534de,cceac5ea,7083cdfe,3de5ebdf,ebdc70fc,4f0856e0,b587e9fc,df8d7733) -,S(88737f45,b2639272,37cb551f,52022693,52457f,21db398c,1312e275,f5a3132a,79a5672c,2895e1e8,4b1a7b22,21ba0c5e,e3e61cfe,c95aa029,b2a179d,e0c496ed) -,S(cbf3e18b,1f277773,34cca35e,8fe1cfa9,2d68497e,46e7a252,4e14bf,cccb1e83,db00c395,65bd456c,3c9d242a,5f24748c,7b91f770,926ba9a4,1ff5c94,86bc3f99) -,S(8070ef0c,f186efae,5f9c8846,72a93a98,8ab65b20,2720893c,40b1a641,c7022f70,da9805b0,46946a05,46824cf5,a87fd838,cc85c853,a745d8ca,a249d881,127bd9e5) -,S(acaf984b,8fa45dbb,e84c5064,8b6fe23,5c57dcb6,21243e21,90286980,c3f71eab,46f4ec16,8259fa2e,f144dfb0,bbae2907,801b8c1d,f17dd0b5,d1db3bd1,2ceb278e) -,S(2893a05,91f9ecea,735e8a32,a57e3d25,e8916252,52a44099,4eeda971,fbfdc965,6ea29941,91e4b123,12b5186,efb7d255,372aa6c2,aaf12a1,8c3b15a0,7bcfbb6a) -,S(64974631,68f0cb60,9c926e28,5ed12df0,cfccab0a,58f11b39,dc05b644,c2be951d,ea74181b,2fa885e2,4344bb21,9f2509c7,d432b5a9,c178b406,160489a,31eafb7c) -,S(b938443e,513394c8,b2d4f7c2,9811039,918621c,5d3a86e2,d1bf0e88,ba1faeef,af47f2a8,c7d98642,50784f38,45ff9414,c52473c8,9b669be0,96387daf,c353fc85) -,S(bd1ee245,ad10f50e,9f8fd4a7,876346b9,24f4758c,cf69bb8d,42f6dac5,9d2a5320,776e2e3e,69d88d5,c26477ac,74ffe92c,134ce443,64b39518,af787348,e0039605) -,S(cb7ec68,805e855f,17e7dc05,4279d8fb,6d8e1320,67a486a9,7d49df43,c660650f,f50790b2,84c04103,11f302eb,71525fd,b12d7339,6d259b5a,91ce4fd8,229e903c) -,S(ef07cf7e,affbb5a,29e22a1c,7c84cda7,1968c615,fbde2a15,e1c1211b,ab30cf83,98f4a6c9,422630d4,103fc2fe,e4c80f2c,2ca5565e,25859979,815c425c,70ef574f) -,S(4ffc1948,4d7fcc59,ccce4ca0,d11400f1,13dc5064,8626781,4eec26ad,3e7b8fc6,be9ebe07,98ff3d83,cb5ac107,5dc87f12,d94b65e3,937ee669,61b4e587,7fb75aa9) -,S(cbdd5373,339ed493,b8cdf0ef,ac6371b0,fad1ad6b,2da4db63,b4ed68bc,61d18396,527de487,c3212d47,1f538b6f,f709c130,3784a7d7,c803e5fa,c77bfa1a,d6bdb13f) -,S(ea035b2b,d8a1d7e9,db7f6b06,5e003f99,4e650aa0,e3035fed,65e7bf5b,c67cb5d2,aecb4370,2219f488,86772e91,afe81c6b,2cd57e96,2a3b0edd,dbc64608,8c3761c4) -,S(de1a4fd6,c1d6240a,d6e9dda6,b2d43fda,911648f6,901ed0cd,99ba8ef5,99f8db89,effc94d1,61c0ff41,d1ca6085,371e2e62,f85f90b1,542d2cd,3a4223ea,884da03e) -,S(2e644141,e8d87ed6,e1215787,8bcffebc,d75e118a,f00fb7f0,e58cf5b7,e6a076ed,4aa858dd,f2ba62d8,6b8a7011,26d22c2,b45c240d,f65f85b7,320e80ff,cb34b8d2) -,S(3844386a,90d6b878,90fb78ad,8f2d28e,47ff8879,2d275c3e,956883b3,71b73a33,f7f5df12,1a8149c0,75f6bde1,2ca8ee89,ff284557,f17cd57c,714fd474,b365cd18) -,S(e1fe9b32,1b91d362,2b618cd8,9ae8203d,bde185e0,bab2fae8,ff7e96f0,74358e42,c590fe90,1797132e,a25eff10,f2bf2a76,cef4f064,acaba1d5,f8537b4a,ddf3e1c4) -,S(560a00da,2f57d821,b6a0144d,45898af0,aefbbded,a1e08a49,9cc727c4,b27a3c0b,64874e4e,39db1377,3bcb79ff,983b152e,5db86d63,4dbbeeaa,a8b0112a,e795e208) -,S(9f33fba7,7ec8de2a,c1b16424,856e2814,1afe9b1d,bd0cd1dc,e5cbb2f2,f379094d,97cb8cd8,1838e2a7,26034f19,b5decd61,d972abd9,bffe3848,92fb0a9c,26fe94b0) -,S(98822fa8,24057512,48f9da04,2a0cfb15,e46ee253,e06a1226,da75047e,72d7a1b9,3e9eea35,7bc54ac,da547561,1f9590f3,db975d4c,ce7c4cc2,a553df14,feb19285) -,S(b814d1ac,4b757268,6ad88327,32f0f84b,bc72875e,7e21707c,c4086a06,ac1dbd88,b6364488,3749a122,401b8ab3,c4a7b8a8,c03462ff,18d69c36,cf145299,f18a98) -,S(246484c4,1e42113c,cd39f7b7,eed9dfcf,b39cf842,85c28cd8,6233c1a2,bd043e97,f35025b0,2e31bdd8,41d36f7,9d0b75e6,80f431eb,44a50502,3877f5d0,eb9552d3) -,S(9f330365,7b41b2ec,d87fff0e,4284e4c3,bbe8c524,91d358e,847afb98,ff51db91,4b9a7bcb,221c8870,de176a43,d4f7cce5,adf519c1,75613dad,317f4337,72d5e70d) -,S(c2e78e9b,3c75433c,5f5623a,8f5a4dc2,b0e71951,4b16161c,225b9bca,9d529d25,1e75c8f1,938376ca,c6387b20,9b24a2e3,e794362a,d62441b9,50588a3c,ab9079bb) -,S(89340ec4,b6e81b7c,855c9636,b548aeae,2125c40d,2907f86,7ce5e6ba,a7695391,f739a94e,263e796d,df1cc2c1,3e2bc10,2b2a9c9d,55248671,575c3ea3,792c72c6) -,S(9204ff15,f1443cc2,78facd4,8d38a6c3,5d66a93d,8fd8e2da,a7e2bbe2,d6629d22,2b9de875,456b50e9,6205020e,c293ff3c,13120555,82727253,be10263a,7559c019) -,S(f156da10,41122fd7,ce6b518d,c325f5de,61fad9e4,a7bd684d,7abc495e,ebff04d6,c73294ab,f4f2adfe,dcbaa78d,2031a5d9,7f2c404d,739f5703,76e46a0e,1b631d4) -,S(771a2d78,37d6413a,13099861,6050c362,2c379a55,26506265,9fa7da02,3280fa75,8b6bc39f,5cfe1f5b,82bef0b0,f6c8dd1b,e4270304,d5bc70f6,6b600b26,5d4c9aca) -,S(14cd58e0,36bb2c59,f63b52b1,f40e51cd,aec29f0e,b1cc0401,8e512366,85a18f69,79c254fd,ed354641,744c7262,39ea4e8f,ea15b19e,746b372e,f270c8d9,9c5e2006) -,S(e5f54077,1060072,5800bff1,390a67de,cd539cc9,52b6b43c,22bff27b,1a8633f1,d6e1c6c3,9baa86c7,5838e691,f9af8a06,80274da9,b0f54b5f,4c3b2028,8d666367) -,S(b0eaaf42,9c072037,fbfd14ba,79693d93,6791344b,3d37c3d7,5b8eaf8a,e7429197,d72661e,4a171b65,4f124d9b,d0201710,bc237382,6a2f0341,51051716,9b7af26d) -,S(e022d70b,44edaed,35957383,284e4ea0,5380f92e,cf62ce88,3c2e11e6,604d67c2,423c55d4,3ba0ed0d,1455228a,3153e9c2,7aed89b,2c3ddc71,52d2b11c,91ab4143) -,S(92a2d73e,b2eaaaf2,65a70f07,b949511b,af1a3eda,9e5d8651,349a665a,4bc5ab5f,4492d419,4794d254,9a089fff,53a32631,5f1703c,5ac34049,92d68121,e00fa973) -,S(43409686,de50a9c,cf35ac44,47a9ceeb,b12f102e,3ee6003e,c96235a9,8db9cb30,2f781040,952e1017,8e4e38ad,bd9c6c8b,c8e1e898,7f316cb0,37d2cddc,4e10bba9) -,S(d349dd1b,643f8d4,1b83aa5a,d735dc4e,94542643,3888a4e1,aaaa0ade,2394cd12,67f2f057,1da2b6ac,295c71c9,ea00efe9,cf082257,ece35bc6,72adece,433249a5) -,S(9a909a95,7fb87ebb,35f6834d,272d8ce7,babad39d,8f8323d9,c6813781,66dd10e6,ce3ead1a,32771a28,7f624835,2a2f6001,c12f16d9,f7093cec,86386572,a2ddbca1) -,S(f38b1e18,df2a2a64,9a3be25d,3686b5fb,1d77f971,1214d452,a67bccf0,ac07fa0b,5c9e9a,7f71b201,ba11ced5,9c0a4623,419a20d8,c488f9d4,591671ef,71e65ea6) -,S(42360fca,26b8d095,df52738b,c2762ed2,7b909784,c12b79a6,a86e06c8,31535a67,6b6f4ce5,e43ec003,be88bc43,2bddc453,db93aec1,657f6f66,5dec1912,468345e4) -,S(e3d7198d,a7c5e3b9,997993ea,a32377b1,b87325c0,5a002a94,53404c36,303f4a1e,72437218,ece6148c,df742be8,35fabfe4,a05f19cf,3205e65f,5c813781,2053ef4d) -,S(39412945,a8301110,6b54f625,8191529e,2f93db5,bd68db48,d6bc6d9,687cb59b,b8db822c,60f5c319,18b05784,40a958b4,e08b0a80,a1015d9f,d2826506,f250f08d) -,S(4d275f7,7e0ee98e,76b857c7,ed9368ce,d93dc914,d54ad4f4,21d2c097,cd241fc2,ecb803d4,9b502911,f619d361,f952ab13,935448e8,90cc2f05,277e48ab,a39d7473) -,S(29364876,c1db9cbd,a3efcd5b,6599ed59,160b145,3c8a9e03,c013f807,869556ce,2bdb4af4,cc44950c,84f56237,95941f7e,43ffb56a,77df186c,2dc31910,f23f6ede) -,S(7531f4a9,63dccdf7,ab83ef10,d3ba1333,6febcf41,f4b21e55,d380ee6d,e4878034,4753da9f,91d56bc2,1e9628ca,2d6269b1,e1dcb1bb,87c55e,9c44034a,1ba36ae8) -,S(8266d626,3d12feca,440dce7a,4bdf8ac1,6050ca28,5bc16777,a3d9450c,5c286e08,2500f2bf,fb8a4eb6,6a5e7e36,399f633c,96d908e2,5cda4877,5455df2c,afe2328b) -,S(66480001,4f339f15,8c39b26e,84389f87,6d5e62aa,59cb63d6,9eaa86d1,4bc589e9,a0699b3f,e3eb5a37,9f078526,375ac319,f145ffc1,da8a42f5,96c7016c,4ad92e2a) -,S(f8efcc85,8b9c0fba,605921b5,e6c89343,f641e2b8,e1f45134,86b77ab6,4cc70d49,ba97202f,7086f0d9,af5a0ae3,35d9a3c,5f4de2e2,79278834,f8b1d875,50a9d607) -,S(a5c1227d,254324a3,b1ec627c,93abfb3d,6f2485b0,1d8e2e73,6c542e09,9c992540,c9189db4,8a163bb5,6d99bed7,f38a7f7a,64cfef45,cf977da5,a1d16dbc,86ecc7cc) -,S(271b2619,a5b253df,fbb655d,7702dec5,6c85bb00,9260d893,8e050606,b8bbaf3,58ccf3fc,22cb8f27,dcdbd174,6abe5591,72bca7e5,d5af3bd8,d86c9a49,3ecd2ce5) -,S(c9e1382b,20c79741,d81800c,e721d4f2,1202ba30,92cac36a,d90c1dfd,570ae16,7eb1fcab,2a47cea0,3a92f707,d799749,6f7a0dfb,f9a43f6,90d213b8,1231e5b2) -,S(574b25,65232a04,1d58cb75,12b48945,45897e6a,8bd47dec,b1e0941e,309f2,bbfb86a9,567d74bf,93fbf2cc,6a9c9dd3,474db8fa,c2b5fb72,38b3af8,fe4615a9) -,S(9efe86ac,a6305eda,4b520e00,4dff6c56,1135e7ec,6953d2b4,a988d508,63046c38,4f92a291,32cb0818,af7cbe67,ec3b4d8a,7afa4f79,91a9ae42,551ad831,aae9af70) -,S(82ea48a0,ff76fa17,374bf4c3,d0918e6a,df26cafa,33d87284,13aa2dcb,d813f254,6a029539,9bb555aa,39de1ca1,417a8950,49b4c2d6,26ddf8e4,a7086b1d,bf2ac9f2) -,S(c289483e,817bb06c,31352a24,ba60adfb,e3af2feb,de329f4f,5fbde755,bdd2baaa,3b7ee90d,8b4aecef,62b6854a,1feb595f,9c49945e,c19685c0,4b13a1ce,1c780a53) -,S(6bde46cb,b5580d58,ea68deb3,1b0587b6,1698660,d78a8300,1c740b4,96e12cc4,3188a6a7,c1cd166a,4894ce75,c79d076,a41cc5c,d142ed91,e096eb32,e9293292) -,S(d1d2a3ae,2844615e,57f0a11d,66fd7571,176738f,a066cbdf,4519ac1f,65827cf4,7c0cfff7,c01c196,8b7697d7,c51562eb,8271f936,5c7daee7,f963122,67f603db) -,S(b74c0c87,4d195557,3b551c85,2abf9a5c,e276b088,cfaa0be8,f6515ed7,ba27370a,f0cb0e,380c571e,fe5e307b,ec4ed8c2,6f0c325e,114d71b5,51e0f1f7,45a662ab) -,S(a9a71b9a,9f126c3f,a17c3041,2317e118,84950077,baee298f,47d42609,f9015874,c05f3ffd,b31bf0cb,7fa4be1d,f634cecf,f1b1137f,551220f0,8f34c2a6,a42e0586) -,S(d6de1153,a161f27,ddb51416,2b3f823b,2b1b99fa,3fa21c25,9b02274a,80dbc68c,6c620863,659785a5,eec15d25,9acbdefc,714fab61,4e766215,348c80bd,bc59764a) -,S(dcaa1dbc,3acdca5c,51f8c22f,359487fa,73a7dc36,2a796df,11292a74,776b73f1,dc4131fc,c22c607b,4833719b,1715179,b4b4d49a,958c7514,7c8c4a8f,cc85159) -,S(135537a0,c4be13,1c3aa93c,677094d5,5f3a1300,95499d21,2206a244,5ab6c,7ef69f1f,d2d3df67,335f0d1d,dd52370b,8f3ebcf,e3483330,48c2f045,64fb0f69) -,S(28f1d817,c23262e6,4cd572bb,e3fd99ae,751dd6e5,5e9e804a,fb3fe9d8,39de93ac,24f5861,987e3da4,2dae0e89,67c835ac,8f5dfe8b,d41e5cb0,97029b48,39e2cb7e) -,S(f7c4ef83,6e8fb7fb,8eb31155,c08102df,e0779b87,9ad641e2,5f8ce135,44294289,7f9a781,db339621,d6150f09,16eb9682,16470d23,6957a0d1,3629964f,1f6bce2c) -,S(f1f5ae5e,1ddc9b35,18b66f7e,25a735d4,ddc8d018,5112faed,a8da8f66,1a28b3e6,9dbff12c,97924d80,50a4a8df,24fe7a8f,5c5c3486,3edb7cb4,1c6d9ddf,b9ad4288) -,S(95f83173,d170ce9c,1ca0dbc7,4578b639,257c10a1,eb65827d,c2afbd73,8b654f,63a83ebc,8294a88,413c3c91,c6918a31,7d5ab83b,7bee35b8,b75d1cbc,3412487) -,S(f4ada65c,9f095e11,eb88c8e3,77d60553,96474935,91be3a7d,f8c83c09,6a3ff750,e7683f28,a38545b2,e6cbc87c,3dbcc4a5,2ede1676,1b0dd78d,3ac51a5c,ad861ed3) -,S(41afac96,f714db3b,1b7bcd59,1dc7bc24,40b82756,d9394fd0,3afe7ae4,299e5fd2,9c2e9c6a,3292ff12,426e98ae,ac654a44,61c52d00,5da7af20,474e9a47,499fedc) -,S(37f30b1b,2cb81c9b,61941fe9,cca35f0d,e1b8dffd,c42f3ffd,ccaa16e,e8487405,92bf7a85,e3401d51,d9fdd08e,1086b649,8086bb3c,a4c9a2bb,61b1d54d,8cb88a0f) -,S(2f577166,646e7eaa,21531202,2ce0c8eb,605a2199,454c205b,9d760716,584fb3ce,f0d7326f,e43dcead,5ae0dc68,4d04b969,af32e8da,ed624ee0,98567dff,3d5f446) -,S(8abbc780,92c5512b,5eba0af9,4affdbf8,3c2e24ff,bf9fe7d,fd57e5ba,64b5150a,58f5998f,c2ec19a,a495b974,ffeccf6d,bb87dec,49152327,91a167d7,f6896b75) -,S(e41ace8f,a01376b3,27c73fe4,7e57cfc,f6da7cf5,c2810aed,219dd065,c147571c,b590aada,3c2a714c,322d0459,272f98e5,715d4545,196127a3,7d8a94bf,776844a2) -,S(300c9877,8b6355ee,ddd80f7f,4124789d,7c0c84fc,9d9ebb5a,be714cd9,890f1d88,dac2ba62,c5718731,c8f5c7a,4e1a7b80,68c5076c,834dd385,20f5e93b,e39c9002) -,S(69e339d2,19d40f84,25a072c1,f7876c3f,dcdb6623,26ca1b5c,87681707,12e24c61,8d439150,59a44700,2157e849,9b535921,4cd47280,937405a1,bad0b86d,38babc50) -,S(e56493df,8e47a99f,8ab3ccf6,41fab7b4,cddd779f,51fc746d,a2fdd484,cbbdb909,68dba20a,559e14fe,d0806036,d41c18b5,9745319d,758c1145,b6e49ca3,e3f5ee59) -,S(37a91c57,8998511c,d39c11e5,86e00eb0,f76532de,574d9c61,1a34d38d,e7f50587,e3a188af,d2d8a24,735975dc,9da895,feac2710,ab9d381e,e5d1dc43,b3145f18) -,S(c5f059fb,5cc262e1,12c629c7,194d783a,6224016f,65e4d24a,86c52742,dee88c1f,1c85bf52,1a96a95a,5177792d,590b46d5,8c090705,1efa0623,ab15578f,b38c890a) -,S(566edecc,d605ceb1,a298c59d,78401acf,c6323c63,f2845827,62678924,9b8716a1,ee0d1373,5adf6f20,789f85b9,32d332ff,8c40b3af,c02010a1,5ad062d4,5a44cc90) -,S(327e7033,c6ef4f87,52e33d,bccb4642,3e6cf4e2,c3ebb4c8,db69ccde,db2c7c7b,fc49092b,2be0f29b,4aa3e266,709aeb1c,12266239,f7bd9263,4aae16e9,53e8db36) -,S(989a7f69,3ac0ac86,55f29704,ea6caff6,84ef5ae2,8c5f5e1a,1eae7009,97778024,573d127b,3396458e,74bb5bd4,4acfea64,e8eb1fd7,3b0b292b,d1b7b642,80dadfd0) -,S(9ca7672f,14f27f54,ed1cec4b,74f49a57,7ce313fa,4a665976,9c22cc61,b30fc94,f920c4d7,31d52a4a,30803f81,82df8d30,6ab14104,eeec11dc,d2d6ca0f,3904e4a1) -,S(db100645,654fe8e1,95831687,17e2721a,6097850,ed2ef0cd,e1d5555e,7847f5f5,2b2c3ece,a9c90ecf,34fcdf89,5f76c8b6,619287ce,e745014c,96281928,31056567) -,S(4e2a0c9e,82743b42,5e6110a8,f3bff14e,418a34fa,65269c07,bb94d00c,d53295a9,512ac2e3,e00bb04b,6b4b9059,a3ac69c,8a34e5ec,8dfa14b3,d98b2c4e,3cccca7a) -,S(c12b3f70,24ea8acb,5136f98,185fb1cc,60c71a77,2943b68d,7334352f,66ac77f6,b799f99b,6f4b76f0,1f09f5a7,bfbe2526,d67a195,83327323,9c07bddf,2544803) -,S(64e5a2e,daf34e1d,ebd7c0cf,616413ff,d6c09b82,bfa783fe,aa755464,8ffd7e58,e020e09,66f032e2,e905d611,adf0926e,7509a2a4,b51844ff,72651f34,3c2f4a50) -,S(2b0b8b55,fa734380,f6ad1857,e03f02dd,3d66ec57,2cfb3b9f,ef040895,3f0a838a,ac897251,a9146597,8e0b45ba,e1c880a4,147ce01c,3408e476,5bd9013d,9e73a61a) -,S(ae0e3d30,a2026133,d3a54529,965a9679,6523e8b4,1efd4c5b,d6778930,2a88525e,fb6918ff,85632d24,250be67b,339ab260,c80c087d,da1efee9,7ec5dfb5,38f80552) -,S(2ff9c711,4dfea166,ffae46cb,1f44c3,3bfa1530,edf23454,a83de862,8fe00dd9,53f667a,4441817,a3e38351,78195c5d,acb0d707,bd20e759,9b5e82c4,6f318783) -,S(cc027014,88b959c6,c043f60c,c42b1449,9e2614e4,c19f5726,3edb116a,4e7bf695,eab3f590,9b22f677,666ce655,149a5f07,7b5325c,2036dfe2,e572e64a,5bb6007a) -,S(1801efd1,3c8035a6,5efe3b47,68495d27,f9dbf45a,f019d455,84d68be8,28a945d5,dff2d19e,fcb5968e,f4ef49d5,9a82f8b,f44a5abc,e0b68568,1acbda1b,fa59c4fe) -,S(6da2a9d5,7b60962,357c09de,4c7ababd,5b698fe3,6e747f8b,e6ab78fc,3cdd7cbf,1e274e70,4aeb8ae2,295ac9f9,b37c0af1,71310b82,99acc378,d505bdcc,e275060c) -,S(7e8fc96f,6a9215dd,3bf9e8a6,ea944ff0,c7dfe23a,1a99f44c,832a11ad,bafc82e4,e9a4fbe1,e0c26ca7,f739ed00,c63f3886,57d09503,a808ed51,ddc872e3,b1342bff) -,S(a6362f3a,77d6d6f7,fe266ab3,78707641,9f53e133,718ccf27,559bb448,7e0caf64,c01622da,3fc2385c,60a5cd86,66f751b,e29d8539,f473cd70,8784d61,d2cc787e) -,S(51865222,28b47493,a3da19b4,7076c1a9,8582bd55,37c25557,44970075,9b37d2b3,f0f0b979,68638d9d,93fca65b,f40cb8ce,826558b8,52451ad1,7d0afbd0,44287be1) -,S(a2a0909b,a9f1b9c3,8c714ff4,f71995ab,4d80212,9e8ee8e6,7e8bc3d1,81d472ce,4123900b,d45ec7bf,71bfdf98,ec453392,8b364d1e,cd925a6a,1e8f5c5e,ec40068d) -,S(da518122,454e7f36,a63f5ac2,a1bf979e,f1357bea,f9f0c921,2b031f87,b83aef2d,bf877efd,d415e80,c828c5e,1b9dd8b9,6cb7f3f8,b9a0cb32,b6bd8f37,686da722) -,S(41c40c54,1a983125,e59aa572,910c5aa4,8a698306,d483f82e,6cbd7506,3947a87d,76dabb65,6b89910a,bba9f129,ffbdf5e7,ef840033,c30f4c81,4e86f101,a3bfc57f) -,S(c49fde83,87f2e464,6847c980,acc50d88,28745e4c,88a41318,709099cc,9aaddbfd,a65bc512,dfd07bd3,79cbaf9e,628be7f8,c7ddb4ee,6611fa94,bbb48c7e,ae7227e1) -,S(85b17d61,b6ee743d,4df21940,6d7b7426,3a6c6b88,e8c51071,7a1f0183,e0fceae,22b9e8a2,74c71feb,5046ce02,2f4bffbb,ebddc53e,704f6be8,92d3092e,55868fef) -,S(c8e1d37f,e6d677f1,3e752189,505639ee,3914afc2,c8d4e43e,883f5c54,f117964f,b0cacd18,d08f5a91,af46ba55,91f99497,ee4a7ab4,36ab48e4,f88ad5ab,39bfc21e) -,S(dfec0030,7d25888c,5a7d6f83,33112995,1a30baa0,b97add9,866078a7,e483836b,4e5a8a06,bf2e9447,ef466416,82af8e44,f407ca0b,6fb97809,56e13a90,bafaa00d) -,S(eac6c438,7c18d8c6,eed7618d,c9d3076e,c842ff6e,5f4d4b20,92594d7f,7f0be9d6,19d69bbf,fc0c1b82,ba71802a,c0feebbd,77a86a67,d734a163,4e823a6b,2265b8d1) -,S(9ff38c4e,4dcddec,a4824db7,97f6ac80,69432c15,9cbc99b7,4d642011,b3424cde,f72fa660,b7c1bbfe,df45b0c9,3cc84b81,266bd041,b94f54f9,1d26221b,51619ebc) -,S(5e78593f,3a5a3293,5f9e4f8c,4fe28555,9153f69d,d44b2c1c,146fc644,a5313f36,9d9d5844,dc63bdd1,b2d95b70,5d63c97,58cbc5a6,1b2d114b,89da9b9a,8afd9c47) -,S(a107c7a4,89284b6f,b01ba38b,3e221c2,ad31a48,77af9b32,d22c8544,71009ae4,66072d4,6be46591,ee386cd5,bc0f9f2b,653b580b,c515d4c4,a0fc369a,27d9f6b5) -,S(241f1d0,308d9845,fe2445ba,67929976,ff98e88e,cc23a8f4,190ce5fa,41b02af1,886697ec,d413a88d,fa15723a,daf91d32,9c881ee,c5ac9c74,366b7ea8,a7e194a9) -,S(319ee8d2,627f906e,83d5c6d2,6eac3b42,34186016,8b9a9283,c8790c6b,e48a72fa,59e496ed,a67816e0,3409f849,1cb458c5,76034453,65fb281,9d0cc427,3e9eaa57) -,S(1866811a,fdf9bd,937f4f7e,96985759,e0100866,192878e1,a2614625,bfca4822,215e0465,e85f9c88,2783a131,6b65fa7c,585f0319,1a642501,72e51269,d5b7ae19) -,S(7effbed7,b949000,5db429fb,8cf64099,3989675a,f7394ce6,9ff2f769,53992f26,6efbb5ba,28f26d4b,5256affa,cbf2dc0b,616d8b6a,c6cd2aa7,a1d09ac8,40c7c749) -,S(d8c72bd0,e59315f2,1fee45c1,937952b2,665c8d66,70f14bf0,957a4d25,2b168867,64c02d62,fdd40a6f,d11e2cc3,a73fc60a,8a2da31b,2c99ae6e,5a946c61,be56fbcd) -,S(710ec622,ce64f381,43b96bbc,b0b0d691,87bbfd51,fab4d47a,bcf18308,18d0db4b,edfd1086,526c3af0,c2e9b961,890f531d,3d275c36,beabb0c5,4963314e,4534d994) -,S(9427964b,9aeaedd4,9c168e76,38086ddb,70574f27,9e4c3348,68e4c595,30d51ca6,110b41cf,2a6b0067,eb3b312e,928583d9,e0026bea,684c57af,7300a611,5c4e2dd8) -,S(aef79435,a8b3ed9c,9eb515c0,6db62165,c5a2e816,5eaa4a5c,46a59b39,8f55565f,6616e8f2,1274c425,c50cb93d,8942aab3,3653511,3c3552a0,118b17a4,5584b91d) -,S(3ebdd832,3546063a,68f40193,59d72f26,f49f0ce,4a5af994,a4ac67f3,3074b5a3,12367d4,b29549ee,d0eba318,f395d712,db7962f2,c8e2d9be,ed895006,78460238) -,S(a38d9e5e,c52b0871,d0bc6bc3,b673c848,19af86e2,534d60dd,729b405e,426aeff2,ebe46771,d9ae6c5d,13895538,3c8de4d5,f6d13428,8ac36a1c,b01c75e9,f32cad02) -,S(e7d29f82,619cbb19,90c407f7,b452cb8e,334369a1,16901b0f,9f4ec342,48a7d624,7595ced4,618b5160,6b8ce230,45d7616f,15b6ce14,aa8eee07,42bec5b5,9fc4e614) -,S(ec869eb0,279227b9,4ae333e2,6018f00c,7523de5c,e3e8c4ed,f81cefcf,4043ceae,a421aa55,2c89c841,a48bdd26,4e67d82b,ca3fe577,64101556,ec6ba7dc,711ac92b) -,S(4549d908,e44a8c8b,6fc5c057,144a352a,6f07523c,e026fae7,c070ff35,c6ec5e71,71d8e320,7707e04,10208c19,e2c8dc79,64b48600,1a6d640f,44c1138b,7ab5dd7a) -,S(51bb6e9e,fef7b8c9,b0a4f381,3e1406b3,2cc7a53d,165b385f,f98144b0,a5b070b2,65282be9,dd794fd0,8a31de11,d46df7cd,5268eedc,aadf3bef,de5956b5,a467044e) -,S(7cdc3297,4c7caa82,44203afc,d48e625e,aa2027d4,d91613e4,5a83eba0,696d001f,b92b9943,3b1a55b3,b78027a7,a289e5a2,6060a411,6c2cca36,19253490,83519565) -,S(3ca9c6be,b8e989b6,a67722f6,d817a6be,aa478fba,10146fc9,3099575,609c9314,5502ed7f,f4b81bc3,8386bba3,4124ca30,74c6e0da,bd148e4d,6bb7f096,ceca2c0f) -,S(aa2abe6c,45edcada,f01bc1c8,38ed5e63,90e1a229,cc920436,864111e8,ad354d0c,1b8229c6,6f91304a,24c61251,f1ba2b26,95bb3da8,87154d47,c44dc9f2,f824f6cd) -,S(b52cae3d,f28c9d59,319f226d,ef73b60f,75466aad,fbe6f75a,2ab6936d,8e3bc7ee,ebee735e,22c091d,cc873848,8a7c958a,421e0759,2e17fa3a,4462db88,8bcfe220) -,S(c1085703,62a6dcb6,13da6283,23496169,635469c3,47b65661,838d9053,3821ef54,fe6442c8,c1e6a8eb,2dc2cac1,40ad4c7c,44511cdd,82b79cde,c38cf9b3,4ceaf517) -,S(f09e9d1c,fcaf127f,59d45476,56422907,83477fcd,2fa6c768,d5a3965d,af08c11d,f01a722,1f44fb15,bf428fc9,c5d7efd9,a5b2e663,cfecc9a2,7e8f964e,8bc15d10) -,S(602462ef,1e473ebe,d88b3b17,9d71b597,fd3e805f,e03d341a,36c277f,495c4527,f91db461,71411dce,aaad9f23,53f2159e,fed2a9b1,eb9d2ce2,844e1f6d,63a079c3) -,S(273a881e,8e0d99fa,104ae355,8126a20d,6b828d13,96bbc70,720197fe,9bb582d,5bb26c58,14a7b914,cd3b2f72,7f76b6c0,d1b40775,79a2c3da,29534a1a,684b0d5d) -,S(7c1df346,616cb72,b42f4172,36fc98f9,e8cd0504,1da47d9f,566c8df2,e80cd54d,ad3e7e0d,d602b9be,45ba8d45,6bc12558,73153c2e,c16773b9,390ad630,4fc41dd7) -,S(796e2634,657ff114,7394551f,3ce800b7,9ad644b0,539786d3,c62c6551,3d942f94,b65bbe38,ed587111,c480eb9,c30081a4,1e8ec66a,8400db11,bb1cc7c2,a14f1c60) -,S(5e2761fa,9985f68a,a469953a,2a6642c8,62b0565b,602fc206,193bded6,1a302bd1,5ba09b70,9db24f5d,2f47c07,51367d0,3715c9da,b7d430b4,713dbac5,7253e274) -,S(46458c92,fd341a0f,eb1ab038,5a246b40,5c004c22,98db90e6,164126c5,4fabe794,859d68b,345341b8,58afc324,263f1ca6,9d018fae,eecf33ea,f02a3dd8,d7446725) -,S(fc481830,bf817c1c,ffc9ddc3,d6f4e624,a410e134,cbfb952c,5c7379a5,81153265,a188b228,bd3d7da1,44a48e89,fd9db4ab,8dfe385f,ace8e169,a43a2787,59322551) -,S(42d9767d,9771a550,3c702742,ce2aedbf,3a780466,804ad901,7792610d,5eed03e6,df69432e,9764f337,3a2c782b,e02d2433,d2e0f568,d0dd83ec,e89ea1c2,5ad50417) -,S(37122c49,993ab297,72e60222,615ed912,462deefd,d28e04dc,dc72f4e1,b9477148,627ff4f0,924cfbc3,aa0422cc,36402b8e,410b3ede,a552408e,f1d3820c,5996e39d) -,S(9c548182,94bafcbe,743e52cc,a76e1ead,3619a557,a5cb8bb7,3140ea1a,5c6896c3,5fcc472e,b88e8528,ec71dafb,f70504c2,ec0478b3,209494c5,b53bf05,b38f7fcc) -,S(7b9d7ad7,aa5b1f69,75c4e025,17123608,a59277f,d63f2a07,7ae69b80,f65a2db9,6cde1ee8,714aa229,d01c14d6,f514ecae,c4a7f15c,a756812f,abfd61fd,d7d1bf8) -,S(af5ddaf2,c985560a,d656d948,e41e082e,6990e950,6c77d53e,171cdea,58a9a102,e348451b,72896ff3,c4839ff7,6ce16b59,1f685348,eff943f5,fd4581f9,eca5b505) -,S(42667f18,e957bd19,5fab366,2e0d1565,d26394b4,14e2a9a3,95becb69,2111293d,288dd2b2,69e9bb63,4e7fb16c,1fe25797,3c0076b1,aecaa2a2,e57020d5,66bbc7a5) -,S(5e9c7a1d,50ab8326,74c2a5a6,f32665ce,9be97161,5e59b618,587541b7,40b276d7,92283461,1f39af42,34292c61,2c70744a,ec466418,ee08b5b1,a298456d,5fa11f17) -,S(98c60ffa,f486b582,2b4d9ac9,7b320b97,8b52b506,8b46bc48,9a2a4f28,dfed8b2a,a1c26113,c2534955,812f42fa,306edbe5,70416d84,aedc132b,5807b29b,745280f9) -,S(92bfa982,1ed52cd9,3c286e71,f350e5a7,f309481f,d866516c,f0a7599d,c385babc,a3fc9796,c71ab4b1,b7a54e73,8dfe24f7,6f527692,9516bcb8,2fae9ed,b2c1ddb4) -,S(9be27408,bd8eb59f,ace413e8,402b0c37,7b7798b9,3bb18c4,ec197382,fa5b865f,11085580,19646a39,68eed2c8,1bb92dde,def3ec29,5024c027,f54e8bfd,a67a2f61) -,S(27cd6a6c,b7bab059,6b791ce3,8c0918bf,7751bc59,db9e5827,5b1b9c46,976350bc,890d5167,8fce2ac5,f13761df,68651e7,2f41d04d,4feb4011,a16f80ee,83faeda8) -,S(e896e14d,aaf96139,4c8f6597,a0c66463,5f22be3c,96f30e1f,5d8881ce,f468f2eb,beb004b0,512c1ab1,dc4d971a,fd88baca,efea7e84,dadd2726,bb9f2b3,b196030b) -,S(24e2d269,ac485401,634b3779,efab2c0f,a9dd2389,850bb3da,54ec0d67,e53f8ec0,de702ec2,642bd4c2,3bca2ca,663a05a3,f5beda5b,e41fa460,8929aa58,219e525) -,S(97a627c9,48c1c9e4,5d50159b,4b121a50,9b5c4d01,de0a7db9,5a9d9c09,681d1676,19bd095b,55399c29,fcad4303,7f5d5c21,8d5f3cf9,a7c90b9f,fef7ee92,6f3203d9) -,S(a70d8251,e604ec5f,777234c7,f9d3c850,33ed6760,1fa0814b,40bd5370,7195b08f,df28d907,74e23de3,f152c016,ac710d43,85325a89,6a859f4e,e126d50,acbccc4f) -,S(2d676c43,4b276472,ce01a007,13d78b17,27743a97,36f3412e,a7c8c15a,fa42f42b,be28cde4,6ef5d32,403b8f94,1082b684,52fa703c,339498ea,24c08ff,c9fa7312) -,S(f66c25e1,75167275,5db857cf,cf27c036,46c89d29,b4a0d729,28fd42b4,b29cf5,3ee23ad4,22c4a884,4c049150,cd9c18ca,8d2a0231,bad69b6e,5926de9,c7193201) -,S(dba47c4b,9d39d87e,ef44f81d,24e8e005,ce6e77ad,8e4fdc6c,29393d7d,2427060,2d5c6492,e53d000f,977eedd,4dc3b5c5,5240f28b,9fcfb597,338edbbb,3d8d7622) -,S(a17601d9,4f627dc5,5895aeda,e91da3b6,94788f65,f083b01b,bfdf8815,27e10f0f,74089fc8,cfea1b15,afb025bd,99905b3a,baded5b,45e30890,fa3d8403,360a1183) -,S(dd70309f,b84afe90,7e261a12,5fb7ac8d,1c24c6c3,54eb83d5,188f3a13,4d80e141,32014ac0,ac93a77f,9d35b786,2c88ddde,4bdfd566,f6555868,2a836535,44bed563) -,S(79fd503d,e746baf9,701253f0,4c6a2f3,cadefb93,920c83f7,83b57768,87037afd,3c5cb658,63180931,3fa20c26,647a523e,86a4e600,8e8b17f,1e0d690d,eca61b93) -,S(d1aaf37d,77c7d63b,1f4eb896,16a29a4a,1e72658a,93560956,6b92c122,ba0ff6a0,e535b7ae,5cfbba07,2bdf0e0b,bf435bdc,c7cac39d,9d9ae32e,cfd13945,3ca93bec) -,S(68ff1b82,b351d94b,9b6b74fc,2cda4345,fe525d58,d6599644,5c752757,aad93c4f,abbb0ef1,c422ac08,d06194aa,c5d93bdd,9186e374,8518192b,79818f3a,b465a13c) -,S(22785c97,18063e5d,5db73bc,f4ca6487,14393ea2,62ece24a,5c41c059,9610552d,9c08026a,d7a7a80c,24c5e75c,8a75cd6e,1933e64a,25cb98c4,157181aa,ae1d8774) -,S(626cb5e7,563fb757,5f066258,3fc21762,e2678063,a77d8580,8891f244,4f5ffebf,8369ff6,72c3c3f2,43516184,5a9851c1,953a6da2,5662e11c,ce170cbc,668498b4) -,S(a99f0ef4,d6f46105,80ffa430,b88a4f28,61c8c4e4,b6fadac5,5e668f5a,80d12d2a,972adf29,39db0083,77802c40,6ae2aef6,4e2f064a,f8304d3e,28fff33e,b1053d06) -,S(b243ce27,2ff0b2db,cb80a3fb,dfbe94ab,784afe3c,cab3fe61,1931de9,c7f02645,db2ead19,fbb8c820,c7233df8,fea51836,3e85b858,4622be9f,41a0448e,360b7559) -,S(c74e3c9d,685cb62c,6a71b21a,a1dff5,43efb264,543222f3,f8bdf570,4363deb3,987d8261,fbf23d05,a38358ef,c4efb61a,5cd550b6,1e833ed4,38734486,edc4b2ec) -,S(ff2f64a7,fc984d4b,d1c885f3,4c096e9d,d34710c2,43dc3047,8886ef0d,ddf71c47,14c06258,fd5e2fdf,1eec9125,7690c0d7,9eac60d,785f2497,65e1a85a,a06e906d) -,S(7d92c4e1,3f4cab24,d36e8a8b,140f743a,6819b514,f6a19bad,ec162141,bb712085,606b5762,2ec7d7d2,a9b19330,9da686b8,3e0dc920,e6be33d1,b726f416,81b698c8) -,S(3a43d4d,9ef45289,89c9487c,77951602,4ce0cc20,ffbcd518,a0bd2546,fe13b6c,5f24d325,5768905e,6ba28d61,e6b126a8,eedad2a1,53499912,dfba3fc0,d9deb36e) -,S(8e72f02,80105e4d,15cc67e7,371d0c5e,6e59fd05,b3c66308,67342a6c,eea25f8f,94ddc51,58fdb86d,f09870da,47b79b03,1eada5ad,9bbdd509,9ea1d9de,96b368e) -,S(b89cfc23,6dc02762,ca77f9d1,8343f12e,ab8789b0,e5872d6b,fd9d013c,ccef54dd,9c9a7285,45a5996b,4a6ce6f9,df860d11,c3ad135c,f1f7437d,2ba7b904,411141cd) -,S(e85ee008,979868b4,bb190b53,5624b3b5,6744a43e,2c473ebb,c64e4910,41ccb59b,d3afe70f,9edec50c,227e3b3d,7eddd1d,e1c9a8b,f842d723,a8075a52,12cbd6a2) -,S(d8dd6bf2,774d6d15,93cc8e16,d5134066,f7f90651,39915b3b,fb0d5d93,b6cb97b5,5a203094,5f734f3f,11431862,b85e9f8b,25f7e6d1,91512b2c,6d256f4a,535e26f4) -,S(77e081c5,328fbdeb,45fbd554,5d133d84,33968ef,98d36aec,3e6385a2,76aa94e8,2ce853f7,ca25f2f8,45a6291a,3e080504,ba597fb7,91a21669,c0cb6be1,14c2959a) -,S(510786ea,e8a49682,6820b82f,549f07a2,b5b9203d,b1ad18c4,fb9c479f,67c904ab,dc130385,4e4dc69f,f63e21ae,71dc8674,b39382c1,eab1d8a8,fbd96867,af9cd96b) -,S(2fbafeb3,fbdad5b6,4c121056,e080d0c2,1169e433,3abc0dda,bb642789,a242639d,a85d82f,d9e6a14d,e599ef0a,11d3eb39,5ff199c9,5ea5f1c9,2f3f8a7c,14405cd3) -,S(200dbfeb,6e6e463c,1f3fbbc2,6b5f00c6,aec80809,1e28eae6,73b2b5e4,7b12ae0a,4852a219,bdaa3d97,83e1f071,15491827,83212776,fcd1b44a,c59dc01c,bba95ecf) -,S(27b140f6,259f7dc,93d46b6,e52cdb85,3ec22572,54218ab4,1acff2be,24b8a3d9,3ceed09f,70cbadba,d40054c4,f130e312,28bb5d63,71a74f7b,c85aa7ff,c0583387) -,S(fe4941ee,535c5311,8222ec35,14c2b02c,e175cca,d728ca0f,cd1d64ab,e95b7e71,e9cdc9ae,286d651b,d89cb442,2a64ada3,748e0ade,585cb70e,d357004e,e51f56f6) -,S(317d209b,4cae94bd,36f443d7,65be2f17,ce47ced,59935d88,5a03925e,75ff1cdf,c191495,68fe571c,ff945af,4b6a801e,c942a5df,78a62864,5434a5eb,8a262d72) -,S(f951a777,764e30e4,7705f8ab,150e9ab,df32e80b,593cecea,d9f9a143,cc93f9ea,efb951d6,25f2223e,e6ccc6b8,b12cddde,6ac2613b,11ae3052,65570f15,23afd925) -,S(71adf0eb,f5fd8e8b,f0f229a9,ffe496aa,4f251af6,6e5a284d,3091f344,3389c8ef,13f47463,293a5536,674dfdf7,2dc73add,98ed5672,e7676425,39ce655f,6b6969f4) -,S(2ea0406,58c0e80d,499cff39,ad463412,c3fbab1e,81f6eea5,911c45,236be75,be52c74,6073721,f09743d2,9a0a4e3,d82c08ed,feee2234,29163bc8,954f923f) -,S(42352390,4b3e80c2,750c4222,33f0b1f3,a373442d,96278935,d9b7e51,b6182aea,7f582349,b27b5166,30c8e48b,a9603224,fe09e8f,814fa966,395fed67,d9221d91) -,S(524d3c82,a92b285b,96064bf8,e9abe0b5,7702a29e,dc08ce53,771fab9e,fa7dda91,a47a0217,fdc6b2dc,d4b68e05,331bfd5c,366a8477,d3ed894,ec747240,f0f29c3a) -,S(f6ee1e08,5ce04de6,6aaeb5f5,f232329c,fc83caf,d16bcc48,776bae16,c056f7e8,3328b26a,7e2bd49a,aa193977,4947d7b4,ccbc955d,18b27c75,c2f6ac6d,bccea4d9) -,S(9c2f7d2b,b88f1417,722b5d11,95077d20,2ea84e6f,9bd93dae,3134d16b,17273978,1089f003,66c8b435,ce73c592,7c5e56bd,d338a4ca,ee5307da,a571be3c,2dab2a3a) -,S(593a1eb6,730fb6e5,1fd24f15,253ae1e7,5897b7b,48efe28f,9b9813c6,ca99cc3c,fcfb7820,fbd22d91,bc03a630,f74e519,9e35c1a,a3b1cace,40433001,7744f079) -,S(62ba10c3,83a7bacc,bcc4bc60,37f87a5e,8ec0eaff,de5a39f4,ef352b1,51f957e3,c267a1b0,dc84a161,a565fa19,aa0a2501,9fd01e0e,d7a660be,c2a7e9fc,cc7bdd45) -,S(1de2ac10,deae62a1,63f641fe,3a4a9da,39e12390,14a77c6a,6d73c619,5f731f64,60f43c95,b6d7969d,427b5ad,782214fc,a512b75f,a6f50006,d7141a89,dbc8d2b2) -,S(f11a5552,709083c8,83d08612,31772f18,c48e9271,6acbaa6d,a43416c2,fd4e1d3,a6d0ad64,7cf48c41,b6ce397b,38d5b3b0,2be51554,da2f3f4c,df593514,a2d742f4) -,S(f4454640,d75697e5,21d5cc01,fca5c7f5,3dbad43f,116c243d,2aeae96d,7cdc33fc,42972cef,46fe7704,5d6d7053,1a74ec87,6b25996b,c4cf66cf,b3784f79,66549102) -,S(2bfaf073,97be067c,1b7c20fa,3b319fad,10905b8d,8ecdad4,cad2ec8d,a1b8780a,ed526499,ea97c967,3d28bdee,9970f4fb,9077deb1,5f823cd5,775cc526,4e590285) -,S(fc1abc81,2b5fed90,bde3ca16,3422f73a,6df6e058,8ed69222,cfec54f7,4cf5f73b,db1c6edb,471cfcbe,468481dc,4b1cd1c4,7ac68f6f,4fe9dd8f,af0d1136,972b975f) -,S(d838c2ac,82e02f9b,a376f92d,293c02ad,b717d65f,be31cc76,12476e6f,4c506a8d,d87a3067,388f8e0,3c176f6c,a7eab123,532dd1cb,3e0f6ae2,51d7b31a,35189377) -,S(4b3a82ff,7295749,a259d54c,a9a5e539,32c53ff1,33a1c4b9,2f697e06,b13ee38c,44372b41,a788456d,3f66a0c4,6c815210,bf60734b,e570a290,32db3075,ba8d6265) -,S(d77cbbf3,6731ad4e,325eaf6a,9bd52f70,8e79d290,e379c2f2,b8d6ad3,fce411aa,ee466d25,f07813c7,91a81237,748bda9a,51f4266,4a385b50,5259bf84,ff8372f0) -,S(3867f6b2,58920b82,6eca75dc,953ac307,bed1872c,c0f1c6ec,84efc6d2,eeea1483,cc6a6adc,e6078097,a013ff18,dca9c5c9,254d70f4,68ac1cf4,b8267135,af88aee3) -,S(7b008875,e85fc84f,618ea7df,f20f7f17,2123fe98,c07b5279,930b52ef,cc1b0a9a,3f3b30bb,8dbc9169,a5c55a1c,4150772e,331f7834,b50bb904,a8c56600,bf075f90) -,S(ba5b44d9,16304a49,87579560,4d4b796,907e9b7a,4da49a5,ba7a1d77,8e34ef3a,16b49baa,48219e3b,9bae124f,dcd4de,4d47ea76,3ed39e13,f874c75b,cf333661) -,S(691eafe2,7fe4120d,852b3a23,b5bfa646,910fe521,355a3594,342d629c,e2b8d9df,43a06097,42184dca,7c294fd6,a5227dbd,bd71ea1d,c4bca878,1887f9f8,b6c71d85) -,S(13a6cbb,c9f5a86f,35173e38,a45dca65,551377d7,c37542d8,44006e48,54a54123,ecf3809c,9a964d9e,ffdcc2e6,2e8faf9e,8a43d38f,3023c4b8,84d18948,8488620) -,S(33fd2af3,fb595cd2,93d731e9,1b4f0e5a,da665420,2dcc36ce,b712e8d5,e6f10e45,e26a307a,a8bdda4,4b981bf9,808cfa3a,80ca5331,b3a94c31,f6331e60,98ed2cf) -,S(75954033,59e47f78,76b3ba57,5a758493,b0033298,22f4e44c,15cbe58b,34b774f6,7ee9a040,70b8568d,b0a99855,3442c000,b6e6651c,a7ad1253,f8e703de,5e0458a9) -,S(79199fb0,c3b17e68,4e815e7e,8414bef4,b3dd3665,10d032f3,6505da59,6f5b9480,95bca973,f358c9cf,ef3aacba,54a055b8,abaab383,4191a1b5,54ac3ee,53d9a0ab) -,S(9705f4e7,962ece0b,2e7ed64e,a33fd40,6edd0bc1,ac8997b5,d6d70000,a51aa352,4d4ce757,ad4547a8,a126193d,8921d6d8,58f40855,f71ab99d,b2bdd728,499ff347) -,S(881af067,b841ab5f,30560b98,3376674d,cadeeb75,b8b16e12,df7da3ce,312fd777,ccc13fd4,512ef05d,7c10f62d,8b144b1d,7588be3d,1a3a3701,9accdec9,3483b84f) -,S(fe8f7a44,33c2c9d8,f42e14cd,97ad0794,41bfc3b7,2fd412fb,1f6d5f5c,10e99621,e5b576ee,cf34374,96dc4ee3,a846c79b,4c8babf3,cc46a657,2a93fdd4,b6b3b2a9) -,S(ff43c8da,18e08b38,3f92f832,3c34e83,84f40064,9e0506cb,91893abc,5c4d798f,a575a059,23a9da02,c0c9dde1,981dbd86,f5a75433,a4bb2fd5,2427db01,7ddf2e7f) -,S(4715056,b97f4e21,13485242,74bb1b33,d8f9d841,73678a42,ed3c6fd5,28db276b,b4c0d146,3521f1d9,fe8cd71e,fb98aa28,73a18bee,66fae12f,cabfa201,854302b2) -,S(85c9d808,c5f51d5a,c2a51394,cb83e7ee,acd85eeb,31a88814,9744871c,271fff51,2a7c3bf,23829b88,66991454,d6ec7f5e,185050d,1982deb8,b4992bbe,5b666a7d) -,S(c02b94ef,8b1e368e,3cb4b25,903445cf,f46b60c7,6d6d2f24,529997f9,7d70dac9,bbb97d29,bcff81e4,8d417825,ade1d28b,10fadba2,acf961d6,80a343c1,e725f3a0) -,S(4b1593bd,28e26f7e,431ac439,3d353a1e,fcb8b63,fee7adb3,e29472a8,38241df6,8a67a728,f4966855,26225b11,3ac9d858,3f184f8b,3ccc8ef0,d6e4e34e,f2fdcc56) -,S(f640755b,ba51dee3,ad650555,9d52869b,7a8e7f6e,4b9dcdd2,31d1cd4f,26a64dd4,7387f800,a53e290b,d4c29f6e,ec24ac07,91e0e3c8,55d14882,a48d0539,6e87e1c8) -,S(949346a9,436836c6,3df6f42c,d708cef8,16d0a522,914a606e,2276979,7789515b,a903932d,952a0201,ef65c847,b8754174,31dd41d3,ede5c073,31383b9,a8e2b356) -,S(1824099e,c769edfc,2390b1f6,698c22f2,cdcc9783,c5cbe45c,de46008a,67f91a60,f8405fa,81e04dd5,6ce051f3,bfa088e2,804a8780,37892ae0,adf42767,311bd1e2) -,S(e6b46fd8,e4633d92,8805f34c,ce95f3dc,683aa792,139c62f9,2ec8acd1,d601d341,533db813,f3fea63a,528faf4a,7cbf58d8,d6c0bea4,c28391d1,6391d300,cc1d824a) -,S(63799b30,dc19b18d,d48d150d,3d4139d3,a04c6252,f176015d,60a436cf,ff992b93,26205112,5ebf4dee,d00e72f5,ff064178,7f485cb,2ba35507,3c3cdb0d,16dcc41b) -,S(8cd02f5a,b1d5a02d,e85b88d3,ae370b0f,7fac5324,9f1fd676,670a29f1,2ead7338,358b42ac,ceb689d6,612cb70f,bc9bba7,511d56ee,c4390627,8e2f0961,bcc0d8e4) -,S(d5e167e6,d48bd1dd,e95aba41,bf33b065,f7612766,4a0a8991,d3ea1a9e,ddf82fab,6cc23982,d653cdf4,fc4ec9cb,3cd86ae2,aaf45f62,38257d70,849c2686,ae71d1f7) -,S(c4073500,6987f2df,1334f09d,97f00c19,d72b1942,5864b0cf,4ff19dcf,7c9bfdba,f6566846,6b461326,a9b366bf,30378f82,b760ff0a,ca568ca8,2bf0c9d3,ff7ff262) -,S(9df1e71,9c501bfb,8a21db2,a838318e,29a7c2c0,fb2deb91,1840c7aa,f0c4fde2,cd628cae,6d0e0c02,b0315ae5,4901e703,e977c75b,43defea5,80a5325c,fad00fc0) -,S(95176429,df73c309,23108ee,6922c597,1c91c249,ad7165b,7d08b84d,2a4c696c,3ecffc49,3b62dbcc,82208470,375c929,1994fbb7,240740cb,dd8086cb,e9c0fbe4) -,S(708c48e8,692b0d35,e13a7e0e,94be8fb6,f57fe187,34f5556d,a318f600,c5628c6e,9534e302,deee1d1f,27e0432e,9f6a2f00,5af7e601,3f7da9bf,e1cde320,a105a664) -,S(2775e17a,b82dc739,b5d62079,4b26be15,46275ec0,9d32622b,2991cca1,4e5b4c09,3aa6ee7c,80e8359f,deeb52c2,8da1328f,338ab228,8744d52e,8a9b7908,1b1ccddc) -,S(47c1aac2,39c4f31,cf334959,b8fb48a0,44da6b34,3c383270,be19229c,30192da,5dad651c,5ba6c21d,845cd402,59a051c4,e5813f5a,21228355,1fde158b,600d7cc0) -,S(f80f445a,4b864c96,1bb2bf5,9cfa25f1,eef459d4,fa28ac70,d77daa1b,b8bad15e,a383de04,6b8c6996,6d0b9da6,ce9f88e5,83cd57f4,a5f12c88,63f7ff70,b374ff16) -,S(2924e7b9,1ad33619,a8df436d,578b7172,b2208125,9f2d5bf6,f9cb903e,bd4d2f66,b8642169,e2319f54,348e4f3f,e15d1f06,afa41255,ad62ceff,a768bdb8,48841875) -,S(37d6087b,91a64ed2,8341854e,3a2b9ac4,4310785e,77e32e2a,f13405f3,76dc4d83,35a23917,e068bccb,a823092f,32e6fcdd,a3ac9f09,2c251b1f,9bdb9971,3df25003) -,S(d748a96d,c79f1be0,6b43691c,bcf84b4f,e000d2ce,8294cfd8,391dcb92,10f4fab2,75b4ade0,65da902e,ce57e5c0,4b817228,975c0927,aafb76c8,223c4da6,f05bf51c) -,S(d05d2a25,eb5084ff,262361ea,33b6fb97,9492414e,c255fa8f,a0233d06,e42cc30c,14bbbeee,cecdc8f3,85b51429,8aa03d9,ba57a198,5ba98f4e,75efab60,69a6f2d2) -,S(69ba995b,d137edbe,5aff3906,764eca9c,b4684bf5,e8a8c302,78c89d97,483ff793,2b1cf451,b6226596,9833e864,91c5db95,a79ad96c,701580b2,46de1936,5bb63e32) -,S(7f01e9a1,5d0ecf28,fde0342f,f506104b,3a50aff2,f1ec997d,9a82ff71,54419461,1c3c9594,a6b8d375,361e25d1,fedcab63,d2704065,a83470e5,e03dcc43,ad12dc68) -,S(719232fd,193b9041,fd201bc4,7184e4cc,f2413d03,f0f8619d,813a409e,56e48cc6,161fc718,7dccb053,5337ff60,9eae05ab,12fb55a0,65f82d1e,68b19d3c,ae29a953) -,S(15b84120,155f7310,3386009a,57bd28bf,9a63bcfa,46c8bd08,2f53dc86,76e78c27,47dd637e,c9017e2f,e9804e0c,840aca4f,188171a0,ea9fb605,1402c503,31737816) -,S(ff429d97,bd380047,7db52ed4,eba69914,4a95ce2,7414da2c,74c074,bbfec567,7b3a6fbd,6e635bab,34973f62,4df77c03,6708c00a,cbcb8f25,69a5aa01,d57b3048) -,S(ccd705b,16be74c,cf1f476d,12c77e81,37917404,b2611ed8,858b1e55,d50a6ee3,8741ade7,5cc7b252,4dd55e17,897f78d6,946cb4c,31ad9f1f,737affc3,40e87c01) -,S(65b61a5e,24b3c57f,91678e81,8300ecaa,94e4b406,8d499534,d54c37d5,bb65b27,90d75e28,aab97b82,f1b86fda,2ae0851e,f65ac4c7,a5c664fd,79c16a76,75ed0c40) -,S(671529df,8f4073d9,43f82bdd,758fb8e5,4ffe0487,c1a38cf1,73c1419f,7ba06ef0,c46d9f2d,1f23349a,dd1121e1,d51ebe4,454fd141,c7076950,4d854cfd,14fede59) -,S(2af8a76,e7a1697,7af8e70,30bbd2c0,73da3fdd,4c6735b6,8e823cff,901b0440,55565be7,9ada7153,c7165976,91ee33cd,7c34f5ad,d65f543f,72ffd026,26c3c1cb) -,S(acd81d6f,c5ffbb87,4fcb3b1f,b7cc730a,4def3fd5,ef59fc4,2fb9472a,6f575707,8e319a8e,c8b8ea9e,11ef47eb,5071b696,b87c0ec9,63e851cc,e0929646,1d181a3) -,S(ab77e7d5,3ab9e8bc,2052d0bb,360aa7f2,ae062ca9,9b91441b,d60ce8db,80ffb912,5f92b6d9,cb0ab95b,9eb992e5,e1d70412,aca90998,b5d6ed8f,dfa4c752,2df96b5a) -,S(798b8195,1a6a8c7e,f8beda09,b06a2303,1d7efaf3,7b663265,e0188ab3,78124046,9592da1b,baea430,3644a7e5,4e67476f,d91382b5,f1181de7,a1bf9d44,e02b1bf6) -,S(f2486aae,c3be77d,8dddea22,488aeb4c,9dbff93a,24ff6f29,ed6d528b,9777b096,8e2b2d50,fe75c847,7c50327f,e36afb0b,d8409b62,8d83a8cc,41325aa8,4829126b) -,S(222e3d09,3b8aea8b,e0f64ee3,3aeeee72,d16ca088,264f4333,f9397488,146d2d54,eff500f,bfe6bbc4,1c2dd16e,8a0ebd79,37ba1f78,ccb098a4,351b539d,cacdcaa9) -,S(6768d3fe,7ca93476,245a18ee,ab53e002,4f99241d,9c321bd0,165b7d04,c121c1c9,402c9d73,c9b99722,2319ff1d,9e1c778,c4dc825,d030a43,823aee8b,90272877) -,S(6eb6740f,b2f0880c,eff25697,bfd7815d,b0b62884,cf8c8ef2,5137f098,f22dda79,cf7e8531,c12f5713,c302061c,1f42e6ac,79c4b695,e458db68,5209f03f,1485c86f) -,S(7101f348,4eb05a7e,aa0f385f,367b6a7e,5ede8959,71729ac2,950006aa,965fe51b,8d1fb913,a040fb75,778fff9f,c71afc2c,2605595a,1e44944b,e264f893,10d5c3f3) -,S(75a9e45c,acc6a25e,3fe4b25f,12030362,a0de03ea,cefba87a,11c8e6d3,e886579,52a85995,e91986d9,26a02cf3,1001fd82,854c49f9,55683f7a,dbe7c02b,cff69c6e) -,S(31194d92,bad76572,98bffc54,27f99ade,ceac14f7,830ac1b2,954d6730,3737dcbc,99e81c45,f5318eee,9d2449fa,33cc5bc6,8c556ebc,dac2ef19,a2d1ff3f,5fdd2832) -,S(904fa3fe,76fd6f43,86ac6138,70b4cce3,c1d743c3,8457d23c,522958ac,bd505af,94273262,1adf4633,79e929e4,54c70595,8dae9bfb,3957a304,5c8aae41,a7c1763b) -,S(1d1861f3,1a828b32,3699aede,f3fa265b,40de142,78a7df26,b5fa93ff,a4a8e0fd,b9657781,f13ffeb2,8e1306e3,b84bb965,3ffc30c2,63a65f61,1995f44d,d899f7dc) -,S(3bd33def,6de1a5d5,e5ef0289,e8565dce,aac95922,8443c09b,73ce545e,6819ad64,993f0109,eb560bd4,97436627,9a70e9bf,8bc9851d,f52441c2,97535ed5,d4f9c810) -,S(ca1b7d45,2a39aed2,a7f27b24,8e5a07c7,e4c257eb,7150e61c,7bec7f6c,58958634,ab11fe1b,c0357c37,b7da9804,39fb5481,179c0f7,442af2c7,298facda,3c4afcff) -,S(273a95ca,dee8386b,53ff29a3,6ce7d9ac,df145f7d,5f928f61,da6d57d1,8671aa58,88a6359d,bb06537d,1a6c6d83,24065284,315a031c,73c53ac2,adb14f95,1a5bbe2b) -,S(7ea4c0fc,a139bbac,553ad79c,d3921c01,c06923f5,29446279,d0f910f9,ac5561e6,bd049d47,45830e2,f31e7982,2639f198,2eb71c37,71aed93a,54dfa0bb,296dec96) -,S(71f1801c,a2babe5,d4793240,15ccc684,d3823f68,fcd12ce8,bc49607,9607d336,41ed07d0,8384e54,209b7de3,7e8fe7a6,14430c0e,439dca6c,f5ae6ddb,1ff1b4b1) -,S(b2838873,652ba1ee,ae8aec51,55541a3d,7000ffd9,6279cf2a,1c90582d,21cd8828,47ff155,73f5e3a5,245faf65,86afcc31,ee4d19f2,a1efc79d,2a0b4811,d27dce5e) -,S(34ca8da7,22634bc1,6873fbdc,c089224b,d9f8164a,6bf0acb5,b68d898e,b55a3e21,d8afb760,36a9c91c,7769055,d85a3ff7,1f041a90,5192df4b,73f9100c,e5c5d986) -,S(212cb397,d97341af,ca0cf5b2,ef6d796b,4b76eb87,89c3915a,a0e72337,4b19cc8f,f06e2cec,5f29f06f,97685f50,1126c50d,ff17e273,2f78de64,875c35d6,42f170a1) -,S(bc0367f6,43bd13dc,32582dfd,e7893f69,d5f29d2f,ce4b42e9,ffa8091c,6ca6228a,9bec6c89,d1251f06,4aff3e44,ab59ac32,c1764179,7b96f73f,527ff429,74556e78) -,S(8fcb1423,5d8e8894,5ab169bb,4d198e4a,5e489e33,cdeb69d8,dec100f1,a9bd5672,fa1cb396,bab390b2,60302a46,b4408427,c45ae320,5b1d1f5f,e52db790,e7fc057c) -,S(70ad8505,6675ec20,cbc43e80,11df60f4,d4917e84,cca25044,e15c2fa,e51e64ae,f4a51356,af9fa7c9,a5e62475,df5b713a,b63d68e0,cbef44e8,c004fa61,1d5a800d) -,S(ada7af47,48074168,86e6df81,f9718c06,bcf6e6d9,846fa880,3ede1f6c,b9695842,f66d51f,50f427d4,dc748bbe,771d952,98369c91,c41dd,575b76db,988a582f) -,S(f1b87d8d,7323ebb1,1bb8108f,9d34f8e9,bf1e977b,a527c52c,7f045d8b,1102eeee,bd95703,51ebe7a0,9ede5842,47b755b3,7e2aa0e7,7e380b7,9bddf768,b4346556) -,S(93659d5a,d55264ea,c900c301,cfed7b83,1fbf7c51,766cc833,cc591356,492a0553,b69389e9,646d0165,afa137df,1c1d02a3,519ff65d,8856c89c,cf46de05,c0154beb) -,S(e9d2bc49,2a9b4ffd,c482f54a,415beeec,409a62e5,d1781f48,b1738f7d,8ed4ffe2,893e4652,2dccbf80,ddde313,f4f25383,8d639208,36150631,60830408,44305df5) -,S(1424160a,7bf1ad91,18103eea,372da6a5,825e0bc1,a8760744,229e2af7,906cb210,c94da226,96a75d71,1e6f1d0e,10b23e96,4f1519e9,1f63743f,209ef8a1,3996af23) -,S(7f902712,402e4bd4,aabe434a,eb5fa7e9,8686d058,e6f26300,c458cee8,9c9efd87,bc00460b,2aefb418,b16cdcdd,c88446a7,1b8b018c,15261602,669188ac,62f95fb5) -,S(d327ce7c,66cb0f53,e86e5f16,c8dc2936,2a133f6a,38147c01,255c61f5,6f72745c,4dc1498a,c3cb39c1,6908b85,b8c52dca,618cc6d4,1c6f95f8,353758a3,86bea436) -,S(f044eb19,c9d81106,13803b,e8bbfc31,137dffce,547bfd1a,d5396ad,e32db3b3,5ad4428d,9c4c3e66,7f8551ce,ab282cfe,8128a8de,ffccfaf7,c102b9df,7e526f2a) -,S(7a6c5237,b95d19be,af46a81e,bdd54403,d135bbb7,f3c03d55,f67c5cbc,e18daf4,62a2e8b8,47fceb5c,484fc6e7,4ff68fed,bd492c66,8a70c1d7,cce2922,a204385b) -,S(59c7fcdc,b069c0b7,bb772afa,f5c20846,ffae949b,47589bb5,80495bc1,b59f82f0,82ec588c,6657566b,71ba4d79,ac8e2c7a,c09b3652,f24d46ec,3358eeba,126c38ad) -,S(f8cf3c21,1ed4558c,c40d3dc6,dbb85e54,81d99fdb,cdf27ae0,ea01bd4,6b6543d7,bd8049d0,1c3df630,8951f5db,dcce3043,5506a5c3,e0a8bb20,54de9dc,87a9778b) -,S(3855d764,b2389d4f,1ff47189,33aca82a,4d2dd23f,cfd13764,2782ce71,524504bc,82c4ea25,4af2abd0,2724ec34,6aae3aa3,b14a71ee,df13df95,9446c0bc,759ef72d) -,S(77644b31,1de4f0d8,d30b1d73,35553dab,6d3e0e6d,af7e6ffa,48cddd1a,52de5431,645e17ce,c0a0735,737730f9,92bb7431,7581c930,695829b4,cdbf5214,f45916b4) -,S(a4d4af43,afd6afbc,b2a511da,a6537abd,56bfc0cf,76659d34,56530663,d9ca138d,be6c9fd0,dd2df31b,b907f073,7d63df34,88b5db5f,3d5ff747,a25a2beb,73bb09dd) -,S(417ffa3f,e673a081,f72c3d64,5e64bc61,2da352ca,fb66d1aa,aa8fc060,74a75be5,9ab8be2f,90849474,809472af,d5a7490e,cfd9ca4a,7f738be1,de093e0,68c50151) -,S(78175154,93115041,6cbd772c,c74212c4,4f19eb04,95e88622,f75ee838,caef73cd,37d4d5c8,ffec3650,26381b91,d7cb18de,fdaf2cb0,a5d94ac2,dd7bf7fd,34d0d3e6) -,S(365c560c,3acc28ea,f560c66c,7e76625a,3c2ee7a4,8f62ef0f,736253fa,b1b5121,25cbc6fa,96c0f15e,38b03f88,338f8dd1,6990aa15,dcec58d6,4517d37c,5b74868f) -,S(c945ad25,1010023e,9126b6cb,3a19a925,6c6757fd,d88cf808,a94fa182,8f5bac7c,c9a8e90c,b4ac43bc,ef08ae3d,fc66f6db,99df4abb,2679de5b,174df92a,d654e2bb) -,S(4aad85ac,45e6d57d,73822387,632863de,ac8c3fb7,b7d3beec,629c0e1e,2c2e0213,38eee8e1,9e81bf64,9641c192,de53a071,29c03689,376f6595,2130b63c,fd6a2708) -,S(2bc10248,b0f6596,adcf9f66,3f624461,907e37ea,7d35367f,24b9f69a,26a291df,e0ac3ed3,3016b37a,91a780f6,b90b7743,24ad0c30,50812b2f,4f35426f,4311c79) -,S(cdc05991,abd28f93,e81a2c0,9a04e1fa,eca89400,81fcfcff,eb91c8d3,93ddfde2,dfda4ac4,4458e2b0,3feb9852,d1a8822f,8bf90a4e,bc79ab32,afc9a1b7,580193a5) -,S(5a24eff0,af2dc429,ff4ea857,f8aab10,31d285ae,9c8beb7d,793bf9d,db46a047,179db914,59739160,897f40dd,b7af0b8,a98b6f61,6aef7327,b53b6005,9c4c8f9a) -,S(16c1e53f,51603ca9,374aae6b,57d15fdb,e7c1d2b0,b0545467,636fe2ac,7838183a,bf858ef0,56e09bbf,5d8af50c,7e0fdc90,8d1f6c1a,570594b,a5368976,63a183e3) -,S(792f1eea,71b92f9a,d893a116,ac177801,a2f2405b,1c6846eb,c3a6559,eb01ccf4,bc062f0c,c610ef39,311ecf87,a7866b9c,52c0df0b,be1e0129,3ccd0b7a,2832a79d) -,S(1b399c40,f057719c,f544dc51,51137fe3,917dabac,f0804dd7,335ba65d,a57378e1,4d6794d3,b6e8a085,41de872c,1dd333a2,bfdd0712,aa846f6d,380a775c,600b425f) -,S(138b313e,b9c45ced,e0cd8219,b888c51f,9f8cd278,abe16ede,c210bffa,ba238e4f,a199a357,cbc8042f,4b6d4951,2f0acd26,13f0f76d,cd6dbf7f,d9e8723c,e6ac56d6) -,S(3e06c311,9c765664,d0068b24,cf4ae1a4,8f401811,17c93122,84ffc24d,eb542338,63a65596,e5607f1b,6a9c4596,39a90d06,93b08ab3,2807b696,498e7557,673624f) -,S(3f32f9b,49c88932,574e5455,c179e9de,80f0f6de,ed1ed25f,8a3de8b4,bbf8bd2e,a2d2bb1a,5fc96f89,ef490257,bf42a9dc,91f49ce,e2b86472,8551fa6b,6a589f17) -,S(89adc417,ffccc50f,a129602b,f5b1b82a,2c4f5efb,e3382b04,1fe77299,46414ec5,4ce7e75c,291b751d,155c291,5aa619ef,6c3daa28,25da8bc8,e2c7ef54,8c253215) -,S(f33fbd62,6bec8c9f,6597d486,2f54f65,e9f208fa,7c1d619,a13feaae,5ce4e9b5,c8f0602b,ebb9f152,87fe2eda,3050b032,a6f43c8b,7726825e,df02b424,51593774) -,S(eccc8ab,7b90e2f7,e45f7703,a0e97406,117fa04f,4512071d,568e3e64,a4a7d6b8,8456f705,a9c4a0d8,f2f3c233,3c8bb367,fcc8a645,f1fc560,48e1699a,58a1b6f4) -,S(f6962b33,a7ad862e,58181c75,42743ed0,e6e31d5,4df1fdfc,a4e3e95a,157de915,af3d47fb,48515ceb,f9f7e8ad,2a0159aa,55c155a,83359cf2,9ee3202,ea9e6605) -,S(3f1f3c6,7996fb10,65ed5df0,2095926a,5c45d2f2,38ff59e8,42b9d234,daace24d,d585c9e4,f0a29f0a,28e3c30b,22228dab,73750706,5690811f,1104bd4a,6d0ea28e) -,S(fcae019,36290e43,d8bf93c1,6ad2cd5e,dc33592d,4081b0e3,4aedd451,6e6e589c,8e98579e,cc42a444,2dc710d8,8cd09996,c8acb958,b9702c24,3a207ba1,471165cc) -,S(548f27ba,355229d,23b7922b,5fc8efad,abc4247d,baa312c6,d89570ab,151f522c,e5597d8,bbb47cd7,c8cba774,ff37c81e,b7b63c63,39b9600a,cb77f1b8,86ab6fa9) -,S(e2f64914,e8bf347e,d465cf1e,f086b7be,49797db8,611803ab,6e439bbd,5c146fa0,8e69e76f,7c641e4f,15248257,77aef9b,88b27a94,72d565d1,d2ed7463,fc6ae76e) -,S(8c532a0,2d970c0f,1d8f9762,2298b40d,c7d362c8,f38cd122,2cdbeaba,2c13db1d,90f8a2e9,428d66d,9e8ffc9f,bcb7606f,568251b6,2dec2768,1b6ffa8,7062bd0e) -,S(64646efe,e3c51972,f6af7e0c,8052aec4,6fc0ed97,af566f6d,3c323218,62291a23,9e29e150,f6ca370b,36a76ee7,171f2ddb,a10eb88a,986ffc50,d6c8f4f7,287a69fe) -,S(6e8ba4da,1df8dff7,cbff69a,6ef65c9,329199bf,9a67d1b5,1eb1e1f3,473be659,ae7562c8,959441a7,35ff2188,3e537bd7,eb5a34a2,7e144a06,f674679,815d852a) -,S(8c21abc8,f7812c0f,6de0d7e1,cadbf1f6,c94c871c,d5b8e9ca,e76c1f33,2b6bcaef,5a7c9cc3,13be03e2,5410ed03,7e0cefe9,5a36d6fe,68ff46b2,663a0ca9,747ed53e) -,S(ce0e383a,7c487e14,26636ff7,657a28f0,10ce5102,1eb89fea,3426b269,2f9f6353,3f95a465,d43f7804,2804e9da,4c73c8ec,97fcb9f6,fdace280,532c0c0d,6232e03a) -,S(7e33097f,51477c4f,f4459848,34673fc2,8078b6c7,c01cb700,80a37ee,1d698eb8,c1275bc0,7317c679,d881d274,e49065a2,e282b7e6,970065ad,141c1ca5,ca2d75a7) -,S(ef4d9cd6,b1487e61,fb31cf42,9eff2731,d686eb66,cfb3f867,9317b0e4,116837a6,c4f6beb4,280ddd5a,24f6461a,6ea1eba2,3bd2ff58,7ff612ec,d118b76a,3d63be1f) -,S(f3edc145,2ee49324,f7890bcb,9a5f8ba3,ce53f4a2,df0c94b9,92c573b2,f3716290,995446ab,fbc9b27a,8db301f0,87c2ae93,5c390565,491c0dbf,552a9820,d3fb2f2d) -,S(c1f62251,7398e914,d6134160,318d20c6,87d17427,2bc62c92,bd170ca8,2bcaa975,1c85ae27,36735b76,d5328d59,3292f718,f6d6da52,1c75cab,fcb06720,87769e99) -,S(a7e81df9,605f0881,d4856153,3e310715,b206c601,9a55b889,7141321e,463dea8e,3ae220fd,1f361be0,f0b70dbb,a7df796a,eb23deb,5c5440ad,aa16fef9,7cae8a4f) -,S(1b69bf29,8f5df296,7a3ac028,87d4ae5e,f46af5ac,5a8cf326,2fe7282b,e46a536b,c9c624aa,2d99a71,ea375c68,419b38a2,d7e9d7fd,8880dc60,28c24f2e,a846a91f) -,S(cddfef74,31763b9,8df15cb9,6b3b3127,b31c9987,fd17251d,b56122ed,dbbb44bb,972fef4,2e935aa3,4c679ce2,6a32a38c,225f0867,8f780b65,854459e7,f24869f5) -,S(32fe1cef,2c8a5163,66b47d30,9ef01e20,ee07f235,e7c0129c,fcb70fff,60e957ff,9e861731,bd376124,8b33babe,c354ea,3d13b2c7,c45b436f,e754edf2,4fb4588e) -,S(a382fbe9,f4914119,d31d0ccf,6afb61fe,4a759657,26556908,505225b8,79c24b0d,aa300360,39a1bfdc,273e0287,c7c222fe,cdde6318,c9838a55,5136cda8,d2111857) -,S(b53b5439,9ae330ea,e13e2467,7c0344d,59e305a7,96a228bc,6d6914ec,1a80ef88,99809053,8dfc6c5d,748f43cc,8ba8a8e2,969d8d1c,47551a36,8f30ee30,d5fadc7a) -,S(621b5253,f11cfec3,fb4bbfed,98b0ad9c,710fe2af,6aedb8d,f521d0da,fb64169a,2a234dc4,8b716af6,22dd025b,63e05c5f,3b93005c,13614bb3,abe0dbe9,260378aa) -,S(83332b6c,cc9c3c7f,3163f442,80f5758c,1e5979fa,b9a500be,d5b315e0,f9435b04,85360612,258c1f1c,bda41025,c402dd84,60c77df6,8762d2d4,16aa16af,dcd30ea0) -,S(27c8d8e3,91202622,2f72d926,da01b10e,fd54e21a,7a4746b6,68aa868f,dbf6538a,88768e3f,b8f2484d,56c9fe83,fde0fff7,4d0c0a81,213ac090,e90d2b42,22d6eb91) -,S(f349c70b,bcd82005,2fd2e05a,c42556ef,6ee768d4,f08b7a91,55d1ebfe,60067e5,6d595c19,4011d050,c7c3c4e9,e7aea90a,93fdc5b0,71d6c9fb,9f621a4e,750c6604) -,S(4966567a,b2029966,62b1368b,ac3f89e1,a0183b20,173a7156,edb827a7,13b24f90,6ef89436,c2bb3bb0,94910ee7,6c083e35,a097b859,16658947,1f59c33,37e21ab) -,S(4909501b,491da13f,78645b84,9bc63fea,75611b76,5ff6eb6,9a7414bf,913e0886,2c20c6b6,f2ee070d,c1dd4c95,6822ac5c,38b1acf7,5e093f17,c54b65aa,81014df8) -,S(1ed2e667,f5a2d140,18cd3ee4,f4163f7,bd5f898e,ee3dda72,bf84e356,10cddb76,bb4970c5,64fa4cea,e204babd,d869e36e,934810ef,68a22794,f9919e3,26db8e7d) -,S(c47bab41,a0bc37f,addf9c8c,7de86d68,c15d1a0d,85257d57,2a1d60d,4612f17b,e52acb1,36f47de1,1128091a,1a3cc3e0,e84ce767,cf8395cb,b09eea81,a2db09e3) -,S(e21068c1,4993cfc4,35490b52,5ece7657,f70825f3,dd2138c1,8f5ec6a0,c67a7394,cd610137,d48f8d9b,2bf99755,35fab6fb,65360fc,9db04a12,43027083,c732da) -,S(635f547d,47a72f5e,b069e144,6508a46,bd6a6f,11eefb87,da07e4f4,3ffaf917,8ea0a9f2,3da273b4,f324c8ed,81cb0bf0,21fecb57,54eaa642,21736923,2be64128) -,S(24632c0a,8648b4b1,fff2f79a,b3f8e64d,3837b6ae,9329eaa8,48565f02,45bdb47b,9c6d0788,c9e155d3,3c260360,862ab236,177ff875,a3823179,8146e442,f66e0426) -,S(43748dc3,cfb229d4,8549cc56,ecbcb01b,146541e1,5d2c3b5e,d59fbf7a,6b7bf503,9975a1ed,23a09906,3b87ea7f,2ccd88fc,b20607e,1aded9a9,265f34c1,45fb9c5c) -,S(8f848323,b8c41d68,31603b40,69be1dda,bb8750d0,11527a58,4bffdca,c3ae3ac0,77a8ac87,128260c2,86f5805a,b17e5a45,be81f83a,2a575c6e,2c88288a,c2d1b37f) -,S(29ebc368,b54d846d,bb5e8be4,81c19c80,2d8907db,c54412cc,6e2952ba,2948422c,e6b793a2,81d59d90,53aeb2d6,f79cbd1a,426f79a1,6860310a,ec72fe26,37c7e845) -,S(9414cbc4,ccf4012c,8c0cbe21,eb714953,d84bc602,9f8e4810,5ba79967,23ed345,ad1eeb92,89e4a109,2d132790,ece35cbd,da45bb64,bb6ae72b,39b9eb80,d57fdeee) -,S(1bd8565b,769d0024,613ab814,90f214c8,bea90a5,db1e75d4,11ec3dc7,288f756e,c050a46c,fc781e91,b79cfcb0,2abdae50,b69c2cd7,dcc56b13,1df2175d,c1d375d8) -,S(4f7584c,35ad66be,3d409154,eb8ded67,14ed0ae3,288593f2,76cec90b,629cb01,f4be9248,232a120e,11ccf1b3,e9c5a17e,1520fee1,8f1da048,fb01eb3c,17712bb0) -,S(5b0009de,7e85b317,ab127401,fd2f3ced,cffd1684,c4772b35,2b9c783e,1dd9f13b,f4585704,f531c34e,3377cb7c,e672c78d,cb8839be,ecfe048d,bb412328,b973ba64) -,S(c66f31c3,79396f01,2ea5fdbc,4222df38,37f85353,3f3ed9c3,ad13bcac,63b32815,7d7b808,4ae5e9cb,c123ca86,1b505242,4113ee84,bbac5ca3,ea1cd3da,6eb22668) -,S(33097f5d,c8b09934,26ba51b3,ee99e696,3d7ba455,e91a7af1,a57c85e6,5e63abd6,fbd26b3b,200c189d,c8b9e120,61869766,987401ed,66e4ed80,63835922,c270d7c4) -,S(1ace5245,a3b7ec60,b9a922d5,ffbbe43d,aa71cf0b,84e395f8,c37dd2a9,c85ffff4,72c0ed67,94708f9b,f29c51cb,b6cbb69c,6ad3f4d,10d62987,1c444da1,bb25084f) -,S(bc197b9e,4cce4c2c,bfb22524,93f9202c,6ed54e32,cd52f512,692a5af3,6b0c4471,d5137663,5182065d,a4d6be56,cec50889,3cad9b95,4d5d17df,adb084fb,dd673f70) -,S(66997931,334bdbed,174cfa73,3ecad896,13c6f500,b79a7fab,76ad0bc8,dcc7df70,fdbd3301,948e198e,ee3e7d3a,504ac560,ab00afdf,26940331,d49bd2c,6599435a) -,S(3ba86cdf,b38d82f9,7c20b962,103f79a,5637422f,370b08b3,89083cc3,1a6eb4bf,acec9811,76debb13,9bd7f981,9b476e1b,5377e32a,bdecafee,33dd6ad2,3258dfc8) -,S(f62432f,9db971d8,4c3acdbd,c2d915d6,6395199f,76e81243,fed930db,ef1603cd,ee89cf3d,177b4cc6,e5856acd,5de8757e,82269f4e,eb11a444,c2e0c797,4a7b5f28) -,S(84b41bdc,6a6dea46,ad6e650,5b280a1,b6d81250,794e0b1d,688aeea9,c067bbaf,9f78703c,b535b4bb,2b88cdf7,b5f0f0cb,e452fe6e,5cd0f2b2,ab8c2439,9fc00e7c) -,S(8e2dfea9,3ea64a14,e28f4883,98b8d455,48c52ac,a5399f88,28a42c1a,c89d4c67,fec01549,cda53605,335df10d,d8ed04eb,e09d7474,f69deff7,5935a499,f2781271) -,S(c3bc6dae,5401ac1d,3fd75e36,4cbc2fa1,dbd2f6a2,40e912f1,18b27759,9b105e0b,170fdcf5,5b739326,fd234506,303700b1,9c5dba48,b6f0cc34,a650c3f,3b63d6b4) -,S(33093e93,1b1e52e7,ac5a289e,27ff810,c2defced,e935795d,a10ecc89,a3c14691,7fbba584,5bd55ebd,a67dc842,1ae10fb9,2114f0b,d68bc47a,7ee87a7f,70deec38) -,S(21b35438,b6d1a3ce,6c765e,dc78dd89,3f121132,ecbcc208,a36fe734,d8141ef9,f6115a5,ed237dc8,f61a82b3,66fb508d,e2d516be,3b166a7f,2566bf06,eae300d0) -,S(ced66583,aa1bed17,30248edf,28e9e4fb,ade70821,1c2e48de,3782fc6,d3892df3,4f43ad36,f29da03b,f0fe634e,3c441c42,c3a81835,2407f1b6,cb38e738,18fdec96) -,S(c5a74420,f541a8ae,b0673122,29fbccaf,37f6eb7c,ccf2bec0,23a8573b,ee6f71f8,ae634c02,44263d36,c00a6e25,d25fa592,1612a535,4934d709,6c864865,60adb259) -,S(304a048b,f30f6b4b,2a725521,15b15ea4,8311c51f,c4cd212e,f0a4bac1,48b9de9e,8f935900,3d6ebf0d,129cb5dc,8a953fab,11ceeb85,b2123fec,154b065e,63bb3cd) -,S(ff96b5ae,7eba0af5,ac9875e,97811e91,6ecb66f1,3bb06519,72ebfbcd,5b9c2048,24af2186,bca71cea,e58a0b1d,b56aed1b,3de89cc8,70fd4e3c,31919e2f,6352a887) -,S(5909ce1c,df732eed,4147243,76fdb3ce,8b6d38b9,4a0b35d0,50bdce27,b1b701a3,2e44944,665e761,825cf223,90383a3f,7d3731bb,bf7792b0,37fc05e0,b224dfdf) -,S(ff6b771f,86d66610,6fa032b7,92844548,8ef9974,caf05ad7,cfb6b30e,abd1d527,6abd2a9c,9393e91c,ff77e055,7e9f6a86,9fcd0bae,3544bf50,b25f0427,908ba4b3) -,S(943ccf04,94dd1fad,1efda48a,12d9ace7,be919685,7e7fc5f4,befd7d23,3a1aa8d9,4f08b4cc,2dd93f8b,3751a23f,ca7e4f10,6014e01c,58791c52,3d01134c,1a0a7bd6) -,S(a79a7a7,a89e1cdc,908e0968,bf26c341,47a4638b,1d9cb5b3,ee6c49f7,405f172c,cb53d967,14b5be3a,e5497f34,ec0325b3,ebadcb76,b9838cd1,b3cee90f,f3bb8ceb) -,S(28ff2efc,71176efa,a861667c,d173f78a,4f548b36,aa33db2f,a50c0515,1c7b89dd,475b3707,db4ba15f,1485e165,68d7dbdf,8e67cdb3,37d79988,dc6e2249,d6fe4941) -,S(85b2c332,16a86885,c0704fa2,55b4ca00,223e897a,f0ae7557,f8687eb3,b1012968,a1f58d45,ba664056,efbcbe7a,f0ef479e,1f2bcbe7,98d055c5,7045d735,d657ea11) -,S(e9fc2d09,eefb32de,4068e2ad,d7bd3692,7a02b3e0,d354dd47,c2a70c9a,5cbb8778,ee009aa5,1216d068,3ee219b,bf53ccf4,f249d7ec,bd8c9cdf,80d0ec5a,5b65c312) -,S(da2dcb50,afd510d3,26e38af9,5a22850a,a1cc88d0,620fed65,763042f9,a0005d9e,1eef47b1,c3700963,5e16af23,f1308de9,ae0eab9a,b16c9443,6d501ebe,133eaeab) -,S(20daa29c,c6b166eb,ce717402,70873566,327891d3,ff7b6f08,b9b7da3c,1eb352e0,2ff6982c,ecd6fa4d,ec1d6692,92c3a326,a30cb526,4dc27a4,299dd3f7,7ae8a3fb) -,S(e16b08dd,2ae5be13,67547a53,496f9f4e,3aab8440,6cc34bdd,71b2ebf7,53674d9b,b70f724b,d9522b1c,8e43d60d,6357b5ba,48a1afc8,b7136c1d,9317a1d9,1ba06846) -,S(888a2daf,2d69db34,ff9485e,b06d44,c59670ec,3c68475,80753567,e56b93d3,ddbe4fa7,792e0b82,ac4753f0,5b271aba,8e804384,b7949a9e,9ba79fb6,31d4e3f5) -,S(747768e2,9090fdd5,2c22e308,131f97b2,ee6d8e0c,bf43d704,d50d60c7,616abd12,eaa75f40,8d1ce0b4,bb52879e,5ee7ff36,27b26645,c8ce3840,99dbac60,9cb61058) -,S(8569f2ac,1c7d131a,8d337cc8,87c00c1f,80897a58,f9131143,5a17d79c,fd8d6eda,504f0b44,252d06e8,2f8e700a,746a3393,85e43baa,a4e5da8e,dda7ed6d,83eacf71) -,S(4f15f3f9,a67221dc,4fca1d68,429b874,c4418df8,be480591,e57d6841,e11860c9,982c0d56,1783a9c1,a16bda10,87d29061,3f1154bc,4cc62a82,b795c54,a496b7ed) -,S(21e51a20,1f226e1e,3ebd56ce,6f7258d6,4e4f9db,aa425943,9e1bf7c0,144a92ce,4c47a801,b6a5a4ad,25c1486f,ec9bd0aa,428f3167,45136359,18d47079,75aac869) -,S(fac7e42e,8865ec0c,d0b4c4f9,dff6bf8b,e0f28336,395bdf2e,d5e2a118,9c0211a0,36812d9c,8337199e,fb1fece1,1997307a,ce656fb7,3bad65c6,41e6bba2,c4dd695e) -,S(a147839e,c91bc77e,cc568671,442d29ee,57f0f42d,7b9cb469,91064549,1a26d225,f404350e,bf7267f1,86120257,fa29fc1a,fc0d064e,2f14eeda,b730770a,c85bc5a4) -,S(d1212cf9,e5086804,44883c1f,4158f3e3,44a7900f,716ade2b,df19e41c,18636b8c,720b851,7b91665,128183a0,f3235c6a,2f9c21c8,e8c6ec0,5553acb0,27fc0964) -,S(13d5f334,a7ab2578,977c125,1a07d7a,2e4852ca,8927ce7,2dd9fe90,8b948975,973869e2,d1d0abb5,1ce31db1,ae8c3816,ff998753,479fe82a,7d87b6eb,798773ca) -,S(1f066961,6dae9e8e,76a9bec3,26bc2136,5ec754a5,34c787e6,b9abdfb0,e463507d,da48070e,b4ea111f,881f9fc1,2993a9bf,c6f99974,b3353ce,b5bd1cd1,c75b262d) -,S(729e187,38681dc3,c4ad9a49,59f975f5,907b15d0,114e029,8d4aad5f,69150269,dbf2ed8e,c60ea01b,6de0022c,8b035a7e,c1901c82,9e8d83f2,4560659f,8d455442) -,S(e92fcbe9,61353477,4d42435f,de190c26,8e3692ee,c2042fa0,2ee21687,1dfda12a,a75b5c0e,3f5280d6,41e36957,5e6ec5cf,585b1451,1f01da84,fb852cc8,2d64f2ff) -,S(85c2e61a,c69f8d39,e9c4dfbf,93f6b904,1ad35bcd,7f2b5c1c,789812d4,c8da36df,ca6d9187,694429e1,a5ca50b3,332ab11a,575264db,bf297752,f38fabb3,c0b53f45) -,S(10d17632,c33cc6b4,f5c2791,b5ae4f00,3adf9958,879c24f,10f147e1,bd1bc05c,e15ee734,f1ddec6f,45dbae00,88e4c5c0,be8464f,31205718,a8b2c929,939a687d) -,S(a6942345,25938972,f39820bd,27ea0bbc,92511dd6,827476f0,28fec86b,e25d609a,e06b3616,870f73f4,93f6d1b6,6256cb48,af49ee6c,b5296bd,ea73083,4f11d6e9) -,S(b4a7d8ed,2b3dae3f,43eba052,45b6c4c7,c401a675,6bb0d906,4f66d88,df94d8ac,ffc81c63,1a2cdb5a,fd7def11,9d07af35,74dcb04,e10a5ecf,d2b0a46d,90963456) -,S(5aebe21d,aebd3c57,285cb660,d9aa55d3,f84fb2ff,584f1266,3031e2ab,dda6fd17,22ea513,6a51b532,d178c40,cd5c8453,8f5994ef,7b35cff6,d9dcd999,daf1abe8) -,S(ac684664,194388d5,b796d64c,b4563aa6,69388d0d,83861c51,278316e7,2c8c7f87,cb9426d8,2dc90b01,97bf114,3f693e93,4d710988,26586e5f,f8913ab3,9ef41ac1) -,S(6f94bd49,f89e621,874c58c2,f27ce8a9,76ad2764,1627e835,6b82157c,24955250,d24330ce,4a54dc7c,5c7d9cf6,8f8622f5,e3633a85,8ec0d2ec,d8df3f9,bc7c5614) -,S(3f96c8c,e149947a,6d9ec5c,9ac5ff44,775e068a,785a2fa9,d0940905,a008f137,a91dcfaf,7111a506,3cf613d4,e360c9fc,9b7d9e40,30e00ce2,b120eacc,805f3f40) -,S(d805b05c,dfd675d3,b862a4c1,74909974,405a5b61,9b2a73c8,f3470959,779c707d,a68b544c,c7279f2d,e3a2abdb,fbb7fcb1,84366ef1,3cc3a66,b6d8cec8,3c3b6865) -,S(d2293c0b,d4189cb6,6be0efa7,874abe9b,59142233,6f2f71d4,808be34e,79df0e4,5fbc3248,87c54960,b9bfe70a,5cea3871,7f24f79a,3fe0d313,18cc068f,212682b1) -,S(931f090b,e22623fe,7ad49d26,e76b3c5d,e3f107fb,556f9657,facad9c,5b209d5f,cc255e79,d2a89899,865daf74,81aea395,848f57c0,1850c144,d5ad1a17,4b1cc087) -,S(118a6283,6707ff6b,c8ea72f6,285403a4,6e4e690a,db340987,a0359732,39e5ddc9,91f00fe5,e65a9058,36f9d447,d96af84,b6f5a18d,85c127ad,72221980,f7ff818b) -,S(81096ceb,5b6cb49a,d014ba42,d1d49e1,b811ca2d,2e6614be,1891c6a4,1f6a985a,da051c5,f8f9f3e5,78050a3c,1354b674,3f494860,6b04b8f5,b4dfe970,b7607e5d) -,S(9a80a438,5ff45ed6,2dd3559e,783eb47c,351b7e43,6ddc468b,9f410989,300cae06,845d1f99,21b69c5b,4628aee8,b0c55398,bee65659,e3e41cad,30e57bf8,b804b6d0) -,S(6a3168f3,b89955b9,7fac1d59,61e95fea,2143954d,fbbb6090,81c2408f,46747906,5b5f1f88,6778f108,3ae44a3f,82c901b6,12c741e,811d5403,c483c572,8cccc005) -,S(9a03ab11,78d165ba,23bd4298,58bc8ed7,797710fe,f4f8d8a7,3db0a90f,e1214af8,70888ce7,e61e4bf4,91512f2b,fa556f51,59a5550a,1d50a65c,a652b5bc,89e85665) -,S(8c90c18d,78b8d9e1,59a61575,48c14971,296c8c41,991dce25,e7878ef6,f4ea2f5d,2a5428cf,de628e51,a1644a5e,5dbb7227,2b97c0f9,b6909a68,2814882,cb1ca074) -,S(2e9bab7f,3062024d,84f7a5da,a02c9ed0,93327923,339fdd43,b68d6dd3,508a8957,c9af80b7,3f3803c9,f21e21f1,9523b2df,ea7e4f8c,9a376aca,4a147530,d2a43345) -,S(2734bf2e,718ecfef,64a95e7c,1fbe6a37,e2129898,343af84d,b5c17671,9a466322,f530098a,9f115f0c,e36a0ce3,4697312c,7d0a1e4b,df8a3ca8,f0a63631,e684216e) -,S(ab9ecaf9,500e4a4e,6e81b997,579b5214,4af3257b,8c8f40d5,e21c2a51,d56aab58,f7d38746,8e081844,9bd5e9d1,938a8859,d0aaede7,5743dbc3,ff30d51c,3de0f047) -,S(ae25f546,a4c09ef2,e5a9cd3e,85baa880,292b4d4d,4e8440c0,1696435a,cb1af368,46a2b3b3,7373840f,b739a9f2,2953c6c4,80bd59f2,11013d59,e051055e,f7f3da84) -,S(54285da6,4ef21cda,f597efaa,884fc00f,4e35abb2,bec04ace,54a83dc1,c12e6142,483beb2,144d7b5b,a47c2dc2,9225dd5c,b962a849,d46ff6e,5220b6c3,20cdbc3d) -,S(bece8434,4bc231f,60ad542e,d6a7857c,35a627ee,a2914874,c8deb661,37dca65e,a229fb80,2f9e72f,8e477fb8,de081254,fe1c93ad,a4d3b4f8,e9c2f4eb,3e2f6a95) -,S(3d55747,b148b857,472fe5af,1e820bbf,89994a2d,ae6c326b,26fd9cb4,fb5e81d1,dedeca5a,e86728a4,f635bc4f,1b2b162f,c9ea7dfb,efd5852d,b90001cf,bde465df) -,S(13c68219,d1633c73,59f6361a,88bf6a72,1846b520,33475715,fbc97dcf,75cde5d4,ce8a3cc2,39fc7f20,96abfe7c,52d79e9f,bddf0ce2,ab2b6e55,935413f9,37f83af4) -,S(e9e40ae1,a8041a47,274c481a,dab52f18,36690a29,be837433,43650126,d5b0a6ac,c19958b7,9c9839b8,1371f314,749147cd,9a22fa22,a55da9a9,577646f2,38c6bb7f) -,S(2e3b4553,7460a1a5,f7353a53,78db61c9,13af4371,9a268eea,6321b4c8,a1493068,f7ba5e56,104966c8,4959d3e2,290e5501,5ccf5cf2,b6fb5bb6,e0452c5d,cba54dcf) -,S(9855bc82,b9214b00,67eaa40e,bf670dce,6a59f3dc,4cca491e,db1f0f48,b4c62b8,a7d93f6e,3be6c73c,e9e37d6b,5b071603,87184e21,38478009,8d4c1c80,ccfcf435) -,S(37f820a9,b9342913,6d44bee2,69cf27df,67486bc5,233b8866,982f8476,15253979,fdcaea9d,aa629d37,7f345a5a,37c566a5,50dd893b,9d7ba88b,2a568a28,7870ca15) -,S(e82d2c98,a92a3b0c,690f6ba2,8070c59e,3e0cd0a2,a384d3b0,3cba9d1f,ded41a98,31e73a32,32d85b36,14833d34,4c7d502d,d09d7ecd,614b060,95c86be0,c8501460) -,S(bd492fc3,6dd4c906,6a071182,7eaece3b,ad46901e,b400bf3a,24b93799,9a923419,caada3c5,1e1fd5a4,6676dbd0,a7fd4049,8b93da93,bcd25af5,fdc6a0c9,1dd7798) -,S(6c8b46da,42d1ec4f,3ca2c4dc,15a69c80,cd8f0d99,7bdf3964,1cded32b,8629577a,d3ad4f62,729e42e0,f72ef596,5bcbc239,cbeb988e,e62b30a9,7f124004,c718c956) -,S(78b1e9e6,799bd3dd,854a25d3,4d356b4f,effee71a,ad0c8f05,ea9ebcc0,f8f5dd62,31503ed6,a26788dc,c07d7005,7a300665,d726ce2b,702e65c1,dd25f892,3931145d) -,S(f2ed02a6,63c5523e,3c68cda6,bfa4ab6b,cb53fa5c,15f0375,c8974eea,5aebdccf,3bde5c3,afdc0320,e3b92241,3220ad32,937720a8,d1477b67,773e725a,3cf36382) -,S(7e43f643,a45800bf,7e54d83,5ff6ba20,f67ab101,5d1aaa60,cde0967d,42caffd3,1f456eda,f473399,b57fbb37,807b5269,58600d12,b556879a,76e21459,5798d68a) -,S(df15e177,5eb73697,aa4c0a62,4b4d2ce9,7ccde2ca,66555d07,6430b656,61319be8,496cdc,f1543818,c2173dfb,8a60ee2d,8397cca,b16e4e53,b35079cf,b27311ad) -,S(edf1d706,295bb20,12dc1648,7940e84b,6707a3fb,91a14fce,ef37f669,c782e2ae,e3a0f2f6,fcd76c97,b20b2dd6,8e888eaf,9ed8f598,f08e4d7d,239a8964,fe019a2e) -,S(c15022b2,6b15821f,3be3c313,73d0464d,fd92cecd,6ba87c2d,9b18fb5c,16f8f6c0,78cd2370,d94e2842,e07961e6,92e9fa04,65d57f25,a80feda9,327581bd,ce136c2e) -,S(bd4df6b,b6ae15e0,109886a2,8a8f8c90,c6cc2bcb,b52dd105,e277da7e,c76001d9,499659b2,b0b4cb96,5b8e5029,96ced2e3,a6f6fadc,da01b875,72f8727d,8ef1446f) -,S(dfcec232,873894ce,525f9b4f,162f180e,1e2d6eb4,c846bed4,b2109700,8fbc0b76,afbc761b,f4c88e71,9c318f05,9a10ab3c,5a477ec5,33243b95,3f8ef006,69b4f92e) -,S(b0076c4d,e3c94fae,23659b00,5b8b41fc,b8473935,764e48e1,a9eb1fef,f5c94e54,e1eb3255,3c55a687,6f42ee5e,44830a09,fe17fda1,b84e8551,f3ea2308,f9c7d4f) -,S(9a1fe9c,17c4255c,c11e9fe3,3d66787a,fe9ebb0,99be88be,94b4c3f0,da2d0c11,e6aef709,99a8e739,6e23e1aa,c7ad1cab,25f6fd6e,62df02b0,96af568d,e88e8379) -,S(1d89a934,126bbc15,d9b99b88,b6c65106,e1d8b16e,799630f2,2576e9e4,15212899,b7e32256,92db0722,e9a79ef,7d95c509,37d64644,ed36cfd7,56780d59,a6f8f4eb) -,S(c60f5c68,b67b3796,3c462d4f,7530edfa,34546956,21bc80a6,ac2be433,700c7fa4,88f8b071,97fff0e3,a19b5a67,60dc92d3,b5507b53,5cec02c6,53f75a60,bf8a7e08) -,S(52cd2b6f,d9b2699,1b76499a,d301be43,6205761c,f768eec9,e6b7d6c2,52d9d949,d127cc66,1fa33508,a0d11a3e,ac782b26,26356382,f547e4aa,13802138,30ec835) -,S(1e44499e,a639835f,f384f107,fd16bb19,c21fbea5,cf4e3be9,20a34024,6d05dda9,41c6a8e9,a9042f9,950d12db,74fd0f21,8f8adf23,e961488d,27412c2,f2d1f53) -,S(139144f0,a56394ba,d1e53bae,360136eb,984ecc56,56a05cb1,c6727543,fc6861de,70394737,ff37e9b2,1bf174ab,6c042bb8,964f3d01,6ea1edc1,25ed3b4,2ed0742a) -,S(934ca02a,2454df18,61fcb954,6634e685,34fe75c8,b6db6eb7,5a2a74f8,654a2280,779e9784,266cfca0,b83caee,74fd24f1,6865ce3a,6be78be4,375fa15c,db195761) -,S(a64f047d,9e1c2459,77da8c32,9d35ecd4,af913baa,2d4b679a,7acd326d,886a3be6,e11e830f,f3b4ed6d,102145e3,b24759de,3210f309,8ec57581,e6014818,79112b2b) -,S(e1c688bd,cd629088,8d8820cc,df15fe8f,cfcf45c4,b8bd434e,2a15428e,818757e1,bc10c6e1,71e7c8e0,13b8e00,e77bb745,a34e7d1a,15267600,d130f6f2,18c77f7d) -,S(b1a30c95,123170f2,d9456de6,827afcc9,ba2bded,d955354,c6deeaac,68137358,9c76a0ab,c16c1caf,d3844346,9040373e,a678797e,dfa1b298,5a17d410,b04071f5) -,S(24cc27b5,fbb0291c,3468ba23,58f5e253,4c7cf99f,699af4d0,d6892bea,e6166e85,eaf369af,2516ba42,673c52e3,ff0768fe,d51aabce,2312b8dd,d7aa1ed8,cf9f71d5) -,S(8bb4017a,6166d1e2,f7fe8921,cbd31cee,bacab577,84da8a92,217aab2d,948f6a57,c899740e,6c476986,356e34fc,7182996d,a09cad72,93d78c8a,5c30d56b,88dc331) -,S(55d8b7dd,d82fdd96,e0ec17dc,20b303fd,e6dafef5,a527368b,ec99a33,60497f6f,fd624511,78bd66f,4361709e,44e72e9f,f4f29230,d1fff657,bbf84762,b7b8beca) -,S(82aa2def,5a5531af,519cbfe6,105dbde3,109d4626,ec47a845,5dbe2852,34c94df3,61160bea,9f83a2e5,8c2df91,925fbb25,8d1e60fa,6a147c4,ebc0ee38,cd811511) -,S(36c1277c,c6df7ff8,47c2cfbf,3cfa9198,804b03b0,c28e1636,ad3438cf,2cf6f7f4,2304fba2,74f81c74,5455d821,ea58e047,a7bb3b60,e32f020,aee5a2a5,16fe4833) -,S(f376fdcc,5b44cad7,e16c9e86,c00b366,d57b8925,fa49b18c,eb8856a,e0cd9119,2d6acd32,e4dee81f,489e3ef,11acfc8d,c3d0e7ac,bdf5c6ac,74fe7aa0,50a028cb) -,S(ea4e10dc,5372e9f5,d96e8ecb,907d3a89,97150b6c,39ecfd1c,c7aaacca,5dc5030b,b0896ea3,93b626bf,c2f486d2,9fdeb897,36d6be60,144fc3f9,5206666c,36d96ff5) -,S(74f392b4,b2664a17,9d3f0a2c,71b144b8,a376ea19,f1a9d91a,d181ca3,a6fdeb08,9bd4db21,428d588f,64ecef67,99b46735,c9523036,406d2636,c6eee083,e09e1fc0) -,S(3a36c842,59ba7774,a41a17da,f0e4c821,11c13a6b,58b82774,ca6962ef,cd4855eb,6ddad1ad,9ede928c,d65720c7,15ef39e5,f35e46ba,45d8ff48,2f095d2b,e0fa5e3c) -,S(9d77b2ad,5636a44f,16e73981,46b17ea9,7635ef18,8f32764d,eae50d2a,5c98c019,532dd027,a775861a,b9392b8a,cb2db097,eb5936cd,9d2f7234,f30c371a,22ee3eef) -,S(2e7402e9,450e2f80,e05168a0,f0c5f1bc,deb6117,ee46ac1b,39aae7e7,bea3c4ab,41e8f36b,5606fe2b,8ed6b3fe,f8821013,cf85721c,f242eb60,34b82afa,cd82fc3b) -,S(aeb2cb25,4ed0b5bd,81b33d35,e8f00a5c,6a6806f1,5314b320,de0c376e,533ebe6f,6b8116f5,2d7bfa2c,b3028249,fc83f317,5d761c0f,76833d0b,142c4d6a,29b9d59c) -,S(c86224bd,55d62c97,a00adabe,3a797929,4cca663a,ba3a3655,fbbcc3f4,5cca7895,a319a3b7,104f7935,36693adf,a6009db4,1d857353,fa950c21,844323bb,cd1cc214) -,S(1d1164cc,2c576a0d,d7b5a28b,cfdce6f4,d53ddde0,534b3a66,aaccfbba,3eefe561,b85890de,aa25d897,fccba694,7c470e45,ec600989,243ea91c,4670a,b44995a7) -,S(2b54fab4,13b915b5,ce76620a,5c493ccf,5e7f0f41,8bcd793b,92f26118,a440e3c8,8aff8d25,56fead8d,7e9bdfef,bddddf37,7a61ce4b,2effcdb,30ad0016,4f9bf5d1) -,S(1f1f2a24,a4e72a1f,609428ac,853e46d7,a9718c25,f2df9887,9a3aa60,5729b340,450dca4,f4920bba,bcf94f39,26871032,b631120,4b217170,991df216,2c421cbd) -,S(412f658e,e6777e4d,24e5682c,5007e057,83fbc559,f22f3200,f185ee52,c8ebd4e5,c2e0b64a,9d9394fe,b930b3d7,afa64cb1,c8399e3,27690e32,887b789b,6571c8f4) -,S(8495dcb5,567791de,976fec9a,367e250d,95102ef9,f92c11fb,f561f854,4cf4912b,65f809c5,7d3d824e,f5e63f19,153bda4f,542e511f,464e11c5,e2a9c32a,2a152443) -,S(f8e7bdc0,d841c95e,3a945b8b,c85ca4c7,b4a18a9,7a5646ee,1bb4ff08,5956cfde,cd0ac83,f93a3679,37c9d28c,24b9fc08,6d6660d6,15df5011,1b4edd5d,f0ed6d42) -,S(8324625a,4e4c1071,24876751,7df28ad4,8c8c5648,76e4a131,64f2f730,62854c94,761b1960,49922825,609c7ec3,70626025,de65e2cb,240b8356,1f5cc230,1f9bfaeb) -,S(8b1c49ff,99f87e22,af4b6bef,d353df1e,16a8e160,3023f2cf,213ed859,13ca04d4,cd4513d1,e178865,2d1cff72,822de250,6abbf975,7e2774c0,2ca1bde3,23ad6c23) -,S(e2ad61a1,20d24d80,8c830e89,d630b466,59deacf2,87aeb790,bcaacb82,96f4f138,51cd19dc,fc1c4867,daad2940,5acdc7ca,91849769,6003321a,bf5dbc6f,b2186291) -,S(e8dcd7e,a9a9a6f3,16a6aa91,53105601,e10356ce,7f4793ba,9eae3ad0,34c197a4,c835bad7,91f3aaf5,d32e2a99,e71c4add,95f69892,6a68695c,2e61ca85,38ea6b5e) -,S(f0b748e3,5875b8ef,361bba69,cfb05c4,d8643f95,9b207556,e46908e9,bcf81233,6a264e51,5d163a7b,678765f6,c29ca61,c1c0aeab,a9ff423e,91e9401b,2dd6e908) -,S(900de96f,9975a16,766dd305,bffe2423,e6eef8ae,93ebd796,2ce97d53,39af3a87,894ab2ec,d9c058a3,a331bf65,dbe69a49,f33f8e9b,12121439,650aa700,4d164478) -,S(8cbe7930,d2ea2342,730e306,7e9ecf95,ce7fbda1,e6d34645,a6e214a0,ed88aa53,867b156b,f875a67d,ae27f2c8,e232c934,85092c70,ec071ac9,919ddd85,70186b83) -,S(a0cbb1c9,5b35d243,945a65c0,fc5706d4,e79237df,c13583e6,9a292fec,9a25e68d,b6d7e9d1,3cd61a45,f81c8a55,40dc06e1,3c6d7024,5e850a40,55ba4eb1,82047e4f) -,S(148aac72,a3fa8cb5,aa6d3bbe,5e987fc,d8050c3d,63b47f4c,832a4488,262463cf,7f29de49,a6e24485,5aa45f6d,36f2e2bb,72749f91,8258c0b2,92a33322,677e4a61) -,S(3b9fed07,3a1afd6d,e6ecaf7e,fa20e2e6,c28616fa,25a218ce,fb07cf33,66f3977f,f0a85b3c,5084c964,a1f0c936,e96ad3e3,4fa9e7a1,348ed0fe,ac7003c,12c65fc9) -,S(7de45ced,5228bfd9,557b443c,30fa431a,7c9cbcea,dfbfe0fe,cc565ac7,ce3537aa,515ddd37,69107033,bcb794f3,ac55062d,78e0118a,60c98fc1,1999cdde,fa2686f0) -,S(9cc1a35a,534f562,98010274,74f3a857,c17cf99c,eba1d5aa,251e61b2,55913dd2,c092cda8,f30fa4f9,96115da3,7bf8e12f,c653e243,af2bc7cc,c691684c,3e433ae5) -,S(d82f1968,759b3b9c,c76ad729,828a7283,10fc71fb,22258562,920b690,7ab52ec6,54cd0a05,26983b0c,73808f8c,ae1c9d81,1b372082,dcac3306,c470af50,8818c607) -,S(16e6a947,3d95a95,c31bffc,c291b60d,1f9c548,85e5a498,24195ead,b87b7586,19e29938,581b6b8c,2e50d365,5a957c04,80ff4c8e,4ed73276,f882c558,dbd8aafd) -,S(d07e7af3,ee4f24,e46b4670,477c3463,ad57a74e,57a17197,ff098e52,3b5cd237,fff34e0f,43c91656,69b1019b,ef618888,d4d175de,b6f20b1b,c696f24c,135d0e20) -,S(2bf644e5,6dc027fc,63a118a3,43faa4e9,8ffe42b9,c983014,50a1f4d9,e5665380,bef5c175,77be1fc5,f8f66fb7,a06b55f7,eb84ca5f,66ea4477,c924f925,5a262ec5) -,S(518f0d37,db1db93,48c80101,442597c6,7a88107e,5e25fa3a,b97ed524,fc5cb045,dca8750e,a4e9ed01,66f113a1,44974250,6eb9f3f4,df8ab741,8dba0397,694d7294) -,S(bd48eb6,c50774a1,2be9893f,8c21f624,57bf54ba,8799928e,9a9c725d,6f0554c7,200a6da8,cd8f0300,6774bad9,769f738,dd58f350,632742d2,e2cfa787,f570f6e1) -,S(ccc8d93a,871169e3,69336622,b64fa1c0,800c5b45,e3c0b130,2aa99e34,db1517e2,40ee7e4,d45e6478,efa11f1b,c4548668,88837309,4809f056,11efd6c3,6d01d845) -,S(86f6392c,75877992,311d2e9a,27be9ea7,27e8d01c,fc27dab,8f4527f1,dbf6bd1a,7ee29611,b647aa2a,3d2b1304,c49ee690,57150518,fd46add3,e7caf34d,10f7922) -,S(e034f4e5,927b0fa6,c3794105,338751f9,9bb5a381,6da1dc1b,bfc41d83,b7d7fdfd,dc9f02cb,838242e4,13282b05,cbedcab9,e902567b,b279fb6f,f2248e75,41a5f89d) -,S(8fc36a16,a9dbf00,5ee3a66a,b825510,75eadfef,b86e1062,837b49cc,6ab51045,c7ee2c40,9605981d,217d9957,a004a4be,66a88527,9ec9f74a,70594999,23d200a6) -,S(d7bb40bc,54077d96,d6489b71,e65dcfe3,997130de,b517d12d,9c10adc8,e73278e0,e2096366,2f64bae4,5aa0706b,d96b5cb6,5897c0be,3a8a9b46,8ce9074a,a68b0a4b) -,S(d7357685,8054c714,1147d2d6,c265ce40,3c882681,157b07e0,b8be0a88,63bd2ac5,94f8754b,2fc94239,c254099e,9cd5804d,d2ce03a5,380c59c2,4f42ebe5,85a9932b) -,S(5b6f8aae,d9353ffa,71da7e99,bd3fe165,3e720ffd,657dc2b6,669ae0da,858f8392,4eeafd05,369c6eed,fa6f85ec,34e245f3,e4966840,30253c10,6e74f473,418f9089) -,S(39444d12,67cc29e4,384b4f4,9c4f4886,ab4076a0,19a0fb39,f7b72c4e,42222000,65c2502a,af90ee2d,8de48adf,35388eb9,329f3057,1b77d0ba,50ea01a1,ca83d771) -,S(53de00db,f1efb0a3,c159c4a7,dbc9888e,16ebad95,cec2d003,a18488b,1b0752c7,328ecbd9,99475dfa,752d6228,5e7bc51a,87dc6166,4d14a6d3,3a556322,5e2fbda) -,S(48a3baf,9b4f7213,e280eef0,d5fb6033,194d1bce,eb48d9e3,d4814a4c,bd5ead39,3b4ac9c9,e04a3852,bbc6f7fb,cc94b20f,7e749eed,44a9a9ce,7099a8bb,28334186) -,S(f00d7630,503c1ced,3c418237,27e22d7,acccf406,fa16eb6e,b524707e,5b3ac541,9a1ddd3f,ec177626,b1254605,df8ed593,c9e2bcff,db7d0404,f47571b7,31ca95b5) -,S(e1ff1994,3ce7eb59,e570858,2e8c21a0,c4f8eec8,40815ee8,9a482658,8941eaac,528e5572,746e72e6,ce61b53d,78aa57e9,dbf27e3e,bc36c3dd,3b4972,d7353b7e) -,S(e4f13c20,c48e750e,e15a665,275c27be,23b3aa04,5915ac55,2562bef0,7459bd49,bebc7ece,c6e51f99,a2e6b9d6,a7b1bbb3,63901053,362a9ebc,a2d21cc7,6e87ca30) -,S(e36e8cf3,824b66e8,7083d371,60cf2719,598c6c04,ac693ea4,d2dd5c83,886f5f20,4ea0e193,8afe57df,3db74910,481a54dc,f5be9fe8,64f249f6,c88d0cbd,a086c60b) -,S(51e1f319,3286d2fb,29cb4a06,84d7c547,797ff5dc,fde9572a,63dd1e0d,2646365f,ac470e3c,6f30ecc6,31a90d7e,6c4c3d43,b8640ced,b9465cb2,ace2cc87,52370e3a) -,S(8e82daa9,c40d4e72,605dadd6,45bc26dc,22277f41,56d2a248,29bcf79c,d5a5fae0,7f8155fd,be9057b2,2b191dd7,233e291b,b01b961e,32a124d7,33ad99b8,167c53ee) -,S(79e56744,273c7aa4,34ffd5e9,525fa788,38bea674,64e2a595,9881b359,3e2c41e3,625089a3,c50defb9,f00ec764,b47122d7,eb786a20,f278bc33,e806e7cb,f385ecab) -,S(a97e00e2,d19c1957,51deb891,84e24a22,af7fe156,f2f1e068,79ded3f6,62743f79,881d7ebd,8bcb2c49,354726bb,c44ff91e,f3f5835d,ea73b282,944a5097,cd8284a0) -,S(3bf10546,7bbf5c3,14e1c3fb,40542378,9bc52fbe,8fb38aa8,f4a70727,b338542,e789586c,fad5b7ff,6dc68e5f,ef840e05,9a87ba51,e58462b6,39042c64,24f6367) -,S(80296c77,58791dff,39b4ee87,ecf3406a,49cce0cf,8437fb2e,1f4880b,55d9cc5d,3b06be11,3c7f781f,ce28753b,708bc514,902e4834,bdb09284,846c4ddb,90152dcb) -,S(48e2cb7a,a3eedbfd,f6a9cc12,359c4ff1,b7b0fe4e,87e57023,59896506,20ba52fe,dc78417a,fa909bbc,594411ba,87f72ee0,a0a45631,3cff4aac,7ad564b0,9ee8ed1b) -,S(dc91351f,cb775488,286b482a,a187d79c,31a3db2e,99730b6b,7b4805a9,73403d46,ed720e0d,2d13192e,8c180ecd,5e09fa5f,fc52e35c,4e509b2f,fa93ff96,f7adb1a3) -,S(5d37c139,48ceb4fa,9cd05b15,1fb344e9,3a2b2653,5b052b9f,1797319,e990a670,f790933c,2590ba48,7a832ad,6b940634,b62e16d2,7c9e748a,1856d53a,1974cb01) -,S(98bcbab0,f8d69b22,6fd7eece,a848ff4,15c8e325,ad9e8157,708eca17,77070aa2,7671e3b3,db715487,e6affd61,5218a7ef,a08aa949,9bb10206,e2de58d,ea150212) -,S(60e2c1cb,3de9486e,fa594384,d5903340,12ce308d,2247a18,8fa5c112,3f35b1c5,6de7031b,9767c66f,5c3c11a3,853bf722,4d58d086,b68e08fa,63942f2f,9369d1bb) -,S(814716c5,aa8256b7,50bf2f70,2e2f9bcd,aaf513bb,329eb467,d873ea72,304885c7,eca644ee,8fa96189,13fba31e,23533de9,eb7efac9,a0fcb58,6300a42d,c7d297ee) -,S(25789f3f,1db412ef,af60f7b,636686d5,9fb71586,200e8e3b,e6d934fb,72f8de77,e5222798,99d1e21b,5734a6f7,7881a686,863bc03b,8c58cce9,633c8302,2c7de0ac) -,S(5382f40c,98bff8e5,646a87fd,f3fcb6a6,27f2a91e,780a1527,ef18cdf2,a0f1bdcd,231d01de,e41ca3a1,da068ce1,39d97a16,39c027d8,38c7879d,9a1e85c6,4a32b502) -,S(448cfd20,9db2fadf,fcaab14d,8f57dd01,67d9ecb3,f18e9dc6,e573238b,a11d1f2b,bad8e2e5,5a4f56c2,435e8d18,14d2824b,2ba1bb67,9520587,5a11c315,9166fea6) -,S(d917ca4b,fe6335f,5012b69d,5444bbf9,f6c4893d,eb612ab5,667afbe8,2e5653d,3fde9a4b,e6a49756,27950f1f,f17ce5f0,aeabc055,3102c33a,4bb85bae,f32bad17) -,S(c7ee9f5,17a883ad,733de053,be3ef583,1dd974e6,a4e8570,db35f24e,91ba8f72,8db7738d,26d367bf,657d2a31,c6a08ce2,e06a7e4d,2df39f3a,2bffd062,79bba44) -,S(83f0a19d,983ed6de,7a2b173,77c843bc,819a77b8,a32acaed,b7085e0,94d9a30b,d2ab3e96,67be4473,d8748b63,6113be60,880acd47,6d574e00,c37f4875,2cafe6a7) -,S(f3f8aa6a,61687c40,98fb56bd,e74d83dd,59674079,7c52f2e,2b299277,2313989d,3a690c9d,98503a3,2d201ff9,a896365c,caa1b54c,36857a21,ad63994f,41a109fb) -,S(4c1a11ca,a30bd6c7,d95d6e8b,3ebcb4e7,914fdd40,4384716a,283ee1ff,5032249e,e7e718c9,4653ef40,d214c604,e65339d0,6598f17c,37f82880,9b7e5215,b9424da0) -,S(2941b952,3419a018,53f3bdb0,420f3182,529ebbc8,5a1c8f6c,1d922c19,3ee5477d,377f226c,29ca66a0,aaa05baa,7f6c1ede,80482b51,8982763,864392dd,3e628413) -,S(9d04d07,aad49af8,65bb3eb1,8c7078ac,4b5f25ef,e18572c3,3842161d,8591a6a1,f572968d,ec2ca89f,b45ae02d,119644b6,779eb0ca,1d48f724,f8512ba2,2c83cd34) -,S(4401f767,c3c3a101,b99a983c,9a622824,d660c50,177bfef4,a2646b06,43d26e20,7952faf7,8e1b114e,16429309,1d0669e6,999f8bde,ee980c0b,b7d669de,86d4e342) -,S(94b6f427,fc4017d3,b328665b,acc863a8,ab8a1c4,7b283fa6,8d7b7f0c,1bbba31f,1336067d,35f0d2d4,6ec8199e,99dd07a9,9cbe7725,a9981868,e09a0217,df40d85a) -,S(41621ba2,92c79bbd,463b87cd,de75574b,f2fba59f,92025445,7389b4a2,4de7288f,355337d5,b6f30b78,81389951,fe67b943,3bc70a07,b294d11b,717ca2e1,a2cd3188) -,S(b0838415,6256c1d3,55900dde,6126818b,8a9b27ba,ab14d73f,c33c399e,fda3594e,2aaf9190,55b162e2,91cc5371,b6a4285f,843ef8d1,5069ec7d,c5d68475,c5a954a5) -,S(cc99a14f,ef418fea,5de9f437,7ccc1426,7d910f13,e8448fb,8ba92746,6c0dc9bd,2e30b64,7c01c12d,d42f164b,ac0c9bf2,22f7b3d9,2cffd7f5,c77aebb7,18536f28) -,S(8d2bb24a,dbec1858,d565d59c,1d805d8e,7b21d6b5,b967dd50,a2f420dd,5764e37,cdc6d730,e78daeba,712537c7,8a09322,fc371d0d,6a5645ef,e7014bf8,999f712f) -,S(63cee6de,f18cf4a,e6ca1871,7750e328,dbb94c6f,27422192,3b233a3,e50f7c9b,81230dad,ad2d233a,1b631b8f,7a885828,ce005031,e1365436,7ca34173,1efdfeb8) -,S(62084e9c,1dc6dd03,9a68d5cb,fba19dda,b2e4d07f,b8f46114,926a59e6,92755a0c,6dbeb4f4,62fb1af0,dc273a,aa827e0a,cc9c7f1a,fbcdf02c,c4bd98b7,5061a26) -,S(110c0eba,f65b6280,14e368ec,17072acc,3f34a937,7df79238,c2773625,5d8dd827,1a4ba716,6f236258,961d5865,b020b83b,c3c3e74,2dafaba9,649ff85b,2ae75c6d) -,S(d848a51e,50fb234b,a807306c,fab97405,baa50a5d,23cd12b6,8927c9e6,f1c87e00,9db9be62,88fb00c8,4cae4b1c,c99449ed,51fdb49f,3cb7aadc,16a72b6f,a96a4fd8) -,S(42311893,a2706ab4,52547f3b,3901b9ee,a8cf2660,581b0023,96bc9a7c,e14c2b5a,750f86db,9ba6222c,199c2a9f,77609a47,d6129a1c,e9ef4d70,daad3d2c,ae4165bc) -,S(4439c4ee,471adc41,32f45496,77ca1e32,6b252f1e,5f17f741,9fdaec0e,3834d37f,bd75c32c,22c5c3de,62f16ab6,6f86f93b,617c9565,b3859195,81a00ee5,75897e87) -,S(4dfce3da,b19231da,648b0bbd,8c52fdb6,e02e9e79,9806fbbf,36bacafe,c113b053,de8c5f1f,4b727fba,440a1c3e,147cc1a2,9d647c59,42feb42f,69d45a2a,13042c3a) -,S(3bba2b2e,e8e72736,f54f9158,281f6c14,9d0ba6f3,ec6d89ef,cddeff9b,8117dc9d,ff087274,77897e56,e5e93f94,7af6ca0f,6f9a2186,a6a60d2b,af690a30,da16ab24) -,S(a2fede43,37bc6b2,482d92ff,f55ab0c,e239a00f,4fbb0595,27f7d67d,8317deae,2a791508,43beffd7,ef08e195,d0ce022c,f780116,2f1852da,98c3638d,45869ed4) -,S(221c4e2f,f503eb4c,4a1aa8e6,77370085,b3d64d09,8430a185,2cb1cc3e,304bc0a3,c3c37b1b,f954e79,c124fd70,ad3f8765,a70a7929,4a262de1,99e11dd1,95b7ae41) -,S(a0c32f80,f7e4ba05,caf945b,49b91306,f909c8bd,559e4bfc,a58ef3c5,14740ed0,d3eb8f01,46ab4700,41de4cfb,dced45c9,966aa1c6,38a42c90,41ba1891,36f9562a) -,S(762e7a18,b4fe627f,1e1ca7,57740811,bf33395,cc962aa1,dff79be4,18da85c6,a0df0f46,50461c0f,4f8a743c,3455b842,5875f795,4af56b93,dce93234,c4f51ec5) -,S(2f02d935,cd95caf3,d56cfbe4,4337b1f,78389f34,1146f561,b8d632c4,b93a29f0,173470d8,23f190b4,f8008872,b23f1a32,9c45441,c12fe87b,e74e927,18f44569) -,S(c9f877d7,2eb816df,1c5adbd5,9fc98a39,c5877d6e,24ef1612,314e6392,e7eab212,14ce9917,88cf7eec,5a5a52b5,8fcaa9f5,88bb0052,754b3ad1,b0858e4,6a067c4c) -,S(cc4dff69,18a05cb7,a6f296df,6cbf5d0e,d6dd1c23,ae76c5df,239d2179,a0baa172,1cd438b1,b8471750,261b0650,663b4a56,e4dda0ba,b5390cd5,b7869448,654a4dc6) -,S(faaac74b,3ed2713a,29c10219,a78acd51,ca015a8a,65646a5b,cccec828,efcbfaa1,adcad43b,dcc2ec0d,bd65c46b,7fe79549,b2e74cc9,13fbcecb,f8bf661a,7d30d934) -,S(171356c9,30fa9bd0,da1444b7,35be6c0e,8a0025f2,3d1a2480,dd0aefc4,44fdbf46,770e9edc,991efb9d,ab44361e,d2398e54,62e2464d,2ee2a14e,b2e149bb,9c9bce3f) -,S(933f56a,e0473763,d2d491af,55f9fb19,c055017a,7a81b43,b641007b,e5680214,66059c47,481cdb63,481ea647,f494e541,ad1d70ff,93b1eba9,f85a9cab,a0ea76ad) -,S(a300f22,b182ad37,d7e44691,bc9c9c9,8a397f76,1ec1acf6,64ac1fe0,5bbb6b34,bd6f2ffc,a90974b9,460de269,4722f215,684abe44,6228b500,7b42bab4,5433593d) -,S(fc5e57ed,6e901355,f97c1d62,dee4d630,878b79b5,528e3fd6,85d6e3ec,af8fe1ea,1122127a,6c21cbb9,e598b1b5,68507bee,bc7c8549,345c9d49,8c4a9b2b,2f5bab01) -,S(5a2f40e2,7a64811f,bd4721c1,99019523,899e956,ea340bff,f3f452fb,5231ef3d,6b2bf95d,12578c79,74a06d26,39d71c31,d8c4a53a,6279886c,20a122d3,2093d547) -,S(59783333,df0b99c5,be76610d,67d7ef62,fb15757d,8dd1f310,6f9179b5,64f2084f,f2a9ea80,dd3d170c,813f4623,ba7583eb,7d309d97,c34f4c4f,a7676694,7e5b7f5a) -,S(cf61124,6b513fc8,73f72bb3,87a29c2d,a1c8bed7,4ca7ca08,1546db1f,37672d95,d23c3c76,697f0443,9ed1d1a5,661fb0fe,1e182cf4,2e07c787,3eff7abc,2f8c70ee) -,S(edd14f05,133a1480,e26eb7eb,8063f8eb,1cb871c9,606957ba,ac14b173,2ffe7d52,d682f280,d295d528,4c1b3aa8,445c274e,ee603308,ca4792a,61b5f8d6,34b1b70a) -,S(f9b0fce9,cdc8af3,8b26e790,2c95926c,33cb8d30,a5de80d1,75fd95c7,fc1a1713,ec7e8df6,f3d163d7,181083cd,c8cf4a89,df958b8b,d6fce2b5,d4752240,f2a3e6ac) -,S(ae906599,54187f57,89306981,7417c566,d9ea4315,f07094e4,e46bfd24,1746a3b7,2241bdad,c09d3313,e9d006ff,2a04709d,17335573,5be5b10,6775457f,231a129b) -,S(55f0f800,76492f7b,f5e134cd,e581ae3b,f68fe9f3,44107540,c54b350e,47d956e9,22a0891d,e68488a1,dfbb4b8a,35fe9835,e258dcb5,c70ccb98,2c8a48cb,c33956ff) -,S(90c8ab06,86fb40e2,31923bb1,df86647c,6cb7e3c4,c451d0c1,b871994c,19663bbb,dc748cd9,570eeb2d,c6fbb2c5,c417979,cb30d718,94c8e463,e3b7be3f,fcc80ab4) -,S(cbf47c2d,6b21ebb9,fb268e73,56ea849d,3e476d6b,ac09eb60,4bb2e27c,84a4c694,f0288fe6,8042894a,39abf8bb,e5962421,416ed9df,dab081cf,16e86fba,7abb2873) -,S(7c30885f,c18b68b2,8fff758,2148d738,d8f1bfb2,46543b16,37e9fce9,7d11fe80,3e2d1cb9,31a11c15,b26c6d37,8c886e10,52c06718,a63e621c,7ea51c76,3c013f2f) -,S(ad614919,d1bcba0,dd2a9da9,de9207db,e137c772,37f333e6,4f11433b,f66d7753,fcaea18b,3512a188,9d604619,2ba759b4,190b72d7,ec53d0b,aad9e01e,d239753d) -,S(8df7041b,af8c9c15,70ab50a8,1ed335b4,a7bc4171,a3939715,a295ca7c,4e5e29a2,e892e43,82677bdd,f3566b24,c7ddc6dc,e12eabc3,84a19a13,99b64ba4,bdce02e7) -,S(9f4c1e57,61c8520e,9a751891,ac1bb5f6,217f4e77,7dd88fbf,2a127804,2cfdadd6,fda210ad,c6cee889,c35831e,b3e12c7a,ed4b6963,9f3d4860,9d9b960f,4e7d0f50) -,S(a436f4dd,23ac70a2,c093bacf,91de3093,174de618,7525947c,2ee8ccab,a515acbf,c0e9d9d9,2a615b9a,9439a450,927bc128,5879e8b3,7d460ec,9fe57eff,7e19afb9) -,S(a38eed16,699743d9,16d8627c,5039695c,37497c67,c59547d5,67bdfa20,b86f1930,6e3e3ed6,effc3b5a,c9b5b5fe,3f26c91d,3be89bb1,48414c18,bb0e5454,49d9d7fd) -,S(5f4590d2,d4043a1,faf659e3,36b0f24c,b6f1de5,88e92586,83361eba,e2fbf3d6,250c0a73,42ceec0,3ec1af11,764e7ff6,ccc833b7,240466,15890be0,55197db) -,S(7565860d,c6ebb900,68ed16ff,8f7282a3,d52beac7,73cebc55,1be51f44,34cf56c0,4b56ecbe,526ed458,5428ad7d,e9d7f3eb,9b84687f,e01e1346,c32461f0,bae24c26) -,S(3e7c7fce,3a56ef01,cabad50f,2003a5a,77292742,be80b5de,c537b50f,95a9320c,98cd94b7,926e7111,f3778904,599fa9d9,d5dc342c,c495b914,a32d2722,93dbfaf1) -,S(131eb457,14cecf84,abf1aaf5,ec4c62ab,2ac91a0f,6af57552,2eb07274,b7cda208,a93aed4f,f0512604,46c61393,faec55aa,9b017a13,60d13031,27bfd897,e320839e) -,S(371bc601,e46963d7,388bff6,9c4b5f42,a98e68e0,2db3e6f1,637dd24e,a2a11ec8,e2fbeef1,932fa241,a9785238,c1b89269,21bbc7f1,3aa6bdd3,7b39d94a,49f84622) -,S(4770db04,92ca73e8,a0136bc2,2c45185,b4d45934,e4430237,1bcf5045,cae47d6d,e1af748c,25b1d906,ab77e080,d21df4bf,99a92f7b,4b1d790a,f1aeef36,2d41ec22) -,S(b31a8643,5af5db57,759dbae1,67ce3af5,e8e2ae34,20786fe0,da82812c,9594bfff,3793425e,860dc99a,a96a85a2,585b06a4,f5aaabd0,551fe0cf,3c743be3,c09aa4a2) -,S(e05eec52,84a2501,fddfe6dd,1619c374,a94121bd,7d1c99bf,9b2e665,bd3631f4,c0115f17,2122f806,99a24ea4,bd742425,4d883d77,6d269ed4,f6cc5626,ffb8e622) -,S(e55ddc84,ee407d3,45b84305,d97d3f57,e57810ef,bff3b35c,e4d8a325,2973d5c8,71f77bb5,b0fa6141,7e43e425,78ebb13c,abb87a6a,fa0cd1a1,26e8936,427ee677) -,S(ed7b6ab1,a5c8a9aa,284bf3ea,5501d33e,1aabbe76,f26a9f0e,d46dd23e,decd788f,2280bb54,19d1a620,18454a4b,cdfd82fb,824027d8,c51770d3,77233e01,1d0db63e) -,S(d4e331fc,3da4d8ae,e13a3329,acd4ee69,ce5cb71e,224f2001,f9606714,8090e79a,895141aa,2f63cd30,9f4a6b42,d6a88112,77821e51,6d08c52,1ae8e158,655e10d6) -,S(4f0ada0e,a8ec1ffe,6682545a,bd8152c7,2654718e,120d3d54,d648b487,896d4417,a603b9ac,6026ab46,47f5acf5,5a9fbaf7,20aaff54,56c88cd4,dc5ec7f5,935aa591) -,S(a2d13541,b08eeee2,4f086a9d,20df7528,a884cc05,4106b1b7,543eae3e,fdca84,5ac0b166,294d6b91,527a5249,7fd605ca,4bb67c35,85e002d1,74503b7f,5c803a45) -,S(4c1d520,14a0459,2b8887fd,afa945ff,cbfc4722,2ce008f,64fe8123,b5b6c8a4,243c4280,17b7918e,57d06597,f348efd4,ebcebff4,3950a608,3bb3e334,50ed738d) -,S(5f9e5a6,7d13e9b4,cc35b8e6,b2305cb0,fc2f5b7d,ff32ac55,1a5970a9,2bc54390,74808637,96965f7d,bc45833c,e8bedf00,85eb0cb7,26f3276b,30d9543b,7395ff6f) -,S(d76c6f80,95381b17,80ad28a8,80e29ab4,4447c297,34a4d286,98534bca,8954575,44b6c3f8,6b30e01a,61205178,90e429de,aa8273f1,277bc498,59c87300,a561b27b) -,S(7577729f,f78775af,703a9eae,b5864a18,6ad19f1d,dac658,e7a8a05b,d9df3344,6b519916,cceaaa53,92d2f822,98e7ecf3,3fa7c5b1,2e705345,32ec3f99,2f0afec9) -,S(50378f2b,457f04ba,d0b19425,86ada992,78700c8b,36bba67,fca916c5,8edc17db,cbd1451c,26bdcd49,1adbf40b,ac5338cf,26957364,f82fcad0,5fea3c2f,76273fc1) -,S(3748dc68,64365160,26384ba0,ec078ff2,7606eb44,e3d62b50,b9138be8,cc9ba86c,6c04e414,f624ae9c,ddd005a0,4e01828d,6e7bfb81,d350d271,96583c99,6611d709) -,S(b23a59be,8ea8d561,fbdeaea4,49eac729,3402f342,d05fd404,7f9c5d1c,57eea53b,bea47c68,f2d35b82,ce3c359c,83f5fa1a,95d40eff,702ed9c4,2fef0e84,406dfb9b) -,S(e4b451e8,7b42a5be,5c5f443,5701d2bb,9538fc06,925ccb49,ebfd71c1,16a64770,2af84669,9a790749,48efa86b,2b79b985,4cb261a6,8a9081e9,e1467b77,2f156da4) -,S(864ac6ec,65b8b086,346e671e,8651ddf9,de74a215,64f3da12,42ff7548,96dff165,f35738a7,7ab48555,91ca5103,c8d2bebd,b2cbf902,dfa93188,d68eb600,271a8730) -,S(b7d04a3d,a6a863d9,b7809022,56643864,fd36c5d7,9a056ac4,ecb27257,f02ecab0,cc40634c,6ba5dc23,e59e4e3b,fe6a07c0,1519abbe,7530f1a1,5ec7ef70,6f83b0c1) -,S(ddfc1af9,b51eddd8,2020de0c,4a8377cf,bd6e2531,ebc844c,7ca8fca2,714c1a0e,cf77c8c,1742c4e8,b22d9f54,a25daab9,c30f23f4,da3e1ad9,57b9660e,3ffe3951) -,S(78fcfe69,d5bb91e3,a13de26a,614d8479,e00c828f,8868fc30,ea75b47c,d51fcbe3,9ec67963,6b7053ba,b0cb231a,ac28143a,98021b48,4340f060,66da6e72,47f2d47d) -,S(dcd918de,16961d71,8222b4f8,19e76ecb,138c9884,7833a8fc,d4204dda,1115863f,abc3d8ba,c8d808cf,ca12318d,d13c2932,3ff7fb0d,813a5ed2,f5e52aba,cb23bb04) -,S(39ce2ef0,5de08106,93294eef,537bc212,e6f64fa2,96ccd2b2,94a0806c,c6c3177e,25eaf4cb,b7697a3,97a0ca92,6f3a266a,bbb5dda,78943492,39fd29db,78730556) -,S(495e4db6,43d4e89e,df50e937,e97ac4ba,1464514f,d3a46b5a,bae6a53d,3157a04,7d327e18,b2960d69,ebe4251c,f8c416b4,f84bb81b,a20ce6d4,6e6b1c57,e6ec1701) -,S(91c17e8c,b6357c0c,1c36dde5,29f9e6f7,a6cb6e97,f5b67dbe,fcaf5b96,637c33c1,2fe52097,fedb8ac2,efde2692,20f586af,f07b76e0,f685ce85,c965ec1b,a54c39ba) -,S(e3c4f480,3dffed44,6291f11e,cc5c9590,1c28749b,d6ae18d4,c0371221,d5ecfdbc,5a2e7102,571e27ce,974ad71d,acef8b28,4e7fb827,5453e40c,65b2be92,cbdc62d8) -,S(b3ee17f5,a0e81e7b,48814377,af9dcbb8,59ae7bea,5680f33a,cc15d8ed,75c25073,135a3c0c,9a6d2825,a6035afe,139ede23,b46332d5,5739ecb,6d092e7d,6cbfe86d) -,S(e4cca844,2bc91bed,342628e1,f6492335,7ca6e8d9,5e5b5732,29866066,eae76b75,dd55a555,39b5670f,f70b42b0,f319ac72,409f74e2,31d9cec,ecc8d90e,516f76b9) -,S(ab39cfc1,81c96089,998c02a4,64eae7ae,e517e4ea,962b6359,b5ebfbf7,da223b2c,def6dc57,b4dcbbe2,e6dcfec1,8281a189,72ba3b50,f996096,a22e4ea9,77d2fc4) -,S(22a32663,9e6e0469,fe4cad40,964f081a,677572d1,94b3ae01,f8e45c84,dfab402a,1c9c9d95,bd4e0ef0,5acf6148,44c98fcc,db44cf50,5d42af26,1b855f98,40d2b437) -,S(2bc788cc,eff94bf0,307c5ead,4fbc4dea,db269da1,7790a903,7c2fcc24,21f9cae9,172f3461,648c5520,44081c43,a8c78c3c,ccecb248,9d60d384,aa703e4e,24bc4b41) -,S(b930dbd2,a6720601,35a75bb8,8bbe69e8,3872c636,9fbcfe4,c622a300,2052729,9983f03,a872e8b8,2830e7f9,a7438b39,ff3f6836,3334debd,83940ff5,ae06f366) -,S(b435738a,2aa9ea40,702db448,da6f186f,29bcd03e,872a3466,f33b2e39,7514e3d3,5828d246,2d3c671f,85617e55,bcc34905,1678cb8e,f61c74e,92c54473,9098636b) -,S(c91f2e81,3acc9baf,2c52df27,d4180dd6,ee1fe67f,9db6223b,532dffb9,3072bd25,1c9c57d6,96c12f13,13afa0c2,b377e1e2,b027350f,bd24f455,69c15f07,85b73c0c) -,S(bb0946c2,8099ba93,8f28068f,416d9003,bad0d06,f8c7d31d,2b995f00,5c8d36c8,8e3878d9,3b575fe9,78fe1a62,1e978f28,1560421f,7782c164,8673906b,ed76da4a) -,S(485e3aa1,2e823374,cd506521,a707f367,5298dbf7,cb44f398,c31a06a4,8f085c8d,a12c8af5,7079b2b1,5a339d4c,302fc262,af0153e0,dfb4f878,a4b60017,86ca9a61) -,S(850f9448,d3282256,940da03f,e8a96eaa,f21d02a,78867db3,e8a9fb9a,713e844d,4551e4fe,3201ba2c,a74df3a,f58a820d,3a67836,a5a8d82,59ab2442,3bfccb7b) -,S(a74816b3,f66c1fe4,9f8e51b1,8eaf51d9,449cd4c0,54b6dc43,682c853b,be39884,4e7d5fb2,47ed7ea1,45af0cfd,c4cc1059,396626e4,80ec804f,15ecef7e,b372f7fc) -,S(2af5c56f,c71da217,79abcc1,73412016,e1eb702d,6b98af77,85ead6b7,7b20136d,7f3110a2,c6a82623,b2c49e95,a31a6b8e,783911d9,b532932,1b651541,86b706bd) -,S(9291ec91,a61adf1e,90d63135,fae60edb,1a313714,97260903,9684fee4,339b5834,d530506b,e8b0dbb3,fc09649f,1832de93,feef42bc,ade2de09,bac1dd17,bdd03884) -,S(160ad3c3,659a7816,4e9cb47,4e18ff6b,a8581fd1,823ce8e1,14444292,cc605b54,1618464d,5f28d719,a61f939e,b1eb91d9,a59f2c1,818dbb58,b6e1f426,a4d141fe) -,S(352599bb,8640920c,2d85a5d7,673dad8d,ea4280f8,6358a572,b4071934,60ba9d58,a78a591b,e8064f2b,22d7707a,d3c95cac,aa2ac3d8,638d564a,50f7d1c2,8b538d0c) -,S(ec20efbd,9a8c634d,92f7a728,1e9e15d5,adb37ce1,2236bf33,4d12c4fb,7b6ba527,acdb29bc,2a5a3115,3919315e,27af9d8a,e8c54792,fd5421e2,a9a57b3b,d51b70d) -,S(40d1e4da,8bdac6ec,55ee847d,c59781e9,bbd38785,1863c64c,5cfad460,e2dbebc3,c630581c,b7c92e68,a67c7d5b,dba3ec18,4e3755ff,27fb53ac,d3a2655a,316e9ab0) -,S(fbe12740,2faadf2e,2b1ac1c3,98b66df4,81674c2d,f0ffb512,7dbba444,e7d08c7,d00edcd7,f97914d0,3ac87182,14491698,f3dfee34,e6e8587c,52f2f7b8,b7f412d6) -,S(d781b5a7,47d191fb,8850fbd8,fb1e123,4070d9d6,2643008b,b0cd930d,c191eb03,a4aa95a2,5c74ab55,f95f2924,519b2911,9762ef30,248db792,d906b18f,346afa11) -,S(6472fc42,d926bc7c,115045d0,395b5e9,22790c39,ee520529,44a446f0,9ccf02cd,512014,a92593de,e2264e37,633c842b,45d1ab5,e2ad068,63db7894,4605a99d) -,S(eee180c2,e09601e8,6a517a93,54607a2c,5fa6cf26,4c80ffd2,c5715ed6,395e0c21,c8cba798,221d6fc5,b4fdaff7,f785ca3,49490af1,ae655711,e0649669,7483e7ea) -,S(900b262d,a172ad41,15bec071,c5763077,9103bed4,db500ab4,fad4b750,45ada2d6,316457f2,bbadfe91,3f418e7f,b3fa34d4,82c4c1d8,516755aa,371423e0,51e2cbaf) -,S(7e93db87,4e1e5070,772d3371,b9ef29d1,5d5e03b1,e66bce20,420801a2,13a34c9e,cdeaa624,750032a6,f5faa0fe,e00cdc10,63f3ec47,b5bfb56a,bc2c2339,e38465a8) -,S(461fb424,65f3a55d,e66761b8,44abfe3a,d172877a,3edb1f5,da98c82f,89a379ca,768261fd,ba032718,f5501dad,c05e41c1,1f584aa6,6b8e732b,7f15285b,18e815d9) -,S(1d9f581a,f0f61a0f,e5d0f0cc,91ba4f93,6de28aa6,5f35059e,997de778,9419e09f,7fe9c98c,7d59dc56,160302e1,89676f54,3f02db1d,622251f8,adf369b4,891bf6cd) -,S(8cd70b52,904b2aa7,240f7a70,e4efe379,66386dff,3ccdf62b,e2343821,767542c6,b3c3d03f,4c7e0b1f,f08bb2,f72bc6ba,e9e293d,886541f1,ff86bec9,b5ddc2f2) -,S(a0b547ea,9c08865b,99a5b8b3,800daefd,99097b23,4e442a2e,819aa628,eb4a5261,607ef115,e585100d,c003cb4e,1a27eb60,fd9d1e18,f2d23a22,80cddd89,f2ca2952) -,S(ea8a60f6,547038e3,683a649c,27e81ab4,192406f5,5fdbd775,78dd6360,4344d289,98afcac0,b05ad5ea,8fcb9f3e,3bc22f16,881b5fcf,5060c691,ac10f746,79822fb0) -,S(e6051a9d,882f9ef,77d488fe,55bb7829,48bce506,91350755,1a8cd4a,14b0a711,1c9cdabe,9d9eb555,cb9257b8,a60af75c,c1ec0c82,4d933498,ffaa14f6,2e920fce) -,S(600876c9,c50fd337,6ce5efb,c07e0e5b,165338c5,4f8eaa4b,39a525e9,88765674,401a671e,f52b21f3,83df5da0,aa0b215b,b044202e,606a746a,213796e4,dbea4189) -,S(3b045b9c,5ef6fdd0,9b3efe12,169e0414,3c0eca56,5b7e0185,274f1e97,f6b2ff40,aa5773ac,b21107c4,2a8085d0,5d6914c3,a135a47b,cb136dfa,d20e6813,62780a28) -,S(dce98d32,ee0b55e0,4d67807f,ded9cef5,f9504b1d,e552a2dc,643ee7f4,b1f0f1b6,d03ac27c,9e992497,cbb746d6,7acf5427,aba058e2,801df1b8,d435a1de,1f3fb086) -,S(365b1148,6e8a60fe,8a91c07a,93686787,dd5aea7f,22fa1449,58be984c,e378fd76,2c7f5217,319e5d50,4c5ecbbc,bdbb8ec1,b36e2767,54f405c3,f852b761,ef01c9c0) -,S(2e37935a,4dc465ed,ee8dc3ca,d4ede356,3c3720e8,57c986cb,b9c73b2e,ab6b5806,bd0873f1,5278f46d,802dc7f9,d7f81a4a,839cb690,10c6d522,c0e3945d,4bce346b) -,S(49b68e1,93745ad7,b60ddf92,70d71958,81cd8585,6e47b0bb,fbae94,f1647568,ca1d4bf0,13e43ef,53bcb2d0,5f4b85be,1dc82d31,f4a7795,755693c0,72819dc1) -,S(6df53d6c,c79c5a88,2c2b6f66,e9ede075,6c8cc6ba,3e60620c,b8130fcc,fa744564,48c3d6ed,3b2b7c59,2472f291,41a61495,4597f77c,afb576e1,729804d1,26431344) -,S(d99f8f06,9104e3b9,26163672,767145a2,2f9467c1,c8e32b8b,d28e170d,bf4865a1,ccfc46b0,55aa5d93,64e67c4e,2c06cb18,c2b43333,e4111479,fd1bfe50,52543d7f) -,S(77727c17,ebbf8338,ba807572,8558a059,e23af7fd,c68c342a,538ead93,e59930d1,a037dc7e,2cde1802,fe3bc65,75f50ca4,ede75194,133e7083,66de0338,40c629ea) -,S(1d40ead8,563a4ff7,c14c84cf,ad1339ac,36ae3789,99ec2663,77e0ca2f,6be22604,8497b443,b093917f,ee65a5ac,1c4dfb87,3a6b0c2d,a968d713,a711ec12,20d1face) -,S(2a39f41,adf5ab33,71a27c20,51840d37,e3226999,17a3d0ef,40590710,406bfae0,cdaf7a8,58e99fb8,23a36b04,8e844c18,8dd1a49e,c70488ed,155f2ac6,905c27c5) -,S(aaae4b1,d8b08cc4,8971cc92,fd974a21,66f5ea92,b6ce215e,28137088,19c684e0,9237995,c10a348a,84fd5cd5,5151e33,c63739d1,3a425bde,a34d78e9,e3cd8f0c) -,S(a5b0c042,591a53b6,334939d2,9ac2c9e2,11315a54,831ef440,965fdafc,e6477d40,ac3e7cfd,5d1f0248,b362b206,b3c7dd60,bc9904c8,d2a416d7,e117a5cc,4a62ca6) -,S(c1b7164,e6166a96,a8f643b4,7f094be4,3c16e3b5,3ebf5a1,2782e41f,27c63f0b,8469161a,4ffaf1ff,5b50ba81,1de3ac79,e34810bf,73ed1207,fcc0f01e,75663a98) -,S(98fd825,4b7963f0,4d8e0f2c,8eb26dd0,342e605d,8fdf28b4,57b98e14,adca63bc,e297a80d,213f6664,77f9dba6,5cbcb99d,2dc14325,be12098f,22061115,b1a192d6) -,S(f1f08649,71b6ed49,2d34127d,8c2e6f19,48c464cd,816acdc1,63eb3aad,594c3281,26ae2a0,f9e04fa9,13b8954d,85602e6f,506a0de5,2fdec31a,346338ab,f31f5c) -,S(ff470cd,c324d2ac,a63441ea,c0506fb5,b63af83a,61a23a91,17240e23,930dd197,e601f66b,b18e77e8,4607a772,a1efa73b,30734b4b,8fd31eba,5a5260d2,5627788f) -,S(90eabc6d,968aa196,b5808127,baabbaa8,ad0f82b9,332ed6dc,d04442df,bc6c63a6,d6df0f67,ffb23cd7,2dffc4be,44476b2b,2faed3e3,dcdc30f9,4c1fa4ee,bb5038f1) -,S(e217b126,acc507a1,b41e0826,b300363e,bc0a43b6,feaf3866,ecd4b8bb,cc7e11af,7eb28def,83db33d5,8b8eb733,2b27a386,921e3a5f,b0321ecd,a8d1fc6e,49e98f30) -,S(2a196fd5,82b85d5e,1772bc21,84d8aad2,b5d008ee,c795628d,20de68a9,fce1d184,994b4657,ee9ee3d4,fdf8dc8c,cad2ff1f,68526c67,89d82230,c3399f6,62201303) -,S(bc9e3bc8,3a6eca7e,8a9897c8,1118f7be,ca770cbd,7e66c2e6,1321d026,7ade4342,9d7ef7e2,d544a561,ab899291,75f35d24,e2b07661,2f84b0a3,f346542d,714f3f4b) -,S(ff2813f3,842a9f84,fea9e367,6f12f209,7e76b8ed,e691ccdf,6f6512aa,b2f198b3,206e3bd6,66d0c161,ac6de438,809f485,b8b6682a,f402bf76,18a484a2,c3fe1949) -,S(6e7599df,2d38d63e,be142321,769d7ca,34a50bbe,4e0adbaf,6c7479b8,d1af05f7,233dcf1d,4b0e4d88,4a9ed56e,b6b4946b,25614345,ecd182cd,5556faa5,e3654c8d) -,S(1edd9cd5,6c82eb28,14d844d1,a9e5c167,8397662e,b576f9f9,ba250719,33666146,a00f4a85,b2ee83e,949b5cb0,4d16820e,39d48ddc,95dd965f,e24251be,3df43f4c) -,S(2723de06,1f794cd7,76a4a090,738a81ea,818a2f73,92d7ab07,18d79fb6,407324af,35c7a9be,f9810c50,3c53429e,344ab888,38daad72,77cd0e78,3db1c1fe,c6bbf41f) -,S(4c4fb244,4cb54def,6d9659ee,b43c13c2,3874ec2b,a7c6b53a,f469ca26,ab9a213d,bbd2eafe,56447a9f,feb9ad15,349b338f,d4a1aed8,5a356472,82751e5,5b8efa3d) -,S(736359f7,347995a8,8e306977,1fb3fbcd,12847ed2,8e4e612f,25095720,667593e3,23bb37ed,4bce0512,35a215ca,6b8f9868,e303fda4,80d655f9,72c95bf9,12bd3741) -,S(15cb9594,ee936bd1,4b981394,60879bee,6f33b0f7,c0ccb293,825794d9,85f595be,aaad772a,2ec81ab6,13775e9,edb274ef,e2e133e6,5e58949a,c7f25429,fb1bb152) -,S(3b5489ab,97e5cf1e,84a90eb8,20b8772a,df574777,a61f0a9b,41e6c567,6be78fa4,145d13c8,e9674a17,ccecad63,f113d64a,d59a1eb,bbb10cf9,e7134cf6,562219be) -,S(78d1b99a,a6f9d385,b09bec7b,b59ce26b,23323e4c,3a259c56,68417597,a29dd2f5,1c8d11f8,e883b210,cf54369c,e9f6a280,a6b890ce,15b4a0ef,3cd8837b,7e16a122) -,S(385e4e8c,5ceffbbd,3a813e3f,938912e,d2fd2d18,2be81210,70cd15fb,39661e85,f4a1c414,9f5cfbc5,213ceb21,c1cc08ca,c9b168e2,58cdec70,36e2dacb,ab68069c) -,S(310f8c70,d8e46c6e,48930df3,c53e9292,a7c87230,292d6b1f,c28d9711,951aec6a,6fe319d3,c92c07b2,56715154,d5d7046f,59d92d5f,6dcedefd,b0386f5c,3417146f) -,S(764f3c30,23d1d50a,e170b80d,48d58923,c1f91a96,42210912,94066585,d7c70bbb,bd92fb1a,becdb4a0,ed941146,878c99cf,c3ee9eb8,c8f2b8e4,b547cb40,e3dca724) -,S(3d5d23ba,b357a37f,1bd3c86f,84010b8a,b37a8075,3c47b1ab,36f7ef72,a3e68126,2bbd1841,bdcf0265,838893c5,f5f9c0dd,7ccbb461,93068e0,8211595d,6b34255b) -,S(a70431ad,cdfc7b8b,febd2aff,d6759e94,6d4ddd7d,50f50dc0,87e256b8,2a7f8a1e,3ca4362b,9362b2ea,c33d77e8,befeccb8,23163921,86ff5f20,384247f5,9147f593) -,S(2a388212,2c1b2ecf,3c800432,7c5dd403,2263e9da,245dc697,bf7d63e6,300e8a7d,ac96d188,53b87bf0,3dc5f2fa,fa9b73a9,a339c0d9,a7245175,fd72c822,12f6ff78) -,S(e99c59a4,ae3022e,b50bc545,f57e3013,56b49bff,33069a9a,b4d17c0a,424b5451,29b24b79,fe55fab7,6c3737b5,61505916,b4fe1a98,20837349,baf445d6,2e9bada0) -,S(a0a42ed1,bd5ac5ed,f63f1a3c,3c3fe2d3,c0be26d6,b0da384b,f19c034e,83306d4,c39ff3d2,d4442374,7a293e28,8c320ee8,8aad0879,672679e4,e5bcf611,5ca0bbc3) -,S(b952e5d6,9ba9f063,f1d1670e,1419730f,5cc17e87,b6f0b01,c0b86ebb,c09e0053,c1e8099f,a230b8da,6e71c9b5,bbf250ae,273a4f9a,f53cd0ca,fe8f0c7,2dc46ae0) -,S(3aee273a,130f5f4e,463892b4,512621c9,be83c18c,655d5a2e,620f83fe,95a4e904,edf475c6,921fb6dc,f2c3c6a0,b93f9470,9237b035,9e8c9131,eb7eeb0f,bf0af7e7) -,S(96ddcdc,dc65af06,acb10d91,b87827fc,aa2f9e65,d28d0449,65ce255d,ba66ceac,2e6d0368,17fd4024,c830d4fe,310bbc23,9e2bf37e,60203584,215f852e,d100ab39) -,S(fd50f406,c757ec9d,b10e111c,32941fa1,e0d07ae7,9e3584d5,af45fae4,d30334a3,71b77494,d49c068f,c7db1d36,4f8db288,ed9ccb0e,c6137348,324f4bcf,d53fde6f) -,S(6f2d8268,11954523,614915c,9568ab9b,bd061112,bca3ba77,d3c64f91,6ba097d1,abe41199,849ca7c4,d317fe72,2a5647a2,97261d68,d025f5af,e880ef78,34787a87) -,S(d88c0db7,6dffb62a,27683d2c,e832a312,9c5099db,e2623c9d,3f064247,21cc1400,5134f15a,df6d7e92,5d81726d,f08732b6,ba5aa289,431bb4ea,542e6352,8dcec51f) -,S(a8de9ae4,ddde3f28,ead01363,2202fe4c,b6c0fd4a,a71d5562,d95f557e,747105fe,179e946b,5a71b614,90bc39a5,17dc752a,53682043,6efa907e,383e3da,a3be8803) -,S(626c6827,f7dc3d40,9daa4811,80e65b0d,799c94ef,e48077ae,6eb250aa,8fcd45ac,3d659db,87cf7b28,32e4a2db,8db88e5e,b30b7ea1,7819c00,fcec5d63,31bf2f32) -,S(28a3a2c,f00efa47,db4b2ef6,9f56cf02,1666ebef,b5220495,5b5484f4,2ca77d02,8dd00ed,fc9870ed,99ce90fb,927086c7,fc16837,9794db01,f7799b16,8393c82b) -,S(df0b029f,27c46405,245d0dc2,f178a48e,c3b67275,7fb92bd5,dbb29370,c1545786,f133ed05,c7e159a8,810a5ad4,e1019f15,757b474b,fea1679c,6ccd18a4,2a1099a) -,S(dc6f57af,9c1e0be5,2d2162a4,e8a6b63a,c549783,4c7c2c8b,421bbc5f,dc1a49ef,6f586aaf,e610fe5c,962ee20d,9b389bab,66fca44a,1c19379e,9e97e104,10f1a0c4) -,S(db796ea2,e0d2c690,19adcc0f,a81c1d93,8162472e,a0e3eac4,bf13b398,b255cd15,2e60c6a7,32e1fb44,641e0766,2191e28e,79375420,43bdb3e2,9474313c,7d05ac88) -,S(569b669e,72ea98fd,a5ba3efc,e74f88ce,881fe269,30b063ca,59fe369,35633a2d,badd8eaf,2551f872,5db3f740,6eb5e376,220b6a6f,ff4f8ca2,f76b7755,f8ca0c8c) -,S(36132420,1f9a33bb,d4b6b6f0,e2d175c6,ec795111,85fd2451,421ac333,78468ae4,f47b56ce,f7bc7366,6eeba135,14756486,62a58e17,d955dee,2821618f,fb3c4314) -,S(cdeb2037,1e4d2014,918fa243,182db0ff,855a0783,c92fd5b1,b604ed33,494a469c,7d3c7718,6829381d,2fd0098b,c84ee506,970a7ed5,5518b393,a83c6f79,d8dfa7d8) -,S(6035cfa9,d750c5ec,d3b721,ade88fff,ff6c4d74,f8db7755,c8717cfc,171598ef,fe1798da,160b2436,412dcde6,5482d202,9bb129d7,d58c9cb7,49f9fdb6,7dd675a) -,S(b1f52e97,e49998e4,e0e75b0c,47178f4,bb250b5d,97d92ac1,8dc9e41a,3b79c0f7,d83f3d65,4e4cfd8c,5f24370c,a2651c5f,de484cf8,1024f33d,8087a50a,d3df795f) -,S(aa799b53,4c73da0,9f011395,dd5f709b,f1a5e056,42536477,d7862b21,6df1b641,3a327047,b5e95b64,593f6887,9f38aa86,dd592007,cbbe7338,a003d2d3,33248646) -,S(da4a1964,45bdf4fc,479e56b6,6d339a45,262d629b,dd8c63c1,8d35e9bb,a445aa03,7b3a5eda,25cc63a4,66cff29,634d5eca,353376e7,26c2c6d5,63f3f92c,b69cb70d) -,S(c300b4ad,c2346d0d,433eba80,f0eef071,7e620d46,a07b384c,231e733f,a1b8d656,32083bb9,48d27ac7,f36aa439,a100b95a,f73448da,454de356,6f4a8771,e3cdba42) -,S(c559a528,67937244,d639bf7b,90df2b2,ed64a907,e20cebe7,6a358b2b,94359f04,9fcac1aa,5c08c983,20d671b5,63f4434a,806d78da,15964474,d2470cd,49bf5977) -,S(39b10147,a46dbf4,f074bca9,a83c10b1,b0911ceb,d3e795fa,9b96333b,dfe83540,ad35dcc8,c3b22743,4daaa313,cd6334e0,168da417,d162855e,64294196,2d308278) -,S(39c9cab7,d2dec601,7f840597,19994c9,4129ab2e,a2779d6b,34774a04,2f7d6d42,c73ebd6b,835a8a13,354cdd45,37ddfb3e,72ca72b4,c8049362,3afdce9e,43781845) -,S(1a625998,8a30b462,adec6097,2e218ec3,f8f81c4d,44131466,fc7b5eee,eec679ed,739beabb,1a97c9b,bf6776e6,2e213bd7,3651a39d,ba042037,bf5f8cdd,334114ab) -,S(396ed910,cd35c308,d412761e,bf283a98,85f33ecc,3ef643bf,3f422dfa,ea4c4308,721cdda6,a08a614a,4dc48cf8,442a46b1,3945e158,83671b7f,556d19e1,144dfe57) -,S(a50e06e8,a2e8ccfd,94aee96a,b0bd831c,83e15340,25e3abec,af7b7af3,9b299a47,593205b2,59a18063,fe5a4575,e8e085e1,4521fc1a,3ab5e14f,3fcd64fe,2bbeba52) -,S(4a9f8023,17b0d1c0,e62c8bcf,7393fa34,dbe15cd6,46e8f4a3,dc3f26b7,11c3e1de,40eff6d,915fff,cdb30c24,434e8928,239867c3,962655ac,2894bea9,f7c6bb71) -,S(8ce5e20d,9decb7e6,10b18562,e2ffbb88,7f323262,55ed9f05,5d2da2fc,8d608b73,eb69b6c,f363e164,e92371,b592727a,63f024b2,aa7011b5,4f1f698e,1ac720de) -,S(f32695d7,9b53e9e5,1f2525e2,8a5540ed,84143ed6,3700be0a,36726f9b,b483f24b,e8d36488,eea2055f,6592ca1f,6fe23493,1d81bd16,1c61523e,f1ee1907,c08471c8) -,S(3826fd86,3bf6592e,5b51ad14,6e02089,d9274881,25d25959,4856de1d,d6c34d07,ea86f1e6,a29035c7,43e82058,a7ff9f82,20da001,a8901e97,26583b1c,ffe4cc83) -,S(7b1afcd3,2e32b0f5,1ba09868,4ec72762,ae8611a8,98e87ddd,dc6410a,40ccd551,deba6ef7,79e10931,8036ee3,9bb6d0a8,a3ce0eb0,bc5620ef,c70828d3,d2e37884) -,S(3eb1fdfe,d2c27587,540d39b1,b66a36d1,8dedddcc,7f7f7b63,348460c1,35a91bd4,b8aeaaca,536ae794,619506cc,a812a67a,642c5345,8cfcf7b9,eb898f96,d26b36cb) -,S(9d61dac8,aae9fc5f,532290cb,683eea2e,b71b4d9e,901b7c45,c214beb5,9b56da8f,2e7caca4,2ea1b22e,7024fc3e,e267ce99,280a8f1e,78a2a271,7938762b,3a446036) -,S(2db372dc,3167faa8,e8e1e37a,85ed5546,e91a43ef,fddba39b,e38d0eae,3e11c7d8,16ab6f61,bc1abd6a,16e79697,fb59f0e8,84f00534,b7196380,9b06e10b,59707ffe) -,S(98f7cef9,f7a2b538,538e83cc,9ad3132a,5b03dd67,f7fc4030,2ff023d2,8805dc80,3b40f823,2813e6c6,bd56df89,1e96a175,468bedd3,f9518dd8,d658105f,aeb98943) -,S(eeab2e6c,c8ab0d24,d5df5852,8a89db42,c48f0861,4d488c7a,363cd195,edb62548,607c41ed,65d3328d,72be2503,f5edf14,523a7f74,402822cc,1709927,c82649da) -,S(955feeff,b2161c70,3469a9d6,c5fb31b7,b7cb5ed1,ada6b537,6d935705,b3db942a,a9195a48,a561c342,779c984,6a710059,283fcd0a,682cb5a3,fdf48ee4,15c0864b) -,S(219a4d2d,70d2ee9e,d3c8f541,1cdac36f,4db23bdd,a981a5c9,d44ce5ac,dccd85a7,67441968,43008ec1,71284aef,2c64f7dd,3dbfdda9,5c6c8e4,70a564f5,c4ef53b4) -,S(4976290d,7794b161,2e2f5cbd,282c1036,d594571,722e28a5,ed542972,f91ddb23,4cfd95f1,60fc5655,2fc8354b,446dc510,23571c24,56f57aec,79004616,ce17ebc4) -,S(472d53e0,268ead1d,bbbb99ed,599f5676,1866e0b3,c14d4a4b,5c44d722,b072b1c1,e9b9c009,6115d4d4,a8ed42e3,1d967b89,e4dfe82b,ec642db8,e31693ec,c2831232) -,S(2a6f5b7e,7a4db95c,af875d61,75a6e1b0,3f3462fb,c0dd5d50,da3327b4,70ab18ef,91b247a3,92aadc19,7d9f5b78,f0b013ce,c9f3724e,a2f37347,9ade7e03,8659d506) -,S(dc1815a3,bf48d81b,b5e5e654,fe0c8c3c,7431a62b,9d1065ba,17df9c45,23146c19,fe20729a,311550f0,e47e2af7,4747effa,d837c5f7,b08c8f36,d0fbdf2f,d594be8f) -,S(8e7953ec,ad8feeb8,97a95db4,f03ffb98,a8b47ecf,3e68bc4f,1df0b6e6,98397776,5dadf2ef,81b21cc4,26c40a39,51f31462,12f7c6fc,dabb5157,893b1637,c141ac5d) -,S(a4d91e6b,49d5724b,9e899fe1,c6686c89,faf96a05,6e666a74,72ee44cc,119b41a5,abd68615,e296498,f5abb820,cbdcfc26,fef10b2a,ba72e474,14ae9de1,960a4893) -,S(b97081a4,f3e426b9,d3a66dd6,8e0e442,754c4922,acae141d,d0294843,6b00eee9,558f6c83,99214bb4,baa9cb64,11550b12,2c8c2f77,8e28a4f1,ea61ed6c,b8f153da) -,S(6882b6ed,82279bce,70a73c6e,f6412c54,b873a5a6,b634a25e,a8c34210,fb825848,c6fdeee9,c8233e39,2ea79c61,6689e8a3,1e3a3b09,21f2b5ae,d6b9e14b,9ff21b3b) -,S(9c542731,1c715709,cabbf11f,a4fdeb3d,1a0dba80,ad50d1a4,62c7ee1a,44717fe8,aa041b10,78163458,c446bd40,ca77f760,ef4b6471,c4f2058d,7ea42975,d1f2b045) -,S(73a14da6,776b5c12,e838779d,e3be58de,4a5ed917,3b195d9,3577330c,780cd32c,c4068ffd,e98ec4d5,a7467bb7,e8bf2c89,ceb58574,cccb3a78,b0ce4a70,7ad2c49c) -,S(6488a286,27d26c4d,bade9d26,1e6ddb7e,8748d835,d9def8eb,fdc6c576,b6af91b5,27f8b1f0,b0501191,8af0916a,945bb07f,3c7f0695,5ada697,b5c601bd,3d6d8ff3) -,S(96546e7a,5b544c98,db9ee2ef,47dcfbce,cca1d38e,1978f71b,d8c9d4d0,5151046c,d04fe32f,8fe9ecff,220f07d2,2095c982,3b10f772,b261189e,84160ca7,5f4309d) -,S(ba046f56,4598b143,a02cdb90,972022ed,e769986c,82d28066,761463ed,8cfecdf8,fc6e23ab,d42457c1,5407d37c,d3d9daa,3e57bc0d,778dd68,53603232,3e27250f) -,S(39554751,e633ca7d,df6d82ed,86a8204,5e76557f,b13ca7df,310b80af,5ad0e4ec,a456ba84,f040f20e,977df5e9,5faa3f67,cdb2ba3c,2fb9bb4f,89486b02,a06d3b1c) -,S(c5f550e7,5fef9fd7,d96c924,11046c3d,ba56b8d7,e1b17c,d46a68a4,989c22aa,548582e0,3aeab617,556a987a,cee7d0fb,8d65ea42,dc8f2cc2,173c3636,27ac3fa9) -,S(2ccc1610,a48d8db3,9a80b2a0,ee063a43,26d4ba75,79b2727e,b999aacd,6e5fa050,de6dd7db,2114002c,8dcb17b,179e5843,fa205d69,4928eb70,a073f97f,f8348c84) -,S(93b07ce7,3e941c84,1e4089ff,2d8e6464,3ae59cf8,fe6e92c5,add89e10,f7084b3f,a6c0476,c5a7267e,54ec362d,3629a1ae,533efcfe,e18d3634,cb5a80e4,4018fa63) -,S(453c01f0,55c14679,5e3aeec8,26859b16,b0ec2707,61cbba3e,438c0566,5a91e7e9,f28eaec9,b9d3c8a2,2ef73843,6088425b,e14ac99,e52e73d9,8745bc49,a56766b2) -,S(3c6df1fd,ac078c28,a0a148fa,d15595b8,c1d09a4c,4a96794,6f8d6465,e80f12f1,4619a84d,4eaa134b,a06a6821,2e7ed292,d443db5c,150b54f,6dfcf267,82a5b58d) -,S(1b7f6968,39959785,30542989,59020dbf,f12054f9,2705efd6,dcc583,11b98630,279dc63e,e3e8fa8c,fbd731c9,b88ec6f0,67ee9e15,d0c14a37,372d9c20,c645c25) -,S(e1b7b953,9d49d0b9,9b90a642,74d2276c,6256f2f6,9cd03006,97ad842f,bffccc19,2b23b96f,51dc6569,8504628b,19e81534,f2acfedb,27f93316,fd0dd8d0,d5f9500f) -,S(404cf0c5,6fbf4233,4bd5f79b,ba97464f,9ce5525f,a56212bf,4bc817c8,af54f911,b5920609,88300588,5c61a6e0,75e3657a,23c04b5,79897c0f,2e22ca64,1f1ef662) -,S(43f1d986,da626bd8,efee817f,a09a3440,e7819aec,17ea971f,43fe2ec9,caae0c1,c5fa5ace,ce891aa,d2811f51,8175179f,3e93f438,2b3ab583,e51a200b,2a74f9ad) -,S(a18845c6,b3209951,16a183b8,1b762112,7bbcaae8,b67ee8fc,d23ecaf6,c5b9c1f,980ed5d9,d7e07e6b,2cfc5350,e818671b,8f54e7f1,5cebbb02,dfcc2951,bbef1f44) -,S(4d9c7eb,af99824,605cc17b,e03c929c,254c38ad,c026d5aa,2a304920,e7ac01ed,c64c5b35,bb0dce53,2273cf00,f3360f74,97065bb9,9fa9b1c9,70d41c19,53e781d3) -,S(e18d22f2,fbc3db09,bcd31783,3e8aa605,55953ef7,4c64814,edaeadc8,97e7c25d,cc258a81,71152072,24f7989d,fcaa8700,f15b8b2,85700b59,53ef2a22,efc7e07e) -,S(160575f9,f220904f,8d2ec9a6,c1417e8,35083aa7,9bc37d5a,3c8bdbe5,2a47879d,1e56b4a6,127e978d,41191c60,ad439fed,2c38704b,309d34ce,d655f93,5279a5e5) -,S(3b651bc7,57b1d626,4d6b7ebd,d3c5355b,4c3c9f6a,a1437e53,f9aa0372,5192d514,977a8774,95990312,ff1d8ec,5dc8a49e,5feb285a,8a1e2e4,19e56186,80231c3f) -,S(9085bdef,56facc02,76025015,498ab286,a9660e96,1fd6bb0c,d9579a8f,16ba532a,fd05d108,a557559c,5e7f791d,90e80e7b,68364c16,8f6b93b8,c55510f1,7ae9fe89) -,S(4224306d,f64a3862,fd33aab8,c1f0ace8,67cf1b25,76e1cc21,fef45448,e40569ec,8740b667,5279bc1d,ce887c2d,c59e42e4,63e72395,ff967249,8bd13d58,f60661bc) -,S(b7376697,4a512e31,a6f806b3,5bc55ee6,e0e2b2c0,ff5a0918,2f83ca35,dc22935c,d350c820,2676fade,ee4152a2,48fd5cbd,890b3e03,9d688462,51c2a082,85420103) -,S(73ba4f8e,d3b5d4d0,a7c505ab,1c1a7486,bb82e068,cba81574,557424da,4d0eb97a,93af3914,552dc360,549b4a2d,863d3f9,3a58ba9b,72541215,adca4bfe,26188271) -,S(285a014e,174724d9,8f0576c4,5694b052,ae93540,6bce1bef,524be03,6fd3d8ea,6fdad1d8,d2ce7757,e6ff5213,f91d4db7,9d406765,968ce8ca,b393e7c8,6a9af7dc) -,S(b0934dd7,27bfb54b,a2a5cea7,c6f8c0ab,84c2fd78,eca0d180,963869de,c28e768f,dcaf0d11,56029f31,4bebbb26,edb09913,484c94f7,d14d71bf,2bc709d8,f0b982c6) -,S(3b627add,8b69a9dc,b751c8bc,cef15d0a,ffcb49cf,357bb65e,c45c8c0f,5b681561,bda1980,9e380b7,2da13364,9d27cff7,693cd2bb,a77215e1,536296fc,dc46d19d) -,S(7e48fdec,1f2289df,a052e3f9,a4766daa,e4593876,5c8aa7c9,a62a369,52cb5ac2,e87af87a,ac116885,66e1e10c,5bedb49d,68449b8e,612939ac,61e384b9,bd8cb5f2) -,S(4031f08a,5de33bba,b6a2c267,feec2e40,d094d890,caa1008b,181ce43e,263ffd9d,cfdc4fd9,9737a5f0,9a789beb,91dfef45,a8f23be3,11b946b5,8a79b7f0,51b0be07) -,S(ba652b7c,61dddbb5,bf6e656f,4d441cc0,ec00a22c,7b900b1d,d5407ebf,931ed764,87fcb392,d1228156,a330b5d8,d3c67e00,1d207095,9a590088,a3b44d07,29556) -,S(fb936572,d1017653,ac7dd95d,2d8c30f3,62c967b9,ba0d3b1b,ffdc1ed0,6590e72d,adfa37af,db6b6a31,a779965,9958be2e,94038246,6b4a4587,b0879882,4836d8ed) -,S(294473cb,5e7c0852,f7c6fdb7,8861129d,b97ff328,19685148,99198870,b03bae7b,bd905536,f991867a,78a09f95,1bd5b4a0,78463e5a,6c767617,246eec38,7d90c86a) -,S(2fc0f44f,73a633fd,91737ced,1683b74c,7687dc8c,6d3a4c09,44a6c873,c5bc574e,29917cee,ffa063f9,4e949991,2ae373eb,ac572f50,9a451184,15e07354,1d22ad1f) -,S(811fb251,882c5a7e,f59d34f2,c8ed8a31,8da210dc,83bb8c40,b9ac0251,116d569e,74df6547,2cb55afa,4ee04ad3,f940de6a,d480e407,5c3cc00,ad291918,d8a0c55d) -,S(45a9e17c,c1d6cf09,1f451894,ad4e7e53,c47996c5,82fdc57b,a9e7e614,b7fc5d07,5169dc4f,2661f5,fb2d1920,89832b7,4e19196d,c37fdbbb,16d1caad,7b069be1) -,S(d577f7fc,45cda7ad,4743d96a,ab5c7bd4,abd06538,b78c0102,645d09ae,b5588e67,55172b71,7ea257df,ced1db61,88c78cea,765e2c2c,30bfd25e,52107128,303be07a) -,S(a6429a95,8098aa6e,39b71e08,d4b0cefe,4fb22d8b,777a59c0,650e11b1,9b06e44f,af494e62,5587055d,cac440f5,786240ab,36ab1825,f2c3a7dc,f6aa64b1,947dd2ed) -,S(f77c304,b89314b4,258b1c80,cf478ee8,50bca37a,63e20679,7396967,a39a743d,c487a176,29d914be,60845213,60f40f19,1c32f414,558e2c72,7e78637f,8dc1c7ee) -,S(41c6f2f6,15981247,71ff0a82,e1ededea,cd76ea2f,fb2f9f5d,ef766165,96d1c988,58a0f544,146c1a07,5ff9ed4f,f9b687c6,3642770e,45dbf1d3,407b52a9,5accb68) -,S(c8724ec8,c13d37af,9eaaacb,35765e3f,7ac2d2d7,1fdb5916,cdf66ed3,2eb968d0,70ecf721,42103e6d,e7d4bbf2,42bd9a6e,6ade66ed,a7862989,5ecd255e,44d81221) -,S(e2888c46,dd58e36,be2204a2,b75fab66,3b139e4a,e070c650,653ba9f3,ff1fbbf2,715910da,e1393b8a,b7d88879,720bd601,bc158498,9522108c,3312b353,2342509e) -,S(f1f4c384,d72d80b8,6b5999c9,aaa66f99,f56cf736,11ea9ec1,c14ac36f,66d834dd,b5543bc2,480142c8,ebb8527a,3c9aa786,2198388a,696b3c44,835e7375,24cc7e3f) -,S(487477f5,832fb7db,768d412,6edd7f5a,17aec3a6,3419de73,f61812b4,31940a5b,90322dde,4203fa98,bc44e3dc,32a6d56a,284f556,36db7c54,c5f78d5e,1b2608a7) -,S(a726963a,583167e2,4b8f957e,b3ee9f5,c55df02,9fe1229b,ff8af037,14ca75af,8fd7a984,d68929c0,81154d15,6b6541ff,4a636925,53a5a32d,99f6516d,c08f7449) -,S(d4c20db4,cf80eb1c,9d93a231,e699a68c,baa763c2,e2013033,8762ac5b,8b99e97c,ba1c77ba,2555a50c,84aa2071,39190a35,f5abc50e,589287a,426c6f9f,6ceca01f) -,S(7cf9c53,89ae702b,bedb5a55,ad8d0f36,5159ba1d,ac56fafa,fa59efe2,3a748168,ece3b324,338c7bbc,a2cec347,c31348ef,489bee0a,6ea4296f,6ec38502,b72336b8) -,S(920108e3,c1ebd4af,3979f9c3,326806f,eec92833,b4dbaf49,6992541b,44b73e55,3e22b133,d8adc483,4f03f348,eba48e65,6cf8f478,524f5395,ba92e200,95f466fc) -,S(1566af8a,98c48762,9b361337,2ad32a53,fc760538,49566a8a,4feb69c4,26479e90,2848c566,4bd72be4,c797db98,62fe1c7b,da5d3ba,eb3f7926,daba8516,da997796) -,S(a4db5e71,2eb8ceb,c7d7a704,12b0a8b1,d2f6d9be,271ef044,c0f76abc,af61723c,663e16e0,75a73ddd,f604bc0a,27a9407b,272f5f2a,f2b9f6a5,6958c8ca,c42e8ca4) -,S(d0c9cf53,8bbdb8f9,625d110,6c79cf1b,33d90e77,60778c13,8493bca7,8d53e5fb,b6ecce0e,8b9fd407,cc0a2125,b8bd30c,9975ad88,7dc1bd9,68379063,8a1d9a60) -,S(765fba92,480f57bd,70596d67,bcf3a389,4a58d514,54e3a04c,e657ce78,ffd8391f,5cb1dbba,1035350e,5a3b552e,3f41ab4c,50879bbd,5f3ae3db,af6ec902,1e18302f) -,S(9f9da9e8,e846702b,4aaa7b9b,68b652f8,9bd3f88e,5af4a503,2c51ee6f,8bfb4a5e,5dbd499d,7ecf17b0,eb17320c,a0688aca,1d8da08d,d2c0684d,edfa2d7f,5696a0f6) -,S(af86c83b,db95894b,72fb1a16,61aef5f0,ad949c9c,b465a5bf,b1192022,13fdd3f4,ec06827d,55410119,603d2b25,cc41c26f,4a7bb9,b1b88e55,123f3c12,d799e117) -,S(fbb48993,2fccbc8d,772b3fc,c80be33b,64c8e3b2,2ccbb09c,d94fa350,fd587e77,f9cdd24,279333da,b3451abd,634075a6,58598ad4,257bbe04,81111b6c,d8c0b858) -,S(40ecb1a3,ad97c2af,62b15eca,e2adc9c0,621f36f8,90a9269b,ae6edc1e,7ed60684,ff9ec194,fa3a617d,920e3e2b,32301fb9,9a41f4b3,ed9845f2,88daa005,3558b32e) -,S(31f892f1,c762b42,fcbd9014,bfe0238f,39873c30,c7d3b691,9736009c,18878f52,d9bd5005,f31f7345,53131066,ef6b92c1,5cd610b8,f7d4fff7,be536734,95718c95) -,S(ba122529,e9f6051e,2d94d150,c5d7739f,921f8193,8cab68f3,1c696fc8,24886c5c,c33c071f,7e9bd539,1b0577d3,37ac9c20,7c02859c,c396bc20,d9c7249a,856b1ed1) -,S(35316412,9a26d311,c993ecbc,5b9a0263,ef45d993,d58158c5,30c215f,2924cf03,86a620d9,521623bb,9ce3e2d9,c5b6385b,f92ef06f,91834e3f,6a9c6d35,7a3a9742) -,S(3024770b,e4134aa6,35ece92c,a4ec7f9c,4a4aa7ac,7851b3eb,f9718a21,52c8e462,1fcfafbd,72147afe,16dc1579,ce7384e4,ab3f8faa,f818d225,bbceb050,ffc8c8ee) -,S(f5ba313d,a40ee86c,5b6dbf16,9941d8e2,533c1ba6,4dd0871a,672d01c8,6bda6564,10a910d,b9697907,c96e95ec,15557649,8f965282,437f58c7,2944bbad,b800647d) -,S(685e17e2,972ccd05,34f7f426,b18c9518,e485a23e,132c18eb,b33b59c5,7264e2f1,96545b38,be84aac1,a77a3f47,51156daf,470fd42d,dea0fa0c,b930144e,b9f291c6) -,S(e01285fd,facc9822,a59e1bca,7e91c07d,fdd481dc,61d268e0,504f65d1,9bf119eb,ae82153a,2479daba,ef83615b,a7202b99,40bf5b5e,41c65063,f77d6e5,9dc39909) -,S(c61e4586,327710ec,784d6720,93201e4,93798a93,7635f220,b5421cb0,55839601,e461fbf5,aa5b64e7,a1e3e016,3ba555ca,5d42fcf1,7433c26d,cdeb8cb2,746c04ea) -,S(1c427acb,4e5890b6,e24d8ca2,513b61d9,3106fc34,90029af3,be87d65f,1fd192d4,1d96e025,1518528b,9bb04fa6,ec3430a1,84935ad5,ee8ae3e9,c9cec0c4,36cf29d0) -,S(5e577bfd,6d51897b,4b6ddb3b,a7d470b8,5a932619,b5982f54,431df6f1,f12fd8e7,c1a17292,9734c19d,3a836e90,8a5a7fd0,123cb044,c7ad1ff9,203d4d79,211c6eb4) -,S(cc78b333,1f968a40,bafaefc8,dfbcadf2,adc6ae76,6d3ea8a6,8173b40a,28237b30,5b7691b2,a5bc068,ff1ef04b,41238cb4,dfc2ce7c,9436f8aa,14eb0a40,45857d42) -,S(3855c437,487b44f2,9e5dc288,faf3ecea,c445372a,95adc16a,b1830a4,ec919fb6,df2e1e9a,48cbfa28,54fbcd5b,308bdbd5,ed1949f5,e1a39519,11c287c8,289359d2) -,S(c05233b4,a83356f,c5ffcf6b,97db3d6c,dc62cb21,b7de7c92,8f158466,b9d16b19,b1bda39,ce78847,3fa0eac6,51e8de54,956616f5,16233275,25ee3bf7,9e54f500) -,S(6c064d3c,f34226a7,d9a00024,5901f355,b736c1e,6561810b,455e7dec,99dfffb,160d9442,d25ec1a1,f80f8fd2,a1c5c42e,aa544477,28d242e9,925824cd,609eb9a7) -,S(9658eb89,70bb1aa5,1b61a93a,de6a7d,b3e20772,4789d009,bf37ba9d,8b714cf2,cd4ba4af,f7da8f8b,7821a903,f40d89e0,96be8949,997d5ff7,a58301ea,92c51cc2) -,S(6e023910,a5546f70,91f2b0c4,c3f996f7,5cf1f969,a71c31b8,7a3e7ea6,4bb4f0c8,f6ed65d7,90ec734d,d9ed8cfc,7d8921b8,7faa9b36,651c3589,99b9addb,34c459c5) -,S(3a35ac98,e9700499,f903528e,330537f,9262901b,d60c7a14,1e68f899,54c7ff6e,913d9516,da631c30,5394ac0c,9eda3824,1f247ff8,a7644eb6,c4d38da1,972069ed) -,S(d089fa51,15dfaa45,a8b6def3,b1948be,2317c66f,249763db,7350e57,76af212,4e6ae973,f326fac4,77a5120c,f3ffa113,a18e5dac,4a190f6a,b12fdc83,18a6da9c) -,S(e733c52f,2aa62ab4,748ea0f2,33d9531c,5b9cd9d5,f790b6ab,45bb2c2,d8cf2ef,701155c9,3c677293,acb23ab2,8d7ff753,36ac4885,70c52d89,fb80ddf1,d582a291) -,S(4b6f7b7d,c006684f,e64aa6f2,42babf86,1eb4770b,b8195b9b,e8caf763,e7f14c7a,6c58b780,ac757b33,c1805d8,a53a04c9,7bfaea05,d8f21d5a,2b0645eb,2194e00d) -,S(1b520402,cd1fac0a,c4d7aeb,8c552e73,44ff51c2,3b4778b4,81126e5f,e267f79d,8ee0d00,56649304,a0c4ee94,39add4d8,30b252f1,93d93c1,9e8ec375,37db1a39) -,S(8936e6d5,d7f1ed85,fc2da4c6,38a885e6,3400cc3f,43d864f5,bf9af2be,b97139b1,29812a20,b4b932a3,770cdc8a,6fd32625,8879f217,a5bd7c47,78d2b041,829b402b) -,S(6808ae7f,4813554d,aa36c043,a55d9171,aebd396f,5ba1a1ee,c4f11045,c96b518f,6afcae6e,88728ddc,578e85fd,5f41575c,f581b983,7c749c22,31b993a5,9c425810) -,S(586c6694,44c73f66,1211bba7,601d8009,93e23293,55a9b10f,2367924a,35a2cd1c,74b0901f,f6eba3cb,408f5507,d37cb7c7,873537dd,ef0671c8,862012ac,fe5416c7) -,S(789c825d,deadf1e0,4c788453,e918541e,b183aa5,99ccc66b,7897be8,1ff89e11,8106aa6f,641bb13c,6be7480b,89f98a9b,e40cc357,ffe9903c,b8f78938,e46cb5ab) -,S(d7ab80bb,fd26faa6,620d0ddf,97f64bca,e520426e,e1d8e076,acd7cfbe,a9419797,26af9f72,a6d1b103,aef4a85f,5139d14e,6e50a58b,9f32eefb,c7184537,90c5a823) -,S(18f712d4,4daf1ab8,4612b311,b1ebc418,bddf0f33,ca02b315,4c256d2f,36f67f7f,c40b1950,f92fd4ce,edb3c3f4,34ff7bf8,6b06d8d3,215d3ee9,f2d9bda6,77d25bc) -,S(8873276d,9f6d188f,78e2a7cb,f998bcc6,fc399d32,21de85b3,eb9e6ea6,c7e5a06e,297e8137,8ee9b9e8,ee820a3a,7e566178,dac97743,c04b6b4e,54a7081,e7c9e1a6) -,S(101b8101,5bd217eb,c08f57cd,fdf431cc,30fadd66,4df79157,1452ca66,c688e0ad,fa6c1b2f,ad203831,185816d4,a8f8dc9,4c7542b4,6c94dab3,39b73718,5d179e6a) -,S(77b3c157,76c31460,11e520a8,cb2071fb,abe3b3ca,2984bb6c,d81d4c53,7f42dd57,8d0bceb1,dab601b7,1c084c9b,443ef5ac,40cce5d,14f0c244,92589905,fc4a645a) -,S(151f2d52,56ac60b6,ff7aca33,8ba66f12,fbe2c189,33c805d3,ecf6a6a0,fddaec7a,d2aacd77,10cd4bf9,917038d6,49e94235,c4833c88,9cd57ea6,74ece9f0,764f62d6) -,S(dd75cf27,f41e417b,46338dbe,24b46df8,9508811c,111bd1a2,29a3809,171d32c7,e328b855,a3389b80,4ab03c33,cc91d86c,ee22170c,d8fb53dd,46c32224,19b67be5) -,S(faa1feb,bdd1d9c4,9de366ab,3f661b1e,6a3f6b76,335b428a,494d7eee,791d7a83,df361d4f,8fce02ab,8c248ee5,61e46555,948bb29d,81a569c4,13b5713d,b825d572) -,S(3cc10dbe,5bc2bb31,fddee65b,66789594,a4cadadf,8c6a7545,671dafed,4d8f8be5,802d45ef,8c66ad6f,e692a3a,9d42c974,7101120a,ea42510d,bc08e657,7039c2df) -,S(9544e725,325dec1c,914dee7f,752802e1,856cc485,35e3a1e,af576bec,a7b93ba2,cec7dba6,81513c04,ebf39b03,717338cc,aaf137dd,e5087686,aad83115,deeeeb49) -,S(94a0fbdc,d5d06236,7b17ff8b,4dcdf6c1,54eec66e,2779deac,38be37c,9f83a964,f25f34fd,5ef06c81,b7223e16,9a42e2e3,fea74213,5a2a30e5,76f29ef4,cfefe82a) -,S(989e29b2,c3fc7e2f,695fbd4b,f217ba43,14f67c3b,9f77633,100e84b3,c6b579c7,608a6d28,cd00297,2b4f3e9,917daaf9,ed003a43,1c22771,17250efd,b621c888) -,S(c38c5fc4,4295a59d,3b0e979b,5934ac2,49b4bd5c,e94097f1,c81064bf,73494a5,16240bf6,d354b36a,648e471a,e0ebc167,1d1dbc71,7cbeeecb,7600462d,61d1e2fb) -,S(de9cf667,35c4046c,58b41d8c,5c658efa,7dc656b,7ad877e1,546c138f,fa7a63b,2fc2824f,ba9162e3,e2372927,5448010b,ecc19de7,d9b94cb7,57586de3,506639ac) -,S(24cfd37,e56708b5,79d84b3,88c33c9f,f1dd9e08,4675a3c4,c8c440c0,f6c06522,1cbcc8ea,9820157,b4b4d289,55ac8672,1aee676a,cdb7df00,7383ac79,c42af897) -,S(9d6e3108,6ad8b9b6,2f4414a9,5e091e9d,2b275d8f,62641ed7,26421639,e87cc121,b924700a,6792a67d,4dab59ad,5a743cf0,43c46ab4,de751bca,757979b6,ead3abe0) -,S(52a89ae,28b28395,739c21e5,38ed38df,74aea22d,d2765d38,673be080,8609354d,c183ed57,9b65830b,d37cccd2,76b2f61,469b06d5,987b5708,89c5b1e,d8334e51) -,S(2ffd3272,491d1807,243f5d31,d727caf5,cda3bf8c,2c172550,46bd3420,da27571d,812e8fbd,6f38b334,a31e48be,6deaef58,599934b5,d3419d52,131cc9a6,535b6ad5) -,S(5d60c609,4269a43a,35e51b66,db193b16,65df689c,270662f2,eba959c5,9c973fca,f591324f,d1afd619,2b31bb7e,3f40cd40,6d3b9285,969c448a,3aff1f48,850efadc) -,S(23e0c40a,bfe53353,f4426340,e1c1b560,4c86daf9,85784d0a,e6da6b4b,3d12ff75,e90844b5,fc86092a,91baf68,280ca144,f19d5a79,9bacf827,f9921511,28191d9d) -,S(945818ab,5d4a1c12,ca6f20d7,7f37da80,50e67d79,30bd2bb1,155885ce,7c6094f6,b5f2c1d0,e2f9ae6d,aa669c96,9ededb60,32ca8163,fafcbb6f,9a11cd56,4a695e03) -,S(d1f4db7d,2586bf6a,187a469c,a0cd7bcd,5043be5d,6206d24b,c41ecd8f,d8724c8c,64054f82,77c4774b,bd480ce9,b2929c66,b1525eab,1c6f365,a1ca5ace,12206839) -,S(4f5c4d4f,24586e9c,1a85f2d5,b42a3d11,158b4f2a,5cf75e18,60f7f4ec,ec14a18d,57576e71,6d547960,6953be2b,e7ffbec2,1e48bb9e,970fb350,986b4a31,b0efdbe5) -,S(c13b605b,dcb31443,d8a3cf5c,5e4f903d,3f8edfc5,1e9a118,c3840cb9,4998150a,8dce2eaf,99f1fbf5,2e62a8ea,948b01c0,6c368e49,f41922b5,2f603cb2,16cb8435) -,S(1937b32a,b66f254e,4964a5b5,a1ceeb5b,a3df2466,e2669753,39174cd0,2429cbb6,9712b0a0,6f1b075c,bbceabb0,53fffb1b,181e079,813e022b,b5701738,ef2e385) -,S(e4a5333f,2f1772f3,84ef386,c3be1f58,d757bbdb,7ad2c4d7,47e61b07,419ba2e4,e84f7da7,2ec2e4b9,389b717,8bc15642,132571cc,9bc14c7c,5af14a7a,cb6b6f56) -,S(2f8a38b0,a3f42a8c,5080a0cf,5cc1085d,d57a8341,ae154dcf,fc7fdb4b,5606cca6,8764c6a5,2c301db6,56408d9c,4eed6294,2fa2a72e,1b1264f1,134f38c6,8e4681c1) -,S(3d2bdc2,c51c2d77,b6c585b6,3ceab5fe,acd14599,b841870b,8735712a,81a55ff7,33f749ad,bbe263df,a99a808f,f0476e44,92246036,a3e8b5e9,496b8dcd,b6d3e9e0) -,S(fc87f808,d6764ce3,376b9acf,62bfa3e2,1ecec215,22dbdb3e,6e5f3cc1,efab7d3a,ce75eb03,c1f4f937,70815dd8,750a4ac1,c0343024,ce1bc581,717cb971,2835176a) -,S(7f81b85c,62dee11e,be8885dc,cc98485,32354952,1c7e6cb4,374270bf,5b1e68d5,b7adef7d,6a84db61,c15ba062,d96cf739,1750aa4a,ed5c97f3,ad70d2a7,6a9c4558) -,S(d618d43f,7afd3ae5,e8dd8f47,f62ef91e,33cc8f89,3c21688c,8268b903,e1fd5557,6180817b,c8ab9b0,82b21267,9900c7e4,42ce9e8d,fc8c3fb4,fc5bcaa6,e0cd34b8) -,S(ba5a4c4f,f2379b06,daff540f,c8383b9b,694430bc,df76c931,ccf94cb,896e4940,3a221d1a,b138e6f,4ed309b2,4f2e9333,25299de5,534a528d,b91075a8,fd07b1f2) -,S(c69189b6,bee3746,88359141,5b35bac3,80136395,c83098ab,cec29fa3,18cfdf56,a185dbc2,b862da3a,cdc232fa,7e3407b1,9795e61e,29b7a79c,5828bd49,d739268c) -,S(51f67d44,32fb401,ab863423,b99d403a,70dffd86,87e5ad71,bcd3732c,1cefae12,88b17485,a2c404a3,2bcae68a,3cbf2166,403e23f,8a64df5c,a8eb2d94,61e10e59) -,S(cdacfe09,e5585f8d,4346fb69,a94b8b65,6001e117,ed3cca36,fa8bee6d,eb7c4bd5,ddf1bc5a,993131d0,15812176,206699d7,af5fc403,59455ece,fdb84492,6e028542) -,S(8129e771,e1fce476,9c701d70,cce90888,481eaaa1,d1661be3,19f33c93,8bf0e769,3eb5713d,a864bc56,39ed8b6f,974966af,8a4db189,b5446d70,d40a816,f045c6e2) -,S(b97062ef,6d415bc0,f302fc0f,8aa730d4,f39c14aa,f82889ad,a68132bf,5abce3ab,8ad70688,cd76c93c,fd8dfdd3,8522247c,6644c9e5,51116829,490f313,d53db3a6) -,S(19c3c98b,4e811b5f,ea5d6af8,c4e86be6,50de67ec,5154bca4,22a6a14f,4f0bd913,bc523f96,48bdc993,30e1b5c7,385097cb,c18b9d5e,924767bd,d5d746fa,a190a109) -,S(b9ef34c7,3616ee74,b1ebe43f,889118e2,ad7697b,efe63559,67a9b3c2,b5b42b9c,12f1cddd,d55b1ac1,b89be271,5e623952,e8dc05aa,3570e254,3b70ea68,5b661bea) -,S(7718e34f,58e2cdb5,80f9c39a,96d84dc7,59dd2a3e,bdebaca8,6e8edb97,f503c34a,a6d105fb,dc0841b8,12dcd8f9,6c4bd17d,cf5e3728,8e0e3093,13567b10,3e96df7) -,S(dab3884b,8e6de737,63bba89b,8d35a369,e259c1b1,8afb6ed6,21fcc871,c77e8dba,f44b6f29,c59a2d42,2babd4b5,edb4a009,c9316e09,2aef953e,e503a278,14a11577) -,S(cb3d0e10,1139782d,e5e6a897,8b5be6df,a6736751,e847ca18,76aedab1,e67f4366,27fe888d,d227943e,67969b33,be48f1d9,572aff67,69c150cf,189f9709,bd57d3ea) -,S(eb1b1ff8,55619d41,8d193db,bf62b4b7,656ea564,6ea2e79f,cca7fb3b,e8c3c6a0,c27fa0c7,5b73d5c1,d7113741,40384565,d36ae93a,49b327a5,cedd03c9,62282ea4) -,S(5d5079e6,bc40f11,f75a1117,3ab6bdc,bee8f9f3,d2e57aeb,58709786,1c39c5dd,14ae112b,a40db9d5,dd65829b,4be7bdf9,4d8435de,1872bab,80581221,446e46d0) -,S(1060ef7,6beb6af0,6d28acd2,6b214bb1,b708098d,e0300502,384fcc0a,a1a7b38e,ce40f39f,f6c6c642,9585464d,aa2183d7,34252c05,5207e2e2,75d0ec48,c3bdf9a3) -,S(9651c463,c001f731,8947c271,ac274529,e7bcc894,70d63e1a,fd723873,aa170695,4e362e7f,e8ff06da,73d6d17f,e8b63c99,3b16ba7a,5a9b154d,21837fb0,e654eaf7) -,S(5c422b76,592821b4,2f6822cd,cb428b19,895cda4c,d224400e,e0928f27,1f363dcc,2fdb4f4f,9e4c77ca,3448258f,f6c07f5,4cb6b4d8,15281484,44e5fcf6,492b9400) -,S(db147d2b,5d98250d,73a3ce51,9452cc4a,ab3868a6,cd4f43d2,b7224d93,a9faba2c,73254380,ad3c6acd,fa343227,a7299684,9fdebffe,64c4925,8a391a7a,50ed0de) -,S(9a6763a0,f97abfd1,65223767,8881e899,e1beca26,ed84d384,a41d16cb,e5454b4c,bb51407d,b6aa5817,32f1a3d5,51082908,e7952f75,92c8bcb2,737a01d3,3890306a) -,S(36fe7933,e9108af4,f4e5c889,ef94f584,7b45a9e,8c520000,7db6a00,e5daea8,d024a5ba,ecdd5a21,c8c3a0f4,a71e15c3,1943c7bb,66b459e2,7fc85bb4,25227ee5) -,S(40dae663,f04f7e68,ce782fb,87529681,44c749ea,5b7386af,c445568a,3bc784e7,49a463fd,ac6bcdd0,2458c85,423cf252,cea2ab47,44b16bb9,47811176,5755050b) -,S(ba1616d,c8fff3b0,8e8c6d10,b15afd9d,da55faba,79fa8a75,42c5c9cb,adc5b8d1,ef096c42,a6233c66,1965a3ac,eca095b2,7710455e,5f0e1019,7641ab25,b0a786ff) -,S(30486f67,23a54952,4d68c948,dbc71273,d69b4a05,5fb9e7d,a702d027,619c4a66,38ca4d4d,279ec9c0,85ea6369,5470a4b9,fd6acc6d,9a049ab6,5743ecba,c2444c76) -,S(1b83ee94,95ead1d5,80f67174,dec2a026,d6accd93,9a89d970,90f25bc8,d9e6932a,196d448,fb5e4851,e1b73d6d,a2e7d0eb,3d263034,9c2b3e0e,34584bc1,d6e20196) -,S(4ea9dc2e,edfa5a11,2fa76671,5c1579d9,328b6132,14ee64f,2e30f10c,b7517396,7414efc9,6ef83e29,5883f0b1,4019b41c,d4a192d9,d06cac9c,21e8f0f5,b06e50c2) -,S(4166c19d,bee9ad08,83b217aa,3b657436,87677792,d5cb9b31,1a097fcd,2eb033da,62c5065c,5fae6aa6,932b4d29,ab375ac6,b80e113f,d38d81f8,abc236eb,7eed541c) -,S(b17567eb,b112f54a,69c511a8,7d3d2f96,bbbc6686,af8e3f31,a2bbe0a,85a74899,f6676341,3788be54,ae3fc693,4b8936df,a6936721,c671cbb1,bdbfd72d,4c9f52c2) -,S(cd2b6515,2ab97f34,89d81fd,f3513131,a6df0685,5022102,12c2b8a9,be8095a5,cfe7952f,9ca41935,15ee40c7,2d44d023,22afff84,b8700bb4,5f492e31,e78f6a53) -,S(375603c4,9f33140a,3241a72,907ac0c7,2086c979,3aeaf74a,44732097,3618229f,7bb740f6,6322a773,e11ddb46,300975db,de08ba13,84480699,6681637b,eb85e837) -,S(102067d4,390a3dd9,6d83c176,f341dde9,7e10955d,2e001632,978f202e,efbb7432,7cf6cfd5,4d28ccc3,a7019f11,b6ba9df6,1d8b7eef,7e70722d,afa81a2f,839ba83e) -,S(47617e73,e3fbc53b,a703042c,f8b48fad,374ef42f,e8c2dd54,4fb7625c,de63081d,1fa4f423,c92a95b,b2c40f07,f43caaff,50cbae67,87c3e2a0,e4782f39,c1d439e8) -,S(2c431baf,57f75062,9f57aac0,8e28a060,46b814bd,318d74ca,82e1174e,f880f84,ddb9e7bc,68574b32,c1004108,9853f41e,62755a52,ac58badb,b8ee58c6,f209de50) -,S(91963643,8143b6e4,19b86b1f,79b708ab,3f4df44b,d774b41,338570dd,8343d599,9034ee17,7171a0d2,9fb91d68,26b87bbc,21be334,90f44049,69622a8b,76312f0d) -,S(bf28c201,af656c7b,838d42db,95683b06,2871859,2b016ddd,a4a4f7f7,c4b7754e,bbd4f04,dda510d2,a8a66c2f,46ab0681,ce6ffb5a,ac320e20,c50b6df3,a345d109) -,S(fcac7386,21825f4,4e1d531b,f598e40b,1aa4262c,a5aeb5a1,babb4f35,9518b137,3b196b7a,957bbea1,f3f2d1e4,1ba37eef,7dcca7fe,87e7c593,6ffff685,52e67b64) -,S(9cfea1df,caaee192,141f0278,e467f809,8ad89cc9,b47ed982,3029c1dd,726e9331,72d81e4e,7f30ee05,8fd0b646,95086e30,96a071c1,5b75df47,b10146b,18db211d) -,S(548d3f42,123553c7,965c7f21,f2802c30,455c5151,99b98e20,1e966f34,6a1334da,612ea25,cebb03d2,89538eeb,15b94686,8c0afb1,311278a,42694a0e,956418ae) -,S(e5be619a,ccf84c26,9b5c545,e8c4990e,ebd46756,c628de22,a6c8bdd6,74295bc0,640864a5,7d841af7,ad83aa74,fa858b91,89e246cf,9b361837,a742e2a0,71b08bf3) -,S(b560933e,3400ed4a,eea8f733,d2368c8f,a260460d,f734e209,e194e9ae,a1ac668f,5438f93d,31337853,9feab182,6cf17bbc,ac0975f4,de29a886,1b1c0c02,2c5f9da3) -,S(21dd9a97,baca3e79,77ecf7d,d74433fd,dedf2d96,8c3153c0,2c652aa2,1ccf60b1,de6e60e0,e048b0b7,b699bbd7,cda0c0c9,b851c4cd,34f4b8d9,17c07cd0,2684797e) -,S(5cfa560c,6d39439b,4c9b0a52,f9bda301,2f147874,48c9ff37,bcaf2900,fd934bbd,c7927a63,cc1959b,f3556998,ce936f29,29d5a5d3,3f0dda32,35affab9,a5b11b06) -,S(4a3b95bb,5adcd41,5036204b,394fcc95,6377afe7,b4902f49,461c4b6,866d4fc6,d59e3ee2,f1bd1e4c,c089179a,4db9387d,8d6be47b,df708023,2a0d00af,a8e84f2f) -,S(cc49a313,b4c69c9,13c06b7b,add06f17,404edb0a,dcdb3d4a,81c4b765,35f4671f,4bd722ec,c35e525e,af36c194,3d375592,ba483715,2c7a91b2,4dd57a89,687bc278) -,S(9d75085a,7426a69d,9ccf4f90,d8b4ee0,e07fdac0,18df3d37,40b264cc,d4146d98,5991253,de04b32d,4772f44,de49467d,ce174ae9,3f941ae6,a4f6e3c2,2cc4b0a9) -,S(dfd064df,737bdadd,2eb12cf5,d9f1e192,caa87c0e,fad20d18,b95b0d06,83210fb8,519f883d,a5bf8d33,50b1d2b,89012fd5,9f317299,3eae1226,13d81b92,9103805a) -,S(2b50a35c,d2356c35,d609013e,a66318bc,1cf20582,685c12e3,bf618102,807eaf9a,7d0b51d,303aeefe,b81f5a77,d9b5829e,fdf4241e,435380f6,ce74abab,1dc76335) -,S(e26e8f4b,2cf175e7,c76e2a59,459cd45e,f3202f3,3027f0c3,70481fa8,685abbc7,4c82e7ba,aa0d5161,53076702,997c34dd,716e5fe2,460eac0f,194f72fc,3ac2013a) -,S(5903db7d,54f4d857,6a584057,ce78dc07,1fd90e51,f825c959,b46d3483,5d0f87fb,c55e2fd3,e9ce119e,47c00332,9d18d6f7,febf9440,a18de0f3,81608011,1e9e99c8) -,S(4bbb0ecd,342a82d,c8b881e9,635241b6,1040e6ee,28b98204,fde953d4,4d25e9c1,12eb090,f3445b7,52abee8d,604e8784,82e97e9,b44d2335,8211a8c8,2cb0ef04) -,S(4a2455a,ae87bf97,c6e6eb38,fd3279e2,7029967d,41b9575b,647550f9,4bc4e8d2,5a340ac4,ffe3bee6,2d52bea1,e276178f,9af3422,f9c61c47,4a595550,73936074) -,S(f086d68d,c8ca19aa,54c329c4,c07b530f,94470abd,dce244ad,1decaf87,53477623,911c49d3,84a16af1,65be4161,cc4869ab,4d9e8ba2,808afd80,20d30971,b4bdbd08) -,S(4f1b177e,83b76c4e,24a53f91,2095f1b5,d4b7cdf7,29788cb4,c989f921,b7ba856c,a5568c4e,b060909a,fc3dc2ff,5bb9534b,99debb69,dc0b811,e1044705,7d80eaf2) -,S(eba87899,29a7e45a,23d2fcbc,884778d,c4fb5ae7,fa67954c,76534303,97db5823,e6f8c729,b3570917,9fc46b4,7f03af9e,801b26a6,1724aafe,e730217a,2dcbf68f) -,S(df117b13,34c9a5a7,92d58084,4444559f,130ee539,89cc6e7d,87723b63,a82282c2,dd87ca57,8eea3c51,2aec5492,ea55111c,1a2fc55d,4e2335a8,c9be5641,516f7120) -,S(d775543b,3e68ab88,36eaa1b,df5f6a06,1f5768e4,baa01a68,621321c6,e6ee82c5,70221b05,47c97398,3cee7a26,c4197f9c,27a2bf46,10506e18,493a9ee,1881436e) -,S(a7f10dd5,5a231ae5,abc5c611,68cd58ca,5e006f7f,fdf064c7,1482febf,4578515d,492a33a7,b66b9694,e225eb38,d1d99399,b2c24af2,d69c31e,b4797a9e,703c13b0) -,S(c79545ef,3119abd9,11336c86,c6b74846,801c6b3,812da05b,5d36e9c,620120ec,24c8fcdb,95b6eae4,51473f8e,f7dea06c,738a33c4,f1214382,bd7204dd,d3c28718) -,S(98bab5e,744f888f,5f843ba2,9e2104a3,afa14dd6,6a2206ec,8e783e0c,52c2cb11,83b5699f,e5e87ed8,c51d929b,8146bcd6,a7abaed4,636afcbe,b2c30d2,bcb94df6) -,S(6dce2828,7b6fa44a,c8213053,d39dfff5,60d84a84,ac264110,547752ef,dcac586e,1e1eb62a,b9d60cc4,5ab2fa8d,d065d1a4,c79be399,53578a5c,adcfc629,e237ed66) -,S(e386a59,287a73c9,306b091b,5b24ad8f,db06a9dd,8f6f0c1,b7fb0ace,623dfa83,4a7e73da,663b64a5,e624ce89,9e16fcd5,c0d3b221,42284ed6,852960a9,d05b34e6) -,S(8fdff782,e62fbe31,98c283fc,9b9543ac,cea0a318,2626d180,4beaa27,ea4fe4d5,fef8f471,9fe0d95b,673ed650,8107e887,a4f5301f,4317c708,c5222d2a,ac086675) -,S(4c9093ae,7842b148,1bbb8b8,4ea564e9,36ed1cc4,35c89089,a10e0442,292eaa37,2d683334,93d245fa,e5ac0903,fe9356f7,8642362b,f85a7426,ea2950a0,a65298dd) -,S(cc0634c5,5c5c52a9,d92b80f9,be072a35,56318c6,fd76cf2f,e866d5ba,33103a1b,750b7d41,b13cb69e,6d236eb0,87fc8600,4004aa77,1b699e88,7e8f0b08,d07f0b32) -,S(9749a673,41fa7ac5,8bd33f5f,9cca4ad9,1d53c7ec,cff76656,9a56f71e,3b918255,b685f1c1,9dc7d6,7692a2aa,fe37d9da,5e68fd69,cfa58d87,ec6ced8,68916068) -,S(b04abcef,b57862f2,5a57fdc,b7da0b1b,a25bd253,72bd91bc,9e0377b4,697d8e75,50479a64,66ad4be3,489b5869,d8b9bbe,62dcb8af,da8e7d42,78b5014a,19e168f6) -,S(d11f7de8,5481fbed,f1a3b395,785f00d6,295059b7,c8049768,22624e85,45c78902,1d163368,be0c1290,1a7369d8,11266982,b48928cb,448039c3,17333658,6f5c3416) -,S(a21c65f4,65c4c7a4,93225af,73b63cb2,fd615160,b29b2b90,970b880b,5756fd4b,69a26b89,394de60e,7dde3476,7048a295,57f1e3e2,5f7a586c,7666aa30,9345ecfe) -,S(53c626fb,b080360e,9243d399,9a58ced0,36ccda8b,186c76a4,fdeefee1,6a497a1f,ad926008,62a7ff1e,519106fb,933616a8,8264d7a,c40476bb,eda7e1b7,742ac9b7) -,S(cf67b587,1b2a3ad8,d0364fcc,8741f10a,11d96933,11b72870,60116c4e,74e6ff0e,2c963b7c,10ccd74e,f68ac068,cce1e30a,7be6537f,259abcae,6d36d29d,22b68422) -,S(50216d8,8cc8700,29da89a4,b34cde0d,36428829,de9f58d7,31ecd6a6,c90b4bc7,920c1df0,96bc4891,8defce32,2a512d5a,36f65d7e,65525e0c,123d9fa7,49e38b21) -,S(1d845594,f4686fbb,7b0cc62d,af790aff,3d6000bd,e26ec1a2,67766c3d,93d1aef3,eae11ba6,bd9dda02,ef134035,1847dc6c,92450b36,cd6a9734,25c09f9f,3134d260) -,S(11ad4f50,b6c5b97d,767d590,859e2ab5,2e7750a5,6f7e70c3,d5c52bb7,9e4785e1,2c2bba36,8725d9c5,2152496,f14cfa71,1826e846,fbf7e7ac,4e263db5,a8023b94) -,S(3568d27c,d72373e1,29a4a519,86082a1f,f76ee425,969d6e3d,12b242b0,bd49388c,e36dfa9,6d094047,16e35668,10a8e57,8eff108d,839cf3da,f04c76d5,8754fdb3) -,S(3772ab35,45e09d0c,5d2abb91,97007742,46310f72,bdc0b8ab,afaa2c17,f17801d7,25229a8c,eae0c746,2d7a50cd,a8b012e0,775693af,8edb7260,5340042,a78884e) -,S(8151b24f,72c4701a,e4624779,c8b93ad2,44f3b299,d1ee131f,a13054e5,c29274f2,58938307,25ffd619,de73fca0,50c28d77,73420724,4d2e4c99,86ed5512,b8bb6429) -,S(46a4855a,d4101f8c,60c59705,e537080,1b57a81d,9227f4c8,69234946,5d539c9a,8fa66dcf,21117195,e2c117ae,e2f20bb,9517ad24,5fea8864,beed3e68,89e36b59) -,S(b81bd54,3e654f3d,eec15001,c38bd2a4,efa7c45f,4ece2d4f,fd893c6,15803d16,15c3f7aa,31299a76,34431622,8f93b6a3,2b3947fe,5a894c4a,75d2ba01,4e9d3e75) -,S(3e169a1c,f2a0324d,2478c054,94d58801,423f10f2,4cfc9fab,a5cd5cad,12e7706,20405bdd,d814ac7c,53469075,a700b4bf,4d454b,fca920f9,86923562,19389135) -,S(74283e4a,b161b33f,f67a1b8,cde619bf,557f39b8,5443efdf,534bdd2d,4da65956,22296be2,89785c04,6773ad2b,c881744d,380c1717,1c77b159,bfee3689,d0b3df3a) -,S(62715786,cb76bc9f,b65da0a2,3b7954e6,1a617fb4,de828092,bde3da39,ea6b756e,3c27bbe3,8829a150,3b563337,bf995110,eec54d58,21e1f17d,34a5fd90,52c2db32) -,S(96200105,db23b893,84336bc9,d5596740,2c93aee2,ca35df73,9c55a000,6f7c8aae,3192968d,400a2604,c80307c5,d9865f49,ea41cdd8,e3fd3b19,a2bdfa17,84a6ba26) -,S(bd477798,bd2691b0,8cc52fb5,cbf8b2c5,31787535,541b5c31,3aad9696,b71d13fb,be2b51c9,a4ab0033,c21dae50,c4e7b2b,51978b39,4a66d50b,6be7e140,abddfc3b) -,S(fa149388,e46ff849,bb5490e8,3aac6788,70da101a,f52dab05,9039c305,475289e7,8455577f,a8d85674,3b32080a,dcd26a1e,c75af3d1,c184d5e3,7f22030b,8867b2a7) -,S(4228db83,af1ffb1,d4bbfae7,3781a70a,8ab50d3c,47200e86,ff436ae0,3391ba90,45db1d0a,b0e6f0a1,801560b6,419bd2e3,2413ddc9,4b4ad637,d4071d8c,b7a270a7) -,S(a97ab279,fe0df5a0,3d494c02,eb69c686,1dc3a39a,fca2bd49,f4161ff3,817c85c,5006c8bf,f128de17,3d72f99f,7cd6deec,5d4b7441,6b1ca290,e535c8d,c59bec7d) -,S(c0d46c57,6bdcc661,4e1a3a1c,c19fba37,9f27dc45,5135eb63,f8d44666,904c668f,396b60a3,b28b250,2c97d7cc,f93c7609,3d19172f,47fffa71,f190936d,cb215f58) -,S(73c5d7e0,4599fa7d,e09b8c2c,25c5bca2,b7ae4c6,e1b88e63,6de3363f,b1a8dbbd,1d9ed08d,558bd642,9e986b0,c431d67,9229adf,6fa8dea3,faf17da2,747bc617) -,S(370481d,a2ef4843,8d897c6e,f1a01750,b4788c65,62ad3ab7,bbf3c89e,e24827a7,a88b3876,c2051901,1d84acc3,3000f0f1,ccf794b4,5385aaaa,190e435c,760fa7b1) -,S(2dcbe303,3006f0a4,99dbb7d8,d34790be,f2b68cbf,649b9d54,eda8819d,637807ec,b82b46e3,c7ab329e,b915de2d,f3fa28d6,92cf43d,584f9bda,5d6f58f7,1a90c1e1) -,S(f45f3ca9,16db45c5,de35d957,c24f7a59,44052b64,f8f423c9,8a442f6,17bb4b7,79ddf02f,b3154d6c,da1d6a79,5c64de61,5b4a0ff7,810bbfc1,dad68e60,229b5a96) -,S(500caa8b,cad0567a,465c99bc,c4802553,ee17346b,e3a9ae93,4fe7e95d,e787605e,40847ed0,75dfc8d6,ae19dccf,73ddd256,4e1beea4,7f822a58,f0570c62,f238370a) -,S(30562986,a23962c5,5b746191,e23b893b,7bcd8b87,6fa85557,c525eec4,d64c3aff,2d5abe,41c45383,1b60c034,7bb55464,e19d8d98,8a5d5fe9,37337507,80577a53) -,S(f687d51a,32526b72,9ed3f690,be1e6205,ec72382b,6a30478f,63a18e0e,b48e422e,efce1b35,19c94f7a,fc54da2e,d36b15bc,f197e2ce,a0c2d680,211e12ab,7d515704) -,S(104a63f0,d385351c,c9ce207e,500ae7eb,22199ea7,dea65018,472884cf,a1ca505d,69c21887,50b20b3c,5af1600a,a2a2edc,a6de0be9,33d2e67c,e05ac4a8,30239cc5) -,S(50966099,4b7b8ca1,abf963e2,ff4d295a,eb3d59bd,43029c03,5e6ac9a3,ea80fc6e,d48589cd,40d019b1,81211674,854aea3e,56be56a7,bc8ae519,72963adf,327287b1) -,S(3106d6e7,94e5e135,1d788e85,eb0f2c7c,7ac22e9f,d1c86a0d,d22cf88f,54513c95,c05e593c,4568cc2,992849d8,4006ae18,4ad2888c,82ce8dfa,dbf984bd,2fa2bca0) -,S(4c967d1c,9977bdce,84f76ac7,13b9e5cf,d1081b43,de681235,e7914f6e,2059fdce,866470b2,a3e99b74,15c2cb09,83a5c7dc,fcc10d02,a28e90ee,206be515,e88968cd) -,S(96319099,ae8d7741,1d8bbb7f,bf58f62d,b4027b02,ff5e32b2,e4aff910,3a781a52,6c110074,daf2849,a3b148f8,dbba2f0b,d776eb4d,b787ced4,22edc5f5,67947389) -,S(7c93bb23,87a36cea,9dd7406d,95af56f2,b972242b,759728b3,bdf30fa3,58247ee7,21e4de98,33487c86,6da01e16,895a0e24,17cb34f6,e3d64e01,8f7c4d99,9e989942) -,S(c65e4a03,88de1618,6d9db143,387a3229,c764dabb,7c6ddcdd,c3ba9195,7f1e074,d586d143,8005b28,cea25a45,7c45c1fa,2137bc2,fd78417b,daa499bb,cfca658b) -,S(d895a924,90c28692,bcda380c,71d8d1b8,381b1fb1,a8108f35,4d9a17d8,64d674d5,d30bda25,a63013f,79ef5728,dbbcd259,c7cf2ba2,b00af73d,9804f758,7fde17f5) -,S(90467c3a,5b36b9bb,faffa164,63d1f70,c892e23a,3c7f1132,27bff1e1,5fdef988,4ec70191,40247d9b,3cfccb41,ba22ad76,20522577,1e33d568,946c8081,ea9b15a7) -,S(5cd03d63,d0e025a,7af268f7,8f53efc7,b4d38e5d,58da5981,abcad74,3e294c7e,c3729f6e,5517d41c,ab1510cf,ee4e0e48,f168e043,34dd8781,1a10b70f,b42dfb3e) -,S(5130c49c,652bc5ce,a3dd7629,bf362294,8bf69c02,f9806988,fc700a25,c7e964b,7e46e219,4bc9dbd3,99f98c7,b7a44313,a027ef23,1abe336b,7381c215,6f2cf563) -,S(95899c2a,33b8d4e9,13947306,6b924812,261a3155,e5a7ddbc,c5447796,8edd34da,8967be99,84240292,9ea7277b,5be0d045,bac79fb4,93a08a41,d4dc5991,da6b7cb3) -,S(3928013,8cb3e93f,7c4650c8,8184dfcf,6e55d238,2e75e604,9dd6e40e,f489745f,70b25e98,b897f3a1,c89bd6d4,72f2555a,56bdf04,6fb43799,58709471,f8006a52) -,S(a47e1331,b5fdbedc,e490497c,bff1088d,ba72070d,3cfc7997,fa388fc3,2f80b451,ca54b8be,fff00465,4086c75b,da3ccb9c,6244746,522124ec,ec22666e,a9576b19) -,S(cc1a608e,16c57528,3cbbb134,4083cfd3,f1b325cb,b48df6c8,2d50bed1,e0cfb96a,5b8aca44,67d9b224,413b0c98,78e09213,591b8f87,b024bab5,55120a83,38cc6734) -,S(d8354bc7,591ebaeb,7ae4d1df,2db3bde3,b7438d1d,69b5991a,5d70f6c2,c3fc3cea,efc89693,6765f03f,29422703,97591bed,7d95afc7,29807a31,fe266f08,9eab5ad3) -,S(6ac1c963,ceb2740b,212ef42e,6da07647,481ee21c,4e3fdd6f,f2ae3da2,8ddef8aa,4fc8817,1b6d5ae2,45453c94,f5f2031c,c52140d7,a110d9f,b1bbf3e8,e5164281) -,S(be130f59,b52e4148,f9c47469,778fb36e,74d4da3d,a00f5c4,dddd2e47,6f18b42d,16dcd9e2,f739a58a,22a7d76,1c1cdf61,c5b9f8b9,46449516,9398dc1,fbc47069) -,S(685db8cc,39864a55,68b56e59,96265bb1,24ee71f9,1f9f4f3f,fc3c79e6,c063bd2f,730a7141,8e5b2f7c,2d333b8e,5be3021,22b396bf,9a75f493,37bae5c,86b50f29) -,S(39f41ff3,89f74c1a,e25e564,b9bc189b,f31f9af,cf0ee4ea,aad66ee6,55d743ae,fbea0f6d,e25d4fee,53f0aad0,9338f739,26fdaeb2,edf9d8d8,8e1e520d,d66c8622) -,S(d7a69574,41bc9639,994737b3,d483bc0f,c29b1b62,cbf59f28,b12b208c,4c20ed1f,ce44e2da,cdf8158e,9c07ca25,1b9a3d06,91eea29f,41f824ce,ef2d631b,65ba8cb) -,S(85bad160,9139cbb7,2be86793,42b37884,22f5981c,5fdf30ba,4914395e,c1eaec9a,99fcd461,29e576b2,b25c57e8,8e3fe3ea,362055c7,843838db,4196a485,cf14dfec) -,S(2380bac4,d428a159,23c2ffbe,8f17da09,74d986fe,4210b72d,51a1eb80,23ea49e5,f4af7313,fde4c7f5,e45e38bf,c4d44bbb,3ca1015b,d209065e,5a6ab074,5ed6f54b) -,S(c0561359,b7d61dd0,e359108d,f221202b,97c1acfb,894f4e9e,46fc29fd,364f9cf2,3c377d80,1c72a9f6,2cfea5ff,350ceb32,75b16103,cecf492e,2901327,d27d83dd) -,S(72c499c1,b8f4f2a,eb9181d3,9bba5b2,76481c04,a588fc6,4ed438c4,920c2a06,6c994c8e,60825314,2a34867b,1f82bc1a,f05ff8ff,b3045e7a,72d01243,b2b1ce53) -,S(8de84cbe,2b66209,f8f8e2f3,f06feb45,66e02c9c,b5df26f8,84e20454,ffcf477d,c7f2f680,c4d07d88,69348e98,6a3b7ac2,ac9e8542,a019f379,6410b993,742a34a6) -,S(dbfec9d8,6581d762,e5ac8048,886b9d2e,9a2d02ee,63c5f442,7d02d12e,401710f2,6e611ff9,827bb1ac,a885acb5,906648d9,b46496a8,98a13c90,48868d,c0daafea) -,S(9dd651f8,6099edd1,b3d0ade7,82aae6b3,9588dc2a,291577f9,f2456f23,d1d0453d,4f6db617,f0d7860e,18be81a,dfb6d773,cd3f905f,98611845,5f5a0b05,ee715ebd) -,S(2fd8161a,c869de35,e777a885,ee608f96,356445f2,fa2f33d1,926260bf,9bd66a15,1d2c21e9,674c2d92,b64163eb,12de6347,98c6e7a2,9787daa,7c6b4c80,fd307f25) -,S(3f25bf89,24f505b2,3f1538ce,4940edf4,8b6d8765,f88778a8,495e8a84,a29dc391,70253583,e7e0782,18ab0252,52c613b8,34438254,9dc57c30,afd47297,2c8164f2) -,S(3c0f0359,d5f72344,f8f3d2fe,28458f30,467dc770,b55eab47,ff2e1ee2,6c773f0b,49583a39,459f19c4,5ac50d78,74626524,b9c25030,e45f2c7b,12729ca8,1edb33c7) -,S(56380666,ec1b5df2,36045855,fa0dd93c,87e38d70,fb170dd7,3be5c308,36b73a15,700690f0,b210ac6a,9aa91252,c8af8f60,b5cbbf93,8291fb11,7bce1f0a,759921a7) -,S(71ca710b,b9a5f7f,ec6b228a,af3fc47e,25f90201,fbe3c673,8bc6d2fa,9c9298bd,7dd2528d,c0750899,b1891287,170159ae,c759bca3,51e243f8,fcc9efe3,2f9abc89) -,S(78ddec3c,c938850e,7c2ec20f,98e1be3c,6ed87fae,827c9102,5112d0b3,5d264575,19072951,766a4050,c8585048,d6f19e60,22b9c163,f1799ddf,d486dedb,3d680321) -,S(9aaebafd,8852857e,8c670950,93dac29a,5813249,ed03e67f,3226ab3c,7b4ed70b,8c6a2acc,b541bd51,65e13bc,a3c4d2f3,2457bdcc,406ba71c,7b9cecd3,4705fffb) -,S(586eca74,941180fd,da16c7b2,8b9bf139,a3096a6a,20ab9bcc,6d12be5b,db2f79e2,b3b1d12,361609e5,afc5a7f8,26a21ea,ac4bfde,56016ad5,bfde6f93,a3488d71) -,S(1857bc3e,dbe4de2c,86fed7d4,cc3ee63,c0e0b6b1,36acf97e,e3638183,8d50ddf8,ea5e807b,e7a588cd,ec759c67,3584675a,8a7fbdb7,cc5a1835,119a4f64,8c275363) -,S(aa4cc744,7572c62,22a6cd,bcb8813b,64206796,27f5f7ba,863d8566,78e5b01a,ba969ac9,d259244a,9a3b7f9b,b3821a61,a4a97b8d,af7e08bf,f39f099f,8fa2f836) -,S(4588ec09,59174367,6885fad0,a43d85cf,d6f736b,cb276179,e794da35,204f36aa,fb835e7e,cdc681c6,ee1c89d1,dcbae3b,a9511692,a54c9c37,2f86f4b,cc7c62e) -,S(867acd03,7a3e5f86,99e33f22,72f7b1fc,25ce6622,5020a4e,ca3b3111,e880653c,e9112ac7,57d3f905,3249ba3c,ff64640e,639cd94e,5d6cf946,d8d7f3ad,25764646) -,S(5e0a4169,e4f81dc2,28ae4663,9ae3bd4,b527814f,4616fc13,318fd5db,26df370b,5bd335a8,fc23934e,bee2e32c,3bacad4c,c38cd624,8cb34ca9,e58f8add,3140d001) -,S(90053469,39df2418,1b5b2e57,82a82f15,542a55a3,adfe8263,663b4fff,b101c0f6,4ff0d589,973985f6,858f3837,89c3a5e1,74460778,3a1b1476,e3f1ea51,37e3d991) -,S(a99439a5,53df33ba,6a32f33,d90b1500,4e2db077,22a73561,8f4c3b0d,63cec63f,198e0929,f11fc777,ea9cd8a2,e4e6987e,6f9c1fc5,f703ce7e,7e6423db,39656cd4) -,S(51f2a136,1381ba14,c8fab71d,f82aa2e7,1c7789b1,b78c355,a0e2fdf1,5f085282,fd5f129f,ca15fea4,d6f23bbe,43197a3e,6e2b7b26,84934ea5,a97197cf,eb2d16a2) -,S(3a91f81c,8b064b2c,99509777,864c5b4f,bed208b8,f541f68e,82053158,2ea91d3a,9d59003a,d4ae39e1,95077329,e585a8e8,a542b594,b6010404,8573a01,23a513c9) -,S(71e99d50,aa22fa17,3f026dee,e728c114,5e491e84,e140b462,1056af19,9736c5c8,ff3e4f77,68588846,7c662729,1d947e77,699806e3,9bb0bb26,53f67ec4,176a4995) -,S(ad149e93,3a0344f7,3fb53286,ace2f3cc,46f7450e,e859980e,6d392001,7c8aaa39,7dbf4798,85a4f354,b4f14060,39a83789,65a5ab3f,f1157e3f,2a4f6fae,909e81bd) -,S(44f0a37f,5ad78f6c,4a40ca20,7969105e,86e79ed7,7ebbcc32,1a247f91,751ccb01,f404d867,911eb3fb,efb1e559,66b5128,70836d9a,12891905,af649555,c353044a) -,S(4f77dcc3,de8de08c,4c0a4a8b,29717868,50f5c0e3,b271ec1d,c0d38a61,b30ad5d,73c7424f,8ae80ee9,2118aa5a,b0aa65b3,58dc7300,806ef2fa,55836a39,4df57c69) -,S(794a108b,102a0923,6366efd3,8ef658c1,6d6d5c24,e5e2dc0d,38d71371,e6005555,871965ef,efd79050,69acf0fd,c1f84798,7c9e304b,5fdcbf75,1a6f6737,ce46ba2c) -,S(f1988561,234b863a,df5bd49f,5a0b1252,a72e297c,ea3083a8,22da48d7,14e8e594,7adba507,d0ab51a1,8c036612,dfda3f8f,abd2f573,d31aa03f,ca6eb361,a83fc418) -,S(48bed556,c07c99e0,71249b8f,7790aaee,f3fd27db,f82d1c75,491a18bd,cc3f4a80,9dae5280,21be418d,1b4dd08c,be5dbca8,46cf0122,d4943543,8561e555,66316e94) -,S(bbfef3fb,e53779d3,8f376fef,974bac74,ec8449bf,c2dc8a1f,3bfcb33f,943ab9c1,bea5b772,ee798aff,c610e849,5be0ea8c,ed462563,848030b0,8006c6cd,e312551b) -,S(42af3415,27b3cd52,3806b04b,ecc175c4,156839af,eebc212e,b74bd6,95b7f06,686e5fe5,ebf16ff6,2376d096,188de980,f91a5518,25bfa137,e7b46df,59dcef4f) -,S(3c56d78b,74ae87c4,6efea376,d58b7d5e,30749726,40c24d69,38ade127,71ce10e6,ce97decc,f9d1e215,d363b36b,6ca2bc6c,39fed00b,511bf883,50732752,48d54a41) -,S(4b122599,1944ef0a,ae6404a9,e48f69ce,67b52a1c,da4f291d,33afdb09,b789b61a,5c8be350,27a3f992,5377932c,b6d92bc0,62b1bc80,78e4611b,f3ebbe66,b6089571) -,S(9e42867,c02c9314,a3658f18,14d8c59d,71674955,2b00be9a,cd37350d,18d49db5,5d26d035,1ff90d73,d783155d,afe20cf0,39f65b1e,6d8d5d0d,831977c7,17a8c761) -,S(9643390c,5a95345,2a027d0d,47bf6fa8,306ab31e,5dbd8b94,402db973,275359ae,b354d7f7,1019e9c1,d23560d0,50fbd4bb,abbf492d,f595c0ce,a699721a,b27a3933) -,S(8b4916fb,86f77deb,505374f9,1f15782,1b6f7884,feae9f77,bacf5620,7e126b69,9a83c0,6d86db13,55c3d59,cbc87fae,ce6d2af3,64f9c213,816cb326,28be1fd4) -,S(d29df4b,109782c4,1f5ee9ab,b8488f7c,11de8efe,9552eff3,7ba3cf0c,d0054b9f,1bf06237,ea242c4f,bbe08f6,a79b6808,d1a5a444,1989fd1c,98a60981,40ca07a8) -,S(2aaf397b,a5405044,539167d0,55113acb,d4a20265,206ddede,203b8ea7,21dbd41d,374e32c7,1132bbac,91e4b4a8,aa32f308,13a81c2,4f7b3c66,63d8821e,9ef73081) -,S(2239b3d2,23eace6b,8ebd287c,8b6a398c,1ca58a94,5d8b7b81,7b1133f9,cf57ef48,fda880b7,4b54a8b2,8af4b26,78e03f28,f01d70fb,3e4ebbda,94ccbd43,e2b4cd46) -,S(8b3287bc,f47e72df,7edc9178,51edb145,b88ee233,9f254f62,e86ec624,a7c7e365,54a06bc0,9f60d54e,5f900868,c0c3d37c,db6d9969,1eb605be,321f0f20,9fecabb) -,S(d9accea3,3e3cfee9,10d7e1ff,3e87539d,ace742c7,24d6d36d,d8d981ca,984f7993,6adc974a,a901e5d2,d8cf5a05,a20bd02d,62947f81,5425e690,565638a8,427dc88b) -,S(d7fc57f8,34c348bd,e6692b50,474ee038,4af245da,40b8f6b3,8df2ae5,a8b3206d,b253e4b,41fd9fea,9b28e04b,a6db0324,231edb1,1f9af406,e38d2b30,244e2d19) -,S(25808fe0,ec4a1409,36b34e16,595021e2,b815f660,7a23d505,9ad5b5c3,14d9588a,d0664ad5,b1d46ef8,8c8a1eef,bb9df1ff,a75bc16c,e8bbcec6,6f4798f7,c58e7b96) -,S(e4474780,113955d6,72152fa5,70da35a7,59e67a76,29a39ecc,3226ea13,99927914,493cc170,aa2f0486,da6834d3,3566c78e,ad4eb3d2,837ef5ea,c1adf3f9,43793bee) -,S(c5040dbe,2af9d706,76ddd900,d00f1046,44e2b985,82d46f11,47602b91,126311ad,840aab11,a2316171,cc9b6466,778a9ce5,a7cabc1b,1077586b,91a8d280,324ddb15) -,S(23391baa,316d33eb,3a7ca123,6c47d4e4,8116cd4f,93bda3a8,12a228eb,437d9f14,1d81341d,9e6d76fc,1ca69af,f6d8d119,bc97c79,c7cb8b7f,1ebb54f5,cb7efd4d) -,S(13211756,3de3ba72,2fc6682c,beb39494,8aeb8fd8,c0b95eb9,45eab34f,bc39ac38,9b772721,8a4b0823,7c961431,e26cbfb9,aa527905,41b753df,89eb9ad8,8d74f006) -,S(3b8bb898,b27a2fc7,a1cf896b,bb5cd7e1,708b943b,afee896d,2ff77a95,ba789708,d81e541c,668003e5,5a1e13e9,6a1635de,7fdcbf79,c34068c9,248100c8,9d36c1cb) -,S(e1d70a2c,9af5c4ba,c505e4f5,5c0040ff,d94f162c,815a2e21,c7ce899f,e0217b4d,b25630d6,d20e0e4b,3686d66d,e2b1e53d,eb063b99,e79c212c,2fd3cfec,97a4532e) -,S(1b1e3823,a51778fa,d38f0c56,e2b36dff,a7e681c8,30fb41b5,ff1aaa7b,d912de1c,f2e99a90,a951201d,ce725855,6bf7fd27,bebe1626,8328116c,d593ff32,2584d4c1) -,S(1e31d838,94f56191,2c134817,55e467e1,8745a91c,d903102,e48f7282,21bda7a1,11dcef88,35dae18f,3c02c6d9,7f80896e,477a7b27,41203aee,5048c94c,7cd610ce) -,S(cb9ac34,795cbc99,bf67a7ff,2bc3b497,311f687a,51b5028c,422b0301,8ab7100e,5e5f0621,c804b35c,e01e95e9,a8dc13f7,e5ff32dd,8a44f320,74e44836,3cd0db1d) -,S(afc34ac4,67dad38,a0e326fa,1a656c48,24dcb884,f00a20ce,56c73835,b4e11c1b,c8b1c404,3f6d647a,382ef031,a02c10cb,77a033ae,bfc6dde1,d7508136,28bdcb96) -,S(3a6fc160,ca85aba1,619430bc,ba14e12,3330f636,7a78273e,603f85fb,e270aa81,594a2b72,86dbb390,945a7a48,3707bc32,cb72cfc9,19c241bb,61774dba,222bc0a) -,S(a840f695,657c9c3a,3f64f56e,af18debd,bdc1e4a8,e3eaee43,46b19601,433ce7d4,8a8a7ac0,ca41e2df,461eae96,bc00131b,1a77b824,7273269d,7a41f49f,ea126fbc) -,S(c044e01,70ec6914,c39d08c3,4a293268,65cd7762,d6e0f3e5,5f69d80a,e80a39d6,7bd63082,7ae51516,25ee0b5e,c2f97b37,6dd5fd7b,9205852a,92dbf922,3a0b4657) -,S(cb90135b,352b969b,45eb5c6,7cfdd288,2bf9271a,41da4b2a,a89dde94,eaa00b3a,14cbeca0,762d9b11,fe4b6d26,7277a8f7,b4dac82c,52634b49,2a84b616,2d79be93) -,S(fa7bc437,a24dab0f,21c7c063,3aa4a8ff,c8216676,75ea6963,c58c84d0,b182a0e,e24267c6,d7300c6b,6dd09326,c49359e0,fdf72114,401f244b,383eee54,d1a5aa35) -,S(e6354cdd,3f503d25,37b2bef9,91533ad8,35e95657,3bc8afcd,d0c1c05e,57b3299a,d6c17b70,6291c8a1,989955b9,ae9ef9c7,cdc2b6f3,f5cada0a,3c4d0b86,859ead7f) -,S(9da36530,7e815e3,df0dce9d,50d7d812,132ec23d,2bf0453b,483af1f,bb45cce8,bb374566,98a28ace,a86a1b10,2909ae91,3bbc4b23,22f4d09e,bd298e51,d067a8dc) -,S(dc457a1e,1a19cdc7,6ed1c3b,a416a886,13b25788,22d691ba,76319b8a,38c9d4db,39f93f66,de5a650d,d49919fa,294638a7,85e25bd8,f8285776,dfce813f,bbdc3b58) -,S(b2377b1f,1b1a0e98,5ff57bc6,64ca456f,ec216c6e,b7b389a9,62b9d82a,ccf0374d,383a5580,d723509c,bf114e74,b3eb9746,7a040fc0,6232adb5,dac199ac,77578c1a) -,S(8b1a6446,755d3a85,3851fabe,b95c24d8,2a5a86ce,5e5df65,78051124,acfc7e50,42b885d4,cb632a67,51a88aef,192a5bfd,ed1cd461,438cb623,1caf3346,9655cf75) -,S(9408819c,bacf1a0c,9e5f1416,23a907a7,c3a7efa2,30a15b3e,7d5a6ff2,5103f5b1,a9758ec9,d6f84f73,fd107451,f0ab79a2,1df08c30,cbb2456b,d6c68cb,c506f98) -,S(8bfef047,7b3f8cb,99d7c933,a884da4e,9ce6d473,c243d3ee,9c319870,b06ce25c,8bbcbd87,d06af17,550d17ee,83017c58,627f1d84,e8a07e37,ca73c12c,f7e5c498) -,S(2a857f0,c12202e1,1dcb84b8,adf582f9,8eff647f,c3803cc0,dc1d294b,414bdb61,9bac456d,a7fd9318,244af8c6,48ea23aa,62c8ae1d,af7fa9af,e430efec,46db6548) -,S(937b8c5a,90485ed3,d06b224,2ff53e6b,b94b1ee6,a493c835,25e3acb6,5d5cb5ec,d37b136f,f9fb374a,50f5a311,ae366ca6,c9c3d867,e9b7e788,da3b2766,a7ccd808) -,S(5f544d53,e2bfd6be,d9150ff3,6a1e5c5,22b24933,489201a0,65a0e0a0,3a43c77a,ba9c20e2,8c47cd98,1752c413,70ced32,8f4c847e,20165562,c3137e0b,12990f51) -,S(67b63388,90bf8baf,a5b64fa7,eb9fa4c9,e3249cfa,81a55cbd,9c297e7a,a7c807b9,dc185675,2d94b811,42b54577,edf808a5,d871ec1,6c8ba567,62061dbe,ae7625e6) -,S(587a9dd5,99cb448f,9f92ffa3,d6328032,b76604d8,386a2e2f,bd324628,98439442,496998e9,a893faa7,a49e73ca,2dbbf533,488aa687,51ffbdee,6b6d6dcd,dbae9870) -,S(36fb7b1e,c576ff9f,81077312,35d18612,18dfe51a,58642a56,8f80294a,63c29b38,34a45ac9,b82cb1bf,2c96fc1a,67de8a63,5c1a1589,61baf8e8,a2f01572,1566c4aa) -,S(87b71c8c,a0afecd2,dd8f49c5,109ff434,ab8a273d,4e4efcae,f775624c,71f4ba95,8519151f,51122588,76527c56,e1e6d9c8,5b3626a1,bd6ad0b8,1bc382cc,525676f9) -,S(acf65cf2,805c370b,a3bed962,c3ba3b0c,56c98,b81a696c,f433a0e7,a463e040,f093929b,f45be16a,f962762b,52f57ef2,dc7b0e23,cd68e3d6,63b3b402,15692d5b) -,S(e092bfed,8b010c85,b91f1674,1cdfb1d,e3e045ba,81297f44,8990475f,2147acf1,e0bb9842,ecc8683d,e4016072,86070da9,8c4d18af,8bdda91b,65770a98,77902c37) -,S(9bdfd7b9,8260bcbf,17812735,c70501db,ba386b7f,28ece691,97c871ca,610a52ae,9bc65398,3f8c4cce,731e01ba,a5f509f4,887d9a78,40620d9a,ffbcfdeb,5e371eeb) -,S(3db22321,d9311589,5c85587a,9095421c,afc8a80d,86a4240e,9a4a2f82,8643545f,42af30b8,2c57868d,e0f23c9a,fb19947e,fdd6bb45,4efc68bf,ddbf7349,8fb78eae) -,S(e9d3f14,a6a77ffc,f86decbd,c5e43fa3,c3757a64,22d37da6,25627961,622b3e5f,83ac0bed,1e2a714c,c6ed0764,da92cc17,fd18ee84,36d667f0,2f90f818,30e67de7) -,S(412486e4,f29b4887,e1448af,ad59599,b31b9085,8682580f,891d51e,9842f2a4,c31c5931,8c0d6790,c2fbbb03,9c2e761c,bc5577b,53161a8f,80d397f,de7ee3d) -,S(e9deec71,41ed506f,e2dafbe0,c9ab75f9,609f8422,a4b2da26,7c529d92,36b4ddaa,8728544,d8463bc2,d846029e,5d2a0a40,8dfb767f,9adb79eb,2209478f,6d94a21d) -,S(5a0a2292,553c46a0,823a1761,2b8925e1,bbf01c2c,5bcb7173,5f0fd6ff,b264218a,3097cdf0,adda0f10,a261f897,6447ff9c,12de696,8f05009c,e90d1575,e55dbae2) -,S(49cb2a37,8b681ad1,ba1dc23d,8d12f186,563a40f9,ce0ffd00,5bade11a,4928d1f,f235e2af,c0f65fa0,ff15a938,ad804a3c,fbecc5b6,e276bbd6,32a06959,3d6732d6) -,S(d4d71cb6,36881177,b05ad510,a621cd44,3dd1afd4,84d177cc,f99abdb9,1615feb3,3ad65378,de3eb9b1,606f385f,a950d533,5316c363,fb076c02,ac7f12f0,7562645b) -,S(591b2e1,4bdd6e00,64f798c3,14e86cc5,529c99b8,3f47d148,b7e3e642,35bfab2f,4f686266,fd2a4c66,4d6bbaf1,2a368d59,12a51789,5d783aec,a986a568,a8fa59b0) -,S(ee503c85,c984bc49,3d7b63c2,92eac9de,be253400,f4988086,970be236,47356876,bd828abb,6f9e89cc,741704e9,614d6711,39449bb3,a7ebdccb,976c573c,4bdaa47e) -,S(2f9b4fa7,2e5a1fc,ca36a3f9,8987c3af,756e78c9,77fd5697,758c95b3,14b3f89e,9668615b,3d5b3c74,4ea2e1ce,e909d9c3,956657f2,1a65fcf3,3f0ea150,1ca4a15d) -,S(18b6d06a,a34124f8,5f92b204,e2a010aa,a1f4aebc,6e13a62,34eb1c92,7afd46c3,66cc31b9,bdf600b0,7e624bf,a3e079f3,258b0ba5,5437264f,b460481d,1f4bef4e) -,S(3bc07963,bf758dd8,fff37d0f,30db6eb,67662a4d,65395688,1cc30340,ddb44ba0,60e11ef2,68209a1c,2df9a3c2,276db6f8,8e6dc1ec,b74548a3,57d770c1,ad057e5d) -,S(bf585d6,5b325423,afd49af3,c9fa68a,91498b5a,f0ee9e3d,d089b288,53a46a8,2f8944e9,ea484b9a,51256e2c,fa9e5396,4c000c1,3451cc05,94bcf6ad,e38e66a6) -,S(887c0a2e,be7a0257,5d5b59a9,11f40ef8,f0cf1438,d7f05a7f,64e9c133,cfb69294,45f334c8,4f9bc66f,50fde594,94175491,9c37c30d,d20f6a58,40271e71,60aec5c9) -,S(9dad7af9,a73325c,59a17700,fc3dc6bc,3718e79f,804a2116,1bf9a36,622f7d4f,2b7c225e,99c6a94,c7e326ec,b89eb8dd,40644bad,1893136,6442985a,e6159525) -,S(847e4f95,72bd29f7,4f3e9a2e,d73cdfcf,63bcb61c,9caf8694,7cb84594,a7dd551b,ba6ed282,e0a92c62,fa86286d,370cb344,f6f1182,a101c4b8,1ea89a15,b393ee16) -,S(25213205,df1c3600,4673c4b4,49256c70,b5d8c62c,cdd3d580,2684af47,f047a593,36dc81de,5af4709,fae2a47a,8a205647,95aabfec,42a79f3c,54763d67,ef096837) -,S(75228cd8,4866df7a,4713a25e,f2fb29fc,95ebfd70,5d73229a,b170cbce,1058e87a,fba4879b,cc02d3f4,fd25f056,c0854415,68a47355,929bb812,a7dbb30b,c012fe6d) -,S(74945539,22867c08,6d02fb07,c0424890,981a1337,42c63fe4,b6adadbb,59b68568,7d774917,8df8b19c,8af0bf0b,5247e751,3e3b8d04,46465180,341ebb54,1d1af3e2) -,S(69db7f53,2899e39c,fa0cbadf,c29946f2,71d28ce3,57f47f7a,609e0fcb,ffc9b04f,cb0243bb,103255da,ad423ffe,e1d50f9f,26da7cdd,764a11f0,a6694b63,199feabc) -,S(727ecdc1,fb4a0dbe,fd2fc37,8902f922,ec4aedf5,53dae225,1d173c29,2929f8c7,ae5bb2ed,13778d60,66446ee5,e5754db2,bfc4f7c1,64bc035c,224d495e,651f453b) -,S(903ced8f,ec2544b,e207f5c9,e2c7f2bd,91213873,5eebc382,b129e334,7ef25b72,2117ca29,ee13d31,5e89bf33,afa8b7db,ff75c795,6be40c8b,b2e41cd5,943190a6) -,S(c4d467ef,5149e117,3638a5ad,6fd36373,1c8906f0,80336ca3,3a6bbb99,1a03f33b,ea5b5b24,4c536bcf,ce3d437e,abf2fcec,431ad80c,ff975b63,bf398163,629b5c7) -,S(16b577a6,5f6d09f7,b23b2b7a,dd80a2f1,cff7a8a6,c36bfcf9,d325e37c,ea37326f,66ba8e2,14674e5e,228a6576,a52a791,84d98be1,db1a2dcb,e9073934,d09f15c1) -,S(ad4bcaf2,e480adfc,e1e45384,6bd7ddf7,67fceedb,d2bf1f5a,6768531d,9b63412f,51fa0360,47810f59,11b1b3a4,525ee72c,c4c891b7,56737f4a,a61a380,e9e741ac) -,S(b249eb38,52d2e787,4a52d776,d1bcb399,51ca65de,dd9e9dd5,87d73362,c33b571a,3e260824,14e4ece8,83cd84e,b177096c,62dd7706,a79c31d9,b1103232,53a66258) -,S(634192c7,696a01ae,81310d3a,59d2c53b,74dd0560,7e3be9db,ccfd1ec4,bde14a65,455b4850,e366e077,d86dcd70,9c787b18,4fd4cce4,4b92954a,dcbe5222,57b0e00f) -,S(ffbecbf5,d433f80,49e159cc,c14b198a,acc3c5ed,fbb1ace6,fd295dcc,4a2f5099,422e7aba,1ec66cf4,36489acf,9c03ba33,dd68d368,8a48685c,aaa1de52,440be3c0) -,S(65b4c4dc,1067e823,9cf4f1a9,d0632da,b6a8c83b,509a75ad,8c133dd1,5c1868af,f7cf5d9d,d7654618,5183f8ae,7f42a03,20c67817,9d5226d8,40dac1e5,f94d260e) -,S(d380ecce,9d603502,d518dbed,405b8d0c,8de48dbb,35d5b559,24c1a560,9bf9c67e,1ae84480,fd18ab10,9eb0ac15,265c609f,8b241b4d,a80b13ae,50c35f8f,db64c128) -,S(17189d28,b5ce1bbe,d78a1d96,15dd1a50,3fce43f7,19d042df,63484ff4,ce44511c,fbca28f4,7c7b3e39,4121b948,ba561289,85c53298,8db2fbb5,7596a473,a782350d) -,S(fbe332c2,e2a8b07d,a85ae4e6,1925bf3d,be685e4,fafcdee7,3f558382,80c2e84d,aa917342,5e187da0,e3f8c6d7,79b42cbe,b11c43e0,6b594eb3,e1a5797,ea4e29ca) -,S(8b9e8a87,8b5e725f,8b4bd518,22e9cd21,2100d1f5,cdaaf210,2d7963b,a0bc834f,331fb31c,c28f56bd,5ff1d6ad,80b65702,b2e873dc,4552c563,bed77a08,cc3ed659) -,S(97e92411,a3c0bcad,17a798ac,eca61ac2,34e1a68a,b668aa3b,d730cc8e,8de111ca,b0f170a4,bac15e17,2e75fb75,93c21a41,4794976,bafc7eb,7cdc4bf1,6947f48f) -,S(20358813,33a13c6e,cc8c76f8,2c279577,49aa3c1f,d4d51691,9cd23b25,d044eea8,480afaa4,8c86af0a,ece2f951,7df0f344,259fc4f1,4d9a5c0,ee73c891,780c7f29) -,S(caa1eccb,1575740a,90155103,9849befe,617579e6,22b7c343,a665beb7,a67dbcff,aa695bf9,f1c972ff,b6fd3451,1bf042d9,1aee5113,9c1ea577,e0bd52e0,a4e0a20b) -,S(8e7c2ba2,36f7a8e,fdaa212a,7fd6b883,f331049e,6e8f2bbd,138a3adb,c2620719,bd03702f,1434fb3f,5846c4e2,e779f8c0,d9b6e031,1feced02,20a618f8,2eec105c) -,S(e07dc033,6dcd04c1,fcfebf09,40c07783,88fbad11,8e4eb3b2,4dd637c7,baace975,b13bd0a0,e5eecb0,762ccf31,1bd53156,ef6f9268,50044195,10d6616a,b32a2c2c) -,S(6606c825,2679af01,9d8a904,4db0b28c,95aba791,d1c33072,97afa2df,bb8ce0cb,7505e59c,a9807993,5710de77,747868fb,10fe6c57,36ba2054,6477cac8,8e1d3cc) -,S(9fbf4cdc,ec48226c,b45450f,b0de5dae,2b31f935,2b99e0b5,22ab9935,1de6f061,f2e4d0a2,3da020e8,60a0d58a,2362b7dc,e9c5b646,7034ec91,a7dfa601,1ef850dd) -,S(e06d697,5195ffc2,988b0403,e977d32c,b7cc8167,e800db1b,976f6186,286916bc,8015370a,27d3d221,7af80e04,a49003ea,68302bb,c1a5c83,63244c0b,c30bb8bb) -,S(adcd67ab,21d2aac,65112fd4,e6e16cd7,ff792577,e9785a6b,cf4a3f0a,9293a6e2,6527b620,29062aaa,5058608,f5cc3bad,8e4f40d4,9b5be93d,faa5c2b,57fd7fb8) -,S(1d9069ea,b43a64cb,1187e963,d96809b3,5a447317,68910e13,3e0bf7a2,e1f2bd38,ab03dede,854b8fe9,4ad2f9a6,8ef5415c,fc78c28f,a4ec33bb,f15df31a,91e29108) -,S(f1f6b776,b8ec892f,148168ae,8ce83f4b,603206f7,2a38140e,3a422e67,a20a768,892ba036,3413da21,17d9b11a,7bb25cd9,e7136a7d,82a7f45d,14abfcb2,b9bff25a) -,S(a884f94a,ce79f4cd,f3a8d1b,f8a2dc3b,c21d1c23,433a7fb0,401c5df,1efab379,5f53356c,6e45248c,ec282fbe,ef03ddf7,c611affa,5d0d3082,dd630f80,dea05c96) -,S(b1988430,197a8800,e1016564,b48d4f7,1fb2be08,35e9efe9,81a80f10,e61da9ff,d5c7864d,ea7d12d2,5be7ace5,86e141a0,e515a41,5ec70bdf,44a68d8e,4dd849b9) -,S(15b73aa7,529d5b84,bd5c1db8,2b6c93aa,46985aae,942f6d4d,1094434e,d27fedb,297e32a2,bc8ad13c,42011259,b1ca3d40,632ac6de,f2fca262,75dabc8,ee721f89) -,S(339a76e0,443c1fb1,65992630,116e523f,8e35cc7a,16cd0f3f,57f7782c,7d97d40f,8990652e,fecd784c,33e75620,13b52e6f,914f0f6b,c413aa22,9e5bd773,cdfe9659) -,S(bef26cff,fb80ddab,9458312e,9b09044b,b1c535e1,84f4e51b,f64b5183,b67adfef,3818929a,ef076a83,58f20518,c5b310f5,2c6943f2,1675bbb5,ba1bde45,9d37490b) -,S(cdc56c81,8dafc273,4f4dae10,84f91b08,3dd40d86,23125894,c71d9243,8b2427e,f4b309d,e9c828b5,44542569,45579f91,b4376935,3f586c71,f07107f0,1f503cca) -,S(3ddefe81,b1f38479,ec9be80a,1961c5fb,a09312a6,2a775911,cd65200e,7d75bc6d,75d83edd,1eb9b479,4effae4e,ba8007d2,7c7e2d51,a9e95d3,a1e58358,56df055d) -,S(da7c6776,99032cbc,4c2bae12,59212cf2,a18879d2,63aaf99e,76339041,10576826,2e7a6d88,360ac45b,9871f779,9e80698e,4314cc3c,3f1cb1d0,c07ae9f3,38553f08) -,S(2611b435,e0bc20c5,88cfaa80,17f4555a,b8aba4c4,ae1c0385,9dfaa911,aa80d927,eb58f81a,e51dc504,465ff8c1,c0529fac,e47549d2,429e5b41,7ce0cad3,7d4508d4) -,S(b0fbe548,36f07c4a,a715aa08,806b71d6,b8f4c09,6945a7bc,3defec7b,67962961,cc60a224,66e7744d,c58668f,ede30ca2,1c1749b0,45ee50de,2a881a53,83e5abe0) -,S(1a03336f,dc51ee75,facb7688,b4603c86,77d371eb,5ededa9e,b50bb49e,c9020581,3fcf1b03,9c0edf8,99855fc3,6acfdbc7,bd507145,9be7e18c,e9f715e4,98daa7d7) -,S(763a1215,c8349155,aa849b20,f2f68a36,cf72892,49e4d3c3,810ee72f,78c159ed,37826a1c,cf30e1ed,a1795fba,d1f2f227,7b68d5c6,9ffd390b,d7dde5e6,58482684) -,S(7fc7b4c2,30183e37,dce0a586,a6f0188c,f7e664d8,5fa05eff,63f2c27d,cada4edd,fd7a780e,6ea89a06,f0649343,abe7bcf,6338d2fa,fe457f50,ac415c91,2bed6a8f) -,S(222807c9,b0686f55,d9eb7d7,412588f,dc543bfc,f016c8d7,74726135,dc65ddd8,b9670902,456c22ef,cb36d155,319393da,9a34b2b4,301c898b,43d957b0,a56cc2ab) -,S(79d8eb36,98d8d06e,6ca33f69,ca04d3c6,db636346,abfd603,ed0189f0,fc5fda77,bffc97e1,1b0234a9,8dd1d460,e19db522,931fd49e,26d7ab28,f1326517,23d955f1) -,S(a2366618,8e72e1b6,d5ab7713,decf6e3,1f801a6a,ac88ddc5,d464d127,ebadd34b,ef23da36,f3e71913,2774cd1c,d150ffb0,70e99ac8,5193faeb,b1736abe,77d60ed1) -,S(b6bad04d,dde6816d,9123e8e7,43fa46a5,b1fcbdb3,fa1f13be,480fc1bb,49dd9612,585fae09,a290b273,a68b7f34,645b80b1,850c6507,d959b546,7f1b0100,b6a4e511) -,S(2bf21c25,3353e715,283113db,8bb5018d,33fcbd58,f3d6face,b491e1d2,f4c3dfbd,e3a033a7,4e8a4d5b,c8c49121,43a47b07,b9fec4d8,a0d5b3ef,569c44c9,cf8d896e) -,S(64c27a41,e978e35d,63f3a90,e71091f4,41e9ad26,6a05edda,358dddd2,5d842744,fcbb625e,8fda695,988aac9e,cfe67c16,bed76802,3b527d27,521c1339,3dae32d1) -,S(620a1ef6,fdfe5b5e,9a4ef435,63cd7c8,af62acad,a02fb399,b7542d2b,6481a58d,b0b79e3c,550393a6,fa07f105,c547e203,a45fa7c5,ec825ae5,7bec305a,ddb8054f) -,S(1523f131,7cef7154,347ef68b,424ee0c6,15e71251,a06bf8a1,ecd74675,307b95cd,c72554cc,1d8ad664,dc1fe67a,3f11e5b4,a55806c5,53dc2612,bf5516ff,f0743b1d) -,S(d765303c,a9c8794,c00d4d8c,2cd73fcd,b43f763c,b753700,f66d7294,4eea0cfd,bafcaca5,204dd77a,a3a17b73,da3064dc,35b4cd22,ae01a623,781603d2,57bc267b) -,S(a75eb61a,fafce965,65198759,c25cbc41,ffbbf87b,61839a8e,a17f04ad,64c468b6,99802893,240f48aa,53c49b18,1a6d50e7,a8eba321,64d587b8,41497d9,65869873) -,S(7fa41b4c,d0bb91b6,c25813c7,1241e691,e7053f7d,beb0bcfa,4084e06b,bce59f2a,a0941779,755a695f,8317e7e2,f6a2c57,9431e22c,4aa09f,7e583b1c,e184aec7) -,S(816c0db7,2240f12a,d8deb440,8ae2276f,3bfa1bfb,d820bd6f,cc5ccff6,16e4dbf5,2a52c93d,d91ee658,9449dd4b,bf70255e,e57acbd0,a981ac9f,67c16604,3f7e52d0) -,S(33f635f1,317f1425,51390ac7,346905e0,ddbb3d87,b0c1780f,bb7dc950,c23414f8,7435a155,84eb1988,b974d570,bbc2b2c1,15123580,2bf93bd,b626a543,e54bfbcb) -,S(d2943ad7,4b0bb03,35307185,fbc438a7,bdfe11e,7b5e0eb3,e94bec46,a251999c,2dca8fcf,19aaa314,ebde41de,fff6e9fc,b6097d6b,3bfec06f,19aa4941,676d577e) -,S(26aa1fbf,c54375a6,fec54390,b5e44a0c,fb524b65,c10d1516,b0112525,9dfb1da6,49eceaa6,4c575ce,337d0b6,ee7e8198,83973c6f,abfa2f,d4b24e03,99a91b02) -,S(780aec1a,f866a030,5ca6d7da,1948f2f6,ab18717d,e82300cd,65eb58cf,a7d28d20,da650041,e45a0e1e,a9075b6d,107b6f7a,414b3a02,18aaf929,92cf2978,bc08b91a) -,S(1dcff259,8e59dd4a,3e515853,b3cc41e5,ef98113f,29ff7b3d,5eed6d50,2cb88b67,d7978630,7c6871e4,5654307a,e3836e07,aed86cbe,a9ab92f2,8c680172,1ab77271) -,S(b19af4a2,77321937,93e367eb,5ece1c63,8f336f3a,9cdb4b01,e2488ee4,373ff70d,a3ea8839,a5105a2d,4277f27a,26a8ee73,b9e73fcd,d54f641d,c214d5f7,9c821dec) -,S(1c8c1f29,548a9df6,f28b6126,b9324972,35f24e2d,a488e066,acf782f6,b4f6755e,1a79ab52,6a1e1aec,5ccc7e2a,3196a07e,78108b23,a86630c9,1795ef96,11ff432d) -,S(b6ff8dda,1ad6c3c2,3c8a10b7,b4313968,e4d70075,12c421d4,f0b1153e,bd5716ce,4d3869c6,b7b74167,ca0d21e4,edb3e01c,af8dbec2,aa87a32d,7c9306f9,a5ce61b8) -,S(dceff4ac,f61ba84a,81821932,9fa0ad60,ec08cf9d,830e6ccb,375488ce,d0f47b5c,949aece1,92bc61b4,883d5508,aa4a4aa8,fb1b8db0,385613b1,736a6eb5,c137d6f9) -,S(5561e7a7,b709689c,97c4aa18,9a3ce841,843ccf98,be851c8b,131eeb37,dca5ebef,4b108c17,f298be36,430e6b7f,26b414a2,33b924a6,e65dd5a7,9a1f15b,a99a14da) -,S(4d989577,89b01595,8e5d5bb,2e064e9d,9c56a254,5b3c8802,7ca0c997,a395a257,aaebaf33,ac950756,c5b200c9,f5b009c4,506964ce,5b706675,7951f221,40b6e0d0) -,S(82b58e6e,6373c4b,30ad55a9,d66cc804,e9da512f,bf4af668,1246a12f,e33bfc8e,8378122d,98dc1e37,2c33b5c2,1ff4c429,d6d7577d,2ff353d3,87cc0478,1a5ffb38) -,S(f49fa88a,a773784b,fe57d880,9efac44f,714c3d75,3669463a,d1199be8,2c6cdf3,41aff6c0,2164a411,c8be7281,493483be,aa9855b0,49820772,b96aa39f,9a18b3f4) -,S(67d485db,ac8445a1,8c1b97a7,8c1852a5,ce910f0,d78b073,969c58ce,c0efd78c,71dda92a,24ff2b31,5fcaa5a8,28bf07d9,596f49b9,cf19f4be,44e6f320,84981e97) -,S(9145f6f2,c19038c3,cff99883,b5a71760,30a46f7e,8b5d350a,db2a9610,4704d4cd,9d9179e7,852ac5fe,1d4664d5,4d778b3b,6c8e422b,b6e78add,56700dbe,6a22b0bc) -,S(492d5247,efc2f5f1,1cf3848c,e0719abd,53674089,808de4b3,5503e23f,46b2631b,374b0762,7812c898,7ed68877,c995a4d4,9f021d0b,29270863,d50b8c40,808fd750) -,S(5b8ddfb8,bb811678,9298d231,72bdb9c5,25c6610b,46187549,a381ca6,17dd1dec,b47d3764,fce3218d,17d0dee0,133d4f3b,c7ae170c,3e8831ce,a92a3531,7b1f7568) -,S(88db73ba,25a61641,af5e603c,cd54c6d4,63c6feb,da11ec5c,6a35d30f,e406c65,39b06f7b,1c1dd7b7,884c67a,e295f8c0,9b8b5be1,c14456b,4027bf1b,4800a753) -,S(3495cc9a,a23c1eb4,2cd85070,bb095563,2a7037bd,e330f721,fb38091a,9c382451,7feabb21,6f3982df,74429957,3c7557bf,b82ff4f,462fc64d,d9b3e10f,b69799ef) -,S(e8a5cea6,970e10c7,93f75666,9d2309b1,a4f7b52,c19db4f1,cd69a652,c445d7a2,daacdabf,bd5259bb,96d2dbf3,668e8c16,fab47624,294d9982,b961f0ea,32402b96) -,S(6e8c78a,e81a7ade,3989c483,7d9efe50,51af33f2,b2b2ee32,b5700b43,67931f9a,e5664504,751b41a1,45b5412c,be10a782,7d1d5193,30dd69ca,47be2975,2c291d35) -,S(b8f520a3,10c5b2f,8291722b,1e3a92ec,b9551db7,744dd208,ab4d1709,310a539e,65901c3a,b6712ded,8f66451e,1915113f,a96d3d1e,d9074790,9e291d00,970f3d75) -,S(a0538458,64459815,888bd917,3a2c16fc,ae0deaa7,cb804adf,e49dec0b,b2d8005a,27882f00,23dcc9fb,890dab73,f98925d3,e712608b,3d6069c8,ca58ca6d,de0d7a67) -,S(41280416,aa7f0924,1ed8b631,fc2959be,2117cf03,9c12f600,1faf8a05,15222144,c2fef80d,fd8e8433,ee55c363,c43f7e06,613f354e,32aef8e1,808817b1,af7f58e4) -,S(c4b8ff36,cbf83d10,51d130b7,e3d613b2,8b536f0e,b050a41a,7dd8f8aa,18c7a1ee,87d3c44c,8867337b,466ba76b,47512399,f6cf6c14,ad4977fc,276d67ec,5e7b4d47) -,S(40eb693a,7cb938e3,a6b85010,6b7cd257,1de630b9,86da02a9,3b7a7f5a,a0a51ac1,27b875e0,14d3417d,cbc3b770,c4cb8805,c7ede7a4,efa9f89f,a51e36c3,af6d8d18) -,S(f7491902,54e30180,75365d67,5f2ddf24,ac0c9d84,df371fb8,6e94a9bd,7f81dad4,6a271b36,c549080f,dc9bf1b5,ad275d62,68af0cc7,2ec68c7c,17ac24cd,5c5a6e46) -,S(cf13261d,e4ce19da,14e6996c,97a23f8e,f16388ac,c364f2e3,6a053254,849f287e,5568858d,be1a7447,f7e4ab51,bb872a78,8218c483,c771ab7c,4a0a968,73adac10) -,S(9c6bda62,9dd087df,d5516606,62226847,94cfd517,72c72a81,7263c761,ad3e8cb3,2c77dc7b,9c7fca7e,bb35628e,d62ffc79,9e5fbcc5,e25bb0be,5b1b67a,10c0eb3) -,S(d8d1035f,64439dec,20ecc9a5,5b314959,c1526d7b,d15b1922,bb7ab7e5,b9d26bf3,ab7e34d6,ccfdfea3,f607f697,b941bbf7,b922a436,b9cb4314,3eb1b948,ccdbbe30) -,S(c6f40a23,b8227a60,de32e104,7080f087,7d53aea5,b00a22a9,39cbc228,d1c1d424,e16bc58f,cf4b8c5c,9106f1f4,b8b2374a,63a3136b,e5a8c64d,7fe6bd0b,c1d80345) -,S(3a69da22,9477d3a5,7147c2de,cce22de1,d1e007cd,61d22509,49400b8f,63a43536,c79c4fd5,c4ba6062,c7cc95e1,c9b79cfa,46b98cd7,389cbc39,25cc2fbe,49a0e284) -,S(1b5fb8e5,492fc48a,46b7f6fc,a658f218,814c3d82,90aa339b,7bc7b794,325fc9d,a6290b12,4c9e0819,2b6f49f4,c4935b01,d2ca4235,8efea982,1646fbe7,dc7fff39) -,S(fdba0f02,b004b4ea,dc9e1c37,d1a7fa7e,8a755922,31f054c7,47bbe8ec,349a3845,42da61c9,e96471c2,6fedefd7,e30c43c9,6c3c09d,d72d662a,e2b82022,391646fe) -,S(c39391bf,cb7b9662,be7279f7,6338988,7c166343,2faf1760,f38f0cb3,a35140df,ea14e034,53dc82cc,484b8b3f,ff79d81b,449f9f81,d7a52d66,4c5b563c,9af556e1) -,S(254ff13d,c716cb2a,1ac0e36c,c6cb20c4,19aedd0a,2219321,675e1744,859cbcb,2644cf3,916d26af,9e36bfe3,247f5be8,896e02cf,83eb3701,c400ad2b,92e35921) -,S(24e4aa60,e9b464ad,a2c8974e,98568026,1769d35d,aa7c8c5b,71c9f57,28930474,9df7c2d1,82a94fe0,80a2244b,ccc9406f,6ed37c38,d9cbaaf7,8d973538,e8479f8e) -,S(7ad9bbad,f906685c,3efd81b3,8599fc02,fb19a4c1,8bff1ef8,702c4f6,d17543a6,9878b970,9c4018a4,f713ac8f,d8a533dc,da45e243,44926df0,133aad64,c5246f95) -,S(97d8fcd9,383a8717,e0c9eb2d,f7dfbaa8,c6e08339,be5fa2b5,1d12565,62d8ae53,1879ca4c,f5784f86,7f8363e1,5d85afa7,b1f114ca,7f8f474c,4a2c028f,7c6a777) -,S(3e0fc785,5a08c32e,1e14d1a9,2c56ffac,2af1acef,505ed72c,b8771ddd,8afe7572,6d79b7fc,fd1e8894,f0844fc9,da30b555,bb1768f3,df15a0b5,884e5b09,6e149390) -,S(d9da17db,b132d864,1da3a9b5,389d6f5e,fda483e7,fc7577ec,55b7ecfb,65602562,80e471e4,5feb0d70,2ee7f9e6,3f8f23b0,33a4f35e,8a0841a7,b67f8c63,c623b70b) -,S(1848f766,afcd1e34,82935daa,7b71212b,f38e2853,9d6fb9ec,a3d9809b,6fca18f3,ca9a7882,645d54f2,49d35df6,3748ed94,5f9196f4,a93d4b7d,ee70f44d,b6f5884) -,S(ed3744ae,9a7dac76,5ad65b2d,4fc2d15f,1a9d0047,f72c6be0,a849ca04,497a9f2f,3cf76d2e,d4e5c6f7,e4b23d03,23c477ef,2fdc5248,7066ef36,b763444f,6ab5fb5b) -,S(c4607b73,edf3545a,b10a3a65,e0312707,91212acc,a86226b7,b1ccfefe,5f3676d7,31ad465b,8595f783,d5c0cd03,6230e3dd,2628ac9c,45dc6d77,28c42093,3d7eb3ec) -,S(1c0962ed,2aaf69d7,8b20af04,93a3fa50,bfb9ad1b,64eb0699,641e4b0a,bc0e96f0,49f11af6,e088e3a2,a429c5b0,a87a7f6a,591b5a60,a397c123,2d56a4a,adaede44) -,S(6a0476c,9a41959e,98dc6ca,fb7b4381,82250e1a,ae62445b,1f09a098,ddc19454,56842c97,8ae3c4c9,2c266cd3,7c8e3514,ab4288b9,ccc7e33f,be552ec6,f511c7e1) -,S(24da0f6,53a30aa0,a6b14999,329f03c6,cdb59a80,e9ca68f6,b9367830,a0191f1c,83e79080,aa78bcf5,b810683a,f061c614,cdbd3b69,9e200b53,d1a2c757,2c138235) -,S(6c3483,22479d07,f5871901,3264402,a078728f,227c75f,6f33743f,9a1a7764,a377af74,4a125408,6bf128d8,45bda458,be779210,f0d85bff,eb192c0b,a0dcc4c6) -,S(212aabbb,4d14cb26,b26cf249,882b36e1,1cdc26f4,a1494905,15478f99,d5c43baf,e9140a0a,81d1582b,98eed57d,7ba8e584,11c22ea3,fc265148,ca1d6050,3847e281) -,S(a27478f1,2afca20a,8d46824e,5b0ba272,f26ee0c4,24a951ed,f371425a,b343b10e,51e74b86,a7fc97aa,5a3bdecb,67818d7a,70ad0ba3,7c7cd759,8ec80a4b,bc4036a3) -,S(e1c1269a,7171f9eb,a2e2fa7e,8f55e0e2,b9b8a507,e8cdbfe5,716f711a,572e293,41cfa170,8953242,f98d8e24,2e827684,5562c4a7,6d034848,e639335c,32afba46) -,S(204d544c,19418e19,bb328e1,ecc0fbd8,62f0f78b,24208780,4d5827c0,f5e09efb,c66098e3,1f5d1587,10a3799c,b4f980c0,18cf4ed4,534e49f0,6d057059,93d52fb7) -,S(16eddf0a,11a6f2f2,df230de2,f78b4cf0,980138b2,3ab196ee,361486c5,7a5172ad,e3db358f,ed8ab3c1,9204a792,6102c420,1327bdb4,fb81718b,b39a0ce2,b5992684) -,S(7c9f7831,2298d96b,65e6b7c1,2315379,3df7001a,79cb080e,af6829d3,2b8995f1,2037cc3c,90e3a0f1,b242018f,c53cb32e,b2481dd1,bbb700e4,a6019546,edf51e5c) -,S(129c2d46,1dbeb8f6,c1b913a5,b2d69602,63aee7e9,530c6dee,21168b16,6198fb1c,29ffeeb9,61c027f9,a2a14b72,a287d566,7bbd80bf,7cea0dc1,747ac25f,55137964) -,S(8be2e565,30d4932e,f6d1f9da,a3225b52,de204927,e0633b12,570a049c,1f6175aa,364b4e87,1a130cd1,40007056,e3c0951f,fabfe4bd,6a687404,23cc1800,505510c8) -,S(40b43f08,42ae9c67,ab0ceb62,453b4c41,42a6e12e,5f880c5e,27c90997,6252fa6c,6d1ac6c5,de1b2e5b,b225e46f,2c5a2d2c,248f11fe,d123ecca,4432a04b,cea2068f) -,S(47e2238a,2f34df3,cf1caa55,93c49db5,4c2cba9b,e3724f17,87473a0,5ac669df,4d04cfa2,3ee255f,eca104a3,60a52f7c,acfc6127,608dd908,9399be82,9cf31f3a) -,S(17286c55,3a45c6da,b4843323,84c565d7,b3de474b,5df8ed60,7c7a5c9e,e1cfc35a,6172d347,75a45151,60b104b2,79543107,5b194d24,793340cf,6d8723c9,6320007f) -,S(3451af9d,3c1492ca,d090bd34,45632ac5,a3e96c9,4d9ed258,b7fb2042,8dd7bb31,dd493383,21236e06,e7284fd7,84c1a3b0,7687c513,927cc79a,cc5f8b41,b14974d6) -,S(b00aa481,eccc5e7f,cb5bee2d,a6e0ac44,ed9afa3a,5b2a9619,d23d0252,14e5ce2,687b486,1f0032ce,f42ceb7,441f81fa,10d732a9,e7e76242,4a2ca8fb,e88866a1) -,S(53ec8e9c,c75bc91f,f248a239,34d735b2,ef706d4,c0761e2f,a8a55c7e,a0b23311,1b11dfc0,63c4b1ed,1b5104e0,15d5c5a8,c352f54b,9fd82768,8b5104f6,45d45919) -,S(1ecde1b3,9c072c9a,3b3eddd8,d71e3383,2fc80d78,7abb70a4,cdc9186c,a5efab66,4f5aec7,5a799762,b70cecb1,82049cd0,239f0c30,948a25f3,daae0bc,ae6dd626) -,S(1fe2fc3,702b558c,7ab9b479,fa08efa5,1e90239d,677052e6,5afc8754,9bb1394e,f6b586ae,3a395d3a,c216df2b,66d48fe6,11a64c0c,8a7db26d,30fbd720,c6845c2c) -,S(b53d0b2f,b8ac2ad5,582ba0c2,f031c7b,76e64cc5,28a5b9ba,872718b1,e06d5dec,8984e589,51ab87aa,64bb034c,17d23252,4101577,9476887b,351f034e,92e3a289) -,S(54e516,3bc2366,673fe5d8,1f335d81,a06ca310,a2116ea7,bc0ade12,8f37cf95,f471c826,9deb2c2b,f1b7206d,6e817355,9236607a,4b9930b4,c5b3a781,7312bd4a) -,S(e7efb772,a1d423a2,d39e2224,4c8bab91,3b8087ac,65d51f59,8c4db283,67b29a7b,f2dfb586,31d08b0,bf2b47f4,17f6a18f,704a39a0,a152e3bd,587e45c7,93a9b6e7) -,S(5ec59daa,e8a263a8,2afb4309,79ef0321,b163f2a,dc083e67,3446b98,d0b519fe,2eab4cc3,6a3deae5,30dc6aab,94e5584f,a8a5316f,5c05b04e,84215ea8,79ef82b9) -,S(427b5cd9,20589dfb,dae975c8,efc1f098,1119f69,c40d1216,58ccb903,d4bb62f5,d055e6e3,b8794842,4162803c,35fca878,6500b5a3,6871b18,d9846866,56d1213d) -,S(54954b15,fc594f3d,8f422c7,9dd42cb8,2cc30dd8,c0d10736,554844ef,9d05bcad,86a7cc65,73569c20,2aff8e04,21a00e4a,9c6b88f5,ebcc3975,64b4734c,f735373a) -,S(ff6f8f8d,23670fbf,2a1aa7b3,39568653,573eb480,67a2a1f0,1b55a1e6,b1f32559,7a53f1a6,c7cabc57,d731552f,9fd9447,36cd33f4,3f8f57cd,2d4ac1dc,1ac7e218) -,S(74d725e9,9021c210,e82d852f,41e0cb8a,3bba8efb,8a01552b,8420c265,958a2381,4ee69646,aa9f70bb,883d6ca4,e1016dd9,92f18de6,26ca27c,aeb5854,f5bb2bb0) -,S(e9439f7e,fc0342c9,c2d68fbb,c58d85d9,feca0570,d77448d7,6d3c3251,e49c845b,27da0d98,1b7e257a,eee90b45,9d0d7065,566667e7,a9287592,2031be02,3e233916) -,S(9684a48d,81a60856,6dd26622,b3ffd133,5facb32,9f2c4f1e,2c055cb0,a5c0b911,92038ad2,50adfbaa,5d587c31,f5e7b4e7,294bbd25,e7af1816,1be3532b,f24e68b2) -,S(1d003af9,469e26e,c7f0f121,4dc58728,9e4cf837,5f9d19b4,16277c97,1a0e7609,99c7c3a5,30822c72,b31dad8,146d2604,ed795f1a,7c37e139,c84afe9e,f71e5123) -,S(f96468f8,73cfaab7,76c32fa5,89f72c09,d680abf,c601642d,1c649ca,e197a149,1ffb4bc4,8495d31,b24a7ff3,353857e3,b6708186,c18936e9,9793e4d4,fa083b1d) -,S(b6ad4106,e30294d2,bcac86a2,131150bf,d93c14f6,51ec65f5,32904412,b3f89d32,19a366a6,74279641,d055201c,c4c42b43,4fa40792,90c1c3ee,5db2a4e6,38d228ce) -,S(875472f7,190bf305,9120fec3,ebb69fb2,2d47828,6cb1c108,a977e7cf,e45b9b9a,1adeffc5,f5dc59ad,e15d163a,95f8049f,a172d8e,30544562,50a7898,55a97c21) -,S(5445a9fa,f4245414,e64f7ae2,a1cb1b1f,54bb6fd5,af4a7407,4d9eeb05,9a27a670,496c5207,7da2e082,3e48978c,a3fb7a1d,3bdf07ea,61fde94c,e87741c4,e9418018) -,S(dae18625,704bac88,51f35026,7856830f,74d3a8f9,7c1f662b,f4c4cc3d,7814d138,abc059fd,7ba90619,83988ee6,35ec835f,c20f62fb,c68e2bff,373bda91,3be6f87) -,S(8a088f12,e8523de5,c7ce659c,107e1929,3d009b81,1fe94d02,deeca893,9d9845c9,4251212a,fb8ebb76,5d2d703c,bc18b208,41f8df47,fc5e44ba,ef7b0f76,7e29114a) -,S(d78f46a8,8f3b08d1,334ed25c,78f57910,716755cf,2bceaf6e,c25b52e4,d7af6d01,eb1855f2,29cb2010,f20b3f01,9cbf1b2d,929046d3,242446ee,5c9526ef,5b06f44d) -,S(1e0b4312,78ae0e27,5e55c4ca,cfefcdd6,f589809c,6faaefa8,3ec0d5c5,f99b034b,f38c53c5,544d3ab4,2ebd74ed,b8348503,fb523fae,9d73657,8bba2881,904918a7) -,S(f03155b2,9edb119c,f411f14,4a588f34,ab02d7f7,c415638,cd534465,ed7cbbd1,72d153e3,ff4fff14,b41d07cd,31960565,31736749,7f9c6495,599d3f06,b8e85813) -,S(f61fd68,3edc7fb4,d14c84fe,3416654b,8df66578,6d0bab41,53a96e39,e5de4c8e,952db567,cf0913b1,885d6884,d260fe4e,e11fc139,f58da12f,d38472e3,d42e5f92) -,S(78310e7a,29e437b2,5cb00e3b,13a4d86e,1ede6d8,4b1f344d,7ee9c7f7,e017dd77,26ff358a,4d5629e0,4c20f700,97c202d4,7030bd3f,43134a51,a7d101b6,e182f2d2) -,S(63ae8c4d,6b7329cb,a61509c2,d0b61ebf,4e6ac94b,c8a096b9,7a4027e1,1f781a3a,a8e954cf,bf407857,d19629cb,338a93a1,af16c929,ef8b96ce,2e483e95,dcd14f88) -,S(948d592a,594b354e,e2d03961,6338574c,ae662f26,ff79afa9,16579725,7cca739,37ff98e2,5ea0396e,89d3992f,773bd6d5,ce02758a,4ee25557,edc867b,2f1876c) -,S(653cf16f,a3140368,50b04de1,8bfee880,660a4161,4dc67a55,398e2d34,46100f45,acaaaede,5ff1e552,6766741a,ee43105b,ea4d3419,3e615c36,49c1db35,125a9202) -,S(46fb6882,8a5edc8b,f24fd1ee,e6a7789,141e1888,64508d2a,f3c511ff,8e8cc782,9d4ae53f,d52ce9bd,6ac9ff4a,e82c2e36,f4d26698,47ec90cf,ef383e01,37fd8887) -,S(5f11a0c7,23ea2a71,7c1face2,b4b0f28a,4ca44208,7a2ae0ea,e24c2005,7138c0ed,5ecaec84,ad97612f,ba7925dd,f126e4e6,3906eacf,6f991d5,bb273316,b80c8452) -,S(b9f49e1c,929bef7a,6d6b6b3b,deb10890,dbf2ba3b,3eba62c0,320bdc84,c2a9039f,98729e76,7e4f8b7b,bd0ecc1c,534aa030,6e1b684c,6f42d15c,2bf6820c,b501e558) -,S(ec8a102,e7d2905f,f273eea7,6c9a4608,965dc2b0,3631d2dc,63c38e72,15ade2c3,d8c899e7,242d96cb,49383686,8f671612,706ffe5c,368ccb6d,be5a3edc,f74371c0) -,S(107f02b3,c351805a,6c92a3c7,742a5259,582c5b0,39cf6daf,cdace604,2be236c6,517236bf,1ab47601,57d74685,8dc724a7,c5c2d55e,82c4a3e,685f389c,a99bfb9f) -,S(f0fb14a1,a5c1c016,d7b8c1fe,a8317872,b10d637a,daf6f6cf,b9860653,56298971,e1d9ed14,d33e65d,4258e87c,7280001c,c40b89ff,b3164337,92fbc547,964540d1) -,S(a5371adb,ea784ede,f6cce83c,ebde068,78a1c80a,ff83b47a,333f9b35,44489459,f5780572,127f5d74,773acbe7,b2a22cbc,7e3d09bc,ccd13edd,48ece3f2,c8129224) -,S(3c031e5e,1b0ba576,13c10971,5fa7d92e,2bbbb817,9603d3b9,99e4fadf,be17300d,d275a3fb,392036dd,474e65a2,cd7b6cc4,79cb40d7,1c363e6b,bf9c272e,ae9c83f3) -,S(87b5899e,685db530,a0969a68,9392080d,f8a1b9ae,523ce18b,2171c69c,5a5318f,6ae3204,e3f0afa5,a2d40b01,a42e84d1,1b1166fa,f99cec08,1f5af48f,fda775d4) -,S(d9f077dd,c002c16d,f9d8eedb,56b7e7b1,ea00d04e,3fe838dd,2ae40501,9b8bf74,6518d51e,503118e2,53cfc486,f70cb9ee,11c27302,ee5512f2,78f21265,af3ffeaf) -,S(9c09ab63,8d15acc9,609ce305,32277f63,7558a492,aefb98e,c9bc721c,f8921af7,b2cac58d,535abc10,8bed6ab3,165225f1,bf2f84a,9fbdf3d9,1caa4b79,e0f6fc) -,S(6ed1ef8b,4c2d9232,5cf8948a,5c369a24,52ab250d,ed0e48ae,1676dc73,9a8a7fc0,c1b7a08c,2cfe5154,fca74136,863da75a,5c6423bc,1c904585,f54ac87e,f6742008) -,S(882e8d70,154b7f6c,279f71c1,e2ba6087,cfc458a9,3079d8f1,3fbd3be2,506928d1,8949b22e,97c41872,9094ac62,e67ac1f2,8b31565,edbb3d1d,9b23a73a,6fe64131) -,S(708472a0,24c86ea0,7119d0af,b2509814,516840e9,fc23246a,a6da139f,b37aba52,9809b7a5,1d551532,a5b378d6,594a3665,3a8b057b,80cd530d,b7a53fbb,128fe5ac) -,S(3a44fad5,9a8b708,4ada1250,d8d08353,769d573d,71a225eb,d87a8cc3,af9fac3e,f29f4551,1250d0d0,a1974bf8,46124813,f9186e45,2d3c5c85,cb0c69fb,4b7f20cd) -,S(a3519dd8,e09e1bd4,160564c0,41c23362,36ba4c84,5899f90a,fcc370b3,cdfb9f30,64cff159,7c910711,d0199faa,6c74d08e,7150088e,34fce674,72dd3ec6,1b881d7e) -,S(5af16ce3,765f5c96,4eb3513f,19d99ff2,bea1affa,d68f829,1c4f0767,5cfcf1dc,864eb5,3bd711ed,4a842db6,b0164a78,511ff7b8,a87aa3dc,1f2402eb,a3815daa) -,S(1ff9a522,19cae5c2,5de1ec08,2641040,18848bd1,37a5949b,4021c2d0,563d54a8,546d634c,122276e1,b5cfb919,a5374309,8f85d7dc,149b14d4,791c83b0,1718e031) -,S(d7a6dcad,72a51ed8,f84926eb,cfab368c,7f02fcdc,aa66482a,c6b6dd6f,43d3e938,9a273cd6,3ea6ac86,5a68f378,e4466ae9,8598a058,6c97278,bde63b22,14e41c96) -,S(154f63e5,5bdccc7d,a696dfb5,2b6cd4c6,3c874b93,1f221282,3f4a8d19,1f32d797,e98f9722,17bca1c8,ea7269b0,d2aa6bc6,f0f29d7d,b340c67a,2df59135,77f76fae) -,S(f6ade08b,8513615c,ccd29095,c21bbdea,dbdbb7da,87ce9991,c27ec758,4c399bf1,98c81be0,19fccaba,131af074,b28a6311,3fc1c5ca,1318e96a,f037ad33,8f234ad1) -,S(9661cec0,3b2715f6,c6d29048,65fec2bc,b786b3f6,943a883a,3e51cb2c,c747637e,eaa1f7d9,9b34104b,74a8056a,9ec739f,cb9c3735,95f0b254,7fe75620,4f5358bf) -,S(e0a5323a,27d608c7,34c03465,f03705c3,480520cc,f5ac777f,53d498b4,655d19a1,1f727d78,a8b8c562,ebc60679,8462975f,63d88eb5,8e7cbaee,836bd629,260cc606) -,S(bab82efd,4646f2,f281980d,5250c6af,8206e95,dece4118,c24ce31d,282f6409,2a60b1dc,26a20126,8df8375a,5656c55f,cafbdbbb,46b7977d,137cd584,8d1fb82a) -,S(389e1399,ebbe958b,1806e9b3,ee51baef,2d7edd20,79e6a2c2,21e814ad,e1eb2631,6c158633,1f3cfe45,9e71fb4d,112a624c,e48adabd,435e6fd5,2c9459f6,ce9ae2be) -,S(b78179ca,c0dc553d,19f08174,7fa4511d,87d8961,1ba44045,8c307727,729d4515,7020be98,c496a50,6e4caa5a,94577d71,ce0a80c9,bb974c97,a6892351,e83e0de2) -,S(867ecd3d,d170f9a7,123d13fc,fd90058e,baa6a6f4,12ecadc9,f1e14d55,ff104306,3c0db3e1,bb91ee23,8fb27689,79f2b543,d698c5e2,fde48dc9,e2535e4a,946759bb) -,S(be71654c,26a1025d,41fd4d08,384b2ccb,db25bb2b,c15704e5,697be2f6,d4eecd38,316ed20f,c37a2dc7,a0af8d18,e4da0efd,2dcdaee4,44b2c1df,cdfaf6af,49406afa) -,S(5a8e1cb0,24d62685,e755b9a2,ad1e0165,41690544,7963dfda,6b6deba9,76e9079c,4c793173,743330de,7a8f4351,68dde95e,3889db2a,91de0a27,d088a222,f11ebba7) -,S(3bfad00b,2347bd0c,f13a761a,d0630453,bb884d0f,ae3d31f8,57216412,b82e6131,ef33c560,94157fec,3f7fe8e6,36d48183,71e3cbab,6f5b0518,96ebdb42,aa545f61) -,S(2447ede,684dce09,c896c2d2,b5c68cb7,60e02635,3b4f2dc7,428191ef,5d2c1961,ad38a82f,e80f860b,62b39e55,44438242,5ad6cb54,d6e7f377,62427f30,1ef7bfcb) -,S(a5eae321,eeb4b9f8,e8807e49,ba8de764,e7685f07,417c5239,9d857d4,8bcf985d,2acf8aa9,f5c1b7d3,2ad5f523,39e65595,17881d,48a7696e,ed3b1023,ab4def1d) -,S(97de995c,5337d938,3cca5b97,3ab05e8f,dc035e11,5c435251,7e575a,e890b13c,4fb2d969,2e308a29,34c3fb4d,c4dcef50,9202505b,cd891f79,e8f91210,e069e6dd) -,S(b8caf25f,a864918a,f803dad8,d0abdf95,25b70f44,546b1f3c,c6b1726c,4438f479,7c51b5fa,c0f56eb3,6ffa8c5a,76c074a,c30e2f36,b069ed79,23663da,c9c05c9) -,S(b5bc868c,1b96e2a1,b24f3001,af140107,b2cade8a,5b1f3443,44521764,ad07b2e6,8d6cfe29,4e929f33,d5aaa456,f545c33b,672a8c07,b214a6f2,38bba367,4938d639) -,S(5f51587c,242a3b22,10db666b,f2414c28,32ea2662,1f13f6e9,784a8a1,373ff602,2c3b260f,ebf20a4e,b853950f,99ccbb9f,1b39418a,66adb427,f5886944,8b46c858) -,S(1d0be0f9,5009a2b5,12a52e17,e044f3f7,4f08e695,60d0dfeb,822b4674,7a2bcfde,c3a82bc3,dbd81877,3783181c,f7b81ddb,a742c3b2,4f866538,9335ce4d,8f3a159b) -,S(3ef0ec28,b8003331,a6621bcd,6ce30ed2,9e0e62d5,b492592c,cecaf4bc,8d22fb8a,fe2c84ad,77d40e86,c92a03da,e43cc7f7,512fd363,98db0133,7d929ba7,a144b16d) -,S(84c29a24,a4ec04da,c76bef42,732a3648,f62f12b0,e7f0ead3,2ef9649,b7555fc5,e7620ebb,283a54a7,10eb454c,f22e49fb,929ec453,38e457ec,b18a7f0a,794f970e) -,S(6bba6634,e75d5fe9,21f40f4e,5f1c177b,a309cd73,107f1e9,28331573,eacf43a8,33ffe08c,42168243,1f086b44,12209c56,5b47fdea,54671a97,9d86be36,fb421582) -,S(13b67af0,51b0c01b,c49a6046,d9e5b6ea,488f6298,9559dbfa,47cf1674,6def0150,d0e8914b,1c1bf0b,5337cc35,d84acacb,a54add59,2321509e,e29f1d93,a0237608) -,S(161221bf,b5dcb62a,ebeabc94,6ccc4a26,fdf779cb,63640720,2c5cf13e,93af9300,d3fde2c5,dd9d6df8,70a66bd3,2b5213c,d1a212db,61aec7b7,2a49b7e9,2cf83b2c) -,S(30c5360c,c62f5846,3af60277,2b52201,7eda1fbf,866dc3d3,9a590bf8,e2eb508b,c8e91af5,9b9a2b,8837dbe8,edeac615,6c30e8c0,1b7679f0,1aab4a81,cac44efe) -,S(c0659a7f,dd9151f5,ea67f38b,7249727e,640364f0,87371007,a38b800b,ec3576,a6f648cb,6fa131c3,5458b5a7,77440361,8c57faae,1ca33ded,648f1601,a5cf47e3) -,S(3215224d,b795a892,446472a,8e1ab1cb,7d50fe95,a6844be,43e2787f,2679386,25750662,97f28d86,690c7eb5,92cffc5f,faba831b,efc3e38c,c5e501f9,358a9bf0) -,S(257654e2,a87a7048,3bd15445,da5c554f,fe776264,998975b3,b19a68a1,a1871145,fcb9319d,c67f14f,9d7fc4ee,fca05b18,9efe2430,96691043,9c28c88d,32636ec5) -,S(a4786a01,e504f154,f3d7926e,6e6908a8,17c8a66d,6db33e80,ce98b17,82f1b49,576e4d42,fc2e4f9f,e81a2967,8b7cfa7a,7f86e8e2,662afbfd,b028612,d323a2fc) -,S(5140f7a9,260c9856,4493ae62,a8af369c,90b484f7,e82e1e38,3c5a59a6,62db1e71,4e5172c2,b0879dfb,63a6aa92,cebf9153,94ddcdc0,985261fe,2f64714d,350bae86) -,S(f559d60c,f0f50b7,9c7d6d90,18a579d7,b781fe13,5210d342,31e6cf32,4ca66dfc,12d9ceae,8e5852a5,ca95fb56,abda8e42,5f1f05dc,ca29e08e,2052bab0,8d4eed15) -,S(88907ff5,fa2d01b,c970e0be,53a05354,a4fb73df,9a337857,cc869a1,b0547e7c,f5853b56,cc1211b6,427145f2,6fca6aaa,5b26401b,c00db73d,ab9157b9,7fa3d2f5) -,S(cc1e4bf6,4541506d,8e91fba3,1e1d8ffb,c8ac82f2,4def27ec,fe4b3ea6,e58c45ca,7617497d,a875183c,684585a6,306956d,1efcf1db,2753fb77,5902a63f,38d27592) -,S(7ee2c437,ef744210,5b6a6f9e,f1edde01,6c39557c,93454dd4,eca10daa,cbca99d5,21754734,5eeff5d9,f30503f6,9515da57,3e6d7b70,dbdee5b1,8274968f,6f3772d6) -,S(72feea2,39f9b4a9,a3f3af3e,f6bf420c,3605ba4b,b42da90f,6539e05e,33e2465c,a036ff,df7adedd,c8c2ad9a,d029428c,85482cd1,6b0cd20a,36d2aed9,e9f553cc) -,S(363da33e,94a0dd00,669b627c,4d7a3a6f,c8a0cbae,2641707c,938c8f5e,99914a,9bda9a77,ef1307a4,e236099,c1506f47,a2f936dc,d478b59c,3d0e98c0,7af58bd9) -,S(76540864,c8394290,9af4a48b,bbe05fdf,93af0f8d,1ec9b6e1,a7e91860,f2c133fe,f06923d7,738ceb02,2213a236,daf3d6f1,b3cc98f5,a5ed4845,83ce5c3e,54a3ecc2) -,S(573f0821,7a318a9f,8bd945c1,62e9a4a2,51e38189,34709606,c94cb401,f2b239c4,7e78e4f2,7de69e4b,948b105f,ec3ebd14,496cc128,d7c73fbe,7ca1d53a,b746bef5) -,S(8537981,89234b93,b5009656,f57e5ed6,f90d2184,819a5467,213a934e,22b01f5f,c94a79e8,cc990998,e1c69bbe,89ccefa2,9281fc0e,c99fa820,ed26f01f,62e475f8) -,S(53388512,29890336,3b1ccd4c,1cf0ed85,6f00a30c,78004512,57f6132c,edeb6041,d56e2a52,f856d1b9,a4f8feac,dbc9a844,dd22f55,469bf722,fd78b44b,6983334e) -,S(41ede48a,750ef7b6,5c49f913,afb98961,c5cb478c,39c4c85,2f33aaae,b0e4796d,d74c7bf9,4b6c4680,18892ea7,f04b53c9,4bdfe9c,d1a4c65b,8de2409c,32559de4) -,S(97e931f3,6596f736,992eece4,eed6a9df,fe762139,3acffeef,b6dd3b53,e5f08148,3da89933,53b9c52a,9e76ce7,7404fba4,39a24614,b62d42c0,9b660e2a,14dd5f1b) -,S(4caf4eea,3ca8b104,39847633,5252b37b,5c55b664,cc4979a5,4db00937,b222579d,c266732,a93bdc0,7cf88580,771d58a3,45a19100,4c0d1464,62171cd6,291607bb) -,S(857c1e90,5b3483c3,3ab24ee4,e51e3839,b52960f8,21a8706b,b7ea7c84,9e7b1ca4,8d6e9d0c,7a578771,b358380c,4a2e6bc5,1c6b09fd,e9b40c01,be5915ba,fe69dd80) -,S(410ef70b,e0dbf7ad,a68fc124,8dcba3cb,10ec39a4,9686b22c,1e7ed2c1,bcb5a182,d26e9ea3,331a56f5,cef074ae,e0b4a5c0,e6925d79,808ffdb3,b7cb9423,247f9e94) -,S(8caf87a8,c831eb10,817e5ec3,7aa431a,89dff6f9,a7e63f7a,30710419,5751029f,3f0bd6e1,c8dda6c3,c8e65ba0,7c3a4649,13aad207,3c5da058,bfe90872,67c8890a) -,S(eedee2cf,e92d2483,54a6a8a3,9d314fb1,b35ca18b,ffb9b779,8c16d5fa,fef10e8e,cb515ab0,21f0befe,4b31181f,3f9ce1dc,9fcd12c9,6793d624,c1eb35aa,e514c4c3) -,S(8cbf7ac7,1e77b7f7,7bad6a4e,9116db52,48bb2a75,744d4312,f02eecaf,2aebcee1,765c4b31,f67b26b5,3d17f97c,30d09636,b6f6697f,db6b799,169a2c05,779b7320) -,S(70cd45b4,cd449aaf,34ff0627,f0e01122,715dc6cb,98642dfc,c19fc672,54995db2,82e59456,761497b1,84320eac,3ada16c6,ee184ad9,10b60c41,20f0c538,2f535c8e) -,S(cfe217f9,783fcfd9,1e79d558,e37bec3f,50e5146,e0f442ea,702fdfb,6c7c45d5,537cbd0e,86453fbf,c57d70d8,78c7c3ac,da225186,17bb4dfc,7b6f7079,95c419d5) -,S(9826c0df,6486bb8e,2bf3d4f7,4cfafa71,ccabd2cb,12bf317e,651790f,48579d52,3dbf3586,f86d6253,d3749c05,2fc36d16,ae3bb457,8d4eeda7,34f172dd,b9c57342) -,S(ea18fcef,381b4bc2,c6b3fa3e,3744e9c4,a13e13df,576c8e74,d0f4f596,e28a02c4,c3e6bf9d,2bc445d7,87103c7f,e595a30a,41c9aa4,c41d1874,d7ffe69f,ee09f397) -,S(6de2c465,c09d5a54,61c618be,c9c16ffa,21b82e5d,673033a0,e88cf90c,fe6d8f4a,367acbd2,8950882b,428a8199,d3b21f5b,e1c4ccb0,3280bf5d,28b65cf2,bc4ee2ba) -,S(d6286e13,ee10c7d4,5ae50f80,3d1a5417,cecc9c68,9efd2847,6ffa73f,1a183f4e,7ab92bb7,55204e89,c7e3ca41,1c829e41,e965ab93,57db88ad,37f13e93,6aa56f56) -,S(7526e6fa,ea67460a,25525962,fdb6f209,73f0c861,ef3c364d,fce83df7,23c3bf58,2c76a8e0,d5a8611b,d3274411,cb323751,25a21fac,12e35ae8,f008f48c,18e3a674) -,S(fccaaada,56d64a3d,6d1d5d89,719f51f6,e737c803,893e8b2a,b785070f,8879308d,8262c566,3facf792,efd750ef,a969fab9,a2ee95d3,fe6e7d7d,8685c6a8,479362d1) -,S(b60d13b8,eb8a5f43,cc448379,7a397847,bd6d91a8,b3a6888a,fef4b115,59b57fe3,abf73ebe,5d2b8585,76104acb,ec885f1f,8405b053,3755b8ae,94ecf838,60ebaa54) -,S(332d4b0f,4a0dd872,ffd6d2c1,4379f925,4250fd66,dfaa2d90,127e6ce8,c377f8be,37f3143,47c2350b,f4333d7d,9e0b17eb,110dfacd,d87ce354,b7887cf3,1bc6232b) -,S(e99b2ee6,2ce6d633,1e0e880,37bd138e,5d021620,b555b94e,52def87b,4cc5788f,c9ea06fe,dabcca9f,6df1df26,8bb3e550,e2858dc2,b91a7c6d,2c048416,4e5546bc) -,S(89ead438,2a977aee,7fe692a1,d7199bdc,5af24191,e80573b1,dfb056dc,49c54353,b572ddce,db2d776c,2a967f70,6b7010ad,7fec43b,ebe5f19c,2de0f9af,d9994ece) -,S(cdad98e,529b413f,b46f6fa,98c74058,4777baff,b090d488,59587b4e,d598268f,d405a95e,543e639,470f10db,821f8786,ceabc281,788b0cac,3efee830,bfed034e) -,S(5096ef41,1cc1332b,e67f69ad,3cc3140a,c269849d,5e0f4f5b,e41290e4,86ee2cc3,7f33869f,ccd4b06b,ed61f312,30a7b3f1,49ef34a6,f2d46bb4,18c45343,73f8268a) -,S(bc0bea70,a0966734,8607253a,2c8be987,8c4d59ed,638ecdbb,8b9f60e2,a4a5be61,e19111ac,3c2b4e0b,4a86129,e6c4c275,54d1ff0,29ddf320,873e20cd,16873b78) -,S(2d166569,ac8f5a08,e0674d3,8aa7d747,b024bb8a,5c8407a7,dc451403,87223ec1,48af1b38,62216a5f,12a7d92d,4eec4e59,445c1587,e22238f7,3dd1bd77,e19a597a) -,S(b8cbcfae,bb8b1150,ddce37b3,26ec77b5,2947cddf,e3cf1d40,f27e8b7f,8145ba30,d5234cab,8b2ad2dc,8630ec02,2868a1e8,ffc2c3fb,cd5f5a05,62b6fddb,34823ca4) -,S(fb396092,563f12f4,ddddb9c0,f1ac19d9,fb2e3ebe,608eea22,7a9aaec6,dc960ee7,65e565df,fda1a394,3d27f661,c2eb01e9,646e88bb,6943953,58c9e62e,c9823c45) -,S(1c6e9d76,b8dcdfa,90625150,db2274b2,f8da06ee,21000225,80affa54,a414b297,706b450d,9ab0b0,5466edcb,bbed8b10,85679fb9,78d74057,607bc2ef,a5666255) -,S(2e043dc1,46ecff0e,6e566b13,d985cecb,77f55a0d,555e0277,dc660351,b9fca1c3,1c4f1ca,f75ceaf0,a051103b,90a7abf,665da500,2aac4e14,28a71e45,726d8398) -,S(5ae17b0c,a1bf8e90,e663ee12,d97d7855,9549f9ee,2d89592c,b4b0bc9a,585f482f,bb0df734,931700bc,73c6966c,1e8e5a77,a71806ad,88d731c7,16f236bc,b4fc8111) -,S(fa8bf342,6a24c3e5,d3c11c46,e75eda94,fca910df,c906a71c,1b08f468,a7caafc4,ca69817c,db07fbd9,e35e6c84,65b3cf05,4e2884f9,e57c0043,5dcada4c,2f5954e2) -,S(2cdff1c1,846dd7f7,b9df67ae,a3f4394d,1e1031b5,de7083cb,f905afb,991a88a4,4bbd724f,3827e42b,7d0530fe,de304711,6ea0d88f,8e564d3b,507ff3e2,ef76f39e) -,S(6fadbc00,55ca49ec,afdf82b2,96504f89,c5bb8291,ca942df9,5f5b3322,9d3b6905,f7671184,33a8326,a56f9472,8c411917,911a3053,f593e868,c06f57ef,54b7df62) -,S(c514695a,2f26aa40,dceb15f5,5d5ea8d2,6f4a1e06,12591fca,2f5a00e4,b8dd0841,5056ba08,2e78b06a,90937567,73fc4ef1,652905b1,16d8fa6e,8005283a,b113266c) -,S(83dcb8d4,93474f85,54c368dd,3e188c11,aad758ee,fdd1f064,66c11e16,cb7ff933,104e5b3d,4e57192,7c67a029,e119e79f,d6ed6fb,e61e288,e9f8bd84,630a53c7) -,S(bc65cf8a,cf9a0b26,43b69089,565f9a9,5f9ae882,2e2b1127,a8bcabb1,fcc8a93f,fdf9716b,a31ddd06,a080ac90,f6699b78,23ff28c1,155a79c3,ae9c292a,14fb2143) -,S(48778fa9,520b12a4,12d74b47,65ad37a2,695e37d6,4070d53c,1e09cbd2,4c9f140b,cdc64805,bec15940,387b4c02,bc51b469,446dd3c5,b2e35b39,fbeca21d,769c373e) -,S(9db2c42c,6a735886,8edc8831,2ed6873f,28077bb5,32d186e8,41f67ddf,a301dc25,e01cb235,ec9db45e,e1193e06,46a325b0,aa0ac5d4,786d0ac8,56990262,bfb3a0dc) -,S(cbcff58f,62bf025a,43a1ef44,256b27ff,37c6c8f,2496d2ae,fb280734,9cf8da6b,4fd99ed5,2da32753,3a9251f,e1e136bd,28f5331b,c1101da2,818de6e5,3bb1896d) -,S(9d520b97,87e68c45,817a12a2,93b1df96,70cbcf3,91788270,93367253,6f4f3639,615e115d,2b539895,d91885ca,a325625,41fec07,9d8fb6bb,22d9ecef,b6bc0f14) -,S(c648ddc4,57c2bc,bc23d182,8cc6d6e,4b0bfd3d,f83b2e7b,3ef6a341,9225dbbd,ac9a863,38dd1966,9bb47e99,e67a3d9d,ec16fe61,dc17ecaf,209a7fbc,518ab3d8) -,S(ae11f835,ea96f767,afde3f1e,79221dee,b80ead29,7b45e29a,7e596461,e82137dc,20453bec,b65a62f2,8996e1b5,f1953acb,4c5dfee5,4e5f9a15,c2a2178e,4c452596) -,S(a35549ad,56f8a64d,d23b9293,d8ef5128,699f6fe,365c0fec,29280d0,a364d46f,c84041cb,a38c9981,3015ffce,17ffece0,8f55a292,3c64868,f11cd6e1,bfbbe75) -,S(75877029,af5575e1,8dbfaef,37dac89a,2aad8308,d473a64,9c347097,e35f8077,843b0497,d19851bb,ed243762,177cc69,603cd674,216cd65b,2e5a85cf,5fc2b8b6) -,S(44ee3168,ca7ffd50,c467b1f6,83e532c1,ae00b9e9,f2eb1ca,917607fb,32d4ea99,10a20ea8,120b5a13,beda9f9a,9110eef,22564e3,9b96c141,1e73eb7f,c92c3270) -,S(9a013c89,8dafaf0b,90678f92,f3bb98c9,461e4595,42cb07d6,477b6f66,7a5337d4,11f8485a,c96623a4,e6c9b773,f5cd9fcb,fec396f1,ff53205e,8774ba1f,da3c2a73) -,S(b45e28a1,44d54182,20819a61,5f50b349,3fa12d17,2b8b5bea,83e73d69,b6b47d5c,d987db83,ccdacd21,dfff1dec,43997253,fb1c2092,95bcae4,5b76c306,92c29f4b) -,S(9e7d6a53,49845888,a8865d07,310192f8,9a659205,1d2a603,cdc03d35,a641a0c9,ca1774ed,ace29fa7,f57e5690,b4d1c0b2,ce5f1fbc,b21fb323,3c001498,54f462d9) -,S(113a1429,be1b613c,567b306d,5805c163,e433a940,8ef14b01,b9afea43,54991f47,225ee5fa,6d26cbb8,49191ec1,a51e385c,321e801,9152a3c7,50014567,7b928697) -,S(32ec8dd1,2cf85df,931e2597,f6b005e9,6d6eb0a6,d0dd7964,77655d71,418d9181,fd718dd0,78b3e4a5,9bef7f4d,9c430764,3423bc05,e1aa22ab,dd7bbb,aff9d8b9) -,S(ada43267,f2cedae4,5e1a5f1,46151f89,b145db70,ef477865,b1218e91,72e9246e,d148bee0,4d1f4d29,f9f15c57,8b047469,16e39686,c2b2ca54,1f3e0d4b,247cf82c) -,S(818a0abe,debd74a6,91fe662b,edba1a52,65f5ca07,2017c6bb,bf7b9847,95bf0cbe,e7b2d06a,1872c73,6988da9b,ce273b7b,ac0f03b,90903bc8,da719ce3,89c0a53) -,S(2f49eb55,ef77da10,804c1a1b,f596f09e,ae76026d,f2d12f14,d80be810,7d0b3c94,6a225810,2f1118,eb689aa1,e6d4ced1,1a79036b,802caffa,5694e383,3e038b83) -,S(7fe54d70,54cb025f,6bef8029,bedbd15e,bf66d5c7,986c678b,a5cc5353,7afaf74a,fdc617ec,72ac6632,6d16afb6,69188554,a47a82fd,db757695,2296c10,b4ad89b0) -,S(84f59366,2b8284a0,c9db8675,db9c55d7,411ec9ba,deec1319,56aa3f75,8eed2689,836e65d9,6bef6ed7,825119c4,c4511c89,48042592,f41eddfe,4de98e83,acd0d88) -,S(c90aa830,1a84820d,e06eb6b7,1ccc9bfc,a46b1612,5e2b5f52,da0a6fb5,4185ee1b,ea86d7c0,b285d82,9331e05c,d99c58a1,cc213449,d9226efb,16135237,f90dc8df) -,S(ffb4d576,abae49be,69f047ef,636142a9,8669b2ad,9cfdcadd,c057d96e,192ef100,3740cd14,b2d5e018,33a700e4,c80f6a8d,3d95966d,a5238120,80a9101b,b7ec6c7a) -,S(408a8d89,67ad6bcc,eb7ebb61,89afefff,12c24b5d,2c33ca3c,8b78fca,cd403de0,3b761fa6,378cc42e,a28fb66f,f1d8171d,4acd3557,fd6313a2,cdcbce47,e1caecf3) -,S(580a33f6,153109db,fdde27e3,f1b0ab04,6c80c04f,18326712,3e3482e8,7c53b787,bb8073c3,fddc81e0,e99ac5ae,69702ff6,f70a33a3,5639add8,1d353c0,e428431a) -,S(2d310a94,7054ccca,c46b1100,88349ad1,4c7860db,38c698c2,505e789f,8344130f,1ea2069c,3c6ec90e,9c11be0a,913d90e,2df1875a,2e26aa9a,5d28dc81,3e3db697) -,S(2874282b,e7b11cad,3f22f2e3,ab835aed,5d82b424,24697b32,985231f8,6a7aa450,286332d,b2e1b922,222e3860,e41d90ba,cf39ce03,21f26b74,cfa23171,f0415c42) -,S(af9e779f,f77bf3a0,10af5e41,82b77981,6940f85b,9530eea4,8b36e401,eb6231cf,9d3d4350,dbaf15c9,269d958b,86d6b88f,4deb7083,ab1ff389,c13f7541,98e84c67) -,S(445edb8d,515ca735,26fd2757,73b2778c,bc93ad8c,a661b35,4471d035,688c1ef3,94917a3c,fde762f8,3b774361,1f36a13e,e94b759a,455382f5,55d64f25,7090dc49) -,S(e010c20a,370d5306,f89993c,f7ec34d1,3e76feba,2b6612aa,dc75012,701811b4,cb45172d,280d9be0,52d57a21,4cb3cc47,798a6426,f215e3ce,e3af64ff,106fd8af) -,S(d34277ca,4625c7e5,b1134080,cfb44cd2,ef548b3b,67bb73f9,eed42352,ae5af8f9,a35f5779,7a628f7e,bb37bd60,9e3f44ee,c391909a,ce27ab44,1ece58c8,d7e4a4df) -,S(be0b9399,3bd54241,b684977f,ea4733e3,d96182c3,c9fb1c5d,d665eeca,cb1d628d,37904353,744ed26a,df76272,8ec41898,13218b0f,5fb09da,dbf5be84,fb7fdb8) -,S(308295f1,ed4a21e9,1ed9f48f,d6b42829,edd9bd34,e812f09d,c3b2c319,fd8f3980,6835c34d,5c360e1a,49a14c31,4ee4cca3,797d434,897c4181,a8ba5d7e,aeac0230) -,S(66cfeb51,61aa879d,fd791604,e10f5fa5,c2e07a5e,66a37b41,2b88db32,dc495b1a,a0e07a9b,f8a2fc01,3e229602,b483bc26,5ffba9c5,fb6ebfe3,f9ff9c9b,3252a1e1) -,S(f42b8fb,849cea70,4cfb3d9d,334a4a11,bf7b3aef,9b55f648,ec885a2d,6fe39ba4,b60621e2,a36d4aff,9f75db65,dd381ae1,f5b0fb4a,bc9f19a7,36d160a,61e8b22f) -,S(429c1785,22906323,2ecfdc46,2666f8f4,c57b7fda,608cc8e3,85a31254,bfab034f,e190ba59,1a868f57,40bbfcb0,481aa04e,50b3969e,abc941f1,8e69816b,2962af35) -,S(c8939d7c,94789a0c,b95e4237,fb378ee4,9895b985,6fc67d7d,fafdf7b8,debf611,143aff62,6e94617,c36d05e2,3062d2d4,47feb77e,9b15e2b0,4370f81f,1cad3682) -,S(5e4155bf,56303243,24e15ae4,142ad81e,2b82aeb7,8dc3ccfb,1d36f3cc,4398ef94,6801f527,2325a3b9,a9f3807f,216d7425,b9083364,203f3b75,ed6f4ff5,eb5da55a) -,S(1196b198,53f093be,7bbfa851,a7114e23,eb01c530,6078965b,5e9dbd3f,8d1b573,794cf0,54bfee20,d80dea44,d183db44,fe79dced,fef0a97e,5c557fd2,bc628795) -,S(d818d920,74bb737b,7db8fcd0,168030e3,39803e5f,6b76ba1d,ea836ed2,c73a6094,6ac7dbb5,1f63118a,80cd2aac,fb5f086e,ff15d51b,fb4ccafe,9d96f179,176e504) -,S(c0276b4b,f5ccabe9,ed9a433e,eae5c989,7039042d,b273ed88,51db464f,b06c6204,489270ae,6349ac81,d481a582,a8581520,972593d4,9b3facc5,fd52efca,24f4756b) -,S(94b2a1c,ca23cd30,eb9b300b,43d0b24a,b898906,1c4d8a7a,d3343d7,cdd83307,47c5ed56,b709bdca,5b960801,58338b9e,e6e74683,99a50640,6075302f,9e481df1) -,S(f2aee379,df2bf54e,e4a1c385,c28fb64,9f157d2b,d345995a,66868876,ae7d5108,ae766bae,9c90a1f9,c9079d35,1676eefb,19a7bf8f,bd56a311,13f2dd56,35c8ef08) -,S(fc8fe44f,3dbdc4b2,afa9cd04,3601c6a9,e81e4da0,456ce222,8306bb85,ba9833ad,6a321b78,a98f52d7,64330a52,ea5082b9,2b07655e,ce8c5094,ce307538,6d56fe15) -,S(d38cdd79,19a4f3cb,fbdaa3eb,e2ddc10d,7444d04b,5830eb7c,5b8b464e,4c255c14,6a0f1ef1,823a2fdb,94a311fe,cdaebe7,e1904095,1ddaae6f,1a565551,2c8c15fa) -,S(ac02e6f6,13d8690,d0c71943,a26b5e9f,916ea119,d7773f4c,14247538,9a4b41f,eadc499e,436b4eab,bed9c5e7,68fd2f67,72659819,437708f3,99531ba6,c05ea2b1) -,S(3948b1a,c36bd462,ac7b5cd0,7076f9ce,dc6d1a75,1ff65177,d7d9b701,d06419c8,ca91fceb,a01c03c7,ab141ea7,1cceb61f,72d5d18e,77964bd2,732bb95d,191765ba) -,S(4c7dbc8d,21d600da,6dd4c0c2,cffd8842,ea9e73d0,5dbcb554,35e31971,7e706e9a,86a77f44,b87b7abd,29c2f412,97f7e859,6db46ebd,8cdb442d,35dc17f5,278230fe) -,S(75228daa,b3825e2d,9f8c2f7,a0743b0d,b7dec731,d9df5e06,98ee11e4,8244f623,963c2987,e122f107,dba37bdf,ed282ea4,75e33665,260a5aa4,51021a88,780a1676) -,S(aa3a86b3,2ed2161f,8f6ea92c,71b7a47a,b584a73f,102c0147,632d2c2b,e80a579,b8fe249d,2b4ec64f,dd345d3,210244d7,f7e517ff,7722c2ab,bc4601ad,ae4e6cb7) -,S(702b912d,9828039d,a58b992f,7d6f3af9,4c03227d,3d3c368a,bcfd3164,193f22f7,25892c49,3a32cd78,130a4e14,c714cc7e,b576ccba,396ad36f,71de5c42,c6bac387) -,S(4ca10c88,6d44bfa6,2a221dfc,10c57011,269f703b,8f6f3567,829d3b5c,9c90ba75,3323eab2,9282e358,d4de6f27,72d77db3,95b04a22,7f0374b9,dac3ecfb,4ffde3e7) -,S(1619ea36,30da6972,2caa436,2c174efc,f3601c35,2e946d34,2da56738,92b9c325,22ad140e,13b8679e,a6d88dd6,148ded7b,a1c12697,91c7ede4,b98a72f9,f0e881e) -,S(21dfdc38,18debfb4,9cd409a8,a302f8ac,64d589ba,b65074c6,365bd398,d34d3032,bbbe7ec2,e835204,a786ddcd,bb6026e6,106d193e,21725c45,79eb17ce,784099a9) -,S(60fbe5dd,802f1ab2,cbae99aa,12cce0ef,36a472e,bbb1bd1,c0ddbd40,85069fe1,ea83b59,2dd304d6,82fd07a6,85408f0b,99feb1b2,b78b1316,7f9be524,a7349dc3) -,S(c804b465,fdcdc5bb,a848ee97,559405d3,dd7c2479,4dc4866a,e29676cc,1e147f96,aa4a2eb7,1fd82b70,ebebf43a,9b828e4f,fb10cca2,cf9bb522,3a7eeef2,5badc5a2) -,S(77a6e3e5,51373b55,dc51b338,3c32f6c0,5c74cfbb,3192fb7b,d96d9d3d,d50336d9,21d2326e,86efac71,48e075c1,ffcd573,5de35d6e,3856f2b6,7d358b6b,c6f047f) -,S(86ddc187,4a72eed2,666706ff,26a4ec65,a89d82cf,64e3d8c9,4731d62d,d5f7a5a,51f7cc40,ce45a123,a9217816,ba3e6dcb,40507b5e,4cde95c,443ce5ab,4f0cc29c) -,S(cf49d0f8,db8eeac4,6c108675,a155e327,8c80d5ef,84ea28ce,4a596f3f,c7d3beca,6ffdc741,ebae75c3,ed82dcd6,a6191d68,7cdd64a5,c3146d41,235b96df,420086fc) -,S(1d75ef89,57eb6722,2d60e872,1e126cec,c9f5c851,5fe18381,518cb54,b75875f4,82c5dfdd,9288561d,dbe4ae2f,5fa1d429,c2076625,7765b3e3,7b99dc66,b78dbdb4) -,S(bea4b735,f62e6122,9d8d9466,69503348,5bb5b7e3,c6ddb6dc,a292ca89,e7ad0689,90e3278a,8ea9e10,e7d9a451,7b7c01f2,7cda5836,f52a011c,d8e20ad3,7a08901) -,S(e85b0ade,a90e5170,18d0aaa2,75d5989e,577f5cf0,b3acb728,1af396a9,6169f2bb,d42970cd,3ca175c6,3916fec5,757b7f5a,30ef1269,d4083358,667f599,e650aaa8) -,S(d97592dd,24050526,e41ed550,fcf7cc2c,82ca5584,c0228f5e,3ffe42d8,a3928934,eac6c169,6bf01c3b,759a3852,a0236f4e,4de0db45,26f2d26a,2174dc4e,fe2d102e) -,S(e023ea4,50b620e2,378e60a9,a8c65778,fd772575,5aeb53eb,edd35ee1,666e00e7,4e4ed850,6dbdcf89,b060f0e7,8915f506,6bdd544c,e37e1e30,6a966353,6894797e) -,S(615b5c95,5cd4fd6e,a581b9f7,e6a857be,a7c0ec2d,c302dc9c,c8304ec2,d935e5a,c221c766,2602325b,bcd845bf,f5d754d9,46fc8074,f36a78d3,6e421b14,fd5f4d46) -,S(b1dfa434,2e12021,b9ce34d6,1391bdb,fa2a0d85,a004985b,c2cc7358,96ec13a7,fa3d115a,8162f828,1dbb7e9b,6f818b4,13c2a5cc,58993ead,d103ef59,9748438e) -,S(b64b601f,afbe47fd,ac675b83,5e4ecdc8,68c7e1ab,32598974,36ba3c9c,bbeada7c,af78c039,d2315746,feb60662,462dbc9a,652ae90d,573487d8,5ea52374,e9dbe68d) -,S(5429d346,fda1d9c8,6c5027d4,e94d7565,b0981f23,52715336,4a0f3264,6bb579cf,5b8ce197,dfecd92e,390754dd,2d74636e,162d6659,51464f37,ac696a32,995b1880) -,S(890694f2,56d6718,b040bb78,1041749c,20e21669,f3787f94,ff954b16,2a6f005b,d966934a,890dbbfc,bb90d7b2,26afd0f8,7bf505b7,31b94df3,5df1c141,2d753341) -,S(3ae75292,cd0526b7,fa6987a0,5fe060c8,269b5d1e,44a2867c,cb92c2b6,743cc117,10959cc1,5a74a82d,8f7d5416,a33256bc,f004eee9,87b82871,d22a2dd5,f2416a94) -,S(9d745a9b,ff717d55,5a353fd5,f1b9fa1d,347bbade,8a4abce9,3bb5dc7f,299b0707,cef338ae,d513c60c,7304f615,ae734de6,10461cff,ade0f69b,bac28e6,7ede8134) -,S(699e9c2c,8130c939,105ce7f4,f922c060,abf1b896,648509f0,aaab9519,d144f166,882b490e,1fb9f944,95d14583,83809d69,bfb7da29,97d244a4,38da39ed,7c3a19cd) -,S(e3a01cc1,dc520509,a91ea704,bcbfe298,ae79b4a5,4f433550,3884a1a7,85591f87,f3c641f3,68d19d57,fca87e54,6ddaf495,2480a891,37490b96,6617fd4,1edcc64e) -,S(5d150dc3,d9df375d,46dd2362,34498514,cc7ccee6,fd8ff5f1,ee5ee38d,6ac433d1,2c091250,d2e2ea0e,7d80263f,18401092,399a83fe,bfadc061,a32316eb,52ab0316) -,S(49fb9761,bb12ba3f,644aea5b,5e011f80,ec477880,58a6eb16,c100c5c2,e0996a66,7134220f,b7208914,58499caf,21654c5c,d9086b1b,92978370,89cfd06,d655e23c) -,S(34c55eb3,a4512dfb,de799021,1adcddc0,bdea055a,1f4f7b13,d530c945,2a44738e,258cc688,beff401f,9a910e26,d0c979e5,fdbb695,323321f2,ba39a4c5,4f98fd16) -,S(7068fcf0,7c3efe00,4ff7b82c,2af0c9cb,9b1c39f2,30dc602a,b2508d42,30a3a98c,e48730d8,844578c5,2e7657bf,202b5df5,2fe50679,7e2e1d77,aaab197a,e37ef1fc) -,S(e1d8910,a987aaa1,12ba1f95,ae8e346e,f49e5254,a2b01909,f73b874f,6b355a1e,8ad0311b,cc4947d8,999c2c14,9fd5c59d,d4a56a20,a0b90235,d7bab907,fe3cdb8) -,S(92509b88,ba8631b,16c6b2d,c60df45c,6bdf06d8,ed4dbd57,c10ac3cb,72d2caf2,3ea47a31,633b6299,a9f95651,b95f1411,ee6f0f33,35ddb8c3,3978af58,746a3ccf) -,S(90fd402a,e8d505e9,96aec994,db7d29a5,6446471e,34dc7512,6a356ac,1a66a519,68c0ff7,bcdc36e0,ada31816,ec4f0e67,9a6dc658,46aaaa62,e1958ba5,bada3b6b) -,S(b380ecb,7d9bca8e,1e35b0dd,d412b128,4cbc77f,c66c5f5,eb390d9f,a9400704,fd2a2092,77d9b783,9df69a7,229d55cd,18fa71db,e1f5f8a7,d78f450c,846a01a4) -,S(40e2e041,aecbb6cf,6f866140,b6149257,f3d029ef,ccf2a752,d3ef7b0,32b83f0c,122710a5,3c83888f,54e26679,417f2329,e1eda641,8e525326,704744c6,bc2291f0) -,S(8e609fc4,3f4e30c9,3893a38e,9aeacceb,7d254eb9,f77b49c8,c99c20a8,aaa03583,947c4c6e,9a821504,7f259a86,b1d70378,837fb57b,e0d696d,66a3dc3,7ac1a3e8) -,S(b871c5b2,2bfe9fd1,6898d00,1af89a8f,8d9c9324,52fce0bb,2ecc0835,f435f5ce,e302e5a3,ecbd0ee9,9f87226b,6f038003,507fe8ee,60b64,cd656f26,8f1d3078) -,S(526daa7e,39e891a,bb524170,96fff4d5,c6f80f57,cce87f83,2ac07cd5,50841682,69f04499,4fb7130e,758fd397,5ad40f68,c477bc9c,cc5c5f43,c5f5a554,b3d210df) -,S(c15c244a,514e3057,ce67cc07,3fb66fa1,5c031f51,8add9ba2,edc12f94,861ad25a,db1021ac,ecc3c897,8de34780,bbc9a8fc,16449ddf,5cb05b90,1ba39598,72846c50) -,S(37e20b19,466a038d,b3b63873,50dd3dc5,d3494876,cdb7f344,3e234173,eac1d388,b80a24,546541e2,ecabcfa2,7db57aba,5ea5bb79,f69ecf25,2d68ef63,fc3b89f0) -,S(6d091f28,feae0142,b311cd81,f57958a5,6a0da5c9,7ff5eab,c598e4fb,564ea528,48bc97f0,4d7ea6c1,38189719,6c85dd22,6e9d9f7c,5a8ba74c,27c29063,fdd07906) -,S(3bdbd416,a76efb56,ed01664f,b819dbfe,d3e545cd,3edd48d3,5ca635e0,bb54fd71,a6954d72,3ed7253f,ef301621,91fbad8f,9a63a893,82b98d26,a6bf36f5,2ceb0639) -,S(cd4e36a9,f111b55f,8c05d41a,4bc33ef0,c4109540,d9871237,4018b2e4,7e9d61ce,478dfa16,52632e69,6ef95ec,452df807,abded9bc,264e6dda,df0c6215,454e3e57) -,S(f23cc4a,9c59c0e,3bf21413,170ac67e,24845771,2e77f1c6,272a9f11,2df24efd,e933bc72,99b6effd,5cf58fc0,72f7a466,dc71cdce,74a3d3da,9ed5e7dc,577fa4b2) -,S(d98c6585,8c97eb35,b6846840,cb6db623,d7a349,435d4989,31a695ad,ed3c33e0,443fea24,ffe8825d,eb6c953c,70627395,ba13781a,164f2eb2,a85b862d,e3114990) -,S(2269daa6,c055dae1,b6d2b9d1,6c74a9bd,65325ddc,a249085f,a946e66b,6c744225,159d01f9,a61f0456,b08f0fe6,a42efdcd,30e14ff3,bb47fdee,2352dc9b,f5bfb3dd) -,S(335044fd,8eea8792,8de3880a,546b01ad,eb4d75b4,23ae7ba4,87740c03,167c48d5,69e503f5,26266bbc,63b0f2bb,757b3be8,cfe1d9c,e63d8226,8187a309,ceda1cc1) -,S(ee7a263d,86f9a83e,54cee87b,7bcae75,a601da9b,637aba50,46bc5f9a,3ff6c512,9fdd3192,203268e9,2388ac1c,840e7635,22271483,161f8f60,42d82909,41373d56) -,S(529b33b3,36f1631b,6c7b6111,ef44a888,bf95f344,766a2d97,6c5e5d5a,53f44245,12856106,93da6f4a,2fabc1a0,3280249f,6f29f9ee,9ccd7000,4cf0a857,ea061099) -,S(f2b3346d,a6cee9f5,1a933718,2d655a88,6a251353,8ebd243d,d3e3cd65,abdf1849,d41df628,be7703fe,9e866526,2f6278d3,55aaefcb,324df2e1,f483b0f7,77b77da3) -,S(535e9dbc,f03d98c6,70d03d04,5d638c7d,1db7a12a,22f3837b,3f559b70,4582befa,2c233228,bad897c5,bd4fa98d,67f8384a,62ea4761,4f64e4e7,40bc1f65,9e358392) -,S(c131688b,70da6ac6,5ee3172d,dff34624,b019bf78,85033970,8253b4a0,b299a7f1,fef187b6,e0e748d9,69a11d82,e9f996f8,d6e1aff,8b84d20,7dd78519,dce5f3cc) -,S(75dc84d3,f7ab7985,10ceddf3,da6bf832,a984d00c,98726a64,5dc71b21,754d3ba9,f5d9edf3,5e110491,2cc5e4d2,82eeaa53,84f62deb,1dc2a183,af5b232a,e3841c50) -,S(591dc7bc,9136c38e,ae727310,25c5fd52,82c6dad7,6f98c648,78847ed4,f32a36c5,fccfa4c4,f81cd382,e003aabb,4cb6c5e8,8d4875b7,21d44233,95397268,d7a421a0) -,S(83a59c89,2a8392ba,e7548fad,b87acf7a,d2c78db6,4c588f0f,b14753ce,12712596,7d00ac1a,33b12065,d67c598,8822ff3c,46f090e3,15cf919b,e3e5030c,e7c5873b) -,S(e9b0dfa5,8c52b2f4,a9c1b8c3,76391eff,6608f968,ec45bfc7,6ca93e2c,ba6f6f83,6449b28d,5846de0d,27489124,feb3f3fb,5c1f0839,a7809be2,e5cb5def,2e0a7c8d) -,S(16cd2f9,67b090c3,d151c002,d3a3d25c,c76adf50,d55a6f81,b1b9a650,b72bc03b,c592601e,2fe77090,39ccc091,bd78458b,a23db74f,848ee06f,50ffe4c6,8ad63a7b) -,S(f347d3fd,1bcde363,69e3d9e2,44d6e5f5,d80b8dba,7b1866b6,f584a38a,3aff1cbe,1c435ab9,ae38a13,98dcfc6d,64125e8,c7349f81,1584fa97,66dc4d24,7e87977a) -,S(5b190d87,d644854c,90c49f11,34921545,f349edd2,b4e9926d,534374cf,da428b1b,8a4eacc3,63efd6bb,5c93ab25,65d2c157,9c1d3176,b2713ea8,56bc97be,fa5401f3) -,S(a7786cb2,d7314ce8,f21e9665,bccacad,c49e78f3,7772c3ab,105f67d6,1c30834f,4fc7acd4,18982e3f,2fb1f911,cb70bfc0,6c4ea71b,a05f6371,46e96bd4,a9441953) -,S(d3654f53,e9071a18,8c5faedd,c0ef3616,abf74d26,f073ddcf,545a01fb,2fbf33cb,a56f20c7,213c0394,5978502f,c4a716f3,77c7a3d9,26c3cde1,880f103b,432f4383) -,S(e1138a87,400acbda,69d8ac3,bb6db4cd,27d03176,ee88994,2039a93,7822399c,f29a8fbf,dd3f6d46,5c640de6,b6853e40,1803cd95,f5e012c,9ce967d5,13a162c1) -,S(d29eb63c,91c0f4e5,b3c49c6,9c9ca952,5714730e,76bb87e7,374ac995,86317708,4ad93702,4e9180a5,9d22ab4a,c856de6a,d9d38c9f,1cb3fdd9,d73aff61,fea5f1a1) -,S(a9d403ba,a6717fd7,6577da1,d8b8ecb3,d2124b30,d18df147,ca48b482,26ee49f8,1eedfe7a,8c5ee1ee,50937bca,d9591144,56f1e49e,db74133f,f45176b7,26d5323b) -,S(ff7b58e8,dbb6055a,eeac6bfd,112d89c9,8d8f3763,98e41e39,ca076bd0,9ef57528,4e4e39d1,ad7a51e7,d6cb57c,836c0685,8e39f1f5,bd41aee6,cf5d250a,fc381121) -,S(43c50a9d,f7839f61,e1b6db23,4e2f146e,1672ea1d,566f5613,1e7bafd1,bd362979,f20fda98,81541a8b,a83e908f,69e05218,1e215885,f60cfbd6,1ada74ea,83f449ae) -,S(f608a9b7,1c91298,75662ae1,6be6d043,5803a9d5,29d3be53,9843f227,174ac30c,5ef364fa,e919dd42,1bad3243,413bb565,d788d266,d7b508f2,83c486a,327ad5bf) -,S(c913e029,dd1ef043,f9bc48d0,c267657,3cc11722,5cdad56,8d013327,445a117e,97573f0b,9c31cbb3,7bdcf07c,13526a04,32a38f18,43e26d8b,ace85a50,19a83049) -,S(aae0c49d,b17e7bc1,66c0c58a,cca847f,61318bb1,3482f63c,ce7dc55c,82a7d728,41170bf3,f68c3dac,22051aae,658cdc0e,810396ff,9d5d9251,6a7e6377,5c6be0b8) -,S(f2805f1f,45a0b622,59b9b15e,3de4a05d,e306c8b5,ebc5ac96,d35aa388,ebc846c8,f5d72739,6ba37244,57725cdd,912fa38,b36e201c,26409dc9,9789d087,6b8d1267) -,S(6969e4e6,e150d12e,4a230e59,37d865a0,f7d2323a,781270d8,7b0a7a90,fa4f39,c71c33d6,d323ed0c,3e77ebe0,8595dc9f,e030a0db,aae16f88,8dab7187,5e14de3a) -,S(aec2bf0,7a0e257a,be4fbdb8,e872dfbe,2aa0643a,411943e3,e4cef039,8d988f3e,d8e9f557,e686c380,c84bc528,fff0a830,bcc3b6a2,724d9df6,ef21d545,c8c931d0) -,S(9c6ff99a,13dfc35c,a502890b,69d91dd5,198f561c,790bf322,6bb243bd,4926f710,2aef920c,84a4f5ad,9d88f541,1ff46839,2f7f4e63,3422b11e,9b683403,f7ef849d) -,S(fa43745b,37a5e238,df0246d6,7eede652,ade75aec,b5dd8aef,afb8e6e0,96d7f1c2,df9d5aa4,2a3c6540,3793c8f3,fef939ee,48aba7f8,59fe9ead,dc44e82d,a98689b1) -,S(694a3288,6c4e26c7,eb3b84d0,9e777f96,ce3b74e,58658741,27643dda,a78d46b9,a54d6c6d,7645e5,6e8909be,922cc5a,a700d932,cb1318b0,1446a9e1,8bdfe67a) -,S(65499597,5be06b28,b4c339a2,b126210d,930fe920,7cc72be4,3d4ad17a,c08f38a0,bdee23bb,467fdce3,2d2cd92c,e81e3f5b,d29fe8b0,8b35abe1,c684443f,72f7900c) -,S(3791c8f6,75bb14e4,b7d4f084,483aec44,ea38eb2,9b108137,400099b0,799f0bd,2dc8f74a,da5e5eb6,f3b96ddb,cbee5ee5,8b2a3f45,c31cb16d,15a4e918,eef7bc76) -,S(d5e41065,eaf890e9,e9046936,acf6a43,59795c7a,1939d8ed,42941a8c,6ef31364,191ec4c8,a559fd4e,7abbb6b8,f2e4c32c,bd2f30cb,d06ff6d,21f156cb,f65bbcad) -,S(16ce2280,fa0b404d,28a29acb,62058b99,e504e6f2,eaaa3ae8,b77ad650,2c970dec,3d4683f4,486addb9,e54bc252,74e590c,b6eaec5e,7f96e9b8,8174b81d,56efb09b) -,S(a6b0ab30,6cdfb1f3,90e5b447,816841b7,e08f997e,d7d47016,bf3b501,c6107d07,2a62842f,b67e2794,92ed337f,d72abc9b,94e96e4,a10f658d,9cb9a4b6,a80abf7a) -,S(d7ca6d38,760b320b,21cb779c,d709f376,52b9d08a,8ff6ad90,21e00628,56033583,d6c05f72,866d59b9,6b91b6cb,b1401619,5e2d1cfa,9982db04,6d672fff,849e7bb5) -,S(78ab0563,2d3f707e,738cb134,7121c73f,e162405d,61a0bef3,75f6cb45,f5609d33,fe1a390c,10c7cb4f,297a4b42,4baa5c50,350eba49,55fb74f2,1094ec5f,ee75a6b0) -,S(c053553a,5b9fe803,65fc5a9,60e48fd9,218e2128,28935879,bd1072c5,180d6f04,e02da774,214dab04,e11c45cf,57be2802,7d0d28dc,51cc08a4,7528869a,3e719192) -,S(bf85d713,e2a995c3,ef98d403,30fc1fb3,5faf8e95,81385b4e,b65d5ebd,23f02d03,a5d45947,58d7b0e1,a8542a6f,21ddd207,dcb68e96,88284bbd,6b940748,b3e59b18) -,S(fb73b6c9,2be578b8,fe2ee0d,eb0aeec0,13816905,9e55031d,69a4d0f1,1bd280a,72ce7893,9bf5a55f,d4430bd2,55bde818,e15bbc98,37e3dcf3,e31d22c5,9614cd16) -,S(56496e5a,ed338dc9,201b04f7,8f4b6c2c,d9928135,83360dfc,1e2f370c,1628aa79,81dbf48a,824fca70,12315d3f,a56d5150,92ffa54,d1300725,86c8a476,be8c2db1) -,S(d698e395,9e81f098,485edcc6,2f2a421a,aecc0a79,58c9f6df,7905c931,b7a2130c,5903debc,e61eaa39,dac01a8e,3e970a39,79408bbe,1d0ffba4,5ce78c9c,79563d27) -,S(84b32e40,86709450,b32ade00,d3404b34,7fad8d7b,9387d931,780764e4,c566ff80,4c80d078,56cc4296,2b7941e3,195c5350,9bb5b0e4,325c24,4aa3a581,bb1cfdc8) -,S(7129c799,2a3689b4,c1873a45,f1ed3327,6528e243,28f30cf0,5ac38a61,8db2ed6,362b4fe8,482125a5,d4d15456,79009aa8,44f86619,cf3fca68,ce38995a,660810e4) -,S(93164c87,fa48b6ea,6b6cac08,8c991c34,5f8cad7e,f68c5b98,78139d28,d180d824,a3ac0d5c,c91cf0f9,cb97771,d16396ab,bd183221,c8d36a87,2785e847,b5d9e26b) -,S(4f90e8e2,37c4937c,a384c7b1,f929f329,94744d5e,8b89ad94,808ed9b0,9f305a68,cde776e0,2b6b484b,83f417c,fceed07a,ce725e00,343c4e70,14748f08,992430b8) -,S(4d9603bc,9f40716a,e6913fae,253eccd3,4442f6a1,3c058ed6,a10f91b6,75f716a1,92b679fc,278ce355,97165827,aa6fb450,9c52a412,284aa493,c6654ee4,3924add6) -,S(8b6f651f,91c54143,12c94f3b,c1632e13,f90cd718,67f906a5,aed13c4c,4ab17203,88c159a4,b80f2556,bb4e2b78,c126c40d,9ded995,bac6ac13,bf83655,210c7066) -,S(6f58b852,cab98347,e86448f0,78d49916,1909e1eb,60556ee9,8cdc20bd,b25ec256,3a4c05f,233d9305,e6abd30d,da0cebea,1681dab2,ad805cd3,2fa7023c,98239885) -,S(6be7f6a8,4021411c,acb710da,3ffafa32,8bb6ca91,59a91008,6cb98071,100c44bd,bf64a6f9,d461dfb4,581c8d59,b5fc1191,86f339ff,320e968b,b5810145,4836bee9) -,S(b2fcd0b,b8ea9e66,f2cfdbe1,3ecff9aa,99661f0f,2ac1844a,b3983d2c,ae102d39,a046989,bb3b8fa3,eb2cbba,d3a7e810,27c38cb0,ea33ec74,1444e8ce,7182bb86) -,S(a1d6ed0e,ab559b29,edf7770b,50cc5913,3916826b,6d99ef12,91bf744a,79a6fd96,bb91657e,c9255ae,173bf93b,51848094,2f17df30,ac6b391,df2237b4,c04ab69b) -,S(28f6570d,ed7130d7,35366201,e9ab639d,440da5e7,e1c9701b,d08a811e,912a9575,39191f60,119c59b2,3e91a7c7,fbf4c2c,e2216e5e,955db62e,dece6adc,f2d2884a) -,S(14c8ced,dbb83de4,218b089d,101d7b6c,31cfce22,49637853,b9c804f,90271fa3,48052d2,a5d02e71,135cba3d,24c7894b,de1293d,44a2f84d,7a8fece4,ea9a41fc) -,S(eaff9f05,fec737d3,d2a28fa1,bc8450a7,a75f563b,9221bca9,eda2f8fa,e12d489b,d6d4419b,5c9873d,7d3349fa,520f463a,2ad9f348,1a111c3d,d3fb70a9,23b8c139) -,S(e8ee4c6e,b42a3712,85b52457,52e7fc3c,ce0757e0,96932a43,d92bed15,14b35e95,d86bd4c,27ef1831,f107ff4e,6246cb7c,ee55abfc,cbc5de2d,5f230a2b,6a3b748a) -,S(98c61909,8213b06,6b70759,1c88a51a,d5e90922,6778386,a0776e6a,ee41e7e4,eb3d2e2c,f98bb904,42e90e2d,38ce4c53,fd72da8,1a37fefb,fc241aef,f65d4c8c) -,S(d4f66b81,f5d62986,c57a0dbb,c38bcb5d,89319806,4e28e17d,946cf7f3,f946dd29,c1930f8d,eedf1a00,cb7c5579,d814b5b8,2a12298e,530bb32,867821fb,7b7a5fc2) -,S(14d73ce7,5f8919b,55d54369,69866f0d,a13dd4c2,ad447c4e,b9879060,1411087f,69b94622,b9cb0d3c,5d106df2,caf4208b,b71c48f2,629d467d,16ee06c6,93ededf8) -,S(57efc935,59c7a0c,6ac51105,8a50a8d5,5646ab40,8a711711,5bc34c20,23da3aec,fca9329a,60b855c1,74bfba0d,92ae5529,27f959f0,5332cc4b,26272c02,b5c5dfd1) -,S(91f13a86,63da80d,a90b9458,55a9f3e4,171213f5,3683873d,cb6372fd,95b3677f,7405e0d8,6734f110,c329a7ae,92055639,e0332ece,134156d0,3cab4efb,419a90ea) -,S(dcc84d0b,46145e25,a83dfd64,b40dc5c2,c3322716,d1337767,5f9d6aff,a1607592,e46a4cf4,8e4dfeac,8df1526,f53246a,51b95161,a7030adc,8bba8ba8,1d2d6c66) -,S(28ab06ac,d5a6f432,116011e,6bf3c6a0,df0bfa1f,df16adb0,54250174,3348676c,51272a1c,967f49da,e9d1d6b7,a4ffcfef,cc31f42b,e0da52d4,27e56b63,97b0cb9a) -,S(7c01b21,f8d1dfdf,d3f2adb4,5915c636,d9c2a92,320c2d00,beff0f45,21d8b240,b4a48fcc,99906d81,fc6f78fd,aaa96b3d,6e7ffd62,d36d1aed,f76fa25c,542c8b48) -,S(f94eeb78,30f8e95f,2a362423,9c0e8fb,a0d3279b,e0cb5f5b,428a99ac,d14d98f1,c96d5b64,69676b9c,a5dc91be,8bb4a93f,7157221d,9513cd23,5cfe3ca,43649527) -,S(ea4674e4,7788cda4,bde0dd8,5f5e32d3,9a6d6477,30e9045b,d406f5f8,11ec35ca,769bf79,a9b9122,3070032b,a18bd769,fb622a61,424e9a0f,e1a46230,a75a235a) -,S(da5a7419,7f8f8685,1317260,682bfe28,19b7b38d,376745d1,7283c250,1fb40112,a60b5eec,5871e18,1325ef5f,5d6373bc,b5a19f41,2107290c,eb663e3b,95c37a39) -,S(c1017fa5,52560fda,18c6820,ded7b76d,a75ebcec,23b8fb6c,22ff72f2,26e9d41d,e947b19d,af2647f9,167da3b8,dff05897,9b5dc1da,6782929b,1b078114,349fed39) -,S(be7c0e1,4e814476,78a15238,b5809a75,1b964658,19bf0b16,4b3e914b,29216a7f,a30ebe97,f64219a6,f0b072b1,5d648e81,880840b,8a36204e,4f1627a0,feb392e) -,S(6758eec1,a4d6c0fd,cc118405,62fff82c,59e0fff2,cf80414f,cb53b139,97007cea,4653bc66,20fcd852,422c8898,862631e8,a0149bba,d0b9cedc,b4fe3eaf,7cb316b3) -,S(9cbb51d3,f88f4d99,9d80cf05,9e8735b3,11014de,69acddae,70d850dc,405b6116,dfa2e748,cad75b52,800e0ed5,17efc4d2,47c6381,9190a3d6,e2510bb,25902360) -,S(63a5aae7,b170792f,17350229,eaa5ad18,65328bd5,3421cdea,3d6e1510,d8bf0bc3,1125afd0,f25d5f49,f7e6250a,ed3634c2,12a261d7,8ce58ea1,95afb883,52da1010) -,S(adf96249,3e5f0328,ebae11fb,243da21,4e036d24,1da62430,b0fe2c89,b2f10657,509834ba,fcd8ddb3,2d018b16,d17d4b5f,219a29de,8a03f7f7,84f34b57,9b1ea1e) -,S(a0d8f5b,7fb44a15,93583364,e04d7225,bfdfa549,c2b25f32,f00765d9,e34d472f,61eab66,f84c2687,949da99f,3d97fe3d,630b6c22,f9f7c48d,d539b122,ef998ab2) -,S(b98308ea,9596a2db,adcdbf81,56d8025e,7a3ee0d2,5b27c33e,f686690b,ae61fc1,cdb4e317,7566a4ce,b4cc582a,3cfd259,445bae6e,586786f5,1250cd05,27ddbd37) -,S(e1a64f1d,37e3d6cc,119eefe3,793ba303,cf3969c8,db4abf63,7f0232af,70b98134,588d7ad8,885dd2f5,ec4d2084,b3f581b5,ddbd3567,8f4ecfc2,f955ced4,1c3231da) -,S(fbd5dfed,e8543aa6,e72253a1,bd711911,318929ee,7af14eca,49c2276a,65fdaaed,317cef0a,432c3516,3c405d51,65b8c310,f234891a,dbd0d6f2,f76cfbf0,193b78bc) -,S(fac4b7f3,b0a39510,84f1a882,2f7b6f20,30b87c4d,c0178a2a,e3077ce6,84da6bc2,7029b920,9e9522fc,160a5c54,a628fdd4,386ce0d1,55f19fae,390b2995,bc867d75) -,S(ca8643de,834fcf50,802c0296,41b5fc7d,3c29fc51,5c75c53e,e64a8185,43ef7c2b,907a6c27,111e296e,2436fd4d,ad9d9fa,f8ecea31,cee714c3,b26fa964,afcf17f9) -,S(71873649,d700ea1,7ea26b19,efe4b48b,a4a73b22,bc54066b,1202c96c,f3315f1f,f6cd8447,4bb374b7,753fc614,de5cf429,51512748,2042215a,bd82c11d,87ded2fd) -,S(67e738ff,21c3c732,26e57482,677c63f0,175b768f,776cbe6f,15ac3c53,48c5e3d7,14e5140f,2343dd72,577a5064,47cf6093,ebd2854,5d1326bf,ac79350e,eaf2bdb2) -,S(514b3f31,f875253f,205339f6,434ee17f,6c5a5c42,662ce934,280f55f1,9a198893,4eb33993,a2fbec70,4cd1c538,ce7cde4d,a61c0fc2,dca9669f,e469807e,4ae9a090) -,S(426acfa6,eab03e75,6ab30a41,418a0392,ca53c216,f84b3586,f9858501,8bc2dab3,c3d63eab,21cc10c5,c0a06682,d0573bb6,d34944d1,749da74,acb59aad,f1083926) -,S(b946bb46,68c05737,ffdcbee,94597c85,b8ad4a72,c58205ca,d420e8f7,a2d7a09c,cc700ed4,12633826,567e63a5,e65bc603,969ea13a,49feeb2c,dc723bad,1e3401b9) -,S(e6a844b3,f6c8b45f,511d7d3c,ccd75df4,1d1e38f8,fb28adcd,80335b95,d98e33ac,7f24789,3939890c,74a3268e,e1f717ab,6c4aa109,cc9257e2,c0b176c2,ec58cce2) -,S(43e62bbf,d9e052e8,c1636b41,5524b98c,493e903f,2313dcd,117d140f,96458001,f481853d,a90d528,30999300,dcff31d,ebee23bb,49ecbcec,8e147799,a63b352d) -,S(c44ef40e,3427476d,42e23e1c,41ddb9bd,e555a844,9125aad9,e94f44b8,8047f817,bedd4313,e43ee593,f2818e14,776f4ae2,38f664b2,db84c9d2,498b9ea3,8e236fac) -,S(a1b35313,dcc11895,c096f93f,5f8e4997,7f58f2fa,afd9b7e8,d408bde0,53212385,bd7eb25a,bf0d50c3,7309f9cf,5093d817,135a9ec0,20262c55,bdc8e8a7,a3079f5) -,S(48a6f3f9,fd6201c9,a37f2f0c,735bd98e,1382229a,d1589c91,b6748a92,1b5e964e,1b545155,3d41a8a0,64862c81,fa9d5966,2c73e039,53a5dc91,9712c50c,5b4481b4) -,S(8e01f574,651db06e,8a19181d,c8eecf1b,75f050cd,c5b2354d,b06285d9,a4061e9f,9d156ea0,9800e7d5,b6c6e90a,2eecada,7d7ba964,ba1f0cae,256fbfb2,275e108b) -,S(4bc0f8db,9e6db576,3eb68b19,5a79f8e6,28e375f3,1694a58f,43da4dca,fa05345d,c6a70789,a1e6b164,bba380e8,126a4a69,6338053b,6a32d9d9,8d0f215c,43a5b555) -,S(966fd0cb,5f5edead,d6230a66,50b7dab8,f4c7ee8d,b00ce55f,32d54a23,ba97a768,9d644e43,bb4f9b65,f5819a1d,ee0a16b8,1e8929c,a9e544e1,6546cf79,811a994b) -,S(6ab519ad,49522ea6,592dc7c7,4438e337,20d50eb8,862467f8,2962c510,857b0d8a,c5ba3a34,2b7250a2,62b67ec3,554c21ee,e82653a0,378ee0da,8a809151,a3ae44d) -,S(f8b0b8e4,3e5060f5,39bd0a0c,d076e163,e55f18a4,25327856,d526d6ef,aa76c62f,743de052,a65853fa,58cf29c8,62839aa1,7d5c95ba,43673ad1,fe1ecf6f,d4d48ba4) -,S(c4509ef8,579d8ff0,ab585c0e,5223d5fa,967e9763,9d15b0e1,6587a125,3ed18bad,7b91f7e8,ee979a58,5a36d8d3,574b8ae7,81199dc0,86f11cf9,7fe58e4f,1db08362) -,S(9a00135a,6ff450f8,e2207c53,894c0e4c,4cef732,cfab43c3,aacb00fd,ab42379f,393ec748,3684c5b1,4760902a,28cabb90,b481596e,8b847d59,4dfb8ff8,1fa9975d) -,S(3d775bdf,173f8d7c,de90c17c,25d3dee2,a484d331,4e525e3e,aa4a405b,6f488601,7e6b08bc,a560f6a,5bf287f5,59d74e25,38a4025b,89972046,b3de98c7,b30e51d4) -,S(cebafd3e,a60118b4,513380a8,d10a29a,a95e5002,d703d7b8,f5d0e983,7b03b529,19477ab6,46f59f61,ff603594,e33ba046,5f6d8b1b,f55290c0,fd61534a,87b74b4e) -,S(ae8a3cac,1ff3e3e1,ef01ac16,2e49b237,7ecbc963,f58adde1,58cb1987,cfa731b2,5a4b0675,2052b749,733f6af9,e8dc773a,ee26fd2b,114a7ac2,baca1e9e,51531efe) -,S(d74d38bb,8bd47123,5c118ede,e477ac4d,fd39b635,d0fbeb28,30843753,ade3b38e,f3e505b6,f17a2839,7a985084,31ba6de2,1ec0a0fd,3936dc32,5d66bb37,7cb54451) -,S(f4287675,7780785c,d14dc1be,fe075d1d,4d4f0b33,b0ce9db2,49595b14,f6beb2a8,a3df2231,eefc62dd,c658bf6d,a361ad6f,950f34d5,3ff25536,4eb1e1d8,60514b38) -,S(e91d576b,da19ad62,76bcaaa8,69cb2099,e6277688,3ca1d454,50dc9401,46378e94,b57e2038,c8da2cb9,9ac313db,83265d8c,20e7918,37e75db8,7acca971,3840779c) -,S(269944e8,7d77e176,3791b53d,af2aaa43,e035e1dd,f3c7daec,7e830cfe,38c66ea2,cb011764,34bdc7fb,528ca43,9b323c9,56764145,7b7eeea7,39ace76c,193707f6) -,S(ed41e68a,8f0b3681,1aa61c68,57bb1765,fb099317,2ff6ea5e,e94e01fb,644a3d1,f2cc907b,880cbe04,26ba1e44,83d95800,71c918e0,8cc085dc,1dd0deb8,c508231c) -,S(6947664a,96cfcba5,e2e36e4f,53a33d69,538192f1,3322113a,b0b79642,dfec0de,6481d1bc,5b65b6fb,a91b76c4,d6ade333,25610195,decf5dc7,7f95dc2f,a38fb6cd) -,S(aa3e187c,e22b63df,6a80a42b,ba9265b0,4379012c,70e8ef66,8ea85c57,1e27fb03,a638dd6b,98109fd1,96ffcab7,3010543,e8732f48,e5cdb29c,38fa91ff,8d011be) -,S(5de4e1,a4bef94d,b4a9fbab,6543fd6e,bfd5ea37,9124e1c5,eff9be18,f84a944b,21c4a282,693be294,b699513,f7744761,58f8aed1,a7ec7442,9679ba9e,7957e2d6) -,S(6533dcc7,2c87b477,81c96c79,3af0af22,fdd18fee,a33a30a0,9646c2b4,287a7ce5,7f03e5f2,3d82f9bb,ce9589fc,23442174,482748cf,a3aeccd3,f8c37058,837ccc51) -,S(139e5f3c,129e584a,bda008ab,85343531,c5109f23,a70b9871,a5ebb00a,64fdf354,497b7e57,41fb8eaf,a53182ee,98352b62,6bf011e4,826ac9de,6190a2f7,773f0a98) -,S(493fe9cc,f7e1e950,83cea991,8d8f2561,3ce57b81,81915f0c,7c779aee,8161f7c3,e69763fd,62fce1d0,454aff6a,6a3bb448,639ab615,8bcc2f40,88cbe4c1,67020cd5) -,S(ed675fdb,d8dd70b8,641ac2fb,4903ca77,900e3c15,766ec8a7,446e6b36,52a064a9,a61bb379,85cef5b4,6e0669b4,b0188ae,23ccffb2,5ce777fd,1f26f313,68416de9) -,S(173670a8,9a769e3a,797c14e3,15393d52,b6d48444,3861cb83,136b0ca9,9a260a4d,4dd43921,c1ba4d2e,95ea1b28,e4908410,d140b3f7,7dd82bc6,d683da27,c7bd4904) -,S(d5a5e3a0,8f87e154,6f11e05a,c106e80,a1da933d,2cca528c,df9e1f09,635d1610,7c6c55e0,daf3c092,8d0a9c6f,2c1ffb0d,aa20df74,20a35167,2552914e,5d175352) -,S(54f5e9a0,4ab321c,692f2e2b,94d6697d,a0a99932,74ee4ebe,4175a338,daf6fa2a,58cf13d1,75fa6e47,34aeb761,4f828dda,58a7d9ca,855ff42b,5cbd66d8,89f2de21) -,S(d6682898,154de995,62e5544a,442622b2,fd9a632d,94445d4c,9e8725bc,7febe6da,98091e3b,9ba3b857,50e02c50,a7971aa3,b2d5045,f760c1eb,d1371dc6,3190f206) -,S(253019b9,2af2c4c4,8d9f6e1a,82decd36,610becff,18c908ca,fef49bf6,cdc2da08,617d335a,d9509d74,e5eebdce,810872e2,3ffbdd3b,da53aa5a,495b86ba,397c680a) -,S(56f64ca,461bebde,560d2bcf,ac08f292,ced72574,50e44f16,bab67cd5,104da6cb,5b2085cf,dc278328,a992bca8,f2ee8142,757cb553,b903a3ee,bd83bf3d,593aee44) -,S(f39c9571,1e153a9a,f0e5c192,87e3ee38,5a31a1e9,bef312f6,4dded245,8f553420,4cc94ac1,1c206b9f,7879df90,8498c132,e742ef62,48bdfa97,4b882930,e3b0b1cc) -,S(437eaa8,cbdf873c,32d3dad,95c5aae5,b2f3034a,5de0c536,8c8ddd62,c13128b5,27d8ea0e,b00310bb,59424599,3d60da59,2f8d1b2d,df0c1fcc,721e3080,993c59c6) -,S(ade1a589,3f5d6798,4490ae62,11c57534,3f13e7a6,14ef71f,a79eb4b,a880e9b2,bd49c17c,537e6a3b,ac7404d8,c3c1b429,e801882b,7f241304,9022e262,3791c715) -,S(936275d5,c3091a5a,b9f57d97,7a4e1b6c,a87ef978,c7ad198f,d16e2d93,3ac1224e,6852690a,d8bd84c5,eab75d96,c6e224d0,ed598851,b17b857e,5aa01207,df6b9f32) -,S(29e55fd,3e8fd5cd,e046db20,5c80b9d3,e294971d,76b5e8c,c33fb5a7,6b9b786e,769e57a,7eb934b9,4578312f,720ce44,2bbf3e2a,d61a6f57,af6cde49,8c010a0d) -,S(df8362a7,350185ff,198b5275,45e16f78,3ae37804,7647c584,168b159b,809051ef,afcb3446,fbd4a3bd,e826b604,84b16c3b,735ece80,ee48da26,3a6cae0b,62af6bab) -,S(5f443123,9a35fe0,f9566037,96cc619d,b9a01e83,96cf433c,25415ece,58a427e,385c2812,fc0aabc5,29272b60,56aa9c17,37d81c72,48fafc90,6fd7d4c2,b0901ac0) -,S(c19c4215,53c6037c,525b77a3,1693fc4c,8c5323ff,5d3dd63f,4b7e3448,15dd2de5,9f76ea8a,879177e1,27116189,6d9e6b20,a19d2255,92c99822,159c8ec1,a93900a4) -,S(8abf3a1d,d1e02332,ead62fdb,36394246,14d19d92,a82113f1,d62a1423,af2d45ac,325a967f,dcf5ec3f,75e7a984,ecc2d9f2,defc2941,6dd507ec,7de1b598,a7e36dde) -,S(c8bfdf90,b93161e6,c4d4a58f,a71ea84a,57c1dd76,c0607b94,33fa3cdd,f759ae7a,23dc38a3,d172fb63,ed47efd3,c3e5aa3c,fd7990cf,1535ce5,b51944f3,270b20f9) -,S(976666c,35c55997,a759e7ab,85f90d7a,a26ccc40,5b77b8b4,43c7e86e,2d2c78d,6d342c3e,44facf25,bf2db2e4,e20cceef,92c52cfe,b4370f89,60551614,381ed0ff) -,S(e7790ba7,7737e4e1,c7bb8e8a,5bd89c3a,1fd65b6c,feb2273a,1c12a8cd,f963252b,2635e20,1534b58f,70e754ea,db28998d,f7138ff2,a9e92e1a,810259dc,ffbdba42) -,S(42cb817f,6bfcec83,f60e3ecd,5b986ac3,b471cec9,975f3efe,37577d81,4576fb0d,ed35e128,b2f9bd90,f2162050,a5737909,144a8596,5075fcce,2708a4de,c45cf49a) -,S(a0886870,1a239333,ffc60397,ae11f145,31902428,a4fd58f0,2450e0f,412f3cbb,c8486f37,1ad6e034,8e51995,b4887ebb,fc6002c9,9cc00ad6,d8a81f99,1883af52) -,S(a40cca41,9f101b8b,40fd8e8,b364a52e,e6a9642c,22661aab,3486f25,732c4bb3,f421b69,3ec096f0,2d1e611d,f0701cc3,b0655b9b,95009285,babb150a,9445a910) -,S(90aef978,bbb0472c,5a75b70b,c9f5755e,c532940f,141a350f,efe604a4,35beb721,f9f05c70,737cf6e4,ca88cde9,2e478ea5,93f58510,9479d187,a5f87e11,e14bbf0d) -,S(ffc23a81,a0f61f39,600292f6,8db9acb6,d73ae433,bb827f1a,7bc6997,ac3407c3,b76a0612,bce5e139,277c7463,d47cce0,4f313b37,a0746803,6865f284,574d4b66) -,S(d3ca7b94,40bdf990,4262bc16,298425a6,742c852e,df99ded,2ab0ff50,20a112a5,9daecbac,ca7e825c,4f44281f,9813ce2c,5ef191b7,341fa2cb,1f9780ff,de4d637a) -,S(2a53a2bb,720ab31c,2a6b7589,ce0e1ac7,469b21ac,d55eeb41,b23b3cca,51bb9f06,11aff933,ffde9646,7a4d0f52,220d06ec,27f7810d,ba44b256,c21a57e3,d451f84e) -,S(487e5356,80c40287,a6fd2f77,bb8f5cbf,22b2fc71,7fb7487d,5a08474,ada1ac96,53bd7fd5,46070d63,77b65326,d5130445,29c9625,520c3a73,1e990d0d,5aa849c8) -,S(3e5a5fcf,291da0c1,fc332cfd,62f4b629,cf23c0b4,8209fa29,63de5b99,667b3e16,86987f2c,43389a1f,4b028df,773bb130,8b33d7ef,7f55dc97,b060ded0,fab86825) -,S(4f90afc5,15a847c2,2c42493d,22dd5704,601840fb,57086b8e,d5f7d779,e3e256f,46e31958,ac2e6892,335f6b08,9ac0d3c2,4ef93994,2b585e33,226ded0f,aab831be) -,S(be07392b,40be3ea7,a6a73807,121be982,c2ff4b38,a4585a17,82c585c1,e23601fc,3a158457,657c9e8e,7bd775b8,1dbe2109,43172771,e66ec38d,a57a8216,f1f258db) -,S(86c274e5,2140375f,222f9e6d,47c24e06,ecc2f741,51b5a603,e0563412,fa1108ed,4a02fab9,4065d590,32eb90b6,4c98987d,2703f276,f92c03a2,aa009692,40a96ef8) -,S(4fd3a6b,e7923898,127b3056,1dac13fe,287277aa,21127626,2678e04f,3573cf97,6498a1a1,63cfecb6,c6cf4b4b,43bc7e96,f07ebea2,3b4380d2,38c0342d,f11173e4) -,S(cfa435ca,5423bdd7,8aafe78d,1fccfd07,cd2a5f86,ba81918c,b68c7695,dd117c94,bf4c891c,2dff79e,35b77854,66845389,c399b53b,4a9f4cef,d7d68357,10ce1fe8) -,S(aa5acb1b,79533cc5,9b29e927,77469afd,414119e6,1f3c90c1,cdf93e2c,3e1d446c,b0df29b7,8713c001,fb6d3854,e183767e,8b11bf10,9c75dbc2,6bb408f4,22a498ab) -,S(1b93c2ec,c21bf558,ddbfa1c4,41bca52f,435c09f5,4d06d175,6353e0a1,545c3d15,56c455ff,718190e6,5ace8a5f,d5c6d263,f72e67b1,a20dcc4a,eb53fb4a,33195ed2) -,S(1744cbf0,2566d20b,f639438b,55f72b0d,c8480092,246410ac,d8551498,2fb91760,7e77a7a2,32b0b5c5,9d1d5da5,7a7d2570,68dc0f8,4bda1f6c,683f5229,df4c66f5) -,S(a0be98a5,ed448c02,8c2f8ffc,607b316,1b9cb9a7,a2291bed,d24a8407,ff02582b,e7cc2c6a,2393525,b4d44462,cf6ac8f,76b86981,ddd369a2,274c1971,11da6ea) -,S(e0e593f5,dab5f7a9,562b2591,d8d75ea3,8b2f2b19,cdc8fe71,14891006,7b845882,9088c762,15e35db5,b3bc2614,1a42ce2c,b5464dc6,49f469c7,e785f5c2,cad67334) -,S(7824d895,a4982eab,d6f1b928,de7b0d65,ffe5796c,5e492b40,8b9fc879,c29290f5,ae175c68,8e428528,38a2d8bb,fc232c60,d6bcf117,57cdad44,8a4af01a,bcc7ee88) -,S(49d2e57e,e0b611dc,214e4a2c,d019ae2d,2aa51393,e976cb5c,4211cf10,f9d96e66,ffa0c4ca,88011f72,779b7919,829bb9fb,11c81e4f,a78154d2,5cfa3cb2,bd5b770a) -,S(da605f6b,8f701a85,86012e8f,83898aea,eeb3de32,e9c7bee8,be2139cf,c75ead00,5ba0c12c,e98a1c1a,89f0ca5e,a93f50fa,5a24307c,6751f633,d699e5ce,9411d246) -,S(aeeaabeb,cde94e6d,5a1de2bd,1d9c380a,9307be3c,1c32e785,652ffd9c,bac16ff2,30094755,8510ecde,500a52b,f107093f,b62e491a,c2596460,6641abaf,d50bf840) -,S(62f1892b,35f3fe64,b1ad1e1f,4305f9e8,66ca0a0b,e5cb778c,b0e1feb1,a10c40b7,1a44205e,e600bf4a,2e287f09,c5bedbf,f1f89052,2d14a883,8e1813a7,3f5780d) -,S(c2091ec5,46772d69,28ebe9f5,50a68083,3a567b33,dae25e94,4ac4d589,96979382,599a765b,d2e89d31,735fa722,a1fe1946,eb610c69,2d5a82b2,3828502d,cad4b31e) -,S(bfd7c15b,19519235,700e1b23,79fe7c22,e50a2455,5f83dba5,97d00fdf,1b242367,ac6de7de,545ec735,ea127213,fafd287,f4cddac4,8d6fe694,372bd46,bc66b17b) -,S(d4d4e784,3cabfdf7,903d8507,3831da81,9581629f,74f3cfd1,16b5f635,132ddc7f,1e49611d,582cbacb,fce65a28,44755cb1,d1cd6d4e,2b8f082d,219742d4,61758a6) -,S(1e575009,c378b34d,f3b434a4,95dd8c31,4945b4f8,df617d02,cddc11c8,8f908fdc,5ce37fa2,810c95a1,2697458c,b8f209cc,10bf2123,3ffa8565,5bd8587f,cf6cdb7) -,S(b5a66a2e,ac237eb8,a1f5e690,ffdf65e5,c9268c6d,37104ee1,108f95c3,b9408fd0,99005ac0,aaa4f6ea,60842ba8,68668c6f,f8cc3280,307630de,3c43ef28,cbf72798) -,S(1da39d35,2599593c,66c90b06,3baeaf8d,66bc3a30,21e3f6e6,cfc3ee6,7f26fe0d,9272a05e,b6b0151b,5470d076,c01c3000,f7e58aa7,8fc7fe48,9f285b85,c941311f) -,S(7f3b10b6,b10000a7,652862d7,21f428fe,4e900c5a,f3844500,2b374434,b5a971b2,b94a2fe0,7907ee33,113bd4c9,256fa08,8c4a4f74,df3c3a9e,1f5d205c,a2ecd385) -,S(426107c6,61850f9b,f6beb61a,e200c2da,e5dc368a,3f5d18cb,baf84cbd,7a4eb2e0,e1fa7c78,a9e6ed0f,8d713488,bd3afea4,857cece,8e8e54f5,40f8c70c,67e511af) -,S(555e2656,708fc4c4,312093c2,1489cfa9,d6c94099,680f53e2,fa374a43,45be9697,f5efb7,1e3bb76a,22566e06,c674ba11,a7822422,c6f44cb0,2f2e2be,284db6e7) -,S(7170b17b,5736e07c,262a927e,725b709d,3360625,4642a8b3,af8fdb12,917dd290,ef437ea3,f8998813,b5ad86e6,9a77ce0b,98b2c6a6,b6df5608,627ae735,30973b1) -,S(1ca8ab3e,66fefd13,49e329d0,72a44f1,eb4de646,c8930172,aaaec311,5a5c2180,6fc641c9,2a87d776,81dda2a0,f4984ed2,c70103a1,5531b274,fd20efa6,3b0a3c49) -,S(8352546a,f6d42e82,bf150c1e,41c1a72b,85f057d3,487b4797,7d5e4f8d,c05366b8,76be5ab2,7ca25b12,a888d7e7,21c2b1c9,ac92b0e6,ea0c484b,1383a835,86c5fdb1) -,S(2f112f7b,1730b9d5,63f988ea,765c48ef,353123a1,4d92e44c,3e988459,9c904cd7,eb348e97,f6487d5a,32f70b16,d2ad1740,27d7a8bd,41a031bb,743a6825,2e34a44f) -,S(e84023c,164dc6c7,1d72494a,d410a5e4,2eb6fd09,16a70f1d,5192508f,3ea5648a,634f3585,29be0328,89b2f510,622816bd,225aa031,ab145b8a,48a6fc80,1ef4462d) -,S(951c4d17,45daf527,b803929,114d57f4,4da40342,31c669af,d6e40127,8e28fc6b,f9083b11,a8b30fbb,2c696f60,8ae82627,b9592ef1,c72fc921,bb2ae4ad,5a27f0a7) -,S(adaa9457,f60b9f3e,e0a5548c,51f945b9,78845841,51ae87fd,689b892f,8ccb19f4,834657f9,2145fefb,8df9b047,55674997,f899b951,40ce5830,2e468588,1761caa6) -,S(649296b3,9800a3b,516ef3d8,52d7fba4,597f3e35,1d303397,7495fdee,619e6ef7,44ce9c90,10215167,fdc5f078,e2edfebc,5c8b441d,d88cf853,5c78533e,d61df105) -,S(2c1d7e97,908575bf,38afe2ba,7875f1d6,9f1e9db6,b11f92ce,4bc94d3f,6006266f,9eb250bc,30abd08,bbbb4e4b,bc09cb03,8c6c8ec1,fd1a6ff5,ba23726,da2cf7f) -,S(b130ff8b,ed4ebc32,78293b10,52fa197,b44adaa7,d1bbd74f,f6d56f9,744647ec,4a0a45e9,b785c7f6,76fd0a95,66e4228,136f60b,dcc1806,212590ff,eea5eb33) -,S(4f2a5997,62ecb2d9,31ae9c74,ccd71cc,29bf684a,d68f0117,32a0cd50,cb0e6231,debf8db4,5cfc7083,fa700dde,7309edc0,fc44216,cf7bc237,377c0bf5,7ccf17de) -,S(97f9e9a1,7fbe6e25,e41419a1,8a5a24da,a178c0b,a99e30d1,cab0d2de,7a23c0b,1ab1226b,cceb480,fb4fdc8,70fb5386,6cb622bb,e71d3c0a,4ddda232,57559128) -,S(e17f3fe5,e9f5d17e,40182067,3b710940,bfd486f1,ad3ef4c,bb93b47d,9d9d8cb,f1126a52,615d3a8a,6b360b26,305124af,44ad7d62,e03ed96b,59c2903b,b5272f58) -,S(1a39f846,7d638182,900c3e94,538a0fe3,3ae66853,aac36688,7a5a8bb6,7b2fa2de,ae7c1399,5a625a4e,42b4dc01,9d7c7501,18492f3f,bb4567bf,28ddef5b,82903aa5) -,S(8a5ddc61,27f6fa44,90a93e52,f4faffb8,baa60581,5142be68,cd18692e,b42f5320,5eb62325,853dddf1,a42559eb,bd5dfcc0,328e69a5,fc787389,74c80d1a,896b0d8e) -,S(117dbfb5,74b7d6fc,d47dc17d,56f5b5da,b864906f,f08d190f,7afe1f9c,fe38c299,4acd2151,30b7144e,437bc923,302640a8,c504712f,6b903b26,bd5db8dd,5d90196b) -,S(b0c31228,431c7eb5,7310706d,950a2a60,eec84ec7,418199f3,f2985a39,8a70a537,a7de9b34,792876ff,e98c3237,260d8237,85e47c,438fe419,a1048b00,b064ff78) -,S(7c210cb9,f493275a,e17e6d5b,517606be,736cbc86,5a5897e0,8d1d1f03,f243946f,17b07523,a8bd185c,ea4a92d8,7af1f1dc,920a7fac,30faedb1,c38e3529,1759c63a) -,S(172e5167,578bed44,6397b519,2b0eca17,177b14b2,f4570aa1,38771610,6ed6e650,9c15752e,4776b805,d63de803,83c73ad3,9d3ba817,c1f88cee,1737cd85,33830ba7) -,S(161afc40,df25fda1,3637317,3dad8046,c95a6ef3,aa9c19ca,47e9ce2a,20030686,5e6fd083,c1265f76,b4b9c819,3a45e0e8,9926f160,b6257759,ab90d6f0,126089ce) -,S(b991f2a8,e18aed33,4d769cf8,b6e39144,2d194e90,ee1518d9,459d3ec3,8a16a85f,1d2ba9a6,b89f71c8,ea169d3e,923d2c1,7e6e590e,21b28e8b,1a0d0cd6,1bcab7b0) -,S(dae0689f,5a6cee77,f796f488,1fb3647c,7d623348,7d5ab502,6f1ca30d,44ca8afc,ee67b670,f730bae2,a15e6964,33be5b95,43ccc1b0,314cdfa8,c6cc8873,c39c329c) -,S(47a58ccd,75f89c15,46a17ba1,4629fb5b,d72805a4,16a12e61,aeafd8ec,8a7e4e41,c15e7fed,1bbb810e,b4be60bb,61fc1f0a,a4bc43b9,73d94767,9b954f3c,29fdd889) -,S(f7ae2fd0,2e3b6ee3,30c0697c,94ef65b6,d7582f69,5c509698,cef09b44,6b040e3c,ade9f8aa,c527139b,c54d8e6d,ddd41ac9,5eb49565,79934ea3,6a9dd8ad,d419ca03) -,S(155f9ea8,9be2ae20,8d7e9c21,4c244a58,ae61cf24,5d5f8dc8,b6c448d9,7c12989d,1204f5f3,840cd19a,fda04abe,6cbf4490,cf5ea60f,4cd17680,8c1ce9d3,65b009ff) -,S(a83cc9c3,933b5f14,fa5348a0,e0d3ee39,e35057b9,13c5a51,89a61663,1e9d74f6,40aa66d7,fad68476,1e2a9c78,e1fbe478,52b91d11,a283e1db,e30d4baf,f072a74a) -,S(ca4951cf,c07b5c23,298a20e0,fa44b554,d7acefbd,bf2a6cce,11fc3ea5,67b5f5df,186a8bd7,6700cafa,c79791a6,b28c799a,35aac545,78586050,b8012c4f,9f4afc2) -,S(cf92dde6,1bad101f,5e71f2a0,dbc2438d,d6760ba5,b84791a9,ae0ce712,9eb6787c,a7d351b7,f3e31e6b,cbcc1f05,329458e2,6c9d8a9d,1137d595,28f53e23,5c3bcbd8) -,S(b1ab0b3e,cfd8283a,3b79df9b,e83e8b37,b06154a9,6e2a687d,8f51985,129c1179,cdb7f2f3,4bab534a,41f4cd97,b812900c,99e97395,3837f058,12d5d0d6,e9506bbf) -,S(a1743329,9cd4c9e8,4fb99295,f3febad9,197296a2,98b30354,24e9524a,e1789ce,40994ef4,4cf53577,6f078088,adcfa6d7,5bee11a4,4f2f3fc4,4282f5d7,f77e1afe) -,S(241b486,4efcac7c,3c7b946a,61a55317,38b31846,607f1e0b,d0a1a2b,d9c0573b,5cce8848,eec61cd3,325f3ba8,fbca403c,2f980159,bad3997c,832f5c98,1fa0d574) -,S(81f88209,64997984,699559ad,f799ab0b,e3efd354,d258137e,d753e3e4,de91b387,8f9fedb8,5bfd7061,1b9e5caa,5f3cc8da,43bda599,afa29967,a32c71e6,aa26d15c) -,S(49d64231,bd2c2145,200793d6,4a2ec254,c22da96b,655706fe,8fbf5d49,464e5a5b,faec8eda,b0d72cad,81df8121,671c6dd9,bf986440,3f1a702b,548d4333,c751e825) -,S(74c14c32,4fad3a41,1c7e1f15,9b740980,6daea24d,9476e938,7e77db6d,66e0ae4,af795203,1fbee5cb,f031a2cb,946e6b65,3ee0165d,abdb89fd,5aa73880,e0641a41) -,S(88bc209c,7342d94c,be3f4215,81383c6c,930f9c19,d09d91b2,a984b6d7,12a1e7c3,acb7d745,76dd8723,89a88866,e287610d,b817ebe6,1581aa23,46ac994c,4c5b3e08) -,S(486c8c68,c81ca88c,df7b93c8,5a1525f4,9bee242,676aae77,c1bd85ce,2a6eb3f8,e0fec94b,35fa97c,d5e64870,6f5e6849,d6249004,fb33e34e,c1add26f,4fe52d54) -,S(4a1efa11,6c588e23,7b5e30fb,5d0ddf37,ba39043d,6e5faf14,e28ceb90,4a681a3,bb196737,3c907165,a8937dd3,1bce476f,65f2acc1,41bd8d53,8fcfbf1a,997b64f4) -,S(d7745c06,c69609ed,db17f30,8efe7bb4,2632e85b,7f7f792f,8da44294,78eb28d2,7575a75,4d1b2bd5,5fc46e11,b1addb1a,5371f007,f702a97c,ad13f082,39b96a73) -,S(bd752f2e,a3db27c6,a6a08ced,df74a87c,dc333d50,fd9995f4,9ca7afa4,2be68def,378f8aaf,67478d20,ba4725ed,26d50c62,ef5c576d,da9c24d7,91dec38b,a5e9491a) -,S(ef588333,15a3c7eb,c6602bff,ace00d5c,55eb304c,7f3301f9,4be457b0,1f224d21,56eb3aab,6253dfbe,3d9a95f7,e843751d,eb52e054,cb5a523f,f46a0c12,b517abd) -,S(2c1de374,7355825d,a09beea4,f42df241,6b495ce,7edf1f1f,c1dc6043,5253727a,98593660,9082f5d8,8f9986bd,f77672a8,5ff92cd0,28d2c588,73a3b1d3,87a150c2) -,S(49f8d71b,23e60140,f50c9001,6f39b2e8,b78e2a22,a88f2535,324ff50f,280daf99,f66bb665,4807e7dc,330ec339,3f6fde20,308111c8,1fe42546,22b93a86,b58b04ec) -,S(365c9f85,754b61ca,2b2a30f9,954f3a52,d18fdf78,db593ceb,6df617ab,189f37be,c43fefe6,aca56bcb,ffa6aced,60a32794,7681b601,22369a3a,f1405a41,5132825e) -,S(1cf2cfe9,e89668ed,c1a446c4,da311cf2,7e2cb53e,1984a310,8e24e8bf,21f1b5af,71e56dac,43c53094,7b78f104,1a685f23,aebc7b12,e2caf803,6731ef5a,20c966b7) -,S(f3303479,62660226,f391c26f,a7e87796,219694f8,e01cbd52,25dce636,b48ca3ec,7dea0bf4,c110e945,dbb59ab8,74f83a42,afa585c8,56a93002,6f48f8fa,62762827) -,S(b689244c,4bc16c88,398664f9,2297ea0,8756a969,1ae7adf0,587c3253,e4b27154,9b488748,1357368c,c97f89a9,b4a75a0,bd7483ae,5c700364,c27d19a8,e450c856) -,S(bf34fcd2,d6b4371c,fef2f874,5e4be021,a78b4302,240d4517,f3eb1140,638cbe41,ce6888d2,7e326eae,8e772914,e1b43bc0,1ef6a238,27f67546,5464e195,5f97ac02) -,S(c2097a6d,231bc796,ce85a594,44c00250,d51ffe63,c45b9cd1,10ed4821,118d74fe,58b06413,fc4ac173,e1e3a85a,ca674885,d1f92b3e,5b99f72b,1350b6a0,bfe4ac87) -,S(874a6222,3d8804f3,a11b1de,3c647aea,e3e81798,40db2618,4d46a330,417afa81,4132a5f6,7986e622,976b181d,5c98f356,b31668e0,ef70f8f,6b13a0ed,af80b429) -,S(ac7c6e8a,1a05d592,8142227a,b0c3ed46,1f28463c,ccaa3b85,b9784e0a,f5bc605c,1a59a195,581e3397,eba60a0a,963f5c71,c107a9db,68794da4,a08b14b3,118a2186) -,S(3f13e2d8,d825a3f6,8875c01,a1715a5f,44bc12b8,2f254a65,575b163a,3333342c,baff6882,fb2c2611,ffef76a6,8b5e2293,6a2e6ecf,d7ba6724,3393fa1c,5825e3b7) -,S(1ebeb354,515e7f39,dc3e2631,51d0630d,aa7e400f,4c9f7cec,4d5f95ec,bfa8fe2d,a2e35cef,c2cdcf,384a2473,c185f3a4,c70724b9,84c72dac,a6ca11f7,ae5c85cf) -,S(c2dcdb65,b211e765,e6c59218,d12b45d8,b47d8f9c,e22b99a0,d2d19a1d,de02b2ab,e0aa5b9c,a960117a,7289326e,9259f886,8722e032,c96b5237,b146f50e,24f3be50) -,S(495d69f7,e2a9d144,8e2ed8a9,c038f6c6,7f360b8,270c9b85,841e8791,64bc0d45,5fb3fe2a,1dabce7b,83b4465d,74fac6f7,c48584be,134283e7,bdf59e0,957088d2) -,S(ceac4569,2139e4f9,701be43d,8da3f515,270a9477,bad5969d,2037ac87,3453bab2,bd1fd9d8,15f4e872,b602f2bd,9604b6b2,f385ea40,d5520b3b,ca32c160,44908070) -,S(7ed1d0b9,3196b8c0,1cd284cb,c0a206af,4e6dba1a,d6cd406,82f55897,9407e0d,e95a3ac9,6ba60be6,22f4ee73,2d75a9c5,11018ec0,d840ce0a,f1bca18a,1d2801c5) -,S(72fb366,4f42cec8,940fd436,5ba7cc97,ac5fe4b2,131250fb,a24b7178,a1040b04,c182b1a,93a211f5,f5de5c9b,4b52ce90,63d551dc,a21ee9bc,dbba2653,c47dce41) -,S(dd06cd8c,9ca91e45,d6720043,d3e6d857,4690192d,59154309,2160f04,6008beea,cdc17327,6eebea3b,f9fa8a7e,e83ebd81,4189705b,900b3ce2,72b85dc6,c41e7ecd) -,S(80f6129,e90a7f0f,1e650439,8bfedb10,3c708c43,2e2c743,da8a9a99,3978cd13,74d97812,145feff4,a3ef594f,85b644a6,d95a3082,3828c00f,e7226d4f,39deb82a) -,S(56af34da,f56b508a,eee970af,bafb9dd2,b48f83c,4c051b24,f5bc27e7,105995b6,d41dfe52,9e788e19,89105a4c,c219dcd3,decca65a,dcc5f34d,8a3ab0de,d1ae68bf) -,S(820225ba,795565b4,c45e29c,4689d91c,148cf693,a1a1c1f6,ca33c44e,4e3f91ee,3622ae5b,c89b9c2e,66bf5a3,17826928,11a0f4f1,4b387334,b24028be,ba4b7db4) -,S(7925fdbf,cfcc202a,895a1b7c,a8c7f09f,ad388db1,5652b703,3bf232be,a2ea57d2,46f7ef01,c9cb7dc9,1559cf5e,c6d3f5f2,1ebcc21c,a8414d0a,9dc37309,4e90525c) -,S(4b224b6a,f38ae731,5b316eb,8dbd2b1e,6638794a,9bff79f6,1027f60d,5d81808,3143ea08,b1633002,bbb2ad2e,11ffe5b4,b6dc6888,1fc669d4,23ff9cb1,595c3dac) -,S(2c0767fa,4135f4eb,602a1a36,e6ce488e,2c1bdd64,aa4113cd,28daf20c,687380ee,ddc3effc,e78d3061,7cc2da71,1373de0,6a65d2b,1050b89a,5f71be3b,fbc16a7) -,S(83837d3e,e7179a84,ef6ed2d9,41a9f835,37b5a2c2,5d511ef1,982d9bba,50a7ae7c,62201e16,60957b4c,a86f1a49,5a6027b5,fe2294f2,7946c8d8,556024b6,e3b66dbe) -,S(cf075b34,e560f057,53a8e011,835bf1da,25e50d9e,1d70dd9b,da427109,5895387a,c73209d0,330ff4d2,38e19f6f,33df38d7,2b11d8dd,180d6a14,4b07184,a2127018) -,S(d583f8ff,9b1875d1,ef468030,e3ebb7,9d06ba2c,1008329d,cb01b883,7c8931a4,f8cfcf1c,3f092ba,6bfcfcc6,9596b508,aaac7c9c,333ba58c,d55be53c,6fae3292) -,S(551fe9b6,21d2389b,fc185372,342edb1b,27568bb2,da1fe220,3431b792,43eaefaa,6c76904a,e48563cc,c6aff505,7f31119f,ff48e5fe,971223d8,c3badd02,563c24e0) -,S(1bb778fc,74062f24,b0962be7,bce7c990,51f06394,bc8e6da9,a9d63f6e,d16a80b2,2754f53d,2f4ed167,3d2700b6,8ff036fa,60e9352f,1dd7bbdb,14be1740,61d88318) -,S(a150af7,1261582f,8949f1a9,3ff8d539,aa0744c4,e97cfbe6,e4a3fe10,e7e364aa,e22a1afe,a68671c2,f9e12471,56e1bf47,100737ed,5f96fab9,9e0df721,eaea4773) -,S(c94ec3df,727fdf91,d7963a03,8e93d68,835ed2bc,2578780b,7242e15a,e72e2a9e,a476a0e9,7bda53c5,46312b35,f0fad09e,11b2810,b3f570d5,a934d21,7152009c) -,S(3366b9db,ebe13231,7c542739,4235a72a,f186bda1,784c7f25,5f8b65f7,f146875a,5ea2478,95f52889,42321383,5439195e,6b620619,20171862,eea32726,1345d3cf) -,S(616c8e6c,e52265ec,cb85ef36,5092b2bb,58bec6be,444c2373,974c38e5,e0e8ba25,4d3d5543,3d6e258c,d8b286f4,5f41249a,724a9890,2f1ef3ca,ba049bf1,cdaa0970) -,S(74df2177,2e38e84e,8b81d86e,f45dc4a7,2617b3a6,32094b1d,432291f,6a651827,4c32baf,30f09527,fc4abc6f,9c9b9a57,2a9ccf1c,6a1b360c,48746d8c,22e01334) -,S(1814a1bf,76b74532,979966d1,5ef42faa,532f8dd9,bee0cce5,d68fc500,21accbd1,5f5df5ff,da9d439,b2205ad2,5fa93b9b,7af1746e,9b2eef3,154bfbad,acd46bdc) -,S(28911e94,98ff7526,badf2287,8e85fbdb,5f444d66,c422a975,c7476c02,b98625cc,5a341cf3,5cf26006,9d869542,fb221ba6,eac150bb,e3809ada,5e4c903c,1e638537) -,S(d5acff71,e82a455c,3a1ce292,689e8686,f441ce1b,e644e79a,bd6d0efe,29270865,aac6d48f,1b46e970,a044971a,ad13f033,ca8cde96,958d870e,dc7d80,1d26d5e8) -,S(5cf51c1b,2210d85,9d765e17,32109514,8f03fc57,51004b6a,91f098e2,e2711596,1eeb19e0,610df459,2c31e58e,aa2a2148,17fe9ee,a3995838,f395bdcf,26d5c3b3) -#endif -#if WINDOW_G > 14 -,S(21456873,b58e3687,52c75800,8d3bcae,9efaf1f5,c5727842,25e3d854,8fd421cb,a2f2d10,c85e8a0f,4a136ad0,5df991ce,7d3c5585,a263d5cf,da50a4f4,3db76cb0) -,S(c10de5c0,51ae2d73,28ac06ca,cca840b4,ed7ab204,21c6122f,1d68fe7f,7893d38d,ee30e086,a891484,2ad4041,f9ab9c57,cff1a315,f0642d31,b31c2914,faac99e0) -,S(be778032,f12c1b77,9bba3d9e,d290ca90,30ac7050,bdd77a2,7eac09be,eea65c0b,8657348b,a1e27a63,1dd2a54b,e2d5270f,4cca817a,219c5378,4d4f73ba,2c932e63) -,S(a05e7551,f8f090c1,bfc8ffcf,fbf7fd57,9d033163,67d5ee64,b85c4f69,33d0ff6b,8eba561a,f42d43c4,99e1fafd,43b49698,a8f3babc,c9c94c4c,4822cbed,a741b309) -,S(6e4d47f6,b17501b8,f3b220d3,83cf5f11,a395c0a,f0023988,c4e7b8b0,ef66ed23,e01c4330,16e3e6a9,535f1d40,905e9b3f,8be9f05c,b53e6143,e81091f5,4b76b57d) -,S(f626750e,b7eacac1,7cf24afd,43345019,c6c32292,c72503ad,d4125d40,67b7e66e,d669f903,67f407d4,5307578c,ee91fa01,f030bb9c,b66c7111,34b91757,1c993f4d) -,S(437acc60,c555f7c4,778595af,db4676a2,1fc8b3cf,2c8538f,cecbae12,811511f1,985fd2c0,7385fba8,4cf25a1f,46cd2c3e,de8dd359,1c6d20ac,584b4a8d,8a65dd67) -,S(8d50555c,6245e43c,a619fb76,ce45441e,dc585c7c,4fb2f33e,1c07965e,d4e35f5c,ea828c37,331ad0aa,44d168ce,c328a9f1,c7deaa35,47ee4757,c776fc46,439ea5d2) -,S(87f5f6ae,580ebfe7,1b2c19c8,cfe770ce,cf8d4223,62718914,eb853f1b,7f4cbaec,eb61df09,12e06f58,ed6d85da,7240dd72,aad00c3c,6a3a9c11,1f378664,cf359386) -,S(c1cfcacc,b95e6577,4e2a7d12,3cb0071b,3325c27c,5d58beb6,781a30d,ff6306d3,fa9ba55,cd95e721,12d98a19,8e3769ef,8cebb355,dde5b62e,e6f3b8e8,52a3e81d) -,S(d68bf50c,89f25969,a765af90,854bdb89,d67acdf8,f1e16bff,64868338,8b88e311,b62d1866,55835dcf,8064e13d,aca1e896,2157576,a02e178c,78d27c99,9cce81a9) -,S(b8d7c25b,8c20438e,702197cd,a3bfc05d,c6577717,c9b6a527,15ef84a0,2c0df867,316b527d,4be0e62a,2015f15a,17a412fb,72ebbffd,b02e53ab,6e5e9791,b771b45c) -,S(d98b3403,a299106c,9c6fd52a,8abd9ee5,cea9ab0f,17a15b4,7eafc809,c34e356f,bebcd24a,9300c739,9bb3af8c,12fa813c,78c6838,dbfa00a7,4ab09669,4df9700c) -,S(dcd15a1a,7cccd53e,db08c2b2,c6367126,de55cc46,a4eaf5d3,335ccff2,1238bbdc,7de57d26,bf74764d,bcc7e15b,72ec272c,58061f47,cc0715ec,48bcc032,60e63a81) -,S(2f6a844e,e758e3cc,8f299e01,ba5753a9,d35e6c51,6a87a683,8f5ce28a,fca17c62,5c29172f,f907c0ef,95e78768,2625c8ff,27e26eb2,cd86df92,b9371203,8b332e73) -,S(e63add7a,e511eed6,93f62498,17f89221,c7a3a909,253faef9,23f37a64,9e2a2f67,c392df22,5ffa1438,c3d10c6f,813c3956,4f94367d,6fa26c63,1d562049,99a77e0a) -,S(f9955ec9,20fc68b6,cfcd163f,34bd033f,4ed7dc8c,30da7f16,e41adb,908c9b7b,4dfc49e4,ab583975,90bdfae8,56ce97af,91c92f60,a17df9fe,9ee923b9,9fe2cf14) -,S(d974d713,bce1db76,c5ea1143,b63ace02,5a2362ae,fe6b84b0,ebb0c49f,22341d7c,991181fa,3ae5f188,38a94047,9ea9e4dc,e8ff9366,78583189,bc340d2b,40481577) -,S(4f0af691,424d441c,698dfa3e,c3e56bea,e2c52fa3,bfd9ca45,763d7805,33a3037e,caac2486,81590630,b0c67160,89db929d,26a4e15e,b06aa9a5,2e19c92f,a9f9817e) -,S(ef6300a0,70060df2,3f9818c1,6ff4d315,fb1c7d4d,fef41e85,c96760d1,3cea49e7,a0622360,2def9738,d87803e8,6405bc00,88afa82e,39666246,10f5d935,993334fd) -,S(fef30954,1cd2a90e,1d473ae3,699ea7cc,ef69fe75,54f7d710,33b1f23,c9e96886,c2479c48,59423c87,5d76f6b1,5c671ed5,c9489af7,79266341,4ca68675,cab64fec) -,S(457cdf17,b1230409,c3d35a88,390f1bef,859994df,3ba21d2e,ba5f826b,6dcb4fc6,5aff71af,708863df,3074c236,446ddd33,5695c0c1,a45bc482,e0787788,a0e4ede3) -,S(a66e86f,fe0e9cfc,686ab0fa,11b641f4,28499f3,450d69a0,dbce1895,6181ea39,de0cb1e5,ca720556,7c6756ce,868df6b,5174887a,61afd354,653e759d,b3e3ec64) -,S(ddad5a09,c37f0de6,67eab59b,fa2cb47f,b79bf6f5,b8b0403b,f689acfa,627f1014,8aed1b91,c9e567b1,9806082c,79ec433e,1a152279,69df00bd,239fd8f3,f8e8d385) -,S(45c5156b,f1439eaf,16a43b39,5c0a393f,a674e17f,76f96d53,9aa6c99b,49042c42,c9bcc2ed,c5b5c8c4,b17d633c,90d45b9e,1583898e,41bb9d90,1d1b5097,57f5f516) -,S(c83b3c9b,564906dd,60049c3e,9f6ed0fa,b848366c,3b93650b,7923e9ab,8172a8d7,5709dd74,1326ab97,8853304c,a02315f1,1f0bed5e,bffab6f,467816b4,4c60a332) -,S(a857354,dd08dc83,ce7b0324,7594e4c6,99692c95,9a4887e5,344cd0a8,7970174e,becb7001,ddafd72f,1f845579,ca8d56d7,2145c8a9,be816924,957ba324,3c396691) -,S(8bba6b47,88259a19,578adb4b,6f7f51f8,d09eb70,ea790d62,abb2ed45,84f94f33,afa42da3,8526a485,60919f12,d30549e7,1d19608a,81f4cf6e,8e49cb00,2492b143) -,S(bb4d27eb,412e73ca,d2697d6c,46a143ca,e4420ec9,30440025,47aefb71,c99a53d0,9ec07a19,842a1e5c,9cf9f76b,55ad98d1,9485e683,b6b6700b,c905e190,bd9da19) -,S(af6f6827,d197688,f00dd3f5,ded1849c,11fc2abd,f90fc7f2,18b33776,e5753277,f9227693,c9405a2b,10e9b725,aac7ed35,eef4281b,ca04e,bd75b143,89323646) -,S(40453814,445cc67b,e7a4b71a,55e0b993,2b8b3477,f093df6b,f27f55a2,8bad2e1b,ec71d7d5,4e823687,d01d7558,6de9a1a3,7edc927f,e221941f,46051747,a69baab4) -,S(f35a6c29,bd596f0d,93cabc3d,c07b5f68,300f6ab,8ecde5d5,da8299d,112c7bcf,73fe2c46,e1b13112,718526f9,7a39f1f0,3d47ced1,84a2e4cf,1e32c168,1c470121) -,S(ecc7ce7e,bbe5da1a,596bf41c,4d19b51,b77f7019,bc431aba,e5ecea57,b095fa93,1ab89d03,9e7c6ddc,7751c9bc,4eb84ed1,b077cc8e,dc828ffa,37426609,e089c8aa) -,S(559820d6,bb3e47e,f68f48fe,1259da06,cd0b380,1f6bedb7,970c079b,7e373bd9,2373137a,a4d88574,151540cd,ab8cbdbc,5831fb7c,4b901c27,8c9a593,172a64e0) -,S(9c9b7e18,4e76bd16,856addae,9352590e,310d653d,809ec800,415f3c64,149be4a0,182cd167,55eedfc3,21d71199,7543b26b,d08047d7,c9363e23,20bb9516,da37a146) -,S(88e4e3d2,2cc3e6f6,19e62ffa,c7a4aff,63b16733,202e5410,52cedde6,9cda2733,ec6e32aa,498a7a30,e1c47136,5671d356,bf174630,d1b984ec,d9453e24,d275e067) -,S(7f2f8043,8e7d7fcf,593e337,a91b06ad,3ad1c461,fcee7bd5,82df516d,cb1c198f,2cb484f7,5a4472b3,230369f0,79f5e654,8dfdce60,98c4e561,a1310224,13dc1d80) -,S(fe0c5945,c5e67d74,ed498120,dae194cf,33a3fe5b,ef0f1ac,2c64c292,59827d7c,4ebff1a1,7d59c8c,469fad0c,79ef819a,8a897ce4,c0fa1121,741c03f6,cab0f659) -,S(ac0662e0,1be37c28,be457bc9,4af19e72,34a9d3e0,8667c009,ec58ee79,7e539642,b3adc375,bdc81a76,8385c9e7,2ecec61e,9b2b21d2,55f65450,c5956187,837f3767) -,S(15e0f7bc,d74e77a,af933c13,6cdc5b1a,1622de61,251090a8,f8509b05,d7dd527e,4d51a063,1fb81f2,fa1ef534,5fa306c1,a0c64f94,66961cc8,b574b06e,646767ea) -,S(e4119d0f,b79bd8c,e1687abd,4ad63790,814f9972,50fac9a4,f1b52d71,93ce282c,cabde097,8f9a566e,32ab229e,63bdfbd3,89f01378,c7d27b0b,f101cc3b,36bf3fe6) -,S(27a5b030,2005a21,5d89c0b3,4e4ee323,5e94742c,262a89b9,29e286c0,ab8e3c24,4548d58c,3792f7fb,18238cfc,993fdb26,f755379c,e0ed1b0,4df26132,8f987a02) -,S(a18ec59f,7621c8a0,59bcad5a,12d3f536,142d5c94,4c7a54d8,b9206132,d993e08,abd8204e,867035ac,8cde70cc,f7daa29b,d47b888e,1faa9be9,b20744e6,ec5a43a) -,S(9bcc19a6,71b787cb,9da72c91,8d7b2264,b9497ab6,313de85d,c3efbeaa,2f492219,4bea790f,67b8100b,9ad9a301,61e3bd9e,583daec8,b77f4628,568ed554,70894bbc) -,S(7ccb2731,cc3eb3a3,36d36af7,f44a0a64,e23aa0b1,12ba0e6a,11280c5e,1ab36205,8d60552,1813ede4,dcfcbe46,c75c5aef,7ec40c69,99cf301b,28b0e875,3031c6af) -,S(94107245,fa13427a,7d21f7c7,cfe0c4e3,2943821f,da0f77b4,23fde091,ba596939,89846c62,7868b1c7,4c546492,dd4821d0,cfe15fae,36896af4,547deea9,295ccf84) -,S(959bf7d3,989d3460,5f4b8f3c,cd12ed86,cd0a2a93,a8d4e1fa,aeb5d6bf,24f1115d,7cc703f3,5417d7b2,b7229626,558be68c,66a915fd,7cc52829,dc98c81e,c0162b7f) -,S(8e92173,ff2de4bd,f468e2cb,fbf6264c,5fff8f23,2fb57e1d,2a07ee75,3b45e7ac,2655133c,8833040e,4ef4c98c,e5c75818,be781f42,cc0b7314,7baa3ef7,99cc017d) -,S(4acbd2e6,98f349cc,42998c5c,53de7b6,3dc29b1,c2b8a569,48cd3489,190f0255,8837f8d4,15b3551,4544878e,1a71922a,ba4a0790,22c74b60,325c6f49,a411b978) -,S(f79cfd2e,b63f6be3,bf0f12d1,fea3524b,1188959a,425f5e38,fa569648,df433fce,9e412cf1,698805e2,a92114de,5694a925,17c31f49,ddca7e0d,b2d83d80,74d92b2b) -,S(41910c81,78f7a61d,7957c065,5d7e2596,a0e6d5e9,a0a9cf23,28f23569,5d818c76,26b318c7,e8a880ec,94c59a6b,d6f1cad,84031d0,e62ded95,1e265ba8,c3603367) -,S(5a864466,9fd276ac,ad8782d3,51bc27b4,9445835b,75f70a80,2ef42a0b,4885cfe3,b2510d98,60be4e66,edb8c935,3c8ff8d,2e008c37,6dd271b0,1f77276b,f3a5a48b) -,S(5e3974b8,1b87348e,e3ae5c83,2dc56d1,85004b16,90445b74,1b8e262b,ecfe0e01,63f644bc,397a1809,a4d57ba8,f18f0372,cd4fd083,1c3d3449,1ef2a654,46275568) -,S(154e9c88,589ff342,6fe2eb5e,dd6e1db,e253498b,2c0b3e0,52e84211,caf9cc4e,3a897093,df7d31c3,754f84c2,68b0594e,85cfd4a7,c2731fce,e01cc3bc,2bbc383e) -,S(b95aa134,e48967f1,bd3a7a48,d89d550e,3c3c3c6b,3c73de48,f2e6fba1,81c93faa,b6f2d3b8,8d0821b0,6b1134d7,ddc898fc,e84898fc,4719f8aa,e3570daf,168b03e8) -,S(316564c4,ff00502c,f159db79,62984516,4d6d24c9,1f20ba73,66669808,95e58b92,6110a6d5,39ddc,d4185b72,cc576b7d,a4577e80,3dd47a92,d4bf346d,ec5905f5) -,S(222b179c,29ff89ee,d6f2a0d2,d38c6246,33237c5f,7803d8c5,e4315f93,6a9bd225,8bddc333,6eeb3cee,a0c3ac01,e7caf4f2,f44a50f2,587e3e31,7046c85b,a57cb6f4) -,S(10347fab,33fb4ee5,6cbf75ac,6cb768dd,f51f9b0c,5498466a,6679439a,32048904,a351f45e,30f32caf,e10d99f6,9e9e4be,c3f4aa22,5388984,bc45bb78,c0c5148e) -,S(7048c0f3,1e600042,4544e9f6,e26783d7,baeb411b,a2c29c7a,5aed8953,bf831629,4683ad69,1d9f14a3,f67131bc,55d28c61,1b78b2aa,329668fa,8fc41736,c95840f7) -,S(a65f7371,b35de05a,78b71171,40ea9e02,7b777785,13fdcc3b,484ad9a0,4bcfa1a3,41d1268a,77b31744,5a270f73,956bbcfa,3f291770,d248d1e3,364b4aba,72b961c6) -,S(dfa35552,8518d1da,ee31f04a,2673d053,11db4eee,cdc81f15,bce79c64,3267a315,19ed047b,4fa52430,18863cd1,d8ade0d7,dad60ecf,10b767ab,52f5cef5,9eea9a8a) -,S(663ec2a0,80564f1f,943a25b7,2f60d3a4,17b62130,3015e17c,85782460,c601a48d,fce25852,5a4dbb52,4057f8fb,a4393116,ebcffea5,5ae3459d,3d8b19b6,a0387232) -,S(cc714eaf,26f9960a,b2cb139b,d2fa0928,7a309c9b,ea852537,e10b6333,2912431a,c1c5c0c,48c98ea9,b57eb13c,fa64146e,67a95569,b45b8643,7752b037,9269d070) -,S(a6ceed6a,bb8f1ac6,13799527,38a19b35,ece44537,e74e9185,a4ce3939,c14f8e77,c0090ebe,d410f2e0,2e56b4b6,adfd5495,488c2930,2c5e7a61,3926880a,88beedae) -,S(e0b0c34c,8d4f77f1,dd09ea34,8b0ec683,cb5ca777,6720546e,27ffcf55,a5e5bded,ed4adb20,ab5da65c,2d1d5d68,9ad63ebd,90170904,65f7ad03,1bf3d811,f407d09f) -,S(2362ff0b,9a2d0f7f,d779a83,8b26da93,65730d32,bc4411ef,fc4fd182,d9e486a6,d3eb4ee4,42bd6157,557e4e9a,dcc9c103,892ca05f,5c5af804,f736ecee,d8a6fc3e) -,S(2f1636ab,a1516634,a00a464b,aa30c507,af25e83,3f7f6fdd,ccf0706e,d5fb57a0,a664c955,c24a54ee,d56f1aaf,fc853c2f,6a81c53f,1ee36c48,46b26452,fcbcc054) -,S(243a8fff,6230829c,73368eed,fb4d62f5,bf478b4f,1752400a,91ac177f,70c303ac,29318b21,9f371dfe,4048c4b1,2f5317cc,b2e9c44f,ed72b537,a2f56d06,65229235) -,S(b17182a8,5f442a65,839230ca,5cc8f67e,835e54b,e0296c6d,e2b62298,74ae804e,11a4fbcb,9f6f8775,9d131a81,939e0125,7f7b4fca,e36ea644,4da3cc16,a161e5aa) -,S(5c9abfd1,9cae1a47,bebdd324,d11cf758,a1224471,6e83795,e42ff5f5,a8142a6f,38a38db6,f64d9d07,4a08a909,28768bdd,adbdd858,79ec847d,28c94dd3,a122e0d) -,S(44a8a4f2,ec3dd02c,226ae0af,d73a12b9,726e03c3,2a41099e,b70cdce2,767e390c,b7e18dd1,e6adcd88,1d1dbead,e1c83ed0,1f1d7b2e,50246539,b6bc2811,d63233b7) -,S(8e477766,c4de01c2,5cc17218,7f3cb6f0,dbc8eb54,fa888911,33131b7c,219e6e13,ba8f447f,10286c86,d1330c82,2647a999,b4b60e56,4131986,a6c05128,a480d83) -,S(c5f862ce,dd253879,8100eea2,92e860fa,321d7709,596a4dfd,6faf6345,82fcd3ae,81ab1260,684fd3d8,1b47c5d4,d5f0c319,93ae7db4,fed1a781,61d9d9d4,50ff831e) -,S(a674db01,836fe328,8566d977,753ebc2e,d55f0116,5ebf0349,51caecd6,ebf899db,12ae8327,737f7db3,56e26fb4,1ab306e0,2294136d,71206f43,78300b95,60f580f) -,S(b0cf999e,f11dea14,3e6b6254,aedf30aa,ba1e8e92,96c500f5,481eee45,a0e15adb,e4970d00,e02adc6a,be5e2433,7e017dab,17a61de1,d977ee99,969591,91a5563a) -,S(b3615f09,29f9b2a0,6a4c68ef,c844ae5,54959ffd,f03f9266,f918f16a,b517380b,31a7675b,83677cc6,ca87c525,27fbba60,d06ea317,fefb17a4,7d7a4242,3595f1d4) -,S(7be97bde,b271f807,96930353,b82c3cd2,c6cce373,198572c7,d289511d,7cf262a1,1af89a8b,cfa4a399,bce5bc21,e26c97d0,5126f8c3,211d8051,626c4f2e,c6f128b6) -,S(692e447d,df9c77f0,2db1d34,101bc355,519d40b1,3fff2cbc,aafeb555,29473d4d,d21950ec,fb7bb723,4e4e48c1,98b93a10,8a85bb5d,5228116e,da6f5cfd,8968fda) -,S(61b6fe3a,21b0bbd2,dfccad11,5123db4a,98058bbd,4f8a61b5,e416b03d,b1414243,75d3dabe,f3e2266d,65d408ef,af6b32da,7591f08c,7fe7de,ff20b9d6,7a3a8a8c) -,S(fe0f9f,aa49555,2afe97f,8462869e,e8a584ac,3c3fba4b,886208f9,fe260ec2,a9c0fd7b,cfa239a0,299afa47,e2861197,f382a331,7607e129,967bb22d,3ae3077) -,S(7f7c9a0,a240180d,c645e77e,c628bff8,fff90d48,c85d2fdb,faaf76d9,b93e26a2,1b12ec74,f801fbe3,ddeeb37b,c940c605,84b0ef14,85e9d888,f3f81c05,607d1222) -,S(3e444ef3,b77b49c2,75aa0524,77da59d5,a68dc6ee,6288e2ce,140512,92e54c60,e211ba3c,6860a898,9e1ee04c,ea9ddf52,25ed88a2,c6ecd9fe,3c2fd500,88367b7) -,S(4844747d,d33f7e4d,39aee79f,138b5fd9,223b4e51,c86e4894,c917a3d4,746d824,68cd147,2560b5d1,6b9bf538,b7f1e193,d2f220f9,ed9f742b,d36a003c,28e2357c) -,S(f0211c1c,8f87fb96,bd591255,6a799865,7382380d,6b5b020d,9095f482,4e8f531d,649112c5,9cf7a8cf,7f9d920a,6b6d1102,d92441f1,1bde7561,9cda8eb4,a26d7493) -,S(918118dc,15520a31,c715adcb,3e02ca4a,4d77c92e,310ef057,3f9c7a4b,d5d2d54d,37d2c580,337de379,925506ab,c6b7d9,4a61584f,4cb2179d,560d3a7b,406873af) -,S(78734d5d,833a5d24,5546e5bf,9d3e5ce5,61f818c4,a4c90fab,c8ae4630,a2c307f4,4b150c27,e054fdad,73506310,80eb5308,b39c6861,23b851ba,aa2349f2,c26b5981) -,S(ee988075,34a02de2,9fda41b1,c821c41d,3ddd5d85,9c5a4ce0,d14ad743,25943f13,ba7fda65,4389494b,40a9fbbb,4b72739b,6f85effe,245b895c,b8c7e423,8d6b7973) -,S(4a821b26,bd1326a8,26be6fec,b90229f7,d7a37a2a,c49e97a2,5bddabef,e854e509,8a645892,37ea07bd,929aee46,6fad63bb,5612de36,cb951200,b9faaec8,b11bfdd8) -,S(23658500,fe8b5ddb,93dd3b50,a46f9914,d04af9d2,2a786be5,9c0fa7be,7c3eb2bf,840e5cca,f9f3e8bf,fe51c1d0,a84de234,d7122cef,fa1f0ed8,9f1701ff,d17c40d3) -,S(71dccb97,7f8e77f5,a03c8e8d,e4b2a30,11d01e13,549949ff,42af13cf,d7ecf208,b70ad10a,5f03ad94,dc8d91dc,e7797eca,6ace74cb,4715bf6d,2b628bd5,f767f34f) -,S(6174a230,e15b2584,7a25217b,9d95f07a,e183f2e4,74d0503e,108994cd,69d20e6b,18cda952,ccd68c2a,5d78060c,6849fb21,e2379b48,425003c0,6f148a34,bf876efb) -,S(57cfc1ee,38d905d2,897dee9d,105fd4b6,90967618,2a2a5d3d,70781cc,9134bb97,bf6b5fa6,4de9110e,7d26e67f,65cd2765,fcedc182,1627243d,a85bc955,2bdcac33) -,S(26605be2,e03705ea,7f199cad,d4d6e711,9805453d,6d4feea5,ec2ae3f8,cdba59c,ced5f775,b62bddf,5935acd,9786847c,e7825da1,5807b117,7459f51b,72fe5774) -,S(6d89e2a6,9ff96c49,a3110a5e,7e17421c,4ca2d07e,6e807a3a,98d79954,7fde2457,4835767c,8f96da1e,78f1788,d9764dea,e4e4a0cd,238ff35d,851ee7d0,9c915df3) -,S(e3607608,338f4229,d77c51fa,cef2697e,f6010c8d,5138e0c6,2b724ad5,6ae79a74,da6a0617,a42d6ccb,44155f27,7c56c58d,42d6037,d234f1ee,ffd720d9,2ae23373) -,S(c8cf20c0,c12de1ba,1ad4dd44,46f76533,7cfefc3e,213c426a,e0cd25ee,2e8bea9a,ef7285a5,ea7393a0,cd78ea31,ef74f605,3d3312ba,f17bf6a0,77b919b2,33227ed2) -,S(f3d2870,fe782b7e,26a1a4f,9c7c3ba9,30e0ee0d,df6593f1,9bf11509,1fa63477,e470c266,ae26fadc,b2780985,9b9d60ca,fcbd9de3,5dfdfb67,9f4fd450,4ed6f3fc) -,S(702a6778,bdf2f3bc,4ee954d8,1e7acda3,1df7127e,a7920e59,a7028253,9019c6c9,2ce19ef9,10d773d0,cc32a503,83f9e968,ca3e407c,c1dfb652,377d08dd,1dca5b96) -,S(ea85cddf,4f79d7d2,a5db06ff,f1c1e3b0,87b0242e,1d7de713,53d8f73e,1bc83888,3806d40d,ccd867c2,2d166056,77d2d64f,d7433dd4,b1e83e25,91860599,2e66fb83) -,S(d0631e8b,30ef6467,de6af60e,61b99112,1949b324,786ff1c2,fe633249,a832aec5,deaf31e3,703df166,b0f92ee4,eff1cc02,684911dd,40054bed,4b21d4da,17f4c05c) -,S(b56cb88b,617a7104,c205e089,b83320c0,5dce438a,50411e5a,d342e9,8b258a3b,757edc72,52d76fbc,24a5515e,417625ae,11db0072,24c02fe1,1e249064,b5127800) -,S(e91ffec8,bc3fa3bf,b0a600b6,89db92ea,7c3ad411,d025a42,95570596,f44702a8,38fd56ef,1f7b476b,2e36aff7,73e190b8,61ec6370,f6ae524,d5dea16d,cc4833c1) -,S(4cd9e6c4,8bf7b1ea,9f855b14,fc904ad4,5e3bb71a,5745b449,e1ab3165,3bdf53b1,b5a075d5,ca9060b7,7d3a00c3,6fbc6404,88df6846,c712afdb,1115798,f382b4e9) -,S(abb07ce9,c4b711ab,d01a12ba,45f0040d,e3ff5a4,e59140d7,cf4ff289,42b5cde0,a8a0e68,350a88b2,397a162f,fc969d28,ed937f60,4704dcf5,2faf755b,d21f503b) -,S(95fac51a,c9deb5d2,b794423,a71cd282,b0604afa,bb3160ec,557a8b74,c578f18b,da99fcf2,abf21cca,c6f4e89b,de2a6e9e,ad199cb4,b97f4122,4f68bb47,b7caead8) -,S(2ecd3e62,b79b4f69,609f33f,2042b56,bad2a9a4,18e2852e,9e8f0d41,1fba8ab9,ef964275,95061068,478e11ec,942b6a2d,99e5b557,830ed0c2,c4291305,41104046) -,S(437d446a,d139d88a,b5437f06,6fdf8acf,7b538798,6baf9551,a414fd4f,101a6440,6c532bb3,38a34a07,28d3273f,e9d9c70,aa79c484,6cb337ed,b41f6029,1e2caa13) -,S(63149b01,94b4955c,1b7e9d51,24e7e7d0,4bb5d902,7e86e63d,f3add9c4,8ab2a44c,c867234b,b4ed27d0,dcdf544,be060a12,4c460c5,7a9312b1,46d2bb61,fdfa6c1a) -,S(78e509ae,99e6469c,41c44dd6,868ee402,8fda1cf8,2c83be01,9fdf912c,1e638bfa,ff3b584c,5ffcb1af,4980e2b3,ace00f12,3be630be,cd91d045,4e031120,245e92be) -,S(cb1d5bf3,f97b2bc4,bb33babc,72de78ea,34cd0a0c,e841cb55,7b3dbc98,61e1544d,e619e8a,dac79a61,eb46add0,96bbcbe1,31d33a6e,b6c99220,123dc9ac,3f27df60) -,S(3247eaa3,9ed5b604,d3038127,9661f350,53ddad8b,8e29d0fa,5c27ed6f,551cf374,1d29a713,d7dd351d,87175b49,afab518b,f268ce81,7fa39ccb,f08b3c58,de1e5378) -,S(d493ab52,8d6c627e,aa3dbd3c,8d809ba9,8a9fe920,307a0c66,2917f8cf,f68b3941,30e4336d,e1621a2f,fe7247ff,157a37c1,edc4f83b,e9fbd84c,af4f96b,8997c7ad) -,S(8dfac8d8,b65eec8a,a65f96b5,571830d9,22469450,42fb2baa,f76a4db2,ea5258c6,c204e9c0,72f643a4,1f53d8fa,dc66e3f0,fdf0d000,c27a5492,6323b2bf,b376af16) -,S(331ca867,1098b530,1b1e6f12,d231793c,de67de5c,640f0a1b,fbfe485e,5d2adff9,b52fb89,3a466c80,ae61d534,cb03fde5,95078592,1da21e0a,a8103d7c,c2e3d8f3) -,S(f34a338b,bb05db6d,55beb49e,526c9d49,fd515792,f407397d,3b520fda,3ffcf26d,6a6921c,4831df6d,91e7cafe,869c4274,faada27d,9d09175e,e86a0b9e,dd70910a) -,S(56d97dfb,284c7417,2e08fb73,3a2d0305,ff774495,2f229bed,cd36e7ff,6058e75f,3775df48,aeaafe14,a8005434,dfc19538,2d10ca90,d05bcba8,edddb2ce,4a4ed7d1) -,S(70e668b0,e854cd8d,d3469cc8,ffab1709,2d9341c4,4831196d,72d9673b,43dfbf7a,60567ba3,5546cd93,f2c356e3,927dc89a,c43fdf50,5e33ca9b,52552587,c905e311) -,S(675af615,9fb50100,56ebed3f,4c9784d1,17538d58,afc5ec75,fa93ee00,29d32390,c501aa90,4f9dfa9d,78107844,983e17b4,34872e3a,a94e37fb,6677186c,fa1abdc1) -,S(99f8e5cc,86ac5587,81a67270,3059442,88b19703,551474a9,9d433d6f,37672d90,30148ff0,9fa33b4f,f4410d57,9afcb705,c1146663,bdbd0fbc,8434f4f8,eacb09dd) -,S(8dcec207,3d74b9bb,bd47f52c,394b263b,e71881af,363bcd80,9adc345c,b9ce9892,d8bc1ef1,79ac54e2,68a685a4,db35e3cb,5b6774d8,e8d6b738,f4d65b66,86782a5d) -,S(d83f7e8d,adf27d5a,f8502d8,3ab81001,a2219805,d942cbfc,76db2764,c4235773,48472e1b,2609f81a,8b12326b,1b19b422,763b0ed9,d6fd67,51751c2f,8aa46c2) -,S(e6f8bcf5,d9ea8209,cb46ab60,643555e0,d0569f3a,dc62ac76,edc09a43,e02fea2a,7974cbc9,5a9dde1f,34560043,7b628eac,3641498e,612c19d9,9a79ae4c,cbde2d82) -,S(d2f30716,e4c1a665,a37d0606,3987d0c5,c19c072b,f1cca8ae,cd0e4d8,6a9e8c1a,e26e6d9,9fbd198a,ab83d0aa,ea53228b,539efd37,ee7ee791,365cabd3,8850eb29) -,S(d7a891eb,551ae5ac,baf366b8,65755a56,edc7bbce,7304a806,2729655c,f7f61cf8,8a7d915c,3a9a1500,616205eb,798915fd,9b33d7b0,6671e9ab,cf02b5f4,667173ab) -,S(5bb03484,f02ef87a,fa07f852,e3ec0664,67ffdc38,39fa28db,de0da07,2fc31246,e0515751,c377266e,ff95f755,f9c9373d,226ccb66,3678e8ef,176af5f,2fea3504) -,S(58716b31,48a0cac1,2024760,60d3734d,ab066ad8,c0f8d8ed,cf5824ea,83e111ce,71ae487,701d16a9,c1d2ab68,1ec7c8b5,8367a4f0,179dfc18,6778579c,553cf608) -,S(4a344869,db8d561d,96944c8,94a3c196,8d649fcc,bd430c7d,4a66ef0c,dc2ca550,285433f1,ff0e7dba,5bae081c,1b33c762,6f30224e,dcacfe66,46787818,da0f810a) -,S(3ecc369b,e7789b92,cf1448ee,28c0448e,ebc5d277,a8bdb5bc,a22d3151,5e246f7c,a5532e1,47848951,cf11e065,3f0627c4,6530436a,5f3773f2,b02c9bea,c1b60e78) -,S(28a5d794,21db38dc,8d7c8cf9,d120a3c9,97eea170,f0f6ed43,7222bf4e,27f170be,88cb09e5,ea40b566,39cce9ee,1245384d,2f02f983,3b3116b7,31ae5576,daed7cf9) -,S(4f54f945,b3afc07,c38e1aae,16dafcbb,b7c5097e,4895a789,e70e0993,cbc905f,6ba69303,24adb3b1,2fc1f8c7,8ea58729,5115adad,52bb1138,7281b9b2,997fa597) -,S(f490bc4a,20f1ecbe,ac2dbbd0,56f2bb77,d258a914,9b0732a,f29aef2f,7ec25f47,aec6fa89,74c124a6,576475a,60931a6b,533d0da6,4e621fe9,c298f03c,a894336) -,S(73b2f8d0,e91e2516,d2ebe348,85b973d,4a0c7919,1ac857b4,74f713d7,348d343d,9dd7a951,efdaa060,19ec71b,e41b294,d047ab97,d0cef4ce,25a607f2,f11bbc26) -,S(d911f5e9,977489d2,847aeb66,8c3cdc6a,ffbc7b5f,4a5aff62,1761ee01,567c5647,3ee4afd0,2ef6d3af,a2b16d34,b59444a4,2c70b3d,4db17788,ad3aac57,184e02da) -,S(87b695f1,5c5d7852,88218586,96bca8c1,9c5a6f3e,f23786d1,fe010fd,d063b0c3,21b54a,46ee82fa,bb5ffe0,e3137892,31623502,9a8e0505,645a9ec9,29984895) -,S(39de5a90,4ba6989e,5d16dda,a7ff67b2,15e08f3f,b593d7a8,4b6babe2,ca25c658,eaf5e6c4,1e1e2fc8,c1581f6,211bc8cb,34dcc08d,58f570a6,e6719626,7124c019) -,S(18c1f673,ca19f805,c426162f,11e7eaea,c675974b,6b4cf0f5,9eb03288,83bb0af1,ad1690ae,65783091,27f602fb,93652b59,d7507414,e76d9b3a,82fef166,68b7aecc) -,S(8d70ebda,893e8d03,d15fbd68,67528b7d,308ddee7,b2620698,15e7f3c7,332d42a1,254be26e,d9e9009f,e4aceb8a,b97020a9,9196a9be,60777fb3,a9d1243c,66df1707) -,S(c32fa0af,ab39b1c0,c96852cf,8e2382e3,93e5b59d,2e83ed50,d5307a0,14ea330,381e8afb,85d47c3d,dc5da037,d6bd82aa,ff2324ef,ab0e48d5,5da3fcca,bf0ee3da) -,S(c350235f,e5ad084a,1aaaee80,d156b302,d34ec03,360a7c0d,3a883cb5,19f4b27,e5ea7c5d,3184e9,b62fc3a9,6c8bb9ae,72535fc0,497f1b58,67bbae06,672a1f79) -,S(8ef5e1f4,8d905df,dbbba4b2,d4b22162,db839ba5,b28c755d,46bc2f00,e25e20d5,6300d9e3,11971dd8,a3e88192,84f3a228,9986270,45b901a1,80f831b2,4153103b) -,S(9b3783f9,c638a6fc,166aa2a3,3a40d95f,35a4e7a6,c8cb5fb5,1e596b9a,f285279c,41b2dd9,c3abce77,fcf798a9,159f36c8,94b55ac6,7c917de8,75b18cd4,e70dcaf0) -,S(c262215d,720180ac,669f0bb6,885dceb1,2c941730,93e561c2,660a4a1e,cdf0a244,7fea7ed7,f654741c,c67b12b9,f115aa40,ce427cb3,8c6498f3,8bd291a9,d73e9f2d) -,S(bb72f723,f0a16f09,7716272b,b905a111,c290c229,94f400dc,c6a24814,f41816f9,52a83ee6,53214a5,3ed2b13b,a367324e,e5606fc2,e3dc05ae,7ce0cf05,ccd6c36a) -,S(d896a5a9,a833d66,51b17632,70b03d36,eb423236,bf3b2b7b,6b2ba97a,f9282a03,e8a823f,ecec375e,280e0d50,49625dc2,1f48e269,77ab5eb1,b467d3e8,a0fccb37) -,S(198cb33d,9a2b790a,2d6fa355,58733bc7,f64cad76,e3921dbd,8d7a1f,8db52b64,c7e93702,ad7df0a4,94fba344,8a8157bc,eba10ee2,8f66f000,7e7f7655,8e6b4a74) -,S(4354e475,81d63d84,df19bd08,d98b2315,67a55550,477e1c53,cd425854,e67cd81a,a612c262,74d79c46,89734884,5b87ef50,29d0f87b,4a06e4a2,8ab36bee,ae6a6ce3) -,S(d956c71c,1c8b110e,19f96ffe,5709f2b2,83a095ad,977878fe,287de35f,283b2606,7c029c97,9a807375,bb589c12,a20ce37c,75178be2,5d5af713,f4fd4070,429c8d0) -,S(2c04b299,1775ae36,ed7d5b1b,d9b0e65e,fb2bff8,ab99dc97,2cd860fe,19b1789d,8b3f3b00,6d63c81a,86f225a,bd8e658d,c9c4c1d6,6787678b,6fa4a692,bc7f78e6) -,S(c7897c17,debd6456,a81f8d96,c0ea580b,db5daffb,5fc8e8e8,9c8612b3,7b229f7,f7334550,d20a1a21,c422f73e,d23fb159,2fb3d9b7,ca61d7b,6e124fa4,147ea63c) -,S(3b37b93e,ff554f0c,7e7f36b1,864ecb73,7b33a93f,6ff31d6,9ea18aab,a9487505,50ccac12,e071f469,3f5e5339,462a0cb8,66bde539,5842ff44,620f7acc,aff09a71) -,S(4584ea49,8a2785e0,b12c86d5,2b839212,f21b2e33,3b64bb0a,9713674e,66216547,2851de5a,b67354cd,6610dd4c,91aaf4ce,b75c4c97,26d524d7,69ae0ba7,997ad79c) -,S(c0c971d9,f5644eac,851ae8a1,d87b4f09,a802ae07,32d9b5a2,d9589051,f139963c,83e07a5a,2b7614c,c064b4f,815b8a76,6df7eeb6,449fdd50,5c43faaf,b0bd075f) -,S(370e8fd0,858c6fbc,f479deed,f35fef5e,80cd2338,90d4b227,1867ea90,6cd15b5f,ef382477,fd2dec6a,fce439ba,9b341a21,17d6ecf4,c8c8d63f,b5775094,6cedcaab) -,S(ad402a30,99c5d5dd,c7ad9631,b592d5a5,862e8d3b,5ed47dfa,c288193d,69366625,b8c0d468,5d0eadfb,9f7e4ce6,11c61f5,7098da29,aaed61f7,6a50961b,b45b7c5) -,S(ec16de3f,32ea8f58,c1dc93da,d1cabecb,5ca33ce2,e3fa3bfe,bf0ee989,f3ebf5f9,aeec3532,c5391ce6,1e23bea4,5b7b5847,2c36cb8a,6c5f1363,e457c003,b18824fd) -,S(5a51f9d5,f5c48520,dbd826b9,49f62f67,c299a228,259e09cb,b3bd6fe2,f4b0e60b,3c498d86,225a83a1,f506eb62,a2e530f9,511c56a2,eeed77a4,18ddec4f,4404b9f5) -,S(9696865f,64523eaa,456ea65c,40ca6e0b,12c6e6a0,211cf8dc,20963f03,7980b684,8f879d8b,491f11a4,1f0025f7,b35dc8e7,c71e420d,7d7d9001,bf5da111,9ad6c2c7) -,S(80c43c8f,6325cc30,8065d4c8,6e3d7bec,6ed85f74,412f6127,4fc3ae49,b1e185a5,31dfbe69,a48f1f39,a0cca355,f3d68f28,cbf3e14f,7d47cfc7,d9e82e25,19bdc292) -,S(54940550,ec4a6ca7,561946c0,65769b4d,d4683f1d,11dfda66,4aa2f8cb,8f1ab2d7,f41aef26,64466fa,ecc076ed,cd383d3f,132b4fe7,5a17f16c,c394b6ec,e4079378) -,S(a9787f8,42b3549a,9a3bea8e,4182555,99addeb6,416118bd,901afd9d,ad4c134,4efc4f67,65c7cf5,ccc2336a,e9eb14c5,a1361067,7632ce89,68033d57,4bc686b0) -,S(fa83e81d,63b85491,92e800e9,7a422ca8,35c03bb1,5579bc05,bdb4367,198a24da,779940b2,ad301a1e,205c0504,fe3ea104,cef6a459,e0479849,90fc94a6,871954eb) -,S(ae9a8d1c,a8a560e4,8a373666,544a7b9c,84bf0475,9de1a63e,4a20b55a,2f25c132,b9b0bd66,4c46edfb,ca2a0bb3,a94ff043,c00c1441,9f1df886,2aaadc02,e25017dc) -,S(a2f47145,296dd22b,3a6f5185,47ab0957,4d3487b6,8786f87,6758cbe3,5f4c0ae7,2ec4171c,15e7a82a,f6ace24a,60176f7b,6239561f,3c369a9e,efc80d52,3fd216e8) -,S(1bdcf82f,a7dd441d,91332a11,35f50be8,4d275358,f95df300,25187f2f,9828f219,99f12980,92a3ecf3,dbeb290a,67d72aae,6acd9cfc,c21918e8,9ff7ad4e,548d3510) -,S(b73c91e1,ae33767b,11bd329,361fdae6,36642d92,6c2792b6,e19b6e3f,947a5be7,b6502357,11ffe955,be5798d1,467eafdc,94df5911,29d2aaa9,b747a2ec,befa9d7) -,S(b23b4ad2,e983e556,e941a35b,b84846a4,40cd25b6,82487f37,a3a30eef,eef15d1,7010f10,88749d1c,f95e52dc,eae1a379,b87762fb,55593d32,a65ef0fe,dcba2485) -,S(e3aad2b8,96fe34ef,9d775743,6e70a70c,b3bb0c6b,8436e616,a23174ca,985fd8f7,5d6edc38,89beb099,dd191564,eaa83c14,3ef0b74d,7789590c,d6083704,61c6676f) -,S(2f22a14a,f69e6257,b909e3a9,50aab3ea,dc09c281,ec52e47,8c578f49,68910244,4ab723e2,43c71baf,d2aead8a,479a1a2e,fd2aba74,800b5eff,56ca46d0,532e81d7) -,S(93806026,554bae5e,9b91f534,f864b79c,81e581f7,bdf3b2ef,dd007e32,dd6872f0,800f8162,a6836801,d052871f,6892ba33,b2f60f82,89a658ea,a8af25fb,f9d9c444) -,S(8895d121,ad1f2be2,3c578faa,1e33656a,e9403ddb,a1f1aea6,1cc7bd03,817a46d9,4f7577d2,420d0d0d,7cc9ed68,ba3645b8,f9466f59,570ddf16,ba168de2,8cfec881) -,S(1838c15c,3bcf1189,546a9e3d,69fb8a73,de39c862,f5faa4bf,423e1dbd,29046ccf,49484789,1b67ea0e,2e7f7eba,4a596d66,b3ed9842,3ffc54b0,e9292a4e,bd6f5487) -,S(111e8eab,d9cb3ec,5eb63cd4,14ecf59e,3a3f0d56,70959226,ec8f203d,947204b0,4ab9b3bf,dc853571,2c0db9e1,5fc2832e,4560e420,af96b043,e587d1de,d996e38a) -,S(80369d1,ec5ab7c6,492db1f9,aa2fa368,ec083d86,75d6c1,e7262e73,a612e493,cbb28c30,db7f7d03,6b8dda93,7e0c4e18,6a09f1ee,2407e55,7f6dc54b,a8c0553) -,S(903c9034,dbd3f982,41351979,c9306a8,42b88892,48cace15,c3e3a8bd,aafe1ffe,d55adb43,d0142740,71499c92,e9b851d8,e6ece26f,f82ceaff,ba63a003,14960f38) -,S(d6490ce4,74bd1e80,82c99e87,a0510a2a,c2c2772b,1921cda7,dcdcd5e8,6ecaacc,85a1fcc6,de4b93b8,b2314da6,31d7abdc,f96b22e4,b44a5545,f274f941,454e98f4) -,S(12f2342f,aa8b19a8,bb0e080b,2ed3487a,14ddd1b4,83e0bfa4,9ea08484,157d5306,eee0b9e4,30a51a3a,49da893e,50360ba1,21660b4d,ebd3ad8f,82805416,10f4b7fd) -,S(3bf1ef66,57bdcbba,a9d9a23,36c75429,c4df4a86,1d71a767,2d7e956a,deff234f,fa98467e,83dd1ca2,2a85cd8f,f12be1f,53d5a939,352f4046,a626a208,601ef6b5) -,S(d0d0f8b7,9a04ac8e,b6e010fa,3608926f,3b5bd886,f84c361a,8e1d9dd4,b01ff717,9bb32b90,6d7de56,c75bd202,b9353128,b6440fb,42dae8e6,74ade0c8,fc96386d) -,S(19507738,80caa9c1,f042f8b5,d1594a12,161635b5,a83e4675,35ffe51a,fcf631fc,9280d033,f7a8efc3,ff22f501,6a6ddfd2,f78159bf,1f13be4c,f758b150,21126ba) -,S(f4f50c3c,eb750a04,95973b47,53b96ec7,22cef833,f4ee7459,a51f884a,f9a251cd,41f554fa,d3d521e9,65fb0768,66caeac7,d9f5c6eb,ba7ba7b1,d1d38c9d,c06d85ce) -,S(8b669c9e,22452528,57e20692,2726f045,e97b8cf2,1154fb74,e199f49d,11951b84,550c47fa,c46060df,4d893afa,9f08713f,cc8e719f,a369e90b,fa8846df,7938c65b) -,S(941cb4b0,31edf346,64dd5e7,92ca135a,1d6cc6f,55341322,66644493,aee5fe32,cfa91a79,29b3b47,d73b8ae6,77cf64eb,cacf9408,3cdc76f1,79e25631,d574ff68) -,S(557e36b1,27307c56,72232c6f,6e92e4f6,f5da9d22,1567b464,8e79d97b,bf589023,ab741e35,109a0313,e7adee7a,2cec2c10,79d18d72,6c27f1c6,5a808b98,8e99b523) -,S(d8081ed,9e7cf1cb,e1ff07c0,b8ef3f9c,c7eac02f,1cf1c6ff,833f4b74,b2a33269,efa297d7,10fb71c8,43e358f3,e04ac308,53027f00,eea43d03,9b87c3ca,2b0fdd2e) -,S(b5e4fdf0,7a443146,263f6539,f6c8d991,7486da78,95b4ba7,fb4c9f14,78324d44,a3ef979f,93ec1a0d,602950d2,ddc400c8,4f018643,229cfba8,7cd9e3,f2fe657b) -,S(1a573259,a5100c21,d75efcc4,41d5a834,a81d96b,f4149731,eed4ae67,508bffcc,8a993dcf,49f94f6b,bc71766,9d37ebfc,614a45f4,1d70a1ca,f4da8834,5711223d) -,S(33d9f9f6,c9ba653b,f9c52166,c29e9c06,2cb7700d,ea2f40cd,28520bf,237b4558,dc80f57c,fc0e73ab,bdfc4a8f,f7e8f4c0,3353e889,bd54cf84,6361c1a9,af5a0a79) -,S(e4ca84fe,307c9237,4d39b2bb,b017b5b9,e478b26b,95236b8d,5bdfb220,f44419d,c0cfc7d8,92271c95,7ef235f7,2f310c7c,7d0ac297,97d42ffc,ba37061c,83775507) -,S(8f1f2d2d,cccb07a2,a8716b77,8c74f3fe,22990d36,b951e6dd,92f5896f,51bc23aa,9eaa792b,426d3400,31a862ca,b805d0da,ed9a4c73,591c204f,c5179b17,22aef870) -,S(20f7f6da,86eb5ae6,6a1b7818,43fd7fe4,c458e3e7,bfb590c8,76afb601,257b2ee0,6dfcd6c3,93e7e9dd,32c7e826,42f90d69,ff1e1ffe,18988de2,bc1cb9ba,db246fbc) -,S(3a3df365,8d65d718,2dc05797,8bc48fe1,5c5eb6d8,6bb241e5,9e178ca3,9cf9a010,ffb89791,7435e8c5,4865bc79,52fb7bd4,1578af51,6f611c54,1f7cfd5,651b293) -,S(7aa435,7dbbc5b9,a01b5f94,6b0240a1,36daa942,1ae1a1c9,b50f66c1,c7f15e48,4640c8d1,ace8f69,6b08ba1f,9a46d04c,f75c5914,3339d5a,181a7dfd,bfc92c0f) -,S(198e4848,8176664d,40fc14c7,acca9eb9,aa22599b,b2370959,5856d78b,5e932e94,fb9dcfdf,b27d062e,8ea5246,275d80e5,6fc7cb09,e81bf066,dfca888a,8df1de6e) -,S(25da8876,d3215051,75694915,c25056e1,2c1329b7,7795b7ec,1d4b66f9,3c911cc9,b8cf4a83,db78787a,6d80a157,c7c205f1,3664a71d,a6e78db5,b52b012b,930c4583) -,S(893d2e9c,3b6fa8e2,136994e6,14121842,bb82e577,89826ccb,eef51fab,de32c0b,d7cb9b4a,1d49b34b,f3f743f2,10c32a25,cf8df45d,8552a7f2,1268e270,ee6fed67) -,S(dde2e8a2,988fd777,4959457a,5c14384f,c8248d1b,a32c7ce1,a727af27,7b217688,1fe0272,137e4c9b,1c6df618,41a240a7,be3b5de1,7b93fa24,ccc055f0,e7972b1) -,S(52a73b51,5326198c,81bd988a,3033e1db,abd9ee27,9a91a434,e7a76813,453e27c1,c23130f,c4b8990f,ee308443,1cbeff25,62963b1a,4a5acb4b,a1319b4e,d77c745b) -,S(1b5afdc6,4598bfee,4ef31904,f0d06796,17b0149d,ac19e7ef,a1d4f19b,c5385490,fcc0c62,47d96d4e,430ae0e9,c19dfa2a,3719e66c,ce25a2cf,d7428d4,4c91e96e) -,S(76da558b,d533e761,4d97b7bc,5a1a98d2,af043ce1,1f2b323,185377da,c0e0abf0,f8dfecd7,94b3d069,ec22f01d,8418bd90,27c3dfc0,62beb597,e352bb70,271d3cee) -,S(17f01b77,d2417d97,e3c14f10,18af67be,c12c31a3,58521f6d,203f101b,227cdbc0,fe16d66f,a194c800,e3c14bb3,f1df0a2e,3ec319a8,66c69d9b,3b492d96,327bba04) -,S(6010e0a1,2cacb745,6e3a8f73,d5219a87,cc14dae6,54be7265,ffbf70c8,c4d5433,7d5f0faa,579afe50,2541a2de,4d525bd4,e7b950fe,2b2dcdb8,d67d3d9a,7b11da54) -,S(91e938c8,3f319320,baa876fa,23773a7b,d0fb81f9,bf9d99bd,13180560,bfdfad6f,b662f401,7a4fa2ff,6603864d,77a6b930,181372f2,5fd6a67e,12a1df6b,f75509ee) -,S(de2ef2ee,633355c3,3d259357,efca96a0,5b669f13,b515e64a,c0bc467f,2abd665e,d3d6254c,5c30daf4,64843190,7c2a8c1a,51baeb23,13605a58,b88c9a78,a6147c73) -,S(186151f0,dc37e48b,3178bdaf,900e7bab,49cf251f,7a2a1b8a,76da8750,2dee93a6,2a240dc,acbbfc19,876c3680,fdbd7ee5,d1085b79,96317e4f,db73d5a1,9f097f8b) -,S(6f19619f,ace0c63c,4dda566a,9a1e78f,a9568db1,1c46f3e9,771756b2,7d8a5c1e,4716efed,7166e06,722a744a,af89d145,4ddd2f0,f7652862,cc38eb3a,2beb1925) -,S(a0e450d6,fb8a6da7,e8f6e62f,7a08c2c7,277a832b,4e5c6dd1,8cbed37c,37db23a2,775223c6,3f81b2be,1bdf0831,9ed65ab8,d3e11c56,38830851,d55a8893,730979d0) -,S(6337ffcc,64f5d358,d90fad1b,646d8d7,46e2fb7a,2a6cc378,9b55ec52,3824de5,98286287,578bfd97,4c161a01,55f9a2ef,707858e2,a32c3fc7,319416f8,5a6e5427) -,S(914a8565,cc1bcf80,19e1eef2,87c9467c,bc42faaf,726d4399,6485efe4,6f99e32f,846c42d3,b1dd8c20,3a744f5,560396e9,b9a92380,2fccffba,c6ee22c7,65bffde8) -,S(dd79a02e,2460ef86,cb4e9ba8,3ee7e231,e99b3303,1d4a6d7d,6dee8b1f,b0050daf,d6a75b67,ba13f76b,172ae0e7,d63b20be,db3e54f9,e54a96d2,aebc326a,131ea271) -,S(b2776e23,3e759f8e,38c52394,d50fe177,c6842acb,f238eb56,c7638549,174c1b2,e18c89b2,dbb6453f,7b610518,8bf090c,f0410e51,97885d52,b50b2507,ffe4dc81) -,S(e0716c4c,c5e84f7c,282adc42,f294a36b,56bb26a2,58cef4bc,c36a7f53,1d5283e1,1442ddf1,57491db5,1692c7ea,5c92976b,8a2488b6,6aa6f38f,7a62946b,a24fc5bf) -,S(2b10c9f1,bfdd659d,9d1e073b,faaa4b13,2a08b678,f757ef39,a137e53c,b291df70,7d22ac48,f4e0aa71,8cf7882a,57a46746,94e0f456,f2cc3aca,30a3f8d4,2b240dab) -,S(fa762181,26a4813e,e97f2718,c6eed96d,da9f6912,ac463af6,a52f3aff,f80f07e4,8c8a04b,f38e2599,4cfd8905,27ace017,e57e3f8d,d378b205,2e767954,80dd5701) -,S(6b893eef,bea81e30,7ece156a,e79abc26,d9f0ca5a,b2dbde11,bb0d8192,f138e58e,510a308b,9fc47167,f72bbc4,f92eebb9,88a6512a,b1679102,f9016b0b,d82c559d) -,S(6cd9b970,332f421d,1aba33e4,75f26a4c,5c5fec37,4a549ac6,d8c10fa6,cbc40032,b57dbee6,68bef693,67188a54,52e3b4d2,cf1c8c25,8e36bc09,432b4f4a,dcc24086) -,S(ba4847ad,40530fc5,f77ea79e,ef7a1c0b,821b5285,5ec4ab8e,d238ce46,48a09fa6,627ba437,8e0f2044,20e61431,5f3d110f,2da9cbe6,2025bbdc,5bc1cede,c36030c9) -,S(92837329,4f59a142,ba84f897,7acf2e7d,9df06a27,74ad88d8,98689900,3750c513,4e938012,b6e55d6b,6f7871ae,c34511c8,40912a1,1a32012f,3bdd27b7,90f86c37) -,S(470c19f7,9aeb9a7a,142ba010,10ea4929,3de57e25,68658d45,42b5a626,864600b9,2e99dcc4,b93d9a36,7544b842,ef4a3085,2e24bc41,e98ff2a2,d9aede05,da703225) -,S(2496996d,c38e4bbc,851f9bd,f9a21b42,5fc7ce2f,2b06993e,97604a0e,db555c34,b6e02a63,f0e2e54e,1cfb9d28,7607bae5,8a68ae6e,a8300ee1,c1170f0a,9e567323) -,S(92366ed3,23ded4df,f4029e42,685c51fb,a8a916d1,999c42c0,a90feb44,4112a78c,88dc8af5,f6d1d14c,5c09d216,8af0e752,3fad76a1,5b311021,7ead491c,12b63191) -,S(ff9760e1,ce161564,22c4962,4962d89c,37e66e64,cd7f8e94,4125fd00,c05974a8,8ca4457c,a5e52e23,d70639c,a9a26f3,12312451,8f0de070,86d385b6,777a63a8) -,S(50d1d5ad,79f919b3,d23c16b1,428d971,5deb186f,2b92b64e,7a1ea1fa,dfca4981,ddb07de,d4ad81b3,cfefe726,33521be1,c7418c5e,aa759440,20dfe92e,b4653ce4) -,S(4934f753,29844b23,80183df0,254d1c7d,342d7d27,9fa5e804,68dbee16,4e9c2c6e,a4f8aba6,7a488a33,40e8e943,14f7eed,5cc25487,5acbaedb,afecfc2d,5405609a) -,S(d7b99142,9cbdf755,5cadf030,7b2c4a91,c0d25710,a0553511,eac6afb4,c544ff81,17bf03a6,83b1a0f2,366b944c,aabe57d4,eac4d86f,bfabd006,66693983,e0241420) -,S(834b036c,145d6905,58199bc1,e7a7bfc2,4831417b,530b0b97,8cc1fc16,af00b966,4a45a9eb,299f24a0,1c520751,2cbee44c,bfb75d0d,14a7eb08,b1668b58,ae58c47d) -,S(d7a8c30b,fd7b8aaa,78dd23bb,86ef2624,5a363857,6ed69739,25ea9d9,194bfb3a,7b5f9ce6,380abb91,6e041388,13baaf24,229ece27,3541f4ca,2883ad77,9e501fa6) -,S(ea4c7ed2,7ced8b13,4a2ccb2d,3828d29f,f80c4825,e5607597,3faace04,d2fb7763,a8454c9c,be19ec44,8a3234ea,97b8fbb,b256a148,11ba0ede,becd8641,42684d14) -,S(a2cb70b,f80d9f6d,696ceaf8,fe8052bd,e59215a9,99d4b92c,ce806a19,71d555c,997bd94c,e5cb12ff,886c1cac,bd21c3c,e2f144f0,3af644a2,c2aaba2c,825f75b5) -,S(89a91f5,c7c8700,175ab017,8c4104f4,a927af06,f269645,36cb78d0,19f8b8f2,6a2f8ebf,e1258b4e,31bf9a5c,31c51a3f,1cb58aea,6e18582,3e87920c,3df8e7e9) -,S(27d7191a,71ecb0eb,71b43dfd,5840079c,bd368c0,5ce62fdf,2967dcca,78f5a6d6,11120002,d0d0fa9c,8db51506,4e1fcc2d,92d8fa9c,8b454294,bfd01c64,889d5e6) -,S(cefb996a,d36deffd,c3c7ddbb,11a5013b,70baa98c,1057adfb,185b4c9,62f3384a,c93cab46,7523b0d2,baef4425,c9ff048e,c586d4c8,69c69cff,3ab9d72e,e3d80f83) -,S(5a8ff765,84746f42,4e06b557,77986825,e91312c4,4f79003d,c1b381cd,4fe5ce8f,3946177c,3c741458,7bdb9506,85ad0c73,b422a8b2,5cc3ad3a,cd486e76,99a42f08) -,S(b179dac7,d2f400bc,bb039f32,91e813e6,f9a7331,80a1a5d0,db51aafb,af582fb6,89a70304,d70cbb61,ffb3a499,1815cb17,458404fe,e43f09bf,d630d480,5978b1dc) -,S(6e14a53f,ab32be84,4eb14242,a3b6a86e,e178cd7,51dbb7a2,b14cb763,ab2fe6de,a22ed4a6,d98c59d8,ca85e111,cce0efcc,60e20df9,6b06615d,69aa3cfb,206494b9) -,S(12ac42bf,d8f919d8,c79a8138,1aae69ef,b789a573,f58332b5,79694dfd,27e7ff20,4ebc3b7e,4b0136f5,19a8df5f,baa7ff59,17f4f632,f85ab1f2,ce502fee,bb3a3a87) -,S(87bf22af,5e9dc061,eabb01c4,eaa867c3,4656599e,da744da7,774fa8d9,aad68630,d34f530d,fbea0d52,9d2d64d1,323fa44a,d80cbe01,fa2806e5,ff069e6b,fc0ce729) -,S(33fe6bd7,ebe2b197,76251415,8bf866cf,b6d3ad5e,1f68519b,edb513fe,6076c96f,c5970cce,f44aa84e,f95a56eb,588b7a8e,d9164f5f,5a2eed83,1f70d308,2320e9e1) -,S(5fc2f44c,fc0f7ab9,9f03b67a,d7b6ee99,d73fa9cb,d74eb5ba,6d931d9e,26ba51af,8b1fbfe9,de201400,6c07da02,4bbcf53e,13bb9f2b,ff3dd6d9,5135a6fd,5842f0f0) -,S(38fb5cfb,e4f348cc,1fa7f9b2,ea600daa,e8330aca,53308f09,b6a7d8b8,5ca8a88b,ac1bf91b,7f53e824,d845c0f6,9534291f,cec2808f,95acf58e,4afba07c,fc735be9) -,S(3ec2457f,fc848504,6f74912b,5c58b270,1be6eeb6,f88da0b3,c5cc4454,48750875,b63209d2,641c65bb,7105af10,61d7513e,409f153e,5d1b5073,232eacc6,f76dde22) -,S(32fe812,e67ef62c,687d248f,e75ef399,48fe8ae4,a01ae10d,ed65264b,fb5050fb,d9c85369,db22ddeb,baf7682f,53642962,cfec2afd,3a20de77,588e7473,18044f6f) -,S(97d7c69b,2aa0277d,2b20e9c7,bb1066a2,be6f443f,d0a428b6,d78c5fc9,6ff71b57,f84ba781,70837aa1,f75936cb,fc50c444,c40c9fa3,22d90088,ac6889f7,e7c0f861) -,S(3621a4af,4d698e4b,60e7f497,6e0c10e9,ca32834f,ff917aa0,6aff912b,2ad80cd,22cfd248,a17886a,ae5d0e11,53621e9b,46289acc,ecd8155,a1bd6372,120c4da7) -,S(ae79a6e5,848b1dc6,cb64958e,87b737c1,858442b3,63d4a2,e9f04561,7d73f8c7,c147238c,59885f2d,dc5dec63,de421eb1,c5a19438,ed0600b3,4c77f4e0,e7aa557a) -,S(36eec623,700e51e7,723a632a,55370ddd,d6b1f917,6ea39a2e,54a2a1ac,52598c35,29698c0e,56b4e2b5,5389dd9c,3d8b509a,e0b87f99,4872d865,3fc74269,7f5bb7c) -,S(50f70061,804dbeab,cf2ab4a9,87ebde2,1f5496c9,a4cd28a,4dd9da7b,310e876f,77e27710,edf831db,6ba9e64c,545f03a7,eb390842,8d9cfa3,3d0e1c87,61371706) -,S(c2ad6b2d,e84bf60,7fe77b8f,a9fe26ff,bb5e1906,1494e469,8da44a33,25843844,17b92ad9,d3938fef,7a17f543,a169a7ad,8ee65dce,36eeedfb,5e3c0c8e,a1b24fc3) -,S(a53504f,e2286269,427fd2fc,fcb64827,bdefdfd9,feb89d50,12651d2d,c60ae99e,6b9d73e7,e046d11d,ce78b114,8aea837f,770d8267,6642dac8,f3b3c035,c10eab45) -,S(5410db61,40a77b31,9f19c969,34a8364a,4881ab60,ad76a6c9,34f317c1,1b658dec,ac45bb6e,2e5fe23d,57297370,cd04ffdd,dd89a9,15a1e9ad,15d7f9e7,6d8b3aeb) -,S(882cbd69,fbd3e262,5093385e,ab82fc9e,7597c38e,45fa5df7,f98c94a9,3bf25467,2083f00,b25b28b7,f92b040d,a4294dc0,8a3d97e3,d951e724,da0e692a,5737a87a) -,S(3141e0d1,22b4c136,f7793c73,9c48f308,c5ec8043,19db116d,64eb14f5,aee83942,9c2d06cc,d765c6c3,cee09b70,247f8806,227d0178,13becbb6,96c5a344,b68b33b1) -,S(1b2f3686,5a63df41,65caea4e,305d8d66,1de6ccc1,c2a28cf5,2373527e,27cecfc,1239d8c8,d60fdcb9,fcf3f5d4,63305037,6d47fd97,4cd6bc64,99e0e951,2d2209a9) -,S(725168cd,9fd59e41,14918b77,6ea96fc9,6315b4f0,86672dac,1eaf59a5,e61ed25f,946f03a9,84a6735d,e72acb38,dfd21905,fa2358a5,e66e7b0a,2f8836a1,8f5d73c3) -,S(4207faa5,c9dc9622,9644df1b,a099a84d,654ec6d2,aa69efcd,a4a31a3c,61f2e1d4,ea72a92,836d1597,5275c18a,900c0e7d,d0502610,d97b6f79,1f6a28c2,1b3ddfd7) -,S(53900d38,a4740830,a6129a11,9dc90f6d,30f32847,708d48d4,20b77764,ff5b9cc7,66822ed6,ed941eb2,20aefe94,4325daa7,a619dfed,5c76bf75,1fc25342,8178d3fa) -,S(d0204932,a3fb8d33,9779851c,d69f6adf,be1a9957,59fcfce1,b8d4f047,e4e4dd2,8ded18ff,bbfc663a,9c658ae9,286f82e0,9ee9381b,3291f5c9,efabf0d5,fae318f) -,S(3ed8ce15,2d34e621,94b8b16d,55605766,41fb2673,14a08c91,d916fa14,f21abde5,48490fe3,9769c60e,38996370,27b57df7,230060c,2505f414,5a1c7f1,4ba16660) -,S(b7d57614,9b5e2ce5,edef3c30,b8cce79e,6f122c70,351d04fc,ed2b67c7,f5cb2aed,7c8fc1c6,bd42b25d,d45e37c2,5cb06f0a,bd2f7051,4a50e6e1,2a67c0b5,b199eda1) -,S(2489e06c,c8f0bfed,9d5ea722,c07ca795,e9ab40e5,45b036e0,f0c11f28,53c0d35c,dff65f5c,20766078,9737f1fd,5af05ce8,3b8edf91,37002b19,f5e1599a,e76c48bd) -,S(9b2140e5,509817c4,465e6689,a3bdadcf,b79c1803,883d493d,4e4e99cd,55f30a29,86374501,705fabc6,62e8c869,a22d2813,f7106006,ee09b6bd,b582b690,50186688) -,S(48d6fff7,d5c37c30,11c9e63b,b3342f92,776060a6,dd179e3a,e2c6bb69,d2f88b3e,783353e,adb6daec,536d37dc,76ae3ff,8dce14d9,65d21d3b,7a17515d,7d3341aa) -,S(35d46a17,b6951355,a055e253,42b4244d,8ce65459,c630f2fd,4708687b,e6a49e7d,13bc21d5,7cc2954,62927cf8,bc31ef3b,5407021a,62c5253a,5950e8eb,b9c735d7) -,S(17ba438,24168f06,274b2f5a,d080fda2,3c0dc34b,f77e81c3,c4413cd2,f594575d,e8b34f9,1ef09f92,7b5d9e51,662216a1,30ef8f87,2e0febe,3f5cce8b,318fc77a) -,S(2a09e4bb,4f6d6b40,f59d0299,93eeea7c,755eb00a,5eba0477,3fc0c796,aee68a07,cbe72772,e5d8b761,15ed6f92,f20028b7,cd06aea6,74e10667,899e78a3,df403f0e) -,S(f3838250,e9a03da6,87139583,2bc6b35c,2d427b60,4cb7d25b,149b6816,235b0e4c,164b211a,60562190,d415bcc3,87d1a147,66e45f14,dfbeda44,833ce45f,b815598e) -,S(b307de85,c4c2e8,4e076d19,647bd205,8c1a3c96,a0261481,322e73f9,f4a2e94f,5af7f6f5,ae7f65cb,b62f021,608473e6,b68d032b,4835540a,f265049a,e506b2d8) -,S(ff92c7ba,5f89d3d4,5273688,907ab9bb,794e5622,f8f300fc,804934d3,b5820e00,3b2e2d1c,420fafaa,e53c9da4,957e22b2,bc76ccbd,99f323d,763fa1ef,f92ea71a) -,S(49630ee0,a8ddf91d,ea678a3e,1dcb623c,688b7c3b,9e39196c,b578d30e,196e63b0,4c1aa073,d1375475,11d81776,e2e59404,aa08db5f,95b80e56,c39613be,fc2bfcdb) -,S(d41ead31,f2fac884,e762ccac,85825cbc,6ab2f8df,a069b2f3,fce3c6f3,d5c95a33,f15e3e23,e19baea5,677390cb,acf97180,86876f96,50fac740,9b6e62f8,b6d40652) -,S(5e62e95d,27ba07d0,781ad685,75a7a11d,df9f2776,48cb5cb0,869ba586,6ff02869,291717d,1a1ff532,e92f0311,881fe2d1,6c8844a,6f5ad7f3,b1ced51,e5088302) -,S(dbdd4f57,1f6d01cc,8a1025ce,3b92ce3d,56d396d9,635e456a,fd856239,27b53bd5,b929d5dd,816bcdd7,78abd34b,c15f2fb9,deff3f9a,aa44de0b,9f7b46d8,b8d70373) -,S(63a8349e,1a891037,9a74a60,babb68a1,4c8cda6f,c2cbc0e2,1a5aca7a,fff7a19f,38858c42,9cfb1e49,5fc90633,ce07abf5,b7c4a4fa,22b955ef,e2c137df,143ec70b) -,S(1805ec70,2cbb1e4a,5da4841e,9e24afcf,b84a3e45,dd6c39a6,cdb6a661,d5c6b1af,193be01d,d3f28479,e352f164,de99d21d,1b3fe8c4,b0af8587,8f21c858,cdadc27) -,S(2d6ff24d,fcfeddca,ab3b19ec,b6a79793,7f5c5d3d,373b9df0,6ec68549,6d075423,b8bbca01,551b2b3e,f6ec3a37,ff020f3b,6b1f5456,69bd8b90,f8a55216,3fb48fb6) -,S(3aa21099,52cf0464,4bfe5de8,69cb2d4a,19d3c4c4,661d6782,967dad8d,cc353a24,68252574,69dd7940,fbdd26a2,483149f0,f71a4b12,fd25b063,73765c52,d45985af) -,S(d6422a71,443b0e37,cbc06f90,4ba1f62d,c2351b7f,e4e0b909,5fc227a1,7f8f551c,ca92a69d,2c9aa758,46c2518,f1ae03c0,d7138170,447b55d9,37108604,f71b9feb) -,S(51e297bc,46529246,a36f8460,f285d713,b1e9ed67,2027eb35,37806d5c,7e756177,5d56e447,63bde166,b456531d,94be0d,7057081b,edbbb89c,be8c4732,13eb0ad9) -,S(378a552f,c061e796,c9ddd101,63851ea0,663f09f1,3fdf852b,ddbafd7b,bf6c258a,6396c9f2,a26b62c6,f33b73fd,98824958,8cbc7c10,e679bd4e,ea0f4ab1,dbf38f72) -,S(bd85fb00,1db4f2fe,95c61f1e,825e65c3,80761832,37be8a86,a20f6fc0,7a586daa,52c21cd8,9bf874ab,7d7e0f4c,d0095d7,6e8c737b,e2ba9d1,a21fb795,d968f61f) -,S(fe68e6ec,3c8e681c,e7230a92,e8762f0,af3e206f,f3b0afe8,be61ab34,2ca076b3,f8683d06,af0c88f6,93a0a6b3,1200cd25,ea2c7e9d,2b8048f8,b983474b,b1dc20fc) -,S(83e55d38,bbe2daa9,f8147b1e,674be115,d919445f,70d2b3a6,cb917a4a,9ff284d1,92d6c7f6,dbbcdee5,8b11a244,34cbe7c,9f9fc0dd,c93f6fa8,b6354a06,5bf90ab7) -,S(fc9cbaca,ed0e1df5,e9d8120,6bb55f26,67e114e7,30347030,8b333554,d0735ad0,d41fc02f,2d4b3f74,f4e9ec00,7a879540,54d12fc9,3d53242c,a45bd38,c75deb9e) -,S(7adf7a3d,12268d0f,c2568d5b,ee296d61,fafcd739,f081e5a1,7b39fe7,40132b05,51aeb855,a84f377b,899392c8,a7daa18b,70ec2a94,7929c93c,67ed8217,41adaa21) -,S(e9631ea3,7da9e68f,eb61f9c5,6eb91bb0,2fdb4d58,d99874c5,2c4af40f,9716aa0c,51d5a6ea,1a5fffae,39c598f0,158272ec,bdb48c4d,faa93da3,89af20a7,d2a1b8d3) -,S(e892f70d,15639bdd,ab70739e,83ab9f04,963e1dff,e2bd81eb,e075173e,6bdd116,2e78cfa8,30b68c55,68f635f1,b260d823,55f38ed3,f5f43c33,b178be12,dc006b4b) -,S(6f3ef2e1,e8d4fd02,2533f4d7,410778c6,ccd9a7be,aaeb3c8d,d9f01699,89598def,c4388130,c278f8f2,7a9947ed,4948f8e4,febe81bb,88bf873d,2d565b4e,3481b86) -,S(cf24cd64,84b07e12,37640f0e,da7e776e,3d4db192,6da8e929,19b36383,15de412e,a353cd6f,a796c46c,49f34c72,64d36df8,6d53f556,a36f430f,7f3f6ac9,3527ca7f) -,S(a2e98e5,36d517d6,528d6353,8bc2be93,4eeae1c1,cd8dcec7,a60080d3,fed33749,205e752c,49a09b0c,8804cba0,62b28ec4,6d9e8f37,9cbcacd4,a7cc9049,47bfb296) -,S(e5ef194,498445cb,718f7c77,6aecd0f1,949a4a49,73e32ce9,a4915867,dc27139c,fc774f2e,1e51f03e,71e637a4,158a0013,5aef5a18,b15ef0b1,e5696338,82bb513b) -,S(311b36a7,1a1d13b8,29c78813,6a989c0e,1b7039d4,d75110b6,ba97f000,749a8d06,2f441c15,6b80f4d,51dce0d9,bceca566,2f3fdd9b,965a0d84,55f6d154,3a661f7f) -,S(324420fb,a5076214,9be852e5,ffb88d20,d1120e1d,2eb9c132,32bdb13f,403a5f6c,378f5d4,1dc1011d,1fd338d,b6073df8,903fb4c1,e17b2122,bdad5eaa,496965b) -,S(7cf4998f,5095c102,a0db72bf,9935ca91,eac814c5,4120eb0a,262f246e,ede142d4,73e6db13,d6db9486,fc870698,7be096f7,7440dd35,67064888,e61dfeea,e98c1fb3) -,S(d6fe26df,d501241b,f8c5e74f,e30714da,7d690be0,91cfbe14,68ed6bbe,23598f7a,102c4907,60fed9b7,239c0443,d01f2742,fed0a0f0,fd7ab9f6,9fb1c58d,c5752fe7) -,S(805ee58e,66ab8020,c9c32afd,4c7fe30e,960f4c3,ae51e94e,da9e5242,af09c6f,19154d86,59fb1837,3d0adf6,daedcfc8,3937af0b,ef9a7d15,f990f60a,c5457617) -,S(491717b1,f22f93ba,d0a3cce4,fac57160,8ad7a746,ba73d375,1713e605,8bcd8450,9c38b3e5,4c89d38a,2307546f,f46bbd68,d4e4ad08,cc45bcc1,575fd120,acdacaff) -,S(a8e23e38,27c54d4f,ae2589ba,cf3c4e1,93f97e59,b11506f2,2016fbe,a9fc2522,ffaa8b74,22b50822,dadd781f,d31b5a31,eb384c50,2fa0bc2,89252665,1c602f3e) -,S(9fee31c6,88b0f7f7,78a39786,a84567e8,34da7ffb,350cfdc8,95d65c4a,afdf69c4,2116e31c,2a0d25f6,48a3ab47,1c897484,d71dd9e5,c678af4a,292a6388,d9e45e94) -,S(6256ced3,f08f1812,ca7ad618,383f1542,baa2bb06,332d4c1f,72d862c2,318854e9,9ae0bbd9,d2fd51d2,9347aa62,12b6c0ca,be530b55,bfd8cf18,6732be1e,c66ced06) -,S(ca1cf364,a5e1f47e,cd0ab0e7,52e785fd,935b8c37,964c5654,2cfb3249,a136d669,17412d75,2f350795,30db27a1,7394c362,45fa376e,d20583fe,b9f7a7a1,2c3b67f3) -,S(19004a4b,28e5352c,7c74def,cf129ca1,cb5c7dc1,5099b37f,dfdb0d5d,1e694400,68ed1edb,9ac650b2,965a4034,2812a692,23b3cf6f,24ab0a05,2e1b8eba,f7335020) -,S(c605e97f,27199d86,18fca176,54e44c9c,8dd20994,aeae0466,dbdbbf0e,ffd1b3c0,606955ce,33ff7b6a,cc6de4bc,4ef80b34,bdf6ea17,b29dada,4ee54f06,f61e9d22) -,S(3e89970f,15e79b51,fba90202,a16da6ec,3d3d5d53,72218d72,bbed0626,31affdfe,5d9e27d0,bdefa8cb,b02ca682,a062ccb0,61a8fc47,b2cc72a3,9b687b45,5f83182e) -,S(c077c861,575ab0d2,944f8e65,8a9dbe54,9fc1172c,6b7b7428,476af472,e625d5cc,c01e7abf,6a3abe2,d2aa2457,76068afd,9ba78fb4,fa39e531,8155597a,90fededc) -,S(8567c87d,c12f1479,5f351d1c,807604c6,636c670e,11edb286,92552ab,382ddaa5,71f0be2a,12ebee63,8a63e848,fc4d8116,e2dcbf99,ecdb15ae,1f4ec6c,84f359ff) -,S(9f1b7785,7421626f,87978ee1,780d0,1e9d0b28,df34c2ad,15332b8a,d94d8dfd,6df504cf,66144d9d,ed530e2a,1436a4df,634a84c6,9de752d8,42e076c9,1f129b8e) -,S(f45c2c6a,2754fc31,c5770e3d,38b19e72,47b0dd1e,5ade8ed1,f2f3219,ea7accce,ee07ec18,8190ce54,e736ffd2,912075a1,128d24d9,b178a7ee,72aeb6e4,9b593f4f) -,S(51a5441a,f3446fb4,cc63ece6,c9650a87,2fa5567c,4918f5b4,ec8668c4,ddba6e0d,413186bb,adad4943,6abc46e9,280a1571,a97ed7f2,a839cad2,935675b9,d167a54a) -,S(adee3e1a,e9a2ab1b,da34fd5f,afd3b3e4,f51255f3,5dbd94c6,8efb994d,afdeeade,f330f0cb,973fd732,eda39ebb,82dcc589,4c148165,428adfa3,b4ff865,1ea83e24) -,S(a8946504,eb084214,d0153ac9,c3437fe7,3ff5696,16e01672,413a62ee,27c97db5,3dd63d46,f74a56c7,2cd5d45b,5bd6f2a8,d913300f,b4ce536a,e504d4b1,b2e311dd) -,S(e34ce586,990e48c5,febc2fd4,70770cf0,4c81c782,3702cb5f,289be0,f4a97205,d1774a35,cdd7cc54,dc68827e,f7c723d7,5c167982,c314dc62,bba17478,611f5854) -,S(7a8a5d9c,edbc4c76,1fdf2958,8289bea,d524edd4,f7cad978,deaeca8a,de47435,559d473f,3a9a7ee3,4ee0a1d0,4acdffc5,6766db36,94fbf08a,5ccef8cf,31e25b6) -,S(848cd57c,62c67249,d84710a1,5c7abc27,93fcba46,497a6b0e,b23c2ad,f8acaac8,a48424a9,59922131,31a763ed,30369b72,b331d9f0,cf46f8a2,a15515ed,6726f735) -,S(6afbce14,1f2d2c4a,c52e7e05,5ba6ea60,7612a590,d74a2a5c,1344cd5b,c49f2f03,910d69d1,cce10aca,bb1593be,2d4d4d28,9745f97a,29fb78a2,a1eb6f0c,a58e4b61) -,S(61f3727d,718644a9,2e08ab04,814c4446,c5dfae82,c26540cb,44fbd310,a5315a11,56665e3,ee6edadd,a154563b,11fdc203,fe4365d1,ac36879f,a30778c2,badab836) -,S(582962de,e00668e7,91741dda,8e86ddb7,b8ff7773,ac1ea51d,1aac139e,a810f3d1,6bd353b2,e004d66,f1e90cc0,7c68a0a5,b532e709,75a7bc58,7a6b1c67,71022f6c) -,S(5c4426f9,f6071fde,a9304e6a,4a2374a2,e2591225,28b62d20,5fc3016,c471b636,ff6e8c71,fccddb0b,5cff9e2a,10c606e7,c571245e,8f5bb5f7,77e0a7d9,733560a1) -,S(ee02633f,c6b41f01,c3c24c33,719db7fd,a9e04b1f,7070395f,e8898a0,efbf6af3,ecdab00c,83cb3465,1d48a696,6a8e4f03,ebecfba6,f73a66ec,4d62a668,48f14798) -,S(fab36b80,e5bba465,63c9078b,b727e0af,c9bb0af0,2e394f9f,2c90e0e,fe9fb816,75173a7f,f5599da0,ab84519,c7c25be4,1f10172f,fea39762,8e7dab7a,3ecbcfa0) -,S(68a89a2,62015a57,5f882215,48c6d3a7,b4ad1f92,f5665980,367107a9,f4cc37a,43ea7b7a,79397dea,c8354436,d53e7731,c94773d1,5b067063,b108c559,c05bc46f) -,S(fa6e2972,87a0e97c,35454378,4a76fb0b,56106727,136474d8,a3edf8b4,e03f95f4,1e80751f,9c127fff,ce28ae,8ce5afe2,eea1c566,fb0a9f20,8030cc96,e1197725) -,S(25474cb7,805d22f8,7a641116,34628321,f086d1a0,40404c47,ebee913c,e9e02a6,2b3aac5c,85ce9672,61757c61,d6a72dd,4ff81e00,87f0b8a4,999b927c,7b069609) -,S(6f7051ef,10fc1485,a9c80ae0,8683397d,c0af15b5,f78fec70,fe4c456f,f33b6689,625086ce,ab7a9173,d9c370c4,c336c63d,2aa85ac7,b8391993,7ffe4118,f6a7b849) -,S(f4720462,2f579de0,701f1e90,558c74b4,ab634664,197c03ed,a85b0fe4,50df4951,c66a490f,f9b588c9,2d17b80f,7f66e5fc,a65187b6,d965e81b,c16039f4,477fdb54) -,S(3b718764,7e722fa3,de42fca9,e3ba181e,de982728,5b8b006b,d51a58e5,ed898c8,bf872047,f3cd3ea,d7a439b,9d4f7776,7175f940,d6cae8fc,930aece7,e1b92202) -,S(5255ba09,df1e199,4c99bf21,709849a1,cd7c4f58,a283e344,6b98872d,a416c40f,a1099eee,e3ad10d9,6bce7a58,839fcaee,1b43e0fb,29ac0300,4e0eb15c,63d1f604) -,S(f4b64a08,16dfe224,595d3a15,8173df8a,7d941a4e,968ac02c,bf87d9d8,93954805,e5585209,2d0cf600,b8b2342a,8371894,f422e3b6,68ec4078,2379a60e,944228ee) -,S(236d83ad,b789d7df,5fde69cd,86d45d5c,f20c5867,b7f2b398,b9373960,b22b29ab,9758044,d3e06295,e33bebaa,befc5776,5db45475,b3aab963,5fea8dd6,77a478cc) -,S(42071659,65af2fda,c9e87319,6dd0c723,e7d61bf9,b71e5e70,667c9858,6371f3f2,fddfce02,588c1d4a,b744301c,6117e504,8f9c2636,5ccafafc,8a6e19a1,ea7b1b37) -,S(7d0c2917,aaa71cf2,e79f1041,5e5e583,ff01b24b,65f1f409,240f794b,d346a452,1e857dbc,c86c1032,e748d8e7,c8f5839d,57295223,22e6bdb6,187b00f1,f489576e) -,S(f0609605,d6e39141,e5e4f0e0,6bb6d55b,9ea2ced0,6a58d4e1,7c46a3df,18257255,e6d54c0b,10826de6,e95553ac,e4689fa4,cb03b959,65472e65,a085988b,d045374c) -,S(86e66299,819b0807,af30c89,228447f3,71fad56b,75f238b5,30bef3e0,b1123204,de635715,b1997f4e,c367bcf2,8f8def4,7a7a2069,3a555b5,396dbe4d,19b1e8ff) -,S(7710dc40,f72bb934,f5f9328a,1284efbf,fad3518a,70c2a0a4,55028bb3,a8b87e9f,d2ebdd39,7dd91ec3,7ffcd8d1,a9b412c1,78f6d228,5e099162,76f9e8f4,a6a28e02) -,S(3d377c80,25607e9a,fd512e8e,7c37a2f2,8d316701,dff7f318,eb24cc34,348d935f,20d2d95a,e8503a11,de19db36,5bb62213,6cd55735,966c25cb,2a56f07f,19cb2664) -,S(812a4ad0,d004003e,fb190ea9,336659d9,7b7d6df0,29f29f97,bc9c8d68,f284a696,6303a024,b2d95d18,f04fa94c,df3d0749,60ed45df,584e16ca,d60a0843,551f94e7) -,S(51cb80b1,9c0dc55a,888421e2,411baddf,6c0eb167,ed9bd04d,294623ed,1bb61dad,d14f756b,f905da5b,6466bc6b,26685501,1fc90892,93633c74,479afacb,c34559f5) -,S(837afe72,82af09de,108711a7,998dd45c,36654f3d,a3cb392d,c46bee0a,b43cfc8d,88b0ae50,5c30a2b5,72c0f69,8e7ecfea,87ea1253,ec133fe7,fb2aff9f,6adc2e15) -,S(ab967cb8,463da438,ad360a8b,3e066669,231fbd,cd590904,fe827ecd,dff3cca7,d82043ef,c614db53,8d06f6d9,9fae98e1,ee6f5065,31b05822,ed2141f3,25ebe544) -,S(5a0b6177,50d828ab,fbf4fbca,576ff8ff,5bd19330,bd357eaa,a5564e39,c718eb49,f6e8d743,e528429c,2cacc478,368d7226,823a45bf,358d9128,9da334b8,5a1b4426) -,S(351b4334,83fae045,ce964f04,f63af62a,6964e0b3,5c1444ca,68d09edc,9a43c9ea,f571f442,7b308ac4,83bfdb4e,87987455,a2a49f77,73220511,dfedc616,20bc18a) -,S(fe64fb54,727ce446,c00dc3cd,5de496e8,2d5a0e9,b13a9a7b,99a96a49,2d0d288d,452c4c9,aee35675,33ce8cbb,e444590e,f5756f14,33865ba0,efd00c4d,26db7d8d) -,S(9403ea3c,773544f4,4eae3cb8,91457ac,89b11f1b,66c3c397,aea8d816,ccab1d49,46ec1e05,d13b40a5,f21ce743,b2ac9756,8ba98b2,8fe1443b,3b0c9cc8,f8a49deb) -,S(e81a5512,2af7093b,b361ab58,534df80f,dac734d,7a863ad1,b080d691,c4396dde,fb33ea54,fbc0c05,f9854f1c,49cfabe,90e259ce,9aafae3,353e8f51,594d49f8) -,S(b7511df8,fccf50c8,192dc3cc,bd79985b,15eaa528,89c4d01a,e21767e3,96bec9ee,c937db57,ddcf0997,aec742e9,cd522c10,d4a52b27,b50104e7,b59c441e,3d0fad4a) -,S(5625f122,4406dbff,a818d98,1e88b5d4,80039f5b,415acc20,ae69ae7a,704dead4,aed9f73d,5265c976,760d094c,e9ced8dd,722122cd,e0b1b34,a8296fb1,dccacfe7) -,S(1b89696,dca54369,27bcf0a5,de32ff1e,e79f6ea5,6f6ffeaa,bce6190e,bc7e2c8a,52bdf0c7,52cc3e5b,1cb9b5df,adccaca7,929046b,bb67daf3,10ba793d,9369b358) -,S(4ef2516d,796d1c0d,9baa8491,7c2db149,e7b89f61,a8f8fb95,e14116bd,473d730d,9a0063bd,6e25255a,70479159,d3089a75,834e54a0,a28c5c61,ea3c33a8,7ab20969) -,S(b36c8db5,51fabcb0,c3fa59e5,9faefed0,1a53b4d,5470ce15,937c889a,a93faecc,1be63f1e,7f85bfe7,2e782cd8,22776567,e3b58794,5f37e2d6,b137da7d,42c8cc10) -,S(7db8ebbb,88c7c04b,fed18b7e,1830df41,490028a2,2918098a,9b34b8eb,c110457b,73fe3f91,f0f8a43c,490f4cbb,f8bab5b,9a6569b9,22a69e9,93ab910c,520fa9c2) -,S(47bb0b5c,c207ef1a,db28a389,7606661d,e5d4c740,3b2858f3,209b7dc0,cac3021f,150e2ce4,44f541ff,7883cf31,79befa4f,5df9c3e1,9da098f2,1d73c37d,1ca48b16) -,S(7803d64,d7622ab8,70a8b927,74e012c6,ab97fad8,4bedfc7b,ac4ce6a,74dad4e6,2662e4c6,1a60a1ff,5485bb34,c1d41d29,3a09a69f,7fe8a049,95245e2a,7770cbe0) -,S(61a64d4a,9a801549,4fa670f8,85988b67,7d317b9f,9b75e3eb,fc6d734e,fe3d3aa4,ff25af65,16e639b2,b6b0dd56,c0e12610,b1b00c3f,d8c59cf1,3fbb1b74,6282d91d) -,S(f2de8cdc,ce609b80,af8b34ca,1c1166c4,3ae0ab9b,e742b510,2ecdd5d,2e94307,d624709e,79346b3e,81b98871,84bf252,949c7f21,861fe6f6,666ef5e7,18ec5be8) -,S(8c740f9f,386f5a0a,228ea52,18a43461,142f744f,87511e9,67080dd0,f3c65d2a,a641bdc8,ae1d4051,a15b1083,27581bf0,22e92b26,a5bbd186,86fb4e59,79f7cd06) -,S(b15a4b19,17448b75,df927416,2795eb5f,60cdb4f0,e657afa9,989e5133,646ae240,e09f731a,226189fb,429c76cf,1ed9fe62,2c148475,92f26b50,c2c45344,ddc73370) -,S(44a65d90,26bbdbc9,89b0dbfb,aa645860,d7a15652,5286a9e8,c67b5a3c,e2dde08b,f2f23e44,bb6cd570,f58ec2b7,b90eb66c,30775109,81279b50,2fc90762,3f12b52b) -,S(60bc8123,92f1e7a2,4eafd5f8,ca0d8fe9,c5880133,209f17d8,6b95cdb2,c9df479a,4d39ae61,cf4368ef,279231ca,b72be100,cfee501a,da7c873c,3db18742,82076a98) -,S(ad5b9079,36391697,61edf9bb,6ed7ae2b,f7e852d4,bae22afd,655a5ed5,754f3618,bdb40449,723089b,ad8221c0,8a46824e,cefe4899,d5e073fd,8606524e,a81a35e3) -,S(c8166cf6,97edc986,6f824df3,82a515f,68ef5d13,dba7e0d,43e85727,c6e15911,86804e47,8118c092,3ab97ef1,ab9dac34,2bc48c7e,3fe24e6c,fbaa74a2,2390f4d6) -,S(3e0a96a,94dcdcb2,9f0df535,970146d9,7f0fd71d,7a4196ed,cd626903,aafbff06,5f6eda99,4651016b,86d28c9b,39efdb4a,b8ad08a8,5c87b230,eaf7ba70,6062a8ce) -,S(e72351db,dcab669a,f1df2767,f5e5f05,ca80608e,29ac5f09,b1ff76ad,43178a5a,552249f7,7a8b3462,c9a268f0,fee20713,5cc14ccb,15914be9,2cd16d99,b2520af1) -,S(a08e1278,71ec784c,4f80099b,5d83c5f0,91978e38,7b0b37e1,f4622c15,80fea335,48e6aef5,349f25d7,40ffc9c2,5de543c8,7e0553f0,54990aef,fec51f0a,9b3585a) -,S(ffb6f3d7,92596141,f7d15157,d1a42bb9,e9b51e21,61a8e297,5aa05688,ba67617d,aea9ba56,8aa7cd30,b9940c75,29cc1e7a,dd60a5b6,8911498b,9fff470,bc4453df) -,S(9c644072,318933ab,4d1459b1,d684c066,d3df3371,d7659a82,fd396bdc,a9fc9e,a115ce28,5a7d9bed,a2a962db,5041cace,9d3b2a3a,12149b05,ddbae7de,30cf52c3) -,S(5cd3475d,8a6fee1f,a6e3800e,911de939,a7568762,4f0a6e69,26ea6160,4ddec04,20063702,1d1d525a,f250876c,c4b49590,9ca8b39d,74603979,8c8b4b39,fa07c17f) -,S(28519616,c035ec81,4e851ef5,191e0545,5f0bbb57,12fcacf3,2b36de77,1c351f88,42ed56f5,5c51953a,6a367398,815963e2,64363681,f9a0723e,7b622784,5cc939c1) -,S(a4e11f70,b3554f05,d0634209,86549001,53d2ed50,1f09f787,99b83308,4dc894b,331b9d59,4260e0fe,381176a7,1873a66d,a7a3b9f6,2a930e0f,696f68c8,6939755d) -,S(c5d7c22d,7a8cc553,7ed85a85,46adde7e,ebddff6a,f7e8a6c9,96f50df4,248a4ddc,dd4749ec,bc029503,1106812a,cee59bb7,acf41451,45883a71,3256912f,be9ee03b) -,S(b56ad6a5,c6fab0,934257f2,9e266052,cdba0bc7,8c8aded9,f0e08490,71770c7e,6aaa84a8,99a4f8f6,3ca8dee1,6df7c090,264e644,de1e58e0,49f99fb5,fd5f4c34) -,S(16c4dbde,37e8df54,aff88810,678f4707,310f29b6,e9e5fba0,384220b8,4f0dec11,4fbdd92d,56a3f76,56b4dcfd,8be6b589,eb02c645,8a247c9d,264fb65e,c84a3a3b) -,S(15e63d71,f02f6bd8,1899f95b,d3051871,84b68d93,6a2ac10a,d29c39c8,d5ba9748,20204657,ae0e1078,6df04a71,938055c,ae208105,ef1beeff,663d8cc1,df478ed8) -,S(3c07006b,8a1e1fe6,fcbc3a6f,fbb7a780,a0008ed,513c9967,853a8cd2,5827dcc9,b2fe428,d4c8d974,72066ca5,ddf32e99,18b5e79a,e81fd6c5,e00b8142,566ce904) -,S(c7f2ddf3,b3dcfa04,91846f0f,2341b1c7,81ce2cd6,ec20acf9,a304fa5a,7dbe73ab,595d0b02,faae2b6c,f6e84bfe,1183ab9e,dcfd6c9f,411d7125,dafbf9d6,60ec5d01) -,S(4c239c01,c05d9c11,3d25dad3,3d14ab28,f94742d6,8c9c748f,1773b739,445bb643,dab0d447,de6a8c79,6809563b,e77c89e7,956f6c9b,ed930d18,f25696a2,e436ebf4) -,S(9e1a100a,c44c33ca,543ae407,f98fef31,28bd1755,6a16e5a7,c1390792,187fac5,540a4e2e,9864a32e,3eedd96a,bb08fe11,b499a551,497e0c83,cdba140,3b303821) -,S(c3b4d7e1,bf3485e4,d028e424,81608ab3,9fe37649,de75733d,78f725f3,63255d18,8f8b00c0,2210cd63,c04f07a1,e10b1a50,f05ad863,b8cbbbff,9b73c84e,c59b5ab6) -,S(dc226233,8dadc96e,5feebb65,b290ceca,f8f5bcf3,e1794f9f,6ade4eaa,b89f3372,25bebe7,cae8b7e8,d755862f,dbb929cb,872e1c88,6b7d03cd,b32303a3,b8b5ab9d) -,S(184b11c0,a52865a4,5f530101,24cb353,dfbc2d26,bdb3af35,d5f029e,6bfe53c9,237a79d,b53bcada,f0a96804,d8072832,4f59f03e,1dc7a76d,ac5fcd01,3838b110) -,S(4ab97ea3,943e8157,3cfaa8ca,680252f6,577ff2a,a93178e1,e1a3dcee,242b460c,b8a6293d,f316c9f1,5fb8850a,87bce47,27d2a38a,d1f5f63a,39d08c92,e9d6d242) -,S(a531936,799791f3,cfc8bc58,4a2967ea,66328c66,98ebad8b,5e5fe8ad,8cd025b,c24d6ae0,8fac8028,a3e0e079,426b94ee,2ca7c845,8efffe1,58f6cb2b,c9046c3) -,S(37cc3686,a6e75e4c,8d7375a9,f291ccaa,937c833,f9e16d77,2591e74c,787b1f7f,557c1bb0,a7c7ed52,93e44cd3,75b04a47,7788181b,b20dc1f1,f6704c10,5a8e399c) -,S(94fab00a,9418e31a,9a229706,112f9386,d537bff,f5f0c4f1,b241c475,4d7336ed,14bced66,1c6eb134,7684cf29,6a303e0f,fa5abc38,ad569011,c09cbfb7,8316540d) -,S(14b851dc,c6b4382f,ca64791c,74a3faf5,adbefe65,b36de8f3,74e12e6f,e3c20e1a,6353d0b,ceff99b8,53557d0f,a893df50,598e0335,249f96c9,4e7a46a,3c02ce1f) -,S(d08e3027,5e05da0c,22991340,8317ec6c,e4362dfc,45b946aa,41e6b541,92c7589a,9553748,22228787,2ae61975,d0969373,8cb346dc,15d07e23,68800ab4,deb5d463) -,S(365ab0ab,6d51bff8,d4bb479e,a666e110,9a838863,2a5f8cbc,b3241bcd,5ba88ed8,bca2f90,ef0d4145,90cf9add,2a9d6793,d678f981,1ad851b,b2f54b6e,6bd093d3) -,S(879e8da9,e1363822,b113e70a,b8072081,f0e34a99,49d698ed,a0f55b4,6704089c,d5091dc9,d33861e3,daec5550,1f52378b,65b25a74,27a04483,c862e0a2,dc1038da) -,S(17006515,8ceda656,b23941e6,33ab3ab,ebb527f9,52ea9876,a8341600,24dc10e7,39a7ce82,b0afdbb6,33e74517,5fef5165,cd44c8c9,d81be0c4,56ee0251,6410b0f2) -,S(574a4f4f,67e294f8,2055793d,e94bf7f8,aa7106a7,f7ef0f2c,3bcbf2a7,352f017e,eac4aaa8,f4b4cf2d,ed8c328a,99b24623,16ee6e08,8805f1ce,783c4cc9,eff7baf3) -,S(4ab81205,32603ea2,9f88ba75,f2f0c4ae,330bb5e8,7f371806,de04f87e,69d5e6b2,1f1967ff,cd42f9fd,1f892f43,f8ea945c,c0135544,acb8010b,8285403d,5e621456) -,S(9a4e968,82b11f0b,5e431867,80dd208a,ba25b3fd,1350ed84,f34f2b43,f03c4378,15653ab8,375c04c3,d7488006,1acf13d9,c5d669f7,bbf70490,44dba189,372f611b) -,S(267b8cc8,3ed6ef12,47a93f07,b4f1195,2fb1de83,6c3e3fa6,782b5e82,80cbd8b8,19bc5752,1a41c7a2,a9dc29b5,cafc66d,7e2016a3,334b4be0,e2811ee2,4ab8599c) -,S(69a8b170,876bb1aa,2faca2d0,a4ed8c02,44d2cfee,a849293f,5ffb4243,256a1017,f77d7a37,5315381d,97ce835c,296593b2,80c395db,a5311a6c,c7fc2c98,d314b4fe) -,S(88aad570,3a4365c2,96946510,5a3a7fdb,6e1f3e66,618c3fbb,ee4c4e13,f333b1ca,10ded35e,c15df656,fabfc4df,a1140b09,196d10af,e1e99b3d,7e1113ef,f7fb8670) -,S(50709e9b,8620f7f7,7b8b6c69,1360062b,cfbea4ef,6448917b,471c3485,55691440,3946b364,3cb1bd81,818b828c,77c771d3,833a1d4d,dc509705,2e5db99d,6cde2137) -,S(1ac1d530,7cf465b9,8f1140ea,bbe7a939,df8155a1,bd656168,55ae128e,bd3959e1,eb02a759,82bfa30,1f9fe87c,75b9dd8b,fe2d64d,7ea89836,1aafe22d,448b418a) -,S(126a8f88,e7f59ac7,3226f2c8,8851773e,873f1ea7,a87342fe,da5d9795,3a1dc956,1ce623ab,abb29b2b,b9fcbde6,a6a6f12b,ec68bfd7,aa98733d,f2452860,bf9349f5) -,S(592fe608,92c09243,20fb32dc,39e7a42b,1f5125ad,1e7d6790,9978ac10,5471427,c4d6ed82,4d33f52c,d975d34f,b9df5698,968a0c57,9b44bd19,8a67fee,9935d310) -,S(babab912,e526a92e,d903a942,ae8ad2a8,930ea5c6,17cbf913,7c074060,6462f0bf,76c7ced2,4318c1b6,c7295d9b,52bbd4b6,707a4170,d020e7dc,1c7b5e92,aee7a4c8) -,S(6554e9c9,bdb1757b,408164ad,1cafdaff,4642a3bb,cf64e785,42c324c7,5be1a903,439d023e,f6c63252,311cf494,4c46a8cc,a3d684a1,d66556e5,dc488d40,e5ddd500) -,S(79ad3f8f,4c429721,281a9b17,d9c05463,f26bdfd9,c856451a,1050b3f7,805304f2,3be5cb37,da868333,4f9a4def,aa8711a0,adb6721f,d4b2bd38,5ad7298e,940dbb87) -,S(fe559c8b,e982e801,7427d308,e50e4d94,d7094aa0,635e553c,c591181b,c9593015,9186fd9,c9fbecaf,f4747597,22b34b72,49fb72f9,f02a67a7,627c1562,ae80485f) -,S(d2b4bcca,38d1b073,5248b4a,7f43f277,8e03f46c,8d7f3a33,ad2dd9f1,70ce0af0,fe0bfaed,846a3f80,10fca999,d0c3b0d0,b54e2fd8,7a0bf751,ba40f560,9eb952e6) -,S(f6b9ecb9,631c784c,8b33a7f6,3fd0903d,baec116b,3dfd2414,4865b297,5c290faa,95fa4ed7,e67b828b,4c685850,4b003928,8ad9e27c,da175b4c,81730fc4,5b063355) -,S(3e70eafc,653ef528,aa12ce46,59c90ee4,32979f0e,9df260fa,b9063f3,d30de2ee,e240ec33,b224a5db,3761796d,2c1285d8,9cff64b0,7c36a184,996cdca4,839a0a65) -,S(dcc76f61,46d05c0d,67bdb161,dc395c83,663ebd48,6bbc6e62,f3576335,a8ee0c59,e451ed85,a9ae624d,4617f11d,67552eef,7279811,6767a29,59708e,3c21208d) -,S(3bb03660,430c43f7,e3b68acf,fe692b,5ed6703c,c808d7a7,503b3536,381180fe,c84c669b,2822cee3,627d4ff7,7c01c9c2,57c57e80,f35e4fdd,eab84a6f,b96fa1ba) -,S(5e266477,dd106005,6a59fc2f,df36b540,e051bd56,c9120b9a,41471c46,b1c5c60f,d6a7ff4a,ee4abbe,cee617,1ad01373,d7916899,5370031f,66f62229,1057e6d9) -,S(c1c13157,56ce83c7,93ca3a0e,12dfc0f7,270a0bf5,38177522,8850863d,37e5e537,750dae34,9090f275,5487778,5a126ea0,f3c2c0b,e3cb9241,326a863d,3179af7e) -,S(c03ae6f7,96692287,4cd10b76,d06ac08b,578511cd,c502762a,cf14eac6,4f1a913a,b3ba2ed0,6cd40752,dc97e450,10699cba,90f38f65,cc4623b5,44d7a57f,250640e1) -,S(5938d249,4edde81e,6fd50332,d81342eb,6cd0d938,f1f02ae,562d1305,cc665bf7,b585c184,1e17e6fa,9924361f,8d06b172,89782433,1d65b3c1,7f2a109c,8be27b13) -,S(e3457146,bf3f5667,e0621ccb,500854b7,a08836b1,e4315d4e,6479b3af,e5c2bcac,3de9142a,5c495249,14d3619,a92dc5e9,f20e4603,5cbe2c8a,95a8e683,bb287fc3) -,S(4187afe,4918d05b,74a969cb,14f54b70,95387e68,c043a581,7dcd1d80,4ca917a3,4e1c19eb,b38f0a15,36afd31d,bda30d09,3c776545,f2d8d823,bc3eae61,35585569) -,S(60cabe6e,ffbc3735,dcc19c15,1abfdf4b,cf082768,e62a1176,f056c4be,ff04640c,7b0fbd84,ee9d787,2896b9c7,19448412,c68a1ef4,e5c6cff2,51ea823f,76d6c4df) -,S(fc6883a1,231355da,115af629,4f06eef7,83447185,edc19e62,b53f3156,e0f540a9,73805d95,d8b2e4f9,d0fb36c7,9f09780f,c315c1b,724c5de6,98d96861,c521a6c3) -,S(90f37677,e738ee2b,3abc9d42,54085349,9cd02836,474624c3,9513950b,c325b66b,90884e24,a4171613,da7fc192,f1bc913b,31bda925,38fc0501,6a55af21,e08bb960) -,S(55e68c72,f76925a8,52d38e8,172e6340,3966f148,2a212131,cfca2497,ca40db3,ebd22c3a,1388485a,e4b48b4a,8b69b98b,755084f7,9f9018e,36769d5,d78cb7e7) -,S(c74f257e,e1bd81f4,fcf512a1,f866b9a2,19586a3c,62e7abc1,112b5946,d5b90e8e,aebcdd14,5555164a,bfa127ab,9f352034,f31a19a1,d36cda02,f51a88ed,9662f44a) -,S(bc63fc6e,d1963da3,7fa064be,f7a371a1,fb471ded,5bf084d,946a6eac,fdbb8d36,a26a6ee7,e178a31c,4ca535e8,e3d1dfc4,dadee69e,140a37cc,a306546c,26a75a2c) -,S(9d11ff44,5e331ca6,fa99f29a,78f5e769,44fbebc3,e3b45a6c,d46ad17,74a1f29d,2f007088,110e9ec,66e5f134,b6d61ae8,70b14741,e9b6259b,ff06753b,fcbfbccb) -,S(5aa47205,f01abec,79b52b1a,2625b773,659166f8,1e300d9f,46bbcdd8,532599e2,f56747f5,c7431031,5b630fe9,b162fa49,26757780,c6ba59e3,6e91c29e,c82fd357) -,S(14dafde6,c8818744,2059563d,1e2cc095,f4bf18e0,f7e41b9e,97a74089,f678ce60,6f6a348a,a4f72e60,9a44b01c,b688ea96,cdc7c3f5,e559ed8e,d9a1c7bf,cf1747b9) -,S(ad8cb71f,1a3739c,afc8a4e1,ea77bd9,f5703d4a,55812381,c5a04847,e85e9950,238d1945,cd5d6094,dee8c6f9,41a19b48,d1eb88,5c986dc4,b8f3908a,508d46d1) -,S(e88df4e2,8b7cb050,aa81792e,ad108c4a,d95e735,6443dc11,f77d70b0,5968de2d,9541f907,f29d79ef,83c25f29,fdfbf819,49f21604,adb5a5df,e939afe7,511cdcd9) -,S(d6b6549e,1ef4fecc,ab56860f,c7a8a549,a354d9d5,63b9d459,9bbfcd71,7631c879,df7a0e04,18a86774,ba87bbe6,132028e2,927985e3,b1319c83,4e1a400c,7b0ae231) -,S(d919b999,faaa7cba,99c79a2c,febbdc68,6d94e07b,3edf8350,6e9a729b,f0f834d0,4b19faba,9b6041f3,9d33a21d,285fbf7d,638f3a07,63e2b15f,df102131,49b94ed4) -,S(b89d011c,57cfd499,fffd2d1,8734f604,83df00a5,6efd43a8,35d5983d,573d902,977f7c06,ed8cb0d4,980c3160,b152a7c9,294d489,2c90fb88,1da40f39,adfe2825) -,S(264873d1,cf9f6f35,d6bbff5,a2405f40,a5568a80,2fa35069,ce422c61,d9f2146f,36b8e9c6,e73044dd,b9b9753e,c682db1b,550d8310,7e3ea3ce,e8ecf031,500b3c31) -,S(d4c388e0,950d24ad,6cc1dfef,a3735bf,bd9e729d,99fafc8f,e4fb5266,8816dde1,3d583de6,27789a58,fd4afbe1,af3f931f,5d12df61,7f5adfaf,95830cb5,4b13743f) -,S(80a2e2fa,40aed900,a7a55f84,d4965f0,2c5632b6,1317e801,b83ec659,cc06e35,9e61e863,69c8a367,72d6a4b4,c2b7bd89,405fad38,4f99514b,485974d3,2342f47) -,S(e36eb1d7,72d5d498,3cdbeed9,b64fa04,1da7f1bd,e324f1b,a734323e,9f5331ea,6c879df5,4a96d33e,6a66895b,f4d12fef,46d5fe48,8d62f073,238fdbbf,d94126d) -,S(7852402c,a08ff966,44a4c1a9,3f7186c1,43f0e1fa,203b5991,d3fda009,1e0a4e76,a9b15d95,3ce9b219,a53da27e,e1b03aee,5431e26c,f035fa1a,a067f1d2,d36d5402) -,S(5d33032f,f7bf3996,14a08ee3,a5b67ff4,850f37b5,eed88e4a,675b020b,90cc4ac,ff5c96f0,5ba73287,f3279907,ebd0fb7,9e0b4866,c32f6fbc,2541d8c5,cbe12112) -,S(138d3701,98eb6569,17b3fc46,c2a3a1c2,3f7c95d9,d355d51e,c85b6062,4675030d,94314f22,6581dec4,3518cd7,61150f31,51ccd59f,3ecf79af,482c4dde,8a24e28e) -,S(3f6ddeb3,4756ed69,de83946,b48281b,c2b60882,d0cd721c,5d76c5d9,ff898c2,be8b8841,12fbfe09,9af67a96,8f4bdcdb,db4469d2,34d64d96,99c6a575,518c48d2) -,S(74676fc7,cf3bce8f,c0c4a774,89b320c4,736b9ed6,171d0b42,17a1433,eeee384e,fce3cf3f,630452a8,1cf3fb72,63c1b5,b66df4fb,864d4b39,7e66c69f,2913c54b) -,S(e0d1a049,cd49ee87,d71ebd9a,95eef0a0,b1d7450f,617841b,590eab0f,3e883eca,99e00118,42e6a78a,d4c3ec3f,f7a61bea,a1a5f8ec,2f4e9066,978e96d0,cbaef51c) -,S(531b455c,c6051fc5,f0f3190e,9523aa5d,2d0485d4,3901600a,aaf207dc,7d2b1fdd,b95f8c0a,b0e63acc,542df948,4b112b2e,e49f53fa,7f3e1dd0,307d9161,7c0f313d) -,S(b86ba09a,2b05e91c,c23db107,9b34807a,778749c0,ed725437,69ff6c17,316e7db7,a91c815f,f8a3b2b7,e5d44357,20e3a513,32cf405f,7501ca3f,b1aa1f59,a01c10ab) -,S(b63b43c5,af63f2ac,3f6e004b,c790404f,a146ea97,94b1bcfb,c4d0544f,2ca3f33,31654108,481b7dac,cbd48e8,c20de95,11406381,ef38fe6f,950b4321,4b145093) -,S(63a09087,e237e0c9,686f2a79,af977ba7,26d77118,29c8ed91,4f99dc43,90c64d08,7771ce4,a5e7d43f,e12b5e8b,c819506d,3b85f52c,fdb0f9c2,92c22bad,790d3b93) -,S(77640a42,4ebd84f7,71734050,7ba400cb,9e8462a6,a91fd0a0,b8f152a5,f5f7868b,516688cc,f422e660,15afa46,b5889331,3cf2d622,d6c829b5,f1d11386,bce41640) -,S(963ae02d,62739bbf,e75965f3,d1b7786d,c3dc6fc,5667aebb,5544db3,157f8a17,b3a109d1,b56570cf,2a5e5056,fd9feb05,2e8f53c4,f2ced1a5,27c3311d,87ba9dfb) -,S(81324144,454cb304,36f365d1,c78ea5f8,9a73706,acc49d5f,125fa282,c28ebad5,77a71aa5,54c0da45,31ed307c,c7fdad32,ab82a4b7,2f2a5154,cc405a2a,fddd3cc3) -,S(eadb105,e80bf2d7,cba9b468,6f6b88ad,34008c85,a7ac4d53,d3fff09d,dcd566b4,199ebce5,872f9dd7,6c14821,622fd343,2b7b6437,3484fe84,714b137e,fa782bee) -,S(a030450b,52b387b3,35cfe8ec,683fe625,884ad73e,2fc1c728,c8d9629e,dd2024ed,895545be,a9009f2c,dcb20441,33f2fad7,ac704ab4,9435fffe,b92836f5,57a114fd) -,S(57e8022d,816255a5,f4d577dd,867d65bc,7d7fdfe9,ed8f993e,d9b30531,fa36888b,9b0b7929,3cef66be,c21b6fca,140e6fe7,9b9f2e8d,48555338,868b6c78,d300233b) -,S(74c14e1a,d52761b1,7206b61f,fdff526,f7008f94,b3707a5d,e5c2a600,97b0dd29,18778822,89711679,c5e41fb0,41b1a806,9b12b709,b526ca1c,44839d5e,3b51e72f) -,S(5a9ce7b6,6368077a,73c09869,38656705,c017faa9,2d9cd40c,69d8e57e,63f8e229,f716b144,cebe2907,928f4618,821af2fc,9de249c9,5ac61bd5,99a550d5,e97363d0) -,S(f0fe4fd9,99c66687,3ab4c904,b9b7c0d2,7f033a0c,7e6c1b6b,4488097b,cdb49fdd,1f4643f0,6f700657,90aa51b5,911b4866,c286128e,de489dc2,8e2d6b64,972738e9) -,S(e86c729d,19347238,a9e97433,355530c8,7b701aa7,d710d26e,6b15ebe7,4796857c,d6260d35,466dbe3f,58d2aab2,1c8d76df,18271247,9715bacb,2a76bb95,5b75730d) -,S(b4e3a39c,8fcb0dc,5a23610b,bbb564a6,765c0135,1a8b666e,d680291f,c97df351,3f1eef0a,7a235130,b5236a2f,f8c9d2a5,fe5f1cbe,22326ba0,54557513,82ec651d) -,S(a9c8482d,a54adc98,4db2d7ac,8fac659b,51c1237,eaf1d524,9bcfcf1c,4ae601b5,446ec925,fc148900,8ef10348,ee167a63,a10686f0,7a01772c,10f7592a,2a544a9) -,S(17adc7b2,c36b1ff9,ea40b398,53246d71,bb973bd8,b469f7dd,fce49aa5,e77b8c06,fc3111a3,8dfc5219,7f41ea77,1682bd8,618f9825,bb2f842f,c7de15bb,224bf573) -,S(328e9a6c,e7397c45,617aefee,130cb6a1,dd26e727,efcfc30c,3d8f415c,187d23b5,6320e80f,e4a57574,1fed0624,c0f956f1,d5b30914,b5da88d5,f63e17e5,64f8b927) -,S(22188680,f765065c,360c52d2,851f3081,b2d3eb5,4201dad0,60b536bb,a45a1a41,b1107c8d,430df246,3b3e91fd,904883b5,cb877b,c10b6f,397a0cf1,c4b6eb35) -,S(620f5772,5919db4d,53b8f89c,5669fc6a,5a3f3846,c31faee1,1e93e53f,b1d20bc7,7d739bc7,4becbd29,2784be81,294185fe,db047d4c,c16c764b,678f9d00,6d27feb7) -,S(49b1228b,b624c71b,2c23e334,b098e84e,d3d8fca0,56303057,49dd39bf,5296666c,3f316e5e,ca9c1aa1,fd5d23a2,613e756f,8ac5e819,8ac16650,a9dff05a,1c8d76d7) -,S(97ca98cb,fedaeddd,b13b86cc,4b6bd7d2,140fde57,dae7b847,c51b118e,e3d6b8c5,1b95c9f,1d6c808f,397c3ec2,a2a2b220,6fdf546e,8c70ac2a,78086ad5,ebe28142) -,S(a679e7e7,3df904aa,e80270b4,d5d57dfe,f5ae819,f240369,b773fa3c,609a1ed0,93201a4b,17286928,be5fdfef,473565be,879cad73,24124c6d,6e1614b5,4e6e5124) -,S(fe17af2f,70887958,1b9b176,4d45d76a,afac0afc,ff50ac8d,9179e53a,c5e3777f,f59728d8,67c3ab63,6d387352,a029b5d2,e9f2d531,7a508894,9a0f6515,f5c4d61f) -,S(f7601ed6,fd64cf22,57cc15e8,e554dc8a,e19e4f4d,ad3fb3ea,a7e819f1,98b3946b,a3292ed3,ff088c22,e9a62b85,4ec87dbf,394cd681,501184c0,b841656b,def0fa3) -,S(3dec302f,cad72c11,54c6b588,ad7f77b2,9368557e,77a723ba,6dcf9357,82d9d917,6484365f,537611ff,49f157f8,6c4bbf07,25094f7f,d8db9a2c,b318ab4e,632cbfce) -,S(a847783e,46ccf334,d7b15f1e,d3aa7dd8,c5b3ef4a,7ced2501,c26d1dd9,4358adbd,7c56f1f3,323a500a,a3496729,ace84a91,6bc6dddf,90435a09,8ca51f6f,5fe5fa99) -,S(dac6ee37,3c655763,b01c5012,fe01518,c3ac1b52,543cfd7e,9ca24d6f,42e4bcfd,6b861af2,f2a82f0,d4c458f2,2d264d82,54f16f46,87e31cce,7199f061,bdbc941f) -,S(27dc7253,90de6a8f,6cd9918a,e3b2f33a,8ca4307d,ca4acf6b,f9c5d0ad,f01b4dd,2a0798f6,7e583426,cca8ab26,e6742692,ee790f21,cb3560af,271b0a09,eb9f8b31) -,S(1c6a5d3d,10983673,5e27dd2e,ff04adfc,7bae277a,870eb4c6,d6379467,de2dea5b,92658db0,8b6b85d8,5c20ad21,f3ad33c3,8de02319,4bc54d0e,4d758093,b4e8695a) -,S(cab35e2c,b731cb9a,402f77ee,44565fa,d6623951,be9deb97,88da09cd,d5abb56e,37bdbec3,638594e2,59018bb,9145c4e7,dfb55b13,bda50c6a,c33e975e,6c5d96a6) -,S(97e4cfd,9e1ec85e,cc49cb90,ada87b99,bcaf8160,9b04417a,70fa66e9,78bf54b6,7423ded2,bc56ddb8,11db577d,f1863fe7,dc758999,55989e4a,d344ed4d,5faa9ecf) -,S(f2a9b193,6f63e9f1,8333cc3b,745fb2ab,7b3749a6,c59e7d6c,42e387b1,1e9d86fe,3c6b6bf9,1c2c4a,859538c9,db95a2c7,abbf8c37,b6e172b3,cc2be8f0,f18b5484) -,S(49024a25,11bdedd9,6c84aeb0,707b5b70,f027afb5,8b4053e5,234a9312,771160c0,22ab8282,914e69ad,8d573e7b,841e9eec,2fdfb939,c76ff330,fb2fa5b4,14a4523d) -,S(781c9886,4bf29760,c44e1f98,9a5266e0,4d25c6c5,f941e2b5,cf92b958,99ecaebb,994a771d,eac92f91,58ecbeae,6227d2b0,4c09df72,c5ee4439,509f0b2f,6e361509) -,S(8f7e703a,ae008b13,590ccda8,b70d2cfc,4c98480e,2a5032bd,dbd5edeb,aefb7f8b,54226771,863fa87f,ec101303,9238da1c,74f9f446,26b50f07,f35d6b59,bb7ff81c) -,S(ecb2e955,ed796695,3eb1ee21,564125e6,e860935b,20fb99da,91556cd4,e5e57bbc,75103469,9b958e18,638f4e00,654d6eae,f5631483,4c890ebb,7e2d93e6,9f4d8bf7) -,S(971cd7f2,9ce90bff,4c46eef1,9df001f7,afa6af09,b553e8c7,792f4ae4,d3f82cf9,d4180c19,7a579e31,f27874df,f29cd17,98e5740a,36380349,6f7dd211,59bda50c) -,S(7ad3b286,3952489d,42cc8394,413545bd,90fc63d9,8558323c,feb8e7e2,50ececf5,5c566bdb,5efc3683,2b22aac3,c0b81f6f,bf656c11,5514ac9d,8a223071,168f139d) -,S(c905b52c,ad0e0281,a90eead3,3939c836,ebd591b9,26787a4,2983804d,e658aae8,df2a40ca,f95aa72a,181f3424,98024f72,f1b9e46a,3816cf3f,ba5ac699,5b996fc1) -,S(e2517e6c,84856497,8ac94585,5c80bdf5,7c074b6e,fdb01cea,e93c17dc,ae4b3ff3,373ede93,2f369807,56afd100,e2f65794,69247690,61a597da,80d10fb6,bbadd3a8) -,S(4d52a8e7,2f3cd95,2e25c8,175e82b2,726a8d95,b735c8d8,a0f1805b,6d94ad78,248b7174,61287611,8000136,dc92b841,de63ef18,a7c9ff71,a10a662,af76ff17) -,S(58e5b42b,e614cca8,e131cbea,24b3debc,9d9390af,469df700,35a01957,3307ac,be4a397e,7809c9eb,2113246e,7812c403,4d42d8d0,c353d841,3001280f,db6bc220) -,S(3f177142,a6e6eb65,ca5e1609,cc89df40,3e3c74c9,e5b291cc,49fb0d8f,eff86ecc,2a445bb0,b648487d,3b962bfe,dc74e4da,d1d98845,cea5f4c8,d2f0c4a8,2bc4c514) -,S(3389c700,9b2b0c6d,a25a9610,4660a164,172a4c21,d0ddaada,c6902bd1,c9f04b38,413344db,77b83806,80647da0,d6086ea4,d1b8394a,a0047a9d,4c21c667,ade67a90) -,S(ecf3f933,4b2b656e,24ea0b14,7528c490,c3a566ea,c4c51885,d3ee94f5,7370b218,3c07fab9,b6404f24,77e4605c,345d3a93,adf9a06b,649206a4,b369712f,7388af0) -,S(a090739b,58310867,5e460a26,7e29f228,effc954a,137f358c,12be2fb5,8011b2bf,a3563d1b,7f242a1f,7ff5e505,280c3898,13251c4a,d9392d82,d3b12a07,e22271f3) -,S(a251cd29,357e5300,5a8600e5,bb9d56f4,c8251f6b,46b4d99d,5dca7b2a,31f8201f,51764fe4,596059a3,b1eb06de,56c6e21b,d58e7194,8e1b6e65,51e53333,5f9721b9) -,S(1f9aafb3,eb39814d,7173b85e,b027ad41,be210c3e,e5c857d3,56288b3f,3b05c5a6,d34526cd,16e7d3fb,76ecdfc8,c11b1bc6,38762bda,b03c1c07,94565cbc,df41febb) -,S(dbd4b724,1fa4769b,db161472,1179fdf2,6df4372c,d3b0c4d5,1e37fce5,317e7e42,7e9bca3b,bda0e211,5f2e69cb,8fcfc333,fc1b8b85,70123816,802b22c4,9634219a) -,S(9ce40b75,7a257205,fdf51545,7d6f9691,7e54a5dd,32b76230,4ec50c2d,3b89b06b,9b128748,851dbe81,255f60f8,1e5e9de4,6b20a545,afec40f0,38beb9a3,f7402e88) -,S(12f6c70f,46efbb73,2150f775,5f597fd9,2a527a33,7039def6,5533cfb,18df3406,7d9f18a2,4988ea,a41a1364,2a1555c2,bc9bfce0,dd62ba87,fa628b84,850e92b5) -,S(3132e530,9b169a3b,7401651a,351f7fce,43471b19,7ded3d1d,cb0b768c,5620fc5d,3e377f54,92c99dab,84f4e45a,7cba38e,9b589fa7,77dfb334,849310ce,53294287) -,S(87160125,8a8a69ed,d52986a9,25a54ed9,51f561cb,8ee9e1ca,6c58b826,495b9977,c5484596,8ebfc8c9,5f317681,78379b88,2e9c2548,b3c579eb,f6da5186,5d51f36d) -,S(82674b33,ef500391,2dfd5f2c,26722df8,19fd265b,3b6e4cbe,239bea50,298653f6,bb6d0457,2adf23db,86b07019,f2f59fa7,ebb4fd2a,ac36ff16,6b22e92c,3952245) -,S(2efc1011,28432933,56af99ba,ea2628de,a518fe02,c5b0eddb,3688c8ea,39d4b07f,d54a087e,bef0923b,6244b21b,f260eccf,e7d590b5,cf98be51,856347da,ea48779a) -,S(f2164194,5de0542c,de90f1c,4be955cd,98f6bb14,ff30ab44,92691985,882fad46,a87f6725,e89afd3d,6f24db13,39fafd45,5f578c9a,104f6509,c83d0694,ef795dda) -,S(72d2c60c,6f9bf0e5,5de82932,88c298b1,4d851deb,6ba7421e,ad22f3d4,2b47ee88,29626eaa,712e6d76,d85b9f7a,7a17461e,132c9bb7,a2943379,c5eee30b,1ffeb1d8) -,S(9bc6dede,ebdbd843,a5534fc4,71212480,ecfba4d,96acfbf7,25e980bb,8a509773,24ef23cf,e1580173,797ffe5e,baff2fc4,3cbd3161,e87e32bf,463333db,5ca904ef) -,S(20ea6c3f,51565fc2,bd5b8eb8,1ccd20fc,f3aafee0,9ccc9de0,733df6ed,8caa9c81,78328fb1,ff260b0f,cea69e1b,77b35679,d6663513,8f136c59,127ec2c7,d9668dd4) -,S(aaa2ee28,a4724d91,f37044a1,3b264ea6,9dd9123a,b3b7b300,999564d1,73057339,250b6164,2ade568b,8a56ae82,4488e740,b9a65f7e,a2b95f3b,4b11b6a3,1b49fddd) -,S(a1e54535,4a8976a9,33c04366,f0361775,824383e5,2c3aff3a,357788b,38014ab1,a6a306b9,b0a7d3c3,d6530094,9efb038f,a0a2cd1d,79bd495a,487a95f6,ef2b7a7) -,S(f2b0c76,18fc3ca9,f9ec5d65,2f39b6e0,158598b3,cb90b20a,53fdaf97,ac58f7d7,1d63cacc,7e8e46ab,47ce7e4a,e5a3336b,8d3d9bf0,f05bc428,f6f769fc,7ec6cd15) -,S(91843b8a,90a43571,4d7500de,fff102a2,fdb53914,2bab12bd,d3f23576,75a9d62e,3cc6365c,7dc3813a,d51cb2a3,d86491c2,c4e38f2b,10a33181,374bb0c7,ac90237e) -,S(f73b2226,8122a4e1,a440f891,14fd8d72,19cad2c2,9798cd0e,3631eeaf,6b125a92,bc14e84f,ed149aa8,ac261f96,6b192168,26f5a2b7,cfb997c8,3f293101,e758aae5) -,S(e87cfcb7,1f2b1c9e,8506b0e5,c56b14a6,52201397,1bb4c53c,855f1de,45644ff3,7e3399af,b4a9f70e,63907a29,c02e4d58,b2e76517,e4f2f2cf,a3d2fdff,808d5b08) -,S(b9657f0a,6de5cebe,47151293,de1fc3fa,b2745a18,bd5c4b8c,62282f26,84404f21,89590e9f,a787f41f,79a0b8b7,682bc353,1ad60107,771233d9,ec303830,e8e8dad4) -,S(b62d02b9,de395843,eb69e8bb,4d974590,7c8d3b26,cd4b13a5,6b4a0e27,44f449d5,173cb5ee,60d3999c,7e795607,bdadf8b9,acf9282a,d7a68ee5,6a204eff,ce5fe751) -,S(b6998e3c,31e9cca5,251a9d89,1aeb5384,fa86c92,74a0f027,8f2dc67,34b5f8fe,7658a71a,fe032a5b,ccb80a1b,1516faf1,5a3e8638,6f74b2b9,b6d17cea,61c3ac5a) -,S(864d4c66,4db88b56,6471852b,eacce0b3,52b55404,46444cbc,afad4f17,204a0170,7001969a,fb35a3ad,fc553e00,b6faeb21,c8fb1af6,135e86c7,f7e91397,a826346a) -,S(22a0ec9d,ecf7a2d4,6f550ff1,5a8f1c8f,6efeff9d,3ff65d47,97512980,216c025e,9d60fca8,97662f4e,947c962b,48522cda,c7ba956c,5a23c3b9,67f46073,af0980cd) -,S(f1be1f63,769f74f2,947eb25a,194171a3,9f9096af,cd454ad3,35809b17,d7e69fb4,b78b3a16,b734c528,c1911d95,895bf873,fcab1440,b62211c,25aa247c,161af243) -,S(7b196c23,1a7650a5,9db8faa7,39b7ffea,488b3623,a0bd7a2c,48b51c97,f5726c76,56e84642,2c430157,bfab8821,9112124d,6bb968e9,3ddd6b77,7ee08228,9a7e1241) -,S(6ad31b05,5a1f1a65,f4e554eb,31e3e048,8570032f,8af2891f,4436c640,9420849a,edeafdae,d10bf173,5de8ffe8,41871909,79f6377b,4cb566f6,3386534d,89bde755) -,S(fb0f3da3,a44c0921,85d90b80,1e7f5aad,6c85d5d0,b9cc4575,ad95ab34,4fa6aa7f,7857f22d,6f9356b7,96020384,919e26de,b9abd707,4dc6db0d,768f630d,b3589b18) -,S(c39b4ddb,edb892fb,2394e875,7c7815e2,f487f81b,45c60749,1c314350,c929d96,530f0c07,68e66dde,e10f0d95,bd66c07c,ba10f165,dade7bb3,77f8b7ad,ac4a673f) -,S(c50b3ae6,d14b11b9,a74dffeb,a5bfb9cb,73652cdf,a2bee6dd,6cc3c912,c312e537,85ac82f8,e3aad88f,9af29cb7,ba66f8a5,8c340d03,a1f32654,2071ba6e,99705377) -,S(a763e636,4e4959d8,9d3047,bff6fbb1,912d99f0,c092fe62,947d4385,2427ec02,bd799a82,a3cea8e1,db94946d,c7d32236,13b008b,da8eca4,921c985c,c022622f) -,S(2abdc992,b2ba838,1da0c2c6,2b35d3c4,ec1a1e39,516b6afe,81fdc7c9,cf3715cd,8115c826,d214c36,36a8fcca,37e89dcf,4be7f34a,2cce7357,3a6c42ea,9e084a66) -,S(2cb83bfa,ef83ab3e,53216500,944b2db0,e8cdb6a2,caad1eec,c9e14c33,a16a07ec,5b1b1199,6e84c17c,13c070a7,99dc0975,3d374018,6f9ce89a,bced7539,7121ec7) -,S(2687de95,b368b07a,7808ebf,e45fde24,d66fdc81,a02744cb,3e96e847,f0a3ca41,5728b8fa,aec73963,236ca282,d1a8946a,b2a26f28,a239590f,9d38bdda,d05a846b) -,S(b143029e,7f32bd1b,a381fe82,8da79713,b53550e,f3cf867,4ef1e952,d4dff9d,a44a622f,ff5fb466,83b69803,c6ea5c16,8d86c673,3ed94058,81aff0a,2a8edfd2) -,S(4c54d53f,cefac583,6fcf3b87,7202afc4,ccd68695,567c7fe7,6068546f,aa9070d,7f42728d,78193fd5,946f3787,6ab124f9,b1045ae7,45df58bc,cab6f59f,a27c6f18) -,S(6b625111,556e3ff5,db9cd8f3,7f610b3d,718220b,e459f546,47314b04,b2ba9d6e,b3ae66ca,fc58bb7,5a057767,8bf806b2,c204b90a,fd114ae8,4ed51378,53b30a78) -,S(b3fb12d6,e16e4279,5fcdc1ee,23d42f9c,198debdd,56217af,5b76989a,271b473f,d38adb77,4ce1d0b5,e41b65c,7c973a27,10c5621f,594e6f70,d235f5e,a4a89386) -,S(9c7c908,6976b590,ba9c80a5,fe12c5f5,ce6bbdb3,5a4058a,3cc59899,82073ae4,399687af,4d3e221f,6168ded6,31644c35,e41606e,94583429,34693221,9322da67) -,S(28cdf6d0,f0374a35,4dd169a9,1c3beef,fc88dea0,4922f841,401ffe91,8bfbddb2,2b8f1d3a,6f001d60,95aab0d9,d6248cef,cf3b97a4,850d1a43,ad2bbb3e,d2ea4518) -,S(1974b196,a25b6446,2ceda38d,d99662b9,7dcd0d7d,15299c00,9b8d14b7,f139e7af,c685622d,96fd6379,6bfc3f2b,6eacd54f,83281ef3,50d2fed0,2507a157,9fcdb74d) -,S(3beafb9f,4cfa3570,3d3346f1,afa48acc,25909889,a60b76c0,6e7774c2,acfe4367,6c8c09ea,7233ce1f,cacc82fc,9c1dd357,51021b92,fb86d6ca,3749bd58,6dfa369f) -,S(b5cf157c,4586fdda,16a111c3,9a500daf,b1aefb07,e32f78ac,a23664b,cef3be73,1d273f45,58e7c2ed,6f46ed71,e297dac3,59489934,b10afdc2,cf0f4270,ad6fd53e) -,S(9bd52baf,cde37895,9439aba4,b1fd4080,84441657,c2b1b36,c45446a6,7b661d6c,87f63761,6dba07e5,96d71dba,f86df28d,c506a123,c6f082ff,47886a93,da068ebc) -,S(20cfa2f5,b391d687,b89cad8a,a4c5ac8d,8624d4c1,ebc94cd5,d47999fd,3278febc,1bd4a896,4641d8cc,f6926323,8b1be2c0,49141736,ee780ba,d2110f27,a674239f) -,S(e54db30e,e18cff40,56473478,2c61d437,c79adc23,51739315,ba845adf,c7e8b6cc,ef631e42,9529a407,cb3f832f,6aee6fb,a26b125c,fd28f43,b9f07e4e,ad8b0632) -,S(588f13bc,3dd3b927,7508ca9a,82ffe280,fabd5cb3,1413e848,2a2aa4d1,78a290b0,95c81a4a,44e6af9,5d8f6fbc,ba3884d6,d6a54057,1835184e,50f5db88,d08517b6) -,S(1927e8dc,ddc7ed4e,62a32a82,bd4a0977,fe24a571,10b1acf3,78826484,de7e757c,e0a9674f,76122a18,dc6004a7,ebd1da86,f98e896,5585518f,bc5f91d0,4699719b) -,S(7b82c663,aa2201cd,71dd7c2f,b8303264,8639f9a7,9de52706,e2deb38b,85dfcc36,90dd6e59,e98c611f,a7162fdf,8fc503ce,71b0ad1,dd150698,e4c21916,d5ded962) -,S(a15fa4f5,97086036,9e9c3946,5f16a458,c7b36ec6,6ad384db,7803ce19,555a2bbf,bd406283,43e40d18,25a02557,6bbf752,35e34400,dfabf022,6cf2bd3d,8fe80901) -,S(2b6199ea,7c42b7b4,2230da51,a895ba86,83950dd9,d4d5ecef,80512976,a0df55af,26ecea05,16faa497,3fb9865,16415ebd,93ce4a6b,e4b5cf11,3507d3e6,6a70b692) -,S(35ad2f4b,b5ba61de,364e8198,f5404ecd,4cdbf26d,7072dbed,d9892804,364b43f4,5481372f,7d1af5e,9e60cb02,ae8512a,6bcee9c,eab1344c,6ac5898b,aeca2e94) -,S(f4eeca4e,2ab38839,8a459df5,b94cf98c,68017522,353aaa98,bc606bf7,5008c6a3,e016b7f9,aba6e910,6a647662,1e7a5b7,12ab97f6,498f451c,21902e0b,9b6c2c2) -,S(6c488180,aeb6c444,78ef24de,21a47431,b2e26d9c,bbf059a5,84631829,a75ec053,ccf084c9,38491cfb,8cf0349f,fe80a315,71bbe0cd,dad9a7d,a4434cbc,9160baae) -,S(a52e5bcd,2214d405,57360828,10ebe384,a94f79a6,579a8966,6f1ef7cb,bc80f4e,c28bb594,e15c47df,9bf4ef2,2666fe4b,d916dd9b,e62b60d3,49c2ba11,506fb79d) -,S(c55414db,3374563e,5c79d9b1,1103ad01,7b7c04b2,3afb5431,8c469cb,49ea9754,f54a4335,7bbaf088,4d18bd70,6f3d69a2,44f4d527,a6dccf5e,52f468e3,752a998a) -,S(b7771609,335ac0ee,1e82539,3fd3cfad,5cb4b06c,98a05bb9,95966e4b,6fc1f24e,f305d878,33f95e99,ff6a3b4a,2b77ffa2,4cddd5af,d253ebcd,d60abb1,438e0745) -,S(da220e1c,c66af350,10736e75,483e2573,91f6d2e1,d355d05b,8471cbcd,4b64832d,bd028d5,5db1c54b,86f6f123,bbabe6b0,f3e52e02,ca48d92d,464311a,aaad3cea) -,S(1a680b36,991edb40,ada892dc,6c102b0b,186bce17,280f9850,ca50eae4,6951ac7a,f03d7958,b0789cc1,43d61fc5,11b70f9f,1ef17239,dd6a057f,ca394f62,225ed9f6) -,S(af8ca10d,b1975668,b8071ea9,5d474b5e,424d461a,e98b5ab7,bc240cc6,44da9c57,e74ea4ca,59f926fd,89bb2bac,61790ee0,50d746af,5e30019c,5b53130b,9cb9786) -,S(e6014570,2ad63dd0,5d98c576,c3d5158d,162857f,7b83045e,d91865ac,bb347922,52931836,4a9fe323,40f13c0e,15c955fe,f718ec64,4b45b141,33fa2edb,c65baa18) -,S(56eedaf1,fec96ae,c2f1e051,9a1c4a76,dc0ccd67,1781cfbf,7804d215,626dd5de,adb8a791,b73aebc9,c6406e2f,83e611b6,286761d1,a6c759c1,de85658c,a4788923) -,S(43c5272d,a3dc8c2f,edb0f5bc,a5bd5f40,fea4bd48,9f367675,cb578690,636fe0ad,52c62fe5,1cc2dbbc,57de501b,839cad13,b94c9e12,12b1cf30,d8463605,f7871c43) -,S(66e76528,7cd0ebb1,9d9e0d76,aaab4230,1aa87367,c3a3f96a,101c6125,84f816da,39a4d3ef,8d263217,3a3a8c3e,d9c1b460,e240cdc6,9c9cbaf9,89535604,a2f28edf) -,S(1a274502,31f1b5c4,9df7564b,f311a7bc,d5123e75,2471c243,65c0e142,d3b292d4,5eb550b4,ffcb5e1e,c695f22c,dafada32,1e967ac3,7e1fc20b,e0e695c4,324c1131) -,S(36f1c3b2,ab6a692b,5d3b1e10,f53b43c7,7d5c4e76,90e089dd,9e70eac2,773c3620,5553cea3,8e56a7dc,384458b,84c419cf,2d493246,1f75f16f,2d1a547a,6fdf0289) -,S(1ff0f8e7,8318fcb0,2b23a1d3,61015c67,6b1a446e,784bbdcb,c088b241,3da40369,39db7b2c,6923a1a2,379b58ee,cb91ad5,554ed5c5,60d5ddba,225c0074,e9fa4415) -,S(c5d7b7f5,d6dddac5,2a2021e8,437f771c,216bfb43,24c57ba2,e8b43a0b,dfd17e8a,78fc37a3,9586cdd2,f1145cd6,f9beda83,43e8ee5c,854c256d,419fdb4,1c9d2bc0) -,S(4af5a3c8,cf107e16,fdf3522c,47fff7c7,b2fcff70,c6c8b36b,7d66a3e0,4b107250,b1b6e5cf,de869937,45ae8632,c5e2860c,76a5f481,ac24ac86,ad135136,e9ff4e04) -,S(37b59d45,86fff48f,67ff3ea3,f31f721c,3daee8f1,a2ff960e,3f77b793,3e35b50,73a7d048,2c93b9eb,4c2f6359,3ce61497,ed455970,9b2ad7af,2d0f834d,6f070d98) -,S(6e9dd180,d5b7c41c,5f529439,e46534ae,b80bd802,b8b12e0c,ccf532ad,a99e663d,e981b043,e936da7f,ecef09e7,cd118646,5bdeaa64,45a00a59,1139eb9e,5628004e) -,S(fde9062a,9f7e13dd,39117543,be4aa5a8,fa10b810,a2285661,720b4586,68acc236,fa39cd20,a5eee1cf,3727df99,32c5289a,96b1409a,5721b9bf,1ad8f42,ee35069b) -,S(d7ef4012,ecc74538,16c392d0,4d1ffdac,76a30992,4c1489e5,159149bd,84847835,b2f5e699,9883a21b,edda98cc,ccc1ee2f,258fe291,c508cee7,39619659,e18c9720) -,S(8355ef2c,f0e37956,56b77adb,5f700f75,47e2c14a,b5f6a0ef,8716c99b,a919612d,d75dc6c2,fdf0260c,6682b16b,42d022f2,f03bdd1b,1e6ef520,da295465,a1988eee) -,S(cd49e795,63655bfc,87bbba18,b72a0c50,52568a26,53bc0543,3661f3e2,2ff159ba,ab28dd46,696b7414,1365316a,c8cd8dc3,2c2f5e01,6ae34302,d103cac7,4e37d25c) -,S(8f93b20f,28f89a46,1afdf08d,7550964a,dfa8df2e,ba2c00e9,9d351b84,2d6e0b78,92ffb09,812b6970,7746493c,c833bdde,6849a2b6,ee7778b8,2b41adcd,62b5620e) -,S(a7b3fa74,4621cc50,f6719d0d,5fd3f2d9,6acd3163,4dad1114,3ece3db5,d114ab2,948a3716,9394841d,68e5b64d,2f86798b,d78c8530,bb8d4d61,f82b5f51,ed0f56c6) -,S(e16b540,d62e3237,361ba514,a11f2ccd,ff72ae57,b37e58c5,d4c3c49d,2cc8fb7a,67efad5f,f02c36ac,a0c0ab0f,ee5e5135,fa7bb3c4,51472d37,abd0711c,6618a7ff) -,S(589645ff,5c3dc06,9d2ff542,5278a51c,c4fff14c,3de96036,b773497f,8940d240,1ea7ba1a,95f65259,c30ce21c,a95b3b95,83d11b10,3c8e633f,6dacbd2a,fbe44116) -,S(d551239e,3448ccc8,9a83b8dc,41396df7,d3db0c3d,f79490be,9d44636e,f5f0d0d6,779118ae,a8db8a05,f2231b5d,923e9d97,5e69a462,5c2ad551,5a8e7777,b1b25899) -,S(c45a22f2,9f611893,d8577d7c,9c1cd46d,82f41b48,a7c18628,ddb609e5,abc434f7,515624f8,5776268b,5a5c74fd,8d87f8e3,3e47648e,2eb8c2e8,27e9b57f,7fee5a1e) -,S(fb8e4546,639d9571,90f2840a,2f72ba12,a72063fd,85f160e7,18477d01,26132b85,3cead630,f8bf75c9,31d19cd9,6f4f3718,1efc4854,b937ac31,c3e0dc6e,363db575) -,S(ec51e7e1,6cbc70cf,1f053860,fd21e120,98b652f8,df9eb31c,74eb787e,87e5ca5d,bd5afa95,6996b7b,357b475,fa7a326c,d6c2505d,1ebf6fa6,feaa27c2,c2685867) -,S(52c497f6,f8b9189d,30fc42cd,9c2a44d4,2d4f70ad,815ccf05,4f50571b,2570bea5,35f54d97,a45e2712,b0f9a720,38adbb27,a31cfefe,c065ba9f,883d36c5,c070e9fa) -,S(2fd360f,1680b7b6,5f49f64d,5a648e8c,97e4a756,fe88e107,91fce9b6,295cfc85,7a88eccf,c4d82e86,72780c6,e1c34bb7,51a6029e,dea0cb77,3d29a85,b0689f5) -,S(7b328546,25307c85,f9ad0c31,ce2c31dc,e746931a,57ec42ac,16231165,74f63d78,6862d363,4360e404,9693dc03,772f4840,4a30f167,993c8f1b,56244c0b,af6e29ec) -,S(af76b473,4cf5f641,25124792,fb558b97,df60d67e,41c2b104,ba27ff35,e3be96c9,21e6d4c6,c1e0d3a0,69520227,c4cf2ef2,8204d85e,26f4ebc4,5d6f81cf,10defdb2) -,S(5b1237e0,54c98238,df2ccb28,a5b42b64,cabac24d,1126c8ea,5520ed69,ac449521,de7ac1bd,4994cce1,8800ac0d,5499c33d,bdde3096,1a0c9028,58de0325,b91ffc36) -,S(b81bcaa2,25743a49,36fec95e,13c8c20f,f818ee5a,6bda3850,870492bb,b3380d5b,6ea959d5,483ea6f3,5b3a4a5c,1987673,a8196c98,d8efe8d0,3aed5884,dcb391ce) -,S(5f6ca7cd,1054051d,3d8a2a83,73be30f3,516b305c,feffe073,ea2773fd,77eeab3c,89287d8,22775f53,61c931ab,bbc43d38,380488fe,5e35124c,2daa5441,3b36c126) -,S(ffb3a36a,8345f9ca,30369f21,f04dc9f9,d5f0282c,d0e1d68b,f5ca1cc0,c05ca91e,21ddcc3e,f5a94fd,8046295f,c0629b61,b1e8fea9,364fe659,d298e0b1,be5a6c17) -,S(51902e3d,8801dff4,e6bfe7e8,8f600d75,42eef0f6,e186df29,3a8c691c,d57b36f6,48a27fbb,cf9dd38,a1ab966b,f635fbeb,35bc3fcc,52f0cae0,d9a3ad5b,2654eaf1) -,S(f1a68a75,8f0f8937,e14a48d7,15c4cda0,679d9b9,12682182,493cd9df,c3ccb345,db85d3bb,b8431e56,d21e8c1f,4eb1c750,225bb222,38da0bc0,30e5da0b,d4f4a985) -,S(81d88ea8,4969d53e,fd0aaaf4,248a3558,f37059da,a4b3d32,da538bf,ca1a4d15,840fe961,11756d96,5c8cea1,32067ccf,31ac66bf,e1086f16,afccdbed,f16a2d33) -,S(b5830ab6,2e236cbe,345044f3,af940029,39b00b52,e779ce10,b02c446c,84163e95,d8720333,b210a391,499f38e,134a0989,254faef5,126750c0,ec2a5850,e1d4a821) -,S(b50caed0,a4e9e41f,f03d16ee,1848d92d,d4e6b76e,4e2332f3,793e8650,20bc4d11,39195ffa,13745502,eed8801c,40f36e2b,d9b636bd,11d62388,8ebab8a6,41d3ab54) -,S(6190402a,3750824a,149945fa,df942c0b,3622acc,b2ee1304,f260593,8de5c333,290f4d4a,73a1c72d,c5ff4228,41e2949d,966da112,5278d082,ab779e8e,d4cb179d) -,S(8966488f,4e991a1e,e34552be,c6246b2d,b9486442,47fda545,f8083b7a,b0435060,7daa3ab7,87283446,a7900c83,b726b849,f7dad684,6326148a,aeeb6233,738c6c4f) -,S(edfa388c,fd246c1c,6bb7bd9e,6d9d335f,9cbd7018,ff2a750b,4ba976d9,dd922b5,c74e1113,f10e6954,6848e4f4,11a5afe4,bbf7dfd5,d252e66,5789627b,b81ce714) -,S(304740e5,1b99d9ae,97de2a55,8dc1abc8,60bb8b5d,a52f6208,af8e28f8,89904951,8ab409b2,3606089e,4a111377,c8a94e5e,75ecf098,4f62aa63,faaf7e18,f93a37d0) -,S(d4ca8aa5,e31028a9,37d77295,96b011aa,c26f58cf,3a7ff671,99aa7f30,3e00bc30,5ecc09b3,bcd9afcd,309280d2,617cbfb7,e4a9350,b4ef79ee,1e46a8c9,56d46fb1) -,S(4110ec3b,ae03a061,59910aac,4f2e4bd7,77d5e055,4eb6920d,aac4b835,2d7cfb4b,c1237e1b,d6f1cf1b,6fb0f248,9e3712ae,5557e4b2,f72ea7a2,2c482e6c,d84eba92) -,S(f7c55f97,3e9df72c,c9da8e04,b1926688,1d53f810,fef5e664,99b81f44,e4f9800,4b45e93f,e02c3993,95238c80,b65533d5,ebd01cbf,1b3dbf44,4d550cbc,4652fa89) -,S(2de3290f,56fbee3e,15def5a0,5d65436b,9d722e3b,a435f269,a5ee0231,857cbd29,f80d2ac2,356ac72,f3106b47,5cbf3701,bf924e3,48e93c9b,f3327b55,bc203828) -,S(c8e3d2b8,21922146,1862d5d3,319c2abc,7dfd568c,59df4367,eb975a95,6e22fda8,d6ec1b9c,e758a8c6,47e718a3,ee8ae232,c416d763,d2887e19,54ae4c30,30404f20) -,S(50c1a147,c117d907,fc831f72,9be19b3e,e93733e3,aa3bf402,e64760e2,edc82065,acebcfda,80706b53,116e4cc8,cdede6d,5aa1b7ec,62ffc942,572f729d,47396289) -,S(7bab8930,55114c0b,e4f7637d,ad165491,c21d6970,c8036375,1387012a,7b785528,6e31589e,2ecb13e,b7bca5ee,39e3bca,fd2e5645,6574a642,131d6178,901c0d97) -,S(dc94ff4,44a12ca9,5180904e,58802ed3,d1be43d9,8396360,e9e932e5,622d257f,ee2a426e,4da3dbf9,8a6d5ad7,9a5437ce,6fdbede1,25e836fa,697685b5,989c86e2) -,S(efb2b411,e66f8e8e,186b0fd0,c572381b,e9edc68a,903e95f3,759a11b6,b6a9dc40,4a7af79c,a1383f20,55bd080b,f410f554,24a21ae5,7b57b63c,bea36486,6c30dbd1) -,S(2f37ff22,26a0c4b8,77a36da6,7a423f59,497a26ca,8066a651,c13573c4,4954599f,f9d1c91,2b74f663,56798637,9de41a46,683a7cb7,61ac6e3a,86d65094,d1e07a8e) -,S(63aa61b2,e24fa178,95688d95,442844cd,7e68edcd,98eb3496,ea071c4,5b46abd,9423daf8,b6c241f8,785b76ab,a40803b0,97da461d,cf6579d4,4308c9a5,e63ac4e5) -,S(58618e22,93c52375,4db8187,34e355ae,27b73f7c,4469d7d9,115623f4,e8e20900,8531be34,22616853,c2c095aa,138819b0,bccd7c51,1380c64c,65ba2500,ae18794f) -,S(61418bdd,2619e7c8,f32c8cc5,34097cc7,4a9a0c57,a38db50b,ad828a60,f658fc0b,acec4e21,774d283b,db9a8a11,115d20be,20cbfcd8,2d67b10a,3d57dba7,74537c48) -,S(79ed2dcc,dd4bd25,67dad04a,b32c9273,39a9c592,95a69b09,be7965a8,c779b2fd,64860dc5,d17e409b,4feef8ea,8a7d7350,3eec186,1fa15f8b,f5576a9a,39f65283) -,S(a20434a4,c51da2a4,c7a6699,84f41ef4,67bd4de8,a628fbe1,385693ee,6b6d8a52,e2a00a0,d00aa33b,b49743ae,6f9c824,d2fe1f7a,f51f7720,cfb0d800,94279dd1) -,S(d8c0bf47,530ff603,c140503e,84fdf6d1,ed908b98,cd27136d,ecb2c4ce,da9f8c61,19e02399,bd898b4c,b9987fb3,4262df35,9b32cca,430e7cd3,aea9d20f,530610aa) -,S(29f06c46,a20b5387,aeb6e490,ef9a7bda,ce16fc2c,8e8eb202,b75973ea,8dc4f3c0,2220f678,daae0cd6,8514c091,a1dd7060,b21c2630,138b5e32,e0d57d79,b7b06d7c) -,S(b18aa504,d9cda828,e67d4f55,ac51c961,e9603d0c,ff737c16,42f1c8b3,fe81aeb9,1f6d7e83,480a9290,789c016b,b62e6e8c,adb4b500,fac710a5,7969bff2,89578ba8) -,S(e7591f42,e649f9f4,477c9cb,bc8559e1,f01eeec5,e9f3a0b4,8d9bf515,6d2044c,24c8777d,5e7c3f7b,2c6fe0e1,cd0e3845,45bef898,aff192ab,c4e719d8,ae466385) -,S(65992fef,50a1983e,bca478b,419ae258,77ce7a52,339ecbe9,2394dba3,8ba72081,32491cbf,baa7f8a,9cf21a4e,57ffa85b,eaba7653,d46d9f95,b4e25212,7bf76781) -,S(771b52ad,e47d035c,ddbb1012,bb89aa9e,b774e0bc,aded4998,86e1e358,ccabf9be,1a897dc8,420a076c,5a723f30,206db0bc,e9760b09,1f698952,1c4edc17,f2dcb202) -,S(a7d5c532,bcaa8ed6,6846046f,d1570837,111281c0,795d3e50,16cd8108,5721d644,13ccc5ee,4bab0d34,2f740ae9,e538d50e,900aa30c,bfe99e54,c69cecc,f18f6aff) -,S(fb504652,a55d01c8,b45ed7,6c71d,9067026b,27e9ceed,c38bf6fc,aee16d50,a150b6fa,f37b0c6e,ce4ebbef,22277b37,44933fd7,a135a25e,5ba8f7b6,1a6b7d0c) -,S(6242a221,115863a3,73bea0fd,39974dea,3c33b794,68e04087,8ebd8bf3,ca09f1d,b806de29,fe9eddde,1556c09e,973fa20d,c4ff916a,3d22504e,19e33169,f6f903e2) -,S(30382a2a,fefc7110,77af1a7a,d8a4a4bd,622635bb,73e50bab,c58116af,d1e8f3cd,d7ff3c80,9845a620,d53299ee,98cf3c6c,499ade93,84791af5,d6618866,3b6b74c7) -,S(b69ab576,13d1527e,990d747a,bab1582c,af995b34,6b25ed1f,df3490c,5549f36c,cf896a0e,4878bc0b,ffa3a750,f83dd329,ade24fa3,76acdba6,dfdc294,768e3f41) -,S(36f6c331,4071ed0d,b2be8f45,fe19be0f,9b37a675,a56679e8,bb49925,9339257c,d593ff7e,a32103e4,9cbf2995,21ad3da1,5b1b44f9,d6c95418,9c794291,b1e6769e) -,S(fc312428,7a9ab1b8,3efce7f8,17f707ae,320dbe77,e5937cd1,513bbbbb,90ed9995,11bce5f0,91dd9ef8,42a46aee,6f3a1d,7cc23da7,381a5f24,4b5a2638,45b2bb0e) -,S(b0de8720,58e1165f,ae1207ec,5ec0888,5f14bab9,35a2fe6b,1f7212f9,7b4913b4,5bab24ac,2589b8a8,c5e102,26a907ac,391289ed,23fba10,b2acdb74,a142b395) -,S(699828ec,db84587e,31ad233d,c27ce5de,a8f4e03e,2c450706,d625e387,12c0af3d,db1d9e5b,9a74caf5,855aef9b,6b8d0c18,c98c27b8,ce0d8a67,c6bd8467,261f726b) -,S(8d133509,d51edc48,97830f8b,3f8a6688,7a16834a,5ea31602,1649e219,cf899cac,9d188e67,2940f23a,39ac6ae4,fa532478,9c5df2d6,57f8b4e4,eca17e02,5560f08e) -,S(9cd47f8c,a9d3ebaa,d94dab36,4412ac4,a74a4b18,bb516538,10da1df3,9efc7582,de1e5cb0,fd5e7a20,322636d1,883b1ce9,71bd0565,a0eb60fa,559b552b,34b42e1e) -,S(1fef4107,648ca126,d5c4fe59,1f190f21,57274d0d,d9c57fdb,ffe2c348,35d36ddd,abf8fe20,87ca3feb,d8150e5e,c66c5d07,45731121,9b759430,4465bb14,55f992ab) -,S(e372b12e,8d3fed92,9e01babb,1a6517c9,ecb54d3e,6d0524ec,42ce57f8,5351d32f,43e910a,32447627,e2d9d5ef,53cb9c0,ab60333c,b07e72d1,c2c6644c,83e7d8a2) -,S(37c346cd,ae9d76e5,7ba2f30f,d05c33fa,3e6058af,642fb1c1,1810b4a0,b97e2dd5,9939c619,e1e49ec2,bf716714,1c23e135,157c7e4e,949e4fcc,b7dac7b9,7d4932d0) -,S(14e337ac,39f0c1d,98333716,a6e596eb,ad0d0688,b815c7a0,c182b546,88e5c3bf,fe45e34e,bfb94cff,a72b6312,a422562c,8ba782e2,16d5ee31,6425651e,e67d3d22) -,S(25517b3f,79da61ae,dd50cd1b,69b1ee36,fce0a44b,feb572e2,e6eb4aef,d751146d,7d2a017d,b9089d13,9a072803,dba874f0,f169ea36,95786e13,7fcd36d8,8b28a213) -,S(7d5957a6,92fd532,b9991383,cae895f2,8554e6c7,83ae3bcf,e72e3678,3475cb46,fa4b9b07,2bc725f8,e35b01b9,590ec1d8,f205f6c1,3203e91d,d9d39954,922d7f65) -,S(77eaf892,c4f9e0d,f63e33a5,1c088e0b,323ddff5,6f854475,b143b458,3e0e2f81,93d0f67d,51abf50,ea260593,96effe6,7f985caa,a9d68250,224e7193,414105f5) -,S(812c11a8,2851f474,e5a0a175,fb527539,7f1c73e7,6a766cd8,7147c9c4,4c970ec4,f9e22a19,a35179de,30379c37,a616d226,666311d9,4ad62b6d,59fcc579,cd024af8) -,S(b633f071,57c5a0a3,7ff5f626,17de24dc,14b3bcd8,4eb43385,e5a59be5,1c371fab,93e70e48,68ab5a3b,e29dab87,8a50e2c3,a09edb5,bf5b47d9,a09ccf59,53b67673) -,S(5e78caf1,9a2031a2,d92e1ba2,1f43f91b,10a98672,5d23ef95,1bdc1f83,cbb16343,b438317e,9446b88e,92206d81,883d5f3f,6497ec33,d144cfc,3a7dba41,db53cbc1) -,S(dd082ebf,88d49fed,50b76df,8e64d3a4,a1d4bbb4,fcdee50,c3ad6d0d,a91e4ec3,9efe99d2,f15d46bd,26d67bc5,ccc122ed,bf5034d9,28bcc946,e4714784,5edb6244) -,S(1ba1e135,62c06b5,63db5c49,7ed46ee5,73399a56,15fbfb1,4e080815,874e6a2e,f298d5df,43111fb,2f050cfe,2a06b3,c9a1fa02,d409dbe8,a225a3e,bec2d8be) -,S(49477847,a590a536,e7370341,5380459,843da9c1,78a1d176,f2f0133d,6ca214f3,3d1b8f64,a1d94169,2baeef3,86b4740c,4eaa84a9,15e4d03,2bd7bfd9,f5d5bad7) -,S(c4336d6a,4fbc288a,2c69fcc9,691fc8e0,e277fb98,e34b7a66,bf29d2d4,32c1339d,64ca0adc,72f0ff2a,f150f01,ea243a51,e91da8e7,480e0553,c7bb268a,22fbd383) -,S(a510cb67,9970c117,49e4e9d9,acdb97c6,d8712ca2,7961ca45,ddc9669d,9e02207,afa065b1,46b75ee2,ff7ada4f,ac7b863c,f4937cfd,15ca2ff9,c0901c7d,faac88b7) -,S(7cd63347,59eec80b,666237b2,abdd6c6f,e5e24a60,9305165,b5bb1a04,2898cc7d,abf7dab,f9e12893,a8040b13,afe16524,1d749660,93cf2da,157e2a78,e89cc758) -,S(e0786f8d,6f339bdc,9ff47416,4070bc08,c864d0d2,6d507762,19c2ee87,61cb7959,892cfd2e,62f4c352,b296a508,455a1dee,8dcec943,f5109add,9d38437e,87ec58c9) -,S(d81f740b,123cfd5,9c5ceb73,47668148,995ca21c,a3ca1b8c,b48e20db,32f6b55d,3af34294,c83c41df,7d5f821c,68e71e34,4656be14,f09d1858,7a204244,6f74f4ff) -,S(f4ba0503,6ffc1812,efbf3fe3,81423d91,38eca2,a67a0f4c,2d0474e6,5db9efc0,b2b3c3b4,4af46f2d,e53b1e8a,adb83d59,4c32b6ca,a7113207,b7993bef,dcdf78b) -,S(aa6f03ed,50640e0d,72fa4de7,ec3964ab,82e7758f,5e6c16d7,78c18296,e3b1a527,322223f7,ecf473a8,36bcfd41,e50f871d,715f9729,93df1359,80794587,59d9767f) -,S(f2d48f68,23984bd9,e8e87772,28da095,4ca134a0,6b43e0d1,1a8843d7,1fd0232,f0b7d9e5,982d0f6f,5ef74bc6,78ee504b,6202f52e,8db7c069,e179d175,c6f760e4) -,S(70e9ec90,7db14601,9741a4d5,ba604187,a7313b7b,500864b5,383b3763,be303979,63f9ef9d,eea1d1bf,a84e0d19,c8f15665,60b4f1dc,839aef5d,b6fbef7e,d6dc6a4a) -,S(23cfe5f9,7198efd3,f34f657d,158f092a,29748586,29983927,9c58944b,146cdf1f,3b8fdd8d,cd82a757,44152552,35de0cae,c39e20e5,f82c7b6a,2afde8f4,1c6afab6) -,S(b1e2b9d6,4c14d667,4de9a6a7,5499cfb,12b30a92,b9bf7578,f8fdbb55,b6d414de,1e91c321,24341a58,e2c6d65f,18f3f735,f9f98d2d,76d124a2,c694db84,37cd0483) -,S(5092db9e,5bde4edd,f385c67f,357e43a7,c8fc8e09,f5c07c14,25bb405b,7e52d1fb,cbad30f3,f96767f9,553c9be3,2adbae2e,1f27f9d5,3fbb2f99,a361056c,ddf52858) -,S(59d39b90,2143ace3,3a1a1e54,a5cd83e9,6cf56f65,4a91f524,af8c8e19,e25496a5,be21c89c,baaffe09,4f2114be,72ff26a8,22db9a1b,818d96a2,bafa797a,3af056a5) -,S(89cc95d8,cf45bab6,9b3f86f7,9e1fa71a,34fa83cd,3d4dfd16,1c9df1b5,817edc16,5eff0aef,63fc853a,f8b65e8,8a45740e,6c78aade,4bcfeca4,c7413ad6,714eef84) -,S(6c2b8809,79398e60,87c756c,443fb032,f2adf5f0,17bf9ac6,44d164b7,d2aeed3f,bc46cb71,c9ed9f46,b34a22cc,e1332cbd,44318165,85407951,580e4b26,270f3eca) -,S(767ca583,c950f7bb,e3aaa6db,b6aa9867,792e0b8a,6930ab97,5c46d09c,30e14a6e,bb90634f,87133104,1c7eeaa0,4a09887a,e5946daf,e88828a,68761cb6,21412d49) -,S(cf742ea0,35c4d9a6,40fd0686,a460ab96,e2015d0,2c15fc8f,333ecb7b,8af4b08d,2bb94f28,bd69b51e,de993065,fd61fbad,c65fc62,90059a8b,d29948da,20b704e5) -,S(84d5d76a,a5a6ec84,52f024ea,b365290d,9c3b6be8,f33a93ea,b0a0ac4e,e6271059,f5565742,f1a47a88,8d0bb802,b002ea6e,f5acea8,864e2f64,fbfb1565,dda51952) -,S(8f5752a,8fbdc1a6,201b6e0b,7bd5db3,cda2eafe,f18cd6d,559724b9,56767d32,d63c0fad,de72b753,6d0c8606,88e0a82b,9f9e35d4,b1db7be7,efa9040b,82298008) -,S(20578def,f94e3597,50ee95bc,61ca76db,f8fc059f,e25e42c5,bf887d49,665d1871,5fc52a36,c95c6edf,46bd5c38,60e151b3,9f123e9b,c58b2079,cd165c1d,e6f33d3c) -,S(30f2b825,739fdf4c,5af0ca08,47f50323,d3ad6eb0,413b052e,525f837c,38f97a4e,d698b076,4417357c,a49b4306,7d73206f,d3d97036,26ab15d4,f11c56bf,4bc820ff) -,S(2350eca0,b4d0c460,12024be,6d458444,b37b20cb,50042830,182b5e41,d564e26b,5909eee2,e3999d60,4cbe0832,58012001,30a344c5,f72ff127,35e66cdd,904623d7) -,S(ea660cfc,45971e57,852d382a,ae8cc6b,1887fe68,dc1b84bf,31f4409,89f89b2d,52297e86,dfec0730,81a280f,9451623f,9e69c320,6f3c205a,f07e56a2,54cd5837) -,S(9cded450,2a7da3bb,77e06ae3,ef398954,7687d21e,df522f3a,cb6b4fd9,d3d49beb,7b13f455,35a49049,277abc34,3cc6f0a,336242e8,7b69815a,e27122e1,d7838a8) -,S(ac8705f2,cf8dcd77,d409a962,f98a6abf,198dd238,3a5eb258,6b0d2def,81daa172,892fa835,a0af6cf9,dd5bf158,44b22cf8,2af258c0,519955dc,ee4966c7,bd5e995c) -,S(fa026b1b,d5e5fe3c,d6b144bc,6b22f7e7,5512ca6c,9525f62,fc7fb4ea,bcd2282c,4ec40de5,7ffc1768,edb20cae,d3a11380,fcc32f45,f410ad9b,8b674d95,6614aad0) -,S(a928eb73,28285c79,5717dc0b,ccb5280f,92f9a4be,5a0b0ed7,67e58eaa,8b9097db,af57cb66,61a9d08f,4d4e9e25,aeeea2dd,e4c88767,c4e177b,37a87ba4,c2bb772e) -,S(bfc9197f,80fded3,c601a0f,1c8c1d77,cbccaab,1c8357ee,4fb67875,cbbc8261,6a721e0,241ef436,69cd386b,d07fa2e8,900527eb,ec3c0025,24bb457e,1bc7aa28) -,S(ae0de043,b332bb4f,91395870,4f3a41f,65e0f3d9,ff77c1d5,ec3add49,6087d5db,34d697f5,dbef1bdb,f581127d,bcd2755,a5a6b32d,73164665,ef84f6bc,145c2afd) -,S(4433db73,29d75b3f,7df0e229,538b7a33,e41183ad,7a7a5e3e,ccf5863d,6bbb692c,3a66630,a03ab85,9f23ae3c,a0a38717,d82ac240,d271b3a6,ccde1407,d0dfdfa1) -,S(bc7380bb,128a6f8a,5cdb971c,31ad12e2,ba593acf,718f5468,285b7f14,69ca2b90,a17af518,9a7b0445,cb37e797,a281c84f,8cf8ecaf,c661e601,4ecc2467,18f1d8e4) -,S(bb53297b,18d2d785,a4756437,70b387d3,ab0fe62,8b78c09f,bb6cc226,79bc92ab,5c34b9b7,cfb3737,bb515ee8,fcff8592,1fe8f30c,e97d21b7,47a4b084,22b0c811) -,S(1accc1c3,f46945d5,7b46b1fa,15291ae4,2f0a616f,df23f1c3,3f0dcf97,53851fb6,bb434ef5,e30fb9fc,15e99b15,b5f9d766,9681be30,d2b0a6f5,a4946268,158d5369) -,S(2fd61a9a,b99c588d,fbe74fde,e8ce95cd,1c0ee9a6,da7ae59,910485bb,9a3ed9c6,2c214840,e2bd764f,74f9db81,43ddd549,3d322dd2,b25790a8,a681c97e,2fda07c3) -,S(4bfd09f1,4cb492a5,7b9ef3ca,d245a0ab,c4bd97ef,12bf7204,8ecfee47,660f7161,57102f3a,ecc42742,657032bd,aa36526c,e67f2589,2775fdb7,e8b029d8,1cc7ec9c) -,S(f60eb13a,8e6485ea,fe653e74,de1c1376,2df7ba0d,4ff0c65f,24bb1c0d,74cea3fe,c5830078,5b74cc82,80128896,f275fca4,9be94edc,744f8535,128ba7a0,5c1d9552) -,S(2b4c7864,9f568eb1,ce1be63d,aaaba4e9,7c31349f,aa353371,6e9123f6,4c57b041,b5dc9c1a,b39325f9,3ead6f35,66c30479,5f817ca1,b3c37258,554c4fb2,51a0ca39) -,S(7fb057e8,5f559f11,b5d41538,6a25a77a,aeb904c5,d1be33cc,bece20ad,57715ac4,2352db61,6fad3f10,a2decdef,5a7fc369,5c8462b3,7d2d5ae8,bde17311,ac6b4ad3) -,S(a49bc870,bfd62cf1,1dd1bd23,9499157d,247ac61a,a9b34210,65d4d029,56f71a0a,b639709,88ffd1ae,ed1b62b1,83ba629e,f5f0c088,f8a9016,d7fa9157,46642e3b) -,S(30b1f21,f8dd3f40,697878a9,fa0b9fbe,d51c1ddd,165bd5f,ed9d1fd6,49ae913f,d5a55164,4628de36,25895fa1,471e0f5,77326d14,132d8ffa,37e0277d,a928532) -,S(8a015768,8aefcd7d,13cb3b98,373a8823,aad11a4e,718a6ea8,5fdb8a9a,6edfd879,e7d92909,4d198910,44c00be,69f267f3,84aca1db,642648d8,34a5b9fe,518e1363) -,S(810ee87e,45d8a5ee,c0e3fd0a,cb771d2a,5a3116be,f4dd7d5f,bfac0dd9,fe072778,92abfc24,9500ba0a,9cfa1725,da4c37b6,cf081f5c,c6cb6a8a,3af889ab,ddd2b7f1) -,S(a0eaaed7,687f6a94,398656fb,3fb15f49,6522c3dc,c19e04b4,598ac4a5,6408d1d9,792a67cd,677ae878,eae040e1,6378cc36,9583b513,bca68fa1,cca3cbdc,37aa61d5) -,S(ca438737,ffa6f30d,9aa695fb,3d29db01,f805f480,ddf1b227,3a0515b9,5f8eba97,56238731,ff5314f4,af6a3835,b30ae83d,feaf0db,dd4449e0,5736efba,8a8cd51b) -,S(b252f5e5,4b67554c,ba3d481d,66a2f223,a633b5e7,f335e357,29928264,e744279c,c6296730,5007e2c9,3fbdb25d,a33a9fa7,411218c2,87b937c5,dfcf8f45,472533a0) -,S(f61b57a2,237befe8,2f1545cb,131acb03,3015a5ee,f0cb77d8,c73add0d,ec0083f7,9b1e0c93,b326a265,eabf096f,f8eedfd5,9f765b51,5007c5cc,d0d3b569,838f381) -,S(30df434c,1051cc43,4ca35671,3957f964,af406830,38ce82a9,5cdf2c7b,55c50f7c,883bc89b,f54c490b,3be0d434,fffb6b,7e829be1,55280401,eaf44bee,7c445424) -,S(fd0ab148,727eb712,adee1fe3,4e3d0fe4,99bf8307,fbe18e4e,d20d5236,f7ac25e7,f5f38f32,df094903,b3219b02,8413cfc0,e56b8ed5,6ad80e5b,aaa00f4e,3877377c) -,S(b4a8fcf2,b406becb,6111c030,ae375f12,79de175,7f2f3b90,13e7ac55,12de747f,d1634039,59a6600a,fa05b1cc,3c459fa4,f1a5fd4c,27ee5382,c5f01e4d,a0259889) -,S(a6c10f0b,33d1518c,8f8b7055,b139aa84,c96e9998,8e8a256c,5883bb44,10687c72,8f0dfa52,ccaec6c6,789941f3,cab90b55,4d4f587f,bb6f3354,b5f7158c,758e4f9b) -,S(7188fb46,e244a5a2,6e38cf13,bf2e3c4a,ff5bdcdf,8d9f78ae,88213692,d866f5c9,8cb07d12,ec743540,3be09b19,4cfb2f1f,c4a85d27,d940cad1,15ab53ea,4b8e0d88) -,S(fe4f9f00,308670fc,48e45208,4063fa94,a6cf7141,d75a6ef7,4f92b474,5bf692ea,5dc45ab4,77f80594,4355698b,e95bc582,efea563a,970217e5,2bd28ede,d7e8cbdd) -,S(93f3b5df,43006183,47c7bc14,3eb046a3,842614ad,78d3cfc9,a6b665e,3327b7cd,ffe5f378,7ac36947,d635d156,7a28fa5d,45c0b5e1,70508cc2,7fd621b4,47b63b53) -,S(dd350a89,e0c3128b,54a3955c,bf802ff7,3a565760,39e1e068,e783ad00,36c13604,45cdb508,3c33c35,fcdbb29a,efddcc63,c4cf3fe7,c08a15d,8b2cd4ae,dec2c3e9) -,S(4f164801,17c1d338,7738b728,96442b9d,66f44eec,e3eeb7ff,ffa87d24,4226e44f,750e6348,490d0ecd,3be07303,5a8e653c,1b1f7c30,d89e27dd,4efedc9d,755b89ee) -,S(b7c62749,aaf79754,de281314,acb4b2f0,271f2a35,fd187307,20349a3c,a4b577a3,f100956e,ddc307db,56542c1,d2c8f176,e0636ba,b04877cf,3dad451d,edcb0df4) -,S(fa5c1278,1dd929a0,2ae4755c,70531cd6,c309261,36ef51ed,7d57c117,c1c8a885,57c5280a,5f08f0c9,393aab6f,eba0ae81,a32f8c6e,2a76c780,a871170a,e37856f4) -,S(e16d6dee,7830b0d,e6cc5e4,9b1cfb7b,50b7d89,57fa4e6c,42ce9925,2e6a29b6,cd5955da,4c1ba840,a3c98d1,7dea8d8c,f4a3d2c0,1e0cf164,2cdc35ee,87fea835) -,S(a2c659f0,a0ef6147,ba84ff26,ca81443c,ac8ba9be,f6fb32f9,50653384,a5db0213,5176a4b1,88b5bbef,3680e875,437e4209,d2fd2462,77c5f84,4a0eaf5,e9d8c129) -,S(7d507179,6a7c037,77fcf84e,62e6eac5,456f88fe,76e71301,76fe458c,8f301a68,14018264,59d3f62,6788fba3,1505c83a,4161674,21dbc2a9,dc14e1a,f45a50a8) -,S(642721c9,20d9b3e6,72db8d82,34ad60f4,bc74684f,11f2ef1a,8171d02e,b9eb1f12,fdde8b98,8aac7393,be2366b5,6e853c7,b72034fb,2cb176ee,770063dc,42b63d48) -,S(65fc35bd,2f604eae,48a1b68e,1d66cac3,627b1498,247d8376,47082702,293c97d,d01018e4,85dba402,17ac631a,9b88d240,de32ac74,79c7d47a,9f5d9188,f8ac01d7) -,S(65c8b230,2e51129a,b81de5f5,22217f06,f5d5360f,af191c56,8f395a33,2b04375a,3201b7ec,117fceb2,b225f137,877ef481,2be4d6b4,52d1c855,f73adb0f,e99b2943) -,S(b82aa6a2,86fb19a,d2eeaac8,9019782b,d0d6009a,8fa07a02,a0d6295,ea8637f0,426f8d72,ec1b08d2,72671566,1f77f470,f334e4fd,3370d96f,b0acca8f,2df99398) -,S(a3222e7a,c6c27f2,8b24b33d,ac78d873,1ce060dc,be055100,862e71dc,e6671a18,6f2c2a1c,4b80534f,8ea53777,71760fb6,5148d47e,ca097fd2,b7bb2f53,bb07ce22) -,S(281ffed7,48a4022b,c663d08b,5681733d,f1343818,d68c8b63,9f4405db,ad7020e2,b5f18609,d8e5c6e7,990808ec,b4fa7d2d,7d4cd106,b7ad2c6a,e356f239,9a535eea) -,S(c520ea8b,a481c220,bab0f218,72ccfcd5,d7014d8c,fe55d1ef,743af305,c0277d5e,e23eaf34,33e4369f,30d371d6,e396b0dc,a065506a,c4159967,fec4475c,8f6bf78b) -,S(54d39ed1,114ec02d,8005d7a0,82178175,78f827c2,1b55a95f,330a7af9,34727958,4aecf190,229c49c9,31862a57,9131aeed,5518cda9,4695e8ac,7ebf7667,d9afb23e) -,S(756b9bf0,1da8d7f6,1627cb2c,b3ce3ba,a9b6450,c2d24596,feae8bd1,2ef67a23,51c47b15,b2ac96c3,5d7b7dc2,d8c57ee9,69b347ff,dadb04e9,cbfd6889,a0ef70b7) -,S(eef22145,6ff200f,ddced960,f422588e,333a437e,d68c04ca,9758d77e,a938ac54,21587cf5,8b8ffb72,6d29aed2,3c984a4f,25df40b0,abc9b7cf,2c07436,ab7e09e2) -,S(b841b560,c0af44a,35bc9320,3c05cb32,250fcca3,f83dafe,30d1dbe6,61aa3d1,e7956525,3d07a89b,2335e2ce,9e11fb89,96e2c146,271189b3,461cf944,2ceee2d7) -,S(14b98f62,5849b798,48f32547,efccc33c,3ead6cd1,a290f03e,618acc2c,1ce065e1,4e7a2415,805a4486,476221f1,ce8234e6,5b81ee60,e1ce5eb6,b6a2e041,ac885e00) -,S(fb0aafb7,68c19f64,17e417b6,f1c22dfc,737bc74,fe8b23e7,4dc1c1c9,aad7ae44,88b83e23,631c58d,c3729cf5,54343721,e9ec7dc4,a889b85e,31cb302f,f2a6ab3b) -,S(885497ab,e34d1745,a3e2ff8b,bdea904,eeacf100,324540c6,86de137a,9756468f,63f3f160,bd266c3a,7c49b13f,c5b06403,d0614b79,17c49824,bf507257,2ac0b948) -,S(52dc7bd7,17e4d8e,8b634439,f6f06b8f,7121a0e0,cfebe7a8,3031668b,9832b8b3,90679373,9bbce1e3,5c48f41e,942d9f15,9161e9ab,273a2217,d9e857c4,3bdd0a5c) -,S(e6ed2c69,a8bd7af3,35591f4e,4dfba7ac,d82e87ee,e2b3bd28,f0f87f02,3abaa7c0,dfec6118,7396bd5,e32ba2e7,a8fc912f,1e54e078,6f2ee222,35adcd22,8feca28) -,S(9e2171a2,c1025129,1757e26f,ba979e5d,6b68c2b4,975c7289,2afe7898,cafc46eb,3dd062bd,210bfc4d,d30cf01c,51d810b5,cf1b8ee3,d3baf490,6bf5d381,b87c9a56) -,S(ef4b8648,3bf209f3,b1c2e166,a32cda39,44b21282,db8acb94,6ef62122,63bc44cb,903d1088,ccc0ba47,b5ac3252,33ef9b55,924e61ba,7ca80bd8,1925b269,3998920b) -,S(64ec6d14,7ecb6e44,6331907b,b9006b2b,fa4fb854,20ab9aba,f1026bc3,4ccdc4b5,583cad3,b41bbfec,d0817207,dd312cdc,26c0411,b888ce5c,c6ee025,baafac63) -,S(128cb9de,125429dd,e5b9b33c,ef9f34a3,e7b38ba,f22dbcdf,8e169894,3f7ae5a9,a10a01dd,33f5a4eb,66091348,c4dbd90d,62879ff6,7559229a,e53c2896,8fb4584b) -,S(a7d2e7db,ca0890ee,e07c4bbb,399a0120,e71fc284,c5b7c96b,4889fbb6,db95dbbe,b8caef70,404a19dc,15670cae,b19d5b74,e70b7492,50390b12,5f559b11,feda83de) -,S(298b17c0,b8beadff,5e6eafb8,ad7d756,8e961468,d8e12c94,78ff3870,dc722450,a0542f35,c7b95774,b1c10f75,3e9da029,ec7a54a6,97bcd9fb,46c98d26,91ac1a43) -,S(31a39bcd,a3d10e9f,6b46e1e,c30b41aa,557ba664,9b12db64,a13557d7,5c592d1d,814f1a6,15382d4,e57b8d41,351fd782,ce7dd9d7,86aa9bbb,c5b1ca7c,207ab12a) -,S(3317f1a8,1afa54f6,ffa6df13,bd3f818d,e9a29bed,7c119b6d,fa31560d,31d81cfd,aa8eb746,4e9acaea,19a42509,a23a281c,e9917788,6d3de977,4398c57,8867e095) -,S(85511857,80eab56a,274cad22,966ca547,3027d3c,3cdd7e25,7d8ed8cd,a5c6ef30,b13de0f4,45d71bd7,db0327eb,15438e9e,84fefc1a,464d8a2b,bcb8c6b9,f59f93dd) -,S(fdbffe5,7e378262,c32bc4b1,e84ae01e,a2d6dd76,28e10b04,9adf6a3e,ef106e83,f19d0c4f,1411ba50,35d3ef23,153f306f,d40b22c6,69e92ea9,22bd7d5f,83a98ad) -,S(7562779e,6aae0c51,52acc7ee,43bed76c,831ba008,82d89c9c,e29a5f3b,8855b3c8,c83c1662,7cb9e1d9,126e07b3,354b82a8,a0cd49eb,3936c14a,8d8d64ed,2a4e217e) -,S(130b292c,10d5b336,4635d43a,fb6d6e02,d5acec2,c2033525,ed72c030,e82a4a08,d534b710,e1201276,6f6fce50,ed6efec7,3e0c3e75,50e0bf36,d5d625b5,4855fed5) -,S(19fecb77,bcfc0db3,e595fe22,e96f1212,b3ed032d,183be5e0,ed4c1b8b,d0501bb3,6b0fafde,2f0636e7,2b4ea946,a0e5c27e,4e5dfb5f,e8b8a1d1,b36bdee5,75d02e81) -,S(ffc668c7,9c6f9fd2,f5c56104,aac1286f,cd4a390d,ca586af2,c348458f,b4130f77,fd7b748,d15f10b6,4eaf4946,34fb4ddc,439919a1,1155e40f,24f3eb2f,482445f4) -,S(b9797c7b,d4112aa4,8abbc827,fae12fd9,6d19f3c7,81626e21,5c26ddcd,b2d4552,ddb0aa81,3113288f,1fd2505b,d23f2a9b,a1ba0a38,dcbbfbcb,46da78bc,5c705327) -,S(9388c9f6,5bda9c81,62ec04ec,5345ff80,da4afe34,7281f768,4d8daa1c,cc3d7869,23ef5140,3f926d0a,d2ebbe6e,48858850,aa98149c,89490e99,65dafeb3,c82644fb) -,S(44cf864,6c2d2f30,e62f63fd,8e145786,80c1d5b8,a27fd496,a8e34bab,5f88270,9784e329,a434b442,fef9af66,b23ea917,edc0f6ca,8d28a992,bf6944ff,26c5cd25) -,S(ebe08589,930001bd,ecb83ca4,45c4a9fb,fd61b229,60ba9848,2e0fd520,1af5a0a9,ce2d31fe,3c271048,24ed891a,910e2cd2,2b99b39b,480ad812,a5d6860f,71ec817d) -,S(176d14f2,5491c2f1,c1d4fc87,a8f59aef,f560bbd9,41872f6f,2a1a6adc,7620f1d7,42c1e0f3,8a3379b0,c5de8a01,11b846b4,35db7783,caa9b84,8084a985,f0e123a4) -,S(74e96d3a,972baa6f,8ad6876c,9494f451,a12adecb,681c4d55,57eb58a6,de920fc0,c2cd92a9,994ad5,f4700561,e8b57201,96e61a5e,b4cb4a55,66959bf1,35a07f83) -,S(6751dff8,5079fa45,7f5df468,624c4a85,db970586,889cd80f,d4514bbe,8de42d60,7cc20505,deeb3f91,3d78a265,cb301c68,49cd5a53,dc029af5,c0db1876,762ba3b0) -,S(f9c63056,24d8cffd,abce64ac,65dd3a09,ebd344a5,5404d08f,b4140a4d,8489628d,49ad5449,bf1b6def,74283afd,2f315f77,3de82cda,d4c9de21,7995a2ff,c44e934e) -,S(69e8c4f7,3f757235,d0e4f39a,f2595cde,f7ff4d20,dd2d45c9,78f32d19,921b6672,8ffc35fd,8a6d541b,3f7135f5,643efb00,14f275ba,d929671,df610748,6f763f55) -,S(3d03e571,ed2aa88a,3309f014,caddfd64,26ae84a2,a526fe35,f30ceb8a,4e645e22,db95c744,6bf115d9,4af9074a,6b274725,adbcbfa6,77f9ce48,535003ad,dd37bc6a) -,S(e5b764c3,dc73619e,51a2afa,fb2292ad,db2b7b0d,e12b46b7,f14b66ce,f8aea7bc,41fbe1bf,41838b6e,9a57fcbc,b3e2e3c8,60170122,29a5ffe1,7394139f,5e8edf2c) -,S(adabcca6,b4252849,76596462,36b17b0f,9d1b4e9d,279af84a,c02f556c,e0f4c385,7d12959,9b411665,dd23b676,57229f84,ae46773a,e13284ab,1cb608d2,ccedafd5) -,S(963094f7,7ea2a7d0,3115e201,45dc6f6a,7318f8b9,a55ab015,8096db54,48e341e7,36bb26ce,3852ba30,dcb1a8ee,ec834f4d,d5342ab9,f7bbe85d,7addce07,62cb22aa) -,S(30ca6324,b4f34e1a,4c3dbe4f,d6dc6b13,a8ebcb35,2f632fc1,5725bff5,f260c508,5c04aa15,8dae7205,3bb608db,1b9245cf,fc57c10f,d015e80f,7afc7532,632eaaea) -,S(8356d1c4,55479df3,adbca347,fdb73f89,6027471b,e528da9a,d9e6a968,8dfba744,c325c86c,cd603953,8f610b03,21b6147a,371314cd,2c41df91,745e579d,8564a177) -,S(996ca7b0,4ae2dde7,b5ee87d8,c077bf97,9a63ce83,cfb84349,c7d231b3,1e15bfd7,cd1d1b48,d75f9736,68b91101,8ade913c,19a1d785,65adcf71,6c805863,fa6c1f17) -,S(8a15dbd3,5cc16f77,b22a87b4,4f93e5e5,810f0503,56e47d53,95769128,a2047738,cf96df1,9ecb6da4,3895641e,4fbd4f27,f00f58ce,cd34d38d,e258fa78,410a1f7f) -,S(23c1e11c,be9f6a93,6c5f8abb,6cc501a1,ca38b03e,f00b31a,79057156,f382ad7c,1d996782,9f709951,2c9728ac,68c16db,1889bcbb,7df432b7,f430ebe6,56b1e050) -,S(d937ad87,70737b1f,d52bfb7f,86e207f1,9e4bed5a,43b165fc,981685e6,24b8e84c,202913d6,1eb467fc,b488fffe,5914f853,73aaac20,1acde09,ef975cc8,a05fd181) -,S(6457f59b,2c744ca7,89537c59,6485abe9,7835368b,47de3667,4740ecff,72e5596d,30b6ffac,65e34e88,43681e64,f041870b,c85b3b5c,86c032b1,e290848d,ad2f7a5f) -,S(7101d56d,813abe1f,c50aa99a,bc7b2363,9532d79d,facc17c9,f2a5b4ff,50edf82e,62a0b9d2,bcab5b18,9075f6f0,e648a4f6,fa66741c,389a4196,a4c5ead7,cbef14d8) -,S(2dd4cb3e,5cb59cbe,b961af3f,d1154fbf,c21916f1,d5331ce4,c8a32ad6,8f7ad818,397dde68,7b1f6b5d,38e457ae,2f5fb332,74917949,801151e5,3d4fe19,9a34289a) -,S(509c6fcc,ae22b09d,b8f3d191,434e584c,9d17dc76,c268560f,2290d81d,53ed66dc,cbf69e20,c3f9ada3,41e32dfc,581f0ba,f015413d,735d33a6,260e0cfa,7a4e4d05) -,S(71babe5a,9458bf5e,112b23a5,3f87007b,66ddd721,32a45a34,2a9c521a,c2029aae,55ac872,a0275be6,4f569901,d84dca32,ea13e2c6,cbe608ac,de228185,34e031a3) -,S(f5f2144a,46fe975f,82b91da3,a98ebcb,6d5769a3,4e5fc50f,3ca640fa,152fa7fd,2fc05c22,2b20b895,5503f23e,627558b0,e023988d,f02993f8,f495750d,db6344fe) -,S(d6f274fa,fdfcf64,25972a56,640e53b8,15c4d213,8e4a72a0,b8ab3394,2955e416,738e267b,2fe0d9,5774afdc,7c4f559b,7bfe2824,ea6b7a49,d3220eb0,460ca733) -,S(81a12fcf,cc6acf7b,89f30fc,8f61e2cd,7882f664,55923993,2b8d3f9b,1d6e11e7,a8dbc6c1,cdca67b0,64b285c4,e2f69242,cf55f06c,5eb28868,d9bab656,eaf9116a) -,S(57019cc4,941f6f5,9ed34305,92f35a83,39a495ee,fb3e311a,fcef9001,cb8123be,a3d632f2,54083f5d,6f2857b6,9556205f,59578908,9d8d8fd2,4d10bf1a,e6d2e635) -,S(4205a71f,504362cd,576c4d84,c8b65252,3d4227fb,d6aa28a7,e7fc3d70,d1387c80,781bfe55,7fecdfff,c54d1c1f,e147792c,5ea7a1dd,7224954e,e110cc6e,18ab452b) -,S(1c42ad3d,f90472e9,e5c041da,52476ea0,896a2032,ccff22a8,fd7bbab1,4c3961f3,a5072a70,be702dae,f9f93148,4bdfaa00,1e2f2ad6,7d79f46b,5717147,17c5499c) -,S(6c9225cb,668ecf25,1f7862ad,999516c0,145faa37,b4fe92eb,561104f8,f1dc2997,8c12c1a1,e372baa1,4e9b1443,d3530548,d7d1d05b,fa354c7,f47ecab3,23993a31) -,S(72a0fd2d,eced2a05,6885dc81,fb61e881,b09104f3,8650a872,44e40471,ed189992,d9c67490,43bb493d,9aea4a1b,3a50da8a,e1c48523,9a480442,32406d2a,68487e6e) -,S(b1d531af,8faa24b5,69945ec8,1448915b,a46fd13a,f7fecb8e,16cd5d03,52c6c2ab,b3ba6cf4,bd36bee,66deba09,35bb85e0,b9ff7e62,5b5c793b,543a091b,dc83292b) -,S(da79daea,d6ea65e1,4e8747b8,b4546560,a9e5a99e,eb572f17,f2ebcf3f,9a307a86,f5b3c430,e0f2d4aa,2f278088,2d683c48,d84f926f,6feea88b,10e06930,6567a290) -,S(1fe7fb5c,99a69a75,a2276ca8,92f67da4,951bbb4f,ee4df8b4,a54c9833,d0d33869,e2b2b4c6,fe0f63f,d97fa179,331e9bb,55786006,f0425e98,71452aa8,361f177a) -,S(fcdb7de9,4eacf36a,9d662371,edd2b535,af33de37,1985ff49,6ce5293b,9d2ac00a,e332723c,7a9708e8,5172e56a,c4291760,baa17e83,72c98dbe,83a186de,77c2aa06) -,S(daeaa6cb,19bdb4b7,78077495,a9cead03,3be16d2,97e742c6,97ac18ed,e5b514c6,4545ca53,bde3c1ff,6bf32604,ef037da,93134215,7057ab10,cf6af451,e7753f4c) -,S(83e4b4c9,1a923321,196fffb9,b45d089e,7fa1f6b0,5ff45a6f,d099f7ec,fe283088,926c28cc,bf405fb1,17c5f168,20216226,4c89cda2,cf669937,2739ea05,279325d5) -,S(cd7f2b53,8363914b,2e83f1e1,c9bced9,32a682fa,cd72b46a,eda578c0,640089bc,ddf6dc27,a5281d3,b4d66af6,8fc80f5b,16cbb7b6,ebfff06c,6902d38d,4632ed2e) -,S(6f3f5a27,b19dbfc0,238bccc8,a9adcf95,adef6480,fd4ca405,454509b2,97a40928,36a56db2,abf62faa,b2255d86,d8a46aec,361fd2a8,65740c31,babb2e2,c551a85e) -,S(f7aa5c92,a523b86b,c27cf714,51f7dcec,fa18ef3a,9e839c41,a8b20c4e,30ba3b77,fa7d3ce9,8009f23d,f5eae927,acf1b28d,5ce4a2f8,8a92da7d,fcc1acb1,3c8cadc5) -,S(4adaaf95,5bfa6a94,b518f7f5,b0ebbdca,493798f6,72293e4b,36d5fdfd,5f641b89,ce675ffa,cff579c0,61e63c2f,36e77f3d,5c2571b3,aa99d3c2,74086b22,a862577c) -,S(2d737aac,3600371c,f6b638e8,8a29884c,978b783,cb843922,bd449e95,814db692,205d944f,13b21441,76d8276d,74da68e5,142aac9f,ba632568,79753c01,e54cf4f) -,S(7cb5d365,10ef241d,ac378fc,ebad8738,e8f2e6ad,6d838731,e5c82bb9,169d51d4,33b088df,5a572e8e,1010886a,d01b68f1,9f345770,81a465ba,8c5c784f,225f6510) -,S(9872a376,e530e254,8b623b6,b9dbd6d4,d123f2f7,30579f47,4d910831,7c714c0c,3de01ddb,3145d81e,6ac002ec,70086f74,6eb2bdee,6295f5fd,9d2cf8b6,1b222e58) -,S(8242fc8b,2e848618,ba0f26c2,6acac090,8eb21b4f,41a08b76,beb35f85,3b8c2f33,58b94d44,3379ea4f,829fc809,ce2632cd,78d8675e,45a29c58,e29fda43,785f2e9) -,S(88800a95,cf1682df,4e5bcde3,a96de21c,3353751c,5300dfa0,d0f802d6,7b60eeeb,2a35b86a,4e213e9e,c53dfe04,d91afb48,25bc8794,a1574ac4,53e81ff,4b6e453f) -,S(3c8e2755,9611937c,b7e2b2cf,8a87fa5a,e5c696df,fc6703b7,e1e65ac9,111ad87c,c54d129a,be0c774d,dd415707,bfabafdb,daedd1bb,2ea9cff3,bcfae0e4,55c916e) -,S(281af73e,a1f092c5,535557f9,3b5a8c94,54165f8,76650801,856bf926,19f06cb8,deaa8495,30951f12,ea157714,3caab5fd,d30f0dce,ac9b80bc,fcdb3477,dc01ea1c) -,S(6b353e5,3202f63c,69bce96,30535f11,1939fa,849dedb,92ad21c4,89f5174d,bd961eed,c16f285f,2eccfa69,d37a6d63,be5fad00,4858c80e,6fc4dfb4,2717acc4) -,S(68c184f1,a06685de,fd20f36c,82b5446,7446d5d9,8fc9c312,4852bb02,f35ed91d,486a3d16,7d94c66a,31f9e134,1652f658,76d49379,f3e3429f,e9f2da30,84f56532) -,S(5e884531,fa011576,3d36e1ad,74b22e23,f765db14,8b8e965c,80f7c9bb,7d561bf0,34c4f03,b137b627,3fbdb6e4,8ac09ef9,bc3c8ccc,e720853c,61ae58da,ee3a0cca) -,S(10c13f0f,313e5ad8,ea61ba5f,ed509aef,5ddd3016,c3339eec,ffc8f9d8,6f131118,28f6ad5b,324e44ae,64ee65c1,b86710a2,91a8e71,c33adbcf,a84f18fb,144dd67c) -,S(aa99d8b3,1031d4e9,8c078a68,7254968a,9141c710,cd8e4842,5a384bf8,414f5c5f,ee6eccfc,1dbdd5a,c9080cc1,ffedbc6e,64fcf847,ab9c0ce,fa91c4fe,d1de44bb) -,S(f087945d,a464e66c,4c73b58c,5034f057,b96ebe34,f5128397,cfadd7be,22ac6100,c5485411,d78fb395,3f229109,45aac354,1a2b2acd,1d95c38a,f51f36dc,d3cd92b2) -,S(2e4d8752,ac21c22f,e4d465e,3d2f5ad8,d9168080,b2b44930,e5de75a0,d9bf91ad,92f394c5,963c0817,500d5a98,2eccdeac,aa55043e,27a9a035,1a6ce245,a8d048bc) -,S(68b59755,44feb608,15a6ae70,9c2647b1,5c7fe073,aa6af8e6,202b9782,83daffac,b3745e92,fd86bfef,ab9d3d26,cdaf57c1,2a329889,cf646b6f,d6cf869a,f727e0c) -,S(15f5f668,e9576897,a287f131,bcbe1216,84f7a108,3c28c09a,afa77074,63dba49b,133e33fe,9bf06bb0,3b814938,7a099da4,77a3e758,82fb19a4,463ab360,bfbc368f) -,S(f2bf3cc8,ea752c11,db2ff594,d3f9b085,1dc9dff5,7999aa39,b5af2a29,30d50491,6e01a801,c5b7e4a0,a16af1ff,b011bc12,cb0483dc,6127fe52,c992b07a,9fd77635) -,S(1b04817f,46dae06c,120f8088,b3cd09e,267d4ed2,db14881b,bc32b5d6,345dc54e,31634e28,56f61b80,56a414e3,94a34ced,200bb172,e9a9aa07,6a224329,61f55ecb) -,S(693f066a,bca2046,ffb860f6,5e769ca2,3d1f46a3,6c09273d,afe5eb89,d2da45c5,719dd749,5c1b1938,a92af84d,eef309e6,ff1978b7,9adadb96,c58caf2b,625fff9) -,S(3fb25a02,bb232d18,c798f688,b16193ae,cb2eb9f5,e124c999,225f0720,63417008,90db4fbe,fdbf8a26,ff9b4afd,355e3771,c7c95891,68e2abea,264aba44,ad74707c) -,S(4c878f4e,6ebfed8e,e12a0a6d,17298b70,79d9de5c,6a7b5359,5ddefe4c,db82a79c,837592e6,927938cf,dc82252b,2cbfd9f6,cbff1950,405b4511,f2c21fdf,a3f72715) -,S(5ccaf6f4,2b75e152,49263cb9,5fdb34a8,770e8828,98a1a0cf,5407c48b,b9ad4ba0,70851419,379e5e2f,dca9613a,a9f92fd3,8ad8904e,e0ce0048,b2510943,ba8ee24) -,S(455907ae,713d1ec9,3792d488,7d9857bf,a02bc2ce,abd2c599,cf576f09,f7d09d11,1fc9ee5b,90a039f8,eb3200e2,ee58022,3f0cc699,60221d67,86f0deba,f13ca6b9) -,S(6f7acd2b,3683482f,c2c2d55b,eb62a89a,37578a34,417bcabf,ba7c56b7,bec14f0b,6049db59,b6210e55,b06401d6,17247d91,64e84e2c,b8de91a4,d4998c15,6f46d621) -,S(100f00d4,eee4ccf5,ea2558bf,92bec83b,223fa214,ad692ae3,b0a2ac93,c546d558,fe055fdc,1ae02552,1557db5b,96a62c92,556f918c,ca908708,46ffa1bc,8192b65e) -,S(8650c359,664c9f15,935dd776,bc6fbcc8,d9cb02d4,c22428e2,aee3e3cc,6e9d0c6f,89dba800,919866cc,8c16895f,785fc9cf,2661f78a,9e065472,652b71ce,d5ec8732) -,S(22b6df12,b3932756,713e2ee8,2d296c64,5d10364e,cca1ff94,9b477fa4,9a2ce5ac,ac58a22f,42769cf1,e2e23308,b3b5f139,4d329323,4bbd6053,4817ab5c,624e995b) -,S(ce87a23a,1554ae1b,9579ae96,863128cb,926a0cce,e51f17db,75155607,754b5992,4bb953b8,9d590216,e326f23e,66768c0d,17626262,6fecf80f,97435b50,d5dbd503) -,S(e3ae6365,29e3fe6b,cd1c89da,d72b17d4,8bf05c1b,c487ad41,d3b97838,a2cbc19c,4634e222,316b6ee6,c7616cfd,cddaee07,7fb2cd0d,26dd9f81,9d0ba43,313b3f4a) -,S(2825cc59,3a0678fb,e0d37d42,df72037b,6be96e98,18c52c49,fd426d75,324bd620,ea0079c9,2ef91a7c,dc587343,7b454763,f2fd4adf,561cd023,8379c8cb,1d281f6e) -,S(a6b2a170,fb23ae2f,943408ef,60fcb145,106735c,8876238,5d0fdd9b,75a2c46,1ab40091,e000012,60837529,58e3134,5f260890,d1bf6930,ddccedb1,dce20255) -,S(99a36f38,759f0a70,d719e3d5,b741a40f,daef1ad2,bcc65293,3992f134,39ff339f,a36d4b07,a7258053,61430332,6be79a,61ce8eb6,97944c6d,8bbf433b,a565bb66) -,S(e511e0a,de5a9be1,1b8513e,a5706258,6de09e2b,e2df739f,d647fd33,7890d36e,c6cc03ed,e9e50830,bd5579c5,9d6db693,dfa5c057,b1c214da,e4064804,9cd7ed70) -,S(bc9de66d,a406288c,a8a94e96,5ca16dfd,379608c2,63222a24,e3fc1116,20a82125,ac471a7e,579cfeaa,fdfdb5ff,9cccd4e,dca4202b,1b0149ab,ba9f6c09,aa219626) -,S(e98cd505,bd593bc1,496b1203,436f6038,ebe3fa4f,361ce4a6,54315402,a74c3a4c,1350c197,1c7979ca,7464c4d2,39b24a55,a1e50812,aaf92479,d566fffc,9135d977) -,S(47c0c788,2490ca53,37cc668c,5a549bde,dac661cc,f77534ed,d11f7ddc,9e0f37ac,ece10949,be122263,26819032,a2d952c3,60b27e2,7e527673,e8fcef08,a8f27685) -,S(e8224d65,35ea98a5,e3fd8833,7bd167cc,776f89ee,7d0ccfdc,46a15fed,93bee5e3,44b260e0,e0b1e1e9,383041cb,1dd985e7,22edb214,ae58f784,f174ba84,ef51c59e) -,S(c195ee35,5880dd77,67e01659,ecaf07b4,571e324b,b8a1a4fb,75265af2,3ea74709,95c39cef,f781f53f,31bde05b,d0289313,4e478b2d,1c55e741,aef8035a,2ecd4226) -,S(60d989b9,c9cccc66,139bbfed,e2902a95,fb9ca9a8,6c2e863f,21eceb4a,7d73c4bb,8295928a,a48ec1fb,775ea29d,9da1ceab,47e82f3f,1e6ef7fb,c7505e26,92bb51d8) -,S(a33b33f6,9db29609,8cfd34,caefd3e8,c3c0d863,ab695b06,b47d102e,f827fe62,669d9d96,842ee809,2cc31cfe,baab0f1f,4007c3e9,e7e41be3,7a08d221,1c6bc905) -,S(bd25afea,d9b8c833,fe332a2a,a9f3b627,d8328152,8fe1422c,5da90163,4b971584,35bb66e7,35326f67,63f4f38a,c18f8412,26da97da,c9e66902,f28904eb,b49cd78) -,S(4d7e208a,4264b565,d8563cd7,80773012,581e8688,a62921f2,d6a334c3,25625279,6729dd4f,b45ecd25,2c5cb033,dcb2f520,dc928ca5,71026fdd,b42943e8,b5da9988) -,S(5dd46f97,fc740db3,ec56348d,ed73fbbb,c440e3f3,33c64a3,a37b7a73,7f0e987d,7e2d9ee6,9e1c07a4,b764cac,aef3d780,e2d43288,2863f76e,35ff4cc6,832ede1a) -,S(4631992d,d72c02d2,2073222a,d35917f9,2770198b,ad13a847,8d3c9ca0,6ac91a3f,e28ce87b,35a69d5,c43b685a,e59d5f9d,ccf187bb,62517a92,90992b39,86d9e1eb) -,S(9153ad32,32177422,e03b6739,d5654209,7fe04d22,28b1e873,f02e990f,8936d1e3,8eb9f3c6,b54726b0,b4e867e0,5ab2fbca,e76d2e20,ce07983d,6edbd5fe,ebd0cc8d) -,S(939a7349,28fd798b,5036e2e9,60360387,b9c080a8,982d4530,78415667,848c2eff,30d2a2d9,5890d023,7d117cde,2eb3c532,e419770a,8783a7dc,dfe40674,709776f1) -,S(8e67bb29,9f11e01,b50be7fc,bee1f73a,5b335f5e,5ece8619,9a514156,dc243f3f,7fd0cb92,d6f9cd8f,bee9d337,90a4492,b8a7fa02,a0914c48,1f8becf5,d9a9d7da) -,S(a2cab3c2,537d8fec,b2f891a8,1da2f523,de4f869d,3c812806,855013c,73485ab2,765d058,c681af53,36ccbc8e,88d2391,b4894b18,15441342,4c4e73ac,1a8e0d71) -,S(9b39be40,976c13c2,faad320b,9338f985,b0718123,d2fb543,b65473a5,3bc2fce0,10f8234d,455fa7df,d09d76ee,41035515,9b560db,7b92988e,a42f9e9c,f7baabeb) -,S(35011530,6f2975be,73e7685,6456c94d,700e9b1c,4685639e,4f60efd6,9e513692,5992efac,9dcc0a58,ac6e00e3,54e44582,7e2d66c7,248e4b86,f8c216fe,a9e44270) -,S(df5a5b75,d96ddb93,9a341f58,7e1f997,3cb9e799,b04ccdfb,9907b57a,7b005d1f,3fd070b9,8d759043,8a53c302,b7ac0dbf,594094ad,7101d500,1cd5d687,e80066f0) -,S(91f14eda,a0db8441,10fa531e,eac54762,d52ca420,bb872327,6b383587,d40fa761,86cbd213,358d1f70,c3f6ac7e,913daf0a,47a80f8c,bd72445d,fcbef37,d0d71e69) -,S(53ddba06,46853311,9fe95719,15a9efe0,bc7fcf80,59d638e0,be6c1aa4,c5f21ffb,e59de2f6,5e583ab,5ac86c77,fc298301,70a18b68,a1979074,c21c0d8e,4a562567) -,S(56599462,4ad07c16,607afcd,76e86218,b15b50b6,9df84695,e60a15f0,3d7bcc49,c6d36636,ef58556f,9b688db0,eecb6bd4,5a7b30e,a9748732,68be57d8,542c966a) -,S(76fd5413,fdee9cb9,7f92fefa,5efa27e9,9aab744,e1e15029,241e35bc,743307a3,bb23f425,9aeb64e3,8ae82c3,b4691bf9,3b4a719e,a8ce076b,d0345a2f,d02a6d05) -,S(511ff159,2127502d,7499b988,7a3b3bd6,1242518,58bb62e3,dc1638be,89204a0e,21da5ba4,34b7819e,53b51e46,29f5fb77,e739ae5,97af55fa,aa09500a,dbd502f6) -,S(8e948cec,51635ab9,5a057404,39ff17c5,ae2e05e4,523bf2a2,3df28fd9,86de6b15,e16aa2ac,6c3d34b,9535b795,29a82b67,34bfa260,4a74ebe8,86110d73,ba564375) -,S(ebda8670,9277fecf,9b8507d9,40da6c74,210c8c7e,ddcff0d6,e3b52ded,3bf57095,3ca95e8e,112c8137,fe8c5088,bf041674,fb657260,70625890,1fdc5626,7655d654) -,S(eb5ffc4f,559f7ad,2469f48,1c730925,1ebf3863,357dbe72,41a29205,5b667682,b1f72d74,a5a16ef1,d55804ce,76974f46,61a49210,8a1a36f8,a59484da,a9bcbb96) -,S(2a93ae8a,d15c82ed,19fd2161,4a7a65a4,cf562432,623bf7f8,6c765548,b02fb57,5a949ca6,60a1430,9d4baa6,9be69b34,848e9874,62471d74,54c4817b,336584e0) -,S(9ac4a3e9,f1c8d115,138bd299,b6fb9132,c5d64a92,1fd94adc,82eb4ae,fa64704e,47f0eecf,a9eea827,ff339f3,48e67e8f,da9f00e1,a6b9086b,6f5441c3,7ae1d335) -,S(add254af,39d99d6d,355510d7,4f8985ad,3d8ec1e0,1e8d0210,27e80049,f555d65f,5b147a1,fc4bdeae,6c2f1224,b35e9e61,ad0799db,53597ef2,a23a8f3a,344dc526) -,S(d374d326,52cd006e,3b27b8d0,3ab47d44,bfb1c5d4,48adc992,5f63235b,c34aa128,3cc6ee09,c04d4cb0,aae8b1e6,6018640e,d0964fb7,148181ab,e9fd0374,642ad9a3) -,S(fa7632b4,78e5389d,cbf380d,8efbf6b1,d4bef9a1,70aa3517,e4c2005a,71a283f,ef2bcbb0,4b20be5,d4bda0f4,26dd0baa,31037d2b,7b530e2c,24105c3d,c817ce89) -,S(68ea197e,76af6950,1633ff9e,c825a817,80c7405d,ba513f96,6106632f,ea73ede5,633a5f90,587d4ea1,72129820,2ccefb30,c14a052a,6c0ca723,65e2f91d,53b3ff4) -,S(8874397e,1813f0c7,6946a84f,b05a0f44,224bb110,8aee722e,736e807b,b045b73a,ced2e2ec,85ae00e0,2952f55d,3626b613,641d2a8e,84b4c9ae,36177bb6,9ef80d9e) -,S(2ffe42bd,89256069,2e460701,b94208d4,85915043,8a85f71f,32246b8,5dea7594,6e7e4050,a35f1570,f8cc40c0,862e9cb5,59e744bd,8788646e,b0dad904,8b2777d8) -,S(c6d3a6f8,c997cfe,779a9a30,79de4bae,c19c226a,21f166d2,71ab4da2,cbc6defe,a8f8a618,3f6c8b2b,1486e60c,337725c9,9a9adc07,7dbb6581,e5b0119e,ca10f418) -,S(9b51cd75,442203ca,c4b8aba6,e9829b73,abe29f96,92b8dee8,500e1a90,9ea9767f,ed0ee32d,6042b6dc,dc818dbb,8cb00619,6bfeb2d7,88f35626,789cabb6,5d159c51) -,S(952c518f,775c8bc4,dbd7629c,8dcf8807,1b208033,8aee2ffa,eabad5d0,be6eaa1d,8a3b10a3,d9343d39,e7bef8c1,193f5cbd,717efa3b,cd2491f0,2dc1aa17,2e5b629b) -,S(49a18372,63eb11af,77a2e33d,2743393a,7eb269aa,f64589fc,8f81507e,55e8ee4d,7feb4a59,64b781b9,640d60f9,4e7eb291,6025d190,95945aab,7ac7771b,6f96cff8) -,S(cf974d8f,46aceb5e,a8c04e55,703b5a43,ac577e84,cb174abd,88198e1c,12708c9d,c50cf6d2,afd79d3,ce275e91,26bdaf0c,f46c1eb,536d0753,9dcf6c2d,d79afc35) -,S(461a831e,8beb6da0,df92dcdf,2697d551,cbf8f903,138d13f2,ec9b7fa,4a7d4763,e5fd85fa,c251705c,27d4e870,64af33b2,ff99b19,14496d96,6fa18916,faf40e01) -,S(eef4eb8a,9eba3f2e,b27e3aca,6cce7335,49f2656a,c26f1921,60c05bb8,fc3f1165,58f74526,a812ddc3,713217f6,fa4be02b,7062d042,2dbf5625,abd1f422,58b54c36) -,S(d674ace8,a7e8ae,d4bd4b7f,235b9f4c,41ef4355,4d9e6e44,3b6a26a2,d16f798f,8a25a7f7,896c0dd9,b1639f99,5c4b3df1,a3536104,b7d59348,c2c56c0b,bb21c609) -,S(a8eb465a,8a2869cd,6419af81,b3ad1355,1508727c,2b2494a4,93b5ffe6,2c1375,f1a27219,f59f29c,bb93bdc0,6157618a,454075ab,b95184e6,a4601ef4,eb2c8a1f) -,S(ccbd9d,6253fae3,f7d2527b,17854e21,58581e95,11a1f11b,55e3e04e,7326e6db,51ddefc2,5d9083ce,e9999e91,cde32f70,344ec937,d6aa5272,3dd62496,c4b0485b) -,S(524bc1e1,5c75e8f0,6718d2c6,da0f6599,c8b5d83,7cb9b48d,615e8e46,49dc6659,f6c91d14,72a50c31,1bb202b2,3d76f224,b55af957,c7bf3c19,69d175a1,d36ed19) -,S(520e667b,a0604a23,dde663ea,1a29971e,7e753301,9b2217af,296b02f9,de1df35d,9c2a2c52,290b6927,ac566ea8,4caa31ef,cb19b65f,29b4833f,5f4eae8c,f12b38bc) -,S(156282cc,65317dc1,3323aae2,d5d83e8,b7113d59,a50e54d8,dc54c1a1,ffc85d23,840cca23,67da3c5a,15b6427,72f0cd7e,675bb8b7,fb5dd58e,8cda9fcf,cb21606c) -,S(15afddb0,5adcc8d8,f1322a7d,f451fee9,873d4b8b,78b0c1e8,1d99f002,84aca6a,15465563,a129272c,b5e25bc3,ac76c52e,b4e115b7,b216a40c,145c4699,175cec9b) -,S(9eec4fea,e9508445,4bd275e3,f8d0d6d2,9040ae95,c8268f55,918d5f3f,2f75865,b7a873a7,5fb4ef70,3d62a723,81df2ded,102726ac,81685725,424a7733,8307ed7d) -,S(3aa7be96,660652c4,de1c82f5,cce1a864,c37725ba,848180bd,52e4dead,1a33f60c,f323d266,3e5d14dd,18fbab76,271f6c8f,32d7de0a,42724fde,f6ed3582,c886c402) -,S(bae9e070,a8e5a976,8347368,c32b4287,c7a6a20c,b491bebe,fc6acc71,aeeecea7,b5791703,f98ae848,1a9c66ab,878f7c27,d37a3e0,133b4e36,82ccb2af,b518e8ef) -,S(7b12ed88,be061d1f,7dab874b,17602bb0,ef5ccefa,54f9ff40,e753312c,335f5f86,70930f8,c465292b,b02ded5,59a235e6,c4c83480,9eb94442,8440846c,377498d6) -,S(9eb22b3c,8faad620,ba002990,4a5d8d1e,8cb4a054,179e3310,73f4ae8c,def4e1f7,6d58b972,ee88dfd9,4e429a2,4f6961a7,d085f00e,8d6f8d14,ff2066e7,df68bc34) -,S(bb2aa6cc,d8402cb8,e7a9a6f,a755c66,366c659e,bd2e5c85,7fa486e8,aa86b857,443e7128,674c040c,b0316d9b,3908bcd3,298e727c,c805bc8e,ca58894a,d51f4130) -,S(c58704a9,fc3bb18b,c460c4e1,f17a880e,c0dce45b,e2caf759,72f55061,d59d30d9,75216472,aee1c9c,280aef07,7208fe42,136b495c,f80d8a79,e8309272,c6c4d6a7) -,S(b7d7c721,70af0b6a,489c41a6,e817da2b,ce59f30c,88a82b11,83a6af8b,174c70eb,59481a78,52f3726,3a02ef48,dfb366ce,7bf170b0,af3c2000,2c1053e6,5dae1ef8) -,S(b1386833,25f5450b,f4f68dc9,93d72fa1,1e636a3e,8b881ac2,f237cc44,42f3461,64d18f1b,87f9463,10627931,cb003c09,981c4a94,969a0df1,7f717830,4daa6cd6) -,S(7e27af99,500cb8d4,d812a82d,29ca369,5e543231,8432c9f5,96f5b76d,c6d1bd8c,25a477c5,a275daad,10973822,40961da7,5385a367,6dff887c,42bd904d,8e885997) -,S(62e04f6f,d953c744,aeca984c,bad13c91,f4e09c1a,d5441603,2bfbc277,5ebbfdc1,4f1f609,db0befd5,fe781afa,d21efe44,846f9f78,9ed9f99d,f3291eec,3cf3fc89) -,S(b08a1f84,a3cbc3fa,f952247e,6d8d8d9b,1ba3ab01,ba03ef8e,836b94ec,dfe2e2c4,5027889d,e524fd0b,e6ada02f,4f33d1a3,4d0c3822,f0ca6651,ecebaa37,3c54692b) -,S(d417933b,c7a8f68a,9e023d64,498b5117,850f8885,b6254256,f9a12a47,538d5bd6,7ad14679,21349d14,10e35750,167282ee,9a6f6044,b6c9d71a,633f4475,5b432ed7) -,S(575909cb,46a36dc1,c270267a,10a62f31,941fb7bf,3699aa43,1a3bc770,fa37d5de,c12ef954,c937d6a7,bda47e2e,67d9ebb4,9434cda,e1571ec9,f604c41e,b49d6189) -,S(5298ad25,cc5a6bf4,d88b693a,d32a61fd,efd763f0,e4008ca0,eee17730,4365de57,75f821d1,66b60185,41cf7653,9a0cc41,597b8b78,10fd1fed,f0da4542,3a26d5f1) -,S(5aab0fa4,b0beb77,d5d2a8fc,c95d516f,1dfdc402,3e3d36b1,4ecb206e,ee8c5ff,7a4659c7,7c062356,c51ee28d,fd0cea92,a1f36d5a,b78a3ae,8b48ac9c,7fc63fca) -,S(482fc791,7c739041,41b69e59,62b0b815,8a9bfa00,f203afa6,46973980,9b250a23,89b117bd,485ac6ef,4de8eae0,a9e96edd,a3615285,e33282b7,bf0b6a6d,e11a9c8c) -,S(a576ceef,40728a7b,b63756f7,f3095c75,ff2ef84,c7933d02,b9dd8a0b,a6046653,b4c707dd,9d880fd6,d7a1ea13,87dcb6a8,e2433e21,8ef3a7f5,e348d2b3,f9a9796a) -,S(3c9d7c33,f8c62b35,fe977359,f290dbd,c2b46fb0,a2fe126c,d06e0422,54d1527f,cf92e34,3ce9f624,84c04c9f,d97569d6,67065598,9418d858,aa7368d5,bd6a2df1) -,S(56bdd1e7,363c52b8,2198cbe8,62ed6d7c,7b96d184,7da44036,2401368e,b2c83b89,505d385b,747c9545,6669809a,a9da035c,364e7971,7cd89417,3d1d5d58,298a1869) -,S(99e0696d,ed30d242,bff69e9f,ff4ec88d,eaa3de35,34dc7f35,c2bb7df5,9f8b440e,2cd1fc77,3bd071b4,c9695f25,458be688,f662f7ee,ae8f313d,9c373172,6185acc) -,S(7d5cb46c,81f4a4ec,f1e5d913,1772277e,d17de7ca,7a4b277a,d6b135e4,dbe61916,cc854503,d73e8034,7a6ad7e7,f5bab321,b130d7d,3d938423,9e0656d9,74971849) -,S(45cb6ec8,9dda9aed,5242347c,a20377bf,c93ebbd,50e48ea8,159530f4,4f4a250a,411a2ade,aaaf43e7,240bb0f7,cde77d8f,846bc700,4721f6c7,4d313fbe,70ae38c2) -,S(a7e23331,bf08ecce,2dda8c2e,a6c3c4ce,9bbbe3a4,4d40068c,e39e94fc,edea42e1,d1f12d24,144bb258,dcda7060,5348c1d,85faf076,fdd3611b,ecf6c34e,843788e6) -,S(d81aa0fc,b0a8fafe,d4c67dcd,6fddd414,80cd5548,cbd6aa58,35e5896b,18797f12,92af7ad3,89320814,bbe53ab,4cb5bd26,3df11ad1,8d2ef235,ae9ba163,74495d8a) -,S(8d379fd1,fc0acf5b,c96d03e,b73b340,5a7326ec,82882235,918a380b,c3e2669,f8c6063a,eefc0e2c,ef94d8d,ac4e5b5,ccccdf25,663d993f,7f9a0172,6756564e) -,S(5e20f600,6f533af1,8f3b6e65,17aaa2a1,2876b79,c99ca059,c2791a1f,1e466e8d,b23fb129,57640a9d,d38bf206,7649216f,50b913b8,69d241c2,baedd5e9,dafac9d3) -,S(1a0a4f54,80d37257,c62d1b0c,18dda7ce,f2b64754,be9a3d77,b3d80ca9,215026df,2f76696f,f4001927,9ceb5652,44d4a60a,9e353266,42bc2138,1191a51d,7661ca1) -,S(be868184,dc2e91fa,b11833b6,f78577f7,8c190220,a2b46551,53cc8ea0,73a217e7,6ffa3f78,1c64c118,68abc331,beb8c284,2919d593,12bad699,53edd222,2b98a31e) -,S(a4650db1,917b10d9,1fffa809,d9f9cdaf,f07faeb3,8f0ecda6,9c80e0e0,fd27592a,d5a6fdf5,647e26c4,1d7b9c78,7880c76a,b0cbc23f,d4c1840b,78717b34,2ade1422) -,S(944b1701,4a7c7eaa,754c9e03,d56516d9,e21e254e,9a871683,7a14f19a,9ebaa517,ee198337,3822c796,3ae7df88,24687dda,eea01e83,c82e66fd,baa746ac,485a6dae) -,S(f9e76020,cb9087d3,a60ba7ef,7ed5e552,3e5a3645,f61f9ee7,27d630b7,98d37ede,28371db3,433bcf49,f6d77711,d7ed9101,f5e478de,49c58103,b021457b,7a0b526f) -,S(7ac0c7bc,e17509a3,e4dc004b,d18c322e,600aeb83,8fe2045f,6da348ec,6f178b41,8b5cbafc,33469334,4886f60d,ee7626e5,36e9a977,60c0dd18,7bab7e45,6b264956) -,S(1d7ef98c,c8520f5,2310ad12,107351f1,966b651b,4b2a39a1,7a47f658,857e3bde,2b78bf4b,7be6f1ec,61cb235,a26e252c,71d91f58,69752719,8125712,55d47664) -,S(fc57f5ea,b40add8,f00c2da6,c7d24540,1b24b6b1,f102836b,4041009e,2fc6d5f0,11d3e017,bbc33913,b7861dff,bc11bca5,5aea26dd,f956d21d,2f333755,ef823af1) -,S(340c47cd,3b473c01,80526815,64e77f7,6ec29eb4,b6603985,d6ef7b64,29e2f289,994d98c9,c1de0dad,d27f3386,eeb7da40,6144e060,ef4db403,ee8a76cb,8e21bf89) -,S(81b13929,f08e9a23,69127ba,3e6e839b,8e9cd05,b19a9bf5,2292148a,26bc47f9,b6c33861,ae8fe20c,7a6c7830,4dd03fc1,a281ea57,59661e74,7f9e904,e4261226) -,S(6f325fba,15a463ba,4a61e2e6,82655af2,72603643,8a48075,f76c9882,4d7e252a,1f205971,70f9f48d,5421b73e,97bb6260,cd2235e4,6f611e9e,99b7f8ae,cf435d45) -,S(4b388e91,fadb26f9,b23b015b,398c8666,91521b8b,484d4510,b3c162d5,834bc109,ade8365,9d59c363,3191c3b,20e395cd,13ddabe7,1933045b,cfd8e941,f2096d25) -,S(2d1c0ab2,83c80dfb,ead3e083,76024910,c1d97acd,6c8be069,252bfd94,ac1a0db6,c4856c74,e5ef2e6a,17ebc35e,3b310f6f,8e7b043b,abfff733,aa3ed9f8,5a391c98) -,S(4c77a1b5,b88ffcce,1f98fd89,251c0085,9d4197f7,d45bee5d,edfded14,a97e5b87,48b8135c,b067c292,6c316424,2392fb06,f698b6d6,e98b2ffb,bcdb028f,4d85e5bb) -,S(d39cd5fb,11cabce0,e31f6fac,10cce3c1,c0bdbcc7,294119e0,2b433b0c,20e3a4ee,487695cc,8a8ec5fa,aafdfe25,3aa7d635,8d44e82f,77328e8e,4541f7bd,f629bb5d) -,S(238a05a5,519ff4e6,29b0f86f,9d259eee,4e620685,a2f0509a,cc9fb1eb,4e89f5f,6772f6b7,816018af,ec95717d,a6be2d05,3d740ec1,80241798,117ed39f,91f3beb1) -,S(c146bf13,72816407,b5f8532d,91210d59,a8a6db2e,54fcfd3b,fe910365,99f7ed14,e952ca9a,f88779c7,eea67194,3df6fad9,72b717a2,19d1eca6,33106f97,2dfdf0b3) -,S(4cd9154,861edfa7,c29378aa,1a7d6d0,83b134a7,572383ef,3010f34e,19d40bea,9ad99f1c,b5841c57,5f7db959,362542fc,40b0cbec,58d16ce1,54c5944b,6ff2aabb) -,S(d35f2995,2478be06,e86b342b,fd2d2cc5,ede30ee8,509da11,504bbffd,5884765d,a0f66db4,a21462ee,e51e226e,2d20d896,2c4edb1c,babc45b2,645968a9,c7810fb4) -,S(caf9c953,ef1f57e6,905bfec0,2fd64fca,92ded9a1,9435ad1c,a672cb7b,117c6fa,23b01776,7662984f,9c2f9e43,756ed3a1,3a574960,558db4ec,8670122f,472d0ccd) -,S(4bd40ba0,21d2beec,ec7317ac,df3b719c,179ec012,1274a198,d0ebd9d5,165bbfaf,9a5751dc,d7885a78,20d8ccfd,1db3e3d,aaa2bd65,b7b6fb2a,2d7b2902,c629d81f) -,S(560928ae,7b15a63,62eb4444,d4c0e069,1ae43323,77a2de40,83f056b2,70259814,ae97006e,fa5986b6,5da4ddbc,2bcea172,f12945d9,b6f5184,4027085d,bf644794) -,S(7870209,38e53dac,8e250835,9e41e313,25b09faf,95b03a8d,c25e83ae,f8255301,49fd164a,915e0af1,a66af8ff,d215d1d3,92e4996e,5ef68f8f,51a4b895,145bbd90) -,S(7aa3742a,6c82c90a,7e6c1b04,a41e4643,47925d,66f4e7c9,ab2aff17,e64932fb,7317dd5c,f2cb9b3d,5cc0fd6a,c433d1be,d1dc8345,b26e10b9,a2b8cbff,ce2db0c6) -,S(7a400535,be3b134d,4572e0bf,75c13098,dccc0f04,1c10068d,31e2b0b9,149c2e08,c00fd102,309626e5,a2f97ef4,e0374a3e,de0a7ed2,e45aede1,40521086,5d10466e) -,S(f4d71adb,438460c7,9003e150,c4143557,ffe30efa,eed122f,dd97c572,e1dbbbb7,e73588e0,fbae054c,140c0474,348b7ce2,92a1976f,e8c940e3,62c29ea4,31bb719a) -,S(34b68d32,810bd1ae,51d0c82e,ef99752e,8206aa04,8c5c30,7c3e9a25,b2d68b94,4d044a,6781875,6aeb8982,61bff840,a3ab951f,bf60cd03,e8befb25,97203c7e) -,S(f83b78af,f18f22b1,f2081707,3dbb9c79,4f180b0d,8871a1af,94d16d29,5c71f1c2,93ea5b8,c7847ea0,2cd5b783,5021d37c,dbbd395e,fe6eff8d,866e333e,9d6083e) -,S(a4a0d5aa,f521e1bc,2e818063,f4575f1c,99bd2447,80eaf848,2737b297,b2deaffb,3906373f,2111a47b,102b0294,f9fe1a4a,7ea9a9e9,aa2d9595,68ff8419,9f1abd97) -,S(cc211da7,28671182,1f0bca25,b9703fdd,ac9d0277,7e1829b4,4d9921d7,998011ff,c0cc46fd,5519211f,3a4cfa43,d84e5b3,bfb316de,39a5f4,9a50b1b1,8dcef321) -,S(8a07ed5b,e0397b5a,8c33ef,108df270,4b385c45,c8296593,1ed3e391,17b2f531,432023e3,8fc1a637,fb5a92f5,9911932d,f5cd23f7,eb16ef68,c8c573fc,86e8c1a9) -,S(8add7841,86b68399,b08a0bf2,a92a3987,36fca803,3807b564,f97af438,ac70d49b,758cdffc,ef477c3a,fb3028a3,2866d860,c65aa2ef,7b3d6261,9664ace3,658add34) -,S(ec6b9f2a,a1cdedaf,306b8a5a,b021e430,e9931126,a1c505d4,a10e71ec,3cc60453,8139b262,40e2c1ca,8ec89808,2a37d7a9,b78a7e5f,6330ed32,f9786cb3,c4ddb722) -,S(22ce2541,dd8a47ae,227dfec0,95ac361b,88ae2cd2,c9547344,f551f6bb,cada196a,68ce4f4,a677a0f9,60aaf4a4,f8e83a24,ebfbf46c,6ce2a470,255d2ede,c4431581) -,S(ee7dd0d0,3e5b6d8c,ae78caaf,27b902fe,4136201c,12a49551,bf208c0b,f88bd33b,aff0eef0,609bbf68,7ce2aef,9f48f87e,67aedd82,e5342159,3809cf5c,da4ac004) -,S(f7f9a352,ca18b2f4,3aa18c00,9ae0eb31,17679db8,d9fd7e5a,41b77e85,b54140cd,afd30383,ccd2a6f7,ae76b953,5bc80330,4419d38e,73e12d1e,dc407ef2,f3b50326) -,S(7793ef5f,8e57e872,ea9fbb18,bd710ab9,6ea4f646,134d3308,930cbf62,e73f0e1c,8d5b3b79,3573090f,a4a7e7e5,c38fd987,e889bc3e,720e05b2,43e856f6,32ae7cc5) -,S(db743211,ba814bf,e6371ddf,d03ba554,b558548a,a90e81b8,e1421321,656065a8,8236f24d,965a9003,84b382e8,d772d7e9,2dee2ce6,c3cb3388,3ea627d5,4a5170c4) -,S(48c22865,6e51199f,6306a6f1,7dac1e6a,13f82d42,61de0f0a,9158ba98,715d3cf9,19a2a4dc,35d2bd03,5bc5daa2,5526598a,8eac11c3,52e5fe70,be726531,747035ef) -,S(70a28bf4,ce75b491,582b48d5,9a5069b,9dcc1e49,c41702d,ee5d688e,6e643a59,7183750e,2995f655,1b58d5e7,21a5f33b,69045934,27f27f34,f8ebf62e,74e49de2) -,S(a90d8505,596b3d01,a5e8dad0,fe652cb2,4a008a7a,61ba3cc6,8401a7a5,5c2e3132,f98af047,6e925c87,e13bb7db,f992b81b,1be564b6,8589cf2d,b79e4800,3ff7b0d9) -,S(88647576,8e960c09,6aec9832,448decac,6574491c,df737dca,dcc42b84,d7e775bb,ad94bcbb,7309f483,19077724,2582f5cf,a39ead6,a4050afd,89a49ecd,7a9090bd) -,S(c505d2cc,ef72aef5,8130f472,2ab3b2c2,3a6864ab,bcfffd5a,725a6df3,fae02112,dcb82329,cc51dc7a,54e7104,462997c,3d135d6d,5c82463f,45e875f5,8738652c) -,S(24a1d4be,c709cf8c,8b8927a8,8bcfb11,43b0d579,10e0900d,68fbb682,d4e14df9,9ccab057,8440f6a2,edaa4f41,28f427de,adce5584,692b79d,624e8724,572a043f) -,S(48c44581,51df1654,fa78370a,6975e59e,576eeb40,e94f636e,72aeb37e,8fbdc4bb,f48e8dfa,bb085834,43a7b495,ced76171,348e92b0,41b9620d,3cd5a84a,d9ee4eb4) -,S(42a7838,d33d0b15,b4409534,18024a33,e93ccad,946b50cc,a543ea1f,1bb457da,dc2f0e6,4f30e973,cdf6289d,d8f6455d,51c2da02,bc4e1d13,6668250c,e4dd791f) -,S(80988f4f,c2dfcb86,f1f65196,d93a6cfd,5c664e1b,5f8875d2,61e7c4f7,b2ea31e4,1e695c33,b526d582,6210e694,49c4673a,8697e1d4,a197c9bc,a3ecafda,2a7d5b93) -,S(a0ae003c,65d7f1c7,b65cf828,124701b3,876d0be,587c2589,9a618c4e,7b79d480,d7f4ec52,bccd57a,9515e80f,2c79be42,a6b53ca6,253ee13d,ca33c917,ff2ddf02) -,S(392f57a0,ebe08b06,cb4946ff,3c1df6c7,c5cdd97,b9cb2190,dbd4678,cdbab3bb,1be9f9db,dfca7981,b3dbbb1f,daf50e6b,c5662fa8,1b8a58f9,9953eebc,d1d0be1c) -,S(cd904f6a,3d8c4ebf,6ebc4e5a,e536c544,4a04e278,389d771f,d5e7566a,fc592d3d,e3e10f61,a15399c5,f3f29626,af323cd4,3d6572fa,bad4f02d,cf76c0f4,9785919f) -,S(27a4480c,df5782bf,52ddb140,ea5a908b,38dc1ec6,a570580d,2b72b922,e7eb05d9,bd96ddd8,1a6aca1f,88847632,5a6d48c8,4d61e76e,b4d0d957,15d39f80,faa42f3f) -,S(6673ae66,3511292f,fa4dd8cd,bc0f7b36,613c56d2,775602ff,a8cf9302,4329f5a5,d8b4ffd8,8ca2530b,18d85762,529d056,e8048cdc,51730082,2d24cf42,e4053141) -,S(3dbae13,5c395043,d5b88161,4dde355d,5a669076,98c36b23,ac4c24bf,80e34f2a,b7d46059,3154fad7,eaa37c3a,291c6c67,16df2944,4274b044,a9f12ac0,a34139db) -,S(f2db4c09,1c3c606c,9784f6af,7dbfb26c,2b18bae3,b22f13bf,4188d761,6cbc1371,8c84e295,f57a9722,260d5816,c5d57719,c6fe2a12,3ba20a48,189bee04,ac252f32) -,S(918e415d,92e768e9,f5a875a8,aafa7dd6,66109cd5,8fb6044d,d2c8640b,f6b966a7,b53400ce,9ee9f6c6,9cc35b5a,3e04eec3,dc89c931,e545068e,ed4a818e,42073e71) -,S(5eda3e22,bbb8c368,82d46c19,2068b3e9,a65624ae,31feba8b,df725d5e,47bc3437,1cc2c541,ce3ad8fb,ac3cfabd,a492c03,87099e1,659cbf88,bc8f27aa,f9a2fe26) -,S(7df83e06,9cf09a92,5405e0d4,3cf0c7bf,52a8e603,d286e26f,f273e218,b455e61c,9eba2975,7f61b054,29c9e915,a092a591,ac1d6044,8a63a8f1,313f4018,1650f4bd) -,S(b778c25,d78b0bc4,68dcdc80,5de93809,1c3c36c5,b5f9569,a9394b5d,c7afb162,901a4ecf,b4821145,c7d9e56b,75e43ab9,cb7ef8fb,1d384a4e,27033e9f,90b80fc) -,S(dd4965e,f6fb759,104f7877,307e2a6a,f837ab6,8c19aa40,6fbea75e,e8a7adc3,45e92312,b5c77585,3c4b95ca,6b4c1740,a70b57c9,97124883,2c53d291,4b0fd4d8) -,S(ac971379,7dffd8d8,2e33f927,48ca063f,f1c8ccf2,5b88fb6,bf80946f,1dc9dede,6ce10e3b,ee4db87d,40e8de66,fb5263db,2a578d6d,be100fef,d6e28bd6,7377bc26) -,S(6046fab5,37fb413b,29797312,5a6049b5,5c085194,4b058264,c39926ed,fe85c6,dcdf9ed1,cbe469ca,2976333,5a159e42,af6f0d32,664ffb5e,173986d3,a277180d) -,S(a0d94b05,8e3b4d30,7f3b3f09,ba5ba28,d0285a3a,22cd577a,1d949b8,bd23f1ae,37fcdfb2,e3027e07,ea77f28,447ea13,93971c67,974304b5,dbb7621,2ad2db10) -,S(da15b971,1b974ef9,14433ca5,71175233,693cab3a,dfd5f6e8,cf034254,6f73dcd,e08c7f62,90f87fc5,4e2f4ec5,a5a93d19,f4484868,3b5ae9d3,810b0615,c7e79402) -,S(b26ba5d2,72a744f5,562cd745,a3f3f143,32980458,60be4e97,d737fbb9,b3b0d544,3d308307,9830f281,14de6c5a,f3876446,507558e2,95353dcb,738deabd,80c0ff20) -,S(fa26c55b,bac04fff,ccee0610,ba9b60a2,4042aa08,7a564ffa,b891e087,7a2185f5,5b5a62eb,1ff579b9,ee4c5d6e,ceeb57ec,e9881b47,dbfc24f4,3b9a18d1,4addf4ab) -,S(5ada4a59,4802163d,4da685d9,b7479f,4b70b489,5ddac7a3,b06a1c4e,a5f46dbe,2ec25e70,871b4958,81f6b0e5,cf821b91,febe83db,a52fe2f8,1a2e4e82,165c7e3f) -,S(a57751d8,895282ac,bef2384b,db4817a3,539899b1,e7fe7a62,2596ad18,5dcf878f,651eee9c,12ecaf92,9eccf109,635680a,a7499537,f2054e2f,69b0f062,c820784) -,S(3f17f0f2,6a540098,d18f8d88,ad323e9e,e300b029,b7b8101f,6aac6ece,8d375f3c,9c0713,79e35319,7f1e76d,55616e5f,8e573a54,b6bfa56e,5dacd2aa,e2e0deeb) -,S(eabdf476,d2e9d76d,775388c,da759930,4e1ebd59,b3a7e491,e3c9c62a,4d0968ba,f4bfd5b5,e0e8ab41,a04c4cd7,763b243f,b82f56ae,9f08a6ef,bc365f3d,fa227c4a) -,S(c5b76ae8,dabb664d,fc1fd499,36399e3f,c2b7366e,a21cba10,dc7eec7c,5c93e0d3,ef30249,19bc03a,c24c8544,9467728a,c160edc5,7c901e64,b947f298,9bb1242) -,S(7161dbf8,6b1080bd,bd6aa47e,dcdf8a77,17b7e281,c692e9d8,739caf9a,f3f23d6,3c30b786,b095288a,4522749a,3d32a35,5a8bc694,cc9cf7ea,989675e9,a1688e8c) -,S(ed6a7b49,9b74e62e,53183b15,6867d41,3ce902a8,4b71fdc4,fa414f8f,249c2ce,793d0356,1bca65c6,be127ce5,a1034b9,86285fe1,f52075e8,1a9b5bcf,87348c4f) -,S(fe6e1abc,3ee3be4e,22456f4c,bf93810f,282f0fec,96ab5cc8,2b35b08,54492bad,96c76282,3adc2cea,1563c02b,fdb25b55,eb15e769,90a7ed7a,3fb8aabe,47bb077c) -,S(979e7ab1,96e66818,b67bf79,31232826,713648bb,ad956add,ed594cdf,8aec2937,696a9505,e3c473a7,2df68f96,13c2e494,406782a4,f92a8fd6,5017a83e,d7912491) -,S(9f947cb3,f859f2af,11a63400,800c18de,b8813c1a,b396ebd6,a1d5bf4a,9689160a,8efeced6,7f1e6fdc,191ac965,5002a02c,386a20b3,eb2aa1be,7fc12008,b8bead1) -,S(71790030,58caecb5,dcd2e281,b42eb59e,57de1e6e,b77f6bad,7d2d1897,6a512eb4,abff54d0,e20347bb,c10a79c4,127f5f7d,868176a7,4e34077a,8ede1d54,7e339483) -,S(d786ec15,c140af46,841b7eb7,de5fc9a3,c0636885,3950bab9,ffdbad01,d836b8b0,fc90191b,63616a44,72efb2ac,a7d84da3,4892af1e,25bca0e2,d41268c8,d381d062) -,S(2d553f03,31eb83ca,edf2508e,67054734,d929367b,ffdd5b7c,dd78dc6a,2e724534,9abcef4e,ee588e28,fa1dee0a,b8c426c1,67d37cde,f8aae9e4,248c036b,baa1af70) -,S(326b36b,eab4d932,c40182f0,fde043ff,d6b84b16,72fe1dc7,3bc7e518,6ef68062,9d86868e,2e871ce5,c3488624,bec901d1,47b91bf9,a3154cab,6445870e,d51e8f1d) -,S(f7a6a26f,4e3583bb,9552556a,5d248735,7ea4af7d,ad1f7a92,717d19ab,34dfa11,7ace27e1,dab2dea9,704c01ce,50ea3de,529d864d,9a5fc11f,fbc0e8c7,81778b2b) -,S(8ca708ea,c072334,42eae4e9,eb0c7b45,83e153ba,84ed7a0d,3ece41f9,4df6cd15,33f41d25,e446c47b,68ce1bc7,d1dd1740,fc701538,3ac90e05,1dc89a9f,dc97592b) -,S(4fca2ed9,e1948697,208a87f9,a890cc96,4aa9e5e5,7c7274b1,deea92bb,586875da,98a9303,4df7185a,df9f557b,b7def9a6,41e7ad5,a3f24051,435673ff,12f0580) -,S(466da0aa,97c68c05,21b8fda0,fc70d74,bb586eb3,da7eab4b,6c104404,d9234d37,5834296,f94f5b54,beddc0e,3d7f6004,659952b7,90a6341a,de99ff26,5530e5e6) -,S(ae22ae10,d016b54c,c0b5423b,3f4c332e,3180ff23,c279078b,864e8e07,77e26a5e,ee21d64b,d6043d56,de3346dc,f93e2c40,b9a51498,b4d7df61,d476d339,7a2d0c8d) -,S(58cd60cc,ea7e0896,2f65a353,5d45ad06,517fea5,575c5511,277103d9,fabb5167,175a68a9,850b4026,bc7b5684,e859c808,edb5f3,7acebc47,9ba489d5,5aa9774b) -,S(4be8a0cf,7ce26101,49cd90a8,68f4049c,43054aa5,68bfb2a1,a5bfa386,9b2b485,a3bab0f3,e3bec469,f779404b,d025ca14,79e3f6ca,9d496f8f,8ce4aa6f,b7e3b404) -,S(428599d9,398a2c59,58c5f74f,1226605f,3c5c8e74,ad8f9bc2,d62b8d9f,d679d3c3,12a1b04f,add5d70,bdc5e15e,d6347f7f,6785c425,61f14ae6,275cf050,3a1bd5a7) -,S(134ba4d9,c35a6601,7e9d525a,879700a9,fb9209a3,f43a651f,daf71f3a,85a77d3,21c112f7,6a9b9b21,e2e3a7c2,8cf500bf,f48aaf1c,48e0e13e,f15618b9,ca62287d) -,S(d53cf8f3,cc5e5739,bc9f9144,a44e7b7b,bb8f2c36,b50844ca,9b2d9cf0,cd0616d2,799c23b6,c57aac44,90d71450,4388cfa4,689393ab,6f30a347,4503400e,c568e03f) -,S(a1e22cfd,e8d12f17,eea1eca4,ea0b520b,6598c036,d1bf837c,e23bc300,a384e5a7,cfbb52a6,e1fb6a65,77cd0377,8bc965b2,a3df592f,f73c34d2,a91b8008,74ecc295) -,S(72bf047f,a0da1391,78b97ea,7b317168,ed0576fd,71f49409,39a8daa5,2a02ead8,f8d93088,cb3457e,7828ba9c,bd8492e4,9eb2bf0e,2e23bfb0,4591e9bb,5273f462) -,S(c5373038,4b951abb,3bcd1f4f,98d983bd,cb5b36a,42719531,c4d1797,2e9bce59,d921f353,a9f7309,6dc16028,f9e1b562,f406bf49,54d78bf9,f2b4c8b9,2db26a82) -,S(ab20d194,e2a6c4a1,5705d3d,19300810,89342b15,e9fc6224,7be58805,a8682a5e,44dc39d1,8342502d,cafafe40,33c4893a,2dddddd8,ad7b238a,efca50cb,5d5b3186) -,S(1432ddfb,108ee664,2eaa9c97,585f47b7,b92a5ae5,39a38093,b8f3153c,e971c8f9,5362084b,5482e375,1662aa95,dd3b9a6e,65235aca,b0ce1eae,f5153951,1391e269) -,S(f199ede,4a69d778,61e107c9,376bdee5,6430e279,28c74d75,66e65589,be8c433c,5e7f6fb7,1b68a535,f407a9ee,2e42f65e,9835bcc7,2c34b8e7,712e5332,a65e9ac6) -,S(b24dbf51,47452b5b,ad94bf4b,493120ab,61ce2ea4,37b3ad71,62e568a,1d595d1a,b3af5a90,8d063602,6b3869d0,c9f31793,61afd6c3,8db99cb9,77b14e0c,46427518) -,S(d7fc29eb,b681e025,992d9ef7,295db58b,40f36c64,d1be10e8,c8e66858,d4d0d9aa,c587764,ca84b3c7,2f95eba,eb62494f,ce391202,90c42b9,e8b2105d,ed972595) -,S(5c71e90,d5f00ee6,e033f0c9,c1ac495b,d148a31d,143a8e3,59a99c7d,faa3cc9c,4acc164,ea3071b7,a4830a27,24135c49,562ea631,9dc4455f,808f1282,4e3bbbb3) -,S(4c9904a9,a33f7e33,9a3d85ac,c12b21ad,11f7d7f2,76e46620,76878593,9d11eaad,2387a445,b0967403,86ce4634,62dd101f,95650365,ac02ef1d,2417321a,3fac1df9) -,S(58f457ec,12d22482,2a91b78e,26f7d8f8,5fa39d90,59fb833c,bce4b1f2,5c9720f7,90808a70,79d4970c,b2b70ae,390844a,2f0283ee,eae05a5c,7d2dcdde,be656f2d) -,S(9867259c,51414805,3be6a73c,de522d91,a8d8b359,9f9bd39b,9c9575a3,90405bdd,9904fa47,34973bc1,77a3d0dd,f0edc0bd,cbd77b36,357734c0,a0feff89,4895f3b4) -,S(663b4991,913148b6,631d16fc,27471938,20a7ace4,ee85c335,17b60cca,b5e12b5b,1b295a18,16b92c5f,15b88bbc,177dc011,f6ef0760,15b5ea47,9bca876,ae072070) -,S(5e3ff13f,bed18235,fe28dcc0,72f09cfd,41394cd,a9a3aa52,5286cddc,e56acf05,c1488c2c,903bff6a,411697f4,44e6e72,6ed9c0bc,5aa87cbc,ed8f8802,6998fc7f) -,S(54c8aa07,2f1fc5a6,ade56cef,d7c6aae4,846f6855,34912868,b84b195f,78bbe14b,ef11dea9,5cb01680,e7205f1c,62aa5242,2c0db969,9b2a0202,966873f3,1fdff34c) -,S(bc69e00d,4118d8af,baef7647,6e435883,2ae9864b,f154368c,e2ccdadd,c58cfd9c,148aea9b,2babfe00,3a6592f4,d3788893,5be42ac8,a50f68d7,ba2cd738,47dd9c52) -,S(50ccf184,c0213602,af114924,fe100f78,1f0d0cc5,beafb671,9dedea00,c7c3ebe2,b6559878,d7c33082,4588dd33,3054c4d,2da86b8,ff23fa9d,6413920c,d876e36b) -,S(c24ca0a4,8ff2cbb6,235ef33b,42ba032,386d5475,3cdda799,e9bc53c0,5c299aee,8555bb16,bf4d7bb7,5c0cbdc8,8594454,bfc819de,72c3954e,76b65780,2be28fe4) -,S(cebc8853,3f6c3a01,58dfab12,ef52b4e0,a7473d1d,209b3585,bc94a13f,a83abf17,42fe28d4,136bf80a,7149a0b,7ddce53c,45e23c0e,7be85fcb,73c0e66,2c4c0593) -,S(7d921a84,65b11feb,7a755a4c,5d96b6b2,f17e07a,95db112d,48c03bd,18f61422,f0ccffdf,7f04e350,13ae7f36,411dea5a,ef69f220,790c37d7,354ce5e,83925f4) -,S(b6909fe5,6824e868,f4cbdd10,d3d00ca,23e5b4,35c78aac,c78a9a1e,321d178c,3d513c55,136d61b0,73dec253,e1ed817,782d9f76,b536d3f7,c3b0d1f,d06e6c1) -,S(5a3df3e8,c78c0fc,56971dea,ced3a6ea,e1ef668e,2485bcb3,d4e24408,7f53cb74,960721cf,316278bb,56bcdd1d,9f3385fe,8feea6b0,661bdf1d,44771067,661aaacf) -,S(dc65c06,50cc30e4,d759fa93,d4d0ab65,5cb16591,289206d8,7a988290,20c22f9e,be39ae0e,a41a81d0,2175dfd5,5e004e19,fa925a99,2166d862,296899e,2532b6a6) -,S(f659d02f,f2d4bc82,9f816525,24019a88,6ad539da,3f38b083,5d8265cc,bf3a67ed,bc9c7a81,9036c702,338c57ef,26134647,2a22b8cc,5543f4b4,4a4f7d4d,d4339573) -,S(b89bbc05,420a8a65,aa03441e,da1c54da,9ca84f11,e85a393d,47cc54b9,78b8e5c0,5f3a2fba,4cef4457,ca6befe2,7dd3f9af,a5d8b6de,86679eb4,c877c7b4,cf03c08f) -,S(b9bbb789,690b53e6,e42266bb,853cfbbb,f6788b58,b325097,a55470e3,d4cbc3cb,1f984f38,78427212,cbfc8a93,8c1f0d87,59792ca7,17635c75,71b2c4f1,29e35c2e) -,S(d8ae91cf,8a99ef6d,2ca0c15e,3132974,33cd46cc,55a2c8f3,9f909e96,7d50006c,4fe4696a,79d2f269,9fecfce8,8375cc1,81c2c2e5,4109f380,3377a020,5496d733) -,S(35dc2c70,181aea7b,ccf6a15d,1f708c87,cc8bc5af,93671c97,35867367,549357bf,6f27dad,a9abbe5e,5e59141b,78a2e6dc,5b5433ef,dc8c9cde,a6269c2a,68346f87) -,S(a4c042b7,d54b67b5,877442e7,2e81de4a,7edbe667,f00838f2,34f567a7,9e3791af,a8c6f7b1,6b23a9cb,64732852,c9734547,69ef3e4b,9165ebf0,a1dc4967,36c73242) -,S(d6ab68a3,353b6c65,3836b66a,8c39f2d0,892cf856,90ebb56,a5e8e4c9,e669da34,4847a9d5,f39ea1e0,ce392c8f,9e63e88f,8f3feb9d,7b2a05c7,23a932d4,b07e38e4) -,S(e161c34e,644eb3f4,fa217d33,dd3129b9,c2b85ad6,40b56e56,e20982d1,c5483d43,ceafd0af,a8cf7a25,be092307,22c30e41,b6ea151c,d027326e,5152aba8,d9a50749) -,S(94959a2,fdc2650c,b4b0219b,83ac99c7,c477132,eeab585c,1fb262e7,6cca22f,6243f3b6,ba7d4f26,24f7b7d5,8e070b2d,64610aad,b281b4a3,b93b030c,ac0cdab9) -,S(491129ee,3130c2,f262c4d0,a1bfede9,e470c3cc,8e80774f,52ea023,67e2e3de,c1e61e2,a5310866,762a0cf0,ebbae0f,738b9527,46001aed,a991e0ee,d95f0db5) -,S(e2967539,b0b29fee,a668eebe,eb8e47c0,1ed84950,a1f9fda8,6884a421,5ab6f265,c304cf3b,b7faabe8,cfeab6b1,b88d3d41,7e950963,745c2479,85211d50,888346dd) -,S(d90a380f,5283132e,7d6760ca,f2b28576,49445507,b8e8872b,d0e1d5f,56a15af5,97fa0739,7a1357c5,e24d0a3e,ce608332,107e41f7,c65d3c6b,98ed66c3,af30a4ed) -,S(cb917a08,153599e3,e531b1ac,63fb8e71,fcce572a,29fde1b,17de843,a99ea2b5,701c08a4,a9da11c9,3b4be64a,6832af1c,900ad3c1,4b4dbe70,c62e3e08,55b41b6d) -,S(e6ee53e2,98efb026,bce900e7,8d31f3c4,539108bf,d4c5139,16417f8b,49199a0a,bedd41e4,751f657e,8cfc65c3,2a82f981,4b223e62,95ec36cd,da5125eb,da736429) -,S(5f777c41,f4e3441e,75c66f28,852e7815,59d0f3fe,b8b05b59,b6966fa0,de84df2a,7fcc66b8,127d26d8,e0ff69cb,b80acf44,bae5546,edc9bc52,90b73da3,447a2731) -,S(16d312a8,1295ab9d,c08f9fbd,61e6445b,5ef1dc51,fce19d,89f04e7c,66ba2e07,6c555fca,2a1d2f4a,24ced2bb,c3966f4e,1bfc1912,eca39067,503df586,41a4d4b7) -,S(660d3993,fa887e1e,8b05d80b,96e2b70c,341c3ba3,351d2562,5792acaf,3859de3e,87b06f5d,4c6f854a,8714eb3a,55454346,f931c21c,c77da23c,2d069d33,7dcf12c) -,S(9d45e660,879b6e8,b8007a8,ba7fe7f0,c7090cf6,9c733bf9,43f4eef9,965a1ae2,c81a3fd3,9b6b83ba,d163c763,f3010359,ac050e64,a47167ae,2ca41345,c7d95662) -,S(c95d92f8,c81d15fa,a68f645a,c1ebebd8,57c6942e,e75ba13a,3a4eb9b0,c45c43ba,2f55ceb6,c1de7877,7b322a91,7f3e48d9,480b80f,d49e362c,99f8104b,a20f392d) -,S(95d445ff,e8cf8240,fc4e9856,9d41164f,50e9ebcc,1fd3bf19,d4309de3,34b4c97d,7c391704,a75cffe2,f8971ddb,417e8158,f97a3688,6841f02a,c4b699b8,df6c0d32) -,S(40f028ca,907d6521,df1f052f,ba5268f9,a60e705,bdf94328,17881b44,1500170d,4eae26bf,37d04379,126ce777,b1fe1115,8c34d077,bba66994,78ede7e,244cc8c6) -,S(dab90c34,e7460068,d80d2be2,2bd81f9e,667bbd96,4e30c23d,3eaa7a75,a61e862d,cafa2892,5128bf3a,4821cd14,8503ca8a,86f06388,d21df6ee,af92d514,e66c5f1b) -,S(6df2280e,381ef8cf,922505d6,7646c1af,105f91c0,59e8e7a5,3ae2e7e6,cb456be,d94a020e,7776b713,b31aff5f,d72be6c,f29bfe46,16ea3d29,95913db4,698ae3ca) -,S(a13d83d1,3c60cf65,cefc8692,f5d339b,2873582e,938373cf,3e4df54e,ae32ffd2,8f511212,a65d8963,d7df7ed6,27d87fd9,208f83a,1a4dd14f,ab0593d6,38ac71d0) -,S(ad4c1ec8,39950ae4,a7fa551e,5aa637a2,e5d40bfb,3fab696f,ea886a4f,40bf2167,fea9b599,202841d0,c3afbf08,ef1da210,cdd92a4e,6cad485c,a0d5275e,8a5dacfb) -,S(64188be9,af657254,1314e661,848970f6,35a0b6be,7e594824,6dcf36d8,66840610,58880b5f,c3df9b6a,45b49ee6,b90f6b5f,f3fc440c,37855167,a30ac013,3d48e53) -,S(9b71366d,a66b165c,6495e4fb,46ecdc15,84a193ca,d65ad8b3,7a01a3b2,cf2e43f6,d7315165,ecec296c,4b71a860,f3b2f0dd,fb9447ed,5c59a458,8b81f679,34321301) -,S(4a3c5006,74814f95,9e9c7726,595658ff,84e369af,636f6aff,ab579bb8,5583d395,1b495757,1a302c2a,d1cbe53c,2ba34a6d,66bf1aa1,8bddad33,679e4890,5f9a21e9) -,S(e4305e5f,72c43558,79a749b3,d563d4d1,dca704c9,c8867d01,ef503cf8,97c90034,ee563dca,4d31945f,c536a318,e9297d28,81954b37,af992722,9e4e0e9,1c16244d) -,S(3aea4eb8,ee74c9d5,2259f37a,da33ae1c,78f5dd8,d97511b0,2e0a0201,82840a8a,8fc58135,757b8c0a,a8f2c2ab,ec9d9152,20ad2046,f429667c,c4586765,10e93e87) -,S(58e8e94d,e9f85066,7cc4c61d,acd212f4,77454942,33deb015,858e500e,9530228d,5a95aa24,fb782a4a,e64e155e,eac2b644,cd614315,9b46db6c,9bb4fe4d,5e5fd690) -,S(6642c782,7e1df912,ff54dbf7,41fa1567,3e9c3aae,5e7630c6,9cb74b60,c070af1c,ff338a86,34a404c0,cb26af9f,59df36a9,e1a848e1,ac178b25,c37ac177,db45e947) -,S(c5c69fa4,65c79a50,a98996ee,cae55474,5c544a3,ea838a42,e12a733e,9181b30a,6e805461,5a424a9a,1fc229b8,7e594211,697386ef,189d1ad6,ac75eaa2,5727253b) -,S(f4faf099,fb16a1e0,e5f64428,5317d91,a31daeed,fbb6a6ec,b70a213f,ee95217d,ebfd8445,42fee872,1f721f3,11ef28e,30618bd1,bdd097c1,ca573285,5b079734) -,S(773b3e69,fda8abed,fa61ef37,57101756,9d9d2a6a,ebb4fc5d,d9049d56,9c66b76d,1bc051c6,302a383c,dc0756b5,114dfc69,1dd2180a,88a4ea9b,6acebccb,a59f27ca) -,S(bcf80e7,b2b54cf7,971fae7b,db8b3826,85acc1b0,f987f352,d9b0b3c7,ac78142a,20620b00,8c010ad9,7a98f093,8d9a381,f9935d5d,4bc9b060,af2ee6ab,151eedce) -,S(865dff30,47f31564,99337316,ea20223c,5967e034,83d92d54,7486fddb,fda959d2,2b655c9e,37697f10,5535b736,a31b2c6,7f5726eb,602f1438,f808ff62,4bac074f) -,S(e48e0e18,101eef40,f351067e,63d2b34f,4fce76c,d204d6f8,85d2664d,fbc92d3c,594061c,8d3f4748,bff85cdb,f70a4035,5ad826f3,46d44aa6,7eca3196,e433bb65) -,S(9807e350,7a03e134,9bca9101,cacca5d1,a564b647,8c906619,61ba503c,5ee15bdb,301e68f2,d584b1fe,3eeee7c5,85cb4d0a,26621bda,229589cc,2704dfa1,1cb8d927) -,S(95f94e75,8602dcd4,60ded52a,c9d7ab40,1fdf1405,b271acb4,133a86be,cfe5027,f08d34eb,e9cf1b1e,78e1fbec,452e1ab0,412c642e,1328b2dc,f5e08b08,38aa3c51) -,S(7ffa20eb,ebbad406,deec68c6,9bdb7b0c,7615a56f,5c62a646,a57535e1,68a82a31,230241b2,3dde374f,7a039eb5,5181e954,f0472056,79edc688,7c4ca6b8,778333e4) -,S(1dc7e0b1,487fbb33,d1ecdf84,7bdbfef5,f7df9f31,d07ff024,be063a51,53eb5498,ebcf72da,18a1a55a,5aec4aa8,efe09407,263a7b36,f09552e,22cbceba,7a3cf980) -,S(a8052e02,e39d9981,2ac6c4e6,2cef526b,9cb29843,127f2227,50a8021f,4ced5cd8,9011f0b4,9dad7e5c,11222b64,c5d8c9fb,297d9afd,c683f545,849d833d,f2697220) -,S(3edfc4d7,f1f699c2,8e8ac2e7,5cd93e69,fff31607,d99a8195,30603437,f9bfb20d,f901260d,68c6dfe8,aef8879f,ea1ba009,a1e1d931,fa6ba39a,ce1e2673,ba759311) -,S(fdf8ae7d,c10d01f1,c39bee75,3be3307b,53307caa,4af0e8dd,9de7d696,45ce527d,2425a3f8,c6147073,3a44d3eb,eff3d8cd,61e5fd55,ffdac357,d7906600,153a8dd6) -,S(1cd5ba80,fcfc77c3,d06e230e,e7ad8ff4,f9ee6c60,a71d37b8,3718d8b3,15d5a4e0,f90ac118,30b963ab,fc64492b,415db7e3,47eba55e,d2c5a64f,578a13ea,b4435cbd) -,S(3cdb43ea,b7afc936,24b80269,18319fa0,e75de21a,c0587af3,541e492f,1510257b,49b6411a,c74a2eb3,ac2ec784,feface51,8d5a5bd6,e76d694,bf5ab8f5,c146abfe) -,S(165b6f5b,9b1e6d08,14e44cc7,c7969297,bba7c659,58dc3274,7e7c4148,e30c09da,e715e411,2e6cb67d,cb8e1ad,997691f3,bd6119c1,3a5f0329,1ea3928e,35c04551) -,S(d4c1190d,da3c01cf,6c75fa06,7b4dd1ee,e645a0cc,8b034f4b,24580661,8ced0bff,c837ed81,b6a0e5fc,6a02d6d5,f837db1a,20eee55b,41ff531b,9bb642d0,52c42bfa) -,S(f7359bd0,bf7db6b0,48f1a040,a0163fba,285780e7,909ab689,7963168a,a7de9c29,8c71bc3e,95ac0f52,54db6192,5c6f9112,759635fa,95846be4,6a28573e,2b25562b) -,S(4d54a2f6,dbebbee3,8950627e,8cf2c65,6ca071e7,86687f3b,a0a77178,be14c55d,6579dace,73dd14c,695fd781,218786ee,bad84445,ccd910d3,43aa2478,f5576671) -,S(f70b532c,e7203208,d6440bf8,55e1293f,cc6ebd75,96a04b27,9fc056e1,2ee32dee,e9d18f7,126ed56b,4a657104,2441bc08,1778736b,91062c9f,cac28cbf,b8737be1) -,S(bbf3ff3e,577aaf34,157e32db,d977b907,e62b16b5,1ae0abd4,f14e71fc,cca11357,cc1a78ff,44af7c2c,cdf17423,9b3aec17,b660ff2e,fc07953,2d9f9d6e,55d3abf7) -,S(53bb2321,b36d1dad,226ceb24,f55d4292,be245444,b2349611,5a649560,59729700,a5db4fb9,46c4a2db,b1a634cc,4032b7b,cf23f7d1,717a0ee9,6c02f131,24f834b6) -,S(3b863ec5,5e4ff2cd,d32cbc81,6e645009,da444255,9bf96267,2cd012e1,15372186,914682bd,d6a052bc,25cb4d41,e9bb28ed,76e9aa55,3f5aaf25,75140e04,eca69fbd) -,S(4cc4a750,d641c574,5c68a48b,953ee51a,258239b2,fda1f5e0,80831417,7b837946,cd6f665f,6f32246a,1cc8fa61,4da2783c,f4c7b92c,4f42749e,b6bd4a8d,8a84c54c) -,S(6f9b5d79,efddf08d,26183b4c,d6001d6b,fdad9e8b,dc5853,f3a8c47e,7e6f9e96,b81148f2,1e50152a,8cd7727c,ad14862a,37fd186e,2054d4c4,a4cdbfba,a9076991) -,S(9e13d0e0,44cd3fc1,1c7596f2,9946313c,918caa65,bcb6387d,361eec31,ebaa6977,c5f55650,7691bc2a,b2c9e4b8,512f7282,24276490,257288c5,2387fee5,54bc9c0d) -,S(a4441292,d0e0db3,2a4f33c4,8bbc5fbf,d40650c8,d9f5c4f4,88a1f69a,d71571bb,a23ef48d,38abc24c,608dd688,d524bed,a3709a5b,3567ef3b,e43f0240,796b7ad2) -,S(def598a5,c4828c5,16b7076b,9682aa82,4e74ab42,e4d4692d,17c8f289,67f3cbb4,e6b4bf28,6dba0803,e4a97a1e,be55a088,10660466,3d7726e9,300109ee,a1d62a49) -,S(8e991fb7,372df8d7,7b09436d,c9424a8,5a14888b,583b3c58,6d2a19e6,91e75b67,1780f6e9,b8379b0f,ebb1328a,69a96878,9f58b45d,8e3ff218,81d753f4,8ed6c43d) -,S(bae09288,e10351fe,fa0b0971,400ac3d1,a7eed65a,b11d1ba4,8a1c6240,bb981114,dfc2979e,dcc2de8c,abd9abd2,27cf7351,4079d950,aba60e3b,f4c775ac,72c30f4f) -,S(4d09ae3c,b484fe27,411d4142,e41de523,2c54c42,b387c7c2,cf42a23e,e7611fc1,b94fa116,27eaf5ab,8fb7fc25,1345eb28,8f5249e5,ec65e056,d60e1294,41481375) -,S(32f57ac4,3cb29fb,f8a00d8b,c95da8e8,3f0f541d,ed6c9e78,8af17a14,6a2704bd,2a969b58,9a3f9a5c,26b51ab6,1a5717bf,c06eb438,85e4f4a,84b903b2,da5bbf09) -,S(595503ae,e179f59e,bfc581b8,7ac18e1d,55b4c794,87d90d62,492d3ea1,1ec57579,1f25d8ba,e38c0a69,50a17836,a842b418,b0f7c317,9486fb16,9ba11b23,d315ada0) -,S(5555fae0,6f1563af,238184c9,304e26ef,f8b2121,394e6856,79de6792,31a56842,6840bd14,faf202c6,60650541,48bb87,df27b979,4ec0da66,9ded6830,b0623980) -,S(714321ed,2f0432f8,a05c33d1,84619de5,f81fb8db,95ab3121,c24fc998,ab9b9ca4,4470cdaa,7067de2a,e6678cd0,6d613e19,35b1edf3,bf278205,da69ee8d,6086c2a7) -,S(d41b84d5,9a0085b,86e88fc1,499151da,b0b9a574,92b01df6,36cc2288,313bb592,c04c54d2,57fe5ba,691f6023,bd72edaa,20e71a97,1a760bf5,3c990a39,f5ef7c23) -,S(ae34a065,b42f5158,e6a5b91b,9ff54b0e,6d5bc906,f6d18c3a,82865e,e9038f34,bf2c90fa,30639811,2ca2ed02,b7ad090d,8bc990db,b6140a05,afcdc80c,bae8490f) -,S(9b3c2682,3050a52,a164ab,f4504ca4,7750c889,b6465f95,658ba7b1,c279139f,ee36938d,8a675824,51ca289a,55265606,cb9ae4fc,8cd274aa,41db5ea9,9a5b4299) -,S(27dc9a57,999ed109,c3dff978,58d44ab2,73987af7,b617e9c,766331d5,c06e0dfe,4e97536e,67e363c8,add07030,d59061,33a726de,38dec51,e5a20009,61ee0fe1) -,S(c3415e9f,9c823521,bad3090f,f2c48e8c,647e438d,70397e5f,7d7a6f2,b7d7d4b4,8c3bb607,c746147c,d5efbef,7e27d236,c4063116,89794cc0,40c235b4,6af412d4) -,S(f47e44dc,90c8bd2f,150d9dd3,e4922395,14990fa1,f2fc361b,a24f853a,b37e33a0,f4282a26,bf5f358f,2dac4956,8bcc15a0,d7eddeee,b43e6fd1,8f35d5e5,4295ddb4) -,S(3cfa945e,6044ec2a,da895f9,9dc24575,deee57e,df8b1a10,a2d2ece1,9951a812,d0ab59a7,46ac6edc,69307a0d,caa00aa9,e7b73897,b89185fa,9dc3899,ae7e3664) -,S(29df8149,9d83bd0f,8fe61eb8,8f0abe0,96a75e5a,2cb0a0a9,76d8d27b,6533a4ed,7eefc80b,63f927c2,e905a56,62d5ed34,e9bde8ff,4402491f,19215c9d,494e62d4) -,S(eea85a80,566d13bd,da65f553,b2077607,c8b9184,6a5a8096,f57afe93,ada9fff4,b5389645,fd772da0,1cf3b535,6ec40279,cf76d812,11f20a16,71d7ecfc,441d71bb) -,S(e1a69e64,4434db7a,54550d44,adc43682,c128c560,3907615b,9282cf1e,e2b74f82,bd434a85,984a6e64,441134e6,d1f1a3a3,adeab658,c29af8b5,4bc42667,634d20ee) -,S(2d99f69f,a7e9f3f6,6a53eea4,381a4c80,ed17e8e1,4507d7f,4a80ef25,293c5fba,25a6aff9,a23a406e,9e34ad6a,21627acc,96b6ceb0,7896382c,833b8fe4,8e603e0a) -,S(d2482127,1554a14a,7283dc8,1ca70179,42a35cfa,c8659b2b,db78c426,51807cb8,a252027f,3fac319f,c767652e,469421b8,d34decd9,c9042d58,f8aa0ab,70e5ceac) -,S(bd030cbc,5f0de61,ef194eac,38f7443c,d231f75a,a0b568c5,416c5b8b,917545d,ad0833b1,4f1e23a,76c0626e,71129455,60fe62d7,4b3a1b95,69e4887e,c0661e78) -,S(afb44b49,ef00b1e9,59c7a864,19d2a4db,71d9bb0c,4e1746,9550d39c,9a37a161,eee390a9,530a5baa,5350019a,f756185,8038c2ee,7f78c365,dd6f62f0,f0589aa5) -,S(9e584f1b,e06ea4d6,5f8dd96f,206cf4b,88aec6b9,ccf06779,53acf110,99e2165c,6994ce27,46b0eab3,d8608ef9,33b61339,d3e589b,c2acb7bd,aba3af72,b082fd24) -,S(d2265b51,b4f7f4ce,1d0966,e7012f9,76433dfe,444b2351,9505b29c,d520c6df,44414498,df439478,328b330b,6f8c6876,682b6a32,b5d01355,2494286e,a635bf65) -,S(fcd56867,58c797c8,3aa1f1d8,a9ba34a8,8e624aeb,666507fe,706b310f,3342264b,680e0b98,455f0e64,94622fa9,e36f76d4,863a9fdb,a3df93af,c688c45d,fdc5967b) -,S(bb9a0c0c,74db0525,370e8235,9d733aa3,494afc03,fb61a1b,7c2536ed,9903fd91,239929a2,1c0ed586,b9bc8f03,af422994,f81619c6,b2fe637f,a511c07c,d9421603) -,S(2358b078,1989d6b5,666d9158,2fc640b1,13d52e61,ea2147cf,a0a103e1,5ae80db0,73f84f47,a78fe2c6,e4d01d7e,3dc10065,e052401f,64796358,c784d59f,742cc8f5) -,S(ddb3409,ce3184a6,d9d7b4c2,cbdf32ef,ebea1be3,595ba19c,42933882,237dae94,59215423,3760cdf0,513442bd,2fbef84b,9c8c0fb1,ef16fa31,783d4dcc,50f24f24) -,S(f99aaa8d,8d42ce59,86ee8ffe,d4dc8a48,81810a6f,cdfa9519,46f00857,4ab1c3c7,d0f29fd1,32bd65d,7f9820b6,830a3e42,8664f9e3,9cb25729,1adc36db,4e177187) -,S(83042093,46ced0d5,a33f491a,c98aae7d,51f17ea4,1e5722cd,29c47f15,49c183aa,1f680d05,ca015018,664dc767,4de0305c,b09efffe,e7b164c8,c733d2ed,18c15d8f) -,S(339f95d5,5e293243,ec10b3a9,a8dba385,dcaa23a1,bb424bbe,4c894deb,c61cc881,3a4ec84d,67831768,e9ad1d9d,db82f785,52883fd8,b0b63bf8,38495a4c,455d5865) -,S(f94de87d,1123f6b6,97d4536f,7bb6a995,ff158060,b7d72b9b,3c9d74c7,1afb6009,f123cea4,bd4859b7,a852270a,17c76c06,e6050a26,9c035bf3,6c505fc4,1fa81066) -,S(71341ad1,bbebbb4a,17a7701d,30dcbf7e,2a70b901,5f6c5ff9,9fb614c3,d3338fca,6ab14a0,4b4956d4,a687acaf,30d7997e,cf70df2c,b49356fc,5b86453c,5ef6d55) -,S(79b8571c,f52ee30a,4d3632d4,965cc6f4,cc6ea06e,fe1cb7a6,ca2c9c9f,1e835bfd,259c0c7c,b8fa8345,57febdba,2183042e,78f8cfaf,24a41dd8,2eb0ad3c,426683fa) -,S(f3ce9dd9,d879e70e,21737426,dbbb27c9,7af84307,6855bf4d,af141d55,5006e402,302a436c,f8be3a4f,dd70a9d1,8f63cc8b,ecd3ba1,ddc9aa3d,f4285239,61e7553d) -,S(4a66f7b1,52a8cafa,78d0e98c,2f8361b9,a0bbad47,d23b24f,5184477b,e90d6318,7555fd5e,87676154,8f7afd4a,33511daf,b3bc4a72,c9f54d4,92327a2c,c235c02f) -,S(cd3b4037,5cd6da61,ff432898,fc592175,c90fbc31,373489ee,c988f280,3459bba7,b0e86ab2,2f2d8d97,5f68a7ab,3ffa3be,511390df,5b647608,fb07f29d,3155728d) -,S(e96f166b,84d98bc5,41ea8885,f7a48612,227bc907,795782c5,d0e2325d,96cb44a0,18ac220b,8def89a1,e3bcc2f2,7a66c0ab,3ee27c3b,882dc16f,e2571963,92b94310) -,S(87adb3fc,7fe6b07f,795bb7d7,ab8383eb,a3f91564,ce89d267,599657b6,9d793838,68677cee,bc7b3d09,efd0f118,d392d0f,d2d5f2bf,f2b50230,e127acb4,97f5c886) -,S(fdaa2f5c,ad1da3c6,3d241a7a,b4365e63,8eede0f8,229a8187,6cd76a3a,7020c545,5b04616a,a1a84785,c4315dda,da6289bf,e57cb9e2,80c42395,a1b13d69,dfb2ddfa) -,S(7eafa986,1a94fc8f,d263cd4a,1e481e1e,8bc1a385,c4ab748,8715b032,3bcdb52d,d655b395,607bb0b,c9092364,803798d8,17a4bdc9,a30e2844,94be8322,42af9949) -,S(a7fe4656,98538c32,844337ea,bc90fb49,feaf2fcb,8b86da6c,d173bf9a,70e62a53,cfb26d1d,689a9075,55057ab0,d4261e2c,acbf30d6,cdd09f95,9cf1830e,5d635aad) -,S(8bcc3b82,d543f365,478fe32f,dc9860f0,10d51f74,b7b5344b,ca6b868d,3c11264e,6bcc32,f7ff3e48,fa1775da,44b64848,f52329d7,d8bb0a09,338b799d,7452b4af) -,S(faf9aa3e,f1ccd659,2feb2add,a1b58ed8,27511b39,bb981cee,4fbe47db,5cab2917,854b88e3,50a6e9a1,fc7e9e45,f3fdb69c,8111c654,877cd620,fd82ee18,ba2d195b) -,S(77012901,ea269067,4d8b4397,e8976f98,e33b1709,c81624a0,7916da35,af75cb29,b63695d7,cc896358,e119eb98,7dc0f67e,22a70c5b,5e6e2072,e61ef62f,9333bc4) -,S(127602ed,f5f1a04b,813e2b6b,2c27f50f,803b70b7,b9525b7d,902f348e,c03591a4,1f791f7d,2427532,968f7a08,f94df6be,a95b7e6c,5490fa9b,5eb5a3f3,207455ce) -,S(17e82c3a,3731a73b,36501eaa,fde3ee8d,ca9f2573,dae1e4fc,594cee8f,e1d19179,8af04092,79792fe2,273e3f0c,e642f3fe,edf1ffed,59c5826d,a7fb2716,ed365a3e) -,S(3c34e27d,5d5737b7,78e968a7,fe8e4113,f802bd30,1e0367ea,41fc8b5c,14b0dd84,67bfc61f,bbd062ce,6224e883,9092a962,eb3105a3,b6634dcd,d59c61da,906a4ce0) -,S(b7a35907,c7b55a8f,7173a5da,c73e306d,64ee0f6c,cf4f5c76,3416bd4d,4f5359f4,d111c21c,e5a8674e,3a64adbd,4f56b1c3,61350b,44a552fb,19186b8f,95ed534e) -,S(6c7d4836,62c28812,7b904cc8,969ff925,8d9fafae,e88f6d3a,e6e4d771,bf8ee7b2,b593dc47,3c29694f,95b00169,286e3981,afeae4b3,dd7a788d,f32a14fb,6e6a8e7a) -,S(dfc406d7,625719b9,4f709993,c5d15062,4c725ef8,eecb2308,bfeec0b3,6050bf4b,651c0d2a,fb29eab7,d4740b5e,1fc2c069,54ced865,7a6bb980,2de8d873,a451717e) -,S(1631fa0f,4e9fdf51,a2842994,da94f835,52b5bb40,348c706b,54079073,665c6bfa,de202803,9a8d1ba5,b133ff28,6df237d2,a8d73343,a08e7c2c,4560954b,eda5ade7) -,S(fc52b3a8,8f712053,2c7667f9,62146d40,eaa3e924,327d959c,a49b74a7,da11e5f6,7bf890f3,daf8f9d9,49e800de,8a3f5458,5aa46e2f,25535cdc,18170391,e2101daf) -,S(6b7036e5,c5993c6,8a744776,abb0b5b3,31a886b4,93e49d41,bc7d93b2,28566fd8,6ebe771,42a56189,f272b6e8,8f70f356,ed1a3d37,ea2d5e4c,998e47c1,319e2ec7) -,S(b13dc5ee,7333e3a,4b13628f,7ef96ae9,4faee9d7,3a46297f,f1e357f6,e7a57a48,4f30b474,99c66456,33f5b521,9164a890,d8cdb78f,8c7ee211,1bd37fc2,d41bb2bc) -,S(1888e944,6fe20426,d4fd677c,5cf1043b,605e93a2,c8532623,b5951e22,34de08ae,9e1f4fed,d5de001b,378ad1a9,98e31f00,30af9674,c383f287,50172e03,ea0b0f81) -,S(2495b334,9884d5f3,166f8fdb,7ff81f9,9042383d,def7cab6,3c2775ad,226189f8,846850e0,2a1cc051,eea77bbf,d5f44499,673f40c1,190e379a,9b37201c,51a06e9c) -,S(e4c0e483,f21102eb,7dd2a78b,5a605b8c,410bafcd,f2ee4bdd,fcfe1374,ab32d17,b53fd34,568f5edd,a6a3abaa,2d2c3a4a,bbeef0f6,c37bec1b,fcf012c3,dac15b9f) -,S(8f9bfd7a,2e798812,eb927fc2,b0ad5eaf,81a0a30f,a97efbee,a1d6d9ef,19348a5f,1eec535d,1bee520a,13a8410b,6f3824cf,7c9d5a82,8208d2ae,dc89fa13,8bb7c2b3) -,S(1d95c760,f3fc2eff,df51cf0c,4b708538,efb56675,eba3ff8d,4f6abe65,d3f167cd,c2bb1122,5016ffe5,6859da47,4b777703,49e4e655,5da3d9a1,6dacbdd2,d42ab0a0) -,S(9df72bbf,fbcdc42e,adb71d69,1791f073,7f945e8,bfbf4e2c,68c5e3f6,5f6955f,24d47aa0,1626b0ac,ce77827,fd7daff,7424d4c7,1d76ad3e,b66d22b2,6f7d1df9) -,S(2df6ef96,7c0e1a41,2bb48bdb,f2cdf8f4,22829abb,4b7a42e,95bd9cbe,8b7f860f,bace2e70,7915069a,bdecd097,9d133cad,bcfedbaa,7eb9891e,ad3380e,9ca99401) -,S(82bf2a99,624e408,188da19,59599de0,eb947438,fcd45784,9a731a1c,15796028,3b6c668a,e5b8f394,3ee713c,a8fbfde5,8ef0f9fd,84054a9d,b626e274,37e611aa) -,S(60260fff,1f213916,9261edeb,5f1d2d0c,a143ca69,400b2776,21793c11,fbc89d41,bec4bfeb,9d09f8d5,cdb11e3c,f65c6a7f,d4aa87f4,e41d7f4,69717a64,5dcf9945) -,S(6391ed61,80cc46fc,33481faf,d21151f3,cb678e3f,4d667748,1a24a01a,c5e9180,c48495fb,fa5962b,44bfbc4f,491b89a6,a8588fe,91677b19,b872dea8,8e34026c) -,S(20807816,758361aa,d5f62d25,8e3951c6,da518890,26507a7b,c0ceb7f6,a96c141c,8526d53b,61c8427b,eb141d91,7a338fe9,f7789a60,cc1a4a62,15dc754d,a73903a9) -,S(1ecceb4f,8acc649a,dbff29c0,fbc62c11,498c7cb3,7d29ed15,e0ebdf03,e994b67d,1c701af7,a9f3d870,81efb798,2382bed6,5d56b8d3,f050bfdf,6da32b10,a18fd4d4) -,S(be82742,dcafe3ca,f646cf01,80202cb4,7086e0f8,ccea3c11,dcccd9de,aeae688d,236d1fd2,5e05d6ab,8651d88e,33d18a3b,caa66c06,b2b68c50,f6158717,f23b4866) -,S(15252ce2,3f666836,dfb47b60,1e642abf,6e56ff2b,5d58fc97,ab09f29e,1b4ec3a9,9a6b2658,f52dfc45,32e6b482,fe909e47,ba7b4442,3be4d474,a524df32,d6149913) -,S(b0429186,21f94599,f7032b4c,1b53bc6a,9259f142,27922f42,fe774772,4b0ee9e7,e73c32d9,ede68eab,e77d681,dd4cbd9e,a356fdf3,bf066f33,6ff2c367,59bed08b) -,S(5fe0917c,1bca66f6,f34bdf1f,dad88a5,b3dc5f5e,2e0227e6,5f3a79c8,9e66c888,885dfcee,c0947b01,71dbaf65,52c09ab4,c0414f8c,7373ec5,e3080521,401ed575) -,S(455985e6,44d9b679,85980752,a13a3f94,94bf9cc,8e6f10ba,fc7a70c2,27ce272c,47eadad3,15e88a99,9d3f5ce7,792ebc10,2fc68f18,cdfa1df,564601f6,3b26c22b) -,S(3562aca3,2291c1cc,ed072a4a,85fbf82f,6b3299f5,2626154,2b41840a,1c868d4,ab4b2656,11db5875,10c48284,7f72c75e,f822f46c,2e7760e2,a46070eb,5db7100c) -,S(54225801,f82406ae,74416373,7408e94d,d3990eb0,60581c47,b453a859,cf63042c,43834935,a6a7acb4,9c086391,24e80fde,72c0a876,1c13a340,1a4e48a5,d96f6a2e) -,S(3c253039,fc8278b2,8135e21,700af1e4,dad4263e,ddc867cf,a3532499,c2c1e48e,ee01ce7c,f8c56c74,1b4b3593,b0cb90a5,9c59cbe6,9a48235d,1295c1d1,ac657081) -,S(8adead1,d898eca7,9e043f71,aa735a32,763f75f6,f6ba7a70,bc47a284,4b580972,7a370bda,412df63d,5590b3da,80365c71,1267cf8c,e3fdd1bb,91ddb981,d213bcd) -,S(8361e522,34c8d62b,9051a95,8af3f090,4f15ee35,4b69a560,7155ea4f,69548037,ca2c329f,8cb65e8a,eb6488f2,2131c525,29df97bf,c8847c87,47145767,7f82c954) -,S(97d65162,d96feb36,e8f00221,52c92c06,2e97087c,703a9dd7,7241216,2262807,15a260bd,bd591c7b,91bdcbb4,c2684545,4706f039,8fef8de,9173e7fc,a3f31f44) -,S(2609f072,5ec8e5ed,4ec86128,dcee3baf,9e62bc24,aedbaaa1,eed8dd31,c9c07503,d51fcfc2,55398507,7e471397,ece94d92,e26375d2,2bddc0b0,d1b780a9,65caf2c3) -,S(820e8f01,5b4ec57,b884dd3e,6a740d90,68fce86a,a4833636,4b65ba6e,9e272357,bfc87d52,eaf352bb,91f071ab,6e986308,4f197671,298eb614,93152f54,345ce5db) -,S(2116bb76,7a56312e,71ac58f5,ff2a7071,1be5b711,1e9e56d9,aa098af4,b991db0,2ebd4fc2,abd618d7,d1798739,7e9b8eaf,8276086c,2a5066e7,e7525603,fbb4c40d) -,S(e43f029f,97f4370d,65826870,3f29422e,7b81112,61364972,e26892f,77eed56f,4e265fe8,40524def,23b7ed34,54c6618e,ec70d3b1,92ff30d2,1b9b6fc,b1f7164c) -,S(9b4ca445,5cada269,2a77f7e8,9aa3082f,ace4de3,898408eb,6a7d1cb0,8ac15c14,1446e397,d1c3fd20,283f43a8,4679e728,64f05251,b1d3bead,58aca70c,4c0fcc29) -,S(e2abb09,c0566f51,7947f99b,2d6fc4a5,637310b5,5f9d9014,84decbb6,ca22cbfe,f334bda6,a1d9cfa8,2b18f8f7,e90b8426,ae13e20d,8834e061,ab1671fe,4f4665f5) -,S(3579fd9,9cdf0be0,2d7e8587,2e213ed3,3a424650,5608d66f,8f936ae7,72511e28,dd93278e,ce754f69,4b3f09d5,a3c32c99,2c5f2e04,cce0a517,de750a38,ccd88abf) -,S(f307f2fd,d0f6c0b3,12841e5e,1e17b966,47d7ca93,4ba4970f,4f9c0c0c,3ccb071f,4829a5bd,40555e18,bf80ae66,b9742249,32679acc,d0e46003,e079e2e3,d20d248f) -,S(a462e750,9e718317,dbc72b9b,fce5909a,bdd2fc36,d56a525,97d3adc1,fe4b98a1,2f9ee390,13b70415,d2e6de97,7aba55ab,1f7c6f2a,a5a7b541,a7101a62,f2799836) -,S(72ec447a,245624d1,1e1270ea,1c4c060d,c6501f11,70c69f4b,229bb98c,e7c47804,cc32a876,33bb7d62,e660ba5,59cc1804,10a51cc9,dc48a9ae,fc3d8225,35fb8ff2) -,S(b97345ad,2a7eedfe,71ae185,11a3e2d6,c431e628,363e01a5,21622c17,e92b32a3,2ba1cb4a,abe0aaa9,619ea819,4e5c0222,3bea32fa,e4ee3378,ba798472,19670e2f) -,S(f417f269,de287f06,8a74a330,14331059,73ee691d,a7f5aa1c,4e00a100,1e2ccd56,1bb297c9,5b3fb72a,3263f126,719a82a6,b8bf415c,e81f6838,2c8b3a9b,42917584) -,S(cdf7b5d5,f7632248,be1bcc1b,61f56491,e81cfe76,1ee897c6,fcebdf4d,109b9b41,118f3f6,32f18892,d37a2aba,1c8d22f6,587ad56e,eacef09,b9202005,75ab7b11) -,S(3540c9dd,992dc4e4,9aba8fbe,8f28950a,24921b05,e1bae568,2714aa6a,95eebb81,841d9499,7bd92dff,53ee3c86,eafc5f6c,6ffac94d,3161ae86,2182caab,8d5a9268) -,S(70f4ef3,37a5519f,466cfdc7,ae779588,74c9a9a1,9a558550,8fafe6fb,d61decfc,413476f7,78f5d377,31aa712b,5c866100,bcc2a33f,ae1a078e,c5e5cbc8,4b7bac5e) -,S(d08990b7,ad5c205a,e5be2700,63bcf8a7,e13c2a,73dbf321,b0d9cdca,a1648da6,b0aa7acc,f47376c,115b0226,1494162e,d425b496,a2392aa9,254655f2,4db6cf48) -,S(53d6c5ec,f59c49fa,d970611d,b8423bbb,e2f5aecb,d4575877,d903d95e,eb88e455,6a954f77,532c80c4,42f2bf65,8e9d763,617c802f,369f1a62,34927e55,ac549f56) -,S(af7216c1,e51fbfb4,a5ec1e93,717f7375,9f15dbaa,86706ca3,6636f499,416ce194,4ed49771,f858a8c2,bad65a31,b5ea5a53,8841553b,accdced4,8c41e2f6,984470f0) -,S(c560d2be,2f2fa6d7,3f5224e,36acdead,8d91eee3,b99a219,a762adfd,a5e79d07,30d4b54d,a96fcda2,2187a2bc,1562d59e,24ab55ce,f9cbfbb8,570cd89,4d436343) -,S(30b40200,c728bdf7,510db9f7,a8a63792,ff70a9f8,c6262e89,4ef902b7,eb30fb8e,8c98fdbf,29f8c5c1,ce6d7d4d,61a2907,ab57b4ea,a25888b9,e8ce751d,6a19a88c) -,S(d7239e30,814ef236,5193c19e,dc91fcbc,955dab78,45b4f3ac,be994264,2a434e1a,454dc941,4500f4a0,f93f751e,1e2d4c25,8c0f10e1,b4f0c6f,3be39b0d,e5170dc9) -,S(60e511c7,7c8d7496,a3f262f6,376d3958,dfdc4645,73aa303e,a6e6672d,b1c21b36,bf86ea8b,c8a37a4e,c5ee1a60,d6e1888a,ac90530d,eadf40c5,b4f61a38,2ea1e340) -,S(55cd8f35,5a242219,3b64633c,27b1c1fb,7ffeed51,c815e1fb,ebaecfb2,3883d739,b6508643,7e53ad24,1fdf4dac,871e58f3,b5abb87a,d4920057,3c37a1c4,b2bd4b3) -,S(73cdc2fd,468a2d21,72a9e0ea,3d4a04c5,ab5fb13e,2e2ff2e0,8af5d70d,ac9bd41b,682e525d,1263abaf,f070bb47,6f754da9,f6c74d,27f319d8,5d9d2882,6d06fd04) -,S(e5f30676,3c9f620,1c5ada9f,6d01201f,97e36fc7,5bb10a12,4cf69cee,619f07fd,611f0f16,39aaac35,5e311a18,a5dd65ca,70e1a52f,452bed2b,3382ac03,dd50546b) -,S(c2c21323,b156ca78,5e53c41d,10bc235b,8e32e4c8,ee377fc2,42d089a0,d2a27d84,6b9f3faf,64331dda,d25d603c,d8f334c8,5cefcf5d,3bf640ac,96fe3bf7,71ce9cf5) -,S(599ff1d4,806aa8c8,b1440a92,9e2383bc,efd9b16d,899289a4,a335dd06,7e63d9,459cb346,7c387470,1b86aa34,c47b8214,7f48a0d2,7b9098bd,2b53d7d8,93e25316) -,S(f02ddd62,a2456e7,b4a90bca,1cb01e98,8b0a09e,62c90154,42db0f52,b635b006,a5666540,6cad4d01,aab99686,90a7ad3,b1ce936,957c317e,57bdb763,b8867583) -,S(f332b89d,1977afdc,aaf681a5,19bca58d,59852f74,78572346,b688d55a,d55a34b,988afdb1,afa1041a,51ed913d,d780b21,5dc90b8a,b5ae857d,73df2883,50ca78d4) -,S(d6fa4679,4fd4d05b,d6b7bdae,22a970f,8c3c3628,ea0d2656,55c0ebf5,2f1b3a73,d9f47018,86512ff9,9c4691a1,60b62e2,616f5c8a,fa2151cb,fd6dcd80,308ad947) -,S(2a13e09f,5c00016b,d974d62f,2c7c7ce9,e46fb142,e7334f5d,98fa2428,e26b25f7,f300cba4,26636d5f,7f8fcb2,bee6e5dd,b9697cdc,9f9c0636,b02b3fa1,820ca235) -,S(c6480cb1,c1bd41ff,e57cbf57,ea854158,36284048,e79dbb51,44a59027,13d13ba0,fee7ee1b,1652e63d,ad49736,8505b302,f135df7d,4a2f8720,74631646,244cd43b) -,S(559613e,8111c9e8,25fa96,aeaf4b2a,4019ea61,4c67446d,76305484,c9a4d7f7,cee9f4eb,2680a723,9187d407,f39390c6,4fed596c,b40f58a3,aa6c96e5,c8c9c2af) -,S(3a95b2b1,e6d19b19,84dcd59,501c33c2,4ca50b59,d410d99d,b9b6da4d,b1dc85ec,7a802198,a5c61542,81669bc0,640a8f40,6815d25,3bf8090,3ed894be,a1b09c72) -,S(5ae541d,b816522a,5d347339,713e92f5,25a637dc,75c9d9b1,5d834f2d,b265c2,e98a115e,f76b2102,7953f65f,cbbfd29b,a79b43ff,8cd6813a,b65174d2,b03027f7) -,S(88b5506a,72d681bc,d34eb118,3d6a7fc3,77e7f496,6d4c65da,bfa60a18,210ec487,c29638a6,ad91272b,3525ab40,1ebcd1ce,ecebab3e,b506cfec,e7e9df0c,6ee40501) -,S(2942de16,93ce8b88,e7e45657,daf88b2a,2118fb7c,9d2296ed,a1725ec2,f7d408a5,778f43,8b4f088e,fb99cb1,819fe6e7,55b0641,8d8679c9,d684faa5,16970f5) -,S(25c22037,e5a46e15,4adfcc47,480a088f,fb53410c,dea814f8,a4f2c387,df2afd0a,45cfaef5,5c5d3742,3380be3c,c38e6785,c85a90be,7cc92fa7,a390bca6,d3e7b3c1) -,S(b1f78a73,d0b935c9,80cd8ab3,b8237e3a,df5a40bd,5f875f7f,bcb13bfb,cc45839a,466141e5,d465c35e,37f80e57,c4923c84,c3a3ba98,549cc8f2,db6e0dde,915293b2) -,S(39405322,a57a4846,d8b42bb2,58f851cb,5570295d,71ded6cf,b803852a,8b4d8304,c81047d5,92fab5a8,c6139ffe,6887d966,e809d2bb,ee3a10b4,5adc5587,ffb302b3) -,S(7faa8352,31e2c6d5,b331ada,5e175954,6142b131,5347196f,bbc5759b,dd6add0,8779b0c9,2c176b72,5355bfb5,ccf5f739,5fc82ae9,48896a38,1be85e58,c48d154d) -,S(b786c145,61fe4677,54e14766,56d33daf,adddce8,e86e09db,ea93f1a,2ff0c3c0,4c5c35f5,99bb9637,75b4d61c,b30da8ad,a4e83a56,2cf7d2a1,fc22f06a,fff92aa8) -,S(ea4b9a9a,b4b509da,d1e70ebf,6604d624,8b6b63d1,c905720a,648e208a,993ce4fb,f5ab8356,ce28ccb,b6f1368b,344e15dd,372d732a,d8953864,21ce415e,6f0a92c) -,S(c986010d,6339bf7d,2ae3e9a6,c977b9a,a2033a42,14a1e9b3,e700abd5,428e2491,4156f13b,a68ebc80,ad12efe2,d5a0469a,a41adc0b,1dceb765,f651b4b6,b652a85d) -,S(385b81d6,e023164a,3662209f,5d694910,22e84b5b,7034e8ea,346941b9,c04df428,9d12b15e,c1868f27,362662eb,cb3c9bc3,1626ef22,36c2d75c,65e82c75,7ff81a2d) -,S(82196a55,104624b7,6710b4b,864b738d,36ebcfec,55226aca,990474b2,58aa978a,48dbd01c,5af9b1fa,21d88b0f,f6b994a8,38d47755,5ad85171,1a4e3d0e,14ab1914) -,S(dcfbdad8,34d74f6f,9df6c143,abd6dbd4,57f954ef,6323ff77,3a19c367,8d6616c,698d3051,8f8d7ffd,b45f0bde,c32c22e,2cb97acc,a8aa0aa9,c16d8789,a128c3a2) -,S(343b04d9,babecad6,5479cf60,e43350d9,8c56f989,69eeca59,5a5e97d,89c25489,14d00978,2729ea38,a79765af,ce78ff5f,16ada59e,9d275274,e6e0778a,facc25ee) -,S(25af2270,88a6beb,7c76a80c,9e87a412,ed166a71,d65d5722,a082e57f,8ac7bb77,d01d89c7,39508a84,5ea64e03,697c2867,5b14bbc,fb484f94,a530e57a,cf19ead9) -,S(1292823c,1759fa5e,48d0724e,67c93df2,c8ce9fef,9124c5b5,8a477aa4,dd3f5e32,c481025f,ece1bed9,26ecd3e0,3cd7eddc,3cc31836,a12855d1,639a85df,7c69650e) -,S(ed92246a,5a5cb2a2,1618deb0,794ea013,20560b42,273638cf,afc901d6,2ff0bb6e,3675cd33,825e611b,8802c746,9cd82b97,b659e31e,c31ceee6,681a35d6,2d5097c) -,S(8174e89c,9b3666aa,69ed3bda,6c73c572,ff3384e9,60863f87,b7d346bf,afd553df,154d75ce,caff95ba,4b5b7b7e,9ea99dff,499a522b,f0252691,cb6b92bd,98182d0) -,S(54169816,f0440f73,1f14de95,e7ab32b6,702c0183,62794ac9,e55ad632,95c4484d,12e541c3,ee64efd3,b5b8781e,bcc5e273,3544653c,d8b55d51,fa3f887e,d8f42465) -,S(c654d2a5,e31ce452,739f9cfd,b2784d37,eb974a4,fda45fad,13a2aea2,f7fdee9,47c9d2e5,24e7391a,f645ed92,cb04a0e5,6aef0362,9b57d593,edc85b1c,686ca4b1) -,S(59724a3f,eb1a1cd3,7fd6a5c,57c3d055,28fbdf48,5102e709,7ac35912,3f9c2ed0,4df18ea4,c0de4053,6bc5a6be,2df794c3,2db2a9cc,19367473,d88829a5,8603010) -,S(d99168a1,3fbeee0b,6aec4b7b,a0060649,1c4ca151,1cadddb9,2ab3478a,325b1073,c2b0876f,528de53a,f2f695b9,b8225fe0,4660a447,c9e9bd9e,4ba5e52f,beb0ce6) -,S(769c1b07,c26b402a,9a4b60f0,5bb0b318,d20f65b4,e941f525,43a15697,5a8f876b,7880299,413ffe86,94a76f26,9acde007,6e64a753,94701bf0,84324215,debf3d69) -,S(6074f53c,ddf9467e,b9fcc4f7,ea4b18ff,777abd8,895c9eb9,71195a9d,57b1b1ac,de1aa32d,e5488e69,eae8a06c,3c89422,a26f819f,af3cd9cc,762d7fa6,1fda3094) -,S(1f9ea27f,3e9e789b,1cde3fff,94bf8046,f5399046,867a2f37,2da59221,e85c655,c47b5ce1,3d399032,89449260,7db3f7a2,52a74084,20ab1846,fa378674,1e7bf7dc) -,S(c2551e26,5d3978ce,49cee376,ac86a0ec,7ba10804,bd894019,e79f51eb,ec9830c3,23dc4415,10635bfc,2af8f85e,c4cc59de,fed9e9e4,198304f7,e57a1f42,736871b1) -,S(2ca9e4d8,3358ea8a,40bc15b7,8c06169d,ed7a5abd,47147972,45078e94,75264d20,f3324029,9fe328b7,ecd14a11,6fd82bf6,5d925532,85a176a9,b7ec892c,ebb2cd94) -,S(e0db4052,8e3eafca,1f514b26,8b673afd,277c5aa9,e2dbe85a,74478d6a,f2ec1f94,f868c782,40dd75ba,3c6809d2,d62f80f1,ab7fead3,c67a90d4,ecc242c1,687376a7) -,S(d34cd3a5,764d99f3,16a260c,9659955,fda3cd9c,cb305f73,d3aaa61,27d422f3,3f3b80ef,74bec102,2e442e69,8fd4e28e,514d3a9,5011ba18,1299793b,b760da72) -,S(588dadd0,79d2280f,37dbeb16,3e05a70f,48ec61c7,cf3e6455,f3ea312d,4ab2e075,731a5c9d,f803c2fd,b22de461,d51af493,5874b745,4ab8417a,940383b2,9404fa3d) -,S(1731c955,931905d1,ccad3bc6,133f5d9c,9fbb10c5,e800be80,643ed02d,6d7477b1,d7e89b3,1f18ac07,6c7b7380,64d2449d,2d9beac,728ffa8f,6d8a7498,d43baf1d) -,S(e2f990d7,6818c0c6,e73d066d,5644e9e9,29f495ef,507b18cc,594871a5,88e45b46,2ca12307,fb565d0,7c60b6c3,e92c9757,45777970,1733c0ad,2b299a20,8f50925) -,S(b92872d8,a146c0da,ec576be7,35a22896,5242cc61,ba37313d,31b0e5ff,21a2273d,8178dd34,e552e97,fff949e9,b101b44d,35d6b57e,79c0e78d,f91ff3f,2817daf1) -,S(b980d2e,9440c3c3,be5cf393,6eb9634e,923cbde7,bbf2a07a,d7a97287,7d6caf11,51b7d51a,8685bf75,c6d376d,441dcd69,cac67b77,762f6ad6,97a9649b,f3d3719a) -,S(db2f9a64,3c3e3706,e9b5aaa4,5ebf08f2,ee9e967c,205a49c1,7dc76b8f,b20a3a52,d05d486f,ab967e27,b9e8c175,e93df203,4657dd,750ad788,1bcc4897,b80f3d40) -,S(5d5985f8,910be82c,538d70d8,9614ec3f,bc9e1f91,9a19950b,a8fc99d9,203d92b5,3efd77d1,27e43849,a710d1e5,7b18b681,c1acb293,2244fa7a,30f360ea,88565e35) -,S(fac2a758,a063dd8b,46b41933,9c70d2ed,3807bdca,69d3b36e,6369f8b1,23200866,8294340d,6154afa2,d7b730b1,301f5ab,322bdcf8,6fb5676,78fc47cf,b15809e3) -,S(cb92092a,d45ab0b8,559846b0,d02a0c67,a13edc86,7d0cce5d,fcc09e63,d1b6cbde,d2593de2,6371136e,390bd52a,c9811334,e13fddd4,e9b86b1d,942cacf5,4615b287) -,S(d715f4a3,66a4a770,bec8abea,49ab6c7e,99e9473b,73e479c,14011843,9470c844,40aff69e,ec6da9bc,38ec119,df4482ff,3bc2b67d,31284db1,8c757990,de6cd0d6) -,S(77312617,4a395a4e,f7bad07d,f2f38843,22293a17,ebf09f20,4732e7f1,2c418417,602cca39,d6352365,420c5ce2,9d2282cc,5d8919b5,e0669b09,22384b69,7bd48a7f) -,S(a7c4b675,f529ba17,e9f1ef44,c88a8066,66131845,dd98da82,4cb04f24,518a4071,d88edc2a,1eb0cd48,57283e3,f8658d8,2da27a7c,7ec16129,78fbb484,41ef438a) -,S(6362f575,d459b970,db814a7f,9a142605,f26f577c,4357be2d,dc16793,64906f7b,fbc9f007,bd08b6ef,cd49c1f7,1e199fa5,ede01123,5d9b015d,515bf7a9,7192f8c2) -,S(6cfc45f8,515813d5,dacdcbd4,c34c155d,c66b0298,8b8a8702,73a5342a,9249b623,f85c980e,394ea0b6,39bdc5a5,ed185de1,7b1f44cf,b7e51c7b,b9f56b3,496b5ee) -,S(d76c0b83,b8a8a8bc,4e8985da,f6f1535b,9ff3b4fe,e13eed4b,39d6426c,87cec8f6,15ddc103,bc6c4f43,6f7e23a4,78e47166,e3f4156b,5ad2d581,7f3a7ade,7d80dcae) -,S(c4f98324,57330d12,e4e26735,464f24a9,a93dcf75,9194fcd8,a2d12ce2,bce0449,e24a6f24,f9a09aa6,f58f29aa,f4e24a0f,864410cd,80280432,d82cd9a4,ea2ac2b9) -,S(e86da865,238fcc7e,d8c2721f,89c2619f,a2caccd8,5e05a21d,8d23a095,634cc439,85b35268,31871eb4,3323caec,13de6de7,94ddc6e7,5d44835b,7443137d,25ee2194) -,S(a6398918,6969469a,939e774,eabbce54,109b833e,b3dfb566,876cf50e,bdc7613a,c48430c3,fa8c730b,dccb53,451b5a38,888f2e85,1f510ca7,64360c9c,b72b6eb7) -,S(6986ef9e,88c8dae7,ecc8184e,a4c5d131,32a87ad2,ff8367ee,63fa0ecd,b7a2972e,e9acba9a,896e1eb5,bc1d2625,983fd2c4,13f54b47,3056a893,7197f940,92eb4bf0) -,S(47bf849a,e428bdde,ceb221ab,e0ea2fd8,c0a5bd39,175aab96,c2fddc57,e809527d,401a7ba5,1999aead,4dfa6ce0,fbad17e8,e7187e52,806a58a6,7033f653,67aa7c02) -,S(c0c02bb0,92af6a5b,73582a14,89067933,8b31318a,f2d5b142,d58833b4,cf07fbe4,a19dff69,5ead3a33,d8f9f7a6,76b8287f,4bf6b23c,6761b084,12d86508,830f8990) -,S(f2185913,405156ab,22baf16e,644063da,b3ba25ab,f191efee,1ff028e2,f7d175e0,814c64f9,9a4250be,2265cf8e,47c8276b,9e5245cf,16ec98b6,b789dd26,be894f3d) -,S(40d840cd,ac4060f6,de850df7,c37462b9,b4d5892f,a1e74f35,89ab3955,a5d941f8,9892b0dc,ff43a872,6974705e,3a3fd077,c2b91a2c,1c6ee153,7b728359,d3217833) -,S(6f6b79e7,9006fe48,5546c3e8,52a33dd1,cfb63f3,96b44d1b,af1fb112,93271b35,f5aa0beb,50a628b7,b5348817,8344527e,d1ecf0ff,a0766a78,faea2361,e8fde7eb) -,S(4edf60c8,c0488128,29e7bac8,7b03ce49,c8df0f1e,6a3e02e2,ea8ad097,f66163d7,9861393e,fcec430c,c00ccd49,3d4e2d2a,a45e1034,fd9a81e4,b015bd5d,56f16dea) -,S(7ab0c44f,f6a444c4,e0feb1c5,a6650c37,26249caa,38f53e62,b6bf225d,bb1e008,e7f9af86,a2839ce0,80c6ee9b,d86529eb,7a7abaed,aa6aa4e7,207e67e1,a500e5f0) -,S(6a90e50d,3dd2f382,1dde8714,57012b3,5c1103b5,80ee4982,f9bb78d4,2541f8b1,5ccd34c1,8455aa76,4cfe6c9d,61507ca3,cb613bf1,4b9eae3f,8391e1a0,9dec03f1) -,S(289d4d81,cccf40af,a61ef56c,242ef8a2,c9883267,54139e1,dbf018ad,5d251df8,f3fead19,c49de6b4,32869220,7e60408e,dcdfad25,26e6e555,9b022941,592081cc) -,S(a1ee466b,c561919,2e82a316,ac3b7514,b109f442,1c93fbeb,234f5862,d37ade3c,db12d4b7,246e8ee5,55dde2b4,9b5c42e7,408eff9c,a853af00,5a6f6c7,73aff21c) -,S(ab30a856,403a1622,14be9837,2ebaa8cf,8d946074,abfddf2b,8e65e2aa,51554329,7a6b7f22,a6ea52be,8c0c8002,29613020,a247c026,86eaf960,7fc56cb7,d696c56f) -,S(17c5f1b8,8e3e4e08,dab8a5c9,2a679c05,688a7437,df6336e8,7b0d22d5,ed56e5b1,96068e6c,72fa9b39,5993913b,305caf70,3186404e,17131b5a,24e14273,a83dccc9) -,S(a76fbdb4,b99e31ba,c434462a,64c0557,8e961a53,dacb9bd7,68400b8a,823190ec,52e31883,5ac1a3fa,e269a4d3,17bab065,7e890844,c3fe96c6,d04fa015,89c89f14) -,S(17b8bb76,10476261,ebd75e4f,299f1805,5c88f36d,ae65cc57,3c959820,25bb794d,1bd9a52e,585a40d2,67db59c6,b9b1bc59,4b8d5344,29b5d4b0,82bb1c9b,b54e0392) -,S(65aa92ba,8fa51cbb,3954b93d,68cfdfa4,d64d97c0,9e099b1b,d1ba853f,18500b37,a2b12d21,b7a1ffd1,af48e4fc,e80c6fc2,e624783c,7b0cdce7,9f01ae7a,5fc96e14) -,S(3450bcca,5d3b30b0,3743f0d2,6b61ea09,de6ef7cf,eed44b3a,c58641ab,93ad7867,4fca3307,5328a298,d310d447,4806f297,3b09d885,9fa3b949,11817d8,39be66ad) -,S(484bf072,134849c7,695ba73e,5f25a8bf,74a183f2,bfe35ad7,34b53878,a2036be4,a5295452,a0830b3e,3c45043,43fe950b,3289d402,73d3bd49,6c0cd7c9,156a1d6a) -,S(2cdf1bc8,920ec641,63fbc8fc,c72fe5c2,dfcb87ec,15725e04,163e1ac5,1b7ec763,c680476a,28f054a9,ac3a073d,67ceecf1,c8262ed,4bc462bc,44798e88,d0e48e54) -,S(59c3c60,8031a214,d3e6be15,c644265c,b6f3526c,2b37d840,86532c24,52359bf9,2248b28e,922e0468,fd98856a,41ca37ec,2fc7bcf9,a13c7a9d,b4135e28,5cdc1bf5) -,S(4f20493a,a7a1e558,a44e54e3,b81c889c,d45b6384,9b8448d4,20a34a31,c7c451ef,bc1adcc0,d00384e7,93c2433a,a76f1f08,b8b23170,6e285d56,3155dc19,d5aaaf1) -,S(bed9949f,dec9813,5bcf76b4,83117fca,57525221,8a6a52c6,a44f2468,29d48ff3,6ab35499,8cad07f6,250dec89,a0840192,b62777df,6e241a4e,325b0c4c,bdad23ba) -,S(1cf32b2c,46deaef6,fbc892ae,4f05653a,3cb69d0d,821a7125,3c2eed77,4e75f767,caa6268b,b8574b47,840b3626,74f4a479,5a2c6478,c440aa4c,36d88a2d,ebacc8f6) -,S(9d3f7c5e,5e0947cb,d9bef5a2,dc1a3e9e,ac22d6a5,9071d0eb,5f270100,3e66dc96,6ad63f62,22f3a787,9544c330,4c3ff653,2a00a764,5ddce01e,c4ac4933,a5c7aedf) -,S(a5a927a3,f03dcbc,b3d069ec,156a6ba3,474f48cd,4828f54c,a673e10d,265eab6c,b5e360fb,39f65847,b63eb29c,a8b403d3,272d9ef1,8127d3f3,7650d13a,9a5736c4) -,S(48de778b,7bf72a21,871ea379,c02b8887,5da9688,37faeaa9,93e68eea,926db673,d25cb808,7a7c13b,fbe8b1d5,522ac2db,6c44526c,13ca0327,586d6a5c,1aaca91a) -,S(a029831,66e7cb1a,fff65515,48faf447,cee8ab2c,d4937269,db002cbe,b8f1d1ef,ef34ec5,42554e97,1ae8897,b049097e,3430c99,d8e93c50,94377c07,a5619ea) -,S(6ed75b96,c4e976cf,75cf0b72,df83c043,5b15d2c3,f8fb319a,94a4d97f,1394df6f,9b63c36c,1e31becb,e1a5a6e2,1abb99d0,d5c39694,cec00fd0,ffc27b53,309bf6eb) -,S(9372c1d1,6997f792,688a55f0,8f246cb0,f206ce31,d0f416c0,c81cbdd6,8487aa5f,ff97433b,be60eaf6,6f19c182,e8a8bbbf,b24cdcb3,7aabf79d,5dac9f13,9c5033b4) -,S(269c7d84,b42f90b2,f39b4db7,5ea0724f,fa6a1a5,4c66a1bd,a21e4254,6f243bf6,8f6f8b36,e278c6fc,bb0c9918,7325f1b9,75ec3add,69708be1,b4703c5d,53d8f8f5) -,S(62f9cd79,921ec46c,d470a12a,9619ad4e,3bed051c,14f47071,e55f9da7,d103793c,92211db,6c846f43,2867b9ee,3b1ff00a,a08f179c,13aa7475,d64d0731,23a69e4a) -,S(fa432dcd,e7e3b40d,a127d65a,e0955d58,a009d81b,46b48745,c4e24597,4e589a8e,a8dee557,cae7e50,d96555ce,c56255b7,c64d10b7,6639b3bf,8d60aea7,58716f68) -,S(a424d18d,c6861074,40f42e5e,f2bfc95,f4c8f94f,e3adf681,79086502,fd9d80a4,cb30797e,1d973012,d488f54,6033b1b3,d6b50c8a,39badf8,fcc12bfb,3a1c4d0f) -,S(c2a6369e,e2857d2e,fce4ab31,49556c08,3ac6af90,6be418e5,ddc5677c,f2f7ec8d,a7097ae2,9fea3774,11ce3f81,b6b3356c,9a2abb69,986ad81f,46b13f8e,a0e7f0a1) -,S(f5eac1a2,3dc91862,d8022931,3be5c7a5,364c0880,23c0650e,53e22f42,2f91ec98,7dd62b80,3ad606c3,3d8d9bd6,cb397ab8,1cbd688f,8375a405,23bb7315,a3f48c24) -,S(dd94fec9,3bf7ec6f,cfa0ced9,df31a1c,131c39d7,e110b5e7,b988c59c,dd594fec,cb858565,6a32e03e,2eb84732,4bdfe2e6,3601148f,7bc7e56d,22cf9aa4,54f063f4) -,S(d3dfdaab,8f9db2d8,edd3db27,d96be5d0,678e9088,5448222c,5b3171da,38fbd501,6b210554,df32021f,35170e13,42e2da18,72be61e9,481a4b74,ec470ed0,b942025c) -,S(47ff9918,3e452838,f63eb828,a239d95b,62f8a746,8acd0b43,6c149985,2afbe3f9,33b7b8a3,a5b51b15,fadc1f9,baec6b8a,88e0da56,5a54bea6,1b2d728f,eabbdc48) -,S(1e99e92b,aae56401,1cc10c94,dac071a9,27565a17,2d6d4a20,224e1b49,c007660,914b98dd,a92484e5,a43d7de4,7bbf57cb,2346d852,f743fdd9,15dcedca,4393aa21) -,S(e150364e,d95ca778,70fb3367,64f9f417,70bb672f,7e794416,13678dd3,65d84fc8,23ddee4,30d7b565,cf545837,58df61fc,502bf86b,a4cbc1cb,7630a9bf,e339ab85) -,S(44dbe753,dd822ae3,f3ef4939,a1d96a98,33e697f8,c4979191,c64114f6,71e8fbb8,b909bdb1,e6e55571,b03517a3,c2345b49,a5793d21,15fac018,2afbefe9,c726c8d5) -,S(fb843458,725d557d,b1a17ad0,427b4d98,6ba189e5,d6da81a8,81867259,6d9d2858,18f1c9ea,bd8e71cc,72e2dcbc,532b101,c7381475,46c24790,d010a6cc,32d4eb10) -,S(48f43c41,b63bbb05,57f8d71,edc739a9,57baed23,efe9c814,848c54e8,54159144,cb75c418,d5557cfd,b29d4807,3f193343,6eafc209,bdf9685a,72f57b98,6676b193) -,S(5520f175,9be037bd,cb5af2a9,a0bdbcc4,9e1531c0,32fd17a4,66f59b38,6d7de1b7,45b933b4,cf256aa3,c6513a2,8a4eff90,7691a34d,e6cc2e7b,a0b83f8e,a7ed4e52) -,S(83936718,1d7d065d,5c15e246,ce8391a4,bec58c71,7f82419a,ed6547c,63f081a9,4c903568,f5ce9a54,65fa845f,985f24d7,6e66cbe,3ce256fc,1703b4b0,5dd636c3) -,S(66a82c47,e756062f,6586ece,86911ac2,23b84c9a,e53e5307,4e22bfbd,3eae6b30,ab2051c,4c231a40,c6da6ac3,5ee32b9,b7eeea17,222cb1d5,a3abf9b6,512db8ec) -,S(974ce35a,9d5a4ef5,84d252dc,3c365423,1335c52a,e3daefa2,8ff9b75,56bf3b46,8c82a9a9,c49d167,4f3995c2,90ae06ac,fa0a5c14,b1c5f41e,c1e449d9,5effb2c0) -,S(1139c2f3,60cb8a4c,e020bb8c,3d19bce2,1c6802e8,5fb3df33,8fc9ffbc,8fc231b6,59adaa14,7980b3e4,73801b73,9f1e0248,2e9f1e17,65df2ec0,183d9f81,d57723d6) -,S(c1bd3793,3b03d95a,b17c10bf,c5167556,4294e38c,740fa3ef,9b356be6,71883b94,c68bd82f,5e926a59,95a83f1f,1a8c2f4,5966b073,91ee74a5,ae2ed99,106c6dca) -,S(c7778ce7,ce668003,86db9263,cddcf608,aff769e4,b4755858,20554ecc,8407bbf2,92509200,9c57f224,8f9b4e71,532c698c,88b91b77,4a3907ae,1ef30c51,78d807c3) -,S(14aa1177,51626b67,8f32418f,1855cc34,52d4ec13,d2d900d8,8a22432c,70ec022b,6151fdf4,f4372a2f,e803478c,da340678,c18a0a7c,d540b0bb,4168f9da,2edd6d81) -,S(a53443b1,b6065cb6,abb18c84,1f171b3c,7152b34,293a7ad1,2e8599fd,f1398cd6,3a07e076,35254aaf,eb30efea,328e3ffc,3a7d280d,5cb2c8ae,9e70b412,38fe704d) -,S(35c3e3ab,ba4c946b,1eafff67,a9831588,d6631e18,9507eca7,66e22449,f8d294fa,94973920,58f6830a,4e5f413e,4d7d442c,4348328a,5115fdc6,ae5ab638,339e313e) -,S(1aabc2db,5ac6df10,1d097db6,26e3623b,295ae6c9,941e3717,ca849065,512a7fa,2d2781c7,b42ce42f,b40b737e,9100ea24,ecfdf58,fd724244,dd67d84f,4a6cb097) -,S(383103b5,5a4beefc,89dd082e,f0e14211,9bacc5fe,8acde710,7429241e,f16820ca,2000fe09,2b820a28,f065924,7823d6b5,18756044,1856dc46,a9fca8c3,84913398) -,S(2cb0f0b6,35022212,88b8be63,a0ed5d71,bc6b89ca,4b2fb4f8,54123124,49445107,9a9eacc7,cea4c27f,ac63a2be,96884112,435d5f6a,bf4ad519,461017c6,1c87b2a4) -,S(ae63a05f,306e6980,f439afe1,b34c7b3c,1453e110,e477e3a8,d7e9ad3e,fe2af088,6facce76,d579afb1,cded78a4,1dc64c79,b6e90279,d8c5f07b,fc2b0a3c,7243b309) -,S(83207533,78d5c6ee,ae26aee8,4f2a0833,a65a94ef,53a477b3,c8708ac0,35dbc24b,d8306300,4caf8d6,7fdcd09b,267a2d5c,b0e83e97,60fc4d8d,2b07e2bb,c2b387e5) -,S(f38888f9,3337633c,9873d501,8b9fbfc2,ad135870,89f6becb,528ea063,a817af28,8beb556d,8e5342f0,6fe06215,891e6091,f8b940fd,b6eebc08,ded95ea0,99985ecd) -,S(c15cc888,7d13a93e,c2411ea1,6f21e86e,4fabe47a,55a94a6c,aff7681e,d47ba1a4,5bcf5b68,91f3e01a,3754fed3,f70e5052,e33fb62a,753c5f3a,532112e7,f7f58f55) -,S(9b3b0b21,1befb305,b02d035a,1e7cad04,3b8ce04,f9315bd6,5067a73,f2680030,75828df7,eeec11f2,e0dab801,5c75213d,cd93cc84,7e873e19,b7d03eab,e368f989) -,S(2028eed7,50cc8973,c1ca2f28,a30c05c7,73e2a05a,db916825,60d41cea,3b4d0a18,40efea34,b941571e,98a0878f,a13c4efe,1e3410d8,d5166661,115cfd55,53bd0d71) -,S(ca697e9f,8954a7cf,593068b9,1078486b,c8c9a71c,d1f7a890,a0a3e0ec,e48521e0,4268dc9,28ef996b,56af66b4,2f410831,b9f8c6a0,2658d706,975a7624,6468322c) -,S(26c2615c,ebe251a8,a78b00d8,1733aa70,f8f9a97f,85c2fcb5,d9287e34,b786d4d3,ecd17c3b,e1b3232e,bde8f859,39f5158e,f8c340ef,cec4e758,cd54eb7b,df4df77f) -,S(7296b5f2,c4ac6a83,c180cc55,2fc79a84,691c50df,8e56ca8c,731ac368,2d8737f,d4410073,1f98235e,cd75e26f,d251bf8f,f93ee806,52446208,c9643fc1,1b938aaa) -,S(465d9610,c3f6c8e7,366ff5e3,9e1e17be,53ab9eb9,f299be2d,3d9dfe6f,fc601a5e,741cfef2,cd41ca9,4b847ad6,93f29e2c,7e0bef4e,6244dfd9,8e3bcbeb,8c3ae7c) -,S(d3264c87,fe435796,b4d40631,a0a64a34,570e36a9,809d98a3,7ffec23d,9f3775e4,e6fa5190,b66bd281,538787c7,40bdaad6,f37a1eb3,90b19c3d,cbc65b19,9bad22ad) -,S(d925ed62,5551d49d,151dd55b,2cde29d8,fa5dfa21,e9454c17,a834f090,7d744640,e398cb93,1c9fc1ea,d9912968,b335015d,162a04fd,c17049da,80a7ad4a,b3b21451) -,S(2f8339f7,72cc9ff5,c59ace6f,d38a13d8,21562e0,a0d5dc2b,a2c074a4,f697413f,d09d6be4,3678836c,e110e805,68a2fbb0,b87d1657,d568d7d0,e4ba1237,dbb4fa4a) -,S(f954909d,f67de727,72437ad4,d3229c50,8440d23a,9215394d,d09c7232,fa5cd0a3,6656c1b9,8e726305,644994b1,eed6234a,834f74d9,2fe16ec2,c945478e,ec53fafe) -,S(962b9348,d9b64aec,7ae38297,e80a5f80,ee1ea253,6964742,99c5196f,cd58f33e,10601c5,87838f02,5b6735c1,b711141d,ed04ed16,2fdc5bb,4dc593fe,9b804145) -,S(b70436c8,4c6e25a5,34c3c2c3,34f13350,7050b552,72a04032,84a744a8,6336efd7,1b9911f4,72a19b13,e8bad704,ad3fc911,3223a5ae,4939138f,86422536,da1009d2) -,S(8989063e,49605ac9,78705f40,cb916505,615cc465,40c4760c,db302cc7,a9e4c6a,e76c05d8,5b32b5f1,9913472a,be4322e9,ff5149e6,e224da9d,dde930c9,948ce8ca) -,S(9e2c1711,29d01e44,25e4d5a,802f4c5,84eaa0a2,2aa8fe0b,bc0aecc3,15fb00ae,b1385087,ff34618a,d126ce7c,dac3a7f5,1f0fec09,2a7a9601,b65c2786,c733fe81) -,S(3a88a3cc,164795e9,cc668d88,d9ffb6d3,52f90edd,c6b0aa5f,dba493e7,273731f7,95f0b3f8,2fc2c9c8,a25b337e,af92ca08,e17ef68,ae5abcd1,43bbf5ce,d68a1fd) -,S(f5cc5ffc,ad18ea3b,c15ed2e7,d0ee8e9a,141bcd7f,8e6fbe1f,81be287e,e7281725,ec049ad7,6ae3bc58,9a60bb7c,ae79dea4,b512fe66,bd812ec6,91fb3182,27d9a288) -,S(c8af958a,201a29a,bf880688,89c211c6,da59b59f,ffcc02db,9010bd6,65b7ccd7,3755194c,76d6e0a9,3f2424fa,f26a512d,f0605393,ecb5216e,d5f1d452,99b247f0) -,S(16f10ca2,a11493a1,361c80df,40066683,93c02635,78f11f2e,d9153dd5,5d6019d7,b9fbc23c,39323b8f,6fcfbfbc,b1a4b81f,e7eb1bb7,2855f46f,5379c68a,dc4680dc) -,S(1b218d55,81d012c,5e804030,ed342308,29675ecb,e1608d75,1ac1fb26,434744dc,8ac73d03,b888545d,dd8d0321,afe66cdb,e8dd7c6d,f1fbc3d,74f7ca46,c551f357) -,S(d16f309a,820828d5,e2d30f78,2f055428,fc8e7bb9,dcedf9c6,34640c19,7562685c,1f27768f,9a2c63f1,cda9f0f4,132f41ba,dd48a03e,5e387abc,d6c73a51,2d1b23f6) -,S(75c161ae,1b38e93e,b623305,e2566957,a277e515,44c2fe13,e02ccb8c,c72886bf,384bd613,39e4e389,5cddf7e5,b0cce8d5,35c03c29,118624c7,32b75a23,a9befea6) -,S(3327a22a,c4891ceb,2a704a19,e60d04fc,64cbb0d1,dbd5a1c7,bcb2f4b9,8a1d0d2e,1ef62067,d81d66,8a7960ea,a63832eb,5c6fe33d,3ed99147,b7f68eec,cf81551d) -,S(8c9fcb52,65eb08d2,90cc1f6c,9c3d70f0,2b553119,2a0c96c5,f59231ed,370c4036,c986a64d,f3972c00,5618cae9,4a84e74f,2566fe4f,aaa0e2b4,d3f52e9b,4acee6bb) -,S(2465bc60,19bab7e0,72bfeefd,9d974124,19bf47c3,24477dd6,c83ea3a9,e9a3f353,675034ba,c62cc0f3,afbf5027,23127859,280e2b2b,91aab521,9b48a36a,d5bcf77f) -,S(3eaaad77,af1f4e6d,a267bce9,e7095672,c44deecc,a71ec3b8,c86d8774,ad06805f,8a3277fa,6247ad67,e6aab22f,a7e7375c,b95eea16,a055ca8b,32615122,30033ff7) -,S(21734e43,c3ab4ef3,55d36330,adc76a02,7fef2658,92c29ea1,a26972fe,48c3528c,e1d82d68,612ba50f,cba70f17,3cfc17a5,d2d380c8,d62322d9,e6e93d3e,475ea6cd) -,S(d21f30a1,19f86a54,2c7d74ba,20796cbf,dc6644fa,2327392b,3aaf9f9f,ada97235,22d5e9ae,2940960f,6722d2bb,c077d9ac,aa12b5f8,b9a404a,e28224d5,5b604f6b) -,S(41741846,c3c6355b,69e39c98,fcedb9b0,73a5b526,75ef5388,819fbf5f,ce1d00aa,3978dffd,d11f4f53,ae1f5aa6,a04153d1,e9ad984d,8feffa10,9ab57fe3,f58145f7) -,S(cca0a89e,6612524b,a9c318a6,879ef971,d346e29a,4cca7c2b,4619a1a3,1f567163,8ed2e1b3,587cb5cf,37e18db,e9a95ca5,17795137,a8215cd5,293aefd4,92b74dd9) -,S(dd3be3cf,83feca12,c3dbd1af,a9166d2f,138efa4a,297c742b,778da203,dfff3728,b0a156d2,93dc289b,94abc958,f17cbdf5,94f04cba,15b71ed0,197e239,8b56976c) -,S(6c535f98,868e9ec3,31135e87,b80aae3b,a0609455,8d426bdd,3dd400e0,344a3cd2,30bb8bb3,4ccc439f,c343d3cd,ceabc511,3efd9087,d17004fc,37f70d98,94e3c04a) -,S(338bec98,1bbaacd8,8b82a53d,d1ec2ea8,aaf7fcfc,e5f502c0,a13b95b1,d5fd9000,dcda1b41,ca43c103,f0c6b294,5f9e94be,be971eb3,12f18197,b4dc795b,1efe13d3) -,S(b70accd5,24961804,40dbb087,c3c11f33,f27c7e9,886aed80,b89b121e,8d51ada9,6272d04b,3ec35419,be43ecf,72824127,ae4fd87b,640a5a4d,8e8ea05b,5f3f9b6b) -,S(dbf05f1e,b489594a,146de62e,c9423699,a7aa2d19,93919b0a,2a26b53a,a0f1a033,9608352e,a1abfc2f,47c42ed3,8f1d2ee4,bb28ce2,9dc98325,eb137acc,36924d65) -,S(56e94226,a4237f18,c57b5ffc,cfe795cc,b11522e1,fc47d549,6dfad2a7,2f109783,f137a96c,7965b8d3,2eaadbce,d86abe0c,5ee79de0,9b94bf60,8d72a4d8,8cafb542) -,S(c206cc19,28af717e,63e6e7be,781ea37e,d7dd1766,f1553fa3,2acc34ea,c1157bfe,78963ba6,f03b670d,602fdb93,d71dafc5,bb5ec7,b541b9e3,a84d42ac,1a444e29) -,S(8b579cc3,6455002c,372bf1c3,21012fbc,c29e102a,9acb149c,93c651ef,e3dee157,9fa8c521,e2f911c5,3438015f,48134dfd,66fa5acd,8916902,c1aadb94,7ceab096) -,S(3ddca5bc,e582f08f,ded36cce,395f4672,9fbfe7a2,c9aa3479,7fd2e332,352daca8,d77a9165,e281ae70,f1e9a265,630acb60,bcb79f30,9cd926b3,550b6c9b,644e5e6f) -,S(ee7c92d3,d81c3d1c,6384c771,b609de3e,e4979ce8,84df6312,fff84a0a,bd5e662,f131dacc,28415d22,729f2b70,934ef8e,3033b7b,c5a38dd9,1a11e4b1,7843978d) -,S(b9f80abf,ab86d596,521bf2d9,cf500e15,adedade8,b51fd8fe,c1d8de53,f4191222,82548186,bb97991f,1f28a93,804cd0a6,378355b,f7c7ed41,4cd585ed,af0afdab) -,S(1ab67bc1,50fcd943,f0b3419f,e5de2969,fb4428a0,b90981d1,a3893c6,18aeeae9,56fb8eb4,4671006a,805e161e,6e3f2bb6,b0199659,667967cd,3c72ba65,97a2c39c) -,S(17425974,39a91dd3,72c09b53,68d9821b,2acba5bf,a5440118,ddb5c494,fa0a807c,1b73d3d8,5eaad3c9,b37f7451,2a7ddd17,97e10e71,b640a820,181757a7,6cd27cba) -,S(72b080f4,d8e812fe,b485361b,59213f59,cd708e6f,d2f7ee71,27af3d87,971633a9,5b9c6a0f,d7a6f32e,f26a4584,542c15fd,e3504935,baa7b48a,d67848b9,67229f32) -,S(94e5f999,b8927b65,a2f4d318,8e3f2fee,229e42b9,ae3e6b46,9f7ea373,d3f11beb,aa27336,204738d3,b2a306d0,4c6efad0,2ae3a431,1da988f2,c6c1decd,b1fb3c92) -,S(2f59f652,2f045980,833c45cf,ef8f3a37,d65ed946,9b3beaac,2167eff8,142e8a03,9101d9d0,60f1a770,9f604eae,4b4243c4,6096c041,2f861106,dc4b8d1a,d9f9b170) -,S(95a443a7,22a88b70,32194130,a349a952,67b89786,e33938c9,7bef7fdb,d211b54d,3d80619,399c0975,a67ea7b8,9a5f6427,ac454278,42f54932,cbf71711,3ae460e7) -,S(c8430fa0,2ce95d35,96eef42c,69f68502,100a29c3,6ddd1f46,daca1e14,4f382d0c,f26c4baa,4a6d9711,e6de2b92,5042c6e3,cadfe60b,93d4f385,d759ec72,5a32bc21) -,S(67504cc3,ffaedcd0,c5a2704f,af1aa41b,4cf489d3,5c23b6d1,4529f4f5,c49afa03,b3858859,b3749792,4d01676c,d96fc03b,37be7b82,aee57e64,a44ba433,2fd936c0) -,S(d4fd8a19,6a56052f,71e8d51,ee3db667,7465ea90,f8449939,be9d1814,86fdb56f,7fc64dee,2bf744a5,ba155865,fb722e11,f3087010,b566182e,8a39f718,922953dc) -,S(12810eca,7f3087,944d3dd2,69baabcd,491113de,99b36ed0,65520569,484fa7ad,f25d02ff,81ed030f,1e67e002,6680a3df,3f27edd7,76155966,6f043f85,f82c9e4a) -,S(b347e0a4,102d2954,cf3ebf6b,7c0e5f88,6a823cb4,c134897e,3169b081,8bd35f4,78494910,3eaf28be,b2d9732,f88dc9a4,66a8b5fd,cc50a2b2,8b347436,2e05cc93) -,S(54cf5638,7972ba75,48dcd07f,1bcc47eb,5d99c95c,a18de15e,9d2ac40f,1435b27,48558294,410d7ed9,9fb008c2,32cc6ae5,33bffa9f,3f02f0a,76b1f390,9e78e507) -,S(e75c0831,ab9569f6,4844f67c,3650f691,e1f84366,46a28613,653c354a,3107cdb,5e2da0f6,83cf019a,82e44f84,e7bde49c,5d477f34,fcbfc3dc,2a9a2a4e,3ead0a1a) -,S(f9eb5462,7d88b64,5899b177,99257d92,4570b3fa,59fca83e,1e302f38,5c524693,dd187873,9fe69020,970609f8,ca1ff56c,3aeac075,43e6cc5b,bcf75af0,2932d516) -,S(8890093c,5bbdd22d,69c91acc,5608e19b,59d2b105,b75e054c,8e873b88,59865997,1f18b0bd,e9b546a,9a2955ad,492290c1,a041b61c,7b534e1a,bcd4db3,b5148bee) -,S(76b95d04,88c9bb7d,2cb28589,f7f3f9a,e2ae24a8,33adf557,76bc3132,4bb80168,590b3022,81649af7,bb2cb0cf,fa0e90ee,13b97294,1a7a8748,bc9ce53,88744e53) -,S(8b3526c5,afd2a987,f8a04949,bb5695da,8b073b93,d8418878,28f9d49,2a6ff4f7,387954e7,60f2ce55,17213bf9,c987a9e7,f9b9b05e,c4677911,22e7a28e,777ab4f4) -,S(2aaaa06e,244684c2,571785e,a77a76f4,2c4bca21,14fb290,ef66d150,74ff2658,49e3135a,3e8ed289,4dcf61d5,7e4cce47,815ecfe2,5bb1d8a,a5d067a7,924fcab4) -,S(981b94b,be061268,c02db0f1,fbc330b7,351d6229,b645e4d4,3d908be4,241795af,c294f8d0,7b6c70e1,c18ce6da,b3d28c4,d53f3e9d,1f8d9ba9,de18cd39,51c8ff5a) -,S(53721e95,737d09b1,49eb185a,1663999d,23429e88,51ab849,a671c0,d86efa3f,d36f27f1,9f812f8c,c9d770a4,1655ef57,efc1f126,ecfea4ac,dd5bd42b,13e20a54) -,S(9ab129e9,a4d92118,3ebf686d,97286d1c,9608003e,67b026ee,d3d06a8a,e21c0bcf,4683a375,85be92d3,331732b7,8e12f452,480a9569,4c309907,2bbb9427,602ab016) -,S(330ed8c3,3c3647e,7b80f38,f3a1865b,d33abc8,ecd4d0d3,390e8ab1,a20d1c0c,5e3db6e9,33d6d0d9,43cb4202,f9ed135d,ced588f,8742556c,2012989e,768dc770) -,S(66c40c78,6933308b,9397f3c0,3c4263f0,357d0f8,a6a9eb06,725c4c15,c226d57a,697777c7,13cf3b5a,ca964377,fb124f87,81743794,afbb1966,4b126a86,9f90bb6b) -,S(36ce2c7a,9c7f1267,c081c9b4,296a191b,951415eb,12e95b02,e5f5d3da,47809b23,ffad6d8a,e00096f3,878f54df,5cf714b9,6646b5f0,9cce0d06,ea38c558,140223e) -,S(73fefc2e,ca71a95d,2e9d5d0d,464a7408,e38e21e,4450ce8c,51ec9d6d,79b43f52,cd47ba4d,6c2ed98a,c369ccf1,a3d65e05,758f7f70,1ca87a02,5baab12f,5b765a20) -,S(cac2c00,567cd06b,d4e98e04,e911f7b8,7d4fcc19,28a5b58c,635fcb96,bc7c0a8f,fde04dd0,3235a3c8,9b304c97,7889506a,c3ef937a,e1dfce4d,ce29a1cd,dd385090) -,S(f6eb390,2654aad1,1c69c028,2d1449a3,4198e774,3d329c3e,85a8af7d,f6219e1,6403deda,8911378f,7defebc1,ef7a4ee6,20802e76,499993e,15b22e42,3e492d0c) -,S(91a7da19,ecc1a979,7d5dd222,edd74bd5,af76d200,30cc27bc,41304ef4,578d8773,a32b1a26,e77631f9,6a3dfe17,ddf16ef2,f38f4026,4d3fb882,dfb34cf1,5fee2f1f) -,S(90c3942a,7b00bc3f,7b852097,ed4590af,cef6fbe,783fd717,9fdc4955,a4fed12a,aa7d174a,8d9f1292,b8e4d9d0,19dd336e,da305ccc,ab69659f,90011b69,85366751) -,S(717c0973,ee959e19,6d11939c,acabeb83,607f9367,83dbfe6b,911f30a3,c51af3a4,f93d840e,88497801,223992dc,24dc976e,dc0b442f,2f845650,4903c9d8,338c1ce2) -,S(831f9794,c88cc5b2,2d202130,3731371d,a0ab67f3,c080cfa4,d958e6db,aa85d140,46ed65d2,1c8b5565,14e83074,e84267d8,43f47154,8774533d,cc11e6aa,cc655895) -,S(f6c7e9f6,69447c19,843ff209,72c47cf9,5341e0f9,d2d5f14e,c9b17abe,20eacdab,1bc7e847,a9f2824b,5895edf,cde746d4,5ef0fb67,b7db1637,e62d2d40,e046650f) -,S(c0ce97e7,ccec223f,947c0db2,62fe3865,9e06fc77,99a41581,7ec36642,9d5f120a,dc281020,af95986,dfafdfc6,ce122d33,e797197e,c24c09d,7e6f04a1,c5b4793f) -,S(e1eae094,f68fad14,5d905240,e79abdef,562ac20e,d52f3503,db34b2db,d2f72d43,71e4754f,ca9df5ef,b3b86c88,7e3eba7a,33554a83,cd68ebed,f6dcdea7,fecc6486) -,S(acaa286,bfd582c2,c938ee36,23a20db7,5cb6f0d4,95419f33,b0b35f2,59841bad,c3eea949,18a16138,caecb54e,ac03b6c9,282006f7,14d4b024,2bad29e9,aea7f667) -,S(87f6893c,137f60ad,22a5d543,2dc2cb2f,f2e05fac,d643839,38936c2d,206afc82,f6bc3092,1de852d4,4894d318,aaff9243,a9a521e,501ca78f,c7baa82a,3a118ed4) -,S(9df94d49,e9508ab5,63ea1,16cc4502,aeed0bb,7b1db426,c6695da5,8da1f59d,51786cb4,a7caea66,39546ae7,5826dcb2,5abc5a76,402fbe9,b32432cc,aa48adc1) -,S(8a902a14,5ecfe343,503f46c9,71693677,80499405,5df02c32,9446a373,e34777e3,fdfaf856,f777d30c,24ce54f9,d503fc8e,a3cdef47,e292ec5f,f98d6449,a69b3f0a) -,S(ad6128cb,8d9903d4,23558eb2,23fa580d,e31c454c,d3985ac2,6a2854c,733c05c9,9b69c9e1,564c9271,5562d4cb,fc040495,6ca539c9,691e2f02,5f41151,ca6667e2) -,S(c2a2ff9f,6d064f4d,551cae44,f726a8cc,b14c9742,96725620,1d01581e,5375e57b,ae53fd93,fc405150,3d6cf2bd,bb51720e,7555cb24,ef7ee8bb,9ca306a0,59563e65) -,S(56c0fc7d,c2ae8f26,4e132fb9,3a52a634,2b80dd38,f329fe9d,1871e2c1,6529996b,5d012467,cd511264,82399d80,c7f8d248,d9267251,e4d18aef,ccb9bbcf,d854414f) -,S(2131bb4c,5014e751,ef0690bd,562ad29c,d8db4461,9eda575c,9f0f75c2,da4e0f32,7bbb234f,7a83afa6,47599f05,8ab8f5d2,83f1f02a,8f8d5292,15c7cdc4,71f03fef) -,S(e8adbaa7,bb0542a9,9b9f7598,59637f1a,cb734257,13247db4,540b8268,6c14a462,72de1317,fb5ed43d,ec57ebf3,dbec4eca,bef50923,a4743359,72aee4b3,c03190f6) -,S(827e8e05,2a084162,19c8894f,ec6f31c1,a7902792,a1e8cdce,6fa5f732,4b428417,d46d9c86,4fb85e09,81bd40b,b6c3a563,8a74c222,6e7c8299,3ef6b408,4aaff5b1) -,S(3dca9759,338dc06a,8e81218,4c14c82d,3fffc50a,6d0125d1,1af0523e,d14fd699,e6c98f39,b3fd3ca7,66ac5444,be93fe24,3085a38,7b484f28,da571afd,4b8ba210) -,S(3ceb28d2,e59d3692,63432323,c36bd680,f531697d,c33245aa,bc7c5838,52bb8eb1,d2456980,96a36ca1,7301778f,d1661743,f43ed9af,3968e4e7,55ab39a1,6ded2d19) -,S(47ce6c4d,c1dc8371,de44ee1c,828e4b3c,6ba040c6,8dab0802,417ecc31,1e7d79ce,2d6b7bc7,c43e478,6df00ca9,75268b3,39f0ad68,7b0c70c9,ca857913,485419e6) -,S(ad6387f,fde71126,d0784af6,fc8a1ca7,be9bfee6,176245cc,2a18c9c1,c17f156,3233a7a,d7d50605,8cb63aa9,becf9eb2,bf8fa88c,afb2ce9d,a9236736,803dda1a) -,S(8c9c591f,e2afc468,4b64d9c,44b92627,e70babb1,aa9f7f00,6dd5b0ba,4ae794b5,5ed4c9cf,30c7d1f1,ab31e9eb,8d20fd16,77b67152,44db075c,c9de1b49,58607617) -,S(2d601d55,1b07c8bd,10db6a9f,516882b3,1525d819,9df56324,cef2c40c,6753ef7e,d32e4bd8,eeb642a4,38a9493a,87824f86,6731bcf1,6c4b1f42,240f07fe,ff075a2e) -,S(2c67af99,3de02d6c,b9db16fb,7fa99fd3,6e32aff3,69e855b3,581af5bd,cf8f81bc,69fc1c49,501a76b6,e21abdc0,27aca6b,a062dc11,5cfdeebc,b8b98ea,ae35d935) -,S(a904b9b9,a0abbb60,4be04958,74b0bf72,5c1c21fc,1ad75b9f,99ed5d60,d1beaa3c,a2cc5370,58dcb26,6677e730,449cafa1,c0135179,4afa24e5,47b10479,a2590069) -,S(bafa5456,e50152d3,115d40f,b9571d79,7ae8fa48,97801c13,238d8b98,b919302d,8108653b,f4f9bb59,de7e26d8,55f72103,20eeb48e,9f127778,5f05ed34,3e63ac43) -,S(fce057b,560e9da2,7621d46f,bb709275,4a6793fa,eedfcd7f,9a782aae,e35cd9a1,c59891ce,d7c19c5e,7a841620,8d0d819,c8634bbd,2466ed60,214a726a,dbefd784) -,S(b8dd80d9,6b6229fd,d13dac50,23f53657,3b353efa,45016033,58a9bcfc,ab61fe7f,a72beda2,c2cefe01,eaf1ceea,714b538d,8b052eac,3df84158,dd3530f8,9c5bcd25) -,S(c676cd53,7366b97d,9a056e87,2bec47df,e2c35e88,947275b0,53212536,a6231c5,9d5fe80f,763e202e,6919c760,bc96c732,844c4c18,7e7a3a1a,a0760c29,80c076af) -,S(626a28b9,c897481,19d6c4b0,bab6e81b,9d6747cc,6c49521e,6f032f50,36c9fa87,f8373b3c,748231d,b8aaf580,90898566,27b112f5,6697b18b,3cd6a73a,16f2203a) -,S(d72eae41,548363f7,cf5b5b9e,ab73076d,650f7616,e7584fd5,1a5ff2a8,ce1959b0,c867515b,46c9973b,53498582,5bebdc1a,54181a33,74b507e1,f0aa21d0,7a6c0e0f) -,S(6e34489a,4ca57c6b,f3b8a98,dac3b2a2,995a7bd,f90acac3,b81d56d7,678920ea,efe88e16,e60cdf2c,3e6a07a0,ad323e7,ff9e731b,26f9cac7,87bf43f1,b3401169) -,S(a8214f4f,1ab2d150,b66eb9e6,f64ea4f4,6ae08909,9248663d,8491cd2e,90a56ae7,5d252b54,ec694068,a0944f8d,4e0ead5f,2cf0982f,3981240,5165b5a7,e4d628fb) -,S(76591c34,fdb90d13,14c5f85,e76e18c3,aff3aceb,4385011c,d4a74bc,b36f775d,f13c54f9,c32fcde6,94d29b12,f2a8d8fb,a99d19be,80ed9a8f,903b33c1,ae52a447) -,S(17d22fdc,c48ec732,afd7bf62,7fd09d22,d2989437,a8ce1950,3acc99f,ef2c0cf9,3bf80fed,48c4c2f2,f25ccee1,9a717067,976f108e,b1cee625,1fb6257d,f1788384) -,S(2ffd19a7,f46bc028,9b11d7d8,2b391091,e08202cd,95c7a4f6,fc351713,d3645b6a,807ee1d7,af310183,fa9edc73,4c098b90,5b0d4021,6c19b797,1429725a,5763d01b) -,S(63496320,c4eaa16d,ca4ed516,bcbae7cb,124af3ef,10969329,dfec9a92,22f143ab,3ce522ae,ffd08245,d5dd6ce0,17ea6915,aece97b9,9314d61e,2d4e9fbb,5b92406e) -,S(685a372c,ead446b,6f8797c6,dbbdf442,e337a200,1b09c03a,84dd523f,674c1e31,9436ad88,7c61bd79,d0a73f9d,1d06ca0b,37f19511,9d9f9f10,6a6d6d97,f0654d96) -,S(d1aa115d,ebf2ca79,61b1a13a,9f8f2f38,8367280b,c36f6208,15cab71,d235b866,9dffc173,6590390d,a2f3239c,f85ac4c5,3e842aa1,3ba035ac,2824a269,c7c2a487) -,S(d12c58f,5e20c6de,34a27270,d29ed5ce,c2a36ac0,8f2a1b1b,69cdf2a5,d501bc3c,cf7bd006,5bedb875,bef1861a,335457ad,66042a17,c9249006,60ee461c,db0a7de6) -,S(95d9af48,d2d3ad22,4ca83889,2d7f14a0,bb4770d0,42ecca6c,d71b9278,79e69898,39e47d1f,6acf9570,5755c560,22a8faa2,e961b25e,c5ca36e6,3a5ecf5a,e54a48d1) -,S(6e4dac4d,1b6d8404,e84152ad,f5d49de8,d269c9dd,1c66136c,65b8f78,5cffec16,62d1dd58,22c06f57,f2ccefca,31c318d1,175a3c60,2aad99f2,e5c63e2b,c8e33afd) -,S(d026e847,3e8eec4b,d9ffb21d,49c13900,34a9a66d,5423174a,40c8b4b3,4f6fe060,682d65fa,cbb29cc0,91a290e9,305e4615,5a5d472e,16d37c7f,e06a9a40,f578c58d) -,S(683bda54,87643e28,8799658,baee6ec4,73ca9c66,4a76c302,b26f5762,877e766a,d3d80b37,117d6b18,c04174aa,2aba0774,43fbb78a,2649eb38,e5798935,75fa237a) -,S(fe2f54a1,830a0d86,ba30acd7,d208f6c7,22e2deda,4e554a5a,533e8e07,dfc76f8f,6a6f032b,5bb03b33,3b28e6bb,30b2b04,305e0aac,cf53e2b,53f215ac,2f1ab8e4) -,S(2486b52c,511b2499,7ef5d49f,8098f596,568fbd0b,756334b5,d5f01852,191d677,ef82dd7f,9dd36f42,55b75292,40af86da,bbbdeccd,6ebb3197,11fb3432,236f5ccc) -,S(c6fe27cc,79f316ca,5a59acd5,911963e3,bd6ae911,c50bfa1a,f2ae8b6d,69ff8ef,70aa6fed,ba4c57ee,5b3b33ec,ab6efe75,e05b8b43,41c3a7b9,bca5053c,40292101) -,S(be4ff208,8334d043,2d35c9f3,806e516d,fae58bbc,d2f69565,ec461006,99af2be2,49de6b17,c8636af4,25ed00f4,228ecdb0,4208d18e,b5c9c194,d6714550,26396adc) -,S(c5789253,316faa6c,2f87f888,a8fa4312,42618ebb,37a5184e,29abf20a,e6b4aea4,77647e3a,e083159f,afe92726,6c60f666,12e4fd31,ace116a5,11678291,185df958) -,S(27d2c091,b2212a3c,b2a827d0,951a4bea,6994953a,cbfff146,cac83f20,f164ffd7,e9fb5899,d757055d,f0e273ef,c38cf691,e958c6e3,943aae43,85f77a14,8189eb92) -,S(94d45ebc,ce92d10a,3294114d,743db35a,8e2ddb7b,7f5bee72,7d093c89,15d98d45,802386db,bd731bbc,5dc793e4,88fcf20d,15be9024,b94d1d19,edf99ea5,ab1c0acd) -,S(46739c9f,6245639b,692a68bb,8587499c,43184d0c,f0ff467,7b264985,b4a2fb62,9f8f41d7,2eb951ff,17d4517a,3fe7dfed,556aeec6,be518188,8c39a57c,913f7da4) -,S(5c9f57b1,baacb2f,67f1bdb5,3fc85aa9,3293a2d9,d85d1f2f,f62ff40e,d26e8c30,6bcc8a89,7ebf12b7,2f397b5d,ba072f3,c91f413f,df14e441,ae2a2155,887c1527) -,S(9ccb3d34,4c813c15,e9b85517,95ddb04d,c3c790a3,a1ae051b,60202b56,b735f3fe,e24525a9,fa784ee6,2576fa15,6ad350b9,eb5802f6,e5d5bbbc,7f4217e8,73f85916) -,S(f0826eec,162f343e,4cd7e135,df33219b,507876ef,5d29fa13,d8fa2326,3e7ca425,649c1d78,6547e29b,d266f2b3,cb70b823,8e71d198,6791fb09,a19ee4fc,1823e02f) -,S(8b672a2e,1b76096c,80b87519,10b6a09e,1b7204e3,ec139cea,46aabe84,4302dfa7,33f05056,ab88de5,e036f8e8,5bcd51f5,423ef431,4faa1015,7eacfd8a,9db71787) -,S(93cb8f71,9db52708,986fcbc6,26679315,fe79d119,9f8abffc,5c02f375,8e5a50e7,ed7d055d,91843e32,4193d866,81551f5b,36b484d1,f0dd5fec,f59e51ba,57b93bed) -,S(da506843,86019984,4004a723,7ae11605,a7132e86,55145d8f,ce9e0e50,feef7d5d,260f6393,886e1b8a,93986894,a4a98fa2,61771a46,16d04ebe,baf8bc48,29816d53) -,S(2d469c5f,26610e4,6bfe1cc9,43cfe267,e1bd0a22,e451aeb3,e74f17b,b9ec2f76,1d702b5f,fe2101cd,f5a5cdc8,4d4a4890,6720ac6f,ca626979,d942c218,163474a2) -,S(1ea83777,5513ab9,cadd3b53,66cd9049,da1b01c5,d347f7b1,c8a74f6f,658cd621,b9e312c7,2dee3d7e,d6e67596,70c65bca,5bec92a,2eb82fab,a122ffde,5b1c7f5) -,S(70bb25c7,9589530e,f129166f,cac1d5d0,81083ed5,fc5b9b99,e744585a,1d6b6816,63234c19,dad2914,3e99ff95,a906a5f7,a48b3e87,2d45436c,8d987baf,a93b3588) -,S(fd9989c8,f68537ea,a3248b19,ae721256,ba8d0d2f,d825980f,f89bb158,a700f0a0,eb76c5d4,93e52d45,5d27a12f,fcdba859,664bb048,1686e67c,e79e40c2,e0160c97) -,S(f1c32c17,8b36e837,b058e9ab,ed3c65a7,e2c76397,4936a524,838a480d,b3089b7,dd4101fb,92488a78,480cb6af,6cf73dec,5aac619f,3bb42594,c3dbef4e,cc7a3a11) -,S(842d8101,ed396c79,b5b19779,c245dbdb,b1ecba7,9ad77d5d,f78fedce,f9d83f33,6fe77300,9117a404,f4b28ef2,57441145,c5afc6ae,2e655ecd,2497486a,fb1ebc16) -,S(6e9e1a2e,847fb133,cc92a79f,767a5ea8,cac887a3,16903a98,f3ea86ad,3e8cf24f,d71de5dc,12be0a35,b996d880,8442fdfe,4a6cd810,7fe29548,da99783d,9049ce3d) -,S(f6739fd0,1f5429d,27c216fb,2b02d871,7028366f,7af115d1,e154f87a,812b5e37,15186c87,f776c8a0,3532b554,1e1b583a,5a465334,45bcf93e,dcf539b,21663c95) -,S(c3acbd98,43bbbd8c,68f153d8,553a81c2,81dbc584,42edb9d0,e51d056f,2b80e2f2,8397a220,483081ec,ea7de090,5d063412,1dfbcc32,ce70379e,c58b33b3,20f39d25) -,S(aa9c8bec,c845e691,a4c3daaf,a9bf687c,ad733290,32abe151,a26c2a27,1fb94732,b82dd0fb,c53fa616,74b684f9,7da10e8b,77f1f7e7,388007d6,656988df,e18df322) -,S(3df35629,654d5b70,db9547b7,5373efd7,e1781dac,da11607f,e4f3c903,5493c8a7,56fbe92b,25cbc615,96f2cd4,10290da,239ec3d9,360b3561,4199b006,c2d2b54) -,S(bcc8b337,98973e00,771a1955,89165cff,83870f8b,a897b8da,84c1bfb7,57168bb9,483a7f4a,70c8250f,62105842,310ed427,168382a2,5d687290,d54e65c4,c83bb16) -,S(bd2b07e,a84da89e,bf5e39f4,d3f03df8,658061fd,8f78d5cb,99f488a3,e992b870,33ae1dde,77c5b467,f5b3da9b,c71a6557,b0cb3aaf,892d0e76,d9f34b40,1fe60c9d) -,S(2c55718b,87b4facb,8ba9a6d,287a2db7,1b5a03cd,c7d933d4,c6014232,ec35d05a,aab1de0a,d8e3f72a,ae822bdf,f3ff70bc,bc5aa56f,1dcc5352,d1f81614,f3f461dd) -,S(eb837dc3,b2e346c2,aba58441,8c84b20,d144f93f,841180f0,860f7280,a7ee23e,6a342fb8,38a63813,e279d1c6,94b2ed26,79c3dd21,652d5678,5f47aed1,5230137b) -,S(827719c6,9b097381,da18519,ecefa193,9a9eba18,189092f4,89bde77d,33046fb1,e73b0e1d,76e40777,4ee6fbf5,2bafe516,f6d94fa7,c7dd1eee,b3c36f7f,6429dd3c) -,S(2b0da4f1,23095370,1f1b9444,847ab289,5cbfecb5,800f2d7c,16e7a56b,c6988d2,fa8b4d9e,5da41962,68e10a3a,7d69b1ca,7963d4d8,cbb5fc1c,83239212,dbc340fc) -,S(95744eb5,13436e2e,877fb0a5,20d5f1e2,1e1ab59e,15bbaf46,206550f8,d5563134,5fb1c034,62040ef2,28adad1e,83fc2c74,57344c38,7b7ffde0,d247bd35,6b5ed1af) -,S(4c805d94,78793e63,4833e90d,d19822a0,ab7d263b,1ab67654,bb77358c,67b327c8,863cb8f0,dbca3c1e,4011928,e5827619,53df792d,449f8980,bd10cef4,472ab56b) -,S(fac22633,3ffa2cc8,93c434b,46fb0cbb,cdee765f,e848cb50,b1dd6e70,272e0ec3,6a6b07ed,46f9b9c0,86e970b1,d2323fa5,d7d66b0e,3ad3077e,da5766ca,ac5b500e) -,S(b9d6af71,c59f0fed,ca4ecc31,25aaa645,f78d43eb,79c22034,1034de56,f59ec4ef,5509e17e,3d7ea457,c428e10a,7e9d8bd6,69f0fdc1,165169bd,a2101d8f,6f4041b8) -,S(57a68137,90725717,2dcd8c46,3a9b274,69c5ef27,2ae2be60,b10b96e8,e6b47537,9f294700,1c04c06f,2e2e5aca,cf4b9549,265db1f5,74b2328,ef4469b0,1c2bcb98) -,S(58ee2a22,9aba401a,637c4d34,2b1ef408,d9f47c53,6133fcc1,de030d00,25e2f53c,d361b0e5,5ef24c74,94cb9e65,cd273e9e,73da6e50,f452f8b1,7d30eadf,32ceabc0) -,S(b8bae4e3,f2e22824,7ac9cd8c,a68632e5,1bb13d4d,735fabb7,305a8169,31b0e34d,ae8ed4e8,6ac41b60,60ca3423,fe6bffcf,a7f215a4,7076f270,a2d1017b,887b8002) -,S(a81d5e0,f11549c1,373b4c02,a61c8908,dd109f4e,7f0cd250,a667508b,aea3feab,8c6cd790,4cb4bc0f,7e56d928,ac362cdb,f096841b,dee9dd48,429c52e7,23511bc1) -,S(fea67ebf,f8f092fb,dbb3110b,77d6981,efaab5c4,97a23c3,42afe294,64f4746b,1dc947e2,94b0fd7f,952a6d5e,1f5ddc9,5f0acde4,de8db93e,41f37ec8,965d4310) -,S(4db2ae8e,6b8e674f,2d79e1a2,fb7c7d10,921c9280,d8eff92a,df1a2b02,4485bffc,8ed56cea,38c2a96f,b6e0ecf3,22b745cb,35c43313,9b3dd28d,9189a9c8,9f2c055d) -,S(be31fba,3995348a,78303047,24ff117a,48dcf5e8,72356d03,ac059306,fc5ae314,8bf72f6b,70189284,ecf86059,affb4a2b,c7b5f923,d7c34429,6f401490,5a94061d) -,S(e8d716d7,18078be7,78535c20,4f9cb681,e8f49ac1,85baf865,e7b78e19,58ee703,2c79f768,c6d3bb3d,b0923d19,74647e8a,966ce69f,d06a8fe7,5601e51,61f49f85) -,S(20ae34f7,f3497d67,6b0496fa,1a68178a,f4fdd57d,15131ab9,c60bedbb,1a840070,21fc951a,2b29ab95,994cd404,b3da37f7,d21fa790,820339df,84f17b50,3572edce) -,S(73db09f1,3c8e7bb4,48629f24,83d56f1d,a207617f,454edbd9,d51ce59f,b7ae1ec9,1e4e5175,efe03956,cce3f160,791595ad,35bea993,139e8967,f591b973,785dc29f) -,S(14f5ae1f,af20b6af,9953fe91,db5bc192,31f302e6,cc03a265,d661b25f,8f07cb18,b790b1d5,ef6ad5ef,97ddb309,354756e,138f4db3,208a873c,17cff3a3,13a8be2) -,S(94ec6992,d2531cdf,3a1002cd,efb12e68,868be66,b704dc26,3dd422b9,9cc379ec,d2c4e479,ce9e0227,4d9175dd,e2a42639,67ed377e,d0416101,7e41e8bc,8adf7fe3) -,S(f73b5edf,c8d60e77,328279af,ae99381f,4ce0de22,17a4edd6,4c228b4,84816527,86758bc6,f44e1204,68555e71,786f7d50,da7f9c72,665a7475,e77c32e9,dcb13419) -,S(94b51939,45a518e7,c602570f,863902b4,385c8e76,c335cae1,b80e1d0c,e118b573,7c285008,4d398cfa,24c5cc6d,879868f4,d8eb60ad,ffc77214,5debabc1,3f154ea2) -,S(26acc055,2fa90d45,1dd6f2a3,9bd46a9b,99b0f66f,3e6e72c3,16e09e52,f7b265b,997dd988,5d5b15a1,957e1cc0,a45518fb,b0e1f847,d58fe9de,9be95273,cbe61b00) -,S(e8a5ac01,959edc90,2050922f,af51365b,ecebc967,8e57cac,420faa6d,4e2fce98,2c2998c6,fdd97d15,fd0cd228,e9975064,f2576316,6e61a45e,ae532481,9dd96227) -,S(d903bdf2,5ce9e855,60f63d72,512626fc,fee11c4e,304d249e,e13a4b69,60f95019,1027435d,bab3c246,c93897bf,ef7779f8,9a165595,a7c9c536,176fec9,1adb645f) -,S(eea105c6,fc04a751,cdc27e40,25f0d50a,99f8d01e,1110a505,eb95206,922e50fc,b93db8cd,b914dd8f,2b57b907,4df41e9a,d8cca9e9,c3a9754b,e8473446,ef3a6c68) -,S(801b116a,1fc2c2d8,fc8b412f,e9b1b7eb,b19f4e96,16b420ce,16f1b4b8,dad235f0,53def02d,8a6deddc,250de95b,d6a96d27,1c197d36,e137e640,4123501c,15fbaa9d) -,S(db3b8667,1b0dc54,436520fa,c8d437cb,7a4c23b6,bb3c3cbf,dd34b605,af406939,36562d35,a298b620,f7a06498,b1032f4a,33cc3b3,ee185e0e,aa8d3e4f,3ec5c481) -,S(7bb26eab,8b808402,a9fb3fa3,8f0e2f6a,7d82d7c7,eef75cec,43594713,dbc17706,f4f86283,713738b2,a9209e49,f82ae1bd,9bcc908e,b9565546,3a8a5dd,8d0c4b9c) -,S(e89fe301,8d87bdae,20fee2ec,7a3f6cd6,cf932d20,a026e1bb,a82f9c63,a47b97d9,92a7e80e,e7657ad7,c72f471,8f0c28ba,acfc748d,a6090026,1191912d,32b8a498) -,S(c9a10a8b,14d1845d,be6eb6a8,65cd2ce3,a4d0be4d,fad24912,b01fed8f,8bc812da,5852b791,85afd22a,6f9ab486,91340dfc,e9979cf0,bc9732b3,637434a2,25001d71) -,S(257df2e8,cf535cb7,954b52dd,7e3ee08d,24cd4415,d1075dba,8f75bf74,74afad3f,f72d1e76,d4da3c0e,5b41fa82,28639f2a,f4e114c4,94073ddc,3e8fb2aa,f82596b7) -,S(3c64aa9e,548a430f,a815bd54,713ed69d,bc32a0a1,30ae7ca4,1541ff21,a5314886,8377911,7426e30b,dbf84c57,b110cc3f,df5acc95,7313cbc9,86e895d,6e0ec912) -,S(cd509f83,3b65a7f9,671b9239,c5e71323,f183e956,2c2c115b,751046a2,33424ee9,579243a,c7fbd433,81cbd0fc,4330d087,cfe0c41e,449ef82e,12def6d9,8977338f) -,S(27adfe4,febc3501,3ca7a0a0,b5f7e525,3768df69,9d236f63,9ab80782,c2d426f0,97cb4e7b,73b065a2,499a1675,88fc116,be5606f,80619d42,ddb63286,4d20521) -,S(ef5bb148,98dd6802,6f25c363,16a34acc,c6131851,a4efe8af,219fcbf4,13a45207,49f30d08,291e60f0,975c93ec,403d2a14,3742aaeb,3777cb9,87ff38ec,b51967af) -,S(58df8d45,955e923,ec7fc327,f8081ec3,7ca6e261,7fdf7785,6eed51dc,95057034,cdfca79c,92dfe719,2ec63f6f,f93d211b,d7cdcf69,4deac173,d3393fd3,7655a310) -,S(2a4ca8d3,fff5ac47,bce452f0,1587a769,443e66c0,164558b6,301a6a2b,d3d44270,ed73b405,521274a2,3abe589d,c5ecd607,b6467691,f81e3c9e,6a2096db,2ec82366) -,S(84bafd1c,7c6072cd,fce244c4,8ea004ad,9b8e1765,bb8796d9,118d6dcf,a5ac58ce,86ab8db1,7c26c921,604a3c3f,f0155a2d,14bd7274,16f9e319,efb68f50,2b636c00) -,S(c3785528,7cc4e3df,f5e95951,c5bc5964,28705a12,10927e89,890726a2,ce00b657,302ebd13,5643eb43,f0bd14c3,65e385a4,c9a177f,96595054,3c3d96db,69ee8f79) -,S(c3aa3cae,efa22927,56c72aa,53507474,50f7a64e,2df1bf64,333d0402,5dc87d25,c2eed94d,ff9c5cac,248f77bb,9e189302,286db019,64214d71,1a199119,4818ac4e) -,S(443b9c8c,7d8c4f7e,de7168fd,666e79,5da85e6d,6c0f6448,7d349de7,66acff4f,2d4f1d59,b0d1688c,9fff0f2,f80e3434,db72d76e,6ff886f0,63dd63fd,e192b01e) -,S(2afe7ea8,688081e5,ee8a4ae9,87aec6d2,ede5ec3b,ca887bbc,1461709c,bfc6e5d9,5c319df3,2556ffc2,56194b7d,eb46dcee,59208922,1e55c384,2a03ddd8,78add90b) -,S(c62004ce,4d82ee0c,e2edb82c,e0ca98fd,413bbf44,55b96624,a86aa252,c346af6c,b68e4fb6,88f78331,bc2218f7,6a5e43f1,cac49fe3,4c5302cc,d6a3f1a3,258564c9) -,S(f759c4c6,e0bd72a3,9aabbb17,fc62c900,d57e0b5d,ab9ecce6,8f439025,2b17cd1e,6dfaaff8,5f9f3990,ad2c55f1,3c74e3aa,aa0f10b2,90def714,229cd3da,d5d18d98) -,S(b527a6a9,d27d0a1d,5adfc1c1,35308e5b,9a805638,132f61d7,e5e60709,ac3a9d9,e387f69,62ad151a,d920c82a,739af00f,628865ad,4ca42405,efd87e89,55b91042) -,S(ba23656a,6b0a5c57,f9a00d6a,9e6a331e,cf0c8097,3675f41c,7f0172fb,caf4eb02,b48ac68f,1a108de9,18d76d4,95a811c2,b7614aac,3c5f6b18,f28de8cc,7bd4041b) -,S(ad94ec6,fa161fd1,60dea3b3,2c63a480,9f7bbb91,49de206d,8cc61306,dbd18aa8,5240858c,ec88a022,7c1c12a7,862b4d18,e5acb344,5d66bf85,79ff9fc,ba866a4e) -,S(db4cc48a,de1bff28,c8987eb4,d00e1c5c,4c49fa6f,125d213d,bd814c34,cb81adc2,ffd64cf7,3c62c097,a2cb3b84,c62bc32c,54fce797,74479146,7b9a2cb5,d6f821dc) -,S(27d276df,fa39d889,beb0b586,42a0e479,8057760f,c392d052,6751f2bf,d0c75aed,c670b966,575401a2,a790440b,e5e5db56,2914aa74,e8304e3a,407aadc5,c87e12d8) -,S(7663e9d8,e34b525,b336587,eba3678f,488f95f0,6e9a6848,d2e72d35,36b569da,472b1c5a,8ee189f0,7a06addb,e6a8d90c,dcb87039,aa35e896,79143547,34e2786d) -,S(b2c81e15,1c1f8ef6,51ea1810,97eaa280,7e3b4a96,fbe210eb,b49554ad,6e0c0c4f,2d914319,f5ff59f8,c7038de7,dc70d1fd,6c4434ca,e5c0451f,4fa99f46,55bf8e4c) -,S(25131e21,9406fae4,ab96326c,7bf22892,1f18aa90,c52f46fe,b23f90ac,59ca570f,2e8a380c,eed5d51,6c190251,4937aa0b,1f39d3e4,42ab2537,e9e8d9aa,396e4c20) -,S(c2694b68,8e33025c,fb9929a8,c7ccd1c4,7fc5811b,9658ecb0,f41e4558,5d9a0c3e,c443d593,e68abc49,cbaa92b1,757ab2ab,c30671d8,4699a5c4,85a30b05,6b1ca701) -,S(8d528cc5,17a371bd,9605d8f4,e7f030fd,8a82d489,5bfffb9e,fb11f63b,be534fd7,ef2f16fe,64ceab2a,d261bd1b,314ebc65,4b4127b8,643466a8,f367b991,d28795d) -,S(409e69c7,62f856a2,4b6e80aa,baec8496,33b75c21,8943dbd,7280bf,e917b032,7f049016,62884d22,dfbda29a,c8061b7e,b82eb94c,13d7efcb,77531f8f,980babdd) -,S(82c9b4b0,2451fde7,8ae877c,ed9af540,1ec0e258,119e27d4,1938f71d,ebae71c8,212d6e4,99b91fd6,372db1a9,4ce3fd9,c5443b7e,fb37a566,f0c5f54b,fd8edae8) -,S(6c9fd728,37a39ae7,1f0b5852,e5c09d7d,cde66ec,e8f19a2f,2ab46fdd,d17c7f88,430d3385,aac729f3,8ef5ed,922e709a,73df8e70,eb9cdb83,c41e5958,272e8687) -,S(9f012582,e527901f,ad1f350e,1a64702a,ca1f6670,e693bea8,fc3eb0fc,2c090329,a2fa07ae,c15e9457,b2c75e50,56c79a6e,a4c8f431,d3c720f0,60f7b5b6,da6e3dfb) -,S(6a1a49b0,7b2b61d6,474834e9,953aa455,63910582,57db16bb,406b600d,bb01300,d4b93b7f,66ace505,cbbc2326,ddfa2fa4,ebab145c,ffbdc2c0,606e2ffa,9dbb41f4) -,S(981d0638,a585970d,4b12e577,95e76c26,1e10d65c,c5a94f19,43560d10,472fc9c8,f9babd66,3d02e030,1fc0ed0f,75cdaf94,fafc18ad,2cc68db6,d2eff7ca,e6c013bb) -,S(7edb47d2,b6295063,6cdda3d7,169b4296,3616b6dd,79e2e148,609a7722,476e564d,179a20ac,a6deb286,76fd466f,be78c3b6,789d31b4,91622149,4d7d634,d4bba999) -,S(51867800,4bd8a43,8f180cdd,efa17ff6,e16e29e1,e5fc4ef3,f5fb9bd0,bbf14ae3,306cc2c8,60ae5871,8632f94,c9acb7,321ba1f3,5092a0b5,72c33b9a,cd8cc956) -,S(bade1926,d8b0d136,69e056ea,ea46b2c8,2bf0f0f9,a25bc481,8a40ca8e,201500aa,7ac76679,c9807217,ee802773,dde582b5,6f0a4b66,f6e21764,285a6a81,4d584502) -,S(87815e7c,d1e5e88e,eb882b23,955de59a,d63f14fd,457a8d96,4b47a611,b3e40043,ca82343d,8e2eff9e,314ababb,15cd03c9,6fe6660c,421af876,63500d49,ade0d492) -,S(77d815d8,886cbf43,c1b4ce94,253e93ef,767bacc2,42ba7c1f,bfb7ffa5,308d855a,a8bb3f95,37ef9a77,ad7e282f,8ae05ab1,8131e59b,46a67c3c,7e85ca00,a2d3e1fb) -,S(49079a0a,7d9d9add,3a17ea11,747c8baa,d0922a7a,e766e5e3,fb80ae0f,dbb7d6a9,162b4e23,58f03e01,b4e09264,8cd0657c,f2cdcf54,f6c25d5e,fe7330ce,421e0093) -,S(28d61211,c183ccc,2b08168,5a4487d1,57bc0714,d3ffb16e,96bf0768,ff8075da,3da98c13,a2d1b07,2ddda165,3fb68a21,aad4a9fe,b4536dc1,507dd78b,7e51e0a8) -,S(40c34a4b,6196561a,d4591c49,df51b8e0,4106e545,26092e88,72018720,41448080,7a6e7478,3ce7d82f,b83f15e0,b74ae6d4,435593a1,67da6f57,f2e285fa,8c107e4f) -,S(88754e6a,e12e77ec,21e64cc2,bfaee207,f5c882df,80c8b15e,983fb1aa,99037c2d,5ae10e7c,e7464c69,472ce85f,5183a836,6ed5b3a9,1fb1af7b,d5078c76,2512f37c) -,S(8bb7094f,ed62beba,d628ef9a,84a0679d,7e0d2b45,a655fa3b,68d9a6ef,b24c738d,9f5370da,993a3811,48ad4da6,2d7845ce,4cc81766,f26189c,2199ca73,4312d102) -,S(79814e63,7bf2cfc1,cad39a36,b06fcc4,f7e865b3,ab2de1f0,c786f9f6,40dd80ea,aae4d149,f1e44635,e4800962,f533eb38,5f067114,3bfb87ab,9e68e27c,b56df226) -,S(d493573f,93018d4b,8599b54f,848c3afb,816e098b,8e218e2e,6304baf6,c726513,383c7ff9,b3ab6472,ecb80f72,2f70feac,7ff26989,bcb6f984,628d5eb6,a409b9ce) -,S(59599fc8,7d6a7532,5ce8f205,204596bc,4cec40b2,f3eae8ca,4530053d,1b7c731a,7a8d91e5,5d989961,889949a4,bbb71e17,84055697,b396a011,eeb33889,88f0681d) -,S(4a834ec4,da3c9afb,c62fec5e,898aa2c9,5a835e60,ef199346,3e4bf255,e32df096,8736155,ecbec836,e8d51d79,9176a5c6,6672aec9,548aa63,b7f5524f,6b20cf73) -,S(2142b447,f2707c37,45e877dc,8039161f,d222c69b,9236592c,c1b3f56a,d30a975,9a48f0a7,1ebfef1e,615a7d5,a9decf8c,70764133,88b0e57e,da554257,256e41d0) -,S(c3831b8a,eb58dd77,e21762c5,f2e88035,63fa8b1d,f5d1fab6,3d012fbd,27971797,45d1f565,6fb2779d,6ae18e96,4d9bdf61,924a5f6,a7dfbecd,2224f1c5,70292f46) -,S(a09dd11d,b78332da,663acf08,c08b3d45,d0f4740f,5df66e39,d53e6c68,f5654040,649959b5,bfdfe8cd,45fc89b1,ea21cff5,94f6083c,da8f5e5b,94525d22,3e326217) -,S(53b22e4e,8a17b408,6b119087,2b8fbc9d,fc667b40,223ecd99,27cdf4d2,a9dadaa,87eb7fdf,b9c6e23f,e7c6a8d7,fdf94438,88c6c0b7,1a3728ae,ca8e83a9,4403bbe9) -,S(7de0aeb6,d3c264c7,f39b087a,e62dfb5e,aac6fb17,483bf33e,bc34a903,f0ee35a7,43f92307,6a2205a7,f2f0737b,2167863c,43f3cec2,ea3abe32,9bba3792,6f070847) -,S(ef20ed3f,3dd1cd8e,a610f1da,64086eda,a4a646dd,e2bff224,ae72f069,f341b532,c3477d8a,a0acf4a1,e9c83a1b,c890e59a,1b739a82,55d3747c,7403034b,221fd0f3) -,S(ab21ffa5,3c7baab0,4ee74647,5a5e5800,dcae9a10,644c84f3,a108cd41,cb0dda53,3a02b102,dc21cf05,3abfe19a,2747f34a,35ec6347,ccf02880,5aa95119,110cdebb) -,S(ee8aa184,532ceae,2c3a5071,d905c6ba,bd1982cb,391151f0,fa869339,aaa50ad5,157d9d2,be135082,9eaf2c54,94e6f90f,8a82ad35,2d486dc,58068cf1,c96a421e) -,S(6b234cdf,fed7575a,f1cd7ac0,76c4251d,5853718e,2ea07c04,77959afe,5c0af2ce,223c14f3,d3d61375,d104402b,bbd51026,a7644b15,4f4d254,85e9a4a6,e8dc2831) -,S(e04eb879,7821557,a875d846,75496d9e,420ac3c8,6e718e45,347a616d,7616e836,59f33383,8354990f,2189cec8,af523611,df4a1b30,3001c5d,84e1de70,bbc6bf31) -,S(6b8c79d7,791e8423,788627b7,a99be936,145a8eed,178c8bec,affa8a2d,72965da8,28fece24,22f67bd8,a2d6ef6c,66fa51b4,c4abe766,7480b520,4f77bd8b,2e3863a8) -,S(d21a9136,eed220a9,708c09ed,2b22f5f2,87868a1d,493f6ed6,2fe9a455,42a4da0e,efb15959,cc7a2c02,7ab7f5f6,ec8a538e,91df38be,f78de45d,dabcd8ef,9b5394b) -,S(f950b37e,a5bfc8c7,a76ebefb,f228043f,de066a1b,cbb30688,b73e085b,cce1ce6a,6bc569cd,609a15d4,28ce7874,53ab8d02,fcdc9c50,c8c44016,ee2b62a4,16849616) -,S(75a72a76,520a5f29,368338ec,fba063c8,977548f3,7bbe08a2,e1ff5e97,88b9bd3e,41c140e4,5e2be58a,dee8af9b,e64cbe8b,4c82860b,98299d52,3b27737b,3266f978) -,S(4474da75,3d9c68d7,2218648,1ce835ca,4e17220d,533adb53,38a1978f,cdfbc3f9,b5e2d3c4,ae2c8276,5a337068,58e76666,52a81638,27cb6b94,3d2b80cb,36ad3eb2) -,S(e3f3e682,fd38b067,33f3e91d,585f3ef2,aaf90409,ca125479,b93039fe,3437388c,aaef5ad5,4bfddc87,f7c3f969,94564ac2,27e6d5ac,ffd345ab,246ee2d8,60d9242) -,S(140ea6a8,ad374157,396b064,f7a952f5,358ff408,951895ee,b66b6140,d969afc7,2f340af0,b08a67db,e6ea7535,581b763,24308f37,6015de2,a4dbfa64,1990cc78) -,S(257c1e04,2fcceda7,9aac2bb1,1f01bce9,37b445b2,bff51fcb,555395d2,d0c16b89,73b21d9,75bf23f1,aa0efe21,5141bad2,5a235978,e36645d,8503a60,3956cb5c) -,S(c243452d,664d2610,d1acedb6,ab5201b9,cddce44a,b9320806,4824329a,e0b7a550,50607848,db2b53c3,c9ed2b4,8c0adc28,322d2e,1b30c3df,1ab9dc37,64b001ab) -,S(a0ae37a7,3aee0e63,c0ca3e50,e59a660f,c7ced178,10dcab26,7f91ed44,3f265fe,8332d25b,94e0555c,21ebab61,cd209599,bab277d2,fb9660f1,f237c9bb,4327668c) -,S(2e4886d6,678f10a4,460b4ca4,a9964125,413a739c,64b6abb9,c44f675,1b47dca9,96f6bb70,9602de31,1be57a61,966c8227,e5dda6c0,48d3f1d3,bb5bafa,fc1e8de) -,S(855b47b,efa7dee6,2452a602,980258cc,de813ae4,6f580a46,d5d18432,5b423f8c,c27f5513,114fea7f,b5a405d2,3f25915d,775ac895,7fdc6e74,2d968bbd,d86c181f) -,S(dd360b5,38fe460f,9d6ba828,e2ac7973,46dc386,de05022f,fe48e891,a115e2ac,8fbc127c,d9e79454,a0be9bb9,cf25b7e2,71a02e7f,b4c68653,b7e08329,747cd68f) -,S(993aa6eb,47f7713e,e6c5bea8,1a65af55,1036d0eb,3df8a6f7,e091c16d,3f424c7,8478497f,a774307,d47ed357,35462f3f,a680eb87,fda11107,275c1883,e859ee34) -,S(4828feb,5e3abb4a,2df7b990,e20e1214,804ef219,4cb8acf6,cb8e85b7,5696d961,d8d2636a,6b664b15,f371ab5d,3ff31279,f7c42678,ff380ab0,9c220b02,6ecf3e3f) -,S(fb8dbd84,64bbb5b1,904a2610,2321e59d,ee9debbd,afdbe585,3e1af139,f8fc472a,54e088c0,91a67284,6c81d136,85b4edb4,391e5121,3c4d35e8,47863018,62844742) -,S(851fc8f,cf378f62,5edb262d,e0360d2c,2e9566c6,93abea8a,aec29e5c,275ecc9f,dbe6025,e9857155,83b38b7,a167adff,da70398e,85223a6d,9b940fa8,30a9d9e3) -,S(4d5d07c4,23079d83,d001c000,8c76fb6a,e03bb39e,325d5794,b5414b,46c6777c,d1c1e970,5b80fef0,8450f941,1b8d6197,21f1491e,87745c26,9458d58c,18d14678) -,S(8164d5c9,cc72b489,b6a54e8b,d9cfa9f,8496cd34,3a227a74,f37948f9,5d35340d,90b51776,9e8c68c9,20f5e948,755b4da3,2b294bd3,eae81da6,e0c0b287,ce229bf7) -,S(19a42dbb,9ff7a400,aa821c88,807281ee,ff7df5c6,e047cc51,9693c191,6145e00,369e9596,903c35a8,bb38f4d2,a74da3c3,cd2246d6,b0391e98,e01d6101,439a1018) -,S(7299deb0,a9b7bb52,76c8acae,37ba0ee7,bbfc9c0,7845765c,136cd762,7e7b7f09,8a0a1d16,f00e3090,cfd9cae,d8aed291,ebc56d97,66a131a1,4fdcf6c9,ce6b49bf) -,S(12c7adbf,112e7718,a3ec6774,1597d6e9,87763a10,4350650,e6a804fa,507ecf6c,b3eced7f,bc3073f2,5f86d647,6d822b8e,eeeab7f2,1b3263be,615517e8,ef3b1a64) -,S(b2d76aba,c1af6c6a,b4840b34,db1125c8,d5baf2be,90dc7e6a,52edbf79,a4b0ccf6,92938b87,641e0886,3f22f5ef,e27f9b18,80210d14,312ea6a1,eacaca0e,58c0f73f) -,S(818baa52,8251c326,bf545ff3,a56596b,58e0b525,64ae359a,c1d5199,4b52106a,9f8b4753,a7b56b26,e0e79b9e,9ae5f30a,64d0ce27,5898bf3,c0f12e43,faa69681) -,S(e08080aa,21c9b6ba,da128bad,62dddd3e,e8e5afc1,c460b997,45eab92b,b1663a80,2b878efb,95a19892,8b3609a1,cdbbc1ad,d1530a38,b528539a,c52fff24,2c382dcc) -,S(7a8486a4,1d774bb1,32321247,f7b87964,1b18a621,508f5376,99b31798,490f3e8,ee8c3085,5c3fa5c1,6f90b68c,89944aa8,dcb824c8,c37a0feb,ac796403,15ee96a0) -,S(f74e74f1,6e67c1f3,f5952373,e53cb85e,650a6dae,2302f495,f6882b9d,e2b71cea,1b15103c,8566d2ee,cf5c59c,dab607e4,97075e30,1443b75,42620545,2d1d2bd6) -,S(3ab4150c,cdfd6793,5f8718f0,dc961126,114a5d82,e1791c2d,48740425,8e8ba004,2a6c6f1b,9b546945,f9d327b1,437b1c58,30a48eef,6a14887a,9d8ca24c,c6bc446d) -,S(effec0ed,bb80580a,7bdf80cb,38cf775a,43b786e4,2c80d73e,7a254216,ed7ab7c9,c7c27bd9,57c996e0,42ceda33,2d0b5972,91ae5725,6df77e82,48bb1716,127c582b) -,S(5f49ea21,4d80f735,fd5f51d0,55d4e2f0,fbf0f804,a8f32615,340bd6c1,65a059e1,72e0f032,83684df0,98e740df,bcc39d61,6956ea36,275ca5ae,dbcbd682,510496ca) -,S(2327c29a,7f906,4cbfd900,43d28618,5c555bb9,bb64bab1,c3e20417,4cee2591,db1711bd,ac9095db,39e3d2f7,d2b84129,41dc6f8d,116115eb,7bfe710c,13b9e41b) -,S(12f2f427,64f77c84,f8a97c5d,7743bd8c,cd0c6132,5cd10fd1,76975a97,b447991,713e4660,cadecd98,3b0e4986,855c2c67,bc220334,2991a18c,bb0c08f6,8282b246) -,S(cdd3eb6c,b496141c,b99bde6e,a66b2c78,7264e6c8,74efdda,5ffc53e4,b3292a08,d1270d9,7cd63394,b385739f,4da31dc0,80f410a6,aee164fb,8147b7f6,9f2f1cc9) -,S(2ad4df2,1ff316e7,ce29d76c,da40cb7e,31aa7e14,49fce23b,93f0d096,e1b74159,972c77aa,160c98d6,c64dd9d1,4a0cedad,875e09b5,b0d5378a,7311cd2d,a7d641a5) -,S(df0ed61,d6c8f906,f970b9af,b4080368,2f12127b,e318575f,8e2111bd,514c33a8,e9e67c4d,7b1b0fb6,fa0a4640,62d72f,28180e6,bc8bef1d,60a1ea79,2c4f259) -,S(9572faff,160577b1,83aca01e,45d61647,7dfe147f,a6ae0b26,ca0264aa,23d2870f,b7de270f,572e1503,8a4a9b3b,706eb7c0,2a6e5e56,ab0f73ce,9f4b7926,a79c5c5) -,S(52583f1f,1d51acb9,bd25b63e,158f66b9,8e021432,427efd5b,bd629594,ba951264,3267373a,94719487,344c9af6,1eb4b726,a595bfd3,41d78b33,f3db8897,7e53427f) -,S(c95cd125,7e59d04a,6d953d7d,f68089c0,c29b6a28,90ff264f,74b469fc,af7cfa58,f5c7c7fd,82d3fd51,4031ce72,657cffd2,da83d072,9b0c4d6c,66180214,9e6ac90b) -,S(67a190df,e1a2bf4e,cc23972d,24d1f13b,803a9b4e,5c1f3cec,55d2c2c,3b0b2487,5c35f795,c29a2f07,74ded776,72ab5a7d,45902f50,e76a229a,212d580e,5edeb8c9) -,S(7ffcb588,ee9192c4,3bc5bd3b,4d0c8211,28c3f2a0,62ec3b0d,77752ada,69f468e3,9204301a,fd0ecd0d,26f49878,47c42c70,e526f7d2,e69a97f9,2aa1c357,d4140a8a) -,S(7d693f1e,6e35e062,83f35910,3c1cdd8a,5279c4ad,ed0edb63,d6c574ea,322e91d6,a9042da9,ff323c4d,46b2b40a,1d44970c,92e3cb32,ddd8dc21,d32d609,c5611888) -,S(7e0e5dae,8ce3c883,49a9ee95,fb357694,a7bd48d0,f27c2eba,49896e4a,3da04fab,a397f8ac,dd4077f9,58d7b5fe,28582bcd,4c46d1ea,fa253db5,18fe90c7,61dbaa4d) -,S(715ea4a8,e5eca76e,48605688,560872d6,7a499a8f,e84f715e,a91d724d,71fc0f06,9a7b3eda,8b82dcb4,60ba3515,18c22f59,fade0636,dc893050,a51530d,77ef8501) -,S(52a9c85c,ca99e4ca,50f5efb0,118fa604,b7e789b6,b589a5d6,368bab11,44c8dbda,3796e4e7,87dda75a,59c7503a,f27732d,8c973414,c1ea0a90,fb6cede8,a5066fa8) -,S(58f1c65d,ee5ea200,57644796,a94e4a42,771c827,fe032116,657e990,b56e42e,7f12725d,388a22e3,4f191714,9f48f0a3,3d537c8a,1037247c,de0594ea,a11de507) -,S(3ce165f6,5f569bb5,e594110e,ef91f30b,7e330586,e86cc4c8,347d1ab0,f4a8eda1,90480327,7376335,72d92c00,10313f96,9a0c5d18,c852597d,1f88020d,f69987bd) -,S(133bb4fb,1a16b008,80379e4d,ca980355,c747683,cbd7e81d,87a9eb8f,4219a314,30e76cea,f57f8b17,de6d31e,447fb926,b1678651,e980338e,8f8327d2,648ba25c) -,S(cb26bb35,4cf94461,c675838f,653c3844,24ce543f,32ed7b5,ec1b6b33,a2f7670a,d6f9be8c,7f3781ea,fc765264,c9e84f2f,6d2ff771,25b8d381,199b67c3,763c4f2e) -,S(7d944d40,58cb78ac,739b85e,6dd3be5,6b08fd56,767fd02b,1d5bba08,d4639f1a,79716d18,44baabcb,aded3600,ffa68989,45920de9,1f2cbc83,e6326ed4,e37c3fc0) -,S(c4577e42,ad4014,e1fbc0a4,d69fe37f,49937d1c,19a95765,74f2437a,d06e6589,4a76bf04,18a4a8b,af103581,b6c2cd16,727fccaf,12a3998d,52b1a095,c5388570) -,S(c71f462,9196f35a,cefd651b,3f6f2b30,485e35f3,305dc774,21535961,60a17a0f,9ff53452,52ccf823,b83d47a1,a6a70f84,b9c83142,db0136cf,d03b1f24,6ec57590) -,S(35acf6e1,cad058b6,7543eb60,ef4d896d,c21c4b5e,292c3885,d9e42cf3,85bd22be,cce4ea31,c9a37f8f,21e32a5f,6f272699,7cddc6fd,8ab11c0d,12c3ca4b,fe6b0e92) -,S(c2872bec,f2abb3fe,8a258b3c,51a2bf82,6712ec12,587cb33c,a6765a4f,e3a3e448,a739cf63,63cdf69c,15c9827a,f759e0fa,f7d92112,9bce9e18,bad86c0a,9f6bf467) -,S(50fa12eb,c3dfb3b,dbb61a16,a8b0cc6b,6e6882ae,f245360c,e5524143,27d2bfe3,873afcc9,5ed9a3e5,2f1b0515,d901e9c9,3677d49,4e64a478,11ec59c4,c3374393) -,S(3ff1688d,65cc134e,c6f27fa2,eba78abb,2cf22eeb,57163e2a,150ed7aa,17b3640b,ec8f8f66,11d8f7ed,a296e690,63b3393e,58d8bf85,90630da7,3dc2c0ec,e9e05870) -,S(91a113c6,c53b57dd,60b2eb66,e6bf7ab0,e721dac1,acd71d76,2c278b31,f2fc2701,beb6c79a,2fdba188,4f98ec5b,fd97626a,131f5c16,d4466a84,a9d77213,96220b17) -,S(732b5521,e6cb7053,ebfec5a9,c5b35f47,8da4a9b4,c4bc5708,42b0e8b1,242bad45,30afe970,fa640757,bff0e825,93a102b2,e1b619db,7f7d68f1,17f27543,e72f57c) -,S(94831570,f0146aaa,fd2a7ee5,11f992c,6e2999a4,b22cb176,dd516dbe,e0e16e5f,eb275132,385efd06,35baab61,5367697b,8bef0c93,14fac991,4a2c04e4,aaf785df) -,S(dadb60a9,3af95d47,cebb540a,1c0aecf2,839f1be3,e264a294,bbd03317,686726b0,8b4bb755,46efb999,cddcb88a,ad5b28dd,b73ae1c6,48c810bc,cd9d0f03,c200e27d) -,S(148ebf0f,7e23a220,52ca69ee,57237eca,6c1caf1f,faeb8718,b9b8dade,4b97be1e,32f68bfb,464ae6a2,b23ac7dc,3910a87b,89ff7042,e863ed3d,3038d75a,f3689f4e) -,S(ec532193,614ca440,33a8275,49c65e0a,af446a21,6705f9e0,68e448e8,6e882bd4,30277366,58dd1673,d9f701ab,50dc3238,f073a297,d579cb8e,2ee51dc8,bcd44b36) -,S(bcb65ed5,b16fe248,bddda875,28eab71f,d9357099,af71ddd2,9a8471e9,b2b26e99,ed827c35,e6e13dff,ade8b9c9,d2c620e6,576db5a7,1b1e22a0,3f943f96,cb7282c5) -,S(de30301f,18df0e9c,15d709a1,35c30473,28cd3356,95922ae0,f283290a,638d516e,89398261,37dbf197,53012e47,6846f6d5,45a48312,bd6f4c65,255b89f4,a1b9df99) -,S(2eb56a7d,b051e9a5,8a7c12a3,a92509d9,5da4956e,8b820006,aef166fa,92873644,30867ff9,7ef8d955,d497abfb,463838aa,c946d487,d702956f,b75ebf89,e25bddc2) -,S(88f839f6,d7f06f85,82ed781d,12062442,66d4f9a1,e2007a89,f660fd24,ebb30d5f,29ce1d8a,376a587e,96fae37b,521a8903,8f0bffd8,9f9934d4,eada0750,32faba00) -,S(112cb93a,8db33b09,641aef75,c3f9a399,b1808314,64e8a855,16e309c4,99ca9a16,66b1a1cc,f2255c2c,119bd0ed,a75dfe73,fe2e9d9f,3aa9a6d7,43a4b7aa,9d76bccc) -,S(407dbfb5,53b43e95,639aa6c8,d6868ef3,2f41f1ea,70cd4aa5,9d76ea2c,83b567d7,69fdde78,a4971ce0,b05a57a3,8891691c,d1fb371f,b1322a6f,97849c64,bd7b57ed) -,S(16fb5fd1,fb41d76d,ffc130d8,9549465f,7976a3b1,ecd6a4d,9e5d55e6,b2a6a40d,3d39a810,95904ac4,9559aa89,8fa087b9,b84ed72b,55f17fa3,aef8b32a,10e942c4) -,S(e40302f0,6c102ca6,e6be1370,2aa6e860,5e71fd37,6c87e2d0,c0ebbf49,6fcb31c1,d32d294e,1e80cd,94925538,2156db9f,2bea101a,f652309b,8943cdf,b82d75a3) -,S(8f2cfdc0,eadf8b00,f74305c7,892a4326,9cd31300,d716d652,92a7a36f,7f1b3b9d,6d0e726,838fd161,32d19538,147248a9,5d76c7c0,beadf1d0,b553e4b6,b7d1a2d1) -,S(c7a636f1,1a9cf793,4385daa0,5c3f3abc,8c3a1589,7be0b49d,ae789fbc,e07674cb,4f715f0e,e52c638c,954b8b3a,84baac76,6a891889,db0b7f82,6bdf81e8,4040cfbe) -,S(245aed6e,5fc309bd,980d5597,9380e8c5,79dcc887,a2758e13,24ed3a1,833dc820,a7980b85,c6ce770b,13a888ff,22a1356e,4136eaf2,49238c38,dd103016,f0d0b1da) -,S(91ea17c1,d90556a3,722dffa5,631286b7,f9db0f01,e411ac16,f5203c4,1a8a824d,281023e9,88fdcec1,94af265e,c407910c,54d25f20,69d64b13,c5261f0,c157a3c5) -,S(729db97d,35fdb72c,a354c65,a0e7f76,7bff9ade,964b1d57,a98f9bf0,39a74eb1,59596a57,7c888b01,6e00143c,63f0be1b,d86d95a1,ef59e075,fe7e377,1472bfc4) -,S(f8cb711d,f74a4961,1391871e,d8de6a63,89679130,b587beef,f4eebcbb,9daaae9b,4c52c310,c6f960c1,53f386ed,6842c4d5,bc1b4c99,433567b0,fbc40e93,91a5e022) -,S(1700d0a,32624d75,258d80a6,2228b6ec,91e66949,a463f3b5,16dffe43,b9fa08fd,a007bbb6,b687b509,f450908e,b617f176,92918f18,be3113d3,8a80ebe4,4ee750b5) -,S(9f2f3ee7,70a2c422,b9b92eb8,a52570ab,b5354154,57f0efec,fcd9141f,62894132,c977d79f,ef198135,b69aa3c3,77a7f251,3274911a,73736b2e,c543a721,17908588) -,S(86f75064,8a2b829a,91acae01,4beb20f9,aa9ee46e,8e513678,c4fbd7c3,2ac36e6e,1768035e,bd1fd375,7caacc22,495a5902,a3c616e6,49eeebe7,4377b996,30192b28) -,S(1d4207d7,adcbd969,d432bc74,35f2fb75,b35adbe3,fa1f45ab,bf3ee074,b8269f68,11d80191,accff888,928a0835,562186c7,30367e90,91d310d8,2a712a9b,13d70f99) -,S(f782bf74,2e55fd7c,ab249b2,1570d9e8,cfc12f46,5330d2e6,57eff609,7c3d19b6,896e9e48,a60ace9,84d07ebf,12449980,9d96639d,101b3405,59eed877,908394f) -,S(22bde2e7,e3c0d268,f556c478,82e50f2b,634c4235,9067cbd5,a0daed53,1a166a7f,5e03a94a,5baf0f92,7f4beaf7,6b7e9649,aa578eb3,f105515c,ed670c3e,e1fa3e72) -,S(85ef9f8e,b54cc4f3,aeed4769,85529945,7eb4f3bb,1e5849a2,aec7b257,a8a9a074,8a0245d2,f0c8eaf2,84a01114,d29c65f1,c146af0c,dedfb5ff,9e3be650,e2acaab5) -,S(3bd6c026,63620684,4d2e1a89,2378ec64,177145d6,24062d23,ce9c2d08,4f34ca81,7f0e5053,87fade82,8596f440,3687b04f,4a2693ee,25361442,1d9712e4,b3e0c179) -,S(364f9a2d,641173de,4a0cd185,972f6d78,75b06722,3cececc2,9bfb8aed,7ccd3311,39e7616,8d64795b,504de9d5,3049dcb3,a95fb3c9,affa2d5e,8e8cb35b,6cf71219) -,S(8833f933,f4049c7,98493b,e5f764bc,47dae8fa,baf420d8,44c7436c,eec27898,bf615e47,1b0f1029,1afb2839,2c874f83,ae55b15a,58e61be4,12b7c7a6,13868279) -,S(d4fa5129,4835f9dc,49cc3ad,b9401f61,97654f43,ec88f206,9a63852d,6abb4a6,f24535f9,9efed47e,80d66925,8924e56a,44530eba,a2aff32b,70f36551,1db59521) -,S(50eb8613,99f79883,58b9de58,88c47cd7,bd4547c3,96e1280f,2806efd0,d0715b89,dff64137,f74442a4,dd0c25ff,ea968845,f9e14ff4,d3e32010,f1c64ca7,6afb1be) -,S(f8608ede,92c5a1e0,5f61c065,606ae232,b0f81161,bcec88bf,b4f2b14e,22165cca,e583acc4,7ee133b4,8c3c1eb6,5d6f4891,b53c84ec,7bb352ec,3b6e41ff,aa6a2089) -,S(2c00145a,60e21169,98f23b9f,6f83223a,6ceafa12,c1b92844,2a17bd63,582a4fd,ed76c7cf,c65a881c,5dd270bc,7be9ce49,c2990e43,425ccb7a,eebe64e7,eff423d) -,S(b42d4c38,79f7aeec,96f212f,1d5bd79f,bdeb9850,ae44af81,b4b3467a,85c29c49,7bdbbcb6,1eb04e41,9ea8f9ba,dd5289e0,d718158b,63ef0599,55e3c5de,41f833f1) -,S(a5831ace,8c19fd68,85e9b9cf,34b9fa4a,9e80eb3c,36e256cc,44cbe521,6efb7128,e10dc489,3e0fa1ca,f2dee476,5b8ab518,c3778f4c,583abe27,af293869,c765955a) -,S(9fccb821,59ed46e9,18a407b4,967e1154,4566afbd,df6c0639,d5cced94,50e56b17,c430e829,438188ed,a443cb2c,aa7d6939,3004ed75,5ff61e57,8dbe9e64,251615ee) -,S(c1efe41f,44186467,cc0def62,eb0f0ac9,22b8bad8,e2347849,28b465e7,1789fcc5,5d73f89f,709d54d4,e167806f,a07ef07a,7fd1a7aa,dab9896d,33c290f1,dca74872) -,S(805c0816,43fffffa,c9055f2a,996fc2f,fa02b4ab,4fa440f4,8af5878b,4eadb694,b0a0dacf,d9b3b9d0,51ac59e2,b367a8f2,eaae274a,ee2b05d9,18cc0042,eb02b6c5) -,S(d5da1b82,9b477768,bec17829,1c9abc82,b595bab8,6240e705,715de420,fefe498,dba833fd,df1915b8,fb43b39d,dbbd635,8f12d4c4,31b547c4,af07a6fd,75fde785) -,S(73a2441b,1f1b9ddb,844caf0f,8cb0a91b,5adc6556,6f883026,8ceeca8f,7c6c5cae,512e46ba,b47e9eaf,64cfce27,24566bf9,ab43e32a,bb0e098a,5dac9687,11927437) -,S(dbff750d,bed18702,eacea6d8,b54540e6,ae60ea05,85d77db8,7a63a050,806037f4,1f349895,29ce56b8,bba91938,16e842fc,f74b56e1,568857d8,2f193e02,207f84db) -,S(57c73f7d,57c7882c,5d574f70,fa225552,ab3d7741,260bfd3c,b616d6be,9698dbb9,f633edba,f7f6cc7a,9d8ff9eb,75bced20,f865fc9e,81245e77,32db2ed3,876e42f) -,S(6663e27a,7760f187,a1f67823,64044da8,d4cb82ef,e296f5ca,90c5d81a,49b7cc5,4df0d12,4ca9c8db,4885f8d5,18cbf06d,f5b437e,242cf86b,b11df29c,5c83937c) -,S(83f688c5,88ee13f4,a9e72023,5169dbd7,ebbe0c68,4cb61827,3e2b75bf,5fc581d3,f76e519a,151ba05f,df5f11e6,f3cfbcdc,4b00776b,14c4598c,51783088,2b2bc6c5) -,S(2114e129,1f65c339,d1bd4373,6c677937,4385b3a5,5dafa8e4,a0515134,6b650389,88103399,1b682f7e,9ba02fd3,e104932f,802ed44e,b996beff,7fa9523e,c9c2a9d4) -,S(a68b163c,db6c8aae,8ddeda39,7d8031a1,394ddc36,48168f13,47774ad1,d569233a,eba470d3,4ae15c94,57ba1b3e,cf5f3d96,682b8095,f83eba7b,f319feee,6740d3e1) -,S(a44b2a55,baa92a2b,cdd2f06f,36874d69,40416b79,20bb6daa,2bd9edaf,c12bbaf6,d06941d8,28f1092d,3667ce3d,59d23159,54d6cbcf,c0da31d5,1663a6bb,ccedbb47) -,S(5630eea0,8fee5570,c094ded,917746e9,18535cb8,b0286bf6,f6cc294d,5714fd33,91f60b64,3457dd9a,b2a02ff,99f931e,b38b4d87,204de10,d8a30cea,ce576b62) -,S(cc8b173b,d3112432,cd0c741a,8620fc26,ac5c5d89,e05c18c3,13067fe0,a41b4b00,8cdcccfe,b4ca500c,34dc3087,58f424f8,52517974,9a33e27e,8859515a,2f7c0926) -,S(abe16c8b,e0c99bf4,d396e70d,af00af89,b5d95f5a,3ba33570,892d086c,4b807943,14b2bcfe,8cec39c5,826fad38,9b8f8788,51e1595b,b25b1a87,149d8627,1218e9b) -,S(62411146,ca2da616,b557f0af,ccc2cb75,d278b07a,4dacd864,7e449ddd,cf29c09b,d081b63d,67ff0c07,5f00a3c7,2771c581,87804c1e,4ec5bf68,faffbd21,4c71e15f) -,S(5952a672,a50af560,66de08ad,be4f5cc2,38f3e4ee,84160b1d,14534c4e,2b50ed52,f7d7e2e3,e9612005,a0344e93,454f112c,792f825,f3d3044a,28d9af6b,798da761) -,S(128fd5b5,420f68be,3742def,c987da3e,bca771d7,af1cf8e3,12d6b3ba,df162492,afe5edc4,80c1c8b9,5580dd8c,aef14338,c09fbf6a,a1c951d3,57ca4df2,9d3f183) -,S(6315678a,13cd71e4,6e283287,24499671,6adedf31,38841718,cf5168f,60d4bf8d,ff691d8d,c5f97f7a,f2ae319b,dc590518,6ec3bd36,7f492d0a,95cda47,9492ad3b) -,S(50277159,4169f70a,ab39095d,d8027324,e212f78b,c3b0865a,a57f1574,dba1bdb1,e31fb30a,58eca0da,aea93548,bdeb9f32,325d6c30,69b3d936,d610bbc0,de3b771f) -,S(51eac8f8,8cdd7ac2,46375960,c6b7d9fa,a89352a5,4024003b,cada1e6f,df389721,6d4c8750,95d6ccfd,9d8a5830,c4672c71,d414ffe7,cff2cc15,b7b5d169,48e872d9) -,S(bd39330,76c0f542,a0590ad6,398b2418,92b899ab,75ba0065,b1ace928,b8cc0ecc,12f4bfc4,57e97c3c,9d4a21c2,ad106ee8,8cb5bfc9,92d151ad,589e90f7,d65b5d8) -,S(bd0eb600,5ae967e,81214a1,889f7dc5,d1e765a1,af74a93,f5292758,539d6dd6,2e532797,9e6a22a2,63025e57,4805e4c2,6d62b33c,5269d35b,bdeee7f6,4a2cfc3) -,S(b7b068b6,8ed18d80,67a0c971,a06cb3f0,5c96ad7f,371dd849,aec3a2f9,bbe23eb6,89871d76,d3e6b605,9997345d,4246087a,a3fa61c7,dd75f5c7,b2ed1e20,59a00350) -,S(10cf2c38,643a08b,dd842c4b,79efa2c0,3b5dcd1b,c708b253,ef71fba7,f0e51f48,e37d14c,934524d2,dc562f6f,997227e1,44094184,e8342995,d5562000,34e71f4f) -,S(5936b571,20b6dc97,ee242ba2,deaafad4,5ab83795,9f1e7390,54a0c026,df7bb342,86bab74f,b9d4f776,e82831c6,3a409237,d5923c7e,7b3e0b18,12ae203b,64fc750) -,S(67bb9ab0,bc48fafa,3ca66493,995ea995,e36cdfb7,152d64ed,ddc56aa2,6c315896,cfa9a456,dc2c82b7,f87f4216,e365f5e7,97223d2a,820a127c,a5ee4ee9,281b71b5) -,S(5580326,678b44ad,fb313c23,dd8a7dbd,c6869fd,70cc58b6,d20f8b92,ecfd81b5,6d343687,f3dc733b,55dac794,c895e5d5,9032613,563f2d72,ee94afe4,c2a932d9) -,S(fe285767,53d2466d,d056d2bb,b7141cf7,e52c2b96,d0ef3c8,52c728a7,d2dd8126,f344b3ad,c8077e92,24c6c5a9,c9f40a1a,d8721351,6b8691ab,c5fa9f73,726a6c98) -,S(12f25359,638fe4f3,97a17f99,c233b2ea,7a794d71,e677b206,aa32f251,8cef615,dd0d68e5,324e4325,ebd45766,441677de,40c15792,19d65c6e,9c63f15a,91519c20) -,S(f1e45fa7,21bf7fb4,45fe3eed,29c26bb8,bf1ea59e,de7c1a6b,e652663d,233c3e9d,6d145f2a,c3a041a9,83b9865e,66775342,a0f8a435,de19626d,ca8b9328,797e20eb) -,S(6b6ab442,d2623235,dcc7e3e4,85d00ade,7f219576,509c528e,6a3417a4,fefd328d,5d627367,ed25278a,6d3505c8,e13970ba,253a26a3,c605d11f,1eb345c5,56584e95) -,S(83e10be5,d21bbef2,ed1ceb33,c4e558ce,bee76405,257d9573,51f5d90e,f219552,41f5e174,c6e9b283,2a39c2fc,4d4fc573,634a8975,e143243d,14dc4be3,434a4380) -,S(2ba25948,9571ce20,f792129d,f43caf4d,ddd93b76,e4c8cd63,7a9de68f,f8d615c5,9469a49a,d1a814d4,2f460325,b7d58f2b,eeb85183,a370cc3,69a685e6,a87f6e61) -,S(3fac1508,b669f540,77a840ca,3ddeec5b,b70c03b0,ff93a77d,f2f73df,2728f36b,dfbac9d5,ceb21745,a6d27c3f,d6fd96b,af708066,a3bf765a,208b7231,d5fb6955) -,S(8996dc02,9b79d0f9,d57b8c8,549fc01c,2e1c1c7c,2ce2cd70,7a0bba0a,b3420ee,d08fcc05,5194c4bb,2d17ad54,2f9ec734,f2a9ab8b,a7dd0467,c5d916aa,10f7b8b1) -,S(16af9433,c9baf15d,921f931e,f530a477,b04b2e03,e1e8cd05,42e20628,df7c3241,65863e2a,acae34b5,a1dd53e0,5efd423b,165235cc,69195973,2d0f64e,c5b56fac) -,S(d82af39e,eda70e3c,f28e2f6b,b8009131,59ada2d3,854e81a9,3798e402,43d1d3c,fe03de8a,326e8bd,b202b5b9,929c2f3d,4bc8abea,a2377cb2,29cd4630,d1dc1c50) -,S(a7ad92e4,7a442903,c2f91033,7e2ebc98,14bfc943,f2747eda,666bc813,c04382ef,ffba6b43,9379448b,56b20163,44439b9e,8d6da764,72f67a27,9c7f45a,359234c1) -,S(fe9b9274,7b27f7b0,6419dd38,53e61762,de7a5116,48008802,681bf521,21a1ff92,f32bec26,b9d24872,1a47c65b,48426130,b8e72e68,d231bd4d,82c5d4c2,bde605a9) -,S(8e22ed5b,e5d80940,970de428,5ca609af,872b8a4f,b8c93942,fa1e62d8,588ac5f5,6a461962,b74b0f93,afa72284,4837ec30,b99a65da,d688c161,cfa42028,2ed97167) -,S(bd3bb0ec,bfdcf06a,62f0046a,989b45e9,c76f4d9e,b3225495,eff70685,71518fb2,5592029f,3eed8e35,727865f1,dd2a6de5,e19e6eb5,f92e520,529fe97a,c296820a) -,S(50a9dbb0,b08a48b8,76dc65fe,6e2efd92,d44053ed,73b8c279,5b688e00,a1fd1455,4a1fae82,51581f9e,32fe8f67,5675ef70,dd7c2ec6,2a42eb3d,e1aa13e6,717df147) -,S(6c1dc44e,67b52cf5,a4564ce1,7a9da713,c718833a,6d527e7d,ebc6b1f2,c893693,89cb4508,681d58ad,77900c1c,aeb25c59,b307c9f6,c84f1329,35e32af1,e39f8f67) -,S(3ffc35e2,4d4fd0e6,ffe4d1c9,b5097d10,c12dc7c0,4356cea3,b5fad66b,5f3333c0,89718e69,78748c6d,e99d181f,137eb74,6e28b05f,27af7726,e86c5f5c,daa1eaea) -,S(fe2261bd,b40fc492,99be54de,1d0bf22a,634aec85,77b5e9e1,51626d67,3f4214eb,896bf33a,5c9b7537,b621a168,f3da1bd7,dbc94816,922350fb,38925c96,5e57c175) -,S(129b6e5,dba2fe86,749274a4,f1ec5999,b2fc682,933a1120,cb8e16bf,4f4131e8,24dce651,b0fe4770,6c78c217,f0d5ed4d,4bda4e7e,4e7ea6b9,ca59e751,b018b5bc) -,S(c2d1b280,79d91abe,1a44c4bb,96ab548,90323054,94075907,37b39ea5,e1fedd72,6974b9f3,80edabdf,e7961bbd,71ba1971,ded6ba24,90466d1d,a5715d9f,92472637) -,S(d8dc5f38,76f6049d,a9a5c9e9,396d287f,911e06cb,ac0148e8,26c8de93,15bd464c,701d0a43,ab41f321,b8f86ea1,b1f51d0e,c22a3399,c1d8534a,433ebc2,38ec248e) -,S(2b1a41d7,ebb9756a,b62a96fa,57909ad1,a747dad4,b3730da9,a12dac8e,3ee4c414,8ebb1512,3f43224a,c2cb4ba7,c90ed765,5470a968,454d0c81,1ebe3384,5c6ca968) -,S(724fe9d6,e7f75b52,7da19421,3c984e31,f63ac3f7,1b5819bc,344ea339,567bc179,a1db688d,ba1d85fb,20da08f,802b5195,163d179c,7bc60f70,4ade1f26,4e1552fc) -,S(835b30f2,8e54b834,5ce95569,7d71b7a5,7cd4b5b3,17ee3fce,57722454,7695c9bf,f431ded9,b7ba9477,ff041f83,22685e4a,8c88c91e,15a14f21,6b16e302,e243cd11) -,S(f5015d22,16cfe581,e650e579,c49b6ccf,b5ca4dc6,42561256,21df7fc8,19047ee6,45b099ab,febbb493,5356872c,40c06825,47aaef2a,72e80d27,521b65ea,e2d4918a) -,S(df0b1b57,f3a0dde8,b136a92f,bf953a83,694244bf,99782ea,98050bcb,3313f826,6f7c8326,bf5f6e15,538a1f31,273adea,6908e5db,7f38f395,49284822,12124d5) -,S(a5a24cab,96c04bdd,6e5180a5,8fe27f9e,51897bcc,3a0aa9d8,de06de65,53d2890d,4f6dfa5a,a6b44550,105fbf39,7dce3a4c,e0b42362,4a97d979,eb31324f,f1215525) -,S(849c2e79,422d1dce,4b568aa4,c80eba4d,d8acd237,71f6dff7,40849bd3,ecdb7e41,a465929c,a3ab167a,dcc4fcb1,7ef9102c,35d8937c,fa900ef1,8022918a,6ebfe79e) -,S(a9a98d5d,d8f8ce0e,ddcd90ae,671c52b7,1b09b75d,b4185d4a,1ff12c71,70b499a0,a4eb522e,3aad7f1,6aec7758,c9528bb0,c07184c9,e3c965f7,afefe128,bd285c5c) -,S(8d60786e,1ec1fbe9,61e056c2,d6a57c5d,813d7f20,bc8c68ac,eea0020a,2c4e57af,3a39b0f1,6cc346c7,fc695f45,91b557b6,3c1f8500,89d742b1,60c39744,90e55720) -,S(4710166e,65b9a2d,8de5b80c,192303ed,25cbb80c,b91c57a0,b31a38c5,5c218fd1,b4cd95bc,fa48a016,658382af,37ada302,26887fc9,8200f77c,2b8819a9,ef489206) -,S(e2183510,40815901,c78a304,e6f0d545,5a116560,a91d84fc,157f061,5ed6c0de,6c557bb5,358454d,419c5cb5,1bcb85e7,db3b04ba,d18e1a63,a75687c9,8fd6d973) -,S(807cf529,8730d656,e68b4aa6,5f8d8692,ce246c2c,4e668c69,b5e93e8c,d26b289c,b22a6fc3,d7ffdf57,f18e7447,38cb1bb0,aafb7b39,101d3259,d31574f9,fff644e2) -,S(568f659d,f19f14e1,5d91f3d6,bd2a4690,b274901e,cf6fc684,dd0d8615,8dfbdd85,28eaf8bc,1db68471,4ffbfbce,30977c7,606bc591,dfb8ec02,e43a31c2,ecafbde7) -,S(651dacbc,564fdedf,f4e5e3b6,f2dd366,37c69140,7fa923a8,ce88ed1c,a65e6b86,88dfdb8e,6f117a1e,b99ba423,89ed2db6,cd5608e7,8be2c896,334ffb8d,2e19aa79) -,S(5a17c956,8214ae71,80322b0e,574529c4,dd7d951c,872809c6,b33ece6d,8cd7cd0d,ba4b0cdc,7d7e6ff9,5a97e4c2,6af714ae,f00c9142,5e562ffa,16942fe2,852a3e06) -,S(6d564251,5edd2987,568dc237,b5b98fa8,de9b86a3,e7176e62,f2609dfd,65810920,a99a0d1a,12534f64,fa97227,825b094a,22fc16bb,e8777669,d5aedc4d,58e81ff0) -,S(e3687c75,c0689381,22f60fc5,b346e8dd,17b2dff9,cd7fbea,94aa54b7,ba1f6de9,4dfd4537,1f62a968,399cfaba,87a0b985,cb333510,dfca666d,395e0f8e,2b7f473e) -,S(1a3d974b,49e7e68e,bb2851c9,c9f22d9a,5929ccde,9d635e8d,61aff93f,f7244472,f6c9e7e2,98815ef8,d53a7bd7,9f10275e,ea74ccd8,5d97cc3d,cf2e97b1,83c97c86) -,S(8e0dba73,12c4afe,8e1bc508,4d9f4944,654a5693,81a64158,d7db7007,3f897cb3,560eb34a,2451905f,2e9daeaa,63dff50f,761bd68a,2321a714,45930de0,4801875) -,S(35d9eaef,6c4ded5c,371a655f,2fdbac45,35471c32,b369955b,f8f30d95,21cd5817,c5a084ba,7b2ea4c2,e3c3d081,dab53c9a,ee40e10f,607ce88c,899f0e3f,5850d75a) -,S(44d1dd16,c42b7811,f78374d8,2ec9983,7fbee7ce,4b3a8ccf,81ae4ed6,3b7d2c73,6a7bd35c,b10c4e89,60e3eba1,8f658510,3be8d1a8,5c4932f9,f1e48d81,e3f66604) -,S(4b7a54a5,e7153a54,e4400ef,9311d6,cc16f641,6695fd92,5fcae9ed,6b2738d5,43a7bf76,ac2f663e,daf0036d,b665291f,cf983c0,791a8a6d,a5ee1956,2dc18850) -,S(add4a15d,d1a350e9,e5df62b5,4a6638d,76ee221a,4007a19e,db5bc93e,87f11ea6,c26d6fcb,3a8bc1fc,f1474c26,31a4216d,740cf94b,a9d7e48c,8f01be28,885ee849) -,S(9b52aafa,119ada49,ce33340d,ff75ac50,ac9a9d87,775e8e45,da58452f,228a23c2,67640253,503b5e3f,89f7ad07,b9379bfe,77c946d,4f61b83d,3fced91b,69e850af) -,S(965916f5,89854944,26c1efb7,88079a55,f8109cb3,8bb111b8,42ef7f00,2d4a45d6,9aa2ef4e,61902148,aea7769c,a561d04b,cbe1b340,a231388,e332c30b,8488e531) -,S(3af7890d,c045aaa4,2f7a8f26,5fcff9ea,41bae0f9,87c75c22,3ae3311d,e09b6ffc,dbb31417,27adbd5d,e34202b7,f7a880a2,41f18b0f,b1a40a25,376c4a30,ec607152) -,S(dc465cfe,c07f839b,46406f4d,9a0078d7,57c2fe0,e62aa4e2,212ed33d,5b2026a,1ef12aff,a98868bf,b51901f7,2693f868,5ba2248d,91440380,53bd137b,24b3bc8) -,S(5ae92f8a,cb9e2ca7,2f4d4c70,f4daaf96,bd237bab,2a83c0de,693d8207,baaa0f4b,54e266f7,aa1b7f22,8f24ab91,5e3f0a92,3220512a,de239da3,1069bbf2,35d63049) -,S(38134bb,c6c5a4b3,63421af6,ae573ce7,20421d36,1f4966c7,b9e7f125,f49659ac,5d42678c,d6f89848,72399321,fa86318f,7a4e3f05,4c3bc6f4,6782be35,4ac4aa16) -,S(f2b807a1,3fd603b4,111ac02d,5c646f6e,eb819a4f,7893992b,9132aa83,76892a57,6f1beea1,a315c000,3c957d85,bc5171d0,ccb8ff06,446f4748,738a3c78,f9ec2d4b) -,S(debe05cb,b308a6da,a1eb55bd,73c3f1ba,248ade5d,ceb1ef3a,baecc6ac,7a5e8c09,f4fb16b1,44beb4ca,789aff58,9374e476,efccbbbe,b74e2693,a4d05ba5,a809ff05) -,S(15cbbf1,2720f8f5,fa1a7752,b6f33333,91cf3d0e,c40f0292,24f5b7b2,c966c099,be3b1573,fe38200,a464f4f0,c3c2f9d6,24bd59bc,9412110f,6eca2ada,2f1c7294) -,S(e4fadc29,2f0cf77e,4b14c3cd,b567f5c9,be82fc93,dcdf2b50,bdf20fdb,f5984769,2858e2ba,c9834a2f,942ea7fe,2e339d8e,b384c255,6a48d688,a9510808,a1235452) -,S(b0a8c6dd,f57434e8,a8bee1a9,530cb9d,3d4ac31e,edd17653,3d84780c,6909554a,4f7467d3,62185e38,f6d6c30,e4c3e4ac,e167f3cb,aefcab8b,eac754eb,c76ea3dd) -,S(a4398869,26e4d06e,5337e61d,dcc6f491,4f40c04,eb3ec752,47d9d058,9dfea2af,ac1fdc5b,70d792c0,7bf7e55a,b07ea1ce,477dcef6,cce8585,84cc90ad,c62b6272) -,S(84b362fb,1597f179,f30b7e2c,b516153,94619081,1131d45c,ba55fd1,94f369be,d2a80ffa,44965152,78c2ee3b,122b5c3f,e6d27f9d,6ed6ba94,9258c2fd,94eed4dc) -,S(75182684,96e2d037,24c11192,e9112501,f7c27d19,8b92fa1c,3b0e931c,2b85d32d,eddd2a6d,d884f93a,b6f8d225,c9fb32b8,9f396f1c,2613be98,d866b713,14a00d70) -,S(aa96e0b8,104884cd,7e22211b,8b12e6e6,b3f3e3f7,fdff04fc,202d8946,838fe15f,d8a9b5c3,9739fae3,dd3b2483,4fd2981d,ea529097,2ba52541,56905664,f289e3e0) -,S(ada17e80,82a0a15f,366f3d6e,6775b5ef,35c980f7,12ea7522,1aa796f4,2454988e,7df4c1e3,191214b6,e40fdae,2f5dabaa,b6e9837b,f53eb10b,dd28e674,230cf2e5) -,S(322a0524,20f0fdbc,85f35fc2,de6690e5,a61260f1,428ec662,4185ee8c,d2385caa,fc81cabd,789995e7,d36d3de0,1b650a20,1befd7a7,a415d250,697114e3,c95e096d) -,S(5082ad62,3bf2ff8c,b4571b9b,86303032,ecd137bc,86c5514d,b9f218c,4f091153,b29d3823,eb4ed958,9b0fbfc9,2d006fb3,698ab596,d3e60360,e435bbdc,be4c80b3) -,S(de9e45fc,e9e0dee8,3bc806ae,286a2c5a,a7978608,42ddf02,d29a6ac3,9fbec470,bcda9466,e7207f7b,7d986e,36b3f238,d5bc51ac,90ec35bc,56e0949b,334ef964) -,S(95cbc3a5,61ff4cfa,278678a5,6f8b16a1,efe2d286,c7103047,310454cf,a1a822bc,8720fda5,58d23b5f,af9b80eb,dd5fa625,93325a6b,eb5ffbd8,f333cd9d,9c8b7366) -,S(fa0e59a0,969de9fa,aaf7be60,24136559,cb384b76,26d3bdec,f70f3e55,696a0632,2e8af3c2,a54e837,ddbfc32d,8a47f342,a856b854,7ec4b0ea,6fb3695,48b8b588) -,S(56aadb8,2056ff5b,3337aa5d,337671a8,77168b0c,f0330e8d,8f5445a0,cdd75075,d6c4cd4f,db81d8df,b095f681,f7349fdc,c2cc80d9,399fc16e,5fa3e86,9460a5f0) -,S(7da6a13c,11d5b063,8132254f,c064ff3f,d3818a5c,e07168eb,ed5b7345,53bbc19,26e912dc,5b03258a,f914cd86,88d6a068,266eef77,7d4f45f1,7c47cf92,16d00c4c) -,S(4004b235,d58417a0,ea1a2071,32b30a8,1dcd6a9c,3ea875a3,6d2a6225,e2b56917,1c960bd1,443c22fa,96f06eff,a717b5bd,efe8b105,7402cd93,7a6aa909,5775e226) -,S(b12c4d85,6ec6c85f,3553bfee,c7dacbf4,f742ccc1,356fbc8d,ab3d25b7,52bdfe93,a8a11692,49dba87,8c8e6c56,ff8f699f,d7e69c6,f994d05d,4e0643a9,7f9cd2e2) -,S(a78d9a2e,8b74ccdf,97c6ea9c,aada2644,8b560287,7d7b0970,41d24840,91490970,39cdd434,1d1e16dc,b89fe937,665e70da,ea80a174,5ae7b99d,dcad04e0,efe841a6) -,S(c8233855,b1f242bf,59b86372,ae49a985,2528440f,e3aa8e,28d594e0,114d2ae8,6f515202,a14738ee,ae4b430c,27391144,c551bfe6,bf24005b,81f92900,bda92b7e) -,S(6da24dec,9d6ec569,8dda9655,672a9b79,4923f595,9157af10,64cb53cd,5e5e8f6d,59517e76,8b0d39d0,2c075a46,c1e653f8,cf876fe,cfb10746,a8c248cf,4c73fcba) -,S(d0c55dca,ab79e0c,84ef08ad,57ff67c5,b36336f,2f6231d6,8efa2fac,54558ef0,d4365ebb,4096888f,c9a74d90,1adc4c5e,16f5dddb,442cb5d6,b5e22b32,99aa573) -,S(d76f084f,237dedd,ac8a1936,319d198e,baef2c4a,3b81ae42,e92f96b6,e222490c,c7737563,9639b7c8,32e4bf45,efc8da2f,53e20e25,641ea714,85674a40,1dd5f14) -,S(6a1f6920,9196c02e,6919abd2,c8fc835b,889c5ca1,6bb25e3d,ef7d0c4b,9f4e6d29,84371bc2,7bd206d7,389534ef,f2a49c6,cca4c9c9,874f59b1,ccc8b5b,bd5df3b) -,S(693b3520,85e1ea36,bc5c8ce8,3fa49843,369300c5,170010c1,b11a3c76,4deb12d6,4441c9b7,808b1ba9,8199349b,243f08db,6cdf5326,d7453828,16f008d9,45c1251e) -,S(5ee94c65,70953f27,37c16a59,590f7cd7,87143bab,405f6b23,718878c7,bc95741d,8578d18e,a49f9204,e51513a8,94920224,70837b2b,ee480929,5e4c4f0d,cf5c7794) -,S(30c174b0,e7b0cec7,e6da6a5d,335f48ee,6f59ef16,984e8912,32e874d6,2e51fe2e,af7f955a,8807444,56b2c965,5c4ad915,e040a360,eef0c4c7,891db1ae,6983867) -,S(3121068a,eb60a54f,dd427eb0,92e30895,92335900,cf191eea,79118442,67b7f4ca,d9e8f74,b8d9c0e7,c35e314b,51a52a95,bf672adb,9c6fb104,8d2ea489,5135aeae) -,S(a06f5e3,6513a659,106ec301,cf1f2df5,6093e690,38daaebd,4b17ea45,9e977ff1,eb19f18a,15630965,d2bd8bce,9e350374,1ab35f0e,4b442f12,9c9d831f,3811cffa) -,S(a26af0b6,50967dba,1c4a33b5,5226c2a,ad445f43,84567580,3b97ca1c,f3d217c7,22c8aba1,604df49,abe16949,59b33cce,db11c241,cbdb171c,50b0fb0a,399e6839) -,S(8e4471cb,b650097e,d3b0e938,18b8ec5,a86fedd1,addc6ed1,8703a99b,4128919b,fa5457bb,4068bf35,7b050244,6eef2507,c1d87051,28770161,ef0e92dd,d2308495) -,S(e9116ea3,24650463,fde960ed,eb7d5dd1,f5754915,62c99f48,31b553ba,2663ba1b,e30d7323,fc29e388,94244422,63434cdb,aebc5895,8a6fb350,33141e96,46a4529b) -,S(8b2267e6,9052f769,833b0fb0,ffe413f3,4b8edb93,9a2009b8,59d6673c,4ca6ec37,97f80a18,ac047152,178432b3,d445a0e9,84755d9b,7ad43165,8707185d,d573fc5e) -,S(79947669,d7bc732d,ca08e0cd,d3e601f3,c4344532,e35aa7a7,12271b12,339ee2b8,55906cbf,e782d32c,13cea8e,83812e8c,84c76d38,472ee59e,134994b4,b7b92897) -,S(ca6d40aa,2f863c02,b6444727,d00f8923,ec58afec,3b4a4e51,f4be232a,4b4c7c7d,ec73856,b0529f1d,9d2ed892,b22b059f,35e4a91b,b60c6a6d,e919d611,d9bd90e9) -,S(7ba23bca,5f9a88c4,588dec37,3861b699,ddfc9f5a,5b277bc5,e6e16f54,513fe7d4,25f10a4f,eeb77ff0,e24170af,dea0e2d2,3f2289a3,e53ad674,1640cc69,c042dcf5) -,S(186da622,d0e8a9ba,e26d43e0,b601c68b,311d2046,4eb36f2b,f86c3e0e,5d4ffcf7,53a6f54a,dd11af9d,50bd82d9,70825bcc,fe9da1d5,ab55e64,bbe4582b,f5248d37) -,S(e9601474,568cfe7e,6cdbf488,63f11f12,fa17ecdd,c623cb11,4818eb52,cafcdf8b,96d51b2,7b5e4fd8,1bbb009a,2ce40fc7,65fc6a3,7f8bda60,c4927766,a52267da) -,S(811f5957,accf9f32,3e48ac3a,33fbaeaf,c5120858,943e7065,9c0da185,71d1d4e9,ede77562,cc8ac601,e3dbdfb5,944d59af,63bd1aa2,ffb35bf4,1f79c418,d1d67937) -,S(77424acd,1d55424a,edb0149,a6ea0349,afcf44c6,667caa51,302b70f9,5fddf277,70e15309,989a2512,422a5bff,221c0e0e,df608746,7a34dbaa,99e77f9c,62b56c3f) -,S(e9e139fd,73c2c50,375d3966,ed4af6f0,4bd80bb,439121,d61bfe66,99dabd2e,260efa55,805918e,d45c98b9,c119bed4,21483d88,722e0f87,de7a31b5,e4b541fb) -,S(a9a5313b,e634813a,b10b9b3,6b38ed1d,a971c0de,5b6d1010,4cbe426d,544e7d79,ef7b3203,2a95144f,17803f09,72f6e2cb,80e6a099,5196911f,916225ac,e97bbb97) -,S(ff29a1dc,b5c97b7c,c5e2b73d,7a0e0244,bef71dfc,765127f5,f7e0f38b,f8a099db,b8334f11,682b9a22,ec08a376,dc3994c2,7d235d5b,a4a77803,79ec0fb6,7b4d0345) -,S(c98df4d2,da452118,852c096c,bb34c8ca,a2ebcb6a,e9a3420d,a4fd3eec,cc31c5f,f4f9c618,44cea236,edef80a1,4634159c,72663322,7372cbda,4b2680,b5dbbf7) -,S(66126139,77cfafb2,283e1a92,d6327174,86add807,b88cf793,12fef2b7,197289a8,504387f6,70caf906,2db248c3,ed5faee0,269d0190,70dd5acc,c8599f5f,5e01d1d0) -,S(efa8bcf,281ad4da,2f083e6e,182765cd,ab0e66f2,e8411007,e216a69b,d73d5e94,6e1afd7,e97061c6,cd0794f6,837aefe6,e8ab76b6,53d80846,98747ed4,64e20a) -,S(d4f9fa7e,6e385f02,c068ce7a,1b80343c,20f85b7a,4699c126,575915bf,69a2f6e7,a6496004,f280f970,c1028b3c,e0d94187,34dece11,3f9fc737,2ef0125c,851de143) -,S(5980a5c,456f383e,f0add523,13fe37a8,874059ee,497b0a23,c6dfbb2f,9f6c494,e1da9a59,c8e3d482,ece7972,9c77308,e47bcd90,cdff915c,32a94908,db1651fd) -,S(988ca976,ac6bcfb0,b42125c0,939a1207,2eb13565,29da3e72,6b70b2b9,5c310e12,97368d81,79a76a51,7c7d063a,179a2941,fe5df19f,25f1e1fd,42a32af9,d5de16cc) -,S(ca49ad0d,25b36130,cc878861,f4b72a4f,e945bc0b,dbae2f4c,629a6375,3d88037f,5ad2c0b7,2e084bb3,95b9268f,22ba1774,c6e423e2,4a5191d5,b940c89c,e1039f0e) -,S(ec18622f,b9771723,c8e6e6e3,5096e517,38c4dafb,82b10317,1f55f900,b24c2e06,5803ea86,c839ddad,6c288b8c,b382a1cf,76a790c5,6f99df9a,fc9915e,eac6dd61) -,S(c53aa261,60e627bf,bd905ff2,6b50a171,18062ebc,af9d9ca0,c486430f,b6de5da2,7d6298e0,f17a515,529fc5bd,2b85c7ef,d183710b,96d62a2c,5a0195cd,ea561790) -,S(ad138110,f9161559,229ead18,4b7ea7b2,846384e9,dc22b8eb,5b771027,8c8913d2,135a3ed1,d9df6a0e,105c7c,e6ce625a,f8173d76,60ea04b4,9ee781a8,90595eef) -,S(46946390,304df8d9,15705fc4,5714f3b4,233a5ec1,afdaf145,b6c09717,9c6b43e1,aef28d5f,88f62a7,e3ecb978,6efc97f1,1123fde3,88ec1bed,bbeee3c9,f9d3e014) -,S(d464a300,df9de2ee,220ae23,4d59b6cf,44f4d280,7ab4f588,aa21dd1e,eeb80819,89988349,b1ab280,8b829754,7e5b36cb,e66ddd16,4d7542d1,cb0cf210,44a8be1c) -,S(5e99ed21,9ade424e,25b807c5,bcbeb05,9b638b7a,4ffb3c6d,d3bd054b,b7af9f41,a373ab0c,4aba0b04,878451bb,96807604,7d811fd3,605e8e46,57574efb,21681aae) -,S(805edc92,6fddf92,d33db068,9334d778,4b30f73e,4e65517,42e62c50,fc6ff2a3,170e4317,4361275c,2102aa8f,5406ff9e,7bd35523,8bf1e946,1a6f16c0,38beecdf) -,S(ec6e5a3f,bb96f0af,dd700701,8c046998,49a879ef,5ebcaf67,456748f2,f25fd18a,9401937d,cf584df5,a9399fa7,bb309ffe,80ae015,20933d63,df1fc181,b2979fbf) -,S(94f226aa,a25c710e,2cc68683,2b9124a,ffc5c3fa,179ace52,327c6866,cfdbb3ca,b92762c3,a4c56d95,1ef16db7,b3992e9e,aa2f9c3,ec48f077,62a379f8,408f94a) -,S(8d2668fd,5d46bd4a,fc84183f,4fc31dac,964358b,fa6b03f9,16ac5bec,a619a92d,c24f6815,3e49048c,a461eea8,ce50c8db,7794b10d,d8080236,2af6677b,45e45f95) -,S(2a3ef112,d00514a,c562de17,a68bc4de,c4c04db7,8266892d,b645ac6b,ced47f67,6e93173d,64333933,c3db0f56,8c05410d,8a1dc73b,6a30c6bc,2b0d5493,d9f9fe1f) -,S(6eaa1185,19d6cdff,45d88426,6fac5867,790faca7,4ccc31bd,6eb19551,8f752dd,affb02eb,277a2bdc,db79d91,10ee8a7d,58c9662,22cfac03,b3d26cd6,3c678f9b) -,S(d17802d0,1944d9f7,aab2b542,fac985ce,e56172b9,e5629e53,ddf57e0a,8dd07137,485ae7ac,34d13d9c,9ade04f2,b3fb8cc7,d0cff406,97abbe2d,4961e753,b8de013) -,S(9e4cd82,67c121f8,96c8104f,988a140a,71f0cf18,782b574d,407a4840,607f5804,c05f08,3fb5c4d3,9d3e237b,101f46e0,6547828e,f05040ae,87db7874,9d7f3bf6) -,S(927758c2,12452995,886e97b4,b1d16c53,4603c,7362e190,dd2558a8,43521a41,30e4d5df,c5ff4b5a,5f4f757a,3483234d,4c658b7b,f24dd509,7968627a,a2a86d56) -,S(589906c5,90a1e143,ae7ea4fb,84edc7a,9f00bc90,dfeadfba,1933c36b,57f2bd25,e9d1d51d,92223636,cab62cab,362b79b2,12a18be6,6468f06b,a543921e,bc9b1c61) -,S(5b516216,1171c076,b10d4987,3aff89b,c080d2b1,9e3ebc3a,de8dcfd1,734e2f35,572c40fd,24965ce8,a78c3402,381bfd90,b683d6a0,d379d7ca,21e66804,31b8ffe8) -,S(1603bb4b,3dced105,b1a2b748,21080a5c,2629a52b,56823524,84deb617,2f6a9694,2dc4243d,fd20fd16,d1f2798f,23e43be5,f88d5feb,1f6fecca,6fadd5c3,f5a63c37) -,S(7bbf7555,4c14bf1a,63ef9f38,ae3ec279,5cf0aa1f,335c816e,580bdeee,10d95ed2,d2e12648,81ba6d5e,e8cf389e,84e37ee1,7c178b8,dda63756,32d9330c,beeeac53) -,S(b2d3aee,d083787,eb4e14f,328640a3,c557724c,e06a62b9,17134ebd,fe576073,68cd90be,2df0fa6b,da2693b0,f18357b7,ea5205e,2a1f5fd7,5a1413b4,fd9ce0d6) -,S(dd10759e,86121fd,6296f171,57a90f2d,bc217238,53969f85,4a71461b,27df81be,713442b0,65546c39,1b71ef30,3bb6ebc0,659471be,fc165a3a,686aae0b,270f13c9) -,S(54229d57,3a274ca,6eda6194,62dce4b9,35ed143d,16e470f1,239f1045,6dd2de16,a6739dc0,916112b7,4fd6ab7a,134093fd,55541758,5b3fb39f,da647bc6,5cde08b3) -,S(141f3cdc,124460ea,15fc80fa,dbba8fce,d89c4426,74e9a3dc,55f74f69,66bb8ff,f0c8d7d4,dac4ba66,1768514f,c9bb9e2b,319645da,735e5be1,51790483,d7b477ac) -,S(e9795743,efacb0d0,4c91c74d,33837b61,8d08acc1,cc2603ac,f02b1610,16fd1363,9f1c8ab6,735f3161,811f710a,1b5703d6,aac65c23,35fc1af1,32ba005b,bbe66d7c) -,S(e5e8c40e,c6c9475d,d4cff6a9,c9db5cb3,f8202bf1,bf60ed41,3e213d6f,2c860797,a9570e76,482a8177,b1adf9a0,1a7716f4,b1e754ef,864d2deb,354a96dc,ea1decb) -,S(5292362e,a095d145,c002f027,be53a28e,d5244982,bcea97c,b56d9ab6,162f7ae9,e7f00a61,8e63664,4555170d,9f13420e,fe1849dd,641bbabd,d3648250,81934e37) -,S(a6772998,3d6a765a,67e9e3a7,45e7de0e,1e42f34e,46b7cdde,8ab20262,ad246822,53281b0b,bb45bbf6,a1e804e4,cb6f443,537b4bb,d551c9d0,8976d53c,1020407f) -,S(7ed3bc8a,8a68ea64,c9dd316f,48f012ed,229e5f9,1a294666,4546ef68,bb48959a,238e6696,a7cac135,ac551927,fef28c04,5bbf23ac,9d24ef52,3d69aaef,27312e69) -,S(96702aaf,a9e17a9b,5fa4fe87,d3b45633,b59779ba,57002679,63a3a5,7e7442c8,53deadec,73ed54d4,db98093f,9e269442,d9a4a955,f9b18878,8be2c410,84014a4) -,S(bd3e9c04,42a9b0db,b063aa20,b09e7e0b,4ea18ecc,55a5794e,14108aea,1ffdea66,b5e43b5,fd8cfa37,dfd49f34,1ef14b0b,c2cc571e,cf9f7511,f2f11e15,825a57dd) -,S(d95c6dde,f07abe75,215e14ba,e76a3be1,6dc514f1,7542a246,e48a2a35,108c0833,e49d6c1b,baaf6f7e,44fa7389,31767757,76d6756b,ce8353ab,ca6e648a,cd2e8fdd) -,S(86f7406,7a86227b,2f5414cd,12c9907a,b78464be,8a5c2284,7d8442ea,d585fe8a,53c73db9,3ebd3340,2856a7e3,d91d29e2,e9439a3d,c43120e2,1fb5bb04,384a8e68) -,S(bdd92d35,ba51344e,4deb6b77,126fde21,9e7030e6,5e1d96fd,4987f1ec,bc5ee6ca,a49915dc,b4f29eb5,af9d643a,6c6f581d,94a205de,3a8bf3f6,a26d294a,be11cebb) -,S(dd4b5fdd,3ca88300,74f19532,728a31e4,152be230,2e6ef55d,a6ef9209,fc70b65e,fed2978a,3cc4c8d8,2012cd5,7e06ea37,4ac5f802,a0032e8a,21d58239,860856bf) -,S(fab1a71f,f8a64cb5,14c94e0d,1c67fb23,70998570,ebbb0e25,9e09df03,e82aaeed,6208c3fe,3fd0d9c,640a1908,1a6a6db4,cdeaf7f2,ede4835d,46549734,c1c50035) -,S(4d6fcaff,167a869e,311e8dd3,f736230e,78634ebc,c4470b91,686018c,7b529509,e860a3b9,28927956,1cd132de,a1de3456,576c4cc6,138bb079,a166b9a6,79555751) -,S(502caf19,5004fb43,75b13ca5,16583e1b,3f60b32f,d9769832,b42423a,f7ec78c3,c0aadc3,36019a17,ebf7f2f0,5afc036e,e807df5a,c2869bcd,19c2aca0,1b5ccec8) -,S(35727dc6,ebe8f38b,1a84d201,2fb24a2e,9ddaedbc,63e8de82,e18de4a3,c4d021ac,8eaca26b,3b88adf2,d19d9d52,c84d83ff,89451750,6a77b4fa,fd717b07,4b414322) -,S(7ced897a,47b5b0d5,f4db6d9a,ecd9c5d,54b35789,91902324,6f270d7e,7ac4b377,1c6ce993,fb84c89,ef5dbdfe,68dad70d,ca39a4ce,29cbc658,d5332d1a,6f6cb157) -,S(60d1d74f,660a5f6d,bac1ee84,5aa43dd8,889c9e4c,6b0ce1ab,e9952ea2,7146972d,dc4291c7,db1dcde0,8e618261,b8d177aa,77b5b0f,2aa8f341,8afc9eeb,dbf068b) -,S(a8b28606,e7040dac,7941cca0,b9cec031,31db3f95,bee7d6a9,8d60c3a,1091f81c,3fbac401,61c81632,ac8655c6,d5c02744,7c836244,e228b9a5,bf5d799f,1fb810ea) -,S(6418a48d,2705a27d,5fe68188,58a61a21,4e4dd39e,4151aa89,9fc6d414,95f975c5,21abfd32,14d98ff7,5b154250,8480b32d,ea8c50c2,3400235b,be800520,1609c7a4) -,S(b46f6f80,c71cb354,3058372b,9ba5e6d5,2617728c,54c10cf6,6ead7ca1,de2700bc,2008111e,c4b86ec4,26bde7ab,f52bf201,10787bed,d7b2e922,e3a5a60f,e68a0f4e) -,S(a0ef81c3,c9f78950,41a8d90,69cc22e9,22bc0cac,4e61a030,495ddf48,eaa6dcfe,8617df0,b32975a1,6666f86c,136e8c99,c07ff948,ff8d8176,9d968544,aee5eaa8) -,S(c03cfcd4,21cc7095,5a3e10e4,a4ed12f0,d31abe86,506da6e9,c83cf6e1,df73d093,8d6f0b3,c0d6edf4,b5d2041a,94d13f89,91adbb03,22ba9f,a56b31cb,63d4400f) -,S(4085a2aa,95e4e8f,11b0e94e,2673c48d,d42506a1,81d93a19,b5f79d45,ab88b688,cc769f7d,f45cece,d3cddf9f,c75c4dc9,bb7018cb,f54986da,434128af,b26c0f28) -,S(a485186a,b21c4650,e9f7375b,2ba644db,f22e2db2,20933cce,2bf0ca7a,c404fcb,2d227efb,68649a60,bee9461e,9390ba02,eb133cb0,eb8388e3,f64d23a4,332ec903) -,S(9faa3103,b212c2ba,9a454898,fb451d17,c3632b7f,c9368452,3ddb88a,7599f14f,9dcb34ce,51f7c4db,7cebb0a2,1b50ff2a,d67c6bd9,7066e505,60132168,3be236e9) -,S(1bb9ddd4,804edffd,78d00b86,ccf6a07d,a798d91e,5d88f2a9,37575d96,81187564,6577e8f3,ac22184b,d46339b8,25a426cf,2dc8cc86,78767d87,999a8e63,5789dfe0) -,S(7b32d099,c78bb658,24868172,1b375689,b91f0650,45fe3d9c,8af4a331,2acfdf58,a4c92e67,f4bc53c5,aa84cef5,908a36ab,afcbaf66,a946d98d,4254271a,b4f088a5) -,S(daf23c72,c67145d5,e2a55109,f95742d9,28cc16da,e53d0453,c8dc22fe,a9eec7f4,205dac83,6614ebe2,a55c04a5,970d4ae5,a9ba4b1d,d8d51f52,50de622d,2a2a472a) -,S(6f156518,addc53c9,76a16944,a059a465,8c49f6c8,6ac4339e,82a2f69f,a3599279,50a277ea,6650fd6a,4a5e4c2e,fb09bfe2,78fe8fc2,c7a86089,b4bb0fa5,fa7262d8) -,S(17661b7b,5b5a8a4c,f700397a,1f819c7d,a6c44cf9,a7d28bcc,df6e7fdb,efe50580,dc1d7f84,841d8ee9,3a9f9fa4,6a03b2a8,365398c3,f94b57d6,77ad4238,264c7868) -,S(c3042389,1483fe1b,12f16146,f48ffe67,3a1ca3ea,ea330d54,db5f7c95,fbfce6b2,131d108c,14a4fda7,77d323f3,f717fdd0,a422acfd,20b9db1e,2b2c4039,a330ce3b) -,S(654da43f,70e4c85f,c9aa2d5a,12ce1a51,d4364a09,5c230ce4,f8ae61b3,cde7fa4c,f82cfe9d,bec57ffa,4109e9fc,c9d79135,49817f50,9fde8195,79190d38,f0afd2f2) -,S(c17be24f,d7d2535a,c4eb722b,bbc4444c,fa529cb1,283585c0,730813de,7219b481,2d35a0b2,27582d2c,b8155b92,680f6651,c0040508,ae3de034,cac87591,654c0c86) -,S(fcb1fa46,f8178153,fe5f10b8,a91a411b,cdc4cfc5,61b5eb2d,29446a79,8deb14fb,29c75252,4cb13054,2b9c1a26,b4606eae,6f40ba1a,f73d006f,5bac65e9,3821f0f0) -,S(7b86452,e43ae1f7,177c131d,999b5fa,a6e4a107,e0a06f6f,4305a8ff,d1ead9d8,3e7cd53b,b2f27d89,829e331b,8236f92e,fcf674c6,478846c2,c18307c6,e82691f5) -,S(8271b58b,67a27540,c1d8305a,840475f5,3faa0031,4e779e2b,9e578c07,366a342b,5cf145f8,6fdff832,6712be08,ca1f3a27,d3e58fc0,baee76f7,a052f7df,450dbed2) -,S(3f027c76,4ebf933b,50df3d37,77f60210,4b997d1d,4b9cee19,cb549c58,b5d0fa23,cb44dc89,c533abb3,e255fbd2,6dace4aa,836caf4b,2589113d,82ad1886,7eee5d80) -,S(fbeadb62,ffe218e5,d0245d5c,4bce7334,cbbfbe91,610e8bd9,f0b89953,bf472bf6,7e824c09,9727cd33,1aafba9c,6776815e,3f954fb,539efa5c,fc4ce034,db602c09) -,S(ee2807ab,44643652,12b021b0,dbe94618,5d22fae2,f500a740,127f4dfe,32ee4c60,d958ade6,cb9d3a,ae21602e,d25556b3,b3869202,beab0910,1a1d97e4,8e360e1) -,S(94ab159f,2448f865,f3d38d65,12273da4,ff476289,3dbf74d2,ef889807,81d6802,88739de5,da331b70,87c58bd0,d734bd75,5853753d,1d3b97fe,39c68555,8868576d) -,S(98d2e8e5,a41a0bf4,a880a510,b4b65321,7b9a62f0,c466c589,d0c1634f,557666cf,aa24bed8,a5cacda,bc3c950f,d56bbd1f,f156efb2,4632e073,ac822875,2617d1f6) -,S(64efcff2,76cda1b7,c8e5ab1b,12c73a48,5a25113,eb9a5be,496e52b,ec6ad16,ac29e2d7,18bbf63a,16003992,d85a9090,98ae89,834dcb24,293d6bf1,b8130e3a) -,S(6a8e3376,1636ef4d,b1116d54,34f3fa05,d8cde7e5,31b260ee,6aa9ee61,1c4cf5ed,5161b5ef,4bafa1af,f76a1e21,bdad444a,2526cf5c,c81636cc,36f18400,b8dc47af) -,S(4786ac32,6312dcbf,a1386ca8,c505715f,2bc7f85c,22b6049a,e4386bec,11648013,67c80d39,bfb6cc58,7fb312c3,8fea53cf,6937216e,8e7f3b3b,4a2290e,6d6df687) -,S(b87d2d08,ee206c18,646713e,8af6bfad,c77754c9,59158fac,c31928af,c66bf596,6110c98f,bafaffc1,7b40277c,17ad9650,15de7069,705019c6,b7a74cae,eec6e65b) -,S(ea9f310b,d088429e,236d565f,d1b3129c,7ca8573c,191d1893,c1c157d2,a0867d4e,61c95d39,c1893c68,fdc60ddb,27909f2d,98c9ddd6,efc67ccc,7482c0e4,3c05b144) -,S(abf862bb,9db85d51,5d6a37f5,5f3942b4,5404238e,d49d3124,59f9ab38,29b34ebb,30d13c26,2157c1f,1ffc8a46,a3679e65,35be1981,c202e7de,10de5386,db863739) -,S(80767b75,df3e69dd,757b4c4b,fd0b4be,f75fecc6,ae22b488,214b0035,a276e492,ceea1fbd,bcce30be,2d88b601,895a8fd2,92f61b61,cafa5589,f9eb9652,8a78fbce) -,S(8b7a47e7,dfc35093,77771622,482e45fc,84708ab2,c9c734d4,fdc9e8d2,499dd950,dbbd399a,d62e8309,14bd0ba6,19a9963b,8aacc765,cad19734,e2526af4,2b2013d4) -,S(13700ef1,f1e82cab,7e9a7d79,d76fcfb0,b6e8c18,ec1e6546,d27eb919,bd871f2c,97488000,f96aa2a1,5913502b,30ae5bd5,f9edc84a,f97dac7d,c79be68d,a0f7f4e0) -,S(51f9a79a,991fe61e,c5b7c93b,d0905bf1,2fea0e0c,bb9e9a7b,d5d99188,f42c8a16,a3ffae0e,92e3bde2,51c9a8c4,1a6d05ef,2fa2ed53,d7a21402,e759c102,65d96000) -,S(ec7c6892,644bcff,715b027b,be48936b,26dde18c,bb4a1a9c,fa1628ba,84d5b456,51bc2b69,b76646df,51644c28,8570bac5,d51a0e9d,6e9f0ce7,1abf6812,650b18bd) -,S(efb8249f,bed3299f,7715b3fa,b6a23bf2,86560ad3,72e31e6c,ec725522,227f5c2,f36f4624,59a7fced,3c621158,8eac73c5,54593c4e,b7c82fe7,b0951bfc,8987bba0) -,S(4efe94a4,c34083dd,49762ea,eaf58feb,72f6e283,9931b706,56427bc,e9913bd,5c8b9448,5c687c16,76605dc2,d414f37c,da98a562,c71e7e72,fb2b8d5e,6ae0d60d) -,S(ecc5864,fd6a1f7e,1e20a84c,d9dc7090,9775446e,2e0bf6cc,bf896bf7,97f9dd73,49eefb1,981d4b87,ff21ca80,5471770e,8e063541,58e9c1fd,9995718b,14d9d6f) -,S(133f3710,9bcf5655,48d03c90,b82d55de,cfae1cf8,a5f3e117,5eaee107,aa7eb121,1af96963,e9113d2c,588ab083,58df45cc,8b68312c,9aaed504,3f17fffa,b29bdd7f) -,S(a8b1b9f3,971667be,2a65072c,efe8b1e5,e64f652a,4758f51b,4888087d,4fb489b4,556d9a3e,c2861fdc,da258a1f,8c6e81d8,1df43669,e64e3daa,90dad4c7,c6c0b662) -,S(104889df,dd81534b,655921ae,5483db4b,b3227f2,fc3563fc,4af46e1e,2c4fa88c,a70984a0,ce97af36,b827aaa5,218a9743,73feb2e6,fd7e2a02,408590,47323ee1) -,S(4603c58f,4fbc4575,7e9e165f,8a4b41e6,b0d2bf09,b1124998,3881ecef,2a8852d7,37e5990d,7c50bed3,2b72a43a,2e6a0ac7,5676cc82,113e3196,d6569e21,3adcd0c) -,S(5d1ddb75,774d6419,9f07f578,21786ad5,9fd7119c,f895196f,deec090f,1240748e,519140b0,1b340a4,a7aa2864,fef5a066,feb59c6,3355c222,6805e45e,160bcd9d) -,S(c9f86104,62644b3a,ec4daa3e,bac656b9,de816cc3,a5aff1a3,633f90af,8401a97f,405087e8,80403629,516d485,f17590a,1277e058,840b3fac,4e02d3bd,7be92954) -,S(b774b1e9,9f42b296,dab0e371,6d4ee04f,8bd517e6,7846d0b3,3ef5e0f2,569e97ae,ec78bffc,d6cfa76e,513a2b4b,db638f73,519b570f,f423936,ec0a54f7,9ceb5f9) -,S(d7a1e238,ad3eddf5,29002e8e,87476ae3,6668d656,595b3d10,2486f1a5,c30e6a28,5c9fdd1b,e132b9eb,4d7b935c,2209e105,55cb28e6,c4616be5,7b248607,697ef6e2) -,S(832b146a,cd002cb8,199e800c,47b2a0cf,d96591e9,91f1b406,b2db981f,c0aff924,f64632de,b99254ce,9d60b026,76551e8c,e21b300c,86fa5bd,8bd7c32a,4a81a18c) -,S(635f97ae,1785487f,437fee89,9ec21d13,dd8228f2,e209637e,18c85ecd,6cf50202,b53fec65,1a1af1ab,2f51eaf8,8a3af104,e1a40e82,691da03d,9a179c6a,3b30e5f9) -,S(f882f983,99891dcb,d58b931d,c215ca05,a232aa9a,7cfe5acb,5226ebe4,f4a598de,3d0313cd,aa36668,5422a6e0,2dd7c560,11fef0ce,3c268a42,3509991a,97cb4562) -,S(5b16de8e,3f8b8670,a98099a5,250e3102,51107cd5,d04bb804,e2a7175f,48183594,33c3d3f9,e3099917,e707a429,3c83205,4a26cf2b,2a9e3118,fa64f441,e7561fcb) -,S(b47e085e,c7a7977c,be3e2329,ea417e98,e86eea9b,aa23fc93,67cc06db,cf06647,cf6f1cc3,f564879a,f9515604,4b7b856b,827335af,5cdcd55d,1f8bde5b,d3f539e5) -,S(afd1a856,e0624d6c,16a876c1,2f78ba44,303460f4,d3cc793b,5dd32a98,d8aca9b7,3b334e53,83301f24,df0e2df6,12cbd7fe,3e1b6650,d5355bb6,c9d3873d,f42d73b8) -,S(454316e,69f558ff,6e19057c,9c754b2b,83eab233,f696ccd1,b80bbb42,3c81ae57,ebbbce3d,4e1cf2a7,315a394d,d03bfb64,300ac0f5,11627d06,7a5341b,43a4ace9) -,S(a51f1d61,dc60b34c,65345205,b2a316ec,766560b9,c50d72a2,330f828a,ec978d05,d4e9b10a,58bfcc59,ef24379f,532784a7,ccc4c077,8aa11bd8,bf008846,44175faf) -,S(771329ba,3ae1f814,764fb9c9,ebe68f37,26b8260a,90d4e49a,7dfbfd30,80cc6128,128479e4,bbcd5b06,ddf46f49,614f6ae1,bb8914a0,7a0a5bc7,34b69b39,caf71b1d) -,S(aaa59016,d18bc9e6,2716bdb8,6d0c6bcc,e04f74f1,98f17675,c021d078,166c9fee,36cd35fd,53be5c17,84dec1ce,80ab3ff4,95abf363,17824a12,71cef620,2784f91) -,S(be187d0,b3afc0,bcbf98ec,bf31bfcb,f4121265,c4b815d6,9403d9ef,926cd254,a3aa0d55,8b5f6720,9d8a6514,fe22026e,66e8d972,912a6503,5faaecf0,ac2d9b25) -,S(228afb7,a9564fd3,641bd417,20a0e44c,d2ab5d99,844fa61e,264ca823,e197da88,24457982,391e3209,88cc44fe,e42cd242,80fe1f64,b87814b9,bb485d2,ed0d7757) -,S(dd55db40,e3333379,7b8ae013,297b477e,bca2f586,16f29300,6625aab4,6c367ee9,836a69d6,603fd34f,92d3f775,d25ce89d,b92d2803,48a21178,44f9273f,1a97a9e9) -,S(f82dfaf2,5113d8d5,728c53de,3b43f2b9,d2aac0f2,f90b762f,390f745d,7e10093a,1097ff80,ef2f5dc,88873c1,2b5acf0c,a8a803cb,ba3624d,4a036649,ffa07bcb) -,S(666f1006,57ebb1b,f05f50c1,2bfa7fe7,cdf11e0d,6cb37c99,4b39df89,acefc7e1,3e3ceb4b,eb292e5,3c00e4bf,ab6dd9d3,becfab1f,19880c3e,cbb93a4c,415f67a7) -,S(9769b542,3b098d8c,18871a53,8403ba2c,d32f556a,7ca7b089,ceb9134a,5d983e73,536e7c80,5c71c49,9d9acbed,c6fd94a8,3e64a2c,8afd8721,12f6848d,60851084) -,S(26081d34,3771ce6e,39ba59dd,2c2e15c2,4c6903eb,b6c157fd,b1c51dc4,e5343bf,82f6d675,39d04825,4cda5bea,e4879547,9570f86c,9ccbe1a2,ee0deb39,afcf5efb) -,S(feef7b4a,dbb0e287,a0762b14,445a8fae,b860e08b,19600b41,45d92447,be732bde,44e79fff,55aed478,f8d951e7,f4a327f6,c4a1e282,ce617a3b,5128f528,33851e5) -,S(ffb8488d,f26d306b,70b5b1be,4b6f2e4e,b6d6b2b,4cf05d3e,9502f3f9,81406cef,f2891496,f5affbf0,bc60c46e,b96baf7,2a4e6797,3297a28a,948adb92,1cfd5dcb) -,S(fd1ec3c1,736f2edc,5c080981,fdd99fca,9e301851,cbe8d840,38f03a6,59f21ea2,86755e0c,7b01dbff,ed701a7e,b5deb21,3566f331,d707888f,4f658879,cfbf3bf0) -,S(addbda08,d536486c,b9d0b4f1,5ffc9104,ff75be96,739d4641,a405e2c4,2775fa4d,4d70179e,1237e2d4,61a0a0b3,c3bf9df7,9483afcc,1b8fe02f,47d4b312,2f339089) -,S(fb5e9c09,8ff0520d,b162e57c,19b80ced,7c63ea68,1c7a2c56,2557a1ea,d2d7a46b,c4d9cfa0,d31cfac0,78c187dd,2ccea738,4667776f,b8eb0935,9330fab4,b9f67e2c) -,S(28c33364,1762626a,c9e4d2d0,53a1e5f0,771449e7,a0977f2c,63db4681,1c675b45,239e717,a76b80f6,2b11c6f2,c459d516,bf81dbb1,4dabba88,9f1e627b,5fcb525f) -,S(68e783ee,84fea44c,59c46bbb,170d7751,c47fb05b,602e9995,2469def7,cd061c9b,7054cae8,31dcb37f,ae8d8298,859b4e56,772f8a6c,d079918d,b49c7bbe,cde61f16) -,S(1526613f,fda17eea,1a7930da,c1be4a6a,4ddffaa5,1adf3c92,73f3a2da,44d69c46,c9c3d04c,996c4d40,b906bbcf,5b0ac89,f541ae4,81b7c5c1,8f9b5762,7b9796af) -,S(263e6099,2adc9f24,1cd1c16c,de291760,babe6e41,d4e3d064,f1a8768b,94bc5439,3ba3eade,1c5b8225,7559c0d7,97c47e5c,41f60195,463b2eac,74801439,b3a6663) -,S(ce58e7e0,73c871b2,673e18e3,c9ebbb8e,e6bbb2d6,226e3d0f,4bbe6bb6,73e72816,85ba41f4,13158058,fe8d068d,df70f97c,acd4f512,cdcded1d,ff9c3c39,eb1ce1f3) -,S(47c3eb29,1402d2d5,25a95ee6,fc54d1f9,721f29c1,e5b51cb9,d82d234b,94de6594,beb5da30,3383e0d1,4d13eca0,8eb8af0,14f8220a,81b1e8f6,47c1f95c,4503380e) -,S(8f5e8092,c71ce97e,af578fa,52f174d,ad0133f3,94bf2ca,ef5c7adb,bbb37ad,1ca41380,ac714a5d,3c6be070,117b10b2,dcff62d1,bef220e2,4063c971,89f6ffa5) -,S(edefd606,5883e90c,31215558,b05f297c,45c64fcd,34cb864e,3f0265e5,7e7d5a4,924502b3,1d0e8df2,2a54ae07,edf1b0bb,f2ad1df4,7de805a,43ae11ae,8cf3d628) -,S(31516a47,50773473,6e691ec4,e6891eef,601d6e42,d7f4ea4a,1e5008cb,b77e151e,7f243d73,6ec9d71c,d2047cd8,d97c159d,345003d8,72556e94,4f7aaa74,acb8562e) -,S(9049e0ee,149d379b,77963972,1027627f,5cf68f7a,9b1c81fd,189ae6dd,eea5c552,ecd60031,71dd9199,77ef92b4,262388a0,7aec9cbe,65d80882,1847a5b8,c758ad26) -,S(977ac11,98214ec6,eb92699c,aaa9c219,6246df82,85a6afd2,fbef31,a5a93b8c,27e01787,d6e29c74,f6308e21,24f9fa99,6a5b78b5,4f45fc95,b71430a,abfb964c) -,S(bd7ead55,e8ebc96e,5429f59,52427ca3,8dad3d9d,649676c5,52a01099,3c359a26,9e596b26,8c90186f,8cf38e1b,f47d6d6a,d7204c78,b557b3bd,25125bdd,c3ef7824) -,S(90c82d89,9178857e,e2563cdf,d822b872,2901b53d,3b93a6f9,2905a4a2,163be70d,3779d0d,c99fc814,8b2f58c9,fab70952,373365d6,1adb6e5d,9ac3f761,9f27e943) -,S(a312a0c,3111faf7,2cea8b7c,3e2786a1,65362caf,11919687,3368c77f,117ac42f,1b78c42e,af0e6219,ccbe3ed2,384f5529,dff57894,b9c82566,255fc4d0,fc798b6a) -,S(7cd723db,c046d3f4,5b0fa248,1197790f,688632b4,5f57569e,2f7754c0,9fc9bcca,eb5fb704,a5cc0b22,979bd64a,790f428,b57bcc79,3bde8fc4,4d6bc9b1,8c21e495) -,S(2b24dc16,59324483,3851815c,1675d051,60713a5,7dff00f8,9e72df7b,d1c7352a,ab05061c,224fb577,a72f5d2a,38a9e59d,18c52645,9564afca,a9539d0,c64c8fc6) -,S(955ffe05,c4653033,c2b4afa1,fcf8d3f1,3b55c9ba,80d67c37,598f6d87,97f11b1f,d3502a31,bb37b950,93b3e594,944d4bac,3314d490,d375e118,4e8c5a7f,2346e6a5) -,S(699392f3,c2baba31,1bfa8aea,180283c1,9036ea92,f287fc08,adb32fa,6785fefa,242acb3f,fcbce5f5,9dba097f,3d358862,11232403,2730700d,724488e,8bee3478) -,S(193d04f3,61eeec14,633c702a,f8e7eb22,2c3de17c,a0130e9b,cbfb3daa,94674d24,39b68a32,79e62533,8bfda780,9f0f8264,ed2ba2b5,ea9c0035,6459882a,a943e088) -,S(564387e1,ed778e70,baf9f876,2a0171a2,6a4e660a,bc6eaf1c,7ef9f00,69794817,7cf553f9,128d0716,e3c81039,3d1ca83f,1cf0fd82,7f7d4ff0,ff538637,34ef42cf) -,S(f0eba12f,b282171f,d20aef8e,192741e5,4469c5c7,bab13f51,7084d293,c3c294cf,bb0211fd,18229247,5238ba93,f6992d34,a41a7ae6,78750b04,fd34f3cf,af61f90e) -,S(a54b91bd,b09d29ab,f4cb354d,283c436f,a8e9cb20,d3a7fd35,e59f59c4,200bc13f,bae1af42,3459a852,bc16d45c,cd35fd94,c0033d89,5c86fdfc,f4fad5e6,3bec2cd2) -,S(a9294788,b2c9d997,18193553,403350af,78008113,ed58cbcf,a2816c80,46f75d47,dea8059,c24c1c84,44a0263b,2896725b,79c2c8a2,6d425479,f44bb7ad,225bed8f) -,S(b6967b59,ea3d2899,c14fd2,cdd4590e,68dce683,de275313,ec94d5d6,1bee65d1,67eb4a27,8813f69f,e5bbc586,15dcab17,11bca30,77327665,2fc333d0,52fd2a0c) -,S(ffc0f3fd,241ebede,ddb0c43a,a9b8fc2a,9e778963,1af8d54b,bf99c64,add0cd7f,203e3aec,321e40fd,414c002c,e5c6cf90,2f3e75d8,ae0e3604,61028ca1,e21da260) -,S(d8f86220,c390bcfc,f714ec3,8b6f6ee3,d37b41da,4026805d,6fbbc798,8a936ab2,7c0ad863,31ab776f,c22b2539,fd65086,2cfd2ba6,2f5d67a1,6eb957b1,8d812bf7) -,S(11295381,19a146b,442c3447,400b6e7e,9b2190ba,dd42a75e,24460ca6,45a3cb88,44950501,75662a98,793416c5,3c55febc,7babcd29,398d6099,23e1c3e1,92dac1ab) -,S(d7cf3779,236c4a8f,d592525,d30dc0a9,a3318c05,1823e0b0,43a6542d,f38d92d4,1f866df2,429a3dcf,1a285265,18308c25,262c1ea7,2aa2267c,39a315c6,dcd22ac) -,S(d2bb0f89,a0897404,25fc85ce,4d8fe24c,ca061808,e426b08f,ff49a525,137449b0,fc4c4bfa,2bf202e,4d10969a,2c4ca383,17a8c179,20dcb965,7de7aaa9,6b97ff33) -,S(832d95a0,cfb91494,5b43d9a0,4f037266,2ad4453d,353f6e78,47d4aefc,449dabc2,6ec0aabd,3c3981b,8ff55747,63bfb800,453f302a,8161de79,b6b623d9,253124f0) -,S(3a224983,f83c41d,33d3aa2a,c9d29ca9,55850388,a968407,664b2830,3967f25c,7cc31841,96c4fb8a,953602ec,3c79ac75,69e1fd1,7a263946,27826a88,7d651f79) -,S(81197d87,1452332c,2fb18793,c0ebeca,3d1b8a4c,f161b709,e3da21f,3917917b,56a0980d,1ed1f77,3c960de3,1ce4aad3,90a5ea76,fc410a2b,107ed82d,b8bdbef9) -,S(b8204012,c77ebdcf,790f48fc,4acb23f0,b03e5d40,6fdcf212,81545200,faa2b4b6,b8718e0,12ed5a02,16485561,8a5fb6c4,ee4db08e,dc9c1842,881287c7,dc7191b3) -,S(766d82f3,b602c418,d020596a,58e61400,20f58fd1,52448443,2f816dc4,8d437750,d17969a3,c71ea79a,3854b526,efd56f8,148b2d79,3ea3c76e,eb14ab7e,de5841d4) -,S(35fe7655,5d4c88c,dacad9ac,1bf125d9,924276c7,8c2ea9c6,a9c1ae87,52d1e323,9ce2d43,ef8fdb37,82a38d69,972229df,9b9c0c98,abad263,1df192f7,e0e75324) -,S(a29581d2,55efc206,4d1d1839,621daef2,ab049724,167ced73,7566f4cc,3a81f5ad,7eced1c0,575b6152,38db2928,964f7713,f65edd4d,c31a4b34,ae20b6a2,babaa8b1) -,S(d7787fd3,75473801,2370e71f,4d2575a5,b9f89e11,aee370ca,2660dff9,dc6a807e,2875ab09,bb1b2a7e,cc6cb39a,939e4a91,2ddb1dbd,5ca43ca7,93ac663,552ae91c) -,S(1fb6cf61,e8be4d39,b36578cd,8853da6a,1e62cc7f,29426838,a7ecf0a2,77395288,1c018114,2dfbefaa,6bfc2957,6b79c91b,16cf03d3,81285e2e,b74f71db,1986e43f) -,S(511e9c97,866e651b,c4e32e41,92f75019,42316ead,6a0cd78d,fa61e0f1,e76aab8a,2e8cd531,d55bb19e,886b86cf,f7105591,68a9507c,7d78d34b,9ec50f92,5485931f) -,S(74afe7a5,6387bd58,d5996a9a,9650730,44141ca3,1f5236e9,da977289,73c9d434,be7311c2,b4566819,12d13546,8ac1e26f,6113b960,3039c24c,5e77edcf,de452567) -,S(5b545191,25d5f8e,cfbae2ed,bb724782,d07ff380,10eca9a9,29ccc9c1,ecd0f04d,21126f87,a0cf1824,1040d707,4d37e8a3,f035471,63de669b,9f502fd8,92322dfb) -,S(5286fb50,1a525e82,a944d1ba,eab49572,52d86693,19af1367,eaa8d5c3,e73ee8d9,f2abec43,68f3800b,30da81de,5b81e564,f94942a4,9409bcb,a9faffd2,51daa0ec) -,S(7b01eb86,c102438,4be1f023,90a5ed7d,beea652d,cf3ef77f,92fd883c,f2993069,becae52a,915d1393,15435d9d,edb72e2f,fb9bda33,4b2e39ed,6e698344,9e1ef819) -,S(3955e911,874fd6d6,74e04ed1,ea3b43a4,486a0ac4,19735114,3b451c3b,3028a674,3552c619,a845adea,64951c82,75994959,8609a3d,2f691d0d,5947b474,4636e06c) -,S(b67801c6,d96aca89,22d8e7a9,96e95729,c4c29d63,180e4f73,dcf013f1,98eb0d29,876e3361,d82f58f3,f1292315,1509ed62,2e2a73af,d063466d,4af5cf1c,1ffbb150) -,S(1efe4004,1c7ddbba,1aade160,cec007e9,8abfcba4,7d292839,4598b5c0,1b763b10,d9f00f5e,d0868390,230168e7,c5839be7,cef8ebe0,b3b70d73,ebd92931,678dadac) -,S(2083d5be,389e4bd0,23f7685f,2ad00b23,e3687672,72183afb,d5d02384,36d122fb,11b6176c,c7554617,935304d0,4e12e8a7,4bacc20d,d438bf77,a1729a15,b424937e) -,S(8a9420d3,93ff0ba0,25bcbb4f,eaaf715e,4ab14281,85b2dd91,f8eede56,f3006e46,f48edd10,dff93031,2b5df63d,ec9c7a2f,ca373d77,65033de3,8a54d37b,2ab1f4c8) -,S(64a2e8bf,b42de0b4,b2dc8fd5,9e3b2c18,753b43dc,e914fbc1,478818f8,145891c5,82583660,40ebc62f,d5526ecb,9f952091,47f7048a,4004a0a4,7b08905,12ac098) -,S(eb97193,28c44e0a,3f2568bc,b99815a7,c5c2e7b7,90e7fcb5,a2e7f7d9,920404f,cfd26c16,e6709873,1219fdc4,aa8ed998,c6fef955,78d7908c,c72c04a4,4bcf305) -,S(cea3219c,e03a2433,f9ad8d93,73a6bef6,c1f30b3f,fa79d7cc,6ced36be,9abc9c03,13ea8ed6,a0dd8fa3,29bd7563,a34f3499,6442b03a,f2eb703b,d8d5228c,cc4c4e7f) -,S(2e1675b4,f00a0843,89b0587b,f0cb723e,1a833539,c024caed,36101cb2,bc4c4774,ec1d76d2,2752a662,5dafb3c9,6235eb94,f9af1286,2b3eff6d,2a0fb965,ad3173c7) -,S(b0eb3277,7c8d1b09,e22c9b9f,1c37e8ab,74be3c49,7ab6d73e,7fb6ec11,10602438,6d44054e,a4cb4a22,3811bbf6,6d2ab2dc,f7263d7d,6421a368,9a9ca4f,97fac66) -,S(48254bd4,8df24e2a,759c5ef9,cee30855,1c1f79da,b0a32695,2196ea1f,987b6d70,9c12a458,f39f4880,ff04b96c,72b8877f,b4ad0020,495626f4,1d9b32a8,84f7a36) -,S(e3c6dc6,cfd0b94a,57b3d34b,3a77f4f4,45328a12,764e4619,efef75f9,f49fe8e9,5c229420,500f2fa2,888d834f,a517188a,207d8f88,c98b7b7d,31484a49,c4d43a31) -,S(a8d9d9cd,def3362c,b260ad0f,3de51aa5,db066c74,4166d9ac,57db782f,656be9e4,bc696df,80eaccdd,bccc9ac8,960325bf,1a0e9aa6,100908b3,cd0c0ce3,43205db2) -,S(38281034,a34cd153,34b6fdc3,26fdc558,555147cb,534a1c31,89beec74,5a2eca97,f4371a13,a65de538,f31ecc5b,50ce4b92,d5dc5645,9e523851,f6fcdac6,5994b5e0) -,S(b745114b,449f0d7a,4521d7e6,728c89ff,54131e6d,8add9f3b,bf18edff,bebc6ca1,18678d66,781a9120,ba33e01c,ee3fb1ac,b7790f18,b30a651a,99b913c,e621eb67) -,S(5987629f,9c26a8cf,ff39955c,3144f4ab,c4d094c8,8270f3de,620fcdaf,93a7fa9,a554b7be,24e49819,f1256c9e,72b8d981,2aa5984a,c942bd81,5709ee03,67894a07) -,S(8fc9dd0,d84cf297,75ece75e,8cfd7c38,dc9f602a,b0152b01,982be4a1,f29b7290,ed128f96,2cf60503,7acdf6d5,9578ca8,9a232a0c,c432364f,2b661ac9,2a3176b5) -,S(c8b5b1af,90d64379,f2c02ac9,51ff715b,2978ef0,bc87f721,3edfd09,983ecc35,c295c0d4,964ef85a,59490ae,dbfd98bb,f6096217,d7633f0,44470b6c,a1816b55) -,S(b4eabf60,c44d78fc,298b2c90,6cdcf7da,a23d095d,867fd304,513f90c5,437775c5,82d906a1,2d10d6d8,e4c843b5,48ab645b,e6f32104,f07d8fd8,c128351b,e7b526bd) -,S(b19350e8,a5163076,bba0b2e7,2159865f,59a8ea83,b0154fb7,64308bc7,4d0bcfa5,29e4ca7a,554269c3,21a12b37,a4fd0fb2,d3e57ed5,4e79423d,f715bd2,ecda9907) -,S(fecf1ff7,663c7921,40f4deac,ced92484,8c66bec6,f4a5550d,c340896c,5543b886,b2621f65,d52538e2,92a50808,9008efa0,8f530fd9,a321bf30,6dd24f26,c9a1208d) -,S(ab70fe2,355d6d6b,5c5a3f5,a6bdb605,86372165,b8f07d2b,ccfd61f4,798dcb7,7adfb6d3,dd44adff,87ce3727,efef0bc,6fdf9f49,44fbd238,822974d6,dd57e8ea) -,S(5ae5d60a,efd1dae2,43df9d7e,ca025c3f,452b6c62,216c1c1e,8b315ceb,b94769b,d90d73b9,6e33cbe3,6d96c45,656f098b,e7e57d25,dd03be95,8b9cb2a1,d00bb434) -,S(fc51f965,bf8dbdde,b5fa4af8,7abee8a9,a380918d,4d8524e6,73f8501a,291eb96b,ceebbb7e,35eda612,47ad8c8a,5d54af8c,9dbc9bd1,194ba5a9,5844fae4,b658496f) -,S(368b51e3,778f8ddc,2d09e9b7,fc2808c8,ac793edd,244fe177,fe3229a,e5a6d919,5b3ff9e5,af4c6ae0,575b553c,c0ce17cf,fc4da66e,e19fc3f6,2d047007,e1716db) -,S(ac9c4efa,5f63ca07,35fafa0e,9612b459,1a764955,d435c14f,91717e42,26ec0186,5d4d3ebf,9a064670,e09f1d48,79bc9e3e,22198188,5610731,29aa403e,73d7777a) -,S(2b5f951f,360dbecb,9eb1d31d,b414aa13,9d9a7d7c,ed952a72,c0f93a61,d52fbc08,8d46f1b9,cb8883e4,cb504715,eae4326f,11187e46,de477dec,2108ccbc,2b3ddd35) -,S(25a3593f,9670924a,a35c2008,bd8278a9,a78d22d6,572841c,98c4399e,26f67cfa,3b07ab0b,8d400f1,af88561d,af8bb7c6,a6e4b7c6,a8bf5915,4cd85291,66ecd965) -,S(3f03be51,b35e265d,d9cb974c,4ac021d9,d22b2291,40016bb4,e9edf52,36193eca,a17df05d,e4b0e5bf,c7ecac3e,e3253017,cc1d47b2,9fd3d1d5,411f2660,c34932f9) -,S(edbe9bd6,f16782a5,a00d7003,488b9291,faa4f22c,9602c736,a3698587,995d25d,64569751,212d2f6e,c2e7a6a8,973be7fb,c49d7a0c,8857fe76,f9c48011,735179ed) -,S(1f477d33,1fb16ac7,45c29e48,77df8c17,83f69e85,5a111a30,e4717fc8,ebf85377,64c947cf,64a66ad,8a417bae,1bbc1cff,56826349,e024d3bc,bc4a9078,f4bda708) -,S(b8ef8b11,901602cc,9fd1559f,c4bd6bdb,22f9bb7d,8b289c6b,fdae85c3,e9aa3e9a,60b3594a,7349c920,33d816fb,295f41b2,7c4d1d86,b4c9d2e2,2cc3f4f,e603f582) -,S(eb6b31eb,198741f7,49e4b69f,85c23e4b,58e3223b,df8537cf,60a94411,f03e0071,576746c8,ba579896,969c228d,67a57cd8,8501e27c,773a3444,35b7e860,bec9f471) -,S(47193aec,aeae207,ad675228,f4506db8,40a316a2,6cdb328c,2af6c24b,bd5e9a8b,dc67bbbd,ca7cfeb5,981571f5,7022986a,4ec3e408,b641c34a,57b7cfd5,5139a1ad) -,S(ae3c9591,c2768a02,f99b0076,9c56fdf3,1a98fae,1eca3680,38698abb,1d44f961,ba9b0c42,90c2fb0a,ad84754b,e1c3fa0d,7e34f737,f3874af0,4ed2824a,46efdb24) -,S(178ef542,8c4cc38f,f088c383,71f0ead1,4e7b4423,6d90bc7e,9ffc3db2,fdbe9b9d,a5f01afd,74aa9324,b10f6041,27ccae19,24da7b23,72269ef,ab984fe6,ba1b347b) -,S(2df7e5c1,3d0fdda3,3ef8f69b,f0ebe1d0,8649b106,8c965d97,37a7e9b3,c13f4c92,eddbf5c6,324853c3,7d478864,a68d0b40,2c28ac46,295c00c2,2359e10d,d0693d94) -,S(671abd13,fe274da6,a5cb6119,f33fc88e,37ee1b75,59adf215,e08fcead,ee946b8,49d7cd3f,3b8162f4,a85787c6,91bc29fd,69eaccb7,1354bbc2,8ba17227,8a8689fc) -,S(b69fbdbe,e72b1418,6fab59f0,6b57d940,fb8cb5cd,92c53727,a0eed42e,532ed39e,71f488d2,e104d21f,c816631e,d774a714,94c0c609,c86ee052,210113d,672ea302) -,S(1d5b8e6a,25fcc50e,a4a5429b,6233e276,47d978d1,28a5f495,a66b1b12,d7cd8714,8428efab,d2bd23c3,2de8da3b,cb630ee7,ebe84541,ec3eff60,645ec4fa,3978a6) -,S(4844a10e,ffce265b,1a5338e6,a10c4f18,b95b0681,bd702e30,9a376e23,7fcefa22,9018e1d0,34bf225,b4826e42,565a76d9,43c868c3,168d74b9,33b34596,98b5192b) -,S(9567ea6e,231a9c9c,3ea5bd83,59b7340c,dff96e3f,d1fa7a5b,c56c88a1,a57d951c,507e21e0,cc59bab1,f2c38cb3,42b9f83b,f291992,a0c83edb,4cb62b49,6c54759b) -,S(60f2f714,71258f56,6de74774,eda196e,46a30d66,3dc0b308,1cbad662,72f07bcc,12588be3,f62dd2c8,1e485efc,76c754d2,de642f53,d3937c68,f058c61b,ed7b6c22) -,S(4276ad32,b33ba53,ef2ab0af,9fc42af6,6c7bb23d,c7b7a9df,9c00e1dd,f76b6283,9c477729,c61fccfc,a2dc0c3,c3a9ac89,b98f437f,bb221be1,268a6f17,5d0dcd9b) -,S(fa3ec157,f8186c36,3419d818,4473745b,fdd2d054,e0c16e1e,fccd514e,95c9336,a7864a68,91aec12c,fe8104a0,eb3cbec4,4a907380,11a3acbb,d5fb6680,289cfa2a) -,S(7d7d2728,b1db5fdc,38ad6a75,3f39df22,88d50838,b106475e,28ba6eb7,5248b600,25d9d454,8b505739,16ec7bcc,877f6aef,e2641eee,8f78f1b1,a7f74c11,40173e1c) -,S(8cb9cc7e,4ec87013,b6994670,aae06b1a,a4785c06,614ca24d,cb6534,6592ffb9,728c4a8b,36bf36b2,a0bedad9,144c3261,71df8448,e87d151b,d8bee067,769113c1) -,S(8a9aadfc,84aa81d4,46442635,d47a9a4e,988e64de,6fe8836,79b8de44,f57c0169,60f39bce,be18abd,10afefa0,2d076d49,73d9615,10017a1f,469eab8a,c15eab60) -,S(3ea01e46,3a9bfcfa,39125216,7b6ce771,5fb309e4,37d495b7,852be3c1,af2a0b5f,2b756a06,75da2633,b8d2650a,a2102738,d5918420,9c57dd64,7b4c6c2c,c5250252) -,S(a0683395,c5245bdc,24b2b275,e8c2a196,5068fda,253343f7,49ab56e8,93672c4c,7f25a7ca,92d25547,975ddfab,fe50c247,6b4855cb,8f9ec4b8,ecbe9271,779431ea) -,S(b8293e68,1e33b654,7d2902ce,3addaeed,2fcc021a,cf7ee396,9be12661,b2abfb5e,7943e6b6,fd0c90fa,824b1e8d,25d63a1b,c01f16fd,3c9e2254,e1dc35fe,416a5afb) -,S(412722e8,ba1809cf,2df25d5a,49c7648d,b19e42c7,3cc30b7e,1107ee4b,f0aabaa1,557a299c,38ef6a75,61d79a10,ea052a52,818ce67e,1b341c1a,d70b984e,8e41fa39) -,S(7a62c6fa,f4a1f6fe,4a45aa48,a854a16d,a2fb19a1,a5647e3e,28a35d0f,619b2844,dab31641,6241ad42,3e7ee774,acb52a96,26b4b6ca,a4ea0b4a,67a513fd,9637dfd4) -,S(c3915b0c,19df99,ac0ef05,3a07b36d,62643630,201073b2,8e3ec588,6714a695,8f21f136,3cb4ff42,a52f74b4,b10f1dc3,5bcd782d,b477ecf6,38866d79,541de3bf) -,S(2a373fd3,ddd12547,3e30efe2,5533316f,355dd52a,6854d7f4,8144d19b,648f4b59,2ba90aa0,b3de3887,c1ba231f,49b28294,677adcb3,2e81c2f0,3c563e0d,221260a3) -,S(d8729e12,46cc8a52,a5c9b7ee,dcdf4d3b,3d0ff8aa,6efafdc5,ddf37480,2dda4476,1966d7a8,7e527a7a,bc1e829f,90e4e3e8,f4a7df30,48f098c0,df8a5eb0,2a8bc40) -,S(ce45fb7d,2ccb83af,dd1662e0,3ffec83b,5173dd2e,448eaa87,edc980f9,10a20dfa,5973238,531c5a84,1388c656,3d4f3579,41283e31,44d84ea3,31374d8d,e2122244) -,S(230a69,f0fff585,a1163702,4b16481f,65bf27a5,3ad7992d,47ec8ff5,edfe073e,61ae3fbd,90f157ba,6332de25,a571777c,30d8144b,e12d9a25,42bc1877,1b6abedd) -,S(d7f91496,1bdd4fe4,7b538429,df2bee94,cc4d66d9,270da392,a85e8c62,1527700b,67ee9184,bb2cb2b,9671aaec,57634814,b6a1a9f5,dd0430e6,6c5e2774,5afa9f13) -,S(4f2e459b,3eac7349,41cb81d9,2d8b3942,ee7b0ded,b2d9d8c1,90ff390c,aff7e4c3,4188f6be,c3526afa,2b29f953,f5044bf3,8e583c27,395c9f8c,979ff539,b4198e17) -,S(8a4a7b6c,3b598e42,851b0913,209a95fd,edf0f8be,6f152b33,1dac61a2,6f9b6997,53c457a9,f8926415,63e85b0c,b39ac9ee,69b31c65,5e3bc200,d37d86ae,d4291997) -,S(a48f69c2,9dbbc922,78a5f8b4,4a2fa2be,f432a4d1,e6fcfda3,8ad60dbe,6d157990,f251873,152f4ec8,fe5fc88b,cdf28ae,acef895b,1d0f0ce4,44105e14,7ac0ff22) -,S(fc0ec54e,20f7e8b1,fed5cc89,d18a5004,b7aa55ba,7520dc18,c9cbd935,7c78eb4c,17374d8d,36116ef6,49b723af,62a48350,4bd47bd4,c17c7990,fb0e119b,47f21ba8) -,S(8203924d,9fc7e5d7,6e3c593,ad439d3f,8512c0fe,5c298163,c8caaa3d,f7b39755,a224b743,258a82ac,2dec871a,dca1dafc,2bfa8e33,b2217785,2b97e57,2e1344f7) -,S(c4f66a17,a595217d,58d5b5b5,da997a7c,79b870c0,f5fa9dde,e146fa5d,c21f9380,13bc8ef7,ce6f915e,fd7a3522,f5fb9c3b,ac603d0e,343d344c,74565eb9,e8e3c777) -,S(4341f0a1,efdd7d68,435f1998,559e43b7,7d1c6780,d3d3e7e6,212efd96,5b30cb47,1777a450,1a693970,c2bf759b,a253e716,b17cd5eb,9a247d47,cc382424,48ae90a1) -,S(865d8a50,ad3b8c21,f8ff0e92,8e853789,a607abe6,e155b04b,3b81d80,c97c29d4,2a506b83,c4166a1e,fdc32c2f,b2d027e4,837d9989,a82d08ee,a31a46c9,dc72b272) -,S(d8d95cfa,ac50b79f,3189093d,50b03b38,3b798532,3f01ba52,d76f033c,83c832e2,cddf6560,d9942228,5a3c0f18,58a7c27d,fd7b8bac,9b23477d,8677a1a3,c01a8454) -,S(d09fa59,8ae65883,60247b05,519aef86,2b1c5196,d38aed11,e8350fe0,5bfd6cd0,45f51a97,67445680,37b1bde9,86696834,6dfaca49,719c5174,a9f9eea2,92ed4ab8) -,S(e19796c9,c9b48a5e,59556b72,9d9b8073,71cd7267,812b044d,637aae50,d6d3d1d3,1b86acc0,d904a31a,b5637e18,872eb31d,32617930,2f3d6bb9,36016653,9f218d89) -,S(6a88899f,be0c3c82,96fd27f8,6f89283a,f83df13c,a273217c,fef69d8,b048afb8,68ba38cc,bee044a7,a026ada9,d51e8d49,97083dfd,f65bd483,a45eb58d,5cc774b0) -,S(e5082ab6,a112848f,9f5f3362,8be3e267,87e24cbc,6d5563c0,7addeed7,ee44662,c3c1727c,d0c09130,8323326d,210a68d3,68bcbf81,bb3814f,dcfe6631,d42968da) -,S(795f456f,5d0cc15c,72ea286c,c881d8a0,21294e05,cf80ef7f,4497caea,92235487,bea99154,424f54d1,e91322cc,c52d3a51,4627fb1b,2fe9062d,91d90177,20530ccd) -,S(6e9e5f96,8c233f4d,8d2bcb8f,25d9232b,f2230e9e,fbafc89c,dca17498,8d7909ba,3f8b0b0f,e60aaf3a,89f5de79,35f9979a,ac3f3fc6,fb161d3f,29ab2ad5,d50411e2) -,S(72ef1e88,89cb7f22,19b4a7ac,92d5678e,a04c898c,5b83128a,1f7fa8a1,63772f28,dffb88e5,3f348c29,411e4d47,3ccd7d41,8a0617a2,6a640a9c,4b03aa08,15ab10d3) -,S(4a91fcd4,32f6d2e7,ad20787d,749524b2,e3e1c348,31b41041,c311421c,1aff04f1,bcd9108e,6e8c6da6,a15156c5,5c9d60be,e4aecad3,b0756cd5,81b1eaf0,ad300b9f) -,S(5f5255d9,8c7465d6,63fb4507,ac985629,8a434d5d,429d5a9,7b645256,e2cebab2,7c38536c,31e7331a,362fc944,38510aed,bad4cf29,bf0e7cab,c995ac6c,1fec04ec) -,S(866b5f8d,a735ab93,e84f7811,a33f1604,40a51373,7b52e675,7f212c8d,65c9eb05,af2cfb6f,9e32f412,5f1c66ac,61393756,b8c6016f,9d45a58b,43e16c6,d3549be5) -,S(636aca,387e767f,4702fb3a,d7b50b4c,4b40fb78,2c8c44b3,a298051d,bb3a71f1,70e580b,6993c9ac,5a48c2f7,558773c1,f5c4ff3f,aa929635,a2a44e97,c0eacae9) -,S(31a28d8c,2205f5c5,75ddd861,df94bfa,5b6b6e38,83797d1c,7d4a487,5fcf7f7,a790eae6,788407dc,89df860a,9ac25011,8b8c65f5,f47e0bae,6aae95ee,2d733698) -,S(c7f36e08,bcea178f,7acb0b92,fdb32411,a028ce88,be5e3480,a47c2c88,891827c8,5c285010,4742764e,7df86e80,e6e2d975,472abeb1,bd5664d3,a994289c,112a9e9d) -,S(85a82c69,2a5e248f,42a3f0d3,e092840c,de52e31f,19a2a161,85b2ad10,6afd92d3,eeec281e,55c79f17,332c4ce0,7ac4edc4,a3d75e67,558b4b3e,4dc86532,6132155c) -,S(e67482d2,4c2e3a75,3c1fa968,bf120a4b,7883d00,950bb0bd,ef5472e0,dfb09287,f9801b51,e0450fcb,9e405ebf,cb535355,24db5e9,91bf1572,6f446aad,34ae4194) -,S(c6ba17e7,81fad656,c9c93e54,36409414,c58e2761,b0297b8e,1811dd68,62779f1a,92583a9c,515a096e,8691b384,4104419d,c4e86966,4da70b3,afcfceb4,b9d74c92) -,S(67cf02c5,a616b59a,ddd421dd,15812e95,f36e6d16,af501663,9e60dd4,a8706b24,7856ad72,8a5f0d18,bf4bc3d3,75468f85,7bbdb1c1,206fcbc4,7ae66b5,6ac91b29) -,S(72bb64a0,aa8c690e,7bb6ed99,847488b9,f37490cb,a7fa120e,a7b5df10,8fce4b61,6057c37e,198f6428,3b9481f0,53441e97,dc827cde,edc55410,5108fdba,a14d81bb) -,S(1b132067,209e179a,5b77977b,eb81aea1,c480b32d,81729c5,32d100df,310575cb,67482a94,b5ddae4f,cfd613eb,68680dd6,c8172553,18478bf,79b5c07a,b0cd817b) -,S(96f5f126,4b68fd7e,f633330e,f32951c0,3716b62,7d1f3368,703447,f9dbb5a0,941fa02f,c6262bcf,dccb1cdd,1637c9cf,719077c8,1b26e7e7,2bb8fe4a,4d530e19) -,S(95335907,9c15cfa4,a674ce65,113127f7,a1ce740a,ecceef55,da5ceed8,e4e56a51,57ee067a,5f506b14,5c1c20ad,6e5d6b11,9bca103a,60c2e6e3,b5049b4d,db15baa) -,S(72ca7d41,76c687b2,1125c290,e737075a,3281ce7d,76b72725,c7680956,e0463f23,1e6a85aa,246b0f1b,324365fd,19809840,242fef0e,6d658cae,cc84bbc3,ad56af44) -,S(d5376a10,2cf819b3,a439feec,b04d9fa3,c90d76c3,b9bb749f,bcd6aa26,39ed5ea,3659d2df,266a0ff9,c2854f6e,f5a5ab04,1c0d8547,77fd4f75,320e064c,c4d0a4da) -,S(664a26cf,a965b59d,10c05dd6,e0aa4e6b,c66f356f,bb61b699,113a83d9,e0a2b4ff,fd191a92,c88d577e,47e725eb,a3c38b3b,9074bc42,16c5d6b,4edb3af7,2c4e20f9) -,S(7729abf,ecf9ca40,e8867936,7fef2d84,29bd877a,56f36780,1e677273,8e8cba7e,d5cb7517,42c9de11,84dcbfb7,5c9e139b,a59b6255,b59c7ef8,539de55e,7a709d36) -,S(c6d5f50f,e8e784db,630bc589,b4df5810,a2001482,9ca1608a,cd3e3634,7bd8141,eedd06e7,95d063ef,3d1627f0,bc7ef37d,a4846580,61e472b8,89679d3c,d88ab294) -,S(baa60dda,3cf83a11,82dc2ef4,f79d362e,6b32304f,896d30a5,b363c639,56ec70d9,cc9e6274,75feba44,b93451d2,753e94a2,85315277,7674b3fb,c67490e5,3627043b) -,S(370243c0,92b957c4,74df755f,e0951321,49dd3669,1a89fa84,e43a0668,8ca235ff,bbe8ff04,6600f245,349fbf3b,1c8ff04d,8d51185,3e35d13b,30deba91,84383ba2) -,S(1182291,92b1e768,2abe56b1,9f90e41a,c882edb2,27b25559,ce4448cb,dd19ff06,24271274,e6156ea9,e3f82ba2,8a72d476,8509dfad,b985c200,244687d5,8a11c1be) -,S(dd134e0,e4fe672,38716aa4,edba1ad7,6879be6,8b5bb029,b32704b7,9edfb2b6,7aed5398,40cd7dd4,7e94c224,151627a5,62f6a519,2f0d0b5c,416e6f1e,5e8a337f) -,S(ab7e722f,458d3acb,ad28a29,2f90cd8f,c2e09b2a,2beff3f8,f08517dc,e673e3a3,522a2227,c724f9bf,1ae08d93,c4c6ffc2,f5434173,7fbfa502,d6e49b1c,2ec4c792) -,S(2fa16842,ebebd6fa,e6c67327,bd5fdcdc,7e985b1c,22dfe307,23a9e2dc,ec43df8d,f027937c,9624aaf1,ccbf7c58,66bdd9d4,5bbb279,c2a37813,9166b720,32030773) -,S(adf5e014,e1f18c38,fd1863cf,76a6dcfe,65827107,fbe0eb99,117a859b,c5268bc5,c9cb3584,728b1771,16985b28,f5259aa5,279e15a8,1c1cc6b9,2b9e5f8a,6206961d) -,S(d939322b,a9b2cff2,6a2b1c4b,5ffcd96d,822dde66,ad0aca31,c24a8260,c9fc6d26,162fb654,6118a68d,7fb88bdb,3e3ab784,9278a5eb,13a940e3,3228580a,2258c8f5) -,S(18fb2621,71f79e5f,46c0087c,ac8e55d9,66f29a49,e2c91363,58900787,3d7e3a6d,cac82dd2,4a0f75ee,adfe906e,ccafd36c,5b0c97d9,cb150fcf,d08b28cb,83787a05) -,S(b8c0ac07,5d009e4b,5ee44298,89864cf6,fd54092,df835ec2,6658c902,57b670d3,2dbc6d4b,6ff28cc1,14e1f34d,2b6cbe52,7ca7dead,24f84681,4407c4e,a0df0bdb) -,S(6477536e,43a3ba01,8988c8ba,753d732f,9ec061a3,49f7826e,2c426ae5,3f2232bc,ede465d7,6b7798de,832e5f68,512cf3c4,d17282a5,ef88725b,36d8af1,5c5d2679) -,S(55b052a6,52008a83,41135e55,ef7de2b1,33eca8b9,ea0c4800,ce4f8019,5f7067db,a823cc05,63efbc19,d47c2c92,5771497a,ef6377a3,8be0d23c,81a56f06,25c43e56) -,S(c86a02fd,becc3647,16c58f5d,f3f150da,6ba86499,2df09dd5,82b9653f,10cc9289,263d1b5e,eff52a27,1a9c46ee,8adf1194,1da9d3bf,e69f62b7,262099af,43d6fe3a) -,S(23c659e0,3a59381b,3d47beea,60f0244f,66af0596,5f903297,c53aeeaa,d143e90a,1c14650e,3aa16bd5,b67e6077,be307cac,2bd2cd39,b246d6f7,216d73dd,dacbaf64) -,S(2f6d8482,734aff4e,21094c39,2c5fe833,1c8f9756,4de252c2,f6f690ad,8b2fa9d,8b143db3,7e14b40,3fa98a74,a81adc79,c34f17ce,5c9e6f21,68770957,1eb639ae) -,S(6d58e265,d6b08c0b,b050ee18,5175a9ed,51b5c64f,d523ab35,ed1457d2,f9caf153,d0675517,eb71ed0c,4fbb86c6,a2b4a7df,259a7795,3293777f,3a87f620,2265edee) -,S(4af09f2f,69d7b9,6676f472,d7f2009b,f0bb6f0,986f502f,322afacb,7e9d570f,1f93342b,ddfe5896,52e8b64f,a348f333,5396012d,3e870885,5b31024,f14f8e7f) -,S(813e446f,87d923ab,ad8b8649,71b1ca39,d00217f8,232a71cc,d6346798,3a9a0e9b,8ce9f4b3,541a8029,f1476728,2bedf1f4,367ff257,60f2ccce,7b273b2c,dccff418) -,S(53c4fd57,ca0b1eb8,7f5ca0f2,3ecae8eb,c44e9c19,aee3477a,3ca8524e,dcdefaf7,b3db3613,aa916430,a3227d73,35bd0532,74c122b8,18e4ac52,858e513f,c3ab95a4) -,S(e0f8afc2,ec89411,d926355,2c33af71,328331dc,9c9452fe,b0665c39,ae90121f,13523c16,1a00784b,f15d2867,15cc05ec,227248ff,80082e73,ecb139e8,f229eb4e) -,S(fe3efcee,6b82a5b5,a8c9a51d,ccc11f01,ef8f1a7e,588ec4b,17ba1369,cc6bb80b,be17246a,4d8660ca,98d57f07,ddbabc29,650f9a89,9da60a53,d21c6c96,dfdee15e) -,S(8a5182ea,591089a5,11ba9f19,ce4fe062,31b7e2ce,ec4cf75e,5c11094b,9ddc8de5,73688cc,f13d97eb,19a86c2d,8b010406,1c69ca94,fc9ec90d,8ada10ae,37503600) -,S(2d95aecf,72501ef8,e20bc117,22dbcc09,38c552f8,f4e0596c,9974d62b,a99fc884,7d9c418e,e1745ac9,e8f5e4c3,9ada4400,e65acb22,d336bcc9,fa2cdbe9,97f7de88) -,S(7908e4f6,ede4d311,3dfaf114,9bf6e40f,e1f8e33d,72094448,5105a113,21d18b80,11d92d74,9b011e83,5e06d7e6,1103cbe,bf958d8d,bd47d0b0,1ac2ad22,2f7d275) -,S(2c6dc24a,687d8437,44baf725,c75e7524,c0e6571,f32817f4,40183b6e,cbaa9f95,9692bdaa,775b832b,48584ccf,713421e7,5074f1b7,ed5477f1,4335db2,7abf03bc) -,S(a019d9a0,4a9780c9,43dd65fb,b87534cb,ab7c0831,f845e724,d663578,ec7bc090,38de35e6,faa2a1ae,e0649333,898a6ca9,264dcdd5,ad9f289d,ef750110,9bc99d4d) -,S(ced934dd,5c15335d,d050af1d,a8295d2e,bd9b8272,58d689ac,f4a48d85,5ef8a0d9,bc0c9237,1ee7fe7b,69c7c100,e5258c9f,1d68b6dc,309736e4,e05718dc,3a49cb6b) -,S(65e5ffe6,502ea7a1,47fe9c98,9cc745a3,b5262bd3,888069c3,92d1d1f0,a08dbb83,c80ee080,84dc5e65,de8df271,c1132cab,b8be293b,69a390a6,fb3932e8,51ffaf38) -,S(f4466d47,2365b665,6d1947b0,6e67e393,4c0e4f3b,91d52ea6,1f4588f2,4d217655,17afe3f7,2d384ccd,9beb59c3,d64353ba,57713f03,b8644e3c,eef45db,c74ae84e) -,S(66a80bd8,ec0d08ef,3d9aca5b,4329198c,b949ce84,7933ef2a,10baac28,dc98cea,7457685c,600a707d,5fd5d527,9f309b9d,5b14e668,1656869d,b041ba77,97029537) -,S(240e3632,7c3f4c63,afdb84d0,8586bf90,9b359c8d,7012f9ff,aec81986,4c44d597,a701b76c,d369e013,7b627216,f75d0ec9,fa208b66,2d7075bb,a6b6d39c,6a1cbb30) -,S(137f0df8,cafdb26d,36e1b57,c427ce08,444516da,ad1ca806,9dd60e2f,2ee23f92,c2922219,9e4e7bf2,f9159138,13e68273,6bb6a998,6c015caa,43cd30a5,aec74a49) -,S(965fef87,a63bedda,fd4b2e35,e1d0baf9,17d5850b,1f6beca4,64d4fae1,997d3a41,5f19603,369108a5,c599ce56,22bbf02b,cf541867,a57cff2d,8b527148,30124ed3) -,S(1e2ca98e,519c60e6,cf7ff3c9,51cde109,209188e0,6c68f4dc,c22eacf1,34a4125e,edaf4c8d,8bb97032,89f9fb0d,d0023783,fd35e779,41773a00,fb4289cd,ef8411bb) -,S(e8e0e2f0,378595db,68f96e6a,882752bf,df039778,e261375a,47fd4394,2b68006d,75b42822,1e2fbf9c,42772d35,e4bf1e0e,8d3b1ad7,92ff25ca,a488b51d,4ef7186f) -,S(a405f5b0,28e89d81,79e7fa9c,2ebac86c,ffd20ade,60dc5226,cfe6c91e,5c2f6634,c27ea4e3,b0da9e58,665f507,84225107,7893d6cf,5225d5d8,a06f68d1,1d863550) -,S(bcbc3c77,7367168e,169f3fcf,dd2340cf,9e6af955,d6038a0c,b763f036,6f4564cd,c7c120cf,99138201,40ec5339,ec23f5c,1ac0dd73,c9f947dc,e19c034f,7e7a502d) -,S(fd569bd5,14843a2d,e86ab2c0,475e0c67,4959c04f,bc230255,db3e82d1,15cb0758,aea9c73b,bc083366,fc5e31fc,90a1da72,66a9c43a,9d16f6ee,67bd56b7,9c354cc9) -,S(c2fdf561,eca2e3b8,f1107475,9cc43b9a,789ef592,e8afe885,d88b9dba,469c616b,678f57fa,fb2e42fb,bd1482d1,e22c866e,683e4fa7,6c1d2714,6540610d,9cbd1360) -,S(50f20965,510b3317,2836e1e2,d6e00ea6,160a9c71,2aa30bbf,ac527c62,9d8f4088,fd9852c6,974c603,7e88bf45,a279b565,d1246924,e3c4a0f4,8877b716,69b68141) -,S(3f293417,1e371e20,cbe0a858,e5984175,ba465906,fd64a7e6,161c8a7e,5847764c,763e8dbe,571ac3dc,1e803f32,7e2f4585,7268774f,1a45c50,9390dfd4,96bd374b) -,S(8276d399,fe32e931,65f2ef6a,2f4198e7,944bb9a3,226b1a55,fff52dce,d2b92b3d,e955a591,5c496a1,623466be,88c45a3,f545527b,4edd4283,582c03f7,2a2d897b) -,S(e77e7701,f4b405c3,5c8b7a6e,ee7d0637,fa1f566f,d2a2cb64,531dbcc6,19a9e474,23fae4c0,7661e588,365ddde2,63b97f2,cca2023b,c70633a1,41a2eb,1d3799cb) -,S(7ae8112a,732d6428,25aa2eef,10298300,42939628,69e7eea9,3fbc7b3d,2c5210a2,3590e349,f878af6,7f7754f9,abf4ffdc,4d4f4442,48c1e039,6071271f,be5971ce) -,S(f9fe96f6,8e20a422,5b563483,c1d2389a,ebd8a97,b1b9accb,ed7bc51,8077771e,cf3802de,20b5ae42,b1d1db65,b033f2e3,602ca08d,972eed63,9234e1c1,48542478) -,S(b9c5eb6d,ab28292e,49a76b34,49cf903c,dfe79b85,f7797623,924a4295,bf0cd171,adc0a5d8,18926d8d,7bdc83fc,72b2ed11,19b87592,900ae961,ffbb165c,4d5bced1) -,S(b7e25a76,3f3b8bd6,1c57da51,bd90ab57,1df3fcab,28003104,30c44fa5,4a6a5765,c471aa74,babc3fb7,dc80138c,83940e42,961f80a3,23e9741c,c44607a8,258141d) -,S(5808e4f3,e01937f0,e9c887ff,8ea3a34f,8fca4d8d,7868a9d5,7de6d854,a0582d71,fee8cfef,2d78896,55dc9560,68e1a23a,4308a8f7,7962c2e4,f90b2ddc,87f011bd) -,S(92ac7dd9,8da0a4e6,60964943,3887974c,5ec4b32f,875c02ba,1163d06c,b424793b,857b2046,8104a986,a0030596,62039e60,71c8f950,b7f7f746,16fcacbf,b8eee5fa) -,S(5c38092f,fba5798d,48d0068d,d1037563,1f40a693,194584fb,7199c409,b85d52b2,32b1d628,15ee2555,f582f16d,d59c4658,67691e1b,389d1fe3,222b5444,294ab391) -,S(ad7beb62,cec8aa9a,b619693,eb40c477,53e22897,a0007693,f10ce664,21d5c15e,49f98176,a360297,42402a93,26e34a38,cc837278,3873b076,f887c811,e2bd98db) -,S(aa335f87,c61f2e9,7d87355e,2a1c2e51,f2a0ac92,1cfd3cb7,5189f256,386ef185,b39741b2,fc158d6a,435bfa8e,1a68eedf,13deab27,388032fa,fa22d649,c9c9a8a0) -,S(854ef509,24fa2fb4,9b7b7b49,44ad8c9d,87627883,60ce8bd9,36e64f12,a550356d,c5af2246,96c7e32c,a385f7e,3eb8326b,7d9e3537,43a95c8f,3010a160,1d6f534b) -,S(71b6366e,42a8e2c5,31ad6770,ff01481f,5a39c54a,d38e0ac6,f068117d,8d5c9d5c,d6684df5,92f085cd,aee8313,59bbceb0,1a357edf,b36f8e14,706245ef,f01db334) -,S(3a4d1869,55b698d0,5e760d75,8842bd1f,cd869e84,c2c29e44,4ca83bd0,3408d6b4,5ddd1b14,15ff793a,80fc196a,83ff2736,e9791418,fba7eb98,71b51269,170d9904) -,S(f596d242,7e51e5ce,403d673,cbdd71b,75550271,dd2d7d93,79883258,9d3c5739,cb9ef0ea,f6326a5f,83e40428,79675f81,188763b1,ec06fa26,3d7793cb,82b4ceb0) -,S(4bb25028,b5598090,15286b2a,a8858e52,227f3b11,9075077b,3083fe16,77efd4ef,cb63c7c6,9de6503a,d33ee35f,95d4533e,1e978f30,2762b478,e88d18aa,5c4ff098) -,S(77c7c018,4c89f974,df648e0d,ea57ee40,73acd63f,c6e22a55,6269ca4e,a5dc1c99,978faba,232a2b0a,9cf3de55,976ca950,ce3f197e,e774b2e0,d4bd1e5f,e65a1b41) -,S(834d038,926b1ff6,13dc9001,7d021bf4,5bae5,d3741460,db681332,61975c30,f5624b83,614f5e82,10190b34,9f966fde,cd4eeefb,e3e6b046,b3028d6c,3807b475) -,S(370045a0,a7f8a64c,a2b9c64e,85a07fe8,9a7f725b,2cdec8db,258b3d3a,d9cf379e,cbec192c,cfc58b62,6b89d6d3,9b4bf622,81e308b2,2aa3ddf,51d45561,37b1811c) -,S(61302164,6103ee82,1c3103d5,f4d2aba4,645816cf,a67d94d8,ca53dcc2,92ca36d2,935e3db4,5ee1789d,ed8f0ded,ac0430e2,7317f38a,87682850,9568feb8,15e20a1d) -,S(4d6868cd,4df5b1eb,8d27e045,ef04209b,c1dd0bd7,aa712937,8f7bc025,e569d90f,dc0079be,850ab0ab,ef9881ac,740140c6,958e12ad,edfcbd79,2f446d78,7157780a) -,S(43413ee9,a35c7c44,bc95369d,38d9e7ed,53175f17,6f9eb54,6df98540,93105549,9eaef64f,45b421d1,ee80731f,ed61f658,861feb4c,72b5b2b0,ec659825,63172f7b) -,S(1e728340,95183b28,a443e00d,6ae01921,75844d9b,ffb1c77f,c00d388a,80a6b76,d1931ac7,fccf26d3,a2ef72ec,e8c7ecef,c51ad264,ecca5748,7e9cfe5e,d798428c) -,S(7b5995f0,fb0b8246,c588e393,4499404,415f0d03,c9174317,6cb2f4ae,b06960c0,716c7849,b6963a9,f1a7998f,49cfac4c,42a329f8,77d7c8fe,5b35f958,ceb9c0eb) -,S(9c5efff9,2be6057,f5223d41,87fbafd1,a59c364b,239120a2,fa1c4596,4fdad960,4f4aa66e,e42548c9,4d6cafa0,81e59ce7,ab65cbd,78027de6,b1edaa,25e6d7dd) -,S(46970472,192c3690,3c7bd061,dee19fee,5f3a973b,a70430f3,581abae1,3a61e55d,4d232a77,62e04a36,c62894d3,41665ff9,ad8ba55d,353d52cf,44f392cf,7787922b) -,S(add62a3e,583dce2c,55e97257,b64c26bf,5e86b0db,92962b3f,a54e7c52,ac00b32e,3c700f82,c5365611,f3cb1ca9,cb6b0c2a,dda80e04,617142ef,eccfabee,178d3dae) -,S(526115b5,34b212fd,9836a98f,853ab3c1,24bb68bf,afc1d641,b47d08d7,39566c4f,29c983e6,2a4de19,4efa5b2a,9cd4971d,6a86c8e9,f535d599,ee04db95,120fdf4b) -,S(87908ac3,ee8f4e5f,31aa08c0,ac97e93b,81ac75fe,33bfbff0,7d4f0934,7c911f45,b756def7,52c71c51,3f69235e,8d515d6b,f3289a5,a579b999,a695a2f6,49586ba8) -,S(2d6e6ed5,d2ea8912,6797b396,8ac1b0e,f876904b,acbace80,a2613b35,d9bbdd11,b1b66613,50ee7a2b,d149ec9b,25a502a1,6ba6143d,32da00f3,13cc389a,7c0e480b) -,S(f076c9e9,8590180d,dfd36cd6,160c21fb,7dc60263,77435e74,30f74cc3,c46533f9,2c9decd8,6da7b49b,1b4d0a8f,47aaaf9d,19d9e8bb,365c383b,63726f64,ae56fb98) -,S(fb52489b,6d101de1,2f51720a,60a78207,84ab4dd8,39d05c9d,a3b9c349,a74452d6,f1a967ae,deb5329e,faac7381,f3f0bc76,9eb8cc89,78d5d56e,f382a17d,4c3baf4b) -,S(dc1e911,53b3435a,8f23cb08,a7b52f64,a5e2870c,9345896d,ab4ab880,9710241c,3468d632,eb3a51fe,133381ce,2b5dc9a1,64f8eb68,9c019b0b,7e48d504,50e85630) -,S(2d8c6759,6c7856d,b7062c63,2aaffbee,46779bdc,777f0be2,a64093d,41d4000,c7006eca,b64904f2,9cd7baaa,14a5226a,e5c4b3fa,68c62cf,65789066,2eb8e8ca) -,S(31e9d361,fa0041fd,bb73665f,2e1541f6,c41764e7,78023272,478cd7f8,e9552f06,62fdf441,4effb45c,5408a0dc,c0a78041,cbe39cac,562659c,ab8c2b89,1a940c11) -,S(792f50cf,66aa0f00,68bd7fb,ee12bf44,e1fa6662,41c43d2f,275a248c,29459830,633cf86a,a3f10f31,40aaffe1,d04ee094,aad1cc56,129149c3,2702c33e,40d91e3f) -,S(be4f52ab,8f6ad1f0,664e4d28,b67be76b,c3d318f3,9f455708,94060e03,2f8547b3,22ffbfca,44482e40,19ef36d9,209b4262,48d62591,7d81b6a1,57ad945a,1878b4c1) -,S(bb693c4f,7110d2d3,8bdcd6af,d8b29b43,80d003a7,d0f6420b,e8d02cec,3e7cf385,3bdfb9c3,948034e9,31904f13,e3dcfa78,13d3413f,5c2daebc,744bac87,9e4314b2) -,S(56e8a65d,2eb188d4,64dd4280,b987b5f9,8b92b8e4,34b6bb1d,1800fc4a,f8f2deb5,11cd5d14,63777189,f8c7d19a,c692461b,d21fa20f,f12d1976,3b915fa4,33006cbc) -,S(f09d5cee,514e56e5,9566953d,f8600a94,cbad003e,9c898261,5bb998f6,a5b8cbb4,d07ee0a9,a0e88f5d,6da3d918,d5f309ca,7234373b,d528cd8c,21ee9ca5,3d1bafd0) -,S(58671c9f,687ab0a6,f6b7c687,ef546765,7f29ecd9,d6250088,d588742,7b96fa6c,70355403,abefa39a,72d89348,9a8251c2,10d59df,80b4d284,f3f02246,f3f6c60c) -,S(e47ec1f,8a7169d2,9c05cb96,42ba126c,aff841f8,c2edfcf,25ec9303,772eea78,ce97644c,ca60474,4c269973,fdfbf169,bf0fa377,61737dd3,77692b9b,ac775c9d) -,S(ed95cc7a,a24a4ed4,1dfb019e,31abc80d,93ca5c04,b0515f2c,492e9105,efdb12cc,1602bbfa,f17e8c16,30ab470f,bd8fd829,b4a466ca,9f210904,7e0903c4,e012d789) -,S(b6fa3ced,a07a9cf4,db717242,9de8069,216a7b51,4145470d,d811755d,a2908a2e,64f695ae,7f19c7d1,17af6ca9,36dcb2df,8715ff96,c8134313,c111da69,7a354dfe) -,S(2e3047cb,4d210007,39b8d5ce,e4884a5f,ae969eef,898a600c,2202da33,239b3627,197f37c0,7c11943e,40328e3a,3c7c11d8,f2d77d16,84532631,53b7cbd7,69808c9d) -,S(df9c446,7a691cae,b8a01ec1,a4a8ebc,fbbacfc,ca347aa5,39d56853,c14ecd3e,acf9554e,906e86ba,8459c108,d49f7aa1,e1e4b2ee,9957101a,f16d43f7,7dfaf6aa) -,S(d452f3bb,2e3e54c4,1f68267b,f846f504,99f39f28,5edb86cd,68330ed9,510aff54,52c5d16b,41eb1029,7f86a30,28d1b610,6f6c5aad,61b63bd3,53d95b2b,fd214755) -,S(cc196d06,9ad60096,c4ba1057,fa4fcd9c,4a50b28b,78227074,22d531b9,dd85a5be,bd930456,14388283,b28cb67,758c792e,5f9d6c0e,2d4c1a86,745e0504,ec902b24) -,S(4974252f,9c246a45,1187b1b6,546cbf27,af9c21cc,d03c7b37,df7a604b,a3b6859c,276e69e5,b85e3241,33f9ec76,d628fee8,3af37bd8,def6e677,bba19739,9da14305) -,S(311548d2,d9f880a7,17e77608,8574ff4c,185cb0f0,a9660ef6,7a94d090,3e2fd845,82b2dfdc,2d0ca2e1,d403c1db,7593dc01,2043122a,fb50961e,d5f86174,18a3d7b7) -,S(30068568,4497d5d3,2c98d3ee,1136a9af,d5bbc79e,340528cc,4e0b3c55,74e867f4,57c141af,fd650050,79ea563b,e9ebb161,a7725bb8,e41e3c13,ec528b2d,df23430f) -,S(1c223f58,1f03b4fc,68024db4,876b743d,8a2b635f,988340f0,d22c389c,43d130a1,9d99aaea,d3bd3b1a,9891dae7,4a3dd857,3a86b643,6c623c00,6604b211,4e27c133) -,S(a675c89a,5d453821,429109cf,45cac77a,880e0e6,396a0b4f,16053ff9,eabfe4c1,8cda99bf,c3426739,c4888767,113b7f4c,9b321a61,1b63b4d1,2dd50a79,d80b90f7) -,S(e990a236,d7854ca7,3e40c661,93dbf3ab,74198351,1236988b,cca29eef,772b32c3,a3d42c05,851b8138,ef1bbb7b,41510bb6,fc893baa,928c98ac,91127b3b,a100aa12) -,S(2a6eff8,af4b8049,2c3d31ed,f6672d1c,d0b231d7,6deeb590,a8d0c4c0,83586027,2a7427d6,951e07fc,4d5cd4f3,ca8a3415,8f0d03c2,3cd2f250,541c0f11,8013a623) -,S(7dad1061,9c4a7bd5,1edf6813,daa8fb4a,2a9e494f,9835db8a,42f4b0ca,827df50a,3e3b2b7b,a44500d0,277b792c,8a529fb3,41667560,1c4e443c,9c2fb2e0,dd17f1ee) -,S(39d5b162,fd48725,1bb42303,b7b8887b,92180fa,ddbdfb7b,a14ef2e0,3cc32aa0,3a8bafa4,5645e4e9,bf4e0175,69fad346,210e65ea,fa92b971,413a2190,b64b6f09) -,S(f9ac329c,ba09d60b,5aa62bed,81e9ca15,7a3bc53d,acd83836,89742ef3,cfcfd795,9c2fff50,aad80c18,2e6593ae,796ada7a,e0a42a4,17ce77bd,ea7be927,161be4ff) -,S(19adeabb,6e9aea9c,fe245329,623b8bcb,3554eff3,999b0b0b,8e035450,14cd964f,c570d99,99e9c62d,a3321f3f,a548d43b,99f05df3,e17273cc,2a45a3d9,20654cf8) -,S(978f705b,eb9b6009,22285468,521eddae,e71f6521,1ae79567,3b122090,fd4eb3c3,8eaa7bc6,1ae92adb,506f9e32,c66f5457,4e1d929b,ef4953cd,a1cd3f8d,c98ff8ef) -,S(e29b57d8,f6808d6b,ec982a12,ac70afca,1c9c19ff,a7b0c724,4fcc5b0e,3dc2fcf1,f7d60b14,133721c3,471fd91a,864e576d,84e5a06e,b031b1fb,3a2947b2,a33b159b) -,S(72073aee,f39510e2,81cca2d9,7831e533,56cc6016,9462a9f0,45100dae,3443bca8,bd761539,177458ee,dff87628,d155c9a2,d6a00e26,51158def,6ce72c35,84d56a3c) -,S(c949cbc9,48db844d,2cd04810,433f982a,680b6a95,e3461ff2,108492f9,247fefb3,162ca70c,c9f19d2,d3da47b,3b0a2361,f5c21492,a12828ae,9c0ff9c7,ef1d7b20) -,S(9acb7d8c,e958f7e5,189676c3,e7248ad7,9f717a67,2d4c80b5,9c425663,e078810d,112dc86f,1b241c26,30d87412,2faad000,473bce32,95bd6989,8b6a4521,7773284a) -,S(e468a13c,e5ad4c24,4df9aaa5,e13987f9,50900b4,a32ba33f,430935c2,1250e4bf,61e3e755,a91bb2a5,3fc2ac70,bb232b2,c1aa356,d494656c,5df93232,a866e400) -,S(26779f67,75d8caf1,46638c17,71e33b02,b41c61df,325acbd4,506199c1,bea8310,e9de26b5,c076eb9,cf3436dd,d9bc7f8e,5772720a,a8401227,7af573eb,65a769) -,S(8c408da9,a816c7ba,ae2846ed,bd923211,926e5e5c,ad595a5f,f2dbb190,f48857a9,89373ca7,e9f3f96c,1f0bc7ee,d427dea,99808bd3,b943964e,f0db4bc4,a7a1256b) -,S(9ccbac95,d80bafbc,b7e699c,aaccea8d,3169db5e,328e1519,825a3f4b,adee6a19,5a8d6936,a2859d57,6accb35a,5e80c944,4d71612e,76cd755e,aa3465b0,dcad8aee) -,S(34c7b7ed,6fe88bc9,803567ae,71ea7c28,c9511f60,e2ebfa8,fffeba31,dbbce2d7,31a3bfbd,c42cffa6,c77aa417,955c671a,426497e6,b35efaee,83a58bf,84de02c8) -,S(7940ca7f,c3bc810b,5679456b,88a73cae,4b2abed8,47260052,ffcb33de,edef6155,8923cf73,9285b368,d32d690c,488d8b38,5d3285aa,c399fdf,6e263daf,4e0b35c5) -,S(2cb10da7,104ff7d8,d8f1742,43425c2c,5e8773ed,71e62e4d,cc0c2d4a,56ac3a08,610cb16f,53ddfd28,7a7ff301,a8047555,801c13b4,81033c94,4e145b1f,98458520) -,S(ced78e5e,58e2893c,3910bd9d,d43fc362,ce06dcea,f44c5aec,ca17eb0e,cdc1fc53,c66050cb,835c97cb,c08ae0df,242895c8,f0f0085d,85a020b5,122e041f,8fb09607) -,S(5e83a4f7,7c4cc672,a7a381f3,e527c8fb,331e8d75,f8578a85,39ae1007,51903f24,545cda31,25c29fca,b343c22f,824c86e8,89f2cd3c,d2a6f3b8,9e3308fa,2968b8fb) -,S(c62958f8,33217811,cb099492,fb8c13a4,5b3d04b8,12a0c1f1,68cac595,e7efcfa0,e179e98,1b92f1be,25c9f892,d6a71ef4,62f3e1c5,43127fe1,f2b711f1,bf61aba2) -,S(7eba00b2,f151282b,83c7fa9b,5df6d9a7,b764e7f,42ca29a9,2734859f,a2f0f016,9e3162bf,a619123e,8e87728d,da825814,4b760c2a,3d05fc2f,1fc25565,1d72a7cb) -,S(8f68c1f4,83ce557b,98d96444,4a2a7d2c,a05d8f25,e6f9f909,cb44b58d,a030cd90,30f15dc2,17e7ce70,a6fae901,70930130,8f7d8706,80c43840,765ee89a,5f864e00) -,S(393d5b72,a9bbc392,4f712195,51ba7f65,4bc4df18,cf93dcaa,bace126f,c4262b5b,976cf232,fe59a3eb,c6514242,19128395,2945cfb,f792e4c8,19248346,37f16e9c) -,S(e1648650,d0d4ca1e,8fac2522,cda2a042,bc93b879,2d6f870,29c6d888,a11312ca,4d919105,9ea261fd,9470ffb9,e60c703,6d21da3a,ce975880,39e1a820,c636f269) -,S(efc7519f,4676989a,a12d823e,8e49b1de,96397ca2,11fe729c,cf0fd67b,bc6d6a74,3f304e50,be6dc6f1,b7c79979,4ae38ff,ed11a253,778d0294,13a98547,e3b889d5) -,S(85726e3e,aa8f7016,1c3629c2,84b7a7ef,79259de0,84f8bbf6,9358f66d,a439133f,756800a8,11a472ec,a72604e4,c2eea080,94971b58,3738e7eb,2c817250,2595e47f) -,S(2e238f2f,de3c39e1,19119541,9eccde3e,b0c4fee3,e432fcf3,f58c4f77,4ba070b1,7ce6b671,c0c79a82,2fdcb88a,a10a8033,bcd0e1a9,2cfab941,d052c09e,4e5e4c81) -,S(9cdc6aac,41e79b7b,ae77a7b9,bc027e99,1d4f8c1c,2b4913a3,1eaaf1a0,9bd87f24,9d666c3c,3503b9ab,d609b074,743f8a3f,460c0122,ad7a0cc5,a22a6d17,9d948ba1) -,S(360dd1e4,608c9215,287936b6,97e5e819,390629a0,7bec616f,7fc713fc,5ef8ec3f,7628d770,5c744125,d5885c2b,de25693c,5afaf8a,3d5739a5,deeeb5e9,ac1c62da) -,S(8657fbee,524c5f5e,25aecdf7,7306c97b,78119e0a,5f155c4f,37918e87,12302d35,242172c2,f90ea26d,b1f7d2cd,dbb9af4d,78a1660a,32402a83,6e598c92,df9e999f) -,S(3ae7e8db,7b069528,acea3e0a,dc005d52,7ca9e1ca,dd3d3cdd,5564ea86,5e1a453,ac203ebf,98b7e46b,bcad5156,cc058857,f32a8d62,2114acc4,55cde626,591fc5c9) -,S(81bdb0a1,9852adc7,afcd9775,54143362,c7e724df,884f1a2e,796d88bd,1c1696cd,2f189af1,a90f9445,353d0549,4d5562f7,4a3d37cd,1362d92a,aefe0393,9b46ef0d) -,S(e95b0171,dd117d45,263141e6,95ceaa52,3498a8d9,d1f09ae6,855fad1c,5e5c3e8,dc8bf907,ea6a4824,9cf930b0,bad3e3a6,c179fda4,107a0812,76f02a9b,9c689416) -,S(20e3979,e95fb62e,ecfa4ff1,3aa3fd46,94b24ab,c814f560,ce180262,11b70bc8,c9d01545,50f1d7be,da471272,822522dd,d6924a98,f6331fd1,cf6837d7,db91da1f) -,S(e0405598,cda639ec,6c058a61,4c39d56,f71c43ea,693f9b86,c9df1bf9,e4fef30b,9df9b561,a7bb2ebd,67b67031,a92dda6e,12550d0f,5cc2368a,603ae64f,ed20ef3b) -,S(faea8667,646d1600,2dbbdfd8,74a59ddc,a2b8024,b2f7f6f0,f2c2036d,ab5c5e9,8112167f,ed386f1,d1e02307,de202bd2,363cd1f5,fefe0621,1c4564fe,eb0220a9) -,S(f01d6b90,18ab421d,d410404c,b8690720,65522bf8,5734008f,105cf385,a023a80f,eba29d0,f0c5408e,d681984d,c525982a,befccd9f,7ff01dd2,6da4999c,f3f6a295) -,S(5906b143,9b994465,c9f3d4fd,f7f09a4a,b9ae0864,262b0140,def21014,8b097533,2917b92b,d0368fff,6e6a98d9,18cfeda4,d039c73,a3cb865a,5d77abff,9fe7970b) -,S(d6443bcf,53ba252e,925f5ae3,5d508732,a3289059,308fa67c,7b051ed9,66b6cc92,e0155fa0,366a2d1c,af8d2c17,a4ad9cf7,f4fc0102,f1e1ec13,7f1b2b51,1af0e7dc) -,S(b95a72a1,dbcfa0eb,ed2200ad,b57d71f0,b96a9703,8bd3cba5,78eff5f4,e9454196,f89c7cd9,783a4c34,1bdd05d8,241ec4eb,d8815463,4d05cc84,d5601f4a,6f3fac0d) -,S(50b287b4,d8b41f03,88804ae2,2b56abc7,be632cb8,a20629b5,3a00fd3d,9a879b6,67c3bbfa,4d8307c0,bd32106,57f5c0b4,78bc070e,53a3024e,1ffe103e,e5397076) -,S(64feb83a,5a81f6d8,8218e2a0,4e6f97b4,6efb89a,6f394264,d905c93a,cb7e5493,3fa224d4,eda77580,4d6ba88e,63df4c3b,5d9fab1e,519eca92,1ada5f44,741d5035) -,S(9434b5f9,2d63c2c,c90ee2fd,b7f7289f,b6277c69,3076d73e,cc38b032,bc8b5cd6,c940b3a6,4c04e6b7,1de7f727,d6fc0883,29443276,6d2ccd51,6d24dc22,3998aee9) -,S(a6db8e98,6d1bda8,995015e4,807b900d,704f8d3b,8ac5fc49,aa16bc61,82390724,3277c29e,bf27d0b5,ef8af507,5e295f23,92c41f29,3803a8b1,6ce601eb,2abedbd0) -,S(50733cc1,dd80ddbd,b254ea6f,14d0679c,6839e6b1,73aa0bc0,9d0ef5bb,bc5c2f9c,246e1742,a5a9172a,ed4e1e0a,9c0d623a,5233334e,47bcb68a,aec41101,92771eaa) -,S(4252122d,5a89f621,2c7b0a99,5ebfa8c3,b980e142,f7a89e07,d4788d91,1163ad99,bc63b87b,fda041bd,f9ac11c,e2e8ab3d,a1368cd0,2e276b55,6419e0ee,3d7fe284) -,S(6bc86411,d3f9d25,bad0a922,21f0146c,9173cc99,d00470ba,a41897fe,b5678f5,e2c1cd75,3915e977,c20d4508,1af1946b,1d8c5926,cca74ab5,c4ec0bd7,921c4cda) -,S(c786df9c,6b2e656d,a30146cb,14da5372,64683e46,5569b1dc,df4c1541,580d40a0,b8d229d1,d8773d5,dedde14a,dcf8816e,acaa274a,1f4ebd01,2086159d,1feb32f) -,S(f42032f7,dc6dc676,5b1a9453,74ee45f8,486e9b94,6a57e651,7dfefb0f,9ea3164c,ad2d7a22,e477f5ce,ad0fbcc1,fe2c2533,78920fd6,cd9ed4ec,1095fa88,2189131a) -,S(3c2fb5d9,a5bc7ad2,d4ce0970,5090a5fe,ef54a6ad,7f8d827b,2ce51785,b29ba5f3,3ec2d878,a4d836c1,71f68648,f8cac869,472847f3,4c267139,5f38e0b5,e96b653d) -,S(b182d837,dbb1e47c,bdbe559e,f30f03e9,ae1efc93,a5a165e3,10285bfd,ffe47303,c40cbcdb,d7f1fd56,c486a35,67420a7f,e4ed4ca8,43a68bdc,81eccbdd,213d7c5e) -,S(75a35130,cea9cec2,81792d7f,ffe84375,a4aec378,57496122,9a77270b,43b12391,988821ee,b6ee31c9,8201a90e,853c4afb,8e330592,6349d405,90c4840d,fdf3fb5c) -,S(a97b9c85,97362b4b,aab43b64,db7e5e0f,3e4cfea9,82939289,e5266f09,87fc8503,ccb75937,fd647eb6,7da4aa7b,72e8d873,c9f035a5,cfa120fd,4d4881f0,9924d8a7) -,S(d129bad3,4c7674ca,60a6f07e,1c1ee8b4,aa3dce4e,82ff890b,cd256324,13a56fe7,b3c8d404,7c8610a1,a56af634,b54dc568,6af075a0,a0cdd4f1,75855fa6,d22cc4c5) -,S(d8a0aed3,cf37542e,a0f06c6e,754503d7,3bd693cf,c3c357f2,7445989e,137f73e2,ba4ad8e6,3bde0d8c,42172a7b,59e1f4f4,581f48e,cffc45bf,929d815f,8133e6a9) -,S(9f905bc0,a5f479ee,6162ed38,24d74a1b,d6d48bd5,4611f840,ab1ac55b,7b84be18,5babdad,4248a4ef,4606dd26,1807e25f,6206dc81,6eeaddda,fd8b5082,52e3da53) -,S(d51c86e1,4519166d,c2aa7604,c88670c6,ca44a84c,6735f692,ee4dda79,e957b85d,fcee6753,29130c5,f4b260a9,cc7efb73,d51e6ec,8ac1ec52,28ca0ab6,51d5b8f0) -,S(ce251fde,ffdf0f59,5a563941,179f6f8a,86402b2c,6bddd1ea,7b37b89,bc649102,5b26a79,882b2f89,79610eb6,5de06e02,b09412e8,bbff66c5,cc650211,d1b9ccf5) -,S(6168ac7b,101fbe73,5b9339b6,9c459fbe,44a6f6c7,bd488beb,bf0b81da,ce511f3,65b6e531,f350983a,2f55db14,588e92db,436f7068,5117255f,ed474aa2,53b5c9ff) -,S(aab2deff,7e77f414,59d4361d,2722b448,6530f0c9,46b93d96,975f5a96,eb4bd091,b416562d,c5b057ef,7e63ec2d,daf0aed4,84320d7b,60695809,c6fa3aa9,e4eaa431) -,S(9ebed934,ca30351f,44b7ea4f,f3f6453f,6d0c7f81,869226c,c8f4312f,d413056,766a6f8c,311550eb,a8500ab6,f3466ca3,52e6b960,c4a52cb9,870ff784,4191a2aa) -,S(a2e78d35,d51970c3,42d03a09,bf3286c2,3a131ff9,abc4bea6,352826d4,5fe2da0e,fcb844e0,4bdf8d96,f423c499,44275ac5,8885c384,57975268,ec8cd880,dc640346) -,S(1a49f352,5203a773,9c7cce34,d21c51fe,dfeba5e5,c0f21622,eb954621,e3d6726d,e617de36,7c6a9283,8d4bcfd2,bf2fd21c,15b53007,6a0367b7,6d6ea65b,af032213) -,S(be65c6c,de6c54b6,c0c4d306,65cb4d61,211c97dc,a74c57b7,13f41028,e2d14832,d7875fb7,5cce3a40,9a74e48a,9b577a04,4c09a43a,989606b5,b44fbade,89e6c03f) -,S(a1572e58,60b10c96,bb3e0b6,7a047d4a,9957448d,74bd8a44,823de9cb,50aaa639,5ae37e0d,88c9f6d,173026ac,58ef45fd,17b0a0da,40304954,f9671c56,93946d1b) -,S(21917639,b6ef2333,378bafe5,fed1780b,24d9fa82,17ee49e7,369099a8,8c9baee5,fee39df,4bcb318b,4dcc4017,7f1af605,f22c44ec,d67a15cc,297f02fc,dfec4eb7) -,S(ac2a8d9b,b2219c98,444d03a0,36db728,ffa182d0,d31831ad,f2643010,bb76d3fe,adec7f18,c9474dc8,d0741d1a,5e72e479,c8b86f74,327fc5d3,cd79cf86,869310ab) -,S(c540463f,bf62ef36,a972d797,2bf79054,80b8e67,415f1895,d42d261c,165d1b86,f04a3516,83039c2e,8bac5ef5,1db4e105,95a27e25,cfe680ed,e7d840e4,f70e50b3) -,S(df63238c,77e75ec9,b844431b,d15007d6,56b849eb,4b6902b4,e79f0d6e,9527ef29,63846f3f,dfba6f2e,46bc7f2f,17af5067,a953cd0b,dbe2fef2,52e73be,b8a17330) -,S(43dd347a,1bf0ee84,ad774d4f,70c67cea,594946c2,94cbc330,15bbdd21,890998d4,b6f58d9e,e6e13c1d,b65dbd28,2343d8d2,3f73035a,b4399672,15b0300c,f7dfb48) -,S(5af8e3e7,f5ba9d80,73c5c1e3,c8d0a62,52eef1c1,17043e01,7d610f20,8b5eff0,246c7a4c,6f6e75aa,eb60e256,756e6365,711e98a6,aefa5345,adefb632,321d39da) -,S(60e7513a,b327df8e,e3d44222,95e0d886,b264f560,1c4e3d03,3b405d37,f6ae8518,4c58466e,b68d6c81,33fa6639,12f4a12c,a4a9f3e3,d4e0f6e2,7e92a85d,4d541cd3) -,S(126520ec,f3129775,786c4d64,7226174d,3ccaf5ae,2e4a1514,90e1b691,f07946a0,d5a2544c,efec281f,e70f05e8,2494085c,133fb918,6416435d,4b7fe673,88c440) -,S(b588e8a0,2396bfa7,8512585b,cd0d0e4a,7d14b5e9,f76e1426,b4591c9,6602c585,d7c6a7d0,827852f9,e34942f9,a6f5eae9,cd0a7f29,d30057cc,46d13e2d,4ec04caa) -,S(257f90fe,4409ef7d,30730e37,d7358c7b,60a1cc21,57acedd0,355d7a1c,89b5750b,b14da56d,9aa8fb67,b2d1260d,8de63c00,a9a7aafc,6fb890a0,e1a148ed,5e371201) -,S(8072b8cb,47c71331,9ed2ce85,cf913c87,85955c84,d338daed,58528427,3f3a4a56,6d7a0ed6,bf3383be,8953b47,d93ac5a5,e40e8547,2fc6d3d7,71f89007,f8d20d39) -,S(fab935ba,b2b72a27,b338ef89,509b3830,b7800817,19c2b3ec,8467c736,24ca2640,2a610c06,77fb514c,b224dcd6,56c5136d,88f87f34,86fa0699,eb71319d,c85a103a) -,S(7c6364c6,4906b7c2,e1ca0d87,6c163932,7e8e146b,afd94c83,2330f990,f979ae52,c97e7b44,26b91f6c,88ab7e39,d57f7b7d,4a5e0f9c,ff15aad5,e58e7017,d51c5317) -,S(98beb1ac,48c8824d,447a10cb,43b51167,b8e7cf0d,9eb4e4c8,43403b03,2208570c,1712c13e,ddff8fd5,191fdb28,717efb74,ed52a9f,f47bc21e,b15838d,fcf00af3) -,S(f683a667,31241c44,4adcf062,156f3fdc,d04e8450,911908e1,95bbea2d,8c5bf918,460eac53,48ea1e78,9fdef168,a150065e,1e4a2f83,85268385,3355586c,87453f1c) -,S(38f065a7,165e5d4,d31238de,8dc38f43,4dd024c6,6eca026d,de03c4cb,b43639a5,790bacf5,d35a688b,130bdb38,29073b8,28837b9c,9357544e,1e44d766,e401d044) -,S(cee8a218,2b3004fe,76714511,30340b0,7cf10241,d9e933c4,97ae84e9,a1d525f2,ed373709,3e0eb05d,3ee2823b,25bbbb11,ec943848,1a3ceae1,89573d71,7a596b3d) -,S(164c6ee5,620f4582,35520eb0,8276d85,9a14e266,b7b59576,d0a3e0a6,636f124a,fe92dd66,139f02c8,76ff6e57,8c769a4d,63484072,5c909bc9,481d4a52,f60565f3) -,S(d4606a18,1a0bd363,eb63849a,81c77d0b,942ff14e,7f885c61,d1fb772,78ef1008,81e7b2cd,e7c5d9,29e1d69a,309a334f,2c01b084,e82b789a,835a7aa8,5d7e93a4) -,S(905f5725,1df1651e,83aa8b3,dec2d96b,a32155eb,90d7f985,b3ce5213,2092be07,e4acfdaa,9eb8995a,a4ac8a0a,2b66cbbb,d561fe6b,389c56f,3af6f62a,d7579632) -,S(2e3ab14c,d3aa69de,a35a8ad4,99130302,b16f3d3,9df06b77,7c30e404,91eb6dda,ade534e7,ea0217a8,88c50bf4,ef81dddb,a5c7ffbe,bc0f90e7,110df2a8,e0c7c2c0) -,S(98207cc0,23f50a6e,5f5ce8a5,68c5b24,d4f4f741,94de76a6,d1e6f44e,72619a9b,fdacc236,bd424684,52508806,b08fabdd,98a15b15,6751953b,95b4c5f1,40bce374) -,S(b6d8bc0f,894863a2,3a793c3d,a33a5e66,cafe8696,f9cdd40e,777a40ea,aa203ee2,7e9b246c,8555b4c2,47c45fe1,d1e5d160,c7ed7d37,a3a43440,deee6ef4,15dc092c) -,S(56d030ad,eb30f1b4,7f806276,651a56d8,7f0d8b6c,458092e1,61351368,8cd0f6c3,bb3a1513,155c5885,e084180a,1728902b,33e1a61b,364c8d9c,94d67ca2,e386f131) -,S(77251aac,f919aa4e,b7610a77,ba27d94,c85b973c,af04c885,92fe5272,a48ec088,ef27aac0,593cc67b,93535bc8,4d0a04a3,e8a865a1,bdf65312,85beac2b,d58e149d) -,S(cb7b6a,cbbbdc23,64711585,6d80df3,2ec9aaa0,c6380b3e,677299d0,13658121,1f818bab,72575e35,a60ce7f1,c720e9ce,2f59b086,63cba841,ea288920,16a40ca4) -,S(4a18eb1c,bddb4c3f,ed44fdfc,6242959c,29720142,21d10154,c7fbca68,5c475d0,bb24f347,ebdcdc0a,6429f8ba,49065475,9cce87aa,8df10496,6d2ebcf2,97e70ffd) -,S(384286ca,1003c97d,7d151032,97d81cfb,e3e3dbbe,5dc70c76,6a8dbdc7,c1e625c,7201deb,638d2ec,6cbb4db4,e955ee1b,a3015cee,e06d2ddc,f024daab,8f07a277) -,S(84b6d6ae,d5e00e31,73c24d39,80f05cd6,f61625e3,11439a55,e03ae2db,d79a7d55,a3da9e1a,4c32e4f9,a1d326c3,6670296d,3ffb18fc,266e169,a99d4d00,4de383b1) -,S(aa1cab51,f7239cd4,dd27a4c4,805e614c,5d972cbe,c2830ebe,7daf6ed8,781c37e9,cf8bb72e,535fc8cd,12a2f4d5,e8f9e257,38a28812,1c93b061,5fd4fdeb,368be5bf) -,S(7c4f183a,f4abbe43,d7fa6d5,77ea6c14,83302f2d,b863a7c5,bf072e51,3d2140bc,1eb08c67,a417c0b,58fe8185,1a66902a,a608db07,24dc38c6,706bb80f,5956c808) -,S(dc30f68e,58ff30a,4bf2f6b,28b30708,506140a2,1a971c04,8afe04cf,94b54d31,6f996e08,8d4f7f53,aa1c2050,644a47ed,bcc1da4f,519978f8,6496ba1e,c7be2688) -,S(145185a9,ac6b036f,d0d3cd25,c904b3b7,c8f1d0ad,3ffe5f89,d87b7804,8b017426,d7f6acb2,828ccbc0,db0708e2,79db6313,fc955d2b,cf9e2754,1a7535e3,24c7bc90) -,S(e8700138,5c0bc4e2,9911f29a,e39a5ae3,ad3cf1cf,d690cbef,32f313ea,fd190fa9,92d83708,2e5139d0,f8084001,8ebf8703,da250361,466caa96,717edd0d,6e7ada7f) -,S(5fac0aa7,9963a1e4,5e1c668e,3512d0fe,2eb2c709,d5ecc71f,c862d5dd,523f864,9c7bfd73,445e7d9e,139b96e6,813f1f80,2ec632c6,a76e9dfb,8afecf40,2788d16a) -,S(441f40f6,f3ca4dde,5a085c15,57f14cf3,fbb7c3f2,5716c33c,63ee90f,45c564e2,c81f1205,1179c2a6,f2614495,322cf40a,34cab55d,c90d61b4,d1bc3787,ec3baeae) -,S(a4068c1f,c63d8f21,203cb6af,b37d796a,3c454bd9,db974ab8,e8bfba8b,b832b043,b5318b99,e9354250,a837f8cb,cf8d9cde,d95bb1d,1db0becb,1e887535,4ddb96ca) -,S(44563417,c647b097,d0238a57,74998fce,3c809a26,f6d2b71c,eeecebfb,134cfad3,3f417680,1c15172c,ef636dc3,12742429,13d59079,73ad09c3,9fd8c6a,8a95104) -,S(d57a5fde,47873327,728f5706,d2f0d64,1c5386a9,fdc41808,a2c062ab,942acb6a,cffcd62a,c0c85aae,4a6b7881,f3be170d,9836abda,baa47d60,8c0b8f60,f9aaedd1) -,S(9dcedd10,d495fa2b,6f4b4387,57cb38be,d6f09949,17e7ece,7de913f7,8cb111fd,73196e22,59d4ae9,950725dc,77321567,167d7761,29cc32e9,d92b6dcd,4c056223) -,S(aea290f3,a4ffd405,d51f1c8b,5f11cf74,60f05300,a1e24c08,25b96910,b24e32c1,f6c100a6,3c918f8,f64ffe8a,95840421,dc384635,e3465cf8,65034bde,17ca8eb9) -,S(bbfcd317,5091846f,181696f6,35fb1b05,802e7659,7ca97040,31339381,46812234,2a0a4ebb,1f09b31e,aab4478,89000fbb,5876d7e2,dd889393,3001a977,8aaa3a15) -,S(2a3b4e65,d9d7661c,addfe1e1,96beaca3,ccbc0348,dff6d2df,21f394c7,a7f4594d,74c6f171,1a2c0c01,78bb6a27,b6e17cda,bddb7260,acbc533,a49b19d1,e0b4a110) -,S(d8e47e32,15cbe145,aaa9efec,ada428f1,8d8c599e,98d2f9d7,8177215c,c85dc2ae,5c4d4f6b,aadcd87c,7ac76eb8,22e1c0db,e7c81342,702bfd98,e193df1,809e0511) -,S(5b5954d1,25d77778,f3c1514c,6256ef65,2ae0ab97,151f8856,dda6c87d,1e04a34f,1c5ddf3f,b185edb9,14769482,95e687e4,40497582,26b36fc6,3502922f,cd1bf81e) -,S(e8097e1a,12c6837,a8f29eec,31ccbd16,f191e7a7,d7b199dd,d6d9ee6b,7f26ef55,84ab3d24,e2c4407b,53e4299b,8de1aa8a,22dab9be,b6efa5c,5715a943,65174b9a) -,S(495ebcc5,b0573416,f2b3e705,fe4a4bfe,1e756211,5f37b8a2,dec57688,dedbdd45,3bc65725,6783970c,7696d5a7,b04ac7ca,8c627ce9,251844e9,e7cca774,4d385be7) -,S(4ffc69af,b9cf40ff,c94beac6,aa020109,b7855e0,a993984f,5e59ba16,fc78ad51,6d43d1f9,e3283528,494c9783,cdcbe9ae,2ede071b,ed494c57,2539df6e,b185ca1) -,S(b047e0d1,afc92251,7eaf5c0d,a9d0a093,fde5e829,84c8483e,d256640d,166dfc75,dca2ef00,a282972,d4bf67cb,74fb31af,da5b8145,ec1b7a65,6636376c,504a70df) -,S(ea7b0b93,48e0b3e2,be800ed,6ca4b121,277a496e,84fb6680,2658f68,37b1d530,cef40d2c,e1cf820b,19b435bb,a541ff1c,fa572b1,ca3693d0,cfeb3b32,8ddf918) -,S(e35a53cc,ad74738a,bde75a3e,e2b10d7a,d4ec39bf,e32e1daa,ecc151f3,bef1966b,ad06a8ab,a0296c17,fb24eff3,b27284c5,6ebca204,f6eee752,276ab9a8,1f1bce13) -,S(70334511,ae9acd50,e094f034,17dbba05,4a104c84,ea8d6250,13e1f8f6,907261a3,d1f603e0,5af2e1df,4b8eac69,b4067810,c302ed18,f02bc964,2eba34f6,bc67e84a) -,S(13adc074,c3ea8877,4598d0b9,ad653285,c81bd98d,d4bb6a43,c126db2c,d1f08d7,4bbda9d3,c83c7a64,fcccf3e2,c4251a7e,f61966b7,ec48e89,c991d44b,9588c83b) -,S(4a2a5fa0,71702fa0,934b66ae,7c003f00,306f07b8,625d92f2,d2276efd,18ce5f0c,f9c2f4ac,d8c594a4,117a836,7fa5224e,a7ccbe60,2475e3ed,b19a317c,5feff6e9) -,S(e2f7dc14,79bac0e,a95b5a2,1a9f4e,8c42a23b,8f25d09d,dacb9a3b,fe3ec638,ae6c82,c4f3dc5,41f140a5,2eb6b0c,dd0e200e,d0d951b,e85efd4b,b9b086ad) -,S(eb1d6d07,8f6b74f5,c48a913b,8510e8d0,5cfeb954,856f3ebc,628d0db1,a253963a,f3d73300,e216d14f,d5a67c35,91b362be,f13818c3,36a93784,875ce9b4,2cd8c7d2) -,S(a22c6d71,1d79ae71,403feb96,6dc11adf,253a5d3f,d3d74b44,5f7268bd,84b52277,86d5212,bf37db8b,4e873476,36201714,3f295f0b,d69d2187,8904a53c,831af06) -,S(42f7eb02,797cc76a,21c95db3,c9a0014,4ec5defe,553a45b5,1b701c0b,6f5ed3d0,60525877,3cb86452,928e37d,ce19e2ad,4da63174,2f049214,9f9823ed,ba679519) -,S(f5250698,b37da26,20a3a80d,a9c1c88f,792677a2,6d2b9fa5,49065339,ecc1e95c,b0826c,66edbd2c,5562bb14,d6f8df25,a5d0bc54,7a1163dd,4a8dc1e3,7d140266) -,S(b845d4a0,bc8db805,43526506,cac5c093,cece5c5a,85750d54,317dd78c,7bc10832,e38db2fa,207ce0b4,d9b01ee8,b174a24e,f28591c9,9d203ca5,7d90080,807279b) -,S(4955d281,746b8c9,4bac7d53,26aa28c3,9fba7149,7b4fc036,f9971f7a,870a67cd,ce72ebf4,aef6e987,3fa5cf3,e66ec918,911885ae,848aff22,eeef12e2,e50e6cee) -,S(20fdca2a,a03d6105,50f2eab8,d5e7d47d,c4e2e9ed,e6d2c7b,bfe64d75,176b9e9,1e077683,2c44d6d2,19d19c7b,aec0a303,f4d3d5f6,4ad8ca35,83f87325,6aee262f) -,S(418de9de,9adbec78,769eba7a,cab3853a,9a85ebc7,2bdffc86,844d0f32,15de4877,20d521c9,974c8ee0,f817ee37,a0fa14d2,eefc4e05,2c93ce87,ee665898,9e49c5a2) -,S(135b5a4a,f64eaa0f,d288bee5,c1bb7846,30df305b,5d3b13da,d8c446d3,6e13485f,3e571c3c,fe32fe42,669b08c9,14a655ce,828f41cb,12b9c18,9234f4eb,1aac0437) -,S(7eb64f50,5e26671d,21d3b2c9,fefbe094,c6300348,25248e86,5daa8939,f8b7e90d,be847834,f303ae8a,55ebaf3b,5bccfd61,6284e836,13eecdae,ab43bb6e,d4d4e986) -,S(9ee1ccd1,670be914,f9b7a070,962f7ac5,ac9d069c,eb3e0748,72db2e08,32870fd6,7d3d9dd4,9e71fd68,4271b17a,a8203ab6,1d2bf6d5,2fe3773c,78a8ccbe,d256cfed) -,S(a256c06a,796cffbc,5c90d91e,93ded565,b9755b7c,b760794e,e3060b33,3c217e71,e9ef8b6d,7731c262,6c93fb06,b7a6b3fb,fbbe0e0f,54682409,e5218a74,d4a064fd) -,S(dde8a9af,ec32c1fb,be9470d7,a435b4fb,bd34416d,e703a1ab,5188fe8f,f721aa4b,e7dbb850,aced2fb2,fcf5ea6b,edeaf383,e4ae0fe7,98badf41,66e58f13,6a87f3ae) -,S(fe88599,811d0e9,f780d359,2e8106fa,2f54fb6b,ba1df66a,b7b0b41,2c130c49,b3b0b8b3,c7f36d43,86f30438,1989d885,31edab91,f25251b4,e01b3d3a,6ec97f2d) -,S(d7da001e,8a606b37,ca65ae71,32214cf8,258dd422,efe0fc83,adabd56d,64b0467d,97f503ce,8eee1873,7e422bdf,91f051f7,1025353b,3a1f6f1,545206f8,2a32aa5d) -,S(65237583,e3e1a640,c2c16a9,a49d09c1,f5dbe2d7,a3845989,574abe33,397e747b,2296a1b1,e2350d8f,14a6fed3,afe30fac,a45ff345,9f8f515a,370aa260,d435f7a3) -,S(419a8e03,2d8fd27c,afda6538,9b757550,313307d,12fd185b,4d2f026a,40ae1de4,2932ea7d,3421d738,d821030,f75b0343,fffe9d25,8b605cf7,e20f6b48,1a94db03) -,S(275d261f,7ae2ab4a,4ad1fd66,1621a223,7ce08787,beaeeee1,a537b103,c0a44023,da955bd0,4ef1256c,9e184615,c4ee666d,c9ae14c7,d95caa7a,5dca6f11,1e5e2e58) -,S(3ac6681b,d0a2968,290ad83,cb0e00c6,6a9962cb,4c082366,953e294,58ff3651,28348b56,38ede228,7578cf14,ae385066,4595a2a8,d86282a0,edcc389a,346066d4) -,S(d4ba242d,9407df55,a9f672b7,e01cb1db,99ef744b,d24d3e47,9b1841af,a6c1f05b,9e395144,aa1fe50,9d72d086,4a1673c5,24c4ad65,fb7bdb16,cbd52053,1c6f11a3) -,S(c6525077,2bd399d9,901d57b5,7e8fc941,cae0f5fb,6d47ee3f,5b3a7cea,3fba2e83,629f7edc,a6ec6b0c,579cf9f1,867e1bef,e3bf9bea,8d8e64b7,2b18532a,47280efa) -,S(f12daac6,d38fcb00,c2425a79,2c52225c,a94d544,c6b96076,7ec9c885,d6d4430d,1764feee,2584dee3,abf2aaf,737a068f,fa6aec89,6c02e2fd,cf0ccad2,7ee8f210) -,S(db858a7f,4a84d88f,236b5994,dca409b3,d7111df4,f7e5c009,4ad1decd,82036673,c0606c89,e4b13042,9e0a63f5,1c93b3bc,95d98832,d89a9515,2e5c1874,f2c94a53) -,S(237f5f80,4d4c50eb,d611b079,5cbc6567,101ec8ba,1a265976,64472f7f,5a725ed3,b558d31b,7647c4c9,1367d696,a67e5d88,76454900,f340cd,5b8d7490,9fdd5993) -,S(e962e9c7,7c97cf36,32bf0a88,d6e939d2,68af9fc6,ebca96b8,6fb679a2,d953eb20,931395ff,a50a854f,5aa29314,c50c253c,c3175739,9c2eb20,600b0217,9f8ef48a) -,S(890514d2,14b57796,85c0cd66,818d182c,3d285af9,771c7c48,92ea2ac,115a8c3a,47c5a,a4d76cfb,2a62993b,b499df86,fbe7e130,d4758235,7decd72c,b61aee8) -,S(8b058976,295a316e,65da1774,da78722d,8d729f88,5ea4402b,f20dc67b,bab7f815,aeed497f,57d52480,23b94a3b,5fbe9c0,e34d0039,2d57b34b,377bda9e,b8703335) -,S(6a4685e0,7d96a793,d55a6416,6b089623,755fe549,3a879fbf,fc9a5a74,7ee7991f,313ffb6d,98044c92,f37b3f66,81f1b4b2,d9b2e42a,7c34a5bb,db45b9c,6063aad) -,S(65157530,e4ffeeda,41064bf1,f8d85174,2b9b8f64,87a05ea9,3d2198bb,3f33fc26,5b0e76a,8f96facf,9d492232,95a0c6f5,6a609504,b9b07c38,a72b6f15,4cb8c9f1) -,S(9f6c288c,1e04703,46b02d47,8fc0a40c,dfc0229d,928639cc,6ad2ac88,96e55085,2af7c1c1,7210b552,4ae2083b,b45e9749,c9452776,c12d5e83,ce265c98,51266c8c) -,S(c566e04f,e5ef7062,7d914a04,40731caf,3a7dccbd,5415cc1a,a2d81328,b8a6da75,a3fa5263,a7f66158,67f43270,77d3b2df,8db1befd,552249ad,e96db0d2,8c439282) -,S(6963ffcc,cb62ca7e,565fa9e7,99db54c3,dcaad601,95bd2dd8,df70d447,c443ba4f,96c715c6,84bed531,27c28e3d,6d6a0214,883aa214,25c4626b,4c11cf17,36b8f134) -,S(50db27a9,8e0328e2,81139df7,5376bec6,37e9272c,f7c23333,510bf5cc,c4f46b2a,b5221242,9eec82,1e9143fe,af9e7813,c135be82,bfc153f5,2ac061dc,c1302d92) -,S(7badba3,8f23f854,2404e636,b96e86a6,84557310,2bceb7c0,241e71c6,1ae22ad5,bd000395,b5d0ba4c,a76ac682,5191fbeb,f6066d8a,81c4a210,56ceda82,e13459e4) -,S(147667bd,5591aa83,26fa497f,c60f8e7,a5ceda47,9d4b2f7d,93bdab3d,81bcbd0e,bcdbbbc4,2adac6ea,413fc3f3,6cd2089f,420a6183,a918bf98,fff27aee,3e870849) -,S(ee576c33,e8404e1e,11e1b5d8,6ea52335,cf8b0ade,49dd16a3,7a61fc10,cd3eefd8,722bad17,6e083868,b3c14ee9,a70013d9,89c01b5f,44188ec6,7db7bc3d,ca26fe2a) -,S(8e3cfa71,f3b7d3cb,fe59d8e0,b579b76e,d33d318f,41d3b76,121b02d3,2acdec80,86be156d,b76429cb,ff2c67e0,c015b7d,d0007c7e,33f6041a,d817ae9d,ed5dc4fc) -,S(e220362f,2df8a485,51dbb7ad,634c4bb3,714151fc,db3cc2f8,e483aac,50d88768,acb8e001,a81eb6ac,99dca40,2d62fed3,8891fe2,eeb8e023,6d8f2447,6f4fd200) -,S(1777fc26,9bd7aebf,c014c785,25dcd40c,f93db012,31541cac,448c44f4,89628808,641bdcb2,b87e04ad,3ea3a3d4,c364e93,1171b2a2,cf3c0205,77552b7e,594c649f) -,S(ddfb5269,fcbac0bf,a855d2c4,c9062c77,836af1d1,145b4df5,688b6a5,24c11651,c353674b,9520ea9e,eac3bbce,a85b0709,d0284c37,a7faf78,8b573ebd,67bac8be) -,S(b01ea11,d4704bb4,24cb11d8,b42411a7,3f227c84,dc10eb13,c2b20a1b,bf23258a,240844e,9ea3edfd,948d2df4,51538cba,ed57f157,d0632f2b,8b644570,5f9ccaf9) -,S(934e20a,46fbb416,fbe829d1,46bebdf5,2220c0db,958c2a9c,64244713,4509cabe,76b7a1cf,79ebb5fa,58f77e64,4395d33e,bf90c0be,37e7439,c3d29013,25b0dd76) -,S(15bfe959,5ee58bec,791981dd,13ac5380,6615ff53,95dd4661,28c23f59,ea236967,d6dd460b,d3d36bdc,eb7d3ba7,745fe6c2,fddba241,fadcbdee,44f377f,bd43ee00) -,S(5e1a723f,403cf56f,8019797e,6f8191f6,6e7ccf15,dfb1965e,590490b6,224ecd24,97342532,36c48696,645a7e60,552eeacd,4cba990d,6d73117a,dc6f2967,a6a0fdbd) -,S(1485fddc,85c819da,8894c1b3,8be82eee,762a052f,3830dbb3,7d21ee74,868c778c,d779373d,d503731b,52f9e689,805988c0,b916a579,921c637b,286c580,93343d5d) -,S(6f4b7385,f881c9ed,202ab6ec,c8302626,668a1296,36274f3c,ac4296e9,1eece7db,fcf6f192,c6c80fff,3f5c2bbc,7c6c4a5b,b0ea2e3,70799827,440e998,cf6b26a4) -,S(bc27cb29,33ca44d3,b56280d7,7d69af2f,9220f4aa,49aa0fab,685c7c54,62adaf76,7607d5b7,a02c5e21,cfafccc1,26e8439,88c10942,aae6333d,b5262426,1ed4da98) -,S(76f86b25,2530d87a,b04e64c2,4cd1e05a,e8324bf0,a717280d,3845cc5f,a6a1a733,2db7ce38,33bd24b3,55e95b89,ae6d8a54,19124761,e382745f,2a7347ce,fd7c382c) -,S(5615175d,2ec968f8,81dacc1d,1bd6c06b,df87c9ab,53fdef11,335818f,bafa918b,5f755638,6154cee9,e71d21b9,cee3971c,7d41e3e0,ca2c1ff,f66982b4,d66fec25) -,S(6390f1af,1ef24aae,20e2ce29,dfe9a0d1,50b2826b,f5cb3629,8e0dc16d,ee2bdf8,cf3e2b98,4f120d10,16f82e1b,8916928c,263f3323,52bbedb3,c29ae1ed,b0d49b1d) -,S(bc5df46b,4fbcb83f,7aa53579,ac8d5c3e,8482941e,cf848810,f9239138,b57e9378,d4d15516,624e72d5,9002dca8,3c8b5914,b224d4c3,75260dbd,cda88f9f,2f772627) -,S(3d069f1d,dd52177f,cd802195,c7c8b2ef,1e43c34,9bd88b41,43bc2d54,6a2b8d33,2ba48861,14218d67,1b1fa4e4,2aae97fd,66164e94,af1e3026,8dfe9dfa,7155fde9) -,S(fa657492,fab9ab23,f1a49c17,40079d7e,abafd7a8,72e481b8,7b30cb63,8a47757c,89d2c7b9,2f1ad11b,d2808968,c426a00f,e584ad83,86dff03c,1a047804,a2e98630) -,S(e2318d84,61f85ac0,7db07d08,aacbed7c,5f5a45fd,7e505bb7,ac86b417,6b3eb46d,3b0170a3,b6f466e0,380ab984,e5bf4b34,89cbc479,cb2808cb,445614bd,8ab012e9) -,S(defa0810,91d1db16,fc2f86b4,fa5a7331,f0c15682,55855134,10f41a6d,a2bfa6a5,8429db90,fbb25354,3e77ca0f,e7a731d7,f1a481bb,f1c997e8,5f585844,423ace4a) -,S(fbaa7567,7306fdd4,8c85514c,bcb78e04,ef4d693a,dc7c356e,f95ad34a,cc880db0,45c4972a,161f4a23,cd71f726,d5617b71,421b68f,b0611097,3edf11b3,8a391909) -,S(5dd76e24,e3cc0c5b,ded55d15,858f1c19,dfff7e43,b299df43,3ee77b46,2122205e,992de68b,87bd6760,a75d6b90,89dcb2b5,5f0b39c8,eb079ba0,e4451fb,dee8f2d3) -,S(890c7a78,d0f1db95,75b53e98,a0a63d81,8096422a,3ee18403,ede8ffa6,3af9418f,7a362df8,7430b479,11e8d310,558195c8,fed28b05,531b68a9,1631ef97,ac008085) -,S(4914f692,f88e858c,b6174e6a,9d4bbdf9,87f0e373,1bf6e69b,8bf3531a,43a37e6c,8751e02b,fa9e0384,2ff3e4aa,307cb7c5,fe4f7941,1069249b,c8b19866,b6169cf5) -,S(a5f97745,ddc25117,81693df1,bd15203f,9d23bc93,9015be73,c6b4e256,d1d05416,57a99674,cf64bff9,7b9ba0c5,69d253dd,52aa188e,3ec645aa,89466c79,5d0f0370) -,S(62da0bf9,8d32519c,16fac809,95869f09,b570b953,e0a7bd83,9623a9c9,bebbdf84,9b9ec74a,c960fa8c,2ea8bd4d,93ff624a,9ce54fa2,4a1822a2,37d962d5,64e9121d) -,S(5caa2062,c25d7df2,23718f9d,ff29a403,e5200d22,bf064b44,c9519742,4c448a5f,6063bf93,1f72f65b,9ca76400,de5f5204,a8a0bdc4,b19cfd12,2664aa33,79a7a27b) -,S(4a81083c,c18dcec3,5825415b,2854250c,9dc651fd,5d897610,2ceb7691,576ebe60,850f48f8,7ffbf26d,eaad1f8b,2c0b8272,5f7c313f,55811b98,408f8f34,8421f241) -,S(ba8baaf4,9d0c194a,4814070c,786fd9f,4b8dc012,c42ed667,7b39f67d,da7fccaa,ceaa8874,10bbe854,9e87af6a,15ae1326,d85bb995,19a8c4d5,dd3a8599,d9ae0ff2) -,S(4c780a0b,886fdcbc,a30f239e,21495f9d,5ea38a6a,7960ecb,ea4dd2dc,9266103e,7e50e1d5,b6c811fc,f86ee651,5d64e06b,26827ba3,656dfd51,1fa64124,224e182a) -,S(50a433f7,f528d66a,961d7123,7e6d2bf6,7321896,5ec6599d,b1f34b0c,db21524c,6bca1083,9ef8d450,e56829d0,cb23ddcc,81e2e7df,e79b53f3,2f8aab9f,e2eec15b) -,S(b98e05de,573e37c2,80d6de1b,fd479bf9,bd23a6b7,2f6ab34f,caf03236,c67ec5fa,d86f07e0,8a4c3d61,f087dff3,a2af2d98,58787d2f,424b49da,de0c584f,4d8756b3) -,S(d0cb5279,e76b8be9,b2e9cdd7,b0c841b3,33398541,24923224,db54a91a,81995433,11fcafb7,28a3307d,2d87f2ae,d107b0b,d64f6030,b89e845e,1f67ce7,4cf7ee6d) -,S(90c89963,619b1593,d5fd7eb6,751ef03f,aa7c6802,46e36bcc,5d0bbae6,25376720,6e8f2a86,75b803f2,c3c87f9a,98318cbc,61b99073,2b8b33b6,62197ec5,73f64a71) -,S(bd3ad39b,989c3a08,e45007d9,116b0d4e,2dcb6a14,26a44dc2,29bff230,6c1a89be,7e633d7,de03e6d6,a7a4a833,f338160b,cb914997,6dc2080,28c3e2dd,b1c1b11a) -,S(1da5082d,a6e4721a,499d5559,91e8d216,f26167b7,d6de224d,17bc4e5b,ac94093f,5f864511,4b89eb63,60ef865e,6eb887c2,bb0b97e3,9a0b7078,888049c1,29f63c77) -,S(19320416,52e24197,d195a0f1,99818925,35c19790,99d15992,8999073b,4028d659,2cf34c91,2d1666fe,1abd3b0,49b12dcc,f7086e58,b7700b23,497bec18,e057059) -,S(79a7b5e0,482523d0,85bf574f,2e6e431d,b3bd6ae8,4e921b87,fff0f683,976efa9a,f713e011,70de0de8,a8cbe229,b147cf82,efc7fe3c,d7171785,c85bbbfa,ef935755) -,S(c2e16cc6,8559a160,9fe16d0a,9be4016d,55fccdc4,2d22ee62,895e0eea,a64436b,22399345,d40c11bb,79b9f036,5fdf6a91,4e1f43e9,bb1f0a87,81d2ede9,fdb6a118) -,S(f76c0f67,bd3c648d,c320125,5c34a93f,ed656378,8c9f61a9,c60933d4,e2d55d7,205c9c5b,83bbf922,8e99191d,e7ef0feb,429050e8,2b9fb3ca,1dbd2d5,cd35f612) -,S(24a3af8f,ee393ae3,2c30230d,ed6f96f2,9797d591,1cc3d934,b16e1304,de7bd75a,302041e9,2ce00cb5,d4a667ea,90df7f90,576865d3,7f462126,400c77a0,a44259b9) -,S(2e8bf897,5f29a6ba,636e6ddc,1e2dcd6a,1373f123,c6f155b3,3c8f46dd,b18baf7c,a93f0c91,258ec64b,d6e18761,872cf0e2,c89f9713,b9008605,b0378f8,1ec867ae) -,S(a5d35483,7f90d71c,8d829897,b3a8fa36,7c38b41c,879a3e6d,52f2988a,b88dcf68,853a586d,9661cd50,12d1ae6a,1501b874,739405c4,c7e32bd4,23ab7c1,62382bfa) -,S(51a6c879,ba6f75d9,4480aa71,2a343be1,bb9aebc6,bb4ca3be,de16d33e,992659c7,3e636d28,f8b0a4fa,a3ecd585,80d46253,61f496b0,344382b3,5742fcc9,403e7e05) -,S(a1d34e3c,aba45bf,1772d2f4,bcacd17e,342b66ec,97dadbd6,780cc453,ff2449d5,6c3a3b8e,9717365d,2f21e2ef,d72308b3,45008ebb,10ca02e,969d14c9,1aaf677c) -,S(fce0f1a1,69034370,33de7e6d,b2364b0d,4441c5f2,ee405e68,5dc546c2,58adc2ad,c018bc7c,fc5ad1f1,36103729,e1a177a7,495a6195,915ca5ae,c086804b,8c107865) -,S(e380e6af,c47b11c5,1ba0c8c3,9b796179,39b07cd9,988896c,38011e73,a4f98a81,60ecd299,c22fbed9,132bd455,1f44022e,151927e4,7ad93f1a,a0539c37,2680f6cc) -,S(6382fb8b,2f4179e3,191d863b,a0ec4cd,94b52103,f24a0377,8f6ee27c,7c81115c,6e8d4181,9621bf4e,3c04c5ea,2b4c0146,dd0ed973,bd4530df,d671f39a,e54db63a) -,S(c488650f,d66629fb,927dcb0b,9f5d0771,1caaa3f7,ad6df39f,7d8f98d9,65490aed,b395d9fa,46475b16,6beed01e,90c9cfd7,83e6138a,7bbc6d5d,f919d41f,3e512c) -,S(5cf1f5be,462dd02d,f8d1e9b,6cb1540a,4f1e5be,de9c8d29,954bfb0,217e494a,5e8727bc,2429c9a7,5123967b,b598207c,46105822,5402bfcd,c3d070b9,b2351d20) -,S(9644ace5,9dba2b1a,f3f3a4af,da130ba3,c3bdefd9,39c3b52e,670ead47,54407b9c,5e83dd4a,e338fc0b,8c501f98,72295400,4b2465f8,4f1c272d,20e3a2bf,300b1b79) -,S(728e6659,f0bb9bd5,916846ff,3aab6f10,85517ad2,c17254e4,c2ce908,c7934781,7df32327,354020,319e9cb7,696b0384,6b8e5bf6,691cc73f,829abd42,44e674b9) -,S(80e68c8a,31d715a7,5068091a,142d4a60,ff30d2c9,42f625c5,d234bb78,31009e8e,fe04addb,b9c47f69,3dc0b126,67b0960c,1b4a7bf2,882aa626,b1888e5e,e4157fd9) -,S(e655129e,90211425,558cbf1a,4eeeb630,df68a4e4,f96a176b,db55500a,89f5af02,d5e3a471,ba698897,9f747ae1,a1aa87e,e10c5069,3df12ed3,ed52307d,a0202a69) -,S(30a9e289,f6ab5edd,7b56f48c,e7373a6a,97dc698b,511343c2,8c5c217c,de67ab6a,f4016c18,c4f75d52,927127bf,c403a83d,4ce304d2,8a4fb965,beef9fda,4e9d3f4e) -,S(8a6a4557,2c1dba29,c9499ecf,d59ea43b,1ebec5a8,78a3e2c5,2de09aa7,c0288e69,56e4aceb,e8315c2f,b9271519,80a21d,c17ebad,63223380,b24a7237,33ec205b) -,S(647d3443,9f4e4f50,cee5b0d6,8047f130,965f8abf,482f6166,8859c86e,326c1bd1,f951b5a0,b180894c,f74c5235,cc625888,fb830382,3b0d085a,dbe857ad,dbc22088) -,S(6d143d17,9f0a42a6,85031c6c,f62ef32,2cde46b3,978b04ba,bc37bd3,34de5634,925d0fd9,11c7863d,b0ed42c1,76591307,72b456fe,83bb8063,3afe5340,cab4b5a7) -,S(f21cebe2,7ce8dd3e,fa30428a,cee881b4,d65eddd1,30f9fa62,9d78291c,a4f4b0bb,4a6d7f43,f2ed3d26,330e58c9,27a87c55,850620fe,1edc6e36,c9a3978,8f922ea9) -,S(37883073,e227a5de,452c7706,a4a06594,5a891c06,e594fd4e,191d36f6,79117c35,224bb4cb,389f3d25,42411fd6,594ad6ec,bf4f1c9,11f723e1,53dbb420,33ae8ec5) -,S(c21520ae,e6cb0358,53a7da78,919c88ec,84c17d10,3ac13ec8,6a412d9b,96e57c54,56720dfc,f748ca09,e27e8aa6,e29ea591,c0205290,3d38bc35,3b0b0155,113a5bbd) -,S(96cdb3f0,d6194675,7346b2a2,1767fc01,2e6d1ca6,f5e788d2,f89e2fd8,89a57924,9f5fda94,e0455b28,1cccc531,7118b175,edd6c93,c212e7c9,fe845f0b,cac5a592) -,S(7b5e5f5e,564606bb,a71b8f1a,7d410b1e,6482f508,879e1bd,38ecdc44,b7effee4,92a3f1b4,84ddc60b,4b005282,89984241,4f91b9bb,fd55eaba,37dddd0a,dcc1c6e) -,S(541fd344,c9d553fa,1e87c9cb,72150cae,a69a9a10,771ac96d,fb292be7,261912f5,80ef7a00,6ce5ac0e,975ecd69,601fd059,a9860e07,77f6f31f,365187b1,f6c9b392) -,S(2b2b3929,50b07da0,5c20b72e,4101e36a,bdfccb6a,2a7f36d5,b57f58dd,1403035c,ff6c1ba2,caee889c,14414086,456f096f,d065a7d,d2f9c7b0,9ed4eb71,3b4002a0) -,S(23acbca3,4754dffa,8cb3176f,d1435d6,4cba0deb,84e12ae7,adaafe88,497aa60c,5d95b3de,26f703a4,fe9efaf,cb273921,56a49687,a71433f6,9a2813ab,5fdb35d2) -,S(5fdfa393,6bf9c699,24417a2a,f36054d5,95640b6e,3ae30807,5ef51bb6,cd63fe34,97fdd994,bf74c959,2a5435fe,f1baea41,8a79c5fc,1243fedb,5fbb0466,4d599d04) -,S(177cf8ef,58aeefed,2832d53,417c7025,c6b56fb3,8122ccc5,2b33f79c,71c461fd,d8a12d8c,69da9b31,832cc10b,55b57a60,b900c19d,f8f38c92,f6bccfdb,98d3acf8) -,S(14f90282,e5a3121d,a59e919a,fcd146a1,9251cf5d,c0d805bb,bd013eef,4ab78bd3,74a504be,928ed13c,f29032e,5c3dcb3,a18a1df8,aad26b4c,a64ebabe,6afb4244) -,S(31099221,e6ceaf16,81b22b33,dd8ee3ef,1c2a95f7,2bed88e8,15333f69,f91867b3,772e45f0,930ebd2b,7f5b7ca0,640467a0,8ab5472b,f6bd347c,903cfecf,8f80176a) -,S(a6a0a416,d8eb22be,49036f4b,dfc79c6e,6cd167cb,38813269,70e199ad,c5d1b5de,54d036de,6b84f308,84faebee,4f944375,fed61a6e,7763bb40,a283ab52,3335af10) -,S(c7c5cb1d,ce484477,82e7da9b,55bb8482,4f715a80,d844294a,3c05dfd8,3dde77cb,bb66731,1bb0c2a4,e493e257,d289a42d,3630ee24,ba0f7f86,134a7c6a,72dbc3df) -,S(f1bdcb49,43267948,fe1c9b7b,51afcc79,7027e4fe,f98c2175,d7d1b8de,770328b,271f57bb,a9249cd7,dc510173,5a2168c6,ea97b341,b44cacc5,4083d115,6de8e728) -,S(2815f09a,8f0e2dfa,d21f50c4,60b8f69d,3aad54d8,aaa99226,86050582,b954d912,dec68871,752d862b,32ffdf2b,482ce1c0,6a659bcd,3a2931a6,29bda260,cb3cbf35) -,S(622619ba,8b74a0d0,5f8fa899,aaddd272,c9e6d43c,49bb6708,367155ec,4907d0c2,aab9b1ad,10201d50,7bea05bb,5b20453b,6474154d,ebe3ddc0,c86535ad,7c701954) -,S(a0390604,a40611cc,6e36c81d,30cc3e75,d162e695,1ae0515c,75417744,c093b997,60428c28,8d32d229,7417b6d9,b1003522,8190a83,66cae58,f7887037,9fb99641) -,S(422c7d1e,b0498cc4,dbba0135,ababc80e,5416f187,11f0dff3,80f1e1dc,23bedf0e,9c47d3b7,eb5713dd,cbb9ec8a,60d931c6,3382452,a4c0861a,847a354b,ba57d9f1) -,S(982844d4,7f572298,afd6734d,98064369,d81e4851,4b176059,6d3a1e85,6f043f5d,9b86f6a7,678cb5f9,a4304f1a,a8d3458d,fa85e65a,ffc79da3,faa1fc8e,a2b7ed2f) -,S(993385f,a76b9373,422e4411,b9e8a85d,3ac0e09a,f9598570,63d50a8,67b67ed2,3e7a9a3b,222a66d2,f55fce7f,e33effbb,bce8cfc2,8991d8aa,376a8ce2,4e9b8460) -,S(15b05ee3,179d1dfa,61bfb0d0,1903f93a,f7e04f98,cfd40be3,2ec094d,1bd5a4a1,ed1301a1,451cecad,30e8fadd,801c9db5,5acfd697,3ed36621,2f2e3032,adddd939) -,S(6062aed5,7d6312fc,433bf7f4,9c10772e,829e294f,e7ad07db,177c75cc,9fe5e52e,96aa4495,c6eb07da,9a5a0e19,8771dce5,23a5d7ff,de314562,3b704f44,c4ffcd24) -,S(ef45dd6c,1213ac0a,5df18426,9491cb3e,bb5312d3,fb55c7f2,8351c98a,1ba564e3,91541d32,43e032f9,450f3605,cab238f2,703a9eea,8e429824,7a6ef63a,45540e68) -,S(a1e32dcb,c3a13a46,166ebb73,7e09041c,3487120a,6ec46987,6befb2a9,94f4a69a,ba88b7b1,8cdb2088,b5998b34,461b8a5,d85a57c6,31aa10f8,6ff808e6,3186e5ed) -,S(817e6c2,6d4ae706,f43ddd7a,cfa4eeed,6498ea2b,86aa661,9a0b45f4,e22ea33d,8aeed38,bccea5e3,4923b959,53bc9629,d9348442,4f33b06b,b02c882,25e47bf6) -,S(e734f5a7,736014fe,2ac9137f,d025f914,7574d67b,3696596,9f89b5e1,aeebf88d,74fe8220,7c83d3ba,ec54f032,f11f9309,9be25f53,565f0d60,5f2ab406,5287c997) -,S(87b2d307,414c314f,184eef07,6e9809d8,ea19c002,390b5047,38eb7bbe,ba1ae7d1,37f5c369,f5dd54b6,87729036,b88dbf37,45f33da,8c2bc9b2,64213468,f1c56841) -,S(dda23ad9,6c51604e,602b8e6e,9f08a67f,981bfa98,93194369,269c56b7,7986b772,6de02623,5ef973da,13e2577a,bbcde720,aa8fbe12,23c5288c,5724bbc0,228074a2) -,S(8d56a723,6adfe6a1,46182431,da5ff846,aee78931,27564954,f14172f5,27048fb9,c7cd6bfb,fdc51a83,252d4e4a,2c978cd7,67fa3809,521678cf,7dc5e514,eaf0b418) -,S(9da30ccf,f147de11,de528d14,863a4fcb,a2ef228f,506aee98,eabee895,eb618def,a4ab41eb,a16b4733,34a818f4,b6bd3c43,de4a9392,c15c9e19,a8b4e961,7fd4bbe7) -,S(e3339c3a,b14145e5,40c08544,eaa631c4,7be6c09e,563ec93d,2a05f219,f4afdf2e,fd586d7f,3a668a0b,f888083a,9ea84f48,43598417,f55dfea9,790ee89a,c412fed7) -,S(a6e08d07,66274337,f3b139a8,d6fc3f61,4dde9ef7,2e03fc52,45f7dfcb,1c0ab41e,d9620b61,116af945,708a610,c78f0b52,8abd97c0,21ee34fa,10d289cb,f3c06d4b) -,S(f8ffa0d3,b463fc5d,44e6eaad,caecaa85,8515bc4,69fe76e1,4ecdb25d,e503a040,e80dd6f8,934fa405,fd4d74b1,1da0d09c,dd723df,daf46221,796cd7e2,4bb83f1c) -,S(22a212a4,3c00408c,b4b94e2a,45a6a999,917c0fc7,aaa565d,c6f982cc,64b0d0d4,663d8ed0,3128ada4,f421853d,8ffd8201,1ec8b997,4b0d827c,ed318551,ff9930de) -,S(8d33b62,f162963a,f6636f18,ef33a83c,e9a17fb6,b1fc58de,6d271d,472a9d82,cf0092e6,60311726,e0856ff7,1893555b,625b117d,4698e4f3,f31611eb,21a56f5e) -,S(3bbf59cc,5b4aa31d,dfa0ce94,1853ff69,9db29cc7,a0021cb2,11ba28d0,1dc61d3f,d54beb79,d1edb94c,d6bd5ae7,11a3ff22,9f2baa0b,efaa139a,e4724ae3,624d8318) -,S(4cc9c2ed,3a7266ca,faffb517,d3ad4aea,2d4d877,d9b08433,a4fca2a3,691aec68,70ac52d6,1094da70,5f714f60,854a5656,8c25cb13,1502171,7bd4085e,8b489756) -,S(a997cf82,50d7ec36,125189bf,eb6b8631,cec31fdc,f156d34b,186f29c6,5d0b30cb,ca73d95b,93b43983,b2c51518,b4e419f8,415f14fc,b6356287,cd65d49f,92929d5e) -,S(5fae92aa,7c43ac60,b4bb4f90,ae2ac462,a6f88681,9aeada99,4d0694a3,a6dc1722,6b7ebdc4,dbe15dd0,9c1e4587,c7f297c1,74d5c933,6bc91511,f31e0cae,2e51b280) -,S(cf541216,323a9591,13561470,2b187b35,fffaff7d,8cf1993a,5144c7d4,aa836308,9d955733,feaab81c,4b03fe4d,25fe36a2,5075357c,b6ebf8dc,1822cee9,7f585f80) -,S(9c2c8607,bad80760,efb4ba73,442a359a,c1cb9b45,f81e54be,28f3f6f4,4699773e,7848812f,f3101eed,137b4dd1,4f503a42,9d71c157,449767c6,a5850204,869a9817) -,S(2f3bca36,fe504b7e,93f70176,2e65dacd,250b3789,541076ac,86352481,c896f77e,5af55f5d,b2e84dfa,38bdd0eb,fde7ea68,33471d28,add88dd2,a7e7c63f,dfe513a) -,S(f2fa3afc,fe4e5da,385f26d8,1848f801,7401b06f,652121d6,9468d2ee,f640260f,54cea12a,b4ced3ee,2ca351df,4310e96a,d3ca0d80,c3a3c86b,267c4620,bd0f69a2) -,S(82559cc9,ead1465f,a910b781,cb2a50ed,9a2b6ff5,d8513182,425b7dfd,983afa50,db5dd99e,242287bb,c94cd149,6e4aff70,7232e2bc,1fa4c440,5cd9f22c,fc4d239d) -,S(954079af,1494e324,fb707e7c,e9f1fc2a,751e194e,4ee058a6,e55e26d8,34901f5,2f90eb0f,43bfff96,c3b0f3a1,bd48c00b,85d3650e,52d1f614,ed65ce70,4fa19e99) -,S(c913a980,b1aca09a,19654428,6edfed20,dce31676,1fbff05c,1c05fa70,7eced342,17d2864e,df39460f,99b5b51c,91752c57,10ca7af9,a6e10c4e,c2b3e9e1,7317d3c1) -,S(815b7dfd,3b97ad9f,cf6ce427,ffe4a91f,2b541e2a,11305b17,2fd7b63b,82272db0,f0b958eb,fbf32959,dbc407bd,5290ca66,6f28bcec,2fa69d1a,7108a2ea,19d58484) -,S(7f7c1689,e93b7c77,20ab5b74,572e87b5,d2a907bd,624fb6ff,d5f29f3f,c64795d5,691a2f46,430c53c,375829fb,46ed4030,b5bc4dd6,70646523,45fbadbe,e6f8a1f9) -,S(8911275c,106e5a48,1c3dc5be,b9b42e2,3be8cf2a,5a76198e,e6749b24,bd9c5e7,747cb0c2,16d899c0,da5a8ed8,f279a650,f4537e7d,ca51bf56,b3ca8c43,92b5e99d) -,S(24cc2552,c907e757,9e85bf7f,fc868ebe,53e44b97,102b31f2,38678bb7,ad8c244a,a152808f,7d615060,ba9e78ae,720c2fca,a67772b7,fd99ed6,ffd5fbe7,ed114567) -,S(b0fc5873,68795dc8,55e3e19d,9236244a,812d1920,afef4c9,7f1e6c79,25395f85,f8b46879,5a0e40ba,2029538a,fb7cef58,9bde7b3f,fcc010a4,4ac962b0,afb8d7e4) -,S(cd6f4558,d634fc66,6dce566d,f94397f,d3ab9178,affd3707,55852679,adc6565f,d34d7be0,ea40586e,4f9007d7,4aca55e9,edb4b31d,8ad4f344,1f611a9d,94161b8a) -,S(fc5e8a3b,ada62f0b,6453f445,7dd4aff3,993005d6,de7b94d7,19fd487e,b88fb7a4,46041321,f7fed84d,2266d4a4,d86d836f,12f12296,d62ed296,6a7d5507,d6717130) -,S(dc72a540,55c962ed,90e64916,bdfaf6ea,aaaacbe2,fc180a7b,7e7bda98,f45488d9,e3b46394,41a2063e,59c4cb06,1a0a7e5a,a171fe39,812922f8,c04df63f,41c8e588) -,S(7d135c33,88bd5896,47f4cc3d,67fc7809,a7a4c530,e96fb5c,7dabe3b4,32a4fd90,79dd3834,8a61b642,9eb7a837,4e9c2176,95cff14a,3596a18d,19f84360,8aa0922e) -,S(7a56712d,b72ac3a6,353dad9a,15cfc9d2,7d9ff67e,9a35936a,e38e1c01,5980980f,6eda856b,9b5d4019,d0efb2f4,9f1af933,8969872c,126b2682,f56a8b08,97a83696) -,S(d3495480,25c7f966,d59b40d9,6ccb9831,2948c992,fcbe2f6a,7a7feb6a,946125a9,b346f8bb,532da4de,96908618,b0f85a10,fe9a87a8,d612e4ac,53bdbaf,9dfdb3c) -,S(22175a8b,d0a51763,d1818054,60951698,14af196c,df8648f5,29d27a9a,825e60b3,756d5713,81b5ce71,e23c0190,a1062fd0,645eddd1,7dc84c9b,b1c7d810,c13db63d) -,S(f557e381,37a1c6e0,a19e4207,4a1dd59b,17c5137d,97a58fc2,55d18be1,bf63877f,6cf0bb41,577ea3bb,7c9945d5,db33a862,3c1cce5e,d6fc13b9,b0739ea9,9af10381) -,S(8ddbadb9,c6a78978,2540d3e1,9ada3ed0,5ef35f45,a38be470,7083dff,75d501cd,75b4c5f9,51f70fb8,a89fec5,d52ea0b1,dbfc5709,3c1ee5eb,ff2ab0bf,f5854644) -,S(53f0892,cac79f48,2194dd9f,fc076305,a8ecdd4,977ac278,92e2d454,965a2aee,b39f7a9c,ecdd4ed6,d0fb1608,3b86d1af,68aa85b8,c733617e,5e97ecda,269ef97e) -,S(2712110,8fe28f55,c746525d,e7cfd4c2,f3a11b8e,3c6329db,a57a7b32,5a7edb40,cf6732b3,74681ab7,3448bad0,ae54b953,ee5d7bb2,5a8658d,3b366a78,dae5fa69) -,S(e7627b26,ff0448bb,cb45a538,2ff8ec9f,9376127a,b8425213,46e899b4,41cb5660,79842f72,e02820b1,e6b6843f,3a0c23dd,c0941ac2,b6fd30a4,39397ede,c78bc40d) -,S(37c48874,f07ce0c6,cf5be181,9ba31bfd,9a19aac,97b27011,1de59fcf,559fcb57,34dcc405,6a6dfa3f,283e0dd1,8b1722e,bad0e367,c30d9f1a,d552f394,9ce19b22) -,S(316868fa,33cf5544,1e9b9bc0,9f74fa1f,8daa9058,3fb8b3cf,8d339971,311eddfc,89fa5c82,9d9f4687,f7cb6b8f,ae20d6a8,cf872ded,a7f9b6e0,6e168c1e,45db4e73) -,S(d34a83f3,7b7673b9,6c8695f1,81ce837f,ce2f15b8,72664d3b,1a045c7a,bceadd44,e4f2cefd,59198808,15692950,19b9120b,495a44d3,4862323f,808b11b3,a8698081) -,S(687a48cd,4142060a,171a1efd,c41dce8f,8127ab64,ebd7c22c,7803f077,19168799,c082e152,41f7db05,ae6c1e15,e4ccc340,f4a7c8c2,cfd8bfb1,6bcd04e7,e635726f) -,S(70d2cd79,1d2d1418,9cf67e48,519aecb4,d58be2af,164d0605,2132517e,87f444e5,73b4c12b,edda1a70,89ae9db8,f105059a,2a558475,f5cf4796,1042c470,c9e190a7) -,S(2a6f2786,a191130e,dba1307f,f1bb0f61,c3d7b8ad,c02286f6,44871cc,170dd2c1,28a0c85b,8ec93fcd,1b9a0617,780da654,e5448475,a02a6222,f7065132,5ad64b2a) -,S(3f482e12,8d5bfc4e,d2f359cd,b4244db7,ec7edf92,f3fc5dde,5367d125,dde8c772,d41be140,cc4b4217,cdfaed4e,b09ce5d4,d3e95b52,ed6689ed,3f6dfde7,3c581cd4) -,S(96673e27,fb0f8a46,8fcc53de,12876045,77786d93,5afbca99,35545363,6614a5d7,f6a4eee7,1c4249c6,ef850090,59c12f6a,44adb8a9,cefe7a8c,ff2ac0a0,da28884f) -,S(be7a886e,499a9c2b,c05e5f64,77bcbb4f,26772e58,4565897,408eb36a,e25a9c58,24457eb7,802810f4,de64516f,24718b06,d61b0adc,bcf0d279,d883b2bb,45363a40) -,S(123985af,a3253837,e51f933f,8f25591a,823b2442,88cf8ba5,a0247ec9,94eecee4,a952096,21f7a9a4,3867c6a1,987dd661,1d3cf996,2aebfadc,dee0a5b8,6df196b7) -,S(75887ee8,c28bd2f6,a96086d9,aef71b7b,5a5fce50,80c3963,787089ed,e39b0214,47386fd9,a9216193,3bb500d9,a1ee8207,dc3edbc,17d3ccc7,32d9c90b,8995eb48) -,S(4f7642fb,12376864,29104657,2a2fffe5,2322df39,7cc097e8,f7a57816,e6709fe2,4f2ff70f,2e99354a,60cc5b2b,c3ef33d3,7e3e9ee7,16766018,e3a0ba39,efe5f971) -,S(8117d4fd,551c9ae7,4c9fdac4,5d87bb66,9bc7dc35,4b08de03,7c4a1378,734653b,13633743,d1ee8fd7,8482e3a,3a9e39e9,75b0f6a7,efb227fa,84feb897,693c5c10) -,S(8afabdf9,acd49723,d73c0deb,1016ddce,571abaa1,a71ae3e9,a20bcecc,ade5782b,2b66e3fa,ee86dde2,23dcc7b6,10ea8ed2,dd42124a,247b7937,9e190098,2580c71e) -,S(c4819cb5,b5af7aa2,895b81c9,31dc6bd1,de4a1434,daaa4fbf,abfca6d9,28c9965c,ae4db5d5,e1a09a03,67df8c9f,fbd2ae07,9f79ff96,410a9a5c,17229fe,5575c22d) -,S(dae02e8f,5d106f77,c8a1e1f5,4366daee,d312da83,1f86dce2,3e846e30,737d49f7,6d666cf4,73d269bf,aa7c3eac,4e5a2868,57df3661,c949b5ea,7f9a7a0d,11206bb8) -,S(a8762d34,c6f8317f,cba5c64c,68e25d55,e5bf7e4,5caadb65,a5468d2e,f9d779f0,6accd443,bb181cd4,591f8fca,210f9996,86460bcc,89dc06a0,2edd7bf3,d4b75533) -,S(bf503c35,fc8a0c55,fdf4149e,96b2d218,d29e4b9,1f703e7a,9b0d4da5,4153d99,7e1c09ab,a1437e02,a2be3d4d,7a444753,e475acd6,e3a42056,94e68ea3,cb7d1847) -,S(7898067,48cc0ad5,ab3a3449,ac82a1c7,d51f2b96,791ee038,dfceae58,ea0c5cc0,66b59634,96eb4a69,b87aa0da,2905449f,ffd2ae3f,ba1555f6,5c9b8ec0,e94ad922) -,S(25833d28,addd8172,c2a323d7,cf498482,732a0be2,c10d1895,8d097cc0,ff4c9a19,74708306,d01258d9,bac99a69,58ce1117,f245d6f1,4a1f92d0,dd48ca9a,4c7b7da6) -,S(6800bb8a,9dffe170,9ceac95d,7d066461,88c2cb65,6c09cd2e,717ec674,87ce1be3,d5228e3a,1e0bce22,c2d85b44,e670e78e,ffb1ec69,6c01a722,2cd1e62a,dc4e63d4) -,S(3d7d5874,42e4816d,af2f0897,dbb06cea,f6c673da,445a5342,c61a8793,420d107b,422b212c,93ab83e5,d6323ad0,35a55321,b7441835,b83f180f,c3803ccb,46fa4ba4) -,S(3c44084f,aeee2803,34db27ea,63339db3,9e8359b5,c9cc9a85,7ea49740,32d063e,36493b7f,1a732a87,db4703bd,61a76825,4a82846f,31d8920f,2cba7ecc,1d744491) -,S(cefffb5e,d26cf721,a51bfb2d,460b91a,a0b40a81,52073da2,cb75050d,f7fe8d19,b4e40e1,1eac7572,efefac2f,a97e5cb2,a0d042c,3ae8c541,e51be4bc,f6d33f4e) -,S(63add0db,5f5099a3,2f274c38,780cc215,bfd58753,144bd464,e75b0da2,dde97938,bbed5231,fe6d5b4,9679a13c,c3c6c382,5c300fb8,42b5eafb,13355c41,120c6848) -,S(ba5d1f34,63130cfc,425cc6db,dfe08329,4d7aef4d,cb207e3f,d1cefebc,7c791920,70df29d7,8030a8ba,56514df4,b6ecbd2f,ebfaa1b3,df7b23ea,ed16458f,f2f18786) -,S(7d363dd1,c6dd28da,94a7f850,ee753327,8b735dbf,f43e9456,67fc26e7,af75d6e1,46026468,2bd00bad,a5be02aa,5034e762,fe50d02d,6cb8dcdc,5aafa21e,423267da) -,S(e2dc0164,c9060646,904206ff,37f912ce,2d50458a,3ca186ee,fdda8d53,4184070,de5267d1,354d12ad,8d9a5930,443dbef9,65947f2a,5efa206e,146e7b1e,df7f5a2d) -,S(2e53caa6,35f0ad1c,7bc4c2ee,1e29b39a,972edbd0,7d3c0feb,9ab0d945,45815ee5,1bb33d23,ad85b572,130e93d2,fe366e49,8371c49b,b47ceebe,de3c1286,3f443b23) -,S(5dbefdc4,9fabdf50,e6bc1464,13d59940,cb36551e,5a6607bb,13213ffe,b56eba1,893fd0a6,1797abe2,fceb4054,c4f540a4,ed644ed3,13a2200b,e1d532db,44d0374) -,S(5ff207e4,2b52b004,6ab8bede,6bd26f5,316ae52c,d148965d,8a21e8d9,63374a2b,1b778704,daa94eb7,a36ad0e7,22a6d56e,c0b43c7b,a739985a,538bcc22,b9181bb4) -,S(da260b,ff4bfb8c,a54261ed,c96493d3,ffa90273,a55538dc,c9b237ec,e775fb3c,c7c744c1,dbe1cd19,20edbe3,c13f7631,1378140d,9ee64c3e,ab072401,86c067dc) -,S(b1985ca2,e7103268,f18d1063,c59d8d78,2250f450,c467d7b2,f4e41c28,1714421,16357630,3970159a,99a34c0f,e114b95c,f115d9d7,dc9b09ad,7c81d769,aeee6898) -,S(bf98e773,fe93f15a,ced03ac8,368e4276,1cf3821b,461cd844,2426d2d,cd1f7d7c,f4fe02f5,f45a9cbb,b67ef626,f239bad6,e5108c28,d783d70f,6bd889b8,6331185a) -,S(5dd657a9,ff99f15b,56c5143e,86ba7bc4,b0f34957,71d91805,71a3d003,ff008fa0,8da0b780,f644b14d,2b661b9b,484225b9,86b13038,a8a9bdf6,6999144a,4f5c212e) -,S(53b42d75,bccf2203,7252ee9d,25830f3e,36e7ed8d,8e1b6d4c,b2371e14,fd4fdba9,7791453a,dda2ca19,a775d684,9ee60c18,ca495808,6f8b56e5,1bf2b216,9690cd73) -,S(a3f43f6d,eb178109,cf4aaeed,a0666bec,481a1894,c25a4fc7,f4a87e82,680d63b2,d0331e73,7dc25db7,35625621,85073240,3a69a474,d5f78e54,93486b5b,3d1c067a) -,S(b83bea86,b07b217d,ddac9cde,9b42b334,c994cd1f,92beaa87,57a7e7cd,2c71b1eb,b68f8fd,66b45aa0,dd568458,73eb7829,1e613569,58345fba,7dcef9ee,dab957ca) -,S(16ce1de,573b3654,a0c00212,e878811b,25832f36,373da91b,9d9d7c89,d06ff12,264031fc,7441fe5d,4ce8ebc9,232d1837,7fa810a0,a0e19ba7,5ab16ae5,e93d5763) -,S(18fdf98e,93a7e380,8762e819,2b6e634e,f255b2ee,51c65b58,1ab799ff,52409e15,2d71afd6,c6298868,52ea0a1,943dbcc8,ff844ba3,80b177e8,62f92852,97868dad) -,S(3d5f8af4,ff89de18,866f596b,91300a32,a7aedcb2,a9423f4f,e364cf26,e2f53e96,46e9bc8c,ddc56d4d,ba25a2f6,e77a6a70,2e712496,7591725f,1d240e7f,9836548) -,S(69dc1e7c,11516a15,9edfa4bb,1afe0ea3,5be5b7a4,7695df8e,728a8dac,e2997db2,71be8ddd,d4c51c1d,5c13704,3aee6129,9541e929,799f7b6f,da08aee4,52f4ce8f) -,S(4e8278ed,ce9b340,1ddb1c3c,6b208539,164e1ad0,3adc082a,8d9dd5a0,9c63f737,13e6a5ea,7b2e8ebe,babd812f,2579b8bf,56b476ce,dd23c418,9be7b85a,940c5d79) -,S(91157569,7aed20df,771c1f4e,78b73dea,c89b2781,9b8a5ae7,5e2dc12,e6e7d148,e7114d60,218eb1bd,73074957,5b96fd10,50fa2d09,f37c0fe6,2887042,24ca1a28) -,S(3a37e743,bd2fe2f1,3f667abc,b6c03077,fd82722b,859d7bcc,ebeaf1bb,a6087d93,4192a6b7,eef51034,64040fb2,6b8d9928,21e321b8,cd611b4c,8d3e0186,646f5dad) -,S(d45b5787,9e4732ad,ad0996d5,879980a1,fc8dda5c,b628435e,96c3b44b,faf98f09,e4d4f5ac,1e4b039e,731143d7,60e2ef35,dc243097,d2e2382d,b86dc82d,eba0554a) -,S(ae5ff450,aa607a9b,bf4549d8,4d96adbc,6041cb0d,719793f9,2ec53b96,14522a00,2f061b20,e9bca3af,358e8d14,a04f1d82,97d1e1dd,a406d60a,d15727d0,66b2b8fa) -,S(befd3684,32785d19,7709ec42,e3b6407c,7a539b55,d97c8fe7,afd4f96f,d2050e17,65691153,b2efb4af,ebd2dae1,a50fd3aa,b648c7af,f5804d99,5270cc22,c02e151f) -,S(d13626c,bc00cd,36c776c7,8bdb17c8,18a2bc14,9612e0fc,7ab7888b,eab48382,ea4c3fc9,fe2238f7,1023ab83,fe0e09a1,dc167c0e,6aa05933,8f177cbd,241bdd45) -,S(9730fd42,fa9ffdc,414f90dd,ac790110,9619c01b,f43bfcab,e65a341e,2434435e,de61024,6152fb04,c997fd62,961209f9,44badeb3,6ea7774e,30e8c8a0,8bb0b496) -,S(a27e09ee,9dd4e34c,6a92f4be,aa1b8c0b,2a60b33e,99fa981d,afaac623,9f616d15,33e6d8f7,bcaaa24,b6008e44,377b4892,5f88e884,5fe73807,8cd4f405,a2747f14) -,S(d2dc7884,31e5a497,3905876d,bd6ceac7,8246c9d0,73d68872,f54685eb,5970763c,85f96d40,e31ecc47,dc07fea4,4856068d,15d2a999,735aeb3a,4959e4f9,9ecf5fc8) -,S(38fe7a6c,c401daba,981875a0,f0c2f528,30ce31d8,816a1d3d,47a3d96a,664a02f7,e9893a1a,87034596,9d95e644,313d9b65,5896a931,81d36f6c,7e390102,3cb28c74) -,S(f2d38ff,14100172,d117dff6,1522c61c,3a590eb7,ee9fca77,dc264e60,32291d78,94eb4046,ab31eda3,7593e705,792fdfee,2e3df8f3,655befa9,ef0ef392,4b02dab) -,S(9e23c290,94b6b8e7,4e112b11,69c5c775,4b690d0e,141b74f8,2988bd84,78d42021,e2528717,28fc8d9a,283bdfa3,a011d28a,f531f392,b5da6da7,1834a29f,203e747f) -,S(3054117c,33c15a,504156e0,97e9a0f7,d76be8a9,c1c88fba,e1d9d2c5,4e1c9185,998844e2,b73e9468,1b0b09d7,4ca48dc2,f29c6df5,f3c38f7f,b6846178,d4ccae2e) -,S(65d1e830,3421444b,7d5f8600,2c6de12c,16f15a88,504c6876,b9e94cfd,a206810a,71c9cca1,6e066545,b11e2c29,edbac8f4,8533ec41,1e331e15,a2bed53f,1b1878db) -,S(124b78b8,948c4374,7c5b32de,50cbb055,ebf9fe7c,56437573,40723180,131ec0dd,c0fefa74,970829d9,4c1314b3,64a8516e,3a3c7fb8,e1d49f06,b1b9c19f,be18ddd6) -,S(f6d81a5c,395ab698,28e5f1f7,84edc6f6,a55137b1,411baa28,615abdfc,36c18567,3a759acd,4b758dbe,79e22f4b,26774b88,40121768,f655664f,c3f9bbbc,91f564cd) -,S(e76bd19b,fe13dc17,ddd14619,da6b12c9,f2819514,6acef71a,9e7bc32a,7abbea8a,68cee27f,152177e3,afa7d47,903801cb,b20ba02a,c48fefd6,e23fc102,e6456bc7) -,S(7356c0d,ff8f26eb,7df215c5,cf923c4e,237fd7ad,cbe58f7f,d5c745be,6451a830,16a0d86f,ebcf42d2,e89e9a1a,803838d3,1dd7debc,527d49e4,a7db799c,e1eeee6) -,S(b8d00a56,43fdc57b,dd949193,c5df30d,8ecf5b4d,8b3a13e2,64ba3ef7,c8bfacc9,f05acf53,9343641c,3feac336,28e9b08b,9a4e3c49,94c029aa,470fde03,d5d8cf8a) -,S(f555e29d,4dd3e0eb,d03f3866,596be43c,677d1ac4,1a1a3a8,1936ca6c,89618880,171d88d1,9abf05a6,981eddea,8f030e53,117a2e2a,97c2f352,255038fe,32ecf95a) -,S(172e6167,6e7755f3,c6a59c40,97a8a870,cdc09d73,2064d24c,3db8ada,7ca50ec1,7c1e58e0,38f322d3,e147b3db,e9b8f311,135d688a,98458da9,f6f8a6d5,4d4e2a96) -,S(f8f5fee7,d4e8eb51,92cb7ad3,9ee26cfb,44724b7b,f9c74fcd,61f95e3a,f33fabc5,607fd05e,361bfd66,519b5e11,d00d22af,8b0ce85c,11b16cd8,eaba71e1,2ebe6bbf) -,S(6fc770f3,f6169350,bb8b247d,16088031,4348ef73,cee49e5,c0f56a19,d2d66491,47708f10,80e755f1,2b1b0d9b,3439312b,dca07d85,fe94fda8,414dbdc6,ed9353de) -,S(2b8c0b49,94d3f78,79776d8f,bd2980c8,7840df15,82427cc4,f07ac806,eb7f7e3,3a335552,ccb38312,92a71376,9c7994e4,19a7919d,b776ce6c,db2ff092,92e4d798) -,S(e473c99b,dffad22b,72b6fcb0,d741179e,afb78aa0,de4b5d42,dd19d7d7,72ab1a60,2d0f795c,61ed1ac8,b5691d5e,9d52b19a,42c368fb,9d0787fa,8ef3b275,2a3d9d26) -,S(f389dc2d,b76a47af,f9d7a380,ab49274b,1a40c4f7,970bfa63,729da698,b4afdc4e,b15c2100,b63f7f5f,911a6474,25866d79,5a57dd97,74c21cd1,4907dec0,f5f3afab) -,S(df6e3625,8fdefe31,dffa19ff,2416f8b4,9fbc09c5,e86569e4,4b7330fa,56cb6e1c,4b5fedbe,835f0b8f,ae20f627,c8e74f41,a5443c1,a764c466,65f673f9,f62dfc7b) -,S(27e40da1,a5d7cabc,ce586e33,a4ace757,da972cf6,17c3781f,3fb0e0c4,e6f0a70e,ffc4b339,9cc0b701,36d871ea,a7c3a6ab,fa9dc92,72625fb5,b8bde8d8,be55904d) -,S(71b6f20e,e558ac12,829362ae,53900a59,ae29cc70,77dd1001,d9d7eae,36b95618,e765adc,1125219b,316beb88,4c0434eb,a6f62499,b8b2d217,c209c7cd,622d0597) -,S(535d5fc6,1eef1a92,50ceaef8,e09e1797,8debd360,8b03f72c,bfe265a2,633332e2,f8453dc2,4ad1ef7b,819d4329,a4752757,26c98e55,65440cc5,b5d509d8,61c98a38) -,S(d1e2222a,26817cd3,a537f2fb,7437ce06,ce9fa651,9d3c1967,71aac21b,97de68bd,a131cb69,cbd27e62,cb65ab48,a7f3035f,a78ef40c,6c42e94e,da326ccd,2b452849) -,S(5aba9590,2b5062c1,59b9639e,f08912b8,e7eacda9,759a4e98,b0e21d96,c2597b07,896a74fe,e2596e46,1e93f4ca,178646cb,4bc5454,227a2dce,1bb5d532,e558b334) -,S(9f07bed8,4449bf9a,815a546e,ffcbd0af,f22c9016,188d15ad,7c353e2e,5cf84343,6fa14d01,ba16dd07,15f3e68,d57738f7,1cb56d95,61eb84cb,ad63bbd2,d9ba439b) -,S(80a1920b,14723439,cc2090b7,189f96e0,20e6eba5,5f8964ad,2f0be013,b4925515,fdb63791,6d074376,8e32f983,f2ff1754,43136323,50b98674,2ccb9ae2,7997a020) -,S(dbb37c16,202dfd9e,914f2922,e8930789,a70d4de0,9fe7eb25,7d9a2b83,aec2b4c2,f6bcb8a,2c7bfa20,491d3fff,bd36e82d,91a7228,9e4fb6f8,9e167803,a17b7932) -,S(f03035f2,f0ad31ac,59e64a6c,f46e9ee2,a2243ee7,de5ccb0d,cb30083,97551b4c,1a1aacb9,798651c1,2bdc6ce7,4146e259,4263474e,d7b9d42d,78026331,60748722) -,S(1886fa45,e7447e89,b0873362,605beafc,4e05965e,53fabe41,41e1c42,4fb234d5,eb5374d,a4a198cd,d9027311,6b4331ed,f0f6a7a2,fc52aa44,8a9274b9,ee3d7743) -,S(46a262a2,5b76baf8,ae0ba3f4,ed8f86fe,e4854272,cbd0ed41,313c4e0a,357471b4,c08ee494,66d7dc12,a8e08880,732574e6,f6fedbf2,71d6dc37,eec3c324,33d8070e) -,S(d521c6c4,a0db2668,5a36b61c,b73d3504,ea7b7488,e3d75410,494e89e4,ab404d37,41f334e7,6a28cb9e,25e6efd4,fe3eee2d,17480189,b921d726,aa027b3f,75f94bfa) -,S(8f44a4e3,c18d714f,62054e54,6e9ca86e,818fcf39,fdde40c8,3044ddbe,be3b951f,210ec152,f8c90d7b,8486d1f9,c5c49a48,68249795,bf7d0171,34d9573a,d5b22aaf) -,S(d5a74098,eb20aaf7,b664fb8d,63e08b0,430733f1,466552db,417ec648,36a31dd7,7eedeaca,97f1c85a,98496159,eb024564,1c8ef0dc,21c31ff8,9d06012a,3387647e) -,S(d2a63a99,d6ab9e57,a2a6d39d,3738c3bc,94505332,2a34d3d2,4cabd1ce,5111bb08,e50f6c3e,796ac830,e276fac9,ab6738b4,722fc87,880f2e93,7417198d,9c6c1323) -,S(a1b826f2,1f7abe38,c622b93a,7510114d,dffe4cb6,d3fe0627,dcc0465c,bc82ad9a,c9cec051,a253ab24,a8507b07,d24ee4a,c1d5a5c7,33f0c3d5,611e8a9a,e4aa9667) -,S(40719ba6,89926b5b,ca99a4,161a1bc,d999d40,2311fc5b,e2f5260a,c3c10208,9edb353a,73e9fdad,96ca6b77,b467dd9,c7d6d2c8,e041d8f2,19448ea4,c603bcd0) -,S(c0ee8dda,80fed10,721e7cd8,9dbd237,216f4e84,bb8f7138,11f8ca16,1e3a0977,6a786e53,2a0f49cf,eabf0338,1d64de56,1a1973c9,36d6a5ca,4aaf4cba,b8fbe1e7) -,S(9c75860,ecdeaf1b,c598a530,48a22158,8099afbe,20cb08c1,3afbb133,b2681809,d7019eb3,5fb61aee,56a1afaf,2675a028,b8735dcc,b3f5d93b,c3e29672,9203321b) -,S(e39df640,6dbf2584,fecea5bf,aae78b5d,bca93ef0,9054c754,d8b235c2,c5463657,33ab2fce,3a2e3e7d,e2ab230b,e69bcb7a,4d71c87e,a1ff5d34,eb8b78f2,d5c61a55) -,S(22480e,4a7cadd0,d17a418a,78074f80,c4731ce5,d9f1268b,1ca50204,1ff8282a,993591da,11ea4445,8ccf8bc,2cd55fae,69e96a77,89d006dd,b85a22ae,85316200) -,S(c613fa66,231d38b3,359c3b94,132a2337,e2a8c608,3c88b41e,58434c19,48a6a1ca,8087377b,c3d6ca30,8c932dc6,ff82430f,3fce21c0,1a8b8b6,c28bab78,d3ddab43) -,S(c0a94837,c2fb86ad,ca791fb,bb0838c1,3bb0c981,e23c4ff7,94dfa5fa,c663e5,1f81050e,d21fcd5a,471657fe,abe6fccf,a391f1e1,9a88c143,4644bfb5,e1f69f9e) -,S(87ab257a,cc2296af,d921bebc,8e52fab1,c9c21f08,ae09faab,18858a06,1e408ccf,d5dd88e7,89d2f2d4,3773854f,ca980411,3dd69475,a56864d,3c869205,d682027c) -,S(10d14c28,cf44c5d8,fbf5caf6,b307f6f,ee203968,eea1be3e,b3697515,2edf45b6,46926a1e,dd4f79ad,74fd506e,4443375,23ec76fa,e09d216d,3ef3ed4c,73b635fa) -,S(2eb78fea,63035a3d,db64149b,612832b0,c9ab7880,539c67e9,d722e252,f7e23166,4f72ef76,d3dd59c0,a4e1be46,6ca5a3ce,fd84d207,f7d671b,240fd41b,20e72af3) -,S(14d8ab11,402af341,dc5cbb6e,1116b858,14decf11,e6761b09,31b449b0,20b6f56d,91bf8c4d,cc717657,990e0e3b,3558a01f,ebbe534e,897d1204,8a7d978c,3a1d735d) -,S(cebc042f,2e7bd361,934da5e6,dd2dc8a,9e73537f,5d5e3e46,3a88bcc3,ff6d5552,baa841c8,5e0a7287,b1f16c89,8ef03f22,3097e92c,44952c32,45f2fab1,dcd988c5) -,S(4f28e546,ef539c7e,8f33191b,897b7245,8f48a01d,79f65b8e,a8f672f7,d0ab027b,b1c1db0d,55be796d,2b415259,89088a7,d86c41f8,cd8ccdff,2bda49f2,407123d5) -,S(c4d31178,b73cf9ab,b0e1d554,a2cf93db,ed9a7b9e,8f49c9c5,4d63c815,6e111505,f5e4528,7089cd96,3118e279,bfc6661c,1e77ab67,b81a71bb,4ec14fe0,ef0c13f) -,S(8e260505,bf045c43,f3fd972e,d4189725,a4db0774,52f94eb9,51e42eb5,6131f0f0,4afee681,c6069893,5ce21991,208457b0,11548d97,9a33a0be,cf3c840f,77c4b4d8) -,S(982818ce,69b4c6f7,631daac,868af6a6,79fa6631,8c9da2c4,bac994ba,f9c95d81,f5b13c91,e7593e5b,69c85957,6398b186,8c503b6c,25179270,7e602f52,f30ca9c9) -,S(75c2f2b3,53720779,8737488d,16a5ca6e,dade382b,78f2b2b3,226fd5ed,6ac6c855,95aec19f,b97734cb,8426e530,afda15e4,c3c3dedb,2aaa24f,7ca73b4b,af475960) -,S(606ed5f1,8e4dc1e5,3b6f5ae3,896433c2,a904cb84,1ea021fb,84537f6a,9dd45ed,3165cf75,26f277f5,b9bf22e7,36291513,10158d63,b97b7c88,d49d88d2,d63dde9d) -,S(a33e07b,c2934f5e,f02ae143,6b3ef5ae,d2d633f4,2b40e35b,d365fe2e,b8c72d51,e93cfd7d,f2e98817,9eb9c348,73530504,bc5cd8e5,d8393f0e,844073ee,df6d6511) -,S(5ee1d077,735a4a18,533b36d1,eb484f14,98b220eb,cd41746,b0947403,d6b4644e,7d4e1233,46a6ba1d,8a862514,4d4bc5be,72e23d,f25287c7,3512817d,e632f8ef) -,S(7485b837,2bb28a8f,d496f6a0,33b92ba5,96202661,8adef933,d6aadc56,55765b0b,a58defb8,deb4445d,80016c9f,5c04c2f6,e06986c8,cc95da94,3105d8fb,d0fe84ed) -,S(3a321f94,2268584c,cac5d8ce,5d6011b1,22169e73,d9093b2c,e3e0bdf9,ad680d21,99fb13c0,ecb6c544,1347a4fb,842a7269,1492219,f9bb7c25,1916f837,7d4e2cc0) -,S(c115a2e8,265c6005,10bf7108,ee30bee1,77893d5b,ab0a8cc1,754810c3,3f112585,e2f0a636,5836a24c,7a5c6997,45022e8d,e0b88afd,37737c84,d1ae437d,eaf0b3d3) -,S(d8895b97,cd390ca2,cf8e6093,c125541,1602fd98,97074a8e,aa11bd3f,5b0f3c1e,af8c594b,bd2308e0,12a632b3,1d05a25e,23247f75,6d7a22f6,fcf48cde,28056ad) -,S(4ad1fd48,e77fe497,b4a15e7e,869377bb,163d760e,105e46a9,a5477d69,fa944eb5,a96cce4f,e2f5f590,17af2359,1dcbda3,b640271e,95290d59,1fdcbd8d,ecf39703) -,S(62ffcf4b,7ce6c5cb,76766893,bd0a6f2a,e33ef821,d953c001,51c4be3e,67f2cd8b,d6b1d025,152db954,968ea1bb,dd2a89db,16103f55,47cdd042,9b7380f7,c4c985f8) -,S(e71343c3,cec5e49f,60fea970,6d256a4d,ba499e86,6f9ab33d,6045a1be,cac40a,ee1fe3df,df226027,78228bba,91afd126,a96fc10b,f5d2cad1,26091119,3a92b426) -,S(31766ef2,f3531ead,2c7bbaa3,279e81e0,b040182,ab78065f,d193061,2792035b,87b93ca8,91151ee9,775669bd,df2e5bf7,9f728d52,efabf584,352ba4db,8cd6f6d7) -,S(1e8764f1,982a97d8,b65a0a60,53a2fb5d,39f1221e,dd4f532,b007b2c8,c52d39f,8ed84e0a,de68b789,5ecf8c07,80ba0b26,53faeb49,3d23a453,cc23987a,b51f3a18) -,S(e249cd91,4e35f97c,92a07f4d,6f9961bc,d7f6efe5,ccdfd44,cb3bb698,9939fe43,9ee2fb47,4abdac66,5bb0178f,d8ff3bef,6381a90d,bfab05e4,a9e5566c,cc362ffd) -,S(b9a28764,d21db971,f7cb0c1e,87c9db64,ee6a1acc,485a02e4,5d5ffafe,ea1012b9,1b55a989,43ff4fb,25db6aa1,12d5c459,b1ee0fa3,aea913cc,54878682,f625e882) -,S(5d042803,9f8c37b4,dc92a9ba,43bf7213,971488df,be699901,31820bda,c0b6ff03,1ffd5348,88796c6c,a631c3a1,4773f89a,ea6d5914,bcdf27c,38949147,cab8ac1d) -,S(6d817b42,52986e2e,8ecb908e,99011265,df0cff59,61a82b2c,baf0c61e,c8b22326,55cac99a,d6a70b96,5559af1f,c5b67469,5d653662,bce7594e,22916fa,7c4b826c) -,S(9b069431,297f0d35,91451039,df8a382c,1eba93c2,f62f4e98,90e54559,39916ae8,70bf9138,a04b9f14,2841a2e6,bdc3600f,1b22c81c,ba27f308,19a763b6,e64fef71) -,S(dbf5e41e,d83110a0,5dce4bbb,bee05f0b,f9700ef8,273b4bbd,57099bc9,460050f6,e3e8f5e1,697b05b1,23632b89,28c3b34a,6cf1e6f,327b4252,c3009046,c8406404) -,S(c8ef12ee,22aaefbe,9ca024bf,ba8fd744,d7c5d489,663cde66,a3ff1dee,8174ef33,db64c2c,db21415,fc552968,fbef01ed,131db2f0,1ec8372d,1b9da98f,4792e8e5) -,S(3d086c8f,af84b66d,bb9212f1,512663b1,793d6893,23f45af,9bdd17ba,fed8d7ce,2d6a47fa,9e1b6c20,a2cf30dd,a99547a,b9ab9c13,5ef86ebc,280ac62d,2ce7847c) -,S(e173d58,714db8bc,cfff3ab8,8cf1be0b,547e03f9,db60c97b,ba5a6735,cbf4bf4a,44b8f991,6764f393,68b36b56,9033e304,7fe90662,70758fb6,85cc3f6d,e31b2fc) -,S(31ef8faa,90826125,66e739cf,299de928,68c6027,b882978e,f72d014c,4aa4f379,9fb9e021,fafac237,8d21caf,f1262d7f,bd9b8333,eaab0fe8,8a3499b3,d153a2e5) -,S(5e112e52,2997b67e,146b998d,781bc528,7e2ad47c,b2c5863d,eccb0873,fa088b3b,19cf3f06,d3c1fdeb,8147e074,a42fe178,c0b14135,2dda5274,50a7d5ce,58d3d441) -,S(9ba2cddb,c1a5153f,89e9144,e862acfe,c624095b,8cf8b7a5,b15edd6e,c7b70eae,f032469b,9527911a,92dcff6b,5847fbb8,9f4ce42e,f20b40d4,80b3a58c,72fc805b) -,S(9ff7e46a,4e2c6e9a,d5843f4c,c5e112c6,557babe,723203de,d75be7eb,179e814,ec890ac0,2ece651a,6614bab2,1e4944a7,d248c886,bebb33c3,36c28df0,69be91ff) -,S(2a13752a,1aea6e21,d25ea21d,b644ab0b,fb84b130,8d3f2083,be26098f,fc4978f1,18f4936e,65ab66db,11bf53e5,7eb7d114,4820fd01,ed827f96,652514fc,d8ce910f) -,S(a0647c4f,2b4f271,97f3fbc3,bd81bc7f,f72d964c,1bcc131e,caf9bda6,57b356d7,5e023102,9a8eafe8,9466181a,80440196,e850390f,d42dfbc2,1d3fbf6d,6373a56c) -,S(6abaff96,aeaca928,ba9a0503,dcff7a51,420feffc,33b1ad53,b1a7bd57,8c641ede,ab59c03f,7ad47f73,df424882,dc3ac2bc,dc2ae6ed,3eaae48e,b807b010,98dc0de2) -,S(442abb18,54161ba2,47fd366e,52d40d56,65293573,c339aa2b,28dc67c6,70f4ee99,c3f44b44,d13ee3ed,4ffe5188,c5134d60,a28806b0,687b5652,99924655,342a5898) -,S(9f54f23b,45f632c1,f05245f6,c5d1c433,9e18671f,da494eb4,3bd22be7,b1610096,25c9e532,1a5563f1,f47a1e4c,99d6def8,541601ac,8420de96,190157ed,aa17445) -,S(50296c0c,185abbc4,1c86f578,8dad10f2,7f76074e,24e931db,53944b48,6ddee613,81a02b32,b1edd539,37ee1c78,ab630f2b,45336e16,cfc560f0,adeb464,fb71b9f8) -,S(39c2d099,e2892b2b,1b6abb1,a198305c,ed59d94,f7022cd6,d521b510,9a8fc219,8900f6e6,3fe1a7c7,27728b92,aea4d70c,1316570f,edba940c,e626e94e,f03dddff) -,S(3581e30b,17067e44,664201ba,d7a6ada3,e0648516,260b760f,b406dc48,11c9d0f4,c8bac129,83e49250,bc478ee5,fcfc0660,37d68f9f,fda1acc3,6861743e,d7a794b5) -,S(72b67dfe,d341824b,9fa09057,b8362d1,38287eac,7292610,1169e41f,19dce477,be527b0e,52ce07a6,99065bbd,ebd360fb,72c6dc77,88030aa9,45fbbabe,7f038524) -,S(805af91,4a973e36,43712cd4,4a1da4a8,3d1237e5,9c991387,17175aec,4a8667c4,f6a7beea,205810ff,5d1f0e8f,5818854a,bb730c7a,1ddf02c0,968b1b05,92ed8a15) -,S(44794289,4b297a87,e3cdeead,5cb2dc42,9fdeeed5,b8038189,331874ac,88e67536,d67efdbe,8d7ab8e8,1e25c340,77687b94,d22d8ec,b89d7f5d,46ca212f,abcc1b5) -,S(b73347c9,baa967a7,5e5c8ac3,14f3c6cf,275cc893,72b26bee,731693cb,48d36df4,307f8fa1,98f1ba57,7ba330d5,816cb8de,d9ec3f13,6bec0586,53c64675,753f1542) -,S(ec6d499a,efd540e9,357f100,4a136049,d1f7df5a,d99c44c4,6e3ed416,9e40acb6,21e8082c,df4fa2a8,38327e80,aac15ee4,40549109,aaf6ea01,ccbfb95d,3f7a47c4) -,S(7607b7ff,8bd8369a,67d22545,c40a1588,aa2e50c1,b5be6115,cbb8794e,2085f283,6c4a9aa2,1dd2ad4f,7d6c4f02,23885803,ac3b06fa,6c0772ec,bfb610b6,a1d25ea5) -,S(dec4b7ae,42e8a25,2c414458,d4e0d7fa,4bf4d0,c9432754,13d3b770,8fb53839,bc54d902,6d035b64,35796475,67805bdf,af6cdda4,d0177206,384c4ca9,8edb5898) -,S(a7be1017,82bf48e8,37c2e0ec,821e37b3,eab03607,36561152,a95a06a7,fbb7ae2b,dfd27057,dfaae0a9,b9523a9e,dc28a2bc,3631e84d,5fdf8c3d,e1e65055,805fe0bb) -,S(cb398b20,29e55994,741b87cb,592e9099,926229a,aea60bd6,30eaa528,726a04a7,263e89b5,85475a8a,50723568,d3328fdf,56c8fa8a,f0f796fe,7b4d2fc5,9aafe2fc) -,S(438a6d60,c289dab2,e8933153,5c2e09b7,a677cfcc,a605ea72,8815bdd2,615c852c,109ed19a,51e01f3b,a9dbea30,f652676b,b3a8afd3,5ab5178c,ae557793,13025f) -,S(4db8d4d,882fe513,e5738be2,347a05e9,2c97816c,b39339b,adeef99,7b682e50,88280370,d13551a8,a9803a28,c56bac47,70feb07f,56a1a0eb,d132262a,f1ea574f) -,S(ae2ad953,bf13c4c5,c3fd5ba3,389323fc,260de722,e36bdbae,6db77b2,1c0df210,a5866bb1,7580958,df07c171,80606be1,25b3ee73,9c3bae92,8fa35e9d,8efc7364) -,S(85b3809a,3f772b20,dc526b9c,19de8cd4,9c2d9814,df4a9b60,1aadd016,64c66c9d,984a8061,2ce95364,b9819440,551ab1b6,4028f61d,3028b725,74dfbeb6,8c174cd8) -,S(7e2ddaec,e443396a,7c7eede7,ad96c2b,63faaef1,66109949,e7431b06,309259e4,3aeb7f92,14fd37f2,aeec1921,e64e7a8f,e6a4c704,dfbbaf62,779d0eb3,3b1e81cd) -,S(4565a74,6cd1d26e,962bebb4,447985ed,7b1622f3,faade84,1291d694,17c3ea84,7215d7b9,6362fcd2,320c0c29,e0b304d0,ab174103,bfd372ef,e6e4534c,64ff3708) -,S(aa8c5a11,712aa04d,a870bad1,606c9549,bbf676d3,1ea5b260,27bd1055,ed56f996,11ec28a5,a7435436,3d302f23,24eba092,68028664,f0ebd323,cb7bc587,7d92aac5) -,S(d9d5c0d4,b5a3305c,9f057dc9,8ecf7482,f6d825e4,69a641f2,caff9180,b7096e0d,d2b0eae9,cdf57651,bd296ad2,f4403e77,d643db66,fadd7a84,27a150f3,6d547ec) -,S(2ab2e7ea,1e1bf61a,8bedaa4f,e8fe3a7a,db66c25,ed1b7ebc,536efc7f,8de22777,28806bd1,fc7dca1b,a0cdc177,908e0588,605f8c1e,e76cbc07,ea05b6ad,80c0e5) -,S(2da97d42,a9d064d7,38bc7fc2,f2db39a9,588d57f9,8094903d,cdaf5054,238c1568,fff93946,e789b902,8694ff95,a68a7fb2,981ca0d5,d2b6de3a,b3112381,b8360f1a) -,S(470fd28f,31418f2d,70367e4e,961da5cd,af8d0255,5bf6bcf5,e7db8967,6dbb174c,59a49444,2a250264,3faf843a,cd242640,e3622df9,da6bb1cc,6c956b7e,5a26078b) -,S(e41bbdd4,6b78fad7,ee62c33,9664fbc7,e884f88e,dc184e12,715e8368,160a7ef5,40252593,7979b92c,f72bfa7d,b3f378f0,cb4de758,a6348c7b,2b1d73d,57ac9faf) -,S(9761799a,7e155a4d,e6aefab,963b23fb,1f17d8a9,cc5f8c64,6d4dd638,2359c553,493bb00,3ab38aab,cb4d4491,b6b9e8ec,ef068c9b,933fbb32,6e0e1c75,ca44bf1c) -,S(d59fe2e0,5fcdcc2f,dcc22cb,b9220051,2c936bc8,2205f5df,75267a5d,b45b1245,68af556f,949df3fb,d8299f05,f5e85874,57d109bb,4d395634,89d3ac77,3d4b7b2e) -,S(f8bf168b,8a03f3c4,8e7568ab,ef613bf9,3f515f71,93a24b62,827455a6,c6bdf142,434f350e,8eeba6f6,d8f07137,a33199b8,88907744,eb547384,dcd96aad,5f9f3911) -,S(65298ff,636b442c,8c45e748,c3cd2d1b,94770ff3,3bde1d63,21135bc0,89ed81d9,d0aca445,cf460f5f,47090202,2c84fe1d,ac0a81e0,b7458e4c,9b21dc34,8c223ceb) -,S(d1ac0d0e,25dd02d6,fea02b6c,c98f4b17,38046416,93258208,f04a81d3,450aeaa5,be491f07,1833efce,56197dd4,d3471eba,2a23491d,f09a87f9,8a4ff14,257d1dda) -,S(be876d37,fc1605e9,ea0923c4,e53497a3,8d51190b,dfc3dbbb,3191a483,949cae1a,8499ad31,ca5acd99,4a98caa9,2a91a321,5fd1f1f6,cd70c463,afb91673,ab6b3a72) -,S(7c440cd,aff0d8da,6fb5e2c8,fe27a301,c2906a63,7d9b1bf2,db848f13,175de738,7dd6cf71,cb013a8e,9494cca6,b418fb,e99e9c80,3ff34d35,e586fe25,8ffc4fef) -,S(25086ee5,f0037c83,e38abbaa,e0e3356f,c49020d6,f9006edb,235937a0,4d7074fb,35c21eff,8cb888db,d3271a5c,4dc1db52,2072e58d,974af68b,4d6cecd5,d13e582c) -,S(b1a7584b,6f43a593,363d6e62,edade636,55ffc711,48e6c9b4,2915d0d5,ebf4dbe9,f418f23a,9dde8808,59816098,ea06d2e4,dbad3385,737b7bff,a1b339e,1b556718) -,S(87e1c0c6,aece59e9,1118829d,ba8e0271,db30409f,c08dd790,4296b91,43fb7aae,4694c5cc,176cf309,e4bd4935,b88e2fb0,e7e1b63c,28c5bab5,d3356733,184ef152) -,S(19f43d3f,4bf0f2b1,9a157f3,3f71c5a1,20e2135,3187b508,e568dc5d,8131a2ea,3ff130d9,835e0eab,2744cdb2,5607fa63,edcf9648,d910e25f,b885ba9f,b340860) -,S(a7f9239c,5e8e371d,7d175c8b,120816be,2e543d89,a22c3f7c,5478ae1a,14f8f6b8,75711a87,561fc767,93510d5,47abe6f1,678d0cd7,335e7bbf,b87abbc2,cc3089e4) -,S(9f3598e8,f80cee53,969a79a6,d3b655c0,66283a8e,f2c5d7b7,8ce89e67,5d06446d,d9cbf50d,c2aedfd4,51fcd93a,46245bc0,772e9f9d,fe5a25f6,3af027b2,ea1edf79) -,S(cc00a72a,66dfc8a9,e7a4edd6,699764ca,c15140e7,216daa59,cadf0edf,d1e3267f,91b10836,c8ebd031,2f72cf2c,cf26c89e,1489c100,c72a04cc,71c0d08,45c27d94) -,S(2dc7758d,b176a48f,f3117aa9,671f7b6b,f0b2128a,4bc60fc3,f907eb1f,d20ff347,afc82704,39787ab6,bec0d4f0,7b7f2896,43073cfb,65e9d3ce,db8ff7b,791f2f59) -,S(2502f7f5,8dba7c37,bc4637ab,8c77c047,700dea3f,5b760ec7,9b68121,9cee008e,f6fea3d6,4e776f5c,cd293dd9,4109d6f0,1e55c039,c30438eb,6e626489,c92f078b) -,S(70d39d43,d7f2092,53967479,de620ed2,bcf963de,6ceae3b1,a80fd275,1801382,fef8bea6,45807be0,e1c5c3e2,4d391d8,bf0a6b33,564749d1,4fcf4ef,a8aa7133) -,S(a09962fe,9a934004,bc31f92f,526ff444,da7889e1,79453a55,b0fee769,34c69c2,dd717079,8cf19b8,1f55fdcf,86cd3755,f708256e,694fdaf5,f929c967,eff687b5) -,S(355a2555,4590dcf2,84ca548f,9ec9f40b,22482773,cf122a40,25ed416b,9d29c692,549ed0bf,db861bb7,4684ebef,7d70ac56,3703997e,c59b1f86,bb4b5dfa,574a2f64) -,S(4c145d2c,a165a5a8,b66f7fdf,c16bcd5c,c22304f2,f0ec3145,9b9fb0fc,797c9b9a,7cc14054,948caa4f,be04b54f,1b60a51d,cc482fc8,c94825f7,8de4f4a9,a63f8d5e) -,S(b5ac199b,fa591300,6d635fc6,86d87cb2,52c5c67a,6b897a09,bee578f4,9c57f8f3,41e164ae,d3d967da,94f0cd06,91cb3ec0,79c5712c,279b3a8a,d75affda,2879b234) -,S(ad619913,f00f620,38321c3,59931a9e,fd26941a,aa02a812,8d9f3bf4,8818185,d7b5a033,9e4b8ab2,bf66a597,45c0b496,b5825886,9084d306,660670f3,a9de912) -,S(f8314cdf,d7659ce,e8377abe,f4c80b00,9c99c1b2,f2bee37d,a726c6d2,a1deea90,db5a45c9,a7ea22cb,dba3a784,131ee81c,2a1d9edf,d9ccb9f9,6fc93d35,a332eab7) -,S(1fe1bfca,5df9c482,68e88661,89e238e3,7915957b,aa1e0c3e,af317d12,c2f84650,dbe03060,745396b6,fb22d6cf,a6b27329,3b3ed08b,a24ddb38,8942199a,765d7414) -,S(c414da43,814bcc43,31269d58,1c0a8c14,9e304f5c,13614a89,7f414725,9ed39070,ca194f90,dac3f722,6090b94a,3b94db7c,5c68931c,7461619d,8b912692,4fd90a4c) -,S(81a098c3,d1ebf427,69f621b8,3eced558,9dc0faaf,24206f97,480e40d1,25faba3,fffac91a,3b729698,b0b26f8a,e6391b1c,8f8327f4,7978b011,d7d1cebb,6b0ad8bc) -,S(f99441dd,e4332003,b6421463,b4bf6595,172121d3,f000763b,a40cccdf,be2cf439,231fa7c3,fffcee74,bd111f18,3689062e,1b6b366b,2fe14440,2061de8e,4688b3b9) -,S(2f930e6d,e3586768,792e565c,211e1abf,99e05fe8,79c01083,3e6e5121,7abdcc60,2d51a776,209a3da9,ca4dda22,7beea48,a93a90db,b51f0721,2864f36,a56424e7) -,S(9f8e96d5,99fd07bb,e9e0010f,90802d25,4b30e359,bf0fdcaa,d6e782da,62c6d25e,baeaf150,de04c7ae,d8d34278,aba6eeb4,9b3f213b,fd56585d,41890632,d6b64e02) -,S(57f186f6,fa5f4aee,e3e8b44a,d775301b,66d7fedc,4ab8c827,cb138386,64727f10,5a65c0c4,a69b16e0,1c32a95e,77c8f99d,53bc15af,5c168457,19bc8220,d7baf849) -,S(d344361d,dd0b764c,be16f46f,5efe166c,10a88bfe,bf532a8f,a1fe138a,78e0e1ac,dc1afcbb,a84b8524,a5d985ac,5506f15f,d0b92f85,875c2c4a,4144a93e,e455792) -,S(444163a7,58095900,e5c8fda4,88ecae95,24fe54ae,2592ae53,7e6db41e,8019344f,bae54b91,e69ddcb2,c1bf22e0,bdd721b7,a9ca51b,dad93b28,59e09509,77c26488) -,S(5ce2e1d6,46f10fe7,e4196414,37fa2c16,48029fd5,5340d2e5,f32d467,e0c4e222,6e95f538,cadb1b56,8313429f,35fb925d,d9ba571d,bc6f3970,ff4fd276,4228e82b) -,S(8b7226b0,8525a07a,84ee858b,58c418d3,1d4acdaf,9b081761,56b83a8b,fde6d773,684e6dc,37a2ba2d,89c0b01a,b4e1fcc2,1734eed8,2f7b1509,6724acab,5e276006) -,S(6aa5e306,36046384,ac8e3da3,f2f00713,8acaa0b,b0d12ee2,1e69018a,4d0554a3,2144dece,31a7453d,3a07e290,cef1b694,f393e5d3,f6cb07b7,a8c991b5,2a788029) -,S(8537990b,dd59836d,da16ccee,3871a232,3bd841f,6128f845,b0369857,66c7e0e2,beda6acb,946a6e08,43ec2890,c2d11ee2,404cadec,afb3f1c0,37cfb9fb,7b733fb) -,S(85a8cf21,1de57c,9c0ba88d,2f9a773,61041619,639c9de3,e2f2bc71,cb9e66d6,80d1d1cc,3c757338,f5a6aecd,815cd5aa,1d772aeb,5c1efa05,d5b64886,97ff6de7) -,S(d4f18d05,cb183c54,7594ea93,9330c174,37870e7d,48a613ab,4a920e38,18068267,32fc3b50,394bfc8f,a2a3f912,b35ebb69,d388c87b,198c3619,b04b6b3c,36b6190a) -,S(123e8bc5,65ceba86,d4c1726d,5e7e2a32,ac6f628e,940aa97f,c96ff72c,ec79e637,e54b4332,975774e0,748fb58f,3ddc5a14,8c3eb1cd,824bab83,edc76c28,e991d2c5) -,S(ac26cf03,c5a95e3,9a975746,a26bde6,8eddd6b1,6c83a3c5,81fa0a79,e93d0cdb,73ebeeed,b96d879b,882ae503,2f400142,5c8ed97f,98daa225,346a5b7e,9abc4832) -,S(54f2cc5a,a4d81daf,6600e921,441f5aa1,5bb51a42,7479e123,b9561d0c,8c71299e,3ff4e7f0,83f85039,d238a740,b7fd16a1,e313cbb5,b0c6fe5d,ad99f221,da4aa27e) -,S(8bd785,b73cca1c,6c405ca9,1ed4833b,428b7ddc,1a61c8d9,b0d1dea8,ef133586,fc5b65e2,5c3fde0f,3239ab96,625a9751,27a30cbe,f98e1ee,735c1f71,c86cf292) -,S(bd4218be,af5f92dd,f96a54fa,fe873cf2,171c2e30,a13c866e,e830bb2f,abb17d5c,86097c6f,91024f4f,8900853b,d17dbede,e2674e36,9f3fc69f,a2578eab,174e783f) -,S(a4006630,1b63e757,fce2f5d2,a7444e5a,1f2d7509,b7f59476,6951f38c,1755b497,87aef8b3,eb160df9,4b46a56a,337b6400,c724658c,a49c1162,c418e900,29efde08) -,S(5c5af5f5,65b2870d,6fd08f95,b4146379,15cda056,e18ef682,4cbbbcf8,adca740a,c7c6de6c,e679f0dc,84e28027,86ea726b,8eb0ad04,af4b9a5e,de516f11,583607cc) -,S(b5c3629,b86e9235,478aa7e2,d2e5b539,b70765b7,79ace9ec,ae76a659,80f0ebd3,86a8a06,84fef80,7a081bf0,3f08c078,7ad04420,76f5e1d4,521cffec,8b2dc96d) -,S(1784e06a,cd25fa66,72d1fc08,9219cdb4,54f5c711,4237bfe4,a2143eb3,20a0bedc,11feb0a7,d8d43ebd,5bfde5fd,21fcaa5e,7f091da6,3acf4b91,956172b3,5d3af378) -,S(39266c28,48f58af4,47e5ce4f,61cb3ba6,9c3bfdad,7e5742fb,ba4ca3f4,f175a291,7be4b872,9d1e2fa8,fee16e5,bfcdf4ef,2cff2872,e9c7fea2,c1997d6c,5d7f1efe) -,S(d6fbeb8c,72214cee,58b33bbf,2eb04924,f96e9b63,d104aa92,fbb09c8f,c2e4b1a7,cd9bbb10,a800d777,9d4cda4,561a2b8,759b4dde,45dfa2c,319e4e59,39938c8) -,S(42ee0a83,85464cbf,cd4a9ac2,73001bb8,592f2a74,b28ab7c,2eb7055e,2a471b76,d22c6ec9,d5499b4f,26947233,a5589aeb,14c94376,9a6166c2,af9d323b,e1adea4f) -,S(8cd2a043,4de9b238,f4dbc3b7,e56ffbea,4f025e2d,6c73a68a,4aa62bb4,9e9057f2,abfe69a9,986ae1db,52a807c7,c08a1116,a2dc7aa2,ec3b649d,7326bafa,ca74d21e) -,S(14c35089,62dcb50,d01750a9,441eda38,1a95abe3,72c501bf,a99f953a,5c94da3b,bc57dbf6,bba79503,f33be20f,96a54fda,fcd7be9,cb064410,3db11e3e,2034a3ae) -,S(2cddb646,76717e44,86fbe0a7,f7d6d853,7c3fff9,465e31e6,8da22abd,b3eedee6,136346f0,cf5fd102,932036c,3605179d,1429a706,71d95524,a14869a3,d1cae8f4) -,S(d806ee3,b5702d23,50c3f179,a00c3701,9c055103,318594c5,8f10b100,1b705aeb,79201749,21e69cac,a0ad5902,42e39a04,c3af8cc4,c665587c,cc0c89b8,3744b9b2) -,S(534f24,715e9b8f,f5f76a4f,a617839f,6fe2f175,3cbc3d80,331d12e,98f6ec30,e26ebaf6,4affe9d7,1ba2cd55,421c33ef,2e4a3fb1,c59a72b5,93ececec,65a40e1c) -,S(f33af0ef,4e23c8ae,7f3de5c5,22e8bd9a,6e527c8a,23242c8,4ae6677e,ec90b8f5,8510bee6,bacb5633,45f38075,8d85dd0f,493d179c,b9250d25,fe88134a,6055aefe) -,S(3cad4725,12a745f6,7e36fb92,1a2926d6,ae294278,8004386b,272d8520,f5a9aa61,d12ccf97,27da84fd,317116e4,9d45d741,776c8278,4b2c9f1a,e3773e1f,57b8934a) -,S(4b7fcc39,5f50944d,5cf3b3f6,2b1bbc3e,3aca20e6,d259e931,d3398d08,cb6fcdf1,99acfb05,a106a389,b7ad644c,cd275396,d76b046e,9992e573,dcead5c6,c7da96ff) -,S(9b5c0e8b,22a62110,bca2770b,778f0a2d,6d67e908,c57f806d,7470f5c6,abbb27f6,da52c77f,ea3056fa,dae674e6,daff8b21,100d007d,8bdefb12,fd56efe8,13c15a02) -,S(ee7b7f5c,e79eac13,d9b500ed,ee0b65d8,e7c93203,aaad71a6,9a935e31,20722361,e77ccd78,bf6380e0,5e5e8de2,20448a00,cabe7d6c,6b7ac318,56c09e2a,9a390778) -,S(b4774237,d36a59f0,e39a133,756bebf7,4df43365,2a4505c8,b0b84833,dd5b3a1d,5a5a03a9,e3463ce2,fa8bbfc9,afde9c25,763f4874,3cf0b2ca,7dc42c3f,9bf3accb) -,S(5827142,c69944cb,a066a985,79acdc02,83e1df82,8935ba82,5aa55047,5a52271e,c05c5805,6bcb6cce,ed5e8c8a,beac78b9,69c3b482,7ef5b402,c94fe1fa,f7fc81a7) -,S(ba06eb6c,a54fe697,9be9e9c0,f8c77be5,ada7bd7f,43894d1d,1705cc18,9c9b0ed,176be0,b5d3db28,7f235e2f,a9531fba,65f5ff8d,55b784dc,bf7271bf,864e3d5) -,S(ed84c2b6,11c1208f,2f059d37,a3d2ddc9,c3a0196c,9b9dee3a,5f2cbb0d,9383625b,6dff970e,b08bb4c5,4dd6ad6e,df25bbb4,621a5ea9,3869de76,2524dd2c,af1c6f6b) -,S(158b136,86fbdcb6,ad8ea001,9005405,b5cfc0d8,f614592b,d9e76b1d,8cdd568a,8c576136,634af4e7,9034b450,1bae33e0,9b5712f8,642cbeb,2b7c8910,cb28fab2) -,S(687d52da,10df8013,7232821a,990adf74,c54711de,110027f0,68464c9d,162c2410,dad3819f,8071b3cd,dd84fde,550d24e6,31785e1c,e137e115,8b5cc687,8cd09f10) -,S(32e8617d,de77c33c,a1d317db,d350298,50dc7fb7,148913cf,413e04b,384dc81c,9cb2fdd5,15231e83,21a3feef,804d62e9,2b8b9c0f,dfb73dd9,c3323017,b29f2ff7) -,S(a53a659f,7cc90421,21d96a90,3801753c,ea43b363,405af6,16d50b4e,fff054df,96734742,ecb3c201,742f8f64,df22569c,92212928,ca0d5453,d706f905,33c345cf) -,S(8a9e4990,b9b1a2b1,32ca9507,16170713,bcbf5719,2dca9d71,7fc9c4fd,a3993fe5,9542de81,f66098dc,c0bb0f89,44ea56bb,bb7e86f,9c63222c,80620c7d,2fac20d) -,S(5966c5b0,f92c5906,b9bda0a,7b3f10f8,e4c29796,f953db1d,35976175,dcb431d4,539665b9,90bc3810,4b7938f3,47ac94dd,7b9228cf,7270284,a825a202,ac62d135) -,S(2170d9c7,4ca5e85,305d159e,697fd1d,d32d6f6c,a2806992,f082ce00,9139c34f,b5cbf529,66f71e55,8015c90b,ea2b95fb,4a0fed8d,ef1f9af4,518789e7,39076c64) -,S(86e9b03c,2497519d,615f83f9,d0f9bf9b,101b75cc,50059e19,4d7b58a2,9b6fdf76,215d042d,7976ea35,a3dd586c,f5b286ba,a30e013,966fbb45,99845111,db8b56ed) -,S(2cc7d91,ba630172,ae56cf60,9a5d3c05,e27c2e68,7d607c85,ffcbf6c9,a467028a,9404f869,32385290,dff3f8fa,1a085661,5855aa6d,e9742d8f,9e2777f9,472ab5c5) -,S(84a89b0b,304ed760,c3a3d972,5a65764a,11d59ebc,25249f69,1d3b8711,10d3cc73,b7200408,fb1ab866,53b61321,10b6bc53,c8a0805e,568f8a0a,80a65678,c54c5829) -,S(4e9c88e,d10be9ea,a34bae15,8ba3093b,42ad9cb7,356f34dd,33eada3b,1937b4a7,b92050dc,95423a8c,759222ea,c09593c1,342c2dde,5fe382d5,6838df0a,877dbd9b) -,S(fe2883e6,6db454d5,31f2aaec,96f4f3f2,868ef393,d09c7685,a65d476,c6c97a99,1ac28015,1bc7c0a1,cc4be80,c6eff3a2,b8ae70b1,180c6a15,7c89dd3e,3e78568d) -,S(c74df902,ba66c205,e49f25c5,62d1eb18,f4f4f697,3cf49135,16000924,80f3f68f,17f7bbc9,59dd7e6d,9043ad38,7c0097b,403c8d1f,e676b8db,d7f2c63,1fa1ecd9) -,S(e7e7a72a,41f95b51,2ea42d1c,76da24bf,67059e,c27d5313,55c30e60,69a72c16,a20c2f51,6e9ba9b1,fd3a8473,8309ace7,da6006bf,bc42d4ed,657da6eb,6efedb8c) -,S(5a93859e,dc4ee632,9d36536e,1bf1008b,603d6a8,859ac6c3,a098748b,d6e18bce,489326a0,1e05c331,d97db6cb,68f098c4,6712d7d2,994e6c8d,be892138,e2106220) -,S(6161b293,71353343,a46d0917,4f6467ea,25a0f77f,fe614133,7fd3bf77,71062de8,57c439d9,a1682d4f,773c8260,6ee65e88,473544ae,64194ab2,3fafc2dd,7612b385) -,S(c35b16b5,a3808dd9,553c7644,400d6fe8,ca48c8ae,49c78018,4a71eff6,b94ce4ee,6c3baede,4925766f,3a7c59e6,d6c1c966,c3348b1f,5883498e,9956f3e6,6d8fe13f) -,S(fbdae49,32baf904,1d295378,2d227dce,4e2af60a,86796a69,86b777ce,bd2cd134,9ed9b5fb,df42e755,a9cd761a,cbb92877,6c66d299,35dc526c,f6950ba3,d63d0c95) -,S(6c5bdede,17ce2007,a3a1c18f,af8a846a,ce67b751,3d8bd602,23610ae4,b01b720b,6492873c,26a22bc6,39d4614a,202cbb2f,2a08b78a,753592f4,10c855d8,12f8d39b) -,S(eba4e62a,bf52b379,9305bfc0,eecc63c0,5221a0b8,b554432c,15e460d4,21dddeb1,e378e6c8,d6ddc7a6,72d83c3c,9d863c53,32b1cdc8,21ed458c,b817c49b,6dbdc519) -,S(5a79ee4a,1aab7803,23ced132,f9c67d5a,c740900e,cf71a0b0,ddb1d6c9,794cd90e,9f608713,47b3a231,548909fc,812624ef,26eb26fa,98630512,2b1466f2,665176cd) -,S(78b702ed,6d816c15,eb31dc27,619d5bf0,6ad646b2,e39750f0,73c31d03,e50d9385,9f1cc224,91befaa4,fbe9721f,86bebcb0,11024a08,4380e46d,bf11ce99,f157fd24) -,S(494e82e4,1c24936e,c291f69e,791979ae,3e2a6696,c8f68601,b57942a8,fe6b98eb,59f3af2f,c720847c,19fceea6,e3d2a918,ff7f564b,2e3bd7a4,beda6415,65bf5da2) -,S(28b3ff40,467a8c68,69fdc61c,33f002f9,73705468,4fc707ab,c0b495e9,a5c0b401,46a44995,b2c8f0ca,a32d8e33,b8e38465,4cfbaf1d,addc4d1b,852b2a04,58f84e34) -,S(4e4cf4f4,38a40e8a,aea162d9,dac13531,f5730d96,59c436fe,d8acd06a,c4c46be,4fb4bf3f,bc394c7b,57f81a59,2ea14c30,1e9ca990,5f48ee7a,5db08ea5,eb6dfd7f) -,S(e2ace7b1,3a9e3e22,a9b8ee66,c56e80f1,9370cda9,eb3ffb6,2d20805c,7f4c34be,1c8fcde1,2a653492,6428319a,981e1602,44aa823e,a82831b4,d0eafd9a,2159318e) -,S(e090ff27,e42469c9,91dab9a8,dc9a3a41,d46b7482,a59ba9b,cf4de93b,c95c7e78,d070752,c5679b45,4e1b617e,8315a48,1cd9d24e,eb53a671,3b4160ac,64e6f824) -,S(705c8790,7b976b8d,c8ccd3aa,897b2ed9,ea091c37,e285c37b,aa321c89,15ce089e,edccb405,5ae9f933,973950f7,eb79657f,e94fe286,27f6cb2e,784d667c,21ad4d3c) -,S(4aefb3df,663a28f0,d531e390,339a56a0,4da1c64d,4692c086,de232740,6d386d57,167af97b,43a36a18,1dfde22e,633547e0,eaac2f16,84e8753e,1ba1741c,2a18fe3f) -,S(ea909685,ee8c283d,1d7dfc4d,6ec8910b,b8d821d3,3997f24c,db5f5ee3,bb7bd72b,685b64,d3e02ee2,be2045ba,c3bb428,636258db,33177da3,17f6de0c,f8c805f8) -,S(5987cd59,ecccc129,b3498331,f20cbfef,f377cacb,dea76ce,2e221aac,d3aace8c,3427cdb4,f7367d60,44ba21b8,adfd5863,bae2981b,340c9bff,d0d7e93b,ee4d6140) -,S(e23845ea,e6ed3d33,14fd6f6e,f6d6e9f5,92f921c9,f448eb93,edb49869,97837eb2,89eb22d6,455cc139,e42c6263,b65233c5,4b1a3b45,34ec3d7e,58b788f2,6b11b131) -,S(cac7dbd9,7dcd353f,fbf60696,d325bf14,2e3920ce,26570b59,ff9aa65a,a6993199,6e81a4e,cd60a26c,90f890fd,6de2d159,50bb70e8,92eed375,25a48f3,31307620) -,S(9dab063,3a5952fe,f168d6c0,3ebb226d,de3e591b,4ad0c9dc,96b247ae,49a317de,846d87d2,7662b958,b3422b3c,a3410ffd,1ae549d0,c6757bf4,f96d2d77,168cc83c) -,S(bce277d9,ed439b09,f255cee8,af5363a1,12ec2d5e,b111196d,be30fb21,43f501e4,63f472d5,2649843c,42e8f900,5adfa50,d6a938ef,8f4f04d8,897a68d8,8c213328) -,S(df9f8700,2a6baec7,8b79cded,bb501dfd,54f376f4,5756501e,f03a6c7e,ac5f1d7a,2a1c5c92,789fa6e2,84105f4c,74b0a108,27ea2f05,5560bec0,5d0000be,b9b6c4d5) -,S(6211dcc9,307c40ac,3c7be1c7,5553511c,15d3224e,3b305c5a,39653d83,f134dbb8,545c00d9,f02b8833,5fe4851a,88cbde99,f7f02d05,ac674f5a,6559ac9b,d03febb1) -,S(d739aa30,8d9022fc,45735eed,3ff92f38,545f6c9b,b70994fc,b5f41f78,772c9378,d3c3fbb,9077dd53,d023838a,5c35b728,af4a90c0,1f16739d,12870e1b,15e1e6ac) -,S(9d85e55e,8ed84471,b6822c68,3268c35b,fa314b72,470e51c1,a7ac9f25,f8bceb6,8b01f444,e84436ee,ae159a32,7026d279,5c4116b3,b2e78f90,99f1035,1511ac88) -,S(25d39bff,22c40a94,b194c38f,be9d001d,4a632407,237fb091,163e463d,7c5c70f,33381905,11368982,445ad7f6,608be022,209466c7,98b9abe4,f4fca781,2c0c398e) -,S(67553ed3,f14c28d5,2abc36c9,3f15d0c4,7f6fe1dd,628b652f,36b29225,ef8ff51c,da5d42d5,9d41893d,10ed28d,569c0cbe,1cc077e3,36bb5c21,e3712bbb,9c480383) -,S(ea3e80f8,c800b52c,a6dcbd2d,399ec5db,65057477,8852a73d,68af22d6,f1abbefb,5cd8f55d,b5330919,377b48d0,8ac1bce0,dfb8c3ea,2b97a5bf,547b7beb,ea64a4d7) -,S(7cf11aaf,638b1fe7,3b8c5753,48bcc01a,41c61ee8,f2eb3279,c2ad21b7,f6f60780,579d9a90,3a8a77a5,6bef3ce0,53ffb3c3,cf969f9a,39ea5bad,b1fa075b,e918f048) -,S(ed377aa8,42897f6d,1092caa7,42c29285,2349bd7c,a0e0cbce,d3cda58e,ffaf5e17,44d1e8bb,6491dfea,cde53662,5e5d7b52,1ca11a47,1eeda260,647f6f0,f0c5f917) -,S(fcafcd82,dfc87415,6e0db5ab,2fa2b56f,dd488032,d22ddc1a,b7a0ec8,1f1c4083,42f88e6a,cf851a7e,ca3fc28d,f771cce2,bef0d7ce,3d26da45,a2d9c307,e9e7e040) -,S(4d372865,7fde43e1,68744112,26b34713,9c1ca4ac,c2905858,de50def8,5515339c,5dc438eb,7091eecd,a4868c48,a7933b71,7ba99d8d,5e8a946d,ca9605a4,7421df39) -,S(aea6fc55,47faaa10,a898f21a,f63249ac,a0625f78,ea819629,8bca035d,7639e470,4d20c80f,173980d2,8e6bf433,bd1dacc3,1882e283,35fa9993,ef808464,a5568d42) -,S(f0ce04bd,bfa81a58,e157a49a,11695baf,7233470e,baa7ae76,3a07f0b7,f71cfce,f9e4d701,baa6f197,d9912b57,d9df016a,b789e60e,d731afeb,f2e5f920,b4eef9f6) -,S(cc476e63,130a950b,b8284c8f,fe74a059,8d9d44d4,c0372a9d,bbabca17,517523f6,d2cd50d2,e2cae10c,df744ff6,61a6c96b,64e17368,5f81027a,c937a292,3ad7476e) -,S(90e0477e,8dacfda2,7a563448,65947a05,d0afe9ea,60634473,143508fc,6abfc73a,d117be49,166bb010,afb0b82,a46a4204,c18ffa42,e3c89764,3eaae0f3,303dcd9b) -,S(522a6781,951f6ec7,76b6cf9f,cd20287d,6977764c,517d4ebc,7209d55,5714b5d4,a109c149,6318d481,4cb22199,3567e5f4,5147b64f,c1f9216b,922d653,7637031) -,S(b0a4c701,725326e5,611ea140,325b0536,b22406bc,c1e7eef2,1f874ff4,e02ec2a5,df44faa2,8a60eb90,3974649d,54cf340e,293fbd09,66b7b7d8,884e4c8d,dc1ec875) -,S(9e874924,90f8d4ca,2ada28a3,2bccfdaa,51ead138,3421d7d3,482af7f6,6df47c51,a58a577d,d03a719d,1bbb64,6ec3051b,44535da0,5e7e04d9,fca42716,2e335fd7) -,S(650a307,7b8007ed,f0441dfb,b7103d3c,d5146ecb,b949f9d9,c8c99e2f,25df7324,aa05b394,8c909957,ed1bd7e2,720286d7,56c7e413,8aa202be,b08bc446,2fdf86e8) -,S(f891ea99,2a3ef255,6feafa4d,7dd3f7eb,1f1401c2,b75d65d2,6ab81372,bab6f932,f7002bf5,821837f5,8df109f7,2ba5eea5,6c767a4e,198a7594,21467d64,df5e0bd3) -,S(d35e82bd,44fe54b,5d2c0543,91260c04,a5ce8d47,32e83ccc,2f3035e5,56bf2626,b002495,99705173,e0a45f97,196b9e41,1a7f5d1e,33f1b39,100b511c,e51f6953) -,S(7dd56d5,1f139070,a382af7a,2db135bf,854c8e98,2a325b41,ed869de4,349323bc,a23a473a,7f263bf4,944ab5bc,2d82e20e,8e9256fd,b11dbc17,bc0e6bfa,a8325f5e) -,S(afed2eb3,c5a95b4a,e88ee73d,b57594c4,7013cf13,a48431b0,f7930d5c,27f5c3f2,26b49096,da666097,3403eabe,342ab065,78c8ec6f,bc3ac7d7,2b3c95dd,54735dbd) -,S(13826776,74f36fe9,ca81cea,ac65c2b5,51e9fad3,af246f,4cdc65cb,cec534c5,a78e8139,760a94e8,3b3f5ff2,a65fbc7b,6b2b55fc,978b8399,df2d7947,18b496f1) -,S(99200c12,6fed5ec,1fc849f7,e9769a7b,aae3178,bd6b59ef,2563ed6c,5342b80f,7a7f1713,38a84536,e73f358f,91eb80b1,6ce8ef27,ea55795d,16aa7f05,577fc13f) -,S(159febb0,27e04f1c,321b852a,3cca550,28aac30a,8bc27caa,73a069e4,df7029cb,6bc7e080,8834b880,c590d249,241b709,e7280a05,7cbc1897,9b8cc9b3,cc21a821) -,S(2add9be1,a3acdd9f,efebdc0d,a4272ca9,311567e4,61db8eb7,3519c1c,6473bbc4,357ae640,a88c55e0,d3559faf,b0775d78,2373537c,c25e595f,f21ed1ff,b36b5925) -,S(8e2d4265,1742837b,b077fcd1,488e73e,5dccd6ba,6401c6c1,8d36fe9c,c428b664,ee9a5b1e,a04ab8d9,6430ef39,7756f62f,a1dcf35f,fff314a1,c3eb1dc8,d9a1e5e7) -,S(79dd7d76,5b4d7db0,537a69d9,b94210e3,8e7a11f8,cb9cdd8c,6aed6a15,748a3ac9,868c4b6,26dc49fd,de693201,3b89cf13,e1dfa1eb,56fb4de8,9e5467dd,86e449d9) -,S(552c2ba9,96a13b57,32c3b2fe,d4e9579d,365e03d9,2bcb231d,f14d1d1c,288a963,118e11e8,646a0335,6834379c,bc93c1d1,3ad80145,dee0a51c,49b10e17,f6952f79) -,S(fcfde18,a53b5a68,9d33bbf7,79d0b699,2faee8ec,243e72c0,7ca09185,d997e581,6709b56f,43013d47,23f15969,ee01b0b9,ff0d9d95,5e2b98eb,7e78e1ad,49cf3d80) -,S(e9e9d7a7,4ad279c5,691367dc,9c4b7bda,b27451b6,a8e4ed47,afae1883,96d8d82c,292bca82,e6d1c88e,8869f33a,7a6df2ec,ad812dca,4c46eab4,5c56c3b9,15f79497) -,S(514054e1,3e7ceee9,3a19dce9,96256b5b,5876a55c,6cab3c48,74b15547,4a58f285,f9ea80de,80403f34,2866dc40,cb0a9aa,4b38b98c,c4c38e3b,37f4da03,fdf7f5e7) -,S(ac0364,eeb9e7b9,b9589051,635de6c9,447b327e,8c820272,f04a4750,6cc5f290,ccde3ebf,13b5a291,a73b0c8b,9a69414,4b217661,7b0a7735,3a6e92eb,4af21b7e) -,S(cf558594,4a73a11a,ef500dc9,60cde799,ffb4983d,ae76826a,a027fd77,811058ba,369ed987,eac1683c,4e8874c6,40049a33,867fa0a,520e5204,df328d89,f197bfaf) -,S(ee216b85,62eaf12c,9189055e,32cc55c8,2ba5e3e0,237de083,a6e77878,63c56291,2a8bad1d,a697832c,856f6adb,e1cc5058,77e543c3,429b090a,1d3cf0,d2df6248) -,S(89903a70,55dfcb5d,175acd28,f7161862,c9fe22dc,ab752d88,3f52801f,92ab1892,e89c4f9b,7954c2b8,cd3b4868,ae171331,871a2693,9355d88b,8d37d4f6,b90c143f) -,S(f9830f50,66b1b44a,89231a81,1192a284,9ac94ec4,13f5223d,51d1e75c,a7727884,18ac8170,58795d51,cb9a5c2c,c249bcfb,ff3fe3b9,1506b721,763c8fcd,7e2ae44c) -,S(326be8c8,55c9f742,19228eae,f7d79c48,b02c2e04,3bc28e9f,275d6754,31afa8e0,293647f8,76b00450,b223e715,5faefac5,990322bd,eef964c7,185acec7,7c105d06) -,S(6117b67e,bbd6b120,906da047,88ad7dde,3549bc5f,c4f80e04,9b216b00,d441dc9,7ebe5576,17dabcd9,f41aa34e,1443e12e,715c9a7,ccfa04f7,ec6a9a25,74c1e540) -,S(1fa858e8,aed841c0,902db240,aa0e4c80,f26927dd,94e0e404,7e8ecc25,216dafce,26566614,2111086b,caff0e12,e4b38940,ecf05a5b,58f3e705,d7011b49,413a52fc) -,S(dd77d202,96a15eda,eef79ced,9b59e77c,1483b936,6e9949ef,ba3298a0,efac4886,b1914a11,80cb154a,f791a934,8c89bb0,70f2ac9b,acc50c5,f75b425a,df6bf125) -,S(e5fdfb45,1e7ac947,ece4e8c0,5b87b9a9,2d49aae3,5ef95f5d,1d18bcad,18053337,841d054a,47b4998d,d3ad8dd3,d2a1ee68,406a195b,1975bd1a,d4194417,fdc4cad5) -,S(decd87d4,6fb74380,56a83258,bee67d9b,1a49e170,bb1b549a,a5c2a2bd,cbc050ef,5ccd1cd3,614fad6f,601a4ad6,e964ee69,a1e06e8a,2e29edbc,7d19562,a4aebc5a) -,S(1a94991b,939bf699,468c465b,5aa4b064,520222,c0ccfcff,193a8484,6f6e4b8e,31b1e6f5,30147e1d,ec0199ae,1830a36c,bcf4fce1,e1258441,3e89eed6,889b9d1) -,S(f32874f,d0f18d03,7f0ae5f2,ddba8f16,fe7ca4f0,d694e803,b9216c59,91bb456a,1dd8f5ed,f228a9d,53cf881e,a4e3c479,6017be43,e613ac30,690435b7,84a4056) -,S(1c5991ef,154b79dc,df2ceafb,3f7fd7b0,7ce7563a,9312ee6f,1dbe5960,f91ba569,497d2a93,28ddb18,221b0075,3432f510,bbf042a5,ebc44cf9,3090d064,4a252a7b) -,S(3c88095e,dce54996,3bf6e312,4dfc14ff,4ed4ecc9,d6240af1,6ecd5984,5f01de9a,499a17ee,e13c81b9,bb7b297,5e7ed1a1,231d9094,348d22fb,9254c520,a65be01c) -,S(c849c359,1c4fdb68,55971840,c0b78bd3,59d1de02,130adf7,e277cb4e,f6eb7748,6add7151,b2640b78,b8fcfdc,fee4310a,4c4c97c8,bb0cdc2e,3bbdf802,750a7920) -,S(f53017aa,a5f79e34,5a0cc318,f40115f2,52ba5401,614b9eb8,ac9245cb,3ca5680d,2d8b8c24,ad89361b,6d77bc72,fb0c7da8,ff129a5f,2bc00e26,e635483e,c4c44b1f) -,S(b3657e9f,84975313,640b7302,a288ef4d,2dbf36ca,651c0189,b39fc10c,87d7c4b0,d821329c,a2f18f94,7a71f5f7,51ac1b2c,e56aa432,992e7a3d,ef84e631,db61fa14) -,S(79942dcf,a834e013,77bb3eec,b7fa31a7,b4eabe7a,578c46d9,3a0dd17c,b3455f61,4c08fe53,c3afcbd1,7fa0a809,bd4ff7af,88713a3e,d7713f82,18c4d4d5,2a757ac4) -,S(e5f14474,619e3acf,905da5c2,3d1bc311,7f1d58ff,8c63ed2e,fe939a22,5fd9d9a8,d4d225b5,85b6b319,431939a6,8e2dafbf,8ed90a6e,5fb559c0,70779d67,7c03028c) -,S(bc5ca503,3ca4398d,5f3c6240,946c5d7,c9102996,e302b9bb,640aaeed,8c9b54d2,ac15cc8,51e59843,fbb2956f,55d39f24,200922bb,6cbf1e86,68ed3ecd,6fae2627) -,S(2f3abe56,d63a2afd,35e35d4f,9e964c61,a5483402,5fea8cfa,66ba9aed,f75947b2,7adeb38c,e14ebe73,8dceae8c,77903b24,3066aed9,bc4886c1,356449a8,27496d5b) -,S(704bf0b5,f564ccef,4d6e5f8b,eb2e90c2,4b46d581,93cc0a41,5bfee2fe,95021b75,44618d17,c54684e,ea1ffe1,53892090,b74201d8,ab3f9312,e7359ed6,5ca94c27) -,S(a898e473,d4b59956,2a905ede,afc78bcc,9f374c6a,f524fc37,86a91375,83d749dd,5452e556,7d72dab5,e085ab72,1168b5e9,c96a0fce,f9d5862b,9c5a0daf,3769395b) -,S(fc4f83da,817b1648,a8a1be3f,dbd0f309,db712225,2988ac8f,64774c29,e8d9d573,57876e31,6a0ea473,3e34f34c,b0df75b1,1194017b,258cc944,7ccded35,19edd00b) -,S(63e97e30,82c36634,d151f0a8,837956d6,16d5d4,64c66373,253bb94,ed5c8236,af68f06a,e045e5be,88242af4,2e314ecc,d719f76e,33092e6d,8b69f791,446c2acf) -,S(4c06073,5107e9fe,f27dfbfd,5df447c,16f1c911,8ec5cfc,8083a588,9dd82b23,8c8508d4,b86e9eac,2058a912,f2581ae7,fe81647e,e27075d4,fd01b051,fe0ab636) -,S(667f609,7b6af1f,cff58520,83175f85,ea01a1d3,c508b12d,a2e19281,c8d8e443,ff9fd0d7,4a0cb42f,3d7ff6d1,67e5a65f,23c34679,caf3f94,ed5d1073,af31607c) -,S(e01e169e,7fbb4365,58e07dce,8f8dead,e2ec2e27,7d18db95,ef8e9f85,ce800fd7,f49f594b,9d60c59d,155ea702,a1b5e3a7,b26aeec6,71b275e7,10d0139a,21041960) -,S(ed10fbe2,565f80a7,65fc90ef,224c7893,cf9df84d,aa0a3b2,9089f7f1,c014ca50,ffc44137,c3ac6fc6,fddc65d1,87d6b456,819ab1b2,df461ecf,899c70fc,59387031) -,S(4563833d,d0052218,5a43bfaf,7e55c2d2,62a12feb,b76254bb,e8310687,e917cc36,fac05d5c,c781d49e,9bab4cbe,384b511d,1c8c1fe4,f68cdc2c,8c576be0,1c669e63) -,S(bf5907b0,1d05136c,b0a1b514,73682fa1,68772a1b,9f5db994,3bdacb3a,1e8c47db,fc69b036,4559f5d3,f9e0c1a3,e4da38ac,b9968e9,17311288,69da2158,2e334cbd) -,S(be106d73,d01ce0fc,5555d4f2,379c906,1ea6ca18,ef8ef8fa,754ecf64,cfc27fd5,9c84f04,947687e,f7d641ba,ff89a11b,da9e9769,8f8ceefe,54e2a4ca,267956e) -,S(5bceda4,2e94ac3e,68f6a3e4,e4509872,4724e9fa,59ee0918,859884e2,2c98f15f,4b19d70b,e1471e3c,7907f797,7311f5e2,ba78c6f5,6f2ccaf1,cb6b684f,7d048934) -,S(e0831b14,fcb2d4f7,3d17b6c7,f6d16803,304cbb32,2bffcd6c,84bdb891,9d7cc9d7,b474a715,5520cd3f,65b64d08,b8e92ca2,4b2238b3,11d91db2,48720a6b,65444038) -,S(df818b88,2300aaf8,41cb3962,2f0c9166,468c1ad1,3aa284f5,89dc354f,bb1fe97f,40f571f9,f63fb358,231c204b,3b9707f0,c5cf11c6,d7ffb93c,991cf7f8,dcfb3895) -,S(d9fdd569,bfc89237,4bc56a1e,e56bab5a,cb5e0ce9,85939b85,c929fde5,82a07bcb,5c56b150,4cf3767e,e22e4b00,fa467b75,4c9ccec4,c1364216,d34ee210,aa5b56ce) -,S(11a93998,d031bc3e,d55e74c9,ab327945,cbace727,647bfcd7,5ed04a2e,4836ba,4aa311b0,6fc8fc86,b67e8eb2,1e75d997,189fa22b,a33e7e99,b07d610b,1c94655) -,S(7c4fc747,7319464e,2d71f787,80aeb385,aebb0420,d8f8588,9652d5de,aaad580d,31d6d7fc,2cae58f7,b3e4804e,f615d7e1,edf9d06c,d1035b30,ee9b55b,21b06eae) -,S(83704a5f,4ef8ca9e,a3d5b163,2bb3df98,acd774d6,4e07b219,b9a36a9,ce88e1b7,52976995,faeb6179,bde4c123,1437dc73,b53b6f90,f0cce08,1e3e1644,e1ebeb18) -,S(5de15f19,21258b5c,f12f240d,147bd38e,fd5e3c3d,dbf148c5,9e541c01,ca7d724c,c0e18562,1500f0,e3fbbdef,45550e16,5fc2a2a,adc72558,e49f1e3b,f5f4fb00) -,S(f5d1fb46,e3288419,1f2cc8e8,2ba81ba7,5bf1d7b5,97ff82ae,8731d27b,7f059938,3d5118fc,9acc8394,9e0bcba5,c7c79fec,2f0cad64,7910976b,e4e8f9ff,43d8baa0) -,S(8ebe619a,985f720b,9381a99c,db63d089,6a787dc9,7d007354,fa83b931,223f8596,7968b6fd,e3dcc13c,512aae25,d9a8127f,313e2d9c,34489606,864732b4,c3b5ca1f) -,S(5b14482d,f96cb0a0,5664bcdf,e4ff7b87,6169db9e,8107b0b5,78baba9e,b1f8fcdf,19a4ed84,cd2ab376,b1e0c2c9,ecded5cf,2e874f09,6d84d946,22be5806,9f8a5e82) -,S(ae810d52,7f94dad0,d140877e,ddc5e0e6,cb636325,f4c926a,1a263f1f,beb9a8b8,c94f0c8a,f5ceca8f,ea29dbe6,c8afa649,f813744d,39e303b,c1f0c135,867658f) -,S(38853d15,d74060fc,7eb2a56a,b8772f6,855aaf83,b731d853,b99fde93,e7c06e7b,ade73ce5,4f513c89,531b5bad,7f47ce7e,a498da85,e378639a,5ae0507e,1f27fa7d) -,S(837a1d99,db477c6c,da832700,37f111f6,eec5402,2bf74773,4c18bbab,35b503b4,ce852762,ed9b36cf,65602da,cfd3a250,c547a971,1977ba86,64f72cb3,89ac1f8c) -,S(3136acd5,a1460d8d,717e452b,a2069b88,4eb6fa81,756f8768,932c210e,df08173f,42ad61fb,edf97b53,f59ed7b6,afaeaadb,831134ef,73e33b1e,26b2816c,99fc330) -,S(a9609269,c3ef7f09,2a43e394,e482483c,119d94df,10bcce43,6691230b,b77d3201,8c580df7,9147069a,5c84abb,73e28b6b,ab9c7c0f,7803d6f1,d9fa86c8,f324be1f) -,S(3cb613e1,1ce19ea4,a8a90eda,cb182c09,5b1601c4,92822974,6ec22fda,be699e08,f05a18f5,aef9dfe6,87e69a9f,287fd868,4c975765,284f578,50294598,51538b05) -,S(b41c56a7,47232950,7777847e,178eaa67,ce61f561,21c7f21,2c525bd3,e7adc359,b0026b4b,6f9dc954,7efedd80,d914a3e9,65b17378,e6e0055e,527f6754,c5c589fb) -,S(f44724a1,3cdcf9fe,5b4a8f3a,f0d3e076,4559c14d,87eb8ea3,803a41da,9ee9dbf5,355b54b0,7ae7c477,9eaa314c,953340f2,f5583ae2,ba730339,acd231e5,c3d64627) -,S(6fceab96,d5851eea,b5db9caa,9a0ff7e7,86c2e097,5c2207d4,67f343e3,cb36ae1a,83f2b505,20094ad6,cb8443aa,69b8af96,b531341b,81cadc21,565d28e7,43bf2c47) -,S(2acc57ff,ff168361,9275273e,9a821fae,54947539,7f6b1936,13917af0,ef83cab5,764b04bc,9068fae5,75a202c1,f01f87,f3650358,3f5d3042,1e246020,9fdcb94e) -,S(2ac302a,28126e57,5e6aee8b,2b12ad19,f5e1c056,2d63d73e,80204b1d,1d4227d2,74494cb4,1e7828f6,9d2dd529,a70f2e52,9bf4b524,26a2a3c1,ab10a974,99624589) -,S(c5de085e,4dcf8dab,497a645,c7abd513,4054b225,32ce8405,f6e5134c,515d9de3,d1da7171,31a859a,a2c90816,386f0318,9759326a,6cef86f9,f3425bf2,390bed7c) -,S(54729254,5f78e410,db85d01a,182bc5ed,84bf6843,3b5784cc,852d3e70,acbfe90b,618b0f0a,7919751f,46c0ec61,1dddd798,cd89d4dd,32d1acac,31432308,d1a615ba) -,S(c6fc6b5d,84bd05b1,ec8b0ed8,fd4eceb9,dda38669,3859d90a,a0853c3,7f75e8a6,d3d8ffb4,988f7e47,2c26bd4b,83f95453,149d1534,bfafa97c,39a1e8d2,70c53582) -,S(1e325c1,ef4a976e,77d6e76e,f9a6dc51,175175bf,23e2c46d,7203d6bf,86ea05ca,60f35511,510aad52,e156e265,6e7ec137,c319b8c1,a1591258,590186ee,be4c1471) -,S(bbca6232,ed8c6093,7ad123f6,87af56db,28947e01,99340510,95850d38,6ac1d89c,d1257327,269836af,2793a1ea,21106bb7,ec95885f,de541f66,1a4a7c38,39c222a1) -,S(c55b1ec1,1f7aff98,710c3b80,34021aa1,83645a14,edfc6926,cd56eeb,f1e5332b,e541bc98,7ecd2b66,d10ce29c,572272ec,28c26b1b,1703919f,d0b28e76,4ffa87df) -,S(f026dc49,feb91051,68f76b0e,7abcb9a3,cc78a5c4,e520c2,57d2f688,5f1c49df,2471f06b,5dc74f9f,6cca7d72,86571c1b,54ab3813,d30bfb57,53274a4b,4257f5c5) -,S(3f721c3c,605169fe,dee4a4f2,b07865be,e1f0838c,669f7eb0,f234e700,f2fb16f5,9691b1cc,ead5fba9,9d9f1feb,fae6baa3,cc7717ab,c5a671f3,8def1556,e27e100) -,S(65bccdce,bb7e968c,a1c5dd12,2d5440b,97b07014,9838f4ae,95962044,b822b0ae,bd594952,f8424625,91375009,3cc6716f,cf7bae14,a6fbab35,4a962282,ee0b3fdb) -,S(6c155658,7020a902,c225d721,7b1a5f2c,5646179,df5613d9,b95826ff,7723f42f,1ee346cb,5841939e,42aa41ed,84bd24b,33075490,68de1809,8e5f8605,59e9c073) -,S(d2c9f745,8f75b42f,b48dea34,13b2bf9b,dc045542,8c5a3dd4,2a08716b,bfc4367,e2a9be5c,8f06a432,6f148cb3,cf58f767,cfc8f8ea,1ff4656e,ec19a64b,183f650e) -,S(aa11c12f,5fda607,aeb4af7f,8430cae,3f5df00a,43910ff9,e413b3a4,7295a38,e506e63c,a0568d96,2c489851,489fbb62,acb60d9a,fb9dcf1c,7aba7be2,2e02c67e) -,S(a355e383,43937932,21affe2f,843d2541,3faf807a,900bc299,5a201f10,d5748f99,22ce77fc,c627019a,ff0245d3,ef2b31fa,55687ea7,69a4948c,5656945c,c5a5c74) -,S(d8f4e393,8b93f252,da68e1b0,16fe8889,d837ea8e,61e5d3f6,8928bf32,22643cfc,c895006,61003ee5,3d8f739,d6fb7cea,e2f7b414,28a65ca1,bf493a3e,27a2e826) -,S(f69ff0ca,3aa0ee7,122a00a9,4b6ef41e,13945263,96e8c590,84ab2b37,6b899cfe,a5211104,271a3020,d65ca305,c0daa6ac,cbbdb1b1,d349a2ba,1abcfad9,bf63a7d5) -,S(64b1b59d,7415d433,7f5b9a3d,98f06d10,7e647525,b347011d,6d3b423b,2a377592,12ea2814,ac8e0bf,1da8e617,c8f051ad,5799593d,f9ffc1f8,abc963b0,faf202b9) -,S(bac6a7ef,9a3de971,51044204,ddc3a2d3,4668613e,101a7e6a,5f93c25a,6b20dca9,7bc2b764,57620478,321de1fd,8ae8afe9,6047d087,b95390c5,bc69b972,654b97cf) -,S(fddae798,dad79951,a4c3b803,11ced882,903c9dcb,4d4dacca,c4cadceb,b837f688,2e21e1f9,f45ded15,76829823,4892d2ca,26ad5b6d,7b0baa77,c2dfbba,b1dbca19) -,S(3dc783eb,40779120,25b7dfe8,f493f073,b3a8520c,ef0c94b2,1c3a5388,b0a9a01a,b3fd9020,2ca16d20,fbe8cee8,fb8bcbcc,821696c1,15545aae,84c414a0,c4401bb1) -,S(299a187d,299c61cb,6893a5d9,cc8831e3,df92ab13,da2f0048,555d1358,e55e866d,ef0b105e,52a18751,56080cc,cefde2b2,848d43ba,6d650068,2b71fb9d,d34b819c) -,S(b690b4aa,fde43b5b,362de597,100c74d8,97cbc750,688a46b4,cb1093e2,e253dc4b,affd5af2,30e4de4f,9971627e,dac86808,c97bfa30,f051af29,bf91e36f,c3edf0f7) -,S(7217384c,1596318c,2a98db2b,7264c909,f823de21,702f5e64,b19af937,cbb8be39,b125b7aa,1bd67232,df7d2d3a,a671bbc1,bace159f,3ba2fad5,e82a1ae3,965d5c01) -,S(4bb4a86a,58f1248a,11f61599,f420fc69,bc77b7c6,86d2838,f4368971,67013852,29909cb1,3bce655e,88300d78,4f7984de,352c9b9a,960148e,a5b65acd,99b62d4b) -,S(4b3a9328,2e473993,9d7722a,7de44fcd,51658eff,93c3711d,3a8f0193,9a54902f,9a012a8e,7df3b988,204fe0e0,50cc197f,a27618ca,d8d712cf,520c7be4,cf4e0f02) -,S(5488985b,26978af,50099d93,8d7b1aa,c545b07,44938190,e0b880c2,11782b26,b51f749a,76b998c0,83dcdbe7,21d5fa0b,c4aa4392,f81821ab,3436fbf0,37d37bd7) -,S(7f2ff4bc,f270b566,d2d26cbd,ffeb1b9b,31b2cd7,b647d89a,2c86c003,b23f644b,f48749b6,21ed28ae,47223281,fe8e633f,35580bf4,8eea29f,d6aae487,ee8e0588) -,S(3305c475,1d63baa8,18f5bdc0,b4e46c9,acdf1c42,9ff5d177,bdfc214a,b838efbc,491d45be,85ae9675,310ae85d,258c6c9c,8e28d7fc,5239363c,911eb12d,ee68a435) -,S(4195dd13,ae5ea569,179dc64,b07f66dd,4a2e2878,d81a222,304d6a88,4da60b86,bbdb99ff,8d4ce150,543b48ee,9109f127,5234c69e,52293758,d0171ae4,ecd49677) -,S(8dca7466,8ffbf319,7dd9826,cfc7f450,fed841ed,83e1d466,e92470ca,1e2582e0,2b19be5f,69fae0e2,563a3f80,2f9450e0,fc48ebe5,973f542c,4c12fbea,97627e57) -,S(e235d150,3449667e,ba23d119,9b5225db,1b26220f,60f84476,70c6bdaa,f5eb7aa9,3d4d8dd6,b0c8c2e0,c8f54f6b,dffe8dd0,5ae22d5a,b4f9dc18,f17acafb,3fab327) -,S(aa214fc7,23c3c458,8bbfd962,b86cc3b3,e1ed52a,25524ed3,ee5c4933,1748ddf3,9b54e29f,63240e30,434f7a22,2679006c,24593e26,90254978,35a60897,d3578e18) -,S(1c468a51,cc9d2632,860bffba,9ed83e5a,e97dc1d8,c8bc3577,5dfef223,b3ffcc73,fc569e94,8eb20528,98b4cea3,86486afa,cec0188e,44dc4e0,25b34855,f1466e87) -,S(c663e752,ce62dec0,81f8ad57,3e4f5c92,138e6a8b,e6c9d015,d5cd2cf0,ccd1a203,ffc249a7,554fb97,c0f9d96f,4cb06fb7,ce6e868c,e7e60b30,f67a2b9e,919f6f98) -,S(949a84d8,5f68f70,81f379e1,9d673748,bed14bb8,dba2458c,34327c03,c893067f,1b9fe41c,f474e57f,8497f6f6,76472a28,fba6b259,91297f81,474cb6fc,f31380f0) -,S(6a4bf3ea,5798c8ed,4b35c629,c6cfdc0e,d16d0d27,39f8bcb8,c34a9105,fa35fed,6f69e357,d5123305,56d04946,f9265353,77610fee,20667815,e7f3cb01,e8196b24) -,S(d0a99a37,d1df89c0,99b0dc1c,16f325b9,b2ec1455,21d4f80e,ad67da85,4f2a5357,7a75846d,eaf7c4e3,5c0c87f,83732eaa,7f6903f7,b721648a,87e1909b,53d3e9c) -,S(e2a45683,f3781309,b6223a7a,5ca64c4c,cbc5d45f,29c66082,912568ca,3ec6d3c0,8e386acb,63c52ed6,5aaacecb,fab458b9,9585951e,cd0e35a6,19c0fc39,5ce1c0ab) -,S(9527ae80,10ddd443,7237c2b3,c8f3afb9,f31e1696,5b10fedf,f150c296,3cb8e60,6e0843a,87833be4,f882c417,7198d985,5af8b144,11e78c3c,497fc49f,5f728479) -,S(15f15c4a,2cc43062,d4360a8d,dcf8e0f,52bc4741,c7924f6d,e1dd9f12,a06b9b2,66a127e7,2c55db1b,57050f4c,a0d8abf3,9ccb455d,9785a4f3,2ee67a42,3bfe5ccd) -,S(558648bd,64c52dd1,189912b2,67078e8b,d3c68952,47e6c848,d7dc529a,7a24a75b,12332187,62872867,5bc88378,88deadf9,3a8f2c5c,864371dc,6be0be63,44fad7ed) -,S(1e87928a,b6e10b59,6b231b08,87a823f1,3c6b3ff3,2852d35c,d1167244,fea2db0b,4cf60a4,767783a9,1c9747c5,7abbade1,3d7fc02f,e833b474,648038c3,b68d96f5) -,S(7a169de9,1d4c3f0,3296279,2c3ebfe7,f2eb4410,f7b9a34d,c402ae64,ce9231fb,1ca2e8be,7a7603b7,d95820ab,86487a04,c91ab3fc,c88e2f0b,514a1589,3908e463) -,S(65185a2f,bbc8c96f,cf9a6df4,d002128,afff1f2e,5c0182a2,95639a7d,9fecaafb,10b6902e,e83c5683,3d796b99,665cf365,c1e41d63,41fe72a4,72e5ea6e,39dbb9e9) -,S(61c45212,4664432e,8fbcd950,1dbbcd9f,1fb8842d,c8e61758,439b6d5d,bf8dd626,2a9c7c57,48509dca,ebfc5062,4d7a0b0c,21c9f5a,45733f8d,e0441bf7,f2b359c0) -,S(f61aff9e,267b6d91,e3d4ab45,73457987,b1af9a9,38b659f4,1ad5cf57,8cc59d62,51d0b694,e5692be0,6841a3eb,160474cc,6c248213,19c9648,c32ea444,29cb2553) -,S(29f27a51,8fd448cd,73aee0dd,7316e566,c655ca44,afc5daa3,ee359ae5,b96f8bef,d5957a97,a6447a8e,a8301219,5fd53c1b,63784a8,14c29c80,d0061fac,2c6cc1a7) -,S(c656d66a,efc3597a,2ee977ba,bdb7357,a2485a6c,d654c56c,bc58a0ad,598f202d,f8267b3f,f293a5b5,11f4e466,dce0fa88,a37f1603,a3a8092c,934fb824,1427a59f) -,S(f28477cb,efe654fb,ccd3a9ab,e816f950,3749e183,3b1faebd,418c85c9,112a5135,9df0f505,6ad98099,ac0dc723,34af973d,9c98c597,ee26e22f,a0a7a60a,a3b76cb7) -,S(d007a1a8,b6f05046,a66fe0f0,9a02e510,3ca7555a,277c40a8,87a71920,5a429e79,d9a68c51,f17fd51e,b19e4946,694e90f5,2cf664ed,d2d45489,5f880400,b410b8ce) -,S(348f74ca,7e5b1ff9,e6ccf3d9,90ff1f7a,4e3a8296,725075e0,33a85b2f,5ba0f338,1648c7f,32a206a4,e21e7309,f1a68a4b,b2ee116a,f3fab3f5,7455da93,7c4afc7a) -,S(1f54e125,7ff3dbcb,f1b55720,564f0c72,d322b8e1,f14d2b9c,1f6244d9,c85f6f70,34c23405,4a970b58,2cbbcdce,e67cc564,6e187cd9,b3024dfc,731a212c,c53c2861) -,S(a984f8be,33360b3f,a012cb99,65ed10e6,43a8df49,26f8188f,24719a7c,ad6b5238,79a592f9,15c925a0,98406d08,75ec4fa,90b5015c,4001addf,1cab32f7,9f06f213) -,S(2ca5e948,76db7877,fb828609,68e39c8e,a413a057,1a39e20e,a7b98f93,f4cc4887,b1ce7c2f,8380eaff,57299cef,e840c552,53629691,7ed367a3,5c59c3b4,ae67a02d) -,S(65bc7a84,15cdd07,5f493310,de05b7a4,ae7c874d,5b5221d4,7ee556ef,4c21a0d5,ad20620,aa39a14f,dfad58b7,9f1ad70d,2c637119,d9eb33b7,ca9abca1,f5dc3db3) -,S(a0b6b293,a9e25a97,18fa0db1,16362757,6e39cd43,83140822,b2241fa8,c432f276,2cbd88cf,29570778,8a6d79a3,b451833d,c596fa08,8b26c6a9,962880bc,48ae2b19) -,S(b4d308f5,74f7832f,4f402626,5ff81788,91a86724,9df74486,f241baf2,28e130a3,ca82dfe7,4c5768aa,46927fe,70c93227,cc7c30ed,c2fb6303,9a1552db,534019f9) -,S(819b48da,f19c48c1,f6efd0b7,c4ff5996,dcd5e99e,7146bde4,1c83e333,ac891b3e,c15bcf4,c9a630f4,e1489585,e5719746,ac55210e,c9b82da3,898a0d88,4eab0459) -,S(66528e21,adf8c447,526d616c,777dde1,fa7469ec,175facb8,3ac9ed2f,db773f85,c5d38c7,c13449ad,4f346498,1eb7abbc,a98de561,d94f46bc,edf3dd10,1839d91e) -,S(a26e3a0b,6f61c611,28c2afc9,15ddf48b,8d3d3901,df93a2b2,aeb82579,4822e605,41f4e806,787884ec,84716647,ed72f331,126f141,6837a232,e1612ac9,99c7d115) -,S(56623040,c198fbcb,9aa32066,90da22a5,a0496a82,5313a2fd,529fc9b,26647d22,35867158,42a4c950,e67b9033,23c55fe0,3ba3bf92,a9ecc5f8,39708869,7e2e1e98) -,S(acb401f1,b535f181,75ba9cc5,8e32514b,be8b6d19,1401248f,20500dba,23ad4f,f57fbfc7,9bb94ec0,eac7d09e,52b699e6,d8407335,e6dda706,f7d1bfe0,71e09f6a) -,S(9e02a873,fbbeddcf,b760d48e,6e29e6a0,b37cae8d,6348a8d5,bd651be0,59ecdb33,9f926735,cb2f46eb,71005600,56dea853,9fd6d140,2a57d05a,e884e8f1,1a293c39) -,S(3e88f76b,ec410c46,ca20cf7,2d90c66f,476fb966,c46f20b7,facb7f50,17f71617,bbbb4d9,a453277f,a7bb83d2,eb8b2950,3fe51b0,7d4b93fd,5e993663,9b78438b) -,S(cd39870c,a6484a9f,e6d30e47,3a6f5e8b,3ecc1702,e191b5de,3d4d6cbf,dade08e6,234240c2,8f2b2233,9369298e,f22cf32a,7663edb4,2524f02d,6879b4c9,f4ab442d) -,S(5de275c2,69799058,3348c4cf,8c039b44,daf431d2,b7b1f862,98ae24ea,271644c9,adcf9fc3,10ce2d93,8459db47,30273255,cc483342,3f6bd4dc,56593f06,6466b8a9) -,S(2d986200,bd9dbe51,eee40ec1,2730701c,621333db,9e71c232,1a6463e1,f26cb76b,57433deb,d9149b32,37315114,e9747758,228d17be,5f7c54d4,f552e730,1e094329) -,S(654868b7,39d6a72e,75223cac,d0f827d1,789c410c,fe0d5ab7,24cdbc2a,c9bcb269,3d8d4270,63cfe,6724f8d4,77ddbd10,b24899a,3ab0a33d,87683646,9f4806ba) -,S(d97cf5c8,e1a40197,75312099,fb1a2d62,2b3354d0,e524cbe7,bbd3187,506f909d,53c8784c,cfc900a2,f159e98b,76481239,3d883d70,8a953905,44691b5,1c8c97d4) -,S(697707cc,9c74c828,7396d53b,9e5d436b,24b861d0,2fcd9208,dcdcfb54,8ad2d903,bd203dfe,7f4a3484,1f5ec966,f063d251,a89b7da5,468bb2f7,32775a1f,3a62412f) -,S(36b4329f,fbbbd80b,e8eecd1,358c05f3,6616b456,588571da,c23d7752,edf15d65,7c42145,d8774827,a0cbe9e,b9ca7b90,2353c6f6,118291ad,950dfee6,124fef3f) -,S(dad2b02d,a182ef28,5b00b0e3,2af77064,ca6b3c1,41766194,7fae0663,4861e144,ece34dc3,704d0561,f6029366,aa45f192,a2b55b1a,1786e8a2,d84b2361,eb2c2af1) -,S(4cdf386a,c0e7cbc6,e19c5f85,1edb009a,59b0526,f3f4d0ca,3c82f280,dd33531,3f8b3eda,4ae484e0,95916efb,ecf1ed3a,27bcb034,6cbae87c,6a388488,331ddc86) -,S(d4b65a7a,eb74d38f,2a8e9383,2ad27a7,2e2a89f2,2ccb5c24,9e4e55d4,da7a0cf1,a080a32c,ac9e0ee2,6e6538a0,233f2374,3428b2ad,821852fa,bbad2a23,63a7d7e3) -,S(c41cd230,d99c5f66,7d7ea000,53945fed,70a2a807,4893d488,5be2ee46,cadff9bf,4a7faa2,3ea4ab42,5f21e12d,dea7530d,429c64fb,c05e1b24,adc24f55,c34af43) -,S(4c67ce59,9a841ecf,ec147a89,c120619a,227100ab,c5dd0ba8,da6d362,6f687824,aec0ecc4,b65694f,150da4f8,fd514d37,52f4c6d1,aebd8b5c,19846ea3,bf4b13b2) -,S(e765b00d,a067b5cf,a40bf02,dc8ed6bd,4e59b470,ed6eebad,c02b49eb,1d20c37,23e0df00,9ca95773,a91c0805,40b024b8,34c0d7de,4dfd6c43,76c979fd,2665f21d) -,S(18a8cbe4,d7585fe2,3b958cab,a9303d9,505928a5,7ca1058,21a9f192,ea52298c,9d00506,4a1f3406,c3864d73,2ebf3e1d,b6f20234,d0f5a99c,3623ed9d,530d71cc) -,S(2dc043ea,a53c27b6,50e2f1c,b6fb7fd8,26c4fccb,9572bbf5,103356bf,87b3d649,2695f192,af96b031,a41b72e7,a61593cc,30672c07,cedb0908,35ee207a,5cf18271) -,S(71699cbd,e1efa1f2,914bd0ac,9b28111,8053f7ec,d51e79c0,44daa4ac,ded9c9e9,8519592f,a3b05922,86797110,b222231c,fef973bc,d51ea4c4,34998999,63637c05) -,S(23f4668e,40761e37,235dc0cd,41b6c7ff,1951678f,131763b8,7d394e12,6be4c370,1cce4181,2279761d,8753dfaf,8bdd206c,e4cbfc5f,ccfa8826,9d2d4327,431fa689) -,S(92366959,9a173d3e,826233c7,8062863c,2a92b525,106c1159,4885058e,4a7797a6,d1c9f57c,d03c0042,38f898bd,cb45c064,a1f2cc56,222bbc03,a61997fc,877b23d4) -,S(a2dd03bb,a75a7bb2,fc9915df,c66c0b22,76a7347e,6cca3d32,e5727cb8,b54bfb70,9ba4266d,b9c66907,b25c41bd,b96f8a94,a9559830,f171a878,66372067,51c7126e) -,S(79174d3e,2379484a,d3191db7,26073dff,d69a31c8,94314f7b,282ed68e,71395ad7,1cada148,7ded181b,f1a9cd30,21afb04f,4402a171,3a570d7e,9f4928c1,2069315) -,S(874597e3,80449235,af5c10e3,7af7eeb8,f755ebe0,6784d5e3,ba0d1021,fcd3b12c,2ebbde83,58c4f2ed,cc89bd52,e6cd61df,a251bcf5,713858d3,d247750e,266a6129) -,S(f23c1888,c22a764,c85c6328,387e9126,f4ad772c,fa0a6034,914d5f60,7efcddc1,6cd5bdba,cb3c6cd7,4c2c5cf8,1c62e774,560211ac,f1ee8096,be9eee5e,b716881e) -,S(a4c2054c,3a834498,6dcca592,db5fbe06,7f80d32f,8c492436,79c57b76,ae13b96,7ca515b7,8a3d5590,6100ecda,f7066459,db9db34,3bec1b4c,6a57626e,1f560444) -,S(d6880dbf,50d3faa9,835404e5,d723eec8,b1bae88e,b8ca22bb,a85fda5b,6a8cb669,a08c4200,718edd4e,42b775b1,1beb9a6f,eb3bb93,b54c57af,5218eeb9,7aa9fa09) -,S(2dfcf2b0,babd3990,c305cdbf,cae7795b,a2fb3cb6,3ea0cd17,787122ab,5af86bb8,e0e921a,15882601,c151fd93,d7b7c607,cf033633,e6498004,d29cbf76,7fb19f6d) -,S(d1dc82f9,aae7e02e,177680f1,e5d73ae,8a178207,7b5ebddf,45b56bac,fa1f11b1,4c9294c,e3ad0fa0,ceefde5f,fd80905f,ce57a5c7,c6807da4,186c9b4a,7c9d6237) -,S(ff111200,4231109b,d131e7e0,f6434461,ff699d8c,6be3e6bb,7eb9e827,9af4a4b3,2c30b8db,bbe56de5,3d8b3307,9dd741ca,8c7aa596,78a3c75b,a781a77a,e470620e) -,S(9fc4e1ac,28a8f268,c66aec12,f5e795d,f3dc23d5,c515c5ec,11c394c5,e6f2a11b,188bc037,ab114fd6,508627db,12317d0d,fa194cd1,bfd56c1a,4ba25d07,206aaaa9) -,S(bdb0b373,5bcad639,386579e2,aa78fc40,ec2f4700,4b3174b0,1bc2cfdf,f4164f95,45d65b9f,eb1f60f3,29195060,78d5c016,8c6b1820,6afcab34,a2623e1,d2bc70a9) -,S(1386e11f,3950b8d9,e87589da,c3dc9a47,bf36b0c7,8378d2fb,253e5bdf,9f704465,415f50f4,f048413c,7eec4c2d,122a4f7d,f4908265,31f9dec2,313bc7b,b1b2402e) -,S(be246169,75b321a2,edd491be,90b7a11d,75a36c12,ca782d20,732a285c,5a6a1572,ca9109cd,5b041864,5026977,9490edc9,d239778c,25609736,7b52d82d,97f588cc) -,S(baa5965a,c352a017,80b1359,3945030b,32c83b60,805bff01,476ece26,cf89384,c83a9515,dee6663b,b5688d5b,483f0a2e,51c8180e,a130e0ea,48f7a4f0,1d3d06e6) -,S(17dfb33b,957bd5d3,36c918f2,cd1fdc95,23e2980f,20a7666d,bd5e8a7f,8ab1f83e,32ffdb3,db6dfa31,ca67a5b0,27a648be,b978b6cb,7ace4241,a0b6a7d8,ceedda20) -,S(ec5dce25,af07a01d,9dc43a9,e92dfb51,29146307,cef69b48,cb7b6e85,d9cbd91f,1018c449,949bb2cc,e185a9,4a9a06b6,bca4c8b0,1a3079b5,3f86d830,21d46de) -,S(a56b5b4e,d4e4e3a6,29701889,2cf21f67,868ebf37,b8696ebc,83afd980,b5c63817,1cea139e,521c70e3,f0a4b02c,c20345df,90a579b1,20ea5dce,bc1385bd,162adfd7) -,S(2ff27783,681d264b,540df574,b478e3a6,2b919e0a,c4ab1b66,3e279083,25a707b7,3a477dcf,65b233e1,34ddae74,7fa5971c,cc0498e7,be9f17cd,5e34bb0b,480d360) -,S(aea30054,dcc9f7eb,c9dbbd45,cbcea779,49780d59,11edcc19,937e6352,a726b3c0,7ba5e2d8,9f681e00,bb74a353,f37c36c0,7264acc,d6a31529,cd5275ee,94a631fc) -,S(78531772,142432df,81802ec2,84884682,5ae2bc93,aed1fa8b,e345c106,7e23d059,6b8d514c,a0a13c1c,6425e5ad,f808aeff,f88fc6be,dbdfc788,1d174868,efd21063) -,S(c104c683,8448cda2,c94b0303,7b5ddcca,d4db1d7e,e744e70f,5f9275b3,244b8405,ac9e6545,3722e2c9,d7d97aa,767c3235,2a213391,aa2e327d,3884ecd,93f4b133) -,S(d4b02b47,3f851a30,604356c0,e9310d4d,7bd0f9a1,17db0c90,54862b58,969887c5,d451896a,5eba571d,4e55d26,9c3c8082,55c5cf18,f1f2d033,b8d30788,224a68f2) -,S(93d2f6a3,e97e4aa4,10fb6006,f3853f85,65bd14d,aec87192,e61b8f97,93f29b32,a0a840bd,336034f1,a98a0239,c6ab3ecb,eadd69c2,51b2e03c,339dd4bd,7a407308) -,S(7d7d7357,467e23a1,2022788b,2ada9a69,1243fbae,486cc61b,56458e2e,781f8f3b,59d5566d,97bb583b,940de406,44e19530,b1bc7ced,2a00c50,f4bbef30,d899e7e6) -,S(ea80f7b5,8c72080f,f2d83604,ccf6e4d3,28a71914,abf94888,8dc87c42,15fd4a6b,ecc6e626,f01f73b2,5d7e92e0,d1220b82,8f2f8ef3,3cc92111,3d15bfab,179ad8ef) -,S(c74366e7,26949fa0,6913e6ab,c41cb17e,c3837659,253c3038,30d543f6,ac0e4aa6,671ed272,2626ab33,14b6b1d8,1cda24d2,9fc132f9,51f97b95,8e72bc0b,9eb42d3) -,S(6170ed4d,c3dc2218,2b45c1c6,fcee9fc1,3897ac17,fc32fb25,aaf2880f,4cbd11bd,cb40f34e,7e8faa89,71338834,21cb247a,4c938f3e,f6a97cd3,1711f803,c872621) -,S(7dacf9ad,5775fa62,f99e093,5e948526,b94ef22e,912ae95d,8dd4e5ba,744a2ebd,69931690,6c73045,d8530a39,d33a8e21,d5912969,9f7b721c,1dd0c616,725d5778) -,S(b1d113f2,ad7b487,908767a0,b6faa413,6a8b3dad,41dad9d2,b6e8e7c,9f294639,7c802cbf,4596903a,90b1de93,649bff3a,6f63ab85,a9e3529a,7d907b41,7f973b61) -,S(d09d8d8a,17a1b113,aaafc270,db36ed63,4342d90c,64b6ae97,9733391d,eb67f3a4,c48701eb,738c3edc,a4f78313,a56660f5,3da8ebaa,3cd8d469,d1dd5910,c618851f) -,S(c264ffb3,c223e60f,fa34faf9,feb18668,4b05b7e0,6770db1f,9561ed5a,ea0bfef7,e4df501e,ebb4cdce,bbe6c4cc,b966de77,18ac5479,3e403e79,389ac330,92928e6e) -,S(55505edd,605e4299,afb5a69d,81f6df34,c7c2133e,dbc7bb10,ebc49187,857d7c49,ddc19610,7c3bee6d,ad955e1f,76afb31e,93a88e4b,de8aee59,aba50864,c295a487) -,S(9d61801b,a07c358c,f9942bd,d3614d3f,74904b8f,8f8aa8e6,a957eadf,79fe99ef,7d9d5980,2fb5dacd,93ec6c6a,92ef86bb,6079076f,7d964d31,70e3ad3b,7bb854a5) -,S(f1a6cc66,3dbf46da,e1ca98af,610f09e5,e9251a44,f6b9915c,b68c58f7,9038645d,e41bc6cd,747c0390,6d29e29c,4cbc2dec,6817114e,daedf220,b7fce48e,7e6f42ee) -,S(df247558,50b523d6,de15c3ec,38537a3c,af9a90fa,2c0e8b25,35696289,10517a79,bb567ba,e42e9899,85fc478a,4303188c,2da741fe,bbd1742c,818ec1c,e64818a5) -,S(4dc30b60,b174bb78,1f339277,ce3996f7,fe102e13,d80873b1,1a9e6b4d,54247cef,b13e5069,a7344a99,4f9cd284,1d9291a6,50e1d969,dd3061dd,ef34f037,7c85e20f) -,S(e77aac3e,946f7715,b9d0999b,1f3aadfe,de9c31dc,f8eab336,c5bcaa51,f16f64a,9d78c14d,90cb37a3,835d23,fd8d5a37,2b8fa160,1274e5f0,2bae50f1,587a11bd) -,S(24f29bd3,51e62864,3a7d2fa,6c47ab78,a6d0c6f2,c73bdf00,864e8bd0,c3f038d7,4a34c7f0,22e43220,f6d30d59,3d3ccb54,dbbcc50b,4b845712,e72636da,d0cecff3) -,S(ad4b9b47,b9cac9f8,a5f3728c,ec610000,163ac2ec,6a18cc34,b630134d,9fcc9364,afc8726e,e0f988f0,53247177,1efb25ae,e07b70ba,ec7c425c,50e3eae,2898c077) -,S(1d38128d,ce7ede1b,265a4f8c,4e6b911c,d0e28087,87244a60,dd9f646e,2932e509,857a6c8,e4f43cfe,129e11bb,462101d7,9c76e99e,c7b4aed4,efc029be,b1b9c1c5) -,S(c171b7a2,7badcf84,c3c61afd,7568d23,5a14f0f4,fec777b,4a91c92c,61358677,cde264a0,48d2cd4c,d53d7371,8546802f,1ab67815,d6ebb3cf,b6415f4d,5cf4057e) -,S(d50f20d6,f4781aeb,eeca2a8e,85e8b75c,187c6d34,a940266,daa16876,96acef4d,9aa99671,35a1dae1,af29ed05,9fa15eb2,a4aaca27,99d98c64,5ae0ed03,7f08f37a) -,S(6b83cb07,7bfd33d,181fc835,63eabdd3,a50be6d4,abb64a16,e338f18c,c098a977,3e04e660,cfe61fd8,1ec67b2,d20ca9fb,f9c6e038,71f7c838,b261ade0,51b564e9) -,S(2e75abad,dc0501f3,afa90484,e85972b2,679d1d04,62d6d206,42c73830,15213b19,4754077d,a6868edb,a0943397,3c60a581,88a55ced,dee38351,93ce045a,e93517de) -,S(8a322085,d749f63a,38dcfbba,624d0c87,b9bcb66c,e4e3d84a,e97f7781,a0e9a164,3b592b8f,9d8cc10b,58fbdc7e,982e3fa6,7aa67c90,e9ca884a,e1f57291,6d7e2076) -,S(b890b7f9,ba1f1945,2a7bf1bf,944f9949,36bb4ad,5e2e0fb8,15ddc1e,2f30d72b,c1b652c4,f8e9d91c,8a92f76e,f6f72ed3,3357b35a,5ac00d63,a039df78,eb778a46) -,S(cdf33d41,c54c8a0e,dd3a0b1a,12290d13,715de82b,21af5306,a1197444,acfdd5c9,2d7b78f,31d08fc8,afdb3940,ef1afaf7,3bf37029,1e1be3c9,5acdc673,ee2150d) -,S(20b24e10,c0f85631,fb891ae5,c0b0b36e,5a3829df,a5018c1d,8b59fe87,b051b55d,b5b9204,67394039,df0a34f1,308b086a,454c7957,40d31fd8,960f6ab8,33998c41) -,S(61976c23,257b9adc,48147038,ff5ace08,39d88274,9810bc9,25590555,b0e1c709,2b31a4c2,a712edd6,6b2da3f,84447c73,f2e3f652,d22b81d,d37ac4a9,def5390f) -,S(4ff22758,a2a25681,d28fbf09,e4cea5f4,74c00681,d9b4fe6d,ef3227e3,6092b52e,4b0f517a,4e56697b,37341ab0,6fbc92e2,4ae3d03d,392c33d2,377f7432,10a89fdc) -,S(46145b19,639938dd,9c6c84eb,d4180cf9,752cf9fe,a77ca609,5ffc8f7e,ead61f35,5b7b55dd,8a5e7d00,a3b62d20,2f371d42,8eeacc9e,7556547d,f2396c85,9503f6f8) -,S(32464689,a5d7626c,fd02b5fc,da68a8f8,dec32eba,887b523c,4b4e379b,c40bee7,6e9cb8c5,3fb716c0,b583b356,7ba6890d,2cdccd39,646a49c8,132ef061,d89f6710) -,S(56438894,2c9aa575,efbaec77,cbecd9fe,79fb4461,c61ac051,195ae384,dc0d6ddb,663528a4,29696073,f9d47d2c,bb2c256,9bf6c452,c171ca43,7cd3480f,95b69a05) -,S(f04fa37b,9c510bea,ec12fd4a,307b1b0e,d934fa1c,78cbfbe3,bf904b00,91491e4e,19b7da4d,826a314f,586c4c78,457a3075,76f3ada4,61af5bb6,c374178c,23a79326) -,S(36fe4596,b1ca6409,741f7a0c,b899f89f,a727207e,eedc8e57,504847d,2cb304cd,78f11f,4473b124,5772a101,564b6468,43d4bf76,afacf02c,bc45ab39,c7221e19) -,S(ce3e6d1b,f2deae03,8ea4333b,ebfa026,d1954ffd,f50df66,e2899b05,1ee87b0d,4cd4635f,10af69c7,50e96ede,e4f38591,2a14b104,ed9023af,60ac6e93,a9b9bcb0) -,S(33ad3a7f,a6008875,74bd735c,b2ec5dff,10ffc5dc,3163d8d1,62644086,888d29,8c959ba3,2f7b8ed0,4cb2bf2f,2b5e5f56,b29a851c,8d1f6bff,b48fab31,5335b3e0) -,S(7101a2b2,36aa7903,6348006e,cb8f81f6,b481ed8d,8a3081aa,40ed475f,13fde43d,d0a93654,51471aca,80a05745,57b4a24,9d627dd5,c1428ed5,79feac02,5fd2cd2e) -,S(ba3b4042,9c0bb526,c31cf602,3f9abe17,69974344,5e66566c,851501a5,d125471f,7db3e93b,e9944c42,b1654407,6d5bc6a0,99806c67,6cc7415a,9d110661,f4c644e6) -,S(57c6a582,1da61528,dc291aec,3a9f1a86,229594a2,27767583,5687ee91,15acd72,a9e4750b,5580b225,7768ce7a,b2909466,589a1a12,2e54a7af,35f44de,44cd5dce) -,S(c8353ee5,847efb7a,ec03d949,633132b3,9ad898e8,9a367c77,7b4a2ece,c47a7c10,dfce02ff,71060be,5e12d377,524c798e,97bafd6,e9aa9e10,27c07a8d,6f7d3a55) -,S(b0f6ef67,78b4ee99,6d7807ca,9f1f6f44,203eed8e,62584c6d,666e3698,e41c0eb1,b92763af,c9ea095,f757e921,ac0bdb02,605eb66e,d3e1735f,f8f17e63,dee5460e) -,S(f2e4015e,62645bd4,6f858b25,cb636f97,6ccfe5f8,da065b65,1ec170c,ecf5c411,8c05cf9b,19459597,7c1d1b6,4ff6e902,5d78a175,6416e0a,ebf33c21,7b3d5dda) -,S(ffcde722,ad4a2223,24396b52,5a95a233,31dab41d,95a4e19c,1a23c2e3,db7460f9,f7282903,525ac2ed,3f9db21a,92d3fe4e,b1635a8c,77dcbf8b,e671146c,8eca8115) -,S(81dc05b5,2d9a210c,4904bbde,cfb4eacd,8b3f08f1,d667e9f0,a27345a9,7d37b37a,747aad1d,bd0003a6,d89f9d9c,fc00977,719d24a5,b8ebb807,98d1b644,87105f5e) -,S(5b92318d,a267772d,94656087,8d698aaa,7d2c721b,28dfbc20,9e4a3e8d,1b0eef1c,b2d274ec,7aade417,4f2f8766,1b5018bb,47c83d32,b2fed50c,437348a7,93041906) -,S(3eabd0fd,6b5bc51b,c187c943,511c3005,8f86e474,8547fcd6,49595070,26fb805c,95e8bbe,8187398f,fa4ea4cb,b50bae2,19f8cc5a,5f09503b,3edd115f,729b2101) -,S(a64d3807,f92b91e0,717c310,ec799908,43e3a394,a5ece3c8,7c3bb209,8d3123ae,50fbacf8,be11f6b0,ea0e36b3,5c46bdb0,8fb79064,59b52901,9af59b1c,e80ad239) -,S(db9ce153,7cd47f3f,4b08858a,d429c975,9ce6738c,2e6d56f0,fca12e70,777b83a1,a91b2016,9fb1e2f,fd52192d,7030d86f,66358516,5ba32829,6c9aac95,192afbf6) -,S(bea03f49,76ee0a86,e00bfddc,79e52173,1baef841,d751ee47,9a46cfe7,89de2399,feec1fb0,3901a923,862054e6,7024ba7f,4c485c70,2ff22aa4,1620e857,6dcc863) -,S(cda308eb,6975d59,db439e23,32505d29,4ebdca67,5373ed79,25b52a6e,f60a33c9,7d2053c5,414c9bcc,5155f17a,6fc206d8,81cc882,54341778,1c5db51f,3ce4c224) -,S(430bfb3a,802988b3,a68d5595,c989cbe,75d409d2,68dd84b9,a1d4a5b9,42360174,3de4c6e1,3c87338c,8bef6195,6559335e,bec503fa,2025529b,b015cac6,6d8060fc) -,S(b4b1b7c9,932be243,6b06b2c1,e5de312e,4a409498,11a226d8,5bb30c5e,1487c36d,e169a70c,b95988dd,fe1a98df,527fc172,61cc3103,88d41ed3,4bff23bb,31da4dc0) -,S(7a954055,d2d6acda,8dbe81e7,46310113,e26af09b,91cd59dc,92a479c6,d6079ef4,83c6d3ff,4582eea7,becaf8bd,422c0558,a2bc8d6f,cb615c59,7c46982,47cabcb3) -,S(aedd36fa,91a7f95f,2b2f32c9,1be77860,75783bcf,8fcb20b5,f20ca664,dd89474b,c747f32a,174ec6a7,936f13a4,7e80a2e9,324b7f5,e163b396,218c4c35,9391e565) -,S(41052d48,54402d09,a813492a,2f9362ee,9799ffa,3d270200,45a0ae07,9f913f60,97cbdcf9,b60518c9,74ddd987,386d60d1,3d10defc,8fe64511,843d5bf7,13774178) -,S(886e5afb,69f6debc,c1c5be6f,b636eea8,7314ff1f,975cd96,9070e376,c1a9973c,6a8ec4b7,98fec5e,b4a8d645,c7b72663,d6bf4aff,8f4f4b36,c064bf3b,f6e7b5ef) -,S(c93adec2,ddf85ba8,d9147c91,82ee4fbb,5727081e,a6938c0,a4bcfbfe,6856dee8,9ebef5d,2b2253e9,4474331d,b52739c1,71214093,aeab11e4,e51a2be4,e201dfb1) -,S(d97166fa,94a4e51b,ad21e1d9,76e01011,655ce24f,5f5afdb8,feda67bf,8ae65a83,815ac894,57f83bf9,5579fed2,ea470ad2,ac1c83f8,546ef3f8,bc383701,1bc62a48) -,S(c23cf94f,c5a93aa1,719ea8d4,4f426fd3,d48220cc,10ea558e,e4680c1a,dc91b18a,64a4dd89,8f36efa6,efce9354,fa30f506,be3766f3,a31839e,1fba56b,5a07ebd3) -,S(7236b1df,88751e98,2689e049,c5084b71,b8d7979c,2c412a3c,995e61c7,2440929a,67155955,bf5d1916,9e36636e,ba56fe44,f7cef6d1,b0afd3c2,beb59b26,5e3b67a6) -,S(d1890a85,df4f7933,ff72fad6,5b95f5c,c9fd8683,3c1bd2fd,56a3b7c3,e90428d,8b4896ad,4b4469d8,af074eba,ac38563a,ca68888c,5411ce0e,b3701ced,75d4f87e) -,S(41ae85b1,9fcaf4a6,13901d2,3cd2376,62f299c9,7cb306ee,8ffc13fc,75d54e15,20d99cc3,215f0b1c,20922ffc,6e111b53,e88ffb39,bb6e118c,61b9e3ee,fa7d01f1) -,S(d125489c,4e07c44f,35d39008,e4e29c43,c28ca505,3e370570,a7bd34c7,57e673f5,d142e19e,825ff93e,b6661160,b60d4e06,b4393388,43500b29,2d4d62a9,28db2bd2) -,S(8c50b3d3,667b2aa1,a60c425d,1128d389,f2786b3d,656ee126,dd57af96,ebaad9e4,55eb7ca1,c2bb5881,7f82cfc,c8b5ca35,5c2aec5c,68dd479d,948261ee,d342fce1) -,S(3e77a3c8,a2e995b7,582f502f,9bb1230b,35311af4,dc8d0744,9211a13b,444fd42,99c427f5,8365ca18,75272508,7dc57985,d59d72ed,aedfd5f9,d61517c6,1fb8679d) -,S(73ffde64,80547448,658ae5a8,529755d7,2ad7ec84,5711f0b3,20acc53e,a15ab609,786de118,c6a0daee,48f3f585,d10b9f2c,b4947661,b844ed51,59903ce5,f2cc8d18) -,S(8f2ec78b,47c61a39,c2ed1110,902b3a43,4fc9ddfc,b11b1ed,75c675be,5b8a172c,441686b5,c1327f0f,d2bee35c,5d8f2aef,b6da72ac,e6206982,6d6812a0,5b937346) -,S(c36c0376,d360f87d,28069511,7eddf1fc,75ae7118,5fd5a82b,b47d8fcf,519ae4d4,44c31c56,cda1c2d4,41161ab7,45f3c0,25c4ada3,72396658,cca23f93,bdb6a303) -,S(1ff06490,3cc7e686,d408909,4812a7d8,531c4188,ab8aaf4f,f10bcc5a,9cac352c,87af78d5,3122ad89,9a6a1297,fcc87c1f,252bbf9c,d8cfbf57,f64cb6ad,fe77f3a8) -,S(1265a4c0,6e1f1a6,126a9e37,a6e4f90b,290fe449,49b82bca,8ea73759,451e0b25,4f0f7a6c,9bc7f00c,42b90d95,95871176,d723941e,38335581,8f7aacdd,f830d15d) -,S(2595358e,4d45d362,5fa1c89d,a3249cc5,a26ec3d1,e554a863,51b79fc3,4eeea90c,d9b8d147,e4e00450,1baeeb5a,8440235a,88913063,bb1ffa78,9402c3f7,2c603899) -,S(3f432621,7a5f415c,b028f338,40fc226e,5906a09b,d054eb55,45609fee,90135082,a572303a,131fb0f9,c63d88e6,3520ef2e,77bcfea5,1031fa60,fada909,a610c830) -,S(9ee85c9b,4cb0102a,6b21c517,947d798c,c26dd853,7bb5d6c0,46a50144,f3297f45,85b798ab,c2e4fcdd,bf3e17b0,49e2a495,6239ba16,9917ed08,ebe109e0,4ac8016d) -,S(479c2ec0,28e8c83f,d7946f43,8d802ed3,d728179,55d94c55,bdef5050,67774934,c262229e,23eacd99,f9d3fb37,b7b9040,47cdd5a6,6872f4ac,800dbb3,d87fc3fd) -,S(2a52f4d,821cf4ae,758ed477,6cdc3bc9,2d3924fd,97a12f1f,4dd5a646,24766b4b,28500754,6ca8f142,6f3a4a6f,6ccf8437,37c6a917,7ab59b92,728f588,f11509aa) -,S(d89159a6,d5447ab1,bd03d44a,a8db3410,c86305b4,4f06b25,b88c4244,5ab1e929,c539ee3a,e7dec645,810c4a02,e1777977,d98ddba2,281d5701,2ed2a4c5,85057013) -,S(c91267af,4c303e07,ad82c1e6,2ddd45d7,cfae00a8,d27a34f1,eea8d15c,1add920,975967db,347415ae,24b427a1,b8f7229f,8db0758a,7ea13f7c,582c260,c0711b85) -,S(c860be31,18ce92b0,39b27a50,960d3caf,88e24bae,6e45fd8c,5a253a78,e3d0e6cb,15b8374,922f44f3,adaa213d,5e3facdc,9de1ff6,4da677d3,d89f6e0a,a800413f) -,S(eb8b5f4,2fa90313,b3dd7d4b,d47338e2,9861e52c,b492e9dd,6a1897ec,4da14c14,9d1c4d0d,56c570b,8835e188,517fe7db,490aa6b2,bfbe1564,579e7af9,c0647bf) -,S(151e39fd,d5961da7,44ac5871,94081a88,666d3dda,6507404b,607d449f,1b3c005f,476bca6d,6bfc5e2b,2c183794,563d35ac,aa8d38bd,ec3846b0,22831bda,38fa28fe) -,S(b46d2d52,b764f922,7ead0399,c391a9db,1737c9ab,35394951,5a57c76c,c3c05c59,8aeb78db,db1e52bb,a8030a3f,b9f57f6,644332be,6d0ad41c,34b7fbd3,13c6eccf) -,S(a89e77d,30c66dba,a27a2dfd,5af0684f,f6ccc84e,49b8d98,f402a88b,20e5bf7,af45b2da,cffcc49d,4f6db574,29f13971,c74f5321,4dd4af49,2bc7ae5f,10abe1ec) -,S(8d774c5b,eaa0cc57,7479873f,9bf5ff6c,808afa4c,6fa6f2be,88b53841,4cd088c5,6b9461a6,600ae1ac,4e617149,73fa8b48,74dd7cc,9f331eb6,e15bfcc3,2e26eb63) -,S(34ecc029,105f5e19,d6c2471e,eae5b671,cd55f2c1,bfba7dc8,46787c92,ba7de2a3,13e3cd9a,db98a6b2,433dba08,ec7d40c9,c2467878,f6f4bcd0,ce60397,67aca327) -,S(41b10298,6889f83e,e89d4f8,fa50898b,c9bbf650,2d153c36,85064c9b,f3dc3c43,559f5bf4,fb827bc,dd068d3,cdb14d6c,ace08a47,c30e3fc7,8972ceb8,9f88c21f) -,S(4a77505,79ae33e4,55228533,b8856da2,b14f70a8,d13ac2f4,f6bdc5eb,4f5c9aba,d365922e,3a487635,3ee1b02b,511c7926,e5c5edfd,aac153e2,686ce4df,b623ed2f) -,S(173af9bc,efacadf6,c107748f,278adc1b,d42174e6,8fe06d9d,f84fe278,70eda280,7b120d62,2463b94a,57303cfb,2c477f95,49d41a66,d6ee7c2a,4c652284,b8535faa) -,S(f0fa5cfd,ba53a5ba,df707983,134c3459,5ba232b5,7fb67a94,5c5c0f25,a0539be9,ccbc91a9,c0a2efd2,3bffec87,cadd16dd,f4292aef,a59b3d31,6e9c7082,742edb6d) -,S(a5df803f,751c4846,10799c60,db405439,9b1d5bfc,c99fb316,fe884468,e57ab77b,27f8f706,a2f08ff3,249f8b62,ac0d59b6,31fe52fa,7ab08ad5,2d09ff2c,4138dcd4) -,S(d165fa7e,d61c251e,a93e8f16,c9291b09,1f258720,fd303a3d,c573131b,d98628cb,cc0dee9,f01f0dce,aba94461,1e48f9c5,282a7480,eded0794,81d0b8c,a9819a73) -,S(87703371,46a8694e,2bb5cb10,76ffcd94,309c9c8c,be6e8cf6,5a77f4ca,4d31efb1,ee64af6a,5569a205,2cd98c10,871b2ba0,6addae3b,3cec463f,6002d86f,b16e5e9) -,S(1c7e4ec7,c090906,3d98f786,dc22db53,da4d258d,6e75cbae,30d4b99e,f4ca47d4,d2001df7,3297e6ec,c0aec17,e72cfa6f,5951e2bc,f03e4aa5,5f329c77,47cd92d8) -,S(d485ec0a,1a0abc6a,69f308d4,c7f8b8bd,fff5ac6f,ad4ae4ee,271a87ce,973b58fb,68f51764,ee705265,3e2f7d7b,7415847c,3856e3e,1a7f4932,6fbfc9c6,5976cd48) -,S(ae5ab510,48215ea2,3be55d93,4e0dce0b,ff88f09d,10c8953e,390b79f2,da26e43f,9f80d71,36a5da61,7f90d0c8,a6d9aecc,5cf88abf,6bbc2181,5f8320a7,2fa8929f) -,S(cb879f42,4613487c,24aa73a7,36f211ea,96541877,33fd7091,40a824ae,7641a708,d46a4ad5,7f607301,f61648b6,e99891d9,ccc41af1,af29a66b,b894575a,a6b3d5a2) -,S(1e8d6ac8,ec0b543d,1e0aea66,7f35b556,87e30be0,72841fc9,3f599c81,4a750d7e,8965853e,6519ae5d,c523cb52,720b004f,ad2f03e7,aa3e0413,bc68efcc,c0617f85) -,S(dd8e5b0f,be63df6f,5c20e447,778f923,2e1b2c22,4d28cfda,b2c672c6,66d05f8c,d8b75f77,f955219b,d4d95e65,35d5cb0d,23c2a1d1,671b9416,2da9c4c9,b2d4a94a) -,S(78ac44e9,938bf51a,691132e,93ec3a42,22be3185,35209054,a76b87c6,645e0252,c0f66cf0,3c20dd,d136d1f1,cc00eb17,efdf2a4e,72d373a3,99c20da8,8342299d) -,S(d53110b9,5034e916,d904cd15,1170761d,4f3492ad,9e257265,3ef37739,df9bb035,c091177d,796d199e,5c05abeb,29d0df1e,e5ceb93,d272e6d,d254b6d9,a6dd35d8) -,S(868b2732,3debb9aa,60942498,3be71d0b,451ea44b,64c22225,2af3d63c,3eb512b,8951dd34,39774c8d,89cf4b4c,485889e3,df2503a,102ae568,c63fa74d,23ee659f) -,S(672de7f2,34e96153,d83da7fe,3e199099,52ee988d,961620ac,b8c6b4c3,520fc50d,ab02a8b5,2a2d9306,8a83a0dd,23ff882f,b1052f22,72a0ad11,cea13c63,4efa33a2) -,S(4887f473,af8189d9,c46ae22f,c86ba6e0,f03c81a1,490de032,72b07937,b63a7527,a2e7a713,e1e6691a,ce09dc0f,a86c92b0,a0097899,7fbf26d3,98581731,a577a21d) -,S(f97ddd77,38bb419d,ec051fcf,a93753ff,e3dfa122,6cf02e1f,23afb376,7a121440,2fa9c241,f747fcda,dd09139,437eafc8,94e7a47c,ec8a7ffa,1e054ce9,21d73243) -,S(ebe75f9b,2c92af9f,11eefb04,3456f6ef,f616d1ec,b616a9e9,9e7f8960,4f1d62fe,40b5cf37,b06cfb0f,294da3c0,f756c867,af06449f,e2a916c8,a327117e,9a47f74b) -,S(10d376b1,1f0138b3,238deefa,b57dc84,7ef66849,14e9f120,1a9619c6,b1715a13,a216f393,1f398b67,d68a2888,1d5a31f6,e5e0da82,e2b5060,4c6f6322,9cd21748) -,S(69e26679,f103a1f9,8a9a4d88,c973874e,db7c82ca,99e48554,37284445,b55517b,cab62aa5,13b41a9c,56ea455b,6a880b95,9d400bba,74e7a203,7b60ccb0,4a89b8c8) -,S(3acf827d,81e39933,64e99fa5,63f89305,dcc60b62,44ecc0a6,b101c6f6,ecd5bdab,77e3bd28,40a99c45,30ab7767,4d8ed17f,f57a4f1a,4ab91732,7059114c,c06fadbf) -,S(2e5125bf,9e263d80,7a220063,434f928,d9a4907f,68601eb9,829041e1,a7b89bc4,9810022a,d7d3c333,d7c022d9,d0779b9b,5807226c,9fd41e65,c3fc8e1a,a7a0b51f) -,S(7b68da4a,197f6bdf,56948023,d2baf10c,9449d6b0,b18addc,49385125,e62506bf,85a92b7a,190aec87,bdcb9df8,42e93917,9254ae6f,b45e6764,32e410ef,4b28434b) -,S(60d4b53,9a29562e,8fab8ad7,3b699550,3fe7d6c1,e2ba1465,f05c92b1,61dc829f,2c2ad439,8fc7c836,5b2efcf2,1e4d0156,1a753f5e,d945ef2,bb1a3394,203d07eb) -,S(5a3a1bd,30250a40,d22aed42,71892b88,3c03ea0a,baba458,6b65cc50,4c79b107,9bf3bf42,df1637cb,80c1fef2,cb9bfaef,dcbff761,89cf9f5e,d00f0f4a,e551e31b) -,S(9b9d93b5,6b70fc67,5476c6a,6913e173,11ed1ade,6ea7b810,b9c90977,a8f3707,ae01a481,7a9ce6ef,5584a48b,fb96a9c5,21d5bb7e,2bf73cb4,b71f4dfe,aa7da298) -,S(44bdd82,86a3a4d7,6ecad7f1,ef66022c,6a49b916,3d7a8ccd,e54bb017,814d2f70,26d345a0,52034ce8,b4382905,f60f8885,e20afd4c,54df6d6c,ccd1c2e2,5d06adaa) -,S(8de8205f,e44946c8,582dcbe7,152dfe3a,7eb85e7,bc070282,3c972727,54463869,1dd97d78,e12a92f0,cc2145ee,db4ef561,af21d3db,f3cb123,ce0bb582,6791a30b) -,S(c36a713e,3d88ae25,f79b4add,90c6a724,77be7d9e,a62ca0ab,2d5a800d,41f9321f,2df57da8,6cf17f7d,63ebb85e,e7570869,cf90b462,e76af48b,641c07c9,45a638f6) -,S(1ce37a88,f25b8b81,941db8a6,13a7d952,c2cf868f,e979bc0d,5f35410d,147207a8,7fab8cb5,f6611850,e541dce2,315a7833,3999041,5c18ab0a,718dfe32,e0ebe992) -,S(e489744b,dbb11e61,a7e827ca,ad18ba55,41f4c02a,b50b75a0,353f4a2d,f504d575,6abad3b5,3ad97e6d,a301ff7c,7931f37e,55246ab4,c7560,363ff214,2cb9a398) -,S(cb4ec0aa,c1cddaf1,c7a67507,5cad6762,cf8ffce7,6a06f76a,38bb88c4,5181ca3d,7f15e726,5092287c,d2ccf3c5,dfcda0c1,8c63f2ad,21c06a2b,469bba5a,d9e4ff36) -,S(aee1c436,6b923847,40127dc4,150c6dcc,ea62864f,394415ed,9a39d539,adda44e6,2496d2da,97990e6f,5fb1526d,b93e92e7,8a011c33,61218d,c3d3c56d,952f8666) -,S(a099ce61,d950fa1f,19abc21a,79c74021,472c46ab,d8f67798,34df0429,ba785491,c4dc483d,6d61ab1d,7578ee0d,7548e0b4,295891a1,39774c22,7d073232,f2f3ecfb) -,S(6c57db5f,b194dde1,b8cc9686,fdb65fd4,eaf8aba1,84434344,7a770ddc,9055e429,2dfb48f1,58663b3,6a7747e8,4b5a9001,163ea20e,f07649f7,1d7a21b9,b11995e2) -,S(f6efa15f,20b2e91b,cd7323a6,51e5d7b7,a8b323df,924c616f,21a7d6e0,e34d3c76,ed48a439,2bb4d596,58e75757,95a0a4d2,7443415d,7662a535,a6246d64,3804fc1e) -,S(e7983476,a900be4,e9dfed94,42f575e6,4d9af362,1e874a99,576e06e5,d31485f8,9d21080a,8b0534f,6b2dfff8,9eb8172b,cb5388ff,d910fdfa,405ead29,9df779be) -,S(88ffff0d,7b415f76,8c515d80,9c607949,b469b07f,3978caff,1ba64e,ce198ba1,6816bd9,ab0e773c,38b73787,2881e96b,8eaf381,b155b205,79b24a39,eb9e0fad) -,S(e5fd2c3c,a1c85b03,3d93a3c1,261a5c1e,c4adb72a,7700405e,7c0bb108,d8fec1fe,97bdee17,50801ab9,a96e3fd4,ec4860,e59034e5,c02f9168,79b1e654,5a65fd39) -,S(fb010f18,146336ff,30dee37,b25aa384,9588b83a,bf943125,613d2c72,c2f5b3c4,4b0ff7e,7a6f15c4,d377e92e,73c8935b,d2d9f7b3,5be91cec,da891f61,c7631bbb) -,S(9be574b2,c28b1460,a1d67d94,43e4bb85,c46a6bcd,a957499a,179cc8f9,7ed33c2a,16aada1a,367def6e,d4f34409,e0ff5d41,f3854494,6a764040,e1109574,109bb310) -,S(358e97b7,6799ae09,b80b6797,90e34630,3d61fd4e,71733d6b,3c90fdee,2ad44bf1,3eeb5209,175677af,c16a3869,5ff7d3a5,e9704201,b802ec33,50c6c2ba,c0ff4144) -,S(2ed930c1,c941b209,b6e7cf3e,83971e70,9e36bed7,a4d3884a,faaf013d,5b589b59,ff6a5a5,e601377b,9dd974bc,4fe71e36,403f2cc,90b16834,b1beb6a0,98553d2e) -,S(d86110c0,6e8b20a2,e6da1930,fbda70a0,d8c022e3,e68255f7,262168f3,2bd58986,34dd600f,9b7157cb,2ec545e5,c50b3f95,2f422b21,4afe255,b7337815,1f3dc048) -,S(4e7ffdde,305ea002,f7dfadbe,e2da926e,6d2c2714,596fb052,7eddfe92,81d4fefd,fb4dc1e9,476cb2d1,3bef4548,9ab7ca86,6ccbdd71,4cfc937d,bf024f12,ff04eaef) -,S(6ba04fe,47c4c99f,849fbd68,7e1ca6f6,3e00179,3ba3a08f,86acf668,df0afdfd,dad78b7a,9d34c738,31112801,91476b92,b8eff31f,fcaa6d,a0704244,5fe32e37) -,S(bda2c2c4,86029d0d,b804f1ea,e9215150,34276a88,179154dd,d5d9f176,cd7f50ba,a70291fa,47b98bf1,fecd9aa5,b53ca619,41d62c9e,c8b02ea7,91c79482,afc8f1c3) -,S(99801a16,4da92a6b,de6ec7a2,69c2798c,b421af01,5ec24c8f,1b090169,18980a5,3af209c7,de27a683,56f242e3,8805a368,66cf7780,60c2806d,76f9eb06,35c18358) -,S(67fcf955,dba84390,638517f9,5792d09b,64c056aa,ba98acf9,d63c2bbd,df5f021f,96f96080,b5758233,ee15e8c4,7ffdc3ae,bbc752a9,d7697e1c,3ec3d479,4f912d2b) -,S(c15990a0,50c2946a,e4518cf6,84ac9cae,1022a29a,bd88f8c2,c8e724c2,89b954c6,611bc99c,e4ad5b6e,3ac932cd,e2e70e0b,a3690ec,758bdead,5edb3b0f,b5b95d56) -,S(c5261ad4,f6d03a0b,c15ace20,aaf95bf,94d9ab5a,95a45d90,6ce7a622,3b09d59c,5fd1b7a3,b22732c7,4b5dc1ca,fac99882,467bd80,53f2f606,ca5af8fe,6d741448) -,S(b0bec3f4,eae81fd7,2b70027,72a49acf,46a5c50f,48358df5,e174eea3,c0da88a4,13a4cf63,fca873d6,cf1b8c35,ce25f439,4d74a5d2,f2fa2799,d4c3bb98,8b50ab67) -,S(e3d32fa8,9218a38a,c503780b,dfe23dcc,e6a7138,d84668b3,f71b3fdf,891b6256,246ebe20,7ab7c536,8f7c9795,9e7aa1fe,69909d50,f4b24263,c32b8bea,7674b85b) -,S(ebf3bd9c,1920f625,4c32467b,7c1c138d,3ac6a4c2,b185557f,6eeffd7b,2aae0d63,58ed82e1,25fa2241,2bc4397e,73009692,af1d5feb,f640a422,f52e5cb6,42d4bccf) -,S(d062e72b,3dc76d03,5827786d,a9cbcb03,b710ea61,2eac883d,b7f50df3,fc6f7175,cc56b076,dc3cf1b9,e544858c,1a31723,33ba9848,a8c463f2,abf2c6d0,dae14a6a) -,S(97444eb2,32b09240,fc596530,374da035,f5ebd37e,6c74b51c,8158eab7,8ae30f89,fa06190f,d2072bad,b9144f72,db18819,ba76399e,d171d4bb,1293c20d,63d70391) -,S(3e1ffac8,15f68300,4714f302,1ed39460,d5e4d63f,6fdc445f,12d8470f,b273c242,86f0839f,8610c4cc,6ae85d54,b951441e,efb700e9,9ce54aa9,fb6c7988,a8494c25) -,S(deef1e7c,12e498e8,6542acf2,3782ece5,2a02b13e,3b4e71cf,e39e79ba,541d2679,e039a94,f4b169fe,a13ed182,f9e541e5,2b117536,d90024e6,9f3bcc7c,988714cb) -,S(69ed1a62,b3de5c,c5785b27,c7926e52,4ca1527,9f8a00eb,b5e1c247,a6c8265,9c5fce7a,84b79a67,9f3030cf,a179a682,cc22c464,11ffc8b1,ceb885ab,4753de36) -,S(cdb36419,5c3be45a,bc9f58e,e5a499a6,ef58ff2d,296ff989,9fa987c6,b753f82c,34a1a6fb,7a6b6c95,2a604340,d2c30c15,69c46123,e5cc5318,833f3a3f,bd622e47) -,S(c5749ad9,f4583689,f2ed313f,dc35fe8,acb6a85e,dd0498c5,ddcd4842,fa21c555,f22ea47,ba61044b,54ef967e,c8c82167,3d14d710,334784f6,a7b46d48,19f99cf6) -,S(fc86862f,b2fac126,e4341121,c82a9e14,d7a48b9c,988b8458,300dc3a,ba10dffb,42339dc,e304641,f814327b,ca5a611f,3638d610,85826d70,3d94c76b,8297f6f9) -,S(66dd174e,446ae0c6,3ded267a,faa20ba5,62131459,5576d10a,1e44ef18,69e36ca9,d93a449f,6d3fef4e,435f6fa6,3191b625,b883c303,1dd8b380,777b556e,acee9df0) -,S(736a80e9,15b39c21,5e5efbe8,ed6f8fff,7aa826f8,5c940110,3c7ce372,86d952c6,4a9e17d8,9066ecb2,95447058,4dc58c36,c84b3d9a,30ea45cc,e62454fc,ae13e0ba) -,S(7b747f80,f4a324af,e6042edb,d8682d3,1b8fe12e,19936844,b44c3e73,f6b7075e,c2684490,56e7633d,2add97c9,75079594,b9c0d038,cb864331,aebddd3e,18830199) -,S(dfd54b47,e4d2abe1,c40e0a1c,2916469a,7e8a61b3,bd95a1ea,8b5fa182,903d8339,c705b4a6,761d2ca,49f87fa9,ebb4b39,35c3c633,4f6b7643,417c8a29,95515fa9) -,S(992a5fca,521a86e3,dce0ccc5,fd1b2ca3,656f44c1,f4967931,8ccb7a28,7879213d,ca2836c0,496c75b6,4c56c13,641d0402,b64cb2c7,617c9fbb,d820245a,9321217) -,S(38e59093,acc26364,de9cc5f4,de398799,54774d68,ed4b0283,2bde2a26,cfcd23bd,953c21c3,14ad2e0d,511d3f05,678358f9,eec2fa48,d6b24c9,6ed4efd5,da3b3719) -,S(889ea31a,5969b77a,c41c0a39,cc5d006f,6ff14f22,a62a5f26,d736ebcc,f5df8239,4c2fa5d9,c2f0316f,dcd6462b,e7571f4,92aaee96,c3c888e5,21cfabcf,78d2c3f4) -,S(f70e24a1,6807d5a1,8e15fdd,f31301e8,bd210ed,5d3d614d,82eec8b0,326d7b6e,dcf95677,b29a5ae6,15e2e7b6,c370cf69,ccec71e8,9569f0b0,5715963e,da6a34a1) -,S(d6eb7425,9c17d292,e1b1a4ea,624e6876,a78aa774,2b14e94,d3fd1b43,562e35e3,c05013d1,4056ea0f,e5f1fca4,b0c74b5f,776a8564,ac973973,c929707b,b3f078bb) -,S(df7cc5f2,69faf306,6050409a,6a03cdeb,8f33d1d7,4e30658e,e871de09,59701b16,3d8a28f5,f604c765,5f28dcf,b2f3407e,6a63db14,6b879fb5,bc785e65,59319147) -,S(e6bfa4b5,85f6df59,7840119b,6a31d0e,4ad800ea,239bbbbf,a8a1a36c,f8c6b5ba,312b5d55,35402ae1,37f9a02c,aba859a0,22a8ba00,88a2305e,4afe8283,98844dba) -,S(3c762a8b,acb68a13,2e3e022b,35634b3c,1907cdbb,261ff639,9520352d,fd94b3af,2ad358b9,65555cf1,e0027e3a,b93d46c5,b104324e,2c62f9b2,5f70930e,bf49f385) -,S(b4d94e26,9955b213,8025e5a5,bc5ea171,c2ea6d04,9ab60184,88f47f7b,f6a6d3f5,197b20a8,81e9280d,96b5b4d6,ceb3fa20,38a28654,63e76ff,d0b5b401,8b59bd1c) -,S(406e616d,907a0f72,12acdf3f,d5341a79,9b482697,88976615,388064c9,74cd8ed1,72730d26,b2698e29,7f62fd98,2a3955c,da516ebd,642d6619,2d33a915,ba39d0ac) -,S(1762d974,37705ae8,37603446,c8c11568,c7878053,f25baf9e,e3bd23f9,5babdaf1,1db8fe6c,77f41656,1fa4df40,23662039,66a8f891,e5467b55,3a2593a5,1ba796ba) -,S(f5fbeece,aa5386c4,d75c92a9,88ce6bf0,f957a0ed,3f0caff9,42f1f29c,7ad765ee,fa45a4e5,85ccc691,88426bd2,8ae561d,a2f59d10,e4bd63b0,4f8a53ef,1cc3ab28) -,S(7e0d92d0,d12bb892,b87b8bc0,993b4422,cd1e9d95,144602c3,a2aa3c06,bc945ecd,601b1019,746bbd4,ba9bf00b,4ffaccd0,b1bf885f,57ec49d2,9fc91744,8aa70761) -,S(64cfeaa1,4d4e0cda,db6b6a2d,9e2c2820,d2fa7817,43d7b2c2,8211b1fa,e17ee0db,f0b199a6,1a1856b3,360f519a,a6056900,7a0ee623,69e0aece,ea64f0d0,8cf568f8) -,S(c90f70e6,99ba1a75,86073eb4,5540b3e0,80bc78a4,e811069e,f861b048,5f11c88b,7a8257ca,cdc7538a,13b55285,939c614c,14d6a94f,70509900,44b286d6,7eb84e14) -,S(3edbcf0e,b4e5e640,f40afec9,ad370813,426b5488,3090f8d4,b72b1680,6694f42a,ede4512c,c4baf93d,f05c14c9,cb17b1c1,fec46052,c7087306,2214a05d,60743c80) -,S(77adf15b,ae449ae2,f63d7c44,3c56cf9d,64d43840,5154473a,5948cc79,160b64d0,a1bf9aaf,7804cae2,c377f98e,86b75e90,6886d293,21aed43c,77e330dc,df9113d0) -,S(350632ea,23e39962,3daa53d6,5a916f31,b2ca02bb,5bca1f58,35b85165,b430398c,41931339,48282550,bfa1cef9,94c28873,ee0165e2,fa970d04,e51f8ee2,b87916be) -,S(3d6aae93,5ee4ab6d,46de768a,d6938703,262e9fdb,13bade31,d38fbd0,9fade000,62674fcc,6eaddef7,b971e964,5a688e32,14186605,615982ed,a09de4ba,13eaab23) -,S(856e564,a155a29d,c1b739e6,309fbbe8,5ea4debf,f12a9249,347a5435,af674993,a0e6deeb,3777ceb4,6017ee63,caeda231,e616fda3,c105f0cd,6174a3b3,dea84256) -,S(95f8b405,c1ca86fe,d56727ea,eecbcce7,32d2c521,415eff95,b3cb42dc,5230cc7f,c8c66b1f,2637df4e,2a5375e,3a2e5e4a,a89404c,810322ce,c4b2bd1c,91163ccf) -,S(b51de213,54aa18ed,6ea589fa,e3b92d90,732dad07,6c80b842,579d53bd,2089e0e0,8f069737,1baca2db,208f7db4,c43a85fe,d816eca4,e35fe95b,780e2c4,a3f1b948) -,S(e36ac0b2,c4b73783,7a96b372,b8d0779f,41605e99,2a0013a5,3c8eb4eb,d5e2a988,d41ea6e,ef06bd62,7c2acd2f,645acd8a,75e353c2,448aba53,452787b6,670eedd7) -,S(4d08e46b,a3e812b0,67071dc8,b76cbbb2,4effce48,cf4a4c5b,ff4e15af,71c51635,fcbf2dd0,ba055845,b70cc545,5a8658f,39ef2176,9802fbda,2d3ab98,ba914c3d) -,S(31421774,5b1a6b68,918e8afa,4e8dda05,6094a6cb,6024c3e0,c10fdd99,245d7501,7ea6ac19,1c0db139,eafdc961,e8f91f1d,79269f69,cce275f7,abe9598c,2916fbd5) -,S(79bb2dbd,f9afbc9c,f605ad45,4768cad3,14d48241,724b301,7b5abd51,6f8dd4f9,d1c9dce0,30fe1a72,5d100c07,d842a78d,beb689a,606a933,ca865051,49007b8c) -,S(112abf7c,1d5d66d0,cbcbf42,1874bcb8,88d3b3b7,5c2cf36b,1399fc04,17525731,b3d3ee4a,f44b5372,8d0957c5,e388094c,34fe0f5d,c51abfc5,76c1e18a,c920dabb) -,S(f6257a3a,60365e63,471fe77f,893a8ae3,174d30a1,9aa495cf,251812d4,c5040400,293ef8f3,91804cdb,34845404,996a24a9,5554fd24,185ec85c,3a27ef8e,c89938cf) -,S(ee7c8ee8,bec75bae,db32c6f4,3b3b7a04,2c10e903,de9e7d21,5ca08135,d59a682e,e68a0137,398fb186,d5168e64,4421ac4b,30a635fd,c15527f3,e56b21b7,c0008ff6) -,S(e292a4c0,fd63ec7c,c661ee1b,25c9d5c7,dd805a97,fc6e64ce,5d3d18ad,ddc92aa8,ede226,7fa6fe51,1d4a510f,e7f5e14d,8fa29fc8,b77d61ea,2e140739,29644745) -,S(cf914327,85a05d41,2ad06146,6df68649,d3b8e0f6,86a83a70,d32c2fdc,978d8124,f74c1223,7b0899dd,53afaad1,b9b06704,c61c6e97,81456e86,ea55e65,96b0b13d) -,S(88e58d21,95376fcf,b3f0c44c,b013f2ba,3379ba55,2ceca46c,38ed48f1,263fe894,f2f38177,bc673cbd,70853432,6ece1090,5863ad84,1140c59a,2a782af6,ccbaa71a) -,S(90ada18b,df0c62d9,dfa35e14,d1eab9b3,48d09579,f4e82cb3,65dad65b,62ba53c5,2c4e704b,fc9a9b97,7d330d92,602c677a,4a06040,74517775,d441d0ce,6c5e5e2f) -,S(3bdc1eca,a939c8b8,c164e5f3,1a02a6dc,9d2712a4,6c30f54f,e2159934,d492d1e5,e53acd26,28f6e646,edb5f53a,d9e1639e,43b4ee9d,b61a3545,a9874609,9b3c1e94) -,S(54a206cc,48c7d529,c8bd2ca3,91501ca2,1b58f5ed,921ba11a,95eadfab,3a720bf,83f4f820,b9a07ae2,8c5e137b,c9ec4f0c,31c875a4,b055b0bc,8de38f74,c54c06fd) -,S(2754b021,13885a9a,f44cacd5,2999a03b,d16c90e,4e3a7a67,cb3426df,f6abe546,f8969b1e,e955f8e2,dc0d3090,167c0116,66beaa68,35bbb1dd,e721c4cf,768ef566) -,S(ae438153,4cf07fc9,1dd14a40,68b3cfe3,aa6e608a,bf1d1c1e,13ac54ee,e0759165,e7807ae7,395fd072,6f77d7dc,956c58a0,69243b63,32bad336,72d2eebd,662fb99) -,S(cb9d28c5,357165dd,fe18010e,4263e626,65fd6315,60ec8126,c7b60603,6ec067a1,86879039,f3264d1e,511fa8e2,4298c9ed,6f1e7625,897666ad,4db9a43,3338f5c4) -,S(763534f5,52317771,551524ae,7ce33579,41da627f,db77d4e1,a9cf72a5,f182d276,9fd8ae13,b1706cce,ad190066,9b1d2f46,8c177970,b5173f76,55efee54,ec5cd8de) -,S(3990fb8b,39d529d0,b2d38432,3c60ffdd,3b32f7c,278aca88,f49f1523,fa16ded5,e43c977f,427570b5,b238edd0,77db9df8,b1b82e20,b73b8d56,84a2ee37,886edb83) -,S(6b76502a,22280e31,d0b6375d,6dffef0a,94dad7bf,e640a406,2ad696fc,2744cbf6,e667122c,b6861cfc,97fc4ed0,e6193883,c79a896c,79e31603,a67063d2,421845a) -,S(7ac03be7,2ff15233,5ec9c349,98e77ff7,79e5f348,a49fda4a,e52a69cc,6b02c02a,74a9e36f,af0ef72d,b493617e,9474b112,593de375,c845c8dc,c1028ee7,9fd17599) -,S(31a83e18,c03c570f,31c3ecbe,bb787aad,6492cdc2,3e07d3a4,43b56ca2,51c0888f,3cbddf10,9bf08e81,830dfa49,d4d3cf95,224b7a4e,fd6d9997,9dceb64a,a8d7e440) -,S(ec13f2e8,53935ae0,705c2644,d1512bfb,8ea4adaa,d45a454e,f761dc68,c7ace561,54139641,97e2f5c5,5b4b7f5c,5267ea7a,bf36b01d,cbd62765,ff56322,c107f321) -,S(ce8e23cc,aa38e603,70defdd9,37803f02,18ae79a7,3679c363,4dab15a,bd46004a,1ddcf92,92ea77c8,4a1346a,a5f79f13,26c9092f,14ce1992,dfc24bf1,a2da35d5) -,S(77d80689,f7cd8585,fc03cb20,14d02425,3b547962,a282beff,17aee956,88292ee2,466283f6,429248fe,301e18ef,61a89784,47142fd7,fcc5c496,36dca83e,ae8e9f03) -,S(6eed61a1,4e7e7ea5,54a4e43a,61fa7eb8,b8e7fd0d,52de9ad8,e4e9b130,78178a5f,2cb4d228,90af9cb,a3c050ab,12a3dd53,1f1c6d6a,e4393449,219d86e2,6465bbab) -,S(10cb3737,a7916d84,12c955d4,32d1ad46,d8c7a60a,e44936ba,f62b2a26,b698e4f9,35499a5d,11e356ad,fc5960d5,8d6842e8,ea0615f5,e8bf39c1,8c217cc6,7a1faa97) -,S(e866ac84,6040f92b,c52d298a,6ae110da,e16bc797,d6958858,1f63c00f,6cc68211,257803b9,ef7bb5ac,59c6b59d,32a49d53,64c6659a,cb0482e,a9d57530,4e244f90) -,S(5e75ce15,aeb91c2c,e4ce06a2,decf02a1,db85ef5a,a43c42b6,179d4a,2eb4e404,a08d537e,529a6654,a785969c,8d8b0b86,e3a76f91,d9b72d92,992f8215,1b61bd1f) -,S(fa80c52a,12afecf4,7a5b48fd,60fa35b5,ffd122d,8616ca07,1c1271a9,bfe2c104,74487acc,dbe2e60e,e054643c,37cd624b,3dbbc3d3,4aaa6009,9c97cfe4,b3d69e81) -,S(ddec1720,dca13ec0,2eee97cb,445044e8,d6b049f5,694ce5a,efa664d9,d89b6dc,122b68af,feed4f56,b72a4a7e,e20a7f8a,8daa9883,9a797857,8dac0851,1b843872) -,S(85116566,57b70a1a,96c5da0e,fa5d3025,49fcd00d,104a4989,442ff143,a08b5a59,2c96bdcc,430c6c28,9d54806c,9c17961a,8121b10c,5168cfed,a0dc8edc,9f4f551) -,S(7de80b36,89b9dfe9,de2f4fd3,4dbcedba,9ad39842,f105f580,d8d5f6f7,e1eb3e58,43d20653,db727ee6,155998cd,f7bb70b0,9be15c7c,a04593b1,398b4586,baa3c417) -,S(e66179d,366fa7af,a982c480,9578d469,91731ce8,c669d8e6,bdc399c2,a2484b1a,9371d856,28bfb10e,d07c3390,b9f08222,98793229,ca2cf2ee,75d53d2d,e8144441) -,S(1d435048,d7b8bfa9,6df91fa8,f8f6d1ce,913bce85,c2c7a1ad,cc199afa,5da012f1,4e389f26,4f36b2c9,296934ad,5f567eed,30f3179d,6538ef70,f4205219,2c3eac82) -,S(5866c91b,619f53ee,3256772f,56191a35,23696c7e,2b5140a2,89f36c11,c1cdfca7,67090999,33ade86e,3a5d384c,840fc584,2a85087,10085798,913c41b0,e2dc1737) -,S(1e06d768,20c95907,405fc2c6,bd75e1c2,fb9c4d0e,4cee156,94e1a4d7,65a77a01,4aea359f,bd26d7a6,1b1e9f75,5544363,27eea590,fd2d5eb8,87ece7c,41759674) -,S(ee415cb8,5e1ef106,28c149bb,2d2f9e1b,a8083367,60a7b56a,f122cf4c,9b59e5c9,f52aeac6,e2fb8a7e,ca5a629f,b431736a,eec16a06,c1a4b876,94ad8bed,bad88ae0) -,S(42da5368,b60f85c0,9f52c3c,9aa82e66,4868ee37,4b1851e,d37ba6a3,fb717e6d,71f65b16,a3937a5e,b535da,ec530798,d1c91c88,722fadb6,580510bc,5f27ed65) -,S(10bf9254,6300aa51,bb08f849,5acf4e53,b1eb4e57,1328fef8,304189e9,7acb81e5,9b519bf3,482c9516,132388c6,dabced4d,971d033c,52bb5607,6c788a37,a9eb49cb) -,S(2f6456be,5c2c184a,1dbdde7c,2dff16ac,8f504a9b,d86de1a7,d9d3c1b2,bb0688d8,6bcdc62d,4e6184ef,1fd39720,55da6e7d,45cca6d9,4d15c052,8ddfa715,4aa68336) -,S(e68e8fb9,beec6d15,207e7017,c3574e34,102fd7f6,5e5f18f1,e533487e,5bb2fae5,13624e45,da0b6edb,df4ae938,82148590,63094aac,1b25d534,f80ca56c,814a944c) -,S(7d314f19,4b776d00,b946825d,f634f763,e0b5aba9,b1fb0424,833301bc,ab1e94ab,80d402d6,a8dca19e,709b9e23,4dfda4f3,9f9f758c,928c1b9d,842b2d5d,aea3fa54) -,S(fd78e68e,5b5b9522,14b35d5f,a0951f4c,4d5df056,28c5bafb,9c6144e5,c2c33a49,49c62b9,aa91e5f4,be13a209,7f941c9d,cefbb300,eeed9fc4,a12c1e45,37f4535b) -,S(e751f61a,11e0b68b,205fd306,9f4abab0,b2576131,3ac3ffc4,eb4c525b,f2b28f6d,aafd8f6,2fe20722,b180ba67,f9c3b6e8,8ab2b96,956d603c,868a8867,c09ddba5) -,S(6db64d2e,281e6734,a8908de8,554dfa93,d7811f01,2852a306,9e6ed59e,c09a4823,1c1276a9,1de36164,309d83a2,d9fdd003,d889612c,6026817a,cda97f8b,d2cec77a) -,S(4de91b17,fc227eca,652f8d15,8cf0c696,c6902df2,b44a02ea,d05dfd68,e408a17e,130fd485,d59456b1,48458cba,922e9ce7,79968340,d7e5267,b2f288d9,6df924ae) -,S(356ceb61,8c57db92,931a305,4537ddbf,8bad8cb0,c13f447c,1c3fa485,5c0ba01b,6f52d242,ec189e41,d8ca010,cdd645a0,8889206a,4df81651,1e820e0a,74bbaa7) -,S(595d8d68,1ccf61b0,456ec03c,53cc5a93,85e553b5,36033f8,ec56c575,db49cce3,773b50cf,f0718e6a,6a269cd9,65b5001d,f5613238,3e279bc8,fb937580,a76ad035) -,S(b076afb7,234e8fd4,4107caee,8d31338a,5122d785,4707605c,2e5dae93,2e6c935b,a18e661,1921080a,84a74df6,15006847,981b552a,4c3021fc,93967c64,b19d629f) -,S(834a4467,bada612e,2705b0ae,19fc9f1c,b80e6e9f,7c4c01e,5899fba0,1f60cfe9,9215b4e5,f8194645,813f00a8,58f77324,e28522de,16e93e80,93197310,38ed9af8) -,S(d00093b1,ba6eea04,c08df30c,90b2f7de,6e13b42,c645b01b,127003b,5642aae0,87739294,746ec547,4497a951,c26ca6e9,12ae4638,1d0e2804,5363fe26,de088434) -,S(66a33bcc,71bb2f0b,ea36e5d0,f1446ce5,f3d44a9c,b715e6ba,ed00cf70,4c4ce1d1,27d0f5b1,a40fb2f1,e1f9440b,c1c15731,50efa23d,b8997928,cbdc0e03,2824a6bf) -,S(ac65226c,dc40fb92,a9632724,20983b87,9e1a7615,fcbde26,ac9754ab,408211f0,ae633790,687f1c02,52115aff,3a7d5c92,9064bbff,616b5eb0,87d5c1ee,57cf8d3f) -,S(a4b98213,78cb0e23,d46b1359,43b354da,3825e27a,76f33334,147a3ee7,52a81913,2786a9fc,3701a6e7,caf07030,3bb382b2,ce6d7c52,42496130,13382f59,92fec4e5) -,S(6f58e6ad,e4af1dcf,633d3f35,8ac86836,cf0968a,49c2e85f,2434ffb4,2475a34f,70e30dbc,dd567c8d,a6aa970d,3131009a,f5297a36,f80750be,6462f1e8,336db9ee) -,S(9bc7ace7,d55fcd7e,e67a0484,7d0d6902,f053288,ef17b3c2,64072dc0,ae0e94d9,7f57fd70,93f3d09e,53a82818,e5ca4cc1,6b46f73d,2c00e50c,698d5963,8a8f3f7) -,S(248195de,ab1ad52d,fe739d17,a03ab762,927e058b,ae666f2a,4f7e220,3173bb3d,1b1914d,3dc9f584,51ac3346,d05f033a,b793277b,dd80262e,d2ffc219,6965b96) -,S(f6008de0,21c5cd46,d9d811d4,4070a7d6,46105a55,2a68c389,a11161ce,9baaae2d,962cd254,e5b0d724,5ddf7114,32ab2800,16f5583a,b8fa02a8,61b7c3db,eed77d91) -,S(f6dce5a3,a919eab8,c1d850b,4643dd3b,96e5c7e2,a1923b58,202543e5,4ece5b40,c1b88f2a,b3d516e4,7d289ecb,b16b9bb7,4082a6c0,8ccafee1,21abf691,73734c08) -,S(23fd6281,b4958fb3,b94ac9cf,851561ca,415cc979,7ed619bd,15192ca7,7ad39a71,fac12f70,ee38f19,b2dbbd5c,3cfe02e1,b69bbde8,7a45f8d0,bdfc909b,640622b0) -,S(da3a5c2d,7cdeffda,1ff2085f,fcda0ded,eb40bd40,3591395,e4b20b0a,25a1aa8e,e0d90d58,a6cf6038,10bf2891,d51da508,77d3aaad,5ccc971d,944ea960,c943e3be) -,S(22113f6b,8015b2f5,bbff28c2,cd5dc253,c495cc62,88361c27,3e788aa3,58a94554,7b6f7bac,2db4f198,20ca6e90,bab75cd0,983536bb,80051e6b,7da589ee,dd2ae962) -,S(3b59d8f,d59a2e6,89c9d1c8,a4e2515e,73317cf7,41e38108,eaad880a,e3417c72,bb96d412,50614b50,8903c28e,b5d39ed5,b4e735f2,ea10bfa,1265aba7,f21ded5) -,S(3407e5a2,4831b572,abc0eeaf,c587b20e,9339dd05,ebf395d5,378cb151,e0dfe661,49214182,78e4d0be,31cd4e1b,9b0458b7,7e028840,4a0745f0,40960dff,b9022926) -,S(9540e180,47717f7e,f6ce71a8,31368919,e4acbfb6,18c1582d,cb4093f7,caad2601,6fe0f64c,3f0aec37,5b36758a,7f65c7b8,e9329f62,3309900,efdd58f0,7bcf244) -,S(bd02f758,513ef045,af72344,f5d790cc,1c549a23,147a2743,b8c0cb30,891af3a1,3c605d60,13a560d0,d792c5a7,6ae2f739,7631ea13,7347864,4c6bbae6,dde96079) -,S(43b10d72,cf1ba39b,17abb149,884fd00e,56525f61,594f9654,48683c16,88f3e69a,cbce7dc6,1bf71def,95bbf6f2,fb03751b,8a0c6350,9eb9ead3,713366d,8cb71407) -,S(32900344,9ad58567,6ba2607d,c873a8f0,80d9c0eb,2f7314cd,9746008f,3c569642,8c6560c6,9a037d5a,3b2e740c,270ff543,54abb60e,b32ce5cb,4d18ecf8,1ab7ef60) -,S(a1495bc1,91188644,4991e097,5334c9eb,cc277640,f568a7b3,1350e4b7,222b885a,c5a1c341,67cbed14,7f28f794,d9d2867a,9019948e,56f986a0,e69a0d6d,6ae7dd1d) -,S(4640f683,f180cf5a,4929c2ab,5169de2,85861055,67c7c2a3,3db2d01b,c3c8d726,7d6ced33,7e752ab5,c87fb211,903c3a91,e5b0ee78,361a43,b716754f,d0daad8) -,S(91b3f9d2,7e989062,ced571ec,f373ff66,f8775213,95e625db,7d1b5168,e895473a,d7efd35f,56ffd001,bcf0191e,2692e832,99d0715a,edc1a19,2b74d8f3,c0b23b80) -,S(437cb866,aedcc0d5,8d89a41f,95cf5dd0,b355f244,7885843f,c163d54,a3839db3,9d644bce,31992f2f,302c5daf,67e42b78,74bf3f9a,a944e936,aef17203,5ac2bddf) -,S(be8cd347,572e0e46,5c745c83,26799611,a5ebb1ad,3ae74bf,474a6386,6f4a3705,6d39457f,c1010837,eac6bd41,bd4a245e,10bb39f1,77c5633b,92bda8a2,c50a3dd0) -,S(f40a76f2,130d31a8,c560795b,54fa119b,153a9a75,bfe7dd28,cc00ca35,2d258331,f92558a4,69f1055e,251c8814,7a94dd08,44bb2048,31f2d33f,d95858bf,dffd695) -,S(17e01809,b94d294f,c4438a92,6f90a295,5a9ed96f,a201df62,b96b19d1,7e837876,c9506f35,8efcf330,35603c30,880d5625,db15175c,486f3c5,841a14e8,8e5f4e72) -,S(7dbc457d,7ad4752f,8d57a09e,d4e8cf02,6c8b009c,bc29afe5,ce2ee745,61630da9,fea9908b,ca852ed8,3c1b44da,207e8bc9,221b8dbc,7e8b61ba,ab8d29b4,14eb29de) -,S(89fe19a7,6fe2208b,ee4de72,249a503b,88c63e22,71794bcb,9484fd11,1df7902d,8a4853de,c3cd9e1a,713e46eb,e771ee97,b88defe4,7e1106d,88ccd713,4e3a6779) -,S(3753a13f,531da9e3,5569ba37,7db76dcf,b43b5483,1e65fd50,a6ea560e,e70f3eb2,ace8aec3,867312f4,f095b4e0,d08ad314,2005cae8,b1369223,d1301e29,8e51d4c8) -,S(30d76056,384beb45,4c54b4bc,fcdcfe0b,1c1ad5b0,5e693384,8794846e,c93a144f,f79b9c96,8eee678d,b899f349,412bf193,5da9cd,c0ccdec8,2e45ac5e,58f3d3f) -,S(d9864700,7c74872b,40ec273c,59aa149f,8059a1fa,95e5b47e,378ec515,841eb2fe,782a39eb,ea47da96,9361a337,c5e2cc0e,49d43dc,6c6f9da6,6952f347,ca51845d) -,S(40d665ec,53720f95,42ffaf3c,30e8602b,53c52123,e9dd3b91,6a2e9099,8d534fb2,cc420012,490afedb,d840a466,bc27f66d,526a965a,ee653886,8cee46a0,6a58ee30) -,S(f31507a5,516719bb,f07438a8,7b6d6d93,d02a88ca,c18fcec3,9190f358,bab3647c,dbec3898,f884cb2,aedfcdff,402ca4ec,8c8f8727,485060c6,8da0d2e4,edb46eec) -,S(62573f5f,75db743e,7939137b,6b5e1d0d,41468ed6,28d2b76f,ca26ed2d,22532c03,9a4da6c0,d7966d8b,138497df,af25b0cf,2d14215f,ff039065,d42897f0,df33be40) -,S(d0887924,f15c5069,1d7ace01,7eeda410,e8d0a10e,f6091a4a,7b5f368a,42c54416,b2fdc385,527d34f7,a434c1a4,1f9fddc5,add3b1e6,82b63838,da0ecd91,16571c4) -,S(f7585b4b,5f3318b2,2307f34d,3e4bcedb,d4b91eb,180be664,4d031bbe,9b5e3d90,b6fd16dd,49993bd6,4d05398b,9ba7714e,798d3ffe,95393231,395c03da,b3ccc819) -,S(c9cdc99c,198ca8e4,458e5473,3e5cc0c8,100fb0b2,2dc6f07e,b1e99d2f,6a4cdc42,c4c21204,67198733,a845efda,33a5c1b7,67cd8ad3,47a16b6d,4a6f5ac,995dd680) -,S(1a054d1,5c4fcf45,384ead78,e1260eda,dee9e907,84021c99,179a9fc1,c7a3ac49,50ac5d54,d4fad7d1,5fbff150,d70a3ce2,9825e79e,206f4279,f1030d29,2de89a07) -,S(b0796a05,52245e66,56b3ce51,99864d40,aed71b62,3b9d55b0,d99163de,7a8e3455,a061fa65,63a84b15,1ef666d,9f99abcb,f1611e3f,6e26dae2,6be7ac56,c0f2768d) -,S(66fcf877,6ea02717,aca92a3b,5c19387e,72658125,f6e20da0,7595e376,804c3738,9fc66cf2,3195dcdd,7a72225d,96a8c5fd,1c84287d,2189e414,d0deb6b6,76e67518) -,S(3c7caf6e,d3da8c0a,effd832c,f5356114,55646982,3a62dabf,2ccb3de3,452ac96c,e44ca4ee,bb290527,4cf8f554,40c92ad9,6055fe3e,1bb344ab,ace5c4f,80e3b984) -,S(edf616b1,1e7fd6c5,96df3fa,77bfbde,f3f82e7f,93e5addc,53c83933,844e4b73,879982bb,b89ac019,e83f5c,dac1fcf4,fb918e2f,53a5ec35,45be03e1,89bfe152) -,S(7e9af2ac,b3044985,181de5aa,9908259e,77207ab,933c7915,9dcd7aaa,90527eec,e4cc83d9,d29778a5,eb83936d,97bad637,370e74a4,3254eca7,65d0a449,106ee3a5) -,S(32dad830,3bfb015b,6aa6759b,c2e8d4bc,2a9e356d,92d97286,c92dbcf4,53591aaa,ee27e7fa,b36a2450,f04962f2,ee60f9bb,68a1147c,9ecabaf7,e0981564,c1164fd7) -,S(d20720f5,73f1db82,c1a2dc61,d3684d7b,a3943186,cd513a5a,9eecd59a,c9225a82,3b29448e,cac88f13,7dcddeb9,36f02724,6819c6c3,3f03a2f8,cc40a6e6,f8704570) -,S(3a732b5f,5dd6dc77,1d215321,f8cd223d,22f2195,9d45c708,5b000129,94d5f03b,3fc75d80,ea7a0663,c90cc7e8,8a6096f1,b3a8c9c6,9849ea50,f1fd5c94,7928cfc7) -,S(201961f5,412beebb,7e190d75,70977b50,230810bc,b3b69e3a,dfb5e259,d811333c,eaa3f681,3816ca15,dfb9aebc,8888b578,e592825,82dd1b47,ea50cad4,f59b0101) -,S(cb184267,70cd3b68,151f7d82,cf7a12c,dae332,868663ab,4546c119,fe26f4ad,6c395538,eb09c00a,3e973def,8272eed4,27a3ca9b,a77d1a0e,c4e206f8,74591a40) -,S(2c13d3ca,9ddbe3b4,2920f0ed,28622260,2cbc0493,e5156655,30b53da4,7ae3ba59,f7d9f8f0,c58510b2,db28e723,6d9af034,658599dc,fae14274,efbff408,dfd18613) -,S(3ae7b7a3,86ae6c41,90b3a0e1,e5f1a7ce,4fffc405,84f05043,93e716a4,3ec83d41,643043a8,55603964,c46e3ba0,999c73e6,ab34703d,9dcdf9de,1743db7,71591bd9) -,S(b5eea0d4,ac4d0a9d,e37fb1d9,6825233d,a00f26be,86c0b640,f0fb34c3,465bc441,9cb5b93a,56d35b2f,2d921c4f,15b4ce0f,fbb9240d,30754ace,f16b3019,54732e1c) -,S(dc049453,9b8d5200,d513eeed,edc2afdf,e76146db,358a86b4,12ae9e28,e8501e3,6f6f2d25,b331a4b3,686adc14,c26814,96004900,34524b53,8418fe5b,9776a3bd) -,S(821e937d,a6fae1b8,3b6aeb4c,f5315bcf,77b2fb07,d0081889,80478765,cea7f398,41405d00,33224982,2acfc2e7,87be9658,7baca419,14b70315,c1a57843,3f85aa21) -,S(818bdf95,f55a8e51,c0d08d83,29574c28,1ae3397c,f6ac5224,4d82ea53,8f465c60,bfd41438,46dbbf6e,3fc442c9,7a66e8b5,32445d39,fae8c473,51e0ee9,9a9a53f2) -,S(e3bb3262,36533fd7,84fc6d9,84cc5590,2b03a19b,6c956665,322c0bb6,264b6d72,bbe4844e,2be51197,d8d84c75,ab83cee7,c9ed7dff,51eac125,1161e09c,c1078aae) -,S(36e3355b,5f946199,b33dad7f,b42d1245,4cf8126c,568c4be2,cb2abe4a,b83decd2,fbd5d87a,8c012064,3ed3441e,ec686237,1759ccdb,4a7f564e,c2ff9584,ab824833) -,S(bd7fc193,1b06bd7b,c6c274ea,73d33e71,1e1e57f1,e6bf7a8b,6452d979,777aaccc,95b84e3,d8c41224,c74451c5,ec8a23ca,35436798,c2f34ad1,b1cd095,2f0170ce) -,S(b82cb5d5,2e026caf,bc075968,6e1c6c18,206231e4,f25c956c,b3a05690,8c72034a,6417cb0e,f1a18ad5,e1a2a5c6,945f3b38,b0522ac8,70188640,80a0f33e,2796b042) -,S(47d70d51,e97fad87,fa0b1c10,43246c0b,32108c36,734c90ec,9de5a2cb,c6227682,6d5a2cdf,e916fe8e,8b45d5fe,14ce650b,79a3cc9c,e4f99aae,2e9c449a,a79a4a08) -,S(13fa7ee2,5ea49c25,200b40e6,b9232eca,16dc6840,4f76b43f,510c8a12,d520dead,2722287e,35c9f98c,6041cb15,845d515c,870f5943,74a1ebd7,36f973e7,5e6dc30d) -,S(c1350b7b,2a4e73bb,90d36674,771d5537,1fa647ff,c490726a,3748e7d2,e72fa7a,2370f4c9,403ba7,8e950274,bc1f87a7,bc80c1fe,7618169d,5c9bc5c4,81e1badf) -,S(dfe512c6,f884588c,80c1ea7e,1da4b3db,ab8d4beb,60749f40,9402d583,ac793e05,b52da5f0,333b904f,678dcd37,a890b79,e985dbfa,b501e61c,89930678,5a0bdf09) -,S(88da191,2face14,e6f5ded2,30d303fc,867f9b26,d85c2299,bfac1a23,9757b34f,4236025e,f82eab9a,f1fd3c12,42a73cb7,fa305e5c,ef6ad5ab,ea62cb8a,4d74bbc8) -,S(b7a82133,7cad0eb6,c1de7b3c,8aff8798,8ee936c,921a7dee,1434156c,c6505abe,d03b693b,4fbce189,a552a66c,3ef4586,35454006,308c40ed,c7dbbc29,75361b7f) -,S(44971116,c14d80b2,f0f88829,fa1fac44,ac44124,11ac6e92,fb898e72,a0aa7ed3,9171395b,3cac83ba,18e9a0a0,34fec786,986534d,667b0521,801638ec,e19343f9) -,S(95f0aa61,8bd8573c,81b2dc3c,aa16b577,6ee636a5,a8f9c963,b8a45370,7f35a618,7f2300b3,90006ec7,37365423,2b488d72,edf5192a,a1d5afc9,4bc95a18,edf5532f) -,S(e1bd29e8,778a30e7,d9d91da2,3db2da23,bc2e8d08,d5cd170e,8e753e3e,917b728b,592894f2,114c11d5,f04dd5fa,6b341cb8,29c58e1d,a7adb51a,19d881be,39f87eee) -,S(f6110619,208f64ea,8f0e8164,1ffe9f32,8e706427,87dcf8c9,28ca8629,adb99e7e,cff63452,a596744a,75c5e8a6,badc4937,e6f2c860,39196251,30784499,733651a4) -,S(4a3f7c9f,1ba0f01f,d6d42aa4,284e4481,ed1433c9,3248da63,76f25b62,d2d2348b,dcd4c18b,2ee4e447,3515c727,1467e6b3,86b6e640,834598e1,4ce3f679,47f5c2b3) -,S(50fc4d78,3964a68,b26689df,34d996cb,6f229f2a,ed017a98,4e027407,5fd730a,7ccd6964,c6c5ab52,5d31db1b,ccefc3e2,7a0882b5,8586a955,b76c754,9698a7c6) -,S(1bdc6b52,e92022,229cb15a,6436d601,26c640da,bd9697d8,bd0c49bf,606ce554,1ddb0cbd,e7b0816e,b65d7ea3,98da0744,b3ff390b,d2e13cbb,f8fe85eb,8f3d2059) -,S(62dac912,48f29712,c3126524,90db807a,af92d3fb,36117f6a,f5c7f5f,de317000,b3bc4dd8,97a2fcf7,483c0015,f793810,29bf6f01,7be37530,18b55e35,4250ee0d) -,S(ea552caf,1d0810ff,24eb5089,31b57573,d8eca976,2b314f9f,38301b04,ff5e2193,68181368,108c4fab,7c58bcdb,5bac3a3e,31eb1b3b,837c7ead,e691b56d,e24aa832) -,S(7d6132a0,9e2c0af4,9e3359de,a750551d,7addad6,8bdc602f,e65af48b,bc1127a9,5bf6234c,903e5f72,45b46187,9d780ffd,72aef438,c0b65c7c,d0b5fc2f,8ad29d16) -,S(916d0d6a,3d08a94c,604c34ae,8c930edb,5ad57532,4dd5fadf,7a4841b2,775c475d,e3cd9b7f,79572001,a1ad9c19,2921ede7,64b12210,4d4d8796,a435eb13,d883d391) -,S(804128a3,d982b50d,203135a9,c59449ec,c43ebb35,b2bf5266,6b710975,a3847524,bcebda70,4364414,dc269d2,6214968b,95ad5bce,239ca9be,f10fa1bc,d6f31757) -,S(850314b3,4898b572,5898dd9e,f39196f3,cabf4026,8248844b,1c3d2f55,a3346f2a,eb8d17e0,3c9f7fde,29276d95,c20b657f,af2173e3,7c620a0f,d2ea7ab5,f4706b33) -,S(fd879539,8c0ee90b,89aa731,a4ab60b7,be0375fb,59932879,7bd73390,58d7aa8,3fd62aa8,35d10f6f,8bf3338b,b48bbc33,8f235cb0,6bcccbe7,56716129,abe8159e) -,S(51536953,12e7c4db,bb18ecbc,26c51224,8f841792,e557e879,8eda9db2,c9840357,175d3e7f,92ddce9e,5595fc26,725f2c09,fc322b2a,251fc323,ad3c6f08,44badaca) -,S(8783f2c5,f7325f73,e5941ec3,5f91449d,558e31f,28af335b,2fde477,86aa2808,dc602736,ccef3e41,60b100a5,ef99c6e5,c59734c3,42b545e6,21d9b03,daf0030c) -,S(c871ab31,4afd8d5a,a58a0cc1,a5eb49aa,f25b4b3b,6e0ffcf5,38851576,27c0726c,d06b7e2b,f44d36aa,fcf653df,a675bbe1,36a18938,60864df1,fbc9e604,5a3707fc) -,S(40efd5c2,1a9807bc,b34a44,71066619,a2bba48f,c306293a,ab59d9c4,b30e9b23,85cf348,4df34dad,2f7aaee7,b8a6f585,4de1314c,215f6f0f,e5a38e61,f3decad1) -,S(7feb5d9,844798a0,2413cae7,cd791e6f,54250fb8,12f998ed,e0ea6eb1,435986e,d90ca7e,8e800e6f,fd0ea027,b8a379b3,9030a03c,7b111d68,465d2a05,99dd358d) -,S(1b2da7e6,f9fa412c,ec873512,7328f1e9,ea77501,5741a284,12018290,76a79b2d,9fe58682,ba3f6ee0,c7b73933,d14ce656,e3fe49dc,ec7a5643,efa07a3f,1a4f26dc) -,S(d7fc1f3f,7a6bcaed,1a84e8e5,7127a6f6,37d935a4,35500e21,47e8fe03,d3b06066,29938603,d89fb118,14d33850,451f5c1e,bc5a5943,70c2d8f0,1d9bed34,f0b2e940) -,S(45352264,1cd962bf,35d8ab65,3d8d6c97,75782706,1454a2ba,3d957152,e177ee5f,de5005a4,3989b6c0,cee0a71,b534137f,b946b262,bfe353c9,6a217c06,c23826b9) -,S(91733546,dedbbc4,c7c32af7,760e0a4b,c2bdf82a,73e2a91c,2d70afb1,100b84ab,e60a6ca6,f2a5b12a,307cab41,8793b7c8,b7ecbaf5,18166c61,acee16ea,83071a3e) -,S(26bcacdb,bd4cabe3,e7adc5b9,27465ac9,616725b7,dce240e6,37117a5d,80a9ffb,172208e7,6603837e,4a9cfeea,22bc6002,a5cb8f1,36d73dd7,ce30d010,acc05db5) -,S(18b520f3,e997b5d5,46a1d81,ad95c52e,7841f14e,11e9d677,de918fae,7bd408d6,51b0cc1d,4c6ec5ba,e6c587d0,d6489663,dcf74bbc,d93c4839,6e4203a9,caae57e8) -,S(e25c2492,b7b25c37,cb88da91,cd76021f,de8511cd,27188b0f,d4bb4fe3,dd845e8a,244facfc,a7dfe65d,6e1d1d84,9bec4e4d,17af0d6d,2611333d,b8b7498f,96c88bd6) -,S(97e572bd,300d9649,b9de3c8a,b02d4ce3,bfbe4ba2,68844329,85971951,5c34a535,324a34a9,39004c24,b2e55e66,83577259,6c9cb2f,84378bd7,e77806eb,75e77070) -,S(4d31f4b9,42526f1e,769bcf70,85f39523,60475a0c,3f8d0a4b,c1fd6a07,a4765fda,27815d6f,3b083965,8fcbb540,925986d2,bc6d1fed,d1c254e2,9580f413,99afa899) -,S(7344c521,23968b7f,7ee12500,e9efa4c3,859a72fb,cb1cc9d7,af91e6b3,b5bbe152,4794848b,1541a965,b7527533,a6d43398,d619df34,2608021,a26bf9a8,76e0e4f7) -,S(1d099181,8da474dc,38e08fc6,d97ac823,be34f4a9,81adee58,806f68cc,ffe1ce9,f5449d7,c69816bb,6f04b32e,69e46771,c7910f3d,77cee6e2,af75c293,119f729d) -,S(84607e2f,ab205637,4b708486,51e84966,9c386eb7,c6855a1a,837c8fb8,5da8e7c3,975b5227,26e4625d,cc5c55ee,22dc667f,1fff7c4e,417cb4b1,45bcb3a4,53180ac3) -,S(3d2ad8dc,11a9103b,2f03b3b6,24d93114,83f4faee,c4b9bc22,f4f8f559,16bae70c,b4f79cd7,27d433f3,72735afd,64ef4da7,de9ac35f,98b3b6fe,5de956a5,ba93f9c0) -,S(2ad5f6ad,c7fe8540,8b9bf547,a564727f,374e9194,460f6037,ee299f83,e842c883,f613f0b0,8e306fa9,fbf39919,e3040d16,ede4dc6f,9d45ce42,e63f4b02,70832f9) -,S(ca92aa9b,e8893819,e49fc29c,dc98a42f,e23084d1,fcc37d19,3e9c638c,db0f2f93,462a5ee3,2bcdca5e,c6bf6819,32ded511,12ca847f,7e110405,a893b011,874a66a2) -,S(4e435dd7,ce2783f1,5bbded75,e832665,e4b4cb00,b50e2a69,d986d2b6,d3d893af,cddec0e7,1615f7f5,769cf2d,ee649723,1218fd34,91a07fa1,fe619f2,26673042) -,S(b1d936c3,fa1fea01,e3e28332,51f3790e,1e0f0038,58656e8,af53a72,118cbd6b,183b67ca,8039f372,d04b685e,c515466e,8ca1fdc3,7b2ae8c1,ebc5fb02,9c0ced9a) -,S(77282290,d994b6db,10b06247,1b86caab,e4524850,22a1e63a,682f92a1,ae65019c,feff37f,1fee0cb5,569db439,a7697327,1a2e4254,a9125ce6,cd94fbae,110f6363) -,S(acd0184f,18bb7c72,f7b6ac5a,7ba3f617,c40e159b,a3dea242,ed8e6c23,ad89dc82,3ab71793,fdf23305,aaebfb52,982a2603,e56d7b3a,5430585b,557d3406,42fddfba) -,S(933e3401,91e41c37,69b60410,fc0ac56a,e5bb44a2,413921b3,d25a52a7,14015cf4,ad3aa53c,76c106db,6187f4ab,755d077d,c6d878c7,64181565,77bd5d3b,affad12d) -,S(6e02abec,969eb027,bcea0303,6648fe60,da6a7c67,d1e4df3f,a34c1225,36de6fa1,c0283bd0,9fb2bc2b,19bf5086,f1eb5c6a,a7dfa258,64c73647,8a6cf0cf,c5ed5c14) -,S(2b86559e,82e5ea58,423163f4,448327f4,2429f1e3,14097621,667cf1d4,f0af1ab3,35bcfa55,9e2a71aa,4ea25edf,f9e1c59e,2274ade5,9354e22a,9cff37e9,31258107) -,S(1c02f45e,5787587b,9d68df04,66df67c9,552301d1,3b32f50b,8c9a2d5b,c826606,5f5de968,b39e9263,c1624aa8,811a4391,35150e,f8167698,c381388b,18a232f7) -,S(d0a65374,7fdd0c5a,68c55060,dd4ed734,34956730,1997d07e,d333b5a8,79894eed,272fe0be,bb192ec8,9f2f64fb,43f3a3,cceff7d2,cf92cbf4,4ddd8fd7,b104b85f) -,S(bb48b81e,e0dffe05,b6b8d05,5e1d2e5,37481eb8,2ce2bb81,cfdfbcef,bca5c6de,717b99e9,63d59e1d,66c0737b,9843231c,9c5e1bfb,26820215,78e8e01f,9e5a3fa8) -,S(23901c4c,625d77bb,1d390891,6befda04,522c698d,3c4e82c5,227c3975,3d7bc3fc,2434bb8d,98ebf9bc,42459328,464c4a7b,b26f258,2d454209,af66edb7,e84effbf) -,S(2a150d7a,961b5c28,434cf4de,ab9bdd3c,d019f667,67437158,c0f3fc38,54de70ab,e0d4756,9cec0eff,b155d7e7,37ee49d9,863374b2,4c6f4ac,876a80f3,7fdf7461) -,S(d42bd53b,1de9e41d,6e5ada81,3b86370f,ec1cfe1e,cc8ace39,edeccdf4,e16e7111,e3d4de0e,e5cb0d3,e3dcfed5,a09dcc,28c9f1ec,969d70cc,ffbd34fd,d0ceca5c) -,S(2a865f60,413764f0,d50adde6,4825eed1,134c6875,d1712396,938cd8ff,784b743d,4b628cf4,8e2a56b0,2142bf67,8829a388,929a0c0,5784426c,ed114f21,ca1dfade) -,S(2189b2e2,e88054d9,c71c2321,8cd229f8,a0165a15,650d1557,3eccc450,671817fe,6b9e0fbc,f9b9c354,644dd8df,3ec14217,66fb6783,5c698a1f,d598d074,aae79d19) -,S(e619a8d8,d63ce9ec,7f11cde4,1cfd33e9,62884fd7,471a4e67,9b9fd1c6,8537fefd,d819f364,5438c886,915f46b,40fb5c6d,6932077d,6f9726d8,86b9ddc4,d5a552a0) -,S(80c0df21,91bd2fa,2fa21bc7,ea86e54b,ee25d9ad,43893869,1cee20a9,b5792763,b27d7eed,198a695b,405cc3a,9204242e,45833ab,3b9feaea,f81db33f,938dde53) -,S(cb3926e1,eaee7f44,6f2eb390,64d4ced3,cf8bfda7,9c54a25f,6894be15,61c2d02e,35d9e098,6612e1c6,fbc2dcf3,54022f34,5b2220de,139d1ca7,5dbaabe,46c69160) -,S(82e82221,5dae0056,917680ba,a3233d29,23a2a0d0,68939d9d,2e2fe013,9aa2a8b8,f28975c9,b27352f3,f6a2972e,ef33eaf8,5d0d0a4c,673e3495,afb71869,e768bcfe) -,S(6b48f2d2,d756c7f1,77d5d33,cf62e419,b32fe0e7,352e84d4,d3056571,fd837e52,d4741717,3212dad1,b476b8fb,7ace774d,fdd545fd,6f99ba1e,b701018d,f762ad14) -,S(6cc8e1cf,ca1a026d,c1db0d97,46029b6e,b9895d7,61f66549,4f29cafc,1243b56,429b0dfb,ca05d077,d4d87022,d5ab333f,d9068170,5e246fbb,6861bd07,7e85b500) -,S(fe3de551,3fc157b6,e5bfbe45,d88f9339,71ff5ad3,c436ca5f,21794899,33f01e9,a50a9cfd,8aee1546,c422c5e1,494dd42a,db36bf43,89bac501,38211c21,803be0db) -,S(25140d46,a9453d6c,9370c901,6cb163a5,a5faf371,50152526,b01c7454,56b995de,6e00dcdd,82ee197a,3d5ca028,86fd7fee,56319f7a,925a39b3,becba6b4,c806cc11) -,S(4b9c4d2f,bbd879a7,de69e578,a2ffc7c8,8a0c700,f27f2e7d,cb8e0c2,ba3654f2,4c876a6d,7778cd81,bb02c450,5867d448,c78e9884,c72af037,55a66d7b,848e248e) -,S(2c11d305,3eb4b59d,8e8319bc,2b62624d,b97244a4,47326f24,6b83e959,5797c2f8,41e096b6,a1d2082b,c852782c,74a02cea,55dc09c,64b9d19,1265c1ed,9c306340) -,S(9a515c26,394d56b8,77c2b70e,ba1745df,9322810e,63c379ac,1c2320bc,48baa2f7,5ccafbd5,d1dc3d86,4a7ac805,adab05bb,5eb27f8f,dfabfb1f,708b2e8d,42e097e6) -,S(791a6bbc,91321ca3,6e017798,1a611cc0,db9d2600,34d2c26f,5f6fa5c2,ef7a5fcb,4cc5b203,db4459a1,f396cb31,acbaf9ca,18446f1c,cfded245,a3b32100,38417ba4) -,S(ad40b691,d3eb6ee0,e22e6d7e,1e0eafff,7afffe6f,2e0e3b75,103001f2,3a9653ec,ff7b436,47c2e09e,84f90910,2b2abe7c,2d38dc2b,151abd2,4f92d214,5607cdb0) -,S(52eeb361,405a56a1,331e3fa4,b854156e,7c403961,240f6003,135df1fa,8f3e475d,128e88f9,1f089e60,61d3df85,fcb2c50a,b0e67ec3,a7e5b3c7,ef1f53a4,5d5336c3) -,S(fe1a5ff5,162731b9,7b4423d,ad1b5169,5401920a,6b1a07c3,6ae9a25,ec3fbd18,22076aaf,ee720a1d,96e0987a,c7bb8756,b04a6b25,ddf5823e,e2f93ac9,e54c85f9) -,S(4c64f48c,fa628f72,b2897c28,4411684f,c0795753,60b8633a,188a89eb,e7fe1ea0,2eeabfd7,1b976ac2,acff49fb,bd029ef1,a42344c5,489334fd,393cc4a9,c305b4d2) -,S(44cbb9b1,7ec26b5e,3489c17d,1da0776d,539d2efe,d9317987,b86225e8,77b4eef4,f5c58a8,6ef02531,bcffcd80,ce788f5c,e43f5ad0,37e940bc,70d8411d,27c32673) -,S(2a5a456a,99eeea58,761c8802,7a86a310,63cdc681,b4ba0e2d,e5bce690,db8f3e84,7c3a47de,ce538330,49e998b3,4415c46a,2ac5c633,1a074e8a,8b4cdcc2,c6d1770e) -,S(566c0ddf,ebb82deb,bc867f76,e2fc5ce4,71249a9d,1b659237,2bfbf9ed,4eb6bf04,76989cd0,e0ffe1fb,a5992e71,50272abe,8a483f5c,6bff023f,3e5e1265,3598bc80) -,S(6fe42288,6d5d8232,4b229084,b1b2924c,b6c45080,3aa095ba,aeb2dd14,7b6def9f,b3b394b3,fc2682be,6e8c1e5a,ef2c87ce,eebe8d98,31aa60d9,ead74896,d7d9a38) -,S(35b45332,b65703f0,4feeaccc,39e04e1,72e58555,db94f04b,1899d835,9abf996b,6643809e,ae897680,5e37891d,3a241094,27ad6dc5,48429a07,64e2e12f,e89c2d29) -,S(17288055,5c0c5643,bd740b89,bbe47949,58ddb0e0,786cbc80,84d64ff7,838930da,f60cda88,7f85da2,3fa719f1,29aab43b,8b9a1578,53f91836,3fee5bd4,fcd16a2d) -,S(76eb57a6,c2d7bb45,d6faee14,4ba7c798,2d8ab2f0,5240862,aaf32c22,77dbc985,ef7cd7e4,d10ab9ce,4551c6ad,18a3ac6a,bc851768,18fe0805,f1c6107a,5c8c291e) -,S(1e5b38b5,81ad0859,454370f5,2f636726,5987e7b3,981af60f,a987c4c0,2440040b,d9817e99,89af200b,da690446,df5d8681,92808bee,91ba077b,400e8de2,712c2ade) -,S(ee17e98e,12a9efb7,c27aee78,15da31e2,af0d3294,40e7dbe1,9783caa0,2bef5709,a78346df,4d7dded6,9146931b,f1ce1b6f,1aae295,50a877ad,5f2dd0e6,adb43e42) -,S(bd574652,1eec6a76,7c2a14fb,15c85590,f7a19e12,342d09ec,67dd98e1,7739a81e,f26894f2,b8eca34,493bf871,dd6a133f,efbf1ab7,687a15fc,336d885c,6f5698a9) -,S(63852cb9,391a1ee0,23947718,b27c51a,8f9a5d0f,2f707f2,d0afd728,6596aaed,9d7c8c01,102abe28,43a7cff5,a1b15fa8,b56f50ed,1a034963,2e867007,e946d639) -,S(6c3fb2c2,d49c1c29,4eff674,158a3971,f65010ce,93f53614,ac9e0497,e31c296a,ffccd06b,98cb8021,589e833c,9c8b3b38,67850545,7e8dcf2e,775bbc71,47243707) -,S(3c29a60,103f7f0d,6f9a186e,48ac242e,46a525e2,380c4430,609f26d,6c3559bd,9381e8a8,7b4bdf9b,361acf28,cbe43e1f,a8fb073,ae2d1d09,6df7813f,bbdcfe22) -,S(bb76e94f,6f9ceffc,53ee4b3b,e27d99f2,d02eac69,8a4865f,9cb0293,a68c5eff,9ae48507,33f5984f,21726a37,c6ed7a79,e832af6,83afa20c,ee5d117f,63ab7472) -,S(422fcd5e,d2774d45,6d5f6312,c716582b,c142fcd1,342b71a3,d729643a,d022b492,b6d75412,aa9d6ff8,9be3a0b0,17384764,35ad4408,b544b53,acb5ba63,119b6bc1) -,S(328db4a7,9fff0037,c79aedeb,e8895e37,75b1e6b0,4d0a7a32,e2fcabe3,29c60dcb,40a2fab2,622ca3f6,39711923,812d8687,9d92b15e,ceaf5855,a970cf32,854b8970) -,S(4269bd58,abcd5e92,c62b0895,1c5ae948,efa1c96f,39ad3601,5e28d809,74da818f,1d1412ac,57ae762a,c3918ee5,33577c29,a8e63afd,c33b69d5,e6758416,6ff87b65) -,S(6c08ab40,97320e51,f3c571d,3beb7d7e,cfb690b7,af3d449b,50bfd276,290b8830,aba73078,edbed082,2164c850,5ca4bc58,6e53b174,83675f9a,26734cb0,747320b8) -,S(f4929f5d,99d0a5a7,3d20a223,c84261c4,6a085af9,fae2fa8c,4a025489,30174c22,afc89b10,7a38c32c,a24e947a,d8efd761,cad69f7f,ce0d595d,d4cfa849,201f6178) -,S(5cf5baf8,726c125b,e1499cb5,3f33bc0,37c983e3,b03f37af,6b48f3c6,29827611,17bd2e3c,d12adb0,5502a9a3,aa418cb8,c3809868,56d00c5f,319c34e,66074a65) -,S(c4639023,b41d90eb,2b275a2d,b7ab632a,592535ff,b439491c,f0e4e692,8188904f,738e1a93,5ace46a8,fb4f6ee0,b9026314,d8c243a,8fe08f37,b23b9c11,11763de2) -,S(a21b2fc0,2a60cae4,e694f206,1bd083be,5ed681e6,53af9271,a8ef9983,5807ce92,7f80d5e5,5a684392,939d6d1d,537919c4,99e799e3,4bdbb27c,b3d79587,f08d5194) -,S(7841ddd5,80f9f3a6,e702b0f9,3e1a4158,5e2c10c8,fcf98add,2a0f6286,c5d285b9,4dabb8e6,2aef6506,392b0fa9,4e2005a5,ad03c4fa,5fb6de65,2e89b31f,6e5ed166) -,S(5d5fccd1,378e4983,8d8b05d,41f89660,1b3a7c0,58df493e,2a74b55f,d8210356,a7e7b0ad,fba08a37,6fa3cbe2,75dcfbfa,bd0629ec,e8a5830d,d6993ec5,15ccf447) -,S(7fbd50a7,360c09ff,fe55369b,fbf6be2f,70cc5965,340e0489,77e01b68,2ab6c9ea,17ff93bf,4fc95325,26caac54,89e22f4b,265f63c2,cf46ff6e,a5b1d387,98a9b72) -,S(d6c8bc1a,479ea533,e99afda5,95365a32,cb1f3a26,72b4b960,2e039494,5b379061,cbfadb4,a6039cad,67ded1e8,8513dbf4,bb1dd3e3,437c989a,1df98b31,d234975f) -,S(5753de48,683d633c,11103cc5,b1bb04e1,5a935e99,297c73f2,fe851d91,5d5ea18a,10ef5d7e,ca1580b7,31ed4fc,3cd606b9,e6af8b1e,dea8bcc9,b91d522a,af361376) -,S(fc0d0265,b6cfdd0f,6b755a8a,c87f0ad5,b5a19894,5348c719,e9593566,91a638f,c5f31483,3c166c18,8c62415c,e58297fe,157fc6e4,b8e36b16,ce28cc75,df9017a6) -,S(61570f72,5b030b63,def84933,d0d25039,cabc8853,e5185302,d3f2d3ed,2611eea3,b3edb685,379c0068,9e9f522b,a5ad9163,9df723b6,b5c3eb96,3b05e5e0,a4b8fa15) -,S(5fa72a54,36b2b7eb,c15b34a,fefbb908,acbada63,23809159,66785d12,fbb3d6e1,1c027ed3,a34e892d,4b3d56fa,7a93ac18,663e475,a16a3d2,fac0ec90,be6d9ce6) -,S(5296b2b3,9f179516,d3cb85bd,5b86a9fb,274da608,be6e95b6,c44267af,187e2371,728aa26,e5869775,9c392558,34d00992,73eb6986,5db38b3e,df87f394,31c75dbb) -,S(b145c8b4,4c3f3c77,658899f0,a5b97c4b,dc2b195c,aa56b328,e0535217,88c80298,c73d96b6,47c2e764,e36caa26,8ebfe40e,c07b1e0,947e392f,be2a9095,7dba2595) -,S(bb585531,3cd05f8f,7fc96d8b,6e5194fd,2a70ff55,e7a7c067,cfbf54bd,129d87c1,31ed0367,8d24c231,8c4295a7,90d31094,e54ca68e,47b289c8,45b2f638,64812607) -,S(c6ebab34,ab48c0aa,aa5243f,c82a90e1,9a2012ad,74c925f2,e4e22f6b,13d6e5e,8107a95f,28e11f9b,bcef4b22,c4228c0,b530cdac,1c977640,53828b8a,15fc065) -,S(92e6ec9f,83dd27e6,3be3b0bc,8ebc521e,d84219bc,177f15cf,1bc840d5,be2b551b,931aabb1,5b3479bf,994f7eeb,34871b04,81efa404,c40e063e,59aabb77,2553ac79) -,S(280280ef,424f01ec,3fff321a,61dde1c3,4e674a56,7142c8e6,643ad1d7,e2dc4d51,84710eb4,5a88503f,b1078d06,26522501,fc165ebc,ce3b90a2,925ab1be,3c9ebfc4) -,S(6326eb72,abc4017e,c3f55af7,6a50a4a8,d0074ce1,2f5c9e08,146682ea,e406d047,53dcc346,7b61d08a,204a70b8,7658e4b3,c4016c8d,b5f03004,af6b545a,60223871) -,S(6e59dc29,408efda3,1bcd7b05,276b9f8e,bd9caffc,7f22c207,61f9fd0,a281ecb8,81c60999,45a6a834,8f2bc7e8,4ee002af,ec5729dc,aeed8187,87060c68,c2763887) -,S(100b0cdb,ed05ba0a,fcfbedde,94ecb25a,5cacfb8f,bbb80fed,1a9d87ab,72e4b5d6,1ac27087,8d6764fc,ce5f036e,ea50294,cf38c4c9,1ca9c3c2,87718505,491e11b5) -,S(95865771,e313a1f8,5629585,7ab9aafc,68a124b,6ae61f1a,a7b6e9f5,fb5de6b4,1c5195a4,338bfee5,9910935a,f5fa6091,7d06a2ff,3908fecb,b3fbe30,b0b52b41) -,S(6962774c,9035ce5e,fbb8e715,9d381004,a1828d67,38082e1f,45307ea2,d1d60eae,e9c36d21,6a2acbe5,5f9f9535,bea4b38e,7b75a149,3a281e4e,11b19064,e282c036) -,S(8e0fb8c0,d2d7977a,23f19efb,aec886a7,5170cd08,6a035386,ac784b15,9fec90eb,1218a3d7,6306cd4a,b3debd20,9bf9238d,ce00984f,47b5fafc,b715e2a,655ca9d9) -,S(6e9ea5e1,127c4c60,a01cd278,ac1dc091,e768acd,41566200,47aaa32a,e9cdf5e4,bfad3214,9a299887,c74bcb20,33e01704,ace7c646,eb00dc71,fd1e0461,af05a6eb) -,S(60fd55,9198e1ce,86c401a1,d31d04a8,fec7da21,4efd01d7,f2081027,1c49206,4f234575,cf4e6150,16ad551c,2f8e7635,3718b626,70ed30c4,a4c15e9a,488e0755) -,S(d413c7fd,2c2bd34e,2ab3e871,38495543,3b5ceb32,cba0e9e5,1e0ce198,cd5ea806,b585f836,7ef44ee1,8e32dd1d,95d6f8eb,555d8e53,451e5d8d,1cfca993,b23e344d) -,S(e26a95ac,c0855b56,b702cba4,abcf2004,c7343cf4,72056bb6,161ac077,bfecf98b,36a4834e,4532fa30,eb1caa21,c1572c46,efe4f7fa,e3c370b8,3f1fc221,632f8c2f) -,S(f0541a0a,d29e3806,e2812aab,ac185a55,687e058a,eb17157,e00a1cae,5a9e3d9a,40e81917,4473fbbb,58d40f1e,ccb2444e,ca4a616d,b0efc710,8f887c09,dd04b4b6) -,S(db1112bb,394f5e1a,b315f575,e2cfb59,4b83b599,6c82365c,c2095bdb,eb7c3cb9,c53249ca,30eb726e,6dfdb792,4db693da,f9740213,d87c410c,afa3ade9,51f9f688) -,S(2ad80407,9fdb7722,c96abd1d,35e76a7d,30948c7d,7b1e62a5,ab0994fd,667103df,5289aade,9f71ef7b,dce049cd,3052f8f9,653a9b69,3876b607,7bb42d77,9829bbe) -,S(7bcd5085,eea0f429,238c23bd,bc14017a,f8dde478,9d99b2de,325503f1,fcf7e738,7338f8a,7980de0f,404764be,7fb22578,ee820c6,16044f18,ad12d4bb,4b35a2a7) -,S(85819e4b,348ef2b6,d141baaf,3297248,7f34b594,8d834249,df465fc8,29a83188,306e8693,e7e718e6,39f48a1f,7dd5d977,9da12288,ef3edc6b,74afb1a2,906f931d) -,S(8d035a4b,5905b0ef,7fd9b050,ac1c006,2c0a8d84,1ab342bd,9444d101,92ed4a79,1ede85ef,aa83c466,4ac1cc71,c2d4027f,632f7ebe,2a097d98,9278cda6,35e2e0a0) -,S(bdc84795,289c3268,628904fd,5d8ef1f1,a89587f6,652aa883,5e83c47d,c008c282,1d8342d9,e330c123,7e232067,6fec10ab,b19c0d76,744915da,9980a9a5,6459a61b) -,S(75dab97b,d9e6571c,afbd8ce5,ffef58b5,72b6d8ff,838777f9,21834b61,1079c079,d048e6d1,fe2598db,31adfa59,8a445f0f,7f97ea3f,dbf8fe92,f2aa495,ff033bdf) -,S(b2a4a872,4a6ccfaa,8b8bde86,64fef1fd,bf9d4edc,215f9f71,738885a9,af19b42a,9bec2c2e,76be8104,f2dc4ea1,3e1ec916,23baf856,a92863cb,33b2781c,35f9060d) -,S(caeb3a77,35824f9a,b24e364c,789fe66,4729fe9,d6577ab3,f9cc857a,e1c2bdaa,ad96c92e,e91cf44e,8f0480cd,106b115f,23f0a30c,fd6ab638,86ee87cb,ba5ed885) -,S(a897e41a,75e6bfb0,78c272d,ec320e70,13afb506,478d984a,b5532b04,6da0502f,136cff6d,896be55b,5da484b6,15a09e9b,13453973,79fe4157,64ac5b5f,35aab82c) -,S(a33679a2,dc5080d4,a77fee11,5de9eab6,d32e6479,bd4fa795,3e4a03e5,3242412,1840b712,9ae52592,d99ee262,a56ae597,37e2202d,2871681c,6625de82,7c57819e) -,S(3183fdb2,b5ad14cf,9e2ee00c,e23b2c42,dfbeab54,acdbf786,622a83f,4db62fd5,7501e003,2ba129c8,50c0f17d,2a16b3c8,602c5225,1bac7212,6d454cd5,fc35a92c) -,S(aa6ac020,42f80323,ca77289c,88dc702e,e354fe1c,eedc720,2b87601d,7641b00,3ef01b0f,8b396221,8c5118e3,2168a6aa,ac901e02,5610db0e,8cf2ab21,bb06995c) -,S(f952d843,386eeef2,64b1078f,d835308d,514bc162,559c8f3f,c8ab5c18,378b40c7,fab32d0e,850f4bac,9a4af6d4,7d15976f,2e6fcf3c,958a72fa,b8db1817,cbc5dedd) -,S(75b58bbe,a5a1d00b,40f2fa2f,9e2ca8c2,eb568bc1,fe5559c,7e40ab8f,a0148e67,7fd6db81,7359736d,26883e35,727f4b21,2813be05,8d5d2477,1563696c,feaaf021) -,S(504e2324,34a12a8f,a96f64e,d39a7c0d,4168bd75,1e0b6249,6b24ab05,eff49d46,3bbb93f8,3d2ee95e,2e2821be,c3d98f4e,1f2def75,b5f8ed09,6947c4a9,1c933ea7) -,S(563fe95,1482826b,38f21deb,207a30d0,21271292,8b53c790,c33080b5,c4fc14d5,9b875a5c,70ee8bac,9e6d7225,1981c9f6,c3b5bb49,c8772243,14c4b287,e990bba3) -,S(91ed3211,161cf1ee,96499e83,7baa574d,1f56b244,56fc1589,d61f4d40,dea01443,f1664cf2,578f5ff5,8d81c281,514c7f95,56bce3d2,2150db9c,6f4a4df,db73d14) -,S(27526d79,f92c2519,838e3e0,a9ebfd02,f66e857b,d49cd8ec,6deaca31,d6064be2,9e4b644c,5bf8d50c,96892f3d,6843c94,f9afb359,55fb10b8,6a2f166a,6fa17f00) -,S(3ad1833b,df1ab0,effb0dd4,d535285a,900060e0,f38555c,ffd3e7f3,392b5c07,5c37afe3,89bf6e88,b88c9a34,6ab5a0f6,2128828a,22b6f907,8f9bc6ff,ed5c311a) -,S(eeda869c,21a8911b,cf713c68,caf261d1,e7fc58b4,3bdb0fb7,e83e677a,ec3ff6d9,f58e7eb2,3a62a9ec,f7a13dd7,b6b6809f,5cf8bc2d,22af477,e002f2c2,9c44d444) -,S(c7a806e7,bfc982b9,342fd4fc,e8f34786,9509fb0c,f0f54522,98162dc8,ec5a398,ba895fb4,f9084463,3eac5226,e91a08c9,e83281db,c406ab37,fa3ffc38,421a3647) -,S(c59586d4,ecde0cfc,3a1f5744,45cea454,aff18703,720fb4b5,1cd7b0de,de79c9b3,1eefa71d,5e67d9aa,15231b20,966951e1,93ebebf7,ae54ea34,e84b7c98,7cd853ff) -,S(3b259287,5283a78c,5aaebc13,5ba13c5d,4e5a1e6c,cfa196ed,6eb7960,e7eed0be,274d3739,5757e482,1ee56c6a,f56c8acd,f58cb337,6bb5096d,2cff4e33,ebb3c1c1) -,S(d062159c,e511418f,ea6e9853,b1e8d769,96c686dd,eef71443,e994a347,3b90e239,95ca957a,b37c702d,c707a3e6,388532cf,26cd3db2,64e4e9cd,fe0aec9e,77ab27e3) -,S(12a2bd87,c4ca2337,7915bd12,3f39e88a,fd7257e9,9587d70c,a9d8fcd3,2aa7ce4b,85562f37,ac813598,cf59e427,106fe886,aa1a078,1170f14d,3968119a,9ed65e61) -,S(9214dd98,2737e4b1,585b3363,c363ef83,b40a3228,53d6c54a,f5b1bf1a,a21e43a8,dbc49c6d,abe985f,d95202b6,bb925094,8b98bbcf,71486065,9b77c447,396e8eb1) -,S(34439200,b0dd5b6c,4fe8cb57,2e26de38,3311a479,ee39ea47,221a179f,fbbc124e,b8c15197,1ea4149c,d2a77b4d,14cea316,6d70b971,a7f9ef3d,315ce741,2ad43e1c) -,S(396b4410,cb5a59ac,15fa6034,7215ac8e,4ce3490,4dd15b41,46e90679,ca3128d3,ad4eef77,94f0c541,e70fd5be,45652364,c43e91aa,34683525,36c8b1ee,c061cba8) -,S(8ee1b02e,3ddb0913,dc781279,6316fde2,4489c98a,4e4c3cfa,c84b4350,34d53d65,9a4686,a5241a7a,cd4295b4,f1c9f094,3f8991a2,b7edeea8,bc4e9c4e,47956cfb) -,S(78f4da51,26b42e21,1d69c640,4e128c71,cd08fb67,efac0157,3bf128c6,73bbf6e2,b3836f1a,e397d7fd,c88d2089,6731fe04,6a46b2e0,b617117b,161e1e7b,3a2958e6) -,S(ff5c1378,c8a233e0,5edeed70,e23bb9e5,a5eb65a8,4b37c6c4,7c0a4952,e00169b8,a7275aab,c73eaa15,22328118,68de268f,189d3adb,da113553,e3f9d36,7664a0ea) -,S(18ff6e74,87ebb21,dc935fdc,265616bd,d3a4bc2b,35037483,c911f185,596a93c0,34209cf1,2710b007,821ba024,f0491e54,bade44da,5980f505,37869b8,b410d0dd) -,S(3ece6ecd,1c52894d,90043c67,59d158e7,143c9806,658e8e65,5fa53867,6609b0b,4b1bbdb7,7ed6deaf,fba0d241,5f2b7993,89cf7df0,7acfb8a7,a22f42d7,7858c622) -,S(a5356c78,6cdabe6,a1c379a4,ca18acb7,b41fd691,c32c31ac,6cd0edcb,9fdc5694,ab8f37e6,d19af264,58ec5b1c,78f54a4b,877c9416,ad76b646,7e91ca4b,24f988f2) -,S(e5dffa5d,961253d7,f99445b8,f8d8aadc,5415c550,da64a987,ee604278,12de570c,401ebeb4,afacec6e,d41006e9,c60e0ec7,a4840c2b,c64527ad,80d640e9,70800186) -,S(12c46133,4aa32bb8,465c1e9f,afe68d91,63a7a9df,e11940f4,593697d5,fd0c9140,e4fdfe80,be2fa183,4c32598c,a096a5d8,15386dc8,67588354,300018ff,5b2e0c2c) -,S(bd8d9bdc,ebfeaaae,691a19ec,c20cca22,af76db4c,ee54f904,ee5aa8cb,2010ccd8,cd5fca87,4a6cc17,79658266,158066a2,840e61d2,28bdd4cd,f2697e19,7c6c994d) -,S(597d8ca,babc10d5,5402f3a7,48987270,7cd5d3b8,3356ea13,6c8c5135,cefe3fc8,bb21d384,a48ed346,eadc6ba0,2b1e2231,7b2014bc,62d17fa0,9196213,6e12ab88) -,S(3d91a096,24fe1048,dafae0e8,c693226,cb89157b,980aa490,a9a12598,e77d7c19,738fee86,ab5a6e43,753b22cc,d6a28732,65db5dcd,38a6be5a,6635e8f0,136340e9) -,S(44addcb,55d0870a,19682075,116c8fc,d8f49b5c,5ef767ea,aec513fd,8d71841e,5e126cb7,8d13c0d0,55c3363,b236bba1,21cc5618,40e3cc3c,e100722f,1cdbdb63) -,S(5bc89297,4447eb3f,54b7b451,6da3d1a8,f23d6d42,54ec7268,f3e9b2f4,78d88467,6d708655,6b679453,253df54f,68541560,b5e542ea,8f1a4a9d,a023d8bc,6baf9559) -,S(8fe4f040,553ba9ef,47a0086f,a8dbb75a,2362af22,a58e0739,7c62d2dd,2ed2fc40,b2d0c561,5afbbe3a,18fcd594,a8e91e14,ac714af9,e34938f1,74a2c7d4,2028f65d) -,S(e36702c,2af02461,4d5f65a6,b855848c,6d72709b,b3ffbb5d,f08206c0,9c481a27,c5558c45,9cc186be,665a54f,19ed5f67,983bc004,c1c196fe,80c57310,59f1505) -,S(45b0165,d5eb9c2f,22c6f2e6,3f2cfaf3,5d4a71e7,460a41a3,9d3708c3,111387d4,8fcc8dcf,9eba288,f0183ba8,345c4b08,1b44cf73,b9df77cf,3e94c089,1e53cbae) -,S(ad02f6e7,378d62e8,87d651a4,eaec6d75,9b15f4f3,b7e999e5,2e9e493f,7d765205,25090d49,2164feca,33270e1b,3b08ead0,fcbc7ee4,aca4b4b7,7e06d865,5259a63f) -,S(5684c664,de3844ae,90bc93ad,426bbf69,5f349b97,6080193a,710b6125,3d6fcb0a,c5138172,4fb53812,9dffe038,7029b209,946a913a,cbc06370,b3b58f1c,759ac8f2) -,S(cb36c4a0,f6d2beae,282e9783,2148704f,aea7bea8,af0abca,ac670a7b,3808a2d6,d0aaf774,d65b7eff,589afcca,746b02e1,edbd10b3,e2938d6,5a0bd17c,f71de58d) -,S(143e1741,5da8c61a,959643cd,bcbd1eba,169257,2a935eda,1d0e2495,6eeee4d3,c12840f7,7a9fb642,50d19be1,5f35199e,1da83a3a,54fda063,99a6908f,87c9beb2) -,S(b6292192,d471ab52,fee206cb,64bb526e,6b8519c4,3df9ae85,4e4aafca,d53c1509,3d6fb4ea,45ae494a,e2c4c776,29047e33,f73af147,4fd217c9,856d5d1,3b837c56) -,S(d490352c,70551c78,9951a057,cb02eb17,fd710a0f,27dceaa2,ff224ec5,3c566a14,15ef3825,97ee6d88,ed8840f5,9d496c0e,6685349a,f1c62c27,a32eb7b2,bb193fb3) -,S(4797be1f,7ae122c9,2193fda3,80dac3a0,fdc14361,110a2a3f,5beb9f26,f3d85449,9377f25c,591ca377,2ffcdd37,65ef9a3d,6fa7c2,79d18e45,83901795,2e5fa3af) -,S(fcf5b790,98cff1c3,b02be521,76e1c6c6,ac10bcf,f083ae4,5d26ead9,82839614,8d94f596,5b075d45,a8f732dc,9fbe679,dffaf0ea,d2c90d16,b2c7ace1,1de05c45) -,S(d7153203,1e8cf246,683ee529,b2dcf54,1a731397,89e5c354,3bffbf4d,f95f76f6,740af4a,40e7849b,a41c4dea,4b7e0479,ca377fc2,69db00f8,b484c7a8,c4c745bc) -,S(27946ccb,dba75dc2,23663d14,2b56bd9f,2e63cbfa,73290de1,8fb7e988,31b44330,52c0ed5e,abb069e0,84fd8363,dcdb9134,364dcd4d,87b46025,9c3460ed,63e04ad5) -,S(cf3ea523,751eff3c,a785884a,b019199d,2a0ccf3c,1d90679e,141d4e75,74e41f61,b38d0808,936a2920,ece323ac,a707e1e4,914b51e5,e54843c9,63abf292,88ef17af) -,S(d06327e7,917280c5,d8a5c516,7e0d0c1b,e5fd9e25,4c877e9b,9ae6b264,6d9a126f,c3cc3913,9d0d7b8b,6a6b0c7d,b48213ba,eade2202,544dab7f,9ae42e08,fc7c781e) -,S(acfc233f,28f98688,2ac5ea8e,61478f62,505b8b48,38833499,1ccad1ed,5ee2a871,244a188a,64a6aa7,9f74e940,8681b45f,88b5c65f,d120650b,1a25674,eabb338a) -,S(87fb09cd,b3b8a514,f6a02da6,1d9b160b,798fdf7f,3f05d7ed,25c1c4fb,84b19253,586effe8,c4252dd8,c225a6a2,8e515abc,e36568af,107f8c75,a941e936,acbf6e38) -,S(77225acb,8ae251d2,be2f48a3,2eff0c6e,4f558287,13dc8a6d,3c6b7bb5,de9538de,d6eb8501,2aa7fe12,285e28dc,3efe9cf5,b0cc8e91,6fd63f71,c28c3f5,60259a8d) -,S(b03074f3,f2effb45,5caf88ef,e0eca7d5,6f901b18,fd04c01a,f0425c58,1f13dd5a,c8e8c915,fe06d774,8ceb2da1,78816b8a,4db1d082,6df3064e,7a4b0f85,ae99d461) -,S(992278e5,229bad50,82c8c346,8542f91,e2761305,62a34627,b1d97aad,a5999908,56ef7d8,d360d7b8,5af0f210,161ad17d,dacebd13,c45b9c8b,34f1ac73,bd6a1ac4) -,S(b73a2eca,5e9d0e4a,ef4f6ac3,e9610f3,1c72c67b,6a152fb4,82681595,8d44be12,c621ee64,b03b17e1,a25f27c2,aaea43d5,eb2918d9,e0949306,d2ef720e,8975c00c) -,S(7f6dba94,39e3302b,e4f7e0b6,f2363609,eedb30e,dc0b135d,e4aef970,cbcbc607,61685e2a,eb8e8244,175deb0,a006b5c,4292bd73,40b2fa1,3548262a,db98a3d7) -,S(88f0e36d,345aaeab,e8af18a2,d14191c3,8330c5e0,d4e32c5f,c562e549,cfad763c,bd062c83,13e44ed1,891b8048,2ee93ac9,95a0142e,e0543a92,a215735d,1e94ac05) -,S(da3a270a,bc03e6e5,3f572a27,94c8075c,8ce4590,b1b626e0,8a83fba,45dab386,884b46e2,3ab44b4b,c3d09f5b,97994e4b,109f2db4,ee04bc77,6752fdc2,6f0df055) -,S(df346699,77cd82a4,8e3e1b11,6311a5fa,3bb0389c,1c500fd5,15573af6,da0b2cfd,2ecf1fe5,fcec27d6,35c28d58,5fdb01ec,2192c8a3,848a72db,f53b7759,7b8b3735) -,S(11a4dfcb,3a443c3e,259c9f27,e24ca426,6e08fbdf,e4bbedb7,2e6cae42,569b0116,7fc6c4cd,1e3a0e22,d0ee0249,d6940def,bd776bac,9da5a98e,23cb6025,42b3de9e) -,S(2ffd148c,132eba23,e235bbd8,f09be1af,dcfd6e4e,5f2f0b49,6e4fadec,b931706e,6a4def93,52d875c8,31794fb3,6cf0448a,8c9ab5ae,804c6397,cec41b0f,24583acf) -,S(109e1f3b,7043c5d6,fb822b8a,54c6949f,117e829b,4065c0fc,c3ba5e05,a79142f5,c976793,6c034671,e5aceabb,9b08f5fb,af3cea75,a7a4485e,6c08f7fd,a63786fc) -,S(bfeea71a,8bb8ebbd,ca6135c6,26b739bc,eb2ada11,9babf946,6db9f4be,c7406610,44ff78f4,76074ac8,fd7ef860,cab01522,750fec0e,4b86f11d,831eecb5,22d1f682) -,S(4d2b7cd4,6cb01842,46e7846e,d0572489,e306b370,81515cb1,8a7c6cd1,dfb51665,60ebb290,44169e56,1d10a8e0,a2971b69,82276f1c,e7d11f60,ad7decde,e1fe9c95) -,S(66f2068c,e65a1a61,ad95ff3c,a2f15f55,29e0ce3,ad522dd3,d6083d5f,793e0e5c,a95bef60,2bb89e00,98723b4d,7fb421a5,b2cc751c,e8862ed7,439c1b36,efba2f72) -,S(4908ff3a,27aebeca,8697ec,dd7d5483,c6e56427,9d78f013,129e26ae,2ff459df,4c5def88,b60cbb2c,a3430911,aa84e4fa,1055fe1d,921c8fb7,bbb83b45,62b0f5bf) -,S(f9a90175,3a0f4236,dcb612cb,fcbf3f31,d97a8e6c,cc4f9e74,3887407,5d19ecb6,ed3c6f61,259943d0,310208e3,dd8d5a40,a5bfa646,35fca871,a6df79c0,830e24d6) -,S(ffed50c1,2434484c,ae866c1,86b88550,b0bd02e9,db04657f,aa81a672,8e321850,f16e95db,d44bc7c5,66fa0a23,669827e9,9cdf4372,6fba5f4e,a3e28d86,33edaa77) -,S(8061e9b6,2dd9d027,d43d13bd,1361ef3d,ccb4e599,c8d3d015,1d3adccb,6c762eb9,d33a9196,419b283e,5579ac98,8c1b6e60,378fc692,69b18da,a38f362d,20ca6895) -,S(ef8d0e44,e8b6b5e4,857d3d87,c82b01d8,f254c516,fdd139ff,7b8d034b,45698162,8325ccfb,6da9438c,e99dffa2,92afddbc,e1a101a1,20955945,cfb1608c,d35e7065) -,S(a31af5aa,cbc4f6ac,aebb9abf,de164046,1b631b2b,8cc43eb3,edb53185,fc1822e4,c3dbc990,691987e6,a8c318d,e381202e,a0c2297c,f06668c7,a2f027de,e5118a2c) -,S(81e47ea6,b60a3819,2094e7f8,f7bb3f48,a839b26e,d2aee7e3,e159bb39,798cac0f,186a8c4,97ba163e,aa779f6d,a8cf88a2,9f5d79f0,43e6f195,9c14bb1c,b1a53967) -,S(e15af4c7,8c61227,ffbf080b,a3b1dc2a,4966639b,926aae67,f2bec480,5c1fd232,76fd417f,4fe9e7c0,96db39ea,180d38ad,2360eac4,2730186a,b1da32c7,33fe9a63) -,S(3a185818,fb47ffff,640f265d,a2c712eb,f7e022ff,67a21a22,a2e941b3,f72639e0,8d370a41,1f133f43,34534b15,655717f0,73293f59,3bd34c5a,fc5c933e,120e76f1) -,S(18e05d9,2f227564,b572069e,18a271fe,2fef9d81,14eaee28,adb0fd2f,5f078e07,75f390d4,6e8f464a,d71067bf,b0d6596d,a945ea44,c7ede2f8,a9082440,d7e9a263) -,S(7bb788b2,4f4e5d49,2af81fdc,2f3a0274,6eedc5a8,cc74d1cf,ad17c2d5,4e80a107,5b28450f,1cd8c61,2b73038,ae889c39,d33cd64f,d452ab5d,28810177,dbb6a28f) -,S(a156cb3f,e4425b79,3334e19d,2b1208ce,5e6e8fdd,78748c0b,a1116031,912fb9d8,b2571319,c644e959,ba401415,3cba9b3f,cd8ac2f0,f8fa1f04,2d59ecce,5de14d21) -,S(eba23049,f5228794,1651a922,f60bc406,aa15acd1,59eaaf37,d1f2cb31,e7d20b25,ac8f8df,155b2703,d65b33a9,af581a02,8afdbe06,f4927a4c,5546ab7f,b5b2cada) -,S(8203a1da,56c4fb7c,96816507,f99a9a2c,950da51d,af7d21bf,123402ee,a95954a8,913884dc,10a53ab4,6b2be70f,5e2d201b,4c6bb23e,b6644817,b4257664,ed2ece88) -,S(d46609e3,ec19ef57,97ef86b4,ec51b8e5,7a854643,f817e7a0,9be4bc7f,291e7795,e1b3a8fe,3cda0479,11ab8c09,ecbbabd3,ce96974d,8a309ba8,c38c1d04,ef730830) -,S(1ffa9ab5,8eea8682,76849108,9e12ee5a,cb0ea4fc,e6f68436,377e985f,fabe919b,302140c0,7d64e9eb,6ea74636,f9efff59,e907a16f,5c876658,2f4a242c,b52f1236) -,S(4032bf99,32057d1c,8b6a8923,1575d3bc,6e2d6d0e,e1c7aaeb,ffa9ebe3,bcd9a0e3,13ae5217,f9f70a4,5f626295,b30eba49,e9f7c697,e3ed7cde,95442a03,b7916a54) -,S(8d32845a,14575fa5,ea061425,5e48e37b,f3a55bd3,9d924648,209d26ec,b94a20cd,e0416169,8f1e1626,18ce160b,e8b502b0,20a5ab81,7853903d,ad7ea792,b76266fd) -,S(403754d8,1a0dbcb7,1ff4893c,a5551387,b73d64b0,25bb612d,5e2187e6,7acea8b4,134dd3d6,8d642070,cb7778c,7ecc8d78,5c1deeb7,2582e25f,5c58b19f,2f59256e) -,S(4fbe9818,60e5f281,cb1afa62,8e8787d3,28afae7c,fcb73637,e2d64337,bd6e08fc,31a10b4d,78155900,7cec4099,3b5c59f,4bbb2328,b00a7550,572a604e,8d55b6c) -,S(a5414064,747b2ac1,e8868074,3a0fb05e,7ef510a2,a48d4f44,4647663c,b5c48b39,4b3ba626,56cbe6ce,2f228f8e,88d00ddf,135d6b81,979286d9,ec41c81a,f74ef7e2) -,S(5af99ffd,9f27830e,6ba54e05,63b3bd39,4bd8cdb5,764f78ea,b103405a,dbf3a01d,f625b35c,f510f9c3,db948363,3b2951e4,b2209b37,1397bdbf,1d899a7,400a4318) -,S(7fa7dbf0,1b2fd3f9,3ff4ee6e,17115c19,1f663d95,ff446dc9,d53d3e31,c98026af,f8aa82d5,28f2ee61,1a71b432,d553eff,ff1aafcd,8bf18e3d,b6dfa38a,f33eff7c) -,S(4838c0c,ed78e7c1,e3707d85,7311b2ca,6c7a4396,5be4e363,d4a374d3,36324640,4404fc6f,1a6c1751,3354d364,ffd43bdd,61b874f0,714430be,8a5571a1,808b5150) -,S(309c59a9,b42b374d,5c88136b,43310fbd,fccd6ba,e439e7ce,3a9c5e7c,ccb8dda1,fdded8d0,661b8ccd,834e4762,db87640a,fb1e9636,b894dd48,e1b4fb54,863863d0) -,S(1cc76e1d,788111f8,eeaed575,43afecba,548785d,3d66296,223142a4,7be59190,560e4685,6204121e,402c977e,76fac50c,446560a4,9bd2be30,c6dd2c58,62ef357a) -,S(188e8999,b9de6190,a65cc051,f936585,9e7a0498,4452402a,3093b4cb,24116589,aca3c642,dec398db,81fab67c,d05ffa2d,948a430a,e26eaa0b,ec3b2cd1,20b01666) -,S(2fca76ef,b917fadd,88e30d06,d6f398e7,6803307a,b8ac9817,4baa2945,9e9517eb,186c092d,95755005,4292ee1b,986b55c8,ee3be8ad,8adb6387,5e4dc582,c1105078) -,S(41d690fd,b5eb4f10,8aac4bff,26eaf866,86489227,b6e59b89,25440780,10e3eba3,251f34b9,d69611a4,31fe9605,7be2e10,6d058db4,34e0c814,b0b8a0c5,f2e50b63) -,S(282f850d,344e63bd,abc4542c,66cf1f1,a6807b1a,19ed7864,82d06a6f,a03b1e05,de82333,48fc960e,b22f5641,5265c1bc,be290ed9,4ee81fae,248d4676,d38a1a5c) -,S(bdba09b1,c1810ad1,ab2f5da1,b628a44d,a8512221,993c83ee,4a9484fe,6416bd2f,7049aac,e507d6f8,d77587eb,b8759f51,1b7bb2c6,5de0481b,d82a2f82,246d229b) -,S(e7e238af,4639d3f7,e5ec4298,65aade7c,c1127f41,d04b3d11,477456c2,b155a79f,da29edf,1e3c0ede,5546ed8d,cf8fa801,b5bf0dc,720a02dc,d9d706c9,a9c6bdaa) -,S(53a635cc,4e24790f,3ec5c17f,f854e2a1,800b2529,fa882945,50a0d237,58d622f7,ae6bf987,2d3a31a7,4f97299d,2fbae146,58c32dfe,418ee242,2029fff8,166656f8) -,S(10750fa7,df634f7c,7d8bd73d,e056e48a,50c413fc,282748d9,f4d0b485,d0ac5c1b,fdc72a01,883f0ed0,52d97ffa,8e6935b2,3f684f58,5e6c29b3,702f5147,dc645e04) -,S(881e3e57,ed8f639c,5023e45c,4e843bf8,e7d13323,289f92c7,143faf66,a65c3fcd,12f991ee,3390b45b,af1aefa9,dcd20da2,5891ac5d,35073750,47836a0d,e75b4dc) -,S(6be50501,4d72c612,bc0d5df9,13beac50,bafefaf0,aac7d032,824a102f,25bb45f7,4a0e0d0f,f2477287,ebd8c221,5bbf3e33,fff7194b,4217f9c7,57efa361,1b3abfb4) -,S(2ca955ef,23ed3481,615d1f0,db0fe5b3,f0fe5f1f,1b7f96a4,bdf814af,c4a58987,2dffc8f1,ce4ceeaa,d09a7610,7ee08e48,a591a177,9de2c84a,765a53e1,808e3c78) -,S(250da25d,5be3561a,92b56f0a,a7ab8fc2,bf7398d7,aca09237,3d416615,6991a05a,b0e62549,ca492ef2,9ab753e2,62b9c3a0,10df946a,99a982ab,812aa48c,def60c81) -,S(57606839,4791a29f,b66f2314,73b6bc6a,ff383623,c889695a,910c1894,d9c060b3,bac9ea05,7285d6b2,7911b19,b32fec7c,1b25db58,ae39eede,f4aedf09,46c04ae1) -,S(46edba34,d53e958c,c3e4e74a,ba8bb4d7,c6266aa8,9fe804fc,e27bb8eb,cba98e2e,2b85a88f,136b201f,9a1747a6,dc55f59b,41049a69,f824e3e2,f7f00787,f687aa6e) -,S(5d4f6ce9,ac52d698,1a13e73c,3156dff3,918d5b72,5e42f415,a503e573,bd6611fa,4c633703,1de35eed,dfc5e646,e8b0f812,2b951fa5,343d7b59,ceaa5c85,e1ce5c08) -,S(c77db927,f7e637fc,24a38bd7,f605383e,91e4e2de,8ba5b1ca,baed4376,8ae120c7,347f43e9,47b5d13c,c7cb6fc9,fc2caa5,2991a0e1,bbd4bc96,d98ff26f,1a81bc5e) -,S(ebe2ccfd,ce91b78c,95cdd34d,79fc9a28,478c406a,224bfb4,668dd5f,197934f4,d7866df2,d346bd30,84ad837a,a0c65cb4,62cad5cf,3d23b0e4,bd260fbb,f4666ec9) -,S(ddc5f94a,d4420ae4,8ece780e,26940338,294b8929,549fb897,82c06e09,b7935549,25802633,a0127d73,21ef0a12,a2a6eb32,692f2d30,5e7d3cee,f137eac5,8896ff71) -,S(e4000918,46f79f21,71b299ae,6b93108a,9377708a,e7d3f5c3,147a98d0,95e876b4,c8d8c4db,8fdecd8e,fda047f,b92bd9b7,3c999493,27c491ce,df19718b,6152c434) -,S(4add9850,90e16b5c,525de57f,a15a9c38,97527b6d,8683e407,3a978cac,53b29b66,dfa1601,d36d2021,6efe432f,8a335e2f,42b6d645,7fd6f032,d727157,32a85dbf) -,S(8a5536ff,ff9c9dc7,b2a67823,5d60ad10,834c9029,bc243f3a,f10d7e14,4ca0a78f,72ee78e4,e0a618ee,191dc7fb,c1143e4d,70ffd570,bd50ce8f,d368ec29,c22bc926) -,S(9f708795,6233a0e,59757e17,5a87e34b,f7a7485c,94f9aa62,61854b4b,3ac62c05,ff9902b9,6a6cd1cb,6ea35965,3527decc,7827318,97b5c8dc,c24e2399,fb16ff15) -,S(bfa5d3b,e3fd56da,d8e70330,dccb79f5,bcc46cfc,220f4921,4cb8e700,e7cd0ae1,2a4870ce,aa2e001f,567ac21a,79eefe94,8763b5ab,c63fa649,8a5cffa4,126c6d0f) -,S(a965e34,47f07286,b91df55,3e4211af,e6b837ad,a9cc10a4,905975f,1983f2fe,393bb45c,3f6eded,b6de1e70,5a706501,cdd10ea0,2548279e,c75e4dd9,15f0da2b) -,S(e5e38677,c1e4a659,51358301,dbba1e3f,c44f5c23,af7011aa,5ab93ad3,c69b18c1,7939d32,de371524,c3b14f5c,745ea023,34f9222,31f29d8f,c8294802,b334821d) -,S(473453e1,80511622,cbe6df28,46f479c3,b8638efe,9af11beb,21dd093a,24d243e,e2b897f,eec79c08,5afb9daf,c9ead107,57d21019,c655d0a4,e5254a69,941962c7) -,S(fff734d0,e5f24c63,dfbc061b,bac37c88,ec5aeead,4974cefd,77f1eb5e,86219772,ef8a22bb,c29c9756,37c600eb,82ee5873,778d539c,a289a50c,5490b5cd,8ee0bfe2) -,S(d0508f53,85f92779,809a1892,43a58f71,47f643a2,a8f5876,510b191a,fa292dd2,329eae7a,2ee52766,a5a2874c,3912d777,e23c4aee,390aca18,140ced23,b8e82d8) -,S(93170604,98fb43a8,41d09d53,98807f99,23405879,be9f224d,52d21971,130fba89,e84fe72a,cd89fd4f,f7db1817,edab493,5f809b78,6d0c3448,f19505e5,a79e60a) -,S(63634cc3,ce570dfd,8bf90307,f4543528,e26f2637,ce32d690,75cecd2f,63dd127,bd12dd78,7ebe0ea6,661dc389,5bdb6478,7435e9da,5812d06d,d9188b47,e1a31939) -,S(30c7e2a7,925a47a1,5aa1e2a9,6f564e31,61b7a559,3af1a696,91088dc8,9ee64431,5ef4f2d9,cfefe53f,3dc76f96,1a04bd71,6aeca894,73553a0,1faeed0f,6bd2d506) -,S(f7b7e1e,d56b7caa,74f60145,98c18126,d8bf10ad,c37cf1bb,5e6c88ae,f9f6e6e4,a019d45a,7e091a62,8b7125e,d3720f95,dcc091e4,2ff17050,da596fdb,58ebc508) -,S(c6e9b0e1,177dedb1,2e19a0c0,d1167a8d,8095b2fa,1f2dc402,adef0cad,d5d87d3a,64440da5,2b3ec64,4565ad12,6f732ae3,c81276df,5ef15605,3318693c,91c12b43) -,S(653d41dc,e6ae6cb9,45533e54,63b50a4b,72f6efa9,7884d878,52c32eac,fa0f59e,693da28a,13a9cde,d1b7597a,c199e00f,fac2f6f0,6bb0dc58,940b6734,e5eb934a) -,S(b9830b38,f0f8d466,e363fe57,38124fd1,8c9f60f8,cdaf6fd1,a10205b9,5c7212ce,a3e31906,6ace61e4,ad861027,7a12d498,5c35969f,62e5573a,5bf4ac35,277cf444) -,S(94d9457b,eb2bf3db,cd38a667,adda8750,f449af92,6a92fc93,f1dbaa85,457182ec,ff1bd647,8f00626d,1b203da6,992a2366,2ca2b39e,f6c1528e,956d7d81,7e2497c5) -,S(816f295f,1648ccd4,360b1807,bfb9b05e,4a84af7a,140a1f2a,f4016527,1d4b5b80,98217f98,6ff6f38,1987db34,7c6d432b,f24b664a,bb47124e,641d0677,aa4ec143) -,S(3b830637,17254b06,16c1a5e8,999dcdc7,cf3cac91,67284981,75c6909,92e2b2d8,dc2d471c,5323eeeb,611495f9,cb37840c,905eaeac,a85cca33,76d24705,d152acce) -,S(33282bad,f48bba9b,3db3cab7,c3b46c83,867a63b0,db393ed1,2a4bf49f,cd2f7c5b,78733604,b1c94144,ab9a4886,80bc53ec,9d67c4cf,dc77af88,40bc3535,f2c42309) -,S(58e15e93,95c3abc5,2ea68f94,6e3f7943,b1ddcc8c,e258aca2,8cd9f5e3,14b257ca,d7c15bc8,53dedf6b,f7dfad87,bcac6e37,f90d32b8,344d95a6,44879ba1,e170070f) -,S(c9ee3e27,54e8c8a1,e99c39ee,cd3d0b50,f8fcd03f,ccdab94b,e503a1ef,b66d900f,a1ce86c4,7f78400,51c87612,1b26922f,2b4b2358,e302c568,da6310f5,14909db5) -,S(6e2621bf,dcab8898,7d50b5ac,b27eb94,b52cfd9d,29e80d2e,befb5478,a3c5a514,ec4c657f,ebbe25bd,9d6b172,68ada77c,5bc4f32f,57f325db,9556ae0b,4d1adda2) -,S(6e3c35cb,9c86216a,250ae256,f8ab076a,76264ca9,97b1a6e7,41ee96da,5cfb2c9a,d45f0082,46489230,268e5c99,56dcff9c,bf6a0621,f8978be8,f2183920,eef3dd74) -,S(f3b5baab,882e20ae,b0f444e7,47688392,37acdb60,e7c878ff,40ec0aab,7896c278,7d8d6b2f,92addfcf,a248aa96,e8a87e92,4c821c1c,cf7b343a,f588ce7e,93e37260) -,S(b89b2380,110087ce,8c8bfded,7dc98e40,3cada8dd,77b2e68d,120361dd,6beeca0a,616e00aa,4aba8494,9835b0a1,eb0ff955,6268d2cc,91b7672,d0164693,848389b8) -,S(6659b720,1db6e160,58854e12,dd78b89d,40d91a17,b7eac836,ab8453c9,ee3cdbe5,5ac9db66,325b000,1983df0b,6693d93b,adf7e35a,a18f76ea,e2053e34,b1b8908d) -,S(6fc76d79,bf3c34ce,afe73e9d,7a77af23,bcc7e894,dc555f63,8b9d53c6,c15803e6,c366b411,1d6ee57d,52d3938e,f2c0c620,746d636c,92ab73f0,bc812888,ef0b5ac0) -,S(a06b2395,238326ea,20545cd7,b021a5cc,9e21e9e3,26c28b1c,fb50f3d5,e0f6e069,8560335b,a5c16aec,a297f185,ab09e976,dc57934,61170b35,b8a3b6b7,4ff622f1) -,S(bb8064ee,177f3753,19e45c8c,4dcdda70,ddc4bfff,1a866b7a,ae7922e3,13d1515a,a3be84ad,274704ff,e7a76277,d87687ff,572633b,2fb46b4b,40f601a1,ccb98d7d) -,S(27f08788,6a2c0ab,8f26ef15,a85d2d38,f6fb8cba,622acf21,77ac20f2,f05962be,ab2f2929,45163b83,c9cda8e9,4f6d8f7f,167bb589,50d4226f,827c5b5f,a782f8d2) -,S(f51d558,dfd8f74b,7c9c3768,65f82932,65c1bbad,d8aa64d1,ebbc09df,b7f6de1,101c88a8,170355ec,ac23ac98,ab5aac67,7a68a94b,9343012f,74cccfe9,308c039b) -,S(60fed665,a3ba26d,eccd1ab6,c956ed2f,e33da384,dc687f41,6c37b550,123a5441,4bc061b9,b2d7c63a,ac042a7c,efb2b5c6,a43260f6,8bd0f843,fa218cc2,3fc9b5bd) -,S(fdb04aaa,f2958755,ed65f968,ce4fbb81,ccd8c616,32e9494d,510a7b3e,d2564256,afbcece8,c52725ce,c0ef2aaf,a094385a,831afaa6,7c4cdc9,57712bf6,1073990a) -,S(7f45848c,cac04d5a,d9caa28c,e60628c,aea7f076,262689e8,27fc7084,d6b94dbb,51e16503,e044b101,a0d12d73,3a57d8c1,546c1f04,386721d7,a6f9fb15,458e41c9) -,S(b4091018,4c556249,30ec006,95f02723,b9cef749,57996d50,72642d8a,b492c9be,1b3c221c,235e721e,95bdd451,f0f0fc8d,a6a18260,d47b0c09,5f3e1b1e,f6135e5d) -,S(4d5b1a50,d00b83fa,93ab4746,3f84dc21,d0ff4559,2e697fa0,bf8e8f68,5e1c9713,da52a118,24ed00e,6a2434d1,ab383f0f,1e495dac,d08c6a2d,2425e25,a9434af2) -,S(63fb80ea,cb68910f,69700533,8a1769f0,69acdc85,da71618a,9cc03557,1d4bdca4,7f2e51d0,4446763,9cfdc2fb,247c7cb9,5b8e01a5,e27e6bda,6713ba98,1936573e) -,S(f5035d5e,12313edd,b0c31851,266f7e92,6f16c1f5,a6031aae,bd5e14fc,18304faf,7381fc4b,cfb33c18,7bb59e22,be95081c,6f52cefe,dd84bf6c,799f419,453f61fd) -,S(f62c9afc,5a2cfec6,afd54b78,375a73b0,eb5a73b6,f53e24a0,6d1e9111,ff20e835,a5d386e,211845ce,9ffeb917,76a8b91e,27f0773,b2d53fb8,2ac44b8e,83198350) -,S(7477749f,3824c134,c1a91bfd,d1b646f6,43f8109,c2f46887,22799f6d,53e6280b,232b459,2259cff5,99e4af77,1e03c94a,11fc32bf,f2598beb,2316d3aa,d9461c55) -,S(2e2c5f43,5fcf4fcf,72f9629e,ef6ac5f4,31073f2e,7034d6a7,64af194b,1e84b6ca,cb94ef61,c794f44f,2c7d1115,b9dca665,7fd1c184,e30f6f60,caf40e75,142ee26a) -,S(8f7e4f94,fd2a651,86e4624a,93272af8,2d362587,62a0baae,f65cf47a,bcd8214a,9edada6a,d23cf1c0,dd98b1f9,d9a83879,4c21654d,239f1a9b,dbace84e,de6145a2) -,S(e184ae37,4704eed2,b054b667,33544ff5,6ce55a9f,bcd7625f,740b6a67,621c75c3,ea773744,2212bf1d,a26fd119,248b0c51,c413ebaf,75e52de8,97b4383d,b397e144) -,S(fa47fd9b,94cb72b2,60fe208b,c022dfe3,a2bce2f9,ec776313,a497cd91,4166850e,9a12bbf8,a6e0ff91,5176f71b,16327c7,ea5d928d,816de31f,c8de2be4,57b0c185) -,S(98d36e76,a4caf051,e848fa49,64e09bfa,815109f8,63cd5e99,405e64ec,d526c67,706b36aa,6e67352,8fed83b6,8118ae7,1e043964,f444c477,590430aa,8d80d19e) -,S(e7722849,c00c5875,44751cf9,a88fe964,9efc05a3,4d810788,f30a2057,cc1d0c72,d64ba14f,978e1769,51951a4e,8431af78,57e6d97a,f5fc5ba0,2a1fd46b,1c215e7e) -,S(93374edb,547efea,e5f22d56,acd80ce2,80e4d47a,bddd1d9c,9d85afe4,aa6fe6e,e9c40824,cdedb038,9b42e2e7,2e15009b,215d9080,7df6316e,6e81ec9d,40dbbee3) -,S(840eb546,a076bf81,e4954196,6eb8c437,3a055239,8dc4deb8,62a73b76,8b380e28,97b69f93,ac1009d,a3f47ff1,b62ea845,f2900d7c,84e8a1d1,48d96f,df6fdb98) -,S(fdc4ef19,59ca06ae,92587249,e45d456f,d7484278,6f4b3381,676094ab,446c3e8d,c832aa3f,f0ce9f79,1fbe89e1,5511e25c,6a7a4230,401471c3,7b9ab011,1b304366) -,S(42abeb49,83403d4b,5f529eff,16bb991c,ce705250,5a61fd6b,96467a51,f661651e,d815247a,f807af52,b454e83c,9d46327e,d80d3ec3,60f84a3c,dc88b9b2,59efb05e) -,S(176fc9a0,b44a34ff,fd652cc8,bf715a12,a9d5f40b,adef6032,24536660,5e0680af,a47100b7,e0fc557a,f5ca7dc1,c220b5a,770231ac,184f14f,57e554d6,11daba35) -,S(11fa2a03,aba7cdd3,1940923d,37045c99,ff531ba2,a1266fc,26ce7a26,c6495e63,360c9e1c,54fbc823,9878d725,30254bfa,70453c3b,934915e9,5ea4542c,1026b272) -,S(b2dda11e,db5f668b,8d90dc96,9d10f8dc,6c95a16a,a3e2cbb,3a1ccc03,d9acec22,f4d44dc4,8c260995,4fc1316a,2d5bfe6a,18ea754,43bd9a55,2b2f2f08,aa0652c5) -,S(baa1d433,e2adc426,5f87f407,1c8c35ca,423f3e76,5a835a70,2d804593,cfc3f7b,3f55a493,9e25a77,8a9d3ad5,4ccccebb,8a45486e,1aeb817c,dc0a2799,6e70e996) -,S(478f18c,30470c65,b578a6c5,df9c71ac,934e3439,ee5d5d23,21f8f5a1,7adfe55c,c43dccf1,9a9e48c4,41ebdc12,f2876cbe,32852cbf,d3bebc9b,a3708fe,6cfa450e) -,S(18223de3,d62283f6,c440102a,a1769ac6,f5e1a0a2,cf3fdb2d,ec62563f,4e149ebb,57fc95f7,f8e3151b,80fa4e68,45349b7,961fe72a,d6ffe725,e3a0a0f8,907a4555) -,S(2c8c523e,179bc8d2,1e3faa5f,5db5dcf2,cfcb0426,3f138cde,428746d9,94a17276,c3f00baa,69061521,5d512c97,aac1b858,40842fa0,d8bdc773,4e11d370,4f6330f3) -,S(a001d77,af44959f,f1e83be7,d6b16496,2aecd428,3ae2c38d,f3ed3fb6,a0f12460,e68a305b,6f60a1ae,5a01eaa6,7675f0d9,8e6c5baf,75d725bd,d0e2a499,1c323770) -,S(cd8a1d36,2ba4a2db,255ebbab,ede7ab7d,383b641c,515250a5,cf52a2b6,a5b2ea9,20716fe1,e0857b5b,55b836d9,39d3175,188a6f9d,d3cc42ba,8c61a7a8,d9a7a1d1) -,S(7796adbb,7949b234,6df5147e,c3d7e0c2,5b61a874,43fea9f4,b4e742fe,6c1218a5,fc338089,c80c6415,dbb32994,cf5e2af6,b5c3342d,d291d7da,def80628,a904edfb) -,S(3c345146,27eb74dd,88ecbb47,aa9933ba,b7fc8cfc,bd80654a,f96aad51,5c1a7017,cf4318c4,1c021c06,5c100913,dc84259d,2b8d6ee8,102e5c6d,c3f809a5,7f8f2beb) -,S(cb4470d2,d5715339,acf391e6,5e3cc397,eac932d5,5acb65cd,a94538fd,eb684f67,15e6e6f3,383b8bd,1b674497,589ed7cb,e0f41394,e366ec61,b7e1b927,daa6434b) -,S(954a527f,c4496d02,915f0b11,4e95f104,c500be4d,a61eca3,2fadde9d,c1f118f2,96acbc82,d0dd6226,5652b61e,226b7ef1,c6f00491,91bce5cc,fecaebd2,fdd28ed0) -,S(d3be92f5,697a11cb,b8374938,9fe89418,97707ffb,24fcce90,16debabb,a4faa4ec,23d04ff1,e309abd2,aeac3159,ed9acffb,9c5336f5,517531c9,f1cc2dc3,a2d300bb) -,S(7490df7d,5a7ca290,fe029f3e,d92f530a,23a7c983,654bf19d,5c9ee21d,b4f57586,3d7f28c8,81b259e9,f5f735fb,be608154,b80f38d9,b5131bd9,a6e2dabe,7ab2bd54) -,S(992c4a82,1176a784,ba2767ae,a3d39697,5f96ea50,b7bc8947,2356fd98,20aa666f,519d9792,458fd39,7050829b,6ef7449d,da4ebdcf,fecb2a3,8ca0f057,f051c851) -,S(f070e211,b384b497,3d2dac23,3373a3cf,6dc7b9a6,2529af9c,b2fb1e84,b40901e1,175cb1d4,f8339521,26d4b41d,9fe27781,92a2a1d4,7d5faa48,1e96f51,beaad506) -,S(108f6113,c2795472,244db9f2,3a1002b9,349bd34e,f9c9d70f,e146df96,be198ede,2bb9d195,d087015c,253af145,bdd6134a,1845dd92,45d7d8c7,c12ad2ba,2027ba2f) -,S(ceea04f7,9b611056,ed7043f9,707bb318,e3ad332,1da82104,9790b1d9,d264349e,5380e9f,1c52e5ba,6ce18afd,289f49bb,c358bb90,9db23d67,a851dcf,9ba5ec9) -,S(1c74297b,14a4fbf1,2a6421f7,561c549,414147c3,2a683391,c4cc5eb0,79948cd7,581c9642,98232591,bd5469eb,c1a01be8,37bd5d43,cb63e21e,8540ee84,52b12ab1) -,S(14bd0f2a,ebcbdc9,22fe8660,c63bf12,c6db8521,f1f0acf,7406e982,a103bdc2,46c3002b,1e5f25e3,98c8d7af,e340aab7,23ccb0d2,7e24bec4,55d547ff,1df59c96) -,S(32c923a1,526240db,b234ab72,565d6880,b260e7a4,33747aa2,802da713,c30ae9a3,b79bdd74,6ce4ecd4,a554d66e,b787e312,a1ed53e9,c77cd6fc,73b1bfee,8b13d620) -,S(af0ec2cf,21ecdfc6,a71c6edf,6f73ab6c,76600a89,86b62006,8b246008,7cdf168,d229f3c2,7db8019a,eeb8f25d,84f3e341,681de4ab,2173f510,51ef4249,7a9dbb0a) -,S(1d648075,8273a9a9,c970cb10,5ae7e537,b017aadc,8be5044c,a1f6a3ef,4d2cb275,3faae8a6,87925e3c,e9c3482,d34c76a5,702c9bea,a307aa45,f2ee992,efd86387) -,S(160ebccd,b4d5561b,488037ac,25224afd,91c66584,660af970,672d9514,87376568,f510b49c,b58b09f9,46001627,2fe744cf,e6e7abef,8f54552b,41b6158c,2ce2db5) -,S(50867128,704795c1,a190077d,49a87c99,8b10601b,c37b7aa9,908ce92f,28969c30,106fc462,a115f2b3,e83a5474,7a692101,8c73853d,83d8a1b2,2b0bb785,bda8a896) -,S(3ff4aa26,7e8d344c,ac75a46f,7b17af59,5d056078,fe860a96,573a8f0c,164c54ee,2632d1fe,f4b34a45,ac38a80d,236b51ae,de92fb72,47b81f6d,af1b9554,4d426d82) -,S(739f875c,ebe795f0,cbb846c5,88c2b809,21468ec6,4ae09034,6032a97d,fda93c1c,8393a2b0,f3e68c9e,a57d5c8b,f8355d8e,71f4699f,201636da,5451023c,92a1b98f) -,S(717bbfa2,b2c4818,ae620498,3506a421,8cdff59f,2e040521,764b8013,b688c7bf,9229cafb,e99cbcd5,3f73938e,82723d2f,e7187ca2,13d9e0a,57c12254,dbc7f63d) -,S(cc0a808f,2618d1f4,27f165df,4412739a,6ad9af38,e8c25a2b,14bc97aa,1c5b0f7b,3b83d5f2,3d94aa87,9769c3d0,5e921731,17c345a1,3418ec3,2f92d4b2,c1e275ad) -,S(4a0b31f8,8f82abc5,6867fffa,6deb20d2,d8e7613b,aff466db,b260734d,1ef8b1c9,375d7c69,83784dbe,a5bfa8c5,8f8baead,8e94b9b5,95c01d9b,2747a06c,5fb7272e) -,S(52149a1c,53b2da97,f39e9dd0,23443cd2,b21e404e,b6235014,ce04c616,9f5d05a8,a9f9a4cb,ea6d202a,c6b5aa93,28f583c4,45db83e5,8ba7fc25,3eb43e3,df7f542a) -,S(6e294aff,9e9fe4df,9345bd93,1229a7b0,955a3b63,fd19d1ac,57bbed72,50262b8b,abe6fad1,5fe423b,e1a55867,137c485f,85639823,beb6ab2,81dd9e1e,ed447123) -,S(e9a70c2,c5e962c4,dffe24f3,8930e095,c2b0b540,cca2d891,2f6f5b4f,e4592e9d,8d115293,95051750,ccc9369,63b987f3,96bd05a1,49915103,1e47baab,358decf8) -,S(e6c934a,57ec5422,5d42dbca,715e62fc,ae957590,52849f8c,b5f282a9,b82d4adf,6da738b2,40ff3070,bf0c4ac5,50ca5a77,31db8a07,20312e2f,f9de572d,d7b67d4f) -,S(89b46ad7,cbcf1b6e,8741e422,ef53beea,49662d96,bcebbffb,57baf0d2,1441a0a2,b7205431,1798624a,3a1708a8,986ca47e,374d9704,22f7d3fc,57ca7f22,94913e8) -,S(5b949cc2,69f0b0a0,c3b85fd9,e45b737e,7379a4bc,70d926cd,cad87ae3,4e7a686,7e54863,c1efbe6a,a98d6466,65057347,7291b068,a43f1783,9d02b190,9327bac9) -,S(787baad8,9882587a,97b049cb,9906db7d,b909239,aa50e073,d476081b,4a73d7eb,8e3bb416,b57585f9,8b337b72,b23c2b9e,c790ef6c,bd397b18,ab78f8a8,cb662425) -,S(58460ae1,5a204740,c375cef9,e447edc1,2fb6a0ae,2f8d18b2,8e82ba60,729c82be,1bdf3641,d16d89ee,378e83ea,302efb0e,2a9471ac,9bcbf1e1,662885a0,81c7780d) -,S(c9bc29a2,1f7383a3,a90ed3d3,fc5f6d32,1697e354,a77173fd,77899d17,2012f63f,1c850132,db81d86e,e866d9e5,75c4f7b6,270599f,2e48c0b4,94317dc3,97d1043b) -,S(d4c54b66,a1ff77b7,63f8c520,181e4ae2,6b82643d,758f872d,cddef933,36cb84b7,23e64d9b,f7456086,ce8b778a,194f8b8d,f1f0bf38,fbb8454f,d271d062,ddb9b9ce) -,S(a947a90b,b27db3eb,8b4ca4cf,f947e587,54fe6a48,7b922ab1,9ef4b5c2,99eabe3f,c83e7022,f6e12dbb,f95e95dd,2bde8b94,3d72cbb6,5b222f57,94d13251,c9fb975c) -,S(d83f6040,4099d448,8ec6785,131524f7,3e58727e,829b3d58,7d445197,cb367746,6d50285f,831e1173,cfd7de2d,d1c7c29,532a391c,3f450b7,f25e758b,f412a8a7) -,S(75d60448,78902615,467175b4,bc16c936,14bb10e7,c9fae9f4,57d4a210,2d506a0b,885237bd,b4277447,fc7970c2,4e3e7240,ca24a07c,e46b8bac,7a91272c,ad9c5854) -,S(1f96a542,2ea4726b,b639d270,17eadf33,43bfbb7f,f1fe9307,a20fb5c5,f1c4fda,5f80a9b3,ec8b0fde,ee914ae8,e6052100,77701a73,57829803,4cac5d44,91ce0a22) -,S(3c0159ab,4f27b61e,c2599ad0,a79b4228,9000fcb9,ceadb440,24e1527a,f5ebb9b1,77df26bb,659283a,37abc70f,9f465794,ef3fb178,107ccaa7,a5404c88,a67a12ef) -,S(5b250c4a,25293ab5,34f287a4,9f9f966b,7ebc1c93,e5a774f7,c98980fa,7980e07a,dd6c9c36,5c015685,9e1ec5fd,3a740d1d,7eaea301,2311d1,a9cf505e,7e594613) -,S(20a6dfe3,71696c50,c3a7abf9,3341c41d,9d6d2111,729fe45e,f3ceb49e,977151fb,bfdd0224,fff97fd7,ac3eda1e,ec0e6f02,8bf7a3b8,23cb49d1,52d643e8,fef3d820) -,S(915fe7ad,5840d789,b94d1bd3,2d555340,3c9152f0,340a5f87,6862ca40,19825b79,8d2f0ba,3459615a,2036a07,ca57d0e0,f3a4290b,f5fa7327,2431e3e7,bc44255) -,S(d6aefb63,618e2fd0,34e4f17c,eb766d5b,c27c9a15,d796b16b,7cf8ba71,31a2404,f0abb6a6,e862f6e5,d71b062d,e9bb7b9,dfb2e4be,1c5a85a6,dd3e0c25,3617e8cb) -,S(4c804837,7d65a97e,f65a342b,c4549e16,5cb1c50c,cd1549e4,d2d2ec10,c663882d,e1ec6bee,d0bb7243,a384e6ef,100e5180,4de6ac00,b06d7b67,3e445dc5,7b76dc8c) -,S(3a6df802,f372b56,1ebed30b,a4740d03,d257d256,4931422d,fd3c8c1c,619847f4,d168c60c,9a86bea7,e48e58db,d8e6bdcf,b6ea7d31,d57f8996,70f79e33,241bc439) -,S(423eedec,169fa4aa,52588642,a62ec6d3,8acf2ca1,c8098c24,4a56a6b3,169f9932,4887b475,7f27b4b8,d288c05d,3efc1d98,c0428b5d,e4db1cb0,6dcc4782,10cc6f52) -,S(2864f372,8f8c5ca7,5dc56dad,8b968c71,a008eaab,80b8bf28,16bba436,78465be6,14f5e2c3,423f863,64962871,b786c840,50cc07b9,f537ddfe,cf81b95a,a276b813) -,S(cb96234a,985e2ada,d8130ec5,472efca5,7ed7331d,ae7570c4,dd42f4db,9597ff08,69722bbe,5b367ce,5868b30b,31f67c8c,a5f047ba,a7f65202,48041458,66b88d5a) -,S(3be93dc2,99b7e701,ddf0f239,286ac598,bea1ce42,f1e21ae8,1cdf07a7,66c1123e,8a9c69a6,6a475e40,d81b5d0c,7734cec3,40f528f7,4fa0073c,ee92161e,cbb92d00) -,S(9022c43c,7acf3552,fed52d25,d25dd3f2,9aa61fa6,988a5499,6aa3626b,88b7f497,c514a46,f328c9a5,dc2fd03f,81ce3fda,915f1e8f,127348ff,55e4b5ca,2eba0e53) -,S(a24cade9,47a24abc,a050ef7,f62d138b,85c96d0d,2edac403,dad58ff7,8a2a9d3b,a209613b,c05a7b52,41697e24,73fa7fc,412f8fc5,b2fd0447,a2e20e71,949cbc0a) -,S(cb2010d3,94259307,ee3491c5,58efbaaa,203cef1f,8a0a1e99,67a4ff3e,719495f7,1bc5b6a5,b5acd447,baec221,141b601b,a5a3a640,7f84b8f4,319a760a,6226b0c) -,S(fda8c6d7,c6302b27,76172f01,5e59da8e,4af1e96c,3bd05f2e,a393fb7e,1dc1ecbd,87ce1baa,ef24102e,19c7a17e,b267acee,7681d40d,705f7058,c514c9c1,f615e666) -,S(b459fb13,5b9902e1,760286b,b37ffa03,ceabb618,e684823c,17ba97dd,c95ebdf5,6e35fbaf,b5175d3f,ac60f2db,97447cc4,a79c212d,5496ab7e,4b536ddd,797a19d7) -,S(ec137d8f,23b119eb,a286af6c,583ef011,5d21f335,8a1a2df,ba6af216,d03b4a36,344fd1e4,869d68a0,87a1974a,d48b9704,5db2940c,dec017fd,a0605c11,8e5c7bfa) -,S(8e0be401,9f2d3cb8,9ab07348,cae295c5,eb7fd7aa,fa5a83e9,3d68d994,af68e14f,542fcba8,51510baf,6f962401,e8a607c5,34a32971,22645ebe,2dd51867,b26c80d4) -,S(b1dc8611,3cc18708,338542ac,698a6981,a6192261,7c1f71d4,3b72baeb,1c0dab03,f3e61423,5b683727,f1cca8e8,41de0474,e8c4da8,d2bef431,3cc2da5c,c4ccf38d) -,S(d438b027,7f6c7048,c1eba2c,c1d7e554,888a7025,3f513261,3bccad8f,a5a0a9d5,fc419852,23f6ba14,adda0abc,389d2d16,4a910dab,b464232,298c2a1c,50ae64be) -,S(5484d618,5cdf3f21,42235130,62ddf251,1f53a84f,f0fada86,602c4b13,3dea0f70,6e697180,33860802,6ff41cec,cea79f48,b695aa37,2a76d046,47603a67,ccf9615c) -,S(8c1856e7,6842f5ce,82c09a82,4d343a6b,ac67ff27,f6d32de6,7117dd75,59df362c,70f78515,c4bd17c,23f61049,d6ccded4,100234ba,b7e1b9be,16925635,a9aeea2a) -,S(48052022,94350095,8c904f57,54285e1a,7a17ff81,dde1f50,8586273e,40bd531d,7f1ad451,38b44b15,33327a0b,15fba2a3,f70989e9,1c271b1,461750c1,5044294b) -,S(4adae425,86b0b95c,fc26159c,6aa0b1ee,dbbc936c,83fd6056,f2b730ec,14dc17e1,e6d0f9d0,bfec452e,3f2f9b39,4d73c72b,990f9683,b6004fa3,8e8831b4,f46f9d4a) -,S(d296fd2,926eab53,db70b1d8,d5c999c5,7eb36987,62537954,2074ae12,af5844f0,b4472b2,c33661db,50b4370,e0ae7811,b16646bd,3f4771a3,113d677c,7f1c0cba) -,S(1dbf607f,5d1ea26f,ee8e416a,52c8475e,a8363cde,6bebcbb9,bc04cf4d,cd19cd54,832c9d78,60c8acc4,5d00a568,2d28fe07,4952a897,619f8b23,42dee2b5,e20482d3) -,S(12321adb,c5997830,8689b103,ec1552eb,679a3ae9,70ccfc46,f4adab54,f8dcb2b2,92dd316c,bef2864c,bd5002f5,ba052712,3f920db9,44992ccf,1b2f967c,b70d1f1f) -,S(fa2c024b,76460eb7,a64d1e1e,fe059496,c28372c8,1d00cbec,9ea76f62,546642ee,5a848904,a654469b,dc3eec26,736d7677,ceae5fd6,d6f30adf,8c3fb95a,bd8e5d8f) -,S(a77dcc2b,218b5acc,d6172931,91e8ac19,fa4d74ab,4c88b84,775d2f35,3f51e7c3,de872263,4e2ff356,7d9e419f,26ff51b6,c41fbbf,48124d01,8409a516,9735a950) -,S(83d740a8,52a6139b,53b60796,50d64902,9f9fe35f,87689977,66246b2f,91e038a,1c630f32,722468ea,72bfa970,8a27bd9a,97b68e53,12b7799f,66ede01e,9c75b57) -,S(d894b986,d74580bd,84b24a68,eba87e8,32a9c34d,bafc5717,cdc03c22,8758c9a9,f0d68c3d,284574ea,21a357e8,cad5fecb,90a57b52,62f6ee06,1868d970,458d502e) -,S(67b4473b,3f1420f5,a8fcb39c,8671d583,cc1b9f48,e288f311,2af6241c,4190a786,14fb410e,e33f4a6a,3fe5dd9d,c30d581d,a350c756,6b513290,7f3ce97,29310b55) -,S(24522965,87039934,a6927d0b,782988cc,b126b61e,db154f07,18d97d41,6dc8f0c6,538c4e2,a7e180e2,14e36785,6dedb105,f688f1c5,9bf81d30,d92a8a93,d3c5a82) -,S(b47bdb89,b087a27a,663f9884,7ab44a64,43fc43df,bb61f4d2,bc5b7ff9,234644cc,ee508868,402613fa,1a200032,afacf672,9bb3f7f2,43b2f415,383f4067,d0212483) -,S(92eb31b5,79ac7b0f,d32ac278,4f3d2c63,93c285c9,567bf912,584c00af,3be97d8e,518e379b,ea24a823,e725a3a3,3608e62a,7a40aaf5,318c2c,41afefe8,ec9afe7) -,S(a5e06969,cd69f1b6,c30ab55,1028e1c6,1bef12b4,b2c2d1a2,572c3648,fc739332,378a3b33,3db8d289,667bcd98,9a3cbe9f,f20b08de,4047164c,7f4bf9fe,5d1f93b5) -,S(604823c2,f1ab2bf7,eba63c65,610fe0eb,c958e8c4,7f509c8b,42b79934,7fbd9bc6,29f532aa,3707e872,2169a02c,210fa9f6,100c6b1f,926c73e,a3bd0427,a1844733) -,S(1b4bde22,bfef0cb0,ec9e84fc,e3af2e8d,ce7f381c,e9766b1c,c1d5fd90,9a1bc891,ab20347e,3f4c7ba3,2bb773d1,50868756,69865df1,18297657,6c283704,49451f49) -,S(10caa116,2067d668,5371a20d,97313b54,4d79b61b,3bb41a87,980eac97,e82f58ee,7ee4f118,32d9c2bb,1f849731,d779d12,571a084a,4ecbf4d6,128f33f,6af477e4) -,S(71e7f07,513d42fd,5c0ad06c,c96ce17d,3542a4a1,a101e581,f7394c2f,d89e2072,e214ca42,1033650f,e420e574,e2266c23,3897de25,90dc3999,bee41181,db0a81e4) -,S(fcbe392d,82b4859a,2424ecec,dd8cd47d,bbb89d15,ea2b9591,f5ff1067,e2cbadaf,9b06334f,6ae45d74,44b5f09a,995fd91c,a2712ac8,b159126c,8cc0120c,513f0bcf) -,S(a64d9e9b,5c583eed,aa7934ef,a7ad036,8dc9adc1,9437f97a,7a16b645,cf46e262,9357dd,1aef4b07,a376b468,99692754,9ddfe9d6,7982a7fc,d607f02b,8a7158a2) -,S(e634938c,aaa4010f,f4a1e760,d87a253d,5fd645a2,4f85a75f,8eba78bd,d876fcd7,84be5fa9,c11d8c3f,54f757ca,d9ec4e18,86e52db1,4b3cd0d3,97f666fb,f347d24e) -,S(4640245e,23e6eb75,6e0a44f7,698c1faa,33ea4f87,7a52f850,3477ad4f,8ae2f4bc,ca2a72a4,1348d3f2,6a7fb977,d3106710,2494a982,a96c6514,7fbfcca9,1ed2225b) -,S(c2a175c7,badbfe95,cf7db594,626a42d0,1247ebe5,160c58a0,2437fcd5,eed8c59,94814fe3,7692ad4f,ef0f4fd3,41c63f84,b282324e,faafbc59,38d88f4f,eff210e) -,S(b1296159,d0651519,d76bffdd,98013d1a,bb17de49,111e3035,5f7a1d40,3d8d9148,ae3c442c,2dac0847,bd8d9052,a5470b9c,80536fd9,feb5f820,e4c54ac1,78aa44e) -,S(d30b1976,b0867b57,84d5e619,a5a63516,13980093,5a9458ed,59e4a3bc,ab69b7c8,1b1eee49,690de06d,7a71c334,4fc0a647,133f2fc2,99a8f096,a8a445bb,27f5b96f) -,S(fb1c3b4,5b0f6f0e,35b93a5e,ea157e60,134b00c5,38a6e429,301962f8,38fe51ae,cf79bafa,d7c3fb08,49e1c2cd,48a90ae4,af507bba,5a42f3fe,bb1e101d,7f5fb818) -,S(2bc4d2c1,d34c6d41,9d97ddc0,c758fac9,ff6489fd,786065a3,61ef442a,fe37199f,5b932f15,9500ef4e,a331be88,7022f42f,5148c54b,30957b0,424a168c,c6d76ceb) -,S(2744c1af,3459c35f,d8e1b27,668ac653,eb25f017,e4fa15d,6c1a6bae,e50f3a99,12f95a25,a87e482c,c647b1a9,f22286cf,3297a354,4c7b575e,aa888dd5,6db2844a) -,S(6429f3ff,d37b53d4,88024393,d3a9dabf,f84e3974,ef60f446,61ec9da5,efc736ee,e8426421,f15768f0,caf020ec,3999e8d3,a1aafcb8,24339574,fe119500,a168016a) -,S(33c132ef,437e9dd8,ee9c028a,2ad51c9e,5a836eb5,4bd97e5b,4b5b6bcf,38d006af,e2527602,e5e74d67,5a5115cb,9a89c579,c760445c,c70d95f1,9ac82a1e,6ca16c6d) -,S(3ac856f3,7d53e19f,f6ab49e3,94da6ed2,c8645e65,f4666bfb,163778ce,7cd910ab,ef40efa2,55d7a5bf,99e39055,8993f753,8fd203d6,7fdfb7d0,81cf8bc7,947cafcc) -,S(5ec9648d,b58770e0,314217e,f090c776,396f47e8,ba27c30b,98c35955,aab03247,3d3402e0,8fb71448,6ee97fd9,15293e53,b095fe03,9cc3100f,21240a24,d70819b6) -,S(54955c84,3c5dddd,89f60de3,828fe4f7,1666d807,ff88006f,b46c37bb,8a822645,c8745950,64b3c721,9eda8253,633deb6e,ac9a7825,8d1de2e6,c2dee05c,f167405d) -,S(e0e845f9,35054008,fa44cc4f,1f2e538,33b58e73,bc6a04fd,c16faa76,c1a92d3c,edc48f46,2a41dc1b,bc604e0c,82d993,edc2990d,f59fa034,11702d86,46dd1c1d) -,S(bdb43235,19acce9f,b95f83fa,485940c5,69108af1,376cd09c,884e6419,718ed14e,5669c5ac,84bacd6,eb6fa8e7,39da1196,dde69170,f5d4e5c6,2ad528,66b6d9a5) -,S(d208bcfd,f9754dc6,7e099754,983fb58d,e5679bda,96d8404f,266c0e65,9e4160ee,c602f6f,f0f586f6,7ac771d1,fbf9d807,c2edf68c,a2c10cc2,314221fc,cd3007ee) -,S(3cce9096,450e620f,29b2446,39e8809a,39000315,a887d6e3,da141ed3,32b1c30a,db0ee91,b8447860,18289da1,11b3bb62,289d21f5,2aa8f436,562e982d,bab44be1) -,S(6c351350,d0fa9ae6,e1723848,33e654a3,f3f655de,7530d9bb,59d92462,1dcf8253,2e5ea374,7a368904,e4cc663,feaf6f92,4060dd70,95bab9,ca2e0773,4c48df83) -,S(c64b42da,d63cff5a,ec1eb168,41fead6b,3dbcbd97,f6786efb,5336da16,35950d2f,73706863,cfee031e,3fee4be1,9241cd94,42c24f4c,c57faf70,f8ff8b81,f094ccef) -,S(c4b99a41,7b2277a4,159bf3b4,859e36de,399862ac,70ffb482,b92e1b11,99c748d4,6ae88f86,1ff14b38,b545ec86,1a808c5c,cc78c3e7,91b48f29,350afe20,9efdc33f) -,S(eecf955a,f1ae50dc,44b57715,5ea67ae,1ae39cf3,fd306eee,e943908b,a7a42a56,26c9e114,22cd3db4,b278adb0,8e4c16a2,1a4c0a9f,b837a493,6cbdb70c,65fc5be) -,S(454ef33b,402e3a59,d437925a,b62100d0,974abf69,8803c04,436b4d2d,5a5819c9,4a38e398,1e1d9809,72df7faa,b06bfa96,20fe213a,36ca0227,c7c20ca9,2ef31563) -,S(50f11935,c20dd410,7a2cfb65,2c94e39,8df7d985,c183259a,70f6a04c,6ac5734a,aed27454,75f207b5,dc1e9f4d,f8cf1108,c9507b03,d0e889d8,d33ebfb7,3b10e670) -,S(43bfd366,10b67773,a254a077,624c2b53,4d8ded30,bf53e918,4f10e597,e2edd980,fd0655e2,e6b257ee,a249a5d4,299146d0,e08653cc,cef19a88,5ad6b33b,ae8f345c) -,S(7ad3c8d8,85cacf19,ed6aca96,4607f344,91448d7a,651fda8f,2446686e,bd06a9f3,9cb921c2,3e338436,73fa1bd,101dc4f8,a9a714ad,7fb91057,dd5af779,835000a0) -,S(874346d6,9cfbfc7a,2e13c605,baa69c5b,d39bd69,36841594,1cc50cd3,18c17380,35326549,dcc29eba,4d35a559,e8f2f0ba,b4d94ada,f2c18612,a45c9c90,8d99ef4f) -,S(1001f64a,23afdd92,789390a2,bfde9ae1,d85737ce,3e5087cb,b1bf2d5c,fd0e6943,184b6a2d,ebd086eb,6e04db54,2146059,e6ee341d,1c8854e6,e57345fd,5dd237dc) -,S(659607d2,68695906,fe752434,a229c309,60b33825,a41589d8,6e663230,c1610fe3,77005570,df191869,38a56d95,4643d991,486c70cd,3d5c336e,11a9667f,fd8f7862) -,S(eab041d9,67f89c37,c04bc6f5,a9059d69,a53e5fbf,ef7c17e1,7cef48d7,e346abbf,a2c2fe6e,63e38c06,477d2821,d22b4a0e,4edb0b55,cb1d9fdd,6cd01ebb,d8fa51c9) -,S(4ff2394f,377db94f,e96f51da,d7364407,ed6bc1d9,3822f24,91630c3c,abacda99,4a77b936,a42493f0,d739afce,b769c7ec,cc0d4720,93e839a4,330054db,22e93b31) -,S(7952c74d,e0576ddc,c85f42e6,24937e98,1502b2c0,105b69bd,4e35f59f,1c2847b2,e7159304,dbd9183f,3abde60d,5ad65ab,5a4972ba,19739b65,1d50c056,ebdd5b81) -,S(b3149a8e,f602b6a3,c69a769d,893d561d,c7438a74,bf47c2f8,ba07941d,b0dd214c,99e591f2,2f8da0b0,c9d7024b,c82d1031,cc4336e6,bf1436a6,bf03bc11,3f041979) -,S(ac3bf353,ce672165,a7e736dd,632c7018,1e454200,77471380,7b875d3e,c81ead58,78def098,2f0f5936,5f5c6519,1857463f,7376ec93,f15c01c6,980d352d,17a40195) -,S(9edcef9e,d26ac408,61d3fdc6,66e09068,a9b1e05,cc23202e,1d0b6e03,faf546de,b1387281,71de9aeb,b02b5290,d3d56d63,b6c98c00,cecf8b0b,540f70a3,79556f2b) -,S(fd48622e,8dc91972,7ac21c30,c0fb8d02,d8cfdead,dfc39a22,59853e17,5d8e6d26,4bf26514,204912d6,8bca0ce6,71a967d9,921bb882,33099b76,7a056967,3fd42bcf) -,S(e6dc2ea,c28def67,78b0a351,6ef0f4b,104fc7c9,88a03a46,8cfbf207,ca0ae0e8,d1892329,e77d5770,d9a84e59,c2d6f6e1,db6de419,87c5e3a0,ea508ea4,a11b3762) -,S(e8ff8f65,559128fb,3fc52650,ba063717,cd2d140e,ed3fc4a9,10dccaad,bb0503db,f35c361a,8ea9b3a8,139676c,3ff31cdf,5511535,7859e5f9,3590302d,bd21e21d) -,S(2e18c597,d4e4a4c7,d54bee9,215a1ee3,d149dce3,25cdc4af,f62a3da4,1922c2bd,3e8595ae,4b6cd57b,7f685a75,87ed61a3,281b52ff,d76e9126,4a0f0666,701c5354) -,S(589924a1,2cc867c5,b2289f81,2d93f324,c2df420e,3c948bbc,e74b6bb4,6d30f262,f9bf3d02,cd0001c0,bb9558ff,515ee86f,e39d4357,fd39cc3c,8ce73c75,72850466) -,S(ef55eae6,4a07199f,1a3f3463,5007a8c3,8d39db17,48af39cb,584d4471,d3d32e18,9d31abdf,91bfedda,3c1f02a,aceea672,21d347f3,5d355042,75452c91,5f4b19b5) -,S(7a8f75a9,41182eee,49883295,56588c86,3021548,70ecc05b,31b83a1d,74be05d0,bda4d0ac,ac72ccc0,c07270fd,1c2bba00,4cc9ce5a,fc927f,6d4bc0a9,b2fb4a64) -,S(330f8a4a,582dad9c,159e0f9,a47101b9,223fed7f,896679e4,f764b02b,3d1d9eeb,50695f30,f9dc9c75,6df20cd9,aca3a06d,7199c138,4b3ede52,2dfa0816,31fea2f7) -,S(6dd34c6f,b89722cd,182cd5b6,a0d83132,56814bc,7ff147ae,668618e0,30bceab1,8998216e,8ccfeee2,78e5c0dd,e206d3b,1fe058c3,990159f,be3beb2a,2a97cd60) -,S(66c2d4bc,1e1ee63e,75481e23,1e6df60b,82c73758,36d4c9e9,fa99a576,304ceb8,f6871e84,fcb56780,682bb226,a8d2f46b,89cf516a,7aa0de01,2ccd981a,b739244c) -,S(560ac5cb,b9a55c0c,8bd6a36e,9dc90922,9297a452,b83f8db0,e0899577,cdb8d04d,b6255568,4574e609,ab7dff47,938008da,5b11adaa,480becaf,287f2216,cf1c7891) -,S(a2377a79,e597dffe,224988b1,63ca63c6,67827b81,ccc645ea,cc23ddb2,2a1503e8,7663e301,4dcdbd71,620ff660,426581cb,7e723605,72b651a7,103faf36,480834bd) -,S(fac987,e1c77065,bb1eeec0,fdd92f05,5d10e738,befbb155,152bde06,87c7fadb,c6fd2faf,683f4e87,77a6166b,59c4b93,e7f5d803,fec49ef3,29e1a4ee,9981e803) -,S(81ee9f52,9b5c6b11,8fc6ec23,88f3ecac,4120f8ec,d134d22c,f809e2cb,1e88a490,e8bba906,3a3ba848,7bdf4a82,c5014493,40da0e2b,fda93fc2,b6440b50,d24536d8) -,S(e6439a0d,545c7431,cd8321ea,420dd3d1,9932427d,475df712,529bfd17,99dbc4aa,6c86e739,b6d0f23c,d3570bc1,86fd9e1f,e617fc41,8089f2a9,d42d0b91,2b4c8d39) -,S(e08169e0,f7362908,a0d207f,bf49a44f,5839c76e,7ad80a74,44e7d24b,573f0bfd,948ce18f,15ef6e2a,23f2db47,db402d38,2a4a3cc3,a8a3756a,c382cba4,f608283f) -,S(5687e6f5,7b2bacda,eafe58b5,94bc322e,70c7afe7,884ab4fa,4d46467a,7a8ba729,994d9091,e432b4f6,72e7f711,b5e0a7bc,b07fae10,b6e05ca0,5a088cc6,e4d89d80) -,S(6edfc830,82a178b0,d9160f4c,f0b01004,65c29bea,e3c29d31,e3826aad,9fa1979,5f4c6676,3df8ac3c,4490ec9,fcb0695b,e9c0532f,df526e83,f27ad47b,5bfff2d9) -,S(28128135,a17d0e29,4871831d,2542c2e6,80dcd79f,6b4fafc2,722b7db8,4ed449ef,4f7e515e,b5c7eb7e,415d7b02,83ff11c4,8f3f3ce,a724c476,71d02d1,50835702) -,S(f55371f4,2d617023,dd5542fa,db9a9127,c16ac04,1545db5a,a18cdbb0,cca4cacc,d0c795cc,54057d47,5bd080a1,acbe6881,3263f593,917e012c,dc1bdafb,920b3ec2) -,S(10fffd7d,a62de848,c07b50b9,64e3b31,ee6a13ed,996fe92d,565cc54,fd0b7c1b,92107e28,5319ce07,61e5f212,5724f2eb,fc61498,f838717c,6637c7af,8f0fee23) -,S(a6a73f68,bcb103c0,523c8f28,f14fafd7,5b8d399d,617a68d4,6ad0a1c8,6f12a46c,d18efb60,37f40a9f,6567c993,24f3a7a7,543fbc30,feec0252,87dc862e,b22fa279) -,S(2984cd0d,5c4f1c06,3854d233,6cdfdca6,50c94275,975feb2d,1b0b5bb1,c7dda582,41b0a86,8064dfd6,5c2653b0,27dfcc75,50eb755d,7c1f5c78,b0c13493,acbb4db0) -,S(a701d075,7be9ff89,67c67622,dfa8ff9f,82f7d5d7,814f6c29,c73045d0,c5b16589,ada61af5,62851c60,66501019,70953ba6,fca0d99f,42378b8a,5059ceb,2a0835f) -,S(f07463c9,c37479e8,259a32a,a2e8f283,27cc267b,95aec8c1,1242a092,bf4c47b,1ae9bb16,e538ff69,1e9ecc98,838e112a,a2016657,c7af104c,ee92471c,df6cc136) -,S(fdec5a71,21a17f37,b4c2e93f,56d910a1,788d2da,b3cce509,b3e2f3cc,f141043b,a62e32d9,336fcfd1,4bab6cf3,26ee3f31,4d2ad023,430768ae,8f093408,e3505d90) -,S(be32f9cf,9a13d4d2,652d122c,c0ce07b,da21fc85,52c0808c,23dd5a5a,9ffb3599,a4a73b26,2b5f8239,e8c279b,20f79c71,7ea47a64,1c084f52,f1bd4f3d,dbcf9c43) -,S(735a1f6e,2575ee01,9ebee00f,a4acbcc5,93bb6572,c4db9505,bf96a2f,43b66f38,20b1c7a,99c6cfcd,58b3f00a,3f9d7739,f9cb682d,946b33c8,879f041e,15e198f8) -,S(a0b840b0,6d92eb95,4f029204,1229b9f0,f1838bdb,4ead7432,4d8facd,70f7447c,383fa2d6,47d88c1b,fc9b04a8,a27b3a99,1a22b82f,7c99fce5,5cf30855,ed1c22f7) -,S(3e54abd4,36a9763e,52b7f46f,4955a339,6db284cc,77d0b351,fee7a568,e4774c83,1c64ede4,fb372325,dd435f71,e4dc914,391da9f1,ee08a21e,2eb5ec18,2834b0ab) -,S(24675c97,67f69242,4e1d43e3,1c46ecf,b418fe9b,3fcdb495,822362b,2a8adcb8,9e38e08a,4359dd9a,a9ddf4c0,8fd1147e,c70ccf1f,8855cdbd,49f44dcf,1edcc36d) -,S(16e0176,9f5a5c0d,f6db88e7,fc95419a,96f836f4,f8255a96,77ca2710,2330e317,30641d0b,fbf7a1de,24c72692,b7032355,6996bf3f,1b541dae,d6ccfe8a,f847646e) -,S(a2e30015,a53829d7,c95d5704,3d6dac44,bca932b7,d4115826,c602aae6,8e4ef847,33ecf0cf,e81236c4,e8fb76e9,645e4827,9bfa617,f6d2760f,dde2b110,77da6ce3) -,S(cd9bcbcf,b7338c75,3fe393d2,2e2e44f8,45a09b83,fe4ce29e,546f2a58,7d7422c5,7683e5e7,f990e09a,e15902e6,c57b8db9,e2b1d29e,8d3bf33a,f90291a4,616c794d) -,S(77a00bb9,6abb918d,774a2a4c,3828fa5d,c7d40bfe,aee10091,f5d92cae,cdfca277,f3febab5,3310a2dd,5dd7a5e1,33572b3a,83950172,be7e4cd6,fec7575d,10142e02) -,S(be2f342c,ca1f161,d15f98cb,ccac9f2c,806c6d1b,f34656b5,c671c730,bdae8efa,c9c7a70a,88ed250d,6a7c0307,d3dd907f,ca8b399d,4affce18,e988ce5c,e0efb5f8) -,S(538bc08,c3c775bd,33edee48,c96c6fbc,1435b0c,f00aa42c,6c15fc7c,5540dd6e,9d8b1293,14283325,8d676a92,d479ebb2,c5ca171d,a43fefae,74c7740c,7e956eb9) -,S(d5e26827,fc0d8283,ee020376,56e83ae1,3ee306db,92d0bba1,6b3fd99c,7af15578,b41d4816,b9643a41,c4f8c5f,4121cddd,d7eceeea,9f2156ff,676d6d2b,61b7d210) -,S(7d18f6e9,95f9077f,c371fcce,729835bf,aa903ef6,682404da,bff6949,4b7faac,1423bd83,89410b9,a2cd8c3d,3d13b495,d856b103,eeb96e64,8c258ecb,a77d581f) -,S(fcb3cd95,fb0b4940,bdf0bd4c,ff534d94,26489c72,953b19d0,cedce320,6e3eb556,46043aaa,3d1ce85a,3009911f,763f49bf,df3d7fa6,347f5573,4c6c36cf,97f15702) -,S(a0e8413e,f66527ff,12f6de1d,2ed4eca4,6617064c,afcc4e98,495f2694,34492800,ac640fc,e3d5d094,54ee6811,81f8bc5f,3fb1bac6,84c8c572,b24fe3a8,66234d13) -,S(fbf60da6,aecd3cd,9137b28c,f7bfe541,efe60e65,52470f80,e301884c,1e9cf33f,aab83f4c,9d9e5ed9,ee35be7d,33a02bec,ebca4f40,8f6fafaa,6f385a89,8f7d846b) -,S(771c8d7f,73bf2b9f,4f032e7c,daf17c39,c375ce1d,2e180758,fcffd82b,26fe206c,af22f29,ac2ec5a8,ecb69e2,aa954f49,63d4a58c,2d6769b2,5255e9ae,2689f756) -,S(a30bea5b,4a911ae8,de11a310,a9cd3616,54143337,30aa182e,ba75601,3d12ab80,aad0f1fb,a9a8d6a5,71301b1b,dd11f4bb,161c26e5,3d3d5143,ad2678f8,9960029a) -,S(55d93940,b0a76283,6aac5bb8,c04f490d,e7ad8da0,4cee090a,e1f381e8,5c13fd27,f1c58d73,b90819b,bab9933d,60f54370,7a625449,d637f01d,bfcd6b44,bb467937) -,S(f6b03260,ae0373f5,b2ebaf15,1a74369c,22535844,13ec4356,ea4a9a32,f2132f81,4fd750b3,7f377f97,7b62580b,6ee7176e,a720a434,8df7aa86,642cc6b3,963cfdaa) -,S(80f7aad4,3deccf41,cf4540db,97150bd4,f4665ef7,72bf6c4e,e551c566,d11d13c6,20a9b836,67cbb397,aadb1211,fbc9a78e,2e998354,6f263403,1d844e7,b95766aa) -,S(4f574d76,130e2eac,16bd6b64,85bdd2fc,88855c3c,68a232b0,29560509,463f0c90,33dabadd,62ec0192,9fc3ad15,587150e8,ead8518,327207c8,7ad2a7ec,c712d268) -,S(41b6872f,f47a0d4a,764ab086,764e1844,a8b4c775,cb2bb06f,643a7c13,5a633e6c,301d54fd,d55c9204,4d337b83,ff17dec3,3faf0bf7,ddf7b5c0,afc8934f,65d54e17) -,S(9f4c75f0,cb44460,ad14d416,76c8b60a,1ae979cb,1ff6a506,b5523cee,8acb1bbd,253d8a0e,985fdeba,1ced50c7,aa3724ae,79c75c6d,7c82315e,65f3b579,5fcf70ec) -,S(25db3430,667796c3,b5f3ec0a,cf4f11e4,73518ce9,aec19932,3f0c5adf,e32f4a87,cce88dd2,ec02e348,ba569fec,15a3c527,ba580e44,c32f25cb,fa6f99f2,a1eb4250) -,S(fa71cf1c,2312c228,c706a7a0,2dc3b9e2,f571b468,913b9cb,3fc5ed1a,faf730d,156df61d,752533f7,afee2781,30763eb9,45a6198b,a78a8288,f30e381b,a809eb61) -,S(f5d3adb5,6d77855d,8e0d0b71,300e620c,f96a45f1,5948d97b,affc3ad1,7226294b,95fea642,5be2e987,968f54f8,f3fb30f1,e9a1ba5f,57b68b1,101a5981,a47f9f4c) -,S(907eec9,6db952f0,eb7d0436,c47f5980,dcae53fa,ebabe57c,aaca00e0,10361460,1cefe286,19dfb7f1,969c7618,e0ed4775,e23527df,6a214754,4cd066a4,65f92468) -,S(abbcec4,36e06bc7,bb92dd79,bcc5d9d7,73189ef9,2546dfc4,54b5d624,2c96e8cc,d1546a38,1f335077,ef40473d,baac9c37,66aba23b,8040c4c0,60778d13,8603be7d) -,S(42f1594f,b1e088f7,2020b68f,7fdd9027,b9638619,b0320410,fc4bec4f,4fbdda76,9a417cab,515a08fc,9e7a7c64,7029a457,9881caeb,df8430bd,c1712af1,3c6b02ba) -,S(a4aace90,751aafa1,fe3e14b9,ead1d460,e1cf029d,cc82afb2,4d169248,e63f83f,97ec83af,dbf32c34,df9cafe7,de0b6ee0,67460d5a,607e1ea,fd13a96d,51999d54) -,S(ac7ef2c9,56b41a0d,824999ca,550ddce0,83f2aba4,8f2bce5,644a579,c0e248c4,d97b0ee7,f3a109bc,bd308b3,e4d4ce2e,c1a65878,e7e5939a,76c9d8f3,6959c5f1) -,S(e9cb9aa0,ab09aa1c,18daf08f,bbdd0457,25d4ac95,8607a88e,5bb14c1d,61d826bf,a1cc215a,124e31c2,e426e337,89736101,b739a56,b6d4e139,ce65272e,2e4b9a5b) -,S(885de0dc,e9700b34,9e10dc17,68f9fe12,2672ed3b,ff9d20cd,93b98e38,ebcc67a4,f66a36d3,75272f66,cad46fcc,cc5d3df6,8c023da0,1ebcf766,f4dfbb0,60e1eae) -,S(8ad4ade1,ff9a19a4,fdc89e75,e4cb61c9,1485ebce,b1e4c063,ccb8001a,c5038e6b,e02acfc2,19c22881,d38a8232,fae54d82,e0b1fb77,e6b8b741,890357c5,be261ff0) -,S(5b395388,a62979a2,b931f243,7f3f65ab,292ddad7,728e67c0,e753565e,578fa354,7e77c8a9,7c274030,b22e802f,f0fd69f4,da65e54a,b50953f8,b9945b79,20fb89f5) -,S(271982cf,eb593e95,17a8fa5,6f62fd23,ddb6c7b3,8e5a87e3,712793b6,f10a2d14,6661cb55,543414dc,e02b3650,8660d54f,48086cbe,4b517092,564188d,6815d2ad) -,S(458be91f,a61f477e,47d7b997,931c992,86281efd,21445349,af820000,58b2a93f,48725c06,e7dbe303,f0c73d43,a5a62b6e,131d004,2bae9dd9,ec12cf97,8df04c49) -,S(763f00b,348c1cb9,e922c6dd,a7e72e22,8624fae0,158af602,457fffc4,cb0bf3c1,8119c3e5,b190c6d8,7f3d7066,72136a3b,d0f1b198,d9f304b4,cfb383ec,e075de74) -,S(4fd5e9e2,77fdf260,8ece7268,10343542,312773f3,2518b363,7075fe98,dcf7719b,c234141c,d3e83309,539aa906,2b17ee35,99a3246d,86ad20d6,2885cfaf,5a88162f) -,S(c578afee,a7e492e6,30ca55ff,8923d9d0,9a6d0583,5553c61d,fe871b6d,e1d956b0,bc2d5e2f,add48f2a,50e357cd,4d4c120e,e744fd96,dca0a959,c0bf482e,2e081ce5) -,S(df02c64e,7a60b87f,73b4add8,5ad93b40,bb6a862c,18e0fba4,3f722650,c0439107,d86dc018,525efc69,cc7b282,cd145650,3b9bddae,607e14ef,3e380d53,c266fe29) -,S(9471f488,84cff3a9,2a99dcb9,4cad96f9,d4761570,c0bda860,bf1b0a9c,32a27a4f,23471d9f,6b3905a2,6d9481ec,dfa10a2e,7c7a5405,119dc8db,de839140,2e063e13) -,S(6d1b5784,f58e5393,fec90c50,a674278a,cb841f46,97da9eda,12013447,a2e0b863,d052c806,2905ef3f,6302892f,48b20497,e89cf7d4,3c345ba5,94233cf8,2586a17a) -,S(94eef4c8,be627560,17e13634,53f733a7,fd590dc1,294cefb6,4d8965fb,3d2ed1d7,49a1e5e4,d72e6a21,14e7c4d0,eb9c9240,b3b988d3,21d2999b,46a562e6,1a203c97) -,S(3206fc87,582d1267,92c2a68a,7400a29f,61097fdd,3ecf4cda,fe495993,87ec15f7,c9a7af2b,88df18f4,fe453bf,fc4af355,519fdf21,9251bf6f,879f291c,32a38eb2) -,S(fcd215,45f8a36a,a5a81bd7,1fb1804d,b3fa112c,c21542de,27cd34e7,f7309a1,191c6b9a,42b0adda,bacffaa9,89bbebea,3424a3bf,11345ff5,2af9c3fb,6193ad0) -,S(4432309a,40f6c71f,cb7fbe26,d6390778,fe6f816,3ee50264,2b2027c4,86fee04b,550981ec,b4d2f6df,fd25f26e,6d65f62e,5e549c1d,79639c4c,d07b6282,2d075847) -,S(7cbff748,7bed64ba,7d6346f9,18e23992,a3712ed,1b7cb89d,a6c0540a,335b582a,ddf155a2,bfb25607,ee6bca12,f6df2a01,98513445,9b353c60,9806fbbe,2d9fbdef) -,S(f8cd164b,ad3e65e3,63368645,76c49035,a95f7928,350c855c,fa534f6,80709789,25412c86,23bca2e9,8d5531ee,d57c80c3,ab01abfc,498cbef3,deeff0e,ae6912a) -,S(6fad2644,990a231f,c27bd678,36ff84c0,11fdec01,120dcc0d,f114b032,1d60648d,6beaeb65,ddd28481,a23af85a,5a417323,350d057e,1a574b0f,5d994816,844d9d98) -,S(1fbf086e,d0adb5d1,9c49947f,d019046b,289c5703,1cf876d0,8cba81e3,7739dd6,86e3511,3d4593f7,a8142c45,8e915fcd,685efd0b,f8cca8a0,79ebded3,f4453acc) -,S(30cc2cab,fd0a2244,2c8a6e00,5b6220e5,4061dbb1,4f8ceabb,6215bce,f5f5b312,b5a1f70d,4a05fff9,9716ac44,57a4342e,7d4bdef2,6cd07fee,b515c56b,19fe72b2) -,S(156efdd1,901ebad9,70eb167a,bb99ac5c,676a0929,3feb0b37,8ba19ba3,6c2a3935,b1d39453,32f0e107,15d06df2,d784b1c3,bac221a7,f184bfe2,4824a368,9ff33051) -,S(48682e29,6b8e8123,c9fb6246,5e8480d5,54350734,bc763757,f319d40c,87f2ddfe,efa5e5e2,be832508,e71b15f5,3a7f1d77,773129e2,e57b2b86,9545cfc9,a20360f8) -,S(d188747c,968b67b1,88958f37,b9990bb3,1a54e3d3,e3fe9e06,7aa9b1a0,87f5e3d4,6d60a049,25660c21,81efbbd5,6a436409,6bbdfa39,b37f70e6,4d13f3ca,6bc76b92) -,S(d7cfeac2,7fdb5922,a5f534c2,b1d325a2,903217f2,ff41b6ea,1e5d2264,8095d3,19618c66,87bb0d92,52133c84,26fb8aa6,4fe1355c,86aaea97,b9ef49fb,de063e75) -,S(dd795951,27b0ff86,94dd131c,e85ca6ef,9aa2022d,d0c7f053,4c83735c,43096c02,caeb4cdc,2633b01f,1b51f7e6,103ede8c,a0ccef5d,e33a8ece,5ddfba8f,736e2adc) -,S(5b2bf207,9a319707,52496851,68aad1e9,5582408,7e5d361e,87b77900,d9c63939,728df41e,69c939fb,59803668,6c44d0b6,f102dc4d,ee146a33,42e1c04c,9b6e30cc) -,S(d2a26a5c,313aef0d,6ac190cb,11c84771,abf97d8e,c7e6e67,bd3313fd,15c2ba11,84a1fb57,1507d012,9d98ebf5,34fac803,5de7a43e,48868269,d5e9656a,773fe768) -,S(22c22c99,860b2b6c,630487f2,5263e77,91b62450,290e9df,379efa7,1edadb52,d2b227b3,dc85c1a1,ed64a7e5,6dd6b178,ce0ab5e,68647b50,1178ac78,4b7d1c93) -,S(b811b039,d2cf5f3b,95e38e2e,14da67bc,417cfd8,623593ee,1f2e924f,d9a064c4,a860653d,ca39030e,8c1ed7bf,aeab73f2,a68cb8a0,5263aaf2,431b6f8d,9c862a28) -,S(59ee23c9,26b38d6d,d6c091a1,d4adcdca,b3a5a548,a5cdaf92,fee9fe2b,c3cc2957,67462318,96e4f107,67e39d47,b03268af,5b54edb0,9f9e8e0c,3f3f89a3,e9d204cb) -,S(cc79ede7,ca5a9ba5,a7c5114,d2039d5e,c6a54db8,fee6c102,577a20d9,18ba857a,2cdc980,3a06af30,c19b262a,12f54132,933ec985,afbd1598,45c40be3,2e24861a) -,S(1319c7a6,2f3959b4,cfee1223,b225c6e9,9070753,a1ad33d8,8f3a8b78,a886f7da,d8a75f9d,b8266ea4,2b650265,6b6c0ee9,7f3598d6,3d149ad6,9a5829e2,f3c29085) -,S(e4ae90fd,74e9b229,b9100cef,1da59b80,753b4f0a,cd7790f6,34930a92,b1eea356,370f1c98,f72e698,73c8d0a4,e76fb117,d7e5a9a4,d13521f,f4902a1b,ed3688e5) -,S(286a98b7,b0b0527c,310afd37,717b5061,467be24f,8a0b5528,52ff26ee,d658988b,d10699be,f79e800a,519b964a,163cffb9,722c3ba5,b56694a5,c1a9b883,b32965d8) -,S(9b8544b3,79746ba1,8524e084,2d15b853,46577b81,7084e02f,7d0cb820,7448f5d6,8421c0f2,ba15f648,246f9cb7,3b10d6db,1de7aefb,fafd9b52,16234dab,8e70218e) -,S(81efaf7b,50a18c8c,2481299,bbd2adba,f3510ac4,f871c3c0,f849ef6d,4550681a,ea8567a2,9c871ba7,fccea923,fe07e8ba,2071d7db,25d33ce7,a6125c0c,2afacd17) -,S(6680fbdb,dab850c9,115d5765,344f1466,b88cc5dc,8de9fab,549f281e,974ed7b,c7871b4b,2690f4ad,1e67ea81,e2cefac2,988082d8,b1c70e67,4389c79a,bc880368) -,S(4c38ce7b,a8e3d317,6f615d6e,27578edc,746fb80e,4701efae,f7557469,a1dce4bc,f6e73d73,61ff5407,10dc9f1a,4bd5c1eb,a7d8c8d6,45f0427e,a4fc3e45,3990b88c) -,S(767146d6,bc1d5bb9,c73321b5,4cf6bc61,e8209703,fe4dddf7,2b3d6089,da60be69,86df7dc3,6894f88e,fe24a4ee,fc78b1e0,fbb5138d,31666be7,97b8934f,d0b9a37) -,S(bffd4856,360c02ac,ee741a65,486d5a7,44e2a005,9db5ef5f,f87b9e18,3adbed20,c11246aa,3bd4ec3f,71f88d2,cb3b96ba,2c210f90,d8234c21,99bf7781,f96ad781) -,S(ad19b5f7,45556650,eb496450,968d056a,fbcb55b6,8852f510,ac96df54,cdc677c0,f78295f8,59445c52,d6ea285,3fe9baa0,5e453bf0,9b3f4d28,6c99e858,62a04bbe) -,S(5924f679,bb94f6db,d8232b01,ca8dfbcb,37a83d24,d0e7026f,b526162d,c82aaac7,baee6567,6a526460,ec7563ad,42482d37,a42f2fcb,f4a5eb7,b37b515,a6c3f1b9) -,S(dee240ea,c90d5399,89d3b3f5,764e0680,1e601a4d,f2c09226,21eb0b7f,bb53ccc6,12668b,72cc139f,5f9fff4c,ef24b5ec,d0648e03,64c17417,f35bfca8,b819316a) -,S(e288a00b,e18b0987,9765940e,caf8972b,1a09f67b,fdc455c8,8e3b4ed9,dc0dad81,fd81e0a5,adf1df8f,42c64825,6b107d44,887d01da,f4cf89c9,11529124,16a1e4e0) -,S(e747d6c7,3f5366ed,241501a0,ca6dc04a,aca7241d,8effbd94,7d3e6a0d,bb6eadb,9954822b,15f44840,9c9e73d,97722194,1eb6a218,ef1ef4f,269ab118,8f9c773c) -,S(57b8865b,ac78b9a1,c244452e,8057be3b,4fe2c6de,9ca9a295,ded04377,2b61aefa,d0e46172,8828f0d3,f1fa808b,1dea8516,b0c30d93,4acc8c90,6ca2bcad,303f06b7) -,S(abda4b38,47ed5cee,7ace4e8e,e652336f,26a8f4bf,4bd610f6,e87e5936,e4e8339b,8860963b,8f266c30,9c6a00c6,cdb44048,a9a1b76,d0a5a652,b4453f7d,330bdd9f) -,S(7f05f2d9,5621d06a,d344bf91,7fa8b9c4,2ceafa3d,fabd0620,bf7086fd,9539e089,298ec6d,8d5a9506,8d916678,dc8e62b3,7b6fb9ef,7967da8a,8419433f,79922f29) -,S(99e4f06b,b8845bb2,12638573,63f7cfbf,3f15570,44256dab,21b5a8fb,c43e2453,5d76066a,86d5c498,323af928,2c3bf419,acb758c9,7883d236,7d9d9e3f,eb8e1417) -,S(ff994b1f,6447ae81,8bbbf97b,8b6d655d,900b04ad,eec06fc1,f57eab70,95375094,6a63980d,3a9324a1,9339a073,977130de,d0fddc50,5b86ff73,464dae04,c3004a68) -,S(3e9af52,f00d1993,8b6205dc,7b6f8ef3,31d624da,fdb2f09d,fd701b78,ed8b0471,a674914c,ac86037b,f0585de4,d867424a,ab9841dc,83c0ca8f,347e16dc,1407167f) -,S(eece935a,e5cd4afe,baca6998,63c5e8c2,e0b338a3,e2ae7dbf,e34102f6,f1c613f8,be70c210,b925dc66,c8546e65,ae9600b4,21a9f668,c3a09a01,8bc5b88b,91cf4d74) -,S(bf10e625,7d336eb4,a962bd97,4cbd9f10,76787b8b,90575250,7f0cfc2e,121d1276,1d93f629,8ddbce2f,1f670326,265c4ba0,f7f5256b,472412f7,a24f999e,f4e1c64c) -,S(73e43284,c80d4ea5,c992ffe3,cdce4149,d490843e,bbac444b,f47ed5a7,3d6e0bb4,82cab83b,c7d2d2bc,87881618,54034d7b,dab132b0,6340b316,964854b7,f2ee3e6b) -,S(5410340,b614b676,63173725,ecf0b8e1,67c2de61,ce999639,be2051dd,2695f8b8,f191ec95,9d6fd8f4,eca243b7,8d844214,976d97e0,65218487,3366ca25,f2e6a091) -,S(203d28e2,694df7a5,6c9b9d42,907c1e02,192e8030,77ead781,8198b2a9,69b127fe,c06fb7ff,2361ac16,a884f0a7,9e4f5a19,b0b5b207,9901e634,be237643,ba93852c) -,S(f9a1e3dd,f53e41b8,84f7c4e2,c2b47131,8d14705a,4e7362df,3221222e,6b2c1921,cd150a1a,abe8ea0d,853245eb,509c1d4f,e26c54b6,98cf9aad,26849a7d,e63b6264) -,S(e82e5e89,db35aedd,4d63b7e,4d55d637,cd2eafcf,f16ffbd5,b0fd1444,c7c783bb,6701a95d,ccae2272,2a834957,e0a4a3b8,3cf5ff19,2f41e8,1619dc46,b8238cda) -,S(9fb768b7,16032fd7,f21315b7,79776882,767d5d64,c9141267,a0ddedb1,55d4ae08,13474a8f,90fda6a3,43e3ea23,e858327,dc2f4c40,4a445f77,4b39b92d,a312574a) -,S(d0793463,ca7cdb50,3622f1cf,90032794,52af3fa8,1866e536,159fd23e,ba6082d7,35301f6b,66858d6a,3e97480b,ec3d2a53,8dee8465,ff5c15a9,1144ede,a208bd0c) -,S(cf8fc191,273383df,f1d703f7,bb237ea6,cb5d1307,8ce8ae62,67fd20da,4d845e05,efce641,3bb676e5,5c0b64d7,589ad771,23900e0d,60feb71f,93270390,ec66ecc1) -,S(f12aeec7,55a7138e,4e91024a,3006db3d,eff6ec84,ffa73d96,da21ef00,452064fd,f0f0660a,22cd7cda,25206f10,e82ca005,3a40d539,472cf41c,b86ed8ae,3d29abd9) -,S(3c40f94d,ab460ccf,c8e47a1e,d015b074,ebfb6142,fbbf5b4d,e77aca70,be67c57a,998efa4e,26df60a6,f1a466f4,c27b2dce,ce6367b2,e05a5ad9,dd71ed8b,482ce55c) -,S(f2fc6db0,49861d3c,a01a6778,22299264,88184967,3802ed49,503857d2,2860f00c,79f0f245,1cc6c5b8,d36c330a,ef8c9c84,95619911,1d4a01a3,d9363382,8b609576) -,S(35d3e3c0,29fdc9e3,88da1cf3,d52df6bd,9ac0ec9e,e591adde,26d3e414,f4fb92f5,62ba2346,6d19ec1b,64d2a6cc,9822feb8,e03df178,3f526a9a,13d10fa7,72de3219) -,S(5628da0b,cc2c0583,902a56ae,711a2217,455bba47,c7222dfe,d60580c6,461b4ae3,1cee8f17,8ce4c7f9,8cf2a2c5,92bf39aa,57616913,bb66f232,a813904e,7b574ed9) -,S(7ec54044,c3fe53ac,8437a540,968e0b,b725e794,a8c240c6,5dac1f12,4ce21be3,f6290891,af9af62d,5dfe10b,d567af1d,6b4b22f2,8177a14b,44edcd0a,be811c0d) -,S(eef7a7c2,a0224a78,aff7c61b,d2379259,7b307a20,bf1c253d,6f03d57f,a8a84203,5c7d6875,905e26dd,2fa4e5,24f73b00,6f4bd0b6,786639af,5d222411,bf69daf0) -,S(3f1e6459,38e4285d,ed30be98,1d149f68,24b264c7,df920f0c,c5d776df,83228cc3,a6a5df53,856be619,25e42d58,2f705567,39c3d7c7,a6e222b8,6385b63e,d1316916) -,S(c83ff186,ae3f42d5,a2c39b43,7712d607,92b9006a,d8bbcc89,97bb9b35,d1663cc6,2380aa52,44674eae,3d96d65,f484e7a7,62cbfa10,96c5a313,9eb4628e,77b72d40) -,S(41d20761,160125ae,c669b1cd,395110bc,94e09a,ffb52ef4,e7e86e,1f4a61a5,c8509f71,2c20aeef,7399d11e,7c438d0e,9b4dec72,76c1013e,a4c76d31,ee5c7496) -,S(cd358f38,d2cb11f2,9fb54431,dc5adee6,721c444a,8fab5743,1149e504,8ba0dab8,e6ab91a8,79a51f40,cf75e405,e508cad8,ec54dbd8,2dd4115c,fda7b255,b1a6fe1b) -,S(d1e1851d,cc95a94c,a8c77b42,5b4430a1,ac10e526,e3f4c6dc,f20267dd,7c5f2d2f,889de789,43c6674e,6bf28470,3ef8867c,8d827681,d2df8bd7,75384ad7,15730ecb) -,S(89268637,1febc520,14709cc6,b2aeb5dc,32e06b14,cdae3d76,b1bc04e7,b9b5dc8e,46823e42,9c0815e,ff99cd7d,f3712f78,9c102af,173b61f,8de08519,f19a3783) -,S(c7341942,420d4e63,263a144c,8a10d22a,fecb1bef,64f926a7,83951e0f,6490caee,925019a5,212e9de7,2e6e2336,c3e2aa75,9511396c,a171412b,53c8f9ff,3743dcd2) -,S(fdede5f,38d83f9f,a4ba3218,fac6f0aa,7c9f464e,33dc59f9,8a3444e,fc0ed7e7,26e4cd3f,3dcd6a6a,211bc8d0,65564250,49c6db2e,9946dcaf,43cb42f3,b0f20449) -,S(b2b5364a,eaedfe4c,f046193a,6777ec1a,1841436e,3cb17c34,9d27f42e,8e536618,32b886d0,f0f94a7f,1b1d87e7,4f2c7dcb,ba4a5dde,8e93c864,f8f48bb4,50d08ffa) -,S(4c3693f4,52a95b79,85e39982,f316897,93d289cf,66b3326f,3e1cc77e,457f64bc,48d7bdfe,fb8c3abb,584db0b,d3407ed3,3e543715,d4ede995,df0e1b8,52e12123) -,S(5cea23d4,927f0385,57f6bc1f,b926e594,93250b3d,6d934a16,9265ae08,24a35e60,5806886e,b01ca724,8434f2f8,be33287b,d9cb3c3e,b927bc4b,4fefbd51,ba98b5b6) -,S(db0a50f6,b4558c10,61a3ff88,1da60f9a,77b42469,a9713c8f,8339b8a7,b903d93,7afa6cd2,57685f49,9635d15c,bb7defac,d6f94c17,aa19be02,4e2efc70,d84c45be) -,S(b0029adb,25f32b75,8023ced1,632de91b,3e3e55a6,1abb56d5,aada032,f2c01ab5,baadabe2,2ebc5fc6,d5dee65b,262e96c,63c99fc9,13277d84,9ec8a730,e1bbfe91) -,S(c336b077,3ce16975,bc204169,8126a40e,f8cad886,6a52c50,c5081ba7,b878af5,6f46f5e7,b82aec01,ad499340,fb90b81,420b4a3f,977579af,d3eb0ce9,c7d752bb) -,S(f403fde4,7232a9db,9efda1c0,5df49636,2137f5c,aacdfc93,1346dacb,d2501451,ba30815c,197de8f2,258c83d8,dd7ed0cc,cbb5388a,415b8629,2cf5c271,2e75bcbf) -,S(85cd71a2,20beec1,3edd0133,6b0b85e2,da056a1c,4a48a328,f371af1a,ee502c30,d6accbba,491c915e,88474b92,bf23c740,2648085f,88a62d51,b26954b3,f6d2d4c6) -,S(324d65,b3c2bc55,d3b2a125,1b673ecc,d26d2b23,e333849b,7549339f,7f0d9a42,83750e95,32086164,e9aaec58,b6a2f00a,3838d76a,208d6453,14042334,b4af616a) -,S(322033a5,c90d7a31,9439c368,b1301f1b,d088974c,91560063,793b6f2,63b401f3,a61f4714,488bd2bc,84bdb122,c615ac94,a7d05157,e6d961df,4f873f5a,582e4606) -,S(a414ed01,691f2a43,b18dbda2,2d3d009f,f94f8b02,672e49f0,58dc2323,b71f5836,2fa3e483,a12ba874,12d709a9,47cdf22,6b96523a,ac7f4afe,c93f98be,f97ec01f) -,S(774310b1,7752d7bc,d8b3059,f7f4cac9,e661a841,9dcb20fe,355bc7be,3a4c65e9,b3333227,469ec87f,19e14e3c,98148b4b,45bde0f6,698829e9,3bbc9313,56e18b12) -,S(fbb23c7b,5c15bbcc,7ad0118b,6826e385,3f6c4078,5342ea57,11109f8a,27dd11e,b12ec70c,9b4c908e,2538f4c6,b0b3d548,ee199f9a,1e9b6535,f1c78081,41664ad5) -,S(4bf836d7,fa7308c,89b075df,1f336fc8,af3c6ce0,64e1253f,853f623d,c483b400,8b368da,424e5a83,48cfe987,93d47a1e,1e9bbeb7,3f5282af,82e12e4a,c7eac850) -,S(91b4a84a,e521232d,71e3d202,49dd1b3b,d134509f,e3e1ed1a,4e8b5062,a438bdd2,52d30545,4972471e,6900afbe,2471e1c9,16c82ce2,2f955ab8,454f9b65,b70ed759) -,S(9751092f,62147caf,f3953cf4,8a117082,37a78b6,5bf0de56,848da1e9,4c3c3a42,57fd0a15,fe069db5,5fbe870c,96d4280,7b9ebd87,33908bd7,49ba0121,a900b08e) -,S(54439284,6f6d46c9,8ac10a58,ac3c34b7,3cc5569f,8f9fd7f3,4e7ad2be,826bf293,1aff0b85,e5b9033d,7c44e877,57513317,a17734d1,13043cd0,780da032,2dc3ed03) -,S(172704b7,fd7f5560,f17cb6ff,ff9a0144,9a05a113,29b86df0,a8d3256,ce139a9f,a416c0af,b170cdfe,169f894a,b10aa97f,2c068a4f,d70a6878,ec9f359f,e8323bea) -,S(2236799a,a82d4b64,5f412aef,eae944b5,e28e0996,8a243ce5,b8986861,6f735dfb,7f20b2cd,af70cbdc,6aeec02a,dae1535d,4bd919c2,631ed69b,9913771c,2f482c1) -,S(6a52af7f,c6f75636,c33047b8,9f0eec31,66bd97d,8df6579d,2e2a441,6ec4fe8b,4eb0813d,220849bc,e0b948e9,a6efcafd,339f8861,eacb9885,40ff8e1,acf1efdb) -,S(8696e0b4,ae3f0dea,bf6d8dd3,854faa5d,d07b01a8,86f710ad,9b4cd84a,5d61a617,67633be1,a662024f,77931f06,38884175,d2c234cd,c4709637,4711c79f,42a897df) -,S(6c4b727e,3bf9af50,fcae1ed6,163ecb00,142d9a53,b6d3f54c,8aa14064,1358ce7e,c4f2665f,395af262,b30561d1,48bb0f4a,f5603102,80f57f40,1506ec37,2bde79a3) -,S(a51d2296,98aa29a9,6d0e5510,f3e815f9,cfc6d492,dd0b2fd5,bbfdefa4,984a6934,861f0848,7658d4a0,141e9d38,aa0e268f,40bad7c9,e2615a37,7a4b974a,6828d525) -,S(1afc4051,cfb5635f,9c2a8477,7dee5fd9,fc4d40a8,3ebe2f89,f36c0b9d,8327288,61ac4eb9,16567e13,d1b03ae7,ad5c3d8d,ef85bf6f,387c511e,bba6c237,96e95f7a) -,S(f8fcde05,5a2a92de,c65d1842,6607a939,b3475abe,2437c5d3,88387fd4,afdff590,4cb8f7e2,825625ba,e3f179bd,4ef94560,6e186346,61edbf48,8ce51ea8,ce1b0404) -,S(cb3dad82,7e7464cb,5fed0cbf,7e29e6ec,112ea411,706d10e5,c1fe6fbc,a04a3e9,a33abaa7,6c9afe3a,a8ce5add,7a2a056,b396cdda,2a002161,3de97556,a0364629) -,S(39d2cea0,acf8059b,a6275a08,ec3a3664,f09cfc43,f143c317,bed8d751,33d4ba0d,6beb4ca3,d3009ac8,881d6d15,e0a29eda,6738befe,e31707d7,f95eacc5,fbd77192) -,S(90bfc4da,3be2d74b,ff9b5539,d0787bf4,4a1b6d7c,2baa14a1,dc6801d4,42187f96,1254e7ee,c8acb35c,fa0695c5,85f61b69,def3ef5a,6219fa97,e3b09dbb,351152f) -,S(50772bcd,454ae992,f97ac3f8,9d8193d5,ed50b69a,b2e62e04,d6a115a6,6e71c977,f199a8f6,f78b0b97,cc20316f,66177383,64338fda,3eee7f0,f36eb0ff,64accdcc) -,S(afe51284,f033bb43,ac6feaea,9520e83e,f2cc1e42,9e273bc3,1b087161,52ea6926,77ecc481,9ffe6efd,33592907,17d22ceb,f4344c9d,f5f5ea4e,4d443d17,25c8aa1e) -,S(b0caf67c,151b838e,4ecaee09,c7908c95,bd3ef86c,797a5a8d,71cb3bf0,3a46ab17,10ae756,7bd2f6d6,712c448b,34636eea,2c7c3d99,98901308,14825b4e,423284bb) -,S(f2766b4,8cac8f6a,80a7cf39,81725834,d186e88d,735fc7f1,5135ce58,43b3dc8c,63590fcc,a4e21c39,50cd78a0,569c0d2e,959254e1,4bf2ff22,8d8fb216,b53601bb) -,S(80d50e7d,28269280,f8ce0dd3,6afb9f43,38df0403,d5661c99,27ff817a,46f60a0e,22fec5b9,7472824a,9b2ff25a,68d947a5,a8952ae,b763f37f,70228978,514cd22) -,S(18114ad0,7097b5f3,7d788165,e45ca1b8,462da0b5,78e5d37b,e4be3632,35d2fff6,87c5f261,39cb366f,25fb6bfa,fcc8408b,f4c69c81,29df3cfe,9190213f,8c15a66f) -,S(3bd52737,68294cd8,73a48831,8f958e45,85871165,c82cf6a3,9126e378,43975444,8c92d391,e39a50f3,4388510f,c8dbb686,27f29251,92ae8edb,b2613948,c01281ac) -,S(acf47eeb,526208ba,8a3de26e,481a86ac,f17f5f88,81d89d43,ab8a5a26,e00db5a5,b451b4cc,8be8339e,4203c913,98b9a29e,de86a91d,3e347688,53442446,429ace0a) -,S(5e39f375,87a07536,86bcd792,1183c424,20159044,a9f66ecc,2bdd552c,62ec35c2,b7131328,297c6995,7df6783b,d9bc550d,5c553e1,30bfc3e,fffedbd7,5e2d003b) -,S(315b67c3,d980796f,6f0a5505,ff2d25f2,8551615d,12bd73de,b10c4897,580371ba,dfaf812f,7525e087,2d11e10d,612004cb,3e2a7024,8c40416e,5020ef66,82d3bc1f) -,S(8f6764f7,73810396,62537cc5,aed6a8e0,318654cd,a95d8695,89fa471a,edd0d7a0,b91cf5db,2994d207,135c1dbf,b9d9d78f,7e3adea5,8c176630,c09140b7,f5c67e84) -,S(e844b948,118fc6a7,eb2f96e,ece3cab6,def55940,75c7b7af,fcc5603,f2012f96,707668d8,89db03d1,561596da,a831aa92,771a0fb9,e1b21273,d11a3415,82292314) -,S(fbbedfd8,4144785e,fa71e234,59973cb8,87deda88,971eb62a,3007f350,1fd0ae4e,51d23941,cf84f121,ff1e6a5d,651d9528,6ef1d803,819ce64,3aba8d16,67ba7dd9) -,S(a0190399,c692b9a,db172ba8,348b404f,19442b60,4df60142,f6330f36,ca6bf352,6ce7491a,b5329042,25556069,71502da1,601e3a04,f38601d0,80b31654,20fb527f) -,S(d240e135,4b9e6dc9,110a6b25,afcf35e0,74fb02fa,f3dbe484,4f46818a,89bca65a,d704be81,e2597460,6014ffcc,ef12563b,45faf24,3e070727,64f341b8,7dfcdb7d) -,S(39bd84aa,f8a15b0b,809888f,133871f3,c40ea5f,2825582,a35fa9a7,808e5e87,94ad6588,658752fc,ce45ea1b,752ecd02,2b621c5a,26908cf8,69c44584,1d831d33) -,S(2172be6e,dccfd021,a56a553e,53f814c7,c7cdd55f,d181d671,4ade45e7,72093142,b21439df,f7229e61,cd3b7c77,fa750a94,660f60a7,53da96ba,d8ca7e20,69abf76d) -,S(57db209d,a40f30ae,fcca7838,2ba525e2,231343b9,250a1b1f,67fad7f4,d4079594,34ce9bac,bd35557e,2f73c718,4287b493,c524a3a,d6b403f4,ae777026,42fd37e3) -,S(845c2bc3,3683d899,8b90a2d5,ff299064,5214b272,a056ed93,63621406,d3a4cc11,44a46738,839b2e3e,1b6b19bc,56a1ff06,7754126b,20654e51,3a1f13c6,de4c6535) -,S(705af30b,251cc64a,26edc929,e3e9ff3e,32ada2e,69c2cfd0,eefce4cb,a37329d1,c0e693eb,94c0c1f6,cf1a0ed4,8c9b13ae,faba8ebd,926c4fe3,ec9071be,2db463dc) -,S(9b2a64df,9b1f8e,34844e3d,920b1af3,14df1b7,78b863d6,f1a6b94a,869061be,5ff03134,722faad1,ab6f87f0,bc3c6abe,8406bdf3,6506b662,6d066ce1,fa6a7cf7) -,S(494967f0,1a0c07df,e7d9a8b3,e6a4ad13,893a894c,2619238,7384e38a,d514cff3,11ba0803,72bc4ffe,b86e25c8,b69ea450,5f6e3b24,504b5e38,210beff8,5d82e1af) -,S(fd547247,812e4233,55c4a977,4dfecfae,812ef2f8,f3fd832d,a3af2ac9,257d50a4,65ed23c4,d776baf4,53faf3d,d3edf65a,5d9935ef,9e22fef2,53319e22,ca4bf51) -,S(4aa16ea2,68ae95b3,2f405fd9,6fa78478,7c369015,4c124733,a07c1953,874b6246,4306725f,579fc013,2cb8c640,7361c7c4,685a2a49,532fa14a,36010779,7f5104e7) -,S(de6fdd33,8b6eaad1,bec84d55,992a5b74,aaca294a,5f804015,796d69c2,cfe67add,e58564e9,d2cc10e7,184d65b1,7e0271a7,f2e59073,bdca05f,ae664f82,7e6fba13) -,S(c8290adf,d0da5f1d,1805f36f,288a8709,eae0b93b,1a7490da,5ffc29fa,bf834592,ff161787,f096e022,f513afc4,e0b84d73,e7f9f347,798e1026,931271b0,8f1c8a87) -,S(1b95c512,815603a6,19750d6e,463d5a33,55f09c22,56484ae9,8f1c76c1,10ed8fec,93b3750c,3a1272d8,bc9e4c52,b5efb6bc,d794c2c3,939bbea6,1848c9ed,423bb39b) -,S(ac0d9939,104bbaf4,d2eb2560,356f2bd4,f1037ee8,397f0703,b7ebfb49,463a22e3,c6e6d039,d6acc470,c1ee1013,722c4a00,4c59e472,11da3025,49351216,f0bb8985) -,S(d8c8f5b6,366c1d29,b2f28f53,8645b17c,f001ae59,71a19f05,fb6ebb3e,9e36faec,5db24ba,6d78e76b,42262b65,e631390c,8540b72a,746cc5b,edc1b681,8b1a113b) -,S(d42ccf6e,6d1c663a,3dd95fd3,c016d535,c50e394,fd63b353,2949716c,49315737,e7337f22,2d353eda,651087c5,13cfea43,96e9cc5e,22aefb4a,5fb3ea8b,579c7298) -,S(53417fa2,4871adb7,6d875c05,8c46065,681f6372,95d221db,ea76d88d,f687b817,d014e6ea,e00c4ec8,ad931dd2,5cf569d2,efb3068f,7aaf5ded,d4978546,1bb31d76) -,S(202e9476,53b677a8,d7aca305,c52af8b9,d33b1ec4,c5ec94fc,5f7775aa,c478f150,539a24fb,211da532,b378f3e5,cdd688b5,c57343c8,2e03a637,39544c8b,34e3087f) -,S(434f1027,72aa0555,8bcb2f6b,1f64bc8d,72bf1bb2,8b972c3a,f6f342d5,f1493f93,a9db9031,f2d1b8b0,e5840fc2,b4534970,90aee2af,5bbd83d2,c14a5ad8,acbf8c14) -,S(a0e54d1a,f09c47f7,cf56d3a5,725d6777,9fdf920d,3c1dd566,caf71666,de7d5d17,87f5db7f,197185b4,73cfc293,7b0661ce,1ea92099,fbb51151,63c2b26d,47ba97f0) -,S(2d43cada,5455b682,f6430cbd,96a2e316,ac0b4b27,e9fb8777,a94dd2c5,81c0e350,bcf18180,1c1722db,1bd9b8f1,8a1989c0,fb372acf,fecbf9f2,c37ec4b3,b459c916) -,S(e5e6dd12,6340f04,431552e9,903ff4a3,c309ea1e,c498e483,e19b9cc1,37418d4d,58d35fe2,24ab47d,93cd53,fba32252,4a3ea9b6,d96390df,25935a1b,dd12126e) -,S(b112e4d3,ff9adc6f,706cac35,195843cf,302324e5,6aa7305,9c8b5f3a,6dd7dbc7,4fe76714,6529e6f6,b0379366,334595be,efcc7cde,d3596ed8,83e3b30e,780dbccc) -,S(d26b5261,ca7be739,95de1bd4,d75991ef,4d357fa2,5c8d513a,e209ac6f,64ad960,5f3b8e07,74e78bb7,5c395bcc,8512f2c0,1b6c451b,5c8d6ff4,18f9ef35,30c6d046) -,S(e2e4f568,eaf2807e,cf43ce08,3146e961,92271bb8,d6d9b24c,e7315b00,1cf04fbd,56894a02,58093a34,22f2ad5e,548158fa,c55ce47e,d00ede05,40434424,4e204b93) -,S(a62080a4,2d8aa307,32255b2b,a239d9fc,19729eec,1dc24bca,67652705,9b1182cb,ae848a12,893c34f2,260c33c8,ce2bcb7,14fb1438,8e6f3f06,d9192549,6a9ec13e) -,S(684c1647,7771de55,ddea8aec,290c1e25,65120fcb,fc8ce0db,4316dde3,f5ae8d91,ba85dda9,44dcfdf8,cfca86dc,ba902675,3d99e751,5719e579,64e0fa0c,3be1f06) -,S(3d730e7a,afa97950,bee35934,da18648c,d0bd62e6,9a49281c,b63589d0,5efbd2fd,c28545f2,3dceca1a,ad0a9c77,23b61519,44a3c984,d57517a7,cf6702ce,f4dbb630) -,S(337c9584,b49a49d9,29b1212d,dee7ecb6,39f007b8,9ba94180,80c9548,459c48b7,b26db317,3e996893,fe1e0797,f75cd05a,2eb23ddf,4806407e,1f173d29,48bb0bde) -,S(7013edd6,f49ba92f,9c9757d1,d3374229,706078df,c2e9c64c,c2e84cbe,85c6b5b7,e850419,7975353b,2863b577,d6f0c392,a8c5bdb4,2dd557e9,8e971114,5e078de4) -,S(9877cf36,bde592fb,5f4a4581,2bc3c39c,68ac9956,23b3487a,635d6e45,89e26e1c,6207d384,737a0d80,fa9f42e0,57684584,efe1fa4,5cd73eb7,bd50abc3,2722f159) -,S(6d35bf57,1c91a2ca,1765ed62,f9b2f680,cbd0955,bc76332c,c83a7378,4bf3eafd,47a589b5,15a88d78,6f94f64d,674182e9,7dd12450,ab3ec375,a9a31d8a,375e5f7d) -,S(40ebcc0f,be3a2a59,968bf6cb,4d638873,5468b532,80a9c96b,639dede3,171db2b8,c2181816,ab9f0d72,c5cb167c,5bbf7e57,9f17d7f4,484996e6,3a23e0dd,5f5d3a8f) -,S(90de4b6c,3a5ccf14,cb033478,577461af,8c347731,9857ff40,79e6ef27,5e557b87,c534bd97,a4af903b,f307c1ce,549a9976,70edb69b,c76ae827,f277ffe8,133cf394) -,S(54e89b59,b73c76b6,cac52433,305c41b6,8f50df66,9b99f47f,599504ee,93ddb110,d307e828,1e89cba4,86ac125c,1c5d8bc,943394ee,222b4b06,f4e3e5c7,b5da176b) -,S(f2ef67ad,60858ac9,fb03ad25,f75f85e2,e5ac151d,95c96967,93ca080,58756f2d,92c0dfa9,372e1e7b,7363f229,2776c059,56742f60,7b100be3,56dffefb,bcda8cf0) -,S(65b7d935,a71dcb6d,eac70b64,91b9fc50,35c63f21,655a856b,afd00a33,52f5be39,b0773657,cbdd3813,8f50813c,558ddbe0,3f8ad81d,e420401f,175bade7,1429927d) -,S(6e950ff,6471cf66,72ea542f,cf05aea8,2c2e1e0a,c2247021,4c78895e,e291ee22,c0ca0886,f0ac828e,21a5c60,776494fc,a6f19e71,741de92e,c11323e7,e874788) -,S(c3b15f8f,96c0079b,471896ac,89d7d11,8ea1607f,18a20627,fb18e1ff,24ee3c1b,33a033c6,68e3cff6,414835a6,ae3f89f6,643326cc,7e149f56,99ab4fbe,d5f506b9) -,S(9e333d9e,1c022776,da901c19,e6936c3c,1af45491,a93e9405,ae343c54,775f36b4,c6734e91,3d013610,6c77a1d3,ced1babb,a6c6723e,316c3fd,34a7911f,cef616d7) -,S(398d2109,4c0baf8a,ab63ceb,6aa6b64c,678bbe86,f7e01b3b,8c0ff291,450244bd,f1ffb185,112ee219,24a1702,183f9075,471611e9,54fafb4e,36f6acc8,4ac7acf7) -,S(8f99c7d,553ca4ea,b160a07b,6d457058,90634086,80c709c,530aef44,bce43c8a,52a15e23,2e90d233,211d707d,5849e214,1f56e8d,189783ab,3c09f37d,b86a776c) -,S(8d798338,b2774399,487fe227,e2d883c8,39698301,5f01bf00,d154f4f9,296512a9,7cb53de9,9303a6be,9aee01eb,3a5c115d,eff0e18b,2cb5e852,75e9b7ff,53e35666) -,S(c9d6aa,ff6b648d,69416bfc,6e4688c5,cf13b711,29c785e7,3ad1e04f,ba02be57,9fa83446,5405aa0f,332a6aa1,922e3fcb,90de108a,db01796d,9045d423,ca0c2632) -,S(f736cad3,f1264671,f2e79bc9,c21551c4,aaa5da0f,befc1928,b9e7fab1,f59c8c5c,2ceae81d,16206893,b3810abf,d2aedb5c,55b79222,1346cc9c,908346e7,cd3e661a) -,S(7748965,7c1fcd79,60fa4a8,36feef6d,835f960a,d3b85009,7462a71e,8320a34d,cfacdaa1,2906f705,d83212b1,55475160,e02cde20,71fc5c9f,6a6d59b6,8e100aa7) -,S(279f43f1,e26ebe73,34924bae,563a0e34,e5cea7f0,eb9f5702,129fa6cf,8b0c67a5,eb5a49af,bada9830,7ceec508,70a49027,7d1cd6f7,6f332249,b2cf2505,82a2a828) -,S(cfccc083,9bbcc7d3,5ceca575,3b9148e4,ddd4464,5727cf47,26f33d62,d83a6a03,e3cc09a0,9d26889e,c969c734,a3361dcc,d638b17,608baa1c,e7cbb99d,a5bc23fa) -,S(e60b0451,70c2e3bf,dd627fcc,5eab1218,d3d598fe,a41f6bf1,dace1a35,2daeb287,a493847f,4f1d3bf,9e90c022,851bb652,691af15c,f4c6c539,bf2831ae,9cf8f2c8) -,S(11875535,ebc90fb1,eb7a08ce,90dede09,fa8cce24,b3911fa6,44ce8111,8848b433,2fb1757e,38148919,bb197d43,48aa536f,c0f06f9a,859ef737,ea50b1fd,82968ce) -,S(c69559b3,75cdaea3,56003ad2,3edd8ca6,c415868c,a13a30d9,11d4c694,f5822179,a39427b4,914b58fb,dd35408a,67ace872,8c299a39,278335da,9228ac85,24652906) -,S(625ff5c3,1e951b28,40f431fb,4842f510,8b738722,cdd52c4e,fdb495ed,e42f1f7d,a3eb00d7,4eb30337,d3f61ae9,d595996e,c7d5a3f0,ceb39f23,3df0f5ff,43298d7a) -,S(1e2fb107,bbb46666,8c31a927,3ce57baf,fd1df905,3fa28286,196a03da,74327c2a,aa882338,5261bb03,a8d8793b,c8f98330,97c22731,46ded3d8,966b16f,337643e2) -,S(d0cbd747,970ab0f6,19e5e4e7,78709399,b65b3f14,24a084b4,a2dca8ab,10d76ebe,7b5f778a,94d3d75d,57b5e979,3de246bb,f36669df,b7dcc24a,ecf4e153,2025b73b) -,S(ab4c057c,a40b84f9,10142209,a5c173ad,6ef31616,db80bd13,61959f11,b739f9e1,598f12b3,4695bb27,ccb2fdfe,a0911ece,eecf2cc3,1063a3bd,42dd100f,e93c7ced) -,S(f9c11e91,2cd3cf06,d31e4795,40c703a7,4f5f3100,8e6ce299,30d5f08c,7307276d,f873ce74,bab3785,156468ce,3d6a8cbf,c532db23,2a0a92fe,91d290cb,ad08713) -,S(2d95744a,79c4d234,40e2f40c,a83cd89e,61576686,21293dab,6716072b,2089b77f,a25249bb,9dd8a94d,44576a4d,7ed800c1,9adc5e26,82874ea0,5d63bcff,2f6b2704) -,S(3bec0dff,e9a96bb1,f3cbccf,cc96ecf7,e1335b1b,86f13b63,6467fd31,5cc33abb,e31f8a49,dee2408a,2d0b9288,4e381379,9fe404ec,1d8b96ab,39413f82,52b85b5f) -,S(23721d31,616051ab,60287a0c,2b4ada42,1bf00825,127ea0eb,1341beaf,a207fedb,8cafc4b5,40e6f3a8,6fd1b546,87ff8c3a,fa2372e0,24696071,59b6e195,f633b169) -,S(ff8e494c,446cf1c4,bd557615,a4a1ce2,b8d25bac,62a89929,993cfd,51d45099,113e1b98,555ddb77,b8680eff,c57eeb96,4038de04,26a05289,8744f8ca,4f3ef028) -,S(f170cfff,f158e368,81cb677a,c9d9512a,3c1705c4,850d5a85,17a66636,7b0cdf21,49512fe4,3ff0f91d,b9ab918b,808ac11c,b5eeb4cb,ed905f21,adce5e4e,42ebbf7f) -,S(e9ff6261,d6c05d6e,4e35e373,57fca0cd,3c3ea884,4a33e504,df3dfa2b,a524d158,4969683b,9af581c1,963525b4,e8244e5e,6b7e7e48,f85c1fe0,1e9f0dc2,c66e591d) -,S(c1c4879a,b614ad86,cb64d15e,cba92aaf,4d1c7742,76d6aec3,4b59f731,addf6cde,6d7185b8,fc1b99be,383a7a5f,385a08f,d7125e3e,f72f93c,25063bfa,d44abeda) -,S(deb0c036,3818a101,ba38a657,5c0db8e4,a65f824d,57014dea,1c110387,7bf2d9ca,f658d43b,f0c106cf,6b45e552,3fcd066e,e754180e,8510b58,43708b5a,b40dbe32) -,S(c4d4164d,f782df0,f5366667,83e5aa9a,8b05c7c6,91c47a49,14798685,1da3fc9b,6c394d4c,3118c8a1,30bea2,2396562f,6dfcf8cb,8f0a91ec,20a43bd1,548bd80b) -,S(94d83b82,f6db0da3,f1bc24ac,8c5bdd0f,6e89cf2a,bafd33bd,2fb3ca87,9cf63a84,9e8658be,59d64a28,7cc0cfde,1f35b83f,e3e098dc,6212afac,ea234437,2591f2ab) -,S(9de3fae6,e6934304,a84eed5a,58e077b3,76da7310,61859847,d6abecfa,fa650dba,7e4cd395,ea8b90fc,20850be2,4ba8dd83,e79dbc4f,4efed68f,504eec04,f9bcb212) -,S(251869eb,7a567c9b,7866c9b5,a829206d,867f2092,8f3a6fe6,46ebc3d5,2df7d99e,bd87d706,c49690a1,9e0ad77e,4b3b8f0c,5efba7e1,2a448a3b,b4ad3c7d,44e35e7e) -,S(e92e5aef,818b2980,43227673,3d15021d,c84192d5,bc9307fa,1add63a2,8e888a9d,ba3a3157,96ab2051,ad53b5e7,a058f700,ea90e40c,c5855712,d2176a0a,c232f94f) -,S(b6a8a783,c2716ba8,9a37c7,d7022dbc,25fef8f6,76c676b8,267038ae,64a33258,93b09e15,8bf081ab,9e69c4c1,6d965743,cc08ad85,a8eb248c,9c67043f,fe61ebbf) -,S(26e95f26,7ee205ad,50dcc75d,82330877,394c56c,84546cb3,72fecda5,f57c2556,dfc935f8,63840ca4,71bed804,d0c2d14e,c9528a9b,ba1e6f25,6545311e,5cae673a) -,S(6c1ed40d,dd086dd8,2fb00bbe,d969ea90,7e363496,97c350e3,2d0074d3,3e05bc13,854d177b,5593cdc3,ab1e4903,c64be02,2b6b0cb2,25c71390,9316faae,a235b269) -,S(a9286b2e,81030401,c37d69cb,1e73caa,b1c68a4f,4ce1538b,11ed850e,67d11aa9,64ab5453,c3a1166c,18f35115,1f031117,e29b1a31,237cb2ba,51f1a873,529766fb) -,S(a2b862c0,ca02cc3a,e1bc5737,876f81ed,83dffeb2,4e6954c7,3cf97bb2,50050cc0,db3a03cf,d704f98d,dad8f48c,5861988a,1caf439d,b50c196a,32289622,b9a49b3d) -,S(19259392,58c25edd,953117d1,fc7a74a4,a9cc2fad,892255e4,fefdac84,4784c917,b86a1bfc,b7bc8844,abe424a5,b7409abf,26e8ac62,7983fafa,70dbdaef,43a88eba) -,S(6b85864b,194b2cfd,af1d6550,4960370,306ee34f,87c91187,230de0de,42fafd09,54a9ddf3,87458a54,cd305e06,61dd43f8,3911e88a,db6f0256,d19cdf15,3ab4b388) -,S(407cbd77,b88e6d47,60b07e26,f53fefd1,2b98bed3,5403c693,e7ea33b4,cd74b5c3,eb73a1d0,fd122265,dc880cb2,920b4eda,610ff1cd,a74660aa,7cb91323,e5485d60) -,S(f65cd6a4,594299a9,6cdb5f9a,7889cf44,62cca331,d3329f7c,43ecb224,d58c817e,8c906c4a,11925697,9f84722a,9440d2e5,f97e483,542658b6,8538aa0b,f10f5572) -,S(2ea38854,775422db,43eb69b7,bbd47a6a,b8ef1694,28753fa8,8cf49c8,9efc6e63,bf6f2d21,2b21c740,a25dfacb,bd22436b,5118f1a,2004bb90,adf580c9,6f21f1e6) -,S(f2bb4814,94677f3b,6af8aa4e,6a3b1100,c2e0e99e,289536e7,eca3e61,a20793ee,a3a788bb,2a810267,9a3d98f2,6a9a2740,91a3a29c,234043ae,aacc488a,67849762) -,S(e157c4a2,84354b8a,73d5e5ec,58dc1ceb,2396ca3d,7f651e6f,4547aa78,99899daf,f06970d9,5bef3e0b,e2bd4597,a1c96581,275c9719,605f63f,9618816d,669a0bc3) -,S(25aa7f3a,3a14731f,c7fa3b81,31a569e7,4bf32c9e,3492e626,aa4a4316,f263cf12,e5c2e210,a8a75180,31778f4f,4737a0dc,bd1a1312,1dfb40c5,5c435803,4bc3eeee) -,S(73ba2208,8cb96b2a,c23dd2a9,7b3cfd2d,c504ccb6,24c2dfd,5062f8e2,bcc442ee,ab9d3a1c,6bd762b,9cd866ab,7abc0e1,f898c567,61c7071a,d64d5233,caec0ca5) -,S(da94893b,3e73246f,6a72041a,44c7279e,dd8d4d3d,55b20db2,eb0e08df,4c5837f2,6949f652,8601b0fe,e572ac03,89fc3530,6b2d09d7,b59c40c7,a1a607cf,51684006) -,S(908480b2,35c49b11,12bd6504,5b3a8e13,7cbd4820,3046880,1688ed05,abb8b7b5,8a887f57,622a7482,3fd40b26,f58ae7a0,18d2d03c,d5ed31cb,93a529e3,387fec7b) -,S(682d7401,31c966e3,2a8bd150,27fae9f5,4452fce1,360c449b,1b20bbd0,257d58d1,ee7f773f,9d074436,685a2fe7,21b1b829,9369f543,dcac37e9,9adf43b6,4525c19d) -,S(c8661c4e,dbe125bc,a31e7a22,83aa0f9a,b4b3ae70,8512fab2,21bdb4d3,8c89fcb,30299a17,16d3fe04,7f48627e,36195b21,e6800d4d,a26dcc63,96c7fea5,8f25a2a) -,S(5112b1c6,2b88e704,f0d2c731,834019aa,d51a108e,1a8614e4,f6e62f68,d7372b4,1bfb5f8a,ee37bb82,5494c9ce,651d32d8,d47e5a29,4b9123e0,7311f260,9ab4053d) -,S(b9214d34,49e16aac,b90f6704,ee589f6d,8fa45126,be235e9b,61ef3ebf,2150eb99,c9465341,2dbb107b,965d177f,de11bb25,53e8795,69814d17,34ee9ae5,267529bb) -,S(94185601,f959999,1999c919,82e5042f,b7e68583,533f9569,73788d5c,3a087b2,5e51c755,de79b6d2,eb640039,a4268d3a,601750c8,dcd0a942,eafc9339,6fa36c98) -,S(3cdad3b2,2a707d9,90fe4228,adefc934,e8c69a9a,8a4cbd87,844a6ff5,a073f511,f6de425f,26e17045,5589e22e,7824dacc,f8cb8561,832db31a,e8fd2910,558ff9f3) -,S(ca986704,a0d1935e,1611e176,60394d00,7d2aa1cd,cb17357b,b4a557e4,f5a4b5ce,8d527934,a73f2b0d,b3cf571a,ac53b3de,11ac99d4,6ba995b7,5a09195e,b10bb5f0) -,S(f5920156,3ec396c5,82fd6090,2d98ac,2d5dcf5a,cd37e651,a1e80c43,f76940e0,2e821f19,7e27f927,20230f1d,9e26dff,5b3d977e,4b4a6cc6,7482f3ec,3cd5523) -,S(9ced8c1e,bbe0d213,b396fb89,8aa8c24d,870d305d,e9346239,b2cb0315,c883cdc,79367b21,4a2e21fb,1e9b24d9,fed6a0dd,b377534d,4da2b501,6999ebf7,f77de2c) -,S(5b07b283,ca262751,4a10817e,bdfc8044,883f4de3,38cae14f,de955f18,9713dac5,b8d6d9f6,8a71aec6,3b7bb44d,1d2b678c,75ff83c6,37c254c8,3a14be30,a5957b5e) -,S(4c2eb4cf,3fe64ba0,21297b8e,321cac6f,a8245614,45848933,19453052,69337386,35ee2473,1830eea9,85171af0,96b6bc0a,72f3e83c,6d83f8af,8ef1131d,c8b52c8a) -,S(5f24fcf5,f8c0bf43,43b8a0e,b3b6d8f7,2901c902,6d43f8de,4bcb1cdc,6d5019cc,87c2a306,138265bb,59b2b2b5,6992fb37,b2ab28d4,ff4909f,d6067e2b,4f312cfa) -,S(e26bda51,c385a875,5083faf5,6a915944,3eb351a7,88e1597b,f17649b9,b23ab8f5,35d66322,ba25896d,2a14a0a8,a3f5bf91,d3ceab49,9b2683f5,db7f58e,68ca1071) -,S(ae5be06a,b1ae531e,5d2338ca,d929b5a3,4c283035,95282aee,7c3ac259,8196bbd6,f4f486a5,bf11191c,9134d522,62ccd692,cc5c6686,c9013ed2,782b816c,da416d25) -,S(d143463b,4661a173,6b88f274,6b3c20c6,d054683f,9efa5221,ffd3badd,14804880,77b28055,7aa11d3d,b2ac8de2,c9c5757e,d0c9b0cb,af6fca3d,bb295bcb,c3ff8afa) -,S(54804f7,28ff88d0,bf6fb4a8,a24d4eb0,ee5379f9,30f890f7,8e31afca,87f23343,79288e99,a38accc2,c59ff29d,9da5df60,42d63089,45900378,c40dd765,2f0f5626) -,S(68c21fc9,93d41345,484cf5c9,8aa93bf2,25fc2c01,922a0151,cb3e247c,f130ba0d,9c435478,23b9d8bc,2e8ba0f3,8f2b60dc,ca5b6030,eef51c6,cdd20eb5,a02c6245) -,S(2f50b870,96b2e15d,6fb35001,cd8f95a,875cea3a,edf21a2b,c433b254,7798b856,44b09dfc,e0b8d522,17e7d9f2,9bbc5d6f,9886fe9e,3e360688,8d7c4e70,c3bea0ff) -,S(9d054954,f0c22da5,f330b3e0,69310a93,66b72129,2fd3c98e,76464796,847d16df,45962d48,143c94b3,57400130,d3e050a7,4defd464,223ad599,e6aa947b,12679a85) -,S(31980b95,9f51a6bd,4cfd9a11,b86dda39,af66ffb,97713ba7,3edf8c10,462d5685,d0a02979,5b45ba4e,7464fc47,7a09a90b,7265f5aa,e6b0d655,fca5828a,837c2840) -,S(e9c0615,f0444234,1f522d93,eda33b29,8951a267,7c4cdcbd,fa02a63c,a57d1ed9,7aef87dc,7095f483,5ebf2b3,156be9dd,ecedf54b,1b0c739f,c513ebda,5c5f296e) -,S(fec8bd3f,f19fa6fd,17523af6,27384c7c,6c92fa85,aeab8bf,bbdd2178,89b12650,d01a278,6ee8f9db,38b1ceb1,a3fb1df6,b631c0a5,23e92460,d0d51367,1098e414) -,S(2094133c,86322dd7,ee1abf80,2ddde826,e6385342,6bc87510,dff63f3a,b94f54eb,efb2ecd2,13bfda3a,227b791e,c24ff627,17ab559f,1bd289b7,e7db992f,d941e850) -,S(a34c3385,ee882646,b44bfbf0,f64225b2,fb86df27,c616a2ba,6cabbb68,cf36f3bc,e99bbaac,57c9f5ef,c64c6687,6f2bd6d3,b9ec8eb5,f9227c98,9a768f34,23e91422) -,S(df09dbfb,564515f3,a6d86e05,dca59a0a,c353746f,b291d9c,add27d68,6810cbec,90738e50,6bead3aa,c0cc4a2d,cdfb8529,5e752945,a7b2e357,1a99c901,49017c47) -,S(df9817de,89526a26,c61e4294,f245ce06,8b5e22a6,4937d5f9,6898b9ed,74078989,c4db6e86,c6a44091,23227adc,345d6eb7,d2f12acb,f2df3b44,978a1743,94072f15) -,S(2e713387,7a0419b3,7bf77874,b24fd0,7cae9fb1,59919a50,223437b,7746eada,5dcc4c1e,12502573,b0520817,16fa46d1,8ba43ff7,e7f8c8cc,e3c141ca,6176f805) -,S(99826364,f0061305,1ba033ad,63b95884,97158ee6,9542d06a,f2f86d91,3bea7a2,5f109254,24af4592,2ab30701,464d504d,6006969e,30a9ce5d,76a3b115,6158c6ea) -,S(19222e8b,5fec6d2f,33a35fca,83c3b9eb,effb9e3a,f2ca9c53,929fe5f2,a43bcd32,c79b4f98,4621b2c1,d627dade,f01fe761,8af239e6,b80c23ed,a2dd1b1b,e750549b) -,S(e0ea59f8,6b7925d3,ad511280,8b1ae5ed,c0acf6c6,d4ed0846,d870a663,5573970,bbfa69be,ef531b32,5272ee02,8c880178,57ab2a32,65b5a6b5,38ef81db,83b5de52) -,S(7df189b7,c29c06ab,83f7d849,58ba3d1e,7da3ebcb,feeb9dc4,64b60420,3631fdd0,88e00d45,8287fbea,5c14ab33,6a879948,e81d9798,cb82054b,772728a4,4b69e56) -,S(42b9867e,7cde3ef2,b4b73f3,e4df7504,b7f06cb0,67aedabc,16edb276,97bbca58,eab47aa1,df9af0f5,40d1c6d2,ba7edcc6,fd436f56,c944c872,1e1f4958,63144390) -,S(9ffd9a,5535bd30,a697f61e,e6fd0ffe,b1a7e5c1,9459bd3a,708a7112,3a3da54b,79fb0a7a,8334fe38,64fef8a7,60610920,af2741c1,fa41f582,37e92acc,29644011) -,S(13ea8e5d,1116a57f,8b223a5f,79c750de,6c25511d,558e6878,e92cb134,7b81e393,a41efd37,d35ea994,8175d989,cde449d0,e325b40e,a247edd9,e8f4eef,e6a4d283) -,S(110d401b,d7a1a0c,e484fdb2,34cd839d,5e40cad8,6244cdee,5c4f2ba3,ee1e2eb3,cdd91a5,4dfa47d2,98a46f15,c021a38,975ca108,f2653019,46013427,349d7ca) -,S(48a9f1a2,fe29b05e,d419a14e,8ed288de,46affeb2,296522a1,f2407b76,a8f6b040,f1c5ea7,887c029f,67202b41,198113cc,f1ba5617,79afc1eb,db0e10ec,5b5d2a91) -,S(d8c4d9a,feb94e7f,7b831464,77aa4e3e,a48b6af5,35015941,4047cd01,1beb7176,fb8af9c8,da06c2b8,8787793,bd19d7ca,6cc64508,7713af45,4f5fb4c7,eeda3c2a) -,S(34e84417,2f5ff4a2,70a9064c,d5994327,9cefde94,d295f424,2c491efa,bc1f0839,2da40cc0,5120e4e7,8e84435f,895a3ed7,6c507bda,4d16cd14,b602deb4,366ff9fa) -,S(ea802ca2,f07a4348,791b7df8,99639d06,c6db8d15,74ae8441,b29c2d18,18b7a6c8,ea475a0f,5f74e6fe,ccfca44b,ddc38a4e,3cc19c49,e2bffa49,a9572146,6338a155) -,S(d80542c7,a7be8da6,6346d867,4154f65a,b1cc8e94,19299d81,6a5c874,f25ee43f,5e85d69f,b5c72ae,bd94b1e4,67e0d30,df8da61e,4150f4ec,e3efcfae,78d88d25) -,S(bdb35e49,7c1c0d1d,7a120366,cd259e7,31cb253,1bf804ae,f0c82cdf,561d0c0c,2675a4ee,aea6dfed,8597c08a,69fc251b,7bad9869,e83f485a,73dd1638,605915b0) -,S(5174e27a,9a1eeafe,6411f3af,b627223c,db0da11,6bca0ac3,d39a3080,815e22a7,b1223046,5f58d183,fcda2603,e4593398,51ed87ed,6839d9b0,4c845459,daa3d5bb) -,S(c8b1299b,1b2880ee,7720ad03,62588349,44bcc309,6a7081eb,ce10ef20,ab1f6731,ead86be8,85584e4d,34ac18e3,d787031f,72feb217,694a32a0,76f2f88d,a04f3440) -,S(fc1378cb,c42fd6e2,f61be9bf,e60bb2c9,b36c5a0a,4aefef09,c8287a3c,f1310d31,ae4ff85e,5b22d2fc,914192d6,28324d12,51ffc469,1ba8ca13,f8347edb,5a9170d4) -,S(7c0bf943,23e7c1a,8004b23c,c05327a4,d4127c7b,eed27e3c,4a825e41,5f3c3a6e,30ad62ec,bd19f80a,a9dcbb5b,145d18af,3248eeb2,1d14e648,d7fd7217,f1089728) -,S(2ede5f01,232c0409,34b07b70,1ccce3d8,27f85ad,2a56c987,e29cd6ee,d841efdf,24cbe9f4,69f036a7,6e140720,f65817dc,847e9562,4820dbdf,b8a1384c,8d39bdfc) -,S(decd1afe,faf01eee,d2dd89c,bdb9711c,4f1899fd,437d0371,55cf74f5,9aa0858,899d1c8c,49b0b3a1,89a24445,568becb1,d3b1420d,ffb2c7a3,8fc291b,258f8ebd) -,S(1dacbc1,4be6e70c,4043f5be,3f972d36,3cb456a2,2ee1b1ce,3e207578,8233a79f,fc3b04b4,f502affd,37d71c58,d6f1a61e,b126cda0,e156608d,7f2ab786,e0734486) -,S(12ad0f7f,cc7cddd7,60cc6a3,3fd3de83,b1ab0e3d,cca013a5,68d5978b,a176cc19,b4e0cf97,335b374,661f6c21,46aa7315,a2c4f6f2,b839f88d,5376e256,99e6e216) -,S(f649bb96,e477a5f3,f852dd31,65496c07,5e14a85d,fa929794,64f1297b,d56fd1c8,46e37dfa,7eddec82,88fd18eb,9ac200e6,79337296,e2cad24e,d67f98a6,2e61d040) -,S(34f5e5a1,248db96f,a165950,a9b74392,acda22d9,95496808,82760daf,642c600e,a8a6637d,a1cad7d2,f72fe1a,df67eff8,49d0ab0d,7e06d7c1,a11078aa,de9dc733) -,S(26e940f9,ab45caba,adb1e4d3,23e5cf70,575c44dc,dd2f0b10,1540174d,d2aa715a,972aeeed,c5fd01ff,3b04f236,c799039a,9c7fe6f0,db1348e8,b97dc885,c57926e5) -,S(e3ad36a5,132f1067,503498e1,ed4b315d,4d06cc67,3a9207ce,47224497,12f51a4a,4fa719b7,37cdf1b1,cd5b963f,16a47e6a,e43dbe0d,490423de,fe5deecc,5baf9e8f) -,S(413fd0f9,4e231525,1aae9d6f,61aa0038,dbf7cc03,10c81185,394c8cc4,8b721a9d,9281c5b9,ac1f56f1,50776cf4,69e57118,8cc6989c,ae41b950,f72ff25a,d6de836e) -,S(9841a473,600446a5,5ce0ab4f,2e77ad12,bc2abc34,1e607241,c0c61d2a,d87148d5,7d1bb113,ee4b5199,95231834,1e05d87f,f9bb355f,df958410,3d161969,1d786f4c) -,S(1d4cdc2e,3e06c052,69958eba,f00484b3,36594f9b,be1ea98c,2382e608,cf78272d,6cf5d126,766fe5f7,75bfef7d,c2d91b48,66d4bff4,c8eb4e59,230d1903,16ac6bb4) -,S(da74f388,86de9c6e,36227258,758111ce,3b9414cf,cf8d5cfa,bcd9b3f5,44f1262a,d9231255,e3d9189e,a8d0344a,80978b83,3f1afb57,5c799f01,8b4ab73e,866a38fa) -,S(b2ebf119,46e37704,e1e12345,c68f70a9,a031c0b1,e85c0833,c5df9c0a,b836a6b5,c1652832,1666f0f4,19806a4a,86f4aa8e,46fccb4c,f7b6493e,26d9699a,9db2bde4) -,S(9fd899da,eb6f84ac,edfdeb4b,fbf8b521,6b5757e8,10d22d4e,56afc38e,da747cf,2daef35c,7ef36b82,d6158256,2466895b,9656970b,4beee8cc,2e0b12da,83d7af64) -,S(eda65e56,9cf07e84,19d07f6f,4aedd24,3c46df2c,bac92772,bca7edc6,ba17b217,1f394c99,b48348e6,fb709e5c,b4b4b77d,41eac2aa,bea2a4a6,353d1982,a9985281) -,S(78567d1a,1a96df56,299c9ee2,1d916472,303178b6,9b18fb00,a23c10e4,f093ed5b,9321fb0,6c5d2dc8,52e64d6e,453d9923,bff7c626,efaf5e50,245b4ff2,64158f23) -,S(c639e1a5,90f5973f,148e96f9,15c94d8d,7c7ec36c,bdf15150,83503aa9,9ef5636e,3620e7fe,faaf7581,886776e4,f7391599,94ae3e2f,2a59d4e1,ad6d508e,f4db90d4) -,S(73ef6655,c49894,7aa2b63b,89b77f14,3ac096a1,d7333494,d9774ada,5467b60e,c04509b6,2135fa8f,816436e,6ec0f513,ccbb23f8,782e2ca4,d5eebfea,6a5297af) -,S(bfa4506c,dca70a3b,a8fb0188,e0384bf7,3afbaa0,6818d503,df5015f4,f10cf341,9fc7388e,2edd63f7,9a5d328d,1b949a2c,a364075e,f94c8de8,37cda5e1,7d566ba1) -,S(2d594b,814a9e92,7ac9433f,3400c5e5,1a58457,6f47b8f7,f5f0b8d8,f48b2cb2,fa9a1577,d565b906,1acb9efb,4bf415ed,f264b662,594d1ccd,51baf83f,101183a7) -,S(401ae44c,a4039850,4d57390f,66044f6b,cf1e9fe9,f0f2b057,3f64f026,b6d5f3e6,ed947768,36ce65ec,f947b81,9dedd31e,c8ceacd0,16a40a35,78a592bd,4c2626f) -,S(43f9397e,a000ac26,8a315406,fc9cd047,b9cad513,8a7dab38,2717744c,ec6662b9,14d5bbe0,52dd8635,29c0b0b2,dff7379f,3e2ae95,6c5b4920,b36452d9,56085bca) -,S(25036a12,d8eca48a,78cb5e84,41aa5a53,16376e83,e2ac7819,db9895c4,dcf2a22e,14c421de,dcfdf9ec,b69a24fe,1c289ec9,f4d0f9ca,6f4b9409,35ac9815,a4154209) -,S(30e9c9a0,d9b9c92e,65794acf,a2cea34a,8d56e3db,d5b56205,59100128,26bf8991,999e4729,bca75c06,18f0bf9e,8ebf0455,3460031d,4ae47623,5e4ba182,2f62550b) -,S(a8fb641,fe27c40a,8e410831,fe1b0d2,cf74072a,bb626b19,2fa51341,e99ca538,f3832ab3,4eb6917,3e2f3755,366b2bf2,4dbe257e,eb516e39,4bfb91e0,a63cff8) -,S(5e09a349,98a824e2,f3ffe2ae,34a835ce,6b2f0d28,43b765fa,8dee010,49df7867,20ea03e8,4817593b,931d1612,2d01dc7e,52715fb9,36838de9,d2c9fb69,9c935025) -,S(e62a12e9,d02a5a7a,475dbcc8,79850ba8,340b638b,a5c3b505,8d3c7ffb,c90f0dcd,b075d21b,40e5897c,7e849529,bceec7f1,d5f87881,318c115f,acc99680,31d17f55) -,S(45aa5534,530265c1,c358b529,de15487c,b6bef551,5125e835,e027b0a,a69a9cb6,2e56d88c,acb32ed3,24068fc4,4c03ed2b,1b70392c,9facfc2c,2fafc696,fdb8d397) -,S(7fe3d940,50e2f358,31b410ce,e54c7c82,5eb05553,981f1c45,b136a24c,4d4a4b57,97b0cfad,4f6669f6,efb2d35c,42302e10,87c03b3b,1c22e23,24050399,345165a5) -,S(110dd614,85bedfa6,c09a2e5d,5737ab2,4a5b35aa,40129388,c6ce876f,bd3d9c30,7972ec2c,621155fd,12f0a1cc,30927669,13a9165a,7dab66aa,8f8fca53,7411041c) -,S(7427d28c,aecb7a35,a4100c42,9fe03d5e,6d3f2f91,a5067866,c618c4c4,5fc53547,8cf74ed7,1324616d,bf4135d,8f442ba8,b473ebab,fe981f2,3a426eed,bbbcff16) -,S(9779c811,98040c8e,754b9df4,b547c09a,a9f25410,1ca1fdde,365b0ef8,34ed95aa,148280a1,d26c8ff9,51774c55,7590081e,36030a10,a148c322,3c7379,67d036b8) -,S(41113833,f7da3a4a,4736fa62,ad7b4508,74ef5b9a,b0961665,e30f3081,7d861adf,98399ec3,485a984,cdbb6817,783223b6,59884450,881d2f41,3f4e59f0,ed5fbc65) -,S(f9830e6b,9a9a9dbe,50abcae1,d44d4856,3a92e505,aefd52d9,2259c41f,4b8b14bd,12061be8,5a0042ea,1baa46df,b36d6f78,62c11cb5,b8a070aa,6c6a8991,62ea1c0d) -,S(71284b2b,36a4c8a4,40fdd713,6b647482,bc73d680,3d6d0142,833d34bd,f2794077,6e54f5fe,8cff4ebe,bad1b47c,4e5d6407,44be9171,b391492c,df48bc35,10e195df) -,S(524a04d,a1b7ba04,34377531,99178ceb,7ea18f36,2c300aeb,a8daefe8,6e63e9d5,1c71ed93,861c3b1e,41a7fcd6,57225e92,b2ddc507,4d54652e,3898683,8c3688a2) -,S(e1fb70fd,2057dc3b,c545fb80,eb91cc9,479cada2,93c3492e,260b0a75,4bdc0222,aa799a9c,25786c64,d5138ba2,1f801e5e,88fc2602,d4e288f1,96c8d79d,7bad2278) -,S(2bf126e9,8302e8cb,407570f8,c3fe1206,3c91bf2f,63cdd9a9,3dcc403f,a8592d29,6452a6a2,20edbb86,3ed65ed6,cddd70d2,6b4975bc,e843a41a,10ce6ed3,d38591f2) -,S(faa217d0,1d9f0517,5950dd5d,e02972c8,b2c88076,36090d2a,6f17e7df,2a70cd7,73077022,dc1cb45a,f9e9d056,19635760,66ba7b07,bc79601d,ae7dca1c,a6cdc033) -,S(3d184ee0,ed45af08,6a7263b3,47b12449,a7270887,b8460b7c,6428ae4a,6dc4836e,d002efdf,1259dd8e,ab5bb606,97e8892b,4cb5376d,c26d08e,52b7c9a,760e8826) -,S(3c825a76,29890675,bfdcdb73,27f37c4e,43214a91,c6ddb6d0,f31e13d3,cd26eae,45bc7ae4,649d70ba,99df5d07,92e89130,87a272b1,bb2d6043,dcad0fda,a5444fac) -,S(3a8822a8,d5b230ef,62f657ed,31a12d63,2862f22d,eff16f08,8065981b,ed3e926e,ddca63dc,57ea2ecd,b25e8d03,2868b12d,abe8f7ba,8125a4c5,56d80a9f,9784a04) -,S(d0042da6,aa3b60a2,463e3396,98229067,c80f8924,12d8323e,7482ff2c,53ad86cd,40697e7c,4c5d6c,4ba11cee,fdbae25c,e234ece6,7db446df,daa03025,5f8adf35) -,S(a06e32ee,93d70c5f,a45a68e,2a180be4,7d8a7f60,17d035e,47c94d47,6f3838df,f4bc98ee,c7f50d34,4e88ee87,d8705b50,4cc0fd5a,5bfba498,5fe0699a,df811bdd) -,S(21426073,9f41da95,2dcfa74e,dbcc2f22,375fb359,93f83842,99e3735b,e39b45a5,697f2d88,74cd2249,cb84c9aa,16d20956,f5c40358,9d5b7965,ea4b46d1,9cd61249) -,S(84d52769,327646d6,13e3e1ec,2d20791d,76b765eb,fc5fafaa,20097164,dc9cda7e,d87be4b4,2e2e55fc,8f87dab5,c8c64493,f09b3996,87ef8fb,3a6c653a,a2250cf8) -,S(ca48382b,49283747,d433be3f,ee0569ac,7d3714fc,bbd76157,ac5229ee,ee25dd0,b67165e7,60894bf4,3cc80df5,6e3109,db7e370a,bebc7503,ce20836d,3f0ebb2d) -,S(8a6a751f,816c206b,91e67608,58fd7def,8ea70956,598b1c61,8e0699ce,602cda79,617ea6f1,c7f98cb6,41f01862,1f4c8cf,12a556e5,675765cc,c7bb1283,cc8ed073) -,S(1d035f81,fdc7c483,9936692,9bebc7d9,15fd3c0a,380f3348,13c65527,d82344ba,e4203070,f687298d,af8f6d66,6030f3a0,5826b0b9,31f0e55,8c356aea,b3464712) -,S(d28f1a4a,1198f572,a8130bbe,3f25e585,348a33c,2d73053c,ee7e29de,8a3ce79c,2841bd4b,c46c772a,57018c74,8510fc7a,dab16644,f157d51,9c38391c,4470f7b7) -,S(41c71a1e,eafbd926,4a49ba4d,e976e72c,691026a2,b1773d4a,88670b4f,d9c57fb8,c2b198e2,e4557f8,41203c16,b511d61d,b39e8a67,21b776e9,865158e1,91ea5ac) -,S(3f0ae72f,b1a06f84,803ff8ad,fa0e5c76,ed0b596e,d52568e2,6fe4aacf,6cdbc3ee,69a9dc3e,a0ae93b0,6c4650f2,941ebe38,fcd4eba2,fc9cc0b2,3fb9c127,81c53f78) -,S(b59e2f6,2f01449e,d6728b04,e9334f10,54c4c8e2,db4a422f,70566b55,ba4d2e5f,1b6b73a5,7444de3f,4137f2ba,722e70ab,e6a785fe,1ead6fae,9f2ec5db,299f00d3) -,S(42145fda,e72df9aa,fa3c20ff,cbf11a0a,d357515e,ec6846a6,5cc6ffd8,8fcb1347,4a34e518,c9d39736,3c88ad65,62ecc0ea,2652c6f,48955852,99a0de0b,5f42b6) -,S(17a085d7,8d8013f9,b98a8509,aad7553f,bda81df3,33aa6f7b,2457a74b,c83f6739,412d9b80,efeca81b,29619ca6,8bdcdebf,7cd253c5,88793675,6a379655,d10df76a) -,S(f5ec770b,2e0d0afc,7b155abe,bf310270,28bdff39,a08d113f,b0409624,e7049ae0,e9ce5d46,2dc5d255,a09ba37a,a7a5edcc,aad29ce8,6f9c6b58,d2781e81,5d88a25) -,S(45e3976b,749279e4,486d2db6,fbbc7731,168e7311,d7d75f62,b754839c,2fd17918,84f0c079,c0127eb,d1064724,927459d9,ebc22eb3,502a99a0,e5876e15,29c8845e) -,S(df15c304,378da361,7f821d07,d00d1bdc,189fae9b,7aabbc71,51c2117d,8fe0c21a,589daf,cad5cc54,58544b9d,a69dc510,9f8f1e82,866b1076,ff1d229,5942deb4) -,S(c5798ca4,547cea39,75e3b613,911434e4,e5f503bc,9ec6e9a4,8dfe8386,a371494c,2864334d,fb2bff0a,4690f2ce,d1a1d1cd,e3b13f96,325f295a,8e0d4f1b,b13413f6) -,S(773ba0e2,e1a80ca3,9060556e,2fa8d15f,83dfd018,dd226751,9262651c,9765c915,e59a686a,3fd13284,e380188,fa40e9e8,28991374,20c906b9,ae882512,7dc7dc60) -,S(6ed4cac2,e1685eec,16c12251,db5dbceb,90f542e3,854177d9,83ee6024,d6e7a740,2558db33,ab598118,1802a84,e6ed32ae,49c25379,606a3150,6ad03ec0,a5308b98) -,S(21cfc6ee,d98915cc,1bb52da8,e83aae9a,64970d4f,ca3e70d1,6536043e,bfb60fef,8154f487,290cb8ea,73cd147,c1286d5b,9f471665,d9e0ee24,c2be264a,2f1fbc36) -,S(f8db764e,bb8f031c,88921a73,92f75323,7d1f4a22,7bc8cc64,8bcfa9a1,235cdc11,82c25fea,2d0a1e37,e16dc4e1,b6737ee2,281693b0,b48911db,c79c1470,c4e6274f) -,S(d52f4eef,14a5a860,983eb0ac,8e02def9,53f2ba03,604cc60c,80882e56,ad6b3dfa,b34b3131,7e37b973,9559bc2,6f85226e,705bf06e,1fcd818f,d5b88eed,f2d6b7ed) -,S(3e9d0688,b9b67517,e25b526a,4e46be08,4e95a171,f9d99ae3,4cca6c14,66adaf6e,e1938d76,c4349375,1d5b9876,4ada7b7f,57144878,78805540,70b7c27c,9bfa312e) -,S(c74f8dab,54590ad1,3fff217f,b62f43ed,7f42ffe3,6c8fddac,fb6315f4,a3406094,1bd8025b,57dd382,5b5b6896,e90ab5ba,fd31ef46,8f02846f,29f1b1fb,f90302d9) -,S(71f88089,a8e0ac,6cd92e03,b1dafb04,76c0f489,f16def9,75985abd,5dcd02ed,839bb263,7827e6ab,f6941b53,67c9aa09,835c588,3956733c,267fb52b,6be767a9) -,S(983d1cde,7d75d70e,328a8a62,ec82a96d,5174ed4f,c9676e10,7c282be7,bd408b07,5fe2426f,287fd353,173c699a,39407e36,c365c413,76986640,7c12f11c,5dc436a) -,S(3cf9defa,a067fd0f,6b012fe9,8b05aea2,83c332e8,cbc8296d,c777951,9e62519a,3fbffaec,c77d872,7dad2011,aa314690,2806f763,b73b780e,375508a5,c77a613) -,S(f415897a,cf653c3c,26fc5231,f375e28f,c23041aa,af05455a,e81419dc,25546e30,3a9d5669,806ef66b,7a0661dc,cb941531,d81fa7f3,e08fec72,ee6312fc,4a7f59e7) -,S(5bfb64c9,cacbd09,244f3a96,d5a6800c,4a012297,95962fbe,a429b659,8e085eb1,e5c4ecb4,9cc4c685,a4fadc80,77889298,b94e779f,7f462aa2,130ed8b,ccc0604) -,S(61a5a78,a086ccfe,9f54cb0b,750b7c8c,5c8dc4b0,e32f3c69,c65ce4f8,9009587d,50193c13,affe3a34,1ff3b8a0,b37f07f4,b49667c9,f8940311,9ecec58f,a76d8c60) -,S(e74514ed,93784bda,ca6e30e4,da2a9a78,c7c70bf9,42cb4ba6,afdc357a,c694ed1d,ee4a8c9f,7d55dd09,c51117d0,754d301a,cc36dcb,49d437dd,ca46a920,7088440b) -,S(dd9aa58,f2cc4c0a,8d2bf548,6dea653c,b4671e40,c0073df5,352b2a9b,95637617,6478aca1,582a65d2,6c0f42e7,48f06e60,ab85a494,d0129b85,5b5fdc62,7dc7f580) -,S(fd7f2622,665c2005,9bdb8c46,d140ecda,ce013ada,6dcf3503,e28eae44,c2dcd83e,536c948e,5db2978,31e2ab3f,fee860d5,dd7fdd16,645cf561,67e484,f4a62c61) -,S(9635dbcb,b2595930,835598a7,149a8a37,be64f607,c227b307,4d8e8184,c2ae99fe,1b2cb226,bd9f23d,bd243ea3,eb57baac,163f4e49,6272d220,9f436f81,7b6d9442) -,S(642ead1c,c24db5c4,77d798b1,515083a7,7777476b,c3a03993,883a7ab5,e1abf814,185293e9,6e6dcd7c,209fc891,d96f9dfc,4012f756,7d3e2f1c,282eb0fa,5de46eff) -,S(3c5be7eb,3aeab34a,2d982ebf,3a766962,822ddb39,527ab79b,83540818,a4e2931c,a161ecfd,2b906280,46d6d1de,c149eee0,e6c92ccc,5f936a51,e2a4c3,82e555a9) -,S(c1a90946,6c0ea8e4,b60611fd,6c61733a,6d90b0f9,d1b7a761,1f9e3e84,6423bde9,f928d301,b6c27eed,79b8a8a,ba388ef5,24b17220,7ebd7396,5623e60f,f650dcf4) -,S(e49d97c4,2ec1b8f1,43180188,382b265e,4216bdcd,82824a15,3a0e1d73,83207541,8e521e4b,95a1f4b0,934753af,cc3b73b4,7b3eb00a,a9c7af48,7e4e5a02,6234b733) -,S(49f71f26,f0d828be,9e9a70c1,bf768117,ad2fe6b4,6e9f416d,eaf17695,80dccfc1,86f4404a,67e8e6a6,9a901589,d7c09873,eb553aca,41b0cb66,f4767621,76ff0d79) -,S(487d806f,67635c8f,b66afe46,3754a5b4,64afa469,2ca69541,5d91a6cc,8903e853,b610d414,26951e55,46bb7216,6dfb62fc,602b3d20,18c38670,760f55a3,6c45c688) -,S(47af5aaf,cc7b69e4,bc536d57,8f57b958,3fa17666,2d302141,54e3e35b,57357e38,b79a4c34,709d215e,dd3b0fe4,9cde9de5,b45ccdd2,af25bbd3,602a0c90,9834dbee) -,S(84f79cc1,a257fcad,546d8218,5caae7da,8a8d523e,7feabb79,16ad7d8f,5421575,cc84b844,55ef03ea,59913a0a,1919c0d,cde9fd92,ce872029,57a998d3,80ec1986) -,S(550b7e54,3d3accfc,eb488b6f,b2b48d0b,9017a5d4,ed54d55a,72b8ac6f,c83f6d14,91f318dc,ea83ec1f,f43d5172,bba5ab1,7891f3e1,2e162b6b,8c512589,5f2e5141) -,S(f691885b,eece383f,1f56593f,92de0b34,1627cd58,389afaba,f442663,88aa6a32,1e6c920d,2eb76656,63c7586f,7907471f,79e5faa1,b6fbf4a6,c905e422,9a441638) -,S(4e3c52a,96889e52,b99aa469,b5f07dc6,f6720e49,29f3961,fae2c59a,98ffacf9,ba3a3d9f,dccc36fd,a8642167,7f54de2d,4c079b2c,e70b46cc,926d7d9c,ef1978c4) -,S(66720c8e,c638367c,c934347b,d8768338,54eaaa01,a81a876b,d2321e41,40381224,eb595ebd,67c5a08b,24482042,5035ecad,f20fcfe8,9a84a60a,93f3c05,a926d574) -,S(4b01f86f,f9feb661,eb33d7eb,87f940b,74302cb7,449b0bc4,84e97af9,56b79d2c,2680db84,1b233e25,16b74190,fd3a0cdd,b8fce285,ed8577b1,e13c2205,9af0d3a) -,S(dea430d,6a4b5e18,fa04f77b,55f85d36,df9dcd47,87ad5899,c16d2533,74494867,46b1f5b6,307a1c05,f3b42ff,e7a272c8,c63c2a92,19bd2971,d70ea793,5bd508e8) -,S(3f987bbe,d7fe896b,8a8067a6,de49de63,670e7260,f255e5c8,a926b9d1,fb62945b,373b2f51,86d7d9eb,18570d3b,9e48756b,663cab9,df388899,7af923c9,bd79971d) -,S(6cbcf291,56e3cb2a,b0d3c03f,3f4c0283,d953a641,9f7e8655,d8c46566,e3990b70,535c1017,fb40108b,24de2a8,358d217,8e47961,e5f4cca2,aa7e7c2b,339c60b0) -,S(d253488a,5610a541,e4ce2cac,bf4d4901,5fe63dec,94615e80,d795b39d,9885201c,c58ac205,e7323ca8,9bfd284e,9c9bcf3b,89b05571,b84d3afc,d69a9a96,9ae4fcc6) -,S(bb77470d,cf0851b2,29494d6b,e69aeabb,dac44010,17200af6,391cc2d2,352bd9e7,187cc653,b6b56e6e,6c9969ea,705a6d9d,3539d4b8,b8777371,b64deff6,45307942) -,S(438c5a3e,1ede7063,eb928da9,693d7602,809b9e08,e49951f2,6a600eb3,e929ad1d,d2918af0,67d34eeb,d8f179ad,2f3f105e,a5cbfc9e,1f416cec,372a5175,8ae797c5) -,S(35db0905,e28b3e7b,b8c4425b,8d9151b9,9cce6a6f,b6e11561,65b7e356,9191e69c,25963fe,ba45cdbf,5472c046,3da3279a,60a3f1ca,9ace47d0,4c4648b1,52d2e560) -,S(6ef2e9b,79e48447,7532ba0,1b658af1,e27b13b1,f1635317,6b47d994,cf3c6bce,88cc8a3a,aa1f2040,7976ae7a,9bfe09f4,f0c1fb85,72f122f8,4aeee871,b87867ca) -,S(c85fa35,4c064f00,ac39d455,7884f8a6,420c4192,aef2d6af,8afd61ec,2b977b33,3d17f849,6ba4a79a,bcdaf502,87fa5fe6,15d2c24e,58f27ab2,7cfb2d86,140a5f0c) -,S(7f47028b,4e84f4a4,21909f01,85df2743,e3f18f1e,134f90ae,166c4089,a9d44803,4c025c2a,c2a1af49,fd7e1e3d,2ddab9ed,104a0e21,17895fc,36eaf9c,7a550e9d) -,S(6ecc57c0,5c7f6b98,6cad9c94,435664e,3b036ae7,325ea091,234ac216,3dd0e324,67086288,9346eaf7,e6bc8ac5,25d60d5c,41bd9701,f5cc5f58,7995fd6,1c75def6) -,S(46a2a28f,61fbbf15,c3afacaa,e181f527,2b957bb4,7f127465,fc03d021,76359328,88b36e79,2c071ec4,adf1a34f,a3d1114f,f9813f91,39b2db5,83320bef,134ace83) -,S(a2072cb2,e25bc045,fe40dead,8fd3f7d6,449f8d7b,57adeb47,b6ae9b7f,7d6a5b2a,fc019c0d,8c9263f3,aed518e4,44c1e5bd,dcf796fc,7d16cc6e,c90c4c59,7877e36a) -,S(fec203e9,60d4ead8,e3510545,3e73999,1ce5234d,a92a20f1,813414a3,599874c5,118cddc6,fe918be8,d2c5483e,c985aaa8,4d708767,4af70444,1fc0692c,b92a540e) -,S(fd166bf7,a69d80da,6e03c740,2ce6f4,a05f1df4,e2a131a,daef89a5,86f73681,1e3f6791,7f2d3824,ba4ef07,86ed8f08,c65860a7,e6913fd6,8cdd759a,2deabf29) -,S(a479787d,b514baf5,b46a578,6a221d72,2eda896a,a7fc1e43,4817f125,2bbe0d6e,1a6f7857,92bc5fc4,e2fcd87c,6b82ed34,20426f30,a9c6fde,4f09ae14,9ce426a1) -,S(7aeeb17d,f75e9c7,2dab575d,2ad1cf87,b3eedf99,8df4b14d,d42b50e3,7895f041,8060c0fd,5f903934,d47f3886,8731ddfd,a6fc1355,53be9a44,38418174,37b79fbf) -,S(6dd254bb,63c3fcc9,a5d1758e,90c0c6d2,bb1a19ae,788b351d,191d0261,cba75c76,b00b5cff,f3246b0f,ec835345,1d9df948,4fd903d2,e278ac2e,59d8ca20,647c2ba0) -,S(d9e76bea,acd64f55,9a9c2888,5834317f,c24fe5f6,7e540d27,6233c187,76cd7323,4d079fbd,15ab81b4,f3aed0d,663178c4,33f976d4,f69af7dd,ecf61a13,b831e71c) -,S(b57b26a0,55c4f224,865b22,287c9402,4c801618,c50b00df,33ef8509,a94a0f57,5abc4303,1701260a,f41a0e49,a100da19,8d033179,8b26026d,6401654d,39d53670) -,S(e03c71c7,9d902be8,5caf4df6,aa401a6d,18592725,2f10be1,f4190b67,bee3bb8f,e5f16a54,ce5772cb,1390e49f,966a00e6,893ceadd,5a753c7f,9d82a2ec,7324240) -,S(b7f3b64c,980f19f4,e4f46083,c1ca758,70f4313b,3c23c5b8,6acd6c8d,57ec0de4,5fd0d8f9,2a70c9aa,bcc1523f,91fa603b,e17fa73,fce73899,2c1d720d,3d55b1ca) -,S(27b24868,2a1b9186,3a1f5c9b,a5010a37,2349c417,e1d7acaf,dd94c7db,c5e12733,c54c23bc,4e17418b,deface22,b8e527e1,4de1aee9,71c921fa,fb3f58eb,e4778125) -,S(5d4b2b1b,5f9e640,bad96aec,6d3bc5b6,169411e9,5dac7346,d1f7f885,50679a14,80f0e3e7,7e8d6c48,62b1f6c9,c0ee37a3,3b98be7d,e1c6c8ef,12759b73,c20a2e3) -,S(790a4189,63c3ec0,ba6babae,18ddb717,463d3ec7,c0b01852,5e760e96,ac5fc2c1,6db8b456,9f2fed97,783a6e80,413d8ff,cd0ac6e,d512f712,4cdacad4,4845242f) -,S(38dd209d,705c3f63,9cbdb0b4,22160943,4ddf1366,56f2cc8b,22d27479,c5446f99,8b793f60,3621f6b0,1b1ac36b,cfd92c3a,7dffb7fb,fcbf831b,1db077ff,7482c25a) -,S(29c6b2a9,24f95c8,58857951,cea2baa0,bee9866d,77b3f7d6,3cf9debb,16437528,c408f565,cc78e5,15a6e0c1,7a96392d,2952e25b,d067a0f2,d2f10eff,b54c2ce3) -,S(19f1ab5,b54c80a5,a32a1fb8,1bb3f389,ebb53641,6c8a844d,3846c2cd,350420c0,38a56a7d,7eaf4155,4f5b8090,c06fcbba,9f516a23,340617e4,dc5951d3,35b75de0) -,S(fa3d2b8e,d73ab5c3,24980054,27830806,3715c17c,7981db6a,61757048,1e1d780a,7bc0b4e2,4cde1ca3,e30ec601,73121a43,f87f679d,cfac6db5,a9bd132b,d6a89454) -,S(908e538d,730377d9,d3585ae,59b0949,c46a6aca,bb04e725,70b189d5,57c26825,5e108800,6cddf00,39f7d855,64252cfa,d4a37761,2b58b6b,5fb2942,7e274af6) -,S(e57bfd8,f38d456f,2e977090,d9f81673,db11a195,568a85b8,dd8bb725,a30d22ec,b5965e5e,e680e791,e87ceab7,156a3e03,dda7e9a0,9a9dcd76,a72dc838,d9e2e6a1) -,S(aabc514c,b88112c4,6e6e1221,d61e2abf,dd7a3bcb,a2c7cb78,4d57dea6,1950534b,96e3d9b3,f3a4c3cb,1473f61c,e224dcbc,a535c90a,7d993409,ed079d32,3c8facc1) -,S(94a800a4,6eb9506a,8f6dd737,ba45c697,4e563c3e,1df40959,4198d1fc,e499d2d8,627ef26,d39e19d,ab4d6bfd,9d4fcc0f,4bb4d97e,b0886426,40b7ca31,952be814) -,S(1022de3d,6caa7542,ddeb47d2,1f82cc3b,6e04170,ed9d4ef6,81b58b81,efd6c3a9,2317f1e8,37716a0d,842884b,cd77cc3e,d6235dae,9fad5661,9f20a883,af459b5e) -,S(9509f343,17c15f7,a54cafc7,3d4275bb,41e39183,53858724,4031baaf,97bed951,dec71a0c,7f8108b2,5e296361,2d6623b6,7b2f6d9c,69d7b6cf,d7273503,fc72b4ba) -,S(bbf19e9a,efbee2db,fbd5eef8,492f52be,2e2f9072,6b3adc1,d16f0627,f4f19d25,d9e691de,f2ce976,c66d806b,f35a2b13,56f9fc07,7b7bb239,30668081,4b52cea0) -,S(b5997bb4,5b359516,b28ee935,e4d59c39,ae434c29,5e5d98e2,2ddeff57,4afabc5,fb6d36a6,fb2e1aaf,d9b5d89c,39a854f4,a3cec053,1e1a776c,b4267b4a,d2bd8ac7) -,S(fb746cf0,cbf2f56f,6a3a99dc,71e84cc5,af76899a,3a7d02c,fb272391,b77c8384,d1e4cf27,57373ab2,d1ba3f2d,d5bf8b26,a74d6814,23a5b16c,9621b788,a51e9796) -,S(644facf9,e6290462,1a5278c3,f4a2ff8,84600c23,69eeb557,bc412540,c4966655,5b5ee0cb,449423fb,67c9b542,3868f7b7,6d1968b,9d7dd751,75e7dd5,2f994b88) -,S(c41931cc,9c311617,f77faa3f,6b6f6e21,bd030c2d,9778b065,6ca105f,cdb8658c,8a759dda,8db8a8ed,eb1f2972,12858879,bb2f49c7,468d8edd,14d28525,ca3c0746) -,S(e8dd9063,48691527,e4f4fc96,2a0e5608,d151aa68,53257e2b,1acb7d94,56f66aa2,470d108a,4180fbd1,2a377517,c5e472d4,680ec468,52bfa472,cc400ac6,91541a0) -,S(6b48efeb,ea6d0d17,346fba31,8fa33deb,301062d5,94b254bb,db6dd28b,ffe27451,94cbae78,eff2064c,cf91bcc4,fe1ae3ef,3d767b63,6eb4720e,35f2340e,87c1e941) -,S(1cb08c2b,72f069c0,e1e4afb,7ea73e48,a33f23cc,cb89fb08,db1b0919,62bedbd4,64d3500d,5b6577e6,6c18d3be,fc0a7dd0,833d3245,1ad03257,b45a31a4,67c14095) -,S(2150558d,bc64dcb6,55224045,6d943208,7b7c7182,3901f78d,9702a736,998906fc,b49e2adb,321e0c49,ddeaa152,9bf83095,762ea96f,6c1290dd,b6ad29b3,c84b8657) -,S(530f4c16,58284100,55a67001,eebf528c,f9286825,fbb60ae5,da4ecac,e3d7f4c1,80b147ab,1eae8922,50bf82fe,1a9263bb,41573617,7dc02e91,fe7e07b9,66bc6af9) -,S(c5158947,8266dd62,fa495d4f,94bbe77,b1230f44,685ac488,7642576c,8d92e6b8,1705fd37,da813af6,2a799e41,3a45a4e2,4d2121e0,1065e692,ec1de149,43be7c90) -,S(e6963d21,b576da6e,6aa6f1ec,da7674d0,d827d533,31e19d85,83ba0e7,31553f86,d3560d2f,91c7219c,76962a5e,3b2aea76,604b5ad4,82da8f8c,419cf2c8,7cfdbe61) -,S(c5aa5963,a249a9a5,9445c0da,9537d482,dcb6ed9c,8372e455,4d440931,3c3f169,7e7f9c15,4ba213f5,981389d6,22af8694,b1efbdc8,18998923,92c9d654,92ae7fa6) -,S(bd04e3d8,5bffa429,81310c7b,2c885f04,69f01977,2819f6f2,5e69621e,5a32752,dc4da51f,b88ed097,b17358d3,da4fb755,254d8ceb,5b0df72c,9dc995b3,8e145d9d) -,S(f8f55476,4418c668,3390b604,c9f9f452,1ef63756,58000c49,d3b8b1da,80261dd4,9943a6e4,1b928da0,fad12667,cc997ea5,6af49db3,8c499a2f,a2343efb,52ea450f) -,S(77dc24bc,5f32159e,7c3b6a3d,168a6698,43b12253,e403299f,b4fa3db8,74350dec,240d860e,c38457ab,6d741edc,e4fd8c51,67f75733,f12fe892,aece4f9a,578c6bd5) -,S(9f238f7d,588d53f1,52da8118,2691194d,99a56fee,373745c9,aa2a3a7e,58d18825,dff57ffa,c2012315,ad6516d6,92902476,cdb2d3f1,58803c3b,4dc854ed,8ba9b756) -,S(92f95782,a59da5c3,a12401da,34c24ae3,fbf3822e,355ec948,6020ac04,3ebbbb6e,1c6231c4,e09c414c,e0d3cbf,9be73bbe,4f1fdd,b3d65a41,c716f0f9,a39788db) -,S(1b40dd47,f435579,1474b560,66a0efb9,88271a1c,19186bcb,b1715196,84f3130d,9fe6dcec,991d652,c9e13099,66b0aeb3,53869f99,28ebc955,6c64973a,4d983b5a) -,S(473f6b8e,d4162f9a,2f40d48a,8827f79d,180052e1,7b28b240,4772fe1d,64cd82d3,743450df,fc8315db,72c01f1b,21c4eea,9c0a39e4,c1e92e33,91096576,37e97fe2) -,S(40cfc629,a550b437,9e0941ae,fa8abc6c,8b492155,2045a8b7,560262a4,86954932,e627bc57,9c84859b,d2a9ba9c,9d7a69d3,8c8f06d7,ccd9e68e,fbaa0697,655a8a23) -,S(4c91dbc9,8d2d2891,a7861599,ab55fce,943755f,5f7c909b,3f0f85a2,bbb75c95,5e541495,ecf13109,6ac3aeda,5324fe5f,6f761ddd,d2972fe,812242ce,12fd23d5) -,S(1fe3c538,ac185172,44461f82,63961364,c3c74bc6,9a91bb4e,69973971,8e729d23,974c02cb,d7d97c,65f89b90,327e6dde,e627d96a,275c869f,22c14bf9,6be05389) -,S(fbe873db,56579349,4ca9c844,8a6e0dde,226d4e4a,2f210661,30fe1075,bb11dd6e,c91061e4,d03f9f09,21f56d76,eb78640d,4df80464,459fc41d,4ca33d4b,5ebbc5fe) -,S(b58277a8,3a6d6779,82af314f,7a41a69a,b1744e6b,1cfb4803,f52a25e9,8200957d,c8faf7cd,59e43256,33403b90,7abb1b83,d3f0cade,ddb9884d,77c5fa54,b55fc51a) -,S(3949cb,e84b7790,a7a110d7,9c41d548,d379604f,ec567cea,e3aaf0f6,fd0d9b49,cdfe904e,56a9c88a,76292c3a,5da21100,57795a76,fddc1610,e7efab84,750617b3) -,S(6ee9ab2b,537aeea0,bd8332dc,d810cb7d,36f8f7f3,57be2bb3,5d84e236,f1bca531,d75518a4,d975b0d1,e2780851,4b726626,dfc182a3,885900f0,4d82c839,1c64722b) -,S(c2875d78,3e15f959,33bbbd48,8a24c65d,2001f599,3536fa83,8a3e056c,20a2eabe,e5870c25,20adee27,83cbeaaa,cfae7283,538446b,7cfd7ded,12e68ffd,3f66de8b) -,S(88e26c2f,dd475547,8795e8dd,8285f73a,dd9eb9b2,68c1b16,65f1a701,cb3c81e9,d00344e1,9d14b3f,1dcf5c7e,8269237d,a2af90ea,93a9e24f,3a0040ee,d3f171f1) -,S(ca8e8c50,660f3928,3cb72105,43710f56,9a1518a,7948689d,3d7e2ce7,a038bc55,57600213,1892bc9b,5afede4f,e71f5ec1,a1516039,ace088f,9a851278,c52b2487) -,S(ecb6e53f,4330d0ec,b9aa3605,b6e6d209,222d611,72858b1f,d2663797,772e0249,b054af9,4c535d01,bcbd955,61770aa2,e08678ea,cd8de0db,d8efcdf8,623e9eb7) -,S(a011ad64,55123316,9916b20d,ca6efe7d,e78c6b58,feee97fa,7f9e3fc6,8d889cfe,f53b71eb,63f87651,aa0de66e,a51f56f7,c5e3ee26,ed4ccdf4,1978d7b6,f0191277) -,S(3ddda2f4,ec1b4020,31a73abf,ae69dd42,8d801bb3,fc96fd1e,b06334d3,cd7dc27f,eb1b6b4,137ca36f,5b160112,38fba958,32c5e5b0,aa5560dc,39600db0,624b6c1a) -,S(13f5b643,e908dc91,415ff856,76357687,bb777f21,3972cebe,e8157828,53982d8e,bc2d3402,f3af6ee7,bef0ec2b,73c75e53,b70309ec,633d97af,b9ababc0,62d20ec2) -,S(ed9fc1ba,60a7db8,93db8148,48790e52,4a246279,d938a04b,cf168ae5,71618e2e,b241c920,ab995cf9,4ab1b707,b06bbc7e,1cf7b8eb,80325934,d57e9e9c,6ba08459) -,S(89d4f6fa,f6252ba0,d036dcb4,54fa5f1d,311ee828,1cc5ca85,73fe7607,7b16fadc,5f441ff0,56fd4e24,ca4c9efb,859d6e16,2e4daa4b,a7f3fc58,e42a540c,23b6075f) -,S(4acfd390,e8a1b430,9af0c28c,87f51308,a1ec5741,8c194072,45c96c79,30498a3b,dde7b57e,5e5ab271,78f2ae5b,6494a578,2757f508,bafbbe64,30b96bc4,96728d2f) -,S(8320cbe,fa7483dc,4f5e7b7d,d74cf492,b95b7e31,b1bdc651,6595b605,eecc134d,e766291d,13959f5,805de8f2,aa59cd66,8376d93e,4b775010,426db24e,b2ff41f7) -,S(fbfa6a21,deb1d183,cfeda065,687a0b96,6d8e50fe,475a17a,7b690019,6e7c696c,f5901c10,5f30f5d9,75530b0,3f943caf,8de85a12,f54e4c7e,5685184e,8bacae2f) -,S(70695a81,45fad213,aa14a7ec,d3c84f51,53e3906d,5483db4a,c6e8c229,ecd2c3b,febf34ba,9744a37d,6b91335f,c735c426,1208595b,3b8d048a,3fb48e76,2008e90) -,S(89fd8cfa,8fd5bdda,b6a80bb9,96ebcc92,6074a15d,371622b6,1cd772f6,ae1ae9a9,85c2cddd,a8065ee2,244b3d35,61e9e057,87c6cc4e,d4b1ff59,53b736cd,d3876108) -,S(342256b4,cfd8e5b7,5f5d088e,3a919d64,ccf38827,b18bdd00,2ee9a6c3,fb4dad,c54f4704,f3512e55,4d96ef92,3005e4aa,34a157e5,8bd6b180,e219dd51,16c4be16) -,S(cbd38ba1,189a152e,bf78ea23,3eccebc7,16f4c28f,273f5c8b,ec9df397,9dba0dd1,d3df2ea,fa52ad52,9089c7c9,581dccbd,a2a0e060,7fd4b902,cc915f28,717c2d29) -,S(5f7ae38f,61dcf176,45affec8,7514c624,85b880ad,38df28ae,b695cac0,fd1d27ed,9b955855,f74cc040,63cfa4d1,fd098e5d,e0030c4c,6dedee41,71bb5e7b,c0939226) -,S(72e72eac,aef492f2,f3c5ce7d,dca58f40,c919a194,3662adb4,3d855a8b,532d194c,d7b5e558,a0cb091d,3b39407e,1dd58b95,30fe7561,6b4c3352,bfa51320,509d2d7f) -,S(925a19f0,c73d85d5,674a62b0,2d5496c0,5868fd41,a43696ce,eb153a0a,2e5b8051,2ff229b9,6c23cdd8,2bdc56da,37495c29,78fae40c,b429a1c7,3111d392,3c5505c3) -,S(baca4fb3,33bf98dc,165cb9e4,3bec920e,bbded256,e990820c,8f902e84,3f6e02bf,af304697,137728d4,e96a38d7,95b830c0,6c18579a,9b46f4da,a94a13e8,d3a0341) -,S(fbe24c7a,53b90f3f,918b92ea,e58ef633,bb72e695,2eee6c6c,2210f6d8,8da9e0df,1febd844,af3d057e,c9ace544,d5fd57f0,c125c55f,1d9df636,4f6be8fc,bc53e3b5) -,S(73b7de54,ae8a38c6,ccde88c9,3f526c2e,54d823de,a6415488,5e864a2a,1b0574,2cfa6943,634201d8,9438e6c6,fbb7224b,c2e6b313,538523f3,305c75c3,5c68aeb0) -,S(84960402,31a60cd4,cd623d4b,80bc69aa,7cfa7c0b,52cd88b4,2f22ca66,17151dfa,b5324b5c,af293ece,38deafd0,76835e10,469997af,7dcccd89,172ad20e,f36162a6) -,S(b6de647b,98585f7c,61f0712,76c6f62a,40926888,b1bab4fe,ad64098b,4b9434dc,f7180d81,be634f34,d878a645,2c662e8a,db9c18e0,ca7e7c13,8bc51e1c,1a5f5c0a) -,S(e062011f,da416281,bc296718,300a080e,fe7ab89d,8469e8dc,fd50680e,12dd9348,c33030e4,1ec1b1c5,4ad01bb9,8c4e2c48,32b2516b,1b2b3b22,adc4add8,1b690787) -,S(f7c7545,649b4659,49618dea,7fd15a06,1e7ee032,5d955649,b76b66f0,534a5501,2a929b2,a68342c1,81b2f55d,6b543584,ac06077,d95ad8f3,fd3f3ffc,24f56a3f) -,S(bd90ad48,1694f297,6506e2bd,e97d5803,b810f9ab,7479ae90,dc1fb146,38d4d5a0,f973b70d,8dca64e0,c9384b7,ad3b4ab6,4d3c74aa,722f9284,a9da82d5,5c6d02e2) -,S(cb5d91e6,68b3c202,b72a38c2,f98e6e4f,14bb566c,f7996d9c,c08aaa07,210b1b1a,68e9920c,597b633f,9bfdfb8,72814422,4ad69ec1,e435e843,73a9255d,79f52d7e) -,S(d251bb9,83bf849b,8f058ff6,32ac6bea,bcd12649,4fea947a,f943cdf0,6e0c240b,5098026d,b8ec5c54,8e3ae103,f0d172bf,e84281aa,b8c0b131,16295587,ed4500f6) -,S(27235299,c1f8d73c,268bca88,62d2b6d6,635f151a,d148c662,6c0cd5cc,1a3d2234,5b03cc60,f9224aa3,10d8193c,74e70cbb,6513ba73,d6d98ad3,2e1c2d,7f78ad52) -,S(1cf437b,aef8e007,ba02a24e,735d8444,698e5edf,2f9d41d3,cdb28cf3,3dd53851,e3fcdb74,b580b8ce,8f6edfe1,c276c478,da11323b,4e96862b,926ca4c7,f739a8f3) -,S(aa872c85,70e9449d,6cf020c6,77669c8a,7ad408e4,d9fa194,99867c6a,f77df918,572579ea,3d1d9575,e60a79a0,7a2aed83,4fdfba52,61b962ed,42e59322,c02fd873) -,S(b3224a2e,80c3a174,66a9994b,717b4c37,424f12bf,9dd3f17f,6eecd801,3ee2ed56,7ad1cea1,128c1605,552b8be2,a5fb6bb8,907e4290,d76bc82b,e17ecc32,1be6fa43) -,S(29b8f73a,7fdf6032,4c907022,b0107c72,ed951eef,29687feb,a8de56ab,4e47b8ad,19b849d9,bbdcf00,a6bba6b2,f1058695,4f286884,9b5be608,d6b4c357,1098f54c) -,S(3c2f5680,96f946ce,3d048364,dce939b4,a05ae9a7,c31c2a11,d2a29a1a,3fed06e2,47701685,b698de43,ac515062,9c40a15a,bb952a0e,bdd96,ba4a1b4c,5f61658b) -,S(b80f00c1,ec0d059,c9f5c69c,10cfcb26,651716d9,3d0b5702,b2c7b295,85af4c55,aac197db,ab42141d,31f63425,5df908fd,fd026d10,1263aa7,63d99414,adfdd02e) -,S(66af071,6b78b854,16572c86,fb3e51e9,b6d66ebb,bfc2a2f8,dd664010,83c83435,b8b2ce8e,fe794b13,4fcaad05,821dd884,9a8318db,614d858,8dfd4d2d,65314398) -,S(7ce8342a,6ea85f61,559cd2ab,e82debe,82eb5aca,142153e5,320562a7,6ba155c0,8a930243,5ebf4269,d75363c6,93ad4255,59f493e0,e492150a,9f110c90,8d7750a) -,S(cfbc37c5,184fe206,7f7b5c6f,c5e50adc,ed58ae61,d9059bb,4ff64a19,f48483eb,bd567b19,3da2b2fd,bb8941a5,be9fc72f,11d9cfa2,4c4438c6,a4db3091,9c8867cb) -,S(728c27be,52c5a742,859774d3,2d33fbcd,41e997d7,25d6be46,af480c8c,f9ec436c,745c7738,2a833cee,19808d12,9768c213,7500e8b0,b140e3b2,94abe97c,9a7c73e7) -,S(4553277,fbb30c09,a1ac1ac6,cb7d38f5,88cd5f3e,d4ebf6bf,5b5f6e78,12d47d5c,3ea80bc9,dac9f1a5,ac4beedb,d254cc15,728f0ee1,6949ce97,53f1bfbf,98e3c78a) -,S(7b752d90,9fd6d063,f1ac0f22,d8cf1e6c,78a335c6,ed11743,88192fe3,cba54cef,a252376f,e482ec59,2ac440e7,3aac3b46,a149e35,1aac2d51,244ffd93,f51d11ec) -,S(e78e796c,eaba974d,89d344f2,b610e84b,d51443bd,1fea5422,d2bea957,5467a376,13f0797,376bcf76,b6ade4c6,a95b6446,962ff925,b32fef9f,4549aa1d,e64e2b1a) -,S(1b7a8c02,83f25ac4,cd4a841f,4045035f,92a39bd2,c1903c90,4071eb44,5e8d702a,1843f757,7d03b6b2,22bdc28f,47c7fe6,fb83b25a,8d795b46,9e3ee9d1,ccf7623d) -,S(90d06a90,6ad81dae,20cfc2fc,6be85b2d,41dd9f23,63e13423,c557c4c4,bf3e5e4f,6ba7a127,58861784,2d7ee3d5,9b71ec99,86a72ae7,71312739,79544095,1e5237dd) -,S(d7bb4e18,ab61d8f1,de4b5bd9,9a5d03ef,1e0185ca,55ef14fb,be1f0b5,4cc4803f,311f268f,a672975b,acabcab5,1dec5754,48eb5a82,685e339e,e23b41fa,112873e6) -,S(6d5f1808,f17e0b81,a6bf12aa,34032644,b708882,96e99861,fe5ba4c5,5546c44f,8eb304c8,92cee7e0,70649d73,ae76893a,610504d3,fdf37af0,92d5dc7a,9eab1094) -,S(e4f62cf,9835a4e5,c2b7a456,596498df,2973192a,af2c80ef,c036c71,69df470b,874a48df,1a25a003,ada8939b,f727e0ec,b7d2e4d7,1efbec4,7193a2b0,50ecaf28) -,S(7fb31d8d,b3d5b77d,4aa9d0d2,692013ce,c82ccd6,83a2235d,848037b,dc6bf8ee,ed5cfa61,9fb4e350,dc37e2a5,2bb67104,90dcb484,b19af368,8101e59c,f9f0f0a) -,S(8887db9c,e3eddeef,ece414a4,f46ff048,3c4fd25b,14354869,6c60871c,5eaa9ffc,50294d61,1040a466,f826e654,3fb93f94,b4d60b11,d589287d,6ea33df5,a8dcf366) -,S(9d9d224a,595c843d,1f70297c,13b3645f,385eec97,80fa9e50,d27115f7,b677aae7,af9d5f61,24594cd9,a3aa7100,ae6f169d,dfd467c4,1affefe9,c9a0a5e6,6d7f2802) -,S(743d9b40,527b23b8,f165b6fb,9d5c14ef,450e1ce6,94439354,ab501eaa,2f34137c,6aad08c3,bf602b52,7d43e3a6,e7efcfd7,f24222fb,f8213f25,e8195501,9c8f0885) -,S(63c850eb,f0cd6fc3,3bb7a4f5,6d43c389,1f93b11b,5f67e3d2,f9b7537e,e5a951e3,29d214e8,bde33612,a5a160e0,f7cf3acc,3b83686c,ec5d7c36,dd90ebb1,d97c7ab5) -,S(b95608d9,84c13243,63809f82,b42cd16,fcf3c6be,5b19ccd2,249016eb,d93b4a54,41aabb2f,e7083dfb,ea380fff,2467a843,c88ef6b4,9740e73b,33a088a7,649fb0ef) -,S(8361b632,5eeafafa,f01e3624,6bd8f0c7,aab461ef,cb3484e6,c1ee871a,7ef95114,34ac956e,791cef3a,baed24de,7f0f59e0,bf34dc75,edd10159,b3870248,255eef36) -,S(807109d4,931731c0,a94127af,cc98e487,1fb44467,6d8cde89,88dfc252,868bc853,363e3944,be00a734,4c50afc9,cbb43183,f56eb20a,c0a5d9ec,74857484,ed9e1d61) -,S(25ef876e,d1654570,244ec258,e7ebda09,35b11784,bf5afb7c,8652e5f8,bdb34055,63459bb2,b8affcb4,1f6ad9b,9437f3cc,6d8082ac,d400928a,29f11fdf,503c8553) -,S(1aa87b1b,54eb6bd3,5fefb162,b27ad9dc,eee4b5ec,c1b69d4f,1fc6e230,d1848435,e5cd86ac,23c3790,369d7fcb,2189098b,a4fb3007,f82e5090,22e8ce5a,b44258d) -,S(cce2b0fd,9497190d,e6ea068c,98bba7de,a8f50aa,12930b4d,9060808c,b1ce6152,b6aea7ee,becee274,2bd8146,d792a6e9,ae75fd79,bb8882c8,11135d0f,8d5e68c3) -,S(fe421506,955b7cf6,f6a84228,30f7c6fa,95e4576c,da711415,5a49c238,e0bdcd4b,4e4a31d5,9b70b51,f73a4d02,eb09e4cb,7dc74a29,bef959ed,86558fc7,d4c8f401) -,S(cb26c118,264778ef,512f8acc,385e5ac3,10b489dc,88991e15,13665b7d,587d713e,7375bbd0,9fb3051f,a907fee6,80683f93,54403c76,85ca7eb,97a711eb,69033c6) -,S(8f286ae6,171d88d7,d82cdc28,93960bcf,53768c8,9cf1f149,fba0acc6,f5056014,6852d427,a888c5a2,4e748f2e,e482d38a,42879db2,2e824d1c,d72cf15b,8e32b085) -,S(b7af4b6d,7eb4eb03,e827f099,fb8b02f4,bdca366d,811d031b,ae827941,235e75a0,7cea697a,e8cc53ff,8c738ec2,55a64e4,4a499643,4bc5e16,422ebb9c,17d3dd12) -,S(c8471c9f,53eaa3fc,850ae514,dfa1109d,e89c500b,e965682c,6a4bc2f9,105be1e0,7d5f32ce,d1e758ff,e38325b4,778e68b6,f0ae5509,fcf9195,c1a79d41,57dc519) -,S(8d192ced,73629184,ff6db80e,b2c6df4c,a8ad77f6,dfc98c52,9406e7aa,dd506536,3b01ec04,ff45b037,c1444255,9cb2f629,7b4f8cff,e4c3eed6,3b95d4a8,88fb2137) -,S(318aa156,f4912dd9,7b90ae6d,c29b0f8a,99f616a2,5b023f08,ad35a8c5,10ec5015,b398cdd9,5ad52ba1,d7038cdc,67e36c74,5625fb94,f62b1b9f,aa2eb5dd,be6ce52f) -,S(b7fcf98a,6a385f68,a1c6f9ee,c6f069c1,81b0c94,df8c05ef,b59b49e3,aad66f54,912e2098,e3b6e44f,46eb6382,83f554e1,80af035b,16c0eb3a,4e000cb8,d4ea2da7) -,S(599b7a5b,e7a7cc6,3e0b66,38171c0d,41d78efb,92a9bc8a,1d0e8f48,b2b92fc2,afb3343a,1983a867,c8e196c5,92f745c,9060330c,1f0c0509,375e30de,3a214b7c) -,S(c3578705,3221f18f,69dbc241,f927ec48,3280ade6,44c70129,2b30a11,a296db9c,2b75b2e9,fdef6060,29633ae,481ba7dc,8ca52847,d4d0a201,9da74056,40a980bd) -,S(9e2020e7,cc4153b0,adc2b1ef,3cf607ac,305a480e,3a8854d1,1907fca0,4811fa7,19153a83,2c9a0612,dfea182f,a855a039,33035757,2e98e5ef,43f26699,3b8bc6b5) -,S(1e0c4c68,6e5242c0,6645f4ac,6ccb18c0,82c5d5e6,c89322b4,3b6079b6,ccb5a5f3,63c4a4d7,3ab71f2f,c49f5532,b543e381,83ce223a,c8609be9,d6b72981,8b5dedfc) -,S(44b11683,5f922e88,e7ed4328,cfb212f6,aabb6199,64fbdf3a,87dc7f24,faa761e0,a9181b5c,341cd78f,2e1446a9,e99acfee,7aa5b91d,4c7da20a,b7cf200c,f470ffbd) -,S(940baf24,717ccfda,e539064d,f6e4b670,2ad8b60a,c32e38cb,fa4eadf2,6a7bd3e2,bf5ab95d,2cd9b68f,cdf535bb,84b967a3,f4fc44d5,5e6d21af,d09e1de,f5f13ad5) -,S(4191f800,85767106,a9e5fa6,8521366e,a3adbd79,ea315b93,9e63f797,2995e7c5,662791d3,407f50b3,7a68e15f,5ee71991,2e893099,a907db3e,f818938f,9c3bb2cb) -,S(1bb8ec05,76ce9cad,f96b418d,cb5c7d46,9b49ca81,7f253b15,8b26cca1,cb9a472d,762e9c6b,2335769,72396f,36a56efc,f2618754,f1c30923,30b521bc,4e0198b7) -,S(c5216da7,91635b83,e55ec5a2,d9f3f8be,b1a2b0e3,cb097528,654c50a3,315be78,2536358,e58ffcbe,789d34e3,25d9f59a,2210c247,a80eac8,c716214b,9d5e520e) -,S(7b1488fc,83a02d7f,d12b9eea,555922d3,f4a9c42b,52f030d9,bdd39156,f0890225,ae7dba7a,d95420f2,8c8185cf,5aa2b777,b9fc5c14,b6c47048,d8ef071a,77dd4397) -,S(e245e4f9,7d6c69d1,5e244f4a,668afd07,d57fea2c,f8401b2d,8cfb6ada,f01f8891,88a0648a,ed5eab1,d57226e4,63411b9d,3632537d,699f39dc,7d7cbe5,49e76900) -,S(ed78f3d5,1f4fb987,5918a0cd,d6e5280d,6516f5a5,acdee916,d3e7c7a1,d757d188,ebc569ce,9b3cd325,528cde0f,9a2ef54c,d9f920a2,1ba7785f,62ef40dd,9463a81d) -,S(3e8d870f,bf768b41,8264ad34,89026fe7,8870e201,3f98696c,81dc3b7b,c0b1b599,28558e59,a6a6c255,a352cc9a,c20508eb,55af7449,8d75ded,c94fe414,fadeb218) -,S(96125a01,8f901790,fe25b41c,f2f7fc98,50cd30c8,cbd05ffa,cb76bc45,94d5f5a8,125db476,3fc8ccde,492e7eb4,45873147,8f8ddc5b,6c2b588a,b72d9b1b,fcd4c43f) -,S(779d9847,6fd72d41,937fe1e3,e12d4076,5cc61f41,19b37437,3919782,18a3dfa0,75a3aa4b,95523e05,42f38dab,b2d80895,cf3738fe,5152c8d0,96a587d5,90442891) -,S(681e390c,323224a0,7ccd9520,23c9d89f,4069100d,3b275c5a,e773efe6,170f4e4a,a9bff0ee,334bcf6e,a3bc44e7,5d85acc,f753a471,ac008e0d,47b19ac2,476b184a) -,S(d7b8530f,3fa18d18,ed94b938,2906e431,44ad5994,5eef1d53,e3290887,5c4af2b9,2efa5bd1,acc4ce6,73b8c76a,beab2e87,6399f84,94a1450,bd6833dd,debddb92) -,S(1277ad75,6e965ecb,c8c04ea6,c22042a3,ca3e71e0,74334012,7063d3b2,da257a5f,38c90310,ee2bd94e,5f3149f1,f38d065f,8df110f,92f126f1,3a69013c,515134ed) -,S(4e66e596,94c521a1,8114b232,427dfb97,8c7f14ec,7b5e18e8,9c11cb5e,6a2f6f65,47d553c1,8a858b59,f1aa8f4a,51803450,c237fd2e,60b137f6,d13647e7,6683caea) -,S(1fc1e8bf,3eae2dfc,b141be5e,ea612378,209ab1bd,7ccce45c,d51fcfb2,8f192aa3,5632d350,ab6b3da1,599779c9,9cd8d7b5,e317ca9d,ef3245a8,eb62af95,ef769c20) -,S(7eca2d92,8d2bf4fc,ed1a8336,eb87c5f7,b864b842,b3057c8f,97d5dfd3,76771d7f,969da039,7a37997c,c243d448,90d8110e,fa580359,bfb35342,bf69dec7,4bb17337) -,S(2531025f,8fddd665,cf34baec,52733303,28e47e4d,827248ad,9a1e6c4e,be3db9a7,e404fbcd,d180b2ad,931b4f61,5902eb06,cf00f66,6f1323f7,bf0652fa,94dff64d) -,S(dd28941c,bf6e4bd,76b4bad7,88f700a6,8c4937a,67958c3,bf6388a9,d5e26441,cc45f07b,9ea1a81c,8d89af84,8883ad1d,53ee8a52,2416c445,c4963791,7a366909) -,S(d3af9e12,53ffb85,ec7829a,4d41d704,1ea62952,4d7452a8,d9ab6ef0,1d6b509b,9c115e78,91b383ec,20739d37,6450a2e6,6f332e5e,c7a3a97b,2eca8c0,ae819bbf) -,S(2c59063f,13ac98a5,ed196aec,4f2aba11,c8647d78,42be85f4,ab87a007,2b49001,e9738418,cbb6e31c,f588a3b8,70883f90,ed3bd8e4,86e3c77a,37fd1152,c22637d2) -,S(6c0ace3,f182c963,45deeee3,c41c5e51,8dce984d,3d409a89,6d766ea1,b1ff0e0c,17e09dc8,dfc53cb4,952fec4c,92782ce4,3515544f,6181bde1,1d1ba1a,bda709ee) -,S(f161125f,3a229d29,2053fb9f,6f118550,43d80e33,9bd45af8,c1519043,2098c9d9,1b442ffe,a186cf2c,343b90b3,66a3a008,e08edf90,f073e740,abd5d20b,8dfa1327) -,S(fd081f05,6b219fef,56a3fc1b,6dc7873a,fb054b40,1b3ae0b2,414384e0,9080827a,9711912f,4ceb0036,3e5921b5,c2f7ca49,387b78cb,f1b9c2ac,9c5d5d1d,1bd8203) -,S(72c6eecd,d87657bb,ffc3a03d,b6e1f9dc,83252d2d,c73ba3f5,8642fc08,fee42b4e,282180c1,7737b51e,d047cc50,64d53cec,6340eefb,d969525e,a1524f0c,a305e39f) -,S(10df231d,4582143f,1ad7fe00,508cbbfb,3d49775d,f13dcee1,d6155768,c14bfc51,b7743bf4,e7cd49f8,88cd0d26,ac196037,e1da9402,26518e07,407bad1d,20af7dc6) -,S(354e8b0b,e40bd9a0,36620006,744c0913,5bd4bcea,34ab3371,9561e36e,f465956a,3e7407a2,2b9d71eb,a04239fa,600834d7,5f643c8,b4ca6308,475f6c9e,8d35fd4) -,S(2ae99ec0,6a4e080e,879a60fd,a93a47df,9ba7e0f3,b87a6772,be6d7e23,9bf2c42f,3fdfcc57,6a36adbd,52467e01,f3490fbd,82766cea,b956f80c,7b1d29b0,5066c31d) -,S(f47ff09d,5e93e827,72e73c7a,8f1623e0,823b09bf,86ba3023,a223a680,fd849bd9,379ad3a3,cd546d27,35fbe5d9,97c3dd8b,8c45a3d1,ce8e9c49,b23bbaea,e93a08ea) -,S(252c0934,acc3a624,c4d8b409,111b248a,2242dba4,7d57718a,aedc9cfd,20647cdf,17b7a015,a2ea993e,89a7161b,f50124ad,561ef131,609981ac,fc92e495,cd2ec91d) -,S(b7f6bde6,7cdbbf9,4a3e06b7,dc1bea75,d6247197,a8617a6e,a1f65f44,a7459006,6d6ad596,fd3472c,9d7eff56,943c1a03,ee4f540f,29782f77,afe999e6,14f5e316) -,S(210c956f,e0a741a7,edad58d5,d47a2a34,fface7c,5edad0f8,f4953b72,28350b2f,4d4498a0,892a9a9a,4e87ccdf,424d7910,bf90fe95,186653c7,6e6966a5,e7a816b8) -,S(7ab93adf,b8f35eef,8af99e5e,e37aaeee,401a1936,fc0b8c88,518065d,12f4a74,4f0782b1,c78954b,8ce37bdc,7e533145,3b885d92,da1dbf85,940da9a9,b7f0dd8d) -,S(bbe1b787,9c93e7cd,891f628b,c9a655e6,f4c7cde4,fa799596,74978224,9fd05fd0,493d3dd7,be33acf1,38ef5b73,8eb8f8f5,4e270323,8f70078d,5f7bd9e7,177088cd) -,S(61f42d35,ffcc6151,f8c93b21,5df0cab1,fb804cde,f9c68818,fc4f413,b804942d,46ef1e12,d6add082,3917a758,9c137d45,c38ae2ed,eadd847d,aa574e06,18708396) -,S(18542b75,3e78191c,b3dabcf,f9c64a8e,5e4b075d,d600fe60,b830e732,7fbc7b40,6a816e01,41b17e86,65ec280b,f6da9dbf,8061329b,6db9d13a,a9f10c0f,41340118) -,S(ef83d0f4,a3d2963e,d14e708c,6d22017e,aa97b2f5,23b06f1,140b4105,459781d0,5587e5,13725819,1b10bd40,e616e06d,16a50392,7a8b1394,a562c396,973d98b6) -,S(fe73429a,7714dac6,ed0db327,d6949d43,30d2b16e,a513d3b6,7b74452d,78a82a4d,7079088d,fd828815,ae087319,c232817a,4928f743,843a4966,e9411276,d16214b3) -,S(2e8b8a63,3048900c,4b82ff8d,fd86a971,86e3f1b4,6206b252,f06a8c85,82555130,74e10dbd,ca84d796,b3b37ae,b32624c5,2c5aabc5,d4fcc5d2,21c1aed4,71c940b) -,S(9f4164f5,4f34a59f,3a7be378,66a8204,def2fd98,8dae6dbf,5d471e0b,caab7017,4b662fde,bf2615c0,8c7b53d0,b2915d50,ddd2916f,a3599d81,bb2eab6d,80e93f57) -,S(c6f3a26b,adab6699,aa08fcf4,6f0ac900,2be3597c,16133225,6a5e6577,11b16ecc,f29db1d6,579d0e36,4528c297,36019f4b,6e8f060d,ad5effe6,d357d709,882a250a) -,S(76a4f5ef,6a869e28,e6494cbc,ffc6eec0,1ca983ad,1b8219cb,d2b84eca,96f8b910,e1d8bd7d,55a297df,32ee185c,c60db286,a2e46cb1,312a8995,5923a068,cd3318d5) -,S(d2c25c8a,cfaa0b2b,3f6e70d5,bf095700,68102f8b,24867970,ef3c8000,b2212d1a,bc907681,9c7926dc,bf81278f,7dbfc4cb,292a8071,177ce8a4,f4e9346b,a2d9e500) -,S(b2fc2ca,5a30c678,61b0bd22,5bf2c088,26d799a5,9c9a680d,dabac9aa,5cb624fe,d4abc7c9,fab915d0,fe9dcf59,a0f83ca,56b27566,6e9841cb,b5b14874,5f6732ee) -,S(110ef531,7824c321,ba7fa94f,ac98de3a,c6cf44af,db92b7be,1006c751,9b425065,cc3daa20,6c0eb83,6bdfe640,1f7461a,261e7233,c70e615f,db82a991,77b83cb7) -,S(fe21a607,7419ed88,12d16ba7,5485e01e,3c063359,f95a8634,3aab1c84,ba6ac00b,d6e08c98,4b7a5282,bc1857b8,82604fc0,692a2fa6,40cf5a5c,d298f344,54c836b7) -,S(c5e45275,ec85bb32,edd32702,7d7d87ac,8394bc51,722e0bd9,58281e61,c454fcef,9b158ee7,89034035,fec4f06f,2fc81755,59f9f762,38742715,92ca6ff9,e5712a8e) -,S(cc68f3f3,36360481,5583d65,7da51968,a4a44a69,1264bac8,289791aa,dc7a4ef4,9db5cab6,7b31f3fb,f3b5fde2,273496f7,93316358,6d14e80b,bbca4613,319df9aa) -,S(6d33be85,5fe8bade,89109a3a,8c089aa3,f7e9d178,969100b7,eee7a693,d83ace80,9312736,87c08455,c43b4cab,afe71408,333fbd69,d330315a,3fc9a52,a9d473d0) -,S(5aa581c2,fc48c38c,2aa2e176,c12f12b5,4810ff6f,862fa17a,196c06e4,812b9e3c,adbff08b,bf6fd5e9,9f91f9f0,9881cfcc,a7b5c2af,709bf838,6055079b,2f75f3c4) -,S(12eb2dde,dc6ea4e8,dfd43067,9d45052b,b882e4d9,bf516b,61edaf00,305fe883,8f948ee0,f8514f9a,1bd8a71f,20c95e4d,e30caa5b,bb3a383d,9561f027,34bb1950) -,S(3d0d7eda,43045e9f,62dc680a,be47e933,74a95d59,945b69cc,60acb89d,e40dcded,45c53d35,e369af07,eb223a79,1d148ea7,1875cd1,8ca066d3,399743f9,65e184b4) -,S(173d4741,5803d266,7ea94abf,319c5917,204256ca,e217647c,c024a9b3,be7b70c,2da6c348,cb066462,eddfe8bd,3dd00ec1,34a0a060,4b7e17d7,e6cda389,dd4d5463) -,S(10659655,e2f1ba5d,db390184,c2d6d1df,1cd2abfa,4cd4bc18,c89decc9,5b5d6319,5ac2793,3a88870e,d5c7752a,459ced45,69435a09,7cd0e030,25608cf4,ac2ae267) -,S(e462be7c,380d7bbe,cd45c6dd,8fe60219,404b0c9,4c5e0e4d,31a23064,2b5b95,872183ec,1ba5b854,1f3f99d8,ceac80c5,9e84756d,cae2e694,9b43ea7e,d1cf752e) -,S(8200badd,1df41faa,19b20cb8,efa424d2,2f39b1f9,26b692c0,2a0ef6e7,feeed67c,8402fa9a,6ef0f83f,42546b05,360296d3,74db551a,d89be995,f2c11866,5be528b3) -,S(760e2457,a3e1a165,526e9fe2,2b5bcad6,e8107581,337cecac,e2ae87dd,a3c54592,c5111ec3,24158a21,56b897a3,82bee2bd,de0f9df,af9ef611,a7fd3fc7,4a635b3e) -,S(ba6229c7,1729cae6,5275719d,9a35691c,f260a003,168f1a25,1ac00b09,aa17872,7d281600,6bd8981,82126d21,70fa0ab1,d5dd0c7b,cc377a88,c43cbf61,70a633c3) -,S(a2cf1392,571e758e,6ec74708,dc45f70f,90833ad4,135e7a34,9d2810a1,8efb5216,2420ffdd,afe96506,9e6f9266,1e3839ba,c9b1db40,d40149ae,3acc8683,86acd175) -,S(f8822204,27cc4b37,33268925,fb80beb5,a52e5391,b2c8e31e,f6e99592,1775af20,6cf6eb9e,b19825da,6edc5d2a,66f3987d,c9eb01e2,b70e6395,abe2903,d43acee) -,S(eea28950,fb676991,444f96c5,7e42ea16,aa380e3d,dde63111,fac35708,a4e45b3c,34d30722,98a686ec,7e1a8095,4e2911f1,5e11d426,ecacf11c,eb45a5cc,7204114c) -,S(7f252a72,6f9a1497,f61bc4ee,7b194a31,432c0178,2f40b16f,2d36e9c3,7279e25f,8edf25c5,f50c6f0d,f8a17f92,611bf024,14e02d0c,de38aced,e96d5a7f,4467c449) -,S(d3da23fa,56881cf3,a42a50a7,42e1067f,54ec24f,2de19921,b1ae7f15,fb90509f,b4ec4b17,8e555cbd,15210f09,bd1ab43,28e458fe,6aa3e800,44bf0093,ea08f90c) -,S(6752f294,f8ad85e9,60b6a88c,cfca7874,5c80ed7a,93f6f05,3782ac73,d96e31e3,976222ef,a6f6358d,42d6289a,4f11bd65,e7e755a3,845ed49e,3c972b5c,5fdb2418) -,S(4fe21b06,24a45b69,7f42aa54,10e6385d,645a8d49,2a61ece5,c8d5b2ad,1fe74efe,f7666c09,7caeea3a,c4b2993b,64f4c0cb,ac934099,8870ade,b7cee48a,c3c2c413) -,S(15af87cf,6dc1acc5,1d323a36,b2daf163,ccc8c201,a92f0677,6a26ae27,7fb9d766,53fe4566,6a975d35,ed20a5a,7bbe63c4,4cf8011d,45e7a171,d5d72e57,5debefbb) -,S(656f3686,c60039b4,4c39a5d3,ee82cd08,e8aa8ed4,b9a943e,42281407,4ab6821b,9f277baf,2da730b3,dacc2a43,512411c0,13ffca65,7092e695,d49c8d24,a4cda4d5) -,S(a13286fd,2c17a61e,6bf8d209,d64f5879,2534b037,cd854470,a09c8c8d,95aa0564,9322d3d4,c735a485,5d76e5d1,fd27fdbb,a8af2fcf,ddf7bdf3,f9e26f97,7f4cd1df) -,S(3b355928,4ddb285a,1eab73c5,6e6bc554,9f40d83a,2b859e01,a30032f3,a5a7109c,780670b5,67755fa5,10fc3385,7745a69c,bbe73e3f,8186b3c1,8a82c51d,5e1d9be0) -,S(b0b15be8,6c2dbfed,6da6e7c6,51c10b17,504070,7d1747c3,ff2dddbb,256fa495,8d2c438a,42750adf,345332d,f02f6c4,55a07fce,afcc51e4,96c270ff,913546e3) -,S(c754130,bd717ab0,fc17e14d,dd6ec50d,aa6bc02c,a338cd9a,798ee62e,72d517db,fddf938b,28500dd,c9f1fe0e,70104564,d1bad398,d3bee900,ff609c8d,f56d3b26) -,S(ee615579,33d877e4,9bb228e3,62766ada,8615d382,c022c333,39f78ff6,5e5d9ceb,3dd38b15,5ce01a1b,3d5434f1,b2e04a26,6a830f47,fe89263c,b0ad1b5e,18bd8b76) -,S(f830dd7,4d03a39,d7f5ba3d,132b40bf,130b33cb,9b6609e2,12b6479a,14287c9,9183a68c,33c2d25d,c237f8ed,b5a63d44,4dd2bffb,d1255631,221edb9a,4c9e9e91) -,S(544fa477,3aa3589d,9e63c8f0,f30cd189,a8b6658e,ba908212,cb1b4caf,2d5f64ca,bbf57d7d,b5c6b8d6,e202a7b9,8ed06edf,e1a9ad01,381da1d8,11405fcb,8ef717c3) -,S(9b270440,132f5b09,6fec6214,dac1e27f,3e6c6f7f,25eb2cab,680c3fea,e0b41b1e,a7e591d,eb990617,6bc87263,6ea19e04,c9a3aea9,59059078,2a757fd7,6d99c6dd) -,S(bbd69c5f,f0b9228b,cfeebb97,32b3c316,c14d9a54,d5a3e9ca,ebb337e1,e33525e4,78cc6c84,8c246e7b,7636949d,4e3f2b94,989c77c4,812b8189,cb857cd1,3457c403) -,S(a920edc1,4ddf5bda,56719c0c,2adaea7c,9aa8aab9,25a5d6fd,41172725,bc65341d,b8afac74,46e560ce,bcaaf438,69dc9287,2805fc14,122cb19a,bb59e51,8336ff80) -,S(3c6e9595,a201956d,ed27e83,41b22822,445148e6,d00b2fcd,ecfdd66b,2405ae3f,2b8ef9a7,d7c37d0,d2b77309,74718eba,16f221a5,f3074678,317f0b6b,7b0841b1) -,S(c35c9e45,3f487f8f,ae5b6010,e1bc1ac3,ebe4ee53,33666876,13cc4b35,5162ed91,7a8e64d4,9f827631,579421ad,3c7f7ea1,f4866432,a341f955,6741c521,c757addf) -,S(8fc84331,a8f8dffe,28f30d71,b39c105a,ec09aca,4876241c,1c81a223,a1953637,aac7257a,cf0fce3a,ff8fc7ea,e8d19606,2ba6d7ad,9b7987bc,35a92b9b,20360174) -,S(b43ca4ce,f1b4a2d0,1a20fc64,2f3e1456,317f729a,1ee69798,4ed88bfc,1c5a2908,39ae1e51,f352c0c9,8a79cca6,cc859eb7,92bad6ae,5318f99d,d62d3bd4,d8fedad5) -,S(7f29c501,75628aee,5d39db41,cc4d89a6,9f133f00,47500f6b,aa7a90cf,e13159d2,cf17c6f2,f6072b50,257f722b,5756d8ad,c7486cc1,d21a925e,8cd29a15,4b514cd1) -,S(3fb93959,55ea2522,61b0488,212e15d6,b28e975e,5ff5f357,15337538,247f2a54,7c3db409,e06d6980,d834639f,e9e357bf,e6a4e9b0,ae6b4fb8,f5e45143,ff625ddd) -,S(945ad871,18199665,a4078a46,a9596bd3,ec7cab84,b6323a0,7ceefc63,d7ba29f5,6eb6d896,a24d02c0,630c909e,65d13d4c,2eacf1ef,6e600b89,1b171594,aa28c206) -,S(513bfa93,57c827c1,b3c0289b,c4ce443b,cadfbef0,b28b32a9,265ab85e,67efaf4d,645c5b3f,d45030f,1aaea514,baba7069,91def89b,56fdc292,4b684241,6653b6d2) -,S(d41b35bd,421ef7bb,1c03c794,477c2851,dee92831,714180e6,6e57e735,caba5835,beea2116,9cf971a5,ffd83596,d9bd77eb,cb1e0c7d,506a45ae,be8c0c7c,22738f9d) -,S(96006d64,fac8f0de,88f93e05,da8e76e6,40afc1b2,8ee09a7d,5633643b,d89ee3e7,1404173d,e96a97e9,ae9bcad5,c9093d05,cba96479,30bfe6d1,96664d0b,13c93618) -,S(ad528227,12257f87,d1ef82c4,4af5f046,648c2a72,497651bc,2327e971,1170e7bb,2ea908a6,c742f542,324be959,4746ee48,4229d497,cc8bd535,e7989525,aa36f079) -,S(b4709a81,c067f6e3,93ef97ab,c26675da,6f01a2f7,e3f35275,e7089ea8,ad5644d6,f655b89b,d6a83838,ffd23f6a,fb944bc0,57fe7f1,1d321a0d,2152568d,91751d99) -,S(3b7bc8ac,5ba85b40,2080612a,84e0226f,3b43c8de,c0e54b6e,ea779b76,812782f0,8405dedc,a02825f3,5a60333f,190001fd,98ea3995,9dc6e61,c28c5e2e,5213fb0e) -,S(2a76b67,d197e7a3,7a38bb10,d49d523d,c4beb4a3,75336974,7e22e407,9e0310ca,6331389f,b9cf9fee,e89b089a,95abca6b,a3c2aba5,38725c1a,6848fa46,997d0e87) -,S(9938e808,77c2baa4,53e0256e,d250439d,b11732de,1abf7555,949a7574,f62819e3,250b061f,bba0faa4,468a080a,fee8264c,f72fc12f,2ac91dd7,13ed92a1,1b281124) -,S(7366eac0,7e5e4573,333291,3e42f111,e53a78a6,5069898,52db2355,de089230,b8dfda33,31646343,bfb60b2f,25050967,e735861e,1654f0f7,ff42ed9,5dd652a4) -,S(10fc632c,cab22fd3,2583599a,a2efaaf1,6e1b01e6,a5a96c59,50871012,33022152,cf53d9ec,c74aef44,7019150f,ddfde494,c2382a07,b2dfd73b,c628478f,7fbae0eb) -,S(785f4da0,240de52d,bb50b1bd,bc53994a,47318076,9a1fe06e,5a40a8e,e677ce63,9b5759d2,f77bbb9,e40ac169,a01500ca,6dd6bd70,6a003871,e7ba4d66,b32db9e6) -,S(a7f20615,593850c3,27aaa06f,c03e0d46,d3ff20a0,9b849810,1759638d,8cbb9cf,13b9ebb6,f0cd59ef,54e0f935,87a14fe1,2337e346,94f5e8f1,10323fbd,d7604d3c) -,S(cf083e4f,e0ed4444,85dbd99d,8e6823bb,483eb749,b94ce672,8671de8,6105aa4a,36eaa305,37378494,17050dc2,8290c74d,d9ff9df4,cbfa434a,2b89de00,e06f3099) -,S(9fb8c370,bca485d1,dcadc251,ee906f58,6f3e177,be37baec,6912e535,f5c7ab0a,df5cf77e,1ad07532,7150136e,7ebe7f35,1db47415,74444b24,e9cf2f4f,31ec683c) -,S(ff9e2f29,170dd456,2c94d48c,eeb0390d,db783702,c13574f,8a8c6a79,6427adca,784c7b68,3c824603,5077911f,957aa33b,47534180,d70a60d9,f248b860,736a24c2) -,S(802343c3,e07f9f9d,ed2ca436,3e455427,367b852c,d23ffd7f,fd690eab,90b4162a,b093f0c5,f0fc7d01,a5dfb7f6,bf9d90d8,8595140a,a13fbfc0,f7d6af2f,54ff5ce0) -,S(ae74ed87,11a1a684,9e558e05,47ff8f9b,f6337551,1dd3d272,ee0597fb,fc2d6914,c304897c,e5afb5b9,a383cb64,e85071a3,cfbb2981,93ea6ce0,55257ba4,cf15bec6) -,S(c099b05a,dceb601a,14892c97,7b267152,f29ea71e,fed6090e,7267249e,43c2390f,6c3ad3eb,8c95c72f,e0030a7d,34329945,fd1eb71d,8c4aa1f9,8fa4656c,6bef067f) -,S(97c6949,a25581f5,945814e9,9d590dff,67d936d5,94101005,4cac33d0,fb3658a5,cdc7faad,5bc387ce,a16a10f6,6971e5ee,6d32756b,596adc14,57081ad4,1dbd2e4e) -,S(14a19edc,a1ec89e9,524548ef,cf3dbc03,81b14b46,928f7425,87b11df1,7aa721f7,f83c4d0,aca08709,63a017b6,8db3434d,6088015c,2ff1d8bd,739fd620,35d1a19e) -,S(4742af63,c7597424,e6d04a8c,cb43142c,54c5b350,175bf5a7,27c39820,2187d00e,bb1f2f72,b21e15f,ec17af32,2147edfe,1ca80ac8,3e030dfe,8be39fdd,f340c56d) -,S(a6597869,4d168b00,d9df41de,fcd48ae9,68313394,db683407,330ffae9,f2559a11,6bf65c42,13317a5d,fb561e8c,872c8b1b,90bdabc8,8a8d2e1e,39919f8e,5043ced3) -,S(9e62e468,1e22abde,4d7a2fa1,2f7867f6,ecbfc15b,54990e26,821a8cde,fed76985,4877297b,a64fa8ed,c039ab1a,e62ac72d,8d7bbf05,7513d1,4237b8dd,9f1acd37) -,S(d24333b4,de55b0f5,d47c72e4,88cee8ee,8c960903,260a64d2,c89bca45,db7352c5,688b20b0,617ac12d,5be38fa2,ab52e785,69766a83,2d8b44d5,cfd6ee88,b19b9f1d) -,S(d203301a,13d1c8ae,a8c79007,1ef8116c,3916bb3e,dd5110a7,304b9145,465be838,a606dcea,398dc313,e61c8fbb,dbbc3874,3c103297,164e66a1,4412a21a,5319e55c) -,S(d1aa98ab,7010146f,16a9d6b,cd911535,2595bfa5,1bccb3d5,5e3a4a87,62666610,3abafa4,999294e8,80e3fae9,edb4206b,9b9786d,bddcaec,e2d01cf1,ab715690) -,S(1e20823e,81051b2,65535085,9aefed6,3631dbe,23b4e79,abd3c17c,21f053f4,e238adb6,86592008,f7fe34b9,9b934060,15c323ec,55981b27,85feae6e,5fde7186) -,S(d878afb8,8527a861,4b4276d8,fba39300,72196017,6f437014,980b7bbf,d4320ffc,7403107b,fca8ac64,baa94a4b,128e72ee,4a015675,845519ba,d5609331,1680e7) -,S(53f86d45,61deef96,ca88a685,38fd35ec,a95740a4,3a52c601,faaad0c2,aa3ab72f,667a6ece,bfb97682,c5e9e5df,b6d29156,9604f63,d9ab00ab,8cb10000,e6b01514) -,S(20990660,f1055420,b885fb0a,38824740,3b141c37,5aa20dce,8a29191a,e77bbb16,7d434476,9e302e38,9e14c02e,f5fd8a5c,64cfcf3d,e9813f1c,f53bc6d3,4da93559) -,S(1e70619c,381a6adc,e5d925e0,c9c74f97,3c02ff64,ff2662d7,34efc485,d2bce895,c923f771,f543ffed,42935c28,8474aaaf,80a46ad4,3c579ce0,bb5e663d,668b24b3) -#endif -}; -const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)] = { - S(8f68b9d2,f63b5f33,9239c1ad,981f162e,e88c5678,723ea335,1b7b444c,9ec4c0da,662a9f2d,ba063986,de1d90c2,b6be215d,bbea2cfe,95510bfd,f23cbf79,501fff82) -#if WINDOW_G > 2 -,S(38381dbe,2e509f22,8ba93363,f2451f08,fd845cb3,51d954be,18e2b8ed,d23809fa,e4a32d0a,fb917dc,b09405a5,520eb1cc,3681fccb,32d8f24d,bd707518,331fed52) -#endif -#if WINDOW_G > 3 -,S(49262724,e4372ae6,f6921b82,aa4699a1,f186aea5,40122630,3ea42648,97c2a310,1337e773,bca7abf9,5a2cfa56,9714303b,6d163612,a75ff8ce,c41b681,5e27ded0) -,S(e306568c,1a240c90,d5e253b3,e477e2f8,4dcc1a56,ff06db8d,1384b079,cebd2d31,eac6fe3,78934260,888f2b10,7f7d0db6,ffbc8042,be373826,692b4083,92546e44) -#endif -#if WINDOW_G > 4 -,S(3b9e100e,2428cefc,271b0e76,23fbd633,74ebf8d9,aab41dd9,c530c39e,363136b0,fafb9815,2d16bb71,df1533eb,8f475b26,a2ae28a3,3ad31f81,953ec16f,6cdbbc8a) -,S(bb0aad49,712ac9a9,2b76ca80,f5dedef7,17ca0768,8107beee,9608f047,2f485d3f,ea699c53,c5835479,8ecd201f,7297da34,895a5afa,31670bff,e7939250,3ca2f975) -,S(79090ac8,e4eefcc0,d4e8eb19,7afe0113,e1e58b4d,b01123de,4aeed33a,36718dc9,eaab722b,91905b8f,13d816cb,cd9aaa56,dd36afb7,ba9008b,963322b1,1cfae7c5) -,S(e77c81ad,e9f97b55,1c03dbbc,e549ba66,8dd71de7,cd775ad2,a269694c,7f60c7d1,3acf1478,eef81321,c5fc3b32,3ea81543,631470f7,1c2986d3,4ec581f2,82d72449) -#endif -#if WINDOW_G > 5 -,S(de2b5ce9,dbce511c,f2d8878e,3ded87cc,3d633dae,a2d45341,501fb3a4,55ccf6b0,f10576f3,d3c3e0e1,bbf717e9,8b1a3744,65b8c45a,c66318bb,34829eb7,11100666) -,S(d07bddff,d491a2fe,1ea59fbd,7c121217,29659ca5,de46658b,26b1460b,13c03c56,b2ad4708,cd3c97dd,f9c40e2,a1de04d5,61d963ff,8cc2eea7,6be3f60c,2b405ce7) -,S(82403e7c,5d3016af,3765ec4c,396ce8e1,f8da45c,434b8257,10edab41,bb6a4d51,d09661b,e27cb767,4456badd,b3e84051,99ab6ccc,4ec67c1b,11e92ead,7b463b19) -,S(eadc3131,fbd626f5,263faa58,c4caf4d9,930f933d,9541c23f,438cb486,750680cf,d3c977b1,c9b4a897,5c64b36c,972d5d01,a388fb9d,c3791a74,36094ff1,2c87a914) -,S(3903ee5f,6758ff24,c518a4b3,86748f4f,36bdd65c,b77e78ac,609f2909,fc7987d9,e92194e,a15241d6,40915934,bd234749,8d222a18,4927a8da,b0cfe2ae,182be83b) -,S(d0803b78,39ab48a3,8475bdcc,f9a9f219,5759c343,dbbf8e93,23e1f882,5be6a5d9,2cc3b180,ff29c97e,a12ec15f,b38bafa4,4ecf06c,e51d1d24,2894a926,64582f0b) -,S(1f56f096,b18a7499,a153a5ae,acf8be05,8496dd23,da8e6c19,215628fb,c0567ed0,fef22b8a,3b52f490,83004436,b65cd69,c94189f4,1a93c0d5,1fc13cb4,379dff58) -,S(1d9f69b1,a4a47432,e386f525,234aa30,79e947cf,cf203297,4e0fc05b,638e213b,d898ec17,949c0761,b38500c3,a2b1da24,5438d5b3,d3f6f720,41f15d6e,e4d4ccbb) -#endif -#if WINDOW_G > 6 -,S(128c913,4d9dcb78,12fc4361,5c67ad0,55213354,dc8008b1,aeb5a9dc,fb629efd,fee3e54a,dd152610,d9725936,99d662,c160c8e4,ec6f76e4,5ff41818,be67c96) -,S(21ec012f,5a95b94d,244b8d51,9756075c,301f2854,8e2c51fc,49c0e3d9,d1a9685,2def2105,77af497f,4c7fef71,6949f28e,7418eda6,fd5fc162,d128de19,3cde08ae) -,S(688f5202,fb9d8bc0,9e480e89,4c7cfc74,761c3be7,7dafb11c,58422836,3e331cc5,96ba7d59,63b541a7,2ec7cabd,92403434,1a393eaf,89eebd94,62d9c218,c7302cd3) -,S(fb5c9eea,1cb9a8f5,b3314c30,a50d35,744d0ef,e8bbf68,2e4d3ab4,f7f02baf,29fb8844,e18fc551,fb28bd26,95c5e95c,6868e0cc,7e526af0,91157e9d,fb630418) -,S(f1479fe2,2eedae3f,2f5f6a5d,84a9de1d,593168ec,7b52380d,e0b3625c,cac03421,1a642d5d,2fd88b82,13b50d1a,3fbd3419,c0b4630c,48352131,cb856b2e,22764606) -,S(2273edc5,e8199774,93c5b0e0,9fe0effa,f60f7b,2898565a,69f5c7b2,bf1a7950,b3aea238,8fd978d9,29f1a1df,98495358,b64691fc,4f50b530,906ae39e,fe7bda12) -,S(99f8480c,30504378,b47d10b3,2b39da2f,496d59f4,b1462856,56f05ad7,9bef5214,e001d55d,8e224286,8d8bd397,cb5aa99e,d930e437,e4e62151,71da7ae6,6264b2cd) -,S(382257f,e4751280,d74fdfc6,993c8642,9c000d5,87f57635,bc9656ba,996a6f1f,c2dc733d,fe52cb06,265a4f1d,a6b5f1f9,30dbfa39,e3659973,1c672aad,8b51d474) -,S(23a13632,9125386b,e45f4e1b,2acc847a,62e5eaf9,f6d5f452,6e145e7f,ecefb24b,9129777e,643ba22,2bf817a1,af7155f1,413cc370,3734ba6f,49f15f55,996854c0) -,S(6659ea60,58a664de,a35791a1,8c5cded4,8cf5593d,c440b9d4,8a30ac35,79149f0b,2adcc705,a85d836f,b347b69e,742fc6c3,5300d1d8,e534f1ff,c820c6d6,b2f2199d) -,S(52dc3bc6,e1acd3b4,7ece6f6c,89fd2a3e,2899b487,41421033,37a67dd,1ba939fc,5daeb346,32ad107f,bd83d9da,15a3c4ff,1e8f6ba3,ee5193e2,709e89c3,43d05746) -,S(524b2a97,93cd5745,bd9189ba,9c947bc1,693fbceb,75f074f6,17376b10,d5573551,9e8099d6,cb23fb1a,9deb92cc,3e8a2fb5,a6865ac6,3dececa0,2d146e1b,bcc80b71) -,S(732181a8,e2bc5953,923e6c3d,d960e9b7,525b7b95,e5906997,6fe79156,1782756e,2516c6b3,5592eb0a,42ba193c,bae98ab,e3c42d96,148f1d84,edac621a,722e4823) -,S(b8e8942d,926e38fd,f338496a,c2ef6fca,49a7ae3d,f76eb15d,8d570111,e502664b,7990d56e,7dea588e,4d670ba2,2031e6c7,97248641,69e51d77,f792f5ed,befaf8eb) -,S(144e88f6,3e73abff,72cac11e,7ddccf79,19e744e6,278941ae,18d1b797,e098e4e5,63cdbf3,5df3c655,c58197f,ea54633d,158705cf,7dc2eb3b,4e09f83c,3021837c) -,S(9436e3dc,489ecd8e,2d16a739,c9c73e3d,60e5bc93,68157039,75b8efbd,5c3a9081,1460531f,50cb6ebf,d1aa7806,ea84e7f7,8e8d76b2,b3a66d5e,3a0bf60,39a7e59c) -#endif -#if WINDOW_G > 7 -,S(9d3c2561,7a56d10b,46d9b01a,1710d193,e840e005,df669e76,1936c275,20890db9,6bbdc0bc,4c4ae9bc,c2dfee9b,82da9b94,1f89ffcd,e8af2aca,4467ce3,78521ea3) -,S(29f98e50,f51b7f8b,e18c6ae0,b453c4f2,d0aca5a8,b0e61d2d,dda8506,3fdb76c8,daf3bcdc,ae8e031c,73eb8b21,14058063,58a6ec30,ad379186,df80e3c7,f0e5d28f) -,S(d67d30c2,c71daa36,1805e31,1dd6046e,17a89752,94d76e1a,538af074,4dc22c94,48b9b0e7,12c807b0,b92e690a,a2e068cc,e87ebbbe,aaf4bd96,9c1114bb,a54f670c) -,S(f22c2ba8,8ce9c2e4,b772c9b7,6d03a017,59aa7b9,97a78334,83566027,2fc81649,6aa9e710,f190be16,243a4e0f,1570270a,2d92dca9,8cf99a3,cbc06fdd,f9b7028f) -,S(c5e718d,6b94c83,e52533c9,ef3234f,36b722ed,cfc074a5,eff30969,9ac5f894,24961051,ccfc6619,dd64e810,fa9c504b,f7f8ce9e,cc445d7e,642b3166,eeef436) -,S(26a8bcaa,c836eb7d,57618999,ef87ee4e,c291dc8b,333554a2,c1f66f73,7944d611,c20051ba,7236663,ace2da29,c1e0763c,e57192d0,e199e7a6,c69cc65d,bbbcecc9) -,S(388e3570,fb7b1545,9bf01ba1,7a6496d5,6bcf65e1,764e7aa,2c083346,2dfa098c,2d4e0d22,a2eb0ff0,545561e5,ae344be6,99120d12,45db6bde,a9500f5f,a07be798) -,S(68189bab,b5a0783e,23227efa,4eab2c6e,da2d1c,2ea57fca,7a7f8f72,15250709,bd30bd83,3694d3fa,a14954f6,251445f8,3e42d517,30d30855,a0eb834d,3c7ae856) -,S(642e0823,bb347795,967b7aa9,418a25,ea6ff683,fd7b3d42,b88d90d1,292190ab,db73dea7,86ec052f,e3674892,639daf39,286b4690,63b68903,210639c7,f3b4000f) -,S(9ab6ea81,e5bf5505,751addea,5896afab,7f4eff2f,d3986027,f916835c,64924afa,38c06aa7,4870a5e7,2ff29efc,bce4b3e7,dd951c9b,29966f2b,47d007ac,7629bb6c) -,S(b09805ae,e567f69c,71a98248,e89e64f9,e059e015,bde01a62,dd18158e,e94a8ee7,62aea16a,7ec912ef,cc5382eb,6d220ac3,dea885a8,e3da12c,8147b28e,1983d221) -,S(3d632a5b,636ed5a3,4a58bfbc,9831691a,91d6b5f0,975bfb5a,82b4c1bc,107e6e5,577a449e,75bf16d9,2eb6ba0f,9cb4d496,7a7ee09c,f1605aef,682cfa31,cf395a1c) -,S(6b821bf0,f70d5ff2,ceedb69d,d96ac8bb,b51e3635,3a36d50a,b1c1a697,40cef707,5212ce11,993fc120,88028674,5cddea94,6371b4,dfa2f47a,6d83b789,c6d12e5d) -,S(bf294951,4496fe0b,8527740b,5cd9394e,dc33b330,c91d996c,789db854,45728b23,790aede5,da35ce7a,343f745c,410de38f,4c53bc2a,bb41bbae,c13272b1,e912782c) -,S(a55354c3,82bf968a,16668267,c4498946,4906f69b,114f6f06,742b6035,1d75ec80,2809bddc,45661a5f,28b31967,6cdfb5b1,9dd6d296,d1828c88,179a630c,ca5962e8) -,S(fc015036,abcd8311,bbfa1574,ffb4980f,b893f8af,84f519f4,5a6fa344,2649a693,d0f6a278,1946e04b,385cd004,29acd3f6,f5542aca,3e7c789,657f676b,f19db819) -,S(6164410d,9f81f352,272a799f,b4afbe24,59caea6c,511fa4ea,b7578980,d9a7aae,92bc1480,ba19fcd,3cbee69c,95b9396f,4982fff5,d4e7dac0,abec7153,ee5a7966) -,S(ef816535,8de9d737,728f9a9b,3182b4f5,6e25917d,1ec05fc6,faa0fc85,170b5f2d,dc372426,403ca9c4,50649df8,8b6fd32d,f1721dc,cb1c7d7e,155c83ea,747ec595) -,S(428c34b9,89a436dd,dc704e68,170d2c40,178c5646,841eb2e2,642c0a48,8987a8ed,b1f24158,251c4646,ca04dc3e,64369634,3836f97e,71945f4f,51237abd,3aeebe06) -,S(6eb61782,f909157b,415e6243,7bebbd6a,5f19da73,7eda64a5,5acfe206,65417a9e,4fe7c546,baedf2b1,6c92f168,f99c42f6,af03edee,290ecc39,4c4efff,e8577b72) -,S(992e0af1,466d4fec,5ef83009,98ce31df,cb6f9573,d14c1646,e4371c62,a376fa4b,d0e3da69,1e4396b2,eb01e3a9,964365,50d000e6,31d79ae3,871690d5,29f9e825) -,S(fedb564b,adc70078,f20f31d1,12496934,513e9903,8cf5b9c3,1084383,5721d11,1a8e2a49,57e8420c,f2d5d97d,657f1602,ba26ae87,d5408b2f,a9448def,38157a39) -,S(f3f2068a,4dd89d18,1247088d,3c424916,3e683226,6274b575,e54430d0,73b24bd,f2aabd19,a7f462,1426ab1e,e0aa7e33,12381c5f,e1f1cf0e,75c1a7f7,7ba2bfa8) -,S(32b9225e,4217a359,8de4e7c1,476a8581,5b6aa458,d93dae02,b3d30772,3ca13680,7466e804,26856340,12985683,dd071e97,53246214,733808a3,96f35d0e,5a133802) -,S(85008a87,385ed6b0,4ff89979,2eb592f9,ee6c6b93,fa24dc7f,c6299b9f,dae64a8a,1f279e2b,8a5b0576,fb9569f6,c0825876,84b5b38f,a250e362,2ae6e284,a504a2df) -,S(4dac7833,ebbeab0b,ec8edac7,cfc49bfd,b835362,f0130e9,e44452f6,a82effd4,fc9d1970,f230aa68,6114ada5,7b4237dd,133dc3b5,db8ec1f0,ccd09aa,23c740a) -,S(9b755881,45a65d54,19b40226,e535df5b,4b44de41,1b93d71,31f3102,d56dbeeb,d0324171,d6937b7,c9b38290,7dbba3b5,c1516061,59e7ce1f,a1ed9d11,e089a02d) -,S(1bd6ceb9,2592a7d7,a66e6e8b,1b645db5,98b525ca,461dc4bd,b583ed9a,cbbc8bdd,9a59de87,84a98bea,48b7abb1,a5b7055,5a1c4ce5,551cde4e,7b790ac4,9a29944c) -,S(25a8b2b9,3b360941,6525b08a,7fe786e9,6b3a3c7d,8b444637,268f5355,bd5b56ee,3c58ccf7,5734687f,dbd027e6,3ec6c550,45f131ae,df71a40a,c45e4e8b,965f22ec) -,S(244b2833,27c33efb,221a5767,15225d6a,bf5a1caa,8da543c0,d88b21e5,17ed9f5f,220036ac,e48d8953,5aecec92,a29f5012,37f83ce6,44380db,c229f0bf,c1f53d7d) -,S(6f97ac0f,27b87905,6b442d13,e566978e,91f0cc1d,d6ac1e64,e9764a35,325dd1b7,83c6e70c,fac6c707,226ce1cc,691b38a0,7e937f5a,5f2d9c81,4dd0d3ff,9f433d32) -,S(72c5d60f,eb014e2d,ba8265ca,d454f261,2d6abcd4,b2236bad,c94c4801,561dce1f,e3119a19,7ef91963,b3b28216,3c5d3acb,97b281b6,d246cbf0,690b40da,63978fe2) -#endif -#if WINDOW_G > 8 -,S(a96d2da0,1b10186,6998659d,f441a1b0,2af32b94,aae8c6ea,707d9ed0,d5f33825,660d7d83,5da5235,9f7cfd41,28c370aa,5659ea71,16a91690,6c0e8108,a513f9f) -,S(2cce6f63,4d815ecc,1981d200,87616677,d906aa27,990c4875,17314dc5,5be3c4fa,615210dd,bd599e91,1b6f997a,fd05475,b33cb274,c9ecb6e5,d3c23323,beba4b50) -,S(992b0084,525dd399,d98602d9,8b8d53b2,4558fafc,758a2f46,60e89bd6,a645f0c4,83ca98d2,26545a29,8c45f40b,11420602,f5a5c70e,595eea57,2da64d61,a4e2f98d) -,S(434efb45,3089619f,cc761ee4,3fd4b77d,c6b0c69e,b45eb88e,44ef766e,9beb7357,3dbb0d6d,1c0b92e,5965586d,236c0be9,26967ac8,830b9bd0,1e9efc2,2a9291ea) -,S(a2179ad,2c683306,a2e4735,93efe304,f0dbf589,c4dc2b88,4bddc5c7,e3fbc156,ee4539f8,ab980176,a18e6dfa,bdb609d2,88a2d223,86dcb20,19207afa,f6033c1f) -,S(3934081e,d3e1e147,aa52bb40,9221ef6,a445f22a,66718f14,6d63907a,ef05a2e1,bc370656,31391b7a,209e79d4,9f1e959b,d3a9fefe,752c6062,14fab290,a7b5b3c7) -,S(35bc24e1,59a2b939,438354,6cc4255f,f1f3f7e2,105293db,39688e07,df95d8ef,dee1fc70,a9698da,f7abeb5c,56724f8,e87e0cd3,8849edfa,246ed0a8,9223ae15) -,S(f5d1e75c,251fb473,8552a0ee,f05d8e65,63aa14e1,bcae5b48,bc7e5258,b948127d,e260c1bc,7044f058,8f409134,d298528b,e7d586f4,bf7b6fe,92d212a8,6f7170fe) -,S(ee0a76d3,6fed282f,a1170dd,6acb7743,f9617bb3,60350f54,d12da1cc,7eb121c,f8cfc2db,eba6960f,e6135ef,ff9e10ca,4e56c458,4b42b516,6dbf7af1,420ba5b1) -,S(9e3b87cf,78927664,15cab377,f1774d14,4d1879f6,16da5676,f94790d1,9ca689d8,f8f34522,da3ca2ac,b273b0c2,b1b1f26a,7a9c2d96,b4547482,266a8e6d,bab3b577) -,S(e26f256f,d08942c0,3c85b89e,e66b8b50,12f409c7,4f625152,86e5b310,eb4868f0,bab3c4d9,6fea49fa,6d08c656,23c9b127,3552c23f,3c4f12f2,1bbe8bfb,56f210f9) -,S(8ac74046,a5d38398,d14b6763,4f07abc5,a3f5c852,ea8c421c,f0858980,11da6c2,d20ca793,f56e3198,854f5916,35402c2,4a71af95,c84288e,1495d324,7229b3dc) -,S(5b00e095,634694cc,93d531a8,6e81d29e,753928bf,b2c83a83,ac677a92,55932bd0,8d2f267a,8071c48c,616daf18,d587e,42882b33,748032d6,4bc3efd6,60a99656) -,S(162190c4,80c5d7b,ab1ae4ba,7b2a6611,546ffb9a,b4e9ea87,2c0357f8,9e11f0b1,db5e2104,12448a9c,e586d7a3,13bdcc6d,bb84192e,98c5d9d8,79693030,92423525) -,S(f6a84421,b4b383e8,87f8520,e06017db,476774dc,9aff636c,f26a676c,85b145b1,504c71a9,596770ed,7a2da8,2e8fe1ee,93717215,bf88e0a8,ed74a80,4037a3b3) -,S(1f02d142,f0b5d3d8,b3f8937d,a49f908d,83e5919e,55c9c134,55a759a9,932dd6e5,e6a5cb33,8ed36df7,50ec2eae,5db7c9ff,fbc9035f,48ae0348,fb3882da,39863e65) -,S(61f4d96b,c326a1fe,a2ae38c3,73484a56,68e29bf5,12d77a04,34a62278,1d78899f,651ef738,62005ac7,64f97021,6180c25e,2172724b,375e6b38,b3a37ad2,d7b4aab8) -,S(ba7d5c0d,623c5e79,8088a71f,8d2916e0,7c7ebe2b,1afa19c1,9c917cae,31c11616,da409f40,d7e3f6c,78655153,fb35595,a1ec37e7,e66c8958,ce45b07d,bd5f5a51) -,S(8b90a590,eacb977c,6e6a68ee,6dbc3e19,fe5a92a6,9abc43c3,bb16f9d1,925bdb09,a5cf5f42,ef655d59,ae734e1,f746a752,4d01ef75,d829b9a9,2a035180,fb5df718) -,S(87f35227,21914cfd,ce8294a3,cb5ae171,f0d994ff,f55b25b7,1c9e9aac,dff4fe4c,cc71d1af,530bc5e1,eae7c1ef,b9a91335,f26b283f,222a3552,dda24c28,64babb2f) -,S(aeea4d36,ba405159,bf0ffe8a,5530f1f3,83d5509f,187ef58b,6c1eee4a,cb77a15d,db563dea,e7403df8,7d3031c2,48aaa28d,96958f7d,ce36b3f7,8d55607a,60d3ac1a) -,S(300fe98d,3996eb9d,57c6f1ef,8058d4c,d8dda436,5774edb6,2a338a59,afcc7111,d148a017,8fdda40c,f937913c,143b76fd,d2e6e226,d27225e3,a49658b2,38c40e77) -,S(c700af5e,22cd146e,839095a1,f6743e4f,d01e9c1b,76d4c73a,a5005f42,99c19fdb,3fe00181,b1f01c27,27ab1fc6,bb6ea569,d4a3092,c2d511d2,8b5546aa,194b32c0) -,S(d03d08e1,17b94138,1aa147af,38448539,94228f75,f96bb4a5,941c3748,cf50bc60,5b119ffd,2785bcc5,2e0bfbfd,c541da8d,f47dd076,e91440fa,10e071b3,a896e31d) -,S(6c6710fa,17a520b8,56d7fadb,6af81a5f,ea9c983e,c94cf832,b395da5f,c22bd361,db4efd26,36e281ea,419964f3,c0897b05,b036a408,25ed4ad6,4fba393c,f2804941) -,S(d7b5c239,9df47a16,6b6cb900,d08a5d9a,5ea3bfe9,94f861d9,b46f3fbd,a3d91bbb,ed791f4e,4ab1c25e,9c83494d,794ffe1f,a3c8a065,29c0b710,cffd597d,64efe8ba) -,S(90f699ab,8f728152,e2deb8dc,ceaaa3ee,53ff2f23,2341a952,4aba9e8e,50f66c06,8bd0c3a7,7f5312bb,9d46d80e,c36921f8,561558ce,6e63c08e,641c82c9,fefce91d) -,S(4d0eae3e,3d7adc34,c91eaead,6a16f569,37557dce,2b68744a,bb9ae71a,8dfb65cc,816b0806,a9508731,ba99a685,142aa52e,6e874c99,5096a53,52c6e2f2,1fa3de5a) -,S(46cd9edd,ec318498,dfb4f815,3315185d,689a2399,8e06b1d0,2438f7c9,b2f7de62,3b5bc1a3,d5fd7874,8c964a8b,b813388b,e0d5d168,1247d008,10a846fa,561f29bc) -,S(4aac80e,3f6eaab7,1c576297,b4552e40,653748fe,21a580ae,bce4eb83,2ff730b,3d42a00d,8014f46a,80fe2dd5,bac6a046,40d331a9,4f1de050,9e435398,6c8c7954) -,S(59bea661,b73d9c09,131e4573,199937a,e03e96f6,2ecbc637,4bb681a5,582a4114,31a20be8,ee8a2c2e,81d062e7,8e891504,d9f2639a,bd5db5c1,30be3d2c,b1afa47d) -,S(7fe9065,88b2ee92,2b19acd3,fec7a4de,9ee089a4,a4e1c338,5e293567,90ca6037,dfb45d90,c5f43eeb,1f5eb326,20763ff4,2659b763,e7ec72a7,c69e9369,35e5c128) -,S(db390f91,32277889,784b5e4a,cf8f2fd1,f3a5fc47,f2c8262f,19dc9518,95322157,4364955b,241c831f,94fd7d4,da63db19,2aaeb5c0,ade82dc8,d5d61cac,d690bbad) -,S(34dd0266,e5fc19ac,7daa9e61,5ae8f78c,985732a6,1c53c29,e6e5d407,7391ebc8,c2d6b6d8,e73fe00,e6013b1d,2c2b48bc,77a5db6b,45232ddb,6611ea1f,c5dd797b) -,S(eea7f72b,7e31608d,d3dfcfbe,16e2ef95,5e6c7ec5,328f84db,336e3df1,9d1772ab,9662c8f1,ccdea4c3,48ea6d94,739aa747,17219556,c6be9b8,8af0d30d,514004bb) -,S(c6af087a,f1b10eb3,93de412d,de856129,9376d264,36d907fc,10d3e7a3,88c391f2,ba99d62e,31856457,8ad8847a,9cfeaba5,e5ff9824,2c614959,eeeb4ae7,50825144) -,S(eae34735,6c715740,ab73d034,bcb43f5a,aff37fbf,50d35518,1364c999,feccefc7,b9386c75,da8bf645,cd6f15d8,4944f74b,9685256d,b61fda98,79fe6639,92fe4703) -,S(4a548c25,f4d8f54,4f9a27e,64e49626,41b68ae3,1d90461,65c24ff7,fb40438f,ae9f2c85,bd608cf6,ef5e40c6,7e29a63d,4c274215,c2a0d578,38252f28,196f6d10) -,S(61925679,dd6545a8,ea19743d,7cb3c0bf,453318d9,e180da53,f43af2b0,ecf744af,a0682d84,d7215372,e9ec062c,a3e4aa1f,47fc551d,44e3d1a1,7260a44f,2bcb184d) -,S(e1db5e86,9574ab76,d4fa260d,2425ef62,50267ab8,52ff04fe,25f0150,9137ea2a,c8eaf421,9fd5f7a3,6c1a99a1,d0c61250,836e204b,fb496774,83f43c81,511905a8) -,S(3062cbca,73923842,2a0ab862,a1fd84f0,38e63691,cfc204a7,d2f9d263,d248c7f1,8f112e57,e3f2970,dce89eee,1e184310,721a85f1,cc9feb2c,f55c047f,dd9670cb) -,S(67c393cc,aa9736fc,eec7a861,eb53f953,9da74ff2,97764f4e,4e814004,4da4f739,93d329d0,9a165fe2,2f8009d5,ad59b524,33ac24d5,46c7d394,2d147c4d,49853203) -,S(c67471f2,36cf2187,ee5a5619,d581cc7d,ac5bc5b1,e8bb728,f943084f,e899bf5e,75c90c9c,787b318d,943c3247,74cbbcc8,3a533f37,fb684aea,62fe6848,8de2c513) -,S(d5015fef,d5938dd9,2133d7a4,25aaac5,12143acc,6547070,1827e98a,e4ed1b52,44305616,a02236f1,5c37c0d6,51d845dc,e9966860,b798f79f,4006c25d,7cf03d6b) -,S(aebcbf65,aaa89615,cb48ed56,4002ed9a,243ca309,1cf503b7,3c1929ce,8164f2d2,4fc1f25d,1a30ee2b,4220305b,a9c88e86,a6ee7f55,55399ee5,35e7d37f,e4b3f019) -,S(15cb1617,1727deef,49ad6821,932a39d1,bb8f980b,b5370d81,5ef00ff,ebb30e43,64ad8c82,87fc053f,ee35c1b9,9734b34d,2dfff86b,490ead93,b1fe7d2b,f80ebd7a) -,S(d404209e,8530d674,9bb88a5,525211a1,19fb2523,63e2698,6bd03080,4c49c123,3763fd68,fdb85d19,e8506275,3b5a327c,46ef87be,8a3432c5,62bcc622,40a7a128) -,S(f3abf8cf,c232849,58e330c2,fc327ac4,d40b4497,f422aa4e,d42e9381,9bffdd96,50861f05,d831327c,3e907643,2d7a7621,d1dfe9ec,7ccf2061,cc720e9a,7d5b0d5d) -,S(78a32893,2ee9dbfb,3f84755a,651b9d23,5cf92b46,c3e4bb4e,57b7ff6f,7c874dea,925b783a,966721f4,6eaccd87,495eab7d,b3c36eb2,92c1a473,b4617f6b,9ac85895) -,S(8165210f,5d146f8a,1ac1ed91,a7bb678d,1b7d15e4,3ed55e8d,f6503209,a750cd4a,fe390d3a,19e22bdc,cbd45875,e396c713,85954166,a1edb63a,384b8587,915d260d) -,S(75269de8,6c2f3d34,cdf17dd6,f3efa198,ba73431f,cf0072f3,633ca57f,7dfe3f09,b162a65f,d19927ec,4446e3db,d5ee8850,f463f39f,1df1a0b1,f5ed153e,704805bd) -,S(5e36ce8f,b393949e,5b9c4e10,44fb2ff7,c520a7b7,a9016b38,9544e512,427145b0,7c40e718,292f96a4,1d9822ce,d54aea90,22074c5c,c82ba4e,7d39a4e0,7811614c) -,S(c8cc7129,fdebbfc6,c0576edc,6ac983e5,c249d360,76da7d25,b05c0b6b,16632746,48a8cce3,a77e4498,76d1a332,c539feba,2653fbaf,d4f75e68,e4674d78,4c716fb1) -,S(9fe1db36,f1ee3e6d,3924d2a9,ae3ddcaf,fa85798b,7383a1dd,2d6c0c14,ea46973f,1d35b6a8,607045c0,95ed9658,80212b63,43dc55ec,beb3223e,7c2e76ce,2c74f6d2) -,S(4ca8ab8a,3d45748e,6e19e02d,dc351279,e23648db,d26d2465,7c9713f5,bc8ecda2,8a5866ad,9bb7db92,273c9f23,c0876c95,13b8a68d,bb20c5cf,164a9a39,4e3e73da) -,S(c8d0150,e4a989ec,5cdbc724,21b1e29f,f1f30818,1d8117b1,3d376f58,b72060c0,5c5880a4,c5a73a4a,1ae42a9d,f0b20032,7ac4a732,cb26e717,49e63365,5082ebd1) -,S(3d61557b,b4b9fde6,49fe1b7c,981c9883,9e368444,f130bfea,fc1e1a0c,12f2aa31,933167ff,62cd840b,3a960c90,e6b1c37e,1e233695,318ea286,71c87992,de5b56f9) -,S(67569f9f,fd44ca09,5b478dbb,85c3ed1f,feaadaed,cb624552,ccfaf169,24e69e2a,62bb2948,230fbd2c,aa941288,7adfb24b,d16619de,af0fc102,feb1b26d,67eb7fcc) -,S(6313d13e,debf1401,eb7d279,2c66daa8,6e3075d0,3cf0daf7,f3b753e,7372fbc2,44621230,50eb1245,86975455,63e06e2f,2839f874,beaff9c2,f65e26ad,d3573ef3) -,S(6f8ec9e7,fbbe6e8c,d0e3085b,47c6cb2b,88529f2,15f13195,5e2fde24,4dd23968,1fb61e14,523b3fae,b543b215,dc46eeeb,23e1950a,8301c78d,c510c76f,ed36cd79) -,S(56613dac,3c5aa1ac,bd9a0ec2,f839b4c3,36f0ae58,e0e02244,7bec0546,710b7f6c,247263ab,86c398f9,3b23319,4434af8b,530908bd,dd7f716c,f7b73aa9,8eca79e8) -,S(c9de15e7,b4147219,137e6e57,c5a7ddd6,17e91ab0,6859dda0,41eb3c21,87aee08c,c7178ea5,cfa056d0,dfd11c87,715591cc,40cc5db1,f5e4b70f,d8ffbfc4,3f8b0009) -,S(7590a4a,627d5e90,e42a4b0f,6be6497a,f906182d,d2dddc48,a8b6bbfd,f56c0504,d611e21a,b5498760,5c97e878,baa464bc,cc5bd875,353b69f8,1f93ce2a,a6c38587) -,S(94b1da0f,b310e056,db0dff72,81db3362,1fcc555d,bf3c973b,76097908,7fe19d6a,8318893d,d5b41a56,33a2ab4,ae4b953c,45c42e9c,8f2fd159,85286de3,fd4fc217) -#endif -#if WINDOW_G > 9 -,S(b5af4299,bcdacef1,e07d081,daec2cfa,d6f8f821,38e151a5,f20e6d52,84c9a6cb,c0984407,8a7db82d,f572987e,b137dc09,c8cf65fd,aedcb20,43b2479b,ab95448d) -,S(5f49ad43,70744587,3980a153,c851829b,f8ef6141,9889bb0c,3c476847,6939c3e3,5c40d385,20f56c3d,ba08ae1,b40fc24a,2ae25c94,45cae0f7,d01d1800,747e04eb) -,S(f6bb067f,88ccc11c,64e30d1a,e6893942,16bea3bf,26ec9c64,5cde1b9e,487da385,315a476d,7268978c,d89d4ec8,adde4a83,28dbfdd9,f2bf44fe,ad4ed721,78288f55) -,S(7b47cede,c02b19e0,94daea0e,ec000455,52690b49,44b3f10,beeed2bf,f9df6950,1bcda5f4,9beedec9,6ebac5a7,957918af,53b7ccd8,c211330,280ed93b,e0efe9a6) -,S(ba69d7f3,82d56d9,eb65e1ab,2d70f52d,18223621,c0029035,a78fd660,9940876d,5f44a2fd,56d5289c,f36bdb9,50ee2538,1d1cf935,ae1aec76,84b6d11f,975d393d) -,S(a3b70894,d226c195,223713bf,330ba39,fe7ec35f,9743347d,1d3dfdb9,7bd929ff,5d0cbdf,42755aa0,355ad2e1,ab39479,495edf2c,20bb0aa5,93cc04cd,56ae6135) -,S(c756e23e,bb2d81fd,91fe73b5,20eb3bfe,5ae602b3,448cf84f,e8da37d,d1c804e5,89f4b6fa,edf86b9b,ca9f52b2,9864a982,5a4faba9,d4fb35f8,98511210,34df49ff) -,S(36327c35,6fab94ab,f791c234,1c39049c,65410e9c,6cdfaa00,d172ee84,3671822c,fe3588a4,698c8d35,f0e01f04,e94f7039,eb745631,8c25927a,be7d061f,d3ed4c6d) -,S(3b75bfbe,8e372311,f46ecf6f,c5eb2af4,b66051b1,874b0c32,1189e106,37dd21bb,b9144a33,e3c3339a,4595e248,87940b4e,2e42a095,d7d1bc2a,ea50aa29,5a879908) -,S(44a61f10,57b4e88a,c55ed72,1f8f4477,5f0272bd,379a97b4,d92a7f75,f0d3c5e2,e870ea65,80340464,9716ec1f,5b79392,18162306,6dc14086,111de144,82d80141) -,S(11ae02f7,663c0a,24c6fe5,ce9206ed,1ebed2e6,ca294acb,74c9a227,97fefd,635a1b87,a262fb30,5008737a,e70422cd,a4e35766,940e424b,d697d28c,dfd6a36f) -,S(c751310a,dfb25d14,2e6ab1b0,ab31b37c,8e987af2,105d5981,69085ca,3e142f5c,a4630dd8,ed2717a9,f10485a4,be685c5a,ccca851d,4bcc1886,4df943ba,ee821014) -,S(fff4d7c6,4009f39c,41757b17,3eb2536c,a639b72b,e15af7f,790bddb7,efefe46a,694a798e,ffe22d1,1030697a,292a4bb1,4c110d6b,dad7edc6,e8976450,ce5080e5) -,S(7d76ea39,c13c9f46,e931e8bc,1cd43707,932b1a,31254d18,c06c8ce9,c3f90534,bc14b2ba,8f0a3d8f,34c7cf7c,3458c916,4cee438b,39a5a6d4,d2a1c9fe,8be415bb) -,S(b6efcad2,ca6ae4f3,6f080707,530aaaad,625fda5e,825f77e8,a6730e95,5e07ad39,4868d8ef,8a56d327,3f6f4a3,23ea6ad6,4694301a,1f6405f0,a421939,bdb1c765) -,S(1a04b12a,a889c4a6,d37f9050,e75406d3,48e38faa,c0d2ab4a,e30caa6e,3633a32e,f43a0c8f,fad38d90,6c817dca,3e7ea09e,21e1c801,7af86966,c246ebc8,dc75911d) -,S(adaeb0fe,9b345190,4e878b12,6c8edddf,b70e2500,5a4d6a6c,531aad51,83209b7e,2b26b16d,dd4d29a7,8cc6b4e,198e6ede,b1c59def,c6793173,f33cb039,d37522ad) -,S(4e4ca02,3931f3fc,b512121d,2d632764,d97fa125,8460d0d1,9a94eb88,2c6e0679,ef90eecd,3704a6c9,454c6860,928eb332,cc917b17,f2594348,515822d1,84537467) -,S(a1f3c279,df69c13a,711b5ee4,139f603b,5654ecac,adc02a22,a7c2087,c11e2971,57249794,54cb78dd,7ef69916,5efe2326,e8aafad7,a8a923b2,252523ad,b6a16b2d) -,S(aac76f81,488668e6,f4b0c911,bc9675ff,c19424c8,6a6903c4,f4b13e0c,e798c7a5,24ae16df,dd6c7d6c,1391df3f,73609bc2,c3759536,eb277189,588a72d1,84dd2978) -,S(70e94171,e59622f0,de360166,6498e6c9,ddce496,a15e30a2,a5bdb701,d0034769,d6d7c0a7,75a9cbef,2b84d4e8,200f92a,446111bb,cf46a57d,5e244f1a,1103b757) -,S(ca17e5e7,11d44492,496fa849,c6ab1c47,3426706b,5b8282b6,f288e096,8ec78890,b3ddd632,2ce577b8,ddb9f501,e17d32cc,e6c58fee,4e283410,5e32f3e8,8bce2c2e) -,S(1a16a58d,8d70fde8,6ac0700f,3a43ab9c,255ec001,8d5fe571,7ec6324a,2faa62e8,f2cb2eba,65aff0a3,dd7bc137,257c1d30,dc2eb6f3,7a3897e1,16c0eb1d,1a710c27) -,S(8f2dde65,b4ddf10,c29c6bbf,5ab2ac11,2dd3357a,e3e5f01e,98190e32,94b9d4f2,e06b8cf7,e5a736d5,4e954bd,8591f7cd,79df335b,d3279f5d,80493fe4,df4c6afb) -,S(3314b553,f8213e7c,80d4562e,cdb3564,ba1d7285,6c88d8c5,a3adda90,4950162,33e83c5e,e3f7c550,f94a7434,e3cad51e,b4dab462,13acc24,fc4aa1f9,fc43532d) -,S(7c107ef4,65ac0c2f,fc5b11a3,348a7cc3,fa589554,ee2b6606,2af3c5ba,25304000,6b5bcf12,2e8a0705,d067fe78,e56d365e,89b5a979,c23f124b,508e63ee,975702c5) -,S(e918a829,325adf67,511e257e,e5596d08,19be4605,36b20cb9,7b76a54a,5be4f8b3,1a92f0a0,b46152c3,e1ba8f0d,12119c15,b70af0ef,3ff0ebf,a9dc9207,cf2fa8ae) -,S(8770da03,d4f3a4b9,e92dd2e3,be309c81,c346c97d,2cea15d1,e3fc94cf,41b9b079,d025430f,dc633d57,18d372fe,64f57fac,53f96461,1fb5005a,10ce842d,ab123c03) -,S(c6b4ad3f,ae2b2557,b126a57f,6bbc039d,a6589f70,c6283ea1,7314aad5,acd8b22b,e8523dcd,2c1c3412,35df278d,e49c38df,85f2888e,cf3c76fb,46e1affa,d8d29bfe) -,S(9aced948,6ffbf984,373b1e91,ff871619,4622741b,1e1ab968,9c88cb70,37a86e14,d7a7eb1f,1b4c31df,ff43cc32,1949c1d3,16e1e7ec,a6a852cd,e8e7f592,8b352d9) -,S(af51536f,fccbdab4,c4f4015b,1e8aca69,b08bf055,e038b22b,87c54f5f,1b9007f3,b6bb0b4c,95c07ecf,49ffa85b,abb1d308,cbe813b7,703a27ef,cf849e,47130f7b) -,S(ec5306df,3ea0abb5,6fc45a09,25c1c925,56e02ffa,18238c3e,5bb2ee53,11823ce2,c950cdb6,720f65f4,18065352,43c90bd8,9457f4bf,d941c9f6,89812840,2dee8b99) -,S(293b1ca5,be127bc6,1a397ecd,59164363,587f468c,81de4d87,6c5d9bae,e72d90a0,4821030f,238e9f05,e93d81d9,1764863d,443a524,3d18e61b,ae26f74d,ba35d821) -,S(ebe54b7d,99876ab6,b2951f0e,e68bfc10,16877142,22ef83c1,2561f486,b4865488,2a1d651c,caf8802f,fa699d91,b8242f51,58d84fa0,d481bc47,9246eeb8,6d381c07) -,S(88f77523,3ab0d69b,ed220109,b29d0d99,33ac8325,445d19df,d38d9c69,3464acdc,8f915122,fbd95ef5,31ea2cb1,aec6bebf,8e059059,459c0d5b,79a282cb,cb276702) -,S(1d84753d,e7210dd8,9db6cfa0,8ebe9797,c7fa40b9,6e94439f,b8117359,a2b3bb01,f7360b5a,ba53a4d8,7440b6d6,f540c485,2e889c33,9f34260d,abfa7861,f1f41ad6) -,S(19e69df5,176f82c1,cf1ae032,cb388ce3,36f82a3e,5e741e1c,27fcefb5,311d4b2f,c401f4fe,c9ba53be,be175dc8,cc1d17b3,9d9f7af,5bb496e0,b95bba6,cbd5c143) -,S(73189e02,c1f125ff,df1a9399,57f29aa5,19b04f5e,42adf729,53d354cc,aee3f2c9,52b8e88f,1c6e7cf8,621d21b0,1e406038,d901de1c,4101d424,1009c01,a537f704) -,S(c5ebe082,8ff1a8bf,52f8956c,b747f1d3,278fd2b0,a5ae7669,1c256e9,2887a74f,ce58cb9,62e74b98,1ab97dc9,2d736b5e,c506e51d,6c09b382,3eff1cdb,cd259860) -,S(783c1621,f7990e01,4296feed,3bc883d5,1a780867,c83b9166,435a0562,4982da76,370b3e2,c9a189c6,9c565c3e,8eb8019d,f5224574,bd5ffbc6,22f563e1,8a36da30) -,S(555e7e80,ccc6a46,1724cbd6,4a53721d,fad66fcb,2c71d579,4d799f6f,fa2b3305,67bbf165,d39d7042,18f5ed31,28fe6dd6,db9b4809,b3270eb,63bda603,f44e9e41) -,S(40c49a26,ab1cd46c,f1e8467e,242c6b1b,faa40a4,cacdd50a,4b0213a5,40243471,16950b00,5002622f,e0b9fdb4,c34224c3,ad55bf30,67f4e96b,dc2813f6,2fdadf86) -,S(eb6b3be5,db098d18,9c810b9f,5593c746,47306226,d77e162,7c8b62f6,d7935298,3d295584,3f356f5c,1f990231,701cedc8,c84e9671,44be22fb,9bd74f0e,15c5bc8) -,S(177218a4,2b55c169,1ca0a073,4d061b53,a0683536,9a04fca9,3f670ce,5eb26091,9611661a,a8a3bc73,7717f243,e5e8b97a,57e0e72,759f0f4e,cedb690c,b3a5fa42) -,S(841a8fa2,f3bc5f8a,7d028c00,127c267a,ea0c3762,8b07ebe3,7f883a67,8fd2a680,579bf37d,b2fd1f77,a0057712,88dbbdcc,526938c,4f9ba89d,9a42d4f3,452cf1b0) -,S(b01ef554,3a377f1e,c801421d,a399c53c,3585789c,d7e51691,32250a61,6edea82d,28f30ce9,7e29b2f1,3af626a0,7a37f14,82e119d1,e66389eb,9620200b,25a90265) -,S(b93e014e,8e3cc643,17ee70d6,ef8c9918,ba344e7c,b38a9a6,2591b0ac,4f38904,129c185,5bdfd10c,6bf152e1,2ff89b4,d0b368ed,c0ae01f7,2b29fc95,240ac3d3) -,S(e0f426f2,43c50d9a,ff80a1dd,26d63189,a00601c6,8ac81373,5fbf548,7acd522,96d883e0,951adc5e,304bd848,ccf39c2a,1c19382a,eb24ad1e,1430d705,deb749fc) -,S(e11e9c74,40e897ad,2870adda,63b9ec04,d5379f14,b3bbbdf2,147ea9b7,9c73233c,49d6e54b,29197532,3f5a9df0,3e22e359,e125e34d,d9f3d6c5,cb9f0a20,6dc1f019) -,S(91ad584b,c5ef145,3b796eca,20027cc2,ae38ee70,9ac4591c,79cf67a7,a96b2c2b,d815a213,a620c531,11f79e5d,b5d9c3c5,565dfd97,ece841e2,3e9c1ca7,530bac2a) -,S(3e725392,f4fa34f2,7413785,cb322f35,1032971c,2303f3da,bfe40461,4299f8d2,8e323a51,5addeed5,f3548217,6907efa5,4e0c1d57,7895839e,42223e5,7708ae85) -,S(5e87bec2,1a589ab,483c00ac,fa863f35,91d9119b,9a0239bc,ed4f5790,45a98160,a88a3b84,33c75c1f,9eaf3c15,9fc39a6e,33625f1c,d0cd7263,3a825023,f2e7d47b) -,S(c2e08613,2cb93b35,749cb652,44e99909,da18260e,d252cf32,489fa1c8,d268a0ed,d3f2e3ad,1f16365d,d47038d6,854e0773,28e02e64,d05a4764,4ed0d82a,8c8a5761) -,S(99304c5e,ccf09869,7b2193c2,31dd9432,3b9053d0,e4b9025c,74517ba7,f1978af,ee77fa7b,638b1396,6f7e77e3,43dd04a0,ba1324f3,1e0da111,338019aa,209dc789) -,S(40e108c5,59adfb37,651f04f7,9ef895b,25a79f03,650d6b1d,1c21322a,b4c5c6bc,8980ab38,5733e648,84aff3f8,c47fef44,210eb2ab,a094eb2c,fc5e464b,679db653) -,S(98c88257,2d190721,20c31528,7f508df4,6d6276dd,c9711aca,5bbeacdc,88c6a78a,5d1aa976,1f5c5ffb,d12ea7f4,8d0510e8,b57f270e,e08c3256,f3ee676b,41a61c92) -,S(389aba7a,25e92306,b84eeab7,a16c37ae,d7b4cf09,806ff740,c05dab20,60af6fed,673ab0c9,ec48e2e8,d372ed60,812b2990,49c32637,35f61c13,d6f0ecf6,d065707e) -,S(9dc64fba,832c956e,93efda62,e5f11b3a,6619eaaa,e539b732,61453eea,ca53df17,180b38a9,3c56ab10,a4267ad8,d8a358ef,8f60a9c9,9483889f,956bafda,f45990ac) -,S(71118e18,e758c2c3,6203528b,8b6707ab,b3439b0c,d3d508a9,6759c155,fe4921f7,c2f61af1,2c1b4e9c,64908719,f11b52d1,76bf22f7,e1cc800b,5ec79e28,aa104ee0) -,S(33bcedee,11b9f3c4,924e0990,9adc5fd1,46218b23,6531a242,45cbb2a8,3ec3d096,15f4bd1a,6c22c673,941a71f6,f4694fdb,f83b3e8d,5e317e9d,655057d5,acfbad0a) -,S(4b599b3a,4ab5e9f1,f161e5cb,62fdba55,fbd97740,759871d0,e66b20dc,4e13ccb4,635039da,9035272b,8b706411,9b342144,6c96019a,2c6df423,2b18299d,4a3fb523) -,S(19f6bf4c,dae54ca9,41b8f642,95136026,decb8dda,35e97627,5694365b,21269d10,a24c3fdc,90b06dc,264bca48,db27502f,6cb31a6b,609d3f3d,a1c92c64,cf3c95d7) -,S(bc3df1a9,8027d14d,f6629adf,7ad073ae,8a270875,b177a67a,58dd46f,1b01314c,99dd3a91,54f51d07,2ee33e89,8d915189,93445065,770745e7,b6bb30ab,808d1f76) -,S(977a4264,521a70e8,4d25f5b5,ac1ae5f6,c34ef31e,4dda285e,1ea4a9e5,7dd72c3c,f1bfc819,7aab2fe4,d0425b61,cd403fc9,dbf44f68,32e1c41b,4fce9b2a,2b9f5a0c) -,S(5fdfde4a,85fc5a53,3ed4a7f5,8adc7b1c,98b2611,3e271b47,a1c12c69,dc9b339,3edf2baf,bd6a94e6,951bad5,26fb24b9,731c2588,b2f6eb1c,e9744f49,16c6555a) -,S(b8bcd72c,dcd28afc,eeac1ac5,fb7db8c,afc17abf,82268747,6ce01423,e9e9c50d,82633c5,2e6dc057,9bbd9f2f,3771a53f,9cb6d0e3,6a7566db,f2c45125,3c55e9d) -,S(6c20b999,133bc37b,c65d01eb,6e946565,721bc2e9,da735c72,8be8a41c,1f75c77,20caf674,d8ad036e,25f42aa4,7a5ae475,5e36f44a,79c5ff20,cf6df115,40b71e53) -,S(bbe49141,69655f15,39ce4bf2,f2e919df,f877b5fa,163b7a70,22bc91ad,315adb07,8cd3e025,6618d23c,8c6b5ff6,db8fc0a5,a77b847f,ec876ac,40f76e9c,cbf93a1e) -,S(748b3078,e38374bf,7f39bbb,c5641737,bf6dfeae,d3980c75,2fe14c68,65e73786,7f7cae0a,61a7dfa2,471f2c80,217fc847,ea86b6b0,6297aeb2,8f3c94cf,2a811ac8) -,S(fa63c7c5,b89a2559,4615728b,2272cf68,5d39d592,d052c0bc,d23d48be,c764e4b4,c4c32ba2,77519d60,e1e38a50,6d67d041,804724d6,5cb4dd31,fbe7d692,8ca47c8a) -,S(c2ed7197,d014e380,a365ea13,d948314b,86978eb0,70e3e444,6c953871,cc56c91c,5c73c293,e7c1cd18,f7854a09,d8b9b0fb,3404bdb7,737dc070,9bdc01e,466a595e) -,S(2514c1ef,cb1e0bd6,c2f34e84,6f3e8006,6c2b3a04,c0d9fab5,f22fe872,6fc266be,c5a0ac6c,7bbb2d9,ff844346,65f66ec6,507c35dd,8ccf9ad0,69a1ec94,c64e3eb3) -,S(5bc07f05,11647f2,58dd2e28,9a3843c8,e2318bff,c96a081d,f6b6ef94,4e286350,213ce093,1217ef04,8d87d059,f2584db5,7a91c465,1e112c66,a41f85ab,ebbcbea4) -,S(edb56e42,97375b03,8a573f70,67ae464f,db9c1335,f6a03dd8,862a1731,9a3cad8a,d3e61a70,16f8d546,61b8414a,426f3be4,35862053,1d981f2e,5314447f,15ef5fa7) -,S(2925276e,78266481,3bf60998,2e028646,6849088e,d0d77d55,817c8d9d,73d5d732,f53157a6,a97c989d,ceb2d755,dbb0cee1,84b33213,20dd6d22,62213fe4,9a87296f) -,S(2c4579d5,bda0f4a5,37209882,937019e9,91286379,c3afb37f,a69e409e,9bc0a034,e150bf4d,d889c3c4,655acd23,f3107bca,a319d467,b1b9b15c,336ca934,5ef7d99c) -,S(5f260a00,11f9f876,bbe29587,af31832,25f21b8,42698b3d,5688545,a8808904,6ad33a32,164caa1f,7a4d2ce0,6eac3d,736fe64e,d83a3a9b,53473a89,8ee02350) -,S(3bbbbcc6,12095ec9,52fd430,f3fb3d6a,9d1f2c69,e8885100,d65a4d7,b6ac4b8b,328e828,3846a6e7,db5b090f,8c9581da,40d244cb,aa3b5948,7e4f9faa,550b0c97) -,S(4985027b,dd0fd8ef,fec9af44,bc222f4a,343e80ca,662d917d,affb9d81,956acff0,58befd2e,37a36e41,305561b5,f2716a23,460b1014,fe814654,68c16c22,3b8affda) -,S(214638e8,d2e30891,9b5eb2d8,803b3dcc,6e826ecc,e1b59b,92e263d5,67959de7,9dd8921,6f131e29,35ae0454,ff5fc9c2,dc22c0f1,c8de7dd8,ad9d41e4,f632342a) -,S(6ced8705,5ced2d6a,f3e3532b,965e0a31,6876c110,69155f35,444004f6,e6f3cfdd,f51b1aab,c86f556f,8b7ba4e2,a1e6aee7,55b17c01,997fcac0,a83eb56f,7e546ec6) -,S(95016e67,876c936c,e3263498,7859d1ad,7fc3ade4,4219727,30a1c886,c9dcfacb,299e78c4,e6e266ee,ffbd284b,81005bab,4df7232f,2e43f160,742bb392,6af4f660) -,S(4bec66c8,30401c39,c42a8019,fc398cf0,c513d20f,9db30763,51315319,ee6f23f2,f1dffe92,3b7d4609,871aa916,28929c63,4fcdeda1,543fc3d5,8e8b2735,938514fc) -,S(b50513d1,40513b97,6ac0015a,60e53ae5,9088c4ef,5ab27bb2,7f3eda78,848a59c7,9c41cae5,1182e6c2,3fb254c5,1b786ccd,dc9282c9,a6674841,29a5894b,99c36399) -,S(59792653,3989a039,6a69bda3,8a920ac9,d1df3845,26f30c00,3e415593,b690708d,7f2c14b7,274887db,5e656192,19ee6737,4c750cb3,97ae4bab,3a3ed02f,1aba648f) -,S(7ba2b766,cf012a93,478fe2b3,e916d665,251cc7f9,3ec16dd3,4db37056,5eacf6f,14fd8938,f950798c,37121286,5e8bdd14,3dcc7e8c,2c84aa69,3fb311f,856404bb) -,S(3062f2fe,f69c90d9,fc947af8,a9e839cd,7f9e9d22,566bd3a7,1c43df9b,eab5d6bb,db84a833,49916d41,7fde7b71,9d92a716,64047d4,21a36bba,ad9972bc,6f5ee58) -,S(ed5f949d,69dbec8a,77f4d695,cb446700,f6fae687,e327cce3,db38c2fd,54b06e74,4724e060,57b3d50,65104ff9,29950bcb,2a690723,f15999fd,ee62febf,2d8930e3) -,S(4d655e03,30028276,e9312fe,a6acc010,30e12950,9ebd68d3,d7170e46,61b7cdc,90efc122,6c27549b,2f5e046b,69e97f04,4399579e,278ccd0b,7bcee523,10ea99bb) -,S(f6b60756,b888efec,d0a9edf4,a483f95b,68e05e80,c351a60d,bf166faa,eaf1b35d,27bedebd,aa781584,6a896b24,1afaf9b0,cb57e98f,bce5df6,bfd22a3d,38a5fb8c) -,S(cc592caa,942ba237,72c4db94,58d6ea2c,8c81c538,8fc7cb51,6ca30188,a3c55748,36e2f7cd,358e5608,36e77d10,361c3f1,bb6bd2b1,d640307c,63d512d1,db288158) -,S(4acba9dc,a5bb4698,21a3acb8,cedf4304,f9372161,976d0edf,6a7a032f,f6c1a456,b36e983a,b2ab47f3,3e72287e,9bbd02cd,d6fb302a,972f2166,9cae4e85,52262437) -,S(c8a5185e,42279d3,2b50e0c6,1b9ce961,7be3633d,84a9472d,97446ddb,eb061f91,cfaa50b7,445e189b,d64c1df7,4668eeb1,cdb7cbd1,ff65c0ff,3c38d22d,9bd4b5cb) -,S(c1c95567,7f4f611,365168a8,89de10ad,535faf08,65f8d20e,52b1041,d35f18f9,34f7bc3b,3d956b63,9afc1eb,956f4472,543919e1,3708e7eb,537ab941,48033749) -,S(8df4fbb7,36f6736e,b4a09370,33f7d256,8bb68d68,f3e1f8fa,8df1ae51,d236a8f3,3d7185fe,8e9a2d00,3987af26,71bb3850,cef6b0f7,70770c81,22977764,5d02122c) -,S(d635f0,e35c7cb8,f2aa1ec0,c475011d,c2c8bbb6,d1ebc297,c2baa5e6,aa5af3dd,926ebd,c588e8b3,1a990a5b,5907ae5f,441e5a99,1853c643,5e36803c,7ba51a2f) -,S(b58d12d,5f865375,7514ea38,30e38e05,3678b525,e8b51923,d6460720,b46a4bc,f7b59183,5b0ebab3,935d587c,e995c0b4,d77c9e40,ea4837f6,48e44841,7438d3e) -,S(bb7c6a8c,b4013640,ecfad075,578e89ae,12cb4253,6461d780,11ba76db,da9a7f36,7dda0258,3774d618,68995b83,5708295a,3c2f5c40,306dcba7,d1c20da1,4836581c) -,S(14f6f0f7,92cc8cef,9dca990a,7fa5b7aa,f116b819,722cfb91,9683b298,3514a9e6,88c35f92,7a07598c,90ce5aac,4b3fecb5,2261045f,f23800b9,7b96f210,3a4d7055) -,S(4b95e5f4,eb9fa118,5ddad896,457f4aa2,fb60f4d0,496ad4fa,76bbbce7,77448541,1e100787,513acb31,ba087f51,201201ed,502d1f08,f7e2b8f4,d27706d1,45e71d21) -,S(e9a17fc0,67f75b2c,6384aa31,223355a3,a7af5366,4d85dc16,dcecbd2a,364b63ae,420a2388,ad674523,62f8fcf0,12b601ab,a40e06a,1b4dac1,9560c085,de7fb8c7) -,S(39d8536,f320ec81,4ee3d066,c0834130,96d4ff43,8331a81c,f10ad544,43ff9169,70ee89e9,1478e898,60d66a55,6054abd0,c7434535,13a7a3be,7a76e367,c28ca248) -,S(9779a0c8,8624d6c,beb1dc72,f371ce26,9f95b993,c49ff20e,1daa3c,2fb636e8,9d9e27cc,67296c50,9da4b0e,6037920b,369684d8,a64cb907,d230a4ab,a0c2712e) -,S(cd4c584a,1dabb48f,6a5c09de,9caf36ff,4a97471f,d1565586,bd78b4fb,66f0b401,95902ab1,eff06e2,b3e104b0,cad2c28e,6fd60eed,c47657f0,bc433411,273446f1) -,S(46ca11f4,142362cb,513164f7,c72b776e,dbeb3f65,5d527196,88eabeea,2561aba4,8060431a,2a2ad442,dfb6d3cb,d6263c61,bcfd0946,6204e2f5,e832c4d5,a434c9ff) -,S(dfebd179,1ffb63f5,76f5c753,50031a21,eb712de5,7e8f83b4,75ac39d8,8a94a513,cfed6c7e,39b2b54c,206aa0e2,2f7c610c,6576af2d,ecb28f0a,a71cb1ad,c7be75de) -,S(c71c6532,82fd063b,44633d9d,7a3b94f9,43daf1a1,7967ffcf,e1238087,5d2c2469,62fcd7cd,e006a10,38df8aed,33abe940,f18a4736,52adeba8,620d1b54,a9d376d0) -,S(63ebbb4d,dc8ba09a,4e2640fb,f48fb75a,6864ec41,fc1647b1,e9f8aef7,34c0ff37,e59d034b,fe16f4b,41d090e1,97360a85,dbf1ae4f,719c62df,77261205,da4ae28e) -,S(650498c8,cb51bf16,58eeac61,61b5892d,ce6e5c1c,271d40bc,eea14db9,dd12814a,e7e66785,5d8e0193,24457769,bbd5d14a,7a614585,70ad5e6e,e3058af9,64a65279) -,S(14a1e03f,14c00863,81599c07,b816df44,90815a8,40c1032a,c41225a8,47c43fd5,35244a59,bc6ba88f,46f66bac,9bb8ef5e,4926da38,50532ddb,6d6d606f,35fe98de) -,S(1c9f6eb2,f6a8a1e8,ecf9a16,71154fff,a4f14c15,bbd50f08,4d6f5315,b6903c5c,e6bde1f5,2ca4ff63,9b66fc51,150eee99,5386383e,402f987d,d266065d,2a03a033) -,S(1de71eed,bade7b1,7c80966,4b00d56c,b43ea61a,c0e069d9,7cff0218,f970f8bf,8d4b2de,77edeeae,d78d42e1,6b7bc94d,ea99d65d,985769bb,5c67da66,18ee1434) -,S(f4432a80,ce954d2e,baa2f062,8bbab706,479f7a39,838d8c3,5a96eaab,5f5cb4b1,96fe6ead,ac34a40c,3cabf47,6fc09382,91f3d077,29c6302c,c67a189c,bed579bf) -,S(8f71e74d,17964af4,5623d3f9,68424119,cb37e1ca,c1524737,4828b5e9,2519fb21,6990f0df,d7f0ca4b,a77678e4,ebf6946e,5b6b1720,869c91c,ec07854d,604865ab) -,S(22293157,5e3dc25e,665546e2,96a83a0,5a09d052,cef701a1,20019c49,c6a6745e,aad8f887,42585607,c792bfae,8a941caa,83d05082,defea859,86a6ead8,e5c423b0) -,S(6585fe63,2ef3a69a,816bf5f2,9e627650,cc57d069,3ac217c6,3b73aa2a,f248a096,820aa3bb,20281afe,edd9ca57,76ecc55f,dc8a893f,de11f7cc,12f37a83,6cfd9f8b) -,S(22232479,e55c51ca,b2963ce5,abf06281,aaec472f,e610d339,1951e41f,93f67bf8,e192fab,2cf22d7f,e67f0514,bc1329a2,888a8f18,a8d6504b,b7c5a9bb,ebf927d2) -,S(da8d02fd,e4ba069e,bccaba08,2b396c94,4460148b,70e98f60,8267db02,5ddf16fc,1a30213d,e337084a,47d67e7c,17a2e64d,579756d0,8b66f4d0,59a76021,e63fa2bb) -,S(a6f72c62,854e82de,f1b8a006,64c4e8b9,ad49e092,78ee6501,708a9f18,92202ebf,8355972d,b08c8104,b7c56ab,c2318ef4,2e270989,1a83837e,daa35537,1d03ba4) -,S(2074fd3a,309e85a0,5c6f8c35,937dcc56,a15077ce,99f5a8ee,8d55ae2a,3bc7db68,e11c02ea,cb783c94,2e58fc0e,806a9816,3061a4e9,aea9582e,53ae1f08,322cff97) -,S(49ed5666,fae9aa2b,70cd316f,62a4b62e,29aa59f3,1826106c,8611c50c,79a1a5e3,5ca7e49a,ae144e2b,dcc0b19e,f986967a,1477c209,2a8368b6,324bac6c,807643f7) -,S(2289ec7e,a1f7e4e9,85f472a7,13722335,b582c4e9,8e191468,3ed13622,5d6c1b1f,11e2b18,689a0867,517bff6,77fe40f7,b03f898b,d70e8902,61a512ca,d9cbbeb1) -,S(ea852ebe,23f1efbe,d8ac64a5,58ba2ba3,fbed0e52,ffc70635,bc49cebf,85859164,bde2ef41,fe97a639,73266583,c7a4e415,25ef1351,5b25cfaf,c97aa635,41cbb824) -,S(5718f0e6,7cc07d3f,1ac1a954,8fef08a4,290b257d,a4179855,3fe9be1b,d302f0ea,98ec4d5b,fca65d7e,e72d8bd5,3645a6af,a6ffcaa0,a2eb894f,d4e40ecf,69acbe90) -,S(df62a2ab,d77afd7d,ee8f0650,b75458e3,10269c3f,780cdad5,50bebd92,4b810a4c,6a6606cc,e384d27b,80bea2e9,588663e0,8d39fe8e,9fc8a8cd,54c4829b,8e4c034) -,S(1010fc45,4b0c268b,c339bd19,809508e7,9ea7dc0e,efd779aa,4974cdae,805e6668,686a3adb,681b597,2b30a323,c6b6bd2a,d51194f1,9d3d801c,3fa65fab,e96410e1) -,S(8ac79852,75673818,69fe93c9,6141493e,72ca344,790487b,d5425ed6,9f5c5c18,bb314248,fcbfc867,d1972e04,b9ef1f90,775375f9,9d25bcec,684c72c9,bdd1c08e) -,S(560e9711,88cbc7ce,c61f3bf4,45f0ade3,6f3f174d,219a160,5f9c8692,3f848b9d,9e92dace,6775cc67,bfbbf21f,c64e6e9d,4d133f8a,c18ee277,bc80ef6d,d1b9cd2f) -#endif -#if WINDOW_G > 10 -,S(8c464204,4b95eb66,cc95ca08,8469a1c0,28eea52f,7f709fe,e6d90700,f5fb943a,bf10fc5d,7bc25181,301b3a61,5ebea597,a3492025,953c3aa5,1a11271e,689d0223) -,S(d293f74c,f3578b71,35377247,cd8b0367,7f2245da,f87453cb,4d8d1cc2,871eb5aa,86c2013a,61dfea14,63e45931,eb09050f,f080e3d4,ae357423,ba7afbed,a64a6f26) -,S(35997241,ae757b1f,c767611e,c76eb935,fefbf7a7,33666aff,4c6bd744,d7687d35,bcbea61f,246bcd4c,c3c7fd35,7bd393da,2f36e0ef,cca0df9c,5994f96f,c44b2aa0) -,S(d096097,7467197d,3c1a0ef8,44ee35dc,285a17c5,bd9e06de,15f36025,7f6464eb,342af6a5,1e06db96,692954bf,c79cde9e,3dd44869,9e88b03c,d144b70b,bd3e8783) -,S(8e875c99,2aeaead6,7033a375,521b0f85,62125797,23a25470,bfdf898c,ae41a777,24aa273d,2d2f19bb,4e0ba10,13127ad2,a5ee6686,1ec6d0c6,53f7a989,73c0bbd8) -,S(bf51d1f3,2703a4c,d1ef47d8,172c5bb8,d622f444,8569aee,d2de1b9,ae541855,8f81e352,b6c60acf,bbde6e40,99353d84,5918d931,4433c30f,3c60a710,cf9aa484) -,S(6fb6b462,9726856,22b2d141,5083ef56,2ebb115b,6cdcbaee,696a8d4c,8341c26f,9c08f7bf,f9cfcd9e,cca923b3,e578ba45,468f2530,baca2032,a899f060,b83c9c73) -,S(75583ac1,8b5cf78d,7de6a21f,aff045fb,1db56f68,6b2cf89d,678df62,93617438,8259a22c,b08546ff,e237c7d,9c669c96,71fe014,9840082d,f6790340,9b69f900) -,S(42611933,a5d759ac,7ec51c89,31b76e95,4aabc2e3,61010f36,cdd8ff9c,b4c0ef92,88a644ce,6b8acbce,a378e2bd,54eb84c5,58cde403,f99cbf8,7830151d,21ed4261) -,S(243a6dbf,6128f964,bdae776c,a716bdc5,6dff9c95,24baf845,8a43ade3,af520d2,262a2e8a,5ce4db48,d0401850,e92bdfa8,3dda744d,a3d9025d,6091f1a5,201b7e50) -,S(212bd175,1548c6d2,41e9307,a7df15bc,46e57e2c,5a76bd58,82b1291,d8c2ac76,82461bc7,6cc97273,267cc788,a8b24082,57f04ef4,719a9aaa,e33cbd77,79391bc) -,S(da6d030b,21f96d2a,aa0b3e56,28ae0ec8,8ca8a546,10bd61fb,c1a7c16b,4d61177b,5b5bc635,8fab0287,4a2b8596,1b49ec29,2c2aad1e,1eabbd0a,1cebdbe7,2e3f9fde) -,S(dc230af0,55a243b0,a581e101,2eea48fc,4a43137e,cfe80108,86a9f4e3,f6c1f01f,d0f98e1b,e70a458d,7030120d,a3d7feed,2eb5a9ab,601718bb,950fa03e,568180ca) -,S(82c2de3a,c815c686,98ce73b5,6f232684,ee9c5972,f0a44797,dc16d04b,a9089df1,1c847065,c6c2cc18,fa253b8e,c1fe178d,c859844,2c1fa432,54462d97,93b8573d) -,S(6ca2de88,74e4916e,e1965dfa,200af89a,cc439f20,6a4077f6,67076149,e20494a3,6ef0b344,97aa85dd,a43cc1aa,57dc7ce6,cd51119d,ae96ae06,99b5119a,9a662043) -,S(ba2687c4,1728fb65,206448f8,28400efb,cf1149a4,90bd31f8,8d33af53,7851d97f,96ad25f1,1f2ce7aa,e8b803bb,3c62cd32,3345500,243b1de5,d61f20b1,86b4c0c4) -,S(ac362040,1947f301,16032d5a,4b303323,d311f533,e46a1aa5,f1ea2f08,d553e0d,53839f95,fef32884,5a75881f,a17db91c,1d5b981b,7b20937f,df171c3f,2cb30a22) -,S(6780ecee,5b1b7205,68d4241e,c3b35c9e,4158c7c2,2dbba46b,ac769476,79049e13,9ac115f0,31e0888d,2dc90b9f,3562e732,46520d57,ecc7ae4e,e0fbf401,3057d9a8) -,S(95377a47,e7a2d5d5,30510d62,2bbd3439,c0f7653a,ab294254,cbb10390,d2a63732,57ac9110,9dafb62c,fe1abe4d,fc64557b,bb01f76a,36649d7b,91be523,f8195fc0) -,S(4f195bf,98fd83bf,7ee97c5,9bd42af5,486a8507,3327415e,85f17a17,2add8921,a56acf25,1c82323,6327cae3,6b1cadd,1a057bbc,f1ef3b59,a865c7b8,691cf3dc) -,S(eccd1fd1,efe8299f,d2208240,adbaabce,cc0510d2,d7b6f6ba,d9e291b1,4cbcb53f,ec2ff321,6da50fa5,c57d6f2d,3198e019,2d9b6f8b,ffc26b29,13580447,a42c667c) -,S(c757444a,f2c3425c,728ff41c,f7cb7475,502e7601,c1edf2b,1eec84e1,b058f438,e1d481b6,169f143e,29701105,bc8b6657,9cd267fc,685014b8,fd070283,6362e53a) -,S(3562837e,bff50776,58d99662,7a11a367,aef3255c,1c470ac6,36f1b57c,645250b8,cdcf4a0d,97aa58fc,ccd374bb,bcafc00,fa1d0d35,ca7fab9c,f4d72d66,299234d8) -,S(ce9dc245,f62e97ab,d2d339e9,7fac18b7,b1f2f07d,fb654a82,b113317c,86d4a3a1,f6e1e325,342afb8e,64fe8520,ec37abde,fcaf1b30,be6ecb79,27ba5615,f0d184d5) -,S(ac022f3b,48ee44ba,9d271a8c,1a01fa8a,aab4818c,e5383dd5,42d9d6e3,2c858a12,1e0563a8,91f8d11f,1989e091,739611de,191e497e,66055aaf,45db9ba9,72ca76fa) -,S(d1d4f682,cb12cfaa,e46e57e6,db6f2277,55a83782,88cca4ff,3a999c0b,a651d9f9,1b19bfe5,870e1931,4c23b4b0,71672233,1607264,acb8e960,488598e7,85e71a36) -,S(79962171,bbddaf94,45fbacd4,f9bdd1a8,892e754b,2d0052ee,2435303a,ff1c8a37,b8ac27de,2a952beb,45472f77,b34c1354,fe47b6a9,daf0720a,b8515be3,7bb98a7d) -,S(445a17c4,2390b604,bb3c3573,b061a2f1,20ecb3b1,83a0f8d8,cf032e3c,509d3b90,b75f4088,7c07fe5c,a0c057c8,7eff4966,4ea76941,e409a6aa,e34ad4b1,693f97b1) -,S(6166b5f9,63a9f47f,5fac49a7,8d175763,8c39cd49,11d16ccf,b0e83bc3,f402051,ba337661,8302aeb2,213e4620,4ec57492,933d6df5,5a045d7e,5317ddf,e92430b3) -,S(cd666e74,28901afe,8e67d0e4,48de7e3,30b6dbdb,a34db4a9,29315d3f,8b251531,af72d8b9,43cba540,e42398e7,49fc89ed,44095951,f11b24f9,e5451810,3802304b) -,S(c833be8c,fd2f6fe0,46d837a1,1d990355,5a6285bc,d7b8814e,e839cbad,523ac72,7ea8f90b,44112363,a8d75153,150c3b4e,b6c07dbe,fe8c8ed6,3a24984,c9a6af03) -,S(cc185f36,3036d385,d890ac1f,5e95b162,e40e4a4f,e8427613,98200369,f25ea477,e0768836,146d9c98,98aaabe5,a9ce12ef,f66d0775,4055eb42,832eeb9f,26338236) -,S(148e0863,24bbc2ba,b67c9be7,407b809,77ccd910,e92c9770,47943c29,8c9c4a5a,89e83c85,9cddfc80,9de733ae,6138e97d,b706a331,fb7176ee,55dfe3ba,c2408797) -,S(9b1539c1,aba5b583,5c88d9b1,92a3761d,cf8b649,54f53a7e,460e0122,bec95c76,391cde19,45be59da,d4c895f1,3aa1ce24,d8472e42,a232795b,967f21d5,acefdc18) -,S(68a2e6c1,75fb01d3,76a9e575,ff427cc7,a6032774,a974bdd3,e93b8a73,e4495cd,153e6484,c8c30dde,5f269b74,1c599647,666cab7,e273d4f2,5573dc4e,78e00752) -,S(58fe9049,35a5a40c,3b633440,533cccac,7669e9a2,e7c2f0b6,6c36c228,61dfb04e,b36905c5,92450e2d,71d06e2a,2d599a77,71ac1e27,15a79555,b39fbb60,5536e1bb) -,S(823c0f96,dcbdd9b0,bfdaff2a,19b6027d,3e9bca6,e298378,3375a783,5eac7080,d91546cc,f34d9a58,babeb6d5,43bf3c36,8831a2b0,d9043db8,895cd208,f2ad0a7f) -,S(4a56aeae,e908f908,55fe7b71,3013ee7,d6812152,4f7decaf,533cde20,2d14537,7e60c801,33b718d2,119995b3,3790eb9a,3129a7fb,2e030d8d,21af90a,c622b7a2) -,S(6c0f3855,e6c4f5f2,c4594e2b,8881319b,82a64bf4,9fe0968a,71f6ca3b,f9240334,5c8e7b6d,a9efbba8,4b5ade85,305aead3,e1478ad1,b4d56fc8,3acfe34d,23b5203c) -,S(d9cf8f2c,d1704907,15dde21c,f172e648,496e40b,5248f331,3aeba2a3,35ac9632,92a7c251,b440f930,bd98299,c35d57f7,15867e90,b6c3e8e6,b073815c,3c934344) -,S(4bfcb492,8b91dc7b,afa7ed43,d9af3039,77592728,fcf1b9e2,7c6767f7,b993d898,276a06f1,ecd9d410,b34c9a4a,e3aa33b8,1854a4e9,e4703dda,7bfca949,a45d14f7) -,S(abde5893,ac4032f4,4ed93dee,8156596e,7cdcc575,e5928792,944019ac,23c434e8,5e03a809,2b9e6044,e942af7a,7cef02fb,46162cb2,4c19916e,d774b00d,8195c40a) -,S(205d6307,7a98a8e1,178814b4,9281da20,4482f1ae,31be20a8,3b3b0fd,526e1cc5,4bbe295c,943e3560,6b95cb19,d6e64bfc,b9cab7d2,55657614,7a79ff50,6fe4d780) -,S(cb4c4c83,e6673a1c,6c228a42,36e6031d,b59653bc,45bf4b7c,3b98cdd2,441c43bd,142e0276,39267ea0,f7c2ff39,75afe714,62f3340c,1fea5149,cfe4e8ea,e31a2769) -,S(25a1f4b2,7ff5bdfb,3af54a4b,493356ef,92ccf0b2,dec7c4f2,b5abb225,2cca77a7,1b25dd93,153f8341,7df3b3af,c991f2d9,36c32e8b,288a7fe9,3e9ff97b,335c3c38) -,S(222f76a7,7eeca0d6,a511c863,a657cb89,5a1b7154,957b66dc,89ca77aa,2a54237b,a8f2bee0,64eff88d,87a598a,8665d295,a205c884,2f6a3492,7945a02f,2cb0b289) -,S(32d4328d,1ad2651b,41bf1015,6936b406,379f5c26,99f1c2da,ec3cbd8f,3b4dfa8d,9f6de6e2,3294a33b,5f4d4062,3e478096,df5de0a1,d069290d,204ce930,7988261d) -,S(cde9ecbe,6948cd70,3b193790,6662b7d,187d0830,cf991b14,e8265691,81f1d3f0,84887b32,e1218d2,9b77794c,e8ad56c5,f5abe8ff,f95515e2,4bce81b1,5b029720) -,S(bc89f45c,3baaef4c,a8343582,6506a006,509f4e7e,265e4b80,11d53d3,a748947d,eff5bca2,714db146,7a272fce,534f79be,9fa15af,7226ba49,51129f5e,6fe68475) -,S(62678cc0,eea2bbfe,2bd4ba65,5434a9ad,39b409b9,b57efdf0,9940f748,ddb51d4f,8d384f4f,d234d31d,1c161245,ef6dd54e,a5cc8ab9,e7bcc883,6735051c,37a74acf) -,S(15e01d39,c63ae225,63dc89cf,3dfa2736,df7c0ac3,4fe86f8a,f219f933,86bc93d0,1f563532,314fcb81,c1725133,49769861,e7efb999,fa317ef4,2bc75588,10cfb13b) -,S(4f8d2b49,3493258d,ff98e813,e428ae9c,52c60103,1bdbeb9,7b8f364b,2bac10e3,8c7d117b,67955db6,c0058028,3f919f57,1e8c58e4,216ca1bc,d66b264e,169b73f) -,S(d14ce31a,2bf16b60,983e397c,ddd3588c,3b0d77b4,f449136f,1a789276,b56f1d61,9a15f620,b227d83a,3722ca6e,4dd7bbf5,833f24c7,2584f356,11ef3734,ad3f0910) -,S(35221b4e,b8c275f5,c10d656c,9bfea000,24c1aa2,c4130841,9c3e8e3b,66f780f1,3d1c5a02,5274afcb,bd78382b,b2778657,6888d46,1b5dffa0,f8ec5dd9,3bf8e808) -,S(82ed9c3b,1c76c1b8,f44ff6f2,9f443b20,83f68617,7270843c,49eac0aa,34a8ddc8,262e9e6b,c2ab2b86,7342081d,90002690,e81f5a58,aefd6fc4,8a91dc5d,e95f1340) -,S(919e960e,acf2aa36,e86342f7,742e97c4,9c49b64a,ff5c6118,d181e349,10717b85,4b51a94e,a3ea1679,cd9ce9d5,ac329f13,ef530d42,c7821650,5a082fe4,d945b861) -,S(cdacae3e,20ce551a,beeabcaf,a643ce62,edca3de1,acf06c30,65ffd366,5bc3ec7d,aaacbb13,872b076a,e28c326d,fa54f4ee,235df4a4,b341c9b1,3d322071,6eb95bb6) -,S(1a4508e2,1bd05c09,f3d80f82,90726f08,de3a62ff,b663d5a8,f949ce26,92a5f2ab,52780ff0,976eb033,760459bf,4bf02994,c6e672c5,6d25d3e6,2b320f5,2cca97ba) -,S(8e46eeed,5686f25c,a94f73d1,3f26c98a,e9129f77,f3aa18dd,d5214262,803a0b45,ee56d38d,7041eea7,c87f2ed1,e7f0aeb6,7253d556,610e8200,782c9af6,1dedcf4d) -,S(782910fa,3bd6b309,dad797c1,5b618469,68d6171e,7a0a0532,a92e5bb3,697e4031,ff178365,c44c2a28,e84c31b8,946b0a80,717914ff,6d3f22dd,ee409753,44e4b3f4) -,S(2ab9e8c,c5a710ca,6cc2d0a2,94f1d7d2,65c50aa8,f9069041,ae93c91a,e5f64e8a,aabcd0f,a2254bad,67cf23d,a5934947,18536602,a13d81c9,db23afc9,a7f89b9b) -,S(d04667c4,4fb25b22,8320cc53,35252937,a094ddc2,4610f7a5,fcb1bd1d,6382c9e5,7c93613f,8bf048e7,86af436e,cac4fa86,6e5a91d8,3064f5c,e31d4794,b2b0f74e) -,S(b9c476f9,799cdda4,a51b0476,c5838994,f157bd29,c9361252,def4af83,6e86b0f7,2ec7619b,c77948b3,f25cefbc,46845527,d1a9b0da,a90529ef,f13aab4a,ca97932e) -,S(90bdedab,f13f9940,4b9d8c56,5d64739c,4ef765ff,dee2ae0d,64fda841,286eee85,a9f47882,d9a848ab,4be812a4,8187d26c,7f8bb8dd,b94f7725,5c628104,e0cf21f5) -,S(a0c394a8,2177734,c02b8310,74ebf0ff,ff4208cd,dcd59e7b,a680737a,fc485c84,c4f08932,b4c62f34,fc82434f,e9b7b164,e835cab6,2f34ee3f,d640e5d7,d09364b) -,S(1b0319bd,3896e8c6,284f949c,72e7694e,bd3c2923,ebeac273,b9aab50d,30294c3e,15dbfe9b,17c3aae7,e5f8233d,703b7b1a,1401b672,1da32080,53ed52f,a2ee339d) -,S(9914ef0f,e92f16be,a27a9354,518dcc0,1210eb3b,3a90f2ab,6992e3d9,bfdc719d,7a0bd065,cea0b11,e8df3629,faf65a30,5e671d2c,86332b83,98ddc2b1,b3c4086b) -,S(3a68fa19,5599f638,7dafa176,395c9615,5798ad6d,7ace7810,daaedd13,ddf60d3e,74575ae6,a3f569db,394faef1,e0641ca4,de158eee,9a8ac54f,5cd96bf7,d4e71a89) -,S(b7361d41,e2b67e31,f1872b1,b1bffc8e,41193dec,7f012385,9da69c60,5e88b2e5,fa9d6b95,66d49bca,73cf5890,f6e7acd0,315347bd,f10be9c2,9b0907e1,80668344) -,S(341e9987,42d84640,f6fd1354,3fb7ff9e,aa93a4d3,12e99bc6,37b85b83,25174e81,c49608dc,91b46187,611cbcff,762e5fc1,e95b4e9a,6ed747ac,8612b6b9,8bfcfc95) -,S(83d6a445,de34f557,40084909,402c9718,1f6420bf,af87426e,2a0f75da,c483e6f6,7a86db44,58c8fb53,5edcf48a,14a94dd8,e9fbed09,277db0fd,787c121b,a1dddfc1) -,S(4f11235a,14bcae9,89082bf1,c6a499d8,32d17686,2fcffbdd,a40b84b9,26ac351b,b50624f1,5f31269d,168021c8,37739cb7,8678ded,be59e288,6e963339,e94a2acf) -,S(8fbb5727,21cfe12c,ea685907,ab6e3d7e,eafb3892,c082115b,998e9a9c,d3ee2b89,da7fe685,c8148e1a,5cd8de8e,2a5b5aa4,ef1bb1a5,af8bfab7,91c923a3,66906680) -,S(804ca63c,b9243f5f,76605b1f,53f5989d,286023f2,fc672bd6,3f52c59f,5496c3de,372912,eedb1156,a1b8300e,eaeb44f8,865fab6d,49c89fd8,43170b05,d75233c6) -,S(b2795c6a,b83ca824,6b18de87,5660d04,60b48ed7,1de9bbf5,8cc1769c,2d2a5365,66e8c2b5,88530b6b,4d351044,186a8a01,db684157,9bdc041f,90d0935b,2a49d820) -,S(deb5304d,b61bd914,c0939d07,c0464eb4,caf3903b,1903a588,208c5e05,36d9dad3,18d54f43,e7e45e76,6a4b6249,1e48073c,40507dd8,3f7b3b27,762a06a9,4d5777ca) -,S(111bf502,d177ec34,b6c61d69,63366901,eb79d5e8,5749f5cf,7743cebb,9b7714c4,be80d52a,bc38bbcc,f036bad4,5e47a0f1,7d8ba20,fe6780f0,bf8c38d7,696a4e54) -,S(94b10f43,c15c5393,e8d4e71f,db863865,daceeb50,674d0f8b,161bd38,dcbe92a5,ec55af2e,a34e8c36,5b3f7729,110586cf,8d087dd7,f1a0ae9b,d25b9b77,f5be6dc7) -,S(4627abf2,2d447784,c53e529d,62d3036b,fb4a422d,10146248,d3b1f188,e895593,8b341d8d,6110b59b,738172d5,6651e948,cbea9ef4,c7e8dc48,3a560503,eb7b3e4a) -,S(19ce15cf,dfeadcc3,7375727b,5ddc5327,585dcabe,c172aa80,757ba468,297c355f,506555e,ce829141,736ca9ec,886cef26,83853e7e,5b3ba66,25cccfd8,4de60f81) -,S(75a40681,8293fcae,8c3e97d8,e1f916d,2950682e,16d3def0,fe6dcfd0,ab9a3e55,5292d5c0,e02ee24d,8139f2af,495298b7,4526780b,f39f5f22,a047d155,dc8c7930) -,S(a7eb8b8d,ef4b7686,b47a341d,4f4a7333,88cb82ce,8f3226f1,cbbf79bc,1f3bf578,85d98b6f,e238577c,b3b52bf3,94a72589,24407ca2,86865cc8,80cfc93f,bd8199a1) -,S(a5b9a2b5,dcc91d67,b352d14,3c19f6b9,6c9f8344,50e16c00,e8a938de,b3da647a,f12d4fa8,39850471,64335aba,1260cff1,26fc4e13,fd16cc29,63472f28,7b9571c1) -,S(7999c6ed,48d589a6,5df7c20e,e9b0fdf5,df58d831,78ad6171,57c09cc8,44015cca,156f4505,3706c3a1,c54b3fec,bd3f12c8,aaacaf0d,22755014,5bcb731d,418f5756) -,S(88fe81f3,b708edd1,b85baade,6c05c7ad,42202058,6dc2e8e2,fead379,c49829b1,cd62e24f,b04b7d2b,b1434150,260a052c,8972a8cd,daa1db10,d99d40d7,df727c01) -,S(18fb0eb0,cfcc61fe,423192be,b694a77d,91216537,5087a64e,89557d5f,4fe86763,3cf72b1f,dfe8b565,38e88e23,ed871d7,80f4a6e3,55229922,b1f28c5d,38169785) -,S(dadb3231,2be4f2cc,cff171d5,baf18e76,4719fa,eb5fcb66,d919c86,efd38aac,8d67945d,752de8bc,b0740e42,3a154449,50e0b330,c6a73981,3d9f4b30,f98bc0d7) -,S(f0b9a086,7cdd9f64,6b3aa0cb,e3105ba,7b17e09c,6c1c39c2,d8057f06,a39e5c8e,2b534e56,25e6d180,40dcf431,9821cbbc,3ff91303,c14bdc81,370c9e0b,5ef4e9de) -,S(dc0e0b05,2e49c3a7,e5d0e253,672e8d43,1cd60166,648b932d,406fbe8a,c2fcb7e0,ff919786,8e1c651a,4cd39cb5,6921e24a,223e7af3,821fdbea,86547e1,c7b791d9) -,S(e71cae98,fb6ddd47,35ec365b,515c6ca5,6bea748f,11811038,b74aa5a2,32eb91ee,804ae818,396c20f6,e2fc5bc7,5dbd1f41,9ed731a7,2801d06c,e6682bcf,1d600266) -,S(50d1b5b2,f7b2e4ff,3b594d48,6bd2ca6c,6b5d5368,2079bb9f,88d792b4,d4ddfd8c,556cf4c5,18fa0660,86b9b03f,aba18fd,5c554fe7,4020df5b,6e34bc88,4d5cc744) -,S(c087403e,2bd5d954,df8c5e86,f23f6cb4,96634886,b4709747,325321d1,bc2701aa,9db44987,d8517300,6e3a549,eed87e06,258bc14b,e2b00679,3a2252,a3507712) -,S(dd1037f7,f3843422,de8988fd,3f68a299,4d45f8f5,1e9242b3,7980f517,bd6d6894,ca8e6d61,5cfbbcdd,8b1ab8b7,673093a6,1a9c08ce,56b065f2,54fc191b,25cccce1) -,S(de229a19,67ca589b,f4a840c3,d18f764c,424dfda5,6c099d14,73a9cc7d,34b5ceb4,958fc9ca,84ca63a9,4323f4b2,ae46ff44,a1d352c1,1b8e8be7,2d5115b,54122b22) -,S(15e33c9,cc9d84fa,16225f48,70a35a42,f8a3a3dd,67a8dcb1,143c7ee2,4cdfd9c,413c0206,ed48cd5d,36205836,45e4ad6a,a59a1e15,c7f36256,2f89b9b3,660e920) -,S(53422561,ca3c4d87,2d23e317,3b21ae38,dc010b99,b7ab0fc4,394e408c,a3d6bee0,6ee906e5,e505909f,6507c7ab,779ce1c8,20f2c50b,a71bb8b7,8debb3fb,6103048e) -,S(829dcf4f,9b2c4f37,32800bbf,f5cb71ca,308bf0a,9176a74,a031d972,9a82b2fc,47378200,429e538a,4e249d3c,9f58873d,abe3f8c4,615c5d3,3525f6ae,5f8483c4) -,S(ed6f6eb7,3769b1b1,4923b989,acff97f1,c05594ba,1d5f4ebe,450e65c3,8ae911e5,dfee6f2f,3fe584db,8b98cd0b,69ff6219,d52e2d9d,a372ffbe,18e500e1,a2c38eb4) -,S(47e52398,1fbe720e,8fcd1982,df2b184b,70616ebe,cb4913da,30327205,c0455503,afd2dceb,f360c30f,6820cfbd,1de0de70,179f4cb8,6c461251,5eae2f4a,baf3e900) -,S(b02937d5,8f48e1f8,6f3f1170,f5e880e4,ba10e2a8,c13dd0df,49fde04b,a9037312,dcb0a4f,3e4c8456,316de580,5355e17f,8a6c7924,f68cbcf5,347d3c7a,28c18c4f) -,S(9f993cf5,3578c1c3,25c10c2d,c3c066eb,878486eb,dfdc65d4,4ee57fd0,ec1989f8,c6b8d40b,16b8811c,d666ea43,2e61baf9,e83eda6f,d38275d,9143b386,31c8bb52) -,S(943b6cc2,5913ec1d,f12730ed,bdfd1d0d,ce431784,f36fe84e,599f9b89,dd3240e6,e58102ba,cac2ff3f,d42d7ca3,254ef55a,9604d3ff,fab5b16d,9f77482,4fed3fd0) -,S(9b0e67e,69b3f9ec,51843da4,f7b5a7c8,59511dcf,47f58a64,81fbf2f0,19acfe0a,6a4ddc28,17a4ecb4,ce2defc7,d7333ca6,2e074c36,f7e49c67,4a009d30,edc54dd8) -,S(97dcee33,9cd8d18f,8c3b0fd4,48ca6e6,c8246b4,136bacc,72ae8673,a4571651,6163a205,cc20bf39,8aae36cf,c8933dc6,29b95246,48823d51,d82d2d2,74e693e4) -,S(a1e5e6f9,26961eda,7cea9c26,f4a1ba02,798c940f,2b7dc267,2999ff7a,d2292ced,50274b7a,6a710f74,ed138401,36d97657,cfc07af9,3b9e8fbe,ca18d31b,8d5f19d) -,S(473d5fcf,7cdfddfc,52fc9bdc,6fc77180,1c21bdb1,840821a6,1a984296,5b4884a9,348836a7,ad7f550,feb2d703,6c82d95b,89ff95eb,e8be6250,eba7c5b1,8fd856af) -,S(9c187442,7384b2d0,4fcc33b2,70544c98,db8c1e13,2bb149d4,54c51ea1,4796f613,2d6dec43,970f0079,3da12e47,595cefba,c1825d36,c71342b,7913f7f5,fcae0a19) -,S(11ce1c46,9150e2bf,b742d826,be740e4a,ed63c729,5f5bf51e,c7a6aa6,562b154,6e86514f,ea38280f,abdf8b93,be8b7d92,67f3b28c,af2a4271,aa3b6a62,1f4fa33d) -,S(1e037904,e4e2de6f,2893c354,18d1cc6f,dde2fd71,4bacf1cd,4d9a5c56,79656042,1bb759c9,34c26821,2a28aa38,a0af035e,3c81ac85,3c01e21b,462e81a5,8c960755) -,S(52fc9467,23f899aa,f1a94f24,f9e3620,3f8d505e,31cc6800,9951d9a7,c0071d82,4632ae0,75430820,20cdfb99,270b47ba,39c909b3,4b3a39db,92419697,d0bd6dbb) -,S(cb585905,997519cb,214f9e39,496f5386,35069eb4,d78dea4f,f9e9d803,642b20d,1b9f42e7,a5b475a1,e42a0f51,ce2d5e50,7131b2f3,5990ed45,64e3913,ec93ac7d) -,S(382c2857,29f14558,75727584,5d37bcd3,e7ab180d,a11c7a12,cecae00f,b4a69c46,cb27e912,20a70fb3,6e258684,3f128693,495907a3,e0b248e4,a25c1e7e,54039440) -,S(16f086c6,c2850e49,8f8456dc,eb33a692,a4dd613f,b2f9564b,6dcecb88,4f4e5024,2e152a08,88eb1188,3448ca68,25a65034,73cb5ece,c9ad5df3,12deefed,279339a9) -,S(7589bd1b,1f0a3577,5530f0ae,446ea275,4439a51f,66730950,6eed6177,65a02492,2d840e12,d3758153,1e5771bb,14d3634,4076fc3,630c389c,ad9765,98462d49) -,S(18b9ae40,cce63a51,3dedbd2b,c3beee9,a80cc5f5,a26b4446,9a0326f4,d4930890,24b86a4d,d5ed3c44,71b57138,2b270d0b,9e0032d7,8e0ad18a,cf6a4eb9,2a2690e4) -,S(8c1f74a4,acc71ef6,4030db5d,14be8627,94e9ba6e,102c89a4,ccfe8a8a,d3ebb48a,a79f0119,98aea529,1e3ba735,c8b26c86,1af1c119,92d5dc94,16eb1673,9245677a) -,S(8d80592d,36bfaab7,5b557ba0,d03825b4,2c0fca08,8ec7d046,5cd2c203,c2bfb080,3e479487,91f27453,4d0a1bd4,a533fd2a,7671a654,10cd7a51,859b466f,151d3f6) -,S(eab0bb19,f477e158,ec85046c,f2c56777,f36782e9,e0452770,f7125765,670ca248,a27d7081,23093af4,daf55e56,32ba071f,37f0bd64,3f189ebd,70074cca,7cc04640) -,S(ff0d0dc9,ebbb2fa2,6d3b249f,d5260ce9,9647e1d,db48799b,db532c6a,2a0a039c,12b0f6ae,7f161f8b,ce1c3505,5d9b760a,fad5b0f5,66211023,3c43942e,fab31fa9) -,S(d89a3235,71dbbd1b,92340346,8b08b7be,be22b320,3ee6b0ad,42a2aa96,3837d526,25da35b9,9988f167,3108124d,9e6f6f1f,db4a0490,5546fb62,146b7421,36e3cf27) -,S(f150023b,f01cab2c,433cdafa,86751f7f,13ffb315,55d34a22,9ec4c012,925b43fd,31f70e21,26ac896,6dc966b7,17a9e483,8ac37a6a,2072bf34,1a9c3d33,3ac7a9cc) -,S(d98ebd3b,2d580978,72ae9d5e,2c2cd0da,76f442c8,e0b4470d,9b3ee019,c83af2a8,9ed5b6a9,5a061970,34bf9873,da6c7224,930fb358,a514c823,e0017c92,75dba3f5) -,S(55b62d85,833a94ee,dfc2e313,df3ca816,8173533b,fa77d827,583fb01b,cbc3c746,9f848773,cb95af7,b79eb921,19a7a139,1f4dbbbf,44c81897,15bad111,364a835c) -,S(dfaf4d76,fef73f93,44c69de8,f6c1c3fc,ec759c49,a2a7a1ca,2860fecf,bd718de6,ac4af693,44e2c287,f6409f94,c36d93ed,7fba1f15,195bd971,357d3142,725a0671) -,S(84a444a3,4510922c,37420f29,a16ee22b,a7839f3c,5810cbf8,38b7f3e6,c5fe29da,ef733d80,2215c12e,143f420a,673069fe,6e89af70,cbf975f,a1898550,1114f06a) -,S(d7c84e11,46c87008,3ddd24d1,296811a3,2c337749,83892548,6291aa53,a72212af,b187dd58,a3be40bd,c3d357e5,480aec61,9579b2d1,4d79745,f84cd406,10844ac4) -,S(fdedc27f,a70b08be,f3a9f616,575072cc,c7fca4b5,71a2ea06,9ffea788,5598051d,fe9b7b1a,1c575a9e,354d279,ba7f4de2,53f6f54d,e7245fbb,3ec462a4,7b9bf9a) -,S(cfa7478a,d3f2cc6a,92022b35,58437b3,f950c250,4d96b9a5,c2d5c795,ef122e77,f3e48dca,e9592835,354f8eed,ffdd4c2e,2ad7800a,3da863bb,158945b2,261409c4) -,S(8e9157f8,3fd62097,70fb7493,d7678fce,aa1584bc,d8dde3f8,337dce8,ee0eefe2,6079ba89,8c05dfb6,ba4f91df,4b4b229c,3322fb5a,44fa988a,c8d9f3a5,3a05351b) -,S(7bf5efb6,103eac30,ec4eb80a,9bddff22,9d422ffc,6a7f9dfd,bea8b928,3116f75,efadb659,64791edf,e5935554,25796141,2cba4b4c,3553fe67,ba138931,3ba71a3b) -,S(f5ba02b7,b7b2c2d2,68c7b1b5,37697079,690a13fc,89d1d53e,85f27820,d0e8df0b,66316d26,b2640e41,bfc329d1,9d2d4430,a9266b64,c3c793a3,af7f1515,9e465485) -,S(5eaacdf3,dceca4c9,6d2bc3db,f22951fb,87c10da5,f1250828,4a1498bf,ff004475,cb3db3ed,9721ce09,16985d40,4831cd04,b38f5810,977ea106,c8c25194,ad1f122d) -,S(1cfe5c17,b8d61134,53552ba6,ad513371,d1320abf,4fa2de41,77c5a768,a64a5554,53837cf6,4846b887,1e64a2f7,e319f740,99bcabe6,7a0894,5edea46b,fd1dcd5d) -,S(92a83f47,8a2ccc86,1cc91dd2,a1210fbe,286f47bb,44e46880,5e21f0a3,7a5dbc10,fee35c65,fcd45b02,f8270b8b,c198132c,cb69ff9,ec35043,684f54f5,c999de94) -,S(172285ba,d5d539b0,f4d86ea1,35bdb79,73c07ad3,24bf5dd1,4f74ab69,cad277d3,45abf940,cf356364,e0bafa15,cee3e20e,cfc29040,288b4897,314c22f9,aaada654) -,S(ad17bd53,92e19bab,8554ae08,bf9158dd,3126ce81,3a05c32c,7646eb73,cb164762,a129819,1c833987,775d4f47,d9d70d4f,8139c651,896f9b94,e164574c,8d065586) -,S(10421b3e,91a4a89c,1f6ce9e9,13e511c3,c23fd307,c4064a12,5267cb31,2ebdeb1c,539bb5d0,9e49f0fd,186b8a51,73118cb,98569700,dac77cc1,92359286,3aa53319) -,S(c43adcfa,78152a3d,dcb9eba6,6632aa5,2e8476de,1e0e30ff,39735b06,21de5bfd,6ddd09ca,2122580b,847d04f0,5dacbb7b,1e81c6e2,6057d880,1a911a55,9cabdebf) -,S(f7a99ccb,603a58d0,4c6b9e50,d9e7d988,14434f1d,92aae27b,5c8d9006,98bf9a73,ccdfc244,76f4393a,e96d6809,1cb74130,5e62934c,cafc9b08,78a3a77d,a71a7ccb) -,S(9abc95bf,70174ea3,5038f44f,4a2ca9be,f602d516,9d249aac,b3175be7,e09c826,6cfbceed,3e71f8a3,d427d2c9,f8cedaca,22a9fedb,4cab7763,617198e0,d7adfe0c) -,S(8a7ca893,35c84873,ecb4af06,b493c9cf,d7bd08fc,d0535c5,546bb9ed,5c5d8d82,2518b372,90d3c08,72f1ee4e,54144799,209ae3fe,d2f285ba,7b00193,21e31bc1) -,S(70c8e379,8649628d,969182fd,862f8d4a,b39fdbdc,c246fb79,ff1c9227,a64d1c3e,c7931ad5,27ec0a4a,ec297d9e,fd56208f,936c9517,4efdb86f,7f50e321,26ea3cbb) -,S(d783f6b4,6121ee0,71ddcf61,b4808fdc,934a82e7,c185876b,9572d628,31002121,aa92bd84,14226949,9e107c82,b9a64898,28b3ed15,694ba62c,a031d98b,5e9c7fbb) -,S(c1f06a1c,29abb43a,cadffbb8,7ea8e4c6,b7592795,9c778758,1a17e4e7,7b654c18,1dae0de2,f1db42cf,ab9b0e7d,9e5a098f,bc102470,aa418547,6cd1925e,fbecdbf0) -,S(2ad74e11,3205b587,866633ea,32172662,d1498a27,48698724,87b7e62e,52cc5105,c70c7507,de1fa1fd,625aa7d3,755c83a,b5c85159,4b8bee10,5de45da0,d0ff779e) -,S(f490e9ad,72246a46,6eb74e23,371c4f57,a9e32b57,74ac9ac0,3d800978,d77408b6,546f367f,8fdd1687,ba6ef15e,4c258507,77e49a1a,8b449fb9,63a0f01a,a9dc3d6a) -,S(20502891,8357b697,e05788b0,55f8bb32,80c431c5,de07055,3f123373,981d6149,39d040e5,44110e22,58da6771,2852fd09,9489ee5b,5c77a777,7966abd0,468e3b0d) -,S(6e91bb8e,c169a3a3,eef59915,d4de9296,e4b78299,e038c5d1,bb001eb2,f86eae95,d2c21297,88f8c9f1,16434063,a89fac48,45305dd5,d208c887,2ae94ba2,80877dfd) -,S(cf2947c8,39fc40b0,610d0d2f,e1e5ad53,39e7d0ba,9e7dea01,90678bb1,6ba34905,6145a70f,7f0cd53f,d758d7b,172e875d,8db00f6a,131ec7ba,aec140b2,3f37c63d) -,S(b48f8387,ea93a6c8,561c9b01,ad32a28,1c8db1c1,ac3c6864,ad161874,fa2366f1,2cab333,cbe07d3e,26fd971b,3609cfc8,9f46bd81,df84276b,375315d2,7a2d253c) -,S(7c4b5f66,c572d34,e4cae58c,696fd43c,30f6054e,8145715e,f391eda1,42a1f827,3cbe264f,be125af0,3907c5fc,c61232c2,d0adc2ad,5f94f3b0,8ed32ad,99843d97) -,S(e5796368,d4649e19,6227f989,78758d9,8fe24e51,f5d5a567,378a85e0,850d86e8,74bb343,c9a69128,9ae880bf,67a7e4be,1fa111b8,d6608896,46ec354e,f6c9d4a7) -,S(dfa1065e,fe83e9ef,c19b8841,6e3ca5d9,67c1ab26,53c7d650,9f02ba58,fc4d637f,22d2567,eb0237ba,2f270e04,685e5352,e23fdf19,a2aa0a23,1ec83eed,ca5042d) -,S(2ea1d8aa,d436c332,8fda3ce9,8e710b80,8f463844,cf131f2f,2347b37a,928af132,33fa7e0f,b8c2ad10,580a243c,ccf2a4b2,13ff9620,7a034432,8fc61f31,e98dc4c) -,S(12ae1451,8122af3f,a788298b,5e59df37,ab6a976c,f8a931b4,c0a51de5,d567253f,85ff1dd2,b3271d2e,de2fa732,9e3f0a5a,1c3ff9ae,b55555a7,926d31a0,1d24877d) -,S(fd46e1ef,b588af1a,a72b84fe,dec75a3b,125579ef,55ef8270,85645930,95bf6619,d06adc6e,ceb6292f,60c7d477,c73a2aff,342e6b7a,e81c5ea4,f57cb7b,27a51b17) -,S(ed7d93e,b8c0d1ef,1c49e1bf,be22acd,c7a17946,b172de61,4a290d0b,7f32b52b,4d0ec30a,39a81c3a,f8f6668a,742abeb2,b5552284,a68ce246,f368ce9f,b2303ada) -,S(fccfdfa5,cd0e79a6,9febda81,475c06dd,58517913,3624f4dc,9d808b6d,e9619ef,79b9040d,11d09bed,f89959c6,992a9636,ec62324a,d60e1513,9bd2441a,dd0adf49) -,S(831762b8,6a9b9afe,d2a044b2,7bc714cb,16823ea7,22b44010,a57a5564,4b4ac477,147ae062,8ef3bfdc,b48b3f77,f84dfd77,2754c1dc,a626aff6,9c3169e4,9956c708) -,S(33448c01,a84d5303,c8f70adb,bfe0ccf9,f92cc461,f2656fb3,4903b99d,4ef26b01,e5727349,ae8ba61,c8ca8284,ee7f906,208ad03c,6fd7c95f,736ea541,ffb8f2ff) -,S(920a1261,6ddf1304,157ccb8c,50ebaf6d,60df85da,b19b24a2,48254cc2,7d215a6,19e4d4f9,cc91e890,3d2f7a11,ca8c0b97,e2cb671c,e0c4ee36,9f1a3ca0,f28d0f4e) -,S(1df8ce1d,3e370b9c,3f60ac00,cbac25c5,458385a5,c4b926b7,fcafe62e,536b1ba4,344df46e,e3635079,52af6160,2729094e,3fcbabf5,bc701083,533e7e60,5099a92b) -,S(7227847d,abfe26b8,13c18175,c37a0526,2e2243c8,d80d93b6,286b2881,d38b7b72,bede79eb,33da3cdd,95289c93,46165cf9,28b5aa41,c46b364,622988b8,a7973d24) -,S(6defba59,e1218bfa,b02571f8,ccc84104,3caff74f,26d8d995,9729f292,eff7fb8d,4d7baa8e,21f2fbc5,96f770d1,bd34e77c,2c188c05,5921c1a6,95696a8d,4c340a04) -,S(c667f4ef,f5127d24,6b31ae02,2adf53be,8302e1a,b631a0f9,90b16051,e02d6bd3,3d7bce76,ce11bdf6,fd4d822c,37d746a2,f8de283d,527af237,3e80c4a4,dad34cf5) -,S(ed9e8674,441620f5,990dcc24,23a2ab00,6fbca1b8,e6bb3d23,55c2c72f,ce29d866,64d5ed9b,b4289a2b,b81a12f3,30930dee,7c03dd71,1ec361a5,8297c22a,5806ad30) -,S(86a36c57,e6b0cee0,33c00b25,66344ef3,219e57ee,ac452ea0,b0eeb98c,3176fb24,b4f4bdda,9e9b58df,4e103874,89592b5d,b147b43e,79a1af25,135e8db3,eafff739) -,S(2e237784,45396ff3,a0e105ac,ba151e3d,fd02bf82,1de70e04,33792280,bccca913,f736539c,e77983f0,610464c4,3bbcc904,f43726dc,a336304f,c0b716c3,67148551) -,S(ccd3c14c,7790d936,5226dbcf,11a0bc00,9db88a87,ac2d68c1,6899f980,20a1390f,b240b35f,bd6d5dd9,f33bac2a,f1899320,f8a9cba8,7df0a67,81cdfdd7,1c3af907) -,S(7713be7f,988d7b1,c6c6566d,558978d,eba4efad,b82761b2,17bccd87,3637b018,8fb91a6f,a9d62baa,2eeef7c5,15fab341,c75f31e6,64ee7d94,70db34c2,74475781) -,S(5485ad60,35dcb3b,9520acf5,6b0855cd,34c739ff,1c59798b,1ab667ba,a4982b02,1dec6c7b,1e7c14ca,743df62e,589311bf,57cbd455,e7dcbf9f,cd439962,96a90f0f) -,S(a597503a,d3be484d,1d2d1cf,c4e8540c,411bd201,f2b05ed1,89c9a3dc,b0ee0f19,35113e7d,38001199,1e2cee66,4dbcf490,becbd6f0,765c94dc,e2855ee3,b01113cd) -,S(ba91b251,abb130b1,57dd07a3,dbd2fd91,1ae24937,80c8046c,b94de57c,dd91ce4a,cfcc2080,500aedfb,a69f33f5,4f642fbb,8377420f,e1799dcf,e1dc3593,d3e1f6c) -,S(adfb5a58,83cc7bd3,c6fd3386,95c86414,5c6d2f4a,603fb2e2,fb045bff,86d324a4,16574ed7,45d82dfd,c50415a1,8c30da91,3a525753,cc975722,22a5553f,7b0cdc5c) -,S(1084914d,dd710a5c,ac854b14,10a4be35,ba1f13a4,e0fba3e2,9d94edcf,a3561ae8,653ca135,3240ef60,412ac6cd,adf8e664,2f2b74a3,5908c3ba,be6dcf85,49c25e99) -,S(704aa271,9af38b14,17a8abe5,b881efe,81876a6a,f807833f,133cdcd1,6e6c6f7b,a6fee2b3,48c1180b,c48726c9,be2a1a41,11395af4,42ba7b92,63f4f66e,a3769e54) -,S(46048cc1,7f5d2a86,5c1f5734,893c6683,fe68b0e8,942c9080,51d7b836,a8aec289,d85cec30,89a8f77d,75bf9c6,bb4f8a33,2e766834,3841b277,a461a079,8b288efd) -,S(50f1e6be,315d3b21,636781ba,8598d2f9,7d04ccf,5ba1fc76,3d547657,77fce9e9,f7dcb7d6,2057b9f2,8cc24975,9dc9621f,25dd0ce1,47e00db7,d095fb0e,ee6b0b00) -,S(7ed0a244,676655ad,10efa03,7748d49e,944df1f3,5bd46d0,3b7ffcd0,a63501c,a8377a65,593f227b,446eb266,936ae475,e9b3ae65,a60768d8,2690d0f0,5c18c21) -,S(d039ca1,ee66c2cf,611c431d,cff1bd2e,19b29d3b,b1f37342,c29f4632,4febccc7,db0d0d82,14f4c661,629ff5e2,4cfdcc84,6e652ee1,15a6476e,7813104e,696d736f) -,S(c27973a,cc55fe2f,4531768d,94cd4a0e,8e36729c,aad61579,7beed810,a7b092b7,cdc310ea,b36ab246,c56d5402,9b9e3314,878e1f1,ff7520db,43917a14,1f41c99) -,S(36842942,cce3c683,25472e48,de202d15,ac14a180,3a2dd84,6de0c33c,6446e945,5000b3f8,19ab82fa,3589db9a,eed5609b,208d95fa,ddaebcb,57403b96,7b8f2f7) -,S(d1aa195c,338621b5,19ff3a8c,55abb454,74865ef7,85e0fd7b,c4554ae,6d62d0e9,e7e1dd33,dc293859,b4634576,d8840630,832ce773,a9a8bc88,c2e67251,a7b737a8) -,S(4f423d32,607439ec,366bd6ff,5766ec13,a59b2c2a,8cd008b0,489f267f,5c0f00f0,5e3c7e9d,7ee94c15,c048e6aa,272c888c,b6c3e058,4b4f4ee,f5e1d787,a4e7a9f4) -,S(6bb1c680,ff8991ef,17c0859a,9b5fa9b8,ebcb9afa,af7398c5,9101bb99,7f06c4a,318da775,d912ae5,d17c242c,97615c5f,217005fd,535b839f,189ff3c9,8669a253) -,S(14095d4,4713a46a,5fcb251c,9fbee2e6,bc393423,30303b8b,d0f2d09a,c0096f68,647e000b,3660b374,959e632f,6867c7fc,1c7aa4fb,b7f5593,22dcb2ba,e604a2b1) -,S(12112bf0,346e9c6e,4a8f831f,6c087876,8943191a,38e9fb83,8b2613b0,4b5e5323,e4149ac2,cb4533d9,4c3abf62,aee4dab9,faf64065,89cfe10e,30a42986,9657a3d0) -,S(f99360cc,c2ed4810,d80974eb,eaeb59fd,4f2197a7,8459729b,4f75c370,8bca5738,b92a2f5e,86d77a8a,c2c1b9f8,6e1971db,a06e4414,935020db,c0c83a92,ee6f1cb3) -,S(2dee5a4e,c81a3ecc,4872112b,be53f51e,64ae779c,49488567,a654e806,ea809ca4,1e2ea8a1,df6d47c1,c0aa1bcf,ffcf260e,bdea4d63,934ff3b1,bcb1e1a4,c73d4954) -,S(5baa6a2,139eeb78,f49638f7,b0dc5010,b73688d1,bbd746a5,f2382c7b,d461229,72677383,10a352f1,9f2a75cd,9e42509f,b08a0ca9,60154693,cc01d595,25dca81d) -,S(a3f77eb9,321d44d6,b774a6f3,b1319e46,f60d102c,d96e983c,8f8568ba,82913d70,f93d75df,8271e70f,1aa38630,26bec1d0,f6db1765,77470077,d3fceb8e,5c613a05) -,S(46ba66b5,fa1f9274,378fd62d,68ae9f38,8588d766,ebbe97db,72f9084d,c7f2cf08,5473e24,3078b8df,92df9b55,52ad5055,f44bf7e2,ecf0785b,72db5dd9,238897f9) -,S(db6a0246,ddcf0260,b2b415b6,f551fad0,bccb15c,ca196af4,291d21ce,ce80dbf2,396cd446,f93e1c97,a56c6f6f,63cd0966,5f88856f,e75e1c7e,a985917f,28591d3c) -,S(b82f8d1c,a7a298da,3992c4e5,8dba1b0b,38187eb8,66992e8c,5cc1c834,6e6c8fa1,4b0ae76a,f9b0413c,8d4fdbdd,db767c6a,b1b80589,533e3ee0,28eb6036,1483461) -,S(446e96a4,dc9264af,e9cc6348,aa612861,d106fdd7,b7ff94a1,82e0f018,c485f000,32dfe3d9,21593a58,1fe23b7e,ccf677bd,2771c40c,a612a507,c8e33df0,99568440) -,S(c86f10,7bfa6dcc,b9f00ca3,465049de,5c8a3e6c,d85bdfb8,1ada1d39,303a2eb9,e64f7066,7e910814,ae18c6a,7323474d,9dcb277e,4aaa7ed8,88bae4ae,7c34219d) -,S(bed8eb6e,cda14299,e4cd94cc,202be7b8,9201c2ab,302a5cdb,83e5f5ba,db6cd710,15736cfa,b375a40c,5d367b9f,6692746d,16a1f03c,20941256,708489a5,5d411aac) -,S(b3efa7f2,c5f6ad10,41f171b5,ad759480,665e0a52,de82a881,da1926e0,8f64d38f,3df63c84,32761a24,eb0dfa,ae98e034,b6dbd361,3fb53ff,c535fac8,ff1677e6) -,S(b0460da0,cd869b5f,235213a8,49e143e1,8fa9afc1,651ee921,ebdc525d,2715cbd2,c11a3ead,f3541877,ce73b4c0,2b57b299,46b4725e,cf630eee,865bb121,b86fd7ee) -,S(28b09517,a17452be,b2c19187,12d600d4,b4969253,a7d0d52a,49cec3ce,d73bc071,36696708,73c7591,11163518,40af594,40ffd6d0,690ddae7,fce7a43d,e920a326) -,S(521becd8,192acb58,7ae76b7,c0bf17fa,ad86afc,47157753,6b1a51b0,fbb5f136,648a54c6,d7aff13e,cccf399e,15451682,ee06710e,edf32669,1dc7fe83,75ac858d) -,S(b7bc19d0,b7fd9d65,26c9bca1,b587d84e,a2a200a7,76d39082,368b761f,79f6cf67,5adefabe,e0d0c8cf,4252c29a,773163b6,4a1e9ffe,ffbfe3ad,2f796e8d,1f70acae) -,S(e48e3be5,1b6ca8d5,41f0c241,21558cec,66db7b6d,c13e7114,dc931f0d,397aea8b,dbcf6357,5b16e2f1,30f064bf,ff12b465,f6cb3a3e,f9f74431,4bf41e7e,e0f28ac) -,S(395c6de,71c692a6,a3247596,8e28f2a5,4ec795b5,9759e890,9b2f4290,9f455751,ee5e0118,3c7dda2,c1eed4e1,5aca155f,b5b097e4,499bc3c3,fcfc2c85,a669a13d) -,S(28938ac3,b1184399,22741291,9c0fec36,663da3aa,8a4e89a8,1a66052b,ca808d99,4ae8de7a,b1ebc1be,a2beadb1,80cb9a10,da168295,ba1ea5f8,310b986,4f174603) -,S(5c0f618,95e88cf6,205472f2,3e27e853,be3af64f,d0a376f5,8523ee6b,5248f5a4,be5c3c55,cd09ebb3,b7363456,9fdb50fb,8473e3d8,3441e624,b41b1c3d,e44be51b) -,S(abe1f7bf,22d0f733,ed28e125,f7ed05ba,ae2e8f13,1eba2ec0,1554dac,5e3ca1d7,2a5a48db,3de31f6a,9708ffe4,b996cb33,e553e6b5,95aeaffc,918aa2c4,1ab0ab4e) -,S(c3042427,57d370b3,79124907,ea609129,5f1dbeec,442a6349,bccfd29c,e08d8be7,67a64eb3,3e0fda75,535b35e2,f8c9811d,528959c1,29e8f144,8bb75ce9,b1868934) -,S(65a59946,356f219d,77af0b6a,9e1a43f7,3152746,6af41c21,c81532fe,3140f5b8,64e7128d,5d3e4fa0,518cf27f,c070da20,1692b059,3d84641f,2463a61c,74f35918) -,S(6c7d2e3b,48428c87,46b066f2,bb99da10,60311cb7,d4dae19e,de2eb53f,141413e2,4ba47bf,c2e7c670,4de2864d,1ed7b383,286292fe,28f7c7ab,2a664bcb,6cb7e3a1) -,S(dd257bd,b99c89c2,b47798a9,bc93ff57,5655797f,a45399cf,44acf58e,93fdcdd9,f8d670f2,a9207f25,52e7e0d7,14289103,e8194f81,6390e0cc,1af2ae36,c1b3e4af) -,S(2516034e,b8ddc424,42952b8f,acd47c62,6827b87c,b08f263e,b2aab5e6,ecc23d7b,ad8e8879,f5feea07,ad3545bc,a731dd30,bd2ab534,4b486826,433c75a1,6216ac9e) -,S(7e723054,27b591e3,b19834b3,8211edc1,7f075215,6591980b,907dce0a,d934246d,5c91fcbb,d8c184a6,f21671df,1098760b,2506bee8,e32474e3,3b080147,4e63a71f) -,S(1b1f9d16,ac3c0d2a,4b87691,45a6f6bb,8d4fb57f,ef9df33e,72b5d399,6dd1898b,6442bf1e,5ffe450,b14a399e,16241a5a,15e94453,94519bd1,24d0a67,f35b4b1b) -,S(e0f1fa4e,57cdea43,a3b9f671,596631c6,65b5144d,93c51a23,e9006c63,fc872f2b,c83851fb,54890d14,2f605617,151dd47,74f9a3de,cd27d864,a49c176,af32e564) -,S(ae95bbb,697c820a,251a3667,b2a0a078,40efa027,99d7bd0b,3e9a12eb,32728c3a,e0dbba97,280096d,86ea4da9,45ae509d,1140e0dc,7b803f10,e685b148,6baebb41) -,S(fc8ff885,d52ef42c,1fe529ea,853ff8c3,afad1ae,6e7f1b30,69e34076,682aed31,525eced4,b26e8f62,7b904f1b,3356d01a,9cced71,432ac850,433e0a64,b1e3dd14) -,S(6613136a,459d625a,d5b5753,3a965a0c,ed68d63c,13652546,c629cab3,32c8e810,10f29ff8,24d30a94,b3d732b4,3b168bd2,28b4cb01,4012469b,93a9853b,655b65cb) -,S(45085915,7b683327,c76309b3,96ef3b63,19dda841,f6be1b91,f24f5a37,ddea56f0,b9a71446,584a88e4,6a155e34,f08d5a6b,2b6ebbbf,b4b1aa12,bbc7654f,91956821) -,S(168ee3bd,8f10ba0d,deb82576,cd5e1711,be58af4c,2274464f,e32f3f7,7c8a4325,6eef1e63,43ff409f,a916891c,982f8700,465fb184,5820b886,68b74202,6678b34c) -,S(b3191d97,763c2341,4eb4db8d,eb2003e4,fdd86b4c,6077931b,71802714,ef048c04,b4ac3085,59f975ca,be7d53d8,3ebdd5c3,ce6860d6,37710a04,f885a83c,c2152edd) -,S(da9d5c5b,4e73dc93,3c72acca,1e93f4bb,3ec477fc,f201096a,51ea0226,3a2f8738,7fb6a2da,65f966c3,689b93b0,d6366511,400c05d0,8b0a15b5,b4b3209,a812f8aa) -,S(140e55d2,a7e75678,1791730f,c526470,8d1cfaa0,954e215c,1e65bcc,e4b0dd66,4bfba0d8,63ea2597,91e470d8,1ef36318,87e2d5e5,c897918b,ce805941,953d5b3) -,S(15a9ccf6,4b95cc87,cee9bd01,bfe3d8bf,b438f7f8,66344a1c,f3f399eb,16b173d8,4f5472cd,bdebed25,605e51fb,f0b31a93,5d0ba59a,6e51bf90,e0363c8d,9bb33f3b) -,S(e86e364b,6776701d,b7b3d3d8,fad181bc,c7ed5e91,2d0a888f,814caa3d,88af6e06,22fd460,afc040d,3e995518,c6286989,24a466d1,4a624915,f834c357,4dea7b92) -,S(3c261a98,cd25f0db,2321134c,723ebce7,b1f81d3a,a6d5bddb,fc282fae,5a500eb6,2b8d2145,5e498211,8a4b6ed7,ec96a66c,4027a506,deaeecbc,45535fc5,77abd9c1) -,S(49b6a811,4d55b517,6cbb1f6c,177aacfc,368c3b5d,238300b,d66546ed,f4c955c8,d1b124a4,9f0e7c1,6b8e001,7f1b0b2a,ab94411,391d5bca,5b535838,a3815b94) -,S(6ec8e861,f0d3e5a5,3f9deab6,20cc4b81,6cee801f,f7a43f71,f34a8dac,c525f6b9,42e0545b,68ccafbd,3309c4f7,eb6b5eb1,1e01a871,c63fae27,782001ab,a6dcfd6a) -,S(7342b341,59aca5cf,d305a2e2,a8f14da4,4b527e57,4640fe1a,c08898aa,4595b9ac,b5261302,d2442ee2,363969a8,4ea61281,27f64f40,ac86dac1,21b5d234,53160124) -,S(842b30bd,54ef350b,65dcfc43,df26967c,b2747757,a609c54b,687d30b9,5a686fa9,4ffa9e92,2caa36b9,ecf31f63,f5c8de57,7d594f7c,71e7e77b,9cc5ac83,f336ead6) -,S(2dba435d,d589a7c7,bc3fb60d,495757ef,7c13bb0a,3e91a153,9998e04c,19f94862,c440720e,a4b23cb9,d238eca1,6775e500,931d3e5c,7df853ed,55cd4889,5e8cc0a1) -,S(9d1e8524,8f84ce5b,2a75a457,819390be,bb284fbd,3d035c07,998d3c45,c73bec02,8e40ee4c,c935ccac,2338bbc8,4a8063f3,6d62e8cf,849bff40,1298074c,94eb9ead) -,S(d2735ac5,d1fba75b,d4f63912,11549755,9a7f8623,62e25cf4,e76562d2,d8b441af,bd2ac36,19f9f339,77b7cb0e,5b52f3e5,b4ade86d,1c9fb31d,a1d8fb36,7dafc081) -,S(b0130e38,f46cff13,ad1a68d3,15729395,b27c2b96,e0a957cd,ca63adfe,b0a3e11a,3d9f697f,4a61401c,87eff844,3b11776a,610f1516,4366c1b5,535599a0,c6aa3c4) -,S(e0aa062f,15306af8,b662d8f3,3b89de8b,f59faa78,29942caa,ed82e668,35ec76a7,c5f5f0b5,6ea77304,a5dffb8a,cac98387,34305b54,25fc6181,79a4457e,c15e6f2e) -,S(ed1626c1,a8e6d1c9,187e15c4,ae9875ec,2156d685,997ac413,9f44bd0b,19432d5,3c0d895b,9dcb4a3f,4235e531,ee7373f7,7f0fad46,c5938d7e,69d50429,71f0c35d) -,S(a2cccc31,4e18fdaf,8cc25aa6,74c974f8,664744db,86e04be8,431d2ed0,4dc92833,b6410e49,d6d471ee,d20e5536,8672f5e4,2e1b9c88,c06438a8,46c3a74f,c759d71c) -,S(5bfc192f,db15f62c,4af19119,b2d96a88,b3b24e06,3d54b31f,a35f675b,f668bf27,46774374,acb4e140,90431bb3,9f62a38a,dbe0dc62,4021e23b,6099e198,47d99051) -,S(66842a89,da73c404,32a2e553,97efb009,61eb2155,886ac90e,97dab5f0,9227028,3a8e83c3,511ea048,88d2dc9d,f1016cd9,da171bc6,89c9af4e,90b18091,21941de9) -,S(ec823197,3ba95f98,d45f8991,3ee8b92b,e3a4a84d,d59342f7,1810766b,cdc516e8,532d3c79,f5113f4e,1973bc88,2a953b5d,77d5476d,ac9972ae,f1d25e19,ab7206fe) -,S(3b65fe78,bc516176,aed5e5b6,5f3ed39f,e8e8e26c,32ab07ad,1ac2519f,72fc140b,856d36de,5190eb9c,13f7f976,466f95de,566a1fd7,314cec1b,9c9f7adf,98208d98) -,S(3ac0eca,51c43525,e9e545ce,83fdd009,f9f31eb3,2722b945,18262036,d18cc346,dc72018b,c3b2a4cf,3244ef31,340e0944,325bebc8,b134de50,9ab3024a,a213a7e6) -,S(4929658d,6c50ece6,edd2db7c,217d9be0,bcdac8b9,bb50972f,fbe53a04,2ee23508,e5aca42c,61aabbd4,b8555980,a2328741,6dfc8df8,d7a10c3a,7284bd90,aacec38a) -,S(9d16e76f,4bc96492,f0e9e748,8c6d2297,7830e2ab,491a6278,1d60ab5b,153a6291,e6590f00,e4ac6922,5436318,9770aef5,5eaa988a,44e9711,da7266ec,895ac7ab) -,S(b0649c4a,1327e7fa,f52a9bbe,7ff97add,4e13b36a,27c0676d,5e09b2b8,1f5df94d,991c8316,a6f36848,e072a080,77f75a8a,d79fdd08,1a606d12,b355c3c,3891acdd) -,S(8f194a21,f6303ded,2c9ce51c,44a4a16b,eb39a8f6,5fe13c9,6b7c12bd,b052235d,bd1df3d0,c9af82e2,545afb23,e9a2dc85,c635172c,edfe70f1,bd755d26,9730739e) -,S(1da71a97,cc7a4cd9,4777f6c3,dd5e665b,3872b721,c6c2262a,60e87f1d,efe21ff0,78d17a41,39036e1a,7af2b9af,1273afeb,a4d30e8,66a3e6e8,7f0d0468,4be6a06) -,S(9fed363,e493f262,d3efabb1,c52291c7,e04e401b,b181290f,7a37af3c,df86aa45,130cc33e,e164adff,bedb1827,6a5c965f,53a54f36,90dfcd6c,b3fff836,703de729) -,S(d166eccd,221c3568,199ebc38,fcbb6140,7a601a3a,c1e7a98f,ebb75a87,a7a1e49f,262222b7,e7c200bd,5dcec562,85485434,b0628c7c,ce5483c9,93795f76,a072f06e) -,S(e7853cbd,3e3770c1,cc307839,294a2e8e,b998a56e,393435cc,2930920a,8ddbe0fd,7977e6ca,67147cc4,965d2918,1023c3bc,cff1e7b1,8fa4850b,80a140f6,980e5a8e) -,S(a8b0feb1,cb140201,2bea3cd5,6b1a1f02,51036ce7,423f511,480f49c5,6227a17f,ccd7c3db,9d3ab6db,6cceedd6,d3801c8f,67afe792,c8977b5,27c9dcfa,75ba8a9f) -,S(57ce5dd9,e1815755,31e90579,74f58b98,6d02e406,a846ab26,c9059f6c,56d617d7,cc34c090,4399f316,269598f8,aa8f9aed,829f61f2,5efc9bc4,e851ac63,fe142d14) -,S(479790b6,4f60fc6d,befbbc1d,365ab3e4,8077b6c6,cbf02f2d,6c8b986f,d0f9c858,157f4982,e3581925,dd25382a,e3e48fa6,5cff911a,95e9bf43,5df8b356,87f2f9b) -,S(55abc7b,1ffe0a41,2181b622,813be76c,8ee0a0ca,3cb37b1c,cb265087,fff17c68,bd134249,23e94c53,4cf9e603,a1dd259,606272bf,8283f2d6,69bedd4c,a971d99f) -,S(6ca7e032,8bf5d67a,b804d431,e5f709e,bd3156e0,1d4511da,1dc67394,24d2e659,c428b133,f3683909,6551c2ff,2f870d80,d80aaaf4,6d2b1a69,7722057,5eca2647) -,S(60df19a9,83e9086c,4cbd20ba,fbafa8b2,346ae4ee,9c1ad4dd,99959e91,2df530d3,dae7b854,29f817a0,421c2f1e,e4e8e4d,a09d60f8,84701e31,d7a8b7b0,3b79cc48) -#endif -#if WINDOW_G > 11 -,S(6f18d50e,5ef5f2ad,bad80ea1,c59a3847,5c22ff05,6ba52c7,e1d26d6d,d3686bce,d1d7ea0f,a166efd0,facf5c83,bc3786e0,d3f3405d,5b4578f5,13a336ad,f0d7d7a9) -,S(b634dc9d,5ed51336,4ac9569a,8ddee9d9,fcdfe00e,65e59233,b3be8a07,2fd949e0,d72e46e2,c61b2575,f25a505c,bdc3456e,fdf18976,6562a1a7,e86d036,eb31db69) -,S(5a37fcf0,2dba24f3,e6646171,43dbc5ab,40d91983,69f5cf0e,4fc566fd,97445910,a960d1d8,13f8746c,662a9582,614c7847,33e6153d,2975cb59,c3342463,75c69d1e) -,S(8aaf16a7,37318032,c60201b6,b196d8fd,eeeb8f8f,1aab29e1,1b83ae1b,f112661c,c461ef56,66a3a4a7,563cc0c2,845f2ae7,6d03a795,987c615d,611bab48,ab9a8e44) -,S(456f0ba5,a05f15ef,d93e7f49,e0729c45,1d85a693,42c2804d,9cd4b8ae,af5e3434,a680f4a9,99221a8b,7f46da13,13041e16,13f616bd,84b9135b,b0f7ecb2,7311cad5) -,S(f89c36a1,f1905409,75f146d9,31e12cb9,4bfdc90f,a178970a,9d0b34cb,38f5c741,3b562c80,58e31b92,a1186615,9c1ffa3b,4b1df38c,eb4a1646,579d2375,9c44099b) -,S(7f6beb11,2e1d8600,d8c4903,1d69cfb4,e23876e6,32f30428,9d2c2503,41f3f76a,a1937407,c0925afc,be994b9b,51627b98,8d98ed6,e8cf6fb9,cddd0ec,a4ff4a9b) -,S(905ad0aa,b585c7c3,78b7130b,ad1d5001,1010f543,194f40d3,827dc606,12d73511,bfce0701,c3ddcd38,150130ae,e91d16d4,a447821f,a2e098aa,b83b8025,b7177a9) -,S(f559c2d1,62122fca,7201e7a3,b6033d1,e54187f4,7550b2ae,f1d51521,f7408b6c,3f10d622,dfd0eb14,7f6f04dc,43108273,7695ea42,38ced7f2,5dc167ad,34154481) -,S(19b328a4,fa17149c,ccae5830,a8bedf53,7c0d8a0c,c3616345,6f4d91d0,718ce8b4,9a1ce80a,2a4e6923,69925883,8e786779,fdff7f09,25d68855,12644d04,9e582f64) -,S(afab98a0,e75619bc,ebcabc24,c1a6a0bf,2743d4f4,921fe53,3a393648,adad5d4a,bf1b3a87,759139a5,79741c09,21f29a10,7c8e5be3,13d75715,7dfd39be,923a32db) -,S(c2cabf7c,1d86a34d,addb36d9,c83a8ec9,b2dfe0ee,8176d085,cca91fd8,ee4181c7,5b32b724,53f1335c,724465bd,6eceb8f5,159ab150,e9c972ac,f51d27aa,4d91070f) -,S(92839424,8e847452,29a8c534,7c14355e,4f6e9cfa,2c1a2be4,f5ad6cfc,2a89f593,bb9c585d,fd41ee06,99ca7b4a,146faf68,51983b15,d652e996,c888a171,7c8c3a07) -,S(bca2853c,389ef184,208cba64,617bd7ad,55e55f12,d0c9fb4a,a8dc30d0,c73c7dfa,9f41289e,f32aeded,3d45952b,16a62fba,fe9a142e,1e65340,17588d79,e1df63a2) -,S(a4ea7bda,94b565a8,ebf53aea,5ce672c5,5745b7bd,37ca77e4,a0e4f281,71bf56fd,c9507485,1405ea90,9b9e1a28,42c5953e,629eef31,37bb0fb0,970cce6a,893e96bc) -,S(71707d45,af71139e,d7327ced,89a2403,da57c18a,8527bb1f,f754e78c,60d5e169,24b36484,fe4da6f3,a3f4e4a8,55a477dd,3eef0f39,fd3c585f,1b9de9d7,10223ef9) -,S(52c1de03,296f591,9d5cf4d2,36b8ff51,5b1f5ff6,d73228c0,7dda706e,4fdf9a05,db958d59,d73d574,384066e4,fda3b785,c9509714,90607c51,35d1d34d,5a344d0e) -,S(7b09c0b0,7852e845,30691989,cbccbb87,74dc2007,df827120,d8b1ea62,2368912f,4edf5717,ffc52817,d0eebeeb,782ba4d,9545a5c,da979f3b,e9c09e84,f82bd263) -,S(e99870ce,b29ad1a8,2bc08834,3e3b3c03,f26e7062,66b32540,681c689d,ffb8300a,8080ad92,78947d65,bcc12dbc,614d17a8,8ff75e3d,91230fad,c6f785a8,cd597f9f) -,S(c7e2326d,e28b8139,85db4cb9,c3d4c5ee,2dd2c2bd,2b912444,adc3a434,205c38e7,5f2863f9,cdc0cc95,1fb87000,e177cf05,d31adf8c,543d899d,195bf5e1,c6ad940e) -,S(883596c8,4ca7bd78,3c586bfd,28fba489,4c6bb66b,5ea52244,1199b55d,3e3f7965,fb114be8,59255f10,c96d6d4a,72945ac9,47a22f5b,68ecfac6,9406bce2,58e9282e) -,S(7f73a648,a19640f5,b0f029dd,37e56e7f,5cf61659,5e532dcf,7ffeb7e3,f20b42cc,4f76248a,f931aedf,b4e2df3e,ba3b426d,8ef191b,9d59507f,4a94ffa8,80ff4feb) -,S(c89ee34a,3660d03a,ce3b5604,1196a66,18c8739a,8a4795bd,db9c382a,9741aa3d,a4a3b888,35fbac57,f2f79ac9,d0ef292f,6838764,b99de084,684d1b95,12923884) -,S(24be4c56,d7dc0c4e,50050cf4,31d81f19,b5c46889,430563fd,566c4ed3,d941d5bc,e07236e2,4936315d,5f0714a2,af1ad769,f6a5fc7,a56fc1cb,ac09a085,f29e6213) -,S(6c31e71e,caa91c00,798ee5c5,3237a9f2,2866a91d,26936852,c4eb9853,e40b94f5,65aff323,2b5f2cd1,c1117e0a,c30b94e9,34543cd9,480f7922,5723c385,9ccf8cd7) -,S(506c373c,8479693d,3e03c022,9b61839f,e470a574,d31fa286,92601ed7,8e58b7e7,4fd0bfd3,a57c5035,268bd4ae,707fee83,e24f8676,e0ffe3ca,1673faca,1b7ab65) -,S(59d9a5f3,ea1a6cc6,16e7b097,871f731c,57571a09,1dc01b45,b48c5332,c98349a4,94ad373e,ee6496c3,263c348f,a7ee539,53aadf13,1aa6b638,21c16e0d,55fc8447) -,S(a524cfab,65371648,f641912f,a6ce67d5,c6f8929d,366448d6,4de381b3,22d75c69,14c26ff9,87fbd599,17a6ae90,bbe7c79a,ac1b6158,c3f46144,71aa36a9,45782823) -,S(126c986d,f83c6307,87c0d3ac,6a6b2393,8aa3fdd4,df26e76a,92af2c65,7f48c550,808539d3,a56a6f8f,3bcf04dd,31ac72e0,3f74ab1d,5e9afd39,7741656b,3d4c5c5c) -,S(32cabbc0,1aebcfb2,7e1a9d5b,4cd05550,d8ff25d7,b9a81db7,3188474a,ce39722,7d30120a,e08031c4,12c070f,6ee6b52a,be191021,faa9f5bb,9576feb1,8fbccee9) -,S(3fde1cba,f7ded6f8,a98975ab,ad5a64aa,8a9f0864,16dc25da,359e1cf8,22f42c64,e50fcac,61f0f174,b0e93cae,691212cc,44ffeda1,60dcff91,9ee3c960,2f5ac075) -,S(9cad22ca,d6c3dfbc,1d3a08d,6b102727,36e9db37,1ee1f26b,3ce932c7,11462e24,5ae84f1d,873dcd04,7f0781cb,aabbb53,422bb119,4e59d5a6,8824db95,50461c6b) -,S(9859020,aa807626,3a8ca18e,91c1afad,c20cf9f,9249c24e,1c652d19,7d5872ef,454323fd,21ab7d6e,470976f7,2d85fa39,a084e7eb,b332edd6,a3d054b8,d3c73e69) -,S(821699a3,e7cbcbd5,a2b093b6,c825281c,ac00bc53,c44b33a9,d8c31b9e,464eb2b6,f7d59c17,2400cb9b,72b44cbc,bbbd3e9f,e62cf451,bce6f840,23b073ab,66a9726a) -,S(bd06d4be,36423862,795fc7a5,5c48ceb8,440b3cc3,fc286dad,74ea7f6d,8cd370d9,3b09193a,fdcec88,ca4a5663,2cbb808f,61bb1253,fbcd1714,accd508,6183b90e) -,S(2c7112e7,9c8cc78d,f04a4ed0,e043c6ca,bb4b734d,9177f822,5bc41123,4bbdf4d2,c81ccfad,d42e2248,7612884a,d900f61e,bae242ef,65ff1afd,6e03ec42,38391243) -,S(51ae390f,a65d772c,833cbb8c,9ddf9ceb,b7f5236e,f1983905,762b7aaf,e122131e,3d7c9f80,80406b06,282f2a88,87dbb714,f1e96e1,e84eaec8,1256e1a8,ed7ba06e) -,S(c59de112,de237a43,2bcb8348,e3b31356,c7432672,6b9167a1,77d826e4,dacc59ea,36109f16,7c5eb66d,9f09c1d9,c5e1676c,aa33e403,a8e052b0,2854c689,d5903b25) -,S(8b99f23a,b7509d9b,151cb89a,45753026,77ca1e6,9219f0f7,57d01823,f556d978,86a31aad,f53afe44,f533cf0e,4bcd573c,d338e12f,904c8e9a,dc8e0080,f56a4164) -,S(4c670f65,7d6fa9bd,9ee4135a,1ef1882e,61f5fb7c,9deea717,39fe0ab9,78369dd5,531a8226,5d4b5363,12875dc1,7f891d1,b54e0435,1b539dd3,c100b797,efe65417) -,S(8e967e35,9daa0f95,fd7024e6,e57f0640,36aed9dc,9df0f33d,9388cedd,e0f38548,36f8055b,a59afaa5,8c88b833,ba110381,45fa0ab1,f0160d2f,1f1a1765,190d218f) -,S(3f611915,9c45a37d,5c7bfaa,cf0cc959,5e2e097c,8c7bc3e,c82e9e33,3b2ac9e1,c80134a,b7437dc5,23e08757,8eeada53,b9d2f3ee,25b754fa,f6c32e02,d597d7d6) -,S(3f59e49d,7c61412b,53fb203a,c7ebdedf,66bba683,87070745,9f85000c,f47641d9,bedd7088,4243dfe3,d238f101,f5dcd4e,64cd0978,986d50f2,ae3e2563,a43ad5b0) -,S(5b7d84c9,b64836a4,3bc44b5b,fcf170e9,ad46d4da,197a2781,bbbcaf87,5bf6d490,9f55b29c,c7d6b0ff,facb8975,507df04b,f2164e5b,9928156a,7c73fec2,b34d984f) -,S(e1ee74ae,ac3e83c,f73bf1f9,aafc3eab,90decf0d,a071aa88,962c29ea,51744b1c,9e86d2f8,b34e8525,568d674,8839839d,eefbe15b,80c66216,50acc508,f1277030) -,S(fa1ccd5b,8d489448,e3196c22,e96ca7ed,eba721ac,beee200e,5ddc496b,6beea871,e2b7f59a,326a6654,9d6479a8,a7a56d7e,8513504b,fd2a9829,d25e5855,2f9bc469) -,S(ef1e1cd7,f386096,1f6199d1,ab4a63ac,b292316b,f7a5e7a0,4c9f0c3a,7bfdc8bf,4cef9c01,a9de111d,8395dadc,e411e532,5783d377,559dc687,eeb510c2,ba98ef05) -,S(db714eb9,3e75d3ba,dfa5cc4e,d4813db2,fe9c395,95a1ee8e,9b3e468a,e1326120,3dc49a86,b81278f4,84d30311,c8816840,fa3cb701,665c067f,618295aa,6a71a206) -,S(5997f38d,bd572858,43ccf936,ee9d3feb,d70c79c7,9ad1c452,29af32fe,e6ea5d5a,adf7d862,b716011b,b9749e08,965c1ddf,1f44b678,df548eec,45a69a56,97e4a224) -,S(97d6f6d9,a920577,7b08ae66,6fc1fc7a,956654bd,3bc6c039,ea4eec3d,3bbaeb92,b450dc47,ff219854,dad5ab97,13dfbbf7,ce03fedf,4e7ffc68,4bdf1b5c,c20068b9) -,S(4f453fcd,5ec8b72b,69549ae3,c4eef99c,40232bca,1d6b10ab,c4b00d00,5ad307c4,aaded568,c4a8bc87,c7a442ba,f960d9e8,bd61f15e,d668f816,b94c0d2,9683f7f) -,S(5a604a3,50593035,c71c0a6a,caa7946c,ae4c4490,c0db71e6,49972705,949424d6,e578fc12,6d8701a7,a02b92b9,3fa89d09,ae82779e,2f78586a,8937a6f4,133be9c8) -,S(3f3071a2,916832fa,1b64cf0d,5b5fe8ee,2de601c9,34e08498,5d118696,7c635b3,e915b199,baeb233,b22adb6f,69df0e43,8712f25c,1be4470d,53851e4,451ad3a3) -,S(745bc1cd,643189ac,fcf02c5f,bf99c222,f7476a6c,2ede6c45,31849491,901c06e5,59a2bb4a,8703775d,e9a519bd,10e59db4,be16cb41,d0275d21,87291d06,d29933f0) -,S(bbd06e8c,adb3959d,853591a6,6387989,ab396736,8a6c1942,17580911,2637238e,ae0d8296,b484e5f3,dc46cb88,90b86a4,d562b003,a65a0c2a,2b4eded,38b8b690) -,S(fcda8db6,128dbe66,850b7e43,63a3b35e,9f3eb569,b7af97a3,85e53fd4,922cf07c,4bf3ddfc,37a0f9a8,5f758ee1,4c4d5c86,cd11f1e8,2a05ff28,3a0f535f,f9551974) -,S(6325dfdf,fc9c7ded,2a65e113,27210ccb,4ed2da97,4eded570,5ca1add9,9873cce2,89fe4c99,683e6fc7,170ada7e,26179fea,7ce1930f,af1a7358,4d7d56d3,4cf222e1) -,S(77594ca6,93495096,3ab5797a,5279d0a7,513df59b,41a3ad59,245e3f29,22ee0d7f,195eb112,2ccfbfc8,fdeddf45,ef2ef58f,631df03b,ca66a4a9,5818dd83,e5faabb2) -,S(f356ec67,ea9b242f,4f1348fd,c6592772,e2defd7e,308427b,ede15452,baa67867,3d2265b9,e23f8ea4,9a2b7145,9c98b03f,d75a2110,8f104121,e4a2fb4c,d633ba7a) -,S(3360ae12,9b0fa48e,c78e3091,4f8ae6f9,86149f0b,590a12ff,cadfdd2e,f8a205c9,79b37bf2,720d5a11,3ec09872,22b0a626,3d7a2051,e337cb83,dcb52df7,25d18a34) -,S(44e90f52,c703c50d,b331a4c5,fc47613f,b29040ab,9ff0f282,3fc15ad3,f9e8727b,62dfb341,92653e6f,636d013a,718932f6,95c2491e,26d16feb,4009ec05,e2f55f17) -,S(e5d367a9,b5c3ae22,31195876,4b28fe35,c9e04289,518aa09e,e7902b5e,4ec84047,ea1b257f,1abf0fa,6fb37c06,907052e7,fbbc06b4,c2382ace,9c9a98bc,e6f8bcf0) -,S(8478e8fd,7910e5ad,3c061e6d,422806a5,559baab,e083b8de,1005413b,59a63957,4f793418,5193499,13fe38c4,514bd4bf,2f3f1ebd,b492fd5c,fd8c1bc3,1a2df1d6) -,S(c38327c8,587731b,f5b5e224,79c9274,10c97dff,f6855b6d,c2ccf761,2a84b42d,eb03afac,cb1b102e,7e87d61f,5012ce74,a213fefa,b855db22,bc657d52,4dabfcd6) -,S(b9e8a812,5348a672,558f48c9,d17f28a2,4662b4b6,604ee14c,d622b521,bc51f10a,35c2780d,65fcd07b,51ea0224,1771b523,3813e7bb,97a1744c,e3dad732,ef1ccfee) -,S(a54aa2d5,95cfa325,38d2e483,70ba86af,d3c3b53d,2141b0fd,cc68a729,a5cc713e,bf74dc6e,63c02b2e,e676b9c8,6a851a48,7e9552b9,a32eabaf,4e1faa06,8bb8a159) -,S(d45fec3c,e2df54eb,844ad145,fb8884ac,420ce2ad,85cd55ea,4cc19e1f,da9fd956,ed8cfb00,65aecb6a,6901dbf9,b8c208d4,bf6be1e7,ee74a08d,205c48bf,8cb81bd6) -,S(f4b44e98,f728b318,ca959829,d4cd836c,5c0136ab,8e433101,87be24ad,53192172,ef5521b3,960bce49,2c841fd8,8cf7b8dd,2febdd8b,f0aa64e8,4d3c2a09,89ea9fa1) -,S(dec6d1bf,d349110,faa0cd40,e8533078,dcec40c6,e260b9e2,8412d424,353d67e3,73a16f81,3609c901,71efe44f,32ffc90f,9451b0b3,24107b72,54ca2fba,65095895) -,S(1fbcdd53,72e17c41,9310b9c0,2273534d,265f1c24,bc1a6039,238b5b7a,b3ff013e,9cf4ff4a,6a61c11,20c4d14b,97275547,b2358f75,8a2a774f,22bc77f2,4c6c27ca) -,S(d9cef0cb,38c6ed7,7aed53f4,93a31daa,50ea1ff9,aa43b890,357012fb,e2ab593b,32a416fe,246872d5,b68e6654,7f19dda5,e161cd13,ed041486,4d0c2dd,3653303f) -,S(1641b549,88e22a18,45e2135f,88d2386,4e2f607c,ce33fcce,de174a60,1ff03da3,edd3f0d9,ed718767,3664e1b9,540f816d,48e3ffd1,cfad86fb,5b68dfbd,7d94922f) -,S(99ef6c16,3c5d9ffb,1b638b21,1ef60166,37938f83,ac4ef76f,96c5366c,3a243cdd,6b6eef62,d819581d,e1dd7796,df043e02,7f912bbe,6ba1e499,a311769e,d6f66b48) -,S(49358d2d,c24c2e8b,80ff79b0,9c53645e,b9c47fb2,8ea4ffe4,e2f4679f,5b5bc97c,512a14a7,f9df40eb,ef7c1cbf,f8e1caf7,b8c80748,7bee3865,37837cae,dc1cf5b4) -,S(e31d3fcf,b1dedfe9,2549c5e1,a14cf383,c8c122a5,a430aee8,a4eec846,7ceb206b,7bc3c266,69db747b,a3ad1dd,e83464f9,effc4dad,b4de7687,e6c3ae56,a5b0449b) -,S(a82ec9d6,ac86bcad,fbb32e66,a28d7483,ad1fbb7f,979a15d4,4e324ce1,86c64adf,bac87d2b,c28b1ae5,f4ab46f1,ac779936,3a9efad0,b1e1f81,6c4ec6d3,cf74c89) -,S(21650994,2bffa2e2,479ab82b,18cd3aba,dc370c3,18c71c08,1bfb53d4,c8ea113d,97a8246a,2f653450,be513b6f,62419f90,f84511be,9a5f3103,feca77c9,c81fcae3) -,S(735050d8,208d9688,7fdf8070,e448e905,e4e666c6,3db5857f,63ceb362,c6dd4b84,2e3fb438,563661c9,e6fe23f0,7c8219ac,216887cb,ad307918,90001f9e,2ab9e2e9) -,S(1d021861,e679dc08,a34c3813,bb9c3e9b,65f87800,79dc08ba,197b3b66,47afe506,14b6d0b9,2303483d,9e92cd0,e295bf08,4a10e84c,ee0b7c50,ceaa6ba7,a6fd2f1f) -,S(7a7eee74,86ca8973,a858c15d,54eff96f,f91c5577,4985433c,1bdc4f4e,46d7810b,5e83a07f,5d9150e7,a7f5057d,87d19ccf,448fed1b,bc1e2297,c7012cbb,77b498cf) -,S(811c3d4,fe0a3061,47c05cce,32a32ada,48593802,32f24b51,f50e726d,a702beec,a6fcc16c,6c9cf4f9,2e84214e,35ad8577,b28e599d,31ed74ef,c95eb2bc,833d9f0a) -,S(2ca14438,89ea9e8f,24d5b1e,e44b26d3,ca25ed08,30ae950b,4357da49,21ad606c,7b48a6c6,92d8a29f,a82c656,f8e6213,c5e90be3,7413d86f,42e10e63,1026c551) -,S(a980ffe1,61041afc,339566d2,957e6624,5dd3e0a5,deee9c80,d57b1f1f,390277bf,3276f7a2,a139343b,87744079,7a174d99,457d5005,71ce47fd,10e41456,7a1c64c) -,S(e570a3d9,cbccb74f,c582954a,998d9371,fde41d98,e65de6bc,9579d6ea,d9cd80bd,5a749177,6658398e,99d3035,12c168bd,9400bc6b,c7dea2df,2739abe4,16973a52) -,S(f5fbaab8,952cf50e,66d3d985,d9280bad,71bd25fb,662358c9,72b954c3,7bce1110,1aca2123,6179f821,a4f097c9,b48a744f,8010818d,3ac6cf,b02f57f3,1fd77175) -,S(2e5942fb,ecbda8ac,15408d25,84ab7c75,6f9e525e,c4dbf375,5559dea1,718d89be,95106507,d14199a7,8f123d6c,f6b59262,30e12a1a,8c0ca016,40c556fb,14bc790b) -,S(92bd04a9,891c99e9,6c9e7f64,a9bab705,a9fc83f,a739413e,a2f33001,b55dd296,cf5e3733,659bfd9c,e5417ba6,817b6a0f,5cc71c34,22165fbf,13019fad,822ba587) -,S(30ddfd9f,a50feae1,e3cc5426,93ddcd62,4d0e52b0,867248ff,ed7d3041,a7b11083,ff15d0fe,2bb183ef,a18389e3,df4269ca,21bdfa0f,87ac641b,14bdaf66,26eb42ed) -,S(8cf5150b,df8ac68a,af319688,245719e4,67ddddb,72fa7f1c,baf39de7,252a9f4f,4c28497b,a299bb19,83b18bc2,508c98d8,2a9963ab,4145807a,2130fc05,4186cfd5) -,S(1f4b4efd,50974efb,3caed9f7,4f6dd979,4a8e3c09,8decc1b8,69032885,265e46c7,6c4b04c7,f7c6b00d,c38adeb8,a47c7c0a,68535229,26500a76,ee1c6feb,179fd399) -,S(9d524900,979afa33,8d5883ba,d13d038c,3f915cb9,f2e29a2,2a028b18,d091af81,409a113c,37c732d,1104453d,6b161d33,db3257c7,b9a73e1,e0f1679e,6802be38) -,S(52e1e4e4,46eed9d0,fd5c124c,1c23403c,5b03984c,f3fb0734,c627f34b,dda2e3a1,674a5731,7375ffa8,c3c4104f,12c1713a,e2dbc630,75a77e5b,26243217,88320a7) -,S(827b171a,8eef4e31,e6ca8b6e,7c6e36fa,e0a6c93,a77d7148,fd22f7a8,16401c8b,65cd85fd,d9b801cf,7de6d14c,b78ba114,1d58c7fa,129f9f08,8275f364,f7ca7540) -,S(124f45e9,61d89642,6a1abc32,e582e246,3db29954,1bea0383,c83f917b,6cdf2f9b,734e2fe4,110b65b1,2d60626f,c6288f87,e48e7a7d,213a4f83,58bb4d67,978d6c62) -,S(3b71298,18b2b324,10e4f002,899204c4,fb4ac9d6,c08d1169,5f5f5699,9a4d67e2,28b6f78b,cee16b5,5c010c51,ec465609,54ba6368,a18ae218,5607c1fb,42c27c3b) -,S(d271d87e,63b5363,e664485,ea6ae70e,e2b887a1,c7f7e0a4,290033b5,512d8a00,65d43804,7865e280,273122ba,8d8644d0,60ef5927,34971c9b,510238eb,9d6da847) -,S(1d1c6d85,2db35160,67cd2d82,e2ba552c,c5ca0c9,ae7bd661,e8494b25,cdc03a7,bc31f4c5,673a0256,ee9b6840,7aeea035,e19f874c,bdd7aebb,ae8b1005,4e691f62) -,S(8fee89b4,71e394c0,ddad274c,ba07de4,bf8d2ecc,695647fb,1d3756fd,46efdd9d,5d5ed0c3,8479578f,d17ae148,7198f9cf,4ba5cf71,46a9b4c4,34ca62f1,bd2b8c6c) -,S(681fcf09,55a0f351,6026302c,ce3ee475,8ef9385f,908dace5,5d7fbd30,8810a6ec,4307f75b,99927624,80187edb,c4c6575c,aa54e8f4,190f0885,e6d358ca,2a38faa) -,S(717fd6dd,fcb5a71b,6a584a28,904cd3e2,6f6c1a89,7fc32918,90792937,b3a6971b,b403f829,71d4ad04,dfc40553,27f6da8e,1b05e25d,341d6511,d7cd859f,58b17992) -,S(f2b95723,94eb9786,dc1f4998,6ad8c340,d2983279,c7323a34,227013e3,754f2ff6,b553d381,3efdcd41,7189645d,d9917b73,bb69e705,e7a6520d,dbaa497e,7766763b) -,S(58714be6,d7d86c89,65309b52,414135c1,9ab6fed0,1d56d7b1,4237485d,96730b1b,c011f34,3e38ce5b,deab84ab,f0e31537,4039845c,5fa4fcf8,1c9a4d5e,6fe3e533) -,S(d33ce5ab,c828f8c1,b9700d49,e9c6b4fa,b30819fb,b2bea23b,7f915bc0,7a6ff3c3,739b6222,39134988,22372ba6,3fbe22f1,ef59394f,37db956f,caca4c11,75a23395) -,S(82202e32,fc7d0128,4eba58ff,42f7d94a,24904808,d6f920d5,9837b26d,63b55479,fde63954,50aa55e4,fcc4fb0a,8ac2c880,63aa3202,9a00004d,edd033b6,2563b4c8) -,S(25e63218,5bfb4c88,fa300e37,c8b64a,941e6487,a34262b7,419fa7c,2dea7781,ae696b07,4802ab99,4df2d84c,c6731d7e,9caa124,548c2a11,42ddcdbe,f716e640) -,S(e0336a05,b9254e1a,f2468a36,343a0dff,9da8773a,1efdc487,53c1a95b,605c114e,41d75960,377ada38,79b97455,346266c5,5ba05915,9ddad050,d96d9d8b,afb12a18) -,S(843363af,7fd2b1bd,1c9a9253,e42489c1,34ee875a,db57b752,62d731aa,9a996662,e5c0a2d1,dbfcf013,ed4bda36,f153a328,12c4b3b1,66e48473,4d2d3562,ffcde6ca) -,S(adb210b8,1cdb7f18,f97955cf,fa7e5763,abb9f202,9d283c05,26df6332,951178de,2c211f05,d8182aa6,d784721,948afa11,364db5ec,2e1becf0,68eb91a5,74ea0e35) -,S(ab0c5fa1,a2fe2235,ee93854f,59a13792,2034604e,5857b6e0,88b65142,f24d7491,e54725cb,e36d6e15,71ca7384,7383553,b9dc48cd,eca6932b,8d92f785,b80124d2) -,S(3e5de77a,1d2163e4,3f3124b0,af4f5473,868a080b,67acd835,f9cbc88d,7885deda,a6ed34a4,2f9503b8,b83e66b8,377f514a,e1927dc4,c37ef6d2,254e651d,15746630) -,S(60c68b3d,31d1d326,5b71f068,8f32f671,32184815,f83a9ceb,50eaef6,4991ec05,977acc61,9f7d24c8,a95aecbe,987737a5,89886729,500ed32a,9d760fca,7c00d498) -,S(21b052e9,b646e595,b6c04a76,a66b9b25,4a126729,6bea0654,64fc5b31,69c135e2,1029e4cd,2fb3d717,6e87292c,4b0dfd7f,18db6ed4,59aa9285,38f0989c,540779e7) -,S(700caf3,7c664515,ee501e66,60be4cca,f58bb2ef,5b11f79d,c027dba3,7b523d68,7df76b88,f1c346f3,2e32487c,19957830,8eac9b7e,56edc948,e1a934c7,6fa08be1) -,S(c5ab9bd2,1293844a,ce5f1c9f,56458315,5d34aeaf,565a5696,29969664,49541e8d,2d2081c6,c61d6c8a,a0df4467,8ec53a7e,9b34d90c,57db2f29,c0361304,1c422d8) -,S(8afc3f2e,d53f5dc1,448d15af,8c2151d8,5713fbdd,5d46a3df,a4ad376a,16d75a3,11f6393,2627bed9,e015a99d,42193e6b,6767c513,f3457897,64db1a4e,4b9b6c8f) -,S(414ad9c6,bb55eadf,cf4cf729,27ae3682,c0d69867,ede9f4d8,6e173c50,3a5007a7,c4bcd0f8,f4de9b1d,1102306b,667a546d,dafb6f82,edbdffd6,181dd3a0,8f603585) -,S(8211e240,b84b7317,a9c5ec88,fdc426d1,a163a2d3,aaf088fd,b2317247,cb04a1e3,ca76a59b,b268bf51,4f06c4f6,d5961b33,a74f10b1,70a9e9be,4e7942ad,26722bbb) -,S(a54dfd32,363add3c,75ec4452,3094b27a,3f7cd291,43ee52f4,29e59daf,22ba700e,f160822c,59510098,3e38d130,49b44865,3639ac74,6a93ebbb,2798d92e,bad4490b) -,S(77d64c55,52b29b18,a7aee1a8,1e1e9d3f,e2921a43,cfbd95e9,a3ba7cb9,498860f7,e97bb8f9,5ea9c8f4,440ad9d7,36d9a06a,fed03a9,cc96597,8d06f2e7,8208ff10) -,S(485b3814,b33e6bf1,1f47f0f5,f0e5a189,1b57c103,60f13d61,ba7947e1,6e309ca9,e6bb7870,ce607c62,a6050dd0,946c8653,f998576f,2c781b5f,15282632,4e38bdb) -,S(ed2381ec,a90a78c2,def618be,1b6edc51,7ced2ac8,14aee9aa,b0a7068f,72739c,cb0873e0,ba326452,380c291e,c635381e,d6859916,2ca10fbc,3de45ffb,134954c7) -,S(e444af79,d36bc127,c83c7369,a4cba0fe,955b6a66,8f2e7a68,4a65e57c,44ed971d,a7876f03,27b6823a,aaf55ca1,6a48998a,ec50e5de,10d34e9,dd7c554f,d3785fff) -,S(af8c34d7,7de75a2d,5f64296c,152fea4f,b8677b8a,96cb278c,7ed7e50,69fc1fca,48ce5862,ab6ec1a8,ce55899f,24632be2,f3c451cb,8b81ca8c,f9ecc3b2,2984d673) -,S(e999d466,243a44ed,18e745a8,1da04a31,8940c88,760480cb,e315436c,f67efe13,f41e8e70,63a84661,c22ac0e7,5cdedbd0,ef55d3eb,7fa813cb,2f7d1fb0,237fe36) -,S(c40ef8aa,7d8964ff,a3cc923a,2fdebec,72cafaa,58b72d66,e209b644,604bcc72,480e35b5,6549a1e6,f112c3b6,176f3378,ff50ebc7,b3efac2f,696f0627,b7238ce5) -,S(482ee41d,e3f9499c,8992b546,e209aa5d,679e4b8a,22a26615,1bd1b0f3,9a52982f,510e6070,d2131815,2d52eff0,ee10ec6f,563f92ec,a0e549f8,32efee81,dcd3de3d) -,S(4660a468,25a3c1d6,67003c69,4d36f8b7,6df7ca32,c6029fd4,65dcf726,5c58fae5,3d982bf5,46b5c296,988acc72,2dade97,791de8e0,150397c0,700bfa10,ba23f618) -,S(b85e624c,92ba6f0b,3fb1dc03,37589994,d8a3aee1,76314d87,3c8bef0,eb5d8f8d,88936b33,20a55ba4,24bff93e,fb36ef77,e2cdff26,866cd486,88c61868,ad75679b) -,S(a41920b5,361a26bf,bd187eba,b62fd5b3,b3be282f,94ef94c6,b1698754,902683e3,7790a196,29d93b4d,3d27201b,32053e02,c95a8f9f,260647d1,491c7a4a,e15ea98a) -,S(93882da9,79262a60,3252f01b,bf101d89,ed1abf8b,15507937,55979f4,fbb7f86e,938884d,f0a716ef,137450b,ad5f022e,23e570f1,3ed37e02,15a40910,189d7e44) -,S(a10509f8,3efeda60,acf56b64,3709b197,ebfa6a59,e66efb06,79c23225,c8952e00,759083d5,559bde4d,9a37df5,24cae4f8,5a06e7a4,7c0e15fe,830f0677,c24d1ddb) -,S(2b945a97,6ea74278,73d7e587,dfe75eaf,c55de704,8aa26d29,4b3b1ef9,2beb3651,423c07ed,27ccbf6b,9d1cbabc,e00b451b,cb488d10,e5daf752,6980ef65,6893c65) -,S(86f9d9bb,c1a0bfe4,e03da0,13f17017,f6951691,28d51073,b594457b,fcc37f0,f370c624,2e303796,9339cd4b,fbc19e8f,62388f02,649247ed,df3c6c67,464c32bb) -,S(f8995af9,555e044e,6238d895,8bdb4e13,3aa9cc0f,90a9206c,16d0f83,dd61ed91,b2d4d2e3,1bee12c8,3b8bdab8,34fa2e63,1febdb93,4af194bc,d0825921,4ea8a060) -,S(ab55a27f,69eb352d,455eee7f,bbc1c74,fdea2621,63d09dbe,2f554417,819394ce,8ac56493,60f585b5,72373bc1,74a930e2,4d54674a,89789353,4a166200,e31b801a) -,S(4fc106c9,c428df98,916a8906,95e98353,ce84723f,fadae522,e8a89916,a23b9fa6,90d732e8,3d54341e,4f4c88be,3392687d,fdebbc4a,7c19afd1,92531688,9eb92031) -,S(c9c85980,8831cccb,77d87b25,73a894e3,874080db,ba076b2,4626bc82,3149a91,9fad4ccd,8c0949f9,be9a6355,f0bdfa36,c5f99268,780566e6,a6f302e3,b2abf0b8) -,S(c0cb5b7e,2293abba,5ff78c46,aa1422fd,a278eb5c,ddd58cb7,aee77149,1c5209e7,8101f42e,36648586,5db6b572,d0df4ca3,cc72789e,ed8d27d5,1330d733,4e10c47b) -,S(dbfc03c5,16d93f83,472ab60c,391bdd69,af2f70ce,fbce15d,140f1590,d8ce0b63,f838e14d,7228ca2e,9a33ecfe,c376aa4e,4811fa24,debc7b46,4658c153,fed26564) -,S(de260685,eea13ff1,1571d891,35607b0,435140b9,62e3baf3,7cc3f3d3,484f59c8,6bc23ec9,a6025865,e6363335,bb66f1e6,c1f5f54c,aa5f8acc,d7f8fae5,99cfbbcc) -,S(58d78d60,b8cb8fdb,1b62f79,f6c17ebb,1ed8129f,c7819e5f,6f73c58b,faa2e71e,7cbbe4f2,fd6bc671,8c222f5e,16391133,b04d6d3d,bb263531,40aa4053,b44bccc1) -,S(e72b9b1a,eed54fe5,ab0869aa,90014e3b,fde1af12,f646d738,211ebefe,2c00a490,cd92d14d,8f595833,842af020,a2cc82a0,d9465969,77d25d34,8cff3273,90af4fc2) -,S(6a86bae,d55a5be1,8b7cef97,c9dff8a8,b725f614,2221485b,3b9f348d,570fd658,138a2691,4c3b3015,10312140,7709fa87,60a14f14,571a9d40,81c06d67,ef2c5724) -,S(1ca08cf6,7240f244,d6cb0059,564fc283,b17c39e1,b624716e,e100aee,bb0a1fc5,22e24fce,655d09ec,34a36317,c66adf07,deec2743,4e9c016a,b3447b3f,d9ef0a55) -,S(d95dc128,feba49c4,73e1ee30,bcddf76e,b7cf628a,fd495607,f558201,824a0b0f,d5340ab8,fea3e137,d1061274,c69b68e3,633e98ba,ae2fe116,1612c4d6,c7c7e8a1) -,S(2cccd22a,7f4fd501,6c3a14e4,769a88bb,ae7e288b,d9987afc,f3c073f8,ccd83857,ae82663c,aea89fdb,4710f849,ff8e4fb8,c2a7b614,4edb5f3b,f2564dd,73b389e) -,S(ec17b5f6,c8e4de23,937bc003,7dd7b411,ae4a9ac8,1f2801d1,c5eebeb0,95628a43,b3e0d51d,fd5815b0,631fa298,968fe70f,74319620,f0798734,8e66e6e9,6658df83) -,S(a63aaf7e,62907f4e,1a613cdd,ccf1cc98,cee8e12c,8bace3ca,95685889,6c96b6f4,2f953ebc,dc5f9973,e9d44ab1,23255a21,f8bc1a7d,e800cdee,ef754031,aee8216e) -,S(8eb4ff30,318d8d0d,6b45636c,b296d137,90e345af,19a14b2c,550e0169,87ad32f3,4b8e238b,ae7ffc7e,7d600151,c5ebb776,cc01d51,827f171,8f28af77,ca4a3e3) -,S(ab1420af,bb5b4397,f578a6e5,74a63aec,2432fa8c,b4712341,4374add9,8276b8d2,faf6328e,a197e927,65b9df90,a79558b,8f264acd,7f75b574,90ce657f,64b94396) -,S(daa1890e,6b2ba1aa,dcc16f1c,c1d5999d,5102aa6b,348ffb5e,9630bd1a,886f680a,19facb69,5a63eb94,cb6f6005,cf2bbd23,8744f05c,2c220510,94bf6dfa,352fa209) -,S(f199f52e,5398d1b4,899a1b0e,df8ebb73,cb08a642,bd22ff2e,b1cf647,7f2a28e3,3619abab,a5e2131d,4ccf8747,67ef9b75,2d5278ac,5549bd9e,5c1b5985,9ec2f454) -,S(182a9e93,a5f9ecf3,6bf20bc1,497a4a35,e75c86f5,9c9fc046,e2752223,f046ad6a,c6095e88,c39dee18,ca867693,d85617c7,e0924dca,34af07a5,c731e488,ffb8bcfd) -,S(8a4cb53,636fe66,b660a701,64277fb2,5ac21eae,906327c,3b509954,b214abbb,693e5851,4cc6a941,23ee707f,ad25d638,8efcb85c,25500bbf,63fd6926,a1d0ed1c) -,S(4901335a,3b40c33e,115e3105,82c55972,f495178c,813bd8d4,2b208916,5c8c1282,47007176,429d740d,dcac70eb,9e1f0e94,f26a9a0e,4dde0166,24d9d801,c84214e3) -,S(8180e5a7,7c34362b,461b49e1,4b9f2e05,df64f55d,cad82b8f,cdf41232,984e01dd,34cf5621,d4b9f100,aa34b0fd,5ac91d,cb3fb49c,130f3e65,de742ac,af05040b) -,S(8f71227e,fea9f4a8,9dcaeee3,58eaa5d5,a90e1d7c,b7d232a4,b1085fe1,3651ee9f,a4da15bc,bb2b79a0,a27c344f,3b914c7f,e272676a,bc045aae,e90daf4e,9655ad73) -,S(dbeb9b74,cdc9bacb,83592a2,a3cc19a6,d1ea8eaa,5a086a3c,cc68d423,cfb58264,be668792,83f07fb5,830732eb,79e16bbc,18e86df9,b659e2d4,5b1009a3,40576161) -,S(f328e93f,a7f52cac,3c7b09b6,280528dd,7d9ea4df,8317a958,ab0a617d,71591933,41ce8c59,811f9e90,61dc3f3a,7d85d394,2f780c17,d7ebca60,fc042311,f2405547) -,S(56d4f403,416b1bec,49c5f44c,2021c245,d4ca4181,5131cb7d,8fb0cf08,30fea051,cc5f6133,948f77be,934cb637,3d5dce8c,51ae1a92,e3d802a8,d35a3ad8,50bd39ce) -,S(8e22e04b,8bb476b7,ccebecf2,a327fd41,dd90c9fa,67cfc49,e9cf4ebc,39022b8,1f8fa60,3204696d,34d03c02,31d3ef58,934e7992,c2c81d6d,3e4193b3,8286b8b) -,S(341b22e4,b9a77c68,f93624dc,1cfefade,b396eb72,bf9fce1a,51867d7a,ef064f6,95839f87,7bc36957,59562bcf,dbcb2db,af11ed72,7d329e27,cfc8ff8b,92d9441a) -,S(3ea42e93,9f234112,879e8680,94fb8a8c,e6af9799,c000b050,45eb2026,3b324763,44324167,6f5aa6f0,4fe4d51f,fecfa8fd,60a5c0a3,38b16f59,1866bd51,2e01a623) -,S(afe7b44c,ef10514e,f94faa1b,b8cde91c,23d8a660,a71c3173,42f927bf,535d625b,7617a788,51218772,bcd51f18,54b063ee,6cfcdd77,7a388427,51cacfc8,7c8b4b65) -,S(a360ca02,abb40d4c,6e0ac725,f2c035d1,12f69ee3,ff0e1dda,37a3fbe6,a2034d2b,161e7178,3fec3ea0,305d0f72,3a60846f,9d8bbe79,255a3814,fab83269,916b646d) -,S(10484e5f,f7d9fe7d,9b65d989,9b2ecdf7,5984d18c,1199f61e,c914a85b,78011b88,12d1c0e2,1e137357,9ede1086,c2c1449f,e7f4e03d,78f7b184,4f744d6f,9576cdc9) -,S(76c2dce1,5dad9ddc,24276c40,eda7de6a,b11245e6,5b051ba6,7eec39c6,d256b138,d9a601ce,585b0839,92e3fca2,a43739a3,61a8967d,3eb0f605,ed4cef15,fc64ce82) -,S(671a31d4,c3e6ed98,b044fcb1,83dc60c7,d1d83988,3a547356,27b99b75,11d4d2e1,6fdd8d15,2005ef3f,7ef3762f,bf43a849,281f185e,a52c1b3b,8ad371b,e053088) -,S(91d0f565,a2da6903,12b72998,57f71c18,c2343a5b,a6f17243,1bee12b6,6e898a37,9d6a55b9,1956a288,d56906a1,1f7cddd,e6393ad6,7249147a,41eb209d,7f32f681) -,S(7e59f058,1953a2c3,cbd4d0cd,8f4df7b8,6b90d8de,7240b2d4,de9ee9ab,628512ba,33b0d1eb,74cc7d60,ef419b0a,f9f03714,35a012fe,328fbdbd,9d9b69bb,9a42a173) -,S(ef78b65e,b791bed,212652ad,ab1f32ff,f43a285b,e040380d,d3492afe,1f788a26,9f3e2538,96d5afc2,3ea7ab1b,24ffac00,f156cdef,93957910,abb1cd1b,6508d306) -,S(78b978d0,199833ee,417ce2f5,fc12cb01,cb0c0e4c,ee752e1f,50a8cdf9,b56b7cd3,9f9c7dd7,372606bb,e3170141,31591f5d,dd631f91,71460cd0,19709478,c1560dd9) -,S(5f785b31,f9945a20,e992f5e8,80abab72,906ffdfa,7ba7ccef,f1b3d26d,70bfe64a,a3cc480e,b3cb386a,ffa1988d,3227911d,57522413,e5d0846e,a6d0a17,2b881c1c) -,S(9fee7999,7cbb492f,cf3aadfa,44484d71,2c3887d,6375c887,fcee9fe5,7806b3d1,43114327,7e94c760,1fbef25a,60e7d448,c0f0b8f0,c6c64437,a129d4ac,fe24c22e) -,S(12f2dd5d,b75d8885,7b7befd7,cdbd7c76,c0f46213,f9a53102,acd8b0c,4ee3f30b,ce27598b,e85049e,9ad3ecfa,d3864070,f8510570,742dd021,6dcb4aa5,334097d8) -,S(c694aeb4,3ee2b51c,3f0e2bef,bc1b718e,fbb86f9f,1d2a84d5,3178325d,cf997bd7,41481f3e,b6a69311,2cac3e5c,c85a6f83,6fc5190e,ae71f226,bdc887a8,ed050977) -,S(fe266a46,14c5c05c,baf3493f,5af3befa,9bd16100,860bab1,49ad78ca,81047ae9,e2e18ebe,c44694d4,b7c614ad,a772a5c4,f58ca087,4957f20b,741b954,18471e6b) -,S(7975e1dc,926b07c,487abfa5,8c183f21,daff04e7,f67a7250,d2152699,356118dd,c984b97,44e2b300,ca54b779,da94dae5,f943468d,9b9729d8,21cfc709,351409e5) -,S(93573cdb,50183589,a0909e8e,6186d700,7022848e,b7fd6951,a137cf16,a18a2b06,7a957c66,3047f6ae,d9490039,d136cace,caae2d8a,fc9f50f0,26590e62,18bf47d5) -,S(c0bd2e1e,a60f6feb,8e0ac7dd,485fc4fe,6771d80e,e29b4829,fa37faf8,81d77660,685b74fd,9edde1c7,69076267,d9f247e8,2effc83f,e25af065,56aff25b,335bacd) -,S(56bac0e1,93192207,906e5f45,d55d5919,b676852b,daa43253,8c4c6984,9c24bf3e,e3bf51d3,9856b812,d2e480bb,c8b118e5,f5c0ae9,f8d09096,a5d207ec,2fc18ebf) -,S(53b41b13,fe7cddd2,ebfec7c4,a985fded,5225fa0a,b93dfc65,2314d1e5,9142c06c,90fcba57,44e4f565,5d2e038d,ccd2bdff,cb4ecf20,48f2ba98,8f62fe9b,c3b69c4b) -,S(bda05e31,ccc0edb9,47ebaa26,9182ca2c,b1136400,674ce5f5,d55fcf2a,c2e765bb,97275979,31236982,a7459356,7308ea97,2fff08da,ae8f707b,447dc6ba,7acf75e8) -,S(48dd1c6a,8a900820,1fe09f19,a8f65f82,91196e95,1c57189b,21aede15,4b0413d8,79a1f6fb,1a943dca,6517e287,80e72f85,c5a6150d,9c50d7af,78c8b63a,c09b98f5) -,S(75406269,e28c428c,8eeff4e2,ce9a2d48,2be8346f,3446451c,13c04380,292f1f2c,4743b097,211c807e,23cd13d7,692efc44,202c44cd,dde5a89f,9e7cdc5a,133e996a) -,S(1aa55d93,bf318133,8840ae4d,24314ffc,74420002,4ddab165,4018604a,2192ee5f,babac354,92d59e8a,656ac7e9,9b6cb2cd,7a6a8e88,1361118f,41e38f1,2cbc3bfc) -,S(75be4c50,db7bc629,e64fa850,3d89f722,34d214f4,9b176fba,b937120c,477dcf03,b5520bba,8c606db2,833d934,3c860c6b,ed2e5e2a,41a6c3fb,51154c82,94b6f819) -,S(f3604822,e4ed8b2d,d4b2486,b611b95b,6508e10a,1c725c7d,8d638254,3cef6c8c,f405ac79,7404bc6a,25a1a412,f2cbd698,75d99d2c,b23ac105,f9839446,222dc0f5) -,S(6c9216e6,6f9326be,fad5f727,ae0326b1,da54ee91,f041d2bf,2d87dff0,e77cefe8,64a021b9,bc1947c8,df546f92,2f5230df,1ec2f372,50651704,557377fb,39d16517) -,S(ae479bbd,ce97732d,df313861,76807678,988346e2,5b12bb09,e74d474d,6905668a,a3ce0355,c5996087,89936336,64d9bdd2,b33a6f97,ea3f28b3,f4b7c0ac,92612929) -,S(ce92c179,66f74db2,1c6abcf8,36cfd2f7,9ccc05a7,aaaf74ff,4807052d,754898be,f3e3d3f3,530f38c4,ca59cec9,c8e3456b,8adebf80,3f10927c,e44e79ca,601bb978) -,S(8a0bbeb6,815275c1,77553d87,5988c4dd,a96f5ae2,378a3b9f,477cf162,6e6ea68d,958b795e,46f45412,acaa9f77,85a4e34,a7c74eac,228476d6,4e917983,5fe77f4e) -,S(c2a44ee9,975400e2,912a033c,5ed1e7a,7f0e97a7,1c86e8d0,c2e5136,8dd9ccfe,956435ef,7d24a507,dbfb69b2,93b51369,70cd17b8,ebf6bc60,596a9545,3675668f) -,S(b615f625,534ddf61,47b78520,85443bcd,3d3bbe91,c815dc29,3cc891c7,199ea1e1,4cabf4f1,99e21468,62a90876,4f65c624,fe3afd1c,6b399e12,267dc1e7,6ec3ea25) -,S(afccaf8d,fdcf272a,cf56dde9,3980bee7,b64a0c54,f80830b5,5fd0b93b,e8a75a0e,8d8ec5d,6f6fc44f,89f6d9ba,735861af,e7d6a660,7d88e95,54f2c141,1042a63e) -,S(534176a8,c5311b26,1f39395d,f78300b,559d072a,cb3873ac,32833c8a,9b135f53,ab84f84b,5eeea7b4,87ef6639,8fa756fa,b16155d,683ef643,b03c7e6c,8ab2f436) -,S(5f7aa173,97ef95cd,f47651ac,6220f3f2,8705abbc,6531b93e,a65fcd14,1b91f34c,72f7d898,3cddb34f,2ed1b28f,17a77d8e,70cffcbb,e0462ab8,b7548561,9881da22) -,S(d4fb4a4c,c1e2fb72,b301db19,335afd7a,b6a95258,6903f449,aa287fc,ac8f3d3b,76b572e8,4a9db287,19d098cd,5dee787e,f213adf7,9ae90306,8881894,e14154f9) -,S(3dc67563,843b2f3a,f793116c,23db0dd0,dad0975c,5abbf569,4c6d454c,9f7a9ff4,ddf65b9e,4db83b7f,43d0ccf8,49a8088,4894b277,4fb39fbf,78076a60,356753ae) -,S(657912bd,1edd014d,1386c449,50cd1667,9c3e415d,b36e36b1,3bb5c82c,a2f897d6,4e2fdfdb,11bbe240,8fc7fb3a,acd06c69,78205e48,c9f5a143,4300927e,fed505cf) -,S(5a453b3,5f82585c,f64473e5,f3fe937,6f412b5f,c4ade7b8,f9081717,3fd69f99,fc169e11,3448b590,4e1dbf06,f4aba1a3,ec2fb4b5,7f2b4c4f,a29b6617,58097ebe) -,S(c3adf45a,c24b4bc8,69acfaf1,f96a3043,d01c68b2,f4ff689,93b37b3,a4052679,3d923207,cd374b49,d3a85bea,972b8d09,4f0d4b83,cedc97d7,edc2ac68,10ae19cc) -,S(1a32edc8,905ddc84,2756420b,e1f25daf,5bd84f0f,acb046b6,e9040fe9,5e1e1d56,7f467d9d,113a77f8,c1cb73ad,16a62f4f,f1612c80,f8cf859c,ca42164,68eb4c51) -,S(70957d98,62e5977a,c328b7da,2e51024a,f925c142,eb1a46b7,b4a3bf20,a74d6c98,269b56c6,2e42cc34,a0951348,881d2c53,7d7ee231,f2327ec1,441fd273,bef09381) -,S(7e69416,5a02b16c,107ae454,b6cdf25,bf6dd256,d976ab44,bd7edc84,837537a7,ffb874db,38360c11,e2d0d2ce,3e47363,a6aac21d,78a37b24,3e66826b,445185f5) -,S(4f81a159,7b42e9b5,24be7ac6,ff4405d8,3b9d8a75,e37b58b6,eed5525,6ddf9678,b2531207,18676065,ad8ffbe1,6d27df4c,3558eed7,992538b3,77cb8497,86e0a78c) -,S(fa250368,577065af,b60be8d,e9381334,9be6fdd6,1bdd02d9,3591a35d,294fd547,f0b991e3,96c77cbf,5d642f0d,cf5ee10b,3b0a1fa7,7b696f06,d4d61cd4,48e81625) -,S(f4df5ebd,67162bfc,3e3da517,23fec6d8,6b61d6c4,a5876c4d,440f025a,272ba3d4,b23ba279,8bc75fb2,d590e384,c9e375ce,6380dc5b,90970d44,674e32a1,8052212b) -,S(ab5b6b1d,b3725b65,fae28e5c,44460d6c,51b8971a,655541c,4a587076,a1ac5015,16d2c457,ecdc1718,3a9d7876,d785adf0,424f72b8,d08b6a9e,286ea5cb,26ee2ece) -,S(a8a4ec7e,13db5370,40680dcc,470d38a4,2e08d99,3c30f981,ac877ce0,28869e55,4a9ded9c,2cdfee53,897d0874,965878a4,754025d5,babb07bb,2d248151,cb7f60a4) -,S(337f54f6,33bd60db,583d08,165c1011,6f914dd9,e2abcfaa,5f1b1410,b8245f48,9453eb28,696afc4a,40b5452b,d3abae4c,679b58e5,408b0a94,ea456771,8176dbfc) -,S(eee337ab,dc2baaf1,544c767,41a5054c,f6db480d,529d20e4,33b642b5,fd901b53,65ad5b88,2cc00d4,a4ba1d8b,a6956f88,825616cd,5f6c9830,87264247,869c27be) -,S(59f52e18,57cb000a,ec1aaf0c,b43f1274,f56e477c,50f010b8,4513fcef,752f1548,d8ca8f6e,8db03b19,8047006b,a6ec1e29,4f225461,9978ce70,a1ae0f53,9e1698be) -,S(6c200a0c,25fadb2a,8a9618d9,d7d86287,8583ab10,f2b4915e,8f5a5f05,406f3e12,14d4984e,374cf35c,145af24d,a5c0d0f8,504649d,b1793a61,7d6ed949,ef8081f8) -,S(1654a2fd,51dfb6f8,71aad878,239b657a,f8144ff8,98a3c2a0,32cffbc3,8aac07fa,8b6965c3,82d98569,b6cdcc1d,4c71705c,e36d46c5,fa5df714,8d59043d,161a839c) -,S(c48033c9,ab473556,c9982f33,953f96d6,7b3ed1c0,7e98efae,8de232f7,67556d77,af3f48a8,7bc43168,10787382,8dcffaad,abe4a54,828b02b6,f897ab4b,ed968bac) -,S(5dd977fa,a9d228d5,1885aaea,557f7a98,1a95771f,212c3ba,f1a4e428,3c3c6032,3bff9d4a,ba178f6c,d2ce5204,3daa06f2,abb06acd,274beb45,49e72a37,8f2eb656) -,S(2a76dc25,dd9a96c4,bcff1d8a,f3c9aaeb,261e4c69,a5d832ab,efefdf29,ce42a564,493452f2,3ad5cae7,de8c972a,af5c3883,7ff82aa,df616c5b,2fcab4c6,d5244806) -,S(cdbd3506,4c0e7923,822bab4d,b4662b2a,fd3935a9,a49e6d6f,f2db8f4b,d29a4b8d,b2126f2e,b61e274f,a688a84c,386fdb5f,58b84515,1543f143,a8ce0a3c,557a90ce) -,S(983f249b,2cb9d4f6,34d82d6c,e713aff9,2bcfd525,a4146a75,bf6f725d,2b54d978,79cd2406,850be02d,a6c4d25f,5a02dabe,af302e77,238833ef,cff0484,8a8abca2) -,S(88c765b4,a5a0a9f3,a257e21e,ffb23e51,9e128489,fade1383,96fdc18c,38afd4f4,f4d5fe64,729995a3,e505cc03,1d144682,e3336ae3,45c28697,1cf89b7d,595f46c2) -,S(197505ec,d603cb0a,199c7d08,b88d0e63,1d147d07,45603692,6b67a582,b7d52c31,947ec13b,f2d75fc5,af5a746,15a75aec,2f212adf,a234e08f,49a561e4,f9057f15) -,S(98184232,e10f605f,58a700c3,d6bc04d,9a19790f,eb638fec,668320b6,3b2eaaf8,ef3076ed,c0e2fa39,30ea837e,36c31f59,dbbdf192,ab18bd7f,39578e1c,eff9c85b) -,S(50f0db35,cba0134b,790f47a9,e322670e,f0c7d081,6869a764,892f8e23,6c0bc002,1c1b1c13,d98a84ea,e77260f6,58e265d8,9e466b44,b8604edd,83233fcb,68396072) -,S(d9e340ea,1a44bb50,ae4bb19f,3f4228f4,99ac8516,cd6bfa86,80c1dc31,d5665502,128a1688,335a2193,ff805251,b83baee9,341445ad,25048f75,355f4b35,5b4aaad8) -,S(15aa8133,1b84ddd,8c706702,555dc19,d42cb4a9,a9474c9,1e33c0f8,e87c539c,79530720,96586400,ebdd2ba1,7762ccbb,2a14bf47,45f63b1d,e22c6a6d,8942dbc1) -,S(6f708704,53d19a4d,b910d169,c7c7be23,d489dd18,23604242,55e182f8,7a5d34d2,e0531956,7c1c2bf4,a0a9beab,d7c4dbb9,c15246fd,5a6de101,35578aa9,99c7dde2) -,S(31e920df,cddca3a4,89ad97e9,168854f7,867f9a58,fe2d3f1b,f33f8dc3,c7167674,52712c3d,b0c6e58,15157660,ebe27dd,244a9c5f,b12cb8af,dbe82900,c3706f39) -,S(93300e11,708ff01d,96f81fbc,f1888c96,8258dec2,86a315ab,8d01f2da,4c8d51d8,15368647,3b6a208c,8449b53,66584e4c,9e0b7636,1256df46,4c93d4a0,e26c33ff) -,S(8f7ad50b,f62d6702,616cfdf,3712c1ca,30c94632,720797dc,ecd54f65,cfacb3db,5ac10a32,7dc52bc,33290080,a1a194c8,1eff0d71,65f9d34,7e4f8b44,8443c637) -,S(6ed80b82,76270d71,c468f5d7,350c608a,7f5cf51d,c8efbdd7,4458a487,2989f4a9,bcba2bf7,38f6e77b,465e47b7,c687c7e1,77fd3cf2,163b5a2,e00923d0,89826dc0) -,S(ec6c1d7d,b94989e2,962cb85f,777eada2,7c2b11b2,86949e38,eea2bb4b,7ce3714c,add9f9af,6042dfdb,1d4089d0,ebca5755,8ef2664d,52fce516,df3b030e,9ed08fdd) -,S(8f77cb2c,24dcc192,593a82d3,510859b9,c59bca8e,9546735c,1fe26084,4a37f093,51674986,fbf499fa,70b55bd4,f0a70cb8,423fdebd,587e6213,83199b3c,4fe07202) -,S(e2addf74,dae831af,aa4c4ed6,2f4a32dd,1122f2d6,243d049f,1fd78c1d,64b6aca,7dbcb394,1eadfb0b,8a56022,4da66128,a73a1aa0,20a5b23c,cf58118f,e28b2297) -,S(bf7af1bc,614d31c9,9afb7c6d,b8cd45b3,3a22b151,34ba872d,3e845da3,2b1e3eb,108d39e7,8cf88a22,fba9e255,23267bd5,2b850464,f1277239,7542ec2c,50125a21) -,S(88ffc7f,cec6580,5b92c5f6,952d82cc,35b4f068,a7581987,93ebc59,8efe50e4,382dacca,94b42c3e,ba1558c7,82394564,d39193c9,8b9e8cf4,a63dc4da,4d378a4c) -,S(b114a384,ef4ae60,b9c569ae,636eab27,9070e207,34cf83b7,a28353d4,7d3a152b,37c7673c,e58ee20a,6076438c,9bbe5cbf,bb826076,6d8a7001,b188c477,cca3fa70) -,S(e411a42f,e20d23b6,fa768fa1,e310192c,cfb0cd2b,1914c9da,627db3a8,c7e801b0,feb1b79b,43ee7980,7252bbc1,728af29a,8f6828ae,8aec480b,91c85008,959b1039) -,S(191f687e,46432313,c085182a,ede5e7c4,31057ad7,f1f48fd7,cb814fcd,74ee1999,5464b42b,3f77ce2d,59a39efb,83808cd8,43e5c540,3d5081e6,e4f4b1e,926dbc72) -,S(63ff4977,33b0a49e,f618c4ff,1aef537,9837744c,85a19bf0,b2208eb9,506bcd81,6ccaef97,ca835931,f3a87b50,a93f2a4,39535d8c,87e26090,3ae49b29,30593d3b) -,S(efe36425,c37705ba,69e7056c,2e8c628,f4ce72a4,68d85556,4c57e5ad,b7fc2c1c,392b9b5f,27ac49c5,831a5f52,c2e55bb2,8faa7f12,521732d0,8dd910c0,51970ad5) -,S(6d2126b,dd7cc08d,1bd41910,21704a1e,841d4737,4e5a0a99,9880051d,f77e94a5,2e9b823a,cda1be97,52f72ce6,ead42127,efb4d4b0,8daf55f5,5da6f956,84e6e806) -,S(cf7b9ff4,297d9c5b,91c6340d,c1cca93c,6d453ac9,86b4ef54,b20df6a5,4933743,8a57808a,2c07002b,111efec2,bf751b54,c20613c4,1e3612ca,83baa3f,eb670c15) -,S(b160242b,4cbe5ee1,d1dba4e8,e2d55a0,27f5a5bf,f7c023f2,c1524fe6,5f7e83e,ac35795,6cf31260,7ee9f54,fb39d3e,4f1faaf4,67d09567,6075b8c6,3c0fb5a0) -,S(7a86452c,4f8918d9,86d3dce0,22619a72,1744d9c6,dfd0e733,c02cdaa5,6abb050e,30d30b1c,b558b0e0,fbaa1fb3,596cf454,542370fa,43d8a85a,91eb6bc5,c90de179) -,S(a279bc1a,64d206ef,ea96d3a,b97c6770,af41ba40,9381d372,408052ff,582323b9,aefc853d,701ebc44,679a7ab1,fe033182,e96199d3,4b58261d,a1b4a6bc,6ce42046) -,S(e8e28570,5c16016b,608c301a,ac59f868,f7691886,261eb01a,d4e6ec6,a9e5cc76,92350315,f8e78051,b703b7a,49427272,c988ea66,27699eb8,f2fb3eac,9f0a983d) -,S(1fd9cef8,14f3fc81,8055f300,a734f9cc,46da1585,b939be73,459e0ce1,8a9f2bbd,dcc4f73f,a50fcc8e,6ec3c71b,c045f020,c26d79a9,794a25cd,26488c0d,9cabb55e) -,S(321b1afc,70275fd6,fd48942,df364f6f,c609d4b6,cf4e574d,39f1ad06,927e5f11,1368ecef,808bb311,ae9ad36f,8a4c81fb,725a80f8,ed029680,c5b54463,80add33d) -,S(4dff29fb,6518e393,dad0cad9,b0dec257,f9ef1e9c,c50cd741,8108c42e,f6d7bf72,4159786e,5aa4e82,4d7bfd06,713ec8f6,d92f8f8b,48304efd,e4d0f4c2,30dfb70c) -,S(937a84a5,eb63055c,65b162e1,1a3f2e54,c839b972,95a8c1b9,274373f7,5ced1e0b,a03078bb,bf11a351,da7fb3b5,2e3e7a2d,62c122b1,a9cf9954,53294f37,7966afc6) -,S(be3faa9b,7cab73b8,4fb2a87d,25db7fc5,56f07393,b3177c7a,56df0447,e96cc3d2,e7051ee0,1ad794af,571dacc4,4e91f7f6,9276446a,7e348ee1,2998968,afaf77f) -,S(58b39c6b,cc36d506,765d24da,6058d7dd,36928d13,b0fbe1f8,c680df15,756c9b41,449e9691,aaa846d9,a7412b77,73f7ae6f,b4ecd99e,c57863d,ad72d3f0,423d74ff) -,S(9b18a971,b1660b46,720e2100,865742c,8c91282b,1c72c7b2,8192bdc9,c3765798,2812e522,98adf83d,2cc07a93,4a065016,2be28d37,59cfd50,6c792e31,32e0f49f) -,S(a6c44c03,dbacd4bd,7a35e207,61778826,c86740c5,c92942d7,f73a1b3e,dec0f59e,73316b7c,d1fa3410,76b73727,8aaf39c6,2258d29e,c40c80e0,797493cc,7056077f) -,S(1ffb2755,628ff8d5,d837495b,94ad78a0,5dde2043,bbfa3aaa,21a05a3a,21682ee3,4a0478f7,6b8b6c,ffd9962d,f70e2a83,a71243ad,c690efec,5f95aff8,dbb5943b) -,S(aea4c48e,36051144,482538a8,8ee5f72,b67a21e7,8fb425c,3d6f1e78,419b8283,4517cab8,c28eb397,bd89d216,ce711332,82c7b530,6b64499b,2216bba9,41a80b27) -,S(ddc59bfa,5f8c0270,8436fabb,5003ca6f,b972f14,382bf127,f5297990,b4ed3eb,f6c3f19f,b80e75b6,53c370b6,742045e9,ad7dbc80,3a996696,99605345,ebd995c1) -,S(22184fe7,ed301b2d,62bf83ed,64742f6f,94d204c9,866a637d,d03c58b,54c80a8,9db27528,1073a3d5,617a389d,c5698255,3bc55d6a,3b80cab4,ace36140,8179b442) -,S(e58617f4,74e46f4a,74b0ed2d,6bafc3cb,6488c510,87136eea,f98aa37a,f201cef3,cc6a7375,52dde05e,71bf2047,d49a41b0,c6b141e2,e4f519d4,36d4f8e4,f2aa2220) -,S(c1aa4092,5addc5fe,de6c2c5a,ba73b3f2,b7394a0f,1d02846c,5b2a0379,824f8e41,9713af07,e30af560,9516ce73,5083ab53,2475bf26,5713570,28b586c1,d28c687b) -,S(4aa5d88d,89576459,1ccd1c2,3064c718,69e4d320,b0b71b5a,c08d291a,c1df6168,1d0ea41b,915c288e,c6b36cc3,f7806481,c048482,dce586ad,f240d32a,c913e6e6) -,S(93876d91,73137834,dca5e192,fa869a02,738d4171,391df1e7,43296f93,a2a8a977,7948463d,32bad450,24e63d9d,d5786a69,73fc6c8f,9d2a7c3d,e2d6fbad,7a6457a4) -,S(c80cd7d,30268025,b233dd13,f2f2af37,5d18080a,54c406ee,50e4890f,a91b7b28,9f73b58b,1f1d11f9,1648f904,ac7ad275,9e6260c9,27870292,278fe521,b718bc4b) -,S(d2bd24d9,7dd4a345,a8c4e857,97a9c30c,e8e7e7c4,3ce79bb8,fba4250e,a0c8c5cb,330f0cb8,15cb1931,90331055,809eb028,55ae895,ee1a30f7,665166b9,6494b9e) -,S(d4e4a3a2,90deea18,fb15457d,f3ab9815,5d722589,515a38b8,dc303307,5dd7e9f4,4854493e,77d0ecb1,742bdc9b,a5219e9a,71c57a6c,b914b8a5,6eec21dd,3e7d1c21) -,S(f0fb6cf4,810de399,fcd1b246,f0e76e2b,d318f82e,1601ebea,2779be6d,47236d19,e3ad5160,66480239,88b0b197,3eb2a41e,2cc9b4d3,7cf58d07,ad0edde7,ac595daf) -,S(dd4ec58e,3f4c470c,36991740,d02b0fc7,9a4f9df1,98647ab0,ebf73b10,34858939,3a6ecc86,a3b058ce,f278c839,541e92dc,737a6390,94ffa464,17e37da0,40a3bfe3) -,S(ec56910,1d7ed954,d4efe1b6,c4f6ade1,2af12f3a,ddc75a8b,8fdaebb7,ab904e51,3497c67f,5d594f71,4327111a,e22f2621,be7cbaad,b2cc1d6d,be0b7e50,d450c54a) -,S(ca45def8,51856a5,7ca5e1aa,64edc3cb,e25ef6b0,e28abda5,a85d9a19,dbaa35c5,db8b2357,268db9eb,e013fcde,111372c2,6eb4ed69,5a7a3df0,4d1d33db,703521b2) -,S(b44c5388,964521e2,4803c8b6,3dc8a494,40f8ba15,435ce2e6,5f6dc092,15b49a47,2e16435d,f30c4b80,cf125e04,b85166b9,509890a9,c1daf1f5,72462a83,de198d00) -,S(95b735e2,35862f14,e9291a5,4b46d977,33a20ce1,b59b4603,666cfeca,e05dea26,e1281705,5f38be19,9bc9977,b6e80c08,f22ab5b1,286ea553,21145675,264aabb9) -,S(83d9d867,8fbb0263,6ce8d231,3ee4716c,a15c71b2,66c1a7ce,e56928ed,73e5bdfc,e0494c2f,be92f132,effe7d78,499f4a00,c35027c2,37df8545,9918687b,6b949246) -,S(98b7c85,a04c546d,bbf6bad1,6914e247,1d3b478c,f30dd6f0,2e843770,49bbae03,769c3b95,3733dfd9,d9027da4,a10b0a65,ce4106f9,44364972,e569c63d,3b2ace57) -,S(3ce7b677,852d34ec,34358a8f,4da66d53,75019cb1,19a45dfe,864062a,a3b12e45,68d2790f,1838b86,96272c4b,d5e418a9,2cf03d9,de44f218,e42562dd,467e409a) -,S(a0bc28f4,d4da7101,41d0dca7,51542b83,6b50bdc8,997b291,e074727e,cad7836f,6ed7e149,40f2781c,d685a581,99f163d2,177eecbc,ca785224,2a8b4859,97e47c88) -,S(9a571ba3,52b1d62b,4e5d290a,c0d41983,97750fc4,9a18cb68,18fe11ab,1e185c0b,1a91cccd,b2b1f58f,9cfc0dfe,d3464917,f6c2870,9bdd8128,ff61e295,ad1b4ad1) -,S(fba0544f,cdd2de73,d24eca5,55a8c4b0,4e135c1d,8348cb93,d53f647e,2a21b9bf,7a11a425,a4ec6acf,2eafe631,ff83be6a,f71a6cc9,f7dbe3f7,aed57e04,2774568a) -,S(d96b253a,1edbf662,3902bdd7,1c3bad9,ecad1115,45614b48,5f7abca1,d4920a9b,2bc88998,f951b831,2f27d09f,2f331536,1499f1c8,b172f1f2,408d0660,3b18c2e8) -,S(2b3c17ce,1081b825,94ae14da,f9723f9,9823382e,947c1356,13a4b8a6,42267c2b,a4cd589f,2ebd245b,88c7f1fa,427a2ab6,e77205c2,dbbcc74f,dbbdfa69,336048ff) -,S(69698780,fdac522c,69313ea7,2e244d9d,3f6bc5c9,4fd86125,2eb56369,c96439f9,e8eeb3c6,460f475f,c06b5943,9bb9994d,8d6e4314,fe20020e,c1001f77,25a03154) -,S(1e344611,4cb4dc4c,963e172c,9bfc2f4a,d1577efc,ae2ffc6d,76395ef9,a0848c68,debbb8df,e6f59a0e,b96d464,3bbc6d51,a2bb4621,6059de1d,a473436c,404f5b19) -,S(6ccfae02,4c7f2a9a,ba12c191,bd35e287,d5c30284,c4273a1f,c558ae8d,286aa61a,c2014174,c78a2fd,d342ade2,51e4588d,94c4cdf1,ee83ade8,54e48388,b6e7cb11) -,S(5b5fd487,69b6a133,35bf0a2e,61a2128a,db43153f,9497c77e,c32b16e2,ca4c728e,9954353f,b23c9d44,eadf2632,168711b5,5a54c9da,53c41088,50fe77cd,8cf00c77) -,S(6b74a257,27af44dd,61fbbbd2,7323b63f,e6a41d9d,f5412215,65a6a9bc,35d069e,a4e1214,f17b8dff,b5bd689c,5f004c98,39b87a46,15245756,48099d33,f432a34c) -,S(5171a187,8ae9ed01,837408b9,fe08f317,8688606c,aae04b2,63cbf143,b8e372a2,b5e7de6b,964153cc,fe64a472,8a8f20a4,44da8e15,c593b7e8,68140276,b172d06) -,S(df9e86a,4337ef32,3518568c,e52958ab,dbce8a92,840b756c,279e96cd,43c8e80d,5442baee,c72f460a,110e8ff6,1e938132,50b2ccdf,61941df,5f591bb4,73027da7) -,S(ce070279,eb6f1f71,af876ab7,3903fbd0,ac9e4693,7b6d3307,2ec80182,3887c850,de83ddf9,88f9d345,e1ff2a79,e91f8ad9,6ea23097,538dde84,aea0ded4,b6a155eb) -,S(a0255c62,44afc84c,58238936,c9d08d36,96e5789b,ed28c40,7667f348,4c2f35fd,93e2d407,aef898d7,c898293,fb20f222,6cd5017,cd62669f,17ee0d16,773c6f7a) -,S(ae82dead,b76d5dd7,140e1197,a383ff62,138e1840,dc2f7ef0,d5126dca,86f0d86b,239dbbac,caaa0779,a9f6d8ec,2e30b590,72d36b58,199a27c6,5f5815ca,5720964a) -,S(cf0999ce,bee65e2e,d596441e,a8942461,97c597ac,9c090884,44c375d9,16332393,6620cbd2,f074edd5,1ff8cd5,45adcdbd,1c664ad2,6935880,8655ffb3,3a748ca4) -,S(5fb4af74,6404b01b,63bff1b4,1bacbb36,9ec06801,9454622a,76258033,9cd3965c,464cb2e1,2cce697c,d409529f,a48e7448,916a51b4,5954fe93,d99ce392,272abff5) -,S(15af3c0a,46b5232e,55e5687,a2bc4acc,2c7a350f,8114e3a0,1993a0f3,1b3216b4,ae03739b,bdce38b0,4735acd9,3a3ff7ba,86c8189e,56a5bb37,ad83a574,cdd45a83) -,S(5d0035d1,d008ccc5,42cb8b5d,32d973da,32c88787,640d0465,76d33e36,540b4b10,448ed8e5,bffa9f28,6689061f,73a74f17,76db8a8c,d5b4af39,6173e7be,6e54c465) -,S(944c70f3,9cf749df,edb9d322,ffc69e3a,a40b0704,fc4af915,e027bad4,83c95527,b0ac0c3b,bf489332,64a6e95c,e49a669a,df10acfd,48e22fc2,1a18ecbd,b86c6f0c) -,S(fa5219f0,82ec3c4a,3f246754,dad62f04,52e26225,6cd28acc,846bc5d6,151e4402,32ce81e9,d6403132,d7b64f26,a0289031,eb730d2b,dcd0065a,1b4e3f3,a7afae9) -,S(c9f4aa30,ddbee263,509455a,858b8518,85c6a16b,5d9bf032,70443928,38a30ede,5ef717c6,b438af31,9a892799,46b73ba7,add20334,c2fa5bae,a15b7632,34ad7b7c) -,S(2f4cf3ca,7454d569,5b0dd2fd,c72d4ffe,529b362,deeea120,162c178e,7b770319,dcda920e,3566ebcb,f47c1ce0,fb767092,fe7c87c5,ff146042,d5a0ceb7,a2f7d487) -,S(2417f576,2e0cd74a,f07a41a7,51f91b3e,a1cb0a42,2246af4,a0a96b8,79969945,6a96d755,f8dc71bc,adad0a3f,61cb44ed,741ef96d,96baacee,fcfba7ff,1e7807d9) -,S(9ab22f84,305a1c1f,675ca5ba,cbb3dba4,d43d060a,ee9148c6,6cfb61b8,5888852c,af0506fa,a2588e3a,7aeac12a,7acdda3b,b51d996b,2cca9c18,e23b517a,a428a03e) -,S(f7421ea2,24627926,28ed878,7e154724,77a91726,5a162f52,87501d1d,24a72b6c,db0ae665,e4484132,f372ca6d,8cd46115,fe1c72cc,885804dd,8f508900,5743fcf6) -,S(35756af3,548d57e8,dc0bb791,8b9875b1,10a912bb,7d971e35,4963bd7f,df5c6f75,1ca46dba,78a2b4fd,d4ed69ae,bd4e1961,86d94b8e,20b1660f,c517098d,e077a1d2) -,S(a7e9f00c,494cfaf2,16449d9a,b0dae7ff,de4041c2,fe031bc0,241c44db,1bf01837,f2aeb9ae,480b406a,9753d009,3b5fbb74,5a7760de,4ef508b7,d10804c0,161a0280) -,S(69451dba,92872879,7737755b,7655ce70,64838aa2,9084fc1a,c88f5e6f,ca62adb7,26218fa8,d40df091,31d845d4,96c7b950,1071537b,51a3143c,c73f1a7,b02b1cd9) -,S(c49c3b30,15cca66f,ce986a37,588205fc,89a92d0f,c520ad3,5eb6cce3,daabf06d,7afde84a,665b02b0,e0cf9ca9,9d2ad097,6242919c,53e31b5e,6216d67c,580e354c) -,S(e9e181bf,b68e6e38,c5b6ee1d,f11c14f8,90c0c744,8570387,1ab6b624,6b9dae8f,b0bcfedb,3f394317,907e260,c3651aa4,d1af5ca5,e1a34018,fc6c26a2,d5ef5e1b) -,S(a428586f,adf41cf,5b5c9e52,e0d6e1f9,2e7d8738,ab99e8bc,4062e302,de392324,77c3e18b,fe71c937,65b911e8,b49cdee9,a2a7413f,4de831c8,3f967f08,95b8d142) -,S(f5c92ed2,de1d1a25,4b4a4830,b656a674,38077be7,5efed94d,785dd0d9,72712cf,7ee98d3a,497849cd,5b5f6dcb,c51c5119,228fdf7e,1a67f1e,d7c670b9,eb3958fb) -,S(a85707ca,6c85f506,311b6930,767b5571,e18c19c7,ff2574bd,f268f018,b49c3f66,1785fe71,cde2e189,aaf67d10,337b8fb8,53654335,4d5ba73d,77518d9f,5e8aa050) -,S(8866f5f,a4c8d1c2,f2de0cf8,19eca5c4,d084ab60,67a7d97c,f9942fe,c0a7468d,3014226c,3f33907a,2f6c49ad,c762be6e,2915288b,a7ec009a,fe693048,3588336e) -,S(425f6d73,37eb2d68,e17d07c8,bda406cf,92af22b5,6461bd66,f40be14c,ae0688cc,e865526f,7c42e391,1ab73290,e80bd9fc,9643659,5871bdbd,ef8d698f,d04d4980) -,S(f70fc3e,1de3b3fd,55418441,43deb4be,36bfe6af,3bc9d9a2,f8ac823d,68323139,8b47994b,1febb309,e3774a82,d6b18d78,8ae5750b,40aa944a,dae404b5,da24ce03) -,S(1be960f3,38d2a16,703b10c,eafa121c,d59c66d9,439e9067,58a0b363,2a83116c,7fa4ca2f,8218ee04,351549cc,3b0100fb,647e0db,19eea010,62f1c0de,3de29aef) -,S(1f2a2d3,bc5c80a3,8af51e9f,5694a80e,e915eb89,4831ea7e,48472d53,320cf385,a18cea39,174b4c49,f9bcb945,5e6701f9,47053f07,6782ce9f,f55653be,6d3940e5) -,S(61d6b60,70846b0b,b7790861,17cafaa9,9aa67c37,fe77140e,88477f3e,44d04766,c7f4be90,86849ae1,632eb59a,6c96de66,b7c4b1ea,caf724d2,5338c11c,a8f2688f) -,S(2b37093,2d9a6451,79508daf,4be7f26,6d540538,9276fc4f,e6ccf0d4,1ee6cc9c,c002a3f4,2c8998b1,ee16a1d8,616ce0b7,91cdfc44,61839d9f,5ca0090e,295beca7) -,S(48f5c3ef,aba8b7a3,4d7fd136,fe9b01f,64af0e95,6a27663a,87cd6629,f2708858,8cc38cb7,fce46724,7c2f09cc,52f973be,90aefdbf,b52895e2,b88f03e8,fe32b5ab) -,S(e609b597,2e5ec227,6f5cfc87,67b6d534,adfbe9e9,9e60b86,e981dd9b,3e62cfa0,6be9c1ee,ff205fd3,e3b85e3d,bbf1b27a,335ca616,9ae189f,a433e65,f2b43081) -,S(ebe40b1a,5b2c9cc8,46eb8ea8,1ef0c1ce,f19a767b,2da6ab0b,2ab66a01,b16d205a,2f7710e8,e4fecbd1,39899bd,1964f5da,967d6920,d70b2f4,45d6f914,97c67058) -,S(97cd4c39,9391b1ef,653d32f3,9b062bcf,dbc72d45,83d81b3f,f70df659,358e3abd,a05a6184,a175b6de,f9bc35c5,6e9f5cae,263acf2b,a233bfe8,13dd98a7,fbf37968) -,S(826928aa,1d3fd0e8,53cd99fc,e6559ae7,257343aa,378100e,bf64a3c1,bea7e6d9,bc4a2db1,a3bde90a,ff50fddf,cf6f844a,faad7f8a,89bb399b,20b07b2,2e1efc79) -,S(3e754097,f3ac95dd,176e9181,410bae7a,83bd1431,6772e398,967ed39a,5fa19121,746cce99,c6a2cff8,a0907ea1,5cf9436c,ca7f94,7f3f1801,135fe675,a518df32) -,S(ce539464,b49b9947,808a236c,8a027066,82991f46,3bb828fa,44653266,329365db,3578fec2,b8bc4763,61f2fda,29c2c38b,a7bda79c,11b2cd41,a74d4c02,762e5dd9) -,S(c933d9d9,cda615ad,7ac41d6a,e64a77cb,44a2b669,21533669,2c90c3af,53e349dd,4a6da24f,83baebbb,8f2a8ede,298babce,a25b054a,a1c4cc11,f9f0b0db,572c610) -,S(459aa43b,1aa9815f,e9116f2e,78ddddef,a78e2def,28027d51,d081a3bc,800b2ac4,1acedbc3,de995e30,b16900d4,cddcd1f2,5c615156,fc29645,4bd5fc7c,63e993d5) -,S(5f2aa5d9,9862ad29,eb467564,639abfc,ff445334,9a30c4d4,3b27f913,1e3b0a5e,571eca2b,e61d0bf2,d9def9ba,445b39b2,5acfbbb7,dd4e2cfb,ce7541c9,61ace144) -,S(ec66ea1d,e6cc5d59,8c393e68,1a338549,fc2c3d7f,947b40f5,75681e60,88f4fd1d,d711ffdb,3b378435,5894dfa9,d0a5497a,5540739f,a3706597,8ab7dbea,a9280f52) -,S(6ac53df5,aa097f2d,9983f018,bd1cab39,69ad0638,c78547ab,1a481682,ad6105fe,95f69a81,5127b919,9488f224,24307969,3cd51796,bba08578,abfc8e05,6618a598) -,S(a8a3e9e2,9e4ad0fd,c466dcb8,fdc02cf4,16fb5c85,b3454fd,3842f129,9f96c0b0,df86eb3e,3006dea5,ed6d152,f394d7c3,169b8d09,bde3685,ce138a55,6716dc2b) -,S(50a764d2,a0d8741b,95ec84a2,feda6df8,1dbe987c,31861166,32c40c3d,e6db251c,b28203f0,233917c1,4b67632a,ce9b512d,76a8c7e2,430a4a40,85cfb422,7fe41055) -,S(c2c314b1,5ef9df1d,26856c9f,a6e39cf9,1bd9c584,582893a9,423746ca,1ab51ef9,a27f9286,ff7fdfaa,b949a9f5,d59f08b7,a22f1e31,e7175d44,93e219a4,e92ab759) -,S(ba655585,da44c8d1,2b3ce375,e220a4c3,64868b75,370fdb75,dbf6bb92,76a9d3df,3d64e16b,a03a385b,def18f61,432cc49c,bdd9d04e,6fc8873b,e51663bb,ca4fda50) -,S(3d45fa49,d4d100a4,b5a76a65,1a5100e,56bd0d13,b9e141c2,aca5cfef,a46e600e,92953c,38eeee42,e1da93b1,3c75ba48,da30390e,731801ec,ed5bdc2b,58059176) -,S(e464c346,e40dc3e2,40e5d96e,1fb2c10c,83e5ab7f,45138596,4ca46b04,bc8c3a8c,63f14b46,182950bd,282205aa,374cd67b,ca364a4,f57cf90f,c7ac90d6,5204cf4e) -,S(14a7e12f,e235b307,5b0d218,bd3dc720,d56f3fe4,c73841e3,fdf42dd5,aea42688,d79683cc,40cef482,ed6a22d4,8137a4f0,eac31249,9ae13809,9eebf3a3,15e9ff2a) -,S(8e7afbb8,21af73b2,25b34ffa,bb2ff6f4,61d2ee2b,85d5d936,a99fb078,963828be,40e4776,5aa0768c,f055bea0,e20e1062,bb528470,dee61ec1,6cc9ce7d,ae6b1853) -,S(9d641162,3227bd0f,4bcf9f1f,9e5ce829,7d844055,8a7ec246,5b160690,53297573,ed0d83a0,68001be5,70067ea4,70fec09e,1f8630d5,da5d1b2c,126c35c3,9b07fc8d) -,S(6758c6d6,d9e49d9f,4125b52b,e3da74e7,52bb40f1,44af0f0b,7bd80589,7fc83eaf,749ae08e,c2aa2c36,3a229b3d,e9577dbc,5f7d22cc,d46826e3,6a1cb434,184fd292) -,S(b3e11a0,45702d8b,14d93df6,3a4c11f5,32632719,b4a33fb8,da11514,bc61d73a,c6e152b1,2b267ec2,1a23892,8cb97044,9660c6b6,34b22d18,9a86fbd9,a9d562eb) -,S(50a325ea,3b309911,1371b0f,e0b9e276,137bf43c,22108b98,994ed5a0,d66fa5f1,946dad1f,d39e0aa5,8a758527,9b39efea,8a99399c,2750739,dfeae140,3745b70e) -,S(f7c8f249,3befd5a2,cf6802ce,8ac508ee,a97341a6,a46efe39,1214e322,e95e9661,3c072cc4,eec1f370,144b7ec0,598e4d96,573883e7,fa3f3f5d,4e33d88d,1e34cb67) -,S(302d3b50,c1543386,f0b0b94e,9c49ea68,38c7e7bb,86c28cc3,c8965dc8,38f85b6,988047d0,d891aa2f,60b66e5a,96c78c91,3588d128,d4e7f720,5672d25a,88310744) -,S(cb8ee728,2e7e5ba6,d0e8ecb,55ede89a,1d3810fc,b0d8f86a,fbf53b7d,219f0eb7,4b04ea2b,efad1099,8c9a4e3,cf0491c2,bc10bd60,e06a118e,75fe0163,ab8094cd) -,S(645caa2b,4a0cd8aa,20cf6f04,ac73a49d,74f92035,f90bd31b,211572d4,cfd5fd42,793f2996,35f9d7c1,de62b64e,afe516db,b0aa1323,7f51d0a6,b6fc8346,fb7ef5b9) -,S(4d37342f,6148b5e7,5434b8df,6617d64c,f00b1c73,3d85f4f3,e69c4a27,395f5a21,6400092b,d4c5c705,464a7db2,b1b6b667,4eebd7dd,38d05cde,d1577d8a,53a708bd) -,S(e634bf17,24e07b2,b4ac6285,ed28bd39,747a2134,36e76d3d,bd693170,18c0e0d8,cccbcade,4b82a51e,c31d9d8b,6b113876,5e9660fb,e897ca53,20db873,13e9f021) -,S(80a00de6,2767c513,d5bff535,431d259a,64c49006,3bbf992b,a5111005,360cef38,7dceb589,e8d73366,c467e23e,8fdc7e03,b2620df7,9530b6b2,3fcdcdf,628ef572) -,S(606d50e6,d23d50ed,9a5b8409,f11d5c76,baf5b765,f719625d,5b2e2dd,9e8f8a0f,19f55492,45b1b4c2,fcc1d220,6c171200,4cbb41e8,bb7c8cc7,48c4366b,3fb32788) -,S(9c8a0a14,f7d44fb7,4a7ea835,ae4a1932,266c3083,38d66a24,7fdd60ee,e4f0420,42c6c237,31578dd2,31eda621,81aedd29,8737fc7a,3b2be8b4,d0187459,e5d9169a) -,S(d6ccfcf7,81a46f58,ff9a0154,8a417924,1a32d3ca,43a8e59,cebc33db,1e35da1c,a1caba1a,ce846b8d,8b4824e6,1570f832,87cbcfbc,910256d5,68bdf223,861d084f) -,S(8cfaf36a,3e4c3ff2,4556f446,4947c8d0,6eed5ded,a40ec0da,4596bad9,f5f2e3c4,991b6ecc,ede6cdfd,e33f81d1,c1067f22,6b72373b,96ca31fc,c80e0692,d8f3c4d7) -,S(d46c3d81,5b0f3a0b,bcef3973,8c6a6cc7,189849b0,4917fda0,541c08eb,b7e664a0,35524bb6,d053e5d7,c8adc9b6,3a84ed81,58cffe99,4041e642,1fece58a,d967c159) -,S(8ed7f0a5,2f1f8df7,f82dce33,e4637dcf,e2ce9b75,ca02ef04,90c23fec,2b7adfff,f02460c7,b418d10c,96c27225,3dee3b66,4be1aa5d,427759a5,5d90c223,628d99ff) -,S(433ecadc,a8a351bd,52ba4d6c,aeea3ff0,825c46b2,8abd2c2b,cea85f6,6daaa2ca,4d3b71bc,c2d7d177,45cd03c4,86f390e3,f6d396fc,83d0438f,983a142f,162977e5) -,S(c0771ef3,10377f83,7a9bbddd,81f6642b,ba04493b,15c054eb,249b3f9c,bba006e6,3e53ddab,1d816a02,7898c6b4,778d4c48,e1ea2b33,a63955b0,784df258,ef4ccb1e) -,S(dc2e0226,4a6a87b9,53997383,e35c6cd8,92072ba8,a741fd23,8ff3a9c5,f597ad7,898ee746,ecd5f723,440ac0ff,6f597e85,8ddbacc9,cbc80e01,d8a3c1f1,7c12c74d) -,S(16bace34,59ad8cbf,1fc5f781,19cd9e31,d043d7b2,ed839f03,11f0b760,6adab771,f64532,6ec697e3,2ca23979,72b2b834,66e835b1,2bd49243,e896c1df,c02fb1c4) -,S(afb94d8f,3a271439,146539a8,68f00346,9af55eda,839c81a4,725f3a5,7d69c736,afdb294e,a455031d,a70a4eff,7563d764,bdf37fa7,5594c9cb,386e8bd1,a35201d8) -,S(bb31d236,4a98f7f4,1edb0ae7,6018e5ea,ecc33780,5f781dc7,6b15aa9,d0e89b74,1a064c03,1f47cc7e,cd49f032,f4dcd95e,87cbc28a,7b9d9c27,a92a4c1f,da031a9a) -,S(f73b1b6c,4bbf5da8,16604ee3,ef6e83b,241e486e,d727e700,1c3c115,3c4318b8,9a28ad6e,9d64cba,b58ac225,5c01b261,25ba08ef,3b7d5ffb,476f9b8a,6c8c9b17) -,S(63bd212,d0ddc5a0,84f8ea7b,69605b2b,708c8766,f0d3313,b236e921,91afa8a4,ee6f4f6,4824032,afbb0b3,a9fd342d,2fbca8e,ccecdb0f,a3307698,c56c3e67) -,S(6367d22b,36068022,30a416b7,8c689078,967b955d,875fd629,9e007f86,1abc6465,c3ee1f2d,14e6793f,17e444ad,5595f9b3,118d1647,9259e0bb,ec628897,f69417eb) -,S(64e2e543,fbb7f52e,57901e3a,448394c6,c922d0f,b632c4f,2df061a8,9485976e,641a602e,336a68b4,fc447e5a,5863a4e6,89511942,4fce011b,48f937df,fcab2a4c) -,S(2e290afd,18c835c8,d1d79e86,9d9c1322,e16e824a,60e67f38,d6bf3031,e3fee1c6,7f85628e,d2fa6b67,7686b0e,c29a3626,da18ccac,5e373874,96266458,79390f21) -,S(859a208a,c475d3d,f5f22907,988c7774,c0ba2dcc,d80ba42b,17ef1087,2cee401e,a667c645,778e743a,d62ed1e3,cfa12fcf,84b982a5,f1349e31,33627ffa,8b19f5d8) -,S(c9291908,ccc50aae,f19c0b86,829fdc63,b608d3db,d92b0939,b92ac02a,2bcaf21,e5c52bb7,47111f58,c71352c8,b2fc89fb,20cb7d45,77c6231a,17d8d01b,6cd2599) -,S(50359490,42b5b620,78ab0141,1f1a1d4b,64bc42c7,58da4459,b04d41c4,61cefb26,f61e823d,b68c064f,f80d9bd8,f272f817,347c132a,f7bd2af1,e5b451ea,bf4f04e0) -,S(f9bcfae7,d6a3f1fb,612787c3,53b535ec,39f29a01,9f45f43e,7b61f2de,c4a4cbf3,f4d86e6f,273ad7e7,902d5a99,50fc846a,a6565862,aeddc67b,28fc07a1,232ff883) -,S(1c8fe8b,901cf050,e93c0004,b0764715,602ac4e9,7f8d5dba,d7747039,f14a9152,b25ddb34,7c452942,92143b6e,cb19f87f,b42a0f27,f6f74c4c,99d7b80c,7d36769c) -,S(3c50be1,4cbe3a87,d363947c,6eb534e0,8ff676cf,412bc4dd,2c543131,e786f552,4434471c,6e03f600,d8a27775,4466cad0,194f553d,bb653238,8a0ee4a3,9b05a74d) -,S(64cd71b2,555472f8,fa968b4b,4f8c8b24,5b3e91ad,6d9dd409,fe72702e,e70522f5,f1b1cb3a,e9fa4855,2d7fc2a,819bd629,40350a3c,168782af,5bff16d8,89ede304) -,S(c1c00444,c584c346,d1bdded8,7cc40b0e,fd8f69e7,d2ec8bcc,c41e3414,619af7a8,d631b494,3e3febb0,87bb391a,d5810b61,f78dbccc,bc6de38e,ee09005d,3d879436) -,S(fa509582,dad5bb61,c7450fd0,3b7e4ba0,2fbd0c28,af971b96,cbef5956,3fa2a7ed,267c2764,617c2f78,9ab890d7,56be2195,2acdff5b,3490b816,165e2b36,2f3df4e5) -,S(655dcee6,864e926a,a6e05f04,b604c2da,35175e0c,f7d264d0,50920d46,c1a2386c,da2eaeda,bf062cb4,ba2d36c4,67965baa,5f1dc238,b5e22df7,2bbe14f2,cfee19c8) -,S(6ab5e1ac,1b7be624,97c8fbe,fec5c4d4,2cc1de06,d15a1beb,7606fc0a,df3c213e,26f983b2,4eb319c,7443e024,7fecdf58,f833928d,4e809d3c,f36231e4,d0a9e466) -,S(c7da869e,39caa2d,e9f73a0d,3f73ab73,6224e2a5,47ef5af3,5f5a9d51,60c25f3b,e99b1102,49a607d8,12af4cf6,76ae4c4a,cfdc0f89,9ec2175d,c7942b6b,40da579f) -,S(2a6d4ca1,5f1c3ced,ed68091f,af4d149b,e20b6854,bf015084,a9cc0d21,4944ef99,dfc27688,ae9295e9,ab8d9284,6a703ac5,5cb44bf3,13f179b4,ced6b638,e661ae0) -,S(447260b3,bba7224c,aa659f70,b1e7716a,92600a27,18129575,2de62cda,11c846c0,f17e3e0f,33ef2ede,8980c922,613947,8331e2a6,40260996,db8da1e0,dc8999bf) -,S(8cdb1cad,baba7003,8d4b0f44,1b312aed,5a8788a6,6e5356fd,5b994f6f,a7781969,b3a5bd0e,262e673a,ae7be06d,8d56c203,b88750e4,ba06cfa1,7c177edd,74536977) -,S(28be0f50,fb60f905,18323e6c,dcf46c0c,bc3e2c0f,175d8576,85126a85,d5caaefe,5cc058f7,fb188c4c,e1140429,568c3176,8d986fc3,e96409de,21bf9ba3,862b7320) -,S(b6dccba,dd2dfad4,8b69218a,d9cf839e,837e2262,7f8f0eb6,f23484a2,994673a0,e1c14ad7,297f1626,774aa2ab,5dcc730a,49623176,ae81eeaf,b52cfd4c,fa2de992) -,S(e45ebec8,8813f7e5,7a7ecec9,dc5fcda6,b9cbb0f9,19bae1d,be770955,e3766a87,3a62a0bb,4ccf3783,7c384885,7acbaa9f,f915cc7f,13a46856,3ff135eb,dfbb07a) -,S(de926f77,26f39d48,1e0b9e55,22b7c874,59bc9d07,df65f0eb,7b21fea,e8dccdbb,9d190ea9,263d4240,24b618ce,1239f6e1,115be2b1,d721aba0,f5f367f6,304d8e05) -,S(f7621384,20669c04,6d794807,569722b4,91e4272e,1305f091,b54a03f2,ecf2caf0,d0c7e8e5,a227f2a9,5c594528,4590caa3,3088c92b,b4c7cf6d,12d293d0,4b9e4914) -,S(4e795e86,44ffee08,f44d472e,8ba0eb9d,a5cdb1d1,619a437d,4a8bbfe8,565ce751,5292d8e5,478268f9,bb9b4be3,c751e587,65038c55,99cb3549,749e83e2,1590a4e0) -,S(70e64689,a944b03f,32b33a97,c8923531,cdf75e8d,e8577559,bf45d2d2,ddb50b3d,a675c6e5,460b89a4,a2dae263,c71e6edf,925a93bb,a916951a,5364d252,c225586) -,S(21637c2e,682b247e,cb8c1c,8b4bff1f,477ef390,3b9da0fa,b08b5cf2,5b67056b,e357165e,3e761a55,7e4c2b6c,727d8387,c5716b58,e24d0e04,8314979e,4e92d882) -,S(7691a399,8dad2e1,741a4135,18bdbb,d8ae5bb1,7466a949,a40560a3,9c1d1964,225f1404,b05b5bb6,cdbf2296,f76e7f27,257280e,28c68be4,d8c81c47,a422b74) -,S(748316a4,f3950849,9af5a14b,27eabf9,b0d11e91,d8752cb,69899af8,79af9302,cdcdd4d2,6bd709d8,c3d87c12,6dd8a2c4,f600fc1b,9e84461f,1793047b,5bfd7ee2) -,S(af588dab,3839e85c,6dc84aa6,c1e05294,a9708951,8006b390,c2ffe0ef,f6ed9b8a,a3d37640,1b06548f,2794131f,5e002aad,616ca135,8cf0c81d,87015416,37d9cff0) -,S(bd91dc60,31706ffb,19b61796,995728b0,5f869d07,6f0b6537,35c46e10,d9b42dc6,3c963ed1,5a74f5c6,1a28db8e,de070870,cdce2cf7,d6525a6d,16171076,44f153b2) -,S(e625c4a5,91460bbf,5c3aa583,c4cb1e1f,c202c82,7debb82d,985732ed,ede98f47,d026c5f9,a9035396,1de50534,8e4ac600,812a461,c913299d,7fddccc1,5970b72e) -,S(6bd227fe,d4b193af,8b94553c,718357e4,122cd057,d95980e8,ebc8fe5c,7fdaac1c,5f3fe540,a98b044,9ed835d3,b0a2b4e7,c66a0549,e4b7b9f0,22fd5249,c621a9f9) -,S(27707a25,895e6f38,523d3872,c5b34e7c,68a0f0f9,54c6ef49,5cff6664,1edb2609,ef6f4f8e,c893d697,69f34b38,f7f677e9,e5de5c91,48cdf35e,3a18022,3ea777ee) -,S(6052248e,3359414e,bb7770ea,4284d7c,c01770c0,e75466db,1f314e0f,cff0ebde,3d982058,5cf0d546,9fa62e02,aa556fb,1a1ac7d3,1cb9712c,8b118e2a,e3f7b7a2) -,S(f2cb5b53,4fa6124c,16d82506,8b229857,4d4fc666,9b45550e,6c75a114,f370f6bc,5cde5707,63a5cad2,13952def,43cc779f,8ec9dcbb,c5fac8a0,ad7a740b,7241112e) -,S(77ad8215,9fe6b9f9,e08030c7,a75c601f,4989b51,4ef6db20,aa9d0b23,e87a502e,9268a1ee,ffc24932,74856add,2ba1ebb3,c13678,99af932a,87fc680d,ea9b703d) -,S(4418748d,171cf80f,a7f80fd7,c2d7891b,5cc9aa0f,ba4ec1c8,a114cbc9,4a8fd29d,5130285,79f01b7f,72f18322,b279fe7a,9916c16a,a67c6aee,babbb418,fb1835c1) -,S(16af4960,6f89c87b,7e5901b4,d11a826d,126e59ff,df7d0883,1d37d7e6,367355e0,1a138440,537223c9,e8e131ca,8ea3b38c,12c8e8ea,50ee09f6,8ca4c2cd,4cb04c2e) -,S(22d2043c,ab4431b8,cf77ba0c,ad81848c,730a730,35277e4a,ae6392f9,de120f9d,d7795dad,5e5b46d0,9c36520a,c7fccf9f,4d71f9c9,8ed3d45a,432f4f6b,991b8acd) -,S(57e7a8b,34826533,7e203360,2f6244b6,41d92c8b,b2419734,9fbb3271,57676302,4d9238e8,ba4bc8b2,c3abd2eb,6bb2e545,5146afdd,3d1ce2a0,9752803b,4599b83a) -,S(45567f60,2755027e,282b39ed,5ddab1c,7ea19a82,4c0609da,9ab455b0,26acc359,db55ed5a,77a354ed,e4229161,141392dd,82c1ccf7,f726fd4c,2fbba48d,4134f5a7) -,S(968fb554,91059347,9dc1933c,a8453201,798a0be7,1a284c38,3e8fa5a0,f67fa80f,63586b1,6853f550,c36d8394,56718376,1c14101,dd03cbd0,b164cca1,24e8920e) -,S(f366c649,f633cd7,f1fef522,b78f7b85,3d640acd,11af2d17,14c14251,ad873107,5fc396af,38f4988d,82c4cfab,59d415ef,25b260d5,711ad546,e56fb65c,7482c6b9) -,S(aa0c4fd4,4a2e68b2,edc16eff,d2b3c29c,59b19289,1503e6e9,ad068743,fc201d06,614e3224,2fba7977,464b5c4d,b76270d0,2763aca2,54aa5b82,b5ddf8b7,ff3fee33) -,S(6c886cee,19b2cec6,91c57abb,da830e45,da4cbdcf,37484ad2,b4444948,8f2cc876,24cfcbbd,9ab4df87,87eb384,fec64e5a,a197e897,bcf2dcf5,def4b94e,afc16a1) -,S(4d600199,c33f76ee,c81d1686,f116d4e0,fbe5e4ca,df3bee43,9a81785b,c6095554,cb414cce,b769f70e,115d4321,fdfed743,2bf73dc4,9f1628e9,dad15f32,5fae614a) -,S(377dd0a0,196d59e0,e71e8472,4b65bb16,12c3caca,d2f2230a,a675a25a,5d0a4fc2,2c727e7d,8c8e27dc,a5ff7c27,b349752,1159c736,2b51f38f,e0343c74,acfeb560) -,S(9cc0cf8a,23afdf35,1bb1826f,9d900b8a,e8aa5019,8cf36552,9ca928a5,9c820f46,b572f15b,e2aac0a8,c8142c53,ea43a0a0,693e5446,5d5531f8,b068d347,f7e67256) -,S(d55dfaa6,41492b1e,981d154a,2be0441e,4cfb01ea,a51c40ea,d4a4d8ed,19fa3050,2e795dcb,408c74c2,a9898f31,523a1e72,da0c4c77,c2dd2eb,45fb2e51,8f238ac1) -,S(46bf63d7,2d113152,3075efb3,fac6c07e,e3d27e87,279724e8,46306dee,7d210fd5,771bb1f2,30fa3253,7e3b433a,2905c4a2,dc4a2e37,32e282fc,94cb2c88,33b0b199) -,S(4bcfe388,3e77c17,8c6f1826,f75e7c3b,594ef8b8,c1a9ba3a,13f00597,50ca3aad,b5562e93,9dcf4672,fa283cf5,6c05389c,ec5ea923,b47d09b6,2ddaaf54,8a1b0129) -,S(c9681af4,715e69ee,d7cce802,34bb2a49,6255ba39,1df76c57,df9747b8,d8c241db,c8b175cb,b03d5206,5f2bb846,81bdcb04,da530e81,31082e08,28c21f7e,cde038e6) -,S(9fa0a1b,56bd6ac7,f4a2671a,3b4f6ae9,bd5538bd,4c6b4101,790b16bc,c2fbc33c,27f9eabe,785c7cce,e4859959,348b4864,16056f68,6d445fb5,c08fd8b6,33129e63) -,S(15042df0,ca178aac,723e7b9,8677964f,a87203f2,bc0e1fea,a56ec6a4,73d0381e,445db657,dac86b0d,f8f9eb59,a143e75f,e271cbfd,2420b3a1,677ee3bd,8d0183f2) -,S(354f6a63,d4c1877,e0e7da3e,921db767,6b7f9dd0,eaf8b65,eb08b032,1f37e9b2,1000503b,d65b80be,eb72f480,a43efd65,2eb784d8,650bffea,5559aa2b,104ea8fc) -,S(19c36161,7a448fc0,49cd8864,d2707d6e,9e4ba74e,79ae3d8a,c11430c5,99de065c,2f9f9fd8,fd38ee81,94ef570c,1b7299ee,75742d18,1610a2fa,4dd06f30,989acff5) -,S(3739848a,d2ab8a66,b6a7a2d4,add9fa8f,5a50807b,56ce5d39,5bd4c146,7083f88e,6fd71820,611102bd,f4dd2056,92e188cd,68a5409,1036951e,6f58162c,65f0cbc9) -,S(9c22cb45,261c2336,7dce66f1,f84b84f5,2dd7e58f,8ac6dba9,50062eac,1c10aa35,ff84e3f5,8c25be72,910bead6,286dcb9f,605b0017,1996d46e,c8dbee64,52a1116) -,S(572145c8,7f311732,7ecc71e4,5e37c555,5a412785,7513fabb,d0fbdd49,6db4538e,163e63ac,5e3908da,2aed5166,c121548d,5338c6ac,4ea7550,242c7910,8a38871f) -,S(c9f07954,d8413eb5,8ef213b7,51a966c7,4c641ed9,8db8685b,d931e321,2de940ef,9e6844bc,804f3d3c,a065fe7c,b09bcecc,92cf5af3,ede9041d,792c184c,cde17fd0) -,S(ac297f46,b07c8a29,d664a24d,f05a8a51,f7b0e4aa,e8800c3,f9291a13,787f25e3,686e3b7f,78e45ad7,fd1bbca0,54a5d182,b1556c77,753c1858,75e98de8,29b66cbb) -,S(6c5913b,b383a688,390274df,121eda23,5ad55dbc,80bc198c,21897934,98b3e1b5,54b9b83a,e3649f4a,2f11ebf4,61e24a55,53e5b4b5,d0f78dc9,1c35aade,2cb9ccf1) -,S(b9926fa3,f503356b,eca59ee9,2163cbf9,846e3efd,c793db45,cf7ea8e5,af2495df,d6dd7c5,33d4e7a1,ed415c51,1fc15e05,54fd00c,100bf047,bb8f9054,42e2a512) -,S(4325d1d2,f2cabe77,fe0ac758,f6073057,cb36adcc,5357fd5a,31473ad8,74e69556,de437968,2ff6315f,8870562d,560cc48f,818c8fb5,c45ad932,ed5a7d4f,534904a9) -,S(a183e95f,fd84bfca,4afc9059,ce1c40f4,eed924dc,d1bfff11,d38a8c1,14164917,11c57610,c7ffca41,145046d,4cdf95ec,c38d695d,bef057f0,a0d01bb4,41d64b95) -,S(b340d0d9,ad6528f0,d9651414,f48fdbc2,ab7af5fd,3baa8091,84d5e881,6cd07114,85ed726a,9ecd70f7,f964dfbd,40e4b68e,ae2671a9,b6c3d384,919d040e,120dd4e1) -,S(b52daa88,35992fa4,1595f0a4,c9e075d0,b146fae3,6c0d640e,8e6f34c2,16719377,6088b139,9fa83889,a6cb5cba,d478c7a0,4f42f082,24b169df,85ec90e4,7a4ad7ad) -,S(90bbd15,42b0f88e,9f7f82bf,7c2b5fe5,f269ba36,4523a18d,5dc5709a,2ab9d8ad,c9df924a,51af344c,a71461d2,bd3743df,c6958490,caa68743,e06e7348,528fc4e5) -,S(f72ee5a8,1696194f,ed3d4603,f2c9312e,b31c54fb,438b1fd2,2788ea6a,a3aa8365,e2963d82,b6ca0f4b,8ffc1078,cd45a72d,e66f4cc,78567074,4fc1721,e50fde8a) -,S(108aeb71,5bc70525,42f5d6dd,dfd348f3,66a10f4d,d99f9298,c35a8397,e6b9fb53,8388b339,75a58e04,a0f6df47,23728986,97b8d970,ac6bd45b,49b9cf1c,3209f1ce) -,S(dc3daeed,87345ebf,824a5ff5,c7f46268,fe54c901,493e2e86,e2667fb6,ff61d5b0,b5a7e641,238e0467,196c1683,bab47f66,cf001079,932a5d56,da20f89d,d93411e5) -,S(3f96a83c,2be16120,e81e1d26,e3853ef3,a82c5f32,f8d6bef9,38179c06,4265c589,eb8d370e,797cf20f,d5a0d734,9fbd027d,630ba1fa,bafffa0f,2ea37131,6b5c64b3) -,S(27caf86c,e1f423e3,1cca2278,244fbe3,b358357f,af1b7866,1de13b96,eff5c4f3,e8f77718,647acfb4,633ddbc2,3dbdca0f,2187e24a,2f2d45a1,39bfa1b8,a2b30f61) -,S(6681cfb9,e2418786,1887f964,84819645,2d301a1c,7c082361,67a24c62,f74d04f,9c89eb3a,7849e944,2f5f521c,c08d11ef,f1ce4869,98d4d760,8dcb4a37,b815151d) -,S(6711b849,48664639,67274709,2fbbafa2,fcac45dc,1795e80e,67fb0e65,beba8da5,ca12c83f,1c8f5ed9,222d8cec,bbcaa51d,6b986a5f,60d2c118,b812b259,294cfcc6) -,S(5ee9cfd0,b1102cdb,a0fd22b0,569875c5,fdd73467,22769011,8b7843e2,b71dd94d,1dd7a4e5,bd7f9ee4,e17c518f,19b60332,60d2294,8b5f463a,ed9021de,87d7d86) -,S(586dad7b,13390be6,f3d95a46,6d0224de,d7538f1d,2d2d9785,e38a3f2a,edf4924c,c777eda5,a68a3582,1735bd33,7119e58c,bc2fb101,c995f986,7bed9786,cc2b64d0) -,S(5a752d2,fa012c7,1924b6e6,90ddc7e8,867f6ee0,ad8eed91,84f7250d,665091ec,57f2232b,32b36429,f15029fc,5789042f,ec1ace97,5f2cad27,d53ae819,47b95db6) -,S(f93cbeff,22bc577e,a9cfef22,378eb142,426372e0,7be72e60,2a8064,a53e638e,abc772bb,401bdb42,94b16670,2279e4f3,eeadb75d,57190a59,96f34237,83afe50f) -,S(8c272c9e,96130972,2efc34c3,6a6e63ac,76052cfb,856eb8cc,3dd014e9,d2608a9,9987d168,13c57162,3ba7d226,18b54003,731e3716,3495edfd,e85e927e,6e4607b3) -,S(bf78a0d6,1519542b,a54226c4,d386ddc0,38dfd84c,9f9555e2,3e187c11,4d769bc5,6094e1e4,d84ec081,e6014b59,d42959ef,e160587d,315bcfe5,5d26ec98,b1910280) -,S(5b264b76,cd092a1b,ffbab651,f42485fd,497aaa5a,e311eb28,ee1fdb99,32e65caa,944f9359,4b68d7c3,6610fdc8,85695b06,1dd84722,d5d88c84,c8c188e0,69d70d78) -,S(a2473cea,8075a0d1,33bc1459,8d147705,322f7151,274e797,4b7e042a,c082b559,64de830d,b6557b06,d9b09d79,4f6c905b,5168d32a,708484b5,d2c68a89,a2575a18) -,S(3e18d5e6,3dd0c514,4341535d,a7087bd5,f14b0708,a292350,6528a803,609efa45,6e9c71b9,7d007382,f82fd041,be53470c,26dc2f16,26a9f0a6,e1d9ff67,54288c5b) -,S(d1acdbcd,b91e6315,bce96eb0,9c229086,6a767441,4285984b,71af6156,8294dfa5,5e3b0cd8,9872375c,3f807201,73e29d3c,accb67e9,66b99452,2c9e9f88,613da5a4) -,S(3aa999e2,9344e0f2,b5ecc880,a35ecf75,25ddb028,c40f64e1,a210aeb7,d850c90d,cd2ce25c,fbe3a1be,dd2e6fcb,e9e9a881,28c454e,c7ca1951,5673aabf,a543d42b) -,S(98a2361d,7c3815cb,ecd0aa4c,8a3a6ca3,3e1b31e2,5a4b6398,146d6709,61a5017d,1f33df78,3040c13,be821395,8d78e039,516df25d,4d9d0de6,d397128a,2c09f2bc) -,S(528b9d8c,907ab870,6d7a5562,84cb69cb,ff348247,be1b7cc4,61351674,53d98d0,f91eb836,d6665778,7c6d67bb,800a1141,29700d53,194c5051,aba7ead3,ddeafabd) -,S(f1adec8d,3d1b0d20,8bda6a86,6b8cf730,f4be50e6,2c8d993a,3556c1ce,625029b6,478324aa,c3bf6182,25bfb61b,32d47956,57e4a754,e08a978f,964741d4,1bcc7224) -,S(ab2ef133,b1b115ac,41870cf8,d75d4aa0,e0181ca,742a8f10,f74d50a7,3924a099,a2c47b74,c584eeab,57949ef5,38c0af69,2f2baace,70a730a5,75629ab0,566a91ea) -,S(9d4eb41a,f6da6f83,b1d20e2b,f9370868,539a617d,111b8c72,348c9b27,e0576f85,c1c7b00d,b786c84f,a8adfe90,4353305f,73acc3c7,1c2580d7,cc5d6b33,c5f30eea) -,S(30edd57f,7b1b2c81,c886dff0,5d9e9062,a553638f,9e4311d0,18a42229,3fb916d9,6bc4774b,16d257a1,81e20b48,5acfce30,f7449e64,aa288502,d44e7c4a,44842ee7) -,S(28e3eb9d,9a2b855,65c58fc6,a492014c,f10969a7,1e81066a,41d1c574,31306583,fc653b87,80734067,e5245c,8c150ae3,59ad3c15,df4a8e7d,dc93c8fc,dfbb6c2c) -,S(cb984735,e3c842d0,a2fbe578,ff3e8263,5a3a8bb6,749d8e08,c91571a6,9aac75a3,e935a0cc,7181c3f5,3013f977,ad714af4,4c3e257b,e9936268,b481429b,7bea8367) -,S(36186672,7e8307ea,eea83b10,6850dfcd,5e4d665b,20aa37a3,ed0051ab,a40fe170,ec626ed3,2ae6dc01,f5d4c710,ce2cb349,ab27cbf2,da5d924b,e32ef8d1,707a6d) -,S(b1a40d5e,69e9f365,c2accd54,dc8267bf,4260abb2,3b503136,2183b17,4c6b7d2e,76619dab,2a7b41f5,2401ff89,4ef632eb,31eddea8,bae27c3,af04730a,3dc186ec) -,S(abd488b3,dff60a23,e83f0ccb,22620064,b32a8f35,d4c22be2,42eb1427,15660825,6eff80f2,17dae3af,96c7a463,d1848bab,fa994904,91a1105b,e1bf7f23,840b3a89) -,S(ac0cfb04,d91ceb48,2f497974,321bdb10,2a572115,73fe4598,c92510ca,4dd6aa22,6b5f6d87,4a90d0a9,658ae4a,64474d9a,3950314a,4662ade8,1c5e5605,274582d5) -,S(1fa8be0f,476c4b67,697c7541,dd1d8be,a3a0bff3,552948e6,87baf11,afc34432,c6b25084,8038461e,32961d20,181c7187,fe79df6b,8f5c5e54,96ddb5ab,80788d33) -,S(281b43c0,d3738989,a817d313,755c5f0f,f336a4d5,7e8d0ec9,b29fb425,c1f90e56,26b5070e,ba1059c9,b73e3db3,1227a6a7,68683044,7f823689,921a9bbc,bc9f4a9c) -,S(d64e69e9,54e81ec4,7446327f,55e5a82d,3b83eb46,2a92af12,f0b2694,c88f4052,aa7ed55f,284c3ca2,9be75565,f66ea54a,27a8f00d,afaff0d5,8f394797,3dc8622a) -,S(f4cdbaee,d4b01db1,f0b5b0c9,d6178235,483fb58c,5421ba54,17bbcd4f,e4e7b028,66d590eb,29d69904,deb9f48c,5a250089,b2b92447,8ea91302,1ddbab19,6c63b47) -,S(8ff94c4a,6c46e334,feca809,79d21a0,761fc1cd,1de76f4c,7243ff0a,93c9dca5,123ddc33,5f3c68e3,29f42d4f,187fdcc5,77207134,a8bb777c,2ab08dae,f149abf7) -,S(c7869b4,6e34186b,7e87c0e6,23b64fb0,efed70c4,f2af5e70,5c33ecd1,27cf267a,66295439,36620898,2f17d95d,7da2bbd7,29aefa4,69005a59,629720a7,5c11f48a) -,S(e0ea76c6,ad5dc87,bd26ba9e,25b5041b,9836f72,6eec0142,351b2431,6cce1a4,8bd724e6,632049ab,88aa620a,78922b65,6a3a4417,c8af7dbc,5a03d4b8,d4eff928) -,S(2fa63ac7,3e5f8982,36419f1f,4883f52c,e8e357d2,4b4aa7bf,c6aa7eb1,29e30159,57e1601c,d6323fa8,f5a5b314,6b5e5c44,7251db28,6f79d51,7d0b038e,b8d8c3fd) -,S(74ed4038,d4c50930,22e783fc,1bb7a671,49d00877,b202012f,6aa6d32d,c73026a1,5b74f70e,65d009e8,8cc618e4,9f7bfda6,58234f80,38e9835e,80e6fd42,6b28476f) -,S(71d6aca6,e38713dc,6ded1f93,4fdf20fa,16ce75dc,dc405148,eaefd2d8,f0025f97,b4314533,7d48dfc8,278c6c4f,b19f69d2,72ffd4d,a22dabae,dd3e60a,7067e302) -,S(28fb47f1,6e91bc9f,9a2d5720,f40297ae,ee617ec6,897044ac,8a174acc,5bed5292,d04b6961,d72472be,4fcdb605,9943c1b4,ef8e7aed,2ba7859e,bdb84a4,f8b498f7) -,S(68fcd5f5,c8655b5f,5d2fca79,59a7b32f,828c5a5d,e262f6f8,94270ee2,1f47a37a,57480650,33627166,c372bc4e,7a710275,7aa1ad4e,5460dfb6,d3d27f32,778d74ab) -,S(c7617ad2,f423abc4,7ed7f8a8,a7a6002d,17c9744d,1ac6be97,49110685,95aa36da,d9904b67,fba96cad,cbe7a9db,833c614a,69e330fc,a06ca2e8,d597f657,b7121d9d) -,S(a7ef4e9d,2396fe16,c0e78b95,5259a9d1,474fdc21,8b24e8c8,df566192,a6487cdd,d6782604,91c6be04,98c3f7e6,86f22f37,23c1e4dd,4f7655c1,f40509ef,5af67f28) -,S(f3be7846,7ff03676,4ace420f,4091bb2e,71856d18,9e24890,eab6b436,771e2578,f3027657,45cbf3e5,67a6966f,6b27ffc1,dc58f3a,6811f309,434662bb,636dbc5) -,S(5c947f95,5bd9ce29,5214c30,3ebf4f35,6c8d9e2a,4e173470,94d3f755,36f0259c,b6b7b775,3e7552a3,d2dfdf49,8578a24d,90a81d8d,68ef39c4,68fb5ca7,b75e76cc) -,S(236fd960,c3b1735e,279b8702,8c25a074,2c54c189,d1040c13,4e4cf40b,bd8b2c68,9ab59bf7,c0bac18d,d0d9360e,b79a76cd,b44bacbe,b425d181,873ac390,59bbc279) -,S(c92c9f26,17cce2f7,659d0243,8b9d8932,c1a9e9ff,ca8b0d99,cd7613b3,b1947b31,abdea94c,1a5e64eb,65e70769,51ace2b2,e4804ddf,1539d50b,725fe09b,52357a51) -,S(986087c9,142c608c,33783a12,4d22c316,733c2ae8,bc1fbd2,8bd1a142,6da94fc0,14925bf5,fd76b51d,6be82c65,4562cdf,8f5baddc,eb26c68d,3fa6113f,ab42a1cd) -,S(465a1f74,f4f6baad,7c644e21,f35650b6,22424e93,83b421bf,91478621,a48a1d43,26da71e4,179430bd,ee6698d5,7db01553,d41c147b,83247157,9f2fe923,c788cb48) -,S(dd7658cd,f28117c4,4ff3c88b,d0b46adb,c7aa2ed9,1590ca00,785cee6f,5c9796b4,32317c0d,1e10e997,a74935a,8e45d27f,9a9b8ac0,f77dcf37,c1c7b340,cfcc43be) -,S(55bd2abf,a803c49e,b4548b17,725f52fc,6222af8b,dd9aed09,715ceb87,57c72033,34ad33b3,9d7344b3,abfc603b,8dcf2a54,96b991b8,41564e35,53adfc85,3d3ebf43) -,S(77be5c06,d10c226c,8c9616d3,15b1e1c,44006876,4189fc36,db0c88a5,ec12fcde,ccf2cbca,5c474949,88f27ae1,b0361b9c,20e8b55e,d965f7f6,ec8fd9e0,429ba01b) -,S(fab72486,3eb6f261,f0460b19,bea7dbdd,80b890ee,d4bb5618,30db6af2,f52ab21c,914f03a,408a2e2e,aa9174ed,99d80e68,b67f6afa,fa9da5c1,5d22f74c,8876d0b0) -,S(232a2039,fafe8b86,50a671f8,de78314a,510db65d,5cf105a1,9db8082,2a0b2f66,14ca7082,510bc1e3,533b9f6e,e216ec13,3be3a6e2,64d2e218,d95f3ec2,ad78576a) -,S(b3482839,612a4ff7,a0584752,68f13e69,deee9fa2,894a8cfc,64e39054,1b7f58e7,722d02ed,df30025b,eb4e9fa,f7c58de1,653b8224,66b1193a,3f2fb71d,5d26ae44) -,S(d3873a57,b0a7587,cab10871,a9322712,cf6fd84a,226dd7b2,85823996,5a353210,3b7e4984,59c7e706,cdff95b1,c55e3351,f1f45d0c,c9fc11d6,60e5e27f,5160f186) -,S(8828788c,eeebb2b7,71d289a7,147c0a7a,26a049c3,26dcb281,cc9b2dba,162c20ad,e428a195,87425f22,3d798922,b4971c26,5da2fa2d,de4a364c,c8c65f48,c07b71a7) -,S(79fee531,26d0c00d,74986c18,993fa174,52f8dbb4,ea75680a,37f0b3f4,ea7e537d,fde50071,3143f994,b4d7b4a1,43ab3abd,525cebbe,93d5b5a4,560017a8,802cb5b6) -,S(f44f39f0,5a9f5f79,5f0f3a8c,e03ab50b,3672429c,bf699cba,ac1e58a8,66814e91,b95e45d1,e4de1300,950a27af,bab28bba,ff75a246,46ac70e3,fc09da30,d59a1dd4) -,S(1138e209,baf9c9b7,b89d7d78,832cf7be,da45afbf,3c2fa148,50426ec2,80aa9abb,15c28d6a,3965b2af,ea28520,7e67f2eb,ac7d5917,9672f88,3727e499,f06a0d6e) -,S(29d3e942,1b98d78c,60e4685a,aa503130,dcd3d3f1,5afc2620,472b83f9,34912c1e,90a514f8,49680969,215d46b6,db7c53b9,411c8c67,c88bace1,a6d45ca7,d2bf5825) -,S(a8a36a94,5fdd33e0,4f0c18d7,cd2d4709,d6efeb88,a53fa0c7,e90969c0,84ff3eb8,1dd7f905,edbfcd70,26aedbe,1cee1cae,23db1fcd,479f02a9,bb596af5,f56ab564) -,S(5a048ece,b3fa944f,90eab4f0,c3e7a06c,3c35f2ca,81263fd5,3670c212,6a981eff,124f1bae,b70fed65,d53caf7b,5e88077c,8e330d05,692199b2,4b3d6d4b,b7c886ff) -,S(32070282,c5ebc2f,665ee579,c645fac4,fd1eb4ec,d7297158,3dc81288,e932b8ba,8f69662d,d68407e,dafb11ee,8842707,c17eda9a,803cbd55,b86dadf2,85bdaa17) -,S(7c22865b,fb04d3f1,bb988a7b,80a49fe,c7810593,27a19786,db77a47e,57afe787,a02eb26e,30f599d7,d5599734,439f19cb,d0830b72,60e70d53,97f06e1,d036bd3b) -,S(a0ba4c13,30ad8252,c06c8269,a3dcc365,fd842e5a,aaf33a4,22de13cb,b9385cc,58ecab13,5cfdbbf7,f3b6d2ce,277b9e84,940fdb14,47568960,c13290e5,fe239bc8) -,S(42ae6042,c8a2ba5d,c8fe47a4,12e2c0cf,7be448,70e67819,4e31ec23,44f76309,72ad69ac,7ba38bf2,2210a6e7,53c64467,36ea3a23,cbc96c3c,e19f209b,dea1542e) -,S(8f3ae8b6,45507a2e,3ea5d82f,47020739,d8f35f0c,8fc11e7c,6e802d5b,87b2a19,61bb8e35,3028ed54,1b83420e,fb9b1473,60425927,d3f9b6a5,d1d2b80,ee5b4cfe) -,S(3a84ba4b,1e151920,a0e4fb4f,30953e6c,a7ba1e12,62ae44c0,d91b437,b05df32f,b20f6579,43525f14,7b23abe9,c90e1d0f,32c44eeb,cddc6ce7,d3cbad9e,7d3e20c0) -,S(6481fe6c,b04a503,3ecc102b,de462e7d,7b87d181,2bc145b6,2d25fd88,e7316210,bcc1b4ab,f5f32ad0,9176538b,808c9187,d4e88b0e,aef31075,b26e5c27,8f64560d) -,S(5340174,722c583f,af9cd365,1f73b33f,8e4bd1ca,cac0af4d,1ff13064,d551a094,e4902135,448a616d,e435180,f85d0a95,d9e4655b,aebf8a41,a3bbe221,1a66a8e) -,S(c0693eae,a5825c4d,6c24e08b,d57bc32d,6c9ee2a7,90dcb49b,b350f852,4e2867cc,da20fb4b,7627411e,5c6c601,bcb8fb55,f4f6178a,efe0ca04,62c85d86,33b9a05e) -,S(c51d0f73,72fd0502,d17f9200,ca189821,e63e581a,8356735c,a91b6e93,3cfa0d9d,8d10e6b2,7ed7edd,2cfff134,54eb979b,a2797a7d,3c6fb413,b3bad4c2,2e352655) -,S(16811856,4d2d99ae,2daf79f8,58b52ad3,3666008e,d9d2c59d,be3160df,bec3290c,2bebf1a1,45617848,e81dbac3,4522cd0b,3e9cc84a,3c08602d,1adf77ba,292e7460) -,S(7ae94933,e1438525,b2ce1622,5654aa6f,b15999a,57835a09,20a49748,7c0afeb5,91912e37,830a645a,138282a5,1e3331bd,a13b87b6,f443f901,95a2f4f5,bd9b95f5) -,S(e7792d97,d02b76ab,2414c5f6,c2d1bf0a,c27709b0,55b2c36b,179599a1,3019d4ac,9f4d9689,5fceb179,b98c75a0,d5d56cc1,dd274614,a2816e8d,16fb98e0,ed3f2b52) -,S(2ffb9d4,946fd63f,24cff64f,4ac79450,3d97d706,eea6c4f7,69d9e34d,3247bde1,66b1c74,34881531,2bd6907a,6e3608ea,cff18832,5576fa9f,f32257b7,eb81014f) -,S(4544ba32,f90ceeb1,1412aafa,b4ae7351,aeb6f4ba,12e00ea3,c165c8b1,ecbb2fbe,62fbd7b4,c2a5cee8,bfb9ede9,b02dbbfc,2bba538b,834797b3,948887cb,9f8f6736) -,S(250b01b9,25d9ffa2,75eb156d,d8c67b5e,5d981ce7,8824d37a,1b09e3e6,7918980f,ba1d924a,32f0da86,e532bcbe,6766259f,eb185161,4042c0ff,261eb81d,3e09c481) -,S(9cf30e54,1f2a5fdc,73046807,32e962ee,62e0b813,901e30f5,ecbe1fee,abeb4d2,7cb246cd,1281b77b,19601d14,baa8ff62,848259eb,6567c741,c6bd54a3,b5510723) -,S(edc9e8b1,3c61a1e0,8f93be12,495084ed,b5a90eca,4f11dc03,cd217b1a,56285a2c,66c2fd21,7e8fac7,4fd43b1b,58c80661,b0e8df85,a2fddfda,5e9f99fe,621e1f3d) -,S(dd94295f,8388a498,2aaa4164,927b81ba,cae9d002,b3ddb6b6,97082c70,f1e2c66e,838c060c,d409c1ea,9bcd9e8c,b1fac83f,3b08c2b2,482d8f4b,fd3ebc18,8d6706b) -#endif -#if WINDOW_G > 12 -,S(7e068e04,dfc0be48,e5c0d3b3,5bfc734e,96e96ddd,d0ac4876,92f74535,685ab7e,df2cd146,90d225c8,d04052e6,93f14bf,69351e08,79883646,2c88401e,4ec70d0a) -,S(73a9bfcf,d10aac9b,46e659f,76c439a0,b7c2a073,7dec217a,21f43f39,949a5052,73b91529,3ea7b052,682062c,8f86cbf,bf379df6,91a9cec2,4a1424a9,b3be10dd) -,S(efddff84,c8cc754,e6e34678,d85809bc,55cc224b,f69be05a,daa847ec,d408c55b,65dd8f41,8264aab2,efe6ed7e,c45b4ac,8aac218a,3b6713fc,1736dd6d,c2f188d5) -,S(46a94585,7118384d,8d23d6df,a4386dd9,dc264f5b,171a7585,7565688e,bfd73f4b,3de5af7e,a298c18f,4dbf16cb,38e7f617,1e684ee8,e8df2a6d,256c011a,65aaf35c) -,S(6890edb2,7ce3c265,d4afa17b,be160a94,45dd0c8c,9ad6d93b,910ea47f,3821cd3f,60f47c5b,10ef5494,cd8810a7,ca8802ab,7c24beea,eb67b852,dd22040f,77cbd1ab) -,S(8cc9eb6,340b886a,81ec4b32,87a251c1,e33e68c2,1f55688d,952b44b4,2a05f5ae,9b176b0d,90e38290,8911981a,3bc475b9,f0323870,150c9c95,5078bf02,307fb6eb) -,S(2b062f5a,da48de0b,58001cca,e96cde15,227875e0,26c94e0b,fd1fe2a,495b0475,537f1c68,3d5170c5,8097bad,4bf17276,da9de994,8eff6805,48b35390,2f1eab0d) -,S(dd55b91a,84b3d53f,4332ff7f,224e9231,cd358bdf,27f30082,52d7a8be,bb7240f9,e6f1a08,a40b6530,ed737609,4deef969,774d2173,a3ac158b,ff681908,192a5c94) -,S(ac5127e0,40b1a979,46c0cdb1,c782ee2c,8986fd80,d7151e75,16fc964a,f2c59c70,849e2249,323d0539,dda0a82e,1764593f,8afbb097,880af8e2,4765ea01,b7ae5db9) -,S(df2f2eda,f0b6ce9a,3784e9ce,1e1ddae7,9d136423,153174bf,f72212c1,b5311123,b9d98f8e,bd78bc20,316da64f,46644026,fde6ab44,162027be,dbac75f6,e86d46a5) -,S(fd83b387,d630c176,23b85e21,62113610,97bdc5f4,3fb08027,73ff93d7,a373e5f9,9a962a7d,375f35a5,9d7503d4,c0fddc9,115805bc,38438837,d3c670b6,ab6cd2ee) -,S(d8fbdfc1,155ec8ac,8bead443,ba3feaa8,d565ca1e,4206cc95,5feb8e1,32cac4df,f9453c0f,ccb99cb4,739258ed,febf7642,7fb1fcd6,1f963abc,9cb9a5ea,751f73ac) -,S(9fc9749a,20a3e8c0,1b309389,16aaf3d6,85f00872,b82350dd,c89110c0,dfbf86d6,a2f679a7,6c92ac59,5773bca7,8f0f18,75c85cba,e75a6379,1094a799,863e19df) -,S(29e0e346,71a91ce9,bdabcf25,2e2196bb,65b81092,d3728f62,b58c815f,2f476a3f,2f440c61,b82e0ae4,798a35fb,9c66b261,1ce5ad0a,ab42f9d4,174bd698,d4d0c0e6) -,S(e4068a15,398955a0,f27e6f92,9cc3dfb8,7fbee70b,a86ee78f,8736b519,ae102d7,a3f2f2ad,550f9cb6,aed99943,84a9a350,16b91143,747d4e7,7d69e698,8f165086) -,S(51b45e10,bb1bd989,8bb156c8,a4c81978,10f16364,d3d55092,48a42028,726c9f2c,e30719d0,4225de63,281ac479,70010cc0,8a1f1d51,48c57f6b,b478c95b,e3e141a2) -,S(14cd5d29,7b8ab6b5,e92ec2e6,6c63b3d,64dc492f,d5a0c5ac,f6fcbfa5,aaa0b83e,5bf307d7,7cdcc866,349ad1fa,fb1c7d8d,5be19270,2a46b327,9b72bd77,e3666805) -,S(a5a8a711,49d6d146,c32254ca,e9c18288,45e9f2df,419ed68f,8c3cddb5,d22c4da6,9f47d887,7bc3d345,af4ae693,35639bf0,b003f481,7833d2d5,49c0bbad,3cbf6c2e) -,S(359328d2,4baa4232,d75b13dd,d146624d,bda494e5,2cc778f9,99a4c0c4,1f9372cb,d31556b5,71df399e,99084afe,c8f680b,b6695d7d,648f7050,a7881acf,241af6d8) -,S(c9eb81ca,4f2a5a2c,17268a12,d901edb0,c8fdacc1,d26c5e8,91af95bd,e673e7fd,6d4a512f,c974fe9a,711ae19c,d9bfbd6b,5acb73e5,355608df,76ed2942,488adb66) -,S(e26631f8,16f3b308,ac4c9f90,eb6102e2,48e55730,24f41f38,6ccde5e6,c2ca8e2c,16e0b2a8,823aecd0,165e2f10,20518253,96cfb814,bd5a248,58a4615f,eb9306bd) -,S(f76e9af3,65c0e7e5,7807b24,269c4732,677e5af9,a3b0a965,8db8355f,f99110ba,80cbf439,d26f164e,bdaf2542,385f9d65,9d174c62,96ada102,8a0cb013,bd2a9407) -,S(dcc8145b,af891483,295d6ab6,9a88fce0,bc333d54,841e7421,e65f6270,852c5dd9,cedb3770,a620e7a9,b40d6cd1,60363bb0,296155cd,80d89480,ccac619a,f31e2a19) -,S(7645e13a,6a1c4d0f,a56a199e,cae93018,7660bc40,41edb847,ed33fad3,c603e4fd,7c8ea51b,7990e5d5,125eccbb,5da890d2,bcfc5353,b22c42ee,1864c22c,be91e713) -,S(ba26886e,d74cbcef,afe7210d,51c1b6bd,4658225d,45e20fb4,4222b318,9e2f3f25,fd885db2,23ddadee,9e65fa64,abba326d,e0b89627,7359e893,bdf50db8,a2b3409d) -,S(68b500e1,31005b1d,901bda65,4a525e80,fc6578d,5e792c92,299d21a5,19050fe1,71ef7d7a,b3544a94,f3dac8e8,77da5468,8df9b127,83e02022,7e05d5f,6b12f96b) -,S(2ccca7e2,613fa83c,27ff851f,12c6fa07,5b19f7c9,940a5064,b84ea75a,da7996ff,5ab70a22,22dd1ad0,d0db2d2f,c59390b,cf37af8f,bed4570,3c6ae0f3,27d7707f) -,S(6d797d2d,6a56a45a,1b5af718,3cb6dca4,383ad9c0,4d5cf3c1,827f4da6,f7179f14,aae34e5,d203d18d,99e84bee,7d6f5a8b,b80e541e,15a3aea6,7b162551,e80edf3f) -,S(aa6997c4,37be76b1,9553751a,d96a53e4,9a565a58,55f67b5,11605996,e98ee327,6034a421,9cdb40e0,9698a15b,2e2f5f1b,6532e277,a1f4f4cb,3cc0c33c,c684835) -,S(56c40fbf,fb8e1d70,a345d53a,7b0f897e,1e62484,dc01adea,d010c5be,ba2a0f48,e9d06789,78b9290,27ba0e09,173d8ca9,676a4a78,7e299f4c,458cb6aa,46f0bd01) -,S(db6ff6a8,3963ed7b,dc262be0,8b52c3dd,b6e1e237,2a535073,1d2903d5,17918d89,a40112fa,f30fd44,b42f6b18,c144ca0f,e248d65,d757bdc,162b7118,7d951769) -,S(8df55701,a46f63e2,338e730d,4a543013,dcdd1173,754e5de4,151ca180,63402c6d,64cf9c9a,64b63ff0,1396ddaf,b48bbf62,b3e69665,bc89ea93,b9dd12dd,57a1c3df) -,S(9d10bc2c,51018f57,407ae460,e5dd5e45,66485cce,de258af3,7bef48a0,1b0588a1,38ea3c08,b2a4e171,7edebe44,e03dfeb9,726b302e,aea0eac2,fcbc9389,84922c04) -,S(13bbc875,cc07a787,2ca7a706,8201606e,560257b,fce7e66,2e4b9807,37640367,b4cd971a,47c82a66,d8ca19ac,baaf1b1e,d2ea3daf,d6f54769,7fe474b1,c0c2c708) -,S(8f26dc37,f617b174,dc947630,d0da6dc9,1857d9a3,13c92b1e,24ec9cc9,5ea9c3e1,3848a303,1d96bf27,4e423877,6591ac44,f887f2fc,1553375b,d5cf76e0,e73f15ef) -,S(2e1e543d,f290916f,5e55236f,660dbe13,a23e0d9b,11065041,ad3a579a,4c7b5f21,885a4527,626e05da,c10cd9f3,218434b7,947bc083,28fe2d28,ff10ad2f,b5473846) -,S(c83c2ca3,e0509ea8,bb876936,e3eb69b5,8bed8f50,e8c7b85a,1238082c,ee3f3109,2b9602a9,bc808de2,b0b0da10,d09da554,74b75e75,5301cc0e,3b07c331,329cd5ed) -,S(8c7903b4,e2c114e5,3264111a,ee385311,afee8b1c,90606700,578d1fab,d3d29607,dd02dad1,964df94d,1eebea9,a2a343e8,b488c401,88299b25,28d47376,f1025731) -,S(48263c54,dd7575cc,b30adfc6,c1c1eb85,b5185786,654c89bd,a38a681d,a6569cc0,e6f107bd,dacdb528,ed98e49,a25936ea,e223ac5f,55cb7955,ddadfb88,1213167f) -,S(6a7c050a,ea7d1f58,7918644c,63cd5d98,accb7127,c54ee274,95fb2546,16f0d2d3,fad19261,27a2646e,34bf733d,c089b0ca,f80f7383,b4bb1546,28d7256e,d821e232) -,S(e1f0a53f,62fbc202,df9147dc,c31cb09f,ece879a,ccc5a3b,f105a198,7f5c3ea8,3930a10f,b0eea30,c314848,94037780,3968f692,fe2e5d8d,cfe920f1,e5706277) -,S(bc0fb113,cb0fca5b,fd66efca,e8a4c866,da9b6a0a,6d4e613b,48526675,d3182b7b,e11e725e,6993eebb,d2715f69,13ecb148,37892c56,745c601,31ca1c6c,bf090f31) -,S(1fe5a0f4,9c438f48,64bf9ebf,89eae7b7,ee7e6a1,74a134fe,266b0329,cb42f908,db8095ce,f912641c,92b3878b,cfa7b596,694514a,ce9b779b,35ad6109,c675f66c) -,S(5de3fdb4,90167002,fa6e61aa,eabfa53c,ade6ea83,3f3c8f6d,e434320a,aa524cd4,b5cbde88,862ad6ce,b344a1dd,88d1ac29,6d7e9ca3,d5e98535,dc158579,147e08f0) -,S(93b06993,a913dfcf,5eeb0be6,294a645a,b2964f2d,e2196073,8adbfcbc,23da54f,7836782f,856cb744,4187330e,fca3c7e2,9c151ad8,1e8b507c,4d14a14d,492ae0b8) -,S(705740d,27d90741,e685a044,f6b055e0,9c33369b,e3815851,886b7860,8e762f0c,c4a58fbb,738d46c6,9e93193b,529f12ac,b2142b32,1fbb3c55,d3f5dc99,173d956e) -,S(7619a000,fc485526,734a20e1,99530f0a,e5b78767,61040864,34a1a1e1,1d93e296,7f300de1,182f479c,f6fa0afe,a2ceb59,ab26f675,77203201,4f8be86d,46ebed6) -,S(fe20f5a8,ddbb5201,6cd346fc,d281413d,cc0d54b6,384e460d,bec5428a,599ff2fe,5b488ae6,e2604871,afebe551,f9957b0d,338cf47a,b4ecae0b,ae7a92b9,242d879c) -,S(995b9727,ba7e52cf,2dd29e07,73c751f9,70768121,8ab88b84,422e1e3f,42ad11e2,c3c9ddc9,7ee41468,c4ec5e5f,529bd8b8,49c8d585,f905b91f,42af5c6d,2f7fd26e) -,S(cb4f2e4d,2ca94d7c,79e91344,55161921,636d26a0,d84c2a16,e267c242,702b3136,215eb6ee,394940e6,cf00df48,f7e2b8b,1b9b2f71,7a68ee49,bbb879de,803ddb9b) -,S(ca0a2a56,34b49144,bacb1070,7668eb67,4572b69d,5e1a4e6f,c722c256,b9fce397,92079cc9,74ab2fbb,a5098c85,56ada7a7,6e2562a7,bdb5ebf,e958eb82,d3f4841b) -,S(fb82332d,c6c0c0af,d72f27a0,24ef163a,bfadde89,67b4c246,acd6b922,e3af7c7b,1a697119,f21cb690,338beaa5,2e2c4b1b,2b90d399,19ccf0c6,60dc540c,a934c7ee) -,S(d056ee05,d9258def,20e184a4,e2018bd6,d07550a0,63db4673,6afec42a,5c513dd2,af2c1d0,d222e356,67e7cfb6,201ad727,89ab0fc4,d68dc31c,276d998c,bc15bffb) -,S(3fadb222,c6584262,c4046c59,4b778635,c6325712,cd828726,7aea1253,42526f12,da5c8c07,fa6811d3,84ca7e8b,fa1d74b7,d181e0e1,eab86717,58666b7e,c199ae96) -,S(d27ac969,e222e50e,5dd915dd,39d3e453,214b818e,fb67e924,8ab4263b,1d9c4b61,c4857694,baead305,6e6709a3,28403236,9a7c55a,d81e7f6f,9b494a76,cb3a1c7f) -,S(412379b4,8b981ae6,a5fa4324,bffd69ef,99cd3a01,91a1acbc,d9340f01,72c565d4,f24036c9,c7dbe4f0,2ca523e7,ebe6ab57,c755053b,245523ab,ac9d3e87,fcfa280e) -,S(d8234eaa,99374c13,b9a8cc3b,663d00a5,bef7909f,b21243ea,ce9dfaa3,f79336f1,b8cbe8e,c4b465f6,6a3c1593,292babc,1845d8f9,1dc80e5c,b1ff904b,6e755c27) -,S(426f8b35,68c5ff9c,bac0ea34,9d8d3c00,427d323a,3d877bbe,47fbaf2a,5d189009,4e02293d,ce023c7b,9c7a1ba7,27cb82b9,9931f57f,78853bfd,7dc4399c,bd00586d) -,S(f1c706f9,2ee5f2c,2412a7fd,c9ca5c79,8717576e,c780f6cc,fe72760a,4497dfa5,c5e1a1a1,727f55c3,b3978700,51a09b84,9ef75895,d6b9c4d5,9f85cfac,2bb7e740) -,S(84e2e07e,cc1d5987,968d6682,525356b7,5982001e,67598b67,608f1869,36c2c679,41ab1343,8ab5ecdc,cbe75a8a,b7fceba5,2903f4f6,f5b43bb6,28173866,cc28555a) -,S(7935eec2,fe535823,44abb699,3a18cf6a,3d599b0b,ef0f6068,9c689b40,76ad2b54,ce2fc96a,ab978861,b6ced574,fe4f5c85,b77480ad,e3d75b40,6c4cfbd5,53371910) -,S(d542a4a8,319f6d56,b79abbef,9da3a009,3e8c2689,421e3839,27aa6a30,b0dbd9a0,5104a162,65d285ea,8f99f3e9,c1951a06,6badb70c,985877a4,f1979aec,7b8173e1) -,S(bc692619,42289890,4af0157,a038126c,41011b9,26fb232f,d3c27d9a,44ece2be,8e2f10c1,47e2a630,9372e854,3cb8ef77,11e2022e,db25f4f9,847369c7,fe52f3bc) -,S(ebe1b736,bb178c08,deacdd80,b48ab650,ae079a90,95f43e51,f4521bf5,d18d8d03,ad81c659,b1450de,45f78ef4,b2a8126b,782f2061,fc8eebbb,cd0a2ea,cddb7514) -,S(e626b908,49e1853e,4fdf887a,df8f0562,666d094a,9382be7b,de152dec,b9e2774c,90cf55da,a4192a27,caab406,2cfb8758,2dca7342,c59627c3,f513ff9,f4834ea) -,S(fba7a057,ba048792,2313b8b5,ba4514f0,d8f571c,bc7ac0b6,1a987a9c,e4381e67,7d2af7fc,142653ba,bf05133f,958a57eb,7cea5b90,ee5300f7,18cee7ae,d69ec44a) -,S(144cdb95,5b5d5181,5a2e5bdb,57033e67,239735a,456579ea,1e3be689,94c35a54,e6016f89,e896fc59,80150d2b,8135b4b,ed0a108f,8a2eaa83,91987a77,6253f1e6) -,S(538de6e,e7ab1b5e,cd74a2d1,a9599d9f,ad28cd8f,2679eb6,81c25e1f,183c0a24,36c0a747,79611193,5bdbac87,d5b38a05,2482b973,213d0960,1de8404b,14121004) -,S(76914f0f,d28f73ee,20ca3806,263b757c,7876eba7,54bef2e,9d10615a,ebc03794,6de24dca,e16855bf,22355786,1626c62c,59330752,f9f8808e,c3930680,33a12642) -,S(69915e6c,f675f7da,f595f7f9,6c912f29,86bee7bb,aa5800af,27e32baa,9e34e4a7,6094fbc0,2f109855,77b53c91,8dd2da3b,139bc31b,77674d56,df72cf22,2b9513c9) -,S(4ee6c20c,900bd4fd,be942dcf,db91182e,2c37eb35,e4287e5d,859ba847,18ce3015,84ac9769,863d618c,4b738e66,8c293d3d,42e2a9c6,4c47cf75,90ed50f3,2062cd64) -,S(a6813c1a,f57bf8a3,8ece11dc,a4c8c581,aa598211,af9ec6a,d2271796,88a0fa61,6420274d,f4e29631,5b7e2335,e98fb2f1,d415c99b,dc5a00e1,d182e809,5b8edca4) -,S(421003b7,107b2897,24dfc743,275db49e,69d91077,6ee53d6c,fdfe6ab,710fce84,cb955569,7b924395,c31cb149,88bcfea6,a932087,3aa8002a,c218f33c,76f9427f) -,S(9cb19e1,cb8c4fc,4009d362,eacf5f25,5e125298,5b546df8,fc60bdc6,48c8c522,227015d3,2c6ee68b,63e20e70,ed7cff86,8fd286e0,905bf623,1b7e894e,c7d70d12) -,S(c7413596,8193588f,38f412d6,4e2ce0cb,c4a7ac4b,75e33704,36236362,8bb953c2,7bee7fa0,1b7cc4d6,d22dd4c9,ec16b39,5e1d70f2,52778801,9ae75ef4,a908aa6b) -,S(2a8e8a05,321f4926,e8fac1ea,8a97cc64,c2f8e398,e86ecec,9dc2e676,61df22cc,63b86507,4e4fdcaa,acb60c21,c0d3f813,64f0c007,faff7780,9c81fbdb,981fae42) -,S(f3ef2e60,7d403594,48aab014,ea8e2dca,5af1d8c7,c6f66127,3552293e,d497a14d,dfcd5334,214b9f44,bc5d1d96,49d78c15,9e9ce44b,f43dbca9,c637c31d,622cccc9) -,S(6d5c41c8,169c33a5,d1111b36,1b1d6713,a9396424,bbfeb65a,80e40280,4857ead9,4c1f74c4,9f01bc2a,27a91d37,f59bde,3d674220,a521aa4a,6a0c548a,a45e84c8) -,S(5d812a61,c6a986b0,2c5982ce,34fd478d,60822322,47e07c73,488c71f4,4afff85c,37083f7b,16018fc4,25749e16,4c923484,680b1517,8bed41fd,cc8da253,ffa960b8) -,S(e01596ec,b82ff347,c3ba9710,82911855,720177a6,9efa7d5,dc6aa847,7f73093e,a674c832,849884b9,d38da5d0,6a58e4a7,a17acac1,8776577e,5547eb3b,b45b3bdd) -,S(67a5a900,313ff2e,7b32fcae,adcff7f0,ad52b960,ef6b0d0b,8344402c,9980f55,e77efddb,5e8e8865,eb807575,37c41e0c,9fdf928a,eb8b6a03,f41703c9,3c0a4a02) -,S(2b96879c,2e2d0ad8,281c1647,7de62583,53d77db3,57281c21,7df0d7c3,6466b277,dd5d3473,43bac32b,cc72408f,64a9fe7e,7e0dae06,786a7074,3cbbc846,80b62b25) -,S(ab94378d,f08748d7,2df137ae,a3e3e123,639b054b,fb726bad,825e2d9c,310367e9,5785ce24,40037d11,a8331865,c78ddaf5,7f9d769f,f2df11c9,9e3dd018,43a10f03) -,S(70782556,fd6fde3,8c93def6,ca3b6c8d,2f3fd4db,87be4985,fa3aabb0,43e7439f,7913bf65,ecf15020,cc5274b4,8eaf5351,51894bd8,fa236af,8f9b3fb8,178ebec7) -,S(3025d070,138bd507,b338c72c,1024a3f7,6b4d5e80,efcedeb3,e71a018b,77ca3942,3a8a6a0e,175eff95,a94172b5,f2a4ee53,8d503295,63a5b096,f83dd669,eb470ae) -,S(3fe372d0,65e97abb,94069e7b,2a8d01e6,576081a1,93897ac9,901a3d18,b9ab0b6,2efcee92,3154dcc0,377315e4,1d67b5a4,82403552,ce260c2d,4c1020a2,54842e5a) -,S(368c7011,3a9133ee,97ebe8f9,cc06bd7f,c3c373e0,da810164,bce5a30,2af55636,21bd40fa,4870a8e1,6f28b942,bc169712,eb7d70e5,a6faa4a1,35bf86b4,d06162a8) -,S(7df8ffd8,beb45e4e,1e440f23,ad6d713,57682f68,e54fd003,87eeac94,ecd96810,3d9e4cf9,908e5a99,44857d78,94c7ffe7,dc55550d,a07d3c9,ec07667d,982ed0df) -,S(cb6ad939,eb49c7ee,7c216262,49b11276,88269172,504fb8bb,dd2dbf7d,b6f23d4,ec8604db,18f27367,de1319c4,59f8e668,5480ca65,e1789cb3,45e0018e,ea98346d) -,S(5ae526c8,fc319e6,e054e6a7,59d9b205,d8a1e042,e684c53d,39098f28,70f4265a,da1e1281,14c25a90,cff3ef80,d5577c08,a03f4bab,d9e33850,f2488617,d50a9a63) -,S(868d7889,6ddbacc,1bbf2b10,e00456d6,17477767,5b8d3323,a8786ae7,25ff7661,d92d681d,189b0df8,e2be57ba,a9c146f6,46e6ce48,342a0ef2,96fc3093,af22ca1d) -,S(9f2f0b4d,e7b881b6,c4dd1f8a,74106a32,23bd3298,47c325a4,8341d899,d7686b74,6fbbd511,c2974af8,b5729ca6,658562f2,deca285c,b47f16e3,c444fc14,8e440088) -,S(faaf222b,813b0df1,5bf2da98,3ee2eaf6,c522f5eb,e8c08b4f,e6950376,d3fca8a3,bec53e69,2e98dac6,8fb2ae87,44f12abd,47f00e6c,5d6d1469,b2cdb41d,440b472e) -,S(7f5209b9,db4ab9fa,2c2a7ab7,6c5c62f,13c81c80,a4ec4008,fd67d229,a7161475,a13d6cda,f9e8699f,f397d1c7,6f191cd8,a58be40b,9acc4ce4,e69cea0b,4a48d193) -,S(f436156e,80b136f0,8065f395,e2700a14,50c7b492,405a0c04,6834bf4f,12c84c2a,cdd957b0,5684e01b,a760807d,39b007e8,e7aa890b,8882a0e5,9118951b,bd7e60c4) -,S(ef9aa749,5c5b37d8,2060c2bb,3454fa6,88216754,2b24d69f,201f1c31,3cf1d06e,f840da4d,f1d84a8f,ac125750,e4e6cd7c,50003aef,d1f77666,54ccf4ca,f27a4aa9) -,S(7deedc43,e96eb93a,c290809c,25e7936d,6d9e1cc8,a5971d40,b122896f,fb5de05a,e65c0e66,27b9d0e4,e7b349,ccf12fcd,de6683fb,6bc93381,22026b65,26a8e0ce) -,S(5a1bef15,6669795c,47be7495,582f361d,878384f4,f283e15c,e74b3ce,986d6459,ce985a81,1fdb02b2,9e35b97e,1833e380,69b28b81,ddf8cd61,b1179c47,2ccf39ff) -,S(d8123d39,233413c2,b14eeb78,983c6fad,73b8fdcf,84b2383b,fa453558,e525fa8e,ea9d399d,905b7200,46ff78a5,abb3cb56,835e35a3,c958095,ea226947,a633ef73) -,S(62f43dd4,f1f4c310,266a36c3,909afb5f,10d3dfd1,a7a6b5d8,93931334,e4d4bc8,bb7589f1,f83bd647,2e34fe22,53a101f2,75525829,daa2e8ef,89fa1dcb,b590f3ed) -,S(6cf371,d549c045,1415aa75,cf594d4,865f6e44,6f62df4f,cc1cf312,f79d72f7,f8ceb62b,5c979bd2,82a4ce20,682b45a0,2b3dee9d,68ce16a,7581adc5,c9e93af4) -,S(5bd7b780,770be9c3,7c1638dd,8f954086,49aeb371,516bdf3c,509efc5b,47cdd7e7,d46c7848,8a87aaf4,f606b91c,5add0c25,efc12c03,2a28b1e3,2190999,286ba9ff) -,S(c7704954,a319bd4a,e5a08665,3b959ba0,81eecd7f,f15681af,e6bf3db,c36b6a62,373543e8,24784ba8,3f53b9c6,189ccc4b,e508f600,b15c7378,36e3b3ca,516d0fe7) -,S(2b4f27fe,41533a9d,d807da70,7102c1ee,d6e92c8d,9e43958,8fedc6d0,39b19cda,98ba8310,ecd7cb1,c11fadd4,a92f4c30,49ba2180,24015d6b,89e2ad9,f81fb424) -,S(e7d4171,b3dc34d,2600c581,d6931f97,2c920c81,3d7c3db5,4d306c8a,5d4c0e5a,b29581ba,9a825387,99fa97ef,b5a6c4a3,3e75b71,d1cd51f7,5b6144f2,4a9a409a) -,S(6203022c,18f43577,5270043,56a2717f,2face761,e806e84b,2b5660d5,f1c5d52e,18a52f25,5d0a4d75,275fe97,3542b97e,212efd6,aa8864eb,6c80865,136a720d) -,S(bd81c7a2,8c1c80db,a0e327fe,3b0fccca,48987679,791e6630,e81c004,92e43b2b,ca50a84e,a14bbc64,9e0831f0,7f185536,416064ac,e93a8678,db1e2347,803871c0) -,S(9bc43e1a,d3c1390f,cd1385cd,603a6e0d,b875eb4e,6f3a554a,626a9b4,fc4bc29a,857a58bf,9aa54bb5,7acd8b34,b79717b2,64ea39bd,d8f4a22e,6b12e6a6,e0cb2cd4) -,S(3055a68d,194de3c7,9ef0117c,b98bfaa1,5e5bfb71,c656f908,2c8769cc,a7e40f33,183f9ea,dfebe1c4,bf0218cf,b6aba6bc,acbd8c72,a7fe086c,1c9233e4,340d1d10) -,S(4adbf984,ad1fd188,c9271072,43583b80,2cec1231,7d8bbe1b,71079fbb,734b08ac,14527188,9560ceff,3d950766,8e3f2d0b,2192ceb6,f79f5954,7094d5e3,d7ec04e6) -,S(38f72dcc,27e041d9,c7bae397,9cf16d22,83fc6a36,aa074b0c,d00651d1,a56487cc,5238c97c,33a106e4,1370d6f2,c0b6ffc6,49610444,2e51988d,f7160c3a,933dc0bf) -,S(de55bd8a,7bdffde0,a1413828,ac59ff2a,4560647,47c27813,322188c6,655be2d3,477861b0,df5b25f3,75f9d097,97b0afb7,67bf9d51,b996d51c,e65d3bb5,42d9da) -,S(c617bcfd,c47e02b8,918edf98,666fe912,e19340ea,6c567893,8739b89e,5e3bcc66,b90ba117,357e7683,2ae0f4e8,644cfc49,a6e04672,b5b08d47,3b826349,65117072) -,S(4655c196,1b5188c9,4b6402f1,e92b3033,c455f4db,ecadb672,4adab3bb,f1c84758,3ceecc93,a2575f4d,fb202df4,f4bc05ea,714600c0,28389b5c,f2c1c6dd,e6fbc4a0) -,S(fca90f40,dc05e5ad,3693c503,fab43da0,110df431,9c1dc4c9,e5f86e8d,d7726a45,f5822f9b,be3e6604,1af37aeb,19a70a6e,7478edec,68c8e1c3,e6cc86fc,5f5771ca) -,S(3176cc4a,dcb28258,779e88d7,f90d3b3e,a31cbe05,78c7cafb,93ff151b,d27f61e9,3863f2cc,148a0a43,c94fe7bb,afb5ab5b,6a18ce44,56cd06aa,c340c231,42cc0135) -,S(63269f73,d124210a,d070db15,14f82cc5,51d9c19c,d31a54e0,b811e650,ebb2ddc4,bf8ec7dd,8a787a42,4a74114e,5088c387,38246bc,3f6aa188,e300f0db,d85cd0ac) -,S(679a1d32,8d0f53b6,1ae7f544,541326a8,f07e749,34dd2708,dee3ce54,632003d0,83ca1348,8f21eca3,11be341d,5f6ee9a6,c9b3eb55,c9a3485c,349018a,725c350f) -,S(69a27d79,29982c84,d3948568,a54d8933,f7172f9d,e80276fb,846cf399,e0b38b28,f411d207,cb0f0bb8,574b16a1,22f39bd7,69c8b7f5,ac2db4f3,a02163e4,3bb26168) -,S(298d5057,1af5042,cbff2171,6029cef2,abfdabb9,cafebc7f,9dd56c8f,6773ee4d,f4343e71,d271844e,412e62c4,bf6dc36f,4271bda7,9ccfa220,75e3c055,aa97e9e1) -,S(3f2983da,46d1f101,8f8eb984,5bcf3930,e26f66e4,544f63b1,f8f8b979,200c4653,4973a914,c4ad33b1,36d57e6,b326d380,9b2c38bc,79d81b53,b26c5995,9d71db0) -,S(f836fd3e,30ceb88d,942d64b2,a1d2a6f9,54412ea1,ef6a3b13,59faa8bf,7e3538dd,720a3081,53476b5a,709fd29c,158b7720,c8161ee3,6e6aba3,b28e0282,cf7f9367) -,S(dd72eb9b,911e38a2,63bc8ee4,fe991fe9,295ed522,1eef930,b3ae2df2,ef583a,2a0da5a5,688bf7f9,79285d9b,360b53b2,398e86b1,43f10b86,83cb40c9,40c1b2ef) -,S(551e2650,46ab255c,c427bd81,8258b7f3,7cef92a4,496119be,283f033,4968a619,317c33d2,4cd8f35b,9b86a5ec,d1582a6e,e5ca16aa,3c6ea23b,2007a370,e7bc4f30) -,S(6683de92,131de3d0,ecb19a30,47825591,ab28cb61,5c852a90,fbd3ad78,5336c650,49eea58e,7fd95523,f8a9556e,c46fa0e4,b3c3b2c2,8e5d9e4,d636d089,282225f8) -,S(b5b3b1e2,84a6ea65,e0a9b146,e8f895e9,ca99ef3d,31a4bac7,bea49c89,3cf97805,a1720a94,f333e296,f2b91437,e19500be,3cf16cc3,547e9667,ffa4ee88,e5b6fe0d) -,S(a5019773,7c337684,9709a232,9718d463,ccdde43a,55350d10,11a2401f,9bcbf466,9cc069e,ffefc5dd,e8fa5e09,b6b751eb,c51fff8c,fbf3c27e,12efad87,a9d429e2) -,S(9ec3498f,eb2bd861,42841b66,3b1c58b2,e5cb7224,88e2f849,e1236b63,ec1588fb,e00c91a5,e14b97f0,362719bf,2150dfed,e517e585,a807333b,a000652f,c1f5f12) -,S(e10b6cb4,adc13185,750b446b,ab926667,581f97bc,5aaf04b1,f4731abe,f3c5b6b2,53a51213,7db20477,f3a87bba,5b65c01d,d5520b42,f2660ed3,c1f5fdc8,35e2b9c3) -,S(b754a967,e36ea7c7,98c93691,e02b6043,60ace927,13b18d0d,3ff61ce1,dd3ae314,8a9a3963,9aa7ee59,a42f8d5f,bab01e50,d83ee029,933cf59b,e12b82a1,5473d849) -,S(5fefcb61,c10cbf3e,6f8a51e,6bea569d,7999a275,6340ac8d,489183ff,32efa869,d81b3093,cbc4835c,1d88c093,28c20541,dfe49950,9b349207,15bbe1bf,4e881e83) -,S(fe51a3bb,4ac97e1,96009400,b27c8995,f0ed6f0a,b29b9184,70aa442f,27d2d848,8568fce0,a4c39e44,f2b8aaf,59f0b183,d306254f,83cbd6,ec5fd568,c9116a58) -,S(6a3e4629,9fccfedb,c58d5d38,aeb2a420,391df798,e447558d,7b591466,fab7dee3,1bed8fba,7bb15d9d,d42e7b5a,3ab1d9e6,89873eb9,e3161a91,aec3ee9b,22a5e548) -,S(adfdbcb8,3c40d4de,f7d62d97,e16bd32,33db304d,392492ee,7457ffc8,97450c37,7b082bdc,163549ec,2a8b588c,4156ac23,8fde7819,2e1cc195,6be85b87,f4138e0e) -,S(96850fcc,9c202c54,83654c27,2d17011,509ed7dc,6ecc6cb9,f06c3dd5,113bf61,10404432,7f966c49,af0c05da,c7ec18b5,b9fcc455,a01c3b6c,88b8b0,d281aaf7) -,S(2ae21197,8f78ca14,d88151ca,804379a7,1703f514,166f3ac4,f09409b5,5c458bbe,4de74cd9,576035fd,451c7dde,387961ce,2328e327,fa0312c8,6cbc9dc4,19ecf7b1) -,S(edc18742,e1b5c996,2661a332,cd62c426,7e5816e3,c52746cf,b79eac61,1a987e57,80003b3f,c63309bf,3f9d484f,ebabe579,29ba9032,30311bc0,2c021a34,5b4fe5e) -,S(7802aa2a,5fa0f0ae,29a90885,c8b94368,38b35d49,843765aa,1d6a640c,fe43a244,c7f329f,e63239a8,407297e0,416c49bb,7e3dda11,85baa5dd,7f5f7167,9192a803) -,S(fb774579,b124475a,c36ede71,2e3fc5aa,c2173de8,35e72386,bf67bf7f,992335cf,c0e66b51,63c17b7a,e43ebf0e,31a8d641,b6f413a6,b763ac01,cdfcbcc0,47a82c94) -,S(d81a3d8a,43abae9e,32f94881,fe9c1200,695a9c24,a31b6982,51e21b3,fcbc2852,630dd811,e8a8cb6d,7bf51de7,e0a98db5,a693e3a3,c9064dbf,2ccf6bf2,dd12673f) -,S(519fcfd4,97cf068b,804da0c7,e2268cda,7cb2eda0,4be5249f,9bf776b7,c7324cf0,bec6f4cd,198ab3eb,be691646,6e44ab9f,a357c8ec,3bca391d,c20e6ffc,9562fdb9) -,S(cc4ad3e4,8fd66073,5e193853,e0f9b1c2,3e31b284,e2770441,24f9296f,868ef592,88af158d,8583c474,7d5520ac,67b03c75,9b12151e,db25af68,996263ad,d783c27b) -,S(add950ae,6f5186a5,98b40cf9,64ded6ea,c06a57a1,4b85de33,8f709034,78d24117,c59ca4bd,2d69285c,debd6853,a0bec744,111f6dfc,7004d65b,c047bff4,a3affa7d) -,S(dc071b45,43097de7,12bc8173,cb358af,ef0437c6,7c4927dd,d0bc3f6d,bab383e4,793912a9,899b304c,173b2adf,c187dfbf,f28fcaa0,fb11b85f,9e410b40,e95ca8ed) -,S(5dce337e,6db6099d,a9c37da4,a96b7a72,fd97a672,47f6babe,94d79b1a,aec167c7,1b887fba,1f098a43,b6482991,f16ba2a0,eb35bf56,64eb21d5,7549dbd6,4e4377f6) -,S(516eb6ad,8493a662,6d22ead8,e808982,900a83f4,3e6109e5,ba284cf9,e1f5cfcb,ca350ab3,8085b46f,48d8308c,61d3f947,ef6a8511,bb36fe3c,68d30fef,ece05042) -,S(f767c150,3b1f2da1,e5b91211,4e917c87,732b3fb8,8c860a3,35af1c7c,f00e5e75,3ecef8c8,cdbe467b,888f64a2,655ddab5,9ec610e,153cd657,95bb473d,a1aaab54) -,S(f9bbebcf,f792c8c,a7bbc5d8,f177de7a,4185582c,2cc65e75,31f3ac26,73c977f0,290ab4fe,fecb3a26,256f767b,8a19e55f,ac751eaa,acecaf52,b8c99657,49614a85) -,S(c6bfe1fe,be5c8db1,f55bff42,c123df61,6ec3adbc,c9b08e8e,af477fcf,4d47c45f,c595f882,d6d6a2ff,d832eddc,95679890,41c27101,347ea995,c79ad56c,d641792f) -,S(56c2d771,808fb4c8,71dcfe6e,5170bb47,c5559521,8b872425,761829e5,e0d3ce1e,6de72ae6,9e03e626,fdca9188,9e721c61,12ec15af,7163629f,5ee0fc9f,540468ba) -,S(20218b05,ec9f5be5,87a96d8c,3c0cf7d2,da9ecffe,fc604fb5,66a3667,5109d663,2ec1a7c2,c5357e24,1f2ea0aa,7a7321ae,b41bfa3a,88b42e12,e79283bb,ef8f6993) -,S(3a089269,a04ccd9,5bfdb4f3,3494aff3,519035f4,bb3a4f09,e2afcaff,976be4ee,e5680e25,fb0ba1fe,91693757,b3404b32,bbeba22,640da757,ed91ad85,6842d1a2) -,S(8f9f2296,a0cd8b53,db0fd0f2,59860496,dfd3e101,b2975a2e,2856523a,f45b3f07,61c15907,2cacdf31,b229015c,d6290d77,8ab3be0a,57785920,a3fb5722,b5c625b5) -,S(86580be8,695bda97,cd1599b2,6d4b6328,97e2b90,d1ea106c,836f474c,fe88070e,abae68a1,7e19ac58,38a2fe5f,d07dc7ee,2bb220a8,9dba4ac6,166c51ab,b17d7d21) -,S(fb6ac38a,1e69d589,ecc5b4f0,e57aa1e5,eb1f9458,fb187d04,8c72dd29,72b4d762,d601dd16,bec271f3,16f1d3af,2b82b5cb,e5d1806f,b960014,7fb01301,86ac32c1) -,S(7c10606b,c54fea81,bf3aec94,72bb09ce,c5bb7d31,b66e27b4,242b8dbe,7ea5f0b0,12215180,d3d65643,76583987,240b445a,2ea522a,3e0250ab,d14d77db,bdf68f54) -,S(85e6ab94,833593bc,74c7822b,1d9f384a,740a5be6,3b846495,2042b017,2d52a1a6,f5c160d0,68d6f86a,8f651213,8cd28e3e,d6e69fcc,dc75f0f9,81fe5ebe,1fae93a) -,S(7e1e2d3a,99cd1ba0,51b74ea0,e5471f50,5e626aec,b880ca27,f02113ad,ff51cfe5,413ec82e,e9d4fe37,8c232229,136f1ade,c1eb96ce,c0062997,81f4b009,9dad89bc) -,S(589640ad,813735f2,ed7a08dd,6931c61d,6a9490ac,729c2bd2,928ebd01,e87aaacd,89d6b10b,8a89fb4b,3679fc33,96c4cd5,7a1e909b,e343ee15,c1a02719,20485429) -,S(7080cf4f,f3465ce8,fdcdb0ef,3741c19d,91fdd7d4,44118c5d,7b7ad040,5e6e6608,7a3f0da9,5cbc0ba0,b5c6d334,f80db1d8,3033489d,34143d34,7dfad89f,8e2441fe) -,S(bb660b4c,2d400269,2dd96bd4,d7737c31,91deb03,6553e61c,7d59a876,26917c55,b494ad13,a7560497,6068403,15e8b86f,f150af11,18dc02fa,f5ea3f40,c0983c24) -,S(73a241ec,7ebf15b2,4408161c,5d8a5c65,3f4f4fb0,8cddae0c,1e2c506d,9f221b27,80534bb4,33a0a56f,78486504,1d480d8f,64bbe192,a2f6f32b,5e1bc175,d463640a) -,S(fdc1ef51,f08bfdbc,7705741e,6a2b58bf,9e45f202,c3d7ba6f,89a15aaa,78b1fe07,7e9d00dc,dc1e4878,647ac05b,55832540,1684f714,755f4e36,880e5a0e,996c0586) -,S(204842cb,a0ce5cc1,3ab44736,ea0e33df,a15ab13a,912687bc,6d6733d3,a33618af,afc92205,a6e991cb,fad18741,818a94f2,9e1804dc,2145ba35,896f92ac,c96bd521) -,S(a03a9c1e,f82c3151,81009567,50486869,a47c4a99,83bad93e,b2bcb60,157ed768,786f9164,fb9c6980,eef3e5ee,d9a43b8b,2158ba2,dcd8663c,a26cf19f,f6090a65) -,S(5e3b6e5f,6cb41784,6355e3ff,7da813cd,fa18bd42,c54565ba,ee19b15b,dbc00ed2,b9c3a553,42bf2284,fc3b8f9f,88d3e4d9,9d6f358a,c5c8acfd,e340036c,42ee603f) -,S(19b0960e,82d1280,663dfbd6,efb2746c,abf76476,1029a54b,154385c,a05dbc70,f8b28bbc,440112a9,45f35645,135d041d,33df5ded,92116f31,2d2664f4,e5504773) -,S(1061e900,7597bafe,74b9b274,ba1a22cc,6f1c2d1d,b6be8d05,9876638,dff3677e,707ac922,dec592ec,44d7b59e,be2518a5,fe2ffff1,4cf4cfa9,8155c781,21444b21) -,S(c9184c11,60fc7d87,5439b567,69a0e501,cc0e221e,3b155f57,9a71cf1,f3030b85,880b69e3,7c04689f,d6dd30f8,75f23899,8e83e594,9fb1ee30,8c43e982,28327805) -,S(a35fb304,4dec52cd,8fc5af94,e6c26ba5,c8fa2364,2622af12,d37559ff,4374cf04,1544f375,692a3584,ac7adcb9,a3422dcf,8b360471,85326840,42dd755c,112242fd) -,S(ba8c03ad,60ffebe8,118efbe8,eb130f6a,1b2c501a,78000a8c,1b204bd1,b90929ca,e95ef729,a3f341e0,faf73211,2f7800ab,65b88d47,ae137722,f11369c6,e3aaafbe) -,S(d2ba5755,842d8a77,97fba189,f49a010a,fe08495f,5e64bba3,361d1b52,8f30ddb9,da3669b1,cad179f,784bc5f0,c3a55d60,549e72c,390b7d47,7c030bfa,53df7957) -,S(3e04eb58,7ec988b2,77b1d2b2,880ccb24,d3de1579,54ac994a,86db9ae,6c8703f2,fa412113,e6dc85d9,eeb1d650,3df96fbc,ff3c6089,cc5c207b,b98cdb4f,e728dd9c) -,S(efe5bb42,4339a49d,3e19aefa,91f466d6,60c9f120,5df91ca1,7a0da3c2,699fe7f6,98c6212f,fb39640f,cea21db2,97cf9fc5,e3576b0a,7cb4408f,f9e3e9d3,245156e9) -,S(a29442e5,a330336d,eefe6591,5c4e0ea7,bca2dc2d,9816c8a3,2bd66a4,baa0908b,a1bf8829,7320e47c,3b774c13,a6fb9e6,dc5e7789,44666311,2db427a9,dea135e6) -,S(454bccba,6f7225f6,a91f632d,1c9218b1,48e877ff,8018d371,4da8aa88,f08bb792,da0ded31,2d532b01,60a1106b,202ea0dd,8157753d,a07e0e3e,918958b7,45ec713c) -,S(3163940,32c39566,cb0631af,a2505404,56573782,e940dfce,d425834c,dcc2dca9,18c561c4,1b15b0d1,a477464c,6f4d668a,67f0895f,a55544dd,8445a8db,cfcc5fc7) -,S(54b5375f,53f07bf2,f15fced,ffc7132d,5240893a,3bce0a92,bc4fc884,49b07703,31be2b3f,a944251,e52922bd,fa2ea218,f5df11c6,d67226a7,b3f163ee,61abdee7) -,S(283ce31b,745d067,2bfb9b6a,694da3cc,de9033c4,639e8328,d2b7ee6,58b3bd,f6a948a4,d452bb56,e3dc24e7,6e81d2c9,dc1c7aa,67aab38f,f9d20044,d8c0245a) -,S(b5e74f53,117ba754,7b12419c,b0494579,48d5f831,624bb3e3,a60167f2,10e99967,5f635754,d635f9aa,a83c22e8,9f383008,3da8331f,4cfd9b5e,10d48280,718dd3e6) -,S(681e5f32,cfa33183,170dc776,fcd51daf,d587c34b,1cd27134,a856713,cbf83080,c587d8b8,d144e4dd,7b4361d9,b7fcf30a,76f646ef,fbe390e3,8f241a54,7279266a) -,S(1fba5eb7,722f289f,2521ec17,d05df56d,2f28b221,5ff8c621,b925a5fd,29f1d0c,df1140d9,97ecfd4d,fa7f287e,fcacb66a,34283b63,5b2bb7d1,524dcbe9,eb11f5ba) -,S(38bff4b0,df378b3c,ed38fc5a,733f1bce,17855b64,cc254f20,31e1300a,6a0d0a77,6d4f065d,f634296e,64c485ee,32537475,f35a5065,e73bfdc2,520dca1c,6606b1be) -,S(707013c3,59a9264b,be4050d5,27b5798f,779df8a0,77cc95ed,6e08f74e,e57de831,b9f379a0,315386c0,657b8dcc,53cd98ae,582313a7,632e4c3f,da9c9157,14ea422) -,S(ad94ed2f,70282484,e490abbb,320905ab,fc5b8c91,9de6535a,73da3f63,45642ef5,9dbe8813,a554e1f3,e98011fe,c6545216,fdf4973,6d026bd6,cb8702c2,aac88457) -,S(47b56de4,e991876a,499ad155,2443785c,fd174f87,58b881f5,4f545584,ff62612e,a140537,5855beb7,7c56117a,5f753777,383d92d2,d4912d9,86bd59a5,7cefdced) -,S(51bce64e,9291a693,1f24643a,f11f2813,f31f624d,cf336af,3cf7b48,15f431e8,8f743d9,a3012247,ee35d28,4120394f,f40c4c69,d75ae13,a063aaba,ed07e552) -,S(76287cfe,b52c5a0f,ce98e56b,49b4ebe0,83b80bee,3bc7447,a0cb9542,e7f7a43f,736b7e56,fa5744bb,d39d064a,50d98b07,e9e3399b,dc5847ff,13e33eb6,e2a7a7bc) -,S(614d739e,ad01010c,3191aaa2,c1b7771a,8dc29bcc,f1c4d55b,181acdc0,df6b8f5e,5ccd4e8f,e8607b76,c8a96c2c,5000464e,5591efdb,aaf07166,4f4db66d,c2f8085) -,S(c38444c8,ee8c35f2,b339404d,90d53ed0,35cd5889,89663808,3e2d33a,5e4e1bc9,8b4408cd,de5452eb,dc222109,287fa9ab,1d2ffc9a,16b93f44,1f4bfaf6,6ccd29f2) -,S(8a9c9649,c6016f35,d819bf02,852bfde6,56a1c197,2dbb6539,2391df7a,99c8f349,b2dcd957,be2c19fa,6c4a6030,a4cb500b,1797aa5a,339181af,dc6e974a,d769a8ed) -,S(a0f5cd1b,e4449709,25d0ea0a,6cd28d75,96292ab4,1d1766bc,ed6b3311,bea04b03,d270b1e9,291b29b0,ce045d92,3e449ce0,c8d7931a,71cf4b8,68af9594,927ff95b) -,S(a78f2336,87675987,7afbdbaf,28e2590,25c64ddc,a9543a64,709d4c11,1f3a9614,1365fac9,a5d245be,e5245b3a,b1f50d19,de34aa9a,439f5e7e,e241f042,32a6de83) -,S(3bfd37e3,ae482c5b,92baa6f5,a413a46b,af6cae30,9ee3fb51,4a9fc3e4,b391769,2d930818,34bbb0dc,66e424a0,7778c9cf,d0219c06,4dc7fd66,bdc554f0,396d1c59) -,S(92cac49a,261d23,e776ea75,7e796d2a,d426f23d,602ece5d,1b41cd71,d13881a2,8c76ec13,8e0f37c8,99a3e587,a8c0c5d8,c7a43ac8,187a35da,c0d8492e,571521c1) -,S(cf6ede0,ea7dc67,cc370894,1493567b,718944de,7a96dd6b,82940214,b56842a,e2b717d4,e939608b,7ad6128a,53dc8c52,fa070d0,f591842c,a76e8d0f,54627cb7) -,S(6204c998,ba512945,26ecb92b,bb06e218,968c8c2d,11e0435e,3dd1bf82,fa91e17a,1690a15f,e78365c9,c8fae21e,f0af2a3f,d1ed18c7,9a607939,d12d8add,94cd0ea4) -,S(a2c4fb48,cc5500e1,35268d13,a6ac2e16,d8ce0707,f2237f12,ef71affd,e4c0aa5d,3809440e,e608c897,cb7e3906,c58123ab,c403f57a,8d59b950,9e5f2d70,3c0cd839) -,S(d8af7fa1,cc303e4b,c5da36a6,d3b2e309,6acc8ec4,d73224f2,b667873d,eb656f60,9fc7f2bd,5a5533c5,dfb39f9,7045b135,5e14d81b,9edeae5d,dd4ccfff,f0c6de0d) -,S(3e9a00ad,b873291a,604e6bbd,b05304bd,3770733e,d1daf90a,864d775d,76dea0e7,deb49457,f6d1c4ef,53524e37,f19a8d77,20a5cb9b,321b4630,51f8eeb4,901ded0) -,S(bef5ae9,30aa620c,9854346a,ac1b2ac9,760ca8d5,ea189368,9de50e5,d3dc3d7f,20d80c42,f7925f59,b0212b9c,7d4041e5,5da98a3,fe373034,c0fdfad6,48dfc48f) -,S(cd4169fb,cd28d507,6c174308,8f39645a,38215e47,888a435d,5922b490,9155f67f,f9e62ca2,1a5564dd,5a65f274,356c1b68,a170dac6,4b5aa5b9,29dc2f26,35e74674) -,S(a4b691ed,34cd2624,fdda2504,797d76cd,4bd37b11,4cf3921d,538b6042,ed5a4c28,c65374b1,6781b4c1,15b0ca54,53e3397e,5c045a77,72c72d12,c336c205,d26af55d) -,S(5e4e916a,4226b788,197cf68f,aa850c0f,c2b3a615,bf9e847d,c9e55dbd,88aa4818,3f3c3ea2,5c7c52e6,5c9991f4,464f4b2f,f3395d05,3eb27280,8d984a31,b798951e) -,S(dd4782cf,f4d69f72,c951b3ad,50a4c601,f743e6ba,2194d05c,a5f474d5,eba74a7c,97a7bb5e,9854ef7c,5e3dd6ae,8628d8c2,5d3a791,d4db281d,6c7c12c8,20977b99) -,S(a1530ad5,4ab405ec,ddb94543,2669c07c,281aff41,13e4af0b,cc080991,c1adce36,f3d25221,2732842e,5dddda78,1e2aa5b1,b18550b6,fdbb968a,77444958,4a63e756) -,S(51924ef7,b438e4f0,614523f,232af64b,e5ee0d32,ad8e5323,4a2d76ca,9e64719e,87c115a8,11f94db5,6736e82b,8b644bfb,fdfe6e55,8ead8176,26858c77,128a8095) -,S(82cfee68,e137d874,107625d4,be20a9d5,6ac9055c,6b97563,a3bd5568,53fada6e,dd49aa46,c4f5c51c,72a804d7,6dee7a72,a363e978,502a5cc0,6ff67987,30733b7a) -,S(a3738876,f7f1ef44,5a1346b,36c7da6,e02b70fd,2cc3bf30,a4efd7e5,5f2e623a,6596f52b,e1ea52b2,be0de46e,5480331a,b1204d36,581b2edf,368d9611,ea04a21a) -,S(ae4ca6f7,aec818d7,2b624fd6,b2ccf24a,8d8382b3,18b0dd7d,d8203658,2980bcbc,6a7ada03,35ad7c57,1e2a29f2,554c8bbb,34815596,1aa995e9,2378c97a,dd8f1ae2) -,S(be33562b,fa9d762f,9b18d198,4dccb9c8,4d6ac894,2d8506b1,400f7dfa,89d12732,b666efb8,77c666a7,35336cc2,14e874a5,c4f5c956,903048fe,473d2e6e,9475d442) -,S(9d7da6d9,815b3db8,5303b288,8a60ff6b,f382891f,5c45ecf,37cb92da,37c74446,46c29073,72ba5be0,e61f6d73,4b413d44,df3d2c0d,89fcc1ac,5402b68d,755b12a8) -,S(39233d31,e513c2bc,c0602849,8bb7b3be,b5981fb,7c99a366,b62a9df4,3b0d4d3f,fc27857c,92e0ea4f,4d8ac3e1,c61fa774,1ec57d4b,a9affc81,f97e384d,b916dfd8) -,S(5be2d788,db90e83b,58d02dd,7b58f41a,547e6f33,a82d84b4,3f7e5143,db7768be,b8cf3a8,6b2dfa33,e71396f2,e84fb6cf,d585ef6b,9a264875,b9049f2f,6fde1026) -,S(3ff59de8,191fa14c,113600c2,5700479e,7c53a0be,3827f5d6,82f7861e,88f162ac,25d5985,6ab0b6e7,beff5f60,c279a11f,8ae4efb,5e79a4df,d815cc32,2dc77ba2) -,S(81dc9c30,ed221920,98ad9475,da00f8d8,b61a18a4,e6305b58,75f75bc1,719a256f,2970745e,5c44cb27,a6f8f9c9,869a25f8,9cccf024,4d40ffc2,ca678d28,f54682a5) -,S(ba3e1e16,579c4099,1576121b,230d4f4a,ea386943,bb7a8d24,f765a3e4,9b70e9da,a1eeb808,653cfa67,8a9d8d9c,7d30e7b1,54eb0de6,55abaabd,90f82236,32c72f4e) -,S(35ffe81,50faaee1,141f52a5,1b7d1e69,fa66d194,3b96f04c,a0589c48,83f854f8,d66a1822,e83f6dd3,fcca09b8,df1105c0,b4ad3163,6070dc9,b7dd08a8,c9366fad) -,S(398ebc22,1435f972,1c214c0a,e38b9817,8b50d7e3,e5724f68,5b950aad,60763a06,c2df549d,eb2eeab,fccd4da7,fc2c8ce9,15551b87,14903011,6825b804,80811f46) -,S(2ba27f33,e7d0a75d,1d18511a,84e5ce1e,9ca89d2a,a44fda0d,6cfa1389,ca89e96,5023684b,832375c3,8f39946c,c91ca114,45c2ac54,fcc12f19,c6bb662b,997cf4a7) -,S(4257063e,7ec51f92,4ecd485,653182eb,2b54973e,f1ff0144,65cd151e,f9e829c2,47351f41,16dd0515,11c9ab35,b69abd64,919f8b5a,812ad5d7,47c5462b,55232c1c) -,S(77e737c1,b5b3ca56,94218582,d2e56519,80da8195,88ee46eb,e3ef172d,9b4063a8,f7cb5c5,e66798ad,37c8d4f1,1cb912e3,651ae45c,4d7b07b5,e0e20c2,89d1587a) -,S(dfcbb64d,71018c1f,bdef98b8,2a4cb72d,ef027d43,47b5e8c4,4a7eec7a,34cdaa4f,dfc0cdbc,c7207588,8af379e8,751c4f09,bc2f4e58,2dca9a92,e06b0c5d,97972a23) -,S(8eb686d0,a7871e8e,32ac5256,746d7189,b39855e2,2a52ce78,ce6962ad,d355ae8a,ea8b3611,fec52837,fd0afe42,4c22c5fb,89b79675,6e8a6a5e,d71e331c,6ccc30da) -,S(d17d8713,ebaf2dd5,316703ff,8c4c20fe,ee56522d,bea7a987,85a96b1d,36cc3e54,ea70b7e8,6d7862ca,9d8a7a19,bf8941d0,e9fdb872,4e46f8b5,6821d85b,ddc10b54) -,S(7d4c77e6,ae050a1c,856d28e9,c14eeeda,249c471f,82cd6cfa,3ec037e2,30b3ba89,c5a07653,f5fbdf93,4b180f39,327d102d,900ad68c,3da1a7bc,ea773fe9,6265fe60) -,S(96381109,451e5e68,6d61d51b,3b250bcc,3721dced,de39e88,f4f50c1b,4d7ebcab,9498f419,b088ca54,7f17642b,dd6f0fe6,9f06514,a7228394,7f15d165,64801b64) -,S(7400b550,54353d73,7b2da8f2,f8f4e953,85f44e83,fda3cd20,8afaf90a,978c2ba7,9933aca3,ce503677,e2129a04,cdb1d5ca,e36bed1d,275048be,6b18aae7,fd909771) -,S(3d7b0c11,fff7bfd2,71ef5963,9f12ebd8,d1de3bc3,93b51be2,a011e4ba,66ff59f,b6397431,7f7ca0e5,ce1eb57d,8a886144,8bddb12f,75469789,b791c4cf,32404b9d) -,S(4944d9ec,7ebf7f14,e6312545,5c8dd996,45d128dd,fde3743c,5cd6f4cf,65c46328,f0655193,13baaec1,329cd408,c9d1f3d3,5c2f49d9,126c9d1f,5bf271bf,2c589996) -,S(9960432b,4764b1d0,f8607d6d,8e08b355,f37b9933,69bacb51,89ce46d2,79bdecf1,304ebb4c,921d2fa,29200ea9,ec214adf,f7e1a9f8,debab865,78fac56b,7160ebd) -,S(313f535b,63585658,fc3409cc,726b5ded,9196cc59,6331681d,9ca84aa3,bb3de4d6,e511a48a,a55fe0eb,e5f23bcf,d01ff4f1,59b049ff,8c999fb3,dd64092f,c56c9716) -,S(85c4586f,8cd36dc0,db9b9006,ef4f74ec,c99478d6,5c011bcb,3ccf034c,548ed7b2,cd6953c0,45c5d6c,dc632592,3f9b0070,144c8c5a,67639f63,a75b4d10,5b434229) -,S(968bc6d2,a7fc359d,1edb668d,b7381eeb,d489b20d,b64d651d,21d706f9,94671af8,fb0ad6a3,723d707c,c1b2f330,4e59517e,de88bcfc,b52f3ce,d0bdb7c,f0725186) -,S(2325aceb,3722e77e,e6cc7221,56ec0e87,26d343cd,cff6a420,e58c563,bf28985d,601a7f53,dd295978,f2a59683,6f3e9eec,19b9c8fd,e81bba5a,21acc8ff,878d39e1) -,S(8c6e76ab,b2313bea,dc0667f9,9aaf32a6,4b1c9335,87c31dff,5407fdd,67acd2e4,27e3b850,d422df3a,c93b19c4,229b390e,3d7bb92e,340daa46,b3f5112d,1e50c29f) -,S(e31fee31,34468d3e,4d6b2c72,8d538a14,352e7a8,8b9837af,9d8d4230,5e36748f,89b096e1,2d1948f8,937974f6,b9a101e2,37f9df3e,280d4139,e419a1b2,6d0309be) -,S(596b586e,849404b4,7c742fdd,7e5a3398,da748ab0,67ae2981,215c17d4,b0d306c6,e96c5cc5,912cc711,5e4e8f05,edadf219,2ac27760,2b2ce791,ff6e18f8,62a0a16b) -,S(200cc167,5cf500cb,a199c3b7,1195270f,d453d5a3,8313f317,71452486,15aa1c02,780aacc8,7e34429c,6445c133,49240371,1905e24e,c17de4b3,e7b79cf5,5320ce61) -,S(7e4d5432,e10e1fcf,79148f8,77a4f247,70f0e96f,81331767,dfb5e9dd,2ad2025f,35f5dbb2,6ee82837,f37f5fd7,d417982d,fa58f0ca,13e3136e,ec0b5251,63aa432a) -,S(c1ed7508,95c97e6e,7a78f800,b6eb10c0,ff21f879,352870e5,776bb7bd,9c0237b7,90723a06,8dc0aa89,9c31e89f,64ffec3d,a38e8095,97209bb1,d8b1418f,eb418fb9) -,S(e5fd4ae8,a53e809f,83d239b2,a15d8dd2,9948ddae,6956d8de,fc7ce730,b2104770,6a4dda9c,1cbb2197,208e8ebd,35f2ddbb,50c7bf5,df4c112a,de02f0de,f71c4fa2) -,S(3ce75f2,4b33bd88,7ab72cdb,42f9ecef,e3534d15,f6733f2c,a766eac1,da51f30d,9eda315b,51ddf6e2,62ce9b5d,828af559,a43eb48c,d3dc9362,13bf04cb,1a838ed7) -,S(98c04c4f,33a81cd4,e498d8ce,77edf598,527fb9a8,8e19dd34,ad8cef3b,8813391c,fd2bcd67,f853f812,f4371c46,30560957,acb4843a,8ff21949,483f0617,ff8bd3a7) -,S(50e9c88,2906cb06,cbce62f8,413ce43d,f3d2dd28,6e4141b1,fc8a079,a87bbf3,43c713b,b05f19cc,685eefb2,ba04474a,479a615a,2f3c8a9c,e1c6243c,d82fa3fb) -,S(5d41ba17,458bde3b,64faa66,3f21b76c,71bf6564,2a73e3a2,eeb8a831,43adf2d1,17effc54,b3082159,2b39e22b,7ab058f,7f64fa7,68763510,87cc445f,57b6cec5) -,S(4e332cbf,2a02593b,6e83cb8e,1d92e076,6b34cc60,646fe3e7,89d38f9d,24d5b077,50fa745c,3ab90300,95b69985,99e391e1,744ad03d,decd1955,c8b2a859,e79e1f95) -,S(1bbf629d,27ee825b,c357455e,43410507,c83cd47c,dddb53f8,34716ebb,35a2dae9,850908c1,e99753f3,4f40070e,c0bd85e5,8fb72f69,601d3709,71ffa894,3de9bb75) -,S(a9149aef,f9dbd62a,ad0cb3f5,debdcb30,23aece9b,dc79db8a,a25f5b01,b5cde650,a7bb4b46,e6db111f,468a16d0,9df686d6,ae3c148c,61d99a79,918f0bf6,b4c327bd) -,S(801009ee,185d642,19de5b40,6b21dacb,b98ffcdd,75f8037f,fc5e1721,fdb72a71,e8216609,57c7ad6c,1dd36f70,645c75f1,38283905,898650f2,daf2e5af,37e26441) -,S(c070e99a,e466f67a,b234584,66f132ec,96c6b639,3900468a,b7368a86,c0ba6770,883fabdf,358d4f56,8a56f77e,3b291fff,be6f8fcf,9c0f0171,a1544905,50769362) -,S(6be89639,cf612761,78f549a9,ed0af9a1,8e028c53,1dff79da,71c5ff1f,54109f4a,777aed7d,dd379131,26a92f38,ff9970c4,ff2dd6f1,6d766e0d,8215fdb3,9604cf14) -,S(d1fd31d4,1ce71e4a,2052e79,6dbb1a87,10094505,2b9d9009,2195afc5,9624ce8c,f357abd3,78a8029d,eaa796d9,1860e5e5,36d5f2aa,ea2bda2e,5b510949,253fded1) -,S(1c85382d,66fef14b,3cde617c,a426996,614c328a,ead99033,7aed469b,8f169d9e,58c5af1c,b236e6a8,4f58702a,b727d9a5,e2406a4d,fdbf9113,a8f895ef,78a71f9) -,S(2d8fa9ed,d5fd67b7,42e5c2d5,2c128ad7,eec32cb7,43cba12e,272edfd9,4f36b5ea,71b15f39,37eb2a09,f9533af4,bc964c32,23145340,f780731f,aa9ad1d,8f2cd37d) -,S(4f512379,d9f6c596,700d0a15,950ddbde,40ceb1c6,87030c95,4c538122,dfdbafb4,54de9b05,f864df5e,ba861980,c7dd8567,4b320afb,e0381674,c7f7c083,4248c05b) -,S(9a5f91ba,48562c21,58e60949,6d43eca3,2c69995c,ed93e834,168d22c,d9e7cd1c,9f88a3ec,c668eca2,e01b1126,6acf9c51,29bfa33e,e12f7638,2d40d2a9,b722b86b) -,S(dda30502,d417fae4,c4ccc6b6,e833b75d,d84d54fe,d58fcf0,6577dd8,52f9f610,fbb88dda,2e74641e,6d45468d,102e2a42,7f4c57a,6c7fab0c,5d4dbfc1,155469a1) -,S(8d2e9e7c,5586141d,848e50cc,631ce5f4,600dfb1,618d65e8,e88da5e3,5b26e117,989c39ec,ffd67c54,d55ab4fd,85c2a556,bb72fabc,f763c9a9,e33a1ed0,251aa86) -,S(726ce076,e6b63d6c,b071cee1,c3d1da27,10c911cd,e3d59bbf,a27a7ca9,641ee995,4e41baa0,c91ff8d3,4d2d01ac,d8ab5d36,6ea5e81,d489595,1c49622e,610af9c1) -,S(debc91fe,183503d3,fbac0dc2,c9e95062,c0d42971,ed2e97aa,27dbacd9,bea43a1a,13593715,a6fece9a,f33b2ab8,d5f26e6,6dfdf3c8,ff688100,d497a333,be2d2f11) -,S(c5394335,77914ab8,e7039e8c,472ff2d7,237c794e,d6b24f41,c585e910,f0fd4b28,2805359b,628a9c4e,7b304112,80aa2a0d,23c26cf6,9a47310d,1fc6fc54,cd26087b) -,S(9a2892fd,33c300b1,802bf1fb,e8a8faec,72b81810,4bee4e1c,c998bc79,a05f29b0,997f123b,c2fa0136,522ebc53,a5ce37cc,5538705d,f5fa8beb,b37f72ff,45186e33) -,S(d4a22cac,f224fbe,7ed7fe42,7e0bf180,1503bbbf,d73de79f,4c558104,b39a351a,8268fe97,30622e09,2a513349,548e346a,23260311,a82e860,341af6b8,3ace752b) -,S(4a4cf3ff,15adbe1d,8d414963,b0709fb9,11d4d2bb,877dc03c,77594fb,9cc11659,57c84583,36f1952a,62441810,ea64ad3,5109a30b,c39ff36f,c2dedd60,d1ced874) -,S(58c0eced,b580d530,98c836cf,42ca2648,e85e0b27,871caf44,1f69bf0c,158e1539,eaf79c49,1e1dbc94,4e63d36f,702cd1aa,92e54a09,fa11ffd7,4121783e,e842467e) -,S(b0fbd0e8,a60c7e89,38a154f3,fe586a33,26132302,7f4e416f,634cc9bf,724892bb,27ba767d,6757f40d,b54fcb50,104998ba,6dd83f93,137c3d07,9a0330c7,82a5d3c3) -,S(a94ae12a,26b0135a,125fecf3,e4ef1844,ee90c2f7,84cb4081,8c16d8c2,d992f0d3,a37447ba,665e7595,c7816a6f,6bba3d66,e046fe36,8877c95,bbc8a760,218e2050) -,S(8cbdb09b,3eb74fae,32b6c484,4f9004dc,c540e240,7305aeeb,9adbe308,8cdcbeb5,2b863a2,91f6efd2,ff07b14c,4e5a169,912df745,1b49e3b8,10e72cf4,34c932fe) -,S(3f8cfac3,b70eebe1,cc6fb89e,d508abd6,ab3131c,40d37afc,f8f39c87,34cdbac8,dbb02111,846ef25d,794b303d,b48964b5,a68b5287,b443d321,f0c493a1,2d58b65e) -,S(b61604e0,cea3e79c,12fe9a4e,1816630b,31fcaf4d,b3ac84b9,547da60,df15b25b,1aaf2bad,9ea0fa5b,56665b41,ba1264a4,317d5388,9018d92c,ea2e9d98,29b86801) -,S(eb0e7410,3c6ab38e,1c26630a,7fbd68b6,fa51bda3,64d1ca3f,7c86ef0,451327d7,dfa05017,57c4d3c1,9541c9c7,d9fb7438,45cdaacc,2ee377d4,4c36817a,e0e82e6d) -,S(636fc503,be51e64c,8dad2812,6762c04b,1fcfdd7e,4b25544f,4bcd0bf6,9556b7ae,57b83b0f,5104149,7f3b6735,a8b7d886,b633c8dd,5052d1e6,9848703a,313f4cd9) -,S(2fcc70ec,4d42235b,c6afc2bd,1d2de19c,5ba9dc65,4ea3e288,c15c7358,e52ab330,6a356018,2bfa1e22,db64cbbf,cfcdb695,35bde8e8,2519d069,39577e65,256a30ce) -,S(115006c3,8d38b8bf,db8969eb,d6bdfa95,83be81e5,bd5bc7d0,1cd10e22,7ea94b54,6043ad02,16eb3fba,9af39e83,f6e87802,3fac023a,73252780,2505a1d4,2080e08a) -,S(17d565a,15ba1c29,60ca2da8,2fe54d01,3756a986,bedc19a5,15b653f2,8db3aaf1,917bb9dd,42040b3e,4b8b05aa,b9d31252,7a633819,33534c35,f274ad7a,9bc7399c) -,S(dcc2489,88501c43,b8598f7,a3e5bca9,d2af8f8a,b482f30e,2374c6d,6b221ef2,a859757d,d5c6ec52,b1f102a6,ef00decd,cd14cab5,99f1eb0a,57864646,4f652e72) -,S(a68b2b9f,4e9430b7,cdd919db,6e808a7f,ae2cf9c3,d43cba03,d833fa8f,351f0b0f,e34b8a32,d3ad0923,8e95614d,92778021,7f45b14d,f2f9cf66,d6525bc5,94786526) -,S(2f954e5a,938e1198,5d2d11e9,ead59539,fe7e2f17,4702d3c2,3190829f,8d0e9462,b2f0d379,fa8b7d40,ba2fecc8,46a393b1,f6aaa6bf,9f89ac61,e55ab1e7,bb16dd5) -,S(223d3d13,6bca94fd,9b3fcae8,6bb2ddeb,3cc33c8d,3ccff556,fa93938c,c27ffe4f,87e19106,e317187c,c256f7dd,83d6219b,27f6cd8a,53bb4ec0,9c74ca58,51512915) -,S(5591d8e8,291161b6,43df3a3e,9b4f495c,b614432b,a0f3aabf,517834ad,9e8f7b2e,2c8d6a35,f6267e52,d9bd454e,bba4719d,30b3fe7e,c40a1416,673ef594,e6d07c2) -,S(eb2cfc4a,d15d1a14,870cbaec,b9e9aefb,4141841e,2e4e6252,c8e93751,45f29a29,78810e08,10bfd992,b7b04c79,c7650150,e62f210d,6d35cb95,5bc67215,7052e5ac) -,S(6112c3f9,9680a818,5e4b1d4c,539cc436,bdcdb47d,2e19f927,d5e3e9,eca3f74b,6e860bdd,723c8bfa,dac8f9d4,1f6ca96,f2579d7c,6a690f35,3b8da52b,98da4403) -,S(892120d8,d552d8b0,c42c23b,9a0f17c3,b9b32914,d7e31579,7b391ded,a7d58b16,e62523ac,b3c778f2,f913d1f6,4bdcc037,cc4a9496,ccf0cedf,32502316,b5cf7941) -,S(4758b456,217ad3be,2315583,963044a5,60ca4a49,168461c5,ecbd1e91,1fc4dc0a,99e4255a,4f30973f,57eec6a,1c30ac1b,bb74987b,3c4e7ca,9604878c,d9d83679) -,S(ab0422a6,9a207a87,97fa0c6f,978479af,a3b95dc7,d962e143,b99e7575,6e5629da,73398d0f,fc9855,ebc280c3,2b8dfced,84af0f70,4994edfa,7a06e2e3,a5823faa) -,S(1980432a,ccb90b14,30d0b4c3,5829374d,852cc7a6,f0a1b20,ee7ad43e,d545d227,96ae3873,bfbc8ceb,2afd1a0e,9b989bd0,69c919f8,f2e51546,7668da5b,9e8b05c5) -,S(4288137f,e2dffb3a,ca761cd7,2abbef3e,93b8a015,743d50cb,b716252e,e0e93f17,c02c333e,36c366a6,fbd855f1,4da07672,71fddb04,59e788de,456086dd,aa238825) -,S(d65fac35,5bc89da,afc4d16,aa73fa4,77e43276,e0db7d3d,52d9281a,d6b6cde2,e6f4c975,a6c5f337,b4500545,603862d3,8e9f07e4,18886b13,5678478,c007383f) -,S(7029b144,e62dd27a,4fe8b54e,1607936e,beb96784,d1b294c8,43e19978,b98f6ca7,8b10ed66,58056c6e,3a2c90c3,855444f0,9a1af347,c73dd14a,a478f2a6,7140a25c) -,S(4f2760eb,df969bdd,e80ea87d,a5da0c19,fa343e4e,44715711,50295b43,cf9183b2,43e2c17b,f3f9ef09,fa01fd39,b8f69b69,15d8625d,4daff425,d4629677,83e28167) -,S(cc996aad,db4196a8,f355f0d2,3b9fa539,b573ce57,f2ee7e52,14372615,c374a5fc,b1c40f87,18782935,c30a9cb6,6be85d11,44284bad,bfff9923,2c09f2dc,a8ef28d) -,S(c7818ad3,f3e3d905,b2c38e39,85eb7091,cd9b3285,3bdac631,3cf4303c,d54ade42,55574c4e,7bbb850b,14763fb0,fc1443cf,3403a5fd,d1f5f937,8007fbaf,94339eee) -,S(6cd03584,6fc48ebf,f4344d1f,3ae5d258,9a45dbc9,e779445e,52a75737,2589c4fd,afa85b7d,b165e371,adf67dda,8e4d1fa9,4d811c92,8d2d4723,a44e8cc8,93416e34) -,S(d652a205,f716b1ae,632b7235,91152314,f5231b92,474dcfd3,bfaebbad,443b2e0a,d2198421,b78240f7,cb82f0d8,5de03d8b,c4646a23,ec166dcb,a458a06e,b93bedcf) -,S(a807d04d,cd844a1d,f99b3e4f,e3400459,81ff0baf,d34e2d73,a6a052f8,dc52fb54,188a78bb,73939835,3bbe5079,ffbbc718,c385c047,97cfb151,af019e9f,a2e2cd9a) -,S(1efd2bbc,a5d6ad48,e93acd07,d6cb02b9,b8c3a95e,9f4cede2,24efdc17,cc9eb2d7,f951ef88,1b98c7e6,357e191a,1bb357f6,2a9d2ae,a8af1a05,63eef3,66745b39) -,S(5bc5e54,d27d3db5,982bcd04,497fe0e3,ea0ff13,7c3bdf66,6ed0b9ac,2395888f,3555bc02,d4f4eb01,661f8b85,7321b36a,5a22d975,2710375,4c1f65f2,82ec3300) -,S(f600a8d,26b08d0d,e6e2ea80,e8ad2f1e,158cca71,15be6f22,1f5b808f,746a3247,23be5a13,4bc3fa5b,7ef75b2,8e8e11ba,76c753dc,6516caa3,cd5b3ab1,8bca3523) -,S(fc7e4e0b,2ab2a7a8,cc5712a8,be590135,f5119bc3,6c73f81a,e492bd26,90ccaf7b,4bd612f4,1f274690,6ea862b8,a6dd8929,e4a682b5,aa835cdd,b31c90ab,381151a6) -,S(51325f3c,fe12d00b,fac67eec,d79b63e5,41641d58,76aa9700,bcd3b3b5,89442655,d6a894ad,7b7ae6e2,db962360,579657ff,982a35e5,91cc3b33,a4437a4b,133ef941) -,S(2db3ac27,1a55f608,f21bd2d5,717f003a,afee9a6d,b8fefa09,5626e4a,c598aec8,c526bf33,a0c01c60,c1cc9fc9,d66609f5,3c662168,b47cfdd6,e0de0c88,9bf9533e) -,S(9080772,93deb01b,5eb05b55,47de4321,35fbd436,3f391be5,1e1d205d,d5fa7dcc,fe961eac,17243337,653d318,b5c62159,64dfef84,d3cc3f23,e034c102,5ed7442d) -,S(32a1ad81,e5a64fc8,2dacc03f,6790cd4f,45557ad,3d3597cc,e2ec37bc,339ed9d6,87abcf68,18010022,7097b63c,a795cec6,79cb55d8,a9076cf3,d1371062,627cb07a) -,S(f7cba8fa,58689c51,a0f1af76,971d17a9,8c5849d,55b396e9,a3771d17,4d9246f9,f4b0aba9,10d5a9ca,eda4d733,35d5fba2,5309a0c2,fc83072c,ac37b9ec,af58ee45) -,S(cda6b104,2da900d9,d65b6b7b,c0579a43,fab75f55,ae7046d5,8ee8af82,6329ea81,70c86c0e,acfd7401,5a1171a0,1e3601e1,a8ee20e2,9ac7c0fc,68d6f1d,cd1771e3) -,S(a261a640,9c5b1ce,9a8f27b0,544ca0bd,a46f3bca,d11b7f2a,c23878f0,f67ee58b,1e26a71d,4c42dae9,b4e9cda8,fd33d725,85da67c3,52594d4,20c6e410,f3fff888) -,S(bc70c967,fd7f842c,c018e885,d1fb6d34,9435aa3c,682f6884,6b394ba6,e9f4db57,a2b99d3a,837e2de0,c40a0784,7865701,3032efc4,87c47e57,18d84e11,f8bd9468) -,S(364152f7,5dc43149,4cbfdba3,ffaf234a,c7a26567,1051e026,9c60389a,7077a9c2,ac3ac7d9,f4ec8543,3038ae4e,7ede71d5,3c8fa601,25bcd8ea,e084c32a,546d265) -,S(52fea4be,d57d5d58,d92f59d8,e4022df9,d82ca42f,a3d89326,cc36dd96,94f3043d,b7e98328,52f98a75,f738f9a3,7a67b39c,5708c608,5b6ab99b,2495428d,8c4feb35) -,S(34fee910,c8bac880,f973a096,a9ac3ffb,9c32ecc3,d2be3ce6,7b8d6822,863e1a4d,e0f01096,9c9dc446,c78db14b,122e260c,2231f6a0,971d08b2,24355620,689c7a17) -,S(6af28f0b,f4c9d2e8,192424ec,31f076f7,f815ab0,f476a4bb,4019b3bd,db49c65b,2c55fd2f,bb663b31,1a9aa346,917f6064,17d1e1dd,bca45d3,f1350feb,6ea45248) -,S(70b6ab66,39e4b41e,644f1b6b,6ac5d36f,a4f0ad81,3baec03b,8bc74f72,4d320e46,ec6409e6,4f4e4fcc,d19ad5f1,96d3cdd,96f7135d,dfcdec95,23780c18,8a913a14) -,S(ede56f11,4ab975ae,adbeff50,ff7dbbe3,614196a,138600bc,15508481,a065724d,9e7fae4c,11f421ed,26d839dc,61b0684b,71906b63,6efdd73c,2dadfc9,5336ecfc) -,S(83c34c3c,840a7310,3d819d74,66648e66,5de54af9,f1683efe,6857c3e4,556df8a4,9c238041,562dd6c0,eecd9771,9ce2eed2,90aa8137,f109840f,d31d70a4,c86cd10) -,S(aa2afc90,89b98,5228cf03,205e87a4,52cbdb45,24d377c6,1020593d,a0c7e200,3443196a,b382ac19,d3d3bc4f,a3161e00,6d812924,fe8a86af,2db5cc27,96be01f4) -,S(e42ec7dc,4310cc8b,9f2956a0,2fbf71fb,e90eb045,881ee800,e3a75730,4155c520,939ef2cf,a52d91cf,e20324bb,e8da54d9,2d000945,58abe7b6,93c2679c,d625336c) -,S(bc0bdd24,937c5200,fd78de47,a16ef9f4,181617ab,267fddd3,4a3c5606,32ec2b21,db04a4c,10b521f7,986e0e1d,192b0870,4a028511,205d7ac9,df6d2993,52b63035) -,S(dc88c9d8,9b43a733,5e310fbb,3f760e29,55c005d5,640df990,6264ebae,adadc8e7,2d6779e4,6f984794,65bfc677,79feb7b7,3fe37b32,cc23d636,25a3c8d4,fc2fc512) -,S(a7ae0d8a,b0c932c6,2ff0cb02,e05d76ef,5ee3dc50,88c57210,f6f9e349,80111c20,d632abc9,d63162c8,98b9dc94,b321de53,ac8dcc45,69233cdd,1d07da1,92e553a2) -,S(4620236e,e7bd6eab,db203af7,57da6e64,d631ac9b,a5f03215,592a5acc,5cbe0e97,5df4244f,69ea1e2a,6cf30cdf,4fae66a2,707851bc,7028d8c8,8fa97690,28627c6e) -,S(804cb84a,3d8bd930,51f50aca,cf932301,5cd35fff,349d8a38,e2bd991f,27d8f671,4b77b812,9ee0f835,96ab2f19,20362128,cdc39552,bbe6d267,bbc9a8e4,70ae8d3f) -,S(6ea5370f,5382b2f2,b801fcbe,ea463912,b4f6fb4d,e207237,8e71dbbd,b91c2ed2,f5b4f909,d8f3ff08,e92a002,f1959ec8,8b513ee2,d37825b1,a8bbe141,90b2d88d) -,S(d8b8de1c,4ff575a6,12bb0852,af61c6b3,1ee56403,b81a1f47,69fc7072,a2e22ba6,1e3c4190,d37abf89,896ad827,55c256e5,f23cbdcb,47b05892,8d538df4,e2468c0e) -,S(66ac1864,4a0bd6e,9c73f3ea,43a00d6c,80d38467,5080a9e,475c8291,edf1b147,2cc60c0f,7db6b776,1503efd,551e1a36,9be98ec6,73dab0bc,a61881cc,4fa1260e) -,S(47194a2c,4ed223e7,7663cf9,38b5a5ca,f2784435,c375d85b,ef3c5367,3f60e942,b0fde11b,5a64dc13,7bf2738c,75027d57,5808a3ce,abdf7604,5f4484c0,d3d9f920) -,S(1141c859,9af2d983,88274742,88dd768c,9fdc1b2a,c5f06290,10bd3cf4,2a4c6186,7a431f47,61ed4613,3317555a,578d0f8,5392a0d2,ba98ec64,d6b508d3,eef0226e) -,S(f905bdd8,e80afe9e,d65da689,bfb8e549,487002d6,16ac651d,4ba300c3,e7496f79,1ec7bf7f,3bfb5045,d461b03b,a7f05067,cd999fc5,f9f4c0fc,a7e25b19,77bfcf72) -,S(ba54b8e4,fba452ee,23c4faad,b14f0af8,232ea62f,ad47a3e5,573f1fac,f15e9e0,af556ae9,efcabbcd,bbd8e48a,82ac80f3,9c96ed0b,11370b8,da1bd4a0,60f5cda8) -,S(59d3ead0,561f6e24,30e87f3c,f361a2b4,1494a042,3a775e9,c08a28b4,a26a80a,9b26f47d,50a92229,c28a278d,427c7306,f5f1ba1c,c2d095d9,ac51e18f,a9bc8) -,S(2a6e5a3f,ab4cc928,d8f2924b,e7e0f3cf,15520a08,eff00f5b,129d9070,ac865d47,55c0350,58727023,86d19196,4609351c,919913de,e93800cb,38b77183,5ca625a5) -,S(898f50d1,c35bee41,88afe91,842cf659,fff1fb1c,5aaebd84,6828b002,a8907502,b2456e80,c97c2ad0,1ae02e49,6b84c02,fc9bd0f1,4a3c5a79,dafb8f8f,62f3267b) -,S(d1854ab8,b49bf0cb,1f9d2304,e9ee3cd3,bda5d9a3,ac04fbf9,422c4671,d6af85a,4e2500f,d8818180,5b16a077,53eddf34,d7bdeb02,17df7fab,d0afebe9,47155c20) -,S(861fb88a,394db6e1,f03cc787,d968ef7e,4a417df4,2856d303,a3edfc66,feaf4680,a5d7e95a,ab8b0b13,23fff11b,638ce02,68f3c38b,dbc018dd,dc6d2362,a135da6) -,S(9544f768,b9fa9dfc,3c155d90,b676cf7b,ea526903,39fc111c,b0ccf62d,813403d6,cec4d92f,cbde624f,851ed21,bbf5154b,28d87603,5e302902,53e99670,806e047f) -,S(f7722192,f80a66be,23cd7b07,89f3a094,311cd40d,3b7149ba,2cb5cca8,d1db68e9,41d0e9f,3243d64e,73e26661,cc851e5,1c11e320,277f7462,d40efe0f,c81b516e) -,S(876b4c65,1f88729b,dbf9927a,89ea91e5,b6bd8e7c,439f6fc1,be9e07ad,698e14ed,ece2cf81,1cfae9dd,cf787b88,f62f2537,7b573084,86ab84e1,6ad31ddc,f96b49da) -,S(706af4e4,62249924,88461427,8917899c,721be8f6,3353b127,b7ecb03c,7b70b10,c972d972,c65d200,e695bd29,813deb74,cdcf0ee0,e612f545,aa6506e9,7e58a5f3) -,S(ce97a218,c9c96262,b5cdde0b,a27e5f4a,4301b75b,f9d17dde,f1495b7d,f3863c9d,e9398e1a,20fd1426,88916410,d7af68f1,c12900b2,72b03f55,c5770aca,2a1ef10) -,S(fb625b9a,92cf831e,886a1f01,c2db3d53,7dae0feb,e9b3d9bc,a8fe6449,d53be895,7f783e74,ba569e04,a29d68f,12cbf223,1fe2a8c2,a651f44c,30d597de,82599a37) -,S(81ffbf69,7a7d2b8b,51b9098a,8833244a,f126c6f3,b42ddbc4,c6b2c5a5,55f4747d,e2c67357,982eefb7,3213d530,3cdaaa7d,90b4d1de,d0fd4d0a,8b002162,f006f33b) -,S(6dfc0f66,8c30ab7c,af16d4d6,309ca2ec,679d6b77,be695ba8,c0f31b55,6a0ed0e4,a41ed2b2,d9a0aa74,3182d7a6,20f441e9,36772438,bfddfd90,5aeff87d,b15a563c) -,S(1c6bf1d1,b953e56a,ba1a9b5b,f63c328,1d5715df,88bcc23f,e77f94c3,3b501b44,c667214d,b4ca1782,19c368b,f7c2ba4a,8f1e74df,91a22d3a,8e336089,e4e4b0ef) -,S(b69112df,5d999f60,5d863231,9144d2f3,5417b9f0,d1e78ba6,b2afd247,fadef93d,2163cf7a,302886e7,70fafeb,8acaddec,464f115c,89422020,9a034c63,558df4ae) -,S(bc038732,ac230f91,7c58b8fc,f9ef9229,9737a2cd,8e01687c,da464bde,4976b6e0,3392601,796373,603e1d6f,a7e23385,7a7ae0d9,df638ab3,7191c046,a25682d2) -,S(96df3295,1047ad4c,6aa4d9ae,e59bb00c,7489c20c,aded01ae,1833ebda,27e32d81,418f6c2d,74ce633c,181189bb,f5d0f066,cbfaa8f1,e6674466,1818c4ef,e2e2034b) -,S(a3c53227,939e40ab,ec6fcefd,eb6193c1,cb6a65fa,2f3501d2,63cd2fa7,6a304979,4468caa5,498ea6f1,92f29ade,37a2f667,f46798,dc600de8,cafa0ed6,dbc967e4) -,S(93fd8207,3dfd6d6d,6b85f1b3,1e172a61,7a0c7d46,b91d5a92,601af0ad,2545eb2b,601beac1,9a8a6a41,1bfca863,6acfebb3,9611559b,20b8a866,88397d47,d563a847) -,S(ba7d3bef,2e2c63f1,f9acef,2468ad8d,a5bc0d9e,b45e4a2b,ee87a0ba,86ca0a9b,ffff9a67,33129e31,10d33ed0,bc5b6bd9,376f29b1,7bbf2e09,7c6efcae,a55114dc) -,S(e0d955c0,2a4f9c35,97597258,2964d7a4,218898fa,97ef3011,1904290e,36157a8,176fdf9e,7d420bb9,a0782f0f,8707789,b28cbc69,d5a6797b,aa2bb985,1c617f0) -,S(16b2c140,8320cb93,112da689,c690d6ab,6cd226fd,e1752dcd,a444750,bff81ac9,2a2face3,dafd3932,f2617488,faa17b6e,5025f792,53c65edd,2abc7790,d98bb281) -,S(2fbb0432,9c823e2f,645d61d9,795a414e,220db4b8,eb4da0c7,fc22bc10,e9f502da,1adf66ef,15eaddfb,abbcda69,c87068ab,cbfe58e,69f58246,a0ab6259,90ebc31d) -,S(649134da,f42d2579,b6522f2f,404d6456,c178f883,8c9ddccc,e132de4e,67208ebf,4385abfc,3c554bc2,78844648,a9aea5a,e7709b51,fe644e8a,4a756c3b,f09355cb) -,S(b95544b1,dcb81f9c,e0601c17,29c7fdef,128d62b0,b8993023,dbcedf8b,d3991cd,f871fadc,ffbade32,d51f2d45,4f0726f,206fe760,93c0ab0f,33cc5383,769dcd2a) -,S(cd403bfc,5034d0c0,a23df5b4,a4b1b096,ace1ea17,288f89f,d063c0ca,5dd668de,c1296131,aa56f46f,49f59760,f3a4bf0e,3fa92e54,a5d8f160,54ee1fd4,26717742) -,S(a4aaf37,d7f8bdc9,90202074,c9a8f56a,1ad78479,95b4d939,4b6ea478,3c04c581,4cb3b6f2,dc02b61c,fd2594f9,40773d73,1a8cb9cb,388af431,9348d3,af16da34) -,S(57102ff8,ebdf048e,85edd3c5,2864578e,97478fc7,e6e7b937,6c37d9f8,abf438c4,c84f1d9b,eaec1962,e79e308c,251b2f31,915aef16,90ab5128,8331d8ee,f8161d4f) -,S(68fe98e9,3c5c5fe1,108c08c5,8fafc701,12424685,c6809774,832b0623,a3c9b6ac,492ac417,fd956b87,ee8078e2,c46f21e3,cb5ea58f,ee871cd4,d6480cf9,c4df273) -,S(d4bbb6,9ef5e23a,f0932cef,2eea4ab,d97baea2,b0893d43,ec08be40,2a4a5e77,5818e60,9c1dae31,f65e223d,f0cd08c5,9e74884c,2a2dc166,607fa4b0,47c7c98c) -,S(e9627957,a8eb8b72,7f0d872f,28acc53d,23a5c53f,763f3b5d,68c7e690,5a83192a,5da92e7d,dc291696,d9466d17,d4ca6cca,cab1057,4f5a08d6,6e59ba87,cd0d984f) -,S(49f21cad,a83bf2eb,7c508ffb,70f9fe84,1cd547f2,df83f207,6dd2382f,1711caf5,1c7d8129,5f834ed8,ac73afc2,132e6eff,2447611a,4fed8114,ca18925f,39f31931) -,S(58282a9,40f61d53,14d1d110,c18713d4,6c34a8cc,5b0ff64d,fd6d0182,aefa792e,7855e155,d3e0f2d6,52370145,7d83d7dd,2a96ee49,3eac091e,677f0a34,105f6ddd) -,S(c9c97a32,4b07027a,7b5db6f1,d70bec7d,dc3a14e7,43d492e5,f5569199,23ca118d,f601f40f,894ddfe1,c2b1e99f,7c2032b9,15d600d9,e2ec41e8,747d74c6,9664b56d) -,S(9e4dc175,8ed67501,86a7bcdd,a11f9273,9bbbe0cc,aa72862b,8d515a21,159e054e,ca11c31f,2bb866a6,be0736aa,19b7e36f,fcf4f4c8,715ebd3b,c9483813,cfc6c0ab) -,S(fd063789,3ae0030b,cd8c1e5e,8cdfbdda,8e5af1f6,268f552f,7a7f0c6b,8aafe2b5,8c09eb0b,68d744a,20468a8e,4326dc01,f4a35480,df1a0435,b2e21d53,dc8e676) -,S(37dfdf3b,6e7a7651,9ba81c3e,c1377580,d85360b5,b466ec77,b3f2b272,fd4af04e,cc3137b2,7b732758,d78f3b07,80129e77,43dcd85,ec941727,ea3b4f8e,d0fb7844) -,S(45ef106a,c8a5e25c,771a2f18,bd2be0c9,a69cb49,de16d8ff,e72a45d4,6c1dbae0,cad6a40d,742e7db7,3f7bd452,e0163490,60e5681b,31918bf4,2ad8b698,220ab158) -,S(258c52f9,88b9ca25,73cde71,472bf58,99648cdb,c1052d14,be02469c,11fdfca4,4491d88b,26ea5c7c,6a66c9e2,1a5b61fd,d60d0b8,8394cffc,359af9ec,29939dfd) -,S(bc92a4a7,727c4e36,3d0cddb9,d36f1d9,d4f8ff67,de881c83,afd51193,a9e65217,76ff6a08,b18b4795,61f1c024,d464e9c0,331c22b4,ba3779d7,9dd13122,63aa5120) -,S(8a19e8c2,58c04834,f11ceccb,c156bbe,23e4e837,fb5ff353,249c12d1,45f27ebd,15fc6c70,bff48ea2,c56caca,2b978fe1,8f50a9cb,85c19f06,5d65e507,e4e92c1a) -,S(e59b82d1,ab90344d,b113c1a7,a39968bf,e6f3b1a8,c2a44572,d9c911ea,55d70eea,91e33d8c,d58c6a1b,e4df0bc0,12eaa76f,6634d699,814b80,cc22afc8,313b91be) -,S(f994ee5f,88244cd6,bc417db7,2f941bea,f3456d2,5dacbeb3,330031b0,7371a7d0,9026f86a,ecc299b3,302bf9c0,4dae48f7,d9c2689f,42707d40,51440a05,ad9c62e2) -,S(776c4c8c,32d1fa50,27b17bc7,9803d121,8000cccd,565d95ff,c1e3a693,7800410f,40ece234,438e7738,6f8201d5,3d3e319,988b64a6,38413803,165f0bad,c8785149) -,S(393675a5,dd13b001,29caea3d,8bf25730,32c1968a,c5e02620,fb83fae5,b5c9b12e,39e6cfc4,793400ce,ed16ff4c,4b0ebcc3,2e5dc773,4e742dc0,3784a69f,a75a8b00) -,S(d7cdd294,22edc7b6,2cdde130,e90be1fc,94dcfdf2,7bf38eaa,2f09fa8c,c3401b1e,dcb9cb28,73cd18b,b74ca141,dc79eb46,728bdd9,8bf14302,db5c7065,354fb184) -,S(bce3f127,2726449e,3f620671,824949d1,9026137a,9885a1b9,9cb67dcf,6e56bc2c,a4240017,ee92dda4,be968f04,ad125ad,1c33c37d,c52a497d,296d5786,e6e76217) -,S(9df098cd,efe9414a,79adaf44,21e35faf,70080137,74399eb9,738dee97,ff5d6e52,6bf9235f,ef36943c,d0f17bb8,6917d97,f04bf4b4,dbef1baf,3b788eba,51abf15d) -,S(9958582e,e561dc4a,9a4839a8,292713a0,5d88ab4,72222522,e8dcc94d,b3d43f1d,e0958a14,b63af23e,86f76cba,2259b37a,850008b3,43b5cdc7,8cb4e88d,68c226a) -,S(3e7fb8ce,7d7b279e,7d292447,c88c048b,dda93379,5233a871,bad933c4,6dfb1f24,4279d08,34108239,2d77a5dd,906ba4be,e36352aa,9385f09d,2296ecad,648806e5) -,S(1cd05450,f7405a11,cec93ee,7826cf58,97611d69,fcb681c7,1ac0a6a3,75e8ed62,85bbc70,bb52b040,d620a3a0,20b9536e,5759d35c,9931936b,39a203b,af34d0f0) -,S(5047776,32145a3d,f6f87bd0,1b81032f,93cf99ca,fb4c5e3,c76adbf7,d7c9b367,7badf59,919c7771,89eb97ce,6c71f418,a0e67b23,884cbf7a,1ed60804,57d1d2c3) -,S(1ea912c9,49b64ba8,309b8d87,ad1498a4,79fd302b,f7f2f0be,636f7a0e,4470e6ea,9b279fdd,b1211de,8414896d,3502ae8d,4acd50e6,cf83ab4d,29086d0,42b7650) -,S(9b3fa0d3,4b00076b,cb4e0b00,95f03c4b,e1ed329b,d2f4c7ac,8c03028f,21a01628,10117a48,b2a58ef5,2e0d5dcb,cec661f,8cef81d5,50efdf41,26e9527c,27d420de) -,S(65fef7b8,1d39dc4,b3ac7f7f,5bad14c3,6200d128,d0257e22,ff678fc0,824c94eb,3021e1ee,680c4fc2,77373b9b,36ef276e,f2dcd6ec,7a02b2fe,3259af09,2708b475) -,S(3e77b23d,af763a55,644c0f2,bc2bef5b,6ef5e1bb,8fdedd46,c5a2917f,7f85f9ac,55b278e9,5bb07879,9c7f0766,a2db2c79,8d4fc785,10fd021b,415b3e4c,2a4f3221) -,S(2ac4dabf,2fec922b,c4615fba,1cd7d352,f69fbf8a,3232f783,96f8c08b,21de2965,2c33c017,76238bcf,2be6018,7f85a518,6d649425,1eff089f,a92f3eac,219f957f) -,S(febc8a20,67da04d0,855feac7,42b2cebb,748be0f1,97e31558,68d54285,4d62c66e,aee39287,3d45e63f,f9a9d583,e105a771,e3db346d,a262bbd1,a554a8d2,65d96083) -,S(a41174b4,a5982751,88c2d10b,d5c5401a,2654202,dc4e38d3,e1c8f689,8606a569,bc6b63b9,9fb5f85e,c6965337,e82b651d,6b589f2f,8d90f67e,3bd087e9,1f732a00) -,S(122196cf,5d10a3af,3bb97fc6,d12f749a,907c194d,3caf2ae9,3a3a464e,5a5de220,ccf46742,b3c1e213,544e2c7c,59423fdd,674697c5,d405b2b9,46fc6e92,9304e533) -,S(77bad5cb,104dcc7,e1bbfaa0,8c867761,9f93ec61,e8e3b73e,799b663c,2e1eadb3,889747b,ad8bdebf,48e1214d,df2522ed,4023fd8c,5ef08fea,411e8609,c6faa3cc) -,S(1e8d4075,8c49ad41,6ad45163,73327e6e,4e3f6c89,695e15d2,f5517ebb,12d4a98b,1d16ccb0,730a619,c9b379a2,ecbc4f83,98d94aa0,d4881cd1,25968160,e3b09f4) -,S(c87a656b,240241dd,487f4974,afb5b535,880ff2ac,f4a028cf,b1869fa5,fbb6ee42,16f25f3a,6fac9538,5ed74412,fa6a790d,34f694a8,b4c99cb7,6ddaff70,be757beb) -,S(96b01407,482c6e88,e9769944,cce16a05,669adf16,e7393b80,71fbd9c2,4b55a4eb,b32be280,590384f0,e08d68de,38688018,82b786e2,1b178ca4,578bfffb,94b50223) -,S(120f68b3,739562e6,81e72fb7,46d08f54,b2afd162,22e1deff,7ebbf884,6dae4af5,7c1eb74f,2b2376f9,477c6729,bd90e14d,2f4da9d,615c8743,dedc1690,300bcc78) -,S(e64871ec,2789b455,8608be2c,f248fee8,49a4411d,285c0989,b65c5dc4,e6acd157,2980b2d1,4999b0b5,5b79ecfd,45ef91fe,f3dbfae5,d02f2145,84376294,58e10a6b) -,S(608b1009,b20d3e2c,25324adf,c73e5c86,43daa1e2,53a8d266,eb43863,aa6798ad,826e5a03,ad5c9638,51181c68,ccf0e663,a021e13c,43efc38b,3b4fe2c8,8d0e13df) -,S(8c978155,8132e45f,60a61435,36f4c1a8,cdc4dc2b,6850b3e5,7c65f841,a1bb152a,ca3b3098,394d81ef,a9083c5,3864f194,1875d63d,9c31b44b,a6ed4137,db7460fc) -,S(353591a,c73b2482,f8d8e731,ce01106f,10072757,68210627,f80c8f8d,9821bf3e,2b7e3d1a,501ab469,ac6306db,2608eab,70ae8981,9f44bdf9,d4f84c7b,41eb6412) -,S(eb2dfd88,ec357372,ece70a67,178fce32,3c387b7d,a9fda978,b05dc430,9cd78857,6f2bb6ed,1f5a5521,c441a8cf,9852372e,3dd7aa7f,ca0a1f63,18c47ef1,a24b88e4) -,S(a41c0ff6,5db1050e,6998f3b0,7eef66dc,abd72ae9,8672c487,b29ff732,992eb279,56fa7b20,5616ff9d,f619d7f8,65210727,bc0786eb,2aacc244,ba951eee,99a99cd4) -,S(8e748b35,f5bb1500,ca45917e,859df11,615d85ad,861bcea9,41524e57,a2217e92,55413362,e226c6a7,84bf8604,3973bc50,825515a3,96cfe66c,9ef75e3e,fca46df8) -,S(a83f6007,cce70624,73cde2c7,b7ec7bfe,bc506c27,ccce7708,f35d535c,26dd17e5,ad48ed2d,af217e5c,63397a37,9d50d615,5a1ac614,887a2cbb,26c3b74c,626af268) -,S(f9ed7a92,7e451624,9380246e,bfd397de,5cf208dd,b47573ab,f118afed,1282d2fa,c1574616,3a6f30f7,80d5d53c,670d380f,3c84407,b4be5324,87bbb5d,c8237b70) -,S(a2bde78a,175ec7a6,7f917707,8f09f812,c7dff012,46c5255a,f0112672,6c2ea08e,7125698f,e82d4c0b,6d7d2741,9dc503f9,3b5dd62a,a5db9e20,b091323d,c9ca12ec) -,S(ca8c05c7,9dcb6736,905cc0e9,b8e1690b,6b37da42,e1875a56,e62ea231,bf9899b2,504c51ca,1e19adba,66560c1e,3fba9caa,2751259d,71389996,41d0f19f,1487534c) -,S(fc106ee,61db13ac,4137ecdd,15018278,61fd4b21,c979f97c,617b019,54eca02b,6da55a28,4fc26638,2afce9c2,cdc5a2c2,971f2cd7,5c92f08e,6bc99651,7bbef3ee) -,S(2cb21839,f47b1068,5419a321,7ac7846f,504f674b,c2f8f90b,8b9b6a71,6492a8ab,1feb332,ae75044a,f6807feb,965e2fc8,63726433,45a97af,f1081249,f00a5757) -,S(678c50ee,759c07ff,fca2963e,fba55edb,56ba3572,79970224,5d4f2132,5561f3ae,1989b787,abbf04c1,c93afce2,d389e1f9,780b1657,daa77107,c498bff4,aecba96c) -,S(ab63e1ce,aa2e34d9,8215097c,30b2f266,75d407ca,41f3dda4,1b21c910,824aa6fc,ec65be61,1150ff72,715d3da2,c4541ad6,812eb7e5,7d0f4d82,4792556a,6ce2363c) -,S(a69399ca,fad59597,5a639a2a,31264983,ec567279,b052bcc9,f5c919ae,903dd336,b525c659,c30c4f4d,a7a799dc,c93ae348,1c87304b,63491755,1c43e12e,c50d97dd) -,S(32bf4282,507bcf5e,d25cb5ed,439c82d0,bd7a48af,d3be41fb,e13753bd,c0fc5f3e,cd92017a,4336d9fd,25682f90,be347e82,6773c598,1e80033a,c20bb695,e79bff2) -,S(a1fcc983,7e720096,7203e2cc,11450716,f2fe6484,f681b2ec,5e42e9b8,eedfd862,1e16b6c3,17e8fb89,dfffa79a,722de49e,a419affd,bc17fa96,4ba6c316,31ed4fd7) -,S(d85a314e,69617e50,18df1e82,21cf738b,60485cf3,3abe8838,472b32b9,7f0ceae0,71a0ffee,e92dde66,66b4b5da,a88a79b4,fbbcbacf,3308a4e8,6e1aa367,e00a52f1) -,S(189226fa,688c70e,415b20e3,1356eac2,f5a53b5e,8043e24e,4ee03faa,f20c2e7f,d9bfd8ac,40c7d53e,7bcbe575,9987cf62,fc2bba7f,952e4eaa,1a0587de,f1515aa6) -,S(d3542e0a,6a931162,d7a674e6,32cf2135,32465d25,4d2d9241,ff70709a,559e1330,25e8f51,e2664234,34cbe5ed,622bbd83,dbd42784,4b1f2bf,9a079917,4b57c369) -,S(514d9e86,fb2cb612,1ec6e6b8,25875856,9a8c0a5a,adbfe45f,2876be18,753a2bc5,700785c0,be5423c4,341918d9,f65f79d9,1b8370bc,48629791,45ca8418,57cbf261) -,S(c9f86365,12e9ccfd,e1f1db33,5ae606ab,43f9aa62,2d723f6a,d6d684a3,ea3fe495,30d3a631,3868a01c,9c6f9445,ddcbe3b9,b7b80b58,f31f5db3,a3b3beb2,1e30270b) -,S(226f20c,8fc089fe,98cd96f,a0e790db,641200a7,2b908768,357d206f,2c2deb93,2e23fbb8,b43e9362,3fc2045,24b43da9,5e02626f,ee180cff,1c03b95a,aa5f66bc) -,S(a1b27668,d4b6f94c,7219bd9e,6b8a7e61,9fcc79fd,88d9bda0,a38496b6,cb5350bd,3933fc5e,b6e1c16a,e7aa62bc,200fd5ed,c96b5f74,b72b9b94,2644f32d,d6d68a32) -,S(10f13657,87bc31,1f7b7181,808eb0b,57dd4e7c,1590dae3,8c40df7e,afe28887,1a52e487,9bdc3ec,4e6c570d,91d4edce,291338b4,a79a3995,db5c6e85,e3366d84) -,S(8aaa0ee,a984f583,f9f55861,500dc5ec,f613b3d8,8f989884,273e1841,cdbe3e46,52962154,f85277d,c02c46ab,c2f246ed,24e56458,156d97b8,f2197d22,a133260d) -,S(32805a71,24b1b7,9b397ce5,f7a93a98,dc9472ef,a5b8b4aa,3bd66643,f1c89d2e,af525c7c,b7c139f5,cd2d0a85,82a74ed6,9e23c765,c0b882a2,f4d50e58,843091fd) -,S(c72f10cc,909ad449,7fb0835a,4f3a520d,58db0c2,87f6ab12,cde50749,a9412451,a5666e7d,5197ba9e,37d5ff15,b64b60f3,b8e2ca32,67467030,a7a112d6,f2c7c65a) -,S(6ec768c7,870211b2,415a74ad,c203bd41,72c0fa5a,d4c05f97,c0320865,77fc9a22,18394a22,aa2dbb0,925e6710,549c8c3,b51cbf42,db67d4d0,5da260ce,af1b09fb) -,S(de36ebbb,ff99d156,60506143,87045fc9,a846e7d0,eef91e61,dc93a71c,3ca64737,c5817652,f3cb37b,40647dcd,a476c4e0,488208ba,1b4d0c81,b39a4b4e,900f4270) -,S(f534155d,5538fc68,5ac01ef8,6dea6f4c,19bea322,b46a297b,c0c20ab7,3cc00218,4fab7df2,979d98ca,eeeb38a4,9a2d1253,f9d0924f,14dda603,d3d5706,b3b9523c) -,S(dafdb850,a1db9025,80ecb98,155b687c,8db2088,d0dab521,bc7fcc1,3286129d,43965ffc,ae6c4c14,3febe601,f36fbbd2,7d0ccc50,60ffe91a,a2ef2fef,651ada22) -,S(ac9a0a21,1dcabc85,1816893e,e33cc69e,2efe4069,680b3721,2999f9f4,99d705ce,16ebfe40,8281d2bd,ffa1e02c,2d00d712,acf64eb1,39f5ba88,79c3971b,98c728ef) -,S(afb37bd4,b48cf6e9,5e1eb8b9,7b8b69fd,31ae2b2f,3b7aceb,1db81ebe,98503030,1ccf4164,f8d9cdd9,6f231af3,e5fa313d,c47c06de,ce44dd84,d3fcdb16,a4b7929) -,S(1b902ef,6c294f83,3ab18e7f,21d6470c,f553682d,2b1287d5,1a602925,3888e709,7735c5ff,34e49fe7,2385e9fe,40d66a4c,66ca0102,46c724aa,24b1ecee,dcd69ebe) -,S(6e4e5b10,8a202958,7c5b4ec3,d33220fc,c61b41c5,8c3bf0b2,55e4e28b,7c3133e2,b49f8306,5c336af4,469ea410,648915a4,b55ae504,6cea2f66,f14a99d,9a8fcfbe) -,S(87ce3f7f,bb800210,5b853276,d3931b9,12342d98,7d81e80b,5b10d1ab,1b7e9714,56c6a847,79dbf39c,293c386,9c1e3385,6b71f898,dd46ee16,d1e1973a,4cf0f635) -,S(8724329b,b7ba649c,9c019372,45a1e946,d368a706,2747dd0c,9f6667aa,c9426b2d,44458e8,48d7d44b,5dba5a5b,b0fa0479,55b109d5,21d170d8,9d090ff9,650b944c) -,S(b91befa6,4735c091,32db18b6,b64d7d7f,c6338dcc,cec845cd,7d297f62,b6a1a4bc,bb3961ef,8c9b79c6,867f16cf,be4766a0,15e7ca0c,8f9f340b,14cf701d,e0138467) -,S(4321ea59,332e97ea,3bcfbb89,68a3489c,9ae3d6b8,65cd696c,d8de3200,a0d08fb3,97e480d4,c5149d53,d7582e3f,c73a35ea,3f6b023,5ce50f7e,e31cb600,84cd538e) -,S(dc4597b2,836d96a6,431051d2,5a98d421,7950a8d5,e88c2069,5752ca6,f6f1bc6d,c712580d,16ba30ca,e84e3a83,c35725ab,362bb4fd,e4c42ad7,f9b73f20,53df36ff) -,S(ce644ef0,85ff3009,b261750,8de007bb,c5f19b65,2d9f8992,9972d39c,159a009,9a41d0,58db965,baa00c92,f6409ab0,c9402a69,20a66c17,c089906c,d73cc8f7) -,S(ba1e35c,b6c7b4ba,b81aecf4,23cb8ef2,2ec439c2,584682b4,a7444e01,9936b41a,f3b3c652,f91dde46,3e178d6f,7b17a8e4,1098b33,1cead28a,d2fce694,35bd6272) -,S(b9f98ea0,2a331bbf,60fc839f,845d8f43,6988c747,1902d14d,72ed1360,86e3920f,9fb2501,a7f23a16,cc726f5e,8aa17c12,35d9b04f,a94bb27d,318fb292,c60d03d3) -,S(70591746,55f90f81,c478e702,ffcff930,dc10dbf1,16d7aed0,9c1a369e,807e886f,8267a0a4,b9d6f0ca,db1ec92,560aa3f7,d09d3f41,d1f36f8c,64b95509,b205a59f) -,S(efda78bc,c43ca063,a7b6469f,84012161,14cc5a6e,4e31c31e,b76221ac,c25434bf,7b436ff6,ef45f859,f521b13,53193d13,4cdf8064,449af2aa,92be3781,56fa2864) -,S(229a4b0f,5d62095e,3a630988,c8056aeb,35fbd874,1a2f0e,4306d094,750ccc34,170d33af,491c74e3,d2d694ce,f6a519bc,741acf35,dc6a3428,8bea3595,e234de6e) -,S(c770f48e,20a02132,189d44b8,3acd0f93,f91860b4,81a6bf17,8ce8e2ec,6af07100,7e1120d3,8b2a191f,9ed43aca,3325beae,a6d8dbbf,7e0bf8c9,610f8621,c0266eec) -,S(a5db2c63,3901d52,8b60a48a,20b189a9,e89b8998,3d424af8,eb74869a,f286aa44,b9961d92,6a93d5b0,1a74e6ab,d9c37eed,384e186,8051ba14,46fe1a37,24af1e50) -,S(3ec7169e,9f330288,a63897b7,c168db9a,4b447e48,cea2c5ff,77b298,da41db1c,c3fe974d,e8e60eda,22c4aa34,ed34a4d6,4b3be268,12e58b49,e4477835,f3053fb2) -,S(b733de17,c3311184,d5860d4c,f99e48eb,810cff93,ce92eb77,7cf2c114,fb5bf3b3,c75c0dd,72d20ad3,2000d537,ebb61571,57fc4ace,9f26a90a,d28e1a43,480c11b0) -,S(57d6e208,d555bc24,15d49616,a158075c,27db59e,6a821df2,8b450161,6c2ed278,83870a79,d130da5a,3528e353,353b34f6,74b5d02e,6cf2a891,fca34c6c,3746eba8) -,S(9e4234f1,aa69a478,3bf2fd3c,3208f6f2,6f069409,fdb2faab,8d792588,6ad3673d,5f9a4773,7725ebc3,e8bed041,47a05841,9fb42b16,affec29b,d753733e,288d0653) -,S(6fe3ff9d,9fc12ffd,bd896202,fd8ae913,22e4fcf2,76068a75,8d43f1f3,9ab68173,ef0d5682,1d414608,273ef7b5,9208c59,bf94e16,3e7faa3c,2ab3da22,b509fa1b) -,S(2c31e54f,d2586e19,efaaf415,e54cb499,54c49257,d11b161f,ff2aae5b,b45c4631,bedfb0ad,364ab1ac,e7f53c0e,9fb825e4,39af354,1a70708b,d8e0e423,13311346) -,S(51597259,23148c3,478ea2ee,2b933858,4d745b89,49c2f782,3b8660e7,78203ebc,329f6153,f688b743,c4fdc470,25790503,b81ff7ce,5a613362,8a59f3bf,66aa1817) -,S(188b3324,58f7d7b8,dc3fcb3b,df51ccfa,d394684,cde37d60,70d41e46,cdcaf1f4,4dea5da,d112a117,31a6b04c,8999c6a8,3d1ddec2,88aaf104,487656a4,d3901910) -,S(92058e41,a503e158,8ceb0a49,4e13e2a8,85f804cf,7f13c90e,307372d5,cfa6e471,368072d4,449e685e,17e5a230,e2177e95,bcbe177a,58cd1510,68e7255d,84ec108a) -,S(6a6f5226,44e06506,f27a7a68,96eac537,726f79e8,9e83105d,5b647883,34099fcf,cf3edd4b,d8ced83e,b167b664,574987f4,7104e79a,5a4b5321,4c19a32d,a5132586) -,S(7e37cea2,340cdcc3,ca21e0ef,ad548f37,c77c3402,34f0148d,89cf926f,2376bb26,c72d829b,42a27c6a,b062938e,5cbc22a,6b02d42b,d31cb69e,83b9fe9a,cc9a0016) -,S(1e6c2069,cf0f6cf7,bafb4b39,bc97a8dc,800d010c,52c3cc5a,d848fb82,d8d0b667,c181e76,bca1d846,86ecfbdc,2cb09140,49146986,630b7e81,f86c7238,8e60196f) -,S(5566600f,e6eea4f7,b06336c8,d44b47ea,f36ba43c,ca404be3,5203ef5b,6f07e16,6bbbd08f,7adc1979,ed4acb4c,f372eda,69e5ac16,7695a78b,5a7fe1ce,1057e55) -,S(435c634d,ed451c5c,21c5adc,45d94f8c,69045016,d529ba76,19ad07d9,31c791b5,31ede268,8252a50f,2206f959,1953c0ca,85009876,2b6f6c14,24b4e47,c74d4cc1) -,S(6fb8cce6,a66071c7,395c0612,252a414d,f19a0d2a,f855e7e9,dd142342,9c57b9b6,17f94249,e2f05314,d4799fad,68232626,183dadee,abfe34c5,b845d89f,2768e052) -,S(866f3e99,20fc4c94,9496a695,f54ee634,11c711a2,99e05890,148de8c3,2980dc36,e99c55af,4f8dc3c1,d38a11e1,3c00db2d,f5211f02,e837909b,ae188786,d18d62f7) -,S(80c13410,b7164899,a724f723,4dcbe505,62404f0b,7c027c79,4616f618,80468b2d,8631942e,71a01e4f,d7b59281,9dc69d39,bd6e8fe1,c2c41621,6d8df895,280b91aa) -,S(8f85bdee,ef4e9d88,53e68be,c17bb6ec,bf37abc0,a4ba44d2,c3815dc1,82a7da99,36d45bdf,8ae9342c,af0f8ce7,8aa591a3,4e8c295e,49ee6962,b4a9fb7e,ee17897e) -,S(9cd0b2b,3393cda6,ccedaf4,ee8a1b3,17a920e4,826da2aa,4404a01a,49600749,3831d35a,51d9650b,b1901e34,8f0c4ea2,3a00c492,a4960463,414e5dee,aafc5a5a) -,S(a0c5f1af,15c67ffd,6cf832f7,974c779a,3ab7ca,dffa32d3,bdbe0377,d49f33b0,6aff40d4,42de6262,41734412,3620c5ff,3079392b,b8843c57,80029682,1cb91ec) -,S(af396f40,13e217,d7e1fbf0,2ec4039e,c0111370,37cb2d78,90a82313,58edfacc,aaaeb9e2,5a57534a,2dc35d16,705f0e5d,6754c599,e85864bc,936e94f5,9acfb936) -,S(fdac3c57,e3e0ecc5,e7e871b0,dbe35979,87d4c071,f2f89307,cf1e71c4,91ed0eaf,3028a0cc,a22ef096,73c877af,ccfe36d6,b14d14ff,5da10b18,cdee6068,3ca09fc7) -,S(e3aeb123,9587baa9,ae12b6a9,68efaedc,ae745fd6,aac5103e,14a471d9,eefa88b7,7ed1c786,52c1544b,e306833f,bb27d1a5,7b460305,a2c8f6cd,2d33397b,caf769c7) -,S(96baede3,382a0162,fb4cc663,c91acb94,eb83d7a,3e3e0a0e,6055a50c,d78352f5,78722e97,b3ad2824,388c3a80,fb930089,5100d61,ea58f997,2adae059,f0c50cbc) -,S(68704956,16975637,f35e1eda,4db546fe,ba93d122,446a3e40,8de04ee2,3bf5f5b5,6247d2fe,b5f7471f,3a06c7a2,4c4261a,934bd226,772405ff,46e361bc,614ca494) -,S(71ccc634,2ca1f858,8ae02d72,eb0dd2b3,62eaf652,f83edad7,94095e09,f4bcf749,487aebd9,23b10e69,4a8e3f22,2703e5a1,aee17794,42a96c68,6cb9f983,dd2a45fb) -,S(6fda1dd0,65739a2e,58cd183,1e8b6109,713844ba,f249cdff,25d0b3ec,f635d3f0,a2ee44f4,8afccb72,4f8a96c3,2a88a8b0,a232a93d,553713df,60a965f5,2078108e) -,S(d3f27709,ff5ad97b,45e395c1,39947115,65cbfcf5,838e7b64,b1016cc6,d5147f45,f96cac16,cdc8e1c3,54e026ed,29bbd6c7,29006ee1,51d9d61a,4391567,93265077) -,S(27ba1944,a28a6eff,78a7d064,bb8292c6,68f82793,8e2be786,41ee366e,a4a011d6,24bef875,9d216430,e7312fc9,458f0571,fcbe305d,574694d0,a77f7a98,4e7bdcab) -,S(fd37b812,5fd87ce0,82fca9ff,7872e0e9,772f4c44,1870748e,e35e7d00,944fe190,9450a525,d9ae198d,db9b8c43,fb337df2,8ec68a44,60106951,1847b9a0,27dcb453) -,S(d9967cca,92583e0d,8d329b63,f32a8017,4467518a,595d8b80,2c24cc8a,8e071c69,6aca3673,c2c39d69,3bc86dbb,92e5af27,28361cd3,2179eab9,7ed64ae9,73376c25) -,S(8ee82d3c,4a8d01eb,d22798ef,bfd95c16,f53cd45f,e3d044f,3d89ed40,b94a0a3c,e0b0ab7e,9167fb9d,aa71c3a,fd5b9c0b,79c8b6a0,db3ae2f0,36c626c7,791e1b2d) -,S(461ec3d2,817cb549,a9fea029,15029707,8d709ccd,bf22da47,64c8a1db,c562caa,661b2d7d,cb5c9790,510f6e12,61650401,26cdf80d,b086259a,db16af47,af6684af) -,S(3155885c,935caed,469bb7ff,b53ff6b8,59f51780,f3de5890,673101bd,41f5793e,603594e9,92ac108f,8d0bbdfe,8f3576e,8ca6ac2,69c7581e,28d434ce,2043dfff) -,S(5cac93b0,ad9199c1,906267a0,ad8874e4,c68a60a2,b9fb6f0d,cad42758,2a4ea9eb,836faa98,a116dab9,69961fe7,ad7483eb,c48e7295,37e6634a,e423b99,880032ab) -,S(1fb6d3ac,afd5ef56,8b6eea1c,4a8f0179,54d05274,24487904,7e3ec56c,6956cc42,b8ef91f2,f89e4f32,6df6a1ec,50c6362,7431be48,1183c839,3133dafd,2e2a5411) -,S(89c0b1e1,52f0005d,a30618f0,3fdee7b3,69fe0157,f7bb2bdc,d31fc773,d82b28f2,61d6e357,bbf46816,acd05de5,b26c67b5,ad8223d8,ac9f47a9,25477ab1,80b4a507) -,S(7c5d18b,1f9d1afc,d663875a,34193240,7cb968be,f31d751,807ab1b,b79a211e,45fbe7ea,985bda0f,bd23b449,5d4e945f,d136b5b1,296c9b3b,6dcb9c37,bc779ff3) -,S(c827cfc1,9393108c,9b31ad4d,b5eb7f00,b6afdad3,a5e2f792,ddf9dd13,f159f85c,5c5fe07a,3025d401,54fe12fc,89951e2c,330ea3d,d6335a12,9c31aaa6,753a1cb1) -,S(6347b32b,b1f3f7dc,205e2fa4,6b201b4,2e0dfa80,550741e6,57117875,57cc5d9b,f8f30e10,9508d34c,a48d7255,3f8ac26d,a455d3f3,b170ee52,e22be1a3,ae8c3ba4) -,S(d489f595,e822101d,5f6e4283,7db032ae,bfa21f3a,94998130,e0a1d226,67ae1014,8b112e89,8dc4a146,8f64c33d,1261f8c9,2bfa98df,eb9500c2,2b4a66d9,227c66a9) -,S(90cb9c63,fb4afbce,adeb8f98,1e76a645,2200d73,d43bc0b2,76f058dc,b8a6205b,894afdc0,f6ba7f1a,bbaf19c6,720471d8,2611a77b,5bf6c87b,a02324ce,52e74645) -,S(40df68bb,19f121f4,e566a1be,f0a98954,869bb06c,699e818b,bc49a795,6a196af4,70d41c09,d0cedf7c,31c9f830,3610f6b6,e1d6b3d2,a431e69d,a31bdd63,220cec90) -,S(4936fd74,a0ac5045,91c962b6,431f17fc,a888dd1e,b35549d7,8b41143a,83da41bf,33a8e1dd,6517853e,d7c68af8,5b3f1cf5,3fc5b72b,5dd0f392,c5ab5ff2,1bff4f92) -,S(17177538,811075b8,f5baad59,2958074b,c1a0c6e7,b2a3f594,288e82b0,da023557,583d4814,efd8742c,5e7a0c5f,734da121,b163fe28,239a8775,4bbb072,c1b10837) -,S(a126b7fb,ad5145ea,b414c82d,8f21f208,6abb118f,3692bab,586770cf,4f8926a2,79b4ac17,b601b4d2,1a2bfdb7,41f7fec2,88d46594,699e4394,452cb2d1,ae2ec669) -,S(51eccf61,f8840048,d55de51,2d865a52,3485db8d,869844fd,ba30e703,ae871163,594ad253,97bdc9f0,82c0c46a,200ea090,12b2c6a9,57a53dce,e87caed3,2ea8d50f) -,S(97781633,6f1b7131,f55966cc,a79d25af,d8984438,8b516882,5105ba3b,52b3c7a9,f1df3541,b4b08fe0,cdda20e0,a5275eb6,105011ee,f4355516,e47e89d9,3b214c60) -,S(8bc2c43a,72248dab,5c78cf6d,b1a35ce8,64231d3a,870bbf01,cdb79be0,2c93f7fe,d52e2e76,173e9dbf,9e8106a,ffbb9d7b,b428f07,80269b2e,f49bbe0e,14cbb425) -,S(59ed7881,6c7ca119,ca4abd03,34b90b37,6c327175,e899e0d9,79953e50,5aef9f2,239fc027,690c0feb,e4db46a2,8669e0da,20779425,34bc6133,152a606a,16449910) -,S(bec399d1,76714995,d4192390,72a39c59,c8ff8e9a,2cab6520,ca0cf6b,2fc70fda,ffc4bdef,7831208d,23a1ab9a,de52f346,a21a2f7c,efc5ffbf,70999bfd,ad0ba8e7) -,S(93bd25ee,f4cef1db,fa5f9951,7d22a77d,9e3b87db,58c63076,68a35885,9e0c4d34,dd7d1412,97361b84,9a43b1f9,4f89970d,fa008c63,3404860,794e6a87,6735b4dc) -,S(b203a657,fb4e4d51,158b2e70,87455a57,44e553c5,bdea4f8e,3e8e6c92,eddcf58,98246948,c63e182,61f0d4c7,543fba7b,c74ae5a7,a19afa6a,ac80359,5ed8c99c) -,S(af38b53c,1dcd27b5,8118a28d,11da8aaa,3e20ac21,4cff64e7,be683dd,80f6aa69,91e38936,ba8b2b42,34686723,7a3fac67,5ec10179,18f8ac16,acdc32f9,c09fd919) -,S(55e4da5b,b99d805,e2058756,20ab4cee,988ed472,f5e6d86,2f8c574f,6bfd8518,7368be34,75179d32,e15b5976,c34c366e,e7713b25,8f179309,40b16117,aceb2d35) -,S(d3d7e82a,a7ebe240,83e1a15e,1d817d91,a3608c6d,d25a35d9,183a0c9,e42133f5,a5245cc,e89537c6,895080b0,6c5e2772,4b1c6d69,6c1bfbfc,ae6a7d4f,fc5d504b) -,S(8bd14f9f,e6b54437,9761e803,1dcc9907,beab754b,68c6c3f2,2316e5a6,6ee48799,f89dc150,a3876257,51663a26,35633868,ecb2eb27,d9ae8603,89110aff,6978fe19) -,S(b1d72365,3f50f42,cfeb0858,972a5a22,3a7dbc5b,4823704,85c88fd2,22212932,40597dd8,594ee1f9,b74aa52d,385b21dd,6279864e,7d0255,70bf3716,c02143ac) -,S(44d303e1,cb7d920c,93be4763,e045cef5,c22d4403,5e1d3a8,593f4f72,679d3023,79fbdefc,5ed6da2f,31bd6fcc,83e3cee3,e77e41a9,a01b2004,76912c61,5d89a70c) -,S(1655ec54,447aaae9,727bd4b9,60eb996,92558999,83d4aed,3dfeba12,3b0cb3ca,8e90e578,cf96e31e,988f7bf8,a9f06d94,6ea28fa6,b1dad744,3b9ece50,6626fcdf) -,S(b02ae3fb,530566bf,66da9326,18990e6e,7902b104,800cacb1,9717bb7d,845a3f29,c6d32713,f4483031,19bb7631,1b397427,d8c05232,92a61051,62a0307d,7b006876) -,S(13c46566,53a0042b,8755e140,2b12b9ad,8e123699,a153ec6e,65e49cd,10c5bcd3,70f3672c,498f603e,3c521ea4,3ac3e10,7bab13a8,a78b02b0,4492c51,6d41c88) -,S(e7c7562b,3fc37b8,2e9c7bff,c5e97b39,dee483f,141df4c6,361eda3c,4f1483f,734be460,3d2b4958,c1bdce51,57a16d0e,1a937298,1dbb2833,1b12f8e6,c3454066) -,S(de025d2d,fb6cfc75,342b2ed1,ebc7b27f,332f3921,c304b8d2,263d7fba,2959aefc,46c609b1,6ab6f3d0,2dafc30c,38373a30,1a88c31d,80694598,5e676f1c,16de12f1) -,S(21e788b4,fed21c3d,25ddb714,abaf053a,25730af4,83817e4b,6a42c323,3eca2e01,1fe716bd,a7d07592,b66af9b8,32335b9d,b249b1f9,cd413c58,ddd29fda,e5c1c4c6) -,S(a7db27ca,7481d50b,1a458242,c75b28e6,d1bc1a9d,da97e012,e39cff10,7b79edce,c4f8686d,cabde6c1,d3455fc1,795a7cc4,84239d2,3b11e238,85136183,71ae73f8) -,S(c5205173,2790f240,e2161627,5ac894cd,e80a7d3e,bd5bdccf,41af64b6,5e2d477a,e9aa295b,209410a0,f0e8e216,deadc3f8,af87700a,40543cda,463beac9,f62ba20b) -,S(487bf4ad,99d1daeb,f1c25f86,d36ebcd9,38e91eea,8b855d05,ea9371c4,9572846d,81293837,ac6ded0b,ee04b2a5,4c18ae0,32f72970,86de0ffe,791a9576,fcfebf70) -,S(bd6dd2a6,bfcf688b,84fe2d55,e56025d,35567574,20edfcb1,3cd14483,e08cb53,c86a45e1,84c83806,38ea1501,c2851598,c467d2c,d1c51a1a,1b037324,d9ab0fca) -,S(94a417fd,fbf188e4,1334fbb6,906731e8,70dbca18,672bece7,936a4c7c,235ec737,e03c6607,343ec14b,81eaf124,bcfb7d97,564e9f93,546f9765,299a443,d9be8e34) -,S(2a57dac3,3fa13b26,a96d9b73,317a23c0,2ac597d3,3968fa8,ebd88d94,66aba51e,1754a6bf,1db7b3b8,b0a7996e,545f34fd,3b05bfd9,805b50c4,42db2937,e8c13b61) -,S(ba2e4a71,6142a39,67c613e9,93083c32,d1c66da1,2c3f9742,eae90b7f,ec7e7df7,c262f8c1,a704e83b,ed7fc60c,5adec65e,ccc6de35,8247cc97,1da7acfe,834cb07e) -,S(4ae19743,b3132512,d28a12b1,1fbbd824,8bb0b9a,730d5a8,a862ea8,ecc01ca9,67b7267d,48fa3ea1,d1c1ec7c,a6a8ba0,cb27883c,3f9d4193,20b4c8f7,a017eece) -,S(4cfb26c,81823667,f18e6ff9,d77493f0,778b9bf,411b63ad,61850ea7,7706ddcb,10df8a3e,3a8c93df,4d7af16,407c3211,aa6c6079,c397a0c7,78e1e277,24e4028e) -,S(9f9e4566,a014b66f,fbc3ef,b3c05062,15f06102,6f7d6561,934d3db9,5d130349,492b8ba2,76d526bb,98fd0c17,c5a0aa7a,ab6e5c9c,ccfc95fb,a417d25,9396c592) -,S(e36c0513,3641b560,b0f9f4c1,1159e2f,ecf2a194,b55f3bd2,22ecf1f6,ac239301,c7fd74ba,48e7fc40,6322aea8,e9f83a82,20e9a113,ac2b0c7f,aa05a5bd,bb43736c) -,S(91b013b3,b94d4568,78737580,bf1da11a,a0bbe0a4,e3ec65e0,33e9f824,d8480bbf,15e3707e,c13a2529,22a6f824,7e33d172,948790ac,3d367f00,6472f22b,e8cfc5b4) -,S(254d1788,8c676d52,236782de,2d539f2c,41f667a,d75d0107,7d43f723,ea324f56,f7042d2e,93511e5d,13f4aa03,bb2dbf27,9bec3df,97974275,5fd25133,c814094a) -,S(452d6b7e,ce7d0f71,2afabe44,2a22f16e,34fce662,99697f0b,6135678,56f4079a,21ea8ba1,28cffe76,3400d69f,ce13204a,9a39ee59,14132d23,db3315a4,7f776998) -,S(1580b9d0,7888f41,81b86b85,5b1982d2,81783185,5f28c163,1f151479,cc4c508b,4d9d1e9c,78b3d9dd,73bcbbe8,778c1b7f,65b69faa,f6576dc3,ecdd00f5,c1d689ff) -,S(79dda23f,c31694c9,16d1470c,2cf25a02,45a5aa7e,d084af45,c43960a,a2fc2700,7c7bc169,a58b8d8c,c4b74e0f,377031ce,d7158c21,a156fc03,c34f25a3,a95bc978) -,S(866da7a9,bf80cdc2,13e500af,b5f4aa0e,419b4905,44653b5,fe2daee1,4149dbe6,626d38b3,b45d57aa,6867e8ad,c8abc49a,81a282c,6bc6524b,239819ab,766bd3d7) -,S(432bc912,bed271e9,321624cf,c6062b96,cdb502ca,f990522e,1024b80b,9411d374,e645449e,dd7c4d41,41e0cc5a,cc5d45df,4cb341c2,baebb605,bcdce6a3,e411cf01) -,S(ac3d3b28,83ec385a,15297086,525d937b,717f5ad,83a5be4,77b3ec9f,6410518e,d126eefc,c9ed7e75,c10d01b2,c0e790e7,3dde58f9,54185a12,5fcc7268,84b9b8db) -,S(4570834b,2a82385d,6db696d9,56ae2667,fa18b262,960d064a,5c13da43,abd6aa37,1e9d6083,b249bf88,7ba2eb59,a9597e7,d9d15c64,ad6404e1,21a486b0,61236f28) -,S(88e9a6a0,ffaae05b,7c29bf79,2163c0aa,b224b051,36aeffd3,341355d4,b983ef15,ed382a2d,fa2f63ea,dc4ef5e2,579abafc,fe457475,d1ae8413,99969324,718d1e5a) -,S(16810eb4,de3327c6,a505663d,cad7f618,b397033b,d6c9748c,4fd8748,2adff706,352ebd8,91326c9d,2159e84c,40dc29ae,30693b7e,5a9ed119,1fbc2cf,ee60c81b) -,S(d7d03a92,95064981,1cdc6503,588d157c,88c861d9,43fa9cab,e2e3301c,994adf7b,8c820bfe,933c2c05,1ca3042d,5ce781e6,ef419c8f,d9aa83ef,2a915e36,382f9627) -,S(5b2c9504,f645ac90,24e25c4a,e880ce7b,f33aed77,e45518d9,1c6f2652,ddcf11b0,500b37bc,c7764f32,11d681e5,e8f2a407,440e1da2,4eaec354,fc289c76,29296449) -,S(d18e26ed,d2c78bbc,16982675,9d59eec3,bab1a64d,f579dc2d,6284add4,8cfbd761,1a1e0172,37a3e78,8fd8989a,a5bb6944,685915da,1392e1a4,4a6c7ef5,7d0770c3) -,S(5f6b1416,9bbc4795,8ca21e88,df252546,dc9e46bf,85d64772,24f34ce2,8e58222d,3a8e7616,4d5a0501,947ca0bf,163e64bb,3a57918d,e383c600,e02aadaf,4b7fd6a6) -,S(d7a625e8,dcc8b456,69802023,8fe85691,ec2e050a,25421373,39bdbc8a,f762bc7,8f1f9935,a8ce2607,abd7bcbc,fec1fd8c,208683a7,10000806,20d50b4d,36ea3643) -,S(a56a5419,72aea4f7,15dc891b,3a1b34ea,7ffb42c9,5e02a771,6bac663e,8d5913f9,47b3dfcd,ad785671,180f7bbf,a7f5d144,59b44023,640e3897,1e999a90,6bc3f994) -,S(1ebb89d7,e574cbd1,37b1a3cd,4a306b44,30325db3,361b7c3a,d93116fa,baade31e,2039c52f,bd30c84b,4983d118,5422a342,ee020c33,49357e6c,b9550075,38da4dc7) -,S(b5728208,931a6575,4b5cd1a4,a798ec27,e189effa,3ee4f0c5,ad493a88,b49706fe,aba785e7,2da3d301,cb29a612,562078bf,358f680a,317836c2,14ddf7d1,bede9ee) -,S(56661670,d67b7c77,202a00de,effc1ef6,f5162a97,47afca8a,a2457c85,85a775c9,adaf08e1,83bc5107,4c55122,e549d3c1,4de8a893,39f199b2,ea044a25,4d8803f6) -,S(18ab56e1,ecc86b69,77104243,35737b51,c18521d1,b170a3e9,3fd068f0,ddf2704d,cc694c3f,43bfba9b,20c9572c,acb30563,df74f07e,ce1ff9ff,46b8259e,8119e94a) -,S(bc12a874,48270360,1575b754,bf5f50f,6e945185,2e0f27c3,c1aa0f1b,ce0ac357,9c6ce76b,ac175ce1,d667783c,7204ace4,abe12d56,62ff36f9,5de017c6,f1ada1e9) -,S(a4494c26,99b2da0d,6edbdd6c,353eca75,75666796,5ddbe457,2c27ac46,79054584,589804d5,8360a9e7,d3e2a914,61d5b1ba,e8f0cf69,3b8add03,5545386d,5082d621) -,S(1ff846f9,6d0e4e7e,be34de77,d036a027,f1baf9e2,ea3dc9c7,8284ac9c,ce3aea6e,8a0a336b,9f0e3560,31f5d1a8,d4c0b68f,27ba3eef,a52dc974,8d03e12d,653f2e6a) -,S(33181aae,91573ddc,728839e0,4173f716,6862d724,35744099,ffa8f1f2,9510b374,1252129a,8cc8ce4c,1ddaaa0a,4c34c4a5,f01ee26b,3e1a9fed,ad0e7c9f,bdc5223e) -,S(e687832d,fb0e44ae,f7649b15,77274a94,64426406,fe4c6ae5,7028c9e5,78012594,5e5b3897,6b734b7,b65caec8,c77ffb7f,c5de4f98,eecab002,8cac0c4a,a513b7c0) -,S(354bbec3,ed9371ac,58174b5e,2a18c76c,c22951,df4c6aa5,755c72f3,94b37def,40d0c876,9283416d,b3613ac7,37401e3f,3c2f4def,bbaba44b,5c2a83fc,c614c29a) -,S(fa46ac6c,5205b81f,3c9e8aa6,8b5ebef2,a8bc68bf,fa2f4511,ae36f726,7439a485,3853f9fa,b016d2a8,1cde37b,13f91185,f25657a,765fbb35,c1b4d52e,3f67d180) -,S(426f86b7,33255f8e,1e85263c,923fb86e,56a53d77,945f6688,5627ed43,3024328c,92ec0168,5301c89d,5b13c4c4,57b22215,658c6341,6aff9148,6a2efbcd,4e8c4fdf) -,S(5c8d1c9b,f9a72d5b,e15d3f4d,17d48cf1,7685dfec,b5ae1ede,b47b6e58,80bc64e3,6205550e,286c8150,6638a3c7,c20f0dec,b6a26b53,641d2dc4,e18d0f7d,29bda7e5) -,S(3a021dbc,7bf7501f,ddc31356,26a9cb01,be673373,fa663c80,271be570,e683422f,64a89c54,ddadf89,784e508a,d056492a,a7a71b82,485fcfff,54c7b0de,4c1bfa53) -,S(8d82aa49,1d719f00,75d2dd9,11d642da,7c0062c3,2296726f,a504af27,23ba47bb,6e616f50,6d1478f6,988ed10d,6c6d3c50,7c2ae8fd,4760e699,1ff5c62c,53e4e77a) -,S(6feee988,fe488e1a,6ed5d60e,fcac1b3d,bbe5451,6e7aad76,f27f08e5,3c5e536f,ee9f95,839fba96,ba26d848,425b68a0,73dcee61,35e04eef,f482998c,b044c502) -,S(36240979,bafd0d57,72fcadc7,314093c6,3063880a,e895ce5d,2df3e59c,ae16fa1b,619d0376,58ef3d85,a7afe326,77d832cb,eb20820c,157836ca,65f17c61,c84afa48) -,S(4c2b8847,4da56053,c2046fc3,26e81704,b78494c,91877407,9984a3,cf6a18f4,459a9e69,17a4d711,61ca0b43,85c5a823,734286e3,d0cab398,dda1fe21,3b28142c) -,S(f921c9fd,b33211ba,a7f4eb5b,15044c34,d6e54f50,af7b85ad,84e12fba,b1478ac2,38cda9b8,c850483e,48c6b16a,5f7f624d,e31faec3,5cd594f9,3171490f,ae016973) -,S(a57769e6,6181d68f,8f86c8a7,da3fdb4e,850ae07d,f41e78b8,ca42c6b2,1b19b257,212a987e,644bc42b,f757e00d,54d50ba5,1dcd6698,280f8eb3,8829dafc,527cfc6c) -,S(95a78104,37abecad,888c9195,23c9b16b,375a2714,fed74639,1ea949a,c7c11d9f,eae320aa,227b056b,242723df,1f11a494,ec642876,91a22748,9e1ecb2,a2cfdf78) -,S(76a7e034,f7ef3e14,2ada9a64,ce984008,9f034a5d,8584a0e5,d10d40f4,29cfa42a,999dc0e4,9633eb3c,2a4ec931,9bc2eedc,9f2e4996,522a2404,79c9468b,668effa2) -,S(eba89396,47567805,1cddf92,9db7d82d,427010cd,5e94247d,f4e8cd1e,eb5881d6,b92ae1f1,c0885214,3f37d8be,616cc5d6,aebe0f8a,8da4a6a5,d4a69b5,dbbca552) -,S(a53a48d8,59fe156,6b14f872,aaed4735,dc0b7589,713ce8ad,dd3f3e1d,6e23704f,9e738da0,7e85a3a8,3d89403f,3ee7d564,4f463418,676cea0d,2528b515,39387fb6) -,S(8326590b,dba5f8a3,8e39b148,105063a7,c831cdf9,98288fb5,95b4fd5e,a707d3bc,a02cf88,a2a1dd25,2d00d62e,cfa4130f,61b7d4f,297e6b06,cb4661b2,bf768982) -,S(6a492194,ba8c10bf,e31714a2,17a74b2f,b0c35a2c,95c54af,7f5ac6df,17916030,3cf0bd65,8e0c937a,92ee8b4f,b4fc3289,c531cd00,6febd45d,b6b6c522,f8c77b87) -,S(b4ac71c6,ff797eed,61d80c49,46ba221d,3b34bf13,7e3d4747,4b6c3068,33c52a57,46acb2e4,8fb6fefc,ef3d2343,4624e0d6,14ae3b60,df813683,90503506,d52820f7) -,S(8b11711e,65bc29e1,16bf05b4,e557b211,13b19b93,a1c1ef9b,49a19316,c286e0bc,79c4a0cf,cf383538,21ad695e,5b4eae58,faa6bcf5,c722c491,aa9078c,8aaf0dde) -,S(b8b00a76,e86b2579,97603f82,e80fde24,727362c3,6d7a192d,8974f643,4408e098,5db6718,8b0108dd,7cc6fa1c,fead7b2e,9e0b9ffb,78487d0a,5851b6f8,513e56c6) -,S(884c3a1b,fb6b968,53427a8f,69b713c6,bebe8f69,645fa52,c50e2d2d,61d89814,3dacc0e5,94b2eef,3743f821,df54dec0,ff28aa4b,d5b18fbf,14d658ce,7a3749b) -,S(3d0c1dcf,51aabf63,fe04100d,cbf6fb4e,c004dd1a,aeb637d8,496a47f9,74637596,576ebd5b,bf5de2cd,6242a6f,599fbb76,883fe013,3e2ef05d,22843236,a5df51c) -,S(56b3edaf,61539adc,25c57f79,a277b77f,1ae972b6,3d5328fa,13f811e2,dabca8c7,40383900,a2b28602,71ab3d2b,5dda95d0,96bdfbab,79b3d347,dbdac66d,2d2e98eb) -,S(426e29bf,50f34c9f,434eacfa,845485fe,5fbb11d8,319f9457,a74905fb,2bcfd3e2,eac47ee8,eeff40c6,20d10cd5,c3b9df40,eeb60b88,df1f57a3,5d613198,33cb117a) -,S(955737c9,f4e24d7e,c6d419ba,a2edadc7,cf0a91fb,5bfc3ea6,7ed50ca7,62929308,97bbb89d,18fd9040,2fa78314,359bf645,b69831b5,bb82e608,67baceed,481675dd) -,S(5d72a813,d46427a0,f2fae639,fd7e7ad0,704e74a0,83a784a1,cbb85017,e8b3e514,c92f410e,851fc61e,559d6839,a99eb95a,2e8c2636,f51c45ac,9bc1613c,b8876c2f) -,S(c7da9359,e9bc8890,620876d9,170495c2,dda7849c,7852406,22551bb7,e769b6ef,12278168,71508d00,95d90787,24a0c7d9,cb41f6c5,c82f01c6,d3794c3f,5c10653) -,S(67080a26,da7af0fd,c2fee080,f20ae516,d92697d7,fe1adace,9729064f,569ac683,ad9a07ac,fbba708b,30944107,e510eac0,8e08c5ce,79f77714,aa522cfc,2316d94d) -,S(210d5a39,d61428f7,6f878ddc,82e3afae,3947f404,5c155a41,63a00570,5bfc0dbf,617effe6,b0a629c2,ed14cc29,67a9193c,2efa804c,93e997ac,96eb1803,2e8c511c) -,S(5d0b9231,ca1511b9,c53242a9,37837d13,9b8e461c,6ff655fc,59021d04,e334ed98,c8070121,f4794eda,713ae1b4,a9e7d6cd,1a2f58e1,f6f8d986,bd13a66e,bfe924ae) -,S(687bb82c,42101161,ed0c8bd5,44c71975,9013fe2a,fcd10ab6,3ce78a67,e2907392,eaf63d87,758aa3a6,f9fc721c,f8b209cf,fafc8e81,10397e35,6a25e966,100d9eeb) -,S(51a44157,b8048f68,1a2a3931,ff2c3ff3,c63527d1,f4bccda4,e66a6d1,ce5f5d33,6ffc8d16,519c2940,14fdc8f4,20a63890,1a0c5667,2db96a1e,c5127fe9,e847dd31) -,S(b2862572,56f515a3,5624786a,478c3bfc,a5dd7b2,2bd7c4f9,89f70bcb,8de86775,22ae96a8,a5a5396,b7a67e5b,29292ffa,f53b64de,45f17692,abcd932d,4664f3a3) -,S(f76b721e,201078ca,eebd89a5,ca396213,6ee129bc,fb92ae58,4bb7c7fe,835bc30,599c6ab1,8419840,3d6b3d17,161bafff,223a0a38,1e96a4b7,a062f4a3,e6c0d561) -,S(12f24a87,63adee06,e82f20b7,ff696911,d9a3b88b,36dedb97,93b07c34,c4178e9c,59fd7b9f,96f01fb7,b265d939,c2827bee,b2427fdf,8c2e1b7,35178d58,e055b7f1) -,S(9e1b8a90,de6c6bbe,2a082d47,758240cc,bcfaf145,c48f90ce,fa0221e3,1922260a,fa5e86a5,b54bd9e0,7c2a54f4,2097d004,8a71eb06,ea48c0a6,6cda5981,b390f9f) -,S(63f05903,20b73eb7,b01b6a66,e28e31f1,ed4117f8,6c4d20a3,8c109031,2fbaae9c,24b8c9d2,d34a81fe,6e88967,a263877f,40bd68ca,baf5d9c5,1abe8b1,9501d8eb) -,S(447c7409,f5402a3d,a1f569a4,ad9f2855,e5c89b6e,99c743a8,e27992b4,63905999,d44e8d9a,b34a7a09,47b37723,be016c08,716baa73,8b93f28d,b7790370,ad49e154) -,S(74a4406a,4c5340af,ab77db0c,20f197e4,25eed4f4,a3f986df,1bbf10df,f8793254,162d678a,a4ba712,8cd36907,d1c46b16,dc4c07bc,52aa46d,fc7987eb,67742023) -,S(f7035171,31872637,ab0e63cc,841cc7b6,2bf5e076,53a45ff,3a23246e,8f047c07,c84b0391,4f470785,721762a9,5972b59e,b3c7eec9,66718936,ccaee9c1,da1097ef) -,S(ec4fe07b,57b23581,2c53bd70,6b0a4152,2194d168,dca164f6,ac999f6f,72eaae11,af495291,45deb29f,ec2b1dc4,e9b76051,b2f9df79,bdd304d7,b5528f5c,a2fff789) -,S(17156de8,fa96174f,7a0b274e,e168d0d4,c6552047,11f36388,78dbab4a,cdd2ac9d,2ae3ec4,36c1460c,984e37ed,6decb88f,c2de9f84,79e28ca6,abb6803f,1461ac3d) -,S(e41b462b,9c5a47fa,cfa9be56,dd30cd,549cb90c,9506a6a,abfca643,9a1b2ede,108fe2b2,8bda60a,c68fb353,38c6958f,e1b3604c,22215311,d380bf11,17507f4) -,S(ba6c0159,20a67883,d7880051,51a8038f,f357ea78,c53b95ad,38a6f437,7744aa38,da49c0e7,deb6b746,83366aa5,c0e8e710,cda1441b,6686f680,4579b5b9,16002cf3) -,S(26f0186e,883a4b6b,87102ab7,f7e52663,7e8a9553,8495729c,ee283568,f8cbf1ae,eef8de4,bb2197ca,ccd51980,995a18a0,aad78823,75702d3,98b245db,4bd5f47a) -,S(10b93de,80c0cebc,351b5588,c0140e63,e00874e3,da663cdd,c4501ca5,b40c9d22,ed3189dd,f79af36b,e7986b02,7ec495ec,1dfef7f2,14358284,2d05b4d0,1c903258) -,S(e79ec274,337a82c1,c97b32da,8f5a8c55,7a159540,76c94255,8bc9a3e7,77769dde,9f23079f,22dafce3,54a4c175,d888f3ee,e527dad9,83d7502c,3b651762,628a06f6) -,S(fda0175,44f0ad3f,c8b9915e,8e0caa4,2be265e3,92041b0c,1b7d31a1,6fc101e1,424e9a27,85d59c6e,bc7e4298,1a505733,e4d49a76,b84a030d,db2f5c1,858902e7) -,S(681f01cb,5380cdfe,50314725,88bc830c,8327d8a3,cbcfdb31,577cf11b,a099c6bd,bf9d2117,cdc3b05f,9c06cef0,6fc9e757,59c02fad,8e0d98cd,794918,f39002bc) -,S(70c25a6b,2a2d2cc2,dd251f4d,9aca250b,d6fe9f8d,b9eff961,1de2095c,dbd12f64,c9eeaf68,a386b2cf,cd3f4dc4,793ea5b7,134dae04,d991e1f4,6b299a4d,1a966126) -,S(464ded2c,404b42d4,fefd5ea4,5f408666,3b466e85,fe8b304,3b121b8,9fccbb9d,ac113904,6ad3f613,23ad2d3e,a568367,610bb47b,e41a5260,79627122,105d910b) -,S(a32df72,48e79198,5d455109,a8c5dfc1,b7ff8990,1b5ce3f0,2ad2f134,13a103db,6db4b4fb,9d60906b,9aea2d1d,876296c8,cf9ad8d3,3e65e173,8212134a,4b160e72) -,S(fe49ce9e,7ee5d39c,97029774,64ec4fea,3ccb74dc,2a5c7fe9,a7695315,165179a,653f553a,35925dce,eefb9866,26155723,90bfc582,b4c426e6,3f58f0fa,3fe7dc8c) -,S(868b2e55,c895a7c2,4da24750,c126b10d,ec0f1a0a,2add5a87,8aa7316e,3354ad14,5e288874,cdea19fd,71f03594,1a6291bc,776bca82,804324,efb61f24,7ac299ef) -,S(fe0790da,90ae34c6,8ad3f1c0,80fc486b,d267ff7e,fd32d1ae,c63d08b5,8c098461,ad331393,de35b283,471a0244,422c6132,cdbfccdb,5680bef4,16f3beaf,6cf7177e) -,S(fe7fca8d,f4f80dc,ff16b196,167dfefa,42a23bf5,66837955,7f6d8279,6fe9a9d9,bbc4dd8a,d7ee925,dd80cb3d,681476ae,ccc5729c,e1815b1e,71c8f1cb,d8d4eb3b) -,S(a236c270,aa4ce20b,eb51b11b,511cf4c2,ae797598,e9f03fd2,3aa36858,9434cfc2,593599c5,75a7bdeb,41cc3ade,608c210a,8bc37040,fbb69f4c,4863a31f,2088f29b) -,S(d6a04a5,6bb8c27f,3ea8a348,538364e2,800472ea,d9e1f644,565546fc,76519248,4b95470d,50b97629,22b099ab,a5761243,dbf6e466,226e8e07,9b77069a,b542deb9) -,S(d09cd377,d64a045f,e1a76f97,4d701a24,67773228,3261aebd,74e02ea9,f8a30e7f,9f0942b9,2b702b3,d76ed2d0,1caf880d,41a342ea,ee06ae57,b90a924d,6588ffea) -,S(d030c72c,16d01a9d,6c2e5245,61c7e3fd,b9a469bf,ff0a7440,b2ed0ea5,e5d98b8b,c6b1308,dba4f981,16b60ff,eaea843b,fddeee67,ca1406f4,73db0f11,531f2c8e) -,S(56c456c6,d2c04a7d,441980ab,80b39a55,57d0c6f7,5706bba1,100c6bb1,e345a691,c5b2f0dc,2c735d0f,8ef10ffc,2753c2b2,825ce525,a0613189,fae34e64,26084819) -,S(aad5adf3,b505d1f4,28dd1b98,dd4fdde5,29d911c5,e0e5837d,75e51bac,308400c9,e94adf67,4f7994c1,123aa411,b790c68c,f55569f2,1df4b6e4,6afab87e,2777acc6) -,S(ac8cd8b4,dd76b8f7,4886b089,f18b4cb2,ca1d43c3,19ed034e,6b1867a3,5e6a0ef0,71d70894,f9daab15,7413f827,1cadcfc6,ffb71db4,9bcc81f3,c759d4f7,137ba96d) -,S(3964006d,f110fa45,409d7a4d,5996b44,93eb4150,f4217948,41dc5357,dc47ca1d,e4a11c6d,21dbd93a,f922a2bd,23f057e5,c2f24474,36bfd7d6,395a46df,3ad7cdb) -,S(2be10b92,27a312bb,74ea37b1,9bf910b7,723a1ff8,fb43dd55,1a0e1fbf,7bca56ec,19aa8afb,c886dc0d,293ecca9,4290b24b,755b2de8,c1dbc0b4,59052edc,c6df59ab) -,S(379c1556,2bd7f51a,1d219a34,dffc8bab,ccc1e417,1c38d342,a4c6325a,b5ad6ae5,47a1f28f,a6371df5,66dce223,10d95535,e7bc6734,7f20748d,b983fac4,2f185907) -,S(24054dc2,e675459d,2af584a7,d78110e9,30a36290,989dd4f9,914cf7a8,1fce9809,6572ae1d,3e05d0a7,1c4e06d4,820d16a5,3553dc81,a6f02a76,12b584a2,e57ae592) -,S(9812e6a6,f46ca979,ab7cd879,1023b32,913199c8,b850298f,a3bb4c8e,a02420a4,468f6eed,dfecd933,1bbaf36,986f9377,3afd963b,56577151,52a12b9c,88f937f0) -,S(46058644,6a348e4a,d84c928d,62c9de2a,9f6c14fb,95c83c6b,96203a5a,7f13c700,9dc55ee3,ca3d701f,e6759c20,3b18840f,4c873f11,57b21ad,90401e77,622d57ab) -,S(a8dbaf97,2d5b05f2,a44d862f,e4aed0fa,1cb877ca,639ac322,8e909507,bcbe006a,3db54c03,f082937c,4f98d38c,6141d0bf,253e6729,b83c9902,51ac4a97,176fa4bc) -,S(9b8b39f4,f4d91329,13324bcd,44f9846a,8b3019,22671128,74178009,391149fe,490a4f72,1c452e5a,88ffc693,90b0d1b3,4e4cae7f,2e0ab097,6b396a99,1c52c1d3) -,S(334681d5,a7ef46db,196404ea,9e501f81,7406ce24,27a64597,73e358ad,314615eb,2b23603a,1d80cd6a,9f04775a,52069de2,e328fdc1,37fe6b6d,6c165442,53ad6c0d) -,S(feb8e310,c63c6ebd,294639b4,a4cce42,bd5f8372,b7aeaa88,2023f0e0,29c32529,cb6e42ad,6a0cd780,aa57934b,86682260,68a45c63,bdf7e617,fbcbf86d,db43b213) -,S(f4a17bc2,c7334e92,dc923252,3b910a55,a8ca5cb6,2b3d93b3,fcf0f2c4,8705cb67,812b7795,1b24729,4b3d55a3,2f45260a,e7f4a9e3,d5cfa304,bb0471b0,da6e9dfe) -,S(8ec2ac7b,85514349,5496d596,bfcaaf4e,c330a995,f082324c,7e0479ba,4ccf181b,ea1588b6,7811d263,7bcb3bcf,5cf0bc4,70e92797,27b1c258,ce4ebba9,35250130) -,S(b1e6d61b,d9aecdbc,c9c4b6d,9e48c6f7,e4aa9eb7,7da3c001,53443c6c,4d4f19a,43af7b55,b2e2c976,8b1fdb34,48d6f339,1bc20aba,eccb1a3,5aef98af,b28cbf4a) -,S(4d83d2e8,210d47dc,3904a397,4db35433,1a951963,2d4e2e4,b69f2049,2f13b2be,7ed96c83,3874fc97,be45f1d8,8e5842b9,7a0e3bac,95400036,7c8572f6,3d37a6b3) -,S(1448e92e,fd51fc21,d6f5d514,35527f67,25f5c5ee,b0b29c36,b9eb6e8f,2bb20b84,248a338f,c8be83e5,2f91c9a2,2868973c,13336aa6,39e43f4c,ea8bbeb9,96e344ad) -,S(e23b03d6,9c2250ac,2cdcc7d4,4e0a218e,39d928b0,2585fe63,dcf7093c,924e4ead,8c69c7d0,4a8a4b7c,1997ef44,fadb04d7,80b91cba,13dee454,2effb8ae,71b9aea9) -,S(4cd1e35e,21fb3fe6,946a929b,9aebfcb8,78663224,da66af94,e5a722b4,32b5d7cb,6b1112dc,5e865b10,ba688780,32978617,eca892d7,730ca984,cba4ab07,7167e3bc) -,S(f3cebaf8,92cb7b0,27cb9212,3596ece0,bf25c6b0,d8f1dbf5,f2efb204,a0db647,a615ddeb,8418c013,91923b88,7bba5d3e,cf3c7172,efbdaab7,e12582bc,a968d8e0) -,S(4b8acd28,500bf88d,68337c81,33181706,dfe341de,7b1d5736,a3a85a2c,6d655e7d,be93d7c3,825a5675,84d6f76e,52f3b06,7b7c5d87,844f18ac,624c96e0,fd219bb8) -,S(8dc7ac81,d04e0088,63fd2de6,2cc68de8,3e567d81,85aebc53,d4771950,7ceb9fe1,62d4b64a,be7b1931,c47a7755,e25c803f,1eb14c89,2ee100e8,214b94c4,11fa9198) -,S(aa63343f,3078d48d,942bbbe,df4f2c19,a817c257,9003e033,7104e530,c1b89a23,277ef834,23a6730f,69c20f4d,9de94758,13befc6d,ce389bb,fe7958e6,6ea7b524) -,S(37de5061,9f301e40,8e9096c0,1a37df3a,dadeba61,bc217495,5d04d7a1,5121d30,7e7049c,33e40b96,6a136516,c005597c,e3f6aa70,d6db4c31,f5732fbc,e538898a) -,S(6d18cf55,506d59ce,a3e8cd44,f347481c,3ebc6682,2f91445e,11f2c0c,45eb83b4,e930e9c1,ca8b73f4,7fb9818e,5d4db8a0,220f7ba7,ce807854,c8ff2af7,b8a30cdb) -,S(77d85660,6de7dac5,dd4203c4,90152c9c,f70243fd,eb1d1c0a,5b797b39,16caa7d3,3f57cfe3,9b37d550,c9db0fc9,4b3c0e3b,1a2722ec,f920522e,8c37d848,f59c659c) -,S(5c2e69a6,c44b5bb1,c55dc8b5,6f9d4fb8,ea56450b,d69d9229,670e635d,f381bf16,f082049d,a69ca9b,a2821a8c,2fd0b46c,9ec21af2,4c34b049,f1af0126,75a3588d) -,S(329c01f5,66d925b,251944ed,92beb06a,aaacb98d,89b2aaf1,918ce400,b5a393ee,7e29b038,427a0fff,6ad50c80,aa49252e,e21c2c45,3d4c72a9,c3cafedf,faa57abf) -,S(4c2e631f,18b2dfa4,37ebb401,771d7b0e,b670f4fc,8546499d,f62b49bd,629525da,8a95ebfb,87423fa7,4c131432,6b7c204c,50c6c2d,a3f85370,1f789ca3,fe9a6f9c) -,S(fe121b93,d254465,c7f7cf02,ce10a575,d3808ce4,c6133fd9,392fbf1b,63d03fdc,33129b07,7bda4311,94fb997f,9443a0ff,e59438a,f360b635,2a80cbce,a49e0ba6) -,S(323ac27b,1cdbf3f7,74e20521,f1e74b8b,2cf8c5d4,4180316d,a532ae61,2f784c23,21156108,f6a64ac5,888b15fe,834ba9a5,c8489e16,f3d31197,bb296b2d,3fc3dc18) -,S(11478f62,fdfcb1e0,3a5f0ed5,ce0c2101,eeccbca1,e5934d37,41b1a8d2,7afd533,a9f79673,2fd3ecc8,644cdb17,6d11527a,aba8d0b2,985366c,70d96999,ec5f9153) -,S(9f0909b6,c9d3c1ad,eb88acf3,aed5a6a6,bc8d82b5,767896e5,e7343efc,20b9d078,a5161ca6,c5c95d64,dc663e30,b8f65234,61a579d7,b99a57a3,3b0f3844,e47db181) -,S(4960a875,32a9ad42,299d8cd1,a1af80bb,2807acb1,b52f1711,c55957d3,a64a6b9f,578e51f3,f1b46628,eb48f54a,93f82f24,4bfc6202,eef77dd8,cd6b90b4,de976625) -,S(675c29c2,bdb265e,5490951c,bfc9f73d,d142d536,4b5ec668,54b582f0,5d310354,22d1f669,3d82de84,202d4f9a,186bdfa6,8cb8ad5f,9da33a49,83229047,e08bd6d1) -,S(c4096cbd,6c75d0e2,6a922177,916ab32d,a9053adf,ad849d36,f65b7c9b,107ce605,5f236b47,2ae3c979,2ff61efb,9633ae05,b2b97e51,24a3c2,94f5be53,95c2bb46) -,S(9ea0d341,ddd05401,f01205ec,2c754155,b1ddd460,1fa3789,dd80ed9b,3b905c0b,3bf48101,97e7d0b7,6f3692cd,53989764,ba7ce059,953f7b71,7e615c20,da28e69) -,S(bdebbed7,84bffa33,72a6edd2,d9815b0d,637367f2,de3768c7,b4dd75a4,32fb92e4,5ff3437e,b62a9b62,dc16af10,5a20941d,297a431f,ca2b0067,6734c4ae,cfd0b9c0) -,S(a486fa44,b46e34f2,d6aea82c,8f554210,cbfe674,77b560c7,bccc7d6c,9e910932,1ab7e36d,8a15e284,8a3caa0,f54ca555,b8ad5baa,7f47fca8,3231c822,f897317a) -,S(4463a0a5,57a1a926,aa204376,a20aefab,66e7abb1,18c7f769,fbd1a7d1,29cbba08,4a823aa5,ab7b602a,704f01de,20b8ad13,7dc08152,25ceace0,9a9dab69,d034af0d) -,S(d6e08a4f,c45e8dfb,ab713584,d91d1d8,8cbdc5c6,2eeb4b4c,593a73df,4d825ac4,2cd85bb4,77c0d0ba,5071ae8f,c0fe2dbd,8be98d9,622fe506,c59800cb,5eb4c55f) -,S(b626e299,2a69cad4,e6076dca,29bbfd34,546d31d0,a4f8b656,a433fa87,f96a10f1,6df4b2ce,ba919268,f1568632,55e27655,62ac5e3b,8cbbfd34,3c656f43,43cb5bc6) -,S(3619e6eb,74645070,b2dd6196,5fe4d25e,25a4dfeb,619e3b05,7e31a566,947139a5,964b8989,ba156121,9d36c3bf,29467c7b,79940c3b,450c1431,1aa0d725,1282093f) -,S(b3529b5e,6718843f,c40a3a65,d5330961,41e5c060,e326aa84,7ccf7f48,c8bda2e9,49e6e0d3,7ce1bf45,e9c595ac,285becf5,31111e7b,2a67b057,9d4fc552,59c1b935) -,S(e51f0067,5bd7145f,fcf85527,dd247ef1,4a199778,94035598,d42afdf1,2fa9e05b,d59aaf3e,8b4d72eb,4523d5fc,69b047e5,7d2e175f,30eb6c8c,ec729cbf,c1b32666) -,S(8a87f066,f64bc468,d225eb6a,a0a7b54b,91c930e4,d4520720,1705f831,cde79b28,a92a5d95,e0057c95,b219062f,5d0e4277,249c34ac,6255113b,b5eebea5,66800227) -,S(d8a81015,aa878ee5,a69c771e,bf88daad,3a926afb,b8aef632,cd7d987b,fd310b06,af77f7e8,f276ed4e,963e3a26,2f3942c7,ec9f31da,199ead3,d5e5f53f,e20acbdd) -,S(88c3fa19,4f3f4d93,dbe5b8a3,865d28d6,51c9abd,519af4d2,c3b743d4,ce0cc5c1,104caf7a,f9ff822,7b3671a7,e7745bee,26b5deda,9982b9d9,a9d648e0,760d8f8d) -,S(f8738725,3434b0ea,f05e9c76,3c729a8a,22070111,6c5a6484,5532c3d9,41ce648e,a8b5eed1,d4ee7913,b69f6627,d3e1be,4c286e15,78167201,46fc9e21,786f7bd7) -,S(5fca538,5afb021f,94cca826,5689605c,7b35c8f8,dc8fef60,6b18420f,909acc33,1d7fa51,f5c28bfd,eb1f9a52,723eb2bf,c5b4d078,d5d4b639,2b791af5,d5b2b3a8) -,S(47484548,d4b2acd9,bb2cef9d,bed4bd0f,f1fddf4f,e1561a51,891464fa,cf5007db,ea61e154,f011cfe0,46fa2539,7fb444fd,b93e223b,ed882bce,3ddaa3c8,328f44a8) -,S(331f17ff,b14d43f,ec69a6fe,b41a8021,dd8ef56d,2540234a,b466ac85,e6c5b8f1,ba20bca1,8d774731,b6b64a0f,8a19311f,37d8c061,2c4699b,68d569b0,9eec144b) -,S(6aba62d,200bd2c6,4ab88ce9,80530e56,5b8971c,f9c427f1,5e9b146d,dbdc68ce,e4c936d7,d7d98919,acd26ef0,cf071f2d,fcf65fd7,78dd8c5b,ab026,e9f832c8) -,S(c76b6c35,e72fa19c,621022b4,d9ec6ece,c0cfee8d,c73254fc,f52cbc69,23ca19c5,5b0ffa7a,48ee8599,9b74d0a1,d7fa0289,b49dba85,7b21bfb1,ee7ba831,fa13efc9) -,S(c056ea3d,43f33df9,b01590fa,429c14a6,aaa438ed,415254a4,4a93854,ce1bb77a,d5b194e3,2337a9f1,2c479e7f,576a571e,58355a02,8ba0231c,c337b8c7,eb3dca7b) -,S(3d688ccc,8ddf0ef1,137bb897,e6b8f3b7,7df652c4,93cac3a1,47e88b3d,bdac938a,bca94788,4d7ae1f2,960daead,111558f7,38b6bc9a,7af3bb4a,691af22d,4d5879fc) -,S(4faffaf6,69ce1180,a9145f0c,df6fd834,c59d7a9f,5f2e49cf,3924b33d,8d2a179,9e015cac,2dca2ec2,5580c16d,8c910abb,dcbad872,79bcc485,b71f5561,60159d2) -,S(47578e3,7cd7eb78,6b5a44eb,3decc7c4,e8ba0c7,6699ef61,4ac30579,a24aecad,948ac817,a6bee00b,c68eab83,fb628ed8,7fd0066,9ebc8569,45eef8c9,67171651) -,S(9aade275,3eaa646a,24ad1a35,f74887db,8c72fda7,77b59dfe,103e1a95,dc618836,b651c384,8f4625f3,1e6e7a05,c94483f,ceef2fed,dc7f4256,87e0373d,d02bca96) -,S(b1b0c3e0,b1c6ee75,55a81852,447b2bcf,321c9b9f,629caf9a,276133af,63aed711,493accfd,624e6ff3,dfc1d0dc,aff17113,c2c74167,58cbd571,759bab24,300ac827) -,S(c557758f,b192a058,eaec5762,ff391a9b,2a0ce462,7bae01c,156dcf3e,bf2a8ff6,1d4e9b53,d209e195,9f10f671,b1bfdbf3,98921284,a7719766,39947969,6d1bd3b3) -,S(73522ded,5120ed4f,b49b5ca6,df5a1b6,edcc082,48df4d07,cc9ad923,2b7b5e0e,47569d94,cdf0270e,d1d299ce,d5bcfdc7,7f87db4e,c9725a96,e4388cf8,dee08d74) -,S(16571c0d,66328963,2a3ae46d,fc2bee50,fd6fbc0c,f0ec73ad,72bb9c2f,e8323506,65de9d86,9e001c60,ced57911,e7ce6150,a936d684,d759f143,d2224448,4bec68d2) -,S(f5fe5564,2eb630a5,c860cc8d,7c9ef86d,b1810d2e,82dcb343,dbe2f958,98e5f090,5cee7a1f,bea9dac8,ca340dcd,fc2c097a,eec2dabd,d7ed7504,e20c913e,9fadfa87) -,S(ef09db32,70d09043,43da67a0,b87cedaf,7aece017,58d78591,8814e3ca,396e3592,5934f805,ba246e9f,965c6161,cefdf4e3,7df14271,2ae076ea,80ca239a,c7b675e2) -,S(886cdbd7,27d2f099,9852b102,bf201ed2,5e174622,f974b0c1,3edfe523,373a54e8,dacb328a,7fca6e5a,e5351825,564e4f89,5166f687,38d46142,6eea7b09,dca73b2b) -,S(b7d86bcd,4f7bf2e,8529ff84,88d9f3e9,62071308,9bbd91f9,6e4ef82a,ce237cff,c6b0aff1,375a547e,a8546dc4,17574843,3acf2a4,ed0d002e,e32fd88f,3b702f0e) -,S(d7d171b2,8132ab85,30791059,395d94ec,c24f5e99,67bc6c4d,22bfc7ba,eb388c67,983770e0,2421e2b6,55d3c135,1bb39bf7,7be39682,97088744,bfe6543d,dc1a8f8f) -,S(ffe712fd,881e30e7,229f1cfa,833dad90,f01a1896,c1493502,a429080a,9794b1be,f4299e03,75d084a,10b11ae5,8f2fa2be,f18b037a,53165586,cdac18ce,54505da8) -,S(563c92b3,3226951,cd7cd10b,3f7b35c7,dff3f0de,6f03d66,9f664655,57d13f7c,dca1eef4,85bef41,80b0ccfb,2416f948,9bb21094,854f5f43,769cb37,33ec10c1) -,S(b8e76ef3,3a2cebce,614056d7,efa47c15,dd52c228,66a7d3dd,9a0d4d64,68f32437,4454e79d,652ae799,a3a539ba,42619a1c,3076ccc2,109dc4a2,2aa41a28,918651c2) -,S(36db2304,f60703a2,df2e429f,b8a99841,7b4a4f3,e08642d2,c5675460,aaf1c971,a0536e8f,5cc30aa3,d9b859ee,e26b1abb,ecf7f9b4,8c8fef0,f842fc9,a684b5cc) -,S(c5d4e51d,1521637d,d6055e52,9e9ae2a4,d537c1a1,b7c6a314,f9d558a1,88d9a5ab,c841eeed,6a13782c,fbf65b08,c6570994,aaf7093c,4b48ad0d,e04db33a,6feb3f6d) -,S(50c03dc2,985859f6,ffb79ed3,f635e17a,b0561533,600af220,7cd98f9f,71c4bffd,c68c8797,a7ed229a,f59a2bd7,451c748a,5c425528,8b7f6b0a,68b64a77,d7137720) -,S(2806d84b,3e7e6f9a,2e10ae5d,cf5bb0ef,98560691,71d31ff3,3645346d,f08333ef,72f23443,38e34ccb,4ccb5ddb,f3a6b58e,bf8cac26,4243785e,54a9b503,c87b429d) -,S(40d70ddd,1ef58dd1,c43e33c6,29840fee,82bb9c1b,e222b53f,4c58952f,388790a4,9b1a9d57,b6dd9932,338d170e,af4d5516,e654685b,3946930d,96b2a1d7,f70770d5) -,S(8850ec32,4e71213,bd77b193,ee21da82,ac733804,17983905,d0156608,8b87c835,aafff7a0,a9160b91,92df58ea,a65c0716,961480b2,b0cb4d3a,7d637f77,ddc160e2) -,S(54951509,bd7c29f4,77f9d4a6,2be485d7,de291b0,6a308bd2,c240cf71,50ad6e8b,2fdb347c,f2a23b9f,a3a45c76,44cc1fa9,b1d8f79f,77c02f27,f136c732,c7ef2722) -,S(9f5ec355,cdf8eb4f,be5af1ab,70a3e7cf,1c3d3e8b,e643621f,acf8f69f,af7e5d44,b203dd5f,b38b3550,6fda94b,ada1c4bb,12b8be5e,92bf8a58,4886f2ca,19d3c06e) -,S(812e4a9c,1bba9e52,8cb5e606,c8b326fe,8b72f0e2,3062837b,bdf371a2,2ec0b3da,2ba7b5b7,14a9ae39,c62bd36a,1ed00135,5d98d248,9ef90f24,d10d1c58,f8e222a1) -,S(e6035ddb,cf85616b,540ff16e,cd5d7fd1,af52c6f6,2a26ec36,c5c1ca86,2a3d924a,a945389e,f687fcac,6f918718,a1f29f19,173d3104,69c5954a,d6cfb5df,f01eec86) -,S(d788a5e8,d771d471,b7169693,86b2339b,2643f129,a6b50bc6,321e752,6a033446,34b85622,5095783e,fa57fe32,a7d91b65,c0c9a42f,79fe30e0,b2598967,e97d3990) -,S(663733dd,29374f9f,1db5f11,6fa32b56,c8ef42f,706bd802,5615d4a4,77c6f41c,3585d45,3ae0fc59,1614e916,a1400b79,85b59f66,6e2553c1,394ec26d,d078676d) -,S(5ec6e728,5ae1413,3dbad4d1,19e2e3d5,6affda33,356146f0,a5ab023d,b323ad9c,3dd241bf,cfc6301e,29cd609d,b1a0fca3,d35a56e4,668de9f6,45c23d69,c0884579) -,S(f18fc442,1fbb66a2,7c336647,1459717c,87532be5,d4416cee,e4a674a3,2cf8f3c5,d38a0881,3bb33df1,fb4e83,6686c0fa,26847e5,f7580de9,b4f229cd,1359d560) -,S(818f549e,d9bcfe1f,14b8d336,21342465,7dec0dfe,eea1d719,20622442,39f5345a,37ce611f,cca2f448,45c1a8e9,d7f4b3f8,48b24c5c,2b9f5368,8cc2c8df,846602ee) -,S(75e2c791,f98e3fc8,2a74ee3a,532e8796,4f4fa8eb,6421aa64,17a5b00b,1edce942,51f2373b,a4951362,68aa17c7,1160855c,7c4d37be,222a8b26,f2d54cd5,37e5f6b4) -,S(711f8db6,4c0c6d31,daff4ec1,f9937730,9b44de59,9f4b9119,9ca6836e,1e3954d3,485955e3,432ac82d,f3170fcf,7b3519cd,6e4dfbba,170bbeb5,b75e3e7d,70caa4b0) -,S(63502c26,6f755a1e,4be2104e,e8ca9c2c,5216f50f,e21e003a,16071bc8,df3ba6a5,a5c829ea,c8fc3f4a,f55075bd,afe77977,3954b88a,f1f3a8dd,90f28aa1,49bea942) -,S(2a677459,ccfee070,1b5bb82f,d2ee57e6,13f5c3d6,3927938c,92d10954,c2850872,ff6e9798,5c5db0b2,9bb1cbf5,db03e0c4,401bbf28,eb39e053,714d5c5e,ef7cbe71) -,S(68f85f87,78fb69a7,9db4a22,3d7faf95,5b359bd0,5f230d99,f051b008,32b52cbe,dc2e949,f4fc3189,c4f7b771,f8b56b85,ef9c65c0,b3bdf89e,405d5f3c,ffc92210) -,S(7ee9d5b7,3b542036,509fd8b9,de590b24,9e9883c8,6f4bb90e,1c2904f3,d2b74ade,98122413,241cf205,f91c6977,b925ddd7,4920636a,9dd67828,2c30ee,7343e62) -,S(8447b090,cdb19271,db368023,d40e520,102b5d04,79eaf391,3817553e,24aa33c8,25b43fe6,55a27481,c02eacd3,9025a523,121d02a5,78896a78,c14a8c21,f7c0bdb0) -,S(316073b9,3f1550e6,b7951f56,90c5ef3b,e45e622e,77a2f268,c89a8b6f,2816a645,557ca5ac,2fc70ce8,c3e54a4d,b31d5c77,a1a6f38a,18646caf,6a52db31,947624be) -,S(fae2312d,a2ef21ac,358fe949,5c011b18,cdaa8ef1,c99284ae,5fc1eb77,4836d6ac,6f3bf661,2d99e865,b0cee7cb,3fccbf08,aa948ad9,b29b4b8b,54eee8d6,3f0b76c7) -,S(280a2bef,5588dfdf,b1e1691,d3162aec,7d4c72c6,b76f23e1,2f8ce783,54f839f0,f00ded1b,c31a9774,a87be1bc,7e440585,b2b4ba63,cc0d9c73,ca7b4873,93683f72) -,S(3f43e77a,9b7b92c9,92b7e5d2,8c75444f,4d0609b2,8aa65ddb,86bf6ac0,bf7ccdcd,b3117903,bb3c0a54,bc6bd6b9,92b8d85c,ac267855,50075536,6cf70a84,4c72a2d6) -,S(3a0afdc8,387bfa34,87e53929,51e10e,9535500d,f6506296,46df162d,d469f2de,75697cc8,f0f690b6,e1f86dff,3f2ca53d,907d4cf7,c8ff324e,8b4187ac,c9bb29c7) -,S(3f972b64,209f723e,99a6e7c4,a72072a0,2789d0aa,8a23d660,949ea417,7970809d,7a482428,7a6bfd9c,afc26e76,9a02c5ff,9a7c053e,e63f2342,b32a4f84,42e47d15) -,S(938ac0f,fa73364d,11df1ecc,4b84e3d1,c21ff85d,71f404df,e8daf4a,e889b0b4,a1c09ed3,d526b381,dee8820,eda06a10,4e968995,64cb604a,63fba74a,45be0312) -,S(5355ed75,2993e74c,275eb9ed,3bd34575,631c9b5a,64e99071,8311ec8a,f4e28bcc,bbb1007d,680aaaaf,ac10279f,600f1851,c8188547,3091a40,ddf7253c,fc6ad088) -,S(880e32ed,70ba76c6,d83bda46,a4340646,b033696f,ab62e457,4e989311,fbf277b7,76feb2cb,8d10d5e2,406763d5,f696686b,8dcdaaf,330e4e7c,623cc7a8,6e0410bc) -,S(daf778aa,a2755b68,2b8beec1,14b74e9c,857ac503,daad6bee,bd6d11f1,8f11aa8,1ed85c62,710d3017,9f0f3024,d6ed6976,e38325f0,92981c88,fd4982ee,98a5f428) -,S(e5c3e9dd,75633d27,d19c0a4f,f3533f80,9a60b95a,42c8c464,1cf7abda,8fb474dd,f1e56af6,5c5c087e,ab303699,f20bc9f,71b7b7fe,16332afb,2517b241,8dfb0dfc) -,S(5d403f34,ecdfd870,977f3bf2,ffb274c9,6859c20c,8cd7afd,d116837d,c0096973,6b5be47c,70246cc5,9781ba70,71764d72,2335c334,443e5e4a,5ba12939,d8f6aeb1) -,S(50ba053c,25511f71,b35b4caa,c990ab27,993bf034,f3e55f81,3896458b,5e246b12,d2f12a45,5c7a3170,67690399,3063dab0,9f8a22a2,bccbe5b8,8a7fa2bb,f2291f63) -,S(385a80ea,ee4aa9ed,a07898f0,b3658793,9f290622,399c3a00,b38bf02f,66629cf,a543320b,d72ac6e5,d750806d,6a90b8fb,8cfe4902,46991eb1,6e6a6974,befcd50) -,S(98610b9,904ede38,6e69de6c,3d40518e,eaa669a5,23620a9b,276e1996,bdedbef,907755a2,eb6aa100,d0cd0c89,25b5ff8f,b88f72d3,61d83315,c4ad0d94,8a06b581) -,S(83f10807,d9640d3b,dfc7b0d3,dcbbf6a2,19ae215b,4754f29e,d4579999,191b7fe8,f62d231b,5095d6d2,860e69c6,509de2c6,fe719e4a,fbc2b5e2,489a6f9a,7293364) -,S(51d22293,927335c6,2f82b028,52759fd1,e3f287fc,67b6059e,74dca17d,4fb1c246,b9b803a3,b5145b4d,188b909e,23c8b126,f7184bdd,3128587b,e05219df,6c63745d) -,S(be6a6342,e5783d43,d2691945,826c37c5,3e8cc24c,5a09fc70,3689def1,4f465006,81c718fc,3fc15279,da9efc14,13ddcfd8,81bc7e4b,1c36004c,2008dba2,7c7ef000) -,S(f21334d9,c36f1284,a4bb043b,58b27070,448681d9,a82ae81,a4e8f226,bc790036,44851,3a87fd30,453dcc1e,b21e293b,f5f143b8,2cf2708e,428f4753,8816eff2) -,S(1558c4e5,af34463f,810cb1f1,b73bd27e,932a832,9253e2cb,419eafae,c9730508,cb8cc650,25e14132,3663f3f4,1a75085c,6921bb37,428a149e,2dd1fe4d,f4c917f8) -,S(1853a32c,8f6020d8,1b4d3596,a88e3825,b575a4ed,99072e64,2e090a1a,665d71e2,8da2a31c,b170aea0,e364aedb,b1861fff,eaf26888,b29405e8,9e3ed982,a03a8367) -,S(ef585cbc,f0f03bec,21df60db,cfafa9dc,2da679b4,3bdd590b,8cc35388,cccd323d,2bc5e203,aff91f6d,38592e07,82813905,f02ccdba,1daa7acd,d93f6d80,78c2f296) -,S(3f4c2e37,e1ea68eb,befd9971,424b3c7b,1fa45864,e0d13471,a1476808,b2fd5c14,678990ab,3d283b3f,aaa665b0,4f329b51,51b9c17,b54385e3,30de36a4,7e0eeaa5) -,S(2b001b8a,d557ac4a,181cb20a,b3abf2ac,59fc9b10,20b5533b,621b4119,e421693a,fe4f3007,f8d19db1,73e6f8c3,48b2525,310a328d,2ca0c675,8fa29723,82c6b94a) -,S(6589d1dd,7d5a08ff,8deb5b10,81fb0ca3,79c90d27,58ba0bb9,8d05bc93,452cd229,82409480,ed842993,4bc8dca2,3e000fd5,fdc5475b,192bc7fa,a1179165,9a8149a9) -,S(c233fd0d,f5d3835b,8e855316,276a6a90,ab4377e5,a3a3a8a8,3b89f0f5,27950a6f,8fe8e0a8,775a9a43,12cfbac0,85aefe06,31468031,86b8b84f,49422392,b4f6f3e5) -,S(82731a85,2a848eee,d6ee3f57,f75a2bfa,a388670f,89f6f6e7,b65b13d0,764cc14a,c00c509a,307c5e87,f1b09688,38e34a21,1ffacc9b,8a7504c1,2080e4cd,39117583) -,S(e21387a0,e5d8b1b0,5aab5150,122942ec,c9dde3b5,53eac977,7eea6d0,6d2a50d,c74de509,f90d93df,343c920,74ac5dfc,fc81c95,93354349,bb2810dc,8db0ff83) -,S(180871fd,2fa443d9,c5b5c341,4d635b8e,92780fc1,6d04236a,bc9a49,5b9fdc25,d66c7150,6008f37a,422014a8,bbe025c6,1f25e636,e2778146,59985003,ab14d120) -,S(b5a9de7e,ed112a8c,1ef29a9a,31156b90,d64dff93,4d83fab4,b44d30e0,bccb2c42,5675a679,a81c3faf,3b0afe66,ef85721,30315ccf,b0ff3d91,130a71f4,3539db38) -,S(9acce472,61f1e50d,f42baf78,c05a5cf9,8ce5697b,6d3b4d,40d011fd,aee7d6,fb7c413c,40464c69,e5756830,4325a79e,6cb8c831,add29e0a,95f88feb,9507a05c) -,S(f80ab79b,7bef7712,2fc7bc4b,2193deed,916796e3,67d85100,a02cc0eb,8b574e5c,c6d4d03f,842d8b25,d9b5834e,d6cdcacc,3a1ac585,b5d22aa,c77019dd,1d5c8f6d) -,S(b431e355,cdb4230c,3005845e,f60b24d9,25d81448,ec161aee,faea1f98,bc9366a1,ebcdadd4,ae230a14,382ddb98,552b6e69,7aebace5,5cc7390e,f69d176d,da41c1cd) -,S(7aa60b9e,8c93a63,51eb686f,46dca4e6,efe56edf,6c2089c5,93f6a800,6e75f1fb,4c81e2,17700bf1,e053e389,2e33e694,cb424800,b4068c98,328f00ef,5fa0347e) -,S(1a88250b,3aa4243b,7441d1a4,da37b4dd,d304fbef,272f696b,a72e7610,1286b30b,625b9d05,57d3815b,e06d8cb0,f056a9be,b33b7658,f459b3fe,3fd5f4ab,69b7a473) -,S(5b524eeb,49fd558a,2d34db23,cb5dcee1,6c4ca47,1eba9966,82dedbc3,aa2b57c7,2d5c2c97,56b7ce1d,735b163d,56e02bdc,25c8b227,2bca2d5d,bf252906,bb8ae50c) -,S(ae60e777,6d9fbe79,d24cb8b1,f756098,191550d8,433bc7d1,8920584e,7676d2c5,430fe986,73772472,ca11be83,eefc8678,b76c36d4,346a311f,fff926fb,158d7784) -,S(323a5e3d,9e29f668,d460b081,a5dce6fb,53e8d730,9c42f105,ab4f812a,62efb9d4,2b457b3,69483f42,16656d1d,3b5ea9af,da6216a4,47661830,c2fa56be,804776ba) -,S(acd1b5b6,591e552c,864e612e,d69429b2,b3db8649,7a5962a2,a8b36511,7a7c1c9d,e6131fff,56f6900,926ba772,92526348,67544d25,1ebc4fa3,26562190,8e6e88b8) -,S(6b4e2c70,817852e0,2a26286b,155248ce,f2e61e60,84742cf1,14ebf74f,785b36f4,8400951c,7a529bdc,2007130d,1cd5297,7398f7fc,d66e5a1a,1e4e8644,e5b893df) -,S(c2b2c727,d67b0a46,1f44cb91,48c34744,4e6a375f,80a817c7,1517969f,8084ab31,fed64359,ebf37b0f,998aa251,9c281fd3,a52c47d4,89051718,82481fae,c36d5f59) -,S(3385eeda,b5b2bd94,f794609d,978a0f86,2ec56422,bda0ef71,2207ca1b,904f202e,2808d2af,1db8a8ee,1c5975aa,31a9f441,b12a2186,746a474b,4907bb71,603d7443) -,S(800f6cd7,f2cb437b,8470c292,3fab4786,edce15f0,d4c52a82,33519c07,14c803f2,981f2e3e,ad11aa0,cde06ca5,9b26028c,23e0a88c,ec397734,ad0152f4,d4a37056) -,S(73aa0bff,3a9f286f,d3c103c6,d7bb6caa,ebfaf4b7,614f1f32,4741c600,eeaa2f3b,30bc529,81a9b983,cb89fe73,dd8bce7c,a54a2e3c,4fde6846,701f1da5,18c6f7b1) -,S(9280fce6,ab5c13f6,80bfdfa9,c3e7612f,86380498,9bcf29ca,789169fb,a178f2c5,4b96ecdb,c5bc2e3b,2fd397b1,8f7f5bb7,aeb6a7bd,db0a3b23,3e74f7cd,ccae36bb) -,S(72055c4b,bb50b9ef,b589be16,270d12ea,9f438780,e5eccb81,7dbf69d,a66e03ca,aeaa257f,c30a77dd,58574693,51a8623d,985ad705,aa1fe3f9,8915a6c6,f6bc7cb) -,S(f0f3cfd0,c771e3db,ba687c7,3fa827cc,eb8e887,12abc8e0,3085d047,e7c1879f,2c612e7d,8b744c54,f8f0c4b3,24fe10a3,1bf8aa5c,cf6e2e20,eff98153,a4936b33) -,S(97c78b65,70b0f270,6fac8fe8,ea4376ac,d8b61177,e5e7b3ec,67a7af9b,e6f5dcfa,1aeb950c,fea95858,a97da765,c3cb5941,1334609b,347c4daa,1279d58f,3be14c3d) -,S(b39ffa1e,967e6fc3,d493a9de,48b077fa,4b7908f5,33a73eeb,9b5c9efe,9e509e69,f55f3951,81ac72cc,d618c00,71c817e3,f76c302f,11219e16,f3b40e75,ea65dc05) -,S(159b9f7a,5ff27c4d,1bc3fcc4,d91b160a,1b2a972,8b1e7fd1,7351c663,f8e7baaa,b0aaef6d,86c54ffa,eba1c7f0,d789fd41,5e60127d,578c2697,a8380b7c,a4c4360a) -,S(25810fd1,8d4a4b16,c7d07a62,b626fc45,6dff76ab,3c1361aa,f729f7f3,cb85e44c,f4052325,7794bd70,ad295526,ab4b8b00,9252dd5f,33578f44,2fcd2219,2f6a2d9b) -,S(27e20a4d,5860a328,c499864c,9075881,eab36291,2da641d,6e1934df,473352b2,c1598cf2,888cb50f,e270b490,503c11a7,d3822a2b,e86a7b,65cb9499,3b45203) -,S(483f454e,517a94e6,6708f465,ba217b60,6d684a68,4d9472dd,685f3bd1,341448a2,c13b3144,d93b9a36,45d23346,c5dcb70d,d338d06f,f0c22aa8,2ba68a61,7f9ad11f) -,S(4f47b2f6,31734aa6,5ae4c9a3,c1532f2,67ef068f,83a4f266,e2e0a59e,be04e6e5,58f1f34c,f11b9cb4,5d33ebcf,3edab72d,6824392e,dd547a27,c0134d66,58d99d2b) -,S(aa78eb7e,835ce84,b4f1774b,8e810cc0,d6f42a2b,11c44574,24fb6341,7797db07,39640139,d957d47c,59cc7541,d3f72e33,ee9ffc63,2171311b,cf493ea,185e743b) -,S(d2598985,83c00560,11dc0655,c37580b0,31a3f1f6,aa5f5944,17eb0ce8,cc033d49,3641c973,9de8818b,a294622a,2dabe172,b6a83006,4d04ed8b,c841d11a,5af24b08) -,S(4f023ba0,ecccb74f,56f38f87,7435907b,f2d2b85d,59f7ffaf,48712a48,55e26634,f80efc33,b15d5125,b8fc35ea,393b6c3f,a2ae094b,86a6ee95,bc48295f,b1a6a456) -,S(9c86f08b,48abd097,7bfe13cf,a15ac8be,8eda4128,f7c143c6,70bf7e2d,763a1589,11511f87,e9ecb88,39eff453,d29d4db2,17d4eeda,c8468a17,1a152f15,c1c2df45) -,S(3808718b,72e95cc8,fffaffce,cd57e269,c5e6ac77,69d8120e,9130d8b8,ee137576,f40ebdeb,cf5eb722,4dae59cf,8ed8b58c,c614a61a,9e3ccee,db789fd3,31ea728f) -,S(8defd15e,399492fc,71c80a1,3eda0244,eb349f47,5c7dfb42,55dfa752,fcdda3df,d3dfa778,4353d0c3,b4fb0d19,ffc39631,a01786ce,e3b0cc7f,f9e4c5f6,7bf7a771) -,S(8dac8d42,5ac1d07e,3a805248,798fade7,ed99f9d0,c324bd46,6eaa8aa7,dc24bf8a,f232fdb7,923234fc,d8b2f097,d354dd6e,62e9d926,20d28087,d6410b72,aaef8009) -,S(87ce6443,f3bce6de,287178b4,f243c3d1,e45d26fc,6f811d35,329cac04,7fa90e1b,a897019,62414ab4,c582799d,77edf3b0,f0af0d4,8f70e875,fac33e95,39724138) -,S(bfee6bfa,bf2fb77e,9eb60a3f,8b7775ba,124a21c8,741af3b,d22966c6,a8fdf08d,29a1c399,541e4bf1,7f26f215,52fc83ee,cd2e8be8,40b83fa6,9c9ce5d5,fbba76f7) -,S(c30fda5,b553a800,2341a553,7aff72b8,44873af,8381b41d,aef9af2b,5cc2bec1,5ce3eab5,87d88d64,fa44aafc,ce34046,8a96f76e,65dd562e,7d14153b,439fea6d) -,S(5e7151fd,594119d7,c5cadbf,e1b419f5,4d922607,728d70a0,f1dd4d8,3400ed97,6a8ceea5,a51d4a7d,62d36816,ecbdd75e,4c64ec96,6257820d,73bd9531,ea108917) -,S(a9c8eb0a,66cdd5f0,f33d0620,8525225b,e974af7a,b50d47c0,4bf690db,ec86100b,f209cb9d,898731f3,b02a24bc,ff290cd4,a4371e88,f3aeebf3,29c9e1b2,8b8e0a2f) -,S(955e79d7,93669150,471b1659,52ee6121,cb804373,5faf653b,9468511a,e3a2e439,68daafe3,2a9b67a0,10ea3bcc,1a56c7a0,2e82cddf,120e6826,1de0700b,cf930d06) -,S(22d27293,d3c1cc6a,5b3bc70b,3bb7e1d6,bef24805,3c8685fa,c192b409,dfa34a71,c74b44e3,4fc855b7,53c4e42e,740dbb59,4d5d76df,b39de389,e6c837e9,639b3357) -,S(d19fcece,f74b1767,4e9d91f7,1487aebf,70d46e8b,3a037835,b2f4e8c4,2137abc0,5b904bf6,3dca0981,3ce224f7,494ccba3,34ca9fe5,f365ca83,fe9adb6c,4adb7580) -,S(6aa1722a,adc74800,d6609113,6bc6a6a8,1723c36c,524a873f,2a437c91,c2336899,8e97004c,df495b4c,63164058,321549ce,3d9709d9,ed667c36,9a4f1ee2,d6319d07) -,S(79bd3623,9ee4d220,12d07262,e96ad186,b16e3b6b,720d052,f736f851,b0ea6efc,a4b43db,f568cda4,1dc972c7,1c7c92c3,6a31166f,ad6b80fe,42df4dbe,f418729e) -,S(b5e02b2c,146337b5,67583c5d,3690c0cf,a1c7d820,14028c9,e401182f,a4f16ce9,4b9646be,3facaa70,e793516f,a0e8a142,1a819ba6,718d26fb,938e2795,9069e0b2) -,S(8e33e271,de2deb4d,6444d64,387f790d,14a2b685,4b38857d,d05af743,7a7403a,d82d53a2,c7a4a1dc,eaa011bd,3e0ceb0,e08d73ff,fe9d71f,c913d6e2,89ecc429) -,S(4ffef442,77dba780,e5769b73,feda37da,abd6ef6,2f5ec36b,74593ca,4c19c2f5,a8a30857,378aa0ab,9ef6162c,fbb09f9b,796755bd,67bf9d69,4a186813,d392f854) -,S(878b652a,633805c8,b58b0334,11b9246f,f7e42ed6,ecba6bde,fb737126,e9f57368,2cfbeb3e,d691158c,d3ae71f0,b4a41d42,148c9711,d274820a,d541efc1,56e85836) -,S(ef9a6a15,aee2aed1,46b99ee6,a79acbc1,a0aa0b2f,1b082783,dd40b106,9deb415e,9909e2ba,7fd53514,a1bc4480,2b49c7aa,cffd9cda,19c54d82,6d9bd08e,49e97240) -,S(d5c248d4,1551d230,60835885,5db0ce8e,c7814e18,c2d548fc,dcfac207,645bf37,f9c5e89e,7bf01f82,8cb78c88,c14d50a8,3cbeb45f,82daa9cb,3c3804c1,15a36f05) -,S(edbf25cc,a526157d,9676e614,81455682,6dad0c0f,96ec289,f2c5919f,57227d1a,6845488,be056456,4a833c13,70d37257,d0ca701e,f6e574c7,409dae02,ee99554d) -,S(5c12026f,b8e2e376,2521f5cf,cf9286b,14be80b0,dfcf378b,26fe6ea5,4ccf09bb,3d98d5ef,4e2c6528,7950154d,581c9a44,94b81a50,40ba9047,1bfa6758,66daa596) -,S(c27e6243,5056055d,614dcef7,f67338c7,ae728bd4,af3970a0,b434d2b2,e48e2d6d,76b586fc,703cf946,f78839ee,bcd28c56,9e372d97,856333ce,d82137aa,7d8525c9) -,S(a298c704,5140186b,4d424e8a,f98ee604,7f67603f,ab14a7e7,b96daede,51abaf8a,4dc70158,2a1b1935,4a5b430d,b4a0c21c,463b779e,ba72f108,5d7d638d,68108fda) -,S(e1fce957,82dae8b0,ac204fb1,9496a332,fdf40014,88ebaf07,3a62f33e,192013c4,40517ee5,d5786ff9,6aa2b50a,a77a10d5,e8ca6439,44f308a4,a264e367,1dd02f4c) -,S(e719bfc,5f06b800,8e4e49bb,62361544,1a2b0c42,f673f3a2,1e139bfc,b097d6d,f0c83c1d,83f5df68,a1e3929e,e18c4945,d14e2c33,4f9165e1,a0a462c2,aefd7822) -,S(77766a4b,a9d8cd62,840b1127,7e697dba,dc27c50,d9c8e35a,17f4c38b,50ad0a4e,5b3a2ad9,448327ba,22265ac,86c190bc,60b7586e,6f6e4554,b26b69ce,231b6431) -,S(f237721f,6215a855,f8660cda,41063690,4f2c9dd7,6260c292,597f28e4,348514b4,109daa1c,187b9f9c,ecae8c6d,33cb9874,46f5ade9,d57b3651,bccb9338,1acfef79) -,S(9408f5d5,e8891a1a,3cc4e7a8,a50dbc83,97517b3b,6c5af3b9,f1953f09,a67b3e08,1b82f212,c32f1ae9,c95f87b9,5ced2bf,ca33e954,32d9eb90,ed879ec9,59691555) -,S(b2837655,11707926,c9f214f1,3e90675f,883649c8,8f1660f4,c4f9f6c1,552a7064,89553739,15be8962,e6f03ca4,5bd5516f,be6ee041,519c4131,829b0bd7,6d1abfcf) -,S(ce42ba00,36b5f54a,4ed2a9dc,b6c0d29f,98641331,3f92f9c1,43767bfe,4b78f4a9,6e547292,cf35baf4,768c9179,2f706bfb,39b757d8,2452a802,4a7bd37f,e3a048d4) -,S(bb3da2a0,1a063a97,bec9325e,8d4af420,d3942bbc,42f0807d,8e9edce2,eccbcc59,7c28e7aa,bc39907f,ef58a19e,cd6e7b2e,25d6eb00,8da14d9d,5c559d27,fad70b32) -,S(25d84c3c,97f3a074,ea76f620,d6fb2691,dd3e9592,6de8eacf,5392c0de,36c490ee,5e0e7745,88c8a9b,7b91ffb,1ad6fd27,4153096c,9e759540,16f73a43,16d5651a) -,S(8baa3bfd,ca256f18,2e55a01d,e7c07617,7649942b,e743b4a7,faf39446,84d5765b,6147e897,8bbe15cd,171c2816,4730b211,587bfe7d,7e71811,7f308b80,d30506f1) -,S(507d6a0a,5b7d0385,11c65dea,8024c706,4d3b6b9b,287c7192,74c69797,21f5170,139f1647,70ea83ae,47ea8141,c3ae32bb,c12793d0,ce30fb37,2dc3adad,7f7bf5d3) -,S(7c6992f7,a059c5be,99b7354b,10fc217c,e45620f3,b4ff30d6,d640fd3a,26bbd846,964474e,fa63641c,2aa7062d,7139fbec,1f64e6a0,50e1ad03,2741a0e3,b5e0bee6) -,S(f62832b0,1bf65b23,14850750,9ea6f157,3d5e3317,bfb0a38f,cfcc6692,5a698bf2,d7314810,7b8fdfd7,3f6ce6f8,84f375bd,1546cc3b,8c75840d,3668c2a6,54c1ec95) -,S(aed21cab,d8e4ec36,2b4e2091,3be3c7c4,594f628a,cccca657,deff8b9c,6bd1ebad,f800ef3,833c7ffa,a8ade1ac,2f41d456,b880a205,60251dfd,f9cdd672,bb7100f8) -,S(46de78a9,343a9a41,6b91b877,aca94252,9e0ba8ca,b6c01f66,e06cdfdb,714bf405,c1441252,4f3ea73e,e12809c6,f19184d9,81f30b87,8df8bf6,6c89d98b,ed4d2bcf) -,S(2832b5b8,ab82e932,5356ae19,3043b99b,ba4b6591,a750a174,a6303b42,54bd41bc,c0363e03,3f59f149,23ece534,cb86695,a8275224,f490849e,249e63f7,34aba440) -,S(5b57c502,4b5c1621,77cabe39,b0f36bda,d85bd04,2736c7ff,9395f0c4,cbe43f9a,842407,dc0c0473,f1bf57b9,b35d84ed,b282ed4c,7adccc06,8530c8c1,bd20766c) -,S(b384da70,8063758e,825bf821,196b4a9c,814c45d8,a9edbaf3,dac4cbb1,c1c2f103,e6e661df,6400cc40,74f92596,590757fb,aa237515,af30ed13,df30befd,230fa325) -,S(36ffd991,563e448a,9b0a5da9,61a5466a,82a5b672,15ec8f8,e7300c5a,5c9a5e1c,97067835,fc17d47e,94187320,84d722a5,d1a742d6,4b513b6,32aed897,bb961c) -,S(8367e452,57c20367,e4e60ecc,33adcd87,5b9d142c,c6c362e7,f5aab34a,ed89d81c,fc7ff090,3ffab26e,d38a9e74,df43819e,b77ce2d5,bbdcf27a,f1f3bf19,948be121) -,S(f6ce47e4,8cc9296f,b40539e2,41238658,4719fb9,d4b1ad17,9c98969b,dcb0564b,368d2b6a,fe5edc0b,6f159017,5cd192ae,b524a606,7800aa60,930d60a,87950e1c) -,S(438c23e4,bedaa6f0,527d20c2,a725645f,194ccb58,8ff9eac6,5091da7b,f9fae013,54620a30,c7218257,dbdc93b5,3722a213,e28dc6bf,f8e48b45,6d6131a6,92ff15f8) -,S(1cf672f8,cc9434bf,7ace8722,85db5017,a1fa1dab,2eec7fbc,84e8492d,86bee7bd,d6d23d25,8bb4dda5,957ccced,b767cefd,8932b511,e2479018,16734bc5,b5cafdcc) -,S(47464e12,b0fa29b6,6e9cd157,4f7155fd,94305263,8af28bf4,4325a23f,3e1a2861,209a41d5,3bcdf566,5e966e80,84869a83,a2468db0,a1b19e56,81da864d,a2b05141) -,S(a9adfba1,c884c904,e6877a0a,9bbf73ae,c4ee223,e0b02ff8,717c075a,6aa964a2,ab16101d,a7bbc35c,73f371d4,afeb527e,b2d809a0,8487a36c,6cfae404,83f79dc8) -,S(2932fede,10600312,5ac983dd,659ecf95,824421ae,5f417f97,d3101c6f,c58edcbe,8601a743,e666156b,f2e34fe0,6f4cb11d,2df54fe1,7c842176,e1075423,dd76d727) -,S(5abf5528,2f87ad04,202b62c5,8ff7440c,64f9ba39,e6989df3,e31d665a,73a50216,71dc4e16,f2705c02,2ca1b37,edc5ce0,610b6f57,282d69c5,d3269295,5a1fabf) -,S(419495d,9a121cad,41887fc2,82c2c7e6,f359cbc,d24093ec,57399c3d,a801843a,9152e197,40295094,11afefc7,83990732,d5e6617c,d8e389d2,956536aa,f73e0c31) -,S(fca38482,ea2be49c,3c27979a,5acbb158,a902bc4e,226f7eae,4165ab7a,29fbc3af,1260735e,5fe62664,90a35f0f,7296c441,bad50a75,7b00e34f,28856a6d,cf46f5f4) -,S(bcf05123,3d703688,aca13530,55bc3ab2,d499ec40,8c912de1,4b7af456,55065d06,f32657f1,645690b,35484e63,a3456885,c16d4991,7670e71d,5f5cb65f,a5fb8bf9) -,S(4e70b42f,6391b424,b159cf74,f5fc96b2,68bf6cc4,a26658e4,79dd8a4b,8e9a92e1,8ba78811,1af31c06,77b24fa4,4b6ce356,66c595b2,3fe4fd36,591b33f7,e53b3688) -,S(3fe853d7,331c60ea,c213703c,a7628dc1,3cdb83f3,8a25ce6e,1be84f0d,e921742f,fb7dbb77,c2c6dc13,6f596154,f24dd3,f27b5125,9b60476d,b230e54,5ddca5d6) -,S(d803377f,c3cadd40,a2aa810,4e97641,ca42f582,3ccf65f5,ee726349,f648b9be,6357b84f,281a8080,54ab7fbf,ecc113ac,aeed2118,5ad12900,d824719e,8fd6fe99) -,S(5ddfdc7b,6f9e7162,2b7128e,77fa5ed2,90a05114,d6d8b845,94106c9e,70bebe1,23eaced,fa1efb7b,fae74c81,a1d03066,714b6dd9,1198e1e9,d5911ee4,55cd76ad) -,S(5f150243,c964948f,e91353e6,b12d167b,7913b46e,d7214411,5bc4cd4a,3b6f7dd5,36abc949,7a2fd102,14991e2,ba360c4f,b18147cd,955754e5,71cdd4d9,b8af903f) -,S(24b4fc97,5b0c4429,7a4cc89c,2b127eff,539f022,61544e14,97969bac,50942647,bd3e3fdf,54ad07d8,5faf8881,9014a77b,11d96f2c,a43cb8f9,a823a257,9eb5c207) -,S(a020eb35,5556b5fc,9de5ba2b,28644187,f11b18ea,ae61e76e,1dcce55c,e42202e0,9a71ea1f,1ad2f457,16b667c0,a982e2b,9765ac6e,beb71880,27e9059d,56639f66) -,S(60b79064,f7173eac,60531de5,961c47e3,8a224c78,ccd58a0f,86f6afda,e1f37a68,3ad04a4c,f6a47d6d,6b9fcbae,d8b54a7d,3437e4e3,627256de,cfc5f38c,490786b7) -,S(835cf1f2,b57d1e54,4ac2d915,9c8e3fdf,d2e233b5,d1109685,1777b7e3,a1f7d60b,7d23dd35,136edb13,bbbf7733,9e1c6e01,a7112f95,7c929b16,1665ca07,f6a84b31) -,S(faf74350,1f1edad5,2e1d8ad,e4b319bb,606cd7de,3188cdca,b1d39527,837f77ed,dbbeb0bd,bffb580e,4b9a0fa0,39b7acff,fbcd11b,85751476,16d48bdf,fe21bcc9) -,S(396c6fc3,e072bae2,3e7f74ed,f121271d,44091a5,d3b2a762,a39dd77,d2de938,5de522f8,a143544d,4cc49940,96b8f54e,9fb0e076,f46aa479,9e99d162,de6fa667) -,S(f8ab940,ad8df2ca,1c2622f8,8ef20c,ae8e605c,1e43b684,881147ee,d44ab88,99fe5281,fa7427ce,c9857163,f804c429,630d28f5,33e451e0,4063e70d,ddbff796) -,S(a6202868,af6dfffc,1e122219,a829c374,8197af4c,95901e78,75841b46,bd772367,2607a20b,c82a49c1,4fa54eb6,f8d68d8f,fe9c4fc4,d83b0e4d,145f7bab,5e9af45) -,S(b12d1993,49a98616,90764484,23a4fdbc,cfbced5f,b76a2bda,4d7c4984,7067e41e,a66dd4e0,ac6c8ab1,29045eb3,f7014449,73fdd555,7001b7ec,99c33d,c2d75e31) -,S(8dc8f55,b4990f5f,c6cd3b97,b1938304,9ae0a734,5cdc9c64,fd67bdc2,15eb3b3c,1be7457d,62cc8fd8,cbb54cc3,88722f4a,c00ce438,c847c2f5,fa641119,e5435d83) -,S(2c0b7337,d1db9e4b,7d521c4b,36351f65,f128643d,add0c53b,1b6d619c,658feeec,e8a27b9c,eb7c1219,f7bdae62,c07cee15,ef765b95,3b082d9a,d8b99005,b39bad53) -,S(891fb4a2,50100689,a48a0d1d,22414ab2,b17ad692,bb5f0d0e,66d06c93,da3bab35,41685166,cdf43c13,be93c03b,c347f3c8,52d06c0e,661a4c7c,cb53e24,e7260f6) -,S(4a3379b1,511c440f,e7213729,de668ef0,39fbccb6,1f5bbb02,ed99ed3b,69ca1738,b12a3dc2,39e9191d,a89d75ee,db44ce88,17b3bf03,d4172b00,39d1464c,a3ac0f6f) -,S(b8b2a7c8,54936bfa,62da360f,83bf8d65,7dc58e3c,1c8780d2,2c57061a,5f815521,8f922c0b,7719362c,25ac7001,252a89ba,1cd4412c,17c2b021,c065a3d5,f6a2d15b) -,S(9066fe19,d1dc52e5,7a9341d,77cf73a8,2fb56ab6,22c97a7f,f0191247,db9624fb,23d19b43,6ec3c575,d81d4929,eb6789a4,c281f5bc,abbc896,2153e7d4,711baf50) -,S(bf9ab14c,19c9e9b1,ca1a18df,2b5b73ee,9f32c8de,6e6757c2,b0534d75,7cced8ec,ec969923,3c3863de,aa72418,837a3af7,85e79375,d5bc91dd,481f174,e9759c0) -,S(68b2686f,9c654a02,225b7e69,e8eb7aaf,78c65686,e885b1af,10265e35,316f9d03,1d3d7504,846826bd,8554d407,739272ab,b6b407d6,f4f7419a,f284b81b,f14da9c3) -,S(20dc8385,5251a21a,94c989d3,92c9f36a,4d3bf669,bf7bda7d,e0427003,710bf2fa,217e6ff,713d329f,f9080c4b,3608c877,975d6794,5623e24a,974760f0,95aa749f) -,S(f0beb49b,555d998c,a39859bf,8c59184a,5c822e46,9a875568,1689a1ca,b5fd0368,e0e05ae7,a23ddf94,ba33b3b3,a75d3f4,2e8ff7f0,160c32f5,3bd08b40,72664aac) -,S(8f1aa973,270ff9eb,a41ad8ab,f2cf4c44,16ddc1ca,dc8a62cf,aab5a3b5,c4a0ee57,90aa3660,e3409b17,a86a441f,12f6eba0,2bd6bbb0,2b9a0a87,71e30a6,595920ec) -,S(c71eb135,278dc147,60cca847,a934b880,fecd43a8,aac9dfb,41382283,928a9957,41667f77,485281b8,89307ad5,decc7f6f,51d23ac4,7e71b299,a9d8715e,b6003804) -,S(e900726e,50d66a9f,37d09df5,d4965c5c,fa904d3d,bba1d180,b0fed651,bec41c81,d520aa30,db036f40,b34e64f2,cdc7d7b3,117f7725,786e9d5a,921c5f09,71028e39) -,S(940ab0af,a15952a9,ba3a6d6b,720efde6,58d72dd7,4f87cc3b,edae63b6,123fa38,fec6d747,6f788a19,b85e443a,a49116e1,6e5061f0,53c40702,f8765d28,f3bfcbcd) -,S(9a13de6d,643e9866,4df3ce9d,412c5ce6,a03ba46a,640c6be,8b62e70c,a8c76949,42388296,6c2d8d87,8b4c914d,4bc6cbc9,a4601630,2eb6a499,6103953,6926dd5e) -,S(438429b2,b31129d9,4a86b149,7d7f62e9,b76d6a5d,bde09d6f,256f83ba,76c577c3,e4360186,a7229be1,b33cb600,be833bdb,b2398e98,7c46c6cd,2e44f932,5cbc1c7d) -,S(3f63b25d,66d472e5,fac7b524,e4300e97,c8bb59be,6a3a8f01,8c1677c6,96d02605,4587042,158e19cd,2bd19bbe,5cff2c69,d9971aa2,fbdf649d,44c95f3b,50ca39dd) -,S(661fdf7,17c7a520,a384f90b,98dedef0,47afe5ed,6cfbd3d1,e1735c5a,bb8cc0c5,bd9a243a,b43c0e19,2592f00e,a52f820f,b83b7433,b1d96549,d9970293,7da80abd) -,S(b9c1bb26,daac6af7,d0c27c36,7ea2d4c8,c999d7c,75bc58cc,279c5f89,5ab951ce,a4d3bf34,a42b86bb,7c66c5b2,eed5d7f1,b872d17b,b58c938a,767b87eb,1b140f4e) -,S(cf5ac4a0,fc6cd9d8,50aaf473,3efd2bb9,7d9b23ec,bab5d099,9b11bfa0,b127e8fa,44926316,c37f1718,7fa94fe,3a62caf5,ad465d77,fd484287,2caf1605,f91070ec) -,S(aa52b2af,ab8da32e,3b882c57,ff0a34fb,749caaa1,b3c29b74,13c86471,beb3b422,4b562728,4a7be595,1b68df35,e320252f,73326084,16c60244,ac4e3ecc,c0859ce) -,S(610f22e,b3aa08d0,a9f2909c,546896bc,7926b056,7987217a,d347f183,4868211c,a52e190d,f35fc4b3,19571e6,166eda3d,2dbf637b,c27746ea,c1bc3552,4819e6bb) -,S(13f24c3,a485a58c,e0454330,79512796,db65f15a,4265fb44,acc3cc34,c51a6d80,faccbfb6,18e069ff,3cdc4327,cf807366,f07976d,b24fae61,1a44984c,7f3bc3b) -,S(15cebea8,49279b29,cb0112e6,922c5a85,caeb18fb,415cebdf,92285d9d,a0eb0f24,23e5ccfe,158ff9bd,539af7ed,4a77b1c1,c36de452,8d0c0d05,821e89f8,e075d833) -,S(2605a18e,fb7d5367,dc41b1d6,24d61a,cf92e0c8,96f29a5,5f2dc872,4d97f6,8d6a6774,f111b7ec,dc58ae51,80ad6fd2,fd6d674c,9402e2f4,f944bd50,5e66d375) -,S(e588e272,a78756f3,7fa36d6c,d35b362a,25cd0513,3694b56c,33d0b05c,be7f9995,15beb983,20b84296,9b8715c6,ad23e53e,115425c0,d071917,66e56ffd,5472fbb7) -,S(80032522,f264edc5,b6b205cb,f79ca7e,3a02cc39,93458b6c,cb98750d,bd6b46a5,479c92f4,fb4e1eba,98f8b93b,5aa9725e,fd2c1de8,d4c3d043,bca7183b,851a44a8) -,S(950c040e,e1a581b5,70501308,a21287e7,94b525b7,f916d3f3,c166a2fa,1641bfaa,e43db20e,911d70a6,9f171725,f760237a,52441a88,dc385a75,1e4ef1db,b738ea71) -,S(e899ff36,423fee57,2e70aeca,db8bc0f5,a634b9be,282dd875,9db5500a,86c391fa,7ed97b0,dfe6b68e,26710034,f87a911,88611790,cb18a790,a0248c7c,b43a9bd1) -,S(d236688f,c206b7a,8f8ce5c7,66e19fb8,6a7415d2,9c57845e,8332a5cb,d8a1a51b,72f2359f,e3d54a60,fe6d6508,5183b525,d5098887,55219113,adb05c2c,656ec9e9) -,S(8d3d7c71,da4b2f24,83e458c5,85c628f5,430eab5f,ddc2686a,e94e2fa2,119dcccf,33c408e4,7948f20c,bd79c22a,d647ff1e,1f435c03,1f594aad,82778f58,1f61178f) -,S(320f137a,e8918199,51a542ba,5d1063fb,fee4b750,c56168a5,87d7fd9b,b72651a9,b840546a,e2a4e1ef,32275a02,153bf003,8603698,a8c5e232,6795bcf3,d3c402c5) -,S(9e8affce,3fe6b259,f4568607,2d46401a,7546c87f,9a46e0de,8ce577c6,1881352c,d0ea3701,d83b7f7c,260ebaf0,97236525,af8639f6,c53ecf92,73e77bd4,c29d02f1) -,S(5df465b8,1d353987,293c915e,a24121ef,daf70ff4,9ad2bf53,9bec72b3,c61eef64,3206c5ff,5ae4c841,58c193d,40f46083,8b38047c,f33c3e54,38541a7a,d5e690af) -,S(999cd326,a18c350b,f4861d48,826ba3c5,1312bb39,886a064d,6e1465d4,8ef28f58,2cd8ab2a,d6dccdf6,7998e662,99551608,a9fceab0,be884b0d,d418911d,c8b1ef12) -,S(81d8fcee,574d9c16,fa2ba6f4,255460cb,479a6667,4761b4cd,c0ab026b,6bce163b,594e7f34,f5897a6a,3b79a996,f5a69814,3cf771fc,fd7c8ca6,38cb4ac5,98673143) -,S(9e83d724,b9ac73be,f932b42d,56f85183,85839c9e,c953a0dd,4da6d843,d096d278,f8b18cab,fed05acb,89efda95,ac496ec5,d3a000,a4a1d689,a1afa5e2,30c88869) -,S(98ba38b1,3b443c08,aecb1f64,73b2d901,908ec33b,35baa317,64f91144,3e320c3e,343f61d7,fc2232fb,f5d2f972,e6f42f49,d8ece7a,3434a0a4,4df1d602,3f99b84f) -,S(2092ea5a,9adf5eec,5a7a9488,6e970671,5822447b,e6c35285,de704806,52a875ec,ddfb72eb,52382722,a94facc8,e2616661,95a7e9c2,6594228f,304adc7b,ea4e7f35) -,S(f9ee909a,8f45a05e,ac77bce4,ebc97410,c044c639,95a1de76,5b9304c2,2eeb75a,861031ba,93f5b0e8,473e50fd,2aeaf13e,3a39c0d3,7e2e9d51,a41ee4ee,1301705e) -,S(a13878e2,3bc55a7c,b342dfc0,2eea9bf9,5c676e27,c63e8603,c75ce535,35df101c,35c0ced0,3d4bb091,92a2f83,3d3e81a6,233f0585,35c72ed0,1bfff82,7b108427) -,S(e8ec81d2,cd32dfd8,7284cfce,9d80c03,b863a7f8,3a71865d,34f7b1b6,104ae3e4,60be9b77,ee12dd7f,f532b01a,f517bfc9,1d24c4e8,b0865e4e,c6e27227,417648b) -,S(f07cb255,1529dc43,3470b18f,e4e06390,d48e9898,69b9a97a,6642b898,1cf35b60,bd46eb77,6d74633d,59b4b941,2e2355a9,c6e85421,59513d2b,a3297a6,c223b550) -,S(39bce423,dcfda9f0,a97189ae,a60b836,42becd3f,2f2cbdd8,2fe884da,baaf7f51,c1599caa,4b71219e,74490312,7303ec91,f3430be8,14979a2b,2db78bb1,ea2c8e4d) -,S(6da611cb,d51db814,18b3de21,13c9e4ff,58142f67,cf2d8ec8,e0fd105,1e9ad3cf,6bc2f048,3250f654,fdbd494e,bb03480e,f7fe5568,2e19cd70,4d178ff3,41e4b7f) -,S(cedb9c03,8d2e0eb9,8a4a5e8e,fa7e95c5,f4e13a47,79470c70,9a3c9fbb,8b1aed8a,79a2fd31,de42d8bc,820d5d56,ed084f40,46804fa5,f7f5e8fe,eca6ad4d,859a0d40) -,S(7d895498,6d1106d0,32f40458,f6c41fe6,25393f84,d00ded8a,3a07a107,5ae3d82,5d4fb6cf,ff1c594b,61aa117c,7e0ade0e,edd110c2,b2109866,ee7d586a,1a6d0d61) -,S(a4f29162,737043af,eb1e2606,93ecec60,851aaf50,c6e9daa1,75a00c43,d7dc3df7,beebfce8,fb764b15,38fabb20,145aaed3,92265d7b,c4628846,b2726821,c79c4439) -,S(b6389dac,de4ccb08,ec0ce964,e689bbcc,e0ba8165,6680c0a2,9cb162f0,f91cab70,e440c7db,d2d02474,17b2826d,28e31fe7,9ee836a7,eefdacdd,679040ca,50303529) -,S(72ce6dac,f752c36f,978ac2d6,aeef37f5,ae4ee016,999ccb49,27b8aefb,f6fcc9e1,ce6ac297,bbd84403,d60c6d4d,5e01027e,8ad38acd,e796bbc6,7c45f10e,d79bbca6) -,S(efad336f,cfd7425a,560931fa,a6bc50c1,4fb3e5ad,f8ad175,31b13846,6c255f06,3fb784f4,eeee9a11,ec7ab559,71817163,9eab6b09,4419203b,2b422e8f,e15a82c0) -,S(f98d4a2d,4bb2166,7c74bd1f,393ca57,22002c6c,f382b49c,2895deb2,34eaae3,9875e31f,7e3778a8,34750763,c6147cba,97a26f8a,d669e69e,9a36cc45,b56fd148) -,S(768cf74d,2bc24233,2c5eea34,2ac13ed1,2b0d161e,65876eaf,b0b89460,c934183f,42337607,e55b4d7a,f86e9f72,dd06a550,af083b32,e72e6265,4ba00fa7,a2fdc34e) -,S(ac26f3b0,1d05c625,915ec27a,aa916d0b,d34cfb6e,22525c59,9791274d,a5beff7b,e36760ac,89b61681,d1913bcb,1ebeb199,a3005576,b8bde54a,42fcecdf,e94f4045) -,S(dadd4181,741a0be2,e665045e,1b042a3a,fcd9050d,a08d1285,21298f34,1f74fbac,6cf46fe0,da78dd04,261e4e2c,863574e7,f6a4dfbc,a902802b,8056e00c,e4a84f60) -,S(e5651598,ce9e6a86,2fb139ed,143f1b73,2c4e1eea,91a88f82,a6fd0ab9,1a86a3e8,bb421336,69ab6c10,109723d8,ff4d5f6c,770fd8a,d569a21a,9e9efdb2,f1f1ac98) -,S(f26f791e,b4f0f596,39b69b45,401ee3ab,2d47a2b7,dcc3d65,de9e48ae,270f5b02,22e34b25,1fe5bbf2,5183c799,ea45757c,2693c591,633a84fb,e1a9bc0b,470ff699) -,S(a50cf10b,95612f48,7a9da048,a84dd8a3,2d2bec22,9db798ac,19fde68e,623da9da,50107d3c,a76a264,1db9f9f4,7cd60598,ce345ecd,cc3de888,e4c81553,bdcc576) -,S(c74883b9,2736c1b,d5f86a5c,1817cb9b,e917e5ab,5ec5cc10,a1197f1b,a45c13c,e03c43bc,e7393cff,d53e73b,60ea2759,d1c2bd55,c2b7a32e,847f4bd1,2c8beedc) -,S(a3437d0,1741ed88,bb05c00f,629e2c8d,be7cada4,dd002e9c,98dfe800,9e1c0a9,a627e05a,257fcabd,1fda00af,a4d3eef8,fc268e67,bb41c9e,d2160713,847bca1c) -,S(a6cc4988,f179bab4,de98ba89,530686fc,90c00c77,4a3f093,8329ffa3,99c8312d,f4eba473,7db25a79,29bcad7c,11346471,bbba86ef,4f611643,712ff475,9d70b6df) -,S(efb34a8,f5778d57,b3333077,6ca1abe3,9e680183,13936f24,da1aca,70b84dbe,a94a216e,fc53fa98,320878e7,167536ba,7e5845ca,149b2595,2f029878,7f428d3f) -,S(139846d8,1385e6bb,b23914ef,487fb9ab,19ec3b8,3fa45a94,a2c5fbd6,fcdfa07a,4fb7cc4e,599b10cd,a99f6aff,28dfda0b,62d837b2,e8c96aa0,9c34cbc6,acfce099) -,S(660923af,98ba567a,83df6eea,ab53ea62,49c2090a,13299bb7,a538cdab,adf2a101,b28b58ca,b1a29722,699890ee,8462f440,ee2a5686,9715478d,4460f0d8,8c94bd29) -,S(f18092b5,8c7517de,3f389d31,f1a6345a,d2f86bd0,c1dc9a98,d3e03890,f52be3c6,a83e7a04,91484ed7,7dc27697,33b0321c,440ca763,2a36c6d0,7e8a9afd,68f9c906) -,S(e8d0aa0d,1b2c540f,38a6a6e2,5b5fb295,7b700467,648cff74,bfee1138,81d0ab75,a324cbbe,52055c1b,d0cc3f29,88a80982,1abfc0cb,feaa56e9,f19bb8ab,d314409a) -,S(2586a0c0,230a0743,f9613df,51f7463e,1d8ee72d,503025f3,c7d2dfc4,6f526c1a,a29735a1,eb2b470d,43c7b469,4850f5c3,ce9b1da2,47406653,ede03ac0,9816c735) -,S(217cfa88,8d826d46,c31bb2d2,7dd7c8f5,8be68254,e42c0e48,a12cab42,677dffd8,4d5d9c30,9ff0fb15,35f9901,7af91ded,34179c57,f48131a0,6d96b6a,c01ac4ce) -,S(4ea65934,71aa3b8f,9e6791eb,37cfd67,943af3bf,100d7ccb,8203a353,1aedf4c0,feed9ac4,19a302c4,58047403,5c95e997,ded8a534,c88beca5,6c12984,84b7b4c5) -,S(974b828b,51026aa4,ea522150,c497eebc,7d7759f2,c9645f7d,4faac24d,18c7a1ae,c0369da0,c3087336,2566f344,ca81f261,65cd3a03,fcb05093,96d18fed,4faa9d26) -,S(d9815b79,d572d7a5,94dc8ae9,3cf45b36,99bb4544,ed1d5755,529c7096,9c978186,9fcebacb,f5181954,ac4ea24f,508fa67f,5b6c20d8,64ed53ec,d67e358a,e75241fa) -,S(52712597,d9bd4e7,cbd506f1,bd65aac1,478208bd,f9f6ad38,efd2b30e,b8368837,52eca996,ba2cecad,9a0911d1,65368010,68bbf0c1,12d6dd79,aef23262,8b3df18e) -,S(d94231af,d890f5f9,ef70e1fe,e8a8f4e8,ed2fc89e,2b8ad818,6af55de8,449abf6d,26592b6e,f0789218,273475fc,32d865cb,84278ff4,8cd0de27,e0646549,219e2867) -,S(64851231,7a69d956,3b3a99d4,b763eb9a,b661f7b0,714d34bf,e5328a4d,a99a7d90,eb20ba33,515040e3,6fa02088,5a3e9216,1e06d3b3,78122fb4,af4920a3,51d46bc6) -,S(d0a4b11b,ef662f17,98f413a5,fc062567,70df9edf,ee00217,79c3811c,ef68a8c2,d4bb9920,18e16945,c38ef5c9,9ab39eeb,748b7a63,ff4d4dbe,8b329f74,dd70b9cd) -,S(1d89b886,c4b24868,1fbe103d,dcbd76b1,dcf54637,3bd5249b,3dc07f06,985802b6,a339ccca,aacd1057,7e36056b,a3a70c6a,a7885a45,42bcdf30,30d0939f,6369535d) -,S(b6cecdd5,936343e4,f136682f,a38ba0b7,9dbab223,beb0b6c0,10a75cb2,e4dbb256,2935c053,87dd87a2,5bda5d1f,ed813666,5f77d12e,8242dd58,3ba8db03,319f7be8) -,S(84b244e0,a0cad847,35ca6c5f,bf581968,40f1b491,98682c4,28aea50,bf2f8e24,62e28e8c,7df80b11,f5713087,ee3a5d8b,148c8e62,da0de1ba,d8289ac8,861f7a71) -,S(f95eccff,2a908028,39436610,2e377c41,66433159,43feb6d1,638df6c1,cc114d1a,bd0da83f,1a0306cd,b8d1b9ea,189856ee,56d16e81,61b4f9ca,7de38d2b,e558eba2) -,S(7c4cedfd,3e613de4,af2ccd25,59a2dd23,2a1e6335,e410d327,27fef321,d10f55e3,331f2109,d9d00536,c697f73c,672a660d,11d4827d,41306696,cdc224e,e7d7b1d8) -,S(235c2e38,1bf2d829,e4b918de,435e276,f88af866,ed31a1c3,4b9f7203,a0269713,50dcdf0d,2671092e,e7c48614,44eaa87a,815a1304,4600fd0f,f26104ef,a0dbf929) -,S(2a961cd0,9ab50975,517ca488,d1c4a388,cdf2686,c5dde923,76128683,ea07cd73,85c91076,b2ee46d2,3cc0f7fd,e7654723,84f84c2e,edd7552d,d7f93be9,2398abe5) -,S(958bc491,f0afb8cb,8713f591,cbf183f7,e00c4775,93d1b51,a628f40e,4cfd65e3,bf5be339,fa21dfe4,9113e026,af0761a1,b2a09a7a,ae8f6eef,92d50c6a,89a65b3) -,S(6e960ca3,7b5b7abf,99f5a2e2,46b7e953,adb5ccc,6424e73d,dc865bd8,3d5f78fd,53ad4bd1,d5e9643f,5f2df612,ea16fcc8,dcc4b0b2,9ccd5a81,bd659b35,6a5e0e15) -,S(d7ac920e,9272bbad,dd961525,7d91d6a8,e747e4a7,a48ddb5a,8b2ece8f,f0d05871,6381b9fc,c37bac5e,38c0b96d,c098c3,9d4c7620,61b66dc4,adf66e24,f0c87ed8) -,S(9b0803b,1de95706,ec123844,ebe941ae,4481c12f,f2d9c078,b6c1d531,5d730609,160cf3d6,b12afdfc,eac2ed01,fe4b801c,5a5ff0bb,13cc3ef2,f5f0962a,6b3fb1b0) -,S(5d50746e,5b74e006,9dce0153,aba04216,991bd509,f022f3ea,689553bc,a4c5fd88,b0fb205f,d2a14b1b,bdba2e48,429c92b6,99cb336f,b6ed0e58,9276118b,6b259ff8) -,S(e1bc2669,fa27629c,92708748,36008c2d,ef4483ab,c686ecf0,bbd01a85,fcbe04ff,6fb7af71,83c0921,6173fd43,5b3a1b2b,15e8b149,3bed8e78,3d409f84,cd95ecf) -,S(cfc9081c,b5a893db,40c51979,7dfa1cf2,f36ac620,cf7017a2,fe90dccb,d8bfbf78,26a88d23,50772fc3,2f377c15,a9bf817c,db321d1a,55c4d659,b5f29ae6,96a69ac2) -,S(54d9c9d,12bd68c5,3961246d,b98ed78c,cd8ad158,8458d4b0,5fad9df4,2229bb9b,b5e97c31,1dec2259,630c961f,ed33d7d4,f8de7005,849225eb,a4549d76,de1cbff6) -,S(8a914ee6,7e9d6619,d00f1924,8735c7b2,bfb11eaa,61fe42e8,d64b5a53,43057dff,1b91e1da,3374da49,8bc2f018,c2a6fa51,99c51846,a2f59b05,a6311ac3,1bc040c8) -,S(d4b81177,3e641dfa,bc704fba,e9ab0ab8,aa2f4c42,fbd23b03,a0b0595,d0240522,ac30ce3b,1ea4a14f,4a5bd364,20f40df1,cf2e6835,17107b8,ce6fbe05,665cc726) -,S(b810a787,c232357c,bb82c351,79249f64,6f3c8e2e,72e0e004,36226670,14780ba9,54364034,1078dd7f,216bac76,9abc8467,4a422c30,f1b7aef7,6a2dbbb0,158319e2) -,S(d71f88ce,dc738ef7,1ad691ea,c3a7eed0,d29c762d,8ec7ce0d,14e72d3f,f534a833,a47cce83,1aaaadae,a2d9d0d9,7b4c5125,97c1b514,95c3aad9,d2a4e716,cfbcd99) -,S(170cf31d,4cac628e,139d9d89,662ce5e1,1ad7092c,cc6c6174,96c99d71,6d147ffc,4fb3b894,e741f585,15e8baa,addf3119,adf6c4ee,695253a4,6f9a5dec,cc6d77a5) -,S(8e7692a3,b1275e80,38ccbf66,ecb9a55b,bfd48d49,4085b4d3,1729a644,ecc316af,f339c1d3,af07525e,26500665,ce66a91a,4fc0bfa6,b8a46411,34cab540,68c504b1) -,S(5d1ff338,3dda5e81,32c47002,ee2b77ce,a07ca869,e7684d40,a27cbefa,4aca891a,a1adb3ac,b0decbdb,6772e62e,74c4516,fe843833,8d2979cf,5b091801,bf5fbb8b) -,S(d566cfdd,a9dec66b,ddf2605d,a37ad558,375e1c5c,5f5403eb,d75ff6ec,3c2b8af7,13e2232c,78586da9,741598bb,25a90a4c,b6007bd7,bfb75ed8,427ade0e,619c78bd) -,S(cbd708f9,cc713af1,999ae74b,2b9ee3db,3cb85bce,249c5e33,764997d0,2fd96493,f01a1d6c,4ca9b0b8,9337a5af,889d8dd9,c264f4bf,6b8066d6,55cf9267,684cb2cb) -,S(fee1ece4,e8ac73c8,8220bea2,153800f3,e8d049b8,f89053f4,ad4b5ba3,f0ed0fe2,9b5208ea,17c80640,a353354a,7cf42f6a,f9763db0,bdb0954f,53d56a2e,ea26aad6) -,S(c6aafa66,de444853,8d7a6c3a,fcb35a8d,db916f33,14c15dbb,79c48bc9,46ee843f,8a61c6b6,7fc590f7,bc81a761,7a6e24fa,34c49d5b,30b11bfa,7cdaf3bf,d1505b1b) -,S(ac351560,83d91f7e,4898551e,7666bbce,dcbe21ff,f005ef1e,a866781,d9aac415,d709d997,77109afb,28c318fb,eeec8a27,5577410b,8da6d494,5ac7d660,1334483d) -,S(a89c2616,7c024b4,81455d19,93ac04f5,7a212e34,95066ef9,21968f72,3d914e18,551d3662,6127866c,77df092f,5ed8dab1,3569ce68,433de199,ac8219ee,13a3c1ab) -,S(9951831d,b58499ea,e94018d8,cfb9162e,b045b95a,fd246a3a,72e8808d,1ca3f06b,fe39aeec,b9d5f867,d5827146,fb384808,81696ea1,5b0d1188,fd487b16,d9e4d773) -,S(b71e17e0,14564447,955be26c,61ecebc6,8615e2e9,37cd2e8c,78d26922,681fba96,ebcfddf1,d21fb8cb,95e3cb22,4efe9553,1a6c5ba9,cc92bdc4,3011c50b,63b9e3bf) -,S(e170f81e,dbdd9ff6,d460ef6a,1c3d4bcb,2fe89fed,4e6742c2,2d683ffc,15914074,93f110ee,f971cac,8ce206e3,df6f9caf,801fa7eb,c7df14d2,d6f67e72,ab96e67f) -,S(431a5547,318d05c5,5ecf04ed,a1fabbb1,4ac8dd8a,47dccc73,acf5d5c8,1ec104f2,3e3188ad,7b141a36,4afa1f04,57ca827a,7a6f1f70,75ca8dea,6fd08bf2,bfa779e7) -,S(299e6a6e,e1587523,2be26ce4,a1f80cb1,3c193291,7f0b5eec,383ffec2,62203394,5dbb70ed,3ad4a211,bfc8e8bf,4c00a055,23c9b3e4,ed3790c9,3bb2a77e,5301575) -,S(66db488f,f2b58869,b2fb5f78,61e7f825,bc99ac9b,ea02b59f,b0978c9c,c38934ee,ab76e112,b51c83f8,b10e997,2f6866c4,6040e7ef,eb14817f,c316b730,e8ae6a5f) -,S(1259856b,66980d52,bb3912fa,78ad5b70,54c812b5,fed402a1,c3c8247d,26274932,ead7cd3f,c67895c7,edfe0557,d5681bc2,d70dfcbb,870c7c22,45d458c7,f2150383) -,S(502c8614,cbb0f3dc,caa5272f,dd252c7c,4269968c,efebecf9,102745df,fdf1cf00,711bc688,7e4e356,fd9d0695,16af0a38,1b2f4500,6487154c,10b90995,3bc53c3c) -,S(e051193c,323c6403,f69c1073,47b6b7fd,f43acdec,17c00c42,2249bcc7,aa8d6fd,2102c271,ce428ee6,16d1d2bc,f25c2630,c574d9b1,87f8b9f1,c85117e3,8a560455) -,S(c9187bae,d768d32,29fd90c1,5c3b37e7,abe7c58,b538acb8,ae0741,adf1dc46,c130d443,f9ebba4a,197d0252,615ac29d,5714f6dc,f27fc0f8,d7547335,89c92c0f) -,S(5b08567e,b9f3b3ee,2b03ae70,1c6b0641,23dba4d4,4e8297a1,6eaec8d9,e90fe897,ad071c15,9079c91a,cdee9c72,6e8f4cbb,914d4b4b,750fed92,aa81a987,a90c27c9) -,S(ae5b648a,c5817a86,cfb06a26,d62691ab,8a9cc554,d0eaa86f,839f4a51,b43ba7cc,1ea8ab0d,b665c22a,ab0a48c3,da17c629,66e75212,a6fe9983,d5e925d,432db311) -,S(3b9bacd0,a092856d,98eea5c5,ccc9abb4,4f2e0d3,27e578f0,42102148,890178d2,b681e88e,9603ba1c,57b628d7,ea929ae0,b79be447,f181a491,1fdc65df,21bd5052) -,S(524df580,a74066da,d522f827,95e415ab,f6dfbf7a,1c1f6d7e,e8d05a86,4659fef4,3facc728,5f3bc1e1,a6fc210c,ad302ef1,9c72c5f9,e358b9c1,ed2aba72,2652f35f) -,S(2e0637f2,ade775c4,87d09a38,3480b875,599a34ea,7fc70cdf,f6ed309d,450e4363,e3c6eb08,7e2f4e49,cc78e903,e4ad55f3,1aafb7ee,ada72369,6da8a0a0,f764738e) -,S(f7fec6ad,beafbd3b,e413fb33,587b9427,3f785728,226f764b,bda6130b,aa0cc483,f646a974,8eb457c7,fc8fefd8,e63b976b,dd42093a,e59fc544,c66531d1,9e08c68d) -,S(75f94ce0,6af64c43,2b6c95b1,2d892dc8,cd6eb497,4d826299,29ad8bc4,8a3608be,bf8716d0,a2b7906a,69316b32,21ec0076,6e32c892,2c7be6c6,22e8877b,b1958a29) -,S(410296de,5e0df3cb,c4f039f,cc869090,f62e07e9,d3011043,31bdc1cc,f3fb4d85,e963579c,a314dd96,ab8a82ff,86265b82,da74267f,c861f96c,383f72ed,3ffecfa0) -,S(cc824eac,5f5e16b,2f7c1703,d97da67b,69b4e698,16cfbb23,cbdffe00,d73ffa05,17c30da6,9f414ef9,5dc58218,27c7880f,d18c6f1a,92afaaa8,b8cf10a3,353e8abb) -,S(acc1b0ef,4d26ed8c,d78f0b3f,d3177077,d2074b64,fa5d8d03,a83ff113,7e6e5820,6cce44c6,8519ae91,19d2a80,4f8fbeed,4fcd24d0,169e8000,11150c8d,9c3ce6c3) -,S(1cb3076e,ccce1d9b,774bccf,4318b921,583c2b8e,31877825,7c2fc71b,c90da922,2a2f276c,58605d,82a17dfd,3ecdc5a2,a6372df2,cf25bb04,c628748e,4ce373cc) -,S(6efda451,2a22f49b,587ea975,9e5a400,8cb3a521,7a38b978,3d5825aa,84fe13f2,11d44ed5,6dfe2fb3,1ff2a54a,de5a2a5b,60673cfd,bcbd5039,54a94758,878e2424) -,S(47f69619,aef4378b,5cc931ec,da8fd996,e2fcf1cd,17de9cdd,51b30c3b,9dbf0858,149556a1,9776e3d6,da457af2,a4d70d66,d2fa28a,c33abee9,bf890894,7cb5e274) -,S(dd3d8e1e,97f5dd5d,539032c5,13a19e26,8b2eaebc,1a47cd4f,8ff48335,794d28e4,7968bc00,20f6a83a,a973d7c6,382ebf33,c2233bb,34be9c2,e0ff9eaa,4c467e83) -,S(2bd454ee,a19d3a6c,be55737c,d3cb4b32,7de2a2b7,50535f91,97aad2b6,65e16d78,a70b0f0,d6a1278f,34271c66,7ad40feb,9f7c6248,87e3f754,9c1f1fd7,129f7f99) -,S(8cfe75bb,2a7e74b4,4da035b2,9a26784e,915462df,13ac2d91,4733184,f5a5ee0,648ffc56,bdc87c86,4f6226d1,c9245540,b65c2da2,7fdadca1,eeff2e24,6607cd1e) -,S(5eff34ae,19c462cb,c2fdab83,24b57bc8,5e046a68,4f112f6e,665b3255,65724d36,198fb5bb,9db347ff,c2289629,d2e01051,d551e783,47c6a6b0,ccfcde15,a04d68a4) -,S(9aa54554,f3673b08,e36db624,47631774,a2c51bb8,1f18aa61,426639f,78f92b91,8744a3ad,4a6e7404,d2e22faf,272b50bd,1d167b46,5f25c6fa,75c8d784,61384806) -,S(4b837575,8cfb5970,dfc7463c,5df06ebb,ac88a2a8,b9d7565a,955cb53a,5ff259e0,87591d42,bda1a53f,6e474396,a1233df6,ed70766a,ab7aaaa9,9171a5e4,fa8df208) -,S(5d4b74b4,9134f90e,673f5a57,959c7cef,c49dc725,85734428,226cc5ef,76428bb1,1b2a8910,f466ee15,abe6bf3f,100d8da0,cdc2f6bb,f19c3cfc,b1f07a0f,bed89425) -,S(d50be2c0,c55244ce,5d93bafa,f62ee680,2d475441,7ab9c2b2,5702a309,57cad2d8,fe207e4c,6ee89ab4,c0185461,7eaa5de4,5a4dc0f2,bc4544e,f241cd5c,162f583) -,S(bb0f61ce,8e0eb384,64e48915,5bf985aa,f93bbff1,416db2e9,a1da034e,1075bff1,13a715,2ddeb0df,30ea1032,cbcb08ef,4e6b0561,31474412,631f6fbf,b77b7d0e) -,S(3ce6bddb,473f01b2,170e41fb,22fc5efa,63e22b9e,14d9bd22,88632bf8,4ddcb2f5,43086057,f4b3d298,426b7308,110dc52e,9a84268f,1bac1edf,8d47a25a,ace0922e) -,S(ffdfb14a,ef1680bf,c90b5490,c7cdb75e,bbcbbff1,a56c3c85,bd37460b,b38f81aa,f3045def,2f1f19e,232880d0,e948b5a5,24f228c7,3bbcca54,7c216ee1,eaf4af0d) -,S(1ac1f2e1,9ab4264d,8126eb60,a2330aee,c828d102,507ac0fe,d59fa4c0,8223172c,7636a4bc,339486af,b215e3a8,f80d8f02,d8fae063,81b4e7f5,133f1936,d8e18bf8) -,S(52534c0a,740e89a,6142957a,a20f2339,b1a1a6b6,7e6c9a2,2d6661ec,adec228e,cf6fe6ba,fe41c899,c1ec2fa5,d884fafa,e1a31835,ae8022f1,365a97cf,3261b669) -,S(40920285,7cd22c2c,78cdccd6,137d32b1,4f36f2c,964a278d,5b9f6462,651b09eb,40c94f73,a5fa3e3f,66dfef1b,f4f16091,f6b7738e,b8a865fb,3bde12c4,2d031d0d) -,S(8b1d3c33,4b9ccdb2,14aac6e4,e840db16,25a5b3c2,4069d9e7,c81bc51,9b029289,114fd464,2acf9599,1fd65898,57822277,8020769f,145f86e5,630d6db5,5e23e853) -,S(ae14de60,b7c7f13a,59c6bbd2,64162dc,8a6055e6,3d3460fd,7e473979,f4a242bd,8b960489,cdb5a333,a14463e2,376f2113,afccfee7,afa00ef1,6cac6a3e,4c65a412) -,S(f37f1c40,99c95e6c,3e8d4e39,5dfddbaf,b8153948,137de420,788386e,2ed3e3d7,1f290080,82f6ad34,b2283d76,9cf76577,a564411,4f51af5,310c0a3,b3fb3606) -,S(1fb07fae,9636889c,34441c1d,3c2496bc,a13f8933,666d05df,aa53ecb2,1b017a84,128189c9,3931576a,c4b68934,b7ff551b,58e6da46,fa97fcb7,b8df8c9c,637753c0) -,S(44d1eb54,e112eced,480ea2b5,1ba22ba7,2afb0721,d0d6b715,52bd9728,4815f3cc,a6e13b28,574c526f,12673e02,ed7938fa,ea1855b7,d5b6e88e,3c3a9b2a,f2ed7043) -,S(6980972e,5732b875,7fe311cf,f76f7bd0,ec94918a,759a7cbf,d8795645,a103238e,7b9fe832,4ffb9143,21776b24,a92fa09a,ac4a0fce,17c5bc26,2d2eb063,63d26a5e) -,S(6a3a8c9d,405bb1e4,de59639c,4f6406a1,a8566a62,9d85b79b,f7030255,50efcfa3,3e8abae8,7b22d04a,8fdb408e,196b47a4,2e0f59eb,9d51924d,ce8de66,cac038ba) -,S(ff3108d4,1598464a,bf5844c4,dbcfa027,bfb6804c,946c3683,1da390b6,4412ed0b,805565e3,3ee1d089,5c6abe85,77054648,11f5d4d0,219cb515,dc072d47,cbd0a317) -,S(ee4f76a,2f8549ab,3e134e53,335dcb5b,49972750,180491bb,2139324e,95517d73,6bd90167,22402b11,68989e89,9c942767,8307367d,8a29075c,8fe81049,7071a838) -,S(c21175cb,1ca958f,36a3b720,5cbaba0c,230c6305,8cd09966,ac78f51a,4c53e0a4,6a2183a6,7a7ca0af,256a0ecd,2c085d81,585a02eb,2ffe6a44,ea923688,cc72bf51) -,S(2d5e4c08,a9a0b398,34e46e39,e7cab91b,953141c0,c5f2d292,c409cbf3,9a37d6fc,7569b9c5,31a331fa,9234f37,e9005ed0,4b512721,dc4ef054,d6164046,75c6e15e) -,S(6302c041,bfbbeb09,cc012408,631765f1,5d573b67,6b799c26,ef7c2a4c,bb15dbc3,32a8f20f,67ce42a0,ac4ddfed,d0932e91,a1e51488,49e463f,915af082,7e491025) -,S(3e61516c,198de08e,f7dc9cfb,89ef9b94,5b6c67cc,2deab08c,a3b36612,5934e2d,1effbbf7,4d5f7104,f7784944,70f62784,5692f3ed,48e4dbe,e956e063,37520d9) -,S(a008bab2,d7d134d2,4ab35a37,8f330521,b8989219,108b05a7,d8aab0ae,e542fe30,77a377ec,903c06e5,463ec2fd,e9c05e43,f5454aea,82b99de6,be09fe31,51b475a1) -,S(7782ff48,b928962a,950f42b8,2e43017,28711467,16f22f8,c389917e,a624005f,78f23e49,38a03e0c,ad1b766d,b9bafe30,8ad2c9cf,5b22bc18,c78c8898,fb608c15) -,S(233b4a78,c26ab44f,d1019d64,8c896eea,f6ffbe71,8cfefc20,d20676f8,27ddcfc2,de508436,d976df90,487ddc1a,48284cdd,f553d342,2e0977b5,18f3ed9e,773b655c) -,S(8014aa29,6eed493,d83d7aed,2d8c3342,3f7a4623,295f2a07,92c5de0c,71b8bb0e,dc58729d,f2a5bc9b,1170caba,4856a9e1,695f39af,81a1e444,f3e6dd55,f583d92) -,S(8a01e90b,233dae71,1bb050ce,7bc61c8c,60882aea,ebead2c1,b284ab59,dbbbdfce,580ed75d,c9e3693e,92c06cc4,12c95a77,b34b72ef,20a51cf4,ca4ddbad,7691fdb0) -,S(50a2349,24a29158,70e6372d,582ba07f,a569881a,96bd1a4,4cbb9232,1ae733b4,6943c220,a97701d4,a79d8e2f,a446fce3,aa21d00e,2f7cfcde,3edabcda,678cc751) -,S(cbf49357,8c96744f,7ab07bd6,182640ee,b51b8f6d,a8a655ce,cbd2087a,eeaa6d83,4d1b36f4,5711db99,404bdb1c,9484a04d,29e79fa5,87d051d5,e75f07c4,ee8d4bf0) -,S(737b3d75,e4edd296,8d164c2e,828b31d8,7c63d11f,fa4ebd89,ad59ba71,8a8efe38,ec7f7ba1,8aa8e515,4527002e,edc8327a,ff1ebf6d,d3877439,e7c822b5,35f31586) -,S(29cb2864,251939ae,6c7f46d6,9d7b4416,8812e0c5,9aaa8b8b,b7e22ffc,ac38813a,c3ec280a,7c98b2c5,c96d77c8,b410ff1b,b5f1eb51,debd38f0,528bb73a,eca2e6e9) -,S(1858aa59,24282fbd,e44dffa2,5197954f,f3668954,24741d35,2c9594fc,5e28fe9d,a0e891d6,b0a69fab,9fbd7879,a7e4ab4c,be50b1d4,4be76485,96fec281,d2d4bd46) -,S(72ce7c58,1a420eaf,67bae314,d4f092e9,26c1378d,d346c4fc,2a9e9174,862eb75c,2329177a,5a9c3e0c,f6e236ae,30858bbb,8bec121f,f7462ff3,6284bde0,7425ae1c) -,S(34c1ca5e,5dfab6d2,4abdcb83,9ddf9bc,a3f9dcbd,ecc315,17bd6f46,af112903,93f6fead,c931cc97,37c4aeb,6a589a08,80088a24,eb49a1a2,7aca807b,22a1f803) -,S(7c5ac4a,80af5867,f803100c,cee3d676,8d348b47,9ce26243,284ba0dd,24392c36,a4468964,903be647,31fdb23d,1ea7ab84,a3201cfe,ab585b86,3370ea40,66fc5828) -,S(be2ddd13,244c7728,1a98851c,8683ff7d,b57bf3d,a746cb35,e594b7ec,4c363caa,adb75939,af8a2cf,1cf3e5b9,2bc7ba65,8c45ea85,47959f25,7dfe4592,3e580fa2) -,S(6dee1f6a,3b3befdc,a4a44471,d62dfd9f,7f7b222b,819979b7,901a1764,8ec13806,5d9e8501,4fa5f6ff,f8c0356c,eb013122,1a9a2431,f641ab6,af3b9999,5c2e5651) -,S(15f264e6,8e2c8ed7,490355b3,a7b11512,c764386b,f6bafc31,80ee6fe7,9de68c19,90574d26,302bf408,ef9053fd,371cf29b,c41291ab,a76ab74e,ddf3f8c5,70326aba) -,S(3d7cfbe9,4cc890c,ea592b78,5a984c8d,6d4c5e7b,183f3666,df9805e,be9c91a3,d55cddd4,4ea7065a,f8f51694,f6a84b54,42b30b48,e7630d12,6827dfe5,e7f62808) -,S(54388bf9,d7951dc,7ab5dd3e,74971201,1ec637b0,7febee14,45b1dcd9,9c3a1e10,17b36788,25dc2a5f,9bc8738b,3f560d23,725f99c2,a9d6fdcf,6fbeff54,aae5a547) -,S(3c229fdd,9a0080a5,948a0d2c,c9281794,425327c5,52063c94,be5f0197,6a088313,34975795,a84f83b4,af883d12,c373c505,192f0a71,fed21d8d,3a8dbb8d,2a926a1c) -,S(b612bb6e,e14659a6,e1691f36,8fa8d7ad,1974e74e,36f1ab26,15705271,27c63210,5948c5d,d623cdf1,f9477733,dd5e8eaa,5240817,e8e08dc2,23b6072c,a4df5bb4) -,S(ec56e585,54470dd4,28341ed3,e900e33b,ae381e42,2efb3d64,d2edefe0,7b05f613,ecd7f151,acf6e308,dfff2bd6,578bce76,86effe0c,d3b156d9,df8f66cf,295e9c45) -,S(1bef3ca,85ff9f8f,bd80c8ba,f9b15b26,a565eeaf,e4d4f08f,25ee748f,fc11f80d,fe0260bb,96be497b,a194b892,71bc8989,125f0a0a,de88b135,272c5683,f92914f9) -,S(1bdbac4a,522b68e2,a90e4265,3d2bf4ad,c4b27e5,a2ebb251,68a083e9,9107c20a,4d60e326,3ede7fa0,10467b9,d2e8b206,5b09e127,e3fba9e,3d228439,50d63ea1) -,S(e9032f9a,567ab8da,551e0f8b,1b2c2c22,6e601b7f,e894b837,3bd9eaad,3662fc84,ac563e6,47d21af3,a0cb0a49,dafde0f1,21d60994,8dcb4000,64e3196d,74eb70e9) -,S(7ce746ec,44af748,a5508044,f56e3467,a9608deb,c8a051a9,fda907c3,8f79c75,8f0879c1,3166bd23,be7bbb80,46f3c019,2c6b8fa0,52fad7d5,40640fd5,f2aa426a) -,S(e0d52789,19de6d1c,a0929856,46cd3200,68862dcb,ef369fc9,6c6de4c,bb59eecd,98f4679d,b4ebdd90,a4f54791,29740bd5,f46680f1,d3ebfce8,8cda2946,ca886b20) -,S(c6a245cd,cf1f4b58,4400a4d4,82f2088a,e28c8b85,641c1f18,a13aea,7e5ca397,d306dbb9,f8f2cb09,958ff944,ab5e6cd1,cb11eca8,33021bf3,605e6768,961ac628) -,S(ff956c8d,9710f082,a1f34ace,c99987fe,4ade0919,4a0deb06,a1b286e7,3695c910,fabec52b,866afd46,1fe8c832,fd8a9375,a8086aec,b0e2e39f,b7823d0c,13bcc306) -,S(549dda4a,d1a604c,d0f44fe4,5c4dc276,5cef1216,6f4accc7,3ff12152,26c23af0,71e3afc0,e05ba826,36eede7,1abb15e1,166fec97,562c4381,a33f765e,100631ef) -,S(66d3df09,21573cc,e69896e8,2dd91f9d,6070dd12,edc21723,2077e644,9e776416,93981613,59a2ee3e,d9429dd3,eaf058bc,9ccf1c9,ea931ebc,25ff279d,5bb46d5d) -,S(61bd3dbc,9426386,9c53ede5,a5c4f186,8a4d7a82,fae1be7,37b702f5,79e4f8d9,8c056a47,e27d4f49,2c9ddf54,efa48c,502aee81,e2336caa,c1b572b4,e082e780) -,S(8a6d8b46,4a31daa9,2702f784,9148db1c,4ef20c76,fa67c006,47d6f3b9,80178f4e,d1f406ee,e4087601,96c82f9e,38205147,c31309a1,93bf4d8c,cfe67cba,ae8f7407) -,S(e2b60e93,99eb8441,700aa90e,1edd981d,37893b42,5acf6b1b,809fd1e4,922e573e,68a0c65f,e394829a,8ae09dc0,ab35d789,bd8a38ad,800e9ed,63513eea,4e19f7af) -,S(4c76030f,e85cfc92,64f16cad,99dfa541,fc23b8c7,2b558574,ac6f26cd,d4f55e85,44b352d8,9a31b4ec,c8f9a574,51855f7d,e98c63aa,98aec090,2d959be8,a12b7bb6) -,S(dcba96a3,59103c35,aa2c9ef,538c13a0,2f0e8997,3663d580,fe454762,5fbaed2e,af9e205f,727698a,de9f91bd,75bfb73c,b13053d2,db2d83de,b4d14c22,176544b4) -,S(fd0497d8,f75fff9a,cbfd3e03,6c9edc73,e682427f,e9b66a43,3b5b2b31,f2dc7883,d23014b6,9c8d1077,ab3fb2fc,c0bde4a9,44576289,896de135,9c0badf,fcd62d79) -,S(5bb401bb,b38e413,43d1b779,54e83f9e,e705009a,eb8a1077,542cc6ed,edf48040,431fccb5,acec1391,f68ea628,378e3ca8,ca944573,ecfa5e,e7a82bf8,82599c14) -,S(1fa96a4f,f9cc6ad8,b2741c38,b35c377e,3acac704,67bc5d20,a262db5b,48bb283b,c3448c92,ffc65afc,f1eaf7f1,f9e149eb,6404dcc7,1b222ac8,bfca8feb,eeb963eb) -,S(9534aef,1ae551d2,7a638453,171d0a63,697ea420,2fec8f11,61432291,642f86ea,cd0c943c,38837dd0,33d48a4e,ca13e96f,46fd7f21,2cbff849,6432aac0,ef729591) -,S(ea72afed,43300390,bc98d08f,3aa4ff4a,138440bf,1a8f8b7,b57032a0,d01b8ceb,e174dd8c,3692cc2,9ca856a4,4eae7e94,af4fb044,85172809,25ea66d2,d858663e) -,S(39593534,3ca2523a,603801f2,abf3a1d3,16569862,35d79fa9,a01f86d4,5c122327,acd3e3e9,2cd76dc8,551cbf0e,94475125,42a5b887,ac6c975b,45d2e000,9953dd96) -,S(d57b2a2a,375e5a0f,6967d4b5,3dfbb51b,4f74eff8,72742a3f,246e3e09,ec2d4721,12d6f848,4d107ec3,10ec2091,3482781d,c0aeeb94,71ae7b03,6a0d2551,d3ed306) -,S(9f2dfc5,1b99eef6,e6c781a,fe0135d5,fc5def8f,d520119c,59bbaaf6,442f1082,8f20962,fd273048,fa3ca6e4,ea96fe0d,7ad1d758,99e25a77,e0f8b56e,5b20dd0d) -,S(b1c30bc6,f030c913,49b36c1f,9c0deda1,afa58776,58c5a16a,9352c1bd,229884b,f8a459d1,6e77888d,cd5c63d1,8a2e28cb,5563e727,f53b59f1,939390c6,1eecdfc3) -,S(8a663e7,40cad237,12dad6f9,1bb5d266,30542933,853e02eb,665e198d,a5c6e53b,e206b399,51175d15,daccf711,63b0918c,786a8fe,2077812,c0c1eee6,bb5c1e99) -,S(2b0956cb,e0ca91ee,f44fac0a,76cc0b00,5f4a5ae8,27e63696,fe1aa8b4,a92941a1,a31e6fa8,dd454eaf,90ee1e11,62627e3,3f84b8fe,da29f423,ddf2a962,386cffd2) -#endif -#if WINDOW_G > 13 -,S(e0144151,7a2ac970,eb6381df,7e11fb4c,6b009980,6a0d330,d5429126,e662c3bd,8238ce9b,a691c80c,21563934,18d18dbf,aeb3fd34,48863a1e,7f4ba360,408dfcee) -,S(be3213e,8b062f33,caf16c53,5a0b666,f344e0d7,1e28aeba,8b215a3,7ec86c37,552523ba,eaca38a4,cd795683,852a2643,550fb83d,d1db0adc,3f1b29c9,7d51cd1f) -,S(623393b6,bfbfbd64,fc7aa1db,9e58e274,1c18eb6d,b5eb30ab,c4fe167e,a9e8ff2b,7c0e4174,f0fd5bf2,a025e316,fa3b7b97,1339a197,b52b0b50,bad4dfe,34e42cd3) -,S(dadeb702,dd0a1e87,669eb624,b8cf40bd,bffe79aa,8afab26f,bc6215b1,dcfe97a,930890ca,e4c29b41,2d660acb,8cd39bca,5a522599,a1ab0bb4,8fbc38df,17253490) -,S(b528d3b7,83179b82,bb1c9cfe,c26184cd,ac98ad5,8e253c13,627fb778,c9362f33,63203af,1545122a,63940676,ba2d18a1,aa902e08,8bb444f0,47c2bd52,db8babab) -,S(2ff223e0,93986e22,ae418a5c,804e9e81,7a4de562,d7436e0,2d025ab7,11734a6a,c5c8d188,ec9cda19,bda76d8a,97838ab7,81990475,d4a00096,5efa79c0,100f678) -,S(cb8731d5,e1e53c9,ccfd2c39,3c8ab1cd,9ec839f6,99fc712f,f946e74b,99eb1742,cd2f9df8,38fec504,dd125248,92ce8a4,a9db3848,e487076d,8c18e53c,f6d19fb5) -,S(1377ac45,d776a5cb,76ec265a,af272690,6dac52dd,be987799,36bb1271,e0cf4a2e,a4b3330d,d5954932,d5a7a818,7d9493e0,25ab2155,d4ed0d4,f34aca1e,c2a04670) -,S(984b9bf2,f140c75f,e03489bd,88041faa,22fbac73,7ac10724,c511a253,641a5ccd,c474f639,9733eecb,a750ea82,ac4d50c7,d82f4c9a,942a2bb5,90b1431f,c8d14ff3) -,S(4b8fd000,74f57cf9,b135d56a,c002bf99,d5050479,7298cc4d,857960d7,afbdcb06,7c044103,1df0f6f7,721937a4,c60cf76c,95560ee9,4c6d097e,3a8e37b3,34c703bf) -,S(57316653,68412236,619250b2,58bd0ddb,34fc751b,8becc0b6,60585683,218b6079,d1d56e4f,30f01c57,48972898,b8afe142,16f8335b,e3a39c37,da64050a,91652904) -,S(c9a00197,a0ff16f2,fbf2cb59,767d43f4,60737367,4f2bbbd2,53c7220f,db69f286,177c6783,d739117c,1de074b0,c605cabc,6b4dfeed,a531f4e4,9cc518,40142f0b) -,S(e23416da,91df23a9,db161618,579b3008,c87b9ef5,7ee8bff6,45eec6ce,a61881cb,e556417f,84043691,e7ec82e0,e1718296,e42fbcf4,a3de0137,93772dd5,70b8da15) -,S(9f96e3f2,369d753c,e6614c45,77bd8a9,14293eee,8a749c1e,3b0e2955,638e9ad8,f5cd1268,1567a4da,71650d10,e413e0eb,9b01a396,e529cff6,b494b2b9,a21ddff1) -,S(48657ba4,b24b0123,cd54317d,de6a3245,ae488078,5ba43d5f,1d94fbf6,b9301fd2,191edec0,6eb53781,2813ca77,2a9021b0,dd4931a0,929a7e36,a4a8c66f,aef0d890) -,S(67b322e9,d72e864d,8cb15511,11402d7a,c6c858c8,77832d4,e0187e69,6a36f24a,cfeb12c2,6b58bf15,3bf87058,c5faa833,e15c867,f7f9a208,c3dfdf3a,c7f6946a) -,S(42e8068,542bdd98,fcce8925,52002db,c545ba13,16082d40,fbde06f0,a44ded15,1645a9b0,c1f33cf5,27364915,8c4f261d,a1ee814e,7aac6402,bf644451,bfc4aae5) -,S(8ee7dce1,339c50dd,55619107,9bbac005,3e058cca,4a8c8e30,7588c105,fe90d4c7,ffbd0af4,8aae8279,2cda6170,5dbe9fe0,98e102ff,1e6f11d2,b4669a81,6ec9d5f9) -,S(abc9504,12926a71,6adaaaf2,7b209216,37a935f0,cc66eece,55978a82,1fa368e6,72e54935,e9b461e7,9fb75c48,4dae4fd2,155a4a48,d3a467c9,624c5f6d,71f79203) -,S(bd250320,81e0e9b5,3b00568d,40378fcc,fd72fd8d,783f2f3b,433ddd1b,a6976ba8,5adb8bdb,85855498,994ca879,717b8e7a,e8c4c87d,29d6a1ca,4c3c6395,6c3ceb39) -,S(b4fb262,fbeee84e,49ae9167,7e7aa0d9,b31609e0,48888740,c018a5e1,8ae25f71,34df3f86,dc091d51,258ecbe4,1cf616e9,265d6d36,8ea3403b,24cdc7f8,e176e5fc) -,S(d1ba9b67,66f24eaf,a145ad14,81063b5f,e4604817,21b361c4,95de8833,be605c01,e80a6cbd,17de2f1e,663ce7f2,8917e3a9,f871943c,a4b8ba75,68476a3,d9e8400a) -,S(5c98b6b0,3a3e5a8d,2d46652d,5eb9e2ab,a80c6702,69dc5ba8,3732752e,922639b3,81e2f9a,145d0cdd,2c51bd13,f907a04,6a35efb6,635292e0,6b8f6513,c50f4a54) -,S(c1fa4688,f75fb86f,61cb7071,4fb25f2e,908abf0e,a87aa84,c8db5dd,4c2618f8,f2f74a77,6d4bf26d,17f55d0b,1aa913cb,9db869e5,ab861d9b,2043ccb9,ca8397ea) -,S(5e806e9,a644eb32,51c62ba2,f09a755b,96aec78b,4405df76,dc22ba6c,f7227ec1,b88c8118,d6a1829d,6aecaa05,742313a,b871d2eb,72f31bba,9d84f87f,a73e614b) -,S(f9d147fe,fd2c1a7b,f623d965,bc7901bd,968636d,eff54c14,34c6326e,d1c8de9a,c7887249,ab6686c7,93a7d77b,41173060,40de44cb,84980c33,cd548d72,d29caffd) -,S(b98cc956,85f6d11f,a8d38a1f,50799634,9f7020ae,3171023b,abea0fec,a70ccdb1,f074d495,3689e8a3,6ee4cc0d,40882355,3dcbdf21,70975f49,5712adbc,990ecf7f) -,S(f161cad4,100817e7,ef9091dc,714bcba6,18458493,f3bb6b03,4648a649,6817b474,b7eeb92e,396af324,22881eb2,45e62515,c4410af9,fa519ffd,61289f6d,9b740904) -,S(7c8b6c89,2ea4061e,456abac2,46edc08b,fb54aff6,8a2678fb,1b7b1c08,5326914c,f08e1f02,6ea1d2c2,9ff5eacd,2b34682,2960723d,cdab95b1,d69c8af,5e7692f8) -,S(4668c29f,16334658,195b93cc,ef71a076,3ab2078f,724dde5d,d3635eed,24f28729,5db228c9,8391ec52,324c723,39d99514,8fd22f7c,2f61cfa1,29ee7400,4c74ea4f) -,S(3443d0f3,9dd6da5c,19a39f8c,f3672652,96fa6729,c9290b2f,4e21c7e5,3167b65e,4b6db639,9a088ddc,8ed31f63,7c079451,14a4320b,b7ed94b9,2a87c0e8,97429234) -,S(d3ce3501,17a04e95,58281e69,3574c096,458dbca9,afac20e8,ffec7810,8bc227b4,bcfc77b9,628f6ee9,3541e47f,8d556ad0,7696ee6e,90ce384a,9b77fcab,6eb9908) -,S(c4dc6363,ad772452,221f8640,9de0ac28,f2bc1ac3,cd2d7080,23301560,f95127af,78c9ba8f,d789a666,439bc949,38345250,38a79c5,97f6a71b,3e096b8b,752d3038) -,S(c771f94,221a47ec,fcd78d7a,123d2e0e,1bf4edcc,bbcdd075,b23d29da,6d5ac666,4dee3b30,829f5aae,f4471924,65de293f,f2ec526f,5b8f5980,d9155f71,ce8d6091) -,S(bff88ce8,96338f7f,5b6516e6,448a1f25,36a1e9bf,275afd50,e772517d,79e6e199,8f3f0c7a,b62010a4,eb0b6211,7e9761d9,c1552629,bb55bf68,53274158,a788c206) -,S(4afcd064,5d57bf24,e850e7e3,d3cac224,6a467e76,f2ce02da,576a1f2a,9a3b97a,52f23b54,87b2af93,6cc692f6,1876d6c0,ef927d3b,c06df93,984ae54e,4d10f0a2) -,S(c4bc122c,b9bf0e20,57f933fd,94db012f,79e23c34,98007abd,f8a8ba21,32b1f373,e40c47b6,a31d81ba,dc45d427,3ab56d77,1daf76bd,7bdf8ce1,a8778861,66fbfc6d) -,S(487a19b1,d1be7791,ce223d27,bab11aca,837a0f8a,7d34d9dd,b4c68f18,51f821a8,a53cd743,16ff4e9a,8633554,45415e35,5552403,7b25ce67,f519e44a,a5d0ef98) -,S(274a3cec,be06c748,7603516,588ccffd,f4ac3d80,a85887f8,10632cb8,4301a326,17a24be3,afbe8b45,9a72cab,5385cb6f,5d06b47a,63bf19b3,ff4989c4,85a9f40d) -,S(32b31f77,b0cb99ac,3bfc34e,7558f9d3,e82fcc6a,be2c4,8a079106,33afa9e8,447b44c,c191da90,e0eb3f71,db804472,17f422d5,b1732a8,993da80a,5d8f5bc2) -,S(78c39dcf,55561468,dc339d46,ffd09337,945285e1,66dfc29,25d8b85a,24a2752,d691ddbb,4e41ca85,eebdf63d,5c023e62,a6680931,5e1109ce,89088467,7ba3ac55) -,S(5fc75911,a4920777,c4502116,deefc1a8,d2f21f96,2b1e725f,a04d6fb3,9d34e5ff,59f36f7f,18f5885c,dff524d9,6a139749,f3fe1662,4b728d50,7a460bb3,497512f2) -,S(ca1590e9,152b2b49,a6d0fc16,4e346e19,fa62dde6,f693b64a,e38289d3,ad08fa8a,46a7bb3c,1174ed75,49e9eae1,7126455d,535ea744,936947f5,24a8ff30,8046dc8c) -,S(5c715266,5ff0bdeb,a7f6e660,bf66d5ad,743d94bc,5ba9b7f1,f3d50cdd,9d11fa1f,7da23b15,56e995c3,a21ee9dd,ccccca4e,e41684a4,f208c39,b31ffe9c,4473a03e) -,S(c7f71da3,6361c73a,55dc3877,4f2e1033,fa0c09ce,1c9557c8,c29d8684,e4177e82,8d6e47f,b5c2cecb,6b22dbf9,a04f0f95,77c6f50c,3429df92,78edb85,59b0dedf) -,S(6e91bd9f,5264a13e,37925900,433b7536,4130b4cc,e6fa716d,a0101c2b,dc58afab,5baa7455,506b5849,5d820c20,f209aa01,ee0f9434,1df5b449,9ed23a51,b4fd604f) -,S(1f00de8e,69ac7cbf,c75c789d,f3322813,244907a0,35059072,68954196,baef0d33,2892ce90,f32330ed,2800c30b,4482b67a,e65fec8,41ba6fea,b2e83703,dae040f4) -,S(c00133f5,7d8c469,421efa3a,d71d8d58,1a2f5b0b,2324de10,91d79145,7d300638,3c76b182,d3ee982,dd05ea45,59e8e31b,1aa3dc12,fdcb67a2,f86434ed,34f18895) -,S(af639e7,95e8269e,12cef756,4bbf970,cdb172e0,66cde48d,2f8e9083,c60cad49,1bd01179,ce92cd29,e414a74,cd1de487,c479daf,5673b219,8082c474,2426abb4) -,S(e6dbd27d,5447c044,18fa0a5d,8ebcb9a0,ede58538,8b73ccd5,4e979797,31f4c9a1,77f38524,f2848320,3d4c780a,d0cf8bd,a2071037,348db8ee,6b5deabe,3d242153) -,S(f51a8d23,c95b70aa,d02dd904,ec1119ea,8d1e3e1e,e405646e,4c2dfd53,336360a9,426b2c9a,1d703cf6,c748871,4959acda,ae5c6aab,51945138,73e4b1a9,c0f46c57) -,S(e12f11e7,fe437b7,f578d8fc,33ae3a60,a3e4d1ac,1ee45863,42944d50,a0f6bcf4,22d15d58,35fa89ab,563985b1,4114c957,8bfec8d6,6dc7d253,e3c6d900,4419f5d2) -,S(e758860a,8ec762d0,62f51e56,d958a14f,ac619351,9d890bb9,bf6bc7ed,e988e14c,42d9e0ef,10b84f21,fb88d780,dcb4750f,10438682,3b003b23,ec41c297,567ecd78) -,S(3c933fe9,ba21e5c,d822b90c,78a54b7a,d4799882,ef91f2c6,e423a398,20a64163,c1eaa0be,531922e2,ca5b23a5,6700b4ad,7fc16135,11f67f96,b672ddf3,669080df) -,S(4757576a,83c9066c,b6eb6b08,e91a79c0,df828e4e,3c09ce07,939134fd,ea857872,13f22fb2,62d77f15,de3e8388,d9270c45,818248e8,9d950d7b,58ee6c6,c38277a) -,S(35e63903,70085140,b19df903,9a7fff42,46570fcd,8661caa8,129d6b4,31045c7,2855f4bc,aa9d60d8,6a44f022,b3c28e84,53cfb3ad,a58691f1,b0e9cae5,e5b9e8c9) -,S(ad446e01,1f118207,3565f031,6d0a85f6,ad5330dc,6a8be4fe,82be632e,32126fa3,240382f1,decee3f5,1f92b2f8,1ac0eab2,1d8acb54,2f730d43,15c194f6,28e83e39) -,S(fbe9e5f3,eb01ac37,820af752,9c4221a6,89164ef5,d77461af,f82d6400,6a718815,f2f30cad,d85a2e0c,e393e088,44de9215,ba207384,2abf8468,47801ff6,12d088e6) -,S(1e675320,d81ff430,a0549aa2,482cc9b8,b9b585f6,32d32916,6e952f13,3b038135,ca0f1276,c9c7d995,c5baa5de,2988700c,2e2c7f1b,366d1db1,b44b4c9a,f0686aa7) -,S(176dc770,23b0e52b,a2eb8068,ad27924b,94c3f643,30e0e85f,3593917c,d6267718,d2dc6288,5df75b06,f450686f,df660950,548d4f6,85d1a701,d510f3fe,297ca8d9) -,S(3c8536c2,32a02b3a,b36feadb,ccc7c541,7ac83942,3cfc8dd,99a0ab7b,41a9c938,a684eea5,249cd12a,d24dd8f1,73022ad1,8ebc7f52,d6a3bd9d,bdc4f5ad,a25186b5) -,S(48aa73ab,c61a76b6,e54c446f,ba881198,ec6ea003,d63c54a5,605a322d,7af006fd,c28c5eee,ffb20882,2d018506,5cf3ddf3,5977fab7,40e4d4e,cdbf9935,8e403a64) -,S(74732762,abd028d,9dad2b36,38baca49,263d170d,ca7e4cb,d83a3a1b,53cc1ff1,ca11df0c,e8dfa09f,3f2ef7ce,5c023b6c,927a88fe,60ba9f3f,ddfbd69d,e536c2c6) -,S(eb71ab09,520e5915,767dc918,814fe901,a4042725,5247c02e,b8672c5b,95698522,5fad7ae0,a7e95b38,ed6563cb,2023b2a9,c81b6901,c007f1eb,8749f56e,4d48e995) -,S(2b101bf6,c7763df5,72eda74b,eb179cc6,af5e8695,965761ce,f8444371,7ef5be6b,dd16c8,4e1d1a3d,98d4629f,ef258421,f6664719,7f89a597,67fe862,3f140ce9) -,S(a099efa8,2c666552,5332b050,75e81ba2,13976afe,8f3b33eb,ca2a4436,6e0ab337,f883957b,5cf1f2b3,ddd6c7fa,a126acca,fb1e33b5,e5b753ab,dc0a99bd,5d136c07) -,S(f4396856,a61c3ce9,5b72ab6d,470bdeb1,8cc107cd,2f58f15,3d5bc99f,8b62f95d,6e3ead1a,a8edb0b0,67240ca,f3274e63,df81c2f3,e1ef2567,cfd76c01,6e9f6133) -,S(da732197,26aabb18,4a0aabe5,a493d803,53215b7c,49458008,bd5e387f,694050c0,e2075f29,17724b68,6bcb987d,85e954e1,9489af4c,e7ce1b46,66d84604,e9a0eeb6) -,S(99171a1e,19596183,f4259c09,b9740201,8fea44d1,4d0f2f45,75f4d66f,980a6792,522b840c,83e1eef3,e7f2cbd8,e07bec0,66af1bd2,e7607f5f,27a767b1,75219a4f) -,S(353cc684,8a2c4f36,2408997a,944889c0,1db7bcf6,9133323f,8f0d34ca,758cf08f,1865bc62,f4ba0156,7e2b283f,702834c8,97effd14,6e0e5fa2,43d5124d,ce67ebe7) -,S(8b16983b,5053d3d3,8e67c77f,1b6fccc1,b9ed7e3d,d57a26d5,deb242dd,7a312852,49d93f92,fa5953d3,956adeed,cff49ac8,caeb3d2,c72a0e9f,be6c85e5,d85d47c6) -,S(68f5dea4,b1da327c,227b2513,83fb622,efb36730,3bac02ef,505e0464,750cabc9,26740f9c,5d624b9d,aed25774,46c9c742,146de045,71cb750c,4356898f,e3d31782) -,S(faf5207f,c3acf00c,8e19d8bd,7208a6d7,cc936706,98559244,e74bb202,20c699b,fab7b446,17a6c6e5,4ac186ac,971de8e7,d42c1527,8607eeb,b8564a0b,cef1936c) -,S(c3d1aa91,b541c5bd,3da04707,a2f01a16,917c0420,a26604a2,bcaf5081,e8d17630,5b57806e,5a58c405,f06d7ce5,4e5f7b45,c9b631a3,44c92c64,d8cd1435,fcd9ce27) -,S(23278a35,4970b920,450db526,391b30f2,54b5bd5a,fe2c1455,623c99fa,8ac8db1a,864d81da,e8df9e47,1ac93b74,660542df,3570486b,fbd2144d,55dee441,90e1888b) -,S(602f6181,33cbca4d,74de4ab,29dcd101,7c12c32b,ecaed25,485765c5,478c0146,4c42cfb7,279ec350,f77d2da1,599b9c85,9ffab342,ce6a011f,91c9e460,27aa968) -,S(1dc4cfc7,126c3b2,5d82aa46,3dcc8cff,c545a9ab,c7962690,fd4ecaad,25843ee9,a9357982,5c535575,35820f17,25e32afb,6002b1b9,2a9b43ac,18225e61,b3fedeb1) -,S(3694f121,6e02bc79,14cd9910,8ca65fc5,887a95df,8b04e8b3,3c6c23cf,ce35af82,7ffee291,b1c41976,d456e742,88458b9e,c61e57c9,9b8386d1,d1c36424,38555d88) -,S(743ada75,a9596420,7b8725e0,af06c2c4,457be03b,a920c3b4,b65922b2,1df1bdbf,8f2b81b5,5ac4c5d8,9cc23ed,92dc1b43,5629b9f9,39b126c0,b16d7175,b40f908f) -,S(bfe9397,7c7cc4a7,b9cc42d7,f044607c,f047cf2e,26d6f94f,210af7d6,b2420085,625d6059,8f80dc83,1ef2b51,dee53d5,666c3dfe,a02e1d92,1260906f,ae373d64) -,S(86c02c0e,6ee646c8,c2944751,7867a1ad,cb56ebff,c8795f83,73e6d8b9,1b240eb9,659b5e9f,da4b1098,b76af529,f56f809,59d39f48,916477b4,bfa66af,c85be4ed) -,S(3b281045,857f01e9,995d357d,3a84dc66,6c4f8f47,4b82ace5,dc3a9229,387bfda4,9948272c,cdeb1542,47c7c42f,1f313dad,e318a123,3f500f8a,16d80e7f,d2e9fd4c) -,S(cddccdd3,b54d979f,504d33d,46d6ff2a,9859038e,33087a3,da9a5284,fefc47c0,9f2a13f8,369313c1,44d91e5e,807ddd65,196c991,a7eb0321,2133aeb4,56683b8) -,S(98100502,a6023ddb,ee34462b,d0232711,8f8c2e9f,33708088,40352c34,870e16d7,1a8bfef4,69af3b3b,1e381c08,454a84ec,4cf8fb66,bd721a57,47a94e90,1969b9cb) -,S(8b76757d,b2fc179b,9016847,9b82124b,c26092f9,b35de316,c90223e5,99978179,47eaf326,588e65ca,541a71a6,a1167321,ee449268,1e8b4960,6eaf9a73,42b16f05) -,S(e66ed7dc,897fb660,6f44d8a9,46b0c61c,45c83bb2,d55ea771,bf2571d6,7ecc3b43,e536f79b,8a9fff4e,c6cffd47,8a405bd,7f1745f9,9374d810,518cc5a9,f214dcbe) -,S(e0600592,cc9c0b9f,8cead065,6ef5c115,ead63209,6a0a0d2,2626aa13,f2bc88c8,628d94b7,8b84705d,16e55254,4c138416,e7f75f5d,d549ff7c,a42d51cb,7f5a584f) -,S(1b0af242,a9cf25d4,cc758fc7,63e2f07,62db2e42,6b392cfb,ffc5ac07,19152767,33ae8aa5,eec30559,a3d28da0,d9354048,592dec4b,2f975a0,ed043fc3,c856a2be) -,S(e204ffaa,142f7eda,3505beee,db0bcbf0,9b80924d,ce5bced5,439aa4d6,af5acb7d,a2804d9b,98e11519,adeacdd1,aef2c22b,a02f7030,479a559e,6924db49,5d8911ba) -,S(afc40e67,651531f6,214ea1fc,13173d4c,a35431f4,92845964,69cf099a,d515ed5,57ef6ef4,1e480de9,32ae8596,3b04d267,5e629707,cd3bdb45,5896d333,b648e0) -,S(59538bdb,747b641f,800588b0,45c0e3c9,72963406,5ca601d4,690dee22,abe8d226,a030486a,3c919c35,4c26547a,3de96087,52ca7a28,5d378e28,652031dc,ec2d4438) -,S(6a91d34f,c38d4028,c63a4bae,bedb2a76,b964cf44,1804a6f1,efbe469a,a997ed8f,32500c83,6a0b5274,2d2ead10,dd3e73eb,45f221d1,ca6cea00,f2b01d75,d9073260) -,S(9260e687,b11d97ee,97dc44ab,5e21c344,332ae39d,c85c2ee8,f7760cc2,8ac28d61,f47df3d,e8d8654e,f7124f5e,2dcd9d95,c1d13e83,a33e5d18,92ce9851,6223e778) -,S(3490e733,7a66f301,f678561f,4b4f293c,b48820c3,dcf9be06,a0390410,4cfe3cba,49591a79,7edb70ac,74f87636,85bbb22a,a8169536,532886f1,f5ea0721,5e9bbd6c) -,S(9729f4fe,1f47a9a3,7dcb1311,ea9548a1,d71d7a81,27803c8a,6ec0a680,8d07b4a0,56e1a5d4,ccc4fd72,8e7ee569,e22efea5,c8f03d73,fe8ab86c,2dcb8af2,eb17f896) -,S(af63904f,6da423d,1cfd77a6,680044f0,5e694eb5,80ccb4b1,c37d8d83,ae9c2caf,6decdc2f,5fe2b948,d15fa10b,4a7e2edd,b8cfaf0f,7c79a400,f3d1b306,dbe110b2) -,S(96271f72,1f4a1f21,a2274edf,87c294fd,403cf0e0,c7b7b1f2,f242fb7a,2c435a3f,66ffbc73,1fc8cfd5,2bfbbca4,49f6e949,71940077,ae411e79,51cf5b21,ca5adddf) -,S(a42ef215,1f0cc5a0,15827287,eba8d960,dfa5a13c,7ee2696a,95bd94ca,4b717c7d,5e491ed4,5f08a591,32296929,814608ee,e3243172,b523a1b,a4995f6b,50046fec) -,S(193b3ded,e770a757,d859c289,68be2780,fc4ce92b,135bec2f,7fb2c07b,b862e5e4,192c4bba,ffbb735e,a1d5cd1,38de0556,d1d1d740,980c5775,22d19b5e,f0716700) -,S(ccf9a075,da6f44e4,cf3b4fc8,26feef3e,54084b0,e2756029,e290a7ce,8c1e8dc7,d04f844d,ccf2c30b,9020f0a2,308219c6,a5d6491,ffe9ba67,bf6b20c9,9a35a183) -,S(7ebea25b,1d69bb43,f60ec69e,f9853208,d3ddffb9,6dce3831,873e7ace,d25b0140,24540af2,bf87d637,54f1a47d,13a3f38,2a948375,8955dd16,fc83e7ca,4fec3d65) -,S(c9eb4a,c2a31b01,9b7ff038,38478b6,674662eb,d729ae45,d7111c63,84a038c7,7e2ee03d,caed3f4e,bef2b90d,78ae42a3,12f6e8b3,29d116a6,e26bdded,81f32240) -,S(45756e0c,8c84e9e,a7b23bc5,cfd87b4a,cd0b290d,86c547b8,7fed946f,e5acd867,9c3f522c,e577c017,3db984c3,d7dc16d0,31326e2c,85b08413,4611da0a,70acdd1f) -,S(1bd58481,21bed636,c789e341,665e2477,59438de7,10aba25c,e4a0db7f,13e3c0da,cb0eb897,bf905399,63a8a7b7,50787430,ffd4d6d7,9589c8e7,350f4351,4786a90b) -,S(f199562c,8e809ba5,84aa80a9,759dd98c,32eda7e0,ccfa4063,547ced9,d9324dc1,33519ead,76430498,949dbcea,33ca14de,2f7ea811,cdd38f32,4009ac7a,b408d1d0) -,S(7fb4e910,e9e37dc1,f56ac3b9,30589522,975319e9,84dcb559,6743d3d4,f45ea6f3,b74a03c,cdbec9c,f36b59bc,fe3203dc,5f4d94a7,bd54c628,55f0d04e,67c960ee) -,S(503d08fd,19839d78,aca27020,54dc4233,c1a1d68a,6b9cf136,4c6fa9fe,886c03e6,84ad95db,9a09eb87,bd905914,473d23de,698459d5,7c436f77,58937bd1,8e448e0a) -,S(335c9204,e6aed3e2,586d0dea,c87158a5,62db42c8,e42fac25,9196083,51e1e713,15b359bb,10f8bee2,940849d4,212fdd84,49b60c5d,d3419ce6,7ef9f0ac,f4c1c2f9) -,S(ba68e5cb,e0f7159f,821117df,5720bb50,f218c298,9ce3f5ef,30c44134,2834bc9f,2ac25bdd,ff34e4e,ff45a2ed,e412a287,101ff447,71c657f3,ca57bc94,40fa5d72) -,S(93d6e713,311d8430,58c20267,739c494b,446d7943,a1e47a0a,2a5ec20,877e6baa,5997c19c,99a2fd26,e0471041,b509f9d,e10bf615,7cd4f24f,db56a65d,201a0856) -,S(7a94bc1b,5cc77a0a,73a84fbe,c5d1b68,cb8f4626,8ecc0c22,ac7500a4,5f397172,128c1c6e,82a4d52a,719c9f8c,1bedf4d3,32d3695,16decef,34af6b4d,578bee5) -,S(f031eda7,c19383d9,45eec848,f6f3e467,75fbe52d,bacadc54,c213c596,c821b809,b4a78d0d,1c17e4f5,db81e2e7,ee52f195,eb505d36,af96bea0,5170c776,23cabab8) -,S(86ef1acd,5c17e082,dd4cb924,c74d0195,ce9f375,60ca7608,57ab7d70,2039907c,6936a13d,b9078ac9,426d34b1,6d5673d,36c3105c,9cc77de1,ef7e0ec2,4cf3bb3c) -,S(fceb6cc9,c78e3a35,49b9beeb,62a14fb8,6d24eec9,2ab10bc9,40916b60,cbc6d720,7c2e6024,5f561f1c,e0b69701,512ca518,9f8d9292,ea75562f,8b17873,77f7583d) -,S(a1d9ed1b,9a36f348,1f426d83,7afe4380,d475e36e,3b140f3e,cd2213ee,dfa5c8d9,3683c97c,a1273f29,ec02cb77,9e9fee54,78bd5e3b,e6aa8c60,7d5bf07,dfa558a0) -,S(d98de999,6311ed55,e15bbdc7,58affca1,3e8f629a,77eb3dac,844f90e0,51bd48c7,8af6194d,272a8ee7,68d1b810,778e5c2,69394353,969d77cc,7d449f2,84ef2a22) -,S(78328db7,cd6afa29,b6f1ba80,d65f8050,60f4d223,9897a3ed,bee8ba3f,a99aac60,e37e496f,1d143ac4,8123377f,4e136442,629f8185,c4996f01,f35c7a9e,76fc5efb) -,S(3d701493,31faf0b,37c1e1c0,9b29ee6c,5d9747cf,cdb26117,223d1f66,e336db5e,d1e99140,8311b20a,b41f7ce0,ab4e9dd3,414ea3c5,b87f88b6,648cd1d3,e77600ad) -,S(f619acc0,47e0d4ab,bd5ba2a,7a54ecc4,e223986,fdbf7a96,e90f762a,ce288628,f24eb63d,e1545d10,fc96a2d7,e7fc1ee,f9cdccdf,cefb5de6,8fa4eca6,781564f2) -,S(cca809b8,71f85a00,3344a851,4f797fce,91718f35,9e2fb489,a1dbc00c,aad0a2d2,b7d72ab8,35658359,2258f260,a1f62f97,aba642ed,382992f7,12b11c11,6890b037) -,S(bbd19766,ee2c501d,afb4eec0,30fba145,aa26c45b,51c1beea,a7d3ed1c,7dc81958,bc709dff,70b3612e,7cf0a6e8,9724442f,6c1ca4ce,c32efcfe,b98f1acf,df5250fa) -,S(6a6fdca0,e4a58197,267a1938,1644aa5d,ca8f0ee8,3a68a5f7,9c34d4af,ec1cfadd,c28b1236,76585255,cc104298,d7ebcc70,6bd7ff6f,cadb0c36,db6517e9,d2732081) -,S(922e3e1,fd401a22,ee7d693d,e52f0ade,9564af2b,17a4be0,2c553216,df5c8006,a7b10065,aae84a40,b9b79e0c,5ca8a227,696841c7,20b944aa,3b9eb1c4,1488f757) -,S(53ffae4e,3526b553,f92bd9da,e3cbd3b3,aff8a6da,d4895490,38382f98,a676eac8,81fdfcae,b51f80b8,3d23b222,8ce860ec,9e665292,c456fd23,cfde43ed,99f8c6f4) -,S(14a0ddd1,c94596f8,9d3e7028,929cfe4a,7c2e70c6,b55d15b9,77227862,a03d119,2b5dc071,febe1d1d,df7e1483,53dc6558,7e8c94ef,b598ee83,806f1fbe,976dd086) -,S(7368240d,fb74f35b,b51a2542,8caf3b90,bebe272a,739eff4d,c0150f1e,3d68c8f9,95392b17,b4c5e82e,774c7168,7c46469f,21801a72,b15cbcd8,fd2ba85e,e4a7a27f) -,S(4c0a8053,b9eab39d,2396825e,2416885f,5fbdb610,7bc5879e,6400d010,20580560,85a222a7,5b7de532,617f67f6,5408b79e,f5a6f826,6083c2f0,93ca97bb,d7db5427) -,S(ca0d66a8,24a6f8ac,bd9447a4,933dfcb2,6751a26a,f5790a1e,91e32053,3ddabbf8,61cc898d,4f8b0845,11dfd49b,1ef01e43,6f7d7d08,a5f16b2,1550f329,79395d18) -,S(646a0775,e62f6a36,d520763b,5c7fb081,a3d7dff7,355cba76,45358a6e,55e9d6d4,3e528844,e7380a64,20db2366,22c936f9,b1100046,e17c66f7,a6b1a01f,7b7dbbb4) -,S(435565ec,f3d6bc13,142d7c47,7052da71,bac77f3e,a81107f2,30303003,6455d070,4ed52896,89fd8d96,343ca8f6,c9f0c70f,ab6edc5c,1ae96d15,9fa9eb4d,a4c9f6bd) -,S(d8b01896,9328544a,a51f22fe,e605c693,7a014aac,37316f,ff6a760b,93aa8f9d,63f51e42,a2b879ad,36d60719,c1497b5d,dd412782,e4c620ac,989f7259,3a06edf3) -,S(b9475950,4a9b3052,94af6f2b,6f182e5e,83a30abb,47f0799a,21ee5446,d63d48d7,cbc74028,37a899bf,79b89676,9e358ad6,9680277c,34ae1018,4290689,c2fb876) -,S(14317c49,2972d5be,c5a01b5e,34842135,d521b467,1b262f0f,c3e6a271,ff8e0ef0,cc4d2235,d1cecfd2,2e6a476a,7db483d9,d318e79e,4c3486cf,c2090651,c2069381) -,S(8bbdb357,5b6867f4,4f062ab3,38928d52,78c4b873,4e95c5f8,fcddd4e4,9d44f8c6,d38d3387,32424054,c05a67e6,c7d00e62,1279eca2,ee1b59fa,90b97f33,5173a778) -,S(7775fef6,36ecbe78,9279786,b996c0d7,380b00f9,4ed31476,1ab0b190,f06aa685,53152a73,162dd659,dce57d7f,cb885c44,34243153,2b8318e1,2a996ebf,2f55407b) -,S(db5e4bd1,39ebe377,bca64950,29e72fb4,bc9b0ea5,5450e42b,a7491c0c,39693b48,a6468113,a5a796ad,a337ceb3,238827dc,416ca20e,bdbe4e62,14194e66,cc5a0abb) -,S(eab057b0,578c52e2,eac11be3,9f069cf1,6ebf0631,709560fc,2414ff11,f1c619eb,5422023f,cf69b8a8,458e5c6c,3c2de1e8,6fb041ce,180c5f75,cddb455,fd023f67) -,S(e955fcd3,c657d611,7e2d43cc,651333e,c231ba32,418e6fe6,d021183f,e7f5e44c,dd0eaa98,65212f27,2454953a,4c46c5da,973095fc,b2e36369,cfe228f4,828e6b57) -,S(5f5a3c57,58eafc30,c311f596,f1d6605f,ec0f5e73,eafb27a7,2a07f91b,42d8e49,3cde0b0,1d1fb2ea,9d85a04a,aa4536f5,c6d9f55e,84ca890c,cf23ef2a,5dcdf1a2) -,S(fb7a31e4,ff0ade1e,efffbd7a,e04af118,49c82cf2,6ad219c0,7572d924,8b99bab,ea87aa0c,431de57e,ee86bc4e,be463dd7,9e69102c,736345a,5502b07f,31df2a01) -,S(d57b1d6a,a3e87779,4b9f8dd9,683ee3a3,6ec18d3d,e6b22b44,e411778d,4bae1ffb,256ffed6,b85bd2f0,9dadb0e,43ccbaec,9fcb9e57,22d88ca,73f8d7ab,dc0f62ee) -,S(9326fc52,d3a24a38,ef0fc90e,183697b3,f726832,c70bcb5b,bd6ac548,cbb8f1a6,863bd0a0,cc0a2bea,d21176f5,c99fafa8,d7d766c2,54d57308,1a58a6f,12889a2b) -,S(58362cd5,abc9b5e6,57617e94,620ad087,d5d310d5,313ef6da,36079b4b,a93caff4,5f2a404,4e86bbd8,d73b673b,2e432233,d6923cf3,c262e1c0,3da48d42,f62fc52f) -,S(7dd488b9,cd06e68f,e01b3a9,6b318d61,b8c4cd69,7e9a3681,34fce81,841738ee,fd7aa5ed,130c897,cb770846,a3d292a0,d963ded0,5266010f,34a99ebe,99782cf) -,S(9bf78b02,524c1554,3330d7d5,a3b41705,1fa2a324,6ba8061d,f9550640,cfe798d,59f537d6,6d2e6801,d79d5a70,3b4219c8,c7d06385,76964f48,10427548,90cf5a83) -,S(4c816973,743ad5cb,18db4f87,9bbd6d1c,e71513b6,eeebfc39,3663dc36,eb3fc47,1a6dc6ac,37a49400,a933ef09,f00f9650,44c6f8eb,d516c254,ab142d89,d41105f) -,S(60636bc2,c7486343,59296408,40f3a26c,173f4e5a,7f0031a8,35c1c56f,b1051be8,71a78b7a,3aed2bc9,70a4190b,d1be56e,efc2e6b,7cf81b08,541dd8f5,dbe88e8b) -,S(a6e772de,c3e90a70,6c663fc9,4d5e6cd3,12211537,40ca4a2f,47a0f3,7f8d00a,25b8fe1f,5c727181,4a6175a8,10aa1eb8,f1090221,d78c32ca,76ba7c73,d0eed520) -,S(79c6653c,60307215,fabb4b2a,aa8bfbaf,1692f613,166326c9,19324e5,7cb89262,36d5ed12,b6b49496,e2b79da4,c0955cbf,c24eaa3c,204e28f8,db1e7ed2,d2197bcb) -,S(3f556b2e,4530fade,d4774af4,ce4454c3,4a2bdb4e,aabda42e,d4ba8546,d646cb15,bab1d321,1ce84331,3be8996b,f5c5c4e2,c9fd04d8,397cf9e0,58829389,ecfd25c3) -,S(eda59a23,8d21fe9f,5e11e0fb,cf731fe2,d645c52a,f3861dd9,3b7273b7,3fb3913a,22f22f01,4ba320b8,2cc29c06,d75b7eb7,d3cea857,40cb2562,4161b9a8,712bbfee) -,S(7a1ea77,323dfb4f,36958adf,71d4f03,3a2bea2b,a9f62cb0,c42a4279,7de68548,4866ce25,ee7a2b5d,a276f976,6261318c,6d2d7f51,f6f41940,f6cc3f20,264825a0) -,S(ad0fd3a,ad62d6d0,bae7c51d,590876e2,33d1028f,62d5c178,a0ecc3d9,a323de2a,88e024c5,9672469f,54f4a64e,b792d761,d163157d,ed982787,a6d40382,83b0601) -,S(1bf19432,f4044a69,56d6e9d6,7b84a5cb,ee743771,8d634dfd,20706cdc,602729d3,4114b200,afb6a1a0,75ef8e3e,16c37e9b,4f2acd9c,3fa4e922,63d1c430,7c516aa9) -,S(514616f2,bc2dafa,8be3b9d5,f00b694d,2fb1af5f,12d219af,c35204c2,e121d93b,3e5cee53,608a299c,f67f4e0a,65adbf2,57ba8eb7,450058a,74072ccf,922eaf9c) -,S(8e3fece8,5338ed31,93721d18,1cff34e4,fdc42330,6a8e1a1c,3b002da1,6921a661,b095734b,6736486b,676dfc24,9cac99ef,12894543,8b333b2e,77664f8,20f686d2) -,S(46c06820,df101ed2,92842186,7d8a20b9,6db1eb9a,ae63355,916d438c,a7ad4447,fcaa10f4,59bb73f,c48d1b60,1147b535,d7d43958,1bcfe26f,9acc7abc,ddf1afa9) -,S(56334df7,1f9b390a,b001e406,ab37af71,3fff8c69,1c2eedba,fec7dbf,cf722b31,22d04394,340dc156,a73c4b0b,f49a6c93,8a3724c4,4744690,4af420bc,726707dc) -,S(202e246d,89045f8c,9dbe3dc9,7ca52d23,b2fd55fa,1b5cbd37,cb882663,ca67c4f,f4e6cf89,9cbcf023,1c9f661e,c4588072,7a6241e3,513cb365,9a2e7b20,a17a62b1) -,S(c8054ee0,10211c2c,f5bc1ff9,43552eff,c56b635c,d65e409d,ece239e9,9b9bd4d5,f50515af,51601cbc,de6842b4,3b854b05,bf1ebd1,678c46b,46e22827,17f31057) -,S(9c29788c,235eb61a,d2940708,4b9701a1,ea3282ae,56f984f5,1c625538,14438383,32111eec,efdbef2e,236469db,4ad30e30,c116cc42,99dd286c,2ab70ec4,9759ead7) -,S(5854e8d0,b7b5c394,7068dc86,f94c3cd6,72999023,367509e7,4bc1745c,19a57ef8,7e7901c5,c06bebd,f50c4113,4e0d2d3c,edafec05,417d45f2,345b75cb,a63eb98d) -,S(8bb2fff0,f45be789,a0446e1b,3547a44d,1104a5dd,9c8e50b7,4d0fa891,f73fef34,c332e365,a5343ea6,6c571e2b,c383f767,efb979df,72223a79,35da9173,73b182c1) -,S(ea88e65,6ee43387,86165faa,cb643cda,992f5656,dc7333c4,5ad8b561,8ccd209e,c38c40d6,4a7a343d,8ab357ab,845725c6,af9f4f4a,843986f1,fd0a83a2,5df0f909) -,S(c0c1d4df,857c7ea6,13322c2e,e0d4ba2a,a3b18ab8,cc8d9ff6,6981d6a9,4446295a,247115d1,e8eef7d,ce6ae1db,ec9be46a,9a284648,ebb7a918,7292fe05,9d72b981) -,S(91e6a4f9,407d3600,2a808d8d,db723ebe,67b8e212,792ba65d,b74e028c,ec7fc72a,ef6ae560,35f58be8,5cce98f7,b2106e0a,12e57dbb,47a4a995,47ee5041,3c5721ba) -,S(cd749618,9a8c1d36,2995cf61,380d0366,24a7a402,e21cf078,18794e08,fb208454,f3dc92be,15d1f912,a03debcf,88afcaba,2dd6ba2f,1d23a4f6,ba02c5ed,cbaf0bd9) -,S(99f5d12d,2e68e70,c304f3fa,44eb24a6,85f63065,af0a15e9,f71752ff,82943018,59f1921a,d97ebf33,68f962c9,c0a297b1,dff9f980,246d5dfb,61168dc1,da0b8a9e) -,S(63c6cd30,f9c07096,11656b1e,75d17191,a6ac02db,9debadff,7b3d602b,b9f7608f,2e439373,70a41b8f,e0e5f0a1,3ab75be4,6d8b1ef4,ee71723,4b73ffef,461083f0) -,S(b7407f26,90a5ea11,d9b7fc55,17e6c1b1,9e04fe47,180b1e93,94cd5e97,5d184d92,1b953929,47dd4984,7420f727,7a6796e7,828ee880,3e0d701a,aed8cf7d,513de6d2) -,S(24979116,161c8840,dd521e96,27a50056,c29ce48d,d86b6297,150f9a6d,e383fd40,13dd71ab,3dd69cf7,384d3e32,5fb16648,76f99943,f7ba3649,143e09b0,28b9a70b) -,S(f109b6c3,6122b278,8656c80d,4c84150b,b419919,4650d96b,6f2de8f7,f9d73b7d,a7457369,bef8d54d,c0a91d4a,39496f85,bd971f6b,4a13dc77,142ead5d,791c96ac) -,S(59b303f8,2031c370,4f17c929,7fbd0ac1,36be9900,a26b5516,9f0e3b6d,69118df9,30c7c4dd,1666271a,5ac8c936,b35068c1,9830306d,c695e02,d6c65ebd,2fd678c3) -,S(6627359a,eb3910db,4ba54cd6,c7b884c9,a678621a,d2bf6cd6,6023974e,d462fc52,bcbcf9ba,d2de78a7,fc486734,79379778,feab83dd,ea4f50b2,555c457d,a910d487) -,S(76fdad80,c4fb507d,9c9d2305,90e818ac,ec7efc04,1184281e,9212785a,dd51f1d9,cc8cc7cc,349cf307,f34adf7e,f559855b,9b88b70d,7fc9d19a,18cecddb,e3a8c346) -,S(7893406,e99cf08a,52fed9cc,4a9bafdb,7f2380cb,4c288700,b983b791,e1313330,ec15e1af,39eafe5a,d081acd3,fbd5b8ec,d0c2e83b,7a5b8074,50ef80af,2511d149) -,S(c454aa4,e8d02133,ed93c229,d0e834f5,18f16cd,d83a39ff,3bbb1ba0,838c81d5,a98e61cf,89c43808,f4895924,529a6e59,8af57be6,debf5f5c,67e3b3a8,73ac51f0) -,S(ff0bc21c,cbe5c122,dd2ba8f9,64239010,97dac1ee,3957b27b,f990b611,72402880,c34089c,1f7b2181,8d4cd5f8,9e445ec1,ecd634f7,52960da,467cd396,77bca50a) -,S(8e4486e3,49a0423b,d8132e39,812b78f0,3a0e61e9,d3eb7735,86f1e279,3731c301,897b24d4,37cc260d,52e1866f,4dc222ed,16bbf084,c108883c,a8a7b9b2,9a2053a1) -,S(4f4ca57f,84f5c4e9,6aca30d2,351089d,bf7fb6c,13847584,590fa5b4,4dc579e7,d53db7dc,1691556c,36f1cb1f,8a1b91a9,33634975,8f28d0b7,17d250e5,ade63a9e) -,S(fe8924b2,d7a24fa9,5c61830,aed8fba,79b3a96f,388b6423,c760aad8,cfc203bb,bd303e29,c6be0e2b,f4e79df9,cb17e0ac,e92c3784,fa8c26a,7e3cea32,d0b056be) -,S(3099f75c,f6a8c72f,8685895d,152f99b3,8ed9a3,320f3fc5,dcdcd14d,c46abb5d,fbb5bc2a,ec76529c,a278a32c,2a95c2a7,4a939c4,c0e2c0bc,6fc20b2e,a6fc9f1c) -,S(3b939f83,f84126f3,b6632de0,12405c9f,43244322,2ac384b9,7415c2dc,9c72f4eb,843b7353,ec454380,e9d4cc20,23a138b5,c1e602c7,f48be55f,1d3c24ca,f05607fb) -,S(dc7506a0,4a50e345,dca3cbc0,6384a938,b032f197,d6d30932,7b0c646d,95c732d8,fe942311,f6d49d62,99f9559a,3d16f43d,c6a39d4e,b623f9ea,e8dde39d,9bd5772a) -,S(f5a4c596,c6996a35,172fb61a,2721d75c,3dde68fb,4abc9433,f84d20ea,83b30dea,175e0d3e,77d2f63b,bb2ef922,d30b962,fd783b30,ef7dd8e3,5ae680bb,9df26572) -,S(7e9038e2,c499049f,e5d222ae,2f79f4b1,373c2f69,262f133,cb9be1f9,aea4029e,3592e66a,343335bc,e016276,6550a363,1d7dc64b,2223bdfe,7146f32b,8025c737) -,S(80f22f73,d16bfc6f,d6c28e92,1f990eb6,e2cb803a,d920850f,af489ff,f62b1f41,8714a5d3,c5ee74bc,73e11fd,24cf4d80,370e6711,c726ed68,2a1bd77e,7b503b28) -,S(498a2ae9,e86e53f8,43470a58,ab96fe0b,7c3107,d9d23535,fc887bfa,fe0c897d,47aa9eb3,73e841e1,4260f651,6ab3081f,7ec3809d,53b8609e,c3cced3a,6401bb53) -,S(601af64c,d14ce184,ca52c542,7a78c746,8e9c069a,80277b6d,960ddf30,3b3a010e,2900a63f,ca1576d0,11b46c27,32c87ef5,56dd579b,3bcd59,9161cd20,ceb7fa18) -,S(8fb2e0f0,7b2fcbc4,ad58b06a,822aa683,957f2bf1,5dd5984,9a1341ff,2d74a25b,7cd82350,8d797cea,b1b386f7,5d5f82af,6137dc9,9f6d6e6,b7c68cb4,75070aa4) -,S(336d780f,e9d14e8,b55a1498,72c63bc,83468eaf,aef3282c,9bde58af,6a69e6d9,92d1004,be45bee6,b8eeba68,2fd0187a,ac3e6679,f4fe0fb0,b723214,a63d2261) -,S(507ac721,f4d58704,4f8d2cbd,fb03aaea,b0634303,cce3e1a5,e4e47efa,90d5872d,b89a398d,e7db05d7,a1055093,97b83d60,9ba53c95,39caaf0e,917d22c8,307174d9) -,S(c42dcec1,3bb7fb96,29171026,f66c012c,992c604c,bea189a0,46e688a9,473ba343,8aa37731,a53223cb,a021bfe7,c413929d,8fe010ec,353464b,e3c1ce02,e54f7bb5) -,S(b02ea2c3,cd6093a2,d5e6b5c4,5c510848,857eedb6,50038417,d9f41947,2a866a2c,ebb45c50,cea190c6,1bb7c505,8cfce93b,ed1d8ee8,c75a5bf8,6ac9c127,2fa5527c) -,S(f4d193d2,9f20ed2e,273dc2c9,aeab43b5,85626d41,59b7edb1,51e17c45,ef70d84b,bda19a3f,19b834a2,c493f8cf,14cda579,1f84b6c,611ea7e7,280e5196,1add0974) -,S(8740dceb,19eac62b,75859b9e,4d0302d3,cc84f6bb,1ff6e857,eef7fb64,fe5f1bb0,a729eb0,4783205a,2e1d5b6e,7eb5221c,f2f151de,1489d1b,1d98fb68,e7c6ca49) -,S(79ec464a,85a29f08,d910bc94,449ce88,50aec626,3693bf6c,92a5ea23,84fcc9cb,77d170f5,b52ed0b2,9aad476d,85abae3,a1d7c544,c625ba2c,d44e68ea,ef53b39) -,S(4f1018d5,dd54bb71,cbc0e29b,255eafd4,6fb3aac0,45889238,847efcce,3207fceb,c32819e5,d23cc2e7,73a9b2a0,271fbe3b,a64531d9,2d416222,24a2f64e,3be7dd8c) -,S(dfbf1936,2094e85f,ddb25de6,8ca85cd4,e53768ab,81780eb0,33a0607b,fbe969a1,25ea0b59,33ba21c3,2ac5f1e4,932debcc,a2ca3aba,e0b7c671,93d97e1d,af80e563) -,S(184c66c0,2c36883,2c1805f1,8612449,940a371,54174f9,b67bb41a,85226649,cf63fe44,f1cfc791,4fb4a24c,1e0530e4,736f815b,a910b487,ec4fec7d,f8662eaf) -,S(daab3606,d386e04e,e39a8a51,a8242e43,ede9de09,f50322e0,a0f410f5,f043686,c0ba1c4,ebe7d10,6fd0d0ac,4e8f6e8c,fbb2b682,3a9d55e5,dbb7718e,d411718a) -,S(a887f4a,5311f252,ba0219d1,f848d334,26b0e216,69020dfa,89dcc339,7e04530f,5a7c04bd,8c37cac7,f429bff3,eda01dce,a5b4fa44,eecd3195,2878f79f,9dedeace) -,S(1b315664,409feb98,4d5dbfd5,a85afbce,4784a907,b284958d,28123f61,7c2d207a,2972cc7c,ba348e5a,5841d463,4597fd57,84eea5ba,a99bdc37,3119c568,aba205bb) -,S(154adfd4,27c30d56,d5f5de1e,d7e8465,6727e69f,82ec8d1f,19dfa16,b1fe4984,5ba86e8a,324b279e,449f61ba,a7fa52df,882477c4,921f2079,98199775,3e0372b5) -,S(debd69f9,fe55c15f,b28df417,cb1af3c2,585fe89f,b44c2f94,94fec0d5,88480994,98d8cc21,55c16d24,e8b1b831,4fcf616b,2564ff,9345fc9e,f8de3cd7,57f9708d) -,S(9fcd3490,2a7c54f9,a2855fc0,9558c465,e0316c3d,fb72c66b,71d4492a,efbaf9e2,a7ac4160,c2b5a416,89e9e49c,8d5aba67,143e1de8,26498be5,1cfa691f,f7f5d14c) -,S(59cacdf6,fe4bae99,598fb1d2,df3de7e0,586fd792,eee0d9bb,fdabfa73,8943a727,7c730d34,7b3ead16,c74d349e,191c484f,624599c4,d379acf,ed8d2341,160df035) -,S(5ce1abd1,fb291d97,db3a4c9e,c4ace635,34e6b373,407a8821,67722fec,7fb226c,abc24634,b4070973,d8a11025,5ff7a81b,a39de6f,5275d3f,7630de8f,23b7526) -,S(f783628e,bd0a0b4f,6ee68001,5b3014f5,e70897d0,ce159baf,3afb1aa3,207d73c,d06438fd,5b96b88c,94a68b6b,1f5fbf32,6c7a6efb,83b2f1df,2849f809,cc39af61) -,S(7830fabc,cc7229ee,35c7130d,b441d2ea,9a988d47,72ebe00c,6c159658,537ba0b3,49e8b58e,6aead178,3d5c901f,a803a33f,78acc889,27f2d57e,835aaadd,1b38fa7f) -,S(c930390e,a8901286,21a4399e,ef9a4a90,6416d549,c28f7482,6252fab,5fcba9e1,fa0e87da,3d0618a2,f54e8fd,d14b4bca,3bab137c,daab0197,4d110ef,b161cfce) -,S(2a0da867,20571917,6f949876,e5f00ec3,ba0924b0,a5e758b5,2d0c23dc,da9cd28a,96cd04fc,69350959,595b4870,f6df11cf,90c1fa1e,cd04ddd1,975d0bf0,fc907647) -,S(f64881e2,60da581a,f576e92e,3968e24,f2bef6ce,dc1c9c53,256374b3,1446fc83,808a945b,660b67f4,43ef833d,b491fa56,2aacec09,f8a2dac3,863b72f5,e7c8b94) -,S(970bd933,5ec5f0d,3a3cea17,5090f1e0,c181e488,1565c341,33017f99,ab81f052,4d1d270f,e284774a,fcbb6658,d5cc019b,8eb30bdb,39464a79,6ca1431f,1ae9fc48) -,S(dfe94b31,24c4541f,4723ecfd,f5cad197,2c058886,9283073,35415bce,e4c4779a,cc283e53,d547606a,a0fafe8c,5d3403c5,d047aff6,8b194b1c,1855a7ab,9540e23b) -,S(f1813379,673ae594,8fa30bba,d8737d0e,16c8bdd1,8f7047e3,bf33a39e,858df800,acd2c1a6,139a2dbf,9b008d50,d0b4d1f2,20bfb9d8,c24855d2,ed54440b,a87d294a) -,S(f4fbc156,fb631bdf,51192bd0,1c0db0c8,8890ec97,9c368f3e,c2106043,6d423740,3cb08cf0,5b07deff,431faf91,e1874baf,9cfccd3a,df487f4b,4f69026c,1fb7149f) -,S(124da4e8,3b079d72,4a7a9a72,5cc45a80,cb92675e,74541bbe,d36224e2,793de6d,3e700066,f12e0cba,4d6200fb,2a759554,1cd15531,ea065e6a,c6fb4986,548d00e7) -,S(749721c4,455e7826,1de045bb,266b97d0,6c2b112d,2ac8c16,428ce961,b78d1138,27556aed,a3f331c2,fe95b237,d3326c7d,25bc594,39f07b87,86559fc,55a3032) -,S(62cdca49,aa58f55,21c60dfe,d50fbf58,257676bb,fd4c4e97,9ff9a91b,7627a028,8bd49b9a,e16d10ea,7ee1528b,4f433e8f,17c4a688,a7148fbb,d10ed605,595c37b5) -,S(64d650f1,39b13aa6,16d3b227,5ed164b1,1cd3a1e8,81759344,7895a4b1,686478c6,deeee52a,f7572d87,f339595b,79643402,f9e2a065,7b95ba42,6b83d87f,3dfa5c2f) -,S(d08a3e55,66c636ef,3417c17c,d8526df6,37cb935e,db00365a,1ecc9f4a,9ab59d,2db049c7,5eec5176,3fcd3502,33856da4,e9ed32fd,24242a54,9c9ae462,240dc103) -,S(8761705a,35bcc509,afa20d62,61859afe,97154782,49ba47c6,f4b8df0e,30f20d89,b34c25ee,bb029622,4929c3db,78046a09,fd43b9e,be2dbf64,436f0df8,adb726ae) -,S(e3453933,4ce22643,146cc317,54e7ce7e,e35f6f4,e37b307,c4e9e11a,3c6f5f85,73ee178a,941e81be,ff22a0ca,f2bb4513,1afdde7b,336a3bf7,ad05c1,d465d97d) -,S(8389192f,6609a7e7,ac8e6f11,fdbfce8e,246b36bf,95e0de27,fac36082,34ca917b,957073a5,50448ec2,9d67b681,ccfb1aa2,67c88976,e53c99be,c68c378c,f2b636f) -,S(8bfd70c0,67bbe25f,e2e78029,a97fd863,bbf287fb,7a24eb8d,e5a61af4,c3c5d387,e2e6c66b,ee7265cd,5a1b1d64,4f24fcec,8b59001a,6edbb1fd,5d894740,f3f952fb) -,S(a5d0999a,a05f0bb1,59a1582d,980520b,eaf82015,68875269,fdb593e0,e6ff257d,e34d9720,5ef05766,676b62b3,62ce4b34,fe6d27d1,a644050b,f9c65c34,c423635a) -,S(44e479a7,b949c88b,507942e3,89ffd9d,17645185,92d4e544,2827baaa,5d5043ce,7b86ec29,8c12c463,b0a71416,24a570a9,e2b10d77,ae12ee23,2504edde,213a7087) -,S(60dec943,d9797811,706e0251,e0abd0ca,3f37bb8d,559213c4,3176ce3d,352aa558,2dc689f4,a31c59f6,c5181448,d6985335,16b0764f,8cc6fd50,8bc109d6,69fcaab8) -,S(5ca58d38,5b5449e6,f93c5c5,35941b98,d4ab829f,e641bb24,af7e7ab3,1f7709b,82afbae9,80eb6f48,110ce090,7f39ddc0,945d9d84,d5d3feb7,4d96581e,c17cd575) -,S(b775967e,a1b1d60c,9b09cf3d,26bf86c3,b9a23ea3,cd329138,10099048,d18b031c,d2b7169b,ecfa1055,70d885c4,adcfadcf,66f12d8c,846f70b7,12004097,840fef1) -,S(73d8d4f6,7d602f61,3c3595f,b9aa05d7,a23bc4c1,1fa3844e,92e6b79a,40220f96,bf722a2c,ffc9fee5,bea18530,9ecd14ec,bb17fb3d,568fe85d,331575ab,2400ce3d) -,S(e8104df9,f49f7822,152bcce,79c6df0c,8b1e9745,448c24d6,1e7b1180,99182b75,dc2fd539,ec8f2beb,1bfb0da0,f95ffbb,e14fc682,1c5d5023,96b1253f,82137361) -,S(ecd72ef6,fb6c432c,8e1449b6,d16180e5,777e5524,4900f209,e89e995c,546113e6,1671715d,358fba99,e509f518,e1458600,4252913e,268129e0,e00d64eb,7a26e135) -,S(e3b5ccf,be829bd1,6f1fc6b5,fa6d7c35,464bfe10,7e9d6455,a9907050,a4fc36cc,ce7abb9b,5471c1a6,de17a2c9,b5b671fa,296cb5f0,10b5ffa3,31e7a87d,a28044f5) -,S(f3591a02,ffab91d4,eb7e75f7,f4ebd22c,41c1ce4f,25f89c5e,d7ca1ab9,27107734,345a2e11,f2bab926,487c7d53,5314bb6b,cf04746b,be2edc10,18a57c2b,94fa4b3d) -,S(ca4b045d,ae54ad95,37d184f9,ffc5a950,c61349d3,227ae1a6,5501ad97,cb45c635,e30f817e,255ebeca,352f3c24,b441d1e9,4660f456,ce9cd72,eaf4c4b4,d7c1d806) -,S(f7cc5740,54a9ea61,fb8ebdb7,b76a95f6,30094720,675aaa72,dfd29bb6,6f41ea38,9d463d8c,fc5424d9,18275aeb,5e046be3,b3dd7fbf,f52d4990,f52c81e,b2556eac) -,S(f75b5f79,fba3e3f8,ee64bbef,7d34e8a9,b4fd9bfb,27b6a9f8,76b1f70d,ed6ab6c2,220b40bc,5c3fb77b,72c48e36,2745677f,7e0e8266,f85a14f9,d4030ec0,90a43faa) -,S(2aa367a2,5060236a,627d89b6,ad0a398d,89d86a64,735a4fde,e88fa4c,d9cd450,2bfedc25,2491b1a,764a802b,c4d77d86,1e70ecff,e9aef8f6,e829448c,d841fc32) -,S(ff7f49c1,11783cf6,e7da1e22,15827b07,a1078ce7,b1eb3257,65a37c38,a141620f,69550c9e,2e48058e,8bca8b54,21251dfb,a488c585,df644bea,d519acf6,54702733) -,S(31d05358,1164f4ec,a45f7338,fd3ebb90,76d017b4,5e679601,6fd02a0b,5c3aa39f,f124319b,72177ff1,462fa90,2e1f8d23,d4d3ea0e,d1bfd1fe,6bccd92a,9963f575) -,S(6eaf0edd,fd1203ec,a2cbf2f3,8da9ad7,c8a02d3,ab5f06ea,bb88fb5f,7e6a3bd0,d9336d01,2d8e9474,49c521a0,10a3b83a,815a0c74,a31596d4,125909c6,73e05f08) -,S(b95a519,77991ab7,fc3943ac,ff5fa88d,68e759c8,11cb91b9,e9a1ba97,7eda1347,8cf2cb5f,446d448a,5a98fbfe,75a2ffa6,9758bd15,36eea87f,533822bf,6de5ef23) -,S(4e5301d4,8ce5edba,f3b1dc21,2e804e7e,1fd386f5,6b90eeea,da6c1c58,211427e8,f503ec3d,e169fdb2,e1d2f684,cbd9d684,dcabaad9,376d96b7,6fb0a5d8,1b9f0d9) -,S(4fd1a9e5,9031b43,715f92cd,c49c2d0a,fc7c2b54,ad61d7a3,9142033c,3cf49cd2,73ecc11c,ab0165bc,3ab4b43b,ecef694a,2d99c9be,8b877160,2c885a6c,8e4adcb1) -,S(67406865,b32543fa,5ebb7fa4,a8d8fae0,384070fa,2e8a4b86,74510099,20257c84,3fdd9ad5,93a4e0b9,4f4451f5,e3227df7,e829a45c,ef3d271f,3fd85896,bbc62008) -,S(14b955ae,d6ee5be6,ef3dcfa0,edac40a0,de7e8dad,19c8dcb4,e4992a65,a46569e4,d4b920b6,21823f81,8481eff6,761353dd,7d9f31c2,5ea9d1eb,ed60a5d5,fa2daf70) -,S(14f283bc,5608d5fa,dfaa0b3f,fe42fd20,4003e434,c6368fb7,22ca5f22,3339ae42,b2415e3d,c3aefd3f,c644d4bf,b0a87fdb,bf0ba630,2baec8c3,7c1577cf,9edb7397) -,S(3fde0c67,7d3ce20a,6e6275be,7f80cba8,5416a55c,58dfd09,8e733a32,1fbd1c1f,9b8ef7dc,610f192c,949782f9,bea1f08,9a018b25,8926389a,1155d033,1adaaac6) -,S(9c55e669,df5f3d05,f15c74dd,48290540,b993bf4c,41dd9247,df5332a2,ed17267,23db0ce9,30c97665,175abd78,33757fc1,8c6b3c32,2d260810,981b4e0a,6e4979f6) -,S(bde84df,ae141a0d,6e8da60b,30f41746,506d2dc3,4b3faee7,d8568a92,82968d16,45a33214,ff1361df,e724697b,99a6c686,900374f3,6c298dcb,468f38c4,4ab3ab04) -,S(1940294a,b8f3c2ca,45f68f45,4c60c5a1,e5d97085,946b30c0,54939daf,c99546a3,563f9f99,3816c62a,1e60ea76,77c61bb0,848bc926,e76e386a,bfd96bb4,ece3b81e) -,S(dd6ea1e0,d0d13e64,7d0df92e,ad22d838,757a34d6,373ccad6,6829fcce,b32ccb0e,c018e9e3,6bf4e8b2,853ad27f,a49e5ff8,384b557c,aa00c3fd,d8e008f0,ee33c313) -,S(657847e8,c7844562,e26656bf,bbc27b84,dc104737,42c4dffe,c0669616,5b7fbf19,dd90dfb6,58b6ada4,901beda9,a4a9a8a,42c6a4b4,e79a4172,5b5f6ab6,95f2df5) -,S(fb7024b1,40be9d6e,906d26c2,edb781cb,49b8e71f,396b8d3e,352506b3,fe3dea6b,de408ff4,e50b2328,b6ad961e,9dd1ac46,fea36005,1407061c,5a0fca32,eb08efdf) -,S(2d29c008,65a7b279,d3a80179,cd3e8944,b3f2be0c,49a398df,a3113350,d1d8e8e0,caaf127a,ee704a4a,65802748,59649e45,25c55005,f2667ee9,92e9d923,daefcf8f) -,S(db690474,79b7209f,4de8d42b,a3c1be3a,39268589,a7c33632,6d87c1cc,53d5662d,90de8be9,5c3587aa,9913ce32,c83e24e9,c58c1fbf,2922c63c,b777770,fbaa4e00) -,S(9806506f,922e4f0a,afd54ada,258d6fc1,723c7087,ccf13f0a,df247356,c941697b,c07e2018,a8cab841,37698eef,3d31cad1,b97fef49,77b277c9,25245a12,f16bc237) -,S(ab868d3f,e6da25ac,5b11c112,28f14621,661e0ad1,e33d25ea,ae1ae7af,60e40187,ee24b698,334a9850,1a1195ce,d57a7fd9,4b12c488,bbd301d4,d47d5f13,3cbf54ad) -,S(e7561fd1,9d2a8ee6,12056be1,74257e28,3122f366,abf66f49,31fd89ee,fd8dcda2,2052e74b,e3656d8c,5c766ea7,3227b75b,85bcb190,8a07918d,5a8a8001,3e166d5a) -,S(5f19523d,84bbe307,be08f2e0,fa844cb5,7b562f01,39950820,83c2df9b,e8f21e6c,3a96fe16,28ee1dde,2ae9ad2d,5724eb88,33377542,6e91acb9,d9be7c41,7265d7fa) -,S(c9fa4668,3c949b11,2422ec1d,c5501efe,2fdcad17,255c7545,69837d28,d9c10cc1,1aaae75d,18f691ac,cf1dcd8d,9e8e0348,b5b6e734,76d47ffa,b5e23ede,c7fd1dba) -,S(1da90e2a,1e911879,ccfa084c,393b8205,1799b2d4,15a42401,b1ab793b,beb8d8c,3d3f7c69,11ea4d38,46cbae1,53b3fc32,74994ee5,1f4fd332,2da4d28e,c89c0b63) -,S(c6fcf10f,3851e432,6bd504ac,b7847f7,707e4098,d8f66915,3e6f89ad,f31b3186,d0ac89f4,a16a63d8,6e36ea10,8f8ee5c8,4e2705af,a9c98bff,3ea5253,93a50ced) -,S(15057a2e,eb56c67c,cb6b7d4e,f1257ae0,3cf236b,1f9b6588,fefd7f46,16378233,4dbab530,ccc0a7a8,c49543ef,5e3d0a87,6f205a62,2f9a90cf,5054bb0f,dc4930c2) -,S(37eeaee0,72d5ac0e,6ea7337d,d07ddebd,45bf1cb7,8c02dea3,6d1e419f,308b20f,b0c64496,5d9daa14,19c77249,a32a3a3d,a5761adb,bf5a394a,ebb91630,f361d506) -,S(5a207bf8,3a8bd0e3,3c71cd96,d928bdc5,f1d6ce8b,7ad9bebe,61a27362,2557745c,3accb757,fadc9b6a,2a5494ac,15744113,ee878901,323c6138,19ec7666,60f54dad) -,S(fe08dd6a,1a0fe325,5a391271,e81befb6,f6b2ee08,907046d1,642d39bb,fbabd139,42c342d1,3535822e,e4ef1b43,69f204c3,665d2326,1379b0d6,c520c64e,181ef40) -,S(b7d262c9,8dfdbba,6483edcf,38044cad,d6d859e0,3d1ddac,a39cb999,78706111,96086350,b308b397,6a007c8f,5181b5ba,30bb4c11,653d689,ee97fe47,28d798e8) -,S(4b12ab2e,23b33775,3ae97d7c,1badf5a,7d354b57,dcc78407,6836f802,34130c86,419d4e0d,9f708bf4,2e11e73,a1fe5815,2bc9649e,49ae45c0,f52fb8f0,f23c450e) -,S(fc6d2682,a96eccda,4b49570c,8bcc47c4,8f362bab,7750b4f7,4f30cc49,d8e88dac,1af56527,30264580,d1f22612,e90597f8,694aff0,96001848,8a243ac,f4beedbb) -,S(c7b9c3a9,a189eba0,54742c40,c4afdb9e,5e07e6c0,e442cf06,32e9b655,1e607e8b,5bb68277,2f2274db,62084cd1,9c1a545e,ef6b38b8,d4dc3e30,fc58042f,f01822ab) -,S(eba4d342,30dea72f,29a339ba,3ed4306a,46c761c2,bb6f9627,3406fa7,50dfd956,fce17a0f,23d278b2,e3da1747,706840cd,d31b01a5,8793506d,2155cbf5,dd237cee) -,S(a4d36dc0,2177d471,35b4358c,6adec285,3595dcf4,6cd9acc8,944a569f,82c04155,85a29779,63b21be0,e378fd0f,b5a60fdf,65f3e45d,c2fafad1,13377f4,81f00281) -,S(4916d063,ae8bfae1,e3f5bf56,fde73abe,eb165aa,4e6d4a16,9060ac95,76109ba2,a7916703,4a0b40d5,f967a08c,a536b7c8,3b2b0b4f,67638656,4ae9b4d4,4c3f22ee) -,S(761cdb10,b2966030,85f8f1a4,404ab49c,9de01979,85817f97,ecbae412,eedd046,1d115720,763b545d,72f8f50a,b881e7fb,9789f0ea,8dda90cf,2ee2f3a2,2e193db7) -,S(d7a2570,4d718e92,df85541b,490bc13e,860ff014,e8ddd9d2,e05fca2b,8dc64ea3,5e454b9d,21346767,71c0e035,fbc6dec6,6102db85,aa3acace,c158f43e,534cb90c) -,S(2af6004f,7962c52b,b0ebcb06,32975bbe,a6b9a99,4dc5a5df,eb20a43f,3d4d3bbe,6988a9e2,26f8cc15,3108e3e,b68c6596,be1deb1b,53239933,d91e095d,d81a14f3) -,S(a92740e5,3bab0860,1127571e,5d33184f,ca805d18,75ba4959,74108f5c,a9504255,5df2851e,2eb76b71,66dfd3d,3aa84e0,96d49c85,10daa44e,68d75eb6,c6d2379f) -,S(90d0961a,510d8a6b,60a87c44,93a0c8ea,76856770,d076057,bcc7ed98,70014939,74d4753c,1c913088,66b6f7a8,a2386ad3,7c13dc2f,85b4b4d3,f8d7603a,ccaa545d) -,S(ce52bea,f2e3a604,f62bfa27,92e2e083,8dd5c6a6,ca338ded,249be611,4ecd12b,a869de73,738a0a2b,7c824444,925f3d9b,dd08670a,8f8ff1a1,a4988008,2d5c009e) -,S(99ca8dc2,10e3fcd2,ffd39a47,1c06ac49,12215441,6cf16be7,cc3e350f,f3cd05c4,78087a80,131adc2c,6bf26309,ef0720be,4550fbe8,912142,c6ce496a,dfbc4982) -,S(be442cc2,9f5a7bc5,d07ff1f4,322deb90,cbfcc6a1,7d8e611a,b51ec610,a202d1c6,6250f2c4,680ed934,8028f2c0,1acf5bb2,fb3d1f25,e324b734,11156128,77c084a2) -,S(53f5f5f4,37fb010,2130346b,51b9b14f,e75d95f9,b8f80e65,67770bb0,e4ec8e54,8da52b53,c6e733f5,aa0dd2ef,23e2e1c2,24c0d571,328520f9,cb1cc5dd,28c62f93) -,S(206ce565,e90ebff,7d799e3a,134a56f6,a897ab19,186ed554,11de6daa,5c8c4d6c,c2ff5d22,bd2d6dca,7dfec5c2,e79d5320,aaa5d53c,38ae0675,4dca9a96,a6a75804) -,S(d1dcbfbb,87ee2fab,811f2a72,726d2b54,2176a20,cc23f744,faadf2ac,7073f443,106c63b,41800bb7,bcafc27e,3f8337d8,f71da693,e1f4350c,1870f968,edd17db9) -,S(d21aa173,c54376ba,1eb9d432,26ffc9aa,a516fd0,ef17c2f6,db117392,db749328,37cf5df4,e01480d6,604f79de,63a754b0,2326f9a4,ed74cb24,7724c682,6074e424) -,S(5234b024,a22c69a7,569acfbe,2cbb7ce6,15e56383,f8e1e031,78dd54eb,7d1fa3d2,2beae442,651db52d,62bc3b04,2a5b343a,b4103895,a74aeddf,d9189630,8bc000cb) -,S(9e6e9875,9f3e21ab,a709dbd4,f598894d,f5048dcf,5ee6cb6a,50941c13,35412f64,2b670199,e38f2e5a,424dd169,e047189,43111033,a7e4f4a9,2dc26906,31757ea8) -,S(8416e295,9a718e77,10df8a92,72de9bb2,89232c73,832597fc,d28f2928,8743ae45,6ef49202,801b408e,d81b7904,4cd1f002,20732a74,764c44db,4c77121f,1133d139) -,S(852a4fa7,48a3b2f,326405eb,e52ba2dc,27462f72,9ea3429b,b108e27a,d53561a5,3e06c046,ee0d9c23,6b0e441c,2cbeb672,770b99f7,8d062ac6,a81ccaf3,a562e520) -,S(2880dda0,2dbe56be,b93b876d,3c083ced,fa6097a1,cb234c5d,3282942e,3677c1bd,dfb0ea10,92d46bb4,fe95366c,5370dfa2,3d371f78,40e919d3,bf966441,f1bb43a) -,S(cb6fbc02,9e828d7f,c03dbf86,99a676a0,37b53555,275c86f0,7709ff89,f1819c65,fc4e2d9a,36577399,15cd50c2,1cb76cb8,ce9161fb,e05babda,ce516277,86062266) -,S(8087bb5b,ff1c3438,21b24106,606d0ec3,abc76a5,8a872161,5f6305ef,f81afebe,578b287a,a602c02b,8f5c5030,ae9a4632,23a4437e,944f4353,d9bc17de,824ce72) -,S(369f54bc,30f2c90c,7af0def2,2517ce58,f8ae829d,124ed482,653a28fb,42d3a33a,b8f2eaf,35af7e32,c63c97ae,f5962143,61f466bd,c4cc1b40,b4526157,b9b59d16) -,S(87be4c4c,1b2f871,53bb2448,ffdb6ac7,df294628,6be49eb6,edd3d533,1fed8f7d,7ef474bc,6386c0a1,5771ec54,21cd51d0,71fdc8a8,66938a2a,dfe6f4eb,ca0effb1) -,S(7b6678f0,18f75bea,8c310eeb,239edbe2,80393f1b,5eed1cfb,c013fa29,1e14715e,78e8b8e2,666ee69a,7388275d,2aa1bbf3,d985707d,3dd52890,c181a8b1,f38b1fd7) -,S(89ec641,96729e02,2a9608f5,8fba388b,77d2826d,6b37caed,90d27394,b160f135,5def3142,108d7387,19ee5a7,41deb18b,5e3030b0,d919a1f8,ac94157,a4786cff) -,S(2cbec739,3769090b,3aa2acba,b78c3fac,8b83749d,641f9311,99e6d1a6,36177f8e,3140e7e7,57ad2d5a,cb34a007,f4f26aeb,67fea7cc,8902fbad,2ca92083,f3de8886) -,S(678cefcd,a2d6a58b,53e7b116,d03020ae,29d57618,4663fcf0,2ebcf0ee,bd946908,f45be9e0,13298eef,37cd56ee,932b2a41,18834fc4,331c1713,314bd028,e6a3491) -,S(8ddbd278,adcc4ece,4692305a,94cdf011,5073b073,c88c1524,b43f1822,c73ec0df,90510edd,3c52c6c8,caa9ea1a,e28c7784,5d2d675b,a33b1022,68b93b17,80fc5b0c) -,S(972bf082,b162ff5f,22b149c3,d238260c,607d7878,aaf70739,3041d0c0,d7e36626,4685b3ba,f61cbca4,d99b64f4,3e90a442,6eca9f24,d0235324,797505be,4c4087dc) -,S(42af0d52,66604ab9,7de801c5,4514d23d,d8c1f760,bc86280f,540cc57c,bbc97230,5649b89,8c9029ed,4357160b,d97b74d5,cced0668,98de3b89,77192bec,1699ce38) -,S(5366770,87296d1d,8e6138bc,a9a1a0c6,1748ee21,4c0410a9,fa5623f3,d7bb30ac,e0683a60,786ba0d3,52619c2f,672d90ba,7c297b2e,59591f31,fd8b8fd8,ed5cac1d) -,S(a03b6284,e85bb18f,f04308d6,bce40e91,7d5d0ab4,ad920255,9de55c11,fc39fc24,2739ee82,c22cc348,23fe7235,a939db8a,c073005b,e014b564,4cad5a8f,e8785493) -,S(2f394ed7,268a53a6,bd998055,a24f7dd,f5801dc9,99233a63,7332e24f,26b66e97,b52b4f3e,e934ba86,d1bd3714,a26bc4c0,e49d09f,5d055413,8d3f4cdd,73918d88) -,S(91773010,527e537e,3aa0c19a,611ef5fe,7740bced,ef0b56eb,bb35a12c,7133f8ab,68f937b3,28b64809,27e1063a,bbbc36b5,b097ae5c,ccfbb965,f4814f,ea9fb5b6) -,S(2851bdbf,cddc8af1,7a20c1ae,bd529df8,28486bc5,50a00b24,763600d6,904af615,d302c085,702e27ae,6d46c376,33035d6,ee2acfc8,3b731758,5d15b2d6,dccb1356) -,S(e986d7ab,25499f1,45610b79,1b47e597,8be3d363,5a6f29c2,5d34da48,314bdfef,d0638dc,b3b3c150,10ec63b9,61104559,cfdb182d,31c41c16,5f53c331,47de35a6) -,S(bc45db2c,5639b2ce,2dc1c5e0,d831d824,ab44daca,7fbfa099,b2e648e2,8f8bfc03,5d93e3b1,27b289ad,49e32740,a9f53e0,79a80580,82606884,2c1f9b52,7213e32) -,S(4145d67e,47d9809d,2c67b4c8,49e29101,849ef512,ca7b22fd,667498cb,50a8dfc6,5471f4fc,2a4f7f82,9708604d,90daa64f,daeae007,d6290ea9,4922173a,4513f096) -,S(2d157f7f,4cd79d56,bb15314a,a738dcea,427e3087,e7a5afa3,c1ad740f,5c686825,c1c4f318,76159f4b,94e7a29a,2766bb46,962a4e21,3a7234ee,eabf1ea2,296fc1c0) -,S(2f426284,77040b2e,5dfe26cb,c12a81b,d6e89696,8226987b,361d7961,a73933ba,bdce120d,141b2879,effcf601,c75532f8,a384f942,879f24bd,45e483d1,8144075e) -,S(b419cfa7,6cc91302,e683c9c0,eef23ca7,bf9f8f44,37ea220a,b8a1fffc,3bbf527f,bb86954e,290f2419,e4891a70,b48806b4,a911e956,e3cd0dba,3c0251e3,aa929517) -,S(cdb4a6f9,5734164f,c7af2913,f0ded939,2b17bd09,b03698dc,ae2d72d5,4925236f,89eda236,bd1bf5d7,e500c47,d4996451,d57c963c,4f125ff,c9ef8e6e,aac8e7aa) -,S(ed4ea751,a45ac44a,33e6f2f1,50392fe8,a12a8c4c,2233ca3e,321800f8,f408c256,9c7e9da7,4a2b349a,ae9266d4,d04d912c,a296d963,98ace64a,caf40634,970ffef2) -,S(9b06fd38,fdf963c2,830ccfcd,1df08a73,84a74b02,fa79a87c,96decd0a,3cfbf5d3,e866461c,e7ee6015,aec4ba3c,d4dad0d6,3ede27a3,2a1b20d4,eb29de00,6b226416) -,S(df11481e,efc1cd1a,97e13f1e,e0702056,c2b7894b,de1a44ef,5166e521,1af6ae75,a1411856,35429fa1,ebee1f24,de73e2cd,80c76661,717abad4,a8354aba,222b7e02) -,S(f8328d01,b1f3fb3,d07bc65d,e807c619,46e4df15,a518a845,23da032d,12a3c9f5,e29dbc74,7746d478,9ca9a6d0,b5ca9ebe,de174914,7a709df0,d5e0f100,cdca6216) -,S(3e3afbbd,b7fc2301,f9a13590,acc4fb5,ff0d1b7a,92e09e46,1fcf0093,4d3fff86,1fc7f7e1,b9821c51,bd44c8d0,9619aeb1,a5c2af1c,3ec28742,f0f26212,6eb6ebd6) -,S(aad17eea,68348015,9cc19f8b,69d335b4,78ede880,4c551660,74d1ea9b,1ff86125,e993b8c,ebab89db,67cf45bf,361ee910,dfa1749d,26b488e8,ed6cf9df,9d365257) -,S(213fbb19,5515c686,fe8f44b6,fe26a178,286442b8,fb29072d,37ce9972,910ea35c,497b951b,7df7f4bb,2d0ee577,19876203,d68c3958,62781362,18e8969d,ed52a852) -,S(cd7f72a5,78ed819e,3e93321e,c8b8c7a7,eba91b47,92821a2,92493790,370120fa,a3d51c70,99280f2c,fa2c537d,991077e6,ca4eac91,93e97ce2,d8ff5fcf,45bb1148) -,S(70a360c7,a72939,f9a3a28a,1d1a9e2f,8240aec1,878f9b19,68923e0,b67f3b51,a1d9c07c,53a4dbc2,2ea4ae36,b6a0bb8c,dd175c98,6d2f61b7,3eb05552,ad710259) -,S(544a615b,4f8e2b66,fa1dd19,99e9cbe8,eedc35fd,9cda6d33,7a076601,21b5e46a,75d26db9,c76fc8d7,65286aec,bdd9c97f,d7ba7a9a,7308e6bd,75150b35,ba8451e5) -,S(4218d79f,76a073d7,af19b265,74d5b5c8,f8b779f7,36c23c92,a01c3467,8ec8acef,6815f631,49073b5f,e65c05f4,eb284c21,87e60355,e207cbda,f2c01eb9,becfb28e) -,S(6ada2638,1a82acc1,8a333759,8635f83a,3deca5d,9e4dbb38,64a2fc1a,a269b0a9,53d356da,65f7526f,60d05f32,b8b5f841,2e77b6f8,b61533ba,e8ace229,5eda6c08) -,S(5fa99d01,d9f29a59,75518e98,7c382c41,8bd46ea4,7813f579,3366618e,e118b09e,d479d238,38deb81b,dcce381e,4982652a,f15f6602,dbec34cd,6fc0e82d,33fc3b39) -,S(cc6ed576,34cc67ab,6ea676d7,2fef96d3,bbb4a00,b2b7fe44,12d0195b,44d76f6e,b15c15a,d50999b8,aac9e5f1,5834284f,dd801b0d,da4be94,f520af62,f7bf820c) -,S(e4cd0fdb,5323ea3f,deb10bf8,90a26b6d,ff447679,d8747ddf,ec32ee3a,40ffceb4,fbdb40c8,ba9c4357,656af718,db7629c4,e2caa87b,c41f8c48,d5d86a30,d220e1f5) -,S(77fd722a,ba51b929,ac1e3ca1,a2346833,b3c1fec,7a756568,6afb7cd8,9b88a8af,d02519e1,d6e9cb4,4f378ee3,1df4bb74,6b5b555b,2c7b0691,9cf90f5b,3de98505) -,S(4d391fbc,a9dd3d47,9d3ca57b,f299f4f8,6291e523,95ff73e2,665418c2,997a41dd,5cc9ec33,b55e606b,b93e9fcd,593c43f3,e5d4a3c4,39ec6fce,1a9ebf25,b4ce899e) -,S(740bc446,17b17b84,5c99d63c,3c92fe81,2eb232f8,8161a2ba,83f3a445,73084e97,fd8ec6e,f4f9567,71717481,c1301876,fb10742a,99028c67,883254af,f8355464) -,S(c258c21c,adeb8453,5bafd8d6,cced030,c6aa12c4,1bdcc392,b2d10e5b,1b46e5c,7cdf037f,3e60bd7f,739d08af,a20de5f2,b73646a7,5ec3e2af,4cb62139,5d171d31) -,S(8fc88069,733a4d5d,bd80261,c0c9ca65,fac22a5e,1bffd768,dbeffb83,24130d44,4211a94b,f88c042d,54d37ba7,41cee691,ca5bf0a6,38f0ca95,954f4aa0,12fc946e) -,S(cf62ee1a,40321c24,7fbb0e0b,ce99d314,f5152de3,32b827c9,67a61bb9,c96ad4c,6284a7c3,e64f7b8d,4bd978c0,77dc0d22,e6137336,6410d5a1,9bb09640,1ec4a3fe) -,S(53351f8a,4d447760,ecc88443,19b69160,bb00b3ca,fd6fd9d0,6c0040e4,549f8ba7,83844e19,3816e6ff,755c148f,d5488384,c7c1cbb8,8c09ea0a,16352bcd,377f6b83) -,S(a02063ce,ee2c9191,94d0e1f6,2ace9407,baa0157a,d2e600a9,e173348a,1d06bb0c,630461b5,55653f52,da9b40ea,c4448a8b,fcdaeeb0,1007dde0,5f4c186e,9f146339) -,S(70bcbdcc,25de1764,7274f374,196608aa,c360c09e,951b9857,5a6a8d6f,e1d35660,3bd5bd9b,716359ce,80b5e719,a9e1d40c,3a1c7430,94a82b64,a90b0f4e,db461d74) -,S(df8ad77,83cfc3c0,6fbb1fe5,2a515de0,54b161c1,74155fff,13812d19,aadc8fc7,bc4090f6,416db0c,9d34ff20,a0b7cb99,af38401b,1264c604,44ec7355,80069569) -,S(2504e9cc,ef399800,5f2fff3a,452d56fa,8788df47,e05509ed,777a9d9e,540a30f9,73c506a2,c6f48efc,af7f4d2f,ab5fd833,6fd6514e,db690a51,11659f79,7390612a) -,S(24ee0724,1c920334,3a6a6fa5,68979fce,18a9ce0c,819e3a61,571141a3,5bc97025,ee642ecd,605b84e8,68940a6c,cd7f4d93,fa0c6816,2fb0bf6,ba22427c,b0bd7b8a) -,S(1ead5ce0,9665c05a,63cd8eb1,12097f35,4961e12b,25c03093,e1c6d919,7a3929b3,1800df5d,a1abcc4a,b1c32fbe,a1dd7120,7284b5f5,dee7009d,c2f4aa6d,7156fcc3) -,S(47cf2ff2,26084f8f,9020b0dc,d838874b,160c69ef,2e5e89c0,98e7891e,ea05d507,a340d3df,129b5aff,1044d0d2,c3866464,bca2efdc,8dc83516,cf8fa522,d5fb7d48) -,S(4064fb9b,8e2e4952,a218bb8e,ae474a4d,51f050a8,3f9a7e75,b04e39c4,42d6cbdd,ff9cec76,a2ef1930,92d3e02a,aaddce0d,18ea66c0,d1adfd2b,9c7886dd,b835de10) -,S(838ac8d6,e58e20d0,321e0150,ba6d401f,cdd70a40,69d980d2,22de3353,fb81904e,993a6f96,2909dbbf,7b9a6b25,14153331,b1ef24fc,e892710,5f95488a,d95614bc) -,S(a5e36d83,189d43d2,34d6ea26,ecf5943,5aedee72,bc4cf385,5fce9b5e,e202f266,78c02c3c,e25c3b89,9dd2933f,b41435a3,dfc2d1b5,e7ebbfe9,54ab1c94,79822c55) -,S(9e240cbc,d357c4d3,34f31209,58d6f7ad,5ad79e7a,9b51f572,5ddc8fe3,1fba72c9,aea34a5c,ed60a062,ec1476b7,b30b3c9c,68cc5e10,cef9f0eb,6729172c,b511f06b) -,S(ad1b0646,bb315380,5c22b91d,1ee47a26,dfc9ed5a,860be0c7,ea8daec3,b6dc2eba,ee2e61a2,2499c509,1a910c9e,ea159873,a298daa9,6d30d8bb,353b9955,92dd2083) -,S(4f7b0889,11d8f64a,550d8c7f,11ecaa6,fa12df74,a236a0cc,35cb7cd3,5b0ec72b,931af41b,d297e18,b4d9ffac,8d7f8691,29b94250,f1de1d99,3e31525c,4dbb21e3) -,S(dab2a170,e4108f3c,93fba874,70bb12fa,834d0274,35695870,d2d3523c,93d3a7ee,262f12cf,c37f010d,deaecb24,d08ce35b,293a5c6f,1746651e,7bb0b2fb,c573ae4d) -,S(3437257b,784d72e,419e5082,311b5a66,d499f687,c4bcfa31,7abc7484,a3cf39be,ce9bcf07,6da8d68e,8453fa14,3b06d7c0,f38bd0a0,76f1cec2,a49b3bda,a5c398d3) -,S(4594ae9f,82611ab5,bf786024,ea34bfaf,939fa409,34ad155c,9ed5e736,899545b,2255c7f5,62b0ba72,c3834e72,e77b478d,77d3f15e,3ee0cda4,c4b3f928,ead450f5) -,S(7337705,12db06fb,36b21fc,26b585a7,3aebb036,b22743c2,f13212dd,81898819,753ddd59,725fb0a2,561cf461,c587f3f8,848b53ed,29283c51,5150c57f,50307887) -,S(bd915814,4d2afef3,552d81c1,8c74abc,a53f4c2d,654f72e,3f2abd66,d69790ff,1af609e1,7f27e373,b42b3277,a5f4714a,31ae895b,95e0c5b9,50e7ed2d,1827763e) -,S(8a11cd4c,a51dfee2,28c1ced9,3d8870d,67782740,1f49fc73,d4ce56db,915bb557,d30ad7ee,ae9f9c97,eec27822,9f47100e,ca46b3f0,27339719,6be0f619,56f5cf23) -,S(7929b5f0,2802bfeb,6c23e688,65b0272b,cfd058d7,c0a45ea6,97d46d87,6f9bfcfd,f9bbae21,8039783d,4d1e366c,32a890c1,8c80d1cd,41f08b36,963b54e2,f4fde5d0) -,S(80df06ac,1d5b966f,8080e79b,cc9f01f3,d55f8855,9b1a58bc,f6e4c526,3bd89d01,346926d0,a59558a9,2625614b,ac010f36,5ee5c337,2660fa7e,be41aac9,41136538) -,S(74545478,9ff383f2,94a92b4f,383ad13b,ed4b01da,d20f4ac6,efc83315,be5ccaf7,36489f77,81ee77fe,de1ea165,c4cf2b5f,e8217361,9e760cea,fae777cb,c160fa9a) -,S(2c6d35bc,b213a8a0,95c11fdb,42828b7f,e562d7d5,f877de67,de62bcd8,5af8fe85,aa30e370,34094f9f,4502206c,72f23298,2e60139c,2bd35631,44dbe6b4,c75d159b) -,S(8353657a,9d934eb0,2811846a,728cd162,4b43429d,304aa7be,830da70f,b2e338db,f8400438,20ffa5d,28189c5a,ce693c8a,ed4a4caf,3aff83b1,66a9d404,74e02b71) -,S(f216e93a,54ce56d7,c7ef6336,561a6299,2177ca73,4ed867f6,fd1a8ddf,aaae494f,db0a3f13,a0fe8326,63e8fad,b11cc347,8da296b7,2f1b672,3f43ea44,acd30611) -,S(dc371221,9b5d73f9,6562baa4,b62ec7f4,2e9a3dc8,de6e7112,273d0811,a88324fb,eecc9092,ec563e96,3720acaa,929f9bb4,4f1c9015,7c3300fb,581b154f,df57c004) -,S(db34736d,48f0b4f1,e1ef6029,6ef534ae,b10f047b,4256516d,d4499072,36649475,1c29cd6c,f7a8c786,952c34c9,b93e5188,1a116966,164d0fdf,dd1be4fe,ac586bec) -,S(a248457,20468424,f355af53,62f5bcf1,971b09ed,358fbd33,78fc7297,3696add,9a703d61,37d0deb8,a3767a56,c2e24573,baffc931,bc850694,8c9a3776,26547803) -,S(bb7b806f,a9ac753b,bbeaa429,31f68d0e,3eba38b9,8fb25ed2,40c9faa3,124436c4,8f812574,a1a8bbe8,d9b682e3,d9b0150c,7c6ff9c,f9b42e64,6e5836a8,12426752) -,S(6703c476,fc28a023,f6619427,69e0f068,489344aa,74495ad5,17b096ff,c3ecf446,8b48023f,7c9ba723,584211a3,6731e14,f42699ab,522e15e,ed3ac43d,28e2a38c) -,S(bcaaf8e4,bfa4b448,fe23f3b7,a1612b82,14cf0daa,349463b7,1b44ba61,e2dbf6a2,bdff2700,e2cc953f,e9d08835,dbe8793b,b07498ec,68ccd736,d6fe1710,d5c7f404) -,S(906b4fda,1a557220,1dd5b446,d726a2e6,21794517,3ec74f7b,bfed8791,9310cd49,d753f2db,cd2c4d28,d0304bc4,78690871,cf838490,2d7f4f93,441a74d3,892653cf) -,S(9ec09783,18f7d95,5180e326,e1bfdd04,fa5369cd,eb786905,8d726ac3,9ef93d5f,9cca8057,994b1641,53ac6842,4d28fb70,ad22baf8,f894a049,d1794add,97acf205) -,S(53347906,b75440ec,28362a96,f114d2f3,6f823cbe,bb0030f3,a2de3314,12b8209d,ccb38e0,471f8abe,47ef1bf0,29550ec5,59581680,3e19034a,b06a090c,ca0c1fa0) -,S(27c53f29,61b70480,93e24b18,eb357807,a33e5411,15215337,3b98f80d,d23a4870,5a3f4b8d,e18636c4,71fc70e5,9ac8c4e4,703fa5fa,880594fe,2f3b888b,da575601) -,S(921927e3,7a115f9a,12a616ba,cf55c213,22ed51a3,e75caa5b,eaccce75,de59b68f,bdbb7c7b,c1e4c5b5,98afb590,6263d779,55884e71,17864ae2,e0636c4d,727b141) -,S(973b3c87,6eb81ffd,677c692c,ae432751,efb3e609,1a3d9ff8,dde6cd6e,3f3ea8c2,340df771,129510b,a4112c5d,adbcecd9,8684b0ae,3a9683b8,49aebdd9,57bbb0ed) -,S(20b817de,f0533767,9938ef03,69204700,d5972c32,12656ce4,205e9ac,1b01ae71,2ae2fe5b,e2daa016,1c65c352,94a0abc5,c6b1ce64,fea99c12,34a14aa8,8395707b) -,S(63e2544f,7a7e9181,7a347b7,f72eb43d,ca9fc5d6,3d931402,aa6889b4,a3c95876,e62aee6d,20d714ce,5cdf52,18bd5fae,adf49cb1,f86e6067,f91cad71,280d16b1) -,S(2f90de10,71508cf0,b3583abf,c47d762d,a69dd472,e4183421,6ac39753,e22aeb80,5371bebd,4a0dd74,625e5e02,5a118488,880f3a89,9c23e64b,76193abd,3788d389) -,S(8d423ce8,faa96d05,45e37cf7,5e5a351f,7c9359c2,ad1c48a,c9adcf29,d2ed7209,83d4b83d,ee76c401,a18df794,8a655c3f,bb9d23c1,5ac0bd6e,ea80b129,bab40f2) -,S(12fa4142,5e028aff,303111a2,9144242,a9c91d88,55b3ea3,becec110,80181efd,6b95b370,8e792b57,ac10eddb,362eb10f,ee5c3b8b,b2e37d4d,c4d2ac40,e8c3ff57) -,S(923ca95f,2a3bdd7c,d7505632,cdf2d730,ce70196f,ffd0cbbf,f8347882,8a706f73,f8b0c866,c39b6173,b383983b,210cfff3,1903afdb,cad0b2ee,3e541ab5,2746abbc) -,S(844d53e,878240e9,63e3875a,728f4704,64ce3aa1,66209776,a869e0d6,88893646,c60cd291,92bf8c1f,f98c47b4,a713bc75,1c84f9c7,19fb32b2,5b855e73,6feeaca1) -,S(43786fd6,c5471d8d,ba277ff8,1005a5df,8838299f,66636b2a,65e7ac21,f1dc98f3,d292a2c2,9c8c5bbd,8f79109c,b8706fe7,745ff884,f98c127e,9142f52a,56091b51) -,S(6d1bc28d,f5e9ecf6,38783f71,fb98a2ce,bb0dec45,8b07257c,e94736dc,ae36d7ab,c2c54192,bfd80447,86214cf7,a28108dc,e2c00e07,2321638d,a0e80023,88d549e6) -,S(6bc4ef34,7f74ce3c,2ef3f89c,c3e265d5,6c742ccc,ff84b7f6,7d8956ab,16ff86c6,eb4492fd,2d2ab04f,1276be35,c6bde62d,be26a6e4,60c5c66b,8b0fccf1,79b46408) -,S(6af45075,fa810958,d42a756e,d08d5c,d67a62b,cb33cddc,b35fa99b,bf678b38,adbb724f,e7682c7,678ffc3f,ab738666,886c7b93,84960bfd,5287ff9f,ba5bff28) -,S(eb6d8b76,36466365,a96f49cd,355b7460,939f340f,905ad1ca,a24e8a66,55260600,7ae9cefd,aea30b7f,b9ba11ff,603b81d2,41f7a187,33f95c3,3c2bae0d,7fbea3cd) -,S(bd0c2233,2fef7d3f,6738dd69,4bad4cf5,b34d5e9b,ad6500af,11e4575e,91795068,eaba5c4e,2ea0b21c,a9100b6,66823a4d,a91c4d57,3aa9d136,76f820be,9d1cf209) -,S(c5e23bbd,c5049419,3483e083,14249157,aa56d9f,804374b5,54c9879,52b7e392,4caeb8cb,f684217f,bfdcd02e,3aa4ae3f,8d59e766,855b4fe2,f7f8ac7a,6e597751) -,S(b5717631,f3aaab92,5543edb0,3d21c604,17178e98,dea38bd8,10867cf8,8c92d2a3,e74209cc,324a9ef,8b31874,524dbab4,d2bdf0ac,8f1d20e9,a02409f2,8c11942a) -,S(9c456099,49601f2f,caca85d5,d30a07e1,b2d17b7c,7b838cca,2fe4b5e9,5d305cfc,2d7a1540,a109dc7c,2841b61b,31e50078,329273c3,585c8674,674ee06e,ff04eeb6) -,S(52ae2946,c0ab36c4,a8aff175,73b6604b,e33dae5d,73228d54,98c77a51,8aa82f63,70e23d9b,66061bfa,4d03f899,b65493f2,7179f5c8,643104d,24dd771c,777f87b4) -,S(149ec3bf,55ff462d,dc1ba490,384081e9,89db9ac2,c29efdce,f4f59f0a,394adf9,59c1d88,b91db942,2ae8fbc7,ce6951c8,49642b5c,df949801,341a8bc1,789dd7af) -,S(aff89294,d66718dd,dff83534,61538da3,dbe14a09,c14d0576,8a163810,42ea7ea7,71866beb,cf5887a5,ece2352a,cbc256dd,7b615491,2a88cbb9,a924e764,4d59266b) -,S(de44f478,2cb30472,ad52d49b,303e2b41,33887eb7,38e2ab78,da7bb406,584e76fc,6798ad84,25bad82c,57c630d,7ac8ef21,b13d08fa,830edda7,eefd23c9,ce482bf5) -,S(e0bc7a73,76169366,c172c88b,e1ba02c6,b3a380eb,2894e134,5a2ec7c7,39682e61,bd147eb9,33b18fe8,dfe7c0ec,87b7e993,5ad1f7c2,ab5424d3,c23609cd,262cb2e0) -,S(5ee34f27,2af69f33,9473cfa7,a536a22,ed26139a,71cfbb11,27c7a476,32f0e6d,c1df8f96,dc0d4d82,f6a57de9,85cdefc5,1316bf10,dc3636cb,80762aea,c4e13b8c) -,S(4dca3bc1,77fa7a63,9b8c274d,fe157d7b,67296846,bed5d13a,68bce5e8,e599a0f2,8fd2b558,36fb9aeb,fdb3fd75,8f59c8e9,2fb48968,52eff2a1,d01c32c5,3d2fb234) -,S(554f6bc1,87560290,ef9ed937,3e993f54,98081034,a03484f5,bc184751,f8b48136,b454c3b7,dfd512a3,517834e0,e8c3f50f,de80863a,1e0fd83d,2064a6bc,a172b26a) -,S(95a81b50,a6c0879a,6a960b2e,162dc22e,955af87c,b539eba4,20b2825b,85592ad4,be55e8c4,dfed22d1,f5872b75,f38aa4c3,7c7d5086,f67011af,2651ab0c,c45c712) -,S(907b6d53,9e496a6e,358d14d3,431f5582,44a4f8a6,ea291d85,3efb8be7,477e5c4d,b3d3d694,3853bb9e,67817fad,1dd7d1d5,ff33e200,2922665c,21f872e4,77150eac) -,S(8527c81b,b342576f,67737cb2,33f17605,c8884c64,6b7a8357,5bcccc09,c7f17aa6,b6d675bc,db8d5249,57b1930c,145777f1,9cd47b9d,33386a64,5044e8f5,877604fc) -,S(8e1e3a7d,5a320d92,4ea13436,f906e9b,bc6bf83a,819b9e9f,913974e2,efab00ec,d94f03ab,d81d5f25,c323dad4,ea792c50,792e07c,79281c4a,ff309e0f,f418b0b9) -,S(fc02cb93,be1f4a8d,9acbd86,bc68cb6a,dd0d8949,5cc7434d,72cfab75,519a8d76,71f7a532,729e45c5,98a6ceb0,885a256e,ffe4cd9d,967e84e9,8b73c772,7e4d4f94) -,S(cf981302,a2858b3b,b1ac44db,4f08751b,ff76357f,9b2ed6af,80a289b1,be6e7b8,237e9c12,bf23666e,70205ded,984f1fa2,f1a8a828,b88847ba,d3a1be88,8d73b528) -,S(3e6e45dc,1408e920,3ca74cbb,ac8d50cf,71718d1e,ba05228,e97dc4be,a8231d82,2e3fdb7a,2ad3a805,f61f287c,a7ef86df,961009e1,f0fde8a3,14774677,3b1ef848) -,S(bb047795,7581471,10809088,8119b0ee,3ce1b2b2,df2668b3,749b9eda,707d4657,95a72efc,5f95f3a6,af5ad697,7dbeeed2,8d6ee55b,fce29bc1,bc439168,75c67587) -,S(4e015d42,b8b02c10,4aba3103,4ce04cb5,fe356d,81291939,3f5d1b9,68dd6748,d35b20e7,dfbf6d71,d94e96ff,c9267422,746419fa,811bcd2d,d3942c00,70a870fb) -,S(609a4c57,90c8b210,9eb7391b,d68d078e,70850af2,410df867,92a37459,24a49daf,f3a6327e,bc965b3a,581cb14e,78a4390b,14431d00,d1f34e8a,e35502f,bad0e98) -,S(ccbe0736,2a955ac0,4e1b7558,a17ecf61,b9ea0761,305b4aa1,780bab03,a27fc730,f96b7c16,6c98a1d7,65ea4e3a,e0643298,d981a012,4b03fabb,71fc47f9,1c92cd3b) -,S(6ed60282,85df2302,e6b10ef9,4e11ce0,9143c569,a84388c3,e2151c69,c3ccab14,675ea3b0,687a3b78,e8fc7564,9665e62f,e91b0d1c,25852608,1d591ea5,1ad196e7) -,S(bdff05cb,a0cca14c,55b3c592,38515532,70806177,443dac7f,4c07ff69,cb49d8e0,5149ad04,86cd8ecc,274a7239,833910f,f09d7993,aaac9798,1dd106da,6e0c9a50) -,S(64ce68c,cc70325b,22be5366,579aed1c,af9f6e55,c2c7386e,ed579911,4e2bff2b,f8c89976,3c8a9a0e,ef61dddf,2213cbba,11bf1be1,eab6506b,d596aede,45cb1cae) -,S(cd42e46f,489150f3,dcaf3c06,e1e5a2f6,b40de7f5,626107ed,af01471a,18ab2bb4,d9c250dd,d2026967,b4c921f4,e253a788,17f11f89,f679e5c2,81dfda0a,1bcfada) -,S(f7c29007,e7145420,e2da7e8e,3ec4daea,5e9b121c,35c4ec43,59d55f01,89619735,66451406,4dbda93e,637735a5,6a06ddb0,5ea2933a,36cfa3dd,c2ba4a33,eba493b7) -,S(6339c1e1,d4944856,26b3d221,4715835c,377609d2,d91150f2,c5c1f679,5e93b7a8,efbe6dea,47b4e8f7,ff55a20d,8facb8c1,d10a6960,98762d95,be532fc7,3ed59b28) -,S(fccf1f13,7d22ed06,5f4bbcf1,e9f4eb86,7b1ec78,d9f40b4d,aaf58014,3489b37b,a5a77c2f,ef9facc3,881559d9,d9756b4d,6646beaf,21b3511c,64a4b550,7dbf3e10) -,S(da97ff10,6f284ec,f123b554,17bc8f5c,a13434d7,58ec3d4e,935c1600,404f62d2,65c2168b,4900330d,f2f1e3d1,cd8ab92a,4f308222,881a493c,f8b301cc,af12e168) -,S(6676a4d5,428a24ce,36957556,c1b44593,343ab6f2,21f0b9bd,dce2d898,333e4fd8,45bddca4,b9332535,f5f4d3d8,3467d793,b7afcf58,45a19593,854b1c5f,3daf7b41) -,S(791e6abe,cf461420,54a22c7c,d3deea41,53396e7a,2a619ccd,30212ade,e57859ca,e4033bfd,8c55c93,ec732990,aff43ecb,e2ec07dd,17e4ec92,68a7b0cc,fadd37a1) -,S(3a7c7bb2,d5181550,a78985aa,84b73246,c66dd947,4bd7c5ae,20717f31,af0018a1,2388eb17,e03cedc5,221f732a,9e505f8a,b6c38d25,184afd14,37b52d45,fe9d7459) -,S(249a2db1,86801c96,9cbca936,101381d7,62b74017,2b454c3b,ef720bc5,413ab999,da185c41,76aa91c1,d783cf9c,85c075e8,2f708e0b,3ec930cf,f71897b5,d1d5e7a3) -,S(b25e0d53,b4e0cc09,985f21e0,c5655e50,32c0857f,b792b136,14da6885,6b4f8590,1bd17aff,6b02e3ac,e1cfac42,fd28d837,ac5b80,42b21055,d6b84e67,5d83eda2) -,S(73605368,5e83388,a869db66,f110243e,bd1073f7,517fecd6,1359eab,b7862fcd,e9c7a02d,842c5a6,fa43407,6e12d41f,e767fae5,5a75e913,d6912536,6d5f9d56) -,S(ec2f0b56,71392e97,2f8a0c9,af259d42,2e5b52da,5e70fff9,7115c961,77f1b1d9,47f7debb,adb24e59,c8571fa,98e56d32,d49e072b,4fdec818,2049498e,908183a8) -,S(7d7a8fa8,250dd43a,91a2ad2f,320e18c1,afc25595,213778e5,cbfa6058,4be2d378,6b48ba16,89627d77,2700f11,9bc20d7,fab2b07a,413f752e,2a0e111,60fea3be) -,S(316a71ce,52b6723b,a67aaa01,e26082c6,6e59490,cff4c366,5c695ff,aa6713d7,d6f1c1a0,7820c612,12b44cf6,e5cb4ba1,84152ffd,cf82e020,e95af73,d6a1cb9e) -,S(21a2a8c3,ade89ff,c32e5fc6,ead97a22,9ace8857,11db9930,ade6e72a,9fbcca51,95fd3d04,38df517b,5712aafb,432f0e35,726fd438,a2b941e4,7c56c1cf,8882e4d0) -,S(3f181867,b3ad8170,dad46c68,f513afae,1ad2cfde,41f9535,5369ec32,728f94d5,a51a94e4,e9f20eaa,d5599189,4222ab0d,91abb8f0,38b00a91,5f09df10,a2317527) -,S(e9673139,11be39bc,f11ecb9b,690ecfb4,79b7aa6d,3158ea69,7d0092f0,89f63c1e,c100cf7,6f8783e3,8de2017c,32022a0,da9be6e8,61307546,1f98142d,4903abc2) -,S(61ea8ab0,1407ac7e,547e94b0,6f3986c6,d3096d43,2bd08cd8,61554fae,9008b122,e5c55bcc,a6f713a9,76490488,e69f1cee,150167f4,283fa792,a105ca8f,f4a4d182) -,S(ad8fae7a,17457fdd,9f481554,239a3f1,49673df7,24a3a402,cab73f93,bedab9fe,53b7dfef,7966c4bb,bb01d037,12563f79,48517220,2ed375d4,d777efef,50f03e6b) -,S(8605cedf,bf7f2e54,d3f62f27,44d9d436,cdf9974c,9190020c,586818bd,b6a829d3,5af8a55f,ca2aa1a,6209fe4d,a7708ff6,e7a33df0,50e85873,d786f54b,7d946b88) -,S(bdde544b,465b9ef4,7dcffa5a,7a794cf9,6e83253c,2f22d4c8,cbcd2d6c,ff921d87,6c536367,7ba867f5,5ede7d23,81be6ab,ec97c8d,f88a1a74,14ebd6ce,8caadcd8) -,S(31882a45,e8b088dc,93eeafca,85c28f49,62a47bd2,bad916bb,fe3e7346,32fe1cdb,b3588f0,c5f86e1e,12ab833c,12e028c9,d03557a9,e02aa1a6,fd11d693,55f176bc) -,S(17be4052,45800f9e,db510b72,603b8e63,e49fadbd,62798883,b0d04f76,a5dc1202,1504ebdc,df8855ae,28f7738,e40d277d,81667e55,a2f59cb9,c9e33a4b,8d32fc54) -,S(c633bd33,bb697d2a,6bfc4e69,707f2b28,a303eaf5,a601b08c,9c56afad,cb629537,86e3f413,2d4764db,f2c06b92,461c64f3,9f3b7f78,33139eac,2b4d59b7,ba18cef8) -,S(f39e208a,f4c710f7,190881f3,a33cd113,633434b6,3b460062,570618f5,8260bb52,90c56805,807b36f6,272e2b66,4d943c33,d0171ee3,ba5cd4e2,bfe52f92,b9e2e62c) -,S(ce984394,14f29607,a54ddfb3,72db8ac5,ee4e5414,f59f73db,89360232,f4a16c54,1a4805a1,d1057b13,c72f7835,4d40ae96,bb80542d,ba5ebd7f,627cfbae,ba24e0d7) -,S(5266e79f,81107a4f,ba571af1,885d755,94504122,a15a673f,6257f633,bb0a76bb,5e7ad1d0,9cc85f12,8773ca39,77b55c20,18d38200,fb739918,d3b0fc96,a559b457) -,S(4fb9de57,63f47aa3,bf370113,c778bc8b,67507009,5126f5c1,1ffc158f,be7056e4,2cd97636,8eec7197,aa2fa34,72fe3db2,29fe0275,8789d75e,52e87553,1486f7ef) -,S(ad168024,a99eddbd,aabec840,6158cb92,4ae7bba8,d233745b,ded57407,23cc0226,ab105015,968e4673,8ede230b,b53c4be6,9ee6386b,91ee03cb,a21f7040,f14095de) -,S(55829ae,f7cc555b,733aea9b,f1b307d,277923ba,148ba8d5,5a7c8001,73719cb8,6a7b2eeb,9c9b9585,5403b47d,6c60a7bc,382969f6,c4bafd3d,3c4f09a7,63267689) -,S(2119f233,8efa4e0e,2204bbe7,84e9de01,4e1e4c43,450d5910,960ebc38,6b78b935,9f219dc3,778544c6,7a337db9,69c513a8,52acb469,34a71957,11c36913,b8e7bb93) -,S(11fc3e1b,9491be9,d7de53ca,a2558d36,c5227498,3f5c1b32,57f0fe5b,b1295bbf,1c69c74d,ecb05933,6aa6b6c0,231105ad,91b8d188,d109ced6,2198c528,844cf6f5) -,S(34b6ce6f,ea6e5143,95091bc8,67e606ad,5e64ac18,99085821,80abea3b,dfd2a908,5b6ed904,f4bdbef3,fb9e41a1,32c7a313,28e9f325,4e180694,40339642,2bccad6d) -,S(6c225dca,b45768ab,3b1c567d,97ef745c,b326fb3d,2db6ae2e,22a40c95,3610a84c,7e85d752,2180fd8c,ebf63cfa,2d843bdb,912fe042,d00ea29c,d72fd768,402a1084) -,S(5f776e5,41dd95c2,32fcc757,14b688b,cbfd2020,e7043e3,2a707144,5a8ed7d7,3b8c5c78,fc6d8354,3a09de0b,9a64d529,c116803f,6d0d62ff,2a20b369,8b273c0e) -,S(3e26d8c5,531543ef,5e37eaa6,3244faa5,d5371e48,16fd94e9,b8bbd932,891b0e23,30a09d1b,43a4a036,ee1a53bc,6c3ebfa,a5b4c70f,6d8af4b0,c70faabe,b79bb65) -,S(c634da91,c17a3568,aaa970ac,26553e45,6be8afb,ee12c85e,8aa0dabf,f18b36af,649681ba,e1390a7b,d05d34bd,98d87ed4,16eb9f99,c606f46d,6d522019,f1a925f0) -,S(ed335d6,4d643598,c6eab4ee,fc242d7e,4e8361b3,ac8d747e,806962df,2e7e9a7e,f0e7c3f8,19c97aa7,2334b690,98f28bee,5a1552e7,f578d5e1,eb56b600,fcaa93e7) -,S(d37f8c09,411359ec,3f63dbf2,2870ffb2,d10be164,7553f28e,d72d9585,1e521581,da7cbfb9,ba3ae036,72df1be7,56d3c9be,831467d4,cbe3b51a,191e47b4,9d1f1922) -,S(ee3121d7,c7475ea5,c3aae061,1c6b420c,5b32d05,ee86f919,43c3352e,7515c360,703b2e37,97bea3b2,9b447411,dad7b12d,b809164a,ba690281,b76f245b,bc4c1686) -,S(7b42c9bc,5c2b114e,a0ef1a59,492a6132,3f5c7290,427572b5,fe98017d,1987a12b,5cf76382,e85b73d7,56fcd92a,99242725,dd57edde,30ddd9c9,dc7dcd95,260d27da) -,S(9af5ff9a,b13a53a2,93f9b6b9,a0f925d4,7c8f9b84,5f6933c3,ad074922,f8a555cd,ca93ec9e,89954734,c8aa13fa,5908c855,13a9ec19,6417042c,a336f1fa,be5d4153) -,S(5ebfa274,1a2df1b,6e1d591,f70983dc,a5b2b850,856bd7b6,59c81877,3848dacc,b0adcb9,6ac23c64,2904c15e,822991e8,46e12411,f472e0fb,5fb69fc7,a0f7ad18) -,S(93b58d08,465e5eac,8518382b,c1f6ebec,daeb486,7da65dd3,ac125e6c,fcc81e6f,54be8918,c3151784,d74646c3,6bca9c8b,8a50b8d8,63b1db8c,f4fb3ef5,1a24a4e7) -,S(a28a579b,4fb46474,ffc943ee,32b40664,5bc86899,edaa111,32c31f1d,cb6fc858,40ee91a3,d5625648,196605f,f650ab7,6e059b14,faef6396,46c9b153,9af14670) -,S(e987909,781d5560,b71f6029,750d20ad,add7cb47,f90c9078,e8de5f2a,d606ac9a,7121ac3,4c80dacf,ffea346f,5c5e1a81,c55318de,ac8cc907,10274f18,ee9819d2) -,S(291ff11d,158780d7,fc0ee62a,e395456e,5c84bca9,75e84a7d,1d2b3bf4,61e1dcef,c5c8cbe8,abb6854b,670298ce,8224a945,71e79e37,9335acee,c230366a,53ec2616) -,S(4adb1390,9e28b53e,42bd9e57,373aa131,efda7d16,b8dffd82,4bd9803e,fde315b4,66d7eb12,b827ae7c,970a796e,5c0c99b1,24eb7002,4fde63ee,fa2ecdf5,d4b1456a) -,S(55e25f4b,95240efd,e3c7e47b,2254601e,1707a8d,e40bf384,6b3a7024,da7591ff,e9f2257b,7e98606d,743000b3,72dcba0b,e4491ae3,22e82266,4b1e2b5b,78c830c2) -,S(d24e7493,e41dfc32,be7a6d8d,5463834d,388ddd01,8c213ad8,aa3005b1,fa747eca,e73a8216,a51b4b16,5e9f5bee,414d49f2,6d7feba0,982b9e93,fc4b7863,48c26cac) -,S(a510b252,6d015da1,cb7e4600,3ed61af7,caa03562,19227d9,ed8eea13,61fd8b2a,3d98c2a0,9015abba,63eb15a2,80c6c479,eaa2b2f2,a0011adc,3565d2f3,8abea726) -,S(c04d04d8,127500d5,15bac63c,ca55d76c,8404cde6,fe681f4f,6b8c2b48,87b314d1,cb3fcd77,9fb80eba,99cdb937,31bc0814,e3cd4458,df7fee1b,98c4067a,db4d9d59) -,S(ec9c7c61,146c3357,ba851e69,18ffa770,6b5dd2ff,a789245a,df70f90,eebd0649,9a09d3fa,10ca6923,c068803c,e9161923,b36b0709,b12627a4,dafd0e3d,3d186170) -,S(95df5d3f,5d504c45,f4b7e840,3805e54b,b2598511,2ca53064,baced58,a0488cc,a43dcd85,89b85305,b07d1ef3,23eb305a,35079cdb,743dcc21,c7a6ad48,4ce8ecc6) -,S(b8eece0c,3a950c52,c46bf50e,b5dff949,2fc8ec4d,6bb19651,c72d447,633a6d16,74e942a3,1b75bf83,ba6c1460,d969a2c2,4a49572c,ce3fb84b,8d0b08e1,d5583744) -,S(599ece16,d1f69c22,53deac51,75121ea0,c82b2d77,c5e2c0ba,520bf1c,72dd09a2,48a10c3,25af3d0e,dd8e2e72,5d7baf48,b2fdb672,66423859,9f73d231,a911bb14) -,S(b8ba5a06,8d9458a9,6e2fdfaa,961acd80,7fff711b,bba4e3bc,35a5fcdf,e82ab32,8035ab22,7554582e,9038845,44d32a53,c2d82417,6e2ac7e3,2d44cecc,50f8ca4d) -,S(b6846be1,cccd7865,e56d3d7a,f1b1fff3,ae806380,a1710c50,8c35ed17,227e65f4,bbdb7025,32945f0a,de989f52,68230763,361ee9d4,9c0e6241,77fe6fb6,cbc7201) -,S(a1ffa65e,69872bbe,ed009e53,f846d9a1,20dd31b3,a11932ff,c3580ff8,da9d0fe,aa32e580,d5763bf9,dd054999,68b6ba6f,31c210cb,26846ada,dc0045b1,ceda215b) -,S(9b38176d,67091c7d,f448c707,80cef08a,2ad73cd6,de65eebe,b62f9a21,730d0fa2,22d26b19,c0fb9b7e,f1ec86ba,b8ff5996,64a45988,190499d2,6fb604ed,4e609207) -,S(bc2ccc9e,209dc64f,bb132553,bdab43fa,accfa4d,7deac898,1fa52841,35fd0cd2,47366adc,176ff88b,674931b,a8791fbd,350d1d13,71891343,74d58305,a55ccfa6) -,S(1ce000a1,65452a62,5d036f51,4fbd2a30,d4518734,e7f93aa6,7a7dcd7,24730f6a,e09103fb,5b90f0ed,54b34baf,3e3d5bf3,fa288acd,b6b0ec19,ee3062af,35c6811d) -,S(846c569a,887d64c0,e8fb26a4,49c62447,4cc63d68,4da0909d,63dcdd0a,dde0031f,547753,132c9f98,d7facf93,d4ff0416,7dcbe44,77987be4,7df408c6,fa12c07e) -,S(6365a8f7,28656e23,c9c58518,5686b18b,701f7b1f,54c84b82,f5c81ea5,74fe59e9,8c7cddfd,a992e53c,ad151d46,c9cc0b3d,be27f2b5,7ffcc23f,c8d9cfa7,eb16c2eb) -,S(ed425f3c,89ae3d8d,97972619,55e8fd17,71dc5bf5,98c5237f,bd267f80,7d2939fc,4226abdc,14f7a03b,cd7285fd,19cf14f6,10c98d0,6e3c1d74,daffd602,99a3590b) -,S(cda5246c,2e1b7ebe,8d667f23,5ae310be,85a0bd7a,2e903d56,62a6dca3,971f00c7,791ef296,f8ea9b34,918534ba,318a4fea,96b2c2f3,21e6d3f6,eae8248b,29247f56) -,S(b42a84e6,ce79c1e1,bedd3f7e,596a11c2,f5017d98,386fbbc6,f906a5a3,f4eaf99e,2e722cc9,60bb3718,36ffad5e,47509fcb,cc3d0601,70b02610,823fa40e,d407e6ac) -,S(358be08c,e1e2e9bc,b43149df,58700875,be23cad0,ba8524c1,6d46a01f,ab0bcf90,f3c4fef0,70baaccc,f64fe0bf,b6f5111b,462318a6,36489b00,34f05c44,1f9d1308) -,S(3ed6435d,e5b36230,a4f74bfe,14571041,427d16f7,9b433ac9,85c9e135,6016a789,1c72e85e,142743d2,b5be677e,352d3dff,ee0dc56d,5aa56d91,4b92762,6041f26f) -,S(249f7e2c,580dda16,5940d7e2,672176f4,afb7e50,b9250610,c253d9e6,2416c910,6fc16311,49e9916e,8f70f842,3dcde36e,1630f508,79e96e48,6dc7147b,3aa9f50c) -,S(97b3b144,e8381ba3,1b0f6f0b,752cbf91,14d2d76f,6f418d4c,69f0de6e,c89cc85f,67c9bd30,33b720b5,a1449257,f1de85a,f7282260,9e411dc2,1820444d,c988724f) -,S(3b38459e,868b2912,51d0fcaf,41245087,80610d0e,395e9b68,cfaeef1a,5f395a85,be5180dd,bfde7454,c78cc9a2,b77245eb,91ec4c25,9b17e3a3,c3e8e49d,5225ce6f) -,S(4e6f1790,9f33e08a,914974f4,48270fd0,74fb35d1,49a017ef,c54fe21c,96163ebf,fb6578f,6f47156,5b6d3491,3a9a5e4c,dcd2880,d774e6a3,e56cd078,e6b9fd15) -,S(9141ac63,e408937d,7425a0a6,70a2565e,72e301b7,75619a92,18db32da,315c75de,d35e290a,56bec3e1,3cc55e72,12aa57db,f10b34df,bd7847a0,5de91c4f,546d6045) -,S(ec9b73ca,72052751,565c006a,4fc9200,337c9162,88eddaa2,e212c611,395ba578,37e11ef5,c1a22e77,38d5f3ab,4c74e2f1,ba192275,4c4e7905,1b15010f,3c224887) -,S(56fc14e1,bb1a928f,ce0430b1,feaac6e5,aef50208,be530d7e,f0f5b81a,ce1caca3,4e5a6084,f8680d07,9f3101d7,a80f452b,b05e597c,c38d9865,f6d7f307,90209001) -,S(aecd741b,2cebd4cc,82b7c362,70f1b22c,cf3997c3,f180e1e4,d803a89a,657df731,5f104b33,6c0df49f,1936356e,8dd09b3a,256bd317,afffd4d,8ccc57e7,f90b8e21) -,S(516267af,54f83d52,24a22b9a,4309e9eb,9b5c1072,31c3ff0d,418f8bd4,15836cb8,4187389b,9e062c17,f4ef6fd5,4b6b8439,cc37e85d,8a3db13d,86592098,7befe4fc) -,S(68bbeabd,8d3f4473,f91a0368,7383b4ff,6e7658dc,6e1287e7,f258f543,2466fed5,cf63c80f,ac99b42,7a67f7cc,d978d5b0,8656fc7a,6a383c27,48635ad,97049c4) -,S(20ce22ab,69467e9b,51d59213,8b52c1e4,49ba908f,909658a2,b90dbeb5,b07b67be,562da07d,9f4173f6,9232d17e,49ba2c17,31649ff1,4a9dcc3e,68f20dd2,de97ce2d) -,S(b5b7d6d3,a4a59f92,3afc1ec6,a5215786,9c86cd90,7ff80b07,d04160ac,6e798f78,d05e32c9,775125ee,dbc55af,4d1597b4,45b5eaba,5bbf6dbc,b8ef3e79,fe9d4de5) -,S(955bd489,7a4280b1,5de3d848,f75f6dba,3967e593,6b077d4a,cdc4c30a,33f45df4,4bbeb7cb,5d79991c,ef3b9fe5,bf25dc01,6448261b,44b156b2,749f9734,3d453a02) -,S(9f60e951,98e7370e,b3c02fe1,8bf53735,50fee849,9c876211,201e47f8,660a5a98,6395aaa9,33ed5866,a02570f5,9321d89b,c865a7ea,62e28a6a,3a62c4fa,4cd613cc) -,S(7081f0b6,f5923d0d,be4041c7,589a7100,9c2b6459,a255468,999f2d4e,50d776ee,9cb60005,e067019e,93aec9c9,1bf28b4a,27f3f0a3,288c4758,403a9ff7,668f9fc9) -,S(e290180,d8d5a7c,1b0e982a,bd63ef9a,b607d605,87e663ff,fb0ab73b,3369561f,462776fe,77289a4a,250ccc7b,80b54e51,993f741a,14299f78,61b88d17,d4d924f7) -,S(8aea7328,b285bd5e,b63d5939,c5c8c6b4,ac254cdf,c42cb521,2f4c5643,58598bfb,b682da77,4fc55ff,eb4a559a,8ca0580a,13819aee,990d9e22,8e0192f8,9568ec2) -,S(e9d108b2,54b24b57,ea4fc287,45865c09,27302d7a,1dfe90fe,b3a17906,2f256e68,fff7274,6d29d9fb,e7b0fc0b,1af14365,8d0ba69a,a45a72c4,8f67b939,aba128d0) -,S(9ea1f93d,1f317e61,786d4909,429e4cc8,b81f2914,17d28913,6d886b86,adba0fee,231dff25,d3b0b351,6e63ba6a,afdee115,975a5c00,b95936e4,5d9c6be4,6980ec0a) -,S(e8a12415,e5fabbee,7cd687c,43e8d530,80701d01,85980c5,7181b68d,481e7a0d,dd69839c,e263e746,99462f18,58745727,ac53bf2,2e0385dd,5d6a21b9,922f62c6) -,S(e287f3ba,ae486145,a1c2e04c,7f6d5c1a,ed796840,27636cef,b4446ff3,6c3def2,9395413d,401db0ea,4ec53bae,ff215580,5bcfbe8e,7e6bd6e0,be5b9fbf,9d968c63) -,S(8f99f79c,ec205ab0,e79756eb,a14c8e7d,fb23e232,6ab77927,641960dd,56ad1194,805953e6,15cc6d6e,2f61b0da,389b24bc,89cbff4f,c9f0ade8,c5dfff99,e819a2ea) -,S(9c87ab6a,8cb723ad,e0cdfb59,e5a1ff6d,3adb63d4,7af33e14,c6b3c343,c766f586,74798122,7a3bd79e,7d5012cb,bc81cff7,6a3699e3,75874200,4edc6e8a,a965bb19) -,S(c52c8608,6f245de4,baa10b7,fb512ff4,6042bd50,7d88bc3e,c75ec75d,d99dc00a,e8c2813a,bae8b8bd,9c8762d8,37d42fe7,85e5406c,5fb5cc2,ca05ae03,4ab3f844) -,S(b6286e1,94d5be25,9a79c6b6,ebd634ac,dd7c3fd,66ab0de,d8d4e160,ba8dafb2,72ec2ea8,ee0bf270,777cdf7b,47991524,27eaaf24,2a0334aa,18b3855a,899b5910) -,S(df7b56f2,45f2f8b,7213792e,370ca89a,45c648a0,5f3ba4ce,8c5d6d34,2f086b6d,386ced48,3850bdcf,4209fc90,d039b96d,39ac18cd,5d97ecb4,3df23ae6,1596ab4a) -,S(2acf4c9f,4cd42357,3e9110ed,a64aab59,459b2b37,675e420f,48ecd068,6d46a3b0,5f1a5829,aea5e981,cddff9bb,d2521ffa,58b37baf,9544c0cf,f622857d,5a2cc579) -,S(bfaf95aa,eb55d378,7210033d,b352372e,6a64f2ac,a420b877,586b684d,9cd33f36,7d22bb13,bb61e76e,2a2fce3e,bbf9ec83,78c6ed2e,5f143b0f,60803cda,b0a3d8ee) -,S(78cdd360,4eaba890,da793c9e,f589cca5,faacb6a9,14a29f6a,6add7d8d,74f31421,ed7e9c15,5b801d1,16b0d60e,fb5e2287,76430c8e,faff4bfd,327a38dc,ea19a634) -,S(f2ebcfa9,50a391f,c7b97713,566a8a49,edb8944c,7cb68276,d9843c22,8d213d2e,b1c7630d,956f9f13,c53a180c,569d534f,9513d16,4f3dd900,bb3f5e78,b0fa4eaa) -,S(43cd60d,83bfcbb3,cc19943,34552eae,857593aa,e8158adf,ca850b9d,1aaf4c2b,ff64bab1,f721e6b,9e23d659,224998cd,996230c,4fccd302,47e9e110,607e8f62) -,S(41925ce0,c01a49dd,7be0c3a3,b27f13b7,2168dfb,a5ec1315,f9209709,f38ea93c,5346b95e,cb6a0ac0,1a2f49c1,9b02d9a9,a725a676,f144ac26,c48f0d8b,94f77110) -,S(fd231210,6c762d82,a851bb47,8d0ee0d8,fa1c232,7e26feee,3e6ece5b,323877e5,39763316,f5a6ece8,baf748d6,234eedc1,4bf33462,1db3e66e,7eb2fab4,f96fa162) -,S(fe3e8a98,cb7abe1f,36a54a0a,a3d1c9f,d5ad684b,d05cb2,6ea683d8,f4556ef7,7d220677,34d80663,a1ff05f9,bad5a648,837b4475,abe0746c,3fa940e0,4f1223bf) -,S(e602a764,ae0d1bdc,4c3f9b1d,271717db,38232e94,84181ab6,9ba8eb73,4f5ec5dd,ad1038aa,26268b10,2c1f951,6b77b482,8bc9bef5,7b483450,d513e6f4,cc916fdb) -,S(871895cf,adb772d9,719cd962,5dd391b,3218142d,364764e,eb0bc6ff,8d81e086,49a09064,f7916421,9d51ef56,53861350,dda2c9ca,4e6269cb,555c8996,3f37722e) -,S(e229d56e,77755805,c814ec27,8fbcc56e,8ed4ec4f,4c14907f,4ab3a0e0,fa7e4b4,cdb07ebd,66d68055,bed7a46b,63ceaea8,6d42659a,ae6ebce5,795ab908,14e48af2) -,S(5535f85,6b0cc868,88ca3118,9d20d68f,471066af,a70addd6,ca4a9537,68bbf8ed,8655c844,245e2a67,8427822f,ac3206a1,f6f52953,4f7a6c29,6ab4825b,770ac5e8) -,S(10657905,4b37ce9a,e240d78e,3d1066c,b8c48d21,fb7130c,dd35ee5,24767ad6,52836b7a,508a6190,28eb013,c0355f70,4393a5af,e133abe2,e8b81dd4,83e125f5) -,S(3366b207,2521d023,99e9e311,e3447778,e796db0c,87428e4b,e6cb0ff3,a0868c1c,ec6022a4,22a8dd2c,a7f2f15d,39998394,ac908c64,74a34ae3,255a28d,4311638c) -,S(4a789396,339be46c,73608a1f,59fdb41e,91bd0164,66417332,f2630316,b5953ca,d45b657f,615aad45,809c0af8,4eb8618d,6e6e0346,ae1ba101,3a123ef9,e5b4c442) -,S(ee4f2484,fa0a9c7f,dc0c64ad,4df60628,d75d70b5,7ab9f0fc,ae9947e3,89f1302e,52b77894,d8ecdfae,df7dbd0d,8dab74a3,4092073f,47a543cb,f81ebf42,9f80170) -,S(4095b5c,163f226f,7937fbb8,3035f6a3,9aa9b760,c5086c0e,af9959fe,25f30a1f,1ce180ac,65554d4e,e9b14595,5c059f64,6a15d032,930465aa,d5547c58,5dff7ab) -,S(6a225d3b,67d9d42,412ecd9f,d018bfbb,7a36a59c,d2f53494,3d6cc62f,b0436a24,29b3d63d,9352e0cc,aa23c91e,e300592f,cc698abc,c73c48da,6a384f99,ea7c2701) -,S(23efaa41,e5f9bbbf,c6953a89,e3f4b9e2,17249254,94f2057c,f46d0c8d,71d36e93,cc89a7b1,7f2671a2,5bd7075,5c269219,88cea3a1,1315b86e,f218e493,7cdb789d) -,S(e30c1e97,f7f99957,58d591bd,6a398ae2,f972176b,f637c66a,258ad081,4f3ae55f,1a70cb6c,3e66e925,fc1edb4d,4d29bd89,3e8e4755,6825adf3,11e64b01,866509e1) -,S(be64d782,acd416d5,2b612f53,4601876b,f05aac91,13c8d265,b57ca32b,df08e278,7a41844a,43e837c9,293b81c8,73cb504f,bff8f15f,5a21e61f,9466acd5,87ad7e4a) -,S(caac02be,e009a61c,672b4c2,82fdf2f0,73ada0b8,d4a45450,76d24c38,f23822ac,7d93e4bb,a040f4e2,23acc304,75c455e5,72a9a64f,c66108ea,500ca62f,9216d06f) -,S(da2539b0,3a9cea94,9209321e,e1719b3,c1ef94c3,86d0e860,fc0ec1e7,684ccb3,e85e1387,bef1cea2,f67f601f,8067e9a4,b1b1306f,6a33df15,7795cbf0,ce3cf9f5) -,S(bf2ee552,5c965248,64bc1bd8,ad9cfba6,4ce4fe7b,be9b4198,700e936,799cc0ed,889dea1d,b1298a24,a11529bc,30339023,5df42398,e760304f,6343030f,6058f18e) -,S(b3e4b141,cb0c3662,9fe4c9ff,7a42c635,1130602a,720a6264,30b967c1,47abde36,f66f7118,c38a828d,8c4ff83e,5d6affeb,eff979bb,2e419f56,a7d7c8aa,52865657) -,S(451eb24f,fad7211a,11181826,5a223649,24a25593,63c33e01,4967ba58,889475a0,889ff940,49f6c3b7,9a5bd321,1c1f33e3,4cb2f8c5,bfb141a2,1fe5419e,44565bb6) -,S(29ab658a,6a754778,2127a0b0,c4b8af33,ea4c77bf,4bc0fc53,b5d65d07,38f5984c,aab1bda9,c77d6c3b,a619f9a,d72da6be,947b8baa,b80b16d2,15ee01a2,2bf0f2c1) -,S(9b59c407,d815c224,5bbb9c0,d1da59fa,9d9e79a,c654f8ac,2879b341,297b24db,a4ef058e,e6300114,c2827811,abacc0a9,17bb35b6,9b1b76c,c761ab8d,a676d190) -,S(87d27b65,82aeb975,8b9b970e,76c3ac77,78e69a7a,52ac620f,c0564e74,a66c9fd0,3ff3b3cc,dec29337,41c83e08,7f07f41c,4d03d5c,93268b1a,cd9098e1,37511e03) -,S(fbb3684d,38958163,bd85a0ab,36bcb93b,7fe7d383,b70d8bf4,d9bba6f6,989701dc,7b07cdc6,c9c5b3bd,10dc2af7,b2606d09,759e7342,68a5d4c0,301be264,87b94504) -,S(82022ae4,ccc42b9d,223cc1ad,c66e58a5,a3ef1494,f95274ea,cc7cf79f,4314a453,c2424250,9ddf2da1,6f0481a,9b4db450,3a81805e,9a8eaa3b,b5cd0e49,15d2b695) -,S(ba5cd45b,3b51cb37,bbe475fa,e91f8975,ab4e657c,57d0801a,1dbec958,be20f901,2e0d4fc0,f8b4f58e,3407eddd,298e5324,7f9eb718,b58e4164,78e3a01e,cf41b0a5) -,S(1293c841,b316d1be,76ab4444,53e72e22,cfadaf3a,df5b6d27,7cd065d8,8a6703fc,98f58f37,40fb4988,b844ab52,3420709c,2488f144,88049749,28670aad,5133c2fa) -,S(ec9fb3c8,54bf1bda,dbb972de,a8ae36c7,987d77e4,8d8437c2,c69aa988,df5015c6,d5f35bfd,ea59e974,961d6b36,4832560c,fe425d54,bfceccb2,a00411cc,a5486d3f) -,S(2ecce03f,4cd55b69,6cbd4466,2e7d58f6,9950eaec,6adaed62,7694dcb7,2544d244,e14f30a9,7f1cf747,ead403ca,e07cc4cc,d1bc793f,de79082f,f6615e6,43f68879) -,S(ed8faf7f,a63ee520,7825e7fa,56f6ef8a,4c6ad5af,ac507c3d,77c025cf,566fb3b2,df120b8,ab21273c,a5af1040,7fa3e54d,cb0636c4,8ebf88f2,c9b046d8,83684a9d) -,S(47cb8f7b,8780dabe,c1eb456a,f30fd917,bf3fd9f,3c28e3a5,bc078c5f,14c32e4f,f8607a02,1f16aa6c,68afc948,f21ee2de,c5889d19,8978e9af,66931bd2,b4aa3203) -,S(76365ac1,fdebab2f,3b9a3ee3,8afe70ea,d4962047,1e38e5ca,cf215a24,3d762009,2cacaf72,8b4bb600,ff37d3a6,97d45fa6,5d778334,dcddc32,11fc51b5,4e53aa28) -,S(c9dd5de0,99b8e552,e1375055,63edc83,9f09311e,11868ea8,a233309e,cc27b424,4bd4d238,4e615eb7,c68f134a,eafe7d2b,38163a8b,b117f9e4,b382236b,b8f8c1a5) -,S(22b6a7ad,cc406ebc,7c1c2f96,bdbcb6f8,9a1e08b7,822e2a31,83e5932d,ad0a8961,52b86095,bab24f4f,d2ebe9a9,534af2d6,87b553e2,77536d5e,22c1eddf,ae0ac794) -,S(3ee808a7,49fa7df0,c37017fe,cab7f6be,96f06c04,b2de4d24,a331a9b6,9f81a158,3e954cef,5f1f9ecd,887dc174,64cffe5,6c4b1356,d841ed0c,1e23c1c,2439cb4a) -,S(2938bc58,8a7a4896,de69ae4,4d5b6240,aa97d302,7043048f,3e49c222,b8fa4803,f26bbe61,9fad1d90,de74826c,ba6ea02a,9ea59a1c,59cb4818,65b054d0,39ada03e) -,S(682558ec,da97c9de,4cbea34f,5df43274,94962e5c,df72b0b1,2c3977d7,e1a15451,c4c2e765,22c7013f,19253c4c,c8ec6cc6,8b543f33,5aeb620f,112824af,b9fedc6c) -,S(720d8c68,fc520da5,79f6811d,e1f3d045,cbfad09,f7f7d8c,8ba68b4,6493620,b867e8a8,4f7a6d06,4d6fd4b,8bbb31a9,7ac26c3,b485fa29,50d545e2,644c9cb5) -,S(967fb3e7,1bdf658d,356153ec,6c0463a9,994d5d2f,b3aca9e0,2a17f5eb,f4b84831,b84a65f8,861724b3,2f5d0926,ec9a84d7,e3cddfc9,c7887a09,4cf602eb,547cc83f) -,S(1d9fd25c,77ecc3de,8e5fc113,1ef13b9a,73f6ebd4,f8673d88,db2a418e,8bcedc85,54a06301,d9720fb4,bfbff58e,23fa4233,33012c9,d62bf0e4,aa6adc4e,ae8035d7) -,S(80138158,a1137af3,114dff5f,f346e339,7d04029f,9050d44a,b4cea89,f1311c0a,16f49876,e6d6ac18,c25cc712,da3afe70,bc5e9489,7c55dc36,bdd234aa,6a5a6b31) -,S(aab4021,77fa5844,e3a0906b,3107df22,33aa3418,222a8c55,c6c37933,c3ef632f,9b83208f,3ad0dced,382d5876,7a089711,9a062039,9a7fbd2f,7034e5e0,3201b092) -,S(8f3fd14c,7670f464,d9ef1e3b,3014be60,3c523237,14bbcfe1,d3612f13,fa72f10,84cb7094,7901b81f,bbfa593a,5c8606e6,862ef6f5,d71c30a4,b546c08b,4205c68e) -,S(3ba9c91c,aba3c06f,eaf4578a,33979ec8,df69a903,30cb8d88,e49953ed,4a1f4933,7048a74c,3eb66231,e8410799,591bbef,fdcff65b,b492072f,582ee47b,7a6f99cc) -,S(2f8c37d2,89dab0e0,d5152468,29f6cb61,7344c21c,29860645,5f29a9ca,dcf36a7c,37f0b64e,9d02710e,bfaf145e,69c79965,4223d093,7a834201,d2f74d40,eb508396) -,S(45e6eba2,c9209d27,b87f6050,a656fca,73fc6128,cedbd2d3,ec40ca,76dce846,a3e28d44,ba1882bb,d1c91a63,5ee22582,81386757,4e66ad90,8a062c93,bf5f16ec) -,S(a5ecd3d3,80a0cd23,4467143f,fe842d9d,82ea7d9b,98ad23cc,605fb8b1,fd767ee9,22f12823,8ea84269,3fb31fe5,b5015cf2,c9ab6c33,d167b95,9bea6e29,4f11353f) -,S(f7f45a71,c4663b0d,44369821,318374e8,51eb66a9,ff6034a2,c943ff90,174be83,3a1633cd,4ec197f5,40d3d6e3,e6a3281d,7fbdf46c,f52fa149,8acc0a43,5b46fce5) -,S(92582286,6b314e17,5af03b7d,e5717d42,52bf6c82,a55ec832,a94b274b,487cb59c,fc8e9584,736809dc,65234670,495bbc7,d6c2f52c,ddfac4a0,369f0527,4a811f68) -,S(c15fe8d3,2303d00a,2f57fa96,6ae6fa75,1d7849f1,4dd527b5,a7f76cc1,e556da4,36242bd0,4685dff1,a67c445c,50cd348b,e017c06a,e2e9cd06,7b5fb109,81c10951) -,S(49ef826,152aa60e,310372df,270bf0d4,4dd7136,7d72be5c,a464f60c,c62b5355,7cad4ba2,dc4480b,9a1c572c,77a93e16,4e369d2e,b565e165,d9c7d2cb,20c4c645) -,S(c8de09e7,538ff94f,e12c876e,163133e3,629b2f1d,ed6686a3,be4ae122,9c91a18f,b5a7f31f,e58088a1,5f1e872,d6096562,9cecb10f,1a76fe88,5eab6247,697c2635) -,S(d86b9fa4,616f43af,1d7a6cd3,d9af24a9,6b3d5119,ef764576,9461ffeb,96abb344,2388ce8e,8f931b49,9481b660,669cb8e8,56df6f72,e392e539,fb570e19,f003bcab) -,S(a2cd7618,f351e2b1,3fa7b719,30fe3041,87c4969e,4f3ec55a,7433ae6f,cbbf88,3e0b5c62,436a363b,1455711a,b310c362,29870cd3,a096324a,a8dd36b8,5d19d685) -,S(b7283cd4,e33e4a3d,7836e4f6,b39b5576,ad6c213b,ed2fab87,ab442ccf,2100b2ca,918006fb,111c2307,1821e7e3,25eab3f,9083367,4248fc,2733173e,8eabc9ea) -,S(b1fd2d2e,9707ba8d,355b123b,9ca31365,d12e1854,6efccd9a,cda40f6,48b9a769,8c37cc16,8e8f55de,f604d222,62818bfe,1a40cf3d,62dae94b,58c9ef4b,475e674e) -,S(1b0997e7,4242e85e,cb4be32,885b5a6e,cf6077c7,395d262e,7c0d2b82,cb39f90f,55b4d8d4,27cd1d8a,ed8c2d2e,f3bcf8ce,f30fae12,4c14b183,fa36923b,6b7760b3) -,S(56ffbbbc,94ac925,dea36258,8ee1bbb3,4f1dc9b8,1bfd7e69,8e055065,d98d78d6,aa73208f,46d72bdb,20af3d23,5bf1c5ba,a517fcb7,b8036208,9f8a7198,d8edc65f) -,S(c125fab0,7ddb7f9c,3426cd36,812611e8,e3908191,67228685,3533e0d9,3ad7045e,2806703f,622f654a,f6c3f118,92c1dd8f,1f235ef4,4df464b6,8ccd30f1,9b77e5ae) -,S(e7ede9db,e4e0c742,8b1fa6fe,e81e80ae,dbab85fb,f259d301,48a51423,fe7f4a17,93ab277a,9fbc5cfa,c80d32e6,5e7f50d2,e236925b,c2dba1d9,e635a56c,d33fc066) -,S(74701763,f1bd6bcc,470c3da9,d853f967,a47c1628,c48b1cc8,aa395159,a3df93f3,ab2c011c,7c5510f3,37393dd5,f05547ba,bd22237b,28ed69d8,a4b6ed55,5d8ac8ee) -,S(8d27f97,55baf71f,e6dffb8d,83784e32,a65541c,5c656576,89c900d5,e79081b8,a7176e68,f3c89601,4ae1f837,bd52227f,f308f90c,b7f31386,e5586125,1ac250ad) -,S(63e06afe,9040b531,eac0a0ff,1ac25db8,71b0db01,8e9828c1,f5798ce,accc7ea9,aaa11884,a9dbe08b,6b28fcf9,9049aed5,c911244,b2a6a13e,9300c007,f4910aa5) -,S(dc7ea1ae,27d60ab3,42d617d0,23e4b1ab,6bf8bac2,882084b5,dde95894,744ed50f,93c7d76e,2b95c5ff,bbfe97fc,754a5a3,b63efba6,e111540e,48a0291c,142f3dfa) -,S(f3aeef6d,f69cef4a,3d7dfb69,1b5aea99,36e40239,bb976253,2213bd1b,f6e842d7,57d37dda,339c7002,f87bde03,1cb1e8ae,72e5628e,f493c115,1fbd0f46,2208de5d) -,S(825bd84c,316e64ea,dc5d081,23d7272e,ae87dafb,28f69b67,816a1aca,76bec3ce,61e3a7fd,ba8370a8,6a3e3f69,d62f87f0,849a2564,97658f1d,c28ca11b,40a52251) -,S(310a2cd7,4dec5370,9d2988cd,8e9426a1,edb63b9,50ec3ba7,f5aeeb93,3856a75d,5d6d86ae,dfa5e57f,7f2b4ab3,aaec250f,e3ff1eee,3e18c228,ffa3b81f,17122c97) -,S(3471d475,62a512d0,f82355ae,f9bb6c3f,69f04db8,977ee4d8,5af582c0,1b425217,272dde70,2fe0b69e,bf86d68c,5037b425,ccd444a9,45040358,aed399eb,db9cba31) -,S(bf6d2563,bfafaf24,20a2b3df,6829aec8,aaeee4eb,ea3538d,8086807e,4c257a2f,e8077a00,7e7b496b,64f847ef,755746b8,3a2738c4,4c1e7ff1,a920ee2b,40b496d) -,S(eb33cfc4,a883f718,52fce42a,3cd876e6,d6f4d465,327223fb,bdbed425,2b9cddc4,9bd400f2,ef608bd9,904f03ad,27de86fb,eaab9137,e25de8d2,a7dada4a,1ee5453f) -,S(1317e0d0,3e5df319,fb383edf,7de95645,6b123d3d,a0d8d08f,82091d6,ecc2279f,3bf6424d,5c6f9d56,b0d22b60,706a5471,dcae4297,eacbbb25,2a9d2292,33675afd) -,S(81b09f2e,99dc43eb,eb22cf5d,c5406f30,7e00f8e4,267bb456,c99bce34,309aeb56,9d4856a4,b300eeac,42f5b1df,92e331c9,1dbc5f6f,ebf17d7c,49580180,a3361932) -,S(deea567,a32ff19,722626ba,ef4ea337,ed436d32,d23df7e,98b86644,855a62f2,5c912697,c61a17fe,8557ab3,40c1792d,4a8310ef,69e785a6,dfe66d43,9d032414) -,S(ce4ad083,5746d173,e68e02ff,a7a91b9e,96ae44b1,cee86755,ef3dc4e8,e43444e5,be86cb89,5238d4c,b553e289,1545fe84,df7cc81a,ff1c2a20,d3406f62,7f03aa7d) -,S(9a993e3d,407f1af6,e4d19a32,48a0715f,2e36384c,7d8184f6,fbbce7ff,530b077e,e4a1a52d,80a267ee,99a7bd6f,e6d96ffa,3f87001d,c543f4e2,481eebc1,301a7a7e) -,S(1f10df2d,7c7f05c8,1717ae6a,1267aa63,9247c7ef,45aafccc,6b36112,fb9bd0d8,670b265b,71e2db79,32683b0e,c967e9af,e45ad643,27cc29af,fdc783b0,58760410) -,S(70ceb257,29c9208e,7db17633,dca775de,d57d1dff,9d914a5a,bad5711,86621b53,6e016e91,b3f3455f,cde11c0e,c6d1d75a,ee9825,7e9d64a,ce7c1ec3,49df0c62) -,S(ba46e5e6,4dc882fb,dfb7921,a106060,43fb6c4,ace9f2fd,46693f7e,74694e3e,eaeb4eb9,79381ff,8a208e06,9d8c436,5868d0b3,dea049cb,f342c88,7d789acc) -,S(bba3badf,d233ad20,e4179bea,f3d7579e,a631d154,e048f7a9,e320d388,3c30d81,f2a7c70d,69dd44c7,317a0af4,e765693e,2bdfce6,8c8a51e8,ed3f9003,5e1b961d) -,S(6df6a769,d300ba68,17e58f1b,f41e0af2,57d491f,38e59283,d93750a6,36d3f8a5,63a083b3,aa51c772,eced1f31,ccdfb4d9,ebf0f492,99f12819,dad9a36d,a73a4a6f) -,S(affd131a,4b8c9a98,294c7ea8,793a5173,4fab1953,1d2fe236,1ada5c14,a7174f2c,4c3de4d9,ec4a3698,3feed322,58a9788f,3426891c,b3205708,73429671,3411be6d) -,S(2da31049,9e54b18a,19dba546,4c7c708d,d42ccac6,bc2196ee,2f0a2453,3b0abc7e,f354ac91,20ad9f8b,56d09d44,51c4d052,426981a3,f7b47e7c,bb0549f,232db974) -,S(3882ec53,cbe3f82a,e8d381ac,edb4c31f,23cdd201,eec93f2b,2dc7d0cf,92e57b61,1d34315d,e5a7bfcc,492b0046,b2740646,71a43d53,2fb0bc78,6cd80ca2,ef7e6e3a) -,S(fcab8635,6a08ab26,39bc8e4e,8e9eb5e3,46825975,2a65cb28,d559bb48,7387f9f1,af4080c0,d08f07ce,57566753,ad3570ae,bef2b38d,4ef7f54,d7b2054,c8fceb94) -,S(fd34b8bb,8a897e12,a29dcd5a,57540caa,847bf011,a1548ebe,5dd89d75,9d36bb58,51a66aac,6a56f973,57927eaa,723106e4,d19b603b,d0d5a55b,76235197,7910b2f3) -,S(1e89bd20,c0d85bf0,76c7a167,87c7d817,1d3b4660,99dd82fa,808d98e5,87d4b469,4f53a9d0,e5768760,3dedae47,574f3123,dcf11590,fbc4d353,eafc8629,3cfe882a) -,S(8a1ea7ba,66909ace,c8d7d93e,aefbaba9,ddca459e,548c448f,5fb3a957,7baa05ed,d58059e9,64f37a4,39f7655b,25018031,ea1f1fcf,8ae94f99,e09c04cf,8b7be091) -,S(e0c3780d,80d59926,96886549,af2961b0,e4451f0c,b5572cb,d7ff76d6,1d1331a1,99d9d2e6,a13c3b1f,c2fe6f1e,5230e7b3,d827ddae,bbeda551,1144f68e,4945491d) -,S(964354e6,ed23ac12,16fed36c,5daade18,8e7e1bdc,ff20e60e,f7cc8c0e,83996035,f748a09a,8563c6e8,72253198,4e6f0622,7e6a408d,3c633529,aa8bd326,3428998a) -,S(9809e729,5125c862,fc6eab86,969861c7,8bd09415,585414a1,ab1dbc3c,1afe3f9b,d8536228,bbf55568,833909f8,6fc84a58,ab0fc089,432fc05e,fd46bf63,987b9fd7) -,S(195f4d02,305e4c42,28d83bf9,4025fc7d,1d8d7173,da14bb34,abbecc4c,f01ed17,957db8b4,97aeb9cd,68152e0,23cb4467,ce13845d,3a88e21a,726b8766,7c9d637f) -,S(562eaaba,3eb17e34,efa3f726,d02490ea,b0203fe6,81b836c0,f2c44a1a,854e0b37,b4e658ed,9e664804,2d3a35a7,70ef4253,97093ba4,d7b32da5,9db56a6f,8552b1e8) -,S(84a2c5eb,1efa9014,80c57969,3302f34f,de3a602c,a4b1a28,8d79f28e,dec8282,700d51c7,88cfeed8,587261db,adcac440,c703313f,5f0da023,bdf62b36,46207cf1) -,S(83d12fcf,dbd9168,b14e7340,6c6d4b84,b93e2bad,77d4c7fb,8ba00973,3672f913,e4856e26,bf2532cf,bafc78b3,682ce9cd,3c0dd6fd,861218ee,523b5131,e7279a7b) -,S(9988a6f2,bbd9320e,fbe73bf,9f4643f8,ce64d522,9ed4b701,dfb0068e,dd5451cf,bbb352fc,bd3b2650,d0a44e4d,892f89a4,d2f431c,2abe9910,ed5a1dd1,8a882d5b) -,S(3e92183d,cfa615c7,33721d1e,2a2116b1,83017d4c,2aa70b51,60f80a10,afff0724,c7888251,f4bcbe62,f0dfe545,3a73f3d2,76a2f30a,74e57d7f,22680b39,142dc945) -,S(d9175300,fa1efe3a,4cb130fa,fb36275d,e5f85b98,5ea5844d,e7763d6c,8239492f,59138c65,e9592a0c,d9a36220,d165abfc,fbad38d8,85eeb521,c5566702,9b678b4b) -,S(6ff5825f,7c12bee6,5d17f7b4,7766e677,ed74c5b8,7a95d068,b4741129,36d933dc,661ae9de,cb7974b,2304be0a,4d2b8d80,2ea9aca8,40cd0381,31f80248,378c0edf) -,S(ed6cbeb1,a8761064,3067d580,ac024f7b,9560366b,bae875ab,15ceb116,50b1c31d,9140687e,d1e889c1,6564d60f,702e8101,1269c476,f19d7f45,19a7d66a,8617dede) -,S(5f8ccceb,32d75aa3,1096b56e,eb132230,853bf6e,38643ca4,43abe04a,8bd69164,35f72a3d,d0c81dcd,4b6ac0fa,c4f5834a,4f6576f0,21cd2d45,6bde5b7e,7995da3a) -,S(81e02085,9bb23977,522896c6,7ed66751,86580d62,f015af7c,479a6e23,982d0b7b,8791fa9e,4159f26f,b42ddc08,85d562b2,fce84a38,e2af9960,1ebdbc64,cffbb669) -,S(de226b16,dd1e5c26,9b7aba7a,d63badc8,3eb435e8,7aca85f1,41d42712,95d8f721,62e1e399,fa2ce72c,3f87dc03,de33d913,3428416a,434dd20d,84156470,1ac8423a) -,S(60a46f42,3fcd3295,fd058be5,9f7ff164,fa762995,27cbd2b1,d13a0bdd,97d140f3,9571d2de,7b789e17,e46bc31e,1a03cab5,912cb854,ccbfec8e,f4d370e,df7f1219) -,S(6fef445c,e1b4bd91,fbd3a77a,ba0c6364,80d7e759,3f42a7f5,ce089fcb,c32249c0,115fbcfb,af46db83,9ae0cae2,e581796f,f82e73d8,7d4c9a91,9a92c5e9,f4fa347d) -,S(6d37f51c,a8d2f953,a3e5f7c2,6edebe57,a9892b5c,14482a30,9145c4fe,4293522f,78e511f3,6718ad4b,de6897c,d3b90e08,cbefae5b,a884bdda,a967eee,9d5309af) -,S(c0ac827,5bd0701f,5c9cb035,eddbe996,738aa155,fe74acea,a76b0351,3d46098,e7f32a2a,188fa708,6a968490,60ce26a4,31d76231,6a65a6b7,c3e83201,f8e3cd97) -,S(9000dba8,6f895023,1fc507df,85faf4a5,822a648d,4b256b93,5d012060,50cde108,9b7ae836,94b2e9e8,bbd8383c,2f4cb03c,32331902,2f58cff1,779d83cb,654ef3fd) -,S(f1109bf4,b490bc8f,36609253,26c2a2e1,ad58dea7,463e1d9a,28aae8d6,969098a1,87431a27,9fd72c10,80230514,1c8c17ec,6e3382c2,c325b022,4a800509,5d2f24c5) -,S(4de871e5,4e9cc6f0,8c4aac8b,36d61f83,929adc8d,4f6e18b0,d1dc855,6e8c0003,25d1fcf,ca98e8a6,c75d7fce,19de16bc,805f4b70,e9a3e9c7,f0187f07,70d3bba6) -,S(a23cb675,92972bbf,3a6e89ff,94e10010,8f47b467,fd8cdc80,b66013d8,62766ece,8dc70b84,ed05c23d,a1681126,77d23aaf,cbca18cd,fd7e9dc7,cae5aeb9,47cf548c) -,S(295d0cc,e96d8f8b,91ba9dd3,be703cc5,79d3c938,a5b7c32b,bb40e149,584244e5,a6d45a06,a16bd4bf,6af0fe37,6538ae5e,745e078c,12b3ac95,2653f7ee,2b03c926) -,S(7c683b91,9d5376a6,d40b13d5,1fbd1769,6cb40bcd,efd248af,9e102545,eebabbce,3da0c9d0,3608856f,5b7ed30b,8d9f1562,197d4e5a,7c23ae39,332b1ada,adfd3f73) -,S(30f7512e,d27e249a,95e0e21f,fe22ec23,8505f39e,ca9f41ec,df5e7ef8,1c0c3189,2f5fd85e,25ea3a3a,15928651,4b473197,9e4e7f7f,56e88164,fad41e42,e4875169) -,S(9377bf8c,96584f27,324a41c7,78d6314b,1c7f842f,b4910835,431f5a76,2f514961,d599cc55,e2eddb2a,e7d7fe92,aed830d0,3cfa892d,3a89cad4,335fd6d3,69f3df42) -,S(3589ffe8,67f20495,ba3530b8,5f83c54f,28a66e78,6bff4ca2,40ac1d55,6d31e9be,98822eaa,983089e1,209c22a8,9f133dc4,d75b3a67,8fdd385b,581a9274,6d224c89) -,S(39c1b1f4,b2dadc4c,e58e0f84,1fcc6415,2c79e77a,11d53f85,999db8b8,ea3f8935,e785271a,d9df3389,6436991d,eff9da83,50bb8a42,616cd31e,6289aa84,d4256721) -,S(dcf11459,d3d62c2d,99879918,8b6118e4,b103f9da,2453b72c,ad5eeded,8b25be33,dc038c1a,af3270e6,345a92fe,7c7dddc6,a190f6c8,fae7d7b3,30a3cc72,f3a1c074) -,S(614929dd,1de9b0c1,3f4d82e5,5bd8050c,a32ff05e,6eb238f0,eed635b3,6623d1d,afe8517,c9e7f17b,a1918e3b,e8180ff6,afafdc43,1acbea6a,e0eaa75e,c4d8a24b) -,S(f4a72228,cff6da94,a45da35,5ec8adbf,ef81609f,b59a8296,a7c1b0ba,9cce743c,545200fb,de095aae,9de90f1,569c6bf,2fbcd025,3cca1e50,a25a81a6,e19cdacb) -,S(63cc4273,6caa5597,46e62fbf,5371b943,57aa164c,fc8fda65,b5fe524,e2c93f7,1fa4ef5b,c5a6413a,d6ad2bd3,4b08289,e7d8224e,450f04fe,9b47c45,ace5665) -,S(ac175228,118438a6,d2cf761,f345cb04,aa7f9d89,9678c201,6b84be2b,8eab8889,dd7df8ae,29643dac,27ab01b6,8f7765f0,832f2989,99a13396,3435a982,aa4af2b1) -,S(9dbb5eb9,637c41b6,c4a5a2f,72efab5b,823e8622,f3786c03,dd678816,9e4a0e48,772d6ba,13f4d61f,42dcde34,b8519aa2,5aa0107,89c625cd,1ba38d4e,b7d924d7) -,S(717095dd,d2fcc135,1015b586,65a0d888,4e88f599,b8c32fb1,73d5731c,3ef7dddc,1de0f109,52b470bc,fb23da3f,3c7b640b,4727326d,d18e020e,581fdfb4,7e4fa5af) -,S(5ac230d3,f829b1ea,401e3964,c14d6e9d,a32c4a68,2ccdbb2a,3319a964,265872ca,fac3c3a6,27dbf66b,c5e06a16,e319ca43,423484d8,3217ae81,51bdcfae,c9c026ea) -,S(d27ecaaf,a39f415,e1457537,b2e74e1d,382496a1,51118100,8577cf76,1f8752ef,fc480b67,46cbaf31,e3d8eb6,4121b68,d5938e84,face3ae3,5dcdfa4b,71c6c037) -,S(e08777dd,f92d99b7,c4f87d53,9fada8c5,703af619,3a088d64,77f1e20b,f2ac6cda,25a4f88a,c6cb18b2,4e96ecc5,3ce10d5c,1202c4e7,edbdc070,db05a501,29ccfee9) -,S(45ae7ab7,afe9580f,bdaa6a13,8896ab97,63bbe3e6,88054776,753a1180,699ba6ed,dc1af7ed,127fe06e,4d0d440e,3d96f43e,502f797e,fefcff1,6c46e6a8,a156f322) -,S(fd28cb3b,71c50453,b3cf509a,768b4c2e,6ae26514,5801c045,327e1de4,f4d00590,b0684f95,4867cf44,aa5081f0,8174ce21,3298a22b,257f6159,c2666518,5ce5a7b6) -,S(f226f00d,ac6f49f0,a195e4e2,23b9fba7,95681660,7671dd7a,158b3260,1c1d850d,d05d5c4f,6925a38a,b4630e53,a1986fe9,d823a08a,3691550f,10f71b65,a109ef86) -,S(3cc61613,a80d8480,87ce23a7,2b3038f8,a994e1ec,8c9c740f,f0e44e90,760337a3,8474f96a,24093af6,94221f09,f95ab010,90377f1e,52a173f5,a11dbbda,cd3c3956) -,S(721ecd89,8cd99712,bd3be233,1f57d686,633e7ed5,c95e6223,e5cdace0,ce60e736,31d294d8,6fc07cae,4a09450b,fec633c6,21dc34a1,2f7668ad,532ac192,a0ffd69f) -,S(dcbaca58,1144d9b1,b2586271,5e58fa8c,d5b1062c,ffabaa2,db0fcffa,2b2eff38,9cf7621d,339f6cff,90efbdca,5e2c6174,708b53e6,1af38689,e6d3b257,21ec7d34) -,S(ed314e93,e649ec2b,ce491938,2c7a256e,b9300b99,528e7878,3421f337,15db8b92,70a81aaf,229fef2,e2922355,e1f15465,53ea0348,e3dfb18b,c837ddcb,60744a11) -,S(6bd19bcc,7a59bc8d,19a97768,95f65ae8,5f5c7eb6,429c09,85436b8c,29c036ee,51346de3,f4f65681,bdbea28f,843545c5,31803ce7,78b5732c,bc42735,4999090) -,S(99ed1e15,6ac8dfb3,604228bb,5be088bf,ebe9d640,7ad8be15,5777c6b1,d43d9acf,75b159a4,478b4cca,80ea0ac0,472436ad,69f57e9a,f447c61,e19910c3,9d2c922) -,S(3e166f8c,793addf0,84add90f,b0303970,f00c3c3,8c36171c,c7fe0877,b2452045,91659a63,b0cd2a65,ec330f6f,b9a6cc6d,9f07e382,7b94b8da,1921aa8,1d5bbd59) -,S(fc1baad9,a3a95f38,bf8d1b16,8409d09d,a1b1a432,841f656,cf8559cd,176df936,31f7a7bd,b013b89d,5045f248,982b5b4e,e0b4d791,21b6e638,84a563f1,a08af43d) -,S(80b3ad3d,4b371eca,c903c879,53386884,3bd31843,4e9c925a,5a5a819c,ff7ff340,fb1ca8bd,aac96d84,c67ed7d3,b65fac69,108ae28,7347abfd,f20e4cdb,712af178) -,S(bad065ab,2901f727,d76c6c36,48ef7aac,2a87d49,4d727422,73cc2e4,68616af2,ae9d7902,16b5eead,4d9d69a2,eaba2972,fa925a34,13f15d92,236329c7,470a37ed) -,S(d1f046d9,d700ca6,995beb99,cc8781e5,a2fb758f,7e81bca9,bce435f9,129b8fe7,274ede5d,7eb815af,34716718,84433143,3090fc0a,46575017,fca345a0,6111a4df) -,S(db535f55,e3dca80a,58dea798,d29aa0f6,99df1761,473a7ea1,751a047a,33f0a22f,e7d8015d,931a3bca,1193df83,7e7a8f10,e61b86d6,477a37cc,ed3528ad,5b53ff6b) -,S(da1dba06,a56ef0fa,f98b1a5d,b9a4f184,8635b7e5,164cdd50,82ae691c,ca42a80,86a8383c,a69531bc,ae806621,5cb4160,8807e265,b2179508,d928e312,a210c9ff) -,S(267c26b4,d980066c,7dd4f29f,f7b54277,3b176b77,9b3588ae,ff5ec28a,9aa42e7,3390c03f,f4e5eb25,5d230053,1d93daa9,d584658c,7fa30341,42ff20b5,827161d) -,S(8024af52,4e6ff955,70c7915,208491aa,5561fd29,fee5c27d,4f3483ff,c1cbea0a,c9de78d0,498f726b,8078fc0,609e76ff,df7a8a71,7345ca16,dff1d7cb,b2dd86b0) -,S(11ff6a68,c7beb420,7f0d7dd,371cf000,dc3dc195,406882d2,77953445,6208f661,b53ddc25,254781b5,1e7cac25,c1f7e3bb,916b75ba,97a7fdbd,658c1bc0,a7b4092c) -,S(562a1083,f9a68203,39a32d7a,65a9982a,b70d6596,b00751f6,aa88c27f,36e3c929,a380ec7f,908808b,950e7d25,510ad741,66ec2061,50923364,55744acb,b1e05b51) -,S(4efe70fd,327c0d69,3b6a7598,7ef64573,e097fa5,4cf077af,68d082e2,d341c413,10d47b9b,92e0b62d,d9a8befc,3ed1db10,b110a346,8cec98a,4a1abef2,c8ce3dc7) -,S(4d64bf0c,d7f128b0,bde8576c,91e01c27,354abd98,2cd3034f,f9ac09c0,23a51f20,159e741a,f57fdffa,de7bf38e,14dbc2e7,da3c524f,3d4c8d6e,b9dc32e5,e8a5e28f) -,S(9a41634a,ff3278d6,b3ef0064,ceecefa3,466de2ac,372ae43b,c48f30b3,a187bf,eefee0f,aebb77cf,8447a193,6564498a,f409e530,f4053c3c,ad27eaa0,6aeae2a) -,S(e1804fb,9a6bde08,8efec2d,2e5c6774,2c85cffc,e78254cf,4fc4ded2,9102418b,e9cab1eb,9c1664b9,c2fe81c9,b3a665ae,447e93c3,183cde7b,fa56ab34,7efcdda7) -,S(a603744,c0247b0a,f821705a,dff44d2c,717611f0,25f9fb41,1eb62f1b,64593212,820fd32b,706a7638,4335c0a2,f8713b9a,6dcdb015,a96b9d9c,e5c19bb8,ca603b61) -,S(a6f1d9b6,895b1298,34972a2f,ec96064d,a1108ab3,aae276cb,66a620a0,495f20b0,9a95dcd0,df038394,63ff5ea8,18679c3f,7f55d7ef,83a06880,29c9d543,6dc8273c) -,S(4ac51432,7822b63,e00f920a,b6e22142,f09f30f3,bd74c418,93baf126,cdac5c48,abf5d148,77e94a46,45fda161,f9455bbe,7ff037c7,720f6a6a,d7e4bc31,a0f43885) -,S(5a2cf55b,a16eeae5,8cec588e,1b339422,48af6e37,33604475,2dabbf7a,f7fb7a9b,8f27be2d,32ff72cd,4fc5aeca,5de55a21,a45f8c1f,7163dc4f,e0c00040,e69322e2) -,S(e16f23e8,ef48c1f6,4012b27,f6ffc4ea,a876053e,30cb388f,232b3d8,db011c99,195ffd52,b0afa5c0,da95bb97,7bda614e,47ffe3ea,13429799,e8c390f,b8c56000) -,S(65367cd7,ac109f71,50de4263,cdd86e92,28923a3a,ff96945a,c1bbd163,8524fb84,cf0b9ba,fbe67dd6,4d09b170,beb4fe8c,a7687c95,68086b6,8a7834a5,1747d731) -,S(10a8840b,39443b8d,7a44228b,d6dd6647,89da489c,8e954d54,a5cef366,6bd6eac2,7ff6f76e,e4aa58de,185163ac,ef7fad13,d8cc4055,c4e10a60,7987e034,c661eff2) -,S(3fefe8a6,c01b8202,6bb9d038,c577f16,7b1db5ea,91ae80e1,528b1327,5245d6a0,a96df5a9,37e6144a,454a0b54,39d68eff,a959757a,7c9fe350,ecd58c3a,3b637b5e) -,S(ef93d77c,e4162e9,6bffb908,f5d654d0,58595fd5,d6184c62,6c3ada21,c4052b61,40088b85,c18d97c7,f59a23a8,645d169d,e535261f,6cd7466b,953fbf40,f3cd0bf5) -,S(f1789f5e,b0fa903d,485edbd8,4971b7c4,9224a2cd,519bdd40,d627bd82,b0ca4872,4c845cb6,5456457e,a2f570f4,77b1f4a1,9e36a905,adaaa8d0,5830161f,a71a9da8) -,S(d0bb1788,ebc75ed0,20c0d15b,ad4e41f0,64193890,8a8704bf,ff3cc4d4,cc9b3274,3a120ca8,95a327f4,8e687796,30666649,43ac5524,44df62fd,8f7abbff,222a7641) -,S(164ac10c,f7807ae6,4d6aab31,72110d42,2f05e461,aeb9805a,3facdf7c,dce8963a,8dcf43d4,40f1dd90,bb1d6f85,849f98fc,9b6dca26,301f3209,3f9dc59b,ea549b69) -,S(f122d965,a8e40e3a,b857dcf8,92949f0c,cd3aca29,739a2e40,9876c782,941fbe5f,4d994b9d,d9e68983,78a192d0,bb670bec,71504372,d218e257,f50d0268,da447371) -,S(ac971547,75e5a92a,1aee2cdb,f5781f09,b975fc21,816e7829,662143a4,e48870a8,249fb603,795b1742,96767945,278dc97a,53fff7dc,f8bbfede,f8943c71,43c9aa71) -,S(959ec91e,dfd5fdcc,90d3da81,1e9c870e,fb0add6e,144b3fbd,d48c485d,2d330906,1e5ec128,b707c761,b61b5ebc,653585fe,29f48975,2a4724b9,aed90a22,6257ebdc) -,S(590795d8,ed7d8232,457b2d15,76de09f0,3c6abd8d,23b5e8b7,c59ba93e,1e982859,5edd2a86,1a3c8841,60e16490,a47ab42d,a09cb123,a9d803c0,6835292d,34576708) -,S(c5372b98,7439245b,eda17853,5cad1507,48fdb4b5,bf1ba555,89714dce,a3e0ba9e,f82d0b61,7159db8c,35536a5,46b69c4c,767afc43,8b64b5a0,22e899b1,60bca987) -,S(f3d959fc,ae39cbd3,ec8d2016,630f26c4,10161128,7dcbdee1,6534f96c,e35bd38a,e1e55c1f,87602783,2ffe2f97,fe460147,da586a03,ed0ad6ce,1603cf17,ac9b3562) -,S(922bc76e,be3ce378,2be3d960,489b064d,3a28043,f8a92cf8,dd5cec2e,537fad9e,b3199f57,2508efda,230b9ea7,51a95218,116fbf5b,d1032b54,352c0995,f5122109) -,S(45c7dd40,7a6d2c95,79ab1df0,8070acca,2c461d88,dbafca12,99a38734,d9f0360d,3a17855b,5f2469ed,6c3c4e04,4dd96f4a,d076eba6,a60e8e73,2644d25e,67e85ac4) -,S(6422d998,dfd4b00a,3dd89a5b,74411c14,f1af5c9e,1f090d5b,33ee2d26,b959bacb,e2358f34,491218a1,93d8cea2,276f5b3f,376f597c,703bba09,cdbf7d89,37a3bb7) -,S(8e048214,33196d15,1a4640f1,92bf6c1e,95b1a3cf,5365a6f,535cc82c,c4b0535c,d6d2d73a,1f652c55,9f282ee5,35f55aa0,20012195,8ba94e65,b638ef50,e97c34ce) -,S(5a2b3da8,b5eb2f0f,8a25a9e1,7124613e,b8a7080f,15d42c4,a1c0709f,e64a79bb,607c791d,eb54aafe,6dc95f8e,6ef9d8a5,a6435a82,6b824cd4,4227f188,bf86e6b7) -,S(143587a3,5cf614a6,750f3d91,220abf49,c5296e00,3cdde13e,1a0d2d5c,f6cd7ccf,49bc85fa,de6cc58b,49a1af49,46c340b,15f14c7c,2e83201b,6622f2df,86a653d7) -,S(f0080c42,8737c74c,c3b2c4bc,8c9d8505,ba357b7c,ff25f1a3,ac81be19,dca93193,bdd0119f,57bf674a,7d7cfe32,7027d1c,1c6a5ad9,2ca24f0b,5cf25c39,4a3951f1) -,S(877ae373,e547fef4,36cb26b6,85d7c426,3e162dae,ac0749ce,f7748d50,5d130034,1f0af495,b750341a,ed956b79,8f268ca3,e1275e15,32e5ca8e,6f9f6df0,d4dfcf5f) -,S(a418df6f,635ca18,8c96a071,469a272f,e55f0706,b73aca0,d1df2ab9,e8e619d4,2b06cdbb,5bbb24e0,fe499a6d,aa5b5918,2e755818,694b8856,525ffcd6,2f754e3) -,S(4c213d74,bb6fbad2,25edce4f,44c7b0b4,114dc209,4eb52967,1d907637,a2aedeab,741bef9f,ccc65c15,8752c7d5,48afa9cd,402fb5fb,206c5be0,e480df73,9f970b51) -,S(a37906fd,3f94e51b,1a94073a,4890011b,2cf93bc3,bb4cdbff,ecb7056,20deb13a,60a3b0b1,c14a9b1d,184d5e55,23314b70,8a8a16dd,894aa332,f01a2d67,30e6030a) -,S(2c677eed,639eaf51,64b8ae3d,26bb4652,d6d6528e,5b85225c,5e84ec4d,4de72301,df0e4c06,d3bb7cba,17f89240,cac07c24,5fe63931,3b2d278e,aca1b9ff,7ee832a) -,S(b551f814,eaf86be5,335fc3c,5b01c001,684473b0,cfac8939,5d61df4b,7d7e77b4,a979cb35,469715f8,3033f923,b4ae1e7f,8818b6e6,11a4cbb1,bd399ce3,646664b) -,S(98d5c718,5c8c04ea,f1f61ad7,40df0c71,2cd47ba8,74141984,fba82146,ddf45c39,aca52591,5c737ec2,eaf88f5,f1ecea89,9d4a8e2c,428f5bc5,b36d2ba4,a0050804) -,S(5148e2f7,260fb652,68c10485,4fbccc62,ed1e1386,ef8fbbc9,a0b23e2b,94cefc7c,65b4dd2d,35dea498,5ba4a8cc,b1a08dbb,9e9b2716,7ca96e1,29672452,a7ca2500) -,S(12c699c1,8c9d6410,b8a40ccc,bbeb4514,a08a227c,982df1da,f91e9131,8e0e753c,7d953c42,89b55724,3469a197,50516e88,4889e968,4ed28e1,20b022d8,932fcc99) -,S(4d0d3ff8,a7734011,b36ecac3,7ebb2312,134e4479,5039ac63,9dc69d48,120a8d20,edff17a0,e0984c60,3c4f1026,197f2173,960b3d29,f0b0ea57,3979605b,144ec64) -,S(ce90b70b,3e7b7a71,a91b0985,a668336f,ccb069d9,81a9fbe4,48125061,5536e42d,8cde9d56,12e0ead7,524640ca,2875606c,d3af73e6,457f1e67,2e63a478,5569000) -,S(28c79327,6bb1879d,99fbf985,1d2fa908,d197f5b1,c83be97e,360c4931,563b2d8,c8944e40,e2f3b546,5b6b10f6,ae1cfbe3,bc0f3e3e,33d91085,7c18496c,ec643868) -,S(6e2dad06,2413cf01,804c2b6b,55b707f3,864d4c80,87d30665,9a1fea53,e7442443,9da67c64,e05d6914,30a1fba7,39c0fe36,497bc028,43441f7d,c4c035df,129430e0) -,S(bef94ac8,3763946,c434d03d,fdf437f9,19f26188,923ee54f,8715b724,8c4d20fe,d2324534,e5fc1dc6,6fb83032,e95e1406,38648473,ce7e38aa,ee7ced54,31e25db) -,S(53548c57,f1b45c1d,ca166a24,c0f2653c,9b7d8664,3d45d125,918cedaf,818e433d,cc138946,f0c207f9,c01307e2,130b13a9,c36aec5c,3cad640d,b6a93804,f10c3b44) -,S(7fd4f784,7f25c901,4e8b0e09,b8b723ed,2aee71ab,fd47988f,90f6ff40,4b5867e,ffc3debc,901f12ad,96605805,a6e402db,58eec18d,375fa976,41b5d226,74a1bd9d) -,S(444a8a7e,499789b4,49c62424,cd9046ef,d4251bf6,9cb883cc,d3dc79fa,5397dd9d,4cc5f03b,3356b020,ae8c775,708d56c2,abbe8e41,bf393f82,8f7c45e4,dbb30282) -,S(ff05c877,84d8625d,20694bd0,a4201c7a,4af8c67,8e62abc1,acb0cea8,5726bd8b,7cf0e8ce,6ac26253,cfa5a0b5,cbe984ee,a55f6aa0,90bd12d9,6ec2de7,a996eeb3) -,S(80fdf7ae,6aa31b6b,ce894ea0,83fd9274,e29f4704,88f0a7c6,79b8339a,de7e4ab2,77d7317b,16962745,6344a8b4,bd4575c6,49e066bf,bde58fe,3f46e60a,3952fb75) -,S(ac38a4c8,10a307ca,d5020a74,f0d772d7,ef20227b,7eb49589,6854aead,41879214,f49c4cbb,3c675858,416f77ca,92e229ec,d75ecfab,3415d213,c7cd2cea,1f5016ac) -,S(b3736edd,f1e10262,fd562f40,8f502f19,3a90a435,de9ab6fe,a2691155,a5f75514,818cefaf,f190353c,f01cb068,2a15ae0c,eafa2de,657ee751,4e483057,ad5a78c8) -,S(66d67e12,d100c116,b57f6d5e,ac6a85ab,e698d4f5,cfb6722f,12738b33,310dc295,9cd4fa1f,3a0c9a54,d3608ea7,9bbd7ea,685faec6,32d7318f,d4e25fea,14a05dd3) -,S(b856d75f,756ae484,daaeb651,46ecdf0a,9fa10c6b,a7b9b33e,b8747135,3eb59043,5c8542b1,2f249649,4b3a177d,8df246f2,6566da1c,727284c4,b041a7db,89cb0a38) -,S(683bfd7,3202393,458142cd,661a6543,c736b15f,b8595548,afc52951,f9c47d27,90f52a40,f5dbdf26,51429f84,ac68cd96,420387a2,8d94d746,b4163411,762de166) -,S(2feaa1f0,811e1e65,13895934,533a0941,41ee1ca7,f8975896,3d00f8a9,1b2923c2,9dd80976,b884d401,5d7701c3,5e6ee1ef,690d1820,7d06e02b,7e3a10f,e8499c1a) -,S(ce652937,da9ebaf3,a9765e9b,144d20cd,847070aa,1a968097,80e07b58,2287cda4,c1c46ffb,5f152dbe,5a9db378,29e7ae84,454e1736,eb7a1b68,1b321f3,41ba572) -,S(9a695bd9,170163fb,ab3f9738,a750bdc7,556087b6,b04dc8a8,4fd5fe68,78976211,f40ba1f3,75accd85,9a42b133,294868d9,dce262d,64d6bc27,d0c9cf12,3eaeda70) -,S(e5baaf68,bd3083ec,bfabd6d0,9e4da4c3,5908b0a1,75578ec7,18cd3223,bd34ba44,ab8651f0,365cc3c1,50476d0e,da3e86a4,5feb7f46,a9afbdbc,e4defb99,ba27fb0) -,S(2c26cea2,b507fe77,d8f3530b,b7ee1fdb,dd0c4dc8,bf63d04c,e06376d8,ffe59cc7,b344e3af,54d03eb9,b0b67151,b5845297,c30a1cc2,aefc004a,5000b69c,e630d62e) -,S(7c67539f,52af2e61,88deadaf,a07e2f6,4d53339c,7fca7a3,c2a149f5,c8bbd0e4,3f9872fd,c21c9136,4ecc97e,c6642ec7,df7a2cbe,61b63038,96ee73e9,309067c9) -,S(4b5ddd2d,ec8b0bc9,3b6e1d17,e1da71c8,3345614f,74201aab,8f9adc1c,aa249574,cfada2dc,aa3eefdb,434d18b3,d2a85a6b,6e16e755,6e55fd69,5dfb36a8,aac5460b) -,S(d775c2f2,ccfc0835,86a66edb,873a84f8,f9bb6680,2eb0be59,216bc35b,88d80e4b,c8a5d9b7,988a2231,cf6aa0b5,19640a86,ff56ca57,91135ea7,65bb3a4c,fc53ddbb) -,S(71a3cf09,78810f9d,fb01d984,43dc3da4,b005b07b,36ad4dc,d3c803a9,bcd9bb4a,8aab8e21,7db0301b,9640c5b3,9617ad55,bd4a3c4d,8989df5a,1ad31040,bcaaa55) -,S(bc71a054,92b696e6,200596ae,3d778ef6,a82f7d05,825c0d3f,ddee8bb1,991f53b7,15789125,9785b8d8,b1374460,630a908,d1125536,e400fb52,b07aaf61,729a2a15) -,S(9d220919,ee62bfdc,fb81ec81,a0f60e58,e8d94a0b,c6b79f7e,6f891c64,fc847abc,8149379b,1a073c2b,8dffe886,59f4e94c,75f3a7c8,a7bfaa16,e530bc7e,6ed0c675) -,S(8369766a,d30bbd19,a330c6c9,1e3ad594,d25bff1b,4e3696e5,c6c8c33e,eff33425,a27f7682,b3f4575c,858970d9,c21f7daf,8ed5d28d,8617c8a4,e4b958b9,72e79e4a) -,S(4e277875,e4aeaab,1a8d36b5,487fb427,e91f51ad,1cd68ab4,57db2e8b,20542451,9faeff65,5bbc4b81,f96bf1d2,a152a546,d138fd0d,a8f8523e,7635020e,a26566e0) -,S(27f907b5,1b9dfff3,e68d202,72605a91,825046c1,b21336b1,8b91023,39a0d2fa,115225c3,6cb13600,fb84bf3d,dd5c49d8,105f459,ffc4068a,cbfd7b0c,52d4a15) -,S(6d9feb20,650674c4,437ff42d,41f70f16,ef0900a8,f3cd6818,64b42eed,56b1fab3,82cd97ec,d82b3c1c,2e55f857,653afa3b,5f7f7b00,39aa2444,f60574d2,fa02065) -,S(8981d2b4,3360669d,361c3b36,3284e729,ecb9cdbd,3bd17558,857f2cf7,8187bfac,1b9aeb27,d5a45d1d,8791bf73,614ecd5c,216b263,6c27645a,3e86d781,70d48498) -,S(84a67518,e47ad1fe,25540d55,77e92ce2,81691685,6d3c10ce,9c5985a7,72e1d72e,d3cb93af,85072ea2,e6c11777,dc4b73fc,16ca04e2,699ef356,dc8a5341,c5631658) -,S(d3e66756,72a6cf77,50c111e2,e65a6674,7e666cdd,b9dfb418,d50c28d1,aca8c683,7776ecaa,20e5c6c3,ab5aca5d,8233f83f,4e2e815b,dd1063f0,7359fae3,a6556dd9) -,S(ede97def,71d45688,804e76b5,ee52563e,522a7684,a68efc4a,f7b2db38,65b87bba,92e6d20f,c9c1276,60a279f9,5758a80e,85bafb8f,b77eb513,7587b692,fdae702f) -,S(3359e142,e000484e,cf7db3ae,2312e703,6ff84f84,247ac6ed,25a0b9c,eae8c871,67b039f2,3c845fa1,f38c98bf,739dbf28,d00ada09,36e4377f,87166f9d,d21cdf66) -,S(e0d0a972,c0502fd,2654a3dc,40914a55,96f675ae,cf0d958f,8fd62c7e,122b44a1,cbeb1bc,34575a7e,bbfd916e,dda11903,3ee29e2d,1b11e171,8db7bd47,576b0312) -,S(50b89367,5df77704,64031ac7,a1f5d5ed,4f332019,d8da2605,9397df84,21a4c987,c4765d81,63ec9eb,a089c3f2,56d6ff0c,45c38253,3d9ed204,cb04f335,d292f293) -,S(5dc62d8e,66775ff6,f21e84e9,9f8e8123,7f80cbbe,41ce9113,91ce432d,cd6d446a,4b456b7d,e27045a5,76e1cdab,d163fd5c,b020cabf,125f5de9,9ad6eb14,1773a9c2) -,S(8ba1778f,c7921845,d2632e18,790710c0,4e56ba7e,22efdb03,fdcd4f96,22c10971,1f31fcff,a8359658,b39d7d43,59707268,48ffebe8,8f418c53,f48c7af6,3e3e3854) -,S(a3a14614,7d1ea7bb,e6bad055,fbf9810a,999a102b,ba8b694b,e7ada06c,8db9fc7,c9827731,d4321284,23ccd6eb,3531ffcc,b3bdb87b,1a727d57,a697eac3,886ac294) -,S(9620a847,bd2034aa,c81671c4,436682c5,f6ce1af6,4d8df286,21ad1c2f,e0af78f5,e1cc6d08,a7e3dffe,cb47e32f,4156bcdd,6168a205,e8959f0d,99e1555,4d826e1c) -,S(a40d86a0,aa7d6a79,3f0b6a52,c48d8fff,95b2c57c,584996ee,bc9d98e2,796016b,ec54d4e2,d453466d,ad94c15c,b25617d8,62911b4,45f44873,96ecd950,a351ea2) -,S(71ef35a6,f60f268a,57573b97,9745986f,7e5f40e9,ba64efbd,5ed90779,b3484c80,eabffa1e,9ff3590a,c577df7f,6f5a6ad7,2f3693c,be475669,8751637b,4f8a1ba3) -,S(bbd1a408,c742a3b2,e49ffa52,c5f70958,5308abbe,f103e674,86fc76d7,a4f68de2,4941cbec,9d07e13e,1b0fbe96,c7328459,ee6e1e08,50a079a,2ac0b61b,5d246124) -,S(169ebf38,92116df5,3e09c92f,f2c89b5f,805d60ff,9584d2ab,433f1f9e,84ba9009,914f5516,e7667ee1,581b5ade,bf1de48e,c997d149,1e932a08,34503599,7c6228d) -,S(8f157abc,4c5ec7fb,eac11545,890d8e45,d71c8d9e,4c4e0c3,9777502c,f8666acc,d41576ba,1e78a9fb,9899883e,602bca3e,14dc709,8982e1bc,63518138,3ff25908) -,S(8cd338d5,694b26dc,4ebcd8,39a006da,84f71f93,94fb8100,91ed8cb5,b4ec9a8d,40318c10,dd88d9b9,c080eccf,45464ab3,3fd9d34,c2027d95,2a6ecd21,d0002578) -,S(20e47e2f,7ba5ba2a,d36171a,f4ad760f,a64748c2,94892e28,cbf0ee3e,293272f2,b96ad220,56b89821,5c052089,789e4267,162ddaf8,76c720a7,71b15254,67be00bd) -,S(582ed8a5,a0d38f9c,db6942d1,1f411dee,f9c31ec6,ffbf1579,3f3cb5e6,5f2bb880,14928c0e,4f9d9d3d,ec4a8db5,64baf4be,948ea892,34a6e352,a4cf4796,3ce8486) -,S(f4a6f59a,6e76c11d,3f7daf30,b8c046eb,b0bcab8b,6d1f5e7b,877eb1b4,601896d6,2d39c6e9,e5d84156,559a05d4,a9b148e5,ccde4641,e4bd9abe,edc8a648,b070f0c5) -,S(2a820c60,f71cf5c,76e66bf0,15623f06,fc8564b8,c763a52d,2c329af7,30957b24,b38c0703,d7429599,e6c9a1d7,250078d2,36f77f7d,b9956d37,fd92646,77ff3ca2) -,S(8c2d9c4e,9fccbf64,871d4802,6077a3a9,33634d3b,c1d7f872,6231848a,6e2799e,ad50136c,ae43bb6d,8c49c534,e80985a7,cf032d77,604c2db8,d5954858,a9351a7d) -,S(b18e9053,744b3ed,d0b991e,23927593,db00d25f,adfc4490,6eb0d19b,74061ba9,90f5ca44,c829b2c6,771edd73,998034d3,43a8aab8,442302a7,2ffea92,b33877b6) -,S(cf1d157,b03d435b,905d2f58,cc53bfa1,d124827c,f4ac4109,33078dcd,1ce835be,ee37a9a1,5547c7d6,a0f03cf2,1451cd64,3ea656df,61eeb1ab,1196d959,ca71b459) -,S(8d8b9d8a,d91a840f,b2e1ac36,a6f4bce5,92fc13d1,f22f84c1,562d63f7,e54a6007,9528be43,93ca8f2d,dae0ec3b,439abded,ee9227e1,47ce6ee1,ce61b46b,b842dba) -,S(604b5544,bbc5b0d5,716c936f,b0d9a4cb,7ae04a8e,1d5a506f,2561b463,fc87fc9d,33fe2f9c,4fb9a6e7,41c1e5fe,7d3d9edb,ee3cde6f,106a1d8a,3e319254,a16ac8eb) -,S(3e7ed414,1058ee44,6057aab7,49e14ca2,cbd16d64,7959fe53,9ec0916,fbaed8f6,fc15b241,86dec6e0,c91aa697,10a015d1,f66bd361,82f18648,1ba24568,952e79fc) -,S(d0ae7435,86c17b8a,c9524243,16cf42c1,26e46f69,4c69cf26,736d0527,7943f326,bfa02de8,b983588a,d4398865,abf6b69c,fbaca03e,8bb5f04b,1971ce1b,f74e0757) -,S(ef5c05ce,d4f343e3,7e6ce2f9,45380ade,3627bc65,9de0597f,5f851eb9,88be1441,d9267c1b,379f19e,3bd0e40b,74ae8e21,b681e7c2,ad49f635,d60c619,74103281) -,S(176b8feb,d7998ad9,7c73015c,3b09d9af,d7cf4265,c7bf38ca,8dc64864,5c8f49ae,b4bcbe4c,8267c9a3,69cda190,5676c781,7f989f5e,a014f4c5,fc821bf3,8522f1b4) -,S(88f683db,cffc14e,ebb58d69,fb6da62f,b20771dd,3542fa00,97b3a766,bd16c3dd,bbef3de,812103c5,266797ca,252b74e,cf80096,b2972219,f52ff718,1d1cb601) -,S(a65d438f,1247ec44,fd8c4121,c3d67891,8488b082,31fb8854,dd1fe238,f637abaa,5f65c84e,551e433f,dfdcf3c0,b4c771af,4bb50095,dd0fc986,d4d4a82f,9a3f36a3) -,S(bd6a7e51,c5028bb7,f7e08148,af1597c6,d5cddab9,2883d2f,f6a5a6a0,6398cc27,3f2280c4,247cdd22,e8b97979,b9a98e93,c1ed14d,a76eef66,2ddb70f6,7859d885) -,S(a672436c,2896a0dc,54b1814e,c5101451,58f7a3ac,74d36202,34411a09,909d274b,dee80293,468178d9,5baacea6,badade56,c81f3d9d,95642654,a7afcece,bfc2ec3f) -,S(ca0f55fe,d3a1d0cf,1adb0993,d7d2daa6,57891ba9,321104bc,8d9e0379,f03a24b0,dc01b8e4,63462dcd,91588baa,ebca8d8f,52016683,9671399d,b5843e6f,5a3cfa6f) -,S(610ff08d,9bff021e,544961c,cb2fe206,211843a7,ea0c74cc,b91f0b5c,4b6429a1,4be3b18a,ee965fa7,dabdaee6,8fcd3e12,d889bc36,35f160dd,9b0760be,d1d46b28) -,S(2d6f8215,a70aeccb,78cf006c,ddf8f0a2,6b695dc9,622dd622,38fcc638,a9ff42ae,3fc0964,e2a3c969,e61e4e5b,ed50f337,7a988715,246c50fd,3ff45487,95a3927b) -,S(8c0e99b4,868e39c5,b610b132,de1a09ae,99846826,a42fc4ea,70b0c630,88a1bbbb,32b8ca42,f0a240cb,2876a41d,e61b8c17,6ead992e,8785a95,c384c536,141cfe52) -,S(1528ba8f,9000ae75,e3062af7,74ef6d77,658c6d1d,65af87e4,dbac9eb0,8fc96ed7,a8dd278d,54df6bcd,1d4e6466,5753a8bd,2d39f0d5,c731a53a,5faeca64,513b5651) -,S(c1466ea5,d9256a7a,f13a040e,29515858,104394bf,ac5af7d2,fa09ef7a,6ff1d7a4,cab6fec6,fb36d879,f0684b54,6003df0,d8bab3b6,e1050a7b,c05457b2,75be5128) -,S(ce8bb093,e051089d,2a297a87,cf90c3f2,2ea946ba,87a76b56,c6f11812,d3e98cb4,a8dbba51,b90684fe,6dff556f,bd13baac,679cbcad,90b0e888,4c252e95,e03a0470) -,S(76f3a73,7c9d9e15,8d30ddd9,b092a94e,7c426763,a17a96ea,9186582e,6d6c86d,5b1ca07c,4f345e6c,778ad27e,c6ce3f05,b29c5302,7e40443,b202a022,e5d16c8a) -,S(f757dfc3,23390b21,3bb98872,5dd7d43b,2ed997fe,af7681ad,ee1572d5,a74017f,d0b4e4ea,67879726,700b63d9,88eb3957,74ec4f67,ca1a56be,461d244b,a5b83cf8) -,S(59bf6198,a2deaefd,f080ec6d,3dbe3c67,f27a5769,d91c65c,1492a87b,9ed5f5d0,bf5eb739,9011a282,3110834c,4d467855,6e02f2ed,601529b3,a2f3d70f,8410f8b2) -,S(b1d02f0a,c86d8757,48685790,918c15a,a7b0e85c,f12cc52d,53f8082e,549ba16,7925e03,99926b76,8a80878d,63f3852b,97297725,96d3d06b,85437fc2,571a19d0) -,S(cd27372f,41d8e07d,1bd2ec1,27c41842,7e5267ef,14f3a908,882e4e40,381d1905,cce36e03,661b9f33,ccf810f3,b411693a,c3329617,52098352,2acaf0c9,5dc77297) -,S(112644fc,26ca3599,3b68940f,5cbaab4f,ad2258cf,bbc81695,b01db49b,dd9d3ace,8685f790,7b5ab95f,2f7a49b3,bedf09d3,7ff1362b,3be9db90,4e74d049,15c0bf60) -,S(918df72a,99ce4a16,20e84575,935a24d9,92fb51ea,eb8498bb,3a606e2c,d97d3ce,88b339ec,9ebbff98,f1b8b0d3,c90794cd,bb6b7918,2749b065,602ccfeb,bb8a8461) -,S(9b8f18f2,65c4ffc8,9425b51,d48a770,436e6424,f34a1af2,a7dacfab,fcdcb83b,bfb95e8,6a34c1b9,2c2e8c78,fc628139,476c4af9,3f63d247,5e454a9a,d585ba55) -,S(ad02f2a,c396626a,42abe52a,1ea1d8e4,3821740a,d8b3340c,9b9c78ff,bc24ce30,fcc738e6,cf8a7872,ff827cfe,1b7bb7a7,ad8c97e5,e254db13,255c2d07,1a2885fb) -,S(359afbd,5e60dac9,8ee34f3,f5acf126,9b5c1928,8f54476c,84bfb9ad,da6d85a3,2e2aa1e7,9cd3fed6,71272155,3932ce17,44358636,a18230f6,b501579f,b3088955) -,S(5639aa3e,230f2f1c,e10c34a3,1cd6c78f,c3c15c0,2061f3ca,55e09116,68b279de,e0b6e95c,15de7f0b,3fa3bc26,3a9e83e2,e3a7d51b,462709c,8ed6c2ec,b511bef1) -,S(309cffcc,7b2f959d,85cef3d0,c25efc2b,693d3b6c,ad42ce4a,d8657652,d669ec44,3abb62f,d917b1be,79809520,5521d522,32f949a6,7999274b,cf7965b7,a950077d) -,S(51f3d5d2,dac1d7c0,5d8eab6,375c9130,534a026a,48abf3ca,ce91af6e,533b86b2,50b1e7f,4bdc48ed,9f3fbfe0,ca05bdda,34f9cf2a,ad04235a,ba998a8f,a3e99f74) -,S(8f563d18,33aa4100,4540e0c6,f501d327,4158b0f4,8b3e4e1f,a3fe25ee,29c2a244,4d4c71d8,5ea93371,57f5248d,a012898f,3d031d93,c1803589,2875928,67432193) -,S(36ca2909,d68fdab9,cbc45b39,fb096ac0,3c4853c0,ee19d108,ee7c72c8,a77177a9,64f511df,c8252960,85f3d095,31467a5e,69cbf363,30e12ed6,90516208,d24301b0) -,S(f628b8d5,1f3ffd7c,c201ca9c,2db26f0f,58dd918e,b4d70cf3,80734702,8ea306e0,bd6bce3,ea82e9b,2e8d6eb2,7f557def,b7c2d77d,e6329c1e,a2d360bb,d8adc2e8) -,S(fb7a6bf5,a82c0b,b2a6922c,9d0350d4,b44fa7d7,61002f25,86e41152,c0e67c1b,c12a1c37,f1c9c703,1f1406,efe8f3e9,8419fc33,23a1acfb,345ebc9,4a702da1) -,S(c2091919,5c3e2af2,df14080f,400c8c75,bf8ec01d,a5a5b033,75391fbc,fe78d092,b307b56f,cbebdab3,ef87b1fa,3b66c327,7aec3818,e880de6c,3826b632,f1adeb9) -,S(7627df89,3d1727fa,a06d7c4c,93774a48,73c3bef8,d19bc03e,8d1bfe28,bd3192d1,35d2676c,36f455f7,aa29a865,f0776c52,1326dacf,f6d366f4,bcf726b1,b68451e1) -,S(26666518,7c9f33a9,6d25df65,8dbfe035,a3df6f73,cb059639,ed54b296,2c62b9,bb30bbc7,d34a5e26,a51fe757,8356a876,c4e7fcae,f4a977ba,468025a4,c686630d) -,S(3bda9185,fa9802e7,7dc6a02e,8f2a6f71,ef8b125f,735837bb,c7abf3a4,c62ac683,202edf2b,c11d1784,d7875a76,a0ae3876,22b3475c,bb0ca118,9362e54c,a05b85) -,S(2f90bcde,4486b64d,81313c71,48570d22,3be1978b,7f524097,bc033d6b,983a5c4d,63864e50,2028d475,365b2e30,cca99dd,f4aa759e,cf579705,270fda71,bc384f89) -,S(8893f5d4,e9b00e6f,dc992e65,4c9fcd71,7083edc2,6c71dcb6,562bcfbc,c8becda7,1faf3055,8e631074,fbf566a1,fe0c6996,a80fa29d,6cdb8313,fe313b4,b238ab50) -,S(acfc4ae6,86be5de3,eda4fac5,4da73510,f482fc25,309ce37d,855c3495,8555abba,387f4597,d1878a6a,d37a5b99,8ec291fd,76423f7c,f9bd037c,b9071685,2ac52d87) -,S(2ac4d090,a4c5e988,2f3a892d,d28a5229,d5fe35e7,d74660d9,5422a55e,2017a469,6058f516,2aa3ec45,47a79f2d,7d8e6869,927d172b,f75a1914,a3bc2571,df086c09) -,S(137ed3f,fc13c572,e5bc235c,d13c7e62,c9b1a3ec,250c024e,9c9f584e,7ebadef6,c1e95cc,3a464f51,b43ff02,3c8758f1,319e7c2,f37acbf5,4fb8536a,8ec6fdba) -,S(28a037a,72148a3d,2c89f606,81152b94,6cfb16f7,58f0a002,cfe4d857,ef3ecfe4,b2f4b650,135cde9b,8d3788cf,5c6e7a3a,ec595124,fa903aa8,a1bb3984,fb973d10) -,S(303ecd51,8fd433fb,ce9d426e,8761a76f,78ad6d5b,5f34c0ae,3bbaddcf,1a7a9eeb,6a7fca44,3b73b19e,967a5945,a275cb1a,cbd8dc3e,89d85385,ea956339,99abb602) -,S(cf63042e,5680f71c,2641defd,9d6569ba,c69cf079,f8b3140a,50923381,51533202,39f3376d,fb17fdc5,719a2052,5e1aa428,176643a,f50dc9b6,b8ff3401,eceb4ee8) -,S(cfafbbef,b4a49fb6,96923b6f,2e56c493,34a229a8,e2dd968c,44f485aa,1b1fe4b7,dc0ed34d,4a9c17e1,ddfafbc7,1d76f71,f3950698,18faa16,b5d25c6,c69f9007) -,S(ec0e3de1,fd527ea,6a493ff7,b3c6aa40,4a7ffd76,9a08953d,785d2f31,390d363e,94bddbce,300234c1,82f3c6a,717f53cd,723129c0,ff353528,fc5c285f,8e7a35dd) -,S(f07d3cd1,914422cf,d4b9c0c3,501916bd,13e9cd84,eeb02f7f,84be2a40,4b2bcde0,cf0c96fa,cb393218,37c48de5,16d1f705,dfe91206,8ae2d810,3aa1f77b,39637320) -,S(4a4254b6,6f2e204e,a3264ac0,a00c7a63,8a6fab7d,e67643e2,8217099f,3648db10,b5510e29,be93fc35,efbef989,15f7df95,b187ab08,bacb157a,c26ab2bc,2ee5023a) -,S(56f3bcf,b38eaf1d,35e62582,9f671945,910285b0,3805c1d9,b5d813e8,e87774a8,a9b964e7,9e6b7f9a,9abf3e5c,a147f773,8a1e8270,8677e6ba,c57a7a75,d1ed9dc6) -,S(f89d8f4e,7d32efc,c2d95bf,feaa4c9d,af6b9886,51fe7561,ace561be,6b081295,ca632f11,56a33867,63a65691,17186994,75e48f51,48d770d1,449ec719,8dbacc69) -,S(5c3791a0,d3e716eb,50ae4a07,51f0e92b,2890b933,c6d9aaf9,758e5205,27c5530b,44ef13c6,2de52d11,179e30da,e913493a,c4ed861c,336ae1c3,ca1f8bab,a7b34616) -,S(2748765a,e6baa4ae,62cd7156,16ceeadb,8ab94ef0,d3a3e331,15fa0132,aba38d27,71d4d19d,de63770d,60905bbe,6c7ae92a,f36b333,a93b3359,cd4f1f2,77f69e48) -,S(964f1fa2,f8ecd778,2ce4ee1,87ee3e78,d2c41a0,45a95453,22e363be,bb27e254,c744bbca,de64a883,e9481a5f,a2cce621,5137ae00,3b9822e6,77556610,d4138a2e) -,S(8bf60775,8709c9fa,8503594f,e6c379ff,ee758a07,4f7d2754,58985e25,79b8ca3b,3e638992,b3fbdd72,ff51cfb8,fb118d0e,ccc193ee,718a7715,a5ae6188,87dd51a4) -,S(fa107123,9189239c,2bfc5a95,ddbee798,fbff70d8,ee0d5f5,a10238dd,2e06612,a60cd5e,1a4eb0a5,99133ea9,71d5ec1e,315a6be1,2d773936,c624c468,f968e7f1) -,S(5b48c6d0,9f6f97fe,c03d145e,f797cb8b,3fe2503c,a8944593,83c34e51,44975588,44d86689,352611bc,c1291762,d965f136,173d6c45,28077d83,c6410a3a,906e30a0) -,S(80e153e8,23aa7e3f,2865d1ea,1e5e88c8,5d4e854d,54bca5b1,ae8f1bca,eeb94fd0,edd3fe29,e435c11b,13a92d8,ef4f6413,c888a12c,71823f7,3ed7acba,a06b9728) -,S(16e225d9,77bf7526,c2590dd1,54c6e29b,cd25de9f,7b1fe3d,ae7ed6d0,79ccf2c4,e0702d23,b9b57554,6d2db82a,fcdc22b7,40088c52,e0fa274d,d85188ac,9710768) -,S(a3440a09,15a16c74,8221b65e,7825ebcb,bb064aa2,de3593ce,7a691efc,d9456938,ff7c7aa0,3a582a8f,5641323a,7f437a67,26fa5d3d,e7c3e26b,be970904,d4dbf40c) -,S(8154334c,d1164468,2320401,f2d59385,8d607203,93eb37c8,a030e9e,cdaa2b5f,bba4094e,5f97e4e7,b0f0676f,4a091488,17126ad8,7d573d54,150139c6,5b3d5142) -,S(c91348ca,27b5baca,3a092b25,74e09976,fe7f2361,3e1b5efa,329e6a5b,7d4d93c7,ce241d0d,e9d49a2c,5060e62d,c01bfb59,e7c37295,4095f639,9d61e73c,5976b44a) -,S(9408b5a8,79fead4c,67635e99,59ca9649,cf362940,737e6436,3ba2590d,7e6e8a88,e10b410a,26c710c1,bf2858d5,21f46094,e02155d2,84b80fdf,cbf17645,7f994fc0) -,S(b851d158,eefe48b8,79e0a159,f8582aae,f80ddf90,d9021b92,e7d3e7e5,d6bdd2ce,290ae2e1,792421,c1cc53f0,69c7d580,60facfd8,e537693f,6abdaa2,c6d85469) -,S(9d320b4d,4a7c2007,65805387,5e536093,87e7a5b8,54da05eb,1b971e6a,e53d10fc,4f6acb7b,6a1f190d,6822acd0,ae783b0c,9b44be61,ca68306e,79603f47,25d7c456) -,S(6d779810,7b29ec65,4ff86799,d13a4d89,eaa49114,d00744c2,2f30a9e8,358ac7b5,8f7993cc,105c4f09,ba060a2a,ce265cc5,77b2a334,3ba3880,4b0a3e79,db823950) -,S(bdb2d2ce,77e14fb6,9a17d62d,b8056d28,680c9607,2c82772d,73c91da9,e57f6489,9c1ef71,d43c3b19,dcf8eced,ea6f5648,8a3bc00,3c2b0c1,84c9e42e,5baa590d) -,S(49a8ccff,1ab70a94,a4db4787,f73bb058,1f7897a8,d0a1adea,741ffda3,f055b3fa,f298d277,2049ebd1,ee2414ed,6e053ad5,15b41914,fd6de43d,8bd9282a,6c6ba426) -,S(ca3f7d6e,b466b7b0,56267992,d317a02d,3b3d5652,b51040d7,7f1a173a,769d2236,a26d6225,9dcf384e,f78e6f2b,f96a42c0,90e538ad,f6f1a1b7,126dbb12,8e145c37) -,S(b672ce14,f1c427d1,b478469c,b0d08b99,902e9cad,a66bc65b,c00ea630,737176e4,176c0979,15176,27a0f1af,f3c5a56c,83f4f550,b8c4bedd,b818bf76,68865efa) -,S(bdcbab57,d4ad621b,d6db6866,f43778aa,2c26dd78,8f2e968b,da3c913a,ee9c199b,79868872,9bb213fd,7dc75a33,8d6168da,1cee9f0e,e93c7c11,24055232,88df5603) -,S(f5f25f1e,382f7df5,74c64aa9,6c5f423e,d5beed0,82d80196,1cb384b2,55fbf9f5,ea388f0b,5ad84aae,58393a82,9a50a4d0,f54bc068,e12724c,98a9dffa,f2210221) -,S(d2a10464,f9f8ab9e,1ca6e280,b2747c43,60372049,85a2650a,a730b894,16ae09c3,d19719ed,8dc46533,28d8dca,f2c902eb,2c9ffaeb,ab3c1b45,4fdcf68b,229c5962) -,S(89255afe,e6724c4b,c5522105,8e5e6aa5,19058c3f,f3ff691c,c5f81a00,20410038,8d626dd,9560c934,11b52ffb,4fbab500,c833c3b4,671713e6,9147d8af,da3fd7bd) -,S(5e468c42,c5eceeee,2a67d73f,57819019,5165e3f2,6c93f94,beb12fbd,556e3952,af83e24a,467f97e2,ab8b6a8c,330e400f,ce1fdeb4,3a4ae1ed,c3866505,8cf240de) -,S(70c2bfac,9eca198b,f606850e,8f54ab03,552caf8e,9385036d,7fc85007,e99c4e2c,60322365,f5ffae57,8a8f9939,20cf7596,3b45d940,d2c4591,544feb6c,d6ea37b3) -,S(16143d3a,fe5f6b42,500f86d,7c79630f,bbb0db1a,64e901ee,ab641c0c,b9c2f318,7078e814,bdf81d7,81109561,d4d1cd37,9fd74924,4cad1e68,ecb8b247,d76a8a94) -,S(8ac33ead,a9341644,db25b034,60ff60ab,e1326eb7,73a0bed0,29f6e966,16b62bce,6d07756,6f0d18b4,bd055d0e,d99bda50,ea9e614f,da46005d,c6d9dbfd,18945cc6) -,S(476b98b8,9e7feafd,ef5f0116,6e0c8eb6,70cb3325,a10fbce7,71ea9e06,2566e22a,38dbf041,83252b86,7e138483,c012f220,fd98bd5d,b80fbf47,30c5d0e1,d6a91050) -,S(e4d262ef,f0de9c3b,d3302bcb,321adfa1,2e383a7f,19297058,a19c453e,ed497f11,a1f830fc,2fd6120c,8f2070c4,9ea49001,953d0c0e,7c02050b,fec7cf7b,ce2781d3) -,S(67bc850f,48f0be1b,f18c4f7c,b9f33e67,e2e09279,4196d987,1bec0fcf,f0b5cbf8,e2560470,334aa4b2,4693e927,1d2f20cd,b7e6fabc,92e0f355,526dceb8,5f52d32f) -,S(50dcb2c5,c0dd4942,2564be02,2ab274e,b543a6a5,a2712b8d,58f51e12,72ef2797,2cbc036f,b69c44c9,9c7854b4,9705dccb,8d2ea16a,2f77fca8,90d89f8d,4ab04ea0) -,S(6c9bc577,784948f4,1e8a57f1,bddf5665,f860804e,89912876,44ba7b76,8758bd6e,84a671f3,5998ac84,7329ca3d,1224901b,a0401915,c9280260,cd40ff44,ebb3ff20) -,S(5dac93c6,d27cdbb9,9f3ceb36,18c6ead1,28b44146,467390e7,a337c494,8382a868,86572065,1805082e,7434578a,a97704f8,8a91c2b8,e315ed8b,ac2a4bf8,342df508) -,S(207903c6,5e1c57e1,7a6e9484,d3073c0f,f6b2a40a,b46b996f,2ed2be7c,85780c86,4b568420,29564d4f,6c4fd310,73e17a3a,bbdcb83,115a6c14,854633c1,47f6a442) -,S(da025f63,9be593e9,3ab35113,2282830f,6ffbc94c,829111dd,29546221,2edc2f90,9b4acdeb,a315e576,f0edea9a,21acf5c8,714defa6,5ef4ae68,eb694383,916d2723) -,S(327faacd,1b489c8,2126ffa6,b87cf191,2a0f61f5,ee47eea5,6030a50f,b2823cb1,634ab42,6010009b,144c5ac2,903e5f8b,14c00c67,5fe177e9,6b7f9ecf,b8c33b9b) -,S(44cffbee,1619f462,a853478b,a9d1bfd8,6c9cab17,f5bf50cc,79a24558,7b7e8084,b08983db,62079e28,7eaf8c28,81079a45,76442a1c,fe35f64,563c714d,748e7da4) -,S(c5d945ca,13730ce2,c21ad679,734d1deb,beb19785,480f93a,43a2170e,6a6fe3a,a3aad11b,4d8b7140,f67f7287,8e4a9c1f,74102ffb,ca3ef04,46e7bf1b,ae3cc3fb) -,S(f4d8cf19,84dfe935,11b2694b,8f1db0ed,d4bf22f6,435359e6,77fa42e1,cec0de31,83d02d22,3aae1880,d7ad76bf,c7e3bfde,5b48a55d,4fb0ff02,c0ba5c2,e9a30845) -,S(13d721dc,8e7b0bc8,90c6380a,fd0f0ee7,a2dce0e1,e153ae70,7e50ae7c,1837c4cd,c620c1e3,e1575411,7eb9e823,70af7e4c,9309c412,d5f14d28,e976112e,88841116) -,S(e5f9efa6,66fc6728,207eb55d,94c1daf2,5164824c,e27b1783,92862e11,6265ce1a,500a9fe6,18302bb5,22ff9fbe,163d79b6,1f0f3cf,53e0956c,7712f23d,5c0d9975) -,S(73ee3cbd,a1ba137,65a7abb9,827b1b32,a48ea0e0,a43e9698,8da603c3,c319c9ec,d96832b4,4093689c,beb30bd5,a2e825f3,bbc909d0,20e18744,b0a5ec5a,1ab38f58) -,S(11b92fc5,94046bba,813285e7,122750a4,3e028501,f027a55d,f101d2cf,c5990d91,e08b24aa,e20fcfe0,40dcfcd0,80949b2c,23b324cd,1d957b63,9fe91716,a4315417) -,S(3043669c,22be0dc5,fb14442a,22a625d,b1bf4952,362f06a0,623ca1cf,9160935b,dc4834b0,4bf47d6b,fad52c04,4d26e21b,41eeadb2,5c92ca22,6dd2c86,24d0eb34) -,S(490c39aa,c290d144,2b87622b,407dec4a,3f92aa61,6a9c8495,132b5c7d,3d5f9a0c,5c76c0fd,57844aa6,fe81361f,73cb314f,110f87de,6773e1ea,b3d68dae,2926b986) -,S(fdd5cd58,67d73347,ca1fb212,772b0c42,3a4caf94,a3e0bf2d,2bbb2433,9002d03a,efe5f407,d1d26bc7,6fb5bcc0,6bc94da5,bd69f84c,85d89172,10bce909,77411995) -,S(bc8a108e,b0830fce,443db272,2655ac40,e2d35989,cad192d8,e9c5017,14435ea9,924c0258,cbc3da74,a708a384,b93196c0,76bd3af6,2907cd60,22069b93,e3c979f9) -,S(ed809b6e,41f4b6cb,86ae431a,718989cd,2c706ea4,10152e3b,3395df8e,ae924b44,135d805c,3295589,c8d42ffe,947aa88,bede6699,b119f8a,324c9bfc,64315da8) -,S(26b50ac7,5d871e07,4147d2f1,ee42d6a8,4398212,79e9f276,7978517b,6cda52d8,26599c63,86426e9f,b14b4c8,3494f0e,1fe37ea0,521e4518,e346bad,545dd7a0) -,S(cced88de,27d0ccd4,7f6746ff,98907cf1,679f6b10,67785dd7,25ab94d4,9fe8efd5,5b0ede2b,4dc584ac,b4b6adc2,c52b4268,e2beba67,ce2bc825,fe4df43d,73f5729a) -,S(d8edf7cb,31526332,308429c1,178886ce,bf3fe516,18f472bb,52da883d,d83c6249,a56abc3e,c155eef6,d43427e1,30ba691d,8c71b80,6b487343,7f3daf07,17984be3) -,S(ed82c3c9,f8db3a75,50949aa5,cd6c8fce,52648910,53f66515,c2fb71c4,7564b4ef,5ee59949,6d9d3c7,6fa9a26d,444a8a45,41ddccc8,15fccf39,b06e8fe5,20b2f0b4) -,S(6e277bae,e89aeb54,5e6249d,56d50848,5853b3ad,8588365e,7771ae44,3d8ca937,84871bd8,1e6f94a7,c31a3fe6,63a1170c,8f9623dc,4e24a5b4,3f7d023,39f40b8e) -,S(aeb67ac8,67271210,565b1229,3e1aff94,f2f8b642,76768967,f702afb9,48a03c5c,fcd3c588,94259c03,cde7898d,66ff5ac6,747100bf,3707e89b,6980d21d,78bde197) -,S(9f07ff4b,aa20c756,94c967d1,e38633e8,45753193,a3d13af2,3ba7ce07,5283da79,ae8b7f0d,49d06168,ff3c5f36,3aca3f1c,14308cf7,d95bae36,3975fb7f,dff2136b) -,S(24046d14,a026daba,1644b3ef,7bc5501b,baafc3c9,76acfdf7,243395d5,713e1520,265485e9,6dc40a31,ba93cd0e,915534b4,37fd5380,bad0d6cd,321867cc,aa029ae6) -,S(1376926,bf8fd1c6,80344f48,c574e6b9,1806afab,7d9f90c9,13bbc233,2b3de519,a34100e7,c4b44c26,f86b2198,e7d3696d,8aed9051,a1755ced,56ebe795,d5a61fa5) -,S(943c6d4e,816cc668,87f7c85f,b116ae82,5e4c38a6,581cd5f1,1efc9a3e,ef5a7d6e,d93d4724,f618da6d,29e35165,7883ee36,74112f70,3169eb24,eca31a60,969de8dd) -,S(adf8041f,159260fd,cafc9e61,d5f4f867,a0f46e94,af60bf53,d4d0808e,885432d9,c4eaba1f,99d2516f,3d731bcb,be90b36e,c055ff5d,e6c3ed95,2b95a037,1be57958) -,S(15c17f13,a404ae08,11ddefb6,707a9fa9,dc0d9461,8325dbb8,d96537c0,6e2dcc44,8740d352,21f95e8,36842b48,2512d79d,a799fb62,60d65dc6,79df383a,e9b6898e) -,S(87bbbb35,62365994,9c5bd575,86b813dc,966ec9ed,1ac31435,80e4b7cd,cacb8ca0,159992c,1bfc3c24,95e14ccb,e24a3e9b,6a28f4e9,1cad4a36,f83624a8,d22a48c4) -,S(39bd144a,96454c1,9e082b5f,eae9c433,564da73c,d5d44daf,95b5c176,9f1fa105,ffe8a11c,30b5d4d6,f8abe12e,bc3ca8f9,dadf1527,330319bc,fa277b13,256fb207) -,S(c4e4eb4f,9bcec0c6,6bb99bfe,265b2f4c,a1c69676,ee970a9a,b78bbd64,a83bca7a,1bb9a83d,316cb9c4,bce4be2b,d05e6381,2ecb493b,44fc3cb7,c2248a0e,96bfc286) -,S(c183e783,1c80d334,f0ddd2f4,48ca035e,8b53f034,f53c1801,488e4aec,cf244e69,f998feaa,c7711d48,3db38926,8ddc080c,8ff2f95,494e60b1,59330d8b,d9a8b820) -,S(99d1d7ac,22a2e108,f093b630,f374d9d2,7ac812d9,5753bb6b,e39c2401,fed47d92,a67d334,88dfe341,e8dca3d9,b36a897b,52080a3d,c366c8b0,39cc4de3,52d0e1f0) -,S(e0700a5d,16cd89bb,df3d6f18,76909082,985a3339,e7f5d2bc,5c3ccc92,ad61cea5,26f6abe0,38953fa8,40bec97b,c9d59c20,1fd08b29,4a7ac7e3,bd994e07,70a0b0f0) -,S(b19bf6e8,cf36d839,51b813b5,67aa62ee,5415e95c,d3fa668b,55487a3e,61a7e721,630e78a5,ca2cdb2e,cd59f59e,4c10e712,46c1055b,a7709041,fc03f8b9,1970153d) -,S(25009156,e90dd0ec,88027adf,a9701474,39abaf72,1c333943,c6fe6e19,ff71fd44,324047dc,86477632,214ed74,cb933859,b7825500,2d19ddec,9c466e1f,573afc11) -,S(45ce7fe8,bbe45d1c,9bb0c98d,9d4c500a,aca5011f,96238681,771b8538,61a3e4ae,8cbc22af,d1adb8f0,a5c72570,2b6c7f65,9e41b176,1358832,7ca062e4,2392f8b1) -,S(73255507,d3a27fc6,7df39212,a286ef6,b939e953,43b12683,4e38148b,619ec059,3174d6e6,e941020d,db0f3ded,aed6c8cc,eeba10ed,1344ce28,a354e93f,25c35b63) -,S(96b2cef4,1c6c39e,1ec9a945,8c8bad3f,6025962d,a1207885,97800ac1,c811df58,ed85ed21,41b4ad26,3adab5b7,c0c0035c,2fbf9e2d,983dda99,7d1249c6,8a7fa8cd) -,S(5764181c,d941b28a,a307bebb,912ae87,57f23cc9,37025cdb,b983eef6,42b9c772,e8173b4f,c23908fd,db5f6437,5457a43d,2495764c,f3ce1b8e,f2c8d2be,e0ac7089) -,S(38ec7839,7e965056,2b1e314,5d5b2782,ea16d2a3,82bb6c60,efd29edc,93ec1b61,acf04ea4,c7b6de2c,d8acaa3b,a4bf2656,f522e631,1cd51089,744d4c96,318ec96e) -,S(6ec4ef80,13d01c79,758439fa,108f7389,79c9f7dd,4b285eb8,b7aed579,76c0b572,2328e642,e618ecdf,3a6560e,3eb6af15,7a6d266a,f5f3c4df,13c1ba2f,c898be7e) -,S(d8da1f6b,30c27b1a,5000fc14,9a768683,4c40a581,c4ed67ba,88492449,ef77141b,ccb532d6,876d92cf,2b8c310,839387d7,d92464e1,727287dc,49a3b348,2d519758) -,S(84f25402,734970ec,966aa9f0,eca84a1e,6894d36c,338722b4,e5fed162,8f7ccb90,f2d7fd09,f07e6302,cc97d283,d9f06319,9bee137,d3946944,983c2192,335cd8b1) -,S(ef6752b5,58874372,859190e3,91d86ff7,3adabfd4,cf008038,136b2ddc,ce9503e3,23d9ca50,13cb479,7cbaa675,98dcf98e,73f949e4,614390f9,1e6159f8,3f131c56) -,S(f88d8590,3b3fe67c,f641cb52,c77c776c,fe198f74,fe116a46,602bc2c0,1085ba6d,58af2abd,2178ad68,a3695714,cddf14e4,21da61a2,8e6cfa32,40507fb7,ba08742d) -,S(93b739bd,d366b95c,675daaa8,c5ded7d2,18cde6d5,d15d354,645de017,2db9c01c,24ec535,6c2f8eaa,633af5b9,6ae0fcad,7afea5f1,c7c8bfb4,748b886e,25cf3627) -,S(732cf404,da7ae5a2,dbf82f80,180c1154,6d313b92,58980f95,d413f223,443394,858e8326,1758b90a,902eae58,a777b56,e8820084,153c9e43,1b7d789a,4d596953) -,S(efde0719,2c40002d,3f82e024,a1b838b7,65fc252b,5be4af75,28ea5994,a9d36e32,89c1d35c,3a153576,91a63585,183a9c6f,b8dd69b5,69d45483,f0c2f80d,3dd9107b) -,S(9eedaaf2,80693392,76420c1c,da950bda,f114e65b,9b1a74a6,b42dd90c,1ec90a15,1399dc24,7fa540cd,3249728d,a4d28c52,26f427e1,ac3b533,7de8ba07,d3164de2) -,S(23f0ea8d,342aa214,69deaafe,bfdb487f,775805c7,d4ba17dd,877d3d42,19433195,dc1c6e31,d2a481c5,5d32ca8d,1d4e93c1,63444dc3,9e7c306e,4fcbfd46,b699b03) -,S(d85270,58c29e60,58916e82,76a305d2,edd47c0d,4e33052c,74cb76e,abe060b8,9a0e4904,e4db5bb9,5ec9e510,59ea4993,84d497b6,8a9a1258,3a2fda6e,bd0cfac8) -,S(1b34c95c,ccf91204,5922d2d1,90cf3860,f7d36b37,7ab3763a,d4d9046b,309f28b8,70c2320c,3f5f663a,b6478c3d,2607cb4d,f7080de8,91bb408f,6f14a11e,2951e948) -,S(32558fdc,ae5e596b,b756d4e2,f10707a,89569d36,1498e8c2,8fca1473,4b84b228,7759a8b7,5ed5755b,b23978c4,3d5aacd9,fe63f6e0,74b6fcfb,501906f9,16038d86) -,S(64818b77,37d2bc57,391a3820,2040afbd,6028d7ec,fa3d6bf8,577cb1e8,dd984acd,4202b934,6ae9554d,9227b891,4a6304bd,2cf895ec,a7267e1f,5707489,71ca2300) -,S(c6af6ac6,ec2d7cb5,42aa2373,24288551,bcd33705,72e1b1aa,e572d87d,8d77b333,fffe5559,4ae5a2df,18e393bc,dd0407ed,5d5af18b,85f22352,9fcc7cda,dec78cbf) -,S(91f8fc44,94ea12f8,fa2a031,7f32fd44,2e7a9e34,28eeaf13,a8b0de3e,a4f1cef0,6a0a47a,d81b1dd0,ac6765f4,20cc26af,e76c2225,eaea2a42,481ff6d9,a554dbcf) -,S(e159a9fa,6a26f57c,879b081f,dc015b46,dc610a61,2335d6c8,e353fc42,11c1c017,c209c643,445ae009,a75656f9,b4c1df2c,f1c181c7,ca81d0b6,bd749afa,a93e8851) -,S(e8e9fc5e,135f3a97,1211eda9,c06d283f,1a705169,b89e5813,556beba5,a4f9330b,e8b96899,3b73e8f6,da7b55fa,6f1e44b5,c88423b9,f3fc5553,fe0b10d4,e9af0abb) -,S(f3f5d529,d5ae4c0c,36c27ec6,e13384b4,11aa9818,aeefb5b1,64243536,bc0edead,3f740643,1e40c133,345abbc4,ffc5e0aa,1dd1e306,43e52ae5,33f5be61,db3d34b9) -,S(c5b76430,f5d8bb9a,e1b9acff,e1417602,9eae65c,9ca1606a,2e4f6d7,6cc81159,80689f09,70089098,24087591,6915380a,29b13933,9a000fad,d2e86d8,cf2429c1) -,S(954aa4b4,34f59074,45ed30c9,ffb6db50,ff275564,72894261,e935109c,cfc09b0,8023ca86,1bad2c25,6cd76be8,b3b0fcf3,a808b76e,80a70ec5,83265d3d,c72e4ad) -,S(55da8bb,4803f339,3020c9b9,30a58336,1b96ee54,4bbb4249,d6df1335,6e3d528b,dcc44b88,ca06e9f5,86cbb209,da01785c,2387b14d,355a2575,799ef7ce,32e5b64c) -,S(8084e800,d810b286,b0ad48d3,d262b4e1,db59eabc,a176e368,77a7f8bb,a3a1de03,d8beea9c,59f865fc,9f09c12,9bc5f980,70d60ac,eb348f85,e0888fc4,63dc1480) -,S(1b2bb6c2,36c87f88,748f49a1,5094949b,d15e0217,b00c0bd7,f85efa41,5718b39b,2164b195,6aadf36e,f1bdd018,6bea9a4,c3c3f42c,b0e81dc,8101ad14,51029c74) -,S(fba687e8,125c372,e5dc65ce,3d2febed,de9139d9,9f91ad84,830da38a,54377872,8944eadf,3b89501,ca4a7a82,105a9613,55aabbf2,57f4bf83,923ec12,73e001c9) -,S(b58e4b80,a5f1c16f,f9c699c9,75a2d797,d21e155e,f091ba94,8aae2dfe,fd560cbd,fff9caba,1429bfa6,e571b7f4,12d6aa97,4606f7d,9025efec,937a5128,52cec3ec) -,S(8ebcd526,da5d6c21,55222551,e05c6be4,114fdb7c,9d43a900,fcef17ce,3426edec,73a0fb98,6b3301b6,3eaaafb1,a52f5467,de11f034,aeedc21e,ae97df86,513aa97e) -,S(fba4540b,924b29e8,95dc68f0,e971549b,7354e032,64040d2d,bb956691,1bee325e,529088c3,3b9857ae,342ba0d0,7e52843a,290f3c27,16f5321b,6c9e6f51,9105ebd4) -,S(8b7a2c97,a1a7d324,6d86301a,66f3f36e,ce014c97,651b25b0,ab46f4e8,bf9c44de,b82854ab,699c35b3,6786c1f4,71ea7536,7c88a684,43fc17b9,4cb328fd,a4b247c7) -,S(9df11743,5adb7154,e7003bbb,a1ba909b,93179677,4bd4896f,40c39a58,ead2279c,a7922f4e,a216cc36,c36913d6,e7ab8641,d4566865,dd7a2f83,77ef219b,41b884eb) -,S(5beb7b84,749b444c,82efd9e7,37314892,c54b6215,c1f9be9e,414adae4,56931cd8,99e425f,32cd0a7c,28e753fb,ff308eff,d32b7cfc,eb51df7b,64f60e9b,2fabb95c) -,S(2a830c43,ff204ba,78c5114f,4a3b7b09,c9f8ed5d,17066f43,cd512af6,4c788879,12523a4,e8882652,eba827fe,d207eb00,9ba14809,9ee42865,61e96230,62666c84) -,S(f71a46a1,4c1f2a18,e68ab408,bcd32d94,985a7714,19c1419,1b69221e,1c57486a,adf19b3e,ea79a53,4fcce36a,4cc0da0f,4fac443f,b281cf0a,ef675b6d,20534875) -,S(2b80e5dc,aa9c2b31,678ae2d9,f7d63c0c,bbad2bab,36c412fd,cb6436a7,c69d193b,bc83e04d,71d60062,b681ce04,c506247b,8f3c9019,c2084ffa,27621d62,22119c3) -,S(49cbdf3b,e521c69c,68375b58,d4449341,75424a0c,3c45d5b,b975235c,e63beece,c5615eea,f0f0e7ce,c3756aba,d3a136ae,91d260f1,563997a8,ae46c49a,5c62de7f) -,S(ce4d4714,b643b115,9215e2f3,1dd070f7,f7aa663b,9ca87739,79c5ba31,ce9ee1b2,b1f35e12,a2fc3aa3,4db59ef5,e62101b0,479745b4,200c10aa,d6f8fddb,1efeac38) -,S(6827b6bb,aa905ac3,8d93bb1b,5d5881c5,a8bef479,ed7c5656,2992d4dd,61e10054,8524a87b,af65020d,91848427,95801f54,30fc3727,7ef2064d,1aff8ecf,296bb869) -,S(e71e4d5,48f4d7f1,c7b7879a,a03a49a0,ab947218,b16dd125,19af4ad1,8056535f,495d0461,7098b3d5,6f7e3bed,ab5c9813,83aeed68,3ded1c09,f0d1bb38,e32f574) -,S(ef683979,7429fb30,d436aa32,a3feda68,65652816,873ce542,6320667c,6e00e032,b4b18e4a,de1197e8,fded846,f188a6ac,2f17506,f014d404,fbba3635,534613f) -,S(c729c1,ac8f7eff,e908007d,e2eed85,dd557e36,c1ec645b,a258b03,e52deaf4,2e83edc2,18584f6a,c5ebade6,a335a087,12365b89,ac38f27,bde7ebf4,561305fe) -,S(cf1d3919,9a716d53,b2bc4f2c,3ae2ded1,290d54c2,2124a88c,c1cc7fb1,115735ab,6b44f5a5,7ec3402c,e8980970,dab8538b,c276c8ee,ad542908,9b7b70d6,dd00e6e6) -,S(6cf3d7a0,266dee28,f3f1f772,ee90da75,a9c28a7f,f82d8f55,cf9d609a,5becdeae,3bd18fb3,1e11cce2,895b9cf9,4d9a99bc,ede5c9b4,c44ede14,34dfaeb,49bc58d4) -,S(da4b5832,ae63eeca,cdee4274,f00ae932,56393cae,cf830be7,f28749c0,7d395542,9aabb23b,d2d940f1,815610c9,d1684b92,106374e3,1b694ec4,dfec8818,cdb2210b) -,S(f91ae350,23210e16,f9c63270,cea2c6bf,407d1a10,e95842d4,b8ad5f7a,4330bbfa,1f161ac,d1962573,5969290e,fd3d1af1,53c91543,33651e16,1b51086b,913aa1c2) -,S(7e1bef52,cc3e2a2e,45847c86,27328526,c72e3f73,fa1c8255,56c874b2,f2f1ac02,be4b0f7e,a706e4d3,db7048fe,e0fc4f50,8ff0523,ee8d97f4,4c4c1787,e6f6e6fe) -,S(dd2695d,30dc2ee3,748e256c,cdc92eb7,706567f1,4be720ec,b27fc814,d3d5998f,9af32c44,f1028013,9ee7cf99,845472b5,bba67740,f0f0b96e,d1a02a19,a32dc74f) -,S(78fae650,714763c8,d12602ba,33b76da,125fe395,43fb37c9,4d20b337,649dbb9d,78dc4c0f,726cce6,f65826e5,eaf1fea4,c3b92532,6624ce1,21de2351,bfce3aa6) -,S(1edf521e,510e5dd2,aa1d3e00,d016b45a,1b6fb6b8,591d98df,ee692636,8dc98bd5,9a0d016d,9b2e9b8d,d0f4d817,71ab0f20,aeafd8d3,63beca59,7518da41,55311f86) -,S(8607bb0c,5e53b60b,9153272c,d3cc69e4,7ce28694,37562b4d,4166aa18,d0101d39,15ca31e,c83c6541,c35a294a,a648af8e,38870757,27924e98,8ef566d5,96eb519a) -,S(65fd300d,9a0503f7,80a0dbb7,c42b9bb7,37f9607,912f2df7,166b65f7,96d02eab,fcd15350,84fba852,11f94540,1f6b43f2,904caf3c,d44ecaa5,335b928b,4ea3b5d9) -,S(c918b3a7,6c847ce1,c01845f0,34ccbeb3,36d031a9,33093f99,f47f1458,cc02d148,f256f403,dbbb2e20,32063270,faa6e62,596329d,ca85ceb5,3ed3adfd,7f728568) -,S(6ac2dcfd,2f0b879,becb429,140ade0d,532e54d4,dbe0bbb5,c1352ace,5661817,f2c26310,abf9396c,5af23074,e72251c3,784c3de3,60466dc,ccaaae16,4a9e2af3) -,S(8d71c4ee,54acf389,cee39b94,b5feb2b2,cf8e95a9,45f6a95f,5b0bff2f,cb3f3d19,98442bd9,5a02c1c4,7dba3881,e3306103,f0bc8857,89b44cb6,54875847,f1ce52d) -,S(e8bd24d3,fd557118,f2c0abbb,511e874,2e5d7368,a909b072,b3dee124,44f583c3,e1d2c3a6,e28622db,65b7992a,6716459e,2380285a,cd60f43a,4d4b1bf0,8bce6538) -,S(62dc2975,5cf8cf89,e52c8c51,6311e3b4,483fd024,ab2ad1d0,32d7255a,3c075217,799e132,d80d22d8,e0f01e9c,d0954251,8b3fc8a9,48f3cd1e,9391f8f,5c0e2a97) -,S(37db13aa,cf727e60,cb102709,9c7d3c07,4d43234f,66a95451,a6050496,d44c0e13,c383bbe,8f8ceff4,196e9d07,e013a1f6,d3402a6d,d09eafb0,62924334,89b1066b) -,S(37bfb765,eab7719e,c858e17c,472f1df1,be9dc439,2699ec39,37875b30,fb2aa1ab,72718bfd,865dc4c2,2f935f4a,98af8ca6,5cf44b5d,66f0eea,23b53563,d1721364) -,S(433ede12,87fcbf35,5fdba6e1,f62148a7,b5d5c3fe,1200d456,6dba452,a85d1b94,b27c5613,ad6e513b,28f0c959,13e30781,137a4c7c,7aee6e60,5715d949,4757c20e) -,S(e582d9f,c5ed0de6,92a1917f,6ab7df46,d23295d0,b8b27b32,3af9a57d,3e671861,33ee8785,e2770dbd,7e79faa5,386cb1d1,d1c9e073,1b78dfd6,5571deff,d4073154) -,S(60b07b40,634bf15a,ee2d4e5d,a0f06ade,ad8fae01,4a6a189e,4e428600,4c9442c2,fee087cd,d243ba,62b4a2cd,68d8aac5,1557f29c,a57b0f37,ff2119b1,bc4b283d) -,S(4b167276,1e5f7ca,a245e35,b6e88fba,643e6da7,ce37c9b2,10265ad3,2de03100,28aacf02,476887e0,90d26c1d,cd51f15c,cacda02b,b6314a64,73b90c93,8ed8dde7) -,S(5d56113d,6d797e74,c4803e63,89a88ae2,fab97de1,4ed4e7b2,a17d2f9b,fe2a3170,94ef2a8,534eb2ff,a62462a2,7eb2b34e,c6545992,e2d973ab,ee42b1e7,d9cd524f) -,S(a9d03fae,75111ad8,d1157287,8e8c4473,f4a06cd8,f28dfa7e,e38b3d06,3a34f828,a0733c0c,c7319879,2ca665bf,968f6bab,480c94b4,c7de262e,4d9d1f95,33517881) -,S(74199571,2b1abce9,ed4db3b7,7b3f7e70,58fd3716,1666c522,50855f25,660e1ad5,710caea8,97f7589,cfd3b8a3,22726000,ea3ef2c1,8aac385f,22b67bd9,da44db) -,S(9f16990d,bf81a5b1,eeba1e5f,84673e16,ba0106f2,acc68be7,cabab96f,25918dc8,d60d47b,62321042,34c49d39,c03806ab,135d46f1,ea6587b0,f0b6588c,50ebc4f5) -,S(3b5069bc,4f12b9a7,ad91c888,fabd15a7,c99143f4,c8b24619,b6a70c0b,2301d57d,dbb87cd1,ae59a944,9fb4ddfd,4b311d66,da18544e,a86b75a8,979828c7,fddd1a79) -,S(9dea63a9,67b5a36e,bbbf9af,bbfabb31,f90cdcd7,9b75c68,1159b946,dabaee90,b14bb99b,11bab958,e31a605c,e9180d23,5c7d2eb,94d4de57,b8a66627,c6bc4464) -,S(d0b23392,1da36a84,2565cb53,4411e63b,9fe6b2c,c33c3a18,8e0ddf48,55e31e79,80ed93ea,1a6e5492,dcaf1cfc,c350b3b2,99117276,43fb6a75,15c435e5,f74f8e9) -,S(8adc9655,966ae44b,f98ca7a4,9f441e3f,acfe85c8,f7111da5,52c817b3,90b03d20,ce72054c,6a717312,180c80ea,c9337430,5dd1d566,db1b93b4,eed1a6e5,73c0021e) -,S(f6f76bf8,cf6d3dea,700800b6,d018a4a6,141ac610,e2e13fe3,ec916726,1e0c1670,b2c478af,e1ea9876,98e5e2a1,6b3a4ee,63e4fef7,6644da54,e241c395,3f9a302c) -,S(d58287d,38b7da30,174fcaa1,873b3913,2176388d,6da5f9fe,f873d86f,14b898e5,785fc934,69ed085e,8318f91d,114ad0cf,da2b8ff5,61e545ee,3502e9ec,6afc8402) -,S(7772ca23,50c5ee55,9ffe810c,6d8702c1,538e3d11,f4b8354a,2fbf674,39a3661c,5a2312de,853fda14,5b48aefb,23e98e4f,fe3dd3a8,ae1fcd6c,931d9a43,686edddb) -,S(a2f9f976,c50f3687,7ad0ac95,efc3fb2c,46ce903e,76ade308,69705df,72433ad5,ec565311,24c289f3,35e11b22,bf8d7445,f201dd4b,68afa38a,22af056f,c8c285f3) -,S(e20d9765,85f8c567,24d0ec16,5ad27110,26fce166,b52ce11b,cb221a80,4f8b15f7,63b61933,c7f63862,98b48b6b,c6abb54b,21d08220,166ac31b,fc85d4dd,998f33fb) -,S(8868b59d,ca1de2,cbe98d94,506db1df,659ba688,b2bf093e,42dcec03,acecc18f,f02e9b07,96b98fb0,51dbfe8,4524ebf6,dea56251,afb53076,e2215d83,fcf2fd0e) -,S(1099f82f,e32a1361,a785f86b,9a6bf0e8,99c83226,7826d6a4,3f8581b8,89fb677c,13fb83f2,9aa7f271,2cf20cd3,592eac46,cd2d3e61,9afe9aac,7fcf37d8,9c44445b) -,S(4af9c696,77ece7b3,5f732969,8ca61b27,deae65ca,ee2d5d31,ef2051f4,35cbeea3,73004596,429da976,f96e3f80,a24408a4,ebfe5196,8130c698,5b210826,664e5ef0) -,S(9680cbca,5aceb8b0,322d4bbe,8713cab9,300d1f8b,d16ee045,edb3b543,57dab473,2f293940,e36ba1d2,ecd4697c,209b33e0,6904ee3c,2798aaec,e9131d9,bd0df58a) -,S(7eefcc3a,fd6347f0,5f9c3720,31480c92,3eb7fdfa,d6e9c0ee,4e2db9ae,27fae7c2,b8e9fa75,4f745c14,7c753e42,17bb1e28,7bb93d9d,aceb357e,9738f10b,fb5cac06) -,S(b823156,d63612b9,3461fbf3,6894955d,65e7805,b025c2fe,98fd46fb,2f9fddb4,f23c517a,826fe91e,45f453eb,fe9eadd4,d0b537c6,a2a8f60c,dab9dc58,10bd465a) -,S(e801d35e,2035fd54,92178706,e2e765a9,bfb9de22,e89182b4,4d5144d3,85bdadd9,1e648234,27dee6f0,818868e0,419e37a9,1c216200,3faa7478,48161809,76956a26) -,S(e9d4610e,56b70969,284369e5,7e890fc,29fd7750,8489a1c,2f348f52,cdc67f3a,8e5f6aac,357d82e1,a29bfca2,2ee4516b,1df0e622,257c2c1f,7d9a84fe,b48e4a0e) -,S(71c3ef0f,51d6ddee,340d7aa0,94680084,b94bae8a,e3528ff,4a481af6,d3b7609b,4d1674dc,2f8087a3,138adc4d,aa615a43,db6886d4,4992fca4,544f57e3,315f6b96) -,S(9567ce43,b6f5c41f,bdf8b44d,938abac5,21aadb83,c157b947,ce999c0e,4a7d6f20,c9d86317,31ea318,a647ca8,945cc35d,1fd0fdd9,b2de4fe3,5e2a0021,33a35538) -,S(34523d4f,81166739,10b3de85,11a1921,4f8fc753,fd8963e,b9db22b7,8edcc141,900fb9fe,268b88eb,9b80a066,277d8ba,877bca84,f277dce7,7d6e90c4,8422ac90) -,S(69fd1f7e,5f1c43df,a2f4350b,f20e5cf1,f2993dfc,b61cd278,1590ad79,e3c1bd98,633726cf,8b74940a,edb15665,a9277973,2d1c923,2bcdd615,43c9f3a,6c51d7f3) -,S(e4c2c424,c28cb8f7,3146dd39,bb4fc6ba,411b2a75,e317faa2,a9f878af,e94a3de7,fb8d17e8,468e5ef4,8da60739,820515cd,c861378e,9b3bd158,fcc8a949,eb21ae89) -,S(5710459a,ada916d0,9c1feb59,c494863,98e44513,226119ea,5ded7b1e,34e32773,89deedbd,d2d83a58,4e56b409,30a8355e,905bf12a,f33f49f0,7383eca4,e63871bc) -,S(d56faed4,171806e1,5ac17f91,37101b27,59a3a8a9,90b85bc1,89b217a0,6fd48e64,fa871ec3,3408b2d6,b62f513f,5368f549,ebe43977,a48878c7,6d731447,34a6652c) -,S(e7416eeb,da0b805b,68b47be8,eedf87dc,cb5cf012,804d03f7,604525db,aa599bcb,8610c716,f11c567e,313eb4c7,77e4314b,533d4f37,13b11185,bbcf5442,b9a56c19) -,S(8ca59862,ebdd3541,91c60608,13ce32c6,a4fbfca4,6e60175f,2d5f1607,d5fa997d,aaf3480f,b132feac,6adfa195,2b14d0d,113dd6ee,faad71c6,980d5691,e37698f4) -,S(6496dc45,1fd43b45,1915867a,846c5203,6eb8e4c5,28c2a181,72fba6f1,53243413,44fdc41,f85c99e,e00a281b,9292cf1b,153fe2bc,5c8b3e87,cb14d624,e44da1f2) -,S(3a424463,aa82416a,a38bc248,dcaccd20,67d20721,d4e8f5d6,c9cb2fc1,91925a5d,71a56463,fd242591,434775cb,37c81bf0,d4857abf,aa527ca9,c3178464,8afa9fb2) -,S(6a945b05,51d55194,adbf7985,aa85fe63,8811781e,6b787418,1574d109,d178c2e6,186d343a,1ca3a836,32421fc0,d267ca27,80df9af1,32625d31,924e99ff,9b57ac44) -,S(13f1f692,682d04b7,b7e7381b,8c5c13b1,32baac0e,b7f8c8aa,c9ffd77d,3aadd47f,572a05e4,9622ff88,9eb36852,85d1400f,43372533,38c47ce2,282aa4ae,26e99f0e) -,S(79fa13c1,4f0de8f1,ed98e7b3,3edb77f5,a2700707,e54ce522,a516634b,d2804330,a094bd88,e1969ee7,3f41e40e,60f7198,cf2484ab,5a2efaa0,96e891ee,d5987c65) -,S(df1ff6db,d2c61bf7,c273f735,a6dab3d,fb08377d,bb3dd101,9dda03db,e533130a,2fdc7ad,68c58689,92e5c969,d8d14a94,cd0061b7,5ab0e824,fd19611d,923f886e) -,S(a8223280,5f5939ad,180f8776,810cc7,2bff651b,df7972ec,51d86d2a,1acbdb34,9681590f,982e3632,b2aea9b4,40043751,e7f2ef2a,d4b125b5,2784ffb5,17c2dfba) -,S(406b0cc0,49f3bf58,6990ada1,63c73932,b3780fad,ba3fd8c4,79e6a688,484c7c44,aab0e4ef,f2508e54,79074fe0,218aee7e,8b217932,859192d3,1bb20817,df6503dd) -,S(4e7043fd,5783479c,3dcf103d,bc4d9bc8,523c81ea,dbac9460,4b73300c,f516bcc8,196287b7,3ed01bd1,e8033ead,66c92625,77c859b6,73a4c7fa,98f53d69,e82d1133) -,S(a9a2a671,b945a5f5,90575c0e,ff24c070,a7d55b00,e9d2f44e,43cf400f,f3e9997,6cd45e20,cb972715,167f957c,af7f2f3f,9ae22ce4,3b46d4ca,5b2a58db,6e0c6285) -,S(692a1394,75ffae88,fba47ae4,9315a6ef,12b2dec7,6807608b,22ba3ff2,883d3c01,74dd5b4a,3c14a54,c0a86732,1a77d160,c834773f,8063406,85a65c16,6ee46131) -,S(36f915fd,156638bb,88928e75,d00fcd49,63b44ac,f5d016e7,7ddaa8c8,d62cfad8,3f11eb6,16edd183,5ee17d02,722cf6de,991dc8b0,e37fce3c,cf7f5db,e842e8b9) -,S(3f0f6f5a,7e010c0b,5442fd6c,a3643144,a5202a7e,bb3ac8f,99aa38d6,4aa53b31,2574d7cf,5b33e29a,950099ac,db0ffb3f,ab1f9ed7,f13cdf9a,b869fd07,c35c649) -,S(8c58faff,71f661d,b21d4258,a92aacf3,508a9dfa,bfc00cfd,26b95673,34b7b067,38d1e894,ea1d4ee2,843d08a8,80b11325,e9a8a171,59de273f,694a14d6,73944893) -,S(d806731a,205c1a3c,64b91864,2d940b12,dbc6f580,866b7a9c,f287fb7,c5da78de,870a8430,2ff57abb,735da831,863525fb,70402006,d241eba8,d43c2ebe,cdd0e05e) -,S(7dbda37e,195db041,a4dde151,5a7cdd97,416bde09,12b9a741,3354204e,2b848648,83c89c7a,649d0070,fde84ff1,32f60a9f,e1c0261a,87a8ccf3,885fb003,10715e71) -,S(8afc23c0,c803b0e2,df78ee09,3b776cfb,410a1b52,7d4be45e,58d8cee8,3ec54a1,b041eece,4f4ae4a0,b3a52957,386394be,bf7b11a2,b97eb5b4,1bee89c,352ed76b) -,S(4e4424c2,2c50fab0,4b803b4b,2562114b,1b2531cd,e5786112,36fb9021,3652207b,22bf6181,51187118,fb421e4,fb0cf243,889d5ca5,c14b6ab5,7e7b9d0d,d9796e6f) -,S(60717788,5a230af8,a0816e39,6e39b34a,f394b1ee,c93ba382,8fd92941,e6e97453,a84df29f,2b9da41b,14f24762,df6db87,fc0a18fa,89e356f4,9f8f4017,dc4b26) -,S(c9f73d20,384e56ec,37bbbf8d,facf70e4,a271f169,2dc22ac,6022ca24,8caf3213,7622e7f4,c77f9581,b73c9bfa,8bf5b578,89070e8b,97616cb0,69ea25f8,8dfb5437) -,S(19ea5dfb,dab5a1d8,c3c2bfea,48d90f6d,a8b9959c,630bfc4a,81ea5eda,ee45282a,c21295d,14bd81,7c3a4d62,af307b1c,870a959d,7d6e4c65,3b8e1db8,fdf1d56c) -,S(564bdb1e,30b2c292,cdf0e149,1bfaf852,4780669,717de5cb,290cbe6d,c1617b58,9a8da0e8,6fc0b95f,99e84198,877f5ddf,32508c1c,ebb9984,7004f74e,7e2b1c0d) -,S(5bc93842,4f3ee6cc,926e2123,7bee0739,50b39d1d,e0dda3b5,4bf46953,7d0bf06b,d4e9c3a9,662778be,b7f4bd4,cd753a50,32bb003b,694b5e00,c119dea4,20fd5d16) -,S(19432e94,829e8b57,3eef4fc3,181c7d7f,5b2a5f2d,a2e8c3a5,980db9bc,5cb7f99e,f75c999e,5c5b8567,bb69316e,36e01acf,2e860781,5c5703f7,a4be72bb,9abcbcf6) -,S(d399281e,6196ce19,a2ec28bf,a0b1b559,8d0235d1,beef1672,ea230cda,20080b8d,1ca7e95,20ffce3a,33e94931,95eba433,d5483cf0,d5edbea9,6384d1a3,5168aa19) -,S(6c84e35a,b220fa9f,e55f5556,302f6656,39372e97,74ae26ba,e21ca8ea,10e73c88,98a11b2a,bd442c0a,d49711e7,b0e8b234,1d15465,71efe9b8,9a7b4c02,1101b2b3) -,S(7814cd8a,b1b045ed,a1797f14,c83bd807,ec4205b6,e9df4858,1180a80c,a0f8f64b,ef917e40,edc8b8ff,f53e8b70,4de63adf,6bf17730,41af2284,1b0e38d3,b515f33b) -,S(7a01ee83,1c8e22a8,bfdaccfc,cd280532,444e710d,7138b993,fb6e06c7,996235f,fe512d09,19895c2a,b62f2e08,90dc3bc,dcb06198,18160b41,4527e7c,281a5519) -,S(655ee6bc,df86c9ef,918b5660,5d4a5e79,512e856f,3f3e40ce,72e8217c,1f9bd908,cbeba5a6,91fcb085,f3996ea9,d081e69b,7dfdefba,123df5c3,cae94f63,12f87721) -,S(ebd68009,fb0372e8,eb0be25f,e78117bc,3d4d4814,440f1d9e,1cf87ee1,de5219bb,8efb7e38,6f96df55,bf0aed2d,6bdb75f3,6da8cdb6,ff65868b,d8ce79b4,ba58814b) -,S(87340818,9ac05bbb,4e95cf05,17d5abd6,8b7834cf,1168f914,9f1d63b6,19a3865b,9f1fbd27,72ce0f15,c91d4dee,dfae0a3e,7d24c0fa,de2bf30c,df63f93c,14480838) -,S(61b6b213,b02a7bb6,4de62e92,515690cb,5dda3a4d,aa96f68b,a12f2c63,30513df3,cc71b8f2,4eff8194,36ad2962,8c003a1b,c42c6ce6,53997d56,e0162508,c2b6144e) -,S(4ba7ee4d,77171ae2,e39c9e66,3849841a,ed5e02e2,182d872,98f0a064,3925fe37,5cdbd5b4,fe344f16,cb72158e,b80a726f,5a9da4f7,751bc4f1,f1fdc734,8e96dbd6) -,S(d5827a7f,c4d5dcd4,32e5bd7a,46892e9a,6f9a3971,fe9e1de2,ee247e6f,208badb7,f790fadc,9d0e0c0f,61efb534,9b23c60c,2fb667a6,3b52cf18,ca0f0a1a,6098e1fa) -,S(81ec5159,7f950cf7,c0d44d4a,89efe691,e9086dfd,ca25098d,411cb9b2,93237633,885b27dd,c9eff80c,94653f28,ef92fb60,741d3a2,aa828065,5fa60b73,eb9a1e7f) -,S(28fc41f4,a0d4f680,76a3e06d,af0aff1e,6e723779,d8ac9e68,4cdba2fd,6ab6dec7,b1e4af1e,7affabc7,3eab9415,c15b235d,482c6a8d,b1085f54,d80ca2aa,49657225) -,S(d5e753d6,c5bf75c7,cb0f5b85,77fa2f9f,6341a88c,cf59b5d1,328b18a8,f7ae4f47,d1aa54b9,8eb01a32,2518a10c,8ecd66ea,fc2f380d,d97953cf,faf0c540,c4a1bff9) -,S(1682355d,89094297,e6008fac,44c1a5a9,257d413d,7589286d,8bad4873,1476e836,4f69c762,e29f90c9,e8459b11,d53ed84c,2ec9c2d9,ded4ea02,78d04546,eb09cf4a) -,S(9ef7a85f,b64cae73,2eb511a7,8cc46e22,73425d1a,d02272e7,9030240b,23e781db,c720356f,6f6a5a47,3f35e2f2,f5e92e2,78a50c9f,3a77604b,3eb3987,d09ce73c) -,S(4f6aebb3,6f429a52,4cb1be48,ace0eaaa,2174468,c13cf612,dd7ec70a,2e915ec,406ad94d,a8b6d790,2ad3609,252b6d7d,b28f96e,8780f6c6,39620b11,cf8e761f) -,S(4cac3e0e,5ac02e66,66710dae,5c0d7e8b,7a3cc7f1,a42b1f8e,88561bb,223f8232,9396ec8e,aa96f3c8,4ffcb9c,d8c29d27,dca65556,c2fe5931,8ba05a08,cb263142) -,S(86f3463,3aa2ac57,2c4a9dd1,64c7606,f61fbd78,60619937,38ea0a60,f79367b8,c802fd2b,556179db,5f776c9f,db4c38af,cfb2aa61,b5ae712a,3f23e58,25824f05) -,S(5323f145,7685e123,e7a5ab4c,d1d39fa8,bcd6f23,ba3d74da,318dc7ff,347103a9,3092fb79,ecccb29e,12dec977,cbbf38fb,94cab4f1,fee1e8e3,46100378,88691cb1) -,S(d3d70d46,402711c7,e680c45f,3a0e1c5f,f85cf106,983ff0e7,1a7f1178,33ea74fd,91982773,d9b90f31,16893b9e,eea7fb9,e4f722f3,e1577c90,fdf6f625,a8d07bad) -,S(df63b937,28a87613,2db5d71,43654f1d,f8cb89fa,1ab1efdd,6fd864bb,db6d4359,7c3b79ca,191a3ecb,6c793034,832fa5b2,a2c7bed4,84b792a7,91bacb7b,62ce5510) -,S(f1fe9222,8cc334d9,5f303169,a4e2262b,28a99494,c7decec3,9746be85,71b70c74,5588f3b8,4e65fa72,a2b35f60,f99af1e3,b67a2435,8c28eb64,69de5136,e751a10e) -,S(9030e75d,918ca330,edfec14c,b7cb28d0,fb0adbb5,fa29fc7d,cb3c9085,ba74fd95,7df20128,61698984,c0928821,c38aded7,5a452dc1,3bbdc4cd,71ad99da,38b427f7) -,S(1cd3c139,35bedb87,134f628c,576411eb,dfa0b586,2c3cc7d5,ddd7cf5c,77ad641a,2154edf2,5488bb08,be93a25e,c847b26,88264cf1,30fabcf,5924bde1,4b9a324d) -,S(e56e0737,a19fec7c,78b9f462,1ec0d5bb,bd6e91ff,ac995f42,202f127d,2446ad96,8830d827,368c760e,40a8d9bb,b693e975,1e69b42f,4b2ed776,98f889aa,3ead70d7) -,S(1b0a6ac4,58abe5e3,63e6dfeb,24ad8a65,56fd0886,78086657,587e63f1,5fb6b101,d2df6fda,e64263a2,b133e5aa,bdddee5e,9a35e86b,2e1f5926,5212cc49,335178dc) -,S(10a14146,8fd4618e,4ed390a6,246d62a2,50bb1676,45cfc679,d80cc081,23ea22b2,3383b868,dd7fdd1a,ecd13dba,f4ebb151,f9a09b25,bc30d562,b033800,fd40185f) -,S(9dc4ab51,5378a351,6db8837e,568afa72,e357f7d7,95d546ac,8a73e419,a43f5e35,8ddaa2d,9bcecfbf,e2a422be,1ea591ee,bfe05ce1,90439a06,cc68d66a,6305903f) -,S(aa93175d,e7a4e1fb,c538eb19,e89b20ae,13539e99,362035de,1aaac76e,3ced7196,edcedb04,c1344568,9f3e133a,d8b48004,c18d146b,ece3da05,effb864a,c2afb9ad) -,S(8171f3e4,da02d9a0,8bb6fcbc,6d06cc6a,94f3cefa,35d4ce27,536ef6fb,222edf7b,e91be5fc,aae62aba,1c02b55f,73c1a64f,c32038b7,a658f189,7499ca59,e9e6dd6b) -,S(51f6c983,c89128e6,635888c9,3c79cf79,893fe627,437464b1,11b08058,1aa19ab6,5d2ef149,4bb164f5,20c1dbf4,1a8dc650,b8cee400,d5e37252,a3d0f059,3881a067) -,S(c0a1f184,766b30dc,6a5016b1,9db0dda7,ec34dfac,74dae580,9500ab8f,6fd7d38a,bdcad3e2,c7b6daf1,29d41051,624d26a9,b27f361e,c695d490,52893597,eac6f01e) -,S(b1bb1ecc,95435169,4ab6fe0,7341efba,fde9279b,1eb78a22,2bd39472,33a0eb02,df523f5b,525342e2,c0cdbf0a,671e0c95,4b149084,de4c61d5,5a7bfab4,c81689a8) -,S(b5cc30dc,86d04ed5,88539ea7,e437391e,3b0891e7,6818c470,1803de7d,640b5dce,f1cc0d9e,45c7312d,fb1acc8,62e03f28,9f55561d,fffe4b65,ca41e62f,42d4ec14) -,S(de2b49e7,5f0ff53,28155b3e,a7d5941c,8cacee23,51fe16b0,da8e940f,9263ccb6,34d7a42b,b12dbf67,b0d7c680,178154ae,4690d5b5,703572ab,74b4d93f,6d8de99f) -,S(8b18f4e7,c129e117,e898404,65870cfc,ea5c0db0,ef2ef11a,d515f3ce,57cc8f51,6b1e1086,c8674a59,3c5e9d6c,dc8edcb3,72281c27,e6b2caff,8842e008,99111f37) -,S(727162c0,27cec888,918e46f1,762a830d,822ce424,b6a5f442,f9e582a9,17c86889,de348296,1452a369,e6fde5af,693e5247,24865623,cc516e7e,8416f38a,2f223cca) -,S(4ae4fc1f,4dd17483,f18eb9b8,1c2494be,946a75fc,a3f61605,6d0856b7,3505058c,d87e7812,e901fc17,da034a05,bd878470,59999b36,e2c617a3,9ae46921,f2563e7) -,S(e90bc9ac,e9e873fe,91826f01,66affd02,72007bba,4ef690bf,58b15206,5ff43cd1,4bc820e8,9acdfd68,51c9b0c0,65b9bfd,47f0762c,d2e56d58,905e6360,4564fa87) -,S(ba0ae6a1,db432fb6,f7a1af7d,be9ef746,8340ba5,7f051020,9af4076d,f51450ba,7d3839b7,4099420,1729894c,51a2c30b,51019a18,c32ea908,c58876af,912be720) -,S(70661b81,f77c6531,1d98b403,ed7b97d7,4f9682bf,2981fa5d,ef882022,d3accfeb,9022b973,18959f4d,9ae4bd7c,fb06fe66,7b4eeb92,5f46677e,4e5bc4e4,a6d06387) -,S(fe1b7b47,28153a07,11f81b81,7d9efa38,29451c15,8d1f11d8,e5e0922,fc471a47,95a075cc,68cfb7c6,fb115dc0,5e4c31aa,85725bdf,2344dfae,19c8a034,d2b0f847) -,S(8acf3bd2,bbaea907,28013d04,f27e3a5c,4325bc37,ec5c5e86,7ab70f7e,9acc3fc0,f679e3fb,36da27d4,f29c06a2,5951f80d,b3e2e0ef,dbe2c785,ee148657,3e16174e) -,S(1d855d37,25fc7d5a,b87fc6a4,7f62ba7c,d2db01d1,ca0f14f,1d6ea8d8,4af395e3,ceb263ac,2d41654e,d4655183,f6268c5d,9b0a9ad0,da8912a5,815dc8d3,20b1b90) -,S(1abb4566,30c24ce3,c84ec6f6,d70d19b7,9934498,451f02e,3926d70,592a8cba,4627706f,6be87fd7,2ad886ef,73245452,1778d293,41229863,f4b19548,74525885) -,S(1b4790fa,672c12ff,965d07e2,44a3f30b,620e5c66,4b098a5f,b86f2bea,93eac036,eed050fc,a758e2d1,f2a2a9a0,6b8391fd,7c19fd70,9c9e1283,1b018d24,e7edd60e) -,S(61878b2c,fc9cc88e,30ddcfc1,2561367b,44c106a0,21e3dc98,a433732a,68de3dd3,fa2454a0,37c279d,1b54cb77,498a9efb,afc6f50b,6b13e29d,436000df,1eaed78e) -,S(84048df0,2767feb1,7bcc21ec,f4502238,abc7271a,931730b5,3354010a,8544308a,d4712e4a,39d608e5,d47f9814,f7763c6e,605accaa,438ccb7c,838c88ec,e993c32f) -,S(eb7ac4e5,6c96175e,c3f1e1e0,37e89f95,8ba37d0c,a88055cf,889bac33,ca683a94,4941e267,2ccc274b,6d8bfe07,513dfc6f,cc07de33,2f517011,2bc3814f,5e85da8a) -,S(48a36ac9,877d4bda,b62b452b,a0288dc1,4cbce455,3809feaf,1a4195af,22142e91,e24d6d8a,1256288,6c6d8848,4e950d8,27eec39c,21ff6e25,30b50eba,ab69659c) -,S(9c3125d0,5a62a25d,7869af3b,1b23a00e,e817b664,c82d2a91,2522ce16,bccca1b5,c6ecda10,f6707168,18417277,4e18f5f5,38566361,5506b450,a189b6bd,39e5afe3) -,S(33e81e21,dcc7670d,c7f3843e,4dc8be3,10160bed,49af116b,c2ca91e6,90f80d68,e694c1d3,a0a386d2,e6df1167,8efe38ae,9ce417e8,9ec05bb8,fa592906,55757b6f) -,S(9543769e,6899e0fc,bfeb1071,50959827,5c1d0d4b,8a68f056,d8e1c033,1b6a1ad2,700cffd,afc58410,7635f148,72ed1ceb,1c4be86,7f668b16,3f579534,ec9b0d7e) -,S(4f41ccd1,73e62c39,7d481e6e,5b50807e,6ca9b163,e21dc203,a0d50826,7439efdd,fbf98ed6,aa8c1972,d88b309b,ab74b254,8fea56bf,e158d1ee,d95ce77d,c69f79d) -,S(4cfb6a45,584b00df,be3fd9c3,38eebc28,a667fe6a,4651bbd9,64ecf20,645f12e5,2ddfd6da,fe080e87,470fac21,d1255900,219638a2,5e72b12f,5501921a,f614652b) -,S(9efb8bec,d9bba33c,a5e217fd,8fae533b,8e536bc9,1817f982,1f217757,75eca626,661300ed,529c15e,918bcf9c,1a7dc3e1,8e3573b8,875e2f8e,9440f8ca,b0658fb4) -,S(c2a80952,5be7e4c0,b85ab953,ebe6dc5c,f5d3c0f9,e850e470,da9e61da,e430e441,1d2ded36,bf72697c,7da6fa22,1c09fbc3,6be06363,d50d277b,4839c4ef,809d9d2d) -,S(42b7ff6b,49ae822b,f5a16276,4c620b13,2501a1b4,1bf830c,a242e02,3bbaa707,e41fe058,83f0e400,712de994,dcbb5a38,fb2c7595,c5ea8b0,eb90a236,82b71d6d) -,S(ee0bb129,d420b641,2afe1518,55f78f39,e00cc3b4,7ee3b86d,f781f0e2,abb0c28c,f71d0e7a,5a4fa247,67c6204b,60edbadd,54b17455,54ae9099,258343eb,5c0aec61) -,S(1f1d8a07,9cdb3bf5,2671a716,26c503c,77546ce4,2a252e78,9ca487c0,78ef5b9a,c611130d,ae55512d,ea8e8e6f,9fbc3064,180ee4aa,63d1dcfc,5c39e98d,97571c20) -,S(5bda9c06,ecdc9fb1,5926ebe5,5418f016,7cf3136e,5f9317b8,b2912fec,d2a31310,358ffb70,dce1260c,80fe59d5,b72eadb3,89076168,a17b63fe,b728dc28,45ecad7) -,S(c32f6503,fa50c727,66652dec,8e0efd71,edc78973,48061be9,1f847544,df866ea6,67234a26,7a13ecc4,7b09443,cb13f0b0,6a34af2a,20b80856,6deb9c71,1fca304) -,S(5483d511,b71feb06,70e6c83f,29612640,849bb673,896bb069,941cdea8,9489caed,a09a6a62,d3233437,40adf0f3,8d8e4ddf,494d5350,7944becf,bfed3927,d88c1148) -,S(3d2d8f5f,f0b86ab9,1ecb9342,5a6cc246,d5e3c6fd,9c43d047,2d518958,ea322ef,4188348b,4c23ce05,1879cf4a,b71d7608,fb45d7ec,a184c509,c739f364,d955b830) -,S(3a5c3939,29ed6780,5fdffa9d,f936bc10,735ddf03,aab89e9e,40b47574,21af1dc0,760b1919,76752916,2ac2a7de,22975c83,44dcd52b,a945c81e,dd8224e,90a7011d) -,S(a3d522ac,7c1cc06e,3ef9272e,fe24a0c4,64886948,3373df90,e5dd484,d4590a83,6f53ba2c,b739dd61,219684a9,50001697,28c377c6,93054795,5661f2c4,ee1b6be2) -,S(ef0b0931,13992018,44078583,62e02aa2,c1437d87,ddb95d42,36751445,d8e8180f,73bf4407,8d184772,7d0408cd,f92f8c74,2173520a,41971980,1b9c842b,9486c634) -,S(8140effd,1498ceb9,c2211899,161185a6,a770c15c,d1ca3e07,f26f40c,6d15da20,4c74f3df,6d2db7f1,be68b7eb,2162f03b,51c1102,a02dc3e,45fc49fd,22a474) -,S(3445d720,8e089f1f,93d32f4d,3fd6fd65,7603c7f0,378b74,215a59bc,ebe122f0,6d41035d,fdb54ef3,3a3c8626,f036e1a2,38da0637,e82953d4,b63e23a4,890b6d5b) -,S(e14b2a5a,6235369a,1d1933f9,7124cde1,789a366d,5fe6ab9c,72c23d43,f7a58cd7,216f06c5,2f63c102,6cafe6ce,58a9e589,d67a9f19,625513be,44744d0b,f9fc8f8f) -,S(6d9640bc,8389bc44,fcd0b2b3,3c088170,eec93106,67348dea,f8f3e92e,2d891e0b,4b4c1485,6e42db64,9fe04759,a42887fc,68b5d4b0,8161b31a,1852bc41,7d04227d) -,S(272f1404,5c461f21,3f67cc60,d7c03b1a,fd028a05,b9e06324,62a0afce,fd9b2916,98635ec0,c0b23538,a63f78d,800eb0df,fd6b7583,31544b1e,825cd433,ab348416) -,S(a8c99928,eaae745a,631250be,cde1ce3a,4152334e,de916257,681329ee,1f3a07e3,4ccc2686,abdf3f7e,8e1149aa,5162fed1,24ae51b7,e61e4620,9f5cd611,e7351621) -,S(fb024b33,7f93d565,899be686,9b1e4c81,1c660d50,fd31cef,fac38600,d8975409,339686b7,8bff3c95,7e8730c3,9457966f,ee562ca2,89d95e12,7b072f47,c4c7fdb0) -,S(e0e48547,aa613549,773ecfe3,691b84d8,a6cb14f9,ce4494f2,35187057,28562f9c,60b6dd8b,56407580,52748838,9396004b,778609f8,69f47676,a6d76eef,dca7b307) -,S(bd6c402d,378b8b53,9f74d29,605e1b0b,ed9e383d,dfec2169,8076ef59,125d16e4,cc3aac9c,bb761c7b,3776a8f8,c8c6d2c2,a276924b,79510f10,75521b22,9def2c24) -,S(e6919231,eefa4f44,144e2c55,4f695235,d5886cbd,e150aef5,52c217ac,5e451c0,e74ee1d4,d34d2612,b4d56133,c2a11cfd,73a888fc,6927f46b,c2aba9ac,63b1cfa7) -,S(1a9acc6a,2a487874,4d92ac5a,328bdb3a,37c481e,8c145463,f9cba4a1,a03d03a9,ba6069a,960e3628,fae22422,47fe1f5e,df71fc81,b49b5ca1,26a7c588,fdf0fb10) -,S(5b52bba9,2e5fe301,f2c4e939,52db99b8,abfde642,3d6da8d5,36ccef4c,f6070910,108ddbdd,901e227d,118c68f0,a71aed0a,cc1ab1b0,2fe74341,f546ede5,b747ae29) -,S(92c13760,1ebe82a9,b11a096a,73be2828,652b0a4,d7f9a286,f1338a6,b1e05242,2e3e93fc,2dc6d0fa,5d43dd57,85f6c79a,51a588bd,d14e0275,59fac06c,a449d7c) -,S(3cb6f8da,79964c17,73a1c749,e89542bd,94b4f279,f6061d69,a12ffe5f,1d4318b8,42e4c1a8,b4f45ad8,dc23bd02,faee2956,72a77771,6e6b1d54,d05ba413,6bb11956) -,S(5fed6351,d34518dd,111a5110,50de0e5,3c60a14d,9a80183f,66415145,bdbf5db,6b79a590,de07a4d0,b74140b6,49bd8375,da77e01e,295e76cd,56a6588,7746c3f6) -,S(2b88f0a7,81c384f2,b7c245d3,7c061128,a14132b1,fd0fb56e,7d3193e3,d95d3840,f787e7a2,11446e57,655b6453,c2244974,c1632bb9,4838a981,bd4873f8,89a0e10e) -,S(c7b247b1,5a3f55fb,35b0ac3e,1da36719,18507f94,e988efd2,47bb02d,83293443,4ab40437,34c65f11,236b6ac8,bc27c548,c3c8e5f6,64f3cb67,99e7b8d0,6db85f4f) -,S(ddfda933,8dcb9481,5c08a20,12c137e0,45df69d2,121d4534,4c6aa375,e03647dd,e95f79fd,2a116bd,5972e93a,c58712d0,95f91255,a46fa091,bbcbfe5b,57795c1b) -,S(dc8da645,5084b105,6c7e3233,b247e87e,9d15a6b6,677f8c29,da04fefa,371da7db,c2a345a3,fde3ec03,f6a07fea,8bd7685,8fc66d28,6637cc80,93132048,441449c3) -,S(f53f3b26,c5fcbfa8,f1263bc7,a6439056,a31547cd,3a8c795b,8e355482,d1ff5333,113ed45,e664b9ca,98d88f1d,a17c4fb3,5249e8ec,7998b1d1,bb68be3a,e6716ac1) -,S(648d23fd,c6d4b5e,4ee1d647,7d969df6,7d754686,9313ba39,1d89dc90,b646cae9,d035e045,239375d3,4e6ffbd4,bae0697c,9b336454,3261206,15edbe28,3e18962) -,S(92e6dd0e,5dbe580f,82473f3e,dd70b343,bd51bde2,b1ca91cb,1c483fe1,3c2839b1,cd90dffe,a5447bd2,592d1a46,5a09b391,a61ab01e,a10c9201,5ddf4614,b39577a5) -,S(1315e58a,7616ef8c,fa223ec5,49415a54,eaec0583,6be6fb78,2ef4ee60,f49f687b,729e0100,802d60cb,c54e1fa4,5dac72aa,2fe189a1,737da80f,1ac58426,d7e1431c) -,S(3c8a9799,9857fd85,e26b284,a3554e51,86b001d5,e6d075e6,c9402148,ab3e2a3b,464f0492,acc720a5,59487b3d,60502067,a722e915,a10412f6,d6c69dbd,28b25977) -,S(ea417230,cc94c5f4,436b37ca,e6f9ace1,bf3c7f8,ff03c879,f862ea76,127591c8,961238cb,8d95d50b,baccff1e,b9cd4040,6f4ec475,7026b3ac,e916067d,85a4faa6) -,S(8eccf9c2,f271079e,329a8c81,62c98af7,48496ca0,b0c5840b,ceb19a15,361a6ceb,3e259a19,165bf1aa,630c6a7c,52f37b29,c8ac5239,a132fa5b,b53d687,b17e56af) -,S(32f0fc83,b3503a59,6873c34a,b54eb6aa,7bf3d913,842cd556,77f398b5,4f0f296d,d4736d6d,906f78b7,62eda345,9cb5f7b0,311e50ad,cc9a1e26,655d8ca2,fb81a811) -,S(b7d63110,77c83a8f,a43c171d,a5ff7cbf,e4fa4cc0,b2614a9f,63831836,e0d7accb,6095f640,56441552,a8ac27ef,9c1eba64,8b84a5b4,c19237e3,5e285ebd,796be9de) -,S(ef6c904a,22df4fb0,a54cd74e,6563e56d,588b4f8,d6926cf0,6c32694b,be536954,308910b1,44cd37a4,e5bc3d3c,43715e22,aa7a0492,e0e9cc9f,b1095a22,65dbaa4) -,S(19e13bd1,e62825bc,acceebf0,b48e17fa,b375241e,6eaaae27,672d7ab,22941a6a,6f22c329,7005bc1,155308bb,dbf8ccc2,855ea666,e4af3bba,d3e3c90c,28b613f7) -,S(57d9bcdf,10f2f790,79349ae4,5f2980b0,9a98a7ab,d792a5df,967b7b11,1c8e9420,bf665de1,d9b7854d,e34f8fcb,1cc027b1,42ebfdf5,bfe4e65e,b5068a72,9a65db68) -,S(37bc6685,7c3d5e8b,878874e,3d1ed324,bb530a21,f13d057e,4e3f87ae,3df06b2,15419bdc,764db12e,f12abbea,c1ca7bbf,77764abd,72f5eec8,3a81c452,4c998539) -,S(1b30c5d9,9ca59151,33c012a5,96512c2c,b572e11c,a7412138,7f3658a9,f9c2cec2,dc42320b,2a0dcd0c,5404d842,17af8c9c,2344f751,16a5d691,1db0590,5ef39697) -,S(96831db3,50c55ac,dd329f4f,85ad4a5d,e6e89f21,85b93e65,b8db4e1f,c1efd0bf,86f43820,fd03739a,d0e75ef6,17072f2c,82bd8bd5,a1f8cef4,55e49ed9,cfd47837) -,S(cd2f500f,aa1f04a5,58309f28,f7acd542,bce7999e,a17cb792,66b93cd5,44e3d8ad,1f977080,ddfceaee,97c743c2,4815f795,27dd1b05,63ef009e,92994046,c8dd8c29) -,S(60392a7d,237c9e27,a3318ff9,d3552928,802f519e,60a783e8,ff32be17,4ad01c08,eb7f3147,df91d1f8,d8994afb,df297c44,88ae9e1c,539fe065,663d856f,22893fdc) -,S(f6cf77ad,df6ab73,20d68fb,9f3c1d7f,d8abb679,179b3c90,d22574f9,fa37ee9a,8ffa29c3,3587f716,6b5d513b,7df76311,77e81eba,1cf9b523,280c778e,2442ebd1) -,S(57c8015a,f542c514,595b6f4f,f11be2fc,944a0ea2,d26a4abd,1807142,da7cdf7a,b67c779e,80153cc6,7b6b32d3,3a3754dc,ffb692bf,d16e3e3d,2c9c673e,a8b05da9) -,S(7fe08558,ac184922,ffbd5c51,cae99931,2f58a17f,bb643b4b,fa1e419e,6b4fe462,7600477d,8bbf58b5,36e7e9e4,cd595858,7268cb5d,1599079e,5a88fbe7,79ec7a11) -,S(2e16f56e,73b39bef,d729b87a,d8e7c4e,3d81095f,58be177d,87bd9f3e,dd517b75,4ce271ef,57323a0d,baac950e,668f0981,77aa59f0,7a0211aa,69b4e417,375fcb7a) -,S(a4d4700d,456d7802,be781f66,6ca24a68,49200de6,d2dd97ad,9c2eba62,18ffdedb,c099f86d,e7ba0f0,e8f0e762,8864a4d8,9124aae5,af12f6d5,efed434f,c66e4532) -,S(b4764d50,50119e3e,a316c921,91e57ae5,a2327e74,187f145d,c048c199,db3fc059,e39be8fa,cc272129,3ec831ea,9016a188,4f127070,4fa4f092,c2f3d56a,4798653c) -,S(3e686ba7,d291abf0,ced5b352,e84fc696,c29fe123,aeb82235,5031931b,e7e2d0e,7b35c0ab,7cc3c81,f84caf9a,9321b9b8,5a889b07,98c9eed8,8c7dc4c1,a985d266) -,S(d7886f2d,1d4c70ef,c5961e56,33122317,58400105,288d3346,db49407c,d24a46c5,da645ee6,17c46024,b2e25903,d4d7dbab,c5ef503f,814f23e8,68d94040,54b9efc8) -,S(7cbd23cc,14654d40,5aa57ba7,1e375466,cea867f2,325db475,d3a7990f,ba17a40,eddce5af,96e66db4,b985541e,e638ecea,88d327f,edd37039,54ce5a1d,d2dcbc51) -,S(54626185,c279e1da,eecea0a9,233c2190,18f877bb,58614a5c,5d2b9894,17eb9795,6507ed85,dc8f8454,bf96730,5cfc7919,8cfb07f0,dc64b09d,928d0b86,e0e9b6f8) -,S(edcef155,1cbec2ce,2bedb20a,addabefa,59e68cf9,e2200681,89285c08,563c32e,ade67143,75592853,c296ab45,bcba4db4,bed59efd,9df68b33,b03d7a3d,be753179) -,S(e027a953,ff6ef9d3,f27db47f,bc91db7f,6a30bc5c,c834add9,9cf8d086,23380cd,1e6b244d,e18ad020,8e52d174,ac452a81,62eafc80,975872e4,c7e362da,cba2bbf5) -,S(a5006d68,db980242,54ea251f,3787d527,66dbf92c,aaa20960,e17ac6f6,72e2b2d6,a1938d7e,e854dd5b,94d98766,c0f74723,72d1e6df,5cd6dbab,fa63faa5,6a0b2b9c) -,S(327075f2,1a1fd9e,da69adf7,32995919,dbb02025,ee504e0,3d5e5066,8427be11,41a57eb1,c32e94be,948ee335,6d855fa2,611a4ec2,4519adf3,2deab381,6bc4debb) -,S(97e1a5c6,66694bca,6b10cdcd,7e95f74b,9c87ac04,c623799a,c1c7959f,1a3363bd,3cc9a48d,1ec7561f,7b72bb6c,4d671c25,56689498,42546a9,48c9b927,c8ab5e88) -,S(450fa640,a7374dcf,d11bce28,f4eeb4ab,d0a2d868,9f6fda04,7f790ed3,b0c07a21,eae88298,dc17cfa1,d482a1f1,70d1dd36,aa35a56c,7eba231f,c4c3ca16,efa77f4c) -,S(f5aa7340,fc0a66a1,2da09ce1,f4094240,d81fad91,87e944a8,a7a1ef4b,9e0a6559,1255b3da,9ef992f1,c62e7738,f84dba74,899d9810,9db522e3,49ad9fc7,2aeb5017) -,S(6900965,55197836,a7b23841,97fbd75a,8857ac8a,8b14ec8c,90cc94a7,8a42f1b4,1dc181d2,38c976d,b4627107,2be05f32,952b5bb4,e9ef4710,f1bad8c,171b027b) -,S(2b1aa05a,8ed84136,7e99f377,bc3760c3,bc3bc0f9,33555e87,8ff2d212,c3f290aa,47b25af4,1eb8bc31,915f5896,57f368bc,35e9000a,cbdd0a41,7b267e58,cc13e280) -,S(a4e6b69c,a18caff0,d993540d,3005e5db,454b1e39,d4c81a7a,b5315d25,d052d81d,7cff2103,9c587904,a42d78ed,c2e7a6ec,df4fcb21,17c89822,36fadc01,a15d70c5) -,S(ab44bb96,c74fca4b,3e39cb0f,d9dd7795,f728e1b2,80a7cfa1,7a36916f,b39d2582,59d91ba4,519fd8cc,9e773feb,b1915967,7edc0dd8,1e794ab7,cb76a2c9,9026f5c1) -,S(83b0c85b,3fb9c3e4,8c96a31a,e5442288,93472975,5d42fcc7,715dbc23,9de332a2,e99f5640,fb620582,fd833b34,2f086800,9652d739,2d6494b1,e36d301f,35a6da6e) -,S(ea45313e,624ecf81,676911ee,500bc0f,e5bd10f4,40e04788,41eb215a,ef954537,4ab8b00c,e2359cce,203bde53,b9e8a454,d5afb101,4d0b644e,81ad1313,6c0c7445) -,S(936c10e4,af823d96,9f7f7a26,98c927cb,ae6d609e,37cf7412,ac4cea1f,51a3cd4e,46f72bbb,10dd850b,8e3e5bdc,f0359f6c,bdb9067b,13d2b60,bf68e8df,b17b7213) -,S(436a5d5b,61aac3db,392cf8e1,36a89b31,847bb116,5d1e296b,36c90d60,f2e9bfd6,f81e688d,ae67cacc,1978559c,84a90f9e,5e342bda,e73647e,33655686,2f36d68d) -,S(9eb95427,3fe789a1,3a24b929,e54f6262,d931a442,2e61867a,abd84d80,4b315d7,38bfc192,7dc0e640,820fba,8effa82a,d29f204a,fec11c60,768f95a3,4d2ef59c) -,S(3826b6f5,87ecbc0a,cb6b4328,a00f63e6,ecb77a0d,bda277a,e6e4ba5,fa280d8a,d9435fe,dcefe69b,213e6eb9,eda63f89,db35e293,8ba3d6e6,57232f04,3a4ef271) -,S(a348cd11,ae0ea1be,3f993bcf,84364b9f,4dbdceb8,db3cca21,cd0f8ca2,4a1dde2,1fc851d3,db7cfaf2,6a1c202f,212b68a0,7078ebd,6d6441e9,1d1d4884,1c83ac75) -,S(bfe15639,237fdf3c,4e67646d,724264e,5d70d1e7,3cb70205,3c4e9a06,2bdf7329,902b37e6,1ec5e59d,9c3c09d1,d7767483,345488dc,e492e3ad,f12d04f9,2b5f88e4) -,S(e2fdb14d,81a1b6f4,d40dc346,c8205821,2642ae10,2707e944,14413cc9,c03dfa5e,3011b4ed,846e8551,6c66925a,e7676062,131e37b2,9b00c408,6c60a3e2,3488fceb) -,S(bbc659c6,8f476748,17663659,db4ac222,cf1119ea,ac27c38a,535ddec6,913c7416,1f8b6ee1,9fdb512a,fadd13a4,d3fe13b,48250120,975b8c7a,47798267,7954b954) -,S(65bd2a02,9866789b,dbd6f743,af85a789,ce9141b6,fd9ee056,cef4de8d,a2505521,32dbe030,1cedb7bc,5d5644a4,6c3e6c56,990b184d,710a770c,6b65f39d,3378f5a5) -,S(1ec0e6eb,8382cf7c,24d75a49,fc0f3724,e9318d90,9e05d406,a3a5916b,2278e981,e50e129c,f486bcaf,eac8ade3,c697debe,fa56ac06,337cd9fc,240cfc2b,3415715a) -,S(7390af1c,203da259,9e1aceb1,ea101628,c0399c92,33658d9e,10dcb10f,63a9eb8c,7d215496,60647b09,d7bcad45,1debe7d8,2c3adaa3,39bce418,320e0df0,977c3126) -,S(99a51469,7b913764,783ff7f3,7099cc45,127baf1e,d8931eb2,b4b71e81,6a1a533b,49c0d00f,7503770b,fcbd57d,bae748fc,809d21f0,8ea38d4c,8a288063,a7e2e8e4) -,S(e4d6e0b1,3b4804cc,cfb7dbf,ef1b7026,320ba2e0,c4fc98cb,f12fad65,8a0394d9,aeb0eaac,73a006fe,6a75ad20,3e0ce2fb,af5fc3dd,81865b6c,75075d36,3b761a41) -,S(488a4141,507ce5ea,cb3e1c46,ad23fb3,1a9aa058,2b553459,d885116e,19fe1a04,6bd6a066,43ef8c7,4cdeaf25,ead63b04,e82f8073,a5fd904f,d7235f4,cf12bd12) -,S(c0ffe24d,ed0ca54d,1ad1c2ff,d2dfbac3,2cb65b47,ca42e8c5,5d2c15d9,67babaa1,d15cc63e,29c54df2,19dbbba8,8df7011f,a0a330e1,6756567d,bbd7c6bd,7e7e9289) -,S(336d9b02,6c74e25,9dedd36d,d8fc5ef1,31b05d0f,f20bffb2,8305b923,767780b1,4aedacfc,9886a707,aebe6510,e1bdb89f,2b1b6461,1471fd1,b055e7f5,414e647b) -,S(98353eb9,8973a7be,3bbd3711,dc7b86e5,9a2a175a,ce8464a7,6aece2d,2dcf04f,a877fac2,27894a43,8f610887,305e1c12,8e45b4a4,3d6c596d,9807461f,aaee767e) -,S(cdc35e1c,17fff9df,63639cec,b54fcb0a,71c9fb77,c38eb905,3f37c361,36da1e61,a8ccb6ba,fe917260,df64f0cc,dc14a31c,87ae559d,7d629778,2bb9b668,9494eace) -,S(912cb1c1,5e62a0b2,71458409,39c06f15,5d7407ec,526ccb5b,5159a934,80111941,584c14d5,1723c447,cd0cecc8,6c70dda6,6fa710b9,8348f5ad,bf4bd587,37049bf6) -,S(2145e17c,7c1e8acd,99eec6e2,cff40341,ffd19568,9800d02b,5ddce693,c3bff3bc,3b8a71a2,40c0b373,95b0e9b8,99da7bac,a5c43088,afafeb68,957bff4f,7636356f) -,S(e4a09336,7e877272,2224f7e1,d03cdc85,43e0910a,20bfc4ab,3aa2ea94,8d0b1692,24b1ec31,33146f03,8eeb8315,afa6e34e,898f48dc,af7d0f80,328155f7,c2cf846e) -,S(fdf526dd,464d459b,b7f387ed,46402875,2b1390d8,4006ebb0,f579b36c,d328db40,4396e6c5,679216d1,dd2cf776,61264ec5,9373269a,a745c963,14147c0d,e53a3987) -,S(6c85c16,b3e37273,509933eb,caddf3f6,52ca4c49,4e751da4,fab5bfb4,ec729f86,9b530fc8,520b807e,5e649040,c5de9929,e592ce99,1b9f9cf1,21766f16,eb648d6f) -,S(4fbfae3c,596ee2c0,10c98ce4,bde00cfb,4e7da2,25583203,feb0c791,2ce28e58,fecf0504,ed0e364b,95edcfdc,ff50fd62,396b8a65,83bc1799,3e73557e,da6ff099) -,S(9bcc3b7b,80171179,3b683c2b,90e9c811,97c1d7bb,d3c281fa,1503513e,778bab8,da2eac92,878289d1,a77825ab,9859baa3,a887f009,d7d8be9f,3b70b917,41bc0b43) -,S(4415a040,e70a3b3,f5a95695,672d1314,855b0a26,3b5e3c8a,24e02f9,6b635150,d8a53b8f,cf55a9f8,81e92160,39afd5c5,6843ac56,39f3223e,c58a5869,da3986be) -,S(55e759c9,cdafbcf6,a38988fc,be203839,b617b536,2d537092,4d2084b7,45b2341,4a6933ea,ca8a3405,89952483,4a231585,3c1191b7,42eb95d6,cf7f82af,f931bb95) -,S(21021f25,bee23c2f,a57e072,bdc83e09,8d115358,adbde4b9,5ed63488,5540e9c8,9aef5691,a7700eff,7c42c98f,8dc822a3,4ed8dc1c,7f8648d4,ba5bfe3c,f9a8c9f0) -,S(2b4e311d,dded1aff,edff3c64,10d40b8a,c70771ef,6904e4a7,a28c7982,cdb376d1,145c30f5,6b255b07,fe43d02,b57f5b96,48b25dd3,6c792575,d20ac730,d709b05c) -,S(5190b21c,7e166100,c90dbf5b,e05d25b6,5ed91caf,904b091e,8b98b5f4,5d5378b3,b83cce47,1fbdc5f8,b50e3f26,8be0d540,1826d26c,216c1166,4040b4a,66650073) -,S(2b211ee4,54c65c0b,3647c7b2,87608189,88b1b009,77d016ae,1f2f4030,545b56f7,75743959,17d8fc1d,571a2563,47a61288,fff74669,b863f506,f9b70ddd,76854f5c) -,S(cb30b792,b41e0aee,3478ec37,ff6ba66f,a3caad4f,9418e1b6,d4af94ae,e64134d4,45571ade,cb3a9f4b,922b8b4e,c0d1c728,9142300d,daeb08e7,71b1aab6,228358c5) -,S(f4e437a8,d2fcaa16,e9749d07,89be67b,e4687952,7eea12e0,65c3cd32,4e4bc6c,fb52d28b,7e81ae8a,30de51f8,bdd0ee28,8e7647fc,392249c4,3449e62a,77ba97c4) -,S(a0a676a7,6a2a19b3,bc6a726c,193d9df8,ce85a94b,cb678080,545c53cd,df50d518,647fe8c6,b1b7bd21,b9816e5,aae40700,41198d68,a3c9bfe8,e437fc88,8f190a71) -,S(15dd4fea,d7f39428,b10544ab,1eaeeee6,75a2ba5d,15d8971c,7860a5bb,b7ff7b7e,89955ddd,5fab2154,7d231342,7b7322d2,53924d1f,1b1fa961,8442c471,9c38445c) -,S(a806b800,40294b47,6377a188,ed74dd9f,1bdea3f,f72cd2b8,850f6321,930ca522,4b6d7365,47d8b1af,697f1fa8,8ab3bb86,53e49aac,618910db,9c6bedc8,deb97213) -,S(41e3723d,ca086487,7a36ff9f,6e431ee8,58a983ac,f3c0406d,f31ba3f5,5b9f148b,8ab166ca,f27c58d0,1a80b136,dcda9fd2,2753c52c,dffca007,9139481d,3b8392e4) -,S(63b8a0f2,78558c89,d9ba3e58,70946615,690e0447,f8d4c953,ea00bca8,65bba3c4,321fad41,85eb8b49,53a95da0,f004c80,8c09b297,728b3a0c,2d300b32,43cf787f) -,S(62beb7f,aa8b0d3a,505cae5f,82229a61,c1ca21da,d2ff856c,8942a9a9,b14c5963,e3d9ccbd,7120c27f,5cd88655,3efdc43,a36f4c02,2f5b7045,1ac9d7bf,56bffd4b) -,S(b75a180a,f524b89e,be5d79a9,92f0313,bc133fcf,3cb2d99a,c65f2c48,1bd20427,e7855056,b11cc054,d37094b4,1e62dfb3,6a636964,633eed48,c39b8225,4a1d2747) -,S(4e5bbf6d,5298fc76,97ddf9cb,e4d063a2,6b51f93c,eef032f2,f03eed04,fe4949e9,66702686,40cd9dc6,54514a19,ecd80930,1871fbbe,99254119,476e44e3,16a12188) -,S(a9778c3d,f509f069,3baedb83,6d5fc1aa,b78e86e6,dcb61200,74bf6df,c173237,33a9c991,86a0f913,95fa0e50,d0a85d65,9230a41c,8c0be5d6,90ee013f,29d0cab7) -,S(f1b3aaad,16664be7,c49790bc,1a4936ac,757fb3e7,26ccbc95,cdb7bb63,cf570449,d1dfe1cb,ea3fdc10,3f218398,14626782,643426,24d3aa3a,52b0fb4a,7460cc06) -,S(d66cfd3a,b015d585,6a436ad6,a4cf019d,9563a05c,af4ce2d0,6988a4c5,9349f598,5ea179b6,d097d9e5,663b7305,6db940f8,d8e91bbe,fb951756,d07cf6fa,111efc4d) -,S(a532a4f0,924b5d13,bef0f30a,a982edfd,5d87a16f,2c0d8470,ea8fe3bc,da0ac7aa,c2e62c19,ca4e3481,3cc3de70,df50386f,74fd1efa,ac6217ad,5532a927,1f8d5c1c) -,S(a9ab2512,5df78835,ffbd08c0,9e07b632,81ebb3ef,3fe2fb3e,1a3e5ff6,28439b70,58ff55db,56e015aa,9aa43698,acc35df1,f2eaadb5,4e950c7e,3501a5b5,85877514) -,S(ce058f84,90813dec,c184dc83,915c6d5,53df174a,41ed6521,f2cff46c,460466eb,414d38c4,58817414,5a815a7,84f4f71a,28237741,97b37d47,c7646b2f,8af3e745) -,S(991fab65,30a2b36a,ab385c7f,31644de9,afe9253,9db603d4,737beaa9,6e406299,2a29b576,77c544bd,f156dc9d,44da01f4,5d373cfb,7ada94df,4f82af9f,e48eed57) -,S(ee6cc81f,bd034eef,cc841921,5ab4817,ddfdd2fe,a13f1e14,e91c3f2,af715d8e,b8f79ffe,48c3e965,21c7358d,ea5cbc04,df8fd847,a97bca3f,6893af3b,e386d8be) -,S(66a2d372,d6426657,5544d5cc,5141e003,16ff2dfe,813357a3,c5daccda,159c5ef2,b57d2d6b,91c6f48d,389423b9,af265e04,780000d0,598229a0,5bada3f7,4dbc8929) -,S(20a02dd9,f697de3a,15043e73,fc7f36a3,7a5798e5,acb4cac6,adf5c692,3a421da9,1e6cf100,d162361e,aa6ab61e,711e3dca,ab4ab538,2fcc6b97,33836c30,cdcf34f7) -,S(a0b8ca43,7818e81f,6be98b15,4da25331,9f92b79a,1ceda110,92e3a303,cb7bf552,4541bceb,f447d990,50663ca1,10fce2da,218508e6,48b630ba,a1abfe5a,3d543be6) -,S(51714ead,73dce488,7e15c25f,b5cba9cd,e0d5018d,db5b8ffb,9e4174eb,1cc52c63,47b794a0,82ef561e,bee272c7,d66dd201,a5c24831,99977097,73b9141f,9bdafebf) -,S(18ea2763,1fe4de07,3e7c41f6,a9921e91,7da195a4,13417a2f,ba74ac2c,d6451c59,398a0b37,fff6bba9,b33e0428,e8d7c93c,d31b3b83,2e955e6b,106aed50,d64df316) -,S(e1d58b4f,c39e1834,a61ec341,acfa985f,c3d1f0a5,9d75b0cd,e8b9057,17c5a87e,1b62ee02,15fdfdec,8fe2ab3,bb7f99e5,af82153a,dd9c7f2,cf299225,9c6b3c47) -,S(39793917,30d3c125,7dff5ba8,eb253dc3,2c19c541,11caf9a3,bbdec3e7,716c5a84,d6a1fb50,189f36d9,912cded5,c851da8c,be7b4ebd,41c2a1e3,f78aa4a7,f5f18015) -,S(49b49e4b,601b406d,381dbf88,8b02519e,1d57360b,24f2aef1,5520f17a,5b9ede88,fcf3ccca,2f2d7b3,59be7be1,9e45a3,a0a76e9c,d0e42fad,bff7e772,f969a38d) -,S(2cd8190d,b42f36d,20d88548,f0ff17a1,d64e38a1,2241e4c3,2bfdaa45,28bdc871,f729c369,22141490,5aa84f45,e5abfeae,2fff780d,2b16aa67,77ef59b,68259187) -,S(1fd0fb11,17385466,2da0cb2c,f1f9d19a,b5b642ea,45d1c6f2,30808626,5e41025a,3136a688,fec60820,abc7825d,1c7012da,94e928d6,dbb6c08f,5579181e,469ce0e9) -,S(f08e5f3b,d7f8b5be,18648a0f,5bd844e5,3f93d5bb,120d3871,7de4440,7af3a141,3dd8725,9067eae1,cab61bdf,cc94ea0d,bf7ea1bc,df1d289f,a526e15f,d9902fac) -,S(a0033c06,b997fa96,373a046b,b5c6bdd7,a0584cf0,1feec5a5,d3f5cab1,1c5ee207,eed61931,aacbe48d,708c2cda,2208d40c,39a577b6,3d4ffa17,d140a8db,c3e268b4) -,S(77deec08,68bea671,df01e29b,117791a7,83ff8f70,4426bb1e,1ea91b6e,62c16f70,b908a228,ba8f73f6,3271ae7e,f19f5e9c,fcc1fe27,c0a224b5,dc426b00,5664861d) -,S(2fcded5f,fe2f10ed,1a1bd1fc,63506b3d,994a03c1,c188d960,5fd5aa1b,a9aa72b1,155bebf6,f09a86f1,d20d7c12,e12a0c66,b4df6628,4ff9d45d,3fab7d76,6bbefc6) -,S(1f0c0b2d,fdf5e733,abcadd0c,9ba47c09,8667f8ff,77c2a904,c8310e20,995db3ad,bd711bcb,84cef55f,5139b761,33268489,70f63182,85ccbe44,8efd7566,577bc566) -,S(b4a8544,e7162c44,60dbdf3c,5edf654f,d603fded,4aa885ef,465ea8f9,a37dcf8,53c04391,b3f2e8b2,32e27b,2292cb38,99f8ee6e,dbe1934c,13938a3d,203c62b2) -,S(df0ebe82,dcdeb735,38f31cdf,ad307397,d00a900c,6d94221a,9d85b0b7,2c5bd68c,c3299639,e7fe2e55,447b869e,3a4acf8b,4a1d07e2,d70701c6,8a2f4733,88decfb2) -,S(eb04b9b6,d1c38c33,e1eed101,fd28f89e,f9fd460e,5b379576,ec7c9267,3c101c0,4f26d849,7f47f80b,2b13cab5,782d6e9c,f5ee7548,3974a4eb,8d8f28,f5e0ee9e) -,S(7bc9efe2,197cc6ce,ac94b37a,cab9865,7db4ee0e,ea7b9cfa,ce9f71d0,d3294334,d931bcad,52347906,a941d940,4b5b3a51,ad8fb493,1c15c9a3,7ff782da,5da72013) -,S(8922d1e8,f4bd52c6,4bd0c10c,66a3e8b5,1321dc50,cc964844,e0a41ad3,b73e0b9b,2b643cf1,7d23e21e,890e6abd,3337dc52,61c9eec6,d5edc318,2a02a7a3,4a41c431) -,S(42f2ede3,3a9312ed,22f6a842,ac46801f,139a7da,77ca0e9a,cdc19d1a,f2ddcc72,50d45bcc,715c985c,b9260edf,fdc8e342,ab95360a,6bf4776a,c70e3497,8f26f99b) -,S(7bdc9720,1862feb2,58879255,726b5e4,627549f2,92936ea2,f3b27051,4d6761c6,700eb72b,7f77adf5,76e6f0bf,f8406660,65372ee4,cad6269,f1ca8541,2da4fa8c) -,S(b9b527a6,4bf549bf,5e42e0d8,5228e1a1,f79d1647,d2102306,6b6d98e1,746314cf,8e1b3464,2a721f5b,93a2a2b6,802f30ea,e35b1539,c6d84eb7,499299aa,aa0cd93f) -,S(b65de529,34d47765,1c29192,93ce1177,d187c431,590d2d74,978ac258,75e3dda9,3d6fcbe7,4ab9b5ce,b3dc5535,13036457,f0755509,ecbd94ef,324e36d6,3b9fa529) -,S(18eab632,608751e,af3604f6,a3f05611,a036edea,3405aca5,c2e66366,ce7c6b9b,89eb07bc,94671119,36e11f05,79f91e6e,ccd42605,24bd7dd9,9d12b365,95074c5) -,S(a2611066,4a479643,909a1606,596d39db,c7502ee4,a31b40a1,4eb1c60e,ead360d5,4b45d74d,88025576,3262d9fe,38198218,85721a81,f323cac0,3e87f372,75814901) -,S(789454b1,2c108537,a019dc58,35cf25c9,c77ac0fa,f6001959,5da9435d,3c08a8a7,6bee870f,ed2859fa,cbef4337,8a0bd760,8841da03,252687a2,591ae0bf,a5829041) -,S(1977c206,fb4f65f0,11b683b9,c2e0df95,f81570f9,9f6625ed,7cfe25d4,62791569,de76dda3,c22244aa,95ff435e,5a9ebe05,9dcc79b2,75d91de4,67de435e,bf698479) -,S(891f0df7,d259d536,40fe6086,1ac34d7d,ec3b5ad4,c3f56585,189ac986,65f4222f,cc5e0bf7,f538a2a,1ee7a601,1a8d6b0e,5c3293ab,404257d,ba90ace9,1b2de219) -,S(8534bbf6,9262f81e,5926c282,f412b4d3,50169de0,3c5c5e55,c80a937f,fe99530b,fbeee581,e0bb0737,4cc764c0,be5451e8,f70cfc23,4d415cf9,fb08e7eb,557423b5) -,S(e5b6f564,4e7dfd3,7474eafa,354598d5,58fc897c,f010198,9e44b07e,a86f63fb,4368bbfa,68a83a8b,76de7d98,38880780,8e153cc9,b380ad0,b2c6ce26,6118da79) -,S(f9591a8b,11c3e514,983dc5e5,507247a8,46e184f3,b4e38e29,f7c90d4e,6c2b850,423b6436,2361f587,cca4e288,a366a1fa,957de393,f29ff2a5,1fe97a0a,d90ff6b5) -,S(3d3239d3,252f5e9e,ef9eb617,c9646379,7c995059,57bc7821,2f2920b1,ff72384c,1c3e37b6,fc9bafac,e52798bf,695eb4df,ef860ee1,a9b67df7,8f73ca9f,22a2e57a) -,S(f4089723,4b574d76,86a8e855,408612a2,a0a6ce61,c1f14055,201d5c67,bcc5dfb8,6b8283b7,3e72fc91,54aaac24,2565a79f,c3a62fa7,602ffaf3,c7453209,c0a56a4) -,S(ace076e7,aea9c745,f6be65f8,498b8b47,95058ed2,b0413c64,bc4b462a,2e267ccf,b62c617,377fa9e5,eb72ed6d,caf353e2,dc58f362,a994520a,31f1dac1,168b97aa) -,S(70ccbba7,408c6069,3230b848,eadb1d1d,b4e63f33,b4fdf6af,29d6fc2d,86ec161,fc1cd9a0,46d30e60,e4128677,654a80ca,5a4ff338,71fbeec4,d7782c7b,a14d6959) -,S(e6e7a8b2,7c0c5b0c,5ea58d3a,4af5abc5,9e33fcb3,9970aede,7a8de629,e758d372,d40d11c4,c8c8b5a5,d511fee2,793e2c80,b40df3a5,c98bd704,9a8db3e5,c98d4a66) -,S(cdc495c7,e0a02e68,329495b7,19e2c424,7910e9a5,cff6739,117b1d32,23216346,63664f6e,9306c0ac,f29ddcd8,7f1df6ec,d51fc68c,6ce422f0,559205b1,681583d4) -,S(2784e89c,2fd721e0,22ba33,3b824dc1,d0142f19,6f35ae4f,825975d0,7a2fc5cc,ba58a66,bdfa661d,354232b9,b25628f4,5a391e44,f00841db,4a335ef5,dc3b8cf4) -,S(ab699b62,ebcb7380,2141dd83,184ba3cf,c9118bf,f6af4d0b,9b98ecde,b01a2390,5e548210,b71420f6,c5d42547,da0a7ccd,2be0117b,79847e71,a609044a,34766905) -,S(781ea7a5,67ffe37f,b9fad6d3,96dd1eaa,2209552a,9835ae08,dda3d4f0,b75756ec,3c76d87b,46f63b97,e4d48174,4ba664cc,403a507,dacdf4b2,af9505a0,f2637256) -,S(75ab2d30,dd5c0a82,a5c04fe7,b8fee5a3,a0e1ce3b,e20b33fd,39d0bd3e,e374029c,aaf46147,fdb1393a,cb9f6f8e,694c1cf7,30536efa,b5ef921a,72215fcd,61914b9f) -,S(294b6698,37303da9,6d23caea,684ad56d,8712433,d11c7ced,85a10cf8,8ddaff0,af4d7ef7,feb73e9e,a9407fa8,b38bf1f1,e5861bfc,82f9cb42,22fa64f7,9b46f7c1) -,S(d8676aea,7433639f,c9683b06,bd97011c,f290f6e9,1257ee55,ea3c6e34,b824c8d6,710c8876,35d45545,90f3e5c,d6aac133,9017b2a,de71e30f,d71a5b71,97a7456d) -,S(5e4eca03,d90f5ac,2ac4771c,6d86a458,cee71427,a93b7544,fd8bee74,161270d0,44fe0143,b970f8bf,affa6d60,33628894,a93bb4a4,f48cbb9f,f0caf0b7,40c97351) -,S(90152daa,244fba85,fe708f21,29b55485,265c3a3d,dbc761dc,157f125b,8580097e,1694d2c9,200b8690,b59fa3b2,8fc2f613,8a6d392c,48357939,b9435739,83ef2cf7) -,S(67dd54f0,96f171c4,53fa953f,acbf2b9c,daf3a199,732ee0f1,91fb3c90,8c5637b5,5327db43,2d33676d,b6502236,5a338c62,5fd6c4a4,536645df,b36279bc,4ede74b1) -,S(c6496a83,8f95ff57,65a0f144,774cf543,2e770457,55efc790,142df95f,bb6c51ef,cc0041d6,604d1d73,92d86f01,d8b05b53,1177b51e,3a38b8ca,ca8267fc,bcd752a2) -,S(e799d70a,b163bfd,475e5e72,8810d9d2,425bf4b6,9461e9ad,933fdb6f,68c11c74,fc34745f,e29bee3f,9b0adcf7,618c6d13,e504449d,1a272b21,5ef9fc18,14ba8600) -,S(6d3c97b0,151a9011,5032aa22,1183d82e,820c8774,c3dcd75a,cb6f45ac,5d489d3b,5aa8bd01,3d15d77b,8f695d43,8cedd9ee,64b57df9,ee672323,1c2cd5b1,4ad4749f) -,S(86e53e00,1c1e7de7,419cf2d9,a4c6a39b,b96d8ec3,a82f8165,45658eff,a517539,f8b1b70,f2efecc0,cedda525,40663114,c24491ac,266df520,ce475f01,ab44ad86) -,S(a641c339,ac877cce,a9a3267a,78edb33f,75feb90,1f3c8743,47c50843,52a9880a,d88a6d4f,2b275ac5,3c7dc101,b7d69ca5,407559c6,afdc9009,c34a7256,f982163) -,S(3a0153a9,4d778266,4581de43,6de31754,b925aad5,4090cceb,9e013568,9d82511a,f6ca48,94935c5a,7a252df3,8ff06cf9,11154b0d,9f0ac55e,35a33d7a,58802035) -,S(e78024e8,a131c9ad,40526b31,d26e96f4,2c2e51d7,c63f458c,5bec2a61,472b170f,c540a14b,1ad7b18f,23493d9c,edab65dd,3a309204,976408ea,f197f658,9f4e0c53) -,S(7858c85e,8351f0ec,740380fa,b1924668,7f05a161,e2dd87cc,7df13338,a86a5162,cad94344,5313a06f,c382897e,7c444d53,7e658e06,5a76fa60,928d7e5b,36a6de1c) -,S(6643e28,1c5bddd4,35a68c17,965f334,ddb9da8a,d599a4b8,2f37147a,cb0263e6,9f9f9e36,8ee1aa0b,9bc8f928,284968d5,6f2dc8fa,6944ff36,d728b588,a72cf79b) -,S(5f36d937,a286f14c,96fe8f9e,3ea05d56,b3132523,e9a135e7,106592d6,b9b2254b,9d6377c,c8265ff2,dcebf753,ef2fd39e,9adb0e1c,3c86acfc,2e54648b,9056310a) -,S(212eb1ae,93d3a0aa,5f626f26,628503c2,310f9172,461ea12f,b17677eb,c63e2224,51e57e33,347f2016,c738d9fd,cf528269,bbc5afe,f5fd6fa5,1dfcfd47,4b6d1b67) -,S(526952c8,940b9f93,32848145,203ce261,dedb3b93,8e6f277e,9a085d77,35e9eab4,8657cfa3,56df2aaf,9a5fe2fd,81804ff8,1d9aa58f,143fa109,52e4f4cd,85a42918) -,S(20f1750d,ef762812,e4ba8778,c953a2d1,419e03c,b97ab6ef,8f98be07,4c1c099f,d2fee9f5,3e7ad2a7,fb20bf88,16a1ec2d,d9d97b4e,5abc060e,bd8e8b31,bacd485e) -,S(e231a3b7,ea011665,c223cfb2,7f13c691,dbc7f5e5,efb66496,da2936dc,d67ee910,aa645c2e,18e80131,f3e7316c,7cdf13c3,45e4f602,fb17011e,96eb5fc0,bf65d53f) -,S(7a4e4d52,3fd026dd,3daeac35,552e7299,d01aa962,687a02cb,ed7174b6,25c702ad,351c12b6,a7398e5a,ae461204,4cd7c9a4,7d2bdfc1,1f941b84,71eb3304,fdb965d2) -,S(fd2f707e,76965670,67ca5a5c,a0010c6f,9a858967,19a23eaa,5574d1c6,cbf137b3,c45a430c,1d5ae473,31f9b161,3ce55f41,df00e287,9e3bf8aa,1ae75306,f8315408) -,S(c506cc1e,8cf2f4fc,e1011d67,6d304877,6c2ac2a4,f8265373,f3f918d3,f02bb89d,8de6dfb3,74029b33,2fa47f6d,1f7ba609,bea33d6e,2f58ef0c,58641e2,a5d3118a) -,S(2ea7ad02,d9ccf999,86ab901c,3c9cde3c,ad1bb4d7,d8f86eeb,b8204b75,ab5c0369,11222bd8,6d750302,763648dd,daf76947,2b213562,494ebd9c,e4003195,eb0ed43) -,S(ab8cc192,3555e4e5,2f84b421,ba2ac134,f8a6023a,ddfd279c,4c338cd1,9e159c5c,2c48e3bd,cc268dbc,23e9fbda,6c449079,5a5b54eb,54ca8ff5,14d1f23f,8751ee1a) -,S(88fec2e1,cc7c41fa,91b48e1c,2a71089a,c3778427,f2cfce04,c54af407,f5dad430,ccb45e88,4f696653,5fac7a04,9b035c26,dce30666,fb1fecf3,c4b89deb,8b3ed80b) -,S(404587ae,1accf5d1,b42c3127,2ea0cdce,940522a1,c64c757c,11d3768,774b0d41,e8dcf25b,25ae61f4,f7368c36,9b351b35,63401deb,5ce55325,f96a393f,ef0e787b) -,S(8a701eb9,cadea8c0,8d0cf20a,b2750915,28a377cf,bc4d9097,51424d1a,7eb9ab8a,4f045982,82a9ac70,c3c76154,ca98b5a1,265e8b26,6f02d43a,4549cdea,caba5a45) -,S(c2812978,194009c2,9da141fd,b108a4c3,66e15e06,c6d64389,29b2aa78,89ad3d56,85409efb,6670e969,a2834255,dcb1e546,9c9db5e7,6e549afa,974936c8,b75db5c1) -,S(9ffd36b1,c810c843,92bb04d1,90b82be0,f8ea4b4,2baa6129,8adfb810,71d72fe,11e27a4b,a11f0df8,1a42955e,bfa9fe1a,6f25fda4,6a65fd87,1caa3d6a,1b38404) -,S(ac4a0044,bc92b017,cad07210,750eec62,39e43147,5e3feb25,f1c6f879,a5a48b96,41c7c3ba,731002ff,1e749853,344c1f53,f526bbbf,457b4de2,d5f88ce4,1eb8dfe1) -,S(c78b101c,157ca920,b3fc83bf,9d19fc5f,57d8086c,d764e142,24ae4e86,7b06eb5a,1a8d2c6e,b9d660ff,faf5f533,b4f3b8f6,b7a9d7cd,5c29c1d2,deb37f19,d38126c8) -,S(d08f3b05,572348b9,5f3c1c2d,baedd921,c24b0db8,e6d17d13,578e5ae8,77147cd2,27b5fcde,a067cbb,69ae3e5c,90a38523,4987dfaf,5dfe0696,91461e26,762713cb) -,S(40ea043d,5060f61e,b81db0f1,c7c5c1fc,1091cf51,c5808489,3d08c4b2,a5e312f5,2ef11ec4,2836302f,e02719be,259f1536,43de03e,fb659f30,84816a00,1d66b27c) -,S(f9d104bd,fb53b4b2,de8827b2,8242eba5,17db73f9,dbb1eec3,9f184ad0,358362e7,d7644a0b,6c371948,2ba707b6,d7d43f0a,68f4e3c1,4af6f167,296ccfcf,4d771877) -,S(dd276aee,14c34829,4e6132b4,9a05dac,fea5f8a2,41712b6e,5703778d,eff9ddc9,9be617d,5d92eec9,7fede655,39690d0f,4803f760,2b74066b,7bc98353,a5ceb7ef) -,S(8522f839,d5f17bd0,c67d11f6,7f0db8db,2104c7d7,785252f4,c8be84f0,61155d49,b7791951,80311f8f,6cb9b59c,ddca495a,e01f3edd,599f8777,3163a959,5a3ea117) -,S(732802bd,b4f3be8e,fc02a62,4614672a,51049166,4bfce64e,eb2030d8,b6b5b225,7bd4cdec,590eee1d,6a505f92,cc0b25ce,d9022d62,d1155f8e,35a6ab72,46a3c6f3) -,S(1b3641a1,2c4f8352,21e73276,b8bdea15,f5ffcbaf,c4496fc6,8fbdb573,5967af62,3d50ef5,e5d12b7b,2ede2e15,3b4cd01c,b824c32,7a8e1ce,f0fd866d,99664048) -,S(d3034e18,4e9284ff,ed6cbe60,cb66d391,c897255,dbbe8c85,2c79525d,3f01a7ce,b3666304,16ce50e7,2a094b05,85f1ba1e,11172ac4,eeb353b4,8c4f8f99,f9d09e25) -,S(8e7a8200,bd22f5ef,18fa4461,8f4f85a,61c6db2a,a3ad176d,65c3270a,69e9db17,841fe3b5,1cce979b,f87536ed,c71f4cd4,4a482475,19b35cea,dee4b3b1,f3530568) -,S(fcccb4de,29ab8671,d1aaee27,61421ae1,c4af5f3d,839009e8,5dab0b65,60a4027e,a0229f96,203b89af,d5b6ac06,9e977e71,a6e269d4,bea29c47,fa6bd22e,f7f993b) -,S(e68cfd7f,44358180,84c681f0,aead705b,9e74a476,1f99e576,9252c007,e44c8a26,add9c0a7,b027e2ae,42378d50,cf0d0eb5,71229161,8e9f13c1,672121d2,c428f82e) -,S(8b6f0fad,4b81ac16,4866de7a,c8bb3252,63bfe008,b726e9a8,72e0461,2c6891d8,9bad6508,a8d604b7,8088d328,ca27fe13,91493e8f,a6291288,92ecaed,ba4bc9ca) -,S(108a0caa,37ac1949,263178cf,20674616,470f8943,57a921ba,8cfd499b,d64b78b1,68150d22,be05956f,5ffe302e,1ff517c7,9b7c0452,6112b2a7,5a819f64,a265bf55) -,S(fed18333,844c579,1d32daa8,3370a5c6,ab8e13a5,2654a08b,42940284,c757edb6,67bddf37,8395ab84,eba29a97,6952ea34,b1b52c2e,d3f89e56,f839c1ff,36457fe5) -,S(bebfb39d,ecd56cf3,50bed6f1,a4cde24,848b2d84,23518da5,1fb2ee0,90170a2f,1302b4b3,bb86f887,22925fbd,e146d948,5acb2db,a61e751,97dd40ca,2ba11573) -,S(67135aed,2a58d3b6,c4470d3c,b4da7b56,af8d5057,9d28a86c,9c67bf28,181e716c,97c40aab,2786e3ef,dc8f3e77,8f374446,30fa2f3f,53eb040,194809c,8efd6664) -,S(b00eb5bb,9566e5a,cdb09dd4,14d6df03,c3dea75e,90db8b9,c37928e5,4354f90e,6d120e41,1cb6e674,e9973aa6,3999af3a,ccc3a670,112c964d,8aef93ee,e69b1258) -,S(721b1a6c,be8d2022,f09db6d3,ba39b2d9,23337592,de9efbb8,ecdf3384,f3bb73a2,cdb41b62,631a0f47,75ae1f2,e94f8075,4acbb2e7,950be088,5b458c8e,4a05310f) -,S(cb8d78ac,15b12ca,8dd47cde,190c420e,42f60b83,9489bf71,d10a3e44,df8a0837,80be31a6,a3073675,e8cd3846,cfb2e127,abdc448b,1081a2d5,d177ccff,ea96dbc2) -,S(491cfbcc,4919d884,d23f3ae6,6d143e55,37e5c52b,e2ee017a,afec785,6c781920,76321b50,26283088,d344d29c,c4d9f2ec,3ba714d4,edc1bee6,2b17ecc4,56874189) -,S(6ca33ee,48992263,23aed33f,f822303b,8145d146,c5ebc27c,fb3700b3,6ab507b4,96b73ab3,f189d064,1e0a20cf,d09522bf,8c376a0a,9c9dbec6,44e3e8d2,c0b11f4e) -,S(6d1fdfcb,3c48971b,6cbb33d3,822cfa68,1bf602ef,98160f89,97ccaba8,19d842c7,82bc7c4,66088262,5e57c062,96f04600,fa555ac4,5596b769,9c6d29c,cfb1713f) -,S(a3e81699,1cf92f41,a69ac3ca,36b23796,daeb533c,3e1e9b55,c88e3fa9,fea43554,87a6fa9b,e802467a,fa206b0b,45405309,65887df5,786d20fa,25e94832,312855f1) -,S(fc84abd7,cbfbc329,4eac7438,d50b2ac4,7f570e4f,3f2ffab5,71f8c3e8,7dd49c70,7447b269,71356b0,e59b3f1c,d99b6416,589f6c3b,a566c75b,6915377d,a7f73dd9) -,S(beb23240,8fc515ba,180d3125,2eca15a1,af4e02a8,73a69769,53982408,355d1b1,12fa480d,6fa8a9aa,e5edeba9,31b765b0,e2bbe6a1,5eb9e95,b3bc343f,519c1459) -,S(68891679,cffad7f3,19a373d7,1bc02529,a50e63b,60434f13,df760364,1a99eb8e,40b78db7,6db28aa2,d2ea7c1e,86d01503,7736ce96,2e6ec524,da07b5b7,68772fb8) -,S(ec435ad,1ae7b040,fde2f736,e8fb5d53,b42e2fcd,428e9d96,ed401ee2,bb068817,13bf6eaa,1283436f,4a828a85,66c4f795,26860c45,d650fac2,44bbec8e,fc96f9f2) -,S(679f5afa,661f688b,7dfb7ce7,f77e4904,60a75576,6216a49f,374594d0,6bde3033,ff3fffd9,6c254fda,558f14bf,c8f05cb6,c8fddd32,a487d709,4e0fb35c,6f617ca1) -,S(9febd8ea,5dc26e5,fbf48aeb,64307b21,1aa2fc02,eceb6d68,ba89a652,f633be60,c0867bc8,ea6238a4,ad36e785,cbbc5e0f,3fc5dc96,2c778992,72be4364,8e630bee) -,S(d886b154,c534b48e,db6bed69,6dd8f9f1,347b381,1b593acf,e2137c93,600b1601,a4cbc118,aa07daa9,c4e246c8,efeaa3f7,d74028c1,93b77964,f10ab5d6,f75d077) -,S(af8ccbef,c187a3a6,83f6ab6,8ff217a1,96a8e27,dcec349a,b7ee4a74,446e9d47,3ee327c,99880392,7da5b625,be554e6f,1662a733,25a8fdc4,990716cf,6be941f0) -,S(1e9800e7,891c261c,a3451d22,44a54a84,42d33458,a997b365,4a6198bc,7dd3d26a,322f8986,bd6ffc0d,d5f1a321,e82e6b37,978120c9,66f753bd,5669a773,65a215d4) -,S(115c62f2,9f008009,5840dc97,f3a90f30,aae4ffa6,a2d255e4,15d64c56,77150044,4d944c12,7e37ce5e,fd7660e0,1e4fdf0a,cceef95e,8bc2da14,a8fd7e32,ead8af95) -,S(1cb9f9d,acbf79dd,b34d78e8,e51225bf,3f53135f,f4282ba2,59855968,2ae0178c,8fd3a4e3,7a189bc9,421595e2,bcf234e,d7b602d0,855de84a,50c68cb4,bd1a4bf5) -,S(62a15bc4,63e4c167,4bab2a5b,dc991e39,af86d258,f9de770b,66a79ee5,2fbfe357,b78fca9f,d9467e4d,256da69f,e6f45522,d376fe41,e8ebde9f,9f7bde4b,8ef52749) -,S(574a6ce0,5bf31948,31570914,a73bed4e,6bd2c82a,5a19dec4,54b11e93,5edf505e,e7b2e2cc,cbd6f338,f0ea60b8,c1a9a50e,d02dbaba,8bb5cb78,9b281a97,5c001318) -,S(64c6e37c,a3a361a4,baf9ceda,d9ed24fd,c5ae50ab,560e6319,4adad1d5,264084e6,e6e42f56,56b6b404,9c54a07,f35ae004,4b7a480e,8271c8d3,f7996ed6,68116067) -,S(49065a97,fe4a8de5,55646af8,475607a7,71b27746,ade7fb11,55308107,4900fd84,985d689f,67a03090,9ab8eb43,c7b2767c,94e7217b,fbb43342,83485f1a,d70ae7f9) -,S(6fd32ff9,185790bd,876a683b,7e889f32,8500c91e,7e5889aa,44394caa,330999cb,12fe8084,1be1f25d,7a93784e,9c6bf01f,efbd6493,8f1a678c,64497a8c,85d2de3b) -,S(4a67d4da,48189c8e,6ff34812,f7094851,2d6d12c4,26fdc98b,4ebb92b6,62d3b185,58ea83f2,f6e5b777,737c668e,efa71b8f,3e50095d,389a5540,684cea51,7f8150f5) -,S(ea1ac931,d3a92770,5d20752d,b9adb464,edecf4c5,95c20c85,987e1beb,a79f4db2,cf689b0e,25aa9601,58316597,b06fd91b,426b5753,68a48830,9c3f6f34,6722b83e) -,S(8cb35a6e,248a0527,d572663f,7abc99c9,61414af3,f196c6c1,2de4dbf4,dd545c5a,4b32e4e0,47dacdb6,66edfc3f,a08d500d,c43292ab,f36bea7c,4a3952e6,680cfcfa) -,S(247c800c,f150c2ea,cfef8dfb,f4581560,84318684,430788e3,c8d99ccd,d27f21c8,cc82d8dc,914fd1a0,e626462f,5829eb7e,a708395d,db3e70a7,57942e85,1f1d0db6) -,S(6543d7c4,7fb927c,fb0f3566,6103708e,5e0c4a4c,ed202482,c9f48647,33426673,e252b29a,69b4ad75,814ae0d1,631ea750,20bbc730,3fdc819c,88d8f3d4,7907ebab) -,S(c4f11255,d81c33a3,a09da4ac,af5c9c16,d5e759db,2e1026c2,9b3556b4,c388e6d0,e2e636a8,1af48ab5,814e5530,e48f518d,95379eab,186e94f2,4fcd551d,1ca8fd49) -,S(cf186a9d,85da39b7,7383d92a,14af5a05,b082848f,c9e60598,1bad8ef9,5e019eec,cabde21b,c860fe08,53f672a1,64010968,6b49f37e,61cc642,48f455bc,b079e3fc) -,S(e6c3e353,ad69dc13,e595c2c7,a88b8fd8,fe9d1d47,3d45f7f6,be9ae903,86ea8f32,7d3becc9,4f455c1d,21610800,a4985f33,96b5a920,d5ed2b57,2107c28,ac690be1) -,S(3827b3a3,9bcb554d,54695dc6,bcf22911,d1ba01f7,730d1c11,8d6a7b2e,c1060988,32413047,b7c9ee83,1b818c5e,cb8f4c10,c800a362,419227bf,d9f50aff,ca25a211) -,S(ff37cd38,a4b149a2,a8dae898,c40b0ef4,4b55ed85,11b5413e,48f5608d,cc6d24fa,5e615919,8f4c6665,7c3a489b,86853a95,f3ffded5,20433cec,a6832cac,b9c49048) -,S(bdff4fc8,5b492fae,1ef34322,9e83b751,d9e53c7c,455141de,f68d3e8a,320ce509,e8fd9864,9dcc5d66,6155088a,29959e12,531f8a4e,44d70b8a,43b4fde0,8bde3d20) -,S(fd6ba29c,313ff2d5,7fb2719d,9018f11e,e59d1007,24146aef,625a9b3c,3bbcd0af,187daf5e,913310c3,39f584b,3196b877,5018dbe8,1e38abf6,de73e97d,f5c1079d) -,S(ea3c422d,48606929,ef72ae1c,3ac30178,4f4b5f78,1405fb62,1d0b710b,1b29ff28,e458b41e,c6c3e06f,c37637ee,fa316e25,d10b377c,ef99aaf2,564fef92,33bf208c) -,S(46537133,4982d600,8d228924,f0b459b8,2ba8aed,af1b3c39,f87053f,487b3978,fd96654c,13189def,f243bb29,e2143dca,3b2444da,3b895700,6bbff65a,4dadf3f0) -,S(fda493f1,1226069a,ac76227f,9f9e1051,b5b29b4a,a2d0f9dd,99637176,8578d8f5,5a33593d,f63d136d,f43a69d7,f9803a62,e04e55b5,25633a06,d8eb86c7,e1d46fa3) -,S(74fc42e9,5f09018a,5468e283,5ea36fee,7ab5e757,c57200cd,966174f,39f3e4c1,ccaa0b40,3802c914,da86204d,45f8f5d7,3760e075,4bfd10b3,2a8b2521,218751f0) -,S(98cec4a,997b79a0,cb818da,58e41477,d98f8c2,8140fbaf,e118bb1a,ec483d53,2fce6058,14945cd5,367b82fa,182c19d5,ac422d9e,840eae4,d81689ac,7eaaec08) -,S(c742ddb7,89a5cbdc,2055119f,697fd575,e4fa1540,96cc5fc1,3c2374b1,13cba60f,9b0af128,34a990e1,d402474b,e6dbaa1,b32248f4,f2b1d680,13fa0dea,46f3532d) -,S(dba2e04f,9a78066a,b5897913,6c4c7224,5b5973d8,3b13819b,77409fd1,e791eb89,34747922,3adb5f74,168240e7,a178f077,aa0e90e0,870456a8,89dfca5e,633baf43) -,S(6d4cae43,6e598586,7b984dcb,6c2472b3,6cc47f86,eb69fbf,1069c69c,42f6538d,c7fb58c9,f0c4f7ce,dd7c53c9,23efef52,125c2b67,d67f1ced,b98bb1f3,d5e0a84f) -,S(4c457f6e,d5b67b05,5b664ed4,3bae291a,9ec5b539,6fd9410f,9cc16a03,b8523982,492e5bcf,20aae19f,5462ed68,2a72827a,a435f47f,ec218e98,8e91fed5,20f344eb) -,S(4d7e6922,34778a41,f58033bf,d74ae295,51fd8ac3,64cd817,9cdd441f,cb46eb3f,756ec0b2,ff5c9d3c,3a453879,17ada4bb,6d7bbd07,bd10d2ad,c092f46,c62750c4) -,S(ac5be50,69bad479,bdbc565e,ab74ef94,4a48399c,a4af915c,fefc47e3,7d464b2,3246e3fe,bc5810b6,37722c54,69ce45d8,8bad5daa,529b4381,928b7cfa,de874345) -,S(7da88d41,21350139,bfe6a481,2534b25a,24f91e0b,60d882d1,5d69e840,da3995b2,9888ad8d,62a7a4f8,700bb03c,f9772432,6a2d092c,98adbeb5,cbc20348,f0b9c587) -,S(389ff31a,63239cd2,c9aa3eb,4d3ceb49,5d3b922b,5d137d4,e8b52be3,b1abf149,b0ec2a2f,bc840bf2,8a22ab22,b76c1485,42f54ed,5515ad49,dc3c0037,38fe7c93) -,S(c1cc1acf,5fb128b2,ea65afaa,d3d5736e,a94b2e49,8dfcf6f8,f3c27a5d,596c4370,8903584d,1986ad31,6cc6bf2d,aa2a88cc,ecfec6a9,c1bb153b,27c409e6,934fd38e) -,S(399ace52,b92768a2,a4740be8,31c96c04,2a34957,e91b3cf9,8b3518b4,87c9aa3a,908314b3,abdb3a47,a117ae09,5d609fa3,fd9af1c3,ca04a869,786eb134,48800005) -,S(69543fd,8c9d01a5,702d9859,305a52b9,470cc606,cadbc76,d8283ba9,ba06d0a2,e998e7d9,a0c372ed,2e348f17,b3298088,404eb1c3,8a901d1b,6f4e8a19,731057df) -,S(2172d54f,df9b46ef,5a1289a5,872b1c28,911e553c,f703ad6d,400b6af7,e8200100,2121b47d,3b790e5e,c820df5,772b226f,34a8fbeb,f642b5d9,edc18971,1b687a8c) -,S(f606f7e9,37a324e5,d0e6847d,24923965,cc27133a,10e43f28,6d45f7ce,9d5e8b56,70013fb8,622a21e2,d1337944,89324a13,f5b80580,91ca08d1,a30e7571,3e86e007) -,S(9f1520c2,dfceb64f,1f432013,b342af35,2f95bb2d,d49aa14e,dfcd8e71,7c40fc99,fe8fca26,feb1f004,8fa4fe3b,764a907e,d53dc0a4,10308199,6cad54d3,898e863d) -,S(6670af6e,7587676e,eb0674eb,75c93d38,53afe418,cb286605,18a9370a,231eaa08,2993ff5e,dfc071ee,97fcee9,bb12fd8,fb59fccc,524d8537,34ba4cee,4beb09f3) -,S(15c6d58b,345cc4bc,e4ca4e2f,ee954c2d,40650a4e,ad6c9524,65f59a94,b3898350,894c53b,47276196,65a0f3ad,f528d2c0,221b12aa,73df2cf3,a6b0e778,a363cf7f) -,S(bc4ab6bf,60dbde42,c9293ef1,75f85a48,adfffd20,960ea454,8a919977,75389621,fe28a0ba,24a4e2a7,45d6bb68,ecd71931,791a74,61549a44,37a34761,19040e42) -,S(5dab1c63,23fbf2f6,e495e87f,1c703ba8,64f20e50,4007dc80,54ef2e11,d3e6ee1,1fd0c200,cf4460bd,ae6db415,3e68bffb,e7f01ac1,6b30e305,9c134a86,52695d93) -,S(2df1cd57,d7357c44,7be28dbb,c339ceb,5cea0bd8,e702fbb2,dd67c189,6a8acaf2,33192011,20cbc8dd,c3b9c031,94db76f5,86eefa67,995dd741,492f425a,e2f1b9e8) -,S(2d81ac17,5a02daf0,83100585,ed2bac76,3d9f9764,15356fea,584ddef,60d9ab8d,f9908cd1,3b1785f5,78297fd4,9e6c26e4,21052e2c,ce9f51c9,cd58183c,2df9a0b7) -,S(1fac1762,fb732e73,2440d40a,5356eb17,67b1e7f4,f11e8db5,9ef90702,437dc097,edd5784c,a58d5113,2b5a08ac,e75cb30d,5ae7ce27,129f158,4df5d95a,7b9b8729) -,S(d06a0b5b,4694b90b,80c93e88,4aa9086e,45cabaf0,99b15a9c,c2b19678,38c8c98e,4cad46ba,2777b24f,cd1b391b,222ff3b1,14fcc814,5f78ada4,98620cfb,747def3) -,S(4928df27,590240f9,9907928a,cb6f0695,870059b8,cf9b1d69,29b152b1,7de53445,b773e60b,655b3b0e,7b0c400f,37dc336b,240b83cc,286a8ac5,3dba751a,3300d505) -,S(a61bcdf9,cd541811,4ba99261,7322827f,f945d450,c331ddda,1b8639ff,87a28390,3e771d6e,d6fdbb28,54601b2b,301fe24d,8e61b370,ebe644ee,b40fe807,b8d93a68) -,S(535a35b9,3e2fb7ab,b3b1228c,a7977,fb8e34c,107f093f,9f641b15,11db93c3,2471ff35,5657cc8c,38283fba,27c2e3c2,92475fb5,e8d52e96,f0c9fec9,b2ff786f) -,S(e68a652c,e0140f29,376888bb,c6be70b0,f23ad42a,d10b8acf,a5f790b4,c465d4d0,49d7390c,c368060b,3134ecb6,dad52120,ea6e0c7e,b80c94c,6cf9c1d,3c1a7385) -,S(e8939e7a,74dfccd3,ef17855c,3ea20e99,f5f05f6f,8bc4757,6b4f0e99,37e25fde,6b48a73e,ff0a55b7,c90c0fdf,449e4c2b,3773f454,da2c388b,3e0829fe,d661b173) -,S(496013ea,31451874,800fa293,a6e70ac,7fe16483,67c31daf,bfd00faf,48751543,b5715111,8790556f,8a4001cb,282b3312,581e1508,b8537f65,6142e2f1,ab8c4332) -,S(444735b0,b1efc3a9,56957a07,22604d09,bb0f6c29,e7cc5201,89ddc3c1,804b1e1f,b1ad60a3,461abab3,a9732a85,7050e55a,3e9a439f,32a5b21f,9aebe400,7e59d6e4) -,S(5805ac8,4acd7d5c,f85a40e7,4b9c98c3,e8882189,e77aa475,da3b4114,3ed9511c,c952923b,fbba533f,7bd70dcf,d8d69b7,1ad0022,aeae363,bb48134d,6a3c07c0) -,S(8ac11518,30fdc785,5e1c53a1,2b690202,c12619bd,c46c8898,dcab77ef,279a9501,29fb7cc7,7867fa0e,1d015493,abfb2000,d5deb3b8,ddb3053a,d59d6bd4,a9ca4fa4) -,S(aa47add3,e42998cb,68fc8a7c,cc7beff5,4d70226f,22f41ec6,7bd7b444,aab542d,cfa5ac81,ebefd98c,3af4f9e3,9f67459a,4f8e8c4f,c1959816,f771e75c,c43683e9) -,S(f3504127,a27a14ee,92133f75,364922b7,d3984898,e433d3e4,19e88db9,e599889a,f1af9f7e,9f9868a8,84ecdae5,47bcb886,56c6d423,a066b313,c09cdf08,601b45df) -,S(33730f44,edcbe688,35887076,69a989a6,272d3ce5,9261b98c,7c6eeeed,7e4bf08d,3f833928,d87716d0,4b2a32d8,1bd2d789,b6fd057e,cc70a794,8605cbe6,e1775a6b) -,S(3169d6dc,8c06f584,880bdf07,29249cc0,a33d417f,be137478,6e5b4a14,3edfb0d6,2a91422d,ec563839,ba782f59,68f428c8,a311600c,2fde77fc,ea163e86,aa74ce5f) -,S(d8c64582,13aae81,cf07a64d,5a8dc3eb,c8c43a45,d57f8e9,80cfccc6,f02a4429,c4873051,968863ae,8c92f195,c9fee3b2,c4773d47,849e2a7b,e7f48c4a,93822aea) -,S(ae67101f,307e246f,7a7cb039,5631b884,7e59c8d8,14da3fe1,7891f69f,402b6f11,f5f2dbb4,a90b09e8,b96767af,a9f9a357,1d3900f9,7d8222ae,e411e1c7,11ed44cb) -,S(a9e87231,83ba8338,1c0a7dc9,c81a2c5e,b4e2ff43,82574f0c,1a9d7f14,81dbd8ee,96810599,90d90e33,d69fb59b,ee68344f,333153ac,3d73a335,4b7ddd6f,96468901) -,S(616bf21c,ae7d40b,2694f43a,a33e6848,694ef879,fb5bc48d,ad141e34,e43376f2,bec18f83,2aa8a0ba,83245115,3b5a4faa,4a27725a,a3d9e799,bf05dc94,9880fc77) -,S(121e8335,601f33d4,78a882b1,1e9be5bb,39be47cf,701a695f,8d351098,af3f5c2d,2e992933,18faa04b,7d85fdfd,cbff81df,10dd070,4485b659,f682a298,4d03b3e8) -,S(bf884797,3025ca9c,9413948,fef1bc48,3a83cc28,4a909933,25c8c97b,b89f1141,1953a326,3d26d1d7,86d5ae3a,7838d125,6de24760,6abbb63f,e2713f6,6ead5386) -,S(7c28e9a6,5a3800f9,85c94d4b,ddc75cd0,dd1b06e0,faeda124,e86600a5,6af811f0,a3756db7,e339f03,8914cedb,707427b4,2d396fd6,f2e43863,13414863,8ab5c277) -,S(e5ec6dad,45e62cf4,1ccb5bf6,bb92387b,46be0791,31bc2b9c,b8b93172,90a66077,d0045ecc,775703ca,f854bea4,be3c4d21,2bacd092,7a210eda,67c33aba,e44f0e19) -,S(6fc96e1f,92039545,fb31c352,544a5974,7036263e,34d8e043,58336169,118c2fed,d032de87,1571de8d,96b0457f,84397e36,6ca7c20d,d90d089d,9aababad,8b8a9a51) -,S(89e3d351,1c219c47,42e79091,47c13146,1db684dc,e1a1149a,cf49115a,746e4133,aabd970b,672e8468,d84b53d2,303d57eb,52fde5bb,bb224b03,6892f918,630c5c90) -,S(2b7a60f0,b2136453,878eb44e,aadb8da8,c043e947,fea1de8,4ff8e18a,390d5890,c829b16,1ba032a0,59340709,1b38b365,b806686d,19026f41,ae8bbab7,d04a5244) -,S(464b9f1a,c2c2aeb7,e6f7c3df,a8782f25,bfeb9879,9263a9d4,2f872050,6c9627e7,7c260bf4,59e1bcc2,df7761db,e503875e,9a23a107,6cb4e8aa,dac5b5b5,b6f7502c) -,S(79253e30,43572295,e331519,e774b670,b25141a,986eb5ab,268b63a2,759b616f,da609d7a,55b62353,b20f5bae,969665ca,ed6467d8,f2577f69,10003586,e27f88e1) -,S(634287c,e900c0cb,5c2b1967,f55190f9,19acb09,43596773,87642d16,dd399556,a2350909,8cf01601,30c042db,253334ac,223c473e,312bf758,1fcb461a,c3debead) -,S(761121c3,8bd8fd5b,a3418557,f6a75b42,d7ef2f4b,91620223,3587f183,421bee98,4014715f,f9c17435,10e6eeb0,1bb29226,76070e34,afaed040,5c897bdb,52dd530f) -,S(2618c8c1,bfbbdf1a,59da3078,4e50a2b0,77990fe1,c2f074b3,e63dd606,6d453413,ae539a37,20f5b6ab,18ce584b,4ea3cb46,4bdaf35b,326fdab0,58169ddd,32a48da0) -,S(d429fccc,10c6f025,fc7a57e1,949308b4,d91699b5,c099820d,ab31f1db,90f685be,da2b15c1,ee155918,de414ae9,1be51688,a8df043d,6fb6c964,689bd4e,5a648edf) -,S(6a18e3c7,c04b8cab,36e07625,ba2daef5,bf1e0cf6,36650b6d,56dda8d8,e4e8b705,66291330,f56c96db,ebf9c9da,bc52541d,20e75440,25fcc49e,d6215d8b,c0e94eec) -,S(985b6846,d1c9f3fe,5482fa4a,d6a21c65,d7ca3eff,a41b3220,1a37a122,f8f97756,3e2b23dd,98e18f6b,76a2f2c3,2c543f8b,bb9dc6c0,8d391592,d56f5440,aaa3a92e) -,S(948a0ddb,4ba838a4,63eee339,5c7bcca2,96fba8e3,9654ff33,55c9296c,9e6e8c64,c5b34c25,da19d83e,b67b69b5,2e527d61,c7b705ed,2f794d2e,12c4325c,3cf5c1d8) -,S(4332d02c,1332b03f,b7a46b47,e82617b2,a437fcc,694868c4,256aa40f,a8a3de2e,e6e5196f,5f9c555d,a94327c0,39411780,393985ab,73765de1,e1bbe0dd,8aaa5289) -,S(5dc977b9,2ac1c895,f3150b68,a8d69f5a,f7e12dc5,6b211d96,a67cc3fb,722a5aa3,45888ca7,4bf1ec9e,1cbd2912,3cc696d2,83260c34,3410217d,10fd0b95,9d07844d) -,S(5b9cf534,ca94f124,a9b0cb6d,f0003924,605e3bd7,d063a2b0,c6e1a81e,3fd15764,44e98dc3,b0516ffe,bda48790,fa0b2d67,f9ba4b48,ce88bd1d,d81bcbc,897458) -,S(84353007,3a63714c,7d26baf9,c895e2de,e2feb4b0,9746ca66,97fd7ff6,d5372f59,d7373a9e,37689d44,4cb7361c,f2f3452,3f9fea7c,826c62d2,3ca3f368,b0c7a175) -,S(9cf0000e,3eef9b5c,89c8485f,c3826e78,8f1a28df,f8746619,804030fa,c21e6a61,2b3dab3a,d8684b2d,94e1fcb9,d2005c20,2764cd76,aa91e0a1,ac2612f7,fe91543c) -,S(bb292fdc,5897188e,20888b25,b491a757,8ee02853,83aff5e9,99671a24,4ce1235c,d3b6d9c3,50ba7863,bcb83990,95893348,d5e9b8f7,27e1a3a0,9e02f59a,412507e5) -,S(95d6d1d8,9835ed57,6a88a21a,9239b623,efd2bc6b,f27c5ced,2d770c90,fb7d680,c91535ad,39db65ce,fab4ac72,f3ce692,b39e7d38,c72ce468,e40bfe06,6cbaf048) -,S(cbe3f20f,a164ec20,9c2c3fb9,ca0c95,15ea3787,df2c8fd8,9ee50a3a,85d09a46,cd589754,faea165b,48e22280,4186e6ed,734a2251,a6588e8b,8252eff9,afb9a28) -,S(3e01dab9,9bab9e20,59b1c215,ba67835d,2942f4,487d6094,9f39e293,b39f604a,b41ddc32,33365044,ee350979,8679f3e8,d0a556f9,e8b6a267,bd5cb5e,8523d481) -,S(298974c0,5543dc96,15f1cfd2,e4b6331d,c798918e,15e3f350,97213a64,76afef7a,68018355,55f2d8be,a74e02e8,747f60b2,22354ea3,62cb657d,e5cd8060,7a99da2f) -,S(1d70674d,54763c96,ea3764b4,641d14f6,2aabdec8,a093c3df,d936793f,511fdc61,9674adac,697e44bc,6324378e,59753f42,80774101,623dc10e,8a4eb4be,38dfe632) -,S(75220107,b43ab970,6261875e,c8f8b634,73c47aaf,91ab8fba,cc0b1c4f,40fece1,29094e7c,c3bf07d0,12aebf2b,fb56efb8,41bc9ad5,9c350b7b,885602e,a3aeaffb) -,S(cfadb9ff,b3474ec3,27db31aa,b0bac83b,fc7f4c8c,9d0efdf9,2e7e7922,f779720,ffb7657f,6f7b8cc5,78f22ee0,2a99fa82,97d41806,cd2b8b06,ab00b993,d9a09b2) -,S(24ee919d,be3c5603,adee46e1,39d84aa7,34a7b4f4,d7b826f4,64ce8b6b,c1cb828f,44039756,794b547b,9360b63c,539b8f11,ca651476,ed57fe29,364a5ea6,17ff1506) -,S(5995e246,2f755256,f4d6b8f1,a5cbeec,c50ddb53,fe4391dd,1b530eff,7cb100f4,77ddda7c,7da05165,c46d7ba2,40127ff,fe78ac6b,13dd018c,e08161d6,d81dc64a) -,S(a7233471,97dd478c,e129fa20,59193c08,364f8c37,1cf19c2,9dbd51c3,234d54dd,2c4e695e,ec2b2ccb,384a5fa0,1a96664,9cfdd711,1a1d19ad,92f2eef1,31796e68) -,S(6466ab69,d5bc21cb,d7e75fcc,5de9fcc9,a57cfed6,3ad41c23,4ed56cd0,132251a5,76e7ef89,6dbb16e2,76622f5e,5f6894da,2e0c1ecf,c4af05d2,990dfa4,25294dc9) -,S(a5eccf90,a29388ab,de6fca2a,bf216145,7fab8bb5,1e33d4f1,1e0acda0,f5c28e60,afd75916,468a11f3,73e88643,56690adf,110e74e2,c81123f7,94805b26,620e3ac3) -,S(4251bac7,493678d9,f26e52a1,e3ed9e58,6a15d060,4d1c9cdf,89ed5871,ee9c2779,fa1df27d,92e6716d,76990c60,e6603bcc,4bb023c9,dff938d,3a15ad8b,72987aa5) -,S(77a9e6a2,4c3cc21,d8cf6b97,3181e283,f40c9d0,26a81903,f042c2a4,fa7db30e,a1ef4fef,23f25ccd,bddb757f,aaa10ccf,e78d9310,72b2f180,b6e3de5d,18155aa0) -,S(33fe7961,c40d4e1b,d6ade73c,4577fa2a,e9c0d20e,999f639d,e751ff7e,6fdbea6b,91b7d5cd,4eeb306c,e316e7c1,464c30cf,9a591994,7232b037,5840b8c,d5f54849) -,S(43f66b2e,5ee52211,a48a9d8c,b485be2f,39535701,5249c311,5b682170,f9179564,5370b55f,fec0ebbf,c30cf7f,e63f5f88,3555e699,728e6892,1dbf7874,2da46a45) -,S(4ad36614,97ef1074,d74c7f6b,446ea87b,ad2f0b43,73f5970e,1a745b6c,38b19bfc,8f5dc1aa,769a5bfd,5eada00d,436f850f,6f9eea82,329ebcfc,cd4cd60,ef5cfd39) -,S(9799aaef,95204d54,f3734dc9,75b797aa,59336866,9b2f12f9,155d5953,c012754d,4b6b34a3,d31fe173,43a5b476,bc492d54,44c256ec,ea236f3a,9845a875,e83e6353) -,S(c86249f0,c6e4635c,2d03f252,50e35d67,c1c22f51,6f9a8dca,fbc9d41,15d828a1,e21770b,37dc4d0d,f4d260b3,94bc76b2,46523893,469f1025,86d99467,ee95ec73) -,S(b48dfcc5,de5687ef,c7282c84,cfd4060,61a08fe6,92fb08e,3accdc2e,6656038d,87e3e1f,ec737074,71f69c7b,c7147665,c0b52a95,37ad1566,277b6d19,fce8927c) -,S(77dceb6c,62d65535,c625c828,fd3836a3,146fa4d,36732da8,58503fcd,4e357fca,d90b2600,5a139713,525b8521,3d370ed2,4304d08c,87fbb67e,9091d1ea,18228bd4) -,S(5b588cbf,4cda0184,4df1cd63,3cc70ac8,69cfb43e,332f5c17,47364750,3175e49a,1424ef1d,f9e69e4a,84eb823b,2f95fce5,a52e1978,474697c0,d47890ca,fad55cda) -,S(c087bbba,83934208,8c70251,8c9ddd93,2c50cea5,11c443b7,da107685,9320b20c,77f26a69,717555f3,b030e345,5cbe4b30,f637c23c,7ebc2b5f,6ec2207b,9209d996) -,S(8d16057b,68f8082f,208b3e7c,fc2c558c,247d7d60,f117ea38,35e474c1,3031ed94,3d305db6,62ffd13d,100f6e0d,19c439e1,6ffb8ca7,eec6b14f,ed551091,d6ba3eca) -,S(75fee0a6,3d32bc8,6dbb8cd2,af7371ff,d17daa96,5e1e19d9,242fdcc1,edc184b7,c2b1e4ff,abc30975,fe7c992f,f8091795,61ee89e,9a040409,10bfdc64,93efa2f8) -,S(65da3959,b147093d,7d092599,a87710a,dda7fb75,460e47a1,10d5c1e2,6f368abb,3599e1f5,2f92c1e1,c3f2b463,d9a30230,a6f53028,cbae3ce9,5e345c5c,21862844) -,S(6561fc10,94632125,d76b787c,a7539870,5dda1a5b,f4407f4d,f8140b6f,967933d3,4c06c7ce,a88e2828,3eae8aec,ab6e8802,cd083f37,6d3a1ad6,29fa9b55,920e6337) -,S(c9a53f80,70493701,523041a6,a9d23343,c8a3fc30,6664d6a3,5ca5e7a4,80c4410e,9af470a9,b2e30d45,ebef0dd0,6e3b2736,369d4dad,f2366d42,18344a22,b6e4bf9) -,S(5c1525f3,443e56dd,b009f45a,1b9a1540,c203f814,5f577bf0,3c734597,33b89158,967892f7,cb3ed91a,d74f4c80,3625707b,58574afa,cb99fc02,f5b3493b,eb4f4f18) -,S(3565ccda,d87c171d,714add6d,472fee0e,69bb6ea9,75f61454,d69939cb,541648ed,9f7d87bf,ec2b6358,5dbd09bb,d008b197,4f02d3a7,6a8d54ed,d486a2d9,3462aef8) -,S(4003ef34,c0f5e1a8,afcf29df,42a14a5c,4527d3dd,138b5eda,bd8de661,1d0e3614,67203152,44894cef,cc3d0a76,35839c2f,3d3ead0f,36174e2c,d3c4c682,4c3048c4) -,S(f5c4df5b,37965079,3ebb7de3,9b495a26,13886422,929393,1cf55d1d,912ea57f,b0b93c3e,12a98cc4,5a3672c7,4a3610d3,aca34da5,7d31a968,f30047e0,31eb3482) -,S(bc9f680,e21186cd,ba63533e,56580289,cbe8698e,69ced0b3,97a96793,569e213a,6adffb78,8105518d,50fb94ff,87d204dd,7bf54ef5,b91e1d72,713fa9,b32e06a3) -,S(4dce8797,f1fe8811,453e15d3,7a3e2621,549e8347,4e7046b0,55f99d2a,c9a16516,ea5e6b77,cca7825a,95cfd9f3,7d70d7b2,fc8a8aa8,749a9d43,37ce0754,abe668ea) -,S(f49b5aba,1ef29570,bd72a0c0,40009382,af2a4f85,26511eee,81869d3e,9759b16b,2e496c20,b996e8d2,696125d0,f60abc66,1d2fb343,b4181202,8658e459,d57c7f7d) -,S(26917d4a,7573e1d2,7b4ff765,72bf2948,a2d02f07,7d7d7fa0,54a1bee4,92125ec,b8e47f7e,ae9b66a0,2a6fd2d5,cf8c88c9,7eb12530,a618678,ad5ce83,7cd8f97) -,S(1b4948d6,285a2fe4,98cb71da,f213e6d8,7ead776e,cf8bbcb1,cd7faad4,fb29d290,1ab4081f,ef87d925,9b736c7a,92d28618,d5698499,b2f5e27b,dd30c1b4,24d3bfd8) -,S(14d712ec,8179baf7,9dd9676f,ea99653c,f8b20ff4,a69636c7,7258bd57,99ae64ca,2e1db8a6,424650ec,32b0df37,d72ce3f0,6f38538,53bafad6,d366e04e,380c6ef0) -,S(7675220,41747684,9e1967e1,54445913,a1111988,8b5bf813,4d9694f7,1d952453,3f1fb063,6457b603,3a155a90,6a722de4,de1a5c3d,6094dc27,37776843,ed82fd31) -,S(5ac8e534,a8828b67,40016d02,80bb1e26,a53b16f,96b24937,fc84ba34,dd49fc63,193d020f,68f5fb7b,2c5a429,6909ce70,18568f87,115e987a,8e5e206e,b8a1fc73) -,S(87cddeb2,8d16562a,531135b6,193449e,d618d0dd,6acf6c43,3372202d,ab4a14b8,5c1de4e6,7c958ad9,9411cecb,de2e9129,cd709425,135c84b,e5b68cba,9f846e2e) -,S(c431ca25,a39ed09f,48e1dfe7,afa86630,4d4f8b7e,eb0d6d52,f8c778a0,424c84cb,450607d6,5b2dbe6d,35cf2d11,d3129330,489eded6,e35ff429,2aeae0a6,7100d825) -,S(8c5021e8,985c1a11,4bfaf3d4,40edc4a3,aaa93002,5c2f2c1d,9bff3683,88a3dd5a,4cb960aa,8077d81c,71d74ba,6096fd4a,b6d31fae,d4315db1,3c2b60aa,a12fb108) -,S(338e54bb,38a47485,8c17c07a,177dbbf,6e7a14b,26781bb7,70b9d717,6e513d4f,7876ae4e,84cacfa4,c22951de,f67763ba,c44a6ad5,52ee66fb,92f80cf8,c4420548) -,S(87f3bca9,efbb3a21,917683ab,ccd268ad,3c7b0fe1,7eff461b,cb06ee8d,2f1f3c5a,a7a1d2a1,ecccfc54,4881f258,bf5fbbc8,e5cc11f1,a117c7f8,361a33ed,55229b61) -,S(f4023df,8ed85856,8e56a037,5a6a78d8,de27d6dc,467c9aad,52407bbb,413a3e40,b2499142,fc4e3a11,6aa30e56,6d59f373,d5e2c545,3e274161,5cff9f6a,1fe178cc) -,S(cfb51fc6,d55a8a22,89d3d282,fe63b2fb,453b512f,374e01a8,92708564,9c6f2d3a,8d4a3223,283811ed,28ec120e,761e61d3,e4ea5312,1cb2525e,b567fe9c,9070635d) -,S(59a44a0b,97050147,bf219db,22249635,c45f77b1,1721c486,8937ce96,ae43c539,31e1ca6,6a910f3f,1de1d0cd,55eb8a76,400ff959,13774efd,158d931e,7039afa) -,S(b99cee56,ec277a37,6ab44628,14bb3a8e,d8e26d73,19fd786f,8ab570e8,28a8ee7e,46e0f398,dda05d4d,7253b16a,b4d80c14,b6be5d31,d1dce230,62ab1135,c23494ad) -,S(a39e136a,d96b1a22,6d039872,5da75b38,1c6b922b,52947cb0,25207ad0,d172bd2,7a5c0758,74de08e,3d10fa71,79639fa8,7dbfc977,8af1a3a2,d910a1b9,b6abb532) -,S(6e8b4125,3b2eb74e,626dd59a,eb7512b7,2c23c855,35f479c4,5b48d974,57001976,cc0b88e1,e4e8c045,5e804068,acb85aa2,715bc82,ec21ab47,873999e8,cd2bc88e) -,S(9942b6f5,681e4189,f7fb6ec9,8efd1343,cd1fb66f,1c98e418,9c44478a,51abb019,200d0ebb,b0cc2d52,90a11e6f,f7c989e2,d2fe986b,ed266430,56951679,8d0e7a9a) -,S(7fdce1ec,3c57b949,44166918,b48af352,759636f7,2eafd744,642e0f7e,5078506d,d7785aef,c19a76e3,73b786ed,1e2d2ce7,53cfb979,65d3d46b,2e313a2a,d7baabd2) -,S(6f13205c,958c83f0,f170906b,d77c79ab,5f51654d,88195b04,a70d4e06,93989c57,8ac9a15b,b386e483,b268d4f1,c950da35,33deb99,55116c99,e848f13f,73b55ee0) -,S(f955a35d,833c69be,40a0665,f4dffbfb,cd405f4f,5b4247e6,e50cd4b6,3697654e,89f4fbce,22468389,a4af2407,f40eb37c,f56e80b2,7da1983e,4e2fa4f5,8bc9ee44) -,S(dbcd152d,619646a3,42a25743,1df9798d,b58b8d1,89238132,e65fb6a8,26248007,66fa717e,c1948fd3,e4425e9e,2e6830f7,e57d23e3,d0219dce,c02b4d36,32d8ba13) -,S(f1aebce8,e57b909f,ac7cfb1d,a2e7953f,99f713b2,8b35b5cc,71eea153,5e6e8ebe,8755fa14,3e77e5aa,60dc24d0,92e4f596,88b0bfd9,585fd57e,1b7f610b,e5d9d516) -,S(a202164d,941f84bf,f89ceab6,50430905,c002bc5a,91d505f5,fef6e48a,4b55187,e0cd42b,2bc268b5,1e572e97,8b9bce4d,b6d4b095,ade884c1,bee3b3ef,c2f057ff) -,S(572e1657,46fde7de,9480eccb,287f8b9a,b1344da5,8026861,e784047d,ca8ad68a,c174ade7,c066abb4,8d2461eb,405dad76,39eda86b,a0fd170,47569617,31eb5d9f) -,S(f4e2c907,fee4d753,c08b1052,b76e49e8,b67047ca,59e64dac,58acce9a,5beba31d,b243aa2d,3a92d2d8,e48b8317,ca8fe897,2b76d134,248070f8,f41bf871,2c11c42c) -,S(a6fc6aec,84455716,f5e9e436,d68809b2,26698781,f24d0463,e06963a5,fdf06dd5,dc16a615,548efd18,6ae135fd,f748d9f0,a96b7f4e,918513d5,73900aa,1818ca8d) -,S(bd806817,5fde9652,9ccd8eec,937f2cbc,c4ffb3ce,b04cc9bc,c00cde2d,5a05f026,b2791ae7,8e014328,e0fe6a0d,8b6bddc6,db048274,5152bf76,bce228b3,64a26216) -,S(f888a667,6f8c3d20,b9d5e810,ecae6b8f,2d8614b2,3a5da51e,16386dd3,5c0165ef,fb4ee20f,e429f3ef,f6f4bfe3,9c7b1ebb,57978853,de242239,42a3dadc,909a0dea) -,S(7c8d1e05,5adbaa71,ec9023a4,8d160fcd,c3182ee6,bda76fd2,3ba8877c,409ae200,8a3b820b,ec595523,d96936f4,fce83779,c489b9a4,f2c8c524,f16e1764,2f907ceb) -,S(18886ea4,ee257120,610ccd71,593baf72,6dfd9bb7,5229959e,75c14e76,26fabf43,266c6695,f57068b0,d33ad3f,7d02b7a,898a3184,39889d31,ffa98d86,e091531d) -,S(fea70f1e,38c8adbd,3339a44e,cac036b9,1242a099,506789a3,184fdcfa,6be52cba,9dff6df5,ba8c1b9,ddc58093,a36670b6,76c0e2f,d745c468,83e26ece,3b9e7915) -,S(4de30389,45aa3c90,76d99142,e79451b8,96dcbf7b,fe420c8f,b1dc4b4a,37d1365a,cee74e9e,9093de64,2401eb2e,201b3377,992ac0a2,13b0b16d,35664ed8,d287cba4) -,S(67d09dd1,eafebe79,c63b8c40,1c102982,8c2d8e6b,6b5bfda3,73988830,1a104fb2,10eb5508,92660d96,8e99049e,818f89bc,d4f03558,d9f2c984,61ffaa5b,bd360a5f) -,S(2b5d70fe,186834f8,d3b96d4d,87031cd5,325e55f4,ffa31b5a,f5ffdd77,40e6010f,646e7e53,24d2a373,78b1f54a,fb2081b4,38439890,c9f53b1f,7bda4d47,a895ed02) -,S(cb426299,8700a76c,193f7b44,6aed0ad0,5d600b23,ca24c752,527f62df,e17be248,92843e13,f3eb60c9,e5f74eb,8cce7723,bcfd0250,4c2186e6,5ace939e,5819a8b6) -,S(3ee6ab7e,75b3bc57,135ce4d0,1e6de88b,22d0b853,fd8e0d25,f9b04ded,418e4e41,69c83f98,4e52519b,931b6afc,933f5200,6ee1ab4f,680ee768,9ad55368,1b4bcc87) -,S(583774b0,a95a5143,17232df6,f17d7829,6918acc7,2a385724,e904085f,c887e7be,33bb1e66,ee8cf17,30c16073,665c353,f8f047fe,150b4424,18c736aa,807c3e7b) -,S(af32e1ef,39822787,79082b77,2a643ea3,eb334100,9a7a3fcb,a8838e0,7079dc1a,6985e28d,c660123e,73aee7e8,b1a36697,16938331,e4b4b7f8,b3a9ecb7,4e95fd4c) -,S(6edf7fdd,32667551,9b60c740,efbfc3f5,50f7249c,deabbf9c,948adc16,e034d0c4,f08c5f18,5def7da7,5fb0de81,9b092691,64534f14,bb7d96d4,bb4513d,ef46026) -,S(3b9a6645,5d268f94,6c504120,a81821e0,86257a60,b3fd9f00,72a0a4f0,1f16b42,ed583a15,aedf6c08,95f60109,6190106,3dfa4848,645b0117,e2e1bddd,2cfe7c7b) -,S(bd035b08,2b5cfdb0,d17cbdf0,7a012b0f,27b52943,82e8bae2,d683ad0a,747a1039,6494cbad,ed4ad7e8,aa135ccd,572be8ac,e94a23c3,8b62bf61,ac90f9a3,9bb2ef54) -,S(e25fbf19,fe9b180b,ae3316ef,89e0382,4dda59b1,41022ff7,a8c45b44,f15338c3,45ec47f6,58a3dd52,34241258,1852e694,7c2c8f11,9f4fbbe6,f6388363,174c7cf2) -,S(2e231dcd,8ffd7356,52ebea7,50165405,f30f595c,3871ee6c,7c072e64,ecffc9b8,c664452,db15961a,8458f3d3,ea24ade2,7610d4cb,ee51927d,29cf3164,6f59317a) -,S(7c0f29c9,3932626f,1b1ae126,316e065,fd2a4174,a66a6048,3b458660,f5338fc8,27ef533d,df6f1272,c0255d7a,587f56a9,b76e2c4f,98c98162,350233ba,75cd037f) -,S(e702d61c,ea6f9fef,fb43e014,4794fb32,7bd857e1,70b299ba,31bb6a20,7cd5bb48,c4779881,c924ee3e,7f228a71,2de07794,ee5e28af,ca63af21,12ec0eb3,1a3f79c9) -,S(f1780044,eadec1b5,bee75c11,7c1647ed,c362c5a4,35a66d8,cc2ae45f,66c852a8,5f8de9f0,f31b3977,f08f63ac,1380310d,e8b7a304,85c9f0f8,9a677572,329e1c18) -,S(7a41b37f,22ec5b18,d4952c53,326665a5,1582ccb7,1660b69f,8d00701f,1f12dd9e,8440be13,2c57259c,80cd74d,2a2f1e01,3448865e,2429c2b9,db750951,607fc443) -,S(94fff7d,8111d69e,198f4e16,57c3551a,a5ce6316,d520a779,ca4ccd0b,282db6d3,482c9270,26c0c05,578a75d3,8b1d8ed7,42541d30,3a933b90,9c3249bc,505c6fc0) -,S(d6a6d44e,8a3ffaa9,56cac76b,1b05a4a9,d3775989,2f70e560,a54c9440,17f4e9d1,48c3bb22,cd839de9,9163bbe7,83a8a057,c7b93e87,de388b6c,dc57ba57,90863e1a) -,S(cc0e25c0,8e24edab,1e5dbc47,71543b92,c47c0993,95b93d53,699204f9,50cdf80c,20c52cb3,7170cf3b,43b76ab2,cb4a6d3b,1a977c55,2431b8c8,220282bd,51fb70b) -,S(cf953f68,4cb7d1af,a125d0ea,cfb83cb5,efddb6a4,41079be3,db72573b,62f8d827,70cfe366,a45d11b1,a847a7b,8e3e50a3,b302fa50,1afc89ac,b89eddb,30909c0c) -,S(1ac22694,2b34ab06,ff16b711,2fd5fe1e,f8ce6975,143ab19f,bff99d6b,6815d5dc,a43d457e,2bd0975,4e9b7fdd,d9e16681,1bd823d2,24476615,4d9e3fa5,ab6539fc) -,S(d02bbbff,1153804a,f0f800bc,f959406c,496349fd,a412e9e9,bb9f7232,7a4d65c2,5de80de,3c7832f7,1d744f9b,9ef08b56,d41e682,1c20f2f2,876fffc1,b802a384) -,S(3ccad347,8d464ee3,42e1cc2b,2c4b299e,d8a60326,4837a040,25a8525b,4f1831a7,35ea2a4c,a59b55b6,ac79fdd,6ceb3401,47492f3e,49b5035a,f3036b26,d02691c0) -,S(eac4d554,3e69c3ce,d762e90,fff84b3d,b3a758b3,419d06b,80f7ba43,36033688,aa64fada,c54374bb,fe8449aa,ddaa1846,ee00fb6d,c9435dbf,17f6a12f,d1deacbe) -,S(3d2879b1,73d93713,3326d0c6,133be281,5df62465,d3dbb7a9,a028e0cc,63fca753,576ce64d,9b95b5e8,a9e3eecb,34cdb8d1,fd38a08c,2a6a8c9d,8f0a7296,68d6e0f0) -,S(3f58ab8d,56a9682e,25137087,ca8c766a,72358a56,99ebbce4,cf74e304,6976ca14,3c9053d1,1a2a8a8,1f30f45f,1b480dad,f6bce20a,15e6315,447405a7,b321f29d) -,S(4f5f1289,b48dcd19,41a9df0f,a8aeae42,2a4ed913,58845b97,3145ddb1,13fd12d7,b5c3e32c,c40c6577,3e286ed,a233ddf,42ac0d6a,5a3c3e86,77f8256,e0dc1428) -,S(a64a29e2,a52dc6fa,e74e70dd,da2bacd7,e4a9dcdf,f9a0bbc5,ad0392dc,93376a76,ade2f8a6,faa9b1b7,7baefe87,33ddc365,c776f2cc,b0e5730b,4ebb0166,418a9590) -,S(dee0aa12,c4d6f88a,d1d86f94,e1c6d3e0,b8694b5d,e234af04,994cc7db,c8480e70,cbd9acd4,cbda37cf,a9d368df,332d30d6,413ae1c8,d34219,3d4651f8,62f93389) -,S(8677a99d,c8af6ae1,b653e294,80eb66fd,772b958c,882fdf74,f9c0f188,d5796936,31c668c8,348c048e,4b7a24f3,a0861f44,6621151d,4dc3e9ed,783eaf81,ff97232e) -,S(51117d3a,cb73a7cc,2b229bc7,9bd6d676,f44aedc1,98cedd80,ed6178c1,f6997fee,5c638c04,123f85c1,170651d3,96343e,78f20770,321c1a4d,174e568c,39110cd6) -,S(48d8af64,69670828,e87585d4,52ea1242,a83c9f8,3423e468,9c3ca383,9f141b12,558a8f42,f07f49a7,c6a9843b,9055ed05,1998dd35,9406c40f,dc4d64e3,5265e9de) -,S(62ba9ac1,b0fdeee5,a143d457,41c164e9,d4060c7d,f5bbb17a,ecbe80f5,f6966d2c,65a0653f,2290416c,5fc96494,b70b3b99,9329fe67,3b034aed,b586c118,a5d9450e) -,S(be4df7cb,679da56b,50ef2058,3c79310,508d8d05,43f3004a,486297d2,49febf0d,c1b56550,dd5f3e7f,a898cb8b,aca88694,ca697306,fa3fa09,95f6c43c,d5f3ba9b) -,S(e49c036c,cca2e068,5acdf34,8473316,424eac2c,ce1550c3,a0c435b0,28c9979d,456bc25f,457fde5,5bd0d273,d27afd7d,21186b1e,3b42bbca,b168992e,61609a1b) -,S(ae6845ed,a81d5d90,b3fddfc9,cb774c2a,976e701a,ad5c1302,7057a6f8,97fd58e3,529bdc55,322ae360,9926194e,7539a534,4501126c,e69b3e11,e5b4a675,7ed755bc) -,S(52a1d8f8,bcc2b772,cc8717e0,2d713864,4c274499,4a19ed18,3fbeae31,bea25e1b,da2a0b2c,e7f17894,848e77f9,53b7528b,dbb80673,c70341dc,9f869e60,4189011b) -,S(ffbbaf01,d89a7804,d5d19f50,dd5a4abd,cc5529c,90d26918,425f3805,96a2250a,88b5f7b7,eba662bd,5aa47a6,c2fe1322,2d514410,f6b1a145,38c37ed9,9a9880e2) -,S(6ffa438,aab51ab7,afb840ee,d4f85725,4473fbc8,ff6051f9,fe5a59e0,ff8c942e,5b0226dd,3b88a040,33860dc6,69613bcb,50a0e95a,2ac7df8e,66884c7e,e602d775) -,S(9c895658,f92ac47e,318f5ee5,91d26a10,c2c1b77a,c8bc8cb5,a45ec943,8a2fc79,708071e2,665ebd58,f1655e28,6de258ec,ef4b0115,ff74f38e,516acfa9,c01045f9) -,S(532e6e0d,efba35b1,3fdbffd1,8ebece3c,a59bb3ce,54fbbb5,df1df6f0,c1861ba9,1af465da,d326bbc3,eb732ed2,464b4593,36f04b0f,a50ba7ff,f61b4754,aebc5b8a) -,S(99043321,e3f27092,cdadd8e,b50cb4a3,8a8a9f80,83da6ea1,38d48e00,e5fff425,11be8597,325c250f,d9e5b1be,8e52c336,404ecb24,df29b786,ef9d1f04,8f77ea6f) -,S(96799080,3a0934a9,9a0a6e94,120c22bd,7d79085c,c331e172,87daf46e,7c4084f9,ea90012d,18450bfe,6a520b5c,9b2812ee,574903aa,d75cad04,7dc46c23,98005e03) -,S(74f5d157,915ffe10,cf6d9981,9eff7616,1f36f71b,4fc386ab,729dac37,3aa0afb9,54a0011e,4922bc74,12ae225c,dcc8c447,4e4ce4a4,941a409a,2c49d421,19b29eb5) -,S(12692753,81c63955,5700ddeb,e8d7a751,76e5f3d7,2aa0631e,3e7cd6a8,c1927855,b92e5076,811002d5,44c554fa,1e1d10b5,3eefeffd,513357b7,2c5e0cc1,c39ae553) -,S(84ef81b,1d143d73,5b6ae35,af18d810,d7cdcfbc,dd1c68e1,1aae007b,80230d9f,cae39a2b,a5b4ce8c,21ebcf2c,638a2e5a,b0dda645,aa6e01bb,33ca2edc,b575d42a) -,S(1c22ada3,326e6ac7,6647af5e,ed62a85,c8d89dd2,a733ea62,dd71512d,ec9037ad,f5a598c6,1562a6af,99e46283,cb9e6fd4,bc4142dc,99600b64,49304981,16aab458) -,S(6b91ca4f,f08eabd5,aa8dd35f,e9e04153,c00f1f48,50bbff4e,73671cc1,fa4aff1b,c6cdaada,85adf99d,4fb68c8b,6104f585,b3c9551a,7dd87977,8cb250fe,11b31852) -,S(57bb4999,6d2e2157,613f0321,983736e4,b99063b5,e8f7188e,23f7895c,edf85bc2,93b46dc6,72eea90e,9274b9b2,73a82da,d0a1ad14,55b550e,94fdb765,ab47cc3a) -,S(75790b27,ebf7566e,1056d9f2,463df8f0,67c38a2,78af81cc,b40f5260,4a33ba6e,ca0c8ca3,d99b0a5d,b065decf,346eadd4,3af8dc71,9ae06dac,6be99c5c,b89d2045) -,S(ca7a75ad,a90b590b,f7f2b6fd,e3004a1e,8dd7b4f4,db8c4a08,f32bcbb5,474ebe9,b3278d9c,5c9351e7,bf4e8a08,e0f1dc00,51273259,acdcba1e,fd3ded69,83fc69e3) -,S(a6dc68b9,3bf46294,392a8d6c,e52bb365,47b65a5a,f318765c,7a4f5d5,2f90b2d1,41ba6d67,fc575561,a0f3c76a,931dc62,37f53348,819224de,8f925c33,c90ad45b) -,S(da2139f3,f8afc90a,c7f5a025,20c36110,2fafed4c,3f525b56,fe0dae1f,6bb6bba5,95adcb88,fa9ed816,dc097522,de5a394e,71e92c1d,f5bac36,9ad06067,1b6349db) -,S(a32b2475,2f0e0063,acb4194b,faba9ccb,2159357b,23f102cd,f5a8e24f,413da4de,57df4143,bd8b27fc,c7716ffd,8c35036f,e09f8ab8,34f053db,ddfd3161,ebe576cc) -,S(aaea491d,33824ff3,c7319d8b,a233c73a,741718f2,2c921392,b893894c,ade9bedc,c8fb291,84d8dc65,93a6a3a1,a5aed86d,a7ad0d32,d5f8ef4e,b24b6154,4c1a63a7) -,S(2935e0e2,7a8409bd,224f3eb3,d68fb639,ccf75d5c,2b0315e7,ed388acd,887f2c75,c4ff024,62c9ae40,983d0068,180d4c3,977e900d,fdfc164,c89a938,c568aad4) -,S(7fca8076,9e2e7253,5834259a,abeafecb,fdebbd96,5066181,63d244ce,770fe577,a3ddc3ab,f04ded22,cac3b8f6,ffd14ffb,69cfecba,7dbaeed9,9a5e13cd,55bc3542) -,S(c5b5f1c6,1caa4a7,fa5e665f,57b45134,bc129ec7,131642a9,6a7b4191,5e8b483e,26cb3816,da5098cd,a3f58fd0,c26011e9,73dabb66,d8cc9257,6d37bfbb,9cb538e4) -,S(410da274,df436772,64decf4b,f790035b,d7d5b174,cffdb4f4,56bfb6a0,79a50d88,71c81968,188eb349,6dc2ef1e,841979fa,254a1939,5bbf00f8,8e1d2bbe,ef9a6abf) -,S(3d9928ca,334dc800,abb6c5a2,43a2681b,6f7976ac,50abf387,54058d05,cf67769a,cfcc01dc,766127b5,3e183cdd,80a0a1e4,62bf01ab,c4df115b,2e4f4e9f,95d2beb7) -,S(65a8f57b,c523e4a6,4777ce31,2000a322,d858eae1,f39fc919,2e4f436c,c8040cec,820698b9,9e953745,b1ff7b0e,a22bff63,c9df69fc,c2055b32,3f07fdc0,61192432) -,S(84e553cc,baa606c2,ffd3ef5c,a62725a4,55f4e539,24a72153,1ac3e66a,5d92fb79,34d6af32,4aaa9465,fd9f7731,1c01221d,4c0b5f75,1902dd67,4dcfd0f3,9cc5f8d2) -,S(3b4a7558,28851226,f391578d,5d146da8,dda3d4b4,f79a36ac,5f8c166a,773783,e37c96fc,4de83cc2,eb4b3cc1,44d4d35a,1a4249bc,4cd7c787,7d0084c1,b1a59e53) -,S(6dbbd12c,6164e8d,ea489819,37fcd12e,74339578,6482ddb8,9226d9ef,50cee6b0,89e48f49,b3f5d154,52e47c17,e1a68ace,eed3bc6,8002a70,33316116,ade02b90) -,S(b64180db,3b926481,74a0b743,1f84af72,f1118e9d,6cc1fe02,f0bfb72a,97c441f6,b394f997,83d00816,267a4f0f,8c95a05c,33cc19db,eac704d9,9e1f0c2c,4fb25fd2) -,S(2173f38c,f47377c6,d977fc08,ebb67f29,37e96fbe,e46b2115,b260f03a,216b5c56,bda02a78,3c4a684,fd88c6df,6becf56,3bd1c61a,4e79d36f,27e22fb3,212e2abf) -,S(9dd9ecd3,f3732f0d,864df0b4,8cf35e06,ea2b89a6,a8a2756a,222e266d,fc5c5214,e42ea720,2ba68242,ed9256a,57db94ad,dcf00b1a,50ded06f,a70d712e,17e921fe) -,S(705f9fed,5cebb62e,dd549526,af729092,9d398232,604d136b,2a121cf,e7af71a9,bb2cb17d,aa4472eb,12e69a4a,57a7863c,2b32c100,a1601d2c,44d2cc29,750d30a8) -,S(f1a908d1,807169bd,7fb7fcd8,cfc125e3,3fbcdaa2,8d8df1a2,17b84c2b,2cef4410,e86cc08,804c6c56,f81cfa75,9851e67a,d792bbe4,87812cc1,4e7aa468,b8911512) -,S(db0c5d79,35693c81,c752a475,6852260c,5625e434,5247cd5f,d40cdc24,e1355f57,120c5ea9,fb00d295,37721f1e,2539ebe5,d0de9bd5,354ce629,fe8c2e8d,c683daea) -,S(5e4d5935,56007e92,1b158f68,3411da86,e979d470,7b53caf5,9a2ed94b,ca423ec6,71588b00,1a0e9ed3,27862fb3,7ce6aefd,c309b5a0,928766dc,b947773e,6272d935) -,S(1a79ee08,3c46e5f8,8e97fd11,22410164,a264d106,7ecfabcd,4872af40,4fec7f28,f928dbfc,49bf7553,356289f,18a5c8fe,54f94bd4,d9406aac,c4df7a32,32349111) -,S(e693f88b,e3be0c46,cb40a2d7,f3a0a435,1c3a1812,4abdf46e,86ca3af3,6cac5468,55f0b7bd,24ab2a2b,aef2db89,d8aec5af,fb4f354d,66538efb,78f094a6,dd649cc4) -,S(6d15e8b1,f3c73c76,f73b12d4,f5e96e28,43bb6157,5d0d7e58,1bcc551a,329ca25e,f21f3ee1,84386427,32a0d05e,419f8a59,173f8cbe,6e3b765d,b74c3588,2d7f069d) -,S(48b8f127,b2614af4,95303f2c,f6593d16,20dd98e4,ff536dc4,8a5aaade,3bddb682,8ed1b9ba,ec137c62,5127e23b,55d786d6,a50d191d,6803ae99,c7ce57ec,2f546e3f) -,S(2ec32631,ee1e4510,94719f29,1a32e0a0,8c29fca4,8ff7e3d4,170a7c0f,5aeb3028,eb861d9f,e21b536e,58d0ee35,9d07d09a,491572f8,13eaac91,6105785c,697aa945) -,S(f7960ecb,3b35d4d4,5ed2c13f,b55cc944,7ab72f66,ea1857b6,776b8ca0,afafce3a,90245cf8,d40f6b40,a7140334,da02eea7,d8f7cf7f,8f87c510,cd6d9ae7,8410f08a) -,S(a94ccc3e,4b22f7e6,ef385780,d58f3aa1,139b29b8,c7dcb5af,7a247125,ba613ef2,ef7050fa,dd6afa0d,a89ba357,cbc6a66e,782471cb,8cfa4c45,e94d445d,a2845409) -,S(e48a7ff8,6d80f430,d3d6f57,6c56f026,8c42b3ed,17086399,56d62f54,f5485c38,b1695229,b4997b0b,229e3c65,c7ffb42b,e429b702,47b98231,a7bd9c5a,5e9a6255) -,S(df99488c,7d46c83a,cda5b422,b2a633d6,cccb09bb,f6488d9e,ac79e9bb,7f22d2ae,89490280,a958f45c,4501a878,5bd3c72b,aaf83a45,d91a38c3,e0477562,f345fd4b) -,S(a150c6c0,4db9f9f4,6f64368e,bba348ef,2bb4e43e,29b27770,553ef41a,ef22fd84,61dfaa74,e1525a0e,c3922ab0,20e3ed1c,e7b5397e,b4485cca,e1f64f29,19c5c201) -,S(9b7dedfa,452ec6f9,1d7aa167,bc984a28,937392ff,d856a4e1,204aa541,f3aa0edd,a37f4912,2f5168de,bca0ef6e,7c9b31ab,b4262c09,ccadbe79,10a4a844,ffd2c74a) -,S(c7d77a51,6d0cea71,b20f75c5,579a5906,ad1aa83c,f9209a23,d38ed358,28e51904,399a7c7d,9e1a3660,37b0a7a1,49b0dae9,8e5a288,cb5ece7f,56de4d8d,74a44bd6) -,S(d313a829,8e4de5b9,a166c2b0,f73d9812,fc1d1dec,b3b86e8d,8062794b,42fe73fd,6524463a,7eb26e2f,34f062c5,dbbdb4db,b8514c9c,60af6a16,fc9a8830,1f708fe4) -,S(4bbf363b,4d66c693,6469b8e,83c4f18e,2e6c2a3c,498f38b9,787607fe,97211e5f,9e42ca4b,243872c5,8c7b6406,11817743,82bb0d59,c0de2562,9f26e8c0,7d1c60c3) -,S(3be10ed,23a0ce86,d4a7ef1d,a667cf19,d471bd37,7467403e,3f84535f,861e9cf2,bb959378,cb317c0,6534748a,49bb9fa8,edfd2090,cb95cead,a7b0433,4066d885) -,S(fcd1f880,d723963c,829074ec,8d29eec4,946da198,cba5d96,b169cdb3,5dca2076,9489bce3,a31362e1,c4cec275,5fa5fc86,d3b105ae,25bed346,7c0919d3,b2a87b01) -,S(b5fb358,993d3662,b2e7114c,d8ea0681,f39f42a8,52cd217c,f0ec0271,fab317c4,89d88eb8,ee622cbc,f0dbfa82,8b04ac27,80a653c5,14df734a,791b3bbb,f3a71b43) -,S(a86bbad1,7fca460a,4740f39b,d2ccab3f,30fc137f,604e77c9,55624815,8fe274e7,c26dc259,ba969ac7,8d294742,e4962c07,1394ede1,263f5a0b,d03b7a29,30753fb) -,S(ed321f6,348cbc96,7e34bc7b,a935d129,9dd3fc94,c27d1467,88792180,1330d29a,b4078360,832b5de1,c77b44d6,cf07bdc8,fc5ac402,15002135,1be0d251,a3f7c3b5) -,S(c8179275,e4ddb936,f55e827e,de094c4a,2c425b8f,701fc979,96ed7194,1ad17dea,d99f1c5b,e241d165,eb49b0b9,266486af,8ce5e963,c52b2622,e16fe99d,d82553a7) -,S(6f08f13f,23b9b383,49274328,3f8dfcfd,eeaf82e,1d91e512,df1d0d7d,de84985b,96b6a829,f99f433a,6ee58ed0,50370ac5,665d61e,22cc7a76,a4a3fe08,d8bd602e) -,S(9443a7e3,410f9d4f,ef9f8b60,9eac3e5f,e6ab5d6c,a11855e4,b35c7e67,9f8f9d5a,d8c507b5,78188c3f,31bc93e6,d07abc22,ac9b2add,5a11db53,8fa0f936,3beded57) -,S(432ea8ca,3ed53681,ad3afcfa,570056ed,d38c8848,de293d2,e37703f5,133c502b,9e19228b,70b52bb0,8e66a49,826c6a61,965dddc,64270118,faa3389b,6bedff71) -,S(1d17589a,42f82fd8,c5a584a3,d3c7fed8,5e22ffea,e2b732c1,30f903fe,1982403b,9f7bcfb4,8f18d208,26564ed0,245f0c6b,511e965f,be5e0e94,54e0f552,78c39ceb) -,S(743399b5,cd84846f,65e778ea,790412ce,1ab8c6ff,ff7c098b,55436a1f,e18e6b2d,dc6cc81a,82801be4,e6566d3f,c01b6fd1,e84ff49c,e5ccf145,fb1f49b2,d8b784bc) -,S(e4378558,3b2848c1,62e3e80e,3b5f9242,5330d232,e05f871f,a279a0da,7910b2a7,c39b4171,aa4978e4,7d3f99f,8179a189,d5e2421b,d076d1f0,80cdacf0,55624b68) -,S(eef768a3,1b1639a8,f1755ac7,d00a6463,8f8a99ce,f5f42a10,664026b3,6718d63e,2a9005f4,cbf4e686,1af0043a,fe97b065,878efcb8,8be29ef5,ee648473,1e24a991) -,S(15db4687,2504612c,f40dce1b,d601d848,fc2afa9f,b2de929a,1800caa1,bfc91fe9,a8b6e64e,7d508d9a,504678a9,d90b82ca,1e72360b,95a2f515,f17710cc,4e7eded8) -,S(ad45facf,2529a84b,9d28d2a0,456a1fd9,d2b3303e,fc78e2a0,c7757bad,d4a4191,1a78e571,473f3035,16ef5867,8f77d5ad,bf8d8109,60f9925a,a6b4a88d,3654f069) -,S(41a03744,6e027b4c,eb775050,a892bac2,1c19b66d,5fa4bd89,58c949b5,b9151824,ed7c44dd,fa96d38f,a721cb2e,60e07a84,27c53acd,6435ce74,bb45437d,95140317) -,S(2020b869,58f4c7ff,2cf64589,f1043d,5a70d5d6,dac0740,56011f1d,27217ae0,111959e2,2757f431,a1994617,124eb1c6,b37f5961,29d52aa0,490b94f7,e1c4e9e0) -,S(2f99a946,859f74a9,50f3bf27,d85a169e,99c5f755,71000180,283383a9,eabd4ba1,3e622182,d3caeaa2,47a4ed24,6e608592,36ecba9d,4e8d79fa,12854f74,df89fc53) -,S(ddcf3989,57f65390,167688c,2e227f29,e7c5675,d4a83a3c,177ebdd1,9e369baa,a700c63f,3fa6833a,239a3cee,a90dd021,c3c3428c,f2b11b87,3da1dc01,2f4b2431) -,S(9863a7b8,4252360,19e2fa9e,9319c5b,92df1eaa,c0b7917b,73bd1042,191ace4f,49a499a9,281dab21,4bf09f8c,724a30ea,3a1fa7ae,4f1b2b6a,3bf63562,e03b69e6) -,S(6c5465f9,ea2c5917,34f3734a,64b8e92e,19cb4def,3c6d5d2e,467a8f58,dd733886,57e22bb,179df35d,15aa2616,a319ab3f,768f655f,a1c07c8d,3dafc443,1e0e733c) -,S(ab375513,360b3beb,d0ca387,fb0a0690,25acb654,fe703a53,d979f14,50f3fcdd,3e9c1149,309a2de5,9b7842f4,3c37a6ed,57f0f776,503ee7c5,46445c2f,6c41be4a) -,S(6acbe3ea,4a72eeb0,b23aee37,905b22d0,ff0878a9,e9143111,4821207a,4c2603d2,1ecefcbe,9f934d96,a163dad7,6c9e6806,ac2ca23c,e495a533,aecb19d,df0d32b9) -,S(7955d144,58fd0c42,5e4ac9f9,c766e253,b4ddd105,7f1c8c3,653f95cf,3a955d89,8fa9c5f7,304387f0,94a89225,53a20287,40c6723b,d25245,84735024,9650aaca) -,S(b5972d0c,90433f,702b25a2,27bd3da2,d488ebbf,e5782132,28c20cd8,35ace377,235470bf,7fbc3de5,279ef70e,d174b2fc,e3e78f84,5c0bf212,cf3d64cb,42b008fa) -,S(a266a810,33a5fa68,a204f3bc,53cc79f2,cc500d7e,4495f8e4,d9cb48bd,4bcf886,31a8b1a1,958d15b7,664390e6,a46f3e37,d52b7824,5b0b91ec,b568b7bd,f55949f8) -,S(1c6412ec,21191b63,5bbbf47e,1e9f7c21,ae7f4f3f,7de0f123,451e421d,44b9cc15,833f8a2c,1111c4f3,f5973851,d0256309,6e7fec1b,22ff969d,82a62284,c42c685a) -,S(ee3532ab,17575b57,9c19ccbe,fee04ff3,8172677c,5e625f68,a7462107,3e0b7fda,f12e10c8,b2fd987b,83dff04d,cc48ee6b,4b704b4,92b2cf53,a9af4510,6e7e8718) -,S(5ed10fbe,4867937,2ed2765a,f7f5b4bd,52ef9a4b,96515e,37944d9f,ee1a3838,8c4eb9b4,9fbe3924,ed8ac641,25dce66,a4bffd7b,5fbc68af,2a8c8633,b4080573) -,S(fe348a21,f04c85ed,69fe7345,f73420e1,b8f6b859,7082152a,15a1d535,d01378d2,d595d446,c9f5abf4,5ceabd10,3e38e423,5069473d,7d9f9911,7fa9cfd2,81f2b7b) -,S(7140369,b7b64ba0,861e1c0,b5ba3973,b573679c,c091623d,bda88745,fb2436e9,f0770350,f9799607,28c3bc21,30c6672e,40dfa362,72c50ad,1f376a54,83a12b2d) -,S(6d14c4e4,8e981e3a,e7ec6b88,b1230096,a7465db,a8381bd4,aa82157,99dad15d,25e4d2aa,a5f2d12a,a4e635f6,db58b2d5,f9c6de8f,b5bea99a,50e5b050,e7e0f841) -,S(7931b9c6,a6837d7e,3620558e,55504e88,4dffe071,5bb628d,aeadb0af,1a4383da,586caa73,320925c6,ddd12128,bf3bd38d,96b7a904,8422c2ff,9d5cfede,fbe80c0b) -,S(149e9d6a,35b83d43,5d0e1f32,a1518b88,88dca145,27aabd95,b0ecd0bd,e5cec834,45807aa0,fd84cc65,e91d49b3,8d012fb4,f87b11cc,1906e1f,cbc74c5a,ce5606f5) -,S(656b276e,b4b351a8,222f2b59,d7949010,1bf6e696,c284bff7,b809bd27,d297394,8746f309,5f8643a2,928ebfa9,a0e35893,905eb6d3,faa8e5d9,b6473281,7b763291) -,S(60f399e3,68086989,ee62370f,f7852e1f,3656a720,539880a6,9884b60a,f1eb02e,55dca05a,8347be14,85251676,d20b779f,9e5976fe,4def267d,4f1b2b6f,d444ad59) -,S(4dbda303,a67a41c,a46f417,54f9bdc1,34a305a,9018ce0d,4cadbe41,886eaa13,e062cc86,fec33458,d65f9fe6,4433b745,909a3b95,d23d7970,c22585b8,3fa48fc4) -,S(816ae1ca,4d64cd9,5a7c10c8,fd819c6b,f8c8b1c4,f495b111,d07f2a00,dd0363d1,c09f6bff,c331d6fd,56ea5520,8e9d13bb,b12187f2,d49366b,2dfd1c18,66526009) -,S(45839f9c,983fe0a7,c3b2b8fa,e5e288ad,87202944,c16d60a0,f18daf,8081b52b,f9368e07,4de74eb4,81f7beb,30835af9,aff40c6b,cda104db,2a785a6a,65dd8649) -,S(50ae4a48,3a49203b,1e04c482,ec2454f2,44b7157d,b23bcd50,63c5b6e8,d4223465,e1b8cfd7,e7bd2e1f,65f2031e,c583bda5,a619028,5c364658,36dba37e,7d5f3008) -,S(df77b231,60395089,19edde15,b21ace77,c5d8bb4b,ed26f9db,a694195f,616b72d6,8a4b75b8,9ecebfbc,b88cff82,2673665c,c99e270c,b33f3037,17dc9500,8b4344a4) -,S(ec6c0e19,978e2f18,b74419d6,70274075,6d2d238d,63b2d345,437b0b8e,f233277d,f90dab9a,2dfc4cc,62571dc1,35bfe4c6,96bd3968,173ced8a,4a363f0b,2636e553) -,S(2874416f,90e7fce6,a6d4eacb,1a722218,5af2a885,4852be4b,a4619011,617b3329,1f323675,f6ced648,8ba4c9af,7912ad7f,b8628e49,5b4da82d,448dd265,eaeb4466) -,S(872367ec,586d3a80,f8c87f3e,83b6dd3e,529de5cb,897c9d2b,e7dacf3f,70ff4247,e5bb60e0,fae0843b,788768b5,e427e009,7dc571c9,e4b62eec,eef68512,a6a3ac05) -,S(c10f2004,baffd30,ae430ce9,40c4af34,4339a0b2,13bf1f48,91b8da3e,424713cc,37be9055,f0c39b36,c546d456,b3f82edf,bf6dbf79,6343ee59,c3537fbd,8631c7ee) -,S(14e12ee1,91c83005,6bdf0f15,3353e80,733b8bb3,b93bc59d,a356dd94,70d847c5,e9707b8e,e00c1781,12b32ba7,c66d7245,d487f032,18d20da,b1550e3a,9befcfb2) -,S(dac3ba1e,2583379d,d2cdd89f,6ad053e4,3687eab4,ae804305,7b57823c,489fdf36,45e3da4d,88211519,55c20ab1,c2d1ec4e,d13a6942,fd37bfa4,7614745c,6fe2c041) -,S(d9bfc67a,5c086ae,e879fad0,b03a5a2c,a2507dbb,fdd2cb09,2644dcfe,bf800bf4,e015dd4b,5a39f5bd,1536c8b1,e93490f6,e5bb4e8e,b23e6ca4,2fc14634,2be6730) -,S(de6f3452,2f04ca0f,170d7e58,1d965982,8a9a981c,12f6cb34,761873,7996c61e,1ec16f3b,28d74fa9,43b9c251,f34e15f1,2fc6d814,ff024e3b,826054ee,f72a0cc7) -,S(432ab355,338e17ae,884a15ef,2365283e,b35c873a,4fa8cd93,f54bf828,a0e30eaf,f56066a1,a130dbf,8a3e076,720c10a5,caa9af0a,7d86ab9e,8703dcff,95447807) -,S(3d2e3507,cfa127c3,a350f546,d95431d4,8d96990d,b5beaafa,35a408d6,7f7c4d99,da60885f,4711c373,145655ca,b0f8a235,7f4a0508,2bbd2ac5,1b255593,a35f74f2) -,S(7f3f431c,b96dd4be,37c29d0a,55f3b71b,f781c7c6,191983f,4576e518,24ba87ef,f4df4345,7649d24c,2b8259f6,f7177b96,cfdb08c2,4e9161c1,695c8027,60b8bfec) -,S(4270bf59,f2c87000,44b6cdd8,b558e6ae,6f7b67d5,f128d716,3d604a7f,2f687143,358cef,2e8ff919,6865da0a,15a25524,6c4a180d,ed25174e,d08eabd,4da99315) -,S(c663722b,9930fc9c,4113af50,d51c6539,b7931cab,ebe2ebd,46f95b8c,7f603852,3443e7b3,2cdf23d8,eb532a31,3ca4b32,b94768c,78f8f13f,719708de,925ecfab) -,S(b0014864,e396ff02,cebd7b65,c66e57f9,168e8f3,95ae614f,21f8f162,c86c4e14,3f6c99d7,e2ec94de,ee65007d,ab501230,4a80b69e,a0e0672c,b7dbe4ba,182eb876) -,S(64c9cd93,98fe9da3,5d3329f0,ccb82e43,c2d735f4,d2467b2e,1250c410,da84f41a,d24b50ab,71bf6033,d1206fc6,dcedf049,c223ef78,ff50905e,c8d95115,564372e9) -,S(ffe0841d,51e05862,4f759706,b27db960,ecccfad4,cf326736,ab4fd9db,cd29b766,6bd1f1c9,f6956c10,4fec1595,24d8064f,eb5d8391,30b34a01,77c07491,79cf2562) -,S(d1dd0c0,c053c597,bad38d63,c40d1e7,4b451861,cf0f20fa,47fd3f9b,77ca7432,34aa97fd,b59495f0,3e7b5628,daaaf66b,5c9dc5ad,de929032,80ba23bd,6c55976f) -,S(87a436e8,c76bd7f7,a3e49cd3,af996f1d,9153f704,1b185d8d,f99eca45,ae8e5779,8d2cf3f9,12553844,ff905d5b,2a1fc36c,369ea4ff,6a89a027,b6dbe797,f11006f3) -,S(a54500a7,4899c440,384f707d,a8fd62ec,1801070d,cd5396e4,b59e9ecb,df27c379,e216444a,6d26bb06,5f5b5e5,72c927f8,5315df3f,11da2cae,2f334572,33cb2668) -,S(937ea4f7,99a319f4,fa5aea85,b48d6323,28417b72,8690a9c,88fbd51a,57d8187b,2931a7fc,9eb4aec8,b7dce4af,d14438ac,fce77bda,a7d3e7bb,b24c8554,cfdc9d9d) -,S(50793c76,bb914aa3,204dbc96,cb04ff26,c7060863,8d497f07,a1eb05d9,b7fa6f36,afaafc78,b5e30762,b68940df,41de9ef3,d963b603,6bb1ffbd,eb13fd67,4bdab21) -,S(8b600630,fadae564,dcd1c570,9bfe1ad5,f8da5282,61d55bf1,3a29766f,6d8bb5a,fbf1b64a,3bd0439a,ec45a7c3,859374c1,7885389b,9c201f4d,c1142120,6b2916c0) -,S(14e88bdd,e32a15ed,a37c9650,ffc18ba,1fc61643,22b167bd,635f3d02,e78c8458,82c1ec3,dc240faa,5fa355be,475afe0b,5cc2cd13,760249d7,35b1efe9,976f02c9) -,S(c201e4a3,24b68472,d453dc02,8c78b1c9,975a3d92,efc70a30,a912fcf4,991c6c06,263a954,41d6e6d0,8ebf3e50,3c786a12,a82f5f8c,d38dccee,62469e9c,f0e2dc08) -,S(4097665d,319a8b3f,71861b1e,11828cdd,4094182e,611b35a7,c5d10ee,99db4fb,ca0d7ceb,b1aa2b1f,576cd1ef,56ffee03,322a6b95,505727a8,5dcb70d5,27a506a) -,S(173d287a,eff9293e,dd2021a0,4be052d9,3713341f,37a537a4,45deab49,b427fa92,9626e204,f03a1886,c27c37b5,85725465,72e5302c,d3f9ce54,1fb9a46c,16432548) -,S(c923c74d,1b114f,30d4b03c,92629bed,227fb8c6,8f1f39e7,8f121a44,694d4256,58edbe6b,dd5e1382,108d1e08,ef022788,c9f91803,d8ad4273,1f413440,5b5b3d29) -,S(92fa7906,b1f25c2d,3df104c5,196cf31f,93e5a8be,6cb91a57,c88c4ab7,cb92d46,a12162bd,79341fc1,e8f74db6,2bcd0d9c,ae99a75e,ce588240,79a61751,c887f307) -,S(37477df6,f51f78c2,a9c8e17e,ed30d5dc,976a9c91,4aea94c,691aa3c4,8639140,6a6a26ed,1955656c,64c6e15d,e50b0453,25c3da66,f5067730,5c2d5fc2,a8089872) -,S(b5b2ee59,1195f38d,f834e78c,abf00fb0,be9bc724,36c5f596,67ada098,dd0521bf,10f36f85,95233008,46dd276d,951abe90,cc8baeb0,fd8fe44,314706e2,15ddd5e4) -,S(b05d1b8,443f1bfe,36a415e9,d307ef2,56039335,76ecb630,94845b03,d2a137bb,99fece4b,ddc90b2c,3102a415,6f0d63f8,54098f48,3e1ef64,65f7f062,7d066cbc) -,S(e5d711bd,4778b3bd,cefd703a,e9525b5b,d69dcd86,6cd0b179,de76ae8a,5d918fd,8af014ae,5aa05b29,a0c88e21,8fef5690,9685d524,af389327,5421c35c,6db64248) -,S(7703cab8,377a482f,bff1c6fc,4d137998,1e217d11,c424beb9,f4f1f786,86fa4f30,3323edd1,3c80b8db,c7e247fd,5568c92c,8dd329ed,420aff0a,8e903571,e884e8b3) -,S(f834af29,c18bb488,366cf722,52a44357,2c87da2c,c14b3085,5405f626,154f3cc8,2e8a0ac0,ca5441a2,9e27dc09,4fd5bcc6,6bd8f7c4,717615c2,82001fed,bd5ab248) -,S(783b093d,13f33c60,1db8ee84,51d852ae,13bbcd7d,1d03a79,4c774336,4bbbaee0,3aa90b01,cfde6abf,fa0dbfb2,ec2cefb,6b5fb1c7,41701ab,66ec9b82,74ae5b4b) -,S(be3cc435,a7770b99,14a243b,48ef2c77,3ae42e82,1c18a266,6f92da59,e01c3391,f0d3bd36,9118c58,159fc64d,e61ebc58,a560f705,25dd5c51,e6aa9276,5ce4a701) -,S(3e980bd7,adac00ee,fe362454,5fee1ae1,97f89e06,84576a08,fc909285,783b606d,c64f0e41,204c946c,74473434,7e091147,67455e30,53fd488a,34d333fe,e9c5c228) -,S(a6b04140,aa621e6a,34959bf1,29790d72,91d7b154,5dd5e7c3,35bbcfb2,d582b442,9cb2c9e2,9cc05d97,5e61d151,542af6e7,a997f8d8,ee42d37f,8041c169,abcce830) -,S(7ea7a83f,c133cb8f,a109a6a1,b29b2c3a,29ba432d,222382e5,1f280e2a,47fa721b,cbe384e8,8a1f7731,831c5562,ad1430a6,6aabab75,e38571b4,5bb7dd8e,a699d7e8) -,S(8525e87e,f0fc9ebe,2f82b5fc,a14ba6d4,8189f9ee,146aa6c8,d842aca6,90fa042,dcf06a78,f311a3cf,182a393f,2a34a570,192873e4,7dfe22a6,86c70e75,6b32c86f) -,S(7555a77d,fa050d0c,9ed29c33,765fe967,16dafff3,6cd04fc0,952a7b41,bbd56dce,9854c0a7,bdc3dc1f,d8bd0a3c,d0af3111,18dc0392,830699cf,d0bd6f1f,17152177) -,S(9ed142a0,7a0adac1,14e6f026,133e00c4,972bb3bb,bee62f71,beee17d,9aac296b,c1eaea41,6c80e3b8,d24d4006,f699af50,9f4dca85,11c27f6a,39150a20,2b7a9d08) -,S(a3fd2cb3,784d8ccd,92aa67c,8118fd80,c9d761c4,2e0169d5,fb13b1a8,dfc56b79,75cd9b41,55db55f2,d50fcdd4,8c90d58a,b0d13df2,7a09df6d,659bfd5b,f87ea755) -,S(2ab4be05,217e7ee8,799ad598,b9c0e211,554338e2,8bb6d42f,c9952203,605ad251,2c2a1a58,da066d4a,7fc8c8eb,83e1e47b,b788afc8,3c8c5dc7,bd8f5e31,5476d853) -,S(4afc2888,af8c1aae,af6268af,566ecceb,8c95d09,d9f8f359,2cea567b,8648c383,b1e26b82,5e69e92e,98902579,7e99c7eb,cf3f284b,e1de0054,58b59336,a84f5eed) -,S(dd800faa,92319d2e,48038600,aac1c2b2,f63f5fc8,dafd988b,548021b5,2d8e3d4a,59fe8092,6e0468d7,60e522ac,91881bc6,8fdbc192,14fee60c,e8e1a977,1039ed7d) -,S(84aaf3d1,daa3a5f8,89b9bc88,6afb07f8,7bb5182,6df9d7e2,af5a74f3,c6378c91,f4164ab8,45eadd6f,a6331218,ecce096b,a04fd586,b744f0e8,11c2a48,3835afbb) -,S(b770f2c3,9e2e9db8,a92823a3,adffb690,d2ffc180,b88cefcc,8adad3a8,27c40b2b,f7c6e37,9894982,5d1b90a9,16ea564f,7e319c97,ca6cd22e,79f599e8,dc0d53e6) -,S(a60608a8,a0d7e556,70145c5f,bb107cc9,7cb1db87,2493f362,36a21e7e,babb2b29,3423527c,4e414548,96406f90,6d4a3819,a289c91f,b580ce19,6f25c57,7b54de5f) -,S(80f470f9,7b7f393a,5e6b4e5f,cc911a73,20f6b0f7,fcabf2d9,21eb649b,53414597,57d8f2f9,6e1bbe0c,1328faea,13c3f3b,770fa14e,4b5b7e4a,fa1ce9f1,2bd9adc3) -,S(4e111bf2,1f5248cc,3fff0096,c64a7b58,72e4a3db,1f0397fe,261cb33a,995abb6f,249cf172,102733bf,5fd829c1,d60bd930,c03af614,31faab0f,6d5acbb6,96eb2b9f) -,S(7d8c0cb5,47fa1d8c,10254660,a20e85ec,960cb70d,f38174f0,18416c68,c62844c9,2d79ba3c,17ec4d79,a157335b,f358cfd3,72b0f1ae,1f6bc743,40400571,5f35a271) -,S(bc0d4cbd,95896fa5,7f23d48f,a5a9f2f0,14b132b8,9b5953aa,f612aaf9,670a0034,f5d06670,7b316581,7a641091,55773bcb,83d7563f,28ea5412,480a0f48,2fa0639d) -,S(b154a2ae,ad08d115,95eddbe1,c9321e15,5cceb0a6,a7e646a4,2dfe70fa,b6d37a40,9abade21,674dd12b,d01e586f,695c896e,17120d8d,9e3c756,c8b5e53f,3216592a) -,S(ef603c34,a6ce06f2,7053bc31,841fe2e6,314be756,7e477325,5315ca58,5772e1e4,f9ebbe28,96f3b0b9,923a7e57,d819a231,15fced8f,3bd08f51,64aae597,c49ad65d) -,S(a601176c,2d901ebb,ad5a05d9,1adc0041,14f7bda,1ac496e2,c04e23fe,82aa9376,f781ddb7,ce0c3649,3772fb84,9e914377,d59abcf9,d3eade68,f8c8a303,1ae88ab8) -,S(abc41547,b6b3104e,fab968b9,bc9a9027,b1c7f0ef,3a9007eb,27331539,5c31e6a7,cd2858a2,28f21d6f,bd8a1821,dd78399b,594c5bd3,52628dce,879b8a37,d97e0ec9) -,S(92890105,c9c721,b2e4c430,26e413a,941d1da6,d31b48a9,2f2e3a17,d87f5a81,c1cad87b,1bdcc617,1e432e17,c13b47c4,15c22399,a7cbfe2b,b3097f28,da60a5da) -,S(e520dea6,9f4b35ca,46a46831,9947690c,500a7a80,6bd64228,ad144a7d,c37ca563,6c00d766,ac3f8fbe,90355dda,6ad4e2d9,e2330b0a,db673356,638b0d3c,8a2a82de) -,S(c0337a23,e2b3f1c1,a57d18a7,9d6ef25e,ac2e9315,18f0ffb3,7502d701,c57fadc4,fcea5873,be22df35,4729c3d5,b07a570d,7ac7e938,f6e061ec,cdd2146f,50808b65) -,S(276c62bb,6a8e2c07,6b5fb6a7,62d1d624,1b796a96,f53593c,fa51279b,2981ac04,5c53a65a,bb6b01d2,3f9284d7,d696236c,773c4578,88f692b,73e2ea17,6e1afc1a) -,S(604e1e87,e5051dc2,b837ccdd,43c8ede4,c4a2de6f,67a9ded4,fad1ddbe,8d663a5f,f70fe23c,e3511973,93d4d675,9444d862,ace4c473,99c34349,2d06b27,8b429bee) -,S(f2fc151f,470d9106,d58b05be,5e9039ba,4aba16ae,f7e4ceec,3b6e3887,5c41f6fa,f49bd2c7,f1aa5c63,d8e7f2d6,e0769060,d4188773,9c16b7b8,5d2a9216,e1e98de0) -,S(8e031346,e9f34ef,3b81d9cd,7e46eaf8,7ee0b294,d66b0315,eb0902e1,340ac560,ff00c8bd,a5e21e1e,5127441c,ee0504e,6b028c,ec0dca,450145f9,2c394296) -,S(a8680f1a,d75b7a8f,27a1cbe1,6b2954eb,d4e26eb3,a85d1a0a,96b9f40f,e5a9970b,60c6bf41,a55bdac6,397281f2,a3f52896,757401be,c42964c6,9501973b,e6070c01) -,S(4d68a1e7,f4d82ea1,e03407c0,5085c794,9ca8c00,d4dcb066,128e6c6f,504f4658,85c5de11,e5dd3691,2aa95d2d,2c36dd6d,26a9550a,3a672af4,d36265e7,a3d1ce76) -,S(3708f41c,2a6d8649,6983cdc1,bd02eb39,758c0bc1,ae78a483,5c6a20ae,e6c2a7a9,310b799e,79b7f5dd,5c9ae0f8,7aab193e,3c2b7145,c70af9e7,f4553faf,abec4152) -,S(8c883967,45028c5f,f1b96181,43f5b732,2d1a18cd,3abb1a92,f6ce3780,a115f059,24563ad4,e4ae484a,c344180,66dd87c,40128e42,5c8dce10,b008a7e7,620725d8) -,S(c445e76a,7b377ad3,bdd0fd1a,94a7263b,652e83c2,6342305d,a0e1ff4,d58f8fb0,4bf5a41a,dc8ddb61,3afbd3c1,3aae7dc6,f60ae2e7,23065b8c,c94cea61,cbacc89d) -,S(4ad9613a,c8a635fe,60d9f1d4,da4b9fd6,36949d5e,edaaee8d,eb2f65da,8e419f16,5a9b5b06,8f67a0fb,3ad31c83,ef1a81b9,38745877,b4b07316,42ab4951,68b0d7c4) -,S(beb3eae1,958bfe6c,9ab49d77,648aa662,2e397fbc,58e90b0c,20d1d29f,d760c943,d5a46be,f43a67ab,225dc6fb,5aa68daf,ec76f27b,6a822678,dbaeff88,382c9b8) -,S(aaa9aab0,bc0e21b3,be3f1dae,ad4a076b,4623fc14,3e4018ab,9df9a19f,d134f397,9c7d7fe,19642c65,a6c0347e,8fa2dad2,d3f094f8,bab6790e,d3c703ba,2742e40b) -,S(553c1e89,99d6f446,2fd7ae86,f1cf9d24,d4011661,9fd5d356,604d6a55,ad99dc52,26b40d3b,8410ac5a,6d2ba776,f7c5f0dd,3f6fe494,379344ed,6460bd6f,f550cebc) -,S(859885ea,36378fc4,398dae9c,4725d604,c3d56509,559ed28a,b47ebf82,5aa1abc8,fae5aef9,fc74b963,bb2fd930,5b2d1636,e6e84aa,3c40b066,9e531fcf,f00687f5) -,S(5fb0a118,679c5d48,554bf7c1,63b82345,89e51032,a70c654b,bb7bdee,f0368f93,e8d55f0,4a6816d3,bfb02111,eb95d868,5b9966ad,39d94c70,a4cf1826,6bc2a2d0) -,S(a424347,86f3e153,c9bd737c,1e70ddae,bbed445d,77ce4302,194be82f,94f91dfa,27d1cad6,abd9fda9,c1012f4d,f25b69fd,a54239a5,8ec12496,97116548,e7beed46) -,S(5d007508,63fc1f3,a0a8213c,c729310c,39465945,72b083ee,f571b921,a0c821e7,e538fbc4,5d055a07,b2cc2605,61238486,d99bfa81,6b0407f9,39f1d12b,feb2df3a) -,S(a3eb25b8,97b10286,934605a0,e4aab7f9,e80393aa,71cdea52,5f82f5e8,282e3db9,e2b354c2,1430c45e,4236baaf,128967c7,6beec58b,e6890c6f,303d83f,71e7f77d) -,S(73f63220,8a133202,96f3f51c,d10fc816,1e309e51,4ea35f0f,ff72e09c,e897981b,43412959,cc78f32e,d6df7ded,349a92e,3095257a,8a1b5dc4,15ed073,a420179) -,S(5f0825d1,c21bb5f3,8f0d9628,f6046648,7760512d,f1bb9bb4,ccfec4e7,48da41af,debac60e,1d95de12,84f1abd5,b6592824,5becd4b8,c2496323,b374239f,fe5c0cab) -,S(cc42a6f2,b4a8e9f2,fae3f624,cd12294e,efc26dff,c66a676d,a10259fe,f7d84294,91b26600,f92cbd05,f13f2adb,2b5fb17f,118a7ae1,6a011690,1bae0e14,3b230519) -,S(7d56e0e7,6eebe13f,a81aad7a,8efbcd1f,4de0c5d6,bd136261,8f0002ec,6f635a17,95462707,fe55e3ee,46dca813,eea5de7c,51122ec,55a91754,f7d13ac2,43fa1ad8) -,S(7972b61b,4fe85ec4,acb605b3,aadb56b6,fba8cafc,3c764dc6,add54c06,f7a5be61,ba186670,2642fa6e,a7cf5141,c46a8e92,4764c4ce,5d45b7dd,9f4926c9,32b8c7d8) -,S(edc8a440,347b1500,899f6360,9674f90f,4344c87f,361fae0b,bbe08235,d5025626,2f812740,9a14bf59,9bcc7cef,ad140b2e,7bf84122,9a51e486,4d01ecc4,1b2cd77b) -,S(bd9b65c9,7a8cf4d5,2f727b57,19f99986,d4ea1bbf,25560d18,d54877cd,3db16899,59cf7127,4e878e5c,bf0d9e02,dbe4f861,ee9c8e3f,5dfe99af,7db98e2b,c2fe432d) -,S(27635e38,1191e8cc,d3756571,44c5d8d8,72d91802,5950a106,f3be2acc,4cf35782,c359fe47,a019870d,7fa3ab,8f51bad4,eb5251f3,7e6b8ce9,db1992f7,cd1ab7d) -,S(4492dcc3,16c05300,a96abad1,47a00e98,359950f4,95dfb261,839ddf21,3b21d85c,edf1371,a4e81e42,dbfb8c6d,2229dc5a,fafed4bf,a58c2433,18934ed7,dc9ad35b) -,S(f8124c40,409e01e5,8de8a386,9bd88f8f,25887fc6,cee37c01,279aa606,edf9c67b,e0071d1,d31fee0a,8a26269c,3d7f3662,2b0f008c,61e749d3,65560c21,a26fa6bc) -,S(cc597b67,66eccdf,a2c0716a,dd5e51c2,ce3aed33,8f55f0b1,b5784bc3,9a05a2b5,12e031fc,394a43d9,d1e12ec4,28e8d5b,df52dae7,f3ef22da,74e3a418,74682865) -,S(142cb2c6,bc1283fb,d2164270,7d525dd3,d4a45f71,a63222ee,6fdd31e2,805aeda2,bde93d12,c72c422a,e4d5b718,bec6458,ed082bfb,7c686f2e,1815edc6,5ed66ec0) -,S(fbf4d602,dd765941,e696704a,1a8977a9,c3327375,e3f0d479,68fd9148,c01d2d3c,65b46df7,99e895cb,a6d4cae8,e68f6160,c7b96fb2,9af7d18d,8ef1396,c06afa8d) -,S(efdb5d57,bb5fe8cc,e3300ea5,ec14c50d,f09436db,cc58ebc7,c6d123e1,8dbfffb8,39083803,d9a90c62,6219ce93,167bd89d,d444e47e,ddd60deb,8137b8a4,203fe01) -,S(5bca4334,faa30557,b4b36c7,b6bf2d4e,921f59f1,eadebd74,97690742,2c3f35ad,3c97baf5,e2a663f7,22bf2fe1,cd646db5,79d27f2a,353fb45b,520d227b,c21206e3) -,S(9aa1dbbc,e90cf065,5ad8a0f0,54aa6641,ff921e97,1a73cd4c,49ff1f3f,51156632,cbf6e81d,8bf1e85d,b802f0f0,b9cc1125,6e0b337a,b90112dc,6513bf40,2b1a4200) -,S(2fc7fc55,86ed7676,4d5d4d23,ddec2827,5386e56f,eff09b86,abaa9562,73c2d408,5bff69e4,773c34ae,e477b0c3,e0310b5d,6019a558,5d4c7f3f,54f9c810,69d6285f) -,S(8e5fb941,c3ac6f2c,43195487,80df9116,6ef3b210,f2fff34,764cccbb,d34190b2,dbe2c1b1,5f6668e2,c63ae154,ce7b32fb,8d29b59e,dcf1ac4b,1df9baeb,fd10d2ce) -,S(7a5bbb59,4748d6dd,5d3389e,aa95b8da,dcfbaa07,26693690,4801bd61,b3d49c6,c2d28043,a42d33fe,8d8b755c,61235c68,ca13861c,effe3fa7,fd4edeac,634187c0) -,S(95beb8bd,f0d33531,ae73ee1b,1b631ce0,917c2fe2,22534745,f87faf21,bfb76753,c6cf8600,d9c55975,527e269f,b4a0e4cb,b9bd7783,7e230ada,a43c2f0b,c64f45b) -,S(f44ecb0c,6d896dc0,304fa480,90ab9793,576dbbd9,76b8fa32,540d223,e2968d25,545064f6,29644329,76a03c62,9ea46a09,e20e470f,5e76f810,6d19f353,c321086a) -,S(8dd32cd3,3dbd936e,6173ef50,1f7ae265,d56d68c2,77061e07,4fb49d26,538109de,6b110e5c,80daac20,5392bca8,a47d6d90,ad158c25,a10c0851,ae985f70,7c3f1e76) -,S(3d4afd30,b0f0f578,d4fbc77e,b71d044d,fea5e3f,891cda8c,77075dda,6237997b,2816e0e8,664df57e,c793d442,49c23ada,ae286ab,e748493e,d83b1efc,58bb9ce) -,S(a9b739fb,beaa3b22,b295ccac,86a07ba2,b8391381,2d2be020,a5ffd17,85d95ff1,a1d08230,21d6a6ae,f696d732,3c43fdec,d3c5d42b,8ed7ad40,1a55b2ae,bfb84f1b) -,S(e9009747,e51251eb,fc2cc754,c8b55966,a37e5d67,acf9b632,bb77f46b,9203715a,34258967,9ea8f997,71b476f2,5571a588,756f277a,17ce3907,d9cdab4f,cef9df72) -,S(7e348ced,55aad74c,c24d09b9,6b332084,2108fe41,3ac4c6c1,a8376439,f21a3f2e,39874f8e,3b722795,d8465706,e439e4f5,c884c22f,365920f9,1edcf83e,b4389e5f) -,S(a7dd6676,5ec2d701,56f2cdab,f0fcc0d3,8e340fb6,8a0d1220,aaaa74a6,fbb1f55a,b7091bf2,ab00a63d,292ded9b,b00bbe9,63710dad,445e8e73,760a50e7,2f41d447) -,S(b8579e9,a8cccbf6,dc033a48,16d8934c,51c0852a,4693fa96,a308d51e,3f57025,e696ecdf,4d79151b,2f164a3e,bc11bda,42c88833,6f694fec,a8bcdcc5,7158268b) -,S(7b29c45,9de0080c,bf8c8c72,e7b59a7f,184f1c1d,46787cda,bb42c2c2,bff57af8,40de8367,a6d8d13d,41901ca5,60376ede,817578b7,25f4e614,5dc46de9,5f801799) -,S(1ceffa6f,89b65be7,ac20e34e,f0b7e503,d1c4e9d,b31fe14e,179afdd,96f00f9f,6fdee8b1,f05930bd,ed98feb7,81790e10,8e293bf5,bcaa6da9,79a744b5,1a76f179) -,S(556e2d6d,11d301c5,6d5d01e9,a01e2ec6,80ba4efe,a004de47,ca2d97d9,15e58d74,9588349b,b633d7b6,b55ba7ee,feecbc99,3d66e6c7,2f4d8961,8a2c5d7,5249d711) -,S(b3506e88,73b93dc8,ed04518a,42b62ea2,b97f7bf4,e9ee66ba,6a7ab917,a1e51586,474f8100,1230fb7b,fe693eaa,7acba9fe,5917a39f,1f8fe3fd,5823ae4c,1b0b3b38) -,S(d186af3,89cb4908,db01a886,f90ee67c,1ba7ff3a,19994504,e9774b96,bd2628f3,3b39782b,c6567cdc,b4778c75,a862ef36,d01d746f,f411821d,5d08f7ee,f2a2db7d) -,S(f951d921,e1065ac2,3fa45900,62c639d,19e8c980,2a810d55,d6788572,ef987bb7,dcf7ddc1,87f8e975,27db239,7f553b5d,51abc66,bb76a070,55d098c7,f9d7d950) -,S(8dce8e16,7bac6fc6,1161b75e,8f340e0b,8bcbf874,fc82a42e,bb53e0fa,c4d915ec,11ce53a1,4a9eb9eb,9b4b410b,34d26ed7,9c0287f4,9032f674,e3212617,e0ae940c) -,S(ce2d3cdd,a0a7a43c,d7d2ed15,ec12a7aa,755dfc5a,ed5a85dc,4f439eea,99e26e2b,6a96aebb,e7ca2740,ea75c285,3c582207,6a8eed64,7e21809a,36b97c60,7a5a145) -,S(239466fc,dcc2d4c5,cef367b5,c8339248,f712c40a,558c80f0,5ea390a8,dcd92092,f2ce223c,9b49f08b,ca63ee8e,98e01736,65d176ab,3b7d718e,d0e855e1,27ac28cd) -,S(220ab764,341d3c08,d9c5bcd8,331e0973,4a2f3c64,4766395e,f6a5fee,3563e033,ec1e4460,d03013ef,467dc7a4,2b520c03,aa51a9a3,57817f4c,f9dcd837,56df5011) -,S(d5455dfe,16406a6c,70fffd81,f3c4d10e,845f0b12,64fa3db4,ee2ffe80,904b469f,a0f93b8d,257e1e62,265d99e4,9158497c,28a20af0,2af959b8,8810a10,60aaf9a) -,S(52367377,a1f6f05d,df054665,f1eec0d2,f5039cf9,cfc1d37e,1a9d89f2,88e60c72,78d89f55,430fc352,cd58d047,7e2497a0,d05e7016,d98f9ce6,a039fc5d,9ec7bb41) -,S(5b996113,3ecc9422,26a3dc88,67364125,a8e569f1,912e6c9f,4c1ddea5,5fa56395,bb9d7764,12076caf,5d8ac902,c5e2fd5f,f7a0bcaa,10898f19,10142af6,4e436d0a) -,S(f36cdb5c,bfbed1e6,58c7fa4a,5b0a6773,eecd1a43,db96cf0c,7c24f32,b84c13fb,cfc6d2f0,5ee9eda2,9156aee1,81b62659,993744e7,479379b9,3156c919,18c394c) -,S(3208c58e,25107af2,b38bf754,5531266f,842ce33,10ec7e44,595fb91,7079a6f9,831c6dcb,5346b6c9,605d9ab5,895ec2cb,653599a2,c88801c6,45a4758a,32c785d7) -,S(a6073a07,1f8510e2,aa021b80,b44d7356,47253583,6501a5a8,c5253918,8c9927a7,e93a9fc5,4c8a7612,16718baa,dcfc9bba,6fefa30d,85803246,2a9f191a,6364fec9) -,S(3350b462,f79eaf7f,260f2147,6aa7ffe8,f7ec1a7e,35624713,9e335758,b9f0d913,1f0c9db3,fce1222,fbd2341,ba8d2e93,20f33bc,482a4d4e,80571711,21152959) -,S(a54d5b17,bc82a74,9207c89b,5a1650cc,1773913e,66f6744c,11de24ce,3073caa,3c243b5f,5309dd11,83c7fe5d,49222c9e,fe62dc26,f92b73af,cdb7b7b1,32cd3ab8) -,S(6590a2bf,676a7a34,a1424f7b,1c7863e,8a7d346d,563905ca,e5b25729,4a04cf8,11cd5803,490419a,1382d972,eea2f734,4f8d0cec,42466f09,39650645,a3e781e7) -,S(b3c09c02,9fc7f48b,d2f461a2,a367011,8840393d,fb5b9592,89e96ec9,c7cba9a5,e7b5aa6c,bce54ad0,197bb1bd,ac030e2b,c6a3e6d6,af2db60a,b97cc92b,8f5cfa9) -,S(d7968ea8,44a137a,7db36143,98b29972,cdc693ef,8fdd4644,26a92939,18fa8bc0,82402589,2901434e,cbd5dd29,410ce2e5,56dd3174,d74da2e5,28326ec8,ad57a75c) -,S(8a57bc6c,2f98f9cc,d1eca172,b2501adb,3bf6edc8,4b50365c,6d959f00,838e8304,2ebf5462,a0f85985,438b5d67,cbfa68c1,bf643410,11a478b9,92cbfe0d,87e7d14e) -,S(51886841,684750a8,c3cb8d18,f8c863cd,1a555dd3,7f0efb4e,551d0d50,6073fd22,eb05f09b,9e983ad0,a6ce0f15,c2f5983c,6a28ce50,6c52f691,f30517da,36f3f192) -,S(fea8c35f,27e4794f,a9eab856,615d55d2,d3a02616,9b9eb7b0,ab7493e2,f67c85f3,c325de97,cf0a6e3a,98512337,8e2ba2e7,b24158f5,4aa97c88,9b54a502,8c148864) -,S(6612cccc,d7bc25e4,f8dab955,d5c1c9cd,d79d5f69,7ef4c510,77b5027e,d1f94b63,615512c1,7a378d0a,e7aabab5,253df9b,e9bd6a80,15c3b200,73d0499a,3457860b) -,S(c998b07a,499859db,4c9d698,33199956,f8a7ae67,9f6d3533,cbdbd7e4,a86f8746,d9e01371,919e775e,a259d81b,ea206e9,37d6b5e9,113838a6,6af11bf0,8dd17138) -,S(5c0e4669,c5cf965f,854fcd0d,23ddc908,c32e3915,460d44bb,520fb0c,3a4cc1e1,cfebbbaf,7e0f9a4d,d2f35ffa,cd0f7cb9,89f5eded,c8b3c554,64fb909c,675adea1) -,S(d0fdda48,30385167,f06f6433,c6a9d3fb,7ab3195b,64f9750b,cb2dbfb8,7158c0fd,4cde5577,6a34f61f,c82e1359,8618336b,f5c6e315,d10abc35,8f0020e3,ef1283db) -,S(d925570f,d78bf65a,5d48265,6222ce74,7cab153,19b7cfd3,7bc70185,fa4a3e81,3c399a,c448ba90,1a21a5c7,b9c6575c,ff52bee0,cdd00ed1,673d8370,87c1924c) -,S(45d2b56d,81f84bac,2077d607,484b0802,a023cc4f,d7818f9a,1d0c2187,98374c8,14ca18d1,92a9cb37,ad50506e,a25663cc,9829411f,848bbf05,3064041,9c19d7f4) -,S(6ad3ac11,8588c5bb,f793404d,df9a10f8,ea8c1978,65a93fba,5b7170b7,9e157400,fa25741f,1e242c3f,edf20e80,fd76292e,382eb5ad,1731ec97,a8762fe9,811686d7) -,S(5da24445,b6dc960b,793ea9e3,912b21d8,26d54028,2ddcbf5,28e1ebf,4a595f52,bc18ff8c,ad1dca69,8995063b,ff8a2fd2,fabfa0d9,8c8885fd,1b401f3,65f16026) -,S(ddff6468,11ce86d2,93b9b89f,865d7133,d7b5f189,d527cf44,5ed15efc,ad32b346,7260e994,cb22016b,e121ae08,12b01c3,4d236b67,13ea510d,b1aeda36,567f5737) -,S(a8b9ff3b,9120fa93,d0f2f50b,c8509846,c1030d98,dc9d5243,6ad9e69b,f897f029,5cbfa29a,4e516872,ea9a4c2c,a3b07efc,c866aaf6,a2b1d7b2,3597e332,8466c591) -,S(943077fb,177b9d6a,723c18ed,ac8deeb2,62875264,868eceb7,a2fc1a01,51dbcafd,219a9fc,41ad01c9,d3f8248d,ac7df93f,ccb6e312,fa5fd442,e48f4a95,18e7eb4e) -,S(75cb61ac,9c9817a,fdf60f52,4245ebbf,82b33f9f,a564d74e,9e810f36,6458b8e3,aa8135bd,f66f0843,460986f5,f9df6b9e,66441477,cd58cfb8,5b3adfde,ec03c367) -,S(1bb7e177,27cb8e85,4bc922b2,28e7f0ae,c34fdcf3,b9bad0c5,750e7c8,e31fccc8,bbf72886,1e855e70,bd9e322c,2425cdea,855ea00c,3e6263d5,2380da38,c0221ca3) -,S(9443384b,39e9dbf3,45b4b41c,f05d0f30,87f02471,c98e2a2e,afda94da,8bee8dbb,e3661173,ccb211f6,38cac6e2,27e3939f,e7b5da57,f6f7a504,abae01c8,fa4544ee) -,S(49bd15d5,a68caab2,8d51638a,ec1a9668,b4c27d54,d6691839,61ccea76,ef740d25,648fc868,8760e47d,fbfb9f0b,d995cc0f,77563b60,eacf3e57,9db7439f,3f18c6e4) -,S(d0c7b78e,92809e85,84d3684f,d078907e,c151aa78,a5832f90,73f945fd,7acfed85,a80d95ab,be494a40,b5529046,bc305203,be91e475,22ad9d57,7ab95b3,8e970c89) -,S(debddd46,3ab22232,5e98f9c7,5cdc875a,7c4c28d8,79748bf0,cd96bd7d,92eb9275,d103c8d,c3fffcb0,5ffb3dd7,a73af259,50d02064,b12bc754,ab594c71,ab9799c) -,S(1d79b17c,192a6a15,8ea2d6bf,9da07312,9f9ebcc8,54b02dc3,3f64012f,1bf33998,6ec818b3,dbc1c8a8,50d986f,bcf64702,c787682,bc408a12,b78e6bbd,4cf60a5e) -,S(2feb76eb,ff5d47e9,7289c38d,7d1535ff,74bd3b57,264c5844,9edfd36e,6e81ca1b,45bd4e4a,7ba3a823,dfae18cd,1f9cabc7,bb462e74,7899c899,378c33bb,89f93b74) -,S(14d0d90,faef5a77,f5372ab6,2e4f5efd,3eef1b39,498653c0,6372fe0b,b0682573,517f169a,80c2b930,4f530f51,d7196831,601a4f97,72ba1312,36ba92f6,36081453) -,S(7306a7a5,728f91c3,384bd9ad,b10b39b2,ad094137,46d2e476,fd522abf,ff313321,215e22ab,a5b9e87b,35bbd4e4,f492f1b1,574c85ed,25b86a85,a8e17b81,b7a915a2) -,S(85d8454f,870cdb8c,b32873a0,698fad20,fd24067a,737e9719,76d4d362,6a55aaba,36d63c0a,36eb9e8e,522a0715,cb9c833d,539fe7ee,111af3bb,951434b1,3117e4a2) -,S(c68f6782,993067aa,259b21cb,9e19122a,2f7da28,96d8cdff,c1f0a0e4,b34384c3,74e6e96a,331c3387,7ea484fb,995d6a3,8dcd493,6b2994ff,b7dc3681,3079e94a) -,S(81448111,5dbe5550,846d5c9c,3351c89c,e29cd850,6870a17f,e18e3184,4214dd3,75dd78b3,d4cdc29c,697740e9,2478689d,540ea33e,5edd6785,210abcb1,670d19a8) -,S(310b5b19,de24d478,f5f25993,a706f21f,24214e1b,cf614ebe,3e204815,60c945f5,8b42c6ca,f01d205,e09d017e,2e840d69,bf04cc53,f02a21a1,47e33327,104318c3) -,S(cf8a47c7,4bafe2b9,dfde4bca,b2e6d451,b0a90f11,c684f420,a025974c,bc4bc3e,f0b7b264,a9a78699,786331e6,2c8762be,614d8a69,c0a65c3d,1cc201bb,e34c97d1) -,S(a0fc6226,7352a904,e70100ec,63d3b60b,ab553388,69b982d3,3d747af9,8b8650fc,ba3ae54c,16b24eb4,64b88c39,521c399f,cd162eb3,f9966497,e2b96f2b,3b85865f) -,S(aae5dbe2,535edd47,584d0339,10045333,2e1eaf70,a4e1bfb0,7dce3c23,6cff8bdb,7cfaa5f6,e55806b7,bb278439,2473732e,a51d85c5,a3558321,91195533,b7a7449b) -,S(8a4e9311,5b897550,cbc0792f,b2705a18,5c317226,86da5bd5,b0a17bb,503ae39,1623adc8,d85f08c7,1751b976,daa17572,2442aed8,a9dc1692,2dde923f,d17cef2c) -,S(cbcef535,eca90b09,5295cd61,29010259,8627e1a0,ccbaff26,a51cdac6,87066463,651c2ffa,c2a2c99c,3fcafb9d,8c50e156,498fee17,3462fc25,9d87fb8d,6b212653) -,S(25971559,4d6a2bd0,baa90e33,62b9c841,bf12c4d,2ead6609,9902eac1,ed0f8c99,49e01b6c,c97404cb,8144002b,c33e8bb1,d974dd22,d0a26a82,94bad2bf,2875245e) -,S(b754d68b,2b049f6b,ac389044,c80f0364,a707da5e,3e9b2a89,1672cd29,b6f1445f,1b29b7c1,625e23d1,67092e3e,ddfc2f4e,bea55542,5f4ddda1,af2aec5e,4de37740) -,S(20aea5a8,50e68f39,cc7ca2fe,2f38b5a2,ab0bde8b,d294c40a,afa898ff,4f084037,6ed576b3,f17666ec,6aafd6a5,6fe7e1b2,ab1e883c,31230fc2,b4e1df0,3f59444) -,S(26844e02,919de923,3288cba9,a97eb85a,c6939fd0,7cd01e7b,f0d5e1db,e31979a6,3df9a8e,6a5fad1,266f11e,518fb60c,cc08a6c2,832c45a1,6c7c5520,5c9ebfb7) -,S(11afca61,33a69aaf,27cfd413,becdf9b4,efbe0a6b,1a38b3fd,485dca95,dc28414c,8d4b8790,c0677fe6,22847bbf,8e47b400,9e4678fb,b9c9377b,2121f5ac,db737b1c) -,S(c46e14d5,2fe25d65,37bbe09f,ce7e95e0,4986337b,23e7160d,f3d78dee,e8d2a63d,a200fdab,4211e9ff,2d008dd7,7ddf67a5,1f04b9ef,43fa1758,9b175d58,f5d2b723) -,S(570aa12,578afe09,245f598a,210a7605,2412283c,8f58e142,d31d9cd8,d455e4d7,c28fdb61,f8e90de1,d43439e0,8512a071,9a2beda9,5d0a5601,b932c0f1,2cc50ac8) -,S(d312db5e,88a1cea0,28570b84,e3854e16,224236ac,cfb14d1f,3a33108d,fbc3fa64,ca5e5089,1843383c,845fa0aa,e031c930,64b8aa4a,ea72e6cf,36b617f6,cf97e1de) -,S(1ee22876,9981670e,14da9ad9,9279f001,c9be5eb8,76224a6d,1fe4ec08,aa398087,62101114,e303e37a,dfe42c65,54460d4,b68603a2,580c7452,6ff31c9f,2176dcc) -,S(1fb9cacd,e2b84ff4,ae85511d,1c964c01,1700b9d7,2d4c04a9,4afa9aa5,57bb81a0,430b73c1,295c5f2a,d6d9f59f,74201435,15b1306b,2cfa038e,e0456752,5f737fcb) -,S(d04cc82d,d3cf0b47,69f2934a,9807e743,4a998bb9,fa44d145,f191a176,611c085b,7a4a19af,b551d151,c42cf1ca,ce123dd5,8f4c13ac,c865b92d,15520169,1be5fa9) -,S(1e4cb208,8bd4d17e,ba8b97f1,f27df5df,8a544f8a,548dde15,712e8704,cfe7e9aa,d805c61e,b72933ec,e799930a,53fda3f3,db066396,5c71be51,5e8466cd,a59b828d) -,S(520aa398,707a85a0,d672bbad,cbcfdab8,8f769f69,df3de8c7,17d6dc48,de51590d,98d344e4,a9047a22,c09095e2,f1176aad,3b54724d,998e052a,39a52554,4ee9ada8) -,S(3a9fe3de,165bef7c,2e0d45a0,60693fc8,e7080ac9,783245d7,a79cac6e,7b614ef2,5189446,fd3fdeef,c7a895f5,2934c888,7607ff49,aa6d798e,151061ef,73038d4a) -,S(9c929dcc,c26c0805,e4289a3a,2b6d68c9,8e3c6806,43730056,65fd8e73,da149938,6dfbf940,b4c29209,3f39f6ba,b102762a,c81edf2d,aabe6dd9,56aa140d,396ba2fa) -,S(355b60ce,f4e00651,8baf1e42,e5e7a08b,ee22abab,c69aca66,d117748,89be419e,7f478a3b,b277fb10,5fe0eaaa,cb53fb73,4fc01dae,bb44f1b1,ed146f43,fc2604e2) -,S(76bff14f,21ad4442,e1389bb1,c11e1019,ea966091,97439705,dfce7bf3,d7f7f37f,3855a291,376aab12,b5f4da79,bc22e02e,a29a34f8,9223f07b,93f6a549,8289d763) -,S(91bb9cdf,10577a3b,7e23aadd,35883396,becbb4bf,fa22e1db,fa08f8b6,6156b454,ec6cbb9e,4f149b02,edc53e93,d1611b5c,a3edea42,c2ca9a1e,f2cccf25,94edbb91) -,S(9e56b10f,1ba86c61,36481204,f0c45b09,a7dde7d,4eb32537,f8c310a5,a8865562,cdf3453d,8552c16c,48bca1a3,79ee8c6a,8b523eaf,d1862d5,16f4361d,5a8aa67c) -,S(4e73594d,af286bde,4e6e28a4,23930571,a11dcb75,4e9a4af5,f4972d,988e09f9,a59f23d0,70c042ce,e03d812c,ea274035,af0d8e53,828a418,cd1b51f1,458a36e7) -,S(156fdff7,e92d89fa,691d3c55,7cb2c614,393d5973,4b11bb1,d9fac953,3923d860,4e929637,c448760c,ef6d68f6,4665023c,bff653cd,23132ee,620eb013,a13b360b) -,S(f2c8b650,eb372336,5d57a905,23d34db9,70d23d52,1f893569,98b0a7e7,ae8ea03b,bd9ac314,84a99bf6,973422a5,60bde9ec,204488c7,6739583d,72f42a87,181a7881) -,S(27dd3657,a4a37430,5f5bb92b,a7b816ba,88d526a2,1ae316c,d4a4e67a,c751e3e3,880cfdd3,c0faa401,6afaf3d5,1fe975e4,8a756b01,f7d84e8c,226424b,83be3304) -,S(f6c25e0c,19f7357c,3cc5d98,1cc4b7f3,7a390182,c2673708,1c64f163,ebb3d1bc,8c80b3ea,7c05a0fa,39944d66,643b3589,29534152,adf37c2f,183e7c22,8e89e43d) -,S(c678800c,71305ea1,ea2847d3,d9d37612,ae280305,716fdf45,87ac7f4,a7fad4f2,be5ffbf4,d2fb2b8c,ddb49a42,ebeaf5d8,55d41d39,f106e2d9,2d549e88,6c0b63c6) -,S(f35db221,e66b7786,fc9e2d3a,68f0d1ee,f98177df,a05bfd30,931912e8,13f6d560,4899a808,e6b2040,89974ca5,afe5b1ee,9eccb15,36a7c7c7,bb67cc00,e43f29fa) -,S(2b93e37d,a915633e,db9843d6,c33888c3,5d944f04,c4074deb,d021c639,93e69de9,eb3d1095,c6ffa1cc,93f72a58,f1320efc,366a4a5f,c7250167,6f2d3c88,4b0522f0) -,S(818023b3,90454716,f51913ab,fdb406f,e4875b94,8b14a331,60901d1,66091b69,b3f5718a,6224e447,c5af3e1,f38e4f2e,6fe57389,fa7d8990,f98e44c2,a227e7b1) -,S(1676e6a,244ca69d,b2ae565b,65b14184,6645ce7b,213dc1fb,db33f060,3c662bb6,88e1cba5,deef5dc1,26b20830,d2c7c0d,aeb9689b,16ecc1fd,cf4a31fb,822e0298) -,S(2f931a1,a92537de,38629d73,323e2f21,d9657454,30e32e4c,3912cb21,dc298d54,93292d08,6fbc0fae,eef6fe43,f5626711,95a5b2d1,bdbbccc,52e1dfae,a30ef904) -,S(7ba4d612,f0dd8c91,8bff20d9,b4f45486,be8a32c1,122601af,2d1730c8,a1fd0279,8aad7aa1,f5b06431,b2e20af1,4cd049a9,3018e3c5,bc4c4310,d0234e78,d2401179) -,S(e8dfab0,85fe7a91,6a79b2be,723799eb,d6974d08,ccc8e3d8,5286aa61,c81d5e78,2121686e,519db556,e6595d47,a5487bb8,fbaec53b,b18dd81c,37dbab40,6e3f926c) -,S(7d5623bc,b1597ef4,6f907106,17eb2e6a,ea751da1,5535a64c,94c90c9a,d84ab5e,dc639f31,8004c4de,31514b70,ebe2e8b8,701b3cd4,5d66b7e4,204dcbc2,a0ce7575) -,S(8e81e2d,8074bec7,48986194,b3b82200,1e4ac916,81de2ad5,7b9c84fb,88a7ffa3,4085ec1d,f4a34480,ca56f6cf,762d03f7,fa94e99a,8df93e6c,dc781499,59fa890) -,S(a9d5a3e7,8290ee62,5e18affd,169c6829,73e68ac9,2b5cc52b,53ed3a85,a68da71e,1cdaad6b,f9eb5889,5189ed29,8793388a,8d6e8b20,ce47a536,ee89be4a,b4805fd6) -,S(4f7c17ca,bcda7c0e,3b7b313,4312f848,984985f0,e46ac497,d64b123c,57dba2cd,860bedd9,5f470c3b,f3cbe7c1,d5070cd0,c877010a,9baa8f5e,888b5ca8,a34a25d7) -,S(478f3d7a,9234a7b9,a91bd016,f55734e9,34b8c3c,535725b5,b4fbb0ab,9fa64921,db97a394,f0253f18,ebabca05,c21e9a7c,3f253054,d83f2101,8ffb4d93,b8051a1f) -,S(ace7e57b,73d96e7d,69f7cc01,b1da179f,3ea09aab,61fba329,f2552eb1,fe7963d5,fa0251f2,2b8dbd04,ec90f824,be025965,7e213e4c,1030611b,796efb89,26908918) -,S(cd56e867,f5170771,8253757c,dcdf69ef,4401f2f8,a1d09f24,374040e7,a908d1fd,878f7216,52cf0ba4,8a2b29a2,2f620c7d,83e4bd84,277b7b90,a454bba2,7f338fe1) -,S(3042ea5c,d9d2f89a,64b1dd24,97b25da5,67a2c672,ba067e33,e923e513,ee4d5329,b84c144,d5516a14,a0a8568c,d6d227a2,d3fa1d86,8e05e612,81ce41b3,5a68b1fb) -,S(55e088d,a094ed26,82b042,bafa0345,30a2e291,57af3f1b,ce351ec9,9e712ec0,c6f8297f,64398324,96091933,514c5449,cacadf,82d51db2,82c9d2e,c66b33e9) -,S(bd2db13a,69dd93bc,a37f9181,7a57a0e9,e0e0da83,eed71875,e63b4691,3b408966,46e12660,f9489b2f,123c25d5,f65b3f8,187ee6e4,405b8cf8,78a742a,9b0da2d) -,S(7d7a5110,cdbb8455,5fe678e6,24ed1a14,ef7c5219,986a7ecb,6095624e,7fd3d210,c9578dc3,c0a54524,f819d640,abaa4a04,626a46da,15c0867,72774a59,6ac6c37c) -,S(1ef12317,513b1354,2a966981,34edabc6,fd4e6d29,1bd7782,5bdb30f4,937a3fa7,e0e4b688,a391bcef,3451cee3,36a8c9f9,12319899,4684c039,909489db,590e1ade) -,S(effa0403,766fb976,dbec6b2e,332d2f12,9f463b86,8b9a1d19,49d30cea,1606baaf,8c5b1c83,bf3efa64,f38de1b7,da03de17,b0cbfdc4,5b4a03c2,38221def,bc1cb082) -,S(dc9271e9,76a9a042,5565f022,273af5bf,20bf780d,9d0ea069,df5da661,a087d65c,dc8679e7,b27bd30c,986f11bb,1c73b76c,55ce7c7c,621490c1,944cd8a6,b63d6063) -,S(ae1ddc2,1e1ca02c,218f6946,275501d6,a1336b93,ddb1b2,384ab414,b8264619,21c6b39d,300b6125,ec8e5c8e,19aa76d7,32466bc9,a887c76a,1ff4220,7db26b48) -,S(aea2c00f,fe5835c9,2b892480,83164635,33dd989,bf2bca12,85cce3ab,4e82cf5b,615598cf,935a6112,42a20e84,e670b193,9aad65d4,53ba967,3e8193b2,93dfa97f) -,S(913d0e16,34b43a86,f55b30b6,5914767d,b45e723e,636c866b,6348c8be,8aebf696,e14c6607,51affda4,d02574af,43172024,39c0c10e,148d4305,1487a5c4,39971a9f) -,S(4f0b3354,775cac80,5e0d6191,6bb0f9c8,40fc163d,8878c05a,301252d2,3bc26fc0,b0b75486,3aedfdf8,3a6eb2eb,5f3e25f1,6c0e1077,6e855ac3,fa8fc3f3,bd8da1e3) -,S(5da21940,73cc978f,7673b2f7,5c65ead2,f469df96,f80883b,181a3da4,f316129d,8516d080,743d2670,570d5e63,e19eb543,237b1db,6285b1ea,f3bc1459,8ef311d1) -,S(76e1b330,ca7af91a,ccb92fb4,63404d36,a8fbc132,269d163d,d4beeed1,6be74a23,10b39253,c5908ef3,ec96f2e5,2ffa0dec,2ce2800,31a791,bcaae0de,1e7f5326) -,S(c4be488b,2f210ee1,82f91263,78b23359,8fe8ef57,671ddbe1,d76975d0,ee393e64,bec1392f,a1a09a54,480beadc,b98ca024,b910cd70,f807eaee,10d4e270,bb79f449) -,S(546918d,a141fd77,b1f13848,d3d608c0,25f5be00,4d36a542,56d0ca5c,9333ff37,3d1d4c7,9684be1a,5cf00d71,6cf9a1bf,b0b82ba4,833704dc,c2d23e8f,39914ac7) -,S(cdfc6fc4,2c51ebd1,2df368b0,98ff0f40,2e6df8b1,9c67e10a,320c1960,266078de,5985e930,23e5264,547bef45,6b3774f3,c2689411,b6f7463c,febe068,fd89cb0d) -,S(7730fccc,593b14a0,6f21eec6,2408e146,36f0e4b,4718ce99,c99bbcd4,7cf03034,f17d0fe2,736e412,9c30151b,492aa7dd,52beacb7,6f97001c,cc28f991,3e016b72) -,S(8aa4c3de,474308f4,674c7b55,9f895bc5,d855a7a9,5fadf090,5726b354,7941b3ea,f275c44a,eac2623,1bf4ae9a,df403ed2,78d9da42,150c98be,7dbd5f71,5cb8594d) -,S(15926da4,97a4e925,8976f87f,f8940491,f32d33dd,7855b13c,5cb54d10,d325bb79,15ac60b6,5b1ebfa8,e871bf67,ec9f71b8,1aa03c78,82880d40,d35f16d8,67ce8e51) -,S(55f4f4fe,aa741574,79462b48,f001688e,fc99f545,d4566dbb,35faeebd,f5b1710d,80ecea05,63f24c84,e767b894,57dfec3f,d015a4ad,b6e3fe0f,662521b4,bb02d15f) -,S(95a56acf,402f7f33,fa357c4a,e4db337e,f04a60d7,4cd73e0d,b137f68,e0e93cee,e72405bf,b7c9ba84,16f4e72c,a30c9ae5,d21c89e3,ce5b61a4,bd521b4e,ef6501fd) -,S(28a9fd90,b50d7bb5,13034b7b,c36a9783,c2a697ff,499bcd6,4b0881ab,8e7a2aac,76b151b0,5c7e7ea4,9a263596,81508781,a37cfaf5,14fa1720,b583faa3,9794a788) -,S(6406dd13,6d6462c4,a4116b93,eac38eb0,b571e2d3,99cdb93c,b36fa5ef,e734b672,3974c77b,92b8e614,52d9c9d0,62a911f9,b4c5eb1a,977da74f,defea358,5dd7fd1e) -,S(8fd8f23f,cb62e1c0,94fef903,9933747e,9d40c37e,376703c2,e3c8b666,f1066529,8b0b2f9b,de10175b,24a9099d,75926296,5ba19013,20912baf,3100e057,d4ab5c8) -,S(51780a2b,d4457368,9c0679bd,c8c94e43,cc525bab,2d2723cc,3e0eec15,63a1a24b,5026cd9b,e178d1e,c746e5db,29391c4d,4b6b08a3,3530fdfc,64603fa2,f0e01109) -,S(aa01493a,e7c7f9bf,3d2fe0e5,cd939dca,5b8c8534,6848d065,beeb42a9,8c283561,a08f0b45,4a42b5e3,6463af14,5199e3d2,1783e908,b3e130f0,e9e88110,2cda82d9) -,S(cd8ab749,d4bbe6d4,ac81c4fa,d6a27e81,e4456d4,196cdafb,97fa6053,18ceab70,fc6c7739,bd68a20d,e01c9249,3cd7ad3d,ca862183,b0529231,da32f1b8,5df59beb) -,S(e69cdef2,e824501e,7a17bc54,e0bb4886,379f56e1,c59a27ea,e00bec5c,55fe3e32,e80ed10,40375398,10125338,f6291791,3fe735e6,6c4bbc80,f41d858d,8ac41cd4) -,S(5a4e72d9,182b1f7e,efb08af1,9e3181cc,f6b6ec69,790184a2,f30188e0,dbff8a8d,2d1cf7f2,d5a857d8,3b31c588,5ac33a5d,7b62ea62,7b5b0bee,2d912502,2df9da19) -,S(9e000859,48bd6211,410416b0,3920a79e,d78f154,5dd0330a,8f23d1b5,f8984a2b,36ae0492,412fd3c,c230680c,edb0dfc8,151ab85a,d8d3338,db611674,c88e3f62) -,S(7e0b97ae,b12f8734,ecad35d4,aea425c7,99f88485,f0bc8d18,ac82f213,258bc6ff,e76f4e24,a4be1b6a,3fc3b0b8,ab0b6e5c,ab95fb40,4692f7bc,cc7640b5,69f3946e) -,S(62285cfb,1bdfc495,dca81ff2,867878fa,b3064be5,81be0c86,b9336c6,61038ee2,f2c91be4,5f60e9f3,40e85ea0,8f159dd4,a65ca8d8,21a6e4f7,71f4dc17,849b5161) -,S(70234e81,2de1b5cd,699870ef,36d5c19c,cd3765ba,eef3cac8,6f126a,a6c82623,e2dbf98a,f92a777,263f3c92,4738ba,3140f769,fd5b6ec,7139bb8,41330736) -,S(ae770461,8f31d5cd,ede40ef5,7434b0a7,7dc1b4e6,7f4be5e6,136978a7,cd5db07d,a4e25164,65584487,3f520e42,74037c,5cc43e12,95167b01,d46d3e93,d93d16e6) -,S(cec7ac8f,e4db698b,48ab78fb,768e6094,5b7f4ce7,d643e604,9e349b6f,246f2b53,491bb545,99330685,433bfd2a,7a4fc831,7f5d3cf4,80d6bc32,5ca6d001,b65fadfb) -,S(80276e96,b051e49f,276f62e8,35622979,852e4cf,c2ff8665,8db4d5c7,7c5eee36,f510d696,882589f0,870d526e,5f7513a4,2c4d4ce5,3733f30c,f06d7dc4,f42f6d9d) -,S(b19027d4,9d85faae,e6163934,ef8f8508,e9e351c9,82bda741,b8944317,da85b27d,c12461cb,dec0e69c,b378443a,f2eb042e,8439f812,205742d6,dbabb372,ea47a824) -,S(57599d4a,cf07c001,d3d3fc78,aae147f1,989c656f,fbc43081,29e05b2e,570c792c,5cf8ea0f,d215ba16,e18e181b,1b4b4f02,38b57af3,9010ba23,f13bbdc4,18514b0) -,S(5ab76283,fa110b82,c53cda2b,653e763c,306e6f8c,2b07d490,bad6e418,eae6e4b7,ff365643,cc2a78e3,17a7de95,b37b3f83,aebe8272,4162a884,f7437aba,b55e8ea0) -,S(7b93d9e4,8602d7b7,ea52dd45,fa0031de,66ea88e4,4250c898,64903e7f,959d4a85,99ccb201,5ab91fe9,a0f50a0,fefad6c3,f6dd060,1f2ad099,a4851d33,162b52f0) -,S(2d5878b6,af642776,41101be7,2b37b4b9,1de26a21,b9610a93,7ee2ce2,fb96ebb6,138ee05d,df4b004e,820815d9,46716f2c,a887066b,b7d218f5,47d4bd7c,2cfc585a) -,S(1d637068,eebc32da,24a0fce,2e41cb57,cf1ccff5,38cfbee7,ac13269c,e560af3b,6a932df1,a2896445,6685ce54,2ddca0ae,d589a494,b7ee89ed,1b4ccfd2,c276eadb) -,S(82babb6b,460e1235,f3187a68,912b057,26a478ef,fe929a3,9479cf04,467de64c,3a9f4e33,603d0396,1f3c11c,94d58369,5de43a1a,327d0faf,f51089e1,1345647f) -,S(ae86e71d,4e715bfd,b63d899a,9daae610,a01c5134,c1b9262,c276dcaa,b48090a,3564b48b,fcae8f7b,feac4df9,3b458678,6f2f9e83,9c9c6126,a301de29,4cfd7b5e) -,S(35a5c2fb,fc661cc3,f4ad6ad7,f1eb32b6,664c50bc,91f4000e,f5774364,2aa413e8,4a5029a2,887f6648,3e072782,68a81c85,b901d692,4ccae752,7111bcce,cad6cde5) -,S(386bf07f,4dd508a7,61e7c29a,dd251d9a,76324496,6c6d760e,cbc6b069,5858e2dc,d4f14804,9c1fa038,1d903e19,68fb14b2,f07c621,15a81f41,e811ad87,de407696) -,S(dfec381c,9bd6f4cc,50ac445e,c9104d87,f9c46c7c,cbd70909,fabde6aa,12346f96,5e7344f8,25b6649b,df97ef3c,ad96945b,d1ce0f76,a48b7f2e,56ccff02,797553f1) -,S(3606dcc6,4db04cc,5493e0b7,ea0bfc2,f8a24302,d2358aaa,7c1ea8,842abbb2,a5c8743b,bc4d9b74,b8b569a1,feca3667,87eea8b1,be2025ed,bb547e78,5687301d) -,S(3441e737,e19096e2,9a3025a4,71d192a0,db086038,8e76d2b6,66052825,e52b0016,6d10f7e,d5cac98e,73c3ad47,bb233a39,5eb9bd4a,37861b9e,7dbb60f7,81eef0da) -,S(b2c97c2e,460d8c34,b5ea7a5c,456a9cf5,b1d902bf,5cdff030,25410a,26636e99,67133081,a8c8ef30,753417b3,cf6973e2,1f151e1f,27216bfa,23289ea3,e2057b7c) -,S(2740bd8b,59a43ddc,f8ffdabe,d59027b5,9b7932b7,3db45a97,3b6c1501,57e045fd,8106f2b1,f69f1ad4,2c0787a6,3c137753,987aabe4,b0ebd82e,1ea7807e,93b02a85) -,S(a1acffd9,bdbd94c0,cd8b4f40,3f9400c,aaa8e269,d8cc49a6,9ee565e1,89b6c21b,62ec7d7e,733f518,974acfbd,4f4e4f44,bcc4fdc0,cc194a66,df7c16bf,ef0235b) -,S(50bb2ad6,8d524acc,3278c0f1,538d3aad,9a5357bd,332d8cff,6301f417,57349847,d8fc33d5,d03526bd,b97d4c6e,1ef018ba,ba4b33e5,9677f139,b8535287,fbacfb32) -,S(ebdfb262,6031b4fa,d675e860,12288101,948e2ca0,8fd0d32e,c9fd0838,5f4fdbd9,b078066c,c470113d,db3964e4,466e319b,4f853a42,8951aa0a,9c4629a7,a40dbf2e) -,S(5daf4c23,65482a2f,bdef73e8,208fd5ad,d57b35f8,171541f6,3a48b742,e98bd48f,9015bfcb,5a248607,f5ffc83c,4fa3dfec,9cbd11f2,c230327d,b2cc75ca,2e87f967) -,S(22db9c20,5d840814,67a19517,f353f825,238c905f,2b12a77d,8551cc9,ee8533c7,680a1bc8,23432a28,a3219264,2b9acf0e,7ad19e29,b604631c,85f7038b,386dcdf8) -,S(404435d1,2e8be51,92625213,f86e6e55,9fb44658,44694d4f,4db72861,d4c100ae,9ebce682,b321eefa,e8e04776,8f82491a,dd734e5a,941e0f4c,b6284f78,6d1586d1) -,S(dcc36eff,6831a6de,f8600d1a,3d52da1c,fe59df9c,cc69c9f2,60c26532,e837530f,8609b5e6,7360b7e8,5ea98c13,578566cb,b6b385ff,6990d4d6,5b795acc,1f77a893) -,S(ef0dfb94,1a1c383e,4a44cd04,c633cb48,e991d140,45e2d9a8,b4353e79,9c1a1514,2685d60,f2a75f9a,b733afab,f693ed05,9c3599bc,3e3346d4,61e5c86a,f76f6f42) -,S(24884cfd,c6c3efd6,b4d2e18f,2ca66b06,410b0fba,d9d61b30,86abc537,1d766b8a,7c1cdc85,66f3daa7,d395c6bf,8a23c130,86a78619,aa68519e,4657b17d,ace2267d) -,S(541b6691,c7004a81,2c607756,f81b6f05,485b0708,678d9a45,de74632,4acd8b20,ddccf301,8a3c429a,c749f0d5,2383784,cefff3df,ae98517f,c7f5e764,c5c609d7) -,S(5462969,67262e3f,a905eea4,ff1f8296,f792cfc8,bb9dbb9a,138242c1,a1fa822d,63012289,8e429527,4fad8e7f,9865659f,da2d7370,10f6e185,70dadbfe,21e6880e) -,S(94070912,ad2c129d,cd122bb9,704616fc,3ddfd949,6ce9f6d,6e18020c,ec848e83,9c3b38e5,6bfac9f1,4c901080,b5a732a4,b5d261f8,2b571536,d1fba6d9,b714017b) -,S(2a6330e4,8ddc661e,afa8071c,c1417b92,ea73b060,3653a017,3edb92a5,6e3ca6c9,b38c51cd,4754c350,ba2d56a3,fbf4fbab,5802bc38,6b5516f3,d8b761e3,c3fc7d79) -,S(9142e493,5f95da17,5ae4078c,5ff5a7d4,8c418c1c,7efc4c39,dacb047a,d3f7424d,15165a74,c47133a9,e8684ea5,5a4f9b05,37d0ab7f,58a7eac0,e698adcc,b885cd05) -,S(2e198b29,5cac4dee,dba63ef3,888d47e8,bb8d372,7fcbd69a,d1eea656,ca85804d,31dd5db3,e700ffbe,152b0c2b,1b1c830c,eb382468,1c522e63,676b9ec,6780fd52) -,S(b44e35e9,b2efcafa,f123e52a,7bd9bc58,32a671e2,fbf0264e,5a3f536c,b272f72d,8d489fe3,beb39fd4,2632b80a,1243e64b,f80c81c1,3934ab08,71c16a5a,5aa43423) -,S(dc99ad01,e1324b6d,b5ecf365,c22463dc,f609f0b5,90e6d3be,efddf641,b83a3cd7,b4b422ca,2feabeaf,32c0ad6a,4393c087,a4c1e794,47a043de,cf0fe486,ed11b682) -,S(e174838e,eb991c2d,cfaaf89b,b868f4d1,3029ebfc,ea286376,48fc51ba,f962a359,f80dcc87,27cbddc9,4bb1b60a,4da5cc74,238dc62,821a9ec7,c05ad2a,a0e7570b) -,S(6240358b,15bd16d4,42cd79a4,8b739eb5,4ca21d18,b568b497,65d10dfa,a2583d33,6acb054d,724e7550,ed6d8caa,8a436d51,fc546116,df33413f,a613c0dd,6cec2d00) -,S(a757fceb,560aac0f,543a29b4,bfd3af7a,aa61c077,2c1c07b2,e6268342,e63f8d70,5864ceef,f80855d0,fb4713e2,7bc6a202,b4c07450,6749457b,39d0c40c,f40352da) -,S(f36e1073,57c3149d,902e9416,2e509d19,d4b1f498,bc74814,3a1bd411,2f777bba,d4d7da2d,139a2693,e40d9396,76c3fe48,45f74b43,78f0c25a,14aa9698,3bd1993e) -,S(84ef2d4b,55a40ff7,13934949,b6277ef0,4a8e0e4f,cc49420b,17269d59,224af99a,57affcb7,1d3508f,65ff2b7a,b1d6752,60465e76,754efe3e,80a83085,85ea73a6) -,S(138ef64b,274ff66d,7defdca3,4ff28bae,96b046df,408b3f47,84f78784,3fce7576,ebdd04e5,1d517c43,412010cb,d03252ed,dfe97912,ee4a7d4c,ed98551b,fee1ecf1) -,S(e82f03fe,2ba05692,212a1145,550d3057,2d454728,e2d9989b,435cb608,3d1f318c,191a6fb9,cf295881,92aaaf1f,ea34e123,613b2937,602650f2,eb25f63f,5812dcda) -,S(56a68400,676b6fac,7eb5fb3e,7f345ec0,11117098,c0d1a96b,e44bd2c8,5aafb317,3a41827a,5ae1b7cc,5b9dcb5f,4c41819e,f49ff2fc,ce1d1949,3f5b0ce,9f1dfb4e) -,S(82f5747f,1b353db4,f3afe255,e1f2660a,8f735b1a,e40a5008,4efa3c32,dc1309f5,42e8b903,f4ccc01f,7e87e4c6,71572bbf,d05f9ea2,a4cf7bd7,dd5a9906,264a0144) -,S(89136941,c47b1964,a4b89e0c,376b3136,80ef76c1,19e02bb,bfad594,76e0cf13,b3a2a785,fb6a564f,f4871bc5,177c635,d722e659,77f621a,f6f7537a,2c2d3f3b) -,S(c6250969,c98f580,f0cb51,eef5d8a1,b9954bb,97671df1,c7360a5f,42238909,83d0324c,915eab22,4dd3f935,e197e0e9,552d5bd9,6b1ed240,219731a3,58ec724) -,S(e2399ad9,63913200,4664a481,dea99d85,ad12938d,dd0e4184,27411fd4,8fc7e3b4,60fffd62,beae28e2,2ea836ed,389c3780,5d8b1fa1,fb10f298,f9b54df8,93c69d47) -,S(4d00b1c,186d2992,9a6383d6,cc8d1796,a59c5d7,c27cc7b8,5a1f821c,3003d959,8752ead1,27eb19fd,49dc8ce7,a0b7c7e6,dd4aa3dd,6f8d5cb4,687327e8,ce487640) -,S(344663ef,8b8b52c9,1aa548e9,8b7e1c48,933cbfa3,59644318,5ea973ae,9264121e,73d099c8,9dfe8eec,b957e624,bea5673,6fe3885c,e2f72b06,dfeae760,514d9efd) -,S(37ff484d,dbd22a98,333038d4,7949b4f3,f411d3d5,7ca319e3,5c788bbd,a0de6648,55a5394b,51618d81,d2fb1455,4ec1f5c3,a45cf086,83980bfb,a9aae6a9,20547c67) -,S(cf3bcddb,ad5066b,909339d1,4cc6d3d8,d2881f70,d6f12e1,4d795b06,17556ca5,e12686bc,99e20f20,6220e402,32760224,b61b90f7,8b7c0b1,3c197a47,11678a6f) -,S(961d02e7,db8fd1ac,a38f9110,13d74a5b,d35e47a1,49818d41,49f02edf,5da73402,9462eaac,d698677c,16515ca3,bff217e9,765dc8ad,fe2fa82a,1db05158,71fed240) -,S(43e62f90,574a8e65,25d22ca6,74814ac,3648b724,45a535c,5e1af97e,b46ec3ba,6def0a56,17c1cf17,9369e20e,d18d0503,e141dc85,9edc73a3,18f6a35b,3d939734) -,S(9e682b79,9d79018c,352113cf,98de93b2,457e4b4,a962d160,33b80052,57dfdbb7,9db9cb16,bfe96343,89c468a0,6405d2c9,b2983354,ee9a81e9,3f23ec5d,5049041b) -,S(790187a7,8079b59d,b2a22d13,8520192,5f9682e4,2002c8f9,436876e4,d5a1a8b4,25c8b46,f6b43180,3654381e,56a8e6aa,ade0ad1d,6a6044de,17e9592c,affa456e) -,S(928a4b8a,6c744b33,99e22d65,35a21ffd,662a0dc3,d5bab1d,683ce555,f0169583,251fee84,c064954b,e1daf7e4,5fec87a9,323d55f6,687fdeaa,75d4dcc9,9a6fcf84) -,S(684e88da,81182f2c,ac5872de,8c98b86f,a6ffb73e,9bbfbfde,6c16c3f4,be084c88,c451b59d,fc9d62d5,921ae45f,f7557ab3,ad179eb0,6afb8bb6,bff0645,cf6383fe) -,S(8bdd2e83,a403b0cd,7a8ebfa8,6949bceb,8e8166ce,a8596f6c,ad7b7bfa,4d174343,7220c147,97f682f8,7d707b2f,eec937c3,643bb359,e9effbad,8ccbc8f,a8177172) -,S(c3fa3b21,6e3c4952,85258ef5,f921f6b,b7195869,e46948b4,b69e80b0,be399543,eb2044ed,21f6661b,77088050,3026c2c5,5a519ca1,748bb10f,c8eed953,aec1796) -,S(1c063c13,eb2d2959,379fb0df,50d355e0,195a8bd2,e642ab48,3d6a38a7,af7e63a2,20538f92,d14c9ff6,75c5005c,8c40e26a,b0042874,7f446ed7,cfcf5737,870f2abb) -,S(60c06797,7b54c18f,4b82dc6c,227cb539,6c6086de,107e3999,81f1b5e0,f31d452,3f4546c4,e3eb11b2,e6fd2617,b57afafe,ce0e8bf7,aacc13b,73755f18,dc98429a) -,S(fc15cf99,92256abb,cf263e90,a231ed8b,421cdc2b,af185722,c0af008b,fea36856,abe346a4,d9c40853,70dd46e4,69a3bf24,c01dbd97,f5c9997e,27634dd7,c635d798) -,S(f6143985,18173bb7,428da262,bc8b07b8,1a92b06a,65926ee5,c6f8fe44,27249454,b1d832ef,3a2558c2,d41f06d,4be8e5e8,11fcede9,9cc784aa,b9f3ce18,d701cf84) -,S(579458a9,62218442,41e68542,76a116ab,1f1fd43,109d4bc7,ad5216dc,ee61b5f5,33e56474,68c157c6,15cc8d46,135bed70,21274a4d,97aebe23,7bdd4b61,2c53e2d8) -,S(637553dc,b0804132,b5562678,fe355e8f,abab2001,fe17e3bd,8c051e7a,41fe62e7,28bd6dc2,ad586e1f,f1a6a951,167ba14f,6989b296,874e0d3c,31917920,9b572dce) -,S(eebbd70f,6f64855b,e21ddb92,3e54f583,89e99ddb,577fa8ea,66c3722e,b580e2a3,3d1b6979,15b50345,4a55606e,ad3ac4ec,7c986698,3df60e1d,edc86827,32fd4d68) -,S(4ec8931f,2bf4b1da,6891135f,37791236,3a6e888b,6e5c5ddb,2e350e42,686c56fb,d5f6c679,4c2b306a,bd719770,48dc3e28,3cbab910,556919f5,35d9df23,56a09bc7) -,S(6b5a7f76,fc5b7e7a,7d84deab,ffd5c771,8f49375c,cc4dc1a7,35bc253a,bee9730e,1e935dc4,8fbf5f6a,b12562df,11855757,9eafb8ab,f6ad8b7a,f8f9df64,43b58af8) -,S(2a3129eb,f620958a,4264c759,17e29807,5f5b73f3,21d4cf27,683e4788,9e013af7,e940f5e4,c1fc28b3,fa346ede,fdb8ac7d,4066732f,a6c276c6,89a1921f,d1020da4) -,S(8bfe81c,e99443f3,78307f34,5bf2c826,94a8723b,c4836d12,4c6f5163,bb28b5ab,58b16e27,857e5faf,9768edc2,68d177a4,87de9848,52e65348,36464ac3,f0433c71) -,S(47820cd9,449c566d,2d39daf3,ee4d356d,5423692,a050cf83,1c1337bd,8ad61be3,48dfae03,2988a810,6d069d,22f27445,1200d38c,a9aea665,5e5f28cc,9952c2e4) -,S(2d7f03ce,8e453605,89d221d8,84c3ef28,f9e8dc52,41d7d131,cd6e9921,55a934e2,8414b3c0,5a39f38e,1f14d55f,e28604f9,16a7b272,6d6c843a,57a2b8e8,b7ee9c72) -,S(83887cec,919d8c86,c2150d4e,e842505b,f5a5b06c,b3b1e67f,1dc2005e,99d8e37b,fee0e7cd,f5c9eae2,78d34fe1,2e58845f,fcea9de7,f9883e32,7a2ee941,92b4c009) -,S(519f9e1,138bbab2,da8c03f,565c3fe0,a9d0b709,1a7b50f3,f37df191,d1ca1e24,64d6bafe,2bffce42,3f631ec0,781e96f5,ef6cd6a9,ade6b9eb,367c036a,1a61ba9e) -,S(8091f78f,84bc74ea,69ade208,72936152,3946ffe6,63edee6c,3cd13ad9,4a8fba61,1aaaa58b,af84688c,1cba5d90,d700aaac,6765faec,39e7a212,fe13a9cc,b0bda1a) -,S(50abc00d,d3fe5748,7c2a5343,4a36f10d,8388cf20,56cd5bb4,9ed8e97e,7adb3afc,ab8bad95,14b6040f,b1c64f01,d9b9db01,670fe0d9,3add5d6,8a80e41d,8ded25ea) -,S(a9a428bb,4da01f44,a9e4f253,3436ae75,20e5722e,6d12931f,aa20772b,36a2f110,ba05121a,1830a26c,440f0582,2fa53e20,f8c226b6,85b437a0,557c8450,774c0c5f) -,S(d7afdbd4,6314d677,727fa11b,211e99a1,d6948be5,b7753ecf,64e9b1d0,ac7a83ce,b5f8b97d,748a4abb,a390ed9d,79cb42ab,ee9b2afa,517288f4,80aba1cd,34e21d04) -,S(2b6b834c,d2b54466,a3d41694,b672ac55,13f19b1a,d518ba99,d622abfd,9b6de265,c1922593,ddc0b3d2,ad1d52dd,3cbeb2e5,74ec849b,892d9df1,87ccec50,7ab9b0d6) -,S(f393cf4a,d7f93fa3,1596ef7e,a9c11c6b,f29c344b,1a3ee5a2,51360c9b,a96ac8ea,4e811ca9,de67ceeb,90e48016,30d06125,fbfa56b3,35e3a7ec,41bedbaa,7a8133e1) -,S(bc3b9250,4e14b254,81305012,a248a94,bbc546bd,52fbc0e,848d75e,9c8f418a,9a52afc6,f8b487c1,7653a911,f11d78c5,8f5eca38,c761a2d9,af0ef2ad,a6a58223) -,S(2f5a0e73,c601fb8a,7321e170,4abdb1f7,e71edc3b,bf6f9cec,1467eef,5f6055c0,d8bb1d0d,142d2cb1,3b9d97f8,f807212,b79a5ecf,13d942eb,c5a3f442,6553e393) -,S(b83e51e3,b4fc69ac,84d099b9,6916c11d,8d8d8d7b,f5cbe15b,fa13ed34,73a54ae8,232e0f88,69c53923,22018084,a7cfc251,daeb7a84,6e1daa78,f3f365c2,ca3dda5b) -,S(10971993,50b07a32,1532b372,2ee89058,e90e9b30,5908cc0e,a249a40b,e7516377,69a0b67c,7bd55a04,9be3a3a5,e308799d,dc735f9,ce56ff67,2c796b6e,5a0a1055) -,S(dbeef75c,c95d5018,f3d71711,a0299dd2,62250814,c1469647,dcb27a23,e85c4477,dd4712cd,16334f8e,2baa6855,6c5237f8,676311e3,1cbf9753,35e76a90,88d66413) -,S(28cb1199,2bdee938,f3405f18,537b410f,2723888,e4ca0d29,d96806d5,6baf114f,e6c63fe,bbe5dd81,e3a9fc1e,83a5ce89,c3e2ef6c,c2a57fea,695ebf4b,e81e5aa3) -,S(f0a2df0b,64efe99e,65f9f176,89cec5d4,caef385a,e4676da3,790ba2e2,4e9f60ba,a7ca7e08,b900f664,14498c12,aaa77da6,6a2520,7bcf1a85,713b6d14,807a4519) -,S(d1bb46eb,38e54396,dc7ad4f,f553106,54fe9b06,9abb1410,799dffe5,482b0f00,14b0619f,e08830b6,d0a5463,96826b6c,d03bbd2c,af930b14,a031f922,eace4214) -,S(27bd2e56,7705126a,5f5adb31,ac1d09a1,85d74002,c548a84,15c0cce0,1f69517a,12203dd7,cba21cd2,9f9ce428,a8e302d7,202690ad,8734c08f,65578192,a5468d32) -,S(6b2cc790,1c72e201,693835ef,ab2b676f,55441add,b8dbc3bd,61d43201,bfd21d9c,59973406,deea0493,daff90d4,b62ff38c,6690bb05,18e75560,1bd5b3a3,4add7456) -,S(75e85c3f,32f953c5,632a8bcc,6bfcd6bd,c63c3b93,e607d267,5df09fb5,94840f27,22f5a376,8714c73d,96b24f89,d426e668,bc59aca0,cbf6dc47,723f01ed,6cb6bb30) -,S(d37a3071,969e152f,41c0eed5,7e28f1e6,f26e1752,68c52683,15e200b9,f86d56a7,53d52726,98751d1d,dc4b1fb,d9621723,70e296c3,b47436d3,abe20356,76ff6181) -,S(715bb304,7f5e6973,36546640,8e183bb2,67693198,94e341d2,37d5101e,a7414976,28440f5f,9e82d5e8,7a5ea672,2e95c3d6,a89dd1fb,3d81aca,db7609ee,a1a968d4) -,S(f72d142a,4f5b1595,a7b4a52c,c6812ec2,8e4924a4,b087c139,68d8adf7,dac642e8,501b644b,b5d8042c,f16ab9bb,bc594c14,585486cc,fbaf47a6,5378f97a,761087dd) -,S(7b3eff8f,b4ca8a3a,5fc3cf02,a469f34,3840846c,d8fbff28,243b962,c1284c26,be2588fd,15396124,a50bc555,5e161022,3bbf636e,fd510522,811902b5,b1748579) -,S(2441a8d7,71fbeca4,cd365225,7974e4cf,ec2a7035,ff2b58a5,9cc5fc37,8a113dd8,54b0776,5316713,4bbf4c6a,7ac23360,fe035d2d,9316cfcc,ae129893,82447981) -,S(c20fca4e,d05467ca,45b916b1,2f4ab386,512d097c,b64b824d,e78e9a2a,14cf7591,8851acc7,96ee4072,ca87e69c,9dad10e7,931fc48b,238cf46d,2b2355a,e4eecc02) -,S(2f6b0e8d,1375263,b74e415a,ad758130,a34c6c6d,690ddd67,63492eb2,49ec8e7,d0c791f8,438cf6a7,976cb614,eb4c9f67,adc72275,f6236868,e384d538,daf25dbe) -,S(bfafc1be,426f056d,6f8b3ed1,1374db21,fc00373c,3dd8c762,c5ab91ea,b2b665dd,9c41f297,a4cf003a,7fa7b071,a106da4,6dc40050,a7592781,68436115,150e2a2e) -,S(cf711dca,90560273,6d776f86,759d74f,895980f7,1728dbe9,1df93076,cdcb4e8c,52a379bf,cf25216f,e3556def,e889b23e,2f91f6a6,47ece012,4e140aa7,734f1cd5) -,S(b9be95de,27aaf198,c3001ec3,63690f2f,f516fd75,1864794e,1c3516c9,abd1384b,68875f97,dca1dc43,3e9b614,488cb8f8,1ff85d58,2ba853cd,27fc1227,1ecb6df9) -,S(f5f257e6,c4d06a8c,53442b37,7519ae03,7bec31b3,c257f331,fff53773,28e9638e,b6a1e60a,48d03213,bb52e3ed,d20d0ca,c80beaec,bb40169e,35ff2165,43e986dd) -,S(fc35c74c,17e38aa1,15803603,30af7d92,a5281b3f,cb6cebf9,df09155e,64099ce7,6e2f984d,41e8693b,5a4c1c58,9814d131,8421fbbb,2ec8e45a,c6239227,db79dae9) -,S(ac135e01,49d97363,7405e5a9,89ffaca6,c1bc18a1,cce34aa7,4732fcce,d54384dd,3e38bacd,ff954a6b,6bccbf63,9f8d709,d8e54553,6113dcb1,c471a162,af021d0) -,S(60a013fb,efb3c5d7,802400c4,e791a019,bfd8f657,cf4c1055,f3674f92,9f5f345d,7e763c48,3582fe3e,2a0a5138,ca320013,9907e364,5468b5b2,711205f3,38a1bd97) -,S(a099a106,5d907a8a,43a3d027,3a789992,ceb3a659,bef93a9,6ed04ea,19a7acb7,137f9ffb,fe3c22ff,c034bb57,9f0c9b46,d5cca4a0,db1407db,6fe3d7b,5bc5a50d) -,S(9ba1da86,d02763d6,187ea5a8,c11c9da4,c6ed7017,49f107b,9ef4fc3,94a792ab,f19e22d8,ab5459c5,5bf87908,90175184,8716aea6,5c2d9650,c472199d,6663f741) -,S(3642701a,d30d1430,17be9363,3f28d90d,b5e02238,9350934f,63a514c9,a677ada0,2fdf9ab9,c76bbbc6,c4e79f48,7a8bbd86,6432fa98,4f52ac22,3440de3b,f1aba970) -,S(29f79c58,100b7098,d8d53012,e2c98719,6188c0d,54712c31,c2ea3a52,d6941a5b,be9edd99,eaa6c1bb,d0ec42f,586a2806,919d5bb7,2d59bf3,7216890b,9a2d524b) -,S(e011aadf,bc35284f,816d5030,c3feb350,4b470d0,ac5ff061,e5ed2c47,89ba1bbc,e0a98f93,4f2b591a,36e6ee97,f293be77,21ec1a9,3f4b2700,55a0c01a,3cc979e3) -,S(a5c8816b,fe5356,37eb54b6,88b9221e,ee06a51,77ffedfb,3ed96ee0,4fd78585,3f86637b,9d63b11a,44897792,9a6aed53,7d65951d,aed6476f,e03be5a8,c9ff8e5f) -,S(3b952c23,7e44350b,95207798,e708fce6,2e6d49e0,912a2509,abef16c9,c7194707,f784972a,419e6c8a,c9d41a38,57912e66,e6ebb631,6bcdeeda,ff49b59d,bdd68936) -,S(8d9796bc,d9d8152f,80c7982a,187a4aaa,b75dd611,99f86632,72502f24,dd57af04,fb9b1479,94a31e3a,28d5695f,2d689951,317c2d2,98e9892c,89c98202,b7e611bd) -,S(96b2bc5b,2f4e6445,1536f689,d7889669,4fde4d7b,6ef67f51,84517704,6a02de40,e0b76d26,f91982db,5039bbf5,afbfce51,914eee9b,352c178b,2145c4a1,88e89cc) -,S(9bf7cf10,9f129500,e2a8f54d,8658ef97,4e3ab2b9,a1d0d036,25bef5d2,432e2d79,2113d7ad,f77e1c68,51b8bb52,188ebd25,dd6373a7,19bcc20b,e32d0f19,496e8582) -,S(10d3ffa7,20375b5e,afc8c741,4d9aa184,c91f853d,61d58dab,11a04f2a,f3d4f1b7,c1f84b2a,8a96f43c,b215c704,6f8c3f02,c98d750a,d416f21b,eeb10ea3,f298c90) -,S(56d64e2b,6adf1cd0,b8d63692,1b68733,e92577e,88430e92,c0e679e8,c3a5eb6,1370e,fbe98423,488427c2,57d5e696,5d4b687e,25e4b824,51b1a6eb,7ef71cc0) -,S(fec4a03e,1c83cf20,75deddbd,20c24792,6dbfa352,a56821c1,420adc34,731528bf,a152b2af,8670e42d,3bba0d98,f387e9bf,1bab788e,fd7bcb2a,a787e6a8,bda95509) -,S(580a7517,7ccea9ac,63ae6d53,e8959e5a,a45d11db,29a87001,779c260f,2fee92eb,793be69c,3263c64c,2048c411,115375a4,86733a90,d8c12a06,862f4f9c,669e8edd) -,S(9286bfe5,78931ceb,cf97431b,1137a19a,991b46d2,d0dec2f5,35edb976,6af636f6,7e774d30,e962db42,83cb38fb,2053b780,c55fce80,51edd5f2,8cb1b5a5,d329f516) -,S(606d55a9,9b702652,5382cf2e,efeec65a,803e3851,da60a041,e5422c1c,28f4890d,dc895a6e,3c2a6411,4a04a1e0,31b8aa17,79ae2c05,1f4eee54,7f8a54c,50eda1a7) -,S(a16a0d40,833ec1cd,dcfef2f1,bcfc8ed8,11387dc6,4e4df6,6e807f69,75f917f5,548d7d37,13de4a53,151f32a8,2880d087,7fd281d9,63011388,ba991bd8,822d6527) -,S(5949d2,be574e23,9a3e3e7a,ae20726c,4a687a15,edf5a62d,9b79d0c3,4f9f0329,71dcb25a,167ab25c,311d9427,5480f78e,f7f4e777,9723e55f,337a9121,445288a9) -,S(841f4e4a,e67b0d8a,49d7b295,e9c1ff4f,cd1e2333,82101536,cef7c4e5,7968b240,1f561c9c,265fa4ed,eb979f4,a8dbe679,ccae8037,8cd73d5c,b56671d0,571f4161) -,S(22623df8,c748e9f2,88bd4b83,142788ff,faf680ae,a2640d,dd43ec1e,46cb7442,380ef00a,dfcdb592,f964381d,ce9f787,17d5827b,494c3aaa,d5e0e013,87a55da3) -,S(816067c3,6438301e,ea07a21e,5a60a17e,670083de,b3b66e2d,c88c6548,f45185e4,5afa391b,9a95e9f1,f04f4e8e,236fc39e,2eeedcec,45026647,f5982aee,4dc4cbf7) -,S(f8f23561,4745c531,24cf6431,ba8e0425,7d28af9c,2c196485,3546924d,ce085c1f,a165067,e3b41b55,a548c1b9,3fe76b5e,bd101275,acd29e75,7f66753,6734750f) -,S(21325584,e25b8a15,c25537d4,c70853b2,28bb933d,de04be23,7753b933,57f2f57a,3708c8f2,78ef57a,f0b00d5,17f21a6f,f627b5f1,59ba1f53,d20b727e,86e873e2) -,S(b2f4f7fc,f48519b2,c00c24b3,7ffac141,88b0baac,bc915c77,845cd6a6,3fdfbda3,b206b59e,6f52ee43,3e7196bb,5f4cf3c7,de49723a,cd5b3e17,1c94e28c,7d57702c) -,S(b4e65d4f,5f420006,b7c70fd3,9564f9c3,fd9c5c53,dacae064,62212fec,ee7f7265,307b6ef2,e3993bf4,f321723e,a83ec2c4,3c75b8d,684665bf,fc073506,816bee0e) -,S(4f104593,9ac609ad,25f3968e,9798ee93,aa58b61d,43f4bab,8f2352b1,de3a7240,ed8d87bb,988395fa,581698f5,c55a5093,ed9d0a89,3f4aa4bd,186221ee,7f8179ae) -,S(9b5e74ff,e515c125,9fa6b215,7ad7529f,90018e85,23888738,d097c016,494672fa,1d55866d,4c4e30f1,7bdbf70c,43fb3b9d,fe2df3d8,41e18bc4,3db3e3af,21fece15) -,S(77bf442,ac8cf718,102968f9,49387b1b,30f8a2c2,c76a2cf5,10d817c8,7e17e302,bb0f9e61,1d90046b,1d3b1103,e6c5beed,e4daaa85,f6eee1f2,6a6e756f,d32af0e9) -,S(27de125c,d49f2049,6b028f34,b16a9988,d2f5d469,30834fe6,4bcd388b,78c266a9,f43d86a8,483dd92a,2ad9dac2,4039ad2b,84cdfc2d,323979b8,1a43de25,5cb54bfe) -,S(21bf7178,ae1d75e1,94bb60ae,4efb5a8d,7f026cf0,7f845b13,2250989c,4be9c116,6caa82ad,bc21df15,d1744466,4d3b58f8,76b52291,5696481d,434f689a,edb8d967) -,S(249254,93ee016a,41b65b7f,8289da2,dc9100f9,9c0b956a,66d245b0,5632e234,bca30194,1cb51f98,1504c536,74f6f904,d883ff46,7aec96f8,2ed5ce31,7c45b3d) -,S(d3f644c1,e3472b4c,d46d89b9,6b937108,ea8e9425,9b9316fe,230e7538,7d867f76,91822603,fd629732,a3b37ed9,d5227942,2e536ae,316bfb7c,597b2da5,d8cade5) -,S(c8461f4b,e2bd14c,a88e52c8,147f656d,915c2675,46252e89,d0337f7a,e325b261,18971181,97ac799b,3f632868,e46efdf5,fa3b615a,a8a92b07,e38ceeda,9cdcae06) -,S(b6e5f590,be20a938,c1b57e1d,a7bd6ca1,a8c2406a,aaa5860d,9133342a,c395a380,a6728cf1,a2f2eade,72d86569,ab5a6305,cf01eec9,6a6de026,ff146d5e,7d8a04b6) -,S(3d25179d,465701d0,56d4eee4,b5efc10d,8b70138d,f14908c0,3124ec95,59eb5d6c,158b7bfe,1d61d7ec,633e88e2,b3c5897a,3b56f7a2,ac557c8c,3e032a71,8b95980f) -,S(abb5d54,c7171499,95893425,bda27f10,d8515511,91af6927,9849a597,46f94d99,4cdfebcc,3be28dea,36d06e89,ff4209c3,7012ff0a,d93d7ad0,4e454422,c4b9a161) -,S(989d0125,115ef9c2,900dedaa,4e31cbb2,f1243386,73ec624c,52352907,b325c73e,d3699ee9,945de070,fc1f28ee,14279750,d553df63,2951c0c8,d1668206,94c6c8df) -,S(c4c5c5d4,29c3d1ff,628bbe4,e0edf70d,5e05db13,c82a2af8,2d0e4232,5e013884,c2c76cb8,825188a9,fc29da67,70ade97f,ccee860d,d13323ee,f2ba7e7,efa97eea) -,S(8662d850,c623b65c,8db5080a,900a0e83,be947111,ec0b9edc,3601549e,26c0807b,a71d677,b0c9e7a4,f66a72b3,2918083b,f91e724c,cf8c9526,b3df0f6e,35da840b) -,S(d26fef49,7e7359bf,33309b38,93abbd44,543b73c7,c0eaa626,cbdedb17,1d083898,ad8bb209,bb090b39,6b501ea9,a5070f90,4d60c20,d48dbad9,56d381f8,79851395) -,S(569be8e8,c584b682,7d742ff8,5b402112,5b4560f5,f173c983,8f8785d2,229d8d0f,b09381a4,a8267d89,a8d5581b,f9a49d52,47c74a33,5e26e354,22edafc7,d41b8559) -,S(de34acc3,4d1787b3,ad967bc6,c5960d8f,842f82bb,c95aa255,d4a9e794,d30116d4,2fddb41c,b2b6b52a,57cf4d3e,883d3f0,e322c40b,ef098505,b6cb3d77,a21816d3) -,S(47430b48,76dbb762,6d549b86,1742a5b3,ece85240,70dd83d5,5446fa99,c5c50b1a,d75592ba,7004573,58c6a0ea,dc8ec772,b53dd048,8ddc73e8,5af357a4,af200df1) -,S(f1d1e0b5,e6687266,ba17339b,76bbab6d,8c2d8ffe,f6c68fd7,9140b097,d6e9fe13,a56226,fc233385,349c5483,72300f97,a1d8494d,a67db50b,b96543d5,bf24e580) -,S(22a6f735,76140de1,3dbd0426,e968c374,6e8132ff,383f44c3,c0515b85,f8cdbcd0,9dcd89a8,90270e3e,358dc004,40f95a43,430a399d,a8405e48,e69e3455,fbd18d1b) -,S(2ddc5328,afd8ca0,9bb0c6ea,57442e8e,fc307b30,c29e2867,b46654e3,e1a9ada2,7b9ab90e,db84e6e8,7bedaa6e,31ff90e1,7d07793,19977393,b5fedb73,c087dee4) -,S(60b6f839,a60af52f,d30a116c,58b9c65,1fb1c854,546dfa9e,1a01e2c1,95da0fca,5e77f69f,28cfb414,be39b07b,2469d8eb,b0e74306,1d856bcd,ca54d83e,20d26c40) -,S(2790c19b,9b9092e5,cb06bfd,f95ea43a,2a1f1f28,57c96776,dcd26a7d,ddee53c,fdeea120,d04e6e78,b2387afa,a0217098,de067759,8b2bc5b6,2715d9f3,714e7f64) -,S(e544320f,9ee8bc8b,127576b1,6fad9782,db181ea3,4514f7c0,d7f9046,f5113803,b93762fb,2397444,e69b63dd,9dce7c32,3c73680a,e26b5e0f,95211972,c0510741) -,S(6c7f25ae,73e428d5,860a236c,bbd4d74f,8e2706cd,69bb4cee,39f9aafa,db55313d,d8cb8fc9,e33f9b18,e9a0864b,e58ea921,8db30c4b,d5dff091,6a44b581,c8dc9121) -,S(289d1b28,ff710d47,4d1e9c3e,f3952f27,dd9eaa3a,30ef499,121ea53b,9b93d4e8,f36af80a,aebc2dd5,84cd5cb7,245b3cba,64285932,77f4be38,cf2b394a,ee880667) -,S(f02ab597,ac01d673,25e87b5d,29130c18,2a6f4a8a,d4ef7476,b9fa1da7,5910b5aa,ae88c02a,ecf28b13,ecec5379,5c34633d,d3262d1f,65ecaaaf,fe89640a,cce38adb) -,S(a9a974f,71a73106,57732c82,d6d4c6d3,c625bb70,4ec29a8d,2d8f8418,dca0413a,c20df433,eed4e96f,d5ef222d,860ed1e5,af1497ac,cfd1dc21,26e8925b,91b372cd) -,S(7866190d,728e0899,19a0e9c7,8634b55e,4cc392fc,1650471f,4a21cf40,8d77496a,1bb5fcd9,540422ef,caa8e265,c35a1e64,29d79de3,a9369b23,3512913,ac0cfd22) -,S(c8a7ffe3,44b3b8eb,f00e4e2d,e63d9540,25cc115a,9110c773,ce0130a4,8333b9ac,ca1ffbe5,10c63b5,674141aa,5ca87246,ca91280f,da97e806,dbb523fe,5ee67b6e) -,S(6cbba6a,13ff6ad3,83419e84,e4da6871,9cc1e633,d4cf3347,2f9966e6,4f9208ba,35122582,c7893f4,4fb92c34,e9c4661b,5859889,62a7d1fc,fac8a2a6,1e214a88) -,S(e07f8dbd,691a8611,eb5450c8,2c765dac,ffe9aa81,49ba3e12,87b23fda,fd9de719,932e35f0,8e39cfee,a2593799,4e118c7f,acb0c6e,5b526bc6,894b061d,8cfbc509) -,S(62136898,32fd9416,cde720d7,1d3f32a5,51f3e238,fccc69b8,4b633a2c,86d2c5d4,137e9a4d,62247e41,8596d968,4f1e5997,791f3b6d,69cbcf68,206f715d,be784e9c) -,S(8b010588,62de6706,253eb2fa,f710c086,40a318ba,1ea684f2,3254e8c0,dba7b9eb,54a48862,dcc56c60,cccbf43c,f7a33f9f,dbd7e419,56f0f48e,2ce2371a,19bfd264) -,S(12d3908c,14af8346,fefbbbac,e56bcbae,3fb2ed87,dc30b1cf,eaf480ea,84f213d8,fc4615fb,df7ddac9,84676421,2c4d99,fef41e5d,98e5824e,cb181a98,9a67fdfc) -,S(219d05e2,a7b8cc69,bbce368f,62922992,b474286e,df7c13dc,8da62d16,1784cd2,8aee4f73,9a7eb1e7,8ee9407d,e8fbabef,dd28203b,2161ede2,761e178,a34c7f5c) -,S(d7d0cd59,9a76fa91,f691fa23,ad265f38,49bbe213,c38cb074,852005b6,d85de204,f349572c,60750dae,5ea1330e,a725a0ef,ed1a2d60,c0b1d9d1,e938f37c,911ce2fa) -,S(a3fa69f5,a04c9023,83d8b73f,6fa8fc3c,9f65cfbb,2c77042d,635f4978,eabb6c6d,c798a1a8,9994aab1,4af95b18,f389a2f1,accb2d7,59997e83,72c1ca5a,c3cbdea2) -,S(902e881a,825c457d,79872e71,e5d94170,8540734c,1d050e92,cc5c8afb,13b2d1cd,ff075132,63bf6fb9,11163ccc,f62f8246,de099f07,ccfc9e33,8ac82c30,bda62d43) -,S(325f19f2,4c470556,d361aa2b,3f1932bb,6923ea5a,4f8cb505,d34cc60e,729c144,f4a9aeb8,29a6a0cd,f981bf35,81bf8f9d,73e3e9c1,61996178,2a57c46b,9e94bec4) -,S(6994f3b4,41a6cf61,53e5f860,2cfffacc,bcdf7245,eb078247,63bb07c6,fa1edd4b,ec2fc5ea,892da897,29c479d8,d3f05152,198ee4ab,87f73bd9,27db1160,1874c174) -,S(21855832,4e8f796f,fd51bd2f,8c1f6a8,5663c5a2,b5bad37f,3b7a1052,6acb2d8c,e77ceecb,33cec03c,99690d44,b0343bf7,3b93c495,5d67ccf4,b15d1d76,a1897c2d) -,S(905daa3b,32f2a801,a567c312,ae4772b5,3196933f,487aa1b0,a5674cef,9d91b099,bf6285c3,6d271719,13691d5d,767fdc17,82b64843,5b2ca1d6,b695871c,41cf369f) -,S(df7cfb84,34b60524,75fe5161,3dbe0e7f,1b685376,315397f5,b39951ee,b65339f1,e725cd7e,1419e455,2d953393,dd9651d5,d1beb3c,6fa44d2e,e580ccf4,df558243) -,S(e7fb9efc,88842b9e,a3c96b82,1ca5eb80,385cb276,28cf64a5,d8c5bcb4,e5732491,c8e676bc,a6f9e037,263b8390,675a97d,1353c128,eddabd5f,5e928153,78f22331) -,S(d1a35f0c,272ba216,1e6ac0a3,fa440f59,bad79715,d71e12fe,cc12369d,cd24285b,1f5b70f7,d475716d,b9ef2f21,bb156400,49dc41a8,96102ec1,806b949a,c99edb3c) -,S(66ba6e8,5f2ddd4c,e17da74a,c7ae629e,4f420429,45932e5,55110da5,2a7b079f,d8ebac5b,eb8eefbc,f4da4f35,79bdffbe,21967904,36487733,263089e7,7a80402) -,S(6f7f69a,26881052,b4bcf806,575f9c50,c36e7c22,1d7b9e48,7b1f39a0,b4f3a749,11d06b84,d89b88b,ab4352b9,cc160e50,bc183558,25bb602b,89235aa6,7331a4c4) -,S(4be16d6f,571d503b,26169906,75c01ac5,41c23afe,84cadb90,eda0c21c,926c0abd,1041ede,ffa1f2dd,61a116c5,dd33fed5,d9ede78f,cb2311bd,9a04fe32,9ec1d06d) -,S(8af88c5d,b55eacb6,760abbc7,91698c57,19160335,ee569bd,33bf050b,1e75886,4f5b850b,6bf2b4b1,29aeeb24,596007c0,ca203eb5,d2be6bea,f61bf596,bdd9a12c) -,S(ad33e77a,3316eb8e,1a764849,13915e81,edb69518,8ce7507,2e2b6088,4cef8672,fa0161e2,4bc88bd9,da5157fd,7950c75d,6c4f4f89,f158f13f,16ca5e4c,af7ccd90) -,S(444a81ef,7620afe7,91d96ee9,b1c34485,cdb51e1f,6022dba0,69ededb3,d9d8c2bc,a88017d9,a49d4ebc,2ee811c7,fbfcd9ba,bd268329,1efafb52,e641af11,9751e2fd) -,S(5b1e07a3,9530f8b6,60787e9d,26503a2f,77af3ad1,24ac8aa5,1d10b663,ceaa5c51,fcf4c0d3,8d55e0fb,2731e59b,686a806a,e87cb510,7bbd013b,4500c470,f77810b9) -,S(3e8c17,e986a86,57b4c403,3317e67d,b1d42e7d,9625e844,ba533ed1,73174309,deebe49f,f4f5a35d,ea0f396,63c7ee0e,9db702f5,c296fe5e,696f5521,94cd6caa) -,S(a1096eee,5e9bcb19,9d24c078,b46b528b,6432af90,7f1d57e5,746e83d8,4d112c1,bd13e4fe,699436cd,656b3019,acd54f3c,97eace0f,e1e92fc1,3f08a76d,d2e7c6d4) -,S(54758579,4218de75,db40a6d8,99a75ee8,36861093,4ded0938,98c071b7,6665f2f0,3bd55642,13e1c689,70cdcd94,fddaa656,6bcde4bf,29c761b5,c6f613f6,19174548) -,S(4eb32992,fcb4bc44,bff56604,f4f74586,a4400290,5ee9adf7,f7bbc694,45456057,8576a8f2,68349f01,ada77c67,30510030,e0cc9d8c,66db7609,21661540,ba45c3d4) -,S(350b2def,d2eb4933,c6d428e7,5990a7c0,f291723,f92e5ea2,69c5b4c8,b661a22d,61acdb00,add9f34b,f36126d8,380ef5bf,70f807a8,1320d59e,3540fb25,90de6943) -,S(914ea8be,ce7f8819,5337341e,eaca129b,2da3c96b,306b017,d7afd984,75f360ff,f2aa5548,ebef80a7,483b563c,e8b242db,582948a4,9fc89213,d3272a63,85ac7b53) -,S(f656e17,38da25f4,baabaa6b,d70e3f5f,ad6d44f9,c53e1a33,4596246b,83dc0fef,40a8b4fc,34639287,a65f53c,f373c2c4,c742ce4b,2040fef5,4c31dac9,59fd83e5) -,S(a47c8af0,334e3ce5,464310bb,c0daa66e,d77e1023,a2124182,ce3e6771,933b618f,6dbccb54,56d7c75,5e71694f,fa1713eb,41ec5b2e,8715ec4b,52295294,c0c7f08) -,S(a8a2862,5e1d04a6,5e87947f,82178d5c,3b5fde31,1eace688,6766ee9d,30753ca9,f82ad6f7,483aa04d,a79e672,efa109be,1feb3f75,d73923ba,94df2f1e,2efc2169) -,S(a01ff54e,5f8eb855,e26903cb,3fd407ef,4fe06208,a0f44837,1e83f7a2,31c017d0,2247c6f9,c52f1a68,84c18ec0,77d92514,9fd59b00,27663ee2,f0e5b2ee,f2edf92) -,S(e7b09c3a,626ac89b,6caadbd6,99a320c,61ef4fe3,11f6072f,f2d7c875,8d42aed1,8ed996d3,6a7b50e9,8e5c64ac,e03cf5a3,37c3c5a1,6d99c5e2,c0faefcd,38609fdc) -,S(3bba9e53,336c2a06,ca89fb52,26059041,96307c97,373cb717,3f35a45b,863ff2fd,f2fe9109,3faffc16,f58ccaea,e54e9b8c,419d5123,6e8c960d,52ae8341,27d24799) -,S(f61d22b6,dc660174,22122400,432f533,11950c21,b6240acd,af905f9c,2c0630a3,6068f5a,1a662cf3,93eb7e86,5cdfab18,692bb250,15de2796,1421a457,49ffb05) -,S(a5b60855,6b1aa22d,8bc38dcb,8f3e4721,891c45dc,2702d13,7189be70,e8a80962,f77f97d2,d5e305ca,1fe20b99,e6c182ae,3a9b3a69,7cd5e34a,7199032,fcb1ddb6) -,S(70c3aaf9,eb2562,e1cae950,be6f592e,f030301b,28022ac1,be3aa5cc,85e1a259,3f2cb7cd,31a8d319,ce4626f7,213aaef7,3f91f2be,a17addeb,61f217b9,4c587583) -,S(1dd70dd1,a8755e37,28dfcc4d,443e7911,a67952af,c33e7d93,b975d136,8d06e530,4684f974,1f5894ef,47040074,2ecc73dd,240e677d,b6bee0c4,141dfcd,7190d084) -,S(d44d698d,7aacfd4b,d8d6bb7f,2d0dca82,f5d37c3d,46573546,2b180cc6,9083fcf9,a18d803d,4232965,90c67b0f,4c415bd7,c0c94041,3740be47,2819bebf,87dc407) -,S(84589ae1,30455742,85522ae7,4b1bc3bb,62730a10,6154d9f9,4109c010,51b34ca5,b979fa08,f2a9af49,bf6ffce9,b2fa707f,de14fcba,3de3b903,49bf6235,37b3606c) -,S(3dec8fdf,89118996,bed31c1e,fff15c1d,bc84e73f,fd04c6f5,469d2f04,8b724627,b143f3c1,e20b5bcf,dbd1a555,f4ff88df,dacccaa2,bfd4310c,16ae2710,1beb2c8c) -,S(367a5fc5,519dd9c6,39bfcc4,70ce465e,23a8dde,417b412a,2f0f4374,8cac160,5b8fbddf,2c6bfc90,e291b136,a3e0f8f3,faa64820,97a87cc2,dbafac5c,a7f021a6) -,S(8aa5587e,7777606f,60bab6b3,20d88e93,1e7c2efd,487bacce,5fa3256c,9463efc1,ac5ba76c,98bfa132,c16921ec,aad52289,50beeb34,449e0c18,88a39fd1,d3f091dc) -,S(79c00191,ea632ea,30fd9e6,b0d11c6,af3aa441,eca678c6,a5d6bf3c,c84cae0,3f954070,3b19a941,3ac0b659,bf401c2d,ae9c8bdf,2bd19e85,472d2d82,39dfb899) -,S(c84de722,21a59e95,cdd951a0,66483255,e858aaa4,ada498b3,d4ef8bf8,3a04fc8,73cde958,915abf28,df811109,a6220449,548fcd2,f639102,158bc451,4af0a0b9) -,S(8b1b8c50,c6327d61,e063822b,2a3c5935,fedf74dc,fe694c21,8cb6b892,b5a9d6d5,57bd8952,9f156435,f47dfc47,9ff4314c,c036766b,5b6437f8,41f60cb0,fe168b) -,S(b45eec8a,3ae82f98,52117c4a,341f8184,33a31ce7,719d7650,e783fd52,48702c52,cd556b5c,c7086b4f,905d0fc,ea01497b,25411785,9ee9046d,c988c6e1,9e0a1c90) -,S(a2d5dcdd,d93096c7,67b4871e,ac58cbdc,31ab7013,865a9cd2,c5707780,80757319,7aa406b4,b130b23e,9e6b5978,b1e0b537,227ae8a8,af62c1a6,a6d46ae,4b064547) -,S(712036b4,e5d35950,a7564ea8,3509bec1,e97f6e19,121ae5db,3d314c19,b9ed2b2d,25862ff3,8d0560ea,4698d2f,425342c8,e3a32232,f9c9572a,21d7414e,68a93616) -,S(5bcef0f7,d70fc8ba,942e58c8,79afc973,dca402e3,795adf0,7562b552,f0bfb392,7cc85a4c,ecb45bfd,3efb0e12,c3fc56f9,1a444ce4,73256474,54ccb089,baf1919) -,S(dcd5702f,9d508a1b,afab9f0,af5c4e9b,b9e5f214,6767ab0e,b5c1d859,39741ada,f7eaead7,ea13e3a7,dccd40a4,a2526501,3369d558,6f0c735f,9eb2518e,ddcc1fa1) -,S(2cea30d0,4f629d,91c3ade,1b8b7176,363bfcb9,25d3eec9,784b91bb,e6cb3d9f,a83f4bad,a42ab171,cfc9a76a,a3dde34b,c48ba454,b39b36e3,44446096,a1c42624) -,S(858b41f2,767b191e,df15fcb1,3a41934d,150e54d6,e95035d0,9c6dfc7,a1c32f8d,8180b97d,76dc95f5,478a2172,4802a28,b34d6e9d,f65d5358,e5cecf82,9fde8dd7) -,S(d5c98002,bee359b8,6d1234e5,ff418013,3eb9a668,d2f1294,245fd020,c30e81e6,4e522da4,cd2bc795,65a2e4e,e2fc87b7,a0b6bce9,1d90376d,921aeb49,5b3781de) -,S(ebf9162,2f9cea9f,71a4ddf5,82de4b7d,34002d76,da8acfb7,d4d6c3a1,9520c1ed,eee75322,3e1881cd,8e3fb483,318c75aa,7e43d049,8e53536e,cd481d18,5ad4e251) -,S(387f6a9,d08756f3,8c2e111,af74be68,acc4504,f3669ff6,b406f6c8,a61db4d,288595e3,ea1d5f91,26df96d5,dcf5cf4d,ed0bbba2,37224c4a,59db552e,87cdd28a) -,S(897ff1c0,989bd52e,383a2d70,e5920144,9aa409ee,9fef20df,25574956,dfe46714,3cfbc0c9,308c6529,f4e95a00,644a873a,de094069,36dfd6c6,bcaecfa5,9adc9d1) -,S(3255a8a6,8e0484c7,8b6bbf21,e2d8b24f,bbcbb337,6f84feef,b577ef1a,b5a395af,17b3c002,f9204b84,e6d4a426,d2d74893,79ef3fd5,441e881f,d8122599,2912aeb3) -,S(2ca4a952,d4d9e3b0,3943eeaf,b1eda225,1fbca101,e7071b7e,2778ef9f,ddc55599,bfacbacc,df02c18d,f81a2c04,4748c7eb,e98631cb,63ca16a0,9892e163,23891e00) -,S(c3e8289c,478c334a,d47b0410,e1b6ecb6,46ee5f8,8a4dbd73,10505f6a,de4383b2,5792c2ce,b0431238,647f4309,cb4ed220,229bee,2727b91f,de4004b3,d6f0f55f) -,S(2bbdef60,a86292f9,867ad63c,67f98420,86fb968d,db92d9d5,f87bd27c,15119049,f4a4b762,3536c479,29099d19,3d40d4d0,e75dac62,54f03538,80286756,60a85362) -,S(77a6e090,9e7dacb3,18014ef0,714a4be1,fe3ee47b,e22afd2c,e0333cb9,ff2496a9,54f0e475,b1a9906c,d1d915d1,81961492,34461e27,e163c384,3815d188,5251065f) -,S(d195b96b,78719254,deb4f413,979f64d6,ea94d5e4,79350b11,45c39e45,4f40ff0,238a4440,613c846e,9472d4b2,b0a4db88,b8245cad,a5af469b,d997f729,c0e0636c) -,S(c39aa336,208aa65d,75bb0f3c,6084f414,ad024d15,48da5bd8,113a619b,4815b1f,7aab1ed6,32741dd4,14883b22,6e573ee6,455a0053,6d849200,4b233153,1126fe5a) -,S(e80ca23d,baf82db,cbe0bd27,24cbb31,d6661c70,44d8a8d2,2967764c,fde31f30,a153d1d4,73187878,bcbc583a,5eb83e5d,f67e8142,46861713,8c484744,a597451b) -,S(395b7a65,a5a9c23a,f96723a,4d595a7d,f3e8505f,e0aec120,711cb7b0,2e72ef80,59020dd5,47476e39,36ad37b1,9a256543,4f88cf03,2992f4b6,2229a5e7,e49bf990) -,S(67a7e8db,b83e23d2,7b57e2cd,9512a5da,e8b49545,ffef2577,644fda22,910b495c,7c01499d,3791b9f4,100a89f7,8e80b410,41fd34ee,68ce1f15,a8753032,e8965735) -,S(c4038e7d,76d2e7b0,86986395,2cbe2ce3,ecfb4b08,61423892,ac9b3b3f,6dc0c7e7,61bb3b0d,9efc9b7d,326a27ba,bc34fc8c,129460b,6642629e,72f20351,65e92f3b) -,S(7705a5e2,26a4d3ae,ee69c52f,5fc3f575,b9bdda08,70a19a8,8a525698,c3a25e5a,458e096c,f01906f8,c2426973,d1c6a982,44be9e02,22406207,3a883e4b,53c7a1b7) -,S(f3ce8bc3,5958b5e6,16a994fa,1fe0396,68a5f1f1,b464a875,9e4a3475,34ff48d0,9c1a1d97,be3ad78b,67c8c441,f7aec63f,8dc92aa0,87500d6b,222a2473,e10058fe) -,S(905ec120,de69cebd,b9a9d764,e01d6f88,3ebb94ad,af5685d7,6649e7f3,3ca4e0d0,92617e99,3974aa3a,774a75d0,e51c00ca,4d42ce12,d79ab0e9,3a8e449e,9ca9d554) -,S(b1b74a4d,a3578592,8bad0edc,3664c1e1,27d48447,fdb246b4,f15ada68,9b21eeed,c43539c7,b84e9e8f,bcce3823,1322c4d0,c14e4d90,33c4e132,8f5b26ea,9d3206d9) -,S(d440165,c72f2d46,b2fa2a47,1c42dab7,8dcf814d,12d3e025,bd5fb963,3d8bcf1,e0864950,261f5fac,e97ad9cf,fc7683df,fabab749,1d80422a,ca30721f,5343ae3e) -,S(ff524c4f,722c19a7,f7b910be,6d573a57,fe08d5af,6580aed1,de03f939,5053b303,fd4ad4e,5b25aa8b,b3a62dea,b320335b,5b9f1368,62f5f913,98fbaa61,b753bf0d) -,S(effde0bd,331c1083,e4b76a53,c9c1ba43,8fafa2b0,4a3ada44,63a5fef1,8d8d091e,fd7a869c,a75c2105,e6ae5420,86ccef0e,c563bddf,2b41ab9a,ee0e14c3,1d947dde) -,S(a5e746c0,99c8d99e,88b4a304,b583adb2,1115ba64,e409d278,f40c4571,2f3875e8,7f832112,c2af3830,2c4baba4,f073f7fe,84170939,dd9e8c07,fd2c1eef,2e934a68) -,S(6accb9e3,af5ee943,9d8daa72,2fe45513,7df5e274,486fa46a,1ba19093,32ccb431,f0de1658,842d6580,507c26a9,b68f92e5,a3faf108,1fcf5dc4,43ec9dc9,9f28dcae) -,S(c813d055,e40d32bf,6e8e782b,3ef85698,b86f3d31,ed0123ba,1ec8978a,f72b6d4e,baf6d757,2f924631,c4da4191,684c6280,47d37ef4,2bb9528d,28879011,8d068ca6) -,S(8b882012,2cadfc62,44fbaeb5,8be4d587,599dfae6,2fdf1177,38a844d,97c7aaf9,f5e6c293,ac900da4,f716e131,fa5a42a8,7867c8a4,76808b2d,4093c782,6f7a6a3) -,S(8f075050,f49ee582,b54a5acc,4ffaa443,bc02ff34,4d0717ee,9619d83,2d7310ce,13b901bb,7ab3d325,7cc555c4,a4799a3d,f1f9f9a8,6b7021c9,b99a1315,b5f7fd3f) -,S(bbc852f8,cf643e54,3c65fb1d,f2f72c97,89a456db,21c81f66,921d411f,b0374c58,ad08eabb,e7971e24,b2bf604c,fb248b3f,a27e1c2f,84f032cd,4c14bba2,b30a590b) -,S(2d77dc4b,662b55bb,878edddc,9dcc2dcb,9278cc,b1e549fc,ffa02503,1a80bc1f,288bb0d8,4fa7f2a1,ad1a62f4,e76ef6ee,c07707a0,89caffff,a8e60870,ecd058eb) -,S(bc83f71f,f3b4a86e,b9bdf7d9,94bba6c8,c90945ab,9c858b4f,fea7914a,d7ccbdf9,18e91fa3,e5067d23,809ed455,3d119541,fa3c2563,a3a88b30,20d3e49,4b232292) -,S(7d5b9657,8d9b88e6,b0e11b7e,847d0524,45f83dc0,e2bbb7b3,205db435,2c200919,1e689f7b,8830c10d,c28e7230,c569af4c,b1c9e672,aafd4d35,2faf5570,90515ba9) -,S(85e9f364,8d758688,31dbab4c,7460c4a1,51614887,cacc3cdc,1baf928a,200cdc80,7f4ce518,d5045c0,5865224c,c07f7fc3,5ba5e4f4,c03ffa9d,d5f8e5a1,31369e27) -,S(425390df,c1c094bd,34855816,dbbdb71a,9c1d1077,45b1c65d,a101d974,4acd0810,81f14cdd,20ef4d70,69026d94,f09de176,707547c3,8c0f27d,1e277d4f,1f49bc00) -,S(3cc7cf0b,66dc93ac,250d00bb,60a0f75a,dbb59409,bf8e4419,4cedaff6,413549d7,331a632f,c3dbd899,f688bcf9,9df70e66,ae17b719,a2beb23a,664c1d6,1c204a58) -,S(fd72088d,b8a1bce8,8fc923b,cff789d8,9d6a0b2a,2be3b5f0,17e2b3eb,ce70853d,d3912b23,a38819ba,eb329638,3a0bedd9,93db4aa8,df647494,b710dec9,9eaf599) -,S(3e558f8d,5e0096da,4d8940af,9a0baa25,c7318541,c7dd37a6,b72b35ac,efe65060,2a403d7f,69d805c,3ebbdb3e,fba95b87,f78f6431,7fec0dde,7695053d,e660e90a) -,S(70708223,f525f222,16c00149,fe1b745f,721ec32a,90fd0b01,e82f2049,d8694a7e,ef4ad787,f0b4d53f,19d86ac9,7d943b5,fce17d88,6366354b,410dabeb,efd12569) -,S(eca29625,eabffaf6,4b9eddb7,11e4cf76,440b4a94,def9d2fc,6e5e9114,aa414f72,f1f83875,75afa3fc,b23bb227,4c5890cf,f798b628,283989dc,d3538b8e,237618cf) -,S(5b7c4750,542df0c4,c4606db4,6861925a,da7423a5,66d6c108,77838f65,5f297695,42811366,1ae1889f,d6ccb1a2,4cd9a6a5,de04db2d,5e805079,5f922b9e,791f784d) -,S(af1a5fe6,40cb2ee,d36982dd,1e7882fe,bd5da168,8005838c,b379b986,bc012042,71570549,305fa634,a63d12ed,1fcfc8a2,5768778e,863d4778,b7e41215,ad3e6224) -,S(727443a2,46787e70,f83cd1be,1189c4cb,e1e8b18b,1d57746a,9a319676,9366b1d2,86357826,9bba3e89,a12565cc,1770e5b4,4df56ac0,d202fdea,d68928d0,6d16d540) -,S(967979,db34e62a,149e6835,213991f7,ae2c9a2b,abf3d255,6c5e198a,12640b8d,99dc1d4f,52445651,3cee44ac,3bf3d1ed,8547b827,251b3b01,4d4c07c1,fd9edcc4) -,S(794009db,8f3491e,27ef9d73,905b06b2,be56937d,be57b8b1,59dfb883,af203601,5a6ad64d,7ee5e1cd,15a6a087,289d86b4,5db60d24,243917e7,50eca61e,2ada40b6) -,S(87cbda39,6f90b090,dba9470b,1fb0dd1f,d2f4212f,50791511,cf6297e,a9851d10,9ca095f3,a2a4f997,501fb4c9,c5585dc7,fb8f7952,e11cd3e7,73a92005,a41b63f0) -,S(9ed57b03,475d1752,58c20772,1be7e12,cd1f3ada,5b95fa8,4b245b01,b910acb0,d58c9054,43bd81af,85c58a7b,d0cb3e8b,25310644,8e1ef50d,324eea36,a3bbd5eb) -,S(ef8d0a22,92ca4498,2dac77e3,86113363,35fd9521,fd266be7,d5d354e6,28b0402,e55c4b4a,556881da,a4a23e5b,677c1a9a,f2f547d2,e2b4037f,f9758a74,3cb58b6b) -,S(6dba21f5,a274f29d,502d369f,4fa4ed08,2299f6e1,b12f5c75,abd01597,d127e3d9,7685f72f,a0ce41e,8c4302de,3e6e9c81,c951f69d,d2df0f3c,930da77a,51a39d94) -,S(8cdc3ebf,857ac235,7dc1b0f4,26ed2a52,7841969b,7fb332aa,6ba44693,c8399a3d,234dd3c1,915ac714,6cd8724,9b68a19b,df250dab,2748abec,a5876fa4,b7f910ca) -,S(a00829c8,caa665b4,7e3391b6,f4706898,a9c790fa,29344de1,e88fd882,b5eca2da,b7c8fcc7,1e834cce,5884b129,98318254,23486297,6068eaa8,184b5316,fd424110) -,S(5872f762,446cbeb1,4a12e54a,1d4f22d6,a4ed5b2e,eff7c5f5,640801dd,2149ce6a,8aacd3e8,862757fa,1a70c29e,24364ef4,4c37d5d8,bbacde2a,c75a0c1c,28ee198f) -,S(b70ed5c0,5dba7150,f22677d2,e5b532cf,53e7ceac,919d3b2f,ec4cc6b9,2fd34f2,7e43f528,cc74171c,a2fcee0b,18d8fcb,76c3d69b,8560831,26bd4482,a4d28cf8) -,S(4beaa213,3c6161d0,c7da6d7c,8eb09cba,2e8ca505,a790a7d3,9d0c16b,8053bb52,da4c083c,9cbdda2e,c6626d8f,e4b2ee13,703496c,c298bffa,db1acdca,99d4f6d5) -,S(a8d31ec6,53ce1834,a78de363,c5f9abd1,8594b34,4d34f5fc,8a10e81f,5804831,b4d6a9cd,7cbbe370,9edb5601,cb7c8ba4,8c462c18,594a4bce,64f4c286,dac5cff9) -#endif -#if WINDOW_G > 14 -,S(a8f11586,f3df4945,a753c485,ee0fd4d,e410771d,bddc1b26,c9ff10e0,77b915b7,a4ad6f16,dbd741bc,71b2dfd2,dd2d340,3816bf73,4e73cc10,abcfa6bb,d0f161a4) -,S(13e697c3,812d4772,254082da,372892d4,e1a66e1a,eb16bbd4,f7a0d531,c979cb2,87fa7baa,f6def12d,31e42c14,f672c0d6,a9d0e2e1,ceee2546,d65bd01,c18df57f) -,S(3cae4590,821a9697,a5963269,b44f0222,98f60021,b6048b3f,49c6fd4d,8650c7a,e03f8745,60418449,ad97f28,41664745,349329d,268c1c43,86e25147,6e44b234) -,S(6f42f6b1,cb6bbe13,cf081480,766cbb36,9d2e63e,e691722e,ac81621c,66e0fccd,e5d8f8eb,67702ed9,e33c7b71,e3cd7b25,cc9cd315,314815b0,b67e8622,fd35f022) -,S(43d24bc8,469cfdb7,51ca7d82,98727059,6fac14e2,11d37041,370f3bec,90e411eb,2129d618,fb1f7030,9715b2ee,d8e70aad,8b172b74,425cd747,3a3fe40,d7c50dea) -,S(259170e1,d48b6f36,6a281592,3474f0de,434f4ccc,e45126e4,a15c503e,c1f8b97c,9ec06188,dc194bc2,be131217,bb862943,aa9cf36b,7703c45f,b1ffd282,c3c12549) -,S(18d547f0,426139b8,7837d1c1,ca0f5f06,883581b2,c001e8e7,2565c9fa,80fa2719,26d9dc3,e1145ccd,23ae36e0,5c133f6a,5ebaa9fd,bb954792,3e762a8a,9fb60260) -,S(23b5936b,f2dc961f,2fc93814,4c96232d,dceb477a,753253cf,1bf05713,1b9e58be,9b678070,1bd976e8,8d66e740,2c00bec8,e4fbdaf4,976289a4,4391b28d,45519b07) -,S(46de46fc,209df62,6185387,938724fb,702c3239,fcf29113,2807894d,148774f6,cdc2ab0b,5d37a348,1b44de55,d9c50ce5,4322f8be,6f284ed1,ee49f04b,65f4f2d8) -,S(d3b78208,f5876faa,c4d3c970,3a87a586,e897c11f,dca9a7cb,6573c814,9b5d5da9,112ecaec,9f4451ae,23485579,9cfee804,ee053df7,8e65713a,cd43d953,471863e1) -,S(52d51f46,ac86afc,391e6a1d,8ab1d862,2492ae18,b3e86f13,5e42fed9,4cf3735a,cea47627,e7eefa90,7b8bfd12,f3212ea0,bfaf9e00,f407bb4,8a86039,d4815215) -,S(46451d04,48f3f959,e133723e,b9138a73,b3877adf,f294ff15,6303a845,65a4c39a,fd1c4a00,bbd9aa06,afb14790,5c0530e1,d6c3b5da,c9001b9f,8ec76df3,c7bf3c76) -,S(a12f5e51,16c58aae,90d8532a,9182d54,f539014e,e2d8357e,5ac7854,26fc78db,3db94e9b,f37ced91,7c9f466d,2a6db2bb,21725e9f,f4dc1482,3e6e384a,265e0cad) -,S(98999fcc,38fe6b71,97ebfd61,fe8942dd,be944f98,6f139c4b,7bd6bd3,28ac250c,48adfd3e,c348281d,c23335bb,8702cf8,acbdfc84,9ee34a3a,14bf36ca,b7dd0ae8) -,S(8ac22420,f9b9aa05,705b31f,bdb57d05,218ad72,ce09b489,4d0b515b,4e5940a8,37a7e2ca,442b2446,686f91da,db6975b,6f63454,e3a96df3,de8c62a4,364d30b6) -,S(cd0804d7,b1aea00c,13a94a33,f75f3736,f5759080,96a2d418,c5b54c72,de31d619,c7f68576,10df1c38,6e677bb,dd6dc121,b3d9e9ca,e54d22bc,a5ce1184,a3dc755e) -,S(b6c4bde6,2f8fe3d7,3c32e641,573098c1,c559e847,e40f60c3,49d40050,49b0411e,62c691f1,68510458,3e5191b3,758d7e3a,b2cfa31e,7a00d7b,97e39f88,786f9a9) -,S(c20990dc,70134917,42cec766,8b725c26,d918cb46,6cbf7ebe,7b1f37bd,63d5df0a,6f1e71ce,e28b22e1,9c6f180a,4d7a48be,9fc696f4,cfd418d,134c1196,6e285d1f) -,S(ebf16672,45ac7f7,385b5356,dbf977a9,3602a11,40ada114,7face805,dd93f9fb,24b15faf,3b3ac9f9,833882db,b81a976,9a37e6ad,1a4228c9,a4f7d0aa,fcca3400) -,S(1c620657,63199ded,804deefc,c33822f9,cf3d4c1d,72f2022f,37714eb3,83367621,600221e1,48f74ad4,dae118d1,b6dca782,e00117d4,92881c23,b5a7cb79,86cad767) -,S(40b300d0,7520348,38bec63e,f155b527,286db841,754702d1,d512c183,345d492d,29305ffb,31b1feba,abe027b5,f432679c,e265a57a,3960b8b5,a66e6de9,5a10fee6) -,S(5768ffa5,c8b56772,1e10c2ea,421afef5,dfd84120,a8d40e13,751a895a,fccc6c2d,52ee5ce2,e60ec485,7ee62e81,fb2eb118,4d2a6ecf,d8ab7e09,dd728d16,5e508d30) -,S(d906e71a,b6bc6697,858c66d6,82aa85af,e8d80ced,5f470ac0,8158b5aa,4cabf2b7,c75ace8c,74552756,8cad89e2,201dd954,bc6f4ae6,3a671d2c,9bed78f6,40b7e70c) -,S(f71937e,f4553a81,a3f155d2,2f81a5b6,e080c0ac,bd8f5c5a,fd437960,6a63460d,d6e4e57d,422df901,e6292a28,c83c3bf4,136b5700,f6da0351,33099feb,f1228b19) -,S(3c498699,da858f1b,364c464f,b4317b76,5d085393,1c187888,83072cfb,39ee337c,cf3033a8,9749a0f4,fd4ad867,67b919a1,c946dc67,cc46524b,af5c0015,833daa0c) -,S(c416570e,cbc5576f,97090660,438dc3ec,be269c42,6e36fc44,45d53b0e,b2c5d54d,cf6380d8,76e20ce9,5cc181ac,4fdd42c4,b91d7132,d1b1c19c,4cc0db01,4ed782e) -,S(8f97b2bd,344fcf8,62846992,e826f5b6,7fe7d103,28f34231,8a9f7de9,20d71110,e296632,fe41f8cd,b3da3ca,e1c356a4,2424c649,11dcdd58,c21aa1f8,cee07ec0) -,S(6283f371,8e67e917,5b8c1bf,28e66bd8,470dc4a0,1a720a8f,cf1df325,fcb0e10f,5e80225c,87c0d6fe,3432db79,e8cf4365,8640ad4f,21efd2a4,333eb6ae,a46bd342) -,S(9e29c616,ba66db06,bb71e56a,2a049727,e07b83ff,cdbff6ab,898a73a2,f2f9d58d,b5997133,bdfa29e4,431494f2,8444f186,7c4fcc1a,516ca195,c8eb6fe3,f5693dfe) -,S(7a0db51d,56a2b33b,8ab33329,a1d41454,a30e34fc,3db33a31,45c1cb07,923ca061,334164ab,64cdd8fe,9a106f2d,156a16c1,5da4f07,fbd7f1ad,e9d1fd7a,c8630fc9) -,S(5994233c,13ba74ea,19c1c65a,c3653a6c,cef79c4b,bbb827af,e736545e,33ac05bc,2175bea7,3090437c,9af6f994,b33023b0,5fdb278d,c0c59063,eb3b805e,a6b6bf6e) -,S(11e13de,2371f715,4d15373d,d52c504e,50811146,10ebeaa3,f47a3335,ee4e17de,fa961827,b81e71fd,60696d97,17820d67,ec86e8b8,74d3d4bb,f50df644,61f738b2) -,S(787099cb,c8896328,dad08bca,4e682e4,90461574,29aaf740,23795a1a,47f25ccc,1ea5755,bd653ed,ee7ee8d0,b3e6214,df2e31d7,731a1c9e,47a95f46,8c3c8ac5) -,S(c644c88a,fa42bae1,27bec7d9,528cd695,7bf7d906,942baa4e,14ac960f,46469cd,9d7b39cd,22007b04,f61c5905,3a3b7614,81dd45a1,532d395c,baf8ffff,377f2644) -,S(79d1abe5,cdc8b0c4,9508a87d,46163d1f,ada43640,ca1a5e89,d2f1c07,8c58820a,465cdc,983f1be8,948b850e,a9a4d9bd,f3898781,65d5a186,1c94d3d0,3fb9289) -,S(e8d4fa8e,db2a1612,d7b6fd8c,d6aa2f1e,a8f1ba1,32572d6e,dd0826ce,bede0e55,92aa3d43,e944d032,afa03d23,dcdb4604,56cb0363,1fe2f8fc,404dd9f3,f832f065) -,S(6f99e75e,b09110e7,3d5e304f,bf569037,577554e,51861356,40c2c69f,4a92e88e,63b5bf05,c554aa30,261a09e3,b292b9ce,8f1bcbf0,ad91c35,aed04f31,567757bd) -,S(cb089170,d912f8ae,e59f21f8,8860c0d5,182b5252,3b2cdf35,b9795d1f,20c37815,4e8c5b3b,6d79cab9,9f2570de,8c58c34e,6b6f5e19,b285bc4,6988ac86,20e645b5) -,S(5c248793,51e487d3,af1b6d16,b25367fd,9d2b7185,9923c565,5d7567d8,ffd621f0,5806bb36,ac3cca86,2624401c,27c54e90,c76fc747,7e83e6f6,ac89f22,35c84211) -,S(f1d10f0a,2ce54b90,ee71ccdd,eb6dc4d4,c2cab0c9,5cd35bea,5f20d3b3,51d15896,7bdb4d3e,cc613f8a,8fb84d25,541970e0,6c7385e3,c04022d5,82e2efb8,4998eead) -,S(536a5966,b594b460,bd27b4f3,aea6b555,95940f06,311970a0,36dc0fa2,3a274519,c44b0b54,cdb4eb87,b5d70d9f,bfd4a601,5c34182a,31a882c9,880878,7910b3d4) -,S(7f8165ce,ed27a393,41d542e,ba9ae875,554265f6,1c1c56c6,cc0bbd66,2ff88686,6993724,26c18b1b,dd1207e2,f3bcc0b8,673f481a,e7638d5d,45134835,9b4e39d6) -,S(12214607,c610d012,83b9265b,c59d7458,4e0a79f6,8a4e8535,a72809fe,11a6830a,5d26e498,9e3edaf6,27cc4bb7,105ba8de,3344e506,d9bc9a33,8f1e3219,e473e609) -,S(9ad7f097,1d1c326b,8ac468ef,706f53a1,9e8fff25,8e599f0e,72acaa15,b21d58b7,2e7c0921,2199c7cb,da8d3645,a5bd7831,4234849c,41a238c2,a3dd7fad,fdb8a880) -,S(355f75a4,9df69d8e,4ccad41b,1fb0445f,619ba9aa,34697a5e,24ec8e92,f5b41068,9ca83421,4622ad8a,90a09469,d155bbec,717295ec,c071894c,6c91a7b6,e1345f24) -,S(bcde8058,8336a996,fa6af5bb,5ebf7441,ed3bda73,4802ab5d,5c0eac31,8017c706,49e40844,78cf1912,ddc91907,26411814,a782a3c1,452117c9,993d9e8b,4f247563) -,S(372cbbc3,3417320e,21ac4ba5,f286a9ed,273b6425,e8ed22b,d0c352e4,f0a97270,6e05363c,bbbd6b11,8f2842d1,243dd629,247e90d8,4e7c9d02,c3677f93,d1d01bca) -,S(a1122e8d,82e97ff6,ce9fd024,cd4ff32c,76aa0aac,c1c2849d,887240a7,a368e064,ef97035e,1df99943,1139cb88,e03bdcf0,8b3a5c86,d4b42d13,9b3acb12,e4e7df3d) -,S(e0101d71,1d0c7b60,8093997c,229bbbed,63b05224,53c0079a,518826f9,2bfc9d5c,a0acb9e9,c3d3d384,7f2d38bf,29da71c9,af0b5a41,5bf738fc,be24e367,c8db2fcc) -,S(6df3e575,4b62c92,41f8aba4,12804ddb,74ec864a,12076a34,d9cdf9ce,be336e8b,bc66fbf9,276fc85d,767c2155,ef481295,963cf371,c0ae6b48,50140d1f,c32f80d6) -,S(e5794801,97d3eb68,fd859d0a,a616912f,a2a52a7e,f3881969,626f43ae,4ac20586,3ba69743,176c43f7,7afdabef,a06eabf5,94b9d0ec,1114f352,7cb1b127,697a5275) -,S(7b290c31,de7dcb10,177313f1,9a15d751,c128bb2,16823c5d,69298baf,575657cc,9d3b3707,d8f2b17f,e14b6b1d,80c55d14,b747c3e0,8c79d55a,bb54809f,d96f99e2) -,S(4ce2adcc,18632b7a,560bfc3,beb7138d,8ab210de,6cc7f6cb,47171b45,13e991f7,5aa8204b,689d8f69,a42e08d,5ecd2936,97ba76b2,1bae122c,e9252659,25a874c6) -,S(dd798cc9,97530af7,d7ce96d1,a6a93aba,c29056db,c69eebca,f4649648,4942bcb3,e9ed537e,7b679852,88bab4bf,36ed677c,14db982c,9ce8714,b4f3a32b,56609e49) -,S(356f4414,9da655e7,c9ea5a3a,5c4847a9,f908c608,aa492efb,15e7cb00,8b065b79,2adb4e6a,ce059ee,44ee8962,b4aa8c71,a4d55f31,28f56877,6c70c4c7,19fa6332) -,S(b607a62b,c16ffea9,b30f61d9,c711adb1,d110c6b4,357b1e0b,dc71c8e9,4d06668b,6b933ae0,9ba42b06,96419a90,e6579a33,8f4f3fc7,5134abf,70cef838,efc5270e) -,S(77fec5c9,24fbca2f,f564bdc2,96ebbfdf,d52f0dfb,15011792,57085c0a,8fec498e,6c7729a7,c92a6626,44f33fd3,1ad5142a,b521720,24e31308,dc11f73c,ee29d69) -,S(804dd2d9,8014a95b,7fea2651,195585ac,acab7a46,1f3134ad,f2c4403b,3de98461,66fae33c,458de63b,dd04fce8,1c425938,dc13194c,ac03205a,c278c071,918a4e84) -,S(65866c36,90a6cf74,95ef54a4,f222bf9e,3ea803a8,98eebc19,2214133e,9ad35234,8cecbc5f,4a152864,6350711f,c4df57dd,8a2c44d,4133ec17,c95e00d8,b49c62ee) -,S(eaccdd6f,2a9616ed,d6f8c3dd,bcb04c1d,49f0c4c3,8d8c34fa,d47174f9,2323e15d,15a435eb,e23d23fb,2313b59e,2fe0367b,17b6d9d,e900332a,20430362,19c4591b) -,S(860d382,8ccde42e,b27652d1,c159d9db,57a0b9de,f290b071,e93e36aa,f730c53e,b4688879,ef616c7b,87bd37,641e0381,115dd487,d5fa3e87,99257afd,26906aeb) -,S(fe446d0e,8d174570,49394416,9c332f9c,eb47e70,3f214d83,2777398a,dc8189bd,d4cb299e,760ef11e,a3846dd3,9a49f34,4d5c10bd,ba66dccb,a43e3647,718e598d) -,S(e4e6bb03,528f913b,bc34d910,2a96385e,bd0b8aa9,a07a863f,9d5d41c7,b982a578,46ed6885,471b4806,aca3c265,d0c40535,4bd63da0,af35a89c,e8a86896,63d38690) -,S(12d69042,a5515732,8b729ba4,4fc3bac1,95c419f8,ec71f438,e676d722,4509bc56,80d7fe55,52e88a74,a87d24ea,de1f9e35,de5c45ea,b8a9b48,9e7a0b8,4bcf5d31) -,S(d3ab5380,1f1b1f7,36d94c4f,2af00a81,ee1815ed,83dafdb6,ef5189e4,13a32552,691c4594,657c0809,f7b6335f,fa4fddcf,8af5b729,9262f790,2ef12e34,f546a401) -,S(50bd549c,2da95051,7b4c72c3,67074539,412f3b4c,45ec69cf,aed0fe61,25b50d7b,147f8768,515cb545,2f291d4f,5a627f36,5c88b2b,d19457b0,1fa711fd,9bc71abc) -,S(a36bfbc2,330165f0,728578b9,ec81d14,c0417090,e6ed73ac,e8aff550,2ad9c62a,acb88155,5251f37e,f31aca05,bf33f9af,9ccc57df,58692067,4f11b787,8c7c9337) -,S(2be3d416,ca9627d5,9f259f0,1d52d915,9972f50,c391531d,70a6b79f,735e7413,fc0eaf6c,97d11c6b,cbc2722a,b3e821d5,363b04b8,edf2b700,15ce37f2,f70e51de) -,S(7ca7ca3,393a9884,c94430ad,20731f2b,7629203e,9c892d22,ae6df1a9,fa66aecb,c05c74b4,e2580f6b,9be6efd4,379b7631,26d3e0d6,d4e9925d,1a7f874c,fd620f43) -,S(6805c83e,19aad851,6fd7a4b7,e9bbb82e,28d9d0e7,1f1608f9,dcf37a71,3b434893,2313791b,8fc68b18,444cb309,9cadde98,f4c95ff9,88ddf601,ea3eacb5,bf1c1512) -,S(7540f073,3a358a90,80d2b07b,64e179e6,5de8010,6eed4eec,dc8c879a,87d007ab,998820f3,bac2fc51,48b0823a,d20b5f77,eb7acf5c,fb2e968d,2b98711,a1ef778c) -,S(6eb9b5ac,960407e4,465a0c22,8d98621e,47f169f7,61189aa8,f7de2fe8,79daa64a,6a32f21d,379c38e9,229ed85b,33b4a35b,9999281d,f96ecdc0,18d2482,67d85d54) -,S(e32d3fe0,80d92f46,58331d25,f0f2bbdd,43671885,98cda416,7b4920ff,afd5cae,61a8a2bc,aa82c5d1,1e958a0,fbfae374,138efec6,84ea8e18,af1d13b3,5388d1b4) -,S(22a0ca56,c95c5221,3ca126b,65e5382a,5f14d17c,976da5df,54942495,43415d70,4cfbb8e7,7e3f04c8,69e62ffc,edf23907,e8b17a48,13fc95d3,cf307e2,978e0bc6) -,S(ce3aeaf2,dceb0f4c,50120b90,fc027d7b,b5a4cddd,fc337e05,14298873,e3ff340d,49f2b65c,4a64b462,69e93c2f,ca6cdf14,b0c81982,b095ed3,644805c,cf333021) -,S(75251b27,b360b236,9c0cb297,c5f6ec1b,70f6afbd,5af1acfc,38bd765,9c9dd5bf,cd0559b3,9b18ceef,85c15189,fbd7a93,1ceb3f7f,6cc93d3d,7681f564,17f3f891) -,S(9d69e5b3,32a9ba92,17884f7,e7a1ab91,53a65c43,917c566a,c2969f50,accb9047,9ef330b9,d347c93d,a9441706,a502491d,55d27723,ac1138dc,751308ee,fc6b3a37) -,S(783ccac1,f7d6409f,758849b6,f7c4d5bc,401fe5f5,b08c2f84,1e0e3fc4,fd7a2d47,e5c62a27,65ea5ab8,6aa1aa00,9297d1fe,57248127,a5d3c36b,9665cd93,b6255f83) -,S(dffbb444,8362773f,e45e0272,eeb1a8b8,fefee1b5,59a6bb12,b9613fe,55ef33d4,fd539cf6,aacc930d,2ff104dd,405ae6e,e4a6b3ad,1a9a0038,f4ffb4ba,1a6115c5) -,S(cfc948b3,c14d06fd,c528d299,22305663,d7a427f2,fe08cc2d,942528d,dac8ebe3,81ab799e,5be02ce0,d3aece6f,c6ce84ae,988872fc,ab640d96,c3ea6bbf,3e2e709f) -,S(d9fb08fe,6a7cb6ce,721cca32,74e20732,5933595a,e59aa0d8,811008f5,cee83490,2c7f1287,8b6ad3b5,88cf9483,f08a92ca,ccc18ece,93c68297,4d80ae31,54965938) -,S(4272b558,49ef0ac2,d7830183,bfe3cc45,65ab9d9f,32b9366a,b0477d1,ae93956a,caa07aa5,d117616d,9f442b94,40549bd0,f64e7a2e,3cf96053,bd14faab,196c698b) -,S(69536c0d,6404b026,61598e11,1e6eaa4f,e50a2cfe,879b0f74,4df57727,933367fa,aeed065,2c5325a9,53913334,7e4fc4b0,d2583608,c2086bf6,b2e5ad25,261c6bfd) -,S(199589ed,5c4b6e24,65d58257,2fcfc194,60f7643b,7019c02f,8038d04,70368268,c48567e7,ef7a3507,14d1b479,1a70e7b0,5c1d4351,eabacd9a,1d8d5e80,a5da23c2) -,S(ef3c4f9e,53ed652b,f48feb4d,1c7b711f,5526dfaf,6588007d,1c2ce942,86db1f4,128e416d,570c3eff,d45da6a6,31246fc4,f45b7d2b,8cf85a93,22b5f65b,361fc49) -,S(6bc3a126,11ca8f8,3d0790c9,f5b5b137,4ce51c66,6c553ff6,9d103370,3b3d7cc4,b20988c9,4b882f50,a0ba8194,2f168bc8,f29eb6fc,4c3d0149,571968e4,81b76ab4) -,S(a0100574,5ea131b1,4c180c17,f26bd3c8,1bd48ca6,c2310c4d,34bad277,6bf51aab,177551d,299c9ca9,92de3e9e,f82b115e,6d3cea9c,fb276955,5509795e,4870a546) -,S(15553b6b,defdbee,532599ab,9e0de23,b4954dcc,912f49e8,f084ebb5,af6088e5,8dbaf203,351a1119,16e8aeb2,e5eeaade,b0ee5d9c,2f5020,62b9f5cc,ca40cbf5) -,S(ae84a42d,49dad25f,f0a5320b,d6a33f8d,79c9f2c7,2871f41e,f8b02cc2,c469452a,9b23f07a,234782b1,cfa524b1,ad539ea7,b8fac3cd,e9bfb867,799a2587,95a48ca8) -,S(eecfc7a7,a41f75dd,43e2b85b,5af33ad5,f017e0d4,8f9b9bee,f0cf4499,a3c762d0,65526d26,73b9e5b2,8ec256bc,a524e376,f0e40f62,2db6e492,e1c53820,a3180d11) -,S(35e427f6,d0be7dc1,2d306ecf,be9fd8ff,107a044f,81c38c8c,5b9a181d,f4565440,de09eefd,27a8bb89,d8fc38e8,d32aecb,5c6bdc57,5cdf91ca,2f18e926,dfcca94e) -,S(d27cec9d,11130024,7f71fadd,4ace1139,cbe3168d,174c93d,4c756c42,89cef3da,5747fbf8,c4040895,fded5c00,e1f60403,40e07827,8924ca96,2f83b3f,e50ed701) -,S(df30926a,ca9062bd,7bbef9d9,e312a1cc,49442ebd,9994b93f,dc652e68,25efe5b9,8d1ffe08,de113447,5c3adb77,ee5aa58c,593486f9,c3f27c32,a20df570,6ff5c572) -,S(c2602b7b,56d0eb73,ab494934,5eb77e88,787e54c,79558ea3,dafe3f50,84f96682,45885bf4,65996b12,993efe44,39861b39,84d5fa89,5242ea8,f498695,57391182) -,S(d6d606e6,28c55e08,61a37803,72c17b1,6a2fe04b,e68a0cc7,60fdf7ac,85c8816c,76b299fb,9e716eed,7f09c879,ea8256bc,a953454e,490edabe,c90a2e5,dd277da8) -,S(d1bb671a,10ec5393,9d67f6aa,3b09e1b,57bb6414,e1f707dc,b832ff67,56289c4,47559cac,311f20cd,55760ed6,2e1e87ac,cd8603e4,c1d0cba9,79f6802,6b294a94) -,S(739ab4bd,6b6132f8,2659fcda,5fb46836,7adf2133,37f897fd,70a9552e,786dcb91,b562e798,2bf508ba,1b932deb,3e6b5962,70bba4ca,402db3b4,d806da6e,fbf6670d) -,S(a710cd7b,2aef0005,6d8db954,2abe6cba,2a6c6132,a48a6670,c501fa82,4de21388,4a6037d1,87db5b52,2996bb0e,47fc7509,1ad9eda8,e15faa56,92d56006,e72fb220) -,S(cdbf59c9,b38e40cc,d63b36b8,b6e894a,c6baa22a,93a1382c,9d7fd070,58e69b7a,3e836c78,6954d509,348314df,8ce08f0b,59967aef,4e5f0136,9c6d0f91,2682d77) -,S(1d32e93f,6e5e138e,7d226636,d5e0946b,8117f91b,bd59efb1,560a15bc,657e4dd3,82c43daa,bc1e23d6,3632e167,6bbca422,9797551f,f729cb5d,c8ac1460,46ed20f7) -,S(2730066,cbe72e84,304e3563,a18689a1,c6c8e0b3,e92d8c0,d63a96c7,e3573337,8804d5cc,6aa91f7a,1ae23506,17332f7d,811b8f1f,752fea43,5208b770,94e67c58) -,S(44624ea,a1607e8b,8bcbd736,9c67f86e,6b0f5226,4cc76a3d,b40042cd,bc621cc4,95867a99,d110d9d9,e382d3d8,a5dff78c,d8db012a,972a87ae,ac24bb42,b2747e53) -,S(8ba805d8,864774eb,4494ca5b,f8257bf6,980466f8,30028340,8aafd665,7f1ef49e,1a1164e3,c1b243cc,57507b07,7348495,95cf67c7,b40d4d7f,f10ad096,3f3866b4) -,S(297d0130,25bdd2d3,f4a008d0,d8c51a3c,7b16b605,95958d9e,93e427a8,7ac01267,56361e70,22138026,683b7bf3,1a6bedaa,988d3938,cf8399aa,e0f3175e,61d7e2bc) -,S(d866bb84,23527208,e66f34bc,e26a8ac0,daea9d03,27c9dccd,cdf0e2a,a0588f52,5e16262d,3564736f,30f26e68,1c5ea26a,b6f63429,f0b25dd2,5635a3b3,1fc45584) -,S(ab1e9d8e,b18e016c,d8ec49e4,388636d,5dd2ab55,8b3dbaa2,433a976a,ad8f16a2,a14cbcec,6327451b,15d47fac,d3f3cbbe,fef828c4,6ea07a0a,9c7155cf,2a2f291c) -,S(cf2f035a,ce393efd,3032cb05,4f4e92ae,5311dd04,bf8f3653,5197748d,2094cd30,75b38e90,9f02bb50,7a778243,35a1c97d,75bc653f,c6dcffcf,615bf8c2,ec6b32f5) -,S(a801d552,e63ba120,2c3ff08b,8fb025df,e545ed35,1adf00f,1a08d982,9e8bf9bd,bdb9274d,f5298fab,4cb08f42,252639e4,a24b553e,892cd1ea,93499c47,41c23165) -,S(f7ad7a63,eb2b90aa,3de2a80e,844e5336,287984f0,6075d9f1,26f24108,f4a5869b,d151e7d,9766a81,1db45134,7cc22654,c5ac40f4,a1d82d96,2de02c58,d46cda31) -,S(732541be,26fcc3e8,c824d539,28282611,96717b00,2af01bc8,57f4c0ac,cded0a80,d44adf28,f26370a8,3c9eee24,4e870dab,3fa7a508,bd14a56f,17c9a845,5055f8ca) -,S(892ee5f2,a5266a86,5bf2094,14c31225,b92dffda,7a3ec00c,ee53dc0b,8c3a3367,21bef833,3b983665,7d243b85,c0b4e2cb,6a5b339d,831cfef5,d676c7d8,87a0df00) -,S(1a4597e3,77569fed,70875f9b,f8f5531e,6bd3b363,b96a345f,9275365c,e1e64424,bd142738,fff7b9db,cbff1c,93a968b1,f0ef3e63,8279b745,21aa53a7,6e611f7a) -,S(c7306404,4b4a3a00,6a584193,e915a174,631c8a2e,ac45973,c815a2f4,aee82f35,280adb29,4f9642cc,cbcc4345,28bacdc5,74beb7df,84c06216,68cc2fec,d78731e6) -,S(c06d9d55,264e4ea9,e160fa78,78a7e4fb,1757f6db,fe610966,503ae03,b4723f2e,c0d82600,ae072564,b29373a1,ff1a036a,45f68f22,9d1594ad,1c9584cc,ab732743) -,S(e878c0b2,bf38b500,6c309a51,5121a3c4,5b13440d,74ff6e27,5bfe71d7,51e6926a,4b8be149,11432ff6,c5169731,1c1db30b,c921cc95,b4c98a39,5228c08,b99b6229) -,S(d1f6621f,89ac4421,7ef39a54,a0922c77,dc7addf4,78b15796,2558ae72,9b24f65e,657556fe,e02492c1,97c9c97a,67bf1d6c,eb689415,80a1ce6a,1e4d98d9,64902f3a) -,S(f9199ae3,ae51f441,d88d72d6,9c1ff64a,d5cc4979,b5fd6a23,c514e9b4,66ea0a5a,3c484bb8,8ec31009,eb95b971,69c7ae03,c20dd833,eef53cdf,fdab8cd5,7a82d4eb) -,S(4e059bc7,516d5fe2,510ae63,d3ca9543,f840bff5,710a744d,62de3965,af6a657f,222309ca,242c5858,5a792045,bbfb3e55,b61daa3c,afedd1ee,19a0038b,f929a47) -,S(c1673413,d8b4298f,6ca04741,a3c32d79,83a7d5b3,dd39ada2,53013d3c,9750ac65,333b1660,7b998e8e,fa7e3d32,2d51c052,1de24d3e,9e389f0e,9a00015d,6cc32d54) -,S(c078723d,8abfbc03,63f12766,cf9c6261,9c31173,5f3a9654,b653a8f9,e08f551c,880fa5d0,be09cb8e,4f145749,1c7f54e1,ceef1477,ba7ed718,5f27013e,32deb89) -,S(c77f3351,4b44b047,3835e3ff,abe8d7ac,ae5f912d,aea4e6e0,4ed03feb,78c41ce5,cade531d,26ee668b,5e2fc7ce,421de2f,d9a14dfb,87286c22,c840144e,1290e910) -,S(90e14c45,4ba40739,10f800b2,bcc7b017,ec58660,bdb1e72,16cc6afb,8320277e,61dfb75d,f5f74d47,287f828d,c4ff46d7,fa351a1f,66da99da,40e74758,2c6bd4b2) -,S(34c65f34,23f2474b,7e2f294c,ed4da6b5,c05d19ef,a2b5a792,103b681a,be1a3f68,d0fba1a3,b12d3e4e,f18acdbc,68fc285b,8ef1365,6aa900c8,c86ae191,37f028ee) -,S(fdcc63b0,aa5017ce,215735cc,2802eee6,aa5ef53a,6a258dd7,a128ed7b,9a5df38d,217ea863,5c9b88c7,19c7f9e6,1286844b,d4f4b758,81535954,7b24df0,1fd5bf03) -,S(10624260,58bb9f6,a5e83740,59595ffd,e7013492,4392c753,15853f4d,9c7070f8,84a92509,e809874f,86e60bdf,85c75d7f,2cab596e,185f56d9,262b06e4,e79cf785) -,S(e21f29c6,70cfc7e8,b104921,bb524414,53acdc5f,fd80066,39417966,ca235c9d,41be8bdb,969ddd53,9093dc1,b85dbd4c,a78f7e68,67fa916c,36136d24,b6c4af38) -,S(154a85d8,60b532cc,16bfdcb2,2769fdf3,6dac818e,cd2daeb0,864eee0c,f78a5c5b,15f2dfc9,3e5e08e4,9d340ce4,bb805afd,79f940dc,f97456eb,c73b47ea,5098e429) -,S(ae6f8b12,d52907e8,4ae5063a,114f8e2a,da7be317,454ea505,571f2132,5e4acf42,49376af9,1aea68bd,cdcd637a,909b639c,b7ff8800,ee003fe6,540d6797,f0f296d1) -,S(de42ac26,47fece4e,69341582,7e3c5b7d,a19dbbd6,22da9fa8,58a3be29,8a47bb65,e57cc346,b83b33cb,79a34805,42811d1d,4178805b,a2b88de6,d90b4fe0,ba8e2740) -,S(14c2030a,c65ec50d,2f7c176c,45256587,59cae0d6,55cd57c2,c1ea970a,11d7bd0e,f3d9f0f0,5881801c,ad4df439,3a3bd2df,1a045181,af7ccbe6,7500b02f,61edece) -,S(32fd40e4,7a94e51b,e4c927c1,42b5f470,b2abd2b6,2773934c,a29a5ff3,924b2e8,b3d74958,f17147e5,1da38ded,7cb09c27,96b7e36c,3149d85c,9b7db85,acd89bbd) -,S(fe468154,cef5383,4820fa33,ad85c158,33635cb4,a55870fb,f588fa6,b8d2918c,96650453,25235606,7bcbc214,b0a04021,bc71c9c5,4617b1be,dd34e6cb,dbb42873) -,S(57826e08,8fa3841d,a33ad3da,e5b5a688,1ee770f5,bfe45f5d,507b4801,ccb511d9,6cb01dc4,4da6d83e,77a6e8a6,d374275e,7d8484fb,4863b5f0,34bace60,30e6b3be) -,S(61bf08fb,1d537624,1dca6119,19f0dfcc,7787090a,6747cdff,8757b037,a1ea59ae,6bcc632a,f4f43c6b,547e6ac5,5854268f,1801614e,5bc9d4e6,ea0dcd99,79f7adb1) -,S(f54dac2c,b5521855,9dc274ce,25b77645,6525e91b,c011e657,5ff812e8,d846ea4a,bb9734dd,af492c18,82bd36fb,f365009,bd41b8bf,1378d9c6,a18477b9,ed627f11) -,S(640ebea4,b85cafa0,d5a38ef7,7373bfb1,36b9571e,f9694724,680e92fb,13efe03e,eaf8d756,c70ee813,60dadfd9,702f660b,516fe3a8,4c50043,92bc7c1b,892a43ac) -,S(6c4814d1,e3c6c16c,366c8776,93b6df4e,266b45a4,26fb0d5b,a2d8fef3,a3803975,d9330c82,8fb02d63,33d57990,b6bedffa,ccd143d5,1b5eac78,5c7f058f,af77a37c) -,S(8dca10b5,95293452,7bd2f264,6170b6fd,59d636a1,f2578b6f,cbde0c96,8bb2db30,50da6972,64516689,57d2273e,55dd046f,1c398d1b,9e5e864d,ae6746fb,825ec83b) -,S(1409a8cc,34389c3d,3fd1b482,fefdb25,3ba32070,dc23b7ae,6b8a1ac0,2f00b776,f8f1c0c6,3bef8011,27ffaf53,d5c07c,430566e2,6c4a9591,f92d694f,82d7a9f8) -,S(1c752b3a,2cdb6257,fe8bb102,e7560b8c,6f86e7ca,e809892f,58df3b16,728c0999,9f1341ca,61dd07f8,882596fd,12531577,d09fcb45,5a086b0d,17dd5390,8326c741) -,S(ae8bb1ae,a4341bf4,c18e7d99,7bc3ebb3,d9f13c9f,b01b93f,885cb32f,d0586999,92eaf2f5,c4e231a6,851a2324,a146400e,6b9eaf63,8eca473b,9d4e034a,3d5c8e6b) -,S(e3d2429b,ba45b4c,2d9c9bed,45f384a1,7d74cd28,56c87772,6d9a98fe,67bcef97,729da85f,927c04e2,c1db1458,c133bdef,c454d0d8,88262b1f,418f3420,5df2380c) -,S(858ee23b,e5166c66,b99d48dd,24cb5078,fcad23e4,a8df9f91,53ffcab2,fb8624b,c5088132,3af436fd,c4f63b91,b06061d4,b26fadd4,6bccaf05,bbe1a8b7,338cdbf2) -,S(7c6a82f0,e2d6c5a3,ba37be0e,1bd8d4e1,99f9aa3e,c9c58054,a66099b9,a4938a1e,881916a7,87e1f9eb,b38906c,c101b0e6,5d245fb7,733c0093,9a7f6f0a,9b4d113b) -,S(4c980c4c,144e4060,c00e7476,c782cb83,42ae8b02,6a155904,c29837b9,fc25caf2,fbc05490,a62e49f5,6daac9dd,5c730f90,183ee565,d62ca949,5bc7ce56,61c2e8c1) -,S(c9b66a8f,6c163037,f5bbc7b9,889e9cfc,357ed5f7,a5e5cd17,6a7e4bd9,6da2fa3e,4eb8b3e5,365a6a44,4b277b4e,89b89e04,2b44cbf8,b73f183d,42c9d8b6,547885d3) -,S(f2f8fb3e,2bd3cd82,99e2faaf,bd5809f0,12190658,b1efa389,f58ffe28,c1056fbe,db6c4cac,35f78015,8fed40c4,341a93b5,64af02c0,12d4817c,478726fe,4faf8273) -,S(8556c286,895b9402,283b5d2,f90ec950,f91c4dbd,6c1c8a0d,6b27cb8c,3bc7da8f,f2979daa,81ea79b5,d3ee2718,4aff3805,9bce1bb7,fa36cc53,4d139b83,c176badf) -,S(4d4c2752,5f24a7d3,ec3673b6,a3c8f110,f5bb5c5f,e9675776,3d81620,90579267,43ee95e6,5834075a,83675a88,15babeb9,824d4703,763b5b09,8c3aff78,837b353c) -,S(cc6689e1,d08b243c,a49a7020,b08ce4ad,817193c7,456fbf4a,97fca02d,f1ccf2e6,32f00dd1,1080c238,cc7e8c9c,60a1b7dd,7503417,2ad0464e,1cdb4221,35ea580d) -,S(966525b9,26bb6596,584cbb3,5da78cec,e6709134,700974f2,6cff34a1,23fba535,b5c18347,52894cc5,26336590,d961af5d,2453d9a3,40bd151d,259d8be7,6c5a9e7b) -,S(df7f51dd,b0e6c595,c8f3de9e,eed5da8b,b05e2cf9,a4555001,760888e6,38b11c4d,19759148,2d4f49cc,b69ef50c,a1cbf3a2,49e3958a,aa9af2c7,becbb72b,8d53f8e2) -,S(4ac2754f,93745ef5,61d6d213,7fd2339a,81cfb619,b6699d9d,21897ed,975f6fea,854a0153,17ce38ef,e070da13,c07829f2,1bf50d40,6458109b,5700a3ec,ed6a3c0) -,S(7c062917,2c59c7ef,2d488806,b1131193,b6b6f0e0,221d1ebb,eca1b358,43959694,77f73272,291c1c73,5d79857d,60cc9db6,b6128e86,4613b3dc,92dd970b,d5dba9ff) -,S(c80152f1,e4b7728a,36acf22,158b8215,d8ce0ea7,401274a2,1139dd71,59d81557,dc0c54e9,88d2ee7d,e8a56eab,d358aaaa,4542a45b,a170db58,89d634f1,dae95df5) -,S(9c2352fa,464cd430,31f43578,53feaddf,7d5ee143,c6403ea1,230961b6,377423c6,841277d5,71934bc0,20f71b36,dcba2293,65819fa2,b20c57b3,5774a524,d6fb20d8) -,S(8d7554f5,fcaae19,cbc20c7b,73f22f30,aaeba42c,a22bef77,3d780205,8c8e1d7a,c6bfa4c0,9db5101,d33abd0c,47c4e125,bffab86b,8ed50864,6b6a2b0f,322bf5d2) -,S(1e75acec,28a2ce98,5929479d,e0842826,bd556b56,6961d5db,66c9055f,b1b63635,89cbe475,d2036dbc,9227db67,d62b51e9,ac669a22,76e4e1e9,d0be9b1d,58efca6d) -,S(9fe62187,5e71bed4,7d9f2d79,91e76b41,88b2c8c6,10f20d33,5b38bed2,eee85236,9a3fe290,fbe192f4,8a44177d,4f0d037a,fc6fa8b1,c57032b1,3d5894c8,c426e8cd) -,S(8dc1710f,8869b645,73c361d1,ada3f43f,6f2c175e,b24ec358,6409e978,1687a220,37a4187e,bce1845,9520b60,9317a4b8,f33b371f,1a768ba1,96316f41,373ec87) -,S(71ad2a17,5cf75568,214fbbd1,f177c1a9,9eb75486,c161f1b7,ad47063b,567e8d6a,29d80786,e42d9cd,4c801f96,a7d44eda,5e325acf,3b82e143,2576ff1a,3b334850) -,S(be0eeb11,aaab9c1c,ef7a2004,731e3ca4,435c8a02,548b36b2,db68ea4a,56ad8b7a,cd7ad5,c9b7e867,1a1c7889,95e45cff,bcdfe42a,6222e0c4,1054a0f5,f7bb00f2) -,S(364154a1,3a7d9fa0,b349c6fb,ec36ea43,51cdabfd,8fa79318,88e4ea5d,ee8bf6d4,40b40474,7e8b30a6,a3cdf3ba,f0956fa5,f7f61a2f,89a8cf7e,c2ed7445,504a71ee) -,S(19daf7ab,c9f69a31,8b2cf1c6,69d50532,5bbd7254,c4bc4126,d7b31dcd,e7b558f1,6b740772,606874b6,5b1f819c,c7339ffa,30669d9b,2770506c,e9fb243c,6ee4a925) -,S(5ab3dc00,eb9efd03,ae491844,50fe176b,765c5da7,d95ffe6f,61aa0073,7366c918,2603f1ce,935e3af8,af5e3d1d,d76a3410,200037c,87c17a93,96e11018,260dfa01) -,S(47bc2c3,d7dd83f7,2b2160a2,64640e58,16316d0e,3272abf4,b859dd0f,6c7b27d7,1ceefb1f,23dc61a7,2f663d9c,3cdd6625,441a63f9,f9cae8d5,c4ba88d1,22c0f258) -,S(b220435e,e903f1bf,3b443549,5a01e739,250be2c1,43f08a73,bd7dbfcd,75602ab5,3659abe7,953b817f,fd1c02b6,56da4e54,9df250c0,7c28e9c0,89ba315a,bf25e1dd) -,S(be25604b,d52413fe,2c743031,98aeff78,c27086f8,97fe4b20,be5b6251,52fa2fb4,ebdb5191,aa195ee,a0a39bf7,399bbe03,76073830,fe54cccb,a3194eef,d8d34fe5) -,S(5cedfbfd,633f16f7,8ec8a8f,3dad7cc6,edc1a6bf,3e37cf3,65069731,64aad0e3,70e687a9,d8632ed6,ab188f14,229f2e31,34a3adc8,727c7b0a,d7a16d78,1244c9a9) -,S(8109ca32,a86fa712,690315e2,1bc09265,bb6bae74,588f507,1bedebac,47e54a3a,e7f3342c,6e8a3dd1,f6d02bf7,5610511f,d0cffb40,1c14633d,308c2939,e662cbf2) -,S(54264a0f,dfb894a6,b29b6922,b859d715,77f0359,ef825442,e0d43b79,a0fbfe3e,4884ea59,cb88fb60,4ca4de66,110b7d98,ec529112,d4574cbe,9a2e7a5e,5a4a644d) -,S(f2756955,a6a7db9f,eabaae3c,844cfd37,5d86ad8b,a84dcfba,582bf4a,273f90f3,b24c14a7,d2f60103,a7d3652b,c5e68988,390c0e67,1f0fca22,ed927f6c,96302239) -,S(351da3e,6ab7c98e,840d0dfa,e7231d21,ca21a81b,3638371a,673892d2,e40498b9,e1c5ffeb,43b443ab,d31332bf,aa314fda,5a4c2634,afccfb97,67bceb3f,13ed5f3b) -,S(b5107be0,90f84c7a,e3d89782,c6751b22,f9a7ad2b,3a1810c8,f14bdd8d,52344357,3d5571d2,36a7c9a1,aada0835,9e8ce162,c46a878,5e09265d,bb52b419,144c5b6c) -,S(b6172135,85b2557b,7c253189,9422c428,79825eaf,64d8e8e2,2f7bae12,31c9ceb7,dbfe3609,df9b8e1a,33629219,eb241daf,42d8be2d,b9a20a0d,942f24ce,1a117e3b) -,S(5eeaaf7f,577b445d,13481c9d,a567825c,f0a5a3f2,9ccfbbbf,d8f1f8a5,36e712cf,84a4352d,c40556ff,ab75acd3,b5a63366,39119d8b,f814feb,e55fb3ee,dea5821c) -,S(c1bec874,44b0210a,9a86ca9b,94891d00,e1fee6c7,490aa26a,1af61f97,5dad1c13,14a61af6,d280ea47,433d795,1786351d,f90a9879,7678781a,8d9d8884,e88a06a6) -,S(34787098,f0df9eb5,e4825449,6fd7eb6b,3118dd45,aa0ccea9,f606a794,126b9ad3,85c30ff1,c8dbde4b,88fe9ff8,20c9908a,a35a0c53,c2175524,a5929eea,5566a564) -,S(6599b07b,5d31c19e,ee02e287,ccaa1bce,70890b14,cd739140,6f1d862b,39d794a6,d18396df,27e6fc21,a9c36a1,8d8f73ef,c79e6c56,ecbab9cb,83750220,a816d5ff) -,S(27b50b15,c92c010c,60feb473,5ac6ae0f,9ec0af75,81e41a90,a3a940da,a1a44ee8,31c2c3c8,61e64b7c,df8ca011,bd4002ba,5373ec63,8c3608fd,619bbb92,3552c1b5) -,S(40aed5af,953f3a17,f5d17622,127f16bd,4cc5bbee,33e23443,5f49c4f7,a48e7a32,e47011ee,96c702a1,1eff428d,2940ddab,d17b76cc,6765d5ed,126876ea,2496f6e6) -,S(cb56977d,f69956da,cf40909b,69fe44c1,4a5ad547,a025d684,c9815ff1,b5331ef8,9904de7a,9ce0f656,2f025ffc,79e8b3a4,2e410ad5,8f0caa16,62a13e29,f0b00bd2) -,S(11dc40ff,58c6d2a5,9768a776,41c611a8,2aa651c1,15e9d36c,bd3ebd18,ac7a0df9,4717af95,274f820,28592bc7,4a84e467,9d168dfd,826a292,5789edf4,a06e0e50) -,S(3baee366,3d2033a7,f3170bd0,723eded9,2fad6501,702fa530,b26d0623,8d6992d0,47497025,41900ac2,fb236a26,81ca09db,c34fc84e,98ca289b,63e07d17,2e4671f4) -,S(6b19e8e6,b2010e2b,d461d716,66f691ea,88417df6,773208f5,18ee5fb1,e0fb580,a7c74380,9f744b05,99b6c4e4,709a8b86,241ef931,effd9323,9a6d15f7,22916578) -,S(412a2c52,b31158ab,9d3bf4ac,d4355eab,b7e94e98,6a839681,94a7322c,72bff9f8,c649c493,b19b713c,8b3c4e30,567547ab,472a599e,cc95ea73,d36d373d,c92f7dc1) -,S(b5e0c57b,f79e7364,9826a818,bed1d521,3cb88645,5dc91a4,eb157a8a,dd869c24,752feebe,9614e233,3b876297,175078fe,f9adc63a,4639242,6c88ca94,aa06163c) -,S(f656ab08,9e75bac0,6eaaf373,1cc71347,6a636347,35ab57c0,222589b1,e914160f,d05493f3,52b660e0,4cb00b45,5cede6b1,74337488,dd1650c8,4ddeaeee,b73a6ae9) -,S(bd2465b7,b5af290d,2d1157fa,76e4550c,ddb23922,7d30c255,8f0cc3ad,ae5fa32a,63a28c79,cbb50c21,bcfc85ab,269090ea,d56f6396,1fcc6dfe,b3a000e7,3284880a) -,S(d53c8d24,3dc3600d,fa32dd69,11a87ab,722108e4,192d7cec,4d84eefb,9b32a351,af681092,6afda47a,ef5bc91d,97f273ab,78a21c01,64f59c0c,ed66f7a8,5b67ca24) -,S(4a83ae18,ab379d5e,f6cd2be,77f64abf,8fc23b52,edc88ea4,9efc1bfe,402432c9,e9eef9c2,f595ad74,abf10b85,6ea24ac5,603d46de,c320f9d9,a1453be3,92eef8a6) -,S(d1df4416,dc7cce22,832f9ab0,b74d927b,f9b3b7a5,c52acee5,3d95812f,f26caa82,9e5242f1,163a863a,a5702af3,cdc21f7d,b0143f76,ddba2a2d,d592676c,57c310f) -,S(e6add3b2,583addd7,8299fd2b,14b87155,93dcb13a,3231458d,ab6864ce,87b9c890,384bb2a0,930ecde4,1e9945f6,247a6530,58e26bf6,88226c8f,ee9a1ec7,a1f07740) -,S(7d3f5447,295479f2,96c11443,eb9b1fbd,fe81a258,78ce4195,d2f01290,7e01fe4,d12e4fd7,9f66a45b,2596b066,651d8686,83e62627,95f681a4,12022046,86304ac5) -,S(60636a7,45442fa9,57f21668,7fbdde4e,a6f7f80a,ea2832e,ca3ea43b,d1f12709,395ef963,bec2979c,fb211f8b,da3f4b4f,2c129ce8,26a35367,d955243d,3b40022b) -,S(6bce0837,39c04ba6,b9dbba8c,f668bea9,4d8a8b38,2ac17b87,765bdd52,86e47963,a2d85e2a,7ff5c433,c2c77363,666ddd3f,3fb28f8b,2b7aea1,16a8f42e,384a0a37) -,S(59e4e7e4,438ceba0,cad5f146,bc127c1c,df7f4735,f581a0b2,6a53a366,947d4581,32207f5,95fa4cee,3c8ea269,9578b28b,6290a3c,33eb0ba7,e3bf7267,b2bfa445) -,S(ae2cb18,d4f053ea,3a497162,8c822f6d,72806f79,bd39dcc8,364ea256,f30af032,583d363,b9ac6fd2,709985c5,79603d9,4902da04,1563879d,245433d0,abc54a1) -,S(bc4eb578,630ebde0,f58fb192,377de006,c630e96a,51219379,43e9a240,c30951f7,5224d403,4635eea8,e63b9e87,2875f27a,129de5ff,fae3d516,5f6d0cfb,5bb7e584) -,S(848ca19,6fc34e2c,e484f74d,79565ba6,9685128e,7b2d21fe,8cf0e4b1,edbd3b13,2a41e449,532de110,e0d3fbb2,bb794fb9,32d0d4a6,33aa65f8,ec40e5bd,5c4314ef) -,S(b90e1d09,4257ae30,bd12debe,648d4cea,3f063740,e3f9d3fb,c67eaa4b,8ca0bcfd,5604b475,31b28a6a,e0a13a47,31f6cc70,de91d429,d2204d45,e1423652,5a5a4b43) -,S(430752bc,3e1191f3,6e084f2,5f3e30b,da104f40,1de93267,62dde1cc,39d94c71,e707daaf,841f62f5,6d9c45fd,3304e616,30b6af9c,d6871476,6132e127,40f5ebe0) -,S(ab919243,c8bd75b9,d67f331a,b3b487e0,ee9c97ff,c35de7b7,e29827c1,ab643be2,d4d853b0,3971f1fc,ce365db9,cf4a54f1,5e6059c3,c5138b2e,dd765c51,7bdc0c7d) -,S(adce8be3,2277c2cf,6ee46781,f1da8f30,1cafea51,18322adf,8d6b8a29,fc3f7551,e819a7fe,73311592,bcfda0a7,3609748e,6c039066,feba9e5d,41e125e8,4dd67fb4) -,S(d6ed759d,15f5d47a,146e7fac,423b952a,5eabc238,a0382762,c2a226ed,8c24b601,456caee9,1c212f19,acdc2d82,9eb90cb0,2ac35a72,8d280042,658af65a,b6840e9e) -,S(3583bc8f,c3ca09c6,6f2f4fe2,83da5c47,f0ebcccb,fe8e94ab,fd315173,fd3fb2be,ed60aa95,504e9b31,81225d0c,a4f513c6,6da2a2ce,9fa9afaa,c12e04c4,f1d50b59) -,S(223879b3,b9e50b46,7bceda29,905d09be,1acb206,5b23a61c,686d6f39,bf0744d4,a8326789,ddb38afb,e993ae33,6cb1c3f7,92addfad,e47663fa,52a296a3,b6f2873f) -,S(29329ca6,c6ce20b5,81a90873,7206d44a,95ff382f,1ca0cafb,755a3450,83883d69,5d2aa87f,59e13a0a,8ca4460a,4db7f496,1c118ab9,b4f783e1,305bf43,ed44fe71) -,S(e1c6a08c,593454a4,aa116edf,13345cdf,6dc00b1d,b63b7a64,fdea70bf,e4301ea,e0f9f3ff,5e7e395c,42b3e093,87b8363d,37092335,31c317d8,1b61f20d,f06fa662) -,S(da098bf4,133f656d,f2a09d95,c437eaed,fadb4c9,8102d164,b355c7c9,38e65216,74ffa0cb,1fe7f0af,8a1a6ed0,531f8e98,28be1110,90b580dc,5ff55fe7,b75d9b66) -,S(f3f7c27d,54b40dec,5b3da04,b2cd222e,1507aa70,bd236bd4,2d6e5c95,c71bbe7c,80e17f04,7cb2203c,cc58c364,d77e9a1c,8abb092c,18a9f8d5,6edcdaf6,1ae4062e) -,S(466b6e28,8981fbcc,92c4ec3a,a54eae4e,2e266041,5b242aa5,523579b5,b1fe93cd,9ae0e0c7,d056b2a6,831f540c,67a97732,33bedbd5,bdcd2904,2a8987cf,1fe2a86f) -,S(e15af336,8c59576c,a36b5f80,d9ec0458,d9534bf2,6650cc26,a2079946,ac43fcce,7fe0423,e6ea121b,308d167b,ada98cc2,fb8cd772,f95c3d84,c1907f09,66e5b46c) -,S(c20ab235,6dfe247,d8fd1a9c,d8c4f16d,a5322bff,692efe70,f256521d,1b990492,3c0aae11,e4cf9a17,57feb324,e1a2f0e,48d5978c,6007429d,ab32b2f4,d1a19bd6) -,S(d8b6c190,4a848755,f126651c,d96fe374,7c5a3744,1fb7048f,e15c4693,dbe35e17,fefb5310,e7e38891,70fca6ec,61ffd2d3,72605ed3,4bd22d73,c852a92c,c22fd30f) -,S(a8256823,5416b18,a01d2df0,f47757d0,f42c26e3,780ae6ca,2421aef3,83361f8f,c9192412,77948b80,87d1c45c,a95224ae,5f9c294d,fa74c1ec,42ad6004,f8646540) -,S(28f2a237,c4dcad5b,a6bb5274,1e743020,e90bc598,8ee66b39,cd672ed2,ccac6c33,416c59f6,c1b1b036,f38a5523,722954eb,52848872,8ecfac4b,5bfea63d,cfc181db) -,S(e65d92b7,571bbea5,4e541862,a4dc7890,bd546782,bca886e8,3c1ea17f,33d77e9f,6116ed43,13def2ae,6b0f2b92,ff07c91f,4139982c,12511152,fd7ed5fd,851bd04e) -,S(68adb9ee,c7ae0198,726b0457,91fe52b4,b5c2ec78,4199da86,bceac230,d55914b5,41ff0808,e42aae9f,e93ff704,6f08fb38,4b72d7ec,7b1dc6cc,e0071306,7ee5cfd5) -,S(3f0f7d6e,6bf73a97,40eb842a,35cd4800,85db4766,f7fc374e,1ac915c0,e4d6d6e2,392aecf6,8b446346,2d37a106,8299a09d,9ceeeaa4,f0ee3397,dc54b2f3,5e3332d6) -,S(929aa2ad,48a1f3a0,24fbf7ea,70e9d57b,9ef65afc,b3cb2d8c,5041a933,321359e4,b1cfddf3,4693ff40,ef16d8f1,8fd1fec,a71252cf,ee13ba4a,16094c20,3b4fbf66) -,S(9a9ff691,f16ad46a,d0b753a6,fb09025b,e196b443,839114a9,580eb2e7,fc494e2a,3776f83b,92c135f2,5e5e600,27f65e2d,582fa2cb,f5842c3f,644fb726,1e305c67) -,S(6752b226,65900d81,47ea6b73,25b212a2,9bcf899,799eb1e6,213857dc,6959d32e,fafdac9c,2f791be2,d1cfa78b,7530859d,c1b2ff43,e546de14,1f42baef,3d6d1371) -,S(9fc32749,e636e845,aebfede1,1d0928a1,8cc6e3b4,5a2536a9,fae0a2b,ddca6434,9021fa85,56c5fe05,cc87bdd3,6cebb00b,3d1b77e1,80ce2f8a,a4d155ee,84fc6441) -,S(60ca338f,ff905b58,b1d70d5f,89c4cebe,15600495,698b262b,e1550da,a0054a99,6d57de6b,f7c637ac,4d728090,9960ce01,4b541abe,754b82c,bfc87ad1,5fbe6ede) -,S(91537a09,697d3658,b06b853,d07153da,6d0228f0,786f334,db6151c,64becb87,231a2595,e04dadb4,b3900188,9f34b43d,5cd3c81c,f13fc6df,d432a377,4f53015) -,S(93a85356,195e109d,ddf054d1,2a901d83,b10db692,fc17e878,849eecfa,5d387fff,58f2112c,3df38b46,51e347fa,5aa8569a,48d95b2,670c76ba,d0de339a,72ee87e4) -,S(d5d1f0ac,bc2ed1f,50490030,43fd020d,7a1afb27,cdf78318,6a043bef,b0708eec,c473908d,4d754fe2,a5fdea86,62a6ad21,b711560d,77ad85d4,e3b47175,b5133e52) -,S(afe283d3,8cbb257c,5f2c0dde,2fd1bd56,2ad33e5e,605c24be,51a255ec,5725b1bf,a050f64e,978a9ee6,36885656,5cf22d7c,2fb45e64,6df60abf,6d3f9e1,132311a7) -,S(179667a1,72e0c37f,33e835d9,b5b6f326,3d963f37,1dd07d40,e790e0a1,21765180,da24290e,e38be6aa,ea2e86e6,bf683d4d,90f5fb79,20257b78,aee8be4d,fa65eea1) -,S(9add8ed2,6feeca4c,d3e583f0,88398ecc,f245d30,a888e135,b86ac1a7,e4e42d05,41bcd07c,c2e6acef,bc488d74,8a338c9a,7e6d3e43,85029f75,63dcde83,54d82232) -,S(25ba1237,6bb6e146,5195db78,29f51889,869dc972,fc9805d3,f6dfabb8,bce6b,a39dfc2d,223f924,47ae617d,537a4877,e6a47e0a,7e5fdbca,e1bfc956,a9c42571) -,S(dbd78620,c9a75ddf,55d0a41f,7312ec44,d3108f34,e7d75195,d3d49f99,88e2f986,c184bf06,ef304b72,1637bd3a,d511dc92,297dd5f5,9bd8d053,a048702a,fdbc400f) -,S(f8d67c64,b71d14af,b07d734f,675913cb,7a1bebc1,6e4a4916,44f8f4f4,6eb69448,eda6023e,5df40a5c,89a7bd26,94767a5,f17042ad,f95fb4f2,88bf9fdd,b91b280f) -,S(fd5f3228,56c096d3,4683a672,64ca5d76,58a8b7bd,41c3c1f2,5de2e6b3,164c8fd7,8372223f,3fab4f89,f6604b16,dd66db85,b8a27eaf,30741bd3,7a90d34f,f19c154a) -,S(ea49d0e1,b07948b8,b122d52f,8e8be6c6,e470262e,1c239b40,483a6076,c005136,b81ee77d,3d8489ab,42a9978,48a2ba17,273517fa,604a2abd,f2e1e726,d71b7e19) -,S(bab8ce82,c1210a99,ce17a5cf,3636baa5,52cc793f,89fd25bc,b6f078c3,92149bc8,afe2bb15,d00cf460,953a7c1c,8e466556,136ebd4e,ebf61a76,e49726f1,e3aa8e73) -,S(98802d2e,225bcdc7,9e02e746,891cdf12,ac434154,c08c2e78,589dd9f4,27277e1e,1eeb6b5c,4fc6459f,28e3fc49,6d9a6baa,fc66ede0,85d4b0d7,4af45840,78987514) -,S(5dc54290,2b33fd65,7d37a22c,c669ff21,75825cad,b34e1ee4,7aecf7f5,2dfd750a,41fb96de,60564df7,6c8ec857,d7f0ceda,2b330fda,2195a70f,5f64f973,ec0144d6) -,S(c4894f07,f6679f4e,13369495,dd501aca,73666303,2f7bab6c,fb81d7a9,1495834e,31b7e5c0,35e81c22,89de373f,85d648dd,892021e7,1d120742,e4ac6af2,44a25a8d) -,S(f7c9950c,d5c5afda,ede613bb,8f21ca15,b0e92487,81e16378,c7f2cba,5efd7beb,1746037c,b9211262,f0867180,16f0fed1,75debbb9,5eca39df,ed757c02,aa282d24) -,S(96703c67,4e7e2859,f274e7f8,d458f7a2,89ac0bc4,961ef3bb,b120a1e1,b82b5a55,1f92a15e,5e8b476a,a165823e,59da387f,2f9ab551,4703010c,c35b787d,c7d8ddf) -,S(4e8fa83b,bf9307a7,8b997e49,68227e86,a0402f0,643f98bc,5d13837b,63d08156,81f1f92,bb2a9ca8,14cd212a,6de7ebe9,7a04ed97,4de89e5f,cd8749ba,6e49e4ea) -,S(bc239122,b0cb1f43,2ed0c2ec,bb3c5391,b7eebafc,c4190fc5,8f62d313,7f58c1bd,5b3cd401,d9cf971a,6b9f70a4,b6f8fab2,d0026a24,cceaea2,a86aef0e,a76a3cfa) -,S(90b7138d,5d2e11b2,86d29b78,521aa9d7,205351f0,1451e134,8a593b78,fe5f1778,77cdd3f5,829af7d9,937ac98f,58a78b99,b54fe9d7,593415f2,18dde880,b5039a37) -,S(631d0fd3,27bca9a6,aec8eff9,54fdde7b,df43edb7,b1f602fd,a32c387,825841e7,d6e8af71,273702a3,a2a767af,3c438f0,b07ab614,2fd0f67d,74a9d358,74e29100) -,S(ac2a0153,d810371c,6a7bc097,ed09be67,14ae9935,4a9910ad,7ee77ab9,6d54cdee,39707795,a4f01640,87b5e149,2ec8fc1e,be11d8f7,c43555ac,6f4674fb,8ac5b0b0) -,S(89751ec3,c1aeb288,1953d3d3,f2f634ee,29b1aa18,c55b8b62,59d5cadc,852ac99e,8b4d51e7,e2f94c0e,ef80e16d,9b62c935,2ac91394,902537f1,e93744c9,72f22a3) -,S(849a6cfe,5e3ab81,2e21f491,4c6ec76b,5233d405,7ffd487d,bb0b5091,2ac499d2,a490b967,b5fcea21,d0135ec3,c9ed5efe,ecf7ac6c,81e06648,66cdca60,a1be7037) -,S(4ffa897e,17d760e,41859b6f,3bfc421c,55fa1e31,eb999f72,5028be41,cc8a9ed,87b4b5ab,d9875b94,aebe632c,64ea441c,71ec7353,5ae2c83b,d9b904e3,7f7fd326) -,S(4fda56c3,8bae34b6,55b2ed2b,621e5074,7ed1dc13,a1a815f3,be12a223,d54c43c6,6cfaa7b3,c53a1dfd,a03dc7eb,6086b84f,ac280c55,7c357d16,fa5938cb,c149bb10) -,S(b572c9c7,9ecd2ee3,154c56a5,9c81444c,b16df1f7,82198eb7,40a78c7a,e5c7e99,a1fb603e,42d3ac6a,5ef5dd74,ced31624,fed9086,5b02b3c9,2bbad21a,ffb1b79a) -,S(a77038c8,e79abb7e,a94b4e17,35f0f5fd,a07b1ad3,367047f4,895a5104,dfeaa623,e9bef9db,e8e2078b,346aee0e,efd64657,2210e451,ed2e8d63,b92be059,c577e1ea) -,S(3158f3e1,14de5071,c6e2bff9,32f1c269,7e374dbb,786e960b,7e59df03,26e2e1c9,1d0e950a,9124a626,4553d29,3e5cb8cd,9dd05d45,f48de2ba,f60fcee0,ca42a9cd) -,S(b0825b69,373aad7b,53c256c3,1258169f,2736d47b,1c4aa22d,a052b864,375a807c,23ec01bf,a857fa0,1f3d46f8,7857b211,f7533c9d,611dfdf7,951d190a,d7ef07db) -,S(9578e6e2,1a738f66,ca04647c,ec610da1,afc5602b,1e72e096,bd192ed,f19c205c,fb5da982,7208b4e6,11e6dc5d,dd8b8ba3,569a578f,275e6d21,3417fd37,7e4e6cae) -,S(a0aa979a,5448d27b,e42c39e2,2fcdf40e,d3b64c74,42b2c40e,2f6d38ff,fabb196d,7a9bf938,937be244,38aa212,d9342f98,ab9a35dc,1361fe56,5d04a25f,176eaff9) -,S(f535145c,d57aca97,f4cef68b,ce57d5fb,62ccd1ea,b48dfeb1,3b87b188,4614be82,1323e73b,dcd6b16f,bc481294,198d8235,b98a1885,a336f07d,593e5df3,a21ccc11) -,S(587d9e30,2f9d60ed,eeae03ca,252cd2fb,117bd07,fc91163d,a7cc569d,1b023f9f,7bcd5b42,3c01038c,9d3f7f71,ef52b4ef,a99e4be1,6de4314a,5e517e8a,950f45d5) -,S(b1e3b70,aa8a0cab,ec119ca0,5430396,ed98d9f9,e3e1a650,94cbd985,4cbd0932,3c9496c8,eec7dd92,9718f7a2,8c7a67b5,c4e55d88,5a943cc0,deefbd11,fa4f8de2) -,S(8f7001e2,928200d3,a478ba12,424be4c8,de8f16f2,a932e000,1468d9a0,48d57816,bedb10ab,72eacf26,1ab17a34,e5138686,34995952,545129b5,5bd6c7cd,84b50bc3) -,S(c95bae04,e1c397e1,498822f7,b7910019,922e43de,83119ae4,8517aa9b,aad6f35,8fff7d3c,d8bd7af6,c8523375,84f73aa,2f1b03c6,585c7987,98fe29aa,36620486) -,S(228fba21,ffe5ff9c,e04017e2,7cf04c71,1cc454d4,534d3404,49bbd1c9,60d2230d,825fb4a9,169ab67f,50963731,10f27fc3,f6f7acbc,9f2918f,c6f0bfa8,a92ed32e) -,S(89610875,bb7c5f53,87929e38,22249817,ade80ed2,a69dec5a,eee31a48,6c40e316,f7d5f522,92a53c2a,447f9b6a,5c06b3f,22fcf19e,4a200ef0,9167c255,a373ef47) -,S(9f0542f8,8e7e2b4b,c20b7b5b,87f051af,6650f605,67dca77b,7b6e1ccb,2a63f6e8,2b80c840,5e343203,d0a7d1cc,ccc99736,4bfa10d0,6e71880d,a0955cc0,b1ff98a2) -,S(859b6ce5,b7075222,549b59bd,3de967b2,1655d163,c57e94e5,6c9fae12,e5222061,25b8cf47,baba2000,19036027,fc86f03a,1c4c406c,4a8b2c34,398b7191,bf125aa6) -,S(e6febd1c,91e66c5d,afc7caaf,4150a023,b70c57fe,2a14f84b,c9fabce7,34982ddd,b606e3cc,f997b627,a0a02c4c,e147e0ef,58e3e275,a43940a3,4ac74760,457ae5e5) -,S(956912,ea1f5ce3,52d39e67,a41e4ec5,8c7106e0,4552e1a0,48e4b195,6cff8c01,b1eb2fe7,7419c11f,f7e34dfd,a752064,39fa2e6f,b9f9d34f,70740950,cee3cf40) -,S(1bca39eb,9b6a5d5,3575e510,6955143d,a6fe9d67,999500,ea78cb89,d832ddba,47afc8c9,358e5f7f,e92370d1,44ecac99,4e69afbf,6ef1af7a,32adefb7,9331173f) -,S(2c6db85b,c4d84c2e,61f0b5c6,2f330e7e,dd672c63,a14fa534,9e4d1488,ad462c5c,bb488565,cb2da5c9,be8a6f6,c71555bd,d85b4a53,20ca0753,f524f91e,ca1e331d) -,S(f66c0d73,36bc153c,5f85e297,52845255,8957a08b,603e4d3c,746e0c19,572c9f82,74e32022,faa58df3,1e4a02b6,f00ce5e7,bf34ec93,d8095144,a1af69f9,c637f01a) -,S(774959ef,cf8c126a,67012f8,10217d39,298040ad,da97e973,9fe13f9,927f6757,c33b9f7d,b2901f8f,171151c5,dd8b890b,62c0a1c1,9b7d4691,9c23ed00,cdafdc24) -,S(f59361a5,74b69786,f7ea4abe,44eef2f4,5000328d,dd72c2d5,a6dce9b8,63037ca6,34deb360,ece45bb0,a2417618,e7c67adb,24b33620,80d464af,a1ef20ae,35da05b) -,S(add233d,31c179da,bb62567d,2a5bc5d7,9afc5c50,93dc8196,9767ccf3,8790a5a0,b9ecd675,13d81a64,8ca5ab2f,4d580d3f,7f7d4def,909f2759,af61e497,b6d8f82e) -,S(3d204b0d,1d705714,7e947150,52a531bd,b6749743,5c94c7f4,8f821579,170fa257,ae20862b,cd86c6d8,e8344911,cfa8914d,f40e3a80,b762fd54,e2b7f704,4de86017) -,S(22be58e5,1c5ce0e2,f1ee6f5e,523a2f55,e110c4b7,bd3135d2,39d7a25a,94bc13f4,56894dfd,6c2cb7c8,5689cf04,3c1d4221,a7dfdfd0,d05b1e68,cc41afb6,6a472a04) -,S(6e015fb9,af8ec2d3,9f101509,f8f1fc9c,d95dcf57,82621ead,4651a062,c8487687,c7dc43db,d1d068da,9cb751fe,51251bf8,7f6edbc0,bb19925a,bc02cf6d,d7cf8554) -,S(3baa1e60,42844786,fb720758,67ec526c,2e0f7fab,ac8e0eca,24eff876,47720c2b,909d202a,b40037e,9afe2ef4,d8638491,d27a1d24,98e497a0,908a52c1,52b1f8da) -,S(689cad9b,2cde514,b9c25275,d6a3e68a,ce0b2216,4418a403,a83d88a2,4dc4d25f,53e7be29,165632b1,d1887aab,94c525f7,86166f32,56b44e70,295dd0d8,bb9f22f0) -,S(c1cc4802,101d0251,76875033,ed9fcc07,a66a57a7,71ca1374,63d7c7b,655fdb6b,ffa73601,5dc4ccf6,8afc41e8,e254501,93eb75a1,60a98c,6c800d0c,f10edc5a) -,S(888e34,86eef22e,2a25aaec,9bc9b84d,fec14fa4,c98e9d57,4fb9e08f,5b0f76a2,d2e3ec7c,db9286b4,b0223762,234d771f,a5b6f378,b6a4bbb3,c94c3303,af49b4f3) -,S(ab355f17,a43d24dc,330a9195,c2be2ed5,6894a9d,e38d3dd1,1a31f9d9,9ca88a93,7f8f8748,c07cfbd9,fce0ac7c,b624f2d0,f83bc49a,53276b00,7ca2b821,51988e6e) -,S(12a65c28,aa2020c6,5f56d916,c1cd111,10f68f0c,2408863e,635e05f0,1dbe4141,48bbab23,1be95484,7a0b61d3,89913ff4,5a8b97bc,384a0780,294d97d3,9c9b9be2) -,S(9d96107c,591d95b,42854234,1371290b,370640d4,2dca9fb,5f5397db,84a5577e,183fa1b1,cda4719e,869c8b44,e97cf214,3ab14e5d,e5d0d781,78e5d68a,923b3dc4) -,S(7ad05c26,aa642731,9eded7a,43f72faa,d344ef4,d413d884,67bea154,4459ad55,cbd8ea0,7fcbda54,813f990b,a6eb8450,6faa12d1,cd478a9b,cc278a32,511ba8f9) -,S(d1ddaa71,27959090,65ea358f,b887e4b0,894028bd,457d217,f1ef6b9d,143a2292,e040cd3,d5f19cc0,456a55a3,88ccb81f,787eae9e,51a289cd,d8ae8d25,881e6ed2) -,S(ec3bc5da,a9be90e5,1af0c1a2,bf41adfa,8023bb4f,b40e65d1,c65a0e82,6bdc30a6,d4962737,f9df1f4,48df1d9c,d8f7a140,233c2175,5d8ef5c6,f292b230,9ce263cf) -,S(f3135904,dc55f515,806dbecf,d51b8106,f13dd1d3,43f78e05,91de1f94,86fd193f,c5bd3002,24934faa,2f9ec634,53fcb3a8,20af608e,efbeb963,23871faf,a7dc2246) -,S(fb5f135f,b2f7638f,36bc332e,1bbd2050,335c141a,49db5452,619f266f,df85e8f9,6e71e045,827c3ef1,b75bffd2,ce54361,1e627cca,c94c8d3c,9b8fff62,e10b7b6) -,S(d1dc12ca,62a1285,e3c16125,f71a1b7,7b0dfa9d,c1068ba,2bb56bf3,98864620,6a6bda82,232af467,afaecb2d,f4a7ca53,3c41d63,d8f7093b,f04a2964,6e4f19e0) -,S(52354730,2d24cb39,f9117e35,d9374ea8,f3b6d027,cfcc23b7,58f0bc1d,b4f2d94,83719f2a,ccc79c43,1d8ea584,c78dd5f8,daded80a,fc3341f2,5789181b,7671d586) -,S(fd8247d,d208839f,93eebd97,f6068ae8,a6640a46,48c16b65,6bc992b8,4ccfc5e6,dd560b93,9b530bf9,a8bfd5f9,614f498a,49e54061,61107517,e9ab0104,54e42f3f) -,S(da5d83a1,9254990a,c14af844,df04bcb9,accab655,5468d08f,3b5d93b8,425f1600,9e5a8786,6be51fe3,54bc2412,6315f8de,1f0113cb,ae78b72f,cc70572c,d978fba6) -,S(1205f8ce,b9c89dce,13cd44f4,9ef0b2e8,14b78639,372d9f61,f0543f54,bdef2944,6c820a46,afd1dd98,499636d6,afc34ae8,218a8c90,2f210dbe,530a9211,a058768a) -,S(7d94e0f3,3969c5c8,164739ff,11aa05e0,45b32702,333d947f,8a0cbb80,57dd3c71,7b92b367,33f92723,17948d9c,a1875303,865fd47c,ecab145d,9ac9d4c9,864d62bb) -,S(d7f22ab5,6840dd87,d939c4ae,3bbe5a67,75e7a2c6,dc969a96,40c7f65a,9c18b2d8,bfc60718,2509244,b0ab951b,f4032852,54b73d5,a23a19a0,b4ccff25,1e5dbd6a) -,S(cee33146,2accf4fa,5f06b598,cc36aa06,342c83d7,eb4b6aff,90b9555b,fee0fe61,97583a48,5c323459,ef4b3f02,bf63f9bc,315cdf91,6163b389,c6a48cf7,4127da34) -,S(1e1d2d64,1ec550e1,1a29bc03,cf7c8442,ca13f10a,182783c0,d4ee9bf0,8c3c8a18,1ca8ff62,fadef98a,4d1faa0d,28e75e5f,117cd890,2934e457,e042b870,d8cff1bb) -,S(f10b2e75,8246bf49,1b70ff95,a385e701,dbbf333a,95a94652,6df7cb7a,4b4cb68f,ad15b5a4,d39d6458,55e57a65,3872d9d7,5f4b3168,182bdee0,a6289f68,aa7f99af) -,S(4674dd8f,16ba5557,c9ef32a0,2b6be805,e864e7af,c4fecb8f,666cf396,f7e6b0a7,c9d95120,73388bfd,45f702ac,8851b5b7,531edbe2,df04d855,7bd58b3a,c889f48a) -,S(95bb741,da472f82,8ff1f98,970c2bc9,1dcaa4ff,2cd4c0eb,195978b3,242c66f5,1e097cf6,d47dbdfa,8c3f2ce,90e0ccde,5adbd581,9a6e135,957ce258,805a4130) -,S(9a892056,42e03fae,b24d8fe0,f94e4f6f,d0c72581,604a65a0,99e3d28b,b103d2dd,c6bee4e0,d94c30de,b99c1a21,5d28d7cf,930e89a0,7865ea1c,87d39f5e,1522b33a) -,S(ade39c3b,e9540095,2176bb09,20541076,dac8e68a,a20903b1,5048e5db,4b0539a4,6bec56bd,60596cb5,7ea8a355,a6a6a4bc,90871c81,de902b0,6abd45d2,5802b204) -,S(45f808f8,bab4b4e1,a790240a,f036516f,bf0a8eaa,dd4dede1,eb88bbb0,7d248b8b,3f3bc72f,bced768d,bb90ddef,5b1baa9d,aba634f,1fe19842,c3b4b456,8957794a) -,S(ac9aa903,845a3081,2ddb195d,d79ffb6b,6e8ef0e,d34d0a5,49b577ca,35a116be,368ddbfd,1c5a2fa,c2c183af,19097414,82b272d0,52cec4b1,745fba6b,4a9fba89) -,S(ba26fbbc,ffa6b9f3,584f18ca,255da089,f561c30f,29a378e2,9f76de9e,b756f6b6,55f67b11,81ff78c4,c4c86e7c,931e314f,dffb392,306a7145,5efe875b,fbe39ba3) -,S(d4b1a902,1ebed925,9d53f2e,d76b03d,25b4241e,d5f932d3,a54c4dd5,db3f0423,6f1dda69,9e60053f,d9d2f5c2,c2ed2ae8,ba3337a9,b669ba05,3e48d974,f73c2d93) -,S(bc91d139,b2de4778,458ca891,fa97e413,d4cf32b1,753cfe0e,540726c4,648b451e,b56454c3,4f568840,6d198248,19ba350e,aa291f16,5676d7c9,fbd2d592,169c76e7) -,S(cd7a85ca,a0f408b,26b29306,3e01dee4,acaa8f9b,36f7273f,378290f,a4435450,1d9508b,1e7f5bc7,ba8fe5d4,f44e8c57,2bff9a98,887c3ef5,2fba3057,f132c5c5) -,S(497f8e85,57880856,32edbfec,b0065ac8,3267fc31,da9100ce,c2b99cba,1e7c26f6,e6729428,fabdec3,2db731bb,f33cf45e,5001b890,8f82c0fe,f7cac291,f89c6a46) -,S(68a607,4065c372,a95e7a6d,fc742e32,e59cc4b,86f9127f,f9465474,a466e30d,58e59131,1cfff974,e9e9162e,e974de92,904ffaf6,ffb97f49,d9dbb1ca,bfd927e) -,S(79d2dba1,67b93ef8,82ca60ef,b803e1a6,eadb4406,7f9dbf6b,d45c1a72,23da19b2,a59f1b7d,9ca146bf,93b89f2e,244dbf00,31511075,4dc03050,aabf0d20,41230ad0) -,S(5a2802ac,f4b92bf8,1c98c431,28ebe1f9,c921c211,910b6648,6391ca0e,4c6ad50c,5a0d7b4d,49b5835,dc3b395c,83031571,f7c361dd,840b41d0,405db351,14d86eaf) -,S(87b8a84b,1fd98b53,e9eede06,74555c7d,806d5b7f,4cfced4,16203280,18c398d5,a38c4d7d,549bd5d,28fa39e9,805e81bb,975cd137,64aa8c7c,a7055d63,bdec52f2) -,S(f7ca4d9e,7ac11395,70db6a06,c7f00833,5982181a,6642846,5d0899bd,907a9223,2c3dcce1,2ee6a995,52a72eee,e0968552,919502,5d4962c5,a33035d4,501badda) -,S(15bf39e1,5a11ff6d,216c0f7f,f1597f7e,ceeeda34,91b450f5,3b3407cc,bf7ced7d,325462a,6591d018,e495c6f3,fedb3abd,75d5a4f,15e9ab99,e43418cc,4aef1ecc) -,S(2755adc5,e69db19d,7caf52ee,117c6907,5b342e73,4af64a4c,77b369d4,269897b0,199bbefa,7e0b1c10,bd78ead,d5e65a6c,e6b3ee49,1400b9ad,a7874bcc,be580d5) -,S(96ef0e89,80602225,1d8bb9e8,693f3a67,5152cc9c,43c4e953,5310b9f2,c4338d8c,2414e799,14b2d6e2,a9be60ed,52508d6c,15765c0a,7fc1746,8820fb99,a9feed56) -,S(c1642d67,339fa6dc,c553233f,116f8086,2edbfc24,5512c2bd,4ca6e348,712bfb19,65e9a14,c7356a36,625022cf,873161b8,ef43ce38,a99586cb,9b5c8189,f3c6b8dc) -,S(54c536b3,cb6da9b7,e4483ce5,d5c9e660,bf973ef2,f4c8b095,f52dfbed,ffdfb96e,777f16c3,b026b75a,c9863f38,d015f04d,e1067f2a,a9cbd15f,9ee27475,ad46a4b7) -,S(706041aa,63dee9bd,4a441238,bd343bef,14e69929,f6e007e,181ae87a,68362926,36e15a44,57b86f4d,9b233dd3,37fab91f,67e4c811,3340463f,8f443b50,5a0ba014) -,S(49acc336,116c91af,6f90a6a2,d69b9d3d,c0be0a16,afb9830c,c1af0b5e,749b2765,bc4f0f6c,725e037e,3a9d9be6,c5d4f80d,67b3e28b,92e5d3a8,fbc8f66d,9ba97d52) -,S(96bee384,ff79ed86,a9d816cf,32f3d569,d1ae03d2,d154c65e,a117707d,74c818b1,848e45ec,27eaad75,5328d84c,a76a7235,ef4f492f,5be115a,a622171b,51dbac8e) -,S(3b2b0810,c4052498,189affe0,4c7ebce7,b9050aa4,6a702d0f,72c5c770,4ca4d1ec,f782ad72,1bec3b8d,b1df97d4,7765434f,e4145c81,27acece3,9dbba604,4df2543f) -,S(54c3547d,e4873721,df6215fb,ef7bcb4b,b9acce42,7b0381cf,2de151f7,c69549f0,5e7ce1b,728a3b21,e94b4138,bcb89af,f4778dba,fd21aa42,16d83a7c,9ae81edf) -,S(9f1c53de,e7b895d5,6081585a,c6eb3821,d89bfa61,55cc96d2,e8b6c472,edf57f27,38369e41,ecbdb4ac,619aa7da,4d708eaf,4c572ed7,f1f2c079,d0bd17d5,3ba8288f) -,S(e79f75e,a1a224c2,a0533936,65a5f705,15eb0aed,b924dfbb,5aa30055,d1d82b44,30c65139,f6a6f5ee,5304334b,1ce9dd15,27ba6031,2ff2697b,8eebbdab,67105171) -,S(7f95a1da,79cf25cd,a904b7f3,11674d02,fc6dbf34,ae8ba7e0,b179b48a,d942821a,3d3dd8bb,31cbafd3,247ddceb,be1faeb3,b00e057f,7e90bd1a,78f89cdf,648f7c8e) -,S(41e83f7b,9067a7c3,bb6ec755,ab7c83a4,dff74c93,65d0259c,cb635bea,718a416a,a54a4b56,5286b26b,d0bec338,2053c349,2de80062,2189e2ef,ed10e3c3,9457a34e) -,S(81599046,453d0a96,2c5f3b47,fee7f827,537c7c58,c5ad068e,e5e6ae6f,7a9c6848,4a83b015,3abd0df4,177ef3f7,e8a7ac7a,e8e5afb9,a2fd359a,c30c13ee,321f943e) -,S(11c9aa76,2cc334f0,a3274f15,17a1e60f,2f0eedfa,d603f83a,120162bb,e87830d0,7c73d374,26f648fe,4a9978c6,a64ac787,f4c8d79f,b58b0f58,70e373e4,d317136a) -,S(2b41f344,b285a31a,ebf4f4fd,f0c4f463,49fcc794,e5762e04,dc39efc7,936735c9,7eb708ba,3f683d48,db8e0c25,ac8a6f8e,5c340749,c3d6ed5,7936d515,7f3d6e73) -,S(dc063e66,38098e8c,6ff55a73,faa20099,c10d0258,87c19850,43d1011b,ab211b93,4abdfdf1,285ca3ad,65bb9a85,7ad647f7,fff01782,79fc6df1,6179e1d,495d212e) -,S(7cb514e8,b6361aee,f9a7abe1,f84ef401,97de721b,609c3151,a056eb03,71ccdf8a,4d359c89,7d03a633,369bddcd,52a67387,fd4d1e00,2406502d,9ba6e967,a5efd0be) -,S(103a6644,ee731721,bf29f036,97641fde,9775a642,9ce8d97a,26b06ceb,f9066693,127b6948,6db0d230,6ae90a1,4b8c8ecc,1e9293eb,cf154371,5ecbd579,e886a726) -,S(adfaf771,662d719e,532ba045,72a50f12,144fafd0,afe93f7e,1d8edd13,99226e5b,b4d0335e,8b600a4f,84d919ba,514bc249,e3048cc4,281db3b9,a7c62013,4f00bbca) -,S(609d9352,30f3c6ed,bf64275a,23a9a258,33fb8c3,9c25dde,4b55ce22,e64b50fc,cbbae84,c57f9c52,67278c4d,3b0cc5de,9327ba71,ca1a1bb1,8aec9a97,bce17552) -,S(5ea5aa20,1b958a8c,49b70510,b7c6a29f,86d9ded9,afd4e833,77c433d0,f62d9ba3,27c5cee9,fe3c0bc2,af8d0e30,57eb0f57,b1fa4237,996bf8ef,5ccd25ef,e1b87ecc) -,S(3f801115,3603a689,800c04d2,7d3b3fe5,c415ea29,c6e11951,7a56712f,20a10862,4280ab61,65b122e1,85abf4d4,14a31961,ac6595cb,421db183,34e57cb3,fe9bd059) -,S(54981ffb,5b692a3d,6d9ec7ce,f027fff3,c5dafb7,aaab4c5,572522b9,e1157e5,893183bb,554c81de,21c84134,e395b9fe,80a5a9ee,b06e3b67,2ef93127,24c307ae) -,S(97c18e92,d499ef62,77585c6b,28f36fec,e9a2e118,f793260e,32750861,a1aeb813,38a87702,7f1df077,d6e734fe,18a023ff,36c6d4bf,4a7bc7ce,d3a3d38f,c3069f33) -,S(d5507aae,97bb6e17,410bc87,26d9eb2d,11558b96,6c54e7db,6428b44a,3589820c,e78d0140,7468dda6,d9c4af92,1984460c,e523c101,79f7aa15,d8004dbc,4fc63cb9) -,S(220d6c2e,6c500d01,9ded2aa6,5de205f7,cdbb15e5,69038ba5,7bb1700f,1182ca70,64b68506,c387ec2d,9e030448,797bc28c,5e09e8a9,95f5f80e,70c26a1f,db7b16b3) -,S(c1a45038,da6aaf1e,396595c,3ab404eb,9584ec90,d894985c,18e779de,793d20ba,1a443da1,72e281aa,4393e1de,6f1e4f89,4fe5d1ec,b3a5bcd9,607cf79e,6f20b533) -,S(9a66f9b7,f3162c80,d22d0b5d,2a659bc6,ac01c74f,46804ca6,c908b6cb,90fb419e,3465357b,209c2b,a7c766b6,9c17abdc,69205c54,787fd0ef,e744692,16b95d3) -,S(8b305bcb,1b6156e3,22f0f0df,28265cc8,79e5909b,b76b546e,eb223d62,89883387,929a341d,dfa05574,90cf5293,244d924e,852b00d0,d328ffe4,7ccc5356,623a31a) -,S(4e36ee67,b5398169,8ed9460a,cb450023,7198f249,4dded391,4c2ae003,63c8f664,a784c95a,9a443b7,5859a1b1,373eb750,150e1ac9,d5120ca6,f273578b,73df77a6) -,S(167275aa,38d02988,c53e0a36,d8312e32,369bc677,6d7143df,cc6fb83f,66747caf,f26b9851,31abcf45,369a6415,84b2956a,7122a51f,b909bc30,5427eff3,916e6e14) -,S(c93d0b74,c99358d6,d24a962a,15adafcc,8a4e57ca,df0afeb4,9d46ef53,cf619797,f93b324a,b144c6df,336e34e1,beef5c13,b931668e,54ab34a5,eee1a8f5,5acc683) -,S(8bcaa2d4,671bb4b6,8a924109,32128551,fbf6d924,d4854027,7c1dff57,3bc4a8f2,88be3e1,6482477e,62255fb3,24512abe,27cbb4df,f63c6d8c,93c3c923,47e519d2) -,S(69d186de,f9a7ea8,be833f2,590db08c,fc0acfbc,64a648b6,8ca412d6,88c03808,d776b644,43a81bf7,527f658e,45d92324,a08ce171,6db6c259,898fab8c,f3d6d41d) -,S(4a53595e,e2cfbc6,7bdc9f07,308f57c,7ff5afc8,a35e27ec,e22cdbdf,6efde161,e55913de,d481077a,ea36c502,494b3b72,b1691786,335b0278,3e40fa1c,1a1b0876) -,S(90856f9a,5f7bbc14,557dd419,516ce5c9,aa451bce,13c17ce5,5c9fb1b5,f2924995,ca083d2e,b5a3a067,4a2534fe,e03bd99d,976b96bd,2b7f16ea,6e2552ee,648e934) -,S(2eed315e,d863298c,aa374ca6,2bf8313a,a0ca07e1,9a94bc4d,58eb235b,52d36dfc,afa36c8f,90d7adeb,ec33ec69,40c08d1f,2a4044a7,477da88a,6653d90b,880856a7) -,S(345a7f2,ab7ef064,eccdbe6a,ebd11dc5,3c7ede0,b62ab3de,f8e409e6,258e84c4,c0c0dce5,93cf9647,c0228d8,42b78407,c3b634ac,799fae19,f0e685d2,6ccfd73f) -,S(5a669d7c,209b222b,47843a5a,633e0b53,48442258,663a58cf,f6ee3cc4,1b893d3d,7067be1d,8636698,2b808b16,3c05e57f,2be77d1a,2bf78038,e242f5c7,4ce10523) -,S(3f0b0f3c,30a991bf,927f5119,6fb4af39,e1399d01,1766b1ff,1f0ff2d8,a3199062,be8f8781,4c06a75,97d062c2,196a49ef,93a73923,f43d16ac,82c015e5,4789d472) -,S(9d7f2c64,98e78982,8492b8c9,2e0e49c7,b5c9d4b2,e86c409d,828447fe,4a2f5a13,95ccc540,8202dbc,78323d6c,7ef66d51,4af34699,5be50b56,98a5864d,34e502cb) -,S(9f741436,55b3cfb5,39917a7c,79fec4ba,164503a8,3958aee1,f6e8f34b,3d861b78,345738c,ff8f3c64,f5cda5a7,a1aee7ef,f3a33141,a5139c3f,b891c6aa,feaaa7ad) -,S(cf1d3136,11d4b6ec,5f1a9728,c9a7b037,d9c16d65,bad95fdb,17376200,b1a9a97a,51c72169,bf7b1ad8,6159fead,dcf3b0a7,a7fc13cf,7bf12d98,409dc3b4,fcb7a9a2) -,S(7e04c6ef,c7433f3f,fa2bb827,3fdcb3a,e0470abb,cc7c8dc5,414ff77a,915868a0,781125c,2184eeb8,87019f7,c5c0b4a5,5922d11c,53c3db9e,d5795bc6,e7539cc4) -,S(fa6d73b2,a97801b6,16697ac6,102b002a,53d29d33,289708f,d8f73964,77f3d57d,543db558,25c67a4,cd010413,9f8a093,7ea7ac2a,380799f1,c2249569,3cf557dd) -,S(d0fd7208,8deac18b,1bd63fbd,6d5be0ef,5dcd34c5,538a9b64,ef43daea,ef321d1a,7a5e1e2a,1b290241,7879f223,8cc8928a,65988130,81366846,69841b93,3ddc3a1f) -,S(e856e67,e28330ed,77d8687f,bfdce5d9,ab8ec155,4c94ae0f,491d1e43,9361cb99,c51585a1,9da7c26a,4fc07c6a,f17999e7,a6718542,d7500fc9,1bd21fc3,8acf1eea) -,S(389cff20,9f240748,b9beba0,34d36e0,5e758a3c,95c678e,28cb0226,37db1bcc,ae5a0d3,db1e17fe,30daa2af,1e1f759e,905811c8,95706b7c,e5741051,2b7ac4c) -,S(28ce0f42,ff79cdb8,16b666c9,c3014051,d46e8df2,e2377c3b,619b78d5,17f21a1a,4e835188,f742237c,fe581edd,937b7294,e06fb295,d401b35f,5b7b293c,6d57f875) -,S(3d955bfe,5b27beb9,68400d11,3b8666e2,63af6ef0,ac6ee49e,8628e2ac,4d1e69c4,1fbd2aa9,b6913655,e00f1384,a15a7215,d3d7340e,4891893a,a67faf39,88801e9e) -,S(53dcaec1,2dd48ad9,ee65c9bb,ef21a023,58cac930,316263d4,9d607074,8aceb771,5b976f2,411d7624,d4659e5f,db624b05,9dd5e06e,f0b65740,ba394020,b9d279dd) -,S(ab822568,f7e9da8d,3f1220e3,24752c80,b02a8124,f8d9f65b,3b4532ec,3740881f,6c2152dd,34451ab5,b47b7c08,f7edada8,f9f230c3,5fdc2de3,35cd93d9,e25703c8) -,S(36719c40,1518b976,684bbdd9,2a923485,ce92b321,dc26534f,e5a0473e,4c873c30,d5d58a83,d493cccd,d16a1282,68aa93e4,94ce8638,41ec947,930c72e0,887564fd) -,S(360c82e6,18a53dc2,e44677b,a0bb8c2e,2a08f6d7,afbe8498,15d605c3,2e5fa969,ade18222,e1d0fbe0,a31c55b8,d2cb947f,1fcdea11,1e08ea3a,4f3dff02,e3e38b70) -,S(ecf50737,25a3b81e,dc621bb8,6c98fd59,f805d6b8,2f08380c,64270df1,95f020f,f5431b8a,cba5d27,1da26cb4,fc3412fb,14ccf088,6e0e08ff,ce0db47c,6b4172aa) -,S(3b751389,e6dadda0,85298860,76076249,46df960c,e030caf6,91f91d46,4d05be4c,244b0028,48829fc3,824dbe61,168fa1c0,3e4d3835,d3da3a53,7c729f0a,191e92cf) -,S(ee6e33ee,7fd9d7e7,aab10b8d,2c58f2a7,26ed307b,6fa69b3b,f1f08a74,f1b04ffc,4233398d,6ee49505,c5f21525,6cc9112f,5dfdd7e3,4bfb9a8a,476b3cd8,2645b8f) -,S(e7141075,e20f0903,f39fa384,f91a5708,7f24deb3,68571939,572caf0d,2fb543f9,5265e24a,bd84336c,26b4607,dfa25c44,49c4693f,adddca01,599d814c,21787cee) -,S(d401b043,ee9944dd,7429a8c9,4291dc55,7e5827d5,88375dbf,1513d394,a778826a,9ac9b417,5ac3666d,7c6327be,5172b8b8,1dbdc96,eaf8578b,76f01128,4434b937) -,S(d48c45cb,b90394d8,23574c16,60898091,75d503b5,99d936f1,f60246d1,79c9cac5,4e6b2bad,a67ebb7,a0743cf8,52298052,2737f0fc,6cbef646,fb270d44,2a285612) -,S(19f6446,fabe1899,ec4476ee,1d61f6af,961da42,ada1f77d,2ab41cc4,28791c64,7a0aa5b1,4f2ae030,d9711963,bbe160ca,424f6a7f,17b6a709,b5f0dce5,af1d0498) -,S(2db1d56e,f19a848f,6d6747c6,82cffa47,78444b3a,d57ea076,b0560b1c,4e57c83e,701a5894,d1d6b6cc,b421b168,fd34aeaa,e85262ab,44f70c65,b8ff61ac,ee541cf6) -,S(443597f7,9da3df8b,5fddf8da,3bc3a060,83f2cb6f,affbb1ab,8a12db92,59661adf,31b2c4ea,362a0cbe,2b9b1488,719b7ac4,3a85f7c9,63e9f2bb,b46ee055,71e2ac2) -,S(e49ad52a,7bd2db07,d972def2,d1ce6684,69aaf6b3,3c7e3427,52d79fa0,9d2ee9ad,b2063f37,1ca78c2c,429cd401,c5e46d6b,dcbf373f,5cb77163,5760b8ed,b4f91ba4) -,S(35b3fc0a,4a625cb5,808e1c2e,73c962e1,6ab7dfb3,28109ef,fdf81e15,841afd0a,cb558481,145a5f75,b639133e,8ce42c98,d36d8fa8,5348c815,d92a2c8e,cc993bf1) -,S(1cc238ef,3f64a075,c3c264b,ed42a0ac,aa6de195,7db40d52,86c482cf,f62f609a,d3382317,2b8a1450,bd918aa3,c57de76d,3012887c,98452f7b,c1f58610,f528af49) -,S(f5a2794f,48885192,dec727c7,79fb0b6f,c2cdf399,4ef7cacb,94e35791,4d138e84,d3ed4f1b,912f5dce,5a0842ff,d2e671b7,f3ae8448,b1a73f43,249a1acf,915b9c34) -,S(21b41016,a8eb7c6f,5519d94b,adb0fa7a,5c553822,6d080e3d,6d2956e8,8a9579e9,802570ed,b9b01b1b,ed79b6f1,76ebc4b3,55dfdd16,f43e82e8,7803be0,fc44e274) -,S(9b5611b7,938ac10a,9818bda7,3615a47c,1ee0f072,75aa3dcc,b8919dcb,e7beaa88,89787c01,d088e3b3,603047e5,2f49981f,7f007c8c,a88502c1,3bd9c327,e3c83b1f) -,S(28163c9a,b08a7ad9,38c7b35d,b19e700b,3865800a,55a3103d,2213c9ef,2c03858e,661e089b,df356bd4,afcd0604,fa5ade9e,74c5663e,77ab57f4,a069bcf9,b8b227bb) -,S(bae9ac08,aecc06f0,ffb8540e,2589a32f,11d34a7f,6d899e5,7a8f5ec5,bcf1601d,f5b63d9f,8a5d23b0,80d0bb6c,b8df736,aa660a3b,6f987683,cc0a54e5,f7d1b4d4) -,S(19f48542,3ed01783,cb83d2d,2efd7264,a10c6c23,1f5a242b,112eccb6,31d91f7c,79ce383f,f011ce13,87537ebc,3e70dcfe,2cc2764a,3d180fdc,74a21062,a5b75f50) -,S(cf459ca,cc8c4ff2,c827efae,6593a52,838658ec,bf1a78f4,75965856,a8ad007e,786781e3,3279964e,da5e6374,bf088fa7,5d18901,df01a0d3,6c87b62e,b419dca0) -,S(c19f2008,e6945d10,471a13e4,8b16f3a6,381de3e2,b24f2d92,77ded25e,930d1f47,7179aaf5,322b51d8,7758219f,cc30e9d6,bad5ab77,b35dced9,6a513b4b,fa7fe147) -,S(3fc1b649,3b6cbecb,1767d0e5,6202c84f,39a6b41,87f05ac0,d659c45f,5bc565c,db9edee1,1768e29b,4eefddae,c6234622,55d06e0f,1979c8c3,5c366f4b,5cac3f5b) -,S(502f74d2,cf589c65,e63b2a8d,b2b1e4ba,5f851715,bbb27e8f,165fd34f,29cff7c5,755e6c73,765bc45a,c2f9d4da,499198a7,36743571,40846ce3,6afd8063,981a96b1) -,S(b9eb62bd,7cc6d1d8,b0eca2b6,1920be5,9227534e,7fb581c6,4dcec4f8,f1ec44ca,ac567b37,891e3eb5,c40fecf2,d4c5b106,bd222c8b,64ab491,f7a028a6,a02178e8) -,S(2e5280c7,25a109f4,c5de565b,9fe5357c,718f9fea,db53aa9c,b07a0f3b,f5030ad4,4783be94,1b162e,79f58d4c,448756bb,8ea18c4b,692e236b,4b2b3ffa,24a456b4) -,S(bd59ac74,92d24606,9b233efc,1b68c371,bbc9713a,284f7f0c,699a1d5e,ccca64ab,1abc71f2,fce8372a,a4a16abf,1d75bd87,a19c08ed,c8843f44,fb71bb7c,a74ec4e3) -,S(6acd12ba,4623582d,d769c8bd,3d6adabc,2c13ba3f,bb67e4ed,ee0fe70f,3f832f5b,982fce11,ff1e6c05,2f21be20,ce1710d8,5cc043dd,eca9bc43,5d100d9f,f68150b0) -,S(601f4285,8b0cbce9,90500c64,e7eb77e1,c433dca5,55e6ddff,5264a98,d688decc,56110eb5,d5b3ed79,5906ed4,c0275827,79cff7fc,ddecbe7c,74d2bf10,ab2beac1) -,S(4d393daf,c47391d8,8208263d,b8132156,e9fdd6b7,da48eae,90489d12,832dc938,a14180a7,898a5a00,6ae5b8c8,d034c233,93ed2ef4,faf6a4fc,42c4df1d,62d0ea7a) -,S(4ea24f6c,3c164285,166bf2b,1918b3ee,3cac8631,5a1175d5,4104506f,68b7171c,87da621a,a18d1a18,b1dc222f,af37b5a0,b149714a,e755ef03,ee3af91d,f2a7f5ea) -,S(eb1f6f2c,a5749f80,b88a7359,f0b67230,b2b844a2,4fb72dba,f5604e73,cf6e432a,6f58093a,55e3cb37,8830e58b,10612b24,56a35fa4,b8e60409,1b9b8304,e35cca51) -,S(2361315a,3d41b82,98a9d768,be7f453c,eeb977af,bf1db132,c831bc00,aaccc9ab,90df3be,336d4b58,7965778d,9300cc1b,3d954d4a,89abf173,a9bfd99c,29492dbd) -,S(44f432f0,46c7defb,630d5535,aca1bd47,10505012,6b2454b3,4591b079,7f8e9b28,1fdfbcb7,25eee981,c19f98b4,6bd19dff,9b6cbdab,730ca2e3,1643d415,e3aa0489) -,S(d563a475,4c130e71,81b60a66,a3f2ee52,7040f9f0,eac9e26,866fb226,f93db593,49fab7c9,6e320961,6f4610dd,532d547b,b24f7f07,f916f10e,630ae5cd,b40d3b11) -,S(2fac4651,f0ac9876,4a74c066,16e7f1b8,aa6d2bb2,99ef9f0f,43bca81e,7a4089b,fff2b7b8,c330e1f9,86a69324,a63bf10f,fad8e78f,dfbb6062,c96a67b9,eb460d5f) -,S(b6f60ef3,d8b793d6,5794aa89,12e8e1a0,9ef7604a,5c9eaede,b803fb31,e8195dde,b9b17946,4057de11,9d0bf993,fe92e4a8,bb633d6c,d03ce8b5,10200166,467e6bbb) -,S(d08c6813,65789ba2,4e580637,2eaa1ad1,d1254462,3cb64d83,5ea2e1d8,6e34620a,e94875ca,f5beb1cc,f88fa3c5,e2776203,a6f3cb5e,b4803618,52215d0a,9076b185) -,S(dfda222c,a4ddbb56,661f56d,b9b74be9,a5a7c34c,4761483d,928aa48,9bfabf52,bfac4ed0,ab4ccfa7,caf64d8e,ffdf1aab,6aad50db,595b1b49,7fab28d7,656b6475) -,S(3f72e4cc,ef5c0bbf,995bf8b4,67759969,d93ee40,8e738a4d,41f55896,17f241ed,c42ad857,3f49218,c7daca7c,8ebc5c7d,f9ac301a,2aea209c,ab6648f9,8ea16f5c) -,S(6e85f587,91431b6e,dd848aa4,70101103,f63881d3,2fa9f1c1,e3324161,e9ebf0ee,f7f00d38,31e09d69,f0684107,59dcf837,eed3d833,90efa352,40a9ac5b,2daa2a57) -,S(d991fc76,2f75235a,5268a32d,64dbeac1,b2333a34,5ad552a4,cedfab54,9b191f14,90d58a07,794983c8,3f6edcfb,55ed0b68,8f43d9f5,eb7678d,29610299,63c748b) -,S(24cd7922,7ef207bb,6b9b678,5156bf76,77101e6d,f5fb5576,a9d33175,8d7c00,44608974,5f1157bf,9c9f45a1,b212a978,8e348a0f,55129935,b038940f,84e91468) -,S(5c053ed8,367806a2,8545692a,47314850,66910d02,3373b89d,e85bc7a1,c25bf6bd,9a3e45f8,dde03e64,6d6c546c,cf4c8fc5,a253054a,2d6df43b,d8c4afb6,385311f2) -,S(4f3a4d88,20948d82,b598f118,1d350719,ffaa5ce9,9a7f614f,a9e3cbf2,e021a6cc,149c6722,980a41ce,5d4c0b94,9cbe3c99,4d94f2d7,c36ef45c,d7b9084a,79f451a2) -,S(badbce64,8d55b579,cf8d6dc6,74580211,a6bff856,10804077,adad7c2d,238aa542,567d75d7,1570d7e5,184f4f4c,a53fb92d,654b67d1,f6bff96d,fddcc3fb,932f0343) -,S(d2eda540,5f828eb2,cd3bc5c1,9f9a838f,8a1186eb,3cbe9575,5cf6642d,13601942,ecb3dc3,655ea992,4773cb57,f4f4c8d,6380c665,69f08184,f521dada,c108629c) -,S(191ad0df,31c7f3b8,258e5bfc,ec9d1ff1,2143b240,24d93a17,893da095,97304f1e,4ad4991,6bd2296f,b6f6b697,dbf5a3cc,4c3ba136,6f6dfade,c859b190,48fb523f) -,S(f108bdc4,a1874aff,35bd1fac,b8e81b5a,7a7ed597,e78dfb7a,c716bf7e,7a15dcac,b88e4fa0,d630d92d,bbdeda05,4a6c6624,e7bb1d5b,a6dded85,347e5275,e08c9414) -,S(30fb7605,7e2a6cdd,59fa279b,3574cf1f,db9d5159,19d0e523,990be02b,da1ebffc,5743e72a,752b558,1b959a48,3b6229c2,33fa1b3b,2719ad3c,a6f8f9ba,1702ae8d) -,S(6facb1e2,6d1ef1cf,ff413145,63f3b2e4,e762ee7,3e43378,c4c15f85,1cd948bb,92000e2e,a3a5bdbf,f6eaeae8,8619f2a,48b649c9,19972b7b,83cbac22,62d484d7) -,S(741c1253,8cd4da52,c596840f,e6233558,fb480a0d,43232756,2a9e2d59,a574b981,79040b6d,580efd7d,84356117,a93941f6,b47e6c0,a53627e1,bb80fcbc,e6881234) -,S(2b86fe60,2b2e87f,59498185,4af1f986,7debc5a,84ae8bf,94d2d6ab,4ec8be09,cf4c27b6,b33b5020,2ff7fdd3,ff0743e8,f28ca75d,3cb74d21,ecf21dab,ad7ae079) -,S(e6e7b676,9f0ed86,4163e9d3,66a7e2a7,a37f1ee8,e827b105,3119b8b,d36e7b84,c2e5b9b1,d82b4504,454062de,6c24430f,53e03bd1,819eb1e3,2f24606,73d09be2) -,S(86600d22,e7bec946,5b0afe05,5e733b03,f8f81548,ea44e008,740ac807,ddaabbe1,abb367d0,5e6d2fd0,a2c1d0af,5ded2926,1439c985,ef287860,80614bf9,8e8e33fd) -,S(67171261,5cbe2da0,b252a773,58f81c91,fbe561f4,87df09e6,cedc8a55,cb3414b2,bf02d81d,10a47287,2b7e65e4,93d97cfa,e3bd6ba4,39977371,8cde674,8829b0a3) -,S(97db468e,7f3a25c4,c34e202c,e9b2480a,4344aa9e,1b76a147,4bd375ed,6d10c0da,c58ceb67,a28f99de,2eca70ef,e8af24fb,c381f962,d5db6e3c,481cca6c,469c4c27) -,S(f3ac0267,ef19ae9d,762c4023,4ba97e33,a88b015a,e6a83f4b,cf730d84,405aed26,cfb8a3ef,d1104873,8c1c927,b31ebd05,105bcce1,d57c7fad,1972a5fd,cbe84f06) -,S(fa44128c,3c258fd,5a99c85e,775fca63,4e8a46d8,4fbff953,b373bd50,6ca3da85,f3196e74,d17cae3e,3c9958cd,ca591374,ddffcba,7e362139,17e5e119,a5538b1b) -,S(95244462,1eda0b2d,acdc1a57,41725c1f,a7c5660c,feafe18d,ff8789ba,164e7dbd,214bb6b1,7af1584b,76a9e5a6,2c32eefb,497324d5,7b00f71d,24b162e7,1383bff9) -,S(11de80de,c03a732d,6769e52c,64be4d2f,fb1d696b,2a658721,94aa384,392dff9,e1eb8932,42386216,f543eea,a2d1099e,531d8e27,7cb2e5fd,ec76b3af,e9e9c7b7) -,S(7318b452,a2b9d23a,eeb30bb1,3883dff5,b373be94,94451c72,36a2c02d,a4c37e75,26713361,aaedfdbc,2966fd1a,ecfa705,772012b2,564b077c,7f5db7b2,c810861c) -,S(82d189ad,e5610825,1b03cae0,4b138ff7,dd2d77b5,422535c5,cef9be7c,1899cf75,3634267b,1b3c3de0,d2dba36b,924949b6,7e05d790,29c9452c,18c6ff70,252d570) -,S(e5dfe995,82152513,80859865,f16fd0fd,e4d60c7,be0e2aa2,d9b2af4f,3714f8f7,e1d87d8f,fdef889,52918e62,5bcc90e6,83f337a6,103cd000,1cfd01d1,eef4b9bf) -,S(54cdeddc,9fda5fe4,63240f72,8ca66c34,ec05394,899f2472,d82d2378,28a06a3f,27bab620,cc373ed,10a71c18,345ff27f,e20e1bef,98052afc,bb45fdc1,80b94a2c) -,S(7f96757b,8b473785,e1359cd5,bffbce2d,5b26e8fb,579d7833,607d58,a791c47a,d4b43e2e,20a43fa3,5a96d1ff,93109aa0,b7831fdc,2d2c016e,181beac9,c1cfcc4c) -,S(eaed18ba,83238fa5,ce4e6c82,edaef108,b1f9929,3148f3e6,2d3a6d4b,535455be,1017291b,805f7b1f,eba367f5,9a1a10b5,f7501355,7e6eb921,20838c50,aab0d29b) -,S(91ca8ba1,da9c2625,66a135ad,81f57b10,65ea4632,5bec5d42,ca1ad62b,826f04fe,2d5d619e,84fac3c1,e30343ba,a61d3bfd,e1c4a9a9,8d968e92,d560956e,138e34ee) -,S(8a31ad57,12e32254,7d0d2907,cb73adfb,a9a1ed5f,fe98d645,22082e6f,1cdb1364,8ecc3fea,886737f4,f94a2984,e6edba9,8128b2d3,bc79a209,2b2c1a7b,b00bff9e) -,S(123acd6b,ca673170,400bfc4,1071cca5,4e03daf3,e1ed1458,88470c04,568b972e,e97dc60e,cfec2d5,c6a6e173,9d60f7e9,838ad723,ad0fc7e1,52b5e70d,b48b853b) -,S(d7c26043,ad647f0f,d056c10b,4ac932c6,6a545bbd,509de346,d4391942,52e69df7,6bbf2f04,2c9459cb,c72e6aa3,1b6d8e4d,e606eeb7,d5d4e0f5,7f729a79,ab1f5e9e) -,S(67c4eb00,548e2cdf,50626c8b,1aec1173,8370da41,9280c9b0,1c8783ee,91e018d0,ffff201d,91a4538a,97ceb50b,c9aac646,bedda1d1,3f22a121,c709bfc6,23b95a67) -,S(7e1264ea,486b08c5,19c7d8e6,5c80e1d4,d2994bb0,95185c72,63172b1f,ead93428,1797609c,816f10a2,e82afe39,65112a35,798b0874,b24503a8,f57c983b,6ce7ef6) -,S(912cb164,5f7d7bfe,5ea443af,1c458500,a95ff22b,212109e3,12fa01c2,41319cf8,bab658b0,111c48f8,a2f620a5,fd130d53,e1c70e7,62e33dec,55b22d87,38c1eb99) -,S(1d60694f,15577a40,f6b9f299,be5eb62d,251f62ad,b9b5651b,df804e27,df919fb7,3799eb92,e18335b0,bdbc29b1,f8ce07ff,3f7cd409,5840d5,dd324bca,2f902a14) -,S(8166b50b,811bf53,4a94af10,7672ab4a,4e154b2f,c5cebee8,c8ef6ebc,18cc3906,6dea31f3,343e5b45,f5b08c19,903491f9,349f4ca,29818fa9,16f5e02d,85e09ef) -,S(4852393,e42d0821,6664d5d,f85eee60,9660eaf9,54ccc6d,fb1c31f9,da17923,e4cadcab,17f64d8a,f5dd74da,eaeab7f7,13be1de9,600d4db1,a781a058,5ed2006d) -,S(f40031b5,ba171b26,e02be47a,c34173aa,18ec3850,1b1d529e,a922a418,1c3491c9,c2db89ec,2e50105c,4074b729,a53ef0a7,9371d2a3,354d2d23,8fb39bf4,bcb5028c) -,S(8926d233,3c842f9a,213547a2,fc5ef5de,b0bbd603,e69d347c,41e7d49e,aad76cb2,8459bc10,b7b2617,b0d434f4,b62a4452,80bb951e,b4ada14c,fa800389,b3ff892a) -,S(7f362b16,9d9bd514,c6289cdc,70ea4b77,e7518db6,a2e33acb,8acefcd3,d8c5726d,dd1e69e2,71d77dc,2629cded,72869345,7c63ea2c,8636c712,e45e6af0,4c15fe35) -,S(261b8037,98ca780b,50dfd56b,81093f32,d7c348e,4f093b91,70470ccc,4516ee1c,5723ca6a,5959d589,4a24c12b,5f87a5af,84c7a6a6,89304000,344bf5d4,81c7752a) -,S(d137c0e8,edb32642,12f6b958,8b527a9e,9e57f3fc,c358a2b,68f11d61,89fbd900,d1043b3,5f809513,ae370588,4adf90c1,9d164c3a,8166027,92ca55df,74c71466) -,S(96274665,253f4479,753de9ff,ac94af8c,943b8231,b1302040,bee72240,2ccc445e,8ef6f9fc,f1e21c2b,d913f877,98c6ac9,f53445f3,6c2b1678,a301a4f5,17867296) -,S(bc6ea584,b1f9b006,5f39226b,e31a866f,7f90229e,12aade70,136dc747,b37f70c3,23f1c4eb,99dfbcbf,66539762,4d20c4dd,4414bf15,172cde8a,b7652ad6,f87ad5e0) -,S(3e968741,5adc1afa,696e3222,fe351939,1d3f19b6,feb1de83,f4f1aec4,d25e2387,e3f4de27,67ea84c7,8baf1382,4b7917dd,477bdc87,cf1cf38f,8f5da1,e096b528) -,S(b5973535,c9c9d4bc,2b2a9b38,57cdfdf6,4995d64b,81c9e68b,abe4d4eb,4eee489,907cff05,5eded925,770280de,9ee0e025,1629796e,8ca05a47,48ddaf98,72bfdc3e) -,S(d616bde5,acd5f345,d23e8b2c,3d95038a,a1d7a354,a7613cac,57ec3e8,d07e11e,6c88c62d,d795d065,c6c86478,cacc56d3,2282b4f8,f3059aaa,55388555,449879df) -,S(540345c6,5869d3cb,cf4099c3,ba7422e0,feb87ab6,ad67429c,2dc99840,e6bc82b5,9f424998,bceafc7a,a58e5f16,c58e53d0,c0d51f64,285b0afe,e84ec9f6,b22f8f37) -,S(6b7893d0,ace6ab5f,c93f2e80,65a3de57,4d552e5d,4a89d660,714113c5,a256fb84,81a016a3,7be94a2a,f45b1bfb,968006a3,58398fab,424811f7,6765fe75,d4438d5d) -,S(357ea5e1,7a0795ca,cac47e4b,9e59bb24,45d1b6cb,2c713f04,7029f6de,2be57734,571de7e0,27dd05af,90bebc29,bd7345f5,77babdd2,75498bb6,d43a668a,8a4d6206) -,S(7baa2739,1db2a0c8,679d0e18,8c5e7c8f,ef1814ad,b7bb3955,519b4189,1a63ec40,73b56168,20fddbb5,749e8dfe,ef834f74,e266df86,e34510cc,f5eebb52,a868075d) -,S(4d5251b2,dd778e04,5143169f,8cab93b,9a9b7428,1a0ea1ff,964225a8,10b1e578,9376395f,2091036,16a95686,4e55382b,39b6934,2b2964d8,34face11,a44f491b) -,S(3c0fb553,b0c6330a,3cc06bb3,b0cb4c2b,31be7582,55264b29,98bbc166,ff57f7ca,f1f409bb,cc227824,4dc08c3,147e0b83,3522da9,6859400f,8d19272,e33ef1d9) -,S(6dcc7ba0,4b3b0827,e3bcb462,7b7db8d0,e0997c7f,900d27de,2d6c87d9,aab2c373,f2dcb11e,87b69faf,4400e9b3,186eeb6a,4fb48cad,6d6da276,3943772a,4e18b450) -,S(a5271e35,ca54c1b3,16d6113a,40414ed9,26bade46,c3258c6e,82a63e9d,927ce06a,e2d6051f,bf42dd9b,e0b2e00,1fa4e308,66232871,313f9c82,fd6ee37,6e8e376b) -,S(574d1ffd,976c616f,60371e4a,76b2712e,84b0a231,8d3c1c0d,3b56b10c,e978efe0,13733a17,a956efa5,733dc130,cc4c848c,19ecd6f8,7fae5ac,82c73de5,6d1bfa0) -,S(ccccd911,ea84c247,262a6e61,8028b2c1,a147f55f,b637b570,97400472,fe3e27ce,cc4b4f5e,491f32aa,eb6d0404,5965a97a,e4119e73,33bd1b39,f2ea9873,7d8f33ef) -,S(df1e4fa5,410f1438,9a41ca26,31eef376,4f10868a,f2f05a1,50e2c7f,8c3a2643,8185a88e,2b4a343d,bbc10da,723d4cb8,29014cd6,3211a82a,63627b01,1b01e87e) -,S(2ca6b7e,b53516c7,2e216263,213c0d60,fbb02f,dd227f6e,4ad29069,f6da9213,81d5fd1f,5264af85,53a8227b,7500d82b,84ca1fb5,87ea30bd,ab30fae3,67e3d7b3) -,S(df4bd790,ac3a0db,1663a8fd,aec1cdb5,b30c7a67,99ac2ed0,16f1c474,5bea92a1,db80f378,f33f920a,d0f4fad9,595b0655,44ffc36c,ebc3f294,3db13b83,cf609bbe) -,S(792648ad,8c053cb2,102dde19,789d3782,79e0e0ca,c500f40,d46bce68,97af2839,3c2d9b55,afa4ba1e,1ce3d142,5e17ca6f,191b4013,7b7d8162,8de35e8,801f72f4) -,S(dc6fe845,50fc1136,1f648fab,deb9b3f8,e7fee837,ea545228,b2fbd432,e53a8aab,2a4bf746,19fc5408,b4bc6421,f4a570aa,172ef263,c890c853,d7b06aa0,65960dff) -,S(10d4786e,9151f2de,89f368f8,9502b7fa,74b7b9e5,7a1485ab,f82fccb4,9c2deca8,15da7f51,bc84f421,2ce948cc,28663e57,8b4b851a,f6533f2a,b548adc8,147d2243) -,S(67c7c0ae,e82dfd5a,194dc416,41388947,29ddce96,5b7d50f3,ca922512,6e730bf7,a8bf40e5,666ba93f,1f723414,24d8a7a1,6a2aed83,7f022fdf,557e6082,e3e515fe) -,S(602c3df0,8a2efee8,329f391c,a9f7b2f8,31ab6d32,bc4623c8,92272934,1f78a4f0,ac17903b,3808ee52,c0208342,696f5250,5789206d,515421ee,8b1ab28f,5b788eb6) -,S(c3441893,e78910c8,3cf917fa,44b608b6,671ea508,37a7d2e0,4e658c6e,2a91d9ef,b5388381,17c264a4,a0876c3b,7c261bea,229c2d0,a7399c05,114f520b,a7185dcd) -,S(49dc68b4,412dc3c6,c4b265c1,6cde755d,bcd49f0f,394d552b,76f67ff5,33c7fddf,f1490a38,cdbb6c88,d270eead,7de6358,132cff29,ddb6aea0,1baf6353,4c0cdae9) -,S(89080197,4a95beff,da864c28,36997c7d,3a4c0fc0,4ad59eb1,5ba4b124,702d0f04,86e165a3,b2e7eb55,9a7996ad,63265609,aa6e3385,30b51d22,4ae4f16c,d30be3c0) -,S(c9671a3d,f749d635,5684de03,1764cf19,1087bd06,965d23bc,4ea0555d,29ee0804,33cc0d4b,b02a1910,c158db0,ad2bcd66,c9585f9b,456321d7,61752148,e6224d85) -,S(f3c1a76e,1d4ce622,dc667a4f,dc0f4ede,7eb7111a,1539ce5a,bca71d2,fd48a26c,269ebdcc,e1d42428,4e0dd49a,73968676,58857998,7a062320,6251ccd0,ac9f9e2) -,S(12002fa6,68924900,8a540429,50ba2901,5870a70f,7fe95ae3,dba4b07f,aa6fa460,51543d34,34568008,74e8b1f6,6ec72fd8,e2936b6a,6022401c,d13d50bf,931996ca) -,S(a59df11d,d3fcf1d3,264028b3,6e26dcf5,62083e44,f91f3d27,f23acdcd,f1392a9a,4dbda718,48afff3f,faffaab0,5c5376e5,5fd15ced,68b03ac4,4785ab2,201cbe70) -,S(89f738a9,802d7deb,5cf2895f,60916fa3,d6d74bf9,e740d2f3,13ba393a,b40cacaf,293aa5b5,b03557a,e7288066,5ade09cd,ae6abc71,8e7d445b,cbf85a44,a035b73e) -,S(d0414978,6252c5fb,b4bfdae7,56092769,dfcdc2f2,ae38a5fd,92ba9df7,f91a9ee,53ffb526,a24df2b3,d6e8faf5,ee6d79dd,7f427d8c,14d2d5b5,880f1863,e7e95099) -,S(4a638f24,ef3528c7,a4e42cdf,3f5bb946,81e6435,ba2c99d3,625dc282,b941d341,39d97ef2,949f1338,bc016ec7,89585780,832043ff,33777357,9ecefac0,ae40620b) -,S(70a25f6,34d32af1,47c4dd06,5d52f78c,eb5e53fd,64bb151e,18e8629d,f4f8088,1b6bf3d8,15a0f919,68dfd6a7,7ab7417,d4aed9c0,a52b93b9,9b4e4e41,d1e558ce) -,S(59ea9490,24765add,f99fd908,11c65ac1,d0f9ee8f,27e459b9,b5851765,8e96ab82,b38bc716,896e0337,e4a1b361,59e2b5b4,e1680ef5,beb4b47e,c5934b4c,8d6675b3) -,S(874a6ecc,6260617f,c6d4f334,40c8e080,3d993594,ccc2d47f,be2869af,9881f2aa,f509e39,6663327f,7d768a67,aa0d2ef8,353b613c,bb60fc38,bd2715cf,349c02e) -,S(dbf3567a,1e634ab1,63a860ce,244f3046,c7f486f1,b12928d3,1c44624a,48bb5df0,bcdfcc85,38e4702f,99f9d55,eaa55216,730405a5,66fbdf07,4c62b310,6baf7ce3) -,S(a534bcb1,96450965,5593155d,2da069a8,4800e4e,eca0b504,62d844eb,d179ac50,f86b38e2,d558be4a,b0a216a2,906099dd,f3cc16b7,30e784e8,745f39cd,829ff3de) -,S(e11bb840,b79063c,4e090771,29d2bce7,8f291f10,120b57ad,63594780,fd1f1905,7fcac0ad,e0cdc573,67c9d74,1c6c9928,15b7c3fd,3a19b266,e0e5a94a,9a9ef9cd) -,S(d79bf0b6,552c5b6e,6e9192b9,765e687f,ea226d86,c6f83f44,b427ea9f,14b404f8,54e7a54d,583e2cac,129f17d6,835597aa,934b4732,6ffecbfe,deb503a9,eb9660ad) -,S(103396a6,57856b61,5507969d,958de14c,251bbbd4,9851a5e9,ea64e0ae,2f87817a,9d66ba9f,cf3e0c2a,655cabd3,91774015,e209d771,334c461e,d27b683f,f83b477b) -,S(9b49e25d,ae607f4f,fd876837,5ffc0fb7,142f9cb1,f0fde836,537f320a,9636723a,3472462f,f9fa5ab3,1fd1279e,7953dbc9,85623021,e714c951,bf00f632,e9f72ab9) -,S(a017d4f8,8e757556,b7ee81b9,d4c9b260,ba2f7f8e,5e1b69a5,fff94abf,723cc438,5f2819cf,53fcc35f,c9c15d2f,13dd51e5,2c8dd134,f012aed3,4b4383f4,8b00cd95) -,S(aff1db2d,3fa6dc00,51a8723a,7127d57f,69ed0b49,ccbca35e,25f72bd,19076211,7cccb7c9,4adc2075,9c7f8870,fbeb1a1e,9f95d644,af0411be,a6b12d3,aa6f00d7) -,S(21ccbdab,f6902a86,d368d445,dfba0f31,4f80de6c,c7f05f7e,9fd1818d,45a174de,eda0b8b8,7f40e9f1,bdd5ded,e65bd72b,6cbe049c,bb1575c9,6b779818,a67251d4) -,S(c3e58ebe,36b0e5b7,2e15c47e,cca6848f,5312369d,d270dd18,93b589b0,56ff7082,212df92d,d724e3aa,c42e293e,b1a2de5,3c340712,7ebba791,b901ff87,9fce94b0) -,S(f19961ea,da1d77df,2fb9d976,7d7c664e,c0400066,2ecd7244,12b72dc3,c5de133,74f321a9,1287943a,8ed14d02,96b05ada,1a24fb52,a09d467e,8e8175ef,8f04a2c9) -,S(3aecbe48,2aaf6af,35e63dda,fc919adc,f974e89e,765c4437,69ef535e,cdc05e01,92b854b9,30e5e4a8,85397592,fde89d3a,601c733f,d88d230a,a1168e36,ee367273) -,S(55fdd639,b87de7c3,9acb95ed,33222935,bd4217c0,fee1c924,f1060f54,fd22055d,81f4ef46,16e51585,cb443bce,f16ad8e2,36d6ed18,87ddfa60,ddba2089,f4b83c4d) -,S(b86a6272,ceed47d2,4ef4cc67,bef0b117,c0761b4c,29548c8a,367d8ae7,bf90744,1c0de18c,d5f3331c,5439020c,5964404,be582f88,3feec4c3,112396ce,b657c4fb) -,S(d141a7ae,9d92913a,26deec5d,d2acb7a2,115da997,63be5a76,c5a0a415,8b5b8170,de784bc0,9308c82b,ce3be9c8,9abe41a,4ed9b9dd,cf817aab,3785e344,dfdc2ecb) -,S(af340559,6902ad5b,e3fe3464,3cbcea5e,7a478a32,b1bde828,ec966837,192344e4,3f65050d,13e7b969,35b013c4,9df385d9,833d419f,aac0f754,5c395ca3,75ae8965) -,S(b70dce7f,870d3d12,472d3c5,481a1288,cccfdb2d,12637a9d,973f4e12,b026cefd,4b4f733d,e5322132,80a36e4,ba57894d,a563f4ac,b1a55a9c,83c8dbc8,96a7fdf5) -,S(14fa3dee,44dafb00,d2e71c91,5d217cd7,a9c2b50a,edcd0025,f7aad2d5,b6c62ce4,67c3a65a,65bd4292,d271fe13,9a8c9d84,343bdf68,cc16e50,11676580,6bc30d8f) -,S(baaa6a53,26a7fc36,e519d9a2,48dd3aca,f6f0628d,a6406021,caf0d0c,56d9bb3d,4fe9c638,c1078c39,a0fc39cb,e9a81bc3,4b15840b,631ecbd3,8ca4a2bc,10d1f3a) -,S(ffe2afcb,5e53bc7c,9ee07740,c8094a3a,32c8e627,4dec7eb8,cf2673a2,dba11725,68d7092e,2b8b56da,1653dfd6,42de49c1,799d3ad5,864e052c,8829815d,b2ad952a) -,S(a25d7c5e,83a0659c,5ead610e,b581d325,adfdd3b8,af03736e,4039ee1f,40612431,679ecfcb,b1da355f,d73d02e8,b79fc949,bdc9fb5b,5a4e28c,5e68c244,7599c806) -,S(1c5d082b,3121c4b0,2e0e2244,88e53b8d,ac5500b,bd396f0,7fc218dc,7311b299,a2a435af,4838d028,4d459216,f3955427,59f1f51e,9a15f28e,d83987dd,9c09e5b1) -,S(d8d21200,2cf2ceae,6c9a90db,89f7d0e0,42a2e97c,458b9024,437e28ed,a775ca26,b31b6a02,4b01de6b,6159ee51,3c118921,f61a536d,c1442525,cc613290,364b9df2) -,S(b5265664,54579771,947bee20,f8e7bc48,1e15d07,2adcecbc,3aae7b91,a4d0f3b3,170ad05a,da7f67ee,f7c611ba,3c55c835,f054bcf2,445e5c1a,399c7cd7,640ba8be) -,S(1d0d2a24,8982635,18a28203,b78cb089,acd5c296,98b86b7b,48fd4db6,3c80812b,71e2e1a2,7bff3bf,9e85e145,7f446048,7643f154,1cbe829e,f600d861,dbb752e0) -,S(cbbd4ee6,33aec586,ec7ba712,c3bbffaf,a0e6497b,8618a476,b64c660b,340046da,d792753f,c73090ac,177ec5e3,40aada73,3b31dcf3,a1f46952,625dab85,7e9b9795) -,S(73cfd295,99b6b80f,8757a873,ce9166ea,b1960f77,fa8f1d55,ddcdc90,9420a751,17832aab,c1083af5,683f8cf7,23c6376c,c22d190,241e1e37,6b1ef2dd,7333c873) -,S(20572bf8,abe50ea,37a064f,738dd18f,531b9404,e7e4d693,2c9fc34f,ef6dede3,41c79375,11c8911f,3146bb2f,63750887,c663d2d6,f3fbbd53,30af73c6,9d332191) -,S(ac208805,2f1518d0,3724ef5d,cb149f36,1ed713a2,94392f92,96173857,94794f70,1820bb1a,e843255,9025f3ac,977d9f59,4e812cd7,e27c390b,b2fe905,ae2b7017) -,S(33467f95,60aae872,b5c9afba,7f29cd32,a213f197,47745d8d,945d06e8,295afacc,44040bd8,138d9bb2,76181e21,79f4bf98,4b0c3965,a1a47d34,be8f47ff,52e15af2) -,S(1a77910,75bd3497,cbaff6a5,d5e8bd6f,439f5bb7,ca3eeb98,68033ef1,cff83f03,d8af802b,daeebe88,f823c43d,447f1906,63ede3d4,c4b9dbd5,caf82a3d,b4f1cecd) -,S(dfacafe8,cc15f85c,f829d913,9a9aedc8,6a98e010,5308572f,94c183b5,533f5bb2,c076b6d,c708d2c9,895e22f3,2fe42f4,33ad38c2,a0c55aaa,5c551fac,fe601916) -,S(3cd975ea,9eb5fc56,14955bb2,db0ca413,b83116e3,a09454dc,7fe973c5,7ee33ca9,261e5544,2fd503f7,7c1c7a49,de96fb50,aeac56d,30cf3ae4,8b2e1cb,1b9fcb6a) -,S(168ac250,d23cbce6,23eeda,1389e261,c56bc718,4234bebe,6b108bf9,bf6df45d,add3ffb7,b0a9a860,21ca51e2,f3d2e2d,19206bad,78d9e661,2895068a,c880fcb2) -,S(47bae439,31966a6,984241b2,2afc8b86,94db88c2,abdb1737,728e1af0,e3803968,a7cb7d64,a07cd13d,2c8dc7a7,8a7a144f,8edf915,5cec20af,102260b2,d8d355a4) -,S(76e73a26,730b1444,8ecf60e1,3489de8b,93355af6,8943669f,20da17f1,4f04d517,41f75520,3d5d528b,2e81bab1,9ce8031b,bf9c73ce,7927645d,178ad762,669b99fb) -,S(f6f08712,d85f9219,bb475122,1ada6a75,1a8d4758,f5dd72f,f5231d56,e634c19f,d72cfc42,379ee25,eb0fb134,338109a3,7752fdd8,1ad102b5,f365a276,1d133f10) -,S(1acac95c,9b0ed53b,e6c37d03,7d47a796,2a371caf,cede380e,799d0110,b0634f7f,658c6b74,44846952,93a5215c,63695a5b,fc80f818,633e0278,f6a1193c,6d441bc1) -,S(5759a8bd,ab76d449,13258631,68773369,5b76d2da,7b1e4004,1bf99198,bb25f218,15c1dc97,8ecff6f7,cfd6cbb5,44ab8666,83127b41,951c247a,f44855,4afde3cd) -,S(cae1e14e,c28ddbfa,379a97d0,5f3ae379,3771750f,5a9ec743,2039f440,8fa7e2f5,eef09268,6b9f60da,8e64ae64,8f13d01,8f7b9ef6,aa849f9f,72df2f9d,f80fbf60) -,S(9aaa132b,947da7e4,9c1de2ea,ce06e3f9,ccdc37d7,6d2081a,be5f3a37,9b0756a0,e9bee628,d6a64476,af601737,68829c11,e8646e8c,beba7174,806d800f,56f6676) -,S(f38b62b2,4d609d01,70cbe85a,cedde44b,7a766a30,d8b7db6,8d935735,c4d0d204,8b61a5f7,e3caa2f9,17ef9ce2,c5eb2499,667558f,7c4e4e84,2644dfdf,a57666c6) -,S(25c121fc,74c57f34,29a143,8ff3c47a,f06b5de,74c4dcef,4a093b87,3a2ab659,69254121,eadbd76f,289cbf3c,21cc96fc,436ea33,9ccbc8e6,fed92b2d,331246da) -,S(95666156,c40929aa,8a7ca656,c42c64d0,e24c3789,ad3781f7,9e2a0ea,c7ab9c1f,116f5750,7e07b846,92106d6b,6976741a,59bf7cf7,909733e8,e1fb54f3,fd77e783) -,S(cdf1c010,7c48b65b,c001df94,c6e84d12,d8885af5,820d65a5,4e7ffea1,ef4c0081,8f3d1be4,206bd313,e1c498e1,5e7a9995,64312ea5,aa823196,9c566349,9c3a04b8) -,S(955269f2,be0d5e20,5382b2c1,959103fd,fa2c2386,9bbdd33e,a09487fc,294dd1ee,6306a092,4ce63798,41b2d773,8cf97ca5,e259f81a,a67b1e0d,42903f1,beaa869e) -,S(78013976,449ddc23,4d32a793,5ea525d5,9afa3617,47e0a8f9,c8141d9c,2b231e14,8d28142c,bb88abfa,1a72d583,4e509d69,3cdee0d3,bdff4788,83618ce7,a1ace69a) -,S(e6d67a8d,fe513147,2c0fe227,bb08a8f2,25e2606e,23672969,ad3acd65,155f972e,46c8695a,5b9d931b,adb568c9,d3f9a8a9,dd501508,fed00c99,5159f518,bed035ae) -,S(1779ea78,eed6d974,563cac2b,b3e72693,409b7029,789e0188,d061a182,3f18e962,82590ffa,6b9e0e13,d2e72bef,96d555df,9f7d2b81,2423a947,e0dae41f,91cc0722) -,S(28ec208a,6e929f8e,a815fc17,7b927086,7d482547,53ba5c3d,3b56fa91,acbb67d8,b4453dd2,eb964348,94cc1cfa,25616a2e,2f0803e2,8796206c,dd31ccd2,dc69aff6) -,S(c218c6d8,3124c9d1,c988981f,d4614af7,ff85a572,dd89e4ef,6209e80f,e7656de6,7259c421,45ef6e9b,d4f451e6,e2dd226c,2e750650,8ff7834a,965cca4b,cdbfede8) -,S(4c9891e7,5559d993,536fec73,a433006f,4f0e4e42,f427300f,7a3825df,85b1cd9a,7463ce1b,9f9af66d,7a5d2d43,ab0f09ed,186eb132,92c75431,ccee645,4280aa2a) -,S(a89fcff0,694ed82d,537399eb,b59a054f,f43eb74,f8e1fc95,be0c03c5,9889c931,3ef3c627,e3011b2f,38d596d0,8ded759f,fe30ffc,9db95356,4e01c8a0,2949ea1e) -,S(a8b3ef89,561da88d,ca9890d,5e4be652,8a4b8fe1,691d1522,54bcca43,1e7ed801,c86fc397,52254f61,88ee5128,4bd54347,8abe7390,c784b51b,6d41c947,5d58bada) -,S(6a2fd5db,da9093c,2f7c7ed8,9eeeec7e,efd7e759,eacc2946,5d1f3a15,baef5b42,8b71ac63,3886ef25,74e212a0,499c34e2,d2c7c1ee,b70fe7f4,38e08914,48395e4a) -,S(d33dada5,30626dc9,1d23d16a,620dbeb4,7551ca44,dd6c8b18,fbf136b3,1ae4e097,4161f6a7,8273ead4,443c93f8,2562a29,1dea1adc,d84ba0d3,75a997d0,f07d4ed0) -,S(53ef9ef5,731d9473,93e70829,bcac3396,3b7a597a,1f3c861d,401af7f7,fb1559d0,8654f8c3,63e53905,a4d1e2c4,378fc3b5,fd5ffe3d,e7fd3adb,399d883b,3d1b9e18) -,S(5f13c5af,6979832,da1bd43c,4b7df970,1ad837cd,e59d8f15,381858d6,6263b0a1,3b0ec16a,1024c902,666dca02,4649c110,2a17205b,e4ac20df,26ce5b92,8baf90c1) -,S(674b7de7,f65337a8,c66dbf23,2f86d6a4,feedabbb,b71e83dc,fd854926,86f14f86,e3961790,a662c6b3,70460e16,18ce3b6f,42bb6142,78fe9e2e,6bb1179,181c2aae) -,S(291eed8b,47c3e2f6,b3c2967f,76743708,5c460c5d,d5d6a75c,489dcf0b,4d98b8eb,e19a9d2a,72fa37e1,e10ec853,9c772565,c53e36e9,160651d,c2a8e364,db408ef8) -,S(e737a407,1bf4fbe4,ee5d3d74,7df3cb54,cca38f48,f977919,907deccc,7090ee3a,ac66d422,79441d73,2809d695,68f700a0,3fc5be05,8241da39,9be3a63f,8da16069) -,S(67fb1676,7c3231f3,428b39e7,bdd082d7,1194a51,ae99a7a3,6c113e87,d338712f,38c2ae1f,afb521f2,279aae5b,6ba5c636,1dd34c04,a7726555,acb9265d,31c996f8) -,S(9b3b4788,71bc413c,5e9d2b9c,61e0cda7,f2fb908b,805f3370,45639,5e616230,7028b68e,af818a13,d32f116a,aeb0bf45,215d3d62,6e6ccb1e,a901544,ef1d696e) -,S(63193415,59bb1e39,2f92dad6,e5f8576f,7f49d4d1,439f4f61,a6f2be0a,75bd99e6,259d5f21,6c780a8a,5bba3e66,2242f26f,1adef829,a535dd97,11f8e786,f0a57932) -,S(4163082b,7720a8eb,e881b398,dae059ff,3a65fba7,f8b93afb,6e3dae6,6a969c79,3939395,d8e90807,e77e87a7,4c89f861,c689de81,a37caf6c,32788310,7b938ffc) -,S(b3a6baad,15c01677,ad6bed54,ea5ee415,4d0bcb7e,3ce59f17,7ff26,ef23b82b,711681f2,1e56c0c5,f2c2b011,dcf75716,300e305c,110f4071,51d11890,25bc4760) -,S(9011d111,fcebd882,b9a228da,fdee1297,824c4007,7d5ad9bd,59e603b,43be8f52,d530102e,aac87930,eff135f2,e55b5310,7c03ea00,d24f1201,6653e3e5,5d778246) -,S(d50adaf1,d68a746,e1e7b148,7660e90c,f268450b,df460d52,e1f761ab,bf7018df,4ed454c4,5eb30cd6,e6f1c4d8,7df2bea,e15ebc07,e4b4e50a,e4dea733,93abcf8c) -,S(cf886295,d1eca9f3,4c95acfa,b86a5061,82e30324,ba5b495c,70318cf7,9e910d70,59bb7068,3147c26e,45c76e7b,e018e467,1f47f488,2c044484,62a5053,8023fd40) -,S(38723d58,ffc69ea0,9a8f2655,dc225da3,78b9224a,f8d81e7a,bf8f29ee,292ddd24,c41d67bb,e699e504,3198adb8,ff11a5e0,4033b66,98d3ec18,256bab11,93db5535) -,S(5b41d5f8,1e2443db,d13521e6,e7b7fdf2,4a226cce,f369279,22b353ef,107f759d,8ad730a5,bfb9f01f,853434b,24866a49,912fc756,e086e781,a07ff2e7,98ef38d3) -,S(4f3c24c7,7dc7e41,843e9018,400d3bc7,5d1dc958,2895c11d,3855b80f,4709373d,a485adae,c547a5a4,e0695913,c4c2fb5d,ea16a3c,5211c162,4819d704,5b0d8d6b) -,S(f603e0c2,8b40c8b0,a6a0378b,c4289059,5a4cf4c9,2b74199a,4e4e231f,a6b458a6,a73aa12d,76572041,f01c33ea,ca599a30,9ba0b838,f1d67fd,67a9a5d5,c3ffe258) -,S(84ef0a98,229c7af,9404cc25,60f4fe1b,4c8e66d9,1aa96118,53fc4f25,eac78a61,653df937,3640b28b,2c2c4061,1d79c4c4,a2d577af,b572f5f9,e50cf3fd,2b2dbcd5) -,S(e675d998,6b3bcd4a,d098ec95,c386be9b,4e96e448,ce6c9371,15c5dedf,d97941b6,4319799e,c4103d65,18590091,e333cd58,9901b020,a62565b7,f84219bf,e31003fb) -,S(10837b33,3603f33b,e528f391,b5b672c8,93fbd813,99c5dfea,f6126e6c,2a2633bd,cdee9534,2456a261,8a293b49,d91ed2ae,f620addb,ed83fc66,d169da3a,a6d0e2f6) -,S(4cb1ddb6,6ad3c1b,68c6b0ea,408ba1d7,dafdbe54,89c22d47,7a62dcc7,77a8e013,6c005484,29e789f7,5c34d8cd,a473270d,75eb8f1c,3db13856,87cda96e,5cd4b370) -,S(db72d671,ff3e0102,b1c52481,b66ea142,8f7fcd43,15e2792,eae234a9,291926e6,71c55f71,68a088f9,980bdb6b,79b052d7,4edd0b19,7ab7359d,9a2f9ce9,f1c5a5d9) -,S(99f92125,162e18ce,7493e6e3,91cd06fd,681371b3,2e147ab0,24ae3799,15f586d3,9286b3de,12ee578a,12ded341,75bdb712,d939b7e5,555e86c1,82f1f283,3c1b1d40) -,S(a2b8b63c,8984a666,2b09c18d,b2d7f263,796660f4,3bd78eaf,af7c63b,986c92d9,2003787b,2af02879,642b0a2c,f716f4d5,85dac86f,e58c7d41,d1959763,310a67e1) -,S(9292ef40,21bbe6dd,8c26a862,c9b7da54,4292e479,a9e89264,618e3a47,9773b446,d1a51e4,65bdfdd0,dbf74fd3,d449f6bb,ea862eed,ad369c52,34a695f1,d229ead2) -,S(8d5a920,547d838f,90159068,ceeab220,cc6aa126,d423edd0,2e136cc0,1cea5d4,c3334a69,f7694e9,43ccb182,2caf2abf,f4caa83b,a006af52,bc010bab,8710b596) -,S(7b62f4a7,7b79c09,76dd2f74,4ec08d9d,21511fa0,7891ff5c,52b8dfa4,ae3430bc,70ab2073,cb3a7cea,350e6aed,dd0c9a6c,ff8e02eb,69bd14a8,a09e9b8e,ccb19a0a) -,S(e18a9c02,5829b47,cdd34c11,f97f2edb,a7fb9b9d,fa4777a6,dbdc3cd6,85245b12,7386fa51,881fe49a,adbd5327,8d6cd0c5,1063dab0,aa830b7d,88c7a4d7,9998e743) -,S(ab9b68ad,61335dea,767c763e,3294d414,74a6d4ce,e4ab9a78,7fbb6749,7307d0f,aab48fbf,53f365ad,bf94f823,ea973a25,f6ddd341,397bd81f,8e825f60,c916852b) -,S(3412531e,8423364d,8d8bac05,bb78973d,7b8d375a,9e52d81e,bed48027,2abdedeb,1b9f5eae,59ea3385,9de752f5,db973a86,4c735e69,fa8882ec,e1ca8350,77d77335) -,S(6a6425bb,af9f65d0,1a401330,46053b50,7ac8d45a,77b30de3,69eed52b,956799b0,7cbdae81,93368c60,5671ae9,faead4ca,2887bd8,9a06062b,dd6707fe,f849f484) -,S(87860648,af9ffbad,50871c2f,29bce0b3,e9693835,8a067201,5c1156a6,7107a4cf,8660c0d8,f1aea58a,c613f6f3,5b27baf5,53835493,fbc0e203,f024ee36,27bbfa53) -,S(35733610,71c55057,5392c685,3cadd8a3,6618443,d80b3625,53a2f197,d3c52539,42935628,adab5bd4,e0aad0dd,a7d76627,58524b2f,34ded1cc,d3e44249,6d213630) -,S(82d21949,2fd48d51,65bea027,6ac15cf5,d27bd736,45e03271,24f0f689,8a2f4a25,f13d9063,fed02a94,1b4e5c67,f42d82b5,33f18ff9,ca4622f6,79c6aabc,ea454c21) -,S(ba1a1c83,6dabf825,e517ff65,549e1d5e,729944a1,d7b17cea,aa4466ac,39ec6eba,f01dd751,3557249,d2fb224b,40ea19e0,57b4052e,adc46787,af587ad1,458bb4f0) -,S(5cfeac36,6bbe58d8,45a36cd7,de6601c8,56943a07,522364b2,23a1718e,6df8de8a,6651d3d5,a344af69,25fe039,c9e29e77,95544b96,66752f4f,c9a3bb57,c5586c32) -,S(e5e314fa,2b2bb630,6fc235ba,cfd356ae,bbf88bf7,eb039629,165d8651,c0c7d5ff,c727787b,a63cddb8,feef96b0,2f6c8d0c,9722fb4c,6274e034,32d9016a,eb4d8cb6) -,S(f84d8db4,b745cfc0,bad4844c,b5a28d7c,80ed5fe,6baefda4,1d9cff9c,158c7ec1,cbd7bc36,a8313a27,feb8121f,a8847bd7,937fa53a,d56ea066,fa600411,d87dcad8) -,S(8806a2b9,d72156ee,4948e86d,43f4b3ac,cb24529,e1b2b2f3,5ff94812,e9534513,aff42464,773f6535,b4dc5eb7,76a3f7b0,7bc2fdce,1413587f,c4055cc5,afca3129) -,S(e2ddb5ef,a1105437,b6107305,bc715e55,ec0266aa,a0ba1bcb,e12ab801,45af7eb2,43e4d056,804f229d,da5a1efa,8f429189,6c9edf94,fba505f3,1f22b511,8b698ba9) -,S(636f32ff,ea843368,c0cb708f,43841ef3,20151e39,35683ebd,bb1f476e,af2f8c5d,7fd53321,517616c,c7d24b51,851bede6,b03c50d9,82269773,dd51e36e,4898365d) -,S(bbcdd1f,f5b47391,d728a06d,b4783d5,b0e279cc,107488de,44446e36,9d11d143,6ac7dfc6,47d25b37,7281abf9,ead782a,b5f815d7,b2c9f6a8,46a8a6eb,9253014e) -,S(af0ed949,22336a4,337e9c01,53357e02,3d7a2728,3c649712,3e117944,39ed3577,d8b9c03,958dfa89,ec2105b1,d9542d68,568797e3,7df16cc3,861627f,298f3359) -,S(11ba75ae,db365552,b0d3f938,f03a115a,544a0818,b2f54f50,e4873249,6f80ce13,a6bce69c,f9838317,70f70370,7073e87c,61b65c0d,bfd34dea,f0c549f9,c58e674f) -,S(e7560fb5,79e5ca35,f45881db,b05383f4,c5536ea8,a5438fc4,ec198ba8,7543d3ad,ff48d1a0,bcf5e510,9ed50a0d,ed8e5b83,44da25e1,a1a3d421,606d19f7,e28fe79d) -,S(ce7e289c,61f4927b,bf933eb5,193fd2a3,a0686435,80c8f235,1e24c33c,e418cf10,17246f2e,e87f4ce,f1c8596a,ecdb1f95,1407ee7f,dd839c9,98102344,2f4dcbcf) -,S(b765b875,32ba4db1,211c612f,b833ba18,156fa0dd,875aa61,df1ba9b4,7d1c405d,862d28f6,d85a8ad3,bebfbc82,437404f5,2e0abafc,64369b51,b75364cd,c827171) -,S(400560bf,d2863ea,2bd9e246,4eafab2c,2798cb95,b976c022,bb9d2153,e5978a0,92ca9a1d,938e53d5,d10f1f83,54abe43c,e8f8c2c9,d4e851cc,a363ed59,71e2681) -,S(7859190b,8e619c98,76af21e9,64f323e5,221cd4c8,83dd9fdd,e56f691e,e3db91a2,e1874376,755165c3,72abd73e,415f2663,bd94cf28,2009492a,e5034da8,6f6bf949) -,S(87d90b40,bb472b84,f9d24caf,ba7a6437,b50febd9,5c643aaf,e235750b,12527ef6,e6a0f719,25697425,23517ea6,183faa64,dee1ef63,183ab1e8,3a603b98,20452c4e) -,S(dbae1ee5,a1b6affd,f9b41ff6,a1f2790b,2c492ce7,53865690,ce5281e,a7f08177,f6a2be90,a2c3cf,8e14bf87,4cc52648,b60f9a26,2930f6e8,9fadad4f,d919db6a) -,S(943a79cd,88260475,10d90c99,4d8d784b,32c03d1f,f2478102,96125f7b,28576216,48d4477b,f97c4cbb,4a96ff99,e427d4ac,cda9a367,2ae66930,88d8cc57,3bb3e2d7) -,S(699911a3,81ff3c7e,71b3a458,14133f3c,ec644378,e3244d66,6d083c55,7b6c040d,3eec684,3190d6f3,85b07116,b3b1ba15,4ecacec0,63e02933,9b83afad,5598b22a) -,S(f002302d,9ca256e5,cc38ad82,e529b461,efb69f28,52513917,fb8d63df,45e602ba,78455ea9,708b750a,97dc74ec,8939c880,d76010d6,78e0c112,3616483b,fb4e788f) -,S(5f701ce9,65a20314,a65e2c0e,1cedded9,ddfc9d01,41a1e095,e91b9915,cd2aacb1,57e770f2,d04e33ff,c9d7807a,4c3d1edb,3f9ed2,c19771d6,7e85e618,463e5663) -,S(454c122a,ff85c42e,49d6f033,87744462,8acfed31,90c41255,e8e34928,83563fcb,9d9d6435,a2c4d146,d92f34cc,40b32a7e,55584885,82143a,52039fd7,129fa6f6) -,S(d9abd19e,81f392d8,8382918d,6ab3f89d,de793abe,2eba3aa7,b58b0ca3,1e614e51,8c1a0f80,8b8d9e56,aed21554,95f8902e,a390505e,15cafbc4,2b71cf05,575abeec) -,S(20779414,b5ed6524,b3613a8c,d0b6e9c7,ff3b14b7,7264cb8d,7b266ef6,cbb224b7,c1437dd7,71f46cc4,3cfa52a1,28c70367,d6682553,28942150,c4068da4,8c218d66) -,S(141739f8,503f2225,feb40431,21f0a5ee,844a7707,62e37d1b,3e43fad0,81c631b5,a0a13de0,10566ee3,1af8c6e6,38411c1c,a3df6c63,c8ed67da,8ef7bd19,5fd6e73f) -,S(de8d06ae,dd58b148,91184145,fcd9bc64,634725fa,e4a77d35,70b21c8b,77890b60,a046f351,eccab99,1d3d1c1c,642387fb,fb9c3f92,75bbb93,46688555,f7aa9460) -,S(312c7ad1,53f7280a,9bb86cab,ac573944,d271bcfe,bd59291,c6f05fe4,ec003a81,3c6428db,5eea01c6,9fa2556b,1f20c1e7,4e65629b,e73e6429,81b971ad,b6563866) -,S(2eafa04b,d276e33,75b8d063,b206785c,ed69f763,7a5a8b99,ef7d3de,bbcaf35,f06464db,56ccf55a,1f41efe4,d1cedf81,a642da24,3cbe68eb,6ddf7ace,f67dac6d) -,S(5873091e,dcc8a95c,a0a47570,3d88e54e,1381c2d7,a418f615,eea97470,2c2c6fbb,5a91598,b8e47d2b,2fee6cdd,c33aa309,9bec74dd,21688542,9b76543a,c233ccdd) -,S(e713bd84,ca505ad3,aa022577,c0cac85b,466874a5,b02f4ab9,e8d14bba,c131fcb,706dab4a,fe49e6cf,d290913d,358d1dcf,62e8b4d5,b9bd46a,322ee4a6,5a660849) -,S(aacaa633,6fe86d41,b05feec1,cf4866d,340fd268,f869f912,c2373e10,bcd95340,d933cc5e,c01024e4,77d1e80e,c533f293,e4fd0dcf,7d1156b8,7ebd9d81,b9489c57) -,S(cbe0ce9c,77649031,25590e03,cd9643b5,dc45ecc,604d51fa,d5bcb8a,196b65ee,d2287fed,c331d56f,e585bf1b,793fd957,ce425492,df41d8b3,4faf84de,c3bf4d22) -,S(f9990413,deca9f9a,4ea6bb8,fd9b8732,57d15ec3,70e98187,f4170103,dd416dfd,b0593cb5,dbce573c,f0a75f2b,c4756781,963e1a2,e988e0cb,23efbe26,c215ace7) -,S(2ee21d79,bf3e82a6,2bcaef34,85276c5,3b51bfd8,becbc9f9,6ad316f3,a74bab97,fe3cfa79,b208de80,f659cb81,bed12184,ea2c2524,dc0bea05,64acefab,1acd8fb1) -,S(af5c91d3,44fccd3e,70345a2b,ccefc0d2,19287be5,aca40ebe,e61de522,56f25faf,bb58da83,bebb5346,9b345695,fc23853c,bc0221b8,5d75ced1,da107fc5,c106875c) -,S(2cf50e13,477d628d,117e0bb6,1d3ff9e6,1108fe94,bf82a6f2,4138a743,6077e0af,339c0a53,77a6465b,29377e1b,dc344464,875687e2,7d1f392d,96a275a,e259793) -,S(c51a6610,1522f63b,84b98ec9,31984865,eb3b29ce,fe115b28,a87f89c,67bc441a,240b9717,6af4beb4,b0502d7b,2caf8c7f,47a9362a,9f9610c5,826762ea,a2a2be5a) -,S(27478eb7,b14d84b0,80426792,b0e2e510,8a4804e3,a15e80b9,c430d7df,c09d05ce,eaa0a072,86fac65f,3da47bfb,4010fed0,fe8a9e17,ae42ece9,233c2078,2b36422d) -,S(531ca72,e21caa6a,43f0c9bd,d0bbca5a,b12dfb9f,70f045b2,f0865077,cdde192b,c4ed88b1,a0397589,3cb14ed0,897d6bd,783dc647,ba59772,16c308eb,630367e8) -,S(295775cd,950d0702,602278a1,56c1d05e,4343474,a4b3ae87,63f4a686,7688e42a,907fa8f,1269cb64,41591004,f6e62b14,4d6c54b5,f6ed424d,6b0a8a75,26935b49) -,S(e88425d8,bf6e89a0,f9c9f525,97eedd4,3c331058,10936c23,4da69d21,9a86f82,56d53ae5,e7a354d0,d65cf742,d603da2b,199e147,3d42bf3d,639f83a1,cf91cb65) -,S(4d20a032,c44453f7,b374a82f,f088d816,c1fa9338,57dae8c7,b87295,98869a4e,a7ad5993,af43cd42,1620e87f,fa0b3305,e7da39ef,704319f,ae5faf55,5e3fb43c) -,S(b98e9728,e9288607,a7ed6df9,c68749e3,9d7efa1c,4f964428,5e9bf81e,246e936c,1620c470,19b9cef8,7c1f0612,cf56adfb,5526573c,f7746a98,48a0d40a,3a92d38b) -,S(562eb109,e9988778,bed85413,2fa7d086,6b37a8b,fa2d2d3,470da3c6,97996a48,29f4f0da,e554e380,613156e3,34207e6,fe8fa678,4c08f2be,c3d6a59d,1e0941b1) -,S(b189e864,8dc0ee06,b09ea73a,9a01cc06,b6fa74dc,f626e41c,ffad926b,901ae851,4e42c870,3d04838a,9f0682fb,bc13c849,a515d5f2,f248f393,e2caf0c9,b6d61d0c) -,S(3894cdb3,425c618e,1da2c6bd,1177109c,49362a4f,24030692,244bb0dc,27af6913,20c0021,5c72939a,497f08f0,bdb03493,8d04ddd4,8fe8f3f2,97dfef19,ec9397c5) -,S(394f74a9,9146fd43,9035266b,ccee72e9,36ff59cb,eab7bf4e,925c6363,fce7d4f0,c7da15cb,c1cdcea3,21efb1fd,c56bb3d1,2bda06b9,993b6f5b,2293e493,5aa3e5a) -,S(44fc66ca,d6e67f97,be95c667,fd5dfdfe,dc82edba,35df2bf4,737b3ba4,14d15c27,9c485757,351825c5,245c6eab,2ec4a51b,ac60c9db,fff7988d,8f28728e,60f418d) -,S(fa355672,d9f7a1c5,30b2d76,f183720f,e50840cc,ba413b64,e449d2a,8b0518dc,63fe1c7f,d97c7744,35613167,660926e3,b7377fd5,97dad03c,9debba5c,a5a76e3) -,S(7325c269,50f1bf21,2f9cff6a,170e446e,62dafc2c,f05dc50,4eb951d2,6322eefa,5f8fa04f,ac5232b6,cb553630,5a48b647,263a57d1,2c485363,6c930497,40965f00) -,S(7004b364,c89ac7ba,ad03a03c,c8e2972,e5fc52c,bc656165,e08df216,afa216c2,971a4284,80556797,ebea8b1c,b37de6a4,1aa11abb,df9b28b7,7f50d362,b6554974) -,S(ffd45087,eb9308fe,e7644817,9406d9b9,77364732,f3570ebe,80a4710d,a0ef292f,f4ae4df0,5af2ee0e,456cca0a,2c9d93a0,83eb9751,a09c2f8c,5bcefce7,83764ffc) -,S(ad899e8b,a7aedce9,e53d86ac,5ca15408,140c8f1d,be3ba4a4,275f332f,b0320572,a914795,bfd9850a,24251eda,98bced8f,2e2627a7,8a1bf6e2,8b66ffec,f11ea105) -,S(7078718d,e94255ff,ae25f1df,4ec2ad90,e59ada11,5ad4a6dc,8b305fcb,93a1114f,ee736453,927cd7ed,bbb55010,32eaa95c,c0f6bb42,be77db4d,62b77650,1094ed7e) -,S(30858d4c,d39abb36,51b8d35,58800c18,5495bf31,bf23dc8b,176c1f04,171e304b,3aad8415,4abdfbb9,1eb95aa8,4e7ace9b,fd8b5f6f,cc8ea08b,e094c874,8161f85a) -,S(c06d6d2e,5637fd7f,df08b41e,5573478b,eb19dded,ead1f0c2,9309fd59,9551c787,78cb2514,37d4ca62,91bab9c5,57e88244,edb9dc30,fb1a6441,78217039,628e1db2) -,S(2f93455c,279d2a26,1cc7b724,4c32c853,459e5d99,32692fd8,ffe7ff0e,493de2c2,455f0902,74d698dd,a1a97586,fe797421,899f7c22,60ef0bbd,db0664e8,fa323156) -,S(c00c345b,b4b53f5a,5dbc5f10,597dbad0,75e28162,32e0ac71,fd778c50,20b663d5,c30f78de,3495063e,ab98f001,83fb4bb5,5cbf58a9,1bd52ea5,36a4a38b,cfe89288) -,S(7d78faed,f86a22b0,14e86e1d,f98d425c,fe2e65a2,39b37994,ab25a4d8,5c863382,cffee7d6,5181e361,679c9d51,feff7a36,e8d84282,32e752b9,62689eef,a1ff4441) -,S(ab492cb1,da2e8463,a2536c0c,7cf143a5,9626497b,23d4c179,d2af4cc7,f2b55866,11d4205f,55a74f81,e9512496,becb61c4,6363c42d,baede671,9bd7f2f9,3e00b14d) -,S(d1a3790b,478bf657,360b3459,555e1dc4,ece339d6,93b5b51c,8a3af121,79578688,c6028991,3ea89956,802f8b8e,cfc8dbc3,5894846d,1aba2074,9a55153b,83f73891) -,S(6fbb6fcd,36fe0388,a4bb648c,95a004f9,b3c64e4f,9aad672b,42d8c649,4c0cef3e,51be473c,74ca2609,c3b79c60,2fe90d98,62eb9d14,b9e52aa9,ddde106f,7253da44) -,S(db150ec5,680299af,681ce826,794e4818,c0d6d3d,e3c392e2,79ecb408,aa55b243,15e47cbc,1c4689bf,fbf7ef42,1db5c57b,e3ab8c16,b69bb518,2ed8a1cf,20067de8) -,S(51ffc919,afe67f04,a889323f,4438da99,72d2161a,54f9e81f,aa1e644e,9cb88835,e4b579b7,e985b38b,486d0600,3f825538,52a9d0ca,b8fc98d4,371a7e33,4898742b) -,S(fc86c54a,48052ae8,d8480235,e4dbb7a7,6d05d830,d2c0cbbd,297db0cf,3d2d6cea,6cd61522,e2a22531,da973c1f,9cca1c77,98ff66a3,8f568935,e378f73f,9f1d7dc3) -,S(d440de01,20d619b0,6add3d7f,66184864,5754a424,f4b1054,479a83bc,7df0db9f,3f09b245,91124175,89071c56,84215cde,a6999b17,b5b2f664,6074e7ec,6c38f68e) -,S(f3310bc7,7556f234,e7c83d69,48afebf0,5bd91a25,b516cf84,60d0d6ec,8483fefa,1d10f23c,e0e35816,6b817553,cbae0792,9e34a4a6,ebb47186,1d401341,1ef2b3e3) -,S(ea770a59,e88b598d,493fc75c,62eaa9e7,485271dc,edeb1d2f,76df983e,54cbb51c,e2a4baac,96c9538,3de82a29,5bf3cf30,53bfe2e4,6fb0861d,65c60c09,978601f) -,S(2cd56ef8,6fd04d2a,ed4f8520,951798c2,a1c69a38,8e635a2c,edfeb08e,3af0e331,3b9de80c,42e0c683,85aecbd9,c8775b56,86a8a376,39efd24,98664343,e712707f) -,S(37bb0206,c96d8fd4,5315e96c,860f5cb4,a44d2b6d,af17844,bc305b4b,59c9c649,c77b4a05,373c42e4,e071090a,7da9b4a,4ccbbeaf,d399496d,f6fea1d1,a83808b1) -,S(55fa08fb,f83dab6e,ea7034db,15bbddc0,ab2b472a,b29861af,543a970e,d16033ff,73c8a90a,86542970,4e25f370,a5caa4b,a68eb72f,5ede1edc,5549105,491858cd) -,S(4eafb675,281fe8,98593817,efe128ca,c59fb775,82f6006f,339631e0,6e7d2e7f,41347946,6630f6d3,9fa97404,6808067f,fca9e173,3e1c4149,6567eacf,47a0bc6) -,S(857587d8,375f24f9,e6924793,9ddf3a60,e0469f38,6ea0d55,d990f1e8,4ba5c7dc,1913a118,9d867c57,2f947fb4,3e062cec,3df37c3,e8edc6b1,927b315d,10c37be3) -,S(89e334d8,f71eacef,6cdd0a87,b1e03352,1078a1fd,20dff144,10108202,93143815,8b49aebe,71b60eca,c9256794,3cf74d9,80bb3e47,161b2730,9ed15872,7accd84c) -,S(69902d6,8a4ecb1,d2e496e8,cdaebf94,58f71f94,8f4341a4,11fbc2dc,524f694a,19a54c4a,5de17930,6c50cc03,b0b8d54,b613cd31,6f0bdfb7,851db63a,9c605896) -,S(52f8a3bc,832de46,1bade518,50121b5d,2ff475ab,5eb0e71b,a91ede46,41f0d576,2a946bc4,42f24ef9,469b8121,31021186,5b22f3a,adf93648,5b7907e4,791236e2) -,S(146fc341,4ca1c497,73734f6b,b78ee9e,56fedee4,9487ea01,a31d3e4c,152d2bf,82e21722,e415f5a4,1a076f3a,8324db4,2436da5,a3776f60,b5c6f53d,e5419db9) -,S(9e22043,8458e463,b1bd7399,28200a4f,ef7c3760,a7b6357e,afc29a5e,36b37b94,b1f5fd78,c1c40d98,1473fd4e,72af64d7,7387c28b,7f005191,5ed2587,674877a1) -,S(53190555,8d044a1b,94caad4,526cbed1,82807c65,2bb053d7,61301ab9,68323f1d,ce591f2d,61b47a8f,8707d8f6,a8717139,68ad569a,667ba4ac,f2d18356,ab6d326f) -,S(b93b3c6b,1297cadc,392b0cab,da322a1f,69791a68,b48b0ce7,4352ba3b,b8a3cc8a,136ec007,24fd378a,53d5c573,3aa7a06,15b2fb20,4fed82ea,934bc131,7e7ef22) -,S(62e6af72,a9fcc956,4367d44,c0699897,3674e3f7,b79c67bb,8c8a82f1,6d3f744,4c1e4e33,2e9316ff,24a7b38d,13ed1b30,a659a8d1,8423db6a,af6324f9,4e7d5475) -,S(c91facca,aad0790,886c4421,d28f3ce2,9d64dc87,514f06d,cfe95063,dbbd0e3b,e7a0c83a,18d655d9,7a555c51,4bf8f117,59ce866c,61a7e691,8ecb1cfc,21e50710) -,S(72b3b928,bea91ce8,767b2f22,958458ab,9a23f455,78f836,65c89717,7e7ea502,773235f2,c9ec74e1,c06e4e7f,89247d12,27f303ff,2fa354a0,663791a6,ffa40e49) -,S(1b014ac2,7213cc08,67877fa3,c0c07b1d,91529259,23f6164c,f1d204d9,addd6f4e,e0dec57a,c1ec264e,380909bc,c62394c7,413cfd48,180b1de1,c5440d08,99c67f2a) -,S(985e8845,97e2831c,4ba48888,ac219b3,bd891dc,63176953,4e0d8a96,bf583a83,5afa0b31,1e909594,4b228958,657b95dc,a198b008,6f5cda96,c3e4da6d,e444a418) -,S(ec3cded4,cce88ac6,22315a51,ec99ed3,1ba2cb32,74a43e6,98e033d4,e490bae,1c2a2236,2704a765,252b2a57,aa1ecaa5,4f1c21a5,2d67c050,a3dba077,ad4b4480) -,S(f882c4f7,7911f6e8,64da7cb0,5f09da54,b9cf7125,21504815,e6fdb9e5,73f24be6,9ba4a4c1,e0978ee6,1f83aedc,b1db2193,518a71d0,c112b9fa,59c629cd,d42ebde2) -,S(f06c3a4a,9f1e80cb,e2ee6b06,ff50e447,13d8eddd,5857243c,cd02c5d2,7996eac6,6b38bddf,fccb4888,da20ce7e,495bac5e,7b9ec8b2,2feaff5,8d4329c3,c546e839) -,S(dd1c366d,5be82883,eb86da5a,f9b5d5b2,89de6b9,1165b91c,20ad7b73,ab4de421,19bb181,70b31a81,45232ba7,ed0fa93c,273751f4,838633f3,c94647e2,93c06bc0) -,S(e965c1f6,89b3f7a5,97d23d9f,378b9a03,fb1c6e29,5354de36,a5bfed53,3338372e,d98295bd,890e98a5,9d6dd93d,bd9eca2e,e79b028c,7459779c,2d3fb665,46692242) -,S(4f9148b6,cf21f5fd,911d7fb0,e92132d4,686d3e10,12da444b,f5a89040,69c2fcaf,60e9b3ef,924260db,ad68793a,d684c316,6889b0d0,38474c70,6ca25978,4a5fa7ad) -,S(d9341e6,6a505a91,dcefd533,90abbd54,52b39594,42deef9f,6a67dac0,8faa5e00,eafdc1b5,2b7c97f2,21ba8635,d49b58fd,17cc7983,92e09d13,8c41d679,6fda331) -,S(b948bed3,4f426bbc,e6c24ca1,fd1d2092,1de6f9d9,f561c32f,877a4104,afe81ae6,5cacf40d,f6fba19d,763c5b0b,83aaa284,f9485705,ad882b6,d51bd46c,b12f532e) -,S(73011c97,dbeaca8,8bf04371,311e9558,1e494b73,1778a2f3,cf906cdf,64dd781f,2b5abb31,c2e56a38,e8236f7f,b28a93ec,1bef3fc8,9be46d92,c2fc476c,42ff4ed9) -,S(44835043,1373a095,13f756e7,36ac8342,24004348,70d6cc5d,ba31f74d,565056ce,748f041b,a9c990b7,70c36f68,5667109a,acdad74d,4569b107,c968e517,143499ae) -,S(3463b029,e9dd1907,bba2b582,c9ff1f26,4a5ef4b,40f5af28,2a00c136,97145ffd,9e30bb18,fbb70c1c,edff9065,968523af,33665b53,3f14457f,59d7edbb,d5f07c5c) -,S(5d95aa9a,9fc67758,56e6655c,21a62670,c567e236,a41b523,436beb2c,18e69c97,d6478496,4220cd62,b4651e8f,965bbde3,22aeacc0,6557f656,764a20e4,649a1ea5) -,S(48c65239,d03715f5,71ddc36f,313a1723,b014c047,30cbbd8b,ca9617b,e8fb3874,c0bd39e6,3cc00fde,74c991cf,f6d711a5,356b029,5b6eb9c0,28c445af,21de8325) -,S(67c610ba,fda8dfe6,c7977b70,7a57ebd3,9654c7d4,c9a0aef2,80c896e0,e8134078,c3d4ffc9,891a4267,612aefe9,6c1093f7,8e1b9a58,746c986,c5265381,3ba46aef) -,S(4605213f,4a21b15a,4a471e10,f157d0c3,faebaf0a,f7cd05c5,a27c56c1,88b6d430,9853c145,5f4b3d38,200aebf9,d08f87ae,3eb4a99a,3d94ace2,94331e03,876fb751) -,S(6277ce5d,fb56c2fe,3d32e28d,6754255a,ecece179,70615443,b0d33e5e,b54e475e,dc7a742f,92160074,69d53e73,da526102,a6f68e7f,e8f07a91,98614f0c,17daf06c) -,S(7fbc032a,fdb50898,3270249c,f1a7d27d,198432c1,6815b7d2,c929ab67,bf12f01a,dd696a37,fbc4f852,6db85ca0,6bb498e8,6dc33480,a4f84564,2b49775a,6bf20ae) -,S(dc849e28,6b934ef,30cab6c0,1cffaed6,9ea74ab6,96578027,4c88845b,8ac264f1,6d7f94ae,347b9b18,bfa2bc0,d6b9a8c1,13ef1a70,78e317a2,53f21590,667f4b5d) -,S(e29e0833,7da9e0b6,b6886c7d,fe010cd8,9a4b10c6,f5e4ce38,c1202f59,94a69016,de082f4a,9c21db41,573dde9,d2ca8256,57c67173,207d43ef,e42ea81a,ee812dbe) -,S(407f0e21,ddccb63b,5672eb15,742d72f7,1a522f9,20d04247,3e1438e3,7bdecd35,28d6f39c,cfb36986,351d7619,daba6271,3c9869f9,357504d3,25c112bb,74ad336e) -,S(653286df,15bf657f,1685bb92,98462383,7c819def,84a8c332,77f6d777,4c8dd3b3,c5ea3d4e,f7a97324,96a98abe,f999c25,9a8c622c,944a099e,146c0708,d108eb34) -,S(47613ca6,ca7fe67f,4286f12d,3b4bcd86,455a1863,94f2bfca,e162f991,3bf6ed7f,4409a6d6,2ae63ffa,a3f2be74,e7d0e5e,3ad4704,76282b0,c2919750,72be1386) -,S(8f9bf4cb,4aee791,12162fff,75f35393,509fcd4d,aada298,655bd58f,567e6adb,893c8b52,c2c25f8,e2ea051e,d1a35a3c,8ddbbf9f,508ac792,37e53143,7818102f) -,S(4b25cee4,2f955db9,79c85682,4dae806a,3925a33c,42e6b6b6,ab4997bd,884f68b1,ebe38f45,bfa13922,d3112af9,1324f526,1c5f864f,4d722576,24e3afe9,9eb7ebd8) -,S(a8a40ca0,56b5e168,6fb9a348,ae26b15b,cf812cc5,b9c5abc3,44f86021,69958e81,a55421a9,4f1fda1a,f6d64e48,cee3e4a3,434293d6,b49a5cde,b521c0de,49cd31cd) -,S(1f7e97c6,198e27a6,48ffebcb,55c001f0,d591ca64,77c7c1f9,43928e2d,dbe88dfe,2dcf0a3f,f296f744,dd402fd2,48d29c96,49abc871,28624da,28134cf7,6242e6d2) -,S(7ee29348,7d6520a5,586b3ba7,4a0a660a,a4392e5b,77529e8b,890a5927,aad1ab71,a51d3123,b4faabc3,77bcc565,d66d4c40,92decf92,f63f81d2,ba3a4f06,2a8ea485) -,S(30880ed,b4f5f2d0,95c34730,d10a8c02,11efdf6,784b4886,4afff98c,407734fe,4ca4b106,41c55905,9a19cbaa,bc6837b5,300aa1c9,8b0d8a72,8caf5cd2,914ea693) -,S(bb7ffe45,b725038b,597a20e2,6f67d0fa,c77730e2,4ebadc9a,23afb4ef,a01b4d50,dcfbe717,46bc35b9,81357857,c0b4564e,1ea11852,c5ed8372,bd15eb69,e674e14c) -,S(ddb59e25,20a5842c,62607d4c,6d31f2ed,b79e387,527dc12,5d96fd04,84385e51,2a167f97,85ee4285,7471c45,2c38639e,69940f77,b3fcd54c,a697100,37d9e5ef) -,S(3c405df1,36b1c6f9,99fe0b3,2bf5a305,bfa4a6e9,994a1506,9c5fcfc,318dacf5,ba5ab8fe,43a2de82,ce289cf1,2255f554,d7881d08,a54017f1,e0c84180,d963f3b8) -,S(ed4e6e9c,9d4eb277,73f2249c,13d6fc1c,5c07be47,9ca48e35,913f6fe8,384851a0,8242617e,36b3c298,b13aab58,b7383dd7,93ccd4d1,7787062e,195456ec,43fc4198) -,S(60fb7766,9f312be7,11d0a269,a72a85c,e06b70c8,1d34416f,f7ce1a28,41d50895,ba2097a9,772a616c,82cd5dc7,84585c80,65206913,474f49ef,71579a3f,8cc0d825) -,S(1336a678,bd5d495d,c688c039,a60b256,a09fc946,830fa80b,1622890d,9c8f0881,6d57f261,b1073b42,f6eeb514,58e994f4,7406b3f2,7245a0e7,528748fc,65a4937a) -,S(adb7e6dc,72c02a9,fb99645e,a3695824,db60df0b,f9b6a420,75cf02bc,4e3713ee,96325866,2a062180,20f8b86e,e5ef1e04,57d01fd6,d5541d6e,50798883,9f03b3c) -,S(674d6e5a,6501f824,87efd592,c37bc14a,ab596cec,4d5e6e8f,1be44a53,a9d2f416,e6ca1153,76af0429,1bc2dd6b,2c47a816,c17e0ad7,c252c1d,cdede8fd,c9a18630) -,S(ed73f5a7,93dd0359,68e253ba,8ac4f2ae,83d7f290,24eea4b6,fdc418e2,4b63dcdb,bf687b81,4691d48,5296e192,d5371ec,daa831ea,ce2d502,4e321add,b62f0faa) -,S(601cc630,47ce63d2,c1fbbc49,f3b2dbe5,6edbca09,17ac41e9,b39f7ac4,5cb3ff8,a773b9b6,d98c7b35,458e956f,f9cc71e0,8539b118,bc2529f0,fd496e54,efc2b25f) -,S(a31ffa07,e16fd36d,2edd7d1d,944ecdb8,2da2641e,cc6ccfe1,88219a67,5677a740,c2253d87,59ab43d7,c919710,9e9ecdae,df1f2d82,d34c5d82,d113958f,cbf1e3f) -,S(131060f1,ba302b06,b26360ad,de531db3,422a6bc9,6ca1e9e2,98b5da8a,c8266249,4dae16bd,40159bfc,96665d6a,d64c6c5,3ce90fe0,95a316a6,8cb84844,ec183cf9) -,S(f4a29fd7,90f35f1f,4b3240d6,c0cbb983,3e701a9b,ca241d3d,bb7630a6,da2de25a,b2ecd794,5afa51e0,1caf3c21,5334dd9e,9f9a1f6b,8f35767f,c63a3f00,69c01382) -,S(b30546b7,c5e45266,854b90ba,53afdab8,be115251,5ae22f1b,5e0c472b,a3b44042,f14a6b95,178fbb85,5aeb9cc3,a4e65560,3e8b18c1,4cc54cb4,1e059597,faad7f4) -,S(b6cbbb5,10ff83fb,c8bdd55f,cfafeae8,947f5e83,4cc78eef,dce45dee,2014e175,d0e29276,a14cfda6,f518a3fc,ac6a4163,13666f91,ce5ae7b9,7abfdff4,925cd415) -,S(fcaed74f,19199482,564ce4b0,7e1033ca,c17bd418,769981bb,6547caa3,b61bafd1,c52c08e,f5331ccc,271b108d,5e7794ee,4a493ce4,f6665773,f97902d6,ffcf40e0) -,S(c6d1ed83,29ade032,c9924945,189ff23a,c6b1befa,e4a33794,8b1b4126,6d14344d,6e1c0e9f,da231092,86d23cb3,2c588799,507368b8,8c0628de,b8a79c97,e4ba817f) -,S(ac7d0edb,a7b86cdb,60963277,cac43674,19dc5d85,ccd9a649,bd335dd5,eea2a9e2,61790bc0,ddf5307a,56fce870,4bc9eed6,9d61d857,f4d2fd34,d53a97f2,4c4c5206) -,S(fd9d0c61,d3dc3ff9,bc3735e2,b2c7d5d6,4a740b1a,bcd46a7a,860816f9,84a64645,701e082a,5e59460e,c3e3ca21,40137ed1,5bf9ef49,fb4673c7,4fa5e4ff,2ad8b762) -,S(82ce7d44,87101716,6ee31310,11bdf02b,336fe44c,88572c37,930a33ff,5bdcea1c,d7fdb097,3961ba18,b53b421b,21c0424b,7b4807ae,256d883e,2e3a6f22,9bc44c0b) -,S(5e507c80,bbd32e0b,efc31714,b464580e,f7ccd3a5,2004f2f1,9fb9b0f6,dad1a767,95facec8,a3b5c996,e0bc9d5f,77c11407,d0ee071b,9cf5af3d,ed625025,3aecc75b) -,S(640d6b4e,bde998b4,1bc86fbe,2e981683,a83789d,b71bca76,76715a29,143c9b55,61334a92,358ae235,104aca00,a632006b,769475a,da8789f4,f7047f75,c8b1123d) -,S(e951dbb6,96ceb16b,6059c3ec,9d84ae8b,8adb146f,fd79a323,59c04677,aff990e,d3443900,ea47be0e,10ea9178,3f1524f2,fe5c5720,efb62458,987dea0f,1612a94e) -,S(2b601b8a,550333aa,2a0e98c9,a4b28043,aa38f20b,13a72cb8,7a8cf212,cd0a2a92,2f3f309d,ff296fbb,a406602b,be72d9bb,c3ca0578,f5f0aa08,6e65ec0d,8989f670) -,S(d803b242,9814658d,df7cb378,bb9708ed,6ddd7270,ffb7d712,b64da007,158a5add,bffd353d,c4d664f8,6d7f150f,30e44ace,fef4abe3,83f30369,15b4d5d6,5ba3c131) -,S(d5a8348d,fbb9f9d5,798d7d1f,3515e25d,a2707869,26ae598d,500186d8,a284e86d,ce31c62,19960c61,f2a8a7bd,2fa36f0d,6ea7838,5463a4a2,9dc1ee95,2f37905) -,S(250dd67,781128de,65f0529a,11b2405b,eab01ee0,1e9bde06,cabcc9d3,cd038065,524aa9b5,8dc5c6e0,6951aa70,c4bfdffe,a2dae26c,1e8341a,5f63a180,731a0dcb) -,S(f3a2017,127dab2a,917dfaba,5eabb6da,bebe554,431e796f,a3b09771,66cd47ec,69d1de46,2e63beeb,1334fccd,ce147b96,23683942,21c4865c,d50fd687,5c1659c1) -,S(15626140,5aabf9f9,d7dfd218,3d7fe2c,900ee051,784537b8,deab8bcf,20c6e0e,863d8797,f2b20b0d,ca1a5b93,9a43a712,4d5f0725,8ae7caba,4b76d308,65f9a98b) -,S(3261fb49,2c55978b,20d2c5b2,3e6ac5d9,5e3b40a9,462b748c,62a41035,2efd227a,4072fb7e,3fafe456,8f62f4c9,83d0988f,f9096c14,317f7584,9fc1aed1,3e39708) -,S(2a5e6aaa,f5cd7466,b851802b,80305dff,3e655dd9,b0456bfc,fe704eb8,582836ac,2e3894d5,762e70d0,4d3595f8,83dbec7d,5125720,c516fcd,f361ab22,be67062d) -,S(e85a7e08,13294e2a,6eebb00d,2e3fdd76,318b7520,dc682705,8b3e923d,536cbcd7,5a936569,77b89e9f,10c4ba6b,7dcb1611,fb6a85fd,af0b1136,b19cf222,a2e9a477) -,S(8e36e66d,2f080ff2,a24ac836,25e50148,e5017b7d,b898820c,b7d73214,bc198b28,edf99b43,c2b976b1,6eda2a75,f8bf5aa8,6945d700,9965b528,bb78b530,3888c56d) -,S(99ead62e,11cc613f,2290332b,9d5ddb98,8c121ed5,21a0147,589bbfe7,db0f0c58,6e73b10d,bac646ab,44f3a062,4150da41,d666523f,ed55fdc1,c1146fd8,c4a262a7) -,S(15e233c4,783fced,39c74cb4,34e77491,83004e2,6e16c372,f6f7f23a,e30efb13,c9954660,eedf09c3,af8e1642,3b57af59,227ee5fc,e1885837,5ac5a853,34fc5034) -,S(3b33e0a1,254d310d,efbf526a,8a2314bf,18bb490f,e592e36f,6763b174,96f57a67,e4e6a395,a6e6c730,67fb2e0e,2c5dba63,9745daf8,bb9d6aab,e96f59d0,8eb24c83) -,S(8be3fe6,f3e45fda,270d54e6,49bdfa8c,1dbbecf6,35922aca,2d605c66,6933e859,10269847,15eddf7f,b7b23972,ed1f6fd6,882481f9,1a12eed7,f8fabad9,da0917c5) -,S(ae6863ae,e6d519be,773edc77,8e7bb5a7,5e0d30ca,91dd0920,aee35870,5bf6effc,d104a8c4,1939444a,1a5843e3,92fc5fa8,d2dd864c,1f442938,9dbdb543,415988b3) -,S(58a06c8c,658430fe,e03b3218,6ec051c1,18174f8b,ade2cfb4,a98cd9b8,13e12dc,17f4ba3,da575c84,81cdfc04,25567dd5,1d2b5e94,a8ed37cb,346f88fa,e6f3553c) -,S(cf0b0d64,3843e10f,142ff912,720373e7,2fd18576,1f3d6c71,52647afc,1ebae367,8ed9b909,f4b622d8,cf5d5b19,fa2e1cc4,bdb42133,c4dd9261,22f1aef4,6dac4c64) -,S(8be41872,15902e71,8f75558e,4b1a5ba7,9d3522d2,e8a2d723,f863c4d7,3c4713a9,f7be5a77,6b8ea8ee,1e59765,ecc6a33d,210eadbf,df4c5586,aba43710,49c715f3) -,S(1e6bfed2,36a10a7d,9efd88cf,af1dc1f1,9649197f,785b4a30,c68391ce,808f713b,90200be1,29c5235f,41a79bc7,2d4d10a9,b00911cf,b9f27b5c,6d47eba9,8530b8c8) -,S(97176463,8cee344b,1ebd8c67,17782c6a,86108b76,e1eb74a0,791527dd,b18e14b5,ccb128c5,2295ca09,626ccd39,b5827ffc,3168a628,6633843e,96184aed,d7bf898a) -,S(2fd20134,8e0b7259,415cc828,c3e4f79b,2184735c,86e534dd,77f1c5b9,9d8cbacb,41fc80ab,25ca1a82,67582a89,f901ac61,2237b942,9d724a2b,8cd0dcb6,c96564b2) -,S(5ba918f6,6bdb4013,481bee06,6aaafa88,f741c362,b5c3a4b,28dd4555,3c1aadd2,230f6c20,f39849af,9de4ff99,8e39ebcd,818d5d6d,8056ca67,8f04f33a,c4fafac5) -,S(69b5676d,b8e2a30a,8870c86c,4a859ba0,dee25a28,493909f0,9ac88af6,83b70797,4831db1,98c1b4dc,69942571,e4908ac7,41ec4568,e27089a4,682ee7c9,8ee905d2) -,S(faab5a9a,c530f7a3,343c71a4,273935bc,fb280258,24a63ce,8f8da6e2,a60135ab,1443a23e,793eb339,f4353371,34937bbe,9bda0eb8,c2fa2d50,bcd85757,68c79797) -,S(c70ef20,284cf135,7c437093,10451a9e,5ef10cbf,e3a0ebfd,b90f487b,8ca62d9,8970b394,35c29dc2,b8254d1c,9c4cdf54,6df52979,ca70ff8a,7dc171b0,5a176ce5) -,S(acb67abb,fa6dfd52,e9829767,182f5ea5,66dfaeab,42a2f2d9,aaa545e1,2e9cc68e,4a097150,2367b1eb,4f51f6c,a394d351,b734b30f,fb36dba0,9e53b4ea,3f6ebfce) -,S(2da4ea09,315e0f1b,f5b6e0c5,b8af330c,c27e26ef,54affcdb,fda834bc,cd578a3,a4097d6,ad006cca,53ea3391,10c80150,f63694be,c5ea7728,f77ebb83,2362a407) -,S(70cb8427,c2d5ee86,59b26055,3499374,63e7a482,6731ab85,6b3fd10b,be3dfdf,f44efbf9,a914063,3e8378c2,6e9676b8,351b6ddb,33f7e7db,5ced5208,e4cb7361) -,S(b14283ed,9a9db980,b135557d,97190066,60e4e1cd,3ab288b8,dccba9b1,67b24934,95fccfb3,827332be,a813457f,28a63a89,87dc8c5,340a8f88,76788a60,f03b2606) -,S(ca24774c,727efbb1,15bbbf12,20e59841,891dfd50,9f99744d,de815f5f,3e959555,2519e414,a9703de5,60f7412d,8949f509,bacecf3a,e672e7ac,58c5f98e,33162bb2) -,S(5a5c1b07,ddc79f18,26bb95e1,13e03894,bb63b593,c808f0a4,2bd44b36,dcd3765,a11bc328,2f672c9e,60846826,521add7,57b891b5,d4fde6c9,738c6329,dabf67b4) -,S(2caf2545,1daf272a,b169a4e9,b0eb9c0d,26888c18,ae7d8357,b8dd2b73,ee4cf7dc,bf8d8ea3,afc9d56d,9799083,c79f1289,7d20d7ed,48ba38a1,acb039b1,2292a3c5) -,S(af6650e3,4022d1a1,b66e8c3a,b0a8e9f3,baf44318,f6946a0d,d1c65aa1,e3f9c9ce,1b0222c1,a5f3691a,248154bc,bc9e5e9c,6b2c96c1,ca468feb,97a7c01f,2551bd5) -,S(3653e476,4215cd7f,83ff59e2,f63f2a7f,dafb8795,95006bd0,182e0e,78ca5b39,c91824ee,6ba3c685,2eeb2695,9a3b136b,371c9bac,4141344c,a1eb3051,8a6d8ab9) -,S(7826902b,cdd4e7b5,463452e1,baf88534,64723588,86643d49,cc89b482,298f6394,dd5bf1b6,91647ce2,86c745eb,6246d087,35cba4f,22c26a37,e326ed1c,4e3d968b) -,S(da19c301,4e77f987,abb00fda,8a5dc50f,d2777850,1fafec84,2ce7e5f6,37edd1da,757fb28b,366104a8,cbd26981,3697d8c7,821c6e0e,5acbb33f,9cbd5fed,25cce98a) -,S(efa31697,2a61cf86,df713186,c1bc61f7,63a618a0,8034c26c,462a2457,907436a,74f17527,e6c7aebb,ed6b28c6,26e612bf,82d61ad,cd1ca156,b971abfe,2efb15b0) -,S(379d460d,12fc351,4c46567a,ce05cc9e,ded3cc35,fb416bfb,76d14f3b,c5164f7e,f548ad44,a5c87313,aeb52885,5ac3a955,178c8992,2415837d,d3e7863d,685004fe) -,S(e3b66f05,ed217cb1,6e3f8ce3,56704f70,36b97104,e39c5649,83bc204c,5b112de4,8a2ee4f3,ab9c8cd4,40afe707,d8dc0fed,473db9c1,be2b6e7,b14de905,ba38ae2c) -,S(b14ebf0c,ccda021d,8db1fd20,a4108c48,750d10a7,e0659cca,64f3e6e,ee8c7a4d,c94ca9d4,d2ba47e4,576aaaad,c15f9019,f335ebc5,763cf232,f56f215d,ce42322c) -,S(1ffb2e29,df24e7a7,6a71f607,f4f03608,43d3715f,c3e468b9,92b684bf,1352cee1,27c39636,54ab505,4b008e5b,4598d025,ade823c3,df6aa7c8,18d4d4fd,32442990) -,S(63e13d75,38f1eb8b,7276ee28,acd56bf0,448f026c,f98c77fd,5f743c24,4872b70,845d65c0,a6cd8b30,7c7ea0c9,8024773,86a50daa,3f361539,57cf995a,43705cc4) -,S(169b95d5,417e6173,b4393c6f,1ace153c,21c83c7c,971418f1,27e1abf3,aaa04673,bcd1ca4e,5618a183,420b34d2,52d25dfa,e7cf699,3e936450,ffaae3d4,61a50c50) -,S(3dde4fce,54d27794,29b6f6a5,8c5315ff,ed682bc4,5601c623,948faa88,2309ed27,2b22dfb2,dc46f625,4f29f8a1,4cb4496a,dcef6806,26d4f499,a17c4751,4a1802a7) -,S(6b37e3b0,2422eccb,299e2b89,1a150be9,ef56a628,62c78c11,f3411614,9fd37802,a9c347b1,fa5105c5,a27ed367,261a1cb5,5d54a071,7a2927ed,29d45eca,6e958295) -,S(7bd6703,ef78de4d,f32f0d7a,274f6371,2d0b0a9b,fafc3f6f,5c03b654,599b443a,33d9b1b6,8254d47d,6aabb7b0,b66298d,8447d674,4612a2b1,f722a597,857fda25) -,S(2e9a4aa0,a2062c8a,63b18e5f,91a609de,b60ae126,93d7f1fa,757057e9,ce169b61,65a55523,e34dd131,3597b250,acd11763,62df6b07,1d3f0f1b,907fe0bf,46ff87ca) -,S(f90c1316,9524f407,8c7328a7,126c48f4,eadd6d65,8baccd1f,403a0b68,ff95e7e1,1d6a1b16,6f5b4f7,9f51b046,42306f53,bd84b7df,2a58457a,a8869,4111cb38) -,S(a7bf0bfa,8e84b448,9ee29801,a5d06f66,a17d2374,a6d91eea,2482354d,66c60074,e60ec871,7ea63cc0,e4785455,478848c0,363f6717,748ee9f0,1c928370,df0905cf) -,S(dc4ac1a8,372c06fb,ea7a44cd,11a352e6,fd204df6,f6868cb,5230e420,9ab36e6b,f3a1b986,c86134c7,40c0ac9f,8f2780,82a103aa,e9e4269,84516e09,659f668f) -,S(538086b2,aba47aa4,dae137a4,4bc747ce,9bb225c0,6aa015db,e9478da5,e2c9cdb3,42ed59f0,fb831257,84b15d27,b9086eff,9aec4d8b,9ac36f87,10f93bbb,2ce7d971) -,S(92eaffc8,955f3f06,fca49a8b,881734e8,6750b34a,d253f160,183388af,f18b8106,fdb45519,36f9e291,9e2e2e6f,7e5d2dfe,16e14da8,b5704a27,60e92d9b,13758767) -,S(63fda46a,4350fdea,fba277c6,190c5f37,c4cf7c88,ab1b2ba5,7b0ce9ec,60249c46,b64fd169,403a2687,f5f41038,91e811f,6dbb344f,2c3a1492,fc408f74,433c65e) -,S(f9f7568f,d2e444a8,14b03934,72564798,5c16424c,1ea6fa80,79f96df2,ff3c73d2,8ae3a292,fbef875d,ca18fd89,8e1e882c,ef7bc222,64140183,1cc2d268,ae795a14) -,S(43a5ef22,93462849,ecbf95d,3c92eb63,ea89a39d,2e0a5da1,eb261c1f,2e8e4bdd,896699cd,e580ef97,64ef1860,19317dd,f7c17ccc,34d340dd,b23621fd,5e5ea5aa) -,S(1fc26dd2,9a3ad966,4206f233,82e54363,6ec9d95e,a58e7af8,a4bc8aa4,736c155d,5f6c4cd9,c6f954f3,f0f3bc54,8bfc4a58,faec99d5,9f3466c0,bcc09053,346bab63) -,S(9a63cdf2,84ee5189,34b73c8f,d8b3932a,50ff88f4,8ecf9b40,c0056c7e,168956b3,e52e7902,6a8d4e95,c7f473e3,84b9966e,16347c60,8b6fb6c8,484335c1,2872f4ad) -,S(aabebcd6,8050337b,1e6caa45,13d279cc,ddc4c218,f849afff,8c1302f7,6b728bb5,808fc6b3,90c2f001,bff1993,346a55b3,663378d6,e457c639,b9a73f87,78ee8d09) -,S(9fd45b70,59cd26ff,2188167,ecdb5ad7,62efbcf2,b668830b,475df22a,bf526239,6fa79fa0,e76536af,92eeace7,77c1b735,19092fd4,870ead71,35634768,700a1241) -,S(ebb3ab2d,e71844f5,b6ff8baf,637cc0f1,1004611a,e8a3b570,1afeebb,a7a4edd4,30eed3cb,55a23613,3bec9aec,b620f1fb,1f39a067,8a44622e,84b9e271,62294133) -,S(a0e7ea2e,33c6a3eb,423138d,8faa7ae1,d7802a73,507d48c1,bb38bcf9,29838ca,31158fe7,ad132036,62449ed9,76c4aa17,67382a8a,cd42c842,ed22badc,882d7d26) -,S(a19abdde,db579ade,1dba9264,9d58b15f,1bf3b87c,eae44520,2ae758ad,f2164fa0,508d24fe,f53d8f4c,77e43ef8,eabecf3a,ddd04eeb,acfbecc9,637b6c07,fbe88084) -,S(e86ea1ab,95e23d10,f086c91f,289e2f80,d10ea0bc,aa9d8f3,1873158d,19166976,4b6bc016,6d95e08a,72c4dac7,9eeb405f,938346d2,ae45ea0f,ab76ba98,8c4e910a) -,S(aad23857,d8d835f8,e3785020,6b1cf1f1,efd9c9b6,ea15d42c,70444ed8,81710ca1,a550855c,381bca50,44be47c1,42d52259,af2f486f,622699a6,aec28138,554cf06f) -,S(b5c04c3b,436fe2ac,97bf2043,3ba57e9b,897816bc,eb8383be,ab11d488,e231a138,b1ee4b56,1965ab9a,9fa87112,57a250a2,d7f06de,7759918d,85c69d66,5546a6c0) -,S(eccf5dee,9b6e3fe3,1e3c02da,a2d5c408,72766edc,29da88b0,cdb01f4f,524b0ad9,7770c7e5,d97ca3f8,cdda858f,ed5976f7,cf2bdcc6,60459a64,daa495e9,28f4cc37) -,S(4c34b06f,6d02467c,9e667ceb,630d9865,4540b18b,8832292a,17e74d9a,d0cabc6f,57671dd,326be6d0,2ada8789,b5f27c7,b052c8c7,d300b2b3,ef881a24,53bcb6eb) -,S(9493f9c3,98a50b50,4db602ed,ef50cfce,5bcc9f0a,bcf80ffd,d5f65d1b,d030ca31,fb45d7d3,fc1216ac,6b948369,42d33e82,932af020,fd7c29f0,f2959eef,a41dcb30) -,S(b0ca3c54,153d435,b9d6427a,20ac3456,ab980b67,ee92c6f7,605aa934,faee0bbc,2e2a47e6,8b959402,1ed83edb,d4968c6a,2eb4be8e,2cf128e3,a3778751,20f27b16) -,S(d5632117,2e9b97eb,4b282d8e,1e303cbc,d50656df,2a99c9fa,bad35909,1888ee8b,30157215,efad51b8,20c03f8,2e4c9c93,11d15bc8,3dc75bea,e44e1e52,7f1ced7) -,S(3a0f593b,69396a6f,62655efd,97c103db,5e209554,8d45de93,8963cbc0,dbb9b4b4,66ba5298,590d027b,30dcd9cc,e4605e4a,73adf43c,6e377bcc,cd19eb92,e20e267c) -,S(10eb3c4c,cccd5ca,e15bcc7b,92d108a6,de762cec,b71bd78e,1917752f,b3f6cf86,6d65809c,79395f45,153d7650,74597eb7,edff81bb,598ed20b,f9780e45,bd91d077) -,S(40ae7e81,e33791bd,154945a5,105be36f,57477fdd,d36f83f9,d31fb73c,862e70f9,71511daf,e9cde10a,7e4ff05b,948a0454,e5fcd355,d98b2bf5,8ed3ca54,1a568498) -,S(994dac9f,3c047519,823c007c,57851a8d,41be0480,7c6ba5bb,88e19869,261fd12f,913e96eb,bcef4fe7,60469aed,51e9dbd8,4910d606,9646255c,9cb3bb7d,55b1e342) -,S(f0d9a17d,112e91df,63c106a0,5df3cf41,6471b817,a3ede631,d845b604,3c04d0a5,3ab43cb6,cefaa228,5c84a42a,8f1f41b5,631bab61,1d006946,f06be576,bc817f18) -,S(20919d38,ef12de1a,64992396,f7b265e6,2ab8267c,bb988d1a,6771d8e,724d16e5,81f79a2d,b629ce97,47f146d6,b16cdfd7,90fccd71,c46cf9f7,fe526e58,8ed1eafd) -,S(b92087f7,43494d53,71978b1d,63e11ae8,a1595239,33b87a44,704ca3d5,30f1b02e,6eef6ac2,49a8550a,135072c2,9bb42afe,5d27c8f7,fec88aee,6274d27,36dc0eb) -,S(f69dedef,a8894583,c05b1fd1,ae205fba,3ba11a37,ca628150,d287f01b,b6920b34,a9f88097,66d18287,9d97e01,5544c7ab,ca0cf8fc,c5b9f305,ed0bd9e5,58fa5b3d) -,S(8bd8b3c9,a301a76,9f5607a3,e116edab,9d87bf79,e4099d62,a328c1c5,f8b8b6a2,167117ec,ce6e15da,47a076c7,afd851a0,cb5dd1c3,d8187f4a,9aa5abca,cc0af771) -,S(d7e2bc76,e2a87357,82611,2619513c,10a2eff8,857fe6fe,a2e2c00,c6f8ef4f,85e1891f,531481a5,e935e80c,448d8da7,32f1d061,dd234e39,d55c58ee,df8cb93b) -,S(2701bed3,778a857e,c7a9095e,6487e92c,555ecc9,32ad8e0f,b1b59d70,4131768c,9e38370a,8d30d5d6,6aac5302,efc7496b,cd5734a2,20d2e76e,fae3c72c,a793d991) -,S(3662a916,a05a80a9,13bfc287,c81cf28b,7295dd1f,aa52badf,5ea1c83f,e1b90521,b14bfdf0,a33c9286,eac83a4c,b982f5ae,82e2e134,99bcb3de,3ac930e,2ed0c931) -,S(d778d74e,317063ff,6556388e,2d2ac429,410337a,d62917,a94b7654,6a04787e,f7d92bac,c92600b4,e8184960,11f135fd,adef70da,b72c1bb,9da26bcf,7a81f0b7) -,S(7b05001e,388f9197,ff3504fd,402a5291,d1257621,c8eb202b,dba87b56,154b6f8c,8c9c1c9b,5c151be,39f2875d,b31797ba,2899047b,6e5c491a,56f7fd28,1b897f2f) -,S(603546d0,1fe46be0,eaa9f00f,c99b2a6f,c38fc225,6553bef4,9ff47442,ffa7626c,1f86de50,aa457ed,ea306251,91cc3cd5,61cbd8f3,2b41145f,139110f0,64b73b74) -,S(80f9318a,ca3b7aca,65cb1965,a36981d0,86ba3b32,8a95cfd2,9c6bb718,1f662c25,c195025d,794abeff,49c9b1f6,724f72ca,70b0bada,d06ae11f,2101b49d,d592ae18) -,S(61182e02,a877565b,1209dce1,bc84c62,f3b1007c,48332c56,6dd6e697,664cf64f,d21f9259,517656d1,3efe7166,750c341b,6c064b0,542bac29,28424a30,ce4b51cd) -,S(21cd4f22,ec3a190c,77073680,58562d82,36d463c,f7706f10,fbebd283,c19378ff,2e04af2b,155beea,daace708,c510555b,467727fd,145426bd,680d1964,fc1b03b) -,S(2d3f6c78,94479443,6004ac92,554a507c,5a20ffd6,f275f715,b176b3b5,3d2000b0,72e0e16f,9d9ceaa,2ffc5a1a,71a2cee0,eea64e44,7f716eec,1fc417be,ba16d92f) -,S(a9f45433,c040d1ac,6bd36d33,5b655fd8,eec0d3a0,bf1a622b,df422039,239de17b,264ed6a,8da4a169,a66869a0,a846229e,81d52517,22fa4c2a,4c775322,f33b1184) -,S(16e052be,bb65657c,309d67e5,b68ea441,4179ace2,38315c8f,df88626e,84281ce,91c007f,fcd4633e,597ee06e,b28296bf,2837f30,8cb21be5,9bdbd52c,4ae0422a) -,S(ff6d96b6,f633beea,1de80512,73c06bbe,181a1098,db737c8,41a48d44,cfab935a,cd9a8011,c22b643a,90f1d9c7,54b7330f,1c1970fe,5ac04225,c2720054,fa6a8444) -,S(dc2e3b1b,a2619ea0,6e4ddc09,99630c4a,7b94c78e,ed13517,25b8b8da,137fa467,f97e82ad,49bb4389,84cd752e,820aac43,bc6cccc3,f9b0d9eb,c2337bdd,89cb83c9) -,S(d53b97c5,8e23d50a,3b855c43,80a992c9,2d667afa,bba4b028,20031f58,dd6947c9,24a54f43,bb9a04c0,8b93aa96,9dc61f92,e705ab75,e644a3c4,40391af0,ad375ec7) -,S(b598a510,beb9cbc1,c4e03f8c,1ff610e0,7123ddc6,ad69dd6e,f9fa7810,f79c8ab3,b895b8f7,68a80a37,77d8b5bd,46754473,c9590768,a56fd586,58ce97a,366dcdbd) -,S(cc2296b9,ee9726c,17b0cc6c,745a038e,38b5535,5e19fc49,e89f4ec3,372b2a05,6a466fd2,f9a5c412,9f5b2faf,aaef4cf2,be71406,590ae031,d68c482c,86e3f89f) -,S(3e84c76e,254c858d,51cd4e74,72c22ec8,364ce28c,de81ddbf,b7b3093f,44acf9b3,ce8ae6f5,f56814dd,21186370,f70196d1,339c264b,c78a502e,bd57e771,b438c81c) -,S(976f67c8,c626f8de,9de43f8b,39585d7f,d4cb35c6,e4211b00,68669ca9,a973a3db,ae4f1f6d,25af4ccc,3eca4b2f,6cda0cad,dcc28f78,c8e881c4,eaca9131,2f0b057) -,S(b28bc958,aed50ba7,6d5293f9,7c419828,53bec43c,21ef0f96,9000fa47,49ee95e3,e7d4cc8f,f68182a2,15dee707,4df2c351,906d5527,c47e6414,54e97c1c,b57525b2) -,S(e54dd5d2,16bc5903,9a630bba,7cccf5e6,81a3113e,be8fb57f,83c51209,965cddb2,86352dbf,5f2b2327,ca50458,b3b2cdd1,8d403629,a2e2a776,5562240,7e8407db) -,S(58379e1a,10115a0,8f2b93a2,3f2f4e2,2787aaec,cf129910,b1911b43,c209f379,a526d32c,abd99175,e63b4493,7a0dc96e,e0feb99c,bbe00c91,1e606537,c871c6c2) -,S(7858a68a,cb34cfd3,e1cb7d06,4d233322,ceefa6a7,a2de391f,991b94b4,da9ebd63,f54490f5,ede73b49,946ffe19,d5ae6f7f,ca026c07,b1dc0138,b1409383,5d792db0) -,S(3c8c636e,d20d58c2,f03c26ac,bbbfed70,3fd13304,74bdf2ea,7526f16b,4fe6f7f7,550069d1,cec630e8,6d22af01,5981f20c,ffdfabdd,6416bb00,f2dd8c6a,44401759) -,S(d03fc7ec,eb716cbd,f033d76e,8db97314,858674db,48ede8dc,1a1c7dd0,82ae7f93,16f7a717,a197fede,dadc25b5,a20b0486,1cfaa63e,3157e5ce,ff0c81d5,bba296d) -,S(6d6c983e,d60601d4,ae5ef4ab,c73914c9,b9546964,a6a3d2a5,681b09cd,afee2c22,13f5af59,61877fb9,2a2ac09a,eb691a88,20ca8361,81359fa3,96558ad7,b2276b1b) -,S(92a9f5d2,149065eb,1241d82,fd06ac2e,f1f48003,3bffb06b,ae3a9d88,a1d05f8d,f0be5964,75545835,f64b0985,1baad682,b84d7a39,91ea0f49,1d19b7ad,77ad75d) -,S(222aac7d,c2fe0066,b766e1fd,179c1912,5f289e98,33cce93c,749afe38,ce0aa74a,bd6c4d8,43e5923,b5944e40,8d309733,dc0cd9c8,b266dd8c,2df162de,fde5bf5b) -,S(28b14628,3a7e1785,1c9d1831,6c9ca17e,56a13c25,7877ca3f,49ab2369,ba2898f1,292856f9,572ecc,5f000e0b,1e7ebdc2,3ec72619,3c97542e,8ccb10cf,d608eac7) -,S(5031a6da,df8d12ff,9eb19209,b844b008,dcc26de,c4a6f9f1,bbaa45c9,daf909a6,ef31dc6e,3cb5c39c,64011c0c,89cddb04,7ef9a881,a0d718b,5057bdfa,3f5e1ffa) -,S(925835ee,ce55e98f,130008fd,a6f01768,aee2de4a,f96f239a,430d408d,95a627c3,cac1b7d7,60362e24,f3b5f277,e370ba70,f0f8c6dc,a338c15c,46c5fb4d,f9f1bba7) -,S(6b7253e6,9dd65781,8214fa04,67f59e92,a4671648,c465ea4,9c993bf3,de8d9e77,50a9cbd6,b429c3d7,32bc3b68,ec581327,1c2b0a4d,2d8587bc,7b26ee15,ee7e92bd) -,S(f82d660d,cd5df408,714213aa,a7406a3c,868a8d05,1fe37689,baa6fbc3,effb3e33,affe0a1a,b7bf498c,83b331fa,f3e7b723,2a2dbc66,3b93da28,e12f0d56,260677a1) -,S(990954a5,5342c5a8,db3fef46,da2b31ba,32b6d597,c67c8290,9329a90,c39845fc,d764f091,40891e20,a2130696,216049d0,b3eb1af5,7dcb9797,4c42abc,5298977b) -,S(d6b8e341,f8bad7e6,ff434dce,fcae81a4,1946f237,e0467120,fd420,f3dafc0b,a8ba941e,81677d32,140666f3,55fc28fa,7233ec8f,8fd13703,214bdf8f,340c389d) -,S(fabf5120,8632ee4c,81ad6d34,cc84de68,728197b0,fcf07971,326d4c04,7017b905,79c781e4,aa7dedda,4663b8db,7fff3cad,f9752cf7,ef2382e4,b0254489,7c6c04b2) -,S(e62db266,d9b208b1,83016754,c871a8d7,4b6848de,e496ee7,e2c1447c,2029b0d5,ef7410f4,f44d7414,53b9c1c6,8e5689bf,37cfecf2,1602e95f,3fe053dd,aea24f77) -,S(4bd90928,14753ea0,1025ea2b,86ae2310,5b581b48,98359481,d1b7d36e,d9c6e478,2f12e4b7,b825c858,5362afc0,d0029880,45fd638d,65f1865c,6ffb31ce,424baa50) -,S(3e397cfb,cc5c9fa1,15519366,c6e814ec,4b0ed9a5,dd093321,219e4028,28126ed,31c352e4,d4bef7cd,8929d3f0,aeecf9b,1d577ef0,e8086a28,40d46966,c1165dd) -,S(24bee951,54baf31c,f5322941,ffc01fda,9e89f80f,2662f5b4,edb751b6,5b372ee8,9568a4f3,a34ce5c9,8f591550,b75f2a84,be5cf67f,1fd7713c,c126f46e,1c3b6883) -,S(d242bb09,e4c6cc42,a2bdcdc6,bad2a02,8e4bfa21,430acb16,3f0e8a70,2ad2f0d7,2eede9ec,799b9e5a,13c40c4e,4cf6dc0f,9640d472,2a78cc6c,d920b610,d070b913) -,S(a57b5fd8,f50de3c5,98073cef,bc6fa56d,20dbacc0,72dbbf81,347bf0e8,7a36ebef,a99f123f,a45b1369,32394f8c,1f7ea2b3,563ca2ba,9c0da00d,b2c9c119,e6f20287) -,S(82a43e2c,a533abf0,6aab1199,fdd20f9e,1616a79b,859c6467,ffca4b27,989da9e,19cd40f5,8c997e78,311e5ba0,c0b3328a,b845da97,91dc8ef,a6cf7e5d,efd51c6a) -,S(95bf3b4d,b8ef8bab,16e00f5e,7dbe9907,b54c98f9,2331c4fe,688129a5,5cd021c9,2b4c46e5,b9d9f915,d5d020a3,3c63fe49,eeb32931,9373bf9b,e359c40a,19328c47) -,S(791ea768,4d333125,893356ed,dd8ebe4b,3f98ae58,e25a2d1,67006a4b,5c05799,5f72cf68,7827ce2,6bebd598,539f6519,a50788c,9d093766,9c3b9c29,f52d5422) -,S(85138ec5,a5d3f0a7,881ce23f,e34fbb80,fc3038e,bb7c2a24,ccfeb2ae,5ef07b74,8eb9e80d,8664b11b,d24753f2,bba612bf,c06bf9f2,a4bd061e,82ce9037,895b084d) -,S(3b4c1149,1d98483,9ff33b31,39da0341,f430175a,d5800c80,37e35dfc,a68ec256,574d6475,e225aeea,dace647a,1489b2ea,873175ea,83cff3f2,fec684b3,fd2ad143) -,S(2ea17f9c,6a028f58,396474bc,8c51b1e3,cb9ac0c6,7f73f533,a428281d,4101b04a,19d1f021,8b8cc0c1,bbfb8925,77087caf,ebed3409,69dc2281,3a1dd6eb,9d6c44a8) -,S(67839592,2fcc7ffb,627486db,e1d98a45,25ee1338,5a98c01d,6b3b9f8d,f64c507a,e13ed82a,a1adf761,7cce3760,d049a72c,7572508a,5ecd0615,1bbb589f,17e10a7a) -,S(54a0d2ed,39778fc1,237ab423,1e4384e6,4156c1a7,d5e999fb,2c92ba42,ef40ee68,3d879ff8,c25ed54d,df848e5c,49e3eeda,e8eccf33,afcb1c1f,67440810,8b3e979f) -,S(263ff1ed,726d0ff3,8b47b398,c713455a,3030d499,3a77ffac,b9cde4a2,cd12f7f3,a5f3fb33,c739bc93,c442508b,ac70884f,d90c3699,34fd698d,bc27f7b0,ca48a0ac) -,S(43b2fae4,a431beba,598b3ccf,caa1e034,91e7099f,c19508fb,8e693de6,dac9e3ac,3e43aac3,379c321a,5313b412,7cd00a1,bd8cd177,49c4240e,7cef1e97,22daf69c) -,S(a73e77a8,5733a296,2da7fe71,f4c16166,cf0acdc8,2d5288e1,8cb9479a,2a31f362,12b393ee,e323fd52,e44a9ab4,3e19256a,f7a8c892,76e9e6c,9052f0c5,3ecbc031) -,S(f007a9f2,bd3d0d4a,8cb9524e,a5aae499,6b2d0c1a,19aaa56d,4038a21c,6dabdd86,517a6a7b,3b75b68,bb04bdbd,d6f93414,c97b4b75,47b8fe22,c5828d6,7e979702) -,S(bc64853f,111371d0,8381c082,c72d2528,823e18b9,99de4303,c85a5fb8,87250833,51e7dc7,23256176,62a9f6f2,70bde4c7,94020e61,9e8dd87f,3f266d99,71596146) -,S(144dc699,a063c473,4b9bfd22,845317da,c4b55e92,a232b92f,965967b9,9c8e21df,a20a7982,7d57de38,85e573d1,6d22025b,648b9ed4,c656c48,bd6f4902,2b67c681) -,S(834ed659,98d49650,c3f525a1,b34ec725,89d167f7,a3cc6e86,8e4cdce3,b2ba3179,6bc2b06,c97a108b,2abf4033,152065f5,24c1bf1a,e79adbd,b7eeec17,9e598cbd) -,S(efce9278,6052c989,adc9595d,cd1500c9,8e93eaa,dafe2b87,2011bf55,3488b1a6,48ca33d4,cc89b486,c0930829,91f23147,d910f29c,c9d13787,7bebf55e,a3dc92ab) -,S(5b150240,c3563354,39adc9fd,23e9f94c,369a6cf9,27f45bc0,f0110cc1,b7321f4c,629b62e3,1a85fb44,b448c7e8,e76ec423,b059c9a,c8144c64,9d77a4da,eb044aa0) -,S(cec8cb02,3f166bd6,9fe04f66,8ef6e949,f4e3d26b,d748c30f,53a9b9f0,9ef3f9dd,997f9fdf,dee5cd89,352e6c38,760c4cd0,a7bb2696,94916567,ae60fc5f,39b908ca) -,S(58427cc8,edc5e616,3726519c,7522980c,30443eef,7e72cdbf,b135ede1,f15c0890,d2fe9c00,7eeb0be0,8295e972,e69db2e6,a54193d3,ec9a3ea9,f2515e59,6e34e88) -,S(a7d0a30c,1787b9f5,8ebff502,e4e38000,6bf896a,2feaefa4,4670dee,6030bee1,774eabaa,863fd4f1,63b3a16e,4c17078a,fd0a1761,b39ab05c,3c6b1d36,5e487592) -,S(9d70eeed,55ed86a1,ba17e817,4c400cb8,ab0e5da7,b568ca81,60b585df,d1a84e74,f4c1fde7,f11b329e,f3c3e196,bd78a3ce,5387662b,859f99c7,d61f7962,2d01b5f2) -,S(e0715fee,9639817b,8501de6d,6561e623,628de7ff,d0dbab5f,bf58ee4b,a365f684,e34ba5d,acb60318,c6ccc001,871800cd,98ba2c5d,529a42a2,fd145336,7b10c22c) -,S(594612b2,4cb1912f,fb945465,1036bfb2,79be0bbd,e718ca26,973552b6,93d20143,d68338a0,d03fd0c5,e6c6e3dc,7070c78,72eef1c8,cc2154db,cbdad699,b594b142) -,S(f4f41087,1dbd5394,5fde2583,b08ba65c,6729dc05,b32ec3ac,c8aadb72,a6c0d8,8e948ba3,853102b2,99f2f558,ffc66181,310bc676,4b82dd7e,85fd075d,70d92fbb) -,S(efca7b38,69f2981c,406cfa40,2bbdd00f,15ba56cf,c6e9f66,9bdfa14e,aa9b1d21,458fd928,a07fa32f,d6a0ffd6,64a16b21,2bdad00f,a4534093,209b0c92,f507f9b9) -,S(25b2384e,d9e09e70,8098971f,153ada48,f3f4a9ae,fb946225,77d213c1,e7b326cd,ef50fa0b,4cd30cdf,2667bb4f,7dff0287,df666dfe,7d5bdb9c,ab567af4,b77c7535) -,S(ed12b20f,aa2ac5de,db62c17,2bc67cdc,f0534a33,6a32e26d,b325321b,81901268,9245a6b1,35df02d9,3db1224b,1a0a296b,a39f07ac,ce7ccee8,eda552b9,748eca9a) -,S(5dfa472b,b84ada50,da3ede14,8bca4f0d,aa885d2c,61633336,b2a8a37c,76b200b0,f314a5d8,2d20fd30,ee237487,7a922a54,f4c10468,656a5432,974cc3db,c2c7fbb7) -,S(a9e5c0d6,5b6d4b4d,b242d87f,57c805a0,5b7f243a,515c5d34,a037ddc6,afcc4470,d90fa599,de5fc8d9,87a42c57,f3bf9dac,d5b766a,fdfa07db,4c56c0d,3d71324f) -,S(4e9ccc2,c0e3169e,e25a6701,a82e7f02,2663d3cf,585100c8,2c6b5da4,d8c42e8c,854aa160,d48d241d,f5bdd1da,2c74d1f9,a00fad7,effa29fa,5ecedc42,3ba43484) -,S(2122c569,da05f145,48d42f9c,5ce3a96b,bbcb49fd,fc5b2dbe,1a7ab0ea,84aec76d,40796418,39879018,93bac618,8a7286a8,f8745709,58a40cd6,1202ac,dba5867b) -,S(aa8cceb3,415df249,b5069899,75a853fd,eb409729,331b1807,ca2242e2,a75c6968,5362b581,fb676eb9,9f125fd,5f674be4,800d89f0,133a1363,f1cb30ec,1fa5b468) -,S(beaea0f0,1fd8e442,50648032,530e41cd,7e3c8271,f4b83b4f,7493039b,b21013aa,e21f7d1,53e5d411,794fb472,47897cc6,a86396f6,3f6291bb,fe2f0f12,a263873f) -,S(8eaa225e,63bb92b9,666bb318,22c166e0,3843ff47,482cec9a,69ff584e,d1a750a6,aa26b32,e69c5d94,19663e05,6c9f7a60,1274aec8,a839ff1b,b5a43c2e,136ffd64) -,S(bcba926,40d8b4cf,8d73c0e3,7867f5dd,81eef91,70e904e0,15f05f3e,1bf6591c,8913cf87,e33aae4c,a16b1391,75d60106,ac7d05f4,a8f10db2,b0569a6d,ec121260) -,S(2d03aaf,6828d0c5,9ffadaa7,5d1b7e95,b3c4a547,46faa5c7,c428fe45,1a9f3332,68468e2d,597e7534,37b3865b,3c968e4f,e3f6b1fa,996e6b4d,296a12c3,20e61cf2) -,S(b39b4de5,be757b36,b1e88773,47cdaebf,11f8d6b8,ab59d780,fbaf2263,a823b5b9,1b609d2,de73faa,d613c4dc,6ac3c2e0,33d62b22,7ca3fcfe,4aca992f,eef90b0e) -,S(eabf705f,b6996148,170b23,9fb8998e,df6214a2,cac27fe2,9c66a899,63d2f0f0,e1867fd2,98603f79,d17876f4,7aea4437,cb39ee7c,bdafbf0c,5452b024,86182d17) -,S(a4ce885a,ebe9335c,6ef43c6f,395e1644,201f578a,4caa7f74,65c12542,27f1bc80,bde32eef,f7fdc498,1c50942c,efb38cf3,c3f1a8a7,5addfe7c,f11723e,f57d0c41) -,S(db8ee69,b0e00ff7,6a094251,a53c61f2,e00dc65e,a11e00e5,553ae121,ea958361,24e7ba71,22742e09,728108ac,59c5f46,aba40d1d,c308edd2,9d494f39,d156b2d) -,S(88a5b43a,d6cdc2b5,aa3d58db,9a9a2e1a,6d70afa,808efa87,1d7f3cbc,509cf064,88483c55,e5bc8717,8114605c,1febc726,e14345d4,4211b670,6b6185d8,ea6b7103) -,S(e3cb24cd,2130716f,10a4d432,d4e59229,2e11a2f5,3190bffd,4f478da2,216b0051,df432db5,caabb417,f8252d37,dd23e117,38066c87,101cd934,73a2883a,1b7e8de0) -,S(d9c88471,97f04254,731794ec,e29ba74,f1d72f19,8f424beb,8309e1ad,e09e1301,12037266,331f04b6,db4264df,ae6d934e,5f753828,35a646f5,cfa4ae8b,e6defdc1) -,S(80bb740c,3510574d,10afa586,a6e541fe,b5368797,231d2a63,67d2890,8877dc58,24ff9389,bb268f42,b04f1702,f7b7c6c1,7194c7bc,c5f4f63,bbcd4ca8,ef476fca) -,S(4b8b08fc,400d6fae,da05cb19,65c9c785,8f93452e,d1be8f29,28c83e6b,4d2b06a1,70a6612,2549ec2f,6cde4a4a,9ae8a528,1b05081f,8eefa8cc,1111271a,1beea7ae) -,S(d2708078,4d19552b,13ec8473,1eafd2fb,bc0ae927,dd746a8c,be1dfced,d072ddc8,9362bac1,806dfc84,e736758f,22f1039d,57a5e44c,40586195,885abb78,f75d3355) -,S(7345d1a2,7b9dc922,f51a0466,57721451,cea5b54f,6673a484,7a210b4c,339d1f18,293053e8,c180ee0e,d81bc4fd,658fcd5b,99bad329,9e62aedb,74867df2,3ac12d98) -,S(3b3a6baf,b9003f37,ca27889b,a2be2a02,748ba52f,6c6dc719,afcacf2d,578b1e24,a9749973,c49ebecc,501f9b18,83056505,6c88c286,2747496b,951892c6,8a61ffcb) -,S(b2d1a3e9,15b02709,1abb5ba7,206ad2c,5d07079f,8d4c7fae,3e6837be,34159226,90007202,78d4188e,b8efc45e,8306ab47,be1c6a16,d88284dd,fb627b1d,92959898) -,S(298019e5,5de972ae,fd0b4c94,9a9d4eb,46689fa0,9b849947,bbe27805,4a3f4a5d,5b7a4298,be50ee99,363b5f9a,1ef103fe,4fec0034,fd8a2364,5cc76f8,ff804f0) -,S(604f1e62,7f503661,5b55fe74,4540df91,67fe575,e0aafe13,8af68214,f1080eb0,2ade0355,b373ddce,2353669e,6af5575,cc6b01ae,58b2a581,2b63f36b,58effd5d) -,S(ddcbadcf,63ffbfce,326db7e9,2df0d483,9a35df32,fc576070,9f2422f2,6e07b8be,7a3bf369,dc3a5ae0,c91cea62,1429ad45,76f7110,b654a1f0,edda9b57,3076306e) -,S(160a19ff,10c8b334,7683b21a,880226da,81d536de,d9dcd357,d4f2283,18853837,91dd522c,f6d1d276,e88287a5,a37afefc,ba010111,82b93eee,1483cf56,e6cf5218) -,S(bc1210ff,d75737ab,51300e3e,ea48a264,5f363793,1f4c6f95,e8507034,84834819,8acc70b,363e52ee,779e6342,ea7dcb7c,d7d09946,5b0eec60,e35ea360,e8baa7f4) -,S(c2da24ff,f2c5419c,3d2ab241,e55cbfff,5f41b9ae,4efaa105,abcc173,a81fa1ec,3fed4d9a,4eabf3bf,6b913bd9,279761f1,4aa630c,e278d0d8,4bc82ac7,af77481) -,S(73a495ab,b26d4be1,bd99935f,f5583f6c,f5c86d79,fc86a4ed,48f87f40,2f12259b,f4126c3b,3e9b8dc7,ead63ddb,5749fe5e,6cb0bb3e,3c85426b,950326ef,9092301a) -,S(599baa65,fdf949f0,f54c44bd,ff605ef6,2f53d68a,f0e44bf8,274f0b73,ce251227,297ec5da,e3893363,617f5448,b13237a1,91fb5a20,e52ee897,a124daff,9f1eaa9c) -,S(9a032a50,6786e1fb,bd9ecd25,243ea67d,57f9e4bf,d1083879,e309690c,fb07f253,a073c6cd,15445d6d,80c51af2,4e7f540d,f1b75fa0,89a4849a,ea14ea09,ededdb0a) -,S(792160b3,eda1d493,48ea96d6,857d8631,ed1e198c,c7f185d6,b9d2c75,2b1cae63,d12d76d8,bd73a681,9bc581e,cdb84efa,dd143704,5554984f,8f1132c5,fe1bc32f) -,S(8fc4cc45,9639aec0,2c337f16,589c09a7,e787dffb,69ba2907,37b6c465,db9f12d8,b2ce3c2,57ccb79a,b677a9d8,49ce1833,2a97fca7,28bf3e83,6dbefd23,5343571a) -,S(fc06a9a,5857b2e6,df0c3be8,b5840946,ca77f690,4ba114be,44e760e,267eeda5,6662078e,f0de0e94,5a770654,b8281a74,f82168c4,49455250,136dadf6,87c5bd2a) -,S(345da4f,e1e89eb,eb27b353,4352c5a8,32d3c9ee,456c01e4,657c2885,733b5f69,3db274c6,b89e7400,cec4e2a9,9995ece7,be8b98da,39a2fa48,bbec96a4,5c758be0) -,S(309850db,36d8c2b4,610cf8f3,e1c12431,3931aebe,1a9d2099,cb3bc7b6,fbd8b0d8,edb3a9bc,f6417672,af9b1379,9bd8aab2,f953391b,27cdf167,320005d2,3fb3e4d1) -,S(8a35d7fd,8c7c75f4,e22ba36d,d84533cb,f314a54a,2e17a43f,d250c941,5025b0aa,97ae015f,fe364a2b,6c12cc42,fe526eea,7250092f,79c40b94,ab7102c6,fde1fa5a) -,S(982d9d66,dbe6b738,2cf2820f,c72ed491,d6a61add,f1eff091,de30fcb4,96ca4161,b4a7b42,2e9cd74b,10cde7a8,12b4d88,f3621324,acdcc911,b39d0952,3cb3b501) -,S(1396bea9,57d47670,735ed20d,e2ecaf6b,afe7e067,5f2a0f65,6b3e719f,573cd1a2,cd77e7d5,a49d6cac,5e7871c4,58df45d8,821d77e,f3ad3db3,56989c1c,700cf484) -,S(6857993,76774ed8,a08da47a,9323241,71d09fdc,964893d2,aa5e783c,b8030057,640c986e,befd426,8fbfb131,8133ca77,879ced3b,56ec251d,12d0a650,28bc9d3e) -,S(801865ee,fecd50cf,4970e6ba,efeed453,769b3e14,c103db6b,2632e241,2405fb6c,b3d3f23c,8f75e475,8784016e,6ce1b91,8db76599,8c7c1aaf,af047282,ebd7a636) -,S(f09220f7,27e57fd3,209eac13,1ed93f96,142c400d,b9bd708c,9e716686,20f1793f,8280375b,1b2f4915,cb82a72c,43c9fc6c,f3a7de5c,32762b69,43187a8f,13510eb) -,S(1c814b69,6104f8e6,5a51b98c,e6b0c4f9,f26b5633,8ce24ee2,24a5aef2,967ab705,1cc2bbfc,61828277,90502c11,bcaa1f1c,b5e34891,a7c669f4,dbbb604b,df2e3135) -,S(22fff436,de961dd2,a7ef38c2,f588aade,320d0721,55e6a42a,3201bc6b,c7d24a54,6f13476a,f48f9197,3845af18,ce68ba91,77a0d4f,a835acce,76814c81,f6aaef5a) -,S(39da98ed,a85b2de3,c9bba6d4,1af633d5,5a392dac,b1d4fb9b,654fde5,a3343a65,29b89534,35045e6f,2ca41bfc,9e5c9ad2,55eee426,95f41744,b239659d,460fbdaf) -,S(6fb84bb6,3be24203,6e067346,1a5c1fbf,7d89a0b0,c98ad2e2,25cc3ba2,191fbdc8,21a37f8f,e4f821bb,3886333,c554d6ea,cb8924f2,bfdd7ebb,339a8a92,ec9bf8a4) -,S(29080a3b,7c1d33e1,13b70c4c,8388fd4f,59118a86,c4bf697d,25346368,8f60766b,745ea31c,e9731f68,89aaf5d8,1e7f686f,b345c9d7,3af728c6,7ac2b8d7,60ffecc9) -,S(a54f7e6b,aaf05de6,77e7d98c,5385d9e9,57f68d2a,8e3c24bc,11b6435f,50cfd955,f7d61099,22ff9c98,ee79998a,597dac10,be885d5a,e7b53158,fb671e38,470b5c69) -,S(7472bc8d,c109d56d,a5f150c0,bc41edce,7e378335,15e17267,62f50cce,e8845b2e,3c59290,820b997d,3c9109ac,7319048d,e37c5280,88e671fe,9cd85487,f03917fe) -,S(6f4cbc32,ff1805da,6cf83c64,b0d0eefc,6bae76d0,586de80f,df2317b0,a4e68267,29e492e5,89bf6c68,17731a29,76577124,c9bc9e32,1856bba8,8a060bf1,6a6c9d9a) -,S(1a93eff,b60cb865,8538cb27,d8c12490,483e6886,16320327,e2689591,c5413a12,d96609d9,251ea2b8,f150664f,efe6bf6f,a0634cda,b8846cc6,5f6c8a8e,97697c9a) -,S(79b82e7b,bb23efda,cd79c0f0,87f2d0d0,e2d3db59,97696c73,e6e94ea,8cb72027,bf16f23,47e594ec,fd087189,48d531e9,8306b173,88546493,d620218,b25e3758) -,S(a806c902,28fbc405,ef56057a,aee9993,ef177261,74d456fd,818126f2,5d93f986,fc49c640,7d9d26f2,f043a1b8,8a41bbc1,3ced6a93,bd669ddf,3186dab2,9eb7c5b7) -,S(227d9094,69eab478,9da2fe7b,3cb618d8,d781e0a6,54892f86,92eccce2,f41e9a1,81cbb45e,adfe3fc1,de5975cc,f87f0a44,e9f106d7,19cfe796,f33b5c60,85de7691) -,S(14f8dba6,4bb5aba,f7f58e8,1c9b0425,2c357f3f,fa8aeee9,fa4ac700,8c49e060,26b19dbc,52b913f3,b6aafb31,3de99445,b49d64ef,2503d28b,bf2f9e2f,4614609c) -,S(f22646cd,553c5008,aa3c4cf9,f01a05e9,20cee021,4e9b0553,38a75c1f,23e5fe4e,52cdb77b,7502794,ac16003e,2f4e859d,ec3e68d8,c84a3365,a307ac80,53d3089e) -,S(515de841,814df2fc,7cd43689,8780686e,f3bdbfff,83eed568,af19c75b,5ee93a2a,7395bd22,705a81a3,d62f3130,ad416db9,268961c7,facf81a4,44d2ed8f,e4df1282) -,S(59f4aed0,38f07bd7,b2aa6600,ca6f15f2,d396310f,e4ffe212,4e6a89e7,3c7c4ed3,47a048be,5d6e45c2,4fa69329,86b86edb,b990eae2,f5dc6524,3eadc69f,43b2ed3a) -,S(7492492a,d7f94293,4287c7e2,5f05203c,4c70b8f5,80d23b4d,4822d1ce,fa3450a1,19523158,2fa06da5,eb5368b0,f0b19971,1a1bdba7,50d1c6ab,80ca1b4a,d649eed6) -,S(2e12d13d,464de937,372a69be,b90dac92,78977cd0,e7b954d9,30360d6e,a51cc3af,35a900c5,6c7cf352,8c4a5af1,56dbebaf,32d2a128,8a58e3a2,ddbcb539,bc3e3505) -,S(ce4c4b4f,a52f06d1,11dce52c,402395e2,a6ffd186,dd8275b7,bd43e941,9f4699d7,957b994d,c5bcd5e0,179a67e7,94a40ac5,cfc074da,6d23d178,969fd8b9,2d9dc455) -,S(c51f1cac,5814de82,f4bd5d2f,a8e4950c,38fe78bb,8d09bc5b,628ec13c,e3084592,721122a2,f63289c1,f8925ce,34d810a4,be52f7bc,9bfea232,47617f95,8db1cc95) -,S(9fbaba14,8293f578,46c717c8,718a3a9b,9dc5df98,63ae10e8,9c3649a3,e26128b1,4917061f,ad964c4c,5d79780,7914b2f4,b6c3e730,3bd440b7,bc00f15d,bed2b497) -,S(a4a9ed86,ed3a1dce,5423c1e,1bb5fb9d,fbc1ed41,66a4219e,bd343922,8542ea9d,fcf6821e,46386764,c61eec0,19b1a84f,6a8851d,89be0da7,9d2768af,6eba9d89) -,S(a6fa3567,9a732aa7,b58582b1,5f3e95d1,f702ab16,5249e9e7,89a5a395,3858d1eb,3bd67e4e,c0dae02c,43d32cfb,d25a4b2a,75898bad,eb2986b5,6cf61825,ed2830ab) -,S(3b3992be,8f7e1b1b,4d8f5710,6feb825d,568b176d,af0e41f5,9c2fd59f,f67d9b7b,ddf2751,ac17a413,2ffc5c08,3e8c7728,a74b0063,377228bb,a60cdb87,1b5db297) -,S(e9ccb20a,8a279cef,2a15de57,e34f510a,f60ce397,3fa2ec2c,4558f166,7ad20201,b70a11bd,1b5414de,1b30035b,3dcd1dbf,17558bad,368c78c9,d5d9136,6592fa53) -,S(98083dcb,1356be80,b324aa95,e38217f7,c437f421,5a7f3e98,ba803fd8,5cc04445,bc0d9ebf,ade6c640,d16b82b6,5328a2,d5ef2f8b,52aeadca,e406ae25,e9b756a1) -,S(6a0f3b01,9e3b2a9d,453cc36d,275fae6a,b94aa14e,e0b4103d,137b1741,8b446ba3,ef30c9f8,46c54902,c10a4ee6,c5013b25,709e7109,fc004b6,e291b1bb,a021facb) -,S(83a62b60,6a1c4d03,1a18473c,f2230088,1d767332,9513b7a9,4f402f18,3dd45640,b23888d9,98bb9c00,ea57c9b9,517080de,95e6491d,cba0d7a5,729ab99b,12a1246) -,S(d2781bf,4b059449,75da8b83,cf82b43d,b5ee89fc,168186bf,74f22321,30678492,76fe1955,18e00974,6af44fb3,6e623f4b,fd0ae8b6,474e91c3,3ec364a3,91049d49) -,S(e4445252,dc6acf3c,f7b3663d,7176d46b,efe95e40,3063d1a1,68fd5742,2795a986,cf7613dd,eb200aef,e665bcf5,a6dd7fe3,cab6ede3,877f6a28,22b6620d,1eecda68) -,S(51f59cbe,68f523b5,b435633c,ce11c0fc,ed2129f3,5d392b2a,ef789044,722052f5,10403f8b,e7024887,3c4f0aa8,e4d0fe46,11f34268,178368e9,1eba8e4,d9b318fa) -,S(7d1806b8,410ec629,77fc41c8,8c86ebcc,74da9a0f,c6b35c43,68d069a2,c8c974f4,efe8890f,5aab9bd,c2da2956,bc089b58,b67ffd79,957ce0dd,9a53da,b26d68b5) -,S(add67544,8cb87ade,f8cfc3c1,85fbce12,e0d1525b,812fb5d0,2420481d,b22dde96,bb80527c,b22a3bf6,728ba305,bbff36ce,c6b44d68,9cf79ffb,93030460,8f461174) -,S(ceb2968f,fcc7b751,f9b560bf,b08f40ec,ba1395fc,9a3f63f1,65a1be1,862c3dae,67727357,b2dc8d2a,47606c1e,ae61ce54,1d79ba49,4a5e310,e0435b,383cf088) -,S(3a03b03a,1348cf01,afc60665,26b6fcbf,b3977ecd,7c17725c,a9f0c494,f31223d0,3e71c6e0,7da0635a,a2fadf5b,78c892c4,c95f794a,88594b72,183a9b2,4dcbe7a6) -,S(42ac22a8,c708f2fa,559f9b9c,fc7ca705,4356d18a,95a69137,bb8b8b17,2b771aa,ef669b2,85ed6abb,477dc2f2,bf0517f3,794c371,9ba5b267,8f622eb4,aa4ce374) -,S(b2ded9ee,ab06f1c4,19c5aad,5163e731,722c4923,818185c0,d99d6a8b,dc603a06,23bb4786,f84e6c75,e565a708,2600585c,e1fd60a2,b935bb4d,390d07ee,5e8646dc) -,S(ea1faab0,bb0b6cd5,454e63a3,d1546747,cf9707c6,48e4837f,3fc6b6f,a2ccc5a8,8fddc23e,651ebf4d,89e54148,2043fc34,7c26b66c,b2ad2d80,1fd2fb7e,77d4058a) -,S(487920c5,14ce0cf0,9d939ce5,81e13409,9fcad06d,3e6974f0,a3b5925,12cb3a86,db447217,8a92e9f8,65a1b022,3baf54fd,618a87a1,15887f02,11cddbe,986dc927) -,S(6828652,aa506655,60349cdf,132ca8c8,9a6f9a1b,8baf6adf,64e10c12,9ef9217b,9615f563,20db2860,9062aca4,7a136e85,40ebab0,3f8b5f7f,93bf0369,aeee0cc4) -,S(b66a66f1,9c94868b,3e45139c,ef9d7586,1a6d06db,72027814,83dbefbb,41157a94,5c0763d8,8aa90b2f,ee04eab9,fb96b280,5ed5f7e0,58c9805b,64fb17ae,9a0f224a) -,S(5318b13d,a824dbec,eced642d,d742ca30,479874e,31c1013d,d770a0b3,c9ddcd9f,13093540,9b5d56cc,d5004948,3bb22009,4b7d5a5b,6d357bd,76b79117,458e60ef) -,S(6bef6b9,555f29fe,b5277c48,863c990,8f1fe2c9,5b4b45fd,8c5eb482,3ef4964c,36c00eed,4281871,fc5e15d7,7acfe3c2,6793455b,9b3607dd,71f3e163,9790e3a2) -,S(7972f783,4c010837,89b92a08,d21b8b8a,b6ff6ef7,92eabe32,fa1c92da,4c8dba6,2c3352f3,f458a538,f8228321,c1adf9d4,a2df9f8b,bd22675b,afbdf041,9538f1e3) -,S(7f03f087,168dfd24,7a93e840,e68cd221,f02735d3,93d777ec,c9d2c9ff,7cb0228b,663dc741,fc8e98d0,7dece960,5b506b5d,a5f2af72,1b64480b,1dd3e7b5,a0ee7743) -,S(d06ffe61,973be011,2f17bec,6f4dedda,9b9d310,4ed22ed7,d4c2f009,843d2c04,175f409c,edd739dc,5adea16a,187a951b,d42df4de,d1aabfae,d56f1ac5,26cda8f5) -,S(9094c510,3a34209b,45f7062e,ec65c14b,72fa75f4,13999117,38cd7f6b,792119d9,da541e51,7211db66,272f8f8d,413e1717,13cf499f,6c9cd694,b98e53df,45e9d501) -,S(22bb9cee,8a5b99fc,d7ac7d67,5e232183,3f71a72d,55248a3b,451699f4,9f151eba,841e7292,93a98297,ebf2e9a6,6d106325,265d91cf,f7e4c245,845e5a40,522b94a0) -,S(b548dacc,944b013e,d50dfadd,fb84173f,d5829b2f,69a2242b,c152684e,7b8a3ecc,6c7b70fb,9ae39eaf,583939b1,1a1b8aad,673b18f2,7568d2e0,b2680b19,8c662a88) -,S(34f46e0a,2281a617,f8ab78c3,86ed27d,f837f23e,e986dd20,bf705daa,1b0188d,4ce4df08,bbf1e735,6760e05c,6e5d3f3e,664fea9d,6e1a72d6,bad17bbf,a3c089d5) -,S(3063ee2e,3834842b,84cce6d9,50ba5afa,1d645c5d,e0acdb00,a9cc4ce3,c266f649,b08247a,f79c2be1,a0e4e021,7c9ccfde,f76d1e46,65f3185e,8623aaf8,63bff9b6) -,S(d7232b55,3740b2fd,464a919c,46168ef1,e09638e3,65117eea,979130aa,d40fc525,f842c256,38e84dbf,47d13fcb,1763a296,47b72908,1b522623,4e307dc0,1a402ded) -,S(6025e82,e2ec643c,32b10e6f,62ef310a,11576957,96c10f8d,b099dd4e,1dd8cffa,1e5aeacc,cc5c5455,d542dc51,b12fa3d1,75061cc9,45931548,7467d09d,945e2596) -,S(141d07cc,256c4d2d,44ddb7f2,ef720aa8,4bef767b,3597ba32,3b39915c,1d84f175,a842c439,9366b2a1,91e850df,333c9cd4,6c983158,cc57989c,588c305a,1144ead8) -,S(ba4ad105,6ffde493,54d13149,31846519,86fee8b2,728917ec,bd1a0112,b986a90c,97ac53,f84e995d,92d14f0b,b156f47c,be5b6506,2a7f8b07,7e235da2,808029c2) -,S(5a6ed894,bae212f3,eb44304d,98ffba1,4a944cde,ccd12517,5e52d767,5e0f801d,d8160707,d43053e1,e5806d7a,bc17563c,ffaf92da,ac51deee,55fcb9ef,715b08d5) -,S(d82a95b6,56bd1abe,50933a3f,e291526,7b257807,c8cde42e,5f1648c7,f35c4f3b,748904dd,3157bb07,65f94c18,7528c74f,ac639a36,be18963b,676b9b37,83f54591) -,S(df7c9de9,8e748188,74967340,34a76645,c1e55bed,3a90fc65,dfd9726d,a2bd3826,3bd77fe3,e4a4018f,3e256ca0,2bb5c8b1,b783b729,21ce329a,fff9caf6,b530b1fe) -,S(d3ae1d68,4614c95b,51cc4af5,a9e8a05c,4ad7eb4a,ba4a65a8,9a151b96,d91bdb68,a24cad0c,ad0ba98a,860d6d74,aea57c3c,23780812,5fb2356b,b55f0bf2,95e25e67) -,S(ca85c924,48a27be2,2b68c9f4,c9ab431a,b380ccec,2439c8b1,944c234c,bd865758,c53177d7,6b16e0a4,389e1e32,7072d460,90e92f48,22043bea,924fab46,4023038c) -,S(34309aa3,4e9fda0d,f2c20da2,3e8f8f31,eebea096,1e769c92,6c4251bd,5440bb04,f655cca9,d5811164,577d0525,2f5605d1,b4e2b6d4,dd5540be,aefed4ae,84caf3e6) -,S(40212a4a,b2bfcac9,62442617,8a807655,185d2929,7e26c437,4879903b,41307b3e,26624605,6ceb4509,b481df00,79e25f1c,4dfea60e,a3768e8a,462ac273,8166dfea) -,S(2e441425,d121e140,5d2118b9,7a3b305a,fcf62e91,4f24bb72,46e92aeb,1ebdd152,c3c7a567,51dfd709,9535d07,23778131,692dfdb1,7584d9c0,c8fed42e,5eb662f5) -,S(31539912,9e59668b,49d9b8bd,5ee66b2f,aa727ff4,96f457f4,33400a20,b5242b5d,5e90a20f,a700c59c,fb0ca2cc,ae3f2837,6dde44c0,3cf6af64,365e4cd3,b4e6b3b4) -,S(3b586e2c,30eb1959,bd5171ad,54b81c36,cda6b0ec,b5e77b41,a7b5b0d3,e1ed4ba,6782aac,d675436c,d969f413,c471edf8,ff7d89a,d0a07575,16bb695b,19ef40fc) -,S(f4299c9e,b3453201,375b972f,fa39f01d,90c68625,a63c9d06,513fc9c,8c623fc3,cbd0e2a5,f9b9ebd3,f482a5bb,c5c17894,d5c320e0,28744292,31c94fe5,55ecf68e) -,S(96d35f35,eee50b32,32371acd,99d6db8e,d2b7c4df,1f62b867,5559543b,785503d2,c0e8bce8,8bee1e02,29a5d2ac,113c9f2a,feff0260,869ecde0,7cdb1cd6,3ba5f73f) -,S(ad3036ec,e2bcae0d,1fc34680,be2d293f,b40d9133,905af375,1ff89c49,2c183e1f,2c0773d4,bd30833d,24222f89,3a4f5e8,cd6abe06,63d66d63,2d5fb832,4c260f9a) -,S(a0f340da,909f04df,70a33195,1c48901f,6353f4d0,4d22f99b,3763f567,be9d207f,caa1d9de,46a37b8d,623a39a8,6792475c,bf3bd694,597351ac,515ecc8b,1a4fe78b) -,S(2adc4874,af0b3cfc,675421b9,5369ff0f,950b55d1,331aeee3,dcd0adf3,859be4d,6ad9fd3f,a840d02e,ddc01fa0,ffa61bf9,4dc1db4c,ec733976,bf1c6e41,bdd92b79) -,S(b9222a37,c14456a1,cf931410,d96cd84f,a304b9f8,5a96edd7,6e67f928,43536175,4002a875,dfc4cda7,4ff7145e,ca46aab8,8cfc5ed4,53b34eeb,1e5dd859,4793e3d3) -,S(530bae23,c3796fbf,76f86f6a,d8b59b80,801328b7,6c46e8f1,cba6398b,270919f8,d4d3b34c,6701f07,bc47d1d9,fb868fc2,b46ff397,2086cbc0,517e29d7,38a7964c) -,S(a7f2ce51,5b932506,c740e84,40f254d0,e0da57bf,4d9199f6,acfa3664,ec36b823,4946fc41,3ef1b3f1,86a2c781,6c05ce7f,803fc7de,a00fbc2e,7e6c4688,fcddadae) -,S(8ff613d1,1c81c4c9,fda3860,cbaa71f8,eab9ac3,d9263f31,55317949,d6ac1d53,54f683d1,fd382305,b2193554,bd3a6d2f,bfbb99b7,5d9c3e1b,876c3b52,e2bdef49) -,S(6fb3bc81,5ef3d8a0,d7aa1a69,dccbdfb6,3f7a58c4,7a12f98d,b09cc105,4306422d,798fe7ac,f9fc71ad,7023a8e2,c9376161,8fa632cb,ec607109,d28a63a3,9a4228f9) -,S(c32aa38e,bf0ec0ac,61bbea0d,d2c633c0,bd49ddae,d77179c7,e0098c8f,4488da8,e01f5fa5,1107cf4c,f4c1c5,78c3b5f3,a1baa059,90bb8913,9e2abb30,2e9e5042) -,S(ef5e1efb,d1ede40a,810434ae,833a4681,5f9021f9,41ef1d82,fb8c1399,16c4933a,94a9cd1,5f160c1f,4f85ec8,16fd1834,9cf19f8e,96ac9247,695ca37a,dbad6ef9) -,S(8e3aacf5,33de35e,4f923b36,c378ea57,7a5aa477,70ea6390,f92c73d,50fbfed2,49cd7650,ff69ed12,b96ac3b1,420784,7677497,b731e0ce,316eed65,7e40e014) -,S(84521790,204c64cb,e026152f,474b0da2,25703d93,25943821,7d66f20e,3ae0d06b,c1da2f7e,438fbc82,57f7fe4c,7e49b73a,446a19ae,775e7f1d,20c8fa31,edc3bd20) -,S(604cd900,97fe538d,b27cc2cf,a2d6c79,692f2e2b,c1b1b23d,1f0eb949,df560697,914d5288,29765538,d77f8e04,182c50f,d2d9aecb,2412ce47,4888d666,46b2258d) -,S(c13a44bc,9a27e241,5531b8a0,5570e66e,6763b3bf,a80e00bf,59d6124f,b3d67858,71557bf0,4c261c2b,19196d0e,9e459f3a,f629cc19,84f411,31835400,3a60563) -,S(14f3399d,5204b654,23d9318e,4adf3af9,dc43099,eb43b719,eb4644a4,897ffbff,13808cff,4c096655,72329034,d489433d,976cc011,d1a30ced,702ba4e9,5892422f) -,S(bd84d712,43dea7fe,f151b207,5d03d2ee,170488ab,4175965b,128411f3,f592a36d,57a1c602,408fee75,ea9e683f,43d7a984,bf03d66a,37513c50,5cbec6c6,6d286fc0) -,S(f319d4a9,b5f2c1ed,6619ae06,e5aaabe4,13a2a6c,265283fe,4a51c7ca,6c49b572,bd9d90c2,2a369a03,1856ca9c,86426171,db952537,edbb1ba8,93fd16ea,35aa43b2) -,S(9649689a,424ec9f5,aa4cf4c8,45588046,c50eaf9f,700d0412,83e02640,9a80c61b,5cba8567,95b0440a,53e0d1c6,ad560364,c398dda9,d2e97a1f,e594355e,1402fa33) -,S(45fe12f5,a340034f,381764b0,adf503b3,8026374,70eb26e9,6f4181e2,68cb1c38,ab7715c4,52e5581b,ed940fde,355892f2,b8a16a3d,d322123c,14a57a23,72f244c1) -,S(98bcd24c,3222401a,a4683213,5a378790,6c9812ee,989b8f52,fa522c6,d39adcc7,14c7cd38,7bb5191c,f49bbe41,52af8b03,7135a6a,bc7e4697,35a72a38,e44433a4) -,S(6dc56512,7be34196,a7653057,f79b854,83c275ab,65c05c2e,83663da5,31d7d652,a6839fcc,ba7db053,affaf5a9,4c95676f,9d65eba3,c2474472,cadbde17,2ad3692b) -,S(7a7f66de,b04492d1,fd2fb9aa,dbc4ea7b,ae5a3801,47b86e68,60513a57,eb6b10f,fffe4f2,b722f36f,1e555671,90d84d9a,39b819e,fb7a3436,29b83adf,f6045f05) -,S(aaf9f188,3865e2f7,eb500794,3888b4ec,9013371,f7162947,2cf52adb,bb5288b,df634c19,e7496b4b,478bc10c,7c00ac8a,5fc24dc6,4f193355,f0fa9c62,d6048243) -,S(6304b1d7,56988ca,25afb747,476acbad,2e5afa5c,86136090,c86a82a0,e52b373,91a2d829,2357463b,ea1a7cb,33d79be5,8bd71732,f1d2cc13,ba4b2724,6fd39f05) -,S(6eb17147,2aad3d80,bf4e06af,a36e37ee,5fed9c18,bbaa1c4f,5cd871dd,c526515b,6afd615a,e2512fa,70c9670f,b56682d0,f304a0c,6a23d1ab,fe958a7c,2a4173fe) -,S(9113b613,ba815ca6,43e7bf66,27dd71d9,8c2d40ea,5c00f596,6216ca9d,d32b1ce,8790dac5,bce4100b,8e4e5135,66a104ac,b55d3ca4,3d6ea083,d23716d3,3894de2d) -,S(5c7af38b,8821169e,2f7e2edf,18b3b73a,c387e6f6,a8ef1cdb,441f5a13,284f365,e12619ea,e2a07b8b,c55dda85,6cd37927,d448cf2a,f4028459,2e371e10,8e91358b) -,S(becf19e9,23fa7b4,1cca0efd,937a5b11,e227fd18,22743fff,80c42692,6631ff0,3213c209,9f255eee,93323d1f,b440cbb7,64e86f1a,4021b82c,485517b0,3440ed4a) -,S(f22954be,430be6ab,34dfbf92,264c2406,df3a0a7,19ed45a4,d09cb161,4abb0c91,a60397e3,ef3308a8,12527744,311673b,c18bc43f,352dba00,4dcd4124,7b84846b) -,S(c50ae8c7,61776e62,5156f9fe,7d863c36,79d43126,c5f3fee7,5b837a38,1803e770,be966bf5,99b67e6c,ffc421a5,e6d12e4b,cbde12,4d84eadd,781ea562,aac7dab8) -,S(c6c3a65f,e849c113,748e9b6b,c9a9419c,1a919503,36201a6d,f989bc5f,fa07d359,fc205b83,b4764ded,ef58082,11eef120,4d9fa959,4d5b7086,c2fa2c9c,3e56f37c) -,S(73466c27,8d5f13ad,dc7da10c,b8855c23,9069f57b,6ec5e80c,e27191aa,196d9b1a,7e7e2cfb,533cfe9b,24243cd6,7680ade2,35abddc3,d8d00faa,c8adae39,15ddf6a1) -,S(6315ac10,35eaf884,8919bb56,759f7013,92fe442c,771a42dd,dab88ab0,2fb0df2d,a49d2c97,6e0e66b4,50e8511f,d91f0f71,a7516fcb,70ca61a0,98f135ed,8e19396e) -,S(fa195146,fdb7ddbc,41daa8c5,98e1f811,36c33eb3,bf23dfc2,3f20b36,1c8e7bca,324fc70b,38677dd4,c8e7bd82,4b836d0e,738dd757,ca408ff1,95bdd5d2,bcb5cef2) -,S(ac40bc48,87734bd,51247e91,43e5e188,e5e2bfa4,2e3c0392,f39755f7,3952bcad,75904ebf,603c2f07,4eef9435,eb22c663,1279afad,94d3bbca,d5349881,7dc4a472) -,S(15b7e1ef,d2c41c6d,416b6dd2,5f6612f0,a0acb0c4,1b161b4b,c40c5ad2,a92604f6,a13da672,17501833,4c4057d8,85be8fb1,ceb6d369,6979b805,83fc0a37,bc27a0a3) -,S(adf4aea6,6fff705d,5bff3c84,93e8870,4ba4019f,ed550cc5,c203439,ff8512b3,53ad2122,30528e1f,4fee43c9,2369dca4,3d071177,3ccfff26,aa16a502,6206a3d1) -,S(da0d5286,fc261d92,1095e1cf,f67e729b,501f21b9,45e8d84f,ba2c80ff,335d105c,5632ce7a,e8d9ce7d,aac7cf26,2ef7bd27,418613c,b288e793,35a0a638,6abd83f9) -,S(463fd081,daf02794,18b95a48,bcb8dfef,3a9dc67c,2237d2e5,dded1522,f714d6d6,3de4cc76,7126750e,4038fb43,bf6af17,63ebc0b2,ef56ba8c,a376b815,6b4f28b0) -,S(15e37b9f,58ce033c,2f0ad85,d49f8207,2e2547c7,91c7ec52,a8606974,2badb586,38816873,5e37c957,c18ad56a,e7ab81ca,8fd89a2d,1710f032,54393ae,a046490d) -,S(2e121b79,765d4f4e,8e7aa8df,5c70e4b3,716b976e,9e4536c0,dbb3b5ae,4044a345,d7ba59fa,97a7d6b3,8b70ecea,312cb01,f9016b33,c160d1e8,d33fdf50,ffcbc928) -,S(8d4c7aa3,c59dede0,bc146b10,38f8f823,8182c4a7,1cde0d8,e17005e8,64ad29db,78aa343a,28a48f90,edd7fb31,849d6d3e,fdb4c677,73cb523f,82c0b187,2c17f44e) -,S(1ae12a1a,19a5d1,3b2f42c,35a385,f8302721,86a67801,c22818f6,94438c58,5cb421bd,990ddad8,16de9439,87bd96e7,e1ddfc5a,8d0f86f7,b30e3483,897815d3) -,S(7a6f584c,d48be9eb,a7b73377,8a173d5e,3833aed3,a603a226,741ae1f3,a1c21bbc,5995b840,bcb6cc28,b83d048,9faa5dbb,c6a93190,46b11b13,59827266,d177d27c) -,S(2dc5ccb4,8f78db2,3f0933f0,ef67bea0,53c7f2a6,80788bad,b71526a4,f55fe758,9e4743f9,ddb46206,a5449942,71743b44,713522f5,f358ab47,34c9afcd,f528736a) -,S(f7a5219c,75dc4426,4322bda0,3b603127,26a6b3aa,c471f42,a33072b4,a44fc9bb,9e1feda5,5da277d5,cb18381a,4471939b,a12c692a,a40ab965,fd03949c,d8124ab3) -,S(a1bc311a,e29e3926,5b3be1ba,23d7ffee,df0de8af,fba089c,fad797dd,8ba67c68,9abf66cf,109821c7,68c98164,b0598068,c4590d7e,b9ff4c53,594af6e8,e0ceee8d) -,S(2c2ffba2,e3fee930,fe8d061,3bbb8290,22429fc6,654d5ed3,61eb8720,1d6b92c5,ed89f28a,bad9510b,acf44d05,5934cc64,ac7e94e,2dbc72c9,986e6cb0,acbe434c) -,S(1d157e13,97f6b22c,3dbfe448,d1168b8a,bc963f86,bb3bda29,a8011f07,d2cb5ffc,bc7cfad1,e1633419,cef1c82c,d0249ee8,4c38b3f9,d628337b,aacf0449,4ca3c0b4) -,S(1b9e9723,56f8a4c9,5e8d5fbc,8e2f2cc5,99c77d62,90b2fd44,2e63b3e6,dc33c772,59db6eef,988386fd,21e8a772,a1fe048f,95ba77a5,122253c0,1a52830a,bc12742d) -,S(80460a3b,16fd9ba2,250b07fb,c77f2526,bec5488d,7d6c45ae,6f480308,39af48fb,bc7648a7,744347ad,e17da2e0,5cd1ce10,db704acd,26c81fbc,db251ff1,c6fdef10) -,S(c6903a0d,d8c26c8c,cdb675b5,972aa050,6912813c,a6f0c8b0,2edfb792,491222e7,f4759b4e,9db7f1db,7c8a1c38,dfe76d86,c3778423,29280aec,12b1be06,d8e49ff5) -,S(95ab78f3,a4268c8b,39aa645d,8c9fbfd5,b92469b0,809d6369,3d57d076,d305a241,8df4c8d0,ed85ac01,a965d580,78f36a5f,690aaa03,d9479d1,b2297a52,53e3c6) -,S(bafa3ae4,40a4b8d0,40862a18,cca806fe,8cd0e780,483b396e,41543486,db91d9b0,d7bd60f0,c0ee0b8e,38aad85a,85a42ede,56c66d54,ee73d371,a3bb7cdc,e93df670) -,S(7cbf5d9e,3bea6864,b87ae157,fee6e352,dc3a4f32,6e7cfc68,377fd199,a6dbb71b,42d082e7,5d55eb62,9771942e,3801c27a,fd80b502,a997ccc5,9f5a95f7,d7276999) -,S(9108db63,751b8a9e,f4870524,f1198f9c,c4d3ec20,af54119d,6011f263,de13ca29,8c1d6c47,aa016e83,d2c8f76c,df0935b1,b6f909b5,bf5c90b,f4203493,22c711d2) -,S(a705e7eb,c20ac4d7,43be660b,d61340c,9629d069,1b08ef01,a59e78e8,2d8b347,1ed8ec9,13ba19e0,851e1912,5854433a,f71b21d8,df64958c,afc5d7aa,cd29ccfd) -,S(b75483e1,60144d46,78af9a3d,701c4ffc,fe154c49,fad45ece,3945289d,c3781c3,a4c0455,13cfa7fb,ba2931cf,722fc569,87b2c79b,c4b94313,5a458d34,5ee16d57) -,S(c59aff26,bd4fdb9,37468989,763376f5,64abce,c00d54e3,45b6dc2d,9b7b76cc,c396c194,db446fb1,a22e86e1,8a37981e,d114e675,474bd24c,784daa96,91eb15b3) -,S(2f6701c7,815ba7c6,37c4649d,d05a31d3,e909d8ba,931e7136,1e0662e,3ea19985,937eb67b,9262bbd5,12a21e90,393f9e65,66e03203,55c77afe,cb98d1f4,bd25e8c3) -,S(170d1e33,f0862542,dc72b1b2,950ba98a,812cc308,74ecd0c9,23ce7c09,ed7cf9b3,5148ef39,68ff35f7,a633ba7,dab6cdaa,54dc6f87,510f1a7d,4d3019f0,c00bc868) -,S(743b02d,b02301db,453f8694,cd517c6b,433f609c,e205cac,6f6a49b8,55890708,7af6350d,56130339,1a9ddce5,f566b9b2,9c10d535,d5183850,6c743124,8dcd707c) -,S(ba6df8bc,f9d83988,4991c6fb,e0aa0ecb,d0b6cdc4,d0e372f,3ec83b51,da6a6570,7d27b176,3a01a8bd,fb7dbe0b,226dee6a,73ed3644,807ca33a,1f5fee61,cc161fcd) -,S(d3b63a2c,364f01db,6a6f384b,4bba6c2f,2fa46a02,86090826,1c8b5045,4b92ca5f,df6b9cfe,fe7aa14,a38bc44b,8b627b6,e0ceeca7,1720d630,cc4fabf7,b020e2d2) -,S(638c2b1e,374ff6b3,4b634f4c,bf363bbb,55d66c8c,af4d3fed,43cf436f,a1daa7f3,9854873,37b48f32,4feda3a1,f267dbe8,8831aedf,d7bd36c8,6cc8d862,857507d7) -,S(1749ab4a,607d7864,5c4cbd30,4bc34c06,94a7a636,9c8c8f8c,be4602bd,16c4b4b8,465bff86,b459b842,dfae4df6,99be1758,8b1aca97,f9802827,d892792c,748ac92) -,S(9071a5ff,ff23ae4e,2d81b2fe,d341bfa9,cb86ae6e,ed32870d,d549af20,a1db9feb,c0e3d4e8,277d099a,9801ddf3,3e513aa9,1761218a,967d530f,21d70894,ea7d38ab) -,S(91bc0055,28e2d857,ac644954,242fe0c7,bbaadcf2,9119837e,898244e3,a305ba6b,6fb63758,3aefe600,46997b88,315d5a24,683ff955,94398694,be304dcd,8b588f67) -,S(9663913d,48c865f6,312fe51b,6e8e7c6c,51ae397b,d141aaf2,df3d6ff5,edebbe68,c6251751,7e24d81d,b1da26a6,6627fbb3,28b5f818,6477b34,43f7c36a,918753bb) -,S(e88e8702,7843b941,61c71887,9a0a9a90,cc0d6dd3,8329c73c,a18acca4,3f44ffc9,7e31ae63,1f9c927f,bd055f58,e682935a,3225e778,9221a062,f2826d86,97143a61) -,S(5ad27e79,dee03a52,be771a9c,ded6a02a,58337f26,be810d1a,f8cc5ddc,f1eeb917,91c18e01,dbee34e9,a5302a7a,11bfa7fd,ac852e1b,e53aec2d,3138259b,bb53e6f6) -,S(bb7f4694,f2935a5e,8711ae47,bccca550,cee2632,4347b468,58e40c74,49111ead,d9f94c14,332ad75a,59dc784b,d674e8c6,146a2b74,566ac1ef,b0ca17dd,9eec8d74) -,S(ff77ae06,e0624cf5,f6d905ee,b0de7281,5377c026,3e01b6c4,a139e4ac,3304e82c,1f27acf9,933d08b6,f0892199,11805d14,1611a318,661e6e7c,75014b84,cc35c395) -,S(84c15fb3,1b12d39e,ae59ce0d,f8646e9a,67c85492,8d6c498b,4b836be2,eb19a060,6aea0d78,d54090e3,2216c3ae,be0dd433,a666e67b,44cce0ec,1609804f,fde33f74) -,S(9a48086a,8bb9b150,a6ccb966,3978f555,41db6d48,1b3d5266,e958cbd1,df9ee7ab,d8eb2109,13ee09e7,b5767661,13157905,b3cafed4,641903b6,da0ebc08,a0ce2f58) -,S(db32ad19,45f4d9f7,eff1b8c6,b87c5545,1b0c74d9,8f1c4ffc,6ff1e79a,21ab3033,2d56e65,a70bd23,617f85f1,4a5d0e4d,52aa6a70,a8594158,36d02d87,309c7eef) -,S(4de7f1aa,b9089f5c,b6d95b67,a04952b0,d4696cc7,6640e1da,f4bbf7d1,da985851,96f2cd33,5fd4b816,4499ddc5,5e81f5ea,c4db4399,17f2151a,f86d2ad1,e2b3612e) -,S(74bcfa73,5aa43e8d,1fb540fc,9922362b,21878c09,666bf541,a0e739b9,dcbfd1c6,84b26fc2,8b2a05cf,a67947d4,99c1ffe8,f94ed4d4,6ba583b7,cf26ee81,ba60bca8) -,S(9c596bcf,3d2e1df7,cd8d9807,8a1ab17b,f16e27d8,66cfb582,ef58498c,48ee0fc4,14dfc093,48f72d7d,af9e3599,8b5f18bd,5287f3f8,381308e0,63666028,dda9ac56) -,S(8e2a0d3b,2786d67c,a15cd72,4f2cc6dc,16cddfc5,cf080ef8,d9576b2e,e5b0ff9b,2ec4853c,c83c72d2,68555129,ce30c836,50fb59b5,17a3d61d,56ac4273,1b33ad06) -,S(25ec4838,5fee8fab,773498dd,85a23ec9,46c59839,14fb8a9f,d1239ea8,ade3f829,123bded6,5312030e,d4760047,1867aa4d,b7537239,b363b6cb,58ecff98,44986924) -,S(a1cd9872,7551e2c5,db7985b5,1698b97a,31b90d3d,32fbe60d,34f8ec2e,398df76e,40858565,aef814bb,8bd91fe1,410f9556,3f1bd170,345c1283,b64fb268,4980c398) -,S(bf7d3973,aae2cc31,e831390e,f2458e85,9ed6847,e9eefd6e,cf91e3d,4a4924ef,c2829fc4,2127b303,c801605f,35602b84,32357564,d9333ba8,d962d639,ef21a6aa) -,S(5a5299ef,e0d394ef,f4b510ba,96dc73bf,6332d358,e276bddd,527ec290,b73e3313,9ccd4618,17e18104,d324e1e8,1597eba0,cb6b475f,4e5f2e02,9cfd2d63,b613de79) -,S(90efd8cf,9e4b9d74,5cb36c13,20a8bb0d,b5cb8578,de49ea4b,c289043,e2ea810e,87a73339,aaceed7b,af47b5eb,97aca554,d80a4f78,d439ee14,4b2d0fb,f8df5e3a) -,S(3a174294,4db7f2d7,2498e2fc,e2026d5c,f8600ed6,958db97c,24ac0de8,417f6def,e60c566f,f3fd14e2,2ff0cdee,45c4c2,31797951,7aa0ca68,af91a5,e41f5f60) -,S(2213e0a1,3679040f,73e4d68c,bb941665,6ea83640,33abac76,2e64d509,48a97656,2b87ce0f,bec2728a,aae6586c,bc6d9a89,a4bb9b9a,211de522,cc909279,5860791c) -,S(382412a1,ab396523,8b06c47b,e941051a,bef3b215,16efb280,3ff3a1c4,824954c6,7cae8b14,1938312f,ba482980,ab9073da,c66c1ca0,d746231e,8ba8f331,4cfd9cea) -,S(3d76bfac,89c1269d,53b6ded6,bf13c785,361b1fa3,84be2ea0,d582ee43,f06de56a,18b1cdbf,96d12859,bf887b89,6d8f2e6c,a08b892c,688c7687,8294974d,af6d6284) -,S(715b18a0,68d86cfd,41a20541,847b36a3,ed7814c1,b5528751,927042f9,85e7ab70,2b8e0228,b0a4d39b,85a3d3d4,f5a10db,c6825659,f4b967c,361da449,24890911) -,S(a31a10ea,e38e6a00,ab4f004,8b45c8a3,e57856b0,d0b64e47,fa90e234,e17943f9,5d4b5150,7d3f3a82,87e5d51,6bb30b89,2cb9f540,96aa5962,1f77e028,480e594c) -,S(b397f965,1dbbb6db,34708066,a1743511,d4a16332,95f53772,72c43a6d,6e21c1b0,673fd327,45bea2fa,748a759,30679b2,471e4004,423dc8b3,f34f95ea,f88d2b8d) -,S(2e4b865b,c1245325,1ad8b3f6,e8776bd1,a5878b93,ec34f847,65af84fc,146d9919,b3e7d479,661ce034,50094432,c538f55f,c8be8693,73a91fd0,350c8089,ec0d76f) -,S(9a38c790,7c0751e5,ba750bc3,485b4a4,72b661c3,63a3980e,feeaf59a,98533a43,dad7ac3b,65493036,d30068ca,72808000,d54b42d6,d263de93,a1ced3d8,fa82ca71) -,S(5599d251,3b3c8337,f8af18ea,70d1d2e1,83f3e363,63735357,2b3f6cba,b4371d9b,7ccddd9e,ec8dd507,69f6f633,cc70488a,6a4e322a,2716218c,5de50fae,45398dfe) -,S(610c472,4699e983,530e8a32,b60a8077,c7f60226,cc3b2010,e49b2e30,f2a98afd,42157de0,fe6d8e53,17a3f565,fa450f53,8755679,6d98c7a7,ba0b3e96,844d25d1) -,S(89c082e1,1438e2b5,6a4bff8b,cadaf804,c9d11fa0,8f47bff5,39cd0741,76f24a59,f4dad4e6,19ccf814,e899d48a,904a88e0,6db6ab19,a2e06a7,b359db9d,cd0ad0ec) -,S(bf810fed,48d1ec4f,77cf3732,ed10a44,df9e4540,2e1a1e1,6b29c82e,32537565,6657fd30,337e294,fa31d30b,409b426d,546a47cf,38cd23bd,75aafaa0,b527d66e) -,S(3b1317b8,bb3c9c91,964ce369,19ea811b,90a8bd5d,ebadabc2,d4d1af3b,50fb3524,cfd5988a,78aa555b,595531f6,5fb0e3f1,e756c1db,626cf60b,4c1b17e6,caca603f) -,S(88520439,61558d79,7b084143,783d9e03,791e6183,c932d1a4,17eed30e,bcec0bd1,271097c4,4c723ab1,c1d13e9,93b7b232,235957ef,f21a13b1,2b3d302a,ed46ba1) -,S(6c420c30,343cf500,da0cc05a,c315d3c3,45ed8aa8,e0551bb0,32fbc512,732f34d7,fb3c0808,698d38f8,3310fe1c,15587cf7,137bef2f,666229b5,bc789dff,1b2f1111) -,S(b12e21e0,e060fcf5,580d75ef,22e8a800,33e2c19,487d0660,615f7d51,ba00e430,3931d63c,a6e0da2b,295bd22a,4bbb27f5,fb52d89a,3c4ac36,795747e6,e74ce944) -,S(4fb9da54,4da95655,c0de5654,f68c2820,a7884734,4bad6934,e671d56,e7bfe11d,16586701,9bc89b28,f5fdec40,78a2a51d,6e087ee4,29456cf3,d258b97c,209d44fb) -,S(18f8f6ef,23bf75f7,a7811025,5babbeff,792109ca,5a550472,245552e4,35588e7a,e712abe6,3a374f25,fd4b18c8,4b1451fd,ea77692a,43c0e3b1,cf3469fc,7a9acd55) -,S(d730d167,1bd36654,7188c07f,78d82ed5,6775d7ef,bd0967e6,1abddea7,7ed6073f,49c4bf3c,ad4e31df,d840045c,aa8be15e,43f90196,818e30f7,b379c74c,1d866553) -,S(a915fb72,7d4c40ab,547c983c,24a4f019,1f5e89ce,7ab0636,e903aef7,592208a6,fdf28a3f,6557f27,5813ccf3,8d927f40,b910c5a9,ddc3c83,14a48eb1,6a5956be) -,S(7abe8d85,bd95c580,cd9d532c,c1295f5a,ad5168d7,e3dcaf28,b19f5e76,95107157,694abe9b,9a6ed0d4,c3ac1db8,79b49038,6fe9d2f9,443647d1,91533fbf,aae3cc02) -,S(93a83e8d,c80c7cd7,64dafff1,edd148b2,9c336de7,cf978b14,fbd35625,c965942c,91ea5775,db50bf9,a7e3f79b,77c7d5b2,deddfa08,a1d455e6,fa21e547,356c634f) -,S(a334ed87,dfd2e1fd,699ce1f0,a09fe921,487f8321,6cdcf75d,fc8d7e5d,cbbd1af1,42a0874e,d148bd32,ba4324ae,eb0260cc,7f0d20f3,f43388,38904640,8f7ae7e0) -,S(811597c1,f4129ac6,e150c231,bfd8e4b8,4ad441ff,2c698486,affd4ac4,c22bf8b5,5f7fb47e,11b476cd,acce1552,95ac000f,3acb3838,6ad3c6ac,191dc12b,d1e299dd) -,S(cf754ed2,47c9eb9d,24f3129c,4b4cefd8,94b5e58b,832f158e,2e82911f,8177a59f,262cb605,2991777e,bd1ed5de,d2e7ce29,76dd73d1,ad4c9bf4,9fb5d8fc,fbe4a3d1) -,S(290ec604,a6b4d816,ffe75715,419b0f33,452530dc,94f48883,b3982161,4592b229,4235db3d,df2e3f1,b61ac412,a90f543a,ddcd519,4f4a315e,d889b32c,ec8f76e9) -,S(1f90b869,4bf9ffb5,7697ee72,29b7f20b,52b47997,35efd7f4,1e4b9102,51886858,dc3d7a68,abaf70b3,c84d533c,48ef38f6,9be7d26a,13c4e834,5a7bee29,c6d3c87a) -,S(ea20b4c0,931087a3,44d5642f,6c018aea,2da5f189,a4d25968,96110281,88545ba4,f9adfa96,f945e745,88d2ab41,e32ef5a,76b370f3,f0362e57,129c3998,e32cedeb) -,S(b8bb88c1,21948c01,3a61fbf9,bae86eda,28e9bb4c,6870b0f1,7109e5b7,c00cf4e1,90685129,8607d7ac,25bea5c6,1cc4feb4,4148e07d,2fc3fe7e,449773d4,8245019b) -,S(2345a244,f2f411f6,ef091904,81eb9083,9128f7d8,67e8b910,124d1e44,d116c529,a8eaf530,c69b792,d6595967,4f23b9,b0e239bf,b69d05ea,466f9f5c,9bd5affb) -,S(75aee824,38bb03a9,b9208cc9,b725f13a,1fee1aca,20ed129e,e5ecdd59,b92c89cc,fb6bc8a0,fe0f684,ce4cf153,2053312f,b97aa1e3,739fab8d,407db39a,737ee51b) -,S(ca46d3eb,c981eb1,764867,c99cd7fc,c414bdf0,31b2c9a8,96829ebd,f31e2e36,46363355,862a64b,97541f7a,7fc5cf51,ecae168c,c6530db5,3a7f2394,2e87bb96) -,S(4fc1d258,575c4830,bc7a03d7,6a259406,7d633e9a,da2c734f,45ce4d9f,99dbbe7d,cbdc616d,fed2bae2,9312c5bd,9e195bb,bfdeb2c8,d1aee5e8,cae8fa0a,4bd6baac) -,S(4edae08,54365c27,f6ad83b3,8f68c7d3,f0a09c6c,153791d4,df98b5f2,3f0b9be,cdc8a485,8ac66847,c732a2c5,4be86af8,d6d637f3,e62c7802,dd71c7b9,2eb18223) -,S(624dca60,16beeb28,c35bef5f,e97d320d,d725619c,3faa7ca5,ed79d491,72b12469,cc33b49a,6fd125cc,98d65a81,c0713cb6,2a7e687,276e7fb,641e2f76,52646c12) -,S(6738d38e,760e50b0,6a18a9eb,b5e3676e,c38f3487,e34461bf,2e5d52c,5bbd6b4a,c3ce0343,9b9f624e,a92eecc9,860ff680,63a907d5,b57c43e,465ead5b,bef5e709) -,S(bcb74527,10f178a9,eb48655e,3d373b56,8f02036c,e9ab826,4ab7cee8,52f7f9c0,4e928392,52ee05de,587c91d4,6eaf5e5,92ef41e1,5a2b5c2a,da9e4512,c25bb416) -,S(3375c7ca,1b5fb4d1,1838ffa0,c21d7e03,de34ca5c,92bb4592,bb4598c4,2b490382,8c284e32,f016d186,875b87d3,3bf4271,4b9013c8,ea159634,b39b7365,7ea837de) -,S(c347409b,336c0677,ee95de61,f93fad4,738268d5,6f31059d,380af075,60e496bf,37dfcc4c,c13bbfa,5df43c69,eda0c68c,42de70d6,ab64a9db,a4ed22f,1cec3fdb) -,S(305ea4ad,ce72ff73,976544d7,a3deb346,452ce997,f280c3a6,106b7c9e,3b9bf5d6,bfc33cd4,ca178310,c4caba86,5b87477,77e9e572,4278f0f0,56b86a86,1f2e13ea) -,S(8333f714,70e57841,312a33bb,4f1463df,d237651d,fec4e1a6,40c0ebe7,478c5a9f,d39b03d1,11657c2e,19ad78d,3e1208ef,f8505695,1bc67098,b891c42e,b427bcb7) -,S(500af03f,eba3b646,a0690f0,74cac255,804c8f8a,c2aaa1f5,f5cee4e4,41913e7,5e67542e,8a8f0411,e9985a76,97ba626d,f0607f66,9f9c11da,826b47b1,a52cfa2a) -,S(e440385,c16bc15,5023cab3,3e7a48e0,5e7e0c57,e0fe848f,26b146ab,237a3abc,dd8ac982,b627fc9d,7fd83c26,51805de3,d7369ef9,2e970664,8744badb,3db060aa) -,S(83eef59b,b0a26fa6,60c94e45,c097bcfc,8622c37,cec46eb3,f9e93aab,d0fa6438,8b51311c,ff685570,d9aa7a66,5b47a3ee,b6bc05c0,a2709421,c73ef814,bc703723) -,S(930cdc95,f723a7eb,d698c1f2,46692f39,e1add95e,f8cf84ca,171d4700,2a7d759c,ff161a2,31fc8964,5bb6dbb9,f595daf4,86cf01c1,944021ff,6ff793fc,2613bfbc) -,S(4f7cb0a2,c83f3520,86085b19,a6e5ccc1,b0beb700,35637e6e,8a79fd78,337c2616,aa32192b,82831ed,a9412f4d,6ac6d148,f68ef492,5b438cca,12a73b37,b4a8fb74) -,S(c7238fe3,17590be1,d8403ca1,3eacc6b1,71cccad7,e2e8f659,f11357ad,70590424,59079180,90bdc74d,aa06abf0,940519fd,d09f24b8,88c15cb,a632b814,fe8910fd) -,S(c6afda17,e6582427,95cd34e3,edefb600,70c73737,2d99f6c,b2b8dd3c,99874880,d805463d,15d185e8,b4461293,b6e6f6fc,a0b58a49,eefd4d0,11ef48cd,da5a16a4) -,S(4a14de26,ab18ebc3,414c6856,1a77d62a,221821f,8c216496,700bfbb8,21d95b2d,8037ef39,d1f190b1,a24078e3,e554ad1,cf86d5cd,f731478d,b34b6b5c,c9174314) -,S(cbcd6696,547fc496,8c6e7ba5,4caa4a74,43764852,43f479e5,558e2be5,77bbad00,8e0099e8,559db5d,dba0bc72,21505ef,d42c1c95,876539ab,19dedb2e,8e561482) -,S(37f168b6,4b41be85,46abd1a4,7a5ab3dd,5d690661,e41b16c3,87025106,caa4e2ae,8c617348,bce3bbf7,54a121b2,37342794,5d734e38,da08066,c4de59da,e60b5c89) -,S(3aba7081,55dbb35e,dc4a3fd1,1db54446,a7501ea0,d67b0286,8d2e6d77,99162697,829502c4,2dd1105c,cb046e0d,41cd68b4,38437394,b93f17de,5534f014,270c4602) -,S(84842bf5,fb46c697,44eca720,7b1be6b4,e5f5809e,eaeb3e9b,1058eca5,4498cafe,f4210fd5,b49f6484,2efe3089,327673d7,95642ad1,73b6840c,7323b7c4,16d61fb5) -,S(88383dee,ee0db44b,959edd96,feec2bdc,73d6ab56,9333fb3c,d4b18b01,ed8af5e3,8f0cf362,7aba3ceb,104009f0,baf84ed1,f57402e,fc330f10,6e0b45d5,4e0626ed) -,S(ad0a97ec,2197c5d7,4e8eb9bf,9798a24b,aa7c3e5f,ad6ac263,1acd5109,5178d8f9,72b352a7,445db832,2e33c93,5619e7d3,266f254,64a4c4f0,96051ebb,1e37065d) -,S(9b727e4,d107418e,1f62b499,99c1f8ec,55ef6e91,a9a10ec6,8905be97,33903d85,27d6456f,5ea52aee,a190dc81,647ce31d,15ac8c36,de65685b,4784eaad,4a32e41c) -,S(e86bbef3,8d740a44,7a2cb0d0,a89c2106,d85299f8,c38fa540,a7075efd,3a02fe03,8a9f75db,ecc532b6,ade5be9,b855a27e,185895ca,d6a6549c,f6c4c1c8,7e151b04) -,S(b72ac468,9209207,2cb735e7,d424a18c,5ef097c9,3a9b96ef,1ab7e29,d0f379de,89111544,27b03712,e2236fcb,12cbad35,98ef794f,b8141913,aeb1ad8d,ed9e6467) -,S(f8f5819b,203b2bfd,ab2dc532,53277103,2f9caf34,c53c7ec7,7253b314,2e731ff3,433fa831,3dab76fc,aad5bafb,12362126,6d8d7c09,9d513ee1,1b633c6e,e3f1e96e) -,S(8e4a8890,a15da3a6,c14d2df7,d09f6157,d5dc95f7,4f9518de,8aecbc4d,c0ac62f2,c06063ce,1d3c2a24,2494a1cd,db381513,6200827b,78ed080e,3cd14f4,5e545acc) -,S(b1f6dbe2,ad730748,f906d1d9,160996cb,f3f2450c,fa656856,e34f2481,40767081,ee6b2a03,3f3245da,76d01bc6,e61afcc6,94a9e64a,4f0256bc,62acb5a1,82e45ae2) -,S(2139dedc,a8365bce,b9c49cfe,3834e4d4,27a46750,d6b0f0a3,4e7672d3,d12509b4,b20a9101,b63be2a5,28340f58,893e10d9,d3c63fc7,77b5c6e6,a9a67193,13725870) -,S(da3aa585,85c00e41,87db0240,547ff665,376aebea,a24e5aa6,67d477f3,c4d3b914,92405390,d255ccfe,a6bc7dad,4fb1676b,c741e530,cebdaa3e,669bfabb,d1c4780a) -,S(89c47de6,84e1eb9f,a5828e65,dd17a852,7226a75c,3d113102,97f5b8f6,5b67b210,970bc229,d60b00a7,c2354a70,37ec8569,ad615faf,ac77ddab,f5847a09,c1fa57ea) -,S(48ea67ce,db716a95,6b6066f1,e5e9fc71,5994a4f6,f4e2cedc,bf0c09f,4f8c8fd1,513e45eb,159f9865,5ac821d0,e18f4e06,fa3cb8e0,9d45c3f1,8d3c3bfc,48ff3da) -,S(c5ae6651,ded2c479,a3b6c9b2,44fa35f1,2eb1eaf3,fc78b529,42ffab7c,4e33a1cf,ae6ad807,435d4a9e,e8bedcb6,3bc804e7,e67e9418,6494bc8e,384b29e2,31af8cb2) -,S(24e485b6,7c27af76,e18ed116,90c9dc90,73a0b80b,e93f5381,6669e2d,3c0175c9,fcb183d8,696805be,789d83fb,a197fd24,996d3542,b2f3eb5a,c207950d,f9c079b9) -,S(3bb47a19,b1bdc527,a8fe262a,ecee2d7f,1e772627,e5cd5c70,eb2a8c39,f1977628,2d10cdb9,91fb5042,905f822b,68846390,a922da1a,7b7b313c,47edaa6,85217fa3) -,S(7d4233a,cd50bad8,71e0587d,e10204f,6013a784,b65b6540,73307364,5f3078da,be85d3d,dca838a,1f35ca11,1333e943,fb498cdc,63258ac8,74bd6acf,2b934b77) -,S(b5d0d791,b6685aee,2f599505,d01bd3,d41d5a1c,531ac7fc,e6c33b97,cb0ed264,47fbad30,413084aa,619d7bd6,62502cfb,9648e64b,e757d6eb,24fd5e2d,6b1629) -,S(bd6178e5,b1c558ba,432a89a0,482585ca,40ea9922,7c94ce,23f5b081,d606c7f0,9cdc6bf9,d32b98cc,73bad7b8,c08914dd,b9a8c937,913eecca,fff72dae,fa1cddfd) -,S(13ca834c,a5f41671,ce7f0978,a310420d,6a82fc38,fcbd997b,88a1e79a,66fb9375,ae32a0df,7f269c8a,744e409e,16ec3d8a,eaac151a,99bdd7e5,50287005,6f48f6a) -,S(96322802,87add117,4040f802,ed5c71c8,5f924398,1ee78480,4f16e5f3,f0fecb6,2d07de71,cfda4b43,44baf838,7933a372,3d536411,7e4c0f84,2b402156,3f9b56b4) -,S(961efbd2,ae687808,bbe275a2,cba1769d,4ca537a4,1046c5ab,ff269c1f,b9477ad1,9d22a10a,294666eb,5c816bf3,c4dc2c44,d7836202,e15bed89,e3d28822,8193251d) -,S(4e7162a3,8926282,84ac4df5,88301fc8,5d91c869,2fb854a3,ffd34c47,7b216ee4,6e6dc88c,d91b9702,cb38cff,2d6a38e1,d512fb46,9d85f878,8510ed97,2704ba27) -,S(6c1f707d,51b1d3f4,ab261d52,6d0106e4,3e0a5b1c,76a59868,62e9d97c,bc6e3e38,d2563843,5dc8b102,c8f4ee13,dc345f85,289cd499,9bcfbe20,1bf3dc7e,7dae1f74) -,S(3ae98e6f,49d363fc,8416f965,4e57beeb,d37635fa,4e78d8eb,77caae69,f2201798,ffd95480,fcef0686,9ee781ef,cd2693f0,e6be2e27,f207411c,39a18465,4d2c3cae) -,S(eaf94fc3,fae4eed6,35382e91,2cf963da,2bbbda8c,3197e522,e0054cf1,4cdcd5b8,a838a439,3d4bc0ee,a57e6235,5dacfd97,7d70afc9,16e61209,10d13fad,7c1c22ec) -,S(7eb52e7f,bbf5b802,2fa6d66d,801c3632,2c195b6a,4eae4050,5295612a,a184e2c8,b4591e5c,c66521e1,b991f63f,456306ce,cb2e7568,5227788f,a2e9a75a,bd58b384) -,S(d22b8dd1,6ff24603,5fda0ebc,77129644,a8469373,99b2c7a2,60d8e985,d4f2a215,7a9a092,e8473776,6718e2b3,9068e163,e06618b1,6d6bc046,b33e2d76,8649611f) -,S(8f6eff05,f746f0e0,9b328ec6,2089e575,ca64175e,d950ae4b,c67a7ce0,83afa1b2,3681243f,ca51a6c5,7ac92100,f38df1fa,d1093fd6,ecd53231,bfc01fcd,89e38305) -,S(ac9ba060,ff520335,9a4111f5,c8c536e8,e27a79d7,33528ef7,9da7b21,36243a07,2ba3cf76,3dfc0860,ff3333bc,e660ebb9,c4e5a988,909880d4,1ceb4219,89f23f77) -,S(d6896830,62bec27c,815191b3,4addf36a,cee1cfe7,475d34d4,d83a83cc,6dce3992,9f038f46,529fb86,30b19b08,db11c630,70593570,70bc51b4,fc1ced24,f43fbd00) -,S(e815019a,f6923eb7,cf963f2d,476db569,bb04cc7d,78a0bbf5,3b422ee1,caf43b70,984c16e6,593d8642,de871694,800ca14a,a103a61,20b91c17,4e06567e,2d731c95) -,S(3670e86e,e9aaf036,40136ef7,3344152d,c792c8d5,a064c0eb,a511e14c,41d6f7b9,eac7dcca,e491cbb7,cd27a522,a7db96cc,7d300c35,7413433b,9bcd430e,152fcd33) -,S(3d03f819,4802149c,c6428aad,851bd879,189c557d,cc9ab1ff,8e2e4cdf,f0723308,1f56ada,27f2c923,27ed2fe5,88d8736a,fb68259a,1d5b1c14,7f85669a,eaf47615) -,S(bf2ac011,9e417837,d4815c9f,74351869,4395ae40,77429013,7aab32,980748c2,17a47bb9,6f7a3e7a,31b5a8ab,2adc9fe8,98fd94d2,9ea7c3b4,a5b6c5bc,9c367ac9) -,S(c72eea14,ef09c0e6,85c22840,95e73e0b,6aafa64f,9410eb0c,97f6ad4f,64dea571,9a46c93d,256f67e4,1ccb609f,4ce94390,df9c91,38a9d2db,9b993456,13346031) -,S(25463446,6da168cb,2d816bdc,3c9e3a43,7ca3463f,8c8a83f3,62704996,c1bb5b96,3d69cc73,6aca2a,cb97e1a3,cd57be14,243e458b,305df59b,3e3a67f9,fdc17b6e) -,S(b40dbb03,7062dfd7,7151013e,7cb0a921,15096a04,c39f7e2e,66188aaa,368c49d2,34923fac,7b1a4570,e824c3c5,2edd775f,ecf93573,2198f801,8f617db6,474fb519) -,S(23fba417,ff084b42,afddc4a5,c070305b,553ed7ce,1311e5d,4c1f7b2,772c9aeb,af4a342d,f9346ead,89b3caa6,6a3f187f,96f2b470,c0a26752,76e895cf,c5ca4adf) -,S(2e7ecc9e,d4f21af3,a3118799,d1ab7e3,a30d011,edc53e33,93dfdc5,6e80927b,b3959fdc,f6c4876,36813bfd,e7e83b4d,7ee0f1c3,54e0491,f3195b4b,aee2df72) -,S(1c68c34c,8aaa0f2c,7daa215a,961180af,3938599b,1324aec8,7a1b3841,710db2c3,d8d68179,71acb598,5cceec45,fc5a754e,e002d09d,4be45e8,ab6d2bdc,ad094b24) -,S(fc0ff082,ca6708eb,9b9294b6,fabef142,2cddb5a3,611dffc6,f06c05e7,f1eeddea,6f67fbb2,df22611,e2f1e796,c67d6c3d,14b17f98,2b6e39a2,7bef257a,d6955b70) -,S(fa683ae5,8dc85748,1a7ddedc,708865b9,267e9fe2,e485a243,1d005e47,64130548,4d9759ed,76326207,891a9649,3b4d2307,b9694fe2,c15e2327,a79dced,db8277e2) -,S(3cfead76,5ef36c3,fa9903bf,6d43cdd2,46ee8fb3,3fa1d13e,42fe9818,6d299009,85a18ee1,da24ebc7,3dd87aa3,ca1e7565,8f868fec,50225e2c,d5b5480e,cc0ccd49) -,S(487fdda7,364dacf6,2fcec7a3,fc2dfd27,c38079ef,d48f0220,85c62746,2c8ac658,1479200c,b06440a7,186a946f,83a137d5,7e5368b6,7ef8a66a,9540a131,e4bc9b8f) -,S(f3e413ff,81c2ee72,74c079f3,451f41c4,bbe1e51,f7c3a1ca,513392bc,9edd487e,46544553,79a33a0b,13fe5904,504cce47,55d0e2e5,6c4163a5,14d5b902,906caf54) -,S(d93692b0,53ad5194,b70b9be0,1dd80926,e2c93754,328b3eb7,bc85c45c,63e6258d,7221837b,3276bd2f,9ba0981d,883cd68d,97d2ce77,9dfa1073,d59b01e5,df311ec6) -,S(e85af4c7,42fd5424,2964eb26,b531fd77,550d3b2,eb64bf39,e97de203,ffe2d28,8368322c,e40ffca8,49ff1a53,76cacb17,98fbf4c4,38f58690,54dcb642,f805b9f1) -,S(9e4e35a2,d913a2e3,bc931c59,298ef6bb,3893b086,ee40c978,430d8436,49fce4ab,ccca94d7,d4bad95e,c15b19e7,9555579,d47cec60,9f42112d,3d992035,6d31f7be) -,S(7d72793c,dcd78afe,23e8b000,41d67983,6528b1f2,6978e262,4d022416,7ac5e741,1189804a,2558ff1f,63a7ee1f,ad5f8ab7,50a412ff,a83a9783,996e5f26,637100fa) -,S(3b8dd2bd,ca65d7de,6a7c55bb,47dd5ef1,5ce6f533,96ab335c,84c0c9a8,4e06a7da,2ac78cf3,e1baa981,b27dfc9f,e1b7cd2b,1ed4c37,f96af6e4,99bca1f7,de62aac) -,S(128aa84b,3d920356,db64bc95,b52d4c8f,3054cf5b,22c6039d,1d21ea60,b2274c44,5a748932,6a98019,824a9d7e,cbea2de0,5ccbd9f5,a2cc5dd3,ee0b3dcd,a92e8758) -,S(de8b04b2,c761b876,4c41c344,a3b57c41,fb62e6b4,ba25ab19,8fc2ded,2849e151,134ae148,d89de734,a222b656,b878fedc,886d5928,fc6bfab7,bdd0a74c,3753f1fb) -,S(f643025f,9fc3824a,6ce70677,23475aa8,8df24d59,682f5a6c,b18b1c0d,5e297017,24eb7c8b,e3de50a7,cb473bd8,81db3515,8f9484f8,8574af66,a15f920d,3986a049) -,S(ce2e5454,54324680,7035594b,1aabcf6d,5d8cad20,729a787a,7e01b61b,106fdf19,f3a2e5d6,745a16cb,3403a768,c1de8f73,cd26388c,c10f296f,f00cf9f5,209b1555) -,S(bafd293,dd071a21,25a857c2,6acc5afb,ea79093d,3c9771c3,cd3b875e,b74b3280,2d56802f,b8f26950,4adb2a51,a91ad2f0,d1ee6501,f8c9279c,6a27b524,8dddbb70) -,S(10e0909,5dc7ae30,9f1afbfe,1bcad71f,c66489ad,56256c3c,a648f554,c000f414,47a5a7cd,968dd158,e8436399,40c30179,3807713b,c09fb0d,83c6c851,c6b7029e) -,S(73b8149b,4e7bf050,b6cd9f4,93c85bf7,61062329,2dec76a3,2d7054b0,c794da63,44cb915f,b6813c71,dff3830b,ebb6888b,76312778,897903f1,d9988c37,3c362bbb) -,S(59a5dcce,9773617e,73c529da,6015ca40,bf923956,339a366b,84a69e23,d0a60fd4,4c62abdb,c4453ffa,2b806a6b,b823fbc1,59f57f23,2234c8da,a471192d,3081ee09) -,S(1ad2aae4,f571c6ff,1abfd45,35b3d085,1aeabdbd,b3a340f6,7bef0f78,f7afa954,1c394b1c,94539758,85d72498,b36a3be5,56b4f80,8ef52977,b0157885,649549b5) -,S(2403f66c,a6a7d60a,254b51e9,32cfb700,f37ad73d,193f25df,6024bd51,d0f337dc,9ad75d44,24517aff,7df86c,9bf4f315,cb40199d,4a2a5d5c,74044c4a,9c79d69f) -,S(f3139f4b,50dba596,87080a7e,b19bcc34,2b58df9,26576bc7,dfdc8e7,4914c524,fbaad228,ab34e8d4,451cf6b3,a1dbe225,bd46bfc4,8a4bcd94,10c150fc,5636c687) -,S(ec415f8a,81b1f559,714dd790,2441eb9b,c5c7bcbd,e87190c,c109ca04,a3e75149,9b90bd46,d27e0200,369fe995,3b50752f,d00b9472,fd31383a,f01bb88f,b223bc5b) -,S(5e336f17,264a53e7,d0899bf8,6f676440,f83ea0c1,5d53fae4,f19a71f6,998a3ca2,2a86fd9a,8358daac,828d42e7,9c6c0fa5,bf977cfe,56899db3,27ea32fc,cdf09f3d) -,S(98828ad8,a6ee9ca1,37f9ec2f,f0cac84f,5e664e09,68455773,3f8fbab3,ec38570d,ae7ba3cb,e617e9e1,6e67f34,f69af863,3e69c9ca,1f46b182,88126f16,9ec0e548) -,S(d6a7c2b7,169348d5,1d98f0c,27464732,6f67ad5a,4809acb1,6b783fae,36808436,698cc098,ebe430c5,4dc74fe5,dc300f64,7ac0a002,4109e002,d2f43ffe,89fb3d9e) -,S(9bf4a4ea,9fc4b731,5391b653,1d3ad3a0,f0fbaf59,b99f76aa,7807c442,f8e63bef,e69fbade,598fccf4,6f1f0931,f37f3c55,900dcc50,64e54ae4,191796fd,a4791068) -,S(38a09628,aa450076,3826f384,7e63121c,d6e9e645,f6ee0f,8cffb106,508021d0,5460c8df,56fb7d67,992928c7,fd969f95,d29de37c,14c2c9a2,2d60d661,6cb7c383) -,S(dcf8afd8,ee73bc87,c17c97c6,807fd3e6,a9c57a1b,cca058a1,ad24f2c2,6e9728b6,efee9612,3e78cfcf,1dc3132a,fa4ef492,12369710,fa2e8e99,3cc70b48,6ba78709) -,S(9c26ca1b,f52eb7b3,a0d40dc,cf546591,38945c43,41e0c611,40d0662d,1033420f,4bfbeeaa,ece9f2e,e11cc672,24749c3d,e12be6d2,d3d21d90,ed742d,31541ec) -,S(2209194a,6a3b76,1ddb2b1,3bca12f,3697248,4bec29e3,102d7734,9832ae6d,7dde1b85,cd00a08d,38035f68,fdef0576,c458476a,93eddfc7,4bd4927a,cbd64543) -,S(6ffff27c,ce5efa3,a8f8af72,edcfc736,9874abf8,5d15e1f4,cc71a186,9a7a29f0,27a0e163,bcdea297,1abe52a8,a92fe191,38b839f4,67772c83,81504328,fad94a2e) -,S(34e91b7e,e2c5f407,8a9d1ec4,7e2b2c02,1b8480b4,8c3b6e47,19cacc36,b4250382,8d60947a,42d88728,e0d67d2e,e9a0559b,55cf3887,92c733a7,3ed50b25,3706cb82) -,S(3b2de979,9106333a,98504128,e2135e5d,7deae86c,1c921c58,529aff14,12fd62ff,4ba40985,8c5b594d,f4bf5e81,bd7eccc6,3a7bbbaf,fb32926e,9a47503e,f031d86a) -,S(fbd44acd,9e593ac2,12fd1f64,c4e18d31,c3b3fffc,ae1c88c4,6aebaddd,ac608b2e,9f4feb5f,2ab68e29,ca64f458,d162dabc,7a05c552,2e38c4cb,74529e3e,41d805d6) -,S(d21c3321,bb6ba2aa,dc0cd52b,be68716,864ce1f8,44107374,c0481c0d,91729b39,2b51f18,7b95725e,f74deb00,8e9d96f4,f1a9bbb5,c9aa28fb,275f700,bd964566) -,S(ea2d29,f85855db,78808749,9ed79c2c,614406c3,adf64663,8756b60f,16166578,33971e79,39faeedf,15b14607,37fa7112,7d6f49aa,fc423f63,783e808d,1fd10369) -,S(2a1a6709,301ba6ef,c5ad4958,e29fa73a,caea18e9,e01214a9,65291977,8bec874a,56c971a8,d29d6641,9c05fcc9,9b0c0156,a1ebd007,bcab2cec,b9e920fc,85f796b9) -,S(aa870dd5,6434af8a,36d89551,a7109cac,c1d0c5d9,f5e43630,17bba88c,579cfb6e,d1fab1ea,cb5652f3,cd4d5836,82aa3cb,3b1b6854,c0ec1157,41486028,73625dd5) -,S(e979a3bc,5165f53a,60042a1b,11e8062a,e74f35f2,d70aab2d,b250a4a6,f4507507,4de86928,b9dfb2d,8509a1c4,8efdfbd7,a5432933,e3f12789,cd51ed9b,b967ff1e) -,S(620979cd,f37b1cc5,b1fe3e01,f761b8a2,ffc29bfe,8afb7cae,7ded5cd,37f97829,cc971616,6ad43824,4c6be489,7cac0b95,afe5ed6b,11be673f,d67f0d89,6d58f7d8) -,S(90a5df7d,986198fa,70152c7f,e2abc14e,2c80d5e,6b75b42b,aa042e03,f3aa00b3,77e0ad,2f3e1eed,472a543c,3852925b,327e3eb7,aae59030,2d7e12a7,862201d5) -,S(17802140,e10d8be8,ef210b69,b7fa1afc,16a85d9f,ea1150a6,c6e5e234,cf638446,af4982e7,fdcb7a8d,b6478b54,a5bd7cd7,c48d1dbd,2a3d003,7e87b6e,13c9f5f0) -,S(1f2b8d3c,fe515cd2,53f66b0d,59fc51b1,4cf75ac5,d9c7b4e8,4c75d92b,f0380b8,6902b31,19f38b04,5b979f94,cc140481,d4e6f7ad,b3efe12c,4de1bfcb,c71be72a) -,S(aee51eec,9e5dedb2,1619d114,5594ea7b,27e21a4b,37accccc,d5fe522d,2e46d29e,d40ef18,86725504,fca42c2c,b8b80dc2,c1028b71,1bf3fb18,9fdd579d,f7f0ff8a) -,S(40fe6d08,b714ee12,a4d643b4,21b331c4,fbac165b,d7cd88fc,ce35a873,875bed7f,c32f1cd6,3083a976,6b7dd8ee,7133831e,6796709a,c67953d3,4ec5d8df,922d2743) -,S(5425c555,8a6f9068,946f7075,db347e6f,cb6c723f,c5ff829f,1634fb2,13b3c820,c218eba,db4e3ad6,e41a28ba,129a0c1f,8626ae2a,16839b77,ba12257a,a6aa2318) -,S(83663c0e,f024207e,16ba74c5,ca534d37,733a7dfb,b2d531bb,21a28243,d0572a00,2699a48b,dc9af87e,bf18c9a0,929359cc,d7f2f137,b84fc070,2bc3497f,69c83d45) -,S(bf931d61,e72f217c,3b820b63,282f5d4a,c929134,efa06fff,88480f86,f6247535,82553f48,bc40dc42,cb8bb098,ecb84af6,5cb3956a,aae7bd0d,cfa9e181,de93c21a) -,S(1c6e0876,3c2242ab,17e2885a,537bef4,e8920782,9c573d00,64fb83e4,910312c1,b7c14efb,bea753a7,5d8a597c,7f1a716f,8ae4298f,379aa64e,d070ab2c,28e66185) -,S(9a2cf62f,9eb5810c,31b27614,1592f201,1eb158a,3d123610,99af0b77,7d42c0be,159ac59d,728d1c49,843a0207,e47d1cec,7b9b773a,9ddaad52,3ff27d78,d2767d7f) -,S(3596950b,393a56e3,443c3b93,b4f8288a,7faa8d74,d26cab37,dd7a5b4f,6a9e183f,f99bbbdf,c566b3e4,e65dd63a,15c727a4,403cbe85,202e45f4,ea5d3462,173babb7) -,S(6f556cb8,f5da812,24bbe628,6dc4e379,ec12b124,21cd95d8,6bb1d580,a13b5c37,eeee3133,1dc89e57,48fdf10a,1fc0693f,1c09aece,aa27dcbe,919d60f7,4748d656) -,S(b952070f,fe60bf94,cb14bf68,b37e3e54,bd9b8063,ec8cd4d5,20408756,bd318bff,57996eae,d38f066e,cb3f8113,aab5e4f7,f322859e,1fc075cd,69ad1ce4,3fc48ff9) -,S(dbecc166,8d94b2b4,8d37c133,26fffedc,3e690b76,87563677,23352ac,1eddc2a5,f124cd3c,e42f56d8,a7588145,e53931e0,ce8b79ca,ba5195f7,3dd861c9,9027823f) -,S(12dde570,aae95b1c,7cbc2da1,ed2d936,bbfa5155,f61979b3,e67057d1,5fe5e1db,328711a9,c30e4455,e2716e60,3bedf4d9,8fa25d1b,e892ac72,b5be17c2,b25ca311) -,S(64bb18aa,fbfb7def,3493c920,d2faf9c5,57856710,766b0bea,275db46f,f8271282,717c28ed,e9284844,49cd0db7,180cc5fa,20ba79d9,41c979bc,c0a8f274,3e2e2901) -,S(a798f4c9,bb3ef48f,d2ba3df5,2b040611,d0d5532b,9134aa28,e21b5585,d2379ee7,91f903cc,a4628477,b208bdba,59ecd246,bc50be70,34620a44,b55e0e9c,214e563e) -,S(7bfc5902,58f80000,82946c5f,a1a352aa,808fcc59,4bf2ed7f,bc6dad3d,8bab00ed,17b5dde0,3bf6a814,efbed180,3e5f1950,59499cc7,13e727d2,405e0748,2f912cd6) -,S(23bda819,978c9a09,864a1c53,e0fed0d6,ddc18777,b614780a,1c6fe08e,c35a820f,aab57ee2,7d226f88,6e55b8a7,c4d7a245,7badf96c,9312906a,3efe2cfd,3292af5a) -,S(8f649152,54696b2c,1804467b,e1619ba9,d37cd874,88db9418,1259d69e,135e1455,b05b39ff,241ac0c7,7e2fad78,da585b09,c98815e1,b368040,d493bbf1,3ab54ac1) -,S(177ea3c9,e592ca96,e9e0ef4c,87cb00a1,cd51ccb5,1e1d5252,963cfd08,77f30331,57185496,db5e5971,24e55b14,1042ef30,99f206c4,67415318,ccbefdb3,b18cacff) -,S(16042996,9ab25db9,e4ee4231,7497a607,360bb1fc,96e74d66,cd87cab4,44af2f36,1dfa3d9c,c3acaa95,1f7ad037,bea4c20f,c311a8d4,c2ce9cb0,bd30078e,b0ff64ce) -,S(10210453,fae1b545,de76c4a1,4b6ea5b6,172ea157,1fa60696,25753231,2630e29b,ec8aa759,5708f292,72e2ebab,eed6bdaf,955b27a1,469758b8,44c2668c,42acf576) -,S(659574c0,39345165,e35deee5,ab4c3b09,5b873ba1,fa14283d,6bced3f1,d562abc1,1a8b17c1,bbd83037,b20fc2ed,495b890e,526461c7,8f0b8d61,e94a35f1,bac9520a) -,S(a8a00f02,174b4d3b,9ca825ba,88cb1ec4,4c188343,5478a00f,38025a5d,1e2cfe58,fdac00d9,55b6872a,62a36dd1,cf666423,b4dd6b4f,4558cca6,d931a1b1,1e42561f) -,S(3ac8f67e,b4c2c3a8,2cd90fce,f612ec7e,7daa1072,6e4f8da3,57d9ab96,56e30414,15f71b5d,17dece22,a696fbf0,2e360226,bfaf685b,6575fb99,68fd52fe,7a21f9d1) -,S(87c56593,9fc7bce5,650e57d9,37e77642,a1ef510b,dadd117d,2732d316,a4f2ce19,59908fd3,e2b646ea,210606ed,c790851b,4077142c,ec7733f8,613dce61,3431570b) -,S(6531e4a7,f9cbc2f3,f0448bb7,f8250542,6cf5c7b9,d4a1ec6b,80098799,d5e43101,622a2201,f3c0f766,6e81be2f,22f1ea60,f4b45807,6800fae8,c353c283,b6ec3d7) -,S(e2a5b419,cf421b15,859aac6c,9beaefe6,29293f39,3beada53,e1ae567d,9bb7cb34,3c20b681,578aef9b,138f852e,90f49526,6d30f3b1,6ea2d3,23dee943,1af4a5af) -,S(d4e9df61,35cf81d2,21003bc6,e167b6c7,9e912c1c,2dcac775,f7d9d07d,6ffc7334,c8f54f41,513d7bde,3055c7f4,8436c812,898770da,754ed9ac,d6eaddfc,a80f6c21) -,S(b83ec734,10a1989b,988e2bfb,a46a421e,dc3ce47,d549d838,8970102f,98a6943e,4e0274ef,ea2966c5,200dbca,d8090f78,98bc66ea,44164fdb,31507ad1,e7e5db5b) -,S(ec57668e,12f0590b,e99a75c7,82c02ef9,88354f47,522c114d,bbdb9591,238d3eb,2b3c508e,81a3f696,389a5ec5,974a1bac,a572c042,69ad2709,25001215,c58ad7e) -,S(5acca76e,7578cb86,8d5ba7f0,aadfcf40,5ca4cc52,d778712b,785764a1,2afa01bc,7b0df4a4,5e048fae,65a0683b,ea0185ff,f867a578,179c153,5fa93561,54138359) -,S(bd563b91,6419f92c,43a7c2d,7042fa71,fd88e5e8,41115b5e,36a673cc,93de4e07,4ec5b773,b35a5579,b7c729fe,1cde3b32,ca34f97e,83b989b6,fe756597,3cbc840a) -,S(a070b055,839d93be,2b4ca25c,a4a6b133,5ef7d09a,268bce7a,fb1406c6,42e71025,d3fe8577,1241be24,ed209e8e,b5b28ec6,e3a0bf52,27f36036,3a7325c7,5eeb6acb) -,S(9c50323f,c758663,346c5863,84d5aef1,123b4338,eae00ec6,86aef2ed,e19b2f06,1dd9442c,cf588e6,6a3cebd7,bc68f2f,6f270d7b,bf01f088,a49a5ce6,da430229) -,S(90fe8f78,166e3f6c,2d19bd0,685fa2d0,1f6bf06c,2ea220ba,cedb0f22,ac9c558f,826d63c1,60fe3875,9c5887c9,cabe8f93,905fa1a5,e87a8272,670cfaa,ffeeba13) -,S(d2f44fa9,b704491e,69488c44,cc8ccd29,6addc630,2fc66900,1703afd9,a2a5d3b9,2de1d619,247636dd,ce1de2d9,75f14515,ec5807a8,c7c0cc4,5c7d03dc,fc19352b) -,S(17f1ce71,9e3dfefa,106e95e6,62786729,e8ec2bf6,25421ede,ca71ca14,5782b23a,62b51d27,74f514cb,5452cd29,e3907a7b,b39a9b9e,400d78bb,f6cca78f,cfc1aec5) -,S(5b1dcad4,5974f0ee,e99d7c23,83e48585,24428c94,daa956af,cd692c4d,5a63213f,6958ca48,f13e31aa,c52e531f,886da246,5ba713d4,748cf6e0,de16e0a0,366c33b4) -,S(ad284e67,a0682585,f18be40f,e966b605,8cc787be,c265606d,12f202e9,31f3067,c86ce860,ac3c3955,28321cb2,508e4da5,abb4dcfd,2844b95b,ede54ce5,b17e45b9) -,S(9ba71712,dee6f0a2,7352cfad,59f6c0ff,f133b1b1,37ecf884,a537b672,a4275c8c,b910f036,f906a419,21fd37d5,5e0273a5,332edf68,43dd8afa,43070542,b0849b40) -,S(cfc757d5,171c9d6a,ed8b9123,a2b4a405,d8e869fe,e80aebd,75255454,ee6319a9,43dc370a,c2eb8fb4,4f78940e,b41d614c,ccf2cd7c,c4f324a7,92ba37bc,7e48144e) -,S(b8288ec3,2e4a569,27df3e13,6e81498a,bc9a52af,80d74bd6,c85eead8,85e0c49d,a0d53c40,d2234ac2,df69605b,1422bd1e,4a1d77db,fb0d7269,13de63bc,a2f96078) -,S(3808cddc,497c9065,cec574e1,3b82a10,fe2323f6,65a99df,1e724221,3eeb9a79,eb046225,eb6aeac9,5659f1fe,75dd910d,2932cab6,9b4b810a,d83e7681,e0c32907) -,S(a1620bae,cc99c311,7b3889b4,7bca5d99,4ecfd67a,ad5a7461,646e55a5,19e46398,5cc4b5d2,edc5f7a8,54cc3054,1c7ec571,e06c59a,52bb5cf5,5882ec18,1b07c0fb) -,S(f1d942b2,bff74aa7,1f9cb411,91ee85d,e6955802,4a4d46eb,53ac02d1,32fefa93,19a564a2,8352bc48,a8dcd932,50274bd6,496cf488,6e2ba390,3cf91631,453f57ad) -,S(1a4e3836,a34db30,c47ed6d5,9ba6fb83,fcb7a5a,a0002ad7,1b93b154,a5fd566a,745e195f,d94900b0,aee3c5f8,7c6fc62e,fdddc18b,984900c4,20c77ba5,4141cff5) -,S(af37075f,866d7aa5,9371a08c,1e7aaa5c,d23ee51f,54428fb6,84c09b27,93b432,b32e8869,fbe53ef5,4250e803,facc93ff,a100a84,becaec5f,872d0548,da4ae9ad) -,S(88e39f4e,83a0d6ad,a1e01ac8,9021a7ea,fdd1f9de,740bc10a,4d572c46,fcee9330,a14f6881,bfaf691a,96249322,37522174,e8a17920,52da7bec,a6c77d4,5fb8a357) -,S(8e406574,a46e56a4,dd4cf780,9a7ecfad,5a1f9225,cfc2fbdc,6b7bfc84,a5ce14fd,bdc6108e,d5616bc2,3ed52c5a,1314642e,a9272707,20f00be9,62e48945,3550f167) -,S(aa31e1fc,118e00c9,8b8f561c,479c6427,8676356c,640304a8,3b687a34,8ad4a091,31c95ccc,2520c0db,7c7440ac,7e640be0,7a8ba4d9,c0020b1b,f31418fc,98d9eb17) -,S(ef278702,becf4f15,ad43fb6d,d0114077,d9f8bdc3,ff4c78d4,d0a2a15,8fe160b,377dcf3a,774d6416,58bf108a,87201b9f,f28c70fd,449a77f3,966ff441,d89246e1) -,S(d1903199,b9762761,fd02c4da,99fcc503,ac15332f,4be01b7f,a044c5c3,f848ebc7,662ca3d5,9ff2c5fe,a75ad64a,f7044a94,60abbc25,defd0a3,aa6b0e6f,2c7f4f3d) -,S(682ffe36,6838fa12,827ae055,7e38c12a,bb571227,47643f26,9cb9f1bc,922b07ab,4531b021,2e8fad86,6f6f67fb,d8eac752,1a360968,f0f9792c,a4568a55,855924e5) -,S(418fa3e0,b32be1f3,f06b96d9,728aeac3,3294ea8f,16f35139,76b30801,81d8e833,dc1608cb,68bb0480,859c9983,6baf9558,9451022e,b9966e0f,498245e0,2183ef80) -,S(e3f7dd7c,f5898b7b,174cd809,5c7c0890,4188bce4,bd6487ab,e974d979,f7faec2d,5ed5ca26,77d3bce0,15a6cb51,9922a55e,9ac1adc0,61bb0774,503e79e8,204441ea) -,S(810ecbe4,f43814f4,e658ce9,234d71b3,946556d7,2ba9c3f3,6fa04b,4dc25cf9,5fc57520,81397434,e395a752,560a8a76,252e6eea,b9ec067a,16befea4,1f1bf1ca) -,S(6dc50f0d,7e9518ab,fa16bcdb,f43ecb2f,745d5ee4,7269225e,36811819,6542b7ff,dfd5e416,2d596f5,b44602c2,20a87cfb,77473aca,6dde260f,856b3295,527bb87c) -,S(d39c9858,5ba2a859,a6fac25d,602c8e1,fb205a88,7aaf628f,5d1a210c,bc648fb5,6e92fc09,9df932e5,1bd0c6bd,5b6567f,61a1e8c3,93d69add,111e9320,661ad724) -,S(d7fd8580,59c1a86f,1b81c05b,ee63bda6,8ca93c4e,5ec99e91,88d9c7f4,40dae0d6,ceb56f19,cb3e5b39,64a4c58b,5cbeddcb,c736f0a1,8a2f8f3f,f0758f24,525a8fda) -,S(2e269d93,319a79d7,513e6f73,918638df,c4b1b7c,4c19ec83,b254d780,dc45fa87,650b6846,4e8537af,583cfc48,caaff61d,f31dc67d,5a48e0f8,5857d7c0,9bea1d70) -,S(19f396b7,7147937e,bef30096,44b292,2a6e3c6,5b5c929,22b73118,7120224,4751cc23,4d49e926,651a9a29,c2a8a55a,f7e4b25d,9cb4bd2e,83530bdf,494b131d) -,S(88f843b4,e3689ba0,264d6d4b,4d310afd,85de2ea1,6fbe7275,d33112c7,538a7c02,5dba8024,30d31ef1,412f2310,3ccc5951,66e903a,55bb2a35,8be1e715,27fe45eb) -,S(b1301f5e,1474083b,3828ba5a,837efc44,21990da5,275f6b1e,bf773b52,5ef14a1b,f9fa0af5,b508ca7f,2345d06c,5bf1e5e4,907f2b19,3681837a,802259e7,7208864) -,S(63bb3295,b57ac21c,4b96ae49,92b8f3c5,7c23743d,44ba348,195c5f58,d5360bb,f5e6a98,96683293,af6b9ded,f9f163ba,15b44017,120c61bc,c9e51758,f3ac793) -,S(dac9f722,7d0c012e,e3e1ce88,a99cddeb,9a23979,14c1cf1b,915dd41b,8ce27687,85bd90b7,7f2917c,cf1ebd47,3bfe04df,386d37de,69893cc6,9e79ae89,2255a12b) -,S(ef05aacc,a8082759,33719aa0,e0958f6e,4be6a6c2,3458f243,f84fb2df,9aa422f0,d6006b80,bf611afd,3f1ed523,988b3e8f,d44be73d,565ef30d,911e4226,ae546f23) -,S(dedf3d9c,807065ad,8c1e3714,f682ff86,4f6ae08d,6bc15773,53f27677,ff86783e,7bf6f3f,1f3e5ca6,6902639c,a0b071d9,50dc2331,52f1b47b,5c68923,9a1cccc6) -,S(3db2b461,d18b367f,cbb4aae0,7a73ce9,6c1b4cbe,140099f4,d3839764,7414b5da,515ead0b,a8ba7b25,9f04484a,4c55b532,5686b882,77562b99,21827706,a036a142) -,S(5516a03,3da8cc3e,28170010,5e8d57f3,daf5bb84,596c040a,3d2ae05b,41cecd4f,6bf44084,f0ad14a1,f129a267,e13b0717,6d2fd274,2d4be75a,2192e54,7ceeebf1) -,S(7bd86d5e,6fa18e26,cb0b6e2d,faf2a4d6,a784e831,2e7168bb,8e660e3d,92514c3c,9b634094,dcf4ade0,eb49eabb,a26334f1,7770bb94,b776de46,64d847fb,f1574afc) -,S(a24a8b40,d63c242c,3dcd2513,fbee3c04,cc15117e,aae40daf,b39c3373,e6a83bfe,49163714,afef59b3,b503eb73,ee091349,e599c563,bac4aa37,13d7a6d,6f5271a3) -,S(acbbcaec,8b01374b,454208a5,19051ebd,e5128307,785f7b25,706642f7,775a932b,102283d8,1bd1e9e7,e5641b8d,a701f51c,86047d76,51becfba,89478d8a,a6226572) -,S(efd5654,8f37a094,19f9fc11,6d818523,c4d76725,860d49e4,a1cd8434,a0cfda99,d521204b,da2b9db5,dfa47c9c,6ae4616a,52b3caad,5440e4f7,f1fc41ba,766bc180) -,S(15600bf3,ffca622,a163244f,47789725,b4c112b6,e3d7652f,fe829a6e,386041c3,b1a1ddb3,e2b0e170,8cc9e6db,13c7b111,93673cc8,397d9b59,5b4e8dea,a39cc5f7) -,S(8d14cebc,62f7cd8d,fc60c2de,d144c76f,55d9d6c1,be5380ca,1e1ecefc,5a85cc53,244bdd67,5030a8ec,af876f5,99a34f98,ef7388cf,e6705734,540f57f4,15641220) -,S(e3cb7328,29c6d09f,6ee940f6,5f30c79,7dbbc26b,b8b8c860,f6e07088,a485ebaa,e50a5c44,6768827d,ddd57e18,68064e61,51c8951e,e4cd920b,b664ca06,67096db0) -,S(9a18212d,45364ebd,3ecf4d76,3efcc66a,ebd17b7a,f8bb7f65,8679664e,16888e47,85297209,abebf492,ebeca275,bdf3bd2f,987d1e29,6bcee299,9d6e59e9,2b890143) -,S(43366191,859bb3bd,5b44f1a,d9076ec9,5439c082,c99f70d7,4363117,8020521b,9dd6d890,16666a3e,6bd8c0dc,76cc9792,fe5d76b8,c49cf9e3,75e031c8,bfae2556) -,S(1b77e51c,b11e514,29955ae2,37659c5b,a8050ddb,685e5b74,fbe38506,33bf9358,f198ea65,1ed4a743,a14fb905,fd0bfefd,843bb00d,675781de,5fb1552f,c7f382cd) -,S(7cc6fcc5,558cc6b7,156a62d2,e823631,e0b95e8c,57fb79d4,b4aa3ff4,9cb718cb,526becaa,c0c84e61,b3fc85f,60d028d2,eb90567e,319bd6f4,12b1a36b,9c3d30ac) -,S(18c1e51e,10a7dc5f,7783d511,6f2c0457,664ca2eb,6541ff29,591ee59b,f9f958cf,7f72840e,ccf4d03f,29ce01a6,725f6b97,d701a935,bce8a2b3,c1e44904,cf98a300) -,S(3b9335fb,b191bc9d,17efec98,77960307,2648edb7,2c427521,34df37b6,f1620c44,ca526125,8239c80a,1ae893b,268d28c2,b02d56f2,d03a8a7b,aca25def,34d6d694) -,S(f39660c7,ba9bf800,381b8ddb,d783dc6,acf8c183,95f9144f,688db8c9,9d7874f4,c5037625,2abd41f9,7574a607,52be4c31,e5ef2874,5e9d80a8,da2ea676,4bce5cc1) -,S(d1d2872e,ee06a4b5,d3b735b1,9db1d88e,cbbf9ba6,89c1e411,980b2cde,e70c86d6,dc5cd630,859fb9da,70f25023,5b7bf2ec,938743a,a9f04fd0,69d1d746,e3ebbfef) -,S(aa4f71b4,720f6470,8b6261a1,ee97bc7c,ee85b274,caf71a6a,1f7f000a,b06a1948,958fa65f,acdc42f6,c1e98f7d,f67ccc39,14dc5e8,d20bb872,32d7c898,e451c017) -,S(85904824,63e69633,42cd1e89,1502c309,d74e1722,fad8e766,d7e8f566,49bb732e,585601b5,5bfef406,ec5f71bb,6bae29c3,c5e77247,befbb549,5ced52a6,da64a2ff) -,S(dc899ab4,89a12ac4,4152ef63,48553ed8,29855449,c204327b,bcce6418,75df4d99,6791a965,65fb749c,44f133d4,b3c9c8d,77488831,c8a99ba9,7b66c9b,43deddb2) -,S(2fd60f25,3e0b4f1f,2589a096,f9a0ea3a,405906c2,690fce35,ac7df791,f106020d,872d52b0,1cbfc3b0,ff699950,5be33b51,64a7054,bb00e22a,9a87d692,dccbe782) -,S(a74830c1,7f816549,cd617b94,c0360b8c,9206b382,6782d351,650785a7,fb71212c,fa928b97,75b28be7,4e340cac,eabf866c,fe7e7299,7c276680,2d211b1b,389823b6) -,S(fd450d48,c59fc4db,e3366b43,caf00c2,bd10045,842311ab,20f8e24c,6a9a10b7,512d1998,db747e39,34451fb7,9aaed7af,48801051,dc8ef756,4580db9f,bad910d) -,S(c0816923,9f2bbbc7,34d52def,79f9f4bd,cbd8c435,d90561ba,fb23f12,f1fcb93,fa00c81a,8c5cc2d3,5f78f0d2,475851f1,73f70cbd,cf2c950,8ebad1ee,b35a0852) -,S(247c4075,9a0e7098,25a5d82,4fad3419,55103052,bcdc7ab,fe4e559c,84a04a66,8da3cae,878260ba,1b95a5db,900f20c,12597187,4191cf21,939ab6c7,fe378067) -,S(fbe3b30f,16ad6608,32f9ab15,2f44076,2f7a09a0,b07b12b6,4375db15,37fa4e9c,98cf3e68,2a914c3a,ee54971a,793a9309,8c63aab3,e2db5389,3f05450d,61b9080f) -,S(79f71ab6,fce86bad,be02055c,520e6e0d,88e98def,d37f2d2e,488bf455,3ec954c1,b5de6a0b,c1745341,3023a650,45262a31,e9264089,8a655b0a,4b3042d3,a9114330) -,S(d190f258,e2e3bb8e,6812da59,606f2f4a,2e3fd1ec,34e2c80a,9d280f5e,e1e9c4cd,98997b49,afec7d7a,26a26f50,9d4948c9,b5ebf9b4,3eef6183,3a2b7a8,6183c267) -,S(24f355ca,c0e00545,f47e199c,3818e76f,534eca88,776ff6e2,54244686,24f0b636,37710da6,5c3afbb4,308d5906,7ad044c1,4df30f03,427ac83c,23b829f5,37d25b46) -,S(bd221461,ae73e639,6b23d269,ed6907ba,330544d0,80342de3,a769d3cc,668cf536,a5f25513,3967fa67,b22dbe31,917d9d1b,ae11a1d9,dc7ab731,26e8f0e2,fbc8deda) -,S(cf0371e7,22194be7,ac5d19c1,1b447978,b38f8a1b,dc1dc3e2,471d4a8f,75d0f6cc,4bb04426,94fe9d55,cc49dd4e,e168b604,564b95f5,99566f3b,9fe2fbdf,16084f1e) -,S(ce21a5e0,287752fd,ae9e04ef,363540ed,f6736c34,266a2d77,b5d0bb5a,868fc32a,fc30fc93,bb5a2731,8b81b942,4fe330d1,878e710e,b9a44fa7,bf4cbfa7,10c7d0dd) -,S(7c95d800,da4720a4,102de774,d585f230,2b849e57,1f42982f,a785bd15,334b4b12,244deb56,fa5b4367,2c39693a,f09083f9,2b153a9d,4829ab3f,ff604fed,a266b30b) -,S(40bce9b4,f90489f4,d392fb93,3f98f71,e9281976,164b25b1,982cfcfe,338d93e2,5a9ebed7,25bf11e8,7bbec766,c52309d5,e2036454,447b8ee6,6dc79dac,7a2a9b4) -,S(f15a2ed8,2c00ed9b,9e7a9338,2d08c46b,33ba7bb5,dc15f5df,4cc29fdb,86f11c4,d02ce92c,e556287a,3acd4115,a190767d,2979dd7c,7a32dfde,cb6d806f,6e7d0205) -,S(4230d263,d5a4a915,cfd863c0,e38514b0,4929d352,d8a90c00,c0ab9ee0,56215932,4b134eb0,51699656,dedc7704,3d5586c1,62134b00,e21ab1b4,517bdc54,5f05fd69) -,S(6cd6bfa9,63327c26,fd2c7aa4,fc159956,1a90096c,dc88f414,d5cc9c64,df6a9e84,6741fda,1f774c52,20b04db1,9ba7402d,9b77eaf5,b8e9e2bd,a000d2df,2022565c) -,S(118face3,ab188a36,581cd1ce,1d434fdb,f1d06f50,1e9a64be,bfed2ea4,ba3f477b,a263037e,c8d5a9eb,be1a8b97,bbfa5624,ce00e852,44828af9,8cfc38ee,1da9052d) -,S(6be81e79,5fd1229a,fb24a395,fccfbb6a,ae4fda11,28f93faa,f74bfb76,c39794c7,edd0f9ae,bbbaaf0e,bd1c01f,af128730,5d5fc5c7,732885eb,327eb21f,62683869) -,S(b9a0023b,6fcbb06a,48f97684,509b8b9b,937f990e,4c3f1a61,27a8a18e,e4c96c3c,e1b25ce1,3e8bda89,ea631d71,4c07adfd,c31fc6b7,304b5e7f,1cc7221a,6597df11) -,S(4e384b06,ee4007e8,e70f22a6,1af73d89,4528722b,cf58bfa1,16eaa29f,e1f2334,2fa6ecd4,8faeedb6,240db0d1,14c7eb3e,63540e31,788f5f55,98c52fd2,538ef0d) -,S(14c8267b,6462dbfb,6ad45cff,58d9b22e,9fb0de4e,3d026999,9357acc4,d254ea52,86da149d,e14de86a,20becddd,e33e99cd,158a50aa,2da085c3,cf675eac,224b292d) -,S(42d0c7fc,21129bdc,97318985,73b6d111,568005b5,cbabcf55,c1828340,4f5de376,8f83e957,92880a3f,dac6738,e65ea463,1399daa4,defbd1e9,41a5586d,a42f652) -,S(bfb03349,2fc28eb,82bdf9b4,417f02ee,f93588a5,b138c520,77250499,23e9f135,c65872e6,9438a5e7,a20c3492,7a3de7d,85c690c8,b20af801,915585d1,98184882) -,S(1a111410,d04e1278,3cded32,b3602007,7dedfa32,6493a780,999c68a1,dee18047,874723b4,c6b63cbd,d957098f,d0124779,3e711a56,fcb8499a,a046f5d6,36d5be75) -,S(a47aa995,3a999aed,9c1d1f77,da8b736e,6d045d3f,9b32ecf,a6bd4225,fa66cf6e,c4ae1566,4da8e033,f0e3fbbe,472e16e0,70a4b40d,f210f7,3d0a6fe9,3dea782d) -,S(52ccf2b4,5cd2555d,5a0a5765,92b5ca7f,5ffa329b,6bb12979,8f2c10d4,bdf34119,92abe502,d23e9f61,f420e4a5,44e42864,2462dd0d,7d7f386f,ff7cf2b0,b3a5043f) -,S(5d2af6df,77107953,e6221a4a,ccecadf0,a2a8d676,5e720d2e,38c386a3,e6b48e4,5a44be69,80ca8082,5d435aec,34db8be4,6dbd05e9,9b8fa176,45888bd4,2260cfaf) -,S(e0f9b457,e184de7e,7484ad3a,dff4adbc,4dfe508c,14341dd9,d2c4f584,807e3fba,d0712e1,3bc4ad8c,78261681,3d00a237,36383731,7de79d0b,1f52264b,6ea70526) -,S(6797c2e1,d1c2643e,a831372a,abf36ab5,fcf88804,9a01f052,a7930792,acd2a7a4,ab005587,69f8d361,2217de,8d4bf205,925bde,7817e97f,d155fa94,8f084167) -,S(f302e07a,8953b3c1,f0b3796b,55bdf133,84809aa7,3dfe4fde,a0d56ae7,a04c2f26,339d529a,a6c0c8cf,f46682b9,c36390d8,28b2861d,6f4906dd,a4659028,c74d780a) -,S(aa4c04f,b8261965,9254f9b3,2d9e25cc,ec651f79,b710cc3d,bdf4eb3c,dfc207d8,520cbe2a,c8c0382a,23d2cea6,6a18f28,bb87e773,6bf60dc1,cca64a58,9fda48db) -,S(cc4bbc6e,7f4b02b5,ebe6d484,6352257,4651fed1,a079767b,fa53d1e0,dc38b5b9,4be5e0de,c97683d4,939077d1,edffcf6,dee4a88f,f7d42894,c3d50302,70c9554d) -,S(6a4bada6,cf1e123c,e80fcf83,2d6934f5,486901f1,6d3ad0af,cc87a4cf,205e6e79,b79145f8,24d693b3,832c6676,e35a73b8,d8acddf1,681720f6,c8d5ac7,f81752fb) -,S(d7ec4d61,1d440625,367b2c5f,a6904b8d,cf6f0d81,39cc3bc,16299e1b,50c9024c,18c402c6,3e818647,7f15bdb6,d514373c,89d1f7ff,bdab83f3,5267eb0c,daa81d89) -,S(4e21e4fa,4b570b40,77ff6876,a1d7e4ed,1db77d0f,56d35445,178ff508,5b197169,dab19080,ef84f0c8,4919d869,36de1aa3,ca85a1c0,aabe902f,b46b31b0,3b350580) -,S(32aa04b7,53752059,7b4ef603,62aa208a,effa6891,240a587c,e1cae58a,28a6075f,ca649475,a58a3ebd,c3802c13,f006335a,7d203ddc,88bbd1fa,f0787839,b9452f21) -,S(306bcc2b,94214994,e86c7fed,4f510ad7,9eb1af11,b824d897,a1cc7564,9eaafe0a,820c2986,abf17343,35089773,5b4da35c,56265a25,4a768346,5dc084aa,ecae6dcf) -,S(37d23716,1044ed4,b395b044,5d70eaaf,864530a7,fd8490c1,fe2d1ea5,61f4bc19,a6a9da7,70558993,ce38d5d4,c69dd25d,134f37f,c28dddef,2e7edc0,c1343b83) -,S(1f324230,886ef594,aecbe39,2d7a4434,fbb9fefa,fe22573e,9302d3c,dc81490f,39e53099,f25e977e,da860f77,6d09338b,c0e75446,42557c8c,b05761a7,c18537fa) -,S(256d4808,d6dd018d,392a6716,2af909f0,51bfeea0,9ce22a76,6266d1e7,61df967,d5643938,c7d9163b,38fc8072,609bcbf3,e063d78e,10cb8cee,32c00abc,6341df09) -,S(58a91493,ff7aa600,1f457506,624ce8ee,b1c142ca,d49f67f1,be099c58,3a7934f4,bde8d64a,79d5722d,6a96d240,897a7f48,8e20f19f,259fc6a1,e4483448,e0290122) -,S(b4a80e5d,eec9391,8f146b4b,e0d91630,606a5c79,1c4b7b87,d4363de6,e2691f2e,a6ff5b82,ca6fa424,efc00b20,7ea90991,fcd5af15,d23140ab,96da6cc8,bd532297) -,S(41bca570,b4981232,f21ba765,4f23d5ac,27f3bab6,9f1107fa,e3dc5102,6f8dafad,5a14cd59,9b0bb884,10ed1475,8445c49,3af3b7c9,2cc6435c,5560c4d7,832709db) -,S(bcff28e0,bb6c242,a7805142,122848ec,6951940,bb4a2e3,5ae05137,d73e8264,43661933,9ff9f2e8,278ef17,329682be,aa801596,e4a12b0e,615fbe7c,4b24e1aa) -,S(8aaa2f44,fbf66c2b,809180,bdbb4e2b,e25ff178,232fcaa5,a2c2563,8c1ea21c,69dc0de1,686bffad,1ceee711,95831b90,c57900a9,baf57ac,2f34a917,6d33e21f) -,S(930a3df,f84583b0,ced82f81,96c39c16,b9318f2b,44efde12,2be6c10c,70b33dc9,ae802936,2b10029a,a81cfc47,1251ffc3,6b586de,da9c1754,4a96d3ec,31cd6d1) -,S(907cf1c1,92b98461,8021a33d,1c9d22e3,22dc83ab,d5768a39,c04444bf,d4e76df2,527eb629,ca0a2e2,7da96361,ee727a34,97edb8c8,68694871,6a7dcca5,13b6f901) -,S(f9d32e84,76c666f6,29e86e0d,3804eee8,abe1ab26,ae2eb396,b584e4eb,e9583b88,d92f265e,9e6c5f4b,bc05a432,6fafeace,1516f823,3e5dc280,b239fa6c,bfdf7fb3) -,S(94772c31,70e50bbd,9952bc69,44e0007f,3d928cb2,c86465b2,ef040fa1,b4f90d9e,29021913,9326e358,2cfa8ee2,428c4307,86cb2de9,6ea2c735,eb71f759,bab14637) -,S(2b49cd38,8cec8c30,e984d40b,f1409c6f,df7ff24d,36cb699b,5f3c24c0,fcc872fb,9e65a427,ce5dcc20,db83a96b,720f29fd,df643b2b,a192736d,c621d92a,6583aa8) -,S(454f174d,8c344479,9bb58158,423d8413,ce87def9,2fd25a,5164807c,982d84e9,bf324810,d9894da6,1eb1e3cc,5a30639d,6500a453,c14e8a40,78353d42,7ac67ee1) -,S(df4461b1,dc1eaae8,5b4b7fe1,e87753e5,546f48f,e39da02f,f1012b24,58a79a17,ac4fd2bc,af8e0b51,48cc5a5d,46373209,8993b377,becd718,732fa339,95412fda) -,S(32973a0,d1be4c6d,1342b2a1,44ffb36b,81fd9b38,c0b7411a,65b8ccab,cda9161e,558b278b,f507b498,fdbbf73b,524c4652,53a0082b,d53a87f0,75d5a49a,bb601b69) -,S(cb63a9f2,d1a11b08,479275f,e1f0bc64,37126875,5bcd8a21,3481be2c,818c69d6,4949d3dd,a31db2b7,b2d42f2b,4709a870,5094d470,1e742f07,b6f86670,e43bfaa6) -,S(543ae5d,a0c271b8,41542353,277e1651,b7b0f587,a5b18ed2,856c2e07,41c28914,22c999cf,aba6f95b,21f87ab8,2f2edb2a,3dbb43a6,ff413506,83835ae8,bbcd0a37) -,S(7ffa63ef,3df62097,a3b61289,4eaf5bf7,4fb39ad2,9ec63f02,2c6f310e,77268c7e,9d26cd72,8fcbfe54,6eda19db,5ac61978,1b456699,59a21628,2500e5f5,389679ca) -,S(72cc6606,b02943a,5bd9a476,6b24caf4,e0e2f83,ae3bf671,5f05b39e,3436122b,f35ff21a,39503637,d05b744a,77797565,1e290541,326d920b,d5bcbb6f,74b56c3a) -,S(f5f21182,de67c3eb,396055f6,a8f64f5e,54043376,cdce9f3,3cffa601,4a348a4c,1fe09f94,8ad7f78,6c184675,3105cbd2,e0f8be91,f9160e81,9201fed3,3208b3c7) -,S(1cfa62a3,70171431,52fe149f,db07b00f,bd8d7928,e5eb145f,b4ff7343,fc19437a,1efe47f,e41677bd,337451b3,92eddb1c,ecfc19d0,5ef04727,12927d4c,77b2a742) -,S(b6609139,733864d3,abbdb6bf,4b827b2,3861594f,ce9e996,4637ef14,f0fb6849,2e807df,ae409cef,b7be1ffe,63351d8d,8de5fbeb,f3be5069,31befc97,d479c006) -,S(13da7c85,bffeaa0f,e295ce6,38de0b05,1b4aaf9b,d888f5c5,5f74fd60,abf2e016,c0477fad,fba6531e,f6369aaa,be663871,3bd6954a,d1e5df1,269c7208,31cd5bc3) -,S(2abda634,547a86aa,1188b2f6,ffaffb36,dd126d94,18406bed,8b81e29f,596526a0,7db36141,2e96e02c,34c0e39e,1201617f,2a7f2100,d5c3cf64,6dcbe563,e2b25524) -,S(4e161f2e,22785c68,3ac494d4,1e3cc2d5,e6b87be8,bd65e85,8aa255dc,8ea8fba0,c81a4e95,a2cfa101,fcb62112,b60c574c,623b5df6,5a1fcf51,e6bf2936,45d5f17b) -,S(586be2b5,740b0ed6,6f5c5f6f,217766e,ad5543eb,8e983ffb,928fc40,9e76397a,f11acf99,8bc2a25,48799529,9c7ea84d,98c6a525,6cbca56c,3ad534f9,26c6b08e) -,S(a76c4f91,1d0dcd58,9417fca9,8124f62e,789e0b05,91a9ce94,13e0b7d,e7d5986f,6a49fc1e,2b32aeaf,6f291184,3995602f,903c8d76,858fc532,9b3a1940,2c2c9b7c) -,S(15f11b1e,804a6d54,a496ee4f,f3030167,eb510e9c,c1754bd1,d46beace,1211a68c,f8968e8d,21bca271,75a79de5,31ad810,ca6c6da7,72ff96f9,937ef824,8f4fec45) -,S(f0169f41,685292bb,4ac93afd,58b2c239,3985ecd5,16acc8ed,ce46f325,74b23e58,6fbd711e,fd488c8b,43151ecf,e3a42ad6,25697053,1df18afb,68f8ad71,ee9aa05e) -,S(2f241e5e,2596d32b,6cdedc4e,b6de5f53,374e358d,8db78d08,9e772b37,6250f359,fe79f0a0,cdbef5a2,7287c86f,afbe917e,4c26c4ca,512f57e4,ab066d3a,3f7e71e) -,S(a14743eb,92bdf49f,5f404a54,ab193100,26f3fbd6,fc5a06e3,e8c6b33d,1f7a5559,3e7e5f24,b1d0425c,ee5c56ef,1e38098c,6d67fd12,f57eb2fb,1ee76c57,41d57c54) -,S(2d097299,db14ce88,8da72472,da686f67,b8ecc812,5618cae9,2acf6457,a011d2a9,e9cf7195,32f71130,5bae1fd4,ce3a8fb3,c8d71088,df35b49d,ad9c16d8,8734a187) -,S(aa7257f0,d7e51fbd,95598b7a,a994fac1,41aa76d6,318cbda0,20d30471,73317f2b,15e00f94,f684c30b,5cd4a978,c6245e6,8d30d959,a30fb39,834e97d8,c18a1b27) -,S(ae524618,e2877095,d52ffc94,67a081e8,b27b4b16,566e2b37,c8d11b1f,1f7416a0,d0275a1f,6d49a7c9,44a07a6b,ee5d5095,7b22b698,2607f822,8ad15253,a546ccb0) -,S(e7a85ef,ff8b0443,eace4cd8,81d768ba,ef4d93b9,79b17eae,fd237e8f,c9ff660f,4b53f073,8f07b360,7d66f720,b1222df3,eee2dd,ca20f40c,630a7911,a0fe2aa6) -,S(daa96eca,b8412eba,75f58a80,84a302a6,37dd7d77,bc9dc502,a2d083f8,35bf242e,ac3dfd97,a01557af,cd1f199c,afea0cce,52c8e3d4,975cb331,1c817c9,fab0815e) -,S(34dec21a,965b7027,44fa7881,4ff6f782,790d551b,7be35c,18cd46b2,e189baca,ee825c5c,5cc289b9,d7f01b43,4de4f0d,d250f9cf,c22c8d20,a1e54175,9bd23694) -,S(dc2178c1,2f015bee,829f0567,566d15e4,d607c8f3,b2992801,4b6a5607,1e61247d,fc86780e,31cf57ff,5da387d1,c3c25a19,36a263d,f6571de1,d098153a,97b41db8) -,S(6faee1e9,354bebe0,1fb65158,20b7e992,9517cb40,23d49d19,2a002ba4,e4782db4,a4915992,ceb8813b,e2778fb0,47766b6d,3958cf72,f18e9172,3f74cef0,1d2276a) -,S(a2bcc012,4112818e,571c8dae,3cb724dd,e45faa06,d04d7128,e9a71dce,22f300ca,1f594d9c,64ba43bc,11764c61,f8fef5c2,e31fda39,3447e7d2,10d004bb,c13870e3) -,S(b8cba39a,c51d86e7,d83a50af,f5370240,cd7b20f3,81aeb799,f951883f,458ead76,3a8bfe74,2b3a05be,27ef835,39988cc4,616365fa,e3738d35,29f9c0d1,c15eed4d) -,S(56e532dd,295792a6,ede9da94,c43e0b2a,25b72725,333f8205,7a352ac9,7a1991d3,a617e234,18bfdccc,8facb454,649a4914,2f0abd64,f30e06dc,838fd80d,7a141fc3) -,S(4803406c,e4049575,19f5306d,6daa003d,2aeddc1f,c1d4db45,15a8d35c,aa39a6d6,7add51c,12412f4,49d7b0e4,b7df38a4,83151126,49660956,da6273ef,8b53fd5e) -,S(bd61ad65,2e44effe,ca39620,2f84e4d5,d81cc579,2a2390f6,52409852,cd79c459,f3d7071b,8bb18928,1d827f71,ab7b1ad,5289033,ab28d20d,643af02f,a2b4ce5c) -,S(1b543175,e5b6f271,58048588,f81a791b,3ab216a3,578e2f79,354da6c9,5e4ea9bf,67a2e60b,321456b8,5b5499ca,e33cd6a6,d5445f91,eadb5a5a,f0e2164f,324417d7) -,S(2035953d,3319ffa5,9f75d86a,8d1b52c0,e8118ec4,d830d15e,d9616215,cb82d080,302cc0d8,5bc1e667,b160bc8a,64cc3bb8,763066a5,6652a0bc,c12691be,c41d7aa4) -,S(bf2a9739,f65bebbc,90413f9f,d311e095,e7628dcd,d76d25a9,8a4681ef,f4f84035,83932d07,cc950bcf,380cea81,28e04322,26b9a4bf,8536122b,fd055517,e7d3b2b7) -,S(a915504a,bb62b4a8,1288c44,8605e8ab,bafb4f0a,ffbcef23,c9c2a26f,f2cb8557,2fec1059,abe1bf4a,834c50c1,edf0e5a6,2ef21f7f,9da2fda,20989bae,18acd442) -,S(318939cc,fb2eb0f8,30d30079,7e209f00,6e28b899,8aecb548,b3b97900,9ea6aab7,5308df9d,10c7d151,cbcbe417,91b627ad,b7204db4,dbd2e01a,c5698e61,bdbda375) -,S(ff9e4851,d3f0c9cd,818facdf,4781cecb,7f622039,c23e236a,7e4b7368,64af1a8b,fd69f241,bac1c6b9,a52d6dd0,6e7bcb6,4a4a79a4,9c3881be,6ef8c83d,3f462c5e) -,S(497113be,a88d4888,2c98ac14,ba0bd0aa,d3c75c8a,58d374cc,86a7fd0a,b6259cc5,9029d9bb,96076d69,a264d2bb,6fea2f15,423ff1f6,ff47c02d,4699943c,9cbfbc4e) -,S(2b2cdb82,6653f563,dfc4c373,96d738e8,3d1dcc5a,ec5f4886,2d5ca84c,2ba69103,d1985cb3,f42e4ae1,7da33b7f,f8563236,6e2f5c89,b849ac73,afc3a7a8,1d049d85) -,S(c55dcffe,fe63e948,af77c8c8,32cb6c0a,c09ced5,5c338bef,fc27fd21,dc63b6c8,edef9fcd,b00fb62f,cc97c03f,26253069,de6f8d00,c13a5666,f574feb7,fabcab6a) -,S(52a0dbfd,371bcfb0,e2c69160,c9cca2b7,8dcf679f,774c9d99,706d306a,30eeb3c8,fe01f320,781275bc,a6c031e6,d71df467,56473d8a,780fc54a,6f8eb1ae,5640bf65) -,S(75c4ace7,6bb32bac,13141f21,615e11e,7608fda9,cba4723,9eb6bb8f,349a9e86,7fde50af,19506ba4,65d49b93,c8884478,dc34ec91,9bd5e22,be6bf71e,a870a70d) -,S(69cd7caa,b220abe7,8f36f7a4,633802b4,85969ac0,e9c4a244,7b0ad782,29daa879,4140a70b,8d9025d1,7fb3402d,2ac8afda,e9e0269,b29d488c,2266c1bd,58accc9c) -,S(b6cf3a30,d2a5ec8f,4480df82,ec6104ff,37355ca6,f16418ab,cad3a0c7,bd8da064,f12006b7,5d406558,51fde0eb,c68113b8,50441595,dfe3dddf,86c17a58,94a6d923) -,S(65c4a081,656d9b7,445131e8,6081b306,3a6e0c02,5339d3d7,cf48e9ec,4e8f59f1,51f4ebb9,4b63b8bd,2cdd6d88,c84c8608,bb380e38,c748ddb3,3dabff1c,f50197fa) -,S(c243570d,e74a1fbd,938bea43,bb17a929,47a228b1,ae47a6cd,15c37524,b034fa66,ca57366f,e3886510,903970ca,e1a5dc5e,bb857007,cd4cc56a,37fc7fca,8aa4cd40) -,S(9290d033,1c95584d,e2bace9b,788c50b2,f7fda83d,d45a4a37,5705400,45339d7,dcb3032f,c4a41076,8b8e442e,46cfb16,b63f4fe9,f94a7d5c,f932d0d4,95e699e6) -,S(295df203,cfa65b66,6afc86cf,b879d650,7075f75b,d1eb753c,709760f6,6ae9df94,2cf505f8,8220196f,9e5478e3,6bd82501,671c6b91,a404fc0f,b1fe00cf,12085934) -,S(1631e6c1,3f89dbca,36cc78db,1056a461,6ce2dcca,62f90b0c,5fcbf232,77d41116,acbcbff3,2c164cd3,b57d3b89,a326b5d1,46b5769f,a5b35df1,efabd2f4,407759d0) -,S(db0b2c5b,eec9f06a,9bb43e4c,de18d978,59a95cfb,9b319d2,5ba619ee,abc49e31,d647147,d8330315,1446a405,85bd857f,ebaef109,22ddd0e,3ac62231,8ee91abc) -,S(2581d046,9e8bdc16,e535c787,1a37c48f,929aad34,b694ac2e,5d264962,11e744f,7bf3c684,3d953b2,dbead1f4,8614646c,d18b0f2a,cdf6fbfd,3ca68498,ab25bc60) -,S(9db20da4,d576f564,372aeed6,eae78eed,f512d13b,13d4e9e2,eb3133c6,13c4b80,40f8b2b6,fa113b6,ed7dce55,d62587d8,a86a43b2,9e0b4876,c5607b89,9144d255) -,S(849b193c,e490990b,e2aa48a1,c31694c5,fa041f96,7086a83,cd1a06b6,ccb5e3c3,353b49a,6ac0c705,5a3d5e31,fa428e2,391165ce,402291b2,5e1b0496,bda41e1e) -,S(ae83dff6,5a1dcb6f,e2f56437,c83162a4,a388a16a,bd387d62,f5c5ed,ea08fe7e,e9c57ed6,5404a00b,a2f87613,4d484842,4a32246b,def6c31b,533caafe,7029eabb) -,S(24724eab,46175b4,efe51d4a,5993da48,1a62c6e5,f05d16a5,17e4f58c,fdb103,94465b42,e4e378c2,1ef0d1d1,8b25d140,fb17f51a,fa4d37e3,450c73c4,72468b04) -,S(c2e2f802,4ac48fcf,41a3790e,e9916018,5a301859,3cc3fa77,c7840552,6700659e,b1fe219,1563f9bd,20c4dd45,615d8cc,400911d,20cfb7a7,672b06,20d32a2a) -,S(8b889bc3,e2d1405b,47a1a05f,fd0c17ef,9b4dd75,4d30640b,e3c4de7d,f70791b5,e2d459ca,285629d,956d5046,54c5e907,6ed92fa6,c95643c0,7d746b78,e03a044a) -,S(336c0585,8f5ee169,fc09fc73,a181ccd1,3bd62dd7,c454837e,1a5d7676,abb2faad,5c29a656,e8f2804,6e855c6c,eb0d908e,38f1b62a,69c67948,9d6a03ce,64a90c2e) -,S(c9a6df46,411961d,a703ab23,605fce16,fe021576,92a9b80e,65b9e4ab,efc9ee93,8b63a4ab,18a4b190,89dbc53c,ef0b0dc9,20c0ec7e,1fcf075,195bccca,58d52f6d) -,S(6cea35c8,b3a45063,75456a6,2c95e8b3,7d84a6d3,e909c5a9,cc4800eb,5bc28367,68198888,eacc9380,4a3233ba,1801d586,e5bcb2b2,78efc7da,6764bd5d,edf0ee90) -,S(f13d4ee6,ea31999d,d8d1220a,13ce8353,7c350046,319a0412,e562cb8d,3e4ee80a,5f7afcc4,37f0b29a,ab11a8b2,14947521,bbb4b622,261b9e73,f989e1b9,9f43a2ab) -,S(7385b644,2e43ab56,f4df8a57,4d0a32ac,6e5a7114,13dcd992,f86c0b04,33830307,6d27608a,8ea00e22,4197c8a1,9e9511fc,7ecd7083,86e94ab9,6aaa35f9,c8c2c5f3) -,S(35923ab9,a784ee6e,5a4e911a,7552fa16,ccefa4e3,dcc90083,e5a19e31,4dfeb06b,c900475d,980cce8,7d5cc091,7a28c18c,2fecd5f5,cd2cc66d,e26deb61,1c5acb89) -,S(d88b6907,3abccb02,2e235e60,4f3e2877,ef979f85,a5b3fc4d,fdb166b,a4155d9a,1eefcc82,69a20b9b,48d30d00,e7ffd021,a9b7b171,378a299,819d6e6d,19d5ed24) -,S(b86c5281,cfb9f3b8,4be4f83b,1d13d33e,1f6abfae,bbedcac1,63362a76,8740a827,c1a32696,fc1f8507,289f111c,85483b23,23d228a6,773030e8,dcf30f6d,57857dbe) -,S(d2813221,9c730094,97c257f3,1fbeaee9,1afa001c,84e4b813,d7ee2452,6454c640,75d722d9,7111d6f6,b6324598,8720ce39,66fae55c,3d81e4d,ade294d6,1269b4ea) -,S(445addf5,bf941ace,6b4aad55,6f174ba1,ee793bf4,9f46295d,19fd8e2,807f8d3b,cbe249f1,fbb39f8d,93079d0c,e84302dd,52212b6c,828a1626,b7446f91,4f6727e) -,S(a2dfad8d,66fd47fd,38fbcb74,b983d366,c57a08d1,b04f1acc,4fdf047f,100552f2,63011d2b,43822a21,ddcdb1cf,ef4dc0d2,5f595165,26939761,953fb738,77586c9d) -,S(c4e84511,6644466b,8c573b8e,c7dd3788,ecf1c6c2,63ecfabb,b13f697f,2b2e3a7c,1e53964,a70e83a8,ed9f5d8a,b6b79629,7368bc5d,cc90e6fc,4e8e6f65,542f63cc) -,S(63c4cc2c,cf368a04,be814d1d,81fa4250,653ebeea,ccdffea7,944801f6,efee1aba,6fc2bb4,a7e573f5,fea2cabf,abd9a145,c7c36d62,11928341,e9553e8a,b38fa90c) -,S(51eb8782,a3445ef6,43f01634,caad6fe2,29585dd6,f073acf3,62cfaa3e,960343c6,56d20f56,8e6d868f,491b6e1b,80fa5c88,e3d625d1,433b1dcb,5ae2d35e,b40a960) -,S(d89ea50d,ab6c4c39,48fc4d4b,73d7812e,a6b59ee1,8e7a51e8,bf6249bd,ec59d068,a1ae85aa,e842ab60,95feec2a,d6ce6206,e81a6e76,7f0b7b20,d41cd28b,6a8c4258) -,S(d121a6a8,11f953fe,a90d8f3,4487d654,fb48e4f3,c5ac4db8,3e3f50a5,cd7bac9c,a5b9e6da,e07a0f1,dc1695e0,20502f55,5fbf136,df11b586,4ecc63e2,d7061a6e) -,S(83f7dd06,e5afbb3f,7b2563f0,faaaa3cb,20c32db1,5bdaeeb5,73219814,caa599b3,c452f49,1e4482c1,1cd4bf46,75d74c5,ab054163,b6d1b837,dd10aa05,950f199a) -,S(1f5ba7d9,b4cf8684,cd073892,4aee1919,1f611d78,a943d49b,509fffa6,31fdc19,a017e13,7a8a199a,e361dc18,527f0135,51e48b02,c2f7f102,a6c1ffbf,fdd0baba) -,S(d25fc73e,a83ef669,c2e127c7,1615df3b,ec61ee38,4a6b3396,cc52066e,c3b70b8b,9b5d55e1,c8dd008f,19b5e989,363ea737,e7d7bea3,f7b0d9b6,951dd78e,be6c5334) -,S(d749373f,ecc1814b,dc8ce6d1,2ebe84c9,e09806a,9cbec814,cf98dab2,4a46ddba,88012af1,84f7ce23,730a3a4f,191d0687,4d5652dc,2be47214,61e9ad31,b39ee397) -,S(8e05da99,971ba37d,38e7642b,693856af,a90d7206,2d360611,6c8f506d,68316b9c,73de534b,5833287b,61f3f985,2723be7b,e8e22ee3,1d1ef4fb,f45d6931,827e3db4) -,S(e71e83f1,c6b285db,157f4a14,825aa540,558a7853,673900aa,fdb84556,ae5c891e,e37980b,c180e3d2,481d81f,f9aa33cb,b297ffad,7dbbdd79,4fc013f5,43ee679f) -,S(bc66d644,dd9da12a,299557d5,fd35993b,ab05ac8f,bdd3802f,25b35890,db8eed32,5fa8c7e4,bdf77750,573a4ac7,1681ca04,4f796ea9,c8379cd5,ed55631d,bfdb8405) -,S(537f194e,efe43985,8dbe1eb2,8e27448f,fd1b554a,b12805fb,3af43538,fe0e37f7,e82018eb,447b2810,1502453f,db4c1cb6,666330d2,ea3331d3,f79d5652,a1d64af7) -,S(4af2a9f2,e0fa4b4e,731dbdf3,676538c1,110f3232,7b8f2766,a7f489de,8aec3b4b,cf2e0ca5,dc830856,43151cc0,1507af4f,d84b253,2f0fdcc9,6489baf8,6c1bd4ab) -,S(81369bd2,a4945c15,389aaea3,4e2855d7,6343e200,a9407ed,d05ae927,5585aa36,a9b4ba4,e26950c6,6648b573,3c0c4e5a,22a51e71,ac3c1fdc,78403eaf,3a667161) -,S(1c0813d7,ef91aa73,9e3a6f0c,e3c7edcb,2b7117a7,2ad1dad6,1aed130f,c61cdd3d,e3390572,67ac3bfc,5373cc31,14bd0f38,ccc3cb25,862b243c,912c0aeb,98bb86d) -,S(8a651923,d2622057,59e5f82,b38bfae7,dc922488,749ea56c,e43f0f74,c268f9ab,f3df434f,14f67030,fe888ba0,185e25c8,38520bf6,6e85023e,e4ff4f04,b056d9d1) -,S(89d98548,30a2a572,dbe91018,e66b28de,835dd02b,f793a469,2de3d720,d70e8f43,629868e9,9e434bfa,98bdc4,f191a08,72e68768,ce8a918c,7c2da42,75e5cb3b) -,S(97d0c83c,5d83d399,c567ecd5,dae551fb,7f1838de,1967e84c,7f053b81,62965fe9,fd716683,73347fbc,407543b6,70734733,df623a55,1766f55,8a02059a,2ce55c4d) -,S(20807bb2,650e6d82,38a66ed4,b239b59e,fe073a5f,9cbf0d6f,e3d9a16d,be427de9,46a25a29,c104c56d,8436155f,64b1d84a,b974fb2c,951470df,17a9704a,be5c1f9a) -,S(3cbb1786,945bedb5,c8ac2d0e,dda1b0bd,ee314cc5,faf56b75,fa878bf2,b218a8f3,ddcec0c0,d05403e8,ea2094a9,6ea910f8,3261932d,701a2ea0,4e93581a,7e4b7275) -,S(961d0144,1618561d,c3504859,7e1701bf,35412ad3,2d04486,704e5593,b9278734,7e137d6b,2060572b,ef66f8b4,c8ce535f,b858327e,26dc2295,6ee6c94b,c83859bc) -,S(2814918a,115ca2d,688f4358,9010b7d8,b8b560f3,6a3dce2,8fcc05e,acd4845b,dbf76f51,ef80e324,8820cb0b,bc7f0c2,4d50ae48,6387d206,c333222c,5f959dd1) -,S(6c4f3b00,c02c19a5,ddb0ab1,798929ca,222a9538,b641cb3c,dd61736,77c9442f,a91d13a4,d3888b82,eaba5173,3ff76fae,8022fb10,8cd61f19,206cd78,7d1c99cc) -,S(8f48304c,ac37d495,fa1a2ff,2178f442,4af030ca,70662a1d,c750bde,5f5d8dd4,ccff6176,47cbdd3c,3d0c588c,37a98723,c2b2aa14,fd17cf9f,ea45ec72,eda8defc) -,S(ae3da559,e3fce253,f5c1fbad,8e12a52d,ee989ea9,8552a192,93f7db0,eaac9405,430b86d1,322191c7,9aed5bb,12eece79,f2519bab,17998346,8aa13b69,94032ef7) -,S(90c093fc,27fa9de,66a1fdc4,d921e5da,6f4fa049,81cb6f91,e085f89b,96561471,1bdad536,4ae198ae,bbb0ff88,3bd5dd2e,dfbaa91d,e989f45a,30befa9,76f2db23) -,S(730a1c4,5ca28743,538fcacf,a65b7d90,b6f4b1c6,87364cd,53dd6585,328eeabf,7420e8da,cc64a059,b46221c6,c3adb4b3,46eceeb8,8effca39,1a1e36d0,d665257b) -,S(341eabe9,66c6ce4,65ac18ca,1eda053d,4e6137c,ac0796d4,36a942e5,99ef897a,d298003d,fdd9f529,c1977b3,ed426d6e,2df46098,539b20ef,c2011a36,b7e49cde) -,S(8f7e1b2,cb538fce,4b4a7775,90d1a95c,2fef8331,9792c0bc,8d5f3493,54fca169,71b0849f,cec62c5d,fdce37a2,61e2a06d,32b3e0de,87c8aebe,e5a95cab,b0c3f798) -,S(c7ea6b43,ce1e0e83,819bee9a,31fba823,3ee03a6b,14988b98,e80aef2c,eace0d56,e9f1328f,dca6a16e,2100ad40,138f9810,17e37e67,7e7ca747,c3a57ad9,24b8891e) -,S(b16ea5c3,b03e58b0,e6c217c8,6eacc4b9,3032add4,30acfd7a,e50eacb9,a0e5c1fb,507fed89,5c14380f,ab9e54e,a3624e5a,cbdaed64,b2712f88,48018b90,7a88f47c) -,S(15cf4de,7c36b72d,f7b98c00,8e928731,a2e71c69,cd0427f3,ac9264b1,5a5fd487,3865beea,6b36732c,5ecfd21a,562ab253,d618546b,c1c24745,8881b20,643d7e2f) -,S(394efbbb,fa740f53,b1e70eb9,d12671e7,55337357,b982921a,79915acf,ddd18218,8f1f1980,6c1d631e,6519aadf,b563dbf2,37b75db1,54baf06f,6fde8218,a0a68eb6) -,S(e6c3e152,27453d32,cd4449d1,ab1ad78d,58f5bb6,f29d813c,e7c6628f,b284399f,89d87957,4b640a87,abadc6a,dc51a533,838a83f,53de4448,9ff0640a,502dfd62) -,S(e2480000,9db30642,f925ef8a,e31c54fb,1340e88d,b6d633f8,415ceac5,f583cee6,39ad28f1,8ecd8302,5cc1fa72,ae4e9897,81318cea,9e506794,50abd959,f19758c0) -,S(1c134120,3c2e7e21,f5b10ecf,402d52bd,33db3278,70cdfcec,f3b277e4,78f551f4,cd6907b,57cfad79,5e14e7c3,b2a06a46,17b7a27c,ff476bfe,38d68d0f,1470dd63) -,S(6b2fbbb1,515c261c,954a0be0,279a1cd6,63daa083,1fbd58c9,c69b7be7,ee6047dd,d38ef59b,4e276fe5,6f1f2fe6,74b6974d,5ef1f4a9,74abb2c8,17cc68cf,78a164a) -,S(dd5098a,8cc8ccf0,7db82096,b52d1fa3,6bd26c2b,57f0cbe6,2ca954db,1773e9cb,a198ec1e,71c53d73,5b50000d,678d7d93,de64a72e,8ad018bb,f515b4f7,c7840aff) -,S(f6dc494,3baa0613,59a000ab,3aed3456,1972d425,34df86ae,3eb8e5e7,cae23c22,7150f3bc,5a968248,d8c71ea8,32b116db,73ff34e5,35ec1e6b,64b2474a,947174dc) -,S(e115c926,5930dc67,bda89798,e267dc48,12c06d2a,a05e4a5a,6519b0bc,7096f84c,5b0dc7bc,82b61275,2aa17a13,c1fe2cd7,6b60cf1e,ceaa9234,ec9e6609,7b2018ec) -,S(6687f498,98a22d8,58ef88a1,bcbfb446,33d51eb2,6c1fc2ec,eeecdae9,e0960c56,fd1912f5,7c0e691,23977524,ba58ea04,5757aeb9,309a5b94,3c993a93,57475ff) -,S(366ea4df,3aa8da52,763b513c,efa3c739,af61a497,6fc4c884,e879ddde,c2457d1c,876520ba,cca3c711,a23186a4,833db7c7,14b3de4f,fc86e8e4,cbd61cc0,9a48f34a) -,S(f7951805,eaddd012,2bed030,f3013e15,6fec02b9,80ba8ff1,1a0b978a,3fbeb778,b255b5c2,db866de0,a145a108,f5eb4b69,271c13aa,8db75fc9,f467843e,a59549a3) -,S(c77d217c,5c7b8fbb,f7bfd244,b2a2d2db,372d8217,43eb4a03,47858678,471d8be7,55573d9b,dd16bda6,ad916820,874d64d4,b260a489,b4a93427,1ea5a79a,f57dc5c3) -,S(c803dc3c,1432ac63,19db169,6d7ebc16,58021b8c,b92c0fe6,a59d1efc,2056f214,ce8e23ae,c7dca471,8666f61d,d7d8bc10,e06d1929,7fbad7b7,7d45526,9e207b09) -,S(676c4c3f,617b661,2affb2c2,dcfe072c,ddee8b29,dad9124f,dd24e87b,52a80b88,6df8c35,be6818bc,b6857f47,f59a11b,e05cebae,ee6c53ed,8cb93fa8,92c49e0b) -,S(8b0c8502,bfa15f59,335cc34,20e04c90,becc2308,12d40c7e,14fc3e30,88b8f34f,eb75d312,9fa4db28,27d20c93,de9c5cc9,4237bbb,a9710371,f767f686,e5ddbbbd) -,S(6ea07148,5594bd90,2d0d526c,28918bb2,cdb7d1cf,d3ad0b1f,a3ebbf76,71a2f90f,3a30be2c,2058cb43,c6f8ae98,1ce8986a,8b4dfc3d,81d49a80,4e40c81a,a1fc8220) -,S(aba7df4,8bcaa5e4,c4fd9a21,6b4bb3fa,27617205,693763bf,71b8b214,9cf83c48,6b1b719f,a0633abc,4580a9cb,9c1210a3,3e5e3bfd,177bc76,39057e51,3fb9b3fe) -,S(ccfca0f,ee5bebb7,26e2062e,2b5cd592,847031d3,5edc7767,414af809,9b3ac2ad,135b2ff2,4e40f04c,adef93ed,ceededb7,380c1e9a,e32a499,467af149,cfb532cd) -,S(9af36417,f3076595,42ea54b1,4671d2db,f7582ff9,b7e659a7,6465ee2d,4db88e35,dc5d07a2,58d4f5d5,ae649b63,e07a4253,8b8b3e42,c65a6ba3,44900028,c84df8aa) -,S(e2f308a3,e4d99e74,d6b37cc1,dc41d9fd,e98a4472,6e86764a,89fe959d,deaf922e,f5f8eebc,d9252e1c,74b9040b,569c9d5e,11d12af5,aa21051,8f87043c,7b47776a) -,S(a62581d4,c4fa4b6,aee11db0,8fb698e9,864cf336,578c536a,8a887d1a,89b43e35,b530ce21,bba9d034,d53dd490,2b76f25b,4391914a,5f87b6d8,2526f7c3,def132ba) -,S(11ef91f5,dfeaceaa,52f434b0,fc03085f,60c12ea9,4441574a,5725aa86,52c259b4,a2c81e79,cb5ad0d6,bf0221ce,2bf7497e,bc91026e,adf0e25e,6269dfb3,2ced7d8) -,S(ff549a04,fb86bf9e,3ad207b5,ac76a74c,2532a1a6,516327bc,96353baf,66269c5c,ef1088fc,633f639f,f0061bef,4c1e4c64,5897ba0e,ee229d44,d99be0d6,95e494db) -,S(11c9ebb8,893b6534,b323909,961bb8ee,4c90c854,52848ad4,18fcf223,c80eb7cd,4b0229e0,89a1ca0e,d60ce2ee,590211a8,769d333,5f4ef32f,4460f8be,940a0dd2) -,S(e86b3691,f8ae48c4,12a6216c,c3633f1e,88667299,f828d6b1,3ff88cac,e060b1b4,14d95d6a,61298fb5,1fc974fe,f3957db5,4aac7130,a1ed873c,cee5cada,6eec0c6a) -,S(e5b9550e,eaeed973,5d8068b2,2c48bd2a,608fdabb,563c0e5a,6c2b2351,24c49d19,506ff679,2ea7c37c,254d7ae1,a459204d,aca23016,93c1598c,2449b758,6d437de4) -,S(cab58ba0,cb15982a,c1ae5b51,ad65574f,55540820,d057e11e,f9c9f9b,a1388335,ae1c9e22,74958b33,2ce0f0c7,ef621a49,4d5b0ad,b04748c6,539dbcbd,6bd4ef18) -,S(715e4568,9bd663cf,e9c83006,82fc7c90,5ae2da55,42b0ea4,40cbe2eb,36e1eb43,58ccbf96,8860cbfc,6b03f6a,a5fe05db,14be0e3f,3d6224bd,ce6eb54f,7372aa85) -,S(df92f1de,4d22a7ee,6d2bf45a,5728745e,f59b6b07,29614536,722c7de7,965c0648,59e18767,f0e22894,be586a13,46950c03,88f1529e,cced0d18,50439dd0,e5bc192c) -,S(885dd01e,dc8ffd40,c5f26d7a,bcecf670,7a791ac0,b2332b91,12e69cbf,11399808,4ad58276,6e763ddc,3f4ff718,569f600d,8c764659,87ebd74c,d506c2,ba886ac8) -,S(d3fe74b6,17a1ab46,c773549b,af4bcbff,917c7ecc,fbedb63b,651b2197,89c1ff9e,b2e6bbee,5d84b593,d43467db,7372f40e,493a9fdc,c5d88fe6,5767f45c,837acf93) -,S(c3730836,74b97237,66d9e9de,f7b6d792,93faedf4,f7d86301,75862d62,d4ada8e3,b669a24,a31f8277,8686d2aa,6b2acd16,872570f0,8e6f06b8,394f498a,dc29f099) -,S(4ef2ace6,422be7ab,6a614e2b,fc43360a,2fdfcdde,51cb31c8,372a2042,2df4e100,86868f5c,37366665,fc6121e0,a8ab3a86,92ba1714,f5b8506f,9a3c3025,eaf9fbc8) -,S(51110764,573c540b,813ebc4e,79d59277,67e30ed1,70a951b7,9ed05f8e,8d142cf8,ea8890e4,9668304b,63fad75e,33f42601,f2649a21,724fc495,61110e79,d7ddfea9) -,S(36cbfeec,5491e1c2,f853d98a,275c1baa,e74dca33,2bd3d830,7d896607,c1cb651c,f67659d6,677b44cd,33c0cedc,d5886ad8,90eac77f,5b393fa5,6cba1077,54489eee) -,S(d1ff3875,e1ef071,eef96f05,bc19d356,aeee18a7,f3892f02,4d07b43b,c3f09dbf,ba825e43,72b4a644,dcb5b8f9,62e0099,ab75ef9e,34b54874,f8d68197,ecbe8eae) -,S(45e7bec6,75819b22,f2761ae7,575ebd6a,8ef87727,a15e33b,3edc7ead,dd58fa5d,3482080e,edaea330,240b539c,7d6a2e42,2cbaf40,f93d5052,28c773f9,6d80fa86) -,S(8ca5d7e4,bd79aebb,bcc5250d,c86ac1df,373eb3ce,1d8cf2ff,5916cbb7,1e8e016e,1af3f417,afa5c1c7,89474f79,a0755bbf,a9a268bf,fdf242f4,c1599dc7,b7cb1e55) -,S(56bf2e78,e7c43841,6324e581,7330a6bd,208edee5,3b5d61cb,a141f9cd,ec3002c4,e8f91e4b,3984a946,29060a4e,534bb4de,f345879a,f4884214,63dd0299,2bfc2fde) -,S(af152859,31540f00,1be4a65c,e3f55437,f7be7d8c,db0283bd,f96bf71c,c004455f,1f58be49,77cf9b8,b7ddf7fb,74f7356d,62b8fe33,6bf798de,3dc435b1,86122b40) -,S(2f4d8117,bcffeaab,7db186c5,7aedcb00,80d67b36,a560c5f0,e323b7d7,79be70b3,e0a50d82,80677ee9,caafcaaa,5d7d1747,3f4980c,73831f43,29b15452,94e71829) -,S(bd96815c,e6b6d0f1,3688cc26,777c42bf,50fb8cd8,cd0aa082,94ad498c,620d1f4d,8a882c49,6592b186,b0a4071c,b0b556ca,27f2ec82,417aa246,ae24b415,8e4ddb23) -,S(cf64bc04,e0796fec,112a5ef1,2c3cd909,5c041b46,2772b818,3e6656ea,16d046c2,6a05162a,eddf163a,fc2cc91f,34f7a7bf,41660b4e,a8ac7af5,698c259e,47e77e86) -,S(3dc4bd0c,2c8253e2,4ed942a0,7f45c2c6,390a9d07,6d334f3c,80dfabe9,282a86c5,e0994668,7cc9c6ca,e2d04840,6d34cd22,e4f8e271,da4416dc,77e59af1,7057c43c) -,S(40e00b89,e58de390,6a56133a,fa574019,51be1efa,6156baa0,45fb3987,94f7ff11,cf675e01,1f20efc4,24b882fb,b7bb9ca5,5a1134f,b628acd9,a597fb97,968641d) -,S(5626496f,1f49190a,48929e9a,403f9f54,319a6b1d,301cf256,692cadc0,41301c27,21702c7e,2ee0efcd,b98a0170,110e3495,e23fe5b9,9674bb0d,b6f09e57,fe76b48f) -,S(2a2c8f2c,a580145b,a9593b87,dfe0dcdd,caa3cef0,20b0e2cd,3792da6e,2f989a11,4aad23a0,e01f6a43,3f6c2a40,f480f945,d45c89b1,df42d67,acf6b0da,3f46bba8) -,S(68a74703,a88b88d9,ee974a87,af7b1be5,1866ea40,ab4cae9d,90a4c2c6,5822b565,3660b266,c74b8be1,c98d3b9,b1f14dd7,e039b476,733a1322,d2d7d2f6,9ad59700) -,S(b50ad45a,4898f77b,c5544dc1,cc8c0515,3b1e15ae,d043d2f1,40bf9dd7,29e413e1,1a59e623,3bea3be0,5713c06,b18badce,69b84693,636be68a,532adfa8,c617a773) -,S(df18b016,3ad015e8,da7e87ad,e6fa5312,d665c696,e42e466a,5e9e2a82,18337c22,532d4260,eb34306e,691f42dd,c215ffdf,2f6cf3ef,cc1363c6,46b8921,ccf277b0) -,S(405bc408,446bb0bd,49eb838a,eaadbf1b,27d413ef,a15fdec9,86e8446e,2c799391,1293bad0,ca26e4a9,f80dcdbf,1ccb70d3,fca9f403,89bcc331,e917d7e4,bf4d0b3e) -,S(1230acd2,75b02450,255fdebe,dd0ae807,38f081bc,5faaeebe,4542664b,ec57bb15,aa31d16d,b145414d,acc29c11,b0ed9fe4,fad90a7c,451d9706,4f7ec6fd,75b15703) -,S(4015c1de,3e09dc64,9ec990be,898db42d,1193e1cb,81956b08,da1c15c4,b9a2af48,d58b2d0e,553dd49f,ab07e5dc,c5a66543,b7dd351d,84375fdf,2ce1db56,8185e67c) -,S(f3da2f12,7f47b9a7,192f00a1,5576aeb0,8bc36211,7fe1246,ad61421,85f79009,865ca0c6,4aa629af,b84f761f,b26a4938,25fdec29,ce1d4a66,9dbcd138,41bb83c0) -,S(15f1e896,f7c7cc94,f3f921e7,6dc1e30c,f0d43b99,e9fa0352,42e56a4b,90a0c736,61e85195,215b864a,6f5bd52c,d0274526,dbc80af1,4395f9d1,ce60bf74,27c18b33) -,S(3fad3455,470a113a,2f773ed1,258111ff,da926643,f7fa1cf2,8e9f7b80,dfd2105b,ffbe436f,a1975bcd,ee4eae51,8dece7d0,cb34aeae,ade738d1,b39f4c6,6ca08a05) -,S(62bbb9ac,282329dc,65ae7b4f,bd15dca7,70a088e5,45850aaa,bc4c09b1,9177f92a,9c000eb7,f6104a03,51e1bd8c,d8ac8f7e,22578291,35eea222,866f2632,2573dd72) -,S(9bf86604,a46cf253,324f5608,b7bc87c8,72939597,131f12c0,eae3482d,b1935e42,e9f2dd2,15cce5af,16149d3f,1116d79,74f51267,1b575f8f,6ab6367f,fede26e9) -,S(a2ec976c,b5e72001,a25f95e,bbd7d354,2f3b174e,80ee3752,db082910,895f723,dbcb75c8,365c6248,c52a83fe,1c79d7b9,37ca8ebc,5060ba7f,60b881c1,964105d5) -,S(dd91f713,ee212c4d,f94b1fc8,c7f246b9,cd162a9c,5c8988b8,f3adff0f,fdb0aded,efd02821,c4eb853b,bb8c55ef,c54f41fe,7e53582a,230d52fa,c18a53d,ca40c81e) -,S(504e6ab0,c47fb3f4,b6b74a7b,1e67f6e8,c28ef108,62c2db35,f16f31cc,e71d423f,e7adb424,3200ab4e,71e50453,2d849315,1eae2247,50ff7a59,52bf2656,65b3ded1) -,S(1a9ea377,27fad3be,155f7ed5,1caf01ab,1d30195b,1629fba0,dd04b7af,c1a4b8c7,2140f144,e531dab2,22cd4137,921b4720,59efbd57,c1c97367,ff2083e7,f2420206) -,S(d76324e8,31920463,d5d94ce8,f9654393,89d97ba3,eb5e91ac,56898343,397b34aa,189631be,df5d46fe,fa8f60fc,a8b22fc2,ac987d23,b21ff267,560863,6ef3a72b) -,S(de87a315,50a6f146,e681d8a9,f9a7cde6,7da28c7b,5cd7a70b,703695e2,3c9bddfe,d33a05e7,77ba9e6d,155bab56,2b8cbba,27f4cc63,13038f7e,d193137f,d14b8502) -,S(d8381e05,7fbc1910,8b5a304,fa984e0c,cc0f5d27,303a3287,9ecfbf73,a1137974,1dc513d5,ac96238c,79d8f740,c855e045,e5c4e567,b3f44744,abb3bf46,ca394e8) -,S(69da86a3,b355f0d8,138bf809,79e314ab,7cb34e64,45be4842,b8f3810f,11b2ad66,7db776df,68bcac9a,c0f8f55e,8ee6a7e1,771d4148,1f5d953e,e9bf832e,cf713cfe) -,S(698f8b8,66093996,e2e357d4,d671d21b,230726a8,84079fbd,766332a5,4e7f18f3,5925e34e,dcab3458,ed959aa,3903ac93,c39b8ebd,1c562691,3f844150,d41ad20a) -,S(37274120,6cb7047d,aa97274f,b12aa8d2,e5eabca2,f3ab0b4b,daa3fd7a,3d5365df,30d36bad,c10337a2,db6c30f2,e8876226,5ccc6a1,7104460a,6f438a9d,3e8e9300) -,S(4e8c8df7,30f5d411,77355739,84a530b3,8ca4012d,3d4c8ce,f6c00689,b72cbeca,d9f7aed1,f5073c8a,8d2948d7,86ce6dd9,93a405ba,393a20a8,719287ce,797163) -,S(1e62c3c7,16e4f6ca,77b6d325,8553a5fd,59f67df,f7295115,cd6e4bb1,19b4b5aa,7df17da2,a7397df9,e314fd8b,6b03d293,ff7325e2,769d7477,ef3802a5,7d8010a0) -,S(c79f25a4,664cae13,d0971832,fee6a316,ff338f15,40c1f3e5,95c707c0,6e035db,5ef7879,c46266ca,7b342264,1594e81,5c189ce0,f057f187,e43a61fa,10330e85) -,S(768a47a3,64304a44,34b097e5,132edab2,b9840584,6e543dd4,755038da,e355cb9b,79896b63,eed7e866,32c33041,d037554e,551f2a73,6f2c2b35,4dd7d7ac,f6562344) -,S(131671bc,604d622,eea3f06f,200edb52,f7223fc9,3fc8d4e5,496af1a9,f72e56ad,5a6614d3,7985f503,2ad7a53,9b99ccf7,7c453f94,3975983c,e948dfe0,ffb867d6) -,S(3b9e6127,48d11bfc,1d2d0081,24e79a9c,604bdb94,6b25ac57,749ca6ef,302d7a58,379e7cc0,fecf689c,f905e84e,8516388f,3e1cb41a,aab8192c,aa024de0,3332cc70) -,S(4f9fdecd,10e8cc9c,f5f2573e,a2fd231f,b1313468,f516af1f,76af0eac,9ad51d76,26d6731b,71382ea2,1172142,fc5e0f5d,d0f7afa2,c9409fdc,62bced0,e8246194) -,S(25f313d7,ad044b0,538bff0a,ead5c689,d5fafec5,7cddd9a8,31b9a4f,59b848e0,f28c77b8,9202c9fe,e64c0580,75a972cc,a4839e20,42c32b66,517605d5,87470c40) -,S(24a8d407,e26c4cae,3f8dbc18,5820f345,81bf4355,7ad036a5,200b9b7a,68bb8d6e,fc6a5d96,4fa25fad,4d09a1a1,a4ec4697,818e46b0,8cdefb70,367e3453,2462b98b) -,S(ef4df8ea,5cc100e2,768aeab3,112c7ac0,6077b754,75cab97,df3ed51d,6d397f4c,fbf555d2,27eb051f,54965eb3,fac1e21b,82d216ec,807b1485,5074ee56,1ad70883) -,S(80c9d594,578f6e4,e8462dc,228cd99,9b621493,63d55cf5,80e1c524,627055e3,b6d5bf04,97b44e3a,7c7e52e3,28f63214,5eedda41,f80c44df,c7ca6d29,77436f24) -,S(35961cd1,57bc1774,40dd41b1,6a81e31e,52349a5a,e4085248,fe4a19c3,b10f7a45,b999ee7c,b32f1051,f0e7eb9d,4689fb30,fac7af1e,b410d53a,85e79f27,70a7566f) -,S(4aa49d09,32a7fc5f,77a76a12,16240142,596a82d6,6b59d388,24f0d8a1,e7f70948,adb5b12a,5e40bd0,a14c174b,13c242c6,c5f25ee0,642a6265,60d293d9,64a4671) -,S(110d8320,a9b2c5d6,5b06f0c0,cddd243d,c83cfe4f,671db970,d1213780,f6c4af0a,a97c2689,5c7b6ea,a3a02564,d2af735c,9b43ceeb,9f6f2557,3fc468b0,467b12a1) -,S(d01abcdc,a363b065,d8d2bb08,388c3545,cc8ee88e,90ee66c6,18a9f575,c0caee80,317409e4,a70e30ac,279914d7,135f9d18,e19fe520,4c83c472,5f86a614,1863b4f9) -,S(cea07679,64506753,8dc24b68,19bc3332,f320f16c,61eb7b85,96e25bc4,1499796,edff87c0,67e97ced,4aa330e4,e9dbec3f,d800934e,ed7238f7,8e97a46c,a6ad9ea3) -,S(d4463e7e,da5fcdd8,8ef0133,a5dbb1ca,c93aefb5,64581da1,3acc3871,cb94ce1f,bb1efe84,81dff341,dc7a4a8a,c2e44ca1,b071bcc3,81e7ecdf,4d4b7edb,6996547d) -,S(89cb575,5e9323b8,7771a2d0,58dc78ab,ad8bba70,6f845a8e,9a45a16e,ffbca1bb,f7e743f8,a24a6728,f8e8051f,5a303d71,f1f47059,202d332c,23f3a293,9ab97e37) -,S(d035032f,8e8e955b,b71006d5,a3b098eb,7dedb73f,a15d0d36,7e01c390,18bdea9e,1ba4cc2,fbabc437,a9d17ff4,f3c59f2d,2a416d2d,c07c0c81,c3e0a180,260bf2c0) -,S(fec9ff6a,e37da167,208b1247,b754cda4,6c6eb072,8d6b65b1,3754e2e2,eb3223e9,305400aa,27a59f3f,f19d1513,3c5a3655,464c6f39,94fd2ec4,562d7f85,fccfb767) -,S(3cfcc8e6,9e872314,5853743f,efd2802d,bb1a05dd,a03a731,77daf6ca,da9007f0,42b23158,fd0c1401,29298d42,a6cce708,743924fa,624d582a,94b682ee,4beb222e) -,S(4438bc8c,f41b7916,dfcdb038,5c9b6806,83362409,69ce8869,c294990b,cd340e45,78154e51,a4dd31d5,14885a18,b7185fc6,84c699de,2862f480,937c9697,6155ae70) -,S(d2ed1c29,faf76c12,fb15b514,6a31cc2f,c799cc4,5fb226bd,c38d3b0,176b5d52,54984b30,96d0c2ac,763654b3,32666baf,82c04562,d0d92310,cce6db16,216bb219) -,S(37f21b9c,d1243170,5ee6db23,eb578ab7,31f4b470,ab07e1e1,68e69bc7,539b170a,afdc95dd,6379244d,cbcfc811,54aa1917,e8093b54,8ec2be73,5867574a,82ec10cd) -,S(73fe29dd,54c8584a,7d25641e,c62f257d,400f013f,763c504f,f0a3ec02,d1ff8067,197ada53,ba57463e,e23b9831,ef8a6a69,d3d2f84d,c7225782,e7569603,fe1d1c83) -,S(56b27676,f0e88c45,3db1819d,36a73d03,95aae3b6,59f612a9,fe28714e,20bc73c,98660256,fb7d7d75,aca14107,dda9e7c2,28459341,ee6de72,9e463c2c,17367149) -,S(fd898f2f,e7f918a4,61f8e57e,f30380bc,5192a5d5,e1f520a0,5b99658e,8d57bf54,6861b3c3,5b0f6943,48bc4886,15eab8b1,36630618,592ac04f,80cdd632,aa63b620) -,S(fef75974,2911ca2,8057e141,6288b351,ccf2d490,634c98a7,a80153f,e9dc6929,9d5d0031,3417797a,83f0ecb5,d4f45890,d679660f,b1b19686,ffbe060e,deff716e) -,S(2c4338aa,18a27e60,d1daaa92,3d837414,f199f585,8d33b66b,471c6562,c8324bb1,13c28f36,25f2b273,8646cda3,5a2a729e,eac1de3d,80430cd1,6a0f3a9a,cb859fe7) -,S(53d6a5c1,deb56159,34416235,c2f597af,f6e10ed5,444d15c5,d9ca82b6,8e1820f8,26a5d559,cc04f53c,6b1ff3c2,4d5a62f,f63e50f4,b7c1b619,9dc54c20,628364c9) -,S(e432c338,e550a635,79ab747c,f01f3ffa,9e39d066,b221fbae,8b44429b,873decd5,297e10af,3006b09b,80d0ae19,3c1e8b3a,80ae9051,3dd9944a,444b2c7c,42d0066e) -,S(a61c5ac2,60f3048f,92cc2af1,6d3f6a4d,696e543,f044192c,9d840962,493f5cf0,1249d4f,83608025,331ab42f,bbe338b4,727a5ccf,b086aeb3,f1d9c96,26859158) -,S(a2f37e43,c3c2ffba,c45ad316,e912b586,2a9ac698,f85ea54e,98fe9a6c,e1fa038d,93e95000,6bd329ea,57397b25,71dc2e78,a466c4f8,76ace5fb,36d945b,a6e9b24c) -,S(b2257994,44c2ed2f,3114185a,6ca617b4,bf4ac15d,40d73b62,44a81852,d30260c2,fd4607f1,3d4ee761,adb6b139,3f87bf8,e8b05156,5561d650,a47efacc,5ef01dc3) -,S(d0607bf1,5317662c,73df9f40,805c9b3e,208ca1e,7fa8c04d,ab9766a2,8c7fffc2,f06da1e2,7e721799,41a9e128,e25ec992,eb030ca3,6161c02c,8ee31d22,388bd999) -,S(596aa391,d4831e61,55d80829,35a85bed,a1ea3190,a499ec6,374389cd,1bd5d8c9,cd9240b2,9845911e,47ad147e,ae55a0c8,639b994,8d72d2f2,72e89fdb,578d4ff9) -,S(433ec09e,19b7543f,a460de41,e70f63f6,6097ece6,dad9b5fb,f4030c7d,bc5862c1,dce03718,a609efe7,1858f6db,184708d1,9275ec2c,76d5e93f,e55a13e7,927cba95) -,S(343b03eb,c285418f,ad522784,f91707e4,f268451a,394e85d2,824c837e,fa48900a,e6595234,643667c4,bb885b8c,1ced3a29,a71212df,f2904549,ccb91de3,75787922) -,S(6094f67e,41b23bbf,4d594e97,b53391af,f10a978a,19244189,63814efa,ccd6488e,ea874289,dd943f7a,c109939b,8fa545f7,58359804,ad81ed0d,26cef135,cd138954) -,S(cd0c3700,bba5677c,8d0ff53d,f06bdbf5,c5adce29,64921c9f,a1591c91,ae0a375,720b88ac,9374709d,1919854c,237cc5fe,dc53b14,3897e4f,3502af17,d7510c63) -,S(d37ef1ea,95ae727e,5166dd59,bf5ee82a,1f215720,79d82e25,6369464e,d9a87cc4,59c5321a,d700c559,c92e500b,1d3a4589,15a88575,df9774e1,4bee7b2,ccf9bad8) -,S(238158e3,d58e7618,95f7a0b1,cdad8a24,3e19bfb6,d1c65929,ff08e766,e62c2b12,1f65fb1,8969ccb7,27d50e46,39c7551c,5b3f25b4,90b7d70c,cc5e4ae8,7293a0b) -,S(260a340a,5245a039,4a2f0908,f2912f0f,63ed68b6,aba66fb1,951128dc,9d542512,d30646c1,e8aabbd5,e758adbe,980715d2,b0b169c6,fe09c502,3beb7f5d,b5422be) -,S(7333eee5,d111e138,f6e0b2d,4b476ba3,6df4357d,b28c8e7d,f232c61a,6c3067bb,d427a423,a4de1e60,e8b73098,b8582e0e,18923637,c44c52ef,fa0b5f90,8ccf786) -,S(c411f215,dfb87aed,be2530c2,82a61e5b,37a0df71,1ce61fd1,25624b44,b7673eaf,ca3d89d7,d136fd46,161fdbd6,3f0b075a,afe90855,51e075d2,391f3206,382a0441) -,S(275b0a1,9dd09495,78298aa1,c4b62ff,11e715fb,6c3740fd,80d7ec03,3f2635e,30dcc412,faf3f389,c9919b6a,f96e7b28,6eb8abb4,ada80525,b9ca7eaa,f3ce74cc) -,S(9f774052,6818bbcc,b068c11c,b400eecb,da60c4dd,22353a3,4145e3e0,91f81617,a9e56fde,8f38116f,cafaea93,35ee3688,50da5107,a5a3e571,92f2bfc,1b55033) -,S(60fb35ce,f1098201,353bd7e6,89b42fc8,9f86dbc6,3eb400e5,3b8d16f6,28ae4358,1906ce1c,6a6f41a5,2f45424e,86633937,8ed56578,ffd94174,f4f85960,ee0f5c2e) -,S(1390a621,f999c3d,1737c72c,3235e542,99ce4796,d65c1ec5,45f60b71,19f4ae25,8f1cb557,b101a876,296881fd,5d30556f,55d739da,5122c0f1,43c04add,3485dbad) -,S(15f372d6,9be09ee3,8d43c453,dc488f17,42f53a7a,7923439,66946210,60f1cfcf,c6007ae8,a836a1fc,b5a4c0f5,e584fb7f,2c468d68,9efaefa,6303bd6a,beecb05d) -,S(bc2b2a76,17dd9fb9,e6d60931,ef2d5755,d33c7174,7e8e28e4,be151b42,14537d80,2582a69,b6e9b9a8,c5bb4b79,4ffeef15,96f383cd,670eb524,2ac4e7ba,375509e0) -,S(5f8e0957,61e307de,26ffd39c,92410937,5dac9c83,7a5a62f0,b0864cd8,a37f2686,d342dc84,7657354d,d524b32b,62f5f69d,5b2ecbfd,71831b28,565cae36,777534c7) -,S(5451cd91,9e849ec,b8dc75c7,9f939957,69a39234,38159544,dea98155,cb001c5c,e00d1d37,f9ec02d1,ae8222a,744381,4f16220,800f84d9,17cea9d5,9a9e2a60) -,S(737b89ae,9d9951da,d2b489bf,f2ff714b,dcfb13fd,829160c1,39875a46,7343adc7,ef9e2ab9,f8246113,726e5be3,5c1da48c,a6b4fca0,53d35dfa,8a3d826e,e48c5ced) -,S(8b80e227,9b0a91a7,6af48413,71ae6fdc,68f4f5c5,58de6efc,1ec0034a,36a26000,909b49ed,6ce8c555,25441ab5,1046956f,d25a3a73,5d979c04,43ae5891,fbd43df6) -,S(9db9379d,346cd59e,ed0c0d44,abc4baa0,3b7af170,9f034c79,151aaf54,69296780,1a8f9e50,918a104d,b525c439,bb16b64,179dc4d5,452c86fa,e87ab757,61e97031) -,S(3aa7c8c0,293e5c9d,fb50b63d,340851a3,88b1641b,b864cc08,fe776500,76f98d0d,974dde95,7c958b70,e0ff9399,d2d03da3,4dfc3437,c1ca557d,2240fdfb,3ae1d36d) -,S(26cfaf0,d27825e1,6014e5c3,19bb907b,7a3b777f,b6bc69da,5cdafec8,40d5b4b5,2eabc11,73729fdb,d31fabb1,722be99,e5b4355e,8c2b4bef,53b21dd8,3cf81ba4) -,S(ee495a13,bd1ba28d,cc26fc72,4cbfee95,3aa72852,57c883f0,cb09d6aa,1bdf3b20,b340a2f9,978013ce,8275b7cb,3fad5c1e,857bc6d7,b43782f2,1e737681,fb39b619) -,S(2e04dc81,831bb465,59d6c354,c4c6105f,41f61301,769d6006,adb290b1,b75540c9,d086cbba,4d221cc3,7cc96b20,adceff4a,6157ab9e,686d1fd5,5d56801,dcf4b779) -,S(557b5b41,b2b2e4c,598460ef,22888da0,aa2ec3a4,7980247a,e8bd465,a6e64c22,6a3c62ef,f80832ab,83a9d698,f61f7903,b7f64e41,9900950e,c7d79369,403d57b5) -,S(a0ea9ddc,e2797fbb,d384a1a,2c26d7c0,edf866f6,9addb763,dc44b112,dc1cdc5d,a085725e,d947778b,40a2baee,98dcf460,b084aeb0,3f96658,4f990895,b15e3378) -,S(1acb89f7,55a51f58,d8ed16e6,99a2294a,b2f4bff9,2fa2d1de,9883061,4ed4b5fd,5b243df,31c3bc95,79c47c57,58eef875,c18bb896,424c0293,22d729a8,b7a32a21) -,S(fbced690,b601e450,2f0ed32b,8c2ac448,31c4b327,a4ad9648,97637b08,2f3d3912,3235804b,549210ae,8cb5bdae,e5b1b474,e682cdfd,8af4acd9,8c0c19a3,cb5c017a) -,S(75339a0,82043d85,54ff592c,186a183e,4597a0ff,48f280ac,d760d134,9dfc6b5a,dbf1aaa6,8bd5db0d,8cdcfee7,de6635b4,b7877ef3,6da38418,5688fefd,dc584b18) -,S(d83caf1b,2994a763,77a2bba0,3c644e48,7f170d5,845a7d17,b8be8bb9,84b0ad1e,e479d930,6d2a405e,f0be6418,3d4f8dfc,a7f58ff,95df1e38,c92a401f,17745879) -,S(35fbbe06,39d9fc5e,d595a67f,442d7adc,ae6f566f,4641fb76,149d6c74,42af49b8,5eaf204e,6217ef53,1ab09a53,e6cf4d12,46d6c4e6,b71ae8ca,4e821474,94d00680) -,S(d5563a62,bd6fba1d,e252a5a5,9c03bdfa,6c570145,71cd1a31,bba43700,2a7c1251,2f83b6a3,2efa7b70,1b4d3262,9e7a8755,8b681d17,cff0b992,1e102b7b,f851f543) -,S(8f2a2a14,a834ec79,107153f0,ffaf8f46,5cbb46c7,5a72d07d,5e2af498,f3359b75,30ac7456,5c946e21,73bdbd9c,dc999e79,260445e0,dad2467b,97234789,a4de1184) -,S(74482ce2,45605bdf,f7d586f3,c2e343a6,8f9579f2,543f7f7,22a4b352,24361b4,b2cae040,9ae59ee9,bff4fb5a,34847ca3,e4acd880,e35e4d5a,5ce47b70,3cc565c7) -,S(ca0c158f,cd362d9e,3724bb2b,f07305a9,5adc440d,24270efa,2a8f208d,7f540295,9e1daa26,5a5effd1,29f62b,bf0f5c60,c0c2b73a,58ddbd99,c832125d,3927e7ae) -,S(9c5403ab,b8b04f47,5eb4ac6b,5d526784,8d237d3d,c36e8698,d59172c8,a9d9e268,89cd0c87,9d02beeb,ffb6dc2f,fa882711,2071cde4,ee71a7cf,669f64b7,d463fbb5) -,S(e6bf2997,5eb88332,64169169,62f49080,29072e85,797fb699,df05526c,c4ee0de9,ae9de06a,1952c472,6047bbb7,b967e6ac,db33a123,24b07165,d2caf737,3fa40068) -,S(ae4ec439,e4392deb,5e1b1565,2310d52e,9cf5c0a9,8753a95d,d7b51e1e,5889a744,1400b900,c3159d2,25ceac35,4e566d2f,4e6f057,f4664b8f,465b0f53,2ba61852) -,S(c6351ec4,27d1d6c5,64c05959,ccee21d9,b086a881,3f4d7406,ba8d0ec8,6cd139dd,b7173d5f,bec7a8da,89c4cfbc,a911687,f39a455a,9293640e,7d473bd3,ef2dba3f) -,S(fe44937d,a54556c2,a50d9538,98abc367,6da5d722,6c6d3379,20092042,d1219cbf,c5c2e2a3,174fffd5,74761486,669b0cab,5a5eb21e,be669ba,c5c5a4a8,46e404b) -,S(760dd500,b18aa066,19a3977f,ddbb6947,d092649e,485f2b6a,d26d01aa,445588a8,cac47a22,6da2825,38126d62,38751a4d,93daf13a,420be353,3fc0f7ad,db68c20) -,S(8bdd111c,e271b136,45d00636,f2d33c92,df570cbf,6bbdc156,69fd898c,ce4ea8ff,884f1430,8ab84796,d61e557d,abb4d15d,15114c0b,dc770388,6ca3ff0c,622df5ad) -,S(406c6d3e,79fed3cd,16d616e6,7fe004b5,4f589594,ecb7ca6e,24210224,c5b4eeb5,aeffee19,f82cee83,d4796668,8545f0b3,b8e61877,f34a0b23,c6a3573c,b98c9b7f) -,S(c645ea95,2580652e,8e05df6a,3d208df0,83e00eaf,50cd7d4d,a7c51458,324a41f5,8b4b9cc9,d3f00fce,332d2ae8,2874787a,6c6c8008,a7577ad5,d225f951,82e8bd2d) -,S(813cd833,dacd8916,76af5b48,5d1ff72b,df03f2ce,c7657e6d,249e79f1,f12d7476,c364d1ee,f5f1d5f2,7438c58d,ee926c18,7162cc71,383e9524,b80cbae,3cea17bb) -,S(fef2337,cf88e025,d70e2a44,e68c22bd,95371f36,14ad9009,f2ba8286,290495e5,b622fc00,8b0a0f9a,9a36ddeb,ce10d871,e5dcd7e9,65ed2784,21ab5891,6aaf7404) -,S(8505810f,22888b4c,c8bb708e,c1e4df79,a3a361d9,5ac2b259,acc18d68,e50b0952,b80fd8aa,b7196e00,3fe24ed,fc6742d3,e7b2115,967f838a,2ef00345,3dbd4d34) -,S(b7aa2500,c77effba,3e93a4e0,b09a0f52,92240fef,4282cae,4c8036ab,2e5e5561,85823a06,1fcf2328,2dde378,8802d211,fb2cda3c,316dbba,d30048be,1295d7c) -,S(6dd2e626,181f0007,6ed53763,32493f55,a77cf5,3c268524,2be805c,7da06c95,2a6a76bc,b3f96c70,78920303,c5ed3208,170fa969,6c5264e0,c3cb1d86,ca322da6) -,S(ff5181a7,ab79b40,a3afdd39,8ac729cf,e49a6a23,2fa46f9e,4ce0bdc4,696e9f9a,99c20ca8,b11b6a05,47e81074,8a34c606,140eb3c7,ce5c843f,60203249,62858aad) -,S(a5dfb758,32aa580a,790fce58,b4c04a1c,9de648f4,19ec33f0,92491275,e8243ef7,78a66f07,e1466785,edfd5523,99fd1935,1ccadfb,e3b25bf9,d5279ed4,1d0b9fd9) -,S(fc5e4688,ea6e4553,610946a7,dd3497e,a5f698b,82d6b439,6a21e082,a9aabfce,d1b32a9d,761df7cc,3d69b5be,d7aac28f,976be204,7b2aff0f,2824fb00,b70d697a) -,S(179fb126,a3cd9931,f135cbe7,2604d3bc,83cd986a,d9a7900a,17436875,d3507016,dc2a57cb,b0bd39d6,c8daf32f,fbe6b300,52cff0d3,12e84b72,c00a7d76,3578e749) -,S(af37b7e,cac16810,9c51fe45,b2d6da7c,3505c1e4,bdc88b10,5a386fcf,e30a6c1b,4dc24b79,61e9199a,f594974,32c9352b,4ca9d735,84dde4f7,a4c0127f,21cc17f1) -,S(62d66f6,b534cd8a,66236ca8,5b7de9a1,eeb49aa6,e65e5298,edd1a99f,96fb1dd1,83c05dc7,e69dcb3c,86dab3d1,153d93f3,e9861239,6e25d3f6,6a6d637,248f237e) -,S(6a40f396,1587f5ab,89280eb0,568ec9c8,6958b4d,d8a379ec,2ce2489b,7e451ece,74972d6,1100a0bf,7751a400,6093ec78,1fe16c82,baaf0e69,74142a17,a405da36) -,S(2838f8f0,c6e20e53,9ecba383,c6e07a2c,5022d436,904e5da2,b91b283e,40bbd6bb,6bbbf962,2b7c41a4,6b72a30b,d051551e,e1227362,b0664dc2,509404c2,819b4985) -,S(21e927c2,82cd4635,c9c19c00,f18ddfe8,7aa9b60f,f3000c3,2019871e,a443333a,6834c23d,e05bc59c,f6fc64a3,af61f049,7c247d86,f76a2ada,7771dd16,999febb1) -,S(d9817ec8,f88f9cef,92cf9df,1fa9099f,3f10ac61,fa641ddc,9f36e854,98822571,53c57b49,4d84c3e7,679060b7,c7c8d4ad,f2db0c4c,c8cabbc7,5c29ad15,80b963a9) -,S(6eaafe92,1994519c,1c61bbcc,c1ad6ac6,f7a2d0b4,fd88354a,6a458e78,17503e30,f29a7f85,f3e91dbd,9e011055,f47a5079,7f55fa4f,46a6b188,ea4694d5,a086b4e) -,S(2bd45f,1625722,2352b5bd,a6d8e2b8,e7d23c3,f8497fe7,348a8d59,97b5cdbb,b5f9d5a9,8ed6387a,41397e54,6b3ff76c,4c6bf446,3093e979,2d1f8748,7a6b725c) -,S(176d02ae,cf4f1313,ff804e22,326d6a13,8b641e2a,3fd4d38f,2c27a35d,f1f456de,5ac13641,d2f19a4f,77097a4e,8eaae498,2afe9494,9188e411,e03ed031,fed9eb40) -,S(6d0bfca8,6296255c,1fede5ef,8d04dad1,2b6625fd,7bc127f7,3f6b82d8,b257ca8c,3c5c434a,81c17be8,8101b5d5,ead55e60,9d9dfb10,c5ce1b41,484d5fb6,f595fc10) -,S(b67d3fe4,f6617324,a4063fc1,142ff4b8,2a605a26,8b8fa146,697db96d,570ecca8,63ed93c7,a95a0ea2,9ffd6090,5c096042,b5562997,4957f47b,2d5bca14,21114bf5) -,S(c171bc24,fd80dd05,4eb3e3a5,5f50c9a5,322989c8,a1213179,be4503d0,2fb1f1a,2ead84ac,7528e7ba,982fec81,4b68ff7f,7aecf675,281f126f,9f41a7c4,5deb2e03) -,S(c4936f57,96269373,21abb8d7,df07e4ae,48ae1f18,ee1f8ea5,6682ced8,ec911593,52ea3664,1b441154,81805582,dcddf216,80eaadf7,4fb324dc,67439b03,aaccb1b2) -,S(b0a38c84,ecc73fce,200658d3,cb43cbe8,e0df114b,5d1ff7a9,33158b67,b404dae0,40c381dd,fc600cfd,ff24d7c,988cd4ce,74c18fe,130f4248,2ced320b,b91f2ff3) -,S(1610da0b,300d59db,d8746d5e,17d71ab2,e7e9c1d,2b43b688,656e570c,60336b82,8923b2e2,fa3fd34f,eff4ad22,7f9f6638,745167d8,fb769b34,b3bb7e12,a25c892e) -,S(f6723495,10cb5b38,da909d65,333adb86,d22ed855,74d24d35,83294cfe,ac88d999,6f726bb3,891187c6,3c74392f,a1e3ffea,f55b9a9e,76e3b584,1d13dac2,e888c740) -,S(3cda21c1,d048a768,d2863f4d,1028459b,c9a91c31,2626940c,f762c074,23d85796,af05c34b,4a15e00b,b6ce97cf,501316a0,85ba33f2,cb536f27,324f5506,54a8f03a) -,S(24e1bc3c,84c0ce3f,52e1443c,1ce82330,b69bbdca,f09724d7,e616135a,d9f99c0c,61385dc5,e5c36e42,275109b7,9c22940d,3ee4c679,99802e67,3163c114,be7fb0eb) -,S(f9511548,94dc4fd6,e2907990,7da4a5d8,ffff1eba,4fe12201,a3ebadec,2620a2fa,d40669dc,1eee21c8,ee1110c2,def5de0d,4f08ca55,6758dd14,b6f3ce64,46b2fe4d) -,S(c6808c80,61dd7e3,f6fb5ae,d129d23b,c2101af0,130537d5,4bb99baa,1b8ee268,2fb3e2aa,77870909,993f9d91,bf670cf9,bcd5abfe,26ea9990,6f9805db,c8707f84) -,S(ca952b81,f79a35bc,effc9f2c,c66c9928,cda6330f,42c44f9a,3191ea5b,5f473c3c,aa53ac41,f34fee5a,2028f7fa,8ffd5106,23cf2dfc,cfe5a1f0,99ef3649,d7f846b2) -,S(679c1de6,521c29f1,9b0d3c5b,ab481e53,d01ec2ca,c719fbe4,16054bae,593c0592,61d4eff3,5daff1f,a4bb875e,bbb42722,9cc996d0,405c74d0,6ef0c6f1,31ade7c7) -,S(6f7ac468,d33618d7,8c59d849,3571abb5,1d445a43,af10fbed,c5d25b13,58170f76,9187ac46,f2076aa,5cf4de93,52e5437c,4cbd2220,d8070172,807e84c8,10a05090) -,S(f4ce85c0,86a4fb78,2f081fe5,379984c3,1a7aab89,ef9ac386,a6a8a11e,596278dc,89d6d9d6,75983a6a,d1dc4c45,a3dafc1,cf951dde,2a038261,b414eb94,f9899886) -,S(18b0b225,19360c19,739623b1,7850107c,32ca6b61,295a8161,fc9d2e1f,8d1e60d4,4d8fd58,98ba10a7,3aadae04,a9ed18a7,8c48bd94,7825f0f3,b42685e0,d391dcc9) -,S(3f75a866,537d022,f6b9b18a,330ecdc0,bdfa7aa7,5b213f4a,876705ff,635d8eb,fd0f335b,b4f41615,7ea2752,2b8aa40e,dcdcacbc,1beaa051,97ecc250,f0782cc9) -,S(58310e74,290245af,c4acb91f,20b29db0,f5195039,24b9f76f,16952141,875d0124,f79e457c,364b374b,43c8d6ee,b408cbb2,94fe8eae,c6914427,83a74757,c8b27f98) -,S(90692ace,4fd3c4cd,3c808952,d5ea0781,2192c807,4619b8aa,4274426e,feb7f6d4,3147db2e,7b3b8506,625c21bf,8803c5f4,e7250b0c,4523a6bd,e25e874f,76d1622e) -,S(154d18c9,6c441173,ba7b8d2b,5099d9d3,92ae7e0d,57419144,229697cf,52384f73,1c196518,31ad8cc5,ea72b3f0,ed0d30f,78b773a8,1f54fc37,29043a35,6fde93a5) -,S(311ebd4f,5f52bdca,290dc97c,73102ecc,421a0b07,4c53c052,11b0bfc7,3b6eb94,69d17492,eca55f53,72b04c34,6696454,ab779ddd,8c7eb07a,34c8971c,b5168019) -,S(f62a716,6976f82d,b62e48a5,1eb45464,c845b71,6436d639,a9aa0a06,feb57d0c,a0b93a32,3fc8c047,3c4198e1,5ab5f499,e3eaa4f1,4bf99a69,b3ac303f,34839448) -,S(c23e0cdd,5e39eec0,d3ad195b,19294bc4,30c11eaa,67c6e87b,a4e2a88c,60998ed4,a521d1b8,8e409682,bf7b7daf,ff45f697,6254b8ce,6c63985a,ad2d9cfa,559208fe) -,S(742ca7fa,a8b4a98f,28040f8c,15db6045,70353954,b862c223,c7979eb2,3443ebfc,251ef412,e97a7e21,292ad45e,46c40774,b97a78cc,7826e45b,cef481f4,a64b838f) -,S(622a14f9,7bd04407,63eb5d52,c15c2f3a,ae185395,e89dda70,3cc4c439,60c5592f,e5db52cb,ee60b303,69da59eb,87ce10c3,c485c239,ae1c849d,32e0e239,df4d4d46) -,S(3d6dbb7b,4e28da6,b731c67a,6c038107,c2ec325b,6b10e31d,9b7d5273,fc81e20c,f0b619ac,febe82f,8c4caf5e,6d4710b0,caf89c2e,1a20073d,66ebe05d,69fc2c9f) -,S(d450d441,bc191b5f,9c2556c5,a56d20c4,48afec13,c7e4b9be,320ddb90,b4c320e3,661be65,b5eef8e8,b357f521,d360379c,585c9e71,c27bd038,f2d63f72,6f6606af) -,S(82f9dd1e,ddb046b2,2b33bf19,2970e41f,c5df0c45,f1375133,fe1b365c,eed1ec7d,cde9eef5,554476e5,e775e829,1d38a572,1d055c4a,925c7eff,35a389b1,388e18d8) -,S(5227c547,834a79e2,d6fb0c3d,720661ac,7ec0e2ff,5a1480bf,3f31ac82,cfb2650d,dca309ff,621c591d,aea1bada,bb1be76d,2fa30a0e,1c83b4b0,d66cbd59,7612c0b2) -,S(3eac813d,7e2c8034,f1d58217,c4372a96,a1fcae27,b29ed9c4,e870034f,7faa78ba,94005cc8,7b8f7aba,143573b1,79aef942,c1519b3,9c63b58e,e420a875,7c4c8b80) -,S(9373c48b,50fb0243,b42762e,3b80994d,61986116,ba2c0677,a38daeac,7dcb21a0,295f694d,70f8295b,cddc1c76,141ed17c,a1cd8e5b,79909785,dad43e92,9247b250) -,S(14019457,db851046,42b51ece,50fb8d94,201a80e0,f29d52ad,1af35e4b,8d82c6a8,c47d97c9,df2816f9,a6147dba,7658b5da,f9588dab,8aa393c5,8f721786,9c498b9a) -,S(1b01f484,ce98064b,f60333d3,65d926fe,ee1cead3,c1497c88,8409be91,2288890b,6817b86a,86c98512,634bf90b,564ce109,13fad61f,c807a256,36a5d6aa,7f2d6005) -,S(5bad5660,f615f36f,6bb9ff3b,19c07b74,9519caab,fffd98a0,4520802c,88b6cb22,4d23780a,e6796a72,324c369b,1987465d,90540788,88987513,13dea0cd,69f90dc0) -,S(7044bd7c,29d2a7cd,d662bf16,90d5ee35,93175691,b62d68e3,f8f66ef5,8304c509,f263888d,52d74133,60ddfb1e,d1c09b9c,871d6eb1,e5833949,13d24973,5721ce12) -,S(186411c2,f90c5402,6445dc4a,4764318a,f3acd811,52c01dcf,d11d13cb,a8c02afc,462b9556,1bf18dff,8a4211d8,89f420d2,122c4ea9,7fda3d23,558b6304,d25b7aa3) -,S(62ea528c,185fd551,745c1512,6fbfd40e,5f8933de,4e1e3b95,92a93b0e,b762ec3f,276da42e,3c8a6755,6be49e00,2e42522b,e3b95e15,39a4708b,36429a94,4f6a86a3) -,S(5e2c7621,efa587ce,bd3c2392,a1b8dac8,50b15316,c42570ed,7270b521,a65d6cc0,c7faa23f,eafb70ce,723338d8,19bebd10,bae703d2,1e72b496,f2f95b6,e83d7d22) -,S(7e27207a,b80f124f,9694f143,9a0cd895,2c67a719,4075d9fd,1bb7c9a5,a22dfa3e,322b729f,e19d75f5,89749527,80f3ae04,48edf9e9,d8c24267,18812dc6,bef5e602) -,S(3de40b43,9077ea26,8d94aaa1,93e9c7cb,98e362a1,551b9b10,d5eb64ce,15986582,ba36c2b,e0f9d3d0,220eb47f,4ea66d01,59236411,2898172,8582d3c5,19576943) -,S(81e94808,7e89846e,6c7e5ad4,feb8f0da,4553e460,e3e4620,d87a206c,9d3232b,e216962e,4068a44,920e6a9e,f03efd5e,afae7f96,3497ecaa,dc741c37,7e9943b3) -,S(3056eeb0,d00a19cc,bb5a2ac7,f320ea3a,4e931187,498ec23c,daadc820,a34f49da,c6803559,271b265c,80257585,1f0a78e9,85abeaac,cb570787,f398766c,aa21fed3) -,S(9b1e1189,752fb763,7a61246a,7134145f,86b973b1,e44a5e7c,c59998a2,77ed64f2,f6793c87,9b8c380e,65296c8b,eaeb98c6,b66e0be0,d03865f4,4a09177,5dcfd332) -,S(807179ba,f1f9ce93,bb1f7dc6,e3c6514,99077419,472b9d8a,1a8cc4e2,f35c0c5,36807219,9966eb7,f18dfb7,d3316eec,54f1a9a7,7214d4fb,ce3f3ff2,935e2ced) -,S(60dd7b7c,cbcab93b,8ecfa461,8cfef03f,a74bdd47,9cb90a1,5e46ca7c,c1bafcc8,1d24d147,9987f779,90cde228,22ea0cd4,4236875d,943eda25,fa25096f,e16b8ce6) -,S(19daeb26,23383b3d,d15b0075,77a5e92f,bcedee4c,91996546,a7c52200,d243e4f8,12676559,3d67fe33,b1c01d4f,cae44be1,5f5f5e31,1149962,83ce8f92,f6485e3) -,S(f42f8e1a,813dab8,9e4db5de,27445215,c0fb1cd8,91c9a96f,ca5ae1db,14e84361,3cd2ab35,55705994,42070743,d01fe633,34819d2a,af95e97,6dbee1b4,e3ba2ae) -,S(1a2b774c,d5d0dd28,26d7c4e5,886d65b7,a219952c,6a413d2b,9fa8f765,73fe2bd8,4e2d0ecb,384a158e,e57da809,d065e39a,27830625,400c51ab,dffdf615,5d88032b) -,S(e9fa7d8,94c55075,1ad1731a,b322fab,fd3d17a,889bccc3,73e44e37,b4c2c880,67528cad,e7987d12,77c61681,36abe0c9,5dfdce09,33129f27,ffa9d36,53673bd2) -,S(5347f349,e54c301b,abcfd8cc,50f6fe6d,8fcd0fcd,861757d2,bc36cbfe,39f460b8,16d08dcc,2a837b6d,f9fe2ffa,b188a966,9d39181a,ed2aeb40,9ed17c8b,554e9d27) -,S(e20e8cea,4450bf03,149bdf60,e95f7ed3,69fd79d0,aff9fb8c,ef6e5287,830c7ddc,fa256932,fcc569e2,613bc0af,5f90263e,6db633f3,6cebfe46,4c70b043,9b886058) -,S(69132e10,b3a919a9,8a7188b3,e9afcf6c,2d53859a,5955e114,a41f1310,55ef8441,e6c339cd,ddd26e0e,ac4a1c2b,39e19cae,2d67e726,8518b750,94cb5e6c,b525d84e) -,S(11e10c95,9bd9f79d,c2819a87,e17c0de7,9105af6b,fdbe3f6b,88d198a7,106c861a,27c29227,4a3677c7,381fe385,8382ca38,d4b98e91,af4250fb,40540828,246d5c16) -,S(785934d,e1b1827a,471d7e59,2a4c3475,3054b00e,b8aae372,444b00ef,d9d894b1,7b8dd2e,a038d4e6,23f0f1f5,a2f75dbc,fe34e76f,6d106ae3,33d88a07,56dc4a60) -,S(f09c814e,8e66b8e5,930f1a49,28b28e5d,206f4108,fe99f04f,ead93096,1cc17605,469bf934,b4059a4c,4a942214,e1d86fe6,dc900426,c7d0eddb,8d89e86c,76d60f24) -,S(732901c7,26982b9f,ff1229a,3e8f7c83,2f47437b,412d0b3e,274a73e4,24ad6480,6b82e2d3,d4830086,cf416593,9b04ff7a,89b835bd,81cccd8a,7a29d47c,b70da3b7) -,S(b8369a11,d23ff4ea,99ce166a,4708ab9d,389cefed,b1843d8d,6fc11f74,7260faea,f4346c36,63ec0ab3,6ac12df7,f61e9848,c2d4cbd8,c8e6e173,2d104d0b,aecaef9) -,S(5499e409,3df85dad,411b8675,c09d0c0,c25bfefc,2afb0228,b94f834a,34ff83bb,7775c877,8fc6e8d0,519a67a8,7d2fe9c,c8abd8c1,15ae1700,ad1a94d7,925a4c78) -,S(fa5bc8e6,fa9b13e8,ad787ba1,497a6b97,5c34a64d,a0da5b5c,836bd71b,88c93740,8c919cc1,19e45de1,54f6d0d8,f22d3b51,169b3f0d,181bb40a,56213cfa,a4ad126a) -,S(a871c481,a84f4447,89ecded1,e2b1f525,9b1d4ab2,b16af331,199f89f5,730cdb0b,c478609,30b85d69,1ae45d62,7aeca01c,9f10a119,500d5d4a,c317fdd7,8de4a103) -,S(63d3be27,66d33bf8,f7a38577,aadd5d9b,234bb77f,d206b056,379e023b,ecd25616,9509d09a,6dad6da0,aa5151f8,dd8e3800,abd8a799,2276ea0d,3c958f76,498ada87) -,S(413ab945,c133d383,d70e81d3,34bda75c,be7bacf5,e49d71e3,7a884489,adb28f8f,c3d49f0d,6c65f6d6,1c9c84df,a4138076,f0168916,393612b,837c1df5,df710a02) -,S(df070f4d,ce208b39,e2614db,77c6aa32,2a50bb26,2ec7141a,b1e26835,911b85c2,b0b1f453,1815fa7,83609235,da7bec0e,f1bf2ad3,b0e71f7f,7c18de8f,83f55a3b) -,S(1ae86e7f,300efbe7,8cc933c,f8cda339,1f0f8f7e,411e6c0e,708a0d75,a1ab1815,d322b34f,f0778782,7d2da5c1,4d6bf17f,f8afc8a1,8051a724,bbd719e0,f5f31a2b) -,S(2a38dfd9,ee86308b,e0c76ca1,8dbb9ec0,fbaa86fb,51075887,9283c070,f31106a9,69cb45,94832b55,abd6b686,f67d493a,9d45e4a1,7d557723,fbbbbb83,7ab30cc4) -,S(2c6d7ab3,b1c3301d,65c79d40,583b566d,3ee39014,345a4553,a77a8e46,95b779e7,eb392dde,318bd27d,446b814e,73f9cbf1,380e38d,fed25022,bd584585,d671e470) -,S(758739e8,2aa2e25e,b1d8e027,b0e401b2,c82db2ca,549ebb9c,e1560ec4,531c5c77,d3792987,c3da2cc5,5760e52d,a19ea1b4,d0c2cce5,3f612760,bfc28414,37090975) -,S(7ef11cac,99fcb66b,71de229b,b34e82c6,e3149f85,ba1ffbf7,f22db64c,6a72588,64d7c546,28892864,1db41465,a134cfab,bc08ea64,11f5b2d5,b1de9f0f,7ae41b70) -,S(a7d48b06,c66ef847,f17b4b3d,ec40eb97,cb91bff1,c06d4a6,5d6db8c3,5561e4c7,2f22aae0,d6eb7221,d24f025d,ad1768a9,a619d6d9,db9d8e74,948d9263,3d0676f) -,S(a14d7354,1bb93625,d80f654,af67febb,d774e42b,6430a14,a907c52f,84088ab,adfe7f75,2b080bb6,89c031fe,c7c11d1a,bc303b7,f1a0ec2,38a4dac4,afbb2a5c) -,S(16076f95,b067381c,9d71cc9a,928f10db,43553332,f747e33e,367cc7ca,ffaa5f88,5c05040e,43a29d4d,e16b5e42,b672f618,8f0496ef,f307c269,13df7c79,ed2b1502) -,S(973450b4,a297ebf1,70630a71,fa74ae2c,8f3f8e39,18ff73fe,41bd1e65,5a5acd29,ba04c21f,e92ea639,99d5d87f,77181c31,ae8ed87c,dca22054,2f746fad,61f63039) -,S(aa29f7ef,d2f06187,108ab23e,16d9f3a7,74ab6459,550048cf,e1ddca0b,45fb5942,431cbd5,c77b31b4,d8b8568d,b092e721,a02d643a,75621eb6,1016b363,9728e2e8) -,S(bba61b3e,52614d14,358dc227,e0c0ea6c,e4dce364,fb7e0500,72d0d780,14642d9b,f33e0e72,6e9ee195,21fb4a80,2510156b,230a7ff,6e4c6b38,cd38b3cf,65336d6e) -,S(911443a6,979ede22,f23df6af,e4b1ab,73867dd7,a47e9268,3e3cd83f,241bfacc,a0e5be1d,31cf0375,7c2469a5,90f3493b,e43a99e2,755af9d8,b87aac67,ee7a6488) -,S(ff2126cc,5698e6c1,2da7f441,b031ea11,30132b86,23994f64,b332a8f2,87616d41,c616d5b3,79eeaae2,b072a11a,d2b316c1,b2c851d6,698b6d86,7fae1abd,482e91d4) -,S(2fe68e9d,de151731,12e1653a,2a6abce7,615062fe,a5375ef6,a2be1e90,67f6d8ed,c24e4b95,718acdfc,cd9f39f5,eca6f2fe,74fe7f9b,ae6aa352,e3651bbe,5d81c9b8) -,S(dc08aedd,90e96f6b,892ee62b,1f719619,6af44975,58d70f1e,7294863e,271ddb99,7250d846,1ac24a2e,e74bc5a7,53d5361f,8c012986,4364d84b,4afe22cf,c94aad99) -,S(e9c21052,f350d1dd,caa82594,b6eefb5b,f8f01ec4,1a423278,fba3951b,fcc7eaae,6992071d,becaac44,a5cd1537,cd066f2f,c432f198,621b70ab,360ea8d1,35757784) -,S(110d5ac,7838b9d2,d33bdf5e,8aed8529,5ceb9334,d409074f,3c26e3f9,f0cb792c,7879e339,427d8425,b597e76f,56a7a6e7,9a8cb00b,374ac98e,9cbec66a,47bceac) -,S(92982af9,ab48532f,cf2ece2c,9ab346b8,7def4729,8ebcc03b,91869aeb,42f9bbda,c6bf5a6e,8639e2ca,772e8c36,5f824b3d,331c7be9,4c13e9a8,ae6a779e,208a157e) -,S(c3f07f47,5246bb78,eac4e9cb,263c774a,3447acce,993a9707,14c1b553,79013162,f1931fa5,d6fd228a,a5781b35,45faba70,df6bca90,936acf17,f81a1155,4897e136) -,S(37640e7a,eef3f326,a598d363,df4f46dc,8f0decb5,ab6e368e,62294c53,ef3fdc7b,54fe19ac,83a074aa,796feef6,8d39358c,7be8848b,433e1eaf,9982701a,3eca7a1d) -,S(e903363b,6c90bd,2bf15176,83411d1d,aa9f0bb4,a22b5f03,ebbee32f,8f0cdf4d,fa44eae0,78b4b6fc,63abac71,ce0a6e0e,16b42d80,94179f1a,657eabd8,7eea2480) -,S(3c5fdd9f,7313d178,312bc477,849ce90b,a22770df,867a815b,2bd1d1a0,600afb6f,d81524ea,9e23ad00,bd7197ee,63457745,75795d6a,63b8b15,a19cf606,72159a05) -,S(40b540cf,43713ef5,c8b919af,6c991632,e60c198a,677887be,33b84c70,7c0ede8f,54586256,7352c824,49ebecbe,6eaae259,8e1cf694,fbb296bd,c14a4a59,240798e9) -,S(67da332f,f57adb72,8eb8b926,5a650e23,bfe5271e,396d74f3,9878c22,6f912053,91aec263,d7b74e09,b4fcffa4,87cee236,356e4fdd,bfa257c8,f3e3be0f,3a3b16f6) -,S(40cea066,fa029178,5662c994,db5b1153,e59fa121,c9133c2,fe1c6d20,91d44d98,61475cc7,a5ff5251,558f258b,aa8d69a1,52ed6497,c8ffcd55,2b66baa5,534df64c) -,S(c4eed050,248cf186,f8e2c079,870a139,c0cb13ed,2cec040e,d98a18ca,9b67ed0,50e9997e,263c7441,9e71405a,4d342e76,c5548e,1a7a3cc2,97e4e00e,91fc476c) -,S(676b60d2,14e309a6,8c7a8470,70d5bf62,8b71b7fd,322ae568,56fd4a48,9f3ee83,16e0d8d,371ad6bd,4713e9f,7c5f329c,72215cf,21a48527,35a0df71,205b733d) -,S(af268996,29117c69,c3beb193,c5cf7944,d4d3cc1b,7481d08e,1a190b45,c03e1fe7,359e17db,bdbe179c,8cb75ead,8a0e3c86,2b1d7d28,4aafd2c,e45e7b9a,c6d83ebf) -,S(62e15cc5,a30d1388,2b3c3890,4e1d11db,97b0a7b7,c658175d,e438591c,ed1ed489,fab66c6b,ab7b5ed5,815c81ca,65cf364,f4cdf8fd,7a6fe8e9,ab5ceb66,3bb4e8f5) -,S(6c7af496,df980977,41f5068,f34d0477,7da16397,c853539c,1b0c1263,2e43ccaa,4eb0e461,5c6fd9e4,3aa05201,88bb264b,d55b3a05,fc2b6c8c,d6f5f51a,4314f6b) -,S(757a45d4,4c662311,289be914,4ccca5ae,6ef89f51,52d66a2a,9be64096,cfc8fba3,732ddb9f,62fdf217,44d7daa6,35ca3e92,c3b84061,bae4c220,13339e06,fd4da7e0) -,S(14978c08,f1eaa9ce,4d878db3,29f0bc94,43301fdb,24b525e5,4f9f27d5,7fc114f9,439d8e8b,2b9fdc0d,85914620,9c883731,26e961f6,82407867,b10bdbb5,3074e5b7) -,S(3f231c93,760d9198,4a8d9adc,abd83c1b,3ae620c8,f067d103,6d1e5e02,2a72bcf9,95eb3a0,a928d3f7,dff3426d,763cf6ed,20d6df2f,c5dfb17f,c53ce0b7,90412bc7) -,S(c90268ee,75cc8e7d,7fe84298,b1db4255,80c3c45d,3643a280,e3d5d0f6,7337b616,f566fecd,1158d49c,c12a1dde,d0b1fd7d,d9cafbb6,ed3fd09b,48689f85,b01cb59) -,S(6457f0e,4d6cee8,7a2c0aee,85306a02,42c017d0,1e1c9807,5b460732,5c1d82f,67bf2f81,262de4e2,ba9d29aa,aecc9315,ff56c3ed,2e73d438,2a3dfa6d,faf9808a) -,S(ddc591c,1abcbb88,3de13bc4,490a66d5,3d96c97c,f1e21ae5,6a430c1c,39b1b629,80ae50f7,b81f043b,e3db78c4,da7b6078,871d4813,1e076ad9,de59fb27,b942f72e) -,S(22b19bf0,5efeb280,44b43bfd,7a6b3427,2e8b3c1,f6635ec8,d6966a,6667a252,47f504fb,ef2cea6c,8692d0a5,1f492560,151429c3,e522c23,2914e880,9ffdeef0) -,S(d5883bd6,c13d93ed,50371ce6,ed6c4263,395c5d28,f589c84e,cb9fbfc7,2dca651e,acde7b79,969cde2b,9a580387,d8e3a99c,45f15d38,f2e2ed79,688a3a95,80aa9a8) -,S(9615736a,4804dbbe,439f2f82,ca576623,a1675aeb,9ea9e40e,f6b910b6,c84af16b,a0967216,67f9dce6,25ce5331,62d45477,31be7427,74eeb1ec,4e3fe578,343c46be) -,S(ea36bced,959bc461,95e730f2,26224652,2472c2c5,70df6832,befa40aa,5c600e32,dd52094,82eb08c4,bc233090,2aa54333,87d06885,a9357f40,246348b4,4d97fbf9) -,S(44814860,ddf61b77,77cad443,18c21686,85c614b0,1c5830b3,b178a52,d85539bd,f3e5fd15,c71050b7,280643dd,bd2c55b9,219e7fda,cfbd2e98,94fa9a4c,9cc7ce75) -,S(814454b,cde86996,56b44c39,69bf0a8f,31b6d032,40098f9e,43d52266,cee66f49,8baf21a6,601db25f,2e18f5fe,decb9f31,9a6378c,adbff6ec,99bfa2ff,8d26b5c6) -,S(1ff790f1,11f7bbb5,b6db5f83,22ac696,c1de09d8,e50b9f4d,641ef76f,d43fdad,145d0aae,c218d6c0,219ce9c2,313b4962,f873c5c3,5424d3b,536c1543,14fa9517) -,S(275cc6c0,6a8faf20,c3c1e88b,87e27d35,661c6401,d3a1bd96,18cb016e,fdbc6d0c,45cc522e,97b61ff7,696c5780,638054cb,5e97b6d4,fc4a813c,7000a633,4e9f2a7c) -,S(9c78cd3f,874afab,23874f0c,8a84fbc8,a6d032f6,7fef6c6f,29c90513,bb6926f5,818a2406,fedf958f,7efafc4a,584ff6b1,7bae1b65,f67d1086,c3e013a2,cc318b1a) -,S(3c060395,f2cfe9f9,e3bb4afd,e5a71e03,c5a92491,323de27a,c9ebe1b,170153eb,344d08c3,8021fea2,6f55c0c5,85af3954,afda21e7,14cdedc6,8ffa3771,43b2ca27) -,S(f4b61a9f,7392b960,752bafd0,ce521e4e,57bcb898,cbb2dd9a,b0f7db8a,3ce5ff2,e412589e,f3678029,15813dfd,acfe8056,2a59894a,4c87640c,6044656c,e8998d5c) -,S(418698b7,6230acce,49505275,a0c01e9,4eb356a2,e3c242ff,470b64be,fa91ce85,cb9dfaf5,4c64ed94,f97e03d,30e07876,9e5a3142,d0fc0902,5e20ac2c,21c4ceeb) -,S(809cbcd7,91c1f309,864ca343,3d9a11dd,2db3d9c4,5350ac5b,27f55e19,b9941ce2,8161347a,92fdcb92,263f1d85,2923a15c,42d5012e,30d7d9b8,623cefa6,12b06bf2) -,S(6410c007,1d1025c9,8ce11509,5359e962,58c6a115,5e7f34fd,30fc8862,f9569f23,d76363d6,2661a55c,6c211bc4,13b1dd7d,63fa6964,a03d9461,e2870f2e,54c87d29) -,S(8394abff,22ef6051,7517e352,12a4dca,103a19ab,4091c7e8,fd417a,98fcfd2e,20d0ad3e,bc0fd15,fd405417,61bfbb40,8e37975d,a77321b,67ad2ef8,35732c0b) -,S(dbec1fa7,765386c1,d7558cb1,f19788bf,ce0e9fa4,7ca41edb,2f2d9ef8,78a04308,5d7c918e,335ef23a,934fc963,48dfd8f6,ce79885e,f4c463c5,b2645c8,48083ea0) -,S(9d6fe17f,3f53f921,893a422f,c9f675d4,652cbe09,a870c81d,8b2ab9ee,9a591cc2,fae9ccd0,b22ce7e3,2e7faed,2d47c36f,25cac5b1,e56ea936,a6811f11,8d485a2f) -,S(622f8f9d,65c4270b,1479e4d6,6f82fbc4,cf23e7a4,d09a6537,22c20d9c,54f85f55,e87650ee,4d9ac5d9,c6566612,1b6e4679,7e52953a,d7c3aedc,2fecc22f,d5b76591) -,S(cb1db853,b615cb5a,b92d0340,7ad7891f,2e7b1d4d,120ba3fd,a1ea3565,ee1d1436,8362a39d,9d425eae,2451d601,27ac2824,3819da08,856d0db2,18f339d6,fcf20046) -,S(5cbc6a63,59d9d6a5,2ceb093f,ca5cae,f32892f7,c9d04091,8245d9ae,ebd594cc,c4c18f88,7436575f,39b9e7c3,27c4efdc,6a3490b1,23c50743,ef03b1bc,34566bd) -,S(37a3cb08,3a9b7561,78ff2128,e7a5b9a1,19577af6,61974869,cf555dac,ee2d11d8,1a8a6297,4d0b6c5a,12155e9b,cf895c95,f6fd2b1a,2776c32,8d6b56f8,32f114ca) -,S(8e0611d7,ae0914d0,5d39e06b,9b359400,f21c3beb,73ede92d,bcaa6d96,8a995b95,ddd4f522,d1c6a964,9629727f,52740664,43e80ac9,7d9c68e1,225e60c5,38129bd7) -,S(9ec34a91,8a4648f0,1c1d726b,51b1874f,36410180,8bee25ac,c159c251,fc115510,bc5ee2aa,b5e43b01,b34ab989,5f4cd71d,1d3e6288,915daa2,e84ed531,4b388b8b) -,S(dc19ec7d,c901e215,f6d0603e,bb5494ca,aa9b5409,67a5a339,8915c4cd,84000654,b55b9596,a18e53c4,b82c669b,92defe5f,bb5e58b0,3cd227b6,3b439b4,ef13bf13) -,S(51bc3804,bda51e9,d0c45087,13599f12,b9a8599d,6e8ce949,5a3f595c,7d38dc8f,ef0d6522,fe3a3c4e,64ee1092,b9ae8f6,e7847bf,94044693,a3ac7cf0,f4aaa37) -,S(13463b32,dff393d3,dfddbe3f,bd6ade13,190e0bb5,83e3f126,344b5e01,3105e234,ea3df1a8,b8270f70,24910f40,a519cef4,9944fcf4,d82a4300,63b2026f,8f019ff4) -,S(c49b3261,2e286adb,606686d9,67dbf4b9,57819dac,9bb75f44,8f1416ec,f900fa5f,ffe45b6d,8c19de7e,c08256e2,96667d89,f290f5d2,25a9e380,c106972d,79551b1f) -,S(10fe7aff,36a8f4ef,79e2d8ac,619ca92e,2300878b,cf21a271,70f89e9b,6294dd28,f67da70f,623fe6fd,2c7113eb,fe6458fe,d0d5471,ab639050,685a0fd9,33afd6a3) -,S(d56037f6,efec78c6,e31e633c,570c5e46,96f96276,b86d0b89,e993f014,53592300,2499b92,4fd99b5e,a56f9649,bd8e53c4,b2f20dab,9fc1de83,dc199022,1f606b37) -,S(a3c1d0c8,939cd4b7,5cce8ce2,f3be0226,589fb32e,55457fde,8e700a77,a60bf003,b9054f66,bf6450cb,782533b9,33190084,d6f5944f,cf4e06f,de72d483,144c941c) -,S(85d0c4ca,e1cfe42f,b5f73f31,42e97e6b,c0855f7e,db19b1a,8668e413,4efcd249,d8372bc,937fa754,b81631aa,33a8ecbc,a25f86d3,d5e0627,d6964ee,5c08e68b) -,S(3092eae2,d41d0ccc,10af9d81,fe8c80f6,9ae27c9b,74b5f696,7a69211c,8d6ef98d,153f0882,f6b720bc,c8ae5924,923e0608,d6163c3b,32d36742,68718d6,e7f35e4e) -,S(4aeb6ac7,fe874a0f,1c24681d,884d5497,3486f293,9b01ebd9,74c34ea3,429be71a,d7077161,c508a7d9,63006566,f652afdd,df87d0b2,8daf3fba,21f206ec,a94a53e4) -,S(729bb0f7,be975284,a68363ef,40003a6e,c770fa4,5d6e6b99,ab0c5042,da563f32,1e0435d5,ea85370a,7293396b,407da43f,c540aa04,24f21de6,a002f555,cccd4480) -,S(96164ac5,1074dce1,3b973689,a39b6795,9bf5756c,4de94829,66bbdd23,9e665fdd,5cf13b8f,56c92710,80c11626,6bce26c2,14a39237,9aa68ed1,b7a05d65,7bbea247) -,S(6d45d79d,9297bb8a,326b889,391b18d7,31af609c,67b31be2,9b4273cc,405e3f80,2d99909a,7b6969fe,148111fa,1b9c9326,97fb465,494a8225,a6c62626,555ed02a) -,S(70091076,b5b81f33,42170f0,4881c941,d2fe9b0e,ff156221,66f0c92b,4f9e8e71,7c676c5a,4fb434d6,58f635a8,20b454f3,4c9795e8,b8860d27,4d0fecbc,ce7824a2) -,S(d04c0a77,c8fcb3a9,a02df253,b8819853,63dd47ca,bc1f8881,88d5e56,87a7db74,302d1b96,c35a2626,22bbc6e2,841b5cf8,efb77374,af428f9e,d69b2b11,6993db09) -,S(3c93d2bb,7ee61cb0,7a25ef65,f3e22eda,6e74d2eb,f3ede111,b4f2a28b,b4f206d5,65ed4db2,b1647b39,7225741e,241310e6,7a47f0ee,4f459ab1,3d29689e,cef70336) -,S(8efd5a54,a4c7567f,bd971cce,7ce3006e,3524dd81,cb7a4ee1,a5c61e12,62961037,6b9688d7,d73db9a7,1410738c,80430ea6,ea329145,718b4177,71e542a6,93b494cf) -,S(e7aa8121,34fa1f75,efd2ff02,273becca,18bf1ea9,47d168e2,cadd6e9a,6c448425,8af9da38,e2471dad,128e004a,d7b03932,2976d84b,7c91f91a,af471546,dfa5acdd) -,S(e4335a32,b3218d51,9c582689,85138591,4b7cd8fd,4e4eabc3,b5f9e0b4,c3212b84,ccfbfb0f,50b5fe75,c849510a,bac5870c,3016573a,53eda160,b14602c2,42ca02c7) -,S(aeff696f,e98cf587,745adbee,3fca1ae2,3f8f5768,56bbad5f,4a26afe,904a17c4,55dfb880,250b9a5b,7eb971a1,fbe0cd6,ad2d375b,88d98e52,6afcafeb,7ac4617) -,S(72fdb2e1,eb120244,4b20bd6d,afd6d49f,46a56f25,63e679c5,2de98cb5,bc999a5d,e29f2,34ad3637,7b4a9cf6,c307b8a3,a779cc22,ae472aac,eb519c10,8137162d) -,S(eda9f183,f89750bc,8c12ce7a,fee54145,42edd9ae,9fefd508,ab588bf1,6c7da0e3,a9328c5,81b0cb02,fc09fcfd,2a57d2c8,fa313ef5,4e205902,9bcf0846,811be308) -,S(744683c1,2a0150be,1d7655e,b5a3fc97,4303387b,e53bcdeb,41dfbabf,ff12f6be,df2e4b05,a459aa27,2d3de8dd,4c211dec,e35eb798,67050285,57dd53e3,5b9950f6) -,S(9f3cabfc,106653e4,65daeb52,e86d99ff,e3ac6df4,5eef90f0,61226cc0,32592ef5,9f20d174,1b78c8ec,d7425d19,fc0a4c9b,1f1cac8d,b97514b5,8585901c,41862306) -,S(9dc15715,9f59c338,d56a7d9d,ce63579e,9e95424d,e6db6927,418b024f,ed95936a,278716bc,3e131fa4,75b9ac00,6e868d88,ce17e6ba,d7ecd202,33fbba0,fb34f0f9) -,S(b6c91d90,b1bf3b46,4b526186,69e1c118,dcf8d6f9,c8ca7473,5a361a28,b53c823e,15132dc7,69e59b7b,fe5e9966,1b82e47b,3ee4c3a3,1c0b8201,517dc567,ff90a4bd) -,S(56604a9,ab972c4a,f18d5f8a,d5cb6d94,2d0c841,a7defd1b,b94b1b25,c31df400,3d2f2a27,adc2eb70,336b4b44,5229e09,a74a113a,f1b21bd9,1e3f2351,15f6a85b) -,S(a5b57de,fcd3016a,917ababf,171c3c31,ed62957b,cd8d233d,c551fd9,6216561d,3731d822,155afc28,8bd7ed39,30c3f6e3,58a46f5d,d9fb3ed2,6d7c7da2,a8dee233) -,S(da179b61,81e27ecd,d545af40,ea5967ab,7c0ea9ad,68a8c0e7,4d4a5aa6,4aafa549,c5c97c42,e74f4991,55191cf3,3118f05e,19633eac,ff5ea8d0,7ec866a0,7fbbef29) -,S(42a0e864,1b594b98,90357e4e,8c32422a,19f368e8,190170bc,6d8abca0,9cf12f1a,bac7a5e5,baf7ddf4,934aaeb9,5078e0a9,c449de0a,cb932b13,a93f474f,52312d85) -,S(74c85e38,944e2003,435bf345,124656a,6a409bdf,fd1c16dd,d1246d45,cadcaaf7,bc18315d,caf237d5,5f3ffc65,41bf9ca9,f39af9f0,cdde6fab,f602e888,dc51bb7a) -,S(8ceda42,698e5995,40091f6d,f50388e2,7c229b0e,76e7def7,f8986b6c,af975e79,a8915f5e,7c524e55,5743c392,2b31c426,71fa938f,84679389,b3738af7,59e92430) -,S(f44e2dd3,ffe43da2,66fbaa1,990d1f19,e3e4e44f,bb565ec8,74af57d5,feeac498,c307b3c1,a90da318,bf928a1a,a8894080,29874639,ece7700d,4f4dddee,d005f6f3) -,S(7e30bb38,c9a603f9,d5fe78f7,453d1c81,30c140b2,1ad7706b,601d6b77,5c703984,49c9de1d,1d057fa6,b135ebdc,f0b5ad9c,f9f51cef,95a4cb7c,ebc11d4a,3bbb6d7) -,S(8e1e53c7,4f7e1595,b4a5f7b4,5b324f0e,435473b0,a61cdd8b,1607c0ef,d11e3c56,584781c3,ae8a8beb,f6cd1bb8,3938fb12,35994977,2d1facc4,240fa43,7bc241d2) -,S(63d0cd75,54bf2c18,bb180269,2d19b4a5,4acd77c,d2eccb7f,360dfd5d,4b9f22bf,ed79b7af,eee5ec82,e498ebeb,467380b6,1369802c,3dd995ae,c844d3d2,91ddd756) -,S(feef5d30,b382dd6d,a0ec0d81,b18ae45a,8dbe12c3,dd695648,cea27c14,7d075be4,20ba81b6,b48ebc6,b185d6bb,2fb7bea5,c6a011a1,24f49550,415eb8f3,cde3aec7) -,S(21bb575f,db07a152,5ff0a7a2,d7d2c189,742df276,9306bc7a,30c2c3df,f2125b94,8ea74299,b7b40a93,3db6afb6,6577ce64,dd10d24a,89bc3907,1f656f5a,71c56953) -,S(dee2dc59,44cad7f2,310afc94,403067fc,5c1c3d2a,dde88ae0,55ba8bec,d6e5cb08,606542e4,5301a6ac,86c5c794,444006d,d77e2bda,11c8af0,6d883689,7a6b6dd7) -,S(4768a2e4,98ca0472,67cef4b4,18e6398c,81289c73,e617a2e8,ca021155,edc576d8,f8c574bf,beea93d7,1a2a331b,cee494f3,75c1bc3b,ea918106,9f1665fd,589dbc3a) -,S(53d75697,160c2b90,aaea7f95,ad24bd66,b5fd7681,f2802bef,d2a71080,74f66b40,4b04d94b,416a8098,144dccab,bcd8742b,13e85b2e,ec8817c7,7b7e5821,2e8b56c0) -,S(832f268d,ad5f3bb2,dafef9dc,f94bacec,b369d4a1,ffbdfdae,bd4fcd9d,77404e99,a6495805,c9b439b3,26e32f78,8b06765e,8d984a37,86ccb4e3,88b36bfc,c9cc582b) -,S(657acf28,15b8cc12,83265bcc,9c826be2,c6d5329b,351fee50,2ed96f4f,bb1a6333,171a0a97,b2809b24,a89b337a,cbeab96e,7d1d850d,dc577a10,ef3c757a,9c2da9fe) -,S(7e3d0a00,a3378c89,741184cf,36e41bb8,758fd131,eccd970,638f60d9,31b8348b,6f2cc777,31f94565,2a3b4c42,29be627e,bb70d5c1,67648d16,df5470f8,90512517) -,S(649a30aa,4fac6630,c7bab764,19f9a34c,6676f17c,2458fb1d,ac48317a,734242cc,fb3f07e2,5737d6b1,a28b074b,880db818,c9623c12,80268b02,dad90da1,c8d246d6) -,S(6b65264f,537fa580,9d21588,fd86b246,4d1818e1,ec7fc43b,94af9211,c835c986,537365ae,4e61460d,c2c1caf0,62ac870c,9536d8b9,436a0ef0,dee6a39e,2bf25611) -,S(dc1a5599,d5cba6b0,2d692eac,304b642b,db32afe2,59e2e8fc,3bdc8f40,72c66c51,bd18d5f8,f99c6070,b7bc06af,568e28b9,2b39dc31,ad49a842,4bff4a55,d11ff42e) -,S(726d39f4,86401794,9e7a5498,8e8fbb53,b8b13ec1,cd5fa3c2,88f0d933,894e193d,f23e9fc5,68c9e0cc,b258dba2,58b3dd65,7aca0dd4,d9cb7bf,274e62d4,f65543aa) -,S(78d76006,857c2f36,889c14ee,90a8f993,79c1e0f3,5344cafd,592c961f,75aa8ee5,76dfacfc,994f3985,70d98c75,4f5e6d00,ae3ed428,49cb75d1,580e81f6,3d7427c5) -,S(d69c3e30,88874c19,71bf077c,89247826,b464d3d5,292196f,88ef0ad6,892375a9,cc7b98de,86017934,c472bc7b,e56f14c8,7494cf5,6f2791a5,d3132c07,26315cf5) -,S(9b4022c,907c4aa6,87631f88,8d47bde4,faeab1c9,23e125f9,280dcf86,7920ae84,c7468b6a,a7b4db67,a9b4a23e,11fff527,19e454ee,65ed88eb,3b89e231,e504c284) -,S(e638a253,84e985a3,5dca200a,5e3786de,52617824,7ed0c9f7,9c9d598b,8bcf8447,69211bb0,be8fcd6f,cdb0ebdd,a8782be8,a47d8852,7bb74b3c,d98c41d5,6aae614c) -,S(e46758ab,e2838a28,42baafad,12376137,7cf72960,d6a93105,3270330a,203134b4,2c7ca1c4,73d0c3a5,8f5ca754,6604ac75,8c460c82,64f5ab4c,832893c3,fcbfc7c) -,S(c8c8083c,3bd1b84,9b9402bb,9472263e,37e7d2bc,53a77b4c,b0ae9b3d,bc70342a,9085d285,6ebd4446,127ab4c2,fe7e5c84,d5c5c114,8ee76a1c,da72933,9ca6578d) -,S(cf21f3d5,75f194a9,3133a382,514ca64a,f998b099,eb307655,46e2959,f71f838f,657df357,aa09b443,c4763432,45d3eae,4fedfd1f,7fa86896,2ffc5174,d61fc4ba) -,S(684aa68,d4aabda9,65adbb29,1056db00,1c41b900,e11770c,c77c687d,ebcd702f,c6f0c4bd,f6f6193b,928d81b2,812c4303,7e6b90eb,598a50b0,742dd21,8d82bf3f) -,S(b9a4ef5c,acf4a82,77b81803,6bcf2672,945ec080,e16e8c3b,19f7b612,c408c884,1cca67ba,9e98e737,b4a55145,7f254d4f,5d793d4e,22b81b35,f4ab48d0,92b9c745) -,S(ff439f87,d4784ca7,490da489,e2757106,e59836ba,f3fe2e4d,f6700c08,cdb2327e,98f21471,84659fa9,a9cdb709,f894236f,18ecdac9,f5834dfb,b91a7bf5,8edb7461) -,S(e1750c62,9c35027a,c1a5f1aa,c9fb4076,badfd925,f5915b11,a267672b,15945ed8,e17610ce,a0b8d837,d1038d7d,9300edfb,5832fa84,c4e630f5,2b01ac64,a79c0e17) -,S(2b7057dc,1c59ed7c,e64f187b,86adbbb7,1d228e5d,eea347c,75c73d2d,a73b3a28,1b136a49,713b433f,f2c79de6,77b5a322,8003e614,2b845470,5ce884ba,329e20a1) -,S(711c07c9,ae61ac68,f1041b58,c0f2ed07,1106c2b1,bc47e104,527d540f,53690434,e9199a45,2f5a3a39,9506473f,be6bb46a,3105aa70,2c517051,7b4c810a,5a194c09) -,S(54dc7650,68c38627,4619d9a1,faadc0d8,c2ad8296,dd0d00a5,f2e53c5e,1a1a0d4b,2e9b7179,3af2f752,c111fd71,c00f4bd0,8fa646a0,428b4813,885d4e4b,ab7e3fd9) -,S(9c5aecba,3f8b3507,db7cc231,c2c1674c,3c3e27be,84757fc,4f1521f9,c3d9323c,413455e1,9e157ddd,17f51c1e,618dd726,d300c023,f0a0d24b,518c93e3,f2954630) -,S(c22c2972,5f67e23,a369342d,9a4e1f6d,dc1bf6f5,88d63086,fb54718c,f5183a,a26ca30b,d97ad611,4ea4ece4,cfdd3928,23c02838,9723d53f,32c3b38,320eb707) -,S(8f87ac94,a29dd2c9,d37aa130,f8b4e67b,da595ca,a22803d1,e2d8cd4,eba4f2a9,551fab10,16227763,6d7ad2c,bb055439,21743078,e02fe0e1,b7dffd6,8749b04) -,S(bc486976,76c0f638,a116bcce,d7ee781b,876ef486,111fd680,4dedb176,8125dbd8,16d7c6d0,19708ccb,510ddcd8,698c2fdd,bc6978b8,7b0639d7,a1c8ec6e,ee3ea383) -,S(5a6ec844,201d9b39,92a46fe5,ad4f05db,6e8cf251,24ecae84,3a28da7d,46e75ae8,9e1538ef,f27344ae,8f9c1049,c12b49d0,2d5341fe,33652a8a,9f2eb512,c74ef224) -,S(dd6b2c56,b13f0ab5,4e0a75ec,526219e1,4d43ad78,7deae379,1dfb387c,541f4d6f,7379c5ff,1b793b97,c8acba99,97a3c079,f1c147a0,f63a2ec1,a0a771fb,fc3d432b) -,S(74e27534,4d7d8cab,e4995d08,6d61d27e,942e2514,3c6e3040,8402a5ff,12a63ebb,7b5914d7,fefb7b3d,2fdeb49,359878b8,355eecef,65ac589b,dd31ccb4,c270d854) -,S(bea186e4,b5e3663a,fb00230e,d8ac1660,67b022b9,b69b6e75,aaecb88d,d750d34d,35807d83,5b75e3ae,670bf35c,d415d37,6fbc86e7,4f99afbd,c60a0b46,9153a0d7) -,S(17ef6838,a07f65f7,cc094d4f,77743c6b,fde12ae3,b81625c,23826228,650f30f0,9d696a8e,a5356fa2,10626ce2,cf312fb7,198b0937,493c9dde,4711dba1,333eba5c) -,S(b3e1bfcb,38c89fac,af3baf39,80b21e47,d6465473,c9d6a29c,8a08cb18,141bcb7,aa33ab83,2a9d4eaf,2a50f9f8,ba55d0b,c5e3b120,69a8330c,23120928,5f6b90) -,S(689d499d,c754f099,83372631,2f307f0d,807f4f6,d67df40a,318aadd5,5776202a,dd4f9012,8a19dfbd,8f5f96ed,df2c7d79,d451f84f,fa63b1a5,9845f84b,759377eb) -,S(4bfb2e58,9df27505,91a73a4c,6ce88397,a2f68f6e,8f866e1f,d3af9df1,f3c96bb4,a9d94c07,29948553,6433f0ec,b4618d1d,af309c6b,73fa4749,aa949e6f,bdc24b7e) -,S(97a3004f,26461f5f,b6cbbca3,13eecbe7,5026d958,a1804c34,6e661722,c67f91d,8b8e9bfd,b9b704d5,13bb5a50,a725bae2,c7ceb6a1,ffcf8c49,8e87c6ff,e47844f9) -,S(a07a76e2,48f87384,48e607ee,7f30aed1,db657b9f,b159ac9a,3d38e8ad,61050c28,7d7749b7,aa6dcd68,931c3c0d,87eb73d9,6bd5f43a,b633e7b8,f77406a9,23fdd47f) -,S(9bcff8ce,3a280998,fe077cb7,a6e4854c,4c834e21,af118937,9a133986,320b8e25,da3214eb,5cfea248,f1f8a1c1,e8b0dfcd,4171b2fa,5e133854,84a6c99b,215c9ca1) -,S(8f1d2dd,bab8242e,fad20574,c0f28976,d2e98df7,5e144d27,e558b9c9,8d75a036,8bd117cb,294db5d6,a39097e9,8976c701,1042af41,680637d1,c8a1d56d,30800bab) -,S(73910449,2a44d0fa,d27b97b8,df75ca46,caefe44c,741848f5,36b78986,8d966991,d31b7807,e1db48a3,380608e6,5f865cf4,445c47f6,c6094819,da2450e4,6b78168b) -,S(e024cfa9,4fdae1e1,2895590f,222b167d,8a41a87b,b1a6b720,61ccac0c,4caf9dc3,d62f1129,cd84f36f,bd1b9439,6f5ce037,fbdafe41,fbebd066,110549fd,50b0ba05) -,S(a378ab39,e3dce826,6805bcec,b8123eb3,ffada53d,883c752e,e46ce4f8,5bf093fc,db9d124e,4c0a8d1f,14cfc406,4498a7a6,513261f3,300ebe0,99a41f0e,701c7dd3) -,S(bea5d211,b808e4bc,5aaa1a96,a9b8842b,5204b60e,24d5e518,4b4e92aa,12d8968f,caf8b92f,87c4b8fc,4692efb,889ccd64,610fd604,b9669dca,e033ae9a,453bbca9) -,S(7ec06291,40b6bfd4,cc4bd45a,8a953fc2,653d73c5,d366b5e8,b732dd8d,5d30428,e96c9515,da8dfae3,a2f4e01f,f02ebad9,8499a318,8905c0f0,fcbcbb58,87360a08) -,S(9f9698a7,6ccc8bc5,31dcd9a5,b21f3f8c,9d143194,8902312c,b5ab89cf,554c3b26,e08acb08,2ab0eb8f,fc31f7a3,1ca8dfbc,d4b1863e,29d155f,4abb8d54,6c59a221) -,S(ad955b37,a45f2bfa,1779e8c8,e6786af0,dc49dc9d,d692281c,da10b25d,7517214f,b2048fe,ee71c152,8c8f5dbb,cedde340,284af2c7,71ee86e1,8d565285,5de918ef) -,S(e7e56815,9412123b,7737b006,f48b3f32,513023a0,70c595af,1749c564,8222e21d,3ff11313,c2992218,cb3a1c01,e333f2fc,ffdd05a0,c381f8e2,24de6add,85aad0b0) -,S(4afab50b,55c2a433,488adadc,ca5d11,2e225f81,9ab817bb,116109ce,71dd3439,d232e25a,e5a8f6d5,68344997,442bdc54,de9cc597,cc474555,5f64cbfb,6252808d) -,S(2f739ca4,6559727c,cc2fdfa7,c66da19,b7d2660f,cc63b74,155057be,d55313bb,c39350a6,10a844f,80730a2f,27bbee8b,a06d7ae4,a279f490,f975111f,eada018b) -,S(f3596671,79f9343b,bc3238e7,bab4686b,5b7aaadc,95848f20,52adfc33,d15a990e,8b5759c8,e0bfb8ff,e298e824,ef18c042,65d7f886,1af8252f,8c9d9d92,c1822849) -,S(b3feced5,8d79e1c4,d0a210dc,de416353,404f533f,5a1295bd,4d888d59,b43725c3,b07089f0,871f7c3e,440ea905,cebf66de,52c68c04,a6aae237,e23c3272,26d99826) -,S(85c74622,bb28186b,5f1bffc9,74d51ea1,8bd7e6f9,1a02285d,6d8818df,b87d2f9c,8eb95100,63263c67,976fda8a,18910459,df0755b9,307e4145,cfdd18,15b799ff) -,S(3823d01,5b240e83,44c936a,c9a5f7f0,fbbe3059,1c20f39c,ca51be63,98ea7a7d,6e6539ac,8f404753,dda08dbe,f7ad4e48,69a67a93,f0efd0b7,b53c14be,130435fb) -,S(b73ae7aa,e97af1d1,b6ae34b5,f6188c62,33ac811e,1ce5818a,a9f20703,7deaa539,cf495bd7,2df163b1,f6908b7,23042bf1,137a325f,bb8ebd78,c0d12086,e7b76005) -,S(f6724463,faac9880,41dc4918,5e27b97e,889e74a1,81f35b58,2601328b,143688a2,a290e04a,f10a477c,7c0269ff,42285277,f1faced9,eff88272,45f2d069,58897554) -,S(9eff8038,1d546c1e,e1b5d562,947f3a98,427e17f4,84d0007f,eebd71c8,261ff959,bca422aa,d4748c66,6aa99f76,eb8e75b8,55f89b0,917ec29f,401caf83,cec111c9) -,S(93384df7,33d0fece,931587d3,410f2520,6bbbd992,5e6fce75,5432252d,8bc1bcc5,9e3beba1,b9a92647,c630cb4a,69b9bbf,80e301be,fb8eeafb,fa0021c3,ae27c38c) -,S(ca85653f,975882c3,71902d14,6f50b3ec,1dfe1fa4,b6e6d5a9,e5068685,632074bf,a64fdea1,66808f60,736f7d84,850f841f,588879e9,5d1adcf8,ccbdc4bf,4f743bba) -,S(b80a52f6,951aa063,1094a2e2,866d3a29,b95cf239,48753ea5,cf5c6f6e,8e082f90,61c95d57,d6fc3ca7,5f92771,61ca211,1f20a67,9a85f4f,2b8b0fbd,494d55dd) -,S(3d5d3037,3a97dd67,fe45b273,2ce21e19,b29587dd,301f3dd9,b411432,e642a3c8,5c8e3a19,896ef1a5,5cf1ad28,41e47dd6,1f207f22,3388c6aa,23d011d8,fd95929a) -,S(b274f8ca,29a87fe2,8a3a1269,ddc35b5b,44f9e4d9,81af118a,187a7c36,acb155c8,410d9c55,bc34c21a,6368155b,c282e449,c5317dd1,c4e5758e,27493fa0,4f028ea8) -,S(f1557792,8cac518,66f59814,a70c14f7,beeaefa5,33d3b535,df19d31b,ce1cacf8,113dbebd,9fef9cfb,93b5606a,e4b48aca,5b7e9c00,a59832e9,6865282b,80b70ecb) -,S(fbe3f262,18fcb657,7fe56753,42765926,59ff099e,f36252f4,cb5af101,622c40e6,4c872d52,f1202df3,e905a0d,3f9c89f,b347723c,99b1b273,8f3dbb83,df0fa2ff) -,S(ef7d13fa,25ef46c5,3663eddb,a677f6e3,b24c7e7c,6895e731,2c6993da,3d9384a2,cda2cc35,114e06d2,1f6f896,666c16db,78fef74d,2ee46fb6,a4a34e09,8546935f) -,S(8e34b93e,afb7f027,cdf8696f,a6407213,91860119,cae17b66,d4f16175,fd7118cc,3198f5fa,27ee190a,e56813e,910d917e,3bb8c850,20b0376e,e55e88ea,eb56397b) -,S(a8291a3b,8e544240,a0f0dcaf,6369b2cd,98ab80bb,4dcbc2fe,e023cea,1fa52399,f8305f7a,b1993569,82b8f2a0,1fa0e808,46a506ef,5cf0ccf4,fcba9211,284e15a8) -,S(bd36854f,90dcd6ac,978c2545,7800489,35c4cca,79a0f9b6,bf461da6,5522c88e,631a3d75,7c05e2cf,4a445b22,73cf663a,332610a,8461dff3,846503fa,12e65ae2) -,S(fad86e9a,ae78aaf2,e55e93f4,b8ee049c,73b86524,e942ab93,f05f9dfe,8b783116,657988b7,20822c63,dadaef15,a5cb3d49,be52946d,53b62ed7,1814ef3,b5aa4b7c) -,S(e1235938,db5e1f30,fa0b4d4e,a9e1925c,6308917c,23efde51,47fb818d,a39bcb2,7641244a,7384acbc,3133fd6e,9ed61af4,40e3b951,751f9d0c,384328f8,b87bb2bb) -,S(40ec62d9,7c9bf05a,cd4bd50c,137cb143,8e3331ac,554098a,57b6a92,afb137da,8b1468fa,f334dcfd,5a43d405,aacd3f31,7e868af2,73498367,4d0e5a06,67186a8e) -,S(f6f5c9e1,c7d94d25,9abe1a8d,745dabfe,59e911cb,c917fefc,e2da2a63,cacb26a0,7f2454a8,550b385e,f49c26fe,bac89a9f,33bd6c9c,2eb05c98,4303a16,6b21ca51) -,S(be4dd8db,c703a834,9e24773a,acefd0d5,70dd2ec,ef07bc70,ea8156bf,d5b516ab,46a7dc2,5d56052e,dc64a0d1,b414da49,dbb218d8,5abe14e5,c753eaa3,84b958ee) -,S(273f227d,448ee218,1e43f2a9,89d5942,54eae85e,54fe9f76,fb67ce81,169e1be1,67cf461a,a6c7ac60,1ccdd925,b4b38e84,1998cbec,cabf9441,29575438,a855f35f) -,S(94ca507b,96c063b5,bfa9d74a,c92e656e,db186570,9a017ce0,e5270bfc,8a8c4a31,98daf409,49c48c6b,8c674361,17aeb669,36c76169,8d39eda8,9922490b,4fa6a25d) -,S(91d6f747,c1c7e012,440cf7c1,34ba64f8,9ef67b54,3a57196b,d2bd6ae8,f5ef4356,e2117eb0,4d4d29cb,5b13f628,f69e5eaf,2befc095,2fa361fd,f757430a,168c19d6) -,S(8e2c4d62,c17835b0,97ba07b,37947515,e710e825,15bc614,75a66ed2,ac4cfb84,7b7f7e56,22bbca12,2863c230,5271ad25,b5e4195f,cb96e5a5,ca2be6d5,273d6532) -,S(55738482,d32c4248,1bb0d1a0,666adab3,8bd2441b,9436b690,77925e15,2d8c948f,93a6705b,ba5e5b36,e73fe83e,e0ea81b,3de393c9,1c209e89,af90c539,9af5ea2d) -,S(7faa0f45,45fa7d68,918396f6,19beb941,43d93f86,c5a26539,5016d386,b3e85086,cde251a8,3de1f2c7,11b884b5,33226baf,cac36791,1ff30e19,25f499ef,27da9c06) -,S(61a766a7,7bf6f8f3,a07ed7c6,6648606c,69134c6f,4ab4931,9033f9a5,e8b7d191,7dfa24d7,6bba181d,7bd77606,c73b1635,46f41751,c05c34dc,ec54773b,4abea4a) -,S(64317c72,4f1207dd,a6009736,6fd2d189,8b702e71,8cf84fcc,7c50427d,7eee171,d1d45f23,b1c5fda9,ee05652,dd30f898,c75923d8,293d6eb4,18a0e892,ae400895) -,S(4c328f82,5923e7c8,9cdba421,92ad7a37,5a328323,71242c4a,e108c771,fc47356,322421bd,92c5142c,efe89e59,4689a7a2,e8e5507e,be8b505f,9dc9ac86,9d90ae6) -,S(360aa32,797804f1,649c44aa,b38fa9a3,5d011301,708ac7cd,a4135c13,d86a6758,ce4b0fb6,6957f5a9,7e4ef923,ebfbd850,4f6d4098,5333db66,1152f1c,ac6eef59) -,S(5b110b6b,d9ec8ab6,635f5016,bc597f31,ec22f7ce,cfeedd2a,1e6f883f,64d2379e,9472fb70,87ab6f91,2b10c6ff,995af03c,5086c034,f0f69860,ead562a6,e409c8b2) -,S(be27b39b,5a657cf2,9ebb1b16,45f5e1d6,bb6e32bf,e3a52b08,a916e091,9affa38c,93fbf27b,5d03ae3f,471ad91b,69e74fd5,a8f2f925,2bd16473,62c4feac,d26d1dbe) -,S(8ec65d75,c599fe6a,bddf3cf4,6ddcb4d6,1e9b5324,f5e7b7be,5407cb5e,28a9df4f,3d52541d,49ce4b07,7b543747,3a219db8,29680777,3cdcbf80,e4b47786,14ca082) -,S(6edaa1b9,ea8c2c45,6c6a34c6,13ad60ed,aed18a04,32e96030,ac7305e3,2dbbf94c,c64c8279,40cbabbf,fcdd4db5,1719c53e,f8cdb650,67af48cf,fd731618,bd304b7f) -,S(3fb5f6f6,60847e2d,e04341e0,26c4102,68d5a1fe,880602de,c07be98c,22640a29,ddd43c38,95e663fa,5aee3227,4a16f532,df3a180f,e0813ba,3ba113d6,f6fbd9cb) -,S(2d740009,d7addda8,a802b263,35d41284,b3b9a119,248a3b,29b4a532,654e84c2,cbe1e2d8,1bffb79a,6f9292f,43ccbbad,e763a56d,6d68cde3,d946f310,dba8f28b) -,S(15bf4abc,1d74793f,6ebf2fe4,aa74e34d,b359ad76,3d5624d8,19c24386,33517436,5efdcb90,259b5dca,39054a98,b6702fb0,f2fd4b61,235ed4c6,cd1f3dc,dab15f12) -,S(feabbebf,3c6ee0ab,9b584162,476c8e9b,f7523c30,7874d7cc,c4a6b88c,b118d423,c51d328d,276502fa,f79168f7,3787d3ac,b4e7bb7e,1f65b421,64ad6e93,2d405460) -,S(e3664247,929c3455,e98de868,60010f47,4258c686,4d4a7c0e,4bec28d1,b9af3188,7cb4bd55,ba579fd4,a3066f83,710a3606,2fab9f87,34311609,902407a5,88454bc7) -,S(d570f391,365aa2ee,29b6db92,2a96e4db,f1820a6b,94fbb8b4,aec45ae2,f97a21af,c0841986,2b0adbae,1cb192e7,bf80dba1,830520e2,35e1e42,569a31cd,fc0c1543) -,S(9cfce5e3,5119ca91,38629b08,c75b77f0,db3cb593,b2bf8dbc,b7d6fe3c,d1eba55c,33891655,226885b4,cd74d8ce,f29e978f,60a71bea,be99a2c1,d2071f53,239e4f12) -,S(186ecba5,f9998439,f6a3dca1,a179608d,a15adf9f,f4d2f386,4268ec3e,e62e4407,ec7eaeb9,bec50709,e8dd761f,6253248b,2fd064a9,638953bf,510a38ae,c7c6d24) -,S(ad52f2f6,fe0b72ed,2a0fe483,3745aebf,acfae58b,b40a0291,21767058,3e0f6b83,b0cae754,85e3038e,c6dc8d,b4e95a54,63e3e6f2,1b99d991,2f521663,3eea0c71) -,S(aa06c0be,7d72350e,6b094df,f4dec4c1,993588f8,5bd82a1c,158f92cd,eaa7804,ed628163,29369fde,f0fac2f1,a533fcb2,a704637d,6dfaa1f4,a3b57f74,4efbeed0) -,S(5f7a102c,4bdf0a06,76e1bd4a,4df17a3f,124bfee6,312b3972,c49fc4a7,14b3e867,85f153db,ab40a9e6,747aef3b,cd30f59b,fc9776c3,93293222,8f534d59,9efb30e3) -,S(31a4309a,64c225e,69567574,e05bb994,3fe01679,6f09a0d9,358b1237,96cd3fe0,9b9862a2,916ad0f4,1e588567,5a1e357d,19ec82c5,b31f967d,af058e1f,da7cab16) -,S(8906bd2a,505e8401,cc89e32,b9362c84,3443b4f,bafb7c03,75bc883b,11c3e59c,ca78e1d0,1c6fca33,b39d690f,5b85c764,ee15dbfc,48fa78dc,5f7d7cc4,5323d187) -,S(41cc93ec,a27c4fc4,19fc1c8e,4568744e,dab8917d,d8936cd3,2723737e,e36b4f9d,c11d8299,bdb95efb,842ba828,a6d89120,1fc6a28a,9f208430,c1e2f748,bce6b7ae) -,S(6e1b0bc6,199c3b84,220020e1,1a698e74,2fa97a58,c498254c,d3af1e8b,23ef34ed,25e0ed2,3f04706,6b4134fa,b6252276,b2205bd0,7a8ba64c,636e0b0e,1d6d0217) -,S(b55741a5,7b9c7270,dd1e5115,995ecc55,8729832d,9f4e373a,6824d9a2,83490eb5,9adffc91,52eca815,465e533e,c82bab6,ec6b37a0,dbb3b6f8,c3bce25f,6e3d944b) -,S(fde1167e,67f0e084,251d50fb,bafb538c,9c375e4c,fd6441bc,59a46104,46ff090f,662451a2,444d39f9,58593a02,e9a94ec1,4a1b8d87,9dc80c5a,73bb68fb,67af754) -,S(bbc374da,188df5c6,5a633621,804d22e6,f7474faa,47a8af94,a1cb78fa,aee68040,c2c74abd,17acf272,6c03bbfe,7dbe06ce,eb1f4e0a,b0001aef,4d8f342c,aef50186) -,S(bde6680d,414ce86,548504d5,55c83b18,c9f94e45,f55b6683,166cc81f,583e0eb,2b1ce8a2,6b5bbd8e,a087eaa6,49f49a48,2891abda,87c2037b,a73409a2,69b5e2e8) -,S(8f9ba006,faf50323,b9637f00,9aa29cb,8e402219,75d329ce,15796428,6c84e5d3,1bb33199,e5c30e98,5f5eaa1d,65879a3c,703b7a50,cb04c7ec,a6c7512c,94180e16) -,S(19f03bc4,3b61d7a8,62bb81e0,f4b84c02,7359a170,de0108f0,e9b9e9d3,95b63481,8239d21c,f31ae885,ae10c62b,8be0ee1a,95db0368,cf0488c9,4a110a76,7d22dd73) -,S(667c2647,2261828f,2653a0eb,e70de204,29231fd8,132961dd,ba3e4853,8e332941,5758f0ef,4362f75b,c4356b3f,cd8cb2fc,3c77cb25,b7d65c8f,ef7b4096,e0d879e5) -,S(86558922,618551b5,c4c66c50,9b81a622,ca376318,7c558ca1,8a00a00d,cf100ca8,32cd16ef,955deafe,e3fedb4e,55fd2071,8e35c1e3,736dba12,9f3c3287,4413739b) -,S(255bfbc3,d0b0d6e,385905b4,af6ee2a0,18109db9,73788509,2d5fb275,f1b47b45,b1b1078c,afe453b9,a35fbc30,c5f605b8,4a1f61a3,1104b406,ab5014db,57e2b167) -,S(acdae8d2,eeab48c1,9507f575,6ba60b0c,e9d5b6be,e2ac15ba,d31e8932,fe89e14e,b077540,ab137999,7e7dfb3f,5e3fff46,10c2a369,2306ac0a,418d5026,caee0466) -,S(162b0c77,da3bc13,a62753f2,b7b19c9f,3fe864ca,66fa2dc4,226c5cd8,ca8d7112,377956e8,59c2f465,2af5159,bdfc86c,df0bd742,ec7f9eca,6e675b47,d6eda222) -,S(9453c9ef,afb6a23e,40ebf013,eb1af363,c28a6e14,d235c7eb,58d3d142,9d1b498b,65e3b737,ede3c00b,5f322b38,9b09a68c,2ff44f30,c7737932,4e9c94c9,bdd78961) -,S(8409ed29,38a5bec8,669e24db,88c1b6fb,b397ba64,d8a1826a,f011e2e8,32e85506,573a0053,1be979e,1ae3f2bc,3d28ce2b,7a3ec55a,bd00242e,73523a2,582500dd) -,S(3b55d457,b1878898,9c486cf5,3d1ef107,4161330c,64fc2250,81096148,f5ea2c45,24780fa0,3e83919b,9e3491a3,7e0b76d0,f5d32f2f,a4c3aaf0,d2e7c955,43476fc6) -,S(d3fa2c21,f4704812,a5b582f,9096fc87,422af325,5c5d006c,63e1e9ff,d2d9ebb6,a6aea607,9ed334eb,9355fbff,27650096,ab19a007,191d57b9,4a8fc12b,a59bbab9) -,S(a938a4a9,9dc45307,29f3bac7,4fcd7241,1e56cff6,f53fb048,c727087a,9a54b374,3949a589,388ef8cf,aee8fe82,fde39e01,41ad91c5,2beaea97,e7494659,1a27bebd) -,S(792220fa,aaf49862,479a6de2,35be75f7,e811d12,7420571f,e46213a3,e77aa93b,5f274791,31fc7585,8b82b021,52057cc4,f1686543,3eb6e22a,de56bea5,8823131e) -,S(b1bcdf1d,57699459,1bc11d27,cb15d84e,75eb3d5b,2f9b4bd6,1c848c14,e9b7f2d1,a2115735,8c35ac77,e116a0c7,77917e62,e1d09897,316e2389,41d8e170,90adeb50) -,S(735b746f,6f0d453a,c45cf288,6941cf13,c63899e1,a41ff3b4,cc1a4c74,a9b2ab33,e4c2b67a,c6bd7917,2478b52a,994dccd4,475cb24a,ed1eb77d,a39fbcda,9c02771f) -,S(1640d0cd,ba4b4fc2,f3670b35,2485027e,2724ea4f,df918b72,3807870a,39fbcb2e,a0a71f4b,ba481eab,999dfc3c,15275eb6,b06d129,48000828,be4754b2,749bae30) -,S(bff651f6,df72e476,a097231e,b496618f,6e7d621d,dfd45356,8b08c718,e138caa7,10dbc188,2d0a17fa,d769f855,bffe1a81,14183445,5d9ae144,e6eddb52,8e67f99d) -,S(1a3fa743,cf429f3b,49e122c4,5c6d6e8d,18c633b3,f9903c9a,207f0405,c2716b69,b1b2c87e,65faf1fd,debc377a,bd9648cc,24abeb81,75efa4cb,5f0a0b06,aa2f1e28) -,S(bc2a9ae8,e2940908,ef5420f0,9ef4c2b2,ae988e5c,c0c0efbf,62f8ea05,b305ff21,ede884fe,6b48627c,84c96869,5944be60,df3ed5c6,66f16b56,188a9e1d,6bb14e80) -,S(8cee080c,e9204a62,502ae88a,15965abc,b2a8f18c,80f6c461,24b073f7,63990ec,3adc08be,7bea0bc2,b2c5ca91,963f4c40,bdfdaaea,318fe3c7,866229e7,e53c8fb5) -,S(2fc784eb,f79f916f,7f57dfc5,8fc62e8d,bcdc7dc6,70d6a444,c13f397d,ed528e2c,56c58a3c,be510393,90a88028,12d03658,20141c,b1b24241,241dba91,74d6eb37) -,S(fcd83e1c,ec7a6db9,1aef0894,cfb2e1e0,d2b48fe4,88bcd28d,c14e7824,6e62aa35,a86c9321,e2dd113b,cb7ec78a,d9d4db68,b5ddbc01,70aa0f67,5586b08d,6694a853) -,S(4e4fc5b9,65584dc3,40cec4ed,87ab0610,d674e1c0,9d76d28f,e28888df,7f9be562,d2344fc3,de7e5372,ebd87d0c,ea5431d3,2364249c,f6c350b6,d7aa2353,26e9ac7c) -,S(8df04fe6,e93afc18,b0508831,320caa9d,b21fb740,46bcc364,aa80564f,6f89270e,d7b37dd,2463e50c,583dde08,ca253215,4d52bd8e,a4252c55,6749641b,71ee7214) -,S(f662c961,3102fc4f,afd27352,cc697de0,1f4a1406,f99a0656,6597b96e,cbc99305,43783b26,759a2eb7,8ba4a3cd,e865d1f6,474b1ae,26eeaa2a,15220353,f6bce384) -,S(2052f92,b66998ca,f172ce,15cde941,484c5ee3,d3ae329c,87f339df,ae944439,3e9ef8c,9f4257d,c563509,6df8efa8,ffd2312f,60684baf,bb9e5d,9cbd04ff) -,S(730aa6c8,9c8abb08,855bc551,1938bc46,bad8f226,4b162386,9f2e1ef7,c2d6702c,7523fb97,799e2bb2,f13ba1d,59510bec,ee682f98,f865aefa,cf3c6578,bf46ff81) -,S(c5773c0,7d65fcb9,7cefd396,b07dfa58,1ab237a6,be3c1739,e6db944b,c7991c59,6afea6af,44ea94f3,ee67d071,4b6654a2,b1b335cb,e914d305,1a60b05d,44cb81dc) -,S(3ef9a63a,5bdce751,48d7c585,5e3e9aec,90d34ca5,1a3b4829,979d67be,c38c83f9,145e65ae,635acb42,e7949060,fe44f350,3535d417,f3ce9e42,4c3b3d0f,b02f2c73) -,S(a1632263,42b900e5,887b1800,196c5be5,11065746,52cb88c1,4011aae4,6d14bdc8,beda5e2c,40b55506,31aae0d3,fd9997c5,3f37169a,2d810b5b,402210c7,7c372cdc) -,S(8c1f5646,65449ca1,f16015a,a876bdb4,4d965993,7ca6936d,5bbb80cd,c2da6d65,7cbacf98,f6f7363,8940358b,60beec4d,1cd1a1d,900f84bb,9db5f784,d4565034) -,S(693ab562,230c1ddd,3493c64c,6f7e2bb3,a74cc535,2b7efc30,630904,e700d5a6,db890cb6,d09d5be7,ddaeec01,299880a1,2e68acdb,dd950118,3c8f5f07,739cf4e7) -,S(d761653f,f7979336,f833ca51,b91b9e90,b2bc04f,7b7407eb,be3c8462,95d59df2,f81a5d74,446e9762,2391368a,ed154b2f,4faefa60,af93d727,8357fd6d,98537c5f) -,S(41de1c8c,a1315711,3435ce37,c2d2efef,24a67cae,59347d23,44bebf0f,a2cecc64,77629b7f,46cf1d57,a03898fb,cc9f4e37,937daac8,12c4df74,846d8c89,60095559) -,S(21f89207,4e3a00c9,39862265,c1762dd3,2662d182,397c1127,4ef144b7,f598b650,e6e30e11,566dce23,b7a6a06a,11e12bcc,978a6b7a,fa9297b,8c978f56,40f8b4f1) -,S(6163f61c,628b4800,dc49f30d,dff19310,369012a8,f31d4a25,27c790b4,c51f068,4e87a17a,12055cd0,4c4bc19,e052a219,7dc5847f,ec984f9c,aebb8f81,7a7065ec) -,S(a68ebde6,43ab3c15,72f5ab0f,85d683f2,6e6eaada,550e2425,f85596db,8e2dd200,487604ed,38a6387a,27e3cf1e,9d4865fe,7fc67e7c,ee26ab11,1f03e0a3,316de778) -,S(9b9fd342,4e065ff5,b82e0c4e,e5efa0b1,d0991087,684c46d5,7885adcf,b352d06c,b11a7a46,570eb251,6562ae87,90eeb403,823380c4,aae99329,de713677,5b5b5e0d) -,S(d80c347e,98db32bd,57ba5728,20c7322b,b295cc3a,ae326fd9,49e7557d,27151fc2,6d734eee,40229d19,465a0e2b,a011af39,62ff5c08,f83a2e17,e5c2783c,a430cb42) -,S(c8aba983,5f814895,e5d05139,7b23988c,7fefedd9,aed9dd20,a9bb0025,49e63ef9,3811b18d,8310a67,532be770,45461d82,e40c0ff5,6af355a7,55ed4708,f1ab0c7b) -,S(1bad15b0,a186d418,bb84a87d,d2fb9255,9aa64547,cf47a93f,73d23953,86b0e301,e432c50f,662da1ae,f7ee8f73,f5d7ac4b,4a4da6ee,5a943d17,7557e64b,5eeab1d2) -,S(720fcf05,dcbb0609,e5b45efa,e055811a,66d84384,16f7091d,7ea66186,922779e1,9045fb14,37d2086e,ae7d6a64,49effaae,17e3a559,571ab010,57f20fb5,80535906) -,S(96a540e7,8fb6647,63d3b129,8a1100b0,88a2c3e6,6da3ebe1,4b6c39cb,f01c4b2c,4debf0e5,c95b9a1,7bec7f14,12018197,88a1c325,12f60973,9d5b4909,f087b5c2) -,S(2f068148,d385bcd9,6fd6b60,b7e331b5,88419085,3942ed16,18b464c5,9c3ca99,596f3fb9,2fa7377f,a9ecc8e5,be8421cc,77339f62,c6f1572d,7a28266e,eb66ae52) -,S(466e9733,ef167fb7,233363de,16d9d510,74d8e5b6,35abaf38,20a037d4,f6b3e45c,73548e1b,d4d5b78b,821fb1d9,94919bac,a9d4e12e,13a2e8f2,d4c5df51,2553410e) -,S(f8a841c,a8c7fb3c,9a334f12,cfed9ddd,d1dbd4ac,764f3c6e,87a42818,a4a8e51d,57ebf669,72e9c4fc,7c435cc6,a85d381,6a969d02,ea85edc5,63c57187,34f0f926) -,S(d8c7d6e9,6719e74b,2eb7ae7,59d82ad2,6aa003ee,58e3d9df,ea97c7ae,6d6b887f,f1bec88e,5e8df038,b069692b,9e44245d,a11feed4,c89ff45f,17bbb6b7,1b0e43ca) -,S(afd5e13c,cabf51c,19c39c4c,815618a6,14a4f461,5fbaab69,624d366d,540ab638,9ced3d42,5c361706,16cdba99,653c00aa,e5212c5e,939c0bf0,3e5a1cb0,a05cba0a) -,S(fb491696,a4a1b9a1,572b462,f4628f66,b8368f3,3ce957d0,6ec29a0,92ce994e,b4fa2340,68741570,a56182bf,4f1c71eb,2c80d6a0,cffa42bf,a3e9d9da,59507de8) -,S(96e301b1,efd54091,80e3aa96,6652a253,78ce4bd3,cf587238,f0367a58,ec45b0a2,1bcdfe49,5ed90efe,7eb853f6,6fdc5b7,365ca2ae,e1d9b787,afd41b9f,c00f308c) -,S(9cde8d26,40d197a0,9ac00167,9b93092a,6eb8b13a,4d9fe2e5,6365a5f5,fc38d809,c86345d9,cf95fe50,40b2b2e6,2bf4267,72cdf10c,988a4f27,836d960d,c98501ef) -,S(d33ba473,10c37342,43e2219c,f3cf4881,2e843be3,c7492d01,80239bdd,20a829f2,ac774707,a5b0888e,b2ffa131,b71035d3,6af5be1d,3a3605b5,751b92c9,9e58a45a) -,S(6b364a32,1b5aecb3,749093e0,1b5229d6,5576e65e,1bea096c,29065a87,e26cf2aa,668ba97c,a01f659b,3687cef8,ac87dcd4,7a8a4f85,4a434f49,9592151c,b8f96152) -,S(d0009cbf,1d0d0673,5f66c16f,5cd4747b,d33b3347,fd7f096b,a026355e,917b5015,41c10a72,3e82bec0,b92e560d,3bf1e0d8,15a22e50,3afb4bf0,e5caf771,569a7dee) -,S(e618f641,a5b443d0,704102b5,40efb697,c470955a,8375e6b,a845c299,f377b701,9d615e53,edf6463,9b3b2d0,8684f8b6,15cf4122,33991a4b,5b7c85bb,f5698825) -,S(789c55f5,d393228c,7cc7920,9e705d29,867a6e9e,750d05da,9bc6dbdd,36c5c49f,8f38e43a,338058c9,39c64ff4,3f8f7bf0,2a7910bf,dc2f9af9,532049df,ca236de3) -,S(8fa4f0a8,1bacc20c,5d402478,23401597,bfbcc47b,973abe3d,71d33e2d,fee792f7,7dfac188,c5d6c17d,9e7430ed,d9038a6,e6fcf47,174347d8,7a68aa4e,cdc46c38) -,S(4d5f8d87,9377b056,afd4c8df,54a48673,c43fce03,d05be56a,56c42a23,356c34a2,b064c60f,a3b75513,577c171d,68acbef6,ac96f665,6a899d54,29e9427b,533b8e36) -,S(7a409ee0,8299930e,ddfc1e4a,db8475ca,9a99bf4f,a178a8b2,540ae448,ac87a3b1,5c4873af,c8a079cc,38a385c7,2ca039d4,4363425e,67de4cd4,15d09514,50f28e17) -,S(ac327275,44973221,dfb8b577,e33bd935,76407a86,77a1a842,bb04832f,68304e88,2b41b0de,3e406560,a57978e6,3359a911,6f993a91,9dd1c2ca,79c9a36a,6a4c8815) -,S(f9168fd3,973728c1,30dda9c6,907912d3,2e6cf9fb,b1c7a058,cc948f4e,44282720,c7005217,a6adf515,d8d3a87a,7e8a8b2e,aeb470db,c014824c,733e9a7b,17111677) -,S(818b9a9a,295d8f3b,bfb69d3a,f4749e5e,b0c1c04c,838ac3b2,9e74f6e5,dc73281a,141d14ab,64b3023c,597e96c9,3fdf393a,b53f45f4,56cd17a2,bd917af5,dca8daa5) -,S(90a416a9,dba0e05,bdd25dce,2dd0b0d9,200aef56,a6c0e16c,748e7d4c,99cac1c7,bc871391,95a2f128,af9c9c0d,56bff605,2fc27648,4e0a855d,6472f0e9,a779e0dc) -,S(678248e3,d48fd800,8e694890,b442d3f8,4f851881,9b152a6f,da24a6ea,88e1efb8,fa5d302b,51a36e66,98477693,9ba9c095,eb8b78c1,8f1bb114,53cb1904,a2185615) -,S(c2333e2e,742bb244,b7dac90a,18c2e65c,1dcb447b,11f8596c,bb3fcb8a,1e85195d,d15b8771,a31ff36d,b46b9ca1,b0ba345e,b877b7ec,48de20d4,71792a78,17ee826f) -,S(7d562291,9c72b694,d81bd71a,e78204af,995a63bf,3e8ecb3c,d9b3f589,c75ef8d8,aa554f52,67d9d3a5,8d35cf02,191b533d,ffdebf32,dde4cf07,252ef949,ec7df6bc) -,S(c5023f92,698f955e,4fcf7fda,288673ba,97b4d275,7f26f25a,c63ccfe9,155232b4,7d9dbce,def550c4,ee4c881f,69010859,c7a09ea5,36a8f7d7,17c1573d,c5db971f) -,S(37dc82b2,ed0e9533,e87867e8,d1eb57ed,707f335,b081d14d,d57aa247,645bb1d5,ff0c021a,d28649f2,3f000ae1,123f909f,1c803a9d,98ef2487,bf5d44bd,a97068dc) -,S(ceae1d30,2bf19dd3,a952ac79,8426244d,968b6ddf,25e16357,553f7636,a15ba8ed,c5a3a752,4d05206,39ecb8b,bf4282df,a1f9c795,ea74410a,ed9e064f,9a37c70) -,S(8bd49da5,fdb92648,f321bfc4,2d8145c5,20b8dea1,46b2bbf2,7a054698,3eb6574f,f769854c,5b5c9058,20ab0765,1a6d8104,e9a9dd1c,7aea6425,2b239ba9,7b0609f4) -,S(d1553a8,9a5226bb,3c5b6296,9f094b2c,1b761aaf,2605b0ba,b3793f6c,6959e8ee,d7b11159,d289d42b,8ca2889,f3dd7d01,e1cd0e5a,745b9f12,ab98b823,3211b2fc) -,S(ccf443ea,d8b17d4c,ec59ab81,74f1b1b4,8b6c3934,6e64a955,c617336e,aa6abc89,5cdbd39c,64510cdd,b342cce2,62915966,f8cef7cd,e10f4a7c,41a0d495,e5bdccd1) -,S(f95ad24e,7accb2b4,ce6afabf,6c1a40a0,172cf2b8,42871778,881ad94e,3f3d8d57,f3142d40,377543bb,6dee8195,743a6d73,e60dc5ef,4b0756eb,68d09d6e,326caf5b) -,S(464189d2,52726cd2,6f5ad4ca,5184503f,c546144a,ce7dfb32,5e4b4147,da7bcaba,910f8aae,acb04646,3c6a2a31,6174510d,8ae8bac9,fdce4c47,6c0dbd62,5196e2f9) -,S(637d373a,7355334e,70c78ae4,99429ce2,a5d97257,c0f407b8,1cb41704,d1b36415,469fa81,5dba5bd8,bb53a5fa,aff5b4c,18e7c28e,fbf21f52,14359d6c,7114c818) -,S(b489330e,2a4a4a6e,a99091aa,4e5aebaf,dcdba016,2bbc38df,5a49d4e4,7eee62b6,e1fed3d,93333ae9,2198b85e,fd68582a,35f6fb60,ff268494,720b387b,b3a7543e) -,S(8f2fbd92,70781f54,9d32ca01,2479438,2ec9cad6,2151c893,64c1cefb,c2324b12,2ae5c8a,2e018e74,2089a4b,12082c73,ba466dc9,851e7226,388e48ae,b1270a1d) -,S(a1871963,e9a65bd3,9e1b667c,55fe1a1b,87fe4215,8273c6c,f338f8cd,9119a828,e6881210,adb32d79,10dfe9da,c46c728b,20bca3e1,ad130240,f0dac7b9,fcc0cbc7) -,S(4a91a506,e8b32ca,13cbad7,99c4e3d7,21fd64c9,7ac8a1b1,e7f4bf2b,cc0ffa1e,66a0ee78,cb63bdd0,1a7c4bed,7bb565fe,832eb2c2,d32f2032,c33935f3,f16a40ca) -,S(61c960ef,2a3a6244,e8e7ee79,d4f5e98,88539c0a,b8be739b,314a100a,375ab66f,13b94913,ac8f600d,dbe9a82e,8987a061,3672629e,45d7d887,822faff2,60fb9e08) -,S(10325f87,f797c48b,2e6c7acb,bc0aa0e0,537fbf59,e74ab9fa,a7630c9b,86a04b72,685c5ae7,26b5c9c0,31e1c830,d513db4,b7fda140,14f8b723,7a9da11c,7ce9403f) -,S(71bca019,c15a3534,e5bebab0,6e1e1821,1ab01e97,dd24e1f9,1f89f834,b2cfde74,102387d9,a8da4f7,a483480b,316f0303,2178e668,f7a72719,2ae7e54d,27314a8e) -,S(7d30b01c,5c93abf8,9a50d14a,535a88f6,7cbb535b,1e58540,661fd7ea,91121fe6,e3d7e70d,1a9c0cb,2d6c86df,53709d18,b1989a5e,7642c1b7,cb381338,f6ed96d2) -,S(6f0322af,c1617968,b2550b3a,cafc8d0b,9445fd7a,4692f933,3ae9146e,fa2d3a4e,ba402962,d311b424,d05f199d,31b07d5c,8534ccff,caf817e0,88712bb4,2e6496a1) -,S(a3719ef2,c34bce90,feb7668c,a07d1a23,e2e6fbbe,1eef4b93,d2995e84,2c74688a,7164f77b,67aadb53,30b4127c,2d71dc46,f11e2d72,25968163,f4ea7358,134e5d56) -,S(3cb0007a,d2f1fb76,aa9752f0,218e2498,b7217440,a6a5136,68e95a78,4f71a72a,2f498749,12e8f469,e511b7a2,5a5046c0,f922a343,24620b51,3f6f0160,6de6b308) -,S(26b62d6e,f46929fd,88f00ca5,a699ac87,e090ab0c,8f02a078,393fb3ad,ae18c055,4fb9e53d,1b643585,4f2c78ed,1a818a80,1ff62c5d,fb0f8f23,d5e4d096,29886fbc) -,S(55e9ad69,68f490d,bfc2e17b,4e90dc5f,58335c1f,7bf30d44,79679acc,8cd7442,d4df7806,f74d9701,378ea804,be9a6270,85767e0f,b816ddec,4dbe34d9,536fe892) -,S(74a87add,723320ea,f1f9c35c,eddb6133,79835723,c74bc043,af36aeb3,5e1cbc45,5c79ef91,bccc2579,eea907ac,85ff8c0a,57fb48a7,c273f9af,6113e177,588fb14c) -,S(d4f1a9e0,2189ffca,c1d9914c,177fd66e,9d9a41cf,d1a38626,aed6b82f,70ba8020,923bf669,6ad7c71b,bfd696f3,9d68373b,9d0cbad,f367363e,2f70a93,4a0dea5c) -,S(593c7afd,c178edf,9eae7fb0,85984992,bc5ca489,16a2a155,a0314d8e,31fed706,ef39bd47,64f3b3b4,cd505e3a,628197df,5aa74126,30d83793,75c85b27,76a1073f) -,S(6622a6ea,569856b4,23e9f68a,78bab680,759a0089,3f6f645b,2e0eae60,f5dc9d3d,e84d491a,1bfc3127,3cfecf5b,65621213,bdf1af30,2dd39d26,d756e75c,4f9bc86d) -,S(d7149e32,fb34d956,1f5b25d0,650409f7,33a28fc1,fa4ad822,eabe98c6,74b3437d,2c249dbd,a1a82561,51b6eca8,a44bad96,1b2d37c6,d01c1d1a,70ceaa38,9b3f5039) -,S(64058ff8,7cadb65,8efbf32f,a68b7b3f,19915f5f,b434830f,bd5ca208,a4a09b6f,71c6dc90,f4d8082f,72d5697e,48fb380b,8486d7e1,5f113cc,28365ef7,d3ee9999) -,S(6a6cbb7f,5b571865,d70ec29d,425115a0,82d1fc1,f0209e8d,47be5e5,a9965dfc,fbf10d18,f3af0e94,b2a6ed30,c610f17f,5bd571a,41d073c4,2b2a4dce,c98ced0c) -,S(3f9a9be2,9a72cf7f,2086d9ff,3701a35a,94a7f81d,4b34a364,916a45e0,d8652874,25b12751,5ff033c1,70feaee1,189a35d8,ba0b8da,d4c943bb,4fdcebd2,1cffdf72) -,S(873be5e6,3cca17ca,95980167,9568b487,3d34c5ce,68abd305,169917a7,30dd206f,6ea148c1,280396a0,7ea5c5a4,17980f48,d076bdab,3df1628a,89da4c45,14bcbd4c) -,S(17865995,f28d4c4f,43e2e9f5,9b20edfd,830a65cd,d632cf9e,e7024ec3,4da0834a,6773c06d,478f3822,86c749c,5ae09a10,910b5666,5b6df747,36d20adc,af58332c) -,S(efe91146,fdfc4865,bd784853,ef79b8d4,d2f020db,3f901f45,38c74c80,bef49172,a81a34a8,dc3a229,8348109c,14d367c8,7abe6753,50d013e0,b1b0372d,2a6ee5ba) -,S(7ee6fb63,36cc88be,3b3c2821,1552031f,d017aa4e,192bc122,973545bf,924e8a8e,a656fe25,846e8173,327ab11b,d8ecd2ed,9d1909fb,21d1f789,588b4fa9,a8ceb0d8) -,S(449677d0,2a78e9a,ce374016,e19e7fae,46efd0d6,4839680a,4d5cbc42,173ee605,47017ad3,3357db8b,ceca2513,c6477157,f3daa99,9cccb709,bbe88340,29312013) -,S(ca9db080,12b9fd4a,cef2255e,83f35fb,e20806f3,9839c2a1,699c5d03,d7b5762,6a1a811,3d82a60b,677d61c0,af995bd1,4c598f08,f915e971,d9f17e9f,8398487b) -,S(d040da2,8dd69fc,67414651,714d4e94,5a27c4a2,9fb44612,d6d87f4f,80e2ba45,a1a72b85,957a01ca,8c8d5d3e,d9ae6a2b,31d2d192,cd7afb9a,4d1e4629,aeb9f356) -,S(27eeb708,fd2d52a9,47f69872,3706b67a,1d6e29b,cc0c86e8,111057f1,e3655608,7f67db4c,25b2e88e,275e53c1,c52eb47f,c2dab668,64b91236,522229d3,1b001a94) -,S(3bc82484,daab22ad,6d887a01,ea9f4b38,bb70e272,b15a7b4d,ab5e3dd2,439d8a23,b0ec952e,6cfe3ed7,4e6246d1,46c9c354,dacbc024,45b1af9a,6a668f0f,6fd52ded) -,S(d0a00060,13596198,8f070ff6,7ea731be,7f97a51f,68faf899,95eb0ad7,746aec69,dde4a735,d6dd08cc,28e2588e,9af0eed7,57017b38,790d381f,74748f30,9717a989) -,S(8efc4c50,51c65e10,56f5ccb6,a4be2014,a9dd043b,641b7690,cae2a8a9,1bbe8ecb,26fd1112,e1aa603c,91eb458e,3874d010,db58efab,5dd9ed20,e156886a,5f39fc13) -,S(e42271b8,881306ce,f166138,7d14f0d,da0db64a,b379368e,fa79969f,432cb110,d2b9999e,7ce9f3c5,8a6c77ce,a97cb9f5,f2860299,9bacdc7a,b7d5487f,8b5c9f5b) -,S(bb068f3f,8e7fbd31,f3aaf96f,de53d134,e3a88b63,9d8d43c6,4b3a2b45,2f8de740,574410bf,903c173e,23d88fb1,3f7534fe,566984c1,aa10f0d0,f54eea9e,7883819b) -,S(a3d0bd11,d728bee1,b166dff1,81c3682d,650fde7f,285ed5ef,b2ac5033,5327cd66,3e290c2a,42afb4ed,8b5a685f,69bdd379,44215104,17a61d8d,bd3dd2cd,805c5f44) -,S(9884434,78bfd51b,d27d04df,b5282a72,4cf82c21,487a8733,9347e560,994debdc,545574c4,359fe553,b694803c,5a07339b,b4e1a95a,b9fc72c7,5d4c8f5d,ec6ce4df) -,S(8cc104b8,58b8fb94,e0771dce,a103a7ae,adfc50cc,dea4cf93,a5f4ec9a,d44acea3,ad73883f,57c470cf,d477f228,8badab99,938b6723,516f97b1,22578f2b,f893b506) -,S(1627b08d,a822d244,ec8fe2e7,d8f02094,111fa362,e7190cbc,11229a4c,2043c626,41f6b029,80fb1370,c1e800de,39507798,8b6f315c,f910bb00,423ff727,e9e04c3c) -,S(459d4b1f,2676fd9c,2aac5937,376dc18c,fd4244d9,dc937407,d641e0d5,491df69,6f22ce37,a6ea6a5d,c9823197,22b0085a,e61fe140,d7558fcf,7bb44976,5de7aae6) -,S(cdfc7b3a,b755c181,72882e37,ff641e2a,94fa4e5e,b1b2947,4cd6e94b,f4f9387,76a11dae,107bced7,c2870dd,62ef183a,d45a02be,ce33e333,dea061fb,d89e787) -,S(5e189861,b1615f76,ac416236,e84b0961,b2639845,ecf6e6ee,8dc33217,b0952afd,1cfc65b0,9194d1f9,71136626,a2c3896f,5a3de705,ff1009c3,49a09c86,ea1667e1) -,S(84749eb3,3d482c59,81cc08bb,8634bad,fe0572d1,42367cc8,57a3c399,821d12c2,146a4fa2,3fecc0de,f00299c0,19406b30,dfbd9ad0,975717c8,7630e726,6e96022e) -,S(d73a1958,e9aa29b3,b1ab0807,2165c06f,daa38c90,6be76384,1851fa3,5711bca3,41f13f90,20633dac,3a5eca40,229ad15b,434c4f8d,4ea570ff,76d15d4f,63ea882e) -,S(1d77616e,1ccf1fda,bd4f0beb,6b60c1b3,1b94576e,bf2b61b8,c085cd79,caf8c018,7d3e5813,cf181271,55f3d084,df1077eb,2bfc9d6b,8ab6ede9,55c0ba4e,5095f23c) -,S(bac936d3,63887dab,cf27ea02,50bd550e,db37cb71,a2a8351f,fabcb1d,6d6ca9c4,7aa18819,8bd513e6,b45d6633,aa1af70d,b1a9c432,ffd1be4f,8a8fda79,a38c47f6) -,S(4d18c5c7,51639d86,b21712fe,b2333d52,5f4bd3f5,e4208537,e1e3bf7a,9343475f,2a60352a,4d8fcb6a,ce01b4c7,63619f16,156868c2,d85e882e,a2e7fb80,16f6500d) -,S(8e473caf,d74fb06,b483d955,ba3e35ec,e99a4495,cc86485,a8b6fada,c4c8eb4f,41708d5d,ae2de832,c7c38389,d0ae46c4,46add069,8e83990f,52a545f1,6ef66942) -,S(91366f76,48ed27a9,2ab639ac,f37aba5c,44e8bea6,1402e075,e307c4fa,ea2cefa8,868fe0f5,565092ad,677eb1c9,8959affe,5af504a0,c929bb58,2f5c3263,114ea371) -,S(1eab20f6,51b63685,a0a8489b,4e3247ce,1592c4db,40cb2f90,7eff1c58,c6609915,c142e9f4,b9522b0f,1db90912,c6f83c7,add6d8a,6bd1de4b,c54503a8,4e873cce) -,S(a0652eda,796ff72a,eaf8cfef,371594fb,e1528929,1320230d,2bc6a252,f4b49484,67e6d40e,8aaca7cd,f2a2047a,fc0a59c3,b4eddc1f,d3d5662f,45bb5792,9e4dc9a3) -,S(83915afa,c936886a,3deb8958,70e926e9,7ee4a6ab,1a5c66b,a1602c13,c4f959f1,86dad7b8,e870dba7,712ca968,1ab63524,2ed55fe0,36a148fe,25b1bdb1,1ac2da4c) -,S(293f0bc4,11454959,86b19fb8,6f738d2c,814523f8,b75b280,f8f9021f,95db6061,12d98ddc,894669fa,86b073e6,5855a0a1,760733e7,b7c5bf5e,868dd977,82a4fdbd) -,S(a829b1c0,d6780732,321871da,2d28ecdf,18d13311,4ddc33aa,8ff4caf0,58fb9ad,c5375298,501294a4,dc38d1f,a8c96f9b,789ee9c5,6533643e,1142bce6,8e1ef5ef) -,S(48133900,866a344,68309fc0,cc18f79,c0e01dfd,ed6a7bb4,e5a4697d,4b9cd462,335b7188,ccea4687,50fcdfc9,a6fa6034,c239fe6b,27cf6460,182a1c0e,c8c96707) -,S(7fe9d310,bbdaa101,b28c1e71,137a7ab5,181dca39,aa8d1469,bc06c856,3c7a70ec,18006c39,538a5141,2371828a,4d73e02,f4699a34,7e887318,57e394fe,75c8143c) -,S(1bd5b65b,d79c3eb,54ee1ce2,541b4352,1b7d6c37,d2a26f21,b51d2c07,103ebd8b,66e81b90,a120f04b,340adb2c,42143ef6,5d8a383,46e71856,673090ef,291d7bf2) -,S(237374f9,306e5714,5f37a1ce,1418a238,73938fa0,8bb971ab,fb5d97e8,e5fa0206,d8410815,fd4049e,f54abd51,fe2053a9,bde7f3ac,f40fe992,21bdcf8d,4b9808a5) -,S(33279bf7,38cee621,c17f75eb,bf78af4,58c1a4ef,a7197456,b57ee679,f2c34bfd,d63a21a4,5dc29462,13750d88,ea5e12c9,900b110b,ce433c49,e9b37382,7de327ac) -,S(ee274c71,b1f43251,11d7e100,5d7e9d97,ed1590d8,95cc6504,3e8ed6e5,5a87a9b,73f2bd1b,1baec4f8,ebbcf9ec,f613869e,8a262d99,7bdee49c,c5b2fb22,b652e9dd) -,S(2f49f0ab,c24536a3,3bb0857d,57c35846,f5dd036,3851a873,46f93d0e,53ab8de2,66b3dcd,d367958f,fd06121b,e42237a0,a9edaf21,79ded853,e8bf3c5,b6a81531) -,S(2d122193,ea92ca9b,46eec10e,2a23268e,9b1f972e,91821489,8cb12571,1e3094b0,b54d4b85,a02f77a1,57a48001,c0a26c81,2c038d0f,b91575cd,835183ff,3a0b7071) -,S(9047eae7,841f346a,374131ee,d4299fef,970f59e1,e4bb1fab,819fecb7,3026ad44,d59d3d2a,2c03be1e,553a54d,2dc61c9,e13364bf,3338a5f0,4e4466b6,86695061) -,S(f689480d,c0ddd61c,ba5aefe3,17aaa497,c2d051ed,d527cc20,16877986,12d7c8f,dac41495,a948d83e,37a9f310,18cd7abf,6d5608f2,213aa5cb,7a2b8f90,98d87398) -,S(4a01c418,be472958,5bae0c45,cf6233b9,ad0177ef,eb6e74ca,ded59788,a22d083a,8a12550b,83de095f,22411b16,937a85b5,a079c7ea,b8137f80,ffa66116,2a1c53f2) -,S(a6c715ad,cdc77020,febc4ae7,c6caf5a1,107147ba,8281d3f3,7945682e,72a5da7c,69b4ce46,2634da4e,e9e43559,72f87511,a26718d1,d232f726,577f0d5,6b49d165) -,S(68ecec4f,aa19ac3d,dd8b928e,8362ed53,3be24406,15f5ddf8,4b8a376b,cbff327d,f725f978,f6129f28,49a1c9fe,b07bc2b2,78fcdf4a,96a6ee3a,70b9b943,98a89f3d) -,S(5701d52e,2cdb7b71,a9ed91e6,95396487,1b656bc7,271299b,62ce0a4a,78dc69ee,eb8e4539,be99cbf0,ad730fa5,fcf785b7,35e1f5ad,f5c16c72,85abfeee,4058ea1b) -,S(8210f0c4,4b2f54b0,62de4761,b7c62d87,42424b13,ca0448ca,ba999eab,73b26409,1c79890,e4149248,b9dcd496,1da563f1,517275ec,79949969,8c6b864f,c03f8050) -,S(64cb2793,4ee57641,9d52cd81,6144543b,e4319d16,fdde7a7e,2bd824c,113bc1b7,c3144c3a,518eaebb,51a55bba,d87aba0a,12d3add5,5a5e00c0,94a2e227,80f0f6b7) -,S(37eb1010,acb889,932d8536,b86648e7,c124a8f5,1005c0fd,ec40bdd3,6369c82a,1da5703f,b387312d,d5a337c2,2d3f63b7,33dcc994,38109c2c,4807fc45,c02a2717) -,S(84bbf980,b54d60e1,ccfacb7,e861aded,b4cd7bd1,a3f7baa0,9a1898fa,22144d2b,3820c4d2,7b545166,2515064c,dc9b4cf,813c2435,e84a4a67,ba47068a,e6e09045) -,S(29e74c02,6b43add6,939ae05b,dc0a5e0e,b7d05bc0,536e23f8,8fed55e0,6f93f1f7,f0f6fd9c,798732c2,1dd1c550,3cfbd56a,71b335d3,aaa22359,75fb0c89,9571186c) -,S(98f3530,1122a0d2,629e5adc,579acbf8,8c0aea34,c3450ea6,784c4ce5,ee9672f1,427b899e,74e0c5cc,c289304d,b9a874c5,1d401369,55dc5b03,e0713bb0,8c3ec3ac) -,S(16af2e5c,4c37b50f,5f2b6e94,341e365c,90548d68,2bd9af37,1d849126,ad2c6c6b,1dd1bef1,6077f6df,32054335,c81ff474,33b7c1c7,d6243dbf,6a2564b0,fb9d8502) -,S(56998d6,bd5b2da6,d452f951,5343a9bc,4ed64463,adc6b8df,6a3edd64,e75e1cbc,ccd52462,9dbda3a3,10f3beac,7b3d3bb2,f1bf3c50,bca242ba,224861c8,1f26760f) -,S(f1732044,ec59c52,86273115,3c53aee0,c7f1c4df,e6e55cb0,e7e37d62,c1e11ce9,16a547b9,a61a6c10,4df1d1a9,de99f54,b42e0ad1,104a6a30,e6e616c4,dcadb2a2) -,S(6e5fcc4d,2df77b2b,8d2f95dc,56ddb885,6030f9af,aa51d86e,20d4772a,854b8973,11939a24,26c1ad6f,90db151e,c5c9f036,3f0b6898,2464fe92,c33aeedc,77347660) -,S(74a3ff02,98c3cbde,ba066554,d6def895,3954af05,f0f72365,680b7b8,4c5e9fc8,23b5f011,e50dd2b6,9c5ad6b,b4dad524,9c6a8abd,f134c232,f40de18c,3c65206) -,S(12a40a59,169e806c,8e32deb6,7e64c615,77a3ca,5c56723d,ebc98ed3,11983bc1,9d97709a,9c644c8e,3fcda745,a70cf3be,c405d230,eedac78f,96792bce,a715c081) -,S(f25dcc0c,5ae3f442,7fc17acc,bf888557,82673050,c3594abf,cea7eec4,7a4662af,52a20297,bb9213cd,d1b4f1f3,4f6168aa,ec2d326e,d9aef5eb,5b497c39,e0642e0b) -,S(fe31ac7b,ee45ffd7,99941eb1,8d65cb2d,38618938,c6278e45,4b87e41b,3c7d0f90,a5f1be4b,e0373cea,c3137a8a,c5b5cab3,e1209c93,2d49b245,eb99a0c6,469c3e64) -,S(c0ff7403,2855c2c9,ba06c2fc,6c9a8fc5,29b4ebb8,be082951,475196b0,ca4d6711,2c53707e,540e0c03,27a10980,25e356a,81fa6a48,b1e41d78,b7fe5515,b022173f) -,S(5b23e392,b87bef43,a3c08956,e1930c10,cae049e,b6f041f9,1bf3de75,4a84f984,c905adbc,337b9e7d,78781dd5,deaa0590,18e20bc3,5114c842,72343879,7a37987e) -,S(2100a6c5,b6b96ad6,37e13430,8d92e2cd,97902da4,7a016ccb,63a20cef,e72ac25c,a1fdc3cf,93560ea3,8418c470,679c5389,7bcc12aa,dc87ee6c,3429c68f,690f7e11) -,S(d57874e,509198e9,ee6ac826,b101ab2d,fe952895,ab288184,55f2d85a,eb2c3387,1c7bd36b,cdb6debc,99228b,341abac2,94dfd768,c9e00e73,8aa58339,d226f940) -,S(ff91057a,e46817be,b3874656,42afecb2,a290d31d,f18c6da3,d6313565,99657c4d,a2bb1559,96ca6cbe,2a375c3e,510df603,69d0cd8,f66d6571,9f9866f8,c6e73675) -,S(7f20e461,ee306c4d,7db625b3,49906235,14aca551,21b7890f,244de5e5,84d18b7f,8cc69fd1,eeb89a9f,9e126be4,3983ed45,d88c22fc,89f47006,ecd57431,4eb5d1c5) -,S(7ca32320,75421226,257670e4,5f277f4d,32cc7b4d,53588423,317203cc,b787696d,1e940799,8f25b7da,8f1212ba,c1dceaae,ca7b1952,26655535,6a98769c,b3da15fd) -,S(bcb7060e,f2685623,9aac249b,f603ce7d,b5c253a2,c998e44c,4ed60db6,730d5450,e03df58e,6d279025,955a4f52,dfce586b,f427e376,ca72e09,36d80c31,5047f57) -,S(30387990,3157ac6,fed71113,a004284e,82fdfc7a,3e08c0ff,1ff5dbc5,dbdfc04c,7132084a,1230ecfb,200ded60,9a1666a5,2f574014,d29475e1,6a061330,fbe19e7f) -,S(c5b3aa24,1147d664,a0b80f33,5dfefed8,a8f7c1a8,c6258686,cb16e3c,c365a249,fb5143c6,5f8907b9,a44f10fd,27064fef,93ee588f,9e77a65b,1cf64e4f,956f5748) -,S(11d8bdb2,b750146d,d78d8c55,6e6ac45f,4d34f1ae,35332673,cbb46bdd,3d76d9a9,1ea28ad5,c92761b8,7df96987,6e5b3243,9fe97661,87b5978a,d7515288,f30a5970) -,S(d6db4c60,742914e,c9c7bfa0,7a716cc5,f5492aa8,5381f31d,f76d089d,a773814d,b0ca5fa3,bc5d1fa2,c62a657d,77215b49,82f72e89,b138552d,bdea8166,359b6a3d) -,S(d28a6123,3b4e073,f1242c4f,5292bf70,9e1ae15e,a654bae3,4239133c,4a8a86e8,89519c8,8c44b38e,ad5c2ace,52d01de1,d74ee0de,5365567,cf1b21b2,2ae8b95) -,S(ff32042b,6a943772,d6f5794a,43420218,2ed31ac2,447167ba,ec82d19b,86751337,16961368,e20f2550,383268c3,9fe62fe3,b5d356b1,da2e4231,8f9618e3,13655f0e) -,S(f2c6177,30a9870f,5999ed69,d34efac3,589baa96,9f660cf9,ac839eee,a10e374c,fbb2480e,b6f191c0,15ee3c58,bd950aa6,7bee7569,1681250e,502e1d76,b6ec9069) -,S(dca14b70,e5e33022,eb559d90,1cf3a533,4c40bd45,7a43df85,e87acd40,90342539,7d038e51,30f77ec7,efe84748,4145594f,87d613bb,85a95715,9d0cd377,91678d23) -,S(9cbb407d,acc7c2df,2d86a258,d5ab2b43,31a18bea,9480f5e3,7727aef7,644416cf,7ab9fb64,c5f54f6a,4e5529b6,eb7834ae,80283bcd,c3f6b24a,8a014d02,b3b80b57) -,S(4552c48f,2d96ef41,aaf27778,a7ab4945,e4f2a2fb,7e1564ee,c375e50e,3516f555,e63da54e,28b70a99,5f35a1ac,3a25e384,6efafcbe,4e8f73fe,d84e095f,126524ac) -,S(b4cfb90b,168dc850,36559181,3d2d084a,9866512,9396f76,879280f2,38e4af3f,cfca0080,37006c35,7fd89c5a,1d444d19,5fd72d4,17fee670,e7b743dd,57f71b00) -,S(8e264996,e4e8a858,a1e32c59,b0df640b,a096401c,e77be6ee,ccd228d9,67dada3f,c9f5a8bc,89322e56,838c6d8d,859b6012,6d0a40f2,8377aca6,b5b4dacd,44931d0e) -,S(34ea02ae,49a4dce2,5ec2dc07,c71e3400,390b3054,83b8f30a,81021eef,5761ed99,b4b6f9ea,c41bf9d6,c4bba143,4639fd57,b8735d27,6098e374,d9324319,3def4c1b) -,S(bd391dfd,8569db85,b567c36c,5e6c378c,c152ad9b,c23d1fd6,1af23e29,543a56c3,9bf167d2,77e6bca3,a8d3cce7,61a36abe,91fcad0d,8d6ce398,877d3748,f2f13bf) -,S(67b295aa,440c8807,95369b98,c67d1d5c,1b9265af,58541994,7353c0bc,47ea8483,c94a0287,f2983c42,14f3baca,a8c5c791,d4d88fb7,30eb5b3d,4309f5cb,c5706f23) -,S(755e0335,284ad31b,5afb5775,fa191486,32b29c84,f38cafce,1b0b3b4f,2d073a42,c4506c75,c8cc96d2,8e31766e,a8ed1cf,531f4f7c,73888831,65f825d2,2b74c47d) -,S(e4b0cb3a,6149079b,5e47ccd,bfc4f351,64e575c9,20cd9827,a83f68e7,e5ba0a97,1604e71a,afa83b19,61bdd7ae,e4be5113,f9e9ddc2,29957255,cfe40341,9e45e5f4) -,S(3baca490,3147531c,905a2c73,277e4f39,c27ff6e5,41f6f2b,3ed4f730,3af0c4a,cf36fade,87b988ee,a4ccec6b,6b70ec01,d057173f,3aa7c79a,6bf4d412,d4bcafbc) -,S(229519e8,2a4dd2e7,ae77d713,21fbc8ff,f31191ee,6604823c,a6aefe03,19d06d95,a70e9af6,14ae7a1f,76224b8f,f5d1fc26,2e34707e,a6bfd26c,8cd7fba9,b5627e15) -,S(59364b22,4a53ed1a,7dbe9753,1b3a2600,2f700045,b0576733,8ee87a9b,2559dd54,b08cc507,70f5f3d8,851908b7,ed79ebc9,7f4f7342,61de0752,e14237c2,14eb5f6) -,S(d4b681cb,f3467c9c,649fd640,7991b4ac,3c66bf50,26ae93f9,e9b0238,9fb7c1f2,6df1a03f,4a5f00f4,8356bb9f,b23f1621,bb18a8e0,5afac4ce,4edbb01f,99a27000) -,S(49784426,fb036d23,a289f4f5,b3b92535,76da111f,ffcefdb6,a4163e55,2c56bc,76de5ca2,16ce703c,6a62ea4c,a0f7ae07,3744a22d,6db67389,9b0e93ff,a69e2a9d) -,S(5b213b9d,3f84b248,a98fe326,929b94a9,7bf78521,106a83fc,adba632c,8ed4892f,8eec203e,d015749f,f01402b1,722214d2,b58af86a,95384ae1,c39a7780,5623a204) -,S(6bb55cfb,9e3f5468,966711b8,6343e4af,6e372d04,ee7f570c,6a12005d,628959ef,75359562,9d633c9f,c2432ad5,f4c9f00,c6f54005,cdffaf82,438e3e58,70d14154) -,S(d760efaa,3a9e5c7a,967174a4,705baafe,d230dadb,4c957cf0,c025ab55,4b2eeb43,c019790a,b1b8498b,58daa784,ba02b7b5,672ba2b6,13d312cb,b4563f6f,e26675ce) -,S(f8be7bdc,6a361b6b,2844c60b,af7fec1a,216d75f6,96418734,337f9ccb,ae9117c0,df66b665,21e3dccf,639a323,5d773c21,4364062f,c5260323,3007e2cc,457d783a) -,S(6bbd2558,84348c88,c75a8155,6529be50,93b06a4,885c5d32,f1047357,a11434a2,842f9093,fd41b2a2,153727ae,ca2cbf00,a494ab7b,eef1a2cd,8696e972,1b1491d1) -,S(e692623d,cda3bde3,d32c1c01,f480d21f,9ccf8f1c,416a7dd5,17f1aab,12d3f3c6,30dab6f8,71f4c6d4,c768e086,fd6287ad,3fd000bc,3b04aa70,35cf441d,44764b89) -,S(86dbfe13,5db905ef,9ec7483c,6f51b75a,71726a1a,27e5131,8d6c0b2c,b0b933c2,371f23bd,45c46d3c,18056f23,10ab6afa,1259c88a,3a55f8ce,cecaea71,aea083a0) -,S(7ee329d5,9c625a92,594e620,4cb48559,458514f8,da94c7ba,fd2a4835,a4f10239,80a58a2b,e17f32da,dc80038c,7ed57de4,c7c561c6,69bf6786,57ee72ae,dd2bef04) -,S(e16a922b,8255d2c9,6ef776b,cda14285,b1cad5f7,62f75465,f8c82695,cf1065c2,44bc0e38,df9ce403,a927cb01,849e166e,6838468d,c7a8bd4e,6ec3fbbe,1f3465bd) -,S(5311e064,23145aa3,10737d38,41adf49b,988c1ca8,e8a705ca,3ca67f98,f756fe87,21c3f6ef,73bcca3a,c376e20f,dec775af,e22e708e,7e500c24,23114b4c,84ea8678) -,S(c09eda1d,dad1ca36,a9aaefdc,d16c5f50,a6ae499f,2cdefa2e,e5b61ab6,69f7fdf3,2220cbe5,bc279362,c5506404,e1df076,52624966,e3222b7a,62a1f7f9,faf00500) -,S(8888e104,18fb5c16,fc3c2b7e,b9ea06c1,da2df71f,c647b989,e71662a1,731628b4,7444a776,fa8f5bbe,959c71e2,c919b761,a2f8fdcb,5e66e5b,65e561e0,928e2d73) -,S(5c70258c,c1030231,d897c9a9,199df5b5,8b920f59,18141ece,d84bbcb8,b9b6c243,d627669a,e3dbb6d8,57d65a42,ec53bdf1,c688492,d189b1b8,67b75c3,f003ff90) -,S(eb58739b,878ea9f6,74b16f8a,406e7135,1ef06377,d9be32e8,1f657648,60e35ae0,752ae84c,8db0c7f4,e956d2b4,5750a5ef,24ea454,8f275f0,52b59ead,e3405ab5) -,S(996af698,ef26245e,35e4845a,dbf9c45d,6fec5564,c1fab0b4,8ac78f06,9840e0e7,a86b564c,ee788008,bbb04ee,e3d66c42,3c6910e7,7988aa54,420f3a4d,3137a1b5) -,S(bd03f2ea,a505bdd,7f39915,23f3e3b7,7532335a,6b5a11a1,4e303542,c00b8f4b,345f765f,cad902c4,56211eb0,bbe520ad,aacf55d9,e9c67787,aa02f18d,ccd88ea) -,S(8480c77f,3dd59c6,329c221b,ed8473e0,8cb0446d,c4e9bc6b,f2dba8d1,7ddf0f1,b055a135,a224f1e2,965cff1,a4f0d764,fed265bb,c644c696,2f3570d1,9af6e360) -,S(f46b6845,fa45e8c4,576b7c74,cd1a308e,f1adeedc,1d539d21,1158318c,ebd4c584,e1ed2665,34a14e05,c1ecf136,8cf8d6bf,fd9f0258,a5f0a53c,8abb00a3,e953c425) -,S(596db19c,38d91452,ad238f05,453bb773,9883df63,a0b545e2,47e5947c,d9f52a2e,bcb35b45,b172aeff,9e4fc5d1,714d6743,46bb4073,6f571291,e6575d34,f8b0d929) -,S(4cfbd998,f9544921,e5f1658d,e3ee95c6,df85b3f9,309f7a85,f6e4d08b,7e535497,ccd54e2e,437e4aff,7fc2ef17,3bed5ce6,b7d6e34b,4b386f36,72140d72,ceba71e9) -,S(c3f056d2,357ffe13,4403cee,6dd5ba3a,a7d2d0d,91d83f25,cb2cee44,34e57f94,1c31cee1,595b3682,fd85840e,312a61e4,40cbbf68,55418b30,bd6b24ab,c3bbf7b) -,S(e272370b,82ffc486,53274eb8,898409c5,9338e024,202be5e7,e18b5ec5,7f824680,d2f4e6c,619f0d,71e38990,f4e52881,de27ee31,ff7ad9cb,11a7f735,80a546cb) -,S(81537bc4,6a5fe897,827aeba4,6e66d576,6cd05a35,cd3fe1cd,9c06a2d7,194be59f,6706c254,125be3c5,92ad55f,6fa6289,4298f23f,2f4f397f,3bc84f50,79bcb8ae) -,S(50e161e2,6bc89d2c,816030ad,45559a3b,49c8606c,b28b6307,6ac6a051,9226d2b2,98478bc6,3f8d6be9,2db02910,67e5e359,e865d046,a5dd853a,fccb7592,72985c67) -,S(76ce7272,fcff02f9,bfc355eb,24286fab,88ba08ad,b15e099,22724b84,315be56,88f98fe7,62e37fdb,b72c1526,59528cdc,fc4c4203,c465e772,38dc8618,78a5a14d) -,S(77935c1,3a7f5f47,13098101,6e10ec54,d5ca10eb,492d4025,365d5265,ef7e6ebb,3c15e7c9,cf230340,44444126,5e74456a,4f3b72dd,7aff0ac1,aa76c67b,ce77dd0a) -,S(b37c3ecf,5813b5a5,2f52fc4,42049653,991d9241,e8677d2a,f9779fda,43c7a255,4361c742,c070b356,387fef42,1a9cdf79,58dd47a0,b7c9add5,57fa425d,626a1786) -,S(90c64aa3,28d43534,271e2f37,3460d8af,d17f9585,516b909a,6a7bea2f,1b12d2c6,79394191,a37a451f,e439e538,5e876c2d,ac397f0e,dfe29114,d14b9363,b76823c4) -,S(a314f637,2362ef7c,c4bec6a7,9396c318,568d9f05,9b6ca38a,c5f56090,c33e5e5e,b3a401e4,f7741130,95179507,2ce3b0e,53d2f51,f2dcaa9,d289e25a,8de01519) -,S(15c25f4e,80a7de90,8c49fc7b,649afd24,4c5a4be4,dfc15b2f,70099f73,6ad003dd,4aa9fb98,39855fca,c9f8bb26,b6322c95,e5d7adae,5aca9bf6,de073949,eb364b86) -,S(445e6d34,90f4ce76,22b6713f,584065a5,e0998d47,1b7603a,2527ed85,5d67d7a0,ecf994bd,7ba618b7,6eaca0,b852e0eb,be7b7f86,70d028e3,f52d1b2,846ce8ea) -,S(def695be,1ded66c3,650e9918,e942e4c,bd420fab,3a4708c2,43ab4e3f,1bf2101b,63569e13,532bf299,a0cf8d0e,a4addffc,1e782a1e,98a2f7c0,e0b64f50,8dd0afc5) -,S(eb364f1b,89938b48,2d32271,551f9529,5013185e,3ee2b534,bf01a288,9a534a88,9e6091fa,b439d0,d96f6a9d,cb468573,881234c1,6bbf4c50,32a6c950,99e6e6c1) -,S(7efe80e6,5c0134b8,49b6c58c,7d4c54ac,873e43fd,1b47f9d2,1d33f9c8,ee26646b,5411262d,63357cc8,d8280243,41d1767f,c25a0972,4c8c7a7f,3ddf6701,d12478e7) -,S(5f412876,3774e9de,6f2f25d8,a1d98de9,edf959a8,884643a4,fa18ac7a,26d6308,d3f6eff0,e336d4f5,abe35a12,4c47ed4e,5dbbe6d8,7d563fb1,8ea89242,aa454411) -,S(c63e3b34,bafd384b,2b60328b,4aee3a28,c7b3ed30,8a7cde45,87aa6c75,6c49c2dd,724fbbfc,11d05623,a5cb449e,a2f9f65f,a3de167a,a811bfcb,6ab9c3d0,3b123ad7) -,S(cc92795e,a0be5e79,757a86b5,147429eb,ca7a7c7,d51a8d3c,93650178,4f6ba5b5,92053ab3,db369d61,3af1093f,50829c73,4618c1d3,610ebc57,420d2824,935ae2ff) -,S(ba73d310,b5170cd1,57bbe14,63bfe944,ce7cea80,1b1aedb2,da3db11d,f1c7ea5c,4114e55,15806ca6,323edc6b,f0b75a92,834c72ff,9579d1f2,27fdadd6,d773c577) -,S(6047bc6,fd3a1c7b,9a36036a,94139542,7d9432c0,f652259e,1d52d709,e5088b22,bb119bf4,5d8ac9bb,1a918e6b,95cdf23e,6e2ccbf0,171579f7,ecfc9126,6d236b8a) -,S(a0600a7c,484559cf,3da255c4,935d2d97,1628fe8a,e75b88bb,1f3c4eca,e68f78d5,a439ac58,42bc6ee8,be096973,d87598da,349929c6,92e37852,e57ac941,eedef402) -,S(bfdef77e,1efac235,c1c49f04,290f89aa,c2e4632c,85f40481,dfdf5c59,d479e2a,e6e451cf,d76433ab,1de85511,9abaa5c7,8e4499a5,fa48ad77,f098c825,206dc7fc) -,S(81ff778c,373975,fb041cf8,ce4bc337,e2c977f2,d6bb2c61,9122240b,8e21234,3fc02add,e92c9928,e94e0ad0,218d6204,d71ef295,4c32227d,96b30b5b,9a61f640) -,S(84c4653c,d1af54f3,fc59dab4,5bbaa470,48f8eb13,4afc8f5b,60a8974a,cbf03933,98ff808b,a4682139,68b73ecb,67fe0a32,85dace7a,19d300dd,bd517e3d,b04ddba9) -,S(9d7ed86a,69f39ecd,c448de07,55197029,f81ee886,7c9a61b9,62d13eb3,abce35ae,d9b27e39,41c6bd1d,87dab6e9,32e8ba57,1dcd2c58,67177ce8,e7ef0fdc,668fccd5) -,S(540b7fe1,ee263e6b,3610bb96,1071d817,b9cdd162,77aaf28,87e7e5fd,df72f5b5,6638015d,591305c1,7a598a44,ba6871cb,8d1d3628,3ea25c5c,846bab2b,cd910340) -,S(4799c5ec,f1fb2112,f479abab,217ed0dc,e936c6bd,14215eee,6bbbb34f,d811cbe0,abfdeb73,4ac738cf,f607cd93,de58c0a3,237201eb,da47a808,3bccaee6,da5c5515) -,S(70a58362,b360c280,626a8698,7e4f2aa1,abdc9f8,f0b8c216,bb88b0cc,133c2312,5e37daac,d2835f3,1d924659,e51858ab,68e3a874,947360eb,c520767f,ce4d46d0) -,S(f345a0ca,857102b6,e225dfc5,7ae1cbbb,dd5c2737,116adbd8,b3d1f74,7d132b01,16fcaf2d,f7cae2ec,ef25da7b,3d51afd2,8f5e9920,5c0d74f0,c1e7b360,17eb2fb8) -,S(c3f4282b,29f253d4,fae8deb7,941484e3,9d2555d3,f96889b4,551e7d8a,eb2a209d,fc562248,8a6e83f1,6bb1530d,2a35629d,b25c8280,2eea7057,d22d109d,4263ac1d) -,S(5542218f,606e7cf3,9cf646a1,3677b0ed,4ff61aac,1dcea3f5,da5dd4a7,d4727632,f1bce63e,a11d5176,f47e576f,66817f45,4b51840b,a79695e6,3a1a1cd6,fb6c07db) -,S(65e81ed2,7d6b839e,5c3829f9,24beda63,98264de8,b2223479,43881582,4d124b35,2a17e09c,e4dd6e6a,32d85d71,e6cc2378,b53b9356,ee5790f6,8fc3040c,e6b6179f) -,S(5066b022,e43a5f83,c4290064,9e2b611e,750a5ded,7c89b8f5,892126f1,e112edf3,381e92b3,e407c6c5,d1c0ab40,6fbe1a99,57643da9,a2118cb1,3b8c6243,9328d9e8) -,S(8df78ac5,c5ff1cc6,df1e1dfb,58ef889b,17886433,61bea73b,a805c3ae,a83e2373,dc668ddf,5b39eebb,7b692997,f22140c1,8347e14b,edb6d343,96017e09,d37ca4d3) -,S(426c1767,7d7b00ee,af8d7d30,1bb11cea,1cebfa58,fc54bf0f,de719937,fb484434,4fcfa5b9,ab7b71fd,560ecbfa,985db2f2,418465f7,cbf8acd8,fdd71af5,7f9519d8) -,S(4f7f0061,bb90e396,63f6aadf,70dd3312,f781b2a2,3867df3c,566e18f9,b4a511e1,1308473f,d8956b35,97d904c6,cf73c05c,fd7c075d,c83848b8,571e666d,dc44b3df) -,S(7393002d,d2e85925,3b23db69,6c140258,8272a847,d834982c,5b22b256,93685107,b61532fc,6706f7ad,78548e76,b334a836,c899a49c,46afa1f4,4579b5cd,27641528) -,S(c41dff65,e88e5c6f,fca3b0ab,6ae69bde,c4215194,cd7c57ca,fd9b38be,feab4e05,9a9ba27b,a0b7e217,d31340cb,acd8506,7f052d8b,f92a4be1,cf59fbe9,6241f0c9) -,S(f619dc9d,6dcc39d2,9155082c,2ed9bc60,99296a8a,982327f0,60fd6208,5765c518,87961d3e,2b850ffd,f080d5aa,cceb1912,120ddbc3,4e0ad8d7,96e74afc,aa4871fd) -,S(6becdd5d,f02a7bbc,d1cc811c,fb83901c,46aa8207,35e81c29,a8d4d4ea,3f5cf99a,a45f7dd1,8949f842,2905c7ee,836004a6,5bb106d2,fb623d68,c2690c14,f181e39d) -,S(cd2390,db1e7c53,f424a893,c2529660,69a8f151,6f60722a,524578e3,e5427196,b817ed1b,457633ab,a3439454,6ed410cd,8140b9d2,e7e679b6,3322eae5,f3466e90) -,S(96cd9608,7f1cbcc9,b017ad2b,c7824285,4047dc3d,f98e7951,2fc09fbc,e3cd33ab,dfdb9090,c8a5ae70,13b8faa7,855554d7,3df381d7,88fd5569,d3a7ef7d,f729d625) -,S(99cd7508,5e9abb74,5fe03e3d,b100f2c5,2a43acc9,4127bd8f,83314baf,70d72b4a,19c98b68,2ded269a,57e50e3a,28b9cd65,344000ed,dac3d3e9,d8ac8370,662ee1c5) -,S(f53c2afa,647496ac,6c1220e1,4627c138,186286ef,b776449,55f9238,b39fdb20,1598c495,106a200,58fe1fd9,b29140e6,a93996d4,fe4cfdd6,74ec10f0,75badbd7) -,S(c127dad5,3b9457b9,51192c79,5793734a,d0a84671,ff6ba236,f53cc40f,769585f8,688e6264,da4e9d1e,fe66f5ab,db078c56,98696ef3,53b3bd42,c344b3f1,3d3ad744) -,S(882bc4c7,651634c,930384d1,3daf5a91,41508df3,2d34818a,e61bb65,40e92bd7,5c456414,430eece2,fc6e95b3,7700f608,9815f5cb,12a09ebe,8a87e370,85bcf255) -,S(4cbc141f,55c0b001,cfd934e4,dbbc2c2e,4b5dc68,72e3388f,2388e54c,e2a91bdc,1749d8e5,30d21894,221b2aa5,96541f1d,e700bbc1,e3427140,24f0a9b,9c0766b0) -,S(bff11777,6bb9bfd6,bbf872a1,3b9b6a62,32465cef,f16c3c75,441c39ea,2975528e,9e7412e4,ae492669,58dbdc9a,b7b1f4c5,d2edefc1,d4f0a483,27f2fd69,f992eb34) -,S(251416e5,887b294f,c752a1e2,3e991f11,90b8798b,11c97033,e470bfb5,b7bb6328,e6981dcf,15fb4b98,ac8a37da,267f1bb6,a2a38b86,3919d20f,72b5bc34,cb5e329c) -,S(bfe2490,569255d1,a62318c8,416e9114,66dec59a,bcca5df4,e64c2f48,46d050d4,f78bf673,577508c8,3846bd5a,312b9284,2283c47e,d4df7651,79d33bda,ba6eea54) -,S(e50d0a78,40779b75,fa121def,456865d9,3d7bb9c5,d566d790,58b1b56c,3fdc7b15,2f2688ee,4abcfa52,9424d4cd,eb40a8a6,a6de26b1,be8946f1,e4ba429b,5b32a6c8) -,S(b3a9d7ef,235df6ef,262e177d,19bd1121,167a056a,3957ffd2,a3d22d00,9a199bab,6a7adf,40ab5386,21fc3447,77c97416,66537460,44113c5b,a73455bd,9658753b) -,S(ec7277c4,20af5d48,3a6247d3,a1da7243,31c0e35a,85d6057d,55a3e526,bb7962bf,2dcd3e8c,5abc47d4,56bfcf,a8086889,89354e10,8188fb0b,c9ab4578,7b91d69d) -,S(91ed86a2,330ef91d,e085df2,a947c9de,f1284b8c,76d9b432,8dee9342,bd297242,fcc226b0,c46a36f3,ac56ec31,bf297360,8375f0f7,d248c669,f8b31ca9,9d056713) -,S(e2a09eb6,6e76b287,36c5824f,829afff2,439d973,e5be5b4,f3c55cea,e83bbda4,6b217b22,123bf3db,f35845f,315264c0,4a67ba18,a49abd08,6b2acc76,ca0b016c) -,S(78501449,bd76ff1f,58cdf2e9,203de4d8,3325ce45,1bf106d,2f474e91,bb0545c1,d0bbcc92,acbad044,218a830d,5f461332,cf488003,4b6f89fa,2f58b708,63aaa585) -,S(c3626c48,95df6e93,2c79d5d7,eac22ef1,d7679f1b,1df1259d,2be08aaf,7217d978,a594df74,250bcb50,dd9f294d,e7322b25,f72cf935,700856e3,c31fc5f,35e61b67) -,S(5c6e0358,ec09945a,c4240f22,3304f744,63269e16,c4f87dbb,99bbb744,bb4afaae,e6168dcb,d719ad05,8020dbc5,b03ec4c0,61b1fd87,d530913e,6df5d498,69e340d7) -,S(4a3fb364,d55fca64,4cc03c40,5a5956b8,a794718a,5b43cdf0,795e5d5d,5f79e7c0,4c4e0c11,5f88ef66,545280de,af9e3d59,3ff7d1ec,d8f20779,70ed84a7,8d660d28) -,S(fdc828e6,e305427d,c925de61,6f57e13f,5d0c8777,b538e511,49cdd304,1b022d05,de9e1037,db0dab0c,fedd8544,3b926a36,88e8bc54,7420b27,c65e2c6d,bbcb1662) -,S(6d70ad6c,375119a0,f4b2b65f,51257d7b,e73a8d69,ab944dcb,232b8fd8,e7021583,31de3a22,c8e8034a,d812a7d,234cad97,978aba7a,1c2996b7,aee623f5,858770e2) -,S(faa9dff,68f63fc5,7ca8c39d,8d950c2f,78a90317,c5d7f787,6ffa035,fcce8dc6,419b6c29,a7c02ea6,c8b7ed5b,c9b6fe89,1b3c705d,2ed2707f,3ef7995c,81a17de0) -,S(53d9472b,eb9a020,e84e10f0,1d5ed8c2,6219d24a,eab4cd67,dd30f084,8fa47a12,624f4c9c,64c02832,9b6ad395,dd51f960,41eeffc3,b3238764,57d21f85,d8c674ce) -,S(598daff5,aac2831e,21d5eff6,319e563e,3208ea18,e3ffe13f,2bf19444,73292f02,3db66869,2538e2f,e3689a41,dbb05504,bc86dabd,e033fc1,dbd7f84d,dd4e18c2) -,S(eefd321d,41fe6468,a7766276,5932449a,d3956209,c4c6a548,c4392db9,b4e39a97,6a372971,d5515d4e,c691b3cf,e73ccf6a,a491df97,570c9f52,3f29b108,c626c319) -,S(5a3a8225,49ecb78a,9c5aa12a,49e02c5e,10c168ac,e053f85f,30921724,96177ee4,482a65fb,f57726d9,d4ad61c6,75cdd5c3,25b6e59,899366a5,3ddbf239,96016448) -,S(e21f7d4d,b2343eb0,1d23d1c,5ec76db9,89e1e624,2fabc41a,b204ca64,838eee55,fb64c87d,ba7c54d6,f1d68d7f,a49d50b1,bd79d699,a75227e8,4363ed30,430b2605) -,S(fd688c92,f80983b8,496689ae,fcc0820a,a3d91fb2,aa4d599a,f48de5b0,98ed491e,7f946da9,9169612b,dd6ad8b5,d686052e,3ff25610,21432c92,f8728187,29e860e7) -,S(65594f34,947f182,bcd1703c,dbb1ddbc,4bf59b2c,2fff23f4,1d363631,cd54af0f,e8d98a21,a603eabe,cc1a1b83,9ccd553e,fa5eb258,5dc94e10,d134f40a,63b5bb1b) -,S(4f47f3b9,8bcf3917,464c07cd,be99d2ea,adf31166,8199324e,d120d087,e14789e7,279da4fb,d718e578,b10d316b,9994dd05,ffa05431,f85db2d6,6d4327d3,68aac28a) -,S(32cd8b52,c027e4e1,7991ccf5,6460f3dc,1d2ea6be,6434067d,bd4880e8,a09196dc,1d3066d3,76961716,1882da20,e467e035,4ad84041,f391a042,9e94d8a0,5d89807) -,S(c454b400,c7946f9b,b35003a7,c51e8037,dd03fcda,f0a19b14,f8daba3f,310d8bec,dffa7652,86aecb65,2744c9e0,21229687,1c305d91,6279b414,1ca1a,acc021b9) -,S(151b7159,4fce7438,2ac83025,6d98abbb,6ca309b6,64ef0235,53495342,34f7b4f6,fc61aa0d,722156b5,dd7ffd24,38100589,1bf236be,a41aff71,c3f1964f,15978a28) -,S(59716aa9,6b60ebde,848783d1,a686e9ab,e337b87d,104aa3f9,4cc7af46,ea8b8710,2e3062d4,a7d290eb,f53ee38,31dd8e80,354fd671,62a01a4c,73c57fb3,4582d345) -,S(81838542,7622429e,832e7a50,b1a670e1,2a626c3b,97cc69f7,abaadd5a,44a92395,18a88d63,d42e3ba2,af4b6c36,9971b0b9,35363e5d,77417116,b58de2d,8b6afb42) -,S(c95cf1fc,af7dd741,479a54ca,40a0e264,a989f0da,99b3a1b3,c4f67284,c8ae2a75,14b32e26,99662bee,51ad8534,fca1925a,a835cd00,9807c5e6,915b8283,63872f76) -,S(9362c939,ea51a649,2ae2dc2b,c01e4bfe,ccdf4612,97932668,2435bf44,e9c6ea1f,944684c5,2cb534b1,4871f48,41e889ad,933299bb,474b392d,a1e85ffc,5763c2e0) -,S(8852fd51,1e5f5e93,c6c3c7b8,4b0544af,cdb7d0b8,497d4bfc,90cb7322,28a77040,b0ea5bb9,c338a6de,7333b4cf,ac29f997,36c248,405facd2,6ce438f9,cb997a13) -,S(59105318,491ab266,2fb94506,532ed81b,74c8f82e,a13581ae,ef6c0c77,80696ad9,3417191f,bdcc1dd1,43323ff8,6e6051ee,921dcf69,9eda369a,afec66ff,a06097ec) -,S(c78bb701,8e96901d,3f13681e,ecc24df9,65b124b6,43f72904,ddf00ce8,bd28a127,ef07ce8,1b9c1cf1,26108dd5,f96ff86b,e0d49bdf,ad3d518b,1004b3c9,4c79bea0) -,S(9eb55ba5,2b5d11ae,3d419ede,5a5480b6,c2aee921,6f9aeb4a,96e51934,e8e4c11d,50094963,25b94022,2642ca89,1fb4697a,5e643e50,19670934,99937432,f020eaf) -,S(79ca2986,d40c7786,dc4d3e6f,71c33233,ad0b65fd,96822383,c11949f1,ab42f5e1,275db48a,fab1f0db,188e1298,4b391ce,6872e216,85c04c0f,3e62d42,d1e6d310) -,S(a2cf65b8,fe2a7abc,b78bcdf3,f25db18f,432ada89,1ce7d99f,faccefe8,e9673463,418e9be4,f6a1dce9,200823f0,5a6a0e31,7924a0f9,44c18b2f,1602a2fd,1ef13a72) -,S(7f6881f3,9f4684d1,3bf35c4b,c350b64b,28eb3c44,2adf05fb,c5e2c1e0,307fef19,20ac47a9,b954e805,db6fa20a,4e1a04f3,36c058f2,1946aff4,d4c24f63,6bd608eb) -,S(abf40dcf,72704e6c,65502d17,aa384bca,5834a802,62ec0de2,fd46ca2d,d9316ef,f605192b,a8c56b66,f3bdb35d,9c1df4d9,94662b41,85e8e6c2,9fde9d27,45039564) -,S(4fbb0d5d,ada948f6,2877c665,9cfe5f57,c6d5be5c,8cbb7bee,71cc575a,f4c92989,d2290911,45c718d5,243e1ef,92b8f7bc,2c77af95,f8666ce8,15900462,35d1c3dc) -,S(6c62710d,d0ce5eb9,5196e202,7c3c1d12,5a25f329,878b1f38,fa883146,b8ccffa4,c70ee1dc,174a6a4b,908b54d,69c94ec,5829bc8d,f6513c82,b0fc02ce,f566dde7) -,S(83ac175e,e220c800,a40adc87,df8450a3,963015a5,2c9e9497,602f930c,37af6c12,b7dd932,95601178,f6db7b5f,98046d7c,e42371ab,34e5f11,31f7cb31,59d37994) -,S(c823727a,348e275b,f52c18b1,43653c3f,8f0a5c0a,e8f48432,a8016486,ec3674b5,760237f6,2222cf21,fe1813da,4cfe9437,edca8286,cf3be63b,5bb05560,fa71235f) -,S(388b02ce,506784cf,2ec7e315,e765f126,23f764a,7d1ef836,fe360355,cb3f0517,ed0998cc,9069f336,c938b639,d6a74e8c,672a7d2a,2fe1dd1a,d7e18969,e7e57b20) -,S(517d4da9,e25f9eaf,7ab6efcd,cc00e6eb,7bfb975d,e8287b2b,d7d15914,4b7a981a,2ea7196b,a14b60c0,78444a20,2b67fedf,8fd119a3,7a39738b,17694cd4,c0dd712d) -,S(eac89275,54b0f71c,4ee80260,4945c5e5,578fdd50,ad68c478,2295670a,80432bee,dfe1ac53,dc9e18b7,1a930e73,cea36af2,8c8326eb,3615f858,fa1d3884,446f59a7) -,S(f77a0877,e7ffd2e2,cba9f0b2,c419e886,73711125,7cee4480,f6529851,6013ce29,fb245db7,29acfa2c,145011f4,42c9d480,5fcb0be8,b7f27dd9,9d532f6,aee2d57c) -,S(747d96af,94b3ae3,4cbcec25,fe8f4b74,e8d2077e,31ca2520,6d0d5613,3a49bd7e,b13d780b,8d322848,de5463af,3dc9c6fb,4cee70e0,da4731db,14916252,4b6d8d4f) -,S(9bf6ae06,6db68c50,4ef9b1cd,6d123efe,1d8608c5,3a1a2276,f1f44493,f8b5bf72,5b0080f7,694a756,f306714,aa9d8b3e,617b7c5e,84d862be,470df13d,e79c8994) -,S(91d0275d,e99c876b,d6de2cd,481fd72,13d9f6f0,e41c3444,4790dd80,cbc72e72,b12126c0,8b03b040,60183216,d1468246,d32d834c,57e687a8,9ce42ae4,d4eba7bf) -,S(e3cd4480,6585252c,8eb09442,74222016,5ed4cb90,462310ac,ddc769b1,b9a111e2,d8821a94,f1bd3def,434557ed,4739d625,c74548d1,44bd370b,180fc4d9,ee04afa0) -,S(3502269d,e8a68ef1,a0d74a0e,1423de94,99b84d3a,1fbef636,d9f38801,ed00d64a,9c4b6259,8c1bb627,449800ba,d9e93c7a,265114eb,99f9b5,7bca5b6a,72e3b302) -,S(244e51da,a54a3c4d,69f7a53e,6ef82bf4,7907bb40,7713f5e8,84694641,1daa2ec3,61f00ad5,f30928ca,a20cd38e,5af6b3fa,afd4def2,f8433609,4f08e82e,d46a0320) -,S(4f00186b,5d6f0420,88ac1221,a13e3aa4,60190cc2,2bd8fc26,4df81f44,1e508032,fcf58149,b8ab94c,67b30d73,4a3a5835,c7f89e44,6aa8d2d9,291c5f6c,b17b2e3c) -,S(10a96b69,2f522f4d,58d1c9af,463ae371,73e6f72d,93aaf756,6267b3d2,f62a579c,fcc7a656,c9d72dcc,1540a638,51328135,85d3a0f4,ba5242f,f5aa35f1,88ee3070) -,S(ee66c2c,2b19242f,4d7a22bd,df36fe3b,b5c151f7,1dd8a81,93fbae52,23064f9d,9d4f46db,7639d9a6,95d51d1e,44b08d6b,4791e443,744042e5,cc9e3933,cc27aefc) -,S(872337c4,e34a3dbb,f4b274a0,a47c1398,f78ce842,fb11b994,b550e9e2,e21934c2,aa8a7840,d6dbf62e,d91577c8,8b8c6baa,69e01f94,5294e3fe,4ccbadc4,c1d64221) -,S(e2eeb213,bfeb413a,9093be1a,7f75820e,5f48dc34,8515ef1c,7026c116,9be224a6,a49c846e,9132e039,9d66da39,57cebf1d,2e673831,3a89f682,c28d2230,1792d36b) -,S(fe264a9d,63932bdd,5cd4629a,dda37c9a,8d2bbb1f,5809d333,80a561a9,66af74c5,543b7920,c6c27b7a,515b5adc,b8d144ae,64118447,dee21638,1d6cfd2,5627fc53) -,S(13806a30,2d32152f,a1ee8060,67b07cc8,fce1e67f,16f21859,e7b60de1,37debf51,ffcb1150,7be5c2a8,90237923,5335b575,4cd83460,423ece53,18be988,c7e5e978) -,S(db67e361,f9d91cff,1d8b99db,b7bd2584,f1b91cfd,77473802,f603ee9d,debf4dfe,6407a133,7604fbb9,35fbdfb,9fd6e2a4,ea6d8f28,a63e7524,172cebfb,d3331e2b) -,S(606d4f47,d1d4cc58,3e30f214,e1ee57cd,98e68b6c,91c852ad,cad6c32c,989d8bd8,81911891,8a074dd6,ebfb95b1,c97b4fd8,5ef0887c,15ae5e88,ec6e97b9,cba46701) -,S(51d60942,e93fbcf7,e230c116,77528c0d,3b63f7ee,64c1da65,692aa91c,af482ecc,b82db22e,3f104807,6338369f,d77dc11,d982296d,e630af66,36cedecc,108ae433) -,S(2553006b,b8474473,29108ffd,cfd9c91d,22b7ad2b,6a0e7bb,72f98a0b,770da376,6173583e,e6b238be,ff3cd6cc,9bba1b48,d89dcf6f,481868dc,773eea98,59ffa871) -,S(52e35836,fb0a1c1f,efb092fe,3c95bb32,26bf9aaf,50fd1ddf,29ef0ba4,b100d794,639078d1,cd1cd22d,135ca950,d754d3f2,bcd11a95,91abb6c7,c4a5177c,53adc86f) -,S(332e02e5,5c089c84,82ee9863,a4dff4ea,b01a7a83,4747ff83,512fb567,7a8ee3d,b1edbfc7,9c1f9264,10c4cc3b,8919b4f4,e89bad8f,34135af5,f16b1c66,9a28b87c) -,S(d9113a61,7d5a4a75,2080931a,84bad37b,ce2f907b,cc05adf4,16750e8b,8951435a,ab1f66e5,8d3a5887,2f664b56,6c2468df,f9d4d76c,a73111bf,57e10d1a,f7df7aab) -,S(71999a85,799030fa,b0575523,fab4111c,f4b60351,e03f8703,1f5a852a,f22131d4,eb171070,d6124255,9adbd82,565c8dd3,fba6b8c0,df939501,4223b2e6,148668f4) -,S(a9436d74,a39c7193,368ccbf0,d24098be,41309668,87ebb8d8,4213e0b3,436c23cd,7b93ba5d,e2ad9b42,ac45ac85,43f7ae59,7300e745,8fed1359,bc392015,540e7a19) -,S(f6288f25,57359179,cd3659c6,1cceef6d,c5a69631,174f63ac,115633ef,83530b2a,d54f0f2d,51a365dc,7ba8b630,67ae663c,b4102e2c,59cfa616,b8878483,6ca85722) -,S(bf685c41,863c9fee,dff2fdd4,ba47d726,1f0fcb6f,b0432a8a,3b7c4f6d,6f52700a,336b1d57,43ca6d28,52e20cd6,ab276441,61b2ed82,ea4e0051,d88ea92c,a66828c7) -,S(672eaa18,1009f3da,3fe74eb7,4b479e24,4b73b54f,206f7342,eaa865ee,f945b00f,3f056594,a113cd63,810adf1d,b76efaad,babcd42d,347282c2,ce66ad54,37cb89d0) -,S(299deede,3b6722e4,4c5e7600,214f85aa,4dd70ac9,df75cfe6,c020ec58,c8c859f7,92ecac9e,4a6326a7,8b01c0e3,6466723a,3d00593b,6597b6e,e16924cd,60105137) -,S(e4268a68,7e6c26b9,2cec18b6,8581bf03,8b25544e,2040d505,7b9823b8,b01c07d5,35d1c370,95a9cc03,f91db5d4,250a904f,b9f9daed,9388b5cf,d6a3699e,b03c30c0) -,S(7164e9,bfa6ade,a42bcc27,db38cf5b,fe908499,eda21bf2,27063fb6,369b1ae1,a2367f94,fe683e07,1cb7ffb4,287cce88,b11336ca,98e6769e,178262a6,b9103d9b) -,S(84d8d32,a4be7402,1c94d3b6,c0913724,b2db26fd,862fee1b,c467a37f,b98b299a,46b92145,46603cb9,1cd5ff05,a237079a,e290b496,19d868f2,8143d660,94e61cf5) -,S(60372ba5,d0eaaacb,c1445979,74a0553a,6e63c4d,15001b76,39f5d05b,84f626dc,8fab368b,c4d011aa,edf7d98c,2e6a0359,5737b1bd,bf701060,d30c9f0e,a8e8c847) -,S(453c17f5,5364f812,a7da0f75,d7c074b1,81cc0901,a938447c,df55ba92,a7decfbc,53d465f2,6d3d86b,a76ad1e6,f147d208,474989a4,64ceb6ce,79972cc9,3e2e2c3a) -,S(cf1f79b4,b765a894,2b967271,85d0c2c4,dfab4c4d,d679693a,4b35b343,c411cdc4,b89916ea,4ea34abc,63b9292f,591b5c8d,5ce802df,9d4f2be,275ef244,7e1ece) -,S(74b07994,b7fe3a27,eff2f9aa,72f8746a,299f9eb7,81f09b15,f3ae595f,a0c4ac37,5464345,f4873a6e,9f4cb569,acc8e551,a9acff9e,5e0a92ca,e2c3f800,1888f905) -,S(f9de1544,89b7a06e,40115de1,fcb7897a,f6bb2b91,5a1e8971,8d5d5ee8,68bab74f,789b5c55,2b352db3,4345ca30,328f542b,ad22e5cf,d98e5b8b,e85646e8,d47a0e6e) -,S(c011f3d1,897cfe72,827d2cc7,c04a6aa7,496273ac,11f0df10,27ab4d69,aa745c5d,8e31fcd8,3842ffbb,a600e771,feb0cc2b,1fb257ab,7c19fe61,67802313,cdec95ad) -,S(16567ed2,4ea1cb2a,15418d66,c70c0587,386201f3,4dde86b,82f687f,95229648,fc4aa805,45366f8c,3ee336f4,51397e3,7f78188e,b6dff3ce,d80c7e7b,6d9f7cf2) -,S(8cd33d56,9acd3607,979b3c17,bf5c2175,ef6f3428,7a25c18e,89a1b38c,979d50e,f4312cbf,f301e942,61b7da0e,cadda424,336b1201,82ad73c3,c907be8d,840f8614) -,S(646e22ba,39927176,4e1df1b3,16767718,79d7a16d,587b9e47,5232a331,42ea2a5b,55378afe,5f29feb3,2a3152ba,4d83305e,f77b1025,79154aeb,7bb8b8ef,c5958576) -,S(2699d984,462e1fa6,208a833b,8af2e32f,58cf2d02,7707b4fe,2e3f888d,82e8e2fc,ed6c46a5,c5121755,5f236a62,21399a40,5fd87fca,f4cc6603,fffb440d,54b888c4) -,S(be4b6631,3fd3e2fb,163530c7,2fa4a41b,e36d04b2,638315a9,1d07de72,c4ced54c,a7a71077,83a27b72,4e8aa644,a88ea181,c770cf6f,489829c6,6660c44d,45fd2ddd) -,S(1f2ad69d,a1438b51,fe02a47,9cf865e2,18bdbe01,259b0818,1b6e7e6b,762a72a6,d4da99d5,7aa328df,3c587a45,2d756bae,fc09c626,fa5516bb,c8781b9e,b1ecd29b) -,S(b1adb241,721a1622,35540622,f8e84291,e1c2702d,70cad33a,89aa3806,f7acda43,e6cd9324,12542fc4,25b8f16c,c0820f3f,26f33e11,1ba0ca5c,b5aeaa54,1fa3d9c6) -,S(b604e2,f06df266,1163604f,2a1941ff,4d6991fb,84796c40,ccbe74e4,cf68e207,306936ee,e887427e,6005b265,38af5ca,53b3cab9,a3aebaaa,96556c46,7db96e88) -,S(afb935fa,1e30617a,9b4f26b2,e7b150b3,f33566b4,7b5b4a7d,6223fe3,9c0dced3,83624f43,66dd82d6,8e4cd94c,464b6322,db0b1774,9fa1125b,a0944503,b0c63b0d) -,S(5cc7252,a08ff892,93022eca,b56a5e9,cd2eb4c4,71161d15,5d7a5113,8b12d235,c272b6cc,42461529,b31943fd,fcb51a59,7a0eaec3,ae8c2754,827fe1ce,a182bcc4) -,S(6c17c206,7c72a1ba,410f2446,e4ae2012,6eccaf88,aa4fea14,522a7607,143c1122,7172af08,2adea428,2f6a3cbc,7946db2f,c0170975,50ad8ee7,f4c514e5,dcd693eb) -,S(fd82afcf,c55d226b,274cd62f,385e882f,716210f,9a14be15,baf7e17f,b98eac8,4aeac666,a1153851,6d66390e,6c7818d3,3de26fa9,3d234eb8,5e4d5b42,853eb3c1) -,S(3d0121e6,c758dc91,8ce3bbca,1884788b,20717075,1e80742c,49b202d3,c2f8012,ca6b47b,306cef6c,662bf21f,77bae3c4,25009561,72dfc630,e2b1a6da,e733413d) -,S(488306dd,3bf3bb5f,24160f1d,67b8c053,bceb8da3,cb1b05ae,7ae9fa72,e3f7b0c2,2356a8e6,77ae2f06,6135bd88,1fab5b4c,6aa57769,3e2d476a,1b2a4db7,fc6c27be) -,S(d7e91488,6786009e,eaf12d14,a23ec6e7,fe41e406,aca5a5b7,47010ee8,8441d6b2,c98389a9,143a8fdb,df4a67d8,7c05cd4d,fff75fae,845e7e62,26c61aff,3dc4dde6) -,S(873a2877,9c45280e,3d196725,5da756d0,ee5ac567,cbb7c52d,c8e654a7,ed78a1f1,9bb9672e,e76feae0,d52be301,983c182d,ec99b228,defb2166,5310a4ab,cae7eccd) -,S(410a7c98,85f531ab,46d99b26,b6fc2576,97723e4,bd9b9c57,6544542e,2cad2ff3,8bc9e686,4f139032,cd443148,4f43abd4,3234e3eb,3825a0a7,db8176be,cb5207cb) -,S(39269060,b38b4abb,107c2230,6f541353,d8627901,3399b368,8b650ad4,cbf99144,780c2949,aad303f,ef8fff3f,b9734551,b45639cd,9437935f,d93f7d95,bc9d1aa4) -,S(bbc52d26,36e861e1,3e593d4a,c6ad573a,e4698ede,f101b3e4,f4aaca54,325b9f9,4a311f44,9f16bfb6,4c5c554,5ba373e9,fc41b7ec,beadb4a6,a929cf0d,79f37922) -,S(bb74e659,5ed6d931,9716b8e6,120f0cb0,57dcce87,150cb26a,cbdf5b1c,f86ccbcd,9f2385a3,bb460cdb,8ec74db8,fc5e6014,f4310665,c5b69e1b,cf96203,1afe085) -,S(67e64d65,badbd97a,bb204cb4,f9009f5a,973700d8,34f6b6a5,395fbaa2,c6eb0672,a122f76f,67490b28,9977d730,df544f7,d725dfd0,93135ba4,4bb348c9,e4dd3303) -,S(dbd294ba,e0775f43,f58ee677,6240eaca,b9b29ceb,92fc3354,de4d4b20,95548050,1987ba2e,3ce8ef0,5b71acbf,4c69f706,e2cb4d6f,354f0fc6,53a7a9b9,5dd1c115) -,S(45c946f3,93658d3e,589fdcbb,6895c97d,60352342,3a3676df,680b6bad,de6cee1,629c7238,db2cd3e5,29e5b30f,a8ba5629,dcbb1ccd,ada1eb22,294f98f0,4cae2d00) -,S(33ad0e14,44be7775,3fe47875,2688e384,2be7ae06,7d38e473,6b7dbe0,c106e14f,d89eed78,6518775e,1ef441d5,fe51c4d4,b2a1e377,eb1a4cf7,804c2e1a,5175f1ef) -,S(f9f78161,4cd463fb,6e358274,e47812b,4b0113d8,3f426aa7,85756c6f,b9e7853e,5eab09ab,51247c76,f87f592d,77e0870,238877dc,a47cf6b4,5fe72940,ff4469a2) -,S(ed3015a6,7a1fec82,f0f7a59c,45cb69ae,8aa0d883,39a05f,f6959c9d,b7d761c5,b7c94a9c,28389f1d,17bdf197,307411fe,1c395483,da8a097a,fb3b5fcf,e392e16d) -,S(301af330,de741ec5,61b71fc3,c5048a42,6b55d58f,800934f5,c59aa8f5,914092b0,3d3137d8,262d196d,872fe1f9,8acba295,fec02ee1,30aa4c19,8c888765,357b67e4) -,S(21e197a7,85953a90,226c1ab0,441e35a0,fd8444b1,92c0e5ad,65588063,f40c1246,6811f94f,18a9569d,4df2ffa7,fd8d75ff,5f66ad1e,62da2a60,c0084381,4437a2c4) -,S(325fcc8c,27804b7c,e73d6687,70db7f5d,3ed4b6ac,feb04003,c61d6262,8fd41385,2110e8d7,24e3a03f,46183536,b208b595,8586202c,2e69b954,d3ee1500,21ae7d8) -,S(48597aad,ec69eb0d,90f60e6a,abf83129,1de759f5,eff24d81,8677248b,ea87d945,c3fd850a,cddc2597,499be90c,24e249b,328728ff,5443fbd5,6515a6f0,4111775d) -,S(58648599,8ac44bd2,e937796,d8dfa60d,c56d94c4,d53cfb77,ee0e380a,53ab8f76,2f47f278,6a285454,475d3c9,ffe9ee44,a93e15cb,b17772ec,67a30943,d3191110) -,S(bd2761c5,722288b1,409aa7a5,db7690d2,73dba76a,3847d94e,3e3d3a7f,2dd35597,42590713,6ab6745d,5e573412,663d4d93,29c4a284,4430899d,68e5ca64,197ad58c) -,S(fac9260f,1d420371,7e468769,1af8c270,dada5d97,5ceda9f2,64deffe9,1990b52a,9ce17c1,ebe94ab4,e092d1d5,850194d1,7e6a87e6,7b283ba4,ba68640a,94193314) -,S(82e65b52,e4585ec1,4bc03591,249cf4bc,e5391f69,7b813175,b3b4b403,a64d6877,627e196b,42d327be,48526318,2dafb37e,222578a0,ccbcc443,7941eca4,a82ac893) -,S(b9473eb4,dd002597,464965e5,b6d95842,543cd14,e18c95d5,b45bb654,eedbd6da,1b6e80a5,377ba31f,b5b6fcac,633321e7,f6e5b2ad,4a54e143,e963effd,6805c3a9) -,S(31113d99,4caaea40,40182db0,17a880ac,64b183af,1746b820,2f29fbd0,d1bcc524,3f476b72,eeeb7c27,f9d04cba,71ac54aa,a25ec4ab,15d77e17,8544a651,653e83ad) -,S(d04adc5e,73e21fc1,8c3b047,4d34f8cd,1cdcebdc,5dabf14,e258af57,860157d2,b21150d6,ad94a07c,d11a81c7,b741a2f0,5cd6a5ae,aba194ce,b874bd19,bfb6c326) -,S(4e59356b,f280f51a,c492751b,3b3c7c2e,3fd1fb58,679b4fb5,5abeeb65,bce6ac2b,33a1ed9a,1d9c34c8,42b95e4a,108c7985,21c1f06,91f3716a,68fa5c5f,89dc73f) -,S(53d76685,9ddc778c,b4f719ad,55f74fa7,85d52300,65c06b1e,4aafc560,39ba3547,168b5451,29170fe2,c53abea9,68a25dcc,2719090b,e0814635,a1dc7267,9d83a01) -,S(7e9107a0,d2830362,7e53e06d,6e82efa8,b1a037a,328df546,a6d04c30,3037a63f,222d8b81,2a99860e,87fa24e0,aaab4ddb,b903cbe6,39c46cb6,3f2144d7,f8856489) -,S(6775b2d7,b23dc08a,beb65049,db8552f5,565a092f,fad86865,c17347e2,a744106b,a6f23c87,fb639e66,9830ed33,34c6dd42,6bab0e23,aadcff44,1d4c73d1,a61efda4) -,S(559885b6,a54fd0dc,b275662e,f66566e2,87a17219,e9c02f68,8c1cc8f5,6f814673,2ec87df5,917d1d7b,f217621e,82c31844,d2bb138b,bc35f873,5b52309a,baf800c1) -,S(6fb774c1,2971b620,b40a17ec,74dccc9a,8c711844,a44a3e4d,e8310d47,bda53428,68ab0f6,57b823e3,35df55d1,ed9632a8,f0825f67,8a05d5eb,9e115ea3,e43ff4e7) -,S(623c155c,2787396e,815ecfdb,5f03bdb7,282aeda1,7c9298f5,306ec10e,21dd0b90,69382be3,a4bae926,47252910,ad1ec62f,f4bbcde5,6259cb52,10ff2158,6b111f66) -,S(c42c41e0,63db66dc,9b32c21c,af94a158,14fd5b62,aaa975d,3ca06925,f6d6ecc2,e93159a3,ad6fbcb6,38f7b09d,40601189,cafbe5c5,90c70103,b56fbd47,d36ccfba) -,S(1103e98e,7a1659ac,4242ad9d,6fb012d9,21696e58,413f71aa,e19fff6f,1c334fbf,9f2d4667,ce5a1285,524d91d9,265d7a5d,da9f5ea6,cd508cf5,90076d57,a975bc62) -,S(9e113cd5,9e7177b9,19859144,598263cd,630f72f3,4da00ad9,84964043,9d82878a,6a09bef7,6e13f2f6,8e70ee90,5dd5af4,495f5965,859a1d83,ef149f67,2643c9f7) -,S(c03c5ebc,d04bf8a2,bdec182b,32d8c726,1913652f,e4547892,3e0dba7a,1fe275ed,f567e3c7,4b9313c4,11ac9411,11f1b62f,74a16f79,e7d90817,b54d4d89,958cda21) -,S(205c4c44,7b84661b,cc8ab2f0,221343f4,140c9efa,fb107c59,b5095b48,25f54b24,94a10344,ac5f48a3,600309ef,8ef94242,a8050865,3c018e57,a7734d9e,da18a55c) -,S(e393821a,58c9e9c5,6e45cda0,334bebc4,359c4b3c,1a60bab3,f1dce2de,c1da81b6,5469cb0f,4edf5f47,80df616,3a6b7074,7b26291e,8830d113,79d84aa2,15814e6d) -,S(38fc36b7,a866b165,a424f0ae,74ca34bb,b05922d5,1bdb447,5df797ad,4d042e2f,a9279b50,4b3edff3,aa8fe039,3415c21a,556609bd,8089383f,f5dbdd34,291c2b1b) -,S(1c4a1aac,3c3247d9,99a75a00,305a4092,c5f34321,d3a33b66,b110331c,85be2b27,a10e4138,a835e3b1,16d7b6c9,46c752e8,dc92c39b,21677968,147a3cab,fa5a0f1) -,S(41d70c82,207c3b7b,716a2d4f,784302e7,e1034555,a79965b7,d951ebac,b7d62c00,7311a36f,cf3de546,37013e84,b2162c35,3eba0387,3d296427,220e5942,af398bac) -,S(bada1cce,dcf3dfc,9834c49d,200fb82a,b13cf2d3,d5da9ee5,c9c35448,352e660a,42e0d3db,511cbbe7,942ff10d,a7d49805,972d9373,a75545b7,206e490b,6c5dc651) -,S(233c0c68,4b9fe726,baf2b7d7,a0503e,7aba8b1b,3c4f28d9,4d095107,2b429bc2,a7bc02a6,2b81154,c3bce0f1,6a0b4f77,d412d162,1c713372,11ac1c61,a8f6fa28) -,S(a675f208,a0d48078,93525e1f,b6c5be3b,ef24ade,8d3ab14a,afac550a,fa6362cd,3f8edef0,3e0600fd,1fdf10e7,c5562ddb,af4266a1,52bfca59,e1235d7,c9e8223b) -,S(4adffdf7,a8a92b65,6f747fe2,92e6bfd2,cd3deb68,ccfd7f01,5639d779,7d21e48c,4d4079af,a6e89720,3a50015,92e43c6e,97fa1e57,11f21bef,c9df4274,441f7d81) -,S(c786e96d,fa658a6f,a9f1fbfb,a15d7021,835ebbb4,3e8ed3a2,c7ea573,c2944dba,81130470,7a10b1e8,74f5b856,b7223346,eef3c562,8959454b,d536494a,f075393f) -,S(10df82c4,64b75895,2c54f335,6fc24ace,cda4578f,d34ae82a,8a1eb2e3,d0830349,dae5c271,86031dd9,2eff2db9,6af91689,2a131cb2,44534495,c3562cb8,dbc5e1b0) -,S(55532c4c,c4483aac,26b049d7,df1da7e1,ef281c7d,bd99d21b,72626443,f2c748c4,58160e32,da446337,d0642596,c17500f7,b0e64081,1017bc1f,4452c4a6,8d2c2789) -,S(fe994c5,d63149e0,d31f6cdb,fce5b941,239c4adf,8d5e6866,37990411,d88ead47,200532b8,4ee2fb18,b2c27cd5,9c3940f3,58c6a2c1,d96ad043,4d826c8c,2a457dce) -,S(c7690e5b,3148cd96,592e654f,2eed33ec,a69d2684,545cbadc,6f6a7e8b,4d3cfbdd,98e0018c,36423854,6dede771,b78bc4b8,c52d956,d26eb22a,e447ab3a,144cd394) -,S(8f1f0986,d273476f,b31d4ddc,de949584,97ec74c9,acc6b0eb,900e4cc,2c98cac3,31f420f4,b9209657,1656b663,a06804fb,78597071,6c138106,119ef214,43aa765b) -,S(bee7ab1c,c23f6101,be01ed60,574ffca,70fbd4db,ae73e5c7,128da065,9f78c042,9187835b,66b2b634,a87d1baa,7666bda3,57dd5ed,26871976,8e0ea9a6,ed102dfc) -,S(8093581b,3205e5c1,90e9d38b,5b5ac422,b48fb5a3,9176bf7a,e1d377,c764f74b,3a3e06f3,4c00cf7f,6216e67f,2d55236d,db54640f,192897e9,fd68820c,bf22ce39) -,S(fc018da2,70dfe007,871e0be7,f5edfb7c,30fc30bd,bed5052c,78a7701b,50954702,9483d20d,af9fb123,723e0c17,7905e94f,462831c7,dceb0238,6f0942e5,188f3a90) -,S(f4ca4cab,7f06af06,d0a8bd7,97d6eed1,7354420d,65d80e09,32f6eaf1,ca12a39c,76770553,69f93094,3f368b0f,2ef6e412,f3d5a45d,1c7edc3d,9550fdd4,ebb1950) -,S(fb03fae2,87265749,787de276,84bfdab0,4993112d,f384113f,1dd41e6a,b438bdf3,ae8829f6,80f60534,50113930,2aba238b,1dc295bc,6598c060,af8393b5,1153b479) -,S(b76268c2,6b873f54,9438a569,5e2d5e24,a92da29a,ca26f18e,143e3290,69638a45,bb4543e,23abdead,c3377320,dd8ffb6a,d38967ac,ea90afd3,23c69373,eeb2407a) -,S(87db8064,9a5a31a6,487893d,f487c00b,143c09c8,fe878621,b592b25a,6c3d8646,872a4547,520d307b,a537d42a,ffbc8e9c,e04d1c80,e3d4f506,b001b0f4,79e92972) -,S(fb9295d5,a7c2cda9,c08b0f39,1fcdea4d,b768b086,dd170d8a,966516fa,bd476acf,62496929,a85c828c,cda71d2a,ae70c429,7bc12f03,5a99ff75,7d66cedd,5fb5135c) -,S(96f749ed,a1fc306,6d133829,774293e0,b179a598,327c3bde,a2e94200,770d12ba,c16915b8,af011de7,614fda0,ce1c4a3,ffeabc2e,2e891e4c,a2d9c277,247fc8c1) -,S(1564d7b9,77b4eb29,e7b23ba7,a3cf453a,8eaadc50,87448fb0,fd9310ec,653ec66d,6d8935ef,a7d41cb7,5c5dad07,c3ca864d,89e49f0,f74d4474,af85bf05,c408009f) -,S(93db7b68,9ed6ad1d,bb61223c,dcca7280,9cf4a49a,14d94f3c,7cae77c8,f1298340,9088165,7b4979f7,26b156c9,d34430db,4a0af993,eeb996c,d091ad5c,4f7bbaff) -,S(2656af7e,d8a2e718,9849cd,793baf93,1c23374a,a3b5596,d8c88841,2b6a5ad9,dca0f4b2,7c7f1547,97346dfc,589374d6,1224048b,ead5442c,9f8950f1,63689045) -,S(a7dc8558,c0adf996,b7f57c08,1b509e34,7819131d,42647498,ba819c12,6d26cbf7,9fc494c9,2bbf6116,14527eaa,1de4708a,f0c19847,3ee9164b,6b9de909,f6a4497d) -,S(1f6d4701,effe09fa,17ecc014,a7a0033c,143fbfac,ba4861cd,d7ee2fe8,5bcb2cda,84c5b017,81ce481a,e610bd8d,96ffa58b,b7a158e9,d1cccd79,7e6436dd,b1308de6) -,S(eefe37c5,d547b779,d905849e,dd1038b,f054233b,f2d1af47,1684e5c2,a1e69960,b5f00dee,8b1f7960,aa068db6,78b6b41a,f8c3e14b,27c1f43e,10f9b34c,fe8eefef) -,S(8d4e8462,60602ee0,948ba5c9,f0506046,d0bf3fd5,e1b93073,bcc8a6b3,30af96d0,62d0e36b,bdffa309,f1257b23,6327506,5a5e7999,b314dbed,edc75800,b35534ba) -,S(da22079d,352d3527,5a80b95f,80b7b8b1,3eb6d178,310b6889,a94cbf2b,9a9a898,e8b06b65,37aae428,cd25fae,d0c1af8b,827b296,886de122,c6690a19,fe94df72) -,S(beb411ff,67cdbb5e,58da6353,172813fe,e386c7,95550395,1ddc23e5,d4e579a4,919f8f30,41f53020,4d3620bc,b0bc80e5,9d87ab73,355c046d,cf2986d3,c9995866) -,S(b0a5732b,76b4a526,e8e742e3,528891c7,3a1febb5,c7657a90,4bc1f95b,96d462b6,a5e4f134,93f9e24,75ac7dab,479092cd,fb59a931,dd042add,3d875e22,76965a9e) -,S(5a87a782,13130193,4ce6180b,714e99c7,30fc8bd4,fd4e8c59,f5b6aae2,f3622561,a929d120,68a64953,90c559f1,ed8ff0d9,bef92431,66117208,d0e8a08a,de9a3d0b) -,S(777ba7aa,6c50e927,64ed93ac,daf56285,9909b031,7c3c5ab9,38ebba26,d62a1748,27a32172,d7ff61ea,b6a26d00,c252f99d,bcf614af,1434641d,cdbd5f4,10e6657e) -,S(ad0f9f5c,8fa07d5d,3c18d4a5,7dc16bc6,3be0dac5,9166fb42,6bfca8f0,65b76720,d2c9c778,3caf2c93,f6c3980e,60ec0fcc,1f1d5ffc,8aff6af,a912b5b4,245fff6e) -,S(8904706f,17aad850,7a71f0c0,94f981e0,5e5a42d9,7f5cc3ed,99b4f635,660e227b,371d5f58,a63ec71b,3cd8b601,ee622586,2822a2c3,99ac70f4,ce293846,23ad8198) -,S(ce32a220,2e276dd,3f5b0a10,38a70f21,3c29ba7,58934c4e,27ee3bc3,c9dadf00,e43d28,80486b34,65e545d7,6618d80c,56874afd,29ea4ee1,e79dbe5b,b1ec1f42) -,S(3d031c0,c717447e,19266420,cef08d59,ac2aed4,7e84c84f,8980e8ed,ee59c7c1,86eabd82,d6a5f57e,cdb52825,a8c726d5,4a9faba3,6272441b,22627c4,a321d970) -,S(9dc08947,fa3983dd,44730aee,d8e94f2c,78eefc44,df126804,281f740,53330b43,58838246,3fc02261,c0e771b9,3d4a90cc,c2c19f7,2893ffb,22fe6d5c,6c5e7318) -,S(f9fb51c7,29646acf,94ecadf7,30989d5e,669ca4fb,3b4dfe66,dad9838a,f239057e,d4a04a8f,f44b86c3,17ce4350,1a2325cd,46b5decf,5f4e14e7,17ef0c30,1241f8e7) -,S(d4a1c33e,816419c1,884c2838,abc7148,c61f05d3,71fe3de8,9f06b580,cc5e1006,28d8f049,a1daec88,5d186da2,66e2b8a2,893d90c8,5e720d03,a53cf8bb,f8a10208) -,S(1b1c6ab,74436126,203ffd8d,8e9c58b3,e18f2767,3a72bfb4,ae4c9e25,ce17c570,ad28aaa5,eaf7128,fc8788e5,b9c1c13b,a4cf16e9,f651da6b,6c43fd1c,cf2903dd) -,S(3d791154,b2c062fb,e1f6ad1,dcc17bd6,b648aadf,cd573cb7,d29f9e47,e089e1c3,a578f2d,a568b0b,e95e1189,7bad8311,3098787d,62756c99,7dc3d795,8e0d3745) -,S(6daac2f7,ee7b01f7,277b3a5a,44785b4b,c6b6adf9,b112dd6a,227b2b46,9f27940a,fe9504e5,75c1e349,9267624f,2b2e603,55befd7e,d66d7fe6,80c521b5,e0d1aaab) -,S(ea6343d7,73a5966c,2ea66806,ed59079e,8b216a9f,4fcbe8f6,744808b3,2478c26f,15ab94e5,cc1f4a5a,33955f6,b30571e2,5104c615,c0aef2bb,6a8f6693,64639f6f) -,S(ffc78cf2,4b436203,dcc1b892,c77fb336,463a8070,332783c6,1824acb3,f5cc55c,7bfe0b6d,666b28c2,3259c4f9,2c0dd94b,fcf53921,91d617df,da1c651a,1fcb81a3) -,S(db38103d,5156c309,67189677,9317879a,f31dcfa6,b8d0f5d9,1f2bc691,6090e6b0,b5b3e45d,9bd41082,cd3115ff,824ff027,78f47a0b,d0ae71fb,32c48d72,cd540c84) -,S(4c08de87,abf89885,2791b455,126e7e54,d660903,f407b842,7b4fcd70,53e0b000,a9f83c6f,dcea99fb,fcb301dd,c31146c8,25c02978,6e5019e8,7b1b6db0,731b9189) -,S(53b6a23b,8f93200c,41bf45b2,bd0d20a5,e6fa5db9,a3686a7c,c669815b,993604c5,31bbf5d2,21023fc2,fef75f0a,f7bc33e,b4d38323,cbdaa511,c40ed497,ef42a850) -,S(b39ebc0e,53b74f35,6f573a40,1df6f8d6,fe1e4fed,f7d976e9,949da398,a45b464e,9d58ae16,a633ea0e,86bad1de,39f0b203,c1ef0b24,b5f1d824,48fc606c,a97fdff1) -,S(182e4920,f4a60741,a0b94fc3,e3ff0bef,39f1d459,cd6c18fb,16b072b8,de0bd416,6d048d0e,ffdf4e60,8097cde5,46955541,491721a3,d6e051ef,9279c5c0,22a32fb6) -,S(7a39e7e0,a2da209d,8cbb9797,5f12acce,840dddfc,5acf7c5f,fe778a11,829e1003,c24aa083,20e6a786,1c161e14,f37b1c7a,65117e55,2c252445,20b47b67,66fb410) -,S(62e6173f,2273d3ff,d9fb640b,87d5cb15,e5df841e,3462bc5f,6b94575d,a110914e,7c424010,4ba37e57,48404997,689a01cb,851343f1,ea8259fc,938483dd,d70ac5d4) -,S(3960d4cd,96de0126,5c2cc88,68e94d66,40e9ac8a,f2abfcd5,2108848c,ad62467,fb24aaf2,85a54405,f75db03a,464bbc29,3bcaaa44,344c763f,dd44656,fa7faeed) -,S(463437ab,42694ce9,98ac17cb,fd4d9034,ab7a1be0,35f911e2,864441a3,eff8e3e3,370056b1,24b894d6,3631087b,194dc5ca,fcd2475c,a95402b8,418f1954,d47599e8) -,S(65774018,fd428788,e4234b36,42c8a354,770ddafa,c38040e9,49f194c0,ff7ad3a4,462ec7,cb17abb6,5200a88a,9874c7f9,40469a51,c48c1fdd,6c0938ad,67741467) -,S(738feb40,e7f16fc3,19ed6649,2507406e,6501308e,5112dff4,db9d12d3,bc0f138a,4923678b,84470212,cc5472de,2163ac3c,51ed5419,dc1b1b1e,78dc0946,f730b940) -,S(546841d9,7985d80b,a0eb3448,3dc5d17c,441b7eb5,d24b6216,ab98b14a,d320cf36,719434a4,952ee43a,b1006ce6,f7785734,c6a5c018,383eed75,e3660f7,94eb6829) -,S(31143de9,1a4b96eb,be7efe31,56b6688,5d39ce66,fa8ce202,57626dc2,8557ece4,d8d8bd18,36e5c388,2273143e,721bef10,b0c3005a,5e2fd3a7,e471ae33,ebfae7be) -,S(ad8076d9,29feddae,a52c009,f3967726,a0a94301,dfc12d59,da63c47b,df6566fe,39eedd66,13fb7141,796c0353,9f560ac,e23f844f,d0d3d422,5b36e41c,b6707602) -,S(b01a4f7b,9362be2e,78f5cdbf,d9e35f21,4d296a3f,3e233d93,2cf33c71,95b3f613,245b535f,c58254a2,157caa87,38e855ac,fa9b071c,1b6182f3,5260da9d,18e385cb) -,S(50f3458f,a781d513,a944ebd9,6f6b791a,1b0cedec,1421f9a0,16a7f350,2d5f429a,4972c646,c1ad5958,18766bab,5bf54ea9,e9c4fe3,19810f1e,27f46cc9,41594045) -,S(d7b606ed,e8fc3a20,925e0a59,5c9462d9,4e04b5c2,b64d13cc,19a47d1,ccf10b0a,dc39a8dd,d5447a0,f07b5e7a,6ea35286,ec01679d,ffb6eaea,6222711a,d57cc63f) -,S(7629836b,73691a1f,f3ae6c99,7e06f597,34fb9625,2d1ec88f,2af15cac,f89c199d,296e4034,8eacfd71,7f64beb5,76736398,62114296,5fc818a3,ea89ba52,1b1a410e) -,S(88f6a162,7baea31,3a2a5d5d,aeda2f4b,4becca6b,812a60d,4b5b4e22,6c822a1,d3acfe53,d6189ab8,31106ca8,2388fc28,5b567e5a,5172050,5be56bf0,187534eb) -,S(8e93c72f,cfeae58d,fecd373e,dd3f31ab,3e4fa28c,f53681dd,ebf37d40,c376283a,e9c82571,2d0cfc0d,e6f35e77,acf0597a,7e2437e2,80f13420,cbe93acc,52901d71) -,S(b2264df0,eaead63,111d7b05,8767cc7f,36d386c7,edf21792,e8aef135,9958b2bd,242eccda,5e4324a5,40e8d098,cad23ecb,88955bb1,126314fc,5da973ee,b1d83313) -,S(9f1c9e90,7a6813a8,da520f6,84553a4c,aab650a6,7eaf4f0e,f2ec212b,95a885ce,416dae6b,f47aeb47,453fd0f4,7da6375d,136b6ee2,450bfe75,504f3619,84a0f355) -,S(dcc7585,132b95e6,a4a24450,d557a0fc,3ec93506,fd1f5f02,17bd0f7a,6943fa1a,c62ca95e,d976d1e7,2bcad48d,9bc3a316,a35e8496,952a7a07,760ecbc,8903b001) -,S(e3c674b1,eeb380f3,f08b1d64,32f4dddd,77cb602,915ac478,4f3c769b,dc2a30fd,fa8b08f9,8bb4a1b7,568c9d3e,754292b,1a35cede,1b377c99,fcee16ff,a16bbe5e) -,S(1152da70,2b7341ff,69e8d3e,6f5ce8d3,bdcd3a03,27df54bb,846ac8e9,18e747e4,7c139d20,1e2ea5db,984cc8d2,4b66c64,8adbd0c9,48c0b085,d59c73ce,b4d7a91c) -,S(3449cac4,abbd3ae5,e09dbc5,c89258a3,df93ead9,1f62fad3,a5add3f9,87a2f83b,197ecb64,5dc998fe,eb9b0df8,6267c7c3,f7af9647,96fea60d,88d4de89,33171e2a) -,S(ad5cc468,11c5a39d,ffa313f6,578acb00,cdda9ce,b3757479,9f2afd6,a8df7a19,4fdf6093,c8fa8a92,7702982e,7e638948,b982d84f,ae6658bc,fa839354,6d6e76f4) -,S(acad447c,b57e8f5,f528a113,347e5c5a,2097766a,b4664c70,3f496635,759a7799,88e1b4ff,3bf3e967,d2c6c948,4bb727a1,d13231cd,acc45463,d421431a,b6fc46ad) -,S(b74286a7,e2699aee,9802563a,4da514cc,d74fd001,48534822,9214395b,36158246,8df2b491,ea018b23,b1c7fb54,b7a05db,b79b0ebe,1117e2d9,ce73e70d,d097bf90) -,S(86bc560b,19d583b3,62c1634a,139bbd16,db30e823,75913cd6,fb688e4,38ceca4d,2126168,75c3adc6,c2aa16ee,2e028052,9e6612b,fe4b1aee,e4961feb,f530423c) -,S(dd79faa2,e97dd468,5f3ff8b8,d5e55598,73736de3,9493a3f4,4e679516,f51e495a,2cb89020,efaae785,5376d901,4d1bc374,21e0ee60,29ac70c4,65bdcdd1,e240e57d) -,S(caf6318f,825ca3d8,6d45c681,60d897d1,76875e26,bcd36d00,82b4e1ea,e6d8c142,d7abc304,55a5fab2,68c6d17c,3763e586,5b9e266b,bc6211b9,48b5ff3d,19f5df72) -,S(c49dbf15,70c3f0ce,1afd166f,884af550,1f26905d,2f726185,7c026405,efe9a2bd,54eaad70,8bdb7b2a,59f5d69b,5be6ed79,5fbc4137,945be17c,b4736649,6e8cd3c0) -,S(a87447c2,83c88db2,15630cb7,6029132f,47dadd57,5ea6f9bc,10d1b36d,8317a91a,8489d3c3,6334d65,fdf6089b,df19c3e8,7eecd697,516e1756,5fc8b977,be82c363) -,S(7467b357,7d21b028,dab4100b,ebfa734d,36345024,adc60b1,10b8f96b,c7860889,b2978a5d,dea9765f,7877d8ff,fba66c0d,f7c8e0f4,6854deab,21908da2,8572b1a2) -,S(6af133d9,bf2d6b57,ef69e0e7,5eef6d,eeb82d31,af490320,bd26f4eb,38ffd42d,7f4a4d1e,ce23c530,a4d64c23,cf0bf8,a46c59aa,74dce4ac,2854c6bc,d11b056f) -,S(faff2662,5a41c80f,c0889d4,83eaf50c,596aa571,6807b118,1e94ce5b,581b0a7d,32f3d057,4afc487b,43b129af,f83bc7dc,d495402b,90fdc30f,736e87a5,469e8aa7) -,S(8c6983d2,8047ab24,ddb292cf,1c8836af,7e75d7ad,6ce23149,e022cb64,2439ba2f,70a10314,447eaa73,924fdf58,fc607dc1,c69a69aa,29b84dcb,156fec4e,568a5bb9) -,S(bfdda2aa,b23a37b2,bc129bb4,280a2c45,926360c3,2719872c,ae1e81b3,1b3d3d02,e8319769,b7d21199,9e5de1ae,76021c9c,2bf75ed0,4c9a6c2a,c52da4f4,88cf78a5) -,S(80e24bf,3559d05e,c0cf63af,21dd7adf,237c23e7,ed930c7b,4124ad4,46871de8,c8f37f91,4e78e037,602ae9bf,ea3511fd,2c95ad3,6665117d,64f9fbbd,ecd10063) -,S(7f56d940,2d6fb0ed,dc6ce187,2ee8e55f,45db30f9,8defa84d,f7fb76ca,aef5e800,f43b9e6c,b60ce85f,44682fae,d8a48e5,3d9599d4,f19b4757,74f7d6fe,2fb2554f) -,S(437e7a08,900216be,72f14ef7,33127d49,9130309a,73369d2e,58fd4187,a0d428bd,3f0a4c4c,63dc779d,69dea37f,786a5157,43b3560c,16d4e56,4a1d7802,f40dec83) -,S(3bb8db7e,8cb3534e,d7f70f8d,eeb1cb81,3ab21dd0,552c311f,f98f38e3,63321626,9ffd98a4,b3c271e7,83ec8c72,98ba83b3,f4f0a5bb,61ce1edd,5c1095ee,eb16a569) -,S(21de8ce4,6aaebc6b,4ac51620,e2c78904,f9300b6,2930fa79,699e2782,5dc2310f,12a21855,50ceab27,aeb2e7cf,14710b7c,b3dc837a,67a1e4d2,6950e2b8,1942b9c1) -,S(6c24ddca,e4245972,5268369c,545bc910,ffddd8c3,49d83fec,eb27af78,cfc0c965,6263abc6,ed17a124,c8b2c5e5,c91b157a,13512939,b9d60e48,929fe6d8,4d032338) -,S(ddc0dfb0,49f7b6b1,cd1d03c6,f8ed2470,ae320f04,bc6f13f5,a88ba89,7bd1f91b,57c5f0df,8fd22e02,da44cd05,74fbcc1,c8b4a903,a909f906,aef9208a,89eeddd0) -,S(6fc5fdee,78c61421,a3ec2284,583a56d8,f18e66eb,58c54dde,e5209a1f,3e3761eb,baeac905,6101b825,8b08a807,72c977bf,60956b2e,d98d1b25,e71b2b7e,10e3d25e) -,S(1b6735d6,ac2f1db0,1c3781d0,cf42e2cc,3ccbf030,2e3837f1,3f6655eb,ba0dfddc,621e8c0e,cedfd28e,608c3da5,135d63fb,93dc6919,2a6154db,bf63e315,2f7db68e) -,S(1a875a0c,ecae6600,4bbdab3c,4fa5a57f,925079dd,671bd9aa,e8ac5c51,b21a5e83,2317a0c0,81c17bed,a15e1148,f44beb72,d4e65fa4,96408778,8216f85b,3924d9fa) -,S(51635c0c,ce51684d,9631c8ad,f6c9c4a9,3f66dc04,a372c891,294c42ae,2be5a84a,5c6cf3f1,bbc9c21b,124e78cf,ba05b2f9,ffb9c902,3895d584,48622259,635d3517) -,S(c548df8c,b685f457,71c564ed,a3e9a77e,a4734faf,7cef877c,b0bd70ff,d85afe0d,2675d6b8,24f99a19,8825f1ee,19510492,9eb633d0,367c01f7,c922bfb,c2cd6dc2) -,S(121592ee,aa39a310,3c02502d,72e360f,f500853a,7d2e449b,16c5e443,f42e700c,b5cfa2c6,689d973d,e0578a39,bc687720,acc0305d,6ad3b678,1d36941b,7f0cb435) -,S(c2a8b66d,cce99233,b3d83699,b20f0c60,21a83ee1,46a491e6,d7e69ebc,92a3e046,e0f3aff2,64228803,d8c1d729,88780d2,ae8c344d,f9571b86,70254b39,b4243705) -,S(b2b703c2,56ab219e,528886a4,4d6b7772,5cfc1b5b,17865ecc,c46e2d2,2420514d,b6aff027,b4408177,8c6cfaa0,123590a7,4615394c,aa83891d,15013d35,ba28a9cf) -,S(d249c36d,fbf43f5d,c6ddb196,d78d4cbe,898d64cb,3b239f89,1e8c4245,ab647afb,4e58c9e9,4199e0b7,8a0179c2,c82b6442,17eb3fe7,80c687e5,166f56ec,f812d092) -,S(ac3519a1,92c13eb,b37cd560,1a141d80,817226ec,7c86a053,42655c1,997b476,3522765a,afc2fe6b,2af9b489,27809189,74c2bc57,58ce502,13777ce1,a569083a) -,S(e9b69596,8983ee86,340b96ce,efd9a289,e86e6d49,3f057962,77b99067,af83c70f,983a83a,e1b08fee,392e51e1,c12a8e12,731d592a,517e240e,ea508f7d,b34059d5) -,S(e11e982f,10e65120,ca357106,f273c5b2,9900454f,81456781,36f52871,65444dd6,e961b155,81ee9ec5,1e6a3616,b7182da1,bd2e5db4,d08dad5b,46bee558,44c21850) -,S(f63f4434,bb0c17dd,3a17c75d,2d179e41,10a7810a,847bd4eb,37827997,94e57b14,480bff24,69c2e268,a51b2147,3d6cf7ca,23a3c61b,513267f7,c25b092,7dcc8549) -,S(cd8ea46,d65bb2da,7234508e,fb48a828,27678525,d102fa85,6d26475,eadc1a69,ba231ab9,513f90be,9cc8260a,fc63b05a,5aaa0280,3502532c,916d99c7,20b7b2d0) -,S(af9a2285,ec491b56,9cf53c8,6ec188e0,5bf18d1c,d7e898c3,c881a5de,481bbe13,a0cca7f3,714f8d00,92af7bc9,62abbe5,4d106dd0,a6089607,35a6d9b4,73d9ed58) -,S(5d90a039,55f41998,62e5cef1,af05ddd9,114632eb,abf27d6b,9b92c6c8,cfed8640,a0025e54,482aa49,11d8a556,2205c2ae,2a0f75c4,6f3faa55,7463b9b9,cce1281d) -,S(aa1f071c,55541753,3a47b490,c5603aed,2d2e5282,71acd0de,6ea7c5bc,ba66a348,195d8b00,fd90b1ad,15e46620,22d78bb2,47c1e9a7,8ab3b018,f341a005,6267a167) -,S(4225728f,ee2495d6,73f64d5a,cee2e372,2713a3b4,dbd2f098,d20415c9,3ab513e6,76c17939,461504e6,e1420d53,c5b07449,ce7f976a,e4de178e,69552755,75e92412) -,S(669c2815,b3357084,bf7bab89,63753b0b,ebbea33e,5b731ba7,5f969890,3a281eb6,23fcf486,e2839e2d,91fb08a9,11ed7361,81de7406,54c13306,575c576c,d0459c28) -,S(7b29749b,393869b0,d7f0977b,340b9e07,76a20ceb,ff6d8f8e,f4650348,11773665,a0d68cd,b6033ab6,a4c92113,c8f07110,aa5cf600,2335d2d5,2ca9b956,2874832b) -,S(6f096ed8,56f38c26,25200774,77ef7ade,19fb616e,30ed560a,ee5b4987,5f43a7db,54453b3d,1ffce3dc,b5e72ec9,3f15b57c,6725b271,d3fe8b7d,8f30ed00,35845b6d) -,S(1354de01,ef040d5c,681318c5,a6dfe7af,5c8eba0e,ab581674,acd5335c,e33c4bec,4002513f,ed215b53,c65686ad,8366cd7e,38711fd9,98d27750,bfce7e24,dda317b) -,S(5f8afb0b,3800c535,47cdf93d,61ae5c67,233c2525,17f99c38,8e97e7a9,1a90b561,7dad53b7,a64b7068,967fc0dc,e7178a43,a06e56f7,7aab1a57,7910d69c,23540671) -,S(901d50d9,b88abad7,84e75135,85a81d9f,a1d167f2,c9f377b8,e2598cc7,b249f3d8,7242b591,3c80db3e,748c63ae,47ee6229,2c1bc29b,e9f9088d,fb882259,405c3dd0) -,S(2f5e27e7,4c7e00df,c0bf6401,7d1a888d,1bb7a3e1,3ff66874,f7c306e3,806a48d3,87c3836c,7fb767f,4b5ac585,62c48a18,21dede2a,7d63fe40,da75d967,cf9191d0) -,S(8b2277a1,70464589,1d8b54cc,43bd5fc3,54fa6f1b,e7a062e6,6349ac2c,40eef8ba,ac3a007d,6b3278de,1c043476,13b254b7,69c9e14a,c2f50f9d,5f025046,2e06081f) -,S(4a6273a4,e9f28e9a,82c3532b,e7d3e564,66e87273,ad1fcfad,7ecace6c,54890de4,6d8b0fb2,1cb99844,610a325c,9592cc1d,e7c8b32,d70e19b7,ab7df472,8fd1aa51) -,S(f07330e,2ab0150e,435fe3a6,8c703091,4e7fb52c,307d58d5,d5120bfb,891f84d5,25b6ebc5,4c1d9206,33891a8e,39aadebd,988bd98b,a29b04bf,6ce4c283,a4438b08) -,S(3a30b22d,6f1fd617,9fff2c21,d6635828,8c21fc8a,94a274b8,993ecb91,eaab54eb,94035c56,6ea179ac,d58eb0f9,d12cb41d,67b94fbe,65805110,61cd9806,890946b) -,S(8c4f39cb,87d7f65e,591fa10,fd46d08f,fc5de3e1,67d8c9e7,718bff95,b112a5a,726c4bb,c64373f1,9399db5,18b5f823,3faef361,3e363b84,ad76052e,bdc8f2e6) -,S(38118e59,63a1929e,74f6d98b,c80e44e4,d9b32254,6a0f1eb0,690d08f4,f3bd4bfb,23167e00,c29513e8,e82d1140,bef5bf02,b806a652,fee592fb,1dad0811,604a4b50) -,S(75d4246b,db065274,550e9784,f3c9437f,3aec0fde,3af54a0d,61430cdf,2626bf5c,8392f570,3896cc62,d66f8485,9f7f269,4ff40a81,9505447b,7d79bb98,77f8f621) -,S(ab3bb0ae,c1f390fc,8d1bd3fb,4ecdad66,3db868c7,c4fbe0ba,6cf4f059,7068ed87,91382a2,2dcfe0c1,b51148ce,bad2140,24cf099c,e3e5e3ee,867db7ee,d070c7e4) -,S(d1453e12,383386e1,1976cae0,8a448b63,1a977dd8,47c19d2f,d7a212ad,5090011c,7044d595,fa8f68c2,4a972658,590d7ab6,dfc06ace,b9d8c320,205b858e,ba0402c5) -,S(894afc53,b0d1bb6a,c948d117,7e83c42,b4ff4084,e593fd75,d0660680,2ec0a4eb,5c5eb493,73e74fc7,39ca4fba,1940ebe4,6912d896,7cfc036c,7402e8ff,8d071d7c) -,S(f1dbde60,43133dc6,8699e89a,3dcaddc1,fbcb5ea5,e815eb5,8e7a6b87,dea2e6e9,96a7b1a5,b36e5492,68168c91,775d6107,a3f87f9,fb5c8b3b,acb75dad,5dc544fa) -,S(ad9126ba,6d35d780,dd2841cb,2ba817d3,f0267446,ee99abd0,ee2b4910,a4450b8,f77eaa1e,66c0f3f6,88268d92,9c9ee53d,6dbbc20b,b74e864f,d7831cc9,3d47280b) -,S(70d5638f,d3fc43c7,6f321157,f9715994,3b797d8b,1d366f5a,a5a7f1e4,ff1ff7a6,ba6f2d41,7af1c5af,dac8c83d,dcc289e9,4d6f29b4,2631ab7b,19414bdf,4a9ece36) -,S(e43bb23e,1f82bcd2,708730b9,3d3ed915,e3b4ad84,61904f68,bd91a065,80a4ebad,3b528db,117cfb49,99941b0b,63f51ef3,926a6230,dadbfcdc,28fd1d6,2bd44147) -,S(9daf3516,a015bd59,b648fd9d,9143e76,46b2e3fa,df5e446a,c57f2e22,9c9dad2b,5ec57ad4,808a9f2,ed297f7d,a7794e2e,3f1bb14c,bef58047,e0bddfb1,8ff11149) -,S(13970b21,3115c499,5eac245b,33633c53,1f2be101,a541f129,7403a727,67df16f8,3444e05a,7e49ecfd,633c96dc,99a0fc81,cc3c359c,440ffcd4,5df61c5d,1c027e97) -,S(12aef793,66978a2d,3fab4377,7debd5c7,4315b002,829b49df,c80fbb4e,1eaa94c1,e3f5c1d6,ea42b741,8bb3446d,c23679f8,e7a96d02,a8f33d1d,3404126f,71f9e37b) -,S(62a2ef7b,887de5a6,19c753f5,e0bc45c1,7c47b8b1,ffbb0ce4,8b93caf1,d1ab4b02,7d00482c,20c25e01,ad6ae35e,89c263a3,5d0fc816,952a96b0,9f2c2fa4,b8fc9bef) -,S(e6b03f17,92df5b1e,ec324ea0,898c031b,d745221e,791d2406,2aa917fc,de6f8a87,b4ee4b18,41153d22,1ec0ffe0,ec05b1c3,408d71c,5d2ca29e,a01ef9c2,e669b205) -,S(dbc02e03,e03e2f14,53ff6410,afded1f4,f0d51461,5ee00f75,d041ee33,c4f35783,6a3a332d,99ffedd3,d442b44b,aaa9d12,9d93e372,36dad034,9c47bd83,7c7674c4) -,S(f11be23d,6884890f,78ccbcaa,c1759ceb,5e7f98dc,19073aba,b85d85be,5fd23ef0,9afda170,dc1270d2,e43989a,4ffac7d5,c848ee6a,51e03b58,c308a4fa,39e2cfe9) -,S(16ec4f95,1db5c83a,c2c26209,f2577650,e9c48c44,224b221c,c09b0b19,1c1c5552,e3959034,d259e9f5,163a44da,f87ffd63,7a35b220,eea5ec6c,301cba9,eb09dc54) -,S(3cf701ab,8991e981,e9cbfe30,7b3aced5,c2147c47,f76bc2a0,733ee544,3fef3f99,1e6a3069,d4d0bb8c,def98d49,cd303b51,c45617ed,833be051,ca2836bc,13b8e1ac) -,S(96d093fd,1a8efbe,4f93c544,d0d7e397,cc83e114,4574f804,570fa3ec,58d5669c,2a29438,a05fe50d,b980db60,b343b06d,1796ddff,7e7fe39a,356cb608,69c05ccb) -,S(a6457eee,21025732,5094d3eb,6f6ea05,21e83184,adeabfa7,b6cd1206,9a9dc9ee,83e436a8,b234778d,9c7be0db,88639177,1d7a48df,19c29c47,682fa2cc,30b5e7f2) -,S(1b366505,1c858ac3,5890e7dd,b4aa7984,dbacbbe1,f4d2b62d,5337b530,da9bb0a5,39d3c2d,42c5d292,40b474e7,2e94a64b,4612f5a,68f5b6bc,586db5fc,a41025d6) -,S(e09325f4,68328cc4,d69a71d4,8ffe0380,bc118cb3,b8f390d3,4c1e56fd,27f4589a,16cbf183,78946fb8,3ff9763,41c6cc3c,9b2f451d,7661bc3f,3811f7e6,ea89a01d) -,S(6a8ea7a9,ddfa0f9a,8473c47e,f5667e44,3e64e03c,5c33a9a1,f0f1257b,40e1ce62,92806471,56238c84,9c0aadaa,2e9efdcd,e5a56a2a,78803f7b,66210333,88f525db) -,S(480b30ca,dc57c623,9ede2763,f113b46e,599076ae,ec687c49,33343178,c620f2ea,b5aa1b8a,ffe1e5ed,de587df3,341dd34b,57180cd4,752a1bfd,d06e4c2c,273b4433) -,S(134be6f0,b03ea43e,98e2364,46a45253,ea5822df,46227aec,b24b09d5,b25a34b2,d4841d54,b7fc1736,b293d314,bf6352f2,c7b08ece,4de652d4,2c1b985,d1fd78a2) -,S(7c84e23f,c54de6a1,a4ff6c9a,c7c88ac6,732d019f,a53b1a9a,a6eb2ab8,a3101f31,4ca88bac,a8d52f44,3703fa27,4fddde3d,ae5924bd,26b062fc,6f7fd0d,43ddf5ad) -,S(7c6a349,911f02ef,2aebdc3b,ce77f639,94c4dd2a,a842b567,141c023f,4f2d92d5,9b4f2f9,6215aad9,c7e0edf6,efcd8aa8,74dbbcd5,4a0c4cd0,fb7e01e8,ba6884af) -,S(9e1dffc6,a919c9b8,4e3d818a,5ec60f7d,5a2baba7,7d2dd65e,137d2ba2,8a1aed3c,cf26f543,bb7ef705,e2d3c429,f0ea27,84e3daae,1a71c556,38d281fd,aa3b1738) -,S(e24f6abe,c7519588,33ecc765,7446ae36,937e310b,d5754c5c,343eecf3,6e140079,c38a0399,774ff24d,90f8e599,183bf011,aa3c911b,9a66bbe6,920522a6,7510e62d) -,S(517505bd,1fe28c21,2fa85f18,99823b01,bcc3bd1,748169ea,54f35ab7,870f0e1,da94c34a,5de41881,1184fe92,8b3f08fc,362aadf7,5e7abf87,5d5f4798,fa712f3f) -,S(a02217de,4ec87155,b877b7c9,dd7425b9,79627f0d,ebe127ce,27d4f3ef,fb988a8b,cdbd866d,7b69e8eb,9321d07b,2a5c9d8f,6eec8be2,f19a6d24,4c987a1a,12752bd5) -,S(2e595023,c8ba084c,1cbb2d05,96ec35b2,7c366bf,cde27666,35d7e820,8fcb0ae9,ac08f27e,b8fd5ac4,deb1f46b,23ac1c5c,aa02b918,9761e6ba,d7c1ebb0,f412d8cf) -,S(ce384358,fba557d3,b76df62e,d2264cf1,e0bc7b43,bab30be9,fd6f65e1,a82b6c2f,a3cbf24a,e067ad85,ae0fc86a,6e8490b6,1e44980b,52f29a75,4a3f7e4b,a79ad119) -,S(9715da8,79cb1c5c,4291e00,fd2822c1,7f067d63,664170fe,463e86c2,d25e46,c5179ad3,a4846fb8,d6f290b9,2f957e14,cee99f6e,12fc8066,ec4dfaaf,a82edb99) -,S(19f61bb0,4cedc19e,5054eeff,8d0bc384,6cf62a35,1af3ab95,e03e45d0,786e1aef,aaacadc8,db84d7c3,f869931b,bd33d295,45fb37cb,7e474fa1,7a69a683,117c05b8) -,S(2a69afa7,581777ad,38882f6c,659ff4da,33fcdc17,a5355583,d1f8ae37,7dcbd718,878eb429,d42dfbd6,435df1fa,c5e0ed4d,e7b2fe4b,6f7dd6f2,6a3150a2,213fa619) -,S(c3da1980,cdf257db,f2a5eda9,94267691,a5e1e679,79d4908c,c06f7f50,71002381,2cdf4de1,90ef2995,a984d882,598c24cc,35cfc47e,5cbd2d53,53d880cf,a944bfb6) -,S(19294eba,9d19c03b,497551cb,7cc8d8ad,3e3b2130,942ca8dd,c8bc5579,1c424d2d,5523ac45,e676daaf,2d8da00f,5e9240e3,d904a536,63e6b704,735889c8,84b680ba) -,S(d8b3b307,41ee7ff8,2306615f,2d2ef361,6e3f7cd7,fed9d56e,69300fb8,5eab6bd3,7d57c12d,e65bf3c4,6dde736c,373ea374,d090b240,6e1d97fc,8049e21e,aa10a74c) -,S(e2fa1bd1,164528f0,87c72a18,e9843e33,43b376d9,b5616b74,5e0c3d00,eca95fd1,72dcfc41,15b35406,8bd3057d,506d592,771eb3fd,60a2c2c3,dfc2645f,86b249e5) -,S(ac587775,bee32b7e,90031ad8,9786df14,8e4d9662,55a06399,e43c0441,883fd6b4,b6d3eaa,6f6a50ef,ef84c578,b241591e,4a718eef,fb40ac34,99a57079,b74c45b5) -,S(74976cb0,77d481f5,e6bf700,6db57a13,f362fabb,e6aaf25b,6e956452,9d093bbc,bb40be31,7cfde25c,75ea859,2b622e4,9d42a0a7,30602241,219bcc84,a5f4bfe1) -,S(e71e6967,f32647fc,2c13a94d,4bc1410a,cf9728d,1f543522,681d750b,2620a668,33c4fc82,720210d9,afb9f1fd,51671f3f,fc1df5f4,e61a5ff8,c59f06c7,91f996de) -,S(bc36cf57,161e9b17,828e4557,74204c59,805b35e3,abdf4ba4,daa9a5c3,fafad6d2,df34c492,3018e879,bf459cb4,528d2983,340444f5,a85efc29,71e260df,29cd8a20) -,S(925251b3,9c8761c6,317c2066,717a2e8d,89e43acf,89527ddd,6078fa49,2d040f95,aa7a084,8b2633ac,ce551f1c,63312895,f4ece420,5e224665,2c486beb,b8131f10) -,S(4ec27df3,d9e755ce,b93e1ca0,e0e43f44,595b529f,6460e3f4,e6cc3765,3a2bbb21,eee3fa06,257b4be9,387ac7b6,6cc1ff6a,aae43583,37d6ed71,27ff753f,1fb179ac) -,S(6f733e9c,b86c3a17,5bce6c08,347577eb,69cceb17,3c19abef,c94b6646,92859812,2a895d6f,c4a7a4f5,610e8b8,9e7361bb,db728625,ee31e6de,927c74f5,b10ad0fe) -,S(c631f4ec,f205b1b4,6bc0fce5,3680e6a7,27f9e64d,5ee3fe24,c37291a0,d3a69b53,f0de9e0,e4bea2a9,cc01a5d,2f9aad2,f5af7ab2,7c2ff98b,983dd2b6,38dced4c) -,S(9326d449,4fcb3049,8badc221,6d3a90c0,131d31ea,cbca74f7,2cf7da2c,bb6aa2b8,c3f268ba,4c9a9ab5,3f9edb88,74f2786c,4e4c065e,ab58487e,cd8101b,7132511a) -,S(538c52d4,8fa6c492,cf546349,675d6a2c,ba10b442,8827dfeb,69f0303b,1b7ac774,c1b1db4f,d6d50f3e,c7533ee8,cea0d47,883b57e6,dd4137c8,2132f846,3b81ebf9) -,S(5e58a25d,8bdb4576,d178fdb7,23158d26,508f8486,ad553727,907901d5,6e99a680,97c1f814,8880cd85,51c9f1e4,9ae58eb3,d1a01285,bfa8248,44bc794b,7d83ec62) -,S(1e9830ee,b75d6c6d,c70989d4,ccb85e62,34a1cf94,ef81b65a,49b25753,cb6c13c4,d0780a7f,9607e530,d80dc068,68b1cf8b,82d3047a,2977d204,65187ed3,13c94c6c) -,S(c5b441c2,f7e97a03,dd690cbc,ac605772,1524dce7,fb5068f3,f73d78ce,50fe0183,9bdd2242,e35008dd,4f907600,64eb3b29,427ee9b2,bbeeb548,62878688,a916e410) -,S(a5f56816,e9448d0a,aaa7593e,e3145678,3be74521,b129f13,f11a276e,d419492,8406662,65c275da,76ef289e,d36f8af6,6ead9be1,48cec081,7c21987e,9e8af9fc) -,S(c5e85955,44004f79,2260d553,25628858,ce50c95b,9362d868,90fdfd20,8d1184c4,6a5f02f1,c0f381f2,7fd21eb,928f03a,c8524dc5,9bfc1bca,d025a290,7cf939d1) -,S(d5dd810,9e691f5,8694c87b,59907ed5,ec18d37b,8554799c,1481ac78,825d2ac9,ffbaef54,fd35a5ab,a49f9946,a11e5ad9,2f29590c,20e28180,9f4be3e4,b156dbe0) -,S(ee5d42a2,c705bae5,a11d9d09,af3217d,2ec16588,64a60a56,d8e4a1cd,4313c61a,f08f0e08,89c015f5,3a2a74c3,3dd625da,b329181d,1d0f4fa0,14ec01e9,5d113d88) -,S(90409eee,78af819e,249f62ea,3b4d70a9,26557f8,731e50ed,532c0b30,4616d615,17aa7a7f,8af635c9,c4ea353c,56c89da9,70df599a,faec8916,ec9a6d82,cdf957f2) -,S(5f19aa1b,a6d6e3d6,9445e8cd,71c95e3f,a3ddad6c,ff0dcb4b,9e09aee5,65ba9e46,f82b3170,c2953397,a6cd29fc,9c87bcd9,76cbc7a3,5f953948,5a57a940,63c2e570) -,S(5081942d,1039bfcd,96a759c9,27583c45,8dd4c013,59fea307,40c65fad,d020606b,f6f204b0,97cecd15,b2619aef,c25328fb,226598b,fc9384bd,de99a4d6,567e9b8e) -,S(43eea7b1,acbb1450,c9a49b0,262639f,702612b1,b184ac15,675d6496,a5df1a54,a31636f9,ceecfbd6,60f78f,f6cee471,d4366d7f,ff863db4,9a5a652c,71b94797) -,S(f2860e98,a30a6c14,ac43dc9c,61bbae1f,b8ecb294,36c8f0a8,7dd43c01,486706a1,bc83bfae,9a4effeb,4beb025e,962108e5,4a5d7979,cb9ae2a0,7cc44295,b95a2e9c) -,S(6b4a8c28,7d5c7af,63ad8d34,9751116b,60a613f5,7cac229d,7ef0d9c8,166d69c9,48333ada,f4810cf,94c78d43,88f8842d,fdc9fd7c,d391e456,a592d8b2,200bd6c6) -,S(d1efc808,393d4498,50837323,9b791d0d,a814e888,2958da8a,87136d93,bf1b7d74,13247e74,3c323631,9e557476,4ad4dcf2,b91dbc97,2d38244a,fabe4c0c,d08a9924) -,S(d3fd7a6a,fdc7332d,f2e6683b,a05ab787,e3c48262,ce837f9e,d8ebae1c,1f6f7ab2,3d25bfd3,3ddd4f74,8ff395a6,b4f36d19,cdb28ce6,b56aaa55,e783e9f6,3d74e70b) -,S(816f76c4,c5ea8733,5f220c54,28b31cc6,89fd8267,e498a675,4d6a2620,a60d9aac,d3b61647,f6624bb3,9fbb672f,51b66613,8a441a3b,660bb223,1f255488,806e79c4) -,S(1e344f97,98f11372,aef5c6c7,6b32a568,16198e18,8e611026,1dc78338,2522cc93,474e0218,9bb4f698,15e304d4,8166e3cd,717a1bc,a9cf4e4b,1f5c5d23,a36e392c) -,S(4d3bcef1,d6cff8a0,e0582d11,22eb7f67,28aae077,e9ef7960,ec519ab,3c6d6087,29f1b01f,a70e6812,3dade19e,d5d2689,6c491389,27a2da1d,3c628965,bccf38e2) -,S(6d5d596e,467ce203,297cdfe6,ce4807a6,1686a8c9,f0606283,5e0fa194,894d027b,ef58ab41,1d6a002c,12f469e2,e9f8ded4,4291b270,4b7490c5,4c70c94a,cb7b24ce) -,S(86f6ebc9,c25f6866,f14af018,88486b22,6c89b1fb,64bd9ac6,e523e503,e2cc6819,b0725647,4d9f3b4,8d4055d,e15b72ca,ce599bfc,247ce9a8,4b0d5e72,16b30425) -,S(520115e9,a47c3df7,23f81df,8422c03a,ea0084df,b122759a,8d6a5b75,540cb339,93b12878,44f22aec,9d5ed727,3d204d85,d3bddaad,73e3545e,5725b171,2b8417bb) -,S(19c9ff30,e5e50038,7e9be1f8,efddca98,7a72de0,d5cad8ce,7569d4e7,2b381009,b43b0c98,402748ee,16b362c8,b68ae79f,8493a7ef,293b149e,3faf7247,83ee3661) -,S(bdf0f8e0,928affd0,87566820,3c95b3b4,e6baf9f,f1da25c9,73814c27,551ee4cf,5f701bb6,8f8a6795,cb4ad675,e00b5ca5,761a0eff,32a1d3f0,9b29d5b6,3885163b) -,S(5c609591,37a48dfb,f778dc26,80de17ce,390ec33c,ea5cace2,a969ee9d,1e413e1a,670078d8,59a2c138,93946d1,e052552d,fd92c380,5fdf2ed7,8aad7795,2ddf2f51) -,S(98f22ef1,b9a62928,c5ddbdf,70e71c08,eb910ff1,fa6a6a1,56de82bf,bed8fae,f87be19a,9433d279,8088c882,5d122e31,bec9102f,c580fa2,24d40f32,2a2db1e8) -,S(d1842bec,2bfc5fc0,d5208d7b,40e04b76,88f26add,9b5a6845,751147e4,b4524615,f0405ace,6dc9bc88,48d18586,b713ca3d,67b76ad9,4f2f794c,55fbe9d2,f72ffa56) -,S(732cdad8,e0aaee77,473c0140,9702cb39,555ee048,357fa448,33ce8e3f,5f50bea5,24666502,448268a5,bc2c693a,85a1fea9,dc5f010b,a9b0cce7,6bf36124,bca1cb0c) -,S(6c86ebd9,5200b1ff,dbb6ce6d,e9fff6b7,1b6100e3,1144239d,77e7201c,db2e8af5,39c687d5,abff0ec7,c7ccc4b2,a4a16ba9,7324430e,a1ef209d,5ea126d2,cef24539) -,S(655d63c1,47441ab0,e65f9893,dd38f3ca,22d2d8a,a7b2c87d,a2e2293,b24ffe0f,d19ede94,b25ca138,94ab8fe9,842cae29,92cb58da,592c19eb,57c4184a,45121281) -,S(8efc14d2,d5845886,ec264438,449ff49d,ddab7567,69999bd3,6191cb39,efa41b72,9f1052fc,416db1a1,d9797e66,a816b403,475ac091,ded4dfdc,e262d527,3c535293) -,S(31a7f0b9,1686e695,d1fae6e3,8fcdbeb4,246fde30,f2ca80d5,2d9fde31,c728eef2,9661bf7d,46248da3,8ae1ff52,a8aba654,351a1f58,4f3bbfed,1875d439,3612190d) -,S(9dd959a9,8c862275,93dcc957,e369b2fe,5cc1d411,d4162ad7,d8e22b64,633adb85,78ccfeef,d95ede71,32a7011d,bd39b9dd,f77e38bc,47f7432c,f90d6583,5a6e665e) -,S(51beca99,fe3cedfd,1ba44caf,58c0fe4,8b926e72,50e5ca7f,8a187cb4,909b1892,12f38fea,aa9de148,7c14eff6,96cccf6b,c7cb23a8,6f2b7e0f,10fa971f,3545a0b2) -,S(1a84e21,3ef9b9a5,9f9a4fe9,d21dc1cd,1ec7a102,fd91557c,1129921b,781e6b51,aefbd931,17a42a75,13db0e04,782aa0b6,9cd79d36,b074f026,bfb7682,983cb78c) -,S(9eb14847,2d02a287,cd197450,78d81963,3943183d,c76c2090,9f68b94,12eeeaf0,6fe4b5a2,d18ac52f,9a129a91,1db00993,ca505380,2054b5c5,48f35380,c6d467d) -,S(9ecb3cc8,da5475cf,1a66ef54,3286f07,f5be1196,2c1fd420,b394bae6,c4256441,b4160952,e3701895,6f25c5d2,98ce90c7,91797571,267902a0,bba53d2c,2fe2cde0) -,S(541e567c,b2160fe2,75e9d479,1beb8ad0,4c07d6b5,12b43d49,888963f6,d6696ce,2444e184,66cc09d6,aec704c6,ea8ef670,4ed1488c,dd8107c0,c625b783,6534d6f4) -,S(8c061b6b,b6b55fc3,7c6d805c,808fb3e1,6fab1cb3,a05853bc,4933eb39,ca7b3580,20430304,c3780c29,a977f8d3,54424539,67924c2e,9a1353da,40716ef5,a0a0d37d) -,S(b9b674ab,361aacec,bbb69f7f,7c2b1361,44e55da6,1566ed97,cd58152e,4d391033,7841975a,4cf0b5b7,3bad8433,10866275,8a8eb93c,3b5db58a,15346083,f3d10386) -,S(3453c3d2,27e1dfc5,3e22487d,cce25ab6,18a3d25a,48f6fd1f,8e9158ec,dd6bfa1c,aeef1768,b754d998,fcbc75db,7a750396,930d169d,bf933c1c,15dfe041,17ff63a6) -,S(f36f7b9f,28463b22,d2c43e29,6b96846c,1b3401ec,53490c5c,35ec197d,da2c440c,9876476d,e2cfb7eb,b1cdef50,a39d20c,4ba5000f,9edef22e,ab7b96c6,f0cb5585) -,S(77c64190,33ef6119,ac3edefe,ed519632,ef5dccf3,f46066bf,6d5204e0,66788b5d,980cc59e,a103486a,9c8cfccd,213cf704,3e6aacb6,abbf3293,c833de88,e5b2716a) -,S(818911ee,6051c4d5,19fb7785,d52c6f27,a82e2d79,a4a55623,909f3d6d,b549e851,5d031307,a2d66fce,4b607967,f662bc0,af855112,11cc209d,8457ff41,968fa325) -,S(bf5900a7,7c211a75,231ebe58,17f91748,c957f5ae,b98377b1,9554fe90,d11ff226,d910b2e3,1760f0de,838cc159,7da6915d,e6c3fb29,80bc0e65,e87a36f7,749cf1f1) -,S(654b4257,11f03dbe,75b7d60d,b578d75,20e7cb6f,4923f774,8799b4a1,df06fa16,12c9e75e,26d3ab4d,645a7a64,d97eb6c9,356a3951,fb715bbe,9e42f500,a0c3f44c) -,S(33a425f4,f178af6d,48b78873,cf70da66,aabbaae0,397e6673,7a9c6074,15ab3d2f,1e5aaddf,d76b1b91,14016f02,1812d7ea,18decd14,ca3e3925,89894151,92178cb0) -,S(cb088930,f0ba3995,d7542d48,92ce47e5,5d8fdd5d,7adf60d9,3651240b,12fe7636,aad156ed,f0b25c30,e4bc3784,a1b7857a,4cabbe5d,2ceffb72,ca2cb7d2,45ddb024) -,S(ffa9e81,afb11dee,83a54b47,fe9b41e4,de4191af,7279d19e,90e1c528,7c205c0a,405233e,b20a4848,80210b40,18c098ff,a0a17203,c5a13b12,5ec0fe92,1d1c3567) -,S(92ce3be2,8fd6c9db,be1cd4d1,f58005b2,af0c136,89181c52,a67c2503,2649a6af,cdb840c7,7e0fc2c3,d4b959c6,6fc47142,622c8a16,b30168a6,c62ef368,8bd23932) -,S(46079065,b64bd3d3,3e3efc91,374e1443,69adc4a,bcd2bcfd,91ebed0d,88f78cff,b09653a1,1c0710bd,b737611d,e5d80e67,a516dcc6,2ee3f63f,e2d6a7,f3794ae4) -,S(5cf961ff,de982138,958471b4,b316cae3,6246ae74,e1309400,a3acd118,e4736c93,ab8e425c,ab39325b,b94925d7,795d8799,18efc449,e44c9f03,cf7bf487,fc32b185) -,S(d8fa1009,27c1aad9,6ba97005,f8a24013,bc29082b,ada0e0ae,f6f72ec9,8abc4240,38d88e5e,183b2c09,d53adeb5,8d0525f0,83a512c4,1dd64cfb,a7024602,f39e484c) -,S(cdabe8c6,7d0d4627,54cdd3d5,3e70bcba,e2ec925c,a46a4536,ce3be9ae,e0b37d8a,c2032dac,527cd15a,a1d812ce,1c658cc2,a0a379a5,2a30613c,2737812a,6e683830) -,S(394fbdd6,7069d83,8fdf87f7,b1c179d9,1a491ca3,680f0103,46de3299,37e92374,5ceac741,828ac862,7fcd587c,69844243,d17ba038,901cdb42,36e96685,d589a693) -,S(84eb6d44,103f56df,96617c7,11c79dc7,a6161189,157a0782,74fec78,fc5f6c37,57a16660,4d1fa3d9,cb358e7a,47984a00,6926df57,4e06a313,7b3c7524,2e882320) -,S(295dca03,657995e5,d432a606,da12bec9,fec8f4f0,582d75dc,5657c973,7cf1051d,c4df0ad7,b1e3a29d,cca4120f,478a2d63,f18fc67f,bd201be4,e2fe05fa,66ba2d6c) -,S(b42d81ca,1bdfb038,d7888194,deda7307,eb846bf1,738d8b7d,89663bf2,8097fa7e,2d913cc9,93ed5118,1082c85a,42495133,ace8bc6c,65530309,c6e15794,aceff5cb) -,S(48484186,4f6d8f3e,94977a3,45bc0db3,1330910d,4c555032,da8da876,912df644,7a78a8c7,68c9d9ef,b5242fcd,b7a5946c,5fbedaa3,2914339f,8b0c0ac0,eb8a3146) -,S(7376d600,9a7a76b9,dfb7e225,c0da3186,b683fb13,daed9fdd,25ac6606,7e7d2316,fc733036,dabd7c4a,719b699c,da115547,8a52d69f,387b8a94,28744144,c0502901) -,S(9be9c65f,5fd6cbcf,522eb9ca,91427f68,152caa2,a152051e,3919307c,9f67ab8f,14da6642,fa3b7c37,41c9f953,d1e01c09,267b7885,8414fe5f,24f47c4,b44c413e) -,S(7d0ae5e4,18d6c6df,45f6d26a,7e962335,4ea1a338,8f183eac,85b1eac9,1962e2f5,551eedf8,264763b0,913307a5,14fd9e09,479f43a8,87983e69,509a3688,d09308be) -,S(d91d965,d3b85441,acec7257,d444cba0,6243b34,14e9665,9cc62cbd,89aea7db,54e26ec,9c82bf54,f06cce16,2cfb924,2a354c83,fe530937,9bbe733,6010f44f) -,S(44c8fe95,aa48f8bb,6c0a32da,a6263918,fc2df7b8,6a68f277,6bf405cd,1bf0566,87fc1fa8,3fea76e5,52f53612,45e54053,9d70377,cd865915,b6b78acb,f73a6e03) -,S(c7f8e825,5f2ddcfd,f21c5c20,ea84a527,2c5f6c59,99843c96,3bce9e0a,aa7ef398,5c1cf086,9c1f790,b1e59ddd,ec9729dc,2b73c6a1,be333dd7,e423a0be,bee50243) -,S(3a8ebd85,a2bd4b1e,6c0373d0,63e9cc4e,a91e6e1a,f4bd7af7,501e0160,8fb7f4d9,4d9351b7,3c3f6f36,1b86ae94,ccecd211,ee3b13a9,522d799f,e78c87df,4473f23c) -,S(bb01a4cf,ad90f3e0,5355f0b6,d1b28420,786c09dd,9db0ed5b,38a56506,4da77e9e,1742b511,43bc276f,273afb9,8473ee3d,3d962050,7462cdf4,a8c641ef,cc2eccde) -,S(eee45594,1a04bdec,a02e7e85,1d86987e,798c27df,adcfd5d8,2979960a,3983f4b9,3cc75025,9b5d215,37570928,1abca8a9,29f5609d,56c8dca4,3d1b23d3,cba3fedc) -,S(d2290ec5,120d591d,2e4e2796,3d10c0eb,e73d8b9b,600587ca,84173ce6,796123ba,c4760011,4c68baf7,b4053666,d8bd494b,b4ef1786,c1d7a522,8a656f10,1c837304) -,S(21e359ca,9b7326bc,b3380282,b9017df0,3cdfb7f0,af95f326,701bd8bc,25dc047a,68b866e8,555206e9,7cc43461,34c3a61d,ce2a50ab,2b514935,a05f8e04,ad95c70) -,S(b4acba20,94b35033,5095b208,9126367f,3203efc3,35caa43a,51857181,f4987e42,fa0f72af,77db4913,af6d906e,54eb33f0,a3e9d20e,d366c878,3b7c513c,c5165c16) -,S(5ac6b2da,18754c30,9ae46ac8,3592d673,ac5d61e0,35ef1b4,512aa9b6,7551862a,e93b1d74,105974cd,b6bd3043,c0dedb8c,b4eaa81,c949999e,68d52fa,4a3941a8) -,S(4a53cad7,2a894cab,9b761157,38ae78b0,c36c293,c60ba8d4,b87300aa,792c51d,4b0dcfda,b890ffdd,cf8a6a71,15f2a351,d883ad8,fe3d15a9,118f3e04,43f840c8) -,S(5edec48f,7d8c9b4c,af3371c2,6e054392,755fa073,1e660971,4e089b04,2a07bc36,b18b8d1e,407f934f,e526fa5d,38b3a408,76bab92a,2bc192b5,b7c206ed,6ad040e0) -,S(986b120,618abe6a,d965f9d9,6f50fd7b,29f1b897,8276ff8c,562519ab,8aa92890,2c981569,23ff1809,1cb47459,bafc0d51,699740b,ca59dd7a,14e07b9,432f681) -,S(8c61517b,397d36a6,b30f0894,98d525ff,bbda959a,126e9be6,f67b9831,e5e7372d,f7608f24,130ce8cf,56a7b762,c1563519,a4be88d1,79e90f1d,b432ac05,d472d771) -,S(d6abe67b,e30fa40,b642483e,a6ae7ecb,4217a07f,35546f97,469aae99,a286b8f6,b5e5675c,91aa08d2,a5a77349,5f1ad2bf,8b6b9dbf,4b35dc6c,262ff1c9,8eaa70ed) -,S(26be12b4,ae013009,45c8ec05,58edb030,e19a75ad,872104f6,8642bf5b,c30f7934,1086891b,3ce97d8a,a568fe54,28164f25,4fc15953,c97d40c8,f32c0ec6,6ed49fcd) -,S(3f0281e9,1dfdf1de,69d5112b,1b86ea89,d737d09f,1cbbb71d,2400d0e7,719987fb,27451e9a,2cb336a2,998d55ca,ac12e16c,fffbbd5a,3703897d,5f566ab4,5f4aba92) -,S(b84b8115,7b1782f1,e4b641c2,a001daac,ac7d53f5,b3f1fa5a,d0a5ddc2,732af3b0,a0c8f7f4,8fa49815,7a6c590d,4ea18dc2,c586b332,2a303061,c19edf44,ebba25ae) -,S(790ab328,fd86da4c,66f0989,296229fb,609de28e,cc8cc6d3,d315eb89,fdf31e38,cdcf83d3,44d103c6,736bb5c6,375bc2e4,3fcc46f5,777d6e5d,cc407700,15d29aa0) -,S(d5fee68a,f9b7f182,20ea6525,6a591f24,da79a642,4ea0fe31,88a0b658,9006fb51,87b8608b,1b3d0d71,c9ab2c9b,84654408,af6551c7,1e8ec6d4,a8f26cb3,20577532) -,S(410f9801,4622b22d,62eef39a,3c5350c9,e80ecef8,48c4295e,2ae279ca,9623e777,53dbc737,5766d9f8,ac0b8b7c,e4b852b0,3214fe70,24386915,84856c83,6376821) -,S(6cbfa6f,fc7a6009,75edf0b,c260bd2d,258bec55,382e650d,c464b16b,e5f34eeb,de72cf4e,33028bb9,18ed3a41,d885faf7,e1d5901a,ad7a325f,801f1a36,2ed730c5) -,S(2a75c02b,3325ec0b,ffa42250,e224a4de,e0c4c12b,69b71039,4bc3040d,80e5c504,ed666a2d,8ac26964,f0445d21,f1719ada,fbaea128,9edd69bc,94ae6123,a2e6b8bd) -,S(ea2bbd57,6c0b20a5,6790ad87,29f25475,24ef97e3,86663aba,2473994e,fab39134,d98d55fc,daedbd5c,3aab619e,1288634d,f526f873,19743f81,149ba85d,535172cc) -,S(893e9899,fe1b8a92,439c1594,634ff44d,1d0a60cd,8a0183a,b810bb8e,f80d0400,c680717b,aa2ff029,7baa807,d7290190,37c73d0f,a5a1878c,9fa2a6dd,d17cbb2) -,S(d75b0a2d,1e9a20c5,398fc3b7,cacc79ba,fd53a14e,ebe23196,e4bdf4a8,f8546422,37a8efdd,618bcff3,3dd0c0c9,f8bf3192,2e131764,305b610c,88a2b74e,44672981) -,S(96c84a8d,5dd2ec9b,44a5b2d7,af3b65e4,9c07786,969452c2,5e8e64f5,a264c14e,292ed1a0,dafdf3f4,83a2a419,6e1b6b28,4d7daf88,88c7268d,70e556fc,ff55341e) -,S(458895f0,77782a62,43abb775,7daec5af,264a71e0,6eccaf8a,3b23baaf,fbd7343f,809eb056,87bb618c,a0f4e1e7,c8d05e48,95f18393,2e949b22,b9ddab0c,55d32b93) -,S(59dba4a8,d7956515,7f639316,75fecc7b,58a0e91a,6c9c3d50,7dae6d40,2e67a9df,718094a2,83e47265,1ef52d4e,db25b0b9,9e069f,391ddfb0,d9987596,d2f4ee2f) -,S(a5f92445,b7cd75c3,9a4b3199,96baf00b,f855ebf,ab3e19bb,71d4346c,878b4bb,9bb1bdb5,baa4d56,5b9c5077,c86b96ec,953ce381,17cc8d53,7b0f3957,a582ddd1) -,S(f146eff,2a9ee1ec,a3f26d6a,17c89639,a1f3505d,2776e340,ae89449b,99c8b198,1674daf7,a66f1a89,7b5378e4,add6a196,fd27795d,88969a07,a210d33d,646a64af) -,S(e67f5967,d98c1d3c,3a4d0872,12d3b65f,6f8df216,5dc14633,92c23ecf,ffc17e1a,c3dbbcab,d1971eb7,a8b088c8,c71d65a8,328bf43,58f0e685,9025db87,e5391380) -,S(32e8d775,ed37cc2e,6f69c85b,71c95d65,d40f033c,b5eef362,86d4499b,fb6071f,2fbb1d8d,a6364791,95ecaf52,6f63eb86,e4604973,edebbf82,b796d88b,ade44334) -,S(b98c7cac,475ee4a3,c1815a17,e460f76e,e5334b27,e1ea319f,be8924b5,819a473b,d7f1bb1b,a653f20d,c7145420,d8c8c339,d789ee60,9b9ff0ce,73910b94,3deeb88f) -,S(d9830fd5,545dcca0,ee37a402,9f406cd7,50bbaf59,e60a80fe,da976bbe,ff9027d0,cffab795,e45a2833,75e7b861,728421d5,f9e22d03,44f835a4,c55207bc,6479b947) -,S(399fbb5e,4f4e27ab,3e737a32,d065fdd8,c003ecaa,84a2430b,4a7b4d40,eb6f9721,93f7b541,121d13bc,480f7868,ac9d8302,6706d2f1,a46955de,a3912735,c5f02e0) -,S(64e067fe,17127128,6ef0fbdb,b2adb4c3,395a1ddd,f2ea76e6,261e6cf0,112c6227,8ef6afa,4bac7536,a23f08ed,eb8656a3,47a13f25,2dfacd37,c215cc3f,473687ab) -,S(57eb5e46,40721263,97f0d12a,532aa1ff,abef7822,4ba9b10e,8fc95e1c,6075a071,8a700d2c,80df0b4d,7e2c9291,9a51e565,8dd6ba5e,59bf1503,7bf7a0a,935545a1) -,S(b83adb94,ba1874cc,c61ade9e,43093cae,5bd86ff5,e86615c1,abca14cb,6eb81877,93417bf2,1fe01c85,5c6f7782,a5cdb01,a5d13b29,d719f0fb,a2373ba2,8bada7f1) -,S(7a90bb49,71537bc9,3d1bed23,891e43c6,e350fa37,ef8e73a2,3fd46ea0,5ed879bf,ee0fa59,3a51af19,70a6d8b7,22d42bf7,ca253572,2324a59f,c041b3e7,305fa3d4) -,S(195e4afc,6c95d6d0,8273cb0d,fda2da3b,4696b569,650d4230,4d396fb,3e653831,44075199,9dce9d6c,f10ef736,7888dbb3,a713423c,f2881cd5,76a681ce,6fee2c8a) -,S(28ec566a,29bd09e2,f8b228b9,ff2ec49d,56660734,f2ea864e,856be0ff,fd6f60ee,5b4f5e34,298b5a56,a6826143,8ba59d25,4922078d,f36dfdfe,d4e8972c,647fe031) -,S(1e005b72,be1bb77c,80512581,58e940e3,544cc133,a76ddf49,b681422c,1815cd22,9c523adf,4ba5d753,93e432f,491f8e1a,435165b2,f40f79d7,889d82f,8951a25a) -,S(f54ae39a,d074c399,636f0dca,682b9405,4e87e87,3132d7f9,cf79ad85,fa82586d,db2e9b90,1c2dac2f,f4851f4e,b0ffae7a,4c0cdf34,ae9f964b,841c539d,84040667) -,S(bc8dafb8,d385cfca,3643fc75,c8a93f9,792d2b9a,715269b9,ec40d581,5936e6c6,dda791ce,186ff28c,db7636ad,4073996c,4a2e2875,80da17e8,90d03886,1c14aec9) -,S(60b6ea82,627f5414,16978e7d,3c9d911d,9d9de92f,3baa0975,a8de4e3a,8ed3ab2d,64693ab,fd095109,ef89cdb2,204f2f3,89dae035,f451fe28,58fcb4f1,dbff0999) -,S(9c8d1352,bf291803,22730718,5ee65aa8,b14211de,6d73dace,2937cc6a,1ee79134,3c6e0d66,48f3fb6b,23e6e4a9,5df3911d,797afb50,9c12e90d,7eac557c,7b1a9505) -,S(bb2a8344,2997babd,6cefa2a6,1c9d2fc7,a42db3d5,bfb19334,c7535bd5,630be896,20de4f27,69596e65,edcd695f,61a0d8,3c8925a0,c8707470,9e84bd41,615ac75f) -,S(ba8bca72,496a6046,7b250a38,cbb536e3,b9fb9ab1,43800655,8ef5d186,2b66d50a,81abbb33,e835f864,3d075858,7ce59671,7e08c1c6,75af4c5b,eb80429b,9dc46aec) -,S(529fde52,c4d1c978,405107ba,d862f7b1,995ffef5,cba4a59e,d71b366c,28e17b46,ed7c2521,d39ca130,60d5f509,d0a8b0b3,40eb78c0,d4e4fc4a,83318a65,226d0a05) -,S(6e0e10c9,4445acc3,593efdd5,4b8ea1f9,db4a45a1,4c2d0a27,edbe3fc0,7a90e91d,43537a25,d2091290,f753460d,8816ff10,41308e6d,fb04b7e7,d5a108d5,c9fd83a) -,S(b2f90714,6fe2e01c,5cbd73a0,c0a358c7,a05aa730,97a060ff,491f362c,75c20e90,d0e680d8,f7d27eff,12b332e8,a92b846b,4242a746,9b31740,6c6af499,5ab51948) -,S(bf631a7,933e3ab5,f7b8707e,55a9498e,31ec3f36,970bb9b3,f5efa0cd,1a3f28a0,1030146a,387d4fd9,c12544dd,a448133a,49b5a6e0,d4b96933,cd47e89c,608dd5b9) -,S(cd7ec470,e9d5e3fc,a4c344f2,9edcd4df,4b7033ef,5e7ee99,de0db6a8,43926034,3aae77b3,bb008cb6,e982d673,7f78e920,f3a587db,bc106c0a,25c65d45,df8a4f6e) -,S(b3ac95ff,8365813e,e71199eb,946b5888,7dd34b1b,a214482f,dd3b7fa,3b8ce6b6,e3d9bbdd,aaba7887,8e763360,abd370d5,9d941ba5,cf758d33,3b480f00,ec5e7672) -,S(7fdc21a8,6962fced,e6f9fbdd,77e60a00,4dfb858b,5b149362,dae4b4f4,a4ab84fa,2ec0f21c,3d1c6d60,f22817a2,954d02b1,ce6e8b91,d826c11e,f8e542c4,245a55f3) -,S(6f019691,def39afb,103e524a,598bca92,3c99e44d,7dff4866,f76fb6c4,47e6b40b,a225b484,cda916f3,559e5782,3b519827,8bd7300a,c31dace1,7a797582,2a2e2a31) -,S(cb9a979f,c4e8d887,f03956da,9ac89637,579813b0,c3b27874,82961a54,e54c16a5,ff42bdc3,1a837d98,b7d37a38,db3c74ee,6109e868,d06b7c33,d5562dde,b11ddbf2) -,S(2ccee51c,9d63f3e8,99314da1,656cbb15,635928bd,309cde4b,69699860,c0e28736,dff9a128,adb8b4fb,7bcaa1eb,6bfb390f,226b2ae0,b72443a4,5982d559,91d379eb) -,S(a239538c,c5e0b53e,879f484f,7202a52b,d52d1cdb,ca7ae7d0,639850cd,b2c4f57c,6cc1f9c5,8998e347,2c6db0b8,6b1d9092,d3cd0c84,267bea8e,75a172f9,f4879dd5) -,S(e77796ac,c619974a,63476635,7bb3bf33,6ad1e87e,8496bac3,378db956,7beaee90,3eaa4b63,c9679050,59d8cf67,7b7095c,4064534,1c592ccd,ddb7626c,10586f0c) -,S(52c332cf,37646a2c,c1bf25cd,26a6131c,3b243688,9c44d804,d2762fae,618250c6,2279bab0,a19f78a9,43e695d4,53a0dc3c,f0312987,6ccbb70b,1d61eae1,e92729bb) -,S(d68826da,36e5f78c,bf728468,88bbe6ef,f6e55d34,f8b47a9c,8296e662,4ad9bbb3,88ffeb15,5f70c6ab,9b83f9e8,30e2f449,7e661dac,889803a6,d30a2ddb,11bfca5f) -,S(af92bd8a,2a5b0034,ea074d69,a1d7a517,808d3b61,58f5f7c2,d3fb08e4,eb825cf3,2fef9245,a4a3c837,d4b57ded,52009294,c077a801,8f633313,b6db2d4c,92c724b7) -,S(df86fa3f,63d95d73,98872011,c7545b3c,f5f27fc6,a821bff4,5d09afd1,bf76d895,a891e766,12953c4f,37a463c5,ce449574,b1906c63,c192ba4c,67f4f78e,d1e93a35) -,S(a049a35e,119e27f6,e272774e,f470ca50,9a1da9b,a4e5d781,6e64a13a,23383c24,4cb8e2eb,ccc82ca4,a2f82841,34eb3a05,f85a2335,a3b1b117,92886029,96fb3fd6) -,S(b3193cbb,f3c8f3b0,b47b1a0e,5689461a,8da801c2,4c8d51ab,fc2e67b,1d9f331,2032a290,3f0cf0ad,21b63de1,565170a3,edee470,a4dbbabe,5f3d459a,3827c7ff) -,S(ff3cd387,554fb3a,89142ff7,3e97fdd8,884964bb,2f457283,e45b79ae,ef1d692d,24475b62,c1ade1b0,ba36ad93,27916e19,637071c,22fb59c1,f2108fb8,d38ec5b2) -,S(c095d24c,42b058d,c2f77e2b,463a2c7f,1ddd1dae,dd6f6111,11ba78db,26763204,d2648519,61974d6c,cf66de22,1028943d,ceccb181,ae03cd38,fb5aec22,fae54326) -,S(5365a446,389f54dd,8279826c,e1e7df5d,b4a9699d,b8208efe,80d1eff,2d883ee,74625a49,b7856c1f,b157776c,cd79270a,2957862c,a437bfc8,75986264,401e714e) -,S(4c073085,e96134b7,75248412,c36b3b33,77afa275,24c83369,a2477b8c,9851f15e,fed40d9f,a44f64b1,59c290e1,63d1add6,92bd2782,51de71db,e302cbfa,67e508aa) -,S(71edf152,ab95a066,2b7e5190,8af75f38,d03d27b0,3a3b6607,4f472b7,706a3114,c3e6f145,dad44a3d,5cf056d6,2c608b4c,840608bb,aa15a101,c9bd3cca,e511741d) -,S(1b7d41a9,3cba67ad,c145962e,7b2c6353,bfbc8eed,34eb4c27,bfc181d3,1ac0a802,b165e7e4,23c5d880,1bc3bd1,ee0c6778,50986b35,9dbad06e,aabb2f57,dbe553bf) -,S(ce997626,cb41ab98,58f591ca,c89f7a73,bc1df836,716ee74c,45c4c781,eef4ccc9,be76f81f,a8e4b053,f63be23a,5e72ad6b,7aa359aa,e9407b60,98bdcadf,e367b167) -,S(5b0cfa70,aeccd544,cd634d10,a2bcccdc,33e4525a,54259ba9,92c40100,698bbf2f,ec50e655,163994b6,4881369f,b3aab550,65df1a5b,dc6037a7,7c01e56,904660d2) -,S(a03873b9,695ee82a,42b72a90,f0cdfc68,dbedbd2e,a50d5ff6,e120d811,ce8d5097,5947c8e3,56e64f71,b36fc1f7,7ecfc7f,a31c0f0b,cbb05102,775648bc,f2435758) -,S(d6b91cc6,6dd31e59,f04c6e58,bd7448a3,fac62753,68579214,11a8b42c,66084ed1,fec7fa6d,778c0b63,e7dfd72f,ef044da0,903ccfc7,1786f0b1,85edd004,f691a0f2) -,S(896a1313,e0a96d35,9fd42841,7790baef,a40647cc,f56264a,ac3b72df,687b5692,831d4b47,52f5fcd3,4942ca26,95dc86d8,4fe49c73,7c2bd46a,f892eef7,304117e6) -,S(779e7400,8e564167,56795a4f,9d2021b7,94aa9689,eaa37780,8e3a6061,b5bdc04d,739ea3a9,4f38be31,df57c052,362d1872,333d2777,c6704c2,e69271d2,9f78b123) -,S(f20988a9,3a3273a5,a015866a,c4de930e,507b5b48,cc5ba52f,a2a71e9c,185e72a5,6c861907,8fadd612,c0535163,dfa4cf39,648b59d6,4b056bb0,4e06695b,3b51213a) -,S(7e8520e2,3151c78f,9f48bd10,5aff4087,dd90f9c4,2ac33e24,19499ab6,8e5b21aa,995827b,43c276dd,61403388,27b2fb9d,9fbb46ec,af10b65a,a8025971,608f38c9) -,S(98f0e4b0,9e72ec0f,d80ce3ad,eab29913,fe84fa49,1786bd79,7f6832cd,7ed4dc6a,58c42bdd,7ca43579,b45df8f,b2a6db3d,41f75a3f,89dfab0e,e000383,c9e04a54) -,S(31cf38d3,dec1162e,e75eeac6,6827aad,22fa3ee9,abfda002,b6956600,6fe596ec,ceeb4b04,fc6c31e7,7a6260ca,bdf92569,92841221,d60ca74e,81309472,8fff4442) -,S(60766d5b,50cc4d46,a1234c92,1baeec1d,29900e23,4493f174,2f06ada3,ed9dfbea,13debdc8,9795f421,6f796a53,74b87aaa,bca4f73e,fda2ecf,7d151870,179c44a4) -,S(1b0ebbaa,35e8ecb5,a76d9c30,ab88fa10,b211ce3,e7c2b428,117645b6,881c7895,a312adef,e1c4a34c,d9f75d10,bb2ceb29,79184181,bb955439,e317cde4,202b2f83) -,S(b3129f71,c3438602,c9c24ee3,2f997341,26dbd76c,60cf7713,200ffb68,e486fc94,bd4beeb5,70966285,6a15002e,a25046cf,996a1cc7,9a570549,467ac179,b4f145f9) -,S(2925ca17,662f0905,3927d40f,f2fdee1f,66cc5c13,c3587e78,fe48effc,40cc075f,6d37757e,64f0438d,7bfb3658,5df58dbe,a8ab8cdd,89871670,dbe221b7,4c416185) -,S(8d55b85e,fce6bd0f,ff8906d1,6497d35e,4b69e701,da7845f2,aec1a049,39c9ec45,435416dd,9fd01388,b717ba9a,df574456,785cc0fa,c115dc04,8a242270,4a3c77dd) -,S(a660a9bd,b419e19b,16823b5e,dc3fcdde,f1021b71,4debd17a,9a0619a3,aabc23c9,ef6d4bbc,e963bb1c,2edffa5c,ef70e330,bddccb4b,3b23cc52,d5b4a689,e0c76c32) -,S(8896427f,c92bdbfd,59699ec2,222b4bbf,2198e160,94945c77,1f207bbe,4cdd6b0b,bc6081fa,abd2df26,b087acbd,a2c67c63,2eb1a8dd,6fae2454,6f3fa747,be421ff1) -,S(47e5d9b2,3f429484,61ee9f38,2f14babb,f93e318f,32d67063,ed20e917,9894e993,bd17f8b5,6084d3f6,62facae,24e93e3e,29205f21,68903ade,4f7476a5,ba70e8b1) -,S(ff352870,69bf1131,6f530ef3,b32a487b,3f11e6e,f8518c15,b1202a18,4e6d5487,8920338,ccf36f98,4afde38e,1a74528e,86fddfc7,8d7a6964,cad4286f,231462b6) -,S(2a713d8f,eca88def,b5fda7f8,8de9c6cf,9b97bf0,4c070173,aa47dad9,197bae2d,5ba64900,f7d18ec6,8887bd26,d2769b0,26d22e96,1007b58c,b27b8983,a6e7adb1) -,S(853d813d,3133ed7d,a85065a5,755ca0c5,3f32f156,154853b4,b018668c,b165ace1,fda8017,e00d20db,6ee4c0a,5790b504,afc376ad,170d74bc,1261abcd,241ea020) -,S(d5c4dc15,37b048d8,6631fd14,7d896d6f,f403ceda,7de8883e,1ccc006b,6d9ccd99,9ea2829e,64213434,eaaaadc,43ed10b8,28e706a,5001d7df,47146058,8bffa8ed) -,S(f649da82,d50fa298,8c598d5c,caf1e7f7,2bde2cc8,8073b55a,2e43b6e7,5d44905e,4438f4cb,d3e1938a,b461b1e7,b94d8f6a,c6e287e2,50d06da6,67aacb1c,609bb6cb) -,S(adc3515d,4fb7776c,b1592a69,13254d7,afcb20bb,8a4d7529,7ddba70a,c35a7193,49b7bd8b,3f280916,c6024e46,afb45e6b,da5bb15f,3d3497fc,85e9a46f,acec3d80) -,S(d78c46f2,603a00df,b45d0495,c1e2b346,963dc82b,84512cac,c2227acb,383f75ed,76b02870,2e7a3da8,79272759,1e2f81ef,54ed02f,debde8b5,38f9ff1e,4335a21f) -,S(13904467,59e0fc27,c2a499ec,384e0906,bf293dcf,c13ca16f,d3bedfda,d320e466,5320c884,b74bcdc8,6e0c21f5,40c16f65,dc61f19e,9ec5e8ef,385fb637,ee7a3701) -,S(93700603,543ec558,3fe48141,310b184,aa8faa04,6058467c,389c10f3,b98c42f0,8e0acf55,bfc585df,4f8cae06,131753ee,23a7bcca,68354182,61450e1d,e1a136ce) -,S(bdcb9434,4c556618,a247c935,29c5ba74,c68f25ea,a5507148,1431c00d,6926884a,c29b7b1b,ad6ec5a8,e7046cf7,cdf99c6d,15f6a3e4,3c6ce718,9ae2acbd,531bb17a) -,S(839ac85a,9337818a,b07b5611,f67eb16,6342c1a6,8aadefc4,6842c023,336afb08,88b30690,e79fb157,3e424c80,75bc810a,fb9d57de,5464a253,79d06222,ea656b69) -,S(2959c32e,bcf9289,9882e003,c8a28e71,3d491402,4d24d878,ba8bed88,47b949c,ba2643c3,95fac027,6b7c55e4,d2d2f530,318665f1,ec2065d6,eaf32c05,123e04c0) -,S(71116eb0,5def3abf,bff3e235,a0306605,b18aa465,b47167b4,4eb3486c,c442f3aa,2652a726,35be8336,f9b51607,76b3af84,26a23716,871fa64c,898520eb,822d6630) -,S(400c1bcb,dd3e3978,3ca06e8c,2abe8b0b,9b45034,a1655cde,fb748ef4,e2a477af,1471c86c,c8b27b48,1d4c45d,1533a5c8,d46fc3cb,ea4788d6,c48dbdad,6f7670e3) -,S(2a4abe28,5cf94456,aa92216a,dd635abe,71a7e825,712d775f,d61fdc98,a4c9288f,3c0d2483,3d6ffcad,b471d234,4ee8d07,15c09719,b18cb581,8ede730,35d89c15) -,S(cb0113a,1832843f,7e32ce25,15b0b23b,8a803ea7,50b500b6,3fb89f6c,e7bb1884,816d7056,b775f13a,cfd94a6,f88f442e,519495a3,6e74d8f8,359a8a03,16583bda) -,S(4d7be7ae,5c4271f6,c1adeb7f,4dac8467,beae22bf,ae00a71b,1e353be9,5ef172fd,cd7e6415,5708d20a,9fc3b0e9,85517642,f677281b,49490439,14845a36,afe6ca56) -,S(bc285658,fd724cfe,e6ec8c7e,35f9197f,e9083bf5,439fd4d8,d9b262bb,7a3c38f3,80c10d7,59f76b4b,8330c96f,38a1af24,1d1b0db7,4e6befc4,4f085180,c1c33729) -,S(a829ee43,221d9955,38ce8aef,e80c49ac,dc6e71f,4293750c,c0585c1,69963f04,144f6b56,d996a18e,627d4c8b,8115b2c1,c369f410,ec8924c1,73382302,3758ba33) -,S(f5450bd7,efc9227b,e7d28ad6,75ee14df,1b2378fd,308e6c5e,68945ac9,a47d82d1,20201fb5,cba463af,cc46e6da,caac8417,63356e64,5cdcfa5d,9d810c48,272cf8e0) -,S(7dcbdb69,46dcf79d,454095f0,b61341e4,45243bc7,c2262817,374fea5,37a1a380,bd2cee4d,c7ebc71b,46fb3bec,bd6787eb,d2be3128,703a884d,98359c5a,43875977) -,S(f1d6c1db,cc8d33d4,fbff821c,8c788d06,2d906063,2f44a786,585a6526,20ce776a,3696a3c,8473bd07,76e77226,8cd09f96,3dbcd143,e631c32d,5d83254,ada29340) -,S(f1688e1a,d5df4e43,67caec6,f2234534,f65aac3b,79a94ca,32a786bb,9fee4b49,efb620b8,e2164685,c9a3837b,5c6eb70d,759824,96541aed,eb80aebe,4193e34e) -,S(b639e284,3ecffb0f,66c2819c,73787e10,527086e2,5d3da074,e037a915,e06a5813,61fde1dd,63ff304c,8ec99d4,67ffbabe,e8000637,b9856bec,344b825a,4f198407) -,S(11a4ff89,d5e63ec8,6a0ce18,53dde8a8,875c9a9b,f563526b,cd25b830,6e3314dd,9f7ec77c,9a3f88cb,7f64b1ca,f2b5c7cb,d70d65d6,dbdba9f2,68832f3c,a2e117a4) -,S(323db783,26abfd99,2b13d67f,3ae01415,77162203,c50322c5,7a7933e8,7d687d3a,92c8a67c,ec834653,d0f1a50e,a7834b38,631d83ec,ee38e50,33ed927f,7e14253b) -,S(2907fe12,c8433ab6,2e6283ec,85b93342,ecf14d16,6d90cfdb,b4061968,aa35170f,160f9790,66291ed7,d51962d4,be02d85f,8a92ff8f,258a9a07,55b8a5ca,2d57c2c2) -,S(67cef7bf,a58519cb,6c5cd8c4,f69d5cc8,84cc77a7,854a4b6e,a40b6dcd,57e43e17,e8071d35,e590dfa7,4d4f4da2,82033f1b,590b9383,70b571ac,ebb3bc11,b9b48482) -,S(81e40522,3d4ccb14,3952867b,b8398cd4,e5ab92c5,d91066b0,d1fdeaed,55c71165,55357564,af12b507,b2e24e6a,425697b9,e6356b82,da36f111,2b5c3394,183c0d10) -,S(4880abe1,47bcc598,a3743304,1afabe99,fc525daa,564c4b05,2aa60c27,5c814628,b6d944f1,ec69e7bf,2cdcf621,864ba76,a1df44a7,ed15ae15,290ddbe5,b91f585e) -,S(fa2bc507,19131dc7,d5f23fe6,9e60377e,2d2f11c7,f8a9a451,82aa69e6,24eef53e,9b0f2017,5f287d80,41f58930,6cd022e5,9b63bab5,1b26abfe,1a295ac3,46a2e9fc) -,S(aaa18fe1,25e781a8,901ac351,38d2bffa,83cf7c3c,99a4c7d8,54b30c70,c9483e8,6a8f9e1e,a40f6383,6008a0c3,596f7644,c044bf53,9700a142,ec5e3c97,c075b03c) -,S(d473950a,8465711f,71a6f1f0,22f4bfcc,1c16ba81,4bf73c2c,1eca244a,da4999f1,6eccf9c8,aafb09df,46ca0d36,ee9028dd,1df62bdc,6ade77b8,a5d410d1,a69bc775) -,S(d7e2b17c,f8e1895c,cf9fb163,b56f4be8,ad99133f,f00f2ce8,8ce911d3,3b8e36cc,b6557693,ed9371ce,69bf397b,56c0b566,21d38958,ebdc0b96,ca488570,1561e6bc) -,S(3f1e73f2,a2192809,acaecea1,71d175af,683e796,e1337db2,11b6b34,8ba924f0,a593bd94,96308bb7,76b63703,bc11e30a,c5f01c17,c8b9748f,3b4c8015,56f52c3f) -,S(4cbb68b4,27899c92,1c0d969c,94341d8d,161f3b8b,3fe4cfca,2b583a63,eb383dd2,6b3c29d4,97728ac7,b45cf7ce,ea618789,95935bea,bd146e1,6c756f61,4698b6cb) -,S(e41b826b,52ff9bea,354af41e,3004b7b9,edd01e13,8cbd466c,ba4cbab8,d63bb4e0,75d5b642,47388aa1,51d4d8d5,2568a804,fcf66ba2,42b3f56b,dee0350d,ecc527ed) -,S(d508dd5b,ec38f795,88bf2d9b,6bcc9f8,aa96689e,91c1381b,9f8db311,94588028,9b144547,1a2ee559,6584c927,2d779fa3,123a760d,9faeabfa,1e39d3b5,ddac2595) -,S(5276f127,3bad7149,ee5ff022,2769dd6e,973018e2,a9948070,fdc82148,ac637de0,73f778c2,caca737f,acd3d877,14e24d83,964dd47c,f22915e6,212bfb09,8e804e21) -,S(2e9ebbb5,9d108d21,71d28c27,32af659d,b534cd10,c5457cea,3fcef018,4d7761a,229d20ba,cbf0104f,b385621f,dfe386df,4f40c287,7d956046,60eb3923,46937bff) -,S(ad819539,5b94bb1f,4e60ab85,932b24cf,2c79c20b,79a972bd,db1e4201,c49f1d1f,9226c45f,4d161a1a,c5c3c0ba,a0536def,3c6052a4,ec22dd24,cc803a37,b5d791a1) -,S(f5d4baf3,93ee5acd,944b2057,78cae170,8a622f30,68d3147b,62bef05a,88fee96f,9a187396,9eeba528,9f5fca32,6bbb922,2eeff5f6,6d205a0c,78b77dea,ee17d1db) -,S(1a0f5e1c,b2fb5d01,fbcbfddc,da83693e,9619ea60,1669c728,7710733a,e6ca778c,3074e8d1,61da2d34,38be57cc,fc437742,533e415e,5f0c888b,834a2fe5,5d4fd6bf) -,S(a78f6f7a,110cd16f,99fbe16e,9be52782,248518d8,e621f478,2167887,f81cdae4,e3f78e8d,507f9af8,11653ab8,5f2286dc,db34d9dc,8106e9f0,57610267,411f02a0) -,S(c53e4243,b26ebe40,a1abffdf,3c42129c,47e92cb7,32bd66c0,3d4a4290,c68b1c25,bd4f96b5,b5801b82,300b2132,2c39fd2c,65b2d084,e657ba2d,7db5df15,ab960e34) -,S(a3a1ddc8,56957468,2e9b8a57,50bbc738,f72dc60a,1c09c95e,a6559b2a,736535e4,94887a0f,a4381d9e,dcc4faf5,1525ce98,fc43116d,29f68c99,236e4940,6842a741) -,S(8160ee7f,738f54a0,698806b8,35ed4bca,113bb568,b23fd331,ef5f1cc2,80b6230b,382ff30b,f13f1e28,95a38af3,13fcd099,249b195c,96ac42a6,6a929fc7,a907b17b) -,S(68552ddc,6b219554,dbabd276,e0f2a5d9,33610bcc,776bc40d,7efdc1c6,1b992e35,eee09352,c82dec92,b0ae8d8c,d6918ac6,df620dec,86a0e4ac,abfe8025,52a0ab5e) -,S(919fef57,f308255e,1fa802cb,5acab880,c1810c62,c79a4ecf,c2251a2c,cc02ef51,cb38c163,8f7890f2,d61a980f,ed712ca8,97296366,7927ff7,39de824d,207ab566) -,S(d7e493e2,e2c33635,ee8d22f3,76fa8de9,31ed4eb0,9771746,f48ba201,307e04d1,ff7e6d72,f712f2be,2bfffb43,2764f677,62917509,3cf6bfe5,eb5cb7ce,85c1a8b4) -,S(6b642a8d,f4131ddf,7f31dc9f,c26b96c9,286e1f80,de2af96d,52e383d1,ffa73a41,1e55e667,5f0ee13e,76818c02,ce424d8f,48cbc930,b25dbb85,363019c5,fc29979c) -,S(7ade4aa8,1df8c53d,1e64655f,bfe0ad88,4057e0b2,1c88bb2b,4c8d5f19,34794191,cb0e9802,fbf1027f,dd8d2167,f4f4680c,f9e18f4c,3bc3310a,c4014745,530a06fa) -,S(6d578cb3,1ed19dc,812fd360,a367996b,91a7ba42,7d2f74c3,e2a1721d,72e1c017,4ac9ad2e,aab987ed,dc994b74,733fc710,19301e1,f691999a,5161cb15,ba11e9b4) -,S(df95b5f7,7bb79814,21892d72,743abe4e,828a7544,f9f0e774,b1f5ada7,a054978c,4ccd011f,a966604b,32f70bd6,1a3c1515,c6d1b261,a3ce5c59,7078cc9d,f723b32) -,S(d7392d17,1cf72e1e,ddea0be,a242edf2,c418e9eb,7dcbe1b3,aa07ae7f,a11ef08c,4b696f78,20a9ac8d,a5f52c8e,9d1a39c,bbb3d3d9,fb5b38c8,1b46bcfc,90e869ef) -,S(f01f2aa9,82842315,98f414ae,f87c9d7b,6eaf21be,c4dddea1,3967677f,5d2a1032,7c3be753,da5485bf,13a4cd72,a9e3fbe2,28fc6a22,c502b19d,1b6f7d18,149e2b3e) -,S(cee8f811,4b1829ab,a47e9b5a,54de7cba,1f6edfe,624f30e2,ec4979f8,3145242,4b01f7b4,cebb1125,20bb0ab2,7013af9d,11d19c4,14b0c29f,d142c7d,5b903a09) -,S(f4215bb,973b5586,ec051388,203b1c99,cf69b555,6b1591d2,fc711842,759e9832,5d8a5ce3,ece7c011,df3d414d,e62ecd4,2d716c73,cab02e29,621307e0,658e6fe5) -,S(e39ecc23,90c9464c,32b08759,9a44586a,da09af95,ba8a3b30,2cb015d6,4a49b18a,bd7957c6,e1feb061,f5535231,4f5c5e5e,c8245f28,4638f390,d079cffe,bd2eea7a) -,S(9e6bbe6c,402e4cbf,e298e789,458fa9a6,68cfd407,3efb3d25,4699278,760589,989bf3f,9912b242,419c848c,f82c3fb6,8690ab05,bc23372f,eb9a850f,b4dd44ba) -,S(67504bbf,57824cd9,8a3bd82d,34fcb59,3d20590c,a90b5652,c4ea4695,1f48905d,93ebbf6d,3678478f,56ae5a54,cde812f7,d8d40928,21b5e82,71669dd3,f0b263d3) -,S(4e5bee50,503a28c0,9252b9bc,dd28af66,cecae127,2128e88e,fc431373,7324657d,d6891df5,3a4cdf2a,d7ab610b,817b0f60,c2502442,2e40269,a7da80dd,2672e0f3) -,S(7481d5a5,bef3d397,533e01b3,640b0809,fd6ff946,a1e5481f,b90f0b3d,dd05c21,21ee7275,9c217d19,3999df2b,e3cddff6,fe59f26a,e570e0ae,58868441,f37e342b) -,S(778dff4f,dd32f251,6defcd94,188f2440,26b9f789,ff4eefd5,84b2c15e,2bc61d62,996a2edc,f43e10d6,93cc2d00,c6f4506f,45be1dc5,c762fe20,3dce124e,34e320e0) -,S(cf531271,3d65d471,929f6108,12db63ac,b1c52203,eb879ca4,a8ee9f62,774580,38e28f4c,881391e0,55fa7148,2c92c097,c842dd,74a58d6b,5753d6e1,2f773b19) -,S(99702d01,9420286e,723625b5,62c8152a,2dd5f1a,eff84437,8a182cf4,25582031,8c4af2b2,654f1631,82d08bd6,e7f8b6ca,d5365b9e,d869fd23,e5a3c4d4,7e5990c) -,S(68614c88,6b59c198,c49245c1,e1232cb0,b4bcce31,e0a2aa15,9fb2331d,ff1dce66,49c870bc,7ac78e22,b635c2b9,6f29e641,3b29c6ec,8ec8b3b7,8fa6597c,90180c7c) -,S(f497a9bd,3c0e923d,5d622ab6,afeb9e8b,d9b4525f,d1f30cae,2a44d0b3,e13256b,af4d0273,e088adb0,b7de7724,b387e109,d49d20a6,eceb369c,12e07eb4,f28c9e32) -,S(50a764f7,f5e29cba,ed7ababb,97d2ace2,22c06c65,9ce87d77,83b5bd0d,d165bbbe,4abc57c5,4c9f1d54,e73cead6,d77a85a0,8be25ba0,ce96b8a5,1b4fb460,5eca949c) -,S(fccfe1e1,e312e6a3,92e83cb,97274576,56415255,b127ad54,432c93cf,4ae29bc0,e681795f,d8340902,da0018a0,dbb8a424,870e4bcf,7de95f0e,b2c7e98f,47a46c58) -,S(66de61ba,48c1fd44,80d5c78c,3f06c3e2,45ecaf25,e4c235d5,8408c90,e1b62ed1,bf3bf086,a90221ba,711819d0,d80194c,c45177e2,57b1408e,7e649f15,a92aa6a0) -,S(4373e7ff,e3995503,97bdee9,c9d3d70b,39f47446,45fd3c1,63b2012d,58e148d6,440a1376,16096124,42c7bff3,5f9a8aa2,3ac64e8b,bd5ca839,bd3c5a39,b84e6fe) -,S(c8774ea8,7d83fc06,c36ab357,b1fa76b6,c647cc9c,ebf2e125,3f3ab303,9306ef1d,ccbde78d,2e4d2c0d,ace4e660,efdc4d1f,a1dbb44,4cabb0df,bfe29de3,191f7249) -,S(748cb6cd,c57d89d7,8842fae7,731b1e28,3b59ed18,cb761c88,a4d2e4c1,c3359fc,62f5b6c4,11c72d4d,a412148b,8b038b32,8f98aecf,ece537a7,237b9f87,646b9a3b) -,S(35a83610,30fc10f3,53d2fdbf,cf67655a,91b86555,cd3d9eba,f962996f,ecf55cbf,6fd79f5c,df8093db,5c7f3a94,52dbe6ae,bd1ca410,199deb04,761ffffc,77ec9fec) -,S(cd05bbae,d0a8d78a,2e05e9d4,1c33cbd2,8d59d384,75d42389,43f9cc35,3a8a30c7,9f7336dc,8e77fd55,bd0b9e8f,23eedf1f,d0c16f69,921994db,dc2588dd,ff72a8f8) -,S(da3fe760,2547c831,2d4f515a,5ce530be,29379325,41c6de36,364c4b5d,ead43c58,df60bf1a,d2fca43f,6d482df4,61fc180e,5e3cf692,995bf8c1,7d32a263,730b3ddd) -,S(bbd7996c,25ba5c24,a14742a9,745dd2,8c18a598,8279581b,f8b5958a,8092051,896a39f1,310be1c5,9de4b86c,7c9bde10,8035ba39,864a45a3,69573d16,4afbc2d) -,S(bf7c20dd,64ba5f51,2a996bd,428fdbaa,df1853fb,f814e6c7,a415fb64,a3e16070,afaec0ea,2b18c89,93a1a565,f3db58dc,748df9eb,4d9f8a04,a18cdc23,4710d5c6) -,S(919d0aa8,10928129,cad99b09,85bea5ba,7d4ea114,9f9d5d65,2b6c0e0f,20464903,60d9352b,d053b01c,83caa121,63e8c9a3,e2153cbf,b335943,7a2a788b,7aa02dfb) -,S(5e7c2a9c,6ab8251e,8f8749ab,e0ef107c,aee593e1,a8632a6e,1e0e0c4e,d3cace9c,74186f42,6f03f806,36d79258,e9edf593,6e21e0b2,d882d933,c0241ae9,7d761582) -,S(2815184d,af1e838d,86d63a32,db5339df,24731743,aee62add,21e3a6c2,c2b0b1c0,2a4951e8,3ec61221,b1035c6b,a7d2cbed,f6ef93e8,cff69e01,295e09d9,20e05919) -,S(e3086e36,91432a20,8602458a,87d82955,c8920ca9,fe1c079,3eed878b,282ec3b0,13db4219,50388269,cd591c5c,d8e07ba1,b532f01b,485829e2,aae4f55,f05e4362) -,S(8264d534,2db3261c,d7e294c6,eba040f5,461fb9e7,e3fa13fb,dfcec29c,20f2fa7c,4dc311ff,10b92db6,b67f47ad,86fd74be,24e3dbe0,d6a74842,92f35d9f,6e95eac1) -,S(9edbed6,3c4b66ce,a8c2ac6d,89622d61,6838e1fd,9b93c363,c2bde528,a629b2b,c1706a02,5b1f9419,2dde89fc,63ae2a81,ea015ab2,964beb58,d5ca7ffe,84266644) -,S(68006753,672e9ae0,79fcdee7,9814a904,80c170a7,f644302d,e5de7982,7684e12e,fc1209de,88ca7c3a,614252e3,153df13a,6d0e8db0,4c82d83a,fcbe65a4,5c084398) -,S(acdfba80,9e519114,a11b1634,1835d7e4,5b93a6d4,7094846a,e1ecec00,18bc4531,a4e57d02,51511f2e,5b729309,4c50ebef,4f8d3cb0,d930ff48,20d0623b,d636d664) -,S(978304cb,e99eb899,5ef43f94,c67c471d,6d42ec19,f83f9323,3a44b9f2,e2d13896,ab26782d,2c1dbf16,a90f90c,8e49d250,1e1172f1,3e1bd20a,3deba979,85fcb110) -,S(8c8b561f,9c857510,88478c03,866b347f,46e06801,82482343,923d7e27,c67f49e8,e7908d27,79cc5b19,dd00f2f0,4ab52474,5c35cd6d,4b85932c,99614fdc,64048cc4) -,S(d4a7ebc1,987b1abb,5d02e598,190f73a,36d1176,d7f0f7a8,cb9491c1,b86a3c55,4f321dec,9c1832e3,b0d0c974,798834ab,6a410bfb,398ebf58,177f39a2,22ba4e50) -,S(14bbfb6e,7910f522,69e544f2,ad3175d2,3a36b7aa,8209c24d,1fbb4277,9508c261,d16147c7,2a1df442,d8e831e5,aecd54c6,8bc3f225,4d0f51e4,9a375053,73e8d08) -,S(d24ad71e,81de43d5,7096e101,6bd4d99a,46e52e56,782d99ee,838217a0,dfea0f5b,ae574f68,e07cead9,f214976,67a18c2f,fbbcbddf,2bfb6c95,3b7ba673,7d08903b) -,S(ac96889a,f0b46b7,6896b763,8e1a13f3,dd24459e,8601f892,c3367c7d,8b52931a,b68a8631,8672c378,d99b0b20,44b06190,876ab100,eadb12e6,c16c2ba7,c1ee2381) -,S(36b4da52,4f4ad5da,d7396445,1e79bd5c,20973df0,efa82bb2,da4bf68c,55afeeb7,5cb7598b,576f0db4,db1093c5,e6c9723c,f493bb91,450a0017,9f79c8e9,92dd6136) -,S(98c7bc3a,7054f928,d062ae65,b4140dd6,293f2fb6,cd16fbba,e00d39d0,b11befd2,82d134ac,3e614e4e,62b1b475,bbb5fd80,a5e6d3e4,e4572dc5,7cb666c9,a06131da) -,S(95bb18cd,991cdf72,1c627d62,aee4655e,aaed0b6a,b1e64537,fa89a0ac,f60b4a52,c37e37ee,5b87a5a5,e61824a3,ea519f03,dc3b0a77,f755485,d337ac79,f1f9e8c9) -,S(41e45ca2,b88a4679,6df9106b,c8b53180,81674c34,9646545,e5ad9b6d,e5f6cdc6,151ba666,b0fdb7a7,18110f62,83e3cb8f,8e40fb8b,fa1a1854,75958a3b,ec10d197) -,S(32d15f16,dda923d5,c2f1bf5c,9c003b33,b77d2450,95e5ad31,2ec62956,ae092805,58d64c72,96ba6976,d61774f,f37a0d1,6316cd19,3ac0d930,bdcf4924,cd904095) -,S(41c4e029,817de516,8dc04b2a,9bde3850,7ae48602,dab08db0,3272c694,6cf099eb,303738a8,7b888601,2f9e2053,5bb8b610,92f6222e,96968afb,98940d85,98181458) -,S(28b8ccf,b14a86a1,84fc3c3c,a6a7dbd8,763415,91a67d8b,4109f026,1dd964c5,899f98fd,5e0c59be,69150d8c,5a917d6e,864fa15c,63072769,f75f6353,8cb276e6) -,S(f2776367,762d6468,c9cc0e38,d3921813,16dd394c,eaeea519,786b4353,a5044586,1a873421,1b170183,a117e420,c41d2725,84acf219,a415778a,4eb0c34b,bee9a68c) -,S(7a1a5f53,6e96ee57,e10b1337,6bb1e895,d0703c6,5adfa4bd,f24937da,98bd7144,860921d5,67fbdd1f,11aa3ced,103453af,8c3f5037,b92ff10b,ee70ddc,e4323206) -,S(d82e79dc,5d6de6ff,8863e039,60401bd1,610500f1,57fd2b41,f20689d8,889c3f76,f1947dc2,ca625df3,af5ec97d,32e62c09,2139d108,948795ba,5cb164b9,351bbf34) -,S(6a2e184c,23ee235f,93f036c4,3875db01,22416a6d,26ef54bd,85a2b465,defd0351,6c44297d,724eb2d3,2f58a197,2f52a7ad,ee49d30f,c8f8424d,7f26c6e1,73dc6868) -,S(ea0d5281,bd1417c7,2dbedbd4,dff37c49,bf143417,d2a40dc2,573b4b3b,2ccddcde,c7a35ef7,685faf18,c5a4cfcb,2eca27b7,46b21d65,ed71aae9,15185cc2,6d2b54ee) -,S(d5432c9f,8ed0b4a4,c3e42dd8,28098f13,11d2cdf3,94672331,51fddbf2,a6030974,1e047ebb,8cc01a43,2ee6ea04,578513aa,17ad2bef,7fc7653e,936b2d22,bf8f6c3) -,S(c99ee053,655c9d53,1fdd2298,3cc03756,299f47bb,5e1d0a4,d7b861fa,c3b5e332,61c5187e,4e12f8fc,617a5fd8,746f28c3,368b6b19,1189172d,8c56e2f4,679f6b7a) -,S(f41ee431,170be2d7,fd488c3f,5f21f3f3,aae5e501,1a3c4ebe,d0f6db8f,63e11e55,f767b289,118391c4,4d27c1e0,76b7c70d,110cb938,e9c5c62f,1af200ad,7e9976cc) -,S(505a65a4,29388bcd,55561f5e,fb3090b2,2d553bac,2f8cee97,6c0685da,40006e41,c72c9e86,6b4de925,3d463d7,e7bcf7d3,d6e7c351,1fe6c4b4,7fc436f6,d793e0ae) -,S(ca34be0d,48bc2931,cabe71d7,9cd2bc23,ffa928a,5d532d67,f3665acd,375dc01e,263008ca,4dcf002f,8fdd580a,65701694,bf4530e8,baa0438d,b77ec246,75b4db4c) -,S(d52c25e,9a76600,b16dfa93,cf9c2df3,38c806a7,d8cff18a,1d262662,5fed6d7,80309810,6055c3a4,d5d1e5ac,945aa815,bb8ca3ed,10b5d54f,156e4336,39c4ac77) -,S(83e43bbe,62e39426,a0a74ef3,831cb4d2,776d7ea3,d5a2d57a,8280bae6,ae0bd8d7,a1c2c1b4,ea1140c8,cb4ec2a6,98a3f727,666eaf81,1ae9b89a,9e09db39,d1a257d2) -,S(12326a97,ad8dbe89,3181d76c,6d7507e2,74d62cca,1f0a3517,30e9ddd7,198de84f,79e7823e,7cfa4df0,bb31e9dc,ac415297,edc6e061,4fca2f18,1ac7fd46,d27fff48) -,S(1ad3375e,c82aa917,88bd787c,37fef8a0,2071509e,aef62e8a,dd5c5e4c,b096cea4,f9f9f10e,efc1fa79,454c6d55,b894d65b,ff5c445b,f4e9e46b,8c82a4c2,a94d5a71) -,S(8e8bf9c3,a752258c,278bcf19,7aeebae6,fcc198f9,2310b13d,d114c1a7,d10fd2c9,e2f41d5,b7d94378,5f61f572,763e6e88,df7b321e,9baf0445,482d9f22,f1160195) -,S(c44cd33a,144e2926,b7ebfb93,d7d9ab56,3888f6d2,694efbbf,a5665e10,f6e0ff7,c2d4afed,f77c22d2,88f9cf38,a057df90,baae8ca3,1e074d11,bb8f89f4,e9e1bf4b) -,S(b960f0cc,bd7d3431,4138accd,aadc2efa,d5b60071,7c69f1c5,92900a40,ea68b24a,e0cbda14,801794eb,19401935,3f8ab80a,f525b8eb,2b64e5ee,62afaa5a,da4680b1) -,S(f7104560,8fe120fe,5d036260,5bc3de58,76e24b6,20684413,a440cf56,6520559b,2e208f0f,fea3f78a,9a283f9a,6b601ce,db4df4b,b2fda7b6,306dc8b7,3d514f35) -,S(83a31aa2,cb10fc14,ca8cb2cd,b21cc163,41cc9862,67a5f1cb,75f3f90e,1a92c59c,be18918,400a6e32,b4fa3469,ea6e3613,251ceabb,29cbbfaf,2c16af07,fc5413ac) -,S(3d7b800f,8802e521,341f83a5,efdb355a,b60669d0,adc15531,72c62097,8106f6ab,f9b179a3,aae98427,e02d4f00,89b3cee7,250e30e5,ed72d59c,198d5ae7,1d639e72) -,S(7bef4e27,9064400c,48d4f27a,a754deaf,8af74b10,d5dfc497,98c38216,803f50e8,bab0d71f,d02c67e6,b274693f,6a4f402f,831aa4a3,5fd83014,fb07c5c2,e62d561d) -,S(e6b2c83f,2a6ea201,f56a024c,482a8076,2f2053b4,2e4d2901,4a5178d2,3361bcc,75d1f7b5,209cafe4,f98e63ac,53052a40,487b3390,e4ab73eb,ac63acb5,cc3dc88c) -,S(eb4f3b95,f12c16a8,e5e13446,d9b8ca7e,92c56bdf,565aa4f9,bc1c47af,914fd145,e3776908,e3f3228b,ba0c0523,7eaf1963,1835797b,ffd7eff5,61b30fb3,9fcd6307) -,S(e2926c0a,858b9732,82c1b34b,4c4ba4b0,3099797d,d29c5fb7,4447f28d,ff962e54,2730f3b,e59e862b,37ac50,e5375d08,920cb62,b87ee8d2,f5ec9975,886359e2) -,S(8bf4efd6,c11d7251,b06a5e08,99ff2e80,349f8022,387f3200,6d9de060,bfbf3f68,5514395,457848e,a79ba6c4,39a7c151,b497751a,a4a1784f,114686e,e351afb) -,S(4ea97c1b,920d2ec5,3c2182ce,d6f7e1f3,df49e673,1a14ecd7,d67aba0f,fd077c78,5e958afc,d3894757,e0aa89ed,ba26e035,f06e4b11,da13675e,29d382c7,b21fa9e) -,S(1b12e81,3c7c19be,18576f93,69d938f4,bc81bbfd,7e9eb443,cf2b9ef2,b8e2b3ee,47220a1f,718c36af,8eb8a9e7,ecee3899,ddc49127,91421438,8760d6d1,699a5ad1) -,S(7c6c144d,4f839904,ba40fba8,b739913,54f40bf0,f5810329,c4e3b961,ee6a101d,6eebb976,3ceae5f4,f1ef2473,a50b795b,a6375c72,df67d15,f310b5ca,9706b5eb) -,S(ec637ec6,bea71803,2bae7631,9227ae58,9581d3a7,131323ec,35f0d9fa,27a3e285,c12b830f,f273fe72,4f3bfdef,4279ce4a,8ae6d0a6,de5cbad2,b0a7b4ab,643c79db) -,S(33c8d6fc,d2b37103,2426910,6b9adb76,6c76f788,9627a9,6807572,e0af0f84,b3f01db0,7ed82f45,252d494c,af735e6d,3934ff78,c89c57e6,6c42a663,e5d6a792) -,S(35ee32e5,f7204f0d,d48b1a80,cea0a418,1d71205e,c373827b,2afc25eb,e3ab7e20,d57bc815,684adacc,756291c6,87d0eab1,63067976,a7c3a2a1,98ef1d8e,bad12935) -,S(97362395,200d807e,623826e8,3bdfa37b,e98793fd,6d7057f6,370720b7,5089a6b0,c908e9de,cd1d54a,172973b9,1706fc6c,c3367d75,2216c2d8,1085dffa,5627f06b) -,S(bd37e01,eb944b32,b379b195,16256ad7,4061760e,4eb44361,5e8e5fd4,34eae9a,dadb545e,2a613e54,6067cb6c,179fbdf6,d94b7b8b,c799adef,391b2957,2b93f57) -,S(b332b57a,4f070d20,35986e86,d82cc6f,7180293,53bd360f,d3f883fd,68e9c5ef,eebd3a05,933526ab,ba9e63f8,cb24ffa8,550e50d6,8cc7a4bf,215c551,ab89832b) -,S(fe5bf27f,9459e640,7489bb32,2012d1d1,69d40635,74dc05bd,6bdd6c38,cffb61a3,72c6318a,3775b8fc,5c790d6e,31bbfddc,7ee07a71,93e5f137,e3c3e098,bae25da9) -,S(f27cbe27,ed93086b,517c5859,9929310c,ad0e05fd,482f1fc3,af041852,c63a2a23,cce74e61,4e14bd09,8f11674f,23e30be6,b3276f4c,f85dedea,b3cbfa49,5a716e4) -,S(b328535,1a1b22cc,51b7a590,3582dc27,518bbfa7,410dc36c,e63da663,daa8693a,1b260487,7d3ad6e3,db75a0b5,d6b89df,df507809,c203b4c4,cb0712ce,ae2e3d2f) -,S(bb47bb09,70dae4b5,4f4c3aa4,ad4c966,ae42691e,ae39f1ea,a6711d6b,5f04b81e,2edfe19b,b52b7b0,2b4cf349,aeeeab0f,67524375,7f35b6e7,b920d343,e71561d2) -,S(fb6c9735,d4333142,5bf6ad83,50c7241d,b82e35a2,9cbafa37,d822304a,c1b3dd02,946a7ec7,1e0e6dd,a4d4c315,2a6e7489,8671dcb6,8a219781,3e2491a7,6a9e3357) -,S(c711f224,40cb6e74,a60509ec,23daa2d9,fbca44aa,9a093475,524e31e5,43575a3b,e4259800,352d0d79,c5e22d3e,2bf59f4d,e4b42484,68d15c47,ab5a9cbf,854294b2) -,S(9c748d45,a07e141c,639ef97e,8887ccc3,aa84bdc,ca0618ff,4f43b1bc,7496c83f,3dab775e,c3001657,e71a9d46,bf8cc120,9a74b9d5,1025f97c,4dbb9457,e932b5b4) -,S(9d5e6479,81a9278,6db60938,4a462621,23070938,d50e1bed,8df9474d,bee12513,30f2517c,6ff04eb8,9a6ef21,e4ff33b8,e14567ef,e38871bd,b9dba6d5,584c8b0e) -,S(4d24d6e8,91644ed6,ac1aa619,f9eb2b58,a9932c5b,3e8c82cb,589694d0,14b1d472,6ef1a21a,9dcba4d6,850e6593,3ee1a259,91203278,2f478fae,cda13d6e,5abdab22) -,S(fa226c4,36b389c4,50143041,da93c906,70258092,a8de85cb,d20a0dcd,284bc808,524d2992,655c77bb,59258257,5db3d663,a7a345f2,85572ff6,e9dd1dd3,21bebf6a) -,S(d4e659a8,e9af7543,2d9ec769,5dda0371,7bd79ff1,9ba73f07,ad0bf13a,45ad3b77,5f4a2de8,db9814f9,9b73ec63,6c77f847,1aa48356,ff67c8f8,3f0b6aaf,1ac7ba9e) -,S(157b6da0,1556b23f,b6c46b06,145727c0,21d6e573,782bcded,d594ae46,598df23,737d45d5,2c247718,e720fed0,56352768,ce111425,72730890,5a84a545,c53c560b) -,S(d97a6087,19c8572a,78b73938,5479e4bc,9a2b249e,a4f064a4,550ce127,fc4bd45e,f11e233a,75ba1651,144368b9,55bd4dd0,f4ba1f2d,2d0bce2e,82315e5b,78e0d76e) -,S(d2fdeec2,9b5f4ef6,374c2b87,57e4867b,d2e036d8,964a2ae,15632ca4,6f79a294,2d2c1502,a935f5b5,960abbda,9db42aea,c9f58f0a,bfaccddd,f8d59881,e2953872) -,S(fbc6a2b1,b3c0b039,9abc55fa,835bbeba,b0461db,41f3d9f3,160d0154,72861b3d,54421d5e,a5ed3abe,f22df1a7,26a2b5da,a298b41d,acc69bd5,a72952a2,13f928c4) -,S(7ac224b,cf7efd8d,b214db6,a6601d51,829d57d7,28c4c3cc,398ba57f,5079bf99,edf12fdb,9e281367,5e7df40b,1cc3c572,55213edd,c0fa07b,4e3f750d,36d6935c) -,S(f2bc4452,4af39f04,afb480c2,f7addb57,a04db86c,3691b26a,922b6ce5,a1724d9a,63c372e2,4a659127,ace8f54d,33969635,1d890dbf,7e2a31c4,251352ed,53c3a0bf) -,S(5ac48ffd,bf27b452,ca37dbdf,83f2fe6d,8f704040,f3a56180,ab991228,a74ad88c,c7ccab4a,e859e7bd,982310ff,2b7eb408,678b6f21,f52ebea8,41021f3d,fab6f091) -,S(daa3d659,a4defb4d,3291a16a,d669a43e,b6891e90,dbe0147f,568b650d,1213750a,af36d811,9ce1ff85,5dd637a3,bd475b10,50216093,aedf5f24,2c98da62,29bdcdbf) -,S(381d3791,30d4beaf,aed138d1,4072bbcc,b8d71d6,dbb13226,ff168f64,3bf55d37,fbfd7b62,3ce32a4,4335682c,d5ccd4b4,aa4430ce,d8fe3d34,9582bba,fedaf9c) -,S(757c7b23,ff6b6ecc,51ac84e6,26ed70ce,4e6e5c74,e4b65f3c,fd17c304,e19b1ccf,56848ab7,f814a047,2bd286f6,b386af5d,34b27c4e,a3ece71,f153dcc7,7e4027b8) -,S(ea498d11,ca35804c,d6103185,ae468bec,6c2f4f6d,ab025173,b1de4027,551b913,ee939bff,8d30bf5,9e3341e3,58acab90,17de8fb6,e2977847,f4322ceb,ca8829c6) -,S(9d119046,59ea5dff,30105d1b,5ee3f8dc,c9291bef,15844057,66e07d44,72ee1418,45355041,4d4715d,e8c087d4,f05b5f8b,a424ac3,49b3ceba,bf806b9c,e657e139) -,S(97bce776,90f8790f,e7d82b68,b7dc1b38,f3baded3,f7c67655,1894fc4f,cd1b834c,fcc18c2b,4f743ca0,e00f4b34,509fc237,c030b689,83451d5f,e7407b81,ed04f7b4) -,S(5339f056,abeb4926,f46dce7,3b8d735e,c6e9c4a3,2057c22a,49c86400,f15d7ed9,5be6a0b9,37e26dd9,f6db74a7,74fa10d2,cbae30f6,bdfafb,dfa2922c,58a8e37e) -,S(27f22d01,4dc5d3,162f39c9,7de3ef62,f2275b5e,cc6d5e32,6ab064ad,f762a446,6aebbb58,d671179,d712926e,d56cd280,8393fd85,dee45558,300a0f8a,a2986f09) -,S(94af2fff,61741cf2,5f158308,e7333e3f,678bf1ee,56adfd56,629312e2,2435f9d5,33a7269,79df6672,b13198f7,e674330,806f2dd9,50d8e82,1774f381,d9ec24d6) -,S(ae8a0e18,486273a5,36d526ee,3974031f,f3ed095b,a6835a68,2e943dc7,e19b37e4,23c2a51f,69df1826,9b21413e,505c0785,576fbc84,acbb2812,fda146c7,f5e8c8c) -,S(623fb527,d3d99023,9f720cbc,64478e0e,a0b84b28,5c0c3f3f,107b3e3d,7dc430aa,3ea48a8,d1eb543e,ade4a55a,f909e62,14e47d26,9471dbf,4d98a3e0,39c72849) -,S(1ff42295,d85e98be,f7aa84c4,47ec854,29f01b4e,c87371f2,b2025ba7,1e31a768,d9500f9,6e8c697,7ecc51d5,7bb7dfd1,3cc97017,58bb4196,b0b11d1b,3c24937) -,S(bc808b0b,67bedaeb,2e7a4bc0,d328efbb,1ff35dc3,b51716ca,3e501a3f,956aed3f,6af0de4b,26a6378e,6d86378d,d1f54243,929c37ee,d5c10bbd,86b80c3,ead8e545) -,S(e8ab92e0,17a9e956,354203b5,5d7b15fb,acc666a2,79158016,33a91865,b5bb46af,3e87cbd3,66926e66,3f5faa,426a9db9,811a9db4,de3a4bd8,79073b7f,c1e3197e) -,S(a7bf0061,c383040b,6e89ba95,b57102ae,2c291ad6,72bb5027,3c27fcd,f90613ec,79ac8ff2,4bbc79cf,431f4159,4852ad4e,2f0a9f86,ca72ac11,9d4e3fdf,8746539f) -,S(6841bcc7,22b705e2,759ba4e6,83d6b83a,19ee6b4a,375b38f4,5722474c,ca41894c,dac48021,5c168519,d147a966,451dd63,7838d236,5667803e,80658faa,1029a7e) -,S(d67e6d5e,a1606817,512f1db3,9033829f,69089a41,902189c5,20f0202b,8511479f,9cb4a747,7224f93a,8447152a,9fdf4c92,36a1b698,2e9196b5,a4355715,b9fd6ee9) -,S(61b3a7a0,53c477b9,e03d0a96,8ba38de0,b02e42df,162a13fe,8ad538c2,840eed06,94c07520,fa19457e,8d98fdbd,d9a9bf93,57642cd8,1b48fa58,b4b14a89,cb6142ce) -,S(cbd26d0e,a00f7dd,4b0b26ba,7358b2c7,587e233c,3a13c86a,d5022ecf,c865e4ba,50e832c9,d84ff55b,7ba79035,559bc889,53700622,59dec3cd,8b3eda3f,1f2b6e67) -,S(17a6f57e,d3d729d,c5ec018e,1b69394b,1ed78e59,6c7a5e31,bfe5dc43,f9c67e56,34f16cdb,c23e46e6,bda5db2,7538d7e1,f66751de,3eb05543,96c66a54,36bdfe9b) -,S(eaeb62d,93fa13e1,ff9d9a4,9eda40ce,dd6006e5,ced0e8b8,c02f7ab9,98f06f31,7e225365,b4b39204,b01c8890,4476c141,1c166f75,1726718,8ad917c4,9a719ad3) -,S(d09999b6,c35d5d71,55605a17,e7f82d3c,dd8d68ce,9be252e6,99493031,a39c7487,9165e761,8dfec3d7,cf733fcc,e548f672,362637aa,8687f47c,b1eb5c18,a780b061) -,S(2b4cf8d,7fb166d8,a6931bce,e67f580,870c61c7,635632a0,71166fc7,4a11c693,7974e2d5,164771d5,2e7a121e,2b015565,b3a874d,d6313721,ec69d3aa,b44d473e) -,S(d5c0045f,a411cdea,470d85a6,66aafa44,49ed682f,a1903c5b,c9594d19,5cbebea6,ffeebc77,5b24e736,8a8b46a3,64837466,85df5c8c,b40bf2b2,291f370e,94c6eca4) -,S(1eed08dd,d9569712,6c0a4039,c6aa5ae5,ab4aabe2,a88142c3,b9aa763c,632b5e38,d180547e,c4640035,ca86d925,10a70a64,5dcbf2b5,d3add4b0,3f6d0fba,5f4c2f8a) -,S(9591b04e,3de43104,3a6982e1,29a2e79f,f525888,846689f0,44e50b18,ce14413e,cc4cc696,73279c51,4aa4fd63,474050b1,930e627e,a1bd9d55,867d700e,fccf8155) -,S(690a17c1,b2dc7ff,520aecaa,380b19d6,d4a28669,83dc5df5,8ab2bfb7,6c7b0600,bdd8a858,e2d989ca,79fbfd46,60ffdc0b,e0231562,711b13d3,47cfd37b,7a53d4d) -,S(800a632a,aca6b505,f9fddc22,14efe53e,4e7ad2a1,a6c07d90,27d8109d,893851ab,bf242683,e0c1a24c,9220c6ab,deae8baa,12c6203c,a0080856,bc5e5ac6,4c3f3261) -,S(6dceb824,c48159d8,57a92334,4c72b4e5,cf2005c5,6fadedaf,5a8b780d,3ceeeab7,e6b961f7,6162ab6a,d44f3fb4,5aefc843,bf0d714a,1a50d13c,68036f42,30a1ad10) -,S(3ef5eff1,2b76432c,4bdfd1f8,23bdfdee,f60b5d0f,5d0b4051,2a3e22bb,665f2b0,8741e43e,9f78066e,d57d317b,d50252fb,11d8d235,3c2c9d57,76191c21,8798b0a9) -,S(4ce8d33f,a53f2e1d,aa696e9a,2de694df,2192db5f,8e6fe88e,b5d51340,83791c17,a023ff40,69587bb9,49ebb15a,d047f141,9985b521,ae915f54,bebc6dbf,5320558f) -,S(da030efd,a3f6363,926abcd1,182f183c,43c4a6d8,8bcb0519,3d137827,6dcd3fbe,c14f27d3,2251248e,3c4b8613,481e7c48,f1493b6e,5c0716c7,8d5e3b97,876ccf3a) -,S(65c12034,87b729bc,3709759d,beabdd79,ee7f50d7,ed2cedfe,f2c2b7e9,97192f40,f440d69e,d59adfbe,e087ef70,9b75b95d,13ac0e06,20683d3c,6d49762,ddf68a01) -,S(82c052fd,dbd6aceb,1f429f21,eed34d44,f915e949,7190aa6a,d487bd6e,68d91c20,90dfd944,c7c20ec4,4ce35d2d,4036eb97,894f5b93,6bef62a0,f2f65082,b0f7678d) -,S(43e2f20e,cab47065,e71abd8b,aa511163,e17e3efd,3e17d790,ba924de5,ab402255,6b1ff657,e37b65e0,bf2c5e60,47e36c8a,2b7ba965,79bdc711,c3ae5935,d2c47bed) -,S(27f177cc,6722e5a7,70200e2e,a9198bb9,f227251f,8efa1988,ac7342b0,985a3853,a76767a5,3743db5a,1062ccb,64452ad1,606d5065,9df8c0a5,64f049f7,764d6a99) -,S(6b1ce20d,d15cf54e,59aec7fa,c1919791,c40c926c,55801801,75c09ac0,dcce0147,c90a76f2,627d2510,8b89df25,23f069a3,6b102201,c2fb7e9c,932ae678,4a28906e) -,S(f9df6109,27b5ff70,d55d2a46,ebc6a734,df165bab,3bd27398,24a60727,5410f62b,4da454cf,7a381056,581fb115,d36161a4,4beeef74,26724d,d4f5500e,3a6c1612) -,S(16bd87e8,2f87778f,6b3f1da1,a04bc048,3b14de01,420b0074,81aab07d,ad806cbd,13a50b5d,886047b7,6898c85d,cd1bfb4,87642f95,8304d54d,12c03b25,9429170b) -,S(f35175c6,2244f0c3,ddb104fa,3ae57557,424c2d0e,f6a20246,e2fa48d3,2908dae7,dfc1ef36,8ffb4e8,2076ae27,7788444b,33880ee5,b6d5bd0a,9a2ba79f,30c4d1ff) -,S(6a9ec43a,b8a6cb70,465ba668,5e15fe2f,9e714c0e,31f1f227,186d95ad,2faeccd9,ee752bfe,4da4feb5,e4c0266a,57929e56,62483704,6e927e73,9edec593,8d538708) -,S(92e3b0b1,3df6dea4,371601ba,3d92f507,2388a23e,302edf74,6da973b4,613d2292,9442966a,dff82878,f6e0b8d9,9e56f99c,68eea310,79b365cc,5f057eed,ec38496a) -,S(35427db7,f03afb34,d13ba232,420e5d9c,4a8d16c7,924a2043,a217fbd,4287230b,5cfc1908,108fa47c,95ff8e02,634351d2,523dd990,aee1700c,7cda57c1,b106a734) -,S(a61be939,d3a33b8f,65b8fb5b,897598a7,ee25e71,5797014c,fdb087f1,90895825,fa6b7a9c,f2a4a71a,857bb126,44fdcf27,c9f4ccf2,7bf6a0d0,dcf8179e,af1a3396) -,S(659868b8,2a9422d7,1da877f8,59956376,b999dc3a,657278f0,89e1b7,a3014222,9ecb6c01,fb97f691,92402a76,13f7932,d8a82252,e6b97c66,5c727d9d,e6b2ac62) -,S(12667366,d27bbe3a,d75f00c7,b28fcf20,86e9caf6,e8b5615e,eee0f180,526602ec,dbac0f9c,32895bf1,21c90190,d5bfea81,84289a4f,a0cf498c,3a3084db,1d4a833f) -,S(74af3ac2,60461898,c502229a,8eb4e7e0,962c8f38,897e43f,6e421ca3,3240b7db,72f03ec2,7c24abdc,dbc9af25,41e10f51,5e470c7b,19ab9680,24eecce0,954c84cb) -,S(9aefb23,d88c5745,da9606e7,ce81d4f4,5a39c8d0,4f5d5f07,62653594,d3a34732,f797796e,5c1c0a56,9886af6b,fd8a8299,29ae1897,ca43314b,cb6ed78c,6c0b0572) -,S(93a3da8b,1f686078,1849ca06,24c2cec1,796f64f8,4f46da9d,34766eb9,dfc1f018,e5c50d0,fe7d2f53,fe1053a2,985d2b15,25125981,30de3cce,2ebf300b,4b944c0) -,S(ed8d18c3,f526a062,bd6095cc,249b7d10,ee09d072,435218be,f2ab6c90,c5ed66a6,42084909,f4bfb751,5ec6da47,2cba7678,7870a9fd,bfc86fba,669e31ff,233a72a2) -,S(dba838ae,b57fad4a,6ecfae8a,acb50123,decb0f60,b702a9cf,7af7d78d,814845df,c3213cec,8f225c2b,fc02519f,dce1f67,5ad59b20,91381f0e,feef93b0,3c6536b8) -,S(f1a033b8,64caff57,21857094,e1038fec,7879765a,3b977a4a,c6616162,68c1d8fe,9592b8b9,e4cc6a7,ce173980,e68fc405,88a83788,a08c6027,8623ef61,ba81b652) -,S(53967cf9,7058ad43,1222e9a,46caeba2,d8fa447a,6b0295ab,f40b8aa1,af1f0097,e8e86c76,cef5299a,9a15a6d3,4985411f,2a71b8fc,99f7a76e,230052fd,d5309017) -,S(2477d3a2,bc3fd88,6daba319,8c6fa6c9,5206bc1e,955e9d4a,c6e5916e,5883eae3,baddd174,ce70e285,1e7ed788,cb81cb7a,3402276e,d94e6e72,f20789bc,ec4f5257) -,S(b483c05e,22824454,52f44e9e,287bc21a,634018f7,babd1252,d7a6bc70,24d9cdc7,5d7cd9d,23ad04b3,3a7ccdb0,38676342,5b2338bf,48d4f910,853e9100,e1f3aadb) -,S(6ae41ce9,6c8f0a33,674f74a4,587db25f,7c368fa8,83abe414,a3f6bf13,840d46f8,d52f2dc7,d4fd791b,36e6448f,5c8f746,759e68ba,994de0d6,48c6b1b3,58476871) -,S(bd1a4d61,e19ce013,d06740be,c3ad88fe,bc3b2391,45563be4,41768f01,45f4c450,88c18e77,c5313848,bd19bf27,374deffb,1f40e479,9687791e,675af225,1141fda3) -,S(1d2fccee,47b4553b,215dd2c7,f26412d6,73319507,43136454,35426bc1,29b358d9,93e52147,c13791f6,aceab8dc,95df1637,83d985d8,3a4426d2,f825d126,e7b8c564) -,S(322cdebe,5aef9ab,957b355c,e8e4fa7c,23f23f83,bf311785,f0fc40be,ce0f7453,2eb8c80e,561e419e,f898f772,12eccab6,e6c4ffc2,5daf67b8,47853a6e,8475d19e) -,S(c7474f42,5491fe9d,51a9e00a,a42bc188,50d4fa36,c19d9869,6939962e,61e207b9,8dd394ad,799a69c8,da550741,7352e7a7,92a941d2,10b3f65,f634cdc3,1f42a875) -,S(ac33b339,1bddf66a,6d04c62c,da618bc4,1ad217c9,7d37526a,38d12e28,9fa9dd30,602267b,59fe438f,ac57d14a,8dd3451f,acde0be6,c8984b58,7cfc1b24,34ed9688) -,S(158e2a30,36f71701,2020f476,dd869974,66f157a2,27548e65,688ae79c,3bf8141b,fac16be0,6033e61,d34d1d,1e2c95ca,6109dfa3,64232edc,8f8f62d7,19ce6303) -,S(88384c6,42d1bdcb,af5b472c,2f7a54b2,11ae4947,433d5d35,add21374,33ec4b78,3c3a484d,5b8793ae,203f90bb,476b4d25,773b268a,8e89dfb5,dcb17576,166b3e7c) -,S(21e3c1d6,32299e3b,5da75f6e,7ffa2958,e5d686c2,6322491a,2597dd44,f6973d2,9866fc69,7b9399b7,4307b1ea,e27eda12,590bb138,b22485b9,de6e3cfd,8d23bba6) -,S(abc484c2,6d06ec8,bba4170f,727055de,2611145c,8e4a33ea,56507b60,3477d319,4f92a638,17f6b635,d2d944a6,b9194d40,c4ab7041,2a8ccf05,e2fee038,58d87592) -,S(7a98d6d0,202f4230,a12fe9d2,e321bc55,a3a3b35c,92443731,cc8112f0,579b08fa,bad00e1b,578de9d3,73f0ea77,85502035,c5a04c98,8904923b,f0059a3a,a8ec6285) -,S(282e401f,57ef51d9,f9a10959,d272e0da,e9898f32,d2a3e059,4a65c901,cb1ae10f,6bb8b543,e9461164,a66d55a0,adc51ada,4ac311be,c6625276,5b2c1639,c803037b) -,S(5259a2f8,3dacac1c,18a9a64,d9834c82,e862169c,7a1b9d24,2b521c4a,d7ec4274,196fac52,458c7d1c,3dfae8b8,2ca130ba,99d43a40,8bf41da7,d2e9d040,291f165b) -,S(cbc4fdda,9ed1707b,59db2171,38e9bc1d,eda499c0,78f22c28,4309e184,cf906081,2929df0b,24074d42,75e8a861,8f064466,9ca0dd45,752c7d5c,8cf32661,f8a1ebe8) -,S(96b294a7,ed8d4916,21f10b04,3c2a5ad8,88b92c76,3c93f375,f6d31d99,64b9cef8,f5502e33,f1416c8,77cf06f2,5752998d,a30ed434,365b8239,617ab3e1,65948a96) -,S(287e1f0a,a510c8f6,273362d4,ff8d96f0,dd27113a,b45d0bf0,1af5d5,d24f5038,4b5ddc1d,6c9c4423,1f27ebde,bf4afa29,df337f18,2a2559b0,33de6830,cd7b9e14) -,S(eed0e323,3475ee14,5160d4b7,49210f47,c58d7b26,95dc8036,eae0e6aa,91a545bf,22407aa5,430aa089,3f7218f,2ca23ea0,16eb04b3,3c967e6c,d4c68ad7,16e4378d) -,S(1417cc87,72c932b2,b1116b4d,ab4e86a6,e7d80fc7,b082a6a4,c148c50d,177299a8,66e06245,56f09207,ab2d944d,167590d6,44afa2b7,b598b92b,65706271,d7b50e30) -,S(af6029b8,93c549c7,3544e849,b01ff2d7,b991fb98,2b8a3baa,b9f1b8ed,2b24bc89,dea2973,a97bcb6d,3257121e,9233956d,43ea9155,8105559d,ae17db09,fbc14f2c) -,S(dbb5544d,d28d2510,8a91dfa5,9a3c7538,1b4173c5,eecc8e18,b5065fd8,fa4fa570,4f84feee,755215e9,15abfbb,ff46eb6,9148efbf,39f69261,a9d2a345,3aaf1bd2) -,S(50ee1b42,be9598e6,3fcb0467,18786633,18b550ec,16645f70,869b231b,674a1878,8f4fafc5,fb1e714d,f52c0a10,55016f9f,3ca57c9e,48fca138,68464b8d,70c6b2fe) -,S(77b88613,4bcf9ab7,a1a6e0bc,82137906,d5c24607,a6d4812b,a6d1c8d9,55a5669f,2ffe0de,c5426e8c,92fc247f,a024f1e2,86668e7e,d7a24c33,2c887946,4cbfdfcf) -,S(2bf83837,74a9b9d4,7acfa6cb,6010fd44,620f51c4,e076d5b7,e798edba,21d7fb8c,5f336533,5203a820,a9f75f58,61bf2d0b,fcad07ae,9e297433,79d22b3e,a75f40f7) -,S(207b1218,9a6c2653,69f66738,b2e61d3a,c43cfedc,bd9f94fa,2b883991,ae69e350,c43b15c8,c08b4592,70c887dd,d15cbe95,d627a3e1,4a1c7afe,da2b0c69,549649c2) -,S(5ec76ba9,63dbe3e1,d054ad89,7a00c7af,f60f043,d2472f6,d3369e87,45637cbc,b66d383a,c4ec579b,8350a1b0,b2751fdb,f2ab329f,6ad63cdb,d6d46e35,944009ae) -,S(d010ddeb,3959bd8a,7a7ac178,ca573326,b578e940,b46f5808,12398722,42e13c94,2343d4e2,a380fc9f,617ed8b0,903b722b,a707c53d,a2140021,403ac617,d71fe37) -,S(49157637,c5c47498,5590bdd0,e4a8cdb9,f9bfd422,99812950,9ed25a49,7dad0da4,2564d49e,5c53c818,770c8a36,6e92532b,59fb90ef,e7ff4dba,c6baedc6,b792eefa) -,S(7e39cef2,8285f9ad,1b5ea712,78720954,f4933546,bcd7f9a,b4c7bcc7,54147a9f,6bbe4096,c4c107d1,c361befc,75916c87,6a2a0da5,dde637bf,1f125a21,5408e78c) -,S(45457311,84171f1d,aa931d3c,16b9926,59357877,84a4655c,54822c9c,1685761a,a13710ad,597e7da8,f4b12c17,9afdc5e0,5fc4f05b,e204567,9314149,9c73b421) -,S(c0bbe693,23e256fc,f69f0427,74c59091,287bc0be,82f0b5a5,6ea8f957,6d647d8b,c22981fc,6a015c20,525a0bf7,a9ba8ac6,dab6256d,d763614e,ea250c5f,fb433231) -,S(bb224b39,ff7d27f8,1ba86e92,a6897776,85074fa5,48b5515,987df332,15dca58,73bbcc60,c3adbb94,651cb73b,b311f690,6995d611,8b8238c0,4519de94,1e6bd47a) -,S(94489617,8b4bb641,9cdce312,5d863395,7ea54002,7f759e39,a8846551,ad3a0866,4a16c110,7730cd80,55fb7ddf,93c6deab,e3282da3,8a35d79b,3238e8ee,c8917935) -,S(9ae267ae,a964e8de,68398609,d6351619,4019778b,2341696c,7e44f446,dc8fac38,6d175dce,e589920,851c02cc,3fe3dfee,e9398e53,7742249c,e2745713,fee236c3) -,S(9e237d91,a6ce503a,65dafb47,a9fc5f7f,6dbcf3cb,b026ea73,68403187,d95afd67,64d491e6,df79eadc,74c198f6,fbdc481a,330d030f,851c7fc9,63974047,ddf2d12f) -,S(a5c5e0d4,920f0e3e,6973b71b,90ae2b32,2fa16960,b850eefa,1e516b4c,37252d6c,1aae183c,52ba9f14,f06c57dc,b483ba6f,740d6bfa,7ebb72e8,266895c,e6f6551a) -,S(a6d0cd83,9a198c9f,62bbefc4,b91b696b,57a4f876,6a16fac8,1131a9b1,1b36bc1,97981c96,9f758543,2c810b09,460c07f8,8520e78,3e68529d,7a1d3bbb,e0a86e85) -,S(4a75be64,16d6a87d,49e393c8,a26467b9,4b43887f,a90a25bb,139626e8,58b122b6,ace3e92a,c693f8d4,210932c3,89d4275d,75a46c6f,a9a76358,39c26288,1b8f83ba) -,S(1559a339,7f1e1195,51d8b4c0,fa53b5af,c693ab8f,843e6b00,1a6fc435,5967d7ee,8e450f28,78b2e9ea,829e965f,ae4484be,7e98f39b,a7b0ecaa,b777914b,848f324c) -,S(33565a48,44d9b25c,109eb9f2,9546fd5a,3f30d4a6,157a4e69,6029420a,21f74deb,c8141513,c4e370e2,400b8df6,208e867d,9bcacdd,d87cd975,8f91913,3ba97557) -,S(b49c8814,23db909f,c68c73ee,3995a7db,89e919f2,dc697855,357053a5,7ce26988,65878108,879801bb,ae412aff,72e83051,bb13c415,60499b94,8e0831d3,c2e11fb7) -,S(3a9635b0,b82585d2,37068f72,76291c4f,cd3d211f,80fa7256,58e28dfe,920e3e93,a1711c74,ba4e1a1f,f0a9b6d2,12c8b995,7b6c8c0f,f71da246,154f13f4,719f0713) -,S(ce6dc56e,6f5c496,71a900c1,ae531e3a,a8246877,98044497,fc543013,2572bff8,1af98ef7,3703f8a7,6fc88e9e,c9134aa8,a9e24326,314bf4d8,2a0c85ed,af291f8) -,S(a945a79f,1627e79c,9ce1cc5b,79ad02b7,c07263a9,11f8f78a,ad314049,92bea11f,f41aa315,4049b7c8,c9bef95,f3462336,ccfadf0e,16c1f129,26a5c9e3,7a443bf5) -,S(3debe447,a5f793d4,210e1607,642abdc3,c3a8d446,5a553a45,d73ede0f,20819dae,c0463782,dc5383b4,f7f81557,efddb90d,30138670,858c4197,5a47e6a5,565e339e) -,S(dba32245,a37b5636,9d7120fb,a99880a5,aa590299,601c6cff,d33238a0,395f8d2f,d589ab1f,ff442551,12aa1283,3deb9b43,947059bc,9cb1b32,4d8a29e1,1da82b2e) -,S(9c52bd5d,1fd61e1f,8e75f23f,f6e8baea,a8b7b5e1,5e780870,ea9f8dea,2b75cd56,e6d0a620,c116a7d2,2b2f797c,da7119be,556cd834,caab1007,e9a8ac02,f8945859) -,S(1ec28a0f,24e8910a,85f3c583,415afad6,dc5e10be,cc600749,8cbb40ea,b80fd383,c616ac82,bc6aa8b7,1a3cf89c,b82d7e9d,ddb95761,dd64da13,290f6bd4,a4ff907c) -,S(4fcefc4f,134d223b,994c1274,bd39655,878a35fc,2f50e405,ce11c76,1a6833c6,50c62036,fa49f62f,ab1781da,ec17a13c,4ec82c57,7993fd20,c5c56d70,145c2a54) -,S(85481ce2,90bb32a6,eb0fcfb6,9cb9fdda,580d8808,5b09611d,2d8747f6,ca657e20,ad2f9361,85aea05b,6a0d20db,9b6620ee,ee718c2b,2ae1810,42f6bf1a,2b3a2453) -,S(11aa1424,7760f682,3c11cf4f,12c013f9,7b1c9eaa,5ff0a504,334d2e41,f5daebfe,dda53fb7,b09620c8,fbcdf9b6,605710aa,f807dad5,c7ee4e9f,c7dc9c34,23302646) -,S(908c4f4a,15c58b2c,a0512eb6,b07c67d6,5b08b99c,13d22358,a52bbe24,b3823dc0,5e708db1,d4b37459,e33db06e,21a45fa6,5dd5c959,22ee7b60,7162a77,d89fc674) -,S(d192c334,65630164,2edf01aa,d974fb7d,af13ce8b,2c8975c6,ddde145c,1a2784c9,96bf7877,ced69d6a,a71f0908,86e2dc9c,f6529297,a2f8500d,d683b6a7,ebe4504b) -,S(8fa0f7a1,97138152,75f6c886,245902ef,b6e57515,c28732fe,d49b7f57,c19c6b9b,c09b428a,e54fe6d2,effdb332,4b1fc1e1,11aaf4dc,965b72c5,f97a8a97,18fdb68b) -,S(e53249d5,4d80b59,31d40779,4c550ff5,d6cfc715,13e0f419,4d7b42e0,62e74681,face5c4e,f404cf9a,275846b,11339448,d9133e1b,470489ba,64c190e0,b73735d0) -,S(9a1c943e,7f7178dc,c4453de2,d578c4e6,ab80d538,70c03001,a7a4d5d6,fabca0de,6ae6fb2a,1a7d87c0,99f6eef5,dea6a53b,a296824b,d8ab0848,b44d1216,c2c0789c) -,S(f0d4f862,dd60a74b,e06c9478,1b14b9db,af5847f0,baa00a97,72b61857,bb3d192c,6f48f413,90f9cdb9,edffe12,859b82ff,f8f7b32b,b655f3af,f28175c0,8f1efd8) -,S(1f474fc9,f6ee1699,7a7f37b5,f10f1d02,f2445e12,ae17324e,cd31d2e,c6fb8e1,cbb396e0,4b754b24,3dd587a7,d71eb673,c41b0fb6,329013a6,8ba95dff,c6d0d9c4) -,S(dd871b68,1cf78706,61bd7b4d,1ab259a2,1636cedf,39ac276d,5d36f086,fc9ad4d3,89456fa8,cce6295e,56cd18f5,9d9b83a6,4e4983ca,b55d425d,730726ef,12958dc7) -,S(5223e3b8,3809df92,8db9f4fc,d2b81408,96ed1b89,e6480fe,8a6b815b,bc7a33a5,95b640ed,128da08e,a10148d9,6f53b9ce,e53077e4,64eac3ca,1f604225,75b12182) -,S(65f26a8c,88fed562,12f11676,e2f237d,b4c500e4,a4ee0715,ae2e332d,74c48815,78df921c,545b864d,7ebe6c36,bedd987c,51ac9d73,795b3c8a,2a125d2f,2fb8cbd2) -,S(b62376f4,bd858d69,dc5d2757,b67dfdf7,1d3f770f,e96a0dce,3c61fcad,ed0e2586,c58d5af0,d669832f,4ff38f98,298e9240,c6202343,4e829b0d,145093ac,9ef023f0) -,S(a3297102,6001a6ab,ac0e84c,bfc4c829,4c607d6,c2147833,b1f726,752ddf07,b2c820e9,35502858,eea3b657,c15173fb,d1d45454,3c4fa17a,591a20d1,802d5c65) -,S(3b6e214,94773849,46056d4a,dec9e5c6,86f9873d,76accfa4,b4a377ec,84081339,d7e8ac79,e03d1cd1,7c83ad60,6a140b26,dfe67ed1,254a46e2,9c527cfd,c6afdf96) -,S(ff6aaeab,11cd4c80,ea69c3c,a10f09a4,40b3e51,abf56ee7,2c337414,f3220264,71d8a65d,7a605e01,852f0fcb,1bccfef9,147007f5,7c6b83d0,ef127b0,fe90bdf9) -,S(a0800062,64942e,b9bc70b9,f40bcc7b,52c0d43a,b4d608b4,ff65d73d,75fd4a87,de229122,80c1d66b,364fc250,5b3020dd,1482e43e,c4e67ad2,f2e49ca7,df9659b7) -,S(7c2b8b50,7e2256da,15afa166,84dcb7e7,c437b925,6c042450,6025a551,cafadd5c,747b5b36,e247939,7dd719aa,6ce55c0a,218312b7,26adf84d,eb7e3820,57a0b375) -,S(631c89e9,ee8a3192,c593ef08,baf3fc1e,d30a47e4,6a4ee9b7,e1c6cf5f,d6a0a5e5,8d49bbec,85a5245d,ecf6b084,fc65c697,190f8220,cbb84525,a344263c,ae10e2af) -,S(7ee8cbf4,a0b12cb9,d598835,bcf13fed,72e441e3,bc4b515,4182cf7b,f2818b3c,ea3b208e,70542467,a1e09248,8f34b44c,3821f0dc,169c6037,a7299ecb,25111774) -,S(69c085e5,86fad3f9,7b94d5b4,63b937be,5a95905f,eb33b25e,11ef9e8d,6b5ab3c4,5badd881,779a04f1,3a7333f2,dfcd0fb3,6167d168,b86b6a8,27640559,6e5510c2) -,S(951c09f5,563288a4,e25284a5,a694aebc,1e4b3d45,db0f0ef5,86ce87ed,237aa05f,a0c2704a,fddd2f24,462ac715,cca72894,7de034a9,2c958111,3f55c58d,83911c24) -,S(ba30b632,6ad18aae,6d87a1c4,6af749e4,6d639106,76f25f8a,673d0249,5e813e42,6c174bd6,3def5d0,2ce342b,1d0f895c,ef792f42,a97768b0,d091a92b,14f5192e) -,S(53a1d69b,77ee7d09,f9530860,31e93038,42daf062,c1ec9f19,1328b346,559fea0a,baea6eed,b33605f7,4bdac4e,749650a7,256bf215,737d1081,2c805ed5,298de5b6) -,S(23635f56,f8122da0,91d7e3a0,1125b99,a0f87e98,a717dbe1,f6d9528e,82f9b4ae,1a326517,904ad591,43f0f733,8c98f11c,2ea0fc9b,54e9eeb8,c41e469d,ef0ed297) -,S(c574946f,79574d9a,32c588bb,5cd8fee5,dc60403e,81b11fad,cafc69be,67c0eb67,d2598c1a,8568e4bd,a477d9d9,909b083d,f55a7116,9ccddf5b,666a8b61,96e2f73c) -,S(966bbcbb,4d397eb1,91ea2ecc,871fb24,b0c47469,33df7b03,124408fe,583db143,11741ab6,a38217c,e55bba9f,1c7f41cb,2e69e54a,8a78cf02,60bd3d2b,22789b8f) -,S(6ebbecdf,69e6e137,ad70cfd1,741ed404,4b3620ff,15a07f8a,769edc8f,c1aa1667,2ac87d70,baa106f3,a3490b56,a5960f64,fd80160,d0c14d64,ca1d40c5,f244c57) -,S(815f7f47,8609fee,733b7239,b272afdd,89c2f984,5da8186f,4ee8be2e,2e3e73ce,a972e06b,388be908,86c1e324,e1d2b953,18e99ef3,c0120906,f1508732,f839b930) -,S(24799358,53364be7,4675e3e3,c141e64a,febf3a04,386fa41e,f19696bc,5d3253bb,d6233c69,ec254367,673bedc7,1319641b,f9c029a7,2523f8ba,39dc375a,df245804) -,S(db32eded,dc803ff,d5a1f3e7,8437efbe,8c098fd8,e05f2aaa,c03e0daf,50ba5622,30ceea35,22ba7bbf,2ffe9c1f,bb817fb0,748efb45,65d01eda,9f9cff5c,b5afdad9) -,S(c5fb9cd8,8408cd00,33592de0,e602ad35,74e873be,4442d0bf,fe3bf837,51601689,a604a6eb,85233ccf,ef57fe7f,8a73c430,10e94b8c,4189225b,fe97637f,e7b97935) -,S(7b74932c,71dc26be,429f53eb,efc29905,bdf088a3,f2cf4bb,9828b701,11798163,e07d2133,c628a82e,4a22f58d,710b7d88,892cb999,2f921c28,3772310,c72909ff) -,S(308a025,4f659ac0,7c4e0850,738a2f16,df89ca15,fd64b35f,8f968413,b00b2819,4b4758f4,1eab6491,a8b50fc5,17f7767b,add40ea1,7b1272d4,1b1adf09,5d33c990) -,S(26a78f16,95b595f,63ff1b4c,cd52acca,ae650319,e67554b3,a77f85a3,637fa8ec,3db38db3,ca1e5dec,c73f2192,c4af6ff,66842a38,c76d62c7,c5958fcb,67f38097) -,S(bc440e62,f8524e7b,aef0af7,38e60a61,b213ab6e,713fa9c7,66d28785,891f15ec,175add64,8d472b3f,1547970c,6de2a57b,d2d3833d,2e847810,253b3712,f4d740aa) -,S(f2300d54,ebe04aeb,7a9409c4,3f2bce46,72d9937f,cf7e2a86,c4e8d55a,ef2a4e26,59e0e44b,9e090bfa,5291f436,6a3a5336,a56dbc96,65ae1aeb,e71e8c7d,e2fe77af) -,S(4d34ac85,c64d7d4d,97d40331,3fc19118,ddf31d19,18196594,d2f7a08c,db951c1a,551b6581,e6a1949a,4bbc211f,30fea215,5da8389,a69f6681,96f947e5,f7c8f7f4) -,S(53c3e6f0,fa2795a,adab1a45,a0f30f00,5f0310e,2f989d7f,d1f4504e,d03f2c04,12b382e9,b867a8c8,55461627,b7996676,880784b0,19690280,e709e91d,93048a32) -,S(259b0a65,79eced6b,2dcaa804,ff86122a,24e0d338,165a3013,9ab59f30,343f9ed3,27195af8,5217e109,33e2e1ba,57ebe333,9910c84,9b4e8f6c,af5700bf,93395635) -,S(fe07b39c,f9bd07e7,980b45c2,bd791e14,450eadeb,f6c41206,e73c101d,51093908,a8e47a5e,7a7cd98f,4f5e0afb,b5cccf03,56491271,c85fe0e4,9ae12558,721c66fe) -,S(7f38bd5a,87e2ebd4,526bfa35,5ced4f47,87c404c7,74e7f481,85d40d10,894210a1,4073ed4,cc499ca9,e7f8ff5c,f91f9c4b,782b6e6,f6225edd,d6f69fa8,b0b7fdd2) -,S(8796a424,9a251ecc,c0b3b44a,37edd05b,e34efda1,20926343,3a099e7b,8ae40a82,c02ec680,2860ecd8,f6ac62e2,845e8470,ff60cc55,10bf0179,49f95517,c1dd25d5) -,S(cadcc04b,9d4d8e5,22c153bb,def50fc,941cf94f,bb3b254,61422a4,7e6891b0,4ea1718a,53d64935,ff01f0c3,37ed2b7e,a31f9a15,edbbb60d,bceef362,8a454259) -,S(f2e614fb,346faa61,ec752d79,f9518b1f,e8f535bf,75496cca,513fa961,77f571a,1831227a,b5a35867,82b30fe4,720d2467,68f8c358,8472100e,fea76526,4581fa0) -,S(cb10686b,d361e64e,d82d6aab,5373f62d,b165d3a1,30bc7022,cb3f37ab,d61adff1,d969d37d,9c3db8d4,2c60a24f,44abdf65,b19fc6f7,56a452d6,7ef1b099,613019d2) -,S(6e903855,15042422,cc16d104,962352f0,2e86847c,f816468d,5754c70,fbc6d3cd,cc49058,80b7c15f,6f718ff0,ec2d8544,62e636c4,3e20dbdc,ee318a87,2d52d9fa) -,S(2c0a40ca,38f70b73,ef4da636,185c8260,e50643ff,9b5a83a0,fc0d410f,5526ac12,3f1eda92,8c32cf57,64d768ef,7a6afeb3,89dba8b7,e5bbe5d5,29b50410,5136ab15) -,S(1da89240,4f7ac31,136097f3,ed3055ea,d700aac5,a87ad4c5,49246211,f0ab0d0,e20f1baa,6ca3514e,ed4ceba5,9afe1875,c717597a,b7dd3c37,6d638e,287bd49b) -,S(5113fec4,172e4cf4,4eb27c6e,932e1d93,f16b3ec5,8c791b3c,e22c9bb3,634f76cb,7b129bae,b450023b,ebf81c01,bcd486a9,b494884f,b005b2e9,48eceeae,a6911760) -,S(a8d236b7,bff53a1a,fe23dd5d,63433dd0,a267e05f,31bce172,f80c5d65,c24373c9,698101e4,33e8a6cc,45b07552,7aa4ffae,3714324f,d5da0ff6,4fbc7123,773dde9a) -,S(79b2cfbc,b5a0c79b,d2ba680f,a1b594ef,4b2869da,3baba7b2,81cbf373,9d6f89b6,df45bb38,a21f4838,9e9eec46,f34eb6a9,78967e6c,5d181a92,e989e275,45756aaf) -,S(ba0eca95,4ec16133,1245f4fe,d70b725b,97393053,84fb962b,d1a0a014,cc403bdd,7bb5626d,2ee7d5fb,ad9cb623,7ba48440,26cbc27d,651811f3,92682622,2df76258) -,S(69609368,c01a1920,d3f62310,311cb7d9,cfca4659,1f53fc31,1f0af251,1f99fcc7,73ee24fd,32b08bef,f4254bf4,51614b2b,c0269e59,c6caf25b,bedb4919,76186894) -,S(c0b4d69b,d2344ab6,df9d8427,d480296f,5e0333a6,4a447302,5eac698b,e916f676,817dd44c,49b24aaf,627620c,ff7bb843,a84c7eb3,cc7e77c4,f65ba06a,14abd07a) -,S(80fd0f21,435d42a3,5ba377d4,e2401afc,dec30b21,db770277,fbab9841,3c5d9f9c,502f305a,a3350f4f,50d418d4,9b19768e,4976020d,8e158f2a,6cada628,e79953fe) -,S(7e18fb26,a881189,e3862fe0,9006e1a5,e07aa6b,39a5ef66,4f52547e,1cd7ebcb,dac9006,d99e8a47,d3c5539a,508f3f41,c649d475,4a53fc43,2dace107,1112ca84) -,S(a5b8503e,3f7c067e,628e5f5a,e65a0891,74385de9,69049aaa,26df1906,ed85af56,e9cc7458,fda4c95b,6b502498,95f4bdfa,ad9ed7d,346609ee,6549fa16,6e98dd1d) -,S(d93f866,450f7693,689bc9a4,644b52a9,3d006ced,d284332,4dac7fc0,bc6ff548,94c7526a,14b30b8c,b5a2b33f,c6508dce,fa141bbe,b6aba116,cf3cc169,ca094b08) -,S(424ec330,e4f5dff4,31ce33ed,1ef8293b,b8cdd070,12b5b18a,67b3f4c4,d766bae3,94f29933,fc5ee8a9,27295c4d,8d28b3a3,67c60d6b,13247616,a4dcab96,b58e2dd0) -,S(58805d5b,10cf81e5,b114c372,69dd5dff,cdf7e153,370a8305,bcba9d3b,7ebfe952,15e7b2cc,3ab0ab9e,a36df4bd,ce66bf72,8c45e295,d4a6c94b,e366f86a,ab39df5d) -,S(dab0c80c,a05aa70a,e626f81d,7b85c06f,b418ca69,8067b9fd,83cc6e0d,6a3949e8,4c728c4c,527f9839,498aff2b,91e8a344,aedb11cf,7ab9486c,ab3c7014,3dde8e3) -,S(55b54261,cd493b2d,7dd46f1c,78ad3983,787a37e7,ad8092d8,5cd6a55a,b870e09b,bee36be0,1168a67c,13faf147,6a614b6c,bf7b149b,4600c93e,4ec199e0,9f7fc63a) -,S(ea4f2da7,a5cec770,d986ba06,b1f18ec2,b3907a44,47fa2bef,4c9fbc10,d92afd4e,18f9565a,41583c3b,f7015986,ca7c94c7,4222b81a,9ac26eec,e7954baf,cb470072) -,S(5d835d26,54e489c3,d726f54,bc06ee3f,11390023,fb8d16,61f76b2c,29cfb78e,83091f39,9d1bfaf5,216add5f,dd4d60a3,469aaf82,ca6bf5e4,1070c03f,792dcb2e) -,S(f5efa7d1,484fe717,428e9f54,88c12db1,c775073e,27d028bf,7def8c3f,4f558774,1139d67,793faccc,70c7f48f,c892c314,988d4767,b9d6fa2a,2f2b632f,367453a4) -,S(132950c1,6f24a24f,a907cc59,704692ed,b6a5d254,79dea8d8,38cd71a2,a5d6542,b1e87d14,db8725f4,e2c2522e,c2f3f290,11d664f0,e6e85368,6c142c3,bfefd736) -,S(e479b0c5,478e49b2,c9e211c0,8e610b4c,1f1917fe,5960ba35,9af83c9b,4640d05,66ab2af5,3ffbfca,fdceb064,452c8ab4,b112ed68,8bafed44,1b66ef80,92144364) -,S(41b8288c,19cfecba,562b30e4,93a4c796,dc3adc21,f0c7a9d1,6adf4459,375edc5a,3ae93bec,6f438174,b3956d57,d9dcf29a,d673f6ca,74c96120,c22018dc,fea42398) -,S(56696d31,6d3cb87a,a3eb312e,1cd41768,2d0183f3,b91f605b,c4389d59,d86052e4,5e96c041,e495e90e,2812c09e,81d431c4,eca7274a,2204cb,a3a00a0e,650c6b21) -,S(ea36425,bc35c1f2,f0d96a49,ce4f4446,72848c5b,ec47d7df,6ac5cc30,d3968ebe,b00381cd,a5c19740,a266e63d,d59fea3b,d3d3d3eb,c899bf9b,da8090f8,1eea766b) -,S(84463c57,b01dd5c9,b98e0e4,38e221af,58c0e077,20540b7,da0b4d89,b3c36502,deb3a24f,9a0305e8,812fbaa2,f81e5fea,fd24c375,6a529c3c,c2bf4aa3,8d87b30b) -,S(13a22d5b,d23428f9,912df3be,eb82f4b,411fb39b,1604fa7d,4db63862,293c2310,99a19b77,c6912900,1047d70b,7e84ed80,a8427709,67384cbc,da11a158,6ddfb1db) -,S(de017231,52bdadcd,21b028b,4cee806b,89e98728,f91784d3,a418d7b1,22aaeb57,7ac0a9cf,15ff4a0c,f7d8a0e9,d2fe1469,1a08d526,7e3475a9,381be3bc,64771e65) -,S(1fc63549,9d462327,afc13d0c,eecddb5e,e99bb085,55076d88,7c064e8e,e40396dc,841f309,e47fb335,d2691c43,248a151b,426f1205,ccba170c,7c644615,54258a55) -,S(323e5acb,f821f131,7ff1dddc,822cba0a,b3b2380c,ea2f1b76,903c906d,83491dda,afc25ce3,b13cad24,6f6d9a2f,71e97d1e,e31bd2b5,967a5cc,7ebb1caa,adc7ee) -,S(57b1ec40,5c187317,ff9e70dd,2fd0eca8,cf2b94f0,3d7737ac,dd1468ab,61f56384,247e6f6d,7e2e70ab,a8d50794,36b1f6a0,b27865ac,791d1f08,c334013a,4ed93386) -,S(d6f5f80f,80586e87,5cd322f5,7836327e,225aceb5,6d8a83b1,6cf3bd12,4b581074,e925199,b597c7a0,a179cf34,519ca3a,f35b6d9b,24d76118,ace70f99,f1932979) -,S(2fef6c2f,eaa8c4e7,1cd31179,e0bfaa85,95d26471,fc36be60,1df75cd9,94e73c02,eedc9575,5bbca159,2271bcdf,d9ec8bc3,466e4b77,36d28abd,e6d68ff9,b9820f06) -,S(e488b041,358bf98b,11cd31a7,77a7d93d,e9cb3a61,c49fbafc,4bdabcdd,7b895964,755147d5,ba8f1d44,4ed0eeb3,d072c11d,f448c132,b9e06f4d,66f92ab3,7114a1b5) -,S(ba2591b6,35e7747f,20553589,11e7165e,618b6150,222a70ab,afa66bc9,a931cf35,3c60585,b16b1d07,7bd578f1,85e76bf6,77ff788e,a9b2caee,6c64ef9b,143ef487) -,S(ff4b12b3,cb0ec8d1,750c648d,6ed2695e,a41f8e82,58ba8b16,bf4727ba,6120ccf4,e2cbc52b,f0031efa,74c1fc8d,25466888,41c695d2,393e19e7,287bb34f,afb689ec) -,S(9e42cb1c,aaac0c62,47e4028d,501c84ba,6279b39,dd17424,73c2cd10,9bd36063,c9d0d646,381ca19d,528d2ff2,b04aaefd,9f8095a6,8811f8e3,e85b5ff1,5a5da5f) -,S(610e8f14,eb180ac5,ee435530,812941e3,ed7dad5f,c7bc7924,10f296e2,449fe005,67632a19,b1567d77,b0b5f013,77c6a05e,9261ca50,d010340a,968d8507,877fd4d4) -,S(f4c4230,443f3324,7be7bd5e,5cc12a0,27f0ff23,ede41c44,beacedd0,64789752,55d7b7c6,866f6bfd,29a410e9,8d5d5e21,98719d60,93e2bafa,697a8b5f,734d8bb8) -,S(66221ff,1d344797,1f308b89,a26e993e,c4d1c05,2c2fa436,3729c9aa,8c9dad0d,c0c78a0f,be8ba04a,932a7d6d,604f0fac,4ee01452,fef801d,36d3ca93,c4b7a965) -,S(c3ea4e8d,f8ac15b2,1dd251f9,7ebd19ca,2d91e97e,b13085fa,98294915,6aecfcf3,a7286bd0,3bc8f0bb,a3d28b6f,c513c4d0,472225b7,aab70f62,18c1a735,b31f1547) -,S(762ea616,8b3056b9,da318ef7,53ae0cb4,ff57eb15,8fff58ec,7e4fca2c,b605a49b,195d761e,9caa7603,ff1b5ab9,85d4bdb9,d128ba93,33d6cd94,f00c62f2,9452c8e1) -,S(50cbfa1c,f9a07c2b,42783077,8cae738c,3c3a0d5,617b8c6b,81914720,25712a6a,40a37fbf,97da5646,a653ec25,eeef583e,15cc1db,5bee9ebf,addf9706,cb14e689) -,S(bb8b806c,6798d001,f0d6b31d,1b17cf31,7a5422d4,3a906a79,294e5243,e22ae3ba,46b763df,b7a7a967,75b6b3ac,d21cfa37,a187ab39,99506c99,31623acb,841d4dd3) -,S(5491fa1d,88f0c9f3,6d87e074,331a9a6d,c17a5f63,b1e3326,500a5bba,1f0081d2,6c206f15,7dfb29d0,3b0e5878,57d1abb3,5f18b260,45c58da,87e8c128,7f699a83) -,S(c9d2726f,5ce823a3,ce02ee66,262d0673,f04ee272,dbc16cc0,27068850,cf472435,ff62f77e,60de3ae1,52c7f943,c3eed295,fe6a7aaf,8e6ba0df,bb60a8a2,b6081aef) -,S(a0d934b4,68151a34,cea5ff0b,d002dfb0,ec51df7d,ca5afd35,56acd53e,39515256,2f27f413,ac43711d,fc69e5af,785546f5,8e0da1d0,c9e89271,c8933b21,5998a999) -,S(342b7a8d,a3664884,1d8198dc,5e17b669,f4e602bd,5dfb28f0,95b7751e,4ce8602e,cf36fd4b,24cc36a2,806f8926,db6951a4,4c545076,70ee674e,8e2fefb7,e33f65f0) -,S(1f0993db,1084fdf2,6b2fbcfc,cf0c8a24,124c2474,92acbcb9,6221b788,18542b87,fbf92437,f6feeffa,4e04267a,c8dc57d0,c6d521b0,2631c20f,876fd9f8,b00793a8) -,S(f8f4034b,d7fcc9b4,256433c0,c2b40f9b,2f45a117,3a371707,f6ebec47,e456d9aa,cd895dbe,d97ab95c,b3c98512,c46a538f,385b9b26,5438f7f9,8caa245c,c680f54c) -,S(c80f3bbe,d409d5a8,cc0502ec,d7d95d8b,69067e61,fd2e8f7d,45f06ba6,7db89a33,dc803aae,6b936dc7,27773f6e,17c5d2d,af87a1f9,464320c5,4fd0cdd6,d7ef5c1a) -,S(b19fd3c7,8ee32a3e,dba4d6db,bb1464b8,5b3a5865,7f0c06f8,31af5b39,de2b436e,242c72a1,91f17614,8ee25c12,e0f8d4ad,52837a48,9b94b16c,27c8053,43c8e523) -,S(c88c52f8,a658160c,b10614bf,c744f668,ac46b774,94592a1b,99562a6e,e6482099,5a2f3a43,bfa6873e,7a198ad5,4fc0e3cb,2047f268,6396231a,a158a5eb,f4aa3170) -,S(b5f02d99,8f8f1c5a,8c8995b0,6879c804,1dca6f17,3666613c,efdbb82,820164e0,8e39ef2,207f5d31,2e36ce55,3569d2d7,2204a9f2,500ccff8,50bb67d0,a0802585) -,S(4d4e728b,5da0713c,18fdde5b,290d24ae,f7150d42,f9e5625e,f05bd17b,124f8302,be413caa,b7c77064,91110243,a20545f,8f9e5357,49ce98d5,cdb41384,5471bb5c) -,S(92832d03,32f7ebae,b67701ca,a0a2bfc2,b36b6403,742f4ff5,ff2ae46c,242dd226,cacf8955,92bc2fd2,90dc5b5f,b4185159,3e4a6a0,709a51f7,32e8c554,7cdc4114) -,S(2807a982,b4fc3fc0,8908fc5e,b3734a83,b2e2035d,8c6e3036,b16f9ac2,f4bba58a,ddbb9f8,3a9a6ae0,9945ebfa,9cb7e7a8,49798032,8545379,df582f93,72cea69e) -,S(e755ddd9,139cc4fc,b266477d,645b4efb,b02088da,752d10af,aee5ff8a,45df9659,fa7daf3d,605846c6,35e2534d,746873ab,cd502ee4,27e62c45,ef66401b,c816beae) -,S(93c33dc5,152a9bf8,31c3cf7e,ea833ca0,485f852d,52a255f3,55d7e67a,c1964f63,4a3a36df,13c8cde5,48feb589,dc56eb16,9a874272,c7a0becd,d40554db,cf4d8f63) -,S(70d66e2c,8f934356,d6720d9b,4809b984,6c7ab1c4,f8604990,d2e559b,a59c24c,24e8b668,4ee0062d,7bd79b3a,c96e0316,dcbffe2c,973ff6bf,e99590fa,192603e8) -,S(c165111e,fc2d7105,f6bde2aa,7f682287,2d803fa2,ec904380,27195cc,147904d2,c71184de,f408b79f,32086d4b,2b0e5d95,aed6e0e0,eb99bfb2,7e917abb,8d3a5e74) -,S(12144a63,67cc355e,e75486,357b0c79,ff4fe703,57a2f89f,3e3f7e20,ef860204,f2bb05e6,e55171c,c839fdb1,2b49ba11,dfd53af1,7a5a9602,4327f93,940b8491) -,S(3179dfa8,bd134725,3988033e,70f806de,fde9c6c7,aa4a6d43,a5cf110d,6fda7828,3133a35a,ffd1f24f,579fb314,2e72590e,475e931e,8766d462,842972cd,70e49344) -,S(51fe3e70,e5f21b21,1cae97a9,d0fa49bd,166dac17,5087ac3,a93219bf,d17ee77f,f3309396,5677c691,2a987cc1,5b3f016a,4efc22c7,6f89f562,4830f09,a9fc9bd1) -,S(2d7c98c,a224ebd2,a5167017,88018bf2,1f29444b,6eeead79,dfd9e503,7fe1680e,abae552b,bbeb09d9,dc82af6a,eea16d50,613c9314,be23eb79,d254a16c,decdc02a) -,S(c356823a,37dc335a,918a5553,bb0dfb9c,704ba647,d6cef22c,1e71bc9b,dedaa333,d8715c0c,a0ebf8be,d79ea3d0,85a70d2b,b40efecf,7dded60e,13d0577,cc235e3d) -,S(91af0d4a,56a75616,e9cb1351,4ca27ef1,b7411d9e,5991be14,c1658450,71a2b3f,f6c845a8,76657a63,ed37bd33,46ca60ef,a8fd151c,24a9e35c,5893f969,2580e26) -,S(6a32ae36,93ee1e7b,77fe8418,7266e6c5,cb41c7a7,37351cea,987a4f80,a26cbe00,2816504,dc3efca2,67e4bba2,5d4c9dbb,e8622e99,4a712503,37320925,ed5f64db) -,S(5851d327,5e18fb4d,79292e6e,2bd6bf29,b6301e08,7b418ac1,43afdf70,7d880901,1e17a9c3,dfa8c3e6,c1e9c34a,785321a6,e58d8024,c61cd02a,8b83ad41,a2366211) -,S(233a98a8,9fec3399,f74d99cd,7d5d4894,1be8274d,8f7ecfa1,f4f3693a,fb26a654,e9d5a9ee,fa5e6cbf,9ffe590,bd7db1fb,b9e08125,93f42238,65298e9,eb42d7fd) -,S(8751bf4a,9676e2f9,5036c3ea,97749d8f,f452f67,cd1259c8,4c39e8de,9cf796c9,4f883d63,bfb0a01b,e26b31b,53ed8755,49ed6c1e,4b67a160,7fb68be1,7b845711) -,S(a21126cf,7330697d,714be16f,27986c9d,cca4a0f0,3a12b6a,d54ef31e,d7a3dc23,3b0e984f,565d9825,2c523913,d2d90a26,b47973a4,8d8669f6,8dcb4c62,399b9777) -,S(8123c441,96d17ce1,c6c1a9d6,2aaecfb4,cdde74b9,317599ea,450e62f1,5639c3e4,406c585b,c9aee3ea,dedc117e,d58b1c3f,db5846cb,6eb11592,469bf958,6872b068) -,S(6f8e1a45,c18ebfce,2e2f710,efbd7ffb,4f107a32,fa6a46a4,caaf8ee2,37a22805,b36a7c4d,712315f9,a89b5ac2,8d1a5d55,5ead81,d7c43b8,8155eee2,b3ba8d3b) -,S(51db2e94,7e75c9d5,4ea07ea3,35942071,5987090d,b81c3b99,40b85684,2b0f0bcf,70967acd,454e6ce8,ad015f45,e0578940,c95dd818,70268d0b,9782a595,9a1462d4) -,S(84e0b0fd,b16e03c2,cae53675,4eb3452c,86ef07a1,ba278abc,d5aeed37,f71a3151,5a8e435b,53a4b51e,2ea659b7,1f3371ea,dfb28579,8b062eda,300664b6,d3b204ed) -,S(ced68408,c2b01401,fc039059,5140ab68,14142b7e,d69a64bb,e6ec5d85,be833367,76ce2478,28d2581f,6779f723,327fa83c,8cb10451,fc34625b,d069885,3cfad07c) -,S(8d860f70,a32921af,6376c310,bf5093e0,572e9b3,44e9204d,f5487554,c4f5484c,6dd24078,cb9f8ea0,eeaa4f4,3f3cf99c,890966c,5da8fe0f,9cd70128,88907cfa) -,S(6223ee77,4e56b9e3,da6e008a,eb3ba06a,40bafa1e,84383ff5,65f98286,d9095d37,ebcec7ec,f750cde,9ff7972d,172340c3,c324d843,f31db269,c3f35a62,c5f15f36) -,S(326943a5,5e7b7ca6,951a78dd,afd00e10,c8ca7f6f,3c01a038,ffc4fc7a,20fe2c63,b3bc5a8b,c87ba023,ee22bb4d,3f92cd81,787f2af2,4ecaebe2,67fe0a86,21c5d201) -,S(f69b5d4a,eb0b550f,851f601c,92698789,f9f94821,47a0ade8,c8a19fe0,5742731f,2a74e8bd,94469645,c8a328b4,24975dc4,93adc83e,4baddba,6c41e10,3b58e90c) -,S(f69a5a88,b8f13bef,a987194d,6b00a79b,7e576749,3d180fe0,32a1868a,26d853ba,6eb589cc,9c51900e,a6d99110,206f60dd,cbdc368f,5ae8dd48,cea05218,3415cbfa) -,S(c00ffc9d,8a57cfcf,9624a812,dd2181f7,195f459c,3b858a19,864393bb,1d1a269e,3097e10a,d6abfc0a,3fa039fe,952034e7,6bda4fc5,c5614092,b124ee3b,bf55f87a) -,S(9c021c49,d6671103,cfddcc3d,8e54848a,addfefa1,d6de5455,e5bda021,126dd183,4fa1ad18,81362f4f,f0587b52,a7a1b483,2d14127,434ffc4,c5bb90e4,fce50834) -,S(59aae0a2,923bc36a,1a5bc8cb,ea5bbbc8,b34f1504,4671a046,eb3090ed,3f4b2345,659f89e0,faa1577e,36175240,2cf1736,a18b070e,4d4b0fae,9ed08297,362cb246) -,S(7ba1ee89,479254b1,f32e9e53,517f0961,79d17d81,3ab3666a,75d4bf7a,7113f252,6530b40b,7e66a084,97168778,61cffd96,5eb71e62,e8b0ad7a,7d2851aa,15a26dd8) -,S(4b0e5728,cef356a5,c6d08616,47c268b4,c8a12d8e,89c2da7b,78e9db87,7b606719,235ec085,a1f3651,11b5f03d,7237dcf3,d70e851a,6dab8446,10e45fa,2996e70b) -,S(54285c70,315d9a43,a040bd05,70c35713,68504efb,fd103098,79067d6e,765d4499,de233654,e7c05b5e,f144d25c,6d539157,51e83ce,7f88dedb,7fbef11f,d6acadb6) -,S(ae15f764,d20e4eba,b95c3463,402a2159,fcd21daf,fa831b3c,e47bec08,9bd43da8,474c4cb8,afeba9e9,3f1d0a2d,28911298,939328e,5e364d44,68c64cf4,fec2eb78) -,S(6de8743a,68c42b81,ad069f2b,fc1482c0,204640f7,74515924,441ebd9c,917e3974,7ed602bc,16300648,86ed0369,21936ee,aa5e9764,ffc294e0,bcded12b,bcc86f55) -,S(7e4951,dfae38e6,f9869fd9,6d058847,2a38b0f8,827052f8,46195e21,44213a47,6fa2e60,a3883383,f8efebc,f39329a3,b7aec31,2958510a,dbdd5a72,728035be) -,S(1f7eb5f4,47d53537,3d29770d,5d7ed36c,a2d2a4a5,550d8bc1,849382fe,3847df55,5a351374,da5a804e,3b995d43,49560f7b,aa417dab,936860c5,baa252cd,1753f25f) -,S(dcc1272e,b31560ec,64a4b53d,24727bde,da576493,b571b5b0,aa7bb3ad,e8b2dfb6,567e08e7,bde60e6d,a614f321,a9cdba4,1b860f41,387b3854,603a8740,f93039b2) -,S(3f4e219f,5014414a,3c757cd,28120043,3cc199b,fa843c40,b344b32b,87dc7e7d,dba2099d,839e9c1e,7d7d4c0c,9444e956,168e2bc,4df1dc52,bb5b4da6,3a8283f3) -,S(dac6f264,74fee94e,dfbe9de,cb2fb88e,272ff622,4d7f8b86,3076337d,6d37acec,1bfc6855,5af0f07a,c9329ed7,5549560e,8d3e0c67,753d2673,eb6706b5,27a0de10) -,S(82ac1fb6,5a975de1,4bbd5709,9e2574d5,ebf883c7,7f38a7c6,1408dd3d,5e49b33f,a6d9dde8,b43656b7,9ab5d880,f3af2ca8,b70da7dc,251a7299,cb236b1d,75276c56) -,S(19a59ade,a0da1340,36a533b8,ff202a58,55b9182f,b19e8b79,caea80b0,9e263706,58030bb4,b17da5b,1879a67a,12c1d929,88cee2a5,d8915528,26456762,9a99f256) -,S(27e8a699,eca192b6,7a66b1be,5b290e37,1ff8e912,5afef253,134af2c6,ae709ead,54ae6059,58d036ec,959d789a,5316c70,a09db19b,179e5d4f,effbb057,abd87eeb) -,S(25e6cdbe,5d7e37ea,fe2b51f1,95cac707,a2aaa70,57fd5e78,8fc926cf,76e65466,576b2c22,cb6ba6bd,6acf0eae,79b52ee4,1fdebde,25293347,d624973f,e9b66be1) -,S(a0114d87,cc03bfbf,97e96821,2b69c53f,12910c87,e87e7a79,109f83c1,7042dbb0,869c33a4,cec89d65,633bbe60,a3cf7b70,1e5c83eb,e7c229ea,a4c279a0,4203a9f9) -,S(e8017e4e,806557e4,61ea997,f5f46e72,9fb668d1,e8faacc3,5804c35b,6d5cbad3,eca21b4c,294ed18d,d0df0dbb,771b8bd1,659c2eae,2c843f8b,bfd3aad,f44a4070) -,S(948209cc,528dc6d6,a406c996,7d7c191,19ab5142,679ac9ba,afc5098d,4d7c83e,3cc37cf5,1aecaa1d,ef14a2bd,cb6a1084,f3e60da0,9fdc4fb0,9d9f9fa5,84f14b25) -,S(10f4d6e1,c141dc53,fecfbdb0,b39e3e8a,c7f5279b,dc231fdb,55b25551,df90fca0,4f5e59b0,9c6daad5,80adde67,1583af4d,fae40d52,6017d5b2,9e798bca,6917e735) -,S(66361888,5d081bf3,9e9fc4bf,a0922dbf,dbbe8eae,451c199f,9aa844f0,71a327e4,f31b98f6,48940706,13a086df,12416779,a5c16ad3,7cf885d,5f1fdb37,1be94cce) -,S(6afc24bb,ae6cbfca,b34fd467,f23a31a4,4a0a35f6,203dd7b,a881ee5f,f340db5,7ab76f2f,6bada7ac,1e01c930,90c741fd,90c41fa6,943aa804,ff960b17,3ab28cf8) -,S(3551d572,2eff7d0b,275e310,d1466a70,2b828d8c,fec039aa,ce629aa1,2a9c23a6,b58af71e,1f9a6cce,c48d1fd1,18902a21,7f1e7f35,3ee9d794,8133d41e,2d2d61eb) -,S(e6e8cceb,f6096fcb,8f21cd9e,d428260d,c3867e0d,9c4cacc8,b8900fff,7bd4c1aa,d1b12068,f85e64f,7c9de5ca,f1490bd8,6dabf18b,4b78b5ef,531d9bd4,f64f13a8) -,S(5cd74a22,d46e7769,15b3c84a,492fad11,8790534e,dd8d9bb1,e117a6a4,78f566cf,397b2429,f978404f,ec96a4b5,28db5a,1b0cf9ef,61f2fc7d,470f0554,eed5ee08) -,S(abeeb656,151fc7a0,fdfca1ae,fef91a7,ae156db7,c433178f,be6fd700,991e8b86,e2a10216,3a8bdd0e,8254f459,b573d182,eb55f2b4,969a3f80,267b060,9f208a8c) -,S(3f9702ac,3b96bd4,ac9412cc,8f40d5c,99f4d7b9,d211bd2b,18c6f96a,ebd2f958,e077e28d,8f171626,9488fa5b,67a54800,b0d5a519,4384ca56,f9836b87,68e9821a) -,S(3c8e54a0,d094d63d,60aecab8,675349e9,f229995,587cefde,eaa1f50,cf3032ac,e77aa94a,fd252860,3bff0189,f11d5f93,fb26fe86,dec719b2,f8bbeda1,3cf38ba8) -,S(8e88168f,41689167,ead8ca79,5ef784c9,8e3cdc41,43a0ff8f,2891d476,98387bee,fb4bf21f,343fc6eb,ca6fe337,ccb7a7a6,899bb29f,d2f60480,ffb0a187,e875b00e) -,S(d5c7df6f,31001177,f2e88aa5,43276617,7a598335,cf6ad98a,e55a6d66,1b75c1ec,2edb20b5,47b7c233,23d5c4e3,295921d9,9d98854,e780f4c1,e756021d,79f1b035) -,S(262b9c58,75087b02,490291f3,963160c,c1f5a3a0,fd6a905c,25c98bb9,f7268514,c7e4ec06,b4cc77a4,ee551a5f,6c90ea97,4a0b2193,f1b828c,305a0fc1,b22e5b81) -,S(cc94ea5b,a4fdaa06,93976b76,893dbd92,f602bcce,822ff271,7a13bc2d,6b31e7b1,c81c01ad,f2ff92f,5c2cc42,f3c30091,11e6901d,36c9af9f,9b408df5,c7460932) -,S(b21abb23,4c435197,5b73471e,3b2eebe2,f537b95d,1b19361d,31ca4e63,336b0066,db02da36,73e62e9d,e96e1bc7,b79ef4ed,49449c29,7f4f0330,227dabdd,5b4c3d9e) -,S(ed130512,5af211bb,28118dc7,fc22b8e,8bc2554a,a19a8c7,16f69f11,a03df1dc,fa146b3c,2e0eab2,bba69407,9ee3b6f4,2f64dab3,9c19a1a4,256283f5,bc0886ec) -,S(42b829a,96989e82,37e48200,20eca1d9,61e487d,a9c6f9ee,60586dad,8fcd0e83,c2e164f0,29b6cab0,14fe76ad,82ee7372,78124cf6,5f251c9c,c260e239,50ec4014) -,S(15f09133,fe57a223,e2c9ad79,dadbbc7d,ec85df2c,6af39fd4,a156eb0b,1602a13c,563206ac,b190bc2f,c7b24d2e,ff376cb8,64102efa,12f7be73,84898cc8,76a12b4f) -,S(b8446387,4262c03e,312eb0cb,e562f460,8cd4f65a,75b099d0,b45e0de7,8398f5bd,da730acf,79fa0282,a3a29b99,7a0ea45,ba0896e7,598be8fb,8298aaa6,9b94640d) -,S(6a926c00,ef4c32f2,52d9f336,29fc708b,e21f571f,1f320ae8,6e6c46b8,9511fb95,9106e0c8,2eb9fa36,4a84a2e8,8eadc9aa,9113927d,99adeb61,a2ac5527,5de9a9ba) -,S(fd6cbc21,9ec03dff,8f3d00e6,9de0c64d,30ca5a04,1556d0d5,87339b0a,925d064,742ce8ed,a4b47eeb,29883606,211c453f,fc15ae40,174e1c74,656a78ee,f3a85e8e) -,S(6fd7f1b7,61116218,68e1038f,d5f341,c43b61bc,b6ec53c2,8d84b321,ac664274,f681256b,947a9492,5b8402e4,26ef8d53,20c65a29,3a7758de,6b7e3f45,a9d635d) -,S(c28c2cff,1e418550,f73fb839,58c1ca6d,4c616c3,74a67978,d4dd71c1,99902ac5,537d774,83b1ca9,50174ee,381023de,cc210f91,3a66615c,b242829e,e3285285) -,S(89458f8b,7db2cd74,346b8b74,759088,fbf81591,5fa1e97a,3f34ff90,908cb183,9b5b21fa,378f50f,dff2e276,353179a,c0a6e43b,13373940,c2e73e20,106742bd) -,S(e66ed94e,793b894,552b3893,88a657d8,55ccbb2d,f9ae0061,2cc07244,bfd434a3,8a6a17f5,da95e907,7b03192b,eba324a3,5595b6d0,660851a4,7f9e2259,2f093275) -,S(8c7e4ce,f5dca16e,620d6690,ce3b9337,8000ca08,e73eac21,deb5deae,83359160,29a44639,f9a6b8ef,990b72c1,5ca6f539,31000a2f,394b59c9,36542992,7959c505) -,S(a0d1611a,807750a2,45c68132,2f7adab1,9b81de3,809a9a82,ac038294,b732bdb,c6e35357,246fec0b,ed0c5491,24f13f9a,a01fe39d,e7630357,110a5878,90d9bf95) -,S(c1cc130c,474f5ebf,e4b4e26e,a444d5d,7542609a,2bc65a68,9c6453f7,9dcf6ab5,deaba85c,f0f7f9fa,cac2415d,9f82c62e,9caf457e,fc9149fb,55bd8f2c,32f74ea7) -,S(d6dd2a36,763b77e6,259f1305,43c8262b,784a268e,45adcd26,efbd6d54,afeabd68,2987d048,9549cdd4,c27222a1,9562b005,56dac521,1e67d052,e76266bf,fbab179e) -,S(885cf8e4,ee0498f,29a7f3b6,a2420629,4a941f56,f3d852e1,4641a604,9415c49d,b1002bf3,e34ce44d,54a18be5,3737d98b,28ad0f7f,31d9bc37,ce31279c,fc039b2e) -,S(8f0c57d0,3d85979d,5bec7346,1f0a3b7d,540fd0c3,8d8a6775,fde2ca35,ec8a0d91,86a3f4a2,cc4f934a,8b833cfb,dbb96eaf,159e00ee,caa0871b,235e4f8f,97bf542f) -,S(53456583,d2f4d9fe,1a13883b,7775b363,3993c9ce,6bca547f,d05021a2,d36cd366,92cec0bd,cd83312c,455690fd,d715e41e,c29cc70d,f5eb2e17,7f0b2caa,f3b5214b) -,S(a5ac3a28,fad5cda9,200bef2c,454b73ee,bbc853a3,e8b2ff77,111ea25e,5f3b5359,4951843f,6e23b9ba,60f326b5,d6b13f1f,f49e8b3d,b399be4e,46cb3ab5,7ef10bec) -,S(2ec53b3e,6d91835e,d236898f,8857a64c,4d898098,9af6ba60,392b774,6eb99ad,e21f4abb,cc05952,eec3fe34,f02d64c7,e7a91658,b0b11b14,118c3489,7bb2a2ee) -,S(5863f940,a45c8f5e,a2361500,84c588b8,a7f99d26,84121d59,9073d38a,69494c38,db422c38,41a2bb32,98390c98,e9f4c23c,da27c64e,a5481870,b33a2bc,866852d4) -,S(3492772e,d177b4a2,5f9eed03,7094c52b,aa72dee7,1c5b315b,70948dcf,a1975a64,c5a26844,26418929,b5bd1488,49b3241b,d0eb5243,61106911,1fc32cdb,29087562) -,S(4405762c,ba4f63b4,2401ce63,120c3599,af37ac13,d2de044d,26d830,9e664a4b,3143da5a,8319bf4d,32941d58,e9bda807,74c58380,ad8c3a33,460bfd85,36d9baa2) -,S(4894f457,1324691,8f32111,e1bd94e8,a43f717d,74e8c465,550e864b,9ae2a16e,9c89818e,6f09fdc5,b36c65f7,12f26be6,40598712,fefda799,4b200967,7de01ea) -,S(620abc9d,4efdc1a,55edc41f,29834528,ca87b333,a8678e8c,205d6817,cb7ec3cc,f524cc99,9e911d67,dd0e8bd4,3e003ec1,64af288f,3135a602,4e93856f,8110f867) -,S(d69800fb,9fe61ca8,97f77226,d42749b,1274176e,29bb85a6,226f91e1,e8c62a7b,43baaafa,e10649d3,ff2bb0cf,10c58f8a,f01fd3f4,1a06c245,a4e9c483,8bc9e3f9) -,S(87a12e5e,d002cacf,f55901c0,d374f81c,ab9da24b,80e1fa9b,25f038c9,38344721,36586bc,17aaf4d2,5d02ae3e,e9f98235,f9d605fc,1954be4a,dbbcb917,1f736d72) -,S(a0af0d5c,bfdf4fa8,98a3ea89,867721d6,3178341b,ba30f091,946c72af,bb876624,100f795b,18dd85c0,9af012b2,5d7d5d1d,5118d02d,3837fabc,ceab0b23,99f98e43) -,S(ac94b41,7becf857,1248a94b,a853f4f9,dd47284,157e0b9b,1756c4ca,fb692086,cf94bf3d,d0c7f89f,acf8f678,5508e510,faf27a33,10915d99,80b9fcd9,62f75c92) -,S(649654d2,966fb2df,b917367,e2ea4034,fe886725,3711bc40,8520d5d,579a3481,bf8ac886,a7550c40,29279fe1,c4d330d0,89935427,d6967412,66d79ec1,f1a2780a) -,S(5f7776ad,e73826a7,fd2969a6,1511141f,cbf6fb11,23c8d7e4,3ff93835,ee1860c1,9faebe0,2140468d,4564f7c8,bfe4f097,dd0ba493,8656fb43,ea9f0f8d,22089e5b) -,S(f5dfe7be,f4c42f3c,e91fea18,10402c5a,9072b001,286a7371,35a00fd5,c71e2f17,9787d33f,821a0633,ab1982a4,f9240b53,38a5644a,4d203b1c,6b5cb212,3c837b4e) -,S(d3432817,3f33fa7,e517d6f0,408bfcb4,6a882c0a,6d78feb7,44f731e7,4e1bed23,bc1e6ff7,cbdaca91,edd419f2,e80e617c,506bf8d,8acd4548,8267938b,813a281) -,S(a4420846,95528dde,2c52d5ec,cd67266e,3024865a,c6e812e5,1ef4f780,505f9d2c,4a721caa,63d62b9a,c23ac717,7a27e27d,d54e5ff8,aa204bf7,3e6b3131,3ccc31ac) -,S(b3818c70,ea29c1bf,db63ba44,1e42c842,11f9d2e,4d6b07cc,79938d3b,b294b820,1b2c711,a98418b8,15abf79,44fa75b7,db8965c3,1779d4e6,1967f009,8c005d2a) -,S(3854b55b,def18a47,7e87f62e,d7607c6d,aa2e737d,e0e5015d,de7e90e4,570d43b0,2865de79,552c68ce,4841ad3a,69376a36,9d74d55a,98c35d25,f97656a2,fa22785b) -,S(e2e805af,78bf592,6a37fac8,7429f6ad,88c45522,e58e5c9,2bd2ddcb,e893ff33,c2206185,254ef80d,fcc7365f,1dee9a3a,cdac0ebc,d0ce6a5d,4c9a6875,f07a46f6) -,S(37510b86,df2d8e60,10d40e34,77af6c24,47f2a41a,fa35ed49,224bee62,eb0b77c1,1f30b802,6a3288d9,714b33b3,7a09cf20,cb754f09,730888d2,a09869ac,1e905ff9) -,S(14b2bcad,c5272c56,8930c574,d745fac7,d190558c,121df6e0,c2c9cc1a,f9662fcf,baaf56ed,f70fc0b6,520bea13,a8794d2,d397e935,65841028,6dafdc16,96caaf3b) -,S(2984937c,e3d6a155,7a185609,9e44bfb7,28dc6d0c,bd8c628a,23a383ca,3f38082a,637c5e4,9b0943d8,e09960fd,2375770c,5d4dc4b1,3ea460df,d5ba49ab,fd6339c0) -,S(e64f46da,d9b9e7ee,3d2878b2,f604728b,8203a591,d02e7d23,721fc436,165918c0,f7ec0e4c,9f66adf9,98b8e41a,d43fe3e4,7cb9be23,6356ef3,ef5b9a23,711e1140) -,S(3f587c9f,1b88ca37,d32af584,e510609e,ae113e54,8d07fbb9,a34f6916,908f686e,37712f53,41485518,241835aa,d31c45b6,f5370c6b,238380a4,ddbd0755,17b2b49e) -,S(8218250d,b1ee7484,b8892bdd,53be130b,4b5d3db4,7c3c9e36,5a17baac,5d8654a1,f19955f2,a7f954b9,2050c815,8e801222,8e77405f,c9f0676e,76ec2e4a,f3b93bf) -,S(5ad1a4a2,55a22c56,e8d17acf,786356f1,7ffd6453,262980f7,188879be,9e1eaac5,fec5d2b7,ac26e4f2,d4d7af01,b49295c3,3a969fd5,28e3aeb3,90e86bf9,85093dc4) -,S(1c92ee58,c5226166,c313b491,5c731d34,739068b8,f0241dde,6f0d7151,243304c6,5dff29a6,1197aab4,c1ac8a25,625c4dc1,11729680,15f03488,b8a4baaa,d541bcdc) -,S(fe622f9b,fd9c4ba8,8c80c82d,d1a07bac,c1c9da11,996240cd,50b6a41,f6f8fdc3,666e59ff,e9efb9a9,b7c36539,ac948438,f1de235b,fbed8fe7,3a084076,39f6b901) -,S(b2e8301d,ee34bbc1,d95de73f,b947bbd0,325bb3a5,555738a2,8fbe4e3,601a40d,6953963d,3496413c,53ef500,6def0fda,607d9a9a,319cb93e,22d9bfd,a0c3b807) -,S(1505e140,4644537b,56da7114,5efd34d1,566ee38f,dd4b549a,34ff312d,5cb9bb96,d6440284,c1ba972b,413f8c12,7fc40001,39954fd2,5ee4993b,4dcd5e3d,a2b843a6) -,S(7a524409,67918e47,53b451e5,243c6996,c053fce6,1f492995,8d2bb84,9fd1088d,e089d973,19788a2e,853a3067,c4a98c59,4fce75cc,a9ba908f,37780e1e,567b7284) -,S(69eff8da,8efa75c2,ab052d71,e898a975,c58a074f,c46fc6b3,2b385e41,93ff5a30,30e873ca,f0e7d1d,e58713db,cf7c5c9,6c9f068f,e0e3d1d6,c3863d44,8da1cca4) -,S(64a5649f,2da4eb15,1be3fb68,b1210cca,61b32492,60225ef5,53426992,95e6d6ec,8c53c12e,8fbd7c,811d4a85,95787105,4719c5fc,368845a1,6b8babba,1d92f56f) -,S(ca23d56f,46ce3458,d95a5b24,d998188c,3ed76a22,2034b337,933c4298,8c804fdb,efcbc7c7,d0d11fd3,ef1c0ac1,38d1a2bf,d0e94a85,a0700cb3,630dcaa,426a4c43) -,S(630b2d2e,62bf28a2,ebf80f2c,2bb10cc,82014ee0,c48e15a6,4cd691db,dfe8a55,908eba92,e889f132,4da0f927,9c1bfb74,dcf16786,c9c8a964,79757a79,d4443e9e) -,S(29b5c3d2,57674ebb,1cab5fd0,56534261,5a059eae,c8002aac,c000a857,a7b7c840,e7724381,f3f1cd4d,198a06aa,33b7fb9a,d6acdd57,45f900d7,be34fd6d,4f6dd41) -,S(f4b9c47a,2454985f,e732c151,3216f7aa,f5de769,89344c0a,4b8b46fa,c15508db,9c51095a,c45d901a,75229288,fe5d49c1,1dbab43b,9a030cc7,c6d71bf8,9d097378) -,S(af0dbf55,79f3f1f,91847143,99a09fff,75c8922b,48213c42,1cb17d11,2ab7ac71,56e7f5fe,e96e464d,50cf98b2,90a04917,430bc2c6,72a411a0,842149,8fe23d66) -,S(7ddbb2fb,f5d68e,6acf574f,1fba12e8,323e06d0,b6b80cb,1b9e9368,5543a8e9,888670aa,f057a051,1738d69d,162ac2f4,9074e5ae,d28cd6a3,a30edf9e,e874d7ed) -,S(43612257,2c25dce0,4a0273a8,a83890da,3a27848b,103d5ee9,1f0bb33f,ddf131c8,62cf1a80,7bdfeaf7,7b9d90bb,ec403b7a,b4261e04,62a16c58,5c9e1435,afb177d3) -,S(8691a20c,6df3b947,e173735b,d764ce9a,4a7773b4,4b4276a,873786a8,8e5b0932,974ca0c,6644983f,e4288afa,a80c03de,fa8d9215,c148a63f,1a1d4aef,365d9e81) -,S(7376518a,528c1190,b95cfdb,ef241485,c84f34d9,3690041a,e4d8b0db,295fe87,fcd56fa1,3d5cbebc,ea197636,ad3e7bb,f9faf472,56d44489,e7cbad3b,ca9e01e) -,S(9c5e491d,838b7471,87eeff8,f44ebd70,d6087ba7,fa2b957,8302e46a,3e5113ed,3e312d47,a32d61ee,f88dcb4d,aa38b024,7327ba59,cd377798,75bcd10c,2aa13278) -,S(884a9710,9e6e95f9,9a52d8a3,7b91480,d33a95e2,4f385ecb,d9666bc7,ddad4c63,f39408bf,4f27f2f4,ef65b195,b231edc6,c50aca83,60d23ff3,32b1c3e7,149e8d6a) -,S(f99760ec,771c8f39,d349fa7d,19b0ff65,bfd2ebbb,f2d4707,eff2d646,4beca7fd,d71a5750,a9737ff1,bdd2fbbb,9674905,5508c2eb,ad22aee3,6aff09f0,1fc9d996) -,S(f2cbe279,98214502,77f79ae5,22da1671,452c8e94,27562e3e,5d78fc17,9e758e2f,8334d592,9b50b714,a50ead97,6fcd8b12,f9806edc,5da45d8a,a226e029,282ab52d) -,S(df67bf7b,861d0636,30784bd7,f9a472df,6c2db3a4,7af8d06b,ea3665,cceb76fb,e939458e,513e55b8,7e4b90d4,3f073e47,620dbdec,d7ceb425,1353f4cf,a8d20624) -,S(e3f17365,4bb1e860,d1812852,c67c0095,50f82b34,434c5326,d5864884,bf64fcb3,9f07baf6,ae6b8c28,e8a9d807,22a97f51,bae7c98b,daa09578,5a2d1fae,3f359139) -,S(1cc073f8,ac4fe62f,e311eb31,42bd357e,45ea17,a844528c,7261bfb8,24642103,52303125,ef059a48,142036a1,ab6353cf,90a021d8,30a936ee,9cc4ffc4,91f514b3) -,S(f6b037a4,9394a077,7483c0ef,326e694c,be4b01a0,3accec75,629f7224,7fce7f0,f922659,25e4434c,4054ea7d,d4bdebc4,d3801c39,be53b037,715c6ec2,88b34db3) -,S(74966556,eb8c4cbf,cd364f06,b2bac116,5b914c76,d394dbf6,b5f2f7ca,14e54207,8ef7ffba,85b9eb27,f444de36,86ce67f7,75c8eb30,5bae0c6d,1962c839,a88202df) -,S(44d3ad0a,bd1f2ad,30957e00,594f7738,18777896,9b4237cc,d61931fb,a564ff35,af69cb36,28168fbc,f194f55e,e7691ca1,88178a44,2e6bb250,84c6ea77,a3d41748) -,S(7914f911,b6956f5,cb0fa063,bff4ee00,cb67058,3dd4eeba,daa4e445,97f816a1,a61b333a,e72fef24,a47f48df,90b5384b,b25b5f8d,5530a5e5,117a4f45,43948fc6) -,S(65a31bd4,10c97121,dcf656fb,55a71c94,ac34ba43,c3219b1c,86f19f56,bda94c38,a2e19092,35d8b549,b1926524,132a5220,e26beb5,f9d87ddf,f46aae23,dd8834c7) -,S(eb092b73,5b789bfe,9a466b70,3801b511,aaa33260,407b8750,cad24563,abaafb49,ee29705,18088ea6,132314c,999ee924,5f50346f,c7a9d114,169fc20a,2e6b6a42) -,S(38574e2e,8ff7d427,3870b6ae,d859322b,deac3824,bdc1ec6c,e34d88a,8d92196f,a0a6691b,4d770ffe,e5503d61,bba954d2,f4185860,19aa60f9,303f3e89,9fbbc7d6) -,S(5e555cf3,adf0d5fb,530f87cb,6fa753bd,e2c09d9b,d703a899,f27d2a15,a051a64e,41bba138,c76d1e98,90ce88be,1053bd3d,559e7118,4b900aff,c048a494,24e1768a) -,S(4e8518ed,92b06242,b0f28b2c,e02582db,e5f908ee,fc660c63,964f5e88,95b509c9,9e4fa860,cd07c071,fea0ccdb,f1b9284e,393d9f61,45dc4ddd,5ded2dad,b8897e5d) -,S(507d72be,dc881de7,86103317,77afe208,69619a4c,f6cd3012,e04c8cfd,2029b562,2f2ec47a,963f7c86,de8497cf,fa70846f,22dad843,29643444,706487c7,d9999da6) -,S(c87295fb,299c6f1b,410f1128,a1c88eb3,4467d0b3,df7dfcd2,18fa3819,58df06f6,2977ab13,5abd0c43,ef791c18,5cdd6b59,443ad076,5f190cd4,77620227,dc38c479) -,S(5f9fcb3e,2d7f842e,22ae0d41,48d74b9b,66b8d98f,fb66e4d0,1f279be7,931731ef,523a9ed2,a911ec36,87619cd3,f7ffde07,e11a2b19,e90771b1,8ff86170,a747193) -,S(42d833f2,b9717832,1b9174ee,75127d0f,5a850a63,52452942,56fc4257,f90f74e7,fcb299b0,ed234bb5,4f0c9ad3,e9a87bd3,f4a83bd9,916c9050,6952df68,f39dbda8) -,S(cb173f92,400cf477,47ec4ce9,f9852778,6636247d,55279b52,81388daf,99b77f68,f9d99960,1e669f8a,d8283ced,317eb2bd,5aebe201,ab97a62c,25573a0,65b28e0e) -,S(a73a52d,a2ed0dad,e9943a25,8e6a1f0b,6b2b772,b010d81f,a6eb3bb1,61877d65,71f7bd19,7e9d575e,25a4c592,92061743,2cf69ecd,f33705d0,3429966d,956a2e58) -,S(209411b0,398bdbaa,7412b2b1,49162c31,da88d9c1,5dd4db67,8ab3e19,c90a8415,1392e77d,af6bcf59,3162c8b2,2e8ff0b5,4ecf8e01,4fbdc743,dda8f061,ba8a24dd) -,S(74590b3f,a03daf8d,537d9eaf,410b6c61,780f4146,44e7360f,7d6e2710,3c8a6d9,d40fb53a,1f6768ae,b4918201,54dc85bb,62c5ee68,614f1e3,b6cbbdb8,e182d9f4) -,S(cd77abfc,78148f0e,1acc919d,e3afeee4,2cb6fae7,5f68ce7e,cd31e3a5,adb54544,a46dc809,f9b1d0ee,4ba8872f,95166de3,87b08a0,b68b3622,492841d3,f4c8ee1e) -,S(ad1d5f2f,ef4890e3,5d1916e5,2dc6bac2,612d3b0a,3511ce92,94262b7e,fe2da353,6aff87fe,3778f197,ca8b1a67,9b8f89f9,69fcaaa5,4ef0a629,c0dd311e,ae83e568) -,S(de45c27f,fdb38ff3,a91c0dda,56076875,be8a1369,23ef5a55,26af8829,c9a17705,43564551,83b6ec8c,48c1daf8,d8f0cacc,4b3bd932,5d6e5adb,89368834,2ef5ee90) -,S(deba00f,aa0d172,a6bf1c71,6d280e2c,8c8e35ba,9c15f0cb,ae574940,fb78883f,2b282f66,c9499232,dbe30521,da2298c9,7a0dfc43,562ac5af,74eaac20,1d2dd708) -,S(eb95be9c,eb4d5db2,ae9071,e5dca616,dcdffd15,762dda32,5d13b576,f6532b04,c21f9054,d504aeac,79f98cda,de167ee,60e8cd52,bd44e4e9,3d66e2be,a9867741) -,S(a2849585,a2d9d78b,9da83fa0,cdf7f4b2,62c29e29,876297fe,3ad3bcc3,691acca9,a165f5d5,9ba43cba,816ddc9c,b33c4d14,e4f768e7,96ce32ed,2f711127,7bb8c720) -,S(e5a492b8,cae88b61,c72c8772,eaf6de20,40c89597,a4c4c703,85c28e29,62bdad2d,a0dd4bd,8cc5136a,184fd7e3,aa025c2f,62f85693,163e726f,cffa37e,2be168c) -,S(875a7369,7940cc11,b00b28fd,c72b31f6,19c9018d,5c261af,f1cef7e1,be71b61f,93718642,241a4e8b,22760240,2b4f4e1,fef54882,1af31e69,cd45afb3,427fe8c0) -,S(39a301a4,69836ad3,f98d7086,24b53106,fd9d9aff,c1253059,f45617d6,ad6c0c7b,a7f00229,6ff382a6,4bcb9dd1,fd9afb5,4dfdc2f2,bac962c4,8bb76603,7224a403) -,S(8bc53451,922203aa,caae8513,4deadac8,10c585c9,f9fb44bc,57113a31,9474f090,a4bc9c8e,8ea5d122,54a6cecf,aa46b791,68cf14a2,280c86ca,177871b2,abc65b8e) -,S(796eec76,37c1fc11,3ef31366,dbefc78d,ba5735a9,28505c0c,e2a22ad8,b447b1bc,11e91c1c,f9195b5c,b8948081,7d8ca5e5,f0fa07e0,19ee5566,90da195b,c5eda060) -,S(ac52e134,1b531c25,60efb2eb,1c0c79b0,d1f3cb6f,3bcc4b16,6a7f701d,7d5a60df,4415cb74,b2ca5b76,985a1386,2278f53f,871813e2,905e51a,cad23265,64efe34f) -,S(c231c57a,ed49f271,2d571e10,fea59a11,c4d427c3,4a67b024,b4713af7,d2288d69,bb4ec242,6026ce7b,56471afb,c4ed8772,dada1335,61d07981,907d278e,70ce398c) -,S(1a1b76ef,11f3d64c,5670f06e,7354fc4f,a7c17129,75ed3094,b5a6df78,c8c03034,600c7a61,188e6ea8,76b8bd21,b121ee22,ba9d50a2,d2ce0fc3,d836829d,1f829430) -,S(82b4e49f,2d9d49c0,f409ce6,13b65a5,c031c8fa,adb3ec8b,62885760,c69bc5,67b8cfb9,56b80bee,5e5ec168,6cbad5f5,cddf38ae,3bffcafe,17d242ab,896fca10) -,S(bb3201,8ebb358d,575cf58f,c08426b2,f7116d40,8cd2d779,9acf6c4f,55de461f,8f3205b3,291c8da0,b0ebab8b,ac292913,12ad3a7a,83ac3ff1,6e6f55d0,445f22bf) -,S(fab9cc75,60a02c8a,e916bfe9,b61cce9e,32d37203,8b42b58,150db6a7,cdd40a22,132d8021,8e3b6ced,e6b3060,5812823b,80c7f0ba,f369caab,8b3b7cb3,bbb477d1) -,S(9f96535a,bbd2b21a,bf41bd19,549528fe,1353724e,cfa3870b,3df3256a,661c7e47,b8acdf49,a9783748,40232e1c,9a0f6854,1547b7d6,d1d60bb5,c321a1b6,54fee431) -,S(60d4754a,2faf463d,f7b0cc2b,ff4e6495,ea9fa9a2,e2f1f4e9,d773301b,3d406daa,43d16225,6bddfb93,3588da3e,511ec648,5599ef3f,7db3a1c8,899c21ea,2fc91936) -,S(3850610e,10a40ef1,5aaf4d4d,b11ce214,7c82a449,ea965cb2,5cd9ad46,45ba44d8,c10cdca4,aa919f20,4ab148c7,2eb4e6f3,7939c70e,e134433f,5c70e45c,fc30be3f) -,S(68089586,3a26181,a6966055,1ad8d431,9d325533,70839d17,fbfed5c7,fb84fab4,a0cee277,97d2ff7f,fb7a6805,604eec37,4ef4182f,a163c53,15924f,287bd447) -,S(aee5d57d,17a9167e,9d3ff19e,8eebeb09,7675b709,e3a89ec7,38280b9f,ab9404da,154f14e4,f991644d,aad6d858,940a6126,5a8f1c1e,ef6071db,5e138081,5e2d34c9) -,S(8f3362fa,659c58a8,2376ab88,c921fe2f,2c8a5de,f36c057b,3154800f,bd493950,5f88cf3c,3fc1ccc2,2105f3c7,8ba7b8c5,525a9fa7,7cf76976,8906d0e8,caa64408) -,S(2bfce32a,9d69a14d,324d8f94,15b42f87,25f5befd,ba3cc6ac,2a5c7778,f23187a3,f7e88e0,51ea8e3b,788e18e2,95355b2a,75fc3c3c,e62f7797,d3b02681,d6a3b63c) -,S(62984e62,5d026f0a,c6c82fb0,46dbc152,a05c9a22,3f55663d,5cdd87d1,e094022,1dadce42,d6b68fcb,19439f33,2d2db167,f33861de,28cd303d,c94e3a8b,7b26964e) -,S(15502824,b02a10a1,d7b13137,4175bcb5,6b70f796,fd3d0713,42bdee98,99d8a057,b391d51b,b2b89dae,5b687e16,e2ce1351,2296130b,e86a7d21,c1d3c6b7,b20eca57) -,S(1bd98bca,c0ed80d4,f23422d,c32c5922,1164ce33,55526ea1,61e1d9fe,518c0e11,6b0afff3,b0fa5029,b4e9731a,fe772fca,c0e30c84,e6c652e0,f22dfd41,a9cf0ef1) -,S(4dc9e532,d5543e88,a59872fa,24b99968,e649977f,9ea08bdc,303ca4e,d574bf40,7c05536,d9181687,133dec90,43cae3af,42dbe034,af05a746,b6de1ef8,20276947) -,S(3e92be78,d7c7db61,1049827,42b0d213,672cc543,c27628cb,f5985c19,5685f3a0,171c3afe,c69648e,7bb7912f,fdfecc4a,78cfd246,a4fe1263,e5eeedd5,330f84e4) -,S(57b6c4f4,75bb9ce2,2086a5a,dfd5473b,73b0f6d6,278afc7a,16854e6d,32b2842b,4fb4aff6,738f05ce,31ec7934,3638a717,3806d347,c11afd82,e39d492f,b961ebb) -,S(571ac8b,835c5f4,a7457344,e8572910,309f0d3a,26b849a1,b3bca2a5,28771b59,317ae805,3aa2855d,aaec95e1,72f4005a,6ae09ce7,187590b6,41fc13c4,9bb4cf9f) -,S(534c2141,e38a7880,bf146951,7d4ceaf2,a25bf5d6,a538eb1d,4161461a,ae54c4be,59dc6548,1b056dc8,c3e98364,ce6b76f5,fbc9c501,6ff24e0c,1c7bfffd,306b03e2) -,S(7a761f86,3a224193,157d3d1f,8fff8a05,e5c13366,a7ef7604,2cd3a1ff,f9f936f1,20e86bd4,5e93b784,f433d6a5,8056c6a8,e8d1fdd9,e924fd37,bd5b16fe,fa0ece9) -,S(c1497e7a,b9373d32,4bfe813c,32aa9dae,f1351351,c86ed382,fd3d4c5,6a54f62c,9401bb9,1621a327,2c233004,d6a8093d,f812ee66,604eaa86,32085b3e,482eccf8) -,S(2dd83787,e31e7237,f49a570d,adc675bb,147b91e1,3910f22c,e41bd16f,edf3c0bc,10148349,6883687b,7ee844f6,d60ee90f,1aeb7c0e,c9f83293,be96eb2f,5cd6d46d) -,S(938f1399,18a0fe3,55ddc7ec,d6dacd34,1d9c996f,9ab4f9d6,90b435e1,fbc0a74c,30c71b30,e7a3c244,b8a576be,9e527e6e,60d1834d,17908e6f,a0771daa,92517448) -,S(e71217df,430dc65a,d188f6,861b00ac,c3214125,447d8e26,7dc5473f,9471284,8f27019f,114e542e,96eb5121,b7c3e094,f18f6287,f2cefd9e,6a5290e8,5e1dbac0) -,S(ca2ba87e,4c040efd,c06ca7fa,50cbe414,b66bb2e3,ded2bfdf,7744f81a,91b102fc,24848b82,4019bae7,4cd7604d,101c4819,6e808ecc,79db885d,bed68354,ba3f138) -,S(c267ce5b,633c7f12,1be2b297,45b4dab9,ff488b02,c8f89ba8,706948c7,77167ad7,16184a77,954c3b5,f9e330f8,e8b308de,1489ebe4,bb9ffe59,f3f545da,e7748385) -,S(1eb9af42,96d58c44,bd6fe2ff,db05e0ba,1b5f581a,af842883,5a47a050,468f8b33,f88a1128,95e53e05,4e514117,5a2c54f6,a235cb08,3494a7a,991fba4a,fd0bf1b2) -,S(ba342b95,76bea3ec,15aafca6,2f4f505f,c35bc2ca,64e2f4be,22323b77,1ee39062,91be5746,1fb662f6,cc28e73d,f0dd61e5,20cd3ceb,2d6fb0b3,39a76e5a,39114afb) -,S(f3a8c7f2,86117118,a4714895,eda7f401,dce4be87,dab4d4fe,b55068b4,c948b350,1dd2f669,31f0ec62,74e8bd53,97cb6b50,d97f9238,2603c931,8ff1c6b,18893bf0) -,S(3cc304a4,3aa02bc5,25437a89,977b8ee0,9f5f997c,56c4d317,f531d22e,4a60f55b,9ce121dc,cce749b4,78823adc,c9a613b8,aaf78f5d,c2eac8b5,d5ee6aed,592c7bae) -,S(e5be6c29,b9f12f42,1f499fb1,13e54bf4,4a577fa6,d8d0dcd9,6b509f65,1b4f3587,7755eecc,721bdd9c,c6e8c96a,d398cff3,c03e77c7,9e34dfac,1f51873b,8771d40) -,S(f933bc46,f296b780,4284de6d,5bbeed68,bae90bdc,cd731cb,b9519c05,278c7fda,b6ec0484,faa4c53a,630a8b81,e1d567dd,543a4e55,4e89ba69,d72646c5,7ab3740) -,S(e1d21ebc,297edcc2,b595976b,2f65b2a7,a6797cfa,3e5abd27,34e2a962,dd2f507e,aa31ee8f,4c80a0fb,9e52f32,c7e4a69d,fbe8d297,8dba479e,b0c9f4d0,350012fc) -,S(c3cf0aa1,8e45aa16,343c52ac,41b12278,f9899b46,e17ef9d,d7b67f75,84a1eb72,174cf510,70418a6e,f83b3db4,97102ca9,5bd99985,f2554e5f,c32cdefb,ba47e411) -,S(e6a90aff,6e1f0311,34f93967,538040e4,92120644,8e8e2106,dbba6f5c,701700f8,93895ef2,1d3513e1,19228b95,86289c26,f3efc024,1ac2c963,b394cb87,265638c8) -,S(e2b695fc,8f1856c6,131761e0,9f75a558,94a4a7a9,2837dd29,f8e8a474,7a9b9a91,b580a2e4,240724d,5c5381df,27a17d72,4d0e638d,958c0a27,fcbba34d,da5361d5) -,S(c0660a14,6db599e2,15f813a9,f267d6db,4542a696,9b08334c,6bc80558,ae518063,6a901346,6bee774a,54ec2f97,47d7a8d1,e157a13,fcde8cfc,57e48d84,374f6ee6) -,S(5c41cced,2b091fa7,df1f8e30,3d78b117,842511eb,41717b59,f776e05e,39daacb5,dc4964e4,d91fc985,af5c0f87,f0026a6e,290bb1c0,b181fe2e,195f7001,52509f40) -,S(6abe8574,49cbaffd,d0e5fdf6,450484b5,f8636170,5c8a0a59,a3612dc0,8d0d52a1,c669b059,3a5fadf6,86b9583e,7fecc9f2,c5eae967,9eb5be36,a2018337,64703bdb) -,S(560dc0ec,2d407e81,4b5034cb,8d26c8bc,7c86487c,f74e2fb9,a076b521,f68e22de,faa241bb,ee929015,b4183152,5aff5062,3a270bfd,6026d94e,c3106e3a,e66783da) -,S(f3ef40ed,8d82c02,a141b953,e8593f06,b74b244a,b85edb18,eda3e693,3c8f90a3,aeaa6d25,6db6b12c,d9a6ab5b,d6d0d854,62c0d298,5a772648,db46b614,3050d4a7) -,S(413e0fff,df030385,248b1fe2,1bebedfa,77c1cb86,d665790b,21914da4,58a4479d,6fa9db70,80ab1736,ee7d54dc,e5d1b545,dd17e3f4,45b39038,595fe180,2b34b443) -,S(ed3c5ee2,cf1cc502,37e5c654,d903083c,6fce29e,cda0f427,5a6e1ac,940b8183,fd265e79,3474e60,109cac37,a867bb81,d8ba8b8f,94b13f08,c409ad5,362492c2) -,S(b98e14a2,3f5e5d6a,a99ef39f,18e234d4,42102e72,2e330d2e,e654b328,e2f3bf49,67a60b41,8e820ef9,72ffa57b,1e383b1,35585920,20434df0,e443c318,89734499) -,S(31bb6293,28793b42,dbafdc9e,6a418c51,f0a0cf0b,6da96879,11a6f046,c146e475,1bdb131c,b14a3d85,a532f889,89112231,341a546e,c88e8a25,8bfa341a,7826512) -,S(79b2d26f,f257ac80,ca67a639,9be17ff1,8ea0c10d,739b106a,a9310754,6ba0b252,e09448ea,b102b1cd,654b6e1e,7e4754e1,c63d11c2,46b0ec5d,31df6175,6b99e850) -,S(ab8cbf8b,c3a740d3,c1bfc2e6,efbd7ac,f444795,cf2e311d,edfd5c2d,124d55da,70599847,895f335,a8bd33f1,811201b9,a860555e,8cde2a27,4c348b4c,6ab449a5) -,S(f6b7c2ba,c5468fb1,cfa0785b,f67972b5,36367ef4,d3dc9ef9,25e88085,524e6021,663be56d,c325b2e2,3753bf15,1f6b2ea0,2d6a62b3,a3d5f565,2734401c,9c661a3b) -,S(f5d2e04d,229d784,d7af5af3,ea65a35d,637b404b,c431ca72,1bec7fa4,dee33377,16c90231,e570a434,700fd8e7,cae5f8d,fbfda2e0,e234ef23,a2e82452,a0a953e9) -,S(4df218c9,4277fac3,3ca43921,e29fba57,6f183e74,fa2ea781,88b8245d,eddab853,7828e929,6c589e6b,1d80b036,2c9bb0c9,2c2a79aa,378c597e,8a64b985,d6e4d108) -,S(60e1cbc2,78d4a0bc,b7973b32,964da674,9e2b3448,24075a0d,1db93e51,ee3414c1,cec0aaa2,3db6c3e,6d6c3189,c2dca9de,8ce91791,a721ecbc,1f09c7ad,468ee8c5) -,S(1e7a9c4d,a6cf3251,559d58eb,bafd1a7f,ee686c72,8b1ad271,d9da3b15,6a9f3737,794e3bbb,cdc0df3e,b9669a10,8a32d7b7,f3fb843,388cc55e,aa893f64,ce1b960e) -,S(e8984316,5ee703c2,a413c7,2a5c8ea0,605c0b4b,58cb844c,85df83c3,b4f361b0,69fd6f89,5cac1716,f0bacdd,5a880f12,f964c2cf,1cd402ee,27ccdbcb,5188b64d) -,S(2b95eaae,6078c535,32a23225,eb9821e,c7bf864b,75187df3,2736459,f0797e4e,aa6e1922,b5102e69,77fc23b5,ac2de98c,edcbcc37,54c928b1,7c7d124d,980666fa) -,S(403c1933,59ac9027,7aed0f41,f9ebc507,8ae553a6,ec3b8a4e,4f66a841,19d221a0,edab5156,8667e7b2,c7793e17,839e46e7,85a6c7a0,8af7295,8e25b411,13829ead) -,S(fb182399,c535de2d,556ecded,54e42f29,8c0054a6,1dea2477,9df1c7c3,bb53e1b5,7bed179b,73268027,4fa6b227,d13763d8,4fa62dec,2e351ac2,d3aa59d8,8961123e) -,S(9375a9d3,ecfff9b4,b672d90,45aa4872,f61c3b8e,4cf86a38,7daf74cd,affaa521,41c7bd13,f4e491db,77a42bb8,d65ba77d,f03acc6c,cd789759,37486d08,c3f691d4) -,S(abb9554e,1b68c554,81d8bb12,5b426a4c,433cb110,79254f8a,ddebabd2,9f5be0c7,946d680c,1bee958d,32089353,41ceb7ee,5b4a8168,a6368a92,e1ab1050,5d0e76d4) -,S(56e8aa51,37b38531,1e5e1097,4df857ea,b4f7e53d,11102021,6463c212,ebcb873d,b51e1981,7eee5672,afe7f688,92ada73,abe703ac,4e19770c,97dac300,8d3b1632) -,S(ac487fb0,4b00962b,2b098cfc,4f22eb28,e5007944,d32a136e,5988dd47,d9828f5,bd305529,5f4200e4,c5e6238d,76665bc7,67ad8402,dad13d8,6c6fb316,a214a5c) -,S(1dd7562a,ce273114,660ccde4,5f41d690,11621bce,56cc49c7,2016f19f,d94e9e9f,a8e8861b,ef664d9a,c19391b6,5bb97715,ef677199,a373f255,876aa9ad,d8a93043) -,S(c198019,cda66df3,2bd528db,e3869d6,1d1d7cae,57ced846,eebcf1e2,bcceb8c3,b0a9c52,ae2b2625,7699d3b1,861474,4d66f09f,8b795d81,acd3e5de,902b247a) -,S(950f54ab,3cb421f6,95404b53,9b1f4936,6b43e61c,7bf9879d,168027bd,f58dc386,e14586c,7f005f5f,21e122bb,2a35194,d5d2fcfa,4898c279,cc296b24,9b48b2a0) -,S(5b20af8a,31b69820,a56d0df0,c7374c8a,37805449,81e0c017,83b4ff49,2bd40ed9,7e49b8a1,c5bbcb32,55991da7,99613598,cfab9d8a,82f731d0,dc2f52a1,6ec39c55) -,S(eb8a10cf,3777670f,437f55c0,2ddd8681,63da41ff,5b534c63,ffb23ac9,ecaed755,99c18d8d,df2ba9a0,d46ea92d,8b983f50,c16f14b9,86b955e,a577f332,10533df2) -,S(12977f3f,d75a9c72,81358c91,73664b40,8d8ccc98,45153ede,c62b189d,8da2b176,f24f505a,75761c5d,939ad836,17f0c6,dfd8a2f3,fea04721,9078e2b2,1aa317df) -,S(7a591539,ff4fc3ce,2e2936d3,50d753fb,131ba419,8d034c65,e76d0744,c159096f,c95d8b25,52b3920a,6341ef43,5e3e797a,446565e0,652a562,7e0674c7,ca243425) -,S(993061ac,819fde52,ae500ed7,3277ecb,fd08930f,8adff61d,f5f9c3c6,cca49640,d54444ce,748f6058,10051838,52f0073a,8a5d1477,f14111d8,b623a316,a67ad06a) -,S(cf807c40,c5664fbd,910a31bd,ed3cb7e5,2e54d1ff,ffcb4b43,7a579931,6f803051,a5d21e6,6fa9b5a8,2882b77b,ca66b6e4,163d579a,d245d089,602274f4,55ca9881) -,S(9c0119ba,461d003e,c6fb7a01,2bb32b89,ec819d97,8fd4cfec,ca1c3b2f,1f14f0bd,b41c5fa,ce1e9a54,f1605e84,61b5e6ce,c11590c0,15838059,2c511360,f4b537c4) -,S(56ea3259,5d97b7f,d7f9fe51,b525d73d,3d77d483,f8bf8460,8d874d25,aed3da3c,f764a40,2cc9278a,f1ae6369,e1723bf5,f0a15a47,992f8fe0,ae33752e,473c3058) -,S(2851e3cc,2fa6752b,e0a65326,46aa8445,71736e1,d22a01fa,ab3becd6,50460acd,ad778ace,631584df,da4730a4,20242779,81f9f829,cb18b20f,8ce727b,d62d64b7) -,S(1674559a,528fe0ad,5aef46f4,eeb4e0ba,34b8c2e8,c23d3409,5ec1e164,ef351979,afaef98e,ee2ada75,7be9675f,fee76686,d2350972,a9d1b80d,fbbc0719,efc38b21) -,S(ede70ea,37946f71,848d72fc,7a98102b,f9c167f3,219671ab,1843b5c6,8ba6d7c0,920d6108,6929e5b8,30c4fa,eb155b4c,9d324001,59d748c9,d7e74980,d54be37b) -,S(fd3b1f22,c5037c8e,93f4f9ac,27ea723b,3d3e861e,694ef349,dfe51f83,50ac9fa5,cc02effd,6df18244,fcbd177,a624ff17,b0da8fec,fd60624a,3d066be0,9c466cdd) -,S(72f037df,352a4619,729bc550,e23ad7bb,6f2d7977,7d39ae36,bbc1d45d,d6e864c2,c4bfcde1,2a5cbba3,7e047070,5937c2c9,da702040,bf49cb5,c762d60c,e8fca76b) -,S(f17a9b25,601ec8ef,e320558f,ca832789,d0d8d558,76ff7c53,6af0f84b,ca799a61,c90583c6,2a863567,b0d8c41,e47c3d8e,7e196a1,9269a409,31a1eab8,f1402837) -,S(ea9fdf49,9e201fbb,b0a26a71,1b9be2e,dd17b2d2,b96390c,4aa2dd00,83bf5c86,64322654,c8bb2a83,ab0cb743,eb907234,d8503fe7,381e17be,c17bad5c,d33b4df1) -,S(8d5d6f0a,24aa6e3e,7dff42b9,ab8b22aa,656788b1,1e18ca35,b4ca6f19,1d50de6f,d509a2b5,e9800d5e,a7d1d047,e945e693,2e5c1923,59bb0210,1b2e8956,33e0257e) -,S(25ebcc4e,84a1d22c,f0a8c980,8252d96,7dfd528a,808ea293,ffcae94,50e1fb81,3127af8e,4012c2b5,c92e428,2e455de1,681eb1b2,6e660fcb,4ee8fef,b64c6101) -,S(c55c17a1,dcd8fa41,8a3edb5e,c2da8678,4fed0840,522b24ed,4bcb85c8,cc45c20,7d583091,25261489,44b56fed,17b07906,9d156fa2,e9bdc462,eeddeebe,68f4f463) -,S(f4297f59,21a867ba,1e58b9e1,def633f1,18e058d5,a7889721,f0e4814b,7e63ecce,a39f359e,35a123eb,5fb66d81,f117858f,b0557859,aa2c388,a8298d11,43f137a9) -,S(626b0a,cbcf0e7,daf7d218,74f72be4,8d824883,4428bfee,f82ea516,c2d1b98d,74ae6867,1c27a642,53a36590,5247cbeb,77173b07,2e429de2,3ce09730,8d54ddc4) -,S(8ed35ae3,c02c5db2,acb516f3,2d3b6823,61964f2e,701889ab,26dc9512,ed40172c,aef4c71c,e241be56,63a091d9,e230463d,237e0717,78b7b6ba,a63688c7,6c694334) -,S(5b082ab8,963510de,46c1cc49,4ac6d3c6,dfa25f33,8627a00b,6b98121c,73899ed,cd8b2b84,185718a1,c4686ff0,7cad18ec,fe3d4532,9537910d,31458086,c280bb32) -,S(deaf505d,b08a282,d5274de6,43c5719d,f51827e6,2ed035f1,74279276,7ddc1158,c1067344,5e4c0d47,ad1ca85d,713a5916,1aef6960,9294d738,103b945a,e99ed1c4) -,S(eb62dcb4,d820019c,e865129a,28b98b5,be6c6e16,a80f7c76,db3a15ee,31ba7aea,e78eec22,be4a175d,68b2257f,c5adbe46,fbe31c3d,5eed4736,2304d80,ae4577a7) -,S(6c58cb64,7ef638c2,337cfedc,a9345837,597ac142,577b2230,7d231a3e,5a9173cf,563008a5,7b823427,60bbc400,5f604024,92f0bcf0,2ab2430a,5d7accc5,b62cbcd0) -,S(106d8978,775a41b1,12f07815,7c3bc5db,bb5980d9,c745806a,b5ca5ede,8b468d51,bf960349,6f7d7906,141bc4fd,b1766102,e8dfc49f,decb469f,75dbc54f,21338dab) -,S(cd6124f4,21796b6f,44c34982,8b536ef7,44bf30ec,6ca08142,e959a35e,c0385224,97ccdb9f,2896e815,19bbe9e8,ae491e61,e83417c6,6db8b6a9,bede3aca,f6608ea1) -,S(2918b2d9,b0bd83d0,b8d02815,59219c6,bd708e2f,2139ad0,1815b1ff,ae60e03c,f322596e,c56984f2,e7b2ee90,8a9bb56a,d213f84f,3088aefa,67e372f2,76e2a233) -,S(6d3fe999,acc04d13,2462f14d,680a90c9,89b747f2,3601d779,507c36ce,8c2acc7d,a6c7413c,36b6399e,58a443b4,e4137ea5,551a9fb2,c5397457,9d55b48a,5df0e30b) -,S(bd74ac79,8b320aaa,e3e51123,9354d4e9,280c99c2,809e88be,13980305,62d55d52,73477881,9b9067a0,78b40108,38ae59f4,3f6ef064,ba35209c,46a9f0dc,aaf84597) -,S(303f6cbe,866b4574,9d282217,1f571fb7,8c54dbfe,901f2f43,681ebb0c,76e5700d,b13dea58,d3dfe08,7fd043f5,8e63e565,85230d6c,273d9e3b,22145e39,afd6ea4a) -,S(3bbb0824,16a2e3bd,e328f013,154f18c1,4e840030,707057cc,f4fa0fae,ff56181a,18b214c7,823b0cb1,76375146,7a49bb8c,ddc0047f,782e3802,be12a119,ecf0f480) -,S(ef42fcbc,999a3f80,b4e7319b,1fafc2c6,49f51845,2e423c55,f57e5e1e,f8338adf,786ffec5,60464882,48641155,38aac187,ced4678a,cee2b9ea,eab6ae61,ab2061e2) -,S(afb21e4e,c095bf31,34276f4e,f1a4883a,6038c20b,a7a87ba6,6288bb1a,3bc6f77d,cda832eb,73dc0e9,fb77315f,6cc7a313,2212c7b4,1075a290,d5917033,62363bad) -,S(329c98f5,a40b81bd,7d121b90,78b50bdf,bc16c9bc,47744368,34a5208f,20d39d63,dc14f7d8,4bd2a1e7,22fdab98,1044d6e5,98515df1,7da5536c,7a95866d,8231a) -,S(6929a4df,e15e7ac8,e8a9c5a9,3544af51,aa621dc7,ca04038a,9c9cf603,8e081754,e1333f46,e4d1f151,f2b8c341,d2ff90cf,d36cf73c,6f441b4c,5c0ae272,6a25fbf3) -,S(f40fbdb4,27d2d68e,854cbae0,24ea5980,5948ca40,e3fdfcc3,3efea0a4,57e2bc24,33493d84,41c8945a,9e291b58,5e12789,34990a7f,5fec49db,ea1ff605,4bf8802f) -,S(220417f3,d9fb32c0,1439e473,d638856,9b169c38,1057b780,c9de7d12,e30dd796,4cd93672,5abc4e39,89e64ed1,af9b3d4b,4732ac76,a6c34d6b,23274573,8d765a1a) -,S(dcbe3dcf,2c0120d9,4d6336ae,6158bdf2,859cdb03,8c76ea3c,cad4ed11,13ed216,670823d9,73c74725,ce929318,c2ea650d,5feb7c33,c7831a26,821f2614,7db7d8ee) -,S(34de2319,c535a31a,87fd9b70,33c363e2,8ff754a7,9e0669a6,37230443,228ab3b8,31c65b12,cf6f4a9d,662238b0,c8ab52af,ceb96acc,35b90b2b,81667b8b,dfd9895) -,S(f0fb2bde,a5626729,720ff432,542c5e41,abf0fbc4,772aca7a,75b882ab,2b364acd,114edca0,74520c9e,2f5b8059,59c5273f,25d2e621,d2f55709,b42d187c,932b6bb8) -,S(90477ee6,a00742ef,78662c11,f3725077,dbda7b66,7ba55b55,f9bfea1a,4c5f88f4,467196ec,638d137,33971505,f291dc0b,b9d0f3f8,f284e3ab,9035273e,d9c7279) -,S(ecdef6b7,455a41ff,96cf943d,e489858c,b7abc526,e41d463e,b24a56f9,dd6eeada,1116e7da,9fe72782,e8c656b,9f677c5b,dfb3e46c,98957c30,49efd7b6,dd5d3258) -,S(58d30bd1,d8dbf5d9,885b6e7e,4f28ceb8,381415eb,3851a031,ef04b073,65e16598,9cb96ab0,546246fb,f5cc0878,7b99db0b,26c9bdac,184a0eba,728fbd26,bc880480) -,S(a7587d1b,771b3421,f56e342a,cca98e7d,82c7dc60,765a481,53379da6,fd341c10,9499ba9d,8351d194,213ba35,43d4b563,aa28bba0,9a6d8811,9b55f389,90742929) -,S(8aa99d89,9db3c7e1,c28bfc5e,18abdfbf,d9fff46c,560e4fc0,cff65ce,e18ae6b0,aacbc2e2,bcc4ae58,1e354d29,617afee6,20ced0ff,859c62b6,669cf2e0,565a9bef) -,S(45d81a7a,b4158aa4,2e45fe7f,3966d278,75f8647b,defa0c8d,a761ebef,894ef249,93a76905,d0e785f2,db52e09f,573a461f,183f672f,9f10005a,eeed6e0c,d40d31bb) -,S(de19bc8,6fddeed9,909eff4,80b0760b,66a1a245,82e33be4,55b8061b,225942f9,6eb2c1f6,f604056a,15c4e91f,789e35b6,1a787abe,aded0f30,abd2525f,19486d00) -,S(653f0e92,977b7830,fa546dec,44f05549,80f5a9f6,61f2cecb,7e360efc,41d16380,58ba9f7a,eb7aed3,40b54d7a,6f9ad0aa,ab5eaa2a,7715d8ec,48d52ce3,c3c57128) -,S(c05441fe,2ddce6b6,64270b69,83d44d5c,251efcb8,2bce4665,9388eb3d,537acce,cc82b7bd,3a049b06,98feacc8,11a1c9fa,e95181d2,50c0c62a,55a6d662,c9587d65) -,S(7a569bc6,a089fbd,294dd5d0,b10f3a7a,31b6bf39,42ee97d0,49c9259f,7adf0a7c,2399d17a,f6207b8f,20286fc4,78896af4,5e596b09,7c97f662,9bff0c03,14db53e5) -,S(1c4c7a37,4e14ce88,fd08a1b3,10025711,7d96878a,e173d29e,1ac53a57,1d6ae794,919f9b82,e827cc78,7352f0ab,99770e97,bfe1b600,40cf1034,b7c5178b,3d1104fe) -,S(fd4ef218,a09baf70,57b53f65,2ca1e2e5,8386e867,521dc998,1bd4ffdc,619c31c1,b1d2e716,64fec6d9,3cc8bf17,70ab5f10,a49a0497,ac1586b7,b8299f7a,e92354ce) -,S(f012612c,1f933373,ac30413c,1b2cfb9b,6582957e,b74e4de5,29c0267a,e7552a41,a38b2418,e7ace7bf,3a15035b,a68f82b5,aae49192,5783066e,f0f0263d,6dbc86fa) -,S(8e0d504b,c9598eac,c4bd2726,8b3ad24c,a22b7534,32eb5a31,d7e54948,d57f6f4b,50f59455,ba1ea3a,5a0cc105,a1c40c4b,72637a31,44bf9438,a1e3b52e,7b30911c) -,S(8635604b,89ec22bb,b3b4e266,3e76cb3a,976cc78e,c7db31fa,fc16a7ab,411ed197,8a11d457,6868d117,4f41c40d,4c82d27e,3960d57d,4b1309a4,531c2617,b1d90227) -,S(aba7addf,c234513b,3e861382,654959c9,984628df,72b2a896,6459b3c4,86bdbd2b,ddec8263,bfdb4c38,c9e7fd,e4693b0d,962c6e5f,a4f9eb9b,9561e81a,f04a3a3c) -,S(12aa3b40,44f699c4,8ff6c598,8a7ce56,84f3af85,8cf2ebd3,4d59ca7f,f7501895,76397e3f,3c42935b,6a42222a,525c2166,7662ea00,25decbf7,8a856391,a03956db) -,S(e01136bd,da38f328,af447a50,43a48606,a1ab5a86,b3bca98,b13a53aa,c7061098,76f3fc47,c1aedcc,bf26ec5c,4f6ad56c,fa163212,65844d01,8d2f2b94,184b64df) -,S(639cb266,f0672340,d0a789a9,41eec287,b60c380e,f2f62f96,41b67137,4b286aa6,d381e7bd,5dffffd9,50645e56,63c36d91,83210038,d70df2ca,4bbb837,e8eff508) -,S(eb12f18c,89a6d2e6,5e07d20f,f7acf3c4,b903ce68,5237aca4,5692c0e0,f6a4714e,d26860ab,e6f97745,dfb01cf,f6225c36,bf62e5dd,24088d54,a6d44384,e9eed86a) -,S(8fd06b6d,96f37c6f,8e69187c,c5ace64a,6e36b45e,37de82b4,872731cc,8781e941,e7dc3254,3b40599e,852d4e9b,e35a5438,ff68b063,3b81c8ff,c2f3298e,931e9e98) -,S(d248d914,4ca3f10b,3fb66763,713492ac,93b42781,9119683f,bf0e0f08,1bb6b241,e7a2ca15,f1867e9a,d19ffdc3,f1a20d0f,2469fa6a,e04f94be,a289d019,c405318c) -,S(ba2150dc,15884df0,34a64e20,89023947,687d1322,475dd073,b163a4bf,4eaf0740,af92a566,a320a0a4,34095dc6,f02f765f,4ebdf04e,d81e2c04,a86e6e2e,923f8c94) -,S(fb12f487,225a6843,31e39309,3133f377,a6f841a7,f6f90ccb,18ce3d39,48b56616,e3358a9,406905b7,d6bc0a33,6a89a5ba,e62136a5,4135c3db,bb32f115,4cf92b9b) -,S(bdeb3e38,7c36bb9f,c45a1d62,f7128217,20e6d0a6,55a285dc,da87af3f,f59e0644,b23fb389,3cdb280a,43275691,3c1de5fa,6da12909,c0ebece7,12c9da49,69a3cb29) -,S(32f3ecc5,925ccc13,f753ddc7,d5c0c576,e80402ab,ffc6dc77,6e8bf74d,15735007,f950add3,926bebef,9d8e3a5e,4d0ebbef,24b54dfa,ae7c12d1,32b6e973,dc67c050) -,S(94a725ed,e57e5162,817d95b0,54e2732a,3afe3a6,52ae3e46,ca9de38f,6dd9f0fd,805f6634,f8ba79b8,ecd5f46f,74b741a4,de5f9678,d29b8cba,eec73498,27671f67) -,S(22197e54,d35357fc,ad20f6cc,986216e7,f24e6dc,cfd9bb89,3e5c1ee6,9a99b3a4,b3e7edac,abb1d1c3,d375f361,1f04a927,9d2995c9,3e18e7fc,4b5dca90,a2a3fe17) -,S(a51664bc,5a1edd2a,ee8ea644,7beef61b,419e20ad,ac955847,5e1d666b,1b4dd52d,b8a95fad,e3aeac7,bcd8670c,78dd1b2b,5dcad225,277ca5bd,f24f131d,94405c39) -,S(896a11cf,f9db64a1,aef51088,baec42d0,16dd5a99,98262f71,a005cdc8,ae8cab78,7a7263ea,f64962db,bd09a278,a3958708,e61c4858,1a759726,c225471b,20899077) -,S(fff75552,46da269a,2124d03c,677f59a2,18b995aa,e69c85d4,3b29f81e,5201a757,dbbf1558,6670c191,9da69467,6e8906f3,80eb3f61,34c656b2,a4ccfc71,4b3223f5) -,S(89da8ea8,56f946d6,6e9b07f3,db5b2ca7,49a07e5f,78b59c1b,e52e46b1,3793e198,25889e02,d2013d86,6653cad2,7b3504d1,4e547343,fec74a37,a3ee71a9,646a36b3) -,S(d260dbae,6ac3e8a1,442ca7b9,8f7118c5,7d6cef72,783c0b3b,a4ad7e7c,3a8836fc,e00ee7fc,95131cd3,3a446bf4,c21b85cc,45a8e61d,2d9d6cf0,287996e2,77b7cb6b) -,S(bacf90ec,75ff002b,c1a259f0,3c9debe5,9f5f9dd5,cc0cbff9,e8fd62c,4552a619,82dedfc1,42202786,a7a12a29,22937c0c,23bddd23,4418979e,78723ff2,6a9e5e88) -,S(1ec23fa,995a22ef,53a91dec,a5b2faa9,514b5ef8,faf125ad,da61f84c,5b13a397,1568ab1c,cf75692c,b7d41c53,2dd4427b,ed7043e6,cdfe01a6,2f9bcb47,cb97435d) -,S(48225de5,eb07155b,dd86e759,9e172a3b,b96f69bc,ddcdb051,af2dc769,f4450b1b,856ce939,b81d976c,6a6c249e,c0d087cb,36e28082,ba050de5,4948d92c,6693f4aa) -,S(e9ac9963,16c1ff8e,a7d2bbf4,148c8b3b,a869d4e1,290168f,b3831d6b,3bbd164f,2b1ac664,6bc87e3a,e6914792,d0bda8b8,5cfe1107,3d0447ef,e4a65acc,6eac846d) -,S(8af31ba2,af0b68c9,4290bdf4,b4b80345,5f52ee89,f4ddbc98,1dda1000,9c1a2ec2,a37cbc1,a5efc09c,dc944f42,a66a305a,b302eb17,21ce5088,a7deb46b,5223f0b6) -,S(1d211de7,d75d4389,4cdac235,9b0b9e40,6b71b8a9,8c0583a5,7d7a0056,b3e88779,3ae4bfde,20f83eae,96982e96,62d65443,4359b2bb,df249a85,c7c83b95,56d7679f) -,S(be6beeec,18aa8d77,20100975,3dc7d745,c6d49f9b,ea64ebfe,b8fdafc0,92a192ac,c9e14aa2,4bce41e0,f444030f,ddbf035d,e808bc06,63a70593,454ba287,4ebe50cf) -,S(b126dd86,555491a8,e2ab601b,2f133960,d86a7f9e,bcd2c88a,cbd8764f,1afee3b2,d22ae79f,fbc60439,baaf2c2e,418edb77,70837ebc,a909322d,b5580c30,27c20821) -,S(857b9c62,6350cec4,f928d456,7d30cad8,6f1cfad,142b338d,74a137ec,61212791,9d3dc070,f610ee55,cfb9cfaa,4bffda56,52f7fd18,7f354634,ed4f2dc,d27f9ca9) -,S(bbb7d30,3e242e87,2e94e3b4,27197ebe,5252c363,43ccd8ca,940202ff,fe5775ac,f2b5b210,a40d1fe,140f8638,3a5b0f9c,96885d5,d9857a3d,252523b8,d59d33f5) -,S(3e90a10c,a61bd12a,fe9caabd,e52dafbe,8bcd332c,e0ff8bd,7718b685,89e26447,3a4d342d,fec7d557,7cc52bf9,d7c60537,50150146,8a05baae,7b562dbe,b626a952) -,S(dc1f2531,d5e0d304,66b963fd,7d09524f,c66e6bbb,3855b6d3,141db170,9af05fa4,f1644b11,e8291f92,4884d3ea,cf89d857,fc98c3fc,e49fef96,7986e8e9,d67c9b0e) -,S(2b4714d1,fd0aa7ab,6c103ae9,19493efe,4a503d5f,beba56dd,93a8c9db,485c1dad,d65bb3c,47efcc3f,7484b6c0,9f51605,30542a81,d1192ac7,5d506c43,16f41220) -,S(c9ffd7fa,3b14fce7,c2946111,e940ab3c,8199b7e5,40bface2,5d8e3b0d,d1a15176,3b40f328,a4539bd0,a0b71e5d,91a881c8,87b31e11,453d9f5,82066f44,ead8d5a5) -,S(e019b0e7,6b4221c0,e45d387c,6ee41bdd,ed5e219e,a7069b73,d92b6339,2657c39e,792691b8,4c8748a,cf10475a,955aaf5a,77328c6,f03c2e9,bd1b20be,f363f368) -,S(51e07e1f,e8dc56df,f6394d1d,7f2887a6,9e7959bc,ca10af77,cd54064e,6268929d,c09b86d6,6837e473,574bdf95,f0b99851,b97a821f,6dc622d0,d9c6cfbf,18db5ceb) -,S(c5c19c69,9a9b6908,4625d3b9,5c6598cc,d1bba7a0,6d4e2f91,88f1b77b,4aab720c,af066357,107d856a,51c699a0,259774b3,352f8c12,988201c3,c71bfe3,c5d8280c) -,S(7b51ad32,ec4a6df5,f9c952e1,fcabd8dc,7661ec53,2631331e,5205d231,533f8d77,e1346672,ebbb97d8,569a12ae,fea65246,e1902f0a,9cd91894,a4b8aaad,5a02ad35) -,S(be3059dc,3789e16f,5ca8f6e2,c469f834,bcd3fa73,5d84377f,907cadf9,e7eb895a,5a6fa277,ee5d317e,81819fb1,11f40778,ab437567,48eed726,238ab5c7,f4d6ef06) -,S(cf75a66e,810f3284,52e09fa3,15451289,e1cba33a,ff1013e,4702ff1b,92b6f587,a0658bc5,8c894702,ec5c366c,5a6b18fd,86269d5a,8117dee3,601dc40f,cc93f17b) -,S(6356c70,7d5228e5,253f09b7,7020681a,fa64dfd6,3cabd703,91d7f892,d9822737,3241ba88,cef88e8f,98d19fda,717904fc,737a9c77,45838ba3,97141964,946ac7b5) -,S(90d7f09f,7b8a1232,236b4459,b031b0ff,d5e8c903,36a35f04,94a89615,3baf8554,4a612ce4,b18b7ae0,f3c557e,c4ab51bd,7c32f26b,24d0ca7e,accc748b,3a2db676) -,S(170265f9,5a3f936f,57a39e1f,a748a3cc,902b1b20,4306c49e,f4485b15,555f80af,d2f813a4,b329da9c,68104a55,301eb7cd,3ff6dfe1,c4aab9d9,d2fb03c9,e7ae2bee) -,S(2d6316de,37598fe8,ed6e3e52,ac47d442,636a6553,64274692,5a468f08,54377eea,e064f40,7f0d3b32,74a61d82,d7b75006,6fab6447,e66f2d4b,20439303,cdb3a107) -,S(8c89678e,73f3085a,1a766e14,f566625a,cc29dda6,3eb7bc9,ed1195b8,5fa2092b,12b42d8e,91c9640,b8b2509a,157229bc,a66d28b8,157742fb,a12d7405,eec110f5) -,S(ddeb928,de6424c,f9ea76f0,abc208f1,16731596,29fdb2c5,c8e6ed28,38ab6b11,b1395663,9ac1f06d,74aef36b,61916872,7709eaff,d8b76905,ca404459,325839b6) -,S(485e8e44,35c46bd1,d0c2a4db,19b958fd,4a87511a,ad4aae65,eec4f5ba,6cbb38ee,e621d1d8,736d6df5,df2db5d2,36887c27,a93733b8,d3232dc0,95d0b2b6,d0be516a) -,S(bc527a44,2547aca1,91fd98fb,84ce7b3b,6210378c,46f7bd46,bfd375a8,1b61206f,ff7c1cfb,d3c21616,85d6f405,e6f19e8b,6785e6be,ce374189,4efc149b,b3031707) -,S(9911194a,7a75269d,2fda7214,21e4e2e,3666ad12,3e76004,b5ff9afe,9ea89ca8,b1f350ab,c87d942f,1aea75fe,6c144ea2,fc5cc040,5c38af56,9ee45413,17c7bd4) -,S(93226535,e27a96af,7953597,4db1d4d5,4a65d3e9,331fc3df,7f028fa3,288c3189,98007e66,60fc6673,5e8e864,afc62171,49168a86,27d35eea,2d02d90f,e6f15331) -,S(752d352b,2459fb97,d5a0c46c,3fef99ed,50ebfe74,ceb1c881,b2fa518f,3aa59e72,c6e99a8a,2544731e,d932a164,ca0def49,dbfe4f29,f8894133,ff5eed02,66c4fbcc) -,S(ab37b416,dd06a595,ae6fe33d,717c4ff1,fd1de2ad,6c58e2b3,660e872e,aac7aeb5,182f07fd,61ba43fd,e11ad355,d7027fef,714c9b9c,364c0b72,1838ef7c,f85d9470) -,S(d2fa3ff2,b1cd8909,52a0d380,d43233f4,1eef04da,aeac6ceb,46dd8e6e,572d170a,85f3c854,3eea0e64,b8a9eabf,18057700,6c3a6f70,a790cce6,24a3f6f9,5752c520) -,S(e256c5b7,99ae8dd7,1daf5a7f,3dd94f94,e040d98,291a2d6e,9b398889,addff0c,b4375e5c,82517974,b515ae28,54c83443,e8bf9391,cb975013,727e3bc5,1473b133) -,S(30056648,afaac00,c1d77bd7,e7b5235a,fea2bc8c,58b34a6b,83e630d2,3036db6c,16ca5c30,6882fd6e,f7d82f93,b25ad01c,eb3e9e69,b8280f0e,e3aef2e2,ec204600) -,S(8602fe69,d4b1f32b,e8422928,200c5b5,816f08a1,759faafb,29861e07,c5dccef7,59a5ca0,35490ebe,66409e2a,283f4c9d,f6e0a7c7,9dd1ec82,f31f7e4e,4f23ead0) -,S(53bb9f5,ed205516,36ab170,7afc75b5,6ab3a75a,3d360c15,3b0b74c2,d7d9d64c,77c6c1ec,c7a53dc3,8c6540d4,461757c8,b5f7b66,654fd754,fbfa8f5a,a5318cbf) -,S(badc41b2,86982d76,e5374b3,dcf023e,dbc1e187,70cd0b2e,2916d436,108a4328,b1694651,a69dfad,924fdf5d,526c25cd,e732078f,31128556,3d42ebb1,3329e2fb) -,S(15b43026,f5134b3f,1ad441c9,793b9e57,a318d455,fd6f10df,e4b0bb91,5d36600,43568550,60fb010a,6d5123e8,b446a1e7,cfddb6b4,6e4fb18f,245a4be8,f9975a1a) -,S(fcc64bd,c9df17,4d4e8e18,cad6116,a48780e2,a180f7c7,57f532da,9fdf37e7,ede37062,35eca482,b935410b,6d495f53,12b133cc,238eeb6d,e8e5f593,65601951) -,S(f394fa79,254fbdc2,7a1b31df,1f868c48,9b48b6d5,1afab542,2da5b1f5,6f3edd2,f56d3d7d,e7f8d9c5,fd45d6e2,cc2af300,fdce3293,9be5b975,9d81cead,e2000e7d) -,S(3c7c8c54,6b853a5f,97f92932,5558793a,e1debf3,3f680d5,6a79bdef,d4608d91,575771ed,f26feb38,a728354a,6c4023ce,4b019d65,3f7adfee,3c83cf58,9f2fe4a) -,S(51d61258,43b8d621,6c0880d,f04f34d,9acbb422,d8194a98,dcbf222d,cf27fc4e,2d0bbd0e,ae299afb,93980894,bfbdbdf8,6edf9509,ea408286,ef602cf0,ce3b33a2) -,S(14b17f35,ac7b5914,e08babb5,5aa37cb4,26d3bd34,f2c1e4f,45acb493,8ef51a65,a9090e25,cd8273c3,15d1ac6a,15eab027,7981f6bd,a85fb082,2b24cc88,2918fbc1) -,S(59ceb93d,d78ff6a5,f45c5fcc,7c1ecd72,43f2d8af,e4ba8a3f,fb03053a,586387dc,28f4d0e6,38ac1fc1,98aa3548,56f4f19b,479ff825,5d150f29,871630ae,f82f3777) -,S(273bc0a7,eb63a0df,eea8d7ac,b24a5200,a7086078,388db5bb,37a0a6f6,acf24656,a971405,a287160e,22909b67,357fb63d,10af5ece,f725b1ac,17c7fc73,759936f3) -,S(c9b5b690,3a45e529,3a298219,cca93e0,52a2719c,25cf2f50,c4ff7f04,5f346475,7db09fca,ff1aeae2,dad001ff,1fca6166,a607eaff,bdfc327b,9b63e2a8,e97f665d) -,S(90044bea,c8459e34,edf7c40d,2a101b45,66728d1,cf0055ee,c8ea07ab,e39307f0,19763d08,77d4a896,ca9ecbc0,56d405b,5a6ebcce,1ff6ac26,593be19f,63caf6cf) -,S(6e0898bf,bf6baaef,d085f41,da7e6b93,6b6c9a88,3728dc7,8ce7d71b,fd597b2e,4769146,91587abc,c2f21e05,4542280a,f7260a72,e822edca,1e63c089,3bea3dd9) -,S(e94563b6,e0156145,ca2ef19f,58de9727,7b806969,a249629a,4f024b99,8a023792,c8949547,a4d25901,f3980cf5,333f65f5,8e1797d8,b42ccb0b,dc550e6d,5909927f) -,S(3cd027e4,173c2799,54d06c3c,ec05c0d,161a3b73,348db0d2,8c03d097,8921ad64,f0d1a3e8,ebc3387a,ee88189e,c1fb3f6d,5e73e895,7b7372d9,32b00144,248271ba) -,S(4c96f51,2b4f0758,38335d47,db599db9,a2dfe1d1,6783960c,dedda119,693d5686,4e840262,66897288,9bd54c15,219ae871,e6426b67,afa949c5,e1226bbe,1204dfe1) -,S(8b03ca2e,458873,963ba6b,c9dcd14b,59fb1190,3f2330cb,22997bb4,19002fbd,2b29df15,c6be49d8,27981ffe,aae26930,7a461f84,8285f561,4f910508,eb865781) -,S(f4217bd2,32229dbf,39066a17,c2524838,38098362,f0891b69,275dede1,f8e64f0d,7581350a,957f480c,89246800,86c2803e,99ff5037,938e3e19,22e3f9a6,7098dd96) -,S(247274b3,d5095d63,132673ca,dbf0e418,898468d3,9a30c538,a46a2719,42846bf8,4265a1b7,7d1dbc68,956f2441,9c4d2b70,9e71f6e4,6e24e336,a978285c,22a84f11) -,S(19c25b9b,97f40ddb,23d62bd4,a298ce7d,befdf39d,327aca47,61815c0a,28d4af9a,a9b5d705,94cf4c7e,b7e947e2,101b18bd,fb9f2f20,fc3bf89d,f5a63d7f,61d3b3ce) -,S(fb69718c,baf0c5f8,e20ca98c,2fdb18f5,59df27e5,c2a064fd,ffb2785a,73bf27d6,b612c590,4e0b1c54,7beb4e07,82ad2716,84eb895a,862b59b5,cf6476b8,af52107) -,S(9fe6e793,ed1aed77,d8381352,84890e3c,f817ca60,37ee80df,6646a3ce,9c316a6b,17214a01,99370a88,41717ae5,41d35a4,96f8f041,e9b3fe88,4188f6f4,e30b0657) -,S(c7f7ab4a,394f17c8,47010e9d,f1764fae,6159b140,578f70c9,fe50703b,aaba62cc,9673f262,c875953b,90558dec,8ddd04a2,6d7d3ac1,672e3d10,c1a3c656,b0318c19) -,S(cc2e30bc,2d63d4d2,bd0f5bca,8faac99e,a6add123,82d014c1,d7bf8285,7ede2297,cb87a21c,f1efe789,fe72ca0a,b6acc5be,63e6973,2ca899e6,fb9e05e7,72d4d8ff) -,S(6fe7070d,a78205ea,1f12661b,4538d0fb,60b4bb4,9c1709c9,e53de22e,c3c25d6b,2f6b773d,492a82f7,f9609cbe,e1af3c9b,2940a12f,1e615c1a,801c02b2,19e6b8cb) -,S(1affe9da,ab5da7f7,9b331e9f,91eb7e3a,f4dad51,2317ca45,3ae13528,66013d8f,2706d2aa,d3139097,73a0febc,191c7a0a,df2ef168,c65e759d,7c034bac,49c8a92b) -,S(13566dd2,d0cdb199,20a1f9c,aa1ab581,c3ddf2ad,125c13cf,efe199d5,bc338231,b403ab04,67df46b,2efa5b8a,4cfa8bd,97399c87,12ffc55e,cae8de52,d4f6f28c) -,S(135fae69,9a969720,b1c0d899,790afa99,83074584,da3ee8dc,1e011336,dbc3636e,b4260b88,2dc79423,8cd0fbe6,5242147b,c96690da,c391e3cf,d2c53ecd,2ae9fc60) -,S(1b05d97,744364a0,5432de4a,7d840834,3ffe211f,a543bccf,71a4b210,3bb0489,d61c9d21,671b2481,a4ca0c36,7d4ea919,ae1b331f,a8aedb87,cc6b6c98,85616a9a) -,S(2877f026,83a5cb48,7014da9d,419c8b9c,920f0940,718e2d06,d7252de5,5b46a84d,849f9fb2,88d3fdee,de734aaa,3592ef01,483e02d3,62a5e0ca,2ead6c0b,42628038) -,S(8a7024ce,6348d2fd,84be71ab,b363bdb8,86ec6a2d,29d9cd83,1934270a,27370b78,8f520972,9e4e1325,363a68f4,ad53737b,688c63dd,1cec6cfc,bf9da51a,98b29c0) -,S(5ac77dfb,2309c061,8f68b320,bb6eb76e,4b0f0792,b8235fc1,ed768c57,44fabb1d,fab11baa,beafeab4,43a14a82,f8d70228,57752732,7b016b56,32b924c9,ccbb1db6) -,S(aee4edc,93413d53,45e0df68,99fc2193,be318a8b,f279f0e0,56c0ac42,a60759d2,b6a87499,1dc68ba8,503beb0b,8a6c09df,cb9efb6b,a44aed6a,3cd7befb,506119b9) -,S(b51d3e77,741d0d44,3a67b5d5,67b45aac,2008c25b,5196c71d,c9f910e7,b76dd2d1,431c7ea3,cf4f577f,950d22e2,74b7cfdf,2c2934af,ad0215f9,459a802d,ddee4c21) -,S(803a2ff,c59c2a94,65d8935d,93d47653,86e5beb9,c8e702a,12d7b565,98a09841,d5e02ccc,5d8ccf6e,29a7fb76,5a257dc9,c902c900,a4fe16d1,53e9187e,290efbeb) -,S(22c17725,44eef514,5636a398,23e874df,8c58bc6b,6935598a,440ae9aa,5b738075,a67f431c,688d4426,c519be32,9b1dd50e,2c64648,4d3612f,35d52089,c98dbcfd) -,S(ed67feaa,5aab50a9,ff71c434,855bafb0,5191f036,c691c8c5,563395,d2053b86,b2d13cb6,4ea821df,f8829ee1,57cb5fca,81dcce75,d091719c,73cc7785,c443f0a8) -,S(f8cc5ae2,3b670b9,3c27ab8c,7d8055c8,4654b427,f9e6b733,b083fecc,c7c5d375,7dc996,7bc3a2f2,f516aab3,682f8d6a,32b84173,ecc742d5,c8a15c5c,72eb261b) -,S(838891a1,fa46e300,a20fa3d0,cba3fe09,3326ffd7,bcdd7c73,b6e96da,5d591332,d46717e2,c5fa3d52,a268aa9e,a85922e4,547ea986,3a37b1ae,b77d75b0,d48a8fea) -,S(92caeb7f,400d043,6d36656c,8ffd5d45,6097cb51,cf512c00,1fe613e,8dcd5544,2096bc03,dfd088ca,25cb9aef,29b24b99,2b2aa00b,e3429cad,c0976a3f,162e47e2) -,S(2e6226d,574b687c,20dcd4a9,683697f8,afce56a3,1e11cdef,6f0ba6f0,dceb89b4,d9c4d7a7,a7aa5f8b,f30f0930,d6c3bbdd,b1963b1d,8cf24796,141bddb1,ba8ffcf7) -,S(33aab3f4,17d936de,b8c1f07a,9fd5024f,802fa5b3,a593a6b0,9fd42871,75f4ee7d,4c13dc95,7311dfaf,932eb4cc,68c82550,3b185530,13008dc6,878dd092,50edca9c) -,S(ed74a882,a947da53,fd62a242,b67dcd04,50896a43,e9882c84,ada77f47,691e5fc4,454a18f,a8fc6d8d,e673410b,213875ee,35190221,9f7cf88e,f363be08,571030d8) -,S(b5d3f084,56db930a,7d8b4728,2caaf807,be7bca65,bddf9738,67a56224,39723ebd,a89e0271,28d5872a,f4d6b4d7,c5a7efa3,b0339a32,89a12918,2077c106,b61e1a4a) -,S(5e40e90c,1a01e008,d5fde186,283919ef,eb859921,c3ec07ca,e34eedc2,b0f07967,e4be6ef4,26eb3c94,70ee3084,f431c68d,82b2df48,5286082,82cc1b2,afe77900) -,S(2f4b14a2,674a743a,4aefd302,7fb214f1,a7678336,3c9e7c8f,8ebee72d,c5f29830,11b13461,b6578710,677bc733,3d28e773,c78dec4b,27ca1aac,a17121b0,de9868e6) -,S(71909162,35890bbe,6a8f7a99,5b1cc3c,a68b3ff9,7551d09,59a97835,5b7167c7,f9aa3992,124fa99f,167f1351,865a1456,8ed9eb92,c7cb2050,5082d228,4b1532de) -,S(8df50d7d,d3cf99c7,b0269ae5,e70546dd,bed3f05e,260bd834,575d56e,e65f7f0,835405bf,3c84c4ba,5e253fef,f306bd1c,c1240ef,8c03da98,d7c092db,3a2606ca) -,S(5e0f6a7c,e9bc1e0b,852841ad,52045b02,b4fd545b,f2106c82,17a76bcb,441173ee,ad70f065,4d75c88f,e6654d56,fe65c57b,857d91e8,ad6abff,148f3577,7afa2aa7) -,S(27880a25,21a78fca,cddd0b78,5a3da1f4,2e832641,8f804a2a,42fe3c0e,f69b43b7,ac9f930,12402aad,c55c12bd,e450700,b0208d85,a6784586,d04f1c93,6df8624a) -,S(6578c4a0,dc25e068,97482b12,3f38cef3,39cfd6b2,ec06c89f,6da11449,de5e43a5,8a249d9a,41e6c1a5,a776ddfd,ea93ba78,15f2e908,b8b854c2,3a7e3ff2,cb99bf70) -,S(c66e890a,71beeba3,301bbbef,2bcf4cdd,def8e634,dcf476f4,6907a280,df3dd33e,f3510cb8,9c46f493,c4a70976,34a9c502,11532929,ddc883ab,d43bd360,1b028dff) -,S(393f0dcd,24b47380,81197794,58bf5e48,b2f5479c,8efd8925,a1f78bef,6bd16665,9898d880,e24f840f,f1b4662d,3d444c29,6527cfe8,2b6f1b4f,f0e5928c,bf09de74) -,S(337fc469,43942ce4,f1601877,874366fc,a8726f4a,65a9bb26,c6c2c013,856a3adb,95df242b,2d4446de,b2b792a4,d36ceb2c,add17365,380d78c6,3b23b101,1b3be914) -,S(b7edfbe5,118cfeb1,4c1aa23b,48154dbf,5e9d1057,a2758516,7fb8e030,a457874,bc1e5723,dabdfd76,c98f408d,1d8c13e5,7dee979e,83b3d610,981b9718,f1e61eee) -,S(4dffac46,6a507b9c,2e2ee5b6,ca81d8e4,d4e8aae6,3d73395b,dd29b024,51436e5b,af227fa8,ad0bfc48,eb469596,b9b2759b,f41eb169,1fb8f896,1451489,ebe0d5d7) -,S(553ab99,3448879,b42c72e2,97d597a6,24416a45,f5b35720,c93a303b,c6dd0e88,5ba2d3fb,222a03dd,c5302b25,ffce74cd,58de90a1,c3e41928,19717c28,52ad1b39) -,S(b351ad4e,4c7df853,8f6f71d4,e95554ca,3a07932e,7a812309,b0b0c807,f98cea2a,5ba5141d,b3d4ff44,7efe06c9,c624d447,1aa3c3f3,47af74af,49929de8,d8558c70) -,S(844b9bc0,ae73df50,e5b80fe2,fb24a35c,dbc91c61,2753c2e8,e3765e1e,47d44263,80eeb80c,414c3a08,a42d89b8,87883d48,84b38bd1,40f7bbee,e977ff5b,c4c57b90) -,S(f64b4ef6,8fc11491,38ed4ef8,ab2d6336,3d494b37,b56649d1,5d15777a,8cd315b9,c6f83010,5dcfc707,f435cfa0,b6bc32f3,8ce8afb6,28bf9139,dfc47279,cafa56a5) -,S(969ceb7a,441f8be1,f16c94bd,6065db17,942f88dd,e5506742,7cd30dee,cf9ba5c7,a08ae62c,6e6758f9,724baa45,d35f3e03,9f636265,d841b61a,f1b31d20,bc8d65f8) -,S(e465041b,78c33311,d4397b30,9a8ba4de,6b312d10,ec2ca906,583162ca,1c599102,3f21d5d4,416f1954,7af1ba97,6687dea3,520ac304,43c180ad,3892d46b,86618f55) -,S(87b2e548,b019224f,b1021a06,522073dd,46892847,308fffe9,910ffc28,5b702bd0,6e641d35,9e7ff12b,20123b72,f0e5ef16,338c3418,38c2f4ea,6dab94c,7c3f6940) -,S(f832d7b3,590a59d7,ec2c8a63,7ca0347a,893fe461,4eaba097,8707c353,8296ee14,3fb3e845,4624fe35,326062b4,a6f30c85,f0e7101b,a3532455,7687812e,412233e) -,S(52aff21f,fe1819f3,7f8b5974,ab004393,6e99d8cd,8342b7bb,ad46d333,5e4d6651,66d79c3c,c7d08828,d8646e4a,6a44853b,4a49df0e,85c95e85,d9c995c2,d09b427c) -,S(aae62778,8069bcdb,fc91bdb,946cedab,63896817,575a471b,315a47cc,d567c678,f254c548,832d95f8,4f20215e,ca4805fe,356e806d,9b3b7338,7dd36e85,214b70bf) -,S(fc15d494,b6580e0d,e1c769c3,95c5d047,202e8d07,ba94bd1a,f96064b8,d1a4bfbc,f9327fc8,75319184,c1876748,bdbbdd3c,bfee8baa,bf46844b,af465d4e,ec6be335) -,S(aacec857,fa4bc62c,82790a4a,496206f2,d79a31dd,e17d2db2,d99619d8,c3d880d9,6dd1e4a2,adc502ac,150293d9,42a1cbea,a576da49,f1de7d15,de70bd67,d95c5fb0) -,S(c7ba3155,bf34fb9a,2441832a,27396e1,99836557,9c9cb856,44c3ace2,9ade66bc,afccc814,243a1fa1,345fa46f,ee4b4190,96082bf0,7866fa8a,2a887d84,d24192f4) -,S(cf7a0525,3bee95d7,711d8f7b,7b301f5d,8036a487,a55e3860,900b25b1,c4599115,e8a4a9be,7b9cf99a,5dcb4db9,8249350b,7a71a12f,a9582620,eda5a35,1a8a0484) -,S(a4336248,6b999ad1,623c4c32,c79ebb3,4e8d6f3b,484f808b,9a088ffb,2885a11c,edf8eef9,74d3e5ae,2a991a28,6323597f,5a161f9,2eeb9256,207be548,f9b38d16) -,S(d3cdbd98,8cefc8ac,3a442587,51364a10,649243a8,d4a63927,f4fa3b10,b1a7dcc8,f10e26c8,11f4a219,da4f948c,51e8b81b,d8bb357a,182031cf,40ffb464,d5f7d7c4) -,S(fa038534,28dd093,26977fc,da344269,fe3c61fe,35567eef,909a2309,8e5ceaef,f31c5d30,9e234b3b,44fbb52b,8c973aa2,bd85afac,1f9f0798,788721a9,380d8606) -,S(718c2bc,26dba98f,24f34af5,18e18870,5510c0a7,4e228cd6,9d4e39d8,a00a577f,c41d0d81,8f093246,5675a326,d0615b0,294b8455,909af0c6,e557195e,11225152) -,S(378ade51,463d949,1ed22ab1,834cd7bd,6b99a123,52c65e18,70d5005b,e97e602f,76469796,d7758ba4,b3bed1eb,9f8389a2,2a421f5a,20f8df71,72821a8a,508e4c1) -,S(40bd7df9,1255680b,b50d3d08,fead6815,5f807759,87e9cf80,15e6359c,9f138b8b,ec0417d4,2eb1ab50,a469a853,edc65ca5,2fe00ee7,53b30b9c,56536e3b,36144e8a) -,S(f01b30bb,985dfb53,7bb4cd62,18cb0b00,b5a77215,4d84a802,8a4969,260d963f,3cf483df,d6b58eb8,46e8ba1b,f06c2e9,6784255a,2afbf68,613f39f1,44b82417) -,S(2392d86a,1bf9a636,38eaa5dd,76a7c6c9,eabd50bc,9f2ba568,183c0995,f7195900,806cd3da,ac23f93c,3b11cb5d,a3bc4482,ea49ed2b,444c6e64,dc557e46,3ac5c033) -,S(b0e7747e,c9496fb,aa7798db,e616fa42,5b0b7acb,7409265d,c989b8e9,20087133,32fa615e,d0286b64,b83cbfb1,e8c4b133,85527655,48071401,89f42d93,330491e1) -,S(8d1342f4,2f6dc3cb,9bb741c1,9daa08e2,25fb6352,ffe860e1,76a26fda,a0601624,82d35ed7,57cb6f31,81af31fc,36f53817,191fb9b,c9338a97,3757d0bf,50d79d77) -,S(ad09dcc1,d3ebbbd6,ecd7be45,d7eec5d,ef743851,2ce076e3,cfc4f8b9,449a2ccb,26bde63a,e1f7fbd8,46260a64,372d015a,fd3d5ae6,125dd801,523a94fc,8421d04f) -,S(128f5199,68435c1,a27591a3,2edff533,d12a725c,f0c7e121,260cbb74,925cc292,dd8945f7,42f1d013,92152dbd,1e4dd8e,53277da8,bab68acd,8c7c8d73,f5d7e190) -,S(118c1167,196e8eac,e519d83d,17ae1e30,36ff1fa0,cbd1cc58,41cc3763,d1d8a931,eea348d,54f47b73,d5d8c2b4,7eb7604b,53beb345,c82ceca3,4f8639e1,45b2e3b2) -,S(81ee4bba,6a84edb1,83e1f2b7,5103e453,2ba9613a,b612e0f1,27009ee7,7be3bfb,e58208,d152059b,73b42039,e0a7a489,df067fab,1d1c2c04,9eed00cf,893f4847) -,S(494a821f,6f4b2d75,7e5be34c,fb9949ba,b9271599,3e060005,dd807c83,adf04f2f,8ab15e9f,c37d368,3586a1ed,ef9ddc59,8dae7206,499cf53c,31a8cc4b,d7ba15e0) -,S(3749271a,da87c292,724a3ad7,2861a7df,9757e31,3c3156a1,72cd3735,608c865a,aeffa1c1,aaab4f09,3998b4ef,e046aaf0,f404d590,d6cd762f,1aea5745,1f8aa3f5) -,S(103c8721,321ddfbb,cc3ef6af,1ea8fab1,3de6aca0,294dbc79,3a1e4216,563dc1f5,fe9cca2d,b459596c,462fb268,a8115880,16c2894e,e8839caa,362e4813,e8e827cf) -,S(ddbfc655,6aff403b,10a643fb,f62a60ed,656baa39,b10febe6,92140bf6,7b78f2f9,1cd4169e,cc8ac589,de57b5a6,e02e03df,f3cc7bb3,45993d5c,4ea57e6,852a8417) -,S(d025f583,3e51a9c6,a1c785c5,1c579528,5af0c297,c0fdb82a,f555fd59,88dbb28,5170614c,110f31ce,d88424fc,7d569f4e,e93d5017,a8c676af,c7261ed3,340d22ef) -,S(3f349cbd,8ebac9e,c570b0ca,29fe8ce8,dbd98eba,103f131d,daaf193,4fe78516,ec9641f3,175ed56b,d0c8f26d,188f9fa4,b38d069f,cef8f4cf,71acf66f,1ef7dbc9) -,S(7624599c,61e71532,a177e838,ba92d789,5160e43f,ad798fe2,9170e6d9,bbcc11ce,409e8cbf,6aea70b8,21533902,150148a0,7e45dd61,c9c8d24a,b8cc3da3,f03c49a3) -,S(8a1e1b47,3c699dea,aa418ba2,85cf7467,51af1cb0,8bf78228,932dc6ed,845403f4,1bd300a2,7a9a8da,6ed2bce3,73b9d39e,661d02bd,b4605740,20934bc6,abf3c483) -,S(eeb91c38,d9b834bb,5e3945b0,9655b988,96efff11,1e3dde8c,add6ef2c,7ea51b09,899d841,24f83b43,e2ea82ad,3a6411dc,cf36fa86,17bdab35,d83829d1,456c56be) -,S(46360f69,8c023375,6f050969,60b3defc,2a1897dd,44e0e159,d185ac04,3315ef47,ec02a6d3,828246f0,684d2059,23ba73ee,10cc88c9,575fc005,6271fb8c,67e0a4a0) -,S(16e5cccc,b410c20,e8de1e76,e5b71649,64cabc26,f629f8be,36eff4da,66f875ad,a80de48e,e079d9c,bac312e0,70f10d6f,fb875c90,7dd3ff57,c9bf8b90,57c0fe14) -,S(c315230,c8ee5bd8,429efc06,bd089f49,5f4c5a1e,2fb188bd,81e41bfb,85acc82f,71430e8e,cee9c6f5,eb91eb14,20e07b5d,736217e5,4bc25cac,9767a749,a477599b) -,S(7731eb8c,1684092a,d9d2ec69,b50339d1,19436082,c9116366,8ce2bda7,ee80c0c9,e6636efc,22a4c339,f8100dea,a227a709,42d18222,8cc58d13,ae4d613c,a879de8d) -,S(2c1c200,4a5f04c0,b83d143f,ede81755,67d4d54e,b2dc4ffb,de00b83d,9802f68b,b3e2e434,30d409cd,26490c1c,818b24ed,b10e835b,d6292422,45c529f7,6e299159) -,S(2d984bc6,a2031a3e,1a57d0ae,d13d798d,fab45382,d29e4a7e,8e029fdf,2a9d95c2,b169c34f,9932f02,8320ed87,4a74da8b,5cba81bd,f20a9454,feb315fe,a0926720) -,S(f61abdda,f7673f75,74e966f1,c77096c7,7f6e8659,746e45e7,2c9fbf3d,5e0db5f6,1717dd6f,86edd17a,b242212c,91878ef8,9ff1b865,b32b4e24,cfdab7de,de90937f) -,S(a68f5871,bfbce14a,1097eced,68a9e906,c94599cf,b6dd4176,ef946fa7,e5552c3b,cbc07a08,86faa82e,d231eb0,739a24e3,62a717ed,30b0512b,96ac8dd9,56ab05f2) -,S(52035076,1af3e786,60906105,36a2ced0,6f8209d,a0eb2757,cba705a3,467ccbe2,7a01b944,5f63cf43,cba95191,262b1b53,ae0af9b,4b172b78,3970f84f,f8ace09c) -,S(bc8f1537,9d4b9862,a437065b,10f6c28c,8c3323f4,51f2847c,63251000,c9f144d6,894826ed,61d85e90,58c00e74,cc731dd5,d62684b1,ca996c07,ab176df0,e4b951f7) -,S(536b0cb5,81dbf6,ab3b364,64a397d7,2a513bd8,a7bb8237,70a725d2,2eb12a98,85bc95fe,6e160f2f,9a31b7e2,74c09023,90cb2f4a,22f15ac3,3d0ee72a,b666f5bb) -,S(267840ea,e2f49fe8,9889bac7,40eb797e,ee42f922,c1821a66,163a580a,a0df90d0,2c7fe7f3,4e06f09d,a1a2b1ba,79906a0b,18c3d51b,d9b6011f,688c69e9,1504a00) -,S(d8fd79cf,6beed8c,fa57bedc,ca06e367,e0667e9d,a057222b,81fba682,979808ec,39cab613,9cef186a,248562d4,fa581384,d6c81de5,a0f7fc49,140d0822,f6126034) -,S(601407de,9ecff4d0,836228ae,eeaa612f,2b659706,576e2eca,74bc32a1,d3d14b7b,6cfde694,2f0e4495,1e25ff02,2f2501e6,7101828f,8088c7bc,a8ef2b25,88036ec3) -,S(f518c5c,bc0e8541,48c40253,d500a2d,1ea1d25f,d31dc777,d6365050,d3b26804,8dcc6378,2b1ce6fb,9f15c8fb,70c5fd0e,53e4d80a,cf38261f,49a558e1,de637b6b) -,S(16a9bcff,334e35e2,80258378,b2e25d9a,56ce58c3,b3426bd,da82978f,370ee6f6,c7b6656e,baa3864e,bfbc5294,fe9836a9,9fdc095d,ceac6a32,642e6911,a6f3e933) -,S(9d940fce,5ecdc659,30c945db,7151b823,a9259d0a,2a3991c9,f71e8b00,bbe35d4f,32f533d,d96f2e36,2109a96,48ef55b2,e5887387,80de97ad,c7974227,b23fe647) -,S(19e973f7,69c2d02a,8bed34dd,b7591828,5036e724,22227a81,850f3d31,3128f586,f2f5fab4,fe79c177,752ee60b,cd85e625,e459b50e,de702010,a6fbcbd1,5b31aa6f) -,S(ff07bc26,473271d6,4371a4d2,9b59f858,b1b01e40,472bb4e0,1769ed2b,66bf2097,3eba7660,492ae09a,abd7bb8,c5d80e33,44539ab7,276edfd5,b599b02f,27c60b8a) -,S(175f786c,93d89acb,8959d846,934c21df,5dc4f6ce,a9c1e150,e7da469f,d27e6605,343366e5,7f5b9f7a,407cd566,7ef1f0f2,464a2938,61fd5f2c,b0363a5b,dc9c2f9a) -,S(a9027f8e,b662a7e0,d70aa1ac,d3e0b9ba,d4e0bd8e,8bf8c883,40b0a7f5,cbafa761,2f9dfc2c,57bfd835,271d63ac,e3cecdfe,f6e19e0a,fc19ac0f,71ef9ec2,7fac30e3) -,S(677daf40,728a6c89,6804ed3,1df283e,19b41c2d,36a3a98f,d4b93fa6,6699983,1affbe57,3a561872,37dafd1b,bdcaa594,e499b298,6af58591,c6a2ea3a,2016c039) -,S(1105aff4,d4761b77,68db74ca,d9fc7aa0,14c5417e,de1fe641,ed1dcdb1,9b5a3690,bfabb1aa,76906ada,4a1ea463,f4caff44,a41afa71,b82e2457,d2756ddd,14946ff0) -,S(3221d033,16be670b,e05ecc94,8b537ca7,9318eb65,f93ab3e7,32e7f36c,bd06249e,92f7b5c9,85ba3fd8,7b14a093,74d4ef94,130d3642,517369e8,f9de5fa1,c8ccb803) -,S(ac10037c,ad83fcbe,6aa7acf2,3043ed,831dcdb5,66921f16,246488de,6e012fc8,d530eaa8,ebe1d47c,8e57892d,9301c4a4,29b223b2,7344e433,f2bf77c4,d9a20205) -,S(b3ea670b,f5001657,913d5d49,ee1005ea,65fdd33c,4ad81987,efa0331d,b29a3e53,6d758db6,df4275e3,fc148e91,6536505f,6393daef,c54c3b0,b708e0d0,8de3f1bc) -,S(42762d8,bf60f678,924b7cf5,4e8c513b,fa1223cf,98e124d9,18d88cd9,a54c8d88,96be42a1,f0dadc84,64a3522d,e13f10ad,3272505,f7d4fc54,e6dc1a33,ef6b2eed) -,S(7b9e0117,167c51ed,c3f7d2b9,edb61bde,aa90efd,88349510,c4b1cf1a,43a9ae6e,c43e0d1d,8a673cb,1f0d9d1a,e3a4c985,bd47a068,2528ac36,67976881,1ead7a4) -,S(1e807fdf,c69acac4,ba5be7fc,9c617005,d34ff896,dae25e6c,428abb96,3255239e,7db7d6e8,8bf3b869,fe4f7c11,65d85faf,55bd677f,5670ebdd,89d2f8b9,f56d972c) -,S(9aadd434,75384190,a6289f2,32cc6491,fb7a1d86,b04ae9ea,94dfd2c8,449c3961,fc491907,3ffe94d1,3b945382,eb9c482e,9da5a764,d9aa1d1c,c3d973aa,5edcd3f3) -,S(5012b7eb,481fd85,db13c3fe,2bdd06a,720eb4c9,805193d2,b99b4bf7,39802f26,db8555d7,e2cc1858,21920564,3c288352,22086161,1a611dcb,d1e98518,7c46cd4e) -,S(78f9e5ba,91071270,5160654e,2393cd73,85e4681f,8efb4a45,cdce5ef3,d73cc7b1,24c4512f,911101c9,d3a4fe24,b7468585,36cb8137,e13578e,95cc016b,96d86e20) -,S(91a7d927,4de2c0fe,84a10579,891ea8cd,f87fcf5b,a0939411,4612efd4,6bb9f826,d5a5e511,b85436b,89e46211,ec69dfa8,d0ee87eb,7c0daa31,24d48462,10e6c40) -,S(3940b4e9,4626f86d,4592b96a,4f27f874,c37c6cbf,5940de,37dafc1f,35350b69,ecc6176c,43df3f71,cbf0160b,697afeec,1a9a0d69,5ebdb7bc,34b0efe9,2cc68b39) -,S(76e7ab54,8c63ee6a,30c736ff,11762061,283af0e5,5a7dbbd2,23fe467b,85c95d8b,f266c922,fc5e61f1,65bf521c,33235e05,113140db,6a481b0e,e4f9976d,2696fdce) -,S(ecdc2e5d,b8d5028f,f93de09,c9f5a6b3,c439b14b,3c322c53,94622a13,80f04067,e70df9f2,bf6b0a35,9029f937,5e74aa93,4014e78d,e68e29b0,9d96da05,5ff78112) -,S(ccfe93db,de087d5b,9194b286,99243dc0,91d4dd5d,7189a5e0,d5621311,9dee9a94,2b0a0a20,cfef0c73,addd2dc6,d9b4ba7e,9e44f2c,26d9f376,8ef90241,b2d907da) -,S(4e82a200,e64f5b3b,3e473e50,e437c224,e21bf875,ec8ac364,7e599ba7,84f02574,ff696d9d,2d9cc0be,217394da,85201a1d,208e4309,9b9372a8,19f6d069,88839c0a) -,S(a292e105,6f3f0a1e,e816a49f,51ef4760,91324316,2e3c734e,802550a2,c942c17f,479a2e95,7a05a686,1c08df3b,221ed2c6,5d192181,189269fe,9ef42a8,e71fd6ef) -,S(47279a82,8311aa4c,b6138c9b,ccb2fc6c,c4b9d27e,2e334389,1773fc1,ee09f461,2480a805,496e8bd3,e02b36cf,8081bc5a,254f821e,40c0ef48,291ecbb1,6699a10b) -,S(b903b4f8,2126fe06,44976643,5f0982f4,394db57f,b473401,9536740,595562fc,e8c97572,bfae91fd,61cfee63,3b24bece,e587291,f65a6aff,b71c6a3b,615e1361) -,S(16b9e3eb,eadf469d,368ab368,431afb79,214bc728,5df165e6,c3bf98a4,701b05a5,26e74ff0,64cf5de9,ec3d084f,8d75337d,c04918eb,f783c65e,b50b948,d48eb003) -,S(4927fd2b,c17b92c1,3b3ca52e,759324ca,353e8505,ba81ac24,9003091d,1cebbfa9,95a6c16d,c4c52f20,2883ab4c,a9c050c2,b2849b71,e19e0df0,8ff495cd,f62d73ac) -,S(70c503d,93e47,10262c8b,b1630409,979b673a,79ad08b0,8d855365,f51ffcaa,2ad207aa,5fe05144,95baf3f0,b0807efb,d10265f0,5de63d6b,563e4ac5,e70b89ff) -,S(cf598642,32972f7a,a6cf12ce,dc5aa95d,4bd0f96e,38ed546b,9ba9040a,e25a9e6e,67f2f83a,f5f09b52,caed83e5,1b9d6de0,58a6e9b8,96d1a6ed,d7ab4d40,30332027) -,S(617b9e5a,8d0b8c44,b186aa60,281cee51,dc224e2c,9e1c4f07,c342a180,78b271f0,b64d8d5f,bc2907bf,90b983cb,a6126586,dbb7e7f3,d95993e2,2bc1b8f8,9472d200) -,S(d52e0c90,c69cd94e,3c849ea7,dbba79d8,6aed2a3e,3ca3f106,d2baa2a3,59c50534,36c8390c,fe400769,fd2b2fe1,b6af62d0,7fbd667c,fcd9a132,b6b4f974,a7e454f7) -,S(ea474a01,36d16bc2,fae6f568,9ea3c035,aa6580e6,b238f42f,e2ab19be,81330a46,d09379ce,aa89765e,1164f438,4b0f0ef0,c1e8be86,427c7455,af98e4b5,c9ee8145) -,S(4e5dd22c,b6a4b205,97f71375,cc49ee10,ba6b82cf,b06cf065,a25d6f5d,bef51d70,d4ff2ed0,55279f96,344dc16e,10e3410,40378ff8,b8d912c3,a17cbfb0,70588cf0) -,S(774587f7,f3038136,131fa9eb,f1eb3407,9e473a8b,b9e5acb7,317ff5c9,17447878,9d3779a1,2b067b00,d2a2a3e9,46f8078b,e6279024,d94c83c6,28c0cd48,145f510e) -,S(ab807569,d1a3630c,e5447b36,c205e601,a6a23069,4d2c0786,19d9b97c,e0ba6611,2b9eef15,54f8ee6,e11af6b,6a1d045e,d47b8821,ec84c6da,366afe10,2730e9ea) -,S(91602928,ed3cea8f,4faa254c,28962b68,c4437602,3076a5c1,6bad95ff,3e328049,764faf56,2d8de3c1,89b7fef7,62012be8,112db4,a3201692,95c7e76d,fcbd3be9) -,S(6c1ecc2a,258a44b1,ca1d964b,c86c5600,49fdfd98,b362c35e,3c830647,cf1266d4,1f9d3edf,5e0e8550,e4534c33,5b07d731,19c49c4e,29397f6a,938fc1bc,ebf8fcef) -,S(e176821a,4006b429,999de3a4,ada09166,f6e5deaa,f09fa613,60bd3733,db8f7084,7d07d1a5,390325d0,27b05e18,d90e7659,f5ef4c8c,c7c6dd00,c7a5427,4ec91842) -,S(2ae0b70e,53536893,8a7faee5,da5d8dbe,e5af4873,32caf51d,7bade79f,eea50df2,e70be2e8,c8110c31,c3eb5e36,31dc5a5e,bebeb184,e6b9f081,bb7236dd,cadf903a) -,S(1c686fcb,d7a751b2,d420614b,56d37c8f,81c9a600,335fa911,835dad8a,7c663e24,4fe2eeae,7ea1b639,b893329a,a65bbfcd,b9fd8f07,28614bd8,6a5b0712,76aa576) -,S(b369d7e5,c31c9a56,f480b44b,3354be,84145c3,97dbed68,d87a4c3c,be31dc5c,50800690,17d31473,59bab021,c876d152,c17ea8e8,b5c95762,c749a2d,29adf3cb) -,S(522d3ac3,42a0ff3a,9a8eb5ba,54ed4dad,fbcdb48f,53bc6e1f,2c0c12a5,61cb1e9d,32ed883e,1e1f562a,50063d79,45075ad9,9ab55ba6,fdff0d58,9d2b4a4d,10df82fa) -,S(7d001803,7b722a7a,17d74696,fed9bbb5,f3d5f6f,d8a623b6,9c952a2e,f2be939e,81ee30e6,deb893d6,274c4b46,8533d845,38073ed8,68b101e9,515ebd84,70e368de) -,S(c76b074b,b228dc24,1dc9b704,75fcc52d,a3f3bf0a,5e954910,ca4e6f16,bd298983,4fcc807b,4c1e37cb,6a6c42da,b939a7bb,6f1d5ec2,87320d74,408622fa,ece22266) -,S(8497f267,99c7f525,83c620f6,e284a9a0,35130556,9d7caa1a,f118de41,c51b05e4,3b861f56,16ce6234,c6847273,16bfa629,7cac9d5,ff562f66,24b26146,413960d1) -,S(ddb10ff0,a217ab76,241a587a,8cd46cdf,ce6ff5ae,e39d2d85,7f47eeb7,6d2bd68e,a4110196,fd0813ea,19846dc7,12537cb6,8faf9333,19e7e49b,553e523,f07b004f) -,S(47eb53da,455cbbb9,a8330e12,e0210d80,cc565661,348fec72,529390e2,a75b812e,88e4a8f,91ada187,5734dcf,42b85e2b,a3f5fc53,1f1c1df1,300c3d5f,e811fb70) -,S(eb0a8903,42fb2710,a4c7811e,78384918,dedea7a2,9bb7da46,e49211bd,95da1426,8d69a88b,d85e2edc,d8264cb6,c44d8218,1ce8946a,818c9d4a,6f757bf8,5817ac56) -,S(d400c8ef,655d3879,579ba4c,488c3e55,af5af95c,1701bd15,482b2549,9334906d,e7bafda2,5a9f5934,6bcec6e2,a9408f18,e81b76f9,7a9d721f,496c27f6,42725e5c) -,S(bae81c3d,1772e104,66625f8b,ef08d4a4,5f07892c,72bcee05,fb7e382,2a6261fc,4ce5f14f,74f28b03,34a6cc64,452b9049,8460493f,3b64d9be,2ecf98ef,c0270377) -,S(7f575b9b,46bd0f74,555a363c,d80122c4,232e8c53,a6624d8,e13b5c06,74986961,edc0ffd5,952fd4d3,c752271b,7cdfaf3b,4cefecd8,66d722f0,3da1e97b,49aaa080) -,S(a86871d9,1292f7fa,7249ee8,e77270fe,e7bddafd,3255b4a1,16851ae,411293f3,c21ee1b0,bd897d82,566cf438,b66439dd,3dfab0ec,3c7a4038,ccb86039,3b0b0187) -,S(c320cfdf,9cbc6579,8c8b33c4,d97d690b,64ae90c9,a5070646,8c8791e9,1ee4a18a,8f1a295b,2a3c8c5c,3b5bd8ce,e3380a04,819a8658,7be87d03,73a0194c,fafac74b) -,S(169a1b4,f2eacec2,be263ced,2e0576b4,ae77b863,525b2a9f,f8fc05d2,c07a8fc4,7703f867,d997a2ca,bb697f87,b97ea986,78777183,aea81417,1dd0946,309e77c) -,S(218de686,ed51588b,1307d8b6,54f7f6fc,e673cb37,553d23b7,b8c23367,d6b7ea5f,98325ea9,150a100a,f5d2af49,2fa25b23,40ee9606,1553c3d7,edd4d870,5288b8cf) -,S(c7c2e438,d12ed0ac,6363564,8bf2899c,d1b39b1b,200ffeda,4ef9cae0,5d8381e5,93a36085,fd09ff08,b83d50a8,3b140edd,a63e2442,e4bf4d1c,7ae44963,c1646f41) -,S(12e834e5,605d6e35,8cbe550b,8fe917dc,59194c58,66b265cc,50b00e3c,38fe058,6a44ecf2,17f46865,2e0991b7,df3b3565,444e7e29,3a2d6378,61a8f3c1,5ec1517e) -,S(30f33c39,af77735c,749fd328,e228ed67,bd625fbe,79dc3b06,ab31c173,777308fe,29a00f66,1c998f1d,bd62935e,44794420,7ffd7b1c,24f63806,9206e1c6,5c3d9604) -,S(c5bd81b6,b057e687,19c47964,d55ab996,6c7ea99b,25c1c2cb,50d6fbd9,af492358,5a6b1332,8562599e,e87c475a,1e7da886,c460ec67,ad81372a,7ed39498,41225e5e) -,S(1fd0e769,9d931a80,dbcfaf1,46b5cebe,b9547f8b,b7fa75fd,b2bac9ae,ac0908ab,11770838,88607506,bad87ba6,38c9ae26,d79a9dc6,6746816a,b9f21d64,fea96838) -,S(ac14a06a,4679e9af,b2ea3aea,15f2749,bc9610a3,b576a506,f96fa41a,76df97de,5aafae08,5b8a0a7d,48ebb339,f4dec906,21bf5162,dcb85100,eb7524e3,a65a4921) -,S(ad583074,13a4eba9,ceecba6b,c568bfbb,30566031,c06e8e97,5c5d992b,9ed2bd33,c2bda9bf,d5c87e0f,a663a40,34162dcb,29b61800,c1dcf02a,c11fe615,25af1772) -,S(5a8bd45d,6fd468dd,41ecafd5,aa072227,6d0176be,81b92061,b4277b73,32acfaab,878a8d5f,7903d74f,6abe28f8,d94d4767,3698a7e,6acbc32d,9e92f9d6,bf31c2d5) -,S(6690c9c1,d9666be4,56d3540a,6a2ed706,372256f0,43265478,7b54e56d,f28df74a,7ad591,23772578,999c90c1,24704c13,a7193b62,64240aef,63d12d88,340762a4) -,S(3c051303,c113779a,6137f46d,38d1175d,8778e460,8b1e0abb,f7bc4539,80b64a2f,9d4d04a0,ad1c772b,4a523c13,cc48990,c733eb87,993cdbaf,61dbf75c,4f6a96c2) -,S(1fdff503,66319168,f5dc381e,8085ac92,223b3484,a8b362c2,26d1f00c,976f9f04,5cb328e8,56aaeb05,62017bf8,65da44b2,94ad7404,df11e117,8426b79c,25a49fa6) -,S(ae83da7,52ec2098,a4a593ac,f99dd58f,cd48da14,361feaae,6cd992d3,96b4fd8e,6dc92b41,f1e1474b,a259e96b,ec4f2b36,108745b9,a500ad9a,edd9c828,4c3d129) -,S(c0f86e7a,6c0fee54,a2f73d2b,6b1522e9,fee994cb,d5089886,d98a4748,161811d7,4aea0b92,2441c184,c347243e,5ad5a064,ba00768d,52d7153,a5e0838f,f497d551) -,S(8e5b23f8,85d683a6,a6a657ed,d2d2f403,1320d4c0,83340126,d2958dc2,4c5f5ba2,25c6db80,477f37e0,ed6c6e3c,c96b1c7c,f9a7ca16,8e940e8a,b2946c7,3b02e61f) -,S(6672b4db,bb16c672,2592c239,7d9ea25e,f081d48d,aeb42c89,ae6c42bb,af09b3c5,a3778252,e239ae3a,f64e3b91,7f646181,4f71753d,b4bc958c,b5bcd3ba,4b5b1a4e) -,S(e0af1a1,b894fe1c,1f7de814,1a393a3f,b12b31e3,fcbd8f2a,356e61f4,402d76d0,37913973,b4de9a2d,23f4f795,709fe825,8eee8aee,afec5996,83d924e7,21fb9b0e) -,S(94355dd3,c3d73a1,cabdbe7a,295cb015,335a5a79,dd301718,10c245b3,d0c840ff,31e96abe,22a16033,56681d3e,e5e8330,628d8090,bfdcb925,79074cb6,82845475) -,S(fc340c8d,1e3e2849,1470dfcd,1c2fb445,e807e1a3,9c525ce8,141b292c,596d2e36,738e7213,7580eb3,615b7eed,9b069cd2,b644447,24696a,7cd22257,7a931464) -,S(c0c4e03,61d923fc,4201872a,1ff525c6,1697412a,7bea7a92,596e9204,f1af90c3,25c4c2c6,d6593ef7,ff5f04fa,a5b0b2ca,736ab33f,5c36dc63,433821b5,382fc4b2) -,S(81afd4a8,d666b97f,dcdf0d36,f2dfdf7,bf7c3322,69728b75,26dcb3aa,df51365c,b7fe7653,2c8d48fb,8c3d0382,68d57839,edf80cb5,732ae303,5c1b51c7,cb8d3efc) -,S(140b32fa,62130c2f,1d49e39d,15f9c64,f5cf54af,3a0c65b2,298e91e3,21b9477d,bac2aca4,c96d4363,12107b2d,8996875e,6772eaea,a5070920,39c1171b,9113b516) -,S(17418ab7,46f1eaa,b98725ab,68bca72b,9cc645d9,cbe0835e,4bf91a7b,3939b98,dc964031,b1292c03,117a4ce8,b3341e23,da54a539,fdd31126,41706257,bb9382b6) -,S(8f0222bb,6cbf7491,12b95780,b50077d7,be2a27ec,5bb6dab4,923cf36d,3a12618d,8df2a149,abcd276,31265890,471094cc,fe6bd8ed,b75c2364,6f7dd54e,30c4c6fb) -,S(e3965324,1c543ba1,2d0ca0ad,88c26ace,b265f42a,41d2b7d4,f252ecf0,a48275d0,44467da5,18786654,5722fa15,36c187a6,f67f2e8f,5a424336,b0ce8bbc,a53f9cca) -,S(6a4b614c,41c4a6d4,ba4f8c53,26d08bc4,ecbc72cd,d2415c3,b7caf285,acb07c1d,76dd92d6,3f85e1dd,685faa18,283f8667,2425de4c,95a7985a,cf5f74c2,7b29b576) -,S(afdd252f,82037cb1,928d896,74f3ff64,57b94412,b563a4e0,1a32cf2d,1afde412,d57f319,300a6f93,1155b0b8,3dd83a5e,d2b4a0e0,5d58786a,8024627b,73360609) -,S(65adaf88,4297a087,6ec0d433,ea82bd5b,9e3590c4,921fc2ef,d1fa0b12,cc74808,30e4ac9,77b97c4d,b7516c02,df65de7c,d9e8ae08,6146716c,3da4b26b,eca17033) -,S(eba0dd63,c667395a,9e9eda33,93f5d101,8462b957,1aae6a09,cb723e2d,a45704e7,8314c569,49b7c144,197647da,baf857ca,a164e385,62c1cf46,bb30e7a7,a8dcb680) -,S(d3341d4f,1f967f0f,10932a5,351c6c22,c748af09,1d547cc,2766e6f3,1a9f570c,9694fb83,74177e3d,80775206,f58b2e12,32b87c9a,21f060ec,19152435,45502951) -,S(1596b717,8dceadc1,b5f3a5de,89c089f,62506b6e,2c6e49a7,f1cc4a11,e502079f,97157538,2aba92cd,8f009de0,9dc143c8,51b0f3ea,31067381,48a34858,8c085d49) -,S(138c0bbb,17c63e1a,a3e65b50,3c602d8c,74178847,8dc2bcce,65b84cfc,95f7ec41,bdf88a3e,34f69fc2,415fb95d,a4b6d3b7,f159651f,36a2d4e0,b4063e5a,ee86dafb) -,S(7d99662d,e6274432,65ab2842,a4ed79be,480404b3,1b847c01,c557e277,ee073176,e2ceda2,bada9b63,ff2fc022,44124d3c,b83dd4d1,f3fb74b2,763ecdb6,46e4cbf0) -,S(9e3f4ea0,b1db451b,7d713eae,35802229,fabbbfd,6f6d0ab0,af7483a5,37992e63,a9023199,10301c3d,78933143,b54e87d4,1419524b,16c9c00c,5550fafd,e6be8b65) -,S(108c8cda,d6ffc3d,b0863a66,43f0a4bb,efcdb0c7,202f630f,f971a7ce,dec3ff40,847ab4b9,8fba1fbd,15f6bb2a,4b3d1038,726c2d66,f4c9b8e9,f740af8f,5067d95f) -,S(5258a6a,7c85d4f3,e650f0e5,1e2d8254,8a768c0a,f276da55,27ab0050,6e97e710,e5605a14,31c8941e,4f2aa3c7,9ab94e3f,ffed156e,ba2159a2,7fde377e,e2ea7e26) -,S(c40820e7,f46acad2,5bffcc6d,745aa3e,7036f26a,b6ae85f0,e3cb8f95,29dc3f3,6ddf9217,88249ac7,6ac2c9b0,1dc5e62e,91587d15,c76fe26d,6d7c3b2f,feaf3b12) -,S(c135f50f,160d04e,43148abf,d76509c4,e55aadc7,554e4ea5,823e013e,a0490da7,f9a597a6,b26a1485,a7d5a91d,486d099,93de9a4,6484edc8,72f8f4be,710aae69) -,S(484be5a8,b903230f,991c3118,38d3ebdd,9759f5cb,11a9d0a3,9bb11a03,3924268,18f80a36,a3d70e67,5bd65253,a1ad3e40,a3152d55,c1141315,57f8585e,315ba462) -,S(af67562e,998a4032,77fc5827,cf222258,cb2f23a7,4dcd0d4b,315564c3,eb66da9c,dd5bf89e,c9b2c178,6adea201,d36f3a66,771b3f2a,cfba7acb,c30024fb,fa73ad6f) -,S(38dd6cd,475f2808,938d92be,8ad0c955,f3cf3255,c3602b99,3c177e06,553af411,1abcdd02,d82cc0f,680362bb,f898bf89,304d681b,6bc3afcf,65454ab5,8d44214) -,S(ee37f0ab,3db1f9b3,2da0031d,48f53766,3530b68a,f47bdb87,679426b0,d90fa6d5,6cdb12d8,136fc9c6,2f025cbe,7882ef21,4e7b09dc,9fba4cf9,b021c4d6,610c0397) -,S(670684dd,fcc19f15,ba9201b,ca36d143,47dabf31,bad07e8d,68e6fbd,2630a98e,77bd28ff,a9699737,1304d4f,82d29d1f,a69dc123,6f2ee438,cffe3f2d,358ce706) -,S(1654f447,78026345,64e3608,bb29004a,812ea39a,d96830f6,66a92f5c,54a79359,11d91962,3f81fda0,36d2d021,607d9750,cbd30359,83c4f47a,21fc8116,ca93cbe9) -,S(ccf0a89d,429a0274,7b000326,d62825ec,6978f24e,8f92f490,e8cab1ab,ff90bfa1,5f047694,375222bd,5968dbcf,a331db73,85b4df25,72791c53,42c62467,3d84400d) -,S(45d36700,32ab11c7,897d648,67ed4d03,a9504461,bf28f3df,7e1276fe,4c1de796,67e837fb,37108844,2338086a,d1506453,ed1f37ff,fb14e617,93908c7c,2a8e6fa4) -,S(9af3b6e1,627a2ffb,c18ddf33,b668fece,bbe7ebe0,986df82f,1b2fdfa1,56dbc565,55e9562e,882f6629,1eae4c6b,5a82b0b,b5bc2cb2,b8f884bc,3e45a126,aeee19e0) -,S(ecfe9d5e,d3b9fe15,c320e05c,7e0f3b1a,5fdaa9a4,5e1ff99f,88012642,a5d45b4a,b3cc1fd0,e0117151,f53ec671,e1d207ad,5f2b0755,8956cf28,2be5228d,db5d48bb) -,S(6e482326,6ef64478,dfa30c6c,f3a951f9,fd9d3108,dbe80e5d,3cbf2217,70f5483c,97a3f599,906b1738,372212da,80309562,d3d4179d,d2abc2b6,41ef2f4e,6561095e) -,S(3de89149,f6c939cc,5419e4ba,f0baa93a,390f01a3,4ad0fb7b,3b170e54,60a380c6,e9a07758,1c4617c0,b996ae3f,b250b723,874b66fb,85a6d826,cc5826e5,bb068491) -,S(d4d28193,53ace188,703643d3,84622505,d9020459,a600349e,69016cf4,faed2e25,9a494bcf,e15bcdb0,97513682,ef09890a,424d6bc1,ad1cb73f,123ff5f6,7babb364) -,S(f694a819,fd0f2035,1193eba,c18e2db7,9c219191,2bfcc60b,6af8e067,2281095a,d80d1652,1e43f18a,4b663898,bfce8670,6f53436d,a30b0663,9ee6f99e,ca87e667) -,S(af8595b8,8de7c459,7d1d1614,ac897de0,5dd9ff05,593dd3b6,cbac81ce,d2e1fb5d,e9dcce9c,83ee7217,857d5ca5,a48bb720,69d467b6,897be9ac,658dfbef,3d40e6a6) -,S(df4177f6,a7deccf4,c618b710,b096bb4e,b310e4e2,470b5795,6a633154,8ae8123e,3638e20,5d42ebc6,7184e567,c177f479,18fbf9b1,e4f69435,487b289c,35c7fedf) -,S(ef50482,30344ae2,70ec6d30,f4daea23,ce7b64bd,b101638b,5a52ff3d,6dbe9fd3,a6eec78f,e38a2e6f,a9c062bd,4ce28dde,c5d25fd5,a3204281,ae30d79d,99a2658d) -,S(f89596f3,ddd57abe,3344080c,a6d85d0c,492261ca,7a698aad,ae00dafc,75615954,f8d7d2eb,45dc2b9e,a0979550,8d9da016,20b53a19,b4150ca6,36bf0f86,ab3dc0dc) -,S(a7c2ffd7,50b99bde,92ac1419,57d8df27,56ca49e9,3f4c7434,b24899f1,24fb3cc5,a1672ade,aadad853,47d1440,d573e3dc,91987d6d,ce55c67d,665402d5,f8b0a289) -,S(463f5f25,b5c63801,a6b1accc,6662e6de,5256fce7,37e1c875,2b4a880f,19ceeee9,858e4a68,39eb48a7,f1a7de4a,514fdb46,1f4203c2,65e308d0,3fb9770f,1f8f13e5) -,S(4c99bf38,57073c27,cc92314c,f260dbf9,e0f4bb7d,1a5ffadd,a808783d,3bb602b8,aa107422,ac7dbbbb,f6e8064d,22a5526a,96bcbca9,9dbaac33,c1f35b2f,c6df568f) -,S(f6825035,64438569,aa7a5a4b,e2468453,8d8bfb88,f7e983d5,33ebffd,f8588520,84ff2ce6,9d79938d,fd910bf0,25a2fe8d,e6013c03,74784b73,168049e,c851cf15) -,S(62ea02ca,16b2e528,2f913a,36463494,c00df046,8afbeb34,cc9573,b71577fc,36be98bd,2c83e8cf,e0fc1aad,98ffd9e2,9ccbad8f,a25b9da8,23de20fb,fe91f9b3) -,S(ea34600a,7591c57,d0a7e351,de6e6d0,2c72220,62a980cb,bcca8966,356a2984,25eccb4f,a6102f52,60e4c545,57aa960,b427e372,80c35b8,edad5f52,1bc93aca) -,S(5b76cc79,2e78f177,97b32c46,92f2eca5,1ae1b7be,a753ce98,8e58d116,6c667027,2e01ba25,799e1b9b,3416493e,3fe9fff2,c46e634c,2175a30d,7458429,3ea60b5e) -,S(62a52d8c,d8562624,48ce5315,28213ad0,6fc6044,b6490db7,c27b7662,bb66f07a,e8f5e0aa,aaa65c7c,2b51e665,f3b31157,54ab9fdc,ac492ee5,fbb2a348,d8db5376) -,S(a276992a,5e155e29,d091e05a,5f0513d9,ff2dfbee,6ec1ffd9,a91f55b9,bca641c1,3d480cf4,e3f6efda,6cea9cc9,d769b16c,d1f3d64,23aefe9a,abc82b8a,adb22e48) -,S(bdb5fd64,bc99741f,a2a672d4,a895aacc,98886a9a,d38a486d,ed1915f1,f0b515f,d9744595,ae6e1e64,5a52a094,75ad094e,6af9655f,185ab90c,c03262cd,39794f93) -,S(cd6c6829,9d2b1c60,9b70153a,45259261,91b9b9d0,9fcf0682,d312960c,c3f82c04,2178ce3f,1bc21a2f,7accf32a,b20d625a,182f8733,e460e8b9,e1067dfa,fee6b36e) -,S(ebbfa9e1,8a4107a2,475f99a8,672be581,f32426a2,d774acdb,efe501c0,af97a0f1,1845a5fd,d71baefa,64cdf1f,d1211158,a70752b3,adf2b4d4,b5bf1a9f,7a0abdf2) -,S(bd5af866,4d51256f,455a3190,88b754a5,34223135,1491f763,3e090bd6,27414fa6,f8b5bbf2,2154786a,29f75090,fca2e149,60f84b47,50ea8db,d7c309d2,52233f3c) -,S(34ef0b38,5a8e776f,1c3ff95a,5852027a,ab6d1da6,6201548a,fa181c81,55382b77,958180ce,9afc501f,84d4d3b4,eb556ca2,e6ae8dcf,f949db6d,33cca5e2,9b357280) -,S(4b5f6663,11e6956c,e186fe3,85f00069,c0dfbf67,e4130bda,64e0e89,1abaf471,a6cf3571,2e790d5f,b500324,773281c,43f6d008,f6578ab2,b48fe4de,1ce3b545) -,S(cb22489c,bac94ccc,887a1d7d,8836cacc,c8c2a43a,4e09595c,39cc6064,ca04546c,dced75ef,d7ee6ae0,18ff2690,9abc82ca,da74e823,c62e4268,606334e2,969bf94d) -,S(b069007c,4a50bfdd,38ebcbe4,31a952ae,5356d63a,9f4179b5,e4cda3f,fe478c42,bb90d5c8,e66c6194,ec55acc7,6dae5f0b,dd498746,2d24a265,c314e93d,618a0f41) -,S(18722ce2,9d9cf99a,e52a420e,23fd8e85,e1582d02,c520d4f1,16c2b82d,464091f9,9fe257cb,5cd5f644,183c8461,ac2dde6,94cc84e9,76d9c623,584a9d94,40fea12b) -,S(a1562afa,6420b34f,92a78951,e9ab1bd7,8772a181,636df487,81bf4bc0,b16bd196,ce4435e8,7105d006,9b353734,5a503e0f,a692d3a,8571e8b9,66d9a722,48ecbd1c) -,S(f466db58,b4fae060,b12b780b,df11c7e5,ea8a08cb,cc50e68b,f5d85926,b9f3cd97,c86b4153,45515a2c,9a831ff1,d6377a8c,cae62456,f207df2c,42a1e767,684f79a4) -,S(686a1d05,e2bfaac8,e31def35,21876c81,27be2ad1,34ef3dcf,6de52778,37278176,111404e1,7f2153ab,43597a74,be1c278a,998b3695,5f4d465f,271a6a46,8e9e8986) -,S(d8433d5f,e5ec423c,73bb3ec4,95d06cf5,3a77474c,1e97ff97,f72a0457,9a60926e,3df114d5,a9d63dad,ada0ec4f,f98cb8ce,f1ad419a,e2c23dc2,f24048b4,1879be1c) -,S(3a9a0aed,4581937f,fe49392f,488053df,349f0194,9666418f,16e56fcc,533cb73d,c9db1a90,2d6676da,251b4be9,7a643bdd,d55c2b15,95ce51b3,281cc866,40cb558b) -,S(b35a204a,28884708,3091abf3,34be3696,b1082fc7,5caeb0d5,18387aa2,711a4190,65f951c8,78232345,487e8e,376c22bc,e5d9e8d5,ac04ecbf,24cafef9,4de358f8) -,S(81ff6fec,11f48691,59a2d23b,b2a6a9b5,68c5e6c5,1df9905f,ff73e1cc,a2c505a,c7b794cc,d657519,fc05632e,33e23474,654f1344,6ef1b4aa,1a1da18b,4acc1e49) -,S(3588a9e1,7feaaca1,a62fcdfb,3952beba,43116167,bb238f10,a41fdfa9,bc316d8e,acb24c1a,58ed9a0b,9744fa76,df4742b9,b440347a,4b4446ea,a3e55234,102d4789) -,S(7eb13fdc,9588b724,e7cddaec,498a8b15,d57a49af,529c8c9a,cc8303b5,e81f91c0,89f6ac3f,38351f7d,e4b293e,f61a87a4,2c08a4a3,ae0c160a,563ae5af,dc62dcfd) -,S(2f68c6ef,b363459d,862710a0,a0ae67c4,afc3cc00,85f02e21,ca4d764,3c76e00a,f8be9930,3a3aa7e5,c50d3f53,9b88bfad,60f05fb0,1461d7a8,225bb21e,18616cd7) -,S(b11994c2,5e3e6d0d,917ac215,c5f39606,3b9b764b,5dfc2b75,ab8ef880,3b57d802,4a7ae35e,c525d91a,cfbdea6f,cc9afbc9,b3cc8c80,acb4385e,9bc20158,f9f2b55b) -,S(d8e7881a,e1e4d04,c431c097,25dd4cd9,b4efb4c4,3896256b,7de47fc6,3a3b30bf,ccaf57cc,138f0bbf,5dbde16e,91d14875,c0d5ea,3842e864,be8de17d,875fef67) -,S(88e02abf,a37ffc97,f564cf3d,8a086c8a,62c05720,802319a2,30ab7cfe,b448c478,ec2d3169,15dd0c2d,6f03f851,97a96f9a,6c0772ee,df0c4524,c08f58f2,39c89308) -,S(ad258ffc,b42d127e,a875b181,a8883a5,31d18a64,d75a6dd4,4111d697,90752d1f,acf5ad9d,bfbb14cf,a25748e3,96bf23eb,aefe1bab,6550b234,90ca0278,276e9db4) -,S(a2bfdb6d,38159e5a,604d564e,af29cf09,a0a8ac79,1aef5a63,e1c05da5,fb6a0c39,7a45c5c,a7ee7c0e,74c05914,1e3d898f,ab62a8c7,31ca0a66,a937ef55,51dad999) -,S(7c7bb792,ef21cd53,bcf33a82,6a1ebf93,e9f3357,51131f9b,36f659d9,594f453d,bc98b32e,173d91ca,e9daf137,766c5ca5,6e0434f0,e2eb070e,7fa7f8b2,e7364635) -,S(40a2000c,dc0c1c9e,4c037a3f,3113b48,f26730ce,11e03b1f,d2f07217,7816f8c,1966929f,210afe16,9daee99b,7b48eef7,27e1703c,8bf42006,922c0496,888b690a) -,S(6427d169,cfd7e9fc,1b310f68,e3371720,28c17dd7,c6d5a32f,4ed6d41a,634f3f1a,b1a71fdc,6a030ca3,d7dc2ce9,27f3b9b3,ca7169f5,2fdecba4,bc85e32b,4e52fcff) -,S(723013b4,24fd897a,1e8ab77d,ee0618c9,3c832117,94f8b822,9d7a9e51,1ba8194f,21acfca6,e5e0cc31,479e5a97,17494692,9134f2e6,ebcef2ac,c7779251,77e9aede) -,S(1b18b7a5,43a284b8,3165bfa8,ca947da5,376fc4a0,8f4070e0,a20aa905,fd12acb9,713ab4fd,9e0bab6c,aadd2f63,1c5ef168,7cae85e7,6146319e,94b19a1e,f6a69584) -,S(65e5990a,4700f51c,9d3e61d4,26c92f88,5506817c,d4d60c66,a341cf91,9646ff81,2ebdd818,f69cd135,1405c63a,7160ad4f,17a6a7e2,d4353db4,7b554eab,3e737819) -,S(eb131661,eb78d37f,92a851f4,506c43b5,1f2a155a,dac7eee3,b1dbc29b,a0b1250c,45f2f418,47d2258c,3f78a2d2,794e9aa8,eab23395,8debf0e,b1440d56,dc728334) -,S(f20aaa98,ab7d6f1,d6de080e,ecd0bd28,b14cac9e,7f27c931,5576b039,16777203,4d0dc753,84c942d9,347f007d,543bc399,ee01e84,7625d5c1,a57cdd67,79c4dfba) -,S(9994a963,ef21ca0e,9657cbcb,3da57f3f,e28ce389,60ae5dd2,812b2949,96969047,93d75bb1,35572b75,4801509e,5b64858b,c0a415e0,3968efe4,2e558786,8516362b) -,S(4696ef39,95e5818f,d7894737,2fd68c75,fbb455fa,8477863b,b2687fca,fc2cd7b5,1cdc53f1,c52112c2,f58a6f66,7c1e4e9,110d83f9,d765347e,a724c784,d8e5d5ee) -,S(7b052f1f,e1af9537,ab3bb5b,3e0e510f,7e101cf0,999f85be,c403fd62,53e68d25,69c7f158,4b6c36c,f7d881a0,fe4efa5e,3f879753,641ce0f4,3e73bfe4,77ada27c) -,S(99452d74,3311867d,1d86c1b1,decd1ed4,7192a58b,3ef98cf0,7816823b,1296abc9,ffabb50d,a1a0451d,36b811ab,5e0c55d8,751a1851,3ca8bca4,8d6b3ffc,61ba36e3) -,S(40c6fec6,5ded4688,31f72de9,fb5c7f67,32c0c170,29f19b36,b00b0f85,5a12424,17aa0baa,eb3ba6e4,c5000e96,c3eb620d,ce1dfd81,b35a3e79,b27b8246,97dd5741) -,S(b9bd9e2f,c55ce5dc,2e46e4df,56401c72,e01ac3d5,201a3cbb,a6609fef,ae2e827b,f545efa7,f95e9a60,72cb9750,6f929b4c,e0360c8f,a9f058e6,5b87bd55,a72abdcf) -,S(867c0fa9,f885935,2756e3e4,11666eb2,59a416b4,7c2ff329,e30be462,13178921,6fdda875,4a50ee1b,d229d4f0,fa8876d6,9caf9fb2,a6af19fd,dbbd2a81,5dae486b) -,S(1cbe8374,3decb58f,f2fc9668,7ba45c64,812507ec,c2f71d66,eeea12c2,92fb36cb,799533ce,46d2c091,d0b553b5,18c82317,f516049c,4a4f50be,909c875e,b0bbe21b) -,S(c654f9fd,57426248,fd24097,2595d71d,80cf771f,cabed8d4,63bdda8,340398cd,898e9224,c9e94d14,3f96702d,c296bf50,9b2cee37,da574bdf,b7c09cec,18357a18) -,S(49e8e14f,4a9f09ff,48725eda,85ecae6c,3fe3400b,81012e00,991f6a69,2d75083c,815230c9,284924fa,57d08944,2a30c61b,8ce19644,7a8ede69,fb645864,ef35977f) -,S(43a6ecde,ed83f1fa,8946f584,99e71bd9,978f610,b46d1613,c15fcfc0,f79786af,2995f70c,11eb448e,68eb3d10,c84b36cd,7605e249,1df1fa3,2e9eb57c,c0275482) -,S(96861d91,678e5004,7c491950,5bbfc70a,e342c3d2,361729b0,4d0bcb5f,d93eceb5,6845ec37,9bee6269,464b2e9f,156ada30,c518bb8e,105153e1,c3b3e948,d38078e7) -,S(3c72be53,c9f82add,504a1955,7b9560a1,7716a058,26063408,79aca60,c55f4515,e584b72b,cc4744d9,6a00dc44,b03ba61f,c2269731,a8178755,2a6dce8,25d31b81) -,S(ce4b4d07,deae1fad,33192544,448ac5b2,77ba7f70,27b81a08,d7f84581,4f71787b,2013299b,2c744a5b,da6b243c,d04d95b7,e515848c,dc28eb40,892d40c,210bd1b2) -,S(37984db1,6d288866,78e1804b,9c94ebf8,f3a1aa05,1fefce96,65712f98,198ce116,20a25966,8ed14a5f,fc3aac09,6d2351b3,b6cb19ab,da4c833b,4a2a6c68,55d1ce59) -,S(ac01bcf,b02e627b,2c9c931c,f87beb2f,4ad7328f,9caf627a,2bf695ed,b7353acd,be4eacf4,77c92348,fe0feea9,3075e93b,bb3633c6,6747524a,e387df82,176ea252) -,S(d5d6af83,1a81b72f,efe5618b,ea43335,bf1d81f1,73382fda,860260d8,1a2faa83,865f9ee,4ff0fc6b,fa761709,db4c67ee,a3213d07,21b2facd,fcd8fa57,8945698f) -,S(3c16399c,4de35853,a6dac8c1,8eea4b40,92a22a8d,5e69ed0c,13b9c2a4,3cd5e39c,bffc2dbc,c2ce4b04,6a92b967,d1a04b5a,2fe40be0,fd9930d0,45b51f8a,15b53edf) -,S(f67018d4,23e50a73,68045b0d,ce803e35,a26d9a5c,288a3a7c,c25ebb03,dad28187,ee97afc5,1c73531f,ea8998f5,53086a59,cc67c6db,955baaa2,8f57153c,afc4e772) -,S(de67026,529a32fa,b3ae79f6,ef9ece7a,47008d2,46f89053,e9339c4c,dcb53b30,4daa8700,4b055005,90611f78,43d258b9,516f1fe8,61cf06ca,d466e000,d3a68783) -,S(a133627c,af6e7ed3,1d267608,19b69f45,7e75ecae,2169284a,48b5ee16,b5dc8c10,755ef12a,fb5c071a,36dbe2b7,1f858d87,31c93d81,d271c999,8f632982,d7e97ce6) -,S(d255c1e7,ccc88c4c,33887c9c,b9c15a2b,52b08471,90ad1420,5fb5909e,d36059c7,83e3e1ca,99a386e8,4b119391,2c20593c,f9573996,d42cb7c3,6db24a5f,cb413080) -,S(aca6c69b,9ea17803,4af67422,71b8062f,77e6dbe5,1df2a570,65fb3057,ea185b8c,40cb09f2,adef414c,816b22f8,d7a59f8c,f5197fb9,b31614d9,ac172436,d0f54647) -,S(fbc19c84,3b656fcb,21d99c3,5289d3e3,2bc58fdb,c2404309,a9d8831a,f2365f24,cc22999f,203a4fae,59eac72c,28bed6d9,291f204b,707bffca,ca6d8359,1e403124) -,S(ea308c88,c366677d,5e575457,cd3e6978,5b491a02,c542dcae,5dd5e149,2f839c55,c1916831,2f48555f,b80845fc,ba89eee7,a7967807,d10c6f6e,b516c190,94873ac9) -,S(d911d62a,33fefc48,abfd4409,7ee2d32f,d7e85816,2a8a00d1,342646ac,8dda6cd2,f160f933,41bb32f7,401d153b,4a2decf8,b793fb5b,4d5520c9,6d9cb9e,cba79aa3) -,S(bb75b497,7d698442,7b0ac74b,939ab3d8,fb94304f,602e102,1fdacf22,27022a4e,ee3cc171,8e9190df,9b45d8d3,54eeef9e,11639423,dc091128,ae09e451,fffe3468) -,S(358e7639,b4031852,b983b5c0,a6c0d33e,5edb304a,3f8bd15c,35d35794,e2cf90f0,5da4be1d,2e9bef5a,5da3cc59,d3c4f85a,e6624ee3,17395ded,398147a,12c56c45) -,S(e098fb9c,440a5cdf,bc570270,4b57eeed,f3087b7,e196522e,4b194618,f3c874fe,9a5b80e6,b22dd111,1f824c36,4830e723,18b7825e,2f2a0fe6,ca460d0c,34eb6449) -,S(62d607b2,d1a16e4e,cf60480a,be9416a7,15d70b5c,56734e7d,1498ba03,7632528e,70c5f4d1,4f5c900a,96291a4e,d0f795ff,439d35d5,2c5bddd2,ab10571b,1d7d20c2) -,S(a630c5bd,ec76f869,40842391,cba6cdfb,9109940b,e1034b87,c6a1e5e6,9662857c,8f28f55e,beed2883,3e347b10,92ff8938,133558c3,bfeac1f6,a6b938a4,c783b79f) -,S(e2a164aa,e17cb0c4,8ae1e911,872b0b3a,7c0e29f0,93cd5e18,97145211,d72147b,23ccf99c,afd1bfbf,a7ce1ade,1590d609,9a423b26,381f5761,c19ba373,290e6193) -,S(742526f5,b95051cf,2ee34994,8385fa72,425162e7,e46bba3,febe5ce8,595a8b37,d106a3be,638987e6,870acf8d,26d4f78c,e6aa0e9b,63e4eb19,114fc97a,eee3a12f) -,S(ce7837c2,31c32444,10dcc790,de465c06,75404a1a,68d23fe9,b69d887e,9c554f45,2c0be877,20cfdb11,8c37b2de,a2c355,d12279da,58f75570,7e738867,146257a3) -,S(601167cb,2788b146,998f0b91,d582cbd,27f4b866,40db7ec6,7f26214,f3ab9212,50525e40,1f2da57d,1f605f34,8f11ac23,19ad1827,41d7be11,46538e83,e03bbeeb) -,S(d2f657da,6f7c3c80,9d2e5291,b1161d46,393009ce,e2bd22ae,32b99eed,f76fc728,6df58d32,b795b6de,2a9c3b15,f4f1dc9,4e6e6757,e01891e2,79acde59,d13e3e75) -,S(e9fb6b74,f84973fe,7c7a0924,e0133b92,bb4c22d1,ce9a94e8,433f0c72,2a86e00d,f4df6cd9,df43c150,9d4b9580,eb87298a,551ebec5,2438597c,87dd46d4,3a8ad2c4) -,S(98d46b64,e43f3384,88c63da7,35af1141,e8b41981,b706ac5a,7aa1c0ac,1182afd3,3b2ce203,5bbd2cd7,f3206b3b,6aa3ac68,31e0e2d4,7f9e57f2,3e780fc9,cf865733) -,S(b358a4c6,a7130b1e,a00d8403,7164e68f,c6cf96ea,c6580ee5,b1cc2452,8d2bb5b,3bbb25ab,4645c17a,2a6f7e64,2d3952eb,86462564,5647abd1,2e80d965,be1d3854) -,S(fd8807c6,c456582e,d03114a6,2b42316d,4d0d386a,aee634cb,d33f2f82,c1ad6f05,c67d1611,e45c57d6,1f8d721c,437c0ca2,189488bc,f363aab0,f25314b0,14f896) -,S(cd53fa2a,1f989ceb,cedfb7a5,237addfb,2efe9469,8b6509c9,3081710b,f0db107a,47e61ca6,4d26e617,8192e993,411d0540,bf7c37b5,8c748eb7,6c1c197c,87c3f844) -,S(38cfdfb1,1b60a68,b00a4096,8f2da5e4,4a60868b,de9af728,fcb888b4,9a098c66,65f4f191,92667492,d717cfbe,bafd0076,59c08392,30da216c,315f2cfa,d3725184) -,S(cc179d39,1c6ab4f3,7fae6380,35886e2f,82038bca,768d1396,13fae8df,a167a271,a12fff68,84a967e6,fdd6e14b,4083c0ba,2a2bcf49,f7d6071,d708c70,4722b1f3) -,S(cdd61b33,75fd00cf,430d9d54,202c5c61,465fe7c0,a3f51660,ce74a3bc,58068c,46e5334d,bad31f3f,6c4bccbc,6812cf13,5c039a5d,d51c6516,49564f45,45f13ab) -,S(39ecf8d5,4fa9c3b,fef7d5e6,5ebe0e75,288f17df,4b33036b,d034be2d,fa5bdbbd,21991cec,ef62e421,70da3bf9,8b2f9bd7,790d5b13,25159727,a53a0735,5ab1d956) -,S(7b621836,342994d2,3185da8,67d47e69,a67a184e,925a3,524f5e7b,63639263,b08c269a,1569538e,653f2beb,3e6e348d,c61537e0,7afc5f13,f56d1f74,518b274e) -,S(28e5ec3b,38359a6e,7d3a965a,c5713365,44b91ea5,c9f350bc,d315c153,72133bb4,5bdc5a02,62734535,8621c1f1,492b3434,be731c25,f82c1a32,163ecf09,7f548465) -,S(37ac3ac2,3f6b2a1,a3a5a99c,707a6b8d,5f05e80,133ac522,107ae5ff,414d33c7,460c947e,76eb51c8,42bd0e6,6ccc0937,87f61bc3,554538b4,c2065fdd,533d0b02) -,S(275f5ef2,a4546ba0,9d96d138,e698cd32,78cf27f3,2ee297a,5ff8dd41,f16bea50,ca91a3b8,5b0a493c,a49168b4,c9eff873,66212b9a,c030fe6d,a9be42b7,45d0464a) -,S(6c43669f,a69bd51c,63cacca0,21c69bf7,9a94ef9f,3f0aaa92,3be9380,a6702e34,b416195a,1419771d,82fc2ce0,637cf5a,29823d1a,95614642,c93a979e,5ff3fff6) -,S(606c37c1,271b90f7,482e6ba1,81bd956c,44a44189,346bfa67,539c188,ac0eb61f,f6af64cd,3f04e30a,1b4a7019,c6caa84b,823bd00f,587eb58a,e190ef25,322154b0) -,S(e4136e15,b3fdf609,f779d0c0,70ce8521,2babc592,577361d0,47ada13a,2a83d43b,1af23c84,ad240ac8,50da2ec2,721531e7,18776ddc,5847edd8,b4d79d52,26e53125) -,S(a338d942,6ce420ac,c9fb29b9,cf572af0,72c0d144,46dc2c3c,75b9d5c9,f7fa244d,c88a4399,f6e3ef2c,619cd9d5,215d305d,3715b962,b02b29ca,231446cf,8ea7c40f) -,S(c454d1b2,6f77ad27,a168d032,fc1a73ca,fcc4aac3,ace31f2a,433599fa,7107fd9a,989b6091,ba2ec267,380c5139,47059d4d,2773109c,1afc21a4,3be54ea6,ad8f19ee) -,S(bbd7bd30,5bf1b36c,6cd6c180,2f41525d,75675d76,9352dc60,1a727931,ee6f40c8,3c3263d3,75bd412e,1d7f7d5e,72f73216,6415ef3,52d1fcf0,58e6c046,ceb46abc) -,S(acae6fb0,5d5b503,c2e3d841,19ce3bbe,1380b363,e5d8763d,3c520a3f,df39f7b6,6fab4b7b,daba880c,9167ae8f,5feb9aa4,3ca19f28,77ec5021,df36ac7,db730293) -,S(c9d4ba53,a44403b3,b06915f,6bd9bb43,4716a639,453797e,5b8e1cf5,abc78425,749cca45,6abc2a6a,4e970589,42cefba5,a2f55dc5,39bf4f3e,be5088cf,ae04bf70) -,S(3408e460,99f1a176,fd52f70,3c772f1d,a46d32db,246815d,a21826dc,c5657e61,a93bd344,de7afec8,2ea2842d,40fbcf60,732be8fb,738b8364,aaaab796,1e20974f) -,S(5e061a06,f97f61d1,5f66c3ff,17372621,4ce82af,3e606b4e,9f64fb62,e405376c,609064a0,bde996b2,d909e50f,726ed7be,b4698ec7,5e1c9c45,3ba18815,2915cb1) -,S(b12ca67f,739f4284,3a7adf58,d2a2f3ca,fd245ff4,b766793c,c79cdc31,45579113,b1deaf81,34f017f,b2bc20cd,da75fcb7,d219c353,98ee9887,612781a0,e3f3d1e5) -,S(95a72f2f,c241fa0f,c9500cea,d9cf069d,23820078,f61d4492,508d0fc4,34fc223d,832a3979,1fb9fd9b,79748643,64643bcb,b227c39a,e4cb5051,d136263c,293cd453) -,S(ab8ccb01,4b672660,b867e544,926749bf,7172a0f5,ac6317a1,a18b7d15,f039fc94,28471e3c,a2d6e77c,87700c4c,7e3df1e9,2fe91efc,77724df3,2f20ceba,1ba000fb) -,S(26131926,5261c0d3,ecfa9769,fa987347,1b9d4ebf,dccd830a,96bd160b,61b47278,dc9ab665,485133d2,59d7b604,5e1e4f52,9b099e9d,4db9f680,4935e712,f8402f66) -,S(87a4227d,2303f5c0,acace6e,96586b68,178dc65e,2c99583e,8e427ad7,167c4a65,5bce1d82,216355d6,5bbf33e0,9b3baec4,fb0befff,ebe48b24,cc01d454,7de6db8) -,S(a6576ea2,39af87ba,392a225f,bcec3045,8920b494,68c54ff3,92d2f509,519ce85f,deb950bb,6a767b3f,3603be36,6234480c,1851ae4b,1980f902,f8fec863,dfabde82) -,S(ed41c3a2,48285ad9,1642f6a6,feccdbb1,66298fa6,467b0ec0,ea256570,c8e343a4,dccf3578,aafbc34d,8ca5fb6c,b4482de,4b94dc65,a8d22845,ac800947,dc1042b8) -,S(227756ff,800f7eb5,4493181f,83050c32,9f27a35b,891a3bc1,ea5f0e89,b94e77e7,571c9345,e9e95238,3c7dc62,69aa0fff,46455825,a032f33a,154a89ed,e13a09c3) -,S(6f3b91f1,3f2d6787,454bc7a2,2ee780a2,3c251697,c0da9aa0,a03dcc3f,f03e2b0b,432b396f,c2dcd370,647eadde,ec058a01,53fac955,4b3f400c,435c4755,5e61afe8) -,S(aa79f0aa,767db1c0,3893c9c9,c75a1f8f,457f3f36,72c1d2ae,31e58658,a916fe5,4da2c69c,8033860c,14f8438b,8edf290c,5d02f2e5,153b68ed,fb945043,a6e6a1f0) -,S(48f2a720,df970127,2385a961,5a215d8a,3d41e0b4,ad439c9a,9d0453af,4699e527,11669dc9,26f70e96,e76178c5,7d698d05,b6e7da96,eef4e986,c4f6e6be,216f22ac) -,S(561d8010,a81a1191,3bb2436b,bbe0ce2a,6f1af6c6,fc064d57,59edaf45,c7f9781a,bfb2561,bc311bdd,707aee1f,af3d5c9d,faa9d564,a5121bae,9989665,b074f026) -,S(64d0fc68,6369a225,a15cefec,431fe434,1a424c78,85bdf2,51cccf53,9e266fed,694fdfa8,12f6bffd,b1c75baa,3b843d02,1b69cc8,20f2a8b8,69908a00,ac7050c) -,S(2b80d86d,341d05f6,218eb96c,fb227834,44bdcdf3,65cc3809,1bcba0ff,fa8b3d09,152eb516,2794fd0f,abf030cb,1968faa4,100e803c,e5b8046d,c36e3075,9317a8a5) -,S(62652ecc,daf7ff5,3aa255de,ecbcd653,7840a657,dd53e58a,514ec1bb,98c9b5b9,2a05c8cd,bcc4a512,1d2cafd0,6289fa14,178e91b5,b1fa1190,e4c7c13f,f50cef6c) -,S(f23fe7d7,69cd7bd8,5e0d97c5,4163e596,a0e7dce9,488e8f67,4ca6f3ca,81726ce0,eb1355f6,ecac2b79,dd299fce,c0f273fc,3767a3f3,3ac4777d,cb871a1a,99077e1c) -,S(91d4028d,1ea8e320,5718f427,b427c21f,4780a944,55ec46c4,2fb2a1cf,4772af1e,7a529f92,3756a212,24dcd316,bf9a3f6b,f5bfbc54,3b015c10,54ae51be,5c2e6b2) -,S(7a8fdf03,175969a7,80475dad,c43e5c66,fa75846f,63cfd62c,e82d2153,d185670a,b7b58ebb,fa0b2d3e,ec2a2638,accd965e,c7db6cf1,c847c1b7,9f0714b0,c1cf7dde) -,S(9d72d9af,5e9d7b2,7fb2b867,4aa35438,946c4ca9,eb9ea4be,e20b2eb5,e7cdb89,324214ce,d556acd2,3ac00175,f120d59e,50dc95e,96e6fda6,ff348bde,5ff7e701) -,S(33556ab7,bbf601ba,44dcb33e,aa5efc82,3c70f507,550f3d7c,22f4ba62,cf2d6bcb,a21d830f,233a657f,7857560f,c030f053,656aada8,f7812424,f38a2409,7505dcb7) -,S(e002b33d,93022868,60b39e1c,2820ad06,2063c344,bef98dec,3a9a0428,20e2c507,3133f829,1c81d970,f879d1eb,2128f21d,7540e135,31189576,191ac4bb,d83d99b7) -,S(9eeb1972,ffd49c0c,7982671c,59071b20,422a053e,394db993,8ef7b3d8,98795c5d,ae48763e,5ad78988,7a756827,4a17708f,8afdd8be,bc9c0316,73dd9485,319763c0) -,S(60f821e8,ad12907f,e445f049,141c7718,a495d1ea,3e39edbf,f0a73018,a5cb6854,6dc1b291,62b025ae,2a285e59,a5b406dd,927a743b,483454d1,20426fa7,50adb95d) -,S(5b8bcdc6,40f4a217,6d0661ef,f2ca5d6c,b1aa2069,557274c8,287fba59,dfd65a41,42ab52dc,cad04998,63e634db,ebaae018,c999eee4,c3cf05b9,4f18d218,23f21256) -,S(e764e748,4ec2a2ac,6843df3b,5316f29b,701b5191,778bda16,a23a20c1,69ed0cff,e1007e10,4ae52971,875bf7ea,9e9d9431,94c2e9b5,bc7b2844,7b7acded,de7d633c) -,S(37f0d948,48742a8b,e73ef1ad,495b88f,ea95f7ee,b343152d,85f9e442,771a22b4,bf960e80,467cf81,bc22380b,af2f57f0,d5938ccc,55f3f691,784be72,7fa68bb2) -,S(7ff13c43,7f2189a1,18b2095f,be268dfe,e1375a3d,f71e88b8,4cf5b94d,63b04612,10295e49,1f0a882e,aba663f8,f0202223,21c422d5,f3b453f4,8ab8bf4b,4319930a) -,S(74f6853e,f4a2d018,4cf113d7,62fe2a1c,33ff2729,5414a5bf,3f381989,551ceaa4,629f116d,37c1809,f4e2ecfd,19c2627,6deff6c5,b89249fc,d4f6e82e,58eeea79) -,S(d54d88bd,abdcc56,c1bb8cbf,cdaea6ac,16949256,f78d70f6,7a1416ba,b4cf51ce,996afb9c,5b36f588,812bad4,95c368da,f9e96035,4bb7dd1,3f457a6e,da159b59) -,S(a860ca66,3ecd7482,c862fac6,f6a7b0e5,f5f6bb26,ee950db9,2942fc89,4b6fbacf,3445137d,2047c17d,65b3cb88,8e1b0ba3,619db023,bd989a0d,c585a59d,14da7b9f) -,S(d794dc2,4e0e36fc,6f38fc8e,7a68cdac,8d547d42,b9667241,2dd7e6d2,c40f9aab,22a9a90c,10f1b80,e277be34,3c492125,24ebc477,1f838070,f2be48bf,cec3a7f5) -,S(7e28db65,2115f5a4,575293c3,d792fc97,9ea1adf9,dac468e4,60e5526f,6847657f,8025944c,16a12ac9,25e67f13,3835bcbd,33c338d6,824b1fba,f0ee001b,d79d66e3) -,S(d3f13a27,524f0c87,266f3d46,14d965a1,3865df67,5d20c5aa,99a4411c,dc6322c4,9a1025a3,845a4bc1,9f7cc175,9377c7f,e46ecaf7,53263433,baed836f,77e2e841) -,S(d845636c,db18d557,1759f6e6,bad6a60d,3a67141c,b0bfbbf9,33e628bf,8344c053,40de706,ef833427,80e5120b,ec6e61e4,a8a3726,32818317,729e60e6,3ab7e37) -,S(f40f53fb,c672573b,c020338b,71589d53,3709ac32,b38cb943,ed0ca0ff,e592e552,502145c,5f542a77,652a4ab7,d79791cd,e92f3e72,d9d0190a,2724e114,49b64e0b) -,S(2065a8bb,a0d61dde,921a0741,21ae5678,8766f712,bdb3c4c5,776af9e3,774120be,fd12cac4,a85d5b10,1aec6ee1,4b1301a9,950df948,86427be5,55f52736,3ca29847) -,S(a9b1e8dc,410466c2,df97cc8e,bbcb3af5,f981726c,2daf8803,ef06ef2f,a23e038f,b09dd4e2,77b1d10d,bfdd06e1,a42baf37,a5157017,ba026d98,fee13512,4a1c5419) -,S(c54ce1c,bbfa3808,f24b2661,793c3574,a58aeb0d,128d7e5b,ddcd98a6,d8c9bdbb,c1a2291f,d20e8a23,f4012b54,37a7be7d,5af5f776,bdbb2c53,193e07da,bc1a3212) -,S(41ad2d03,31f57724,6476d0c1,f2c46216,6156296d,8bfd3783,eec40892,835ec421,62777bb0,f8b6ba08,128f1727,9c237286,abc5d2a6,492b9c67,3edc903,7b0e3008) -,S(a8eddde5,eb761183,ef5cce4d,a7958b92,db28bab8,2f695fbb,597f6535,50048a3c,7f60d3aa,95ee5ae5,f4cf10ac,cb5729e2,bf89ba7,6b1070c7,ba385f41,a5912685) -,S(f1db8d40,2cee572f,6eb250bd,ed3d978b,1346ce96,d65291da,977b42cd,36bd073,9bdd0bdb,a546ce4d,774f79fc,3561c0fb,ca11f4fd,b46ab1c2,a7520913,f254f42c) -,S(55cee66c,7ebecc0c,7f22d03f,8f166b99,ec7b5e6a,776bcf60,b5f4d452,c861bfc7,772832cd,55b13c5,890c7ba9,96731ced,5a2e1c05,6ac89469,320c08f4,43159d36) -,S(61427868,7710db98,d4347d4c,aae4c70a,9efbfc7e,bfeffe5d,6f33bddc,4aeddedf,fe8b32bb,d0c7a7d3,b93dcb7a,99a5cc8f,e386bf89,7dcdcd86,ffaac641,6550dd85) -,S(9f3ac763,c117bd99,658f5379,119aa025,cd422ed3,b1ed2cc8,545d6f93,39baf4e4,41b2409d,cec0065e,4026e879,84b99d35,4eed93f4,15e8981,256e8734,a4eebb74) -,S(8510bf74,8f5255a1,8f408565,30f909d5,2bed111d,6347da9d,8da2a97e,751d4a98,2ed99b6,6af7cc01,37329730,1b0b63c9,f8732547,fc632eb7,7357e67e,df5549b4) -,S(d81fc0cf,9646ae0,7dad1a3f,e06adaf,1d3508fb,13af2309,c200c2e1,2228807d,cac833d6,c94e674c,a7aec186,42e4a501,ffbfed92,dfa1015e,c95740e6,57978cd5) -,S(32aa5e70,972a899e,e25e6c6d,e43c32ee,df07ebcf,e5ed13e,5095f7c3,3bb55622,38e82901,990a1e42,38639a42,66a93fb5,4368df0e,befe19a,7f234424,a8b68c0d) -,S(68f7b02a,ea38424f,decbbfc3,498c6193,62c732a3,b048800c,85d042d,b284f7d4,bef680d,90660176,f3d3d009,9f6cf818,a277dc5b,3d765a30,b7a4ee9,cf3bd46e) -,S(9437ace9,6b566bb3,87d9946c,2c32c06,f62f1158,dead214f,2b721c6f,b6e8888d,f8dee3bb,331e1e33,9963b7e2,316a1352,c8748f42,44463ffa,5bf2265a,243941d5) -,S(af40e909,85e5ce8d,dfb6d6d4,222d3c57,2ffae40f,53de2c06,55a74cc,70cd8dc5,2f08f237,3fc922c3,f0ed9d6c,b9538f4b,c661ccac,ea2f4975,50f47ec2,17d8e626) -,S(382e5a07,f1f236d5,ca1a68b8,f0fdb813,29e0393c,c375df88,f87914d,cef93c64,e24ee731,c0a88fa4,8ed3dba,87e97096,e0ec2224,dd657411,a9f1a9e8,2b0a6657) -,S(99fce288,c6ef1d18,ad630097,8ba82dd9,1c779a60,b266109a,288d51c3,978fe565,294c9e53,3cd42a54,c071d5c8,acb7edc9,897db8ac,d25b5f10,9eaf8dac,42a9c1a4) -,S(748326fa,c8dc9394,2de0a000,933dc18c,6ef92cfe,bac46939,f4405d89,627e6727,adf2d561,45581b4f,e706ccd1,8dc82bcc,14d76fa6,94ac8a61,a51d06d2,89e36d2d) -,S(43fef689,67074a2b,7e944b76,8f8b1ca,15aac3ad,c8f5590c,f1f02c3,afa82e90,5313cf6e,8cac44d9,fd548032,dbef3ab2,26e93880,644468bc,799c87d4,c0bc3f99) -,S(404341da,829f537a,c425050c,5ba93ca7,baa8a8b7,dfe51c23,e2ce7c72,43d57659,f91a0d59,bc35db64,b250adca,3cfbbaa2,2a82cfb4,d684e8db,e17484ee,af009f9b) -,S(3af33cb6,b4d553e5,50fd35f1,a0b569e3,eae05737,7b7d735b,545f7f00,d9acae67,42aa2cea,deab8cb3,b1ee9c3f,4b1b06df,e157cbfa,3912035b,585980bb,cf85279c) -,S(2e96133a,1da8a378,c138583e,86ba1de2,3450b285,3559a431,654ec9aa,1f64229f,3bfa5a75,4dbd936d,7a41266c,97472020,6cac86b4,d684bc1a,59dd1f27,fed8e76b) -,S(adc4b672,69fbb719,92bd6e22,3cf9ecb3,c9388b5c,45ffadd6,94c72e2f,b355984a,ed177eea,ac8cbd88,2a368fcc,4908ba4c,8a4054ae,3411d75d,b06939cc,72522a7c) -,S(68ac3244,49eac1e3,df997282,65a0176,bf6c6115,64daf79a,135bc6c2,5578b6e,407a75bd,b1e5e6be,a9b815ce,833c0be5,f5c462c5,c71a086e,59fbe0d2,5e7b1fca) -,S(5176afcc,b4235cc5,ea41eaa7,b657a77,bb383bf,aa71ef8d,d33990b9,9c2acab9,cb363792,9d249fc6,1c0931c,8a27dbfa,c8371574,52c40306,c3291814,ceb57095) -,S(4938cd76,e1aa6b28,2a89e883,8671e4e3,82d7bc76,dc4653c8,46323cd2,51d18542,2bfe67eb,6da39ea8,c8160621,158eac48,550c3730,664590a2,731247a1,399bc42f) -,S(9364dddd,dadbaa52,efc81971,75041c81,e7ebb48a,f20b82a8,125d85fb,a7fea192,ee568f7,53513b91,cf6720,2c45c4f4,181e855,ac0300bf,d7de30e7,317a6ea2) -,S(bdbc0937,243e563,df29781d,3b14d4ac,a664fe5e,70f3d9c1,39ef1b69,57839156,2a84b153,549c6d1b,27dd9ac2,1ab86f34,9ace0619,6f814d08,92a1958e,d137bb1f) -,S(b616b635,adf7b64c,43c4e242,32ffb330,bf28ee8e,48918093,9584c26c,28c82f2c,27fddaab,e5d47957,6344022b,68744822,eec7b937,d29b0631,93c7f6c5,6385cc89) -,S(55a3849a,50606886,abf6f0a6,5a3e657f,46031cd7,4c117365,8f27aa14,326f3cac,4a522c0c,17fcd116,61b11d9b,f88e0ad,c7a5761e,e01db8ff,a7bc3dca,a7976b00) -,S(d53e472b,439dc5dd,c8ff479,ff678dae,95b2e207,c92df108,728c3783,f8818542,3f3f7ecf,df3d9f89,1c723161,75a57931,4ebeadab,3c4dccf,bf2b834,c762d30f) -,S(1e27dd,f6186285,41f5d8a1,6587e2a4,ed38c34d,8393a6c9,fc0a7c07,cef36053,280b223,da8d01c2,12315c1c,ba7dd8d9,96d3202b,91c4eb4b,26c802e5,9494378c) -,S(b6d9d97c,64ba01fb,e8a9d29b,806d8a6,42413bfb,fbb4ae0c,10d8fe52,7ae6415d,894875dc,d912f8fa,845614de,a2b09796,d402c738,ca1f3c9e,c0796681,d715b8e4) -,S(2c97985a,5fd96164,e4c4d9d5,9a9fb52e,b2e6df0c,77ed4745,3dca6eac,7550756a,b3526bbd,de58e408,a4f45dd6,61f5c6fe,2f82d2ca,3e2172e1,c99d1fee,93d44c98) -,S(405deafb,528991e2,ef924f55,b7e4dfd8,185de449,cd6f71d6,53025999,4caae657,e959b7e,59cecac7,f813dc1b,a15bb71b,4a4832ca,54026e18,479d71d9,191c3ad) -,S(4276ecae,a14c0556,b4573b26,dba35226,4fff2c3d,12a3e4a8,4937ae9a,3f687bfa,7611836b,d3b335b,66f92914,6df0de13,d6ecd47e,88369ffb,6c9aa493,e67dfc71) -,S(6fd734de,6d2fadcb,d7b19f56,ae7153d9,1ddb396f,e0c1e51f,ae31fe80,8a35556f,aaa647c6,92865772,f31fdc1a,3b430ffb,e1647e10,3cd5d629,19bcc905,ff7ae633) -,S(4f0a22c,ad6ebf6c,e6b444dd,35a54e38,70017bae,eecc14cc,3f7ca88a,6d4e27c9,1386d40e,680060ca,bb46d678,d2be7209,418d6f72,d3917e20,7b833124,29b43ea1) -,S(873ccb39,5c10f57,6e50093d,44879f2,687d9321,441d8a7c,993c1083,ae7b0570,b261d029,dbe15f4,ff70ee42,36f558de,8984db4a,608d45f,4e28d001,e564c5e2) -,S(75d41857,5be3709c,5c732073,24f36089,b87532b8,e91db4e6,70a89117,9d25e039,47e29f54,fa62ef44,139db763,4b1c8f5c,e027b0d7,e1ec3501,1e8c6dfc,dcd1a105) -,S(b325bb90,cea81ac1,c79df75b,e7615ace,9b2a9d4c,fa1f4504,1a47e0d4,30b64b67,3024fffc,2005699d,5351615f,baee8c49,8a319a19,45ac8132,71c609b4,23e14a07) -,S(436c92bd,a6c7e124,5aaffb22,62036329,ddb8984e,624f2469,b30fab18,1269ee2b,2a9f90d,88c01880,62a152d7,e7ed5acd,33f12e92,4e36fab0,bc0602f8,2c1d3e3) -,S(c0105c64,4e51d333,c7ed28b3,c94292d8,6d9c04f1,89b3827d,f1f22fe2,99bc51cc,d73bc012,1233ba52,ef9727b3,1249babe,bf63cacf,ece0192b,5cbd618c,c48a9d35) -,S(9f2a01b0,46109d49,d11ee109,5e94c281,1cb6f76f,7773141f,632b3a9,2e5f3f7e,1e260290,fda1caa9,ea315380,781f633f,21c90765,2815251a,fa70b169,e4b0da58) -,S(4d805499,23dc1905,7fd35a86,feefb937,f2b621e,48946e53,b8390620,3aef584a,2cd9c060,d66be813,12a3fd9f,ebb9cbdd,4fc23431,c3e0531f,4a026f50,a40dbd30) -,S(76779423,b5e5acad,55137380,276c4033,a865ae5f,9ada0f30,dee6986c,444a1526,9a6fc30b,4f4c5093,b343c8d1,aa204ef3,7c2a6d5c,712ad8d6,39ef545d,1eaa9a57) -,S(1ccc1998,33f8b121,18227adc,2f27c3fe,8d328b26,684b271e,85f8368f,40378881,da21e917,94851bd5,a8859173,830ddd0e,988ffdd7,f7dcb263,f6755eab,e2d73f75) -,S(afeea14,e8306fb8,e69689a3,d12efe72,949b6b03,8c4cdc70,c95bc351,1f999030,cafbd04e,79378032,47c71954,d8c2a11f,d60e53b,35045507,8f6701ed,621e7d53) -,S(cefa268b,e551b02f,8fe50481,44920abc,3d03d97,3f2e9368,d2d2cb42,341c11b3,77440b02,64eb1972,91d2d69,ebdc1de7,66915a09,aa01615,e4001d62,7219d491) -,S(8625c163,58bfd43d,888ef97b,e33d9938,c62f7f2a,9e7b9735,26dd14ca,7c76abda,e1351920,59085272,3ea7b55f,49c4045e,2dda5ceb,c1a31841,1b6cf38b,b97bc1c4) -,S(43b8caf5,d4f72519,19630044,13bd459c,f5913edc,ff303fa6,dceb3412,f8e39c2,7d1df179,13186dc0,d7957f61,a3232180,21a6b50f,61a86f33,72623f5f,d3dc1a11) -,S(163fff8b,cece557b,6fd77b4d,e22e5b55,a6ed51a7,76dfe2b1,362040bc,9e7e4fe0,29204f73,5bc6428,3c510e0e,2192299a,7f6ed56d,1a0cc569,aa37f895,c0c4646a) -,S(fdbfcee1,69aa6724,b5839a55,e1c54856,86503b51,d1320b37,dcd9af73,2bfc4497,d7f75ba3,7af2f969,31bfa612,446c6807,a207af9a,17269199,77b0d71b,16b11a0e) -,S(f1981a9,aa585d6d,102b3a7d,e3509e0f,ed002866,b379b4e2,ba9d175e,4e5879ee,bad6366b,71a7cd67,163b6313,3dcd442d,24f9362e,5d0b9791,2a8dbfb5,74517e1a) -,S(dd3de17f,1cffd240,424096cf,effcaeee,87bf4d30,4a41d5db,6953102e,4b91853d,d136d363,1b9b968b,7c7d1a16,b2302e7a,7770e5ce,afae92a3,8f6e1299,6fb04718) -,S(b1d95fc1,4e35f77f,7e64f62a,36b26218,86397228,35ccadb8,39fa7d7b,834bdae3,75611c0a,920e0251,345b3213,422959c5,ac66c495,14d50c35,de7aa7ff,2a330a6d) -,S(1eeb92e6,75f25a35,9ed16c8b,51a5c130,d2210c35,ce954430,ea2cb3a3,af69187,cdefc1ac,40fac4de,e42ba496,eae80bc7,680e214,4117e6da,c2b3bc12,ce9eec45) -,S(aeef491a,fabae168,9d58c2f3,808b22fd,760e8607,c043c10b,591ed211,6fbb5ce9,b0db916,30810159,7e79aa7,82d8b643,d739bda2,c45ee36c,4f328108,4e55a33c) -,S(c56793cf,822c3da5,300c6c2d,cf06b5ef,413d51af,633ec77b,b9b68b1d,d3079e43,a423e25e,1eb466da,f521c5d1,6395805f,a2da609,fcfcffc1,2728add5,61eb2c0c) -,S(2aa824c3,c8c648eb,8bd0c151,b30452aa,c097bc38,a9f53db5,a8375631,25887e06,20aa4bfa,3bb2c5c2,a113299f,6c61102c,7586deaa,938a33f8,4a517dc,4ba78ada) -,S(4a0bb8dc,1833942d,9ae3428,ed493cb9,5716b50e,c96db120,c18ccac4,f6c3dd9,d0526d5d,c8be139f,53427e50,17cedc51,6b4960ac,bb98d4a4,f07fdf26,640b78b) -,S(2808616a,309b64c1,5d061adf,ae65711a,a561f8b8,345132e1,5b18fdb0,e476240,d2190f22,7320a55e,ad2dc736,671db631,9b18d6cc,b4d2bffc,cb4b692f,74eeaa0c) -,S(3dc4b015,13a95221,32ef431d,33435ba,8cf9e6d7,7e4ac75e,54848916,c23e7959,eaa2516b,9b13bc99,1f4b8ba,fa90a6dc,a007fea4,e26fbe0b,a2c5d1da,326d5420) -,S(473f6157,50af1d8,839ee0d0,eb5dfb8a,c14ce65a,e04e5f03,99fe8666,bd6efe6a,18d204d9,1b27527c,50823d5,222c4e4c,e3e193e5,a282daf2,75d2b43c,ffba8412) -,S(3b87175a,db1a5e49,1cf7565a,28250c51,9fff906b,ef0eecb,e8e50a7d,a190aaaf,fc58f2dd,16f1a5cf,1a728117,dcac3dbf,3a3963f,3859a518,2616b65b,59e96403) -,S(12f1b577,1410d1be,d0c4863,360e37d9,d36643d8,e0cf6fe7,8770478f,504174fa,be29140e,6b5a40a1,40559972,7e0727f8,ca904c3b,813897d2,bea089d9,dc2f17bf) -,S(8658f35b,902afb85,408280f2,3b4d98db,9526b57a,1e6cd0e9,37d8c629,ae174a3c,4060349d,47a69720,7d29e83,d8c82197,d32bb9ae,8c83879,1e09a7b7,1c3e7c28) -,S(530545eb,526d9657,2ce6cfc0,22e1c0a7,b9965c7c,3c2db355,cb5d414a,6c1ac8c7,99243b26,17f8ae2,898b96b4,1c3c65f9,96a9f8f5,83ff341c,671a2d5f,2d04637a) -,S(2e808732,bbab8507,e65936f3,fd1d1662,91ada8c4,c0d865ff,849e0a1a,5f08d265,96dbf7c9,53fd2f61,7e149f06,89b66431,88b091d5,1227a1a6,a0ebb140,18a79fdb) -,S(4272e028,b4b9c90c,44526fe6,b25f5e84,4b8baba6,34ceb2e2,33447413,cd5bb35a,6b4a4076,fc3706a7,50b0c824,93f5e363,f9fcdb64,9d683a1f,fc3bc2af,fc8470cc) -,S(78712f3,449d07ac,7f8171d5,42ee8b40,4761e054,eb0362c8,3b30cd52,6f9ac60,c7ff5ae1,38ca3c13,79457619,dd76061b,7b59778,79db2ca1,5b07ea47,7aa41bf7) -,S(be40166a,60ad9af2,d1bdfc7d,9b0660c1,640d4f1b,640ce485,8fb22eda,65d15a21,78c49afc,1d992bdc,b70bab6d,d3619305,a32fe90a,2f2b1b43,38d77c80,b208cf90) -,S(2fd5831e,6bd5a79b,35bc75f,92e83e4c,9acff5cf,61eaad7e,dacb149f,46d5e6ba,82f38222,4b6be0f2,f52318eb,7fe44a4c,4c0c1b05,8eae3f99,dbdea80f,a70ca3d0) -,S(32fc3fb,4574a651,472e0328,c15a71e3,bf9a12ca,15d341f1,c5102dab,2ee6de37,7e9398a6,760df809,e5eb57df,8fdc3234,eff1aa8,bef57008,c36e7953,c07f25a9) -,S(b9018d98,3452e952,7944f2fb,3354487d,a82f8b90,e52689d4,edb2a91a,a8faa6bf,e9cd0e4e,5c5efcbf,9ca25cf9,f271f9c,a2c46b4a,322cc966,e7789607,324348f8) -,S(a74ba662,32afb3e7,d5c22ad1,c792da33,f1bc88dc,244a8ce5,d4d582bb,b16ced23,444c5512,b49c2c63,4cc0328d,20f7321,a88db1ee,6d525be3,5d2de8df,cc381377) -,S(40f6df83,6d5e8c94,332174e2,2fa43556,d06f48a8,f52cfd69,820c2c46,2185dbfa,852c5b98,15ba4ef0,18f5d231,195fb62d,afafc08d,fbf9159a,eb5f6063,ca353424) -,S(e05800f5,f7890a14,6bbbabb1,27924cc2,e33e3c81,eb88606c,6bca020f,1aa71747,ab905ec6,3af1bc11,897a44e,89c2c2a8,3fb7255,c0e7f76e,8378e59f,1289158f) -,S(7b75dff9,a1afde87,be8528f7,9df63d70,e4df925b,a15f01c5,8e8162f0,89ee735e,bc057ff8,bdc9e37f,554a6ad2,3ebfeb2e,5d64adb7,69fa0082,2b2d4902,ca82712e) -,S(2fb81423,3b01e312,7ceabacd,a9ca518e,b1ab993c,bff855a5,20a96f52,afa9a0cf,a7e4bc57,b53affba,9e2cd875,9665cd9,215fcc,35dfc402,4d1db86b,9605c4b7) -,S(f346a33a,ec17d0e6,a10262f2,fd8185eb,f80a1fbb,f6b06bdd,1c04f18d,75dbaaeb,c09caf81,120586fc,33a6a0bc,97ef5cc7,56d20806,1340a1cc,ba9955ff,4a059e10) -,S(d128544f,a5f5dd38,62a759b8,5d538baa,63d112e2,f8c343a1,1bb3b8bb,ebf548d8,7893faee,b73f0530,bb67e8e0,9c2806d7,e303dd5e,116bc9e5,93e4dcdb,eac031f8) -,S(69046ec4,11c06822,59de20b1,a2a8f84c,58c56765,2ddcae,a26f533a,9c706f43,c17a9640,adc07d61,4a264ffe,272cd686,99b9af9f,6890cdc9,ac02c761,637dda8a) -,S(7b50f61a,9dd7b9ef,7af49c17,6ca5555f,eadf3b67,90998365,29379dd2,a3c85b5b,c08e18cc,bea8a970,7bc34d98,6b36475e,e2e24695,2304df65,bbe0347b,6052416) -,S(794a9728,9db4743e,c91a8560,e430b14,a7d8312,1fbacfbd,ec37a9bd,c749d3f,c57a5b9a,f0cb23a3,5e9b092f,386cda86,bf2f8242,1f74dfa1,837047c3,ae0d2235) -,S(fd8d1485,3d2fa064,c4682ee1,1c319a8a,49fa9b23,2cde9d1a,9a44b2dc,93b2f251,8cc4001d,f0121ce0,ad2119d1,7aaba363,ec45345,87fa10b0,c94a5043,f641b91c) -,S(7b5fbad,8105fe06,6962a72e,39a9a4fb,fac27794,e39a6660,133b9ef4,a6877557,b9b4c9c,1200d879,6013de67,958176c6,dc04ef69,b1021057,de8d3b40,564fbcd3) -,S(2c7ffc8b,40eda03e,20e64678,68959141,c66f01e8,b7cb050d,c60e8a48,6f6e41f9,cd0f3510,39aed3c1,56ae2b0d,1a117f78,c14a704c,992db297,60d22700,2f71ff7a) -,S(79533078,d81a6fe8,446dd750,b59ecdc3,8904f13b,48ca89a6,5644aa8c,9233de64,d7c95bff,77fa9894,74634aab,3b8f86e0,ee0bf92a,3a338fb7,f89881e6,e1fd746) -,S(be96c5e5,d3fb03a1,801a7760,16bf3824,aa16010e,884359b,d5e30658,5f13b214,d156346f,158d0c1a,2ef96a95,86cd8d34,20be21de,6997904,8299744,b40a5d9f) -,S(165c53d1,9ac89139,c063d934,511478aa,bc296cb9,7201dbca,fea4cac2,16a4fa02,4b002644,1e6f1369,d3603780,f33f74e8,42a812d8,b4e7ff7a,4aeea468,35f67348) -,S(508fb72e,dbd27f3c,76569185,a18af8bc,6242462e,cecffffb,3352ce3a,da5ccb5e,e1698f3e,1d53607b,4911423a,f2167466,a473a8f1,e2226849,f4dfe551,dfd14652) -,S(e9be0fb7,8e95dc1c,7b79f4eb,7976367,a85034ce,ea8642cb,19106dad,1d10ab92,b7867a7f,51f89779,a32a7b8e,273f9659,fb84367b,90ca3ff6,afc2cdac,7f596c45) -,S(e6ea5e6f,97116554,2de16c66,1f15d6e1,24aa449e,960b393a,e5337de1,d4c94800,bbd62bdd,1c235fea,60be143a,9155ffa8,204a1b11,3f19f4e,6e683c7d,e234ca7e) -,S(ab3f8a0,5b8f5ff4,149a390b,a858092c,9653d159,6d84bbc5,6e4a7a8b,fd54d7e8,41008916,311de07b,16c1b49,c6aa65ed,8baaebf,7a4e75b1,5aa1bc34,37483e53) -,S(515e02e9,52a347e7,5e0c5eed,a266242b,48bf33d0,70048562,c20feb3f,aecea1e3,797b3ef8,f6c35440,58517c56,ef5c6464,fcb63353,2bd6d2e2,83487a1d,8a403b36) -,S(520cf598,b3552fe0,a42438f8,55aefb81,3a3e10d3,f4985998,492e06a2,42ef46e1,c69de50e,2bf9658a,40567066,3cac0e4,8c8d2920,95ac1df9,9535b7e9,209324ed) -,S(26a8e655,4a2cf338,33bd27fb,d96880bc,bcc1d360,2a76920c,37075790,1c50bb1a,ba5a4560,5ddc5236,2a0d09df,3247a507,9c87e652,c4ad35f2,e19ecc9e,ec1ae4af) -,S(bd06a5a2,362ac91a,759dc578,dff3a3f8,102a67ae,a86ac11,5ddb2e14,bc1bba44,e8751dd7,153537ca,eec17988,98337cd2,abdfa554,52c597c8,61c364dd,78f49de7) -,S(ddbccf92,da0ab07a,e99fda1f,4a03927d,66b0bd21,f1e54fc5,afd4f329,35a0cae7,26fc18c1,52755bc5,d68dc3f2,461d60ee,b4dfc02e,a04b4779,6e7725b1,23acf8dd) -,S(650e1616,2a30c776,b54130c9,9fbbf567,32e2bdde,f667b09b,9b7f25ed,93c0737c,14972f76,429eb04c,1ebb0583,8c54fa0d,309fee09,a55d7eb3,700be0df,5801d56b) -,S(2920d280,41ad7365,cc0e33c8,7a3d6f3c,f9fec9c3,b00e5698,55ae3b83,8cf08973,3821fdd1,fe36668e,16f2cbd0,b2704fbc,24354f08,8ba19a1f,67d1b11a,b70c2d68) -,S(3842fb0f,1b26bfe7,535c9f5b,cee85ba5,6cd491dc,346829a2,a178ce65,c5294302,8e02342a,cb0e1233,9e638018,a125622c,5f66ab52,86a74a6c,28982c25,aa3a0fe2) -,S(9c21d89f,f1142d24,1e62c1df,e0481268,c2273d01,f153af5c,d31b3514,5b9b41ac,f5a924a1,d60e1eb3,72837535,4e252740,593c96f4,87328e9e,2a80cae,15fabdb) -,S(59320ba5,c9088701,f354a3a1,93391880,2829ce91,be9b4c14,c9018fe6,4fcd387a,610e48aa,705e2e7f,86a6a12a,817984a1,7bc60f9b,abc0ba9f,775f3446,8e3f3815) -,S(d800691f,83c2903b,1add209b,35d796e7,15b805a0,9bbe6120,3bf68a08,a13c46e5,21d194ed,bcb8bea0,cc35a9f2,328f1689,cdacc58a,73f65a28,56811e54,d96e5576) -,S(865588f8,66c21986,7b9643d8,7f1215fb,90fe186f,46478e8,522a5da6,724f6e8f,91a6b315,a7ddca8d,b4ecfbc3,9b55eb81,393f4c51,f573fef6,e7ca0c9f,cc551e7d) -,S(9dfe808f,cf7f574a,ddb251c0,4b053d00,8915f8fa,5a975479,d43c719a,b67aa4ad,4d40cc00,ea6720db,ff1f1339,7bb26c0b,281686a8,726fa430,bce0e4e4,ff01b01d) -,S(835f1c87,cf8d4420,72728601,ab6aef63,cd0d73a1,80f81f07,f5d57cc6,bab5ef7d,bac2d1d4,c8541f65,be0644c9,40a18f7f,d2c30360,2083a455,4d70a111,1c5bf07c) -,S(9562dc71,33c48e4,b46d73ac,d42db4c0,b0222c4d,dcd0e76e,b4f84969,348fa46,7cfe0965,96f691de,d358c00e,a292975d,465ef064,e9437556,40bc1d4a,33c3a0ba) -,S(21afe3b9,4237473c,dc032588,c4c1b7ec,853987a6,dcd1fce,2c48bbb6,8d0f3b45,1751c5ef,674cf88d,d5385943,b40a20a4,6d20cbd3,9876adc4,a4a4bba8,477e78a7) -,S(89809c4d,572cc5c1,2241ae09,fe1cee6f,71aaa292,c9ff8d6e,c3eb8a92,8e144ebe,462c023e,1710ed77,bd47d22e,e222598c,68cd7c56,b004369,a9356a47,ed6809d) -,S(b7c6164f,b9e175c1,5724c596,988b496a,b9f5b0d9,dd45d0e6,4a0f08cb,9000e3e9,1a13e8e5,a23b40a0,aba44bad,5cb4d37d,a6061157,aeab7a0d,d327242,ab2ad11f) -,S(62088450,24eef2d5,4fabe8f8,fabf519,72908ac3,23596378,c377c458,9719bba8,26216b3,a353295e,a1877547,b826c240,351f227e,293abcd2,e3967fed,30391f5a) -,S(dcfe82df,4049089,f3f8b275,120ca438,998fb22f,e11d40e0,9d09c4ce,c12ad036,388f9754,39b1c412,10014136,c3b58fe3,30ab524d,d7d3524b,37ce9133,5cb3bf3f) -,S(324ec5b0,12de7919,2f27f5ed,166344e1,934b3527,2b197d28,9a634044,5dd4bce1,99944794,579e12e8,c5c0c11f,a8eae5f1,88cb8cdb,3ce7814c,f89e3f1b,a3d3de0f) -,S(b3a70b0f,af96cb56,7dc4245,13ab7c6c,bbc38634,faa0c286,b81b9754,454a363f,b507745b,97843c90,170f8ffb,f731fee8,4532c1d0,6b2a077c,2aba5d94,189545ed) -,S(c4a6ff4e,cdf1ac83,29a1cdb7,b5165d88,2a1f1823,d1c38006,1b53144f,56187fce,6f7d0fc0,c08a7ba7,386f9a59,330996ef,b13d9d21,eb6d3915,4c8fb919,66159919) -,S(61d9ee96,1ef58634,5c4a73e3,a8c3df82,eac28aa2,6d740cbe,1833dcf6,d5a38811,c9e4a482,1700107,f2d4af3d,fcc74e68,8123b589,4da1c2bb,1fd926e7,11330892) -,S(67ecbd0f,4f4fe300,49390655,5289c9a5,cb6ac090,dff38502,75f7751,a84c6172,e422b1dd,10467cfe,921028f6,71cc75cd,2be5d8a6,75e644e5,d3c40b3a,2836726d) -,S(47f6c669,70898fa8,16dcd4d7,4553c644,2ce5bbe9,cda91324,ee3bba7a,868ff0f7,e56b9590,838bdfaa,1c2be1c3,95f775e,4a0b3982,d0eee531,26ec7ddc,9e3f77a6) -,S(e39ec9af,c8dccd35,4b155dd3,1d1750cb,ab096807,f89c8afc,fe61e6d2,e348cfa3,df3fca08,99158319,b93bac62,88c302f8,a59e175a,cda9fbf7,6f0ad59,8358088) -,S(2d1aae84,500037f9,8e08b64,341eab03,e0f1cdf,5a079b46,738746c2,18b3a0,747c23ac,8173adcc,de767d2e,ac156384,ddf40797,131a6167,c32486aa,12c89e5) -,S(ed1bbf04,d4570df5,8f584158,1fc47665,481ebf59,cb88322e,497d128a,678c2b4a,a40765c4,772da2d0,b3c8f107,22ec3931,ab3fc8cc,c28b003c,bea1a0da,279c8fba) -,S(bcbc3e1f,7bd268,93f377b2,eee4b76d,49a8a603,738de309,5353fde3,deff55f3,fb697a08,2f2570bd,1e9e4ec3,fc7f6c81,2a27a7e6,f7b8a53e,30da80ef,f59ef2cc) -,S(4f98b2d9,2f0b5d57,51ed3784,94cf4de5,65cf632e,982a270b,2746a5a6,3da9333d,43857e7e,437bdc02,6dcdbe68,d056784f,a2cc606d,7ce09a0e,12978a74,5b67e529) -,S(9dbb995d,d0667371,1731bf05,c8029035,2b413411,45318de8,2236df5c,87728582,c0a90e4c,6fbc0665,f8cd9fb6,fd59ea3e,f6ae9a16,9bfb71fc,5fe73e3a,4d665f86) -,S(83692208,1d099344,3d979c51,90940e44,5465624d,3a945c05,7885cd00,5ce6b9e,49be5e40,2e1d05e0,67b16279,855bc1de,6f0d8aad,35d8bc0e,142dbe87,33a14e13) -,S(f713e920,7a699b68,12d7ee9d,1475ba85,a6c56af2,8b73ace7,cf67ed6b,55650e97,a5a2c2a2,45012812,29fc71c8,103db717,48a51f88,61765d31,4b9ec278,3d0aab45) -,S(919f2d21,256ae682,fe514320,9c6551cc,d165de1b,8213fdbc,9c06578d,ef705725,9780da96,eeaac4e8,c96f3d6a,89c222cc,9b16b4c2,e8faad4d,96cc0136,a06021d3) -,S(1738093d,197a5ce3,cedd1fa7,e2a8ff03,959a6c23,6aedf9e8,9dbd74c4,d82b6e48,74363112,d16b829,d371a0c,f1b3bcd1,2000254e,196ea80c,a9d46570,1ee4a1d8) -,S(41242a81,35811b36,d4ffc40d,bbdeaa7c,cce36135,3c4fc9f2,d23191a4,b9c46379,7b894326,789f3071,374983c7,cd2a5ad7,e0ee49c5,e740dd33,817a31ed,97c388ba) -,S(894a6ec9,96eaa8e0,9e077b34,7b4f1e1,a387c930,a526c469,aaefc0c5,402d41a,a080fb43,c8e6bc6,388fa766,2398e096,b65032e8,26c5a9a8,47793924,4dcf5e41) -,S(a71f2131,3599cb7e,8c1058c9,52a5712e,661d01d5,79bc7ee5,1fbadd35,34ca5d5f,afe5b47b,663ebd7c,d788e0f,d3f963c9,ac63ee24,b7495e61,4a5d6553,9ab5f859) -,S(8f330e77,82eb62e4,4ea389f5,7f1c58b3,458c5d39,127d9783,6ddef8c1,27fa390,894e6142,bc359171,999489e1,1ed08224,4a46100,136fba84,e2b8732,e9bb626b) -,S(d2f0700d,6124c46f,a64cb709,1181cea9,34fe0406,21267334,c85ace2,cf05fc6f,8dc30ae9,83a95b74,2d800490,fbd8c290,bda64daf,f82d8fa5,e69243cb,43556cb4) -,S(c2478e89,8c075873,ba6cd5e9,6a730e1c,b6ade2f2,7fc9e7ec,93da9201,63f88c32,c6412063,9921d8c5,77dced53,76907410,82b1b4ff,4434bd,9a55b6c,8591ed5c) -,S(c5bc11a3,4e701898,d22e2920,2806c880,b24efa7a,c6d4ee36,cd440386,e4463a10,2c2b89fc,48feefc8,8bcb4ef5,68d16b44,cd7d8c7,485c9703,91c1c243,bf91003e) -,S(4b3930e8,21827b05,8c487bd2,fefa3458,6d0d3f20,5a2236fe,1b735d63,ac8c62b9,c38a29ad,c9b9941d,dc92a0db,4ce5f312,252c1f66,8a3189c5,595a371,19321c6c) -,S(fc646e3c,eab5a96a,1785da2b,1b50f7db,f0515091,76ade1f5,b057d05f,3aa3b8fe,b2014537,dbf2637d,6f683fb1,6af00d5c,63d4ed59,cdbdd673,f3bfbd48,e9574dd5) -,S(c0ada793,e2d9ed24,8ce307da,a6bebffd,3df2fc27,d2001dd4,5dbfc7be,c5f97a0c,6f3a787e,d40f073b,4965d52c,40700f66,da93f679,9efceafb,4894788f,5c9c7fd7) -,S(b1a45f3d,f2d45a,e21e43af,31ec3159,e8877d91,3efea814,b66f6fa4,a227b157,d988122a,eab167b9,f89db9e2,dd82405b,404f8a9c,a9acfd29,81c8bfa4,273ed248) -,S(4e19b9e2,ad3e421f,1b85a174,89d8841f,65672fad,9a17ad70,ca4fcd12,716d7a68,51412d39,59b158c1,3905c267,f5cf66e2,364aeb8,b66a11fd,ea6f5471,35db6dcd) -,S(533ee2b1,379a6ddd,6e5b3a2a,3a197e7d,eece722d,5c5b9c66,5e1be9dc,f3c09adc,b91b7477,fd0eabdd,bdc4047a,9bcad0cd,9da8496e,bd328fa3,a3ab20a6,3508a6d9) -,S(ccdb933a,816ac55e,c8fb97e1,504fa512,67408fd3,77aeeaf9,565ab66c,a2033b94,20299202,99b57beb,5d3817f5,26aae569,b490b24c,d5834dbe,8b05e8bc,89110de4) -,S(770d7c72,2e9964d6,84dead28,328b1925,287184b4,6e3abbdc,534eb87a,e0ea5873,363c73a7,bbb9b2af,3c0cc91,6f8ffe74,837a99c8,58b5464c,9f253764,e4a78285) -,S(d440dafd,b1d0609f,7c2354d5,74e711cf,852b364,8827fd41,88228ca5,98f71eeb,57d438de,c1aa78b7,c872cae5,c6803a2c,9844809c,7bca1a54,1be6f779,893aae1c) -,S(1602ca76,35ee0795,4fed3cea,d3e54470,41033887,2f060e19,990f3cd3,501b951e,1ea7f857,4b72d3e2,bd45fe36,c828f18a,5810812f,ab6e0936,a7854ed7,c7e32bd6) -,S(9c4d2a24,e4ad8226,bccab8ee,96960b1b,4722d2a1,88a429ad,f9d194ca,6687f7e,e3a4b46f,bf608018,ada2383,5c70fbe,cabbd446,78c9e5c1,35e91138,7d66b01b) -,S(fdf84be7,5be40fa8,db537848,e2fc8ba2,b7c58824,74fea4f4,6e8fcf15,f33d3bb1,2af57dd8,60ba0e6c,dc3606a9,a902420f,9283f721,70ce32d8,39c33673,5da1ff77) -,S(6083a785,fc5aedbf,34615139,e2f97964,ef65d254,a38251ba,203f8ea0,26eea81c,bb4d48bb,894fb656,22cd752f,6e3bc6e7,670a4bd2,64675035,8481561a,2c18439c) -,S(e03ad08e,5b4b9e01,5103e028,668f09a2,7d2f5254,25c6a985,6dfee667,6afffb82,f53acd57,1ab23ddb,d6b104b8,71d957c7,f254bc40,c37017ad,f7350e18,7a24865b) -,S(5a382a4c,88656b6c,4a5c8dcf,4052b1c0,a0bbc0a9,86289ab0,e212fd24,b852d9bc,912caa9a,32a10900,eadd0eec,423f710a,3e0aaba7,93f7b675,912223a2,6ba14f31) -,S(37dd526a,b5392b03,3bd05ff9,3952a31c,7bb0cfe1,f02f4f57,3b8d0ef0,c05d5ec0,7e329228,36595c82,14c8a776,15482931,98966225,4d4315c,c236c156,254e3249) -,S(ed4460f9,cd4bc957,aca653a0,5b6f0935,9dd7e19a,6d65c60,ca585ea3,ee2e1263,733af30e,6edd2b2b,317bba97,d24abd7e,41af6256,e7353f97,58357ff4,1a701829) -,S(eb01d9cd,50ff4778,b29e5096,93388ee1,12cfbc35,2c1b1382,7b3195e7,44a3bc3a,24877b7,99b7a2c9,db23047a,3194e9cb,91e5dd50,d0f1e252,b6f3bfca,f5b4d110) -,S(9fcfa274,b180ce82,14624545,22bb9289,1e0a8fc9,71949bfe,7aa25cde,88dc284e,6787be0a,12a76a23,9de45596,2a11f7f4,4051fbbe,3ba7dfb3,996c60ee,97be2b9) -,S(c8a0d869,87a7a854,99bd5663,30a07d67,70265d8e,cd3286ce,c9be4d02,6145bff,a65c64e4,af865e6a,893e902b,b06c43d6,10bb8181,134a4b71,d136b5fd,f42982a8) -,S(374294c5,932d3f74,a6e74731,6c6a84ca,dfda6d35,5edd914b,70b26161,50628735,ac47d048,8433754e,3deb79c6,7056d828,14d73bdd,703b299a,ca910180,e518672f) -,S(baa9e3a6,2b4bf099,1fde27ad,4b043b50,76a184cb,4f9a6da9,9b56ecd8,a2ab99e5,1e8e836f,f76043c2,c187ee45,7138cf3a,270e2d3f,5bc96979,c12c34cf,9205c63d) -,S(72f85ea,784a5ef1,71516c22,13abca1e,8017db34,4e00b397,4cb509de,a124654d,c78ec627,6cbc5072,fd75b28c,8d395f13,e84731f,7767448d,e06c0ba7,372968bf) -,S(c9173d63,bf5a1301,f0750b1d,e3cb7061,bb9cdd36,296b422e,d23513d1,10b61903,d26a6a0a,ceef78eb,73c6b031,a5455d2c,2a9c4ab2,d916b7cc,7b8e627d,6d581c56) -,S(865ff86a,58fb9853,8bcfe496,26c0bb89,e419083d,f21dbf6a,7b13e041,d5cd3f18,f0bdbabb,8118de57,bce9a90c,83529ec8,abfc2812,ab0088d2,8ade4bde,fe2fa383) -,S(3f14eb28,fd9852c9,bf4d4497,4d794ef1,c30f7748,5c7bb766,6f32fcb5,5ad910ad,e982971b,ec014b05,a9b5657c,a0bf45b7,adfe19d,22726075,80b42eeb,f4dc5217) -,S(61dfae27,c7bb68a1,ede331c,6499a7ed,e242457a,77e5a606,cea82e9f,f450d01,973739f2,c1e4ff77,cae3cf59,b481e730,5ebe8196,c5b62b9d,a96ae224,9b83efa7) -,S(e319690b,e944c297,f7c1bc1f,462ac3b5,a74fb913,9b963384,ac11046f,4343883a,3dadda66,538ea9c8,8fa0c02f,208ede8a,b6ef3480,82af4a32,2ddb5fa7,96d2efeb) -,S(f3db5e84,a9015b39,1617fea6,58143553,baa1975a,ab017012,38dc4243,7d9eaf9b,df55628b,c50cb2b1,be2ef193,a7f90e6a,3bfef4ac,63aaeee7,39907906,547d8b62) -,S(83a7dcd,58742725,8d17657c,ec64b5ed,4807db49,911296e7,10cf349d,c4fc709f,e5201a27,c37cca5f,2f7bf74a,fe000c0f,56643a5b,bafe9f91,de181e74,1d327183) -,S(b95b2363,28f51c80,b376dd90,a0f92d08,1e395132,deaa8f42,c142f642,3d3611ee,c111a08c,a6dbccad,2e784498,22816422,f2200f6b,bb24842a,f96c9502,13479f55) -,S(c3ff0645,921f2b9b,2fe590de,dfbac094,8475bdfc,a6446177,6422cca5,6fb549e6,e07ecccb,4b972834,e2711423,c0fba72f,eb0bb7c0,71a9e206,bf7715f2,62f03e04) -,S(96a37acc,527ee163,51c46241,1df94da3,eb0229b8,6a6e34d0,234bdcb0,5313c10a,46014617,fdd3f8b3,a67269d5,20a49680,9e5fa57e,76da4ef3,59ef862a,c58380c) -,S(b135c091,ec98a07d,b624fe48,4d336b85,62facf81,50346e2d,d0be2cfd,618d1e0e,24456a71,e8f2cc29,19f53594,6d7aaa79,e3d7dcfb,4af2feb5,ea0a2ad3,a23ec070) -,S(71d26219,81730b69,b0411b1c,f553c81,6f35a34,e09d086c,4500ba,94812017,c25357f,8915a2c4,98fe0d60,ca979ecd,8bd7ded3,ad6bc9ad,262db1d2,c3d3e7be) -,S(363cae8,ab2259ee,80283084,d98dc16,60c0934,68e3e854,dd86d9a0,d5e97884,756c60f7,c5e113d8,6e92df38,8fc9a1a2,a4889d86,f7440429,7661365a,ccfd8ce8) -,S(aef32d83,81ba3804,6e5b3305,6764ce3a,726c4e5a,ea61a17,ac114599,63f36247,dea5fc8b,d4ceba19,89640462,a957a8a7,44ca42d6,901716a,734e6f87,9aadb81e) -,S(65980f89,e4d0e342,d4b4fcf5,228692c0,9ebfed11,52d951c7,80963e6f,8c81313e,2d594cdd,a1f0b9db,7b3d8815,f7402a06,acba8e31,b9b0c597,8d2118a2,5dffa75d) -,S(f979280d,7e35cce4,8b9372cd,f73cebe3,6ee08388,e98e6069,fbeeb168,52329433,9181e8aa,bf7d4723,4cb851d5,6b3ca08,8c5f31eb,6b1b8c7,2879cfba,bd3ecaac) -,S(3b9f877e,286a13c8,a8463db3,b306ad62,c152065c,6708bbd5,68931e8a,2deb537f,12436d2a,5269a319,4f605dc1,4a34fcb0,445be9f4,5cc2bdc1,b96d86e8,b9465631) -,S(f2c70f82,1f86e94d,426e3e3c,e31ee519,f5a95b6f,38b663ae,9a6aba4e,f7bdc4e5,dc534655,4ba850bc,fef2485d,51e08c3,ab546119,49fee2ee,4dfc4e09,ff203b44) -,S(e2fb481,da8a356a,ab82098a,f622db2d,6f0a4349,2428dbac,922c1350,65801f15,5f735bb5,bb805980,d85ae242,4855bb2d,5de0c1f5,5018e1a8,e65bc2f4,86b7742d) -,S(d99e2001,33cf632a,f66c382e,d8ef862a,17092764,2c8f1f40,bd3d7bb,f0070324,d00f12db,cdb6e1ed,d190a754,fcbefdec,ee459be4,d5a46d69,afd6cbf8,4a4d30f2) -,S(dd765b6b,cb2dd356,f5965a8d,38108610,688fedc,eb3ce48d,352b095b,aa0daa,636258b3,58171669,f0dc68bd,3dff2a6d,bea6e5ef,20060913,66b12082,e2d7fa0) -,S(f549c14,f099a957,6267ad6c,3adc985b,9d0626b7,3f1f5849,d64ceb1e,266a9965,45a17dc8,30118c3d,28e73a3c,3d026afc,29ecf50d,198afdab,dff3d130,8f32f3d3) -,S(20d80860,90a192a8,51eddb84,f79b2882,ad7ce8a0,9374b365,61e6da34,427e8226,b48b6947,9febc104,880aa8b4,17344206,b19dd720,e5392bac,7e1954d4,a341eec1) -,S(b9f383ff,2545078a,c22cf9cb,83fc9e00,e9d37f30,e03ae03,5694437d,c1de2d7f,14f8b209,d1128a44,20dfb93d,3dc9ccb6,7ed22dd8,ecf5a181,2cd687dd,64a2996b) -,S(2ba0e5b,cec7a4f0,c6edd1c8,2d2f5927,2d97f4dc,3ecf353,8d3854aa,8d6f9739,8b10b217,6e56e5e6,5b99a617,eb71da00,3bee99af,b80e5ef7,3ca8c332,5ca7a75f) -,S(28b45a0f,3c308ecd,c0f7beca,c62d42b,500b704a,9af39931,b8debae8,8cef27e,9a3f95d,a17888ac,19eb4e42,1279c400,a60a0c1f,70a11696,4cf6943,9fc858d8) -,S(d8993bb9,e73af10,26ab41f0,9ec5adf7,437ce08a,4295cccb,283657f0,7a9ca3a5,ad8930d7,817534b1,e8407db9,bb8a608f,538b2bc6,9827a234,743382b,4381ddbd) -,S(77cd88a1,76bfed38,d7dd7152,32e2554a,a644b79,64a85f86,dbd6ffc6,69714e82,4394630a,42436802,1d0a0681,87fcc6a4,dfee0fe3,6db3bf2f,dac6fc58,34faccf5) -,S(d2557185,9c0fd15f,1f3666d3,aba99e38,89419099,ce7be94a,81ca1045,158f2da,90e94d6e,ac00b9d9,19832505,75bb2f,3242e7fb,fb429dc2,a90e3231,d1316cf0) -,S(f4e26c7d,4ccd80e2,7620917a,fdc72ca,94178f54,547eb330,77baa95c,d92a981e,c8ff014d,a388dcc4,c634304b,5973b274,785927e6,190c5557,773b9a0b,ef7d7005) -,S(da3a12a9,50dcd18d,c9e531e9,86f85a53,e7ce5bb8,8f2b5869,9830c44d,8c14cba2,7380a5b8,c01209e9,a1face4d,798f63ad,519a67fe,6bc90511,c763ca19,7e8c6b41) -,S(3565fae0,daf5d9ef,609bede3,6e19417a,45d8c0d2,59163f71,b4d9f54,43756fcc,7b1ef713,a88f9965,be7e6799,4a936960,c44f67ae,d5fa798d,8c0286af,e9da257c) -,S(6683fb20,d435a139,bd08c35f,adcc8aa5,8fbb8f48,7f9576d1,6f41d086,3a4e3de6,6a969f08,566afbc,dc98abfc,9d0d4d54,5076ebaf,efc9b966,957f1dd0,af52209f) -,S(900de92c,cbd4528f,57a72013,77dc1b51,7af67416,1013a20b,30d356bf,e011f508,cb55db4c,8799575d,9dea64f6,9fdf081d,959210eb,32b26bee,b903bf0b,80264c60) -,S(9d84bcf8,1be8a9f5,df2c6e80,d1b5679e,476e39c5,c30351ef,dc6b0b41,61c17613,8aa0cee8,cbc22e60,b71d9066,3533c2cc,a02b8d7f,7df93ce9,897154c6,2fae046d) -,S(6280fba,a3c3c8e4,4fcf0f55,a783eea5,2ebda748,501730de,71781be,abadd211,45b74c18,f0c18d3b,76cc1089,8741246b,202fd272,cdd0e866,5e1f4d86,ee527f5a) -,S(a4237add,7a5ea66e,8a1b48cd,7d5ef195,d90f25e5,6f2f148c,6d4eeff1,805b9024,d512d16e,632bd9ce,6cb1b2d4,c9a41e36,f9a2b83e,73fc8631,1e4dfa1b,b3bf71af) -,S(51effda3,e84027a,47afb48e,dc5c1937,9a685a24,ded2998c,c2b74422,b1e83fe0,346a9d82,cc07ed91,d785c6f0,dc32b62,e3e7877a,892007cf,c015444e,46001f19) -,S(87ac6bee,837ce155,29c005a1,6eca4540,de1480b6,91bc0ed8,90fed51c,de923cf4,9a9aa52f,1be1a33b,7280d0a7,3c19f5c5,b6baf99d,3c9c2d54,4a8d9bf3,a25ceb71) -,S(c8fd7df6,a3b0c0e2,5a931146,72a0af1a,1f995f1a,109e6e83,10b0d433,5dc2666a,3a853149,9b28c2ee,b5baf17d,dba8f57,3cf6e269,f4f21b1e,72bf38c7,79d239c4) -,S(890f9eed,47126c8a,355658f9,296b1845,b142eb17,4c2270d2,46293ba2,997e5a54,f294c38a,1c929ba4,2a9234d3,249690d,10a990cc,137bda3c,ada4b3,6d4e4b79) -,S(9329dbcf,45adc298,65c8defb,ee2ce008,a3474855,39826516,b417b9d3,bd47c86a,469a6cde,e1b0c094,f536fa91,f7617890,1be77c00,896efc5d,94cdd787,3886959f) -,S(6fa5326e,7b161c7c,742188d1,c47263a8,2f1f78e1,df83c664,2546c9ac,70660332,86cfd636,11879179,16d51a4,eac57709,5b8abab2,1024ce5d,35d64b4c,78559375) -,S(ece2e23b,8915d7fd,dab9e58e,8489b053,24eb1485,d18eff66,ee5013ac,3e0556aa,6a94e4cb,8fdf0549,a01621b4,438c2757,fe9753f5,13dcbb35,5655f9b2,ebaaea58) -,S(891b613f,413c155b,c2dedaf9,96d75e1b,54a5b5b0,3705808c,f575cdf,1f697ced,11904787,c1fb6f8f,8856aeb9,f7e05bae,f599b78,d7450bf9,13288e95,ff3f871f) -,S(b7bd8742,d1af6cb2,9b55a307,dd3c0318,6923be55,78ba2797,e38a7154,8d6231c,269e9a33,7a9421b4,cf45938,1961b0a4,3e4a0f6d,f6a0f10,2d7a831a,d7d4cd3f) -,S(7c6f5db3,1620a83f,b4388d45,75d244ca,1f38a0d8,611300b5,d4fdc9c4,34a16432,d5c0c35b,e4a371b0,3b85214e,f5e472de,e6c8175a,b140f05f,6e52b766,aa313f7a) -,S(18d303bb,d2bd6f9b,7f941879,6a23fbea,5ece2078,982064a5,e040c95f,c534ad3b,76eaa3dd,b73af546,7b1862c5,7b4385a0,28b03b7c,66729fce,94885373,1ed2dccc) -,S(31c0daf3,31aa6248,de302243,a768aac0,c8e27da2,c2b8e0a8,7fd74214,b49bb78b,e8e1f975,b77550bc,d404631b,12c72d38,55d3bf5e,5477a588,b11d57e0,e71e1ebe) -,S(940aa62e,e3bff798,327e806,b644a972,fae9eb09,dffb8394,61b080b4,708f715d,2853e12d,56898ea6,8e922497,3660a29b,37ec41c7,339b8059,2075c7a,2836c1b5) -,S(66db37fe,3bcfd7bb,25ca4a1f,b2ee09df,5c748061,1c3a6fb5,d0f079dc,cdbf9b7a,a6d37fd5,5d58ee33,73898711,69794421,9cd7a2f3,3becc8fe,761bcf83,ce603b9a) -,S(fb04bfa,a93a8ed9,3d755351,98895c8f,e90d545f,8eb1d08d,5d7282bc,66026e3f,e77f3c9e,afa2791,b4db2f69,3438d051,47edc983,a8541296,a8cae9a2,174e03b5) -,S(5792afeb,7766365d,e6b36beb,aafde8a1,8e556ac4,207965d7,9e18c1ca,63465c78,95fa5ad4,4b93db96,2c26d740,d2aa582d,da19b761,480ecadc,212452ef,cd885b40) -,S(186c0feb,6298e341,a2440465,547ad137,c56593dd,ed82b608,6824097f,3f83f8eb,b3b58cce,8375d9a1,e63500d,141feec1,38778c46,4be1ad43,7c63256f,33ac3b6c) -,S(d39114b7,c22beefe,6796b6ae,3f740a39,9e3c98bb,58b647b3,5cb23ead,76eae678,1df690f,383db8a3,86284ff8,f914925d,c688aa2a,8ec01a2a,243eb309,e79aa071) -,S(6195550f,8ce49ce2,f762011b,2e8feaca,509a0628,eaa93151,4c779616,721b39b3,ee8208f1,6d86fdbb,c75c265e,88090c85,aec112be,a1d803e1,211151d6,cfbeee2c) -,S(a8429368,37b33a8,2d41a26d,e11a0fd8,7af231bf,30d3eb64,73aa064e,acfd8740,18524c63,c0cf7a0a,b4e0eddd,61717f6c,3221a8f6,3522d35d,4eccee30,b6ed82c9) -,S(bf42ae9e,a64351a6,eb1d2c64,57d23481,f913de5a,d3c00359,5eb8cb5b,228fb202,2d74804a,34413cef,8d2cb488,ea780cf5,15faabd2,36a9db67,91549577,70a09d3) -,S(f1bdfcaa,ba133809,f915e0af,1a08fcbb,dd9cb3d8,b62f545d,6b71b44b,b130daa2,51fba8b2,2c7935ed,4241a87,f19c2b76,bc1a288e,3e53855d,c532f0b8,1ee382c9) -,S(7bf32637,4c6adf01,c7796f59,a11e5c3d,103e3339,a0cfbdc2,dec57f5e,69429bcd,8926e57c,a1fe7442,72d2e89,d037feff,df263831,e40e9ac4,8473336a,269f6b44) -,S(95b652a7,7f58b0d3,4c6d25e1,c294907f,a22a3ee0,f8e8478a,4e8458ef,37791c2f,e7dc4caf,b5bfdaa4,7185f0f3,a98876d,b50bfb35,a77a8b11,b522196,9f255845) -,S(d9f8c6ab,693f8058,8c73e2a,9221b0c4,c8f1d1bb,5e1e58e1,8468a48b,c74f50e1,cb38d48a,89c1ecc0,23e0e248,e1991ac4,3fbddf5a,9beeb53b,4cd9c49d,41f42a9e) -,S(43f62528,287e50,5cbf1a68,18bd99c,9f307e95,84e0d73a,f9fefeb5,b6dff92b,85fbb4ea,b81a0409,ce43ca05,3dfd5a1,9756fb5,f4b964bd,dc409efe,696c2ace) -,S(425a68ad,6d20661c,ca7d688,6bb9c66,f37dbf29,30ccc6da,dc34025a,5ea7a92b,7853cbea,d7816579,fa98ab94,875ebd2e,7ceebf73,20b50b2f,7e67f0f6,dfd2eeee) -,S(929ea74f,9b75c327,a7b26127,8828feca,821e4d8f,c5e308da,f3169a2,bf84bc2,f19e6cfe,d8c966da,bb070d42,3c62289a,5193146e,4297fa35,5908663a,a36b0578) -,S(83da36be,b1bedbd9,4a4ee417,f9faae5c,c20a9763,2c1ab2c8,b997f23c,f6d35c31,a91def1d,7871aa84,eed0bce6,12bf6a82,98d0ebb7,536d8e49,f6757a48,aa7a86ea) -,S(a2e1da8b,4318fad3,52c8c285,46f0a8d7,8fd6cf6a,b506f8ac,2d6746c6,75f2d5b3,584489cc,58b08663,1cdd1b7,3e61cac3,52c16814,493b611e,ffb94a71,2cd85699) -,S(5d7c1af4,4b257440,22b82ca2,9923a180,bb7fc209,1990b111,12061b6e,9eec4d2b,b40ca0f6,a974223,3a7b0253,9f0dbefa,1bf23dfc,cd59c747,c290f525,2e960b02) -,S(e2831933,6cce89c9,993bf230,ae4311ed,48fb0913,b5f35da2,b7531418,b512a75b,660aa9d9,8bfea898,810107e1,711abff0,88881efa,4d9d586d,91381b11,67cc2a21) -,S(722c1e28,498d3c21,66fb0f1b,f44e3ba6,181a962,75efeed6,ac83b36c,12426031,27a135d2,3b70006b,480c3aa3,bd057bfa,200da08f,f9eff741,6bff7885,4a1795be) -,S(f3cd71bd,f93f2100,c534d788,ba607845,cf6049e3,b94f5274,84e8608d,7adb9c99,b8e86285,db09b729,dd789293,7cf5fdc,989e00f4,5dcd4916,a6860bf8,d77cecfe) -,S(36341496,d986b096,5e5ad593,de6f88,67aa6130,889714a3,dc0d58b7,19647318,8cbeb984,a3f4bb5d,75cf77ce,14368b9b,77dfeeeb,7313f16a,8a573953,c7b898a2) -,S(a48443b4,3783c58d,4b7b2f27,17efafc5,e5ffe24c,a7c26bbc,dcbf93,538fbdea,33bd2bf6,9a64a742,c461fc0b,b0ae8770,9ed47a9a,26e7d05c,b71e4e2d,20c894a5) -,S(d4364d96,71f2876e,843dede5,9991ac5a,cf92268a,73212ab0,54b1c196,197dddfa,b30038a0,fd9f7387,fb37754e,9b050e80,e0f28596,d251d627,5149149e,880f6d43) -,S(ce277a60,19ac0b41,16b9d863,5a2555cf,30ef3408,f1a15769,91e48d0f,9465d250,5260ee90,65c89bc,7ef55fa3,d5f5d7ed,594fe592,322b7e97,965a9a3a,5654e710) -,S(587ecb1e,7c08da9d,75ed0249,b1281762,e9c71475,5c3ae35a,f7d66b53,c83117be,c6dda341,cb7d88b,b4a1b13e,313dcca6,1ec58063,376d38f2,cf142b56,87bafcb6) -,S(d87f96bc,69510c4f,19b84e93,cd8dd0b2,eee4fbb6,c5c5074f,ea76a209,e059f41d,a9b83947,b557c4b6,41952117,45ddff77,b5952798,66fb4095,6b5361a1,b463d326) -,S(af9f0d3a,78454c,eb8ca65,c9d7a324,312c01e9,dd8a00ad,e923f2f6,41fb0ead,2d3003ef,29a5ad10,20262c54,936411f0,f8082630,8506fcb1,e1848a7d,5d16482b) -,S(efd0467e,f4791ec9,9380be87,394225ac,637f906f,800abf9b,1ad5b3cd,cf9f017f,a14308d6,b0d16772,f36da4fd,d77945f7,1d82276c,ec4dddc0,de24f760,965c5725) -,S(e892235e,39ac312c,f30dfb97,97e88446,dc1f9a3,ef5cb8eb,d540c64f,d6b6129a,5b291ebe,7c055f52,b9fae6ff,cdcc6dbf,f84cad1e,4d35f495,4dc19b3d,64eb992) -,S(3158351a,542ff38b,12f82b5a,daa6ea3e,6e75caae,600b76a1,16ebe3f8,c9bcd66b,2006c258,a327481c,d324acda,b8ddc331,6a6aca81,44dba340,527babd6,4de975e2) -,S(f17bbac8,c0a7d2da,bbc5a5cd,4b28e96,4ab88639,546b2b22,d40c519d,25dd448d,14f9f488,e76663bc,278961f4,a33e11f6,98d6f5fc,1eaac638,79ccfae,1ab40991) -,S(9aa24eb3,44e010c2,d6fd3efd,fa03cfe6,aff67d25,2f08dda9,3d00332d,3065defb,494cc5bf,e60fff11,f42190dc,e607f067,7e355a9,52ccc682,6845111,322ac050) -,S(3f36168d,77711926,deb0f7ea,b6dad80b,8c755db8,e6705fa5,61285f96,84f1ccc5,486d57cd,b46d998a,5d064f9c,68511657,e53e544a,ee8c5521,87a1cd16,4121c6c2) -,S(fad18e89,219c449,87551525,6150e4a8,1fa2b23a,b6c1d90c,2e2f9152,ee8cd054,b285a7de,4eeff44b,751b4e51,f252f3a0,be7c2223,a715e301,23e9bcea,495ea7d4) -,S(1cb1cf55,9c56951f,58147d84,9482dba7,8dc6050e,2897f389,e30aa87c,519dadb6,b9e54a71,93a8e255,b2cf1fe1,80fe54e4,3e17470,60e9128d,bd527abd,c7ef1f97) -,S(74e68afc,9c8d9e0c,92675d9e,2fc12803,4ce7d22f,e31f5332,d18817a3,bd05efda,1d8442db,d55e8abd,aa1de803,f4fb1295,e9a8710a,3f25a242,7af9a5d0,b5dd786a) -,S(10336317,ec82d4e8,543dea2e,b8cb597d,3aec0e70,fb2971f8,7c5699aa,e4576de2,f2ccc066,5eae8645,54816dfe,c82e1162,226ab207,a17c6085,62925f5a,ffa3e021) -,S(b06a55cf,57668bef,6c51bb66,ac8ba7fc,6714c864,ca788279,2c8b759d,290342b3,7311f47e,5b526dbc,e4bc7833,e4c5b45a,190e3517,8f0f8137,2857e7b0,fb1f0528) -,S(af83a357,81306453,e576c819,d1cdacd2,689b0198,4f108d2b,6d9b8148,50df5523,14f52176,909c7e1b,eda13d20,7567f31e,161a80ac,112e4016,ad7c0bd6,20ec0ce7) -,S(f8f56d54,54faf536,3ea98913,827d57f2,a8983112,aa8809dc,594af919,3ae5c4a5,cc9d4182,bcb00a0d,cb73bfcf,da46ced0,ecee167d,fd7bbfc8,899063e8,d659dd7d) -,S(61aa26b7,415001ae,d6b3afd0,1c690177,879cac31,93a2e410,4148df74,733c4ea1,972510d3,697b93ad,60711b39,f3b3c237,771bfbc0,b7238e78,5a786707,dd179f23) -,S(781f196c,dde0f8e5,10ad45ad,6be062aa,1315c246,85d0ca97,21533c65,627ad492,6f3248fb,e7e61cad,1b01ec2c,fdb4dc4a,b1f4dc25,3666d4ae,27a88d50,c566d18b) -,S(c422d61,7f84ddc6,4483d55e,19228dcb,395f16fc,e85b5c93,2778f62f,ce8917bd,2f3cef48,deefbbe9,9477389b,be898cb3,90499b2a,615899bf,1e910e21,ed337652) -,S(c325955e,b56fe9a6,66555a32,72f637d7,3351b65,da5059f2,17748e68,4da4a4a8,3fa27721,2364140b,5b71526f,ad963d01,16889555,bdd42fda,c2b451c,fb70a3b4) -,S(e393cca1,49142f01,9be9a4a6,e8597354,e34f8d55,b400fa4e,8ac6b4c5,7e50b7a7,e40b69bb,44d6d1e5,22cc30f7,26b7a262,3e5b76e,7b190f07,10325a08,a99fb2ac) -,S(33e3686a,e4e69510,e939e53d,62fd669f,f1a39af5,c6179364,a190ae11,a600cbf1,cfe60b76,1306222e,7052b0f1,f799380,ed564d47,1f6418ac,dfb13d98,47f9154) -,S(1c35b5c8,3072f4d9,b3b294b7,69ff1b8a,ed2954cd,a013c7b3,34b53fec,c783b251,1c691a2e,782ff393,b0ac6c31,94f4cb0,f8dbd5f5,b51654a4,3914a458,6b855318) -,S(147255dd,3af5eb26,119e3d86,b2bed206,43579099,742c4ccd,974f7fb9,83e47fa6,5e0a0a01,7497235b,4766b44e,2fbe8902,aa0e2c2,69e7ceb1,d65c0f34,7a97f7f9) -,S(9524d71,57304a13,71d46aa,bc43986a,5ece70cb,ea008aa2,b8c97070,6436b237,a343af97,db30b94b,3d8d366f,1cd27b11,83c9f44a,75f0aa93,8c4932aa,52f6ea55) -,S(8502e7c6,e498d868,3816188,a99d0f35,79058887,dbeb3c03,676b3b91,be7481a0,28bda608,a9e18df9,c304896f,94efa7d2,46ee528a,6061afd0,322e052b,e7cfb68e) -,S(b89a0d8d,a21903a7,200b196e,46714aa5,ad49c5b0,8fc84de7,8e72ca76,2a3ad3b9,953bac1f,85e4f631,38464a99,e6e3be5c,328b3c10,7523701,c60aad8f,d57e6bee) -,S(49bf791d,67125d38,496d8ae6,ffcc25f8,97114f6f,9fcd5541,9876dca,4bdd7d7,6c2976ec,1b9078a9,a90f55eb,510b1a89,17efca39,d2fda494,b9013d07,7f4e05d8) -,S(c63bdf20,1ff5b07c,14273727,ff174322,422b6497,9ca8427f,5f868eb3,a1fcf05e,c4135e1f,1b5a09b5,d628674c,21ead97a,42957d31,92a44de9,b785986b,3269a782) -,S(58c8c84b,e9f85bd,b26f99b3,cde715b4,4b057d56,d5411c3e,a3000829,27ebe551,15de85b2,1467bee0,d4e0b0c5,114fdafd,410cf720,3ab35f1c,1eb2577e,fc2ec620) -,S(5fc5177f,e0b59e31,e4abef85,31f3fbaa,e3399bb4,126b6119,c7acac83,777cf9b8,adf27f69,b613fa62,3cff72eb,4dd10b4c,4009b73f,2cb885d9,57ab8c78,ca705fe9) -,S(1017a9b8,5116ce3a,498888e5,7a408f36,12a6e8b,b18f6961,d6e1d2e4,38902928,24f7a939,5e0d3c0a,579ae611,b733248a,640db7da,929edb24,b11bd617,3e573658) -,S(d9ea68f4,6af94d9d,232a5deb,c485fed0,d719cdf3,2afe4617,524958ed,751a2c47,e59f2193,db2fe578,642a774f,c4fc8515,f638d1c0,ae8081f,e9d3c0a0,fe20410e) -,S(61d975c7,e4d7e262,5b067179,667325c9,a32ef6de,a0bcbcb4,a825d89f,de6f7aea,b7a00d17,5a2d827d,37de6c8,667bebd9,da92ba42,4efeb706,54092342,e644db9f) -,S(2ff5cd3a,fefe0c25,bbb8245f,c9399409,83194bf8,f4599f3,101e9d79,b7f8d9bf,3c154b7,11964aee,5fe9175d,deacabe2,400350e5,3ea1ba23,20d9e675,5aac8fa9) -,S(cb438486,954c4a00,effd88db,29e0e61c,f9fef94,5b42bbca,8939e0a5,dad9e8a9,920ab096,41789957,6c3a8ab7,249ae2cc,73d1443f,5c650ad3,4da9d473,221de71e) -,S(9aaeefc2,889948cd,f59fa4ac,352204ab,46aa399a,c848041f,446be421,e0e4758d,8e4d2899,2ef8d6d7,3e1e118c,70729e7b,4e0bc28,69d7b5da,72df7b46,38fb3365) -,S(ace47cbf,846e95f2,9387dab7,6ed4e272,e32f6215,1e745738,69f2bfbc,720c78f0,a35997f8,37b8e86c,3b4377d9,71098d88,95d6a008,b9d65552,b1385a4b,49c53d3d) -,S(66610f69,1558942f,8285a9df,3081e431,5c946a5f,df958f03,b2ffde5b,c591850f,be93a2f6,53a8630a,ef037f8a,624e623,8f2ad9d7,3ff4624e,f4240cd8,d3495a98) -,S(db4bc8b3,7a12e950,706e148e,4f07df0d,a24d1de,615f2201,2dc1befe,f1ad95ca,fd55628c,c260a1a2,e56b95ee,ebd6b854,f548dfcf,2c4a6b99,7c4e95a0,a52c4894) -,S(a2a7aebf,58a9a58,24d5a996,da18958a,5fc23d8,452d13b2,b254d4fa,bcba959,d6440764,1642f25c,8b31a117,cd7ed90b,dcdc54f9,e652a818,bfa032cd,18bf085) -,S(2d8846f3,fa8a7a0d,408f8ad,bd76366f,4bf7bade,c255e2fe,595e4e22,cfe86684,2c0a7297,228185cd,3b21c10b,5c7f490c,b01bfe72,9513eb63,f2716d27,f0fbe19) -,S(27ba20c,a44821f,d6ebd41c,8c29e584,6237d8bd,13b3eedb,a82b5aaf,10a6fc59,68d65fe7,b511bde2,f922f119,4bb411a0,c000b4fd,268c2c86,e14279ae,9a63e42) -,S(c2f0b611,3a6bebe9,22ec3e97,a3962280,ab0b6713,76a6778e,5ceb73a7,e2894b13,27b90863,65989917,68a9635a,7f6c674e,71a433fa,ce4f1ec4,cd775277,89d290e8) -,S(8420787c,a0df74fc,5c81d19e,64f7ed56,8bc54a2c,ce1c5714,1706888d,bdf377f8,4a94b5e6,ad402877,dc4c0df,38c7fe41,d9e6e085,e70431e9,99c2b724,e35ae74) -,S(29d08c36,c45715f4,1eb5138f,a5c2f002,b4021f2b,bdc49592,e4242443,1f4d5f0a,903d61f7,2e81352f,582ce3b3,ead7b6f9,e0340c23,6925882a,cdb41285,6181bcab) -,S(ccabdbe,f68b6549,2158d4c8,91dd1d23,efa7a84a,a985252a,3a1e895d,757e5f10,94a0e915,2addabd3,d5adad5e,cbcb38ec,e1a045bb,9d7295a,92aee49c,a6f0bb4b) -,S(5bd30e4,9e2ba9a,745c6ebe,434b8d4f,1d8c34c7,6d478ffb,2871466f,a3ff23e4,1067b3c8,5980ea3a,dd1a4cba,8bb0b96f,ad988cc6,4dd8e206,51eee853,915226ae) -,S(eb233898,8f12eb2b,5369d9f1,56d754dc,8733745b,30967e17,697e69c4,4fa80493,c258bfa5,e993ff4a,4a9eb82f,ce1530ce,25fe74ec,2bbc2639,683464f8,a26b5667) -,S(4b44ca53,f01e1c64,8ff41a97,721e7c3,b0d62b4d,b15c5bd5,d84621c,4dee2ace,d8999254,b359a155,99e59761,f42639ad,27caf87f,ed4ddc57,203fef6c,9abbd922) -,S(ce5ef1f7,6cef6b65,35631e65,d4f47924,df370ac8,ce059a19,5455fb1e,b156f7a1,74c9b95a,a4dc212c,3e127bdd,266aa89c,a4773f27,5607dff1,4438647c,f0e50a60) -,S(563d7e99,40325aee,e66557d0,b14b7e8e,14f86643,de2b3300,1bcfa7f1,ef788bc4,ceebeb99,9878a305,1a8bd9df,bd6cb2f7,3ac18776,ea78df41,30fd22d1,bcdf37da) -,S(ff929868,fb5a1b53,6acca702,f5dc1e83,efe8cb96,f96a3303,d107c6ae,ab5dbee3,82828150,fe8fbb3c,f2bfe03a,3c79fa5e,67c33d97,b12faaaf,572b1455,6ae11969) -,S(1004e4ad,487212a5,8af57ea1,49e0edae,6aac884,2f488bc7,1b75a5bd,4a20204c,88d9a6,164cbc21,52d60ee2,7c8003b6,b39e418,b10c72d0,504a6a7,d7b8b2db) -,S(28dca143,206abca7,1c48137f,8bebd26e,6c79666d,ce164fdd,ef1ca7ac,8e141a25,ec1dea42,575e5cc0,804f6da3,21ee739b,ff244cb,2b299413,4b8539e3,88f7ccf7) -,S(cbb81690,a7e511bf,56a5190,b9366345,7b4fe8f9,64b8fb57,36df2067,28e1ca48,c2d2686a,5405dc79,d6a2deef,95a97813,4a434309,c5303985,f173015c,6571e5e) -,S(3e1e663e,378c44b9,b61d04ca,bfaf65fc,df6b59a2,ae83719,11b11582,978f008f,bbf4b3b8,2010fd76,70d23b07,6018708e,8f78d70a,b2da1efd,be668c9b,d5125d51) -,S(7f742a3b,9edf6aaf,cfbbf368,5a622318,1a6c3b5d,588b74de,c2d2c049,91d97784,238a4f6b,5cd25489,1b8aa5bb,41f253e6,6a59a020,bce98966,ed4c75f6,b7939e32) -,S(f073f95f,f6c809d0,9271eb48,abf35b2d,b760caa6,54b0969c,e327cff,f806f43b,6a7eb8ce,9e297e07,170e9287,7fc737cf,bf923cc1,e72efdbe,5b3b4920,6602746f) -,S(855f6451,5b98ef1,67d3a11a,fec74625,cf3801ab,75df42d2,1b33b1bc,c36d074b,6e8cb794,9990748b,f54a9291,e7ec374f,a31bef56,ed1812a7,7b2ef00,149938fd) -,S(f0164c7,f204384,d3235b4c,cc1bb9ed,bb10cabc,d69c02b5,aed1dfa9,56c74d49,872fc547,78580a6f,38792974,a64399b8,cd674622,659ec31a,91fea06e,77e27118) -,S(16e83238,e95e29f3,ebc297e7,fbbc77eb,53431f3,cc90f809,1e540457,aced09bf,3f3c0ff5,754630bf,88ec765c,a5c04da3,f6ca4ad5,e72d9c0,715cddeb,69c4f8b0) -,S(70d371c8,8b2e47a,47982dfc,bc98ffd8,324b6bcf,2f1aa2a8,f4815f66,dd4949bc,34cc039d,3c69b4d1,833375db,e7315340,bab2452b,2a82163b,dec73702,f4c8da46) -,S(db250b65,6848570b,5a59a2f2,d45e99d2,de1b3813,46fa6ce0,8bca0b34,57c27d10,2859a0e8,fde87061,d7ea8786,f5667aa8,b2633e8c,c52926cc,c5427d64,a7ae6494) -,S(d6ecb3fd,b1ef3350,a2a831e2,321cfe9b,6b22b38d,6a8fa0f,b256f2cd,ac73f949,ad83f35b,c1b5c568,49436cfe,6ff17f5e,8abc6891,e24f4a0c,524d88e0,6c3f1028) -,S(ee2059ff,a2c5bef0,646bf76d,ae2f3bfa,193b8a28,bc74cfbf,a96b48,921ac0d0,3a8f4693,15d6a6e2,2e57edb7,e5897039,153e0283,8d66b1ce,1814ac74,195379e7) -,S(6dd7fa4d,bc12da89,1669cf7f,b1024a8a,551d7281,83fd221a,7a0ca9a0,8c2aa725,67fe6a0d,fca0fc02,1fc89584,d2a5f19e,ce890708,490c79e3,cdbd43ad,ad24493e) -,S(15102e09,b966ca25,1a9b4609,16ca1229,7ab64d60,980582e5,e8bf0e4d,80fd6c35,7ebf61f9,956109c4,3cfb52ad,4e60078c,93ea653f,17c7328f,9120545c,48988be7) -,S(a0697816,4a0511f9,3a48efe1,de74992b,54679aaa,a99e328d,6771386,945e9039,92d24154,971add65,c40e6f32,a5b5fd01,765effb6,c8d64676,c9d97e8b,f857d630) -,S(ac925df1,3a9ce7db,18b9071f,f81880f7,c8ec97be,4b78a31b,27917d71,da0defce,6347aee9,abe9b2bb,1f1e3ab2,2792009e,ee009011,337fb184,d3f637f3,186acba6) -,S(74f3c7b4,e237db77,9229cb2f,1fdba8be,9ba990ed,6dd84976,ff92646e,55e21091,44e9a71e,a07e4254,c4dae620,9c437873,7c56187f,23f42224,3167e45,932055f2) -,S(78f0a024,f6a5bbaa,f3eaf550,92a55bae,73348e82,37dc095c,11ee34fc,3194eb00,54e9b6e7,2f758d54,23d5b9bd,b329262d,6745eb32,c93c2571,f86f40cd,1cfeeef9) -,S(83d3e538,92d722a4,8c006910,a22f32ad,2ff7bdec,d9bd2ea3,a2f315cb,550a1bc3,a4f3c8e1,732b23ae,9f21c03e,7c3711ff,687683c3,13455107,68278332,8d9a25d0) -,S(15deb2e3,f0f0b65,5edbb7d1,8d86cedd,7242a693,a271d853,b468d57a,52cbd647,7cb1ea70,8e12acb,6bbec5ac,26f513cf,51460493,9db6cccb,ba712561,a6f4a80) -,S(6fc5c841,eca2637b,67fcd5f1,3c3dbf40,3b00e4e5,270bccad,617c58af,ac54195,afc3fc7d,92f0f77c,5147ae41,8aae93d3,b5cb7785,d65e623a,391d6a06,1f82d4c4) -,S(154dad09,40e83686,d0942998,e220f8b6,bd106af7,beb9bc66,1f1a4c2e,29300f20,9a47095d,b2a357c7,16d8773f,18c953ff,dc0ed270,1cd881f,f3088176,e61bd7ed) -,S(a498ef6b,89b882d6,81ea0647,f83d53aa,d1fb39e6,6bba74bf,8008a43f,197b301a,cf4d289e,f723ad46,27edc96f,5315bc2c,9ad39c04,4e8e6785,222ca142,3f5c2881) -,S(5c01e4d2,465c3326,1828c45d,bbb2cf69,79cdb746,fb659a6b,44f0f2f1,f388fa3f,315dab9e,5e53f939,610e9729,3e686d33,e46f8262,5ddfb45d,46728b03,927a6837) -,S(d058f58b,255164fe,e6d60472,2b32624b,2eb523b,6c7f1e6a,7ce1c248,fb3fe505,21761abe,1bcb844,39645310,7a3dd2ee,28bb4dc9,93dcd0e9,a09d5176,1a7c6536) -,S(eb89dbf1,67c1352e,5ea2a7fb,206663b1,8c95d962,cec35412,3b9be6b3,51799ca1,9566074f,ec54174,a49a5f84,e4965174,408425f2,22d485ec,b020740c,74b08ef1) -,S(19ddc300,84dda580,db5b1230,b0fe9508,5575eb10,680181ff,ee0d521b,17b39cb8,6af18172,bfb03b77,db456836,b9617f05,bbcbcccf,f6ed2dd9,a9c6e734,c01d188f) -,S(66240aec,7e72f707,69560e0c,f31f2c41,9a8efab5,32f17f59,19bd56e2,93c41e13,16fad661,3600a79d,41eba5b2,d0721dca,afe94372,fe83b20f,7178e29a,e6f3949a) -,S(3c75905b,9e7c7751,9f4617ff,6010c39f,92b852fe,89dca73d,cb3f15b0,23f7a286,799ffb8,94fd4f3e,61dd489f,da746fdb,ae955eb1,3c8dd9eb,e4f73d41,2feccec1) -,S(9719a34,e765cca4,68ab3453,3c6dedd1,6247af51,b73295f6,8b936914,c03f10a,4d4e7f2d,ee3aec6f,71fa8978,f532e995,c0e1533c,5cf0b51d,f35d8f8,29cc10ec) -,S(e32f292e,e5c41e2d,bd262c45,eda0b729,713207c0,17fa5c47,c8bce6,ca550814,105716c5,5995ffa6,998f2209,b9d0b37e,f2bd78be,527f6c12,b707faf1,ef73a82c) -,S(76aa4115,595e7656,c76300d0,a60e3316,fd9c1b60,d41920a6,128e59f0,74a9dde5,f3ca0754,b6daef99,acd6e1e6,fb36d93d,e068c0d2,26b843a6,e7e111e9,9df8efda) -,S(215186c7,ba018fee,747c2030,f57d1105,945b021b,be053da,efb1136b,f0d6f0a9,62994ba3,62d9a8a0,7432690,689a859e,ef498860,3d52352b,e27e0f8f,d02e4de7) -,S(62e16f47,4d3ce3d8,a21f0c8c,875eea7c,111ca0f5,21c03f54,6bcee790,ab0d48bd,e9a8c8ab,99f916e0,4141972c,f60843be,72088d1,e044b27c,6a84b21f,c787abb) -,S(372b5966,8b00faaa,a714e7a8,2462107a,3d1226e4,988faafe,988d06a7,dfb27bd0,c6d349aa,6a53d0bb,185e0f59,a4c137c,8622be1c,5df205f3,4b090080,bf4e4035) -,S(b11cb8c,cd6302bd,e6005ed0,9a1ce2ea,a81fbd9c,748a17e8,fe1c139e,d2d1d725,29ec84f8,e8d627a6,b81a63c,4b13abb,88d7e5d4,9e56e2b9,a3f15f40,60efa38d) -,S(652b5427,f45d07c1,8cd9afb6,7d5743e2,836d78f3,528917fe,2a5c6162,c4a06d81,3e93d9e4,25ce53a4,915bd12d,4327e89b,64a7112c,5ebae53,35c631c9,64b2e5f9) -,S(c0812ee9,89fa0531,56847bb4,edd517a6,7d6d7d0,90ab5955,a59326da,f3833afa,2450338a,cf923109,d67b0501,3557f310,f3b0550a,8f1cd5fc,6eef8a5c,14b46c27) -,S(627c169e,fb0d9937,8ddd0fd5,a73afa16,2a317e56,7d957695,41e52a41,d9344ca1,11dfbcf7,75bafe74,eec503cc,22c8b485,90a17079,580acdd9,c51158f5,efd0cd7b) -,S(69916299,5b83ba3a,6bf16e2,97e8031e,74dc9054,c05ab59a,335a8296,d876a66d,39e45d50,aeceb888,8a1d64ab,9cb3b127,71269b7e,a14ca4eb,2179d762,4ee6d953) -,S(6693adae,579636f3,2332a418,7e49ffc6,921aa51d,852b5136,9a96c8e1,cc268574,ae73a660,580a4005,50865060,dbe9ab43,2f304ca5,506b9f4e,7e17f602,1456bfa2) -,S(ccc178c,7168ac1e,e7bf7579,f75f9645,5ca2b558,e1e709ee,de86df5e,5ebe0789,81c63b04,eddbf33b,432e00c5,9e76d319,fd1ef2f7,d6f31349,1f7a3c10,431a2130) -,S(d80687f6,89f7c28b,d6ef1531,c4e4b283,c6e5dabc,ad7fe5d9,6dc20d30,e1feeea2,71e24cd5,9d2c33ac,2b298946,bc90e0fe,d229720d,539a6f5,e128973a,9bd6c5fb) -,S(c53a6911,88f785f3,efc1fe1a,d142a259,cbda5f76,f3e9de36,895a8963,ffefcb74,7a225bd6,a348728d,951d55bf,257de9e9,d88df32c,ff2c4391,f4ddae8e,ce357cc0) -,S(d512c64d,1932fd1,5636740e,2bbd302c,3d8674e6,52a30d40,ce879145,bed9b7c1,52e336dd,3c7eca6a,469bc97e,a330fa03,1cda3c57,a4354ba2,acffcaa,a1e6b424) -,S(384aed3b,531098a1,99312d65,74b1b1bb,e79a8bf0,ea4f7a86,c5114fda,b32061d6,f2290bbb,2bbe7b53,eb64f87b,17a9e1,49356d9e,de3c0be4,28a4dc7d,709ef731) -,S(6db6c2c1,1fbd5b92,31a4e34f,ca2f9315,dde00dee,909b8d53,d7149c6,6e3cecb7,cb2f0b26,e1bcd464,6e6ee074,8efcd499,f535a8ba,f61a38e7,aaae3511,3c781649) -,S(6bc2f0f2,c0118efd,4fbab4c4,90c56da9,d66c0b1b,ec88e8b1,c8da967a,95d1ae60,a568f40f,24e51e2a,d01c13de,4490f34d,5a5bff13,e005ce77,94a59128,f6d871ae) -,S(12e4e92a,aa40ad9d,281316d2,358bb0d6,c69fac28,24114a9b,a96091d1,64ee29cb,f717cba6,b07eac9c,34b8821c,218519c3,886d5cc7,a22be959,54b3eefa,8819bb51) -,S(6dee0e1c,b887e155,e67996de,92716821,7874f9f0,a14c8673,1eaba91d,272705b3,28d9f2fc,23807874,9dd40ac1,8ace2dce,18ac3980,7c7a5922,43260eb8,ededbc3) -,S(f9d667ac,ec2120aa,50c2b6f0,810b54eb,4928bef4,779e2311,7d12eebf,d093f139,29c9458a,52d4cde7,e32a265b,fb537b3e,5a5fdbe6,ece9be95,b645b960,c160166d) -,S(e026f66,af79f4ea,52955b52,bca16e2f,b2cb05f4,38568c06,ebf1ca25,e6f5be17,6319ae60,3e733681,c8caa501,d7715b98,6244c1df,1c42d391,d8d47e15,a681df15) -,S(1ddd29c9,bbb37823,1185f631,23d5e1fd,39c6b03e,44e2a542,318a6f3e,8325ffb8,22d80158,cee2f596,8da360e5,93a2a86,ce1ed25b,77a4d66,a2e7592d,26c2c715) -,S(138f88f5,f9f46b81,2246373,6034958a,d5476a0f,348ca538,f789e980,9c799f30,adac6393,3e2de680,6fc38d7b,23ec5214,43ab505d,cedde216,6accf786,bd4e4aa5) -,S(b516a9a9,4630ba5e,7469d5e5,ee0f03c2,51bfdf5,a1983506,79baca9a,e6de6f6,9c184956,7ad68859,89a2013a,5a902fea,66d398e4,6c85203e,b7a143b1,90b42587) -,S(bb1a5499,548ee5a6,79500a49,a1466b11,9d56918a,735c3e07,31939ed0,2d47abe7,b946e966,2df43be8,6478e809,ac690d4d,b25398e8,de13731e,89867f80,63f8021e) -,S(394ee032,8be13bc3,ffa069f3,92b72070,36ad018b,503ed70b,9bbf9f7b,458faf36,3a494b0,dd538dc,fa3a10e9,70b83c4a,2169b4ea,255c6423,50f7ee72,40a6910d) -,S(a021889,ce4c941,606c0226,2b423afd,f44d6a75,483dc4cf,797b3512,8131e2ed,d8ae98ca,572b5a38,cd10a763,6638c47f,2867710,373af6a1,bfab6cc9,64b26547) -,S(99e2cf77,a0f389ad,a6c21457,d3e94ee5,95fded19,89c326da,3cef2e49,670f2572,8144a88c,a90a7685,ea3155ea,8fa5cc0c,c282fc25,532aa5da,84494b97,94810a1c) -,S(23c4b50e,80278869,b77c62de,8232a70e,52a4a3c3,4d0d6114,78989746,54e57aca,afba6a63,e35b15f3,1a24e5b5,844b0f3c,b247deee,a764b3c1,1075c3b8,c65bb0b5) -,S(ae0ea240,91b09648,6bd06ec7,ab6dd488,fd6669be,58c2e91d,e8486560,47493d5a,63e13a3,aed0b2f5,a11e914a,3617b1ea,abf62d4d,731eda05,62251d76,939aea63) -,S(d9e9ec51,cea0b150,28199afd,70fa86ef,dfa90e86,b9613831,9cbbeb86,c6573bf2,561519ee,f8dd5ebb,df47d4bb,c24eed76,5ff4342d,6ec6e537,8a2952e7,db51354a) -,S(e674a628,7472d602,8c0b888e,1dc86429,207e38a,af61d3e7,60708721,c1a44613,c145e723,eabf1dc7,f09fcef,1ae24116,1bc0d24e,9c96c83a,3c4e76e4,cdbb9e7f) -,S(19a43fb6,ad571142,42644af6,a3ce367d,329f44e5,bbbd8948,9368620d,944f413f,29a616f2,5f2bf4df,e516574,cbe840de,9ab9ee1d,abc86ca9,6413bfb7,a79a4095) -,S(cf1e1a87,32eb52e1,660186f9,6aaa4cac,9248d8ef,2738a6e7,5e600f3b,658825d,379dd9a1,8355ac8a,94a9614b,e3f51540,c17a76dd,3e3f853f,252f0e75,164dd346) -,S(342147b5,8a1ac1d0,baba5b2d,e924e7a3,b804e385,466f5ae8,29138bc9,5c5b386b,9d8792c5,8917aabb,6a3cbc4c,7f18d2b0,768dc9b9,1871bf48,8ebabc00,f51e2bf0) -,S(1c24e35d,35fda6b1,f6ae6b43,7599ec91,dff1fbb3,b3d26976,783c0539,a8b9af32,58591ff1,68290b12,d729c621,f5da504c,e697ef00,7d922152,9a76ed61,2dbe8608) -,S(d0fa4d47,a29e1101,baa08cca,73e00d6,660e2588,6e1b5cce,ee1c2a5a,9fb806da,918cb1f1,608f9e40,37a59bb7,28c25708,db898d76,a8b2e2b9,d4450c64,3606212) -,S(f3307ffb,7e72413e,2207918d,8a93f183,d5cc93e6,ae07d196,a6d22f1d,253b2499,8a44b83b,feffd6d2,78442d72,51929c0d,42b690a2,d91d99bc,c5dff056,d37e1f27) -,S(77e612a6,9931080c,7d910573,fe55582b,30eb4ca4,c7b7fe1c,9c4eeda9,b296097f,cc85c0f3,6f020bb0,9705f560,15268e36,bf61db2b,814b51b7,c958f1a8,656c26b8) -,S(fe3b3fdb,b8d768aa,8248087b,70e6d0de,592c95e9,b9816996,a3b4c88b,21bb9605,23b44ffb,20e8fc95,ad3c035e,3f52fb53,51291965,95fbda63,8a192cf9,43630e0d) -,S(e664460b,253050fd,8814a2,b2bc0f56,fd8d2f53,94673a67,9a76eee3,f7ae6e80,bf0a7515,a0a6351e,62bdf527,6974f06d,be87345b,438eea33,ddb980fc,788eec9c) -,S(b8ab3266,6cb96b06,a363d87a,a7ee820c,695b7372,b9341b,292dd0f1,d5fc35af,720da144,39ac9d53,c480dc25,5eb45ffa,b9e406c,8eb5bae5,1c145058,8120f900) -,S(38242b07,d1904c72,6da9ca1c,f1acced2,96c1c4a9,b37671c2,e529917d,a651b99,3d47a793,688603a,d6ddfc87,1c85a19f,e21ac51b,d292ff7c,69e219e5,7a0dea85) -,S(ae9a9354,e451abb4,454766fb,7eaac21,5982008e,6cd47d7d,df5a6289,27131913,46d291c0,7f99fbb8,2eea4c66,525602f9,6af5c16b,f4c31ca8,c26a831e,a39985f) -,S(59e59fd6,6a89a538,f5277950,816bf2dc,7070f70e,98d04b95,1b83a80,dab205a9,cec6b519,4d1122d6,dd3e39a6,fb3e80a3,2d829158,3ddf0bb0,3dc3086e,9f247f4d) -,S(59aade5,c117e92a,97ba1785,2e1ef3f6,d000620d,a8f82e2c,1d4272d5,34a8e22a,6a6b6ab1,bd9a69cb,181538fd,eb4a9e8b,eda75811,96ef31ae,deaf516c,e68c1cc3) -,S(f29d02a4,5b464774,fbc1bcd7,7caaf22f,12efcc9b,2a569966,b9adbe8,18a9f075,ba87956,5e0a1c56,fd03175b,a781110,3f34542,ded10367,6d44f706,7b8ab418) -,S(db630bf6,e9ff0092,eebeebb8,a5bc72e8,774c083,cafa0519,2e6d913d,112181a8,6b764e8,2213a7de,79b9abe7,edabf502,d9ac04c8,eb5a4b26,9d22b666,f657685f) -,S(45b9f064,71b848c7,48ff3fc3,34d425d2,57a71abc,27c4d002,dda26c77,1b09d2b8,c2119389,e4cecaa9,c0c72e4e,20c95cf9,1acb1698,c0bcfd42,f8620a9e,d781de57) -,S(d4919e2,3a278aa4,25bb55cd,2fdcde2,eac63058,4cd57f50,390c6a9a,1015ffb4,f8e9f461,950f17fd,8c46f04a,3a6f3c52,5318cb93,a0aa3f3b,bf90c02e,80e1c288) -,S(ea000677,2a76378f,3faa3c1f,c7227cc1,4b11764a,3c9a14c0,4f18f9d0,b55acc46,eafaf0b5,9a308182,8e6d07d7,2e16509f,bbf76fbd,e1473e35,18b795c8,87ff84c6) -,S(70b539a4,4750f763,be1145b5,b433e98,847545a2,8fc72986,2c17045b,f0d6fded,d5438ebf,18eb5feb,fcf6edae,4fcca2af,e0208adb,2f82648,2af428cf,bc761464) -,S(10b4a235,99ce2be7,fdc31f8e,ad91523a,47b8162f,8ed9387b,4c208657,25fa88d3,773ef1b3,a3943b86,729661bb,6ce6f4ae,e8c7165f,97a88fe9,5df9e027,3ccf9e7c) -,S(67d7633,499323f7,cc378c5e,2e62cc6a,5f34ff83,e11e6061,9ec4a404,d63b91b7,cd7616ed,60f0f4fc,1006dcf1,850807d7,e8730954,30db6761,cb7cbbf1,a9c2958b) -,S(5744c77f,8371057,61b1c782,1c9d9c53,14219e1c,5df80ea0,f772f9fe,ff157aa7,578459ee,13ec92b8,b685acda,a153f24,f6c844bb,e195ad58,77364ead,7a9e5fa4) -,S(7c6b254d,39ab709c,cd63c2c2,56c43483,183b1b27,25ca49a3,19753f68,6486ad02,5669fcba,d8662be6,2d12cde6,30102f3,70f7ef0b,5b347fa8,6000ae6f,497fad6a) -,S(8ec715c5,bda8f9ef,3b197ea8,a182a3dd,6cbc3b8a,88227e00,53a2eefb,b2006676,e59ecc81,aea7f2a5,4f659bdf,a317bada,3f8ccb7b,134ae21d,733b9710,335e73c9) -,S(fc7eb1e0,95d0b18,58d22b5,ad36fbac,1b513d86,2bb3c9ef,61b55a5e,985e642,7206dfc3,10056bcc,4071e9f8,13495744,dd903d72,2aa0d6b7,3fb35394,4b66c85d) -,S(4954bd00,308e205b,90c191ab,6262daf2,81939084,668c43dd,1ae998d7,e143f1dc,8efa802f,e67f72c2,5b4fc279,4e23608,7b343d89,255272d6,3c3968c8,7f26237) -,S(f27e6c84,f60858e8,2eb53d39,a6860189,9172da9c,e0d1ea70,9225effe,23de6969,90533e33,321f1f5a,ce37ff79,b4dd3109,a1efd6eb,de502aae,4dbdf58b,1e697c74) -,S(166f3aeb,cd040509,85df120,edf55c1b,f6eed0b5,fb24173d,c7d9125d,d0b2b29a,54b8de8b,c24b1cd7,8f89820f,d4b3ac6a,1588ebce,6de99b9c,81773ba,5fd32e20) -,S(c0797522,8dabaaf2,b46108c4,88ebd104,b0bfafdb,b344b5e0,72f6cb6a,f58f3cdb,bae0280c,704e0d0d,2d421b20,828cd00d,9b388f32,fcadb511,ad5ed4de,281a4a29) -,S(81366739,2085f96c,6a39c9f5,ff60b51c,4991a289,7106619d,1ab0de9b,34de87bc,d7b8599,2464c1e1,9f575cfd,de5bec08,987230b6,20d911d5,d6dd3d2a,8a75e079) -,S(335f446a,f3964e77,8f4985a5,c19e371b,876494b4,467ed700,482558a,9cab3c65,6e8fa42,24cd52c4,b78af9de,b7efa726,c26a94d,85bfeb6,fdb1b97f,674cbe6f) -,S(b6a34b42,bf5e4781,df14fe99,1a14b414,fa488da2,29314366,1ba83ecf,1e80d60c,b633c9f3,cd359dc9,2ce47287,670fe80e,131315c1,6fc17811,f319f1e9,82f88e8b) -,S(95f99013,a9e937e6,ff784b07,23287960,5eb4532,e16b3881,25a18012,17ee3ed9,2d0fa2ee,1aed211d,5b90915f,f3b2116a,28528f19,35b6b534,333b102d,177c08a2) -,S(9c0923b0,d681933,bc8bca36,a6af4058,682c5661,95d3a211,a1ef602f,933f6a45,a72df8d,a9a951e5,a63f0424,4974d74f,fb809cf5,fe7c24da,9c1715a7,2419c7d5) -,S(931cd34d,e32188a8,802b6a73,204eadf2,cae8d8de,52423daf,daf042cb,946657f1,d84b7406,d58c53e2,89ca15bb,4ba78db3,6bd2947,34d0ee9d,6939c15a,9f28b856) -,S(24be4b41,f845c43b,5fc594ac,90e3e4aa,b49cc79c,4b0a8408,1803c27b,ce62fe4,c6651cb0,be54ab0,78940179,6dca2448,3d9349ee,e45e78d4,b786a636,83861bb9) -,S(f19a51c2,ebff1d77,81b0e7f0,a29947fc,3ed9dd26,9f0b9cb9,c27c3f7,500c81eb,8e1cfe92,6128173f,556b3ec4,4c394ba0,201a4f93,e2db054f,63934b2,479a301e) -,S(f6e7e4cb,88ecad49,a1653a6c,5510571a,cec77024,2f490774,a8dd62a7,d6e16363,60842dbb,b8ae082e,9538e725,1a3dd7f9,8edabff3,5444719d,97134a3c,236c97b3) -,S(e7b7bb26,af8cc2ba,6e54e923,6af55e40,7ff704c6,1264cacc,74d96b52,81f2ca00,3abaca16,e20f74d7,6d11a942,415987c7,8da5ed50,3d781f2f,aba6d534,cbc3908c) -,S(c8acf1d3,89a29f6d,e0d03835,80a0a562,aefcaa99,b184f910,f2c8370b,bedc4c16,924e9b2e,2c6463ac,e8eda0b3,feee2f82,73050559,1071bbcd,72f6e323,31617359) -,S(1453b2dc,efe09d16,373ffc2d,42e79805,64ff194c,6b9944dc,b12d3cdb,1d84ae27,2d7faeab,7ca11212,a1aa9d4,a462c04b,8dacd2ec,1f7ee3b8,28fcdfb7,a26c6e17) -,S(ae92e090,b3c6ae15,68a12c6c,882d1b4,345f0a46,b9ad364,bc869243,dd533f4d,3f50449b,a3865900,ff63d944,27a0b967,56c00179,5b5f51cd,5996ca2b,19ad7abf) -,S(3086b503,ad8afe4d,fe2795f7,c972e0c0,8d6f040a,1be88309,606fee4d,b977fd06,b8631fad,80689ce2,7f62db6c,d6a56f3c,d3dc110e,610f3732,fa3f2c10,a4d588d9) -,S(7a17def1,e9c2b175,9944eb35,262908e7,c988f602,2440e151,928dfb44,462e2856,42171a1,f71ae8ea,d437a1d7,e1ec3394,b713044d,6c895930,2535787f,b93fcec3) -,S(97975e9e,b0698b70,995411da,37ce2a87,91198b90,e104476e,b86c4a77,dc5ce9c4,b8999b7,69b36de2,13cfc81c,c2fffc3,65e5dbc2,db1906a0,ec88e931,cd05bd41) -,S(839fa603,a2ec722d,1253328e,15f7d187,55ee80fd,b6bc7b09,bbca59eb,316d1b22,4e43cdca,1b33fa9,cf397ef3,91d40b46,fdcfa770,b2be8e9d,9ee22d61,6e12dfa9) -,S(ccfb8b97,7baefebd,eaf49c7c,1ddada20,861e1c0d,acba4caf,4e30f21b,ca3a05a7,7d9bced6,62579237,a348071,3ea1af91,256e9d62,1265fa27,cc80b5fc,cf75f99f) -,S(8f9f369b,3f325823,e8c9b16f,f2142ebc,3c6f7bfd,dd28c4df,63d1c92b,581cb6a4,114c7d9b,3f54f549,c10d93d4,25843477,9c297e2f,3f07b208,12335fe2,5771b12c) -,S(f0deaa5c,324c5ead,6f6f1cb0,cf1dac32,ef342606,3533435,65ac164a,ac8f0f2f,ef6dd597,e2203c03,f0ce0780,bcc1e963,621c1460,7a4ce616,9ee6624d,11c2eee9) -,S(638362c2,18c9e0e8,72dafa8e,fed86fcf,da5641eb,7cd01725,9a85103,f04fa408,3c224389,bff1fd09,338ea28c,7c9a93cb,32be8749,4a6c629,5c1c3dff,2b582877) -,S(49acbef2,64708117,a53f52e6,84bc15e9,d004baa2,fb3a756a,72d35efb,49871759,b678efb3,fa09158f,d1f9c74a,87a56883,b0a8316c,d4848ef5,1f35dfc0,8c4b5bb) -,S(a79d63c7,b718cd66,b393e70a,f032bc50,a90209b2,5f5b07c0,303eb8d1,1db618ee,ecf7f89d,2f6f9877,9b5e390,ce5837ba,49bc2b3,a7c1047b,7a7c852e,89f1551a) -,S(c922d543,f192f654,3445d3f9,c36a05b8,2ee043e0,92afcae5,a21b9b17,a06d0257,cf77d5eb,9e555f90,34ce1c14,63f7c4b6,a0202d81,deb02ddf,a26113ba,292554e7) -,S(dbb8f077,b411a4dd,faf0d89c,3dc20375,1bb20e16,2052ee46,915528e5,1f461387,a6c0d5df,91cc4ba1,cbba0588,774d47e1,7ef97281,63ca8950,7ff6b779,da12b7e6) -,S(dea21a21,eccb1733,14d76fcf,dc6109c8,88a633d9,645f86e4,e59ee237,cb18110c,a1390d1d,69a304f1,a2792ecc,675f2dae,1ddef908,2f2e3929,6b9a068,3933264b) -,S(f088ed85,750dd58a,cd03b3a9,93d88760,34f50780,985f7552,114f957a,ce8904a1,b810e652,f596cb80,c369f61,f632bc3c,fcfb1fc2,b906acaf,c1f39d02,5e3ae4dd) -,S(b85da431,16b898e8,56fe3c18,b60a48b7,c2ba9f65,ad67c31d,f45ac3b6,608b774c,357d324b,474ae7d8,97398506,c550a1fc,5353a00c,7e6f1245,c0f57683,80ac9e1f) -,S(eaac0d2c,276000ff,899dcb3c,61b41663,70123276,14585bea,7704de95,d164514b,aad696cb,1af2f12,1ba915ec,64afc13d,a689719d,8f188424,25d6068e,9bb06a69) -,S(7a3cfc7e,51fbf61f,ffed3430,eb9ac40,c84164b0,21220837,29f20ed8,eacac977,9015b896,e034d2b6,684f7352,185e959b,5c45406f,6187930f,82f62269,d3ba70a) -,S(5a9def12,e06f0ac4,35b9f853,53db864c,77288050,c349ed7d,a8d8b109,b001a856,b63b74ba,868df816,9dfc30a9,1efbae1e,1617a230,3ed20239,9ecf5798,5ec4bf99) -,S(b937b3d4,287a0f84,5323cc72,95b4a201,ba9d97d3,2d968533,7caccbdc,ce8623ed,6f2ad251,a66e5ff0,77384746,9208db13,2a396dc2,17e781ce,9aa8d556,83fc0adf) -,S(d44f7fc2,97e079f4,ba0689de,dc743d4,964c6ab,8c34bbff,f95bf22e,b7d3c209,b5afe3b6,f6b02542,e6ce811b,f4bb0fce,79e7916f,fed8845c,dd83de07,9320a2d1) -,S(5980fbb1,6be7acd7,b090a2b1,c83dbf80,9148cc99,75fd6834,edf564c5,50fdf2f2,72340269,8d22b946,ae51c9c8,33d5b44d,ee884a02,e12a6d4a,23957483,32abac9) -,S(94733aeb,dce57a89,16961f41,3eb04b5e,71f0a055,29baf93f,c9ff178a,12b70511,e591b62e,5cf92ea4,306e16b5,acc5958d,a5516bf5,7a7dab17,db38cef7,44302c47) -,S(1172b006,3d5ae491,8699e756,75ddfc59,fb5cc8d4,f332ce72,f99fb99e,c9799d96,2845be1b,b97830d3,f9d04a3b,36ae381c,5654bef3,f3fa8516,3a7b9738,ed867ef4) -,S(29afd093,5ca567f7,eb4cc1c2,ebbbe8c3,bc405691,b41a2812,b7c71312,81bbe691,77e9a59d,c0aebd28,9cf2960,ebe7fc19,236c1859,7882df0f,a8e6e0c2,6d92b821) -,S(191c7ed6,72c36def,576f645c,6b475eff,793119e3,ebc3a29b,71eee3c9,cb52a635,642bdce7,90d0f104,54ebe4d6,282be83a,443f8f44,faba4c76,5b1491d8,c7c83210) -,S(237eff13,89c20d30,9902a738,fa4543d4,c2a4a2b5,6731603,500997bb,40d28eda,973d696c,ba9eb05d,73ce7491,5c1cf3d1,5a998608,7ce85854,f7bdd157,3d5c7394) -,S(d4985b52,80673074,53ec0edb,f02b9d4c,b1ce9a0c,af7c675,77789b8d,f3b5ab33,ad8fa145,94c510a7,830f3353,4ac94a98,cdf2fa30,b6a1b572,9222969c,e27eb1ea) -,S(3baed9b6,25f5d0b2,6e0132c6,20a9015,f79bd8d1,8e5ce170,20fed78f,a2238914,6ef88df1,3c7a9023,1180edfd,d041b950,3ad89f22,4ec557b7,2e900bc8,fa820c19) -,S(6e2298a6,102268b1,af97bf67,c0aba783,5463165b,1df8a824,530ee5d7,86d354f6,c3864e52,3bb5cfe0,a64adc7a,9e8926e9,876516a4,c83767d8,5ebfc39a,e125c19c) -,S(f9e87f15,2412598d,775131de,abbd0272,4d658849,cb60aac6,92280e63,8e835e9,e843a3dd,a30f9685,70fcf86e,86206c22,af40ce3a,3beb620c,aa167e63,271d95ac) -,S(f9925b7e,80b8b8b1,b5c56f80,74bd5ee1,9e419678,2c5a33d2,c59f8016,56cfbb0e,3e2fda0b,50aa7671,5810a8d2,2d4778d8,66bd2515,acf87b79,7b2f4875,dee19719) -,S(6fc34efd,5d11ae35,2cca3254,c5f8a040,52b81357,556d4d67,dd02d22b,91f4e49b,f14c656,ec946492,a6af3f2f,56fd7355,71e41b2c,dfeda7bd,ed567658,202f6e61) -,S(ab504458,4b38c846,e282038,1f02f55d,fc6a5648,1b1830c1,e4ee94e3,d11af8d9,4ad3821e,3f5219c,aab31787,2a8fbccf,f0f445d7,da30f05,d9523f55,13eee3cc) -,S(2378d11,716b6d34,85bd5a57,5c5b2c96,1b817abe,e21b7d45,38244933,5ce7e7a5,33682ec0,8c59a158,c4ef12bd,d2a46d31,6abc6dd4,f81a1fef,5be40577,4e03fab) -,S(cfa95425,8608d9b,9c568a1c,fd4b078a,ff49150f,a4681324,ac56b6e9,df569016,e200a3ae,2d82ddc2,a71767e5,842ef30c,86cd9b17,7c5e52ff,ac316e50,1e7e2) -,S(585542d9,a3a582a3,bde74fef,112924c4,e00cafcb,61518d87,f524211d,bdb98993,2035bc19,7a0ea2b6,8d1d1333,b5aadc61,c9dff2c1,e4dea034,1539ff15,9a3d18ae) -,S(fab2433,905e5b46,e47103f2,e353d503,cb141e61,2167cb4d,34946a5c,cd2c06b,7097d735,3f17734f,8eff6993,77916c9,884f67db,42f7a96c,62a3e1d9,9e341547) -,S(b10db548,be55521c,de5edc26,fa39716,154e365d,a1b8b7fd,2265d78b,7edee8cd,389efe1c,7fd8b4a5,4a42e651,b5c06a2a,7c153664,e52ef30d,90eda2d5,9e9690c8) -,S(218a8a36,273fce14,85c0c9f7,1910aff8,64910b00,6254af75,e78a6b5b,3d5c7bad,4a1984e8,e90d4695,b8dcf34a,55eaf568,b0fd34cc,528a147c,bebb052a,8e6e8604) -,S(e120bc22,fe6dc81f,dc3ead1b,a2ca966f,c5702ec,479793b1,5f0ebae3,b6c5ff3,9f92f1d5,e8aa56f6,1ef20685,c8085782,be180658,c7d2b9e1,c020c98e,cd425835) -,S(e83373fa,f80d4560,5ac4da9a,c9cfa220,b2a2c656,26857035,a228c93b,495be15f,8b915652,3c532657,7945021,d6c1b1a6,3b1fd090,ea93cf01,90fdb791,a2397a91) -,S(b7d8a393,a10590ea,91d2a495,eec07262,f2f43e29,74f7b2e5,6ba6ee92,17e3e74b,4ad6671f,58b2c7ba,7a940613,5986b3f3,5a6e13ec,8243b0fa,c8bec130,2afbad0f) -,S(75a5ed46,b2103f5f,ee808803,bf419bbc,232cf5d3,84955e8b,1d4fbaee,5194ca35,51b9670c,4c65e969,a5a56e15,25f33dc9,458c317b,6faf484a,186d52d1,757e4857) -,S(6d8d67cb,c309ecc6,3c1e04d4,aa42683c,775d5f32,51111500,9166c574,b0dd66e4,e127b8c,f431cf09,5939712e,c96d299e,efbdeeec,eeca3d2a,9f6b3d29,fb8f72fd) -,S(51a6d684,463065c8,7d3e0fee,ac72e4f3,1e5187a4,dd14d59e,ef71ee93,85fb229,7fe1069c,b384178c,ae2241fa,6886e1fd,286347f0,d2488dbb,f4d6eaf9,e722a90a) -,S(5140ba9e,81a272eb,30ac5c96,a8b054bf,870b1785,9519cdbe,4f2e6573,2a56e6bc,3b6a2c0e,7421eab3,147b61e6,d8252326,1819bd94,9e3c805f,ca2a12b2,e13599a9) -,S(b94c7812,6c60a3b0,48b28f47,f9d461e,27ffdf7f,93a3ee70,ae38962c,8060166b,bab7aa94,385d224f,f20e7c60,7f7f11db,4ec3526a,c226cc96,16af6a3e,356208f2) -,S(45046678,76689fbc,a94ebd79,ddb5d655,3e97b788,c91cee0,b62ee75c,1fd12ff3,635b3d75,a0621530,d7ff26cf,f1878d52,2864a6ea,e82b220f,d35ae5a5,edea1895) -,S(45f4025d,7b88ddaf,e39566e4,27060b7c,ac59ae7a,526ac3d6,a489424b,d677a54d,d732c322,18307ace,354ade14,21d13438,ac4c7c3,5b5021a6,cea9137f,b47465ac) -,S(c6e8912e,a197f39b,817b743d,deb3320b,558af332,96e0ebb,58c258c4,f1c0d5cc,6e0c8ecc,fd97ccd,deb08f4a,73ca13cf,b48d3633,afb74139,36550e0a,c23f04ea) -,S(6fd13fd,c7d3809d,6a3bf6b1,5208d0ab,5f476e99,57a7fc71,29824154,a05a7dd7,95922641,32be31b4,c34ea614,df6b8c1a,c386dbc2,1318868d,b40869a7,17b862e6) -,S(54fc0732,968b0207,ea2c115f,d11bfb57,b9b28164,4644d82f,45af1100,6b63d0b3,318ef9f3,b2173c45,bba5ffdd,8345a08b,66c8e183,80ef9dbb,b5d80c1f,15f95bfb) -,S(9e6ac718,6e09f698,1f384cdc,b9c48703,a8ee3726,d6d8ee3,a10499f5,e17731e1,95b4c37f,ec98faca,b41c628e,12f606e,79829b17,96ef3dce,c4aba99e,3882bc0a) -,S(85732ae2,eb7944a2,6609aea5,607604c4,c30f25ca,c365fb2,e01c7600,40542ce6,928a62fb,b082f38b,52890540,7b20f9ac,1f4841a7,bde217ab,828780ee,94749fcb) -,S(3ea5ace,80e47aa1,9bf1406d,3559fd50,85d38504,93752563,de66393e,37a652a1,db5fa543,142d36f,fcc1cc8,36b1f4c4,e82d4980,f2b277c7,bec53324,fbdc8e9c) -,S(7d40f7ae,f1866d87,8e42f9c8,d5afff76,2a427567,f6130f73,439d67fe,d14be54d,5bee61f5,31e4ebb5,679c9645,d565cf,f93b391b,f48c5504,a5054e23,47859d2a) -,S(3dc80cd7,478ea38e,1d6e1e41,aca892c4,4e4d8339,acd72fb4,c27861ae,3e7d8664,98412c68,68af56ab,19876499,fa30c8b7,8bfa5d19,b4aea0ec,52787690,49b7e3b5) -,S(2dd92155,81bbbcdb,a1900b90,9018ea30,2e40ec35,cf2b74ca,6065e8d1,f3bcc057,cdb59ee3,b5d42deb,5a4ffe56,46f5dec0,218d0e9d,569cdd3f,b96610ab,2a382fe5) -,S(a245a185,ed85c547,3b78a561,76a32e45,b35efe75,36a1fef4,569f4f70,ba510ae5,93b66fc4,6fde9554,1363bdbd,117073cd,f3f5e406,75fc5710,34bef6bc,47a2519c) -,S(5136c2e4,5004c1fd,615fe81a,e4463153,2753c670,86d1bba0,b3a35bdc,47bbec08,1743f5c5,d0a58608,a66fab55,69f7134d,7fe49fad,2dbee1a6,d01c581d,18f97d85) -,S(b65423af,618b242b,71e258e8,c22f975b,621a8900,9e0a3f12,f9f8314d,7fc6ca54,e3c39b1c,e4159306,e730c2ad,4ecec430,720355a2,815b63a9,720ef623,b91e4230) -,S(d6db49c6,4e68f6b0,59cb5a00,3c826a59,bea1e9fe,7622a2e,6eca605e,fe9a7858,cff0a39d,83e246f1,efad5dad,72c5df0d,62e9cf8f,4da81a5a,68586187,3dfd758f) -,S(ff2f739,8e5aaae1,a589a82f,e8e36315,34ff1081,cb083933,d08473b4,bd16f03,1559e2e8,49dc5aeb,50f3de13,1478fa99,e110627,aa0c4c5d,43ab03ca,dde04cdf) -,S(a7c9398c,5938a3ca,e32d2947,d8e3a58,e42a669f,5cd9b219,d8acf6f5,2cef9bf5,43e2a5a3,dae4bd5e,64a30861,7056fce6,cf86d0b7,41c3b46e,3a3ed90e,98d2d51c) -,S(faa9724a,357b6806,7be30aa6,4fb85879,1969191e,346d5d73,8a85b27c,c6608d72,ea1f8a66,8f4881fc,4ecfc556,f0ca4e12,b93ee6ca,54a0fce,b2fe51ca,174d9713) -,S(28301cf8,328171c0,74cd585f,6e5870ac,815de8d0,9c9f15c5,5540de9a,b29a86df,31910e6f,15585710,74e87f41,e5cc9c73,4ddd15bd,4436ec8f,59806afe,7901c2e4) -,S(fbde2380,ae0cccc4,e044ca59,92be8e11,5fc782eb,c1d49bc2,cbdfd1f5,d7908a09,c1a1d67c,74777fbb,68919bf4,11de555a,6485436f,7e34062b,480b7516,8a03dba3) -,S(59d8ba7b,6c71ba1d,191d4cce,662483cb,9784ede7,d1908e81,815d0a48,4b84bf7d,8a32e968,1ecf963b,3c23a9d2,f382490b,1f229b27,a663f4a6,9819c33b,f9f6149f) -,S(6c3a61d7,1c999ae0,604511ad,23f620ad,dfc7891b,925eeed1,6a5ca37f,b41b47e4,f7115905,c696c2b3,e2b82a30,9728923e,b8eba53c,363f1456,73676b59,9b50b9c0) -,S(8e53027f,8e137bfa,73eb5167,35382ba,ab3468f4,d4227b19,a45c51c2,ef3d8339,2b5ea7b9,542a83ab,a1c402ba,be13437b,c621067,96e83b7a,2cdedc52,2bcff513) -,S(113aa35e,6a5f794b,a56b04a3,d639b1e1,64a790b5,8ff310c,fbeab588,f93be16a,227c17e7,d95583e7,fdcc3ab7,b24182b5,1bb11e91,9f28fd7b,3a2e4a40,4f333962) -,S(16c4c83f,5a06b2de,9d3f39e7,1f0a9de7,af6e8fc7,b0fecaf3,2c82f1aa,fe9a5343,b4cbf71e,c3ad4635,87f8e355,cffe1ea,a19f1dc6,d233d617,776a69a9,ab8dec03) -,S(4d97594c,613de84a,e685199a,ac639a56,e5c15a0e,c00282bd,197cc2ea,90f8fbb0,b9f39a44,24cbb1e2,f77afa90,ec7266ee,64ea987e,80a32b34,483c1f2e,b0c5844a) -,S(b679693a,b3fecff0,819e0598,65406521,1f9aee9c,1ea44417,eba86ebe,32414ac3,7bfe1ba0,ae17291d,71aac3f3,66e5a927,56b53312,a6818d1a,78b7d9ef,a5d01b2f) -,S(a97c2730,a78cf5b7,538b518a,87d8fc55,f95a367d,4e021d23,79f163eb,98b6eb9a,aed1e51c,3ce7e35e,ff69e7d9,3fd3a968,59f0f23a,7bbab9d8,3b60cabd,cebd34f) -,S(7dd4e84f,6547d66b,5e0b204c,ed1d0258,4fe92ed8,6b504ae4,eb1b3d66,d43b8ca4,7956148f,de975510,5e3b5126,f82e77b,89a77b68,ffc9364c,bfb596e8,187ea99b) -,S(5e856d1d,25acc306,e8c1a2b7,a9ccea1,beb3008d,c224b38f,e2f31376,65d07c3f,7dccf6b1,55c12be2,f3da02c9,12fdb666,816558b1,11a2a545,9d88aa28,9d855e6c) -,S(c85ee868,7f507429,e5c26af6,7ef1fe45,e782661c,1fa03aa3,ee9dd9c9,302e5dd6,732de6ad,d071a0b0,b77e47bc,14e176d4,c85b39d0,ac5b4ea,55f0d367,dba5ab5d) -,S(a97ba3a5,cc2d5148,3f65c65b,483b3e4f,3c68e46b,87bcfea1,42aeed8,4c42e42b,f4eb1271,3024d1,b7612c3b,7dc3dff8,ca336f23,5db7daf9,3ca6f7d8,1bdb4a21) -,S(3c0396cf,6ff0150c,5b6bd528,4a05d0a5,3b735c85,125bd49c,f62db5b6,4eaf54a7,6ec02c02,f8d9a61e,6bb38d64,daaf3c7d,5324462e,37e2df8d,4ad12bfa,37fd2cb2) -,S(e36fcebc,e406d2a4,ad42f7dd,cc00e9f3,cf385eeb,58cee004,5aab8174,82d84f94,7c98182f,6edd358e,76d66de0,b45ae9f6,5eb75092,1a25194c,1911bd9f,7e6a1a6b) -,S(171ea2ec,b9641746,7d7edcf,ecd6d85,8577322e,6ebac130,5ab57f33,62eb4e37,9f219970,753a7b9c,e4f0c6ce,5745596a,aca8df7b,a73660c9,10add5a9,d4c533d6) -,S(a81d720a,bf8047e8,ef67bf2,71a13f47,636a5f9e,ec425649,1cbdad65,39652f9e,92b37c88,275c022b,635df6b,9246edf5,5dbd8284,eaa4cd7e,3d3ce6d1,c0ca3794) -,S(fa3b6973,4bd9939c,4b6ecd3b,f0a06327,2dc11345,1bddd717,f17b745f,bc3f99b3,f38a4e1a,bcb35097,7acc8f2e,d7f73f75,d406e7f2,22fdeea,2c12d8b9,e5d2dfa3) -,S(c117681e,b55bff67,feda80a1,ae88b4be,c806860d,91916619,288a7ce0,b31aef86,d94ae124,dca678bc,b69c9421,f295405f,d6dc1fac,de96a2b4,58ba5fd2,72faa032) -,S(5ccc0619,92744a57,683de5e3,7b956fa1,fd7287d,b4516fc9,f8635be3,a0db42a9,af1f73ea,4d2168e1,7550ffc,dcbba288,8397931b,e457ce6f,3f8082f8,cfc5f03) -,S(858b019c,8a93524f,6c86738d,cb10b534,d8caaf86,5c0ce75c,fc9b83b0,7c661a0a,7c59d30,1ffc8ce1,b0767ed7,91f84bc5,60bb8ca,ed3464ba,698a53c,160ec570) -,S(e1e217b8,69da0c77,599dcc38,40fa1d8c,a8d08b1a,4ac9a882,da1476cc,cc76fa56,83f0ef77,905f0801,4bd86e17,63b8c2cf,ab2018a8,9586620a,b49a15,9fc314ca) -,S(15a1ae40,b4fc51dc,554b75d4,db0c2bfd,62dfbbfc,dede18e1,4edbb689,91525cff,4f0453b7,e4e0e99d,9663e5c6,bb018007,b52c8e14,d78a28d,c4a888e4,8c4326c2) -,S(1b9a142f,fc4d03ea,4b079f2d,b05fad98,8ddb2d32,b359967f,c173801f,63320825,59bda7ed,5b691c20,4fc8f8ac,f53be298,ae628954,a8134d0f,dd097e67,be9ff9b6) -#endif -}; -#undef S diff --git a/external/secp256k1/src/precomputed_ecmult.h b/external/secp256k1/src/precomputed_ecmult.h deleted file mode 100644 index 17df102967..0000000000 --- a/external/secp256k1/src/precomputed_ecmult.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************************************** - * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php. * - *****************************************************************************************************/ - -#ifndef SECP256K1_PRECOMPUTED_ECMULT_H -#define SECP256K1_PRECOMPUTED_ECMULT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "ecmult.h" -#include "group.h" -#if defined(EXHAUSTIVE_TEST_ORDER) -# if EXHAUSTIVE_TEST_ORDER == 7 -# define WINDOW_G 3 -# elif EXHAUSTIVE_TEST_ORDER == 13 -# define WINDOW_G 4 -# elif EXHAUSTIVE_TEST_ORDER == 199 -# define WINDOW_G 8 -# else -# error No known generator for the specified exhaustive test group order. -# endif -static secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; -static secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; -#else /* !defined(EXHAUSTIVE_TEST_ORDER) */ -# define WINDOW_G ECMULT_WINDOW_SIZE -extern const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; -extern const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; -#endif /* defined(EXHAUSTIVE_TEST_ORDER) */ - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_PRECOMPUTED_ECMULT_H */ diff --git a/external/secp256k1/src/precomputed_ecmult_gen.c b/external/secp256k1/src/precomputed_ecmult_gen.c deleted file mode 100644 index 248fb077e5..0000000000 --- a/external/secp256k1/src/precomputed_ecmult_gen.c +++ /dev/null @@ -1,1779 +0,0 @@ -/* This file was automatically generated by precompute_ecmult_gen. */ -/* See ecmult_gen_impl.h for details about the contents of this file. */ -#include "group.h" -#include "ecmult_gen.h" -#include "precomputed_ecmult_gen.h" -#ifdef EXHAUSTIVE_TEST_ORDER -# error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode -#endif /* EXHAUSTIVE_TEST_ORDER */ -#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u) -const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = { -#if 0 -#elif (COMB_BLOCKS == 2) && (COMB_TEETH == 5) && (COMB_SPACING == 26) -{S(7081b567,8cb87d01,99c9c76e,d1e0a5e0,1d784be9,27f6b135,161e0fd0,3f39b473,ad5222ac,f062cb39,21b234a7,15b626ae,f780b307,9b5122d1,53210f42,d9369242), -S(228af17e,df90d1cc,a40173e9,478fa445,9780dacd,c3f15b90,fda5d00e,1faa1b51,8ff47c4d,a4ba636a,f656da9,12a81f79,6252496d,1e519886,b2c2b073,25be2b4a), -S(b515ebe0,f48fb34e,9e01824c,d90553af,db116579,96667847,5ebaa700,242fd722,4cf08191,510fbf0,51f9e19a,198f11f6,ea31268c,2a6d384c,60557250,f0553c50), -S(c37581f1,35446ff3,e80cde04,ec987f08,5af3af9f,71d87494,99b03ba,dcb8f78c,9e46324a,8d8754fe,fbda7c34,2446cf72,b7472708,25cfb92f,a22a4e73,4f1e9bc7), -S(768392e3,b2ccbbc,21792f2d,6f43c63d,efcc249,bcd549cb,96abd8ef,4ae59e90,5d061a40,ac3f93d1,82f0f7a9,914fff5d,90bbacb9,1965882c,591e89bf,c49da994), -S(a9db5de9,2d96c715,8ce5ee00,3d186cf1,976f6a76,f1be0714,726594fb,6c1ba564,743df2a8,ee73fb4a,47b3d0f,2f2b8cab,5af5227,f232946a,82676e4e,8bb70c8b), -S(58921d8d,3712f640,657e762a,737ccd0a,cece1459,a2ba8323,20b43903,d4953f93,78c26959,7e422c02,c01fcbef,484a9d44,9f635c82,849bc2a3,2a9bf6ef,3e6f1e7e), -S(bae41760,ade541bb,60028015,f6906b78,aa41515a,d995dc40,afa091da,77ae8b9a,716ff74d,ad6dc24c,77ebe31f,abe19792,41d18b0f,43ff7598,c6ea04c6,6899219f), -S(e836ff6c,6f9e02e2,4e6f6bcc,2f2460b4,9de88730,6d69241f,b22fa574,7e100f80,77c41df1,4d87b6d3,de74deca,ad426635,f85daca0,ab966a4,5a26a972,32105c5), -S(c7f17d19,fbbf28e2,543fceb2,4268ff6f,1b85e189,79b09991,7457fca0,9ba1b5a4,23a6d4aa,83ee15bf,f1655575,3e4162c5,8acedadb,4c4abfc2,54b7018,f477514b), -S(79c337ad,8835046e,572eea35,df76276b,84e99172,7bbc68a6,8c0b743,28619a,af6cf2b3,9c6b51c9,f1f92e42,6598dcbe,39da6196,2abae0da,d5fc8d0a,aa16a875), -S(1e77739b,12d20887,2bfe200b,d202972a,544804f5,2b0969c5,c22fbe1c,b8b23837,880c7490,c0455322,a0f1e67d,34b3fd1e,33c1e7da,83b9b047,5aef7bc1,332ccee5), -S(b1d314c1,74d493f6,c36a893a,830d90b,f1e86d0c,6deceee0,edb77ff4,31e9607f,8a4ba010,ec3e47cb,29d8f056,e056eb73,3b6b35f6,4c742d06,9ab832f4,68bcd3be), -S(2498aea6,471f748a,f14e50e6,bc17e0a3,ee09514d,fccbd174,f8a21d02,dd0fae48,55a3949f,2e4188e2,b3d344ce,6f0276b5,99b121bc,358e8fe6,bc4f03f5,a8219d08), -S(42d0778e,27e87710,dd19285e,d531af1e,7064386d,11b1b3c9,fb788bf2,b0c112dc,37888909,d943825a,9610e37a,362549f,547b7c7d,ae64a27e,c34290f0,b4fc5fcc), -S(af09a9f8,3a21b2fd,69ce14c5,495c680e,df18e426,c1ca5a1c,af56246f,d6ea5bbd,8eae43ca,8e591017,62c4cb02,9e5cacd2,58f0fdb1,ddbef7e2,c5765208,107c96af)}, -{S(4a7f72ed,ebd8df1f,13db15be,3ab296a8,d67edee4,37965f03,eb501205,3518ddea,1f8c4dc1,2d0e59e7,7d30a326,fd4ecbf8,aacd5fb6,7dc7169,898a9708,ac46b972), -S(c4d4f8d4,949d1ff6,559925db,f4d34972,af16062b,d59493b8,b1e0d546,c2870874,cd7f93e6,c0ee3fdc,4267625a,a6620540,4f6d80c3,d0f7210a,ce6b52e,c350706e), -S(773627f7,dcc56184,7eabafa3,42fffade,325b8ee2,a96f2f77,cbe675a6,2942277d,fb0ad731,9bff4c9c,270d93d1,89a4c380,218ec9df,1f564228,641ab35c,46526bd6), -S(ff443101,befd0bd9,e1914864,3eceea06,b9cf711b,1405e3d5,3883a29f,906063ed,aa1b7d9f,59cbddf7,bc1ad03c,44c4295e,efb406ca,7960c683,eca508d1,b2a9a2dd), -S(cbfb6813,a6874b65,9234e866,c2875f70,e45f9f76,3d634752,3f86040c,880a2e56,ed85d1a,6620c1a4,85ba3038,d2ee6590,4e27206b,eaa531ec,1eb5b886,8232cbca), -S(4e85c77b,27788563,aaeba139,975f7125,f3c933b4,8d67ba6a,2e964243,bdd7bb51,200a9d9b,3400c87b,1fb98422,3200aeb8,e6a5af1d,58c061f0,d059c0b8,d431c08a), -S(d58178ed,f0ce32e3,39a524f7,ad389f7d,8817f41f,ed782612,45218816,2a67d4f0,4840df81,5dab9596,93f9284c,54bdee72,f4861d39,3944c648,ecd76ec5,6dd3225e), -S(670f8f7,9b66496d,13692558,d56d4cd7,a1eeb0d6,9e5133ab,4f0a064b,7152fce4,1a72206,6f530586,927c2e39,370d11f3,e251bd9e,eee10303,406b7592,716333d6), -S(10b41abd,ed4de2fe,b7a40050,e61e5982,89a8cf3,6eaa608c,f2a82c63,5788f1d0,532d168d,680e9c74,4d5111da,6aab902a,9a0f5283,7836b9d9,585dbc8b,1a407de4), -S(76abd21b,103aea9a,f04b4040,297894ce,a501474d,9d38d30,8ed02cc7,137bc7c9,b5a432ad,9e92935f,7040897e,3b04152f,693c5f2,cc1e1d53,2c33f70d,185318e1), -S(4335e10d,5e4f02e6,f1b58a0d,ffb473ec,15f735a3,bf96c140,50bae78c,37061db2,1301143b,1f29f122,afcd0230,d46b6b38,b154e589,92b7eeb4,16088968,a7d57485), -S(2b3966f0,7e37e771,ac4c68ad,b8eef3c0,977cb895,2f47676b,e658aa86,76057f67,5382a6c5,bcdd1a01,6d79d817,80faf650,c0a486bc,ea8fb592,1cd3492c,42c91c3e), -S(f7738800,b7fdf237,dc7f03fc,43724011,8b53aea4,4d7953d4,276f3b4d,bf5c0ff8,c1de7924,ef8dfeed,c4fb409,f1a15d4c,5e8ab42c,90ea9c92,867b5b5c,f2921605), -S(5cb07874,ac4ffb86,2da619be,4c8fa38b,e8b261ec,3ec73a12,cd4cf8fc,4f8d5dae,549d1896,4931dabf,ba4553a2,461f2660,87733454,ea8eec6b,f671e3de,60c70340), -S(5cc85d41,7b2ae9ac,dedb1b44,ce78d8a7,8f56b878,1a4b3af6,635a55c1,fead3be7,66a48c79,301e57d4,54cc8644,d2e778a8,45d85762,2c10eb98,d77eb873,e58bbeca), -S(f27211c9,a067b01c,7fe7fbf7,7b5d9b0,eb0f2475,9d541457,6eb24ba4,19fd3db8,e26d28eb,89f7b518,e9ae0b88,fadbfb9b,641d3a44,c59c6f93,ec28a541,486e041e)} -#elif (COMB_BLOCKS == 11) && (COMB_TEETH == 6) && (COMB_SPACING == 4) -{S(629bee58,a391595f,eb20c534,4933937a,cdb2eba1,86d49f8b,845c1b5f,4ca87182,8dae4162,73c6c068,2e2aede4,76efa86b,7612c07e,f72070d0,dc4486f1,47e95085), -S(6fd5e13c,a94b874b,28cd574b,726efdbf,143ab108,1089b846,7b5b2ebe,6c6a3c8f,4a4db306,52c9772a,868b2859,57c5a005,d83f6afa,6e65d87c,700da998,ce651396), -S(609b6576,191514f4,83f5b428,500cfbaf,96871b8b,3348fe5c,1a131768,bb266b6f,90abb9c1,1bf184d2,8dbc424a,bbf74eb8,de4e0582,2ea5dd93,7d1e8b30,e5f695e7), -S(b5ec0263,27cfd922,23a46abf,a755e6fc,547806ea,333666cf,a43865a3,f4ae647,143353c,cc733d02,617f7764,7dc29c65,67a2e245,aed27120,e5fc11b3,95ffb9c9), -S(ac1fff6,cd869ed5,ca920544,1ceb990c,ce304998,10e27587,6536dcd8,1d4cd15,67a7a012,3e5ea292,85dedf0a,9f138b80,58a1d23c,2a233c5d,783bec39,b6482126), -S(c1807552,644130a3,f9b8aea0,29fdccdd,59e03e27,ff2cb1f9,9d13cf0d,42da7b13,85e99587,f77a25b0,bc64b882,bd279fa3,5be0262e,c2f5253c,70a43261,bd1fe361), -S(42919187,2b3c6877,c3b91266,79266e49,9fa37a8d,74d094a8,8c4a3638,89c2717c,1e4bd2df,a9757d42,285cca1d,856b49b0,ad481ad,828d826e,8921f744,7e04d6ad), -S(d4b10124,283afe03,4b278e5a,91daf61b,be608417,fc845e1f,9b9f52a5,43659f2,fd070859,75e2bad6,b34e0396,47b81a87,cab9fb,fdba802f,6ae3cc8b,67cc98cb), -S(ec4c2c4c,722a54ae,edc37acd,cb6ac490,3077bdf6,3f2c145c,7eb25e74,87c046aa,327bfe37,d745283b,a385dfd0,8e30b61e,2b4e5499,4432be41,fd3f0d31,c00e9ed7), -S(559e40a7,e151eeeb,46442b86,aaf4922c,12030adf,7279bb2,2bca24c6,67566a05,5483756f,60d26b97,82033592,cec21681,c5b5496a,c47f600,2013e5e5,f2ea82df), -S(c1d2e92,19c0138a,9f0a34fd,acc92f4,eafe13cf,1c004b6a,3175133d,6cc7bf12,8fa653f2,a20c1262,be59c7db,20f12579,b2adb1ff,54d84ebc,e5ad4116,3d2ebc23), -S(1becc6c0,e4861825,576624e4,fa622c01,139d9cb0,50c12062,9b87ae6b,9622245,d8516472,656ea10f,5b23839d,43f64e,85fc727b,faafcb6c,fc9c6e89,bf9c038d), -S(c483c2b3,8ceefd35,a9fa9e7a,da242c,d618cd6c,8b3bcb62,e39d68e,c1effab2,71964aca,9101863a,d7c865f2,41e814ef,3c20face,f46246b6,4a742026,471b2495), -S(3487162e,40c7efa6,92bc827f,9af9121e,af5ac549,b4ab6585,6353d699,a94a3783,f5b29042,28833bd6,e3ce0deb,dc0396ca,42701752,f930f437,d042cab2,8f135c1a), -S(eb3b21fa,f733f15a,b94ee0e4,3378e9b6,47571aff,d69292ad,a1b107c8,ad511d5f,cd95b4ad,b8768858,cb750cbb,4fa64523,6b6fde59,ceb71dd4,73a7fe48,9e5a2304), -S(21c8dd7c,34d3f333,758d1d1b,72748fe0,8695af46,3d0bd9ad,e4a6498d,1d01e9df,634d8671,7b885f36,a54b6691,35c3c026,667f3cb6,f2577701,beb0d3bb,84f07940), -S(608e33b8,14998177,5d78e286,d5c6436f,99623417,4e887da0,a95274a0,d120b57d,5d094ca1,181f8dca,87d1e043,f798bfaa,f1004edf,a470fce0,7ff8b124,328397a5), -S(f77710b4,dbc5f7fb,ac6b015e,956ed26a,6bbfb540,6a931a30,d4215aed,de610c7,7508a762,a7333ca8,ac244d6,47e47647,c62c82d,387d8df6,175fb563,1de83d54), -S(f37040aa,b0347fe,976d5980,cbd83db5,4d8cb90e,7f2d2118,85159911,af769d61,df228dd7,67fa0d5c,d44c3f6d,b09e662b,99faa5c6,688b088d,949ddab1,6f11e42), -S(7bf929f3,25374a1b,a0cbaa50,db47fea2,a5d1e3f9,3c34bddc,ea5c2250,d8252071,8fe2d2bf,b23a6755,50f16760,a6511ae8,4e4d316c,45d7cd62,4411ad3f,c72805c), -S(261bc0f3,a69d636a,b82248,6132bf91,2ab7ca95,e9a4925,b3f68bb4,745ee63a,68f52f7,df1ec349,77856c74,7b280907,cb3d456f,988ff7a7,225c4ace,8457a804), -S(60ef138d,e7086d09,711defff,68dad211,88d7f878,d616efb6,dbd3d498,5b730243,ca7c3297,3c56b178,b0cfb8a,da98748a,c3d06cc0,7fe050d7,3a6a9695,52500f8e), -S(8bfef3d6,4be90cac,8b83bf20,906b4277,75a6d982,23d5141f,b74e3851,50bc5eec,ea8b6b4c,c7c8d9ba,809ca811,3621c72c,b82006d7,81ff5f25,32010fc9,57858324), -S(9ca85f3d,4ba47ab0,e9fc0a28,74cd10a4,a8ba9aeb,ff319405,6140fea9,6e395ff3,41182ce8,96554f45,93768fc3,a656981e,69719f05,5469f9e4,ba79de22,bcfe8a8e), -S(38cd0c79,437b1299,9567999a,f54d4f8e,82a6354c,8a93a5ef,56ca2ff5,8a1ce180,c96f5ed,d78de5,9f560716,82b60b13,f06de5f9,49206258,80544bfc,73dfa76a), -S(be37e05b,9369b159,6b390290,3eb8fa0f,f221f599,1270c5f0,47edf62e,a1d0e6e2,4fc860a7,1fa69a27,fbefd8c0,906fc68f,4713fa2a,b37aaa2a,7edd3c8c,d100963c), -S(aa640e99,b091512f,85faed73,a3ac8ede,ee120513,b661f812,9a046a74,d624aaaf,dfb48ad1,a01fd508,e5652406,b681cc9e,13d0d600,68411dae,72d68061,6f6b94ff), -S(d08bb931,f008a1a7,38a16200,9fbf1ab3,d3d455dd,47f45cd6,617e81,8b8e0245,18d92218,21c9a2ed,bcaa5d26,2b7aba18,1f7f1e,7f2007a9,ec6f7d18,f038d723), -S(4e6ed1f6,c39c894f,eaa53e1c,e115fda,75fecf8a,55794628,d9a2202a,9dd5c719,1bb97d73,2e0e137c,e9c94d4c,763f9a6d,e1496548,904460d,df1c3a2f,73b66c1e), -S(867e83ae,610a24bf,401119d,8e1af6dd,414a7161,52b2ffdc,50f71f77,2fa8409c,d5d21ad5,ef365994,b3ad0533,92df82a5,6f677cb3,8500781b,a769dd50,1f6d235), -S(6031361c,6dffc505,dc7e1887,bc75c1d9,5a9db023,8b7240e4,c254f855,b35686fa,b9a9a979,c6b8c576,11eeb783,8b4ac2ae,66506bb0,a203fdf6,3efa9b59,98c7643d), -S(8502d0f,34684503,68784822,f4510c5c,562ad30f,be29a792,f0667e83,b6f95773,cd0e6511,763674b5,57fac9f1,bb62f9e2,3163a0a4,cf08cd52,a6d10064,d8b02ade)}, -{S(840e41bf,13203a96,f41ea041,1ec034fd,db0dac3d,53b6bbc9,4f8a3a78,d0371235,71b51550,a79af319,56c9b3de,fcb167d0,c3e318eb,a852eedc,78490dc5,fdaaca85), -S(5678a034,a24a1607,d78036b2,23eaa3c3,845c9f9e,7293f656,7390354,2f714d5f,57f624be,ff5d1774,c6962dd4,d14cc565,acae170c,7aaf8c6d,b0552daf,e3bdf48c), -S(722012a5,57ed9c9f,9d737a87,39954469,ca12ab29,9dedbaca,507c1259,7a27c6f1,6c28881e,a0e62453,80d73a7f,499f05a4,d9a9c04f,c2ba11e6,9fdd0b6,7c5d5ee4), -S(70c638d9,3eeab892,8bccf1e4,82368eac,a03ca8f1,b30f7b2d,34258539,8c95c014,f8635082,3dc2a200,67dfb293,891929cf,18a810f2,5c85c169,159a4b44,b190a029), -S(2ce4a530,b5f6c77d,c0c4d891,6e89b24b,c25c04c2,723842d4,29300f82,5e260458,6f306154,4d1195ea,98b972e,91a962e2,95a2a4eb,9be03949,a789b01c,f61dd705), -S(89e71182,851bb441,c0af4e31,cad89dc7,3947369b,fef12eb6,b1dfa71a,72498c51,20b7ffd5,878718c2,2b5bfdc,ac422794,63aac0da,4bcdec2a,8f3b538e,3a9f574d), -S(f01f06b8,da0ba34c,e1045e83,adb95fbe,b76f134b,35235539,6b07f8de,9dd25869,afa0fb5b,45ad1f24,73460f17,5ff4bfd8,f162262,65c423fd,ebd92bc1,72f3aa7b), -S(f0c217c8,1dda2201,1f46648a,e096906d,71fba006,1b4dfdb9,85dfe59c,9d8f1894,d5ddd6b7,bdf2a6f6,cba166ae,4c01c60,b012c9ee,ad954a46,6f631f9f,928b3fc), -S(bd9acff2,87cc2a2b,396aef61,b0937a49,c43a2366,a2c3c461,c1283987,a7b6f53,828de0ad,b9067b2d,8f8fefe6,ce3a5c94,e7d63ea1,7c891d2c,5f266e8c,a5fac116), -S(ee314d97,2b9c10a4,fec9f8d,ccab0015,d4923e52,d915eae8,b319911c,7a8fe379,82057aef,ff05c496,ba8b4753,c4e57832,aba9a724,adf70a9f,1b3765ef,952ab52), -S(d39fa7b,9b87ee2a,aa32454a,13470406,c8024c39,cf387143,3364de62,cb94c103,5cf1309,530f9e09,c9b38ad9,3a778ec5,533f60f6,4a42e31,1cd97c2f,c984b9cc), -S(5ab1a07e,5f6aff68,16780e5a,23c9faff,b29cd7d7,5bfb8984,4834fb6b,c6b34a14,deac47fd,6567023e,b5ec7a94,a0133bbf,158c0425,c0a6d288,23558986,314d54bd), -S(b1a4ecc6,94bb5212,98e80464,cffacd32,331ebc7c,4d545141,a129b522,a4818830,9772044f,3722ec57,d76a049b,2afce2b6,319f0bbc,b17c7f06,175a288f,3ce3534d), -S(56015e42,81aed744,a0859e29,eb913a7c,b44ebd39,2ed8c0b7,1eb42f9c,9c93c8ba,8f973650,45f7d8a9,24a276ac,20056895,fb2b0aaa,4b35468a,a51f41f,722b9d33), -S(7d99a5c5,21543229,c8f9c7b,50dbaa64,b200bf86,47c71b35,a0105dde,2b3a8e0c,eae09ef,3ffdec8b,9a30291c,244c0a72,6466c26d,fe2c8d30,174f57fd,ec6aba60), -S(ab7d21f9,1e7dac68,afd6e4e4,794551d5,55a9f42,59825109,5b25652e,946ebdae,8805a806,710ed7b0,fb99ff30,130c074c,6a0be3d2,abe6e155,f9c07496,f8b92454), -S(b31a5f85,d65e5200,8f5261cd,fd6d36f6,4b2a1f3a,6f08d7b8,defc7e84,21d0f7db,2e6d46c3,3733b3b5,597a133f,7459ee2b,570ba333,4d1e7648,1980dda,1aa8d2d3), -S(30af789e,850c8ef8,9eeb226b,27786679,442a9a0c,35cb7337,98345400,29220fc5,f6651170,c83e24e1,eb6e8da,ffa0b0bb,a6c53676,72558d44,c5b77176,3d9b5d7f), -S(8d87f808,98fb8007,ffd5093a,bc6bad2d,23e09e90,e6967031,48d5418,4c60e0ae,3d14332c,21df527f,a2e98243,d3ed4bd0,6634d799,9f62efd,e8d6c919,8ed716a3), -S(a961c219,eb9ea127,205af30d,909ef732,8cc599a,b2080966,f615796e,1126dd98,3e235ae0,37b10074,32e5cee5,56778856,1d552e3e,bf40bb82,5b527cac,8e1e5b9c), -S(b9c2de21,40cea728,2aec5293,bb77dc7b,550a72c8,84389c05,310651bc,7570f2ea,74171cd9,4a5683b7,5bc7c5d9,b4c8fc10,1fecc3b1,b7349ce,840b6ca4,877fed21), -S(cd041ff2,e8191946,8fd7ef0,c33021d2,9533cd75,64772252,c686f718,7e33166b,3f54a9af,e8597bb,faccbbd2,9280e60,93d31bc5,b366aff2,2c95e21b,fbca6041), -S(adfce0b5,8a9cef85,e690b84a,c7ccc6,8f5aa4de,ada5e265,3720412b,e1f19ae,8ae2dcdb,c6ce83be,825593d6,87f9afbe,a88af079,564c60d5,c9b88898,897515ea), -S(833a50c2,cb5507c6,60bd450e,cde341c9,64f2809a,e400215,c52dfaa0,9825df96,de85e216,493cdb4c,4541f720,201f4c67,1472b6a,d61cf8ea,3cf54ccd,a4584b77), -S(3475027a,628ea423,2d689d70,d45e975d,39d62303,282b16b,1f94a427,3d7ea746,97c3052d,9270df78,6efbd2e7,beaa58cd,f864e28,905e3ab5,507cb9aa,e3c69160), -S(cbda2707,e61d9e40,124668ef,7ed83973,dd293dfd,221396a8,d27e7aa1,392edcb3,fd5023a8,af8eff08,f0e3c8b9,b6a22a99,b3ec3aeb,7e0104dc,1f8409cc,d83d8a02), -S(963722ec,aced2105,2bf447fe,619a8532,dc78816e,2e17a111,3ffc601d,9bec0381,f31feba,259f7d0e,3c326c69,53aae60c,1e0479da,5ca839ea,77c6f1a4,9419172c), -S(fc531e1d,49d2a984,83c861b2,b299b8fd,b26831e0,3bced6da,5c4449b0,18363be7,9f9cc9b0,8d72ced1,998c6329,a17695d9,c94cfc76,ba9f6943,1c5dab83,60f2942), -S(dab255f5,b47d96d8,ec5272b,5cde4ca4,33070920,84aa4866,d53b674a,330aea2,feeda13b,a544f090,b790514a,42064cea,509bb3f3,9dbd4567,6bd75414,37579d7c), -S(ac5b161c,fcc42998,71b49d1f,8cf35bd4,dd6bf98e,5f84f2f6,420bc363,b9cac257,4511d4d3,1fa26d7f,e56f671d,7467bbd0,41358b36,b60775f8,65f7d491,3d17b685), -S(b62fbfcc,2aca0706,b0fe67f4,ed5d96b,4a65b048,f73e8f4c,9782e1ee,36189e31,6549e8c2,f77bc824,4e1a90b4,e42ca64a,5ade1768,a0996d69,8d7b047,7bfbf862), -S(56938443,5e509000,5cf3dd18,ea629078,e15097e9,da7bb5c5,737cfa0a,a40e8818,f86a1815,4f379054,11016994,9b2eba6b,477c32b8,b68091a4,4b14990a,5e8eaf92)}, -{S(7c028bd1,75367939,74871a6b,cc957d95,3813331c,87ae606c,17aecbdf,a704ebb4,4fea040b,a0ef0319,91ff9b8b,7829c0c3,93895439,d506c5c3,1a1a3fd9,e32e7e59), -S(24e966d0,bf1227ca,11eb8fd7,8dc5369d,2bb9b681,927990b6,dd02b948,fc18a169,72b7fa7c,f929a6b1,c556a372,4149a279,8d57f504,4b50a1a7,922cfddc,17308ca7), -S(a2b7db3a,265b30aa,94823577,6d5ea839,c4fe564b,97a5e3da,313f7fc4,5de617c5,5e895546,a2778162,4a91ea4e,c104c911,85f3e954,f8378fc2,bea41a3,f1cc9e15), -S(e365c695,449c9976,cb67ede3,325d9229,ee526349,e6b255f7,f4e72184,6722580b,eff99cdf,a0920505,ac37e46,b812d47b,31a29113,e491208,a19e3edb,557ac2e), -S(c3d90905,297c3a65,2c6c3d5d,915cd9c2,d741f472,4a47c8cf,35e5cf3,cac9dd11,8e9ebbd,34a7dd02,24fa6e33,193cdd72,4906dc81,a5aa41ee,4a34d3d0,4b2ee5b3), -S(6e4e23cd,ee4388d6,e8b61f8a,af7678d1,a62b3e1a,3385d278,895a02a,de4c9f00,f69b843b,ae39cf41,11fe9b99,a0287057,5695421e,e1ea690e,2e76d937,e7e32c01), -S(92eb38a6,3743088a,39b58cad,4eb4a27e,a8b08c27,444d704,6d2aa5f4,89713217,22af8d6c,d3567a6d,cf7403ef,e0afea02,48ea4266,1577005a,9afb5f2a,19611864), -S(b3c84323,e2d022fd,d2a80d07,203f4a26,f5d32dae,62842072,9663a994,3a829d08,9a899de,82329d94,83b88e1e,1bce53ed,8714cad4,c68cd491,1b71bc0a,e3839821), -S(daae5199,57a6002,8958b22e,6dbbee20,c4bbd8e1,7ed589e,b8528f35,7a4dbb40,afec8a03,321586ec,ac38e941,7fa8e342,f0542193,59decf5e,56479a39,c32f92af), -S(7afb9a56,89fd1344,cdbc5c72,62dff7b,718c2e47,a6e19ec,665af795,86ed0161,d1c2c9cb,60a191a9,a3db7e20,2ebc2eff,444bbaa8,d81ba086,6f8825f3,8c765f53), -S(8d0c4a2a,e72b54c6,236d997d,61a2a24f,ddbd39c7,ee16f1e7,d7c45b22,b4bfdac8,15a58f4f,fdad9e3f,b4d33c7e,170747cc,6a5abfdd,bfbe5814,ef0c3611,6a0a9e91), -S(24d8c0ca,53400126,347e67f3,72f19298,595b6d33,76ba2f19,2fba6dd1,7b57bda1,7c01404f,bd316814,f10734a1,559049ca,d6f20e90,d6b13ed5,f9542630,db77f9ec), -S(4c2b7a58,87a49df4,f98cfc72,22fdd832,362b8cc4,c5f4fff4,d0a20674,c9749bde,c2a1cfcd,e8636288,31a5c450,fb5cf552,c76e581f,9274e5d9,888a3a68,c37ca349), -S(2028e381,f42cc2f7,a8829308,bb72881e,94e5b54e,3331d848,898ccabc,bf971cb,16debea0,203f0709,d9b55b0d,2b8651b5,cb085d8c,8f56708d,c1fe4d33,a616dfab), -S(d11e0753,f72b7c4e,641ed50f,84dfa24d,a0baea77,98fcf062,8b2696ba,a7ec2529,55af37fe,88324646,777387e5,a9b18059,ace20e9,becd7488,5e43fee5,fa6809e2), -S(72309865,b8a1a6f3,9d6d561f,43ddf5b7,f2d022ed,95df130b,2563eaff,9008a95,f3fca0be,3ce7d9eb,e1648964,58eba87e,934d000b,a535f223,868dae11,dd5230e), -S(adca4785,cbf38a0f,28de7b36,daccc761,89b8b918,f3fafa7b,abbbd9b1,4ed5485f,880d76a6,fbcce864,657edb9b,349f124d,1b22c7af,2b0ff833,40d7a0c4,84b49de0), -S(bb43e0c0,93d58c6f,3946e58e,4727d7e2,d223c84d,513c4e2,222406bc,aafb03c2,c00f7dc8,fcbd55b3,6a95f2f4,a3a07b7f,9599736f,af099a69,e2fc2630,a2aef1d5), -S(179eb588,d1c7aa5a,24e51f5e,6d86e4ed,2e6f0f98,bf956b71,ec1caca1,b7f775cf,42f461c8,a784f643,d5a8682a,6ec9b470,455f0ab9,f269140,b1ad2376,95f64afd), -S(9144fc75,b00f8608,714f027,16b30575,be19dc01,d3689e8d,2665d967,6a077d11,b168c324,7dc6c31e,8302b6df,a2e7c053,dd849538,f9d45b87,14d889ec,cc789704), -S(d6cd2a7a,b7253b86,34231eb3,2793f062,bdf103b2,4fade912,6206e745,a3b429a7,9903e507,dc5e3a61,d73fc83c,5c4ba476,6ae92655,9b208369,bee55948,4bfe444a), -S(264845ed,623bd3f3,808ca51e,517def45,1fbc237b,e47e3ded,70c3769b,391a9f83,cb5022fe,3d535f4d,192e73d8,5d9ede23,78e0824c,e560a97,d53aabdd,f8717377), -S(2df9621c,cf3e67da,54c47ddf,81e3ba7e,7b50e713,cc7d08ac,d64f47e9,85c4f334,8058f6e8,139d8e87,cce4a389,c470e3d8,45da3537,ccead4f3,abbccf42,a5fcc49f), -S(ccfd6c4,c5966144,32d2efc4,1ccfa0eb,3e0b44ed,a4558128,c3e4d68d,949a5cac,bc77b87b,5f50d3a9,6b28d5cf,fb371b4a,36cc1360,15c548b3,f98d661a,beda8acf), -S(4e2e6052,cd35d585,6531fcf1,73bf124d,3c569bf6,6cc54ed6,9a520d42,cb836296,6381d100,e5d9ae50,f1821122,b8e91a5e,f365edee,556fee1c,2fdb6d17,3fd29c65), -S(6603d715,ed0f8725,7d9c3f29,cf86ad4c,aa0500ca,fa16a708,3168e265,b87d0255,9d2eda4a,6195e2c4,a4576e4d,5d02383,a3a01b2c,f94ab8fd,fef2f338,15807d31), -S(f09ef30d,fade81df,2fcafe31,387ed34,5a8029cb,e93fec3b,eaaeb8ac,8adc9803,f9f3039e,5b73c7cc,cf841eb8,1c15203f,ba192e,9eb39aeb,36f56c29,44b286bb), -S(ebf4611f,cb3a44a9,f9d5b00a,c559dbb5,394840c8,41a06496,bbd2011a,2508cc34,1e183324,9a610584,5d62ef4b,685152e5,c75c7525,c703f81,51bdd87c,6fda0d43), -S(31fc3226,c19aea7b,4845ff2a,ddeca6a9,36505a49,92102cb3,499d66f8,a6e1a3b5,49babd41,b1e8a6c,a728f971,d8d8cb76,47cdb94b,89767a67,fd975ac6,93f144d1), -S(be1e37d9,dadc4b4b,7a5ba74d,fb7eb55c,2b0a4fdd,81564f8d,51038afe,f716e3d2,de6f0c3d,b6efc974,975a7d6d,3c6e9d44,a712879e,4e95c612,164273bc,5de1f4b), -S(f8034e14,2425cdce,31e82b49,cde33ba8,3630d1ae,283b8b47,73960539,c67f1652,a302e3b1,860252a5,e7114568,748746ad,1e02c2e4,280bc913,dd4b4d2f,92a561af), -S(21e709bf,369cdb2d,b7f51b10,f0ff56c1,2c1938d6,18419d00,34e57d94,7b83d5e2,d7e09ab1,2e7d04f5,aab3a75f,8cf75876,ddc3cf0d,cb4b9526,ea7f755a,dfe1e495)}, -{S(638b6618,c1498946,75a1a943,8755a68,30d7dd3c,9d8a9f20,d65a7161,9c8b477f,e4e66035,e947c73a,c34a48b,b43a3762,d1038e6,893dee23,cf658a12,190d2a56), -S(4b6ce93a,acd4954e,cf0febd1,fc9a965e,ae7fbc1e,e24a12d3,a4b86573,62eb255d,8cea4838,1bdf4e5d,79e25ed0,1aab94b3,5f00267b,3ec7eeb6,63833507,583407b3), -S(e2a42110,3e8e2a80,a6451f71,b348434d,7d508023,beeed16a,d87417b8,5c7b7913,5fc15b62,124014e7,fa8f95cf,78ce8415,d46a1f97,d88be55a,76431786,8de3d605), -S(6949956,91582c2c,2e14576f,5ec0dd37,65133237,a4e43369,633edf69,933d1f75,5ca8c2a6,329882f5,2daf48e2,e291c48d,febbbd29,9ccc9ff,3ad54ed,33ccef43), -S(55d836af,2dd4b8a5,7f20eb57,6886790e,a3ccfcf9,2a2940b3,646f263d,685f62cd,7cc1ffe6,37781c72,d3cc26dd,9d4147c2,183c8e0a,95b87742,52ac47ac,19db266), -S(442a3090,46bbf3ef,503a138,b60ddfa0,ea4a5901,ae801003,f3f18ad9,9703a44e,129d9913,eff78c49,16e67c4c,cb658784,fa47da35,92ea1c98,4054b371,a275639b), -S(76981efa,29944c2d,9463fc94,67a92e1f,9403c287,dd595292,4860aee4,b78626ca,c87cb5c9,ce93ff3c,23189404,cabf8e09,996c4cde,e67935d5,874c705d,6a7f95ae), -S(42ad08fc,2a1eafc3,d793f04e,304831e,c1bae89,c7d00b24,7785d870,904bef5c,c3913fd3,6b8c08c2,553b9c48,5b90221e,ecdc8d02,6d558bc2,5fdd6ba3,df78ed63), -S(4d70ffbe,efc6254d,cee74a89,70244bd3,384b3af5,8510ca61,258fcbf8,f0c82575,ba3e19d,b022a75b,c75cbaea,84ff912b,867124d,a20e0d28,a007fb74,9a9d1c7b), -S(4ec8dca8,7079487c,adfd516,da2df139,5477b524,df4aa6d6,4db5e206,cfb14b9f,e88e5bad,c8654d60,fe1f8f6a,73328209,63bb10cd,31aae381,ea1b4d9c,eaf9cb27), -S(2e5a47c9,a47cbbb5,ef701784,34798a6c,48244df9,dab1e5d8,83c7f732,b89c7d79,7c8202dd,cf7fb6ec,471856d5,830d59e6,99c04377,c553d835,f64cb333,cc405c35), -S(3ca98150,bc5f116a,e7034a07,628d698f,67cbb8d3,74869ab1,534464f5,5e8ed24f,fad702ec,c6b738de,5b653f78,f51c98d2,1e4bad57,4db97730,58324d1e,12b89f9), -S(f414495d,9093ad22,11e001f8,b07b38bd,f5430a11,72899bcc,2c553b55,a9d4a225,bc130e93,998db229,6aef128a,5b8e5b9,9cf67eb7,713aa7d9,9fc4c902,af660f4b), -S(44e794c9,5a28ee80,f9b64193,9c626a78,4a851a4f,84f28887,9eaec508,1b60e508,b219e000,1b07a275,f63dfb3b,e977a40a,f505be1e,d3eb8194,b919b9ea,70d7198a), -S(35024622,bc17bec1,9c352280,297ddf7f,41654c08,61c3744b,13c74ed5,6673b98,64aece4c,3ec0b19c,cdbc06b7,4eb15704,50ff689e,6c5bafb7,6ae99396,12f4cca0), -S(45c4f36c,ac4c4738,ab216363,e12b2475,50b8ef09,7a986ce1,60b0462f,f8725a58,fb944806,dee59834,7d256885,3761e3a,9ae666b,9b0ee095,fea33ec7,bbce9a5f), -S(20a0b4f7,cfb58bd8,d09d008d,70e7f807,b4fa61ff,65f2e15,f00bddeb,55df1124,7961d1de,e98ca40f,4d09e5fc,52ae4916,cafdd6e,2bdb9f9d,2776239c,a3480157), -S(fa10af8c,eb2de4c9,3c0c2cb0,95f95911,755b19d9,90f17e33,69930d6,6002fcd3,68a3bfb4,533bb5f0,54fbf91c,b771b08e,e388a61a,9727bb7f,a3a1f67e,60b2eba7), -S(d417d7dd,30ebe9f1,7d52edd6,c82d91f9,25d5987f,a6f53b0e,d769a34f,e557c11e,ea89c810,619e32f2,369258ae,8ad8a456,cc36d87e,b45a42d3,83956039,62e437c8), -S(349b002d,ecee0e4,1788a3c0,cabb9ff7,c17848e2,78ef8905,63924c55,52d59853,47583a2e,7ff61b9,6fa168b5,1191b363,efa3e0a1,ce825a3c,5bb04e5b,e403b4b0), -S(4b8efc8d,7eeb3554,b5128e8d,ce20c29,697f79cb,29f61b4e,a2f7ac28,57910bb,e3cef657,7b5c0d2f,dee52c96,b6353073,b099fc9c,65688969,24cd744b,981c5ff0), -S(f356e8cf,5785b05e,e99a2b4,d202b64,2b1e98c2,57741e60,7241fb9f,d3f5ea2f,9079fd65,59d5a93f,91370d16,20ba487a,a8c6ad3d,e67f2c83,a1c335,fb5398a2), -S(bfb74aa2,15e5ce36,97cb6156,c2666ef7,1b579a50,56ff60ba,d3d5e10a,7eb2d31f,3def8a80,ddc3f407,e30d11fb,232f0e31,191bba1,d51a7eaf,b86d7f97,45d78dce), -S(658748bc,bbc75ba,30c969fa,371fc1d7,76c32a5c,7e632201,264deb36,b296ad2a,c173fe4b,14ead07c,2c6574c,8887500b,53f6c02e,dbd4048b,e69aab41,9267ef9f), -S(f51a5ca6,fd6dde25,447fa46f,c0984d26,66004c02,8d402624,8886d0d4,604f6ad8,fd4290e1,7b2928aa,f2e03b98,97252b82,d481c4c5,ad4edda6,16dc1cd8,e7ee83b2), -S(20ef1ab3,491b8d0d,a1565e2,8dd92dff,efcb88f,e88c6c2f,6b100b30,b58249b6,6814d32,7b5b94c4,12fb770e,2fc4077f,fa9a336c,9e7db2a4,bc7dffa4,286eee0), -S(d98785a,82dfe5de,343bea0,d91cd8c4,93344b86,7fffe1e6,efd7758a,90cdd899,37ad7f7c,5783d262,5204bac3,4405c207,972b7fb4,cccc3585,ee152f0a,48ee16c4), -S(3885e910,18a66e64,2d3f0c76,bca6dc82,a6916cb,1e46a858,7aff5ea2,d9390689,20765590,83ba89c2,14be9178,46e40553,ea195c49,de203c9,d175296e,a4430819), -S(c88cf650,3b50f5eb,7bac15fe,2097ff76,9c57b983,1b5d05c9,fbd8dc58,d4a9a746,b6443b76,64984192,e7056478,e9f372cb,21a0c7c0,cfcb0e84,850443a0,25ff42b6), -S(2831fddb,2ba2d301,2dedd58,a3f47434,3450985e,80e4e4c1,646745cb,1abc69d4,1b04e1b7,db84b6c4,882f264c,7bba91d5,2256dc97,fdd22e58,483dec32,5020a257), -S(5e492bf,c9d19dcb,c3bcb9a8,b7bec84c,23c359de,a78aa0a1,e0522232,df037abc,614fe5b7,cffedd76,35d371b5,2d89baf0,55af687d,e6c12d80,b221d0b3,9d03d0ac), -S(bbc64d06,681957e9,685c9864,c5f9bfda,34b4dd02,6b749399,a12bd8de,87f311e7,3c525096,dd6b7d11,26c6ca50,5064da63,f7f6a203,87594f4f,e4ae0403,fb4d66b6)}, -{S(2b00c7db,16887372,753ab219,17092563,8c603992,f501b07c,9d8442b3,721addf9,8e7c5f66,4c2493ec,77cc74ef,d9221235,f26bd3bd,6f505347,39f0fe19,c41b9fad), -S(56b9a3eb,d9360224,56267f52,21ade9f9,674863ee,4bacb7c9,ef0155ca,b36b336e,2e2b1a4d,f6c150c8,6dcfe9d2,e2836579,f82ac4d4,2f8fa4d5,d814b952,e92da69e), -S(ff52bbc2,83bd15ad,523e6d08,873a8896,9449a1c1,c5ec8570,ed532000,5a92aa3f,dd9c534b,e59d3845,a1943435,1a20513d,1a829424,e65ed8ad,60342b38,6578b21), -S(84f79356,86b0d45a,13a1ce22,7e7c925e,d80be5d9,9fd7e671,270c4c35,7254e9ce,3dfe2058,1e91dc25,12c16951,c667fbe6,83192bf3,3fc0bdec,c760dff6,730f82be), -S(db14da0a,86bcd275,71cb9348,36268bb,85c306c8,9ee1b78b,83c247a1,71c7355d,66ba535e,81e877b4,71b0b75a,6545970d,6e33cbe0,ff011e3f,d653d026,f4fff395), -S(28bfbd9e,44554371,74a4c24a,cc65ef45,5fd4d39e,b466e94,358cef4b,b0eeaa5,5f5ce6de,2925acc9,e503d731,d46601aa,7e668001,669819cf,fa54b3e3,dbb98f32), -S(a7b21a3f,a07b4049,7f9f5087,c763b431,d5f04cd0,e7b7e0dc,f9c6c664,df7c6ac7,daf23f35,b903ecc,af4f50cf,459deac9,85d0d008,3b5afa73,7131a61d,8591bf9c), -S(12fac42a,40935aa,e881894d,245b9691,cd1f6ad0,e0481e1f,444e0ccb,6ee88781,c519e0b9,e3c19fc8,f67c07e4,f357f43d,589ec23c,7714f7a0,4347be96,4ca572fb), -S(5c2e28bc,94f8639e,50133dba,9b6c8a35,348eefdd,2fdbc18f,2abb792,eb8807dd,c546b3c2,5f2809e2,7977a8e2,3a1c3ddf,36229f31,434c90e9,1386ee84,b64e8fdb), -S(e8e73382,fbe8b94e,58bef90b,aeb28305,d27ea48d,9c5f6e08,ef47e4dd,5fad6b78,d3529a2e,86240f06,a63ba03b,ce419c05,24d22622,fab9107d,aaf3016c,6ff7fe3e), -S(26b93629,ebe68d1e,878e94b7,5babd663,6fe1f6f8,659b155a,e10801eb,c2cc51d9,f4630056,b3e532f7,32238911,555c0ffd,f4951c9a,b2f45119,cb12e774,aaa2666), -S(57b3b642,431f793f,24862328,dbd271ae,19d343eb,c3b0ca7c,affe4fcb,319d8d94,1d7ed35a,5abc7e39,1858a9fd,b90f907e,6a065648,c00f94a7,75f06d2b,1cacef1a), -S(c2123794,d98f0311,c1327522,1767236a,6f45cb14,8fcd65d7,e0be8d13,2a650953,d5a382f,fcc2ffba,3917763d,ebe0549d,66f358b,d727c281,288551f8,4ecd193b), -S(16789662,9208b510,7528efd1,36036980,994d6c3e,5b34c69f,ef3b86a4,3db9e8f2,217105f8,39b0ae0e,932b5207,e8e7c190,3ea463c5,40c043aa,e4f8b106,97ccc84b), -S(3a0b8ffc,83a1702e,214adfc3,79bec5a9,753274ef,9e3271ca,8ec5b067,a5f3b6cf,2c3de01b,f27dd574,4496c2a4,75a07e60,71ee60ef,7eaf1c94,c257418b,744d1338), -S(482e5ac2,6477feb7,6c848d58,40173d87,1687c5b7,3b2970ec,b8dd69e9,3393f923,dfb3995a,ca5b54a3,b48e1dc,107023d4,dbd7a918,6adf2af0,61f92160,76e7f78c), -S(3869373d,638a30cb,63177204,bfb194f0,2c6ff503,3cb4ef1f,b146741a,f3b495ed,f2ac9f3a,ca159c7,c2ce9f48,e895c543,d3f19066,74f335b9,efdc4b47,4ccc23c3), -S(98c16ec8,54b34ea2,f08aa4fd,3ce1877d,4a36f2a6,4e673191,17f74e5d,86e57f4e,3448646f,c9aaab0f,4d9ec298,8f7c07ef,448888e7,6318e0ac,552d7cc,b59820a3), -S(1b3a4ebc,8ad1c200,2847e182,de7c9eba,f0f7a408,e2aa172d,484bb9d3,ab897b73,b93decef,69cf2da4,5c3a2373,ac2abd77,311fc1f9,21e7df8,5f5b3504,a5ecbdb4), -S(57b5b2d2,87bec103,e4aa7b96,16129718,64780441,fb5ef847,19f16d,a1c909fe,2c2d983c,d8c37a7d,653716e6,15756121,9e5ad5ab,25664967,67a0fbd8,e8180c71), -S(cd7e277b,ae1498a1,8e7bc00c,2c299a49,69f6862b,bf96e6d9,f5143db8,7b582115,f9548ddf,c27108bb,38f80025,6ffdc25e,28621c17,c370a40e,5009b968,d40660bc), -S(80615f12,82ed7a8f,bdd70890,77c24f18,c03fa395,3cbea7bd,32a26c7c,260102e7,8d54a3a2,83383d6c,a633d17d,e2f4f756,3bcc3826,10cc1012,3f2f192b,e654c2cb), -S(9b16f5dd,c8c8c8d,53786b49,e2d025a6,838f6322,700fe105,7de6d78e,92281a9e,a36aa3c2,f2034285,76f5c570,63bb1bd7,e6e0410,2e1cd2dd,f100a54e,431ca08f), -S(f1d04075,35ffd40f,2a0b59f9,14ecf368,67700c5,b33e15c5,153fa9b1,c724d36c,22a8b48e,4db1d3d1,28cc735f,99db74d9,ba7457cc,67b8fb39,7b38fcbb,153f7c0a), -S(c252ae6b,cb711704,659c37a6,f425b215,1ac8a4c6,63420eba,899127e8,1d8df3b7,8e9a75ab,c5a2cd8c,d44331ea,b07e5d97,a30c6619,8e382261,642c0e10,8f6d46b3), -S(59f6fadb,4a8a3389,999b93d4,cdf1f8f0,4735b397,9fa5397e,64df420b,85876ed5,c6e8baae,fdeb7019,23a68b71,9c88596f,60742a38,db04d7e5,76bd1b8d,1ae25a6b), -S(3c2e03c9,3f610ffd,db519c7,80c201ce,b58ffed8,ee10e21f,d1610e99,33fd08c7,d339d979,38e1c5de,7492e7d2,d64fe34d,ed889d48,54670345,1c51432f,ec6c829), -S(59d16070,f9147ce5,5bac599e,aaace0ef,24c02ea6,85249cc6,ccfbeecb,a4bba83f,8105bf41,47f22f7b,18c73941,3a85ef06,40bf6805,51c68a10,e16be920,193977f), -S(3aca1182,3f31b2b,a12e628b,604b1010,62c45fce,22e15dd0,8b9b5ef9,a53dc02,bdca8ab2,d2dcab6e,3a98e7f8,7e192c19,cae60952,fc6f54bb,d46acb49,60d51c0a), -S(261e9b93,3648c7d8,d5255219,fd0634eb,112e1dd3,fcce0a04,135b2784,e67b5e32,e0eb5ec4,30b1f9ef,2bd10916,b21f4fe1,4cfc80c,2bc179e0,fceb8678,ff933068), -S(75918e0c,a0f03b34,40cd6239,c108bb72,f293a881,a1f2e9a,73c604b8,8c451c39,7f02a925,80e50aa2,5b786d10,422f1d80,2c42cb37,27f09ff1,1f5e0dd9,bf6a6c1c), -S(42025e76,3c05c64c,311a275d,d6f1fb3f,2da2108a,39ed24be,3de83123,b1c1d1e9,dba2eec,7405b67c,a1915b13,45702062,7bfeebb8,6b90dbd4,87849e5a,756921c6)}, -{S(ef2c5fa8,b23285e3,50d7f05d,bd8c96bc,6e662824,5b10e1cb,4b659bc5,ded5836f,1b37679e,1177b653,8975790a,4d5d2abe,3626d636,1d863e0e,1db5881e,8e0c54a8), -S(a1d5a92c,93df3c75,a06f9c2b,a604789d,fd487513,62d957be,68c033e8,3e202fe7,64c1c00a,3964fd5,b35fb52,b423b285,77c8d269,bb1ffd16,325c5e0f,7be08bdb), -S(ef13ec66,d46813ce,68038fcd,541e5e8,bdbc970d,337d7b5b,9099d0e4,3fa4288,7ad7f4f0,c8345229,96341248,b1455ebb,89aaeb6e,1ae9db25,1b86930c,9f779fd9), -S(aea7cf4c,afc1079e,e61396b6,2df9bac3,bf334745,54af4678,8621e337,4c7486c7,c0538605,5911c893,459b98b0,4be449f1,2e9f98cf,ef4cc292,9975d42a,f460d65), -S(8f082b3b,6476b4e9,ffb317e6,1fec0cbe,8e389041,1fdc87d6,8d4d26f5,44c2e6e3,eafc2bd0,d6570a7a,cf8bb5d1,6cdc1020,456473c9,e7fec1b7,fc6217cd,89d0a2a1), -S(e0d6310d,e5e664b3,164faddf,39c93676,4ddd3f0d,f5e007ef,5293ee35,980ae0cc,de093cfa,ca1033bf,47e88723,4978758a,74b93cc5,2cef48a3,daf4dda9,adc79ccb), -S(2518110d,5d064422,5ead0e2a,5ac8b8b6,b1fb7fe1,55e351c5,1d39673d,dab0f6a7,84f0d6e4,b497043a,95b6af9d,e72cd502,a7b6a68d,ecaa01b0,9e0d8ff9,9d8a16c9), -S(6dc820b8,5db42353,c97453eb,d7d768cc,af9732d7,c261bc6f,8399caab,34cf5b93,30b168c0,2509e2f7,2035f60,8be8b89d,577b6e72,540f521,934fe980,7412459c), -S(bddc1c75,5bca9911,3c9ae05d,c14441e,2c707fe5,8a329f8d,feaa36ff,12771376,8c0087ca,b7688dcf,5a3cf1a3,3c27c7b9,cee36007,3aeb9b9f,d7088623,af20f62a), -S(b6e5ef5a,a84c6d2c,a209d50e,8fa8e1d7,93c61ed9,bfbc22d5,2ecf293c,9489ac13,f76e3adc,a89cb983,b6b670f9,5a7e774a,c015de5,1ba56417,40ac1f68,e3df377a), -S(26699dfe,93788eb8,d91cb601,cae628e5,75e8468e,73f6cefe,588755b8,c396071c,e5f9e00f,bcf6f1cc,cd39ab13,41cd06b0,ef2e789a,17d761f6,6a7a83b1,c036791f), -S(72f7e16f,77f0a4f7,92db2cd0,354382af,34282dc0,7b8cb290,a89a5d60,894e8090,54d32ecc,2cd022c6,c03f1379,657450b0,db9f08e9,6e2be5ab,5233dd84,62733cf), -S(f84ae7f8,a03b60,af9cc359,36f0ae78,96935b2c,534f852,8ad159bb,6c0b44e7,68f4dfc6,20a354d9,d6904bae,67792622,337e3180,ab340828,80bf04fd,f47cc23b), -S(5dea33b1,b5207880,6debbcbf,83ca17db,4617488c,ac5c6997,ad4092a9,8a7bff7b,99976fe5,ae88d36f,597e16bc,6dbbd4b4,547f4dcd,7e85786c,d10af30e,1d81bbaa), -S(31be76bd,4f946e41,7de73037,ceaa0dd7,c6eccedd,74399e14,2ae6fb2f,d2b59def,54ad8748,ef129085,dc3172aa,904cc376,e203fa69,38783007,2af33889,52cc6549), -S(b6124d0b,f603a00a,22662897,8dd0da87,fcaca5c4,fb04ebaa,81a7d13b,39f2e307,34ce08c7,4463b06c,afb03c02,583288eb,7bfa6f2d,3eedfed4,91e31781,dcff10da), -S(6aa4bd60,90bee70a,295c451c,c8af72bd,3665680f,545f46c0,bf5af990,aab5f43d,9c2364d8,25406b76,94ec9db,a0ea2f9d,bb36fb2c,5bda62a2,bec941c6,874e68f7), -S(f72faef0,e268a7b0,a9b00a57,3674d846,c1f0dcab,c9a586da,be318b1c,d2874d8b,16b3cfda,65db0f3d,1b5274cd,20b1329e,61ea0404,1f702e71,cd98708e,28c9307), -S(1d26df15,98a6b9a8,7c0a6171,767539e1,86d51d1d,cef130da,1001226f,87872c5c,f227cd82,becf5493,e2fc7635,6a37bb48,3e681a19,ab4d9dc7,92edb114,3a7b072e), -S(28690cb1,db697840,13e9eec4,d9388723,4c28451c,cf9dd51a,746d1274,b13b4610,d9bc39ef,19228981,a1ead1f8,94deb254,162fed5d,cbb58a76,6d361e04,3d8f62ea), -S(4b0b5258,22dbc31b,1966b004,4d39c5de,f2e16d5,1e032045,f9973b1e,fe83ca12,2db33ff4,3631fdc3,b3608b40,7dd494f6,ae730212,9619ae35,f6ea08eb,51aded12), -S(a5b4e205,462ae419,8fffc1e7,393d366f,c5a9eea4,e98c67ee,1684d63f,cc09aa64,d3c11017,de4ad175,17cd076f,cf6c0ce0,4d3108ed,60eabdf0,935499f9,4226078b), -S(d4f1af69,2a3e9fee,1f92d892,b14eef6a,a0ec1f4e,d4d455f3,c70bcb19,52fa9837,115c7ee,73b90adf,f142191b,eca0be01,7d5a651f,93e2e90,5a36646e,21790294), -S(c275c715,9d6e9757,d2adef47,2ee53856,dcf067db,bd4f380e,892c9832,708d46b6,70da1cdd,853a0dc8,a6a9043,3c319371,25590c9,5807284c,ae168f65,62e4465e), -S(d2e38b27,83156e2a,a8e4eac0,149bf2bd,bc2918af,1cfa2a23,d1c7136e,15dca7b,738a0fe,751ecfa3,459e005f,72b7461f,a4b5e1ed,736420d2,22c5428e,2ec1348c), -S(f8f5b3d,b3659174,e0149fc6,fa747c22,9607c434,8f9eab60,900bfe92,b23f9a4d,d89eff33,94a093fb,549fece1,4e11028a,614cdce2,21d5ac26,1bc25f32,dca3919c), -S(5e266403,e49fb860,e6ed0928,45bc0811,a214a0e,dcd6174b,290ecca9,3539d862,ab300acf,5d8b8a14,2fc9e93f,ea995d2c,d7a2bdb8,6a146f65,2b8bd49c,4e8dac1e), -S(8ff869a7,60230ba6,aa5adf91,1ba61702,17cbfdc,5ffa4018,b8a09b9e,4088d634,db5a5aae,bdb946db,80e4c207,22ce38c9,4921bf41,47eea510,70e5aac5,c592f32a), -S(f3d39b65,95bd5ab9,aeedc43f,f49bdb20,73a211f4,5ec2c1b7,72226a97,a31c059b,ea41abf,9322d733,bb5971ac,194da6a0,a6d41c6c,a0d0acaf,a53e17bd,dabcdc68), -S(18ba0c34,10169914,7f7589f9,179b94f9,daed92c9,287f3468,d283bdcc,d71cc637,b3512d25,c199d2a4,c115bd11,eb53d6a1,6ef16c3d,97be6291,5ff76b76,890ba675), -S(2cf3354d,7f96c58f,3c6336a0,6fa30c83,8da767af,48f89fc5,5ced5b40,e0b86cee,403ac306,f6c3ad55,be1ee5bc,29cdd46e,2e3d83ac,71050909,5f117d21,7ef015cf), -S(5d31d140,f754d6c,5943deb7,6aa4d867,cac81abd,9911618b,82327795,da8d085f,c25f99d0,5bc5d583,a3a72b41,4e5eac5f,c14ced01,98247ded,79ba482c,882bec49)}, -{S(e0ad91c6,6ca95326,d440f44,df91c1cd,cd3ec344,e906d0ef,51fd4a48,31ce293d,3559f3c,e349f7b3,cf66c17b,2c3fe7e6,8ba3804e,438c0816,b68ecfe2,30da18d), -S(d8b8c50c,ae9f285f,d6d9282c,373607d8,5fda59dc,71ba0066,148b378b,37440076,ef83dd08,ddc115cc,24948009,f9eb4afe,dcd65c64,b6ef2194,bb4ddd0f,ece180e6), -S(881fbbf1,a9627bd,369abbc2,edda8026,a61b10f,4161e442,530a5e36,447a0290,6a63cb8f,7e5094d3,c8beba5a,2a1d7b54,bc33005c,efdd5a1b,20d51f74,d00c2fcc), -S(36bc0df,fd1441be,1a4efd6a,43ab9d83,243d44bc,a6e108dc,fa9a79fe,23106f0e,eeec58b7,dc37eedb,4432dcff,4de7f88b,2a0e0721,da2c0a72,eadac4dd,71037ed9), -S(7652c155,c2ca8a23,7680f015,a62c7c31,31682752,a99c4329,77ccfb9d,cb58b03e,5339a51b,36ad4548,197d3018,4bde4428,b38ed983,d624bd18,a5f8c4e7,21871c5), -S(904774bb,fb8b0c12,e2b3f91a,e5a2a0c1,a92971f9,86e29fda,9edc609e,e85b222d,ee843f1,8039e251,9c7b23b3,725ca099,114b4f0,26970111,35ded92b,94445e2d), -S(1c7c82cb,fc14b9b2,cdb3c12c,32df33b6,a08e7af9,df62f310,79fa0710,f28f5f95,93471b5a,17c84eea,a45948df,80c0f56,d8684f35,1aa2ce73,ab84b3c,1b8250a4), -S(bb060f5d,971ce062,427a5630,8f114532,40ec54fe,6479d5e7,9ce81444,27f07927,fcbeaa69,8278eff3,d4dad904,836c0233,40a866b2,d8f66774,70d1159e,201501dd), -S(287c5b8b,8dc168ea,197200ea,97c4f63d,db0b620c,7f30d623,7934f856,a558438a,260630e6,ce310eb0,366acd78,bb58f4ef,27fe4836,edc8ff0f,5d5ff987,b659bd20), -S(7d4c5c6a,d6bb0f0a,47b45a35,1264f4e6,a81ee0b1,65a7e665,4b226c95,feb59dbb,e89691f3,ceb4c57f,5aabc1b7,4acd9aef,41531851,b41ec1c6,608f16a2,2243ab5e), -S(ff806f2b,9eaea4f6,47d85077,d8aa5052,9d4b96d2,1e0b31e0,7c86b14b,73b7ab4f,9acc2f77,a994997c,7a2b1aa0,79c0b5d4,c84f6715,e4a50e33,628b871f,8885ef9), -S(3ce795ba,1d91a9bc,b0260654,3450ced8,c94184dc,8a41ac5,e1b84856,e88927de,3492e696,cd1ab2dd,587d4707,ae34fd67,3ab7902c,d0c0972f,ef419795,1ad88a1), -S(299ad528,afa3f36b,c80a757f,f081a8d,c4a6ddc2,d2b57fbe,1e3d361b,ee5a5d8c,9fe823da,74eda2f,266a8e9b,331d511b,623dcd32,ef9ab7a7,f1d1cb4a,7e6fa65c), -S(bc4b0549,16177aa9,b52b29b7,cb91673c,9ffce4c,7d0066b,e4249383,4467e3b9,55bc6436,7db68687,e699cf6c,f2db9dd8,c2b9a438,8202fef5,11acdce0,ab06f969), -S(a8e8b02c,ff5de02a,9e6652cc,6fbe41cf,6e87ae0a,abb14ac5,a178b3d9,e697d0a1,285d4af9,405b03da,c57c993e,4b40df8e,82c6979,f8de57ce,4543b7ef,3381e0a8), -S(e50aa8b6,d7dcc055,4f406959,b056dac5,21a7842c,ffaf09a1,ac24a3d9,8aef5228,46656395,ee84d061,a9f5788a,cb05975d,5ffa5fae,edced564,1f81b5cd,2491c23f), -S(cb516899,98a214c3,c31e4f2,692cd7d,fad6f1aa,eb8afd1f,b29c23ce,429c224b,2292b8a4,5a89eb80,167238ef,2027f975,98a2aea9,a4460c5,3646d088,82403c63), -S(ded04c06,74c6eb16,557b5bed,4b6703d2,cc37c6aa,bae466e,ee7b5665,6693c3c9,4f3ea70f,8e75b02b,76934cc3,645d2af,eee8e9d0,8d100117,40e8a16c,dbf01113), -S(f3d0a253,edb74436,897e6cc6,621c74e1,30457b41,e0690b6f,7b2a203e,8ccf8ac8,89cb07e0,97495bdf,403490fa,d58eefe3,e79ffa33,1deb5cfd,2c548ec0,8771be67), -S(d4c66267,aa73ed55,bd68fee3,2a166a4a,4ec660fc,4cb13e18,fb6ab0fb,19a5f330,7c2efa2e,4509b221,97589483,40b6c74a,8ee2b5b6,5fbb794,7f838c47,ee03e2f0), -S(dbe9a638,f262f9a4,b3a8955f,22293feb,50ef4b32,20df0184,f363a373,d7110981,4c563e83,5e957756,5e6a8996,97510c67,9561972e,5601c1cb,2f2f789a,c1e0b5dc), -S(70c7c07,1b1e6fd0,a97b55cc,5ee34297,166f4d02,417a796b,eadcfd43,96e1b338,b5c49a6e,2ab03e55,f4755f37,e5211d4b,e23339d9,d464fd28,6781bb29,56db23bb), -S(aabc501c,6d52961a,a613fe66,96f0bacf,fad74fcf,8386cbf8,b18704bc,a1392ffc,cb72ba86,70bc3f7c,85a00d3d,76b11596,6cfa0fc7,44b31e01,9129da9,a5b04b77), -S(47f72ec6,e7820788,f0f7814f,aefd6e2e,af5d90f3,f877677d,ae72569f,c6a2e8f5,6709731b,ef2dd880,4696a6,a0661d13,fe579704,5e0a9bc0,e5fdc0af,789c5830), -S(20026251,d9413e42,47a5884c,209b144c,98e36f7d,8ef3f56a,68efd475,8a2ba8c6,9c5531b6,94ba0d24,a943d0c0,94bb623,75c798ca,c9716181,a9d659af,2acb978c), -S(8dfc6293,9b300c9b,fb617d23,6885f652,424b4f12,d04f8bf1,151d1ccf,935e445d,9a519433,18e94107,5472aa9d,6ec3390,59bd3bcb,bbbf6937,c9290e48,9da25f8f), -S(afef3520,3b558495,6fde0eff,5cfab48d,8fb08806,3c1d7cbe,d7e352c2,9d49176f,a764e6e7,bd0c8fa0,8a6f7f30,aa38d7de,fe71773,fb7ea484,68b3fd9a,8adfd650), -S(354c0a98,1628dfff,8be8ede,ed809db4,bc39c686,39a26828,ff28dd47,90801c46,8ff40299,d607036b,acd7c0ab,66a102ab,38f8d3a8,a271e2a5,20b43cbb,687cce6e), -S(da2e7eb1,1a1e66d9,5001ec4,f7b66c1e,d9f7d0ba,ea3bb326,672b9069,5cf4bebb,cbc1c7da,b9bf7e0c,dea9297c,5f45ad0b,9c4fb093,318b55f6,1e4a8951,726c4021), -S(6f780994,d0662667,8fa74156,4232bafb,b3a7f54b,a5b66507,9df32545,c192c3fb,5f11f0f3,af1a763e,4c9fdcb1,1e5e57a5,6dfe0d0f,f27535b4,4343a312,90e375e3), -S(8e28948c,729c1438,5bd09316,31ed3eb8,7acfc5f4,2a9eb4f8,afa50362,33591cec,2c09fa1c,bf0044eb,a78ae81f,bdbd4271,2a89ffdc,f7d476af,881d29fa,2627f250), -S(4011cf05,a85ef14f,1875cf3f,4f78a51,a52a89bd,a8930a4b,8e13802d,b85f319f,35045b10,45c4f71c,c762fa78,5b8d4daf,aa2a1c07,ba37d82d,ee0592ae,ad807810)}, -{S(9089bcb7,1c1559bf,e17f6c0b,91fc098,c63785fa,18a42d69,798b063f,a0930175,de229175,5e4ebf17,1047f79a,37d81b9f,9004a7cf,df747589,7365e174,ae367969), -S(4d1caeb3,41f25459,3b06f715,9e9418df,e29ee076,76c26e6a,51d8add2,5c70a5d1,bf773e4e,4151d17,650aa7ed,1d6a5505,2d622264,75c50f31,3261aea2,cf68dc37), -S(b0760330,517c0d66,2571cfae,830da7fc,a7e0d86c,1ca7f75f,5150f625,db50ad2,d8d10ef3,9c84bc13,32c2cc01,4d4df0fb,45e5c546,1849fb1b,81b7fdd0,7484d35b), -S(3db731e4,273e5b20,2de984c9,74b4112a,d0feebe3,7bb0d2c7,db38c7a,21bd8c67,b425c1d3,46b6a61f,2893a3aa,a243d60f,5563cba2,40018cca,3f80925f,71f4f1b1), -S(3a74a50d,cfbf2ff2,5c99c4d0,1a13a917,9f510c2d,eca1d5a,7ac8fb69,7eb9795,d2b468b6,714681f4,57bc586f,40585c01,e1dc14a1,a42ce887,9ce044d9,ddb92d82), -S(b9139ad5,4f44fed8,4917ad55,c49c23c7,8d62aadc,e83c9ebd,9efde865,cb1eb298,18068856,c80abc3e,2a02a441,bb7a7609,aae8d2d7,8abf4e2e,378fa3d0,a27aa900), -S(bcf5cf94,5887f183,e58a0128,4ed9a4f9,fcf918dd,4e68d70c,5a54eeff,166cb44c,8235f63b,bb06a1a6,d9ad2ae8,47aeb2b3,4838c962,9608943a,93294c6d,e21a3ab9), -S(4b598ce3,a77680c4,c5f66e90,1b76627a,27f35301,9641520f,53ea3894,dcbbd187,357af043,f77cb9fe,c04ce1f4,dd9b610f,9151d15b,3b7383e4,ecc5384a,8ff7c5cd), -S(b588aec9,2dc045e9,a95abd7e,da929837,28b5a7dc,d637001,ce7f0917,1283b16e,e682f53b,5e94fd84,914b7bed,5afc28a,30ae6f53,e12d948b,3c0d88fd,adc5d0e6), -S(eb8f5080,218ac5c3,cd792042,b59e80ed,e3857a75,a81d67e0,7c2221de,d3b7a677,c5f272cc,3734e0f4,6a5cf40,626973ae,1aa76839,1953f211,eb52693d,254a7fc3), -S(87d119ee,65a60dd9,aac3e784,22049cfb,4123d262,ac9e7473,4c9cc418,fb7ce4f0,5185ac,7bcaee8f,f1334eeb,cdf2c39e,83b8b665,1ef9d8f5,48a029c6,464242da), -S(cfd0438b,186d0f5,c64b5f38,a190baf7,35b67512,a439f486,fb79d501,90294683,985edeea,243e9c6b,d9c57cb5,c7372202,7492156f,e10bd2e5,67edd14,8603daf6), -S(52abfb67,5fa8b12f,1b0cf0d,8e85f402,47696662,64c7252f,69562590,839ce4f8,8483ab43,2d4851d7,4f432c0a,8e3863b9,783cff58,3d4c390a,9865d7f7,d1aed67f), -S(52926df,cf12eebd,3008459d,3c91dc1,73532f1d,ce3c5d0a,874ea4c,67331787,18b48fe6,1bd74ac6,4b34f2d0,e7de8920,2c875625,bcad84bd,cb3c81dc,cc86dd87), -S(695e09db,8c4479cf,4c305005,b5737ca0,63f89d02,aced2010,5600d65f,58e26401,32123a91,8bb23fd8,79715cc7,488184b7,53e0eb00,6dbbc95a,ef9d815f,3833c08d), -S(97c35716,e5aac70c,45dcdd45,a5ca0155,5962f09a,cc22c16b,c79ec272,ce1c12d3,93869464,6470f8e3,c0db18b6,2e4378e6,5caa7203,c4d6a079,a10c8182,b8eaec3a), -S(35197cbb,8da9188a,fc60faf9,71cf08fe,73372e15,f857b93b,6afd77e6,bf4db7ed,4e0efeb5,2db601dc,a539c777,14f4aede,c5ff121d,77dbdeee,7f16fb0c,4cfc19af), -S(afb2f842,e0818237,46c294b5,9ae8afd2,279e834f,100f7d1a,58a9551a,98408d49,5bf5ac43,a3609b4f,f058d6dc,6ae09fec,19a19864,6d12096b,6bd3e06d,95d15ae8), -S(a37f6113,882459,b1dc6335,26253a8d,287c9285,b7862721,f9bee74a,d2c4c09b,9ed3252a,303c6d,e01c9985,c5b3edce,1074d478,db56b961,d91fdaf5,1b1d07cd), -S(4579a503,cb12a345,182b28f6,9a3fb98c,4a80579b,2ff592d1,ab18b32d,212098d8,8c61c503,df79dcf2,6083f15b,c3ee1f99,9e1e0960,8bf6af9f,b3175699,cb0e32d5), -S(545031f7,883a2c8e,bd56a405,52719096,4aa1d40d,b22a1730,242f3064,530ce326,ecb024e8,e762b456,f62072e,5f471180,bbc817e7,54e830ee,7757ed7b,df5c9300), -S(b127fb32,bb3e193c,99d232e,d50dcad0,3b45c072,e0d521dd,de72daa9,e20e97b4,b198428,12a344b9,2e8a8d26,f7964c66,82cb3652,66ab3e28,2ba56197,a159f1a), -S(28cb3582,d312cfcc,75ab637d,66c646f7,5157dc74,7a464e9b,933c0820,2326b6cd,a87042b8,510ef9b3,ecf918d,916128e5,f946f43,6f18fd5f,ad62c46c,5882a23c), -S(8a46cb3,27efbeb6,850e3861,c4845ab1,21414f12,9fb27387,4560826d,c9116886,ab09eda1,9156f1f7,194b7b17,fce15268,ba041c96,24765ce,fd964ede,d1f05b3e), -S(b73af914,10ad56f7,d490dc37,1a2584bb,633de0f5,3f00cd0f,6b8a6019,53c7ef16,3dbf4e52,753e5d33,3fd23cc1,c839f278,38eacb3d,5980cba5,bf1be426,b27641a4), -S(b38c1896,427a0108,3f24a917,2a64314c,d9dc1759,60971135,1b2db6f7,d66ab745,d3a71a74,f80d6919,b65629f9,80c7757a,cc49c2aa,78dc67d3,d6f76d06,91a90d85), -S(6f6ac108,aa819a27,6dae862e,276b3ebd,8ed5a3ad,9b0296e0,4f8b65a7,f6a5ac1a,e3048583,7aa2140e,de381363,788d6d95,25a7ee33,9e3a3ed1,2518619b,30d9f71), -S(72f5809c,7c282ab3,4dd81851,33070d85,53999a6f,14fd753f,2ed8deec,ed7adc5b,112bf5fc,8cfd71e1,84ca1967,d05da765,801f12b4,c852768f,60afa7f1,e9576534), -S(4c348833,10f7dd6f,b385ce25,e2d6eef9,8556a59b,5e79a084,ec83425b,37150085,9c4c97e1,be47b073,5209ecf1,5f05cd8a,58ece74c,1b35a92d,96a70287,11d95add), -S(f16e4513,2291b577,ab360b42,c1babcdd,ac61e623,da85819,e9c4c73d,463204b2,5556d7d3,a2d45955,28781d15,16b59aad,941ea356,1b5c88ec,94d09314,555ea64b), -S(3580d3f7,896fb70e,d48d40f8,1b31a72b,51405574,2c2b4369,e3e7dcb,aca4ca22,e38da3af,f409e459,82098305,87aa0eb3,b2339959,75af2e33,501115ce,648360ee), -S(407e63d2,c0cd6d37,84c27734,f7e517fb,4bdf7847,296dc7c,a8714fab,16199828,2dbe5da7,4b29bcc,fe9adabb,69157830,987ac51f,389c6001,2577f298,710025f1)}, -{S(f61f644b,e2414c07,66c6caf7,5d32683d,efafb133,cb4d341d,7eb565e8,9f6e4158,2848548f,15a6e7d7,2b2eefc1,1b76e318,15ebb4b2,1e3bb938,e0c2e9d4,5ad4f7d1), -S(5b891f8,ec902550,429a5ea8,33fc29c0,bfdddf6b,a6f62c19,87a14050,a9689a9e,77901539,1ef92985,6d3e3b35,4e4ba2db,3bad967c,dedf331a,c0bff08e,f25f2e99), -S(d8c5a617,62655ffa,c943ba35,3b595b46,88012282,af068e52,d918bbec,46bec87b,9263db7f,6f74aa,df0dbdaa,7e7ccd76,cb3a498b,44de2bd5,f9b23029,2ebc6009), -S(2e940645,cd189edd,2d6cc2f4,f9b49e4d,305cfe8a,46f2a596,fbb55200,89fa5b21,4c197028,e89ef8a5,b5b6cbb1,3733e90,408877fe,7425d58,1f4bd063,ce286fb2), -S(396c3bd0,9c6af07d,123a8441,c9f79ab3,a783b8f3,fdd69dba,ba61c7ec,f65e3098,534c8657,aeb8cdc6,ea34b372,68f1c70,70881797,46b8e335,477c8525,cd17aa8b), -S(c34e6be,b079f3e8,d1355754,4246d2b7,a82d551b,740b4b59,b9220bbb,768796fe,57806a7,653ff7f9,3d7cb6,b3acf68e,aed049c5,75988fa5,f03b1ab5,1103aee8), -S(5d2d6aa5,252fc9b2,55d89773,e920891e,7021f233,5f7d0ff8,c6bde5eb,b65c5149,1fdbd2c5,6b8bd095,2d16c304,8d9c588b,2a26379a,17f748d,f1345695,1c5959c4), -S(dec812f5,745fcbed,fc36c635,76874bc5,96dde8ef,68a8724c,201b6af3,be7c6e2c,1715328a,f75f9661,d58c667e,5c5514d4,c99dc881,8cfbe702,e0c3c8cf,662e6906), -S(32499061,83487250,f65684b9,9434489d,3a83ec93,61531dfe,48086b2e,b2bd18fa,53217af1,2a25fc6f,45555d93,98fe46df,4247d38d,7b162e34,945f8928,bfe148ba), -S(d3e9381d,83f31116,ee161490,c9b5d1e5,7e086c6c,1552160,2c913315,af033ddb,97ae863d,34271b26,a4d6577a,32028c12,f092a54,8a18ae1b,a83de384,3b8fb84), -S(1347dca6,d097faa5,7c6583c1,c292c6b3,ed87b31e,9f7afe8f,d0d151ee,50ebdeb0,570a9be,e4806ee3,e30696c9,71b5d905,65d09ee6,8b4fa8e2,8acc54c0,7fabb492), -S(691f9995,af2bccbb,f556f624,b28a1da0,67854c15,4f014e92,a56a8cdd,9a43c25c,81babe0,ae44984c,bfdfa958,4dc5c677,881d1b0f,63993075,a3fc462d,e986866a), -S(cbfb62c0,b91cedb2,5a9d4b3,ada43cac,7839dd18,33174711,24688ca5,5f162cb,77c12161,e8199410,b040dd57,4d90c39c,2f1b499e,6b7c17c7,fb21438d,aff4e674), -S(53627516,8de62d6,2c792f64,f87996af,3ed8ec88,653532a8,ad60942e,cae4a339,d8449a0c,c6ae32ff,45a11652,97b3d3a0,57e67c64,42d3bdb1,ea2cbcbc,cf0655cc), -S(2a81679,7505601c,763e6f6d,f7ed5c0c,14ee7fbf,d75b8755,7bd57f3b,e2d3c7c,99f26af2,10540397,b8423da2,c4809942,63734d99,f0d642d8,96b5f216,767b759e), -S(54b2c03b,7a7ea964,220a255b,bb688767,99ff1b83,f0934e4f,fd03c2bb,51490e22,b3cc56a9,ada9240a,a3730828,26733090,ace3d7e3,91200d08,2cbfacfc,bcdb9c08), -S(aac88c8b,7c96e629,6f023e5e,8f260324,9f4e645,bd701705,8f38e9f3,a034eb57,da03ca87,b98ab6fb,e4869756,7c2db04b,7f9948d9,ea65d93f,d222d52f,6d48c552), -S(bfdd8394,fb49f93d,630f6b8d,469da38b,105529d6,70b9a1ab,e3196816,d2a13978,39a97919,4249f78e,c336b00e,475722e8,7ca734d4,3d1e97d4,d2aed074,abfacbe9), -S(5b5dc3d8,66ba3647,d2aab2ac,3338abbe,4d1ca08c,6cc6fb26,4335f40d,4dfb2331,3432ba31,46a0f15a,beca45e4,1ded8729,e6a0a49e,70315745,bfcb3388,4e1b9e64), -S(77057b28,a1d139a1,91e05ad,a8d72f3a,c7bbd198,7647070a,b6a21355,7bc0c73c,46f32321,4519afd2,f830cf7d,567aacc9,47ae6b8f,8c841adf,988e39ad,e7b9757b), -S(f6c8d1da,e28a3d23,2a388998,1b638b23,f381618f,18dc81ed,67bfa696,4cf1626f,2ad8c92d,43378941,8d298dc8,2cbf288e,86d21467,ac73c0e3,383ef3e0,a03142fe), -S(b75b5cc3,77a55310,a3b97067,34f1929,fc0db732,3265e6da,71405f37,729d5a90,be077940,4dc94ea3,3cff505c,e1aef457,bc120359,521eae05,1de1963d,b1948053), -S(a66d54d4,4b4d06ea,f141307e,27e1c225,41274eef,5c0b1743,e6398b22,fbaa4068,51b6b8a8,48e1c27f,107f82cd,d0554643,b9e16611,fa93b789,a2199b3e,3bdce296), -S(56b2f9,ab707dde,3479d0ea,baeb62a7,6cb9bf03,66278eed,559e027e,a1ea6b3b,27c47e9d,646684dd,2a54db0f,c245fcdd,721416f7,22ed568b,736e3e1b,f195b379), -S(a9642a49,83b19c3f,f5f63ea2,9e76afbf,a25dd0c0,221b32b7,6e67373,36e7f5db,8ada3766,9207c6b6,a6b6006b,5240a4d6,cdb8b807,c0c16a56,91289b7d,62b3a051), -S(18eef8d,f9e64c1c,548db40,ad77d92b,11f3ac43,60c63792,5f7d598d,7d8d5155,806db24,eefc3a64,c84da338,937811e1,20c6d0e6,9cde79ee,9957a4fe,c53d0e12), -S(d11359fe,61861a36,8b3809cc,c727320e,42905036,774d0e83,98453ac0,68d404b9,d4182ce7,2500637c,8e14b977,34fcad09,f061838d,57c555fa,420fbd50,9abf6b81), -S(7ea072e8,f60ff273,9cad1d8f,c560f208,b54149a2,5748900b,50830e3f,738b2db2,af09e54b,d44feb44,b39956af,fdca6894,91c7c6fd,f029e71b,e780f8f6,77a48a0f), -S(f53406ab,9fb1317,b038dc28,f0165abc,115b37fa,77d23bc9,e51993a7,8a15ba00,a293f429,f7fb281,9cb60b53,b2e6f07,afb6537a,39a18be,a5ad4cfa,55aea13a), -S(b1674e5f,9f194a16,94fd12d1,4b64ac8,bba69432,241aefd9,9a1c49d,23287635,83cb0060,1f5c33be,9436d946,22c3b3ce,68d20733,ee1e2392,8c3d6c14,a7cde085), -S(22b72e08,66b96344,ee53b898,ea725f7a,b5832c12,7c0881ce,862ea945,5eafee85,b886e8e9,cba29b15,be5c22d6,ada99b02,1098be69,d1c500fe,6fd2ef8b,f1ecae25), -S(9b7151af,698a85d,2246c88e,8ffb14a0,c762c2e2,64ab70b7,e30e2434,9b8370b7,fd9c3d89,46ee9d90,e7fb6d26,796062eb,4cb6c160,76df4834,eecd2748,c8a7bb4b)}, -{S(5ba26c2d,53b04b63,d260c6cf,392786d9,41a1a7c,b88331c1,149cd3b9,9c207f5c,9c7f6303,bd72850e,d4da618,3427e7f3,eee078,6f67cf9,85d483ef,79c2eab7), -S(f7d26944,6d29f81e,39a44a88,49f12184,b9f42eef,16c5d88f,60c96a28,cf0c3e48,e7ec965e,d0a966a7,45087e09,a058421b,852c8a7c,3790a3ef,7abc6ccc,e17c6084), -S(98590b7d,36bd2ef9,37ce788b,22cab951,d921724b,87c3ad83,8263416f,b5a67dc9,b711c21e,5af72a36,5cc1b220,7ed09ebe,be918555,55e9239a,e9b03d75,c0261d5c), -S(92e1cc4e,5f57514e,9ed13535,5f3e2cda,b0b22f8,8f56a972,a657dba4,7263463d,14d296bd,452f2faa,7d6f42e1,550fe35b,3c47eb2e,fe7636c6,2eef90b2,e7822da8), -S(33de9b1b,e153bdd6,efaf9d1a,30aa9b3d,faf26a32,4486b6aa,ecb1f958,f11c4673,7ef29223,4d3a565b,c0f0e295,deffa3c9,a86a6bf1,933a084f,9334b790,51eb0270), -S(f9fad0b7,e1dfd4b2,47cd2cbe,bd863e1,95b3be25,6cf7a707,5d422b9b,f5631ca6,fd5262f9,e6ca0cee,e1c7e531,83d9f3c0,7ac518b,c024681b,56c06a1d,1826f5ef), -S(455ec5ea,f34c02c6,961469ed,27bc7883,c07c9a18,663e22ca,83830a66,569b2b36,4dbf1b57,a7de2fdd,7c0380c2,b38fa5d3,697a5995,8ca0c0f7,6405244d,bff4c9), -S(940fa05,d96fb400,bac8fa39,e696c536,71a490d7,c98b3851,ef76ed35,c62bac19,b6de17b4,1a045978,5755497f,1c2a953f,17554b4,20f2ccaa,9fcfedf3,5afb9b46), -S(16012402,4ded6478,72374af4,6daf9c2d,a9000841,9a7d4672,98b627c2,420981b,7c2607e0,a4b86f7a,d5df7371,60987d21,35d2ce2d,bc422ab9,b643d080,26f84323), -S(caf887e3,339046ff,42c629ff,c954873,2c629ecf,319c44be,6701a9f7,c81bf842,d253a688,3b3d51c5,a914ffb7,46e7ab68,70c2b1ab,5b7e46c1,7a5119e8,4ab6c878), -S(41a5b720,595bfc66,18406547,d59ec09b,4efba0ec,5bbd3191,9e9256ce,f40a7afb,87ee1be5,2233ba8c,82dc06a3,6fd0a1b,4ee8d7d3,ce89cb56,1dc96c19,dad79613), -S(8bdcbe80,fe8533a,174045a8,3cf9d89a,ca438ef0,8f6393cf,6e24d923,edb02586,8d21379f,c053e8dc,c628f0cb,83a7782c,b4e946e3,ca88d467,36232762,fc6f8fdf), -S(409a4482,6b6f0ff6,36178d65,aedd64cd,2d28b39f,3e9cd93d,a0afe712,b75fcd19,25a3bec4,74216dae,d686825b,bee6aac,487a6d07,606e5aed,7c3032df,f4911eba), -S(b7f414a8,4c0af927,64ed5b52,e96dad38,6995771c,2cd90af1,1986bdc3,cbeb61c0,702b0a68,4e93f0a6,26b807d8,8049db6a,3e65001a,d75a476c,e4be230,89574e8e), -S(58b0cdd7,bed4f327,bcecd493,d835c0f0,e45f6fa4,3687d1d2,f19de285,5bcb5c11,21b0a478,2c1d14db,9c67817d,7b23db21,a96e456e,62a85c3f,2a02c76d,78dcad10), -S(c75cbf00,893447ba,5b3f8462,9d6897ff,64be841a,9a6bb714,54adb849,8df03900,15f68903,ae20ae4b,9b3fc7c4,f8135936,c09de15,18317dde,bcf66190,2db79f72), -S(e6258fd4,b63be23f,38361a16,cf3f81cf,f2d7343e,515b2d0c,ea0bfe38,6d4400a9,aedca212,9b73e49b,9757cd7d,a39a1e92,f885b267,a188521b,32089ae7,6d351eb0), -S(7c61b66d,d76f759f,be92708,8b075147,2ba10db2,eee4f0a4,2eac1ad0,d2dac3a6,c2b79de,70372e1a,6c9449af,2612e34a,8e101cc2,81ef378b,97cd77aa,bff004af), -S(29c71194,bbe41f4e,b2f58bf5,799616c3,7b247283,c993bce4,630929d7,55f7c8c4,c0fb083f,d68f63d3,599c2da,9d0c1f03,b6903545,a47581ff,3caecbf4,359e0235), -S(f1cd983,5bd3eb61,f8207495,48da075b,ff4191ff,d5b1521a,a1f4413f,2173a68e,beac8102,13b643a9,4658cdbc,71713894,39b72abc,f8644697,2fe6310b,4ff0233f), -S(94f2137a,ae170855,3af3dd45,8f8fc9d3,c1bf07e4,35a62798,25d5b93a,37380144,e952d6af,b27f9b2b,80ccbe89,59fb8b15,5fe1b2db,f3ffbf14,cf9c1fe9,b8e8209d), -S(f4f0cd2,e28cb8a1,9b469b18,90033912,4a40a39e,67ae1642,a3a677b9,fa1a9a3c,75412f04,5c41770d,73d7cd77,bce0da96,1e6fc69,cfc6cb9,8f691d43,dce1e548), -S(15ba2fd,b652ea98,f2b326ee,e5e1629b,ec8f8e7a,36078d7,cb8a80c8,c943e98a,db416844,cf757376,cfcd5a9a,9a318b51,184f8c89,fcda3d97,e735c120,43d47c35), -S(5754903c,ffa8cb6a,3ffe3488,e484c498,69163b77,7c07183e,8d2da037,78b8da34,508312e,6c2fd008,fac12bd,afdf8e50,1940a81b,d05efd38,5277a85c,ccf125da), -S(3bc76f6b,8abc155a,dbba76a1,9c0fef85,373bb1bc,9775f431,1b3ccb12,9c7fb29c,48036702,aea467ec,daa8b809,97c41c07,9e38c414,f798bdc3,a531b08b,fb4ae303), -S(2992c410,306d3d40,313ef69c,a2e3383,88f592d4,a9c2bd36,ebd9f51e,883aa33,cdecc5df,41cd193a,ecb26700,baa42486,a0506372,d56de3e2,2fa09156,7b525519), -S(baa7d83d,6d70a528,e6392adb,b2af797c,72772b92,ace96a25,90d65c37,b0ff1bc,9943b555,4e44b480,28815d8b,e50189d3,6617e9b6,c8f07393,8309e04c,9978fad7), -S(935488ea,4c88c2e3,cda6c0ab,5b42d519,e7fabe09,fdd3e36a,7c78c9bd,730612fe,705c8f8b,228be0c5,539eae13,1f4f4bdc,2fecf6ce,6cc567c4,dc692af9,7c1d506d), -S(8edeb68d,e63c35e2,5e36bc8,61445a63,8b0637ab,d14557bc,f0b0648b,db43f86a,d20bd0ec,14ef4f35,68954130,6577ef85,baeeeed1,c1004130,80687a5a,94a9e9a3), -S(9a39617a,27c2ff2d,9869acff,b22fad1e,a7d04271,be154547,43234f54,7f21924b,917bf9f3,fe0563a9,8daacf90,dfdcd8eb,e657f023,3fb15711,79bc5ce6,e6f5dd56), -S(41dcb02d,21137ea3,a179b469,199f9ed7,9b831923,68719a4e,5c727ce0,d42e95d,4669d53,82147266,8327cd6b,31c21b80,d3394bf7,fa29a43c,2ed7441,d866f5e1), -S(d4e3e3cc,387e0364,6688a62d,9390d585,a69ff43e,1060811,431dea8,d868355e,3309af2c,b3d7ca6,55334f2e,c53de6aa,debf5d57,1618ecc2,9dc9830f,ec46144a)}, -{S(90edfd0,61871350,b7f1f029,c4114190,b050065b,2030a400,9a8a7a6f,4b92aae8,872d4f07,5f60ae2d,dcec2f12,98a22da2,53d54de4,fde85560,690dde89,1628db56), -S(27e3ce53,b4258f97,a499f408,ecab24f0,60aabae1,dafe992e,5a34952d,5e6e486,d393fad2,9be684f4,7ecec306,332ad969,75b79d29,b5863d98,5f959c4c,b8ffb442), -S(420f1078,27c75c95,d5bc657b,a46cbe2b,415a7d42,ad62cdf1,6c84ee89,22215379,8b257a28,e0b15fcc,ae0b555a,cdadf4a,be93bbb3,a208ee45,77710a9e,d58da7fa), -S(28859abc,b60a95e6,b26c0996,566bf798,60c1a194,2d3342f7,9655f286,32f9d5df,2a770426,5eeca5d8,87840cab,3923d868,aa7b7b18,f9d19941,738ca006,54ccba6b), -S(c33c317b,490e2266,2649a021,e87f6596,3897633c,90be208a,193f1d52,28614059,af850be0,d18708bf,d0e1f523,c1a4fda8,9a6c156a,55f82518,2bd99bb9,b999a358), -S(2333793d,b961d3d6,740fc725,6cf9d833,81b5dc92,85b6d83c,5c343aa8,5baea83b,accc199a,ced3012f,b6db99c4,7a36c30a,f88e7eee,b62c2ed4,1352b488,ba0167bd), -S(4834aa89,caa9c25,a99ee4da,e4a64c15,25a5d74f,9ce573ab,ff44b63f,c3a578aa,fb189539,448a265b,eb87a268,b71a18db,f12fe8ac,e502720,c83ca156,c1cc7a39), -S(432cc05f,c78b0d56,e605391f,e4708bda,a1ff3edc,96a729ca,aad3cb0,300c4d4d,6675d8ee,ece8c078,e1bad373,247ce383,d4c65519,4a6aed20,a7ca5eca,34a89c30), -S(874fda6c,b284ca2d,a216bbda,28249388,88da3968,7f615ab,52c8e61f,b72a1fd,2d7199e2,b0b88f45,18e6eeb1,240b2ffd,a9bfcee4,6f754a4a,3db7959,dfe857e6), -S(7fe21a0f,3ef67d60,1de05f67,2b163285,a5577948,ee78274b,19fc35cf,2d2f6801,62fb2ade,5e2fffe1,28542038,91a6ea73,aabfa35b,1f7fb000,95190adc,de6663f6), -S(cd0540e9,efe497b6,2beb2227,a2da819,a1ac3bed,8eae24c2,6e2991c0,a707dd69,446c3218,7d0c9229,d65dad2,1392e4a1,66445386,4a5c1620,bf768fad,20a45c06), -S(a533c295,74e78024,52218573,66c30001,6159d772,f5bedcff,28d7f7cc,3051457,b61a106e,e0166d54,5e1b945a,f3e4e285,31a34cb8,56a34dd0,cd21184a,9555eeee), -S(5e144f44,ed88845a,c089331c,eb58811e,4c164e02,5d1758ee,51a7a522,c66deb30,ff95cab7,597cf62f,e1aa8df8,a2cd3844,d71ab4dd,4eb02a9e,6175077d,261e2540), -S(97487a40,9562ee2,7620fc2b,c5bd55ac,6509d487,8ab41257,53884b97,7c5a84be,e52a282,1430c540,5f1143d0,62b69faa,16592f02,cb9b8602,d52c9fc3,70769091), -S(906f9ac1,d3db4690,d74771b7,f1940679,b0de7731,a68d7d35,89caae34,c3760eea,6f2be7,2275dd5,1e77a066,b8d3c303,f565cb97,b8fb0dd3,14445d18,876665a6), -S(4c355a31,d17617f3,5d4066c7,a125b2bf,1d6f77e6,27b585ba,2d271a29,a88c81b1,6a686e69,237b75a1,a1ecb86f,b715e858,35aa0686,e2ef10bb,38b762ca,5646e9db), -S(15aac1a8,9b6b7629,57375d4e,aad87c9d,e1fc2617,89e57d29,731fe96c,1380140c,2968c0b2,2c3dd83f,3286d37a,639bcc14,3d89e75f,cac1da56,7e07799a,62af1008), -S(4642f29b,37b87118,65767998,d00b41b9,fca6718d,bfc55785,1c459efc,2ea15037,a1ded31c,be33cc1,425df851,998ddd11,1518ed13,f84756c1,c7cc46cf,3f5e9a72), -S(9554abe,9e092bd2,c4ff46a0,abd0b7c7,fb73d85f,1c01fd96,83146559,306ea727,89e2c07d,db1fe6b0,9872ce91,66ce9ca8,1124986c,c7e48e09,f80aa3cd,70987711), -S(1c0977a,a773c56,2e36dd15,58b95fff,d35b4dea,ac464011,ad7b79cd,26227238,e04ce4c5,b0b165e9,87dfef97,d32094ea,3e86e6dc,33a4c96f,c9470336,34b0db68), -S(71d44171,60361c39,6295e5cf,b1540ef2,1ca046b5,98645a23,e8c9772,ac21be4f,7122d5b,32a654a0,1476a47f,d3317a25,ed51536,4a21253,f4068dc8,14660c55), -S(d906f59b,4d56bc12,f26d60e6,6fc31733,e5450707,89025ea3,8a6193c8,520ddbc7,cd7f414b,c6cc79aa,4c65b943,ff914234,a9d85cf1,9853be59,2a71fe1d,dbb20163), -S(11b7dfb3,17dd5c23,6b8084d4,f3cc157f,c25c0e70,8248b472,240963dd,9a3fbca7,dd2c8caa,2a2d14d7,fbec267c,9fe87ab2,8b1ddd92,dd100449,f75ef1da,97d4e5e), -S(3ef8274a,fca8fbb3,1894d7a2,d1ad59a9,4951b21,328b1e84,ecaa6df9,cc1ef473,2e4f0c04,f5da671d,4a2b641,46ae749,27bc35b5,98a54190,3883469b,3e7874de), -S(a861fc27,f5e6300d,ec0fbf6c,3315d053,98f90b84,2422992,bdfba11b,1c1c7e34,75a7458,5d98bca4,e3517897,afef848,8e524168,a586d8da,18834171,4b51846b), -S(9537019f,57d7869,2a358758,47e885bd,1594a426,4412c595,62eea9ba,4ab34de8,21bfd84e,a66650dd,79cc8c13,7217a351,57b9c046,938f20b7,246362c8,6637d5f4), -S(71c80c38,b1889d4f,507132a1,87af0c91,79994b84,1b816c8a,6d130a,df1b500f,8de1f76c,100e75b5,1572da6,d08c76b2,10cdc447,cf903e0e,2b00e002,5dee0ce2), -S(2fa9ce2f,59865d10,17880d74,d31cd446,5c28ff56,50f29e6b,d74a810,977ef9ec,6c5a2073,55c0dd3a,b994778a,6bd02b87,80ba8e1a,899330ee,cd8781b7,6e15cddc), -S(96ca6bb4,bf74c748,75703386,ae02dc29,13329d9e,a5395892,df1c6f57,4a84fa4a,fcb510b6,dcfe8da5,690f8fc9,4dea8ac0,e42af209,35c33347,b088cc79,52e98b1d), -S(36a066ae,694f2645,25cba884,956ebd46,ae568acf,11664965,63cee00d,a32f2199,5d1e975a,856ebd1a,cb1fe254,101e89ab,ea089e8a,b38bbd0f,1100e914,709fd965), -S(4922879f,800234c9,63f4b572,d236843,4c4da5c8,ff741982,c3d1e341,841d1309,9b259470,24b5f4cb,97c68d18,f7f8dfca,1e57f7de,63208765,2ce15770,98f35494), -S(ee27e2b,acf95f6d,dbb5ebae,bbf181bb,43322a3d,6db87e78,14e57a3d,41b581e0,3d6a18a,daf69ae4,88ecc9d8,7d6b1bf2,c8d65544,3f4b45b4,c5a0ac51,7b1dc3ca)} -#elif (COMB_BLOCKS == 43) && (COMB_TEETH == 6) && (COMB_SPACING == 1) -{S(e3adcb1a,fe947e6e,7cc4f5a2,df78310a,b235e2c3,bcd75eba,1904de80,c8814c50,e0b27ead,c4bbb9d2,37dad580,6e366674,4a9f9c3d,e024f2bd,1edb11d2,fafc0a22), -S(612c2ec6,f0e9c4ec,c2200d23,ddca77eb,d003be35,61e52b1,890bf846,3bb53ea5,9e944d7b,dfc7a952,c1c5ee15,485d7199,dda19551,2d729628,c215a9e0,285f656a), -S(42053dc0,9f90a7f7,86feca60,d68a5c3c,789e44d2,3479aa13,2d1a427c,621373a3,b338f891,f3930ec7,738669bb,3a29ae2d,637be08a,954f2a8c,acb661af,a660bd22), -S(4d227ea1,5194ed57,10f8ea4d,a639be04,fa68ecb4,f3d2d9c9,43ec32f2,80f74051,28a94075,bda4c195,40c20493,b5391df7,166b1264,b957fef9,683cfbec,4c6e6875), -S(8ec4abf4,d4db3b0,2b0712dc,ef54a405,54b6cac9,3f88fa9d,d8cad4c0,9b94eb1e,4e37e159,517346ee,17e948c4,a17912b0,b29c303e,497cfb38,16796752,99aaf9e8), -S(ab186398,117fb83d,db8b9392,cc888fe2,50d2f604,5a0c3f89,92d8a82c,382175c0,79437224,b3b1604c,fae64902,e3030448,51ef17b8,9af02d7c,54a92c34,7fa2abda), -S(2bd09ae7,1e8d85a2,ba550bf2,9c1787a2,3d2c8985,e2ed07bd,1d39e7b9,8ef8135,ddaebb19,195bfd6c,a44ce82f,b7f3c65a,8af935ae,52e2d2fb,33cc231d,c4b16082), -S(e6da6560,c8265e7c,8f62edca,78dc739b,74bd6543,44a939cd,bac0f489,12b920af,147f5ce4,a98377cb,981dfaf0,1a1e4740,238f1c5d,ee69cfff,a54f3aeb,e53980eb), -S(7df5abfa,d6b46a37,30bd5892,69edb6fa,b70a0d31,936c0787,407d5d6,96506263,bc5cbafd,1f5fee67,1aa449ff,bacefc67,cf7c529f,86100d7c,a8160e4c,376c76d4), -S(ad672823,cfe3ac01,50038d30,81a1a109,d8629b4a,a4e26779,373ee0db,44a466d9,c288397c,f91157e6,770c401e,dc84b328,87b22534,d11e11c,c8415a4b,743fef9b), -S(72032cac,3177c280,ceb3076d,7f510405,2413706c,956ecf38,acf410ad,a12473a6,8bbaf50b,95797824,2994e6d0,a4bf6d07,149792bf,f2a74847,1095f845,bb332036), -S(36a1f78c,3bebf8c7,1fae5e29,cf08485d,d9debdae,348a20,ad84ba5d,4308fec9,842f57e2,e900d07b,eefda7e5,9dc40139,c5deefcf,11c07c42,4629c59d,593e01af), -S(5f418454,72e80d51,1c1b8bc2,b6b89224,9119ed43,5b915809,f7b26d01,8427f579,dfc29fdc,f3c65221,a6615262,cebd9a14,acba91ba,cca22ec5,d84303cc,1fe0085e), -S(5577ced2,f6bf41f9,503aa4a7,c0060fae,6d33cda6,e3c8ec55,1eaec315,bb91fedb,858ded64,6c3d6231,87c0967a,84ee5253,2b21c4e5,b329bdbb,76f6a6d4,93cdcb4b), -S(bc74b56a,c94ef36f,2b356bc5,dfd11d2e,7a371087,653ad607,dbfcfeb8,27abc502,d57d74e7,39e758ee,96a422e2,f1fa61f7,4f6308f5,71e6dca6,3b0b0103,e83cf1f3), -S(727ed91f,be4c5086,50a0d365,b28ae4aa,c9434c0,735fce3c,7b3ebb42,f4be911a,8c595547,5e627c22,6bfa855a,22ebbc56,d3d0b331,9120d8e9,13bed868,7d3bf331), -S(6286bb90,71f8887b,c4fbb3f0,a9ecb19e,fcdd2cf1,5e286da7,1bb60c9b,5ff5e644,73731ec5,ea3e537c,c6060ac5,dde716b7,2aef4117,ba747b12,1c26fc9,eddbda74), -S(3905682b,72282a78,2b8d8dba,72cf147a,de0025dc,a21521e1,ea989040,c248852b,5da3bf52,dceaa14a,a3534068,c05bb015,2cf9c722,cc80c56,cf828ace,d96fc390), -S(561a2ccd,ca12b67f,dad28ee2,c3cee78a,cf811766,9e4a2543,c81b1ca6,eb4bd16e,3b386a9d,553c2746,893477f5,17a05e99,bbc8ddf0,896249e3,85e406d6,a57b9ed9), -S(75bdfa06,6a1a42a7,50f283e8,3ec91cc0,a5b68829,6e6aa24a,28a61e33,65f378e5,c73224ec,797d6736,c1a541ab,34523d91,e1ec3754,fe7fed44,474f9cba,29f305e5), -S(e881a840,847aa2e2,2417cd3d,3e798c56,1e630290,5dff6bf7,754d9419,98d401e3,8816d775,f1555452,f624e45,710a240e,90fc5e23,7536d217,cf555349,b5e31bac), -S(1fb527e9,4e9c70e8,657de745,8b81ef9e,e3c2b4e0,128a675b,f7e28980,e18b201e,bab00a09,1145407e,693d5353,7818bd30,49e1f364,757d228,58b8aac5,416e3e78), -S(1c2bd878,b94169da,722a9de0,c4e317ce,a8802aa9,60458301,11a89d1d,9de4270c,95b7d99,bc3df31e,f0dbf17a,a09ef148,71ae6c5d,870ebe75,1f52aaad,a48dfcc5), -S(41f7fa0a,9a59513a,e221e3b8,4b91995f,c9d40eb5,d120a6d8,e663452a,d92099c8,813dbbe,92ec4b62,25d1cc5e,5820ebb7,dbdc2964,d5dd1ab3,deabceb9,5e793d32), -S(e5cbd627,89c6a843,25a24407,89b88dbb,1dc55afb,9e8296e6,bb8af7de,57a50e60,2cf01cea,ae4f4fed,46c4efd7,86ca5e4d,ef5af524,e9393d74,e9dd224c,604b9408), -S(eb3bc68c,623b1f46,ab905412,c7f2d588,fa25abb7,7a7bd782,ba9bb3aa,c05a70ae,df9f46e0,5dc1d126,2f72ef3e,8db01fbc,11915af6,4aee0c51,da1cfa,b4d15ef0), -S(5702fb8a,2602f41f,52699f68,8d4b005a,128762e1,1dfd13fd,22ea751c,cbedb2ef,a77105b3,7af534e6,46f58c3,b02543fd,9e0666c1,58051952,a61f8389,73f5847), -S(66954eca,5434263,4036fc7,fc0fe33,81f5195e,88433bc3,2c5a8a60,341e2859,d8b1b14,40e9f123,f39c8658,f9d64e7d,fe4071f0,ada879ea,42eebad6,4d37f4fc), -S(592152c3,98d6c719,636a03a6,dad64246,a5a6814a,a62c156b,ce5332f,6759b031,8d22d1e2,d93dcccc,889f3b6e,dd5e2098,2f5586d4,bac06842,d689a37b,4b845c12), -S(5699b93f,c6e1bd29,e09a328d,657a607b,4155b61a,6b5fcbed,d7c12df7,c67df8f5,c147ee87,14325497,6b2e534c,e6902748,2a5c33dc,867732a5,8338f05,73368388), -S(c62c910e,502cb615,a27c5851,2b6cc2c9,4f5742f7,6cb3d12e,c993400a,3695d413,e80c2522,898d8a22,2c4dc0b9,8dc9ce88,740fe252,5144656a,c30f978d,dba83c1f), -S(0,0,3b,78ce563f,89a0ed94,14f5aa28,ad0d96d6,795f9c63,3f3979bf,72ae8202,983dc989,aec7f2ff,2ed91bdd,69ce02fc,700ca10,e59ddf3)}, -{S(efbbec14,ff6d7e18,a8015d68,ba3ceb19,d4cbfbb8,a1bbc09c,ce755a23,e9d4b3f4,a76faa08,2b02b8a4,405573c9,5ac067f3,ab936127,24bfc14e,a27f923d,3adf0133), -S(f02f6744,a0ee7b0c,7bf0abb3,c7ec0a5a,3275d109,92be2893,7e9ef649,23fa932d,955f3630,c5621787,13e6d8f,39efee26,d91a0947,8da36db9,4ab4a89f,aaf9019a), -S(1c6f9f0f,d6ecbca1,fbcfbe9d,1f3d2476,dbd3b6ca,ac8e18a5,949b993d,8c0063e5,e3e3770e,33081dc9,5125d69d,c631450e,5494d21b,2ddf48f1,fbc3169f,3cc1eb91), -S(2062725b,739b793d,c9798397,dfc7b1a7,24ebe8f7,5e5654df,536adff1,25970841,22f3e3e5,c0201265,5e6d8e58,b8ba633d,9a9216b5,445a7f78,a2605688,4a5b6092), -S(57ffda66,e0c29448,7a1570f7,e2f5dc58,ecf9b906,5f374046,5bd1734,841785df,22ae8728,a8800436,1264c380,3beddb65,a9dee575,6f0cfa97,c01dc047,3c806def), -S(4b49fa7d,463cbb43,b14928c6,7b3a85a6,8132ad9c,427d3cc3,bba76d1a,7c9a69dc,7e7e3133,3782b30,5c7c3bd6,94e3c306,b3f9829f,86f76f08,d44b1a76,a207f2c5), -S(411a3b18,c9b638fa,38a0e811,ee370f34,5c9476db,61df1843,863d6d7f,4e803ccf,bb306f97,e97e492d,e74afcd0,a771570a,8210b51,9e61df78,4e6e97e0,ac23e109), -S(c8227510,49de1572,37afdf55,d175196d,5d315001,3670b478,a0255a4c,ebe95075,16be5950,a3f12be9,5905fb52,8d5bd93,23eb5908,211d2e8c,26204b32,556c5c45), -S(e46bdb74,8692d0fa,e6fc9f50,6685487,31d61f8a,5717fb88,4e1f7a41,70e4997e,35398e06,48bea42,cc48fa4f,2805efbe,6bead663,c054eb08,2c15ad46,c0611052), -S(d18293cb,d0902dab,e4c014e1,22969601,84aedbbf,a01526a8,6978e144,88ca794f,3a5b423e,32c1d2f4,bf754f42,9da3c9b6,84bb798c,ea73f637,1777ba77,1aae6086), -S(7b9cbbfa,a53923fd,e9f50845,3130101,3b17548a,8097433,79d3a526,d1c90c31,3fd7b71,5b6801cf,30fe22a9,8b7895d8,1b483f6e,9fdefe7e,6c59fec8,fb9786b4), -S(ab6e185c,be9ee393,5ad6278c,167396fa,aa4d936,80524d16,27ca8e93,48fce67c,7154007d,3f96ce60,d09499a5,1262c7bc,3ab5e9aa,929e0594,994a9671,8f912987), -S(56ffb418,8b9c9c13,4a110c03,8df8636a,71141ff9,8448cb79,eb6dece8,a28b65b4,1d728ed5,23ab821,ac0c40e2,b9348e27,191536c6,79a73835,8bd9b3c,b43dcafe), -S(bdba1eff,bf6af786,dca1da26,cc226102,1f95d56f,245298c0,b87a40e1,fa9a0cbc,fa18673b,41f765b8,25d13f2d,7963f1c6,b3308a14,b033fecd,e1d0d597,583440b2), -S(d9a4a7f5,5b3af93b,1c49ffa7,4f8154e8,23aa1477,16b16441,39fbc86b,2d9346ef,19ca90e7,538ac3d8,a28e1aad,5d8b1dcc,756f8a84,240e5769,a0f561d,f53289b), -S(ee5c17b2,74c78b87,9eda9341,256b1506,25582835,60a0bdcc,c8eba320,32d58638,d7d02f4a,b81215b1,7843e3c6,abb63755,c7e05d20,6c61a4f6,bb08d1b0,256409ee), -S(6953ae81,7ec599fa,5f739bef,dc4cd8b,4670eac6,912bd03a,a3fbe91a,5122ba0b,61bca3fe,36245ced,31cae918,fab6d463,50856947,f64a3be,d0eb62d6,f9f16059), -S(3bd721f7,59f7c3a9,93474472,4ffd3e34,503cbe45,fa7fa5ef,40a5a173,b8bebcea,bd7cbfbb,797034c2,d293aa64,1bf175dc,74a44dba,84b8d99b,8182d2be,6512ef2), -S(ab6e36ae,f5b7ff2f,fd2f42f5,8c408b7f,3ac84253,e1d8a43a,55cac222,678dd38e,ff0dc59e,51e504b2,9a0ba824,3ef26eb1,2446f628,78293da2,d924028c,21f57342), -S(bf1a1f6d,7f73b09d,3efbd73,eb9ea2c6,23e17911,9063489b,42fb1303,7b53fce4,236566ae,5371fc97,b5449b9c,2db32175,90e02412,b44539d3,bda7a814,3cd4a634), -S(fa0c6aa3,4c4825de,304cfece,37a20bbb,f72044e3,94cad202,c9e1edc3,b288ed57,df8e64ba,5f5e8381,4b6891b6,14dd4753,fed5f566,956a6dd,95540bdd,25c73995), -S(d2ea634d,ab56961f,52e39ba8,ebc5c150,ba9eeb1c,6178aef9,64fa97d5,e80581c6,2928f71e,a09a35b9,6fc1976c,f6cd3c1c,7d1fcea0,2142eb80,9666917d,c9a0621b), -S(827d6a36,697cb2f1,cf19e27a,ac30c06d,20d818c9,fe869309,6435f1f2,171c9b75,53237d41,3781a1df,d0d977c2,9690d488,b051dc2a,841ba226,c552cc28,12ae7caf), -S(59dafec5,4df05695,e123004d,38d9aa12,6a06c399,e5215245,5392e5e3,f1a47dd6,ff7d173d,ceda39ec,ca8d2c95,ab1658a8,6ad99618,e3fdb7cb,b07b03c5,2f96a86b), -S(5c4f5b9,2acb30ee,8c7ec4b0,ec577f41,a9502af9,a5a384dd,3386f230,3e62a830,8aea5f7,145de3a3,679c86ce,72e8b36,f3d6ac81,bb1d2043,9d719c32,ca2f8b30), -S(38add3d6,209080c8,efb65551,3d9420aa,457f06ac,d3ec84e8,db84e208,a0664ba9,ad95a891,c60f01a1,5fcddf2c,923790e2,d5596334,4d83a21c,dfe5f6bc,4c2b32b3), -S(9038876f,21c3bc14,111d5f6a,4749d07,34e40a53,7d398c68,809355f,764cf1ba,da030216,5e661aff,53367578,4a4d3447,707f14af,cf0d771a,53e8e687,b9dc29e5), -S(b07d3e8,dbbe686e,5e163725,8402cac3,e1e4f29,fdf154f7,bf008c5f,9969da10,c8b668e0,56bf8173,2d9778e2,eaa069d0,cdfbf826,47f615c3,6d0b311a,b2e14922), -S(8bc89c2,f919ed15,8885c356,844d49,890905c7,9b357322,609c4570,6ce6b514,2cec0c32,283233e9,21889013,c4a76d3e,e8d2cfa9,eed8890f,909c0b30,5736aad8), -S(308913a2,7a52d922,2bc77683,8f73f576,a4d04712,2a9b184b,5ec32ad,51b03f6c,b5a4f6a,bc0141a0,6e1cace0,993fc8a2,57ccc015,7d42e0ed,9f54a102,1701afc8), -S(3f0e80e5,74456d8f,8fa64e04,4b2eb72e,a22eb53f,e1efe3a4,43933aca,7f8cb0e3,34992828,d693436e,16f463f7,b7a2fe4c,6afedac5,59a4ac5b,34fd761c,15a0bbe0), -S(d30199d7,4fb5a22d,47b6e054,e2f378ce,dacffcb8,9904a61d,75d0dbd4,7143e65,6afc7262,f51c2a3c,4c292136,167c7f9a,e089f33c,9b127e69,fa4c00df,dbef9176)}, -{S(983e1ca0,5dd64afe,8d39e15e,43c1cf9f,6badf550,12cdea89,5fd85021,b49f173b,18200e81,d75a745,c1ecfe5a,3ead988e,4327693b,7e3c0e04,329b0c80,3d9934ba), -S(4e1200fe,d3e5048f,f6c9fe53,cdff8ef7,5d78e601,4df471fe,369f3d1e,80e46674,a62aca58,4ecf32bd,cc297b38,c1951c71,a66966f,b9ceb2ad,de411da7,d175df94), -S(82f5f27b,83d49042,63e69f48,b676c9a9,2446955,cbc18ec7,fd4346fe,37e0b0a1,e523d039,d0b8ccae,737bfc11,9b83dfd3,d6878403,862618bd,40ddfc89,9a688557), -S(a8c0fd4e,ab1f0e3a,cab37da6,58fbab3d,949ad9a4,31d6461,b2648308,35762d19,950200a9,63c3dc2e,6d2771e2,eff401d1,f9ce037e,75782943,3fd3c560,a169713a), -S(25c1b464,33068900,bff89a4,ee973937,b03c11a,5b33d16c,4f672fd4,bfaa11f9,471f1f8c,df18e73a,e12cae35,43506cf2,c57894a8,f633ad4c,e1c5330f,eae42b43), -S(497e56ce,8793bfec,4dc6f972,dbaf4a72,aa5d8412,3bcac5d4,2aa9baf8,ccfd6723,1d3d028e,b70105b6,eae66785,5dfe7e0b,7c0a6b3a,b069a475,bd913aa9,c29cf426), -S(68a285b0,d30c2dbb,b543e480,f66824b1,69aa339f,7e2282c1,5dc60f50,8e3f2fa6,87529a0e,1d53588d,21064447,99a8fee8,ffc791a7,cacc9e26,f7a7d94b,25e74cdf), -S(721c92ae,931712f6,15f4d7c,498dda23,e1029dbc,944cea16,9442b22e,d755a100,7ef052e6,a0d2646c,a5dff39f,3b2a1019,de43e3b2,5e51913f,d636281d,cee74a85), -S(aae8418f,1b124d79,ad15f773,1bdcea1b,453493ad,4cb0cd6b,ee5c9a8e,34335ba3,c2558bb1,4a7addab,62d1f308,1a9e6fd5,92a06976,3be877d2,af9ae1e8,b510d98c), -S(b6a06052,b492d74,c68640de,8bd3251d,fbaaeb0,ce1eb997,f2127ead,4bd0b81,7bb4269c,4a9ece8b,e8ea2f0f,d663a193,2a571249,2814eb73,4ae1493a,6a97b39a), -S(42fbe048,38761203,11e43178,6af555ed,d7bea551,d4d5aa18,afaa4c05,2c6d0c19,9ba562c0,a4cdc664,87caf55c,291d8246,65c29f32,2a56360e,90138b06,f109d83b), -S(9d6dcb88,b378e7bd,233464e0,25e97bf9,97768e29,6e4aac31,301fa1c8,bfbcc27b,f434ea54,3f7269cb,1ae1279d,4178dd25,bbc337ad,2f0d5141,610dc061,80daa8c0), -S(fa6fa5c8,1e6713d8,90cd6f29,cc8b7d03,c5f8f2d5,88963652,7c199f6e,8f98e060,726194a,2a5da1b5,85eba1a5,5e06ce36,5aebb89d,ba5f7971,db3c1571,c848c5f9), -S(809167d6,85e432c7,372dc111,8573e620,d9ce7e9b,c3ebc15b,ea7e866a,3a8addf4,bf0cb694,f00fd1b4,b62119b3,9dd6c88a,22ef1fed,a94ac0a0,9cf33225,9298b968), -S(99d28ee0,962c1bd2,fa63109d,f5485653,964059df,bd514206,24117eb4,e582ad46,8cbdbb66,4ee209b3,419c0b80,36affa24,85cdfbc6,e6644429,33908490,f6f6353e), -S(559d0617,e0860cd1,87f1c68,e9a9951b,fef7dba,3a67594a,eade6e25,e2df593f,194595af,721e3b26,786fc25a,cf5b2d77,1fe00649,b0cc4938,7168a9ea,1fd2947e), -S(ab9a7228,f0d533a3,4a95af3a,51021b55,bb324229,8d101a66,eb362c97,eac48b02,80a6d111,e451eb09,cbebdd5,a3ce4fdb,42b3665,f8974df8,912221b0,fc7db6af), -S(42c6680d,18b0f528,274c2eb5,422e4731,560ea862,adcc4419,68bb5f3a,5bbfcf16,c8961934,e5bd6e7d,d64d4b1d,f7867c7b,978d182e,48315ae4,3fe2e082,a9455792), -S(e8bc0f9a,c3687bb,69627de1,df71fb34,21e0252a,e33d15da,3039a200,43ec3374,15de9e9e,2ac74839,5116ef76,1267300d,78c2e583,9286e6b6,366c8a6a,540036cf), -S(604ee928,4ea1c8a9,a0a75bf7,be3a5c02,8f52d71,b5fb6340,53401e8d,8f5d3d6,43bc16af,5875b25d,8e2427b3,3913f6e0,bda886a7,52a3b812,f8f191cf,f7bee54b), -S(7f589067,5b771ce,ac754412,a9984352,4f2a4a6b,a5cecae8,5106bb81,f7e4d9dd,a74f2eee,584696c6,88157a3f,fc27085c,6445c7eb,e363c6ed,7a1f5902,63de2024), -S(80aa63b3,1fdd0d2d,ef602bab,dd88a15,71abd052,270988a4,63abe269,fc489fcb,9a145d0f,6dcf0edb,a4873287,a2f221dc,4be613df,f70f7755,f28879a,6e7d9978), -S(ca9793bd,796ae0c1,d778f3,6445bb8b,aa50d859,4be28fe0,ea1e2d16,30972503,7304af4,4c56106e,f0064436,c09b411b,926c4c56,cd82577f,f8c01ab9,9f7c4c6), -S(4cca305c,baf6615e,8cdc8a58,f3a9e52e,97ee20f3,ef080793,ce105a03,a1f1d3d2,637ea84c,9578321b,b5dcc239,7f6206bd,abdfff2a,128d3645,47d474f4,8a8ae493), -S(cb7813b1,a7227a24,cc53b458,1985592a,a9077113,28fb2a05,1d4972a2,3127a913,208b7263,f8f8193b,76dbfb1a,6c4f9264,dd12f63f,e852aa8f,8375fd00,eef83482), -S(d61676be,a11dd1a5,79164cfb,b2488e54,555d7d55,23ddc8a5,454c49e,4a86d8ea,1875b5d5,6db950bc,60b1eeb8,17a94af6,5a19f690,d48aacb0,e483ad52,61995cd9), -S(7142872,6f59c2c8,b398b22f,2ab5c3ca,e803a34c,ab580947,9b7b4d83,1f8e8c0d,3702510e,324c0911,b3154c61,e064ba23,68eff5fe,6f05353a,34980ec1,87ab9ad), -S(72a73d15,9cf7f79b,950971b7,1c66f362,54d13783,c5ef67b8,4da61dcd,4cf432aa,77d711e5,c1793c36,eabf9b86,bf3a692d,234f02db,e4d5854f,5deef926,b9818d2f), -S(ab3b2de,c0a8f23a,a7d3b9d2,88870969,2e45ef47,37a792a5,d65af92b,e58f6347,ac4e4ac9,1bbb57cc,1437e612,e4d4ce37,3d4f0286,5905b621,56826d80,895cb48f), -S(fe5efdb4,32715fed,f9bbb16f,d65ddf6,4ce9bb13,14a491c3,3bfedeba,cb4704ef,e5dc36f5,5fac6974,eaf9d8e4,232a22c3,8aacc6b9,1225a97c,2e695940,ec795c21), -S(5f94851c,a4149e75,e44a0d8,17e81c75,132eb242,c96ae41f,53f30ab9,c8c828a,d9473c47,505e0117,1a0f8682,777d0ca1,7399208a,b03974fb,4014f5bf,c8cbaeaf), -S(5d1bdb4e,a172fa79,fce4cc29,83d8f8d9,fc318b85,f423de0d,edcb6306,9b920471,d7bc7d98,86c861d1,86b4466b,c75dd9a9,8614e166,693a9184,8fccf998,847cb2c)}, -{S(8cf1437b,d87e7faf,550fcbe8,81b0741c,ae0b48e6,e0b3c3d9,9b1b1924,2a925a26,17b40146,c313b1c5,3bdf52e0,efebda45,80d86783,910996fb,8b2d0acf,9bd253a8), -S(fedc65f0,d622743c,53fa6172,e68d983c,2c9b8fbc,58943f48,ad06a852,c98403e1,ca5dcf28,1a2f20d1,5fed06db,89dfd290,8c9d32a,cf40fe6,817e861f,7f168ea9), -S(846c6a48,e771b90,4ae1e8d9,d3daf1ff,d1cb4c88,bbd1de98,454bc817,954654f0,5a4947a5,8a0ab994,3cd0a90,6c1d1f0c,3fb73d2a,49b9c0d1,a9bd35b2,99475dd7), -S(4998795e,a7d80937,e4abee13,6c14585b,40b2dbbb,3fd3c80f,c8c61b45,cd1d59e8,8c817eab,e210398b,59b31660,267c099,baf29e4c,894e09d9,a50894b4,ebbe97f6), -S(76c29921,eb3f3d12,5c11b906,3d1ac276,a205804b,b3e7484b,72ae0483,e4b3c517,48d8a8a5,fe658e1a,4d736bd1,8f07b5ad,28cbb775,d9388e7c,4fecd837,c8eb964e), -S(78de8fb2,b15ff39a,487135a2,636bdcea,57bb3a14,efc329f5,a06bcefa,7ffeaf09,a55c9e98,5e1f529b,ba7ccb6d,3a5c00ce,28cb14f3,e9012d5f,9f66d8cd,5e45113d), -S(71fb3464,b0600c08,7fe70906,2792a676,27830e50,a0bfb473,ec909530,30799282,fe036726,cb928a8a,8affed30,38977377,2a016e7b,1dbde8f3,6db810d7,cd423f36), -S(f1f23de6,bf779cfc,d864dbc7,b46009cd,d2306b1d,cd0de2c3,65f3006e,565d9e21,84f5a011,74ff8e7c,c9a98f52,3f2980eb,4b013695,f6239016,9cc5a1d2,acd8193), -S(f18909a5,a5db0daa,ece22ac7,12ae04ee,53484793,6fd8355f,9ff5ffcc,ab6ca78d,6306f08d,13ce2b0c,b60b3b8a,b0bd5f46,b3ef2a83,7edce51f,2cb5ce41,79f46344), -S(7598d96b,189f476c,bcb1992d,9a38adcf,9d1b6ce9,6c87058e,24584514,a0df4770,7f288be1,b82da02c,a37f655b,d23643ba,bf3d5cff,3b6c2726,9ece7409,ed78bcd6), -S(1e44193e,8223b57d,8fc68641,924cded8,3a04d806,cf9dc18b,7af06010,4e6216eb,45ea3ada,fd726fbe,2b1d6fd1,858ccc2d,57b237bb,bc2965ca,ebcd1b63,53c2f2e1), -S(80954b78,4872286,8fe38891,2d76dfba,d676b4e7,7901e559,dd5983e4,e908f13b,6fe564cd,a0966639,e0237f29,46e92d29,4aee124f,cb33da53,974e8882,b0acf22f), -S(6dd8a9a9,ad7196c1,3c36464a,5cb9fb41,aad8b0cc,423b99fa,a281c5d5,a6ce6ead,79a51469,8767adcf,ed287aa4,914eedc5,8382af71,5485c2aa,c3a77c4,efe2aafe), -S(1895cc13,f99534a1,187a3d65,d1480669,f0d0c0bf,b42b2a9f,1a6392d8,7e1d2c6e,b7905afa,c0eb9b66,51de3583,2cfb9ac7,ae8d2355,1e334d59,32909de9,ed400a0c), -S(f1efcb8a,86f94997,65b38fa5,8edced68,7737b8e9,49dc05f2,190b359d,9ed2c0a9,79b2c874,22de216b,904572b7,a39f320d,f53e392,8dd8e533,a1a28d93,fdd4945e), -S(2944af80,c207d107,ce89fb90,ea6daa2a,c65c1360,503c36c5,ad798333,90432ce4,44b53d27,fd6730f2,33b8c29,f1256136,c637740,86e001a7,60bc1ff0,f8b6211a), -S(938a1dff,117540c8,f6ee7df6,2d3c2cf3,31b38593,131527c3,9804c6d9,874752fb,4683d049,f096bc21,2e0dc20,a8600b8a,a02133d5,d0ae8d6c,b26e4694,ed6f2aa9), -S(b1b3b2c9,54d1fb6e,98fcf939,efc18803,2f693989,81f19c32,f5e55b30,1f59eb16,423a6754,1a29bb01,95adfe15,c1df1c9d,81394e96,2bd1926c,cc789f5b,eef9ec29), -S(52e23f2b,19048d43,b1725695,e3bdfc7a,f4ebd2bf,594f013b,b80d6d0c,ec10632f,258a6236,67090b8a,73881e39,746906f8,eabb6683,4bc3473e,1c6fa8b6,54641cdc), -S(5799a463,cc817bfa,26bcc543,efe0e00b,ca9d2320,1989e854,620fc9b1,ffc14afe,645238d1,8c69338f,9c9395fa,5ef7c9b0,f62b7dc9,c4c6b9e,c545c850,95b6b7ad), -S(1c493b52,3f5a4467,6268220a,58246228,608a603d,f6edb1c9,1a90b060,70b16069,8d311a45,5af92640,e9fe08f0,2981db57,3b22bf4,8fd5e76f,31c175be,23e24fd4), -S(84f5a9c9,cda291c0,71aa9f8d,d7af5a8b,f2ee0dda,fb9139ed,fee08f0f,3f9cec2,df381327,16527be1,d86991a9,bc28966a,c3c6c081,4fc0def8,85e5d160,f59f4458), -S(712c18a0,ae87e7e,87856c8b,ff6e3f6d,996ae157,970e754f,bba80bee,421fcde7,b2788ba,e69d34ba,eb5dfd62,830396df,3b8934a9,551c6070,ae8203c,ccc50ac9), -S(a5104184,ee996a34,7122a460,cd2eba5a,11d04aaa,a47d2ede,25ea13fa,41ee01f4,f4b5f2b3,f7ec9061,7ab5f3cb,763233d0,afc8d4bf,fc535076,5dc5fd41,cc547ffc), -S(79383075,a46a8eb,559ac95e,7dbeb9ee,51b6e906,27e55b9b,922473fd,5f2eb63a,243f56e9,84fd2673,58754a67,2bac56a7,9ae71a5d,68150740,8eaf8c2d,b55ef1a0), -S(2b22635f,b83ab0d4,9b82edfa,a54d6234,8d3bee6f,edbe3315,9470b18a,96f97821,41d9f3a9,52f17182,ccf02725,b58ebd7a,1f37235,1fbb8f2c,15403890,e8b25b82), -S(272fdefe,148ef7e6,957fb8a1,4a07f0ad,b17c27ea,49532547,5114c1f4,76170a0,789b8eb,5846e50b,d489bf66,cebd873f,7cf05619,3674e7d7,147ea691,6a9b8451), -S(2c2da4c0,8a6e73c0,2efd6e7d,13006135,f09990a1,4c0a0eac,1f286108,f4a2a0e0,8011a521,d7fa0ab2,75765bcf,50dba163,9e89c9,300e8a25,31942cc3,fdade63d), -S(19a9e5f,1c4cae30,797a98db,a24051a4,38ea755c,7b062094,a34ed6e8,8a8ff2cf,e199e398,157a50a1,56f9d6d,afed48cf,f3181411,77b792ca,c5881898,24f1b8dd), -S(f7a4be3d,fc6579fb,43c5a960,890893a,f4026165,ed9e3ab2,e6929378,b63968b6,29221093,17dc39ea,de2d6fcf,c735ad2d,668fd047,2eefefa1,b6b225cc,2f3cb3ad), -S(e5380fe8,575f26ad,b7924ae0,d58138d2,68112776,b11bd34b,3eb5e196,33f0e9aa,4680278c,6f784be2,a496ec9c,6db371fe,9046b1a2,b97ce71,3b45bec8,bf7d8a20), -S(4c1b9866,ed9a7e9b,553973c6,c93b02bf,b62fb01,2edfb59d,d2712a5c,af92c541,3e086d2c,df4175f0,804348ac,31a91963,39ad1528,1bc14e52,8d3b0c01,39701c0f)}, -{S(5a13b9b2,5aa6944,1b0b5fb7,f7665dda,95aff48,e3250b4e,34cf8e28,87406c1c,245f250d,78fd66ef,24745e09,f067f16d,d400c387,66d2a1a9,af51e84f,733d0ba2), -S(617b41c6,8534072f,2302290a,4956171e,902634bb,4356bd27,ab83a377,13d8ef6,c867779b,97383817,dfd0971f,64c09c71,7c468a5d,e1bb8ed0,feb98f5a,305d8e6a), -S(ac118ae,ed46b08b,488202f6,96d9469a,e9af3cc7,ddc8eb71,44903a3c,ee43c654,f992fcea,8268ca6b,79f5ce69,c87dcfa8,42ea0345,d7c85a5e,a1b89f1c,9d0217aa), -S(741dc47d,2e0d1424,3f2bd96d,9033d8c2,9008c1e3,66bfb5a1,1434f1cb,3d85310f,c3135d44,e86f574c,266f97d0,f0279dc7,52aee0ab,8e3ed78b,ee0fc646,c133000e), -S(2e973138,f6cea9c0,5adfbb5f,49a7b928,5ae0c15d,120a8b1f,2d0c76ea,1fdcc7e,a05bc93e,68bc82da,7a7c7e38,95a647d8,7f724f20,c5b312b,738c6dee,90de771a), -S(9d938d6a,cf56104b,5522351a,3c424e01,e4d21c33,771ca94c,f55357fc,fe51f91e,881d05fd,4658b08b,edf87396,be3fbb95,ec9f371d,79ff4586,6ddc803b,65ae763f), -S(37a8ed2b,4085961b,84645ad9,8f2c901d,fe9a9a8b,4de8fc89,2cfbca5,c8909835,b1bdacde,94fdc3a8,78cd0eac,f8865d64,77e2cff5,efef834,97b93835,5b7b401a), -S(da1ba954,899cb05,dae6fea2,dc8ddd7c,5ef9e91c,3455838c,a49d2858,ec217d66,14051c3a,12332d70,f8ad8ffa,567765fb,def69640,4291b81e,d3978bf4,51f788a0), -S(92d2ef44,5a10dbc6,73f8c1e6,af093596,13bd1e3,c1b24705,bad2b3de,e8f11b81,adfed916,800d3e94,91a42c59,dd72e3ea,57d47081,b9afe668,f853cec2,c72cbab7), -S(e62208bd,52620df8,91b3ddbf,e6cf0641,6059ce50,be3b00ce,14e7a53,6d1acb07,1fb71455,53b2f4c,431fd86f,c72d51af,5e2edb41,dd3f69a1,9a971371,d9679dc5), -S(191fec47,a48ee268,35ed37ff,6758a80a,532f7011,ab099048,b024efbf,cde1d0ab,47b6389,b3f5534d,a632924d,5b65918d,f65c9c2a,2904ee95,4f24aeb8,c6a02557), -S(60c822fe,a74d52b7,d5203720,b2c2a361,b7628aea,d2a683bd,80655636,bed15714,5d9a9c0,120211b2,e8285b77,8f8d4bc0,b06240d9,22944248,e1cfce73,826bb67d), -S(f602da1c,788ea65b,cc339a38,c353bc08,1c43c2f2,6e05ea6d,ab52648f,890c9101,21468929,89348f8c,67cfdeda,31ef3429,23b5a450,9fbe9a49,f011d42e,57f998e6), -S(756240c0,5274101b,3059d23c,76d9ecdf,33e1312b,7a36af,ea21e6a6,c52cdbb5,ab24e853,900c7ff1,3e4f813d,a2acdd5f,53ce1710,b785ffbd,e74494ab,43e583ee), -S(8e815b45,7adf482e,e30e475a,4949e5ae,c7ff494a,a918f07f,c39441e2,360d112c,a966f04,2dd9edb9,436b0005,7473aa66,dd19b4d2,cbb3bd95,932ba98e,f1a1f406), -S(216d5970,36c661f2,cf6122c0,a136cc33,9660306f,1c190ee5,5f3bf438,e7189261,5bd23797,c6753eee,6fb934bf,dc897ec1,25b31c9b,9e797ef1,56d8cdda,2ec1d128), -S(a30ed06e,ce34d29,a92fdeef,6954b5ed,4065d592,3af09be4,f0ad4a73,e7c24346,f6aea418,6b38c188,b84fb6f4,2b6559be,f52dc13e,b7ddeccb,6e85a76a,8d4efeaa), -S(aa42d20d,8acf7c47,fe40ac15,3fcaf1ac,6c4ecc37,dfa39c39,fe5c7657,c78444d5,bc3becdf,464ce930,e42a05b2,c52d3589,fd45ff37,c7d1767e,f8462811,89634059), -S(7585f8cb,4812e306,de02393c,c06e9871,1953133c,bcb67ec5,c6a79228,69124ff5,c242853d,1a2c1c9,a1cd1b5b,364888fd,28bb23c1,2b0e169,67961b3,e7c8b95b), -S(b096a1aa,fb969483,185ba1fb,a5fa3f3a,d1da87dc,a10344a4,d74ef471,45cc45ce,edbc9490,23801861,44ee39a5,7bdec0a,230df57a,72649e04,c4c99883,a147f0f), -S(7034d8cf,df226df1,6b310628,35dc02c9,f3e3f91a,635ad93c,46be292d,56c0ec2d,f783b6e8,29447cf2,32769a13,7ff33f82,f9fb166a,aec8c3ad,1679c48,c1a913a0), -S(9f88b01b,b936defd,f61156a,b55ca290,cf282a2f,3718b0cc,2d32dd3c,49248b4f,c24ebc35,27052f77,41087cb0,e772ce12,1035042e,603f1301,e19cee0d,30029230), -S(14443190,51f05d23,343367e9,6add133d,fcb63209,2f218847,59ad81ba,c65e7445,745216d2,d11f2556,7e3b224b,6dce478c,bb988b96,a1240093,964e4ba6,f3b15554), -S(54aa2e02,3038fd83,f17a633f,d9ab441f,e039dd0c,57f9368,3da013f1,751c6813,f4d163ac,a9af3e08,c009b44c,b358ebaf,31aacc5e,e0bdb917,d1b4df5,420d2d34), -S(fd44e742,b04ca4df,693e3109,3ec52ad6,1f67264e,100618e5,88d638d6,d96efa41,7ac09cb1,2134a246,b17ce054,b38f3bb7,7d794f9b,2fca3786,a0ba665d,3eb0f14e), -S(f662f214,10cf6e6b,7f79fca8,7ea3925,6760d83,17478419,ff4671f0,2bd2ab6c,be4ad0b7,a56c87a4,8fbc166b,da8473ba,6518385d,bd004b5d,c85126bf,7b9309bb), -S(520e2755,1cd804d2,67f9b4ca,b3986952,612bb099,cbd3f3be,a54f505e,bba4db64,e3c75cd2,c831c539,b095ac18,3bb13a72,ba7cb152,5b9c214c,288509a3,98a9cc3b), -S(4d16fa3,2d74de13,111b3f22,c4133ea5,377921ba,e54af1d,666d6e9f,b01e117d,a63bdf75,78d73f03,75aed657,fbb8675,67230c3f,868f2cf7,b7275ec8,b02ac46f), -S(ab928c61,ad1c2f68,905b9e95,3c2629ad,9bb7c8cf,ad9f5a4b,35b35fad,69a92568,bf39ec2f,6c1ae222,ff383375,6bd83882,c05be6ae,692539a4,5124b972,e72159ee), -S(8731aaa4,93580732,66b96577,7bc24a46,17fb8363,51c5ad8f,c8bc053e,802dd07d,36957f16,1020430f,69a3b1c3,1a6df993,d9ca8e2a,8f487b7f,b2ccd44c,7f528ce9), -S(3514d41e,8b9388e4,33d1155c,c777c398,22ab36c6,3c2aaad7,ce674831,21231d11,7657cdaf,e9fe8147,10bb2ee1,a97c6100,6c7b0ce2,f5086141,ac2904be,1c7a9e3a), -S(9bb8a13,2dcad2f2,c8731a0b,37cbcafd,b3b2dd82,4f23cd3e,7f64eae,9ad1b1f7,6ba44d4d,50111c46,490622d7,b079c17a,f0ab57bf,b8ad2ac,9becf9d7,3c7edfaf)}, -{S(e60e88f1,dc24f079,f835b687,778307af,83446e,71809086,e6dac0db,9f191de4,25a0b86e,ff05c849,d79a176,1a634d82,29d2a759,fbd003c,b6ca4147,85726362), -S(55a5e6cd,c9e11103,749d469,dae84a88,9e744dd5,d9309762,15050a83,fef66fe,31278ace,a971a41,e2f9fb16,8e80ec03,37009cd5,b0a49938,c28c902c,a7c71fd2), -S(5f25326d,e99a7c5a,d81bf2ea,61a9195d,48832bfa,8caa9777,53e483f2,b5a62580,40b69a1b,baa2d0d1,5cb78a3d,3d184c08,5b4c16d2,90751ec9,bf3eb3c1,d3ec2ab5), -S(1a32cc7a,f88976b6,cbc89865,89e685ac,49381a29,1579bd2a,13f9488,c0333d19,4667a3e2,2048f781,11f009ae,5d7b1b97,850a3a5b,86f77880,b128c8c6,a9720acc), -S(1d78e74c,66247be9,352c9797,5fbc1299,743f9c74,68c64d1,f2d8affd,1b098769,37adf553,fa2a11e2,6913ab02,e59c4f2a,48133fe7,d9aa3c24,a76e9af9,48a29d8f), -S(8bb6f83f,6be5c2e2,b2bb265a,9bb3c931,bd5cce6a,48efccdf,daa040da,535dbc86,eb96a982,23278b81,6284fee7,b5b8a121,7350cdba,d56b6078,89602bba,bc003481), -S(a9f19ca8,1d2ebafc,4bb5d881,76bce19a,d2d2564e,185f905b,8f9eeca5,d6b12d6b,ab23a468,3279a9f8,e2e8f880,e0accbba,844bd4e9,4d3e4b43,74db2b55,d998771e), -S(19680305,c887467a,c3bfe44a,dbe65431,7323d8e5,62271e25,1a794b78,618befcc,48e9303a,3d6371f7,cf0a904c,cf16f606,b0007583,87ae0952,c6119521,dde25532), -S(18b3bd03,ed4696c4,7c3f896e,5df7481d,6f19a5ef,53d62ff8,2948f1b2,154175c,85fb04fd,6573a19f,2c136753,a1ca2585,d39dd64e,6e6e3fa5,fba362b4,ae9dad36), -S(38e3bee1,3cc3e18,a57aef97,4ffee58a,a392c311,14ac8baa,1376b56d,f8ac017e,8596c7f9,8abf3e44,4ab5491b,fe659619,f6defb58,f48e2b7b,57842193,cd48fb5c), -S(dba5da08,8cd17c33,3e892bcc,46261694,d2ff3a22,2a26f92c,17c5e1e2,797b235f,ebc15bfc,5729e986,85a19afb,d7f9a219,e60d2784,e9b283cd,3697f782,630fe222), -S(60456426,caea7fc4,48970eea,fab9c632,3e66fcee,50f92630,7b130937,25b85ee8,dd22df89,c5dae339,49459593,1433f2f6,5f719379,68e56f92,a38d1290,17881924), -S(f1ceac82,15670212,279f36e,f0c8ce28,3a192f66,460e4875,d90b2f51,a38f5712,ec11f026,c76c271e,fabd7d55,c8488d99,3298f6ff,c05ad4a1,26be9447,7d878b9e), -S(2c2fb5de,5dea249a,7bf6b196,8bdec8d6,1838da2c,12147045,18d6494,f09e50e,6c0d020a,d6bfd730,5ee73634,e939ac89,ca2b7d4f,dcbe760c,2d14ade2,659a5b8c), -S(2858ea8c,d40ce264,3c9a305,c0e2c758,af5b0b4d,5c57ed21,60cf7ec4,154ffdc2,33586bf,a61a3cde,4f402bea,123c69e2,2410c0e,590a71d8,9a1e8130,85cbb579), -S(2749a250,4e7cefa3,a3647088,6bec22fa,339fec0d,ec63c02,19e6af39,7fdec3e0,d3415104,a9070af8,b61acdf0,77954d37,57fcf742,a006129a,5c0d3529,3aa95407), -S(8edf3ad8,39e661b5,f7f16a85,dce3caf5,d571acf4,d0c6195c,53b618e,5311ac65,fca0efba,35a14d3a,9944367e,db4ac982,7dcb7aa0,12438c5b,aa5627c4,c4a15ed1), -S(dbb92358,8b083294,5d6d3b62,9cced57d,7085d3e2,d0890bde,95d80400,98c22745,42816661,5515429a,aa023737,5fb77804,624546f2,1f0a34ac,1ed4e4ee,dceddccd), -S(aaca9896,6196ce2,e13df3c7,d058a5e5,10566df0,5fefc04e,51f9dd,85a4349d,be389d02,789548e0,aaf67c57,3b91b389,c7e6ed80,ca3e637a,2a147262,80cd5620), -S(104804ab,e621b098,61fc540f,f4d6be9a,750e3cfb,706170db,e34c06ed,e0a431ea,14b700ed,a465915a,eff84ab9,fa568535,f63e4f44,1387ab4b,d841072d,97739071), -S(b2215070,a8ea71f9,b71f1a73,d6ce366,c322b8ac,4d135b3d,ccea68e5,a51f1c0f,9e415cce,3bcc4e62,6f3c8caf,fd632eea,862a046e,bb45e8bc,84fc05a7,a4b87e00), -S(600c6e28,be5ebd28,d83e6c86,bbbd9b0b,aca22006,42234634,6124133f,3348e6f7,822b1816,79e253db,a47ddd76,c0023991,5c0c0206,8f422415,94ac38b8,ff7994fc), -S(f8b9b45f,c6298dc7,13355bf1,3ee33ca9,c4c1aace,c09776e2,56b3746d,ccae0dc,bf4b7f96,1844aa2c,6ed8c8a5,6626386d,174e77fb,98c0c23e,e2b6de90,3f1f79cd), -S(63987b18,67fe5a17,333eef28,5385a0a6,576163e,2c74cd00,ba87b6fc,96a57faa,23ce6655,51d48ca3,c702a5be,87a05d98,b5aa1097,dd5877e8,11e32d76,4873e6cc), -S(2eb06c4f,5ea9ad2b,124a1202,cb13c1ae,aec4394f,4af7c96,d6a9ecba,540ee04d,b96173dc,77b46ef0,6f4141ec,96ce8d1,4adfcfde,f0bd7ea2,479ba6d7,522d037f), -S(5db39904,153002b3,1498bb01,16efd0b5,838e3495,62d9428c,912987f1,3aae5ae,2115b896,479d0d0f,75ffcb54,ff9e3f73,d1356ff1,4b14292c,6bfe8d54,e9e08861), -S(c0f14110,7f324ffc,f3d3e6c,78d5a628,6000d57d,7e85bc7c,fda15f75,79cef3ed,6eb03650,c8142b12,b330b96b,81214a4d,d01b068a,74827611,53d2c52e,e1315ce5), -S(7e3d1510,ed767345,bbb3515b,6f9819bf,33ed9dea,fab35d01,a7284cc2,371b0e66,4c6b3aca,5159023b,d43ec0b2,57e77e87,e5a6b745,178bb017,9960c89,361fd97), -S(f98b5dbc,3e54c227,b002f458,94850ff4,3b15b2d6,1607851c,50d1e4d1,8b20907d,1d2af742,b0b5ec05,bd6c648f,94563361,be03261f,da56f1ca,7caece63,a336d580), -S(188ef3bf,ab103784,37e1859a,7d53e899,6124c395,ca422c05,d6b21b3c,efc76ac1,19036685,fad04566,2ffa04e7,30c671c7,1b299217,c389c78a,cae9fcd4,ad70fb73), -S(b89070ae,96ead4dc,49be16f6,a1a30bc2,41b4e98b,c18d0227,4c9d9d87,dcbf00eb,90db373d,375d2770,b8dd6b1b,3e3b5899,34f274f9,49469598,e480e431,e4f195e1), -S(381c4ad7,a7a97bfd,a61c6031,c118495f,c4ea4bc0,8f6766d6,76bee908,47d297fd,6c950ac4,dc71111b,70c1a058,f66ea133,fbaefcd,246c63ff,6c531ce6,82b6bc6a)}, -{S(704a26e5,19071bb0,24eb2a16,48b66a6e,157b07a5,52fc4258,381f7d02,e8fd9b9e,d169ea55,8650aa3b,ce52c645,278422a3,69326e74,46039381,920f5857,fa3492fa), -S(705063f5,e481735,60afe9dd,5b2beeda,d6e46391,75ad7fb6,f73350df,51edf53c,32290956,61cacec9,472dd014,bda52364,3399d7cd,9ce2bb31,a5b23590,22c6ee5c), -S(972e7585,f8b1725f,4a7d18e7,77939aa6,3600a7b,a07c4d94,5da9511e,889473f5,aae4382a,49b4c97a,bc3edb7d,26ba7bad,16752047,dc99b434,f306c673,2851310b), -S(260530bb,e338f4a9,71930b12,4f18c82d,e33f22d7,32de9375,81e2b0d5,15e59d97,77c66c36,d6b09205,8ade9c0c,a311b60,a705c8c8,73fd2d4,8e6327cb,71eefd4a), -S(15464351,d21d2513,f792ee32,aca3eca7,a52cdaaf,9862172a,e7224a03,804581dd,d9ee19f4,502f1c44,f656ad4e,add6adbb,d8a04f5e,5344b554,894721eb,8e3e2285), -S(4fcc68a3,caf3ff91,dcce9770,11ad5157,6c844132,321791ca,a652593f,6cafcd04,e8db3aea,a35371bf,9700a9bf,b85e90b3,93cc088,9cd655e3,fb18635b,49fb59eb), -S(301c65ad,567952dc,6b39134e,c361030b,3f5203ed,da89784b,225548ec,45c75eee,95e2c0bc,7b4a7cde,8ce3dace,a691bafb,f78fb03f,3170b347,ee807f42,6b947560), -S(96ca5edd,8047ec6f,b5f8c37c,a734533d,13f0e6e7,f55d28,b8b10b5,121f4abe,1a21f1ba,f6a2e336,247f6ee0,88cca9ff,816b0667,3badc241,d9ed00fc,d2070f1f), -S(c94633f5,783c4e68,12143fc4,6e670978,8e8a526,819afea9,404dfa00,df1bd839,874f8760,33dba9,de463f86,b597219a,c1ea37f3,970bdadf,97c96c48,feec4ec5), -S(963146d4,5bdaa05a,b5115ac2,3ee862a0,2305ba9c,75003f4e,ab838f7,e9adcdfa,d75766de,299e5cf3,c8796234,5db9866c,cf011c5c,f108a794,5642a6b9,dd33eb0f), -S(dde8c870,ec4e9890,2a820a7b,c5784034,19ac261e,de5afd0b,82b8c5a0,7c2863df,e7833936,50d4af7,427158e4,6c753ac1,a5143c9b,c09de97b,3b27065,6f622b82), -S(546c6b00,c5e34a8c,4cc7255c,2edea33,d9f77e7a,c67ee629,bbdf1879,4622265e,5ae149da,f65aba8d,e214fa63,be9bbf11,3dd3c220,12d206bd,d56026e7,4a019897), -S(4340c850,d91b63fd,bdaf41bc,f8d8c010,d3f30eb5,79eeefc9,e67c127a,33324071,dd66033e,eb5ae8b3,3c47a940,2482bcdd,4db5c8e,dda3b422,35627434,dc3bad1f), -S(f796431f,679d9cb5,77bce62d,236d1fe9,b5042a83,fdd1cf94,1a2e00c0,5a261d11,718fffe7,68aa2591,d3fb1fd6,1a00537,3b529f9d,f9c27f79,31ad0df9,9aa74859), -S(f3d17ae9,d5b4cf41,27423894,916318bc,adfb5a9a,6c2ca219,1b918e43,eb5ed129,9da6d033,49c64d79,7ad09a33,bf71cf87,8e0ae6a7,9fa7bc3f,1451126,18415960), -S(23899a73,a4b52d27,29ab52a8,370ceef8,4c7684c,cd535f4a,ec360eab,cfa5a787,f1bcde3c,5c4740c7,37b066b3,8a1a88fa,c43357f7,f3fa23a7,b00815a3,85336320), -S(5805914f,5418971b,106305cf,c397dc12,f63a3b2d,8b451e5d,c1b60c2e,3d9e9208,616e2764,67a5f1b6,46279ee9,6e8645f3,76a80192,31e17a5,c92e26ec,1b76e62b), -S(85ffc326,1991848b,5e918c4a,53f291a8,31796b52,d56a5c38,8bebe625,d78cd07e,95fd6f12,7b155e6f,806c089f,3f5abe95,344e9014,e2c72fdb,e720bb8a,93d864a6), -S(6f1a57d0,6566bf81,f4b16329,19f477ef,aab4f829,e29dda4b,27627b96,1cbfe3eb,de1e8359,7ff20c63,3d28b909,caef273a,a57898f1,a797fd91,e00e2e7,da1872f4), -S(3d28eba0,4d0ae2f6,208adc71,cd6af3b0,e208860c,722903ab,e106feb0,af3185e9,cf8bad18,40d3d2b4,abfb5b28,b50702dc,512527d9,5bcd403d,9713ec7b,ef1dda13), -S(46511979,2b845113,1b32663e,baa14c4,20a5408c,1f53afb2,43cd496e,c4b18118,40bd602b,d740096e,842b40fd,8304ee73,842b074e,415d5ac,c5e2243,28b241f9), -S(393a8bb8,7ffe4265,51678524,8ac940c6,4aa70e71,512ebbc2,3485596c,a6d9da5,25773032,d2c1f80b,3954715a,6e4132a1,74b4468e,658f6cc,4d5f5d63,d458980b), -S(aeb37eed,35274696,2b85a21c,86b9fe34,60433606,9ae4ce6e,3a8235a5,e43c48ad,d94165e1,5372330a,7b5507f0,377a966a,541b6fcb,949398c8,dd6d6f52,2411d86d), -S(b0bbb4d3,100ce417,dec58f46,95ed8b30,4306f21f,ee11f899,585fb37e,a9905c59,89141fcc,9344e617,7742e31c,42c565d0,45c7ccb8,6f88df7c,5c36d23e,45e51d75), -S(49694de7,330b4c3,1431d452,f3e9e562,eddfe029,1cce58c,73b69cdc,b89e0f49,4715ea3,b6fdccf8,e224b93a,ffdfd1ac,ad8baf44,c5bce735,e7c9b4ef,3faa2656), -S(9a7720b3,ff0363dd,7263e1ad,83c32526,67b67d3b,72c2c14c,95f0804a,dd20f7a8,815a769c,494824a,a819ea,54b560ed,e1df9bca,d7df2d63,aae69c4,a02f9f20), -S(b89c399f,cdb3aacf,99796fd0,95c17cc9,786d79b4,9a1a255d,5c9ee510,38d3620e,ee3c4936,d4f9d1f9,d2642043,d25b21a1,aa32fa3e,ef44f409,73db47a,96965cdc), -S(add68bac,d7180ac1,4e9bbc5d,1e0c3911,f2202d90,1f9ba649,46b06507,b86ed5e9,fcffc13e,a9be67be,8d090a77,9fd9107b,f62bc785,3f98e97a,c0358b3b,7719944d), -S(9bf62cdc,cdabe928,c1ab44ce,38cd0611,135971ed,81ce6c6f,dfc5eb5b,d9c3996f,885b2381,e0e785d3,cc3f78c7,f9fd54b,ecdd9d9f,c2979e23,f97e9bd2,a4f10d3c), -S(bb223cee,f11450d5,c5e0b75d,20eb44be,9d44dcff,28574117,12fc5875,3b839339,8bb29985,87eb6f5c,c8cb615,285d9e69,71db8e31,8d81fd5d,6318909b,8311a00b), -S(9ed73f09,2263e84c,d022388e,da82361b,445f573d,b646cc62,fa0bf5c5,1d33fd27,49ce7698,144e1115,118a4b0c,bdb98dab,6b57dc1a,4d1bb6cb,a68d4d20,d8e937d7), -S(e747333f,d75d5175,5a0cc9f0,a7287084,65a02c58,7737a7b8,b8fa1b8b,4bb2629a,d5001fe,baf8f3ee,b33bc9fc,7fb3da7e,377c8955,91e56965,607269e4,96b90559)}, -{S(516ea742,3f956765,a15f856,182f1e7c,18d3e548,b9fdca94,ea46024a,1a8fcbc0,cfddd98f,be500604,28beb901,92c01282,aaf9ed93,76f0e26b,e912ac42,a378d542), -S(8ed072cb,13eb90c9,e5c107f6,ba576a87,ac75a431,53025e6a,86addb95,bba7862f,eece8a5a,f28d356b,f1a84c14,2549ae7f,894f7c07,305194f3,18e30e0c,873fb5b0), -S(3e0e488b,1c8acc24,f81bfa1a,f6761afd,b4fa5f5e,6317ba72,bfba2f07,6c2ff593,2c4ec39b,2f37b948,fdbc9e3b,a3fa82c0,dcfde2e2,57830a04,4c178759,ef5bbc8b), -S(f6b3f19f,cd7eac5a,13630ad1,bbf331b9,5608b7a0,ceaa67e2,4a1e830b,5eed9825,a2a64078,19ba0f7e,7a890df9,523c6736,50ad08d5,c2557cd1,53c6ee65,ef493ce5), -S(e2de599a,879285ad,398b1031,8e1a8387,21a5c4f7,1105469e,affc8e37,189548a,dd977e62,3dc05cd6,3155a71d,d87d91d1,d74d6e31,5f73434b,679b605d,9db264df), -S(bc52359,683840a8,59fc2c8e,22d72ec5,da2493a4,bb5073a7,f658517a,de83f867,76a13651,712ff42e,a0c10f09,45c4ce41,2cc8c4f2,ac3ae446,7cb383c8,656d3186), -S(d87e2b08,154e38c0,13847a5a,2f84c276,dc088b6f,c19a9bf3,90a8a433,fa937fda,d91447f,7c9042e4,6f64a9c6,40a5c294,1a6f08f5,d3eed464,b09b2a1,1c402c0c), -S(4359ac5c,5dd70bf1,d4f24f00,1301b9f6,17d9c69b,63350dad,9a8cd192,655ea801,c9e14f94,d8ec39aa,46092657,5d770426,350794a4,b1ef2410,a9b0118c,ac5d55c1), -S(3ab3f503,29e22bf6,8fe9882b,3b4dc989,36dfd840,be6af588,ab6d61de,48094b9e,4a40c435,9f4dd21b,11664095,4b55e6b9,f0308786,eec32fca,6bcdd5d5,8d055ac6), -S(a0f1ac27,d046d987,b9a98bf3,f770205,931fce93,59b75944,6494d221,dc2752b2,bf1bfdc6,47a15997,97b5b6cf,2d8a2a44,e9c36b9a,20b53abe,58ce9e0a,395fab70), -S(a9aa63ed,3b0260d2,b35b030c,7a5511c8,679b6170,b8a4f386,fae0bfa8,92735905,2f654620,4dba9b31,99bd648c,cb1605f7,62f312d1,67123d98,ed66f02e,4d794e90), -S(e51da157,5e566ef3,bad3fa66,e55432e1,29be6c36,32e390c0,f4d76719,bae34b7b,55930b79,2ffc91de,674820b1,eec290d7,74ecd79d,1ca07d6f,5ea2f817,4759984e), -S(8b69a891,b417ea65,7ba52bae,58920eb7,f101bb92,e150dc1b,c961c37e,73cd18b7,5b824edb,f4a68988,39de0d70,ec16ee1c,a01a4692,f29263e1,1069aec8,6b149214), -S(ee5c1186,77462649,6d37fba,e48e797,dc69f31c,d6ad22cc,937c7224,ef7ce8db,13f7987c,f2cc4551,e058d410,3d5c24d5,13c2d602,ddccadae,fddcab82,d14d5310), -S(b961cb45,5de8b5b6,c4c5c2d5,75303c81,35b5d278,503a15d2,371b0551,5b236b,3ed18486,5ca969ba,31c734a,19055129,1cd664be,576925a3,2a142769,4fc40df2), -S(83effa4,c127b5ad,7a0c53df,5be5596b,d4a42987,2eafd8f1,5498a6d2,47b87314,efa99759,c9360b14,7643de2d,64ad07ea,39cfabe0,2bc94e00,dc9b2e70,c2e2c217), -S(f253fc52,4fb0254e,e772f50e,5d6c16d8,48692455,c855d4be,15ea9f9e,9a5411dc,59bd1f8,2cece609,8a63fa1d,48e4166a,d79174ec,5f8216c3,16c48c1f,e5c9a0d7), -S(6b61024e,e6451d97,1446b55,1476c3ec,eb6b19ec,16155acd,317bc2be,11086411,8de5c6e,37b562da,ca5a203e,ea028b76,e6befaff,e54b49d2,6605f169,592242cd), -S(1691a90b,9cf72621,3680a72d,af59ef24,985448ff,5f35372a,ab6e2aef,df8b33e5,83d2032b,6ca761d1,286c1348,31250054,5a230558,cba391e6,f0db9c9f,97c2d618), -S(42a078dd,cf749f25,aec7a1f2,8e976f79,e268c36,a7b5b0cd,6aaee3e0,925746ea,c60f1846,6f025987,e0ea6ca0,3eb98df6,99389753,b57abbf4,f5739509,bfd09d1e), -S(21bfc1a7,16b09543,5142c31e,5038d4ea,4643d9c3,2fd4728d,1374dba8,1ca1f07a,a991d491,2601ca23,8e289e71,e9d743da,4385aed6,c732f808,6dc21406,74540acb), -S(e75223e8,fe247a98,5220cbfe,52151978,c98d1460,746f8de2,8696d235,71f3336b,dbbb8075,ab489582,52472982,c7b0c3bb,d82a0762,36c07c05,44417ff3,883f6f18), -S(7a756a,72fee88c,7a2758a5,3294da85,6b06129c,1978e217,2bc7952c,92b05265,c4ad3a0d,be72fd27,bfa475d0,fbd16a92,5e939362,bc0748c,c39ba9f0,3ad84133), -S(2bc697fa,d947fd62,63bb2841,1a274520,f5d582f6,7f039114,293438fc,9aad7c82,543109b9,82097efc,cb44d854,11fc5230,6c7a219f,2f58b37e,3dd354a8,2ffb28ad), -S(3862db95,1ed8994b,a8cc0178,f6dc97ef,db6e1380,c18719ab,cd24a88c,87039744,af1e8ac9,2b195d3,6fe1b1be,a68e9215,a453e638,67e65d88,64a8baf3,ff5c1267), -S(7b648cfa,40ce7274,59a6fae2,2836ea1d,b18ada4,9b18a61d,748127f7,7ceee771,f2a30c56,42887135,30124a69,da2c0355,8688bac3,dae6d95f,a252855,a85a9b4f), -S(f803d7c6,1820f980,ebe0b297,87aa688c,ddadefca,229b99b3,a6bde5e9,922f94d2,a5f8b450,34dc7de1,461dfb74,e7ed9c49,80407bf0,4b0d9159,af703a9e,1e0f9c61), -S(2247f630,9be2f3aa,e30c5907,c29095d4,b9198d25,1a17bb34,7cf5cb35,a2ecb1f1,82685964,20d87b07,1c5a4044,b79b069f,7fa6ecf2,cfc0f839,b2161475,5728c2f1), -S(1d770ace,ceb2183,fea7c924,a8fba197,579df37a,908992be,d42c8e80,8bd98ee1,d87077fa,b910a21,8769cfc7,49aad579,c809e35b,f1c2a813,6047e85,e2c6fc65), -S(5d134e5c,5da47f7b,a495f216,b4994d90,4a79057a,3d0076be,34f09013,99f1f366,fc4e10b2,c1f7bafb,d241d5b5,1c57d48c,30fd29e9,df5774c6,1d4f2c15,3b66ed03), -S(a49ed10e,aaab9323,3a5f485d,4bd18c06,28ab2629,f0b8c3db,4d05956d,6c953fa9,338d476b,99f0ac67,1fcb893f,5f202204,a5178acb,6971e7e4,984d42dc,b904afbd), -S(4d000b62,1adb87e1,c53261af,9db2e179,141ecae0,b331a187,aa4040a,ee752b08,95f2a470,e71f2daa,34927daa,7d268d33,34820a0e,e638d6c5,c18d7adf,b7cfcf45)}, -{S(44d42980,eb92b3e3,b16816f5,56858355,e031b88c,99117385,def6599e,f274e56f,6e3de5ba,4f693fdc,747caacd,b2cf0107,f29fa7c,9c6a1a09,a527cd16,4c2c1484), -S(9812d508,d6da303,6f08fa7b,54cae319,232f925d,6af91d71,fe6c2fb3,bc86be5,735081a0,35fc17f6,7547b9b8,f0f91ac7,f0ddb965,19f6f398,dea745a9,81441e2c), -S(5a022ba,a90ddc87,42246783,4f692ecf,dd2c2dcf,b054308f,4afeb17a,7ff6ddcf,6fc2a9a5,4c7a130d,fd26ca48,82406fb9,f67db0ab,7e6a6d95,1675fef,2e2d4256), -S(c181ffeb,a8ea7d69,c524cd42,18af3030,1cac8e97,69eaf6f6,ba73027d,30fb7bd6,e88959e5,b07b7d3e,693756a,f94590bf,997763b,afa7d850,a80dd9fb,88e6e904), -S(e29375b8,21c056c,30954b81,4f9ce795,c1493dfb,ebf06f6f,f32c92c8,c74839f1,a9040ad0,95c9d45b,1527c624,bac86841,a1f28b7,ccf8dd37,b7e950b4,858e6e18), -S(69445948,ebec5ae3,9fcb505d,7efb7902,6bc1e8fd,5d3024ac,2b772439,72142d80,5b6c2694,abac3938,db899396,62635c21,e64fe2aa,40d18678,9c246e9,fe3f4be6), -S(a86f3aad,85d0bbb3,8270956f,58c2fd65,f5425428,27d7a658,da1b111f,64c02c36,dec740b0,ee35208c,dbec5b7f,69bb94f0,7fccd075,7868a37,6ecec7b6,dcbe20e0), -S(ba2bf65f,aac92da5,6c252b50,8dd74e3e,99ace1bc,42b9d2db,9d0ead3d,b6820306,37bcd01a,75027b42,eb0d7b85,564bedf9,67153930,6fc97106,ab6623e9,90b031ba), -S(78419e61,4e8b5eb9,d09e0c09,79ce4eaa,26271696,fcc68269,4cddf1d9,6a4c7fa,a32dbb3b,46f9b6b4,9adf4dde,f1986af9,72662a6,2ed6b6a2,f8b920b6,82b32363), -S(71163271,204207c8,a84b5993,88beb505,640898ab,b24c4c10,42195dd8,15d77985,aab43609,9370f246,7035ddc2,e71d73f3,c0f1aa13,148303bd,840459da,ae307e8d), -S(473f52a1,fb7c3920,f09ba6e0,a3c891c3,3f4a13cd,9dbf51f0,f3d39ef2,d6bc07d0,b2c403d2,4aef71eb,1b834df2,8bc08b67,5130897f,a6d9855a,eb21ccf2,780444cc), -S(581e93b2,99b8c50e,e6338c0f,f426502a,d8699563,f17935dd,abe08a73,6932b71f,46e7c7c5,1e076fd8,9b8aa98c,f0b3933b,8ca82cc4,d21783a4,d74ae1b6,ca9896e6), -S(e65d9e24,e7340122,875a9d86,d6071a48,691ed5e5,a94b315c,76f169f7,f3d69c48,73575103,a70b7a59,90d9b880,8698b651,271c8c0c,ac93122a,66873bf1,fa3c6fab), -S(cceab216,41d0597,f9c7ab64,7f99154c,b22d4827,70395d6f,ddd6db5a,dc752825,4084c57d,5aafc328,e7a250d0,a7c3c0a9,627ddd70,c77c2be7,e5a1af34,359b9b86), -S(4222ee66,5baff421,17f47df5,c1c1df5a,dbafb790,d5c75bb7,2646cf85,7ae85923,43088d6c,a029903f,f5a789f8,16730345,5a5cd0af,cab57e15,12781396,fcc9b6da), -S(391c5d0b,17a8c11,3440cd30,83434841,969b0833,71758b30,27e38a25,e778da6a,69f3d295,be55f859,4bbb2fb4,116de5d0,b24b5a80,ed62c1e2,8fca9b8,3f6d7439), -S(803b7149,f87e86c0,13599898,b0c9050c,d4a6e030,e07e8d7c,a49c46a3,8a6ea6a1,6b367fcc,6d5916e,72f670a6,5ada9c39,54800e90,a8830fad,c9ea17c0,494cd9aa), -S(f7aa1c64,f8f92f20,1319f316,353d89bb,eaa4d65a,e148b01f,ab66aff6,c9deb179,e9b407d9,4c2b385a,74f22eba,93dc35e9,bebca7d5,17401b7b,576b7d2b,e13ff0c0), -S(f1c34d52,2b7493ec,cefd49da,99732e00,85ace2c9,fd14e9b0,69b67dcd,5acd5e23,29460fc7,dd77494e,a5a7764c,7ca6db5d,5d7a5e3f,65e865b9,e5f85d58,e77713e9), -S(db19a1f6,38ef7034,5340e3df,8d384944,7500640d,cdbc3be4,df3b191c,edb9db87,baac873,a76e0b91,c4847770,9dbe88e9,6195e9c4,ac4d7749,71ca204d,4a5e748b), -S(4ad12e00,f384c7f6,ea669c71,3649da6,55e0abec,67551a58,224b9f9d,de6bdaf9,2e0314a,8e3f32da,33a22ecf,ccac4965,1f1f6f5,20baeddf,39a02bd8,423cd40c), -S(c9130b88,cd451d4f,6eafffc8,357ba391,ae920c27,69e7c48b,49881070,fd088ad5,aac7c2f,4f2f8b90,bea9267,897e0079,7d6515e1,937fa4fb,1043111,6b5e1de), -S(88260ca,df81b391,be79bde7,b54f8a98,428aeacf,970cd843,d683e6e9,50686db9,3b9b187a,b998a22b,56b2933c,fcd09333,9c23889d,1180e365,10dc086,9869cf2c), -S(3984fce2,ab73c70f,a5538206,c2a61e60,2f160b1d,2eb61980,fe174cbe,fe464dac,b7e65c1a,46b50c72,621e3fc8,4f4c7cf3,6860567f,abf00743,5fd1b13f,7400326a), -S(e6b48495,c8277598,23b73f35,762c55fd,8cd20420,fe5be6ad,f27f12b0,68bdd63c,ccbb7124,3b0300fd,993dc9d3,4b55534a,12515243,e07ab78a,8d8fd528,46e5a69b), -S(6af5144f,342f492f,3f506ee7,fc515d3d,d3c93d02,27ba841d,74bc6548,97d4830e,b195d9e0,8113eeaf,fab92a2,81ddeaa0,95356053,a51cf84a,b5d60fec,5368f98), -S(14439b7f,e40ca407,374da12e,217edd9a,86c84397,e2fcf6fc,965023,ba984a1f,112ad656,47c47c30,f19ae62,e0c06b35,effd49bf,d5e604d,6d621471,9f088fee), -S(d4a7e4b3,863fece9,660baefc,ee57d09f,6f60cd25,f4aa178c,cb6f8a17,5fda9d4f,4985a973,ab0e8627,f6de7ef4,470de4c7,1adecaf9,f3766197,a86f4e40,14ea474c), -S(facc2a9b,9d3ad0e8,9fa479e0,ba777a0c,90a0c229,59d4b719,a9304df5,f1e96ff0,6e12c914,70c78733,3e5a65b9,8c01d342,827810aa,be3e4e33,cba0b7bf,eb283b91), -S(3d1b3f54,2809a7d7,79ca2416,a7b7d007,4a728599,e4f30cc9,14bbbba8,3daa091f,dccd0d01,e56c7e6b,90829ec1,f0fc733c,8f1cbcb8,79916982,3b466448,cc21674e), -S(a8c1ec56,3cf9596,d761e41a,bd6bc960,562eeaf5,b54eb83e,3d7e7259,f69671d5,a03c9fae,e160ba53,8aaf38cd,96ebe3a6,db59a04c,ce7074e7,dc3757f1,ccc244e9), -S(219b4f9c,ef6c6000,7659c79c,45b0533b,3cc9d916,ce29dbff,133b40ca,a2e96db8,db2639fa,26a61015,a5bbe7f,3fc8d591,c6b0753a,c16fa89a,d820fe57,72c49068)}, -{S(b445babc,55be50ee,bedb8c27,dfc6c37b,492649ef,8a65de02,111b9f74,29b8c3af,6f74c5b9,f9a022b1,8d3a706c,5c608b31,9f7ce25d,8424d893,4cbd2f90,84b78bcb), -S(dbed76fb,7e46e1d4,1b507edd,8994fefc,f94bd651,a9720d9f,8d62dc3e,9f329104,c047fc1a,41689ba6,9855f063,c563bfe8,49bd8b5d,37b3836b,d8bc57ca,fd02ef64), -S(844426e0,860ff2db,f012ed29,ad2919d6,f46eb102,68073862,c1792e99,f1b2b33c,243512c9,c6ca739f,fb181482,a901ecc6,a41893f1,371d6b12,31d5427b,fb486394), -S(1df697b5,9a2f9c91,b2c5d4a7,8035ea2a,351dc000,4e1c3bd5,5973020c,24836aa1,e89f949c,f6af652e,d7e79758,74a994ff,46475df5,4f7b17f2,a5c29cd9,7f722831), -S(cf4ffa86,87d9a39,7b4727ba,a033cd02,7d8a5377,46903db3,34c35f1d,855999a1,d1316b65,e027ed02,b4be11bc,4c21c1a8,585bb247,45cdfa67,5fb9cccc,faf0c546), -S(e3eed1d6,1813e3ec,d1b9fcfe,3e8bd700,bf3412ff,78a0a9b9,724d4dde,ddfd98b,dcb09803,b70d4c34,ee2bd7ae,6444724e,9ab27c20,5c3c736b,172af37f,cc673105), -S(3a202c1d,94a94eef,18fa396e,5cb8a867,8c3ae45a,e4ee64b0,822d207e,6c814fe7,147992e5,ab565bc2,ad1b1355,60f37dc6,b5cbee74,fef8e5ca,4e4f418f,811a0482), -S(6ce8f558,a853dacf,205db4a5,80c4cbab,8ef477a6,47bca6cc,9e676cb6,5f3f696a,e88e3934,b2857ec,6edb911f,acd132fa,f0078971,2805aa59,9afb3d80,942dc23c), -S(7fef9aa5,b2df37ac,99ca488a,ba598b4d,eb222149,55e1cb4d,c3ef1e7e,7bd38945,d4b7cb4a,8f9edfd2,3a0efd1,9882baf,98312b6f,7b5775ca,65e9dbf1,f2c32870), -S(6ec1ce91,d1eff7ed,9beba2b8,2f4a526f,736e717d,6442dd29,b55ae2e5,3371e0a2,28240ee,12e2b1ed,b40698e,ba6f087a,145eb772,caece880,b3e94b97,700dbd58), -S(645b9fba,2cb739ee,9b148b29,8fbe9884,f284893d,968c21d9,50696d2f,efbbf0bd,b06977a1,2d19836f,add50b7,b73399bc,698729fb,fd182026,d918a267,eab4b7c6), -S(7b930561,3a4a7cc5,ce1e7f5f,29314e1b,40bc8b93,40604f81,76578c18,69abf6c5,55a7e3e3,3f19805e,b5056d15,deaaa4f7,aea07a46,f9dc6a09,6ce15392,e146fb3c), -S(bbcc74ca,3697ef46,e7415ec6,b31a0808,1e6ade01,c7e2264c,f9d4d94d,d849ccaf,27bf64e,e1005f13,989639a0,8772c42c,b4249ba6,9d90cae,3f542ee1,78929f26), -S(4a45fd82,af96af67,9e640bbf,561cb385,2585a8e6,1b57df7a,e028ed33,a017c680,4ba76ea1,19a0267a,f019b3b9,89cde9ce,7b1c0b6e,da3c773d,ca31e44,61e048ed), -S(c3efb1ce,ddc6a749,a5db9daf,48032a6f,3f1a848b,aef9e44c,ebd76127,a9c90d0e,3de258cf,e593b489,8f92e8ac,50be894c,3636019b,a9f31f70,28468eac,687b8f89), -S(ec71a2a4,6f24acb2,8fda6bbd,ab9326e9,6590a96f,b9b9a4ef,405949a5,e3d2858d,31a91fa1,71207da3,1b0acc25,cace1e7c,5126ca2b,4c8d9733,4c50a7f5,29bc61d2), -S(65dc268e,cfd191fa,f07421f0,dcb16701,f979ad24,81ac5ddb,1f77d3ab,41a773e0,f8c9ac90,255d6460,15ddd1d3,57b92522,53bb55c7,e2f5d843,d7d9a025,2766d2c0), -S(62152eaf,df564900,4379891,4b53ddd7,3b91fb60,f16f2d18,941caa96,18d8ffd3,3a185ef0,a8d8a35d,112f678a,6a04a654,df565a8f,87e99abd,95fb4977,1b278ce1), -S(f68e6fcd,b2c49661,ae59bff1,f24e97e6,fffe7cfd,f185d0b8,133d58e3,bec1c89b,223dee27,5e9cc518,af12be21,ee7ef3a9,ab39c7d4,4f950fdd,9ce5c78e,b50514a2), -S(5d02e9c4,108860e8,2b1ae04a,4afbe1e2,9e0a8444,89876776,7e5b60d9,3fe5c753,25fdcc35,5f1970c1,43dae96c,a1ef0a7c,f95853e4,102548f3,d869d3d5,8bcf962d), -S(f6217e4d,4e6d06d1,27668a01,8225f88f,a1e0fcd8,e8654fd,ab26c8a5,4c6d4751,65a6acbc,19bb2835,13eea5d2,5fae521d,aeed63ca,50f9aed8,edb74dd9,c43d066b), -S(c18bb768,bae77077,35b4d3d0,e82cac24,fe3d7ee8,dcba20b6,a320ba6b,4695a406,b7a7ded3,a589153f,8ee504cf,fb5b45eb,b2d8e121,40f2f475,186153df,1fcf84d6), -S(36fc443c,1350b40b,881e41c4,d3c15952,31f8da9f,cdcac4be,f1d0c5da,ceb9844b,9843bb7b,fd0ebca1,762785cd,55669233,16c36aa2,d2c37b3f,2b196f78,bfa5830a), -S(ba7b8c09,d5293e6b,a2548e6f,ff3c939b,80d2ac54,34903039,dfb8b661,29e19cfc,54fe2a,9353fc1d,a0d34e07,b6d34d1f,f3a1f67d,f4aafa7e,57919142,95c2a5e3), -S(50a8ddf1,17a91c92,37a48fe8,f1a00e72,a5dff682,7398a4c5,d2f78b4d,d49ee339,f91d9b20,da28e51b,99fa102f,13f5e451,ab22e139,80052384,6b9c66bf,b7da1578), -S(642ece53,832d1859,c6543147,56b618f9,520a5888,2549277f,6b27f16,e08e3d1f,d9963beb,2c6da204,339a49c5,f253498c,48cc3e99,b715ea8f,a5eb00cb,1d6cffbb), -S(a68c0d3c,13d764d0,7b513390,5842c9,a7171e4f,755a9737,609db06e,1a44e5e0,a2c3fdd7,b7938a87,86f3756d,dbc66b29,72469e79,839a1448,b367db5a,2bc52c15), -S(5b33d730,288fde53,b123fdee,177758b1,ec113adf,74e79eac,513eadd4,cef377ac,1bbc10e,9d45cb00,db58fceb,bc4bcf4,a0e2bcd2,a7d3ec12,7d87beb7,a134a20b), -S(aa6dc4d3,ce531af3,e68590fc,acbe7816,c8293af0,d77914a3,c7119e23,e50ce56e,14386670,5dbe1ad6,91e09123,a19a199c,3ee67b25,708ef57,4620c5ca,821224f6), -S(180a4ece,d74ceaab,e0f7db3b,b038034e,5e659c61,3c66a534,8d962d14,efa32402,b675b2a8,b845281d,524403d0,db01417a,59fd3a6c,80232e74,cdfc87f1,3b76b0e1), -S(3a55690d,abb5e00d,c2d0d8a4,96d16c44,76ee767c,a9d0d1d3,694c856e,e5b7ad0d,3c1d71e6,8a5f9a84,4de0453,6810660c,fe353475,353cede7,2936786e,4d173828), -S(33b35baa,195e729d,c350f319,996950df,3bc15b8d,3d0389e7,77d2808b,f13f0351,5a75fe7a,9bf54078,6b9bfc9,db72ad43,559a9f10,4377648f,d43afc32,34728817)}, -{S(52f79560,fdfadd45,6165a204,6bf61bbb,726cd726,3a3ed2d2,45f07631,5b0b6ae8,e6c46e55,5b4a0410,bf38965e,5a7ba381,fd259482,2280482f,877a7ec5,84d14012), -S(29eeb07c,7b27f82a,1b031881,11d324a9,4df77713,a8cadb36,2ce4012f,52cafb19,b7538574,28faf258,f240d4a9,f464797c,dffd0a68,f9f978fc,476f9bf0,1a0a2df5), -S(2191ebbd,a95c29f8,e7062f21,a70cb368,ac67ed59,dc44b167,66e52120,cfe8e742,2812f1fe,557496f8,f21b1f11,2df7bd19,db6aad90,59494ad4,eaed4d77,49f66a4c), -S(3c29d849,e25364d7,576779ec,78755ff1,8aa64e2a,65140a2,bbcf22e3,da33a4f3,3658d9ff,e2e283c,f8973cc0,ede5af6b,69ac4970,3c6b1370,f6a2ba4a,78a28a97), -S(37230e16,e11db299,f54ca0f9,f5423ac6,5f05840a,e166175a,ff0732be,c72ba88d,2a26ac2c,e8f9ebdd,20f1f5f0,f628d3d,d0e02745,6132cbf8,78b614b4,51db28f2), -S(8fbb3be7,98e16bfd,b738a512,ceeea92c,1be8eeb8,5374702b,e927c614,ab1f1baa,8280f387,64a48061,26392be0,c95f0c58,3607343f,d0b24b98,afe3605b,8f7e79f4), -S(fb639ee6,29dd1f03,8e12330c,bf40ec7e,129d7da7,655c1c21,86452fe4,9589c89e,171adbae,2efe213c,8d01e273,ed9c5d47,c4e85503,de3849b4,d909823a,bb1da898), -S(2399064b,876b7584,8c977bf8,e35d6b32,2e45d1a0,c4243fe1,2a31a581,d1d5d826,79c1ef29,c1af9497,f3b3db13,17432d42,86fa014e,17e5d780,a0d39df,b61369c1), -S(dd5663da,63acee49,eb7fde29,6ac1215a,772512ee,6a080f3b,1266c7ef,51da5dd2,d19c7348,3754112e,9cb3a4ce,8986f748,3eba26ab,c415abdc,5effc956,27efb7dc), -S(30862c58,43b161ba,c127bea6,7b23d3cc,46b6c42f,8faaa281,6ae47092,8ae47993,44ea1101,26a7c448,dfed4995,46a0fc8a,3658e540,d7d0c2b4,18f8cba0,accf9537), -S(df7ebbdd,4e416e4d,6b1e67aa,34915da2,cc15bf8f,f6d79ebf,273b63a8,32d6610a,d05fddd7,e9618753,21f473b1,bfb5ff48,65b3c4f7,5cf4ae26,549989a9,e13056d8), -S(13adba8d,2485bda5,1ac7994b,c45a7e4a,1b21aa9e,8188e631,59b217a,29d4237c,6256a795,3f24b25a,c1f59384,aac3eabb,4458e504,af3b99c1,99ae614f,8def4ff4), -S(c160f7ac,9a453a1f,8811d031,9849be43,22d8bbe4,89cad7a9,cb815927,d4b54720,7958b41c,751ef3a1,fb985ea9,c7cc85f6,c16282a4,c374fed,5999d8d6,3227b720), -S(c66af931,82a7a9d6,588e9c7b,3eda3b49,40fdcb99,346aa55e,e6549d4f,f9382228,ffe4d0df,43f00af4,fe885b10,92ae38fb,97d21a8d,26aa5f69,9751d52c,a9ccea4b), -S(d3a4f4d7,d208b43e,c4c2fd00,798d882d,922f302d,a199b707,76a70f36,5ff404aa,8df220d9,63faa827,1c4ee360,67a536ab,25813239,82252483,311616d0,1458e1b), -S(47bdd428,d57ed451,cd8754ea,817c5f5f,9658274c,ef6757b8,70527b4e,96f372f9,fbcf0ee,9fb14de6,3c288dbd,b1888fcf,72f0265d,3fe2209e,12c85841,2c375b53), -S(6e6deb95,7f2eea30,5d625288,3cb311c7,f0365a42,480fb807,36315c4c,62495438,ba0fdd63,9b8678f2,ab0fe3e9,a16512e,ffd9ec23,e691cd4f,86146969,534978aa), -S(dcd2775,7cd691e8,28e21987,d6eb6b54,e8def24d,27238cd5,dfb36a3d,d0f05caf,40bf37e7,bd776a62,ab420209,c71df7df,74d185c,f0d6b038,dea9c8e0,c1dad163), -S(eda569f9,9bccdc21,580da94f,92d89312,cef87d13,f08d8ad5,f1574e12,30a64ce6,4e1da1ac,dd274e3,f9d7def7,746f0652,678e549,ad5476d1,410adbbf,aa3c1e42), -S(5d3d4a29,734fb7ad,2846ae12,4c803364,ea3d57bf,e8d77d9e,6a3b3f8c,9cff26b6,d3e598a7,1a469323,a357df08,319dcd1a,d7337a32,c9894b80,6a30c575,b19756b0), -S(10161fa4,61e87595,f269da7a,ae3ccf01,40e910fa,891276c2,df1bd91a,95e4d046,b36eb5f4,b8291a01,18691f1e,50235d8b,f66e14a7,f0641dd6,18ad7ddd,ea150196), -S(7ba1b276,3df207f3,cfd1d58d,5190eb91,99cf82f4,9d2d0927,f5f260f7,2ea0f178,cb9fcac,4be96ef5,3134f513,5509c178,99af24c6,4eabd650,afc599d8,3927969d), -S(4bd6edd3,aaa1802a,b0f46e05,418ada37,e75728e8,6ea4b293,6619c92f,57674dc3,c9e962d3,de71eafc,7fc9a329,3bfd721f,305e876e,a2a4755a,f9567dca,21aa3c0b), -S(95fa0b32,40b24ba,29a484d7,f8f022eb,b3f30349,9d8abc1,9a69b690,3e885b68,dfe6b88e,56d7b923,dcf8bac6,2241d663,3ac2ae55,c3a01fcb,9f966d62,8f3acadd), -S(d0fd4d10,18c37114,2d5f8a86,617c250e,b6c3d5,210ca465,6ec84e87,d0ae42b3,4e3bf443,290404a9,3af38e72,a54fa06c,3b2d6a81,161fc8de,554edd9b,f3399587), -S(992e1183,d4e7afde,166c45e1,37c71c88,d4039709,4262163,b4ae38e,538293f1,c29534fb,55e47a08,ecee311c,8f0ba4c0,39096edf,b2d7ed63,21a2810,32e85900), -S(9c124ecd,4e6ce167,f60dcf38,25976f33,64cc30ff,61f7dde,966f8c23,4c13a4d9,7ad73bdb,e0afe3c2,c89d9135,d445ba4c,796066eb,1909349,9e6ec14a,f74f664c), -S(b09cdc9b,d102f89f,bcca0ed5,888519b,7c5c02b1,64ccbfa0,3d0fe42,b1b113e4,f409865f,6ab4371d,f52790eb,88df67d,84b3b74,f17edbc1,29b802cb,d5e49a59), -S(6b4f628e,beb6d619,1d616e87,3233ae37,ca4cc3f2,ac881e59,9c2c8e3d,295ccdc0,1140b988,60f4ac7b,659eb012,6fdfb796,c0baa652,2202cce0,bf54b3a4,865f171b), -S(a728c830,10169439,3af3f780,b1ceae3a,6ca08ea,4bdc7554,2ae84564,f542c28b,7b68fde9,8c97db32,eb3cdbd7,15816e51,9aa58458,259dc74f,5d722dc,f48f1933), -S(21ce4401,4ce959de,f16b3912,e88ff48b,d44ef79f,5fed2d35,bdd2dc78,de8f7605,cdc598fd,c5d30508,a2690299,e0e25b91,b1ccb69,97b99fd3,eca1baed,76aae6d0), -S(89912259,11b9132d,28f5c6bc,763ceab7,d18c3706,e8bd1d7,ed44db75,60788c1e,2574b267,83365364,d84789ca,a64ec905,c969637b,21061ee,9ca3bddc,7170ed3e)}, -{S(5914f66e,28c1a0a3,47f461d8,1d7f2c55,845e35eb,3dc39945,584b5efa,8d71a215,cd2ac885,3f681e4d,884e308e,ed3ca185,b47e2d63,3fdfff6e,efb6dc67,4d7de056), -S(519834c0,d16c807a,7867b8fe,c99dc93c,3b9ed218,87a9ca17,9343729d,3ba9e294,b867d57e,fe2dd7c7,8586303,152f02fd,f67b5648,78a7727a,190d304e,64f97203), -S(959eda70,cbabcb05,fa8fae96,7227b6be,876db942,ae38bfea,a9c3d359,977e1c52,86373396,9338053b,b00d206c,5d67abd,f95d35e6,992ad69d,8d8a3322,7370fdc), -S(a40279c8,48dc042b,a3ee929c,2910e326,eded6051,9d9eb1a4,98fdd7e1,fc88a6bd,f2c962a9,f2950d2c,acbfcf29,35bad39e,2709c0e7,36378968,fa04d957,1dadc4ee), -S(650b8181,edcfe46c,eea03ec9,f8ee5af2,c288e618,7d634961,6c95554e,25957334,ce140ddc,c2e2b07,a57e5627,62da3eb5,ca1acba5,463e97,fff7eae3,55b954c0), -S(eb04688d,5f4c8d2e,4ccd509a,3d003b30,8c5539b2,dd160a45,cbe71efe,36fd9005,37d80690,2062bde0,b96fc8ba,7a7f751f,9461f774,a1d6f3e8,8999c676,a2ae76b), -S(f79206b6,7813cd64,9f946313,3bac4aca,3762975e,954e0ef5,a876b78e,4b5a5d24,6033d4ee,936e956a,af117dca,6086eb1f,6466ab18,d503503d,4b011315,365242d8), -S(539c99d7,728cf662,13e024c0,9f1226f5,ca5d09cf,67bac12d,47814b2b,b1e7d611,87efd14e,e58fbff,5491bf85,aafd48ae,6680f37,e0d928f0,13fb6cec,6f417f76), -S(2308281d,e761f602,66fb8228,45eec88b,e32f8fdd,4a06b8b9,3dfad9c3,75d64a8e,933f4071,e4f2a9ae,95f4a299,f4267098,94b661de,c96443c5,f03f6cb,f3be87ed), -S(a93d05ae,fa31c0c1,54c02f68,9184c1ff,344c670b,e13eb304,2de517f2,1f6124ed,b7549c5,4651fa60,61f4103e,27d316a5,db531e3e,d7396a46,e360341e,f53ed274), -S(35717dcb,4feada90,b039aa79,10cf064a,c8c998b5,fcbb037c,22bf9e92,eba560d8,b6ff9371,d98bf532,f82d7fdb,24fffa69,2afeb0e6,59ba30da,602b3399,2bbe5a5), -S(941d37ef,1671d5f5,675be9d0,d5cb1f0a,ab6dffdd,2bd342c5,c5b62be9,88d5a0aa,4834d5ee,a8f9ae8e,ba5cc8b,2fb52260,33e35767,d55b6aa6,d204e0e1,a38b42ed), -S(c22cecb,aff78c61,f6e34c9d,9367c4f4,1acc9c35,29e9d894,7989a874,1d70bccf,38a37fb0,5fd9036e,762e2f0c,fef8fcbd,c04a92a5,4cb72ee2,ba08213c,4b58f1e1), -S(7863ac2f,1704fd,5015f0ed,30edf5d4,33c5ea2c,e150833b,a15c1db8,a5e4d2f4,7468fa15,eeab5653,c9f982b4,ad9e4c99,2f44083f,a7a93e9a,25ff70e5,b8742b4d), -S(f702cfa6,f0cfd275,a2c7af50,b53d0c94,bb965063,c433f4f2,cfd13d99,800da48d,3da4a4e1,bc5f2c6d,2f8daec4,599a9704,7c1b930a,b37d6b2c,f8a586cd,ef7dce1), -S(c3a1da3c,6e6b8f2c,2a8eb81a,1875f2b9,1e9cd286,414862d6,57626b47,a413d7dd,983d0892,5983d42e,bdbce2d8,df116bc2,f5cf8c87,aeb833da,e5e7e9ca,f9699798), -S(df0a4106,d61fc3c6,b2a14ecf,ebea3dcf,7e38069b,8faac576,a0b8a1b,7c8e7b5e,dd97a06b,840d64db,1798cee4,9334b033,e8d3f4a,79da565d,c6130da,f0bea75b), -S(ee9901fd,9312a21c,879d4e1b,24d5a299,b8200a15,6e65e147,4a2055c8,a2363423,1bb2933c,8b10f8e8,ab93ecee,16f861ff,a86781ea,59b891b7,740fdc2d,f6c206d), -S(52890b99,c8dc48c4,b6b1e4ae,5b823fca,ad9495b9,8217fa4a,b4f8e960,77cdaf9,6ca2ba73,72606e82,9c3395fb,dd2e4b74,8c771231,e86fade,5e2d728f,e5e7391e), -S(a372b545,bf56b58,b7c4628d,aca9bc14,e8bc634d,d79d139d,8eb7a2d4,13465c3e,afde23df,fad41c68,df94abdf,90a642b,31d62f84,c6254c4b,4cad2934,376372f2), -S(89d02f41,f88b1f7c,90b01078,d7599a70,a1eb9c23,1059e856,4237b0a3,2c18010a,7e8e810b,b063d75b,c224f41,a842972d,6fe065c2,aa6b16e5,7bf224fe,e44b2275), -S(7ef367d7,23fedacf,86425861,f67c5ba2,2deaf04,69e31988,7a3a3a12,2f39576a,4b81e743,e00bfbc,1d98cbc2,5c98c516,55e574,fc7fa1f5,86f15d9b,1b5b7ac1), -S(2eec37a1,5fdd1caf,b4c0855f,e86c5534,1a78cdc,b3944798,311b1cf4,7df768ac,1c18cf5c,1a98fe9,70d1e635,ab133668,4e0d964b,4df0b16d,7c51ea01,c9a63), -S(72208b8c,fd9840d,76dfa6e0,f36cf57e,502f285b,422f0ba1,9b119500,6b2ddd11,fa09196e,a89ce6a,888415ec,a8eb92f4,149bb39a,50174a85,8a29bf63,65b4e577), -S(9f46479a,69411d57,c3c7ea6a,dfa833f9,1fb2109a,fd30c790,2ce323ae,4b14be0c,6cd6d7e0,8494cb95,9e67c258,1be426f6,4eee4514,83e9a9a1,278b073d,758487c3), -S(a9aaf56b,5016db58,5b8116dd,cbad1169,4b16de8d,9db5ea5a,279ccf4d,91b1d7a,218fed41,389a4abc,44fb2a83,7016eb50,99c40e86,bb419265,7f57714e,194a5900), -S(5f950f20,b610c06b,76949dab,52fc6149,97d254be,a1330a0,493f1ea2,1d608864,d9098481,823b3ff9,d1c0b7d0,bce90856,186b45ec,6f20da26,9b158283,8a4c96df), -S(ed621f77,98add722,b0dc5e52,9c6fec6b,dff60827,b0b12c85,18d798dc,761f1075,a8973e79,a9caf1fc,e3165145,df08b7db,6b7187a5,28b12712,6c62bb5d,4f0c46d7), -S(15b8390d,652d7338,e18ee091,97e0e176,74f8c4ba,fa2e7b85,8f5badc9,9c89240f,87930df3,710172f7,c5422833,385a6066,4cfc9854,a3e5ccca,d1d06106,1cd90be5), -S(ac2acb9b,21999a70,540708ab,68338266,aef650ee,d81c5b30,da1e87d8,a8a923b7,897bbd7a,ee3e8db2,e36505f2,ec2614c,9f4f2f40,ed2d85b0,5d23edb4,2832db89), -S(17c072d5,6bdd1382,a782481b,8aa4d223,2db79438,5870bcad,c3063330,a5cd5379,26fe420b,d7c25f9b,1883edb8,50e2fcb0,76a65389,d9a452f2,8351fad,4ef72f0a), -S(8d262002,50cebdae,120ef31b,4c80cd5,d4cddc8,eadbcf29,fc696d32,c0ade462,1412c44b,8ea40bc8,2ce090d2,3c11c945,e2b504b1,8d9874c5,271f5745,f0d9b523)}, -{S(ad9144f1,bdcc3673,26d51685,a047ea9c,3c4feb3c,da4b9b83,80e1ada6,300ba487,68003744,ab5b2c8a,cca5bcfd,e1c4262e,88ffbc0f,b0ad4206,2d57dcf8,62c93c47), -S(f3b90a0d,7a8cbf1d,9b994b19,7ce215f9,b8ed861d,d526228,59fe1811,68727bab,95f48e8b,c05a7bf1,e47fdc86,87513ae,5a56472a,44f384f6,1153a954,2db68b81), -S(24af6d7a,99122466,45b07a1d,29b4bb1,a68b5b0e,f9422065,b5bb0050,61d43cdb,f9dc7725,f628cc4e,d4e5554e,f0166b22,566d59e0,4d55c28,a4d0e975,8306c31a), -S(f704aa4c,2bf19c9b,128311c7,1bab5f8a,f2a3865b,728f4838,b8ccc7d7,82574cdf,ae7c46ce,c44d54a7,2e3f758a,e855710,dee6b189,1223d120,9e059620,38d12453), -S(f701adf5,a1bd988d,d7e1fadd,9903c453,e6798760,252579c8,b90cdce2,a046d9a7,db39a987,48aa20d0,5d8b8538,fc4b7d77,95e2810b,160198c7,ad98305,96407c31), -S(bfe36081,c492ed7e,3b91059d,bb1af376,47dca509,69be6665,50f94903,d948ca7c,a1fc9468,2c3dc954,764ee858,822b8c1a,5d0184e0,93f12bbe,21e9931,18911f03), -S(e707057a,297a3d7d,904a615d,ac1b8e81,78f52481,32fa166e,afb621e3,af3f4f34,9161a930,bfd583c0,bfd3b121,acf574a3,6eb534ab,5198aa84,ef38253d,9ca19bc1), -S(27a6c7a7,970a9e3a,7cd42b6b,4478be62,31f53ff8,481791c,4394e78a,968fdddb,e4bf1b16,6bd56269,9e2c341b,b1a51c8a,c2ac7d28,807899e1,3ab1f726,90f44108), -S(e65f799a,8fb3b6c,ad088351,614db5c3,d64660ef,8c977ec1,2bbe58fa,a53314d6,5897f680,253a948e,fc260fa2,8ac39377,4e6a445d,d2bde00e,4e01ff03,b4398e2), -S(8406a84c,e9e63204,761dd406,9651f20d,6fc3efe3,f98951d0,d0a2db9b,cf86e0a4,ef81aeb3,eac17e5,676f4455,b4372ccc,e405b786,f11a871b,d781e54c,6307d1f2), -S(c012cad9,4742fd49,8daaedfe,5b847f34,7a45c792,53c8a645,2192e905,e256c7a1,c4866f98,48f31660,8a81da9f,da112a71,34232f9c,75e388,7ff987b6,8404cd42), -S(73795313,e9de1efe,3d91ae5,15c620c4,4f9c6bb3,a21e3097,c8794710,b2032683,548ce754,93817f22,cb96c674,5d67708d,c7b9b133,c71cba5f,fede1316,c55245f7), -S(352b89f4,78a47e86,b5575fbe,ee1373bc,e93ca316,1f594564,9efaf048,a60bfebe,d784e6cd,88d7862a,d82747d9,b23340cd,b50235c7,65f30be2,ab5d313b,edb0624d), -S(8a0b3d0a,80d41abc,4b8a028c,6c523923,7b040445,525dc345,d2d8a319,c4708316,7b7a427a,f0e1f902,dd1b9bb4,65b6b376,ee68b9a3,f495cffa,c52fcb9c,705443e9), -S(b4bf6756,61462829,53f9a44a,ee3b5427,2485b45,951013a2,8d59346d,62f65894,85d0c26d,2987dbd9,e26c9673,71ca86af,3b8cfb4f,cbf97404,c99ef900,5379a1c6), -S(bff69744,3ac23a6e,574bd1ac,d0fea305,2f05ea65,14814f1c,65e86e9d,5b46a2a5,36961462,5b998565,9324f5f,c8714d9d,57ff314b,5d5c2cc6,99a4ab39,69add4f4), -S(ecb09f5d,122adf91,e68e98ea,d39e5790,27e7c4ca,405bcaf2,e086d4a3,e68242ed,aa214cca,8a601fa0,a92633cd,a353ca02,7a7dee71,cf335af8,fc75de56,a3405f60), -S(310d957f,10fb34ef,ca3a2a0b,35c901f5,35c0862c,68310134,10982d7d,e74af8ae,289cda3f,29a489a8,86121f4b,4e75a90d,2bc4ff20,e95aa103,4044ea80,cff56378), -S(3a5f1ad7,c59ee6cf,e090f210,7040b419,4ca15fa7,dc8e9f69,20825fc4,e012ac2e,8ac8986b,48d7bd1f,5ae99535,2505b0ad,78f855e,d8411b03,15725571,dc99c920), -S(725f136d,1b426894,c24f8782,43fdc1d3,79636a23,d682f389,dbaf71de,d4672067,db0ffaac,ec5ffadd,f32396be,3f01fe2f,45bb0cbe,eb0d98bc,2390f3ca,c3dfec84), -S(b28e523e,6fc68192,445180d9,5da3e411,2fe0db1a,5b3bd5e8,e00a1090,39c69d53,7c172a4b,31339fb3,47db74a6,beedf59d,c24e6aea,c71e2a0c,434714b4,d61a2f70), -S(b808db0c,e34b5607,8166b308,1dd4b2ca,cf9d2d51,3079648f,fc3c617b,8e45ba09,d69c4ab2,fc7e490f,6887f2c2,49e0b71a,746e3e2b,97a7415f,34475bd6,f6dee79), -S(5e0b091f,3144d7bd,c7e40dbc,98c716cf,d7e64eda,ee9c1fa4,6838bcd9,e0c6878f,1586cf7c,da66b005,8b2d0d49,f588d444,65eecf42,1d94c004,a078dbd,47e0bd20), -S(1c3e88b3,ba46410d,8e08f9fd,5db8b53f,8dff33c6,4f5314f5,e005442d,10cef1f8,ba365020,5f85aa9f,71a42c0,392345b7,4a17a5ab,9ff91109,4d81252c,d8c8f72f), -S(b4926018,fb0e9c,e80c5614,37c3f22c,cc223412,384321e3,6f408e4c,ec0d81ac,55544f6e,cea3575d,e81649b8,4950f225,8a94e78f,13325ffb,16debe1a,8387173d), -S(f4bfac1c,b0834e1a,e332b7b7,1ab84500,b1c8460d,c8c2efad,6a5efbb8,ae78cd1d,5faab691,59ce9d3f,6bdb1818,676684b1,cc2309af,1401b5d5,137e1c61,5fbe287), -S(220ed3d1,fe028d87,b96e8ad9,37ede03e,ed8f262,ce877c0a,42718ab9,cb2ddfb6,5ee2d60d,f96a1b8b,e11c9139,7abf9b4f,a0671966,34bf37a2,8d26864,31933fb6), -S(dca5fad2,d045526,b6a4c309,de1d95b5,23f9a7db,e669b558,edd75ca9,40c85878,f350337e,877c9c61,98fc912b,5d53876c,78ea94cb,bbf3744b,62a52fa5,f5ae4399), -S(486ba509,3272eb1d,16ece443,861eae7b,2d8604f3,37014bc5,11267485,9872642,688d4585,9fa732c4,f582d65c,45930567,8c27dc6e,5525d47c,3908daff,f0a534fe), -S(96bc1bd3,b4840354,14aa92eb,6db81f5,403e2858,c0552d5a,6b21d33e,c468f31a,83027873,f4066b5e,ba6f413d,6a7d4d18,d57f4a62,25cc9289,b514f153,91ede3b9), -S(9f131ffa,b53e20b4,e9cd9e33,793f4614,922c03df,7d11222c,7fffec33,42fddec6,c4deffeb,3f4cd90b,102cb6b,3f713728,2c5cdcab,bc6e7153,91ea890d,76207bdd), -S(c15c8c23,d90c8e35,c1a214dd,e2d4383c,735ae45,bef61f10,aa1a1c25,5984cf74,d456ab27,d7adddca,372390ba,1da02845,b84088d2,af4fea5d,3b5b7326,c6334c2f)}, -{S(e24b71ae,8fdea24b,2d42a2c6,5cb022a8,2aa9e03a,3067a889,e778caf8,34903fa,f87d5757,cae83263,1233b840,296d6066,52cd1ddc,e8334629,25c992db,7e0ee14a), -S(886a7626,6203c559,807acbf6,7e1631ae,1f6bcacf,3fde277b,ddcd795b,292c38f6,b1f590a1,52d3ecc3,2b699c23,a89b2601,de78be2d,fa11b20a,1ef1235d,93ed9e99), -S(3079f709,3d5270f2,95fee75e,a6c5cd3a,5638ee37,aef535b6,523604d2,eed0d57e,492dd2cf,d76705d7,42187f38,f38982d1,85efa30a,fd1639cb,984a8772,3e912a91), -S(7773469e,c557e3e9,4097bd55,33a87583,a79e3eb4,2e421cd6,592363c2,76641966,f827b0dd,46f4b5fb,4a656731,d827cf21,df1ec610,f36dc2d1,215f33fa,20a08020), -S(ebeec367,eb032a6f,7c421ae6,f8fb56f9,3fcdaa68,f6741e46,1992d019,7567336d,6e78af43,e10c742c,35467149,3323f8c4,a6cff91e,7b1f1c2c,65b21fa1,e63f3a6f), -S(b41658a,3683b512,c751d817,f5d92f8e,5d158632,1f2eb836,b446aebf,d276030,9396ba60,ca61b35e,4e52e879,a457ce5b,fee9121a,b2673c19,15e78236,483e069a), -S(2e2ed965,a926700a,1428af7b,68b7dbf7,61d1bf53,6eb9f75e,d56afa0b,63852cd6,8d77656e,d5f11224,3a94e462,3dcfbbdc,61749930,dfcca6cd,c4303cc4,617e9133), -S(4b54bd22,e5604384,9ff2268e,88c695d6,4766e0c8,4f598f5b,634e1dac,d03063ba,176c68e4,a1f25683,37c14fee,dcf9a64b,17cba4f7,283428c,1514990c,98d29d71), -S(b6cf7c38,2d4c63cf,78557116,55b5de99,1fd32da6,8b8d2dd4,cfcd6f5c,59c45251,c4c190ac,2870142f,2a13d7bd,5d6768b8,fb5ccdfa,b99d0e3f,6bda805f,7741ff52), -S(857b6db4,79177eca,82a6c801,bd763647,c1a49021,e5b4f405,ad02e6ec,7ccc3629,586cde8e,cbf7907f,704a6610,f7a8a910,16599e9a,93bc6a6b,1b70d59e,39c0db4b), -S(a18a23b7,6643d92a,9e1bd2c7,7bfee61d,c5171b33,12f64d7f,821fbe05,6a771ee2,321f460b,b9525303,c159fe3a,6762dd97,60432307,919a2f1d,6120c946,47cd8568), -S(19b91028,cc2e5434,b162cee8,c77351d9,d38d9eb6,8ff9b09b,f26cb25f,4b88510e,cbcf2e52,3335ee5c,56ee2a06,7c565627,a5c60f16,808ea8e9,94250c15,e427c883), -S(657e2f30,b1e0241,82c0e57d,996cccf4,7bdf8eec,5a4da875,1638b3f4,9bcdbd2e,8e0a3117,12da36b2,2d0cd048,a9a99b26,5faadec2,14162083,5210f1bc,bb79fe3), -S(576879e4,f4a8e697,45014bee,36ba4267,cf72038a,f5997d38,cf512f08,f0ccf6b0,3f313f,388c011c,18ba0938,51b0e7e,84627277,2e9da999,b839b58,92ede5c0), -S(ed72d681,6516c2f2,7a9e97c7,1a7c99f2,faeb8e31,a5f29260,faa0bbf8,6475117f,331fb25b,e71c24fe,f4d2133b,f1591f3f,e5f8830b,15615134,36fc47fc,522ad4b), -S(e4ed422d,9152f00b,96bce64b,bc3ddaee,6089e1a4,1ffbb58a,109c688e,ba44699f,6dae6420,2dc6cec2,e4a49203,6b16c9f5,9c517436,bf3b9d9b,7e8f458f,7fcba8e9), -S(fc3b8afc,fe39404c,29622db5,b06c989a,8d7a0c4d,85018796,d006bd5e,43dec087,7b77feef,2211c1a5,724af5e9,a841e09c,d7940bc5,43d70c7e,51676689,7682ef15), -S(9c2421ee,e2e7e66b,decbd152,a8839f1e,4cf03808,649399bd,ba55cfbd,9dda6360,8d9477c1,c66a532b,967895ae,66c7585e,608e9653,4f870bd2,c97d7398,74a84700), -S(22040517,334bb5cd,2252d1b9,8a9da91f,a0bd32b5,562c8218,4d991e01,d94e8f13,167d3dd5,738a467e,f8e03064,d6482c2d,64503892,b4f5b9d3,c4b04684,fe2f15c0), -S(b648a617,3c728243,f3c0c7ec,2aadcb13,dfab92fd,77da9aca,1602d47a,80022dd4,7199a3cf,89c596e0,d607d05e,de95c8db,ad763ac0,76fa7ee8,ba7ae6e1,4c14308a), -S(a7d7ab3,6722b9d7,940b2a15,c94bb9fb,41a139d4,26215286,bfff84ec,57386dae,25ea853a,c3e772b6,f400d850,a7cf5760,ed568add,a145ea75,6f20b77a,c32d9f28), -S(9787a21d,ea3dab74,366214b4,933a702c,7a07c4ab,696eddb7,3a84cb5f,80f2ba41,8663b959,2214a018,e373e360,a9e035be,f68d9e01,f6fff1ab,f8ad9b8d,3f6f324), -S(1d2ebbd0,65bd4f50,8dd697db,9c8bafff,b548edef,856fa4e,39f893cd,349ff205,85d0716b,109ab208,a96367e3,bd0a2314,ad2c8586,169096ef,9521d780,61df01a4), -S(d0a506ce,14e88414,46c08a61,98ea0aaf,75b9dfc2,c4d2cc58,1238a597,154981b4,dc8c863c,7c4611a1,85744975,34c8c02d,7cb7504b,dffa91f5,96765a25,98d1f506), -S(b6c4d103,a57d0af,27e93627,f55a34b7,75b2ef48,47d7612a,5fac0748,b41afee9,dc9440a1,596cbfd9,ff87fade,8b426091,4799dad1,ce0f7b60,d032e94b,bbaf53f9), -S(5b5d965c,f2f37462,86f088e8,b58887ab,2182f874,484686dd,43a245e3,dcbc55c7,6718ba28,cf43ba30,eeba6e49,a7234ec8,7f01762,e915ff12,41fb461b,6d87a875), -S(bc85aec9,55e6e99a,c5fa7738,c7972354,57b3935b,bb69e8e1,ddc69d01,d34a47f5,59dd49e8,cb3100a0,9c48ceaa,20cbde82,5072e13a,7af0a44e,601044a,361dd971), -S(66b7ffeb,a34d8cbc,e00b4d1b,a0558741,5123d8b2,89ebdba0,47587d66,b260bc99,43bafb96,c88a5917,c6333dd9,b4a546b5,1c37ab48,3f3873a3,6932ab97,efd79712), -S(3cf9208a,b230b73d,68470411,bf3d4899,e0f19675,f829e32f,cd148d,3c07d7c8,21fc39b3,ea5079a2,ae131935,9a3e98df,62b97b37,2a473a63,f3b56e24,25b30e27), -S(66e3fcef,b7b24cf7,af0f8de2,8e53c2df,2bd1dfb2,c0289b10,31239da0,948e129e,df4074b0,488f3f09,a674a40c,b3207f34,a0282661,2e5ac4ae,8d443c9e,d1184045), -S(28df781d,4ec05680,590f4658,713c8a91,fef23763,87ddb6dd,674a35c8,b0e74459,eb66159,95ecf0e8,34f24e87,6f0dd86b,5c86a45a,fe5190f5,721f833e,10a196c0), -S(85d8da47,48ad1a73,dec8409b,e84f1a13,16e65c51,96aad27e,766746f,3d477c2d,a76b74ac,99a3996f,a794ac9a,ce103843,6b4f5fdf,cc3b2a59,df867e8f,382e1ebf)}, -{S(39ca1e6b,9fd848fb,ac24c444,5a9f398b,8639fa6f,c0c2f2b0,8058d84e,6c0caf1a,8797227c,f956ba7e,5228a452,91cdd51f,8958ab7f,43f6c8b5,e06176b0,dc9048e4), -S(4c87e538,c9eac9ba,d5a2a81e,43a6f1e5,f8403c01,68ad5020,4adef77d,5e3aecde,6ee8b74d,dd0b9bb7,c8b7ed7a,728dd99d,a9fab941,f0132d0e,998e65b9,ffbcb9a), -S(1226617,9f5dabe4,6d963b7,e96247e1,e29f2440,f831c8be,578d628a,78561987,2d3552bf,ddb5ec6e,a7758830,9badce7b,41d71926,857962d3,c3bb28cd,5d68ce7f), -S(866c0a90,893b6b3d,807a96fe,3c67b928,67c1d95,e05146fb,40038476,26981201,8d8f3188,da86e510,b7a7642a,97778201,3926dae6,4ce80663,335bc448,d204413d), -S(8eeb2e94,9a66824,26a6f474,9e7578d3,1b356aa8,d1b42049,5fb83e5f,5d08f723,e439d710,c45063c6,d23aad9e,ac0cae8e,36552ab,ca6f2c02,6eeb03ff,6162a052), -S(ffc93fcd,85fd9502,78369b3d,291f1ffd,5da44964,888d5eba,3c3f60c,95082bfa,9aa66635,a4b0defc,b2514e97,515aa0ec,3f65ce8,6f6962f7,72eaca41,d5ea7983), -S(605ccd66,4f18c83d,edf36f62,e5089f14,4ed23f4,f88635fa,ab161567,fd20c8d5,cfccf020,363a805c,1d614aa5,b9a912ec,99cfea61,5c088789,275ef531,dddf2418), -S(d1e4f37e,7d3902aa,dfdd7254,fc727a44,98eb9303,a12fe71b,4d193be4,8dba6913,bdd29d53,4881cbc6,c2e301fb,7d757bc9,9224f12f,4296e834,9badb88f,84fcc289), -S(f30b6d53,f330e6b6,b23d21df,7b4350a0,c42ad202,4a92751a,5dfed94c,47bbe60f,b5ca6c03,b31d06cb,183b0b18,4432a06d,8143d511,8af4bc01,c364f024,b46e0c38), -S(540944cd,42101851,c2cdb0ad,61264e18,cbf948cf,2090df68,54482628,74271ecf,cd16820b,4ccf9131,476b8778,ba3e83,f5970507,7110686c,653be572,2e99db3f), -S(846e5478,5d9cad5b,5109c7e4,6fd62b04,f686c723,1fc3c0af,66bea20a,d9d60dd0,4b1a28c1,78bd097f,aeee951f,fd4f46a9,4658a76c,268ee7b7,9aea4bcd,e75fc8ff), -S(16e732f4,43b4c616,24a495d5,4497a23c,c95612d0,58df9f81,11d1340c,4b2b8b5f,61ee476f,30ac2be7,e3ff09f3,ebf0b3e,2d76177a,30573465,101f4cc4,ec0585be), -S(4f30ef37,2c730ba,a6a40ff1,94b6b58f,436111d6,848b4e60,10be9b9f,abef17b7,b579a133,7f3247f2,8c6afc05,644778f2,3668e73a,a7c6d14b,649bf948,ef126142), -S(595a0d2f,1668c0b4,9ba0994f,3b681c42,6e3a67be,e957bf52,47acd9c4,7cb7d009,fb10684b,3ef1b0ee,37684ba7,53858b3,3586b837,aba6d82a,958eb947,2eca319e), -S(85dfb59e,d7ef6e0e,355e0ce1,304fe5dc,8bc6a3ad,74de3352,2089f224,8894e0c4,7a9b9ad1,10099903,d0d84a33,6838d422,5f98abde,32d82ab1,a383969c,1fb98bb2), -S(c8e13980,cf58416d,8719bc94,96e21774,c29f2e1c,5a36e760,2ce7783e,2c810fd5,5bdcded7,bb484d46,48bc40e3,ee6a3761,cf995e36,2af21f0,10048a91,6fbd4717), -S(80b98fb8,e48f44e,db69fd8b,18eec95,2404fb59,45c8a35c,bf3616e8,c746aecd,d44010a7,20622d14,6af5319e,155fe4ff,591bb829,f5086c7b,1fc1ed6a,32ccbaa5), -S(17629b1,cf015e58,eccdc7a,de049215,fca806e7,805e0e35,951df2ed,5cb87d38,afd56698,44f6aefb,528dcea4,29438e0c,d10c4b21,23f02444,a950834,97a61f17), -S(592677f8,695479dc,b215af2d,bbc90621,e7f3cba8,650563fe,1b2a8765,6c44107b,3741e4e1,b39b0e2a,58373166,854a1d31,ed062a25,c4e3e1fe,bc82e941,eeaaf50d), -S(98d5f85a,a93c9d87,e34e3bb3,597d9380,f0a7e5c5,b03ec219,4025c89e,42126453,dbe42a83,66753aec,61f7f01d,e5dfde1e,b4b989cf,95bd36bc,a66ddc0e,ffeea196), -S(9187b546,70d2b9a6,b711c88d,353bee60,72a1f5d9,ce75288d,4e6c9111,80dd4126,80e73529,d211ea24,d4bccff2,b9de3e31,c6307ee2,3cd9267e,b2d372ef,78f8d2c0), -S(e38c81ad,8ddfd8ca,4e01f380,78eafecb,f8edba6,8e33e565,309a3ad9,f0abe0eb,9f0ace1,f05f0a85,a1488644,88cce81a,2cf55eb3,a91fc10a,e6b82f47,60dbe618), -S(7ee9955f,99e218e7,dadfed94,dad7054e,3e0b97ba,932338db,69ed056b,6f8adf55,5244e198,524a105e,2b5de11,81d7bfe9,ad56aa0,128a3d87,8cbcc5c0,25b41ca), -S(eb9e5ae8,cdf64b28,76349aab,c3f75c9c,9d95a335,3214d0cd,d43123c,265b08d,858611ee,f67a32b9,7b8a9090,6639e998,a05d9bbf,8ccb7c1b,9e5eb711,4216b877), -S(2aa74ebd,7e8b6b2d,952effaf,e5545eb9,e99b9678,a2515698,975247ac,c83ff081,1ec12cbe,6877aafc,f353f641,1a5edf9f,e4bcc09f,31422df,d076932d,8f0defbf), -S(1b7b8fee,a3ed4af1,cf9b07fe,b435ef76,1d081b1d,f1007697,f78fe5d9,89076aec,b4aa0d8a,efbc71d9,d338e998,197054f0,20c5a2df,7a9504b1,ca7cb603,6641f85d), -S(3f293b75,9f152a4c,b92e319d,e5d02b82,f5dcfbc,2ee7a53d,fdf7ef6c,e2595c32,b67babb8,d1d1963,fd742c22,5ad5bbe4,27e57d6e,b9e17bbb,f91d2c1e,a455c1d0), -S(3eb9968a,c9b01fd0,882ec65a,8f9f5a5a,b0fbec2d,e2dcbf88,cc9a70b7,887ca59a,1a4de130,4a46fcc7,6719c254,dad5e88e,9d6a0839,9a9a28ac,7f171aa5,9624ee2d), -S(a559381a,f41b944f,e2bab9d9,62ec7c53,efb25ce4,1ff1a456,54a99f46,d97ce20c,ebc6f66f,75ad7322,4c1319c6,4268c997,4142,11ca65b4,58c5f79a,be0ba0cd), -S(a8bc942f,c60ff2e1,140f9a97,3d7e0b8b,77698254,57098005,f9186e97,9e430593,2a82070f,25480267,c4fca773,3173b354,fcd5cc1b,ae497af8,58b7d451,8f048c73), -S(2f456ca2,c4f8806b,ce4caf12,32446b07,3405dcab,7b3cdcc0,247dd079,adc7a626,7308e58,5b9bafab,b2dee049,9bbf60ac,fdb37242,3e915156,15314ffe,5ad866fd), -S(b56f4e9f,9e4fd1fc,7d8edde0,98f935f8,4c750d70,5f0c132b,d8c465b6,6a540f17,cd171acb,d63357a9,2c23ee52,fa7d2e2,de2bd69c,343357ab,b95d0350,fdffec02)}, -{S(ec474055,43c52e68,5c9e6c75,97616fbe,edb70df4,fe3c375d,d7d24729,2b120851,22c1c1a7,30066375,5ef8c2fc,86452667,90347223,f11a32d7,9f1c0169,a467530c), -S(3f50e502,c45fd922,94fcc46c,b3118a86,43af00d1,634bd694,dfc0eeb8,be2dd4d5,7cb992e0,f29fbc5f,2887161e,6d1e266d,f11fb723,3b6c020f,26eee393,fe96b526), -S(443007f2,43c3f6f9,76914031,c41e0d49,61337340,9bd4a681,f20e4c79,934fc2de,df67adec,c9ce5f6a,e6c8312,699e0353,68ee87e3,1e96790f,f0bd3408,94af74e2), -S(1e15b9e9,c28f77df,75837a0,cc9504ab,a3a49aef,26a88d99,543fa7d2,a875620b,2a081093,6afbc025,3808ba31,f5597287,e32898ac,77fd0021,9e6fc298,26b0370c), -S(cfff0258,ff6c0d97,99823447,775b75b9,1881e06e,bbd72ba4,28f8248c,5cf2144e,61e63569,5c4a8fb4,f68f974,219bbf4e,e0c277dd,4b74b843,88f99041,f97809e8), -S(2824f4b,f72f9229,2aa04058,7a0c5395,4c87e7dd,bc5dd199,af6918e,6db62f1e,16ab1473,3bf8382c,521af6fd,27f8b2b3,b421dbdd,bcf06c62,3bcd86b6,4bf33274), -S(5dc7571e,27d6b955,6c789b4a,80d49fd3,17416fa4,e04a7eb2,3cdbb88c,9c253a44,b7261e2e,39327d68,a5456abc,9d4600c7,fb6d6e51,a732c7f6,c64cbd0d,56de4a17), -S(e93f3aaa,5d9edc53,6029d332,9ac0bffe,af27d4dd,40f550e5,3df879a2,a5c1d993,25b442d7,f2e2e03e,c7f1588,16a1af43,b5d2870f,e0cdf429,babb19e8,951c0982), -S(8f91f5a5,7aa40d62,ba407d8,6ea5678b,65c84ea8,f241e2aa,dd6df242,52635a86,e9333d7b,d6c319be,3ff4f5b6,f286a8eb,27d5a1bd,29646cdf,77441c40,f716a6f0), -S(77d398e0,228add30,e9e120ea,b16436be,30c254ae,65016672,8bea1198,de1fb17f,749a20c8,ad6f4312,fb6e6fa,c390a4a8,209704be,3355362f,31db9b45,f3876963), -S(96976a85,b6dfc4b6,13dde357,c21c3518,a5f55c7b,a2d22976,592d7632,3b5a8546,96dc660f,8ef3b0b6,adbe77b5,69024fb5,dd713566,617cfc51,c8013f2,5b424e9a), -S(49093c4d,26194278,623c2ff9,6c8e2f11,f9edf3b,13c33099,57b57f1,9db451c6,5d53ff56,50b82edc,9dee9f43,ed6db93b,f6a26233,2dbcd699,130aa9ce,5130384f), -S(49187f03,d5f5f628,b9210b88,8ac4f1b5,2f754015,541e9f38,162e969d,6a99f4f8,276aacaf,d38d0bbb,416bcd0b,8ea590d9,7735a3f2,8de72aaa,76bed0d,6644bd80), -S(7d64e446,65c03917,87fe0b14,16ab1048,3a6025af,b20e8c19,3bbba444,2864c587,2c0da181,6507f8b6,4c9e5684,a4d53d98,d6b88215,772def9f,fa5a7a1b,f2b2ccee), -S(2223484b,9ee12b26,2a21a18d,2682ab01,c291ee1c,fe3b4b9e,2e93fb67,aa08535d,4cd26418,bf0d62fd,b266a768,5f7aaffe,d7bc95e1,be41c6bc,7a0c9076,1ace3974), -S(aac92330,7d6a55d8,552ce6f3,9c531d5e,afdd5313,f801242c,21df07b3,a656c618,93d9be6c,590901a9,1413cc23,94cb426e,e6a61593,93511c,e67e1ffe,68b8f3c4), -S(6ec1a0c7,fe40c40a,f3515ff6,60f0b53b,8fb6be3d,d912f8b2,c7a473d2,3e49d201,b10f000c,191e9423,60fe6b5b,2b6b7b85,73c0c2ee,384dedd6,e3dc04a9,7834f93b), -S(bd982a5d,a4d0291c,38568fae,ebc76df3,f2b0e5b9,1cd0d3b6,d2f32077,6c35c43,48566068,d5142f6a,90b13105,e7841d32,38d869d4,fcc7319,3e3cc9ea,76739c5b), -S(25d54513,b9084ddc,a3f20e18,94382290,115ad5f2,dc72c267,ba845b3c,6ade39f9,e908508,7fc5efab,a6f62c41,ea8fe856,226c8e2f,95dc31fd,2b49a7c3,6aa53b39), -S(29ab6cd5,add595d0,cb64ead9,c3d275a6,ce383f15,9340faf5,118ec2d2,9bb9a62d,54584613,dc27c249,d5d1210e,9e121aa4,7d606fad,1c4621e1,67f67b90,d8f3434c), -S(4cfd960,86f86d5,bd805667,55979c32,d5419dbc,946d63a3,40dcc6f,6d6dcd48,f032b7b5,9d85d0a9,fdc290bd,a1fc703,55b5404c,f70d45c,d15fa9e1,33ee9319), -S(9c786066,b6642e11,139aa303,800314b0,6afd4d97,e8314a1,de9d7002,5b7bbbf4,463a2ded,e2185c8d,944f29f0,140f6b66,9ad6e3aa,8ab6e292,a2af551e,685e58ca), -S(4e98485,f15c506d,6cd29d7c,3f9a59ea,4bfab065,78d86b63,f25e74e3,e7aea96,2baf3fb1,c26f2b0b,1a0725b1,5d1ceeaa,7ccece9,a1dd8f2,7f80d825,d8cf1d71), -S(8412c389,bc88e9bc,b157d835,85af0dfd,48689532,e38044b9,117b8acd,ce3b62cb,17eaa404,ffc1f62a,38f7ce99,6216b1f,40bb62e9,6d1f7a5,8bca370,c0d30b44), -S(31b9b8dd,7d37b38e,892e94c7,a5e817c8,ffaa1c1c,f56979ff,7f25815b,758b6d09,cdb680a,ae795ef1,f94e7e87,50ad9077,7a55eec6,c6f0795a,ef951e3c,ab45d186), -S(2be45d05,e89c58b1,8212890b,b6eaf935,6f03e37a,fd957291,4ab71a97,7af8350d,c3b05f04,c9f7a1db,b6689fe0,6ecf7a80,3ecaa147,8d09a1ec,9a7d71dd,a75406da), -S(5185cfa5,fe6302c,b5573594,61f375dd,c483a66b,c615b5f9,30abbd4a,5c7ae0c,83cc447e,53c91e07,6f44d265,389bef06,549b8d78,9776000b,5c35ce36,5fcff98d), -S(cd42328d,e4a16323,c51ef888,b7e67ba,f9ee1c53,82161b90,65e1db15,bddcffd9,caed06b1,7e86b470,b665de93,74725fdc,94792c57,5509ebfd,f012133e,122302f3), -S(7a1ffea,8fe5114b,8a638306,3b7811c3,25a40c19,42451557,679e75e2,b304ab91,1ef3fbde,4f0283ab,96efbc83,bcbb5a6a,d781a215,e6ff6262,ca50b9c3,986816db), -S(cf0bdf47,a3f15b24,5c7136c2,3a3e38f2,661fa8a9,4df29fbd,8b41ef22,c291dc6e,c73d1fe3,919e0aee,5b3adc4b,1a86e709,4b039302,d44a0d56,638c3eba,24857a99), -S(3a571630,935c1f02,d6fd8744,2c082060,cd5e792a,1c6f92bd,c4eed01,686df50d,7a1ec78c,4a660cd0,ae90c00d,1a8f5f22,1f5507e1,4487e5ee,2dea74d6,17a69494), -S(1c5e5481,32b49a7f,66ae9fed,8323480e,d1ab974,622e7cf0,8993895e,ec87fac,b00309f0,7c80b970,d446a605,e2b3d52c,5c215314,d901cdb3,aaa284c1,a03d2740)}, -{S(2b081f0,268d6ff4,1090561d,79144bb9,554b1f3f,1f0f2cfb,c9344e2,b692157a,597920fb,c528543c,26499af1,8b5e7d7b,5ebf5ada,5df4a46c,edef52f2,1e2fda5e), -S(2ce45dc7,d84d3143,884d6696,73738e55,e30f6045,8bac95cc,c30e86f8,71779827,deb79108,80a1b675,a628fb09,725c9307,d1629b07,8027f566,29f8560c,2ea80458), -S(9dfa0cb6,2a63244a,35ce3a0c,f102e7c7,93a4530e,21c6c03f,15a4fb91,e116c480,b01c1aff,902f0831,bc8cd268,663f0ce3,6d8e22be,86026460,a8950636,ce44626b), -S(61a32d1d,cbd7e887,def51ffc,9c1dfd55,d06d72f6,a73ee2df,f83cfa0f,52d47bb4,69a3b17c,fa91e3d6,faf28d83,2695aa66,c87b14ee,7b2d987c,80242fc,ce2cc42e), -S(8cbbac63,5414c0ac,b6d7f659,5c6eca39,886c3ceb,82549f72,d07a4019,e3076eb8,c838dc49,fd5af1b5,e503a430,71901bcc,90e1ea38,9f735e31,236491ec,43e7b621), -S(d3f77c5f,663c6efa,670b46bf,dfa96af4,fc4720d8,e1df6e8c,1ffc5696,f37cb55,aeea0c3e,50eee6a9,16462a13,90ce5d47,c060efff,1fd3108,1db77513,34300332), -S(6f774118,4a0210a0,79695d20,f93f861b,658137c,3a072076,7d80e5fb,8b1ebdff,c12aecc9,b55bff04,bd6b6e73,870deadc,666973b8,ec498bfd,bcc4c33d,23f5d674), -S(fecfabd4,897a948e,5fab7200,969f9955,9eb1c9dd,2a31325f,34dc4f80,13da72c9,ba70c9bc,c8048aee,6fdaf5f1,8ef638ba,ce739c0c,76ec4c13,fd4dd6c1,1663d02d), -S(d1a1a1d4,24fb5ab1,3e985c86,9bd7c02f,f81b4633,dcd22e96,c3f33489,2e80d543,cd5b79ae,af62769f,dce99530,8b921b5e,39a60fd6,f989dd7e,1d0d7219,e9ee8865), -S(7099682a,c3c083a8,80467746,fb924d4a,56f23d16,a3b57f10,1a824b9e,653d45,6a9c296b,cdd72c93,df840003,24ce78b9,1f9df6b2,bfa33922,ef32733,fe49cb31), -S(1035866a,4e9ff0fe,6b0066c6,3f0a2392,c0b8cd61,36e13ada,21f6dae9,f22c39eb,6390f9ae,ec1989de,2146cd00,a5eee99e,76ea4536,423e9bf2,c778ff29,85538fa8), -S(e18351cf,163e4df7,d31851c0,409b5705,a5ffd472,dbda5dd3,bf05e66b,fae50fec,264c1d26,41f185e2,72b908d4,77222484,c651e8e1,9a9e1fb0,1ec5ed4a,8a4b6c08), -S(dfbee778,ae4bc89,24f32c18,bc0a740f,d01922b1,28e1a595,283bfb4a,fd8f2f76,d11f9b3c,25ae3619,99ec2c9c,2f1a5903,d80eae59,e096c5d,c5e37201,81756acb), -S(842cdb54,414fa977,58ae3fb1,9316ef32,af9c4f0d,649f0abd,cb94267a,124b59fe,a016f899,288f4caf,dcc6edcc,3cbcb561,fdb4047a,f789e1a8,51ad21b3,be62f5c8), -S(3deb5d22,a81540ef,cff29ac5,585a056a,204e4d67,2fb858f3,5c23e939,790c744f,20d73911,5b24b1a0,a4b31302,73321dc5,d8b74398,d6516439,4e1423f8,b4022d6f), -S(3108e61a,1e0f079,f76e3ab0,d69cf068,779674e6,49768aab,718a09b0,640251bc,245a9f2d,141f390c,f1a17bcc,a06c5a66,5cf3a87c,1096f5e9,b04c4fd6,737d9a56), -S(63b9eaa,ce6b32cb,e4cf4a69,6599f8fb,3797bff5,9103ba0,c1351e78,b16cb0fa,938ac414,ef911df6,bda32b5f,1f69cd7a,87a25d82,177763de,568ca95,e846fa5a), -S(f37a5a41,cc96a04c,c882c27e,e362d054,7d6267f1,c91c5403,2daa5c12,1700abda,108bd6ad,27aa72de,48406693,758a74df,53a3ff98,d490e303,54c45ffa,c64638bc), -S(52afb7fd,6a16dc6b,98f9d7d9,555068d2,c2317035,b7492e8a,fbf28aea,3b1fcaf3,548d8ca1,2cf7a11a,b0100455,c7240290,6cb2e92b,101d1e2e,32ab263a,3f3de413), -S(f644fce7,874e9154,8f3fb284,b7d1ba17,fad6eb6e,c581f57d,5aa11804,86de9889,b2acbd8f,5bed4270,ec131ea,1891c99d,ddb46648,60acaf39,d68d2a54,a58b92bc), -S(863cdfdc,66065a4,50c2b7c3,1d694c58,e63ccc09,fccfacdb,4fdf0b1a,b150e937,14d168dc,c84d859b,55a3d5af,9d17ce4e,83bd90ed,55e099f2,50932dad,b5d2693a), -S(9f5569e0,50a26288,5d91f82e,9cacdf9e,f4487676,730f4da1,46ce8769,3d8807ba,cba008af,547e01f,6a9c6c45,8f9d71e1,8ad062c4,4b305b52,3f3a6655,3979a2b9), -S(a0f14b6b,99f0bd74,cf9864bb,17b1c43d,51ade513,6cd72a15,89312dee,706d50c1,e2bd2d82,c549b4da,cebfb888,c1a7c5d2,f0757fe8,53e07fb4,747eb7a1,542137cc), -S(9e7bd727,fbab45a9,db36d17d,5e5437eb,f028a10b,392ea470,d5cff0d3,2e9bb0fc,fb52eb32,e43133db,28125280,e3cc55a6,76877c58,b4051f70,9c031f84,24f12d9f), -S(7d8b1a30,4c0c8931,2d5d712d,ab396efc,7a117483,7f62bb38,62a81a3,660b1068,472a2dbf,ee99c398,94d14c1e,ce87cf17,c8aee10a,4720357c,c5ce79a6,19aafe2b), -S(d5eb073c,a5afa126,70602de8,417fe50d,bd8f0768,d615ef2f,565e421b,4e7842f9,52571e4c,e4f0c424,fd288f3e,8b6c54b7,7481c3a,43230fc7,4c6f48b,d4041089), -S(3c41cd8a,77728b07,ea592254,5ac45462,2c7927fb,6a7aeefd,61635cc4,217acc90,eab0f00e,84099fcc,c2f4d339,77ff7d68,4c035b3f,34c6c4e6,aa812c9f,43af366c), -S(1eeeca5e,cadfae31,188218ae,7beda45,57f85c25,5c99dd64,1d00d8ce,2e6f7809,d7e5c2ff,4ddf421f,cf09b655,113b8cf1,a4c25e90,d02b871,91dbac55,d6606ef1), -S(54c13737,454414e1,76bfaf1e,b4402bf8,678daab1,555412d0,c6d3fd44,653510ae,753f6a,f382d0be,f1dab47c,1b9368f9,57d586c4,acef0d19,dc241ce,f008ea3a), -S(4d608c37,1fd6f635,9ffc57c1,9f1aa5b3,5b0f5702,55851cec,34278d2f,465fc8f4,12d1592d,c2cbccc3,7e5c9fae,4b864e9a,ca6967e,9d4852e,9adc9e31,1000670f), -S(71157d64,8c0a1a33,19b713af,f806cf9b,c91a446e,2ba48ca2,fdd1ed4e,8c43da59,c2ac2aeb,a298fcfa,c0d5eefc,6eae54ec,330f5c0,5b34952a,9821ded3,9b72d383), -S(327f876c,93652555,fa80a054,968b4712,930dc930,12ee6b8d,c10263ed,3b89a762,4d2bfb15,4cadbfd9,4f6696da,a1e66846,8aacaf8f,1428201,636026a5,46dfc92e)}, -{S(4d3b98d0,b5926a8b,3e5622d6,10b30e88,caa6e7ba,eb10bc3c,38aec3c9,c1267578,e84056d8,4726291d,e6880a2f,2d3b0b01,371dfa27,5b8c9cff,4805d18e,a5bdc788), -S(6e463689,111d1a5d,d10b09e1,5d0f438b,1cebdb67,7a6cd230,bf6349c3,70667db9,de10eb3f,5d2f4320,7265952f,b33fc23f,154972fd,d3394cc0,21b66276,1b51db3), -S(48235e7b,76c94c32,b0d21bf1,7fc215ed,df036366,a9ef494,19723485,78db8943,4f5ac8ce,36c77403,b2fa83ba,1fd0e88a,3da4c8cd,3c10ddb,aafe2d0,5da40a2d), -S(668af7c1,4063dfba,1a4187f3,f69cb457,cae4edbf,a3bf9669,4080b6de,bc3e2f0e,ec95f37c,7bac26a0,df23275a,283828a8,5a102d8,f33eef1e,87cb56c1,850740cf), -S(d4426fcd,cbdfd904,725fb501,656b9f2e,2a9f9ee3,c6522064,f078165f,61c31d97,e73f2a38,c56838a7,174ee704,948d28fa,5b5fdc34,7774df9f,72f27834,a85eb4d), -S(d0f49ec3,42076b68,4cd91172,f15584fc,ea38aaf0,a3201063,f854ff1d,f68d4600,28d95ef2,82dd7d6d,72be7854,e8858b1d,a142002b,ad7b7b4d,bd1e582e,94341e16), -S(8a36f3c3,50bc0f1a,1b1687ed,4ff83a68,1578d74c,c28fa875,f6969e52,4887bbb1,15ab9e05,c3ff823d,ba090e21,1033c34c,fa713d39,feec4346,88e3ecba,4b431e10), -S(4d1ef23b,b316e821,7d2cc409,a1baa273,cc06f79,8fdd4d16,5d5b6805,3718e238,fc37e62b,db18154a,2add98b0,ec221e8b,bd1a2096,ac2dd1fb,cf8e2e64,821301fe), -S(eec1f8e5,76e87803,bac48bb4,65ed923a,a68b2965,64365d45,bd1c24c4,cf7041b0,2c6985e4,7cccbc38,3b85be66,ab34a166,c98a8000,aad08f73,616e4d2,2a15a009), -S(9fbc20e4,de372a38,90443786,bd7cfc40,c6195b29,4cf51874,6ccd9ecb,cee223e9,f734bfc8,a6973209,903edaf8,52f63bca,b23fc1a4,879906b9,1c5df169,9d24683a), -S(7984c8ec,a2b02dd4,e8b9c69c,6f803418,48f108fc,b63d7038,de58e567,e64a894,49adeb11,13c705a0,9eb01e50,dea5be48,86e5d424,689282ba,6d64f745,74f45e8c), -S(29a7400b,16f5712a,2324becc,29fc4b98,57fbb926,f8741dcb,324c26d9,6cd178a3,90770be5,5c0a94a8,16bcfa38,aeab11aa,5ec3b7d9,eb4e7d29,1bee1c02,69e87267), -S(8299d2fc,84770bff,a4e630b9,8f2e6744,99b1c7f5,719e907a,d70515f5,140a00c0,c790968f,a3c3d4ee,3e25a1ee,8e1d4923,3c22f034,ba7c172,b5d7d91c,99eabfa8), -S(5cfbd498,5b608db3,5d1a2872,b9cd03fd,d775e498,4629f41,61a2bde4,fb2582f1,8288fa89,81056333,acd1720b,bde757b4,e83d0a49,9c5f2220,521a0bc8,dbe827f8), -S(281f1fb8,e144e39d,9ec2104a,96bf0f1d,494eaff3,57fe084,63825228,ecd286e1,ae40e075,d19ee5f1,1dd7e22b,f1c277ed,9a02abe9,975609c,a7c811f9,7c54e493), -S(51698bc6,73d3289d,6b4882b0,cab14e67,97d31221,e5bc6e53,af061aa1,9f546daf,7b850099,fe977f6c,f50abe00,bb3a0b68,90f47c45,24e9ae02,94304b6b,20bd986c), -S(db701e92,9b696c86,d7fb459c,97af90df,ef847bf5,1d235337,2a2a4792,5fa8ae53,edc7e98f,1a108bc4,8fdbe65c,2904058f,7da5e188,e71d194c,4e9dbfe6,8a55d18), -S(c900f57f,e9a31d4c,9715a822,5a906e90,22d81c12,714006d5,81be0c7b,aeb5a490,8493eb00,90517d9c,b70a4bc,39043ffb,e0863475,17cde2,a9bd0d95,f616bb66), -S(d74e842a,fe2da0df,df6342bb,582fc223,717e0641,f1ce0e14,584c5c63,f379ad72,cefdbd7b,b4ecbdaf,409a0fa3,9a0a305,b1bd986,4913f977,bec6c47d,5d525c10), -S(b00a5f4,f033d126,64366147,a1bbb9b6,ea60a38b,863c5f3a,e323e8e5,1aee200c,11e9f1f7,b7701a4c,26a881ce,30fac1e0,92e157d7,b9c2e4ce,cffeb38a,172ead87), -S(5772b134,68bf9f09,d26074c5,16dd7472,d3a83624,92306cc5,c7544ec0,d73de280,2e2a7931,aefe2a31,6dbad1c,e7f9d42b,7f38197f,43024f16,9e27fbc,7af31d0b), -S(8bf8af02,ccdafb15,598f6725,5f172fb4,ba8960e0,6c81ffa5,b4c1c313,6f95f29b,96041af,1efd128,ef133e5e,b0aa3d9a,6ac3a651,92598b09,ed649847,385a9b2c), -S(292889a2,d8329139,3410385f,cf5bf489,7e1ee23c,e0e3b5ed,82ceb340,d89f87a5,41099fb2,bcec7e07,d4d4ad14,3cf605d1,b0a32487,1736063b,e49b06f6,d648aa69), -S(ad227b2b,737dfd02,665c15d5,9b28c7e8,76413dfa,25c9068b,90efa79,ce83142b,82f1eef1,7e2f6b86,87137302,741f8486,26fad679,9c6a22fb,3a49e341,c7e51e9a), -S(b4245dc5,5df02839,4cff2610,4a4255ef,89f3e708,21541c3a,4631ee4c,145bf85,5a40f72b,7a67540b,6858e5e,b15005c1,3fee862f,3cc54a52,7643204f,d0b8be2f), -S(15aaef61,568537a4,695c1990,c05ecb9,2c605232,f705c3e3,729720de,7e9c2400,e6efd1fb,b74e9e43,ec1244e0,bb4cff2,2a5ede8c,848a4f5f,5eec6f8c,77b6f5af), -S(ade2e63d,4a828328,b4c53763,30790331,734d7f90,37c1a584,59570c8,f31e72d1,c42898ab,3633dc7b,f3a454f9,d5475c4e,fcf1f786,d1f609fa,23616f26,b23a1a97), -S(d8a9043d,297681ea,c5ed63a5,de306500,6b66e4fb,167aa5ec,c76a8e2e,df426e7a,cd3de058,a0a93d7d,7122d777,1446b2b4,d4cf53a7,1759fea3,78adcf03,5093f4f6), -S(30651cb,592d282b,5348f192,5be3f04d,da5033bc,39e2fc7b,1e61500d,9769b57c,dadf77cc,44853f67,53b1dbdc,17a97d3c,e6d5b2e7,8c6087fa,800c5af9,ccdc54c), -S(aa21c60d,6f7d6253,9d42bafe,95c58f30,33c0396c,fa0ceef9,6d2f91ed,d6569044,4d519779,3b19515,92e2d952,2be520b1,11a5453e,ec6d7ccb,3e6db3bd,3d0c84c9), -S(5335cea5,e99eeb23,765b3444,d9bc7be6,1da67d6,91bcc42f,d43ae543,e9c22bc,c4072fdf,8963addb,5f980f7f,f314795,373cf3dc,935e0e64,c3d3d98c,342530cf), -S(708a530e,9e52c73b,ee87c9d8,8161c810,5d5762,2c29ae69,1cf999a8,3a1187a5,6477b7ee,1e065768,569a923,4492c7d7,c13258c3,92cac175,a75b0e63,b8c2426f)}, -{S(3fbd5a4d,ebbeff54,8c2271e5,33dbaed3,fb8ccc23,e3fa2579,4c8f7fd4,47ae186e,fdee4625,45bf75f5,5c29a724,6496d970,4616c54,ba01d0ba,feb9155b,cafdb555), -S(c1483ec1,78ba8414,c371b57c,49c687fa,69669e2,e3e1067,cc6d2a93,b1a9d24e,edf94395,962adfed,c2ebb3bb,29346136,e4dc870c,5c76299e,3b07da35,6bb26bed), -S(26df4b09,693a3905,2cb7a1be,5bc2cc97,222b70e3,3d297a54,43741228,beb77017,a3d6b908,cc6d5f80,aecda93,99e17a8,ce33c423,f00cfc4,dea8354,af502760), -S(b6c265d5,90475506,e15b2388,b894718b,be67aee5,ba40ceca,51876946,e336d903,b451d3f1,2c666c85,bf9486cb,296c39f9,49f9f98e,96d50a19,80f86f85,a1efb999), -S(da6cf69c,feec7b1f,c848639a,7e27932a,f49cd695,a2e56a50,693fa862,6e257c66,4506f44e,e6e0d822,7e67dc4a,9f8e2ec2,d3ec0c3a,c2a70c7d,d25fa9c,34cbe3ae), -S(d57648db,adf18b77,db185ffe,3f86f859,6adeec05,ffb86215,4b894a0,75776eac,a3f2fec7,7186d81e,4228cb1f,691e00e4,82a125a5,bbe9e6ec,45a53604,4932491e), -S(4de6cc4,d64d52c8,49c0e8d2,45409ba0,88248399,1916df3c,238be4de,ee2504d2,b389e7f1,ca72e9e,1cec2ed7,70f21441,590f0bab,1b963f1c,411f9bff,d3df03f0), -S(15f1bb11,78b01439,f26412,1d36a44d,b8333fbc,eabeb471,da2e6c1,1b8b3ee3,bf137117,35e10854,95acf3ad,97fe510b,33d6628f,e67d0067,499169e6,6c12274c), -S(badc76d5,481e77,9df71d6e,223c6965,9e9ecba5,8415a95b,eb7118cc,b1f931a4,475e47ee,115d258,3f0607f1,7542ccde,626e6d57,6ea884f9,61b41354,aef37247), -S(13015ae5,d770f4a9,75825bae,a6cbbece,78536dcb,78d7116e,d304aaca,199add2b,f5e28585,7a99ff0d,a4fd15e,8ac650a,98421629,aa102bca,25df3930,7e5cfcbb), -S(7734d2ac,707b9b53,afbd2a64,50c9b609,1905c391,958d7215,f92353ee,fd3c7be5,751d38f,ef48bfea,8fa5de06,8188a658,ae6c9c75,a359a4ea,efaac5e0,b5e859aa), -S(91814384,7fe2ed34,e9cc9c61,3fc2c67f,2b76a208,561d0e06,271b812f,6c678856,9a97f6e0,9888e076,93c9ebec,b8773485,c3c5d208,c793a77c,6984fb09,cdfd67b2), -S(98c516fa,2a2c8073,70ca9d7c,b4187108,ea345652,c8f814b8,b4a9405f,b48c2469,7b3446f3,2e8c4764,a8eb0846,4be3bc6d,f42b8d14,b7da65a2,ac96a018,d0831c7a), -S(5691d1e3,713302c7,48bf633,189ce032,10832e4a,9af1dbc2,abc3e99b,cb4faa01,d802e21a,fab84c54,5d665ed3,54130d9d,f7f18283,30b3a1fe,e30c2298,8b71654b), -S(1f8cb624,6440b640,aadba62d,c02f4ce7,a0ba9be7,d535987,64072fed,95c0d1a1,647a9dea,abf8247e,f46b60c6,53cdcd5e,cff0d1c6,88b7519b,a778f9ff,c894e1f6), -S(1489af53,94878f07,5cfb2e20,931fa3a4,e585d494,78818e4,f47f05e1,2be54d14,cd5bd721,4e535822,43270bc2,dc692ba4,c57e494c,eba92d4c,dd2e13c8,e24d8550), -S(66159248,2b2229d,ea70ff76,d2a5e70f,ad1905c0,9211e3d6,2d1d652f,ccd709a7,8f5ab85,57948aec,67e7b538,fa9c704b,ae939c22,4041e6e1,65f6045b,a6fd0fdf), -S(bc894efc,d0fb7497,ba70d654,961aa79b,6ac5a795,95537c80,82c525c,2c44c3a1,d5254292,ef0fb6fc,db587393,3b17adfd,87d13320,858ff783,75e356fb,b0d3415e), -S(f117d7f6,85457601,9b559bf5,f5bc150c,13363e7b,72123435,b441d98b,d169dd27,a8f4a23e,dd0d8f2f,8950c124,1abac43e,e629b0e1,8505c3bf,780ea378,20c8623f), -S(2a8d99c2,65a66a51,56b60556,775c61bc,b2a81a62,34896a31,16238c2a,b7716ec3,5e842306,efe11f66,5a049c0b,fe3ac74d,d72c5033,6dbd04bf,2a77b0d2,4d7ea651), -S(ea747597,1a6b6d94,2e368bcd,9979876e,afa4622d,313d819d,5e8291c8,2da95830,41d4a478,e0950bb9,e6595bef,3c197e5,d0f77ae,6340ca8f,2947fec4,70465193), -S(114150c3,fe8853ed,9f3e26f7,bc9f3d6f,aa50ba0e,6ae2d8ff,97924b04,dd9678b4,5530c22f,4ac30716,2b272015,460426ba,9602256c,ab735174,1a2fbbfd,cd71d134), -S(65d96017,c91a746a,656eb595,d39dc9bb,3476dc0b,1a1036f2,df7a4ea8,1846631,de46bfad,6999b108,1f358edd,7809919e,4de768f1,fb21dc09,4b248bbd,56b3dc76), -S(f2aec214,61c040c0,ebd18204,bc277312,732b452,266bfd55,aa071853,e458bea7,52a1b71a,eefe2c48,5ae2918,e236f1d2,1622d37,13b4bc04,36124567,d48cc453), -S(370ef89d,c39e637e,8bf6be31,63a4f76,7cebb202,c868647e,db18f991,977681de,e6d402ba,9769363a,b963729,822bd6aa,9794592f,36e54461,579ae53d,4c8bc4cd), -S(8db6356c,4f31f46f,961e4342,a1ff50a1,8240629c,a0decc36,e1bb24af,f6742e57,8ee033bb,96958466,15626ad6,736e9025,fb76320b,c2d0ceb8,ce3400cd,743f934f), -S(14a1a08,502510e7,1060f291,1316ee01,b1fc2bd3,c88eaa1b,656cba0e,8e3515e4,5a4dc536,b62c349b,c9bfc6d7,fb677231,1368655e,fcb9c89e,572aa58d,a57f08c6), -S(d530fc7c,4d5b4fd1,5f44ba0,c0f08f24,889b278a,93ee30ab,935fc112,5e244a58,39c0ea88,5984c2d1,d5119a28,7cd842ca,d3cb54c8,ab6aa222,c01e7152,98aad10f), -S(50f3c13c,a474f604,ca992658,bca68207,76acff7d,d507d63a,b5e18b28,5c5be81,685e151c,7d8fddee,6c9d8513,dbf167e2,c32dd70f,b6932397,38eb63fb,3e4f7afe), -S(c0a72dda,13174682,726ede1f,7ecbaa68,b4b137f6,d44298d3,4e17b7fc,10e19d4a,1e45ff3e,4a4239ba,4a897489,a265a60d,9a91f3f2,83fe2e75,9e770156,c9ebb3ca), -S(7121e14e,7e2a2c57,76b5702e,c83a845c,28785c79,9099a007,54b50fca,b4d9279c,e6b3ff5,ce62fa35,adf45e69,2ccafb91,b805d7cc,b6eff2e1,38dfd680,d0684401), -S(c0c01f34,ae41b8cf,e466b4c9,c6a5d5f6,14f570d6,fcbef768,a81a6c8f,5ff4adb,f47b0a41,1bca80a3,836c85f4,bf8a4731,3243bc2e,8f2ea47a,3b1008b,53caebca)}, -{S(4f20ce51,84fb2949,443286cd,8ea201eb,15248749,6e15aab6,f3ea2597,d4cbf47c,bf37770,62691c5a,d6c6cb8d,c30fd3b1,73578a3,bcac43c2,c8404b6e,c085c97c), -S(17ceec36,7fad4365,520599d7,62c66c12,5abeff81,ce7242dc,bde4e799,402759c0,91e024e1,e2147fe9,73091001,984dd3c0,9f887257,73bbbedf,47f00c7b,c5c9f626), -S(dcffc4a,5557f2a6,ac7a3527,5a8228ec,325ea0bd,d9bf52c3,8a78217,6bd716,87658163,dcfc39e2,ad08a499,898a1505,988d9b86,72b6d1e9,64e6845b,cb41129e), -S(625fff43,45337aa2,1efa0884,73a6662e,d5340470,a79576a4,362e30dc,bcf762d4,92ad0a66,d0bea2a6,d7eedfe0,e33295b9,3a656e45,9220026a,5ff3be8f,83184187), -S(410b96fe,7db23faa,7d123e97,c1a82a9,7b24a26a,80143e50,dcc6d9a9,1a6e81d2,ca0da356,dce88799,5f8cc790,64d197aa,6532dcf1,20fe93c3,7e2ff4e2,f14394a7), -S(8136e51d,ca68170b,136d40fe,76980b4d,d4f435fd,e38f3017,99de734c,b2491551,823dd1ed,de1d326,676649a3,9d5ba083,7c48e180,ecd0a648,eaffe7c8,2894e819), -S(64a67d9a,a7a31390,3ed9e348,e7300917,6c1d52d0,be63f54b,aa3ee8f3,f1227a52,ef770581,df4aa013,6d191e99,cde7f42,a14fdfbb,11e1b709,bb540100,1dcda1ed), -S(5fcf0465,a905aa8a,a1da5073,d524e8a3,30af663e,f4307359,c03a4c6c,c423dd9a,58641e67,fa821fc1,2307a66e,fe0129e6,4ace7c36,c3f5395c,db87667e,5e742a42), -S(aae6747f,ac3d8c9a,148009ea,c2d25574,39a8b546,455fb3a4,5016891a,f9372dbc,66084f19,b1d97f2c,22e182c,d5450d43,d56636e4,92651cf6,22772a7c,5b46d9), -S(377dc2c8,13e36bb4,642d1e02,cafce754,2ac6d9fd,c2212edb,5432674f,38e242c7,8395dc2a,39d3b1cd,ae9d7d37,d0c4597a,11f931d8,75c8bcf5,8eab03d3,674d5841), -S(35c598c0,7ac5dc3,7afe6895,29d815e9,406e2608,292ffa0e,7b24df65,3278d8ce,e793aaf1,45f538f6,c133309e,53cb5343,dc1dcc74,985c57f,27361c6,aae23e7b), -S(e9666336,6bb286d6,c86f425a,2d5658cc,1d733223,9ec2e9de,c8ab7295,4b329845,908dc533,b6098e9e,9b737e4,b96e7345,e635f591,60bb3df2,75e165bd,d1cc5998), -S(46fab0d4,7fc6586a,31cf861d,ff5e0bb8,cc12b60a,53103007,c8974ab8,204af703,845ab7de,7654fb36,618dbfb1,287534a9,2d43db6f,2a2cdfe4,5365b4b1,893fbe9d), -S(4d80486f,fe748d1e,f88aabff,76bb82c6,a45db736,76ee0ff7,d77cdffa,2c69d07c,2a52044b,d4fc6a59,fd16dabb,df35bb6,8057ad4c,292e87b5,528a3847,c8784638), -S(2c1d108b,f4945c0e,df62cc15,6bf0830f,7a45ca,1baa636e,9f759bb8,bf078a55,81e34495,d269afbc,1be39ce7,5417ebf7,d45decb6,eaddb635,4480a7f7,8d7dd34d), -S(320a08af,eac009eb,7f254b8d,395d836f,ca6ea527,4e2f309d,dfb7f120,2f1b3cdb,75269a2,41199c0e,5f1cd9e2,d102a294,2324a3ea,cfae231f,99ccc5f3,e0af00c2), -S(8b893fcb,9a524af2,6de5aa38,8ac3dc,2159817c,7062e5c9,d5c9e7f7,dd889ad8,cec6a5ba,481f7e3,88c1cab,c11505f2,39afa143,68977ed6,52ea2d6a,19d2cbfd), -S(ea89b95b,36cd5203,22c8e5af,7461f9e1,a054f23d,2720469,fa74cd67,3a52aab5,5325d16c,4b866865,2437b6b8,598b31c4,59e6101,2cc1b147,e0473527,5935ada5), -S(cdfea79a,8c16ce78,75a9fa1c,5b7647fb,ad641ffc,5b73fb31,d9354a1c,3c1cabfc,184c309b,b0f52999,2a3f6b93,77b9e6a7,6da6b943,d8031408,b71223cf,b3ba9100), -S(3daaaf0f,785a6397,c652331,630931ee,a975c522,35899736,1b7e5fcb,409880fa,952efec1,ebd4c107,b26a98f3,c6683903,a498c840,ff4a36c7,ade569e4,c899919b), -S(7cea5226,a56d21cd,45bfdbb0,7fea6670,40247c70,ef43da28,d1f8bbf0,6e4ef2a6,b03edff9,6a5f32c5,6f8f63f6,ba9feb68,f43cca62,391ea587,81396c7,5d963b67), -S(1f5f4c27,847ba921,c63cef52,8b57fef5,5bdb5344,ea67a23,c173828d,c59199e1,d37f6918,e0b774ad,317dbcac,75c82188,c8a421f0,ff5756bd,853a05b0,c95ef089), -S(36cd4da9,2a77613b,6417deac,1d9a0dad,1bf0e506,de26b529,7fffbd03,4a4663f3,ec1dd8f6,6226bf5f,fedb071f,7027f9d8,d931e6af,e378396c,d0d296eb,a63737e3), -S(9835c156,1be21ce5,db788f1,3c0aea13,fde6861e,97cb2cc7,a67fbd37,17eefadc,7fad454b,7372d969,a6e754ef,c73415d7,fcd4d589,c8e255c5,1adf5a9a,82228f42), -S(5e218414,d9c9f0ad,35ded20e,76a484a1,d41b3894,ba9d3be4,bcb4546b,371d0e4d,76966ecf,9c8f1c9a,452cf971,10ca6555,2ca59d31,21092e93,333bbd61,6eb9cfcb), -S(b105f4f4,40e7ea66,e3272da9,d6b2b76e,d00e96a5,6f95224,34ca0df1,5340c585,9e8fea7f,35bc9eec,f82ae118,bcb6dc33,acae587b,f37b149,1f8312e2,4ffc86d8), -S(81d5713e,a732b4d,98d085a9,75cac9b5,3fa65171,e5cf49f4,684a7856,7c24fea9,32480cf7,a0bc0c50,a4de8200,9343b524,4a0f2aa8,ce67b11f,4a5482cc,6fa00bf2), -S(d47b4f1,88f5e7ed,a9eab2e5,8ad2c140,c6278d63,517bfaca,8cfb64aa,cfbcc7ec,524f6580,9d3ee034,afb1e64b,1a0f8ae1,1e464915,3722e345,bfda9671,1b94a5), -S(16e85ad8,6a953564,39b97957,7bedd0e9,6e2eed72,76ba269a,626fbd58,447996c0,8bf74f51,4bdbb6c1,4de81a3,1ff12aa5,de49bd52,63a962ab,b777439a,47eadee7), -S(c299c6b0,6e6c78ae,852bd55c,dea35f99,d264cb5a,e836b77d,ab209ac9,c05201e1,a558c66d,c9ee7fa4,c777b0db,288b328,428b230a,7c53d516,522ccec4,af0ae08c), -S(63c4624,35ef974b,393b05b3,7d1c89d7,b0d8958,ebd541d7,584e2bbc,7235c795,1d806446,ecfc7bfb,bce099f2,6ce37a49,61b53453,5b65642,c0cd23f5,a4eef9d7), -S(6d36d105,ed8cc5ce,53f2cb69,8ab620f9,469a3e5c,b25bf6e6,d413f414,c5af726a,1b45a3cb,1c889961,8d273993,6a3affd6,233a66c9,4bef75ca,3a8fb6e4,ec05ffb2)}, -{S(abdd85c7,a2f8bc31,343382d4,e405978,3874c8d0,1405ef14,85047cf7,f0f71d50,d5a03157,798fe828,a03ab63e,84bb007,b53a5315,1db7af14,e4ab612a,736232d4), -S(31297c6c,f567267b,3c8d65a9,72afc752,e8525eb3,de2958aa,76f72e14,5ad903d7,f4735877,a6c6d89b,d1beb50b,edd1235b,5f5e5d0a,878e4610,e7d756c5,34813389), -S(64706e69,11a7d0a1,2e587c86,91117a27,cbfa64ad,1d5617fc,81e55b8f,64e0da86,59d9af3a,419957d2,b3de7570,15fd8531,a5d07430,5cfd7444,5e7e70b3,57e62772), -S(a4988ed2,89d8397c,f1b897d3,b81d80fa,92658ce,2b935f4e,e2e3f0f9,b193af51,813fb8,73270570,50f23c3,f8082bcb,563ee366,1f6b2af3,f631f5f,916c8478), -S(3c2769bf,af401993,595a01d9,9c72a6f2,699591fe,4b869077,8c6b5ee0,f172a866,f3e0d8b6,cff168c,95873f44,871d27b,df1e79a2,d9e0bd4f,6f90f682,538c1f24), -S(49d93e09,df655edd,19548fbe,affce201,4c6822a7,e196eb98,b9ddfad7,3cb70125,26e6957f,84ced17b,c64f710f,b37656d,31ba088a,98350337,8f7323cf,c57f0eee), -S(53c06842,49997cb2,6e5b4cc,5f166fe7,db0ec0bd,52639a27,d8fedea7,214a78bb,8a8dd3f1,b3081dd4,948255ed,dd178089,a0fa7342,1ea616a5,1f639057,34a489c6), -S(7a8e7d18,3f2aa640,d0e2ea02,4cdca5fa,1767d9f,9ae38805,5d38e8e4,a81d33b7,c2fb92e3,5556fd14,4a894be2,3d97c6d4,30872ccb,25e239c0,d959a24f,aaa77397), -S(a5221a2d,29cf3ef2,f066897e,4ee74ac2,95b34cd7,54390814,297537ae,abdf603f,ec0ff395,8c3a1d1b,5a379417,5a61cd97,782c9683,aa2c7c07,5d147db0,2b134278), -S(3f49da9c,1d62eccc,afc4b88c,814e44dc,8440341d,f347de1,fb60126d,59578dbd,c3cf8e96,2fa9478a,f1be08dc,961734ca,5021a65d,b1b45f80,78fa8e8f,d2813a79), -S(47b16636,f5a64b07,534be14d,6ae37af1,9da79b42,666b201d,d0afda9a,2daeb6b6,f1218111,31ebd87e,e1fd7c9b,d24a0a11,a12e842c,6c00f445,6a342309,9b171f12), -S(a7b5a8ea,1f23ff1e,c1768eaa,2fef0d66,b75744c6,dc925d3f,9068beff,d69b32f4,fe01a23c,b0e5acac,e60058a2,889f9434,9ffce6c,b24f4a3a,662e0079,99bcb690), -S(3e14e2c,e7044716,d42e9b6e,54cb0500,a1e4374e,18917336,e3205e31,4a878b47,18af982d,2c78ac23,818644f1,ec657da8,ad66bdb,3d5a9b84,3f8bb988,4ef8dc3f), -S(71393e6,746d3072,830299c6,c1244303,750742be,361c5f08,6eb314a4,76f1736a,dc30a7ea,9b644339,ce8f1fe4,eeeba07,5bb08934,8135e819,cb061559,aa14e42f), -S(37721b73,e6861f15,7993696d,aded49d3,78994f3d,e2b573a7,defc907e,d6f301f2,ee0e1755,d8efb25a,5cf4d783,ec847425,746fa442,d460cead,56e73a69,42561de1), -S(7803c663,509fc9cc,55b372e1,dc0fa76f,149a0ca6,3db4516c,4abc0ad7,5961e4ac,356c72f7,794a70e4,db3463be,eaa847cb,256c58cd,b6a7d862,fde4feef,d896a46f), -S(32976d3d,a3d033cd,c073b0f,c7d2f445,25646893,fbded1c8,1a0a1761,a8703206,5e6b7900,a069ce4c,65cd84cd,f290f092,2b936bda,af6ea40d,9c36a321,a7c9dcfc), -S(c52c7b18,b5fae5fd,a4e3597f,39c96b8c,6d6c856a,80f1210d,a1ebfc15,34850763,b87e50f6,20b66865,307d0747,a02ba22a,b310712b,cb0bab6b,963c589c,c5a208b1), -S(7de59c8c,3922fd51,68f4151e,cb783775,cd0bc0b,1185ecd3,6ee075e1,14e66cf7,688e2cad,e4d49da7,fe691497,412c9372,c67288e8,ca4b64de,308eabeb,723fda15), -S(ac49d6f3,32cda691,c345f099,667ace08,f6496126,830c39ed,877223a8,cedc8be7,267e6a52,5ddae4f6,7e05f0e8,52b9dfe,5101c491,64d791c9,82249937,c3a7b031), -S(5a92401b,698cc394,c9b714c8,bdcd92d1,20fa72e9,b1311839,1c383024,f469ed22,e29f2926,84c255a9,a739ef0e,5d13cc55,987f5b3a,5c6ed623,29431033,70edb4a2), -S(3609dfba,51616095,ab060e77,d6779025,6456eddb,f4b651c6,442cd673,f893878b,f85fa9b9,442050d8,ad9d9314,9ede8698,91dfc99e,c05a2a48,5854cbeb,55a6c380), -S(332bb85e,92c90a15,3bf602f,45dc33ab,3dea5ef8,7034af81,944113a7,4edc94d9,59b6c879,5f2a824,96d631b5,ceff8708,507db41a,375c7257,7533d8f1,461fbaf1), -S(16e9e054,916b894e,730d7126,27b1bc81,e7689efc,23cfeacb,a423362,df49d87f,303d0428,b701f1e5,fe8ae460,e54adeb2,d4b5aa93,a9c7d7ec,7b903cdb,20e440f3), -S(4e62ab89,1d4c4cf0,2c44915a,4e2fd522,88d75aa8,e22b7463,30dbfbca,97ed9515,a7c21be3,3b5cd522,4de0bd25,faa9c2de,5d6b2f50,b50a6901,b7167b3,c4def4fc), -S(649eedbd,5612c429,2aedbacc,b846e759,4a2b5870,f21452f3,1ac9e697,fc055db9,ca694303,ee206a4a,acfc4cb3,1aa9f117,8fcbe37f,d6bd11a4,669289cc,7c37b0a), -S(e858f72a,5fe2314,951ca096,8ba59760,e3d2a667,e76dcae8,c3ae2d7a,4721afbc,f1c7131d,3e2d0468,ebb89bce,700e0eca,ae83afee,75620938,60e1fc70,cfc7810a), -S(cd351498,29ccb1e6,9b18e35a,72a24b30,e074793d,aab4028b,1c5eefe2,b7b3163d,6bbd52b2,93b43cb3,a19f6291,69ba5b2a,59785099,16842093,1e58dc1,a040c57b), -S(19ffe344,69ba3e43,7d901863,3be7c298,ad8b65a0,49c30dc1,bae30ca5,97ab38fb,c33ca345,efeec662,96802e95,69f0f34d,12ceb64f,30fc704b,b77261f0,ce5c98eb), -S(8a2f772a,a38a5b55,a7081d0a,61bc27d5,89f9832b,1326a230,d81b9f58,4d634293,a4707a0e,a7bf528c,ac62e361,6f09287c,182aa3b6,6862430,dcfef3c2,69d1567), -S(e583bee3,1dbc8f0e,572eb18f,366f88e9,3a7a0484,b4299b9d,335f7836,a222636,8a4fae1b,be122228,be9d8afe,be223c53,dac161ae,ca77ff4f,e14d9c78,894fdfec), -S(8b6e862a,35566848,50b6d4f4,39a25950,47abf695,c08b6414,f95a1335,8dd553fd,15a1f76e,f12ee34b,f2ef43d2,b14605e,db53c3a5,e7cc7c2f,27fc252b,c1641642)}, -{S(1c185b5d,e988ae93,eebe0aa4,a98396aa,fff2671d,8246ce2a,4394db96,7a541ad4,dddf4244,3532024f,d225f86d,133b8156,3ea8c92b,f0ddc354,88e6a04a,d41da5fc), -S(addee173,b29de510,58dc107a,47fad47e,c48bf332,2f7c138d,51060322,571faacd,3890624e,c6920ca8,6a9aadb9,90a15156,799dd771,901823e4,9f3bfcb6,8bf05d5c), -S(9e20bbed,ccdd5c05,d683b2ef,852760b8,e246e5d9,6a8900ea,999ac8bf,5e8f12e3,9f28e5a,b4257f6b,b826d076,ffff259e,1caeda5b,7d34f658,ddfa0401,7cd4768e), -S(dc825d1,5f707c17,46920014,9d7be56,acf2d1d3,c444fa27,cefe5019,6f5b317f,226d4960,2f349d4e,9cd10a57,6bf01681,e4981cb6,4235d347,72a1e5ce,7694a20c), -S(812e2cda,3f473919,1f2ac087,7d70d0e0,2ca0551f,10c96d95,51ba4199,22780f90,c8d05855,6b6364bc,d9aff119,5b9ef26b,85cffa72,1e880b83,eed73cbd,d23b91e1), -S(aebb0870,76f5918e,68194fce,42d0b925,cfd2a506,359af62,146c8ceb,8502231a,c1c19605,e0456cb1,3e57229b,45c83ff7,c3695a2a,31908bc0,31b08140,9c2040fb), -S(af7332f3,3ec274c8,d34f47ac,fcbacf8f,7980cca5,7220012b,8fd5ff94,cbf3d8b,d439f1a2,89799dc8,92b7e53d,a84a9e82,7bf7bdb,7240c34a,caef59a,777188a8), -S(baf71cf,7851a758,12d7e09b,192741f2,1b5d2a36,6e31892e,e54c282c,81163a6b,1ef3bf2c,a81acdfe,17cd6b45,266241a0,22caf299,ed4d87cd,68d3d4d4,526b4d38), -S(615991c5,d250cebf,8c7bd1b2,969213f0,403c7da1,a3ba913,44fd0490,88c2474d,4f014177,12142cca,163f29a1,f5790004,32726712,93c2e87e,f46d2138,c14040b6), -S(b1574b39,26ff27c7,b2dace6,6108b93f,3fc75d48,478567cc,66bba29e,750c0c86,2759967d,8d05be25,3f88a66f,830dfb83,5139e32d,6f42cf3a,43b199ce,ab85b55c), -S(5fe92a7f,d1c407fc,967dbb19,e9fd4d,8361aefc,a3d5a9a4,2f8237a3,458e5e90,9b89ce35,57d469b6,9b9034d6,cee93609,c291d023,d1d9349a,d9bcf47a,aed8b2a9), -S(d65b0a5c,41b2dc6b,e5aa87e4,adfef952,621f9d99,550e424d,176ee180,65f666e,a76fad91,3b80b0cc,3d3ceac3,9a465cb9,4d8c79de,92adf9cd,7a4efae7,c85c30a4), -S(61d7de65,fe34ec4c,f82f67b1,75887263,11683263,145cbeae,18ed192d,14ced48d,effac049,d7e5412c,5052160a,6d1b2230,7157669b,856af0e,e3e46a25,2d2ee19), -S(9a77de66,5165a9be,3dd2758c,39aa7a14,1f052358,fbac634,5ea701c8,c93bc4a9,1044e428,bb381024,70108d56,b8b3e3bc,7512300c,5a6ae44b,93b2098f,a13fc023), -S(4ccb2426,b6eed0f9,651f80d5,72b23e78,d84d6928,57648077,3663216a,bc8a418f,1840c,bf5ccdd7,19f7fa8a,33e7151,aa351d,2f620972,6ec67d1f,fdada8c6), -S(53f96bb7,86516e0f,2ac7611a,1aac61d3,cfbca76a,9609fe,e4cae036,52f68271,97e3acbc,468b777b,bd1c8263,5332dcc4,b08b9fb1,9608fb35,cd51e49b,f09d9087), -S(395253a1,b6a349a6,dfdb0d6e,65695572,2a597411,fdea9294,6e48d107,596d8ac8,c57110d4,dd0d35a7,663fb3aa,e15d8c4,dce5cb67,d3173d91,a6ff7ea2,1bd28107), -S(d7becbeb,c47d0de0,899ffdff,8620124d,b29c8e5a,fd71a0ed,76e0df76,bd4e26e6,d8b52fa3,e16e7f19,e925e769,3b5a731e,18f3163b,1ad4db34,7f878381,da75fc15), -S(fa3afae0,4f8c1fa2,778446af,88e29150,256b0413,d9bfeb44,45288e41,29be15a5,9dc76b39,574453ab,2d46cf23,ce8cdb06,cbe7df15,d03fd390,4470a86a,822028df), -S(da56da00,dfdd788f,90a12219,db03cac1,403efef3,ae706031,e153aa16,b3a52eb3,1012ca8e,ae20efdf,41c77128,93fce97,fc66b187,caec55db,7aaa81ef,cc12838f), -S(f07866f0,cca3474c,40e7fa59,26df41c0,e46fbfce,faab92e8,9ccd1170,3ccf79bf,37ed66d5,5e891f4,e644fa04,182f34b6,1f1aedbc,d2a71aac,dd1523bf,f579dace), -S(853f72d1,edc4d953,348528b8,3656894d,67032333,28a16801,64a84511,15c5e968,197737d0,de83e73b,247d861,510ac76c,3ca214d8,ebbb958a,74ce1c31,5e715e87), -S(7c7eae74,dce7ef76,9ef0ce86,cf6ac861,ffc3d4a9,6313f379,fb2c0325,daa91aba,131e1689,fb017e15,e869d858,2dcfc4f9,153d1e8d,246fd613,b3922302,5b5c3767), -S(56028652,bce9dc6c,c8b4ad5c,f9f222c3,412e5bb7,8d556225,2c06c2e4,25a6e31a,2aa8e093,d8653f6,2153972c,e54806ba,666d49ba,3787934a,a37bd65e,79374ac0), -S(2eb98b01,550a00dc,59d280b0,71e472b5,a65eea89,298fe4b0,9f6f0e07,9315ad7b,74e22fc5,3daecdee,6a0b50be,e17f1d7d,d9481e77,28778957,274c8d29,a0d89fdc), -S(7268b61b,f65d73aa,37766a99,9960d998,18aa4ef2,ae8a97b1,db8476fb,32f891a4,824e99db,3157b706,38573513,618f6901,ce1fcff8,f25019d7,c5c45bb2,f3bb4d47), -S(cdea8771,4a764e3f,a94e7356,879b7d9e,da7c5b6f,28c172a6,1c0ab012,9b9ddd7b,daf49b12,34ce20aa,263b4349,f9f88cc5,1334db26,59b7c587,212f407f,cbb2644b), -S(38831af3,193c8860,690a9d74,cc0079c0,9e3ae0fa,ebe0da02,67ad6e23,99059d19,be188500,5193f11f,e34e70a7,e470cedc,902bee92,e7041403,c2f1ae53,7a8bb077), -S(df3acf55,bc6d97ce,34ebeb46,34fe1010,ed3d6d6,383c11a7,53a93123,e9c8381f,94c22735,ae6f858a,59f663e2,12532e14,4efe6a81,981c7619,e5002968,dcb81df5), -S(a8b08b86,4946ac6d,a101eb85,ee7bdf55,24282ca1,a9956e4a,eeb1afe9,87a43ddc,80ff0174,375c95fe,cea6e00,20f17123,5cda4bba,d4ef893c,78ffe37c,205d5577), -S(fd9941ce,e1c26864,248f7035,352787d1,aba9e93e,f5edd333,d08c89b8,4bb9dc8f,85be138a,42bf190b,921681fa,8777a619,878d4d02,11016c72,8bc151ab,1a687b5a), -S(7e2cd40e,f8c94077,f44b1d15,48425e3d,7e125be6,46707bad,2818b0ed,a7dc0151,6fa48af7,d523054c,7d59e574,cde106a2,776411bf,5111f7d3,65c43ac5,df8ddd68)}, -{S(282c5bc7,5b9c3f76,73e244af,29f22b80,c171bcac,d7e39b4f,ac7ba6cc,656d9010,e8db2eb0,a56699f1,73d5b5f7,99d39e14,dde34648,f159ad0d,c1c7767a,19ae72aa), -S(d5a3eb7,cad9c548,839ceb7f,67145e0e,96c60d8d,68415f76,73b73700,5ce3a8b,34ae4e12,355d1df1,25149efb,1a9050fd,490e251c,4404fb37,31b6dcc9,e233b9f1), -S(68718b29,86197989,3c5f7b1b,48abc254,13bd23c8,96c8828,7000ebe6,6db742a2,bef9d2a1,bb596fdb,3caeef3b,4d950568,8a94b436,4fd85f37,30b20de,b9e9a4fe), -S(a5ed1709,7932011f,9a597511,a526e61d,f22d0bd8,ae3e15ce,655820e6,b1ff1238,dd6dc7d0,81e70b57,4f235c10,c7c3dbed,a57743c1,15e6fe01,a20ac751,34cdace), -S(ec37904d,9662a487,1a471d9f,778bdef3,430df9e2,26fc42e4,7fc4bf5f,80e3a9c4,8413f2f,1ed55d8b,8448e336,ac9d1418,c48846e2,acb43509,f1a3d935,8cd18ed6), -S(b09f9c76,1cbbb685,f695328,61c459a4,d2b16989,3cbbad2f,dd49c87,1d860db4,dbbf9049,31b18454,21c41f2d,2185e3d6,c8f55dad,f1514ab0,655c856e,3391278e), -S(ed1a335,48864e9d,b41abcad,3344f4e7,ebe57841,9371095a,6b95fe4e,ae59edd7,d1146be9,83adc77d,bd9c107f,3092a9c2,9c271248,d78ce913,7831127c,c403f44c), -S(d39507d2,6ba377f5,c7116aca,78df331d,a795cdfb,54e5c912,8558c0e,997b74f3,fa7971d4,32cb5a44,589dc705,de28ad0,382206f1,6e11229f,86ff82a,efef3131), -S(641dc311,baa77b14,35f408e1,528445df,53c5ac5c,32803a3d,84e8fb66,60d71d,2b355a47,76980bfc,8a4e0ac6,a3bd7b02,a6b20ffb,f8650b16,89010456,6953e49c), -S(c3dd73bc,cfb744bc,57bc95f9,3c260df7,7f3b7e74,9e4a5237,f3865f8f,f0c89489,15d58dfb,83654754,80e53bb2,a1ba430a,ce213c38,ea71c7b7,51b4143a,fe2bd124), -S(3f883fa2,e834df1a,6e9b5c46,b663880e,9a0b42f1,891b92c,eb30600d,5641813e,7acff194,a5fb76e5,bd3d8fd4,2c7f07a8,3a991ba6,7f0e4edd,c55e1d8d,3025d590), -S(70c8d4f5,21d808e7,221bd5c6,31f171a9,5e7aa358,4477068c,2549c59e,228688bf,52badf20,6106d5a8,d7bff921,580eb5f5,3a53aeff,e0369f9a,1bcb282d,7b4cc26c), -S(ae08db34,874d39ff,bfb9c92c,5e4253ca,7ed508fd,d12841e9,63600461,b2b3a0e1,dc0504ef,d209be71,381eefd2,91508120,fb6ec1e,df62d24a,cb1d77a9,4eebf1be), -S(627027ad,4aa88477,c6240517,87a25b88,7d5b98f,b968221e,8e45d584,3db6e0bc,34b553a7,c6ac7004,69367afd,17c5eaf8,7605ca18,6a57667b,650fd8c7,18ab76aa), -S(573ef2ae,72ae8fd5,eeb0b720,f8967b44,f7d9d96d,c8a4825c,23a3dbed,fd2bb442,264f508e,efe5e0a2,55e55a54,bbf739b5,757d0a15,994ea9b8,4e139738,7c484786), -S(28907848,cf84eec6,773a384,ce5f4a5a,24c8afc8,606488a2,ccdeff25,6f896dab,ea87d4f,41df8727,2fe84537,d11126d5,62618bee,a51008ca,895a8375,4f05ec5e), -S(163db4c4,536114f0,75521627,c61f62d9,14214d64,ac9e66b0,d85b9991,62c54c5b,7ffc24e1,11c0c845,1c574e9b,e4b56610,696d3667,a6e6abbe,9d1a5ea9,4122aa1f), -S(2ec11f2b,71ffc28c,fb5e779e,7739098e,c969bc78,3cca5a22,77d2bf53,e6574d1c,c5e9fdf2,89a3090d,e24d13a1,bc8377d9,de0bcf4,63482ebd,9620cbdf,8b238fb0), -S(30549ae0,9a46820f,f49423b8,9c6fdd48,703132fd,ac166dc9,90609a32,49039f0a,b8c94b4b,36d39247,732976e,fc16d500,ccdc07f0,d7b97db5,7a1d9fbf,d8cb5d2), -S(98685f94,a043399c,89e74674,240322ac,5a595bf5,41aaa44e,d781781a,10fe9225,4506b1ef,7561b811,53f44e8f,325f9222,e999013,30523885,d8c59864,db13a3ef), -S(9acba196,3014ea9,1baba28c,e273c6e5,b9a2e1a0,98216c3b,194a0b56,dbda7db6,f0a3358e,eec737af,2e313262,b29ddf6,2adb9e97,9f56def2,65102272,6b976290), -S(e81e91a1,7aeec75c,19df0ef7,fd07ce2b,e477c031,179e3f99,4ca13857,e2b5ff93,65236424,aaa8b6cb,fdb2fb20,46ae3c3d,839d97ed,217edc6c,c774f889,d2ce8b45), -S(61e60aeb,821c3f80,b53ca78,2c3b4d21,960eb0d2,c90202f0,a5fba651,1725ddba,b029275f,690d10bc,b52e8bb2,acceb071,f07834fe,64175088,a97e26f9,8ff34432), -S(a931c410,8fcb4346,6802dd4a,8ec2cf62,cf4c5558,8129299c,b3a87e95,6fba2a34,c21a8dd1,43d4a639,339fec49,f56d717c,658a55af,ad72da1,c754fb9a,117cf6e7), -S(fb5c106f,da32fcfe,ffe9b5a2,7ac8cfd8,d9a73da1,5fa6340f,e09d187a,7a83cb88,a3f4c60f,90003375,11c39100,ba4c4721,c6c138c1,cbae09dc,46d1a1d2,5baa95fb), -S(dc25e18a,18f0035c,2a05e80d,d6b38830,7fb3b176,a66ae451,8c5640db,7540dd24,3ba83beb,3e6b29c2,97a0ead6,148f9b93,711556e2,e5fd513e,ee649228,c62d8f3c), -S(ecf7b689,ca03b840,739283e9,c3003a01,65ea3f,3bd17e06,9260c0e9,ad403273,5e0dbad6,47997fca,c0d7ba2a,170a7954,67036ae8,e61dc532,b5fe184a,deb8a7ea), -S(263e593b,10c982d5,1bf89ec9,71f6a3f4,60e53bf4,cb2f6af3,2381214b,2e981bbc,e255bc11,11470eb8,894ead67,c618d7ca,a6b76ae1,a230ef05,3830d028,4a7faf37), -S(f79781e7,a4137ac4,7a9a9d00,9d239b37,6cd0fa3c,b9f5de46,8cba5a11,ffcdd69,d10ba78,896e086d,5e25444,165e79d9,7b3d485,1a448e03,26d8906b,2f27745b), -S(a4d28024,11f577c1,c5d08fbc,457a46bd,428f4d2a,b29475ea,ef622876,593e49f0,e4855491,ac0342b1,dc804bc2,7ae23877,82eeaf22,52874a00,4d4e0d66,b07b434f), -S(87195a80,dc83be4e,cfc9d4b8,29725cbe,11101c26,13c98f2,641753af,1ee840f8,f9fce233,66931c51,4ea09224,b565dec7,22763d8f,6f572057,fdd7d96e,9811289a), -S(210a917a,d9df2779,6746ff30,1ad9ccc8,78f61a5f,1ff4082b,5364dacd,57b4a278,98f1e4ab,af4a1a84,85c6417e,7298c82,c87619e5,500df403,80d8ec01,f384d9fe)}, -{S(6c16768c,433a000b,adc47b10,ba4e132c,f5480e65,ae83d1a6,8aec34d2,c00c76dd,ca1a47dd,66c2d74a,ddb69283,2ea289a6,ae679669,edd80bdd,4ffdab2a,defbb542), -S(f757e860,ed04db61,594bd647,5ae81b7e,d6d2fa58,80cad10a,7756fa26,810b8543,f2aad599,4e491e02,9b1ae256,2c90912a,1c9aa6cd,dfc2331d,a0069a79,861208a), -S(d9f269d2,9aa777c6,9989d706,91403dfd,9025b491,ba03ddf2,dab8c9,af7dc764,1b39b85c,cb4749fb,7f47086a,ce63924f,3ebb4213,af5dfc95,fda796e6,c6b0b8b0), -S(d05e14f6,fe6ca50,a23e9339,e449f771,98e842d4,80a72d5f,8f5e4c06,43547cb9,869e3bea,6b19e0f2,de83fa8a,e932086d,d66e838b,637ea603,5f0fa081,5912c8f1), -S(9f723d81,1818046f,b7512abb,faeb46d3,52d8da9b,3abe819f,3861f9c9,963c583b,37df0657,3f2bb428,6c8b3efe,f6941e2c,4e48d90b,931cd0a5,78a4b52c,6581ee7a), -S(e65f0b42,54ad9df9,681c0db,3428ccaa,11194df3,9e837aab,4564e1fa,254e6f97,43e59d10,54aa35b5,80373e08,cfc02aaa,4f581406,58341e67,7e50977e,5bd893dc), -S(605d61db,589fd91,78a65cb5,99697001,73afca81,23f663ac,5fffd0b9,8f5e7a64,a976a9d,a47745f,447ad4dd,7eb63875,c228b979,a7dda50a,d994df7b,545d0ede), -S(43298aaa,faf20e9d,c2240256,493ef19f,5630db6b,f6376e4a,356bd034,98f1be7e,737551c3,653af1cb,4f8c1e8a,347f50ca,142c03e0,29007f29,c76bb763,b52ed053), -S(8afba782,d6373f0c,54734f1b,4b854e63,bf2a3b4f,23f57a3e,6c2eae86,25c691c6,da3054aa,228b9757,b7321da0,64516249,652fd814,15017584,2c7683ce,1a3638a2), -S(3156d359,e01d64fa,9c8fd8b2,c47c3492,82dd459a,fe89d94f,35906da2,c6d0208,85a23f48,f0a7448f,c57ee545,3978e2cb,6f2bbe54,864477d8,a63775f7,7ff7289f), -S(88e1a44b,1e206eab,49fe97af,30be5e47,25e1011f,312a5222,e9e80819,b3f26357,63dfe52e,10317c4e,227b2a5a,d61b713e,2d93aba7,f0a51e0,b5621191,40c58ded), -S(d10de96b,f2e4a6f8,78e0f37e,15569f3c,b9717a38,7fb98928,6d65d171,4b81b301,2c0a46c9,6a2e3884,e7f3b146,acc170d2,6d12b959,4b75a901,dd535016,f0355ae2), -S(eb36b865,812ae4bd,7893e50,5aef6f14,bfc90c1b,42e75ea5,91615aa,a2101784,1523537b,790b2a61,fb6696d0,a622ff31,efea1255,e1dceb86,763985e2,6c5ca8df), -S(d54be697,e41396c6,3d63f96f,bde9bba2,36ab1649,3c156159,3df81d69,c906fe60,89de1769,433b5678,1f7a2206,ca98258,20d0c7dd,a6d5b672,f77029c2,6bb59f33), -S(d5aa72fc,9063c2f8,bd0fec97,da30dcd2,a5b36aee,7894463a,f7042795,1998c979,ed90095d,bf2d3a67,2d2f1a0f,9737c4d,e8f3e773,c04b77d3,a2345dda,ab662199), -S(ee8cd53e,8ab64281,b5cad323,f03fd06d,7aa166eb,df9185b4,8d0eb0e6,1bd0bc61,4781263d,fc518e4,809e5ea7,7f9df238,1ee7b6ee,ab25c1d9,5cbf3fce,72fdd615), -S(ddc5e95e,2a46736d,9bbeee74,74364bf9,e1d2724f,c43522c,cffa05a8,7d078be9,60908fb,809ae964,98a26cd9,67532df2,409491aa,73c46803,eb58861,7ad86745), -S(ae503a2b,b6250ff6,6ee615d8,41cae4e,751160fe,aef7f33b,dd1feaad,ab236b58,6e53d2a8,8f09f78f,96d49a6,2f98773b,a282b575,ab6e24f8,4d604c3c,8583a66c), -S(8a502d08,bb3cc1da,438c5780,e2120c50,12c1a972,8aaab6bc,5d908b6e,2a83dbdb,fa02e62b,85d7de78,8cf11d9e,ab406523,bba1f912,53006a89,f3a491cc,dd99575c), -S(b52891bf,5acb0019,a8d10b94,87fa47c4,22f83a00,ef539e91,44bd9f7a,d5075716,ae58653a,b167a9e4,b71eecd7,4f4a8786,19c19026,29c0018d,9f082e7d,5920b2f), -S(176170af,b40a3e79,8a88b98f,fb6c578c,d1ab56b5,b7f4142e,b2d84a59,1b009f97,6e1d5682,36176d58,ce5fcac6,4d4d2885,5db107dd,5215c71f,b4076aaf,d31c5d24), -S(27359f7e,8d3e3dcd,ea35f603,d8fb15c0,bd63c08c,3ae4d2fe,8cb6434a,ae2e716d,a0d64207,8fba00dd,4683d597,27f3c67f,3c25075d,802a4ea8,eb08c20b,47a941f9), -S(1e9d955a,2f68478,5227e866,491990a5,62c802ed,1b106bb5,42d02d29,93542067,fbf5f466,57707b3,3f116a23,fe5991a8,90a9583f,fd063943,37a19aa7,e125ccab), -S(b5c4c10b,1b0e0813,37deef6f,c089d2e1,ee14da2d,cbb48e6,74b7dbd4,429e22eb,fdac245,b109947,8f6a53a2,8a1ec4fe,da43b4a9,2ef49e25,8f9296c2,88c48378), -S(bd2f651c,ff6e614b,1d6535cf,c3a2c5d2,da5307b0,1cbd3f48,655623c2,55503916,3715b0bd,bcf29d97,63d7fb35,f9c5b54c,769a863,3517a2d6,8dde74e4,c4277779), -S(c4c2a8e8,f1e257a8,fcd0b11b,30635c5e,782fedcf,f99b0b95,828e1369,3ee0af73,3a08abb4,777a066b,49ec4c01,aa5b0868,f100a473,e555def1,7c5a9d84,b1fd9ae), -S(4aa77ce,15dd97ff,47c1125a,77bcf0e9,d302b79a,e8a919c6,a875e5ed,eab8c2ec,31a09dc4,89a90240,334836f6,302d7e81,57f19762,a9b5f727,6c276e63,560a9d10), -S(3731162e,66a8d2d8,ff4df3e,95950103,f5a03f9a,86bf37e5,605746,cf4be846,e19d7835,10af5daf,724be4b1,932dfac6,23899ccf,7e3e58ab,5bf3265c,667cbf28), -S(6e2114ed,297ba44f,c3926603,bc03a87c,af3e9f2c,8bd84e64,afcd9846,bd9c8f0a,faa6e5f3,3d90f91d,82592af0,7f3a26e2,f6f4138a,2f06a6a1,4286eb71,2e95cf94), -S(50d775b5,f72d186b,266a14e5,254cb5aa,49fd8633,81c36b09,842632d7,ff004130,cbfe11c4,f0b15aa8,3ae8dbcb,9feff9c0,d68a26ba,11095b3c,ba94739a,2091bbc2), -S(8f3ccf31,f8b74b9b,624a5d1b,7cb1096e,202fe5e7,233777aa,859864d3,775732c0,980e32c1,d2c61ace,7610b926,6831ac27,56f19788,ab7a77da,18c421a0,9a46bad4), -S(24cfc017,6da2b46f,a8bb5bf9,636be1ef,fd7e297f,29122fb3,e84c9ab0,c18ada5f,14007044,f8639e59,67978eb2,a21256d8,126a635e,5b07eb0d,97059ec5,6875a3c4)}, -{S(6efcde8b,e99d9ee8,ee0d6b8f,a76584bd,5deb67b1,415e729b,48f3d41a,f1cc1386,4ddcef4a,a6ad5be2,d1e83449,9eca4a8c,73219f80,464a4a9e,ebb7f3f1,b70c9fd2), -S(24fdd052,a1e535e2,4eb79ffd,f03093f8,5778241a,b845b548,31b9a82,730ee3e,c6ff8ebc,7edfd9df,9b7410a,7f54c93d,ff0c682b,152bf4db,1b79c0a6,9889797d), -S(aaaf86ed,31dbf395,687c959,6c445b6c,dcd1fe7e,ba2aa13d,1bf41867,dc87b30b,582b9683,729be5c,85fa83e,2ba2abac,e3037262,2a24aa35,c7753312,1de2fb93), -S(23930d0d,2400db1d,56525bb4,67172fe5,e930bf86,21124fa4,6c5a421e,10b059ea,5e11f202,beca3d5e,dc9b282c,2e86d5d9,30f8f5d,27a5c4d,d2cd6dde,6d1497ef), -S(76ad10d0,bc92ad8f,55b665a1,8ee84e01,2e92dcc9,37e0c604,59bd6fd4,ded2d9d2,d4ca7386,ce0c4c5,fd37da9b,eb8fb040,97d98891,35a5ecc0,320dfffc,95ed3c10), -S(10b324b,e959f0c8,c8a82142,4a8f87c1,fdeb7f88,258e1021,c9cfaa66,b131f3a4,590e672a,daa8d547,161f635f,153fa12,b3500694,677af3f8,90dd4ca6,9620bb56), -S(afdb2acb,ebfdc11b,3577177c,d8bcde00,65151495,79c6ad2b,f7386275,a9314317,87d7786f,5ba775c0,ea47b141,cd0d4274,c7e58634,b64e4c58,f7f0c595,5a307250), -S(574cddbd,59b34df5,30f5dc4,61884ebd,1c867ed5,6cb60832,4a11b1f5,29ebf733,1bfea852,34256807,1fdb4f5c,485caa73,7136e3c3,b4b8a39a,389d7dc8,724f16fa), -S(97ffea2b,5de34e1d,495ce082,d0097b72,e7daddb8,1cb622c,2c14e814,bb0ae278,45fd3d2a,9d1e6530,61b4a356,65aa9e70,43766950,622e1c25,2baab265,6d4ed95f), -S(de627f6a,a7b56d85,535c398,80d0276b,b910ce4a,6066435b,512e5e0,21ef55ef,753033a6,ef89f053,c0e662c8,1557e6cc,d8b4c8d4,5204f5d,e1c8c742,72b96277), -S(b126c35a,d7993bd0,164867c,58c88421,d2cddb6f,d16a5966,7d9683bb,1b428eb5,a9ed1bb9,e9eacf9e,e712bcda,be629143,ad0e7652,82cbfab8,e586cb07,131e5b1d), -S(847b90cb,8837f488,ef027a05,71b2be6c,620cf86f,ead235ad,e76e3408,d0dd1073,9a2667be,6ce36e7b,d76117a9,fdb8f1b8,7c7cb45e,1a03f53e,7b32bc63,6f274b4e), -S(8ea21457,6f1bc2c8,fbee9065,c2cf5c3e,7a3b9fe5,403fb980,96040c2e,c6fe1488,dd75b454,acef4d3b,1b355a63,f0cd17a6,66aa9e65,f1262629,f0c7d1e0,33571b58), -S(9e11bb60,ba4b2d5d,fe53bb9c,598edb16,f3926bea,1cc90eb4,3e05ca34,e83f1896,263d7ea,50d83b8,791fc911,a4f73cac,4d42a09a,85f5ae68,86cb268a,fd562dd0), -S(f741856e,f353a7c7,17db9a13,4ab4aaf9,13c1f7da,cef08bfd,6f81dce5,b1130e20,ee63dd2f,48e15f68,d1acbf49,705fe010,231e26b5,14146c47,1a689960,d568eca4), -S(671ef05a,410b41d9,3b092b04,e523468d,44837d2d,26dba670,27400715,eeefa2b5,686d318b,b49eccbf,40dc18af,f1938fa9,b16d4d2c,c19dd2ac,47c7830f,89b8d55c), -S(59ea10a1,e5bffd6,a34593f4,b986e37b,5294ddbc,60d92906,52c6e9d5,75f88c55,c0a2eb5,6d04ab99,abb5b76f,7b2b55c9,c09d44f3,3785e3d4,64554c3e,dc7a334c), -S(37f2c7c5,69c6fd15,9b721d8b,8d40138e,a8873b6b,452af0a7,89a50551,e9703c1e,d114109f,f9e6d7c0,c51a542f,b2e3ef5b,74654bef,5eb84aef,c87f5096,2a30c078), -S(1d280637,9d77e509,126a440e,b1e56f1a,8723728e,97c92420,5ed13081,98c868b9,85003989,93a4a600,dfd0f092,b13a1186,c1c52dd8,8fc8eace,9bd4f1c1,b47741d8), -S(39aed6e6,a123061c,228d3d1f,857e0c9b,29b70cdc,549b4ea1,9fb6802a,8d8beacf,6bf86967,98e3dbf6,75865a1a,b86d5bbb,10f16e8,4f9104a0,87602c,e6946aec), -S(aa770804,4a996b1d,5bda074c,941b30c1,d1474da6,47d7c4ed,248d3a9f,c3c3c525,10ba5652,b20482f,fc2434ce,ac185d8d,af6cc6e3,61e77d3f,258abc0b,55610879), -S(7626a96,9f9ef188,3ea82737,83e5571e,4054fb73,6190977a,299c2a05,d29f60c7,172d4618,e5f88055,ebfcdf9f,55267ee5,cdf18396,1d5a2a22,55b87ba3,c7d7d2b9), -S(1a550684,d1195da7,c4b09349,f149eae2,5a1ef23,c9a81109,115d93e4,c98cdbda,c31d7dc1,b7efd019,c491010e,30f90ed8,7503c4bb,1b37fbce,3dae199,6609e3b1), -S(8d2306d2,dd8c753f,2b093e62,86fc282,ba3e1dbd,7b4ba101,83d1070e,d2d06e67,97dd14c2,d2c1d147,486a3dfc,d608ba28,d63fc03,251a106c,9811b088,978e3a5e), -S(f31a69ab,97039589,940851f3,cdc98bc5,d400ff93,63794f81,4d88215,4f00db99,56e510be,7f41b009,89792401,13641590,40f5f305,f27fe1e2,db1cd7ae,887ff5e2), -S(ce96b3e9,6eb94b7c,8bdc7b57,efd2186f,62e23e72,f11337ab,be7405d3,43b4d762,cc0dc898,33e7a632,d0fed52d,487f2c60,96c69664,f698a71c,3f7f8a29,4f181add), -S(bed97e25,7d31b5fd,36b41227,462d9122,706da670,d432ceff,5d37d83e,fefda56c,c0cfe30a,2c3b3074,1af492b6,e3797c4f,3b00593c,6806e2e2,f2cff401,6e877ff6), -S(923bc6c9,960f6e4d,ca2a7070,6d160e19,83a16b6c,8535783f,12c5ac69,4aad226a,c47f08b,6b2056d2,8e9f119,9ec6d5ce,b48801b8,7ee56280,d6a48352,b2b42b1), -S(b3cb28fb,7465cdda,85823dcf,819400b,357bce11,23d9229a,eddb8262,53b246c3,cf035ed0,b624dd68,8a31eb5f,3b28e83e,c0bf9453,649dfe4f,44078eac,9345f2a6), -S(c69aa2b9,ab3c5e45,8713a912,e7f95bb,4e5498a6,d4090323,5cfed1c9,c2a60709,2e95e198,85637d55,744e32a7,98c02c7e,b29f3bf5,7cf7c870,7cafdf41,f6710f0c), -S(45996af,5795ea6e,43e0fd29,671e119b,8b8d6ad2,4eac90ec,d27d5db1,b4fb6a39,2c0651f3,1c7d93cc,98d79d7d,f21110fc,8c1dd74b,f1ffefac,a3d52484,f8da40cd), -S(264559d8,7829256b,ed116900,d82d0c37,9f0e4d12,53c68e6f,cf2d41ae,7cddab8b,861a42e6,d92caed3,108439c8,fcbf8d28,8579ce50,c6350e19,3609b4b9,ffe217bc)}, -{S(ac13e0db,846df259,fc38d6,3b0248ec,9fcfa8d4,bcee368b,1f4a66c6,d41f9163,6721b0df,2ed06fda,9b485cc2,aa56f1f3,3a913e99,f6809577,95280451,9ddc96ec), -S(b6b7227f,228da269,a0e5640b,8a2cfa34,555ccdec,2243dd0d,4b2da0a9,b4cb5e4,6afe41f9,dc129d28,4786bb76,17786c8d,42597435,240f998a,f970620,90d32059), -S(460672e4,4f2768b9,842a98a5,ca8b90df,7d9f52bc,3fa2665c,4272d7ad,5f48b992,6d7f8b36,13b38fa5,80ed1d4a,21d196bf,be491b46,49c96da8,342441d3,f4af4ca2), -S(1d3d4ab8,b7c06136,8dfd612a,25f04016,2bd3f6cd,cd9cf58d,c11647a0,d28b629f,434dca08,17bbf964,eb0a316c,b2b0df20,eb2e965d,c4d8d795,1d4a6e66,5ed23d38), -S(9c5d6342,303bc7c,73763cb9,2e3d7069,7d913f6c,1a6e2f47,39470da3,22b7c1b,825c1a54,395b9b41,ccc2e3b5,3fe1092,f04c382f,b2ee3a29,fd59e255,5f22fc15), -S(5c751285,a4b55535,fe24fe27,568868f3,afb43cf,aad1d2b1,c6367daa,ac9493b2,e2388ab4,414c4e4f,e34a4c78,c869dd93,7094ce2d,4f4666a8,2eef8047,3b681fb6), -S(8c1592f3,8d73e277,d3c18d4,ee3eabce,32e86f92,2b27c2f0,1f50509e,74dbc211,399c9507,43cd9e7b,200c255b,bd25670e,cc111462,2d5dfacf,9dbebdb,53ee59ab), -S(85320e36,5f40235e,621171d5,c8008845,890f521b,d7e2cccb,88c7fb7f,a08200c,96bbe8ec,74b5f1b1,2a6ecbee,2aea6f0c,b6d0657,aac3556c,ddc4e46f,17cd31f1), -S(5fc21f20,13403705,687b8ad3,387a725a,f2e6300e,13d28403,569d4cb6,5dda7f34,bb709fbf,be95aeef,c00846b6,a4645b72,dbb4e1ed,866edb57,7bc5d9a8,2b774b0b), -S(fa40e658,588f8a5e,29d380e9,c1a6482c,888f53e5,e331f8ed,9b1273a,56d094e5,5486cff5,3b7baaaa,de8a51a6,1d1a9255,95ecbea3,39955c0e,172de4c3,4762eca1), -S(9f87d04c,5fcc48f,375c40af,3197c28f,c62cf3c5,10fcdbde,5aec79a7,4e6a6bc0,9a6cc172,23a770c7,a03b5333,6922170d,e9409f3b,9846b9f4,41832ae1,f70f5c57), -S(bb66dd5b,2f88786e,736b50,e536a0f0,3d59b86,511e95ca,1bab2cb8,875bb187,f8215527,c76a5af,e5e76a33,eb2622d,5f822ad1,d284c68b,c840f65d,4f731c63), -S(74d223e4,bce2d6b9,b2fa9482,46327e04,18eda6c,cfdd76c7,cda8be62,3f6dd3a9,b7276bb3,817c0e72,e1ab002d,50531065,e1c4ca30,9c6d6f18,bb5796ee,457b4270), -S(80298b62,eb4d3ff2,e10607dd,dbcacda4,3bb30e57,f3c8c7e7,6f9f3968,bf391316,fc72362b,48c8b606,4e428e6d,1ef2ac87,931caf75,e936a33c,228a5caa,c460c5f0), -S(8519f27d,9560acdc,509fddee,9b4a4a7a,8b13496f,14760a08,22609f3b,2ae07963,193aa9db,b98293f8,e70d7253,51d3893,a9f5fc73,6f3c8e65,28a2dfd6,5dedc220), -S(49d734f9,c8eff915,fd66757b,d6484bc9,548f20a,d8c05959,f651eb36,e45cb88,4c594f79,7651b49e,929932a4,59e3bf21,3e74c0b8,acb20907,697a25a7,ed21057b), -S(6a528c6d,19b1e28d,b4d9ec9e,19c4f7be,184ef845,1f41b322,e5932f05,575bcc4a,7350b90b,c22ab41f,40c13a80,18749e8c,275d3e5e,5d687df0,ddd47133,c092eadc), -S(6f3df40f,5647143f,cb93b23,4795d9a7,708db6b8,2e2df53c,f214de4b,61eebaa9,dee10664,54b625ba,34ce4b54,f7285714,7874b5d0,6b38b1dc,37b7471f,9208dcbe), -S(5abfd7eb,c4c5dc14,cbf0e335,f2e87e7a,7db96a2c,b78000aa,64fa8aca,517ee1e5,d65a98d4,20d872e4,4c43997,55cca5c0,bb94ccc0,b25e30fe,8b5a4fcc,7006364f), -S(1bf3714b,da04d769,782e37cb,c4a4b347,f9fc769d,a18e4940,d19a205a,bdd22a23,d0852b21,33b04274,183f4de4,9a20769e,4a08ea16,ca8782bd,84a4da7c,64c928a2), -S(773ab884,a4e90454,ea467caf,f18c3b64,e316468c,b5789fa6,4958f73e,ec3204f1,62213b85,b4838d8a,fa3a14f9,32db7d79,dec538c7,d872d9d2,be1640a2,4e367caa), -S(33a283d9,9b7564ed,6ed10d88,ba26ba,fbf3a375,e00e10d1,577fce27,2c204324,bf84dac3,40736625,cf0e6be6,98072c6c,5fb8bf9d,2850be84,ded3f652,569370d2), -S(62bdb467,596ffefa,22b735fd,d3dfd959,d4a6e187,a19d4c1f,4d647b4e,db380c3b,210a8e93,d1a184d0,a3548be7,6283d180,8e4f32d9,52834c,515953f0,4ecf9acf), -S(ef16d3a3,233f03da,5864801a,c246756b,d1356137,971bc164,b5512067,b369dad2,480e3d32,7f1df8b0,646c3b58,a51126a3,e91522de,ab77d6d2,f2bedadf,1219b877), -S(a6834869,c006d044,a9dcfb9,8a5a14df,86469fd1,fd0cba06,a4e8ec1e,1fba89d6,c1a3e0ff,7abeb1e,8cac11a6,8c1b4c1c,f663e615,9f508c35,f4747f50,84b247e9), -S(203d13c6,53a3c36e,55a836de,b38c7443,681d7b7,c681d71a,38fb0fde,986ce9c3,5d7dba97,573ffd85,b3fd4417,f09192e1,92461c4c,125a9947,ced9c737,ecac65b2), -S(c48819,b8f32966,bd50f162,30f5c0a1,45cb3570,d9c4b104,4c306696,2f4d6667,feb08ff9,1f543c1,35b6e0f0,b21d7624,91ac096a,181bf093,fcf8f4b7,bf6559a2), -S(31441031,ceabfbf8,59bcdd8b,6e177f91,df7bfe08,f9015172,1ead3acd,ab64acff,e36315bf,6f087118,32894704,8d2fd259,6b8beae2,e1917341,d690a1f,786db5f9), -S(e3e4750a,310c48,38920654,b6afa032,79589d52,74e48139,6e22d9cd,3c05fbdd,f05868fe,5452da6f,fadcafb6,69e5edfb,4b9a7840,3a305004,345ddce1,eaca43ac), -S(3659ba70,60d8200c,9512facb,5c730111,4cdc2b9b,aa5bde14,8ad9bf9d,d8f8fb8c,b1185617,f91fe5e8,ec68da07,138b6780,e1ebd12b,1bb44eca,8a1b9472,8337585e), -S(1a46b7e9,fe99a4ea,492fbc90,3281b924,6831fe59,9360af53,bde4ce8b,43ed5996,97c317e1,5c0e23a8,f1c11f7b,5f9c140a,af786b56,10ad8ba3,d11b12ed,17379f81), -S(f16a409c,677a40be,402f8efb,3752373c,aced053c,6f702b82,8bda222c,a412b6fd,d5becee8,ebacd866,285958a5,8b1cf1b1,e9abf9a6,db61435b,d9725187,135fa955)}, -{S(32c932eb,6fa35974,90a408a6,ce962d7a,ef2bd22,72cdaa,cb80f798,9836abc3,3e145848,c2f8197e,f0264d7c,370d1784,7d21a09c,77fd9f7a,73245ce7,2ce5f3f6), -S(49d837bb,63890b4e,8a4a63ea,6d88599a,c9961c20,80dcc955,aca6a101,bc935f16,358a7f6d,b540ac03,78d83bc,304cabf1,84c7580c,46c258ec,58f22254,e3e03aa), -S(23516ddd,40dab9d8,63dcad6c,cd325503,b783379,d870ace0,9a0b238c,d7b6b2bf,b1fb8268,a7814efc,54f3d637,88956b67,a3997a31,10a738a4,94786d95,a5fa1c59), -S(6b4e215e,df56e6ce,6378fa98,5d604f68,e3561275,788283d6,c40cb249,6d16310e,cdf9537e,e6f4304,dbcb9df,f8b97a71,a12f014e,29867e5,6b09b388,78c9ce8d), -S(f4f30433,c933dddb,949ad868,cc0d52e5,247149a,7ec98f12,3e7f63b4,acf6b7b9,949123eb,9fb848fc,d7b94401,a64b21a3,53fde44c,d93dae3e,b7a2d3d4,78055af2), -S(dc3523f4,cd24be1b,30787dd7,5140fff,b66e4487,55e9a3c9,6124fe59,c07faa28,47b945d7,6d37b855,8ede59fe,e297a8e7,81d3ea96,f0a81588,b68db767,9b9641f5), -S(b92cace4,e31dc724,3b3530b1,f90de1c3,47cc39e5,5b247455,a1296912,4e3c2a09,78f89163,c735cb13,b1d8fe7e,547027f,68d8f864,a1f093b,22c0d9cb,95fe28c2), -S(8f7ed1f1,77238a68,bbe32e4d,ae6d67fd,be07c9a2,9fc6b940,6ef81a77,65a8fb75,98e627d8,d32095bd,5913daa5,920c5c60,334691be,537b08d6,da5b8c19,7bf81c8f), -S(47fa27ac,e035176f,34c59581,8d3dca2c,a2b40e53,29756c55,7cf81f75,4f99316a,ddee5921,f381ce26,3634a34d,1b4f9513,4d9f0e50,5e96bb79,b87d98b5,282aee7c), -S(7584cb68,60ae81f2,e0df701c,97d7aa29,8132cb96,fee4ad59,15424bec,2e280dcd,4b76458b,e3926b5b,bf59ad77,da4a96c9,1f9147bd,88a234c0,74b0e09c,a6993228), -S(2cd4c11e,70d432ff,38550aca,481667f4,d09ad11f,9aed62d4,968492d7,5de28dae,82514708,3e5bf46,341177e8,9ad2cfb3,a215578c,52f9436,d3952432,e9acd430), -S(2b524c99,2b18a6e0,30863716,362d236d,e385a10c,3679eec,2774edb7,a1a89be9,1abb3b28,3477769a,5c7b4580,93efb22e,f2e61296,da90d4d3,1d6b2ff9,1766f89d), -S(d642c258,9d0e47ef,f5b2b60d,9321db58,727315ad,522daf58,3bdf35d3,336f1081,1019505a,994030be,484e5340,abea0b7a,51276c99,29cd1f1b,9d19798d,aaacf3d9), -S(3e5e09b,451bcf5d,549f1d66,b96da0ea,25e63270,dae59606,bfc3165b,f89f29fd,2ce591f5,32d57be6,4fc48aa4,ba40231d,9c104615,b76ed6bf,11957694,16d2f0e9), -S(4756965b,82fc23bf,64041d23,a23cba32,cb71d3e7,ef3e6c03,51b20f3f,dec049b6,75f3a293,eae07f4,362c47e9,44a78561,323244ac,bcecef0c,6ba2f5fe,d1933679), -S(f296e9c1,41694ce2,c197ba85,bb9f172,54fc0bc7,f89347,a0e92b8,58491a39,73c7fbdd,91c88ce2,bbcadaae,df8880f6,aff07e8d,3a1ce05,a468e3c2,3008d98d), -S(b437d387,ddae39cf,e26edc85,b0e600bc,2a199b6d,b521f9c9,88d921dd,7e6fc761,ce2111f4,d937905e,2af7f2dc,559f9eb8,bef286dd,909a5965,53c7f61c,f51aed18), -S(bacd4a38,f3e1b7b1,b601fa5a,2a579e87,459fd189,a607314,5a0dcfb6,1ad3c21b,8be8d6b3,9553648f,2a94754f,4c6c14,c4917296,aa9987f0,deeb7e66,d81c3777), -S(d8164748,8ac6bca,945fce70,e8f6a256,90512c8c,dd4c8fbf,b553c131,96f7f607,16b75474,65a80a67,86b5246f,e086d32c,4db03b83,58271938,41877c38,2b5bebed), -S(9c2b0749,cef57b4e,36b31328,e01503dd,ddbd2834,5cd86ca2,5224b967,1b7897d5,f020f978,4eed44cf,cc4aa33f,b2eb4b71,f24b5f3a,a8dc1d72,569bdefb,5f6276fc), -S(ea277814,9f0ab428,63b05bb1,c113ea7b,91afb815,e8f0791,12c11573,eb044e4d,8199dc4f,4e72b691,1c562ded,1220aec3,ab967029,139d30ac,58c753d2,f4548030), -S(4be6fcf8,40673659,5a9e4f2e,877ad7bf,28e25177,63d74238,6e43e6da,1c1c43fd,eb5456f3,d1c40592,2eec37ab,3e0d08da,b7cd257d,9babab02,44e5b2d6,a827a7cb), -S(3f1e9ab5,160733e2,9e7aeb6a,378d169f,9be5c266,a6462e2d,e736be07,f88c1da1,907fa0b9,814da057,9bb11309,aab51902,a0699aad,9422e1f,b8f1a8c4,aa9d4399), -S(eb730dbb,1ba9b2f,50453837,35ec6da2,ac4b5019,86cf03f0,3f5061e2,a28285f9,41dc3a0f,f42fb1b5,d3b464a5,6e305fe5,c60c4561,d6e5a6a7,8cba87ce,15c392fa), -S(aeac891d,f7032059,54d0bab7,41927702,1a595a4c,37bfc34c,5d315876,3e85f3ce,168f8260,1331b5c5,edf941d9,9f1cfe0b,72fd2a1c,3e4bbc2c,c62d47e6,6399105d), -S(667e04e6,daca6315,4888ac26,a268876a,f4b754fb,87687ca7,3c4cff77,d6dac204,1826a26a,cdca828,8e2ac81b,855a4d40,86f3009b,162fba82,83cb1d17,b9f7aa4c), -S(240ec754,24e46326,8e2e4ce0,240f335c,78c46150,1e18cedc,b32e3c51,77ade3e5,be09c744,cf6e9c6a,75976c03,530329af,5e11e5ed,3fb13e8c,af40bc5f,95872645), -S(7b83e4b7,70e7a442,3efbb501,c23881c5,2bbde4b9,d5aacc38,7071decf,79690025,d242ed74,441d1ae6,61b97c83,70be2f52,dcbc2831,1e8707e0,1b44c827,420dcd45), -S(63589c41,fa8975f4,c8738f57,579cc0d8,447218c,69da1a34,ee06af0c,215f6c27,c34f2ede,7589760b,80dbae48,94a3c13c,7351bf5c,33a35351,9988ba67,c2a56d48), -S(db092b0f,4638ee45,190473c7,cb60cfec,45c94d96,99aaf289,82d28af,16ba1c66,8a96ecdf,29ad2fd6,3a85a7fc,b73ab6d7,719bbd6b,98d052b3,3a0cd91,ab924f46), -S(11c4dd8d,3eddc0cd,9a832dd2,dc91c8bd,491fdb51,f5da21c5,732dfb7a,362b8df9,ba4c2789,740b53d5,51bc9fbc,776f049b,e848182d,9d13abb7,e7cd860,96911eff), -S(a65a3a01,df3b5ef2,e620d431,49fbe1,4d71457f,19d1ed35,aea39d57,89303fdd,86715f6b,f300a390,470bc272,6f12d389,7979e2fd,b0512c35,252bb571,fd19752c)}, -{S(d8558716,b7033a9b,29afb346,fd71663a,79b6e86,2719bf12,6e532dc3,f581b7d,a790d460,1e5b2630,1ad6ec43,62f79120,d75449d,8a500e2e,6f17c021,8037a405), -S(842c01b3,54353026,c43dedc7,8829ead1,db35b63d,8c4d0d36,8cd7b661,2eb5e11,f173cab1,a37ee0d0,68e097af,17bf859c,13bb4823,255abddb,f0dbeffc,573e06e7), -S(acac5cae,414c3556,38e293fa,e7cda051,18924e9d,abb81bdd,29123768,c7f21443,5d17b909,5b997254,5f56770c,dcb8af40,e37e1a8b,6e01a989,34ec22fb,f7d04537), -S(c8e73810,c024c6eb,d5398bda,3784261e,542279e5,3438d49e,83b2639f,80889aea,7a2183e7,be4f81,b0337993,935657c4,c55d20df,729d2e8d,b25af238,f3d85f4b), -S(f78c5f53,5e7ccb53,555a6f2c,b1de1c5f,da379360,f6a7fc52,eaf86ecb,dbb3bf90,cf2d33f5,eab2ee1d,5a32eea3,18f9927b,cc982fed,cc9add2e,2461ba14,9def0292), -S(4cd40c43,bdb8a042,2babc95d,eb00a405,59519074,5906a8b7,b5ea00da,b7f995f5,a0bd1c74,79125d2f,5baec520,21fb7c62,415817f7,2afb80,b2315dda,40cf4c4b), -S(647c5950,f8a7fe9,e6945b3d,6da91932,b486a4fb,ed903836,9fbc20f9,a849ac08,d331cf32,d72e148,b47af547,6794a33d,55f49ffb,be47db02,7d2de73c,542bbbc5), -S(97664e78,980a49f0,8269ff19,649e86cd,7da88a76,eb1441d8,a5f3fd2a,6ea335d2,b2898268,9a8cd91b,b1b16be8,ee46b4bc,252f7016,f72432c0,431f1264,8d7450a7), -S(523f68b,b39c2ded,81d22a4e,575483ee,d8748c9f,52c06081,391c27d7,7afe3805,5c331672,4464dc47,cc9cfe32,864b6095,ee8bd6a8,42c1af98,b3e33183,a46e2471), -S(cad866de,5cbf4938,989b835d,5aed958,cd7c316b,980b7c76,2109d688,d7ef5b25,3ae79c30,e77d6d4e,fe404b8f,324179c2,f677f434,8a1c4367,2a0fb5eb,b706607a), -S(ba065cef,b47170a,d6796033,d157fd1c,f22052d0,7b7f9992,6cd58e03,316f95a5,26177c08,bc535702,7f5d03a4,9d982637,d74a6b20,696be76e,742243be,b9ecddca), -S(27ca8178,be756f12,22cebe6c,d05310d8,5a6c4f59,eec71613,7777b625,e6d44c97,de547a17,ddee9fc5,1fecee01,45f9cda1,b65f097,5d1b9544,aa2317f5,102537cb), -S(bfab1d94,d04f4909,dee00998,78f77cc7,d9de94a7,96b5b770,5f3c759d,2ae97ec1,6ec39a8d,9e900a79,b8b88098,d1e5d79d,b75ef91,e442cb2f,27ea531a,2db21bb9), -S(b48a4f25,9d82242,59f08a08,29b05ac8,ae6b97b5,56cccb84,20a479f5,df92701e,beef137f,9f9acdc,8d31a780,2290fe79,9d9470a7,3c8a01a,35abcbee,9730d17a), -S(e3f5d307,ed2f2f13,d23ae5b5,9dd567f0,8161996,776d506f,b53e14f2,70a52370,40ecc697,7da3771f,32a66438,cf70ea9e,550194be,1af85a08,c8a4515d,32365803), -S(818b0462,d5a815b1,57216ab2,4d795886,17cc99bb,7a7abd91,655cacb7,ba99335e,c6ad05a6,7d2a391,a15b6600,7716e02c,9fe40db2,f82283ef,c9c0a7d5,ebe854f4), -S(7e3c52ed,23220b73,ba47613a,bf39a9fb,b3a6bb6e,22c972a9,3ef21a61,50cdf830,b3e4a95b,875719b3,bec1b113,9e29670d,4ba8f39a,2fb76700,f69961fc,bd01fa2c), -S(594e4129,9c1a117e,ce8564bf,ba88ce04,297f2e14,7ecda07c,5f12913c,14d9a5cc,60bd54c8,7395fee2,7fedccfb,ca9524a9,b5750b2d,d712621d,e73e0692,46c2e347), -S(3686bf4c,f387e340,6fc314e,f02c637,ee6f5062,ee9bb567,235b00e6,4d516648,915e5904,b106e057,a0db43,151ac9f8,4871e843,126d5285,337dc3b4,52c67165), -S(338dbd1f,42480753,516d3cb2,c535492b,72849870,a7828b48,643dc143,b966ea61,e51f11ec,86104334,9e9dae17,78116032,949c66c5,3c4d441d,3c88cf4,c7ad61c9), -S(56f935ae,f58bb403,7649198d,1a5da704,26fd944e,c5694c18,38c94287,2130215e,a9c48fd0,3b059474,e528016f,9c998e02,cac7c40b,8c859852,b58b9082,b638222b), -S(1faadcd3,da472591,cc723754,82546c81,c4f53c14,d0d8dc5e,ab95a58f,379e6899,5bdcc45f,42d0ba3f,783a0806,a5d08c74,a1b1b9f5,a559248a,8681b153,74e74958), -S(532d8cd8,fdf838c7,70b87ca1,4703a884,116dd928,74acc660,6ddddd61,8eb053e8,67a31325,853db4d,3e5877b1,c76e7e39,468d2d77,37cb8a6d,af4f16b8,17cd8ad8), -S(8a8cbfd6,d45e5740,aa9f0a21,f40e3671,ef897fe,bf2bf753,ee2d2f75,844ab648,d00eed6,efefa26,46c36895,3a54045d,96da4cce,8ffc554b,9bc989ac,2f62acaf), -S(38ae095a,3c705343,38e542ff,6789902b,cc1b0b5,7763cc43,2f50cd9a,d26d0f1f,100de239,87026f09,e483839c,fe9e1f10,11bcfafa,662a9331,95a8e4ec,e4fc804c), -S(82d9e5a8,385de1f4,fa541796,a00533d9,a3aa4656,74583d07,c4b3c344,b6ff8cb6,70bf2bd3,5765165b,a466171e,f26439e8,f790e178,f67ef5,d2e15e98,435b4261), -S(1843988b,42ddec86,dcc6c9ab,36b381ad,a0ca745e,aba36bf0,237e2830,579aaafb,f1bdc95c,d76337e,cb3cfd65,d9c30b7a,e7c7d667,65c9db5a,6130edf5,e240cec4), -S(a32f7415,9c2743c7,2ef192bf,4a68e838,97a86a0a,3997d1ce,fda3c581,b4fbe683,8862903b,db791be1,dbab5031,ca57f161,b6449bcc,db061438,f45e610d,50ff3bef), -S(b09dcc04,d9c30c35,2bd63880,a766da1,f6314287,dc201bbf,9605516,3db2a09,7580cf9b,7e30dbf2,8f72e9c,a5152ff1,956ae42b,3e952b18,512824c4,7f4e5b9c), -S(ca07cbfb,b24ad1a5,edd9a12a,8ac54157,6f3f2ba1,4b878d82,ab7dc996,bd7e2c95,5123ceef,cd20f120,b575dd98,43ef9936,c53cf90c,c481f340,fa166452,72af1c8d), -S(f8058324,c6b9c2e7,e62147e9,a41ad78d,60e3ecf4,17524c05,80832add,f11349e2,6a39f1a5,f577a932,3217e559,f15eeddc,af6b674a,9d921772,a053b960,a4dfd633), -S(2e3c0532,6255d80f,a42fc69,d5c92aa4,cd326a5,3e8535f0,435efb7b,694a09ec,ffe0076e,9a93904a,42251dbf,47d03e54,1fb75ac3,8f8499ae,dacb797d,7738c9b1)}, -{S(7bd8469f,80f009fa,b4960cdc,bbfbd4ad,d8e37bb,a4b2a34e,d5c95d17,7a94c207,f3062154,c3bcc160,b2aee99,aac98446,516a277d,85b37fe9,34be9359,4af905c6), -S(139b7c10,ce844844,f5d0a9db,bd7e1679,17b37e93,9bb6fd2b,4f19643,f22a6af1,32d4e929,27f5951b,ffa4ddde,4b091ec8,531a6f23,f1772c9d,ada292db,2b88c1da), -S(f49cdd14,14b38e5a,2dd34bff,3d01e1cf,ddefb954,2a641edb,df698d83,774ee70,5c10a6d9,200253e4,a932a42d,2e770f18,69d0336f,3c44f480,ce4a3305,83050c31), -S(ee145304,4771c862,745f03b,4776ade3,104ea0cf,eda8710a,5fa108eb,1e946826,b91f14,b6127808,f1175b72,2c09e02c,66eae622,109f4156,261d65ff,506b88bd), -S(c9ebbdda,867f333d,39142483,2e4150a8,c98090ec,d8ba9c09,3673330a,8777d790,c46d72c6,6028477c,e4754960,d40bd10b,b2defc1a,17dbf018,538b71b2,d208372b), -S(707bf0e3,9f2c8c6c,73a5d0d3,3edb32e3,46e73ac5,dbeef6c,60fb5ebe,b95ece24,adc6edbe,151bcb7c,2ed5fab,1cb9b2de,3ba2f3c5,ca762082,902582cd,e9e27f54), -S(4a002722,9fda7d33,320fc533,27b6c9cb,88a09c2d,e95aad01,65f68f45,1c82e2a9,233416cf,1cc1ee38,90816a09,17c5fd0d,da0bb8f5,d33c709f,6f1b07b9,916282e0), -S(8efefe27,b45a4cc0,3088b6e2,2a0baeb0,3e772763,58af3217,f39c7222,1e20b59a,b9f3fcdf,65771acf,cc7b7486,9b10bc3f,b0e8fb2,960cad82,24ea2430,fdad1634), -S(7bd3815d,6779f321,195047a5,b1772b19,ab29a99f,cc082e93,c442e927,b1ddb235,eeeb4bb7,480f3dd0,92e627a,a042533d,a9eb598a,6cd1ed9,2d75aa89,a592ae8f), -S(883f939b,6bc9169a,3860d36,9894c4b5,2863b5d8,d0348c4c,62368a94,737fc3cb,96e37629,c05b7231,8800ad96,8e922f7e,5b8a2c39,62a25210,9b3e4949,4b24934f), -S(4ad8cfb8,e8ba3265,4d32a656,76822176,95c40b92,e97c6d3b,af26449e,149f4b3c,491d3eda,89930ffe,e401b994,54919947,7ef33a8d,6cfdfb9,eb28295a,c5ce94fa), -S(ff15cd1a,4b185632,c6f11ee7,19319bd3,abce5167,65539608,b1ee3a4e,1671369,24df322b,ab157296,40aeb039,c00ab8,91c96833,4142f87a,1e00d105,b08c63a2), -S(3fc8e63e,995fda97,1d09d96d,4c84e18c,3e0f4d6a,9f8bca41,20c7c832,c4e9d49b,e17b239d,8e6f7fe7,3c4e46d,3aef9040,6bd631f2,da1677c8,db698484,85922ae0), -S(d88b3d3,6bfe995e,45812e9f,63e8b6e7,d5a87562,1c4a23b7,ab46f6ad,2f7d1e81,63079694,7c97b00e,311bfdb6,198c2c4e,eda57d09,b17fd74f,7140b40e,d2842d06), -S(da6971d1,4c0e9c37,e5b1379b,9cedd83e,218ba47,95e4af56,7956922,c64750cc,a14a0bd1,ebd0727a,258c1246,3aaff478,fcb490f0,53d08a40,44cedc97,61be43fa), -S(d098ccf,e2fee442,74377e1c,57d0b924,45f0954f,7af643d8,b7ed5d9e,956fba23,85c99754,17df24ef,2786621b,c0be5069,a9c59da1,61e14759,ee26b524,e9587d18), -S(633f9b18,9dd98f3d,8c4de,528f7170,1c9d5972,cabe3219,cc4e5f0e,e7e094e0,3d69c877,28c859e5,d9e8ea27,3c04ec98,ca084df5,d7c9cb34,9fa537ad,f7da0b5e), -S(2e14be9,af0dda46,8d59df19,9ac9edb0,c875f829,5715cdda,5ba3bed5,d54fcab2,a04688b,64c5d34c,752396d7,f864a9e1,59eea9aa,db8c93c1,5b4d7cd2,539bfa0), -S(adc92567,7678b197,1e45ed31,38a991dd,a4cd3586,a1ce1498,3ea30be0,642a2dbf,70f2c69b,7e47aa55,cab6ab22,e6482571,e8e1ea52,a52df934,d5ab99d9,acce2770), -S(ab89aaff,b04be186,183e8076,46c64111,476c552d,10df84ba,10a1efdb,32c01162,fccc1e20,17ac63a4,b9f78ca5,af245a74,4174c952,cfe29491,11ce1d71,e4be8f87), -S(1195576c,ca3a49b9,4db3f827,1ff2308e,66b66739,a30d73cd,e8acda4,a382002c,6a2be3a1,c6ae9f0d,b314a7d4,728977f2,17e7c7d0,199868fb,c7f79d31,6cd7d32), -S(8a15bed9,bfa215f5,42c62c89,da0adb8,c68cbc33,d9c879d7,a2f2803,b7068556,ef437bc1,1786cd73,6dc321d0,a3360517,3e7572f5,bce04b7a,3c8cdb85,cb56e697), -S(b4521d6d,f9b20080,4d3799ca,4cdc87bc,ea970d60,a3005071,e910210f,5654da88,c4ddf348,2a23e98f,b86ab9e8,4decc6b6,ad18d879,e96435d7,4b944d8c,f7cc1587), -S(4074523e,b75634f7,6442c3bf,ed9a52d4,5f6636f0,77a10e84,5e6ed950,b673a9ea,d8889a02,ec95b511,aa74db1a,10c91547,45b89b57,981011a0,9d4ce57b,e4e1f032), -S(b2e71794,e6ac98d1,ce532974,df79215e,bed8c668,561dc391,505e9e26,8444a858,94d8ff19,b8a74599,fbe5f471,e7f3e1ff,e0238cc9,2504f99a,9c4f5fbc,2e482854), -S(2e672209,8a6b4ca3,905a8910,6d23daf5,aeee63e4,34e7bade,70395df0,e5a1af87,708e9fd2,a3c0a3b1,b0e03f96,c3d477d2,abf6dc0c,bb8a7181,ca4b18db,ed12e3f7), -S(7ec0fbda,63fe7404,438e36,d567d9b0,bdf18b09,d929329b,24a8bc91,816fd433,f80ab84a,99d214fa,5d288e3b,c2b5560f,a1791412,9c3d16ff,cabed23,736e4f85), -S(f166252a,34572146,8bf3a3d7,bdd2c67c,b0d36b02,d7a70033,add26f97,128b1637,134eea4a,42b482c7,ad625407,bb89a615,656e3a2d,232f4bbb,a33660b2,403d6f63), -S(7af860e0,27d3b1df,aa0244e2,51f9459e,488afbce,6a3aa610,e5e223b7,81ba2d93,6ad22116,415c668,7dd3f4f7,b5a00599,bd35705,951e1093,3f85f815,4d0c8af7), -S(e4ad03b7,e01c5d04,7030fe59,6e7e7960,77d9847a,e604d2c1,d801a5eb,e21c0731,c7757ea8,f57af58f,b64f3eb9,c7762bc9,544f28d,a80d760f,c46b0c9,589019e8), -S(ffb2f941,f27aa8ad,6a59ed01,24e83bb,d49f2588,a5602389,15329f6d,f77220dc,6812c00,7dd44185,fc3f0687,6f7a62d0,d31adc40,c0a1a060,c67df13b,e4cd4873), -S(42ca15ab,9f245041,ce991e19,3d696f4f,4c277df9,8cad603,8ad0772c,2da6e03,972d10d9,37e3a836,9b831b2e,347ff11,29917a59,7ef94158,7c977604,73cb849c)}, -{S(576abbcb,8b768480,882aefc,81380709,831625a4,b9de63a7,b9c3390b,9cb4c7fe,b49453e4,6e17bbae,2f1f8f9b,91c3ed04,80d5f194,33917cbb,d28b878,bc6e6c4e), -S(f9d8a157,c151181,3e085c1d,ef2958fb,df2a17b2,6b330a0b,2d512c87,69e5c14,7eacca29,26aa402f,f8b78d57,f5e02add,91087da9,d607bb41,b56a40f8,f7b19b78), -S(d31dff73,7d2d3422,7fe39dee,b2eb4bcf,dc84bd39,d6cfc4ea,ff09812,23400a80,4af55e8a,fe8e8ab1,2e2c4463,d41824df,7b53e44d,efd946ad,b6128214,4244055d), -S(9ff2bce8,a9fe6c7e,e68a8292,f0d2f4c4,8d963c47,63018a55,89a2c130,667bc861,eb138923,94aadfc9,6eca7c5,78c0fcc,bb31a40f,98d02e93,a140abd3,cdf041b3), -S(1397cd8b,aed3c601,b6eee616,243a61dc,fead22fa,da50db4c,1f9e2776,6e5bc9da,534a8e23,59316503,cae233f0,3b6ef0bf,1c7e0105,119d1a49,ee688f04,40695c66), -S(4ee38986,511024ab,5385f710,42bc3778,7cbedd0a,ad13ba24,b77f42c8,2ae935d6,cf87468,24a38404,f313965,a64c927e,4ba0b7e0,140f6b36,47e2049e,35a74e4f), -S(7614cd7f,9b5f1455,74d0d38a,370f69ca,f3050297,10af5242,e5ccf19b,187dd189,b946eded,e4b72db1,6dad876e,396e836a,875d7c9a,28a9c739,f665c741,29ab7648), -S(67fd2372,5bfb445e,5254bc42,f7dbc1a1,65bd4017,cd1019b0,8a3f96cb,7b3c7cec,b556e950,a144febd,a81dd3f2,f729ecb,fe43fc78,8658bb7d,2b9735d7,b06a920a), -S(57572b1f,1f17070e,e9b30b6b,c7168cb2,4741ec5a,b3496b1a,c06ec0f2,5f910fce,8cfe2940,3dc97084,7ab28da7,167e78fe,f2310c83,ca476a97,91ca35a9,610bc560), -S(1f111332,1e31a294,cab4df73,5a0ef333,e753c2f,7c83705c,9a5bf27,1321c4f8,8fed26de,202c92dc,5b51b13b,6e9bae41,3c7c88d7,b858dd72,a11f073b,e2945f9b), -S(23c9e313,b04eebff,15fb0625,43de6975,d19decf6,6416f4d1,855083bb,d738f882,90673370,f380ca49,e876d5f4,b6649de0,24f4454,29cf9d91,96f4f196,8a49ed99), -S(b9251407,6ef7f01e,379aafe8,8f22c156,65a85ead,f671d8c9,89602c5f,804725e7,b3a9409f,7bf973b4,aebe08e1,5ac65562,56983f89,23415e0d,eeda4f4a,c0d7c5f2), -S(1bf9deee,948b3fe1,b4345800,51c67266,8fdb7af2,99275a83,706f9716,7e38e38a,688fc563,771b7d27,f9c09953,c40cf009,a55d7329,5fae0b7d,8fc37710,729a3911), -S(34e20de5,9d00dd45,19a70b3f,2994fc4,588ca9b2,beaf6afe,4a1daae2,10692f33,7804aff0,a43f1ba0,438c05ff,8d013e3b,e5180bb7,3a969825,fc97ef52,6da1b6a8), -S(80fc119e,85e88b0c,8c84d23f,9e44e96,1c7722d8,51d4c9bf,f1824fb3,365823ef,efee941a,a60743a,28b6ffd,39762f9e,437d2b00,206e718,7fc423bf,4eff0caa), -S(89ab0f45,e3860393,f24b1845,7578fe79,b812926a,6bff3788,c8baf283,89fdbf0e,57d4fc21,42bf446f,8e4d9331,659e7673,90391fe6,62e77ee7,f7a4886c,8f440c8d), -S(1f092931,664bb98b,79d8fb4c,efb287a0,f72641fb,1cebe711,820c92e0,42f26437,59f63ca0,b8e2e959,a97b1c1d,1cfa4c02,380dc42f,db7cb5b0,995ceba1,d7e45d94), -S(95ac9f36,f447928f,344eb4e1,9ea806,717600e5,148ad222,fdd52a83,86bc3537,cdef5355,e928b1e8,225b5a53,bb976822,6fb50d1f,6c6cde20,758d5ab0,e9f28543), -S(a9ce5ddd,9941ea69,1343ea71,c85fcd73,6269826d,6eda5008,44cdd1b9,4a66044d,29504563,1fcb7590,27d904c5,4ffc325,2ce3c8a2,169f4649,907db751,2ef3ce43), -S(2edf81,45c4bcf9,62425707,ccb36a3e,7fa1fadb,4062d14d,f78771eb,f3ec15d9,dcfc961c,547548f2,73206d9e,aa0d829,a235f66c,5afbba92,68fdf9e6,abc8260b), -S(fcf5b985,c935e207,92907b93,e9976ceb,ed320a14,3cf286ad,b38540ad,b4077dee,8a0e0b4d,1ab114b1,caf7d0d,f749f219,b75acea5,6a71b3f6,aa18557b,1da85262), -S(2bd4391f,42b70803,2baf4816,54569f48,95f1434e,be6f146d,41447f45,f14581b3,dbc9937a,61f43af7,42635810,5cdfa02c,49a5186,ce67bbbd,7ced2842,19a37506), -S(eb00deae,6cf69ccb,abe6b93e,e5493e05,d22e53c1,b069a6c,4660330a,4e3bc069,18002f2f,61b08dbb,60c784b8,4c6d71d4,6b004e6a,3089a0d5,f853d659,83242d9b), -S(c7c62a5f,ce15326f,25b2fc5b,697cc7f7,26d231e9,e7e9f15f,5998b8b0,10605524,8ad4b370,ea0506f6,f25eb16a,78f87ef2,f408cd17,fa4ec63d,4ee21448,1d5286b7), -S(aa1c2baf,632673de,6f6704aa,5a76c077,be0c24b5,223de654,88d1386f,15a1a002,de4648e4,fda7db79,41efc5e8,6fec516b,c6aef164,62d6dc08,fe93ebc7,a85261f5), -S(11871161,13c3c670,e7f5366,edd22282,1f76ec98,d1a3500d,f0e483d1,e53f2666,d0042c9e,8dc1d72c,f53836f3,2c76b5b6,52fd5ec1,9e8fde42,aed1a7e0,9d242745), -S(e232a92c,9ffdabcf,24422182,34078534,6b6b79f5,983ddd57,2580c3df,e4ee4118,6c1144c7,471342d8,7a784fe1,587ef576,483f8980,bbab12f9,35aa0d84,83c1d76d), -S(1ab6237,3998ded,e50aec45,8043f830,8a7b4564,2dd3c9bb,4804f98e,a7c2e0c9,5528e158,6a23aec9,81f04b51,b90576a9,a9e7feb5,53200e51,e604898f,e55996f3), -S(3bc24bc9,cbc58de3,46644de9,b17ffa7,39a0f7d8,83eb9f52,af19eaf4,d8d52891,f71cf5b,7587c275,8014127b,f404b70b,b257bad7,f5b78d2e,c792e1d6,b2fa4493), -S(a2bf9afe,e6eec182,ef5866a,b4bdfe2e,9d045323,343aa422,8c1a13ae,fee515dd,a5ee438e,3aa35484,c5f5a1d5,43fa15d7,ff0d1c55,6571678b,a3c5694e,f93cfa1d), -S(a0b2b4f,ed0ddd23,8812806c,fccdfa9,7fb3b42a,748721ae,6477dc9b,18953133,325ee7d3,4a540d0,fc3e3935,79ba7372,905c7b17,4f12b456,b43db5c7,cb50ec66), -S(e7b9796b,5ca006d1,632f482d,7f0fe393,2cf16a5a,e104eea7,a7ea1c25,1073e879,ed476773,e6e961d0,20bdefd5,8c833e35,634a40da,1256750c,c718ef75,45575e97)}, -{S(a8565dfb,75f8eea8,ca9ca6e7,c7d18a5,bf3e437,5d1f4e87,68d5f51a,57199ac5,daa7d7c6,cb86b215,a682141f,2308d9b,4c204196,eb779f32,fcddf0a2,da194921), -S(974619cb,86016199,20f507ee,62d10295,44abdd66,456952a0,54e945bd,7890250f,6c8d8bc8,21da8234,1ffd0cf0,548be1dc,a1bb7e1f,47354dc8,3e5d96c8,2c9676f3), -S(24bbdc24,1396b6e1,75f23a6,4bfb41fe,f8329b80,d306586a,ecb69e41,2a2014b8,aa6448ec,f00a0710,27b46f09,d696642b,9274ce3a,11a3e986,e84536e3,7fd7b2f8), -S(eed9a6b4,68004486,e3bd388d,591d3b65,2f35a3f1,9401e5de,81a86f5e,b7cd972c,c81f9aaa,d7300671,b3dbdd73,a095c79a,d73ffbd5,9f845eed,9fe3a57f,a41e9468), -S(5260e0f6,fdc6858a,8d519d3f,6c71929e,36979b65,431a6f3a,a7507797,e54654e2,5af860e5,fbcf9676,bb00c329,d3e2e058,efc860e5,cb9006ad,224caa32,9fd49f07), -S(11e53f67,d844c511,b8118f28,de6ed9b8,66b70bf,214d4d1,ed79adfc,18f7d6bb,20dd984d,7b9eb626,77e411da,2e823045,685a4bc5,2a3f4e5a,3aedea95,1060b330), -S(98c9f3f6,81e220e6,d4bba711,fa8b212a,dcc21bc4,8219b813,eabdfac5,70e6fffe,bd0890be,d9cf4ec9,44f6abb1,56250329,a37d2cc4,64c931ba,8606c2ce,55127aa2), -S(f644f4f0,43d7713,ba4380d8,26ad0f3f,44106352,142fef13,7c6e05ce,5e9f1571,3192280b,f3971223,c00ed336,94779866,536020b6,79ba8cb5,c4f9c515,69d2f97d), -S(334ab869,32c4097c,8d8d8a23,d529b079,6a759d47,a907b047,548e735,5b3b766b,18f11736,d54c9d00,89149b07,35f5a9de,b15d9c,cde4ee06,155a4f3f,de98a7bb), -S(983542dc,61b43ee5,c4a7f36f,22da008e,832d4eac,6791d838,1a095d0e,6d8a14b5,cd225f2c,334d1ba9,94b0a681,d6be7696,16bfb2a2,426e9939,d2238cd4,43bebd02), -S(dbbac008,1b678270,4a0fcef0,73683822,a3d4107,d7f1a71b,41497da2,9cc942a0,cd25ef66,36f21a8b,532371ae,b91b67a,deea5797,983dc36f,54aed202,d9845515), -S(477949e6,9ed28a74,879bc8cc,660696cb,115e6392,5a63817b,60e5187f,1f77f3be,dd8ca490,fb8e3bc1,44f5fe9f,aa41ce73,56a1dce1,cc8e11c3,ca5725e,d1b764ae), -S(7616b9e8,b451d4e2,e4826586,9bfad6c8,ddbf5fd2,2342c6c8,42d6bbe0,398f94a2,4e3bb1a9,76efd345,3c4474ad,e6a494f6,4f97c6dc,c98cf68,72bca24b,dd9e946f), -S(b87fb86f,6ec4ad7d,5bec3bee,e8d68618,c8e4906d,1c584368,ec819f2f,871ca8c3,c64723c0,aa587911,4dda9c75,493f739b,e8c2221b,b2e75ee5,b25def54,a1d40c2f), -S(56ea4572,61a6ccfb,46fced99,1258b31e,8573a488,aa53b7ad,65333452,b06d41c4,d8529601,4145e12e,a72ae4d1,5ae6e5f6,9cc88ba1,4d79467a,3df3bfef,33d84290), -S(e4c6540a,19682e0d,e1f1258a,103037a0,af4df5ad,f27cbb7c,9e3ce67d,e23e13d8,a31e1b08,4bdb5728,36e53d93,1de035,c90b1efe,b5343b23,cac0e7a2,bf5b3868), -S(1902cf3b,90fae93,1855d758,24995b03,e1604861,199853c6,ece84903,c8bd67de,3b3d41e3,a2dd4c28,16d492c3,e6c53c83,e5203c7c,a8100d41,24cbdcd0,e12fe222), -S(6519f4d3,b5d731fe,eada6806,727623a4,daf924d9,b6337a51,56096ec4,16ab42d4,62e2c1ea,afa990bd,6dd91675,e3b2d1e2,acb2fee8,e56ec30b,eb25bdce,2d3ad30e), -S(e1128682,519b965e,a933f197,eb0997a0,16114459,4c0915cc,9c55ea4,a30c1ad1,cb1370ba,f8707c78,84817ee2,8227da3b,7b7c97c8,266af491,e0d52bc4,ea0f9614), -S(4366960c,6ff595d4,143d4cd4,f0f0df2d,3bf864d5,73790abc,23419c7d,6ed9201b,623faab8,2caebb5a,b4c42bf6,b2a686cd,4640cde1,a95a65a1,f8d32836,9e5ee0cb), -S(5acdf691,3c1e283,c1220355,6efd99c5,d347ef69,bda1d040,44cbf0d1,ae41b16a,1bca567a,71698c35,e35e031c,e8a98dd,e34270d1,4e2e2439,9276a7c3,6a1f35df), -S(807ecc04,81aae374,1efec46c,8c6c194b,faa0607c,cf5b7cda,fc270fb5,f5b416bd,cc60be6a,6736dd94,848fbb05,375f6459,d556866d,165a2c16,41984411,dda33fc3), -S(29c470bd,97737284,765adcaa,68a98af7,5e6c275f,fa4fcd5d,6c71d428,bd3bfd79,b19ab40f,33c15201,41fed31f,681f176,4a464373,23283677,a40b4018,99a6eec0), -S(41a6d6f9,40bb8abd,9e8748,dcfd23f0,5333eafc,4ce311a3,161440a6,619efabb,b2a3702e,900788cd,bf35204,27e0facd,b090804,62f65418,89a3c34f,ae2cc008), -S(d5f5096d,776ffdb,f694b9c5,c9a9ae0,ab5897ff,c5ca3320,82cb2a2b,8afcfe89,6461e24e,28560d11,336244da,2038e13,c69ed5,a7a435a6,d07a1d72,be43daa0), -S(f65a00d9,5707ce6c,6bd55e8b,4b0ef381,1eca65b2,9845433,d7b307e,518ea724,7ae079e,9aecabf0,4ec5210a,b85328f7,e60c8ff7,3deb037b,c8e6e1d3,34774734), -S(346cff42,23c9ed2d,a1082d46,eeaff341,f7866e72,d95561b9,678def2d,9f7cd187,f97f85d8,92002750,11efcc9e,f8ff58e4,894f105f,b94e7390,7e185806,575698b3), -S(d0e3cdff,a47417f3,86f64a2,4029e3fd,9bc7a464,6e839bf9,232a0d50,349ecaac,5bdbecfa,2a2b35d3,ce2e9837,222535c1,57ec5bda,5fd70186,1920803d,a279989e), -S(f6bbbd77,b8dba8fd,704a3f02,1bc418c0,f8524c49,ccfcd14d,fcbf7f04,c9a18d,38184001,f39b257b,6755a132,86bdfd92,1a8ff771,fdd5530d,48eb8227,ea70be1), -S(6717bbd0,f019990a,c01a2996,e34f0912,9bf60a3a,71d8124e,fd86c777,9cfad879,9581f790,a16825d8,f44f316f,db3f0bde,108643cc,b390bdc0,75f3dccb,6520029f), -S(417c765,ca91a120,2b07459e,3713d5e1,bbcdfa82,bbc26cc9,279fa2d2,59251fa2,8d281a2a,ed38a80a,cb697989,9839d7c5,265b4e78,8a9e1176,66cfb6fc,4143a935), -S(e2f349b0,f89c69bd,3c8cf2a4,10730dc5,8e0beed4,7048c58c,15f9ffc2,508d2cc2,e014d0d7,f07d8dc8,7e79f513,89fdea45,bdcbb417,1f63424c,81cb8426,1f2b3be0)}, -{S(aceb57c9,187a5202,118c4dbe,573906e1,646b0325,781c1352,574ed15,e02b87b,68ece7f4,4037ff05,d4b89120,d90f08c6,f0499fee,d4e9e02a,a2e68bcc,2d7b70a), -S(365e555e,de9130af,99f996b2,106229c,c36c1ea5,8b065cb5,38af3a5d,2cec1145,81fc523c,b4b97bd3,cccce1e1,d1980769,fbc25a9f,a403adba,8e7e8074,13c87f9c), -S(d0a3812c,b9244d7b,c1f5b652,adbb0df,22d15d41,b1724071,fd297d00,bc8cbb01,f8d7650e,fda2be30,24ded196,eb3baf7f,351d2013,2479640,16ee4c6,b469951), -S(8f4ce1e2,a51c0ebf,f5e34cb1,c6aedd87,85e415dc,e7307119,143bbe9a,3e7fc632,617009a,ee7d4d81,1ba2bf14,d1647911,bf1a3bbe,cba8dfda,9030ead3,803fc217), -S(ea23d837,54cb2e9f,9b884ef,f4d1a708,bc1826c6,59fea53b,f52c51b4,9fe0e21b,7e8c691b,cfc3b7e,56a7699c,4f56a11a,fca5710d,963d602b,b102e1c5,b36dc3f7), -S(e3c970b2,c764c9f4,ad8bdc15,cf995690,807f5d09,4a849787,9d278d18,eed6ceea,aad8c7d7,13ce5439,b9125d9e,c14b5d8a,1c694cfc,f84e6922,b7e58df1,4ab8a34), -S(8ade30a,94b236b9,9597be14,bd421130,b6843895,a85f3613,efcfa0ce,9781a96e,78e4bf57,974cfc0f,c310330e,6aa47de8,2b0f5009,5a703fa,50093d5b,a8e8f0ef), -S(fa5f1cd3,4427d71a,de7e79b2,b0a17ba9,66d05324,1f9996e,be8143c1,9186d24a,3481bd18,2319ddf8,f344e4b0,196b3ddb,10deef4,d8d75c0e,49fc5fe4,cbd6e1fc), -S(8b88b79e,8cd28dc8,58e3f1a6,155146b9,af1e3697,d57b7435,c649f6c3,bf8574ca,e736106c,8ffb9bf4,d83d79f2,4faf8fe2,ba5dc258,e4ae1b1b,b58a1a7e,4922c95b), -S(12078a5,5c46d721,96a148d2,fdf6505b,d059e423,c5d5295e,facc2b82,aec51f5d,66a4332d,cd265085,add9a141,2fae2562,17441d7,dd9596ad,46309a0d,bfb4e55e), -S(841523ef,29f5bffa,b31a526d,bf74b16b,fac3a3aa,391f7404,6675cba8,7808c171,7a3fc3f5,bac300b5,7ef843df,e334c995,cf66de11,2283fdfc,767cb57e,e7e7329c), -S(c8831ece,f4545c2b,387378b4,f88173d3,f1cc7db9,d064774d,60394f0a,ecaf5af6,f32f1a48,bb802757,34e66cbe,58a3ed3f,adf28dd9,374a42a,a824a095,6701322a), -S(30001ff3,7b1b1691,9a135a31,287e3a3d,383ef3ca,94748e33,a52c146,586dc4b9,9d71b25d,6fc35db7,26b58d1f,642dabb,46dfa64d,e0ec2a12,c53c414a,9dd2574b), -S(a17d3621,74d3c789,c4e00888,fd4b0f4e,ea3929cf,afea9e9f,7439901e,d6b0fe44,2bcf09ef,2d374194,510fc057,dc973fe1,bb687428,91e9056d,a5b4df7a,de79bf), -S(4725e2cb,19f95359,2da72565,d8405e09,92a64299,9ad74ed5,b41f5d24,44cb6b0f,be23fa82,7aec3121,7b90028d,b61d1092,764b2824,9f3fa0ef,91929db9,b2e0246b), -S(67c560dd,74c276c4,df3efbe3,b95dca4e,a56c4563,cc7ae225,ebea90e0,f5e212fa,2c9e3120,d52ef31d,7e9e36d6,eafbcdbf,ed8a28c6,7edefb94,1df7f38b,cb05c160), -S(8468da98,7b33b79b,e08da5fd,57cee298,ef86f624,3bb975da,2f4261e8,f7531d92,455d8a8e,b4f45693,2e8b6f77,ddefe070,591dd37f,d6ad3a27,5774055b,8a63e650), -S(3416d4bb,78de7570,b1e9e912,83a3e8fc,be6524d7,4463dee6,82e84e52,72c0953c,94e55458,2c17fffd,321364c9,16658093,986b56,f88b4818,129e19c8,ce685dcc), -S(5c66928c,a39a6e22,672c1dba,8bb6331b,41a7f43c,a72276a6,afd3e209,6416a9c5,181cdfc4,15e7d6a3,c24be94b,7fe328cc,ab624c0d,dfabb1b8,f9a73b56,cdfe1b28), -S(971f7a13,210680a3,ff6a12ad,17481a63,ef624d0c,e4121166,7e63aaf7,9cafce,5de2fd1b,3149e321,2980c7d,88a49018,26f83f18,7438061e,9bdb8d33,6a4b08f6), -S(650277a7,9ae7682d,c5f3526b,8411342e,b48277a4,9876caa7,61ec6815,9a1f13c3,a903255,fcf09808,cd97d92a,26dbd2e4,7a29571f,ae91107a,7cb6f0cc,3aea1985), -S(76a79cc9,7fb80ab3,e8d31e5a,d11f5ce4,74696d23,f1ee7aab,3928848b,556f483e,1779bc5d,c763d1ef,7611b402,4583f07d,c7dc9c96,7afcf83f,e6b6ee42,da75972e), -S(6e0b4015,474fe250,d372400f,13efa0b,70c4e8df,816c0e8b,8d27a7,a8168d54,f01dafc8,8178dcf7,15f8fcc2,e7163137,9e1dd4cb,6c88cfbd,e9a051f,ad204c3f), -S(ee5dd472,b5efeba9,d0e354dc,21228d22,40a69088,842d00dd,6b6358e4,309d1f5b,bce93ac,3fd4a098,9e74448f,5832643a,a2a172f2,eff1e2c6,c61ea99,cc6e7cdc), -S(df99a925,ef2e9f9e,57208fe6,5373ff94,876b1448,368dd453,436c59d0,f2a857e2,88dcfe81,4397f990,56f92a27,143c902a,2a6a66f7,f7e9652e,e0b16f13,33252a1e), -S(9186f095,43dc64db,ad582561,cab96a38,89be54ad,e1cdb27d,674af836,22b5d284,71ae31d5,a73b29f,54af1aa3,2d8e541b,14f7cebc,9279ac26,c846d466,aa975e20), -S(645da454,63357bfb,61b5b932,1897a73b,87af6077,81487bc8,af1a66ba,49bc5e37,4b925aab,aa7bbc19,5963025e,f1896cb5,b6463242,cd8a35f3,b1b404b0,7faf8e94), -S(5cd9a6c4,e9d372db,90a65f11,1f1a1b5,f28bc3b8,3d05f599,39979c91,5277eab1,c147420f,7dfc4ef4,d7d1f08c,1c523771,86a8d7a7,10cd7017,82b97c55,63287aa8), -S(4fd699b1,2c720ccd,7b977e5b,dc622671,18ac3028,bd635b26,fce648cf,335cacbb,3936f10c,aee5f51,26b86240,3249e1d3,5566714d,17ddc19e,cc4d1056,71e523f6), -S(b3fa0545,83510d6b,91226711,4bac7f4,ba4ae5fb,baad7230,3003efcc,4c3c18e1,57a3db8a,6cbf0a94,845e7d67,f9b01902,55aa5b66,ef31abd,34ee0410,ed55d0e0), -S(fd73c052,b194c6c6,dd46aca9,d640981a,ec796009,17a565eb,e77fd534,649a2115,9df8973e,37e877bb,fdf5454f,d9082926,fb09fea9,d162bde0,fb635483,59458f55), -S(2982dbbc,5f366c9f,78e29ebb,ecb1bb22,3deb5c4e,e638b458,3bd3a9af,3149f8ef,59e4a416,5099ddf5,4605acc6,384a4362,f6a2466b,ed1c127b,a918d94e,e93859e7)}, -{S(8aff982a,fbe09f67,6d6e0f49,e2b68f88,8f20dd2e,6387b420,8157ab24,d19027ed,f2350ea9,d00fd861,41259f03,b51b5326,6ce05a34,74508bd4,31ca74e1,366eaf92), -S(27ff285b,1e14961d,a042bd31,56aa44af,5e73717d,fa413a47,b300f358,e1960dd0,8b578851,264a8fea,2e29bbcb,cb9c90e4,93e8c731,983f4bba,65381e88,bc83a8a7), -S(fc6acf61,4a214859,1418ab5e,e0f0274a,309a8248,2cf01f73,db8a9790,825486df,190b9c0d,46953d99,c9de2bdc,bcc15d23,ee90485c,c4c152d8,e28322e5,4c927d54), -S(743bcc6,ac86b0be,a25cce81,1fdcfc13,73f23926,e3116fc8,9415b8c0,4c1983ac,f3df10fd,4afbd3b2,dc0678c9,102150e6,3d005680,6a5e45fe,c95ea495,9f2b8555), -S(bb165428,2c13362b,b1e017e6,6402613e,f82bbe22,9429f29c,6a1a522e,4956d67c,ec542c4f,7fbf3c6c,32e71aaa,86e3e4e7,e52b0d43,98589e15,1f17417a,40b31b07), -S(b3f74ed2,5a7fd474,5820a2f6,221349aa,e41af762,25c2b706,160a463d,1d59e7bc,a9af9d2d,89dcdfe0,21ca46e8,5f09bdb5,197c8f23,bc56d705,851974da,1608dad2), -S(20c0914e,f88902a8,6af0ff68,a08f96ea,25f15ea6,b1128900,120028a1,1049a77a,339567f2,71a1f1c7,16eb1d56,2f009537,68ff4cd3,9a81c6d9,6359d2f5,5d04db9c), -S(a3555aea,2e96f05,d25a145e,4ad0d2f7,fb453974,8c4a3097,a703c0f5,404a0e7a,ee236b76,8fa04380,b0448beb,d2589665,e43299ee,b9fc78fe,5a64db69,ac92b7df), -S(37191a66,1d2a7bd,c96a0767,ce47d97d,7acfb8c0,ce251e9a,1421e2d6,29230c2b,57093393,4783afd7,2df6524e,871c8e67,ff2f48c9,c73e2054,fb219cf,d3c2a68c), -S(1a2f5b6c,5fbe300,8b01407a,b0b28c3d,c823cca9,b4c71a1e,4fc814f1,e186e062,b2f1c632,a9d92a4c,82d31a55,f4fd50bd,d53ee99a,2e1452a4,e43e5ac4,b8cbb7c6), -S(2976575c,c5e70e47,cd9c10e1,32a593dd,12b65215,38613cb7,22390022,73fb41d0,c3f0b08d,a2a3a046,d87dcb13,38c35824,1a8b9959,e2567543,852dcf73,c4f5cba2), -S(bca28e75,5cd6ab74,85884b30,ef399f,44188695,fe9c4143,6016bdec,25d502f7,b67538d4,a571e935,cbefe237,c5a01f77,4ade337c,fec9f95f,3e9cf042,f0dbab6c), -S(3dfe1718,beafee83,b858048d,25d46ee6,7741d3bc,bec1e52d,3ce308cf,738b715,8499a8b3,a0c7c599,f62f056a,a8364494,ec6e0198,2c47bbf8,7e2df591,de0ff537), -S(bde6252e,a9e4823f,36bd1737,ce188fae,be4a271,9984c9e6,76f9f4ff,d070c1c1,2e5db82d,e02a1fe1,39d903,7e7adeef,12d40366,de0eb164,c04b2ef4,b1e849b6), -S(2c74b766,eebac93c,479fc0bd,78a3805,de50be2d,a6ad70c6,9048e43e,c91343af,ab7a929d,588ff993,55094f83,6e7b3b58,c6381bfb,b284f9bf,7dc44cc2,67cc741c), -S(f0e084a7,af9abfaf,b6ebf3c5,b526d545,b8b1cf5e,8e09a06c,3670aa37,6af83a3d,6bb279db,abdb2b2d,fcc97510,2b075dfe,b42d9e6a,5a8af760,f4b63788,c315f8dc), -S(715aa28f,4e52fc26,a2f4b9f,391894b0,6adc3b69,b508827b,4732396f,5eb7edb5,c5d0d68b,3a8c6532,2f6303ab,99b6c48a,88572c4c,56c780d1,d51d2441,86ba110c), -S(8f980e69,3511ec3,cca89b2c,362835bd,24d9c8a6,97deff86,5540f7c2,b0bacf8b,2d5e8470,f2041ca6,f158ac83,e92a2345,4059492f,af27ada2,92bbe51a,d67ee5aa), -S(6823a4e9,d80838b2,750dada3,cc31f59f,3cc9d6c8,3f33aa5,38d949aa,c4d6d657,e087127a,3ddc19cb,e4088a2a,6df61863,e8e81cf5,c5cea4a8,8cd2ab51,bfbcba8d), -S(8c9af14b,11add28a,818f85f3,276d1d7a,1e3478f4,23e74b72,caaf2440,24558538,a7c17174,da1eed2,7eeb7b6,c1d93e4e,9e4515c5,3cd888d5,e4527cdb,94a64fb1), -S(5fadb7c4,74b13592,a1a27f76,b7c2011a,102b66a0,c6ffbc02,a7306e1b,a9ccf49c,7bf61c4f,134f8b4,7a5f90a1,938918a1,4d151f2c,7f1c4bea,cb8c4773,cf11609d), -S(79a21b82,9325fbe5,c01ac979,8b89cc47,379eac4b,682fd747,47e0c04b,879b404d,abfa4d5c,7ff916c4,9f489c12,5235bd9d,a0395b6b,84d6699f,c96f9c0a,5a4cab2b), -S(b213d11d,e4b5601a,5f10827e,d39a7825,adc36bc0,1130a055,cf8b3e8e,fc96d10b,27c0e5b7,a739fcd0,5eb73321,3fd1bbb7,873de0a1,2b92cbc,21de57c6,2bc812b1), -S(299ef8e,e131f523,72949d7e,fc2f0f7f,9965e69b,56725b55,4d513435,ac8b0b3e,8ba93fa0,2a4d97b3,54d47c10,d5d791c5,f724b68,4f501eda,1931e563,2c6faf06), -S(5143ab76,43a21de7,7ffd0f3b,c4746fb0,589be22d,9d9ca2fb,89403a39,86d1cd37,20991000,a7c01e4b,26d9236a,45568bbd,91c968d6,c87dbe05,15063af,d8db5a03), -S(738ce787,49783066,923ceec9,a841d60b,56855e09,93e67cb9,9d52a0ca,7a64b5b2,aba44aa,272945fc,5eee0330,976b659a,a6455dde,feb5c894,cd274414,71610384), -S(6bb9bbe0,4c3dbaf,6c60adcf,5ec5fa59,29cdb04b,14633c10,5dfca2c,183e1d97,b7dac59b,5c35c3cc,15521da5,89c0d333,9dac05c6,614acaf1,d8b9e834,8e02c3c9), -S(f325eeb8,49a32b2a,fb19491d,8c3c112f,a7ca3443,438c8c19,99bdf791,6981472a,169df94,a26f26b1,e5aaf810,7a148faa,17742c3,10cac320,6daa69,f8aad67b), -S(d279bc0c,f7f58a85,b5abbe25,936d5088,4d8ae8a4,b415ea30,2c0f1133,de98603c,1e69875e,2e38f9af,222e03b1,6c833bd1,12bc10f8,1724da7e,bc780e6f,5228fd17), -S(224d079c,750eb1b4,2d70aa25,5fa0c3fd,c2d07c1d,ae4d6cb1,17c1e61c,5ec1c6b3,e54dc4fa,b0e05362,60d27fa7,ba53c37c,a37ce30e,617365dd,1c58a59d,2c93ed00), -S(f4741ca2,b3de5414,49426531,d546272d,ab8fc55d,8f65eb3d,5ea780a,d25cb53b,3b7290bf,dda0d0f,e3704f27,d8537063,f2fe9571,4a0791a3,e1a25865,96a5b0b1), -S(e931258e,8eb5559c,6d697272,8a704c17,b775a26,5b4527d4,a4d4d742,bbfd71fa,4e1ccc9,b3c0211f,17a14be9,636ab4bf,4c6b931e,44a1ca0c,c2642f2b,e8b2c928)}, -{S(fa01dd32,fada2843,c51845e6,3cdc1b76,79dee47b,d2f4b767,5133aa5e,62029057,6ea6596a,b0ea0201,b6c8bbbc,e9d07fd0,8040e1fa,198c8767,67ab6055,34a33), -S(97ec9d33,a9d88115,471619b5,3fc58a08,e6997662,7a28afc0,b75b2f49,55eba300,92ad1d6a,f8a0a100,27d9ba90,4f7fea6a,571f3c32,53393a7c,79abb0cf,9a558390), -S(ef364ba7,626d72a6,87bc9776,3f2c0833,50640bec,6ff4d80,9dabcf2,9ea9145c,7f8d7c48,1bd80ff4,8eccfa9d,2de5eeb9,800cb98,c02da539,3b3d6c83,8fe4a2ff), -S(45961303,a778b47a,89109231,3242304,30a17859,7d940e9f,fc2f25bd,1be61c00,5fa356b6,daad2b1d,7bb19cce,b9148d31,58d2651a,b4b436c0,b99193f6,61cb037d), -S(8aa677f4,d73c0725,e2163e5d,ed3dc312,7ad5ee29,f9bad8b8,5ab8f50d,ec6d77e9,1fcb9da0,d3fb9bc3,3a45bcdc,50aa2ba1,16c2b05e,836b539c,863163c7,2436c334), -S(8c6b2873,33082bf5,a3597a26,7cc14696,2b689f20,59caf1d9,35972c98,9b14c86b,aa86d282,a1107f8e,21307e0,2ad1420a,a4061fea,3e3dd6f5,9b5d6900,6bf4827c), -S(46c963f0,3bdbf433,cbd60858,5a4d659e,9815c286,9f684eaa,cd879d66,ceed05ed,be2a8d60,636c5b80,e443b13a,9e21c91e,90a9e781,1c35101a,dfd61a49,88193e86), -S(cdbe43bc,582f3936,314a88f9,fa21b29d,f4b5acf5,96cdac3,4667e9c4,b02b926b,8f2a5b62,4f20b20d,cce97348,d73d5653,8651dd41,dfedd476,8792fa61,1bac16fa), -S(6f9c5a84,1ffededc,ec45dc63,7ad15aea,207116aa,a3036ea,ddfb0656,1dfd074d,ddf1c22f,9168232d,cf9c36a5,dfb7835e,62d28405,bd32ec15,5e3ddb3e,df834088), -S(42000663,3223b99,e15a2a65,bd95b229,820abee9,5ba5be39,6f8879b7,3f421e7b,9f3f3d66,40de91bf,c6872619,87487226,57e60a4,3ac633cc,48f684c0,cf42696b), -S(f02335b9,9cb524b7,45fa9167,41da4259,f70279d8,efe851ab,f5b0b8a5,32a087ff,e1bc6767,ba068b22,cb7389e1,36805da5,c30ca62a,e59b92f5,48e4dd1d,5327cfbc), -S(5bbda2dc,cf8154e8,28ed49b1,2fdabc3e,eb8c3f9,d0da5878,77611ff4,49d72e7c,312377c3,6277addb,d5b044e,fe136626,d5f7e7e7,a73cfc4b,9751e8ec,e4f77084), -S(5cd5cb83,ba2f225d,1ef4faf6,22e226e1,eaa85a5e,99721d3,82aae23a,f9dff565,254f58ba,9c49244a,4178a067,b0e4bf6f,dd7f3e15,65e21637,bc41f9f3,55045908), -S(3b20ebc6,b453aa16,e5b61381,1d81ca1,f87dce6d,b54ba85b,d8578ee3,23bff228,8c9d3054,56627a,7313505b,4aa5140d,9fc40d83,bcc298a6,43842f04,70a335f4), -S(cd531999,cf33db75,df4430c6,bbcf32d0,642be18,5736d79b,f2947989,e52c8da8,c7e99c34,2a5c1112,400edc69,f58246e3,d3cebbef,2c43ff47,7520b027,e2aa7d78), -S(40b3856b,273bd2a5,145b70f,d16a2972,e488b33a,f3719143,db7bc567,26ff23c4,d8bf895f,71d96e6e,20d523dd,1256bd56,44e11442,c4757d74,f116ae44,69dc9b21), -S(1a0cf029,2d7cce75,32b74bae,acec6864,9e682788,3cef4bbd,c8b24fdb,53e885a5,32c87d92,6f969f69,7989837d,d8ec8ef1,c284d9db,2a86ecd3,5bbb6772,dea06692), -S(7fd5d251,93dd6c17,8d0be92c,342f94a3,c92c061,27998f4d,54f7dfb6,1326fefa,ea7d0755,e0a804bb,8b7ac8f2,dbe1dd7f,9ccd36ca,2fa94365,631ae455,5d080075), -S(51820145,6c07fa3e,70d7b24a,7754b11,e42828e9,c1b96b0f,fd79bead,2f44050e,126f5526,1a55b724,7d08c868,366d697f,a6898c66,d14094f3,44b0a6b3,613d043c), -S(86f2c87d,46038770,3be5ddc6,c2ba1ccc,7dfdd56c,a9986663,882f85da,345886da,ed34fc59,4b66f7e,f06f54de,84f3c7f6,ea1d877b,bbfc4185,3df800f2,fa805027), -S(7f7d8a69,5b86ca13,d6a0ba07,99e60cbe,f5c4e1f4,c74a62bb,93d94d4f,8c1f296e,44a14061,b2c741c4,6a52639e,9bf08776,5db5d496,92bb6d1b,e97f9ced,a89953e7), -S(ec61e956,83714c55,1b72ed5f,c5b09663,6dbdea9a,64d13ef8,c9cf0c55,89da5ae4,39a6e38f,9f7927cf,ffcd0847,df91e856,4188bf58,276bb4df,3721335a,5357c77a), -S(e5906c85,4a75bee9,322d70be,a5d31c76,31a59389,2f479bf,8dc11bef,9ad5101c,125b3a58,8c6c1c5f,288402f4,3ce74ec5,fe9c2dd3,3f3605df,9ab41210,32641524), -S(6c9faca8,b1b435b9,213fde17,ce967f05,46e6f27a,cf0e131,8496bcfd,d856b092,a04ac67d,4bb07624,6b59df97,2fbe2c1f,bb04be99,e269d33f,ccc81f76,3f567577), -S(61031a0c,730cf279,d929b4f,5608f16e,6b1b1440,c04e5a9,fa300ff8,27303def,acc4d732,afb4730e,39a10c0f,5ae2cee9,5099be03,bf5612ac,391900fd,b51238c2), -S(e58fa07f,ebc3aa4c,61ff4fe3,bfc8d04d,48a1e3c9,935317e1,83d537f9,7f35826b,d2402844,7e63c3e0,be630190,8139a75e,2e1a2b22,b05ce52b,e453ccf7,7c35f1fa), -S(4d4d2982,b45a339,1720af,cf6b92df,2c201d38,5b9b6c3a,8fc53b4f,fd3bfdd1,d72650fb,d130482d,116524fa,e2b3dd71,c68b4bbd,54fc55a8,f9824578,cff67503), -S(9adeb6f9,6ffcbb56,f171919c,a8a64c70,9b8ae835,828bd573,b7a1bbc1,3efb0360,6d920a2e,d2e3f41b,4820d838,ca342b66,9af35a7f,7b6d09fd,b1ba4298,9abe027c), -S(64ba9514,d8680f6c,dd66895d,9c5ad45f,6e29,33506f8e,d7be9770,822aa9b8,7ed8c0dd,59bce424,481f88d7,3e641b61,a010e490,97cf84ca,16c2e045,49e9c6ca), -S(9e4ac64d,9ca58a04,46ca18bf,c1700f2c,16937ef9,c82e8b55,9ccbd751,2a0c0222,315ba2e2,601b18b2,cf7f1720,9c4cff2f,e39dfcf0,c2546fb1,e930898b,5b023274), -S(f13a99e5,8dc72fcb,c62a492,d2850704,621ddf48,f1f433e6,9a9814c4,17d4b84a,cc3d3732,f0f4166a,55946e32,e1c01f91,491c82b8,ef0d269d,7a66f039,ac02dfae), -S(fd6451fb,84cfb18d,3ef0acf8,56c4ef4d,553c562,f7ae4d2a,303f2ea3,3e8f62bb,18ba314d,4e78ea87,490185a3,e43cbb33,5d54b6d,2dff17c0,2f526f78,ecd3f31e)}, -{S(f1a749e,6cab100e,2aeef8ee,6a654551,c0ff906e,e7d11d77,f390955e,9d29d783,a60f7295,3c8c3bf7,f1dc1358,e39baf76,3dba22a0,1ce7917e,aeabd996,e21e845b), -S(e8c45020,4c9d9ad,f7878aa4,184a1576,d4c65d5a,c1c4d494,ff427e86,8b42ec1e,aabff02d,8a715c2c,34414b27,808882c3,f656389c,71c26d6b,d7ac8013,83f4c57c), -S(c1febd79,1784fea9,bf378237,a05522de,1081df6c,27d22ea2,aad805dc,7c2f1c4c,c38782e9,fcc1004e,aa677f79,536aa069,7dd9002d,ac16936a,1f0b8736,8734174e), -S(91925564,4d9bdf2d,4522825b,5758b3f0,4d32da73,3a4e772,bfe3eb2c,9909f4ef,2568e18c,1a0448ab,d038ae62,a652d152,4bdec1c1,a0293695,9772bb65,d78450af), -S(25bb4202,9880c39,f5bde432,c1fa357c,7f4867f,6fee48b9,24ecc824,5e1a5253,5d43db2,64c23715,b4b0eeae,63127cf6,9b4bc79e,f96ea8cc,d17cb53c,c3ac0fc5), -S(2597e080,e772d36f,df500782,5f92f797,c61c72c7,8d801dd1,3deb1bfb,9e91b12a,fd5918b8,938ded17,a458d0ae,559c552f,bd45feb2,5b4f59a8,f5b735cb,bdab92c1), -S(70231b28,f578dc12,9f8ac54d,fd4e3577,73d0fcbf,65be0dcd,51132882,5a36e7e1,d12aaf89,4dff3e42,405a4140,58524e30,b7c6c4a1,83763268,6852acff,83d2b7cb), -S(f8ddfd5e,5f3b46a1,ab363169,12b74c97,b0bd654d,87824040,bf6d2cad,b4fcbf95,931fc58f,5b429636,5e080d5a,8fb35ba0,f92104d3,891d6584,8d24c0f7,fc95bda3), -S(a033f432,670a382c,57e2408d,3bdcd2a6,6758e63d,77574598,6b123e4,d927bf10,83b52f69,d79e7445,b6e33545,c23f16fd,52691151,96ee60d6,2ecf6de5,b2961a0c), -S(8e77f9ed,9a643f3c,bf197b09,80f92860,f37d8b83,93633230,6c902c38,3bb7f96d,71b4da9f,f736f9f1,f8c3c099,c34c1bc4,30bb5d26,3c861e2c,726fe891,cdf7d1ce), -S(f34153e2,29934c71,5d895102,778425f5,e92f4ee5,b96d1333,df207e62,6761b328,954584f1,64c8f35f,2c4e0188,76186ceb,3e91523a,5e8ac03,d5998253,49b7b8ac), -S(e133aa94,c0252f05,379b5bd7,75ba3f1f,92de2876,68613613,28946904,11b3ed52,40363801,613423b7,cc6c0cc5,af3641f4,dc2a7ac4,48b178ae,d1393605,103bd6dc), -S(28119c6f,a57d02ac,856edb00,f594c7be,22772b0d,700ad14,713affe5,7e385b5c,969b6cb2,8ef483a0,db4a96bb,92e2d332,6e6d86a1,73bc3d5,831bcbf2,5efc437d), -S(8c728d65,8b78d96,44003708,dadb48b,65dcf6f,6d9412c0,e31cce3d,b5384d00,bb3cf660,9908467d,285f1c7f,40f4f18,ca618093,92633beb,b4ce30c4,72680662), -S(477321b6,1fd5b4ef,3acd1e8d,8432ef5d,e70576ee,6b8490e6,839f1985,dec96490,88008466,2244e3f9,7d2ded5d,2193c70e,2d72c67b,9b7cd70e,9f14cb05,70306bee), -S(ebedd345,ccdd0e04,4bd3d4d7,e1f1cb6b,ec06ad10,5ec2cec8,821580f5,d08a63d4,4278bfb0,88e4ff81,a3fe15bb,e01be36,40450f85,885da0ae,e15c6b9f,e78ad14a), -S(f4795df9,41b315e2,24a98dac,d9149ff2,8b9a7bf,e758a1f3,5cb6336e,8e1f9814,6982bc20,285c27d8,12c5c648,d0635c7,fdab85e6,fc6905d8,65da387e,596da791), -S(65a5964e,ea76e30c,74c472bd,3ddd5169,11dcfb3e,1f2d7ff2,9661e254,4a38ea30,a7c394af,80ebbd32,e442271f,b061bb42,a7b1758f,44d7d952,89152fa2,a88fe3f9), -S(f3d10725,da6b6c76,6da6fb5b,969ba7c6,3e33b4f2,d062a446,4ffb20bc,dea2d376,4d65ff69,64518942,bc3142a6,2148137,7bb609dd,6545bc26,9678ea19,62812ddb), -S(f5fe0f35,cde00589,301584a2,f4f5b1e9,3977082e,9c9bd50d,7c2c672b,ef05cc9f,1b49ac82,486e6344,dea32ca3,c96cd5c1,446ac2fb,2a658a42,50425f32,e8d72e94), -S(fce17cd4,d9519a53,f0a100f,ca54d1f9,fa87eded,98a12654,769c95be,151e33c3,40d342ef,83a4d715,bd13df0,f21197c6,e189681b,efa0d925,248733f,5ee07b8), -S(fd5d90d4,a97c1d1c,4fe18a10,6808f46,f6ea4422,c4408860,c2256b66,618af8e0,7ffc76c3,539bdec8,f59a9a7b,b36fd534,99306cf3,2dd1fe43,a2db5b59,af2f7e3b), -S(1c71f824,1b147abd,9e3c1ca3,fad5146b,e531dae7,c9c0d586,4f2d8bd8,7a6457aa,23e7e758,2cfc92dd,e498c0af,b942182a,92e02bb0,7e95bc1b,763d8030,9ddc9137), -S(dfb018bd,9bc352,f36889b8,2a46512,8850a158,872554cb,3a3dad28,a0496f20,2daa780b,d615d778,3de8f5e8,25cbd934,5c021df1,9ef80a6d,39ff87db,67a1e5ca), -S(bbd320ee,dacc1282,d3fd2109,c26f6bcd,46205ec1,d96b806,dca35dc1,4baa823d,ae7beed,3b5f72bc,ba66c794,89c05666,efa85966,14bacc45,9a99d882,8edbdbfe), -S(c9cd8f21,a068f78b,ce5129c0,9084be52,e48d688b,f474e690,b7720360,e362dfce,a10b9fe2,78c7814e,37851b5a,36aa4246,54c6279e,89df8fc2,ed189ad8,11518f22), -S(ddcf39db,aba52181,72c36a53,50883245,39ccddd8,46ec4258,e72dcd71,40041491,85cadc4a,a569265d,412c8fa9,4872bce1,51a750f7,b43385e2,2db405e3,54428a5b), -S(391562c3,f19436b1,a6e41d06,7435fbe8,27de66b5,555540c5,3ca7a0cc,c7876457,c3a5d917,5b56f67c,66ff269f,72c0a1ac,74503106,9059aaad,f3e66dad,45a80ee0), -S(63d4b224,7b2d441d,680a0437,604533cf,1dc48c9,bdcb9e10,e0249960,f966b2d4,e25cb896,ba165d4,46f73344,61e6856d,4c186736,402dc6a0,d866f97e,bd5cdfff), -S(5fe057df,5d2508c7,611dc21d,412739fe,3e7cf9e9,670812df,cbb00255,4d44cb22,33b88e83,9f22a7bd,17c149bb,65bd4a49,29b2a29e,b975776c,e82189de,80c7d45c), -S(5ac83bf,498f7eb0,79507ac,d5fbc587,f758afa9,b6a1ee51,4c857f8d,608a7b1f,1c866393,8a91904,f0530bdd,ba15390a,4c10fc4c,ef8a2f07,d799c89f,69a33097), -S(b0f9e4b9,b29790b6,33bcc04f,d860cb0f,823d8d1a,4cc1a1c1,413c1606,cc9a8e2c,b617d40e,7bc52192,be344f46,f9021c0f,ccaf33fd,3e8e3118,93df993a,20c2ee7b)}, -{S(eccf169c,9514a854,8f7e1131,a7438469,4df7dc2,fab96462,20e5799d,6d3f672d,452e53a2,aaf17617,37055bb7,24b64f4a,8fef29ed,f8571ff9,a3a6d2c4,6acdb91e), -S(a77bcddd,a0fecd39,a99c6387,57bda1bf,30257248,6a3fa08a,e2d6ff17,e6e4b6ea,debf4c03,b4bb5c7a,8a386a7b,1e459426,6c78eec6,55f01cd9,f137ff18,c5fbdb1d), -S(a77b91ec,6db6a66e,a48de424,65079a2e,ce220fba,da221601,840546ec,2295c2a2,3c721fea,81f5fe05,163562a9,849bdb15,90bc818e,86674ea2,57fe8d0f,4050086c), -S(99a28a1a,3bf2af79,ef2bf134,d31880a,71c2aad3,824fb7df,23fc4fb7,d54b2910,620e2918,df14e3c5,dbfceada,1905941d,32d77592,89ec607a,f9851a6c,5592803d), -S(7eb52616,71402db8,905c7097,2af96b72,2bd77d,f124bbcc,5418f217,f6d8c7be,ce1e663c,8276bf42,99919592,11feb13b,66aefa37,5d6dca15,8b7b66a3,ffc6d7ec), -S(c88b1815,f183e6ea,3ce8469f,ada5b88b,805288d6,828473ba,368d52f,2145e7a4,55e78f2d,3784952e,cb47f6b0,113eb471,8cc58225,85f9d1e,2198dc60,af3f90c9), -S(dd893c5e,a2e4e70a,fcc161ac,47232d3b,77f16c95,54c98770,9a7a6f64,c0cf7ab1,a1a58b41,c7d4d0c5,6d6c908b,32d97467,b8b6ed20,73e6a677,54935665,6a92a480), -S(591b8422,eddbfaf9,d2c27c28,dd84dd30,712a15a0,deb752dd,dee682cc,34722ea7,877b0c99,6a248082,fd442509,b0ce4cc1,b181d4f8,8ff755dd,5f0dba66,ebf95d1f), -S(75f9e3a1,ffdd902,be5d1d2b,3ed18b37,62e42e95,8b024ce8,f892ee13,ab35c674,57fabc84,7c68cfdf,272effee,e7a6ee2c,5fecdeb4,8e4877c,ccf2a8de,2e2264cc), -S(c8a53d5,e1895cdf,db61c1a2,395a866b,ad803773,23ea43ca,775408f7,a4141cc6,ddeff9c9,97a11e4d,d0afab30,f63229f8,1b52ac,c25749ae,2749ddb4,2b201196), -S(8827d23,668f3006,b966cb19,698a066d,aea556b7,4108739d,d6414d8,e8dd78c9,3d009ac7,2baabb53,2e3658e1,8941d4b1,efe512b8,fd7696d5,14b12216,215f10e0), -S(dde6b713,5cf165c6,53c7f5db,542501bc,b0a41e3c,c6779aa6,194ac1d1,8a830b01,25c04b4a,937e16b6,e72616e2,d64a413b,6a7c29ac,71dfcbf6,826261dc,2507c16), -S(8cf6210c,5426b3a5,ed594699,da6cb8b9,8069a3d7,b926cae9,fedb2e96,25d20010,78017fc1,7915e3c8,62557896,acd002fc,7263bd7f,aed38fca,d63ccaa3,57391f30), -S(35772904,91661db6,340e7d1c,a98db8bc,2f50f557,283ccf11,8e446f71,925ade9b,fd8a4a56,b82dff95,a59e29ea,bd5d8e8b,a876bf95,4abf0537,60832d1b,d7edc31c), -S(60e4201c,4dbd9c99,c5eda030,f041f51d,f648f77b,13ec2072,4d89b6be,f249d793,ebd96057,d60b7cae,71349c51,1a3ca99e,847419ff,cdcaa0c8,54d75d40,8263d81b), -S(f39d686,b17ad518,3a7d300f,1bfd015c,57541f08,a96b5943,43d2ef82,bf20bb6e,f1298c9c,633a958a,a0d12b87,8c95836d,f9f93b5f,5e3a6bbd,93a75ba1,1b96d4d0), -S(37ea7dc7,2a3a0b4e,72412814,bc1e1233,17ea3e1c,c4ede35f,cab5d31c,93cc330b,aebaca93,8b14b315,708360e,5662e6a1,af25069b,cc07f581,225dd131,c656c607), -S(ff1f61ed,ba3cfc6f,2fdf3043,37205bab,301c965b,501e4f2f,fcacde00,dd127b25,fb1edca5,90e00f87,eeb56ef9,94e9bb12,b64ad1ea,f5ef0afe,6f0125b4,e100a483), -S(3376e0a5,b93f15b6,c46b92ea,e313ea2d,c5d0b961,a2623487,8919cf5e,25e9ae38,a4cfc1be,fd24647a,20ae014b,2041ab3f,6cb7585d,48a607f8,299e0c10,96bcfdf1), -S(be575f99,842187b,30bcb312,987ea218,3d613442,8878804,b5e7d920,12e58d9c,154e02b0,b573c81b,d2079a4f,4a6efe5f,5f37502b,33225064,4eb38b2c,3f0a1767), -S(5a215836,f1f2997d,9b09d4d0,6473c55c,46cd3006,70d85d6f,6b5531aa,c8da043f,ef5fba1e,b6e1deaf,bd83e480,fcd4984d,cf60f91f,4799e8b4,3f4edd15,f94b6d33), -S(d73fee2,16a503e3,a7d6b0a2,675adb1d,197c3fae,4d43835c,b6b043f5,d44909f5,6f2cc9ee,fbc36b4d,a5b3e704,c13daee9,cb81ce9d,470f1290,8b32f047,ae231053), -S(26fda2e4,d07ec613,ded58e14,ee84e421,ea58e5b9,5beed698,d847f6a6,db185f6,683c0002,bcd6d8b7,1d06e592,db4b961d,f2518fbb,47cb4ad9,96020d84,ed8a5909), -S(cd3d4e87,e433f2b5,5dc55c6,a3f280fc,57f899e1,f8f0777f,32705f3,eb24551c,2315d85b,7521e4e3,8e69f29b,a49a3203,abc7f280,ad49365a,4c78f21c,3ee12542), -S(652476ac,2c9b871c,e108fa13,6a739766,879a76ec,60d787ac,a1b7447a,67f8afd8,b66bf6db,cd3a1393,f70ac7b6,d53069d2,5f084dd7,f05c97a8,76f7f646,c7b67fa8), -S(61ab4f97,61c96446,ea7a75de,7ed36224,7b5ce8b9,e7b442c3,432f9fa0,ec74355e,f391652b,17a910f,6d476c29,89e854f7,d31a5f31,fead5fbd,5013ea56,e44985db), -S(36e4bb36,e62f78a6,a6155351,36a73637,13fe8be8,1c8c3460,a94bb642,4f7c80de,12b38983,c10079f9,b0016df7,fba0685d,5eb87518,234c65c0,7dff006,dbb6a563), -S(f5e4cb89,101e90d4,b2f50097,aa0b22fa,df076932,f4045e9b,7a9ce8d6,ba178780,c12ec4ae,56db7971,3a1bb0f,2559e3a1,de3f8200,650c809,74101940,181eb52b), -S(1138ad12,333790f9,20e979f6,a6471274,2a9bb567,2356e3c,80ffff89,a9de533,4caada48,a78ae26b,790f23c1,606a5820,98642f4,bab5bfff,95748f6a,2ccd6bc), -S(e0346d21,121ff741,fe4eaa23,938a4347,a71df442,9e55359e,aa20d691,c9f40840,c1197c8e,c36676a9,28a92b56,811845d5,d9632c65,9142cc12,3c65e54f,c282dbd), -S(d42011d6,1061388,fec6b7f,3f332b20,24ab318f,2a9ba7ed,23731207,3e32478e,451a2b16,5c82b1f3,e4d2a0a0,bb407b84,904db4d0,caaf733c,e31fa97d,2fb1735b), -S(63964eee,619074e0,780140fe,2e90836,e72328d2,448386d4,59c5be23,187f5048,c49304c5,947630be,5c60064e,3cb40436,c2a7f46c,b221937b,c7c5d7b1,76cf5e37)}, -{S(8f741868,43906722,ab9f5c6e,c796573b,622fa2ae,6d985bfe,ea4d51a1,8f141792,61ecd858,d6992c4a,bdc22472,fb8fd242,929dc5b5,36ea8e35,d1c8c513,bcb9e31e), -S(f2dd67e5,6f75c397,76b29366,149ba4ff,69385651,53afb385,3853acb7,9fc2bd59,3a24641c,d48ca39f,fe992bf1,50291604,79066af4,a0cf364c,9e52a9f,9b51eb66), -S(9386aa5e,c3452728,a8f65141,e2f43a14,c250173,9349c96d,e1968a4e,48cd30,a3a38a85,4f68048,d8f81002,3eef9966,780262cb,aacbe859,a8fc66fc,27c37f32), -S(6c9901ea,920c0f4c,ce51fde7,ab283f98,eebc30dd,c76a3219,1df4c4c9,db467aac,6773f8ae,e601201a,84dd4485,fa560e22,81d5eabb,25a3b3d8,525f4a56,65f79d05), -S(ed1eafec,876154e0,58597caa,8250b0ef,7262ff70,b719ec9b,63c0b2ff,9d167fe3,73505073,2b563f93,89078cc3,93ff9837,227ab8a6,c7d789c,6d2bc835,2018f77b), -S(515806b5,13d4d4bf,83533b56,3b39bf9c,4e808426,f2e4cf16,562e759,cf2d56ab,83c2fb,673a08a6,b8a86b1f,e1ba23d9,3347903a,d6855059,130d8d39,737ddead), -S(30a726d4,d8db1cfa,d59331a0,8f4b5376,36848547,914dcd75,37a80e40,109b8e35,8f628b92,6a11ddc0,dfb1cebb,934aeaa4,3840d442,a61145d1,803f771f,7bf65d7d), -S(116867a8,d72fb00e,80a6f267,e8163770,34affeff,36d667cd,38219f0a,e3c9038d,270f15be,b2a3d50a,4088720a,e9a2c3dd,df00817e,31e1a5b1,d850fe23,dfe51657), -S(abea2899,e4575c6a,201c96fb,a60a24ee,1f1fe0c9,b718b54d,18981938,4f33a1f4,d43d54e3,9e8d433a,ce66ad94,e52662fa,8013e778,f8bc2e3f,31938a6d,5681c660), -S(1fa796d,9f658aa8,6ccd0fb4,6a735651,102e3181,302e371b,8c965dd4,5f078b30,69815d18,43c3b4d9,f7fa4af7,3d2e5dda,390e5372,28608912,79826a53,a437031b), -S(f5022faa,c8caa29f,304ab6c3,d00931c5,e09085e2,73beab04,c1d18f87,1c0fde73,c6abd143,73213fe8,ffa5ec64,8a22dddd,fdf2cb25,e32afd58,4f92dca7,838e8249), -S(8190b10b,97bc72b9,301b1dc,cc60e69e,460e389e,ce7d5d11,4e2284de,853ea02f,f1ffb850,dbff0f06,561b75f6,5d2ae823,cb13881f,d1150eff,274db4cf,112d2253), -S(ea230fbe,c58d7e2f,1a3cea60,f9018562,d2fefb49,8efa312f,4beafcd3,139da094,6045d69d,b27bee6f,3357180c,e92d3866,b480faf4,2debc033,cfa118fb,b89c3bd2), -S(333d063,ccef6aa1,f78c81b3,4a84975c,82bc2cc2,bb897608,f0bed49d,cd08829,90ad105e,f72b7e4f,a927240d,9c69729b,a0aae3a2,3a45342,3be2c385,488840a1), -S(4d95cb48,58d808a3,be82f42c,da4f64a8,c64ae176,3b50257f,2e4ae655,fcc4802,5f6efffc,99bdde54,6d8ffde5,e9a551d0,121a39c3,86db540d,1caf74b4,894c5559), -S(b87b5eca,6e0111bc,5b756816,fa82acf9,77f81376,af796cdd,1e8fcb09,4d363d1,442fa845,9c2a7799,2c09015a,db80f26a,28428851,62432660,56026009,5f2f9d8), -S(34baf43a,a82cce1b,19945590,ef3cb582,2ab03142,6538ea5f,74571582,ee14cf00,9a76705b,c0141e29,75d11543,215377b5,3c051c31,156697cb,e8f56721,da386e2b), -S(f07c5d98,a2579c17,53b3fb58,22a139a1,53e7deeb,ae9304b,114bb188,d61cdd0a,ec18ce0c,1e51b8bc,e12f3d85,23739f8,bc25708f,32deb81d,a780cc4a,1010692d), -S(9a146c80,5ee261ad,3e708885,aa41041a,53bd3758,b3d1ab7a,1a44aa7e,29acca7,fc553e71,4ad8a192,90f94ed7,7c171f9d,9ad9a047,6791f045,4a3ab7d3,f8834f02), -S(c8088409,650feb74,9f9fe21,61772279,128db1d7,58610a9a,8b9fc4b,ef9683b7,692a6be3,132a08d3,82295ee7,1c469465,ae7d63d6,c20c7357,36935003,28799639), -S(53bdc8b2,3edd83b6,b149b79,c88130c6,b207f999,e7045285,7e828f81,b325b9d8,a9a039d1,79486167,8fda727b,1706e9ec,7ec3eba3,26e6a4a7,e27db3f0,8a6ee238), -S(fd08fb47,4af98207,3d8b4ef6,d39012f4,78225f1a,bde3c841,6fe3881b,4fd276c6,d38b53a9,100da1fd,1d2a987e,6907370e,7bca492e,98a22e5d,74a10c9b,93a197e1), -S(5c42ad93,2306363e,a0edf86d,31d14b04,c3f7bc09,c9fe1326,d1ad085d,c84fb7ca,1bdbf812,e9ad6486,ff572d4e,de5be4c9,59de7be3,f21e0dd8,76534091,f13ca3d3), -S(66257876,115e7eef,fc0e6132,9f177d3a,437c81c4,1150f86b,45904f86,30bae971,df830e1e,33aeded,721a0a6a,62a3a402,1d2b7ab7,438b7b3c,d834d67,3a857aed), -S(4feea8d8,2cc6601,c847deff,35581c1d,bf1f4070,402bb948,ce9a41ee,16661627,c09a7686,ad6bcec4,ea9ab0f7,8316adc0,7c7a2899,9332cee7,5d70c50d,249a0007), -S(2d3bb180,73f5345e,cff0c901,9a6f2fb4,e0a237a3,9315fc11,fd53c7d5,aec43670,58a9459c,2710ac75,ff2510ce,4c9c5fb8,b4f739c9,c6611494,daf896db,e43b080), -S(bd539f5f,47b25116,7159153,f402e0af,8650c17a,de7c5dde,2d9d9cc2,d0a3103d,407cab4f,ca581f10,eb386e20,9158541b,8649951e,b2f5e454,2a7032b6,53f0caa), -S(c7a72935,87ba5114,744c3d0,9030be19,9ccea57c,7f80be87,bfb5b79a,8f8e200,7c2a98f8,b4526422,b211bea0,875a81f1,d379012,486db005,e31b9682,404e14a3), -S(cdf20316,f4b63ca4,c472e1cd,b3a938be,291d98b9,3ad8f3f2,4f3e1a4d,f1a6cc80,ab993e8a,68988d4d,2749760f,241399c8,136ee9d2,3d4ae7d1,e6d26df4,6056587b), -S(1d341e6,2eca1f48,165bb2f3,86207da1,f2c7fc86,dff7a75,cb63976e,f21bb074,923b53ed,fe2f5bb5,56aa7cae,2a08ff86,160e3344,c4adc09a,e7aeadfd,f31e2b9c), -S(8704f69d,9d335975,f0e3bb83,5aa3024a,60103d89,e5578253,fbb3d537,1983ce4e,94f4adfa,31dbd13d,95c738b2,8a569453,cba45efd,1cfd20b6,78f6a724,e9a8d025), -S(7175407f,1b58f010,d4cda4c6,2511e59d,b7edcf28,f5476d99,5cf39944,b26b64f1,bc4baabc,bb1c2aaf,c92cbfe,ecb33791,4fe01748,8bb8e2d5,bd918104,4dbdc75a)}, -{S(a16a4734,9afd167f,d5e79d24,9784d87,5121fa24,2c3a54a,88f9b176,72669aa1,4df3fb81,7021efdc,e5296735,3a177b5c,51cc7762,4755ba28,1084db5c,4809e02c), -S(91d1abe3,8d3f9671,54337e03,d27fa6f8,c3007f32,323d15c8,31306b3a,30900328,b1b8c71d,b388009b,98000f9f,291b66e3,f890d42c,a5812f34,5c070f6,e73b89f6), -S(61b64b1c,f2a0e720,e9bb4853,537b9f38,66baff87,388df7f9,f14c06c7,12080b96,44444011,b6ddadc5,7ee00eed,b6af3772,e4116711,c3853f13,7f9c7b00,2bf2a1dc), -S(3b96b2ee,d9cf1ed6,3aaed8e9,aca3a464,d6a6fbf5,e6fd48f0,5aacc318,dfdbc87,51c41c26,506cac9e,bd0c5dbc,8ce8788a,3469e42d,de794707,9e0cd0d9,826e9c58), -S(7bbd147f,77b293ac,ff797b9,a52778de,5874b754,c08df397,72ed8ef7,53242efc,3e843df6,75abef2b,e4d32c83,205322cb,f53bde0,2563eb8e,b5dfbe6f,27d4cada), -S(becb7fc5,de84f994,9f97e55d,bdb6981e,f38c0c45,1e0e454,519c9411,5bae3d7,754145ec,ee6f9c7c,f91963fb,5b0a683a,ef24313f,1125570c,c9b9c7d2,afab99a8), -S(87936626,aa88346d,6d4330d9,3a188ed6,992bdbb8,387b395e,d21dab93,63d833eb,a28c868a,18dbe0e7,12ca5237,53f6a50b,9313e687,85f3b31f,ec778fac,87aa9327), -S(e79d4b2d,e33de1e2,e7eeeb44,d197aec1,f5883ad6,1394dd79,de274ef9,76e3b022,9c73ade7,7c661527,ec2ec6cd,b370c130,380bdd9a,4bcb668a,86e8259a,ca85f293), -S(863f0d65,34de1222,237a07bd,ebb066b5,2c1cdd83,d7a6d3df,278e57c8,bb59b8c7,c546940b,99d04ae2,5cf7c881,28a985cc,9b6223a6,ffc06fe9,8a3e0f68,439b9db6), -S(71e9b0d1,3972d9e0,2225bbda,5a1024e9,c373eeb,f6514eb1,c113ef88,dffdc3a,4436c52e,c58a34c,562638c7,8d76e3fa,29e3586d,fa667577,2fe0b932,c4a1ade2), -S(ef4a500d,c9369125,78fcfcbe,3c313bbf,f0323caa,75750b6b,a317e1e3,dd8054e3,e807e9cf,7911c919,fef82e40,a3ae1b9b,ed8ded38,e74126ed,863199de,c031f2a1), -S(806dd4e0,fbf72904,c7b0080b,4e7526bc,c71fc52d,f143da80,e571041,dd964915,2f4e2e67,3348c32d,6bcc0741,2e76f4fe,944f96bb,d73382c8,c6880cf6,629eac8a), -S(9ea889e8,acf0441d,6e299687,c532ea8f,8b9453ed,5fea0d47,f735056b,1eb3bfa1,e43f79a8,4d302f3c,88698896,5fa7b8f1,a92c620,dfcb3462,c4befe3f,4afbff5e), -S(9a990a22,1d27d8f3,40e79489,58cff3ca,2720dd3d,ac71688d,9c3c9e2f,afeee215,4957ac76,db370918,7992b0b,63370656,7e0f4a0a,9e5f1d9a,be8f7d5e,8a950eef), -S(d3291003,98ad3d92,1d6cbc6e,b37ac3f3,9360cea6,23edd794,64d34a51,fa7adc60,657c110,5bd8df6b,fe52addb,2fdfc41b,810a1ff7,8662021c,7c220b0d,b3509d14), -S(65eac576,e149d97,3cbd772c,60570870,e437e92c,2e5138ac,9c0534df,b7a45582,ebecb6a,edb87cc1,417e066e,fef8e52e,c61eb00c,dfd98205,91d63c08,9dfd5347), -S(b6976b99,c2515be2,2bc901fd,8671255b,f8fd76ca,1f3474cd,5eebe39e,98f6f14f,84ab17d,da67b61c,fd01881e,b1087e69,845aecc9,ce1535fe,1c7245fa,8df98181), -S(c7f5967f,f9910e10,54c93e1e,d0290102,9bf31787,15f53758,f5c53cd3,c79a52bf,bfb01210,5c1ec69c,847ceffc,d1105ac0,528129fe,3b4d3086,2b6e9562,836f5eb2), -S(ffa0da7a,e8984e4,d02a0fe3,acfb4e81,2a63d6b1,682dcd78,fd2635bf,88cfdf1d,49459ee5,3fad1097,2da786fe,45a2d201,e4a52260,7779b1d4,23defafe,29e70098), -S(5a53d683,3bc1740f,d02f278b,2ac15a87,f137f2,c798f157,725a4aac,63f1798d,ac5e7ec5,86d5960f,e25f9e25,7cf9ee05,110d9595,e440d032,c416d444,6242d10), -S(70f67487,9b030a4d,9ccc0bf2,90d5b78,c455f8bd,a1fa2b52,efaf0200,6b70a6cb,10f5b1c5,dc46c0c0,68757804,93805aa7,5a259dbd,95b4bd14,d031daef,a81bf7bb), -S(a4baf0d7,d3a53c29,e78ff81a,52d634a,e009391b,30a9aa91,df8f7bb6,13e3c16,c9f9d001,7f388f09,b6802c45,e1fa036e,99443467,c3847937,8b384a9,dada35cc), -S(351b8e4a,dd336c28,5d140c57,9f2b089d,3c656a05,b1ed6,4cdbaf7e,e5bc671b,b996e61c,cb14553c,b7b79803,c82332b6,704ce97,fb4e19a5,1f70b13d,f8e2732f), -S(d248350,92898c0,5dbb4465,18695efa,e59ac007,d58b5df5,bb3b7038,82f18e61,23455e7f,5104051a,44600be5,2e242a90,95213d25,b4fd65a7,62c3f9fc,9234c2a5), -S(d3fc6d75,10cb0b20,77b52b00,93e84d47,54dd1a28,4f3928f2,a9e3cc02,f1869588,26e86b02,c16171d4,4238aecf,666146f4,9386e0eb,52dfed87,7ac0b409,51ced10b), -S(1c611335,3d115906,182b0e4a,7eb3d39f,552c49f0,c5928aa1,15ae00dd,c23a3b70,1c3e3c4e,ed65ce47,ea82a33f,df8fa6b5,532977d9,53aed38a,f0f4dab3,98477c6b), -S(6487c5c6,abb6e673,821c4b0,2c485f83,3e149af1,83b3f025,71a81fbe,660e98e3,63c4f6b4,7eb37ed6,7668b41,1e83d9c8,9ea323f3,2d9e8918,20b65276,a8a7b7d6), -S(1b0baf63,6daaf2c4,28a62bce,bdd41de2,a4d7cf69,93f0b931,222a40cb,9f5f9a2f,af9a62cd,f91e2c6b,47f308af,e2de8f16,def4972f,24bf4c5b,2b1f92ac,f63a21d2), -S(95bbd974,78e1b8a4,1622e460,8aa82fe9,e77d43e7,492a0d21,1146d987,f9b8f255,412bc52e,d61c3880,210d3df7,f0d2f27,d458d51,388803e,fef1c016,d7c9e7f6), -S(a3466715,5b6ea598,2d3945fb,743a1510,c671b96f,a3494a57,e0349010,55ae087,de35a05a,1a943a42,7210165e,55d5cfae,3ac15490,dc6b0f43,34c0c99b,dd778608), -S(2ed76c11,52ac3600,7aa17c85,a5f902f1,7c845a05,a4e0aaa0,7b05e836,cbcad59,9c60b2bf,bc47a0dd,d3259151,37e89812,a08d39fe,cf5806be,eb538575,3b159531), -S(20e6e2e7,96946bb6,30c7071e,f1b92ea3,d53d280e,e450111,5f5da36f,840dd273,2c528501,b0eaa61b,b5f45e52,6878b9aa,7ee13686,c25796c3,3f8302e9,44b9469c)}, -{S(f040a2fa,b839c753,4e216425,6c2e8dd8,57c52dac,e75cab3d,512a7b1d,562075d2,9e211cf4,bab24e0e,f745e2a0,9b59565b,be7b2449,8123f6b2,ba383b25,29554b36), -S(c66813b,904831cc,12f89e3f,bde93eb3,11ade6dd,f6cfdf72,21cc61a2,ff46bf26,3b60c8c9,9da35a58,7b9650af,f85ca785,ece41146,e7ed8d6d,ef8d26d1,f3d055ce), -S(cd38ece8,7c7a9cbb,e23b58ef,59925633,734de285,f93b3ac4,eb01e03a,adab904b,a5f48fcd,afe414f4,1a44917a,5dcb80b9,30373af9,70e9f22d,c1af80f,a8b06320), -S(72d6f7db,199564a2,6e823a49,eb0171cb,ebb76a2a,add56c7c,6d3102a,9c3ee18c,bd2039ec,c390839f,e2d4451c,9437fef6,3e98dc62,3ab0eea4,c56376f2,e270f626), -S(2ea6c313,1e101867,2454e15c,d34d5fad,13829d5,4ca86062,f074e512,a274167e,67e3d34a,56f12e1b,43687f51,c2d56395,14355d7d,9cc52726,22f62ab8,91c8d5de), -S(d66bdd78,8b20da57,b2485804,a2f6e2ef,78c7ca87,ae1c5c66,fc533533,5b624162,1a8688a1,300e6d39,e130037d,3f074ccc,57addd1b,88977e64,2ab296ac,d6e054c9), -S(6d6458d5,d1683d85,8f9e40,15e5a94a,73868bda,54f6139c,446b5283,6d211542,e44c7ca8,33761e13,ca5458ff,dc682f22,3819411c,a3c5feb6,24f06412,471b9f5a), -S(49f8063,b3d98f6,f159f2e6,65b0e07,8ef8c7df,44da06c3,55b592ac,13402b9d,b0b2d838,4b24ab11,de895013,e897e825,45c3e8dd,6cdb0990,555cd871,5841f8cd), -S(8b2fb6bd,e60449da,2684f8e3,6267fff7,254051ac,faea37cb,102c9bfa,91abb2ca,c82cb9ab,c33c1817,10d3fb19,60f2850b,5072eb47,404266f7,c7964fb,f98027d3), -S(cf90331d,73644476,47c8f86e,eaa6e67b,f3fb4b3c,4c895b82,30ab2f38,80df1e42,9c493d94,3471efd5,ea90f723,db576a35,8cd1ee6,1a119b56,6c65b16,112eb2b4), -S(e70667cd,8d2759e,43f99417,ecc505a7,953d80dd,e7ce2cba,3c8c948b,d43a912a,92a534b3,51449a66,82395a3,b75877ae,851923a2,e791acc3,7293d728,777a2247), -S(4cc07d11,4a715e9f,4b4d0811,f0337c7e,f4bdff74,2fb008d2,1ce8a9ea,50520d47,478b279,613d92d3,dd24ae31,2658eda8,28a7d628,f0346e04,5d5d9dff,7178f093), -S(2a1cee60,4cdd3b2c,1f859bfa,af63d7e3,9aaad910,92c2a38f,a9362798,9753c30d,325c248e,d409e8f3,b96dccab,6fdb62a6,83b7eaf3,36d2864e,b821663d,ed31a6f5), -S(7c18d0bb,9a01969d,302616cb,bad8722e,d00103fa,9985a50b,765f0e2b,9a2ea14c,f6365a6c,b06e4749,c48c212c,63fff571,8f46e0cf,6fdc8c42,34d4db64,ceb72080), -S(a706754,65cde407,e853e882,8fb7a2fe,98638d7e,64b8df0f,b0a7a0b4,e629d0ee,fd694b2c,1354a5e9,415926d0,1590eaac,dbd1b36b,5ecc46b5,72467c3f,e2cc5393), -S(7ff57a63,36ec73da,cc1dc527,928cc6ff,4ec063b1,56b36292,23b8bbb0,a8ba2c7d,4d6dfc43,da0fe33a,1e75dbf5,5e5d669e,be6471d,eb8a4102,6db1a41e,9d5da637), -S(d4b1f7bc,87558c27,7e0fdf91,22bfe488,b3182555,599dd384,5cc039b5,93218e9f,992f79dd,c8f46682,5c44a54d,626b352f,7f59139b,d545f78b,44bd0b10,55c3c1fa), -S(897773f,a9de63a7,46ebf58e,248d0c21,10f90230,a792f0b6,ea5a25a0,9d1940d2,b7c7dd27,d561dde6,ca7588b,8e3a09c7,16297ba3,9d501744,f9639a25,b16b4f64), -S(2f9cb312,b071a600,e5d24cfc,79b0fdbb,f6da1527,10ec395d,53078453,1a3b07e7,49260f95,757b9b66,feeb5c20,16aa051,b444bfc8,836fd8a2,ab913e98,731fa97e), -S(5c53b27c,4c0ae241,8569c806,8dd43a5c,6fa23ac6,74d001b4,eee6a748,d86c9e6d,4e0e720a,f430972f,b0ab89b8,79a56eb4,f0af5161,cae83ca1,964a8099,f9d497c1), -S(2671ef50,5a321387,9560f0d9,e8588707,1c2b87b5,d06bb9d,dec3d179,6275b098,750ea18b,dbdcbd58,be994eb5,cb3539f5,8c3dc630,7d50bbf1,f69050d6,235826be), -S(59baa5ce,9d6e707b,b0738f4f,d37c9890,801ed796,a82afb2a,ecd2c5ba,195be65b,e6b66356,20a8a106,b58dc202,10cccdd1,e0e8c579,c92f3fbf,8b335765,b30d8291), -S(bb422d0,88abedca,e4686479,295aa1a1,77d7e68b,293bcd31,4097ddc1,af764b90,a96d33f6,46d4861d,a471f853,e0c6ae32,b1eea619,a7441504,a773f5e6,fc548805), -S(8d7df8a5,f08ba2b0,923662fc,e594f111,5295cf6e,c5aec9ca,df0f7236,fe51b362,26452215,7d8572d0,f057ec9,6f572f11,ebad3fd0,56032240,26b54df2,991f9046), -S(9e2b1637,352d8988,1e76fdec,c2dc8533,6a71b18b,3c98e59d,397602f5,8b9087d7,b997404f,1c0b1e64,90cff078,fdc47c42,aedf245a,e69d844c,18a146fa,6d8c3d13), -S(972c7bc4,6362bca6,b58f1d0b,87c0b8dc,fe91a217,7f0cd7af,404f6f06,47e09358,cfda778,a59d944b,4ec08bcb,3aabd70a,cd6f29c5,204c9161,fe2e5bd5,71d03f6c), -S(f7dd32ed,89ceaace,52e7f26b,202ea6a5,c7e8ff42,6c7ebc16,12106f7c,6fe51a54,7349c17d,d8ea6ad1,cb346e3d,26989950,3de00c11,4205b3b5,50d27ff7,67efe75d), -S(c9f96f88,3e34aed,97351928,fa77b07a,f4b01bb4,e4515f0,59745ee5,decc9fbc,6fd62453,dd6c9dab,10fb7d79,c15b4822,178eba31,258800e4,519e627e,91ef20c9), -S(9c28cc93,809b35b3,96a4c9cd,d6976391,17402ffb,5588cd76,7c41a92f,e971a9a,ca3b2634,28513516,86a661c4,747aece4,c8130d93,ff4108a6,3365e725,2bbb80ce), -S(263a3fca,437c4dbf,48ca36e6,aa892d61,abf58f6a,d3c82b1f,fe945dc,c45a15f8,604c5bec,69e0f1a7,3e8f8a80,4f762cda,96ba2198,35268887,910c8df0,e83d3044), -S(7fe42dfb,b3466ed4,d7cb8242,5e66b5e1,14a70516,b118911f,9170656a,3dbb04fa,d11385f4,b0a3a0bc,cf09374f,868cb30f,55175d77,2d3e463a,a298b6ed,1e6f6fa6), -S(53f2432b,a8171714,3fa9df3d,ff41ced2,4a29b314,bc5a8c96,f5f6400a,d7c0979,42ad1004,3e0f8648,332b1c1f,6ee4f821,b42a5b0a,361747ba,60816f2,ac84c58d)}, -{S(b8b52efd,bc367a5c,a1534bb2,f339a048,50fc4941,1668780,dcdb8b51,2daa7526,306a2236,856070ea,1e0fd846,cd571889,e20968cf,cd490bc9,facfc4e5,a5970b2a), -S(27e226b6,ed59c89,5bd20232,bc677c35,495d9601,5f37493f,5075718c,2017e42c,a130a5c8,54ed8ab3,ed657e0f,ee4a04cc,1b59a291,6e96465a,74b36144,7cc621f0), -S(1733f1c0,da38fa79,a7b37988,1822ef51,2392d8cb,59d1ad1e,afaf535a,e151fb64,a93ddb00,af779565,eeb230af,815f9434,958ad39b,387d9069,a03cfcb,8563a920), -S(e3f4b777,d06c8839,c63dfb41,73281787,72debac0,ed45b991,724c19bd,85ab3c58,2d6a84ea,745decd9,e6444b7a,dbb59fa3,21957b7c,3f8141e6,fd633d3f,7539dcdb), -S(a2b42fb8,9ac10df9,ebe804b6,c105e855,25cb05eb,7407d383,3031e216,64491ff5,d0973dbd,346a87b4,f4ddfddd,12be3131,e6c6a397,8e17be2c,bda23683,62f80765), -S(66d441a2,6b28378b,cf23d33b,ffac1163,7c23bbb7,7ad352e7,ff5cc09f,41bf6e91,982aa46e,5fa0b19a,28ecfdee,539c0ec,b5f06e2a,217f7687,6c3cbf1d,e92a6068), -S(3721fccc,20338f8a,779aceb8,eae3fc7f,bb0e4040,1de2c8e5,27941ad7,f789d0f7,d9516c54,8f457b6e,d44f6bbb,23f36c7c,e6fdc548,60e5042a,b3dd4f67,ad5ae3ea), -S(959e980,4618bed2,73b5cc48,5565df27,b8e09c9,a128a9e5,ea92e347,66e02015,cee3a227,1bddee01,3582d65d,c3e26c8a,f80a4601,abcff432,b1737127,91ca15a4), -S(f2e81d16,c19466a6,1b56931,935d03e2,aad6b8d0,7f193d97,bacdc29e,13cdcf38,afb8e973,8d563dc4,1e7688f6,c6b43b71,f366b576,9479f093,88fd09e5,faa1063f), -S(98305a48,800f92e0,bd815192,7b8658fc,60a97c64,c9f97383,68812614,3563910e,d32db8e2,6699b969,5b644c08,39f2399,f8ef45ad,a0d857c5,2d0c7c3f,96a62993), -S(8dbd4fba,113c50ba,ff3f251c,96aba9c0,440d8e69,8a1e4ec1,84fba97a,e497c443,f642b1d9,b012eef2,40c6ad38,fe441d11,cfb42ec2,a3c15540,45e64c76,c15be491), -S(deea5bb6,c7eac0a2,93e90817,836a3e55,2a7f1354,395296c8,97964c2a,4527a727,4cbe143c,c9fde617,c6142335,4323b9d8,bba13dd7,fbd46db5,cbf4ce2a,11c9c00), -S(349f46a5,8621034,9f207a07,4558787d,336cb0cf,a56c1e67,8dd3b04a,4d717f4b,a6479d8,f7f017a6,32c369c0,8679fecd,985b3c16,ff444ba0,3fe43575,8b96455a), -S(a6d818c9,dc182fd7,81343bc,b737811f,611c8499,e44a6cdb,33a36beb,7e44b545,1a8ee36e,d6e9b191,b9cbf840,3924e6b8,ac3c3f8a,cbc9a0b5,ff965d6c,734d741d), -S(f9cad333,7b82ea41,b00f3ef1,bba37b8b,fcb24e8a,175fe380,8e399b67,d21837e7,cb206854,4e7f2cda,28c035f1,b8b50009,319797da,bb498b99,d31e24e2,4fa27ca9), -S(25042b59,f9b29a9c,83d04515,c78f1c25,5b72f97f,7b387113,e88c36b9,9da3ebdc,d966ba9e,a7eb9734,e1481cb7,2df63252,7492e1c4,43f1fc9,c0efe0af,442b5a13), -S(e19c4319,b5c9a01e,b588c629,8a7c6b76,1b80bf4b,e39424e0,666ddc45,fd57e0f6,1b0a2c30,4a1bb1b1,9dd0b50d,29df625,bf958a73,46cc6b1d,81a213a3,b6636285), -S(59c26fc1,6d151c0c,7da0edf6,c474463c,587c45cb,7e407589,d15aad89,de223fa0,f7b227b5,4855c1c4,1e576431,8a7106eb,ea214686,ef815b42,db8c18ae,d5c940a5), -S(d967d546,e07ac1c2,31fd50df,a1d25a51,60594d88,3e816f6a,bd62c15c,446aeff6,8eee6c03,6e22a014,5d9cf3af,9b44e005,cd1d36ce,d7c420f5,e2db918b,e4fbf83a), -S(424b149d,9104254e,3f5772b3,7d973cf2,a46bd110,89d8f850,7666f04d,382c972b,7272ad07,54c18fbd,66e2abb3,952c526,d8113d5b,166283a3,9ac8ecb6,2b7a3e46), -S(40b4b2ac,bd299270,e64bc470,8607c586,3bb50913,45e573f3,a5e2461b,47dbc053,d094311e,fd81bb1f,4622d17e,68044107,a2a8ed54,3cd5ff8c,b531b28b,9b8ec99e), -S(79e79ded,6bc0d851,fa769b5e,8d65857c,f3c1c18e,6c990cb6,116fc45b,63e9f924,4fa89e89,ae4214fc,ba2aecdb,41984788,8154eaa6,bcbbe29f,f04a6262,7299f469), -S(a11ad5ea,59c644b2,8dd7402a,5f96a970,68d96e2e,eb77d59a,fe0c2fc,cc6b252f,38e379d5,150109df,36ed7ad3,a2daa41b,4fb9c731,718cf5e3,8f8f8cf7,d1f3d770), -S(b3002b00,ec5be154,cd8e5226,4b97f5c9,f444b305,8f59c4c,bcda5edf,9d10dc88,f7e9ae65,6ad2c823,8e8e0436,e007d821,b17d9405,984eccc4,617e3977,2f25d636), -S(8d1267b1,94da1334,fd20cb8f,77fa01cf,9e9ced90,43107e41,d1ec4057,eb6115a2,a7ba1b9e,2c6f0f19,5ff1f50a,7a8da22f,da3003fa,44b818b9,953b44d3,e6d6a0df), -S(dde6a3a0,87ef41db,2359e4e7,ca7cb064,424301e7,c5cbb5bc,4b6e504a,f3af4837,24175b1c,b4b39b7e,23718e26,be4a22bb,8bf54302,1f156234,e7f18010,d538aeb), -S(79efa584,2fb89f4e,85f556e,c4be170d,5c1ef88a,3f3f75cf,6b20fc1a,96984ad,b0704aaf,e4d8f30f,4f29fa85,6d55da13,91f5f3ce,36cdef6f,25133999,cc8541a), -S(3aa09dc0,5546977f,7369fa0a,7b60c94b,eab86a1,10d85af7,7b826475,7d67eaf5,343b4cf3,aa6c5ebc,ed041d7f,2381be57,f7fd32d0,29a2f42,a7c8821,4f425d8), -S(53fe8af9,8f9419fb,1445bb6a,94750d46,46be9f37,b7155763,88b11064,df2e6ffa,6cd77e81,84aeab9d,e9bf3093,bb9b21a3,a04a0719,fc428f3d,d5e14c8c,9b16cd7a), -S(fc395dc4,a5114dc8,bcb0f7f0,3a4d3e9,38a87a3d,78d33864,d1dc4cba,9e41e20e,c7991f6e,f72f82f6,b3147e56,74224929,fddeb8a5,97a1b1d4,8852733c,1830b941), -S(b1d25d51,b4558f5f,d0ccb868,3af9a9cf,62a169c6,91627fa5,92d80b18,36695f94,8f92258d,fcf16f4e,8415f53,e65457e8,9f090e72,5479c123,5a481464,a11cd4f9), -S(b866d6b1,42df940f,2cf28b54,c92f0c12,94e0b6a2,2a91f2ef,44bcd88c,4384480d,e6eb4f4c,bd95148f,765d8728,15652853,db1add7f,b4e27929,f19a64b7,f3b34c87)}, -{S(d4aaf32e,dd897f48,5ab16466,76d747cd,fec5b7a0,a05c917b,60c07311,45d16f89,4857e649,beff4089,2470f700,cadb73ae,d4866a84,c3f0b975,6fd8570e,df9d29d8), -S(4ebe5b8a,f3b1583c,9f41bd98,afaba549,f45c381e,c93ec9d1,4a543d87,9cefbaf3,63ed1d17,9b215f34,f1f580be,4b3f671f,2fa14689,74cd03d1,19fadae3,c92935ff), -S(20df6160,556dd3c5,a26620a8,70ff5323,cbbab94,be3e3bdd,ad8b936c,554f28f1,7168e7ab,cdbafad,26fbb5be,a09dadde,ed36c20f,c8deafaf,75a480b5,f980e981), -S(86c663f2,cc6f7ee2,50be25fd,fb35fd8e,5873481b,c477bf5b,c0f1bc1e,3f1320f,c13c5795,cce0ad92,e31240da,90a823d0,d2352314,f2852e67,cb62e0c2,8570994a), -S(3fd8085e,57f6870,b25e41d9,7df00126,150f6022,a7ede22f,d27da581,d234ccaa,c6657746,98d6ac03,ed1ea2d7,bd3f70be,86351c5d,407a4d7c,227fd7d0,c330ef04), -S(1510fcf0,b0fb5a23,c15e041,2a7f6d89,9fac4244,8ce316bf,d88fb58b,10e23118,1879dc07,b34d0a62,f0b9517f,3629ae0f,e8aa6d30,5a783f37,69bdf65,3b40408e), -S(67e9982b,c40f427,98df055c,2d8bdcc0,2ea97bad,68d34024,85498e27,d99e19e4,4f087caa,efc5fd7f,b099c134,a273635c,d1d5ace3,26e3103f,9b2fe22c,e95f288e), -S(e8eeab21,6c3395d6,d16338ea,de4108da,1c25e471,67fb13d5,99e8daaf,93e7345f,7fd2ba87,7c7266a5,65a31548,99950ea1,e5e3d73f,612addea,318ad5bc,a965228d), -S(ab20c7c8,9dd74c20,447bc762,e374c548,e7a8ac31,eec11123,1a040cd1,36e9a546,facacfb2,52eb9532,9106a26a,60128a0f,ae1d7e5c,fd39483c,aeb54dd9,231b55ee), -S(a9004211,b7cf5494,1c530a0e,d658fb6e,3b5d2ee1,37b7d7de,45fef6b5,efddbf0f,58cbaf67,5cc5a131,54eef7a1,462b5d1c,408d5d56,3553ca55,45388d77,c6391d4f), -S(8db64274,422ae0f5,6474b83a,89912fa,e3a39b6c,b3fb8370,308a572e,b6b3c020,9b71a72d,431fd44,aa8632ee,23bc678,61d96edd,b7ec72ab,4b1679b8,a4ba73e4), -S(301b330,c478189d,dce4314f,380cb2d8,38bbd416,5dfad8c4,90f2443f,2a56148b,737da0,1c05cf73,db36a1a4,5005f562,1327167f,d3b60ece,3da3705d,131903fe), -S(b9cbc7a3,4a1cbdd1,300e789d,b7ffec1c,dfe1f738,fbe1fe19,67dd7c14,92ee3ba7,5a816a0,9d08c4be,2b8d062f,200fde4c,534fbdbf,854c7e53,64532c08,60c97c01), -S(6a15e51,6f9f0a7c,25f2eac7,649285ea,d86a1e01,5a386dc,c7f94ba8,4782b45b,63eafaf4,660642ef,988aeee7,642e7c4b,71124a1c,2ca2f5c3,d4f2eec9,ea72d70e), -S(f4c696f3,34c56e08,2ab2e627,4d450f34,fa7fbce,29f3e14d,332bcadf,87d5fe0d,6ee44edf,f574d9a8,363f98b6,b863a648,27d3020,1e652935,be12041c,1bbcc7c3), -S(d2f3d5ad,237ba177,ed312bbb,1d02fb2a,e4bda20f,41f5c217,8b70dd9a,c26ee9b0,cc5912d4,2ea1af01,aa914b98,8c42cef8,46a5a059,664c8545,fc00b662,e0327920), -S(5588b0a4,757beb33,e668af5f,adf87fb3,2aed8e16,e6ceabf1,1576ae17,c6a2b843,70d8961b,ac203e89,c437b88b,ce331309,c4f7eca8,d614299c,74aef9b2,17c741de), -S(f993cd07,f6eb75ad,d41426d5,cc653886,18dde1f0,88aaf3cd,b2631eea,158373e0,1e74f804,5f60349e,a85b90e1,206f0ea4,b0cd3740,861186be,648063e8,58c2b395), -S(2cd04170,78291a50,750218b9,44a11a64,1cb75e7d,cd5cc4f9,64f53c8d,a1ef08f4,1f54a70f,f66ce343,c7ed3001,78d7b99e,49129e23,90b5a026,7ba25af5,3467b6d3), -S(52fc09a1,d4f0cc2e,c7ba6cba,1b30e1f0,b9e37f31,3bf59c33,60fc02e3,3b0c15e8,9bd14bcd,a7c7b6ab,dd7e17dd,ab81a1cf,846be336,a76858a1,8e8a0194,776f0a80), -S(90d29aba,764a9b49,1e2878c2,9b964bf6,e510af,3dd5aeb9,3fe29e13,b8f03b23,396b1f6d,e9b8fd1f,463ca064,11b09823,26cb6ab7,4bbbcaef,43031497,f149a620), -S(ce1d6e8e,ddd063f4,316cb006,b4a4213d,9e0952c8,43e6e1e7,570a35e,aad7fa53,a1abcd7,e2c23ad0,895c5aa8,82a805cd,1d7d434c,72f0c528,2ceec0b7,a7016f7c), -S(4df6e1d3,93a4be66,6fd88c75,e1e686a1,e2cb1844,f5f1303e,f7b0a751,99b42bf5,262d8b9,f7e202a3,78a51928,91ee3fc9,f269ef5d,e14dd0ff,f1fec9f4,4cdb9058), -S(f71b9bfa,bcc353a4,11a055eb,a7d6f48f,47c4e437,96382bcc,d5b882cd,a9059638,bfc1c3f8,fea7df8b,d1cd088c,b1f02e47,377d6656,9b3bd8a2,8b457ba5,e6453468), -S(ad5e9212,d3ef76d,8319fd98,72ee753f,ec99fab0,6244f4e2,a9567068,a635eb53,65fb538f,cb570092,7b0f775a,73ffb0c1,4e6c2274,e253f3a6,2dba9caa,27a3e5e4), -S(81a7dfa0,7659fdbd,57e1c8ae,20c14a80,ee8bfc51,46caa8db,b077b653,23bad4a,ac9d2438,3ef0d99f,26744be4,77e69d51,49d44ab9,84801bb,759d3a5b,7fed1e2e), -S(3bf8c1d0,a613316b,e90eab62,6788c8c3,b1641d65,d0e50245,9e5b19c1,ab1eb617,e1edb59a,8594d73,669e6f93,ca10e210,1254946b,8c9e8eac,3fa84a49,e4e2944f), -S(30f9283a,767c551c,e9fe87d9,5730eff6,fc302a4a,1810e4de,11ba62af,fa17eaae,1f383ac5,e714240d,67980617,d96b0c05,76008599,f8e3fa04,d57454e9,927e729b), -S(1c5d4ac6,91d37d0c,9db5e071,c809a59e,99056263,fbd83028,ee9530e9,c2b3f3c9,b98c7be9,7a2fb196,3d3d4a75,4f7fecce,2fbeb8fd,cf23c229,73b6875,86bd276a), -S(3dfe48e5,2f055be1,1db79fa4,501b44d8,f5ae8447,c5a1293a,a79f683f,1e1e9bf,2d7e8303,b988fc17,18c9b64c,1c03373d,27fd0c32,13c26e6c,b684ca94,49f79d5e), -S(adc4251b,c3ef6d5a,a4d6eb22,46ab2787,bc835b65,1d17ceae,489f181d,57d37248,4f0c489d,1c3a1814,a2f9c1c9,d6fe908f,4623aa44,ebaf4143,79fb8352,15234014), -S(edfe16b2,db401803,11f98920,7a2fef7,d05b2a3b,b676899f,9c6e2192,d38f93e0,1196fd0e,35a24c9,6b28b055,b4fa2f2d,a4c2aeff,3b91dd81,c2fe86c1,1d6bf682)}, -{S(b4b57b34,6e1b41b,7394e655,e059cc93,44c5d83e,f0ef17db,2789db5d,13777b78,6fa187a7,4d983b7e,cea6a268,61039430,63e599e7,cba73144,fe3eb23,677c6265), -S(9937238,7300054a,1a8713b7,6942f003,99818b28,6c6fba5d,ca60b9da,1aa7767,6c003e1,848ce30a,65601eb,e7b76acf,b2e122b6,882d7439,f463c042,ef1b31a), -S(ebd177f8,b5757665,58851c7f,a7ada38b,e3596080,f2679181,f994efd3,82714784,d0fe8eb0,97c852f7,b284d5f,bd81f77f,79c35af7,cc30338f,4e63211e,9e20a244), -S(367ef258,b279f923,a18215b7,67d396e4,c6bc874d,2be6b369,b01afffa,2e041741,bd961242,2452eddb,33831dcf,fb3a0273,30ef141f,6db77d91,5bec2ecb,553b6e6c), -S(d89f40c4,f752cff4,5bae5762,37f5096e,f27d46d0,d934d4de,c3011a28,59464e8e,9d32661e,e2319d6,f6427ea,a3014b5,cf98306c,666c4a9e,970dba2e,65e04886), -S(ef6ff862,1d84c5d5,22e490f4,db21181f,a17bafea,3e097868,4f1f0215,759772b9,ae006f11,aa85db2d,3624cf51,ae319ad2,8b4970e7,eac03301,1eb15db8,dc59d62b), -S(8b0a1b1b,d476bbfb,6da1d071,68d3a988,3b49802f,8ffa04a3,bbba1313,17c67a00,d8c74ae5,65c38597,8d9fda2e,dff6b932,1512e40b,ec5b62e2,59d4d81c,9b657b55), -S(9aa9250f,12ffde38,21384434,849d7eb7,bcafbae5,9a3b861f,68a3addb,d75d3715,19b4b1a8,8d8bfeee,38b54564,30d5f73e,ed0365fe,49092d4a,2f52fa12,b65e3ac7), -S(aaccc00f,55e96f0c,e66d9b43,12f9abd2,6772d8b4,30a6c62,edd2aab4,97acbc22,5af203cf,97d11147,82374056,f012f5f9,2825476a,820dce2e,6e1c4b33,cef5337c), -S(43c34546,2836b544,ddd6e432,6aa19b4a,9de7fdfb,86f43cae,ce98ce7c,32b1ccaf,dd518249,f1fbc1c7,1f905860,17a6f60b,15be97d4,18c66d42,f4f9adcd,d722c096), -S(9a38eb25,935441ab,8983097a,d58c821f,d784f091,5f85dc26,3f0c020b,b80c39a0,d8e6dc57,41e4ba5c,576179e8,9a6dcb4a,bd7178c6,13a1100b,e2bd731b,f3e819e2), -S(6b10527,204a4f7c,e8afcacc,fe771634,376f18da,f12774e,50f23a90,9efe0223,b443a451,529b4208,c8c98904,f5eb2ee,2e2ede2d,80ca50c5,aa29b95a,714181a), -S(1a88fecc,71d7550a,abf7faf0,8e884e95,835f6dc8,1815d2d7,7dab66ea,b238d6b2,82cf6711,1dd38ff,d0daebbc,ea2c064b,17b6b21d,34804f93,4a037936,9edec692), -S(a6b1751,f30507fe,5927b6d4,a92ebbbd,77358c02,9b750d05,a56e4d41,efb99144,ccf7c048,a2a0983d,fdcccfd,a071b80,e8035866,c479ea3a,3bbe7c80,12dfd618), -S(e186601e,8b545292,f23ae7fa,4cadc80f,1fcaa1a3,430ddec6,cfd2af47,c835cdf9,fd471f16,7c3683c9,2e5fc0c2,89b646a5,c8ebda6d,5b6da213,d862c3f6,2c292e9c), -S(91b3935,d8ce2b80,c179ee0b,87850140,4c418c7f,7cf94e4a,64b9fc9c,e396a093,45a5043b,8184546c,9083982f,550807d7,d61fe677,ce73ef21,9b3aa573,97c4eca1), -S(3fbe61fd,2a387654,dfc428e7,dac09e91,5e1ae7d6,d3794288,743f2535,20858ef5,206fd9a0,e3265118,e0a6475c,4df87e43,cc7c8898,59d8aa08,23b6dfff,b68b34d7), -S(31a35020,697d9d52,55476289,ce4fcbdc,4e1e0690,c2c36d1b,a4f4640f,e4c5ba18,91f660f9,159d463a,857f08ad,fc3c5ddd,804507c5,92f73de4,2ee44555,da538553), -S(7dc6b83a,10f26e71,e12c0bd,7ebcccc6,61b4394a,68f576fe,bfca1c23,256e8aa2,b4796977,bd386b98,f3e2fa8e,798b6548,fae52a80,40bb12ea,7e6ad675,64fc8736), -S(67a9c3ff,9c7b99b2,5318ff9e,2b85ee23,ec244655,8042ea8b,d880e23e,7d3ce221,a7bcbbbb,895ca7b1,847a43fa,98809ce4,98016123,bbb3c099,7d34debd,cb023f8d), -S(36602997,eba2c6c5,aab4cb65,8d4efd46,65ab3965,f643ff66,831646dc,f6443bf3,c82d0e80,ef775f9c,7ec7862a,e3158556,a57038d,e6850dd1,e349629c,2546239), -S(9eb9244b,299bfd76,f63bb140,ae2f42a1,4af1e072,83f8259f,6478ac03,d411df24,e43f91da,13c2ba21,a9d17d2f,7a8a629d,9051346,93a6552a,538d590,9d2bdd38), -S(ba4450fa,27d57993,3d949a1a,66013906,7d1a9716,6794993d,e45d9426,b4bfc5ed,8e3f3b9b,d8cb8210,7a5ae2af,92b96259,b73633f,6528ac04,20c3e101,6bb6d8a8), -S(e6d5335f,b67abd36,2712c7fe,575ee769,53d488b,236e8589,5664fb04,7f385248,9e255154,e070a5bb,e98e97f6,281fb999,a75e68ea,7681fdf6,fea093bd,919aa5a4), -S(63c099a9,300a331a,3bc4348a,a373e514,c84a810e,1ea8a8d1,4ac8d7cb,818eb534,ed7d4029,3cc4a086,b1d40c24,6086109,a02dbcb5,a864777,27939024,6fd6bf91), -S(7088617f,66cd93f,8130eaeb,874c3f77,3bcb0daa,78923b70,a65512a2,992554dc,5a3ff995,3c712066,291ac4a2,dfc2573e,1d0aed56,75ef526b,b15f61b0,d20f8156), -S(cc354aaf,746d756b,9387730f,2f12b999,4fcd815c,6d25cdab,2e1185aa,4aa639b3,fb1dead9,4fd76859,1aac8d79,5c337924,dc155fbe,5cd5c953,4d55ee31,f6d284a6), -S(e7e47c3a,e2bf4307,7f33ec3d,ac1ae2a7,5c669e61,e248f588,590cfe07,3e2186e0,46e9c4d5,4429fdcf,5efb375e,18f46cc8,3fa7a403,6013777f,e450e228,aebd4cd0), -S(c6ed5e63,28ec31b1,37041108,42d4ac23,fbb883bb,349d88db,1d747cf7,325fe9cc,21b8bfa4,b62807cf,d6cd11ed,a38084d5,7bb068d4,9f0dd30e,f3f431e2,b57022e4), -S(331924c7,50b3417e,48e279ff,6ed7f3dc,ba2e121e,9f69f8fb,e64093b6,c38a8cc6,357086be,e4cc0fe7,d45a49fe,41d004ce,80466165,316164ab,3b171f03,b9a7841f), -S(b4319cc9,f3e0d3b,313626ae,5385796b,c49b300c,88ba4553,dec0aa4a,77829372,b8f82bb6,6590afd4,48501f,63de3a5d,8f84edea,35c1ee44,88d6333e,f522a808), -S(da433d5e,11ceccc0,abc5c762,6ce7bab4,2e89b221,f785c409,282de545,f3fceb19,1b67242c,de57efcf,e214423b,506a1ade,718803d2,6dd84d88,97b18ede,590a2fcb)}, -{S(ebae7464,ece277b8,309d056c,cf3775e2,11a77aa,81c316a4,b6b7b953,6f90f539,62a4d6a2,95fdd811,f2051715,322f17e5,1753c9d0,835ef9a0,3e8dc9f5,c69bda31), -S(5b20700c,1af63394,a3e4cadb,b0ea682e,19cf495a,b908418a,d41f4c6c,ea4477f0,8435d15e,34b03a22,ca89c73d,326c2f88,142d2e23,8964ef6d,99287125,79738f78), -S(b2f25f91,138b974b,561328c0,92f50fdf,8a694004,fd4879d0,12a4a6cc,c8059d1d,d9ec0b2d,b8e81b2,f6feaf55,9776ff78,cda3401b,47826de0,ca06e579,9d866c09), -S(64e79790,7783d6fb,321eb785,acdeb2ff,4628270,fec3342c,527c8db0,a34c516e,c0c4da5d,abf3da9c,a8613f82,ca28e84,a1a18376,c9967c08,aaf70bea,7a2f34c2), -S(a50cae84,a08f4f32,4984853a,d4c6bdaf,77eaa788,9cb8fe95,72fd56e,9078ee73,120ecbf,76e47b38,503067c8,36853003,60ed261a,40fdf440,161ef2cd,19786b93), -S(76ff3ac8,80a451a9,6741fc70,82bc4c82,7bd51c08,95eea8c8,b422b8a9,96ba4794,25555d71,d4313a60,b189a154,58e0a40,c643c204,277334e,966e2abd,3a23f6c3), -S(307e5caa,8b708760,3d9f845b,b78f4f10,72c49c10,9747f91d,192f8d6e,70c0f4be,f5992f76,37167e1d,55cd31a6,1cdb4756,85eb1503,34fb6009,e0240a18,fa8302b8), -S(d8e62e47,b28fd165,4d420137,884dcf21,c10cb159,d9885843,da34b0d9,d09b2758,675c75b4,b903ad28,2055a71b,2c470e2b,1dce69bf,ecf160cf,3a027de2,55b723a9), -S(ec5639c7,73dac23d,3008dabf,732dc005,3154703d,26ee3bbc,7689286e,4a73e39f,aaa5ea4a,2cf5c23d,57cdd0d8,8accbbf9,9fd2c213,97bb45f8,83547876,3aab1248), -S(3d928ee3,2065557a,27722f08,5202f48f,40917ed6,c7ac1963,2a122226,8b0cb9df,ece112a4,e7a05ad6,17c2fd83,76f89102,9eb94eb0,930fb23c,a342d7f1,f021a0c7), -S(616228a5,cc6c3a92,cd694cec,4b2b8574,5dfffa90,b2a36d8f,32eaa6cc,2530de51,50d8d140,4d506a78,700f8e82,967b36a5,1b4de644,a8e22271,d509c8d2,4adf3148), -S(6f85f308,e847b145,c13a07be,bebdd4ba,6c138939,6afd8670,733f44a8,969406d0,864bcde1,be36c9c7,b7e04ef8,cd2366e2,b3c22902,5ee7efce,d005ef5b,ff7dae2b), -S(f3d1ecc3,53a82621,1bd78f0f,aa029076,c6ca779,9bdc54b2,128fa3d2,aec00c6d,75aa0cf9,fd0b7bed,19183e34,58142f66,c94a5aa9,3915435e,ae51c1fe,96625ccd), -S(a5918de3,f18cd8d1,2a234f9f,3a19fcaa,2d83671d,ad566f16,8aea2b1f,b9de41b0,c515dda6,43c0f6c8,d8fea16,5d595917,16b7f521,43d3b941,f28585ed,8a49c06c), -S(3c49e2ef,1d2d3464,81e05fa0,33366609,1615ebcf,535f68,be257f35,7bd91592,57901e0a,c8af3a31,aa404987,72c903fd,175c9b00,5c7458ee,ed667f11,57754132), -S(6c45ff2,c0c30320,83c343e6,dc80b4f7,bb64502a,52f412ff,ada521d4,a544a9f0,e9936037,f1e641eb,1cd6f801,a25271d3,cffe67d,c9bd7162,babf9855,9628a9a8), -S(66df5d95,acdf4260,ee0e465c,e3916d79,395df522,aa086aeb,6c283bb7,18296d46,cb1f3deb,8aea0337,625f46dd,903416d1,5647be91,1633c4c0,cf0e629a,413476fc), -S(428bbba5,ef351762,9eee4059,a3339213,40c7fee2,5ccb051c,88d75e53,ba618858,ef18809c,28227ccc,115876df,b3f378cd,374c0670,2c658501,7990e767,922c3999), -S(e8993820,d782657,ed8badc2,d515e360,df336730,860ef49e,65ca58dd,1a385815,feb41189,16c7e8f6,53c7f5a6,5fd7b6be,7a029814,149c4645,847073be,770959de), -S(2b77e42a,63502244,d6c7d1be,54b7857,9e2742d2,7143d689,fa3f70a3,5986ccf1,721e9da8,bee88ad4,2155dc9a,28be505,86648378,1d6af5b1,382cd47d,771e6428), -S(acffce3a,ed6beea3,2ad71633,21e1ca53,6f69ce76,fb5cd394,9d9dcc14,bbcee96,5384c97d,eac946c0,afc85b54,f3a56b79,fe263bff,63e1894c,6d52ef1b,9b456602), -S(e13d8d4b,25bece8d,90a008e4,c004824e,223b06b,7cf65ebd,1215e910,2e67b639,3e92b1f,14cbee57,9640b377,6ed5938f,9aee0e11,b139a678,3f207cf4,6dd7e20b), -S(d8f356d9,d2498eaa,b3fa12a,cb64562b,dff3e270,c7809a31,25a9ae65,9cb1f3c5,a5403cda,2d499a7c,7402b57c,c9f99e3,64f5085a,91fd8cfd,8a67c7a8,dbce04fb), -S(350062b5,22fb5d0a,8c79a5db,29e92216,79b9fbc6,3e1f95ca,e7d087f3,fedffc49,74cacf57,5e79c85b,d7e77a40,796e8750,a3ca57f2,a47cce8f,3d2de02d,b014df0b), -S(c159e630,9ab23135,58ebfb6b,22edaf93,eac8e16,77cd9f3b,1cd9492,20bf8e54,99244263,53f32608,831c6d74,da51d61,c344defe,f4c1e401,6a3db44b,4c57f4ae), -S(9e568b70,36a2daa2,fe7a3a52,49c56eb8,3fe4afa2,decebd60,c6c3245f,17bc6a13,b6643644,274eab9f,5e83c598,14978681,17c5a078,765156ae,3cb65fd3,830e06ae), -S(9bee7471,6b6c1ff5,62c1bc36,57a65de3,99a91d72,115703f4,4c3819a1,87828478,bb23a3da,ed34028a,7d39a7ed,fe2e23b,73e085a2,d6c2e51a,ef2a2076,a7c902ad), -S(c430c044,91228a7a,ea835698,ecf0f552,9aeef469,a36305cb,52902ccd,1c897473,40d0ee56,61cca82,80d11da,bffe97c4,f10c93aa,5e07224c,154b666e,bcd58c74), -S(2be073f6,b294a01b,eda0b0db,6832e4bc,23ef3889,7a859853,5ee726ef,ae0f15b1,6153f846,349c2a98,26008065,8be2a7d8,311a5e70,cc310ff8,7935a901,8d575813), -S(2934de46,a6d921f8,720567e6,b46e6362,36a7ed53,483b13ed,20958452,3225accd,5979698,26927cd7,abfe4c57,c53fc72a,48b71679,174c749d,aecdb057,e6a2d961), -S(4e9991b,92fa8c4e,4e8efe45,66966073,319e80d3,a54d4b7a,b61cfcc4,7ddaa5d5,9d03ea22,21d4d80e,261952e2,73f6a8cf,c31f6091,e5aa0a8f,2281ffbf,1345df9e), -S(ff3d6136,ffac5b0c,bfc6c5c0,c30dc01a,7ea3d56c,20bd3103,b178e3d3,ae180068,eccdc641,7b1bfff1,bf2fc8d3,2269523e,ab89890d,bffe0a19,8f594490,e7739bb8)} -#else -# error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build. -#endif -}; -#undef S diff --git a/external/secp256k1/src/precomputed_ecmult_gen.h b/external/secp256k1/src/precomputed_ecmult_gen.h deleted file mode 100644 index 283738a5ce..0000000000 --- a/external/secp256k1/src/precomputed_ecmult_gen.h +++ /dev/null @@ -1,26 +0,0 @@ -/********************************************************************************* - * Copyright (c) 2013, 2014, 2015, 2021 Thomas Daede, Cory Fields, Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php. * - *********************************************************************************/ - -#ifndef SECP256K1_PRECOMPUTED_ECMULT_GEN_H -#define SECP256K1_PRECOMPUTED_ECMULT_GEN_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "group.h" -#include "ecmult_gen.h" -#ifdef EXHAUSTIVE_TEST_ORDER -static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; -#else -extern const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; -#endif /* defined(EXHAUSTIVE_TEST_ORDER) */ - -#ifdef __cplusplus -} -#endif - -#endif /* SECP256K1_PRECOMPUTED_ECMULT_GEN_H */ diff --git a/external/secp256k1/src/scalar.h b/external/secp256k1/src/scalar.h deleted file mode 100644 index 70f49b1cf2..0000000000 --- a/external/secp256k1/src/scalar.h +++ /dev/null @@ -1,105 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCALAR_H -#define SECP256K1_SCALAR_H - -#include "util.h" - -#if defined(EXHAUSTIVE_TEST_ORDER) -#include "scalar_low.h" -#elif defined(SECP256K1_WIDEMUL_INT128) -#include "scalar_4x64.h" -#elif defined(SECP256K1_WIDEMUL_INT64) -#include "scalar_8x32.h" -#else -#error "Please select wide multiplication implementation" -#endif - -/** Clear a scalar to prevent the leak of sensitive data. */ -static void secp256k1_scalar_clear(secp256k1_scalar *r); - -/** Access bits (1 < count <= 32) from a scalar. All requested bits must belong to the same 32-bit limb. */ -static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count); - -/** Access bits (1 < count <= 32) from a scalar. offset + count must be < 256. Not constant time in offset and count. */ -static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); - -/** Set a scalar from a big endian byte array. The scalar will be reduced modulo group order `n`. - * In: bin: pointer to a 32-byte array. - * Out: r: scalar to be set. - * overflow: non-zero if the scalar was bigger or equal to `n` before reduction, zero otherwise (can be NULL). - */ -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); - -/** Set a scalar from a big endian byte array and returns 1 if it is a valid - * seckey and 0 otherwise. */ -static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned char *bin); - -/** Set a scalar to an unsigned integer. */ -static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v); - -/** Convert a scalar to a byte array. */ -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a); - -/** Add two scalars together (modulo the group order). Returns whether it overflowed. */ -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); - -/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); - -/** Multiply two scalars (modulo the group order). */ -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); - -/** Compute the inverse of a scalar (modulo the group order). */ -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ -static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Compute the complement of a scalar (modulo the group order). */ -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Multiply a scalar with the multiplicative inverse of 2. */ -static void secp256k1_scalar_half(secp256k1_scalar *r, const secp256k1_scalar *a); - -/** Check whether a scalar equals zero. */ -static int secp256k1_scalar_is_zero(const secp256k1_scalar *a); - -/** Check whether a scalar equals one. */ -static int secp256k1_scalar_is_one(const secp256k1_scalar *a); - -/** Check whether a scalar, considered as an nonnegative integer, is even. */ -static int secp256k1_scalar_is_even(const secp256k1_scalar *a); - -/** Check whether a scalar is higher than the group order divided by 2. */ -static int secp256k1_scalar_is_high(const secp256k1_scalar *a); - -/** Conditionally negate a number, in constant time. - * Returns -1 if the number was negated, 1 otherwise */ -static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); - -/** Compare two scalars. */ -static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); - -/** Find r1 and r2 such that r1+r2*2^128 = k. */ -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k); -/** Find r1 and r2 such that r1+r2*lambda = k, where r1 and r2 or their - * negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). It is - * required that r1, r2, and k all point to different objects. */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k); - -/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ -static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ -static void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag); - -/** Check invariants on a scalar (no-op unless VERIFY is enabled). */ -static void secp256k1_scalar_verify(const secp256k1_scalar *r); -#define SECP256K1_SCALAR_VERIFY(r) secp256k1_scalar_verify(r) - -#endif /* SECP256K1_SCALAR_H */ diff --git a/external/secp256k1/src/scalar_4x64.h b/external/secp256k1/src/scalar_4x64.h deleted file mode 100644 index 700964291e..0000000000 --- a/external/secp256k1/src/scalar_4x64.h +++ /dev/null @@ -1,19 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCALAR_REPR_H -#define SECP256K1_SCALAR_REPR_H - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef struct { - uint64_t d[4]; -} secp256k1_scalar; - -#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} - -#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/external/secp256k1/src/scalar_4x64_impl.h b/external/secp256k1/src/scalar_4x64_impl.h deleted file mode 100644 index 807b9b70ab..0000000000 --- a/external/secp256k1/src/scalar_4x64_impl.h +++ /dev/null @@ -1,1000 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCALAR_REPR_IMPL_H -#define SECP256K1_SCALAR_REPR_IMPL_H - -#include "checkmem.h" -#include "int128.h" -#include "modinv64_impl.h" -#include "util.h" - -/* Limbs of the secp256k1 order. */ -#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) -#define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL) -#define SECP256K1_N_2 ((uint64_t)0xFFFFFFFFFFFFFFFEULL) -#define SECP256K1_N_3 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) - -/* Limbs of 2^256 minus the secp256k1 order. */ -#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) -#define SECP256K1_N_C_1 (~SECP256K1_N_1) -#define SECP256K1_N_C_2 (1) - -/* Limbs of half the secp256k1 order. */ -#define SECP256K1_N_H_0 ((uint64_t)0xDFE92F46681B20A0ULL) -#define SECP256K1_N_H_1 ((uint64_t)0x5D576E7357A4501DULL) -#define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) -#define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) - -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { - r->d[0] = v; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; - - SECP256K1_SCALAR_VERIFY(r); -} - -SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - SECP256K1_SCALAR_VERIFY(a); - VERIFY_CHECK(count > 0 && count <= 32); - VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); - - return (a->d[offset >> 6] >> (offset & 0x3F)) & (0xFFFFFFFF >> (32 - count)); -} - -SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - SECP256K1_SCALAR_VERIFY(a); - VERIFY_CHECK(count > 0 && count <= 32); - VERIFY_CHECK(offset + count <= 256); - - if ((offset + count - 1) >> 6 == offset >> 6) { - return secp256k1_scalar_get_bits_limb32(a, offset, count); - } else { - VERIFY_CHECK((offset >> 6) + 1 < 4); - return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & (0xFFFFFFFF >> (32 - count)); - } -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ - no |= (a->d[2] < SECP256K1_N_2); - yes |= (a->d[2] > SECP256K1_N_2) & ~no; - no |= (a->d[1] < SECP256K1_N_1); - yes |= (a->d[1] > SECP256K1_N_1) & ~no; - yes |= (a->d[0] >= SECP256K1_N_0) & ~no; - return yes; -} - -SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) { - secp256k1_uint128 t; - VERIFY_CHECK(overflow <= 1); - - secp256k1_u128_from_u64(&t, r->d[0]); - secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_0); - r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[1]); - secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_1); - r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[2]); - secp256k1_u128_accum_u64(&t, overflow * SECP256K1_N_C_2); - r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[3]); - r->d[3] = secp256k1_u128_to_u64(&t); - - SECP256K1_SCALAR_VERIFY(r); - return overflow; -} - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - int overflow; - secp256k1_uint128 t; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - secp256k1_u128_from_u64(&t, a->d[0]); - secp256k1_u128_accum_u64(&t, b->d[0]); - r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, a->d[1]); - secp256k1_u128_accum_u64(&t, b->d[1]); - r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, a->d[2]); - secp256k1_u128_accum_u64(&t, b->d[2]); - r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, a->d[3]); - secp256k1_u128_accum_u64(&t, b->d[3]); - r->d[3] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - overflow = secp256k1_u128_to_u64(&t) + secp256k1_scalar_check_overflow(r); - VERIFY_CHECK(overflow == 0 || overflow == 1); - secp256k1_scalar_reduce(r, overflow); - - SECP256K1_SCALAR_VERIFY(r); - return overflow; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - secp256k1_uint128 t; - volatile int vflag = flag; - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(bit < 256); - - bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */ - secp256k1_u128_from_u64(&t, r->d[0]); - secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); - r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[1]); - secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); - r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[2]); - secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); - r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[3]); - secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); - r->d[3] = secp256k1_u128_to_u64(&t); - - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(secp256k1_u128_hi_u64(&t) == 0); -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - int over; - r->d[0] = secp256k1_read_be64(&b32[24]); - r->d[1] = secp256k1_read_be64(&b32[16]); - r->d[2] = secp256k1_read_be64(&b32[8]); - r->d[3] = secp256k1_read_be64(&b32[0]); - over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); - if (overflow) { - *overflow = over; - } - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - SECP256K1_SCALAR_VERIFY(a); - - secp256k1_write_be64(&bin[0], a->d[3]); - secp256k1_write_be64(&bin[8], a->d[2]); - secp256k1_write_be64(&bin[16], a->d[1]); - secp256k1_write_be64(&bin[24], a->d[0]); -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0); - secp256k1_uint128 t; - SECP256K1_SCALAR_VERIFY(a); - - secp256k1_u128_from_u64(&t, ~a->d[0]); - secp256k1_u128_accum_u64(&t, SECP256K1_N_0 + 1); - r->d[0] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, ~a->d[1]); - secp256k1_u128_accum_u64(&t, SECP256K1_N_1); - r->d[1] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, ~a->d[2]); - secp256k1_u128_accum_u64(&t, SECP256K1_N_2); - r->d[2] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, ~a->d[3]); - secp256k1_u128_accum_u64(&t, SECP256K1_N_3); - r->d[3] = secp256k1_u128_to_u64(&t) & nonzero; - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_half(secp256k1_scalar *r, const secp256k1_scalar *a) { - /* Writing `/` for field division and `//` for integer division, we compute - * - * a/2 = (a - (a&1))/2 + (a&1)/2 - * = (a >> 1) + (a&1 ? 1/2 : 0) - * = (a >> 1) + (a&1 ? n//2+1 : 0), - * - * where n is the group order and in the last equality we have used 1/2 = n//2+1 (mod n). - * For n//2, we have the constants SECP256K1_N_H_0, ... - * - * This sum does not overflow. The most extreme case is a = -2, the largest odd scalar. Here: - * - the left summand is: a >> 1 = (a - a&1)/2 = (n-2-1)//2 = (n-3)//2 - * - the right summand is: a&1 ? n//2+1 : 0 = n//2+1 = (n-1)//2 + 2//2 = (n+1)//2 - * Together they sum to (n-3)//2 + (n+1)//2 = (2n-2)//2 = n - 1, which is less than n. - */ - uint64_t mask = -(uint64_t)(a->d[0] & 1U); - secp256k1_uint128 t; - SECP256K1_SCALAR_VERIFY(a); - - secp256k1_u128_from_u64(&t, (a->d[0] >> 1) | (a->d[1] << 63)); - secp256k1_u128_accum_u64(&t, (SECP256K1_N_H_0 + 1U) & mask); - r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, (a->d[1] >> 1) | (a->d[2] << 63)); - secp256k1_u128_accum_u64(&t, SECP256K1_N_H_1 & mask); - r->d[1] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, (a->d[2] >> 1) | (a->d[3] << 63)); - secp256k1_u128_accum_u64(&t, SECP256K1_N_H_2 & mask); - r->d[2] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64); - r->d[3] = secp256k1_u128_to_u64(&t) + (a->d[3] >> 1) + (SECP256K1_N_H_3 & mask); -#ifdef VERIFY - /* The line above only computed the bottom 64 bits of r->d[3]; redo the computation - * in full 128 bits to make sure the top 64 bits are indeed zero. */ - secp256k1_u128_accum_u64(&t, a->d[3] >> 1); - secp256k1_u128_accum_u64(&t, SECP256K1_N_H_3 & mask); - secp256k1_u128_rshift(&t, 64); - VERIFY_CHECK(secp256k1_u128_to_u64(&t) == 0); - - SECP256K1_SCALAR_VERIFY(r); -#endif -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - SECP256K1_SCALAR_VERIFY(a); - - no |= (a->d[3] < SECP256K1_N_H_3); - yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; - no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */ - no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; - yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; - return yes; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - /* If we are flag = 0, mask = 00...00 and this is a no-op; - * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ - volatile int vflag = flag; - uint64_t mask = -vflag; - uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1; - secp256k1_uint128 t; - SECP256K1_SCALAR_VERIFY(r); - - secp256k1_u128_from_u64(&t, r->d[0] ^ mask); - secp256k1_u128_accum_u64(&t, (SECP256K1_N_0 + 1) & mask); - r->d[0] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[1] ^ mask); - secp256k1_u128_accum_u64(&t, SECP256K1_N_1 & mask); - r->d[1] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[2] ^ mask); - secp256k1_u128_accum_u64(&t, SECP256K1_N_2 & mask); - r->d[2] = secp256k1_u128_to_u64(&t) & nonzero; secp256k1_u128_rshift(&t, 64); - secp256k1_u128_accum_u64(&t, r->d[3] ^ mask); - secp256k1_u128_accum_u64(&t, SECP256K1_N_3 & mask); - r->d[3] = secp256k1_u128_to_u64(&t) & nonzero; - - SECP256K1_SCALAR_VERIFY(r); - return 2 * (mask == 0) - 1; -} - -/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ - -/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd(a,b) { \ - uint64_t tl, th; \ - { \ - secp256k1_uint128 t; \ - secp256k1_u128_mul(&t, a, b); \ - th = secp256k1_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = secp256k1_u128_to_u64(&t); \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \ - c1 += th; /* overflow is handled on the next line */ \ - c2 += (c1 < th); /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ -} - -/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ -#define muladd_fast(a,b) { \ - uint64_t tl, th; \ - { \ - secp256k1_uint128 t; \ - secp256k1_u128_mul(&t, a, b); \ - th = secp256k1_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = secp256k1_u128_to_u64(&t); \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \ - c1 += th; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK(c1 >= th); \ -} - -/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define sumadd(a) { \ - unsigned int over; \ - c0 += (a); /* overflow is handled on the next line */ \ - over = (c0 < (a)); \ - c1 += over; /* overflow is handled on the next line */ \ - c2 += (c1 < over); /* never overflows by contract */ \ -} - -/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ -#define sumadd_fast(a) { \ - c0 += (a); /* overflow is handled on the next line */ \ - c1 += (c0 < (a)); /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ - VERIFY_CHECK(c2 == 0); \ -} - -/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */ -#define extract(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = c2; \ - c2 = 0; \ -} - -/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. c2 is required to be zero. */ -#define extract_fast(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = 0; \ - VERIFY_CHECK(c2 == 0); \ -} - -static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) { -#ifdef USE_ASM_X86_64 - /* Reduce 512 bits into 385. */ - uint64_t m0, m1, m2, m3, m4, m5, m6; - uint64_t p0, p1, p2, p3, p4; - uint64_t c; - - __asm__ __volatile__( - /* Preload. */ - "movq 32(%%rsi), %%r11\n" - "movq 40(%%rsi), %%r12\n" - "movq 48(%%rsi), %%r13\n" - "movq 56(%%rsi), %%r14\n" - /* Initialize r8,r9,r10 */ - "movq 0(%%rsi), %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9) += n0 * c0 */ - "movq %8, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* extract m0 */ - "movq %%r8, %q0\n" - "xorq %%r8, %%r8\n" - /* (r9,r10) += l1 */ - "addq 8(%%rsi), %%r9\n" - "adcq $0, %%r10\n" - /* (r9,r10,r8) += n1 * c0 */ - "movq %8, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += n0 * c1 */ - "movq %9, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* extract m1 */ - "movq %%r9, %q1\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += l2 */ - "addq 16(%%rsi), %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n2 * c0 */ - "movq %8, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n1 * c1 */ - "movq %9, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += n0 */ - "addq %%r11, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* extract m2 */ - "movq %%r10, %q2\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += l3 */ - "addq 24(%%rsi), %%r8\n" - "adcq $0, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n3 * c0 */ - "movq %8, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n2 * c1 */ - "movq %9, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += n1 */ - "addq %%r12, %%r8\n" - "adcq $0, %%r9\n" - "adcq $0, %%r10\n" - /* extract m3 */ - "movq %%r8, %q3\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += n3 * c1 */ - "movq %9, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += n2 */ - "addq %%r13, %%r9\n" - "adcq $0, %%r10\n" - "adcq $0, %%r8\n" - /* extract m4 */ - "movq %%r9, %q4\n" - /* (r10,r8) += n3 */ - "addq %%r14, %%r10\n" - "adcq $0, %%r8\n" - /* extract m5 */ - "movq %%r10, %q5\n" - /* extract m6 */ - "movq %%r8, %q6\n" - : "=&g"(m0), "=&g"(m1), "=&g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6) - : "S"(l), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc"); - - SECP256K1_CHECKMEM_MSAN_DEFINE(&m0, sizeof(m0)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&m1, sizeof(m1)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&m2, sizeof(m2)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&m3, sizeof(m3)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&m4, sizeof(m4)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&m5, sizeof(m5)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&m6, sizeof(m6)); - - /* Reduce 385 bits into 258. */ - __asm__ __volatile__( - /* Preload */ - "movq %q9, %%r11\n" - "movq %q10, %%r12\n" - "movq %q11, %%r13\n" - /* Initialize (r8,r9,r10) */ - "movq %q5, %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9) += m4 * c0 */ - "movq %12, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* extract p0 */ - "movq %%r8, %q0\n" - "xorq %%r8, %%r8\n" - /* (r9,r10) += m1 */ - "addq %q6, %%r9\n" - "adcq $0, %%r10\n" - /* (r9,r10,r8) += m5 * c0 */ - "movq %12, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += m4 * c1 */ - "movq %13, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* extract p1 */ - "movq %%r9, %q1\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += m2 */ - "addq %q7, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m6 * c0 */ - "movq %12, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m5 * c1 */ - "movq %13, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += m4 */ - "addq %%r11, %%r10\n" - "adcq $0, %%r8\n" - "adcq $0, %%r9\n" - /* extract p2 */ - "movq %%r10, %q2\n" - /* (r8,r9) += m3 */ - "addq %q8, %%r8\n" - "adcq $0, %%r9\n" - /* (r8,r9) += m6 * c1 */ - "movq %13, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* (r8,r9) += m5 */ - "addq %%r12, %%r8\n" - "adcq $0, %%r9\n" - /* extract p3 */ - "movq %%r8, %q3\n" - /* (r9) += m6 */ - "addq %%r13, %%r9\n" - /* extract p4 */ - "movq %%r9, %q4\n" - : "=&g"(p0), "=&g"(p1), "=&g"(p2), "=g"(p3), "=g"(p4) - : "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc"); - - SECP256K1_CHECKMEM_MSAN_DEFINE(&p0, sizeof(p0)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&p1, sizeof(p1)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&p2, sizeof(p2)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&p3, sizeof(p3)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&p4, sizeof(p4)); - - /* Reduce 258 bits into 256. */ - __asm__ __volatile__( - /* Preload */ - "movq %q5, %%r10\n" - /* (rax,rdx) = p4 * c0 */ - "movq %7, %%rax\n" - "mulq %%r10\n" - /* (rax,rdx) += p0 */ - "addq %q1, %%rax\n" - "adcq $0, %%rdx\n" - /* extract r0 */ - "movq %%rax, 0(%q6)\n" - /* Move to (r8,r9) */ - "movq %%rdx, %%r8\n" - "xorq %%r9, %%r9\n" - /* (r8,r9) += p1 */ - "addq %q2, %%r8\n" - "adcq $0, %%r9\n" - /* (r8,r9) += p4 * c1 */ - "movq %8, %%rax\n" - "mulq %%r10\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - /* Extract r1 */ - "movq %%r8, 8(%q6)\n" - "xorq %%r8, %%r8\n" - /* (r9,r8) += p4 */ - "addq %%r10, %%r9\n" - "adcq $0, %%r8\n" - /* (r9,r8) += p2 */ - "addq %q3, %%r9\n" - "adcq $0, %%r8\n" - /* Extract r2 */ - "movq %%r9, 16(%q6)\n" - "xorq %%r9, %%r9\n" - /* (r8,r9) += p3 */ - "addq %q4, %%r8\n" - "adcq $0, %%r9\n" - /* Extract r3 */ - "movq %%r8, 24(%q6)\n" - /* Extract c */ - "movq %%r9, %q0\n" - : "=g"(c) - : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) - : "rax", "rdx", "r8", "r9", "r10", "cc", "memory"); - - SECP256K1_CHECKMEM_MSAN_DEFINE(r, sizeof(*r)); - SECP256K1_CHECKMEM_MSAN_DEFINE(&c, sizeof(c)); - -#else - secp256k1_uint128 c128; - uint64_t c, c0, c1, c2; - uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7]; - uint64_t m0, m1, m2, m3, m4, m5; - uint32_t m6; - uint64_t p0, p1, p2, p3; - uint32_t p4; - - /* Reduce 512 bits into 385. */ - /* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */ - c0 = l[0]; c1 = 0; c2 = 0; - muladd_fast(n0, SECP256K1_N_C_0); - extract_fast(m0); - sumadd_fast(l[1]); - muladd(n1, SECP256K1_N_C_0); - muladd(n0, SECP256K1_N_C_1); - extract(m1); - sumadd(l[2]); - muladd(n2, SECP256K1_N_C_0); - muladd(n1, SECP256K1_N_C_1); - sumadd(n0); - extract(m2); - sumadd(l[3]); - muladd(n3, SECP256K1_N_C_0); - muladd(n2, SECP256K1_N_C_1); - sumadd(n1); - extract(m3); - muladd(n3, SECP256K1_N_C_1); - sumadd(n2); - extract(m4); - sumadd_fast(n3); - extract_fast(m5); - VERIFY_CHECK(c0 <= 1); - m6 = c0; - - /* Reduce 385 bits into 258. */ - /* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */ - c0 = m0; c1 = 0; c2 = 0; - muladd_fast(m4, SECP256K1_N_C_0); - extract_fast(p0); - sumadd_fast(m1); - muladd(m5, SECP256K1_N_C_0); - muladd(m4, SECP256K1_N_C_1); - extract(p1); - sumadd(m2); - muladd(m6, SECP256K1_N_C_0); - muladd(m5, SECP256K1_N_C_1); - sumadd(m4); - extract(p2); - sumadd_fast(m3); - muladd_fast(m6, SECP256K1_N_C_1); - sumadd_fast(m5); - extract_fast(p3); - p4 = c0 + m6; - VERIFY_CHECK(p4 <= 2); - - /* Reduce 258 bits into 256. */ - /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */ - secp256k1_u128_from_u64(&c128, p0); - secp256k1_u128_accum_mul(&c128, SECP256K1_N_C_0, p4); - r->d[0] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64); - secp256k1_u128_accum_u64(&c128, p1); - secp256k1_u128_accum_mul(&c128, SECP256K1_N_C_1, p4); - r->d[1] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64); - secp256k1_u128_accum_u64(&c128, p2); - secp256k1_u128_accum_u64(&c128, p4); - r->d[2] = secp256k1_u128_to_u64(&c128); secp256k1_u128_rshift(&c128, 64); - secp256k1_u128_accum_u64(&c128, p3); - r->d[3] = secp256k1_u128_to_u64(&c128); - c = secp256k1_u128_hi_u64(&c128); -#endif - - /* Final reduction of r. */ - secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); -} - -static void secp256k1_scalar_mul_512(uint64_t *l8, const secp256k1_scalar *a, const secp256k1_scalar *b) { -#ifdef USE_ASM_X86_64 - const uint64_t *pb = b->d; - __asm__ __volatile__( - /* Preload */ - "movq 0(%%rdi), %%r15\n" - "movq 8(%%rdi), %%rbx\n" - "movq 16(%%rdi), %%rcx\n" - "movq 0(%%rdx), %%r11\n" - "movq 8(%%rdx), %%r12\n" - "movq 16(%%rdx), %%r13\n" - "movq 24(%%rdx), %%r14\n" - /* (rax,rdx) = a0 * b0 */ - "movq %%r15, %%rax\n" - "mulq %%r11\n" - /* Extract l8[0] */ - "movq %%rax, 0(%%rsi)\n" - /* (r8,r9,r10) = (rdx) */ - "movq %%rdx, %%r8\n" - "xorq %%r9, %%r9\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += a0 * b1 */ - "movq %%r15, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a1 * b0 */ - "movq %%rbx, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l8[1] */ - "movq %%r8, 8(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += a0 * b2 */ - "movq %%r15, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a1 * b1 */ - "movq %%rbx, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a2 * b0 */ - "movq %%rcx, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l8[2] */ - "movq %%r9, 16(%%rsi)\n" - "xorq %%r9, %%r9\n" - /* (r10,r8,r9) += a0 * b3 */ - "movq %%r15, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* Preload a3 */ - "movq 24(%%rdi), %%r15\n" - /* (r10,r8,r9) += a1 * b2 */ - "movq %%rbx, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += a2 * b1 */ - "movq %%rcx, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* (r10,r8,r9) += a3 * b0 */ - "movq %%r15, %%rax\n" - "mulq %%r11\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - "adcq $0, %%r9\n" - /* Extract l8[3] */ - "movq %%r10, 24(%%rsi)\n" - "xorq %%r10, %%r10\n" - /* (r8,r9,r10) += a1 * b3 */ - "movq %%rbx, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a2 * b2 */ - "movq %%rcx, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* (r8,r9,r10) += a3 * b1 */ - "movq %%r15, %%rax\n" - "mulq %%r12\n" - "addq %%rax, %%r8\n" - "adcq %%rdx, %%r9\n" - "adcq $0, %%r10\n" - /* Extract l8[4] */ - "movq %%r8, 32(%%rsi)\n" - "xorq %%r8, %%r8\n" - /* (r9,r10,r8) += a2 * b3 */ - "movq %%rcx, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* (r9,r10,r8) += a3 * b2 */ - "movq %%r15, %%rax\n" - "mulq %%r13\n" - "addq %%rax, %%r9\n" - "adcq %%rdx, %%r10\n" - "adcq $0, %%r8\n" - /* Extract l8[5] */ - "movq %%r9, 40(%%rsi)\n" - /* (r10,r8) += a3 * b3 */ - "movq %%r15, %%rax\n" - "mulq %%r14\n" - "addq %%rax, %%r10\n" - "adcq %%rdx, %%r8\n" - /* Extract l8[6] */ - "movq %%r10, 48(%%rsi)\n" - /* Extract l8[7] */ - "movq %%r8, 56(%%rsi)\n" - : "+d"(pb) - : "S"(l8), "D"(a->d) - : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory"); - - SECP256K1_CHECKMEM_MSAN_DEFINE(l8, sizeof(*l8) * 8); - -#else - /* 160 bit accumulator. */ - uint64_t c0 = 0, c1 = 0; - uint32_t c2 = 0; - - /* l8[0..7] = a[0..3] * b[0..3]. */ - muladd_fast(a->d[0], b->d[0]); - extract_fast(l8[0]); - muladd(a->d[0], b->d[1]); - muladd(a->d[1], b->d[0]); - extract(l8[1]); - muladd(a->d[0], b->d[2]); - muladd(a->d[1], b->d[1]); - muladd(a->d[2], b->d[0]); - extract(l8[2]); - muladd(a->d[0], b->d[3]); - muladd(a->d[1], b->d[2]); - muladd(a->d[2], b->d[1]); - muladd(a->d[3], b->d[0]); - extract(l8[3]); - muladd(a->d[1], b->d[3]); - muladd(a->d[2], b->d[2]); - muladd(a->d[3], b->d[1]); - extract(l8[4]); - muladd(a->d[2], b->d[3]); - muladd(a->d[3], b->d[2]); - extract(l8[5]); - muladd_fast(a->d[3], b->d[3]); - extract_fast(l8[6]); - VERIFY_CHECK(c1 == 0); - l8[7] = c0; -#endif -} - -#undef sumadd -#undef sumadd_fast -#undef muladd -#undef muladd_fast -#undef extract -#undef extract_fast - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - uint64_t l[8]; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - secp256k1_scalar_mul_512(l, a, b); - secp256k1_scalar_reduce_512(r, l); - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) { - SECP256K1_SCALAR_VERIFY(k); - - r1->d[0] = k->d[0]; - r1->d[1] = k->d[1]; - r1->d[2] = 0; - r1->d[3] = 0; - r2->d[0] = k->d[2]; - r2->d[1] = k->d[3]; - r2->d[2] = 0; - r2->d[3] = 0; - - SECP256K1_SCALAR_VERIFY(r1); - SECP256K1_SCALAR_VERIFY(r2); -} - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { - uint64_t l[8]; - unsigned int shiftlimbs; - unsigned int shiftlow; - unsigned int shifthigh; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - VERIFY_CHECK(shift >= 256); - - secp256k1_scalar_mul_512(l, a, b); - shiftlimbs = shift >> 6; - shiftlow = shift & 0x3F; - shifthigh = 64 - shiftlow; - r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0; - secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); - - SECP256K1_SCALAR_VERIFY(r); -} - -static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { - uint64_t mask0, mask1; - volatile int vflag = flag; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d)); - - mask0 = vflag + ~((uint64_t)0); - mask1 = ~mask0; - r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1); - r->d[1] = (r->d[1] & mask0) | (a->d[1] & mask1); - r->d[2] = (r->d[2] & mask0) | (a->d[2] & mask1); - r->d[3] = (r->d[3] & mask0) | (a->d[3] & mask1); - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_from_signed62(secp256k1_scalar *r, const secp256k1_modinv64_signed62 *a) { - const uint64_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4]; - - /* The output from secp256k1_modinv64{_var} should be normalized to range [0,modulus), and - * have limbs in [0,2^62). The modulus is < 2^256, so the top limb must be below 2^(256-62*4). - */ - VERIFY_CHECK(a0 >> 62 == 0); - VERIFY_CHECK(a1 >> 62 == 0); - VERIFY_CHECK(a2 >> 62 == 0); - VERIFY_CHECK(a3 >> 62 == 0); - VERIFY_CHECK(a4 >> 8 == 0); - - r->d[0] = a0 | a1 << 62; - r->d[1] = a1 >> 2 | a2 << 60; - r->d[2] = a2 >> 4 | a3 << 58; - r->d[3] = a3 >> 6 | a4 << 56; - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_to_signed62(secp256k1_modinv64_signed62 *r, const secp256k1_scalar *a) { - const uint64_t M62 = UINT64_MAX >> 2; - const uint64_t a0 = a->d[0], a1 = a->d[1], a2 = a->d[2], a3 = a->d[3]; - SECP256K1_SCALAR_VERIFY(a); - - r->v[0] = a0 & M62; - r->v[1] = (a0 >> 62 | a1 << 2) & M62; - r->v[2] = (a1 >> 60 | a2 << 4) & M62; - r->v[3] = (a2 >> 58 | a3 << 6) & M62; - r->v[4] = a3 >> 56; -} - -static const secp256k1_modinv64_modinfo secp256k1_const_modinfo_scalar = { - {{0x3FD25E8CD0364141LL, 0x2ABB739ABD2280EELL, -0x15LL, 0, 256}}, - 0x34F20099AA774EC1LL -}; - -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { - secp256k1_modinv64_signed62 s; -#ifdef VERIFY - int zero_in = secp256k1_scalar_is_zero(x); -#endif - SECP256K1_SCALAR_VERIFY(x); - - secp256k1_scalar_to_signed62(&s, x); - secp256k1_modinv64(&s, &secp256k1_const_modinfo_scalar); - secp256k1_scalar_from_signed62(r, &s); - - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(secp256k1_scalar_is_zero(r) == zero_in); -} - -static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { - secp256k1_modinv64_signed62 s; -#ifdef VERIFY - int zero_in = secp256k1_scalar_is_zero(x); -#endif - SECP256K1_SCALAR_VERIFY(x); - - secp256k1_scalar_to_signed62(&s, x); - secp256k1_modinv64_var(&s, &secp256k1_const_modinfo_scalar); - secp256k1_scalar_from_signed62(r, &s); - - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(secp256k1_scalar_is_zero(r) == zero_in); -} - -SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return !(a->d[0] & 1); -} - -#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/external/secp256k1/src/scalar_8x32.h b/external/secp256k1/src/scalar_8x32.h deleted file mode 100644 index 17863ef937..0000000000 --- a/external/secp256k1/src/scalar_8x32.h +++ /dev/null @@ -1,19 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCALAR_REPR_H -#define SECP256K1_SCALAR_REPR_H - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef struct { - uint32_t d[8]; -} secp256k1_scalar; - -#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} - -#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/external/secp256k1/src/scalar_8x32_impl.h b/external/secp256k1/src/scalar_8x32_impl.h deleted file mode 100644 index 2610496052..0000000000 --- a/external/secp256k1/src/scalar_8x32_impl.h +++ /dev/null @@ -1,816 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCALAR_REPR_IMPL_H -#define SECP256K1_SCALAR_REPR_IMPL_H - -#include "checkmem.h" -#include "modinv32_impl.h" -#include "util.h" - -/* Limbs of the secp256k1 order. */ -#define SECP256K1_N_0 ((uint32_t)0xD0364141UL) -#define SECP256K1_N_1 ((uint32_t)0xBFD25E8CUL) -#define SECP256K1_N_2 ((uint32_t)0xAF48A03BUL) -#define SECP256K1_N_3 ((uint32_t)0xBAAEDCE6UL) -#define SECP256K1_N_4 ((uint32_t)0xFFFFFFFEUL) -#define SECP256K1_N_5 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL) - -/* Limbs of 2^256 minus the secp256k1 order. */ -#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) -#define SECP256K1_N_C_1 (~SECP256K1_N_1) -#define SECP256K1_N_C_2 (~SECP256K1_N_2) -#define SECP256K1_N_C_3 (~SECP256K1_N_3) -#define SECP256K1_N_C_4 (1) - -/* Limbs of half the secp256k1 order. */ -#define SECP256K1_N_H_0 ((uint32_t)0x681B20A0UL) -#define SECP256K1_N_H_1 ((uint32_t)0xDFE92F46UL) -#define SECP256K1_N_H_2 ((uint32_t)0x57A4501DUL) -#define SECP256K1_N_H_3 ((uint32_t)0x5D576E73UL) -#define SECP256K1_N_H_4 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_5 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) -#define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) - -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { - r->d[0] = v; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; - r->d[4] = 0; - r->d[5] = 0; - r->d[6] = 0; - r->d[7] = 0; - - SECP256K1_SCALAR_VERIFY(r); -} - -SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - SECP256K1_SCALAR_VERIFY(a); - VERIFY_CHECK(count > 0 && count <= 32); - VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); - - return (a->d[offset >> 5] >> (offset & 0x1F)) & (0xFFFFFFFF >> (32 - count)); -} - -SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - SECP256K1_SCALAR_VERIFY(a); - VERIFY_CHECK(count > 0 && count <= 32); - VERIFY_CHECK(offset + count <= 256); - - if ((offset + count - 1) >> 5 == offset >> 5) { - return secp256k1_scalar_get_bits_limb32(a, offset, count); - } else { - VERIFY_CHECK((offset >> 5) + 1 < 8); - return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & (0xFFFFFFFF >> (32 - count)); - } -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ - no |= (a->d[6] < SECP256K1_N_6); /* No need for a > check. */ - no |= (a->d[5] < SECP256K1_N_5); /* No need for a > check. */ - no |= (a->d[4] < SECP256K1_N_4); - yes |= (a->d[4] > SECP256K1_N_4) & ~no; - no |= (a->d[3] < SECP256K1_N_3) & ~yes; - yes |= (a->d[3] > SECP256K1_N_3) & ~no; - no |= (a->d[2] < SECP256K1_N_2) & ~yes; - yes |= (a->d[2] > SECP256K1_N_2) & ~no; - no |= (a->d[1] < SECP256K1_N_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_1) & ~no; - yes |= (a->d[0] >= SECP256K1_N_0) & ~no; - return yes; -} - -SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_t overflow) { - uint64_t t; - VERIFY_CHECK(overflow <= 1); - - t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; - r->d[0] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1; - r->d[1] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[2] + overflow * SECP256K1_N_C_2; - r->d[2] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[3] + overflow * SECP256K1_N_C_3; - r->d[3] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[4] + overflow * SECP256K1_N_C_4; - r->d[4] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[5]; - r->d[5] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[6]; - r->d[6] = t & 0xFFFFFFFFUL; t >>= 32; - t += (uint64_t)r->d[7]; - r->d[7] = t & 0xFFFFFFFFUL; - - SECP256K1_SCALAR_VERIFY(r); - return overflow; -} - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - int overflow; - uint64_t t = (uint64_t)a->d[0] + b->d[0]; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[1] + b->d[1]; - r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[2] + b->d[2]; - r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[3] + b->d[3]; - r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[4] + b->d[4]; - r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[5] + b->d[5]; - r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[6] + b->d[6]; - r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)a->d[7] + b->d[7]; - r->d[7] = t & 0xFFFFFFFFULL; t >>= 32; - overflow = t + secp256k1_scalar_check_overflow(r); - VERIFY_CHECK(overflow == 0 || overflow == 1); - secp256k1_scalar_reduce(r, overflow); - - SECP256K1_SCALAR_VERIFY(r); - return overflow; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - uint64_t t; - volatile int vflag = flag; - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(bit < 256); - - bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */ - t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F)); - r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F)); - r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F)); - r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F)); - r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F)); - r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F)); - r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F)); - r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; - t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F)); - r->d[7] = t & 0xFFFFFFFFULL; - - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK((t >> 32) == 0); -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - int over; - r->d[0] = secp256k1_read_be32(&b32[28]); - r->d[1] = secp256k1_read_be32(&b32[24]); - r->d[2] = secp256k1_read_be32(&b32[20]); - r->d[3] = secp256k1_read_be32(&b32[16]); - r->d[4] = secp256k1_read_be32(&b32[12]); - r->d[5] = secp256k1_read_be32(&b32[8]); - r->d[6] = secp256k1_read_be32(&b32[4]); - r->d[7] = secp256k1_read_be32(&b32[0]); - over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); - if (overflow) { - *overflow = over; - } - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - SECP256K1_SCALAR_VERIFY(a); - - secp256k1_write_be32(&bin[0], a->d[7]); - secp256k1_write_be32(&bin[4], a->d[6]); - secp256k1_write_be32(&bin[8], a->d[5]); - secp256k1_write_be32(&bin[12], a->d[4]); - secp256k1_write_be32(&bin[16], a->d[3]); - secp256k1_write_be32(&bin[20], a->d[2]); - secp256k1_write_be32(&bin[24], a->d[1]); - secp256k1_write_be32(&bin[28], a->d[0]); -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0); - uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; - SECP256K1_SCALAR_VERIFY(a); - - r->d[0] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[1]) + SECP256K1_N_1; - r->d[1] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[2]) + SECP256K1_N_2; - r->d[2] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[3]) + SECP256K1_N_3; - r->d[3] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[4]) + SECP256K1_N_4; - r->d[4] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[5]) + SECP256K1_N_5; - r->d[5] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[6]) + SECP256K1_N_6; - r->d[6] = t & nonzero; t >>= 32; - t += (uint64_t)(~a->d[7]) + SECP256K1_N_7; - r->d[7] = t & nonzero; - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_half(secp256k1_scalar *r, const secp256k1_scalar *a) { - /* Writing `/` for field division and `//` for integer division, we compute - * - * a/2 = (a - (a&1))/2 + (a&1)/2 - * = (a >> 1) + (a&1 ? 1/2 : 0) - * = (a >> 1) + (a&1 ? n//2+1 : 0), - * - * where n is the group order and in the last equality we have used 1/2 = n//2+1 (mod n). - * For n//2, we have the constants SECP256K1_N_H_0, ... - * - * This sum does not overflow. The most extreme case is a = -2, the largest odd scalar. Here: - * - the left summand is: a >> 1 = (a - a&1)/2 = (n-2-1)//2 = (n-3)//2 - * - the right summand is: a&1 ? n//2+1 : 0 = n//2+1 = (n-1)//2 + 2//2 = (n+1)//2 - * Together they sum to (n-3)//2 + (n+1)//2 = (2n-2)//2 = n - 1, which is less than n. - */ - uint32_t mask = -(uint32_t)(a->d[0] & 1U); - uint64_t t = (uint32_t)((a->d[0] >> 1) | (a->d[1] << 31)); - SECP256K1_SCALAR_VERIFY(a); - - t += (SECP256K1_N_H_0 + 1U) & mask; - r->d[0] = t; t >>= 32; - t += (uint32_t)((a->d[1] >> 1) | (a->d[2] << 31)); - t += SECP256K1_N_H_1 & mask; - r->d[1] = t; t >>= 32; - t += (uint32_t)((a->d[2] >> 1) | (a->d[3] << 31)); - t += SECP256K1_N_H_2 & mask; - r->d[2] = t; t >>= 32; - t += (uint32_t)((a->d[3] >> 1) | (a->d[4] << 31)); - t += SECP256K1_N_H_3 & mask; - r->d[3] = t; t >>= 32; - t += (uint32_t)((a->d[4] >> 1) | (a->d[5] << 31)); - t += SECP256K1_N_H_4 & mask; - r->d[4] = t; t >>= 32; - t += (uint32_t)((a->d[5] >> 1) | (a->d[6] << 31)); - t += SECP256K1_N_H_5 & mask; - r->d[5] = t; t >>= 32; - t += (uint32_t)((a->d[6] >> 1) | (a->d[7] << 31)); - t += SECP256K1_N_H_6 & mask; - r->d[6] = t; t >>= 32; - r->d[7] = (uint32_t)t + (uint32_t)(a->d[7] >> 1) + (SECP256K1_N_H_7 & mask); - - /* The line above only computed the bottom 32 bits of r->d[7]. Redo the computation - * in full 64 bits to make sure the top 32 bits are indeed zero. */ - VERIFY_CHECK((t + (a->d[7] >> 1) + (SECP256K1_N_H_7 & mask)) >> 32 == 0); - - SECP256K1_SCALAR_VERIFY(r); -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - int yes = 0; - int no = 0; - SECP256K1_SCALAR_VERIFY(a); - - no |= (a->d[7] < SECP256K1_N_H_7); - yes |= (a->d[7] > SECP256K1_N_H_7) & ~no; - no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */ - no |= (a->d[5] < SECP256K1_N_H_5) & ~yes; /* No need for a > check. */ - no |= (a->d[4] < SECP256K1_N_H_4) & ~yes; /* No need for a > check. */ - no |= (a->d[3] < SECP256K1_N_H_3) & ~yes; - yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; - no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; - yes |= (a->d[2] > SECP256K1_N_H_2) & ~no; - no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; - yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; - yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; - return yes; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - /* If we are flag = 0, mask = 00...00 and this is a no-op; - * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ - volatile int vflag = flag; - uint32_t mask = -vflag; - uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0); - uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); - SECP256K1_SCALAR_VERIFY(r); - - r->d[0] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); - r->d[1] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); - r->d[2] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); - r->d[3] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[4] ^ mask) + (SECP256K1_N_4 & mask); - r->d[4] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[5] ^ mask) + (SECP256K1_N_5 & mask); - r->d[5] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[6] ^ mask) + (SECP256K1_N_6 & mask); - r->d[6] = t & nonzero; t >>= 32; - t += (uint64_t)(r->d[7] ^ mask) + (SECP256K1_N_7 & mask); - r->d[7] = t & nonzero; - - SECP256K1_SCALAR_VERIFY(r); - return 2 * (mask == 0) - 1; -} - - -/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ - -/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define muladd(a,b) { \ - uint32_t tl, th; \ - { \ - uint64_t t = (uint64_t)a * b; \ - th = t >> 32; /* at most 0xFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl); /* at most 0xFFFFFFFF */ \ - c1 += th; /* overflow is handled on the next line */ \ - c2 += (c1 < th); /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ -} - -/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ -#define muladd_fast(a,b) { \ - uint32_t tl, th; \ - { \ - uint64_t t = (uint64_t)a * b; \ - th = t >> 32; /* at most 0xFFFFFFFE */ \ - tl = t; \ - } \ - c0 += tl; /* overflow is handled on the next line */ \ - th += (c0 < tl); /* at most 0xFFFFFFFF */ \ - c1 += th; /* never overflows by contract (verified in the next line) */ \ - VERIFY_CHECK(c1 >= th); \ -} - -/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ -#define sumadd(a) { \ - unsigned int over; \ - c0 += (a); /* overflow is handled on the next line */ \ - over = (c0 < (a)); \ - c1 += over; /* overflow is handled on the next line */ \ - c2 += (c1 < over); /* never overflows by contract */ \ -} - -/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ -#define sumadd_fast(a) { \ - c0 += (a); /* overflow is handled on the next line */ \ - c1 += (c0 < (a)); /* never overflows by contract (verified the next line) */ \ - VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ - VERIFY_CHECK(c2 == 0); \ -} - -/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */ -#define extract(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = c2; \ - c2 = 0; \ -} - -/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. c2 is required to be zero. */ -#define extract_fast(n) { \ - (n) = c0; \ - c0 = c1; \ - c1 = 0; \ - VERIFY_CHECK(c2 == 0); \ -} - -static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) { - uint64_t c; - uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15]; - uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12; - uint32_t p0, p1, p2, p3, p4, p5, p6, p7, p8; - - /* 96 bit accumulator. */ - uint32_t c0, c1, c2; - - /* Reduce 512 bits into 385. */ - /* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */ - c0 = l[0]; c1 = 0; c2 = 0; - muladd_fast(n0, SECP256K1_N_C_0); - extract_fast(m0); - sumadd_fast(l[1]); - muladd(n1, SECP256K1_N_C_0); - muladd(n0, SECP256K1_N_C_1); - extract(m1); - sumadd(l[2]); - muladd(n2, SECP256K1_N_C_0); - muladd(n1, SECP256K1_N_C_1); - muladd(n0, SECP256K1_N_C_2); - extract(m2); - sumadd(l[3]); - muladd(n3, SECP256K1_N_C_0); - muladd(n2, SECP256K1_N_C_1); - muladd(n1, SECP256K1_N_C_2); - muladd(n0, SECP256K1_N_C_3); - extract(m3); - sumadd(l[4]); - muladd(n4, SECP256K1_N_C_0); - muladd(n3, SECP256K1_N_C_1); - muladd(n2, SECP256K1_N_C_2); - muladd(n1, SECP256K1_N_C_3); - sumadd(n0); - extract(m4); - sumadd(l[5]); - muladd(n5, SECP256K1_N_C_0); - muladd(n4, SECP256K1_N_C_1); - muladd(n3, SECP256K1_N_C_2); - muladd(n2, SECP256K1_N_C_3); - sumadd(n1); - extract(m5); - sumadd(l[6]); - muladd(n6, SECP256K1_N_C_0); - muladd(n5, SECP256K1_N_C_1); - muladd(n4, SECP256K1_N_C_2); - muladd(n3, SECP256K1_N_C_3); - sumadd(n2); - extract(m6); - sumadd(l[7]); - muladd(n7, SECP256K1_N_C_0); - muladd(n6, SECP256K1_N_C_1); - muladd(n5, SECP256K1_N_C_2); - muladd(n4, SECP256K1_N_C_3); - sumadd(n3); - extract(m7); - muladd(n7, SECP256K1_N_C_1); - muladd(n6, SECP256K1_N_C_2); - muladd(n5, SECP256K1_N_C_3); - sumadd(n4); - extract(m8); - muladd(n7, SECP256K1_N_C_2); - muladd(n6, SECP256K1_N_C_3); - sumadd(n5); - extract(m9); - muladd(n7, SECP256K1_N_C_3); - sumadd(n6); - extract(m10); - sumadd_fast(n7); - extract_fast(m11); - VERIFY_CHECK(c0 <= 1); - m12 = c0; - - /* Reduce 385 bits into 258. */ - /* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */ - c0 = m0; c1 = 0; c2 = 0; - muladd_fast(m8, SECP256K1_N_C_0); - extract_fast(p0); - sumadd_fast(m1); - muladd(m9, SECP256K1_N_C_0); - muladd(m8, SECP256K1_N_C_1); - extract(p1); - sumadd(m2); - muladd(m10, SECP256K1_N_C_0); - muladd(m9, SECP256K1_N_C_1); - muladd(m8, SECP256K1_N_C_2); - extract(p2); - sumadd(m3); - muladd(m11, SECP256K1_N_C_0); - muladd(m10, SECP256K1_N_C_1); - muladd(m9, SECP256K1_N_C_2); - muladd(m8, SECP256K1_N_C_3); - extract(p3); - sumadd(m4); - muladd(m12, SECP256K1_N_C_0); - muladd(m11, SECP256K1_N_C_1); - muladd(m10, SECP256K1_N_C_2); - muladd(m9, SECP256K1_N_C_3); - sumadd(m8); - extract(p4); - sumadd(m5); - muladd(m12, SECP256K1_N_C_1); - muladd(m11, SECP256K1_N_C_2); - muladd(m10, SECP256K1_N_C_3); - sumadd(m9); - extract(p5); - sumadd(m6); - muladd(m12, SECP256K1_N_C_2); - muladd(m11, SECP256K1_N_C_3); - sumadd(m10); - extract(p6); - sumadd_fast(m7); - muladd_fast(m12, SECP256K1_N_C_3); - sumadd_fast(m11); - extract_fast(p7); - p8 = c0 + m12; - VERIFY_CHECK(p8 <= 2); - - /* Reduce 258 bits into 256. */ - /* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */ - c = p0 + (uint64_t)SECP256K1_N_C_0 * p8; - r->d[0] = c & 0xFFFFFFFFUL; c >>= 32; - c += p1 + (uint64_t)SECP256K1_N_C_1 * p8; - r->d[1] = c & 0xFFFFFFFFUL; c >>= 32; - c += p2 + (uint64_t)SECP256K1_N_C_2 * p8; - r->d[2] = c & 0xFFFFFFFFUL; c >>= 32; - c += p3 + (uint64_t)SECP256K1_N_C_3 * p8; - r->d[3] = c & 0xFFFFFFFFUL; c >>= 32; - c += p4 + (uint64_t)p8; - r->d[4] = c & 0xFFFFFFFFUL; c >>= 32; - c += p5; - r->d[5] = c & 0xFFFFFFFFUL; c >>= 32; - c += p6; - r->d[6] = c & 0xFFFFFFFFUL; c >>= 32; - c += p7; - r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; - - /* Final reduction of r. */ - secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); -} - -static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, const secp256k1_scalar *b) { - /* 96 bit accumulator. */ - uint32_t c0 = 0, c1 = 0, c2 = 0; - - /* l[0..15] = a[0..7] * b[0..7]. */ - muladd_fast(a->d[0], b->d[0]); - extract_fast(l[0]); - muladd(a->d[0], b->d[1]); - muladd(a->d[1], b->d[0]); - extract(l[1]); - muladd(a->d[0], b->d[2]); - muladd(a->d[1], b->d[1]); - muladd(a->d[2], b->d[0]); - extract(l[2]); - muladd(a->d[0], b->d[3]); - muladd(a->d[1], b->d[2]); - muladd(a->d[2], b->d[1]); - muladd(a->d[3], b->d[0]); - extract(l[3]); - muladd(a->d[0], b->d[4]); - muladd(a->d[1], b->d[3]); - muladd(a->d[2], b->d[2]); - muladd(a->d[3], b->d[1]); - muladd(a->d[4], b->d[0]); - extract(l[4]); - muladd(a->d[0], b->d[5]); - muladd(a->d[1], b->d[4]); - muladd(a->d[2], b->d[3]); - muladd(a->d[3], b->d[2]); - muladd(a->d[4], b->d[1]); - muladd(a->d[5], b->d[0]); - extract(l[5]); - muladd(a->d[0], b->d[6]); - muladd(a->d[1], b->d[5]); - muladd(a->d[2], b->d[4]); - muladd(a->d[3], b->d[3]); - muladd(a->d[4], b->d[2]); - muladd(a->d[5], b->d[1]); - muladd(a->d[6], b->d[0]); - extract(l[6]); - muladd(a->d[0], b->d[7]); - muladd(a->d[1], b->d[6]); - muladd(a->d[2], b->d[5]); - muladd(a->d[3], b->d[4]); - muladd(a->d[4], b->d[3]); - muladd(a->d[5], b->d[2]); - muladd(a->d[6], b->d[1]); - muladd(a->d[7], b->d[0]); - extract(l[7]); - muladd(a->d[1], b->d[7]); - muladd(a->d[2], b->d[6]); - muladd(a->d[3], b->d[5]); - muladd(a->d[4], b->d[4]); - muladd(a->d[5], b->d[3]); - muladd(a->d[6], b->d[2]); - muladd(a->d[7], b->d[1]); - extract(l[8]); - muladd(a->d[2], b->d[7]); - muladd(a->d[3], b->d[6]); - muladd(a->d[4], b->d[5]); - muladd(a->d[5], b->d[4]); - muladd(a->d[6], b->d[3]); - muladd(a->d[7], b->d[2]); - extract(l[9]); - muladd(a->d[3], b->d[7]); - muladd(a->d[4], b->d[6]); - muladd(a->d[5], b->d[5]); - muladd(a->d[6], b->d[4]); - muladd(a->d[7], b->d[3]); - extract(l[10]); - muladd(a->d[4], b->d[7]); - muladd(a->d[5], b->d[6]); - muladd(a->d[6], b->d[5]); - muladd(a->d[7], b->d[4]); - extract(l[11]); - muladd(a->d[5], b->d[7]); - muladd(a->d[6], b->d[6]); - muladd(a->d[7], b->d[5]); - extract(l[12]); - muladd(a->d[6], b->d[7]); - muladd(a->d[7], b->d[6]); - extract(l[13]); - muladd_fast(a->d[7], b->d[7]); - extract_fast(l[14]); - VERIFY_CHECK(c1 == 0); - l[15] = c0; -} - -#undef sumadd -#undef sumadd_fast -#undef muladd -#undef muladd_fast -#undef extract -#undef extract_fast - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - uint32_t l[16]; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - secp256k1_scalar_mul_512(l, a, b); - secp256k1_scalar_reduce_512(r, l); - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) { - SECP256K1_SCALAR_VERIFY(k); - - r1->d[0] = k->d[0]; - r1->d[1] = k->d[1]; - r1->d[2] = k->d[2]; - r1->d[3] = k->d[3]; - r1->d[4] = 0; - r1->d[5] = 0; - r1->d[6] = 0; - r1->d[7] = 0; - r2->d[0] = k->d[4]; - r2->d[1] = k->d[5]; - r2->d[2] = k->d[6]; - r2->d[3] = k->d[7]; - r2->d[4] = 0; - r2->d[5] = 0; - r2->d[6] = 0; - r2->d[7] = 0; - - SECP256K1_SCALAR_VERIFY(r1); - SECP256K1_SCALAR_VERIFY(r2); -} - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; -} - -SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { - uint32_t l[16]; - unsigned int shiftlimbs; - unsigned int shiftlow; - unsigned int shifthigh; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - VERIFY_CHECK(shift >= 256); - - secp256k1_scalar_mul_512(l, a, b); - shiftlimbs = shift >> 5; - shiftlow = shift & 0x1F; - shifthigh = 32 - shiftlow; - r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[3] = shift < 416 ? (l[3 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[4 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[4] = shift < 384 ? (l[4 + shiftlimbs] >> shiftlow | (shift < 352 && shiftlow ? (l[5 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0; - r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0; - secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); - - SECP256K1_SCALAR_VERIFY(r); -} - -static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { - uint32_t mask0, mask1; - volatile int vflag = flag; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d)); - - mask0 = vflag + ~((uint32_t)0); - mask1 = ~mask0; - r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1); - r->d[1] = (r->d[1] & mask0) | (a->d[1] & mask1); - r->d[2] = (r->d[2] & mask0) | (a->d[2] & mask1); - r->d[3] = (r->d[3] & mask0) | (a->d[3] & mask1); - r->d[4] = (r->d[4] & mask0) | (a->d[4] & mask1); - r->d[5] = (r->d[5] & mask0) | (a->d[5] & mask1); - r->d[6] = (r->d[6] & mask0) | (a->d[6] & mask1); - r->d[7] = (r->d[7] & mask0) | (a->d[7] & mask1); - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_from_signed30(secp256k1_scalar *r, const secp256k1_modinv32_signed30 *a) { - const uint32_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4], - a5 = a->v[5], a6 = a->v[6], a7 = a->v[7], a8 = a->v[8]; - - /* The output from secp256k1_modinv32{_var} should be normalized to range [0,modulus), and - * have limbs in [0,2^30). The modulus is < 2^256, so the top limb must be below 2^(256-30*8). - */ - VERIFY_CHECK(a0 >> 30 == 0); - VERIFY_CHECK(a1 >> 30 == 0); - VERIFY_CHECK(a2 >> 30 == 0); - VERIFY_CHECK(a3 >> 30 == 0); - VERIFY_CHECK(a4 >> 30 == 0); - VERIFY_CHECK(a5 >> 30 == 0); - VERIFY_CHECK(a6 >> 30 == 0); - VERIFY_CHECK(a7 >> 30 == 0); - VERIFY_CHECK(a8 >> 16 == 0); - - r->d[0] = a0 | a1 << 30; - r->d[1] = a1 >> 2 | a2 << 28; - r->d[2] = a2 >> 4 | a3 << 26; - r->d[3] = a3 >> 6 | a4 << 24; - r->d[4] = a4 >> 8 | a5 << 22; - r->d[5] = a5 >> 10 | a6 << 20; - r->d[6] = a6 >> 12 | a7 << 18; - r->d[7] = a7 >> 14 | a8 << 16; - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_to_signed30(secp256k1_modinv32_signed30 *r, const secp256k1_scalar *a) { - const uint32_t M30 = UINT32_MAX >> 2; - const uint32_t a0 = a->d[0], a1 = a->d[1], a2 = a->d[2], a3 = a->d[3], - a4 = a->d[4], a5 = a->d[5], a6 = a->d[6], a7 = a->d[7]; - SECP256K1_SCALAR_VERIFY(a); - - r->v[0] = a0 & M30; - r->v[1] = (a0 >> 30 | a1 << 2) & M30; - r->v[2] = (a1 >> 28 | a2 << 4) & M30; - r->v[3] = (a2 >> 26 | a3 << 6) & M30; - r->v[4] = (a3 >> 24 | a4 << 8) & M30; - r->v[5] = (a4 >> 22 | a5 << 10) & M30; - r->v[6] = (a5 >> 20 | a6 << 12) & M30; - r->v[7] = (a6 >> 18 | a7 << 14) & M30; - r->v[8] = a7 >> 16; -} - -static const secp256k1_modinv32_modinfo secp256k1_const_modinfo_scalar = { - {{0x10364141L, 0x3F497A33L, 0x348A03BBL, 0x2BB739ABL, -0x146L, 0, 0, 0, 65536}}, - 0x2A774EC1L -}; - -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { - secp256k1_modinv32_signed30 s; -#ifdef VERIFY - int zero_in = secp256k1_scalar_is_zero(x); -#endif - SECP256K1_SCALAR_VERIFY(x); - - secp256k1_scalar_to_signed30(&s, x); - secp256k1_modinv32(&s, &secp256k1_const_modinfo_scalar); - secp256k1_scalar_from_signed30(r, &s); - - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(secp256k1_scalar_is_zero(r) == zero_in); -} - -static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { - secp256k1_modinv32_signed30 s; -#ifdef VERIFY - int zero_in = secp256k1_scalar_is_zero(x); -#endif - SECP256K1_SCALAR_VERIFY(x); - - secp256k1_scalar_to_signed30(&s, x); - secp256k1_modinv32_var(&s, &secp256k1_const_modinfo_scalar); - secp256k1_scalar_from_signed30(r, &s); - - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(secp256k1_scalar_is_zero(r) == zero_in); -} - -SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return !(a->d[0] & 1); -} - -#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/external/secp256k1/src/scalar_impl.h b/external/secp256k1/src/scalar_impl.h deleted file mode 100644 index dbb5b0a01c..0000000000 --- a/external/secp256k1/src/scalar_impl.h +++ /dev/null @@ -1,321 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCALAR_IMPL_H -#define SECP256K1_SCALAR_IMPL_H - -#ifdef VERIFY -#include -#endif - -#include "scalar.h" -#include "util.h" - -#if defined(EXHAUSTIVE_TEST_ORDER) -#include "scalar_low_impl.h" -#elif defined(SECP256K1_WIDEMUL_INT128) -#include "scalar_4x64_impl.h" -#elif defined(SECP256K1_WIDEMUL_INT64) -#include "scalar_8x32_impl.h" -#else -#error "Please select wide multiplication implementation" -#endif - -static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); -static const secp256k1_scalar secp256k1_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { - secp256k1_memclear(r, sizeof(secp256k1_scalar)); -} - -static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned char *bin) { - int overflow; - secp256k1_scalar_set_b32(r, bin, &overflow); - - SECP256K1_SCALAR_VERIFY(r); - return (!overflow) & (!secp256k1_scalar_is_zero(r)); -} - -static void secp256k1_scalar_verify(const secp256k1_scalar *r) { - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); - - (void)r; -} - -#if defined(EXHAUSTIVE_TEST_ORDER) -/* Begin of section generated by sage/gen_exhaustive_groups.sage. */ -# if EXHAUSTIVE_TEST_ORDER == 7 -# define EXHAUSTIVE_TEST_LAMBDA 2 -# elif EXHAUSTIVE_TEST_ORDER == 13 -# define EXHAUSTIVE_TEST_LAMBDA 9 -# elif EXHAUSTIVE_TEST_ORDER == 199 -# define EXHAUSTIVE_TEST_LAMBDA 92 -# else -# error No known lambda for the specified exhaustive test group order. -# endif -/* End of section generated by sage/gen_exhaustive_groups.sage. */ - -/** - * Find r1 and r2 given k, such that r1 + r2 * lambda == k mod n; unlike in the - * full case we don't bother making r1 and r2 be small, we just want them to be - * nontrivial to get full test coverage for the exhaustive tests. We therefore - * (arbitrarily) set r2 = k + 5 (mod n) and r1 = k - r2 * lambda (mod n). - */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k) { - SECP256K1_SCALAR_VERIFY(k); - VERIFY_CHECK(r1 != k); - VERIFY_CHECK(r2 != k); - VERIFY_CHECK(r1 != r2); - - *r2 = (*k + 5) % EXHAUSTIVE_TEST_ORDER; - *r1 = (*k + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; - - SECP256K1_SCALAR_VERIFY(r1); - SECP256K1_SCALAR_VERIFY(r2); -} -#else -/** - * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where - * lambda is: */ -static const secp256k1_scalar secp256k1_const_lambda = SECP256K1_SCALAR_CONST( - 0x5363AD4CUL, 0xC05C30E0UL, 0xA5261C02UL, 0x8812645AUL, - 0x122E22EAUL, 0x20816678UL, 0xDF02967CUL, 0x1B23BD72UL -); - -#ifdef VERIFY -static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, const secp256k1_scalar *r2, const secp256k1_scalar *k); -#endif - -/* - * Both lambda and beta are primitive cube roots of unity. That is lamba^3 == 1 mod n and - * beta^3 == 1 mod p, where n is the curve order and p is the field order. - * - * Furthermore, because (X^3 - 1) = (X - 1)(X^2 + X + 1), the primitive cube roots of unity are - * roots of X^2 + X + 1. Therefore lambda^2 + lamba == -1 mod n and beta^2 + beta == -1 mod p. - * (The other primitive cube roots of unity are lambda^2 and beta^2 respectively.) - * - * Let l = -1/2 + i*sqrt(3)/2, the complex root of X^2 + X + 1. We can define a ring - * homomorphism phi : Z[l] -> Z_n where phi(a + b*l) == a + b*lambda mod n. The kernel of phi - * is a lattice over Z[l] (considering Z[l] as a Z-module). This lattice is generated by a - * reduced basis {a1 + b1*l, a2 + b2*l} where - * - * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} - * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3} - * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8} - * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} - * - * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm - * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1 - * and k2 are small in absolute value. - * - * The algorithm computes c1 = round(b2 * k / n) and c2 = round((-b1) * k / n), and gives - * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and - * compute r2 = k2 mod n, and r1 = k1 mod n = (k - r2 * lambda) mod n, avoiding the need for - * the constants a1 and a2. - * - * g1, g2 are precomputed constants used to replace division with a rounded multiplication - * when decomposing the scalar for an endomorphism-based point multiplication. - * - * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve - * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5. - * - * The derivation is described in the paper "Efficient Software Implementation of Public-Key - * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez), - * Section 4.3 (here we use a somewhat higher-precision estimate): - * d = a1*b2 - b1*a2 - * g1 = round(2^384 * b2/d) - * g2 = round(2^384 * (-b1)/d) - * - * (Note that d is also equal to the curve order, n, here because [a1,b1] and [a2,b2] - * can be found as outputs of the Extended Euclidean Algorithm on inputs n and lambda). - * - * The function below splits k into r1 and r2, such that - * - r1 + lambda * r2 == k (mod n) - * - either r1 < 2^128 or -r1 mod n < 2^128 - * - either r2 < 2^128 or -r2 mod n < 2^128 - * - * See proof below. - */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT r1, secp256k1_scalar * SECP256K1_RESTRICT r2, const secp256k1_scalar * SECP256K1_RESTRICT k) { - secp256k1_scalar c1, c2; - static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, - 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL - ); - static const secp256k1_scalar minus_b2 = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, - 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL - ); - static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST( - 0x3086D221UL, 0xA7D46BCDUL, 0xE86C90E4UL, 0x9284EB15UL, - 0x3DAA8A14UL, 0x71E8CA7FUL, 0xE893209AUL, 0x45DBB031UL - ); - static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST( - 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C4UL, - 0x221208ACUL, 0x9DF506C6UL, 0x1571B4AEUL, 0x8AC47F71UL - ); - SECP256K1_SCALAR_VERIFY(k); - VERIFY_CHECK(r1 != k); - VERIFY_CHECK(r2 != k); - VERIFY_CHECK(r1 != r2); - - /* these _var calls are constant time since the shift amount is constant */ - secp256k1_scalar_mul_shift_var(&c1, k, &g1, 384); - secp256k1_scalar_mul_shift_var(&c2, k, &g2, 384); - secp256k1_scalar_mul(&c1, &c1, &minus_b1); - secp256k1_scalar_mul(&c2, &c2, &minus_b2); - secp256k1_scalar_add(r2, &c1, &c2); - secp256k1_scalar_mul(r1, r2, &secp256k1_const_lambda); - secp256k1_scalar_negate(r1, r1); - secp256k1_scalar_add(r1, r1, k); - - SECP256K1_SCALAR_VERIFY(r1); - SECP256K1_SCALAR_VERIFY(r2); -#ifdef VERIFY - secp256k1_scalar_split_lambda_verify(r1, r2, k); -#endif -} - -#ifdef VERIFY -/* - * Proof for secp256k1_scalar_split_lambda's bounds. - * - * Let - * - epsilon1 = 2^256 * |g1/2^384 - b2/d| - * - epsilon2 = 2^256 * |g2/2^384 - (-b1)/d| - * - c1 = round(k*g1/2^384) - * - c2 = round(k*g2/2^384) - * - * Lemma 1: |c1 - k*b2/d| < 2^-1 + epsilon1 - * - * |c1 - k*b2/d| - * = - * |c1 - k*g1/2^384 + k*g1/2^384 - k*b2/d| - * <= {triangle inequality} - * |c1 - k*g1/2^384| + |k*g1/2^384 - k*b2/d| - * = - * |c1 - k*g1/2^384| + k*|g1/2^384 - b2/d| - * < {rounding in c1 and 0 <= k < 2^256} - * 2^-1 + 2^256 * |g1/2^384 - b2/d| - * = {definition of epsilon1} - * 2^-1 + epsilon1 - * - * Lemma 2: |c2 - k*(-b1)/d| < 2^-1 + epsilon2 - * - * |c2 - k*(-b1)/d| - * = - * |c2 - k*g2/2^384 + k*g2/2^384 - k*(-b1)/d| - * <= {triangle inequality} - * |c2 - k*g2/2^384| + |k*g2/2^384 - k*(-b1)/d| - * = - * |c2 - k*g2/2^384| + k*|g2/2^384 - (-b1)/d| - * < {rounding in c2 and 0 <= k < 2^256} - * 2^-1 + 2^256 * |g2/2^384 - (-b1)/d| - * = {definition of epsilon2} - * 2^-1 + epsilon2 - * - * Let - * - k1 = k - c1*a1 - c2*a2 - * - k2 = - c1*b1 - c2*b2 - * - * Lemma 3: |k1| < (a1 + a2 + 1)/2 < 2^128 - * - * |k1| - * = {definition of k1} - * |k - c1*a1 - c2*a2| - * = {(a1*b2 - b1*a2)/n = 1} - * |k*(a1*b2 - b1*a2)/n - c1*a1 - c2*a2| - * = - * |a1*(k*b2/n - c1) + a2*(k*(-b1)/n - c2)| - * <= {triangle inequality} - * a1*|k*b2/n - c1| + a2*|k*(-b1)/n - c2| - * < {Lemma 1 and Lemma 2} - * a1*(2^-1 + epsilon1) + a2*(2^-1 + epsilon2) - * < {rounding up to an integer} - * (a1 + a2 + 1)/2 - * < {rounding up to a power of 2} - * 2^128 - * - * Lemma 4: |k2| < (-b1 + b2)/2 + 1 < 2^128 - * - * |k2| - * = {definition of k2} - * |- c1*a1 - c2*a2| - * = {(b1*b2 - b1*b2)/n = 0} - * |k*(b1*b2 - b1*b2)/n - c1*b1 - c2*b2| - * = - * |b1*(k*b2/n - c1) + b2*(k*(-b1)/n - c2)| - * <= {triangle inequality} - * (-b1)*|k*b2/n - c1| + b2*|k*(-b1)/n - c2| - * < {Lemma 1 and Lemma 2} - * (-b1)*(2^-1 + epsilon1) + b2*(2^-1 + epsilon2) - * < {rounding up to an integer} - * (-b1 + b2)/2 + 1 - * < {rounding up to a power of 2} - * 2^128 - * - * Let - * - r2 = k2 mod n - * - r1 = k - r2*lambda mod n. - * - * Notice that r1 is defined such that r1 + r2 * lambda == k (mod n). - * - * Lemma 5: r1 == k1 mod n. - * - * r1 - * == {definition of r1 and r2} - * k - k2*lambda - * == {definition of k2} - * k - (- c1*b1 - c2*b2)*lambda - * == - * k + c1*b1*lambda + c2*b2*lambda - * == {a1 + b1*lambda == 0 mod n and a2 + b2*lambda == 0 mod n} - * k - c1*a1 - c2*a2 - * == {definition of k1} - * k1 - * - * From Lemma 3, Lemma 4, Lemma 5 and the definition of r2, we can conclude that - * - * - either r1 < 2^128 or -r1 mod n < 2^128 - * - either r2 < 2^128 or -r2 mod n < 2^128. - * - * Q.E.D. - */ -static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, const secp256k1_scalar *r2, const secp256k1_scalar *k) { - secp256k1_scalar s; - unsigned char buf1[32]; - unsigned char buf2[32]; - - /* (a1 + a2 + 1)/2 is 0xa2a8918ca85bafe22016d0b917e4dd77 */ - static const unsigned char k1_bound[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa2, 0xa8, 0x91, 0x8c, 0xa8, 0x5b, 0xaf, 0xe2, 0x20, 0x16, 0xd0, 0xb9, 0x17, 0xe4, 0xdd, 0x77 - }; - - /* (-b1 + b2)/2 + 1 is 0x8a65287bd47179fb2be08846cea267ed */ - static const unsigned char k2_bound[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8a, 0x65, 0x28, 0x7b, 0xd4, 0x71, 0x79, 0xfb, 0x2b, 0xe0, 0x88, 0x46, 0xce, 0xa2, 0x67, 0xed - }; - - secp256k1_scalar_mul(&s, &secp256k1_const_lambda, r2); - secp256k1_scalar_add(&s, &s, r1); - VERIFY_CHECK(secp256k1_scalar_eq(&s, k)); - - secp256k1_scalar_negate(&s, r1); - secp256k1_scalar_get_b32(buf1, r1); - secp256k1_scalar_get_b32(buf2, &s); - VERIFY_CHECK(secp256k1_memcmp_var(buf1, k1_bound, 32) < 0 || secp256k1_memcmp_var(buf2, k1_bound, 32) < 0); - - secp256k1_scalar_negate(&s, r2); - secp256k1_scalar_get_b32(buf1, r2); - secp256k1_scalar_get_b32(buf2, &s); - VERIFY_CHECK(secp256k1_memcmp_var(buf1, k2_bound, 32) < 0 || secp256k1_memcmp_var(buf2, k2_bound, 32) < 0); -} -#endif /* VERIFY */ -#endif /* !defined(EXHAUSTIVE_TEST_ORDER) */ - -#endif /* SECP256K1_SCALAR_IMPL_H */ diff --git a/external/secp256k1/src/scalar_low.h b/external/secp256k1/src/scalar_low.h deleted file mode 100644 index 2711eb932d..0000000000 --- a/external/secp256k1/src/scalar_low.h +++ /dev/null @@ -1,24 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015, 2022 Andrew Poelstra, Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCALAR_REPR_H -#define SECP256K1_SCALAR_REPR_H - -#include - -/** A scalar modulo the group order of the secp256k1 curve. */ -typedef uint32_t secp256k1_scalar; - -/* A compile-time constant equal to 2^32 (modulo order). */ -#define SCALAR_2P32 ((0xffffffffUL % EXHAUSTIVE_TEST_ORDER) + 1U) - -/* Compute a*2^32 + b (modulo order). */ -#define SCALAR_HORNER(a, b) (((uint64_t)(a) * SCALAR_2P32 + (b)) % EXHAUSTIVE_TEST_ORDER) - -/* Evaluates to the provided 256-bit constant reduced modulo order. */ -#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER(SCALAR_HORNER((d7), (d6)), (d5)), (d4)), (d3)), (d2)), (d1)), (d0)) - -#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/external/secp256k1/src/scalar_low_impl.h b/external/secp256k1/src/scalar_low_impl.h deleted file mode 100644 index 84e1a380a3..0000000000 --- a/external/secp256k1/src/scalar_low_impl.h +++ /dev/null @@ -1,206 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCALAR_REPR_IMPL_H -#define SECP256K1_SCALAR_REPR_IMPL_H - -#include "checkmem.h" -#include "scalar.h" -#include "util.h" - -#include - -SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return !(*a & 1); -} - -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { - *r = v % EXHAUSTIVE_TEST_ORDER; - - SECP256K1_SCALAR_VERIFY(r); -} - -SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - SECP256K1_SCALAR_VERIFY(a); - - VERIFY_CHECK(count > 0 && count <= 32); - if (offset < 32) { - return (*a >> offset) & (0xFFFFFFFF >> (32 - count)); - } else { - return 0; - } -} - -SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { - SECP256K1_SCALAR_VERIFY(a); - - return secp256k1_scalar_get_bits_limb32(a, offset, count); -} - -SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } - -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; - - SECP256K1_SCALAR_VERIFY(r); - return *r < *b; -} - -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { - SECP256K1_SCALAR_VERIFY(r); - - if (flag && bit < 32) - *r += ((uint32_t)1 << bit); - - SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(bit < 32); - /* Verify that adding (1 << bit) will not overflow any in-range scalar *r by overflowing the underlying uint32_t. */ - VERIFY_CHECK(((uint32_t)1 << bit) - 1 <= UINT32_MAX - EXHAUSTIVE_TEST_ORDER); -} - -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { - int i; - int over = 0; - *r = 0; - for (i = 0; i < 32; i++) { - *r = (*r * 0x100) + b32[i]; - if (*r >= EXHAUSTIVE_TEST_ORDER) { - over = 1; - *r %= EXHAUSTIVE_TEST_ORDER; - } - } - if (overflow) *overflow = over; - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { - SECP256K1_SCALAR_VERIFY(a); - - memset(bin, 0, 32); - bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; -} - -SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return *a == 0; -} - -static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - if (*a == 0) { - *r = 0; - } else { - *r = EXHAUSTIVE_TEST_ORDER - *a; - } - - SECP256K1_SCALAR_VERIFY(r); -} - -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return *a == 1; -} - -static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - return *a > EXHAUSTIVE_TEST_ORDER / 2; -} - -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { - SECP256K1_SCALAR_VERIFY(r); - - if (flag) secp256k1_scalar_negate(r, r); - - SECP256K1_SCALAR_VERIFY(r); - return flag ? -1 : 1; -} - -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - *r1 = *a; - *r2 = 0; - - SECP256K1_SCALAR_VERIFY(r1); - SECP256K1_SCALAR_VERIFY(r2); -} - -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_SCALAR_VERIFY(b); - - return *a == *b; -} - -static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { - uint32_t mask0, mask1; - volatile int vflag = flag; - SECP256K1_SCALAR_VERIFY(a); - SECP256K1_CHECKMEM_CHECK_VERIFY(r, sizeof(*r)); - - mask0 = vflag + ~((uint32_t)0); - mask1 = ~mask0; - *r = (*r & mask0) | (*a & mask1); - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { - int i; - uint32_t res = 0; - SECP256K1_SCALAR_VERIFY(x); - - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) { - res = i; - break; - } - } - - /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus - * have a composite group order; fix it in exhaustive_tests.c). */ - VERIFY_CHECK(res != 0); - *r = res; - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { - SECP256K1_SCALAR_VERIFY(x); - - secp256k1_scalar_inverse(r, x); - - SECP256K1_SCALAR_VERIFY(r); -} - -static void secp256k1_scalar_half(secp256k1_scalar *r, const secp256k1_scalar *a) { - SECP256K1_SCALAR_VERIFY(a); - - *r = (*a + ((-(uint32_t)(*a & 1)) & EXHAUSTIVE_TEST_ORDER)) >> 1; - - SECP256K1_SCALAR_VERIFY(r); -} - -#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/external/secp256k1/src/scratch.h b/external/secp256k1/src/scratch.h deleted file mode 100644 index 6164330b39..0000000000 --- a/external/secp256k1/src/scratch.h +++ /dev/null @@ -1,44 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2017 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCRATCH_H -#define SECP256K1_SCRATCH_H - -/* The typedef is used internally; the struct name is used in the public API - * (where it is exposed as a different typedef) */ -typedef struct secp256k1_scratch_space_struct { - /** guard against interpreting this object as other types */ - unsigned char magic[8]; - /** actual allocated data */ - void *data; - /** amount that has been allocated (i.e. `data + offset` is the next - * available pointer) */ - size_t alloc_size; - /** maximum size available to allocate */ - size_t max_size; -} secp256k1_scratch; - -typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space; - -static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size); - -static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch); - -/** Returns an opaque object used to "checkpoint" a scratch space. Used - * with `secp256k1_scratch_apply_checkpoint` to undo allocations. */ -static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch); - -/** Applies a check point received from `secp256k1_scratch_checkpoint`, - * undoing all allocations since that point. */ -static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint); - -/** Returns the maximum allocation the scratch space will allow */ -static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t n_objects); - -/** Returns a pointer into the most recently allocated frame, or NULL if there is insufficient available space */ -static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t n); - -#endif diff --git a/external/secp256k1/src/scratch_impl.h b/external/secp256k1/src/scratch_impl.h deleted file mode 100644 index f71a20b963..0000000000 --- a/external/secp256k1/src/scratch_impl.h +++ /dev/null @@ -1,99 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2017 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SCRATCH_IMPL_H -#define SECP256K1_SCRATCH_IMPL_H - -#include "util.h" -#include "scratch.h" - -static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) { - const size_t base_alloc = ROUND_TO_ALIGN(sizeof(secp256k1_scratch)); - void *alloc = checked_malloc(error_callback, base_alloc + size); - secp256k1_scratch* ret = (secp256k1_scratch *)alloc; - if (ret != NULL) { - memset(ret, 0, sizeof(*ret)); - memcpy(ret->magic, "scratch", 8); - ret->data = (void *) ((char *) alloc + base_alloc); - ret->max_size = size; - } - return ret; -} - -static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) { - if (scratch != NULL) { - if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { - secp256k1_callback_call(error_callback, "invalid scratch space"); - return; - } - VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */ - memset(scratch->magic, 0, sizeof(scratch->magic)); - free(scratch); - } -} - -static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch) { - if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { - secp256k1_callback_call(error_callback, "invalid scratch space"); - return 0; - } - return scratch->alloc_size; -} - -static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint) { - if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { - secp256k1_callback_call(error_callback, "invalid scratch space"); - return; - } - if (checkpoint > scratch->alloc_size) { - secp256k1_callback_call(error_callback, "invalid checkpoint"); - return; - } - scratch->alloc_size = checkpoint; -} - -static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t objects) { - if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { - secp256k1_callback_call(error_callback, "invalid scratch space"); - return 0; - } - /* Ensure that multiplication will not wrap around */ - if (ALIGNMENT > 1 && objects > SIZE_MAX/(ALIGNMENT - 1)) { - return 0; - } - if (scratch->max_size - scratch->alloc_size <= objects * (ALIGNMENT - 1)) { - return 0; - } - return scratch->max_size - scratch->alloc_size - objects * (ALIGNMENT - 1); -} - -static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t size) { - void *ret; - size_t rounded_size; - - rounded_size = ROUND_TO_ALIGN(size); - /* Check that rounding did not wrap around */ - if (rounded_size < size) { - return NULL; - } - size = rounded_size; - - if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { - secp256k1_callback_call(error_callback, "invalid scratch space"); - return NULL; - } - - if (size > scratch->max_size - scratch->alloc_size) { - return NULL; - } - ret = (void *) ((char *) scratch->data + scratch->alloc_size); - memset(ret, 0, size); - scratch->alloc_size += size; - - return ret; -} - -#endif diff --git a/external/secp256k1/src/secp256k1.c b/external/secp256k1/src/secp256k1.c deleted file mode 100644 index a248519dfd..0000000000 --- a/external/secp256k1/src/secp256k1.c +++ /dev/null @@ -1,831 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -/* This is a C project. It should not be compiled with a C++ compiler, - * and we error out if we detect one. - * - * We still want to be able to test the project with a C++ compiler - * because it is still good to know if this will lead to real trouble, so - * there is a possibility to override the check. But be warned that - * compiling with a C++ compiler is not supported. */ -#if defined(__cplusplus) && !defined(SECP256K1_CPLUSPLUS_TEST_OVERRIDE) -#error Trying to compile a C project with a C++ compiler. -#endif - -#define SECP256K1_BUILD - -#include "../include/secp256k1.h" -#include "../include/secp256k1_preallocated.h" - -#include "assumptions.h" -#include "checkmem.h" -#include "util.h" - -#include "field_impl.h" -#include "scalar_impl.h" -#include "group_impl.h" -#include "ecmult_impl.h" -#include "ecmult_const_impl.h" -#include "ecmult_gen_impl.h" -#include "ecdsa_impl.h" -#include "eckey_impl.h" -#include "hash_impl.h" -#include "int128_impl.h" -#include "scratch_impl.h" -#include "selftest.h" -#include "hsort_impl.h" - -#ifdef SECP256K1_NO_BUILD -# error "secp256k1.h processed without SECP256K1_BUILD defined while building secp256k1.c" -#endif - -#define ARG_CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - secp256k1_callback_call(&ctx->illegal_callback, #cond); \ - return 0; \ - } \ -} while(0) - -#define ARG_CHECK_VOID(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - secp256k1_callback_call(&ctx->illegal_callback, #cond); \ - return; \ - } \ -} while(0) - -/* Note that whenever you change the context struct, you must also change the - * context_eq function. */ -struct secp256k1_context_struct { - secp256k1_ecmult_gen_context ecmult_gen_ctx; - secp256k1_callback illegal_callback; - secp256k1_callback error_callback; - int declassify; -}; - -static const secp256k1_context secp256k1_context_static_ = { - { 0 }, - { secp256k1_default_illegal_callback_fn, 0 }, - { secp256k1_default_error_callback_fn, 0 }, - 0 -}; -const secp256k1_context *secp256k1_context_static = &secp256k1_context_static_; -const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_static_; - -/* Helper function that determines if a context is proper, i.e., is not the static context or a copy thereof. - * - * This is intended for "context" functions such as secp256k1_context_clone. Functions that need specific - * features of a context should still check for these features directly. For example, a function that needs - * ecmult_gen should directly check for the existence of the ecmult_gen context. */ -static int secp256k1_context_is_proper(const secp256k1_context* ctx) { - return secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx); -} - -void secp256k1_selftest(void) { - if (!secp256k1_selftest_passes()) { - secp256k1_callback_call(&default_error_callback, "self test failed"); - } -} - -size_t secp256k1_context_preallocated_size(unsigned int flags) { - size_t ret = sizeof(secp256k1_context); - /* A return value of 0 is reserved as an indicator for errors when we call this function internally. */ - VERIFY_CHECK(ret != 0); - - if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { - secp256k1_callback_call(&default_illegal_callback, - "Invalid flags"); - return 0; - } - - if (EXPECT(!SECP256K1_CHECKMEM_RUNNING() && (flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY), 0)) { - secp256k1_callback_call(&default_illegal_callback, - "Declassify flag requires running with memory checking"); - return 0; - } - - return ret; -} - -size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_context_is_proper(ctx)); - return sizeof(secp256k1_context); -} - -secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) { - size_t prealloc_size; - secp256k1_context* ret; - - secp256k1_selftest(); - - prealloc_size = secp256k1_context_preallocated_size(flags); - if (prealloc_size == 0) { - return NULL; - } - VERIFY_CHECK(prealloc != NULL); - ret = (secp256k1_context*)prealloc; - ret->illegal_callback = default_illegal_callback; - ret->error_callback = default_error_callback; - - /* Flags have been checked by secp256k1_context_preallocated_size. */ - VERIFY_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_CONTEXT); - secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx); - ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY); - - return ret; -} - -secp256k1_context* secp256k1_context_create(unsigned int flags) { - size_t const prealloc_size = secp256k1_context_preallocated_size(flags); - secp256k1_context* ctx = (secp256k1_context*)checked_malloc(&default_error_callback, prealloc_size); - if (EXPECT(secp256k1_context_preallocated_create(ctx, flags) == NULL, 0)) { - free(ctx); - return NULL; - } - - return ctx; -} - -secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context* ctx, void* prealloc) { - secp256k1_context* ret; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(prealloc != NULL); - ARG_CHECK(secp256k1_context_is_proper(ctx)); - - ret = (secp256k1_context*)prealloc; - *ret = *ctx; - return ret; -} - -secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { - secp256k1_context* ret; - size_t prealloc_size; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_context_is_proper(ctx)); - - prealloc_size = secp256k1_context_preallocated_clone_size(ctx); - ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size); - ret = secp256k1_context_preallocated_clone(ctx, ret); - return ret; -} - -void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) { - ARG_CHECK_VOID(ctx == NULL || secp256k1_context_is_proper(ctx)); - - /* Defined as noop */ - if (ctx == NULL) { - return; - } - - secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); -} - -void secp256k1_context_destroy(secp256k1_context* ctx) { - ARG_CHECK_VOID(ctx == NULL || secp256k1_context_is_proper(ctx)); - - /* Defined as noop */ - if (ctx == NULL) { - return; - } - - secp256k1_context_preallocated_destroy(ctx); - free(ctx); -} - -void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - /* We compare pointers instead of checking secp256k1_context_is_proper() here - because setting callbacks is allowed on *copies* of the static context: - it's harmless and makes testing easier. */ - ARG_CHECK_VOID(ctx != secp256k1_context_static); - if (fun == NULL) { - fun = secp256k1_default_illegal_callback_fn; - } - ctx->illegal_callback.fn = fun; - ctx->illegal_callback.data = data; -} - -void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - /* We compare pointers instead of checking secp256k1_context_is_proper() here - because setting callbacks is allowed on *copies* of the static context: - it's harmless and makes testing easier. */ - ARG_CHECK_VOID(ctx != secp256k1_context_static); - if (fun == NULL) { - fun = secp256k1_default_error_callback_fn; - } - ctx->error_callback.fn = fun; - ctx->error_callback.data = data; -} - -static secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) { - VERIFY_CHECK(ctx != NULL); - return secp256k1_scratch_create(&ctx->error_callback, max_size); -} - -static void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scratch_space* scratch) { - VERIFY_CHECK(ctx != NULL); - secp256k1_scratch_destroy(&ctx->error_callback, scratch); -} - -/* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour - * of the software. - */ -static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len) { - if (EXPECT(ctx->declassify, 0)) SECP256K1_CHECKMEM_DEFINE(p, len); -} - -static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { - secp256k1_ge_from_bytes(ge, pubkey->data); - ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); - return 1; -} - -static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { - secp256k1_ge_to_bytes(pubkey->data, ge); -} - -int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { - secp256k1_ge Q; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(input != NULL); - if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { - return 0; - } - if (!secp256k1_ge_is_in_correct_subgroup(&Q)) { - return 0; - } - secp256k1_pubkey_save(pubkey, &Q); - secp256k1_ge_clear(&Q); - return 1; -} - -int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { - secp256k1_ge Q; - size_t len; - int ret = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(outputlen != NULL); - ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33u : 65u)); - len = *outputlen; - *outputlen = 0; - ARG_CHECK(output != NULL); - memset(output, 0, len); - ARG_CHECK(pubkey != NULL); - ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); - if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { - ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); - if (ret) { - *outputlen = len; - } - } - return ret; -} - -int secp256k1_ec_pubkey_cmp(const secp256k1_context* ctx, const secp256k1_pubkey* pubkey0, const secp256k1_pubkey* pubkey1) { - unsigned char out[2][33]; - const secp256k1_pubkey* pk[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - pk[0] = pubkey0; pk[1] = pubkey1; - for (i = 0; i < 2; i++) { - size_t out_size = sizeof(out[i]); - /* If the public key is NULL or invalid, ec_pubkey_serialize will call - * the illegal_callback and return 0. In that case we will serialize the - * key as all zeros which is less than any valid public key. This - * results in consistent comparisons even if NULL or invalid pubkeys are - * involved and prevents edge cases such as sorting algorithms that use - * this function and do not terminate as a result. */ - if (!secp256k1_ec_pubkey_serialize(ctx, out[i], &out_size, pk[i], SECP256K1_EC_COMPRESSED)) { - /* Note that ec_pubkey_serialize should already set the output to - * zero in that case, but it's not guaranteed by the API, we can't - * test it and writing a VERIFY_CHECK is more complex than - * explicitly memsetting (again). */ - memset(out[i], 0, sizeof(out[i])); - } - } - return secp256k1_memcmp_var(out[0], out[1], sizeof(out[0])); -} - -static int secp256k1_ec_pubkey_sort_cmp(const void* pk1, const void* pk2, void *ctx) { - return secp256k1_ec_pubkey_cmp((secp256k1_context *)ctx, - *(secp256k1_pubkey **)pk1, - *(secp256k1_pubkey **)pk2); -} - -int secp256k1_ec_pubkey_sort(const secp256k1_context* ctx, const secp256k1_pubkey **pubkeys, size_t n_pubkeys) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkeys != NULL); - - /* Suppress wrong warning (fixed in MSVC 19.33) */ - #if defined(_MSC_VER) && (_MSC_VER < 1933) - #pragma warning(push) - #pragma warning(disable: 4090) - #endif - - /* Casting away const is fine because neither secp256k1_hsort nor - * secp256k1_ec_pubkey_sort_cmp modify the data pointed to by the cmp_data - * argument. */ - secp256k1_hsort(pubkeys, n_pubkeys, sizeof(*pubkeys), secp256k1_ec_pubkey_sort_cmp, (void *)ctx); - - #if defined(_MSC_VER) && (_MSC_VER < 1933) - #pragma warning(pop) - #endif - - return 1; -} - -static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { - (void)ctx; - if (sizeof(secp256k1_scalar) == 32) { - /* When the secp256k1_scalar type is exactly 32 byte, use its - * representation inside secp256k1_ecdsa_signature, as conversion is very fast. - * Note that secp256k1_ecdsa_signature_save must use the same representation. */ - memcpy(r, &sig->data[0], 32); - memcpy(s, &sig->data[32], 32); - } else { - secp256k1_scalar_set_b32(r, &sig->data[0], NULL); - secp256k1_scalar_set_b32(s, &sig->data[32], NULL); - } -} - -static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { - if (sizeof(secp256k1_scalar) == 32) { - memcpy(&sig->data[0], r, 32); - memcpy(&sig->data[32], s, 32); - } else { - secp256k1_scalar_get_b32(&sig->data[0], r); - secp256k1_scalar_get_b32(&sig->data[32], s); - } -} - -int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(input != NULL); - - if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { - secp256k1_ecdsa_signature_save(sig, &r, &s); - return 1; - } else { - memset(sig, 0, sizeof(*sig)); - return 0; - } -} - -int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) { - secp256k1_scalar r, s; - int ret = 1; - int overflow = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(input64 != NULL); - - secp256k1_scalar_set_b32(&r, &input64[0], &overflow); - ret &= !overflow; - secp256k1_scalar_set_b32(&s, &input64[32], &overflow); - ret &= !overflow; - if (ret) { - secp256k1_ecdsa_signature_save(sig, &r, &s); - } else { - memset(sig, 0, sizeof(*sig)); - } - return ret; -} - -int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output != NULL); - ARG_CHECK(outputlen != NULL); - ARG_CHECK(sig != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); -} - -int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) { - secp256k1_scalar r, s; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(output64 != NULL); - ARG_CHECK(sig != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - secp256k1_scalar_get_b32(&output64[0], &r); - secp256k1_scalar_get_b32(&output64[32], &s); - return 1; -} - -int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) { - secp256k1_scalar r, s; - int ret = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sigin != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin); - ret = secp256k1_scalar_is_high(&s); - if (sigout != NULL) { - if (ret) { - secp256k1_scalar_negate(&s, &s); - } - secp256k1_ecdsa_signature_save(sigout, &r, &s); - } - - return ret; -} - -int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msghash32, const secp256k1_pubkey *pubkey) { - secp256k1_ge q; - secp256k1_scalar r, s; - secp256k1_scalar m; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(msghash32 != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_scalar_set_b32(&m, msghash32, NULL); - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - return (!secp256k1_scalar_is_high(&s) && - secp256k1_pubkey_load(ctx, &q, pubkey) && - secp256k1_ecdsa_sig_verify(&r, &s, &q, &m)); -} - -static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) { - memcpy(buf + *offset, data, len); - *offset += len; -} - -static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - unsigned char keydata[112]; - unsigned int offset = 0; - secp256k1_rfc6979_hmac_sha256 rng; - unsigned int i; - secp256k1_scalar msg; - unsigned char msgmod32[32]; - secp256k1_scalar_set_b32(&msg, msg32, NULL); - secp256k1_scalar_get_b32(msgmod32, &msg); - /* We feed a byte array to the PRNG as input, consisting of: - * - the private key (32 bytes) and reduced message (32 bytes), see RFC 6979 3.2d. - * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. - * - optionally 16 extra bytes with the algorithm name. - * Because the arguments have distinct fixed lengths it is not possible for - * different argument mixtures to emulate each other and result in the same - * nonces. - */ - buffer_append(keydata, &offset, key32, 32); - buffer_append(keydata, &offset, msgmod32, 32); - if (data != NULL) { - buffer_append(keydata, &offset, data, 32); - } - if (algo16 != NULL) { - buffer_append(keydata, &offset, algo16, 16); - } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); - for (i = 0; i <= counter; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - - secp256k1_memclear(keydata, sizeof(keydata)); - secp256k1_rfc6979_hmac_sha256_clear(&rng); - return 1; -} - -const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; -const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; - -static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar sec, non, msg; - int ret = 0; - int is_sec_valid; - unsigned char nonce32[32]; - unsigned int count = 0; - /* Default initialization here is important so we won't pass uninit values to the cmov in the end */ - *r = secp256k1_scalar_zero; - *s = secp256k1_scalar_zero; - if (recid) { - *recid = 0; - } - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - /* Fail if the secret key is invalid. */ - is_sec_valid = secp256k1_scalar_set_b32_seckey(&sec, seckey); - secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !is_sec_valid); - secp256k1_scalar_set_b32(&msg, msg32, NULL); - while (1) { - int is_nonce_valid; - ret = !!noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); - if (!ret) { - break; - } - is_nonce_valid = secp256k1_scalar_set_b32_seckey(&non, nonce32); - /* The nonce is still secret here, but it being invalid is less likely than 1:2^255. */ - secp256k1_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid)); - if (is_nonce_valid) { - ret = secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, r, s, &sec, &msg, &non, recid); - /* The final signature is no longer a secret, nor is the fact that we were successful or not. */ - secp256k1_declassify(ctx, &ret, sizeof(ret)); - if (ret) { - break; - } - } - count++; - } - /* We don't want to declassify is_sec_valid and therefore the range of - * seckey. As a result is_sec_valid is included in ret only after ret was - * used as a branching variable. */ - ret &= is_sec_valid; - secp256k1_memclear(nonce32, sizeof(nonce32)); - secp256k1_scalar_clear(&msg); - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - secp256k1_scalar_cmov(r, &secp256k1_scalar_zero, !ret); - secp256k1_scalar_cmov(s, &secp256k1_scalar_zero, !ret); - if (recid) { - const int zero = 0; - secp256k1_int_cmov(recid, &zero, !ret); - } - return ret; -} - -int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar r, s; - int ret; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msghash32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(seckey != NULL); - - ret = secp256k1_ecdsa_sign_inner(ctx, &r, &s, NULL, msghash32, seckey, noncefp, noncedata); - secp256k1_ecdsa_signature_save(signature, &r, &s); - return ret; -} - -int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { - secp256k1_scalar sec; - int ret; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - - ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); - secp256k1_scalar_clear(&sec); - return ret; -} - -static int secp256k1_ec_pubkey_create_helper(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar *seckey_scalar, secp256k1_ge *p, const unsigned char *seckey) { - secp256k1_gej pj; - int ret; - - ret = secp256k1_scalar_set_b32_seckey(seckey_scalar, seckey); - secp256k1_scalar_cmov(seckey_scalar, &secp256k1_scalar_one, !ret); - - secp256k1_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar); - secp256k1_ge_set_gej(p, &pj); - secp256k1_gej_clear(&pj); - return ret; -} - -int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { - secp256k1_ge p; - secp256k1_scalar seckey_scalar; - int ret = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(seckey != NULL); - - ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey); - secp256k1_pubkey_save(pubkey, &p); - secp256k1_memczero(pubkey, sizeof(*pubkey), !ret); - - secp256k1_scalar_clear(&seckey_scalar); - return ret; -} - -int secp256k1_ec_seckey_negate(const secp256k1_context* ctx, unsigned char *seckey) { - secp256k1_scalar sec; - int ret = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - - ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); - secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); - secp256k1_scalar_negate(&sec, &sec); - secp256k1_scalar_get_b32(seckey, &sec); - - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { - return secp256k1_ec_seckey_negate(ctx, seckey); -} - -int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) { - int ret = 0; - secp256k1_ge p; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - - ret = secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - secp256k1_ge_neg(&p, &p); - secp256k1_pubkey_save(pubkey, &p); - } - return ret; -} - - -static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak32) { - secp256k1_scalar term; - int overflow = 0; - int ret = 0; - - secp256k1_scalar_set_b32(&term, tweak32, &overflow); - ret = (!overflow) & secp256k1_eckey_privkey_tweak_add(sec, &term); - secp256k1_scalar_clear(&term); - return ret; -} - -int secp256k1_ec_seckey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - secp256k1_scalar sec; - int ret = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - ARG_CHECK(tweak32 != NULL); - - ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); - ret &= secp256k1_ec_seckey_tweak_add_helper(&sec, tweak32); - secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); - secp256k1_scalar_get_b32(seckey, &sec); - - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak32); -} - -static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *p, const unsigned char *tweak32) { - secp256k1_scalar term; - int overflow = 0; - secp256k1_scalar_set_b32(&term, tweak32, &overflow); - return !overflow && secp256k1_eckey_pubkey_tweak_add(p, &term); -} - -int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) { - secp256k1_ge p; - int ret = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(tweak32 != NULL); - - ret = secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&p, tweak32); - if (ret) { - secp256k1_pubkey_save(pubkey, &p); - } - - return ret; -} - -int secp256k1_ec_seckey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - secp256k1_scalar factor; - secp256k1_scalar sec; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - ARG_CHECK(tweak32 != NULL); - - secp256k1_scalar_set_b32(&factor, tweak32, &overflow); - ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); - ret &= (!overflow) & secp256k1_eckey_privkey_tweak_mul(&sec, &factor); - secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); - secp256k1_scalar_get_b32(seckey, &sec); - - secp256k1_scalar_clear(&sec); - secp256k1_scalar_clear(&factor); - return ret; -} - -int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - return secp256k1_ec_seckey_tweak_mul(ctx, seckey, tweak32); -} - -int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) { - secp256k1_ge p; - secp256k1_scalar factor; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(tweak32 != NULL); - - secp256k1_scalar_set_b32(&factor, tweak32, &overflow); - ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - if (secp256k1_eckey_pubkey_tweak_mul(&p, &factor)) { - secp256k1_pubkey_save(pubkey, &p); - } else { - ret = 0; - } - } - - return ret; -} - -int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_context_is_proper(ctx)); - - if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); - } - return 1; -} - -int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { - size_t i; - secp256k1_gej Qj; - secp256k1_ge Q; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubnonce != NULL); - memset(pubnonce, 0, sizeof(*pubnonce)); - ARG_CHECK(n >= 1); - ARG_CHECK(pubnonces != NULL); - - secp256k1_gej_set_infinity(&Qj); - - for (i = 0; i < n; i++) { - ARG_CHECK(pubnonces[i] != NULL); - secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); - secp256k1_gej_add_ge(&Qj, &Qj, &Q); - } - if (secp256k1_gej_is_infinity(&Qj)) { - return 0; - } - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(pubnonce, &Q); - return 1; -} - -int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32, const unsigned char *tag, size_t taglen, const unsigned char *msg, size_t msglen) { - secp256k1_sha256 sha; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(hash32 != NULL); - ARG_CHECK(tag != NULL); - ARG_CHECK(msg != NULL); - - secp256k1_sha256_initialize_tagged(&sha, tag, taglen); - secp256k1_sha256_write(&sha, msg, msglen); - secp256k1_sha256_finalize(&sha, hash32); - secp256k1_sha256_clear(&sha); - return 1; -} - -#ifdef ENABLE_MODULE_ECDH -# include "modules/ecdh/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "modules/recovery/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_EXTRAKEYS -# include "modules/extrakeys/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG -# include "modules/schnorrsig/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_MUSIG -# include "modules/musig/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT -# include "modules/ellswift/main_impl.h" -#endif diff --git a/external/secp256k1/src/selftest.h b/external/secp256k1/src/selftest.h deleted file mode 100644 index d083ac9524..0000000000 --- a/external/secp256k1/src/selftest.h +++ /dev/null @@ -1,32 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2020 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_SELFTEST_H -#define SECP256K1_SELFTEST_H - -#include "hash.h" - -#include - -static int secp256k1_selftest_sha256(void) { - static const char *input63 = "For this sample, this 63-byte string will be used as input data"; - static const unsigned char output32[32] = { - 0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, - 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42, - }; - unsigned char out[32]; - secp256k1_sha256 hasher; - secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); - secp256k1_sha256_finalize(&hasher, out); - return secp256k1_memcmp_var(out, output32, 32) == 0; -} - -static int secp256k1_selftest_passes(void) { - return secp256k1_selftest_sha256(); -} - -#endif /* SECP256K1_SELFTEST_H */ diff --git a/external/secp256k1/src/testrand.h b/external/secp256k1/src/testrand.h deleted file mode 100644 index 3c1ed3d45d..0000000000 --- a/external/secp256k1/src/testrand.h +++ /dev/null @@ -1,48 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_TESTRAND_H -#define SECP256K1_TESTRAND_H - -#include "util.h" - -/* A non-cryptographic RNG used only for test infrastructure. */ - -/** Seed the pseudorandom number generator for testing. */ -SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16); - -/** Generate a pseudorandom number in the range [0..2**32-1]. */ -SECP256K1_INLINE static uint32_t testrand32(void); - -/** Generate a pseudorandom number in the range [0..2**64-1]. */ -SECP256K1_INLINE static uint64_t testrand64(void); - -/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or - * more. */ -SECP256K1_INLINE static uint64_t testrand_bits(int bits); - -/** Generate a pseudorandom number in the range [0..range-1]. */ -static uint32_t testrand_int(uint32_t range); - -/** Generate a pseudorandom 32-byte array. */ -static void testrand256(unsigned char *b32); - -/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ -static void testrand256_test(unsigned char *b32); - -/** Generate pseudorandom bytes with long sequences of zero and one bits. */ -static void testrand_bytes_test(unsigned char *bytes, size_t len); - -/** Flip a single random bit in a byte array */ -static void testrand_flip(unsigned char *b, size_t len); - -/** Initialize the test RNG using (hex encoded) array up to 16 bytes, or randomly if hexseed is NULL. */ -static void testrand_init(const char* hexseed); - -/** Print final test information. */ -static void testrand_finish(void); - -#endif /* SECP256K1_TESTRAND_H */ diff --git a/external/secp256k1/src/testrand_impl.h b/external/secp256k1/src/testrand_impl.h deleted file mode 100644 index b84f5730a9..0000000000 --- a/external/secp256k1/src/testrand_impl.h +++ /dev/null @@ -1,167 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013-2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_TESTRAND_IMPL_H -#define SECP256K1_TESTRAND_IMPL_H - -#include -#include -#include - -#include "testrand.h" -#include "hash.h" -#include "util.h" - -static uint64_t secp256k1_test_state[4]; - -SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16) { - static const unsigned char PREFIX[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', ' ', 't', 'e', 's', 't', ' ', 'i', 'n', 'i', 't'}; - unsigned char out32[32]; - secp256k1_sha256 hash; - int i; - - /* Use SHA256(PREFIX || seed16) as initial state. */ - secp256k1_sha256_initialize(&hash); - secp256k1_sha256_write(&hash, PREFIX, sizeof(PREFIX)); - secp256k1_sha256_write(&hash, seed16, 16); - secp256k1_sha256_finalize(&hash, out32); - for (i = 0; i < 4; ++i) { - uint64_t s = 0; - int j; - for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j]; - secp256k1_test_state[i] = s; - } -} - -SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) { - return (x << k) | (x >> (64 - k)); -} - -SECP256K1_INLINE static uint64_t testrand64(void) { - /* Test-only Xoshiro256++ RNG. See https://prng.di.unimi.it/ */ - const uint64_t result = rotl(secp256k1_test_state[0] + secp256k1_test_state[3], 23) + secp256k1_test_state[0]; - const uint64_t t = secp256k1_test_state[1] << 17; - secp256k1_test_state[2] ^= secp256k1_test_state[0]; - secp256k1_test_state[3] ^= secp256k1_test_state[1]; - secp256k1_test_state[1] ^= secp256k1_test_state[2]; - secp256k1_test_state[0] ^= secp256k1_test_state[3]; - secp256k1_test_state[2] ^= t; - secp256k1_test_state[3] = rotl(secp256k1_test_state[3], 45); - return result; -} - -SECP256K1_INLINE static uint64_t testrand_bits(int bits) { - if (bits == 0) return 0; - return testrand64() >> (64 - bits); -} - -SECP256K1_INLINE static uint32_t testrand32(void) { - return testrand64() >> 32; -} - -static uint32_t testrand_int(uint32_t range) { - uint32_t mask = 0; - uint32_t range_copy; - /* Reduce range by 1, changing its meaning to "maximum value". */ - VERIFY_CHECK(range != 0); - range -= 1; - /* Count the number of bits in range. */ - range_copy = range; - while (range_copy) { - mask = (mask << 1) | 1U; - range_copy >>= 1; - } - /* Generation loop. */ - while (1) { - uint32_t val = testrand64() & mask; - if (val <= range) return val; - } -} - -static void testrand256(unsigned char *b32) { - int i; - for (i = 0; i < 4; ++i) { - uint64_t val = testrand64(); - b32[0] = val; - b32[1] = val >> 8; - b32[2] = val >> 16; - b32[3] = val >> 24; - b32[4] = val >> 32; - b32[5] = val >> 40; - b32[6] = val >> 48; - b32[7] = val >> 56; - b32 += 8; - } -} - -static void testrand_bytes_test(unsigned char *bytes, size_t len) { - size_t bits = 0; - memset(bytes, 0, len); - while (bits < len * 8) { - int now; - uint32_t val; - now = 1 + (testrand_bits(6) * testrand_bits(5) + 16) / 31; - val = testrand_bits(1); - while (now > 0 && bits < len * 8) { - bytes[bits / 8] |= val << (bits % 8); - now--; - bits++; - } - } -} - -static void testrand256_test(unsigned char *b32) { - testrand_bytes_test(b32, 32); -} - -static void testrand_flip(unsigned char *b, size_t len) { - b[testrand_int(len)] ^= (1 << testrand_bits(3)); -} - -static void testrand_init(const char* hexseed) { - unsigned char seed16[16] = {0}; - if (hexseed && strlen(hexseed) != 0) { - int pos = 0; - while (pos < 16 && hexseed[0] != 0 && hexseed[1] != 0) { - unsigned short sh; - if ((sscanf(hexseed, "%2hx", &sh)) == 1) { - seed16[pos] = sh; - } else { - break; - } - hexseed += 2; - pos++; - } - } else { - FILE *frand = fopen("/dev/urandom", "rb"); - if ((frand == NULL) || fread(&seed16, 1, sizeof(seed16), frand) != sizeof(seed16)) { - uint64_t t = time(NULL) * (uint64_t)1337; - fprintf(stderr, "WARNING: could not read 16 bytes from /dev/urandom; falling back to insecure PRNG\n"); - seed16[0] ^= t; - seed16[1] ^= t >> 8; - seed16[2] ^= t >> 16; - seed16[3] ^= t >> 24; - seed16[4] ^= t >> 32; - seed16[5] ^= t >> 40; - seed16[6] ^= t >> 48; - seed16[7] ^= t >> 56; - } - if (frand) { - fclose(frand); - } - } - - printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); - testrand_seed(seed16); -} - -static void testrand_finish(void) { - unsigned char run32[32]; - testrand256(run32); - printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); -} - -#endif /* SECP256K1_TESTRAND_IMPL_H */ diff --git a/external/secp256k1/src/tests.c b/external/secp256k1/src/tests.c deleted file mode 100644 index 78533b11c2..0000000000 --- a/external/secp256k1/src/tests.c +++ /dev/null @@ -1,7841 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#include -#include -#include - -#include - -#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS - #pragma message("Ignoring USE_EXTERNAL_CALLBACKS in tests.") - #undef USE_EXTERNAL_DEFAULT_CALLBACKS -#endif -#if defined(VERIFY) && defined(COVERAGE) - #pragma message("Defining VERIFY for tests being built for coverage analysis support is meaningless.") -#endif -#include "secp256k1.c" - -#include "../include/secp256k1.h" -#include "../include/secp256k1_preallocated.h" -#include "testrand_impl.h" -#include "checkmem.h" -#include "testutil.h" -#include "util.h" - -#include "../contrib/lax_der_parsing.c" -#include "../contrib/lax_der_privatekey_parsing.c" - -#include "modinv32_impl.h" -#ifdef SECP256K1_WIDEMUL_INT128 -#include "modinv64_impl.h" -#include "int128_impl.h" -#endif - -#define CONDITIONAL_TEST(cnt, nam) if (COUNT < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else - -static int COUNT = 16; -static secp256k1_context *CTX = NULL; -static secp256k1_context *STATIC_CTX = NULL; - -static int all_bytes_equal(const void* s, unsigned char value, size_t n) { - const unsigned char *p = s; - size_t i; - - for (i = 0; i < n; i++) { - if (p[i] != value) { - return 0; - } - } - return 1; -} - -#define CHECK_COUNTING_CALLBACK_VOID(ctx, expr_or_stmt, callback, callback_setter) do { \ - int32_t _calls_to_callback = 0; \ - secp256k1_callback _saved_callback = ctx->callback; \ - callback_setter(ctx, counting_callback_fn, &_calls_to_callback); \ - { expr_or_stmt; } \ - ctx->callback = _saved_callback; \ - CHECK(_calls_to_callback == 1); \ -} while(0); - -/* CHECK that expr_or_stmt calls the error or illegal callback of ctx exactly once - * - * Useful for checking functions that return void (e.g., API functions that use ARG_CHECK_VOID) */ -#define CHECK_ERROR_VOID(ctx, expr_or_stmt) \ - CHECK_COUNTING_CALLBACK_VOID(ctx, expr_or_stmt, error_callback, secp256k1_context_set_error_callback) -#define CHECK_ILLEGAL_VOID(ctx, expr_or_stmt) \ - CHECK_COUNTING_CALLBACK_VOID(ctx, expr_or_stmt, illegal_callback, secp256k1_context_set_illegal_callback) - -/* CHECK that - * - expr calls the illegal callback of ctx exactly once and, - * - expr == 0 (or equivalently, expr == NULL) - * - * Useful for checking functions that return an integer or a pointer. */ -#define CHECK_ILLEGAL(ctx, expr) CHECK_ILLEGAL_VOID(ctx, CHECK((expr) == 0)) -#define CHECK_ERROR(ctx, expr) CHECK_ERROR_VOID(ctx, CHECK((expr) == 0)) - -static void counting_callback_fn(const char* str, void* data) { - /* Dummy callback function that just counts. */ - int32_t *p; - (void)str; - p = data; - CHECK(*p != INT32_MAX); - (*p)++; -} - -static void uncounting_illegal_callback_fn(const char* str, void* data) { - /* Dummy callback function that just counts (backwards). */ - int32_t *p; - (void)str; - p = data; - CHECK(*p != INT32_MIN); - (*p)--; -} - -static void run_xoshiro256pp_tests(void) { - { - size_t i; - /* Sanity check that we run before the actual seeding. */ - for (i = 0; i < sizeof(secp256k1_test_state)/sizeof(secp256k1_test_state[0]); i++) { - CHECK(secp256k1_test_state[i] == 0); - } - } - { - int i; - unsigned char buf32[32]; - unsigned char seed16[16] = { - 'C', 'H', 'I', 'C', 'K', 'E', 'N', '!', - 'C', 'H', 'I', 'C', 'K', 'E', 'N', '!', - }; - unsigned char buf32_expected[32] = { - 0xAF, 0xCC, 0xA9, 0x16, 0xB5, 0x6C, 0xE3, 0xF0, - 0x44, 0x3F, 0x45, 0xE0, 0x47, 0xA5, 0x08, 0x36, - 0x4C, 0xCC, 0xC1, 0x18, 0xB2, 0xD8, 0x8F, 0xEF, - 0x43, 0x26, 0x15, 0x57, 0x37, 0x00, 0xEF, 0x30, - }; - testrand_seed(seed16); - for (i = 0; i < 17; i++) { - testrand256(buf32); - } - CHECK(secp256k1_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0); - } -} - -static void run_selftest_tests(void) { - /* Test public API */ - secp256k1_selftest(); -} - -static int ecmult_gen_context_eq(const secp256k1_ecmult_gen_context *a, const secp256k1_ecmult_gen_context *b) { - return a->built == b->built - && secp256k1_scalar_eq(&a->scalar_offset, &b->scalar_offset) - && secp256k1_ge_eq_var(&a->ge_offset, &b->ge_offset) - && secp256k1_fe_equal(&a->proj_blind, &b->proj_blind); -} - -static int context_eq(const secp256k1_context *a, const secp256k1_context *b) { - return a->declassify == b->declassify - && ecmult_gen_context_eq(&a->ecmult_gen_ctx, &b->ecmult_gen_ctx) - && a->illegal_callback.fn == b->illegal_callback.fn - && a->illegal_callback.data == b->illegal_callback.data - && a->error_callback.fn == b->error_callback.fn - && a->error_callback.data == b->error_callback.data; -} - -static void run_deprecated_context_flags_test(void) { - /* Check that a context created with any of the flags in the flags array is - * identical to the NONE context. */ - unsigned int flags[] = { SECP256K1_CONTEXT_SIGN, - SECP256K1_CONTEXT_VERIFY, - SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY }; - secp256k1_context *none_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - int i; - for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++) { - secp256k1_context *tmp_ctx; - CHECK(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE) == secp256k1_context_preallocated_size(flags[i])); - tmp_ctx = secp256k1_context_create(flags[i]); - CHECK(context_eq(none_ctx, tmp_ctx)); - secp256k1_context_destroy(tmp_ctx); - } - secp256k1_context_destroy(none_ctx); -} - -static void run_ec_illegal_argument_tests(void) { - secp256k1_pubkey pubkey; - secp256k1_pubkey zero_pubkey; - secp256k1_ecdsa_signature sig; - unsigned char ctmp[32]; - - /* Setup */ - memset(ctmp, 1, 32); - memset(&zero_pubkey, 0, sizeof(zero_pubkey)); - - /* Verify context-type checking illegal-argument errors. */ - CHECK_ILLEGAL(STATIC_CTX, secp256k1_ec_pubkey_create(STATIC_CTX, &pubkey, ctmp)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_ecdsa_sign(STATIC_CTX, &sig, ctmp, ctmp, NULL, NULL)); - SECP256K1_CHECKMEM_UNDEFINE(&sig, sizeof(sig)); - CHECK(secp256k1_ecdsa_sign(CTX, &sig, ctmp, ctmp, NULL, NULL) == 1); - SECP256K1_CHECKMEM_CHECK(&sig, sizeof(sig)); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, ctmp, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(STATIC_CTX, &sig, ctmp, &pubkey) == 1); - CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, ctmp) == 1); - CHECK(secp256k1_ec_pubkey_tweak_add(STATIC_CTX, &pubkey, ctmp) == 1); - CHECK(secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey, ctmp) == 1); - CHECK(secp256k1_ec_pubkey_negate(STATIC_CTX, &pubkey) == 1); - CHECK(secp256k1_ec_pubkey_negate(CTX, &pubkey) == 1); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_ec_pubkey_negate(STATIC_CTX, &zero_pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_negate(CTX, NULL)); - CHECK(secp256k1_ec_pubkey_tweak_mul(STATIC_CTX, &pubkey, ctmp) == 1); -} - -static void run_static_context_tests(int use_prealloc) { - /* Check that deprecated secp256k1_context_no_precomp is an alias to secp256k1_context_static. */ - CHECK(secp256k1_context_no_precomp == secp256k1_context_static); - - { - unsigned char seed[32] = {0x17}; - - /* Randomizing secp256k1_context_static is not supported. */ - CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_randomize(STATIC_CTX, seed)); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_randomize(STATIC_CTX, NULL)); - - /* Destroying or cloning secp256k1_context_static is not supported. */ - if (use_prealloc) { - CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_preallocated_clone_size(STATIC_CTX)); - { - secp256k1_context *my_static_ctx = malloc(sizeof(*STATIC_CTX)); - CHECK(my_static_ctx != NULL); - memset(my_static_ctx, 0x2a, sizeof(*my_static_ctx)); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_preallocated_clone(STATIC_CTX, my_static_ctx)); - CHECK(all_bytes_equal(my_static_ctx, 0x2a, sizeof(*my_static_ctx))); - free(my_static_ctx); - } - CHECK_ILLEGAL_VOID(STATIC_CTX, secp256k1_context_preallocated_destroy(STATIC_CTX)); - } else { - CHECK_ILLEGAL(STATIC_CTX, secp256k1_context_clone(STATIC_CTX)); - CHECK_ILLEGAL_VOID(STATIC_CTX, secp256k1_context_destroy(STATIC_CTX)); - } - } - - { - /* Verify that setting and resetting illegal callback works */ - int32_t dummy = 0; - secp256k1_context_set_illegal_callback(STATIC_CTX, counting_callback_fn, &dummy); - CHECK(STATIC_CTX->illegal_callback.fn == counting_callback_fn); - CHECK(STATIC_CTX->illegal_callback.data == &dummy); - secp256k1_context_set_illegal_callback(STATIC_CTX, NULL, NULL); - CHECK(STATIC_CTX->illegal_callback.fn == secp256k1_default_illegal_callback_fn); - CHECK(STATIC_CTX->illegal_callback.data == NULL); - } -} - -static void run_proper_context_tests(int use_prealloc) { - int32_t dummy = 0; - secp256k1_context *my_ctx, *my_ctx_fresh; - void *my_ctx_prealloc = NULL; - unsigned char seed[32] = {0x17}; - - secp256k1_gej pubj; - secp256k1_ge pub; - secp256k1_scalar msg, key, nonce; - secp256k1_scalar sigr, sigs; - - /* Fresh reference context for comparison */ - my_ctx_fresh = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - - if (use_prealloc) { - my_ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); - CHECK(my_ctx_prealloc != NULL); - my_ctx = secp256k1_context_preallocated_create(my_ctx_prealloc, SECP256K1_CONTEXT_NONE); - } else { - my_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - } - - /* Randomize and reset randomization */ - CHECK(context_eq(my_ctx, my_ctx_fresh)); - CHECK(secp256k1_context_randomize(my_ctx, seed) == 1); - CHECK(!context_eq(my_ctx, my_ctx_fresh)); - CHECK(secp256k1_context_randomize(my_ctx, NULL) == 1); - CHECK(context_eq(my_ctx, my_ctx_fresh)); - - /* set error callback (to a function that still aborts in case malloc() fails in secp256k1_context_clone() below) */ - secp256k1_context_set_error_callback(my_ctx, secp256k1_default_illegal_callback_fn, NULL); - CHECK(my_ctx->error_callback.fn != secp256k1_default_error_callback_fn); - CHECK(my_ctx->error_callback.fn == secp256k1_default_illegal_callback_fn); - - /* check if sizes for cloning are consistent */ - CHECK(secp256k1_context_preallocated_clone_size(my_ctx) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); - - /*** clone and destroy all of them to make sure cloning was complete ***/ - { - secp256k1_context *ctx_tmp; - - if (use_prealloc) { - /* clone into a non-preallocated context and then again into a new preallocated one. */ - ctx_tmp = my_ctx; - my_ctx = secp256k1_context_clone(my_ctx); - CHECK(context_eq(ctx_tmp, my_ctx)); - secp256k1_context_preallocated_destroy(ctx_tmp); - - free(my_ctx_prealloc); - my_ctx_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); - CHECK(my_ctx_prealloc != NULL); - ctx_tmp = my_ctx; - my_ctx = secp256k1_context_preallocated_clone(my_ctx, my_ctx_prealloc); - CHECK(context_eq(ctx_tmp, my_ctx)); - secp256k1_context_destroy(ctx_tmp); - } else { - /* clone into a preallocated context and then again into a new non-preallocated one. */ - void *prealloc_tmp; - - prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); - CHECK(prealloc_tmp != NULL); - ctx_tmp = my_ctx; - my_ctx = secp256k1_context_preallocated_clone(my_ctx, prealloc_tmp); - CHECK(context_eq(ctx_tmp, my_ctx)); - secp256k1_context_destroy(ctx_tmp); - - ctx_tmp = my_ctx; - my_ctx = secp256k1_context_clone(my_ctx); - CHECK(context_eq(ctx_tmp, my_ctx)); - secp256k1_context_preallocated_destroy(ctx_tmp); - free(prealloc_tmp); - } - } - - /* Verify that the error callback makes it across the clone. */ - CHECK(my_ctx->error_callback.fn != secp256k1_default_error_callback_fn); - CHECK(my_ctx->error_callback.fn == secp256k1_default_illegal_callback_fn); - /* And that it resets back to default. */ - secp256k1_context_set_error_callback(my_ctx, NULL, NULL); - CHECK(my_ctx->error_callback.fn == secp256k1_default_error_callback_fn); - CHECK(context_eq(my_ctx, my_ctx_fresh)); - - /* Verify that setting and resetting illegal callback works */ - secp256k1_context_set_illegal_callback(my_ctx, counting_callback_fn, &dummy); - CHECK(my_ctx->illegal_callback.fn == counting_callback_fn); - CHECK(my_ctx->illegal_callback.data == &dummy); - secp256k1_context_set_illegal_callback(my_ctx, NULL, NULL); - CHECK(my_ctx->illegal_callback.fn == secp256k1_default_illegal_callback_fn); - CHECK(my_ctx->illegal_callback.data == NULL); - CHECK(context_eq(my_ctx, my_ctx_fresh)); - - /*** attempt to use them ***/ - testutil_random_scalar_order_test(&msg); - testutil_random_scalar_order_test(&key); - secp256k1_ecmult_gen(&my_ctx->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); - - /* obtain a working nonce */ - do { - testutil_random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&my_ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); - - /* try signing */ - CHECK(secp256k1_ecdsa_sig_sign(&my_ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); - - /* try verifying */ - CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); - - /* cleanup */ - if (use_prealloc) { - secp256k1_context_preallocated_destroy(my_ctx); - free(my_ctx_prealloc); - } else { - secp256k1_context_destroy(my_ctx); - } - secp256k1_context_destroy(my_ctx_fresh); - - /* Defined as no-op. */ - secp256k1_context_destroy(NULL); - secp256k1_context_preallocated_destroy(NULL); -} - -static void run_scratch_tests(void) { - const size_t adj_alloc = ((500 + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; - - size_t checkpoint; - size_t checkpoint_2; - secp256k1_scratch_space *scratch; - secp256k1_scratch_space local_scratch; - - /* Test public API */ - scratch = secp256k1_scratch_space_create(CTX, 1000); - CHECK(scratch != NULL); - - /* Test internal API */ - CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000); - CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1)); - CHECK(scratch->alloc_size == 0); - CHECK(scratch->alloc_size % ALIGNMENT == 0); - - /* Allocating 500 bytes succeeds */ - checkpoint = secp256k1_scratch_checkpoint(&CTX->error_callback, scratch); - CHECK(secp256k1_scratch_alloc(&CTX->error_callback, scratch, 500) != NULL); - CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000 - adj_alloc); - CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1)); - CHECK(scratch->alloc_size != 0); - CHECK(scratch->alloc_size % ALIGNMENT == 0); - - /* Allocating another 501 bytes fails */ - CHECK(secp256k1_scratch_alloc(&CTX->error_callback, scratch, 501) == NULL); - CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000 - adj_alloc); - CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1)); - CHECK(scratch->alloc_size != 0); - CHECK(scratch->alloc_size % ALIGNMENT == 0); - - /* ...but it succeeds once we apply the checkpoint to undo it */ - secp256k1_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); - CHECK(scratch->alloc_size == 0); - CHECK(secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000); - CHECK(secp256k1_scratch_alloc(&CTX->error_callback, scratch, 500) != NULL); - CHECK(scratch->alloc_size != 0); - - /* try to apply a bad checkpoint */ - checkpoint_2 = secp256k1_scratch_checkpoint(&CTX->error_callback, scratch); - secp256k1_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); - CHECK_ERROR_VOID(CTX, secp256k1_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint_2)); /* checkpoint_2 is after checkpoint */ - CHECK_ERROR_VOID(CTX, secp256k1_scratch_apply_checkpoint(&CTX->error_callback, scratch, (size_t) -1)); /* this is just wildly invalid */ - - /* try to use badly initialized scratch space */ - secp256k1_scratch_space_destroy(CTX, scratch); - memset(&local_scratch, 0, sizeof(local_scratch)); - scratch = &local_scratch; - CHECK_ERROR(CTX, secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0)); - CHECK_ERROR(CTX, secp256k1_scratch_alloc(&CTX->error_callback, scratch, 500)); - CHECK_ERROR_VOID(CTX, secp256k1_scratch_space_destroy(CTX, scratch)); - - /* Test that large integers do not wrap around in a bad way */ - scratch = secp256k1_scratch_space_create(CTX, 1000); - /* Try max allocation with a large number of objects. Only makes sense if - * ALIGNMENT is greater than 1 because otherwise the objects take no extra - * space. */ - CHECK(ALIGNMENT <= 1 || !secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1)); - /* Try allocating SIZE_MAX to test wrap around which only happens if - * ALIGNMENT > 1, otherwise it returns NULL anyway because the scratch - * space is too small. */ - CHECK(secp256k1_scratch_alloc(&CTX->error_callback, scratch, SIZE_MAX) == NULL); - secp256k1_scratch_space_destroy(CTX, scratch); - - /* cleanup */ - secp256k1_scratch_space_destroy(CTX, NULL); /* no-op */ -} - -static void run_ctz_tests(void) { - static const uint32_t b32[] = {1, 0xffffffff, 0x5e56968f, 0xe0d63129}; - static const uint64_t b64[] = {1, 0xffffffffffffffff, 0xbcd02462139b3fc3, 0x98b5f80c769693ef}; - int shift; - unsigned i; - for (i = 0; i < sizeof(b32) / sizeof(b32[0]); ++i) { - for (shift = 0; shift < 32; ++shift) { - CHECK(secp256k1_ctz32_var_debruijn(b32[i] << shift) == shift); - CHECK(secp256k1_ctz32_var(b32[i] << shift) == shift); - } - } - for (i = 0; i < sizeof(b64) / sizeof(b64[0]); ++i) { - for (shift = 0; shift < 64; ++shift) { - CHECK(secp256k1_ctz64_var_debruijn(b64[i] << shift) == shift); - CHECK(secp256k1_ctz64_var(b64[i] << shift) == shift); - } - } -} - -/***** HASH TESTS *****/ - -static void run_sha256_known_output_tests(void) { - static const char *inputs[] = { - "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "For this sample, this 63-byte string will be used as input data", - "This is exactly 64 bytes long, not counting the terminating byte", - "aaaaa", - }; - static const unsigned int repeat[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1000000/5 - }; - static const unsigned char outputs[][32] = { - {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}, - {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}, - {0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50}, - {0xf3, 0x0c, 0xeb, 0x2b, 0xb2, 0x82, 0x9e, 0x79, 0xe4, 0xca, 0x97, 0x53, 0xd3, 0x5a, 0x8e, 0xcc, 0x00, 0x26, 0x2d, 0x16, 0x4c, 0xc0, 0x77, 0x08, 0x02, 0x95, 0x38, 0x1c, 0xbd, 0x64, 0x3f, 0x0d}, - {0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30}, - {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}, - {0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42}, - {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8}, - {0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0}, - }; - unsigned int i, ninputs; - - /* Skip last input vector for low iteration counts */ - ninputs = sizeof(inputs)/sizeof(inputs[0]) - 1; - CONDITIONAL_TEST(16, "run_sha256_known_output_tests 1000000") ninputs++; - - for (i = 0; i < ninputs; i++) { - unsigned char out[32]; - secp256k1_sha256 hasher; - unsigned int j; - /* 1. Run: simply write the input bytestrings */ - j = repeat[i]; - secp256k1_sha256_initialize(&hasher); - while (j > 0) { - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - j--; - } - secp256k1_sha256_finalize(&hasher, out); - CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); - /* 2. Run: split the input bytestrings randomly before writing */ - if (strlen(inputs[i]) > 0) { - int split = testrand_int(strlen(inputs[i])); - secp256k1_sha256_initialize(&hasher); - j = repeat[i]; - while (j > 0) { - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - j--; - } - secp256k1_sha256_finalize(&hasher, out); - CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); - } - } -} - -/** SHA256 counter tests - -The tests verify that the SHA256 counter doesn't wrap around at message length -2^i bytes for i = 20, ..., 33. This wide range aims at being independent of the -implementation of the counter and it catches multiple natural 32-bit overflows -(e.g., counting bits, counting bytes, counting blocks, ...). - -The test vectors have been generated using following Python script which relies -on https://github.com/cloudtools/sha256/ (v0.3 on Python v3.10.2). - -``` -from sha256 import sha256 -from copy import copy - -def midstate_c_definition(hasher): - ret = ' {{0x' + hasher.state[0].hex('_', 4).replace('_', ', 0x') + '},\n' - ret += ' {0x00}, ' + str(hex(hasher.state[1])) + '}' - return ret - -def output_c_literal(hasher): - return '{0x' + hasher.digest().hex('_').replace('_', ', 0x') + '}' - -MESSAGE = b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno' -assert(len(MESSAGE) == 64) -BYTE_BOUNDARIES = [(2**b)//len(MESSAGE) - 1 for b in range(20, 34)] - -midstates = [] -digests = [] -hasher = sha256() -for i in range(BYTE_BOUNDARIES[-1] + 1): - if i in BYTE_BOUNDARIES: - midstates.append(midstate_c_definition(hasher)) - hasher_copy = copy(hasher) - hasher_copy.update(MESSAGE) - digests.append(output_c_literal(hasher_copy)) - hasher.update(MESSAGE) - -for x in midstates: - print(x + ',') - -for x in digests: - print(x + ',') -``` -*/ -static void run_sha256_counter_tests(void) { - static const char *input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"; - static const secp256k1_sha256 midstates[] = { - {{0xa2b5c8bb, 0x26c88bb3, 0x2abdc3d2, 0x9def99a3, 0xdfd21a6e, 0x41fe585b, 0x7ef2c440, 0x2b79adda}, - {0x00}, 0xfffc0}, - {{0xa0d29445, 0x9287de66, 0x76aabd71, 0x41acd765, 0x0c7528b4, 0x84e14906, 0x942faec6, 0xcc5a7b26}, - {0x00}, 0x1fffc0}, - {{0x50449526, 0xb9f1d657, 0xa0fc13e9, 0x50860f10, 0xa550c431, 0x3fbc97c1, 0x7bbb2d89, 0xdb67bac1}, - {0x00}, 0x3fffc0}, - {{0x54a6efdc, 0x46762e7b, 0x88bfe73f, 0xbbd149c7, 0x41620c43, 0x1168da7b, 0x2c5960f9, 0xeccffda6}, - {0x00}, 0x7fffc0}, - {{0x2515a8f5, 0x5faa2977, 0x3a850486, 0xac858cad, 0x7b7276ee, 0x235c0385, 0xc53a157c, 0x7cb3e69c}, - {0x00}, 0xffffc0}, - {{0x34f39828, 0x409fedb7, 0x4bbdd0fb, 0x3b643634, 0x7806bf2e, 0xe0d1b713, 0xca3f2e1e, 0xe38722c2}, - {0x00}, 0x1ffffc0}, - {{0x389ef5c5, 0x38c54167, 0x8f5d56ab, 0x582a75cc, 0x8217caef, 0xf10947dd, 0x6a1998a8, 0x048f0b8c}, - {0x00}, 0x3ffffc0}, - {{0xd6c3f394, 0x0bee43b9, 0x6783f497, 0x29fa9e21, 0x6ce491c1, 0xa81fe45e, 0x2fc3859a, 0x269012d0}, - {0x00}, 0x7ffffc0}, - {{0x6dd3c526, 0x44d88aa0, 0x806a1bae, 0xfbcc0d32, 0x9d6144f3, 0x9d2bd757, 0x9851a957, 0xb50430ad}, - {0x00}, 0xfffffc0}, - {{0x2add4021, 0xdfe8a9e6, 0xa56317c6, 0x7a15f5bb, 0x4a48aacd, 0x5d368414, 0x4f00e6f0, 0xd9355023}, - {0x00}, 0x1fffffc0}, - {{0xb66666b4, 0xdbeac32b, 0x0ea351ae, 0xcba9da46, 0x6278b874, 0x8c508e23, 0xe16ca776, 0x8465bac1}, - {0x00}, 0x3fffffc0}, - {{0xb6744789, 0x9cce87aa, 0xc4c478b7, 0xf38404d8, 0x2e38ba62, 0xa3f7019b, 0x50458fe7, 0x3047dbec}, - {0x00}, 0x7fffffc0}, - {{0x8b1297ba, 0xba261a80, 0x2ba1b0dd, 0xfbc67d6d, 0x61072c4e, 0x4b5a2a0f, 0x52872760, 0x2dfeb162}, - {0x00}, 0xffffffc0}, - {{0x24f33cf7, 0x41ad6583, 0x41c8ff5d, 0xca7ef35f, 0x50395756, 0x021b743e, 0xd7126cd7, 0xd037473a}, - {0x00}, 0x1ffffffc0}, - }; - static const unsigned char outputs[][32] = { - {0x0e, 0x83, 0xe2, 0xc9, 0x4f, 0xb2, 0xb8, 0x2b, 0x89, 0x06, 0x92, 0x78, 0x04, 0x03, 0x48, 0x5c, 0x48, 0x44, 0x67, 0x61, 0x77, 0xa4, 0xc7, 0x90, 0x9e, 0x92, 0x55, 0x10, 0x05, 0xfe, 0x39, 0x15}, - {0x1d, 0x1e, 0xd7, 0xb8, 0xa3, 0xa7, 0x8a, 0x79, 0xfd, 0xa0, 0x05, 0x08, 0x9c, 0xeb, 0xf0, 0xec, 0x67, 0x07, 0x9f, 0x8e, 0x3c, 0x0d, 0x8e, 0xf9, 0x75, 0x55, 0x13, 0xc1, 0xe8, 0x77, 0xf8, 0xbb}, - {0x66, 0x95, 0x6c, 0xc9, 0xe0, 0x39, 0x65, 0xb6, 0xb0, 0x05, 0xd1, 0xaf, 0xaf, 0xf3, 0x1d, 0xb9, 0xa4, 0xda, 0x6f, 0x20, 0xcd, 0x3a, 0xae, 0x64, 0xc2, 0xdb, 0xee, 0xf5, 0xb8, 0x8d, 0x57, 0x0e}, - {0x3c, 0xbb, 0x1c, 0x12, 0x5e, 0x17, 0xfd, 0x54, 0x90, 0x45, 0xa7, 0x7b, 0x61, 0x6c, 0x1d, 0xfe, 0xe6, 0xcc, 0x7f, 0xee, 0xcf, 0xef, 0x33, 0x35, 0x50, 0x62, 0x16, 0x70, 0x2f, 0x87, 0xc3, 0xc9}, - {0x53, 0x4d, 0xa8, 0xe7, 0x1e, 0x98, 0x73, 0x8d, 0xd9, 0xa3, 0x54, 0xa5, 0x0e, 0x59, 0x2c, 0x25, 0x43, 0x6f, 0xaa, 0xa2, 0xf5, 0x21, 0x06, 0x3e, 0xc9, 0x82, 0x06, 0x94, 0x98, 0x72, 0x9d, 0xa7}, - {0xef, 0x7e, 0xe9, 0x6b, 0xd3, 0xe5, 0xb7, 0x41, 0x4c, 0xc8, 0xd3, 0x07, 0x52, 0x9a, 0x5a, 0x8b, 0x4e, 0x1e, 0x75, 0xa4, 0x17, 0x78, 0xc8, 0x36, 0xcd, 0xf8, 0x2e, 0xd9, 0x57, 0xe3, 0xd7, 0x07}, - {0x87, 0x16, 0xfb, 0xf9, 0xa5, 0xf8, 0xc4, 0x56, 0x2b, 0x48, 0x52, 0x8e, 0x2d, 0x30, 0x85, 0xb6, 0x4c, 0x56, 0xb5, 0xd1, 0x16, 0x9c, 0xcf, 0x32, 0x95, 0xad, 0x03, 0xe8, 0x05, 0x58, 0x06, 0x76}, - {0x75, 0x03, 0x80, 0x28, 0xf2, 0xa7, 0x63, 0x22, 0x1a, 0x26, 0x9c, 0x68, 0xe0, 0x58, 0xfc, 0x73, 0xeb, 0x42, 0xf6, 0x86, 0x16, 0x24, 0x4b, 0xbc, 0x24, 0xf7, 0x02, 0xc8, 0x3d, 0x90, 0xe2, 0xb0}, - {0xdf, 0x49, 0x0f, 0x15, 0x7b, 0x7d, 0xbf, 0xe0, 0xd4, 0xcf, 0x47, 0xc0, 0x80, 0x93, 0x4a, 0x61, 0xaa, 0x03, 0x07, 0x66, 0xb3, 0x38, 0x5d, 0xc8, 0xc9, 0x07, 0x61, 0xfb, 0x97, 0x10, 0x2f, 0xd8}, - {0x77, 0x19, 0x40, 0x56, 0x41, 0xad, 0xbc, 0x59, 0xda, 0x1e, 0xc5, 0x37, 0x14, 0x63, 0x7b, 0xfb, 0x79, 0xe2, 0x7a, 0xb1, 0x55, 0x42, 0x99, 0x42, 0x56, 0xfe, 0x26, 0x9d, 0x0f, 0x7e, 0x80, 0xc6}, - {0x50, 0xe7, 0x2a, 0x0e, 0x26, 0x44, 0x2f, 0xe2, 0x55, 0x2d, 0xc3, 0x93, 0x8a, 0xc5, 0x86, 0x58, 0x22, 0x8c, 0x0c, 0xbf, 0xb1, 0xd2, 0xca, 0x87, 0x2a, 0xe4, 0x35, 0x26, 0x6f, 0xcd, 0x05, 0x5e}, - {0xe4, 0x80, 0x6f, 0xdb, 0x3d, 0x7d, 0xba, 0xde, 0x50, 0x3f, 0xea, 0x00, 0x3d, 0x46, 0x59, 0x64, 0xfd, 0x58, 0x1c, 0xa1, 0xb8, 0x7d, 0x5f, 0xac, 0x94, 0x37, 0x9e, 0xa0, 0xc0, 0x9c, 0x93, 0x8b}, - {0x2c, 0xf3, 0xa9, 0xf6, 0x15, 0x25, 0x80, 0x70, 0x76, 0x99, 0x7d, 0xf1, 0xc3, 0x2f, 0xa3, 0x31, 0xff, 0x92, 0x35, 0x2e, 0x8d, 0x04, 0x13, 0x33, 0xd8, 0x0d, 0xdb, 0x4a, 0xf6, 0x8c, 0x03, 0x34}, - {0xec, 0x12, 0x24, 0x9f, 0x35, 0xa4, 0x29, 0x8b, 0x9e, 0x4a, 0x95, 0xf8, 0x61, 0xaf, 0x61, 0xc5, 0x66, 0x55, 0x3e, 0x3f, 0x2a, 0x98, 0xea, 0x71, 0x16, 0x6b, 0x1c, 0xd9, 0xe4, 0x09, 0xd2, 0x8e}, - }; - unsigned int i; - for (i = 0; i < sizeof(midstates)/sizeof(midstates[0]); i++) { - unsigned char out[32]; - secp256k1_sha256 hasher = midstates[i]; - secp256k1_sha256_write(&hasher, (const unsigned char*)input, strlen(input)); - secp256k1_sha256_finalize(&hasher, out); - CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); - } -} - -/* Tests for the equality of two sha256 structs. This function only produces a - * correct result if an integer multiple of 64 many bytes have been written - * into the hash functions. This function is used by some module tests. */ -static void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) { - /* Is buffer fully consumed? */ - CHECK((sha1->bytes & 0x3F) == 0); - - CHECK(sha1->bytes == sha2->bytes); - CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); -} - -static void run_hmac_sha256_tests(void) { - static const char *keys[6] = { - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - "\x4a\x65\x66\x65", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - }; - static const char *inputs[6] = { - "\x48\x69\x20\x54\x68\x65\x72\x65", - "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69\x72\x73\x74", - "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e" - }; - static const unsigned char outputs[6][32] = { - {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7}, - {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43}, - {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe}, - {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b}, - {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54}, - {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} - }; - int i; - for (i = 0; i < 6; i++) { - secp256k1_hmac_sha256 hasher; - unsigned char out[32]; - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - secp256k1_hmac_sha256_finalize(&hasher, out); - CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); - if (strlen(inputs[i]) > 0) { - int split = testrand_int(strlen(inputs[i])); - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - secp256k1_hmac_sha256_finalize(&hasher, out); - CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); - } - } -} - -static void run_rfc6979_hmac_sha256_tests(void) { - static const unsigned char key1[65] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5, 0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3, 0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5, 0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a, 0}; - static const unsigned char out1[3][32] = { - {0x4f, 0xe2, 0x95, 0x25, 0xb2, 0x08, 0x68, 0x09, 0x15, 0x9a, 0xcd, 0xf0, 0x50, 0x6e, 0xfb, 0x86, 0xb0, 0xec, 0x93, 0x2c, 0x7b, 0xa4, 0x42, 0x56, 0xab, 0x32, 0x1e, 0x42, 0x1e, 0x67, 0xe9, 0xfb}, - {0x2b, 0xf0, 0xff, 0xf1, 0xd3, 0xc3, 0x78, 0xa2, 0x2d, 0xc5, 0xde, 0x1d, 0x85, 0x65, 0x22, 0x32, 0x5c, 0x65, 0xb5, 0x04, 0x49, 0x1a, 0x0c, 0xbd, 0x01, 0xcb, 0x8f, 0x3a, 0xa6, 0x7f, 0xfd, 0x4a}, - {0xf5, 0x28, 0xb4, 0x10, 0xcb, 0x54, 0x1f, 0x77, 0x00, 0x0d, 0x7a, 0xfb, 0x6c, 0x5b, 0x53, 0xc5, 0xc4, 0x71, 0xea, 0xb4, 0x3e, 0x46, 0x6d, 0x9a, 0xc5, 0x19, 0x0c, 0x39, 0xc8, 0x2f, 0xd8, 0x2e} - }; - - static const unsigned char key2[64] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; - static const unsigned char out2[3][32] = { - {0x9c, 0x23, 0x6c, 0x16, 0x5b, 0x82, 0xae, 0x0c, 0xd5, 0x90, 0x65, 0x9e, 0x10, 0x0b, 0x6b, 0xab, 0x30, 0x36, 0xe7, 0xba, 0x8b, 0x06, 0x74, 0x9b, 0xaf, 0x69, 0x81, 0xe1, 0x6f, 0x1a, 0x2b, 0x95}, - {0xdf, 0x47, 0x10, 0x61, 0x62, 0x5b, 0xc0, 0xea, 0x14, 0xb6, 0x82, 0xfe, 0xee, 0x2c, 0x9c, 0x02, 0xf2, 0x35, 0xda, 0x04, 0x20, 0x4c, 0x1d, 0x62, 0xa1, 0x53, 0x6c, 0x6e, 0x17, 0xae, 0xd7, 0xa9}, - {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} - }; - - secp256k1_rfc6979_hmac_sha256 rng; - unsigned char out[32]; - int i; - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(secp256k1_memcmp_var(out, out1[i], 32) == 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(secp256k1_memcmp_var(out, out1[i], 32) != 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); - for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(secp256k1_memcmp_var(out, out2[i], 32) == 0); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); -} - -static void run_tagged_sha256_tests(void) { - unsigned char tag[32] = { 0 }; - unsigned char msg[32] = { 0 }; - unsigned char hash32[32]; - unsigned char hash_expected[32] = { - 0x04, 0x7A, 0x5E, 0x17, 0xB5, 0x86, 0x47, 0xC1, - 0x3C, 0xC6, 0xEB, 0xC0, 0xAA, 0x58, 0x3B, 0x62, - 0xFB, 0x16, 0x43, 0x32, 0x68, 0x77, 0x40, 0x6C, - 0xE2, 0x76, 0x55, 0x9A, 0x3B, 0xDE, 0x55, 0xB3 - }; - - /* API test */ - CHECK(secp256k1_tagged_sha256(CTX, hash32, tag, sizeof(tag), msg, sizeof(msg)) == 1); - CHECK_ILLEGAL(CTX, secp256k1_tagged_sha256(CTX, NULL, tag, sizeof(tag), msg, sizeof(msg))); - CHECK_ILLEGAL(CTX, secp256k1_tagged_sha256(CTX, hash32, NULL, 0, msg, sizeof(msg))); - CHECK_ILLEGAL(CTX, secp256k1_tagged_sha256(CTX, hash32, tag, sizeof(tag), NULL, 0)); - - /* Static test vector */ - memcpy(tag, "tag", 3); - memcpy(msg, "msg", 3); - CHECK(secp256k1_tagged_sha256(CTX, hash32, tag, 3, msg, 3) == 1); - CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0); -} - -/***** MODINV TESTS *****/ - -/* Compute the modular inverse of (odd) x mod 2^64. */ -static uint64_t modinv2p64(uint64_t x) { - /* If w = 1/x mod 2^(2^L), then w*(2 - w*x) = 1/x mod 2^(2^(L+1)). See - * Hacker's Delight second edition, Henry S. Warren, Jr., pages 245-247 for - * why. Start with L=0, for which it is true for every odd x that - * 1/x=1 mod 2. Iterating 6 times gives us 1/x mod 2^64. */ - int l; - uint64_t w = 1; - CHECK(x & 1); - for (l = 0; l < 6; ++l) w *= (2 - w*x); - return w; -} - - -/* compute out = (a*b) mod m; if b=NULL, treat b=1; if m=NULL, treat m=infinity. - * - * Out is a 512-bit number (represented as 32 uint16_t's in LE order). The other - * arguments are 256-bit numbers (represented as 16 uint16_t's in LE order). */ -static void mulmod256(uint16_t* out, const uint16_t* a, const uint16_t* b, const uint16_t* m) { - uint16_t mul[32]; - uint64_t c = 0; - int i, j; - int m_bitlen = 0; - int mul_bitlen = 0; - - if (b != NULL) { - /* Compute the product of a and b, and put it in mul. */ - for (i = 0; i < 32; ++i) { - for (j = i <= 15 ? 0 : i - 15; j <= i && j <= 15; j++) { - c += (uint64_t)a[j] * b[i - j]; - } - mul[i] = c & 0xFFFF; - c >>= 16; - } - CHECK(c == 0); - - /* compute the highest set bit in mul */ - for (i = 511; i >= 0; --i) { - if ((mul[i >> 4] >> (i & 15)) & 1) { - mul_bitlen = i; - break; - } - } - } else { - /* if b==NULL, set mul=a. */ - memcpy(mul, a, 32); - memset(mul + 16, 0, 32); - /* compute the highest set bit in mul */ - for (i = 255; i >= 0; --i) { - if ((mul[i >> 4] >> (i & 15)) & 1) { - mul_bitlen = i; - break; - } - } - } - - if (m) { - /* Compute the highest set bit in m. */ - for (i = 255; i >= 0; --i) { - if ((m[i >> 4] >> (i & 15)) & 1) { - m_bitlen = i; - break; - } - } - - /* Try do mul -= m<= 0; --i) { - uint16_t mul2[32]; - int64_t cs; - - /* Compute mul2 = mul - m<= 0 && bitpos < 256) { - sub |= ((m[bitpos >> 4] >> (bitpos & 15)) & 1) << p; - } - } - /* Add mul[j]-sub to accumulator, and shift bottom 16 bits out to mul2[j]. */ - cs += mul[j]; - cs -= sub; - mul2[j] = (cs & 0xFFFF); - cs >>= 16; - } - /* If remainder of subtraction is 0, set mul = mul2. */ - if (cs == 0) { - memcpy(mul, mul2, sizeof(mul)); - } - } - /* Sanity check: test that all limbs higher than m's highest are zero */ - for (i = (m_bitlen >> 4) + 1; i < 32; ++i) { - CHECK(mul[i] == 0); - } - } - memcpy(out, mul, 32); -} - -/* Convert a 256-bit number represented as 16 uint16_t's to signed30 notation. */ -static void uint16_to_signed30(secp256k1_modinv32_signed30* out, const uint16_t* in) { - int i; - memset(out->v, 0, sizeof(out->v)); - for (i = 0; i < 256; ++i) { - out->v[i / 30] |= (int32_t)(((in[i >> 4]) >> (i & 15)) & 1) << (i % 30); - } -} - -/* Convert a 256-bit number in signed30 notation to a representation as 16 uint16_t's. */ -static void signed30_to_uint16(uint16_t* out, const secp256k1_modinv32_signed30* in) { - int i; - memset(out, 0, 32); - for (i = 0; i < 256; ++i) { - out[i >> 4] |= (((in->v[i / 30]) >> (i % 30)) & 1) << (i & 15); - } -} - -/* Randomly mutate the sign of limbs in signed30 representation, without changing the value. */ -static void mutate_sign_signed30(secp256k1_modinv32_signed30* x) { - int i; - for (i = 0; i < 16; ++i) { - int pos = testrand_bits(3); - if (x->v[pos] > 0 && x->v[pos + 1] <= 0x3fffffff) { - x->v[pos] -= 0x40000000; - x->v[pos + 1] += 1; - } else if (x->v[pos] < 0 && x->v[pos + 1] >= 0x3fffffff) { - x->v[pos] += 0x40000000; - x->v[pos + 1] -= 1; - } - } -} - -/* Test secp256k1_modinv32{_var}, using inputs in 16-bit limb format, and returning inverse. */ -static void test_modinv32_uint16(uint16_t* out, const uint16_t* in, const uint16_t* mod) { - uint16_t tmp[16]; - secp256k1_modinv32_signed30 x; - secp256k1_modinv32_modinfo m; - int i, vartime, nonzero; - - uint16_to_signed30(&x, in); - nonzero = (x.v[0] | x.v[1] | x.v[2] | x.v[3] | x.v[4] | x.v[5] | x.v[6] | x.v[7] | x.v[8]) != 0; - uint16_to_signed30(&m.modulus, mod); - - /* compute 1/modulus mod 2^30 */ - m.modulus_inv30 = modinv2p64(m.modulus.v[0]) & 0x3fffffff; - CHECK(((m.modulus_inv30 * m.modulus.v[0]) & 0x3fffffff) == 1); - - /* Test secp256k1_jacobi32_maybe_var. */ - if (nonzero) { - int jac; - uint16_t sqr[16], negone[16]; - mulmod256(sqr, in, in, mod); - uint16_to_signed30(&x, sqr); - /* Compute jacobi symbol of in^2, which must be 1 (or uncomputable). */ - jac = secp256k1_jacobi32_maybe_var(&x, &m); - CHECK(jac == 0 || jac == 1); - /* Then compute the jacobi symbol of -(in^2). x and -x have opposite - * jacobi symbols if and only if (mod % 4) == 3. */ - negone[0] = mod[0] - 1; - for (i = 1; i < 16; ++i) negone[i] = mod[i]; - mulmod256(sqr, sqr, negone, mod); - uint16_to_signed30(&x, sqr); - jac = secp256k1_jacobi32_maybe_var(&x, &m); - CHECK(jac == 0 || jac == 1 - (mod[0] & 2)); - } - - uint16_to_signed30(&x, in); - mutate_sign_signed30(&m.modulus); - for (vartime = 0; vartime < 2; ++vartime) { - /* compute inverse */ - (vartime ? secp256k1_modinv32_var : secp256k1_modinv32)(&x, &m); - - /* produce output */ - signed30_to_uint16(out, &x); - - /* check if the inverse times the input is 1 (mod m), unless x is 0. */ - mulmod256(tmp, out, in, mod); - CHECK(tmp[0] == nonzero); - for (i = 1; i < 16; ++i) CHECK(tmp[i] == 0); - - /* invert again */ - (vartime ? secp256k1_modinv32_var : secp256k1_modinv32)(&x, &m); - - /* check if the result is equal to the input */ - signed30_to_uint16(tmp, &x); - for (i = 0; i < 16; ++i) CHECK(tmp[i] == in[i]); - } -} - -#ifdef SECP256K1_WIDEMUL_INT128 -/* Convert a 256-bit number represented as 16 uint16_t's to signed62 notation. */ -static void uint16_to_signed62(secp256k1_modinv64_signed62* out, const uint16_t* in) { - int i; - memset(out->v, 0, sizeof(out->v)); - for (i = 0; i < 256; ++i) { - out->v[i / 62] |= (int64_t)(((in[i >> 4]) >> (i & 15)) & 1) << (i % 62); - } -} - -/* Convert a 256-bit number in signed62 notation to a representation as 16 uint16_t's. */ -static void signed62_to_uint16(uint16_t* out, const secp256k1_modinv64_signed62* in) { - int i; - memset(out, 0, 32); - for (i = 0; i < 256; ++i) { - out[i >> 4] |= (((in->v[i / 62]) >> (i % 62)) & 1) << (i & 15); - } -} - -/* Randomly mutate the sign of limbs in signed62 representation, without changing the value. */ -static void mutate_sign_signed62(secp256k1_modinv64_signed62* x) { - static const int64_t M62 = (int64_t)(UINT64_MAX >> 2); - int i; - for (i = 0; i < 8; ++i) { - int pos = testrand_bits(2); - if (x->v[pos] > 0 && x->v[pos + 1] <= M62) { - x->v[pos] -= (M62 + 1); - x->v[pos + 1] += 1; - } else if (x->v[pos] < 0 && x->v[pos + 1] >= -M62) { - x->v[pos] += (M62 + 1); - x->v[pos + 1] -= 1; - } - } -} - -/* Test secp256k1_modinv64{_var}, using inputs in 16-bit limb format, and returning inverse. */ -static void test_modinv64_uint16(uint16_t* out, const uint16_t* in, const uint16_t* mod) { - static const int64_t M62 = (int64_t)(UINT64_MAX >> 2); - uint16_t tmp[16]; - secp256k1_modinv64_signed62 x; - secp256k1_modinv64_modinfo m; - int i, vartime, nonzero; - - uint16_to_signed62(&x, in); - nonzero = (x.v[0] | x.v[1] | x.v[2] | x.v[3] | x.v[4]) != 0; - uint16_to_signed62(&m.modulus, mod); - - /* compute 1/modulus mod 2^62 */ - m.modulus_inv62 = modinv2p64(m.modulus.v[0]) & M62; - CHECK(((m.modulus_inv62 * m.modulus.v[0]) & M62) == 1); - - /* Test secp256k1_jacobi64_maybe_var. */ - if (nonzero) { - int jac; - uint16_t sqr[16], negone[16]; - mulmod256(sqr, in, in, mod); - uint16_to_signed62(&x, sqr); - /* Compute jacobi symbol of in^2, which must be 1 (or uncomputable). */ - jac = secp256k1_jacobi64_maybe_var(&x, &m); - CHECK(jac == 0 || jac == 1); - /* Then compute the jacobi symbol of -(in^2). x and -x have opposite - * jacobi symbols if and only if (mod % 4) == 3. */ - negone[0] = mod[0] - 1; - for (i = 1; i < 16; ++i) negone[i] = mod[i]; - mulmod256(sqr, sqr, negone, mod); - uint16_to_signed62(&x, sqr); - jac = secp256k1_jacobi64_maybe_var(&x, &m); - CHECK(jac == 0 || jac == 1 - (mod[0] & 2)); - } - - uint16_to_signed62(&x, in); - mutate_sign_signed62(&m.modulus); - for (vartime = 0; vartime < 2; ++vartime) { - /* compute inverse */ - (vartime ? secp256k1_modinv64_var : secp256k1_modinv64)(&x, &m); - - /* produce output */ - signed62_to_uint16(out, &x); - - /* check if the inverse times the input is 1 (mod m), unless x is 0. */ - mulmod256(tmp, out, in, mod); - CHECK(tmp[0] == nonzero); - for (i = 1; i < 16; ++i) CHECK(tmp[i] == 0); - - /* invert again */ - (vartime ? secp256k1_modinv64_var : secp256k1_modinv64)(&x, &m); - - /* check if the result is equal to the input */ - signed62_to_uint16(tmp, &x); - for (i = 0; i < 16; ++i) CHECK(tmp[i] == in[i]); - } -} -#endif - -/* test if a and b are coprime */ -static int coprime(const uint16_t* a, const uint16_t* b) { - uint16_t x[16], y[16], t[16]; - int i; - int iszero; - memcpy(x, a, 32); - memcpy(y, b, 32); - - /* simple gcd loop: while x!=0, (x,y)=(y%x,x) */ - while (1) { - iszero = 1; - for (i = 0; i < 16; ++i) { - if (x[i] != 0) { - iszero = 0; - break; - } - } - if (iszero) break; - mulmod256(t, y, NULL, x); - memcpy(y, x, 32); - memcpy(x, t, 32); - } - - /* return whether y=1 */ - if (y[0] != 1) return 0; - for (i = 1; i < 16; ++i) { - if (y[i] != 0) return 0; - } - return 1; -} - -static void run_modinv_tests(void) { - /* Fixed test cases. Each tuple is (input, modulus, output), each as 16x16 bits in LE order. */ - static const uint16_t CASES[][3][16] = { - /* Test cases triggering edge cases in divsteps */ - - /* Test case known to need 713 divsteps */ - {{0x1513, 0x5389, 0x54e9, 0x2798, 0x1957, 0x66a0, 0x8057, 0x3477, - 0x7784, 0x1052, 0x326a, 0x9331, 0x6506, 0xa95c, 0x91f3, 0xfb5e}, - {0x2bdd, 0x8df4, 0xcc61, 0x481f, 0xdae5, 0x5ca7, 0xf43b, 0x7d54, - 0x13d6, 0x469b, 0x2294, 0x20f4, 0xb2a4, 0xa2d1, 0x3ff1, 0xfd4b}, - {0xffd8, 0xd9a0, 0x456e, 0x81bb, 0xbabd, 0x6cea, 0x6dbd, 0x73ab, - 0xbb94, 0x3d3c, 0xdf08, 0x31c4, 0x3e32, 0xc179, 0x2486, 0xb86b}}, - /* Test case known to need 589 divsteps, reaching delta=-140 and - delta=141. */ - {{0x3fb1, 0x903b, 0x4eb7, 0x4813, 0xd863, 0x26bf, 0xd89f, 0xa8a9, - 0x02fe, 0x57c6, 0x554a, 0x4eab, 0x165e, 0x3d61, 0xee1e, 0x456c}, - {0x9295, 0x823b, 0x5c1f, 0x5386, 0x48e0, 0x02ff, 0x4c2a, 0xa2da, - 0xe58f, 0x967c, 0xc97e, 0x3f5a, 0x69fb, 0x52d9, 0x0a86, 0xb4a3}, - {0x3d30, 0xb893, 0xa809, 0xa7a8, 0x26f5, 0x5b42, 0x55be, 0xf4d0, - 0x12c2, 0x7e6a, 0xe41a, 0x90c7, 0xebfa, 0xf920, 0x304e, 0x1419}}, - /* Test case known to need 650 divsteps, and doing 65 consecutive (f,g/2) steps. */ - {{0x8583, 0x5058, 0xbeae, 0xeb69, 0x48bc, 0x52bb, 0x6a9d, 0xcc94, - 0x2a21, 0x87d5, 0x5b0d, 0x42f6, 0x5b8a, 0x2214, 0xe9d6, 0xa040}, - {0x7531, 0x27cb, 0x7e53, 0xb739, 0x6a5f, 0x83f5, 0xa45c, 0xcb1d, - 0x8a87, 0x1c9c, 0x51d7, 0x851c, 0xb9d8, 0x1fbe, 0xc241, 0xd4a3}, - {0xcdb4, 0x275c, 0x7d22, 0xa906, 0x0173, 0xc054, 0x7fdf, 0x5005, - 0x7fb8, 0x9059, 0xdf51, 0x99df, 0x2654, 0x8f6e, 0x070f, 0xb347}}, - /* example needing 713 divsteps; delta=-2..3 */ - {{0xe2e9, 0xee91, 0x4345, 0xe5ad, 0xf3ec, 0x8f42, 0x0364, 0xd5c9, - 0xff49, 0xbef5, 0x4544, 0x4c7c, 0xae4b, 0xfd9d, 0xb35b, 0xda9d}, - {0x36e7, 0x8cca, 0x2ed0, 0x47b3, 0xaca4, 0xb374, 0x7d2a, 0x0772, - 0x6bdb, 0xe0a7, 0x900b, 0xfe10, 0x788c, 0x6f22, 0xd909, 0xf298}, - {0xd8c6, 0xba39, 0x13ed, 0x198c, 0x16c8, 0xb837, 0xa5f2, 0x9797, - 0x0113, 0x882a, 0x15b5, 0x324c, 0xabee, 0xe465, 0x8170, 0x85ac}}, - /* example needing 713 divsteps; delta=-2..3 */ - {{0xd5b7, 0x2966, 0x040e, 0xf59a, 0x0387, 0xd96d, 0xbfbc, 0xd850, - 0x2d96, 0x872a, 0xad81, 0xc03c, 0xbb39, 0xb7fa, 0xd904, 0xef78}, - {0x6279, 0x4314, 0xfdd3, 0x1568, 0x0982, 0x4d13, 0x625f, 0x010c, - 0x22b1, 0x0cc3, 0xf22d, 0x5710, 0x1109, 0x5751, 0x7714, 0xfcf2}, - {0xdb13, 0x5817, 0x232e, 0xe456, 0xbbbc, 0x6fbe, 0x4572, 0xa358, - 0xc76d, 0x928e, 0x0162, 0x5314, 0x8325, 0x5683, 0xe21b, 0xda88}}, - /* example needing 713 divsteps; delta=-2..3 */ - {{0xa06f, 0x71ee, 0x3bac, 0x9ebb, 0xdeaa, 0x09ed, 0x1cf7, 0x9ec9, - 0x7158, 0x8b72, 0x5d53, 0x5479, 0x5c75, 0xbb66, 0x9125, 0xeccc}, - {0x2941, 0xd46c, 0x3cd4, 0x4a9d, 0x5c4a, 0x256b, 0xbd6c, 0x9b8e, - 0x8fe0, 0x8a14, 0xffe8, 0x2496, 0x618d, 0xa9d7, 0x5018, 0xfb29}, - {0x437c, 0xbd60, 0x7590, 0x94bb, 0x0095, 0xd35e, 0xd4fe, 0xd6da, - 0x0d4e, 0x5342, 0x4cd2, 0x169b, 0x661c, 0x1380, 0xed2d, 0x85c1}}, - /* example reaching delta=-64..65; 661 divsteps */ - {{0xfde4, 0x68d6, 0x6c48, 0x7f77, 0x1c78, 0x96de, 0x2fd9, 0xa6c2, - 0xbbb5, 0xd319, 0x69cf, 0xd4b3, 0xa321, 0xcda0, 0x172e, 0xe530}, - {0xd9e3, 0x0f60, 0x3d86, 0xeeab, 0x25ee, 0x9582, 0x2d50, 0xfe16, - 0xd4e2, 0xe3ba, 0x94e2, 0x9833, 0x6c5e, 0x8982, 0x13b6, 0xe598}, - {0xe675, 0xf55a, 0x10f6, 0xabde, 0x5113, 0xecaa, 0x61ae, 0xad9f, - 0x0c27, 0xef33, 0x62e5, 0x211d, 0x08fa, 0xa78d, 0xc675, 0x8bae}}, - /* example reaching delta=-64..65; 661 divsteps */ - {{0x21bf, 0x52d5, 0x8fd4, 0xaa18, 0x156a, 0x7247, 0xebb8, 0x5717, - 0x4eb5, 0x1421, 0xb58f, 0x3b0b, 0x5dff, 0xe533, 0xb369, 0xd28a}, - {0x9f6b, 0xe463, 0x2563, 0xc74d, 0x6d81, 0x636a, 0x8fc8, 0x7a94, - 0x9429, 0x1585, 0xf35e, 0x7ff5, 0xb64f, 0x9720, 0xba74, 0xe108}, - {0xa5ab, 0xea7b, 0xfe5e, 0x8a85, 0x13be, 0x7934, 0xe8a0, 0xa187, - 0x86b5, 0xe477, 0xb9a4, 0x75d7, 0x538f, 0xdd70, 0xc781, 0xb67d}}, - /* example reaching delta=-64..65; 661 divsteps */ - {{0xa41a, 0x3e8d, 0xf1f5, 0x9493, 0x868c, 0x5103, 0x2725, 0x3ceb, - 0x6032, 0x3624, 0xdc6b, 0x9120, 0xbf4c, 0x8821, 0x91ad, 0xb31a}, - {0x5c0b, 0xdda5, 0x20f8, 0x32a1, 0xaf73, 0x6ec5, 0x4779, 0x43d6, - 0xd454, 0x9573, 0xbf84, 0x5a58, 0xe04e, 0x307e, 0xd1d5, 0xe230}, - {0xda15, 0xbcd6, 0x7180, 0xabd3, 0x04e6, 0x6986, 0xc0d7, 0x90bb, - 0x3a4d, 0x7c95, 0xaaab, 0x9ab3, 0xda34, 0xa7f6, 0x9636, 0x6273}}, - /* example doing 123 consecutive (f,g/2) steps; 615 divsteps */ - {{0xb4d6, 0xb38f, 0x00aa, 0xebda, 0xd4c2, 0x70b8, 0x9dad, 0x58ee, - 0x68f8, 0x48d3, 0xb5ff, 0xf422, 0x9e46, 0x2437, 0x18d0, 0xd9cc}, - {0x5c83, 0xfed7, 0x97f5, 0x3f07, 0xcaad, 0x95b1, 0xb4a4, 0xb005, - 0x23af, 0xdd27, 0x6c0d, 0x932c, 0xe2b2, 0xe3ae, 0xfb96, 0xdf67}, - {0x3105, 0x0127, 0xfd48, 0x039b, 0x35f1, 0xbc6f, 0x6c0a, 0xb572, - 0xe4df, 0xebad, 0x8edc, 0xb89d, 0x9555, 0x4c26, 0x1fef, 0x997c}}, - /* example doing 123 consecutive (f,g/2) steps; 614 divsteps */ - {{0x5138, 0xd474, 0x385f, 0xc964, 0x00f2, 0x6df7, 0x862d, 0xb185, - 0xb264, 0xe9e1, 0x466c, 0xf39e, 0xafaf, 0x5f41, 0x47e2, 0xc89d}, - {0x8607, 0x9c81, 0x46a2, 0x7dcc, 0xcb0c, 0x9325, 0xe149, 0x2bde, - 0x6632, 0x2869, 0xa261, 0xb163, 0xccee, 0x22ae, 0x91e0, 0xcfd5}, - {0x831c, 0xda22, 0xb080, 0xba7a, 0x26e2, 0x54b0, 0x073b, 0x5ea0, - 0xed4b, 0xcb3d, 0xbba1, 0xbec8, 0xf2ad, 0xae0d, 0x349b, 0x17d1}}, - /* example doing 123 consecutive (f,g/2) steps; 614 divsteps */ - {{0xe9a5, 0xb4ad, 0xd995, 0x9953, 0xcdff, 0x50d7, 0xf715, 0x9dc7, - 0x3e28, 0x15a9, 0x95a3, 0x8554, 0x5b5e, 0xad1d, 0x6d57, 0x3d50}, - {0x3ad9, 0xbd60, 0x5cc7, 0x6b91, 0xadeb, 0x71f6, 0x7cc4, 0xa58a, - 0x2cce, 0xf17c, 0x38c9, 0x97ed, 0x65fb, 0x3fa6, 0xa6bc, 0xeb24}, - {0xf96c, 0x1963, 0x8151, 0xa0cc, 0x299b, 0xf277, 0x001a, 0x16bb, - 0xfd2e, 0x532d, 0x0410, 0xe117, 0x6b00, 0x44ec, 0xca6a, 0x1745}}, - /* example doing 446 (f,g/2) steps; 523 divsteps */ - {{0x3758, 0xa56c, 0xe41e, 0x4e47, 0x0975, 0xa82b, 0x107c, 0x89cf, - 0x2093, 0x5a0c, 0xda37, 0xe007, 0x6074, 0x4f68, 0x2f5a, 0xbb8a}, - {0x4beb, 0xa40f, 0x2c42, 0xd9d6, 0x97e8, 0xca7c, 0xd395, 0x894f, - 0x1f50, 0x8067, 0xa233, 0xb850, 0x1746, 0x1706, 0xbcda, 0xdf32}, - {0x762a, 0xceda, 0x4c45, 0x1ca0, 0x8c37, 0xd8c5, 0xef57, 0x7a2c, - 0x6e98, 0xe38a, 0xc50e, 0x2ca9, 0xcb85, 0x24d5, 0xc29c, 0x61f6}}, - /* example doing 446 (f,g/2) steps; 523 divsteps */ - {{0x6f38, 0x74ad, 0x7332, 0x4073, 0x6521, 0xb876, 0xa370, 0xa6bd, - 0xcea5, 0xbd06, 0x969f, 0x77c6, 0x1e69, 0x7c49, 0x7d51, 0xb6e7}, - {0x3f27, 0x4be4, 0xd81e, 0x1396, 0xb21f, 0x92aa, 0x6dc3, 0x6283, - 0x6ada, 0x3ca2, 0xc1e5, 0x8b9b, 0xd705, 0x5598, 0x8ba1, 0xe087}, - {0x6a22, 0xe834, 0xbc8d, 0xcee9, 0x42fc, 0xfc77, 0x9c45, 0x1ca8, - 0xeb66, 0xed74, 0xaaf9, 0xe75f, 0xfe77, 0x46d2, 0x179b, 0xbf3e}}, - /* example doing 336 (f,(f+g)/2) steps; 693 divsteps */ - {{0x7ea7, 0x444e, 0x84ea, 0xc447, 0x7c1f, 0xab97, 0x3de6, 0x5878, - 0x4e8b, 0xc017, 0x03e0, 0xdc40, 0xbbd0, 0x74ce, 0x0169, 0x7ab5}, - {0x4023, 0x154f, 0xfbe4, 0x8195, 0xfda0, 0xef54, 0x9e9a, 0xc703, - 0x2803, 0xf760, 0x6302, 0xed5b, 0x7157, 0x6456, 0xdd7d, 0xf14b}, - {0xb6fb, 0xe3b3, 0x0733, 0xa77e, 0x44c5, 0x3003, 0xc937, 0xdd4d, - 0x5355, 0x14e9, 0x184e, 0xcefe, 0xe6b5, 0xf2e0, 0x0a28, 0x5b74}}, - /* example doing 336 (f,(f+g)/2) steps; 687 divsteps */ - {{0xa893, 0xb5f4, 0x1ede, 0xa316, 0x242c, 0xbdcc, 0xb017, 0x0836, - 0x3a37, 0x27fb, 0xfb85, 0x251e, 0xa189, 0xb15d, 0xa4b8, 0xc24c}, - {0xb0b7, 0x57ba, 0xbb6d, 0x9177, 0xc896, 0xc7f2, 0x43b4, 0x85a6, - 0xe6c4, 0xe50e, 0x3109, 0x7ca5, 0xd73d, 0x13ff, 0x0c3d, 0xcd62}, - {0x48ca, 0xdb34, 0xe347, 0x2cef, 0x4466, 0x10fb, 0x7ee1, 0x6344, - 0x4308, 0x966d, 0xd4d1, 0xb099, 0x994f, 0xd025, 0x2187, 0x5866}}, - /* example doing 267 (g,(g-f)/2) steps; 678 divsteps */ - {{0x0775, 0x1754, 0x01f6, 0xdf37, 0xc0be, 0x8197, 0x072f, 0x6cf5, - 0x8b36, 0x8069, 0x5590, 0xb92d, 0x6084, 0x47a4, 0x23fe, 0xddd5}, - {0x8e1b, 0xda37, 0x27d9, 0x312e, 0x3a2f, 0xef6d, 0xd9eb, 0x8153, - 0xdcba, 0x9fa3, 0x9f80, 0xead5, 0x134d, 0x2ebb, 0x5ec0, 0xe032}, - {0x1cb6, 0x5a61, 0x1bed, 0x77d6, 0xd5d1, 0x7498, 0xef33, 0x2dd2, - 0x1089, 0xedbd, 0x6958, 0x16ae, 0x336c, 0x45e6, 0x4361, 0xbadc}}, - /* example doing 267 (g,(g-f)/2) steps; 676 divsteps */ - {{0x0207, 0xf948, 0xc430, 0xf36b, 0xf0a7, 0x5d36, 0x751f, 0x132c, - 0x6f25, 0xa630, 0xca1f, 0xc967, 0xaf9c, 0x34e7, 0xa38f, 0xbe9f}, - {0x5fb9, 0x7321, 0x6561, 0x5fed, 0x54ec, 0x9c3a, 0xee0e, 0x6717, - 0x49af, 0xb896, 0xf4f5, 0x451c, 0x722a, 0xf116, 0x64a9, 0xcf0b}, - {0xf4d7, 0xdb47, 0xfef2, 0x4806, 0x4cb8, 0x18c7, 0xd9a7, 0x4951, - 0x14d8, 0x5c3a, 0xd22d, 0xd7b2, 0x750c, 0x3de7, 0x8b4a, 0x19aa}}, - - /* Test cases triggering edge cases in divsteps variant starting with delta=1/2 */ - - /* example needing 590 divsteps; delta=-5/2..7/2 */ - {{0x9118, 0xb640, 0x53d7, 0x30ab, 0x2a23, 0xd907, 0x9323, 0x5b3a, - 0xb6d4, 0x538a, 0x7637, 0xfe97, 0xfd05, 0x3cc0, 0x453a, 0xfb7e}, - {0x6983, 0x4f75, 0x4ad1, 0x48ad, 0xb2d9, 0x521d, 0x3dbc, 0x9cc0, - 0x4b60, 0x0ac6, 0xd3be, 0x0fb6, 0xd305, 0x3895, 0x2da5, 0xfdf8}, - {0xcec1, 0x33ac, 0xa801, 0x8194, 0xe36c, 0x65ef, 0x103b, 0xca54, - 0xfa9b, 0xb41d, 0x9b52, 0xb6f7, 0xa611, 0x84aa, 0x3493, 0xbf54}}, - /* example needing 590 divsteps; delta=-3/2..5/2 */ - {{0xb5f2, 0x42d0, 0x35e8, 0x8ca0, 0x4b62, 0x6e1d, 0xbdf3, 0x890e, - 0x8c82, 0x23d8, 0xc79a, 0xc8e8, 0x789e, 0x353d, 0x9766, 0xea9d}, - {0x6fa1, 0xacba, 0x4b7a, 0x5de1, 0x95d0, 0xc845, 0xebbf, 0x6f5a, - 0x30cf, 0x52db, 0x69b7, 0xe278, 0x4b15, 0x8411, 0x2ab2, 0xf3e7}, - {0xf12c, 0x9d6d, 0x95fa, 0x1878, 0x9f13, 0x4fb5, 0x3c8b, 0xa451, - 0x7182, 0xc4b6, 0x7e2a, 0x7bb7, 0x6e0e, 0x5b68, 0xde55, 0x9927}}, - /* example needing 590 divsteps; delta=-3/2..5/2 */ - {{0x229c, 0x4ef8, 0x1e93, 0xe5dc, 0xcde5, 0x6d62, 0x263b, 0xad11, - 0xced0, 0x88ff, 0xae8e, 0x3183, 0x11d2, 0xa50b, 0x350d, 0xeb40}, - {0x3157, 0xe2ea, 0x8a02, 0x0aa3, 0x5ae1, 0xb26c, 0xea27, 0x6805, - 0x87e2, 0x9461, 0x37c1, 0x2f8d, 0x85d2, 0x77a8, 0xf805, 0xeec9}, - {0x6f4e, 0x2748, 0xf7e5, 0xd8d3, 0xabe2, 0x7270, 0xc4e0, 0xedc7, - 0xf196, 0x78ca, 0x9139, 0xd8af, 0x72c6, 0xaf2f, 0x85d2, 0x6cd3}}, - /* example needing 590 divsteps; delta=-5/2..7/2 */ - {{0xdce8, 0xf1fe, 0x6708, 0x021e, 0xf1ca, 0xd609, 0x5443, 0x85ce, - 0x7a05, 0x8f9c, 0x90c3, 0x52e7, 0x8e1d, 0x97b8, 0xc0bf, 0xf2a1}, - {0xbd3d, 0xed11, 0x1625, 0xb4c5, 0x844c, 0xa413, 0x2569, 0xb9ba, - 0xcd35, 0xff84, 0xcd6e, 0x7f0b, 0x7d5d, 0x10df, 0x3efe, 0xfbe5}, - {0xa9dd, 0xafef, 0xb1b7, 0x4c8d, 0x50e4, 0xafbf, 0x2d5a, 0xb27c, - 0x0653, 0x66b6, 0x5d36, 0x4694, 0x7e35, 0xc47c, 0x857f, 0x32c5}}, - /* example needing 590 divsteps; delta=-3/2..5/2 */ - {{0x7902, 0xc9f8, 0x926b, 0xaaeb, 0x90f8, 0x1c89, 0xcce3, 0x96b7, - 0x28b2, 0x87a2, 0x136d, 0x695a, 0xa8df, 0x9061, 0x9e31, 0xee82}, - {0xd3a9, 0x3c02, 0x818c, 0x6b81, 0x34b3, 0xebbb, 0xe2c8, 0x7712, - 0xbfd6, 0x8248, 0xa6f4, 0xba6f, 0x03bb, 0xfb54, 0x7575, 0xfe89}, - {0x8246, 0x0d63, 0x478e, 0xf946, 0xf393, 0x0451, 0x08c2, 0x5919, - 0x5fd6, 0x4c61, 0xbeb7, 0x9a15, 0x30e1, 0x55fc, 0x6a01, 0x3724}}, - /* example reaching delta=-127/2..129/2; 571 divsteps */ - {{0x3eff, 0x926a, 0x77f5, 0x1fff, 0x1a5b, 0xf3ef, 0xf64b, 0x8681, - 0xf800, 0xf9bc, 0x761d, 0xe268, 0x62b0, 0xa032, 0xba9c, 0xbe56}, - {0xb8f9, 0x00e7, 0x47b7, 0xdffc, 0xfd9d, 0x5abb, 0xa19b, 0x1868, - 0x31fd, 0x3b29, 0x3674, 0x5449, 0xf54d, 0x1d19, 0x6ac7, 0xff6f}, - {0xf1d7, 0x3551, 0x5682, 0x9adf, 0xe8aa, 0x19a5, 0x8340, 0x71db, - 0xb7ab, 0x4cfd, 0xf661, 0x632c, 0xc27e, 0xd3c6, 0xdf42, 0xd306}}, - /* example reaching delta=-127/2..129/2; 571 divsteps */ - {{0x0000, 0x0000, 0x0000, 0x0000, 0x3aff, 0x2ed7, 0xf2e0, 0xabc7, - 0x8aee, 0x166e, 0x7ed0, 0x9ac7, 0x714a, 0xb9c5, 0x4d58, 0xad6c}, - {0x9cf9, 0x47e2, 0xa421, 0xb277, 0xffc2, 0x2747, 0x6486, 0x94c1, - 0x1d99, 0xd49b, 0x1096, 0x991a, 0xe986, 0xae02, 0xe89b, 0xea36}, - {0x1fb4, 0x98d8, 0x19b7, 0x80e9, 0xcdac, 0xaa5a, 0xf1e6, 0x0074, - 0xe393, 0xed8b, 0x8d5c, 0xe17d, 0x81b3, 0xc16d, 0x54d3, 0x9be3}}, - /* example reaching delta=-127/2..129/2; 571 divsteps */ - {{0xd047, 0x7e36, 0x3157, 0x7ab6, 0xb4d9, 0x8dae, 0x7534, 0x4f5d, - 0x489e, 0xa8ab, 0x8a3d, 0xd52c, 0x62af, 0xa032, 0xba9c, 0xbe56}, - {0xb1f1, 0x737f, 0x5964, 0x5afb, 0x3712, 0x8ef9, 0x19f7, 0x9669, - 0x664d, 0x03ad, 0xc352, 0xf7a5, 0xf545, 0x1d19, 0x6ac7, 0xff6f}, - {0xa834, 0x5256, 0x27bc, 0x33bd, 0xba11, 0x5a7b, 0x791e, 0xe6c0, - 0x9ac4, 0x9370, 0x1130, 0x28b4, 0x2b2e, 0x231b, 0x082a, 0x796e}}, - /* example doing 123 consecutive (f,g/2) steps; 554 divsteps */ - {{0x6ab1, 0x6ea0, 0x1a99, 0xe0c2, 0xdd45, 0x645d, 0x8dbc, 0x466a, - 0xfa64, 0x4289, 0xd3f7, 0xfc8f, 0x2894, 0xe3c5, 0xa008, 0xcc14}, - {0xc75f, 0xc083, 0x4cc2, 0x64f2, 0x2aff, 0x4c12, 0x8461, 0xc4ae, - 0xbbfa, 0xb336, 0xe4b2, 0x3ac5, 0x2c22, 0xf56c, 0x5381, 0xe943}, - {0xcd80, 0x760d, 0x4395, 0xb3a6, 0xd497, 0xf583, 0x82bd, 0x1daa, - 0xbe92, 0x2613, 0xfdfb, 0x869b, 0x0425, 0xa333, 0x7056, 0xc9c5}}, - /* example doing 123 consecutive (f,g/2) steps; 554 divsteps */ - {{0x71d4, 0x64df, 0xec4f, 0x74d8, 0x7e0c, 0x40d3, 0x7073, 0x4cc8, - 0x2a2a, 0xb1ff, 0x8518, 0x6513, 0xb0ea, 0x640a, 0x62d9, 0xd5f4}, - {0xdc75, 0xd937, 0x3b13, 0x1d36, 0xdf83, 0xd034, 0x1c1c, 0x4332, - 0x4cc3, 0xeeec, 0x7d94, 0x6771, 0x3384, 0x74b0, 0x947d, 0xf2c4}, - {0x0a82, 0x37a4, 0x12d5, 0xec97, 0x972c, 0xe6bf, 0xc348, 0xa0a9, - 0xc50c, 0xdc7c, 0xae30, 0x19d1, 0x0fca, 0x35e1, 0xd6f6, 0x81ee}}, - /* example doing 123 consecutive (f,g/2) steps; 554 divsteps */ - {{0xa6b1, 0xabc5, 0x5bbc, 0x7f65, 0xdd32, 0xaa73, 0xf5a3, 0x1982, - 0xced4, 0xe949, 0x0fd6, 0x2bc4, 0x2bd7, 0xe3c5, 0xa008, 0xcc14}, - {0x4b5f, 0x8f96, 0xa375, 0xfbcf, 0x1c7d, 0xf1ec, 0x03f5, 0xb35d, - 0xb999, 0xdb1f, 0xc9a1, 0xb4c7, 0x1dd5, 0xf56c, 0x5381, 0xe943}, - {0xaa3d, 0x38b9, 0xf17d, 0xeed9, 0x9988, 0x69ee, 0xeb88, 0x1495, - 0x203f, 0x18c8, 0x82b7, 0xdcb2, 0x34a7, 0x6b00, 0x6998, 0x589a}}, - /* example doing 453 (f,g/2) steps; 514 divsteps */ - {{0xa478, 0xe60d, 0x3244, 0x60e6, 0xada3, 0xfe50, 0xb6b1, 0x2eae, - 0xd0ef, 0xa7b1, 0xef63, 0x05c0, 0xe213, 0x443e, 0x4427, 0x2448}, - {0x258f, 0xf9ef, 0xe02b, 0x92dd, 0xd7f3, 0x252b, 0xa503, 0x9089, - 0xedff, 0x96c1, 0xfe3a, 0x3a39, 0x198a, 0x981d, 0x0627, 0xedb7}, - {0x595a, 0x45be, 0x8fb0, 0x2265, 0xc210, 0x02b8, 0xdce9, 0xe241, - 0xcab6, 0xbf0d, 0x0049, 0x8d9a, 0x2f51, 0xae54, 0x5785, 0xb411}}, - /* example doing 453 (f,g/2) steps; 514 divsteps */ - {{0x48f0, 0x7db3, 0xdafe, 0x1c92, 0x5912, 0xe11a, 0xab52, 0xede1, - 0x3182, 0x8980, 0x5d2b, 0x9b5b, 0x8718, 0xda27, 0x1683, 0x1de2}, - {0x168f, 0x6f36, 0xce7a, 0xf435, 0x19d4, 0xda5e, 0x2351, 0x9af5, - 0xb003, 0x0ef5, 0x3b4c, 0xecec, 0xa9f0, 0x78e1, 0xdfef, 0xe823}, - {0x5f55, 0xfdcc, 0xb233, 0x2914, 0x84f0, 0x97d1, 0x9cf4, 0x2159, - 0xbf56, 0xb79c, 0x17a3, 0x7cef, 0xd5de, 0x34f0, 0x5311, 0x4c54}}, - /* example doing 510 (f,(f+g)/2) steps; 512 divsteps */ - {{0x2789, 0x2e04, 0x6e0e, 0xb6cd, 0xe4de, 0x4dbf, 0x228d, 0x7877, - 0xc335, 0x806b, 0x38cd, 0x8049, 0xa73b, 0xcfa2, 0x82f7, 0x9e19}, - {0xc08d, 0xb99d, 0xb8f3, 0x663d, 0xbbb3, 0x1284, 0x1485, 0x1d49, - 0xc98f, 0x9e78, 0x1588, 0x11e3, 0xd91a, 0xa2c7, 0xfff1, 0xc7b9}, - {0x1e1f, 0x411d, 0x7c49, 0x0d03, 0xe789, 0x2f8e, 0x5d55, 0xa95e, - 0x826e, 0x8de5, 0x52a0, 0x1abc, 0x4cd7, 0xd13a, 0x4395, 0x63e1}}, - /* example doing 510 (f,(f+g)/2) steps; 512 divsteps */ - {{0xd5a1, 0xf786, 0x555c, 0xb14b, 0x44ae, 0x535f, 0x4a49, 0xffc3, - 0xf497, 0x70d1, 0x57c8, 0xa933, 0xc85a, 0x1910, 0x75bf, 0x960b}, - {0xfe53, 0x5058, 0x496d, 0xfdff, 0x6fb8, 0x4100, 0x92bd, 0xe0c4, - 0xda89, 0xe0a4, 0x841b, 0x43d4, 0xa388, 0x957f, 0x99ca, 0x9abf}, - {0xe530, 0x05bc, 0xfeec, 0xfc7e, 0xbcd3, 0x1239, 0x54cb, 0x7042, - 0xbccb, 0x139e, 0x9076, 0x0203, 0x6068, 0x90c7, 0x1ddf, 0x488d}}, - /* example doing 228 (g,(g-f)/2) steps; 538 divsteps */ - {{0x9488, 0xe54b, 0x0e43, 0x81d2, 0x06e7, 0x4b66, 0x36d0, 0x53d6, - 0x2b68, 0x22ec, 0x3fa9, 0xc1a7, 0x9ad2, 0xa596, 0xb3ac, 0xdf42}, - {0xe31f, 0x0b28, 0x5f3b, 0xc1ff, 0x344c, 0xbf5f, 0xd2ec, 0x2936, - 0x9995, 0xdeb2, 0xae6c, 0x2852, 0xa2c6, 0xb306, 0x8120, 0xe305}, - {0xa56e, 0xfb98, 0x1537, 0x4d85, 0x619e, 0x866c, 0x3cd4, 0x779a, - 0xdd66, 0xa80d, 0xdc2f, 0xcae4, 0xc74c, 0x5175, 0xa65d, 0x605e}}, - /* example doing 228 (g,(g-f)/2) steps; 537 divsteps */ - {{0x8cd5, 0x376d, 0xd01b, 0x7176, 0x19ef, 0xcf09, 0x8403, 0x5e52, - 0x83c1, 0x44de, 0xb91e, 0xb33d, 0xe15c, 0x51e7, 0xbad8, 0x6359}, - {0x3b75, 0xf812, 0x5f9e, 0xa04e, 0x92d3, 0x226e, 0x540e, 0x7c9a, - 0x31c6, 0x46d2, 0x0b7b, 0xdb4a, 0xe662, 0x4950, 0x0265, 0xf76f}, - {0x09ed, 0x692f, 0xe8f1, 0x3482, 0xab54, 0x36b4, 0x8442, 0x6ae9, - 0x4329, 0x6505, 0x183b, 0x1c1d, 0x482d, 0x7d63, 0xb44f, 0xcc09}}, - - /* Test cases with the group order as modulus. */ - - /* Test case with the group order as modulus, needing 635 divsteps. */ - {{0x95ed, 0x6c01, 0xd113, 0x5ff1, 0xd7d0, 0x29cc, 0x5817, 0x6120, - 0xca8e, 0xaad1, 0x25ae, 0x8e84, 0x9af6, 0x30bf, 0xf0ed, 0x1686}, - {0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x1631, 0xbf4a, 0x286a, 0x2716, 0x469f, 0x2ac8, 0x1312, 0xe9bc, - 0x04f4, 0x304b, 0x9931, 0x113b, 0xd932, 0xc8f4, 0x0d0d, 0x01a1}}, - /* example with group size as modulus needing 631 divsteps */ - {{0x85ed, 0xc284, 0x9608, 0x3c56, 0x19b6, 0xbb5b, 0x2850, 0xdab7, - 0xa7f5, 0xe9ab, 0x06a4, 0x5bbb, 0x1135, 0xa186, 0xc424, 0xc68b}, - {0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x8479, 0x450a, 0x8fa3, 0xde05, 0xb2f5, 0x7793, 0x7269, 0xbabb, - 0xc3b3, 0xd49b, 0x3377, 0x03c6, 0xe694, 0xc760, 0xd3cb, 0x2811}}, - /* example with group size as modulus needing 565 divsteps starting at delta=1/2 */ - {{0x8432, 0x5ceb, 0xa847, 0x6f1e, 0x51dd, 0x535a, 0x6ddc, 0x70ce, - 0x6e70, 0xc1f6, 0x18f2, 0x2a7e, 0xc8e7, 0x39f8, 0x7e96, 0xebbf}, - {0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x257e, 0x449f, 0x689f, 0x89aa, 0x3989, 0xb661, 0x376c, 0x1e32, - 0x654c, 0xee2e, 0xf4e2, 0x33c8, 0x3f2f, 0x9716, 0x6046, 0xcaa3}}, - /* Test case with the group size as modulus, needing 981 divsteps with - broken eta handling. */ - {{0xfeb9, 0xb877, 0xee41, 0x7fa3, 0x87da, 0x94c4, 0x9d04, 0xc5ae, - 0x5708, 0x0994, 0xfc79, 0x0916, 0xbf32, 0x3ad8, 0xe11c, 0x5ca2}, - {0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x0f12, 0x075e, 0xce1c, 0x6f92, 0xc80f, 0xca92, 0x9a04, 0x6126, - 0x4b6c, 0x57d6, 0xca31, 0x97f3, 0x1f99, 0xf4fd, 0xda4d, 0x42ce}}, - /* Test case with the group size as modulus, input = 0. */ - {{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - /* Test case with the group size as modulus, input = 1. */ - {{0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - /* Test case with the group size as modulus, input = 2. */ - {{0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x20a1, 0x681b, 0x2f46, 0xdfe9, 0x501d, 0x57a4, 0x6e73, 0x5d57, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff}}, - /* Test case with the group size as modulus, input = group - 1. */ - {{0x4140, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x4140, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae, - 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}}, - - /* Test cases with the field size as modulus. */ - - /* Test case with the field size as modulus, needing 637 divsteps. */ - {{0x9ec3, 0x1919, 0xca84, 0x7c11, 0xf996, 0x06f3, 0x5408, 0x6688, - 0x1320, 0xdb8a, 0x632a, 0x0dcb, 0x8a84, 0x6bee, 0x9c95, 0xe34e}, - {0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x18e5, 0x19b6, 0xdf92, 0x1aaa, 0x09fb, 0x8a3f, 0x52b0, 0x8701, - 0xac0c, 0x2582, 0xda44, 0x9bcc, 0x6828, 0x1c53, 0xbd8f, 0xbd2c}}, - /* example with field size as modulus needing 637 divsteps */ - {{0xaec3, 0xa7cf, 0x2f2d, 0x0693, 0x5ad5, 0xa8ff, 0x7ec7, 0x30ff, - 0x0c8b, 0xc242, 0xcab2, 0x063a, 0xf86e, 0x6057, 0x9cbd, 0xf6d8}, - {0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x0310, 0x579d, 0xcb38, 0x9030, 0x3ded, 0x9bb9, 0x1234, 0x63ce, - 0x0c63, 0x8e3d, 0xacfe, 0x3c20, 0xdc85, 0xf859, 0x919e, 0x1d45}}, - /* example with field size as modulus needing 564 divsteps starting at delta=1/2 */ - {{0x63ae, 0x8d10, 0x0071, 0xdb5c, 0xb454, 0x78d1, 0x744a, 0x5f8e, - 0xe4d8, 0x87b1, 0x8e62, 0x9590, 0xcede, 0xa070, 0x36b4, 0x7f6f}, - {0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0xfdc8, 0xe8d5, 0xbe15, 0x9f86, 0xa5fe, 0xf18e, 0xa7ff, 0xd291, - 0xf4c2, 0x9c87, 0xf150, 0x073e, 0x69b8, 0xf7c4, 0xee4b, 0xc7e6}}, - /* Test case with the field size as modulus, needing 935 divsteps with - broken eta handling. */ - {{0x1b37, 0xbdc3, 0x8bcd, 0x25e3, 0x1eae, 0x567d, 0x30b6, 0xf0d8, - 0x9277, 0x0cf8, 0x9c2e, 0xecd7, 0x631d, 0xe38f, 0xd4f8, 0x5c93}, - {0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x1622, 0xe05b, 0xe880, 0x7de9, 0x3e45, 0xb682, 0xee6c, 0x67ed, - 0xa179, 0x15db, 0x6b0d, 0xa656, 0x7ccb, 0x8ef7, 0xa2ff, 0xe279}}, - /* Test case with the field size as modulus, input = 0. */ - {{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - /* Test case with the field size as modulus, input = 1. */ - {{0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, - /* Test case with the field size as modulus, input = 2. */ - {{0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, - {0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0xfe18, 0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff}}, - /* Test case with the field size as modulus, input = field - 1. */ - {{0xfc2e, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - {0xfc2e, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}}, - - /* Selected from a large number of random inputs to reach small/large - * d/e values in various configurations. */ - {{0x3a08, 0x23e1, 0x4d8c, 0xe606, 0x3263, 0x67af, 0x9bf1, 0x9d70, - 0xf5fd, 0x12e4, 0x03c8, 0xb9ca, 0xe847, 0x8c5d, 0x6322, 0xbd30}, - {0x8359, 0x59dd, 0x1831, 0x7c1a, 0x1e83, 0xaee1, 0x770d, 0xcea8, - 0xfbb1, 0xeed6, 0x10b5, 0xe2c6, 0x36ea, 0xee17, 0xe32c, 0xffff}, - {0x1727, 0x0f36, 0x6f85, 0x5d0c, 0xca6c, 0x3072, 0x9628, 0x5842, - 0xcb44, 0x7c2b, 0xca4f, 0x62e5, 0x29b1, 0x6ffd, 0x9055, 0xc196}}, - {{0x905d, 0x41c8, 0xa2ff, 0x295b, 0x72bb, 0x4679, 0x6d01, 0x2c98, - 0xb3e0, 0xc537, 0xa310, 0xe07e, 0xe72f, 0x4999, 0x1148, 0xf65e}, - {0x5b41, 0x4239, 0x3c37, 0x5130, 0x30e3, 0xff35, 0xc51f, 0x1a43, - 0xdb23, 0x13cf, 0x9f49, 0xf70c, 0x5e70, 0xd411, 0x3005, 0xf8c6}, - {0xc30e, 0x68f0, 0x201a, 0xe10c, 0x864a, 0x6243, 0xe946, 0x43ae, - 0xf3f1, 0x52dc, 0x1f7f, 0x50d4, 0x2797, 0x064c, 0x5ca4, 0x90e3}}, - {{0xf1b5, 0xc6e5, 0xd2c4, 0xff95, 0x27c5, 0x0c92, 0x5d19, 0x7ae5, - 0x4fbe, 0x5438, 0x99e1, 0x880d, 0xd892, 0xa05c, 0x6ffd, 0x7eac}, - {0x2153, 0xcc9d, 0xfc6c, 0x8358, 0x49a1, 0x01e2, 0xcef0, 0x4969, - 0xd69a, 0x8cef, 0xf5b2, 0xfd95, 0xdcc2, 0x71f4, 0x6ae2, 0xceeb}, - {0x9b2e, 0xcdc6, 0x0a5c, 0x7317, 0x9084, 0xe228, 0x56cf, 0xd512, - 0x628a, 0xce21, 0x3473, 0x4e13, 0x8823, 0x1ed0, 0x34d0, 0xbfa3}}, - {{0x5bae, 0x53e5, 0x5f4d, 0x21ca, 0xb875, 0x8ecf, 0x9aa6, 0xbe3c, - 0x9f96, 0x7b82, 0x375d, 0x4d3e, 0x491c, 0xb1eb, 0x04c9, 0xb6c8}, - {0xfcfd, 0x10b7, 0x73b2, 0xd23b, 0xa357, 0x67da, 0x0d9f, 0x8702, - 0xa037, 0xff8e, 0x0e8b, 0x1801, 0x2c5c, 0x4e6e, 0x4558, 0xfff2}, - {0xc50f, 0x5654, 0x6713, 0x5ef5, 0xa7ce, 0xa647, 0xc832, 0x69ce, - 0x1d5c, 0x4310, 0x0746, 0x5a01, 0x96ea, 0xde4b, 0xa88b, 0x5543}}, - {{0xdc7f, 0x5e8c, 0x89d1, 0xb077, 0xd521, 0xcf90, 0x32fa, 0x5737, - 0x839e, 0x1464, 0x007c, 0x09c6, 0x9371, 0xe8ea, 0xc1cb, 0x75c4}, - {0xe3a3, 0x107f, 0xa82a, 0xa375, 0x4578, 0x60f4, 0x75c9, 0x5ee4, - 0x3fd7, 0x2736, 0x2871, 0xd3d2, 0x5f1d, 0x1abb, 0xa764, 0xffff}, - {0x45c6, 0x1f2e, 0xb14c, 0x84d7, 0x7bb7, 0x5a04, 0x0504, 0x3f33, - 0x5cc1, 0xb07a, 0x6a6c, 0x786f, 0x647f, 0xe1d7, 0x78a2, 0x4cf4}}, - {{0xc006, 0x356f, 0x8cd2, 0x967b, 0xb49e, 0x2d4e, 0x14bf, 0x4bcb, - 0xddab, 0xd3f9, 0xa068, 0x2c1c, 0xd242, 0xa56d, 0xf2c7, 0x5f97}, - {0x465b, 0xb745, 0x0e0d, 0x69a9, 0x987d, 0xcb37, 0xf637, 0xb311, - 0xc4d6, 0x2ddb, 0xf68f, 0x2af9, 0x959d, 0x3f53, 0x98f2, 0xf640}, - {0xc0f2, 0x6bfb, 0xf5c3, 0x91c1, 0x6b05, 0x0825, 0x5ca0, 0x7df7, - 0x9d55, 0x6d9e, 0xfe94, 0x2ad9, 0xd9f0, 0xe68b, 0xa72b, 0xd1b2}}, - {{0x2279, 0x61ba, 0x5bc6, 0x136b, 0xf544, 0x717c, 0xafda, 0x02bd, - 0x79af, 0x1fad, 0xea09, 0x81bb, 0x932b, 0x32c9, 0xdf1d, 0xe576}, - {0x8215, 0x7817, 0xca82, 0x43b0, 0x9b06, 0xea65, 0x1291, 0x0621, - 0x0089, 0x46fe, 0xc5a6, 0xddd7, 0x8065, 0xc6a0, 0x214b, 0xfc64}, - {0x04bf, 0x6f2a, 0x86b2, 0x841a, 0x4a95, 0xc632, 0x97b7, 0x5821, - 0x2b18, 0x1bb0, 0x3e97, 0x935e, 0xcc7d, 0x066b, 0xd513, 0xc251}}, - {{0x76e8, 0x5bc2, 0x3eaa, 0x04fc, 0x9974, 0x92c1, 0x7c15, 0xfa89, - 0x1151, 0x36ee, 0x48b2, 0x049c, 0x5f16, 0xcee4, 0x925b, 0xe98e}, - {0x913f, 0x0a2d, 0xa185, 0x9fea, 0xda5a, 0x4025, 0x40d7, 0x7cfa, - 0x88ca, 0xbbe8, 0xb265, 0xb7e4, 0x6cb1, 0xed64, 0xc6f9, 0xffb5}, - {0x6ab1, 0x1a86, 0x5009, 0x152b, 0x1cc4, 0xe2c8, 0x960b, 0x19d0, - 0x3554, 0xc562, 0xd013, 0xcf91, 0x10e1, 0x7933, 0xe195, 0xcf49}}, - {{0x9cb5, 0xd2d7, 0xc6ed, 0xa818, 0xb495, 0x06ee, 0x0f4a, 0x06e3, - 0x4c5a, 0x80ce, 0xd49a, 0x4cd7, 0x7487, 0x92af, 0xe516, 0x676c}, - {0xd6e9, 0x6b85, 0x619a, 0xb52c, 0x20a0, 0x2f79, 0x3545, 0x1edd, - 0x5a6f, 0x8082, 0x9b80, 0xf8f8, 0xc78a, 0xd0a3, 0xadf4, 0xffff}, - {0x01c2, 0x2118, 0xef5e, 0xa877, 0x046a, 0xd2c2, 0x2ad5, 0x951c, - 0x8900, 0xa5c9, 0x8d0f, 0x6b61, 0x55d3, 0xd572, 0x48de, 0x9219}}, - {{0x5114, 0x0644, 0x23dd, 0x01d3, 0xc101, 0xa659, 0xea17, 0x640f, - 0xf767, 0x2644, 0x9cec, 0xd8ba, 0xd6da, 0x9156, 0x8aeb, 0x875a}, - {0xc1bf, 0xdae9, 0xe96b, 0xce77, 0xf7a1, 0x3e99, 0x5c2e, 0x973b, - 0xd048, 0x5bd0, 0x4e8a, 0xcb85, 0xce39, 0x37f5, 0x815d, 0xffff}, - {0x48cc, 0x35b6, 0x26d4, 0x2ea6, 0x50d6, 0xa2f9, 0x64b6, 0x03bf, - 0xd00c, 0xe057, 0x3343, 0xfb79, 0x3ce5, 0xf717, 0xc5af, 0xe185}}, - {{0x13ff, 0x6c76, 0x2077, 0x16e0, 0xd5ca, 0xf2ad, 0x8dba, 0x8f49, - 0x7887, 0x16f9, 0xb646, 0xfc87, 0xfa31, 0x5096, 0xf08c, 0x3fbe}, - {0x8139, 0x6fd7, 0xf6df, 0xa7bf, 0x6699, 0x5361, 0x6f65, 0x13c8, - 0xf4d1, 0xe28f, 0xc545, 0x0a8c, 0x5274, 0xb0a6, 0xffff, 0xffff}, - {0x22ca, 0x0cd6, 0xc1b5, 0xb064, 0x44a7, 0x297b, 0x495f, 0x34ac, - 0xfa95, 0xec62, 0xf08d, 0x621c, 0x66a6, 0xba94, 0x84c6, 0x8ee0}}, - {{0xaa30, 0x312e, 0x439c, 0x4e88, 0x2e2f, 0x32dc, 0xb880, 0xa28e, - 0xf795, 0xc910, 0xb406, 0x8dd7, 0xb187, 0xa5a5, 0x38f1, 0xe49e}, - {0xfb19, 0xf64a, 0xba6a, 0x8ec2, 0x7255, 0xce89, 0x2cf9, 0x9cba, - 0xe1fe, 0x50da, 0x1705, 0xac52, 0xe3d4, 0x4269, 0x0648, 0xfd77}, - {0xb4c8, 0x6e8a, 0x2b5f, 0x4c2d, 0x5a67, 0xa7bb, 0x7d6d, 0x5569, - 0xa0ea, 0x244a, 0xc0f2, 0xf73d, 0x58cf, 0xac7f, 0xd32b, 0x3018}}, - {{0xc953, 0x1ae1, 0xae46, 0x8709, 0x19c2, 0xa986, 0x9abe, 0x1611, - 0x0395, 0xd5ab, 0xf0f6, 0xb5b0, 0x5b2b, 0x0317, 0x80ba, 0x376d}, - {0xfe77, 0xbc03, 0xac2f, 0x9d00, 0xa175, 0x293d, 0x3b56, 0x0e3a, - 0x0a9c, 0xf40c, 0x690e, 0x1508, 0x95d4, 0xddc4, 0xe805, 0xffff}, - {0xb1ce, 0x0929, 0xa5fe, 0x4b50, 0x9d5d, 0x8187, 0x2557, 0x4376, - 0x11ba, 0xdcef, 0xc1f3, 0xd531, 0x1824, 0x93f6, 0xd81f, 0x8f83}}, - {{0xb8d2, 0xb900, 0x4a0c, 0x7188, 0xa5bf, 0x1b0b, 0x2ae5, 0xa35b, - 0x98e0, 0x610c, 0x86db, 0x2487, 0xa267, 0x002c, 0xebb6, 0xc5f4}, - {0x9cdd, 0x1c1b, 0x2f06, 0x43d1, 0xce47, 0xc334, 0x6e60, 0xc016, - 0x989e, 0x0ab2, 0x0cac, 0x1196, 0xe2d9, 0x2e04, 0xc62b, 0xffff}, - {0xdc36, 0x1f05, 0x6aa9, 0x7a20, 0x944f, 0x2fd3, 0xa553, 0xdb4f, - 0xbd5c, 0x3a75, 0x25d4, 0xe20e, 0xa387, 0x1410, 0xdbb1, 0x1b60}}, - {{0x76b3, 0x2207, 0x4930, 0x5dd7, 0x65a0, 0xd55c, 0xb443, 0x53b7, - 0x5c22, 0x818a, 0xb2e7, 0x9de8, 0x9985, 0xed45, 0x33b1, 0x53e8}, - {0x7913, 0x44e1, 0xf15b, 0x5edd, 0x34f3, 0x4eba, 0x0758, 0x7104, - 0x32d9, 0x28f3, 0x4401, 0x85c5, 0xb695, 0xb899, 0xc0f2, 0xffff}, - {0x7f43, 0xd202, 0x24c9, 0x69f3, 0x74dc, 0x1a69, 0xeaee, 0x5405, - 0x1755, 0x4bb8, 0x04e3, 0x2fd2, 0xada8, 0x39eb, 0x5b4d, 0x96ca}}, - {{0x807b, 0x7112, 0xc088, 0xdafd, 0x02fa, 0x9d95, 0x5e42, 0xc033, - 0xde0a, 0xeecf, 0x8e90, 0x8da1, 0xb17e, 0x9a5b, 0x4c6d, 0x1914}, - {0x4871, 0xd1cb, 0x47d7, 0x327f, 0x09ec, 0x97bb, 0x2fae, 0xd346, - 0x6b78, 0x3707, 0xfeb2, 0xa6ab, 0x13df, 0x76b0, 0x8fb9, 0xffb3}, - {0x179e, 0xb63b, 0x4784, 0x231e, 0x9f42, 0x7f1a, 0xa3fb, 0xdd8c, - 0xd1eb, 0xb4c9, 0x8ca7, 0x018c, 0xf691, 0x576c, 0xa7d6, 0xce27}}, - {{0x5f45, 0x7c64, 0x083d, 0xedd5, 0x08a0, 0x0c64, 0x6c6f, 0xec3c, - 0xe2fb, 0x352c, 0x9303, 0x75e4, 0xb4e0, 0x8b09, 0xaca4, 0x7025}, - {0x1025, 0xb482, 0xfed5, 0xa678, 0x8966, 0x9359, 0x5329, 0x98bb, - 0x85b2, 0x73ba, 0x9982, 0x6fdc, 0xf190, 0xbe8c, 0xdc5c, 0xfd93}, - {0x83a2, 0x87a4, 0xa680, 0x52a1, 0x1ba1, 0x8848, 0x5db7, 0x9744, - 0x409c, 0x0745, 0x0e1e, 0x1cfc, 0x00cd, 0xf573, 0x2071, 0xccaa}}, - {{0xf61f, 0x63d4, 0x536c, 0x9eb9, 0x5ddd, 0xbb11, 0x9014, 0xe904, - 0xfe01, 0x6b45, 0x1858, 0xcb5b, 0x4c38, 0x43e1, 0x381d, 0x7f94}, - {0xf61f, 0x63d4, 0xd810, 0x7ca3, 0x8a04, 0x4b83, 0x11fc, 0xdf94, - 0x4169, 0xbd05, 0x608e, 0x7151, 0x4fbf, 0xb31a, 0x38a7, 0xa29b}, - {0xe621, 0xdfa5, 0x3d06, 0x1d03, 0x81e6, 0x00da, 0x53a6, 0x965e, - 0x93e5, 0x2164, 0x5b61, 0x59b8, 0xa629, 0x8d73, 0x699a, 0x6111}}, - {{0x4cc3, 0xd29e, 0xf4a3, 0x3428, 0x2048, 0xeec9, 0x5f50, 0x99a4, - 0x6de9, 0x05f2, 0x5aa9, 0x5fd2, 0x98b4, 0x1adc, 0x225f, 0x777f}, - {0xe649, 0x37da, 0x5ba6, 0x5765, 0x3f4a, 0x8a1c, 0x2e79, 0xf550, - 0x1a54, 0xcd1e, 0x7218, 0x3c3c, 0x6311, 0xfe28, 0x95fb, 0xed97}, - {0xe9b6, 0x0c47, 0x3f0e, 0x849b, 0x11f8, 0xe599, 0x5e4d, 0xd618, - 0xa06d, 0x33a0, 0x9a3e, 0x44db, 0xded8, 0x10f0, 0x94d2, 0x81fb}}, - {{0x2e59, 0x7025, 0xd413, 0x455a, 0x1ce3, 0xbd45, 0x7263, 0x27f7, - 0x23e3, 0x518e, 0xbe06, 0xc8c4, 0xe332, 0x4276, 0x68b4, 0xb166}, - {0x596f, 0x0cf6, 0xc8ec, 0x787b, 0x04c1, 0x473c, 0xd2b8, 0x8d54, - 0x9cdf, 0x77f2, 0xd3f3, 0x6735, 0x0638, 0xf80e, 0x9467, 0xc6aa}, - {0xc7e7, 0x1822, 0xb62a, 0xec0d, 0x89cd, 0x7846, 0xbfa2, 0x35d5, - 0xfa38, 0x870f, 0x494b, 0x1697, 0x8b17, 0xf904, 0x10b6, 0x9822}}, - {{0x6d5b, 0x1d4f, 0x0aaf, 0x807b, 0x35fb, 0x7ee8, 0x00c6, 0x059a, - 0xddf0, 0x1fb1, 0xc38a, 0xd78e, 0x2aa4, 0x79e7, 0xad28, 0xc3f1}, - {0xe3bb, 0x174e, 0xe0a8, 0x74b6, 0xbd5b, 0x35f6, 0x6d23, 0x6328, - 0xc11f, 0x83e1, 0xf928, 0xa918, 0x838e, 0xbf43, 0xe243, 0xfffb}, - {0x9cf2, 0x6b8b, 0x3476, 0x9d06, 0xdcf2, 0xdb8a, 0x89cd, 0x4857, - 0x75c2, 0xabb8, 0x490b, 0xc9bd, 0x890e, 0xe36e, 0xd552, 0xfffa}}, - {{0x2f09, 0x9d62, 0xa9fc, 0xf090, 0xd6d1, 0x9d1d, 0x1828, 0xe413, - 0xc92b, 0x3d5a, 0x1373, 0x368c, 0xbaf2, 0x2158, 0x71eb, 0x08a3}, - {0x2f09, 0x1d62, 0x4630, 0x0de1, 0x06dc, 0xf7f1, 0xc161, 0x1e92, - 0x7495, 0x97e4, 0x94b6, 0xa39e, 0x4f1b, 0x18f8, 0x7bd4, 0x0c4c}, - {0xeb3d, 0x723d, 0x0907, 0x525b, 0x463a, 0x49a8, 0xc6b8, 0xce7f, - 0x740c, 0x0d7d, 0xa83b, 0x457f, 0xae8e, 0xc6af, 0xd331, 0x0475}}, - {{0x6abd, 0xc7af, 0x3e4e, 0x95fd, 0x8fc4, 0xee25, 0x1f9c, 0x0afe, - 0x291d, 0xcde0, 0x48f4, 0xb2e8, 0xf7af, 0x8f8d, 0x0bd6, 0x078d}, - {0x4037, 0xbf0e, 0x2081, 0xf363, 0x13b2, 0x381e, 0xfb6e, 0x818e, - 0x27e4, 0x5662, 0x18b0, 0x0cd2, 0x81f5, 0x9415, 0x0d6c, 0xf9fb}, - {0xd205, 0x0981, 0x0498, 0x1f08, 0xdb93, 0x1732, 0x0579, 0x1424, - 0xad95, 0x642f, 0x050c, 0x1d6d, 0xfc95, 0xfc4a, 0xd41b, 0x3521}}, - {{0xf23a, 0x4633, 0xaef4, 0x1a92, 0x3c8b, 0x1f09, 0x30f3, 0x4c56, - 0x2a2f, 0x4f62, 0xf5e4, 0x8329, 0x63cc, 0xb593, 0xec6a, 0xc428}, - {0x93a7, 0xfcf6, 0x606d, 0xd4b2, 0x2aad, 0x28b4, 0xc65b, 0x8998, - 0x4e08, 0xd178, 0x0900, 0xc82b, 0x7470, 0xa342, 0x7c0f, 0xffff}, - {0x315f, 0xf304, 0xeb7b, 0xe5c3, 0x1451, 0x6311, 0x8f37, 0x93a8, - 0x4a38, 0xa6c6, 0xe393, 0x1087, 0x6301, 0xd673, 0x4ec4, 0xffff}}, - {{0x892e, 0xeed0, 0x1165, 0xcbc1, 0x5545, 0xa280, 0x7243, 0x10c9, - 0x9536, 0x36af, 0xb3fc, 0x2d7c, 0xe8a5, 0x09d6, 0xe1d4, 0xe85d}, - {0xae09, 0xc28a, 0xd777, 0xbd80, 0x23d6, 0xf980, 0xeb7c, 0x4e0e, - 0xf7dc, 0x6475, 0xf10a, 0x2d33, 0x5dfd, 0x797a, 0x7f1c, 0xf71a}, - {0x4064, 0x8717, 0xd091, 0x80b0, 0x4527, 0x8442, 0xac8b, 0x9614, - 0xc633, 0x35f5, 0x7714, 0x2e83, 0x4aaa, 0xd2e4, 0x1acd, 0x0562}}, - {{0xdb64, 0x0937, 0x308b, 0x53b0, 0x00e8, 0xc77f, 0x2f30, 0x37f7, - 0x79ce, 0xeb7f, 0xde81, 0x9286, 0xafda, 0x0e62, 0xae00, 0x0067}, - {0x2cc7, 0xd362, 0xb161, 0x0557, 0x4ff2, 0xb9c8, 0x06fe, 0x5f2b, - 0xde33, 0x0190, 0x28c6, 0xb886, 0xee2b, 0x5a4e, 0x3289, 0x0185}, - {0x4215, 0x923e, 0xf34f, 0xb362, 0x88f8, 0xceec, 0xafdd, 0x7f42, - 0x0c57, 0x56b2, 0xa366, 0x6a08, 0x0826, 0xfb8f, 0x1b03, 0x0163}}, - {{0xa4ba, 0x8408, 0x810a, 0xdeba, 0x47a3, 0x853a, 0xeb64, 0x2f74, - 0x3039, 0x038c, 0x7fbb, 0x498e, 0xd1e9, 0x46fb, 0x5691, 0x32a4}, - {0xd749, 0xb49d, 0x20b7, 0x2af6, 0xd34a, 0xd2da, 0x0a10, 0xf781, - 0x58c9, 0x171f, 0x3cb6, 0x6337, 0x88cd, 0xcf1e, 0xb246, 0x7351}, - {0xf729, 0xcf0a, 0x96ea, 0x032c, 0x4a8f, 0x42fe, 0xbac8, 0xec65, - 0x1510, 0x0d75, 0x4c17, 0x8d29, 0xa03f, 0x8b7e, 0x2c49, 0x0000}}, - {{0x0fa4, 0x8e1c, 0x3788, 0xba3c, 0x8d52, 0xd89d, 0x12c8, 0xeced, - 0x9fe6, 0x9b88, 0xecf3, 0xe3c8, 0xac48, 0x76ed, 0xf23e, 0xda79}, - {0x1103, 0x227c, 0x5b00, 0x3fcf, 0xc5d0, 0x2d28, 0x8020, 0x4d1c, - 0xc6b9, 0x67f9, 0x6f39, 0x989a, 0xda53, 0x3847, 0xd416, 0xe0d0}, - {0xdd8e, 0xcf31, 0x3710, 0x7e44, 0xa511, 0x933c, 0x0cc3, 0x5145, - 0xf632, 0x5e1d, 0x038f, 0x5ce7, 0x7265, 0xda9d, 0xded6, 0x08f8}}, - {{0xe2c8, 0x91d5, 0xa5f5, 0x735f, 0x6b58, 0x56dc, 0xb39d, 0x5c4a, - 0x57d0, 0xa1c2, 0xd92f, 0x9ad4, 0xf7c4, 0x51dd, 0xaf5c, 0x0096}, - {0x1739, 0x7207, 0x7505, 0xbf35, 0x42de, 0x0a29, 0xa962, 0xdedf, - 0x53e8, 0x12bf, 0xcde7, 0xd8e2, 0x8d4d, 0x2c4b, 0xb1b1, 0x0628}, - {0x992d, 0xe3a7, 0xb422, 0xc198, 0x23ab, 0xa6ef, 0xb45d, 0x50da, - 0xa738, 0x014a, 0x2310, 0x85fb, 0x5fe8, 0x1b18, 0x1774, 0x03a7}}, - {{0x1f16, 0x2b09, 0x0236, 0xee90, 0xccf9, 0x9775, 0x8130, 0x4c91, - 0x9091, 0x310b, 0x6dc4, 0x86f6, 0xc2e8, 0xef60, 0xfc0e, 0xf3a4}, - {0x9f49, 0xac15, 0x02af, 0x110f, 0xc59d, 0x5677, 0xa1a9, 0x38d5, - 0x914f, 0xa909, 0x3a3a, 0x4a39, 0x3703, 0xea30, 0x73da, 0xffad}, - {0x15ed, 0xdd16, 0x83c7, 0x270a, 0x862f, 0xd8ad, 0xcaa1, 0x5f41, - 0x99a9, 0x3fc8, 0x7bb2, 0x360a, 0xb06d, 0xfadc, 0x1b36, 0xffa8}}, - {{0xc4e0, 0xb8fd, 0x5106, 0xe169, 0x754c, 0xa58c, 0xc413, 0x8224, - 0x5483, 0x63ec, 0xd477, 0x8473, 0x4778, 0x9281, 0x0000, 0x0000}, - {0x85e1, 0xff54, 0xb200, 0xe413, 0xf4f4, 0x4c0f, 0xfcec, 0xc183, - 0x60d3, 0x1b0c, 0x3834, 0x601c, 0x943c, 0xbe6e, 0x0002, 0x0000}, - {0xf4f8, 0xfd5e, 0x61ef, 0xece8, 0x9199, 0xe5c4, 0x05a6, 0xe6c3, - 0xc4ae, 0x8b28, 0x66b1, 0x8a95, 0x9ece, 0x8f4a, 0x0001, 0x0000}}, - {{0xeae9, 0xa1b4, 0xc6d8, 0x2411, 0x2b5a, 0x1dd0, 0x2dc9, 0xb57b, - 0x5ccd, 0x4957, 0xaf59, 0xa04b, 0x5f42, 0xab7c, 0x2826, 0x526f}, - {0xf407, 0x165a, 0xb724, 0x2f12, 0x2ea1, 0x470b, 0x4464, 0xbd35, - 0x606f, 0xd73e, 0x50d3, 0x8a7f, 0x8029, 0x7ffc, 0xbe31, 0x6cfb}, - {0x8171, 0x1f4c, 0xced2, 0x9c99, 0x6d7e, 0x5a0f, 0xfefb, 0x59e3, - 0xa0c8, 0xabd9, 0xc4c5, 0x57d3, 0xbfa3, 0x4f11, 0x96a2, 0x5a7d}}, - {{0xe068, 0x4cc0, 0x8bcd, 0xc903, 0x9e52, 0xb3e1, 0xd745, 0x0995, - 0xdd8f, 0xf14b, 0xd2ac, 0xd65a, 0xda1d, 0xa742, 0xbac5, 0x474c}, - {0x7481, 0xf2ad, 0x9757, 0x2d82, 0xb683, 0xb16b, 0x0002, 0x7b60, - 0x8f0c, 0x2594, 0x8f64, 0x3b7a, 0x3552, 0x8d9d, 0xb9d7, 0x67eb}, - {0xcaab, 0xb9a1, 0xf966, 0xe311, 0x5b34, 0x0fa0, 0x6abc, 0x8134, - 0xab3d, 0x90f6, 0x1984, 0x9232, 0xec17, 0x74e5, 0x2ceb, 0x434e}}, - {{0x0fb1, 0x7a55, 0x1a5c, 0x53eb, 0xd7b3, 0x7a01, 0xca32, 0x31f6, - 0x3b74, 0x679e, 0x1501, 0x6c57, 0xdb20, 0x8b7c, 0xd7d0, 0x8097}, - {0xb127, 0xb20c, 0xe3a2, 0x96f3, 0xe0d8, 0xd50c, 0x14b4, 0x0b40, - 0x6eeb, 0xa258, 0x99db, 0x3c8c, 0x0f51, 0x4198, 0x3887, 0xffd0}, - {0x0273, 0x9f8c, 0x9669, 0xbbba, 0x1c49, 0x767c, 0xc2af, 0x59f0, - 0x1366, 0xd397, 0x63ac, 0x6fe8, 0x1a9a, 0x1259, 0x01d0, 0x0016}}, - {{0x7876, 0x2a35, 0xa24a, 0x433e, 0x5501, 0x573c, 0xd76d, 0xcb82, - 0x1334, 0xb4a6, 0xf290, 0xc797, 0xeae9, 0x2b83, 0x1e2b, 0x8b14}, - {0x3885, 0x8aef, 0x9dea, 0x2b8c, 0xdd7c, 0xd7cd, 0xb0cc, 0x05ee, - 0x361b, 0x3800, 0xb0d4, 0x4c23, 0xbd3f, 0x5180, 0x9783, 0xff80}, - {0xab36, 0x3104, 0xdae8, 0x0704, 0x4a28, 0x6714, 0x824b, 0x0051, - 0x8134, 0x1f6a, 0x712d, 0x1f03, 0x03b2, 0xecac, 0x377d, 0xfef9}} - }; - - int i, j, ok; - - /* Test known inputs/outputs */ - for (i = 0; (size_t)i < sizeof(CASES) / sizeof(CASES[0]); ++i) { - uint16_t out[16]; - test_modinv32_uint16(out, CASES[i][0], CASES[i][1]); - for (j = 0; j < 16; ++j) CHECK(out[j] == CASES[i][2][j]); -#ifdef SECP256K1_WIDEMUL_INT128 - test_modinv64_uint16(out, CASES[i][0], CASES[i][1]); - for (j = 0; j < 16; ++j) CHECK(out[j] == CASES[i][2][j]); -#endif - } - - for (i = 0; i < 100 * COUNT; ++i) { - /* 256-bit numbers in 16-uint16_t's notation */ - static const uint16_t ZERO[16] = {0}; - uint16_t xd[16]; /* the number (in range [0,2^256)) to be inverted */ - uint16_t md[16]; /* the modulus (odd, in range [3,2^256)) */ - uint16_t id[16]; /* the inverse of xd mod md */ - - /* generate random xd and md, so that md is odd, md>1, xd>= 16; - } -} - -/* Negate a 256-bit number (represented as 16 uint16_t's in LE order) mod 2^256. */ -static void neg256(uint16_t* out, const uint16_t* a) { - int i; - uint32_t carry = 1; - for (i = 0; i < 16; ++i) { - carry += (uint16_t)~a[i]; - out[i] = carry; - carry >>= 16; - } -} - -/* Right-shift a 256-bit number (represented as 16 uint16_t's in LE order). */ -static void rshift256(uint16_t* out, const uint16_t* a, int n, int sign_extend) { - uint16_t sign = sign_extend && (a[15] >> 15); - int i, j; - for (i = 15; i >= 0; --i) { - uint16_t v = 0; - for (j = 0; j < 16; ++j) { - int frompos = i*16 + j + n; - if (frompos >= 256) { - v |= sign << j; - } else { - v |= ((uint16_t)((a[frompos >> 4] >> (frompos & 15)) & 1)) << j; - } - } - out[i] = v; - } -} - -/* Load a 64-bit unsigned integer into an array of 16 uint16_t's in LE order representing a 256-bit value. */ -static void load256u64(uint16_t* out, uint64_t v, int is_signed) { - int i; - uint64_t sign = is_signed && (v >> 63) ? UINT64_MAX : 0; - for (i = 0; i < 4; ++i) { - out[i] = v >> (16 * i); - } - for (i = 4; i < 16; ++i) { - out[i] = sign; - } -} - -/* Load a 128-bit unsigned integer into an array of 16 uint16_t's in LE order representing a 256-bit value. */ -static void load256two64(uint16_t* out, uint64_t hi, uint64_t lo, int is_signed) { - int i; - uint64_t sign = is_signed && (hi >> 63) ? UINT64_MAX : 0; - for (i = 0; i < 4; ++i) { - out[i] = lo >> (16 * i); - } - for (i = 4; i < 8; ++i) { - out[i] = hi >> (16 * (i - 4)); - } - for (i = 8; i < 16; ++i) { - out[i] = sign; - } -} - -/* Check whether the 256-bit value represented by array of 16-bit values is in range -2^127 < v < 2^127. */ -static int int256is127(const uint16_t* v) { - int all_0 = ((v[7] & 0x8000) == 0), all_1 = ((v[7] & 0x8000) == 0x8000); - int i; - for (i = 8; i < 16; ++i) { - if (v[i] != 0) all_0 = 0; - if (v[i] != 0xffff) all_1 = 0; - } - return all_0 || all_1; -} - -static void load256u128(uint16_t* out, const secp256k1_uint128* v) { - uint64_t lo = secp256k1_u128_to_u64(v), hi = secp256k1_u128_hi_u64(v); - load256two64(out, hi, lo, 0); -} - -static void load256i128(uint16_t* out, const secp256k1_int128* v) { - uint64_t lo; - int64_t hi; - secp256k1_int128 c = *v; - lo = secp256k1_i128_to_u64(&c); - secp256k1_i128_rshift(&c, 64); - hi = secp256k1_i128_to_i64(&c); - load256two64(out, hi, lo, 1); -} - -static void run_int128_test_case(void) { - unsigned char buf[32]; - uint64_t v[4]; - secp256k1_int128 swa, swz; - secp256k1_uint128 uwa, uwz; - uint64_t ub, uc; - int64_t sb, sc; - uint16_t rswa[16], rswz[32], rswr[32], ruwa[16], ruwz[32], ruwr[32]; - uint16_t rub[16], ruc[16], rsb[16], rsc[16]; - int i; - - /* Generate 32-byte random value. */ - testrand256_test(buf); - /* Convert into 4 64-bit integers. */ - for (i = 0; i < 4; ++i) { - uint64_t vi = 0; - int j; - for (j = 0; j < 8; ++j) vi = (vi << 8) + buf[8*i + j]; - v[i] = vi; - } - /* Convert those into a 128-bit value and two 64-bit values (signed and unsigned). */ - secp256k1_u128_load(&uwa, v[1], v[0]); - secp256k1_i128_load(&swa, v[1], v[0]); - ub = v[2]; - sb = v[2]; - uc = v[3]; - sc = v[3]; - /* Load those also into 16-bit array representations. */ - load256u128(ruwa, &uwa); - load256i128(rswa, &swa); - load256u64(rub, ub, 0); - load256u64(rsb, sb, 1); - load256u64(ruc, uc, 0); - load256u64(rsc, sc, 1); - /* test secp256k1_u128_mul */ - mulmod256(ruwr, rub, ruc, NULL); - secp256k1_u128_mul(&uwz, ub, uc); - load256u128(ruwz, &uwz); - CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0); - /* test secp256k1_u128_accum_mul */ - mulmod256(ruwr, rub, ruc, NULL); - add256(ruwr, ruwr, ruwa); - uwz = uwa; - secp256k1_u128_accum_mul(&uwz, ub, uc); - load256u128(ruwz, &uwz); - CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0); - /* test secp256k1_u128_accum_u64 */ - add256(ruwr, rub, ruwa); - uwz = uwa; - secp256k1_u128_accum_u64(&uwz, ub); - load256u128(ruwz, &uwz); - CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0); - /* test secp256k1_u128_rshift */ - rshift256(ruwr, ruwa, uc % 128, 0); - uwz = uwa; - secp256k1_u128_rshift(&uwz, uc % 128); - load256u128(ruwz, &uwz); - CHECK(secp256k1_memcmp_var(ruwr, ruwz, 16) == 0); - /* test secp256k1_u128_to_u64 */ - CHECK(secp256k1_u128_to_u64(&uwa) == v[0]); - /* test secp256k1_u128_hi_u64 */ - CHECK(secp256k1_u128_hi_u64(&uwa) == v[1]); - /* test secp256k1_u128_from_u64 */ - secp256k1_u128_from_u64(&uwz, ub); - load256u128(ruwz, &uwz); - CHECK(secp256k1_memcmp_var(rub, ruwz, 16) == 0); - /* test secp256k1_u128_check_bits */ - { - int uwa_bits = 0; - int j; - for (j = 0; j < 128; ++j) { - if (ruwa[j / 16] >> (j % 16)) uwa_bits = 1 + j; - } - for (j = 0; j < 128; ++j) { - CHECK(secp256k1_u128_check_bits(&uwa, j) == (uwa_bits <= j)); - } - } - /* test secp256k1_i128_mul */ - mulmod256(rswr, rsb, rsc, NULL); - secp256k1_i128_mul(&swz, sb, sc); - load256i128(rswz, &swz); - CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0); - /* test secp256k1_i128_accum_mul */ - mulmod256(rswr, rsb, rsc, NULL); - add256(rswr, rswr, rswa); - if (int256is127(rswr)) { - swz = swa; - secp256k1_i128_accum_mul(&swz, sb, sc); - load256i128(rswz, &swz); - CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0); - } - /* test secp256k1_i128_det */ - { - uint16_t rsd[16], rse[16], rst[32]; - int64_t sd = v[0], se = v[1]; - load256u64(rsd, sd, 1); - load256u64(rse, se, 1); - mulmod256(rst, rsc, rsd, NULL); - neg256(rst, rst); - mulmod256(rswr, rsb, rse, NULL); - add256(rswr, rswr, rst); - secp256k1_i128_det(&swz, sb, sc, sd, se); - load256i128(rswz, &swz); - CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0); - } - /* test secp256k1_i128_rshift */ - rshift256(rswr, rswa, uc % 127, 1); - swz = swa; - secp256k1_i128_rshift(&swz, uc % 127); - load256i128(rswz, &swz); - CHECK(secp256k1_memcmp_var(rswr, rswz, 16) == 0); - /* test secp256k1_i128_to_u64 */ - CHECK(secp256k1_i128_to_u64(&swa) == v[0]); - /* test secp256k1_i128_from_i64 */ - secp256k1_i128_from_i64(&swz, sb); - load256i128(rswz, &swz); - CHECK(secp256k1_memcmp_var(rsb, rswz, 16) == 0); - /* test secp256k1_i128_to_i64 */ - CHECK(secp256k1_i128_to_i64(&swz) == sb); - /* test secp256k1_i128_eq_var */ - { - int expect = (uc & 1); - swz = swa; - if (!expect) { - /* Make sure swz != swa */ - uint64_t v0c = v[0], v1c = v[1]; - if (ub & 64) { - v1c ^= (((uint64_t)1) << (ub & 63)); - } else { - v0c ^= (((uint64_t)1) << (ub & 63)); - } - secp256k1_i128_load(&swz, v1c, v0c); - } - CHECK(secp256k1_i128_eq_var(&swa, &swz) == expect); - } - /* test secp256k1_i128_check_pow2 (sign == 1) */ - { - int expect = (uc & 1); - int pos = ub % 127; - if (expect) { - /* If expect==1, set swz to exactly 2^pos. */ - uint64_t hi = 0; - uint64_t lo = 0; - if (pos >= 64) { - hi = (((uint64_t)1) << (pos & 63)); - } else { - lo = (((uint64_t)1) << (pos & 63)); - } - secp256k1_i128_load(&swz, hi, lo); - } else { - /* If expect==0, set swz = swa, but update expect=1 if swa happens to equal 2^pos. */ - if (pos >= 64) { - if ((v[1] == (((uint64_t)1) << (pos & 63))) && v[0] == 0) expect = 1; - } else { - if ((v[0] == (((uint64_t)1) << (pos & 63))) && v[1] == 0) expect = 1; - } - swz = swa; - } - CHECK(secp256k1_i128_check_pow2(&swz, pos, 1) == expect); - } - /* test secp256k1_i128_check_pow2 (sign == -1) */ - { - int expect = (uc & 1); - int pos = ub % 127; - if (expect) { - /* If expect==1, set swz to exactly -2^pos. */ - uint64_t hi = ~(uint64_t)0; - uint64_t lo = ~(uint64_t)0; - if (pos >= 64) { - hi <<= (pos & 63); - lo = 0; - } else { - lo <<= (pos & 63); - } - secp256k1_i128_load(&swz, hi, lo); - } else { - /* If expect==0, set swz = swa, but update expect=1 if swa happens to equal -2^pos. */ - if (pos >= 64) { - if ((v[1] == ((~(uint64_t)0) << (pos & 63))) && v[0] == 0) expect = 1; - } else { - if ((v[0] == ((~(uint64_t)0) << (pos & 63))) && v[1] == ~(uint64_t)0) expect = 1; - } - swz = swa; - } - CHECK(secp256k1_i128_check_pow2(&swz, pos, -1) == expect); - } -} - -static void run_int128_tests(void) { - { /* secp256k1_u128_accum_mul */ - secp256k1_uint128 res; - - /* Check secp256k1_u128_accum_mul overflow */ - secp256k1_u128_mul(&res, UINT64_MAX, UINT64_MAX); - secp256k1_u128_accum_mul(&res, UINT64_MAX, UINT64_MAX); - CHECK(secp256k1_u128_to_u64(&res) == 2); - CHECK(secp256k1_u128_hi_u64(&res) == 18446744073709551612U); - } - { /* secp256k1_u128_accum_mul */ - secp256k1_int128 res; - - /* Compute INT128_MAX = 2^127 - 1 with secp256k1_i128_accum_mul */ - secp256k1_i128_mul(&res, INT64_MAX, INT64_MAX); - secp256k1_i128_accum_mul(&res, INT64_MAX, INT64_MAX); - CHECK(secp256k1_i128_to_u64(&res) == 2); - secp256k1_i128_accum_mul(&res, 4, 9223372036854775807); - secp256k1_i128_accum_mul(&res, 1, 1); - CHECK(secp256k1_i128_to_u64(&res) == UINT64_MAX); - secp256k1_i128_rshift(&res, 64); - CHECK(secp256k1_i128_to_i64(&res) == INT64_MAX); - - /* Compute INT128_MIN = - 2^127 with secp256k1_i128_accum_mul */ - secp256k1_i128_mul(&res, INT64_MAX, INT64_MIN); - CHECK(secp256k1_i128_to_u64(&res) == (uint64_t)INT64_MIN); - secp256k1_i128_accum_mul(&res, INT64_MAX, INT64_MIN); - CHECK(secp256k1_i128_to_u64(&res) == 0); - secp256k1_i128_accum_mul(&res, 2, INT64_MIN); - CHECK(secp256k1_i128_to_u64(&res) == 0); - secp256k1_i128_rshift(&res, 64); - CHECK(secp256k1_i128_to_i64(&res) == INT64_MIN); - } - { - /* Randomized tests. */ - int i; - for (i = 0; i < 256 * COUNT; ++i) run_int128_test_case(); - } -} -#endif - -/***** SCALAR TESTS *****/ - -static void scalar_test(void) { - secp256k1_scalar s; - secp256k1_scalar s1; - secp256k1_scalar s2; - unsigned char c[32]; - - /* Set 's' to a random scalar, with value 'snum'. */ - testutil_random_scalar_order_test(&s); - - /* Set 's1' to a random scalar, with value 's1num'. */ - testutil_random_scalar_order_test(&s1); - - /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ - testutil_random_scalar_order_test(&s2); - secp256k1_scalar_get_b32(c, &s2); - - { - int i; - /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ - secp256k1_scalar n; - secp256k1_scalar_set_int(&n, 0); - for (i = 0; i < 256; i += 4) { - secp256k1_scalar t; - int j; - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_limb32(&s, 256 - 4 - i, 4)); - for (j = 0; j < 4; j++) { - secp256k1_scalar_add(&n, &n, &n); - } - secp256k1_scalar_add(&n, &n, &t); - } - CHECK(secp256k1_scalar_eq(&n, &s)); - } - - { - /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ - secp256k1_scalar n; - int i = 0; - secp256k1_scalar_set_int(&n, 0); - while (i < 256) { - secp256k1_scalar t; - int j; - int now = testrand_int(15) + 1; - if (now + i > 256) { - now = 256 - i; - } - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); - for (j = 0; j < now; j++) { - secp256k1_scalar_add(&n, &n, &n); - } - secp256k1_scalar_add(&n, &n, &t); - i += now; - } - CHECK(secp256k1_scalar_eq(&n, &s)); - } - - { - /* Test commutativity of add. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_add(&r2, &s2, &s1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - secp256k1_scalar r1, r2; - secp256k1_scalar b; - int i; - /* Test add_bit. */ - int bit = testrand_bits(8); - secp256k1_scalar_set_int(&b, 1); - CHECK(secp256k1_scalar_is_one(&b)); - for (i = 0; i < bit; i++) { - secp256k1_scalar_add(&b, &b, &b); - } - r1 = s1; - r2 = s1; - if (!secp256k1_scalar_add(&r1, &r1, &b)) { - /* No overflow happened. */ - secp256k1_scalar_cadd_bit(&r2, bit, 1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - /* cadd is a noop when flag is zero */ - secp256k1_scalar_cadd_bit(&r2, bit, 0); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - } - - { - /* Test commutativity of mul. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_mul(&r1, &s1, &s2); - secp256k1_scalar_mul(&r2, &s2, &s1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test associativity of add. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_add(&r1, &r1, &s); - secp256k1_scalar_add(&r2, &s2, &s); - secp256k1_scalar_add(&r2, &s1, &r2); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test associativity of mul. */ - secp256k1_scalar r1, r2; - secp256k1_scalar_mul(&r1, &s1, &s2); - secp256k1_scalar_mul(&r1, &r1, &s); - secp256k1_scalar_mul(&r2, &s2, &s); - secp256k1_scalar_mul(&r2, &s1, &r2); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test distributitivity of mul over add. */ - secp256k1_scalar r1, r2, t; - secp256k1_scalar_add(&r1, &s1, &s2); - secp256k1_scalar_mul(&r1, &r1, &s); - secp256k1_scalar_mul(&r2, &s1, &s); - secp256k1_scalar_mul(&t, &s2, &s); - secp256k1_scalar_add(&r2, &r2, &t); - CHECK(secp256k1_scalar_eq(&r1, &r2)); - } - - { - /* Test multiplicative identity. */ - secp256k1_scalar r1; - secp256k1_scalar_mul(&r1, &s1, &secp256k1_scalar_one); - CHECK(secp256k1_scalar_eq(&r1, &s1)); - } - - { - /* Test additive identity. */ - secp256k1_scalar r1; - secp256k1_scalar_add(&r1, &s1, &secp256k1_scalar_zero); - CHECK(secp256k1_scalar_eq(&r1, &s1)); - } - - { - /* Test zero product property. */ - secp256k1_scalar r1; - secp256k1_scalar_mul(&r1, &s1, &secp256k1_scalar_zero); - CHECK(secp256k1_scalar_eq(&r1, &secp256k1_scalar_zero)); - } - - { - /* Test halving. */ - secp256k1_scalar r; - secp256k1_scalar_add(&r, &s, &s); - secp256k1_scalar_half(&r, &r); - CHECK(secp256k1_scalar_eq(&r, &s)); - } -} - -static void run_scalar_set_b32_seckey_tests(void) { - unsigned char b32[32]; - secp256k1_scalar s1; - secp256k1_scalar s2; - - /* Usually set_b32 and set_b32_seckey give the same result */ - testutil_random_scalar_order_b32(b32); - secp256k1_scalar_set_b32(&s1, b32, NULL); - CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 1); - CHECK(secp256k1_scalar_eq(&s1, &s2) == 1); - - memset(b32, 0, sizeof(b32)); - CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 0); - memset(b32, 0xFF, sizeof(b32)); - CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 0); -} - -static void run_scalar_tests(void) { - int i; - for (i = 0; i < 128 * COUNT; i++) { - scalar_test(); - } - for (i = 0; i < COUNT; i++) { - run_scalar_set_b32_seckey_tests(); - } - - { - /* Check that the scalar constants secp256k1_scalar_zero and - secp256k1_scalar_one contain the expected values. */ - secp256k1_scalar zero, one; - - CHECK(secp256k1_scalar_is_zero(&secp256k1_scalar_zero)); - secp256k1_scalar_set_int(&zero, 0); - CHECK(secp256k1_scalar_eq(&zero, &secp256k1_scalar_zero)); - - CHECK(secp256k1_scalar_is_one(&secp256k1_scalar_one)); - secp256k1_scalar_set_int(&one, 1); - CHECK(secp256k1_scalar_eq(&one, &secp256k1_scalar_one)); - } - - { - /* (-1)+1 should be zero. */ - secp256k1_scalar o; - secp256k1_scalar_negate(&o, &secp256k1_scalar_one); - secp256k1_scalar_add(&o, &o, &secp256k1_scalar_one); - CHECK(secp256k1_scalar_is_zero(&o)); - secp256k1_scalar_negate(&o, &o); - CHECK(secp256k1_scalar_is_zero(&o)); - } - - { - /* Test that halving and doubling roundtrips on some fixed values. */ - static const secp256k1_scalar HALF_TESTS[] = { - /* 0 */ - SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0), - /* 1 */ - SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1), - /* -1 */ - SECP256K1_SCALAR_CONST(0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffeul, 0xbaaedce6ul, 0xaf48a03bul, 0xbfd25e8cul, 0xd0364140ul), - /* -2 (largest odd value) */ - SECP256K1_SCALAR_CONST(0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffeul, 0xbaaedce6ul, 0xaf48a03bul, 0xbfd25e8cul, 0xd036413Ful), - /* Half the secp256k1 order */ - SECP256K1_SCALAR_CONST(0x7ffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0x5d576e73ul, 0x57a4501dul, 0xdfe92f46ul, 0x681b20a0ul), - /* Half the secp256k1 order + 1 */ - SECP256K1_SCALAR_CONST(0x7ffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0x5d576e73ul, 0x57a4501dul, 0xdfe92f46ul, 0x681b20a1ul), - /* 2^255 */ - SECP256K1_SCALAR_CONST(0x80000000ul, 0, 0, 0, 0, 0, 0, 0), - /* 2^255 - 1 */ - SECP256K1_SCALAR_CONST(0x7ffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful), - }; - unsigned n; - for (n = 0; n < sizeof(HALF_TESTS) / sizeof(HALF_TESTS[0]); ++n) { - secp256k1_scalar s; - secp256k1_scalar_half(&s, &HALF_TESTS[n]); - secp256k1_scalar_add(&s, &s, &s); - CHECK(secp256k1_scalar_eq(&s, &HALF_TESTS[n])); - secp256k1_scalar_add(&s, &s, &s); - secp256k1_scalar_half(&s, &s); - CHECK(secp256k1_scalar_eq(&s, &HALF_TESTS[n])); - } - } - - { - /* Does check_overflow check catch all ones? */ - static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL - ); - CHECK(secp256k1_scalar_check_overflow(&overflowed)); - } - - { - /* Static test vectors. - * These were reduced from ~10^12 random vectors based on comparison-decision - * and edge-case coverage on 32-bit and 64-bit implementations. - * The responses were generated with Sage 5.9. - */ - secp256k1_scalar x; - secp256k1_scalar y; - secp256k1_scalar z; - secp256k1_scalar zz; - secp256k1_scalar r1; - secp256k1_scalar r2; - secp256k1_scalar zzv; - int overflow; - unsigned char chal[33][2][32] = { - {{0xff, 0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff}}, - {{0xef, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x80, 0xff}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0x3f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00}, - {0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x1e, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xe0, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, - 0xf3, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xfc, 0x9f, - 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0x0f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0xf8, 0xff, 0x0f, 0xc0, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xf7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0x00, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0}, - {0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0x00, 0xf8, 0xff, 0x03, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0xc0, 0xff, 0x0f, 0xfc, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, - 0xff, 0x01, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0x7f}, - {0xff, 0xcf, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, - 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0x01, 0xfc, 0xff, 0x01, 0x00, 0xfe, 0xff}, - {0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0xff, - 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, - 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7e, 0x00, 0x00}}, - {{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x07, 0x00}, - {0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfb, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60}}, - {{0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x00, - 0x80, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0x1f, 0x00, 0xf0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00}}, - {{0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, - 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0xff, 0xff, 0xcf, 0xff, 0x1f, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x7e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00}, - {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0x7f, 0x00, 0x80, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, - 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x1f, 0x00, 0xfe}}, - {{0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0x03, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, - 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff}}, - {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x7e, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, - {{0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, - 0xff, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x3f, 0x00, 0x00, 0xc0, 0xf1, 0x7f, 0x00}}, - {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00}, - {0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, - 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, - 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0xff, 0xff}}, - {{0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0x00, 0x00, 0x80, 0xff, 0x03, 0xe0, 0x01, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, - {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xff, 0xff, 0xf0, 0x07, 0x00, 0x3c, 0x80, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x07, 0xe0, 0xff, 0x00, 0x00, 0x00}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x80, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0x7f, 0xfe, 0xff, 0x1f, - 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0xfe, 0xff}}, - {{0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, - 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, - 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf0}, - {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, - 0xf8, 0x07, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc7, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff}}, - {{0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, - 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}, - {0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, - 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}} - }; - unsigned char res[33][2][32] = { - {{0x0c, 0x3b, 0x0a, 0xca, 0x8d, 0x1a, 0x2f, 0xb9, - 0x8a, 0x7b, 0x53, 0x5a, 0x1f, 0xc5, 0x22, 0xa1, - 0x07, 0x2a, 0x48, 0xea, 0x02, 0xeb, 0xb3, 0xd6, - 0x20, 0x1e, 0x86, 0xd0, 0x95, 0xf6, 0x92, 0x35}, - {0xdc, 0x90, 0x7a, 0x07, 0x2e, 0x1e, 0x44, 0x6d, - 0xf8, 0x15, 0x24, 0x5b, 0x5a, 0x96, 0x37, 0x9c, - 0x37, 0x7b, 0x0d, 0xac, 0x1b, 0x65, 0x58, 0x49, - 0x43, 0xb7, 0x31, 0xbb, 0xa7, 0xf4, 0x97, 0x15}}, - {{0xf1, 0xf7, 0x3a, 0x50, 0xe6, 0x10, 0xba, 0x22, - 0x43, 0x4d, 0x1f, 0x1f, 0x7c, 0x27, 0xca, 0x9c, - 0xb8, 0xb6, 0xa0, 0xfc, 0xd8, 0xc0, 0x05, 0x2f, - 0xf7, 0x08, 0xe1, 0x76, 0xdd, 0xd0, 0x80, 0xc8}, - {0xe3, 0x80, 0x80, 0xb8, 0xdb, 0xe3, 0xa9, 0x77, - 0x00, 0xb0, 0xf5, 0x2e, 0x27, 0xe2, 0x68, 0xc4, - 0x88, 0xe8, 0x04, 0xc1, 0x12, 0xbf, 0x78, 0x59, - 0xe6, 0xa9, 0x7c, 0xe1, 0x81, 0xdd, 0xb9, 0xd5}}, - {{0x96, 0xe2, 0xee, 0x01, 0xa6, 0x80, 0x31, 0xef, - 0x5c, 0xd0, 0x19, 0xb4, 0x7d, 0x5f, 0x79, 0xab, - 0xa1, 0x97, 0xd3, 0x7e, 0x33, 0xbb, 0x86, 0x55, - 0x60, 0x20, 0x10, 0x0d, 0x94, 0x2d, 0x11, 0x7c}, - {0xcc, 0xab, 0xe0, 0xe8, 0x98, 0x65, 0x12, 0x96, - 0x38, 0x5a, 0x1a, 0xf2, 0x85, 0x23, 0x59, 0x5f, - 0xf9, 0xf3, 0xc2, 0x81, 0x70, 0x92, 0x65, 0x12, - 0x9c, 0x65, 0x1e, 0x96, 0x00, 0xef, 0xe7, 0x63}}, - {{0xac, 0x1e, 0x62, 0xc2, 0x59, 0xfc, 0x4e, 0x5c, - 0x83, 0xb0, 0xd0, 0x6f, 0xce, 0x19, 0xf6, 0xbf, - 0xa4, 0xb0, 0xe0, 0x53, 0x66, 0x1f, 0xbf, 0xc9, - 0x33, 0x47, 0x37, 0xa9, 0x3d, 0x5d, 0xb0, 0x48}, - {0x86, 0xb9, 0x2a, 0x7f, 0x8e, 0xa8, 0x60, 0x42, - 0x26, 0x6d, 0x6e, 0x1c, 0xa2, 0xec, 0xe0, 0xe5, - 0x3e, 0x0a, 0x33, 0xbb, 0x61, 0x4c, 0x9f, 0x3c, - 0xd1, 0xdf, 0x49, 0x33, 0xcd, 0x72, 0x78, 0x18}}, - {{0xf7, 0xd3, 0xcd, 0x49, 0x5c, 0x13, 0x22, 0xfb, - 0x2e, 0xb2, 0x2f, 0x27, 0xf5, 0x8a, 0x5d, 0x74, - 0xc1, 0x58, 0xc5, 0xc2, 0x2d, 0x9f, 0x52, 0xc6, - 0x63, 0x9f, 0xba, 0x05, 0x76, 0x45, 0x7a, 0x63}, - {0x8a, 0xfa, 0x55, 0x4d, 0xdd, 0xa3, 0xb2, 0xc3, - 0x44, 0xfd, 0xec, 0x72, 0xde, 0xef, 0xc0, 0x99, - 0xf5, 0x9f, 0xe2, 0x52, 0xb4, 0x05, 0x32, 0x58, - 0x57, 0xc1, 0x8f, 0xea, 0xc3, 0x24, 0x5b, 0x94}}, - {{0x05, 0x83, 0xee, 0xdd, 0x64, 0xf0, 0x14, 0x3b, - 0xa0, 0x14, 0x4a, 0x3a, 0x41, 0x82, 0x7c, 0xa7, - 0x2c, 0xaa, 0xb1, 0x76, 0xbb, 0x59, 0x64, 0x5f, - 0x52, 0xad, 0x25, 0x29, 0x9d, 0x8f, 0x0b, 0xb0}, - {0x7e, 0xe3, 0x7c, 0xca, 0xcd, 0x4f, 0xb0, 0x6d, - 0x7a, 0xb2, 0x3e, 0xa0, 0x08, 0xb9, 0xa8, 0x2d, - 0xc2, 0xf4, 0x99, 0x66, 0xcc, 0xac, 0xd8, 0xb9, - 0x72, 0x2a, 0x4a, 0x3e, 0x0f, 0x7b, 0xbf, 0xf4}}, - {{0x8c, 0x9c, 0x78, 0x2b, 0x39, 0x61, 0x7e, 0xf7, - 0x65, 0x37, 0x66, 0x09, 0x38, 0xb9, 0x6f, 0x70, - 0x78, 0x87, 0xff, 0xcf, 0x93, 0xca, 0x85, 0x06, - 0x44, 0x84, 0xa7, 0xfe, 0xd3, 0xa4, 0xe3, 0x7e}, - {0xa2, 0x56, 0x49, 0x23, 0x54, 0xa5, 0x50, 0xe9, - 0x5f, 0xf0, 0x4d, 0xe7, 0xdc, 0x38, 0x32, 0x79, - 0x4f, 0x1c, 0xb7, 0xe4, 0xbb, 0xf8, 0xbb, 0x2e, - 0x40, 0x41, 0x4b, 0xcc, 0xe3, 0x1e, 0x16, 0x36}}, - {{0x0c, 0x1e, 0xd7, 0x09, 0x25, 0x40, 0x97, 0xcb, - 0x5c, 0x46, 0xa8, 0xda, 0xef, 0x25, 0xd5, 0xe5, - 0x92, 0x4d, 0xcf, 0xa3, 0xc4, 0x5d, 0x35, 0x4a, - 0xe4, 0x61, 0x92, 0xf3, 0xbf, 0x0e, 0xcd, 0xbe}, - {0xe4, 0xaf, 0x0a, 0xb3, 0x30, 0x8b, 0x9b, 0x48, - 0x49, 0x43, 0xc7, 0x64, 0x60, 0x4a, 0x2b, 0x9e, - 0x95, 0x5f, 0x56, 0xe8, 0x35, 0xdc, 0xeb, 0xdc, - 0xc7, 0xc4, 0xfe, 0x30, 0x40, 0xc7, 0xbf, 0xa4}}, - {{0xd4, 0xa0, 0xf5, 0x81, 0x49, 0x6b, 0xb6, 0x8b, - 0x0a, 0x69, 0xf9, 0xfe, 0xa8, 0x32, 0xe5, 0xe0, - 0xa5, 0xcd, 0x02, 0x53, 0xf9, 0x2c, 0xe3, 0x53, - 0x83, 0x36, 0xc6, 0x02, 0xb5, 0xeb, 0x64, 0xb8}, - {0x1d, 0x42, 0xb9, 0xf9, 0xe9, 0xe3, 0x93, 0x2c, - 0x4c, 0xee, 0x6c, 0x5a, 0x47, 0x9e, 0x62, 0x01, - 0x6b, 0x04, 0xfe, 0xa4, 0x30, 0x2b, 0x0d, 0x4f, - 0x71, 0x10, 0xd3, 0x55, 0xca, 0xf3, 0x5e, 0x80}}, - {{0x77, 0x05, 0xf6, 0x0c, 0x15, 0x9b, 0x45, 0xe7, - 0xb9, 0x11, 0xb8, 0xf5, 0xd6, 0xda, 0x73, 0x0c, - 0xda, 0x92, 0xea, 0xd0, 0x9d, 0xd0, 0x18, 0x92, - 0xce, 0x9a, 0xaa, 0xee, 0x0f, 0xef, 0xde, 0x30}, - {0xf1, 0xf1, 0xd6, 0x9b, 0x51, 0xd7, 0x77, 0x62, - 0x52, 0x10, 0xb8, 0x7a, 0x84, 0x9d, 0x15, 0x4e, - 0x07, 0xdc, 0x1e, 0x75, 0x0d, 0x0c, 0x3b, 0xdb, - 0x74, 0x58, 0x62, 0x02, 0x90, 0x54, 0x8b, 0x43}}, - {{0xa6, 0xfe, 0x0b, 0x87, 0x80, 0x43, 0x67, 0x25, - 0x57, 0x5d, 0xec, 0x40, 0x50, 0x08, 0xd5, 0x5d, - 0x43, 0xd7, 0xe0, 0xaa, 0xe0, 0x13, 0xb6, 0xb0, - 0xc0, 0xd4, 0xe5, 0x0d, 0x45, 0x83, 0xd6, 0x13}, - {0x40, 0x45, 0x0a, 0x92, 0x31, 0xea, 0x8c, 0x60, - 0x8c, 0x1f, 0xd8, 0x76, 0x45, 0xb9, 0x29, 0x00, - 0x26, 0x32, 0xd8, 0xa6, 0x96, 0x88, 0xe2, 0xc4, - 0x8b, 0xdb, 0x7f, 0x17, 0x87, 0xcc, 0xc8, 0xf2}}, - {{0xc2, 0x56, 0xe2, 0xb6, 0x1a, 0x81, 0xe7, 0x31, - 0x63, 0x2e, 0xbb, 0x0d, 0x2f, 0x81, 0x67, 0xd4, - 0x22, 0xe2, 0x38, 0x02, 0x25, 0x97, 0xc7, 0x88, - 0x6e, 0xdf, 0xbe, 0x2a, 0xa5, 0x73, 0x63, 0xaa}, - {0x50, 0x45, 0xe2, 0xc3, 0xbd, 0x89, 0xfc, 0x57, - 0xbd, 0x3c, 0xa3, 0x98, 0x7e, 0x7f, 0x36, 0x38, - 0x92, 0x39, 0x1f, 0x0f, 0x81, 0x1a, 0x06, 0x51, - 0x1f, 0x8d, 0x6a, 0xff, 0x47, 0x16, 0x06, 0x9c}}, - {{0x33, 0x95, 0xa2, 0x6f, 0x27, 0x5f, 0x9c, 0x9c, - 0x64, 0x45, 0xcb, 0xd1, 0x3c, 0xee, 0x5e, 0x5f, - 0x48, 0xa6, 0xaf, 0xe3, 0x79, 0xcf, 0xb1, 0xe2, - 0xbf, 0x55, 0x0e, 0xa2, 0x3b, 0x62, 0xf0, 0xe4}, - {0x14, 0xe8, 0x06, 0xe3, 0xbe, 0x7e, 0x67, 0x01, - 0xc5, 0x21, 0x67, 0xd8, 0x54, 0xb5, 0x7f, 0xa4, - 0xf9, 0x75, 0x70, 0x1c, 0xfd, 0x79, 0xdb, 0x86, - 0xad, 0x37, 0x85, 0x83, 0x56, 0x4e, 0xf0, 0xbf}}, - {{0xbc, 0xa6, 0xe0, 0x56, 0x4e, 0xef, 0xfa, 0xf5, - 0x1d, 0x5d, 0x3f, 0x2a, 0x5b, 0x19, 0xab, 0x51, - 0xc5, 0x8b, 0xdd, 0x98, 0x28, 0x35, 0x2f, 0xc3, - 0x81, 0x4f, 0x5c, 0xe5, 0x70, 0xb9, 0xeb, 0x62}, - {0xc4, 0x6d, 0x26, 0xb0, 0x17, 0x6b, 0xfe, 0x6c, - 0x12, 0xf8, 0xe7, 0xc1, 0xf5, 0x2f, 0xfa, 0x91, - 0x13, 0x27, 0xbd, 0x73, 0xcc, 0x33, 0x31, 0x1c, - 0x39, 0xe3, 0x27, 0x6a, 0x95, 0xcf, 0xc5, 0xfb}}, - {{0x30, 0xb2, 0x99, 0x84, 0xf0, 0x18, 0x2a, 0x6e, - 0x1e, 0x27, 0xed, 0xa2, 0x29, 0x99, 0x41, 0x56, - 0xe8, 0xd4, 0x0d, 0xef, 0x99, 0x9c, 0xf3, 0x58, - 0x29, 0x55, 0x1a, 0xc0, 0x68, 0xd6, 0x74, 0xa4}, - {0x07, 0x9c, 0xe7, 0xec, 0xf5, 0x36, 0x73, 0x41, - 0xa3, 0x1c, 0xe5, 0x93, 0x97, 0x6a, 0xfd, 0xf7, - 0x53, 0x18, 0xab, 0xaf, 0xeb, 0x85, 0xbd, 0x92, - 0x90, 0xab, 0x3c, 0xbf, 0x30, 0x82, 0xad, 0xf6}}, - {{0xc6, 0x87, 0x8a, 0x2a, 0xea, 0xc0, 0xa9, 0xec, - 0x6d, 0xd3, 0xdc, 0x32, 0x23, 0xce, 0x62, 0x19, - 0xa4, 0x7e, 0xa8, 0xdd, 0x1c, 0x33, 0xae, 0xd3, - 0x4f, 0x62, 0x9f, 0x52, 0xe7, 0x65, 0x46, 0xf4}, - {0x97, 0x51, 0x27, 0x67, 0x2d, 0xa2, 0x82, 0x87, - 0x98, 0xd3, 0xb6, 0x14, 0x7f, 0x51, 0xd3, 0x9a, - 0x0b, 0xd0, 0x76, 0x81, 0xb2, 0x4f, 0x58, 0x92, - 0xa4, 0x86, 0xa1, 0xa7, 0x09, 0x1d, 0xef, 0x9b}}, - {{0xb3, 0x0f, 0x2b, 0x69, 0x0d, 0x06, 0x90, 0x64, - 0xbd, 0x43, 0x4c, 0x10, 0xe8, 0x98, 0x1c, 0xa3, - 0xe1, 0x68, 0xe9, 0x79, 0x6c, 0x29, 0x51, 0x3f, - 0x41, 0xdc, 0xdf, 0x1f, 0xf3, 0x60, 0xbe, 0x33}, - {0xa1, 0x5f, 0xf7, 0x1d, 0xb4, 0x3e, 0x9b, 0x3c, - 0xe7, 0xbd, 0xb6, 0x06, 0xd5, 0x60, 0x06, 0x6d, - 0x50, 0xd2, 0xf4, 0x1a, 0x31, 0x08, 0xf2, 0xea, - 0x8e, 0xef, 0x5f, 0x7d, 0xb6, 0xd0, 0xc0, 0x27}}, - {{0x62, 0x9a, 0xd9, 0xbb, 0x38, 0x36, 0xce, 0xf7, - 0x5d, 0x2f, 0x13, 0xec, 0xc8, 0x2d, 0x02, 0x8a, - 0x2e, 0x72, 0xf0, 0xe5, 0x15, 0x9d, 0x72, 0xae, - 0xfc, 0xb3, 0x4f, 0x02, 0xea, 0xe1, 0x09, 0xfe}, - {0x00, 0x00, 0x00, 0x00, 0xfa, 0x0a, 0x3d, 0xbc, - 0xad, 0x16, 0x0c, 0xb6, 0xe7, 0x7c, 0x8b, 0x39, - 0x9a, 0x43, 0xbb, 0xe3, 0xc2, 0x55, 0x15, 0x14, - 0x75, 0xac, 0x90, 0x9b, 0x7f, 0x9a, 0x92, 0x00}}, - {{0x8b, 0xac, 0x70, 0x86, 0x29, 0x8f, 0x00, 0x23, - 0x7b, 0x45, 0x30, 0xaa, 0xb8, 0x4c, 0xc7, 0x8d, - 0x4e, 0x47, 0x85, 0xc6, 0x19, 0xe3, 0x96, 0xc2, - 0x9a, 0xa0, 0x12, 0xed, 0x6f, 0xd7, 0x76, 0x16}, - {0x45, 0xaf, 0x7e, 0x33, 0xc7, 0x7f, 0x10, 0x6c, - 0x7c, 0x9f, 0x29, 0xc1, 0xa8, 0x7e, 0x15, 0x84, - 0xe7, 0x7d, 0xc0, 0x6d, 0xab, 0x71, 0x5d, 0xd0, - 0x6b, 0x9f, 0x97, 0xab, 0xcb, 0x51, 0x0c, 0x9f}}, - {{0x9e, 0xc3, 0x92, 0xb4, 0x04, 0x9f, 0xc8, 0xbb, - 0xdd, 0x9e, 0xc6, 0x05, 0xfd, 0x65, 0xec, 0x94, - 0x7f, 0x2c, 0x16, 0xc4, 0x40, 0xac, 0x63, 0x7b, - 0x7d, 0xb8, 0x0c, 0xe4, 0x5b, 0xe3, 0xa7, 0x0e}, - {0x43, 0xf4, 0x44, 0xe8, 0xcc, 0xc8, 0xd4, 0x54, - 0x33, 0x37, 0x50, 0xf2, 0x87, 0x42, 0x2e, 0x00, - 0x49, 0x60, 0x62, 0x02, 0xfd, 0x1a, 0x7c, 0xdb, - 0x29, 0x6c, 0x6d, 0x54, 0x53, 0x08, 0xd1, 0xc8}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}, - {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, - {{0x28, 0x56, 0xac, 0x0e, 0x4f, 0x98, 0x09, 0xf0, - 0x49, 0xfa, 0x7f, 0x84, 0xac, 0x7e, 0x50, 0x5b, - 0x17, 0x43, 0x14, 0x89, 0x9c, 0x53, 0xa8, 0x94, - 0x30, 0xf2, 0x11, 0x4d, 0x92, 0x14, 0x27, 0xe8}, - {0x39, 0x7a, 0x84, 0x56, 0x79, 0x9d, 0xec, 0x26, - 0x2c, 0x53, 0xc1, 0x94, 0xc9, 0x8d, 0x9e, 0x9d, - 0x32, 0x1f, 0xdd, 0x84, 0x04, 0xe8, 0xe2, 0x0a, - 0x6b, 0xbe, 0xbb, 0x42, 0x40, 0x67, 0x30, 0x6c}}, - {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x73, 0x2f, 0xc9, 0xbe, 0xbd}, - {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, - 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, - 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, - 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, - {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - {{0x1c, 0xc4, 0xf7, 0xda, 0x0f, 0x65, 0xca, 0x39, - 0x70, 0x52, 0x92, 0x8e, 0xc3, 0xc8, 0x15, 0xea, - 0x7f, 0x10, 0x9e, 0x77, 0x4b, 0x6e, 0x2d, 0xdf, - 0xe8, 0x30, 0x9d, 0xda, 0xe8, 0x9a, 0x65, 0xae}, - {0x02, 0xb0, 0x16, 0xb1, 0x1d, 0xc8, 0x57, 0x7b, - 0xa2, 0x3a, 0xa2, 0xa3, 0x38, 0x5c, 0x8f, 0xeb, - 0x66, 0x37, 0x91, 0xa8, 0x5f, 0xef, 0x04, 0xf6, - 0x59, 0x75, 0xe1, 0xee, 0x92, 0xf6, 0x0e, 0x30}}, - {{0x8d, 0x76, 0x14, 0xa4, 0x14, 0x06, 0x9f, 0x9a, - 0xdf, 0x4a, 0x85, 0xa7, 0x6b, 0xbf, 0x29, 0x6f, - 0xbc, 0x34, 0x87, 0x5d, 0xeb, 0xbb, 0x2e, 0xa9, - 0xc9, 0x1f, 0x58, 0xd6, 0x9a, 0x82, 0xa0, 0x56}, - {0xd4, 0xb9, 0xdb, 0x88, 0x1d, 0x04, 0xe9, 0x93, - 0x8d, 0x3f, 0x20, 0xd5, 0x86, 0xa8, 0x83, 0x07, - 0xdb, 0x09, 0xd8, 0x22, 0x1f, 0x7f, 0xf1, 0x71, - 0xc8, 0xe7, 0x5d, 0x47, 0xaf, 0x8b, 0x72, 0xe9}}, - {{0x83, 0xb9, 0x39, 0xb2, 0xa4, 0xdf, 0x46, 0x87, - 0xc2, 0xb8, 0xf1, 0xe6, 0x4c, 0xd1, 0xe2, 0xa9, - 0xe4, 0x70, 0x30, 0x34, 0xbc, 0x52, 0x7c, 0x55, - 0xa6, 0xec, 0x80, 0xa4, 0xe5, 0xd2, 0xdc, 0x73}, - {0x08, 0xf1, 0x03, 0xcf, 0x16, 0x73, 0xe8, 0x7d, - 0xb6, 0x7e, 0x9b, 0xc0, 0xb4, 0xc2, 0xa5, 0x86, - 0x02, 0x77, 0xd5, 0x27, 0x86, 0xa5, 0x15, 0xfb, - 0xae, 0x9b, 0x8c, 0xa9, 0xf9, 0xf8, 0xa8, 0x4a}}, - {{0x8b, 0x00, 0x49, 0xdb, 0xfa, 0xf0, 0x1b, 0xa2, - 0xed, 0x8a, 0x9a, 0x7a, 0x36, 0x78, 0x4a, 0xc7, - 0xf7, 0xad, 0x39, 0xd0, 0x6c, 0x65, 0x7a, 0x41, - 0xce, 0xd6, 0xd6, 0x4c, 0x20, 0x21, 0x6b, 0xc7}, - {0xc6, 0xca, 0x78, 0x1d, 0x32, 0x6c, 0x6c, 0x06, - 0x91, 0xf2, 0x1a, 0xe8, 0x43, 0x16, 0xea, 0x04, - 0x3c, 0x1f, 0x07, 0x85, 0xf7, 0x09, 0x22, 0x08, - 0xba, 0x13, 0xfd, 0x78, 0x1e, 0x3f, 0x6f, 0x62}}, - {{0x25, 0x9b, 0x7c, 0xb0, 0xac, 0x72, 0x6f, 0xb2, - 0xe3, 0x53, 0x84, 0x7a, 0x1a, 0x9a, 0x98, 0x9b, - 0x44, 0xd3, 0x59, 0xd0, 0x8e, 0x57, 0x41, 0x40, - 0x78, 0xa7, 0x30, 0x2f, 0x4c, 0x9c, 0xb9, 0x68}, - {0xb7, 0x75, 0x03, 0x63, 0x61, 0xc2, 0x48, 0x6e, - 0x12, 0x3d, 0xbf, 0x4b, 0x27, 0xdf, 0xb1, 0x7a, - 0xff, 0x4e, 0x31, 0x07, 0x83, 0xf4, 0x62, 0x5b, - 0x19, 0xa5, 0xac, 0xa0, 0x32, 0x58, 0x0d, 0xa7}}, - {{0x43, 0x4f, 0x10, 0xa4, 0xca, 0xdb, 0x38, 0x67, - 0xfa, 0xae, 0x96, 0xb5, 0x6d, 0x97, 0xff, 0x1f, - 0xb6, 0x83, 0x43, 0xd3, 0xa0, 0x2d, 0x70, 0x7a, - 0x64, 0x05, 0x4c, 0xa7, 0xc1, 0xa5, 0x21, 0x51}, - {0xe4, 0xf1, 0x23, 0x84, 0xe1, 0xb5, 0x9d, 0xf2, - 0xb8, 0x73, 0x8b, 0x45, 0x2b, 0x35, 0x46, 0x38, - 0x10, 0x2b, 0x50, 0xf8, 0x8b, 0x35, 0xcd, 0x34, - 0xc8, 0x0e, 0xf6, 0xdb, 0x09, 0x35, 0xf0, 0xda}}, - {{0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, - 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, - 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, - 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}, - {0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, - 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, - 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, - 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} - }; - for (i = 0; i < 33; i++) { - secp256k1_scalar_set_b32(&x, chal[i][0], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&y, chal[i][1], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&r1, res[i][0], &overflow); - CHECK(!overflow); - secp256k1_scalar_set_b32(&r2, res[i][1], &overflow); - CHECK(!overflow); - secp256k1_scalar_mul(&z, &x, &y); - CHECK(secp256k1_scalar_eq(&r1, &z)); - if (!secp256k1_scalar_is_zero(&y)) { - secp256k1_scalar_inverse(&zz, &y); - secp256k1_scalar_inverse_var(&zzv, &y); - CHECK(secp256k1_scalar_eq(&zzv, &zz)); - secp256k1_scalar_mul(&z, &z, &zz); - CHECK(secp256k1_scalar_eq(&x, &z)); - secp256k1_scalar_mul(&zz, &zz, &y); - CHECK(secp256k1_scalar_eq(&secp256k1_scalar_one, &zz)); - } - secp256k1_scalar_mul(&z, &x, &x); - CHECK(secp256k1_scalar_eq(&r2, &z)); - } - } -} - -/***** FIELD TESTS *****/ - -static void random_fe_non_square(secp256k1_fe *ns) { - secp256k1_fe r; - testutil_random_fe_non_zero(ns); - if (secp256k1_fe_sqrt(&r, ns)) { - secp256k1_fe_negate(ns, ns, 1); - } -} - -static int fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe an = *a; - secp256k1_fe bn = *b; - secp256k1_fe_normalize_weak(&an); - return secp256k1_fe_equal(&an, &bn); -} - -static void run_field_convert(void) { - static const unsigned char b32[32] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40 - }; - static const secp256k1_fe_storage fes = SECP256K1_FE_STORAGE_CONST( - 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, - 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL - ); - static const secp256k1_fe fe = SECP256K1_FE_CONST( - 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, - 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL - ); - secp256k1_fe fe2; - unsigned char b322[32]; - secp256k1_fe_storage fes2; - /* Check conversions to fe. */ - CHECK(secp256k1_fe_set_b32_limit(&fe2, b32)); - CHECK(secp256k1_fe_equal(&fe, &fe2)); - secp256k1_fe_from_storage(&fe2, &fes); - CHECK(secp256k1_fe_equal(&fe, &fe2)); - /* Check conversion from fe. */ - secp256k1_fe_get_b32(b322, &fe); - CHECK(secp256k1_memcmp_var(b322, b32, 32) == 0); - secp256k1_fe_to_storage(&fes2, &fe); - CHECK(secp256k1_memcmp_var(&fes2, &fes, sizeof(fes)) == 0); -} - -static void run_field_be32_overflow(void) { - { - static const unsigned char zero_overflow[32] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, - }; - static const unsigned char zero[32] = { 0x00 }; - unsigned char out[32]; - secp256k1_fe fe; - CHECK(secp256k1_fe_set_b32_limit(&fe, zero_overflow) == 0); - secp256k1_fe_set_b32_mod(&fe, zero_overflow); - CHECK(secp256k1_fe_normalizes_to_zero(&fe) == 1); - secp256k1_fe_normalize(&fe); - CHECK(secp256k1_fe_is_zero(&fe) == 1); - secp256k1_fe_get_b32(out, &fe); - CHECK(secp256k1_memcmp_var(out, zero, 32) == 0); - } - { - static const unsigned char one_overflow[32] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30, - }; - static const unsigned char one[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - unsigned char out[32]; - secp256k1_fe fe; - CHECK(secp256k1_fe_set_b32_limit(&fe, one_overflow) == 0); - secp256k1_fe_set_b32_mod(&fe, one_overflow); - secp256k1_fe_normalize(&fe); - CHECK(secp256k1_fe_cmp_var(&fe, &secp256k1_fe_one) == 0); - secp256k1_fe_get_b32(out, &fe); - CHECK(secp256k1_memcmp_var(out, one, 32) == 0); - } - { - static const unsigned char ff_overflow[32] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - }; - static const unsigned char ff[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xD0, - }; - unsigned char out[32]; - secp256k1_fe fe; - const secp256k1_fe fe_ff = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0x01, 0x000003d0); - CHECK(secp256k1_fe_set_b32_limit(&fe, ff_overflow) == 0); - secp256k1_fe_set_b32_mod(&fe, ff_overflow); - secp256k1_fe_normalize(&fe); - CHECK(secp256k1_fe_cmp_var(&fe, &fe_ff) == 0); - secp256k1_fe_get_b32(out, &fe); - CHECK(secp256k1_memcmp_var(out, ff, 32) == 0); - } -} - -/* Returns true if two field elements have the same representation. */ -static int fe_identical(const secp256k1_fe *a, const secp256k1_fe *b) { - int ret = 1; - /* Compare the struct member that holds the limbs. */ - ret &= (secp256k1_memcmp_var(a->n, b->n, sizeof(a->n)) == 0); - return ret; -} - -static void run_field_half(void) { - secp256k1_fe t, u; - int m; - - /* Check magnitude 0 input */ - secp256k1_fe_get_bounds(&t, 0); - secp256k1_fe_half(&t); -#ifdef VERIFY - CHECK(t.magnitude == 1); - CHECK(t.normalized == 0); -#endif - CHECK(secp256k1_fe_normalizes_to_zero(&t)); - - /* Check non-zero magnitudes in the supported range */ - for (m = 1; m < 32; m++) { - /* Check max-value input */ - secp256k1_fe_get_bounds(&t, m); - - u = t; - secp256k1_fe_half(&u); -#ifdef VERIFY - CHECK(u.magnitude == (m >> 1) + 1); - CHECK(u.normalized == 0); -#endif - secp256k1_fe_normalize_weak(&u); - secp256k1_fe_add(&u, &u); - CHECK(fe_equal(&t, &u)); - - /* Check worst-case input: ensure the LSB is 1 so that P will be added, - * which will also cause all carries to be 1, since all limbs that can - * generate a carry are initially even and all limbs of P are odd in - * every existing field implementation. */ - secp256k1_fe_get_bounds(&t, m); - CHECK(t.n[0] > 0); - CHECK((t.n[0] & 1) == 0); - --t.n[0]; - - u = t; - secp256k1_fe_half(&u); -#ifdef VERIFY - CHECK(u.magnitude == (m >> 1) + 1); - CHECK(u.normalized == 0); -#endif - secp256k1_fe_normalize_weak(&u); - secp256k1_fe_add(&u, &u); - CHECK(fe_equal(&t, &u)); - } -} - -static void run_field_misc(void) { - secp256k1_fe x; - secp256k1_fe y; - secp256k1_fe z; - secp256k1_fe q; - int v; - secp256k1_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); - int i, j; - for (i = 0; i < 1000 * COUNT; i++) { - secp256k1_fe_storage xs, ys, zs; - if (i & 1) { - testutil_random_fe(&x); - } else { - testutil_random_fe_test(&x); - } - testutil_random_fe_non_zero(&y); - v = testrand_bits(15); - /* Test that fe_add_int is equivalent to fe_set_int + fe_add. */ - secp256k1_fe_set_int(&q, v); /* q = v */ - z = x; /* z = x */ - secp256k1_fe_add(&z, &q); /* z = x+v */ - q = x; /* q = x */ - secp256k1_fe_add_int(&q, v); /* q = x+v */ - CHECK(fe_equal(&q, &z)); - /* Test the fe equality and comparison operations. */ - CHECK(secp256k1_fe_cmp_var(&x, &x) == 0); - CHECK(secp256k1_fe_equal(&x, &x)); - z = x; - secp256k1_fe_add(&z,&y); - /* Test fe conditional move; z is not normalized here. */ - q = x; - secp256k1_fe_cmov(&x, &z, 0); -#ifdef VERIFY - CHECK(!x.normalized); - CHECK((x.magnitude == q.magnitude) || (x.magnitude == z.magnitude)); - CHECK((x.magnitude >= q.magnitude) && (x.magnitude >= z.magnitude)); -#endif - x = q; - secp256k1_fe_cmov(&x, &x, 1); - CHECK(!fe_identical(&x, &z)); - CHECK(fe_identical(&x, &q)); - secp256k1_fe_cmov(&q, &z, 1); -#ifdef VERIFY - CHECK(!q.normalized); - CHECK((q.magnitude == x.magnitude) || (q.magnitude == z.magnitude)); - CHECK((q.magnitude >= x.magnitude) && (q.magnitude >= z.magnitude)); -#endif - CHECK(fe_identical(&q, &z)); - q = z; - secp256k1_fe_normalize_var(&x); - secp256k1_fe_normalize_var(&z); - CHECK(!secp256k1_fe_equal(&x, &z)); - secp256k1_fe_normalize_var(&q); - secp256k1_fe_cmov(&q, &z, (i&1)); -#ifdef VERIFY - CHECK(q.normalized && q.magnitude == 1); -#endif - for (j = 0; j < 6; j++) { - secp256k1_fe_negate_unchecked(&z, &z, j+1); - secp256k1_fe_normalize_var(&q); - secp256k1_fe_cmov(&q, &z, (j&1)); -#ifdef VERIFY - CHECK(!q.normalized && q.magnitude == z.magnitude); -#endif - } - secp256k1_fe_normalize_var(&z); - /* Test storage conversion and conditional moves. */ - secp256k1_fe_to_storage(&xs, &x); - secp256k1_fe_to_storage(&ys, &y); - secp256k1_fe_to_storage(&zs, &z); - secp256k1_fe_storage_cmov(&zs, &xs, 0); - secp256k1_fe_storage_cmov(&zs, &zs, 1); - CHECK(secp256k1_memcmp_var(&xs, &zs, sizeof(xs)) != 0); - secp256k1_fe_storage_cmov(&ys, &xs, 1); - CHECK(secp256k1_memcmp_var(&xs, &ys, sizeof(xs)) == 0); - secp256k1_fe_from_storage(&x, &xs); - secp256k1_fe_from_storage(&y, &ys); - secp256k1_fe_from_storage(&z, &zs); - /* Test that mul_int, mul, and add agree. */ - secp256k1_fe_add(&y, &x); - secp256k1_fe_add(&y, &x); - z = x; - secp256k1_fe_mul_int(&z, 3); - CHECK(fe_equal(&y, &z)); - secp256k1_fe_add(&y, &x); - secp256k1_fe_add(&z, &x); - CHECK(fe_equal(&z, &y)); - z = x; - secp256k1_fe_mul_int(&z, 5); - secp256k1_fe_mul(&q, &x, &fe5); - CHECK(fe_equal(&z, &q)); - secp256k1_fe_negate(&x, &x, 1); - secp256k1_fe_add(&z, &x); - secp256k1_fe_add(&q, &x); - CHECK(fe_equal(&y, &z)); - CHECK(fe_equal(&q, &y)); - /* Check secp256k1_fe_half. */ - z = x; - secp256k1_fe_half(&z); - secp256k1_fe_add(&z, &z); - CHECK(fe_equal(&x, &z)); - secp256k1_fe_add(&z, &z); - secp256k1_fe_half(&z); - CHECK(fe_equal(&x, &z)); - } -} - -static void test_fe_mul(const secp256k1_fe* a, const secp256k1_fe* b, int use_sqr) -{ - secp256k1_fe c, an, bn; - /* Variables in BE 32-byte format. */ - unsigned char a32[32], b32[32], c32[32]; - /* Variables in LE 16x uint16_t format. */ - uint16_t a16[16], b16[16], c16[16]; - /* Field modulus in LE 16x uint16_t format. */ - static const uint16_t m16[16] = { - 0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - }; - uint16_t t16[32]; - int i; - - /* Compute C = A * B in fe format. */ - c = *a; - if (use_sqr) { - secp256k1_fe_sqr(&c, &c); - } else { - secp256k1_fe_mul(&c, &c, b); - } - - /* Convert A, B, C into LE 16x uint16_t format. */ - an = *a; - bn = *b; - secp256k1_fe_normalize_var(&c); - secp256k1_fe_normalize_var(&an); - secp256k1_fe_normalize_var(&bn); - secp256k1_fe_get_b32(a32, &an); - secp256k1_fe_get_b32(b32, &bn); - secp256k1_fe_get_b32(c32, &c); - for (i = 0; i < 16; ++i) { - a16[i] = a32[31 - 2*i] + ((uint16_t)a32[30 - 2*i] << 8); - b16[i] = b32[31 - 2*i] + ((uint16_t)b32[30 - 2*i] << 8); - c16[i] = c32[31 - 2*i] + ((uint16_t)c32[30 - 2*i] << 8); - } - /* Compute T = A * B in LE 16x uint16_t format. */ - mulmod256(t16, a16, b16, m16); - /* Compare */ - CHECK(secp256k1_memcmp_var(t16, c16, 32) == 0); -} - -static void run_fe_mul(void) { - int i; - for (i = 0; i < 100 * COUNT; ++i) { - secp256k1_fe a, b, c, d; - testutil_random_fe(&a); - testutil_random_fe_magnitude(&a, 8); - testutil_random_fe(&b); - testutil_random_fe_magnitude(&b, 8); - testutil_random_fe_test(&c); - testutil_random_fe_magnitude(&c, 8); - testutil_random_fe_test(&d); - testutil_random_fe_magnitude(&d, 8); - test_fe_mul(&a, &a, 1); - test_fe_mul(&c, &c, 1); - test_fe_mul(&a, &b, 0); - test_fe_mul(&a, &c, 0); - test_fe_mul(&c, &b, 0); - test_fe_mul(&c, &d, 0); - } -} - -static void run_sqr(void) { - int i; - secp256k1_fe x, y, lhs, rhs, tmp; - - secp256k1_fe_set_int(&x, 1); - secp256k1_fe_negate(&x, &x, 1); - - for (i = 1; i <= 512; ++i) { - secp256k1_fe_mul_int(&x, 2); - secp256k1_fe_normalize(&x); - - /* Check that (x+y)*(x-y) = x^2 - y*2 for some random values y */ - testutil_random_fe_test(&y); - - lhs = x; - secp256k1_fe_add(&lhs, &y); /* lhs = x+y */ - secp256k1_fe_negate(&tmp, &y, 1); /* tmp = -y */ - secp256k1_fe_add(&tmp, &x); /* tmp = x-y */ - secp256k1_fe_mul(&lhs, &lhs, &tmp); /* lhs = (x+y)*(x-y) */ - - secp256k1_fe_sqr(&rhs, &x); /* rhs = x^2 */ - secp256k1_fe_sqr(&tmp, &y); /* tmp = y^2 */ - secp256k1_fe_negate(&tmp, &tmp, 1); /* tmp = -y^2 */ - secp256k1_fe_add(&rhs, &tmp); /* rhs = x^2 - y^2 */ - - CHECK(fe_equal(&lhs, &rhs)); - } -} - -static void test_sqrt(const secp256k1_fe *a, const secp256k1_fe *k) { - secp256k1_fe r1, r2; - int v = secp256k1_fe_sqrt(&r1, a); - CHECK((v == 0) == (k == NULL)); - - if (k != NULL) { - /* Check that the returned root is +/- the given known answer */ - secp256k1_fe_negate(&r2, &r1, 1); - secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k); - secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2); - CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2)); - } -} - -static void run_sqrt(void) { - secp256k1_fe ns, x, s, t; - int i; - - /* Check sqrt(0) is 0 */ - secp256k1_fe_set_int(&x, 0); - secp256k1_fe_sqr(&s, &x); - test_sqrt(&s, &x); - - /* Check sqrt of small squares (and their negatives) */ - for (i = 1; i <= 100; i++) { - secp256k1_fe_set_int(&x, i); - secp256k1_fe_sqr(&s, &x); - test_sqrt(&s, &x); - secp256k1_fe_negate(&t, &s, 1); - test_sqrt(&t, NULL); - } - - /* Consistency checks for large random values */ - for (i = 0; i < 10; i++) { - int j; - random_fe_non_square(&ns); - for (j = 0; j < COUNT; j++) { - testutil_random_fe(&x); - secp256k1_fe_sqr(&s, &x); - CHECK(secp256k1_fe_is_square_var(&s)); - test_sqrt(&s, &x); - secp256k1_fe_negate(&t, &s, 1); - CHECK(!secp256k1_fe_is_square_var(&t)); - test_sqrt(&t, NULL); - secp256k1_fe_mul(&t, &s, &ns); - test_sqrt(&t, NULL); - } - } -} - -/***** FIELD/SCALAR INVERSE TESTS *****/ - -static const secp256k1_scalar scalar_minus_one = SECP256K1_SCALAR_CONST( - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, - 0xBAAEDCE6, 0xAF48A03B, 0xBFD25E8C, 0xD0364140 -); - -static const secp256k1_fe fe_minus_one = SECP256K1_FE_CONST( - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFC2E -); - -/* These tests test the following identities: - * - * for x==0: 1/x == 0 - * for x!=0: x*(1/x) == 1 - * for x!=0 and x!=1: 1/(1/x - 1) + 1 == -1/(x-1) - */ - -static void test_inverse_scalar(secp256k1_scalar* out, const secp256k1_scalar* x, int var) -{ - secp256k1_scalar l, r, t; - - (var ? secp256k1_scalar_inverse_var : secp256k1_scalar_inverse)(&l, x); /* l = 1/x */ - if (out) *out = l; - if (secp256k1_scalar_is_zero(x)) { - CHECK(secp256k1_scalar_is_zero(&l)); - return; - } - secp256k1_scalar_mul(&t, x, &l); /* t = x*(1/x) */ - CHECK(secp256k1_scalar_is_one(&t)); /* x*(1/x) == 1 */ - secp256k1_scalar_add(&r, x, &scalar_minus_one); /* r = x-1 */ - if (secp256k1_scalar_is_zero(&r)) return; - (var ? secp256k1_scalar_inverse_var : secp256k1_scalar_inverse)(&r, &r); /* r = 1/(x-1) */ - secp256k1_scalar_add(&l, &scalar_minus_one, &l); /* l = 1/x-1 */ - (var ? secp256k1_scalar_inverse_var : secp256k1_scalar_inverse)(&l, &l); /* l = 1/(1/x-1) */ - secp256k1_scalar_add(&l, &l, &secp256k1_scalar_one); /* l = 1/(1/x-1)+1 */ - secp256k1_scalar_add(&l, &r, &l); /* l = 1/(1/x-1)+1 + 1/(x-1) */ - CHECK(secp256k1_scalar_is_zero(&l)); /* l == 0 */ -} - -static void test_inverse_field(secp256k1_fe* out, const secp256k1_fe* x, int var) -{ - secp256k1_fe l, r, t; - - (var ? secp256k1_fe_inv_var : secp256k1_fe_inv)(&l, x) ; /* l = 1/x */ - if (out) *out = l; - t = *x; /* t = x */ - if (secp256k1_fe_normalizes_to_zero_var(&t)) { - CHECK(secp256k1_fe_normalizes_to_zero(&l)); - return; - } - secp256k1_fe_mul(&t, x, &l); /* t = x*(1/x) */ - secp256k1_fe_add(&t, &fe_minus_one); /* t = x*(1/x)-1 */ - CHECK(secp256k1_fe_normalizes_to_zero(&t)); /* x*(1/x)-1 == 0 */ - r = *x; /* r = x */ - secp256k1_fe_add(&r, &fe_minus_one); /* r = x-1 */ - if (secp256k1_fe_normalizes_to_zero_var(&r)) return; - (var ? secp256k1_fe_inv_var : secp256k1_fe_inv)(&r, &r); /* r = 1/(x-1) */ - secp256k1_fe_add(&l, &fe_minus_one); /* l = 1/x-1 */ - (var ? secp256k1_fe_inv_var : secp256k1_fe_inv)(&l, &l); /* l = 1/(1/x-1) */ - secp256k1_fe_add_int(&l, 1); /* l = 1/(1/x-1)+1 */ - secp256k1_fe_add(&l, &r); /* l = 1/(1/x-1)+1 + 1/(x-1) */ - CHECK(secp256k1_fe_normalizes_to_zero_var(&l)); /* l == 0 */ -} - -static void run_inverse_tests(void) -{ - /* Fixed test cases for field inverses: pairs of (x, 1/x) mod p. */ - static const secp256k1_fe fe_cases[][2] = { - /* 0 */ - {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), - SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}, - /* 1 */ - {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), - SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1)}, - /* -1 */ - {SECP256K1_FE_CONST(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, 0xfffffc2e), - SECP256K1_FE_CONST(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, 0xfffffc2e)}, - /* 2 */ - {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2), - SECP256K1_FE_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x7ffffe18)}, - /* 2**128 */ - {SECP256K1_FE_CONST(0, 0, 0, 1, 0, 0, 0, 0), - SECP256K1_FE_CONST(0xbcb223fe, 0xdc24a059, 0xd838091d, 0xd2253530, 0xffffffff, 0xffffffff, 0xffffffff, 0x434dd931)}, - /* Input known to need 637 divsteps */ - {SECP256K1_FE_CONST(0xe34e9c95, 0x6bee8a84, 0x0dcb632a, 0xdb8a1320, 0x66885408, 0x06f3f996, 0x7c11ca84, 0x19199ec3), - SECP256K1_FE_CONST(0xbd2cbd8f, 0x1c536828, 0x9bccda44, 0x2582ac0c, 0x870152b0, 0x8a3f09fb, 0x1aaadf92, 0x19b618e5)}, - /* Input known to need 567 divsteps starting with delta=1/2. */ - {SECP256K1_FE_CONST(0xf6bc3ba3, 0x636451c4, 0x3e46357d, 0x2c21d619, 0x0988e234, 0x15985661, 0x6672982b, 0xa7549bfc), - SECP256K1_FE_CONST(0xb024fdc7, 0x5547451e, 0x426c585f, 0xbd481425, 0x73df6b75, 0xeef6d9d0, 0x389d87d4, 0xfbb440ba)}, - /* Input known to need 566 divsteps starting with delta=1/2. */ - {SECP256K1_FE_CONST(0xb595d81b, 0x2e3c1e2f, 0x482dbc65, 0xe4865af7, 0x9a0a50aa, 0x29f9e618, 0x6f87d7a5, 0x8d1063ae), - SECP256K1_FE_CONST(0xc983337c, 0x5d5c74e1, 0x49918330, 0x0b53afb5, 0xa0428a0b, 0xce6eef86, 0x059bd8ef, 0xe5b908de)}, - /* Set of 10 inputs accessing all 128 entries in the modinv32 divsteps_var table */ - {SECP256K1_FE_CONST(0x00000000, 0x00000000, 0xe0ff1f80, 0x1f000000, 0x00000000, 0x00000000, 0xfeff0100, 0x00000000), - SECP256K1_FE_CONST(0x9faf9316, 0x77e5049d, 0x0b5e7a1b, 0xef70b893, 0x18c9e30c, 0x045e7fd7, 0x29eddf8c, 0xd62e9e3d)}, - {SECP256K1_FE_CONST(0x621a538d, 0x511b2780, 0x35688252, 0x53f889a4, 0x6317c3ac, 0x32ba0a46, 0x6277c0d1, 0xccd31192), - SECP256K1_FE_CONST(0x38513b0c, 0x5eba856f, 0xe29e882e, 0x9b394d8c, 0x34bda011, 0xeaa66943, 0x6a841a4c, 0x6ae8bcff)}, - {SECP256K1_FE_CONST(0x00000200, 0xf0ffff1f, 0x00000000, 0x0000e0ff, 0xffffffff, 0xfffcffff, 0xffffffff, 0xffff0100), - SECP256K1_FE_CONST(0x5da42a52, 0x3640de9e, 0x13e64343, 0x0c7591b7, 0x6c1e3519, 0xf048c5b6, 0x0484217c, 0xedbf8b2f)}, - {SECP256K1_FE_CONST(0xd1343ef9, 0x4b952621, 0x7c52a2ee, 0x4ea1281b, 0x4ab46410, 0x9f26998d, 0xa686a8ff, 0x9f2103e8), - SECP256K1_FE_CONST(0x84044385, 0x9a4619bf, 0x74e35b6d, 0xa47e0c46, 0x6b7fb47d, 0x9ffab128, 0xb0775aa3, 0xcb318bd1)}, - {SECP256K1_FE_CONST(0xb27235d2, 0xc56a52be, 0x210db37a, 0xd50d23a4, 0xbe621bdd, 0x5df22c6a, 0xe926ba62, 0xd2e4e440), - SECP256K1_FE_CONST(0x67a26e54, 0x483a9d3c, 0xa568469e, 0xd258ab3d, 0xb9ec9981, 0xdca9b1bd, 0x8d2775fe, 0x53ae429b)}, - {SECP256K1_FE_CONST(0x00000000, 0x00000000, 0x00e0ffff, 0xffffff83, 0xffffffff, 0x3f00f00f, 0x000000e0, 0xffffffff), - SECP256K1_FE_CONST(0x310e10f8, 0x23bbfab0, 0xac94907d, 0x076c9a45, 0x8d357d7f, 0xc763bcee, 0x00d0e615, 0x5a6acef6)}, - {SECP256K1_FE_CONST(0xfeff0300, 0x001c0000, 0xf80700c0, 0x0ff0ffff, 0xffffffff, 0x0fffffff, 0xffff0100, 0x7f0000fe), - SECP256K1_FE_CONST(0x28e2fdb4, 0x0709168b, 0x86f598b0, 0x3453a370, 0x530cf21f, 0x32f978d5, 0x1d527a71, 0x59269b0c)}, - {SECP256K1_FE_CONST(0xc2591afa, 0x7bb98ef7, 0x090bb273, 0x85c14f87, 0xbb0b28e0, 0x54d3c453, 0x85c66753, 0xd5574d2f), - SECP256K1_FE_CONST(0xfdca70a2, 0x70ce627c, 0x95e66fae, 0x848a6dbb, 0x07ffb15c, 0x5f63a058, 0xba4140ed, 0x6113b503)}, - {SECP256K1_FE_CONST(0xf5475db3, 0xedc7b5a3, 0x411c047e, 0xeaeb452f, 0xc625828e, 0x1cf5ad27, 0x8eec1060, 0xc7d3e690), - SECP256K1_FE_CONST(0x5eb756c0, 0xf963f4b9, 0xdc6a215e, 0xec8cc2d8, 0x2e9dec01, 0xde5eb88d, 0x6aba7164, 0xaecb2c5a)}, - {SECP256K1_FE_CONST(0x00000000, 0x00f8ffff, 0xffffffff, 0x01000000, 0xe0ff1f00, 0x00000000, 0xffffff7f, 0x00000000), - SECP256K1_FE_CONST(0xe0d2e3d8, 0x49b6157d, 0xe54e88c2, 0x1a7f02ca, 0x7dd28167, 0xf1125d81, 0x7bfa444e, 0xbe110037)}, - /* Selection of randomly generated inputs that reach high/low d/e values in various configurations. */ - {SECP256K1_FE_CONST(0x13cc08a4, 0xd8c41f0f, 0x179c3e67, 0x54c46c67, 0xc4109221, 0x09ab3b13, 0xe24d9be1, 0xffffe950), - SECP256K1_FE_CONST(0xb80c8006, 0xd16abaa7, 0xcabd71e5, 0xcf6714f4, 0x966dd3d0, 0x64767a2d, 0xe92c4441, 0x51008cd1)}, - {SECP256K1_FE_CONST(0xaa6db990, 0x95efbca1, 0x3cc6ff71, 0x0602e24a, 0xf49ff938, 0x99fffc16, 0x46f40993, 0xc6e72057), - SECP256K1_FE_CONST(0xd5d3dd69, 0xb0c195e5, 0x285f1d49, 0xe639e48c, 0x9223f8a9, 0xca1d731d, 0x9ca482f9, 0xa5b93e06)}, - {SECP256K1_FE_CONST(0x1c680eac, 0xaeabffd8, 0x9bdc4aee, 0x1781e3de, 0xa3b08108, 0x0015f2e0, 0x94449e1b, 0x2f67a058), - SECP256K1_FE_CONST(0x7f083f8d, 0x31254f29, 0x6510f475, 0x245c373d, 0xc5622590, 0x4b323393, 0x32ed1719, 0xc127444b)}, - {SECP256K1_FE_CONST(0x147d44b3, 0x012d83f8, 0xc160d386, 0x1a44a870, 0x9ba6be96, 0x8b962707, 0x267cbc1a, 0xb65b2f0a), - SECP256K1_FE_CONST(0x555554ff, 0x170aef1e, 0x50a43002, 0xe51fbd36, 0xafadb458, 0x7a8aded1, 0x0ca6cd33, 0x6ed9087c)}, - {SECP256K1_FE_CONST(0x12423796, 0x22f0fe61, 0xf9ca017c, 0x5384d107, 0xa1fbf3b2, 0x3b018013, 0x916a3c37, 0x4000b98c), - SECP256K1_FE_CONST(0x20257700, 0x08668f94, 0x1177e306, 0x136c01f5, 0x8ed1fbd2, 0x95ec4589, 0xae38edb9, 0xfd19b6d7)}, - {SECP256K1_FE_CONST(0xdcf2d030, 0x9ab42cb4, 0x93ffa181, 0xdcd23619, 0x39699b52, 0x08909a20, 0xb5a17695, 0x3a9dcf21), - SECP256K1_FE_CONST(0x1f701dea, 0xe211fb1f, 0x4f37180d, 0x63a0f51c, 0x29fe1e40, 0xa40b6142, 0x2e7b12eb, 0x982b06b6)}, - {SECP256K1_FE_CONST(0x79a851f6, 0xa6314ed3, 0xb35a55e6, 0xca1c7d7f, 0xe32369ea, 0xf902432e, 0x375308c5, 0xdfd5b600), - SECP256K1_FE_CONST(0xcaae00c5, 0xe6b43851, 0x9dabb737, 0x38cba42c, 0xa02c8549, 0x7895dcbf, 0xbd183d71, 0xafe4476a)}, - {SECP256K1_FE_CONST(0xede78fdd, 0xcfc92bf1, 0x4fec6c6c, 0xdb8d37e2, 0xfb66bc7b, 0x28701870, 0x7fa27c9a, 0x307196ec), - SECP256K1_FE_CONST(0x68193a6c, 0x9a8b87a7, 0x2a760c64, 0x13e473f6, 0x23ae7bed, 0x1de05422, 0x88865427, 0xa3418265)}, - {SECP256K1_FE_CONST(0xa40b2079, 0xb8f88e89, 0xa7617997, 0x89baf5ae, 0x174df343, 0x75138eae, 0x2711595d, 0x3fc3e66c), - SECP256K1_FE_CONST(0x9f99c6a5, 0x6d685267, 0xd4b87c37, 0x9d9c4576, 0x358c692b, 0x6bbae0ed, 0x3389c93d, 0x7fdd2655)}, - {SECP256K1_FE_CONST(0x7c74c6b6, 0xe98d9151, 0x72645cf1, 0x7f06e321, 0xcefee074, 0x15b2113a, 0x10a9be07, 0x08a45696), - SECP256K1_FE_CONST(0x8c919a88, 0x898bc1e0, 0x77f26f97, 0x12e655b7, 0x9ba0ac40, 0xe15bb19e, 0x8364cc3b, 0xe227a8ee)}, - {SECP256K1_FE_CONST(0x109ba1ce, 0xdafa6d4a, 0xa1cec2b2, 0xeb1069f4, 0xb7a79e5b, 0xec6eb99b, 0xaec5f643, 0xee0e723e), - SECP256K1_FE_CONST(0x93d13eb8, 0x4bb0bcf9, 0xe64f5a71, 0xdbe9f359, 0x7191401c, 0x6f057a4a, 0xa407fe1b, 0x7ecb65cc)}, - {SECP256K1_FE_CONST(0x3db076cd, 0xec74a5c9, 0xf61dd138, 0x90e23e06, 0xeeedd2d0, 0x74cbc4e0, 0x3dbe1e91, 0xded36a78), - SECP256K1_FE_CONST(0x3f07f966, 0x8e2a1e09, 0x706c71df, 0x02b5e9d5, 0xcb92ddbf, 0xcdd53010, 0x16545564, 0xe660b107)}, - {SECP256K1_FE_CONST(0xe31c73ed, 0xb4c4b82c, 0x02ae35f7, 0x4cdec153, 0x98b522fd, 0xf7d2460c, 0x6bf7c0f8, 0x4cf67b0d), - SECP256K1_FE_CONST(0x4b8f1faf, 0x94e8b070, 0x19af0ff6, 0xa319cd31, 0xdf0a7ffb, 0xefaba629, 0x59c50666, 0x1fe5b843)}, - {SECP256K1_FE_CONST(0x4c8b0e6e, 0x83392ab6, 0xc0e3e9f1, 0xbbd85497, 0x16698897, 0xf552d50d, 0x79652ddb, 0x12f99870), - SECP256K1_FE_CONST(0x56d5101f, 0xd23b7949, 0x17dc38d6, 0xf24022ef, 0xcf18e70a, 0x5cc34424, 0x438544c3, 0x62da4bca)}, - {SECP256K1_FE_CONST(0xb0e040e2, 0x40cc35da, 0x7dd5c611, 0x7fccb178, 0x28888137, 0xbc930358, 0xea2cbc90, 0x775417dc), - SECP256K1_FE_CONST(0xca37f0d4, 0x016dd7c8, 0xab3ae576, 0x96e08d69, 0x68ed9155, 0xa9b44270, 0x900ae35d, 0x7c7800cd)}, - {SECP256K1_FE_CONST(0x8a32ea49, 0x7fbb0bae, 0x69724a9d, 0x8e2105b2, 0xbdf69178, 0x862577ef, 0x35055590, 0x667ddaef), - SECP256K1_FE_CONST(0xd02d7ead, 0xc5e190f0, 0x559c9d72, 0xdaef1ffc, 0x64f9f425, 0xf43645ea, 0x7341e08d, 0x11768e96)}, - {SECP256K1_FE_CONST(0xa3592d98, 0x9abe289d, 0x579ebea6, 0xbb0857a8, 0xe242ab73, 0x85f9a2ce, 0xb6998f0f, 0xbfffbfc6), - SECP256K1_FE_CONST(0x093c1533, 0x32032efa, 0x6aa46070, 0x0039599e, 0x589c35f4, 0xff525430, 0x7fe3777a, 0x44b43ddc)}, - {SECP256K1_FE_CONST(0x647178a3, 0x229e607b, 0xcc98521a, 0xcce3fdd9, 0x1e1bc9c9, 0x97fb7c6a, 0x61b961e0, 0x99b10709), - SECP256K1_FE_CONST(0x98217c13, 0xd51ddf78, 0x96310e77, 0xdaebd908, 0x602ca683, 0xcb46d07a, 0xa1fcf17e, 0xc8e2feb3)}, - {SECP256K1_FE_CONST(0x7334627c, 0x73f98968, 0x99464b4b, 0xf5964958, 0x1b95870d, 0xc658227e, 0x5e3235d8, 0xdcab5787), - SECP256K1_FE_CONST(0x000006fd, 0xc7e9dd94, 0x40ae367a, 0xe51d495c, 0x07603b9b, 0x2d088418, 0x6cc5c74c, 0x98514307)}, - {SECP256K1_FE_CONST(0x82e83876, 0x96c28938, 0xa50dd1c5, 0x605c3ad1, 0xc048637d, 0x7a50825f, 0x335ed01a, 0x00005760), - SECP256K1_FE_CONST(0xb0393f9f, 0x9f2aa55e, 0xf5607e2e, 0x5287d961, 0x60b3e704, 0xf3e16e80, 0xb4f9a3ea, 0xfec7f02d)}, - {SECP256K1_FE_CONST(0xc97b6cec, 0x3ee6b8dc, 0x98d24b58, 0x3c1970a1, 0xfe06297a, 0xae813529, 0xe76bb6bd, 0x771ae51d), - SECP256K1_FE_CONST(0x0507c702, 0xd407d097, 0x47ddeb06, 0xf6625419, 0x79f48f79, 0x7bf80d0b, 0xfc34b364, 0x253a5db1)}, - {SECP256K1_FE_CONST(0xd559af63, 0x77ea9bc4, 0x3cf1ad14, 0x5c7a4bbb, 0x10e7d18b, 0x7ce0dfac, 0x380bb19d, 0x0bb99bd3), - SECP256K1_FE_CONST(0x00196119, 0xb9b00d92, 0x34edfdb5, 0xbbdc42fc, 0xd2daa33a, 0x163356ca, 0xaa8754c8, 0xb0ec8b0b)}, - {SECP256K1_FE_CONST(0x8ddfa3dc, 0x52918da0, 0x640519dc, 0x0af8512a, 0xca2d33b2, 0xbde52514, 0xda9c0afc, 0xcb29fce4), - SECP256K1_FE_CONST(0xb3e4878d, 0x5cb69148, 0xcd54388b, 0xc23acce0, 0x62518ba8, 0xf09def92, 0x7b31e6aa, 0x6ba35b02)}, - {SECP256K1_FE_CONST(0xf8207492, 0xe3049f0a, 0x65285f2b, 0x0bfff996, 0x00ca112e, 0xc05da837, 0x546d41f9, 0x5194fb91), - SECP256K1_FE_CONST(0x7b7ee50b, 0xa8ed4bbd, 0xf6469930, 0x81419a5c, 0x071441c7, 0x290d046e, 0x3b82ea41, 0x611c5f95)}, - {SECP256K1_FE_CONST(0x050f7c80, 0x5bcd3c6b, 0x823cb724, 0x5ce74db7, 0xa4e39f5c, 0xbd8828d7, 0xfd4d3e07, 0x3ec2926a), - SECP256K1_FE_CONST(0x000d6730, 0xb0171314, 0x4764053d, 0xee157117, 0x48fd61da, 0xdea0b9db, 0x1d5e91c6, 0xbdc3f59e)}, - {SECP256K1_FE_CONST(0x3e3ea8eb, 0x05d760cf, 0x23009263, 0xb3cb3ac9, 0x088f6f0d, 0x3fc182a3, 0xbd57087c, 0xe67c62f9), - SECP256K1_FE_CONST(0xbe988716, 0xa29c1bf6, 0x4456aed6, 0xab1e4720, 0x49929305, 0x51043bf4, 0xebd833dd, 0xdd511e8b)}, - {SECP256K1_FE_CONST(0x6964d2a9, 0xa7fa6501, 0xa5959249, 0x142f4029, 0xea0c1b5f, 0x2f487ef6, 0x301ac80a, 0x768be5cd), - SECP256K1_FE_CONST(0x3918ffe4, 0x07492543, 0xed24d0b7, 0x3df95f8f, 0xaffd7cb4, 0x0de2191c, 0x9ec2f2ad, 0x2c0cb3c6)}, - {SECP256K1_FE_CONST(0x37c93520, 0xf6ddca57, 0x2b42fd5e, 0xb5c7e4de, 0x11b5b81c, 0xb95e91f3, 0x95c4d156, 0x39877ccb), - SECP256K1_FE_CONST(0x9a94b9b5, 0x57eb71ee, 0x4c975b8b, 0xac5262a8, 0x077b0595, 0xe12a6b1f, 0xd728edef, 0x1a6bf956)} - }; - /* Fixed test cases for scalar inverses: pairs of (x, 1/x) mod n. */ - static const secp256k1_scalar scalar_cases[][2] = { - /* 0 */ - {SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0), - SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0)}, - /* 1 */ - {SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1), - SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1)}, - /* -1 */ - {SECP256K1_SCALAR_CONST(0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, 0xbaaedce6, 0xaf48a03b, 0xbfd25e8c, 0xd0364140), - SECP256K1_SCALAR_CONST(0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, 0xbaaedce6, 0xaf48a03b, 0xbfd25e8c, 0xd0364140)}, - /* 2 */ - {SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 2), - SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x5d576e73, 0x57a4501d, 0xdfe92f46, 0x681b20a1)}, - /* 2**128 */ - {SECP256K1_SCALAR_CONST(0, 0, 0, 1, 0, 0, 0, 0), - SECP256K1_SCALAR_CONST(0x50a51ac8, 0x34b9ec24, 0x4b0dff66, 0x5588b13e, 0x9984d5b3, 0xcf80ef0f, 0xd6a23766, 0xa3ee9f22)}, - /* Input known to need 635 divsteps */ - {SECP256K1_SCALAR_CONST(0xcb9f1d35, 0xdd4416c2, 0xcd71bf3f, 0x6365da66, 0x3c9b3376, 0x8feb7ae9, 0x32a5ef60, 0x19199ec3), - SECP256K1_SCALAR_CONST(0x1d7c7bba, 0xf1893d53, 0xb834bd09, 0x36b411dc, 0x42c2e42f, 0xec72c428, 0x5e189791, 0x8e9bc708)}, - /* Input known to need 566 divsteps starting with delta=1/2. */ - {SECP256K1_SCALAR_CONST(0x7e3c993d, 0xa4272488, 0xbc015b49, 0x2db54174, 0xd382083a, 0xebe6db35, 0x80f82eff, 0xcd132c72), - SECP256K1_SCALAR_CONST(0x086f34a0, 0x3e631f76, 0x77418f28, 0xcc84ac95, 0x6304439d, 0x365db268, 0x312c6ded, 0xd0b934f8)}, - /* Input known to need 565 divsteps starting with delta=1/2. */ - {SECP256K1_SCALAR_CONST(0xbad7e587, 0x3f307859, 0x60d93147, 0x8a18491e, 0xb38a9fd5, 0x254350d3, 0x4b1f0e4b, 0x7dd6edc4), - SECP256K1_SCALAR_CONST(0x89f2df26, 0x39e2b041, 0xf19bd876, 0xd039c8ac, 0xc2223add, 0x29c4943e, 0x6632d908, 0x515f467b)}, - /* Selection of randomly generated inputs that reach low/high d/e values in various configurations. */ - {SECP256K1_SCALAR_CONST(0x1950d757, 0xb37a5809, 0x435059bb, 0x0bb8997e, 0x07e1e3c8, 0x5e5d7d2c, 0x6a0ed8e3, 0xdbde180e), - SECP256K1_SCALAR_CONST(0xbf72af9b, 0x750309e2, 0x8dda230b, 0xfe432b93, 0x7e25e475, 0x4388251e, 0x633d894b, 0x3bcb6f8c)}, - {SECP256K1_SCALAR_CONST(0x9bccf4e7, 0xc5a515e3, 0x50637aa9, 0xbb65a13f, 0x391749a1, 0x62de7d4e, 0xf6d7eabb, 0x3cd10ce0), - SECP256K1_SCALAR_CONST(0xaf2d5623, 0xb6385a33, 0xcd0365be, 0x5e92a70d, 0x7f09179c, 0x3baaf30f, 0x8f9cc83b, 0x20092f67)}, - {SECP256K1_SCALAR_CONST(0x73a57111, 0xb242952a, 0x5c5dee59, 0xf3be2ace, 0xa30a7659, 0xa46e5f47, 0xd21267b1, 0x39e642c9), - SECP256K1_SCALAR_CONST(0xa711df07, 0xcbcf13ef, 0xd61cc6be, 0xbcd058ce, 0xb02cf157, 0x272d4a18, 0x86d0feb3, 0xcd5fa004)}, - {SECP256K1_SCALAR_CONST(0x04884963, 0xce0580b1, 0xba547030, 0x3c691db3, 0x9cd2c84f, 0x24c7cebd, 0x97ebfdba, 0x3e785ec2), - SECP256K1_SCALAR_CONST(0xaaaaaf14, 0xd7c99ba7, 0x517ce2c1, 0x78a28b4c, 0x3769a851, 0xe5c5a03d, 0x4cc28f33, 0x0ec4dc5d)}, - {SECP256K1_SCALAR_CONST(0x1679ed49, 0x21f537b1, 0x815cb8ae, 0x9efc511c, 0x5b9fa037, 0x0b0f275e, 0x6c985281, 0x6c4a9905), - SECP256K1_SCALAR_CONST(0xb14ac3d5, 0x62b52999, 0xef34ead1, 0xffca4998, 0x0294341a, 0x1f8172aa, 0xea1624f9, 0x302eea62)}, - {SECP256K1_SCALAR_CONST(0x626b37c0, 0xf0057c35, 0xee982f83, 0x452a1fd3, 0xea826506, 0x48b08a9d, 0x1d2c4799, 0x4ad5f6ec), - SECP256K1_SCALAR_CONST(0xe38643b7, 0x567bfc2f, 0x5d2f1c15, 0xe327239c, 0x07112443, 0x69509283, 0xfd98e77a, 0xdb71c1e8)}, - {SECP256K1_SCALAR_CONST(0x1850a3a7, 0x759efc56, 0x54f287b2, 0x14d1234b, 0xe263bbc9, 0xcf4d8927, 0xd5f85f27, 0x965bd816), - SECP256K1_SCALAR_CONST(0x3b071831, 0xcac9619a, 0xcceb0596, 0xf614d63b, 0x95d0db2f, 0xc6a00901, 0x8eaa2621, 0xabfa0009)}, - {SECP256K1_SCALAR_CONST(0x94ae5d06, 0xa27dc400, 0x487d72be, 0xaa51ebed, 0xe475b5c0, 0xea675ffc, 0xf4df627a, 0xdca4222f), - SECP256K1_SCALAR_CONST(0x01b412ed, 0xd7830956, 0x1532537e, 0xe5e3dc99, 0x8fd3930a, 0x54f8d067, 0x32ef5760, 0x594438a5)}, - {SECP256K1_SCALAR_CONST(0x1f24278a, 0xb5bfe374, 0xa328dbbc, 0xebe35f48, 0x6620e009, 0xd58bb1b4, 0xb5a6bf84, 0x8815f63a), - SECP256K1_SCALAR_CONST(0xfe928416, 0xca5ba2d3, 0xfde513da, 0x903a60c7, 0x9e58ad8a, 0x8783bee4, 0x083a3843, 0xa608c914)}, - {SECP256K1_SCALAR_CONST(0xdc107d58, 0x274f6330, 0x67dba8bc, 0x26093111, 0x5201dfb8, 0x968ce3f5, 0xf34d1bd4, 0xf2146504), - SECP256K1_SCALAR_CONST(0x660cfa90, 0x13c3d93e, 0x7023b1e5, 0xedd09e71, 0x6d9c9d10, 0x7a3d2cdb, 0xdd08edc3, 0xaa78fcfb)}, - {SECP256K1_SCALAR_CONST(0x7cd1e905, 0xc6f02776, 0x2f551cc7, 0x5da61cff, 0x7da05389, 0x1119d5a4, 0x631c7442, 0x894fd4f7), - SECP256K1_SCALAR_CONST(0xff20862a, 0x9d3b1a37, 0x1628803b, 0x3004ccae, 0xaa23282a, 0xa89a1109, 0xd94ece5e, 0x181bdc46)}, - {SECP256K1_SCALAR_CONST(0x5b9dade8, 0x23d26c58, 0xcd12d818, 0x25b8ae97, 0x3dea04af, 0xf482c96b, 0xa062f254, 0x9e453640), - SECP256K1_SCALAR_CONST(0x50c38800, 0x15fa53f4, 0xbe1e5392, 0x5c9b120a, 0x262c22c7, 0x18fa0816, 0x5f2baab4, 0x8cb5db46)}, - {SECP256K1_SCALAR_CONST(0x11cdaeda, 0x969c464b, 0xef1f4ab0, 0x5b01d22e, 0x656fd098, 0x882bea84, 0x65cdbe7a, 0x0c19ff03), - SECP256K1_SCALAR_CONST(0x1968d0fa, 0xac46f103, 0xb55f1f72, 0xb3820bed, 0xec6b359a, 0x4b1ae0ad, 0x7e38e1fb, 0x295ccdfb)}, - {SECP256K1_SCALAR_CONST(0x2c351aa1, 0x26e91589, 0x194f8a1e, 0x06561f66, 0x0cb97b7f, 0x10914454, 0x134d1c03, 0x157266b4), - SECP256K1_SCALAR_CONST(0xbe49ada6, 0x92bd8711, 0x41b176c4, 0xa478ba95, 0x14883434, 0x9d1cd6f3, 0xcc4b847d, 0x22af80f5)}, - {SECP256K1_SCALAR_CONST(0x6ba07c6e, 0x13a60edb, 0x6247f5c3, 0x84b5fa56, 0x76fe3ec5, 0x80426395, 0xf65ec2ae, 0x623ba730), - SECP256K1_SCALAR_CONST(0x25ac23f7, 0x418cd747, 0x98376f9d, 0x4a11c7bf, 0x24c8ebfe, 0x4c8a8655, 0x345f4f52, 0x1c515595)}, - {SECP256K1_SCALAR_CONST(0x9397a712, 0x8abb6951, 0x2d4a3d54, 0x703b1c2a, 0x0661dca8, 0xd75c9b31, 0xaed4d24b, 0xd2ab2948), - SECP256K1_SCALAR_CONST(0xc52e8bef, 0xd55ce3eb, 0x1c897739, 0xeb9fb606, 0x36b9cd57, 0x18c51cc2, 0x6a87489e, 0xffd0dcf3)}, - {SECP256K1_SCALAR_CONST(0xe6a808cc, 0xeb437888, 0xe97798df, 0x4e224e44, 0x7e3b380a, 0x207c1653, 0x889f3212, 0xc6738b6f), - SECP256K1_SCALAR_CONST(0x31f9ae13, 0xd1e08b20, 0x757a2e5e, 0x5243a0eb, 0x8ae35f73, 0x19bb6122, 0xb910f26b, 0xda70aa55)}, - {SECP256K1_SCALAR_CONST(0xd0320548, 0xab0effe7, 0xa70779e0, 0x61a347a6, 0xb8c1e010, 0x9d5281f8, 0x2ee588a6, 0x80000000), - SECP256K1_SCALAR_CONST(0x1541897e, 0x78195c90, 0x7583dd9e, 0x728b6100, 0xbce8bc6d, 0x7a53b471, 0x5dcd9e45, 0x4425fcaf)}, - {SECP256K1_SCALAR_CONST(0x93d623f1, 0xd45b50b0, 0x796e9186, 0x9eac9407, 0xd30edc20, 0xef6304cf, 0x250494e7, 0xba503de9), - SECP256K1_SCALAR_CONST(0x7026d638, 0x1178b548, 0x92043952, 0x3c7fb47c, 0xcd3ea236, 0x31d82b01, 0x612fc387, 0x80b9b957)}, - {SECP256K1_SCALAR_CONST(0xf860ab39, 0x55f5d412, 0xa4d73bcc, 0x3b48bd90, 0xc248ffd3, 0x13ca10be, 0x8fba84cc, 0xdd28d6a3), - SECP256K1_SCALAR_CONST(0x5c32fc70, 0xe0b15d67, 0x76694700, 0xfe62be4d, 0xeacdb229, 0x7a4433d9, 0x52155cd0, 0x7649ab59)}, - {SECP256K1_SCALAR_CONST(0x4e41311c, 0x0800af58, 0x7a690a8e, 0xe175c9ba, 0x6981ab73, 0xac532ea8, 0x5c1f5e63, 0x6ac1f189), - SECP256K1_SCALAR_CONST(0xfffffff9, 0xd075982c, 0x7fbd3825, 0xc05038a2, 0x4533b91f, 0x94ec5f45, 0xb280b28f, 0x842324dc)}, - {SECP256K1_SCALAR_CONST(0x48e473bf, 0x3555eade, 0xad5d7089, 0x2424c4e4, 0x0a99397c, 0x2dc796d8, 0xb7a43a69, 0xd0364141), - SECP256K1_SCALAR_CONST(0x634976b2, 0xa0e47895, 0x1ec38593, 0x266d6fd0, 0x6f602644, 0x9bb762f1, 0x7180c704, 0xe23a4daa)}, - {SECP256K1_SCALAR_CONST(0xbe83878d, 0x3292fc54, 0x26e71c62, 0x556ccedc, 0x7cbb8810, 0x4032a720, 0x34ead589, 0xe4d6bd13), - SECP256K1_SCALAR_CONST(0x6cd150ad, 0x25e59d0f, 0x74cbae3d, 0x6377534a, 0x1e6562e8, 0xb71b9d18, 0xe1e5d712, 0x8480abb3)}, - {SECP256K1_SCALAR_CONST(0xcdddf2e5, 0xefc15f88, 0xc9ee06de, 0x8a846ca9, 0x28561581, 0x68daa5fb, 0xd1cf3451, 0xeb1782d0), - SECP256K1_SCALAR_CONST(0xffffffd9, 0xed8d2af4, 0x993c865a, 0x23e9681a, 0x3ca3a3dc, 0xe6d5a46e, 0xbd86bd87, 0x61b55c70)}, - {SECP256K1_SCALAR_CONST(0xb6a18f1f, 0x04872df9, 0x08165ec4, 0x319ca19c, 0x6c0359ab, 0x1f7118fb, 0xc2ef8082, 0xca8b7785), - SECP256K1_SCALAR_CONST(0xff55b19b, 0x0f1ac78c, 0x0f0c88c2, 0x2358d5ad, 0x5f455e4e, 0x3330b72f, 0x274dc153, 0xffbf272b)}, - {SECP256K1_SCALAR_CONST(0xea4898e5, 0x30eba3e8, 0xcf0e5c3d, 0x06ec6844, 0x01e26fb6, 0x75636225, 0xc5d08f4c, 0x1decafa0), - SECP256K1_SCALAR_CONST(0xe5a014a8, 0xe3c4ec1e, 0xea4f9b32, 0xcfc7b386, 0x00630806, 0x12c08d02, 0x6407ccc2, 0xb067d90e)}, - {SECP256K1_SCALAR_CONST(0x70e9aea9, 0x7e933af0, 0x8a23bfab, 0x23e4b772, 0xff951863, 0x5ffcf47d, 0x6bebc918, 0x2ca58265), - SECP256K1_SCALAR_CONST(0xf4e00006, 0x81bc6441, 0x4eb6ec02, 0xc194a859, 0x80ad7c48, 0xba4e9afb, 0x8b6bdbe0, 0x989d8f77)}, - {SECP256K1_SCALAR_CONST(0x3c56c774, 0x46efe6f0, 0xe93618b8, 0xf9b5a846, 0xd247df61, 0x83b1e215, 0x06dc8bcc, 0xeefc1bf5), - SECP256K1_SCALAR_CONST(0xfff8937a, 0x2cd9586b, 0x43c25e57, 0xd1cefa7a, 0x9fb91ed3, 0x95b6533d, 0x8ad0de5b, 0xafb93f00)}, - {SECP256K1_SCALAR_CONST(0xfb5c2772, 0x5cb30e83, 0xe38264df, 0xe4e3ebf3, 0x392aa92e, 0xa68756a1, 0x51279ac5, 0xb50711a8), - SECP256K1_SCALAR_CONST(0x000013af, 0x1105bfe7, 0xa6bbd7fb, 0x3d638f99, 0x3b266b02, 0x072fb8bc, 0x39251130, 0x2e0fd0ea)} - }; - int i, var, testrand; - unsigned char b32[32]; - secp256k1_fe x_fe; - secp256k1_scalar x_scalar; - memset(b32, 0, sizeof(b32)); - /* Test fixed test cases through test_inverse_{scalar,field}, both ways. */ - for (i = 0; (size_t)i < sizeof(fe_cases)/sizeof(fe_cases[0]); ++i) { - for (var = 0; var <= 1; ++var) { - test_inverse_field(&x_fe, &fe_cases[i][0], var); - CHECK(fe_equal(&x_fe, &fe_cases[i][1])); - test_inverse_field(&x_fe, &fe_cases[i][1], var); - CHECK(fe_equal(&x_fe, &fe_cases[i][0])); - } - } - for (i = 0; (size_t)i < sizeof(scalar_cases)/sizeof(scalar_cases[0]); ++i) { - for (var = 0; var <= 1; ++var) { - test_inverse_scalar(&x_scalar, &scalar_cases[i][0], var); - CHECK(secp256k1_scalar_eq(&x_scalar, &scalar_cases[i][1])); - test_inverse_scalar(&x_scalar, &scalar_cases[i][1], var); - CHECK(secp256k1_scalar_eq(&x_scalar, &scalar_cases[i][0])); - } - } - /* Test inputs 0..999 and their respective negations. */ - for (i = 0; i < 1000; ++i) { - b32[31] = i & 0xff; - b32[30] = (i >> 8) & 0xff; - secp256k1_scalar_set_b32(&x_scalar, b32, NULL); - secp256k1_fe_set_b32_mod(&x_fe, b32); - for (var = 0; var <= 1; ++var) { - test_inverse_scalar(NULL, &x_scalar, var); - test_inverse_field(NULL, &x_fe, var); - } - secp256k1_scalar_negate(&x_scalar, &x_scalar); - secp256k1_fe_negate(&x_fe, &x_fe, 1); - for (var = 0; var <= 1; ++var) { - test_inverse_scalar(NULL, &x_scalar, var); - test_inverse_field(NULL, &x_fe, var); - } - } - /* test 128*count random inputs; half with testrand256_test, half with testrand256 */ - for (testrand = 0; testrand <= 1; ++testrand) { - for (i = 0; i < 64 * COUNT; ++i) { - (testrand ? testrand256_test : testrand256)(b32); - secp256k1_scalar_set_b32(&x_scalar, b32, NULL); - secp256k1_fe_set_b32_mod(&x_fe, b32); - for (var = 0; var <= 1; ++var) { - test_inverse_scalar(NULL, &x_scalar, var); - test_inverse_field(NULL, &x_fe, var); - } - } - } -} - -/***** HSORT TESTS *****/ - -static void test_heap_swap(void) { - unsigned char a[600]; - unsigned char e[sizeof(a)]; - memset(a, 21, 200); - memset(a + 200, 99, 200); - memset(a + 400, 42, 200); - memset(e, 42, 200); - memset(e + 200, 99, 200); - memset(e + 400, 21, 200); - secp256k1_heap_swap(a, 0, 2, 200); - CHECK(secp256k1_memcmp_var(a, e, sizeof(a)) == 0); -} - -static void test_hsort_is_sorted(unsigned char *elements, size_t n, size_t len) { - size_t i; - for (i = 1; i < n; i++) { - CHECK(secp256k1_memcmp_var(&elements[(i-1) * len], &elements[i * len], len) <= 0); - } -} - -struct test_hsort_cmp_data { - size_t counter; - size_t element_len; -}; - - -static int test_hsort_cmp(const void *ele1, const void *ele2, void *data) { - struct test_hsort_cmp_data *d = (struct test_hsort_cmp_data *) data; - d->counter += 1; - return secp256k1_memcmp_var((unsigned char *)ele1, (unsigned char *)ele2, d->element_len); -} - -#define NUM 65 -#define MAX_ELEMENT_LEN 65 -static void test_hsort(size_t element_len) { - unsigned char elements[NUM * MAX_ELEMENT_LEN] = { 0 }; - struct test_hsort_cmp_data data; - int i; - - VERIFY_CHECK(element_len <= MAX_ELEMENT_LEN); - data.counter = 0; - data.element_len = element_len; - - secp256k1_hsort(elements, 0, element_len, test_hsort_cmp, &data); - CHECK(data.counter == 0); - secp256k1_hsort(elements, 1, element_len, test_hsort_cmp, &data); - CHECK(data.counter == 0); - secp256k1_hsort(elements, NUM, element_len, test_hsort_cmp, &data); - CHECK(data.counter >= NUM - 1); - test_hsort_is_sorted(elements, NUM, element_len); - - /* Test hsort with array of random length n */ - for (i = 0; i < COUNT; i++) { - int n = testrand_int(NUM); - testrand_bytes_test(elements, n*element_len); - secp256k1_hsort(elements, n, element_len, test_hsort_cmp, &data); - test_hsort_is_sorted(elements, n, element_len); - } -} -#undef NUM -#undef MAX_ELEMENT_LEN - - -static void run_hsort_tests(void) { - test_heap_swap(); - test_hsort(1); - test_hsort(64); - test_hsort(65); -} - -/***** GROUP TESTS *****/ - -/* This compares jacobian points including their Z, not just their geometric meaning. */ -static int gej_xyz_equals_gej(const secp256k1_gej *a, const secp256k1_gej *b) { - secp256k1_gej a2; - secp256k1_gej b2; - int ret = 1; - ret &= a->infinity == b->infinity; - if (ret && !a->infinity) { - a2 = *a; - b2 = *b; - secp256k1_fe_normalize(&a2.x); - secp256k1_fe_normalize(&a2.y); - secp256k1_fe_normalize(&a2.z); - secp256k1_fe_normalize(&b2.x); - secp256k1_fe_normalize(&b2.y); - secp256k1_fe_normalize(&b2.z); - ret &= secp256k1_fe_cmp_var(&a2.x, &b2.x) == 0; - ret &= secp256k1_fe_cmp_var(&a2.y, &b2.y) == 0; - ret &= secp256k1_fe_cmp_var(&a2.z, &b2.z) == 0; - } - return ret; -} - -static void test_ge(void) { - int i, i1; - int runs = 6; - /* 25 points are used: - * - infinity - * - for each of four random points p1 p2 p3 p4, we add the point, its - * negation, and then those two again but with randomized Z coordinate. - * - The same is then done for lambda*p1 and lambda^2*p1. - */ - secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); - secp256k1_fe zf, r; - secp256k1_fe zfi2, zfi3; - - secp256k1_gej_set_infinity(&gej[0]); - secp256k1_ge_set_infinity(&ge[0]); - for (i = 0; i < runs; i++) { - int j, k; - secp256k1_ge g; - testutil_random_ge_test(&g); - if (i >= runs - 2) { - secp256k1_ge_mul_lambda(&g, &ge[1]); - CHECK(!secp256k1_ge_eq_var(&g, &ge[1])); - } - if (i >= runs - 1) { - secp256k1_ge_mul_lambda(&g, &g); - } - ge[1 + 4 * i] = g; - ge[2 + 4 * i] = g; - secp256k1_ge_neg(&ge[3 + 4 * i], &g); - secp256k1_ge_neg(&ge[4 + 4 * i], &g); - secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); - testutil_random_ge_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); - secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); - testutil_random_ge_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); - for (j = 0; j < 4; j++) { - testutil_random_ge_x_magnitude(&ge[1 + j + 4 * i]); - testutil_random_ge_y_magnitude(&ge[1 + j + 4 * i]); - testutil_random_gej_x_magnitude(&gej[1 + j + 4 * i]); - testutil_random_gej_y_magnitude(&gej[1 + j + 4 * i]); - testutil_random_gej_z_magnitude(&gej[1 + j + 4 * i]); - } - - for (j = 0; j < 4; ++j) { - for (k = 0; k < 4; ++k) { - int expect_equal = (j >> 1) == (k >> 1); - CHECK(secp256k1_ge_eq_var(&ge[1 + j + 4 * i], &ge[1 + k + 4 * i]) == expect_equal); - CHECK(secp256k1_gej_eq_var(&gej[1 + j + 4 * i], &gej[1 + k + 4 * i]) == expect_equal); - CHECK(secp256k1_gej_eq_ge_var(&gej[1 + j + 4 * i], &ge[1 + k + 4 * i]) == expect_equal); - CHECK(secp256k1_gej_eq_ge_var(&gej[1 + k + 4 * i], &ge[1 + j + 4 * i]) == expect_equal); - } - } - } - - /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ - testutil_random_fe_non_zero_test(&zf); - testutil_random_fe_magnitude(&zf, 8); - secp256k1_fe_inv_var(&zfi3, &zf); - secp256k1_fe_sqr(&zfi2, &zfi3); - secp256k1_fe_mul(&zfi3, &zfi3, &zfi2); - - /* Generate random r */ - testutil_random_fe_non_zero_test(&r); - - for (i1 = 0; i1 < 1 + 4 * runs; i1++) { - int i2; - for (i2 = 0; i2 < 1 + 4 * runs; i2++) { - /* Compute reference result using gej + gej (var). */ - secp256k1_gej refj, resj; - secp256k1_ge ref; - secp256k1_fe zr; - secp256k1_gej_add_var(&refj, &gej[i1], &gej[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); - /* Check Z ratio. */ - if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&refj)) { - secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(secp256k1_fe_equal(&zrz, &refj.z)); - } - secp256k1_ge_set_gej_var(&ref, &refj); - - /* Test gej + ge with Z ratio result (var). */ - secp256k1_gej_add_ge_var(&resj, &gej[i1], &ge[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); - CHECK(secp256k1_gej_eq_ge_var(&resj, &ref)); - if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&resj)) { - secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(secp256k1_fe_equal(&zrz, &resj.z)); - } - - /* Test gej + ge (var, with additional Z factor). */ - { - secp256k1_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ - secp256k1_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); - secp256k1_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); - testutil_random_ge_x_magnitude(&ge2_zfi); - testutil_random_ge_y_magnitude(&ge2_zfi); - secp256k1_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); - CHECK(secp256k1_gej_eq_ge_var(&resj, &ref)); - } - - /* Test gej + ge (const). */ - if (i2 != 0) { - /* secp256k1_gej_add_ge does not support its second argument being infinity. */ - secp256k1_gej_add_ge(&resj, &gej[i1], &ge[i2]); - CHECK(secp256k1_gej_eq_ge_var(&resj, &ref)); - } - - /* Test doubling (var). */ - if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 == ((i2 + 3)%4)/2)) { - secp256k1_fe zr2; - /* Normal doubling with Z ratio result. */ - secp256k1_gej_double_var(&resj, &gej[i1], &zr2); - CHECK(secp256k1_gej_eq_ge_var(&resj, &ref)); - /* Check Z ratio. */ - secp256k1_fe_mul(&zr2, &zr2, &gej[i1].z); - CHECK(secp256k1_fe_equal(&zr2, &resj.z)); - /* Normal doubling. */ - secp256k1_gej_double_var(&resj, &gej[i2], NULL); - CHECK(secp256k1_gej_eq_ge_var(&resj, &ref)); - /* Constant-time doubling. */ - secp256k1_gej_double(&resj, &gej[i2]); - CHECK(secp256k1_gej_eq_ge_var(&resj, &ref)); - } - - /* Test adding opposites. */ - if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) { - CHECK(secp256k1_ge_is_infinity(&ref)); - } - - /* Test adding infinity. */ - if (i1 == 0) { - CHECK(secp256k1_ge_is_infinity(&ge[i1])); - CHECK(secp256k1_gej_is_infinity(&gej[i1])); - CHECK(secp256k1_gej_eq_ge_var(&gej[i2], &ref)); - } - if (i2 == 0) { - CHECK(secp256k1_ge_is_infinity(&ge[i2])); - CHECK(secp256k1_gej_is_infinity(&gej[i2])); - CHECK(secp256k1_gej_eq_ge_var(&gej[i1], &ref)); - } - } - } - - /* Test adding all points together in random order equals infinity. */ - { - secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej)); - for (i = 0; i < 4 * runs + 1; i++) { - gej_shuffled[i] = gej[i]; - } - for (i = 0; i < 4 * runs + 1; i++) { - int swap = i + testrand_int(4 * runs + 1 - i); - if (swap != i) { - secp256k1_gej t = gej_shuffled[i]; - gej_shuffled[i] = gej_shuffled[swap]; - gej_shuffled[swap] = t; - } - } - for (i = 0; i < 4 * runs + 1; i++) { - secp256k1_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); - } - CHECK(secp256k1_gej_is_infinity(&sum)); - free(gej_shuffled); - } - - /* Test batch gej -> ge conversion without known z ratios. */ - { - secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1); - for (i = 0; i < 4 * runs + 1; i++) { - secp256k1_fe s; - testutil_random_fe_non_zero(&s); - secp256k1_gej_rescale(&gej[i], &s); - CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge_set_all[i])); - } - free(ge_set_all); - } - - /* Test that all elements have X coordinates on the curve. */ - for (i = 1; i < 4 * runs + 1; i++) { - secp256k1_fe n; - CHECK(secp256k1_ge_x_on_curve_var(&ge[i].x)); - /* And the same holds after random rescaling. */ - secp256k1_fe_mul(&n, &zf, &ge[i].x); - CHECK(secp256k1_ge_x_frac_on_curve_var(&n, &zf)); - } - - /* Test correspondence of secp256k1_ge_x{,_frac}_on_curve_var with ge_set_xo. */ - { - secp256k1_fe n; - secp256k1_ge q; - int ret_on_curve, ret_frac_on_curve, ret_set_xo; - secp256k1_fe_mul(&n, &zf, &r); - ret_on_curve = secp256k1_ge_x_on_curve_var(&r); - ret_frac_on_curve = secp256k1_ge_x_frac_on_curve_var(&n, &zf); - ret_set_xo = secp256k1_ge_set_xo_var(&q, &r, 0); - CHECK(ret_on_curve == ret_frac_on_curve); - CHECK(ret_on_curve == ret_set_xo); - if (ret_set_xo) CHECK(secp256k1_fe_equal(&r, &q.x)); - } - - /* Test batch gej -> ge conversion with many infinities. */ - for (i = 0; i < 4 * runs + 1; i++) { - int odd; - testutil_random_ge_test(&ge[i]); - odd = secp256k1_fe_is_odd(&ge[i].x); - CHECK(odd == 0 || odd == 1); - /* randomly set half the points to infinity */ - if (odd == i % 2) { - secp256k1_ge_set_infinity(&ge[i]); - } - secp256k1_gej_set_ge(&gej[i], &ge[i]); - } - /* batch convert */ - secp256k1_ge_set_all_gej_var(ge, gej, 4 * runs + 1); - /* check result */ - for (i = 0; i < 4 * runs + 1; i++) { - CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge[i])); - } - - /* Test batch gej -> ge conversion with all infinities. */ - for (i = 0; i < 4 * runs + 1; i++) { - secp256k1_gej_set_infinity(&gej[i]); - } - /* batch convert */ - secp256k1_ge_set_all_gej_var(ge, gej, 4 * runs + 1); - /* check result */ - for (i = 0; i < 4 * runs + 1; i++) { - CHECK(secp256k1_ge_is_infinity(&ge[i])); - } - - free(ge); - free(gej); -} - -static void test_intialized_inf(void) { - secp256k1_ge p; - secp256k1_gej pj, npj, infj1, infj2, infj3; - secp256k1_fe zinv; - - /* Test that adding P+(-P) results in a fully initialized infinity*/ - testutil_random_ge_test(&p); - secp256k1_gej_set_ge(&pj, &p); - secp256k1_gej_neg(&npj, &pj); - - secp256k1_gej_add_var(&infj1, &pj, &npj, NULL); - CHECK(secp256k1_gej_is_infinity(&infj1)); - CHECK(secp256k1_fe_is_zero(&infj1.x)); - CHECK(secp256k1_fe_is_zero(&infj1.y)); - CHECK(secp256k1_fe_is_zero(&infj1.z)); - - secp256k1_gej_add_ge_var(&infj2, &npj, &p, NULL); - CHECK(secp256k1_gej_is_infinity(&infj2)); - CHECK(secp256k1_fe_is_zero(&infj2.x)); - CHECK(secp256k1_fe_is_zero(&infj2.y)); - CHECK(secp256k1_fe_is_zero(&infj2.z)); - - secp256k1_fe_set_int(&zinv, 1); - secp256k1_gej_add_zinv_var(&infj3, &npj, &p, &zinv); - CHECK(secp256k1_gej_is_infinity(&infj3)); - CHECK(secp256k1_fe_is_zero(&infj3.x)); - CHECK(secp256k1_fe_is_zero(&infj3.y)); - CHECK(secp256k1_fe_is_zero(&infj3.z)); - - -} - -static void test_add_neg_y_diff_x(void) { - /* The point of this test is to check that we can add two points - * whose y-coordinates are negatives of each other but whose x - * coordinates differ. If the x-coordinates were the same, these - * points would be negatives of each other and their sum is - * infinity. This is cool because it "covers up" any degeneracy - * in the addition algorithm that would cause the xy coordinates - * of the sum to be wrong (since infinity has no xy coordinates). - * HOWEVER, if the x-coordinates are different, infinity is the - * wrong answer, and such degeneracies are exposed. This is the - * root of https://github.com/bitcoin-core/secp256k1/issues/257 - * which this test is a regression test for. - * - * These points were generated in sage as - * - * load("secp256k1_params.sage") - * - * # random "bad pair" - * P = C.random_element() - * Q = -int(LAMBDA) * P - * print(" P: %x %x" % P.xy()) - * print(" Q: %x %x" % Q.xy()) - * print("P + Q: %x %x" % (P + Q).xy()) - */ - secp256k1_gej aj = SECP256K1_GEJ_CONST( - 0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30, - 0x0643d79f, 0x05a59614, 0x2f8ec030, 0xd58977cb, - 0x001e337a, 0x38093dcd, 0x6c0f386d, 0x0b1293a8, - 0x4d72c879, 0xd7681924, 0x44e6d2f3, 0x9190117d - ); - secp256k1_gej bj = SECP256K1_GEJ_CONST( - 0xc7b74206, 0x1f788cd9, 0xabd0937d, 0x164a0d86, - 0x95f6ff75, 0xf19a4ce9, 0xd013bd7b, 0xbf92d2a7, - 0xffe1cc85, 0xc7f6c232, 0x93f0c792, 0xf4ed6c57, - 0xb28d3786, 0x2897e6db, 0xbb192d0b, 0x6e6feab2 - ); - secp256k1_gej sumj = SECP256K1_GEJ_CONST( - 0x671a63c0, 0x3efdad4c, 0x389a7798, 0x24356027, - 0xb3d69010, 0x278625c3, 0x5c86d390, 0x184a8f7a, - 0x5f6409c2, 0x2ce01f2b, 0x511fd375, 0x25071d08, - 0xda651801, 0x70e95caf, 0x8f0d893c, 0xbed8fbbe - ); - secp256k1_ge b; - secp256k1_gej resj; - secp256k1_ge res; - secp256k1_ge_set_gej(&b, &bj); - - secp256k1_gej_add_var(&resj, &aj, &bj, NULL); - secp256k1_ge_set_gej(&res, &resj); - CHECK(secp256k1_gej_eq_ge_var(&sumj, &res)); - - secp256k1_gej_add_ge(&resj, &aj, &b); - secp256k1_ge_set_gej(&res, &resj); - CHECK(secp256k1_gej_eq_ge_var(&sumj, &res)); - - secp256k1_gej_add_ge_var(&resj, &aj, &b, NULL); - secp256k1_ge_set_gej(&res, &resj); - CHECK(secp256k1_gej_eq_ge_var(&sumj, &res)); -} - -static void test_ge_bytes(void) { - int i; - - for (i = 0; i < COUNT + 1; i++) { - unsigned char buf[64]; - secp256k1_ge p, q; - - if (i == 0) { - secp256k1_ge_set_infinity(&p); - } else { - testutil_random_ge_test(&p); - } - - if (!secp256k1_ge_is_infinity(&p)) { - secp256k1_ge_to_bytes(buf, &p); - - secp256k1_ge_from_bytes(&q, buf); - CHECK(secp256k1_ge_eq_var(&p, &q)); - - secp256k1_ge_from_bytes_ext(&q, buf); - CHECK(secp256k1_ge_eq_var(&p, &q)); - } - secp256k1_ge_to_bytes_ext(buf, &p); - secp256k1_ge_from_bytes_ext(&q, buf); - CHECK(secp256k1_ge_eq_var(&p, &q)); - } -} - -static void run_ge(void) { - int i; - for (i = 0; i < COUNT * 32; i++) { - test_ge(); - } - test_add_neg_y_diff_x(); - test_intialized_inf(); - test_ge_bytes(); -} - -static void test_gej_cmov(const secp256k1_gej *a, const secp256k1_gej *b) { - secp256k1_gej t = *a; - secp256k1_gej_cmov(&t, b, 0); - CHECK(gej_xyz_equals_gej(&t, a)); - secp256k1_gej_cmov(&t, b, 1); - CHECK(gej_xyz_equals_gej(&t, b)); -} - -static void run_gej(void) { - int i; - secp256k1_gej a, b; - - /* Tests for secp256k1_gej_cmov */ - for (i = 0; i < COUNT; i++) { - secp256k1_gej_set_infinity(&a); - secp256k1_gej_set_infinity(&b); - test_gej_cmov(&a, &b); - - testutil_random_gej_test(&a); - test_gej_cmov(&a, &b); - test_gej_cmov(&b, &a); - - b = a; - test_gej_cmov(&a, &b); - - testutil_random_gej_test(&b); - test_gej_cmov(&a, &b); - test_gej_cmov(&b, &a); - } - - /* Tests for secp256k1_gej_eq_var */ - for (i = 0; i < COUNT; i++) { - secp256k1_fe fe; - testutil_random_gej_test(&a); - testutil_random_gej_test(&b); - CHECK(!secp256k1_gej_eq_var(&a, &b)); - - b = a; - testutil_random_fe_non_zero_test(&fe); - secp256k1_gej_rescale(&a, &fe); - CHECK(secp256k1_gej_eq_var(&a, &b)); - } -} - -static void test_ec_combine(void) { - secp256k1_scalar sum = secp256k1_scalar_zero; - secp256k1_pubkey data[6]; - const secp256k1_pubkey* d[6]; - secp256k1_pubkey sd; - secp256k1_pubkey sd2; - secp256k1_gej Qj; - secp256k1_ge Q; - int i; - for (i = 1; i <= 6; i++) { - secp256k1_scalar s; - testutil_random_scalar_order_test(&s); - secp256k1_scalar_add(&sum, &sum, &s); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &s); - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(&data[i - 1], &Q); - d[i - 1] = &data[i - 1]; - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &sum); - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(&sd, &Q); - CHECK(secp256k1_ec_pubkey_combine(CTX, &sd2, d, i) == 1); - CHECK(secp256k1_memcmp_var(&sd, &sd2, sizeof(sd)) == 0); - } -} - -static void run_ec_combine(void) { - int i; - for (i = 0; i < COUNT * 8; i++) { - test_ec_combine(); - } -} - -static void test_group_decompress(const secp256k1_fe* x) { - /* The input itself, normalized. */ - secp256k1_fe fex = *x; - /* Results of set_xo_var(..., 0), set_xo_var(..., 1). */ - secp256k1_ge ge_even, ge_odd; - /* Return values of the above calls. */ - int res_even, res_odd; - - secp256k1_fe_normalize_var(&fex); - - res_even = secp256k1_ge_set_xo_var(&ge_even, &fex, 0); - res_odd = secp256k1_ge_set_xo_var(&ge_odd, &fex, 1); - - CHECK(res_even == res_odd); - - if (res_even) { - secp256k1_fe_normalize_var(&ge_odd.x); - secp256k1_fe_normalize_var(&ge_even.x); - secp256k1_fe_normalize_var(&ge_odd.y); - secp256k1_fe_normalize_var(&ge_even.y); - - /* No infinity allowed. */ - CHECK(!ge_even.infinity); - CHECK(!ge_odd.infinity); - - /* Check that the x coordinates check out. */ - CHECK(secp256k1_fe_equal(&ge_even.x, x)); - CHECK(secp256k1_fe_equal(&ge_odd.x, x)); - - /* Check odd/even Y in ge_odd, ge_even. */ - CHECK(secp256k1_fe_is_odd(&ge_odd.y)); - CHECK(!secp256k1_fe_is_odd(&ge_even.y)); - } -} - -static void run_group_decompress(void) { - int i; - for (i = 0; i < COUNT * 4; i++) { - secp256k1_fe fe; - testutil_random_fe_test(&fe); - test_group_decompress(&fe); - } -} - -/***** ECMULT TESTS *****/ - -static void test_pre_g_table(const secp256k1_ge_storage * pre_g, size_t n) { - /* Tests the pre_g / pre_g_128 tables for consistency. - * For independent verification we take a "geometric" approach to verification. - * We check that every entry is on-curve. - * We check that for consecutive entries p and q, that p + gg - q = 0 by checking - * (1) p, gg, and -q are colinear. - * (2) p, gg, and -q are all distinct. - * where gg is twice the generator, where the generator is the first table entry. - * - * Checking the table's generators are correct is done in run_ecmult_pre_g. - */ - secp256k1_gej g2; - secp256k1_ge p, q, gg; - secp256k1_fe dpx, dpy, dqx, dqy; - size_t i; - - CHECK(0 < n); - - secp256k1_ge_from_storage(&p, &pre_g[0]); - CHECK(secp256k1_ge_is_valid_var(&p)); - - secp256k1_gej_set_ge(&g2, &p); - secp256k1_gej_double_var(&g2, &g2, NULL); - secp256k1_ge_set_gej_var(&gg, &g2); - for (i = 1; i < n; ++i) { - secp256k1_fe_negate(&dpx, &p.x, 1); secp256k1_fe_add(&dpx, &gg.x); secp256k1_fe_normalize_weak(&dpx); - secp256k1_fe_negate(&dpy, &p.y, 1); secp256k1_fe_add(&dpy, &gg.y); secp256k1_fe_normalize_weak(&dpy); - /* Check that p is not equal to gg */ - CHECK(!secp256k1_fe_normalizes_to_zero_var(&dpx) || !secp256k1_fe_normalizes_to_zero_var(&dpy)); - - secp256k1_ge_from_storage(&q, &pre_g[i]); - CHECK(secp256k1_ge_is_valid_var(&q)); - - secp256k1_fe_negate(&dqx, &q.x, 1); secp256k1_fe_add(&dqx, &gg.x); - dqy = q.y; secp256k1_fe_add(&dqy, &gg.y); - /* Check that -q is not equal to gg */ - CHECK(!secp256k1_fe_normalizes_to_zero_var(&dqx) || !secp256k1_fe_normalizes_to_zero_var(&dqy)); - - /* Check that -q is not equal to p */ - CHECK(!secp256k1_fe_equal(&dpx, &dqx) || !secp256k1_fe_equal(&dpy, &dqy)); - - /* Check that p, -q and gg are colinear */ - secp256k1_fe_mul(&dpx, &dpx, &dqy); - secp256k1_fe_mul(&dpy, &dpy, &dqx); - CHECK(secp256k1_fe_equal(&dpx, &dpy)); - - p = q; - } -} - -static void run_ecmult_pre_g(void) { - secp256k1_ge_storage gs; - secp256k1_gej gj; - secp256k1_ge g; - size_t i; - - /* Check that the pre_g and pre_g_128 tables are consistent. */ - test_pre_g_table(secp256k1_pre_g, ECMULT_TABLE_SIZE(WINDOW_G)); - test_pre_g_table(secp256k1_pre_g_128, ECMULT_TABLE_SIZE(WINDOW_G)); - - /* Check the first entry from the pre_g table. */ - secp256k1_ge_to_storage(&gs, &secp256k1_ge_const_g); - CHECK(secp256k1_memcmp_var(&gs, &secp256k1_pre_g[0], sizeof(gs)) == 0); - - /* Check the first entry from the pre_g_128 table. */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); - for (i = 0; i < 128; ++i) { - secp256k1_gej_double_var(&gj, &gj, NULL); - } - secp256k1_ge_set_gej(&g, &gj); - secp256k1_ge_to_storage(&gs, &g); - CHECK(secp256k1_memcmp_var(&gs, &secp256k1_pre_g_128[0], sizeof(gs)) == 0); -} - -static void run_ecmult_chain(void) { - /* random starting point A (on the curve) */ - secp256k1_gej a = SECP256K1_GEJ_CONST( - 0x8b30bbe9, 0xae2a9906, 0x96b22f67, 0x0709dff3, - 0x727fd8bc, 0x04d3362c, 0x6c7bf458, 0xe2846004, - 0xa357ae91, 0x5c4a6528, 0x1309edf2, 0x0504740f, - 0x0eb33439, 0x90216b4f, 0x81063cb6, 0x5f2f7e0f - ); - /* two random initial factors xn and gn */ - secp256k1_scalar xn = SECP256K1_SCALAR_CONST( - 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c, - 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407 - ); - secp256k1_scalar gn = SECP256K1_SCALAR_CONST( - 0xa1e58d22, 0x553dcd42, 0xb2398062, 0x5d4c57a9, - 0x6e9323d4, 0x2b3152e5, 0xca2c3990, 0xedc7c9de - ); - /* two small multipliers to be applied to xn and gn in every iteration: */ - static const secp256k1_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); - static const secp256k1_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); - /* accumulators with the resulting coefficients to A and G */ - secp256k1_scalar ae = secp256k1_scalar_one; - secp256k1_scalar ge = secp256k1_scalar_zero; - /* actual points */ - secp256k1_gej x; - secp256k1_gej x2; - int i; - - /* the point being computed */ - x = a; - for (i = 0; i < 200*COUNT; i++) { - /* in each iteration, compute X = xn*X + gn*G; */ - secp256k1_ecmult(&x, &x, &xn, &gn); - /* also compute ae and ge: the actual accumulated factors for A and G */ - /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ - secp256k1_scalar_mul(&ae, &ae, &xn); - secp256k1_scalar_mul(&ge, &ge, &xn); - secp256k1_scalar_add(&ge, &ge, &gn); - /* modify xn and gn */ - secp256k1_scalar_mul(&xn, &xn, &xf); - secp256k1_scalar_mul(&gn, &gn, &gf); - - /* verify */ - if (i == 19999) { - /* expected result after 19999 iterations */ - secp256k1_gej rp = SECP256K1_GEJ_CONST( - 0xD6E96687, 0xF9B10D09, 0x2A6F3543, 0x9D86CEBE, - 0xA4535D0D, 0x409F5358, 0x6440BD74, 0xB933E830, - 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D, - 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88 - ); - CHECK(secp256k1_gej_eq_var(&rp, &x)); - } - } - /* redo the computation, but directly with the resulting ae and ge coefficients: */ - secp256k1_ecmult(&x2, &a, &ae, &ge); - CHECK(secp256k1_gej_eq_var(&x, &x2)); -} - -static void test_point_times_order(const secp256k1_gej *point) { - /* X * (point + G) + (order-X) * (pointer + G) = 0 */ - secp256k1_scalar x; - secp256k1_scalar nx; - secp256k1_gej res1, res2; - secp256k1_ge res3; - unsigned char pub[65]; - size_t psize = 65; - testutil_random_scalar_order_test(&x); - secp256k1_scalar_negate(&nx, &x); - secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ - secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ - secp256k1_gej_add_var(&res1, &res1, &res2, NULL); - CHECK(secp256k1_gej_is_infinity(&res1)); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_ge_is_infinity(&res3)); - CHECK(secp256k1_ge_is_valid_var(&res3) == 0); - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); - psize = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); - /* check zero/one edge cases */ - secp256k1_ecmult(&res1, point, &secp256k1_scalar_zero, &secp256k1_scalar_zero); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_ge_is_infinity(&res3)); - secp256k1_ecmult(&res1, point, &secp256k1_scalar_one, &secp256k1_scalar_zero); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_gej_eq_ge_var(point, &res3)); - secp256k1_ecmult(&res1, point, &secp256k1_scalar_zero, &secp256k1_scalar_one); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_ge_eq_var(&secp256k1_ge_const_g, &res3)); -} - -/* These scalars reach large (in absolute value) outputs when fed to secp256k1_scalar_split_lambda. - * - * They are computed as: - * - For a in [-2, -1, 0, 1, 2]: - * - For b in [-3, -1, 1, 3]: - * - Output (a*LAMBDA + (ORDER+b)/2) % ORDER - */ -static const secp256k1_scalar scalars_near_split_bounds[20] = { - SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fc), - SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fd), - SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fe), - SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6ff), - SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632d), - SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632e), - SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632f), - SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf76330), - SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b209f), - SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a0), - SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a1), - SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a2), - SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede11), - SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede12), - SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede13), - SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede14), - SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a42), - SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a43), - SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a44), - SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a45) -}; - -static void test_ecmult_target(const secp256k1_scalar* target, int mode) { - /* Mode: 0=ecmult_gen, 1=ecmult, 2=ecmult_const */ - secp256k1_scalar n1, n2; - secp256k1_ge p; - secp256k1_gej pj, p1j, p2j, ptj; - - /* Generate random n1,n2 such that n1+n2 = -target. */ - testutil_random_scalar_order_test(&n1); - secp256k1_scalar_add(&n2, &n1, target); - secp256k1_scalar_negate(&n2, &n2); - - /* Generate a random input point. */ - if (mode != 0) { - testutil_random_ge_test(&p); - secp256k1_gej_set_ge(&pj, &p); - } - - /* EC multiplications */ - if (mode == 0) { - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &p1j, &n1); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &p2j, &n2); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &ptj, target); - } else if (mode == 1) { - secp256k1_ecmult(&p1j, &pj, &n1, &secp256k1_scalar_zero); - secp256k1_ecmult(&p2j, &pj, &n2, &secp256k1_scalar_zero); - secp256k1_ecmult(&ptj, &pj, target, &secp256k1_scalar_zero); - } else { - secp256k1_ecmult_const(&p1j, &p, &n1); - secp256k1_ecmult_const(&p2j, &p, &n2); - secp256k1_ecmult_const(&ptj, &p, target); - } - - /* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */ - secp256k1_gej_add_var(&ptj, &ptj, &p1j, NULL); - secp256k1_gej_add_var(&ptj, &ptj, &p2j, NULL); - CHECK(secp256k1_gej_is_infinity(&ptj)); -} - -static void run_ecmult_near_split_bound(void) { - int i; - unsigned j; - for (i = 0; i < 4*COUNT; ++i) { - for (j = 0; j < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++j) { - test_ecmult_target(&scalars_near_split_bounds[j], 0); - test_ecmult_target(&scalars_near_split_bounds[j], 1); - test_ecmult_target(&scalars_near_split_bounds[j], 2); - } - } -} - -static void run_point_times_order(void) { - int i; - secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); - static const secp256k1_fe xr = SECP256K1_FE_CONST( - 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C, - 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45 - ); - for (i = 0; i < 500; i++) { - secp256k1_ge p; - if (secp256k1_ge_set_xo_var(&p, &x, 1)) { - secp256k1_gej j; - CHECK(secp256k1_ge_is_valid_var(&p)); - secp256k1_gej_set_ge(&j, &p); - test_point_times_order(&j); - } - secp256k1_fe_sqr(&x, &x); - } - secp256k1_fe_normalize_var(&x); - CHECK(secp256k1_fe_equal(&x, &xr)); -} - -static void ecmult_const_random_mult(void) { - /* random starting point A (on the curve) */ - secp256k1_ge a = SECP256K1_GE_CONST( - 0x6d986544, 0x57ff52b8, 0xcf1b8126, 0x5b802a5b, - 0xa97f9263, 0xb1e88044, 0x93351325, 0x91bc450a, - 0x535c59f7, 0x325e5d2b, 0xc391fbe8, 0x3c12787c, - 0x337e4a98, 0xe82a9011, 0x0123ba37, 0xdd769c7d - ); - /* random initial factor xn */ - secp256k1_scalar xn = SECP256K1_SCALAR_CONST( - 0x649d4f77, 0xc4242df7, 0x7f2079c9, 0x14530327, - 0xa31b876a, 0xd2d8ce2a, 0x2236d5c6, 0xd7b2029b - ); - /* expected xn * A (from sage) */ - secp256k1_ge expected_b = SECP256K1_GE_CONST( - 0x23773684, 0x4d209dc7, 0x098a786f, 0x20d06fcd, - 0x070a38bf, 0xc11ac651, 0x03004319, 0x1e2a8786, - 0xed8c3b8e, 0xc06dd57b, 0xd06ea66e, 0x45492b0f, - 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 - ); - secp256k1_gej b; - secp256k1_ecmult_const(&b, &a, &xn); - - CHECK(secp256k1_ge_is_valid_var(&a)); - CHECK(secp256k1_gej_eq_ge_var(&b, &expected_b)); -} - -static void ecmult_const_commutativity(void) { - secp256k1_scalar a; - secp256k1_scalar b; - secp256k1_gej res1; - secp256k1_gej res2; - secp256k1_ge mid1; - secp256k1_ge mid2; - testutil_random_scalar_order_test(&a); - testutil_random_scalar_order_test(&b); - - secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); - secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); - secp256k1_ge_set_gej(&mid1, &res1); - secp256k1_ge_set_gej(&mid2, &res2); - secp256k1_ecmult_const(&res1, &mid1, &b); - secp256k1_ecmult_const(&res2, &mid2, &a); - secp256k1_ge_set_gej(&mid1, &res1); - secp256k1_ge_set_gej(&mid2, &res2); - CHECK(secp256k1_ge_eq_var(&mid1, &mid2)); -} - -static void ecmult_const_mult_zero_one(void) { - secp256k1_scalar s; - secp256k1_scalar negone; - secp256k1_gej res1; - secp256k1_ge res2; - secp256k1_ge point; - secp256k1_ge inf; - - testutil_random_scalar_order_test(&s); - secp256k1_scalar_negate(&negone, &secp256k1_scalar_one); - testutil_random_ge_test(&point); - secp256k1_ge_set_infinity(&inf); - - /* 0*point */ - secp256k1_ecmult_const(&res1, &point, &secp256k1_scalar_zero); - CHECK(secp256k1_gej_is_infinity(&res1)); - - /* s*inf */ - secp256k1_ecmult_const(&res1, &inf, &s); - CHECK(secp256k1_gej_is_infinity(&res1)); - - /* 1*point */ - secp256k1_ecmult_const(&res1, &point, &secp256k1_scalar_one); - secp256k1_ge_set_gej(&res2, &res1); - CHECK(secp256k1_ge_eq_var(&res2, &point)); - - /* -1*point */ - secp256k1_ecmult_const(&res1, &point, &negone); - secp256k1_gej_neg(&res1, &res1); - secp256k1_ge_set_gej(&res2, &res1); - CHECK(secp256k1_ge_eq_var(&res2, &point)); -} - -static void ecmult_const_check_result(const secp256k1_ge *A, const secp256k1_scalar* q, const secp256k1_gej *res) { - secp256k1_gej pointj, res2j; - secp256k1_ge res2; - secp256k1_gej_set_ge(&pointj, A); - secp256k1_ecmult(&res2j, &pointj, q, &secp256k1_scalar_zero); - secp256k1_ge_set_gej(&res2, &res2j); - CHECK(secp256k1_gej_eq_ge_var(res, &res2)); -} - -static void ecmult_const_edges(void) { - secp256k1_scalar q; - secp256k1_ge point; - secp256k1_gej res; - size_t i; - size_t cases = 1 + sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); - - /* We are trying to reach the following edge cases (variables are defined as - * in ecmult_const_impl.h): - * 1. i = 0: s = 0 <=> q = -K - * 2. i > 0: v1, v2 large values - * <=> s1, s2 large values - * <=> s = scalars_near_split_bounds[i] - * <=> q = 2*scalars_near_split_bounds[i] - K - */ - for (i = 0; i < cases; ++i) { - secp256k1_scalar_negate(&q, &secp256k1_ecmult_const_K); - if (i > 0) { - secp256k1_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); - secp256k1_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); - } - testutil_random_ge_test(&point); - secp256k1_ecmult_const(&res, &point, &q); - ecmult_const_check_result(&point, &q, &res); - } -} - -static void ecmult_const_mult_xonly(void) { - int i; - - /* Test correspondence between secp256k1_ecmult_const and secp256k1_ecmult_const_xonly. */ - for (i = 0; i < 2*COUNT; ++i) { - secp256k1_ge base; - secp256k1_gej basej, resj; - secp256k1_fe n, d, resx, v; - secp256k1_scalar q; - int res; - /* Random base point. */ - testutil_random_ge_test(&base); - /* Random scalar to multiply it with. */ - testutil_random_scalar_order_test(&q); - /* If i is odd, n=d*base.x for random non-zero d */ - if (i & 1) { - testutil_random_fe_non_zero_test(&d); - secp256k1_fe_mul(&n, &base.x, &d); - } else { - n = base.x; - } - /* Perform x-only multiplication. */ - res = secp256k1_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, i & 2); - CHECK(res); - /* Perform normal multiplication. */ - secp256k1_gej_set_ge(&basej, &base); - secp256k1_ecmult(&resj, &basej, &q, NULL); - /* Check that resj's X coordinate corresponds with resx. */ - secp256k1_fe_sqr(&v, &resj.z); - secp256k1_fe_mul(&v, &v, &resx); - CHECK(fe_equal(&v, &resj.x)); - } - - /* Test that secp256k1_ecmult_const_xonly correctly rejects X coordinates not on curve. */ - for (i = 0; i < 2*COUNT; ++i) { - secp256k1_fe x, n, d, r; - int res; - secp256k1_scalar q; - testutil_random_scalar_order_test(&q); - /* Generate random X coordinate not on the curve. */ - do { - testutil_random_fe_test(&x); - } while (secp256k1_ge_x_on_curve_var(&x)); - /* If i is odd, n=d*x for random non-zero d. */ - if (i & 1) { - testutil_random_fe_non_zero_test(&d); - secp256k1_fe_mul(&n, &x, &d); - } else { - n = x; - } - res = secp256k1_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 0); - CHECK(res == 0); - } -} - -static void ecmult_const_chain_multiply(void) { - /* Check known result (randomly generated test problem from sage) */ - const secp256k1_scalar scalar = SECP256K1_SCALAR_CONST( - 0x4968d524, 0x2abf9b7a, 0x466abbcf, 0x34b11b6d, - 0xcd83d307, 0x827bed62, 0x05fad0ce, 0x18fae63b - ); - const secp256k1_gej expected_point = SECP256K1_GEJ_CONST( - 0x5494c15d, 0x32099706, 0xc2395f94, 0x348745fd, - 0x757ce30e, 0x4e8c90fb, 0xa2bad184, 0xf883c69f, - 0x5d195d20, 0xe191bf7f, 0x1be3e55f, 0x56a80196, - 0x6071ad01, 0xf1462f66, 0xc997fa94, 0xdb858435 - ); - secp256k1_gej point; - secp256k1_ge res; - int i; - - secp256k1_gej_set_ge(&point, &secp256k1_ge_const_g); - for (i = 0; i < 100; ++i) { - secp256k1_ge tmp; - secp256k1_ge_set_gej(&tmp, &point); - secp256k1_ecmult_const(&point, &tmp, &scalar); - } - secp256k1_ge_set_gej(&res, &point); - CHECK(secp256k1_gej_eq_ge_var(&expected_point, &res)); -} - -static void run_ecmult_const_tests(void) { - ecmult_const_mult_zero_one(); - ecmult_const_edges(); - ecmult_const_random_mult(); - ecmult_const_commutativity(); - ecmult_const_chain_multiply(); - ecmult_const_mult_xonly(); -} - -typedef struct { - secp256k1_scalar *sc; - secp256k1_ge *pt; -} ecmult_multi_data; - -static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { - ecmult_multi_data *data = (ecmult_multi_data*) cbdata; - *sc = data->sc[idx]; - *pt = data->pt[idx]; - return 1; -} - -static int ecmult_multi_false_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { - (void)sc; - (void)pt; - (void)idx; - (void)cbdata; - return 0; -} - -static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func ecmult_multi) { - int ncount; - secp256k1_scalar sc[32]; - secp256k1_ge pt[32]; - secp256k1_gej r; - secp256k1_gej r2; - ecmult_multi_data data; - - data.sc = sc; - data.pt = pt; - - /* No points to multiply */ - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, NULL, ecmult_multi_callback, &data, 0)); - - /* Check 1- and 2-point multiplies against ecmult */ - for (ncount = 0; ncount < COUNT; ncount++) { - secp256k1_ge ptg; - secp256k1_gej ptgj; - testutil_random_scalar_order(&sc[0]); - testutil_random_scalar_order(&sc[1]); - - testutil_random_ge_test(&ptg); - secp256k1_gej_set_ge(&ptgj, &ptg); - pt[0] = ptg; - pt[1] = secp256k1_ge_const_g; - - /* only G scalar */ - secp256k1_ecmult(&r2, &ptgj, &secp256k1_scalar_zero, &sc[0]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0)); - CHECK(secp256k1_gej_eq_var(&r, &r2)); - - /* 1-point */ - secp256k1_ecmult(&r2, &ptgj, &sc[0], &secp256k1_scalar_zero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 1)); - CHECK(secp256k1_gej_eq_var(&r, &r2)); - - /* Try to multiply 1 point, but callback returns false */ - CHECK(!ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_false_callback, &data, 1)); - - /* 2-point */ - secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 2)); - CHECK(secp256k1_gej_eq_var(&r, &r2)); - - /* 2-point with G scalar */ - secp256k1_ecmult(&r2, &ptgj, &sc[0], &sc[1]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1)); - CHECK(secp256k1_gej_eq_var(&r, &r2)); - } - - /* Check infinite outputs of various forms */ - for (ncount = 0; ncount < COUNT; ncount++) { - secp256k1_ge ptg; - size_t i, j; - size_t sizes[] = { 2, 10, 32 }; - - for (j = 0; j < 3; j++) { - for (i = 0; i < 32; i++) { - testutil_random_scalar_order(&sc[i]); - secp256k1_ge_set_infinity(&pt[i]); - } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, sizes[j])); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - for (j = 0; j < 3; j++) { - for (i = 0; i < 32; i++) { - testutil_random_ge_test(&ptg); - pt[i] = ptg; - secp256k1_scalar_set_int(&sc[i], 0); - } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, sizes[j])); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - for (j = 0; j < 3; j++) { - testutil_random_ge_test(&ptg); - for (i = 0; i < 16; i++) { - testutil_random_scalar_order(&sc[2*i]); - secp256k1_scalar_negate(&sc[2*i + 1], &sc[2*i]); - pt[2 * i] = ptg; - pt[2 * i + 1] = ptg; - } - - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, sizes[j])); - CHECK(secp256k1_gej_is_infinity(&r)); - - testutil_random_scalar_order(&sc[0]); - for (i = 0; i < 16; i++) { - testutil_random_ge_test(&ptg); - - sc[2*i] = sc[0]; - sc[2*i+1] = sc[0]; - pt[2 * i] = ptg; - secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]); - } - - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, sizes[j])); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - testutil_random_ge_test(&ptg); - secp256k1_scalar_set_int(&sc[0], 0); - pt[0] = ptg; - for (i = 1; i < 32; i++) { - pt[i] = ptg; - - testutil_random_scalar_order(&sc[i]); - secp256k1_scalar_add(&sc[0], &sc[0], &sc[i]); - secp256k1_scalar_negate(&sc[i], &sc[i]); - } - - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 32)); - CHECK(secp256k1_gej_is_infinity(&r)); - } - - /* Check random points, constant scalar */ - for (ncount = 0; ncount < COUNT; ncount++) { - size_t i; - secp256k1_gej_set_infinity(&r); - - testutil_random_scalar_order(&sc[0]); - for (i = 0; i < 20; i++) { - secp256k1_ge ptg; - sc[i] = sc[0]; - testutil_random_ge_test(&ptg); - pt[i] = ptg; - secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL); - } - - secp256k1_ecmult(&r2, &r, &sc[0], &secp256k1_scalar_zero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 20)); - CHECK(secp256k1_gej_eq_var(&r, &r2)); - } - - /* Check random scalars, constant point */ - for (ncount = 0; ncount < COUNT; ncount++) { - size_t i; - secp256k1_ge ptg; - secp256k1_gej p0j; - secp256k1_scalar rs; - secp256k1_scalar_set_int(&rs, 0); - - testutil_random_ge_test(&ptg); - for (i = 0; i < 20; i++) { - testutil_random_scalar_order(&sc[i]); - pt[i] = ptg; - secp256k1_scalar_add(&rs, &rs, &sc[i]); - } - - secp256k1_gej_set_ge(&p0j, &pt[0]); - secp256k1_ecmult(&r2, &p0j, &rs, &secp256k1_scalar_zero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 20)); - CHECK(secp256k1_gej_eq_var(&r, &r2)); - } - - /* Sanity check that zero scalars don't cause problems */ - for (ncount = 0; ncount < 20; ncount++) { - testutil_random_scalar_order(&sc[ncount]); - testutil_random_ge_test(&pt[ncount]); - } - - secp256k1_scalar_set_int(&sc[0], 0); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 20)); - secp256k1_scalar_set_int(&sc[1], 0); - secp256k1_scalar_set_int(&sc[2], 0); - secp256k1_scalar_set_int(&sc[3], 0); - secp256k1_scalar_set_int(&sc[4], 0); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 6)); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 5)); - CHECK(secp256k1_gej_is_infinity(&r)); - - /* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */ - { - const size_t TOP = 8; - size_t s0i, s1i; - size_t t0i, t1i; - secp256k1_ge ptg; - secp256k1_gej ptgj; - - testutil_random_ge_test(&ptg); - secp256k1_gej_set_ge(&ptgj, &ptg); - - for(t0i = 0; t0i < TOP; t0i++) { - for(t1i = 0; t1i < TOP; t1i++) { - secp256k1_gej t0p, t1p; - secp256k1_scalar t0, t1; - - secp256k1_scalar_set_int(&t0, (t0i + 1) / 2); - secp256k1_scalar_cond_negate(&t0, t0i & 1); - secp256k1_scalar_set_int(&t1, (t1i + 1) / 2); - secp256k1_scalar_cond_negate(&t1, t1i & 1); - - secp256k1_ecmult(&t0p, &ptgj, &t0, &secp256k1_scalar_zero); - secp256k1_ecmult(&t1p, &ptgj, &t1, &secp256k1_scalar_zero); - - for(s0i = 0; s0i < TOP; s0i++) { - for(s1i = 0; s1i < TOP; s1i++) { - secp256k1_scalar tmp1, tmp2; - secp256k1_gej expected, actual; - - secp256k1_ge_set_gej(&pt[0], &t0p); - secp256k1_ge_set_gej(&pt[1], &t1p); - - secp256k1_scalar_set_int(&sc[0], (s0i + 1) / 2); - secp256k1_scalar_cond_negate(&sc[0], s0i & 1); - secp256k1_scalar_set_int(&sc[1], (s1i + 1) / 2); - secp256k1_scalar_cond_negate(&sc[1], s1i & 1); - - secp256k1_scalar_mul(&tmp1, &t0, &sc[0]); - secp256k1_scalar_mul(&tmp2, &t1, &sc[1]); - secp256k1_scalar_add(&tmp1, &tmp1, &tmp2); - - secp256k1_ecmult(&expected, &ptgj, &tmp1, &secp256k1_scalar_zero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &actual, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 2)); - CHECK(secp256k1_gej_eq_var(&actual, &expected)); - } - } - } - } - } -} - -static int test_ecmult_multi_random(secp256k1_scratch *scratch) { - /* Large random test for ecmult_multi_* functions which exercises: - * - Few or many inputs (0 up to 128, roughly exponentially distributed). - * - Few or many 0*P or a*INF inputs (roughly uniformly distributed). - * - Including or excluding an nonzero a*G term (or such a term at all). - * - Final expected result equal to infinity or not (roughly 50%). - * - ecmult_multi_var, ecmult_strauss_single_batch, ecmult_pippenger_single_batch - */ - - /* These 4 variables define the eventual input to the ecmult_multi function. - * g_scalar is the G scalar fed to it (or NULL, possibly, if g_scalar=0), and - * scalars[0..filled-1] and gejs[0..filled-1] are the scalars and points - * which form its normal inputs. */ - int filled = 0; - secp256k1_scalar g_scalar = secp256k1_scalar_zero; - secp256k1_scalar scalars[128]; - secp256k1_gej gejs[128]; - /* The expected result, and the computed result. */ - secp256k1_gej expected, computed; - /* Temporaries. */ - secp256k1_scalar sc_tmp; - secp256k1_ge ge_tmp; - /* Variables needed for the actual input to ecmult_multi. */ - secp256k1_ge ges[128]; - ecmult_multi_data data; - - int i; - /* Which multiplication function to use */ - int fn = testrand_int(3); - secp256k1_ecmult_multi_func ecmult_multi = fn == 0 ? secp256k1_ecmult_multi_var : - fn == 1 ? secp256k1_ecmult_strauss_batch_single : - secp256k1_ecmult_pippenger_batch_single; - /* Simulate exponentially distributed num. */ - int num_bits = 2 + testrand_int(6); - /* Number of (scalar, point) inputs (excluding g). */ - int num = testrand_int((1 << num_bits) + 1); - /* Number of those which are nonzero. */ - int num_nonzero = testrand_int(num + 1); - /* Whether we're aiming to create an input with nonzero expected result. */ - int nonzero_result = testrand_bits(1); - /* Whether we will provide nonzero g multiplicand. In some cases our hand - * is forced here based on num_nonzero and nonzero_result. */ - int g_nonzero = num_nonzero == 0 ? nonzero_result : - num_nonzero == 1 && !nonzero_result ? 1 : - (int)testrand_bits(1); - /* Which g_scalar pointer to pass into ecmult_multi(). */ - const secp256k1_scalar* g_scalar_ptr = (g_nonzero || testrand_bits(1)) ? &g_scalar : NULL; - /* How many EC multiplications were performed in this function. */ - int mults = 0; - /* How many randomization steps to apply to the input list. */ - int rands = (int)testrand_bits(3); - if (rands > num_nonzero) rands = num_nonzero; - - secp256k1_gej_set_infinity(&expected); - secp256k1_gej_set_infinity(&gejs[0]); - secp256k1_scalar_set_int(&scalars[0], 0); - - if (g_nonzero) { - /* If g_nonzero, set g_scalar to nonzero value r. */ - testutil_random_scalar_order_test(&g_scalar); - if (!nonzero_result) { - /* If expected=0 is desired, add a (a*r, -(1/a)*g) term to compensate. */ - CHECK(num_nonzero > filled); - testutil_random_scalar_order_test(&sc_tmp); - secp256k1_scalar_mul(&scalars[filled], &sc_tmp, &g_scalar); - secp256k1_scalar_inverse_var(&sc_tmp, &sc_tmp); - secp256k1_scalar_negate(&sc_tmp, &sc_tmp); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &gejs[filled], &sc_tmp); - ++filled; - ++mults; - } - } - - if (nonzero_result && filled < num_nonzero) { - /* If a nonzero result is desired, and there is space, add a random nonzero term. */ - testutil_random_scalar_order_test(&scalars[filled]); - testutil_random_ge_test(&ge_tmp); - secp256k1_gej_set_ge(&gejs[filled], &ge_tmp); - ++filled; - } - - if (nonzero_result) { - /* Compute the expected result using normal ecmult. */ - CHECK(filled <= 1); - secp256k1_ecmult(&expected, &gejs[0], &scalars[0], &g_scalar); - mults += filled + g_nonzero; - } - - /* At this point we have expected = scalar_g*G + sum(scalars[i]*gejs[i] for i=0..filled-1). */ - CHECK(filled <= 1 + !nonzero_result); - CHECK(filled <= num_nonzero); - - /* Add entries to scalars,gejs so that there are num of them. All the added entries - * either have scalar=0 or point=infinity, so these do not change the expected result. */ - while (filled < num) { - if (testrand_bits(1)) { - secp256k1_gej_set_infinity(&gejs[filled]); - testutil_random_scalar_order_test(&scalars[filled]); - } else { - secp256k1_scalar_set_int(&scalars[filled], 0); - testutil_random_ge_test(&ge_tmp); - secp256k1_gej_set_ge(&gejs[filled], &ge_tmp); - } - ++filled; - } - - /* Now perform cheapish transformations on gejs and scalars, for indices - * 0..num_nonzero-1, which do not change the expected result, but may - * convert some of them to be both non-0-scalar and non-infinity-point. */ - for (i = 0; i < rands; ++i) { - int j; - secp256k1_scalar v, iv; - /* Shuffle the entries. */ - for (j = 0; j < num_nonzero; ++j) { - int k = testrand_int(num_nonzero - j); - if (k != 0) { - secp256k1_gej gej = gejs[j]; - secp256k1_scalar sc = scalars[j]; - gejs[j] = gejs[j + k]; - scalars[j] = scalars[j + k]; - gejs[j + k] = gej; - scalars[j + k] = sc; - } - } - /* Perturb all consecutive pairs of inputs: - * a*P + b*Q -> (a+b)*P + b*(Q-P). */ - for (j = 0; j + 1 < num_nonzero; j += 2) { - secp256k1_gej gej; - secp256k1_scalar_add(&scalars[j], &scalars[j], &scalars[j+1]); - secp256k1_gej_neg(&gej, &gejs[j]); - secp256k1_gej_add_var(&gejs[j+1], &gejs[j+1], &gej, NULL); - } - /* Transform the last input: a*P -> (v*a) * ((1/v)*P). */ - CHECK(num_nonzero >= 1); - testutil_random_scalar_order_test(&v); - secp256k1_scalar_inverse(&iv, &v); - secp256k1_scalar_mul(&scalars[num_nonzero - 1], &scalars[num_nonzero - 1], &v); - secp256k1_ecmult(&gejs[num_nonzero - 1], &gejs[num_nonzero - 1], &iv, NULL); - ++mults; - } - - /* Shuffle all entries (0..num-1). */ - for (i = 0; i < num; ++i) { - int j = testrand_int(num - i); - if (j != 0) { - secp256k1_gej gej = gejs[i]; - secp256k1_scalar sc = scalars[i]; - gejs[i] = gejs[i + j]; - scalars[i] = scalars[i + j]; - gejs[i + j] = gej; - scalars[i + j] = sc; - } - } - - /* Compute affine versions of all inputs. */ - secp256k1_ge_set_all_gej_var(ges, gejs, filled); - /* Invoke ecmult_multi code. */ - data.sc = scalars; - data.pt = ges; - CHECK(ecmult_multi(&CTX->error_callback, scratch, &computed, g_scalar_ptr, ecmult_multi_callback, &data, filled)); - mults += num_nonzero + g_nonzero; - /* Compare with expected result. */ - CHECK(secp256k1_gej_eq_var(&computed, &expected)); - return mults; -} - -static void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_multi) { - secp256k1_scalar sc; - secp256k1_ge pt; - secp256k1_gej r; - ecmult_multi_data data; - secp256k1_scratch *scratch_empty; - - testutil_random_ge_test(&pt); - testutil_random_scalar_order(&sc); - data.sc = ≻ - data.pt = &pt; - - /* Try to multiply 1 point, but scratch space is empty.*/ - scratch_empty = secp256k1_scratch_create(&CTX->error_callback, 0); - CHECK(!ecmult_multi(&CTX->error_callback, scratch_empty, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 1)); - secp256k1_scratch_destroy(&CTX->error_callback, scratch_empty); -} - -static void test_secp256k1_pippenger_bucket_window_inv(void) { - int i; - - CHECK(secp256k1_pippenger_bucket_window_inv(0) == 0); - for(i = 1; i <= PIPPENGER_MAX_BUCKET_WINDOW; i++) { - /* Bucket_window of 8 is not used with endo */ - if (i == 8) { - continue; - } - CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)) == i); - if (i != PIPPENGER_MAX_BUCKET_WINDOW) { - CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)+1) > i); - } - } -} - -/** - * Probabilistically test the function returning the maximum number of possible points - * for a given scratch space. - */ -static void test_ecmult_multi_pippenger_max_points(void) { - size_t scratch_size = testrand_bits(8); - size_t max_size = secp256k1_pippenger_scratch_size(secp256k1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12); - secp256k1_scratch *scratch; - size_t n_points_supported; - int bucket_window = 0; - - for(; scratch_size < max_size; scratch_size+=256) { - size_t i; - size_t total_alloc; - size_t checkpoint; - scratch = secp256k1_scratch_create(&CTX->error_callback, scratch_size); - CHECK(scratch != NULL); - checkpoint = secp256k1_scratch_checkpoint(&CTX->error_callback, scratch); - n_points_supported = secp256k1_pippenger_max_points(&CTX->error_callback, scratch); - if (n_points_supported == 0) { - secp256k1_scratch_destroy(&CTX->error_callback, scratch); - continue; - } - bucket_window = secp256k1_pippenger_bucket_window(n_points_supported); - /* allocate `total_alloc` bytes over `PIPPENGER_SCRATCH_OBJECTS` many allocations */ - total_alloc = secp256k1_pippenger_scratch_size(n_points_supported, bucket_window); - for (i = 0; i < PIPPENGER_SCRATCH_OBJECTS - 1; i++) { - CHECK(secp256k1_scratch_alloc(&CTX->error_callback, scratch, 1)); - total_alloc--; - } - CHECK(secp256k1_scratch_alloc(&CTX->error_callback, scratch, total_alloc)); - secp256k1_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); - secp256k1_scratch_destroy(&CTX->error_callback, scratch); - } - CHECK(bucket_window == PIPPENGER_MAX_BUCKET_WINDOW); -} - -static void test_ecmult_multi_batch_size_helper(void) { - size_t n_batches, n_batch_points, max_n_batch_points, n; - - max_n_batch_points = 0; - n = 1; - CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 0); - - max_n_batch_points = 1; - n = 0; - CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); - CHECK(n_batches == 0); - CHECK(n_batch_points == 0); - - max_n_batch_points = 2; - n = 5; - CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); - CHECK(n_batches == 3); - CHECK(n_batch_points == 2); - - max_n_batch_points = ECMULT_MAX_POINTS_PER_BATCH; - n = ECMULT_MAX_POINTS_PER_BATCH; - CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); - CHECK(n_batches == 1); - CHECK(n_batch_points == ECMULT_MAX_POINTS_PER_BATCH); - - max_n_batch_points = ECMULT_MAX_POINTS_PER_BATCH + 1; - n = ECMULT_MAX_POINTS_PER_BATCH + 1; - CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); - CHECK(n_batches == 2); - CHECK(n_batch_points == ECMULT_MAX_POINTS_PER_BATCH/2 + 1); - - max_n_batch_points = 1; - n = SIZE_MAX; - CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); - CHECK(n_batches == SIZE_MAX); - CHECK(n_batch_points == 1); - - max_n_batch_points = 2; - n = SIZE_MAX; - CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); - CHECK(n_batches == SIZE_MAX/2 + 1); - CHECK(n_batch_points == 2); -} - -/** - * Run secp256k1_ecmult_multi_var with num points and a scratch space restricted to - * 1 <= i <= num points. - */ -static void test_ecmult_multi_batching(void) { - static const int n_points = 2*ECMULT_PIPPENGER_THRESHOLD; - secp256k1_scalar scG; - secp256k1_scalar *sc = (secp256k1_scalar *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_scalar) * n_points); - secp256k1_ge *pt = (secp256k1_ge *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * n_points); - secp256k1_gej r; - secp256k1_gej r2; - ecmult_multi_data data; - int i; - secp256k1_scratch *scratch; - - secp256k1_gej_set_infinity(&r2); - - /* Get random scalars and group elements and compute result */ - testutil_random_scalar_order(&scG); - secp256k1_ecmult(&r2, &r2, &secp256k1_scalar_zero, &scG); - for(i = 0; i < n_points; i++) { - secp256k1_ge ptg; - secp256k1_gej ptgj; - testutil_random_ge_test(&ptg); - secp256k1_gej_set_ge(&ptgj, &ptg); - pt[i] = ptg; - testutil_random_scalar_order(&sc[i]); - secp256k1_ecmult(&ptgj, &ptgj, &sc[i], NULL); - secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL); - } - data.sc = sc; - data.pt = pt; - secp256k1_gej_neg(&r2, &r2); - - /* Test with empty scratch space. It should compute the correct result using - * ecmult_mult_simple algorithm which doesn't require a scratch space. */ - scratch = secp256k1_scratch_create(&CTX->error_callback, 0); - CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - secp256k1_scratch_destroy(&CTX->error_callback, scratch); - - /* Test with space for 1 point in pippenger. That's not enough because - * ecmult_multi selects strauss which requires more memory. It should - * therefore select the simple algorithm. */ - scratch = secp256k1_scratch_create(&CTX->error_callback, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); - CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - secp256k1_scratch_destroy(&CTX->error_callback, scratch); - - for(i = 1; i <= n_points; i++) { - if (i > ECMULT_PIPPENGER_THRESHOLD) { - int bucket_window = secp256k1_pippenger_bucket_window(i); - size_t scratch_size = secp256k1_pippenger_scratch_size(i, bucket_window); - scratch = secp256k1_scratch_create(&CTX->error_callback, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); - } else { - size_t scratch_size = secp256k1_strauss_scratch_size(i); - scratch = secp256k1_scratch_create(&CTX->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); - } - CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); - secp256k1_gej_add_var(&r, &r, &r2, NULL); - CHECK(secp256k1_gej_is_infinity(&r)); - secp256k1_scratch_destroy(&CTX->error_callback, scratch); - } - free(sc); - free(pt); -} - -static void run_ecmult_multi_tests(void) { - secp256k1_scratch *scratch; - int64_t todo = (int64_t)320 * COUNT; - - test_secp256k1_pippenger_bucket_window_inv(); - test_ecmult_multi_pippenger_max_points(); - scratch = secp256k1_scratch_create(&CTX->error_callback, 819200); - test_ecmult_multi(scratch, secp256k1_ecmult_multi_var); - test_ecmult_multi(NULL, secp256k1_ecmult_multi_var); - test_ecmult_multi(scratch, secp256k1_ecmult_pippenger_batch_single); - test_ecmult_multi_batch_single(secp256k1_ecmult_pippenger_batch_single); - test_ecmult_multi(scratch, secp256k1_ecmult_strauss_batch_single); - test_ecmult_multi_batch_single(secp256k1_ecmult_strauss_batch_single); - while (todo > 0) { - todo -= test_ecmult_multi_random(scratch); - } - secp256k1_scratch_destroy(&CTX->error_callback, scratch); - - /* Run test_ecmult_multi with space for exactly one point */ - scratch = secp256k1_scratch_create(&CTX->error_callback, secp256k1_strauss_scratch_size(1) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); - test_ecmult_multi(scratch, secp256k1_ecmult_multi_var); - secp256k1_scratch_destroy(&CTX->error_callback, scratch); - - test_ecmult_multi_batch_size_helper(); - test_ecmult_multi_batching(); -} - -static void test_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, two, t; - int wnaf[256]; - int zeroes = -1; - int i; - int bits; - secp256k1_scalar_set_int(&x, 0); - secp256k1_scalar_set_int(&two, 2); - bits = secp256k1_ecmult_wnaf(wnaf, 256, number, w); - CHECK(bits <= 256); - for (i = bits-1; i >= 0; i--) { - int v = wnaf[i]; - secp256k1_scalar_mul(&x, &x, &two); - if (v) { - CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ - zeroes=0; - CHECK((v & 1) == 1); /* check non-zero elements are odd */ - CHECK(v <= (1 << (w-1)) - 1); /* check range below */ - CHECK(v >= -(1 << (w-1)) - 1); /* check range above */ - } else { - CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ - zeroes++; - } - if (v >= 0) { - secp256k1_scalar_set_int(&t, v); - } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); - } - secp256k1_scalar_add(&x, &x, &t); - } - CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */ -} - -static void test_fixed_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, shift; - int wnaf[256] = {0}; - int i; - int skew; - secp256k1_scalar num, unused; - - secp256k1_scalar_set_int(&x, 0); - secp256k1_scalar_set_int(&shift, 1 << w); - /* Make num a 128-bit scalar. */ - secp256k1_scalar_split_128(&num, &unused, number); - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - - for (i = WNAF_SIZE(w)-1; i >= 0; --i) { - secp256k1_scalar t; - int v = wnaf[i]; - CHECK(v == 0 || v & 1); /* check parity */ - CHECK(v > -(1 << w)); /* check range above */ - CHECK(v < (1 << w)); /* check range below */ - - secp256k1_scalar_mul(&x, &x, &shift); - if (v >= 0) { - secp256k1_scalar_set_int(&t, v); - } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); - } - secp256k1_scalar_add(&x, &x, &t); - } - /* If skew is 1 then add 1 to num */ - secp256k1_scalar_cadd_bit(&num, 0, skew == 1); - CHECK(secp256k1_scalar_eq(&x, &num)); -} - -/* Checks that the first 8 elements of wnaf are equal to wnaf_expected and the - * rest is 0.*/ -static void test_fixed_wnaf_small_helper(int *wnaf, int *wnaf_expected, int w) { - int i; - for (i = WNAF_SIZE(w)-1; i >= 8; --i) { - CHECK(wnaf[i] == 0); - } - for (i = 7; i >= 0; --i) { - CHECK(wnaf[i] == wnaf_expected[i]); - } -} - -static void test_fixed_wnaf_small(void) { - int w = 4; - int wnaf[256] = {0}; - int i; - int skew; - secp256k1_scalar num; - - secp256k1_scalar_set_int(&num, 0); - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - for (i = WNAF_SIZE(w)-1; i >= 0; --i) { - int v = wnaf[i]; - CHECK(v == 0); - } - CHECK(skew == 0); - - secp256k1_scalar_set_int(&num, 1); - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - for (i = WNAF_SIZE(w)-1; i >= 1; --i) { - int v = wnaf[i]; - CHECK(v == 0); - } - CHECK(wnaf[0] == 1); - CHECK(skew == 0); - - { - int wnaf_expected[8] = { 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf }; - secp256k1_scalar_set_int(&num, 0xffffffff); - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); - CHECK(skew == 0); - } - { - int wnaf_expected[8] = { -1, -1, -1, -1, -1, -1, -1, 0xf }; - secp256k1_scalar_set_int(&num, 0xeeeeeeee); - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); - CHECK(skew == 1); - } - { - int wnaf_expected[8] = { 1, 0, 1, 0, 1, 0, 1, 0 }; - secp256k1_scalar_set_int(&num, 0x01010101); - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); - CHECK(skew == 0); - } - { - int wnaf_expected[8] = { -0xf, 0, 0xf, -0xf, 0, 0xf, 1, 0 }; - secp256k1_scalar_set_int(&num, 0x01ef1ef1); - skew = secp256k1_wnaf_fixed(wnaf, &num, w); - test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); - CHECK(skew == 0); - } -} - -static void run_wnaf(void) { - int i; - secp256k1_scalar n; - - /* Test 0 for fixed wnaf */ - test_fixed_wnaf_small(); - /* Random tests */ - for (i = 0; i < COUNT; i++) { - testutil_random_scalar_order(&n); - test_wnaf(&n, 4+(i%10)); - test_fixed_wnaf(&n, 4 + (i % 10)); - } - secp256k1_scalar_set_int(&n, 0); - CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); - CHECK(secp256k1_scalar_is_zero(&n)); - CHECK(secp256k1_scalar_cond_negate(&n, 0) == 1); - CHECK(secp256k1_scalar_is_zero(&n)); -} - -static int test_ecmult_accumulate_cb(secp256k1_scalar* sc, secp256k1_ge* pt, size_t idx, void* data) { - const secp256k1_scalar* indata = (const secp256k1_scalar*)data; - *sc = *indata; - *pt = secp256k1_ge_const_g; - CHECK(idx == 0); - return 1; -} - -static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar* x, secp256k1_scratch* scratch) { - /* Compute x*G in 6 different ways, serialize it uncompressed, and feed it into acc. */ - secp256k1_gej rj1, rj2, rj3, rj4, rj5, rj6, gj, infj; - secp256k1_ge r; - unsigned char bytes[65]; - size_t size = 65; - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); - secp256k1_gej_set_infinity(&infj); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &rj1, x); - secp256k1_ecmult(&rj2, &gj, x, &secp256k1_scalar_zero); - secp256k1_ecmult(&rj3, &infj, &secp256k1_scalar_zero, x); - CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &rj4, x, NULL, NULL, 0)); - CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &rj5, &secp256k1_scalar_zero, test_ecmult_accumulate_cb, (void*)x, 1)); - secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x); - secp256k1_ge_set_gej_var(&r, &rj1); - CHECK(secp256k1_gej_eq_ge_var(&rj2, &r)); - CHECK(secp256k1_gej_eq_ge_var(&rj3, &r)); - CHECK(secp256k1_gej_eq_ge_var(&rj4, &r)); - CHECK(secp256k1_gej_eq_ge_var(&rj5, &r)); - CHECK(secp256k1_gej_eq_ge_var(&rj6, &r)); - if (secp256k1_ge_is_infinity(&r)) { - /* Store infinity as 0x00 */ - const unsigned char zerobyte[1] = {0}; - secp256k1_sha256_write(acc, zerobyte, 1); - } else { - /* Store other points using their uncompressed serialization. */ - secp256k1_eckey_pubkey_serialize(&r, bytes, &size, 0); - CHECK(size == 65); - secp256k1_sha256_write(acc, bytes, size); - } -} - -static void test_ecmult_constants_2bit(void) { - /* Using test_ecmult_accumulate, test ecmult for: - * - For i in 0..36: - * - Key i - * - Key -i - * - For i in 0..255: - * - For j in 1..255 (only odd values): - * - Key (j*2^i) mod order - */ - secp256k1_scalar x; - secp256k1_sha256 acc; - unsigned char b32[32]; - int i, j; - secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 65536); - - /* Expected hash of all the computed points; created with an independent - * implementation. */ - static const unsigned char expected32[32] = { - 0xe4, 0x71, 0x1b, 0x4d, 0x14, 0x1e, 0x68, 0x48, - 0xb7, 0xaf, 0x47, 0x2b, 0x4c, 0xd2, 0x04, 0x14, - 0x3a, 0x75, 0x87, 0x60, 0x1a, 0xf9, 0x63, 0x60, - 0xd0, 0xcb, 0x1f, 0xaa, 0x85, 0x9a, 0xb7, 0xb4 - }; - secp256k1_sha256_initialize(&acc); - for (i = 0; i <= 36; ++i) { - secp256k1_scalar_set_int(&x, i); - test_ecmult_accumulate(&acc, &x, scratch); - secp256k1_scalar_negate(&x, &x); - test_ecmult_accumulate(&acc, &x, scratch); - }; - for (i = 0; i < 256; ++i) { - for (j = 1; j < 256; j += 2) { - int k; - secp256k1_scalar_set_int(&x, j); - for (k = 0; k < i; ++k) secp256k1_scalar_add(&x, &x, &x); - test_ecmult_accumulate(&acc, &x, scratch); - } - } - secp256k1_sha256_finalize(&acc, b32); - CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0); - - secp256k1_scratch_space_destroy(CTX, scratch); -} - -static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsigned char* expected32) { - /* Using test_ecmult_accumulate, test ecmult for: - * - Key 0 - * - Key 1 - * - Key -1 - * - For i in range(iter): - * - Key SHA256(LE32(prefix) || LE16(i)) - */ - secp256k1_scalar x; - secp256k1_sha256 acc; - unsigned char b32[32]; - unsigned char inp[6]; - size_t i; - secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 65536); - - inp[0] = prefix & 0xFF; - inp[1] = (prefix >> 8) & 0xFF; - inp[2] = (prefix >> 16) & 0xFF; - inp[3] = (prefix >> 24) & 0xFF; - secp256k1_sha256_initialize(&acc); - secp256k1_scalar_set_int(&x, 0); - test_ecmult_accumulate(&acc, &x, scratch); - secp256k1_scalar_set_int(&x, 1); - test_ecmult_accumulate(&acc, &x, scratch); - secp256k1_scalar_negate(&x, &x); - test_ecmult_accumulate(&acc, &x, scratch); - - for (i = 0; i < iter; ++i) { - secp256k1_sha256 gen; - inp[4] = i & 0xff; - inp[5] = (i >> 8) & 0xff; - secp256k1_sha256_initialize(&gen); - secp256k1_sha256_write(&gen, inp, sizeof(inp)); - secp256k1_sha256_finalize(&gen, b32); - secp256k1_scalar_set_b32(&x, b32, NULL); - test_ecmult_accumulate(&acc, &x, scratch); - } - secp256k1_sha256_finalize(&acc, b32); - CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0); - - secp256k1_scratch_space_destroy(CTX, scratch); -} - -static void run_ecmult_constants(void) { - /* Expected hashes of all points in the tests below. Computed using an - * independent implementation. */ - static const unsigned char expected32_6bit20[32] = { - 0x68, 0xb6, 0xed, 0x6f, 0x28, 0xca, 0xc9, 0x7f, - 0x8e, 0x8b, 0xd6, 0xc0, 0x61, 0x79, 0x34, 0x6e, - 0x5a, 0x8f, 0x2b, 0xbc, 0x3e, 0x1f, 0xc5, 0x2e, - 0x2a, 0xd0, 0x45, 0x67, 0x7f, 0x95, 0x95, 0x8e - }; - static const unsigned char expected32_8bit8[32] = { - 0x8b, 0x65, 0x8e, 0xea, 0x86, 0xae, 0x3c, 0x95, - 0x90, 0xb6, 0x77, 0xa4, 0x8c, 0x76, 0xd9, 0xec, - 0xf5, 0xab, 0x8a, 0x2f, 0xfd, 0xdb, 0x19, 0x12, - 0x1a, 0xee, 0xe6, 0xb7, 0x6e, 0x05, 0x3f, 0xc6 - }; - /* For every combination of 6 bit positions out of 256, restricted to - * 20-bit windows (i.e., the first and last bit position are no more than - * 19 bits apart), all 64 bit patterns occur in the input scalars used in - * this test. */ - CONDITIONAL_TEST(1, "test_ecmult_constants_sha 1024") { - test_ecmult_constants_sha(4808378u, 1024, expected32_6bit20); - } - - /* For every combination of 8 consecutive bit positions, all 256 bit - * patterns occur in the input scalars used in this test. */ - CONDITIONAL_TEST(3, "test_ecmult_constants_sha 2048") { - test_ecmult_constants_sha(1607366309u, 2048, expected32_8bit8); - } - - CONDITIONAL_TEST(16, "test_ecmult_constants_2bit") { - test_ecmult_constants_2bit(); - } -} - -static void test_ecmult_gen_blind(void) { - /* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */ - secp256k1_scalar key; - secp256k1_scalar b; - unsigned char seed32[32]; - secp256k1_gej pgej; - secp256k1_gej pgej2; - secp256k1_ge p; - secp256k1_ge pge; - testutil_random_scalar_order_test(&key); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej, &key); - testrand256(seed32); - b = CTX->ecmult_gen_ctx.scalar_offset; - p = CTX->ecmult_gen_ctx.ge_offset; - secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, seed32); - CHECK(!secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej2, &key); - CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); - CHECK(!secp256k1_ge_eq_var(&p, &CTX->ecmult_gen_ctx.ge_offset)); - secp256k1_ge_set_gej(&pge, &pgej); - CHECK(secp256k1_gej_eq_ge_var(&pgej2, &pge)); -} - -static void test_ecmult_gen_blind_reset(void) { - /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ - secp256k1_scalar b; - secp256k1_ge p1, p2; - secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); - b = CTX->ecmult_gen_ctx.scalar_offset; - p1 = CTX->ecmult_gen_ctx.ge_offset; - secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); - CHECK(secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); - p2 = CTX->ecmult_gen_ctx.ge_offset; - CHECK(secp256k1_ge_eq_var(&p1, &p2)); -} - -/* Verify that ecmult_gen for scalars gn for which gn + scalar_offset = {-1,0,1}. */ -static void test_ecmult_gen_edge_cases(void) { - int i; - secp256k1_gej res1, res2, res3; - secp256k1_scalar gn = secp256k1_scalar_one; /* gn = 1 */ - secp256k1_scalar_add(&gn, &gn, &CTX->ecmult_gen_ctx.scalar_offset); /* gn = 1 + scalar_offset */ - secp256k1_scalar_negate(&gn, &gn); /* gn = -1 - scalar_offset */ - - for (i = -1; i < 2; ++i) { - /* Run test with gn = i - scalar_offset (so that the ecmult_gen recoded value represents i). */ - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &res1, &gn); - secp256k1_ecmult(&res2, NULL, &secp256k1_scalar_zero, &gn); - secp256k1_ecmult_const(&res3, &secp256k1_ge_const_g, &gn); - CHECK(secp256k1_gej_eq_var(&res1, &res2)); - CHECK(secp256k1_gej_eq_var(&res1, &res3)); - secp256k1_scalar_add(&gn, &gn, &secp256k1_scalar_one); - } -} - -static void run_ecmult_gen_blind(void) { - int i; - test_ecmult_gen_blind_reset(); - test_ecmult_gen_edge_cases(); - for (i = 0; i < 10; i++) { - test_ecmult_gen_blind(); - } -} - -/***** ENDOMORPHISH TESTS *****/ -static void test_scalar_split(const secp256k1_scalar* full) { - secp256k1_scalar s, s1, slam; - const unsigned char zero[32] = {0}; - unsigned char tmp[32]; - - secp256k1_scalar_split_lambda(&s1, &slam, full); - - /* check slam*lambda + s1 == full */ - secp256k1_scalar_mul(&s, &secp256k1_const_lambda, &slam); - secp256k1_scalar_add(&s, &s, &s1); - CHECK(secp256k1_scalar_eq(&s, full)); - - /* check that both are <= 128 bits in size */ - if (secp256k1_scalar_is_high(&s1)) { - secp256k1_scalar_negate(&s1, &s1); - } - if (secp256k1_scalar_is_high(&slam)) { - secp256k1_scalar_negate(&slam, &slam); - } - - secp256k1_scalar_get_b32(tmp, &s1); - CHECK(secp256k1_memcmp_var(zero, tmp, 16) == 0); - secp256k1_scalar_get_b32(tmp, &slam); - CHECK(secp256k1_memcmp_var(zero, tmp, 16) == 0); -} - - -static void run_endomorphism_tests(void) { - unsigned i; - static secp256k1_scalar s; - test_scalar_split(&secp256k1_scalar_zero); - test_scalar_split(&secp256k1_scalar_one); - secp256k1_scalar_negate(&s,&secp256k1_scalar_one); - test_scalar_split(&s); - test_scalar_split(&secp256k1_const_lambda); - secp256k1_scalar_add(&s, &secp256k1_const_lambda, &secp256k1_scalar_one); - test_scalar_split(&s); - - for (i = 0; i < 100U * COUNT; ++i) { - secp256k1_scalar full; - testutil_random_scalar_order_test(&full); - test_scalar_split(&full); - } - for (i = 0; i < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++i) { - test_scalar_split(&scalars_near_split_bounds[i]); - } -} - -static void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { - unsigned char pubkeyc[65]; - secp256k1_pubkey pubkey; - secp256k1_ge ge; - size_t pubkeyclen; - - for (pubkeyclen = 3; pubkeyclen <= 65; pubkeyclen++) { - /* Smaller sizes are tested exhaustively elsewhere. */ - int32_t i; - memcpy(&pubkeyc[1], input, 64); - SECP256K1_CHECKMEM_UNDEFINE(&pubkeyc[pubkeyclen], 65 - pubkeyclen); - for (i = 0; i < 256; i++) { - /* Try all type bytes. */ - int xpass; - int ypass; - int ysign; - pubkeyc[0] = i; - /* What sign does this point have? */ - ysign = (input[63] & 1) + 2; - /* For the current type (i) do we expect parsing to work? Handled all of compressed/uncompressed/hybrid. */ - xpass = xvalid && (pubkeyclen == 33) && ((i & 254) == 2); - /* Do we expect a parse and re-serialize as uncompressed to give a matching y? */ - ypass = xvalid && yvalid && ((i & 4) == ((pubkeyclen == 65) << 2)) && - ((i == 4) || ((i & 251) == ysign)) && ((pubkeyclen == 33) || (pubkeyclen == 65)); - if (xpass || ypass) { - /* These cases must parse. */ - unsigned char pubkeyo[65]; - size_t outl; - memset(&pubkey, 0, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - outl = 65; - SECP256K1_CHECKMEM_UNDEFINE(pubkeyo, 65); - CHECK(secp256k1_ec_pubkey_serialize(CTX, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - SECP256K1_CHECKMEM_CHECK(pubkeyo, outl); - CHECK(outl == 33); - CHECK(secp256k1_memcmp_var(&pubkeyo[1], &pubkeyc[1], 32) == 0); - CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0])); - if (ypass) { - /* This test isn't always done because we decode with alternative signs, so the y won't match. */ - CHECK(pubkeyo[0] == ysign); - CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - secp256k1_pubkey_save(&pubkey, &ge); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - outl = 65; - SECP256K1_CHECKMEM_UNDEFINE(pubkeyo, 65); - CHECK(secp256k1_ec_pubkey_serialize(CTX, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); - SECP256K1_CHECKMEM_CHECK(pubkeyo, outl); - CHECK(outl == 65); - CHECK(pubkeyo[0] == 4); - CHECK(secp256k1_memcmp_var(&pubkeyo[1], input, 64) == 0); - } - } else { - /* These cases must fail to parse. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_load(CTX, &ge, &pubkey)); - } - } - } -} - -static void run_ec_pubkey_parse_test(void) { -#define SECP256K1_EC_PARSE_TEST_NVALID (12) - const unsigned char valid[SECP256K1_EC_PARSE_TEST_NVALID][64] = { - { - /* Point with leading and trailing zeros in x and y serialization. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x52, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x64, 0xef, 0xa1, 0x7b, 0x77, 0x61, 0xe1, 0xe4, 0x27, 0x06, 0x98, 0x9f, 0xb4, 0x83, - 0xb8, 0xd2, 0xd4, 0x9b, 0xf7, 0x8f, 0xae, 0x98, 0x03, 0xf0, 0x99, 0xb8, 0x34, 0xed, 0xeb, 0x00 - }, - { - /* Point with x equal to a 3rd root of unity.*/ - 0x7a, 0xe9, 0x6a, 0x2b, 0x65, 0x7c, 0x07, 0x10, 0x6e, 0x64, 0x47, 0x9e, 0xac, 0x34, 0x34, 0xe9, - 0x9c, 0xf0, 0x49, 0x75, 0x12, 0xf5, 0x89, 0x95, 0xc1, 0x39, 0x6c, 0x28, 0x71, 0x95, 0x01, 0xee, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Point with largest x. (1/2) */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, - 0x0e, 0x99, 0x4b, 0x14, 0xea, 0x72, 0xf8, 0xc3, 0xeb, 0x95, 0xc7, 0x1e, 0xf6, 0x92, 0x57, 0x5e, - 0x77, 0x50, 0x58, 0x33, 0x2d, 0x7e, 0x52, 0xd0, 0x99, 0x5c, 0xf8, 0x03, 0x88, 0x71, 0xb6, 0x7d, - }, - { - /* Point with largest x. (2/2) */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, - 0xf1, 0x66, 0xb4, 0xeb, 0x15, 0x8d, 0x07, 0x3c, 0x14, 0x6a, 0x38, 0xe1, 0x09, 0x6d, 0xa8, 0xa1, - 0x88, 0xaf, 0xa7, 0xcc, 0xd2, 0x81, 0xad, 0x2f, 0x66, 0xa3, 0x07, 0xfb, 0x77, 0x8e, 0x45, 0xb2, - }, - { - /* Point with smallest x. (1/2) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Point with smallest x. (2/2) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, - 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, - }, - { - /* Point with largest y. (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with largest y. (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with largest y. (3/3) */ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - }, - { - /* Point with smallest y. (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Point with smallest y. (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Point with smallest y. (3/3) */ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 - } - }; -#define SECP256K1_EC_PARSE_TEST_NXVALID (4) - const unsigned char onlyxvalid[SECP256K1_EC_PARSE_TEST_NXVALID][64] = { - { - /* Valid if y overflow ignored (y = 1 mod p). (1/3) */ - 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, - 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* Valid if y overflow ignored (y = 1 mod p). (2/3) */ - 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, - 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* Valid if y overflow ignored (y = 1 mod p). (3/3)*/ - 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, - 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - }, - { - /* x on curve, y is from y^2 = x^3 + 8. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 - } - }; -#define SECP256K1_EC_PARSE_TEST_NINVALID (7) - const unsigned char invalid[SECP256K1_EC_PARSE_TEST_NINVALID][64] = { - { - /* x is third root of -8, y is -1 * (x^3+7); also on the curve for y^2 = x^3 + 9. */ - 0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, - 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }, - { - /* Valid if x overflow ignored (x = 1 mod p). */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, - 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, - }, - { - /* Valid if x overflow ignored (x = 1 mod p). */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, - 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, - 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, - }, - { - /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - 0xf4, 0x84, 0x14, 0x5c, 0xb0, 0x14, 0x9b, 0x82, 0x5d, 0xff, 0x41, 0x2f, 0xa0, 0x52, 0xa8, 0x3f, - 0xcb, 0x72, 0xdb, 0x61, 0xd5, 0x6f, 0x37, 0x70, 0xce, 0x06, 0x6b, 0x73, 0x49, 0xa2, 0xaa, 0x28, - }, - { - /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, - 0x0b, 0x7b, 0xeb, 0xa3, 0x4f, 0xeb, 0x64, 0x7d, 0xa2, 0x00, 0xbe, 0xd0, 0x5f, 0xad, 0x57, 0xc0, - 0x34, 0x8d, 0x24, 0x9e, 0x2a, 0x90, 0xc8, 0x8f, 0x31, 0xf9, 0x94, 0x8b, 0xb6, 0x5d, 0x52, 0x07, - }, - { - /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8f, 0x53, 0x7e, 0xef, 0xdf, 0xc1, 0x60, 0x6a, 0x07, 0x27, 0xcd, 0x69, 0xb4, 0xa7, 0x33, 0x3d, - 0x38, 0xed, 0x44, 0xe3, 0x93, 0x2a, 0x71, 0x79, 0xee, 0xcb, 0x4b, 0x6f, 0xba, 0x93, 0x60, 0xdc, - }, - { - /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0xac, 0x81, 0x10, 0x20, 0x3e, 0x9f, 0x95, 0xf8, 0xd8, 0x32, 0x96, 0x4b, 0x58, 0xcc, 0xc2, - 0xc7, 0x12, 0xbb, 0x1c, 0x6c, 0xd5, 0x8e, 0x86, 0x11, 0x34, 0xb4, 0x8f, 0x45, 0x6c, 0x9b, 0x53 - } - }; - const unsigned char pubkeyc[66] = { - /* Serialization of G. */ - 0x04, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, - 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, - 0x98, 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, - 0xA8, 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, - 0xB8, 0x00 - }; - unsigned char sout[65]; - unsigned char shortkey[2] = { 0 }; - secp256k1_ge ge; - secp256k1_pubkey pubkey; - size_t len; - int32_t i; - - /* Nothing should be reading this far into pubkeyc. */ - SECP256K1_CHECKMEM_UNDEFINE(&pubkeyc[65], 1); - /* Zero length claimed, fail, zeroize, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(shortkey, 2); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, shortkey, 0) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_load(CTX, &ge, &pubkey)); - /* Length one claimed, fail, zeroize, no illegal arg error. */ - for (i = 0; i < 256 ; i++) { - memset(&pubkey, 0xfe, sizeof(pubkey)); - shortkey[0] = i; - SECP256K1_CHECKMEM_UNDEFINE(&shortkey[1], 1); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, shortkey, 1) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_load(CTX, &ge, &pubkey)); - } - /* Length two claimed, fail, zeroize, no illegal arg error. */ - for (i = 0; i < 65536 ; i++) { - memset(&pubkey, 0xfe, sizeof(pubkey)); - shortkey[0] = i & 255; - shortkey[1] = i >> 8; - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, shortkey, 2) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_load(CTX, &ge, &pubkey)); - } - memset(&pubkey, 0xfe, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - /* 33 bytes claimed on otherwise valid input starting with 0x04, fail, zeroize output, no illegal arg error. */ - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 33) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_load(CTX, &ge, &pubkey)); - /* NULL pubkey, illegal arg error. Pubkey isn't rewritten before this step, since it's NULL into the parser. */ - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_parse(CTX, NULL, pubkeyc, 65)); - /* NULL input string. Illegal arg and zeroize output. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_parse(CTX, &pubkey, NULL, 65)); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_load(CTX, &ge, &pubkey)); - /* 64 bytes claimed on input starting with 0x04, fail, zeroize output, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 64) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_load(CTX, &ge, &pubkey)); - /* 66 bytes claimed, fail, zeroize output, no illegal arg error. */ - memset(&pubkey, 0xfe, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 66) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_load(CTX, &ge, &pubkey)); - /* Valid parse. */ - memset(&pubkey, 0, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 65) == 1); - CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, pubkeyc, 65) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&ge, sizeof(ge)); - CHECK(secp256k1_pubkey_load(CTX, &ge, &pubkey) == 1); - SECP256K1_CHECKMEM_CHECK(&ge.x, sizeof(ge.x)); - SECP256K1_CHECKMEM_CHECK(&ge.y, sizeof(ge.y)); - SECP256K1_CHECKMEM_CHECK(&ge.infinity, sizeof(ge.infinity)); - CHECK(secp256k1_ge_eq_var(&ge, &secp256k1_ge_const_g)); - /* secp256k1_ec_pubkey_serialize illegal args. */ - len = 65; - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_serialize(CTX, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED)); - CHECK(len == 0); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_serialize(CTX, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED)); - len = 65; - SECP256K1_CHECKMEM_UNDEFINE(sout, 65); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_serialize(CTX, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED)); - SECP256K1_CHECKMEM_CHECK(sout, 65); - CHECK(len == 0); - len = 65; - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_serialize(CTX, sout, &len, &pubkey, ~0)); - CHECK(len == 0); - len = 65; - SECP256K1_CHECKMEM_UNDEFINE(sout, 65); - CHECK(secp256k1_ec_pubkey_serialize(CTX, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); - SECP256K1_CHECKMEM_CHECK(sout, 65); - CHECK(len == 65); - /* Multiple illegal args. Should still set arg error only once. */ - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_parse(CTX, NULL, NULL, 65)); - /* Try a bunch of prefabbed points with all possible encodings. */ - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NVALID; i++) { - ec_pubkey_parse_pointtest(valid[i], 1, 1); - } - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NXVALID; i++) { - ec_pubkey_parse_pointtest(onlyxvalid[i], 1, 0); - } - for (i = 0; i < SECP256K1_EC_PARSE_TEST_NINVALID; i++) { - ec_pubkey_parse_pointtest(invalid[i], 0, 0); - } -} - -static void run_eckey_edge_case_test(void) { - const unsigned char orderc[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 - }; - const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00}; - unsigned char ctmp[33]; - unsigned char ctmp2[33]; - secp256k1_pubkey pubkey; - secp256k1_pubkey pubkey2; - secp256k1_pubkey pubkey_one; - secp256k1_pubkey pubkey_negone; - const secp256k1_pubkey *pubkeys[3]; - size_t len; - /* Group order is too large, reject. */ - CHECK(secp256k1_ec_seckey_verify(CTX, orderc) == 0); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, orderc) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* Maximum value is too large, reject. */ - memset(ctmp, 255, 32); - CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* Zero is too small, reject. */ - memset(ctmp, 0, 32); - CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* One must be accepted. */ - ctmp[31] = 0x01; - CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - pubkey_one = pubkey; - /* Group order + 1 is too large, reject. */ - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x42; - CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 0); - memset(&pubkey, 1, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* -1 must be accepted. */ - ctmp[31] = 0x40; - CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 1); - memset(&pubkey, 0, sizeof(pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - pubkey_negone = pubkey; - /* Tweak of zero leaves the value unchanged. */ - memset(ctmp2, 0, 32); - CHECK(secp256k1_ec_seckey_tweak_add(CTX, ctmp, ctmp2) == 1); - CHECK(secp256k1_memcmp_var(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); - memcpy(&pubkey2, &pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); - CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Multiply tweak of zero zeroizes the output. */ - CHECK(secp256k1_ec_seckey_tweak_mul(CTX, ctmp, ctmp2) == 0); - CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); - CHECK(secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey, ctmp2) == 0); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing - seckey, the seckey is zeroized. */ - memcpy(ctmp, orderc, 32); - memset(ctmp2, 0, 32); - ctmp2[31] = 0x01; - CHECK(secp256k1_ec_seckey_verify(CTX, ctmp2) == 1); - CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 0); - CHECK(secp256k1_ec_seckey_tweak_add(CTX, ctmp, ctmp2) == 0); - CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); - memcpy(ctmp, orderc, 32); - CHECK(secp256k1_ec_seckey_tweak_mul(CTX, ctmp, ctmp2) == 0); - CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); - /* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing - tweak, the seckey is zeroized. */ - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - CHECK(secp256k1_ec_seckey_tweak_add(CTX, ctmp, orderc) == 0); - CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - CHECK(secp256k1_ec_seckey_tweak_mul(CTX, ctmp, orderc) == 0); - CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - /* If pubkey_tweak_add or pubkey_tweak_mul are called with an overflowing - tweak, the pubkey is zeroized. */ - CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, orderc) == 0); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey, orderc) == 0); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* If the resulting key in secp256k1_ec_seckey_tweak_add and - * secp256k1_ec_pubkey_tweak_add is 0 the functions fail and in the latter - * case the pubkey is zeroized. */ - memcpy(ctmp, orderc, 32); - ctmp[31] = 0x40; - memset(ctmp2, 0, 32); - ctmp2[31] = 1; - CHECK(secp256k1_ec_seckey_tweak_add(CTX, ctmp2, ctmp) == 0); - CHECK(secp256k1_memcmp_var(zeros, ctmp2, 32) == 0); - ctmp2[31] = 1; - CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 0); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* Tweak computation wraps and results in a key of 1. */ - ctmp2[31] = 2; - CHECK(secp256k1_ec_seckey_tweak_add(CTX, ctmp2, ctmp) == 1); - CHECK(secp256k1_memcmp_var(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); - ctmp2[31] = 2; - CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); - ctmp2[31] = 1; - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey2, ctmp2) == 1); - CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Tweak mul * 2 = 1+1. */ - CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); - ctmp2[31] = 2; - CHECK(secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey2, ctmp2) == 1); - CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - /* Zeroize pubkey on parse error. */ - memset(&pubkey, 0, 32); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); - memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - memset(&pubkey2, 0, 32); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey2, ctmp2)); - CHECK(secp256k1_memcmp_var(&pubkey2, zeros, sizeof(pubkey2)) == 0); - /* Plain argument errors. */ - CHECK(secp256k1_ec_seckey_verify(CTX, ctmp) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ec_seckey_verify(CTX, NULL)); - memset(ctmp2, 0, 32); - ctmp2[31] = 4; - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_tweak_add(CTX, NULL, ctmp2)); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, NULL)); - memset(ctmp2, 0, 32); - ctmp2[31] = 4; - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_tweak_mul(CTX, NULL, ctmp2)); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey, NULL)); - memset(ctmp2, 0, 32); - CHECK_ILLEGAL(CTX, secp256k1_ec_seckey_tweak_add(CTX, NULL, ctmp2)); - CHECK_ILLEGAL(CTX, secp256k1_ec_seckey_tweak_add(CTX, ctmp, NULL)); - memset(ctmp2, 0, 32); - ctmp2[31] = 1; - CHECK_ILLEGAL(CTX, secp256k1_ec_seckey_tweak_mul(CTX, NULL, ctmp2)); - CHECK_ILLEGAL(CTX, secp256k1_ec_seckey_tweak_mul(CTX, ctmp, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_create(CTX, NULL, ctmp)); - memset(&pubkey, 1, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_create(CTX, &pubkey, NULL)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* secp256k1_ec_pubkey_combine tests. */ - pubkeys[0] = &pubkey_one; - SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[0], sizeof(secp256k1_pubkey *)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[1], sizeof(secp256k1_pubkey *)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[2], sizeof(secp256k1_pubkey *)); - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 0)); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_combine(CTX, NULL, pubkeys, 1)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_combine(CTX, &pubkey, NULL, 1)); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - pubkeys[0] = &pubkey_negone; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 1) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - len = 33; - CHECK(secp256k1_ec_pubkey_serialize(CTX, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - CHECK(secp256k1_ec_pubkey_serialize(CTX, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); - CHECK(secp256k1_memcmp_var(ctmp, ctmp2, 33) == 0); - /* Result is infinity. */ - pubkeys[0] = &pubkey_one; - pubkeys[1] = &pubkey_negone; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 2) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* Passes through infinity but comes out one. */ - pubkeys[2] = &pubkey_one; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 3) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); - len = 33; - CHECK(secp256k1_ec_pubkey_serialize(CTX, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - CHECK(secp256k1_ec_pubkey_serialize(CTX, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); - CHECK(secp256k1_memcmp_var(ctmp, ctmp2, 33) == 0); - /* Adds to two. */ - pubkeys[1] = &pubkey_one; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 2) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); -} - -static void run_eckey_negate_test(void) { - unsigned char seckey[32]; - unsigned char seckey_tmp[32]; - - testutil_random_scalar_order_b32(seckey); - memcpy(seckey_tmp, seckey, 32); - - /* Verify negation changes the key and changes it back */ - CHECK(secp256k1_ec_seckey_negate(CTX, seckey) == 1); - CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) != 0); - CHECK(secp256k1_ec_seckey_negate(CTX, seckey) == 1); - CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); - - /* Check that privkey alias gives same result */ - CHECK(secp256k1_ec_seckey_negate(CTX, seckey) == 1); - CHECK(secp256k1_ec_privkey_negate(CTX, seckey_tmp) == 1); - CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); - - /* Negating all 0s fails */ - memset(seckey, 0, 32); - memset(seckey_tmp, 0, 32); - CHECK(secp256k1_ec_seckey_negate(CTX, seckey) == 0); - /* Check that seckey is not modified */ - CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); - - /* Negating an overflowing seckey fails and the seckey is zeroed. In this - * test, the seckey has 16 random bytes to ensure that ec_seckey_negate - * doesn't just set seckey to a constant value in case of failure. */ - testutil_random_scalar_order_b32(seckey); - memset(seckey, 0xFF, 16); - memset(seckey_tmp, 0, 32); - CHECK(secp256k1_ec_seckey_negate(CTX, seckey) == 0); - CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); -} - -static void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { - secp256k1_scalar nonce; - do { - testutil_random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&CTX->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); -} - -static void test_ecdsa_sign_verify(void) { - secp256k1_gej pubj; - secp256k1_ge pub; - secp256k1_scalar one; - secp256k1_scalar msg, key; - secp256k1_scalar sigr, sigs; - int getrec; - int recid; - testutil_random_scalar_order_test(&msg); - testutil_random_scalar_order_test(&key); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); - getrec = testrand_bits(1); - /* The specific way in which this conditional is written sidesteps a potential bug in clang. - See the commit messages of the commit that introduced this comment for details. */ - if (getrec) { - random_sign(&sigr, &sigs, &key, &msg, &recid); - CHECK(recid >= 0 && recid < 4); - } else { - random_sign(&sigr, &sigs, &key, &msg, NULL); - } - CHECK(secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); - secp256k1_scalar_set_int(&one, 1); - secp256k1_scalar_add(&msg, &msg, &one); - CHECK(!secp256k1_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); -} - -static void run_ecdsa_sign_verify(void) { - int i; - for (i = 0; i < 10*COUNT; i++) { - test_ecdsa_sign_verify(); - } -} - -/** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */ -static int precomputed_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - (void)msg32; - (void)key32; - (void)algo16; - memcpy(nonce32, data, 32); - return (counter == 0); -} - -static int nonce_function_test_fail(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - /* Dummy nonce generator that has a fatal error on the first counter value. */ - if (counter == 0) { - return 0; - } - return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 1); -} - -static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { - /* Dummy nonce generator that produces unacceptable nonces for the first several counter values. */ - if (counter < 3) { - memset(nonce32, counter==0 ? 0 : 255, 32); - if (counter == 2) { - nonce32[31]--; - } - return 1; - } - if (counter < 5) { - static const unsigned char order[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 - }; - memcpy(nonce32, order, 32); - if (counter == 4) { - nonce32[31]++; - } - return 1; - } - /* Retry rate of 6979 is negligible esp. as we only call this in deterministic tests. */ - /* If someone does fine a case where it retries for secp256k1, we'd like to know. */ - if (counter > 5) { - return 0; - } - return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); -} - -static int is_empty_signature(const secp256k1_ecdsa_signature *sig) { - static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0}; - return secp256k1_memcmp_var(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0; -} - -static void test_ecdsa_end_to_end(void) { - unsigned char extra[32] = {0x00}; - unsigned char privkey[32]; - unsigned char message[32]; - unsigned char privkey2[32]; - secp256k1_ecdsa_signature signature[6]; - secp256k1_scalar r, s; - unsigned char sig[74]; - size_t siglen = 74; - unsigned char pubkeyc[65]; - size_t pubkeyclen = 65; - secp256k1_pubkey pubkey; - secp256k1_pubkey pubkey_tmp; - unsigned char seckey[300]; - size_t seckeylen = 300; - - /* Generate a random key and message. */ - { - secp256k1_scalar msg, key; - testutil_random_scalar_order_test(&msg); - testutil_random_scalar_order_test(&key); - secp256k1_scalar_get_b32(privkey, &key); - secp256k1_scalar_get_b32(message, &msg); - } - - /* Construct and verify corresponding public key. */ - CHECK(secp256k1_ec_seckey_verify(CTX, privkey) == 1); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, privkey) == 1); - - /* Verify exporting and importing public key. */ - CHECK(secp256k1_ec_pubkey_serialize(CTX, pubkeyc, &pubkeyclen, &pubkey, testrand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); - memset(&pubkey, 0, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 1); - - /* Verify negation changes the key and changes it back */ - memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_negate(CTX, &pubkey_tmp) == 1); - CHECK(secp256k1_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); - CHECK(secp256k1_ec_pubkey_negate(CTX, &pubkey_tmp) == 1); - CHECK(secp256k1_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); - - /* Verify private key import and export. */ - CHECK(ec_privkey_export_der(CTX, seckey, &seckeylen, privkey, testrand_bits(1) == 1)); - CHECK(ec_privkey_import_der(CTX, privkey2, seckey, seckeylen) == 1); - CHECK(secp256k1_memcmp_var(privkey, privkey2, 32) == 0); - - /* Optionally tweak the keys using addition. */ - if (testrand_int(3) == 0) { - int ret1; - int ret2; - int ret3; - unsigned char rnd[32]; - unsigned char privkey_tmp[32]; - secp256k1_pubkey pubkey2; - testrand256_test(rnd); - memcpy(privkey_tmp, privkey, 32); - ret1 = secp256k1_ec_seckey_tweak_add(CTX, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, rnd); - /* Check that privkey alias gives same result */ - ret3 = secp256k1_ec_privkey_tweak_add(CTX, privkey_tmp, rnd); - CHECK(ret1 == ret2); - CHECK(ret2 == ret3); - if (ret1 == 0) { - return; - } - CHECK(secp256k1_memcmp_var(privkey, privkey_tmp, 32) == 0); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey2, privkey) == 1); - CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - } - - /* Optionally tweak the keys using multiplication. */ - if (testrand_int(3) == 0) { - int ret1; - int ret2; - int ret3; - unsigned char rnd[32]; - unsigned char privkey_tmp[32]; - secp256k1_pubkey pubkey2; - testrand256_test(rnd); - memcpy(privkey_tmp, privkey, 32); - ret1 = secp256k1_ec_seckey_tweak_mul(CTX, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey, rnd); - /* Check that privkey alias gives same result */ - ret3 = secp256k1_ec_privkey_tweak_mul(CTX, privkey_tmp, rnd); - CHECK(ret1 == ret2); - CHECK(ret2 == ret3); - if (ret1 == 0) { - return; - } - CHECK(secp256k1_memcmp_var(privkey, privkey_tmp, 32) == 0); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey2, privkey) == 1); - CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); - } - - /* Sign. */ - CHECK(secp256k1_ecdsa_sign(CTX, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(CTX, &signature[4], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(CTX, &signature[1], message, privkey, NULL, extra) == 1); - extra[31] = 1; - CHECK(secp256k1_ecdsa_sign(CTX, &signature[2], message, privkey, NULL, extra) == 1); - extra[31] = 0; - extra[0] = 1; - CHECK(secp256k1_ecdsa_sign(CTX, &signature[3], message, privkey, NULL, extra) == 1); - CHECK(secp256k1_memcmp_var(&signature[0], &signature[4], sizeof(signature[0])) == 0); - CHECK(secp256k1_memcmp_var(&signature[0], &signature[1], sizeof(signature[0])) != 0); - CHECK(secp256k1_memcmp_var(&signature[0], &signature[2], sizeof(signature[0])) != 0); - CHECK(secp256k1_memcmp_var(&signature[0], &signature[3], sizeof(signature[0])) != 0); - CHECK(secp256k1_memcmp_var(&signature[1], &signature[2], sizeof(signature[0])) != 0); - CHECK(secp256k1_memcmp_var(&signature[1], &signature[3], sizeof(signature[0])) != 0); - CHECK(secp256k1_memcmp_var(&signature[2], &signature[3], sizeof(signature[0])) != 0); - /* Verify. */ - CHECK(secp256k1_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[1], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[2], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[3], message, &pubkey) == 1); - /* Test lower-S form, malleate, verify and fail, test again, malleate again */ - CHECK(!secp256k1_ecdsa_signature_normalize(CTX, NULL, &signature[0])); - secp256k1_ecdsa_signature_load(CTX, &r, &s, &signature[0]); - secp256k1_scalar_negate(&s, &s); - secp256k1_ecdsa_signature_save(&signature[5], &r, &s); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 0); - CHECK(secp256k1_ecdsa_signature_normalize(CTX, NULL, &signature[5])); - CHECK(secp256k1_ecdsa_signature_normalize(CTX, &signature[5], &signature[5])); - CHECK(!secp256k1_ecdsa_signature_normalize(CTX, NULL, &signature[5])); - CHECK(!secp256k1_ecdsa_signature_normalize(CTX, &signature[5], &signature[5])); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 1); - secp256k1_scalar_negate(&s, &s); - secp256k1_ecdsa_signature_save(&signature[5], &r, &s); - CHECK(!secp256k1_ecdsa_signature_normalize(CTX, NULL, &signature[5])); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 1); - CHECK(secp256k1_memcmp_var(&signature[5], &signature[0], 64) == 0); - - /* Serialize/parse DER and verify again */ - CHECK(secp256k1_ecdsa_signature_serialize_der(CTX, sig, &siglen, &signature[0]) == 1); - memset(&signature[0], 0, sizeof(signature[0])); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &signature[0], sig, siglen) == 1); - CHECK(secp256k1_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 1); - /* Serialize/destroy/parse DER and verify again. */ - siglen = 74; - CHECK(secp256k1_ecdsa_signature_serialize_der(CTX, sig, &siglen, &signature[0]) == 1); - sig[testrand_int(siglen)] += 1 + testrand_int(255); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &signature[0], sig, siglen) == 0 || - secp256k1_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 0); -} - -static void test_random_pubkeys(void) { - secp256k1_ge elem; - secp256k1_ge elem2; - unsigned char in[65]; - /* Generate some randomly sized pubkeys. */ - size_t len = testrand_bits(2) == 0 ? 65 : 33; - if (testrand_bits(2) == 0) { - len = testrand_bits(6); - } - if (len == 65) { - in[0] = testrand_bits(1) ? 4 : (testrand_bits(1) ? 6 : 7); - } else { - in[0] = testrand_bits(1) ? 2 : 3; - } - if (testrand_bits(3) == 0) { - in[0] = testrand_bits(8); - } - if (len > 1) { - testrand256(&in[1]); - } - if (len > 33) { - testrand256(&in[33]); - } - if (secp256k1_eckey_pubkey_parse(&elem, in, len)) { - unsigned char out[65]; - unsigned char firstb; - int res; - size_t size = len; - firstb = in[0]; - /* If the pubkey can be parsed, it should round-trip... */ - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); - CHECK(size == len); - CHECK(secp256k1_memcmp_var(&in[1], &out[1], len-1) == 0); - /* ... except for the type of hybrid inputs. */ - if ((in[0] != 6) && (in[0] != 7)) { - CHECK(in[0] == out[0]); - } - size = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); - CHECK(size == 65); - CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); - CHECK(secp256k1_ge_eq_var(&elem2, &elem)); - /* Check that the X9.62 hybrid type is checked. */ - in[0] = testrand_bits(1) ? 6 : 7; - res = secp256k1_eckey_pubkey_parse(&elem2, in, size); - if (firstb == 2 || firstb == 3) { - if (in[0] == firstb + 4) { - CHECK(res); - } else { - CHECK(!res); - } - } - if (res) { - CHECK(secp256k1_ge_eq_var(&elem, &elem2)); - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); - CHECK(secp256k1_memcmp_var(&in[1], &out[1], 64) == 0); - } - } -} - -static void run_pubkey_comparison(void) { - unsigned char pk1_ser[33] = { - 0x02, - 0x58, 0x84, 0xb3, 0xa2, 0x4b, 0x97, 0x37, 0x88, 0x92, 0x38, 0xa6, 0x26, 0x62, 0x52, 0x35, 0x11, - 0xd0, 0x9a, 0xa1, 0x1b, 0x80, 0x0b, 0x5e, 0x93, 0x80, 0x26, 0x11, 0xef, 0x67, 0x4b, 0xd9, 0x23 - }; - const unsigned char pk2_ser[33] = { - 0x02, - 0xde, 0x36, 0x0e, 0x87, 0x59, 0x8f, 0x3c, 0x01, 0x36, 0x2a, 0x2a, 0xb8, 0xc6, 0xf4, 0x5e, 0x4d, - 0xb2, 0xc2, 0xd5, 0x03, 0xa7, 0xf9, 0xf1, 0x4f, 0xa8, 0xfa, 0x95, 0xa8, 0xe9, 0x69, 0x76, 0x1c - }; - secp256k1_pubkey pk1; - secp256k1_pubkey pk2; - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pk1, pk1_ser, sizeof(pk1_ser)) == 1); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pk2, pk2_ser, sizeof(pk2_ser)) == 1); - - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_ec_pubkey_cmp(CTX, NULL, &pk2) < 0)); - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk1, NULL) > 0)); - CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk1, &pk2) < 0); - CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk2, &pk1) > 0); - CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk1, &pk1) == 0); - CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk2, &pk2) == 0); - { - secp256k1_pubkey pk_tmp; - memset(&pk_tmp, 0, sizeof(pk_tmp)); /* illegal pubkey */ - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk_tmp, &pk2) < 0)); - { - int32_t ecount = 0; - secp256k1_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); - CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk_tmp, &pk_tmp) == 0); - CHECK(ecount == 2); - secp256k1_context_set_illegal_callback(CTX, NULL, NULL); - } - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk2, &pk_tmp) > 0)); - } - - /* Make pk2 the same as pk1 but with 3 rather than 2. Note that in - * an uncompressed encoding, these would have the opposite ordering */ - pk1_ser[0] = 3; - CHECK(secp256k1_ec_pubkey_parse(CTX, &pk2, pk1_ser, sizeof(pk1_ser)) == 1); - CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk1, &pk2) < 0); - CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk2, &pk1) > 0); -} - -static void test_sort_helper(secp256k1_pubkey *pk, size_t *pk_order, size_t n_pk) { - size_t i; - const secp256k1_pubkey *pk_test[5]; - - for (i = 0; i < n_pk; i++) { - pk_test[i] = &pk[pk_order[i]]; - } - secp256k1_ec_pubkey_sort(CTX, pk_test, n_pk); - for (i = 0; i < n_pk; i++) { - CHECK(secp256k1_memcmp_var(pk_test[i], &pk[i], sizeof(*pk_test[i])) == 0); - } -} - -static void permute(size_t *arr, size_t n) { - size_t i; - for (i = n - 1; i >= 1; i--) { - size_t tmp, j; - j = testrand_int(i + 1); - tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } -} - -static void test_sort_api(void) { - secp256k1_pubkey pks[2]; - const secp256k1_pubkey *pks_ptr[2]; - - pks_ptr[0] = &pks[0]; - pks_ptr[1] = &pks[1]; - - testutil_random_pubkey_test(&pks[0]); - testutil_random_pubkey_test(&pks[1]); - - CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_sort(CTX, NULL, 2)); - CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 0) == 1); - /* Test illegal public keys */ - memset(&pks[0], 0, sizeof(pks[0])); - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2) == 1)); - memset(&pks[1], 0, sizeof(pks[1])); - { - int32_t ecount = 0; - secp256k1_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); - CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2) == 1); - CHECK(ecount == 2); - secp256k1_context_set_illegal_callback(CTX, NULL, NULL); - } -} - -static void test_sort(void) { - secp256k1_pubkey pk[5]; - unsigned char pk_ser[5][33] = { - { 0x02, 0x08 }, - { 0x02, 0x0b }, - { 0x02, 0x0c }, - { 0x03, 0x05 }, - { 0x03, 0x0a }, - }; - int i; - size_t pk_order[5] = { 0, 1, 2, 3, 4 }; - - for (i = 0; i < 5; i++) { - CHECK(secp256k1_ec_pubkey_parse(CTX, &pk[i], pk_ser[i], sizeof(pk_ser[i]))); - } - - permute(pk_order, 1); - test_sort_helper(pk, pk_order, 1); - permute(pk_order, 2); - test_sort_helper(pk, pk_order, 2); - permute(pk_order, 3); - test_sort_helper(pk, pk_order, 3); - for (i = 0; i < COUNT; i++) { - permute(pk_order, 4); - test_sort_helper(pk, pk_order, 4); - } - for (i = 0; i < COUNT; i++) { - permute(pk_order, 5); - test_sort_helper(pk, pk_order, 5); - } - /* Check that sorting also works for random pubkeys */ - for (i = 0; i < COUNT; i++) { - int j; - const secp256k1_pubkey *pk_ptr[5]; - for (j = 0; j < 5; j++) { - testutil_random_pubkey_test(&pk[j]); - pk_ptr[j] = &pk[j]; - } - secp256k1_ec_pubkey_sort(CTX, pk_ptr, 5); - for (j = 1; j < 5; j++) { - CHECK(secp256k1_ec_pubkey_sort_cmp(&pk_ptr[j - 1], &pk_ptr[j], CTX) <= 0); - } - } -} - -/* Test vectors from BIP-MuSig2 */ -static void test_sort_vectors(void) { - enum { N_PUBKEYS = 6 }; - unsigned char pk_ser[N_PUBKEYS][33] = { - { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, - 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, - 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 }, - { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, - 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, - 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x03, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, - 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, - 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }, - { 0x02, 0x35, 0x90, 0xA9, 0x4E, 0x76, 0x8F, 0x8E, 0x18, 0x15, 0xC2, - 0xF2, 0x4B, 0x4D, 0x80, 0xA8, 0xE3, 0x14, 0x93, 0x16, 0xC3, 0x51, - 0x8C, 0xE7, 0xB7, 0xAD, 0x33, 0x83, 0x68, 0xD0, 0x38, 0xCA, 0x66 }, - { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, - 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, - 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xFF }, - { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, - 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, - 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 } - }; - secp256k1_pubkey pubkeys[N_PUBKEYS]; - secp256k1_pubkey *sorted[N_PUBKEYS]; - const secp256k1_pubkey *pks_ptr[N_PUBKEYS]; - int i; - - sorted[0] = &pubkeys[3]; - sorted[1] = &pubkeys[0]; - sorted[2] = &pubkeys[0]; - sorted[3] = &pubkeys[4]; - sorted[4] = &pubkeys[1]; - sorted[5] = &pubkeys[2]; - - for (i = 0; i < N_PUBKEYS; i++) { - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkeys[i], pk_ser[i], sizeof(pk_ser[i]))); - pks_ptr[i] = &pubkeys[i]; - } - CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, N_PUBKEYS) == 1); - for (i = 0; i < N_PUBKEYS; i++) { - CHECK(secp256k1_memcmp_var(pks_ptr[i], sorted[i], sizeof(secp256k1_pubkey)) == 0); - } -} - -static void run_pubkey_sort(void) { - test_sort_api(); - test_sort(); - test_sort_vectors(); -} - - -static void run_random_pubkeys(void) { - int i; - for (i = 0; i < 10*COUNT; i++) { - test_random_pubkeys(); - } -} - -static void run_ecdsa_end_to_end(void) { - int i; - for (i = 0; i < 64*COUNT; i++) { - test_ecdsa_end_to_end(); - } -} - -static int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) { - static const unsigned char zeroes[32] = {0}; - - int ret = 0; - - secp256k1_ecdsa_signature sig_der; - unsigned char roundtrip_der[2048]; - unsigned char compact_der[64]; - size_t len_der = 2048; - int parsed_der = 0, valid_der = 0, roundtrips_der = 0; - - secp256k1_ecdsa_signature sig_der_lax; - unsigned char roundtrip_der_lax[2048]; - unsigned char compact_der_lax[64]; - size_t len_der_lax = 2048; - int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0; - - parsed_der = secp256k1_ecdsa_signature_parse_der(CTX, &sig_der, sig, siglen); - if (parsed_der) { - ret |= (!secp256k1_ecdsa_signature_serialize_compact(CTX, compact_der, &sig_der)) << 0; - valid_der = (secp256k1_memcmp_var(compact_der, zeroes, 32) != 0) && (secp256k1_memcmp_var(compact_der + 32, zeroes, 32) != 0); - } - if (valid_der) { - ret |= (!secp256k1_ecdsa_signature_serialize_der(CTX, roundtrip_der, &len_der, &sig_der)) << 1; - roundtrips_der = (len_der == siglen) && secp256k1_memcmp_var(roundtrip_der, sig, siglen) == 0; - } - - parsed_der_lax = ecdsa_signature_parse_der_lax(CTX, &sig_der_lax, sig, siglen); - if (parsed_der_lax) { - ret |= (!secp256k1_ecdsa_signature_serialize_compact(CTX, compact_der_lax, &sig_der_lax)) << 10; - valid_der_lax = (secp256k1_memcmp_var(compact_der_lax, zeroes, 32) != 0) && (secp256k1_memcmp_var(compact_der_lax + 32, zeroes, 32) != 0); - } - if (valid_der_lax) { - ret |= (!secp256k1_ecdsa_signature_serialize_der(CTX, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; - roundtrips_der_lax = (len_der_lax == siglen) && secp256k1_memcmp_var(roundtrip_der_lax, sig, siglen) == 0; - } - - if (certainly_der) { - ret |= (!parsed_der) << 2; - } - if (certainly_not_der) { - ret |= (parsed_der) << 17; - } - if (valid_der) { - ret |= (!roundtrips_der) << 3; - } - - if (valid_der) { - ret |= (!roundtrips_der_lax) << 12; - ret |= (len_der != len_der_lax) << 13; - ret |= ((len_der != len_der_lax) || (secp256k1_memcmp_var(roundtrip_der_lax, roundtrip_der, len_der) != 0)) << 14; - } - ret |= (roundtrips_der != roundtrips_der_lax) << 15; - if (parsed_der) { - ret |= (!parsed_der_lax) << 16; - } - - return ret; -} - -static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { - size_t i; - for (i = 0; i < ptrlen; i++) { - int shift = ptrlen - 1 - i; - if (shift >= 4) { - ptr[i] = 0; - } else { - ptr[i] = (val >> shift) & 0xFF; - } - } -} - -static void damage_array(unsigned char *sig, size_t *len) { - int pos; - int action = testrand_bits(3); - if (action < 1 && *len > 3) { - /* Delete a byte. */ - pos = testrand_int(*len); - memmove(sig + pos, sig + pos + 1, *len - pos - 1); - (*len)--; - return; - } else if (action < 2 && *len < 2048) { - /* Insert a byte. */ - pos = testrand_int(1 + *len); - memmove(sig + pos + 1, sig + pos, *len - pos); - sig[pos] = testrand_bits(8); - (*len)++; - return; - } else if (action < 4) { - /* Modify a byte. */ - sig[testrand_int(*len)] += 1 + testrand_int(255); - return; - } else { /* action < 8 */ - /* Modify a bit. */ - sig[testrand_int(*len)] ^= 1 << testrand_bits(3); - return; - } -} - -static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly_der, int* certainly_not_der) { - int der; - int nlow[2], nlen[2], nlenlen[2], nhbit[2], nhbyte[2], nzlen[2]; - size_t tlen, elen, glen; - int indet; - int n; - - *len = 0; - der = testrand_bits(2) == 0; - *certainly_der = der; - *certainly_not_der = 0; - indet = der ? 0 : testrand_int(10) == 0; - - for (n = 0; n < 2; n++) { - /* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */ - nlow[n] = der ? 1 : (testrand_bits(3) != 0); - /* The length of the number in bytes (the first byte of which will always be nonzero) */ - nlen[n] = nlow[n] ? testrand_int(33) : 32 + testrand_int(200) * testrand_bits(3) / 8; - CHECK(nlen[n] <= 232); - /* The top bit of the number. */ - nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : testrand_bits(1)); - /* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */ - nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + testrand_bits(7) : 1 + testrand_int(127)); - /* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */ - nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? testrand_int(3) : testrand_int(300 - nlen[n]) * testrand_bits(3) / 8); - if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) { - *certainly_not_der = 1; - } - CHECK(nlen[n] + nzlen[n] <= 300); - /* The length of the length descriptor for the number. 0 means short encoding, anything else is long encoding. */ - nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2); - if (!der) { - /* nlenlen[n] max 127 bytes */ - int add = testrand_int(127 - nlenlen[n]) * testrand_bits(4) * testrand_bits(4) / 256; - nlenlen[n] += add; - if (add != 0) { - *certainly_not_der = 1; - } - } - CHECK(nlen[n] + nzlen[n] + nlenlen[n] <= 427); - } - - /* The total length of the data to go, so far */ - tlen = 2 + nlenlen[0] + nlen[0] + nzlen[0] + 2 + nlenlen[1] + nlen[1] + nzlen[1]; - CHECK(tlen <= 856); - - /* The length of the garbage inside the tuple. */ - elen = (der || indet) ? 0 : testrand_int(980 - tlen) * testrand_bits(3) / 8; - if (elen != 0) { - *certainly_not_der = 1; - } - tlen += elen; - CHECK(tlen <= 980); - - /* The length of the garbage after the end of the tuple. */ - glen = der ? 0 : testrand_int(990 - tlen) * testrand_bits(3) / 8; - if (glen != 0) { - *certainly_not_der = 1; - } - CHECK(tlen + glen <= 990); - - /* Write the tuple header. */ - sig[(*len)++] = 0x30; - if (indet) { - /* Indeterminate length */ - sig[(*len)++] = 0x80; - *certainly_not_der = 1; - } else { - int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2); - if (!der) { - int add = testrand_int(127 - tlenlen) * testrand_bits(4) * testrand_bits(4) / 256; - tlenlen += add; - if (add != 0) { - *certainly_not_der = 1; - } - } - if (tlenlen == 0) { - /* Short length notation */ - sig[(*len)++] = tlen; - } else { - /* Long length notation */ - sig[(*len)++] = 128 + tlenlen; - assign_big_endian(sig + *len, tlenlen, tlen); - *len += tlenlen; - } - tlen += tlenlen; - } - tlen += 2; - CHECK(tlen + glen <= 1119); - - for (n = 0; n < 2; n++) { - /* Write the integer header. */ - sig[(*len)++] = 0x02; - if (nlenlen[n] == 0) { - /* Short length notation */ - sig[(*len)++] = nlen[n] + nzlen[n]; - } else { - /* Long length notation. */ - sig[(*len)++] = 128 + nlenlen[n]; - assign_big_endian(sig + *len, nlenlen[n], nlen[n] + nzlen[n]); - *len += nlenlen[n]; - } - /* Write zero padding */ - while (nzlen[n] > 0) { - sig[(*len)++] = 0x00; - nzlen[n]--; - } - if (nlen[n] == 32 && !nlow[n]) { - /* Special extra 16 0xFF bytes in "high" 32-byte numbers */ - int i; - for (i = 0; i < 16; i++) { - sig[(*len)++] = 0xFF; - } - nlen[n] -= 16; - } - /* Write first byte of number */ - if (nlen[n] > 0) { - sig[(*len)++] = nhbyte[n]; - nlen[n]--; - } - /* Generate remaining random bytes of number */ - testrand_bytes_test(sig + *len, nlen[n]); - *len += nlen[n]; - nlen[n] = 0; - } - - /* Generate random garbage inside tuple. */ - testrand_bytes_test(sig + *len, elen); - *len += elen; - - /* Generate end-of-contents bytes. */ - if (indet) { - sig[(*len)++] = 0; - sig[(*len)++] = 0; - tlen += 2; - } - CHECK(tlen + glen <= 1121); - - /* Generate random garbage outside tuple. */ - testrand_bytes_test(sig + *len, glen); - *len += glen; - tlen += glen; - CHECK(tlen <= 1121); - CHECK(tlen == *len); -} - -static void run_ecdsa_der_parse(void) { - int i,j; - for (i = 0; i < 200 * COUNT; i++) { - unsigned char buffer[2048]; - size_t buflen = 0; - int certainly_der = 0; - int certainly_not_der = 0; - random_ber_signature(buffer, &buflen, &certainly_der, &certainly_not_der); - CHECK(buflen <= 2048); - for (j = 0; j < 16; j++) { - int ret = 0; - if (j > 0) { - damage_array(buffer, &buflen); - /* We don't know anything anymore about the DERness of the result */ - certainly_der = 0; - certainly_not_der = 0; - } - ret = test_ecdsa_der_parse(buffer, buflen, certainly_der, certainly_not_der); - if (ret != 0) { - size_t k; - fprintf(stderr, "Failure %x on ", ret); - for (k = 0; k < buflen; k++) { - fprintf(stderr, "%02x ", buffer[k]); - } - fprintf(stderr, "\n"); - } - CHECK(ret == 0); - } - } -} - -/* Tests several edge cases. */ -static void test_ecdsa_edge_cases(void) { - int t; - secp256k1_ecdsa_signature sig; - - /* Test the case where ECDSA recomputes a point that is infinity. */ - { - secp256k1_gej keyj; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_negate(&ss, &ss); - secp256k1_scalar_inverse(&ss, &ss); - secp256k1_scalar_set_int(&sr, 1); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &keyj, &sr); - secp256k1_ge_set_gej(&key, &keyj); - msg = ss; - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with r of zero fails. */ - { - const unsigned char pubkey_mods_zero[33] = { - 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, - 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, - 0x41 - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 0); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); - CHECK(secp256k1_ecdsa_sig_verify( &sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with s of zero fails. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01 - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 0); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 1); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); - } - - /* Verify signature with message 0 passes. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02 - }; - const unsigned char pubkey2[33] = { - 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, - 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, - 0x43 - }; - secp256k1_ge key; - secp256k1_ge key2; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 2); - secp256k1_scalar_set_int(&msg, 0); - secp256k1_scalar_set_int(&sr, 2); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_set_int(&ss, 1); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0); - } - - /* Verify signature with message 1 passes. */ - { - const unsigned char pubkey[33] = { - 0x02, 0x14, 0x4e, 0x5a, 0x58, 0xef, 0x5b, 0x22, - 0x6f, 0xd2, 0xe2, 0x07, 0x6a, 0x77, 0xcf, 0x05, - 0xb4, 0x1d, 0xe7, 0x4a, 0x30, 0x98, 0x27, 0x8c, - 0x93, 0xe6, 0xe6, 0x3c, 0x0b, 0xc4, 0x73, 0x76, - 0x25 - }; - const unsigned char pubkey2[33] = { - 0x02, 0x8a, 0xd5, 0x37, 0xed, 0x73, 0xd9, 0x40, - 0x1d, 0xa0, 0x33, 0xd2, 0xdc, 0xf0, 0xaf, 0xae, - 0x34, 0xcf, 0x5f, 0x96, 0x4c, 0x73, 0x28, 0x0f, - 0x92, 0xc0, 0xf6, 0x9d, 0xd9, 0xb2, 0x09, 0x10, - 0x62 - }; - const unsigned char csr[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb - }; - secp256k1_ge key; - secp256k1_ge key2; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 1); - secp256k1_scalar_set_b32(&sr, csr, NULL); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); - secp256k1_scalar_set_int(&ss, 2); - secp256k1_scalar_inverse_var(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0); - } - - /* Verify signature with message -1 passes. */ - { - const unsigned char pubkey[33] = { - 0x03, 0xaf, 0x97, 0xff, 0x7d, 0x3a, 0xf6, 0xa0, - 0x02, 0x94, 0xbd, 0x9f, 0x4b, 0x2e, 0xd7, 0x52, - 0x28, 0xdb, 0x49, 0x2a, 0x65, 0xcb, 0x1e, 0x27, - 0x57, 0x9c, 0xba, 0x74, 0x20, 0xd5, 0x1d, 0x20, - 0xf1 - }; - const unsigned char csr[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, - 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee - }; - secp256k1_ge key; - secp256k1_scalar msg; - secp256k1_scalar sr, ss; - secp256k1_scalar_set_int(&ss, 1); - secp256k1_scalar_set_int(&msg, 1); - secp256k1_scalar_negate(&msg, &msg); - secp256k1_scalar_set_b32(&sr, csr, NULL); - CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - secp256k1_scalar_negate(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - secp256k1_scalar_set_int(&ss, 3); - secp256k1_scalar_inverse_var(&ss, &ss); - CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); - } - - /* Signature where s would be zero. */ - { - secp256k1_pubkey pubkey; - size_t siglen; - unsigned char signature[72]; - static const unsigned char nonce[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - static const unsigned char nonce2[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 - }; - const unsigned char key[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - }; - unsigned char msg[32] = { - 0x86, 0x41, 0x99, 0x81, 0x06, 0x23, 0x44, 0x53, - 0xaa, 0x5f, 0x9d, 0x6a, 0x31, 0x78, 0xf4, 0xf7, - 0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62, - 0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9, - }; - CHECK(secp256k1_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce) == 0); - CHECK(secp256k1_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce2) == 0); - msg[31] = 0xaa; - CHECK(secp256k1_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_sign(CTX, NULL, msg, key, precomputed_nonce_function, nonce2)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_sign(CTX, &sig, NULL, key, precomputed_nonce_function, nonce2)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_sign(CTX, &sig, msg, NULL, precomputed_nonce_function, nonce2)); - CHECK(secp256k1_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); - CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, key) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_verify(CTX, NULL, msg, &pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_verify(CTX, &sig, NULL, &pubkey)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_verify(CTX, &sig, msg, NULL)); - CHECK(secp256k1_ecdsa_verify(CTX, &sig, msg, &pubkey) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_create(CTX, &pubkey, NULL)); - /* That pubkeyload fails via an ARGCHECK is a little odd but makes sense because pubkeys are an opaque data type. */ - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_verify(CTX, &sig, msg, &pubkey)); - siglen = 72; - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_serialize_der(CTX, NULL, &siglen, &sig)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_serialize_der(CTX, signature, NULL, &sig)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_serialize_der(CTX, signature, &siglen, NULL)); - CHECK(secp256k1_ecdsa_signature_serialize_der(CTX, signature, &siglen, &sig) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_parse_der(CTX, NULL, signature, siglen)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_parse_der(CTX, &sig, NULL, siglen)); - CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &sig, signature, siglen) == 1); - siglen = 10; - /* Too little room for a signature does not fail via ARGCHECK. */ - CHECK(secp256k1_ecdsa_signature_serialize_der(CTX, signature, &siglen, &sig) == 0); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_normalize(CTX, NULL, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_serialize_compact(CTX, NULL, &sig)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_serialize_compact(CTX, signature, NULL)); - CHECK(secp256k1_ecdsa_signature_serialize_compact(CTX, signature, &sig) == 1); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_parse_compact(CTX, NULL, signature)); - CHECK_ILLEGAL(CTX, secp256k1_ecdsa_signature_parse_compact(CTX, &sig, NULL)); - CHECK(secp256k1_ecdsa_signature_parse_compact(CTX, &sig, signature) == 1); - memset(signature, 255, 64); - CHECK(secp256k1_ecdsa_signature_parse_compact(CTX, &sig, signature) == 0); - } - - /* Nonce function corner cases. */ - for (t = 0; t < 2; t++) { - static const unsigned char zero[32] = {0x00}; - int i; - unsigned char key[32]; - unsigned char msg[32]; - secp256k1_ecdsa_signature sig2; - secp256k1_scalar sr[512], ss; - const unsigned char *extra; - extra = t == 0 ? NULL : zero; - memset(msg, 0, 32); - msg[31] = 1; - /* High key results in signature failure. */ - memset(key, 0xFF, 32); - CHECK(secp256k1_ecdsa_sign(CTX, &sig, msg, key, NULL, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* Zero key results in signature failure. */ - memset(key, 0, 32); - CHECK(secp256k1_ecdsa_sign(CTX, &sig, msg, key, NULL, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* Nonce function failure results in signature failure. */ - key[31] = 1; - CHECK(secp256k1_ecdsa_sign(CTX, &sig, msg, key, nonce_function_test_fail, extra) == 0); - CHECK(is_empty_signature(&sig)); - /* The retry loop successfully makes its way to the first good value. */ - CHECK(secp256k1_ecdsa_sign(CTX, &sig, msg, key, nonce_function_test_retry, extra) == 1); - CHECK(!is_empty_signature(&sig)); - CHECK(secp256k1_ecdsa_sign(CTX, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - CHECK(secp256k1_memcmp_var(&sig, &sig2, sizeof(sig)) == 0); - /* The default nonce function is deterministic. */ - CHECK(secp256k1_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - CHECK(secp256k1_memcmp_var(&sig, &sig2, sizeof(sig)) == 0); - /* The default nonce function changes output with different messages. */ - for(i = 0; i < 256; i++) { - int j; - msg[0] = i; - CHECK(secp256k1_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(CTX, &sr[i], &ss, &sig2); - for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); - } - } - msg[0] = 0; - msg[31] = 2; - /* The default nonce function changes output with different keys. */ - for(i = 256; i < 512; i++) { - int j; - key[0] = i - 256; - CHECK(secp256k1_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); - CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(CTX, &sr[i], &ss, &sig2); - for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); - } - } - key[0] = 0; - } - - { - /* Check that optional nonce arguments do not have equivalent effect. */ - const unsigned char zeros[32] = {0}; - unsigned char nonce[32]; - unsigned char nonce2[32]; - unsigned char nonce3[32]; - unsigned char nonce4[32]; - SECP256K1_CHECKMEM_UNDEFINE(nonce,32); - SECP256K1_CHECKMEM_UNDEFINE(nonce2,32); - SECP256K1_CHECKMEM_UNDEFINE(nonce3,32); - SECP256K1_CHECKMEM_UNDEFINE(nonce4,32); - CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1); - SECP256K1_CHECKMEM_CHECK(nonce,32); - CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1); - SECP256K1_CHECKMEM_CHECK(nonce2,32); - CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1); - SECP256K1_CHECKMEM_CHECK(nonce3,32); - CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); - SECP256K1_CHECKMEM_CHECK(nonce4,32); - CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); - CHECK(secp256k1_memcmp_var(nonce, nonce3, 32) != 0); - CHECK(secp256k1_memcmp_var(nonce, nonce4, 32) != 0); - CHECK(secp256k1_memcmp_var(nonce2, nonce3, 32) != 0); - CHECK(secp256k1_memcmp_var(nonce2, nonce4, 32) != 0); - CHECK(secp256k1_memcmp_var(nonce3, nonce4, 32) != 0); - } - - - /* Privkey export where pubkey is the point at infinity. */ - { - unsigned char privkey[300]; - unsigned char seckey[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, - }; - size_t outlen = 300; - CHECK(!ec_privkey_export_der(CTX, privkey, &outlen, seckey, 0)); - outlen = 300; - CHECK(!ec_privkey_export_der(CTX, privkey, &outlen, seckey, 1)); - } -} - -static void run_ecdsa_edge_cases(void) { - test_ecdsa_edge_cases(); -} - -/** Wycheproof tests - -The tests check for known attacks (range checks in (r,s), arithmetic errors, malleability). -*/ -static void test_ecdsa_wycheproof(void) { - #include "wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h" - - int t; - for (t = 0; t < SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS; t++) { - secp256k1_ecdsa_signature signature; - secp256k1_sha256 hasher; - secp256k1_pubkey pubkey; - const unsigned char *msg, *sig, *pk; - unsigned char out[32] = {0}; - int actual_verify = 0; - - memset(&pubkey, 0, sizeof(pubkey)); - pk = &wycheproof_ecdsa_public_keys[testvectors[t].pk_offset]; - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pk, 65) == 1); - - secp256k1_sha256_initialize(&hasher); - msg = &wycheproof_ecdsa_messages[testvectors[t].msg_offset]; - secp256k1_sha256_write(&hasher, msg, testvectors[t].msg_len); - secp256k1_sha256_finalize(&hasher, out); - - sig = &wycheproof_ecdsa_signatures[testvectors[t].sig_offset]; - if (secp256k1_ecdsa_signature_parse_der(CTX, &signature, sig, testvectors[t].sig_len) == 1) { - actual_verify = secp256k1_ecdsa_verify(CTX, (const secp256k1_ecdsa_signature *)&signature, out, &pubkey); - } - CHECK(testvectors[t].expected_verify == actual_verify); - } -} - -/* Tests cases from Wycheproof test suite. */ -static void run_ecdsa_wycheproof(void) { - test_ecdsa_wycheproof(); -} - -#ifdef ENABLE_MODULE_ECDH -# include "modules/ecdh/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "modules/recovery/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_EXTRAKEYS -# include "modules/extrakeys/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG -# include "modules/schnorrsig/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_MUSIG -# include "modules/musig/tests_impl.h" -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT -# include "modules/ellswift/tests_impl.h" -#endif - -static void run_secp256k1_memczero_test(void) { - unsigned char buf1[6] = {1, 2, 3, 4, 5, 6}; - unsigned char buf2[sizeof(buf1)]; - - /* secp256k1_memczero(..., ..., 0) is a noop. */ - memcpy(buf2, buf1, sizeof(buf1)); - secp256k1_memczero(buf1, sizeof(buf1), 0); - CHECK(secp256k1_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); - - /* secp256k1_memczero(..., ..., 1) zeros the buffer. */ - memset(buf2, 0, sizeof(buf2)); - secp256k1_memczero(buf1, sizeof(buf1) , 1); - CHECK(secp256k1_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); -} - - -static void run_secp256k1_is_zero_array_test(void) { - unsigned char buf1[3] = {0, 1}; - unsigned char buf2[3] = {1, 0}; - - CHECK(secp256k1_is_zero_array(buf1, 0) == 1); - CHECK(secp256k1_is_zero_array(buf1, 1) == 1); - CHECK(secp256k1_is_zero_array(buf1, 2) == 0); - CHECK(secp256k1_is_zero_array(buf2, 1) == 0); - CHECK(secp256k1_is_zero_array(buf2, 2) == 0); -} - -static void run_secp256k1_byteorder_tests(void) { - { - const uint32_t x = 0xFF03AB45; - const unsigned char x_be[4] = {0xFF, 0x03, 0xAB, 0x45}; - unsigned char buf[4]; - uint32_t x_; - - secp256k1_write_be32(buf, x); - CHECK(secp256k1_memcmp_var(buf, x_be, sizeof(buf)) == 0); - - x_ = secp256k1_read_be32(buf); - CHECK(x == x_); - } - - { - const uint64_t x = 0xCAFE0123BEEF4567; - const unsigned char x_be[8] = {0xCA, 0xFE, 0x01, 0x23, 0xBE, 0xEF, 0x45, 0x67}; - unsigned char buf[8]; - uint64_t x_; - - secp256k1_write_be64(buf, x); - CHECK(secp256k1_memcmp_var(buf, x_be, sizeof(buf)) == 0); - - x_ = secp256k1_read_be64(buf); - CHECK(x == x_); - } -} - -static void int_cmov_test(void) { - int r = INT_MAX; - int a = 0; - - secp256k1_int_cmov(&r, &a, 0); - CHECK(r == INT_MAX); - - r = 0; a = INT_MAX; - secp256k1_int_cmov(&r, &a, 1); - CHECK(r == INT_MAX); - - a = 0; - secp256k1_int_cmov(&r, &a, 1); - CHECK(r == 0); - - a = 1; - secp256k1_int_cmov(&r, &a, 1); - CHECK(r == 1); - - r = 1; a = 0; - secp256k1_int_cmov(&r, &a, 0); - CHECK(r == 1); - -} - -static void fe_cmov_test(void) { - static const secp256k1_fe zero = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0); - static const secp256k1_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - static const secp256k1_fe max = SECP256K1_FE_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL - ); - secp256k1_fe r = max; - secp256k1_fe a = zero; - - secp256k1_fe_cmov(&r, &a, 0); - CHECK(fe_identical(&r, &max)); - - r = zero; a = max; - secp256k1_fe_cmov(&r, &a, 1); - CHECK(fe_identical(&r, &max)); - - a = zero; - secp256k1_fe_cmov(&r, &a, 1); - CHECK(fe_identical(&r, &zero)); - - a = one; - secp256k1_fe_cmov(&r, &a, 1); - CHECK(fe_identical(&r, &one)); - - r = one; a = zero; - secp256k1_fe_cmov(&r, &a, 0); - CHECK(fe_identical(&r, &one)); -} - -static void fe_storage_cmov_test(void) { - static const secp256k1_fe_storage zero = SECP256K1_FE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 0); - static const secp256k1_fe_storage one = SECP256K1_FE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - static const secp256k1_fe_storage max = SECP256K1_FE_STORAGE_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL - ); - secp256k1_fe_storage r = max; - secp256k1_fe_storage a = zero; - - secp256k1_fe_storage_cmov(&r, &a, 0); - CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); - - r = zero; a = max; - secp256k1_fe_storage_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); - - a = zero; - secp256k1_fe_storage_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0); - - a = one; - secp256k1_fe_storage_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); - - r = one; a = zero; - secp256k1_fe_storage_cmov(&r, &a, 0); - CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); -} - -static void scalar_cmov_test(void) { - static const secp256k1_scalar max = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, - 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364140UL - ); - secp256k1_scalar r = max; - secp256k1_scalar a = secp256k1_scalar_zero; - - secp256k1_scalar_cmov(&r, &a, 0); - CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); - - r = secp256k1_scalar_zero; a = max; - secp256k1_scalar_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); - - a = secp256k1_scalar_zero; - secp256k1_scalar_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &secp256k1_scalar_zero, sizeof(r)) == 0); - - a = secp256k1_scalar_one; - secp256k1_scalar_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &secp256k1_scalar_one, sizeof(r)) == 0); - - r = secp256k1_scalar_one; a = secp256k1_scalar_zero; - secp256k1_scalar_cmov(&r, &a, 0); - CHECK(secp256k1_memcmp_var(&r, &secp256k1_scalar_one, sizeof(r)) == 0); -} - -static void ge_storage_cmov_test(void) { - static const secp256k1_ge_storage zero = SECP256K1_GE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - static const secp256k1_ge_storage one = SECP256K1_GE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); - static const secp256k1_ge_storage max = SECP256K1_GE_STORAGE_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL - ); - secp256k1_ge_storage r = max; - secp256k1_ge_storage a = zero; - - secp256k1_ge_storage_cmov(&r, &a, 0); - CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); - - r = zero; a = max; - secp256k1_ge_storage_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); - - a = zero; - secp256k1_ge_storage_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0); - - a = one; - secp256k1_ge_storage_cmov(&r, &a, 1); - CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); - - r = one; a = zero; - secp256k1_ge_storage_cmov(&r, &a, 0); - CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); -} - -static void run_cmov_tests(void) { - int_cmov_test(); - fe_cmov_test(); - fe_storage_cmov_test(); - scalar_cmov_test(); - ge_storage_cmov_test(); -} - -int main(int argc, char **argv) { - /* Disable buffering for stdout to improve reliability of getting - * diagnostic information. Happens right at the start of main because - * setbuf must be used before any other operation on the stream. */ - setbuf(stdout, NULL); - /* Also disable buffering for stderr because it's not guaranteed that it's - * unbuffered on all systems. */ - setbuf(stderr, NULL); - - /* find iteration count */ - if (argc > 1) { - COUNT = strtol(argv[1], NULL, 0); - } else { - const char* env = getenv("SECP256K1_TEST_ITERS"); - if (env && strlen(env) > 0) { - COUNT = strtol(env, NULL, 0); - } - } - if (COUNT <= 0) { - fputs("An iteration count of 0 or less is not allowed.\n", stderr); - return EXIT_FAILURE; - } - printf("test count = %i\n", COUNT); - - /* run test RNG tests (must run before we really initialize the test RNG) */ - run_xoshiro256pp_tests(); - - /* find random seed */ - testrand_init(argc > 2 ? argv[2] : NULL); - - /*** Setup test environment ***/ - - /* Create a global context available to all tests */ - CTX = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - /* Randomize the context only with probability 15/16 - to make sure we test without context randomization from time to time. - TODO Reconsider this when recalibrating the tests. */ - if (testrand_bits(4)) { - unsigned char rand32[32]; - testrand256(rand32); - CHECK(secp256k1_context_randomize(CTX, rand32)); - } - /* Make a writable copy of secp256k1_context_static in order to test the effect of API functions - that write to the context. The API does not support cloning the static context, so we use - memcpy instead. The user is not supposed to copy a context but we should still ensure that - the API functions handle copies of the static context gracefully. */ - STATIC_CTX = malloc(sizeof(*secp256k1_context_static)); - CHECK(STATIC_CTX != NULL); - memcpy(STATIC_CTX, secp256k1_context_static, sizeof(secp256k1_context)); - CHECK(!secp256k1_context_is_proper(STATIC_CTX)); - - /*** Run actual tests ***/ - - /* selftest tests */ - run_selftest_tests(); - - /* context tests */ - run_proper_context_tests(0); run_proper_context_tests(1); - run_static_context_tests(0); run_static_context_tests(1); - run_deprecated_context_flags_test(); - - /* scratch tests */ - run_scratch_tests(); - - /* integer arithmetic tests */ -#ifdef SECP256K1_WIDEMUL_INT128 - run_int128_tests(); -#endif - run_ctz_tests(); - run_modinv_tests(); - run_inverse_tests(); - - /* sorting tests */ - run_hsort_tests(); - - /* hash tests */ - run_sha256_known_output_tests(); - run_sha256_counter_tests(); - run_hmac_sha256_tests(); - run_rfc6979_hmac_sha256_tests(); - run_tagged_sha256_tests(); - - /* scalar tests */ - run_scalar_tests(); - - /* field tests */ - run_field_half(); - run_field_misc(); - run_field_convert(); - run_field_be32_overflow(); - run_fe_mul(); - run_sqr(); - run_sqrt(); - - /* group tests */ - run_ge(); - run_gej(); - run_group_decompress(); - - /* ecmult tests */ - run_ecmult_pre_g(); - run_wnaf(); - run_point_times_order(); - run_ecmult_near_split_bound(); - run_ecmult_chain(); - run_ecmult_constants(); - run_ecmult_gen_blind(); - run_ecmult_const_tests(); - run_ecmult_multi_tests(); - run_ec_combine(); - - /* endomorphism tests */ - run_endomorphism_tests(); - - /* EC point parser test */ - run_ec_pubkey_parse_test(); - - /* EC key edge cases */ - run_eckey_edge_case_test(); - - /* EC key arithmetic test */ - run_eckey_negate_test(); - -#ifdef ENABLE_MODULE_ECDH - /* ecdh tests */ - run_ecdh_tests(); -#endif - - /* ecdsa tests */ - run_ec_illegal_argument_tests(); - run_pubkey_comparison(); - run_pubkey_sort(); - run_random_pubkeys(); - run_ecdsa_der_parse(); - run_ecdsa_sign_verify(); - run_ecdsa_end_to_end(); - run_ecdsa_edge_cases(); - run_ecdsa_wycheproof(); - -#ifdef ENABLE_MODULE_RECOVERY - /* ECDSA pubkey recovery tests */ - run_recovery_tests(); -#endif - -#ifdef ENABLE_MODULE_EXTRAKEYS - run_extrakeys_tests(); -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG - run_schnorrsig_tests(); -#endif - -#ifdef ENABLE_MODULE_MUSIG - run_musig_tests(); -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT - run_ellswift_tests(); -#endif - - /* util tests */ - run_secp256k1_memczero_test(); - run_secp256k1_is_zero_array_test(); - run_secp256k1_byteorder_tests(); - - run_cmov_tests(); - - /*** Tear down test environment ***/ - free(STATIC_CTX); - secp256k1_context_destroy(CTX); - - testrand_finish(); - - printf("no problems found\n"); - return 0; -} diff --git a/external/secp256k1/src/tests_exhaustive.c b/external/secp256k1/src/tests_exhaustive.c deleted file mode 100644 index 6efa88982e..0000000000 --- a/external/secp256k1/src/tests_exhaustive.c +++ /dev/null @@ -1,466 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2016 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#include -#include -#include - -#ifndef EXHAUSTIVE_TEST_ORDER -/* see group_impl.h for allowable values */ -#define EXHAUSTIVE_TEST_ORDER 13 -#endif - -/* These values of B are all values in [1, 8] that result in a curve with even order. */ -#define EXHAUSTIVE_TEST_CURVE_HAS_EVEN_ORDER (SECP256K1_B == 1 || SECP256K1_B == 6 || SECP256K1_B == 8) - -#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS - #pragma message("Ignoring USE_EXTERNAL_CALLBACKS in exhaustive_tests.") - #undef USE_EXTERNAL_DEFAULT_CALLBACKS -#endif -#include "secp256k1.c" - -#include "../include/secp256k1.h" -#include "assumptions.h" -#include "group.h" -#include "testrand_impl.h" -#include "ecmult_compute_table_impl.h" -#include "ecmult_gen_compute_table_impl.h" -#include "testutil.h" -#include "util.h" - -static int count = 2; - -static uint32_t num_cores = 1; -static uint32_t this_core = 0; - -SECP256K1_INLINE static int skip_section(uint64_t* iter) { - if (num_cores == 1) return 0; - *iter += 0xe7037ed1a0b428dbULL; - return ((((uint32_t)*iter ^ (*iter >> 32)) * num_cores) >> 32) != this_core; -} - -static int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, - const unsigned char *key32, const unsigned char *algo16, - void *data, unsigned int attempt) { - secp256k1_scalar s; - int *idata = data; - (void)msg32; - (void)key32; - (void)algo16; - /* Some nonces cannot be used because they'd cause s and/or r to be zero. - * The signing function has retry logic here that just re-calls the nonce - * function with an increased `attempt`. So if attempt > 0 this means we - * need to change the nonce to avoid an infinite loop. */ - if (attempt > 0) { - *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; - } - secp256k1_scalar_set_int(&s, *idata); - secp256k1_scalar_get_b32(nonce32, &s); - return 1; -} - -static void test_exhaustive_endomorphism(const secp256k1_ge *group) { - int i; - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - secp256k1_ge res; - secp256k1_ge_mul_lambda(&res, &group[i]); - CHECK(secp256k1_ge_eq_var(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res)); - } -} - -static void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj) { - int i, j; - uint64_t iter = 0; - - /* Sanity-check (and check infinity functions) */ - CHECK(secp256k1_ge_is_infinity(&group[0])); - CHECK(secp256k1_gej_is_infinity(&groupj[0])); - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - CHECK(!secp256k1_ge_is_infinity(&group[i])); - CHECK(!secp256k1_gej_is_infinity(&groupj[i])); - } - - /* Check all addition formulae */ - for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { - secp256k1_fe fe_inv; - if (skip_section(&iter)) continue; - secp256k1_fe_inv(&fe_inv, &groupj[j].z); - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - secp256k1_ge zless_gej; - secp256k1_gej tmp; - /* add_var */ - secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); - /* add_ge */ - if (j > 0) { - secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); - } - /* add_ge_var */ - secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); - /* add_zinv_var */ - zless_gej.infinity = groupj[j].infinity; - zless_gej.x = groupj[j].x; - zless_gej.y = groupj[j].y; - secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); - } - } - - /* Check doubling */ - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - secp256k1_gej tmp; - secp256k1_gej_double(&tmp, &groupj[i]); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(2 * i) % EXHAUSTIVE_TEST_ORDER])); - secp256k1_gej_double_var(&tmp, &groupj[i], NULL); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(2 * i) % EXHAUSTIVE_TEST_ORDER])); - } - - /* Check negation */ - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - secp256k1_ge tmp; - secp256k1_gej tmpj; - secp256k1_ge_neg(&tmp, &group[i]); - CHECK(secp256k1_ge_eq_var(&tmp, &group[EXHAUSTIVE_TEST_ORDER - i])); - secp256k1_gej_neg(&tmpj, &groupj[i]); - CHECK(secp256k1_gej_eq_ge_var(&tmpj, &group[EXHAUSTIVE_TEST_ORDER - i])); - } -} - -static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_gej *groupj) { - int i, j, r_log; - uint64_t iter = 0; - for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) { - for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { - if (skip_section(&iter)) continue; - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - secp256k1_gej tmp; - secp256k1_scalar na, ng; - secp256k1_scalar_set_int(&na, i); - secp256k1_scalar_set_int(&ng, j); - - secp256k1_ecmult(&tmp, &groupj[r_log], &na, &ng); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i * r_log + j) % EXHAUSTIVE_TEST_ORDER])); - } - } - } - - for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - int ret; - secp256k1_gej tmp; - secp256k1_fe xn, xd, tmpf; - secp256k1_scalar ng; - - if (skip_section(&iter)) continue; - - secp256k1_scalar_set_int(&ng, j); - - /* Test secp256k1_ecmult_const. */ - secp256k1_ecmult_const(&tmp, &group[i], &ng); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i * j) % EXHAUSTIVE_TEST_ORDER])); - - if (i != 0 && j != 0) { - /* Test secp256k1_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */ - ret = secp256k1_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 0); - CHECK(ret); - CHECK(secp256k1_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); - - /* Test secp256k1_ecmult_const_xonly with all curve X coordinates, with random xd. */ - testutil_random_fe_non_zero(&xd); - secp256k1_fe_mul(&xn, &xd, &group[i].x); - ret = secp256k1_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 0); - CHECK(ret); - CHECK(secp256k1_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); - } - } - } -} - -typedef struct { - secp256k1_scalar sc[2]; - secp256k1_ge pt[2]; -} ecmult_multi_data; - -static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) { - ecmult_multi_data *data = (ecmult_multi_data*) cbdata; - *sc = data->sc[idx]; - *pt = data->pt[idx]; - return 1; -} - -static void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_ge *group) { - int i, j, k, x, y; - uint64_t iter = 0; - secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 4096); - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { - for (k = 0; k < EXHAUSTIVE_TEST_ORDER; k++) { - for (x = 0; x < EXHAUSTIVE_TEST_ORDER; x++) { - if (skip_section(&iter)) continue; - for (y = 0; y < EXHAUSTIVE_TEST_ORDER; y++) { - secp256k1_gej tmp; - secp256k1_scalar g_sc; - ecmult_multi_data data; - - secp256k1_scalar_set_int(&data.sc[0], i); - secp256k1_scalar_set_int(&data.sc[1], j); - secp256k1_scalar_set_int(&g_sc, k); - data.pt[0] = group[x]; - data.pt[1] = group[y]; - - secp256k1_ecmult_multi_var(&ctx->error_callback, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2); - CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER])); - } - } - } - } - } - secp256k1_scratch_destroy(&ctx->error_callback, scratch); -} - -static void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k, int* overflow) { - secp256k1_fe x; - unsigned char x_bin[32]; - k %= EXHAUSTIVE_TEST_ORDER; - x = group[k].x; - secp256k1_fe_normalize(&x); - secp256k1_fe_get_b32(x_bin, &x); - secp256k1_scalar_set_b32(r, x_bin, overflow); -} - -static void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group) { - int s, r, msg, key; - uint64_t iter = 0; - for (s = 1; s < EXHAUSTIVE_TEST_ORDER; s++) { - for (r = 1; r < EXHAUSTIVE_TEST_ORDER; r++) { - for (msg = 1; msg < EXHAUSTIVE_TEST_ORDER; msg++) { - for (key = 1; key < EXHAUSTIVE_TEST_ORDER; key++) { - secp256k1_ge nonconst_ge; - secp256k1_ecdsa_signature sig; - secp256k1_pubkey pk; - secp256k1_scalar sk_s, msg_s, r_s, s_s; - secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; - int k, should_verify; - unsigned char msg32[32]; - - if (skip_section(&iter)) continue; - - secp256k1_scalar_set_int(&s_s, s); - secp256k1_scalar_set_int(&r_s, r); - secp256k1_scalar_set_int(&msg_s, msg); - secp256k1_scalar_set_int(&sk_s, key); - - /* Verify by hand */ - /* Run through every k value that gives us this r and check that *one* works. - * Note there could be none, there could be multiple, ECDSA is weird. */ - should_verify = 0; - for (k = 0; k < EXHAUSTIVE_TEST_ORDER; k++) { - secp256k1_scalar check_x_s; - r_from_k(&check_x_s, group, k, NULL); - if (r_s == check_x_s) { - secp256k1_scalar_set_int(&s_times_k_s, k); - secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); - } - } - /* nb we have a "high s" rule */ - should_verify &= !secp256k1_scalar_is_high(&s_s); - - /* Verify by calling verify */ - secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s); - memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - secp256k1_pubkey_save(&pk, &nonconst_ge); - secp256k1_scalar_get_b32(msg32, &msg_s); - CHECK(should_verify == - secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); - } - } - } - } -} - -static void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group) { - int i, j, k; - uint64_t iter = 0; - - /* Loop */ - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { /* message */ - for (j = 1; j < EXHAUSTIVE_TEST_ORDER; j++) { /* key */ - if (skip_section(&iter)) continue; - for (k = 1; k < EXHAUSTIVE_TEST_ORDER; k++) { /* nonce */ - const int starting_k = k; - int ret; - secp256k1_ecdsa_signature sig; - secp256k1_scalar sk, msg, r, s, expected_r; - unsigned char sk32[32], msg32[32]; - secp256k1_scalar_set_int(&msg, i); - secp256k1_scalar_set_int(&sk, j); - secp256k1_scalar_get_b32(sk32, &sk); - secp256k1_scalar_get_b32(msg32, &msg); - - ret = secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); - CHECK(ret == 1); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); - /* Note that we compute expected_r *after* signing -- this is important - * because our nonce-computing function function might change k during - * signing. */ - r_from_k(&expected_r, group, k, NULL); - CHECK(r == expected_r); - CHECK((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER || - (k * (EXHAUSTIVE_TEST_ORDER - s)) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER); - - /* Overflow means we've tried every possible nonce */ - if (k < starting_k) { - break; - } - } - } - } - - /* We would like to verify zero-knowledge here by counting how often every - * possible (s, r) tuple appears, but because the group order is larger - * than the field order, when coercing the x-values to scalar values, some - * appear more often than others, so we are actually not zero-knowledge. - * (This effect also appears in the real code, but the difference is on the - * order of 1/2^128th the field order, so the deviation is not useful to a - * computationally bounded attacker.) - */ -} - -#ifdef ENABLE_MODULE_RECOVERY -#include "modules/recovery/tests_exhaustive_impl.h" -#endif - -#ifdef ENABLE_MODULE_EXTRAKEYS -#include "modules/extrakeys/tests_exhaustive_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG -#include "modules/schnorrsig/tests_exhaustive_impl.h" -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT -#include "modules/ellswift/tests_exhaustive_impl.h" -#endif - -int main(int argc, char** argv) { - int i; - secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; - secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; - unsigned char rand32[32]; - secp256k1_context *ctx; - - /* Disable buffering for stdout to improve reliability of getting - * diagnostic information. Happens right at the start of main because - * setbuf must be used before any other operation on the stream. */ - setbuf(stdout, NULL); - /* Also disable buffering for stderr because it's not guaranteed that it's - * unbuffered on all systems. */ - setbuf(stderr, NULL); - - printf("Exhaustive tests for order %lu\n", (unsigned long)EXHAUSTIVE_TEST_ORDER); - - /* find iteration count */ - if (argc > 1) { - count = strtol(argv[1], NULL, 0); - } - printf("test count = %i\n", count); - - /* find random seed */ - testrand_init(argc > 2 ? argv[2] : NULL); - - /* set up split processing */ - if (argc > 4) { - num_cores = strtol(argv[3], NULL, 0); - this_core = strtol(argv[4], NULL, 0); - if (num_cores < 1 || this_core >= num_cores) { - fprintf(stderr, "Usage: %s [count] [seed] [numcores] [thiscore]\n", argv[0]); - return 1; - } - printf("running tests for core %lu (out of [0..%lu])\n", (unsigned long)this_core, (unsigned long)num_cores - 1); - } - - /* Recreate the ecmult{,_gen} tables using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */ - secp256k1_ecmult_gen_compute_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, COMB_BLOCKS, COMB_TEETH, COMB_SPACING); - secp256k1_ecmult_compute_two_tables(secp256k1_pre_g, secp256k1_pre_g_128, WINDOW_G, &secp256k1_ge_const_g); - - while (count--) { - /* Build context */ - ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - testrand256(rand32); - CHECK(secp256k1_context_randomize(ctx, rand32)); - - /* Generate the entire group */ - secp256k1_gej_set_infinity(&groupj[0]); - secp256k1_ge_set_gej(&group[0], &groupj[0]); - for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); - secp256k1_ge_set_gej(&group[i], &groupj[i]); - if (count != 0) { - /* Set a different random z-value for each Jacobian point, except z=1 - is used in the last iteration. */ - secp256k1_fe z; - testutil_random_fe(&z); - secp256k1_gej_rescale(&groupj[i], &z); - } - - /* Verify against ecmult_gen */ - { - secp256k1_scalar scalar_i; - secp256k1_gej generatedj; - secp256k1_ge generated; - - secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); - secp256k1_ge_set_gej(&generated, &generatedj); - - CHECK(group[i].infinity == 0); - CHECK(generated.infinity == 0); - CHECK(secp256k1_fe_equal(&generated.x, &group[i].x)); - CHECK(secp256k1_fe_equal(&generated.y, &group[i].y)); - } - } - - /* Run the tests */ - test_exhaustive_endomorphism(group); - test_exhaustive_addition(group, groupj); - test_exhaustive_ecmult(group, groupj); - test_exhaustive_ecmult_multi(ctx, group); - test_exhaustive_sign(ctx, group); - test_exhaustive_verify(ctx, group); - -#ifdef ENABLE_MODULE_RECOVERY - test_exhaustive_recovery(ctx, group); -#endif -#ifdef ENABLE_MODULE_EXTRAKEYS - test_exhaustive_extrakeys(ctx, group); -#endif -#ifdef ENABLE_MODULE_SCHNORRSIG - test_exhaustive_schnorrsig(ctx); -#endif -#ifdef ENABLE_MODULE_ELLSWIFT - /* The ellswift algorithm does have additional edge cases when operating on - * curves of even order, which are not included in the code as secp256k1 is - * of odd order. Skip the ellswift tests if the used exhaustive tests curve - * is even-ordered accordingly. */ - #if !EXHAUSTIVE_TEST_CURVE_HAS_EVEN_ORDER - test_exhaustive_ellswift(ctx, group); - #endif -#endif - - secp256k1_context_destroy(ctx); - } - - testrand_finish(); - - printf("no problems found\n"); - return 0; -} diff --git a/external/secp256k1/src/testutil.h b/external/secp256k1/src/testutil.h deleted file mode 100644 index 64b3bb41c0..0000000000 --- a/external/secp256k1/src/testutil.h +++ /dev/null @@ -1,148 +0,0 @@ -/*********************************************************************** - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_TESTUTIL_H -#define SECP256K1_TESTUTIL_H - -#include "field.h" -#include "group.h" -#include "testrand.h" -#include "util.h" - -static void testutil_random_fe(secp256k1_fe *x) { - unsigned char bin[32]; - do { - testrand256(bin); - if (secp256k1_fe_set_b32_limit(x, bin)) { - return; - } - } while(1); -} - -static void testutil_random_fe_non_zero(secp256k1_fe *nz) { - do { - testutil_random_fe(nz); - } while (secp256k1_fe_is_zero(nz)); -} - -static void testutil_random_fe_magnitude(secp256k1_fe *fe, int m) { - secp256k1_fe zero; - int n = testrand_int(m + 1); - secp256k1_fe_normalize(fe); - if (n == 0) { - return; - } - secp256k1_fe_set_int(&zero, 0); - secp256k1_fe_negate(&zero, &zero, 0); - secp256k1_fe_mul_int_unchecked(&zero, n - 1); - secp256k1_fe_add(fe, &zero); -#ifdef VERIFY - CHECK(fe->magnitude == n); -#endif -} - -static void testutil_random_fe_test(secp256k1_fe *x) { - unsigned char bin[32]; - do { - testrand256_test(bin); - if (secp256k1_fe_set_b32_limit(x, bin)) { - return; - } - } while(1); -} - -static void testutil_random_fe_non_zero_test(secp256k1_fe *fe) { - do { - testutil_random_fe_test(fe); - } while(secp256k1_fe_is_zero(fe)); -} - -static void testutil_random_ge_x_magnitude(secp256k1_ge *ge) { - testutil_random_fe_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); -} - -static void testutil_random_ge_y_magnitude(secp256k1_ge *ge) { - testutil_random_fe_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); -} - -static void testutil_random_gej_x_magnitude(secp256k1_gej *gej) { - testutil_random_fe_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); -} - -static void testutil_random_gej_y_magnitude(secp256k1_gej *gej) { - testutil_random_fe_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); -} - -static void testutil_random_gej_z_magnitude(secp256k1_gej *gej) { - testutil_random_fe_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); -} - -static void testutil_random_ge_test(secp256k1_ge *ge) { - secp256k1_fe fe; - do { - testutil_random_fe_test(&fe); - if (secp256k1_ge_set_xo_var(ge, &fe, testrand_bits(1))) { - secp256k1_fe_normalize(&ge->y); - break; - } - } while(1); - ge->infinity = 0; -} - -static void testutil_random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { - secp256k1_fe z2, z3; - testutil_random_fe_non_zero_test(&gej->z); - secp256k1_fe_sqr(&z2, &gej->z); - secp256k1_fe_mul(&z3, &z2, &gej->z); - secp256k1_fe_mul(&gej->x, &ge->x, &z2); - secp256k1_fe_mul(&gej->y, &ge->y, &z3); - gej->infinity = ge->infinity; -} - -static void testutil_random_gej_test(secp256k1_gej *gej) { - secp256k1_ge ge; - testutil_random_ge_test(&ge); - testutil_random_ge_jacobian_test(gej, &ge); -} - -static void testutil_random_pubkey_test(secp256k1_pubkey *pk) { - secp256k1_ge ge; - testutil_random_ge_test(&ge); - secp256k1_pubkey_save(pk, &ge); -} - -static void testutil_random_scalar_order_test(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - testrand256_test(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -static void testutil_random_scalar_order(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - testrand256(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -static void testutil_random_scalar_order_b32(unsigned char *b32) { - secp256k1_scalar num; - testutil_random_scalar_order(&num); - secp256k1_scalar_get_b32(b32, &num); -} - -#endif /* SECP256K1_TESTUTIL_H */ diff --git a/external/secp256k1/src/util.h b/external/secp256k1/src/util.h deleted file mode 100644 index 88a4149421..0000000000 --- a/external/secp256k1/src/util.h +++ /dev/null @@ -1,451 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_UTIL_H -#define SECP256K1_UTIL_H - -#include "../include/secp256k1.h" -#include "checkmem.h" - -#include -#include -#include -#include -#include -#if defined(_MSC_VER) -/* For SecureZeroMemory */ -#include -#endif - -#define STR_(x) #x -#define STR(x) STR_(x) -#define DEBUG_CONFIG_MSG(x) "DEBUG_CONFIG: " x -#define DEBUG_CONFIG_DEF(x) DEBUG_CONFIG_MSG(#x "=" STR(x)) - -/* Debug helper for printing arrays of unsigned char. */ -#define PRINT_BUF(buf, len) do { \ - printf("%s[%lu] = ", #buf, (unsigned long)len); \ - print_buf_plain(buf, len); \ -} while(0) - -static void print_buf_plain(const unsigned char *buf, size_t len) { - size_t i; - printf("{"); - for (i = 0; i < len; i++) { - if (i % 8 == 0) { - printf("\n "); - } else { - printf(" "); - } - printf("0x%02X,", buf[i]); - } - printf("\n}\n"); -} - -# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if SECP256K1_GNUC_PREREQ(2,7) -# define SECP256K1_INLINE __inline__ -# elif (defined(_MSC_VER)) -# define SECP256K1_INLINE __inline -# else -# define SECP256K1_INLINE -# endif -# else -# define SECP256K1_INLINE inline -# endif - -/** Assert statically that expr is true. - * - * This is a statement-like macro and can only be used inside functions. - */ -#define STATIC_ASSERT(expr) do { \ - switch(0) { \ - case 0: \ - /* If expr evaluates to 0, we have two case labels "0", which is illegal. */ \ - case /* ERROR: static assertion failed */ (expr): \ - ; \ - } \ -} while(0) - -/** Assert statically that expr is an integer constant expression, and run stmt. - * - * Useful for example to enforce that magnitude arguments are constant. - */ -#define ASSERT_INT_CONST_AND_DO(expr, stmt) do { \ - switch(42) { \ - /* C allows only integer constant expressions as case labels. */ \ - case /* ERROR: integer argument is not constant */ (expr): \ - break; \ - default: ; \ - } \ - stmt; \ -} while(0) - -typedef struct { - void (*fn)(const char *text, void* data); - const void* data; -} secp256k1_callback; - -static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) { - cb->fn(text, (void*)cb->data); -} - -#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS -static void secp256k1_default_illegal_callback_fn(const char* str, void* data) { - (void)data; - fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); - abort(); -} -static void secp256k1_default_error_callback_fn(const char* str, void* data) { - (void)data; - fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); - abort(); -} -#else -void secp256k1_default_illegal_callback_fn(const char* str, void* data); -void secp256k1_default_error_callback_fn(const char* str, void* data); -#endif - -static const secp256k1_callback default_illegal_callback = { - secp256k1_default_illegal_callback_fn, - NULL -}; - -static const secp256k1_callback default_error_callback = { - secp256k1_default_error_callback_fn, - NULL -}; - - -#ifdef DETERMINISTIC -#define TEST_FAILURE(msg) do { \ - fprintf(stderr, "%s\n", msg); \ - abort(); \ -} while(0); -#else -#define TEST_FAILURE(msg) do { \ - fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ - abort(); \ -} while(0) -#endif - -#if SECP256K1_GNUC_PREREQ(3, 0) -#define EXPECT(x,c) __builtin_expect((x),(c)) -#else -#define EXPECT(x,c) (x) -#endif - -#ifdef DETERMINISTIC -#define CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - TEST_FAILURE("test condition failed"); \ - } \ -} while(0) -#else -#define CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - TEST_FAILURE("test condition failed: " #cond); \ - } \ -} while(0) -#endif - -/* Like assert(), but when VERIFY is defined. */ -#if defined(VERIFY) -#define VERIFY_CHECK CHECK -#else -#define VERIFY_CHECK(cond) -#endif - -static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) { - void *ret = malloc(size); - if (ret == NULL) { - secp256k1_callback_call(cb, "Out of memory"); - } - return ret; -} - -#if defined(__BIGGEST_ALIGNMENT__) -#define ALIGNMENT __BIGGEST_ALIGNMENT__ -#else -/* Using 16 bytes alignment because common architectures never have alignment - * requirements above 8 for any of the types we care about. In addition we - * leave some room because currently we don't care about a few bytes. */ -#define ALIGNMENT 16 -#endif - -/* ceil(x/y) for integers x > 0 and y > 0. Here, / denotes rational division. */ -#define CEIL_DIV(x, y) (1 + ((x) - 1) / (y)) - -#define ROUND_TO_ALIGN(size) (CEIL_DIV(size, ALIGNMENT) * ALIGNMENT) - -/* Macro for restrict, when available and not in a VERIFY build. */ -#if defined(SECP256K1_BUILD) && defined(VERIFY) -# define SECP256K1_RESTRICT -#else -# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if SECP256K1_GNUC_PREREQ(3,0) -# define SECP256K1_RESTRICT __restrict__ -# elif (defined(_MSC_VER) && _MSC_VER >= 1400) -# define SECP256K1_RESTRICT __restrict -# else -# define SECP256K1_RESTRICT -# endif -# else -# define SECP256K1_RESTRICT restrict -# endif -#endif - -#if defined(__GNUC__) -# define SECP256K1_GNUC_EXT __extension__ -#else -# define SECP256K1_GNUC_EXT -#endif - -/* Zero memory if flag == 1. Flag must be 0 or 1. Constant time. */ -static SECP256K1_INLINE void secp256k1_memczero(void *s, size_t len, int flag) { - unsigned char *p = (unsigned char *)s; - /* Access flag with a volatile-qualified lvalue. - This prevents clang from figuring out (after inlining) that flag can - take only be 0 or 1, which leads to variable time code. */ - volatile int vflag = flag; - unsigned char mask = -(unsigned char) vflag; - while (len) { - *p &= ~mask; - p++; - len--; - } -} - -/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ -static SECP256K1_INLINE void secp256k1_memclear(void *ptr, size_t len) { -#if defined(_MSC_VER) - /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */ - SecureZeroMemory(ptr, len); -#elif defined(__GNUC__) - /* We use a memory barrier that scares the compiler away from optimizing out the memset. - * - * Quoting Adam Langley in commit ad1907fe73334d6c696c8539646c21b11178f20f - * in BoringSSL (ISC License): - * As best as we can tell, this is sufficient to break any optimisations that - * might try to eliminate "superfluous" memsets. - * This method is used in memzero_explicit() the Linux kernel, too. Its advantage is that it - * is pretty efficient, because the compiler can still implement the memset() efficently, - * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by - * Yang et al. (USENIX Security 2017) for more background. - */ - memset(ptr, 0, len); - __asm__ __volatile__("" : : "r"(ptr) : "memory"); -#else - void *(*volatile const volatile_memset)(void *, int, size_t) = memset; - volatile_memset(ptr, 0, len); -#endif -#ifdef VERIFY - SECP256K1_CHECKMEM_UNDEFINE(ptr, len); -#endif -} - -/** Semantics like memcmp. Variable-time. - * - * We use this to avoid possible compiler bugs with memcmp, e.g. - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189 - */ -static SECP256K1_INLINE int secp256k1_memcmp_var(const void *s1, const void *s2, size_t n) { - const unsigned char *p1 = s1, *p2 = s2; - size_t i; - - for (i = 0; i < n; i++) { - int diff = p1[i] - p2[i]; - if (diff != 0) { - return diff; - } - } - return 0; -} - -/* Return 1 if all elements of array s are 0 and otherwise return 0. - * Constant-time. */ -static SECP256K1_INLINE int secp256k1_is_zero_array(const unsigned char *s, size_t len) { - unsigned char acc = 0; - int ret; - size_t i; - - for (i = 0; i < len; i++) { - acc |= s[i]; - } - ret = (acc == 0); - /* acc may contain secret values. Try to explicitly clear it. */ - secp256k1_memclear(&acc, sizeof(acc)); - return ret; -} - -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/ -static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) { - unsigned int mask0, mask1, r_masked, a_masked; - /* Access flag with a volatile-qualified lvalue. - This prevents clang from figuring out (after inlining) that flag can - take only be 0 or 1, which leads to variable time code. */ - volatile int vflag = flag; - - /* Casting a negative int to unsigned and back to int is implementation defined behavior */ - VERIFY_CHECK(*r >= 0 && *a >= 0); - - mask0 = (unsigned int)vflag + ~0u; - mask1 = ~mask0; - r_masked = ((unsigned int)*r & mask0); - a_masked = ((unsigned int)*a & mask1); - - *r = (int)(r_masked | a_masked); -} - -#if defined(USE_FORCE_WIDEMUL_INT128_STRUCT) -/* If USE_FORCE_WIDEMUL_INT128_STRUCT is set, use int128_struct. */ -# define SECP256K1_WIDEMUL_INT128 1 -# define SECP256K1_INT128_STRUCT 1 -#elif defined(USE_FORCE_WIDEMUL_INT128) -/* If USE_FORCE_WIDEMUL_INT128 is set, use int128. */ -# define SECP256K1_WIDEMUL_INT128 1 -# define SECP256K1_INT128_NATIVE 1 -#elif defined(USE_FORCE_WIDEMUL_INT64) -/* If USE_FORCE_WIDEMUL_INT64 is set, use int64. */ -# define SECP256K1_WIDEMUL_INT64 1 -#elif defined(UINT128_MAX) || defined(__SIZEOF_INT128__) -/* If a native 128-bit integer type exists, use int128. */ -# define SECP256K1_WIDEMUL_INT128 1 -# define SECP256K1_INT128_NATIVE 1 -#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) -/* On 64-bit MSVC targets (x86_64 and arm64), use int128_struct - * (which has special logic to implement using intrinsics on those systems). */ -# define SECP256K1_WIDEMUL_INT128 1 -# define SECP256K1_INT128_STRUCT 1 -#elif SIZE_MAX > 0xffffffff -/* Systems with 64-bit pointers (and thus registers) very likely benefit from - * using 64-bit based arithmetic (even if we need to fall back to 32x32->64 based - * multiplication logic). */ -# define SECP256K1_WIDEMUL_INT128 1 -# define SECP256K1_INT128_STRUCT 1 -#else -/* Lastly, fall back to int64 based arithmetic. */ -# define SECP256K1_WIDEMUL_INT64 1 -#endif - -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -/* Determine the number of trailing zero bits in a (non-zero) 32-bit x. - * This function is only intended to be used as fallback for - * secp256k1_ctz32_var, but permits it to be tested separately. */ -static SECP256K1_INLINE int secp256k1_ctz32_var_debruijn(uint32_t x) { - static const uint8_t debruijn[32] = { - 0x00, 0x01, 0x02, 0x18, 0x03, 0x13, 0x06, 0x19, 0x16, 0x04, 0x14, 0x0A, - 0x10, 0x07, 0x0C, 0x1A, 0x1F, 0x17, 0x12, 0x05, 0x15, 0x09, 0x0F, 0x0B, - 0x1E, 0x11, 0x08, 0x0E, 0x1D, 0x0D, 0x1C, 0x1B - }; - return debruijn[(uint32_t)((x & -x) * 0x04D7651FU) >> 27]; -} - -/* Determine the number of trailing zero bits in a (non-zero) 64-bit x. - * This function is only intended to be used as fallback for - * secp256k1_ctz64_var, but permits it to be tested separately. */ -static SECP256K1_INLINE int secp256k1_ctz64_var_debruijn(uint64_t x) { - static const uint8_t debruijn[64] = { - 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, - 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, - 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, - 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 - }; - return debruijn[(uint64_t)((x & -x) * 0x022FDD63CC95386DU) >> 58]; -} - -/* Determine the number of trailing zero bits in a (non-zero) 32-bit x. */ -static SECP256K1_INLINE int secp256k1_ctz32_var(uint32_t x) { - VERIFY_CHECK(x != 0); -#if (__has_builtin(__builtin_ctz) || SECP256K1_GNUC_PREREQ(3,4)) - /* If the unsigned type is sufficient to represent the largest uint32_t, consider __builtin_ctz. */ - if (((unsigned)UINT32_MAX) == UINT32_MAX) { - return __builtin_ctz(x); - } -#endif -#if (__has_builtin(__builtin_ctzl) || SECP256K1_GNUC_PREREQ(3,4)) - /* Otherwise consider __builtin_ctzl (the unsigned long type is always at least 32 bits). */ - return __builtin_ctzl(x); -#else - /* If no suitable CTZ builtin is available, use a (variable time) software emulation. */ - return secp256k1_ctz32_var_debruijn(x); -#endif -} - -/* Determine the number of trailing zero bits in a (non-zero) 64-bit x. */ -static SECP256K1_INLINE int secp256k1_ctz64_var(uint64_t x) { - VERIFY_CHECK(x != 0); -#if (__has_builtin(__builtin_ctzl) || SECP256K1_GNUC_PREREQ(3,4)) - /* If the unsigned long type is sufficient to represent the largest uint64_t, consider __builtin_ctzl. */ - if (((unsigned long)UINT64_MAX) == UINT64_MAX) { - return __builtin_ctzl(x); - } -#endif -#if (__has_builtin(__builtin_ctzll) || SECP256K1_GNUC_PREREQ(3,4)) - /* Otherwise consider __builtin_ctzll (the unsigned long long type is always at least 64 bits). */ - return __builtin_ctzll(x); -#else - /* If no suitable CTZ builtin is available, use a (variable time) software emulation. */ - return secp256k1_ctz64_var_debruijn(x); -#endif -} - -/* Read a uint32_t in big endian */ -SECP256K1_INLINE static uint32_t secp256k1_read_be32(const unsigned char* p) { - return (uint32_t)p[0] << 24 | - (uint32_t)p[1] << 16 | - (uint32_t)p[2] << 8 | - (uint32_t)p[3]; -} - -/* Write a uint32_t in big endian */ -SECP256K1_INLINE static void secp256k1_write_be32(unsigned char* p, uint32_t x) { - p[3] = x; - p[2] = x >> 8; - p[1] = x >> 16; - p[0] = x >> 24; -} - -/* Read a uint64_t in big endian */ -SECP256K1_INLINE static uint64_t secp256k1_read_be64(const unsigned char* p) { - return (uint64_t)p[0] << 56 | - (uint64_t)p[1] << 48 | - (uint64_t)p[2] << 40 | - (uint64_t)p[3] << 32 | - (uint64_t)p[4] << 24 | - (uint64_t)p[5] << 16 | - (uint64_t)p[6] << 8 | - (uint64_t)p[7]; -} - -/* Write a uint64_t in big endian */ -SECP256K1_INLINE static void secp256k1_write_be64(unsigned char* p, uint64_t x) { - p[7] = x; - p[6] = x >> 8; - p[5] = x >> 16; - p[4] = x >> 24; - p[3] = x >> 32; - p[2] = x >> 40; - p[1] = x >> 48; - p[0] = x >> 56; -} - -/* Rotate a uint32_t to the right. */ -SECP256K1_INLINE static uint32_t secp256k1_rotr32(const uint32_t x, const unsigned int by) { -#if defined(_MSC_VER) - return _rotr(x, by); /* needs */ -#else - /* Reduce rotation amount to avoid UB when shifting. */ - const unsigned int mask = CHAR_BIT * sizeof(x) - 1; - /* Turned into a rot instruction by GCC and clang. */ - return (x >> (by & mask)) | (x << ((-by) & mask)); -#endif -} - -#endif /* SECP256K1_UTIL_H */ diff --git a/external/secp256k1/src/wycheproof/WYCHEPROOF_COPYING b/external/secp256k1/src/wycheproof/WYCHEPROOF_COPYING deleted file mode 100644 index cddf9d9182..0000000000 --- a/external/secp256k1/src/wycheproof/WYCHEPROOF_COPYING +++ /dev/null @@ -1,212 +0,0 @@ -* The file `ecdsa_secp256k1_sha256_bitcoin_test.json` in this directory - comes from Google's project Wycheproof with git commit - `b063b4aedae951c69df014cd25fa6d69ae9e8cb9`, see - https://github.com/google/wycheproof/blob/b063b4aedae951c69df014cd25fa6d69ae9e8cb9/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json - -* The file `ecdsa_secp256k1_sha256_bitcoin_test.h` is generated from - `ecdsa_secp256k1_sha256_bitcoin_test.json` using the script - `tests_wycheproof_generate.py`. - -------------------------------------------------------------------------------- - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/external/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h b/external/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h deleted file mode 100644 index 736737fd61..0000000000 --- a/external/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h +++ /dev/null @@ -1,1564 +0,0 @@ -/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */ -#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS (463) - -typedef struct { - size_t pk_offset; - size_t msg_offset; - size_t msg_len; - size_t sig_offset; - size_t sig_len; - int expected_verify; -} wycheproof_ecdsa_testvector; - -static const unsigned char wycheproof_ecdsa_messages[] = { 0x31,0x32,0x33,0x34,0x30,0x30, - 0x32,0x35,0x35,0x38,0x35, - 0x34,0x32,0x36,0x34,0x37,0x39,0x37,0x32,0x34, - 0x37,0x31,0x33,0x38,0x36,0x38,0x34,0x38,0x39,0x31, - 0x31,0x30,0x33,0x35,0x39,0x33,0x33,0x31,0x36,0x36,0x38, - 0x33,0x39,0x34,0x39,0x34,0x30,0x31,0x32,0x31,0x35, - 0x31,0x33,0x34,0x34,0x32,0x39,0x33,0x30,0x37,0x39, - 0x33,0x37,0x30,0x36,0x32,0x31,0x31,0x37,0x31,0x32, - 0x33,0x34,0x33,0x36,0x38,0x38,0x37,0x31,0x32, - 0x31,0x33,0x35,0x31,0x35,0x33,0x30,0x33,0x37,0x30, - 0x36,0x35,0x35,0x33,0x32,0x30,0x33,0x31,0x32,0x36, - 0x31,0x35,0x36,0x34,0x33,0x34,0x36,0x36,0x30,0x33, - 0x34,0x34,0x32,0x39,0x35,0x33,0x39,0x31,0x31,0x37, - 0x31,0x30,0x39,0x35,0x33,0x32,0x36,0x31,0x33,0x35,0x31, - 0x35,0x39,0x38,0x37,0x33,0x35,0x30,0x30,0x34,0x31, - 0x33,0x34,0x36,0x33,0x30,0x30,0x36,0x38,0x37,0x38, - 0x39,0x38,0x31,0x37,0x33,0x32,0x30,0x32,0x38,0x37, - 0x33,0x32,0x32,0x32,0x30,0x34,0x31,0x30,0x34,0x36, - 0x36,0x36,0x36,0x36,0x33,0x30,0x37,0x31,0x30,0x34, - 0x31,0x30,0x33,0x35,0x39,0x35,0x31,0x38,0x39,0x38, - 0x31,0x38,0x34,0x36,0x35,0x39,0x37,0x31,0x39,0x35, - 0x33,0x31,0x33,0x36,0x30,0x34,0x36,0x31,0x38,0x39, - 0x32,0x36,0x36,0x33,0x37,0x38,0x34,0x32,0x35,0x34, - 0x31,0x36,0x35,0x32,0x31,0x30,0x30,0x35,0x32,0x34, - 0x35,0x37,0x34,0x38,0x30,0x38,0x31,0x36,0x39,0x36, - 0x36,0x33,0x34,0x33,0x39,0x31,0x33,0x34,0x36,0x38, - 0x31,0x35,0x34,0x31,0x31,0x30,0x33,0x35,0x39,0x38, - 0x31,0x30,0x34,0x37,0x38,0x35,0x38,0x30,0x31,0x32,0x38, - 0x31,0x30,0x35,0x33,0x36,0x32,0x38,0x35,0x35,0x36,0x38, - 0x39,0x35,0x33,0x39,0x30,0x34,0x31,0x30,0x35, - 0x39,0x37,0x38,0x38,0x34,0x38,0x30,0x33,0x39, - 0x33,0x36,0x31,0x30,0x36,0x37,0x32,0x34,0x34,0x32, - 0x31,0x30,0x35,0x34,0x32,0x34,0x30,0x37,0x30,0x35, - 0x35,0x31,0x37,0x34,0x34,0x34,0x38,0x31,0x39,0x37, - 0x31,0x39,0x36,0x37,0x35,0x36,0x31,0x32,0x35,0x31, - 0x33,0x34,0x34,0x37,0x32,0x35,0x33,0x33,0x34,0x33, - 0x33,0x36,0x38,0x32,0x36,0x34,0x33,0x31,0x38, - 0x33,0x32,0x36,0x31,0x31,0x39,0x38,0x36,0x30,0x38, - 0x39,0x36,0x37,0x38,0x37,0x38,0x31,0x30,0x39,0x34, - 0x34,0x39,0x35,0x38,0x38,0x32,0x33,0x38,0x32,0x33, - 0x38,0x32,0x34,0x36,0x33,0x37,0x38,0x33,0x37, - 0x31,0x31,0x30,0x32,0x30,0x38,0x33,0x33,0x37,0x37,0x36, - 0x31,0x33,0x33,0x38,0x37,0x31,0x36,0x34,0x38, - 0x33,0x32,0x32,0x31,0x34,0x34,0x31,0x36,0x32, - 0x31,0x30,0x36,0x38,0x36,0x36,0x35,0x35,0x35,0x34,0x36, - 0x36,0x32,0x31,0x35,0x35,0x32,0x34,0x36, - 0x37,0x30,0x33,0x30,0x38,0x31,0x38,0x37,0x37,0x34, - 0x35,0x39,0x32,0x34,0x35,0x32,0x33,0x37,0x34,0x34, - 0x31,0x34,0x39,0x35,0x35,0x38,0x36,0x36,0x32,0x31, - 0x34,0x30,0x30,0x35,0x33,0x31,0x34,0x34,0x30,0x36, - 0x33,0x30,0x39,0x36,0x34,0x35,0x37,0x35,0x31,0x32, - 0x32,0x37,0x38,0x34,0x30,0x32,0x35,0x36,0x32,0x30, - 0x32,0x36,0x31,0x38,0x37,0x38,0x37,0x34,0x31,0x38, - 0x31,0x36,0x34,0x32,0x36,0x32,0x35,0x32,0x36,0x32, - 0x36,0x38,0x32,0x34,0x31,0x38,0x39,0x34,0x33,0x36, - 0x34,0x38,0x34,0x32,0x34,0x35,0x34,0x32,0x35, - 0x4d,0x73,0x67, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x4d,0x65,0x73,0x73,0x61,0x67,0x65}; - -static const unsigned char wycheproof_ecdsa_public_keys[] = { 0x04,0xb8,0x38,0xff,0x44,0xe5,0xbc,0x17,0x7b,0xf2,0x11,0x89,0xd0,0x76,0x60,0x82,0xfc,0x9d,0x84,0x32,0x26,0x88,0x7f,0xc9,0x76,0x03,0x71,0x10,0x0b,0x7e,0xe2,0x0a,0x6f,0xf0,0xc9,0xd7,0x5b,0xfb,0xa7,0xb3,0x1a,0x6b,0xca,0x19,0x74,0x49,0x6e,0xeb,0x56,0xde,0x35,0x70,0x71,0x95,0x5d,0x83,0xc4,0xb1,0xba,0xda,0xa0,0xb2,0x18,0x32,0xe9, - 0x04,0x07,0x31,0x0f,0x90,0xa9,0xea,0xe1,0x49,0xa0,0x84,0x02,0xf5,0x41,0x94,0xa0,0xf7,0xb4,0xac,0x42,0x7b,0xf8,0xd9,0xbd,0x6c,0x76,0x81,0x07,0x1d,0xc4,0x7d,0xc3,0x62,0x26,0xa6,0xd3,0x7a,0xc4,0x6d,0x61,0xfd,0x60,0x0c,0x0b,0xf1,0xbf,0xf8,0x76,0x89,0xed,0x11,0x7d,0xda,0x6b,0x0e,0x59,0x31,0x8a,0xe0,0x10,0xa1,0x97,0xa2,0x6c,0xa0, - 0x04,0xbc,0x97,0xe7,0x58,0x5e,0xec,0xad,0x48,0xe1,0x66,0x83,0xbc,0x40,0x91,0x70,0x8e,0x1a,0x93,0x0c,0x68,0x3f,0xc4,0x70,0x01,0xd4,0xb3,0x83,0x59,0x4f,0x2c,0x4e,0x22,0x70,0x59,0x89,0xcf,0x69,0xda,0xea,0xdd,0x4e,0x4e,0x4b,0x81,0x51,0xed,0x88,0x8d,0xfe,0xc2,0x0f,0xb0,0x17,0x28,0xd8,0x9d,0x56,0xb3,0xf3,0x8f,0x2a,0xe9,0xc8,0xc5, - 0x04,0x44,0xad,0x33,0x9a,0xfb,0xc2,0x1e,0x9a,0xbf,0x7b,0x60,0x2a,0x5c,0xa5,0x35,0xea,0x37,0x81,0x35,0xb6,0xd1,0x0d,0x81,0x31,0x0b,0xdd,0x82,0x93,0xd1,0xdf,0x32,0x52,0xb6,0x3f,0xf7,0xd0,0x77,0x47,0x70,0xf8,0xfe,0x1d,0x17,0x22,0xfa,0x83,0xac,0xd0,0x2f,0x43,0x4e,0x4f,0xc1,0x10,0xa0,0xcc,0x8f,0x6d,0xdd,0xd3,0x7d,0x56,0xc4,0x63, - 0x04,0x12,0x60,0xc2,0x12,0x2c,0x9e,0x24,0x4e,0x1a,0xf5,0x15,0x1b,0xed,0xe0,0xc3,0xae,0x23,0xb5,0x4d,0x7c,0x59,0x68,0x81,0xd3,0xee,0xba,0xd2,0x1f,0x37,0xdd,0x87,0x8c,0x5c,0x9a,0x0c,0x1a,0x9a,0xde,0x76,0x73,0x7a,0x88,0x11,0xbd,0x6a,0x7f,0x92,0x87,0xc9,0x78,0xee,0x39,0x6a,0xa8,0x9c,0x11,0xe4,0x72,0x29,0xd2,0xcc,0xb5,0x52,0xf0, - 0x04,0x18,0x77,0x04,0x5b,0xe2,0x5d,0x34,0xa1,0xd0,0x60,0x0f,0x9d,0x5c,0x00,0xd0,0x64,0x5a,0x2a,0x54,0x37,0x9b,0x6c,0xee,0xfa,0xd2,0xe6,0xbf,0x5c,0x2a,0x33,0x52,0xce,0x82,0x1a,0x53,0x2c,0xc1,0x75,0x1e,0xe1,0xd3,0x6d,0x41,0xc3,0xd6,0xab,0x4e,0x9b,0x14,0x3e,0x44,0xec,0x46,0xd7,0x34,0x78,0xea,0x6a,0x79,0xa5,0xc0,0xe5,0x41,0x59, - 0x04,0x45,0x54,0x39,0xfc,0xc3,0xd2,0xde,0xec,0xed,0xde,0xae,0xce,0x60,0xe7,0xbd,0x17,0x30,0x4f,0x36,0xeb,0xb6,0x02,0xad,0xf5,0xa2,0x2e,0x0b,0x8f,0x1d,0xb4,0x6a,0x50,0xae,0xc3,0x8f,0xb2,0xba,0xf2,0x21,0xe9,0xa8,0xd1,0x88,0x7c,0x7b,0xf6,0x22,0x2d,0xd1,0x83,0x46,0x34,0xe7,0x72,0x63,0x31,0x5a,0xf6,0xd2,0x36,0x09,0xd0,0x4f,0x77, - 0x04,0x2e,0x1f,0x46,0x6b,0x02,0x4c,0x0c,0x3a,0xce,0x24,0x37,0xde,0x09,0x12,0x7f,0xed,0x04,0xb7,0x06,0xf9,0x4b,0x19,0xa2,0x1b,0xb1,0xc2,0xac,0xf3,0x5c,0xec,0xe7,0x18,0x04,0x49,0xae,0x35,0x23,0xd7,0x25,0x34,0xe9,0x64,0x97,0x2c,0xfd,0x3b,0x38,0xaf,0x0b,0xdd,0xd9,0x61,0x9e,0x5a,0xf2,0x23,0xe4,0xd1,0xa4,0x0f,0x34,0xcf,0x9f,0x1d, - 0x04,0x8e,0x7a,0xbd,0xbb,0xd1,0x8d,0xe7,0x45,0x23,0x74,0xc1,0x87,0x9a,0x1c,0x3b,0x01,0xd1,0x32,0x61,0xe7,0xd4,0x57,0x1c,0x3b,0x47,0xa1,0xc7,0x6c,0x55,0xa2,0x33,0x73,0x26,0xed,0x89,0x7c,0xd5,0x17,0xa4,0xf5,0x34,0x9d,0xb8,0x09,0x78,0x0f,0x6d,0x2f,0x2b,0x9f,0x62,0x99,0xd8,0xb5,0xa8,0x90,0x77,0xf1,0x11,0x9a,0x71,0x8f,0xd7,0xb3, - 0x04,0x7b,0x33,0x3d,0x43,0x40,0xd3,0xd7,0x18,0xdd,0x3e,0x6a,0xff,0x7d,0xe7,0xbb,0xf8,0xb7,0x2b,0xfd,0x61,0x6c,0x84,0x20,0x05,0x60,0x52,0x84,0x23,0x76,0xb9,0xaf,0x19,0x42,0x11,0x7c,0x5a,0xfe,0xac,0x75,0x5d,0x6f,0x37,0x6f,0xc6,0x32,0x9a,0x7d,0x76,0x05,0x1b,0x87,0x12,0x3a,0x4a,0x5d,0x0b,0xc4,0xa5,0x39,0x38,0x0f,0x03,0xde,0x7b, - 0x04,0xd3,0x0c,0xa4,0xa0,0xdd,0xb6,0x61,0x6c,0x85,0x1d,0x30,0xce,0xd6,0x82,0xc4,0x0f,0x83,0xc6,0x27,0x58,0xa1,0xf2,0x75,0x99,0x88,0xd6,0x76,0x3a,0x88,0xf1,0xc0,0xe5,0x03,0xa8,0x0d,0x54,0x15,0x65,0x0d,0x41,0x23,0x97,0x84,0xe8,0xe2,0xfb,0x12,0x35,0xe9,0xfe,0x99,0x1d,0x11,0x2e,0xbb,0x81,0x18,0x6c,0xbf,0x0d,0xa2,0xde,0x3a,0xff, - 0x04,0x48,0x96,0x9b,0x39,0x99,0x12,0x97,0xb3,0x32,0xa6,0x52,0xd3,0xee,0x6e,0x01,0xe9,0x09,0xb3,0x99,0x04,0xe7,0x1f,0xa2,0x35,0x4a,0x78,0x30,0xc7,0x75,0x0b,0xaf,0x24,0xb4,0x01,0x2d,0x1b,0x83,0x0d,0x19,0x9c,0xcb,0x1f,0xc9,0x72,0xb3,0x2b,0xfd,0xed,0x55,0xf0,0x9c,0xd6,0x2d,0x25,0x7e,0x5e,0x84,0x4e,0x27,0xe5,0x7a,0x15,0x94,0xec, - 0x04,0x02,0xef,0x4d,0x6d,0x6c,0xfd,0x5a,0x94,0xf1,0xd7,0x78,0x42,0x26,0xe3,0xe2,0xa6,0xc0,0xa4,0x36,0xc5,0x58,0x39,0x61,0x9f,0x38,0xfb,0x44,0x72,0xb5,0xf9,0xee,0x77,0x7e,0xb4,0xac,0xd4,0xee,0xbd,0xa5,0xcd,0x72,0x87,0x5f,0xfd,0x2a,0x2f,0x26,0x22,0x9c,0x2d,0xc6,0xb4,0x65,0x00,0x91,0x9a,0x43,0x2c,0x86,0x73,0x9f,0x3a,0xe8,0x66, - 0x04,0x46,0x4f,0x4f,0xf7,0x15,0x72,0x9c,0xae,0x50,0x72,0xca,0x3b,0xd8,0x01,0xd3,0x19,0x5b,0x67,0xae,0xc6,0x5e,0x9b,0x01,0xaa,0xd2,0x0a,0x29,0x43,0xdc,0xbc,0xb5,0x84,0xb1,0xaf,0xd2,0x9d,0x31,0xa3,0x9a,0x11,0xd5,0x70,0xaa,0x15,0x97,0x43,0x9b,0x3b,0x2d,0x19,0x71,0xbf,0x2f,0x1a,0xbf,0x15,0x43,0x2d,0x02,0x07,0xb1,0x0d,0x1d,0x08, - 0x04,0x15,0x7f,0x8f,0xdd,0xf3,0x73,0xeb,0x5f,0x49,0xcf,0xcf,0x10,0xd8,0xb8,0x53,0xcf,0x91,0xcb,0xcd,0x7d,0x66,0x5c,0x35,0x22,0xba,0x7d,0xd7,0x38,0xdd,0xb7,0x9a,0x4c,0xde,0xad,0xf1,0xa5,0xc4,0x48,0xea,0x3c,0x9f,0x41,0x91,0xa8,0x99,0x9a,0xbf,0xcc,0x75,0x7a,0xc6,0xd6,0x45,0x67,0xef,0x07,0x2c,0x47,0xfe,0xc6,0x13,0x44,0x3b,0x8f, - 0x04,0x09,0x34,0xa5,0x37,0x46,0x6c,0x07,0x43,0x0e,0x2c,0x48,0xfe,0xb9,0x90,0xbb,0x19,0xfb,0x78,0xce,0xcc,0x9c,0xee,0x42,0x4e,0xa4,0xd1,0x30,0x29,0x1a,0xa2,0x37,0xf0,0xd4,0xf9,0x2d,0x23,0xb4,0x62,0x80,0x4b,0x5b,0x68,0xc5,0x25,0x58,0xc0,0x1c,0x99,0x96,0xdb,0xf7,0x27,0xfc,0xca,0xbb,0xee,0xdb,0x96,0x21,0xa4,0x00,0x53,0x5a,0xfa, - 0x04,0xd6,0xef,0x20,0xbe,0x66,0xc8,0x93,0xf7,0x41,0xa9,0xbf,0x90,0xd9,0xb7,0x46,0x75,0xd1,0xc2,0xa3,0x12,0x96,0x39,0x7a,0xcb,0x3e,0xf1,0x74,0xfd,0x0b,0x30,0x0c,0x65,0x4a,0x0c,0x95,0x47,0x8c,0xa0,0x03,0x99,0x16,0x2d,0x7f,0x0f,0x2d,0xc8,0x9e,0xfd,0xc2,0xb2,0x8a,0x30,0xfb,0xab,0xe2,0x85,0x85,0x72,0x95,0xa4,0xb0,0xc4,0xe2,0x65, - 0x04,0xb7,0x29,0x1d,0x14,0x04,0xe0,0xc0,0xc0,0x7d,0xab,0x93,0x72,0x18,0x9f,0x4b,0xd5,0x8d,0x2c,0xea,0xa8,0xd1,0x5e,0xde,0x54,0x4d,0x95,0x14,0x54,0x5b,0xa9,0xee,0x06,0x29,0xc9,0xa6,0x3d,0x5e,0x30,0x87,0x69,0xcc,0x30,0xec,0x27,0x6a,0x41,0x0e,0x64,0x64,0xa2,0x7e,0xea,0xfd,0x9e,0x59,0x9d,0xb1,0x0f,0x05,0x3a,0x4f,0xe4,0xa8,0x29, - 0x04,0x6e,0x28,0x30,0x33,0x05,0xd6,0x42,0xcc,0xb9,0x23,0xb7,0x22,0xea,0x86,0xb2,0xa0,0xbc,0x8e,0x37,0x35,0xec,0xb2,0x6e,0x84,0x9b,0x19,0xc9,0xf7,0x6b,0x2f,0xdb,0xb8,0x18,0x6e,0x80,0xd6,0x4d,0x8c,0xab,0x16,0x4f,0x52,0x38,0xf5,0x31,0x84,0x61,0xbf,0x89,0xd4,0xd9,0x6e,0xe6,0x54,0x4c,0x81,0x6c,0x75,0x66,0x94,0x77,0x74,0xe0,0xf6, - 0x04,0x37,0x5b,0xda,0x93,0xf6,0xaf,0x92,0xfb,0x5f,0x8f,0x4b,0x1b,0x5f,0x05,0x34,0xe3,0xba,0xfa,0xb3,0x4c,0xb7,0xad,0x9f,0xb9,0xd0,0xb7,0x22,0xe4,0xa5,0xc3,0x02,0xa9,0xa0,0x0b,0x9f,0x38,0x7a,0x5a,0x39,0x60,0x97,0xaa,0x21,0x62,0xfc,0x5b,0xbc,0xf4,0xa5,0x26,0x33,0x72,0xf6,0x81,0xc9,0x4d,0xa5,0x1e,0x97,0x99,0x12,0x09,0x90,0xfd, - 0x04,0xd7,0x5b,0x68,0x21,0x6b,0xab,0xe0,0x3a,0xe2,0x57,0xe9,0x4b,0x4e,0x3b,0xf1,0xc5,0x2f,0x44,0xe3,0xdf,0x26,0x6d,0x15,0x24,0xff,0x8c,0x5e,0xa6,0x9d,0xa7,0x31,0x97,0xda,0x4b,0xff,0x9e,0xd1,0xc5,0x3f,0x44,0x91,0x7a,0x67,0xd7,0xb9,0x78,0x59,0x8e,0x89,0xdf,0x35,0x9e,0x3d,0x59,0x13,0xea,0xea,0x24,0xf3,0xae,0x25,0x9a,0xbc,0x44, - 0x04,0x78,0xbc,0xda,0x14,0x0a,0xed,0x23,0xd4,0x30,0xcb,0x23,0xc3,0xdc,0x0d,0x01,0xf4,0x23,0xdb,0x13,0x4e,0xe9,0x4a,0x3a,0x8c,0xb4,0x83,0xf2,0xde,0xac,0x2a,0xc6,0x53,0x11,0x81,0x14,0xf6,0xf3,0x30,0x45,0xd4,0xe9,0xed,0x91,0x07,0x08,0x50,0x07,0xbf,0xbd,0xdf,0x8f,0x58,0xfe,0x7a,0x1a,0x24,0x45,0xd6,0x6a,0x99,0x00,0x45,0x47,0x6e, - 0x04,0xbb,0x79,0xf6,0x18,0x57,0xf7,0x43,0xbf,0xa1,0xb6,0xe7,0x11,0x1c,0xe4,0x09,0x43,0x77,0x25,0x69,0x69,0xe4,0xe1,0x51,0x59,0x12,0x3d,0x95,0x48,0xac,0xc3,0xbe,0x6c,0x1f,0x9d,0x9f,0x88,0x60,0xdc,0xff,0xd3,0xeb,0x36,0xdd,0x6c,0x31,0xff,0x2e,0x72,0x26,0xc2,0x00,0x9c,0x4c,0x94,0xd8,0xd7,0xd2,0xb5,0x68,0x6b,0xf7,0xab,0xd6,0x77, - 0x04,0x93,0x59,0x18,0x27,0xd9,0xe6,0x71,0x3b,0x4e,0x9f,0xae,0xa6,0x2c,0x72,0xb2,0x8d,0xfe,0xfa,0x68,0xe0,0xc0,0x51,0x60,0xb5,0xd6,0xaa,0xe8,0x8f,0xd2,0xe3,0x6c,0x36,0x07,0x3f,0x55,0x45,0xad,0x5a,0xf4,0x10,0xaf,0x26,0xaf,0xff,0x68,0x65,0x4c,0xf7,0x2d,0x45,0xe4,0x93,0x48,0x93,0x11,0x20,0x32,0x47,0x34,0x7a,0x89,0x0f,0x45,0x18, - 0x04,0x31,0xed,0x30,0x81,0xae,0xfe,0x00,0x1e,0xb6,0x40,0x20,0x69,0xee,0x2c,0xcc,0x18,0x62,0x93,0x7b,0x85,0x99,0x51,0x44,0xdb,0xa9,0x50,0x39,0x43,0x58,0x7b,0xf0,0xda,0xda,0x01,0xb8,0xcc,0x4d,0xf3,0x4f,0x5a,0xb3,0xb1,0xa3,0x59,0x61,0x52,0x08,0x94,0x6e,0x5e,0xe3,0x5f,0x98,0xee,0x77,0x5b,0x8c,0xce,0xcd,0x86,0xcc,0xc1,0x65,0x0f, - 0x04,0x7d,0xff,0x66,0xfa,0x98,0x50,0x9f,0xf3,0xe2,0xe5,0x10,0x45,0xf4,0x39,0x05,0x23,0xdc,0xcd,0xa4,0x3a,0x3b,0xc2,0x88,0x5e,0x58,0xc2,0x48,0x09,0x09,0x90,0xee,0xa8,0x54,0xc7,0x6c,0x2b,0x9a,0xde,0xb6,0xbb,0x57,0x18,0x23,0xe0,0x7f,0xd7,0xc6,0x5c,0x86,0x39,0xcf,0x9d,0x90,0x52,0x60,0x06,0x4c,0x8e,0x76,0x75,0xce,0x6d,0x98,0xb4, - 0x04,0x42,0x80,0x50,0x9a,0xab,0x64,0xed,0xfc,0x0b,0x4a,0x29,0x67,0xe4,0xcb,0xce,0x84,0x9c,0xb5,0x44,0xe4,0xa7,0x73,0x13,0xc8,0xe6,0xec,0xe5,0x79,0xfb,0xd7,0x42,0x0a,0x2e,0x89,0xfe,0x5c,0xc1,0x92,0x7d,0x55,0x4e,0x6a,0x3b,0xb1,0x40,0x33,0xea,0x7c,0x92,0x2c,0xd7,0x5c,0xba,0x2c,0x74,0x15,0xfd,0xab,0x52,0xf2,0x0b,0x18,0x60,0xf1, - 0x04,0x4f,0x8d,0xf1,0x45,0x19,0x4e,0x3c,0x4f,0xc3,0xee,0xa2,0x6d,0x43,0xce,0x75,0xb4,0x02,0xd6,0xb1,0x74,0x72,0xdd,0xcb,0xb2,0x54,0xb8,0xa7,0x9b,0x0b,0xf3,0xd9,0xcb,0x2a,0xa2,0x0d,0x82,0x84,0x4c,0xb2,0x66,0x34,0x4e,0x71,0xca,0x78,0xf2,0xad,0x27,0xa7,0x5a,0x09,0xe5,0xbc,0x0f,0xa5,0x7e,0x4e,0xfd,0x9d,0x46,0x5a,0x08,0x88,0xdb, - 0x04,0x95,0x98,0xa5,0x7d,0xd6,0x7e,0xc3,0xe1,0x6b,0x58,0x7a,0x33,0x8a,0xa3,0xa1,0x0a,0x3a,0x39,0x13,0xb4,0x1a,0x3a,0xf3,0x2e,0x3e,0xd3,0xff,0x01,0x35,0x8c,0x6b,0x14,0x12,0x28,0x19,0xed,0xf8,0x07,0x4b,0xbc,0x52,0x1f,0x7d,0x4c,0xdc,0xe8,0x2f,0xef,0x7a,0x51,0x67,0x06,0xaf,0xfb,0xa1,0xd9,0x3d,0x9d,0xea,0x9c,0xca,0xe1,0xa2,0x07, - 0x04,0x91,0x71,0xfe,0xc3,0xca,0x20,0x80,0x6b,0xc0,0x84,0xf1,0x2f,0x07,0x60,0x91,0x1b,0x60,0x99,0x0b,0xd8,0x0e,0x5b,0x2a,0x71,0xca,0x03,0xa0,0x48,0xb2,0x0f,0x83,0x7e,0x63,0x4f,0xd1,0x78,0x63,0x76,0x1b,0x29,0x58,0xd2,0xbe,0x4e,0x14,0x9f,0x8d,0x3d,0x7a,0xbb,0xdc,0x18,0xbe,0x03,0xf4,0x51,0xab,0x6c,0x17,0xfa,0x0a,0x1f,0x83,0x30, - 0x04,0x77,0x7c,0x89,0x30,0xb6,0xe1,0xd2,0x71,0x10,0x0f,0xe6,0x8c,0xe9,0x3f,0x16,0x3f,0xa3,0x76,0x12,0xc5,0xff,0xf6,0x7f,0x4a,0x62,0xfc,0x3b,0xaf,0xaf,0x3d,0x17,0xa9,0xed,0x73,0xd8,0x6f,0x60,0xa5,0x1b,0x5e,0xd9,0x13,0x53,0xa3,0xb0,0x54,0xed,0xc0,0xaa,0x92,0xc9,0xeb,0xcb,0xd0,0xb7,0x5d,0x18,0x8f,0xdc,0x88,0x27,0x91,0xd6,0x8d, - 0x04,0xea,0xbc,0x24,0x8f,0x62,0x6e,0x0a,0x63,0xe1,0xeb,0x81,0xc4,0x3d,0x46,0x1a,0x39,0xa1,0xdb,0xa8,0x81,0xeb,0x6e,0xe2,0x15,0x2b,0x07,0xc3,0x2d,0x71,0xbc,0xf4,0x70,0x06,0x03,0xca,0xa8,0xb9,0xd3,0x3d,0xb1,0x3a,0xf4,0x4c,0x6e,0xfb,0xec,0x8a,0x19,0x8e,0xd6,0x12,0x4a,0xc9,0xeb,0x17,0xea,0xaf,0xd2,0x82,0x4a,0x54,0x5e,0xc0,0x00, - 0x04,0x9f,0x7a,0x13,0xad,0xa1,0x58,0xa5,0x5f,0x9d,0xdf,0x1a,0x45,0xf0,0x44,0xf0,0x73,0xd9,0xb8,0x00,0x30,0xef,0xdc,0xfc,0x9f,0x9f,0x58,0x41,0x8f,0xbc,0xea,0xf0,0x01,0xf8,0xad,0xa0,0x17,0x50,0x90,0xf8,0x0d,0x47,0x22,0x7d,0x67,0x13,0xb6,0x74,0x0f,0x9a,0x00,0x91,0xd8,0x8a,0x83,0x7d,0x0a,0x1c,0xd7,0x7b,0x58,0xa8,0xf2,0x8d,0x73, - 0x04,0x11,0xc4,0xf3,0xe4,0x61,0xcd,0x01,0x9b,0x5c,0x06,0xea,0x0c,0xea,0x4c,0x40,0x90,0xc3,0xcc,0x3e,0x3c,0x5d,0x9f,0x3c,0x6d,0x65,0xb4,0x36,0x82,0x6d,0xa9,0xb4,0xdb,0xbb,0xeb,0x7a,0x77,0xe4,0xcb,0xfd,0xa2,0x07,0x09,0x7c,0x43,0x42,0x37,0x05,0xf7,0x2c,0x80,0x47,0x6d,0xa3,0xda,0xc4,0x0a,0x48,0x3b,0x0a,0xb0,0xf2,0xea,0xd1,0xcb, - 0x04,0xe2,0xe1,0x86,0x82,0xd5,0x31,0x23,0xaa,0x01,0xa6,0xc5,0xd0,0x0b,0x0c,0x62,0x3d,0x67,0x1b,0x46,0x2e,0xa8,0x0b,0xdd,0xd6,0x52,0x27,0xfd,0x51,0x05,0x98,0x8a,0xa4,0x16,0x19,0x07,0xb3,0xfd,0x25,0x04,0x4a,0x94,0x9e,0xa4,0x1c,0x8e,0x2e,0xa8,0x45,0x9d,0xc6,0xf1,0x65,0x48,0x56,0xb8,0xb6,0x1b,0x31,0x54,0x3b,0xb1,0xb4,0x5b,0xdb, - 0x04,0x90,0xf8,0xd4,0xca,0x73,0xde,0x08,0xa6,0x56,0x4a,0xaf,0x00,0x52,0x47,0xb6,0xf0,0xff,0xe9,0x78,0x50,0x4d,0xce,0x52,0x60,0x5f,0x46,0xb7,0xc3,0xe5,0x61,0x97,0xda,0xfa,0xdb,0xe5,0x28,0xeb,0x70,0xd9,0xee,0x7e,0xa0,0xe7,0x07,0x02,0xdb,0x54,0xf7,0x21,0x51,0x4c,0x7b,0x86,0x04,0xac,0x2c,0xb2,0x14,0xf1,0xde,0xcb,0x7e,0x38,0x3d, - 0x04,0x82,0x4c,0x19,0x5c,0x73,0xcf,0xfd,0xf0,0x38,0xd1,0x01,0xbc,0xe1,0x68,0x7b,0x5c,0x3b,0x61,0x46,0xf3,0x95,0xc8,0x85,0x97,0x6f,0x77,0x53,0xb2,0x37,0x6b,0x94,0x8e,0x3c,0xde,0xfa,0x6f,0xc3,0x47,0xd1,0x3e,0x4d,0xcb,0xc6,0x3a,0x0b,0x03,0xa1,0x65,0x18,0x0c,0xd2,0xbe,0x14,0x31,0xa0,0xcf,0x74,0xce,0x1e,0xa2,0x50,0x82,0xd2,0xbc, - 0x04,0x27,0x88,0xa5,0x2f,0x07,0x8e,0xb3,0xf2,0x02,0xc4,0xfa,0x73,0xe0,0xd3,0x38,0x6f,0xaf,0x3d,0xf6,0xbe,0x85,0x60,0x03,0x63,0x6f,0x59,0x99,0x22,0xd4,0xf5,0x26,0x8f,0x30,0xb4,0xf2,0x07,0xc9,0x19,0xbb,0xdf,0x5e,0x67,0xa8,0xbe,0x42,0x65,0xa8,0x17,0x47,0x54,0xb3,0xab,0xa8,0xf1,0x6e,0x57,0x5b,0x77,0xff,0x4d,0x5a,0x7e,0xb6,0x4f, - 0x04,0xd5,0x33,0xb7,0x89,0xa4,0xaf,0x89,0x0f,0xa7,0xa8,0x2a,0x1f,0xae,0x58,0xc4,0x04,0xf9,0xa6,0x2a,0x50,0xb4,0x9a,0xda,0xfa,0xb3,0x49,0xc5,0x13,0xb4,0x15,0x08,0x74,0x01,0xb4,0x17,0x1b,0x80,0x3e,0x76,0xb3,0x4a,0x98,0x61,0xe1,0x0f,0x7b,0xc2,0x89,0xa0,0x66,0xfd,0x01,0xbd,0x29,0xf8,0x4c,0x98,0x7a,0x10,0xa5,0xfb,0x18,0xc2,0xd4, - 0x04,0x3a,0x31,0x50,0x79,0x8c,0x8a,0xf6,0x9d,0x1e,0x6e,0x98,0x1f,0x3a,0x45,0x40,0x2b,0xa1,0xd7,0x32,0xf4,0xbe,0x83,0x30,0xc5,0x16,0x4f,0x49,0xe1,0x0e,0xc5,0x55,0xb4,0x22,0x1b,0xd8,0x42,0xbc,0x5e,0x4d,0x97,0xef,0xf3,0x71,0x65,0xf6,0x0e,0x39,0x98,0xa4,0x24,0xd7,0x2a,0x45,0x0c,0xf9,0x5e,0xa4,0x77,0xc7,0x82,0x87,0xd0,0x34,0x3a, - 0x04,0x3b,0x37,0xdf,0x5f,0xb3,0x47,0xc6,0x9a,0x0f,0x17,0xd8,0x5c,0x0c,0x7c,0xa8,0x37,0x36,0x88,0x3a,0x82,0x5e,0x13,0x14,0x3d,0x0f,0xcf,0xc8,0x10,0x1e,0x85,0x1e,0x80,0x0d,0xe3,0xc0,0x90,0xb6,0xca,0x21,0xba,0x54,0x35,0x17,0x33,0x0c,0x04,0xb1,0x2f,0x94,0x8c,0x6b,0xad,0xf1,0x4a,0x63,0xab,0xff,0xdf,0x4e,0xf8,0xc7,0x53,0x70,0x26, - 0x04,0xfe,0xb5,0x16,0x3b,0x0e,0xce,0x30,0xff,0x3e,0x03,0xc7,0xd5,0x5c,0x43,0x80,0xfa,0x2f,0xa8,0x1e,0xe2,0xc0,0x35,0x49,0x42,0xff,0x6f,0x08,0xc9,0x9d,0x0c,0xd8,0x2c,0xe8,0x7d,0xe0,0x5e,0xe1,0xbd,0xa0,0x89,0xd3,0xe4,0xe2,0x48,0xfa,0x0f,0x72,0x11,0x02,0xac,0xff,0xfd,0xf5,0x0e,0x65,0x4b,0xe2,0x81,0x43,0x39,0x99,0xdf,0x89,0x7e, - 0x04,0x23,0x8c,0xed,0x00,0x1c,0xf2,0x2b,0x88,0x53,0xe0,0x2e,0xdc,0x89,0xcb,0xec,0xa5,0x05,0x0b,0xa7,0xe0,0x42,0xa7,0xa7,0x7f,0x93,0x82,0xcd,0x41,0x49,0x22,0x89,0x76,0x40,0x68,0x3d,0x30,0x94,0x64,0x38,0x40,0xf2,0x95,0x89,0x0a,0xa4,0xc1,0x8a,0xa3,0x9b,0x41,0xd7,0x7d,0xd0,0xfb,0x3b,0xb2,0x70,0x0e,0x4f,0x9e,0xc2,0x84,0xff,0xc2, - 0x04,0x96,0x1c,0xf6,0x48,0x17,0xc0,0x6c,0x0e,0x51,0xb3,0xc2,0x73,0x6c,0x92,0x2f,0xde,0x18,0xbd,0x8c,0x49,0x06,0xfc,0xd7,0xf5,0xef,0x66,0xc4,0x67,0x85,0x08,0xf3,0x5e,0xd2,0xc5,0xd1,0x81,0x68,0xcf,0xbe,0x70,0xf2,0xf1,0x23,0xbd,0x74,0x19,0x23,0x2b,0xb9,0x2d,0xd6,0x91,0x13,0xe2,0x94,0x10,0x61,0x88,0x94,0x81,0xc5,0xa0,0x27,0xbf, - 0x04,0x13,0x68,0x1e,0xae,0x16,0x8c,0xd4,0xea,0x7c,0xf2,0xe2,0xa4,0x5d,0x05,0x27,0x42,0xd1,0x0a,0x9f,0x64,0xe7,0x96,0x86,0x7d,0xbd,0xcb,0x82,0x9f,0xe0,0xb1,0x02,0x88,0x16,0x52,0x87,0x60,0xd1,0x77,0x37,0x6c,0x09,0xdf,0x79,0xde,0x39,0x55,0x7c,0x32,0x9c,0xc1,0x75,0x35,0x17,0xac,0xff,0xe8,0xfa,0x2e,0xc2,0x98,0x02,0x6b,0x83,0x84, - 0x04,0x5a,0xa7,0xab,0xfd,0xb6,0xb4,0x08,0x6d,0x54,0x33,0x25,0xe5,0xd7,0x9c,0x6e,0x95,0xce,0x42,0xf8,0x66,0xd2,0xbb,0x84,0x90,0x96,0x33,0xa0,0x4b,0xb1,0xaa,0x31,0xc2,0x91,0xc8,0x00,0x88,0x79,0x49,0x05,0xe1,0xda,0x33,0x33,0x6d,0x87,0x4e,0x2f,0x91,0xcc,0xf4,0x5c,0xc5,0x91,0x85,0xbe,0xde,0x5d,0xd6,0xf3,0xf7,0xac,0xaa,0xe1,0x8b, - 0x04,0x00,0x27,0x77,0x91,0xb3,0x05,0xa4,0x5b,0x2b,0x39,0x59,0x0b,0x2f,0x05,0xd3,0x39,0x2a,0x6c,0x81,0x82,0xce,0xf4,0xeb,0x54,0x01,0x20,0xe0,0xf5,0xc2,0x06,0xc3,0xe4,0x64,0x10,0x82,0x33,0xfb,0x0b,0x8c,0x3a,0xc8,0x92,0xd7,0x9e,0xf8,0xe0,0xfb,0xf9,0x2e,0xd1,0x33,0xad,0xdb,0x45,0x54,0x27,0x01,0x32,0x58,0x4d,0xc5,0x2e,0xef,0x41, - 0x04,0x6e,0xfa,0x09,0x2b,0x68,0xde,0x94,0x60,0xf0,0xbc,0xc9,0x19,0x00,0x5a,0x5f,0x6e,0x80,0xe1,0x9d,0xe9,0x89,0x68,0xbe,0x3c,0xd2,0xc7,0x70,0xa9,0x94,0x9b,0xfb,0x1a,0xc7,0x5e,0x6e,0x50,0x87,0xd6,0x55,0x0d,0x5f,0x9b,0xeb,0x1e,0x79,0xe5,0x02,0x93,0x07,0xbc,0x25,0x52,0x35,0xe2,0xd5,0xdc,0x99,0x24,0x1a,0xc3,0xab,0x88,0x6c,0x49, - 0x04,0x72,0xd4,0xa1,0x9c,0x4f,0x9d,0x2c,0xf5,0x84,0x8e,0xa4,0x04,0x45,0xb7,0x0d,0x46,0x96,0xb5,0xf0,0x2d,0x63,0x2c,0x0c,0x65,0x4c,0xc7,0xd7,0xee,0xb0,0xc6,0xd0,0x58,0xe8,0xc4,0xcd,0x99,0x43,0xe4,0x59,0x17,0x4c,0x7a,0xc0,0x1f,0xa7,0x42,0x19,0x8e,0x47,0xe6,0xc1,0x9a,0x6b,0xdb,0x0c,0x4f,0x6c,0x23,0x78,0x31,0xc1,0xb3,0xf9,0x42, - 0x04,0x2a,0x8e,0xa2,0xf5,0x0d,0xcc,0xed,0x0c,0x21,0x75,0x75,0xbd,0xfa,0x7c,0xd4,0x7d,0x1c,0x6f,0x10,0x00,0x41,0xec,0x0e,0x35,0x51,0x27,0x94,0xc1,0xbe,0x7e,0x74,0x02,0x58,0xf8,0xc1,0x71,0x22,0xed,0x30,0x3f,0xda,0x71,0x43,0xeb,0x58,0xbe,0xde,0x70,0x29,0x5b,0x65,0x32,0x66,0x01,0x3b,0x0b,0x0e,0xbd,0x3f,0x05,0x31,0x37,0xf6,0xec, - 0x04,0x88,0xde,0x68,0x9c,0xe9,0xaf,0x1e,0x94,0xbe,0x6a,0x20,0x89,0xc8,0xa8,0xb1,0x25,0x3f,0xfd,0xbb,0x6c,0x8e,0x9c,0x86,0x24,0x9b,0xa2,0x20,0x00,0x1a,0x4a,0xd3,0xb8,0x0c,0x49,0x98,0xe5,0x48,0x42,0xf4,0x13,0xb9,0xed,0xb1,0x82,0x5a,0xcb,0xb6,0x33,0x5e,0x81,0xe4,0xd1,0x84,0xb2,0xb0,0x1c,0x8b,0xeb,0xdc,0x85,0xd1,0xf2,0x89,0x46, - 0x04,0xfe,0xa2,0xd3,0x1f,0x70,0xf9,0x0d,0x5f,0xb3,0xe0,0x0e,0x18,0x6a,0xc4,0x2a,0xb3,0xc1,0x61,0x5c,0xee,0x71,0x4e,0x0b,0x4e,0x11,0x31,0xb3,0xd4,0xd8,0x22,0x5b,0xf7,0xb0,0x37,0xa1,0x8d,0xf2,0xac,0x15,0x34,0x3f,0x30,0xf7,0x40,0x67,0xdd,0xf2,0x9e,0x81,0x7d,0x5f,0x77,0xf8,0xdc,0xe0,0x57,0x14,0xda,0x59,0xc0,0x94,0xf0,0xcd,0xa9, - 0x04,0x72,0x58,0x91,0x1e,0x3d,0x42,0x33,0x49,0x16,0x64,0x79,0xdb,0xe0,0xb8,0x34,0x1a,0xf7,0xfb,0xd0,0x3d,0x0a,0x7e,0x10,0xed,0xcc,0xb3,0x6b,0x6c,0xee,0xa5,0xa3,0xdb,0x17,0xac,0x2b,0x89,0x92,0x79,0x11,0x28,0xfa,0x3b,0x96,0xdc,0x2f,0xbd,0x4c,0xa3,0xbf,0xa7,0x82,0xef,0x28,0x32,0xfc,0x66,0x56,0x94,0x3d,0xb1,0x8e,0x73,0x46,0xb0, - 0x04,0x4f,0x28,0x46,0x1d,0xea,0x64,0x47,0x4d,0x6b,0xb3,0x4d,0x14,0x99,0xc9,0x7d,0x37,0xb9,0xe9,0x56,0x33,0xdf,0x1c,0xee,0xea,0xac,0xd4,0x50,0x16,0xc9,0x8b,0x39,0x14,0xc8,0x81,0x88,0x10,0xb8,0xcc,0x06,0xdd,0xb4,0x0e,0x8a,0x12,0x61,0xc5,0x28,0xfa,0xa5,0x89,0x45,0x5d,0x5a,0x6d,0xf9,0x3b,0x77,0xbc,0x5e,0x0e,0x49,0x3c,0x74,0x70, - 0x04,0x74,0xf2,0xa8,0x14,0xfb,0x5d,0x8e,0xca,0x91,0xa6,0x9b,0x5e,0x60,0x71,0x27,0x32,0xb3,0x93,0x7d,0xe3,0x28,0x29,0xbe,0x97,0x4e,0xd7,0xb6,0x8c,0x5c,0x2f,0x5d,0x66,0xef,0xf0,0xf0,0x7c,0x56,0xf9,0x87,0xa6,0x57,0xf4,0x21,0x96,0x20,0x5f,0x58,0x8c,0x0f,0x1d,0x96,0xfd,0x8a,0x63,0xa5,0xf2,0x38,0xb4,0x8f,0x47,0x87,0x88,0xfe,0x3b, - 0x04,0x19,0x5b,0x51,0xa7,0xcc,0x4a,0x21,0xb8,0x27,0x4a,0x70,0xa9,0x0d,0xe7,0x79,0x81,0x4c,0x3c,0x8c,0xa3,0x58,0x32,0x82,0x08,0xc0,0x9a,0x29,0xf3,0x36,0xb8,0x2d,0x6a,0xb2,0x41,0x6b,0x7c,0x92,0xff,0xfd,0xc2,0x9c,0x3b,0x12,0x82,0xdd,0x2a,0x77,0xa4,0xd0,0x4d,0xf7,0xf7,0x45,0x20,0x47,0x39,0x3d,0x84,0x99,0x89,0xc5,0xce,0xe9,0xad, - 0x04,0x62,0x2f,0xc7,0x47,0x32,0x03,0x4b,0xec,0x2d,0xdf,0x3b,0xc1,0x6d,0x34,0xb3,0xd1,0xf7,0xa3,0x27,0xdd,0x2a,0x8c,0x19,0xba,0xb4,0xbb,0x4f,0xe3,0xa2,0x4b,0x58,0xaa,0x73,0x6b,0x2f,0x2f,0xae,0x76,0xf4,0xdf,0xae,0xcc,0x90,0x96,0x33,0x3b,0x01,0x32,0x8d,0x51,0xeb,0x3f,0xda,0x9c,0x92,0x27,0xe9,0x0d,0x0b,0x44,0x99,0x83,0xc4,0xf0, - 0x04,0x1f,0x7f,0x85,0xca,0xf2,0xd7,0x55,0x0e,0x7a,0xf9,0xb6,0x50,0x23,0xeb,0xb4,0xdc,0xe3,0x45,0x03,0x11,0x69,0x23,0x09,0xdb,0x26,0x99,0x69,0xb8,0x34,0xb6,0x11,0xc7,0x08,0x27,0xf4,0x5b,0x78,0x02,0x0e,0xcb,0xba,0xf4,0x84,0xfd,0xd5,0xbf,0xaa,0xe6,0x87,0x0f,0x11,0x84,0xc2,0x15,0x81,0xba,0xf6,0xef,0x82,0xbd,0x7b,0x53,0x0f,0x93, - 0x04,0x49,0xc1,0x97,0xdc,0x80,0xad,0x1d,0xa4,0x7a,0x43,0x42,0xb9,0x38,0x93,0xe8,0xe1,0xfb,0x0b,0xb9,0x4f,0xc3,0x3a,0x83,0xe7,0x83,0xc0,0x0b,0x24,0xc7,0x81,0x37,0x7a,0xef,0xc2,0x0d,0xa9,0x2b,0xac,0x76,0x29,0x51,0xf7,0x24,0x74,0xbe,0xcc,0x73,0x4d,0x4c,0xc2,0x2b,0xa8,0x1b,0x89,0x5e,0x28,0x2f,0xda,0xc4,0xdf,0x7a,0xf0,0xf3,0x7d, - 0x04,0xd8,0xcb,0x68,0x51,0x7b,0x61,0x6a,0x56,0x40,0x0a,0xa3,0x86,0x86,0x35,0xe5,0x4b,0x6f,0x69,0x95,0x98,0xa2,0xf6,0x16,0x77,0x57,0x65,0x49,0x80,0xba,0xf6,0xac,0xbe,0x7e,0xc8,0xcf,0x44,0x9c,0x84,0x9a,0xa0,0x34,0x61,0xa3,0x0e,0xfa,0xda,0x41,0x45,0x3c,0x57,0xc6,0xe6,0xfb,0xc9,0x3b,0xbc,0x6f,0xa4,0x9a,0xda,0x6d,0xc0,0x55,0x5c, - 0x04,0x03,0x07,0x13,0xfb,0x63,0xf2,0xaa,0x6f,0xe2,0xca,0xdf,0x1b,0x20,0xef,0xc2,0x59,0xc7,0x74,0x45,0xda,0xfa,0x87,0xda,0xc3,0x98,0xb8,0x40,0x65,0xca,0x34,0x7d,0xf3,0xb2,0x27,0x81,0x8d,0xe1,0xa3,0x9b,0x58,0x9c,0xb0,0x71,0xd8,0x3e,0x53,0x17,0xcc,0xcd,0xc2,0x33,0x8e,0x51,0xe3,0x12,0xfe,0x31,0xd8,0xdc,0x34,0xa4,0x80,0x17,0x50, - 0x04,0xba,0xbb,0x36,0x77,0xb0,0x95,0x58,0x02,0xd8,0xe9,0x29,0xa4,0x13,0x55,0x64,0x0e,0xaf,0x1e,0xa1,0x35,0x3f,0x8a,0x77,0x13,0x31,0xc4,0x94,0x6e,0x34,0x80,0xaf,0xa7,0x25,0x2f,0x19,0x6c,0x87,0xed,0x3d,0x2a,0x59,0xd3,0xb1,0xb5,0x59,0x13,0x7f,0xed,0x00,0x13,0xfe,0xce,0xfc,0x19,0xfb,0x5a,0x92,0x68,0x2b,0x9b,0xca,0x51,0xb9,0x50, - 0x04,0x1a,0xab,0x20,0x18,0x79,0x34,0x71,0x11,0x1a,0x8a,0x0e,0x9b,0x14,0x3f,0xde,0x02,0xfc,0x95,0x92,0x07,0x96,0xd3,0xa6,0x3d,0xe3,0x29,0xb4,0x24,0x39,0x6f,0xba,0x60,0xbb,0xe4,0x13,0x07,0x05,0x17,0x47,0x92,0x44,0x1b,0x31,0x8d,0x3a,0xa3,0x1d,0xfe,0x85,0x77,0x82,0x1e,0x9b,0x44,0x6e,0xc5,0x73,0xd2,0x72,0xe0,0x36,0xc4,0xeb,0xe9, - 0x04,0x8c,0xb0,0xb9,0x09,0x49,0x9c,0x83,0xea,0x80,0x6c,0xd8,0x85,0xb1,0xdd,0x46,0x7a,0x01,0x19,0xf0,0x6a,0x88,0xa0,0x27,0x6e,0xb0,0xcf,0xda,0x27,0x45,0x35,0xa8,0xff,0x47,0xb5,0x42,0x88,0x33,0xbc,0x3f,0x2c,0x8b,0xf9,0xd9,0x04,0x11,0x58,0xcf,0x33,0x71,0x8a,0x69,0x96,0x1c,0xd0,0x17,0x29,0xbc,0x00,0x11,0xd1,0xe5,0x86,0xab,0x75, - 0x04,0x8f,0x03,0xcf,0x1a,0x42,0x27,0x2b,0xb1,0x53,0x27,0x23,0x09,0x3f,0x72,0xe6,0xfe,0xea,0xc8,0x5e,0x17,0x00,0xe9,0xfb,0xe9,0xa6,0xa2,0xdd,0x64,0x2d,0x74,0xbf,0x5d,0x3b,0x89,0xa7,0x18,0x9d,0xad,0x8c,0xf7,0x5f,0xc2,0x2f,0x6f,0x15,0x8a,0xa2,0x7f,0x9c,0x2c,0xa0,0x0d,0xac,0xa7,0x85,0xbe,0x33,0x58,0xf2,0xbd,0xa3,0x86,0x2c,0xa0, - 0x04,0x44,0xde,0x3b,0x9c,0x7a,0x57,0xa8,0xc9,0xe8,0x20,0x95,0x27,0x53,0x42,0x1e,0x7d,0x98,0x7b,0xb3,0xd7,0x9f,0x71,0xf0,0x13,0x80,0x5c,0x89,0x7e,0x01,0x8f,0x8a,0xce,0xa2,0x46,0x07,0x58,0xc8,0xf9,0x8d,0x3f,0xdc,0xe1,0x21,0xa9,0x43,0x65,0x9e,0x37,0x2c,0x32,0x6f,0xff,0x2e,0x5f,0xc2,0xae,0x7f,0xa3,0xf7,0x9d,0xaa,0xe1,0x3c,0x12, - 0x04,0x6f,0xb8,0xb2,0xb4,0x8e,0x33,0x03,0x12,0x68,0xad,0x6a,0x51,0x74,0x84,0xdc,0x88,0x39,0xea,0x90,0xf6,0x66,0x9e,0xa0,0xc7,0xac,0x32,0x33,0xe2,0xac,0x31,0x39,0x4a,0x0a,0xc8,0xbb,0xe7,0xf7,0x3c,0x2f,0xf4,0xdf,0x99,0x78,0x72,0x7a,0xc1,0xdf,0xc2,0xfd,0x58,0x64,0x7d,0x20,0xf3,0x1f,0x99,0x10,0x53,0x16,0xb6,0x46,0x71,0xf2,0x04, - 0x04,0xbe,0xa7,0x11,0x22,0xa0,0x48,0x69,0x3e,0x90,0x5f,0xf6,0x02,0xb3,0xcf,0x9d,0xd1,0x8a,0xf6,0x9b,0x9f,0xc9,0xd8,0x43,0x1d,0x2b,0x1d,0xd2,0x6b,0x94,0x2c,0x95,0xe6,0xf4,0x3c,0x7b,0x8b,0x95,0xeb,0x62,0x08,0x2c,0x12,0xdb,0x9d,0xbd,0xa7,0xfe,0x38,0xe4,0x5c,0xbe,0x4a,0x48,0x86,0x90,0x7f,0xb8,0x1b,0xdb,0x0c,0x5e,0xa9,0x24,0x6c, - 0x04,0xda,0x91,0x8c,0x73,0x1b,0xa0,0x6a,0x20,0xcb,0x94,0xef,0x33,0xb7,0x78,0xe9,0x81,0xa4,0x04,0xa3,0x05,0xf1,0x94,0x1f,0xe3,0x36,0x66,0xb4,0x5b,0x03,0x35,0x31,0x56,0xe2,0xbb,0x26,0x94,0xf5,0x75,0xb4,0x51,0x83,0xbe,0x78,0xe5,0xc9,0xb5,0x21,0x0b,0xf3,0xbf,0x48,0x8f,0xd4,0xc8,0x29,0x45,0x16,0xd8,0x95,0x72,0xca,0x4f,0x53,0x91, - 0x04,0x30,0x07,0xe9,0x2c,0x39,0x37,0xda,0xde,0x79,0x64,0xdf,0xa3,0x5b,0x0e,0xff,0x03,0x1f,0x7e,0xb0,0x2a,0xed,0x0a,0x03,0x14,0x41,0x11,0x06,0xcd,0xeb,0x70,0xfe,0x3d,0x5a,0x75,0x46,0xfc,0x05,0x52,0x99,0x7b,0x20,0xe3,0xd6,0xf4,0x13,0xe7,0x5e,0x2c,0xb6,0x6e,0x11,0x63,0x22,0x69,0x71,0x14,0xb7,0x9b,0xac,0x73,0x4b,0xfc,0x4d,0xc5, - 0x04,0x60,0xe7,0x34,0xef,0x56,0x24,0xd3,0xcb,0xf0,0xdd,0xd3,0x75,0x01,0x1b,0xd6,0x63,0xd6,0xd6,0xae,0xbc,0x64,0x4e,0xb5,0x99,0xfd,0xf9,0x8d,0xbd,0xcd,0x18,0xce,0x9b,0xd2,0xd9,0x0b,0x3a,0xc3,0x1f,0x13,0x9a,0xf8,0x32,0xcc,0xcf,0x6c,0xcb,0xbb,0x2c,0x6e,0xa1,0x1f,0xa9,0x73,0x70,0xdc,0x99,0x06,0xda,0x47,0x4d,0x7d,0x8a,0x75,0x67, - 0x04,0x85,0xa9,0x00,0xe9,0x78,0x58,0xf6,0x93,0xc0,0xb7,0xdf,0xa2,0x61,0xe3,0x80,0xda,0xd6,0xea,0x04,0x6d,0x1f,0x65,0xdd,0xee,0xed,0xd5,0xf7,0xd8,0xaf,0x0b,0xa3,0x37,0x69,0x74,0x4d,0x15,0xad,0xd4,0xf6,0xc0,0xbc,0x3b,0x0d,0xa2,0xae,0xc9,0x3b,0x34,0xcb,0x8c,0x65,0xf9,0x34,0x0d,0xdf,0x74,0xe7,0xb0,0x00,0x9e,0xee,0xcc,0xce,0x3c, - 0x04,0x38,0x06,0x6f,0x75,0xd8,0x8e,0xfc,0x4c,0x93,0xde,0x36,0xf4,0x9e,0x03,0x7b,0x23,0x4c,0xc1,0x8b,0x1d,0xe5,0x60,0x87,0x50,0xa6,0x2c,0xab,0x03,0x45,0x40,0x10,0x46,0xa3,0xe8,0x4b,0xed,0x8c,0xfc,0xb8,0x19,0xef,0x4d,0x55,0x04,0x44,0xf2,0xce,0x4b,0x65,0x17,0x66,0xb6,0x9e,0x2e,0x29,0x01,0xf8,0x88,0x36,0xff,0x90,0x03,0x4f,0xed, - 0x04,0x98,0xf6,0x81,0x77,0xdc,0x95,0xc1,0xb4,0xcb,0xfa,0x52,0x45,0x48,0x8c,0xa5,0x23,0xa7,0xd5,0x62,0x94,0x70,0xd0,0x35,0xd6,0x21,0xa4,0x43,0xc7,0x2f,0x39,0xaa,0xbf,0xa3,0x3d,0x29,0x54,0x6f,0xa1,0xc6,0x48,0xf2,0xc7,0xd5,0xcc,0xf7,0x0c,0xf1,0xce,0x4a,0xb7,0x9b,0x5d,0xb1,0xac,0x05,0x9d,0xbe,0xcd,0x06,0x8d,0xbd,0xff,0x1b,0x89, - 0x04,0x5c,0x2b,0xbf,0xa2,0x3c,0x9b,0x9a,0xd0,0x7f,0x03,0x8a,0xa8,0x9b,0x49,0x30,0xbf,0x26,0x7d,0x94,0x01,0xe4,0x25,0x5d,0xe9,0xe8,0xda,0x0a,0x50,0x78,0xec,0x82,0x77,0xe3,0xe8,0x82,0xa3,0x1d,0x5e,0x6a,0x37,0x9e,0x07,0x93,0x98,0x3c,0xcd,0xed,0x39,0xb9,0x5c,0x43,0x53,0xab,0x2f,0xf0,0x1e,0xa5,0x36,0x9b,0xa4,0x7b,0x0c,0x31,0x91, - 0x04,0x2e,0xa7,0x13,0x34,0x32,0x33,0x9c,0x69,0xd2,0x7f,0x9b,0x26,0x72,0x81,0xbd,0x2d,0xdd,0x5f,0x19,0xd6,0x33,0x8d,0x40,0x0a,0x05,0xcd,0x36,0x47,0xb1,0x57,0xa3,0x85,0x35,0x47,0x80,0x82,0x98,0x44,0x8e,0xdb,0x5e,0x70,0x1a,0xde,0x84,0xcd,0x5f,0xb1,0xac,0x95,0x67,0xba,0x5e,0x8f,0xb6,0x8a,0x6b,0x93,0x3e,0xc4,0xb5,0xcc,0x84,0xcc, - 0x04,0x2e,0xa7,0x13,0x34,0x32,0x33,0x9c,0x69,0xd2,0x7f,0x9b,0x26,0x72,0x81,0xbd,0x2d,0xdd,0x5f,0x19,0xd6,0x33,0x8d,0x40,0x0a,0x05,0xcd,0x36,0x47,0xb1,0x57,0xa3,0x85,0xca,0xb8,0x7f,0x7d,0x67,0xbb,0x71,0x24,0xa1,0x8f,0xe5,0x21,0x7b,0x32,0xa0,0x4e,0x53,0x6a,0x98,0x45,0xa1,0x70,0x49,0x75,0x94,0x6c,0xc1,0x3a,0x4a,0x33,0x77,0x63, - 0x04,0x8a,0xa2,0xc6,0x4f,0xa9,0xc6,0x43,0x75,0x63,0xab,0xfb,0xcb,0xd0,0x0b,0x20,0x48,0xd4,0x8c,0x18,0xc1,0x52,0xa2,0xa6,0xf4,0x90,0x36,0xde,0x76,0x47,0xeb,0xe8,0x2e,0x1c,0xe6,0x43,0x87,0x99,0x5c,0x68,0xa0,0x60,0xfa,0x3b,0xc0,0x39,0x9b,0x05,0xcc,0x06,0xee,0xc7,0xd5,0x98,0xf7,0x50,0x41,0xa4,0x91,0x7e,0x69,0x2b,0x7f,0x51,0xff, - 0x04,0x39,0x14,0x27,0xff,0x7e,0xe7,0x80,0x13,0xc1,0x4a,0xec,0x7d,0x96,0xa8,0xa0,0x62,0x20,0x92,0x98,0xa7,0x83,0x83,0x5e,0x94,0xfd,0x65,0x49,0xd5,0x02,0xff,0xf7,0x1f,0xdd,0x66,0x24,0xec,0x34,0x3a,0xd9,0xfc,0xf4,0xd9,0x87,0x21,0x81,0xe5,0x9f,0x84,0x2f,0x9b,0xa4,0xcc,0xca,0xe0,0x9a,0x6c,0x09,0x72,0xfb,0x6a,0xc6,0xb4,0xc6,0xbd, - 0x04,0xe7,0x62,0xb8,0xa2,0x19,0xb4,0xf1,0x80,0x21,0x9c,0xc7,0xa9,0x05,0x92,0x45,0xe4,0x96,0x1b,0xd1,0x91,0xc0,0x38,0x99,0x78,0x9c,0x7a,0x34,0xb8,0x9e,0x8c,0x13,0x8e,0xc1,0x53,0x3e,0xf0,0x41,0x9b,0xb7,0x37,0x6e,0x0b,0xfd,0xe9,0x31,0x9d,0x10,0xa0,0x69,0x68,0x79,0x1d,0x9e,0xa0,0xee,0xd9,0xc1,0xce,0x63,0x45,0xae,0xd9,0x75,0x9e, - 0x04,0x9a,0xed,0xb0,0xd2,0x81,0xdb,0x16,0x4e,0x13,0x00,0x00,0xc5,0x69,0x7f,0xae,0x0f,0x30,0x5e,0xf8,0x48,0xbe,0x6f,0xff,0xb4,0x3a,0xc5,0x93,0xfb,0xb9,0x50,0xe9,0x52,0xfa,0x6f,0x63,0x33,0x59,0xbd,0xcd,0x82,0xb5,0x6b,0x0b,0x9f,0x96,0x5b,0x03,0x77,0x89,0xd4,0x6b,0x9a,0x81,0x41,0xb7,0x91,0xb2,0xae,0xfa,0x71,0x3f,0x96,0xc1,0x75, - 0x04,0x8a,0xd4,0x45,0xdb,0x62,0x81,0x62,0x60,0xe4,0xe6,0x87,0xfd,0x18,0x84,0xe4,0x8b,0x9f,0xc0,0x63,0x6d,0x03,0x15,0x47,0xd6,0x33,0x15,0xe7,0x92,0xe1,0x9b,0xfa,0xee,0x1d,0xe6,0x4f,0x99,0xd5,0xf1,0xcd,0x8b,0x6e,0xc9,0xcb,0x0f,0x78,0x7a,0x65,0x4a,0xe8,0x69,0x93,0xba,0x3d,0xb1,0x00,0x8e,0xf4,0x3c,0xff,0x06,0x84,0xcb,0x22,0xbd, - 0x04,0x1f,0x57,0x99,0xc9,0x5b,0xe8,0x90,0x63,0xb2,0x4f,0x26,0xe4,0x0c,0xb9,0x28,0xc1,0xa8,0x68,0xa7,0x6f,0xb0,0x09,0x46,0x07,0xe8,0x04,0x3d,0xb4,0x09,0xc9,0x1c,0x32,0xe7,0x57,0x24,0xe8,0x13,0xa4,0x19,0x1e,0x3a,0x83,0x90,0x07,0xf0,0x8e,0x2e,0x89,0x73,0x88,0xb0,0x6d,0x4a,0x00,0xde,0x6d,0xe6,0x0e,0x53,0x6d,0x91,0xfa,0xb5,0x66, - 0x04,0xa3,0x33,0x1a,0x4e,0x1b,0x42,0x23,0xec,0x2c,0x02,0x7e,0xdd,0x48,0x2c,0x92,0x8a,0x14,0xed,0x35,0x8d,0x93,0xf1,0xd4,0x21,0x7d,0x39,0xab,0xf6,0x9f,0xcb,0x5c,0xcc,0x28,0xd6,0x84,0xd2,0xaa,0xab,0xcd,0x63,0x83,0x77,0x5c,0xaa,0x62,0x39,0xde,0x26,0xd4,0xc6,0x93,0x7b,0xb6,0x03,0xec,0xb4,0x19,0x60,0x82,0xf4,0xcf,0xfd,0x50,0x9d, - 0x04,0x3f,0x39,0x52,0x19,0x97,0x74,0xc7,0xcf,0x39,0xb3,0x8b,0x66,0xcb,0x10,0x42,0xa6,0x26,0x0d,0x86,0x80,0x80,0x38,0x45,0xe4,0xd4,0x33,0xad,0xba,0x3b,0xb2,0x48,0x18,0x5e,0xa4,0x95,0xb6,0x8c,0xbc,0x7e,0xd4,0x17,0x3e,0xe6,0x3c,0x90,0x42,0xdc,0x50,0x26,0x25,0xc7,0xeb,0x7e,0x21,0xfb,0x02,0xca,0x9a,0x91,0x14,0xe0,0xa3,0xa1,0x8d, - 0x04,0xcd,0xfb,0x8c,0x0f,0x42,0x2e,0x14,0x4e,0x13,0x7c,0x24,0x12,0xc8,0x6c,0x17,0x1f,0x5f,0xe3,0xfa,0x3f,0x5b,0xbb,0x54,0x4e,0x90,0x76,0x28,0x8f,0x3c,0xed,0x78,0x6e,0x05,0x4f,0xd0,0x72,0x1b,0x77,0xc1,0x1c,0x79,0xbe,0xac,0xb3,0xc9,0x42,0x11,0xb0,0xa1,0x9b,0xda,0x08,0x65,0x2e,0xfe,0xaf,0x92,0x51,0x3a,0x3b,0x0a,0x16,0x36,0x98, - 0x04,0x73,0x59,0x8a,0x6a,0x1c,0x68,0x27,0x8f,0xa6,0xbf,0xd0,0xce,0x40,0x64,0xe6,0x82,0x35,0xbc,0x1c,0x0f,0x6b,0x20,0xa9,0x28,0x10,0x8b,0xe3,0x36,0x73,0x0f,0x87,0xe3,0xcb,0xae,0x61,0x25,0x19,0xb5,0x03,0x2e,0xcc,0x85,0xae,0xd8,0x11,0x27,0x1a,0x95,0xfe,0x79,0x39,0xd5,0xd3,0x46,0x01,0x40,0xba,0x31,0x8f,0x4d,0x14,0xab,0xa3,0x1d, - 0x04,0x58,0xde,0xbd,0x9a,0x7e,0xe2,0xc9,0xd5,0x91,0x32,0x47,0x8a,0x54,0x40,0xae,0x4d,0x5d,0x7e,0xd4,0x37,0x30,0x83,0x69,0xf9,0x2e,0xa8,0x6c,0x82,0x18,0x3f,0x10,0xa1,0x67,0x73,0xe7,0x6f,0x5e,0xdb,0xf4,0xda,0x0e,0x4f,0x1b,0xdf,0xfa,0xc0,0xf5,0x72,0x57,0xe1,0xdf,0xa4,0x65,0x84,0x29,0x31,0x30,0x9a,0x24,0x24,0x5f,0xda,0x6a,0x5d, - 0x04,0x8b,0x90,0x4d,0xe4,0x79,0x67,0x34,0x0c,0x5f,0x8c,0x35,0x72,0xa7,0x20,0x92,0x4e,0xf7,0x57,0x86,0x37,0xfe,0xab,0x19,0x49,0xac,0xb2,0x41,0xa5,0xa6,0xac,0x3f,0x5b,0x95,0x09,0x04,0x49,0x6f,0x98,0x24,0xb1,0xd6,0x3f,0x33,0x13,0xba,0xe2,0x1b,0x89,0xfa,0xe8,0x9a,0xfd,0xfc,0x81,0x1b,0x5e,0xce,0x03,0xfd,0x5a,0xa3,0x01,0x86,0x4f, - 0x04,0xf4,0x89,0x2b,0x6d,0x52,0x5c,0x77,0x1e,0x03,0x5f,0x2a,0x25,0x27,0x08,0xf3,0x78,0x4e,0x48,0x23,0x86,0x04,0xb4,0xf9,0x4d,0xc5,0x6e,0xaa,0x1e,0x54,0x6d,0x94,0x1a,0x34,0x6b,0x1a,0xa0,0xbc,0xe6,0x8b,0x1c,0x50,0xe5,0xb5,0x2f,0x50,0x9f,0xb5,0x52,0x2e,0x5c,0x25,0xe0,0x28,0xbc,0x8f,0x86,0x34,0x02,0xed,0xb7,0xbc,0xad,0x8b,0x1b, - 0x04,0x79,0xbe,0x66,0x7e,0xf9,0xdc,0xbb,0xac,0x55,0xa0,0x62,0x95,0xce,0x87,0x0b,0x07,0x02,0x9b,0xfc,0xdb,0x2d,0xce,0x28,0xd9,0x59,0xf2,0x81,0x5b,0x16,0xf8,0x17,0x98,0x48,0x3a,0xda,0x77,0x26,0xa3,0xc4,0x65,0x5d,0xa4,0xfb,0xfc,0x0e,0x11,0x08,0xa8,0xfd,0x17,0xb4,0x48,0xa6,0x85,0x54,0x19,0x9c,0x47,0xd0,0x8f,0xfb,0x10,0xd4,0xb8, - 0x04,0x79,0xbe,0x66,0x7e,0xf9,0xdc,0xbb,0xac,0x55,0xa0,0x62,0x95,0xce,0x87,0x0b,0x07,0x02,0x9b,0xfc,0xdb,0x2d,0xce,0x28,0xd9,0x59,0xf2,0x81,0x5b,0x16,0xf8,0x17,0x98,0xb7,0xc5,0x25,0x88,0xd9,0x5c,0x3b,0x9a,0xa2,0x5b,0x04,0x03,0xf1,0xee,0xf7,0x57,0x02,0xe8,0x4b,0xb7,0x59,0x7a,0xab,0xe6,0x63,0xb8,0x2f,0x6f,0x04,0xef,0x27,0x77, - 0x04,0x78,0x2c,0x8e,0xd1,0x7e,0x3b,0x2a,0x78,0x3b,0x54,0x64,0xf3,0x3b,0x09,0x65,0x2a,0x71,0xc6,0x78,0xe0,0x5e,0xc5,0x1e,0x84,0xe2,0xbc,0xfc,0x66,0x3a,0x3d,0xe9,0x63,0xaf,0x9a,0xcb,0x42,0x80,0xb8,0xc7,0xf7,0xc4,0x2f,0x4e,0xf9,0xab,0xa6,0x24,0x5e,0xc1,0xec,0x17,0x12,0xfd,0x38,0xa0,0xfa,0x96,0x41,0x8d,0x8c,0xd6,0xaa,0x61,0x52, - 0x04,0x6e,0x82,0x35,0x55,0x45,0x29,0x14,0x09,0x91,0x82,0xc6,0xb2,0xc1,0xd6,0xf0,0xb5,0xd2,0x8d,0x50,0xcc,0xd0,0x05,0xaf,0x2c,0xe1,0xbb,0xa5,0x41,0xaa,0x40,0xca,0xff,0x00,0x00,0x00,0x01,0x06,0x04,0x92,0xd5,0xa5,0x67,0x3e,0x0f,0x25,0xd8,0xd5,0x0f,0xb7,0xe5,0x8c,0x49,0xd8,0x6d,0x46,0xd4,0x21,0x69,0x55,0xe0,0xaa,0x3d,0x40,0xe1, - 0x04,0x6e,0x82,0x35,0x55,0x45,0x29,0x14,0x09,0x91,0x82,0xc6,0xb2,0xc1,0xd6,0xf0,0xb5,0xd2,0x8d,0x50,0xcc,0xd0,0x05,0xaf,0x2c,0xe1,0xbb,0xa5,0x41,0xaa,0x40,0xca,0xff,0xff,0xff,0xff,0xfe,0xf9,0xfb,0x6d,0x2a,0x5a,0x98,0xc1,0xf0,0xda,0x27,0x2a,0xf0,0x48,0x1a,0x73,0xb6,0x27,0x92,0xb9,0x2b,0xde,0x96,0xaa,0x1e,0x55,0xc2,0xbb,0x4e, - 0x04,0x00,0x00,0x00,0x01,0x3f,0xd2,0x22,0x48,0xd6,0x4d,0x95,0xf7,0x3c,0x29,0xb4,0x8a,0xb4,0x86,0x31,0x85,0x0b,0xe5,0x03,0xfd,0x00,0xf8,0x46,0x8b,0x5f,0x0f,0x70,0xe0,0xf6,0xee,0x7a,0xa4,0x3b,0xc2,0xc6,0xfd,0x25,0xb1,0xd8,0x26,0x92,0x41,0xcb,0xdd,0x9d,0xbb,0x0d,0xac,0x96,0xdc,0x96,0x23,0x1f,0x43,0x07,0x05,0xf8,0x38,0x71,0x7d, - 0x04,0x25,0xaf,0xd6,0x89,0xac,0xab,0xae,0xd6,0x7c,0x1f,0x29,0x6d,0xe5,0x94,0x06,0xf8,0xc5,0x50,0xf5,0x71,0x46,0xa0,0xb4,0xec,0x2c,0x97,0x87,0x6d,0xff,0xff,0xff,0xff,0xfa,0x46,0xa7,0x6e,0x52,0x03,0x22,0xdf,0xbc,0x49,0x1e,0xc4,0xf0,0xcc,0x19,0x74,0x20,0xfc,0x4e,0xa5,0x88,0x3d,0x8f,0x6d,0xd5,0x3c,0x35,0x4b,0xc4,0xf6,0x7c,0x35, - 0x04,0xd1,0x2e,0x6c,0x66,0xb6,0x77,0x34,0xc3,0xc8,0x4d,0x26,0x01,0xcf,0x5d,0x35,0xdc,0x09,0x7e,0x27,0x63,0x7f,0x0a,0xca,0x4a,0x4f,0xdb,0x74,0xb6,0xaa,0xdd,0x3b,0xb9,0x3f,0x5b,0xdf,0xf8,0x8b,0xd5,0x73,0x6d,0xf8,0x98,0xe6,0x99,0x00,0x6e,0xd7,0x50,0xf1,0x1c,0xf0,0x7c,0x58,0x66,0xcd,0x7a,0xd7,0x0c,0x71,0x21,0xff,0xff,0xff,0xff, - 0x04,0x6d,0x4a,0x7f,0x60,0xd4,0x77,0x4a,0x4f,0x0a,0xa8,0xbb,0xde,0xdb,0x95,0x3c,0x7e,0xea,0x79,0x09,0x40,0x7e,0x31,0x64,0x75,0x56,0x64,0xbc,0x28,0x00,0x00,0x00,0x00,0xe6,0x59,0xd3,0x4e,0x4d,0xf3,0x8d,0x9e,0x8c,0x9e,0xaa,0xdf,0xba,0x36,0x61,0x2c,0x76,0x91,0x95,0xbe,0x86,0xc7,0x7a,0xac,0x3f,0x36,0xe7,0x8b,0x53,0x86,0x80,0xfb}; - -static const unsigned char wycheproof_ecdsa_signatures[] = { 0x30,0x46,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x21,0x00,0x90,0x0e,0x75,0xad,0x23,0x3f,0xcc,0x90,0x85,0x09,0xdb,0xff,0x59,0x22,0x64,0x7d,0xb3,0x7c,0x21,0xf4,0xaf,0xd3,0x20,0x3a,0xe8,0xdc,0x4a,0xe7,0x79,0x4b,0x0f,0x87, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x81,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x82,0x00,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x46,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x44,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x85,0x01,0x00,0x00,0x00,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x89,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x84,0x7f,0xff,0xff,0xff,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x84,0x80,0x00,0x00,0x00,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x84,0xff,0xff,0xff,0xff,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x85,0xff,0xff,0xff,0xff,0xff,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x88,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0xff,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x80,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00, - 0x30,0x47,0x00,0x00,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x05,0x00, - 0x30,0x4a,0x49,0x81,0x77,0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x25,0x00,0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x04,0xde,0xad,0xbe,0xef, - 0x30,0x4d,0xaa,0x00,0xbb,0x00,0xcd,0x00,0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4d,0x22,0x29,0xaa,0x00,0xbb,0x00,0xcd,0x00,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4d,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x22,0x28,0xaa,0x00,0xbb,0x00,0xcd,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x81, - 0x30,0x4b,0xaa,0x02,0xaa,0xbb,0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x80,0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00, - 0x30,0x80,0x31,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00, - 0x05,0x00, - 0x2e,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x2f,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x31,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x32,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0xff,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x00, - 0x30,0x49,0x30,0x01,0x02,0x30,0x44,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x44,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31, - 0x30,0x44,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x82,0x10,0x46,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x30,0x80,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00, - 0x30,0x80,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00, - 0x30,0x80,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x05,0x00,0x00,0x00, - 0x30,0x80,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x06,0x08,0x11,0x22,0x00,0x00, - 0x30,0x80,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00,0xfe,0x02,0xbe,0xef, - 0x30,0x80,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x02,0xbe,0xef, - 0x30,0x47,0x30,0x00,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x30,0x00, - 0x30,0x48,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x02,0x01,0x00, - 0x30,0x48,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0xbf,0x7f,0x00, - 0x30,0x49,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0xa0,0x02,0x05,0x00, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0xa0,0x00, - 0x30,0x47,0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x23,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65, - 0x30,0x67,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x43,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x64,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x43,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xca,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x43,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x13,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x43,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x08,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x46,0x02,0x81,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x02,0x82,0x00,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x22,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x20,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4a,0x02,0x85,0x01,0x00,0x00,0x00,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4e,0x02,0x89,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x02,0x84,0x7f,0xff,0xff,0xff,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x02,0x84,0x80,0x00,0x00,0x00,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x02,0x84,0xff,0xff,0xff,0xff,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4a,0x02,0x85,0xff,0xff,0xff,0xff,0xff,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4d,0x02,0x88,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0xff,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x80,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x22,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x23,0x02,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x24,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02, - 0x30,0x47,0x02,0x23,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x00,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x02,0x23,0x00,0x00,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x00,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x02,0x23,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x05,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4a,0x22,0x26,0x49,0x81,0x77,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x22,0x25,0x25,0x00,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4d,0x22,0x23,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x00,0x04,0xde,0xad,0xbe,0xef,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x24,0x02,0x81,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4b,0x22,0x27,0xaa,0x02,0xaa,0xbb,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x22,0x80,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x00,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x22,0x80,0x03,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x00,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x24,0x05,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x00,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x01,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x03,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x04,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0xff,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x24,0x02,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x22,0x25,0x02,0x01,0x00,0x02,0x20,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x02,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0xe5,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x44,0x02,0x20,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x44,0x02,0x20,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x82,0x10,0x48,0x02,0x82,0x10,0x22,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x46,0x02,0x22,0xff,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x25,0x09,0x01,0x80,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x25,0x02,0x01,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x43,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xbb, - 0x30,0x43,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa4,0x56,0xeb,0x31,0xba, - 0x30,0x43,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf7,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x43,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x01,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x46,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x81,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x82,0x00,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x21,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x1f,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4a,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x85,0x01,0x00,0x00,0x00,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4e,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x89,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x84,0x7f,0xff,0xff,0xff,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x84,0x80,0x00,0x00,0x00,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x84,0xff,0xff,0xff,0xff,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4a,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x85,0xff,0xff,0xff,0xff,0xff,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4d,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x88,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0xff,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x80,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x22,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x22,0x00,0x00,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x47,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x22,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x05,0x00, - 0x30,0x4a,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x22,0x25,0x49,0x81,0x77,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x22,0x24,0x25,0x00,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4d,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x22,0x22,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x04,0xde,0xad,0xbe,0xef, - 0x30,0x25,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x81, - 0x30,0x4b,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x22,0x26,0xaa,0x02,0xaa,0xbb,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x49,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x22,0x80,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00, - 0x30,0x49,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x22,0x80,0x03,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00, - 0x30,0x25,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x05,0x00, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x00,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x01,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x03,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x04,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0xff,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x25,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x00, - 0x30,0x49,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x22,0x24,0x02,0x01,0x6f,0x02,0x1f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6d,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0x3a, - 0x30,0x44,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x1f,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31, - 0x30,0x44,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x1f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x82,0x10,0x48,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x82,0x10,0x21,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x30,0x46,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x21,0xff,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x26,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x09,0x01,0x80, - 0x30,0x26,0x02,0x21,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x01,0x00, - 0x30,0x45,0x02,0x21,0x01,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x83,0xb9,0x0d,0xea,0xbc,0xa4,0xb0,0x5c,0x45,0x74,0xe4,0x9b,0x58,0x99,0xb9,0x64,0xa6,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x44,0x02,0x20,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x86,0x43,0xb0,0x30,0xef,0x46,0x1f,0x1b,0xcd,0xf5,0x3f,0xde,0x3e,0xf9,0x4c,0xe2,0x24,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x46,0x02,0x22,0x01,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x84,0x3f,0xad,0x3b,0xf4,0x85,0x3e,0x07,0xf7,0xc9,0x87,0x70,0xc9,0x9b,0xff,0xc4,0x64,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0xff,0x7e,0xc1,0x08,0x63,0x31,0x05,0x65,0xa9,0x08,0x45,0x7f,0xa0,0xf1,0xb8,0x7a,0x7b,0x01,0xa0,0xf2,0x2a,0x0a,0x98,0x43,0xf6,0x4a,0xed,0xc3,0x34,0x36,0x7c,0xdc,0x9b,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x44,0x02,0x20,0x7e,0xc1,0x08,0x63,0x31,0x05,0x65,0xa9,0x08,0x45,0x7f,0xa0,0xf1,0xb8,0x7a,0x79,0xbc,0x4f,0xcf,0x10,0xb9,0xe0,0xe4,0x32,0x0a,0xc0,0x21,0xc1,0x06,0xb3,0x1d,0xdc,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0xfe,0x7e,0xc1,0x08,0x63,0x31,0x05,0x65,0xa9,0x08,0x45,0x7f,0xa0,0xf1,0xb8,0x7a,0x7c,0x46,0xf2,0x15,0x43,0x5b,0x4f,0xa3,0xba,0x8b,0x1b,0x64,0xa7,0x66,0x46,0x9b,0x5a,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x01,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4d,0x02,0x29,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x3e,0xf7,0x9c,0xce,0xfa,0x9a,0x56,0xf7,0xba,0x80,0x5f,0x0e,0x47,0x85,0x84,0xfe,0x5f,0x0d,0xd5,0xf5,0x67,0xbc,0x09,0xb5,0x12,0x3c,0xcb,0xc9,0x83,0x23,0x65,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x01,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x7f,0xc1,0xe1,0x97,0xd8,0xae,0xbe,0x20,0x3c,0x96,0xc8,0x72,0x32,0x27,0x21,0x72,0xfb,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0xff,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x82,0x4c,0x83,0xde,0x0b,0x50,0x2c,0xdf,0xc5,0x17,0x23,0xb5,0x18,0x86,0xb4,0xf0,0x79,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x46,0x02,0x22,0x01,0x00,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9a,0x3b,0xb6,0x0f,0xa1,0xa1,0x48,0x15,0xbb,0xc0,0xa9,0x54,0xa0,0x75,0x8d,0x2c,0x72,0xba,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x44,0x02,0x20,0x90,0x0e,0x75,0xad,0x23,0x3f,0xcc,0x90,0x85,0x09,0xdb,0xff,0x59,0x22,0x64,0x7e,0xf8,0xcd,0x45,0x0e,0x00,0x8a,0x7f,0xff,0x29,0x09,0xec,0x5a,0xa9,0x14,0xce,0x46,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0xfe,0x90,0x0e,0x75,0xad,0x23,0x3f,0xcc,0x90,0x85,0x09,0xdb,0xff,0x59,0x22,0x64,0x80,0x3e,0x1e,0x68,0x27,0x51,0x41,0xdf,0xc3,0x69,0x37,0x8d,0xcd,0xd8,0xde,0x8d,0x05,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0x01,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x45,0x02,0x21,0xff,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x4d,0x02,0x29,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba,0x02,0x20,0x6f,0xf1,0x8a,0x52,0xdc,0xc0,0x33,0x6f,0x7a,0xf6,0x24,0x00,0xa6,0xdd,0x9b,0x81,0x07,0x32,0xba,0xf1,0xff,0x75,0x80,0x00,0xd6,0xf6,0x13,0xa5,0x56,0xeb,0x31,0xba, - 0x30,0x06,0x02,0x01,0x00,0x02,0x01,0x00, - 0x30,0x06,0x02,0x01,0x00,0x02,0x01,0x01, - 0x30,0x06,0x02,0x01,0x00,0x02,0x01,0xff, - 0x30,0x26,0x02,0x01,0x00,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, - 0x30,0x26,0x02,0x01,0x00,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40, - 0x30,0x26,0x02,0x01,0x00,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42, - 0x30,0x26,0x02,0x01,0x00,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, - 0x30,0x26,0x02,0x01,0x00,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30, - 0x30,0x06,0x02,0x01,0x01,0x02,0x01,0x00, - 0x30,0x06,0x02,0x01,0x01,0x02,0x01,0x01, - 0x30,0x06,0x02,0x01,0x01,0x02,0x01,0xff, - 0x30,0x26,0x02,0x01,0x01,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, - 0x30,0x26,0x02,0x01,0x01,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40, - 0x30,0x26,0x02,0x01,0x01,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42, - 0x30,0x26,0x02,0x01,0x01,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, - 0x30,0x26,0x02,0x01,0x01,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30, - 0x30,0x06,0x02,0x01,0xff,0x02,0x01,0x00, - 0x30,0x06,0x02,0x01,0xff,0x02,0x01,0x01, - 0x30,0x06,0x02,0x01,0xff,0x02,0x01,0xff, - 0x30,0x26,0x02,0x01,0xff,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, - 0x30,0x26,0x02,0x01,0xff,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40, - 0x30,0x26,0x02,0x01,0xff,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42, - 0x30,0x26,0x02,0x01,0xff,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, - 0x30,0x26,0x02,0x01,0xff,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x02,0x01,0x00, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x02,0x01,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x02,0x01,0xff, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40,0x02,0x01,0x00, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40,0x02,0x01,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40,0x02,0x01,0xff, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42,0x02,0x01,0x00, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42,0x02,0x01,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42,0x02,0x01,0xff, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x02,0x01,0x00, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x02,0x01,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x02,0x01,0xff, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30,0x02,0x01,0x00, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30,0x02,0x01,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30,0x02,0x01,0xff, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x40, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x42, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, - 0x30,0x46,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x30, - 0x30,0x08,0x02,0x01,0x00,0x09,0x03,0x80,0xfe,0x01, - 0x30,0x06,0x02,0x01,0x00,0x09,0x01,0x42, - 0x30,0x06,0x02,0x01,0x00,0x01,0x01,0x01, - 0x30,0x06,0x02,0x01,0x00,0x01,0x01,0x00, - 0x30,0x05,0x02,0x01,0x00,0x05,0x00, - 0x30,0x05,0x02,0x01,0x00,0x0c,0x00, - 0x30,0x06,0x02,0x01,0x00,0x0c,0x01,0x30, - 0x30,0x05,0x02,0x01,0x00,0x30,0x00, - 0x30,0x08,0x02,0x01,0x00,0x30,0x03,0x02,0x01,0x00, - 0x30,0x08,0x02,0x01,0x01,0x09,0x03,0x80,0xfe,0x01, - 0x30,0x06,0x02,0x01,0x01,0x09,0x01,0x42, - 0x30,0x06,0x02,0x01,0x01,0x01,0x01,0x01, - 0x30,0x06,0x02,0x01,0x01,0x01,0x01,0x00, - 0x30,0x05,0x02,0x01,0x01,0x05,0x00, - 0x30,0x05,0x02,0x01,0x01,0x0c,0x00, - 0x30,0x06,0x02,0x01,0x01,0x0c,0x01,0x30, - 0x30,0x05,0x02,0x01,0x01,0x30,0x00, - 0x30,0x08,0x02,0x01,0x01,0x30,0x03,0x02,0x01,0x00, - 0x30,0x08,0x02,0x01,0xff,0x09,0x03,0x80,0xfe,0x01, - 0x30,0x06,0x02,0x01,0xff,0x09,0x01,0x42, - 0x30,0x06,0x02,0x01,0xff,0x01,0x01,0x01, - 0x30,0x06,0x02,0x01,0xff,0x01,0x01,0x00, - 0x30,0x05,0x02,0x01,0xff,0x05,0x00, - 0x30,0x05,0x02,0x01,0xff,0x0c,0x00, - 0x30,0x06,0x02,0x01,0xff,0x0c,0x01,0x30, - 0x30,0x05,0x02,0x01,0xff,0x30,0x00, - 0x30,0x08,0x02,0x01,0xff,0x30,0x03,0x02,0x01,0x00, - 0x30,0x28,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x09,0x03,0x80,0xfe,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x09,0x01,0x42, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x01,0x01,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x01,0x01,0x00, - 0x30,0x25,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x05,0x00, - 0x30,0x25,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x0c,0x00, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x0c,0x01,0x30, - 0x30,0x25,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x30,0x00, - 0x30,0x28,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41,0x30,0x03,0x02,0x01,0x00, - 0x30,0x28,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x09,0x03,0x80,0xfe,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x09,0x01,0x42, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x01,0x01,0x01, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x01,0x01,0x00, - 0x30,0x25,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x05,0x00, - 0x30,0x25,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x0c,0x00, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x0c,0x01,0x30, - 0x30,0x25,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x30,0x00, - 0x30,0x28,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x30,0x03,0x02,0x01,0x00, - 0x30,0x0a,0x09,0x03,0x80,0xfe,0x01,0x09,0x03,0x80,0xfe,0x01, - 0x30,0x06,0x09,0x01,0x42,0x09,0x01,0x42, - 0x30,0x06,0x01,0x01,0x01,0x01,0x01,0x01, - 0x30,0x06,0x01,0x01,0x00,0x01,0x01,0x00, - 0x30,0x04,0x05,0x00,0x05,0x00, - 0x30,0x04,0x0c,0x00,0x0c,0x00, - 0x30,0x06,0x0c,0x01,0x30,0x0c,0x01,0x30, - 0x30,0x04,0x30,0x00,0x30,0x00, - 0x30,0x0a,0x30,0x03,0x02,0x01,0x00,0x30,0x03,0x02,0x01,0x00, - 0x30,0x08,0x09,0x03,0x80,0xfe,0x01,0x02,0x01,0x00, - 0x30,0x06,0x09,0x01,0x42,0x02,0x01,0x00, - 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x00, - 0x30,0x06,0x01,0x01,0x00,0x02,0x01,0x00, - 0x30,0x05,0x05,0x00,0x02,0x01,0x00, - 0x30,0x05,0x0c,0x00,0x02,0x01,0x00, - 0x30,0x06,0x0c,0x01,0x30,0x02,0x01,0x00, - 0x30,0x05,0x30,0x00,0x02,0x01,0x00, - 0x30,0x08,0x30,0x03,0x02,0x01,0x00,0x02,0x01,0x00, - 0x30,0x45,0x02,0x21,0x00,0xdd,0x1b,0x7d,0x09,0xa7,0xbd,0x82,0x18,0x96,0x10,0x34,0xa3,0x9a,0x87,0xfe,0xcf,0x53,0x14,0xf0,0x0c,0x4d,0x25,0xeb,0x58,0xa0,0x7a,0xc8,0x5e,0x85,0xea,0xb5,0x16,0x02,0x20,0x35,0x13,0x8c,0x40,0x1e,0xf8,0xd3,0x49,0x3d,0x65,0xc9,0x00,0x2f,0xe6,0x2b,0x43,0xae,0xe5,0x68,0x73,0x1b,0x74,0x45,0x48,0x35,0x89,0x96,0xd9,0xcc,0x42,0x7e,0x06, - 0x30,0x45,0x02,0x21,0x00,0x95,0xc2,0x92,0x67,0xd9,0x72,0xa0,0x43,0xd9,0x55,0x22,0x45,0x46,0x22,0x2b,0xba,0x34,0x3f,0xc1,0xd4,0xdb,0x0f,0xec,0x26,0x2a,0x33,0xac,0x61,0x30,0x56,0x96,0xae,0x02,0x20,0x6e,0xdf,0xe9,0x67,0x13,0xae,0xd5,0x6f,0x8a,0x28,0xa6,0x65,0x3f,0x57,0xe0,0xb8,0x29,0x71,0x2e,0x5e,0xdd,0xc6,0x7f,0x34,0x68,0x2b,0x24,0xf0,0x67,0x6b,0x26,0x40, - 0x30,0x44,0x02,0x20,0x28,0xf9,0x4a,0x89,0x4e,0x92,0x02,0x46,0x99,0xe3,0x45,0xfe,0x66,0x97,0x1e,0x3e,0xdc,0xd0,0x50,0x02,0x33,0x86,0x13,0x5a,0xb3,0x93,0x9d,0x55,0x08,0x98,0xfb,0x25,0x02,0x20,0x32,0x96,0x3e,0x5b,0xd4,0x1f,0xa5,0x91,0x1e,0xd8,0xf3,0x7d,0xeb,0x86,0xda,0xe0,0xa7,0x62,0xbb,0x61,0x21,0xc8,0x94,0x61,0x50,0x83,0xc5,0xd9,0x5e,0xa0,0x1d,0xb3, - 0x30,0x45,0x02,0x21,0x00,0xbe,0x26,0xb1,0x8f,0x95,0x49,0xf8,0x9f,0x41,0x1a,0x9b,0x52,0x53,0x6b,0x15,0xaa,0x27,0x0b,0x84,0x54,0x8d,0x0e,0x85,0x9a,0x19,0x52,0xa2,0x7a,0xf1,0xa7,0x7a,0xc6,0x02,0x20,0x70,0xc1,0xd4,0xfa,0x9c,0xd0,0x3c,0xc8,0xea,0xa8,0xd5,0x06,0xed,0xb9,0x7e,0xed,0x7b,0x83,0x58,0xb4,0x53,0xc8,0x8a,0xef,0xbb,0x88,0x0a,0x3f,0x0e,0x8d,0x47,0x2f, - 0x30,0x45,0x02,0x21,0x00,0xb1,0xa4,0xb1,0x47,0x8e,0x65,0xcc,0x3e,0xaf,0xdf,0x22,0x5d,0x12,0x98,0xb4,0x3f,0x2d,0xa1,0x9e,0x4b,0xcf,0xf7,0xea,0xcc,0x0a,0x2e,0x98,0xcd,0x4b,0x74,0xb1,0x14,0x02,0x20,0x17,0x9a,0xa3,0x1e,0x30,0x4c,0xc1,0x42,0xcf,0x50,0x73,0x17,0x17,0x51,0xb2,0x8f,0x3f,0x5e,0x0f,0xa8,0x8c,0x99,0x4e,0x7c,0x55,0xf1,0xbc,0x07,0xb8,0xd5,0x6c,0x16, - 0x30,0x44,0x02,0x20,0x32,0x53,0x32,0x02,0x12,0x61,0xf1,0xbd,0x18,0xf2,0x71,0x2a,0xa1,0xe2,0x25,0x2d,0xa2,0x37,0x96,0xda,0x8a,0x4b,0x1f,0xf6,0xea,0x18,0xca,0xfe,0xc7,0xe1,0x71,0xf2,0x02,0x20,0x40,0xb4,0xf5,0xe2,0x87,0xee,0x61,0xfc,0x3c,0x80,0x41,0x86,0x98,0x23,0x60,0x89,0x1e,0xaa,0x35,0xc7,0x5f,0x05,0xa4,0x3e,0xcd,0x48,0xb3,0x5d,0x98,0x4a,0x66,0x48, - 0x30,0x45,0x02,0x21,0x00,0xa2,0x3a,0xd1,0x8d,0x8f,0xc6,0x6d,0x81,0xaf,0x09,0x03,0x89,0x0c,0xbd,0x45,0x3a,0x55,0x4c,0xb0,0x4c,0xdc,0x1a,0x8c,0xa7,0xf7,0xf7,0x8e,0x53,0x67,0xed,0x88,0xa0,0x02,0x20,0x23,0xe3,0xeb,0x2c,0xe1,0xc0,0x4e,0xa7,0x48,0xc3,0x89,0xbd,0x97,0x37,0x4a,0xa9,0x41,0x3b,0x92,0x68,0x85,0x1c,0x04,0xdc,0xd9,0xf8,0x8e,0x78,0x81,0x3f,0xee,0x56, - 0x30,0x44,0x02,0x20,0x2b,0xde,0xa4,0x1c,0xda,0x63,0xa2,0xd1,0x4b,0xf4,0x73,0x53,0xbd,0x20,0x88,0x0a,0x69,0x09,0x01,0xde,0x7c,0xd6,0xe3,0xcc,0x6d,0x8e,0xd5,0xba,0x0c,0xdb,0x10,0x91,0x02,0x20,0x3c,0xea,0x66,0xbc,0xcf,0xc9,0xf9,0xbf,0x8c,0x7c,0xa4,0xe1,0xc1,0x45,0x7c,0xc9,0x14,0x5e,0x13,0xe9,0x36,0xd9,0x0b,0x3d,0x9c,0x77,0x86,0xb8,0xb2,0x6c,0xf4,0xc7, - 0x30,0x45,0x02,0x21,0x00,0xd7,0xcd,0x76,0xec,0x01,0xc1,0xb1,0x07,0x9e,0xba,0x9e,0x2a,0xa2,0xa3,0x97,0x24,0x3c,0x47,0x58,0xc9,0x8a,0x1b,0xa0,0xb7,0x40,0x4a,0x34,0x0b,0x9b,0x00,0xce,0xd6,0x02,0x20,0x35,0x75,0x00,0x1e,0x19,0xd9,0x22,0xe6,0xde,0x8b,0x3d,0x6c,0x84,0xea,0x43,0xb5,0xc3,0x33,0x81,0x06,0xcf,0x29,0x99,0x01,0x34,0xe7,0x66,0x9a,0x82,0x6f,0x78,0xe6, - 0x30,0x45,0x02,0x21,0x00,0xa8,0x72,0xc7,0x44,0xd9,0x36,0xdb,0x21,0xa1,0x0c,0x36,0x1d,0xd5,0xc9,0x06,0x33,0x55,0xf8,0x49,0x02,0x21,0x96,0x52,0xf6,0xfc,0x56,0xdc,0x95,0xa7,0x13,0x9d,0x96,0x02,0x20,0x40,0x0d,0xf7,0x57,0x5d,0x97,0x56,0x21,0x0e,0x9c,0xcc,0x77,0x16,0x2c,0x6b,0x59,0x3c,0x77,0x46,0xcf,0xb4,0x8a,0xc2,0x63,0xc4,0x27,0x50,0xb4,0x21,0xef,0x4b,0xb9, - 0x30,0x45,0x02,0x21,0x00,0x9f,0xa9,0xaf,0xe0,0x77,0x52,0xda,0x10,0xb3,0x6d,0x3a,0xfc,0xd0,0xfe,0x44,0xbf,0xc4,0x02,0x44,0xd7,0x52,0x03,0x59,0x9c,0xf8,0xf5,0x04,0x7f,0xa3,0x45,0x38,0x54,0x02,0x20,0x50,0xe0,0xa7,0xc0,0x13,0xbf,0xbf,0x51,0x81,0x97,0x36,0x97,0x2d,0x44,0xb4,0xb5,0x6b,0xc2,0xa2,0xb2,0xc1,0x80,0xdf,0x6e,0xc6,0x72,0xdf,0x17,0x14,0x10,0xd7,0x7a, - 0x30,0x45,0x02,0x21,0x00,0x88,0x56,0x40,0x38,0x4d,0x0d,0x91,0x0e,0xfb,0x17,0x7b,0x46,0xbe,0x6c,0x3d,0xc5,0xca,0xc8,0x1f,0x0b,0x88,0xc3,0x19,0x0b,0xb6,0xb5,0xf9,0x9c,0x26,0x41,0xf2,0x05,0x02,0x20,0x73,0x8e,0xd9,0xbf,0xf1,0x16,0x30,0x6d,0x9c,0xaa,0x0f,0x8f,0xc6,0x08,0xbe,0x24,0x3e,0x0b,0x56,0x77,0x79,0xd8,0xda,0xb0,0x3e,0x8e,0x19,0xd5,0x53,0xf1,0xdc,0x8e, - 0x30,0x44,0x02,0x20,0x2d,0x05,0x1f,0x91,0xc5,0xa9,0xd4,0x40,0xc5,0x67,0x69,0x85,0x71,0x04,0x83,0xbc,0x4f,0x1a,0x6c,0x61,0x1b,0x10,0xc9,0x5a,0x2f,0xf0,0x36,0x3d,0x90,0xc2,0xa4,0x58,0x02,0x20,0x6d,0xdf,0x94,0xe6,0xfb,0xa5,0xbe,0x58,0x68,0x33,0xd0,0xc5,0x3c,0xf2,0x16,0xad,0x39,0x48,0xf3,0x79,0x53,0xc2,0x6c,0x1c,0xf4,0x96,0x8e,0x9a,0x9e,0x82,0x43,0xdc, - 0x30,0x45,0x02,0x21,0x00,0xf3,0xac,0x25,0x23,0x96,0x74,0x82,0xf5,0x3d,0x50,0x85,0x22,0x71,0x2d,0x58,0x3f,0x43,0x79,0xcd,0x82,0x41,0x01,0xff,0x63,0x5e,0xa0,0x93,0x51,0x17,0xba,0xa5,0x4f,0x02,0x20,0x27,0xf1,0x08,0x12,0x22,0x73,0x97,0xe0,0x2c,0xea,0x96,0xfb,0x0e,0x68,0x07,0x61,0x63,0x6d,0xab,0x2b,0x08,0x0d,0x1f,0xc5,0xd1,0x16,0x85,0xcb,0xe8,0x50,0x0c,0xfe, - 0x30,0x45,0x02,0x21,0x00,0x96,0x44,0x7c,0xf6,0x8c,0x3a,0xb7,0x26,0x6e,0xd7,0x44,0x7d,0xe3,0xac,0x52,0xfe,0xd7,0xcc,0x08,0xcb,0xdf,0xea,0x39,0x1c,0x18,0xa9,0xb8,0xab,0x37,0x0b,0xc9,0x13,0x02,0x20,0x0f,0x5e,0x78,0x74,0xd3,0xac,0x0e,0x91,0x8f,0x01,0xc8,0x85,0xa1,0x63,0x91,0x77,0xc9,0x23,0xf8,0x66,0x0d,0x1c,0xeb,0xa1,0xca,0x1f,0x30,0x1b,0xc6,0x75,0xcd,0xbc, - 0x30,0x44,0x02,0x20,0x53,0x0a,0x08,0x32,0xb6,0x91,0xda,0x0b,0x56,0x19,0xa0,0xb1,0x1d,0xe6,0x87,0x7f,0x3c,0x09,0x71,0xba,0xaa,0x68,0xed,0x12,0x27,0x58,0xc2,0x9c,0xaa,0xf4,0x6b,0x72,0x02,0x20,0x6c,0x89,0xe4,0x4f,0x5e,0xb3,0x30,0x60,0xea,0x4b,0x46,0x31,0x8c,0x39,0x13,0x8e,0xae,0xde,0xc7,0x2d,0xe4,0x2b,0xa5,0x76,0x57,0x9a,0x6a,0x46,0x90,0xe3,0x39,0xf3, - 0x30,0x45,0x02,0x21,0x00,0x9c,0x54,0xc2,0x55,0x00,0xbd,0xe0,0xb9,0x2d,0x72,0xd6,0xec,0x48,0x3d,0xc2,0x48,0x2f,0x36,0x54,0x29,0x4c,0xa7,0x4d,0xe7,0x96,0xb6,0x81,0x25,0x5e,0xd5,0x8a,0x77,0x02,0x20,0x67,0x74,0x53,0xc6,0xb5,0x6f,0x52,0x76,0x31,0xc9,0xf6,0x7b,0x3f,0x3e,0xb6,0x21,0xfd,0x88,0x58,0x2b,0x4a,0xff,0x15,0x6d,0x2f,0x15,0x67,0xd6,0x21,0x1a,0x2a,0x33, - 0x30,0x45,0x02,0x21,0x00,0xe7,0x90,0x9d,0x41,0x43,0x9e,0x2f,0x6a,0xf2,0x91,0x36,0xc7,0x34,0x8c,0xa2,0x64,0x1a,0x2b,0x07,0x0d,0x5b,0x64,0xf9,0x1e,0xa9,0xda,0x70,0x70,0xc7,0xa2,0x61,0x8b,0x02,0x20,0x42,0xd7,0x82,0xf1,0x32,0xfa,0x1d,0x36,0xc2,0xc8,0x8b,0xa2,0x7c,0x3d,0x67,0x8d,0x80,0x18,0x4a,0x5d,0x1e,0xcc,0xac,0x75,0x01,0xf0,0xb4,0x7e,0x3d,0x20,0x50,0x08, - 0x30,0x44,0x02,0x20,0x59,0x24,0x87,0x32,0x09,0x59,0x31,0x35,0xa4,0xc3,0xda,0x7b,0xb3,0x81,0x22,0x7f,0x8a,0x4b,0x6a,0xa9,0xf3,0x4f,0xe5,0xbb,0x7f,0x8f,0xbc,0x13,0x1a,0x03,0x9f,0xfe,0x02,0x20,0x1f,0x1b,0xb1,0x1b,0x44,0x1c,0x8f,0xea,0xa4,0x0f,0x44,0x21,0x3d,0x9a,0x40,0x5e,0xd7,0x92,0xd5,0x9f,0xb4,0x9d,0x5b,0xcd,0xd9,0xa4,0x28,0x5a,0xe5,0x69,0x30,0x22, - 0x30,0x45,0x02,0x21,0x00,0xee,0xb6,0x92,0xc9,0xb2,0x62,0x96,0x9b,0x23,0x1c,0x38,0xb5,0xa7,0xf6,0x06,0x49,0xe0,0xc8,0x75,0xcd,0x64,0xdf,0x88,0xf3,0x3a,0xa5,0x71,0xfa,0x3d,0x29,0xab,0x0e,0x02,0x20,0x21,0x8b,0x3a,0x1e,0xb0,0x63,0x79,0xc2,0xc1,0x8c,0xf5,0x1b,0x06,0x43,0x07,0x86,0xd1,0xc6,0x4c,0xd2,0xd2,0x4c,0x9b,0x23,0x2b,0x23,0xe5,0xba,0xc7,0x98,0x9a,0xcd, - 0x30,0x45,0x02,0x21,0x00,0xa4,0x00,0x34,0x17,0x7f,0x36,0x09,0x1c,0x2b,0x65,0x36,0x84,0xa0,0xe3,0xeb,0x5d,0x4b,0xff,0x18,0xe4,0xd0,0x9f,0x66,0x4c,0x28,0x00,0xe7,0xca,0xfd,0xa1,0xda,0xf8,0x02,0x20,0x3a,0x3e,0xc2,0x98,0x53,0x70,0x4e,0x52,0x03,0x1c,0x58,0x92,0x7a,0x80,0x0a,0x96,0x83,0x53,0xad,0xc3,0xd9,0x73,0xbe,0xba,0x91,0x72,0xcb,0xbe,0xab,0x4d,0xd1,0x49, - 0x30,0x45,0x02,0x21,0x00,0xb5,0xd7,0x95,0xcc,0x75,0xce,0xa5,0xc4,0x34,0xfa,0x41,0x85,0x18,0x0c,0xd6,0xbd,0x21,0x22,0x3f,0x3d,0x5a,0x86,0xda,0x66,0x70,0xd7,0x1d,0x95,0x68,0x0d,0xad,0xbf,0x02,0x20,0x54,0xe4,0xd8,0x81,0x0a,0x00,0x1e,0xcb,0xb9,0xf7,0xca,0x1c,0x2e,0xbf,0xdb,0x9d,0x00,0x9e,0x90,0x31,0xa4,0x31,0xac,0xa3,0xc2,0x0a,0xb4,0xe0,0xd1,0x37,0x4e,0xc1, - 0x30,0x44,0x02,0x20,0x07,0xdc,0x24,0x78,0xd4,0x3c,0x12,0x32,0xa4,0x59,0x56,0x08,0xc6,0x44,0x26,0xc3,0x55,0x10,0x05,0x1a,0x63,0x1a,0xe6,0xa5,0xa6,0xeb,0x11,0x61,0xe5,0x7e,0x42,0xe1,0x02,0x20,0x4a,0x59,0xea,0x0f,0xdb,0x72,0xd1,0x21,0x65,0xce,0xa3,0xbf,0x1c,0xa8,0x6b,0xa9,0x75,0x17,0xbd,0x18,0x8d,0xb3,0xdb,0xd2,0x1a,0x5a,0x15,0x78,0x50,0x02,0x19,0x84, - 0x30,0x45,0x02,0x21,0x00,0xdd,0xd2,0x0c,0x4a,0x05,0x59,0x6c,0xa8,0x68,0xb5,0x58,0x83,0x9f,0xce,0x9f,0x65,0x11,0xdd,0xd8,0x3d,0x1c,0xcb,0x53,0xf8,0x2e,0x52,0x69,0xd5,0x59,0xa0,0x15,0x52,0x02,0x20,0x5b,0x91,0x73,0x47,0x29,0xd9,0x30,0x93,0xff,0x22,0x12,0x3c,0x4a,0x25,0x81,0x9d,0x7f,0xeb,0x66,0xa2,0x50,0x66,0x3f,0xc7,0x80,0xcb,0x66,0xfc,0x7b,0x6e,0x6d,0x17, - 0x30,0x45,0x02,0x21,0x00,0x9c,0xde,0x6e,0x0e,0xde,0x0a,0x00,0x3f,0x02,0xfd,0xa0,0xa0,0x1b,0x59,0xfa,0xcf,0xe5,0xde,0xc0,0x63,0x31,0x8f,0x27,0x9c,0xe2,0xde,0x7a,0x9b,0x10,0x62,0xf7,0xb7,0x02,0x20,0x28,0x86,0xa5,0xb8,0xc6,0x79,0xbd,0xf8,0x22,0x4c,0x66,0xf9,0x08,0xfd,0x62,0x05,0x49,0x2c,0xb7,0x0b,0x00,0x68,0xd4,0x6a,0xe4,0xf3,0x3a,0x41,0x49,0xb1,0x2a,0x52, - 0x30,0x45,0x02,0x21,0x00,0xc5,0x77,0x10,0x16,0xd0,0xdd,0x63,0x57,0x14,0x3c,0x89,0xf6,0x84,0xcd,0x74,0x04,0x23,0x50,0x25,0x54,0xc0,0xc5,0x9a,0xa8,0xc9,0x95,0x84,0xf1,0xff,0x38,0xf6,0x09,0x02,0x20,0x54,0xb4,0x05,0xf4,0x47,0x75,0x46,0x68,0x6e,0x46,0x4c,0x54,0x63,0xb4,0xfd,0x41,0x90,0x57,0x2e,0x58,0xd0,0xf7,0xe7,0x35,0x7f,0x6e,0x61,0x94,0x7d,0x20,0x71,0x5c, - 0x30,0x45,0x02,0x21,0x00,0xa2,0x4e,0xbc,0x0e,0xc2,0x24,0xbd,0x67,0xae,0x39,0x7c,0xbe,0x6f,0xa3,0x7b,0x31,0x25,0xad,0xbd,0x34,0x89,0x1a,0xbe,0x2d,0x7c,0x73,0x56,0x92,0x19,0x16,0xdf,0xe6,0x02,0x20,0x34,0xf6,0xeb,0x63,0x74,0x73,0x1b,0xbb,0xaf,0xc4,0x92,0x4f,0xb8,0xb0,0xbd,0xcd,0xda,0x49,0x45,0x6d,0x72,0x4c,0xda,0xe6,0x17,0x8d,0x87,0x01,0x4c,0xb5,0x3d,0x8c, - 0x30,0x44,0x02,0x20,0x25,0x57,0xd6,0x4a,0x7a,0xee,0x2e,0x09,0x31,0xc0,0x12,0xe4,0xfe,0xa1,0xcd,0x3a,0x2c,0x33,0x4e,0xda,0xe6,0x8c,0xde,0xb7,0x15,0x8c,0xaf,0x21,0xb6,0x8e,0x5a,0x24,0x02,0x20,0x7f,0x06,0xcd,0xbb,0x6a,0x90,0x02,0x3a,0x97,0x38,0x82,0xed,0x97,0xb0,0x80,0xfe,0x6b,0x05,0xaf,0x3e,0xc9,0x3d,0xb6,0xf1,0xa4,0x39,0x9a,0x69,0xed,0xf7,0x67,0x0d, - 0x30,0x45,0x02,0x21,0x00,0xc4,0xf2,0xec,0xcb,0xb6,0xa2,0x43,0x50,0xc8,0x46,0x64,0x50,0xb9,0xd6,0x1b,0x20,0x7e,0xe3,0x59,0xe0,0x37,0xb3,0xdc,0xed,0xb4,0x2a,0x3f,0x2e,0x6d,0xd6,0xae,0xb5,0x02,0x20,0x32,0x63,0xc6,0xb5,0x9a,0x2f,0x55,0xcd,0xd1,0xc6,0xe1,0x48,0x94,0xd5,0xe5,0x96,0x3b,0x28,0xbc,0x3e,0x24,0x69,0xac,0x9b,0xa1,0x19,0x79,0x91,0xca,0x7f,0xf9,0xc7, - 0x30,0x45,0x02,0x21,0x00,0xef,0xf0,0x47,0x81,0xc9,0xcb,0xcd,0x16,0x2d,0x0a,0x25,0xa6,0xe2,0xeb,0xcc,0xa4,0x35,0x06,0xc5,0x23,0x38,0x5c,0xb5,0x15,0xd4,0x9e,0xa3,0x8a,0x1b,0x12,0xfc,0xad,0x02,0x20,0x15,0xac,0xd7,0x31,0x94,0xc9,0x1a,0x95,0x47,0x85,0x34,0xf2,0x30,0x15,0xb6,0x72,0xeb,0xed,0x21,0x3e,0x45,0x42,0x4d,0xd2,0xc8,0xe2,0x6a,0xc8,0xb3,0xeb,0x34,0xa5, - 0x30,0x45,0x02,0x21,0x00,0xf5,0x8b,0x4e,0x31,0x10,0xa6,0x4b,0xf1,0xb5,0xdb,0x97,0x63,0x9e,0xe0,0xe5,0xa9,0xc8,0xdf,0xa4,0x9d,0xc5,0x9b,0x67,0x98,0x91,0xf5,0x20,0xfd,0xf0,0x58,0x4c,0x87,0x02,0x20,0x2c,0xd8,0xfe,0x51,0x88,0x8a,0xee,0x9d,0xb3,0xe0,0x75,0x44,0x0f,0xd4,0xdb,0x73,0xb5,0xc7,0x32,0xfb,0x87,0xb5,0x10,0xe9,0x70,0x93,0xd6,0x64,0x15,0xf6,0x2a,0xf7, - 0x30,0x45,0x02,0x21,0x00,0xf8,0xab,0xec,0xaa,0x4f,0x0c,0x50,0x2d,0xe4,0xbf,0x59,0x03,0xd4,0x84,0x17,0xf7,0x86,0xbf,0x92,0xe8,0xad,0x72,0xfe,0xc0,0xbd,0x7f,0xcb,0x78,0x00,0xc0,0xbb,0xe3,0x02,0x20,0x4c,0x7f,0x9e,0x23,0x10,0x76,0xa3,0x0b,0x7a,0xe3,0x6b,0x0c,0xeb,0xe6,0x9c,0xce,0xf1,0xcd,0x19,0x4f,0x7c,0xce,0x93,0xa5,0x58,0x8f,0xd6,0x81,0x4f,0x43,0x7c,0x0e, - 0x30,0x44,0x02,0x20,0x5d,0x5b,0x38,0xbd,0x37,0xad,0x49,0x8b,0x22,0x27,0xa6,0x33,0x26,0x8a,0x8c,0xca,0x87,0x9a,0x5c,0x7c,0x94,0xa4,0xe4,0x16,0xbd,0x0a,0x61,0x4d,0x09,0xe6,0x06,0xd2,0x02,0x20,0x12,0xb8,0xd6,0x64,0xea,0x99,0x91,0x06,0x2e,0xcb,0xb8,0x34,0xe5,0x84,0x00,0xe2,0x5c,0x46,0x00,0x7a,0xf8,0x4f,0x60,0x07,0xd7,0xf1,0x68,0x54,0x43,0x26,0x9a,0xfe, - 0x30,0x44,0x02,0x20,0x0c,0x1c,0xd9,0xfe,0x40,0x34,0xf0,0x86,0xa2,0xb5,0x2d,0x65,0xb9,0xd3,0x83,0x4d,0x72,0xae,0xbe,0x7f,0x33,0xdf,0xe8,0xf9,0x76,0xda,0x82,0x64,0x81,0x77,0xd8,0xe3,0x02,0x20,0x13,0x10,0x57,0x82,0xe3,0xd0,0xcf,0xe8,0x5c,0x27,0x78,0xde,0xc1,0xa8,0x48,0xb2,0x7a,0xc0,0xae,0x07,0x1a,0xa6,0xda,0x34,0x1a,0x95,0x53,0xa9,0x46,0xb4,0x1e,0x59, - 0x30,0x45,0x02,0x21,0x00,0xae,0x79,0x35,0xfb,0x96,0xff,0x24,0x6b,0x7b,0x5d,0x56,0x62,0x87,0x0d,0x1b,0xa5,0x87,0xb0,0x3d,0x6e,0x13,0x60,0xba,0xf4,0x79,0x88,0xb5,0xc0,0x2c,0xcc,0x1a,0x5b,0x02,0x20,0x5f,0x00,0xc3,0x23,0x27,0x20,0x83,0x78,0x2d,0x4a,0x59,0xf2,0xdf,0xd6,0x5e,0x49,0xde,0x06,0x93,0x62,0x70,0x16,0x90,0x0e,0xf7,0xe6,0x14,0x28,0x05,0x66,0x64,0xb3, - 0x30,0x44,0x02,0x20,0x00,0xa1,0x34,0xb5,0xc6,0xcc,0xbc,0xef,0xd4,0xc8,0x82,0xb9,0x45,0xba,0xeb,0x49,0x33,0x44,0x41,0x72,0x79,0x5f,0xa6,0x79,0x6a,0xae,0x14,0x90,0x67,0x54,0x70,0x98,0x02,0x20,0x56,0x6e,0x46,0x10,0x5d,0x24,0xd8,0x90,0x15,0x1e,0x3e,0xea,0x3e,0xbf,0x88,0xf5,0xb9,0x2b,0x3f,0x5e,0xc9,0x3a,0x21,0x77,0x65,0xa6,0xdc,0xbd,0x94,0xf2,0xc5,0x5b, - 0x30,0x44,0x02,0x20,0x2e,0x47,0x21,0x36,0x3a,0xd3,0x99,0x2c,0x13,0x9e,0x5a,0x1c,0x26,0x39,0x5d,0x2c,0x2d,0x77,0x78,0x24,0xaa,0x24,0xfd,0xe0,0x75,0xe0,0xd7,0x38,0x11,0x71,0x30,0x9d,0x02,0x20,0x74,0x0f,0x7c,0x49,0x44,0x18,0xe1,0x30,0x0d,0xd4,0x51,0x2f,0x78,0x2a,0x58,0x80,0x0b,0xff,0x6a,0x7a,0xbd,0xfd,0xd2,0x0f,0xbb,0xd4,0xf0,0x55,0x15,0xca,0x1a,0x4f, - 0x30,0x44,0x02,0x20,0x68,0x52,0xe9,0xd3,0xcd,0x9f,0xe3,0x73,0xc2,0xd5,0x04,0x87,0x79,0x67,0xd3,0x65,0xab,0x14,0x56,0x70,0x7b,0x68,0x17,0xa0,0x42,0x86,0x46,0x94,0xe1,0x96,0x0c,0xcf,0x02,0x20,0x06,0x4b,0x27,0xea,0x14,0x2b,0x30,0x88,0x7b,0x84,0xc8,0x6a,0xdc,0xcb,0x2f,0xa3,0x9a,0x69,0x11,0xad,0x21,0xfc,0x7e,0x81,0x9f,0x59,0x3b,0xe5,0x2b,0xc4,0xf3,0xbd, - 0x30,0x44,0x02,0x20,0x18,0x8a,0x8c,0x56,0x48,0xdc,0x79,0xea,0xce,0x15,0x8c,0xf8,0x86,0xc6,0x2b,0x54,0x68,0xf0,0x5f,0xd9,0x5f,0x03,0xa7,0x63,0x5c,0x5b,0x4c,0x31,0xf0,0x9a,0xf4,0xc5,0x02,0x20,0x36,0x36,0x1a,0x0b,0x57,0x1a,0x00,0xc6,0xcd,0x5e,0x68,0x6c,0xcb,0xfc,0xfa,0x70,0x3c,0x4f,0x97,0xe4,0x89,0x38,0x34,0x6d,0x0c,0x10,0x3f,0xdc,0x76,0xdc,0x58,0x67, - 0x30,0x45,0x02,0x21,0x00,0xa7,0x4f,0x1f,0xb9,0xa8,0x26,0x3f,0x62,0xfc,0x44,0x16,0xa5,0xb7,0xd5,0x84,0xf4,0x20,0x6f,0x39,0x96,0xbb,0x91,0xf6,0xfc,0x8e,0x73,0xb9,0xe9,0x2b,0xad,0x0e,0x13,0x02,0x20,0x68,0x15,0x03,0x2e,0x8c,0x7d,0x76,0xc3,0xab,0x06,0xa8,0x6f,0x33,0x24,0x9c,0xe9,0x94,0x01,0x48,0xcb,0x36,0xd1,0xf4,0x17,0xc2,0xe9,0x92,0xe8,0x01,0xaf,0xa3,0xfa, - 0x30,0x44,0x02,0x20,0x07,0x24,0x48,0x65,0xb7,0x2f,0xf3,0x7e,0x62,0xe3,0x14,0x6f,0x0d,0xc1,0x46,0x82,0xba,0xdd,0x71,0x97,0x79,0x91,0x35,0xf0,0xb0,0x0a,0xde,0x76,0x71,0x74,0x2b,0xfe,0x02,0x20,0x0d,0x80,0xc2,0x23,0x8e,0xdb,0x4e,0x4a,0x7a,0x86,0xa8,0xc5,0x7c,0xa9,0xaf,0x17,0x11,0xf4,0x06,0xf7,0xf5,0xda,0x02,0x99,0xaa,0x04,0xe2,0x93,0x2d,0x96,0x07,0x54, - 0x30,0x45,0x02,0x21,0x00,0xda,0x7f,0xdd,0x05,0xb5,0xba,0xda,0xbd,0x61,0x9d,0x80,0x5c,0x4e,0xe7,0xd9,0xa8,0x4f,0x84,0xdd,0xd5,0xcf,0x9c,0x5b,0xf4,0xd4,0x33,0x81,0x40,0xd6,0x89,0xef,0x08,0x02,0x20,0x28,0xf1,0xcf,0x4f,0xa1,0xc3,0xc5,0x86,0x2c,0xfa,0x14,0x9c,0x00,0x13,0xcf,0x5f,0xe6,0xcf,0x50,0x76,0xca,0xe0,0x00,0x51,0x10,0x63,0xe7,0xde,0x25,0xbb,0x38,0xe5, - 0x30,0x45,0x02,0x21,0x00,0xd3,0x02,0x7c,0x65,0x6f,0x6d,0x4f,0xdf,0xd8,0xed,0xe2,0x20,0x93,0xe3,0xc3,0x03,0xb0,0x13,0x3c,0x34,0x0d,0x61,0x5e,0x77,0x56,0xf6,0x25,0x3a,0xea,0x92,0x72,0x38,0x02,0x20,0x09,0xae,0xf0,0x60,0xc8,0xe4,0xce,0xf9,0x72,0x97,0x40,0x11,0x55,0x8d,0xf1,0x44,0xfe,0xd2,0x5c,0xa6,0x9a,0xe8,0xd0,0xb2,0xea,0xf1,0xa8,0xfe,0xef,0xbe,0xc4,0x17, - 0x30,0x44,0x02,0x20,0x0b,0xf6,0xc0,0x18,0x8d,0xc9,0x57,0x1c,0xd0,0xe2,0x1e,0xec,0xac,0x5f,0xbb,0x19,0xd2,0x43,0x49,0x88,0xe9,0xcc,0x10,0x24,0x45,0x93,0xef,0x3a,0x98,0x09,0x9f,0x69,0x02,0x20,0x48,0x64,0xa5,0x62,0x66,0x1f,0x92,0x21,0xec,0x88,0xe3,0xdd,0x0b,0xc2,0xf6,0xe2,0x7a,0xc1,0x28,0xc3,0x0c,0xc1,0xa8,0x0f,0x79,0xec,0x67,0x0a,0x22,0xb0,0x42,0xee, - 0x30,0x45,0x02,0x21,0x00,0xae,0x45,0x96,0x40,0xd5,0xd1,0x17,0x9b,0xe4,0x7a,0x47,0xfa,0x53,0x8e,0x16,0xd9,0x4d,0xde,0xa5,0x58,0x5e,0x7a,0x24,0x48,0x04,0xa5,0x17,0x42,0xc6,0x86,0x44,0x3a,0x02,0x20,0x6c,0x8e,0x30,0xe5,0x30,0xa6,0x34,0xfa,0xe8,0x0b,0x3c,0xeb,0x06,0x29,0x78,0xb3,0x9e,0xdb,0xe1,0x97,0x77,0xe0,0xa2,0x45,0x53,0xb6,0x88,0x86,0x18,0x1f,0xd8,0x97, - 0x30,0x44,0x02,0x20,0x1c,0xf3,0x51,0x7b,0xa3,0xbf,0x2a,0xb8,0xb9,0xea,0xd4,0xeb,0xb6,0xe8,0x66,0xcb,0x88,0xa1,0xde,0xac,0xb6,0xa7,0x85,0xd3,0xb6,0x3b,0x48,0x3c,0xa0,0x2a,0xc4,0x95,0x02,0x20,0x24,0x9a,0x79,0x8b,0x73,0x60,0x6f,0x55,0xf5,0xf1,0xc7,0x0d,0xe6,0x7c,0xb1,0xa0,0xcf,0xf9,0x5d,0x7d,0xc5,0x0b,0x3a,0x61,0x7d,0xf8,0x61,0xba,0xd3,0xc6,0xb1,0xc9, - 0x30,0x45,0x02,0x21,0x00,0xe6,0x9b,0x52,0x38,0x26,0x5e,0xa3,0x5d,0x77,0xe4,0xdd,0x17,0x22,0x88,0xd8,0xce,0xa1,0x98,0x10,0xa1,0x02,0x92,0x61,0x7d,0x59,0x76,0x51,0x9d,0xc5,0x75,0x7c,0xb8,0x02,0x20,0x4b,0x03,0xc5,0xbc,0x47,0xe8,0x26,0xbd,0xb2,0x73,0x28,0xab,0xd3,0x8d,0x30,0x56,0xd7,0x74,0x76,0xb2,0x13,0x0f,0x3d,0xf6,0xec,0x48,0x91,0xaf,0x08,0xba,0x1e,0x29, - 0x30,0x44,0x02,0x20,0x5f,0x9d,0x7d,0x7c,0x87,0x0d,0x08,0x5f,0xc1,0xd4,0x9f,0xff,0x69,0xe4,0xa2,0x75,0x81,0x28,0x00,0xd2,0xcf,0x89,0x73,0xe7,0x32,0x58,0x66,0xcb,0x40,0xfa,0x2b,0x6f,0x02,0x20,0x6d,0x1f,0x54,0x91,0xd9,0xf7,0x17,0xa5,0x97,0xa1,0x5f,0xd5,0x40,0x40,0x64,0x86,0xd7,0x6a,0x44,0x69,0x7b,0x3f,0x0d,0x9d,0x6d,0xce,0xf6,0x66,0x9f,0x8a,0x0a,0x56, - 0x30,0x44,0x02,0x20,0x0a,0x7d,0x5b,0x19,0x59,0xf7,0x1d,0xf9,0xf8,0x17,0x14,0x6e,0xe4,0x9b,0xd5,0xc8,0x9b,0x43,0x1e,0x79,0x93,0xe2,0xfd,0xec,0xab,0x68,0x58,0x95,0x7d,0xa6,0x85,0xae,0x02,0x20,0x0f,0x8a,0xad,0x2d,0x25,0x46,0x90,0xbd,0xc1,0x3f,0x34,0xa4,0xfe,0xc4,0x4a,0x02,0xfd,0x74,0x5a,0x42,0x2d,0xf0,0x5c,0xcb,0xb5,0x46,0x35,0xa8,0xb8,0x6b,0x96,0x09, - 0x30,0x44,0x02,0x20,0x79,0xe8,0x8b,0xf5,0x76,0xb7,0x4b,0xc0,0x7c,0xa1,0x42,0x39,0x5f,0xda,0x28,0xf0,0x3d,0x3d,0x5e,0x64,0x0b,0x0b,0x4f,0xf0,0x75,0x2c,0x6d,0x94,0xcd,0x55,0x34,0x08,0x02,0x20,0x32,0xce,0xa0,0x5b,0xd2,0xd7,0x06,0xc8,0xf6,0x03,0x6a,0x50,0x7e,0x2a,0xb7,0x76,0x60,0x04,0xf0,0x90,0x4e,0x2e,0x5c,0x58,0x62,0x74,0x9c,0x00,0x73,0x24,0x5d,0x6a, - 0x30,0x45,0x02,0x21,0x00,0x9d,0x54,0xe0,0x37,0xa0,0x02,0x12,0xb3,0x77,0xbc,0x88,0x74,0x79,0x8b,0x8d,0xa0,0x80,0x56,0x4b,0xbd,0xf7,0xe0,0x75,0x91,0xb8,0x61,0x28,0x58,0x09,0xd0,0x14,0x88,0x02,0x20,0x18,0xb4,0xe5,0x57,0x66,0x7a,0x82,0xbd,0x95,0x96,0x5f,0x07,0x06,0xf8,0x1a,0x29,0x24,0x3f,0xbd,0xd8,0x69,0x68,0xa7,0xeb,0xeb,0x43,0x06,0x9d,0xb3,0xb1,0x8c,0x7f, - 0x30,0x44,0x02,0x20,0x26,0x64,0xf1,0xff,0xa9,0x82,0xfe,0xdb,0xcc,0x7c,0xab,0x1b,0x8b,0xc6,0xe2,0xcb,0x42,0x02,0x18,0xd2,0xa6,0x07,0x7a,0xd0,0x8e,0x59,0x1b,0xa9,0xfe,0xab,0x33,0xbd,0x02,0x20,0x49,0xf5,0xc7,0xcb,0x51,0x5e,0x83,0x87,0x2a,0x3d,0x41,0xb4,0xcd,0xb8,0x5f,0x24,0x2a,0xd9,0xd6,0x1a,0x5b,0xfc,0x01,0xde,0xbf,0xbb,0x52,0xc6,0xc8,0x4b,0xa7,0x28, - 0x30,0x44,0x02,0x20,0x58,0x27,0x51,0x83,0x44,0x84,0x4f,0xd6,0xa7,0xde,0x73,0xcb,0xb0,0xa6,0xbe,0xfd,0xea,0x7b,0x13,0xd2,0xde,0xe4,0x47,0x53,0x17,0xf0,0xf1,0x8f,0xfc,0x81,0x52,0x4b,0x02,0x20,0x4f,0x5c,0xcb,0x4e,0x0b,0x48,0x8b,0x5a,0x5d,0x76,0x0a,0xac,0xdd,0xb2,0xd7,0x91,0x97,0x0f,0xe4,0x3d,0xa6,0x1e,0xb3,0x0e,0x2e,0x90,0x20,0x8a,0x81,0x7e,0x46,0xdb, - 0x30,0x45,0x02,0x21,0x00,0x97,0xab,0x19,0xbd,0x13,0x9c,0xac,0x31,0x93,0x25,0x86,0x92,0x18,0xb1,0xbc,0xe1,0x11,0x87,0x5d,0x63,0xfb,0x12,0x09,0x8a,0x04,0xb0,0xcd,0x59,0xb6,0xfd,0xd3,0xa3,0x02,0x20,0x43,0x1d,0x9c,0xea,0x3a,0x24,0x38,0x47,0x30,0x3c,0xeb,0xda,0x56,0x47,0x64,0x31,0xd0,0x34,0x33,0x9f,0x31,0xd7,0x85,0xee,0x88,0x52,0xdb,0x4f,0x04,0x0d,0x49,0x21, - 0x30,0x44,0x02,0x20,0x52,0xc6,0x83,0x14,0x4e,0x44,0x11,0x9a,0xe2,0x01,0x37,0x49,0xd4,0x96,0x4e,0xf6,0x75,0x09,0x27,0x8f,0x6d,0x38,0xba,0x86,0x9a,0xdc,0xfa,0x69,0x97,0x0e,0x12,0x3d,0x02,0x20,0x34,0x79,0x91,0x01,0x67,0x40,0x8f,0x45,0xbd,0xa4,0x20,0xa6,0x26,0xec,0x9c,0x4e,0xc7,0x11,0xc1,0x27,0x4b,0xe0,0x92,0x19,0x8b,0x41,0x87,0xc0,0x18,0xb5,0x62,0xca, - 0x30,0x16,0x02,0x11,0x01,0x45,0x51,0x23,0x19,0x50,0xb7,0x5f,0xc4,0x40,0x2d,0xa1,0x72,0x2f,0xc9,0xba,0xeb,0x02,0x01,0x03, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2c,0x02,0x01,0x03, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x3f,0x02,0x01,0x03, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x3e,0x9a,0x75,0x82,0x88,0x60,0x89,0xc6,0x2f,0xb8,0x40,0xcf,0x3b,0x83,0x06,0x1c,0xd1,0xcf,0xf3,0xae,0x43,0x41,0x80,0x8b,0xb5,0xbd,0xee,0x61,0x91,0x17,0x41,0x77, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x24,0x23,0x8e,0x70,0xb4,0x31,0xb1,0xa6,0x4e,0xfd,0xf9,0x03,0x26,0x69,0x93,0x9d,0x4b,0x77,0xf2,0x49,0x50,0x3f,0xc6,0x90,0x5f,0xeb,0x75,0x40,0xde,0xa3,0xe6,0xd2, - 0x30,0x06,0x02,0x01,0x01,0x02,0x01,0x01, - 0x30,0x06,0x02,0x01,0x01,0x02,0x01,0x02, - 0x30,0x06,0x02,0x01,0x01,0x02,0x01,0x03, - 0x30,0x06,0x02,0x01,0x02,0x02,0x01,0x01, - 0x30,0x06,0x02,0x01,0x02,0x02,0x01,0x02, - 0x30,0x06,0x02,0x01,0x02,0x02,0x01,0x03, - 0x30,0x26,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x43,0x02,0x01,0x03, - 0x30,0x08,0x02,0x01,0x02,0x02,0x03,0xed,0x29,0x79, - 0x30,0x26,0x02,0x02,0x01,0x01,0x02,0x20,0x3a,0x74,0xe9,0xd3,0xa7,0x4e,0x9d,0x3a,0x74,0xe9,0xd3,0xa7,0x4e,0x9d,0x3a,0x74,0x9f,0x8a,0xb3,0x73,0x2a,0x0a,0x89,0x60,0x4a,0x09,0xbc,0xe5,0xb2,0x91,0x6d,0xa4, - 0x30,0x2b,0x02,0x07,0x2d,0x9b,0x4d,0x34,0x79,0x52,0xcc,0x02,0x20,0x03,0x43,0xae,0xfc,0x2f,0x25,0xd9,0x8b,0x88,0x2e,0x86,0xeb,0x9e,0x30,0xd5,0x5a,0x6e,0xb5,0x08,0xb5,0x16,0x51,0x0b,0x34,0x02,0x4a,0xe4,0xb6,0x36,0x23,0x30,0xb3, - 0x30,0x31,0x02,0x0d,0x10,0x33,0xe6,0x7e,0x37,0xb3,0x2b,0x44,0x55,0x80,0xbf,0x4e,0xfc,0x02,0x20,0x6f,0x90,0x6f,0x90,0x6f,0x90,0x6f,0x90,0x6f,0x90,0x6f,0x90,0x6f,0x90,0x6f,0x8f,0xe1,0xca,0xb5,0xee,0xfd,0xb2,0x14,0x06,0x1d,0xce,0x3b,0x22,0x78,0x9f,0x1d,0x6f, - 0x30,0x26,0x02,0x02,0x01,0x01,0x02,0x20,0x78,0x32,0x66,0xe9,0x0f,0x43,0xda,0xfe,0x5c,0xd9,0xb3,0xb0,0xbe,0x86,0xde,0x22,0xf9,0xde,0x83,0x67,0x7d,0x0f,0x50,0x71,0x3a,0x46,0x8e,0xc7,0x2f,0xcf,0x5d,0x57, - 0x30,0x31,0x02,0x0d,0x06,0x25,0x22,0xbb,0xd3,0xec,0xbe,0x7c,0x39,0xe9,0x3e,0x7c,0x26,0x02,0x20,0x78,0x32,0x66,0xe9,0x0f,0x43,0xda,0xfe,0x5c,0xd9,0xb3,0xb0,0xbe,0x86,0xde,0x22,0xf9,0xde,0x83,0x67,0x7d,0x0f,0x50,0x71,0x3a,0x46,0x8e,0xc7,0x2f,0xcf,0x5d,0x57, - 0x30,0x45,0x02,0x21,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x40,0xc1,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc0, - 0x30,0x16,0x02,0x09,0x00,0x9c,0x44,0xfe,0xbf,0x31,0xc3,0x59,0x4d,0x02,0x09,0x00,0x83,0x9e,0xd2,0x82,0x47,0xc2,0xb0,0x6b, - 0x30,0x1e,0x02,0x0d,0x09,0xdf,0x8b,0x68,0x24,0x30,0xbe,0xef,0x6f,0x5f,0xd7,0xc7,0xcf,0x02,0x0d,0x0f,0xd0,0xa6,0x2e,0x13,0x77,0x8f,0x42,0x22,0xa0,0xd6,0x1c,0x8a, - 0x30,0x26,0x02,0x11,0x00,0x8a,0x59,0x8e,0x56,0x3a,0x89,0xf5,0x26,0xc3,0x2e,0xbe,0xc8,0xde,0x26,0x36,0x7a,0x02,0x11,0x00,0x84,0xf6,0x33,0xe2,0x04,0x26,0x30,0xe9,0x9d,0xd0,0xf1,0xe1,0x6f,0x7a,0x04,0xbf, - 0x30,0x2e,0x02,0x15,0x00,0xaa,0x6e,0xeb,0x58,0x23,0xf7,0xfa,0x31,0xb4,0x66,0xbb,0x47,0x37,0x97,0xf0,0xd0,0x31,0x4c,0x0b,0xdf,0x02,0x15,0x00,0xe2,0x97,0x7c,0x47,0x9e,0x6d,0x25,0x70,0x3c,0xeb,0xbc,0x6b,0xd5,0x61,0x93,0x8c,0xc9,0xd1,0xbf,0xb9, - 0x30,0x25,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x01,0x01, - 0x30,0x25,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x01,0x00, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x41,0x9d,0x98,0x1c,0x51,0x5a,0xf8,0xcc,0x82,0x54,0x5a,0xac,0x0c,0x85,0xe9,0xe3,0x08,0xfb,0xb2,0xea,0xb6,0xac,0xd7,0xed,0x49,0x7e,0x0b,0x41,0x45,0xa1,0x8f,0xd9, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x1b,0x21,0x71,0x7a,0xd7,0x1d,0x23,0xbb,0xac,0x60,0xa9,0xad,0x0b,0xaf,0x75,0xb0,0x63,0xc9,0xfd,0xf5,0x2a,0x00,0xeb,0xf9,0x9d,0x02,0x21,0x72,0x91,0x09,0x93,0xc9, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x2f,0x58,0x8f,0x66,0x01,0x8f,0x3d,0xd1,0x4d,0xb3,0xe2,0x8e,0x77,0x99,0x64,0x87,0xe3,0x24,0x86,0xb5,0x21,0xed,0x8e,0x5a,0x20,0xf0,0x65,0x91,0x95,0x17,0x77,0xe9, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x09,0x1a,0x08,0x87,0x0f,0xf4,0xda,0xf9,0x12,0x3b,0x30,0xc2,0x0e,0x8c,0x4f,0xc8,0x50,0x57,0x58,0xdc,0xf4,0x07,0x4f,0xca,0xff,0x21,0x70,0xc9,0xbf,0xcf,0x74,0xf4, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x7c,0x37,0x0d,0xc0,0xce,0x8c,0x59,0xa8,0xb2,0x73,0xcb,0xa4,0x4a,0x7c,0x11,0x91,0xfc,0x31,0x86,0xdc,0x03,0xca,0xb9,0x6b,0x05,0x67,0x31,0x2d,0xf0,0xd0,0xb2,0x50, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x70,0xb5,0x9a,0x7d,0x1e,0xe7,0x7a,0x2f,0x9e,0x04,0x91,0xc2,0xa7,0xcf,0xcd,0x0e,0xd0,0x4d,0xf4,0xa3,0x51,0x92,0xf6,0x13,0x2d,0xcc,0x66,0x8c,0x79,0xa6,0x16,0x0e, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x27,0x36,0xd7,0x6e,0x41,0x22,0x46,0xe0,0x97,0x14,0x8e,0x2b,0xf6,0x29,0x15,0x61,0x4e,0xb7,0xc4,0x28,0x91,0x3a,0x58,0xeb,0x5e,0x9c,0xd4,0x67,0x4a,0x94,0x23,0xde, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x4a,0x1e,0x12,0x83,0x1f,0xbe,0x93,0x62,0x7b,0x02,0xd6,0xe7,0xf2,0x4b,0xcc,0xdd,0x6e,0xf4,0xb2,0xd0,0xf4,0x67,0x39,0xea,0xf3,0xb1,0xea,0xf0,0xca,0x11,0x77,0x70, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x06,0xc7,0x78,0xd4,0xdf,0xff,0x7d,0xee,0x06,0xed,0x88,0xbc,0x4e,0x0e,0xd3,0x4f,0xc5,0x53,0xaa,0xd6,0x7c,0xaf,0x79,0x6f,0x2a,0x1c,0x64,0x87,0xc1,0xb2,0xe8,0x77, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x4d,0xe4,0x59,0xef,0x91,0x59,0xaf,0xa0,0x57,0xfe,0xb3,0xec,0x40,0xfe,0xf0,0x1c,0x45,0xb8,0x09,0xf4,0xab,0x29,0x6e,0xa4,0x8c,0x20,0x6d,0x42,0x49,0xa2,0xb4,0x51, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x74,0x5d,0x29,0x49,0x78,0x00,0x73,0x02,0x03,0x35,0x02,0xe1,0xac,0xc4,0x8b,0x63,0xae,0x65,0x00,0xbe,0x43,0xad,0xbe,0xa1,0xb2,0x58,0xd6,0xb4,0x23,0xdb,0xb4,0x16, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x7b,0x2a,0x78,0x5e,0x38,0x96,0xf5,0x9b,0x2d,0x69,0xda,0x57,0x64,0x8e,0x80,0xad,0x3c,0x13,0x3a,0x75,0x0a,0x28,0x47,0xfd,0x20,0x98,0xcc,0xd9,0x02,0x04,0x2b,0x6c, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x71,0xae,0x94,0xa7,0x2c,0xa8,0x96,0x87,0x5e,0x7a,0xa4,0xa4,0xc3,0xd2,0x9a,0xfd,0xb4,0xb3,0x5b,0x69,0x96,0x27,0x3e,0x63,0xc4,0x7a,0xc5,0x19,0x25,0x6c,0x5e,0xb1, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x0f,0xa5,0x27,0xfa,0x73,0x43,0xc0,0xbc,0x9e,0xc3,0x5a,0x62,0x78,0xbf,0xbf,0xf4,0xd8,0x33,0x01,0xb1,0x54,0xfc,0x4b,0xd1,0x4a,0xee,0x7e,0xb9,0x34,0x45,0xb5,0xf9, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc1,0x02,0x20,0x65,0x39,0xc0,0xad,0xad,0xd0,0x52,0x5f,0xf4,0x26,0x22,0x16,0x4c,0xe9,0x31,0x43,0x48,0xbd,0x08,0x63,0xb4,0xc8,0x0e,0x93,0x6b,0x23,0xca,0x04,0x14,0x26,0x46,0x71, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5d,0x57,0x6e,0x73,0x57,0xa4,0x50,0x1d,0xdf,0xe9,0x2f,0x46,0x68,0x1b,0x20,0xa0,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc0, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5d,0x57,0x6e,0x73,0x57,0xa4,0x50,0x1d,0xdf,0xe9,0x2f,0x46,0x68,0x1b,0x20,0xa0,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5d,0x57,0x6e,0x73,0x57,0xa4,0x50,0x1d,0xdf,0xe9,0x2f,0x46,0x68,0x1b,0x20,0xa0, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5d,0x57,0x6e,0x73,0x57,0xa4,0x50,0x1d,0xdf,0xe9,0x2f,0x46,0x68,0x1b,0x20,0xa0,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5d,0x57,0x6e,0x73,0x57,0xa4,0x50,0x1d,0xdf,0xe9,0x2f,0x46,0x68,0x1b,0x20,0xa1, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xb8,0x02,0x20,0x44,0xa5,0xad,0x0b,0xd0,0x63,0x6d,0x9e,0x12,0xbc,0x9e,0x0a,0x6b,0xdd,0x5e,0x1b,0xba,0x77,0xf5,0x23,0x84,0x21,0x93,0xb3,0xb8,0x2e,0x44,0x8e,0x05,0xd5,0xf1,0x1e, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xb8,0x02,0x20,0x44,0xa5,0xad,0x0b,0xd0,0x63,0x6d,0x9e,0x12,0xbc,0x9e,0x0a,0x6b,0xdd,0x5e,0x1b,0xba,0x77,0xf5,0x23,0x84,0x21,0x93,0xb3,0xb8,0x2e,0x44,0x8e,0x05,0xd5,0xf1,0x1e, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xb8,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xb8, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xb8,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xb8, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x16,0xe1,0xe4,0x59,0x45,0x76,0x79,0xdf,0x5b,0x94,0x34,0xae,0x23,0xf4,0x74,0xb3,0xe8,0xd2,0xa7,0x0b,0xd6,0xb5,0xdb,0xe6,0x92,0xba,0x16,0xda,0x01,0xf1,0xfb,0x0a, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x1c,0x94,0x0f,0x31,0x3f,0x92,0x64,0x7b,0xe2,0x57,0xec,0xcd,0x7e,0xd0,0x8b,0x0b,0xae,0xf3,0xf0,0x47,0x8f,0x25,0x87,0x1b,0x53,0x63,0x53,0x02,0xc5,0xf6,0x31,0x4a, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x15,0xd9,0x4a,0x85,0x07,0x7b,0x49,0x3f,0x91,0xcb,0x71,0x01,0xec,0x63,0xe1,0xb0,0x1b,0xe5,0x8b,0x59,0x4e,0x85,0x5f,0x45,0x05,0x0a,0x8c,0x14,0x06,0x2d,0x68,0x9b, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x5b,0x1d,0x27,0xa7,0x69,0x4c,0x14,0x62,0x44,0xa5,0xad,0x0b,0xd0,0x63,0x6d,0x9d,0x9e,0xf3,0xb9,0xfb,0x58,0x38,0x54,0x18,0xd9,0xc9,0x82,0x10,0x50,0x77,0xd1,0xb7, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x2d,0x85,0x89,0x6b,0x3e,0xb9,0xdb,0xb5,0xa5,0x2f,0x42,0xf9,0xc9,0x26,0x1e,0xd3,0xfc,0x46,0x64,0x4e,0xc6,0x5f,0x06,0xad,0xe3,0xfd,0x78,0xf2,0x57,0xe4,0x34,0x32, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x5b,0x0b,0x12,0xd6,0x7d,0x73,0xb7,0x6b,0x4a,0x5e,0x85,0xf3,0x92,0x4c,0x3d,0xa7,0xf8,0x8c,0xc8,0x9d,0x8c,0xbe,0x0d,0x5b,0xc7,0xfa,0xf1,0xe4,0xaf,0xc8,0x68,0x64, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x69,0x4c,0x14,0x62,0x44,0xa5,0xad,0x0b,0xd0,0x63,0x6d,0x9e,0x12,0xbc,0x9e,0x09,0xe6,0x0e,0x68,0xb9,0x0d,0x0b,0x5e,0x6c,0x5d,0xdd,0xd0,0xcb,0x69,0x4d,0x87,0x99, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x3d,0x7f,0x48,0x7c,0x07,0xbf,0xc5,0xf3,0x08,0x46,0x93,0x8a,0x3d,0xce,0xf6,0x96,0x44,0x47,0x07,0xcf,0x96,0x77,0x25,0x4a,0x92,0xb0,0x6c,0x63,0xab,0x86,0x7d,0x22, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x6c,0x76,0x48,0xfc,0x0f,0xbf,0x8a,0x06,0xad,0xb8,0xb8,0x39,0xf9,0x7b,0x4f,0xf7,0xa8,0x00,0xf1,0x1b,0x1e,0x37,0xc5,0x93,0xb2,0x61,0x39,0x45,0x99,0x79,0x2b,0xa4, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x64,0x1c,0x9c,0x5d,0x79,0x0d,0xc0,0x9c,0xdd,0x3d,0xfa,0xbb,0x62,0xcd,0xf4,0x53,0xe6,0x97,0x47,0xa7,0xe3,0xd7,0xaa,0x1a,0x71,0x41,0x89,0xef,0x53,0x17,0x1a,0x99, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x29,0x79,0x8c,0x5c,0x45,0xbd,0xf5,0x8b,0x4a,0x7b,0x2f,0xdc,0x2c,0x46,0xab,0x4a,0xf1,0x21,0x8c,0x7e,0xeb,0x9f,0x0f,0x27,0xa8,0x8f,0x12,0x67,0x67,0x4d,0xe3,0xb0, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x0b,0x70,0xf2,0x2c,0xa2,0xbb,0x3c,0xef,0xad,0xca,0x1a,0x57,0x11,0xfa,0x3a,0x59,0xf4,0x69,0x53,0x85,0xeb,0x5a,0xed,0xf3,0x49,0x5d,0x0b,0x6d,0x00,0xf8,0xfd,0x85, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x16,0xe1,0xe4,0x59,0x45,0x76,0x79,0xdf,0x5b,0x94,0x34,0xae,0x23,0xf4,0x74,0xb3,0xe8,0xd2,0xa7,0x0b,0xd6,0xb5,0xdb,0xe6,0x92,0xba,0x16,0xda,0x01,0xf1,0xfb,0x0a, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x22,0x52,0xd6,0x85,0xe8,0x31,0xb6,0xcf,0x09,0x5e,0x4f,0x05,0x35,0xee,0xaf,0x0d,0xdd,0x3b,0xfa,0x91,0xc2,0x10,0xc9,0xd9,0xdc,0x17,0x22,0x47,0x02,0xea,0xf8,0x8f, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x75,0x13,0x5a,0xbd,0x7c,0x42,0x5b,0x60,0x37,0x1a,0x47,0x7f,0x09,0xce,0x0f,0x27,0x4f,0x64,0xa8,0xc6,0xb0,0x61,0xa0,0x7b,0x5d,0x63,0xe9,0x3c,0x65,0x04,0x6c,0x53, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x2a,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x3e,0x3a,0x49,0xa2,0x3a,0x6d,0x8a,0xbe,0x95,0x46,0x1f,0x84,0x45,0x67,0x6b,0x17, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x3e,0x88,0x83,0x77,0xac,0x6c,0x71,0xac,0x9d,0xec,0x3f,0xdb,0x9b,0x56,0xc9,0xfe,0xaf,0x0c,0xfa,0xca,0x9f,0x82,0x7f,0xc5,0xeb,0x65,0xfc,0x3e,0xac,0x81,0x12,0x10, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x30,0xbb,0xb7,0x94,0xdb,0x58,0x83,0x63,0xb4,0x06,0x79,0xf6,0xc1,0x82,0xa5,0x0d,0x3c,0xe9,0x67,0x9a,0xcd,0xd3,0xff,0xbe,0x36,0xd7,0x81,0x3d,0xac,0xbd,0xc8,0x18, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x2c,0x37,0xfd,0x99,0x56,0x22,0xc4,0xfb,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc7,0xce,0xe7,0x45,0x11,0x0c,0xb4,0x5a,0xb5,0x58,0xed,0x7c,0x90,0xc1,0x5a,0x2f, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x7f,0xd9,0x95,0x62,0x2c,0x4f,0xb7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5d,0x88,0x3f,0xfa,0xb5,0xb3,0x26,0x52,0xcc,0xdc,0xaa,0x29,0x0f,0xcc,0xb9,0x7d, - 0x30,0x43,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x1f,0x4c,0xd5,0x3b,0xa7,0x60,0x8f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9e,0x5c,0xf1,0x43,0xe2,0x53,0x96,0x26,0x19,0x0a,0x3a,0xb0,0x9c,0xce,0x47, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x56,0x22,0xc4,0xfb,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x92,0x8a,0x8f,0x1c,0x7a,0xc7,0xbe,0xc1,0x80,0x8b,0x9f,0x61,0xc0,0x1e,0xc3,0x27, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x44,0x10,0x41,0x04,0x10,0x41,0x04,0x10,0x41,0x04,0x10,0x41,0x04,0x10,0x41,0x03,0xb8,0x78,0x53,0xfd,0x3b,0x7d,0x3f,0x8e,0x17,0x51,0x25,0xb4,0x38,0x2f,0x25,0xed, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x27,0x39,0xce,0x73,0x9c,0xe7,0x39,0xce,0x73,0x9c,0xe7,0x39,0xce,0x73,0x9c,0xe7,0x05,0x56,0x02,0x98,0xd1,0xf2,0xf0,0x8d,0xc4,0x19,0xac,0x27,0x3a,0x5b,0x54,0xd9, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x48,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x31,0xc8,0x3a,0xe8,0x2e,0xbe,0x08,0x98,0x77,0x6b,0x4c,0x69,0xd1,0x1f,0x88,0xde, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x64,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x06,0xdd,0x3a,0x19,0xb8,0xd5,0xfb,0x87,0x52,0x35,0x96,0x3c,0x59,0x3b,0xd2,0xd3, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x6a,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x3e,0x3a,0x49,0xa2,0x3a,0x6d,0x8a,0xbe,0x95,0x46,0x1f,0x84,0x45,0x67,0x6b,0x15, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x2a,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x3e,0x3a,0x49,0xa2,0x3a,0x6d,0x8a,0xbe,0x95,0x46,0x1f,0x84,0x45,0x67,0x6b,0x17, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, - 0x30,0x44,0x02,0x20,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x02,0x20,0x18,0x5d,0xdb,0xca,0x6d,0xac,0x41,0xb1,0xda,0x03,0x3c,0xfb,0x60,0xc1,0x52,0x86,0x9e,0x74,0xb3,0xcd,0x66,0xe9,0xff,0xdf,0x1b,0x6b,0xc0,0x9e,0xd6,0x5e,0xe4,0x0c, - 0x30,0x44,0x02,0x20,0x32,0xb0,0xd1,0x0d,0x8d,0x0e,0x04,0xbc,0x8d,0x4d,0x06,0x4d,0x27,0x06,0x99,0xe8,0x7c,0xff,0xc9,0xb4,0x9c,0x5c,0x20,0x73,0x0e,0x1c,0x26,0xf6,0x10,0x5d,0xdc,0xda,0x02,0x20,0x29,0xed,0x3d,0x67,0xb3,0xd5,0x05,0xbe,0x95,0x58,0x0d,0x77,0xd5,0xb7,0x92,0xb4,0x36,0x88,0x11,0x79,0xb2,0xb6,0xb2,0xe0,0x4c,0x5f,0xe5,0x92,0xd3,0x8d,0x82,0xd9, - 0x30,0x44,0x02,0x20,0x32,0xb0,0xd1,0x0d,0x8d,0x0e,0x04,0xbc,0x8d,0x4d,0x06,0x4d,0x27,0x06,0x99,0xe8,0x7c,0xff,0xc9,0xb4,0x9c,0x5c,0x20,0x73,0x0e,0x1c,0x26,0xf6,0x10,0x5d,0xdc,0xda,0x02,0x20,0x29,0xed,0x3d,0x67,0xb3,0xd5,0x05,0xbe,0x95,0x58,0x0d,0x77,0xd5,0xb7,0x92,0xb4,0x36,0x88,0x11,0x79,0xb2,0xb6,0xb2,0xe0,0x4c,0x5f,0xe5,0x92,0xd3,0x8d,0x82,0xd9, - 0x30,0x44,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc0,0x02,0x20,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x32,0xf2,0x22,0xf8,0xfa,0xef,0xdb,0x53,0x3f,0x26,0x5d,0x46,0x1c,0x29,0xa4,0x73,0x73, - 0x30,0x45,0x02,0x21,0x00,0xc6,0x04,0x7f,0x94,0x41,0xed,0x7d,0x6d,0x30,0x45,0x40,0x6e,0x95,0xc0,0x7c,0xd8,0x5c,0x77,0x8e,0x4b,0x8c,0xef,0x3c,0xa7,0xab,0xac,0x09,0xb9,0x5c,0x70,0x9e,0xe5,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc0, - 0x30,0x45,0x02,0x21,0x00,0xc6,0x04,0x7f,0x94,0x41,0xed,0x7d,0x6d,0x30,0x45,0x40,0x6e,0x95,0xc0,0x7c,0xd8,0x5c,0x77,0x8e,0x4b,0x8c,0xef,0x3c,0xa7,0xab,0xac,0x09,0xb9,0x5c,0x70,0x9e,0xe5,0x02,0x20,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x48,0xc7,0x9f,0xac,0xd4,0x32,0x14,0xc0,0x11,0x12,0x3c,0x1b,0x03,0xa9,0x34,0x12,0xa5, - 0x30,0x45,0x02,0x21,0x00,0xc6,0x04,0x7f,0x94,0x41,0xed,0x7d,0x6d,0x30,0x45,0x40,0x6e,0x95,0xc0,0x7c,0xd8,0x5c,0x77,0x8e,0x4b,0x8c,0xef,0x3c,0xa7,0xab,0xac,0x09,0xb9,0x5c,0x70,0x9e,0xe5,0x02,0x20,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x65,0xe4,0x45,0xf1,0xf5,0xdf,0xb6,0xa6,0x7e,0x4c,0xba,0x8c,0x38,0x53,0x48,0xe6,0xe7, - 0x30,0x45,0x02,0x21,0x00,0xc6,0x04,0x7f,0x94,0x41,0xed,0x7d,0x6d,0x30,0x45,0x40,0x6e,0x95,0xc0,0x7c,0xd8,0x5c,0x77,0x8e,0x4b,0x8c,0xef,0x3c,0xa7,0xab,0xac,0x09,0xb9,0x5c,0x70,0x9e,0xe5,0x02,0x20,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x65,0xe4,0x45,0xf1,0xf5,0xdf,0xb6,0xa6,0x7e,0x4c,0xba,0x8c,0x38,0x53,0x48,0xe6,0xe7, - 0x30,0x45,0x02,0x21,0x00,0xc6,0x04,0x7f,0x94,0x41,0xed,0x7d,0x6d,0x30,0x45,0x40,0x6e,0x95,0xc0,0x7c,0xd8,0x5c,0x77,0x8e,0x4b,0x8c,0xef,0x3c,0xa7,0xab,0xac,0x09,0xb9,0x5c,0x70,0x9e,0xe5,0x02,0x20,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x48,0xc7,0x9f,0xac,0xd4,0x32,0x14,0xc0,0x11,0x12,0x3c,0x1b,0x03,0xa9,0x34,0x12,0xa5, - 0x30,0x45,0x02,0x21,0x00,0xc6,0x04,0x7f,0x94,0x41,0xed,0x7d,0x6d,0x30,0x45,0x40,0x6e,0x95,0xc0,0x7c,0xd8,0x5c,0x77,0x8e,0x4b,0x8c,0xef,0x3c,0xa7,0xab,0xac,0x09,0xb9,0x5c,0x70,0x9e,0xe5,0x02,0x20,0x0e,0xb1,0x0e,0x5a,0xb9,0x5f,0x2f,0x27,0x53,0x48,0xd8,0x2a,0xd2,0xe4,0xd7,0x94,0x9c,0x81,0x93,0x80,0x0d,0x8c,0x9c,0x75,0xdf,0x58,0xe3,0x43,0xf0,0xeb,0xba,0x7b, - 0x30,0x44,0x02,0x20,0x79,0xbe,0x66,0x7e,0xf9,0xdc,0xbb,0xac,0x55,0xa0,0x62,0x95,0xce,0x87,0x0b,0x07,0x02,0x9b,0xfc,0xdb,0x2d,0xce,0x28,0xd9,0x59,0xf2,0x81,0x5b,0x16,0xf8,0x17,0x98,0x02,0x20,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xe8,0xe4,0xf4,0x4c,0xe5,0x18,0x35,0x69,0x3f,0xf0,0xca,0x2e,0xf0,0x12,0x15,0xc0, - 0x30,0x44,0x02,0x20,0x79,0xbe,0x66,0x7e,0xf9,0xdc,0xbb,0xac,0x55,0xa0,0x62,0x95,0xce,0x87,0x0b,0x07,0x02,0x9b,0xfc,0xdb,0x2d,0xce,0x28,0xd9,0x59,0xf2,0x81,0x5b,0x16,0xf8,0x17,0x98,0x02,0x20,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x48,0xc7,0x9f,0xac,0xd4,0x32,0x14,0xc0,0x11,0x12,0x3c,0x1b,0x03,0xa9,0x34,0x12,0xa5, - 0x30,0x44,0x02,0x20,0x79,0xbe,0x66,0x7e,0xf9,0xdc,0xbb,0xac,0x55,0xa0,0x62,0x95,0xce,0x87,0x0b,0x07,0x02,0x9b,0xfc,0xdb,0x2d,0xce,0x28,0xd9,0x59,0xf2,0x81,0x5b,0x16,0xf8,0x17,0x98,0x02,0x20,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x65,0xe4,0x45,0xf1,0xf5,0xdf,0xb6,0xa6,0x7e,0x4c,0xba,0x8c,0x38,0x53,0x48,0xe6,0xe7, - 0x30,0x44,0x02,0x20,0x79,0xbe,0x66,0x7e,0xf9,0xdc,0xbb,0xac,0x55,0xa0,0x62,0x95,0xce,0x87,0x0b,0x07,0x02,0x9b,0xfc,0xdb,0x2d,0xce,0x28,0xd9,0x59,0xf2,0x81,0x5b,0x16,0xf8,0x17,0x98,0x02,0x20,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x65,0xe4,0x45,0xf1,0xf5,0xdf,0xb6,0xa6,0x7e,0x4c,0xba,0x8c,0x38,0x53,0x48,0xe6,0xe7, - 0x30,0x44,0x02,0x20,0x79,0xbe,0x66,0x7e,0xf9,0xdc,0xbb,0xac,0x55,0xa0,0x62,0x95,0xce,0x87,0x0b,0x07,0x02,0x9b,0xfc,0xdb,0x2d,0xce,0x28,0xd9,0x59,0xf2,0x81,0x5b,0x16,0xf8,0x17,0x98,0x02,0x20,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x48,0xc7,0x9f,0xac,0xd4,0x32,0x14,0xc0,0x11,0x12,0x3c,0x1b,0x03,0xa9,0x34,0x12,0xa5, - 0x30,0x44,0x02,0x20,0x79,0xbe,0x66,0x7e,0xf9,0xdc,0xbb,0xac,0x55,0xa0,0x62,0x95,0xce,0x87,0x0b,0x07,0x02,0x9b,0xfc,0xdb,0x2d,0xce,0x28,0xd9,0x59,0xf2,0x81,0x5b,0x16,0xf8,0x17,0x98,0x02,0x20,0x0e,0xb1,0x0e,0x5a,0xb9,0x5f,0x2f,0x27,0x53,0x48,0xd8,0x2a,0xd2,0xe4,0xd7,0x94,0x9c,0x81,0x93,0x80,0x0d,0x8c,0x9c,0x75,0xdf,0x58,0xe3,0x43,0xf0,0xeb,0xba,0x7b, - 0x30,0x45,0x02,0x21,0x00,0xbb,0x5a,0x52,0xf4,0x2f,0x9c,0x92,0x61,0xed,0x43,0x61,0xf5,0x94,0x22,0xa1,0xe3,0x00,0x36,0xe7,0xc3,0x2b,0x27,0x0c,0x88,0x07,0xa4,0x19,0xfe,0xca,0x60,0x50,0x23,0x02,0x20,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x63,0xcf,0xd6,0x6a,0x19,0x0a,0x60,0x08,0x89,0x1e,0x0d,0x81,0xd4,0x9a,0x09,0x52, - 0x30,0x44,0x02,0x20,0x44,0xa5,0xad,0x0b,0xd0,0x63,0x6d,0x9e,0x12,0xbc,0x9e,0x0a,0x6b,0xdd,0x5e,0x1b,0xba,0x77,0xf5,0x23,0x84,0x21,0x93,0xb3,0xb8,0x2e,0x44,0x8e,0x05,0xd5,0xf1,0x1e,0x02,0x20,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x63,0xcf,0xd6,0x6a,0x19,0x0a,0x60,0x08,0x89,0x1e,0x0d,0x81,0xd4,0x9a,0x09,0x52, - 0x30,0x45,0x02,0x21,0x00,0xbb,0x5a,0x52,0xf4,0x2f,0x9c,0x92,0x61,0xed,0x43,0x61,0xf5,0x94,0x22,0xa1,0xe3,0x00,0x36,0xe7,0xc3,0x2b,0x27,0x0c,0x88,0x07,0xa4,0x19,0xfe,0xca,0x60,0x50,0x23,0x02,0x20,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x63,0xcf,0xd6,0x6a,0x19,0x0a,0x60,0x08,0x89,0x1e,0x0d,0x81,0xd4,0x9a,0x09,0x52, - 0x30,0x44,0x02,0x20,0x44,0xa5,0xad,0x0b,0xd0,0x63,0x6d,0x9e,0x12,0xbc,0x9e,0x0a,0x6b,0xdd,0x5e,0x1b,0xba,0x77,0xf5,0x23,0x84,0x21,0x93,0xb3,0xb8,0x2e,0x44,0x8e,0x05,0xd5,0xf1,0x1e,0x02,0x20,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x63,0xcf,0xd6,0x6a,0x19,0x0a,0x60,0x08,0x89,0x1e,0x0d,0x81,0xd4,0x9a,0x09,0x52, - 0x30,0x45,0x02,0x21,0x00,0xf8,0x0a,0xe4,0xf9,0x6c,0xdb,0xc9,0xd8,0x53,0xf8,0x3d,0x47,0xaa,0xe2,0x25,0xbf,0x40,0x7d,0x51,0xc5,0x6b,0x77,0x76,0xcd,0x67,0xd0,0xdc,0x19,0x5d,0x99,0xa9,0xdc,0x02,0x20,0x4c,0xfc,0x1d,0x94,0x1e,0x08,0xcb,0x9a,0xce,0xad,0xde,0x0f,0x4c,0xce,0xad,0x76,0xb3,0x0d,0x33,0x2f,0xc4,0x42,0x11,0x5d,0x50,0xe6,0x73,0xe2,0x86,0x86,0xb7,0x0b, - 0x30,0x44,0x02,0x20,0x10,0x9c,0xd8,0xae,0x03,0x74,0x35,0x89,0x84,0xa8,0x24,0x9c,0x0a,0x84,0x36,0x28,0xf2,0x83,0x5f,0xfa,0xd1,0xdf,0x1a,0x9a,0x69,0xaa,0x2f,0xe7,0x23,0x55,0x54,0x5c,0x02,0x20,0x53,0x90,0xff,0x25,0x0a,0xc4,0x27,0x4e,0x1c,0xb2,0x5c,0xd6,0xca,0x64,0x91,0xf6,0xb9,0x12,0x81,0xe3,0x2f,0x5b,0x26,0x4d,0x87,0x97,0x7a,0xed,0x4a,0x94,0xe7,0x7b, - 0x30,0x45,0x02,0x21,0x00,0xd0,0x35,0xee,0x1f,0x17,0xfd,0xb0,0xb2,0x68,0x1b,0x16,0x3e,0x33,0xc3,0x59,0x93,0x26,0x59,0x99,0x0a,0xf7,0x7d,0xca,0x63,0x20,0x12,0xb3,0x0b,0x27,0xa0,0x57,0xb3,0x02,0x20,0x19,0x39,0xd9,0xf3,0xb2,0x85,0x8b,0xc1,0x3e,0x34,0x74,0xcb,0x50,0xe6,0xa8,0x2b,0xe4,0x4f,0xaa,0x71,0x94,0x0f,0x87,0x6c,0x1c,0xba,0x4c,0x3e,0x98,0x92,0x02,0xb6, - 0x30,0x44,0x02,0x20,0x4f,0x05,0x3f,0x56,0x3a,0xd3,0x4b,0x74,0xfd,0x8c,0x99,0x34,0xce,0x59,0xe7,0x9c,0x2e,0xb8,0xe6,0xec,0xa0,0xfe,0xf5,0xb3,0x23,0xca,0x67,0xd5,0xac,0x7e,0xd2,0x38,0x02,0x20,0x4d,0x4b,0x05,0xda,0xa0,0x71,0x9e,0x77,0x3d,0x86,0x17,0xdc,0xe5,0x63,0x1c,0x5f,0xd6,0xf5,0x9c,0x9b,0xdc,0x74,0x8e,0x4b,0x55,0xc9,0x70,0x04,0x0a,0xf0,0x1b,0xe5, - 0x30,0x44,0x02,0x20,0x6d,0x6a,0x4f,0x55,0x6c,0xcc,0xe1,0x54,0xe7,0xfb,0x9f,0x19,0xe7,0x6c,0x3d,0xec,0xa1,0x3d,0x59,0xcc,0x2a,0xeb,0x4e,0xca,0xd9,0x68,0xaa,0xb2,0xde,0xd4,0x59,0x65,0x02,0x20,0x53,0xb9,0xfa,0x74,0x80,0x3e,0xde,0x0f,0xc4,0x44,0x1b,0xf6,0x83,0xd5,0x6c,0x56,0x4d,0x3e,0x27,0x4e,0x09,0xcc,0xf4,0x73,0x90,0xba,0xdd,0x14,0x71,0xc0,0x5f,0xb7, - 0x30,0x44,0x02,0x21,0x00,0xaa,0xd5,0x03,0xde,0x9b,0x9f,0xd6,0x6b,0x94,0x8e,0x9a,0xcf,0x59,0x6f,0x0a,0x0e,0x65,0xe7,0x00,0xb2,0x8b,0x26,0xec,0x56,0xe6,0xe4,0x5e,0x84,0x64,0x89,0xb3,0xc4,0x02,0x1f,0x0d,0xdc,0x3a,0x2f,0x89,0xab,0xb8,0x17,0xbb,0x85,0xc0,0x62,0xce,0x02,0xf8,0x23,0xc6,0x3f,0xc2,0x6b,0x26,0x9e,0x0b,0xc9,0xb8,0x4d,0x81,0xa5,0xaa,0x12,0x3d, - 0x30,0x45,0x02,0x21,0x00,0x91,0x82,0xce,0xbd,0x3b,0xb8,0xab,0x57,0x2e,0x16,0x71,0x74,0x39,0x72,0x09,0xef,0x4b,0x1d,0x43,0x9a,0xf3,0xb2,0x00,0xcd,0xf0,0x03,0x62,0x00,0x89,0xe4,0x32,0x25,0x02,0x20,0x54,0x47,0x7c,0x98,0x2e,0xa0,0x19,0xd2,0xe1,0x00,0x04,0x97,0xfc,0x25,0xfc,0xee,0x1b,0xcc,0xae,0x55,0xf2,0xac,0x27,0x53,0x0a,0xe5,0x3b,0x29,0xc4,0xb3,0x56,0xa4, - 0x30,0x44,0x02,0x20,0x38,0x54,0xa3,0x99,0x8a,0xeb,0xdf,0x2d,0xbc,0x28,0xad,0xac,0x41,0x81,0x46,0x2c,0xca,0xc7,0x87,0x39,0x07,0xab,0x7f,0x21,0x2c,0x42,0xdb,0x0e,0x69,0xb5,0x6e,0xd8,0x02,0x20,0x3e,0xd3,0xf6,0xb8,0xa3,0x88,0xd0,0x2f,0x3e,0x4d,0xf9,0xf2,0xae,0x9c,0x1b,0xd2,0xc3,0x91,0x6a,0x68,0x64,0x60,0xdf,0xfc,0xd4,0x29,0x09,0xcd,0x7f,0x82,0x05,0x8e, - 0x30,0x45,0x02,0x21,0x00,0xe9,0x4d,0xbd,0xc3,0x87,0x95,0xfe,0x5c,0x90,0x4d,0x8f,0x16,0xd9,0x69,0xd3,0xb5,0x87,0xf0,0xa2,0x5d,0x2d,0xe9,0x0b,0x6d,0x8c,0x5c,0x53,0xff,0x88,0x7e,0x36,0x07,0x02,0x20,0x7a,0x94,0x73,0x69,0xc1,0x64,0x97,0x25,0x21,0xbb,0x8a,0xf4,0x06,0x81,0x3b,0x2d,0x9f,0x94,0xd2,0xae,0xaa,0x53,0xd4,0xc2,0x15,0xaa,0xa0,0xa2,0x57,0x8a,0x2c,0x5d, - 0x30,0x44,0x02,0x20,0x49,0xfc,0x10,0x2a,0x08,0xca,0x47,0xb6,0x0e,0x08,0x58,0xcd,0x02,0x84,0xd2,0x2c,0xdd,0xd7,0x23,0x3f,0x94,0xaa,0xff,0xbb,0x2d,0xb1,0xdd,0x2c,0xf0,0x84,0x25,0xe1,0x02,0x20,0x5b,0x16,0xfc,0xa5,0xa1,0x2c,0xdb,0x39,0x70,0x16,0x97,0xad,0x8e,0x39,0xff,0xd6,0xbd,0xec,0x00,0x24,0x29,0x8a,0xfa,0xa2,0x32,0x6a,0xea,0x09,0x20,0x0b,0x14,0xd6, - 0x30,0x44,0x02,0x20,0x41,0xef,0xa7,0xd3,0xf0,0x5a,0x00,0x10,0x67,0x5f,0xcb,0x91,0x8a,0x45,0xc6,0x93,0xda,0x4b,0x34,0x8d,0xf2,0x1a,0x59,0xd6,0xf9,0xcd,0x73,0xe0,0xd8,0x31,0xd6,0x7a,0x02,0x20,0x44,0x54,0xad,0xa6,0x93,0xe5,0xe2,0x6b,0x7b,0xd6,0x93,0x23,0x6d,0x34,0x0f,0x80,0x54,0x5c,0x83,0x45,0x77,0xb6,0xf7,0x3d,0x37,0x8c,0x7b,0xcc,0x53,0x42,0x44,0xda, - 0x30,0x45,0x02,0x21,0x00,0xb6,0x15,0x69,0x8c,0x35,0x8b,0x35,0x92,0x0d,0xd8,0x83,0xec,0xa6,0x25,0xa6,0xc5,0xf7,0x56,0x39,0x70,0xcd,0xfc,0x37,0x8f,0x8f,0xe0,0xce,0xe1,0x70,0x92,0x14,0x4c,0x02,0x20,0x25,0xf4,0x7b,0x32,0x6b,0x5b,0xe1,0xfb,0x61,0x0b,0x88,0x51,0x53,0xea,0x84,0xd4,0x1e,0xb4,0x71,0x6b,0xe6,0x6a,0x99,0x4e,0x87,0x79,0x98,0x9d,0xf1,0xc8,0x63,0xd4, - 0x30,0x45,0x02,0x21,0x00,0x87,0xcf,0x8c,0x0e,0xb8,0x2d,0x44,0xf6,0x9c,0x60,0xa2,0xff,0x54,0x57,0xd3,0xaa,0xa3,0x22,0xe7,0xec,0x61,0xae,0x5a,0xec,0xfd,0x67,0x8a,0xe1,0xc1,0x93,0x2b,0x0e,0x02,0x20,0x3a,0xdd,0x3b,0x11,0x58,0x15,0x04,0x7d,0x6e,0xb3,0x40,0xa3,0xe0,0x08,0x98,0x9e,0xaa,0x0f,0x87,0x08,0xd1,0x79,0x48,0x14,0x72,0x90,0x94,0xd0,0x8d,0x24,0x60,0xd3, - 0x30,0x44,0x02,0x20,0x62,0xf4,0x8e,0xf7,0x1a,0xce,0x27,0xbf,0x5a,0x01,0x83,0x4d,0xe1,0xf7,0xe3,0xf9,0x48,0xb9,0xdc,0xe1,0xca,0x1e,0x91,0x1d,0x5e,0x13,0xd3,0xb1,0x04,0x47,0x1d,0x82,0x02,0x20,0x5e,0xa8,0xf3,0x3f,0x0c,0x77,0x89,0x72,0xc4,0x58,0x20,0x80,0xde,0xda,0x9b,0x34,0x18,0x57,0xdd,0x64,0x51,0x4f,0x08,0x49,0xa0,0x5f,0x69,0x64,0xc2,0xe3,0x40,0x22, - 0x30,0x45,0x02,0x21,0x00,0xf6,0xb0,0xe2,0xf6,0xfe,0x02,0x0c,0xf7,0xc0,0xc2,0x01,0x37,0x43,0x43,0x44,0xed,0x7a,0xdd,0x6c,0x4b,0xe5,0x18,0x61,0xe2,0xd1,0x4c,0xbd,0xa4,0x72,0xa6,0xff,0xb4,0x02,0x20,0x64,0x16,0xc8,0xdd,0x3e,0x5c,0x52,0x82,0xb3,0x06,0xe8,0xdc,0x8f,0xf3,0x4a,0xb6,0x4c,0xc9,0x95,0x49,0x23,0x2d,0x67,0x8d,0x71,0x44,0x02,0xeb,0x6c,0xa7,0xaa,0x0f, - 0x30,0x45,0x02,0x21,0x00,0xdb,0x09,0xd8,0x46,0x0f,0x05,0xef,0xf2,0x3b,0xc7,0xe4,0x36,0xb6,0x7d,0xa5,0x63,0xfa,0x4b,0x4e,0xdb,0x58,0xac,0x24,0xce,0x20,0x1f,0xa8,0xa3,0x58,0x12,0x50,0x57,0x02,0x20,0x46,0xda,0x11,0x67,0x54,0x60,0x29,0x40,0xc8,0x99,0x9c,0x8d,0x66,0x5f,0x78,0x6c,0x50,0xf5,0x77,0x2c,0x0a,0x3c,0xdb,0xda,0x07,0x5e,0x77,0xea,0xbc,0x64,0xdf,0x16, - 0x30,0x44,0x02,0x20,0x59,0x2c,0x41,0xe1,0x65,0x17,0xf1,0x2f,0xca,0xbd,0x98,0x26,0x76,0x74,0xf9,0x74,0xb5,0x88,0xe9,0xf3,0x5d,0x35,0x40,0x6c,0x1a,0x7b,0xb2,0xed,0x1d,0x19,0xb7,0xb8,0x02,0x20,0x3e,0x65,0xa0,0x6b,0xd9,0xf8,0x3c,0xaa,0xeb,0x7b,0x00,0xf2,0x36,0x8d,0x7e,0x0d,0xec,0xe6,0xb1,0x22,0x21,0x26,0x9a,0x9b,0x5b,0x76,0x51,0x98,0xf8,0x40,0xa3,0xa1, - 0x30,0x45,0x02,0x21,0x00,0xbe,0x0d,0x70,0x88,0x7d,0x5e,0x40,0x82,0x1a,0x61,0xb6,0x80,0x47,0xde,0x4e,0xa0,0x3d,0xeb,0xfd,0xf5,0x1c,0xdf,0x4d,0x4b,0x19,0x55,0x58,0xb9,0x59,0xa0,0x32,0xb2,0x02,0x20,0x7d,0x99,0x4b,0x2d,0x8f,0x1d,0xbb,0xeb,0x13,0x53,0x4e,0xb3,0xf6,0xe5,0xdc,0xcd,0x85,0xf5,0xc4,0x13,0x3c,0x27,0xd9,0xe6,0x42,0x71,0xb1,0x82,0x6c,0xe1,0xf6,0x7d, - 0x30,0x45,0x02,0x21,0x00,0xfa,0xe9,0x2d,0xfc,0xb2,0xee,0x39,0x2d,0x27,0x0a,0xf3,0xa5,0x73,0x9f,0xaa,0x26,0xd4,0xf9,0x7b,0xfd,0x39,0xed,0x3c,0xbe,0xe4,0xd2,0x9e,0x26,0xaf,0x3b,0x20,0x6a,0x02,0x20,0x6c,0x9b,0xa3,0x7f,0x9f,0xaa,0x6a,0x1f,0xd3,0xf6,0x5f,0x23,0xb4,0xe8,0x53,0xd4,0x69,0x2a,0x72,0x74,0x24,0x0a,0x12,0xdb,0x7b,0xa3,0x88,0x48,0x30,0x63,0x0d,0x16, - 0x30,0x44,0x02,0x20,0x17,0x6a,0x25,0x57,0x56,0x6f,0xfa,0x51,0x8b,0x11,0x22,0x66,0x94,0xeb,0x98,0x02,0xed,0x20,0x98,0xbf,0xe2,0x78,0xe5,0x57,0x0f,0xe1,0xd5,0xd7,0xaf,0x18,0xa9,0x43,0x02,0x20,0x12,0x91,0xdf,0x6a,0x0e,0xd5,0xfc,0x0d,0x15,0x09,0x8e,0x70,0xbc,0xf1,0x3a,0x00,0x92,0x84,0xdf,0xd0,0x68,0x9d,0x3b,0xb4,0xbe,0x6c,0xee,0xb9,0xbe,0x14,0x87,0xc4, - 0x30,0x44,0x02,0x20,0x60,0xbe,0x20,0xc3,0xdb,0xc1,0x62,0xdd,0x34,0xd2,0x67,0x80,0x62,0x1c,0x10,0x4b,0xbe,0x5d,0xac,0xe6,0x30,0x17,0x1b,0x2d,0xae,0xf0,0xd8,0x26,0x40,0x9e,0xe5,0xc2,0x02,0x20,0x42,0x7f,0x7e,0x4d,0x88,0x9d,0x54,0x91,0x70,0xbd,0xa6,0xa9,0x40,0x9f,0xb1,0xcb,0x8b,0x0e,0x76,0x3d,0x13,0xee,0xa7,0xbd,0x97,0xf6,0x4c,0xf4,0x1d,0xc6,0xe4,0x97, - 0x30,0x45,0x02,0x21,0x00,0xed,0xf0,0x3c,0xf6,0x3f,0x65,0x88,0x83,0x28,0x9a,0x1a,0x59,0x3d,0x10,0x07,0x89,0x5b,0x9f,0x23,0x6d,0x27,0xc9,0xc1,0xf1,0x31,0x30,0x89,0xaa,0xed,0x6b,0x16,0xae,0x02,0x20,0x1a,0x4d,0xd6,0xfc,0x08,0x14,0xdc,0x52,0x3d,0x1f,0xef,0xa8,0x1c,0x64,0xfb,0xf5,0xe6,0x18,0xe6,0x51,0xe7,0x09,0x6f,0xcc,0xad,0xbb,0x94,0xcd,0x48,0xe5,0xe0,0xcd}; - -static const wycheproof_ecdsa_testvector testvectors[SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS] = { - /* tcId: 1. Signature malleability */ - {0, 0, 6, 0, 72, 0 }, - /* tcId: 2. valid */ - {0, 0, 6, 72, 71, 1 }, - /* tcId: 3. length of sequence [r, s] uses long form encoding */ - {0, 0, 6, 143, 72, 0 }, - /* tcId: 4. length of sequence [r, s] contains a leading 0 */ - {0, 0, 6, 215, 73, 0 }, - /* tcId: 5. length of sequence [r, s] uses 70 instead of 69 */ - {0, 0, 6, 288, 71, 0 }, - /* tcId: 6. length of sequence [r, s] uses 68 instead of 69 */ - {0, 0, 6, 359, 71, 0 }, - /* tcId: 7. uint32 overflow in length of sequence [r, s] */ - {0, 0, 6, 430, 76, 0 }, - /* tcId: 8. uint64 overflow in length of sequence [r, s] */ - {0, 0, 6, 506, 80, 0 }, - /* tcId: 9. length of sequence [r, s] = 2**31 - 1 */ - {0, 0, 6, 586, 75, 0 }, - /* tcId: 10. length of sequence [r, s] = 2**31 */ - {0, 0, 6, 661, 75, 0 }, - /* tcId: 11. length of sequence [r, s] = 2**32 - 1 */ - {0, 0, 6, 736, 75, 0 }, - /* tcId: 12. length of sequence [r, s] = 2**40 - 1 */ - {0, 0, 6, 811, 76, 0 }, - /* tcId: 13. length of sequence [r, s] = 2**64 - 1 */ - {0, 0, 6, 887, 79, 0 }, - /* tcId: 14. incorrect length of sequence [r, s] */ - {0, 0, 6, 966, 71, 0 }, - /* tcId: 15. replaced sequence [r, s] by an indefinite length tag without termination */ - {0, 0, 6, 1037, 71, 0 }, - /* tcId: 16. removing sequence [r, s] */ - {0, 0, 6, 1108, 0, 0 }, - /* tcId: 17. lonely sequence tag */ - {0, 0, 6, 1108, 1, 0 }, - /* tcId: 18. appending 0's to sequence [r, s] */ - {0, 0, 6, 1109, 73, 0 }, - /* tcId: 19. prepending 0's to sequence [r, s] */ - {0, 0, 6, 1182, 73, 0 }, - /* tcId: 20. appending unused 0's to sequence [r, s] */ - {0, 0, 6, 1255, 73, 0 }, - /* tcId: 21. appending null value to sequence [r, s] */ - {0, 0, 6, 1328, 73, 0 }, - /* tcId: 22. prepending garbage to sequence [r, s] */ - {0, 0, 6, 1401, 76, 0 }, - /* tcId: 23. prepending garbage to sequence [r, s] */ - {0, 0, 6, 1477, 75, 0 }, - /* tcId: 24. appending garbage to sequence [r, s] */ - {0, 0, 6, 1552, 79, 0 }, - /* tcId: 25. including undefined tags */ - {0, 0, 6, 1631, 79, 0 }, - /* tcId: 26. including undefined tags */ - {0, 0, 6, 1710, 79, 0 }, - /* tcId: 27. including undefined tags */ - {0, 0, 6, 1789, 79, 0 }, - /* tcId: 28. truncated length of sequence [r, s] */ - {0, 0, 6, 1868, 2, 0 }, - /* tcId: 29. including undefined tags to sequence [r, s] */ - {0, 0, 6, 1870, 77, 0 }, - /* tcId: 30. using composition with indefinite length for sequence [r, s] */ - {0, 0, 6, 1947, 75, 0 }, - /* tcId: 31. using composition with wrong tag for sequence [r, s] */ - {0, 0, 6, 2022, 75, 0 }, - /* tcId: 32. Replacing sequence [r, s] with NULL */ - {0, 0, 6, 2097, 2, 0 }, - /* tcId: 33. changing tag value of sequence [r, s] */ - {0, 0, 6, 2099, 71, 0 }, - /* tcId: 34. changing tag value of sequence [r, s] */ - {0, 0, 6, 2170, 71, 0 }, - /* tcId: 35. changing tag value of sequence [r, s] */ - {0, 0, 6, 2241, 71, 0 }, - /* tcId: 36. changing tag value of sequence [r, s] */ - {0, 0, 6, 2312, 71, 0 }, - /* tcId: 37. changing tag value of sequence [r, s] */ - {0, 0, 6, 2383, 71, 0 }, - /* tcId: 38. dropping value of sequence [r, s] */ - {0, 0, 6, 2454, 2, 0 }, - /* tcId: 39. using composition for sequence [r, s] */ - {0, 0, 6, 2456, 75, 0 }, - /* tcId: 40. truncated sequence [r, s] */ - {0, 0, 6, 2531, 70, 0 }, - /* tcId: 41. truncated sequence [r, s] */ - {0, 0, 6, 2601, 70, 0 }, - /* tcId: 42. sequence [r, s] of size 4166 to check for overflows */ - {0, 0, 6, 2671, 4170, 0 }, - /* tcId: 43. indefinite length */ - {0, 0, 6, 6841, 73, 0 }, - /* tcId: 44. indefinite length with truncated delimiter */ - {0, 0, 6, 6914, 72, 0 }, - /* tcId: 45. indefinite length with additional element */ - {0, 0, 6, 6986, 75, 0 }, - /* tcId: 46. indefinite length with truncated element */ - {0, 0, 6, 7061, 77, 0 }, - /* tcId: 47. indefinite length with garbage */ - {0, 0, 6, 7138, 77, 0 }, - /* tcId: 48. indefinite length with nonempty EOC */ - {0, 0, 6, 7215, 75, 0 }, - /* tcId: 49. prepend empty sequence */ - {0, 0, 6, 7290, 73, 0 }, - /* tcId: 50. append empty sequence */ - {0, 0, 6, 7363, 73, 0 }, - /* tcId: 51. append zero */ - {0, 0, 6, 7436, 74, 0 }, - /* tcId: 52. append garbage with high tag number */ - {0, 0, 6, 7510, 74, 0 }, - /* tcId: 53. append null with explicit tag */ - {0, 0, 6, 7584, 75, 0 }, - /* tcId: 54. append null with implicit tag */ - {0, 0, 6, 7659, 73, 0 }, - /* tcId: 55. sequence of sequence */ - {0, 0, 6, 7732, 73, 0 }, - /* tcId: 56. truncated sequence: removed last 1 elements */ - {0, 0, 6, 7805, 37, 0 }, - /* tcId: 57. repeating element in sequence */ - {0, 0, 6, 7842, 105, 0 }, - /* tcId: 58. flipped bit 0 in r */ - {0, 0, 6, 7947, 69, 0 }, - /* tcId: 59. flipped bit 32 in r */ - {0, 0, 6, 8016, 69, 0 }, - /* tcId: 60. flipped bit 48 in r */ - {0, 0, 6, 8085, 69, 0 }, - /* tcId: 61. flipped bit 64 in r */ - {0, 0, 6, 8154, 69, 0 }, - /* tcId: 62. length of r uses long form encoding */ - {0, 0, 6, 8223, 72, 0 }, - /* tcId: 63. length of r contains a leading 0 */ - {0, 0, 6, 8295, 73, 0 }, - /* tcId: 64. length of r uses 34 instead of 33 */ - {0, 0, 6, 8368, 71, 0 }, - /* tcId: 65. length of r uses 32 instead of 33 */ - {0, 0, 6, 8439, 71, 0 }, - /* tcId: 66. uint32 overflow in length of r */ - {0, 0, 6, 8510, 76, 0 }, - /* tcId: 67. uint64 overflow in length of r */ - {0, 0, 6, 8586, 80, 0 }, - /* tcId: 68. length of r = 2**31 - 1 */ - {0, 0, 6, 8666, 75, 0 }, - /* tcId: 69. length of r = 2**31 */ - {0, 0, 6, 8741, 75, 0 }, - /* tcId: 70. length of r = 2**32 - 1 */ - {0, 0, 6, 8816, 75, 0 }, - /* tcId: 71. length of r = 2**40 - 1 */ - {0, 0, 6, 8891, 76, 0 }, - /* tcId: 72. length of r = 2**64 - 1 */ - {0, 0, 6, 8967, 79, 0 }, - /* tcId: 73. incorrect length of r */ - {0, 0, 6, 9046, 71, 0 }, - /* tcId: 74. replaced r by an indefinite length tag without termination */ - {0, 0, 6, 9117, 71, 0 }, - /* tcId: 75. removing r */ - {0, 0, 6, 9188, 36, 0 }, - /* tcId: 76. lonely integer tag */ - {0, 0, 6, 9224, 37, 0 }, - /* tcId: 77. lonely integer tag */ - {0, 0, 6, 9261, 38, 0 }, - /* tcId: 78. appending 0's to r */ - {0, 0, 6, 9299, 73, 0 }, - /* tcId: 79. prepending 0's to r */ - {0, 0, 6, 9372, 73, 0 }, - /* tcId: 80. appending unused 0's to r */ - {0, 0, 6, 9445, 73, 0 }, - /* tcId: 81. appending null value to r */ - {0, 0, 6, 9518, 73, 0 }, - /* tcId: 82. prepending garbage to r */ - {0, 0, 6, 9591, 76, 0 }, - /* tcId: 83. prepending garbage to r */ - {0, 0, 6, 9667, 75, 0 }, - /* tcId: 84. appending garbage to r */ - {0, 0, 6, 9742, 79, 0 }, - /* tcId: 85. truncated length of r */ - {0, 0, 6, 9821, 38, 0 }, - /* tcId: 86. including undefined tags to r */ - {0, 0, 6, 9859, 77, 0 }, - /* tcId: 87. using composition with indefinite length for r */ - {0, 0, 6, 9936, 75, 0 }, - /* tcId: 88. using composition with wrong tag for r */ - {0, 0, 6, 10011, 75, 0 }, - /* tcId: 89. Replacing r with NULL */ - {0, 0, 6, 10086, 38, 0 }, - /* tcId: 90. changing tag value of r */ - {0, 0, 6, 10124, 71, 0 }, - /* tcId: 91. changing tag value of r */ - {0, 0, 6, 10195, 71, 0 }, - /* tcId: 92. changing tag value of r */ - {0, 0, 6, 10266, 71, 0 }, - /* tcId: 93. changing tag value of r */ - {0, 0, 6, 10337, 71, 0 }, - /* tcId: 94. changing tag value of r */ - {0, 0, 6, 10408, 71, 0 }, - /* tcId: 95. dropping value of r */ - {0, 0, 6, 10479, 38, 0 }, - /* tcId: 96. using composition for r */ - {0, 0, 6, 10517, 75, 0 }, - /* tcId: 97. modifying first byte of r */ - {0, 0, 6, 10592, 71, 0 }, - /* tcId: 98. modifying last byte of r */ - {0, 0, 6, 10663, 71, 0 }, - /* tcId: 99. truncated r */ - {0, 0, 6, 10734, 70, 0 }, - /* tcId: 100. truncated r */ - {0, 0, 6, 10804, 70, 0 }, - /* tcId: 101. r of size 4130 to check for overflows */ - {0, 0, 6, 10874, 4172, 0 }, - /* tcId: 102. leading ff in r */ - {0, 0, 6, 15046, 72, 0 }, - /* tcId: 103. replaced r by infinity */ - {0, 0, 6, 15118, 39, 0 }, - /* tcId: 104. replacing r with zero */ - {0, 0, 6, 15157, 39, 0 }, - /* tcId: 105. flipped bit 0 in s */ - {0, 0, 6, 15196, 69, 0 }, - /* tcId: 106. flipped bit 32 in s */ - {0, 0, 6, 15265, 69, 0 }, - /* tcId: 107. flipped bit 48 in s */ - {0, 0, 6, 15334, 69, 0 }, - /* tcId: 108. flipped bit 64 in s */ - {0, 0, 6, 15403, 69, 0 }, - /* tcId: 109. length of s uses long form encoding */ - {0, 0, 6, 15472, 72, 0 }, - /* tcId: 110. length of s contains a leading 0 */ - {0, 0, 6, 15544, 73, 0 }, - /* tcId: 111. length of s uses 33 instead of 32 */ - {0, 0, 6, 15617, 71, 0 }, - /* tcId: 112. length of s uses 31 instead of 32 */ - {0, 0, 6, 15688, 71, 0 }, - /* tcId: 113. uint32 overflow in length of s */ - {0, 0, 6, 15759, 76, 0 }, - /* tcId: 114. uint64 overflow in length of s */ - {0, 0, 6, 15835, 80, 0 }, - /* tcId: 115. length of s = 2**31 - 1 */ - {0, 0, 6, 15915, 75, 0 }, - /* tcId: 116. length of s = 2**31 */ - {0, 0, 6, 15990, 75, 0 }, - /* tcId: 117. length of s = 2**32 - 1 */ - {0, 0, 6, 16065, 75, 0 }, - /* tcId: 118. length of s = 2**40 - 1 */ - {0, 0, 6, 16140, 76, 0 }, - /* tcId: 119. length of s = 2**64 - 1 */ - {0, 0, 6, 16216, 79, 0 }, - /* tcId: 120. incorrect length of s */ - {0, 0, 6, 16295, 71, 0 }, - /* tcId: 121. replaced s by an indefinite length tag without termination */ - {0, 0, 6, 16366, 71, 0 }, - /* tcId: 122. appending 0's to s */ - {0, 0, 6, 16437, 73, 0 }, - /* tcId: 123. prepending 0's to s */ - {0, 0, 6, 16510, 73, 0 }, - /* tcId: 124. appending null value to s */ - {0, 0, 6, 16583, 73, 0 }, - /* tcId: 125. prepending garbage to s */ - {0, 0, 6, 16656, 76, 0 }, - /* tcId: 126. prepending garbage to s */ - {0, 0, 6, 16732, 75, 0 }, - /* tcId: 127. appending garbage to s */ - {0, 0, 6, 16807, 79, 0 }, - /* tcId: 128. truncated length of s */ - {0, 0, 6, 16886, 39, 0 }, - /* tcId: 129. including undefined tags to s */ - {0, 0, 6, 16925, 77, 0 }, - /* tcId: 130. using composition with indefinite length for s */ - {0, 0, 6, 17002, 75, 0 }, - /* tcId: 131. using composition with wrong tag for s */ - {0, 0, 6, 17077, 75, 0 }, - /* tcId: 132. Replacing s with NULL */ - {0, 0, 6, 17152, 39, 0 }, - /* tcId: 133. changing tag value of s */ - {0, 0, 6, 17191, 71, 0 }, - /* tcId: 134. changing tag value of s */ - {0, 0, 6, 17262, 71, 0 }, - /* tcId: 135. changing tag value of s */ - {0, 0, 6, 17333, 71, 0 }, - /* tcId: 136. changing tag value of s */ - {0, 0, 6, 17404, 71, 0 }, - /* tcId: 137. changing tag value of s */ - {0, 0, 6, 17475, 71, 0 }, - /* tcId: 138. dropping value of s */ - {0, 0, 6, 17546, 39, 0 }, - /* tcId: 139. using composition for s */ - {0, 0, 6, 17585, 75, 0 }, - /* tcId: 140. modifying first byte of s */ - {0, 0, 6, 17660, 71, 0 }, - /* tcId: 141. modifying last byte of s */ - {0, 0, 6, 17731, 71, 0 }, - /* tcId: 142. truncated s */ - {0, 0, 6, 17802, 70, 0 }, - /* tcId: 143. truncated s */ - {0, 0, 6, 17872, 70, 0 }, - /* tcId: 144. s of size 4129 to check for overflows */ - {0, 0, 6, 17942, 4172, 0 }, - /* tcId: 145. leading ff in s */ - {0, 0, 6, 22114, 72, 0 }, - /* tcId: 146. replaced s by infinity */ - {0, 0, 6, 22186, 40, 0 }, - /* tcId: 147. replacing s with zero */ - {0, 0, 6, 22226, 40, 0 }, - /* tcId: 148. replaced r by r + n */ - {0, 0, 6, 22266, 71, 0 }, - /* tcId: 149. replaced r by r - n */ - {0, 0, 6, 22337, 70, 0 }, - /* tcId: 150. replaced r by r + 256 * n */ - {0, 0, 6, 22407, 72, 0 }, - /* tcId: 151. replaced r by -r */ - {0, 0, 6, 22479, 71, 0 }, - /* tcId: 152. replaced r by n - r */ - {0, 0, 6, 22550, 70, 0 }, - /* tcId: 153. replaced r by -n - r */ - {0, 0, 6, 22620, 71, 0 }, - /* tcId: 154. replaced r by r + 2**256 */ - {0, 0, 6, 22691, 71, 0 }, - /* tcId: 155. replaced r by r + 2**320 */ - {0, 0, 6, 22762, 79, 0 }, - /* tcId: 156. replaced s by s + n */ - {0, 0, 6, 22841, 71, 0 }, - /* tcId: 157. replaced s by s - n */ - {0, 0, 6, 22912, 71, 0 }, - /* tcId: 158. replaced s by s + 256 * n */ - {0, 0, 6, 22983, 72, 0 }, - /* tcId: 159. replaced s by -s */ - {0, 0, 6, 23055, 70, 0 }, - /* tcId: 160. replaced s by -n - s */ - {0, 0, 6, 23125, 71, 0 }, - /* tcId: 161. replaced s by s + 2**256 */ - {0, 0, 6, 23196, 71, 0 }, - /* tcId: 162. replaced s by s - 2**256 */ - {0, 0, 6, 23267, 71, 0 }, - /* tcId: 163. replaced s by s + 2**320 */ - {0, 0, 6, 23338, 79, 0 }, - /* tcId: 164. Signature with special case values r=0 and s=0 */ - {0, 0, 6, 23417, 8, 0 }, - /* tcId: 165. Signature with special case values r=0 and s=1 */ - {0, 0, 6, 23425, 8, 0 }, - /* tcId: 166. Signature with special case values r=0 and s=-1 */ - {0, 0, 6, 23433, 8, 0 }, - /* tcId: 167. Signature with special case values r=0 and s=n */ - {0, 0, 6, 23441, 40, 0 }, - /* tcId: 168. Signature with special case values r=0 and s=n - 1 */ - {0, 0, 6, 23481, 40, 0 }, - /* tcId: 169. Signature with special case values r=0 and s=n + 1 */ - {0, 0, 6, 23521, 40, 0 }, - /* tcId: 170. Signature with special case values r=0 and s=p */ - {0, 0, 6, 23561, 40, 0 }, - /* tcId: 171. Signature with special case values r=0 and s=p + 1 */ - {0, 0, 6, 23601, 40, 0 }, - /* tcId: 172. Signature with special case values r=1 and s=0 */ - {0, 0, 6, 23641, 8, 0 }, - /* tcId: 173. Signature with special case values r=1 and s=1 */ - {0, 0, 6, 23649, 8, 0 }, - /* tcId: 174. Signature with special case values r=1 and s=-1 */ - {0, 0, 6, 23657, 8, 0 }, - /* tcId: 175. Signature with special case values r=1 and s=n */ - {0, 0, 6, 23665, 40, 0 }, - /* tcId: 176. Signature with special case values r=1 and s=n - 1 */ - {0, 0, 6, 23705, 40, 0 }, - /* tcId: 177. Signature with special case values r=1 and s=n + 1 */ - {0, 0, 6, 23745, 40, 0 }, - /* tcId: 178. Signature with special case values r=1 and s=p */ - {0, 0, 6, 23785, 40, 0 }, - /* tcId: 179. Signature with special case values r=1 and s=p + 1 */ - {0, 0, 6, 23825, 40, 0 }, - /* tcId: 180. Signature with special case values r=-1 and s=0 */ - {0, 0, 6, 23865, 8, 0 }, - /* tcId: 181. Signature with special case values r=-1 and s=1 */ - {0, 0, 6, 23873, 8, 0 }, - /* tcId: 182. Signature with special case values r=-1 and s=-1 */ - {0, 0, 6, 23881, 8, 0 }, - /* tcId: 183. Signature with special case values r=-1 and s=n */ - {0, 0, 6, 23889, 40, 0 }, - /* tcId: 184. Signature with special case values r=-1 and s=n - 1 */ - {0, 0, 6, 23929, 40, 0 }, - /* tcId: 185. Signature with special case values r=-1 and s=n + 1 */ - {0, 0, 6, 23969, 40, 0 }, - /* tcId: 186. Signature with special case values r=-1 and s=p */ - {0, 0, 6, 24009, 40, 0 }, - /* tcId: 187. Signature with special case values r=-1 and s=p + 1 */ - {0, 0, 6, 24049, 40, 0 }, - /* tcId: 188. Signature with special case values r=n and s=0 */ - {0, 0, 6, 24089, 40, 0 }, - /* tcId: 189. Signature with special case values r=n and s=1 */ - {0, 0, 6, 24129, 40, 0 }, - /* tcId: 190. Signature with special case values r=n and s=-1 */ - {0, 0, 6, 24169, 40, 0 }, - /* tcId: 191. Signature with special case values r=n and s=n */ - {0, 0, 6, 24209, 72, 0 }, - /* tcId: 192. Signature with special case values r=n and s=n - 1 */ - {0, 0, 6, 24281, 72, 0 }, - /* tcId: 193. Signature with special case values r=n and s=n + 1 */ - {0, 0, 6, 24353, 72, 0 }, - /* tcId: 194. Signature with special case values r=n and s=p */ - {0, 0, 6, 24425, 72, 0 }, - /* tcId: 195. Signature with special case values r=n and s=p + 1 */ - {0, 0, 6, 24497, 72, 0 }, - /* tcId: 196. Signature with special case values r=n - 1 and s=0 */ - {0, 0, 6, 24569, 40, 0 }, - /* tcId: 197. Signature with special case values r=n - 1 and s=1 */ - {0, 0, 6, 24609, 40, 0 }, - /* tcId: 198. Signature with special case values r=n - 1 and s=-1 */ - {0, 0, 6, 24649, 40, 0 }, - /* tcId: 199. Signature with special case values r=n - 1 and s=n */ - {0, 0, 6, 24689, 72, 0 }, - /* tcId: 200. Signature with special case values r=n - 1 and s=n - 1 */ - {0, 0, 6, 24761, 72, 0 }, - /* tcId: 201. Signature with special case values r=n - 1 and s=n + 1 */ - {0, 0, 6, 24833, 72, 0 }, - /* tcId: 202. Signature with special case values r=n - 1 and s=p */ - {0, 0, 6, 24905, 72, 0 }, - /* tcId: 203. Signature with special case values r=n - 1 and s=p + 1 */ - {0, 0, 6, 24977, 72, 0 }, - /* tcId: 204. Signature with special case values r=n + 1 and s=0 */ - {0, 0, 6, 25049, 40, 0 }, - /* tcId: 205. Signature with special case values r=n + 1 and s=1 */ - {0, 0, 6, 25089, 40, 0 }, - /* tcId: 206. Signature with special case values r=n + 1 and s=-1 */ - {0, 0, 6, 25129, 40, 0 }, - /* tcId: 207. Signature with special case values r=n + 1 and s=n */ - {0, 0, 6, 25169, 72, 0 }, - /* tcId: 208. Signature with special case values r=n + 1 and s=n - 1 */ - {0, 0, 6, 25241, 72, 0 }, - /* tcId: 209. Signature with special case values r=n + 1 and s=n + 1 */ - {0, 0, 6, 25313, 72, 0 }, - /* tcId: 210. Signature with special case values r=n + 1 and s=p */ - {0, 0, 6, 25385, 72, 0 }, - /* tcId: 211. Signature with special case values r=n + 1 and s=p + 1 */ - {0, 0, 6, 25457, 72, 0 }, - /* tcId: 212. Signature with special case values r=p and s=0 */ - {0, 0, 6, 25529, 40, 0 }, - /* tcId: 213. Signature with special case values r=p and s=1 */ - {0, 0, 6, 25569, 40, 0 }, - /* tcId: 214. Signature with special case values r=p and s=-1 */ - {0, 0, 6, 25609, 40, 0 }, - /* tcId: 215. Signature with special case values r=p and s=n */ - {0, 0, 6, 25649, 72, 0 }, - /* tcId: 216. Signature with special case values r=p and s=n - 1 */ - {0, 0, 6, 25721, 72, 0 }, - /* tcId: 217. Signature with special case values r=p and s=n + 1 */ - {0, 0, 6, 25793, 72, 0 }, - /* tcId: 218. Signature with special case values r=p and s=p */ - {0, 0, 6, 25865, 72, 0 }, - /* tcId: 219. Signature with special case values r=p and s=p + 1 */ - {0, 0, 6, 25937, 72, 0 }, - /* tcId: 220. Signature with special case values r=p + 1 and s=0 */ - {0, 0, 6, 26009, 40, 0 }, - /* tcId: 221. Signature with special case values r=p + 1 and s=1 */ - {0, 0, 6, 26049, 40, 0 }, - /* tcId: 222. Signature with special case values r=p + 1 and s=-1 */ - {0, 0, 6, 26089, 40, 0 }, - /* tcId: 223. Signature with special case values r=p + 1 and s=n */ - {0, 0, 6, 26129, 72, 0 }, - /* tcId: 224. Signature with special case values r=p + 1 and s=n - 1 */ - {0, 0, 6, 26201, 72, 0 }, - /* tcId: 225. Signature with special case values r=p + 1 and s=n + 1 */ - {0, 0, 6, 26273, 72, 0 }, - /* tcId: 226. Signature with special case values r=p + 1 and s=p */ - {0, 0, 6, 26345, 72, 0 }, - /* tcId: 227. Signature with special case values r=p + 1 and s=p + 1 */ - {0, 0, 6, 26417, 72, 0 }, - /* tcId: 228. Signature encoding contains incorrect types: r=0, s=0.25 */ - {0, 0, 6, 26489, 10, 0 }, - /* tcId: 229. Signature encoding contains incorrect types: r=0, s=nan */ - {0, 0, 6, 26499, 8, 0 }, - /* tcId: 230. Signature encoding contains incorrect types: r=0, s=True */ - {0, 0, 6, 26507, 8, 0 }, - /* tcId: 231. Signature encoding contains incorrect types: r=0, s=False */ - {0, 0, 6, 26515, 8, 0 }, - /* tcId: 232. Signature encoding contains incorrect types: r=0, s=Null */ - {0, 0, 6, 26523, 7, 0 }, - /* tcId: 233. Signature encoding contains incorrect types: r=0, s=empyt UTF-8 string */ - {0, 0, 6, 26530, 7, 0 }, - /* tcId: 234. Signature encoding contains incorrect types: r=0, s="0" */ - {0, 0, 6, 26537, 8, 0 }, - /* tcId: 235. Signature encoding contains incorrect types: r=0, s=empty list */ - {0, 0, 6, 26545, 7, 0 }, - /* tcId: 236. Signature encoding contains incorrect types: r=0, s=list containing 0 */ - {0, 0, 6, 26552, 10, 0 }, - /* tcId: 237. Signature encoding contains incorrect types: r=1, s=0.25 */ - {0, 0, 6, 26562, 10, 0 }, - /* tcId: 238. Signature encoding contains incorrect types: r=1, s=nan */ - {0, 0, 6, 26572, 8, 0 }, - /* tcId: 239. Signature encoding contains incorrect types: r=1, s=True */ - {0, 0, 6, 26580, 8, 0 }, - /* tcId: 240. Signature encoding contains incorrect types: r=1, s=False */ - {0, 0, 6, 26588, 8, 0 }, - /* tcId: 241. Signature encoding contains incorrect types: r=1, s=Null */ - {0, 0, 6, 26596, 7, 0 }, - /* tcId: 242. Signature encoding contains incorrect types: r=1, s=empyt UTF-8 string */ - {0, 0, 6, 26603, 7, 0 }, - /* tcId: 243. Signature encoding contains incorrect types: r=1, s="0" */ - {0, 0, 6, 26610, 8, 0 }, - /* tcId: 244. Signature encoding contains incorrect types: r=1, s=empty list */ - {0, 0, 6, 26618, 7, 0 }, - /* tcId: 245. Signature encoding contains incorrect types: r=1, s=list containing 0 */ - {0, 0, 6, 26625, 10, 0 }, - /* tcId: 246. Signature encoding contains incorrect types: r=-1, s=0.25 */ - {0, 0, 6, 26635, 10, 0 }, - /* tcId: 247. Signature encoding contains incorrect types: r=-1, s=nan */ - {0, 0, 6, 26645, 8, 0 }, - /* tcId: 248. Signature encoding contains incorrect types: r=-1, s=True */ - {0, 0, 6, 26653, 8, 0 }, - /* tcId: 249. Signature encoding contains incorrect types: r=-1, s=False */ - {0, 0, 6, 26661, 8, 0 }, - /* tcId: 250. Signature encoding contains incorrect types: r=-1, s=Null */ - {0, 0, 6, 26669, 7, 0 }, - /* tcId: 251. Signature encoding contains incorrect types: r=-1, s=empyt UTF-8 string */ - {0, 0, 6, 26676, 7, 0 }, - /* tcId: 252. Signature encoding contains incorrect types: r=-1, s="0" */ - {0, 0, 6, 26683, 8, 0 }, - /* tcId: 253. Signature encoding contains incorrect types: r=-1, s=empty list */ - {0, 0, 6, 26691, 7, 0 }, - /* tcId: 254. Signature encoding contains incorrect types: r=-1, s=list containing 0 */ - {0, 0, 6, 26698, 10, 0 }, - /* tcId: 255. Signature encoding contains incorrect types: r=n, s=0.25 */ - {0, 0, 6, 26708, 42, 0 }, - /* tcId: 256. Signature encoding contains incorrect types: r=n, s=nan */ - {0, 0, 6, 26750, 40, 0 }, - /* tcId: 257. Signature encoding contains incorrect types: r=n, s=True */ - {0, 0, 6, 26790, 40, 0 }, - /* tcId: 258. Signature encoding contains incorrect types: r=n, s=False */ - {0, 0, 6, 26830, 40, 0 }, - /* tcId: 259. Signature encoding contains incorrect types: r=n, s=Null */ - {0, 0, 6, 26870, 39, 0 }, - /* tcId: 260. Signature encoding contains incorrect types: r=n, s=empyt UTF-8 string */ - {0, 0, 6, 26909, 39, 0 }, - /* tcId: 261. Signature encoding contains incorrect types: r=n, s="0" */ - {0, 0, 6, 26948, 40, 0 }, - /* tcId: 262. Signature encoding contains incorrect types: r=n, s=empty list */ - {0, 0, 6, 26988, 39, 0 }, - /* tcId: 263. Signature encoding contains incorrect types: r=n, s=list containing 0 */ - {0, 0, 6, 27027, 42, 0 }, - /* tcId: 264. Signature encoding contains incorrect types: r=p, s=0.25 */ - {0, 0, 6, 27069, 42, 0 }, - /* tcId: 265. Signature encoding contains incorrect types: r=p, s=nan */ - {0, 0, 6, 27111, 40, 0 }, - /* tcId: 266. Signature encoding contains incorrect types: r=p, s=True */ - {0, 0, 6, 27151, 40, 0 }, - /* tcId: 267. Signature encoding contains incorrect types: r=p, s=False */ - {0, 0, 6, 27191, 40, 0 }, - /* tcId: 268. Signature encoding contains incorrect types: r=p, s=Null */ - {0, 0, 6, 27231, 39, 0 }, - /* tcId: 269. Signature encoding contains incorrect types: r=p, s=empyt UTF-8 string */ - {0, 0, 6, 27270, 39, 0 }, - /* tcId: 270. Signature encoding contains incorrect types: r=p, s="0" */ - {0, 0, 6, 27309, 40, 0 }, - /* tcId: 271. Signature encoding contains incorrect types: r=p, s=empty list */ - {0, 0, 6, 27349, 39, 0 }, - /* tcId: 272. Signature encoding contains incorrect types: r=p, s=list containing 0 */ - {0, 0, 6, 27388, 42, 0 }, - /* tcId: 273. Signature encoding contains incorrect types: r=0.25, s=0.25 */ - {0, 0, 6, 27430, 12, 0 }, - /* tcId: 274. Signature encoding contains incorrect types: r=nan, s=nan */ - {0, 0, 6, 27442, 8, 0 }, - /* tcId: 275. Signature encoding contains incorrect types: r=True, s=True */ - {0, 0, 6, 27450, 8, 0 }, - /* tcId: 276. Signature encoding contains incorrect types: r=False, s=False */ - {0, 0, 6, 27458, 8, 0 }, - /* tcId: 277. Signature encoding contains incorrect types: r=Null, s=Null */ - {0, 0, 6, 27466, 6, 0 }, - /* tcId: 278. Signature encoding contains incorrect types: r=empyt UTF-8 string, s=empyt UTF-8 string */ - {0, 0, 6, 27472, 6, 0 }, - /* tcId: 279. Signature encoding contains incorrect types: r="0", s="0" */ - {0, 0, 6, 27478, 8, 0 }, - /* tcId: 280. Signature encoding contains incorrect types: r=empty list, s=empty list */ - {0, 0, 6, 27486, 6, 0 }, - /* tcId: 281. Signature encoding contains incorrect types: r=list containing 0, s=list containing 0 */ - {0, 0, 6, 27492, 12, 0 }, - /* tcId: 282. Signature encoding contains incorrect types: r=0.25, s=0 */ - {0, 0, 6, 27504, 10, 0 }, - /* tcId: 283. Signature encoding contains incorrect types: r=nan, s=0 */ - {0, 0, 6, 27514, 8, 0 }, - /* tcId: 284. Signature encoding contains incorrect types: r=True, s=0 */ - {0, 0, 6, 27522, 8, 0 }, - /* tcId: 285. Signature encoding contains incorrect types: r=False, s=0 */ - {0, 0, 6, 27530, 8, 0 }, - /* tcId: 286. Signature encoding contains incorrect types: r=Null, s=0 */ - {0, 0, 6, 27538, 7, 0 }, - /* tcId: 287. Signature encoding contains incorrect types: r=empyt UTF-8 string, s=0 */ - {0, 0, 6, 27545, 7, 0 }, - /* tcId: 288. Signature encoding contains incorrect types: r="0", s=0 */ - {0, 0, 6, 27552, 8, 0 }, - /* tcId: 289. Signature encoding contains incorrect types: r=empty list, s=0 */ - {0, 0, 6, 27560, 7, 0 }, - /* tcId: 290. Signature encoding contains incorrect types: r=list containing 0, s=0 */ - {0, 0, 6, 27567, 10, 0 }, - /* tcId: 291. Edge case for Shamir multiplication */ - {0, 6, 5, 27577, 71, 1 }, - /* tcId: 292. special case hash */ - {0, 11, 9, 27648, 71, 1 }, - /* tcId: 293. special case hash */ - {0, 20, 10, 27719, 70, 1 }, - /* tcId: 294. special case hash */ - {0, 30, 11, 27789, 71, 1 }, - /* tcId: 295. special case hash */ - {0, 41, 10, 27860, 71, 1 }, - /* tcId: 296. special case hash */ - {0, 51, 10, 27931, 70, 1 }, - /* tcId: 297. special case hash */ - {0, 61, 10, 28001, 71, 1 }, - /* tcId: 298. special case hash */ - {0, 71, 9, 28072, 70, 1 }, - /* tcId: 299. special case hash */ - {0, 80, 10, 28142, 71, 1 }, - /* tcId: 300. special case hash */ - {0, 90, 10, 28213, 71, 1 }, - /* tcId: 301. special case hash */ - {0, 100, 10, 28284, 71, 1 }, - /* tcId: 302. special case hash */ - {0, 110, 10, 28355, 71, 1 }, - /* tcId: 303. special case hash */ - {0, 120, 11, 28426, 70, 1 }, - /* tcId: 304. special case hash */ - {0, 131, 10, 28496, 71, 1 }, - /* tcId: 305. special case hash */ - {0, 141, 10, 28567, 71, 1 }, - /* tcId: 306. special case hash */ - {0, 151, 10, 28638, 70, 1 }, - /* tcId: 307. special case hash */ - {0, 161, 10, 28708, 71, 1 }, - /* tcId: 308. special case hash */ - {0, 171, 10, 28779, 71, 1 }, - /* tcId: 309. special case hash */ - {0, 181, 10, 28850, 70, 1 }, - /* tcId: 310. special case hash */ - {0, 191, 10, 28920, 71, 1 }, - /* tcId: 311. special case hash */ - {0, 201, 10, 28991, 71, 1 }, - /* tcId: 312. special case hash */ - {0, 211, 10, 29062, 71, 1 }, - /* tcId: 313. special case hash */ - {0, 221, 10, 29133, 70, 1 }, - /* tcId: 314. special case hash */ - {0, 231, 10, 29203, 71, 1 }, - /* tcId: 315. special case hash */ - {0, 241, 10, 29274, 71, 1 }, - /* tcId: 316. special case hash */ - {0, 251, 10, 29345, 71, 1 }, - /* tcId: 317. special case hash */ - {0, 261, 11, 29416, 71, 1 }, - /* tcId: 318. special case hash */ - {0, 272, 11, 29487, 70, 1 }, - /* tcId: 319. special case hash */ - {0, 283, 9, 29557, 71, 1 }, - /* tcId: 320. special case hash */ - {0, 292, 9, 29628, 71, 1 }, - /* tcId: 321. special case hash */ - {0, 301, 10, 29699, 71, 1 }, - /* tcId: 322. special case hash */ - {0, 311, 10, 29770, 71, 1 }, - /* tcId: 323. special case hash */ - {0, 321, 10, 29841, 70, 1 }, - /* tcId: 324. special case hash */ - {0, 331, 10, 29911, 70, 1 }, - /* tcId: 325. special case hash */ - {0, 341, 10, 29981, 71, 1 }, - /* tcId: 326. special case hash */ - {0, 351, 9, 30052, 70, 1 }, - /* tcId: 327. special case hash */ - {0, 360, 10, 30122, 70, 1 }, - /* tcId: 328. special case hash */ - {0, 370, 10, 30192, 70, 1 }, - /* tcId: 329. special case hash */ - {0, 380, 10, 30262, 70, 1 }, - /* tcId: 330. special case hash */ - {0, 390, 9, 30332, 71, 1 }, - /* tcId: 331. special case hash */ - {0, 399, 11, 30403, 70, 1 }, - /* tcId: 332. special case hash */ - {0, 410, 9, 30473, 71, 1 }, - /* tcId: 333. special case hash */ - {0, 419, 9, 30544, 71, 1 }, - /* tcId: 334. special case hash */ - {0, 428, 11, 30615, 70, 1 }, - /* tcId: 335. special case hash */ - {0, 439, 8, 30685, 71, 1 }, - /* tcId: 336. special case hash */ - {0, 447, 10, 30756, 70, 1 }, - /* tcId: 337. special case hash */ - {0, 457, 10, 30826, 71, 1 }, - /* tcId: 338. special case hash */ - {0, 467, 10, 30897, 70, 1 }, - /* tcId: 339. special case hash */ - {0, 477, 10, 30967, 70, 1 }, - /* tcId: 340. special case hash */ - {0, 487, 10, 31037, 70, 1 }, - /* tcId: 341. special case hash */ - {0, 497, 10, 31107, 71, 1 }, - /* tcId: 342. special case hash */ - {0, 507, 10, 31178, 70, 1 }, - /* tcId: 343. special case hash */ - {0, 517, 10, 31248, 70, 1 }, - /* tcId: 344. special case hash */ - {0, 527, 10, 31318, 71, 1 }, - /* tcId: 345. special case hash */ - {0, 537, 9, 31389, 70, 1 }, - /* tcId: 346. k*G has a large x-coordinate */ - {65, 0, 6, 31459, 24, 1 }, - /* tcId: 347. r too large */ - {65, 0, 6, 31483, 40, 0 }, - /* tcId: 348. r,s are large */ - {130, 0, 6, 31523, 40, 1 }, - /* tcId: 349. r and s^-1 have a large Hamming weight */ - {195, 0, 6, 31563, 70, 1 }, - /* tcId: 350. r and s^-1 have a large Hamming weight */ - {260, 0, 6, 31633, 70, 1 }, - /* tcId: 351. small r and s */ - {325, 0, 6, 31703, 8, 1 }, - /* tcId: 352. small r and s */ - {390, 0, 6, 31711, 8, 1 }, - /* tcId: 353. small r and s */ - {455, 0, 6, 31719, 8, 1 }, - /* tcId: 354. small r and s */ - {520, 0, 6, 31727, 8, 1 }, - /* tcId: 355. small r and s */ - {585, 0, 6, 31735, 8, 1 }, - /* tcId: 356. small r and s */ - {650, 0, 6, 31743, 8, 1 }, - /* tcId: 357. r is larger than n */ - {650, 0, 6, 31751, 40, 0 }, - /* tcId: 358. s is larger than n */ - {715, 0, 6, 31791, 10, 0 }, - /* tcId: 359. small r and s^-1 */ - {780, 0, 6, 31801, 40, 1 }, - /* tcId: 360. smallish r and s^-1 */ - {845, 0, 6, 31841, 45, 1 }, - /* tcId: 361. 100-bit r and small s^-1 */ - {910, 0, 6, 31886, 51, 1 }, - /* tcId: 362. small r and 100 bit s^-1 */ - {975, 0, 6, 31937, 40, 1 }, - /* tcId: 363. 100-bit r and s^-1 */ - {1040, 0, 6, 31977, 51, 1 }, - /* tcId: 364. r and s^-1 are close to n */ - {1105, 0, 6, 32028, 71, 1 }, - /* tcId: 365. r and s are 64-bit integer */ - {1170, 0, 6, 32099, 24, 1 }, - /* tcId: 366. r and s are 100-bit integer */ - {1235, 0, 6, 32123, 32, 1 }, - /* tcId: 367. r and s are 128-bit integer */ - {1300, 0, 6, 32155, 40, 1 }, - /* tcId: 368. r and s are 160-bit integer */ - {1365, 0, 6, 32195, 48, 1 }, - /* tcId: 369. s == 1 */ - {1430, 0, 6, 32243, 39, 1 }, - /* tcId: 370. s == 0 */ - {1430, 0, 6, 32282, 39, 0 }, - /* tcId: 371. edge case modular inverse */ - {1495, 0, 6, 32321, 70, 1 }, - /* tcId: 372. edge case modular inverse */ - {1560, 0, 6, 32391, 70, 1 }, - /* tcId: 373. edge case modular inverse */ - {1625, 0, 6, 32461, 70, 1 }, - /* tcId: 374. edge case modular inverse */ - {1690, 0, 6, 32531, 70, 1 }, - /* tcId: 375. edge case modular inverse */ - {1755, 0, 6, 32601, 70, 1 }, - /* tcId: 376. edge case modular inverse */ - {1820, 0, 6, 32671, 70, 1 }, - /* tcId: 377. edge case modular inverse */ - {1885, 0, 6, 32741, 70, 1 }, - /* tcId: 378. edge case modular inverse */ - {1950, 0, 6, 32811, 70, 1 }, - /* tcId: 379. edge case modular inverse */ - {2015, 0, 6, 32881, 70, 1 }, - /* tcId: 380. edge case modular inverse */ - {2080, 0, 6, 32951, 70, 1 }, - /* tcId: 381. edge case modular inverse */ - {2145, 0, 6, 33021, 70, 1 }, - /* tcId: 382. edge case modular inverse */ - {2210, 0, 6, 33091, 70, 1 }, - /* tcId: 383. edge case modular inverse */ - {2275, 0, 6, 33161, 70, 1 }, - /* tcId: 384. edge case modular inverse */ - {2340, 0, 6, 33231, 70, 1 }, - /* tcId: 385. edge case modular inverse */ - {2405, 0, 6, 33301, 70, 1 }, - /* tcId: 386. point at infinity during verify */ - {2470, 0, 6, 33371, 70, 0 }, - /* tcId: 387. edge case for signature malleability */ - {2535, 0, 6, 33441, 70, 1 }, - /* tcId: 388. edge case for signature malleability */ - {2600, 0, 6, 33511, 70, 0 }, - /* tcId: 389. u1 == 1 */ - {2665, 0, 6, 33581, 70, 1 }, - /* tcId: 390. u1 == n - 1 */ - {2730, 0, 6, 33651, 70, 1 }, - /* tcId: 391. u2 == 1 */ - {2795, 0, 6, 33721, 70, 1 }, - /* tcId: 392. u2 == n - 1 */ - {2860, 0, 6, 33791, 70, 1 }, - /* tcId: 393. edge case for u1 */ - {2925, 0, 6, 33861, 70, 1 }, - /* tcId: 394. edge case for u1 */ - {2990, 0, 6, 33931, 70, 1 }, - /* tcId: 395. edge case for u1 */ - {3055, 0, 6, 34001, 70, 1 }, - /* tcId: 396. edge case for u1 */ - {3120, 0, 6, 34071, 70, 1 }, - /* tcId: 397. edge case for u1 */ - {3185, 0, 6, 34141, 70, 1 }, - /* tcId: 398. edge case for u1 */ - {3250, 0, 6, 34211, 70, 1 }, - /* tcId: 399. edge case for u1 */ - {3315, 0, 6, 34281, 70, 1 }, - /* tcId: 400. edge case for u1 */ - {3380, 0, 6, 34351, 70, 1 }, - /* tcId: 401. edge case for u1 */ - {3445, 0, 6, 34421, 70, 1 }, - /* tcId: 402. edge case for u1 */ - {3510, 0, 6, 34491, 70, 1 }, - /* tcId: 403. edge case for u1 */ - {3575, 0, 6, 34561, 70, 1 }, - /* tcId: 404. edge case for u1 */ - {3640, 0, 6, 34631, 70, 1 }, - /* tcId: 405. edge case for u1 */ - {3705, 0, 6, 34701, 70, 1 }, - /* tcId: 406. edge case for u1 */ - {3770, 0, 6, 34771, 70, 1 }, - /* tcId: 407. edge case for u1 */ - {3835, 0, 6, 34841, 70, 1 }, - /* tcId: 408. edge case for u2 */ - {3900, 0, 6, 34911, 70, 1 }, - /* tcId: 409. edge case for u2 */ - {3965, 0, 6, 34981, 70, 1 }, - /* tcId: 410. edge case for u2 */ - {4030, 0, 6, 35051, 70, 1 }, - /* tcId: 411. edge case for u2 */ - {4095, 0, 6, 35121, 70, 1 }, - /* tcId: 412. edge case for u2 */ - {4160, 0, 6, 35191, 70, 1 }, - /* tcId: 413. edge case for u2 */ - {4225, 0, 6, 35261, 69, 1 }, - /* tcId: 414. edge case for u2 */ - {4290, 0, 6, 35330, 70, 1 }, - /* tcId: 415. edge case for u2 */ - {4355, 0, 6, 35400, 70, 1 }, - /* tcId: 416. edge case for u2 */ - {4420, 0, 6, 35470, 70, 1 }, - /* tcId: 417. edge case for u2 */ - {4485, 0, 6, 35540, 70, 1 }, - /* tcId: 418. edge case for u2 */ - {4550, 0, 6, 35610, 70, 1 }, - /* tcId: 419. edge case for u2 */ - {4615, 0, 6, 35680, 70, 1 }, - /* tcId: 420. edge case for u2 */ - {4680, 0, 6, 35750, 70, 1 }, - /* tcId: 421. edge case for u2 */ - {4745, 0, 6, 35820, 70, 1 }, - /* tcId: 422. edge case for u2 */ - {4810, 0, 6, 35890, 70, 1 }, - /* tcId: 423. point duplication during verification */ - {4875, 0, 6, 35960, 70, 1 }, - /* tcId: 424. duplication bug */ - {4940, 0, 6, 36030, 70, 0 }, - /* tcId: 425. comparison with point at infinity */ - {5005, 0, 6, 36100, 70, 0 }, - /* tcId: 426. extreme value for k and edgecase s */ - {5070, 0, 6, 36170, 71, 1 }, - /* tcId: 427. extreme value for k and s^-1 */ - {5135, 0, 6, 36241, 71, 1 }, - /* tcId: 428. extreme value for k and s^-1 */ - {5200, 0, 6, 36312, 71, 1 }, - /* tcId: 429. extreme value for k and s^-1 */ - {5265, 0, 6, 36383, 71, 1 }, - /* tcId: 430. extreme value for k and s^-1 */ - {5330, 0, 6, 36454, 71, 1 }, - /* tcId: 431. extreme value for k */ - {5395, 0, 6, 36525, 71, 1 }, - /* tcId: 432. extreme value for k and edgecase s */ - {5460, 0, 6, 36596, 70, 1 }, - /* tcId: 433. extreme value for k and s^-1 */ - {5525, 0, 6, 36666, 70, 1 }, - /* tcId: 434. extreme value for k and s^-1 */ - {5590, 0, 6, 36736, 70, 1 }, - /* tcId: 435. extreme value for k and s^-1 */ - {5655, 0, 6, 36806, 70, 1 }, - /* tcId: 436. extreme value for k and s^-1 */ - {5720, 0, 6, 36876, 70, 1 }, - /* tcId: 437. extreme value for k */ - {5785, 0, 6, 36946, 70, 1 }, - /* tcId: 438. public key shares x-coordinate with generator */ - {5850, 0, 6, 37016, 71, 0 }, - /* tcId: 439. public key shares x-coordinate with generator */ - {5850, 0, 6, 37087, 70, 0 }, - /* tcId: 440. public key shares x-coordinate with generator */ - {5915, 0, 6, 37157, 71, 0 }, - /* tcId: 441. public key shares x-coordinate with generator */ - {5915, 0, 6, 37228, 70, 0 }, - /* tcId: 442. pseudorandom signature */ - {5980, 546, 0, 37298, 71, 1 }, - /* tcId: 443. pseudorandom signature */ - {5980, 546, 3, 37369, 70, 1 }, - /* tcId: 444. pseudorandom signature */ - {5980, 0, 6, 37439, 71, 1 }, - /* tcId: 445. pseudorandom signature */ - {5980, 549, 20, 37510, 70, 1 }, - /* tcId: 446. y-coordinate of the public key is small */ - {6045, 569, 7, 37580, 70, 1 }, - /* tcId: 447. y-coordinate of the public key is small */ - {6045, 569, 7, 37650, 70, 1 }, - /* tcId: 448. y-coordinate of the public key is small */ - {6045, 569, 7, 37720, 71, 1 }, - /* tcId: 449. y-coordinate of the public key is large */ - {6110, 569, 7, 37791, 70, 1 }, - /* tcId: 450. y-coordinate of the public key is large */ - {6110, 569, 7, 37861, 71, 1 }, - /* tcId: 451. y-coordinate of the public key is large */ - {6110, 569, 7, 37932, 70, 1 }, - /* tcId: 452. x-coordinate of the public key is small */ - {6175, 569, 7, 38002, 70, 1 }, - /* tcId: 453. x-coordinate of the public key is small */ - {6175, 569, 7, 38072, 71, 1 }, - /* tcId: 454. x-coordinate of the public key is small */ - {6175, 569, 7, 38143, 71, 1 }, - /* tcId: 455. x-coordinate of the public key has many trailing 1's */ - {6240, 569, 7, 38214, 70, 1 }, - /* tcId: 456. x-coordinate of the public key has many trailing 1's */ - {6240, 569, 7, 38284, 71, 1 }, - /* tcId: 457. x-coordinate of the public key has many trailing 1's */ - {6240, 569, 7, 38355, 71, 1 }, - /* tcId: 458. y-coordinate of the public key has many trailing 1's */ - {6305, 569, 7, 38426, 70, 1 }, - /* tcId: 459. y-coordinate of the public key has many trailing 1's */ - {6305, 569, 7, 38496, 71, 1 }, - /* tcId: 460. y-coordinate of the public key has many trailing 1's */ - {6305, 569, 7, 38567, 71, 1 }, - /* tcId: 461. x-coordinate of the public key has many trailing 0's */ - {6370, 569, 7, 38638, 70, 1 }, - /* tcId: 462. x-coordinate of the public key has many trailing 0's */ - {6370, 569, 7, 38708, 70, 1 }, - /* tcId: 463. x-coordinate of the public key has many trailing 0's */ - {6370, 569, 7, 38778, 71, 1 }, - -}; diff --git a/external/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json b/external/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json deleted file mode 100644 index 9c90747993..0000000000 --- a/external/secp256k1/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json +++ /dev/null @@ -1,6360 +0,0 @@ -{ - "algorithm" : "ECDSA", - "schema" : "ecdsa_bitcoin_verify_schema.json", - "generatorVersion" : "0.9rc5", - "numberOfTests" : 463, - "header" : [ - "Test vectors of type EcdsaBitcoinVerify are meant for the verification", - "of a ECDSA variant used for bitcoin, that add signature non-malleability." - ], - "notes" : { - "ArithmeticError" : { - "bugType" : "EDGE_CASE", - "description" : "Some implementations of ECDSA have arithmetic errors that occur when intermediate results have extreme values. This test vector has been constructed to test such occurences.", - "cves" : [ - "CVE-2017-18146" - ] - }, - "BerEncodedSignature" : { - "bugType" : "BER_ENCODING", - "description" : "ECDSA signatures are usually DER encoded. This signature contains valid values for r and s, but it uses alternative BER encoding.", - "effect" : "Accepting alternative BER encodings may be benign in some cases, or be an issue if protocol requires signature malleability.", - "cves" : [ - "CVE-2020-14966", - "CVE-2020-13822", - "CVE-2019-14859", - "CVE-2016-1000342" - ] - }, - "EdgeCasePublicKey" : { - "bugType" : "EDGE_CASE", - "description" : "The test vector uses a special case public key. " - }, - "EdgeCaseShamirMultiplication" : { - "bugType" : "EDGE_CASE", - "description" : "Shamir proposed a fast method for computing the sum of two scalar multiplications efficiently. This test vector has been constructed so that an intermediate result is the point at infinity if Shamir's method is used." - }, - "IntegerOverflow" : { - "bugType" : "CAN_OF_WORMS", - "description" : "The test vector contains an r and s that has been modified, so that the original value is restored if the implementation ignores the most significant bits.", - "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." - }, - "InvalidEncoding" : { - "bugType" : "CAN_OF_WORMS", - "description" : "ECDSA signatures are encoded using ASN.1. This test vector contains an incorrectly encoded signature. The test vector itself was generated from a valid signature by modifying its encoding.", - "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." - }, - "InvalidSignature" : { - "bugType" : "AUTH_BYPASS", - "description" : "The signature contains special case values such as r=0 and s=0. Buggy implementations may accept such values, if the implementation does not check boundaries and computes s^(-1) == 0.", - "effect" : "Accepting such signatures can have the effect that an adversary can forge signatures without even knowning the message to sign.", - "cves" : [ - "CVE-2022-21449", - "CVE-2021-43572", - "CVE-2022-24884" - ] - }, - "InvalidTypesInSignature" : { - "bugType" : "AUTH_BYPASS", - "description" : "The signature contains invalid types. Dynamic typed languages sometime coerce such values of different types into integers. If an implementation is careless and has additional bugs, such as not checking integer boundaries then it may be possible that such signatures are accepted.", - "effect" : "Accepting such signatures can have the effect that an adversary can forge signatures without even knowning the message to sign.", - "cves" : [ - "CVE-2022-21449" - ] - }, - "ModifiedInteger" : { - "bugType" : "CAN_OF_WORMS", - "description" : "The test vector contains an r and s that has been modified. The goal is to check for arithmetic errors.", - "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." - }, - "ModifiedSignature" : { - "bugType" : "CAN_OF_WORMS", - "description" : "The test vector contains an invalid signature that was generated from a valid signature by modifying it.", - "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." - }, - "ModularInverse" : { - "bugType" : "EDGE_CASE", - "description" : "The test vectors contains a signature where computing the modular inverse of s hits an edge case.", - "effect" : "While the signature in this test vector is constructed and similar cases are unlikely to occur, it is important to determine if the underlying arithmetic error can be used to forge signatures.", - "cves" : [ - "CVE-2019-0865" - ] - }, - "PointDuplication" : { - "bugType" : "EDGE_CASE", - "description" : "Some implementations of ECDSA do not handle duplication and points at infinity correctly. This is a test vector that has been specially crafted to check for such an omission.", - "cves" : [ - "2020-12607", - "CVE-2015-2730" - ] - }, - "RangeCheck" : { - "bugType" : "CAN_OF_WORMS", - "description" : "The test vector contains an r and s that has been modified. By adding or subtracting the order of the group (or other values) the test vector checks whether signature verification verifies the range of r and s.", - "effect" : "Without further analysis it is unclear if the modification can be used to forge signatures." - }, - "SignatureMalleabilityBitcoin" : { - "bugType" : "SIGNATURE_MALLEABILITY", - "description" : "\"BitCoins\"-curves are curves where signature malleability can be a serious issue. An implementation should only accept a signature s where s < n/2. If an implementation is not meant for uses cases that require signature malleability then this implemenation should be tested with another set of test vectors.", - "effect" : "In bitcoin exchanges, it may be used to make a double deposits or double withdrawals", - "links" : [ - "https://en.bitcoin.it/wiki/Transaction_malleability", - "https://en.bitcoinwiki.org/wiki/Transaction_Malleability" - ] - }, - "SmallRandS" : { - "bugType" : "EDGE_CASE", - "description" : "The test vectors contains a signature where both r and s are small integers. Some libraries cannot verify such signatures.", - "effect" : "While the signature in this test vector is constructed and similar cases are unlikely to occur, it is important to determine if the underlying arithmetic error can be used to forge signatures.", - "cves" : [ - "2020-13895" - ] - }, - "SpecialCaseHash" : { - "bugType" : "EDGE_CASE", - "description" : "The test vector contains a signature where the hash of the message is a special case, e.g., contains a long run of 0 or 1 bits." - }, - "ValidSignature" : { - "bugType" : "BASIC", - "description" : "The test vector contains a valid signature that was generated pseudorandomly. Such signatures should not fail to verify unless some of the parameters (e.g. curve or hash function) are not supported." - } - }, - "testGroups" : [ - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", - "wx" : "00b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6f", - "wy" : "00f0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuDj/ROW8F3vyEYnQdmCC/J2EMiaIf8l2\nA3EQC37iCm/wyddb+6ezGmvKGXRJbutW3jVwcZVdg8Sxutqgshgy6Q==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 1, - "comment" : "Signature malleability", - "flags" : [ - "SignatureMalleabilityBitcoin" - ], - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022100900e75ad233fcc908509dbff5922647db37c21f4afd3203ae8dc4ae7794b0f87", - "result" : "invalid" - }, - { - "tcId" : 2, - "comment" : "valid", - "flags" : [ - "ValidSignature" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "valid" - }, - { - "tcId" : 3, - "comment" : "length of sequence [r, s] uses long form encoding", - "flags" : [ - "BerEncodedSignature" - ], - "msg" : "313233343030", - "sig" : "308145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 4, - "comment" : "length of sequence [r, s] contains a leading 0", - "flags" : [ - "BerEncodedSignature" - ], - "msg" : "313233343030", - "sig" : "30820045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 5, - "comment" : "length of sequence [r, s] uses 70 instead of 69", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 6, - "comment" : "length of sequence [r, s] uses 68 instead of 69", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 7, - "comment" : "uint32 overflow in length of sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30850100000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 8, - "comment" : "uint64 overflow in length of sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3089010000000000000045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 9, - "comment" : "length of sequence [r, s] = 2**31 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30847fffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 10, - "comment" : "length of sequence [r, s] = 2**31", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "308480000000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 11, - "comment" : "length of sequence [r, s] = 2**32 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3084ffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 12, - "comment" : "length of sequence [r, s] = 2**40 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3085ffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 13, - "comment" : "length of sequence [r, s] = 2**64 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3088ffffffffffffffff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 14, - "comment" : "incorrect length of sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30ff022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 15, - "comment" : "replaced sequence [r, s] by an indefinite length tag without termination", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 16, - "comment" : "removing sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "", - "result" : "invalid" - }, - { - "tcId" : 17, - "comment" : "lonely sequence tag", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30", - "result" : "invalid" - }, - { - "tcId" : 18, - "comment" : "appending 0's to sequence [r, s]", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid" - }, - { - "tcId" : 19, - "comment" : "prepending 0's to sequence [r, s]", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "30470000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 20, - "comment" : "appending unused 0's to sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid" - }, - { - "tcId" : 21, - "comment" : "appending null value to sequence [r, s]", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", - "result" : "invalid" - }, - { - "tcId" : 22, - "comment" : "prepending garbage to sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304a4981773045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 23, - "comment" : "prepending garbage to sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304925003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 24, - "comment" : "appending garbage to sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", - "result" : "invalid" - }, - { - "tcId" : 25, - "comment" : "including undefined tags", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "304daa00bb00cd003045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 26, - "comment" : "including undefined tags", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304d2229aa00bb00cd00022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 27, - "comment" : "including undefined tags", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652228aa00bb00cd0002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 28, - "comment" : "truncated length of sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3081", - "result" : "invalid" - }, - { - "tcId" : 29, - "comment" : "including undefined tags to sequence [r, s]", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "304baa02aabb3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 30, - "comment" : "using composition with indefinite length for sequence [r, s]", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "30803045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid" - }, - { - "tcId" : 31, - "comment" : "using composition with wrong tag for sequence [r, s]", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "30803145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid" - }, - { - "tcId" : 32, - "comment" : "Replacing sequence [r, s] with NULL", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "0500", - "result" : "invalid" - }, - { - "tcId" : 33, - "comment" : "changing tag value of sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "2e45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 34, - "comment" : "changing tag value of sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "2f45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 35, - "comment" : "changing tag value of sequence [r, s]", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3145022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 36, - "comment" : "changing tag value of sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3245022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 37, - "comment" : "changing tag value of sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "ff45022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 38, - "comment" : "dropping value of sequence [r, s]", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3000", - "result" : "invalid" - }, - { - "tcId" : 39, - "comment" : "using composition for sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304930010230442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 40, - "comment" : "truncated sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", - "result" : "invalid" - }, - { - "tcId" : 41, - "comment" : "truncated sequence [r, s]", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30442100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 42, - "comment" : "sequence [r, s] of size 4166 to check for overflows", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30821046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid" - }, - { - "tcId" : 43, - "comment" : "indefinite length", - "flags" : [ - "BerEncodedSignature" - ], - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid" - }, - { - "tcId" : 44, - "comment" : "indefinite length with truncated delimiter", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba00", - "result" : "invalid" - }, - { - "tcId" : 45, - "comment" : "indefinite length with additional element", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba05000000", - "result" : "invalid" - }, - { - "tcId" : 46, - "comment" : "indefinite length with truncated element", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba060811220000", - "result" : "invalid" - }, - { - "tcId" : 47, - "comment" : "indefinite length with garbage", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000fe02beef", - "result" : "invalid" - }, - { - "tcId" : 48, - "comment" : "indefinite length with nonempty EOC", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3080022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0002beef", - "result" : "invalid" - }, - { - "tcId" : 49, - "comment" : "prepend empty sequence", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "30473000022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 50, - "comment" : "append empty sequence", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba3000", - "result" : "invalid" - }, - { - "tcId" : 51, - "comment" : "append zero", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba020100", - "result" : "invalid" - }, - { - "tcId" : 52, - "comment" : "append garbage with high tag number", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31babf7f00", - "result" : "invalid" - }, - { - "tcId" : 53, - "comment" : "append null with explicit tag", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31baa0020500", - "result" : "invalid" - }, - { - "tcId" : 54, - "comment" : "append null with implicit tag", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31baa000", - "result" : "invalid" - }, - { - "tcId" : 55, - "comment" : "sequence of sequence", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "30473045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 56, - "comment" : "truncated sequence: removed last 1 elements", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3023022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365", - "result" : "invalid" - }, - { - "tcId" : 57, - "comment" : "repeating element in sequence", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3067022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 58, - "comment" : "flipped bit 0 in r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236402206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 59, - "comment" : "flipped bit 32 in r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccac983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 60, - "comment" : "flipped bit 48 in r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5133ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 61, - "comment" : "flipped bit 64 in r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc08b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 62, - "comment" : "length of r uses long form encoding", - "flags" : [ - "BerEncodedSignature" - ], - "msg" : "313233343030", - "sig" : "304602812100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 63, - "comment" : "length of r contains a leading 0", - "flags" : [ - "BerEncodedSignature" - ], - "msg" : "313233343030", - "sig" : "30470282002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 64, - "comment" : "length of r uses 34 instead of 33", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022200813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 65, - "comment" : "length of r uses 32 instead of 33", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 66, - "comment" : "uint32 overflow in length of r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304a0285010000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 67, - "comment" : "uint64 overflow in length of r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304e028901000000000000002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 68, - "comment" : "length of r = 2**31 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304902847fffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 69, - "comment" : "length of r = 2**31", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304902848000000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 70, - "comment" : "length of r = 2**32 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30490284ffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 71, - "comment" : "length of r = 2**40 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304a0285ffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 72, - "comment" : "length of r = 2**64 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304d0288ffffffffffffffff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 73, - "comment" : "incorrect length of r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304502ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 74, - "comment" : "replaced r by an indefinite length tag without termination", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045028000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 75, - "comment" : "removing r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "302202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 76, - "comment" : "lonely integer tag", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30230202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 77, - "comment" : "lonely integer tag", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3024022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502", - "result" : "invalid" - }, - { - "tcId" : 78, - "comment" : "appending 0's to r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 79, - "comment" : "prepending 0's to r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30470223000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 80, - "comment" : "appending unused 0's to r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 81, - "comment" : "appending null value to r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022300813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 82, - "comment" : "prepending garbage to r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304a2226498177022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 83, - "comment" : "prepending garbage to r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304922252500022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 84, - "comment" : "appending garbage to r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304d2223022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650004deadbeef02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 85, - "comment" : "truncated length of r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3024028102206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 86, - "comment" : "including undefined tags to r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304b2227aa02aabb022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 87, - "comment" : "using composition with indefinite length for r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30492280022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 88, - "comment" : "using composition with wrong tag for r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "30492280032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 89, - "comment" : "Replacing r with NULL", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3024050002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 90, - "comment" : "changing tag value of r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045002100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 91, - "comment" : "changing tag value of r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045012100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 92, - "comment" : "changing tag value of r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045032100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 93, - "comment" : "changing tag value of r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045042100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 94, - "comment" : "changing tag value of r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045ff2100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 95, - "comment" : "dropping value of r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3024020002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 96, - "comment" : "using composition for r", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304922250201000220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 97, - "comment" : "modifying first byte of r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045022102813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 98, - "comment" : "modifying last byte of r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323e502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 99, - "comment" : "truncated r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3044022000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832302206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 100, - "comment" : "truncated r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "30440220813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 101, - "comment" : "r of size 4130 to check for overflows", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "308210480282102200813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 102, - "comment" : "leading ff in r", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "30460222ff00813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 103, - "comment" : "replaced r by infinity", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "302509018002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 104, - "comment" : "replacing r with zero", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "302502010002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 105, - "comment" : "flipped bit 0 in s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31bb", - "result" : "invalid" - }, - { - "tcId" : 106, - "comment" : "flipped bit 32 in s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a456eb31ba", - "result" : "invalid" - }, - { - "tcId" : 107, - "comment" : "flipped bit 48 in s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f713a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 108, - "comment" : "flipped bit 64 in s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3043022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758001d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 109, - "comment" : "length of s uses long form encoding", - "flags" : [ - "BerEncodedSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 110, - "comment" : "length of s contains a leading 0", - "flags" : [ - "BerEncodedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028200206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 111, - "comment" : "length of s uses 33 instead of 32", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502216ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 112, - "comment" : "length of s uses 31 instead of 32", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 113, - "comment" : "uint32 overflow in length of s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028501000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 114, - "comment" : "uint64 overflow in length of s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304e022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502890100000000000000206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 115, - "comment" : "length of s = 2**31 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502847fffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 116, - "comment" : "length of s = 2**31", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650284800000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 117, - "comment" : "length of s = 2**32 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650284ffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 118, - "comment" : "length of s = 2**40 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650285ffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 119, - "comment" : "length of s = 2**64 - 1", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650288ffffffffffffffff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 120, - "comment" : "incorrect length of s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 121, - "comment" : "replaced s by an indefinite length tag without termination", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502806ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 122, - "comment" : "appending 0's to s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid" - }, - { - "tcId" : 123, - "comment" : "prepending 0's to s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365022200006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 124, - "comment" : "appending null value to s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3047022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502226ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0500", - "result" : "invalid" - }, - { - "tcId" : 125, - "comment" : "prepending garbage to s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304a022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222549817702206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 126, - "comment" : "prepending garbage to s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652224250002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 127, - "comment" : "appending garbage to s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304d022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222202206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0004deadbeef", - "result" : "invalid" - }, - { - "tcId" : 128, - "comment" : "truncated length of s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650281", - "result" : "invalid" - }, - { - "tcId" : 129, - "comment" : "including undefined tags to s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "304b022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323652226aa02aabb02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 130, - "comment" : "using composition with indefinite length for s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228002206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid" - }, - { - "tcId" : 131, - "comment" : "using composition with wrong tag for s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365228003206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000", - "result" : "invalid" - }, - { - "tcId" : 132, - "comment" : "Replacing s with NULL", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650500", - "result" : "invalid" - }, - { - "tcId" : 133, - "comment" : "changing tag value of s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236500206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 134, - "comment" : "changing tag value of s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236501206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 135, - "comment" : "changing tag value of s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236503206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 136, - "comment" : "changing tag value of s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236504206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 137, - "comment" : "changing tag value of s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365ff206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 138, - "comment" : "dropping value of s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3025022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650200", - "result" : "invalid" - }, - { - "tcId" : 139, - "comment" : "using composition for s", - "flags" : [ - "InvalidEncoding" - ], - "msg" : "313233343030", - "sig" : "3049022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365222402016f021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 140, - "comment" : "modifying first byte of s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206df18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 141, - "comment" : "modifying last byte of s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3045022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb313a", - "result" : "invalid" - }, - { - "tcId" : 142, - "comment" : "truncated s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021f6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31", - "result" : "invalid" - }, - { - "tcId" : 143, - "comment" : "truncated s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3044022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365021ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 144, - "comment" : "s of size 4129 to check for overflows", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "30821048022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365028210216ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "result" : "invalid" - }, - { - "tcId" : 145, - "comment" : "leading ff in s", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323650221ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 146, - "comment" : "replaced s by infinity", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365090180", - "result" : "invalid" - }, - { - "tcId" : 147, - "comment" : "replacing s with zero", - "flags" : [ - "ModifiedSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc9832365020100", - "result" : "invalid" - }, - { - "tcId" : 148, - "comment" : "replaced r by r + n", - "flags" : [ - "RangeCheck" - ], - "msg" : "313233343030", - "sig" : "3045022101813ef79ccefa9a56f7ba805f0e478583b90deabca4b05c4574e49b5899b964a602206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 149, - "comment" : "replaced r by r - n", - "flags" : [ - "RangeCheck" - ], - "msg" : "313233343030", - "sig" : "30440220813ef79ccefa9a56f7ba805f0e47858643b030ef461f1bcdf53fde3ef94ce22402206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 150, - "comment" : "replaced r by r + 256 * n", - "flags" : [ - "RangeCheck" - ], - "msg" : "313233343030", - "sig" : "304602220100813ef79ccefa9a56f7ba805f0e47843fad3bf4853e07f7c98770c99bffc4646502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 151, - "comment" : "replaced r by -r", - "flags" : [ - "ModifiedInteger" - ], - "msg" : "313233343030", - "sig" : "30450221ff7ec10863310565a908457fa0f1b87a7b01a0f22a0a9843f64aedc334367cdc9b02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 152, - "comment" : "replaced r by n - r", - "flags" : [ - "ModifiedInteger" - ], - "msg" : "313233343030", - "sig" : "304402207ec10863310565a908457fa0f1b87a79bc4fcf10b9e0e4320ac021c106b31ddc02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 153, - "comment" : "replaced r by -n - r", - "flags" : [ - "ModifiedInteger" - ], - "msg" : "313233343030", - "sig" : "30450221fe7ec10863310565a908457fa0f1b87a7c46f215435b4fa3ba8b1b64a766469b5a02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 154, - "comment" : "replaced r by r + 2**256", - "flags" : [ - "IntegerOverflow" - ], - "msg" : "313233343030", - "sig" : "3045022101813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 155, - "comment" : "replaced r by r + 2**320", - "flags" : [ - "IntegerOverflow" - ], - "msg" : "313233343030", - "sig" : "304d0229010000000000000000813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc983236502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 156, - "comment" : "replaced s by s + n", - "flags" : [ - "RangeCheck" - ], - "msg" : "313233343030", - "sig" : "30450221016ff18a52dcc0336f7af62400a6dd9b7fc1e197d8aebe203c96c87232272172fb02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 157, - "comment" : "replaced s by s - n", - "flags" : [ - "RangeCheck" - ], - "msg" : "313233343030", - "sig" : "30450221ff6ff18a52dcc0336f7af62400a6dd9b824c83de0b502cdfc51723b51886b4f07902206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 158, - "comment" : "replaced s by s + 256 * n", - "flags" : [ - "RangeCheck" - ], - "msg" : "313233343030", - "sig" : "3046022201006ff18a52dcc0336f7af62400a6dd9a3bb60fa1a14815bbc0a954a0758d2c72ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 159, - "comment" : "replaced s by -s", - "flags" : [ - "ModifiedInteger" - ], - "msg" : "313233343030", - "sig" : "30440220900e75ad233fcc908509dbff5922647ef8cd450e008a7fff2909ec5aa914ce4602206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 160, - "comment" : "replaced s by -n - s", - "flags" : [ - "ModifiedInteger" - ], - "msg" : "313233343030", - "sig" : "30450221fe900e75ad233fcc908509dbff592264803e1e68275141dfc369378dcdd8de8d0502206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 161, - "comment" : "replaced s by s + 2**256", - "flags" : [ - "IntegerOverflow" - ], - "msg" : "313233343030", - "sig" : "30450221016ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 162, - "comment" : "replaced s by s - 2**256", - "flags" : [ - "IntegerOverflow" - ], - "msg" : "313233343030", - "sig" : "30450221ff6ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 163, - "comment" : "replaced s by s + 2**320", - "flags" : [ - "IntegerOverflow" - ], - "msg" : "313233343030", - "sig" : "304d02290100000000000000006ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba02206ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba", - "result" : "invalid" - }, - { - "tcId" : 164, - "comment" : "Signature with special case values r=0 and s=0", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3006020100020100", - "result" : "invalid" - }, - { - "tcId" : 165, - "comment" : "Signature with special case values r=0 and s=1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3006020100020101", - "result" : "invalid" - }, - { - "tcId" : 166, - "comment" : "Signature with special case values r=0 and s=-1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30060201000201ff", - "result" : "invalid" - }, - { - "tcId" : 167, - "comment" : "Signature with special case values r=0 and s=n", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid" - }, - { - "tcId" : 168, - "comment" : "Signature with special case values r=0 and s=n - 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid" - }, - { - "tcId" : 169, - "comment" : "Signature with special case values r=0 and s=n + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid" - }, - { - "tcId" : 170, - "comment" : "Signature with special case values r=0 and s=p", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid" - }, - { - "tcId" : 171, - "comment" : "Signature with special case values r=0 and s=p + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020100022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid" - }, - { - "tcId" : 172, - "comment" : "Signature with special case values r=1 and s=0", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3006020101020100", - "result" : "invalid" - }, - { - "tcId" : 173, - "comment" : "Signature with special case values r=1 and s=1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3006020101020101", - "result" : "invalid" - }, - { - "tcId" : 174, - "comment" : "Signature with special case values r=1 and s=-1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30060201010201ff", - "result" : "invalid" - }, - { - "tcId" : 175, - "comment" : "Signature with special case values r=1 and s=n", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid" - }, - { - "tcId" : 176, - "comment" : "Signature with special case values r=1 and s=n - 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid" - }, - { - "tcId" : 177, - "comment" : "Signature with special case values r=1 and s=n + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid" - }, - { - "tcId" : 178, - "comment" : "Signature with special case values r=1 and s=p", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid" - }, - { - "tcId" : 179, - "comment" : "Signature with special case values r=1 and s=p + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026020101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid" - }, - { - "tcId" : 180, - "comment" : "Signature with special case values r=-1 and s=0", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30060201ff020100", - "result" : "invalid" - }, - { - "tcId" : 181, - "comment" : "Signature with special case values r=-1 and s=1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30060201ff020101", - "result" : "invalid" - }, - { - "tcId" : 182, - "comment" : "Signature with special case values r=-1 and s=-1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30060201ff0201ff", - "result" : "invalid" - }, - { - "tcId" : 183, - "comment" : "Signature with special case values r=-1 and s=n", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid" - }, - { - "tcId" : 184, - "comment" : "Signature with special case values r=-1 and s=n - 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid" - }, - { - "tcId" : 185, - "comment" : "Signature with special case values r=-1 and s=n + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid" - }, - { - "tcId" : 186, - "comment" : "Signature with special case values r=-1 and s=p", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid" - }, - { - "tcId" : 187, - "comment" : "Signature with special case values r=-1 and s=p + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "30260201ff022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid" - }, - { - "tcId" : 188, - "comment" : "Signature with special case values r=n and s=0", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020100", - "result" : "invalid" - }, - { - "tcId" : 189, - "comment" : "Signature with special case values r=n and s=1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101", - "result" : "invalid" - }, - { - "tcId" : 190, - "comment" : "Signature with special case values r=n and s=-1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff", - "result" : "invalid" - }, - { - "tcId" : 191, - "comment" : "Signature with special case values r=n and s=n", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid" - }, - { - "tcId" : 192, - "comment" : "Signature with special case values r=n and s=n - 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid" - }, - { - "tcId" : 193, - "comment" : "Signature with special case values r=n and s=n + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid" - }, - { - "tcId" : 194, - "comment" : "Signature with special case values r=n and s=p", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid" - }, - { - "tcId" : 195, - "comment" : "Signature with special case values r=n and s=p + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid" - }, - { - "tcId" : 196, - "comment" : "Signature with special case values r=n - 1 and s=0", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020100", - "result" : "invalid" - }, - { - "tcId" : 197, - "comment" : "Signature with special case values r=n - 1 and s=1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140020101", - "result" : "invalid" - }, - { - "tcId" : 198, - "comment" : "Signature with special case values r=n - 1 and s=-1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641400201ff", - "result" : "invalid" - }, - { - "tcId" : 199, - "comment" : "Signature with special case values r=n - 1 and s=n", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid" - }, - { - "tcId" : 200, - "comment" : "Signature with special case values r=n - 1 and s=n - 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid" - }, - { - "tcId" : 201, - "comment" : "Signature with special case values r=n - 1 and s=n + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid" - }, - { - "tcId" : 202, - "comment" : "Signature with special case values r=n - 1 and s=p", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid" - }, - { - "tcId" : 203, - "comment" : "Signature with special case values r=n - 1 and s=p + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid" - }, - { - "tcId" : 204, - "comment" : "Signature with special case values r=n + 1 and s=0", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020100", - "result" : "invalid" - }, - { - "tcId" : 205, - "comment" : "Signature with special case values r=n + 1 and s=1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142020101", - "result" : "invalid" - }, - { - "tcId" : 206, - "comment" : "Signature with special case values r=n + 1 and s=-1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641420201ff", - "result" : "invalid" - }, - { - "tcId" : 207, - "comment" : "Signature with special case values r=n + 1 and s=n", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid" - }, - { - "tcId" : 208, - "comment" : "Signature with special case values r=n + 1 and s=n - 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid" - }, - { - "tcId" : 209, - "comment" : "Signature with special case values r=n + 1 and s=n + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid" - }, - { - "tcId" : 210, - "comment" : "Signature with special case values r=n + 1 and s=p", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid" - }, - { - "tcId" : 211, - "comment" : "Signature with special case values r=n + 1 and s=p + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid" - }, - { - "tcId" : 212, - "comment" : "Signature with special case values r=p and s=0", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020100", - "result" : "invalid" - }, - { - "tcId" : 213, - "comment" : "Signature with special case values r=p and s=1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f020101", - "result" : "invalid" - }, - { - "tcId" : 214, - "comment" : "Signature with special case values r=p and s=-1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0201ff", - "result" : "invalid" - }, - { - "tcId" : 215, - "comment" : "Signature with special case values r=p and s=n", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid" - }, - { - "tcId" : 216, - "comment" : "Signature with special case values r=p and s=n - 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid" - }, - { - "tcId" : 217, - "comment" : "Signature with special case values r=p and s=n + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid" - }, - { - "tcId" : 218, - "comment" : "Signature with special case values r=p and s=p", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid" - }, - { - "tcId" : 219, - "comment" : "Signature with special case values r=p and s=p + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid" - }, - { - "tcId" : 220, - "comment" : "Signature with special case values r=p + 1 and s=0", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020100", - "result" : "invalid" - }, - { - "tcId" : 221, - "comment" : "Signature with special case values r=p + 1 and s=1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30020101", - "result" : "invalid" - }, - { - "tcId" : 222, - "comment" : "Signature with special case values r=p + 1 and s=-1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc300201ff", - "result" : "invalid" - }, - { - "tcId" : 223, - "comment" : "Signature with special case values r=p + 1 and s=n", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", - "result" : "invalid" - }, - { - "tcId" : 224, - "comment" : "Signature with special case values r=p + 1 and s=n - 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", - "result" : "invalid" - }, - { - "tcId" : 225, - "comment" : "Signature with special case values r=p + 1 and s=n + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142", - "result" : "invalid" - }, - { - "tcId" : 226, - "comment" : "Signature with special case values r=p + 1 and s=p", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - "result" : "invalid" - }, - { - "tcId" : 227, - "comment" : "Signature with special case values r=p + 1 and s=p + 1", - "flags" : [ - "InvalidSignature" - ], - "msg" : "313233343030", - "sig" : "3046022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - "result" : "invalid" - }, - { - "tcId" : 228, - "comment" : "Signature encoding contains incorrect types: r=0, s=0.25", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3008020100090380fe01", - "result" : "invalid" - }, - { - "tcId" : 229, - "comment" : "Signature encoding contains incorrect types: r=0, s=nan", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006020100090142", - "result" : "invalid" - }, - { - "tcId" : 230, - "comment" : "Signature encoding contains incorrect types: r=0, s=True", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006020100010101", - "result" : "invalid" - }, - { - "tcId" : 231, - "comment" : "Signature encoding contains incorrect types: r=0, s=False", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006020100010100", - "result" : "invalid" - }, - { - "tcId" : 232, - "comment" : "Signature encoding contains incorrect types: r=0, s=Null", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201000500", - "result" : "invalid" - }, - { - "tcId" : 233, - "comment" : "Signature encoding contains incorrect types: r=0, s=empyt UTF-8 string", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201000c00", - "result" : "invalid" - }, - { - "tcId" : 234, - "comment" : "Signature encoding contains incorrect types: r=0, s=\"0\"", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30060201000c0130", - "result" : "invalid" - }, - { - "tcId" : 235, - "comment" : "Signature encoding contains incorrect types: r=0, s=empty list", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201003000", - "result" : "invalid" - }, - { - "tcId" : 236, - "comment" : "Signature encoding contains incorrect types: r=0, s=list containing 0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30080201003003020100", - "result" : "invalid" - }, - { - "tcId" : 237, - "comment" : "Signature encoding contains incorrect types: r=1, s=0.25", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3008020101090380fe01", - "result" : "invalid" - }, - { - "tcId" : 238, - "comment" : "Signature encoding contains incorrect types: r=1, s=nan", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006020101090142", - "result" : "invalid" - }, - { - "tcId" : 239, - "comment" : "Signature encoding contains incorrect types: r=1, s=True", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006020101010101", - "result" : "invalid" - }, - { - "tcId" : 240, - "comment" : "Signature encoding contains incorrect types: r=1, s=False", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006020101010100", - "result" : "invalid" - }, - { - "tcId" : 241, - "comment" : "Signature encoding contains incorrect types: r=1, s=Null", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201010500", - "result" : "invalid" - }, - { - "tcId" : 242, - "comment" : "Signature encoding contains incorrect types: r=1, s=empyt UTF-8 string", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201010c00", - "result" : "invalid" - }, - { - "tcId" : 243, - "comment" : "Signature encoding contains incorrect types: r=1, s=\"0\"", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30060201010c0130", - "result" : "invalid" - }, - { - "tcId" : 244, - "comment" : "Signature encoding contains incorrect types: r=1, s=empty list", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201013000", - "result" : "invalid" - }, - { - "tcId" : 245, - "comment" : "Signature encoding contains incorrect types: r=1, s=list containing 0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30080201013003020100", - "result" : "invalid" - }, - { - "tcId" : 246, - "comment" : "Signature encoding contains incorrect types: r=-1, s=0.25", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30080201ff090380fe01", - "result" : "invalid" - }, - { - "tcId" : 247, - "comment" : "Signature encoding contains incorrect types: r=-1, s=nan", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30060201ff090142", - "result" : "invalid" - }, - { - "tcId" : 248, - "comment" : "Signature encoding contains incorrect types: r=-1, s=True", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30060201ff010101", - "result" : "invalid" - }, - { - "tcId" : 249, - "comment" : "Signature encoding contains incorrect types: r=-1, s=False", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30060201ff010100", - "result" : "invalid" - }, - { - "tcId" : 250, - "comment" : "Signature encoding contains incorrect types: r=-1, s=Null", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201ff0500", - "result" : "invalid" - }, - { - "tcId" : 251, - "comment" : "Signature encoding contains incorrect types: r=-1, s=empyt UTF-8 string", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201ff0c00", - "result" : "invalid" - }, - { - "tcId" : 252, - "comment" : "Signature encoding contains incorrect types: r=-1, s=\"0\"", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30060201ff0c0130", - "result" : "invalid" - }, - { - "tcId" : 253, - "comment" : "Signature encoding contains incorrect types: r=-1, s=empty list", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050201ff3000", - "result" : "invalid" - }, - { - "tcId" : 254, - "comment" : "Signature encoding contains incorrect types: r=-1, s=list containing 0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30080201ff3003020100", - "result" : "invalid" - }, - { - "tcId" : 255, - "comment" : "Signature encoding contains incorrect types: r=n, s=0.25", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090380fe01", - "result" : "invalid" - }, - { - "tcId" : 256, - "comment" : "Signature encoding contains incorrect types: r=n, s=nan", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141090142", - "result" : "invalid" - }, - { - "tcId" : 257, - "comment" : "Signature encoding contains incorrect types: r=n, s=True", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141010101", - "result" : "invalid" - }, - { - "tcId" : 258, - "comment" : "Signature encoding contains incorrect types: r=n, s=False", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141010100", - "result" : "invalid" - }, - { - "tcId" : 259, - "comment" : "Signature encoding contains incorrect types: r=n, s=Null", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410500", - "result" : "invalid" - }, - { - "tcId" : 260, - "comment" : "Signature encoding contains incorrect types: r=n, s=empyt UTF-8 string", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410c00", - "result" : "invalid" - }, - { - "tcId" : 261, - "comment" : "Signature encoding contains incorrect types: r=n, s=\"0\"", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410c0130", - "result" : "invalid" - }, - { - "tcId" : 262, - "comment" : "Signature encoding contains incorrect types: r=n, s=empty list", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3025022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641413000", - "result" : "invalid" - }, - { - "tcId" : 263, - "comment" : "Signature encoding contains incorrect types: r=n, s=list containing 0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641413003020100", - "result" : "invalid" - }, - { - "tcId" : 264, - "comment" : "Signature encoding contains incorrect types: r=p, s=0.25", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090380fe01", - "result" : "invalid" - }, - { - "tcId" : 265, - "comment" : "Signature encoding contains incorrect types: r=p, s=nan", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f090142", - "result" : "invalid" - }, - { - "tcId" : 266, - "comment" : "Signature encoding contains incorrect types: r=p, s=True", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f010101", - "result" : "invalid" - }, - { - "tcId" : 267, - "comment" : "Signature encoding contains incorrect types: r=p, s=False", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f010100", - "result" : "invalid" - }, - { - "tcId" : 268, - "comment" : "Signature encoding contains incorrect types: r=p, s=Null", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0500", - "result" : "invalid" - }, - { - "tcId" : 269, - "comment" : "Signature encoding contains incorrect types: r=p, s=empyt UTF-8 string", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0c00", - "result" : "invalid" - }, - { - "tcId" : 270, - "comment" : "Signature encoding contains incorrect types: r=p, s=\"0\"", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0c0130", - "result" : "invalid" - }, - { - "tcId" : 271, - "comment" : "Signature encoding contains incorrect types: r=p, s=empty list", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3025022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3000", - "result" : "invalid" - }, - { - "tcId" : 272, - "comment" : "Signature encoding contains incorrect types: r=p, s=list containing 0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3028022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3003020100", - "result" : "invalid" - }, - { - "tcId" : 273, - "comment" : "Signature encoding contains incorrect types: r=0.25, s=0.25", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "300a090380fe01090380fe01", - "result" : "invalid" - }, - { - "tcId" : 274, - "comment" : "Signature encoding contains incorrect types: r=nan, s=nan", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006090142090142", - "result" : "invalid" - }, - { - "tcId" : 275, - "comment" : "Signature encoding contains incorrect types: r=True, s=True", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006010101010101", - "result" : "invalid" - }, - { - "tcId" : 276, - "comment" : "Signature encoding contains incorrect types: r=False, s=False", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006010100010100", - "result" : "invalid" - }, - { - "tcId" : 277, - "comment" : "Signature encoding contains incorrect types: r=Null, s=Null", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "300405000500", - "result" : "invalid" - }, - { - "tcId" : 278, - "comment" : "Signature encoding contains incorrect types: r=empyt UTF-8 string, s=empyt UTF-8 string", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30040c000c00", - "result" : "invalid" - }, - { - "tcId" : 279, - "comment" : "Signature encoding contains incorrect types: r=\"0\", s=\"0\"", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30060c01300c0130", - "result" : "invalid" - }, - { - "tcId" : 280, - "comment" : "Signature encoding contains incorrect types: r=empty list, s=empty list", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "300430003000", - "result" : "invalid" - }, - { - "tcId" : 281, - "comment" : "Signature encoding contains incorrect types: r=list containing 0, s=list containing 0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "300a30030201003003020100", - "result" : "invalid" - }, - { - "tcId" : 282, - "comment" : "Signature encoding contains incorrect types: r=0.25, s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3008090380fe01020100", - "result" : "invalid" - }, - { - "tcId" : 283, - "comment" : "Signature encoding contains incorrect types: r=nan, s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006090142020100", - "result" : "invalid" - }, - { - "tcId" : 284, - "comment" : "Signature encoding contains incorrect types: r=True, s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006010101020100", - "result" : "invalid" - }, - { - "tcId" : 285, - "comment" : "Signature encoding contains incorrect types: r=False, s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "3006010100020100", - "result" : "invalid" - }, - { - "tcId" : 286, - "comment" : "Signature encoding contains incorrect types: r=Null, s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050500020100", - "result" : "invalid" - }, - { - "tcId" : 287, - "comment" : "Signature encoding contains incorrect types: r=empyt UTF-8 string, s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30050c00020100", - "result" : "invalid" - }, - { - "tcId" : 288, - "comment" : "Signature encoding contains incorrect types: r=\"0\", s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30060c0130020100", - "result" : "invalid" - }, - { - "tcId" : 289, - "comment" : "Signature encoding contains incorrect types: r=empty list, s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30053000020100", - "result" : "invalid" - }, - { - "tcId" : 290, - "comment" : "Signature encoding contains incorrect types: r=list containing 0, s=0", - "flags" : [ - "InvalidTypesInSignature" - ], - "msg" : "313233343030", - "sig" : "30083003020100020100", - "result" : "invalid" - }, - { - "tcId" : 291, - "comment" : "Edge case for Shamir multiplication", - "flags" : [ - "EdgeCaseShamirMultiplication" - ], - "msg" : "3235353835", - "sig" : "3045022100dd1b7d09a7bd8218961034a39a87fecf5314f00c4d25eb58a07ac85e85eab516022035138c401ef8d3493d65c9002fe62b43aee568731b744548358996d9cc427e06", - "result" : "valid" - }, - { - "tcId" : 292, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "343236343739373234", - "sig" : "304502210095c29267d972a043d955224546222bba343fc1d4db0fec262a33ac61305696ae02206edfe96713aed56f8a28a6653f57e0b829712e5eddc67f34682b24f0676b2640", - "result" : "valid" - }, - { - "tcId" : 293, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "37313338363834383931", - "sig" : "3044022028f94a894e92024699e345fe66971e3edcd050023386135ab3939d550898fb25022032963e5bd41fa5911ed8f37deb86dae0a762bb6121c894615083c5d95ea01db3", - "result" : "valid" - }, - { - "tcId" : 294, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "3130333539333331363638", - "sig" : "3045022100be26b18f9549f89f411a9b52536b15aa270b84548d0e859a1952a27af1a77ac6022070c1d4fa9cd03cc8eaa8d506edb97eed7b8358b453c88aefbb880a3f0e8d472f", - "result" : "valid" - }, - { - "tcId" : 295, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33393439343031323135", - "sig" : "3045022100b1a4b1478e65cc3eafdf225d1298b43f2da19e4bcff7eacc0a2e98cd4b74b1140220179aa31e304cc142cf5073171751b28f3f5e0fa88c994e7c55f1bc07b8d56c16", - "result" : "valid" - }, - { - "tcId" : 296, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31333434323933303739", - "sig" : "30440220325332021261f1bd18f2712aa1e2252da23796da8a4b1ff6ea18cafec7e171f2022040b4f5e287ee61fc3c804186982360891eaa35c75f05a43ecd48b35d984a6648", - "result" : "valid" - }, - { - "tcId" : 297, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33373036323131373132", - "sig" : "3045022100a23ad18d8fc66d81af0903890cbd453a554cb04cdc1a8ca7f7f78e5367ed88a0022023e3eb2ce1c04ea748c389bd97374aa9413b9268851c04dcd9f88e78813fee56", - "result" : "valid" - }, - { - "tcId" : 298, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "333433363838373132", - "sig" : "304402202bdea41cda63a2d14bf47353bd20880a690901de7cd6e3cc6d8ed5ba0cdb109102203cea66bccfc9f9bf8c7ca4e1c1457cc9145e13e936d90b3d9c7786b8b26cf4c7", - "result" : "valid" - }, - { - "tcId" : 299, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31333531353330333730", - "sig" : "3045022100d7cd76ec01c1b1079eba9e2aa2a397243c4758c98a1ba0b7404a340b9b00ced602203575001e19d922e6de8b3d6c84ea43b5c3338106cf29990134e7669a826f78e6", - "result" : "valid" - }, - { - "tcId" : 300, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "36353533323033313236", - "sig" : "3045022100a872c744d936db21a10c361dd5c9063355f84902219652f6fc56dc95a7139d960220400df7575d9756210e9ccc77162c6b593c7746cfb48ac263c42750b421ef4bb9", - "result" : "valid" - }, - { - "tcId" : 301, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31353634333436363033", - "sig" : "30450221009fa9afe07752da10b36d3afcd0fe44bfc40244d75203599cf8f5047fa3453854022050e0a7c013bfbf51819736972d44b4b56bc2a2b2c180df6ec672df171410d77a", - "result" : "valid" - }, - { - "tcId" : 302, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "34343239353339313137", - "sig" : "3045022100885640384d0d910efb177b46be6c3dc5cac81f0b88c3190bb6b5f99c2641f2050220738ed9bff116306d9caa0f8fc608be243e0b567779d8dab03e8e19d553f1dc8e", - "result" : "valid" - }, - { - "tcId" : 303, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "3130393533323631333531", - "sig" : "304402202d051f91c5a9d440c5676985710483bc4f1a6c611b10c95a2ff0363d90c2a45802206ddf94e6fba5be586833d0c53cf216ad3948f37953c26c1cf4968e9a9e8243dc", - "result" : "valid" - }, - { - "tcId" : 304, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "35393837333530303431", - "sig" : "3045022100f3ac2523967482f53d508522712d583f4379cd824101ff635ea0935117baa54f022027f10812227397e02cea96fb0e680761636dab2b080d1fc5d11685cbe8500cfe", - "result" : "valid" - }, - { - "tcId" : 305, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33343633303036383738", - "sig" : "304502210096447cf68c3ab7266ed7447de3ac52fed7cc08cbdfea391c18a9b8ab370bc91302200f5e7874d3ac0e918f01c885a1639177c923f8660d1ceba1ca1f301bc675cdbc", - "result" : "valid" - }, - { - "tcId" : 306, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "39383137333230323837", - "sig" : "30440220530a0832b691da0b5619a0b11de6877f3c0971baaa68ed122758c29caaf46b7202206c89e44f5eb33060ea4b46318c39138eaedec72de42ba576579a6a4690e339f3", - "result" : "valid" - }, - { - "tcId" : 307, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33323232303431303436", - "sig" : "30450221009c54c25500bde0b92d72d6ec483dc2482f3654294ca74de796b681255ed58a770220677453c6b56f527631c9f67b3f3eb621fd88582b4aff156d2f1567d6211a2a33", - "result" : "valid" - }, - { - "tcId" : 308, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "36363636333037313034", - "sig" : "3045022100e7909d41439e2f6af29136c7348ca2641a2b070d5b64f91ea9da7070c7a2618b022042d782f132fa1d36c2c88ba27c3d678d80184a5d1eccac7501f0b47e3d205008", - "result" : "valid" - }, - { - "tcId" : 309, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31303335393531383938", - "sig" : "304402205924873209593135a4c3da7bb381227f8a4b6aa9f34fe5bb7f8fbc131a039ffe02201f1bb11b441c8feaa40f44213d9a405ed792d59fb49d5bcdd9a4285ae5693022", - "result" : "valid" - }, - { - "tcId" : 310, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31383436353937313935", - "sig" : "3045022100eeb692c9b262969b231c38b5a7f60649e0c875cd64df88f33aa571fa3d29ab0e0220218b3a1eb06379c2c18cf51b06430786d1c64cd2d24c9b232b23e5bac7989acd", - "result" : "valid" - }, - { - "tcId" : 311, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33313336303436313839", - "sig" : "3045022100a40034177f36091c2b653684a0e3eb5d4bff18e4d09f664c2800e7cafda1daf802203a3ec29853704e52031c58927a800a968353adc3d973beba9172cbbeab4dd149", - "result" : "valid" - }, - { - "tcId" : 312, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "32363633373834323534", - "sig" : "3045022100b5d795cc75cea5c434fa4185180cd6bd21223f3d5a86da6670d71d95680dadbf022054e4d8810a001ecbb9f7ca1c2ebfdb9d009e9031a431aca3c20ab4e0d1374ec1", - "result" : "valid" - }, - { - "tcId" : 313, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31363532313030353234", - "sig" : "3044022007dc2478d43c1232a4595608c64426c35510051a631ae6a5a6eb1161e57e42e102204a59ea0fdb72d12165cea3bf1ca86ba97517bd188db3dbd21a5a157850021984", - "result" : "valid" - }, - { - "tcId" : 314, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "35373438303831363936", - "sig" : "3045022100ddd20c4a05596ca868b558839fce9f6511ddd83d1ccb53f82e5269d559a0155202205b91734729d93093ff22123c4a25819d7feb66a250663fc780cb66fc7b6e6d17", - "result" : "valid" - }, - { - "tcId" : 315, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "36333433393133343638", - "sig" : "30450221009cde6e0ede0a003f02fda0a01b59facfe5dec063318f279ce2de7a9b1062f7b702202886a5b8c679bdf8224c66f908fd6205492cb70b0068d46ae4f33a4149b12a52", - "result" : "valid" - }, - { - "tcId" : 316, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31353431313033353938", - "sig" : "3045022100c5771016d0dd6357143c89f684cd740423502554c0c59aa8c99584f1ff38f609022054b405f4477546686e464c5463b4fd4190572e58d0f7e7357f6e61947d20715c", - "result" : "valid" - }, - { - "tcId" : 317, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "3130343738353830313238", - "sig" : "3045022100a24ebc0ec224bd67ae397cbe6fa37b3125adbd34891abe2d7c7356921916dfe6022034f6eb6374731bbbafc4924fb8b0bdcdda49456d724cdae6178d87014cb53d8c", - "result" : "valid" - }, - { - "tcId" : 318, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "3130353336323835353638", - "sig" : "304402202557d64a7aee2e0931c012e4fea1cd3a2c334edae68cdeb7158caf21b68e5a2402207f06cdbb6a90023a973882ed97b080fe6b05af3ec93db6f1a4399a69edf7670d", - "result" : "valid" - }, - { - "tcId" : 319, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "393533393034313035", - "sig" : "3045022100c4f2eccbb6a24350c8466450b9d61b207ee359e037b3dcedb42a3f2e6dd6aeb502203263c6b59a2f55cdd1c6e14894d5e5963b28bc3e2469ac9ba1197991ca7ff9c7", - "result" : "valid" - }, - { - "tcId" : 320, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "393738383438303339", - "sig" : "3045022100eff04781c9cbcd162d0a25a6e2ebcca43506c523385cb515d49ea38a1b12fcad022015acd73194c91a95478534f23015b672ebed213e45424dd2c8e26ac8b3eb34a5", - "result" : "valid" - }, - { - "tcId" : 321, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33363130363732343432", - "sig" : "3045022100f58b4e3110a64bf1b5db97639ee0e5a9c8dfa49dc59b679891f520fdf0584c8702202cd8fe51888aee9db3e075440fd4db73b5c732fb87b510e97093d66415f62af7", - "result" : "valid" - }, - { - "tcId" : 322, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31303534323430373035", - "sig" : "3045022100f8abecaa4f0c502de4bf5903d48417f786bf92e8ad72fec0bd7fcb7800c0bbe302204c7f9e231076a30b7ae36b0cebe69ccef1cd194f7cce93a5588fd6814f437c0e", - "result" : "valid" - }, - { - "tcId" : 323, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "35313734343438313937", - "sig" : "304402205d5b38bd37ad498b2227a633268a8cca879a5c7c94a4e416bd0a614d09e606d2022012b8d664ea9991062ecbb834e58400e25c46007af84f6007d7f1685443269afe", - "result" : "valid" - }, - { - "tcId" : 324, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31393637353631323531", - "sig" : "304402200c1cd9fe4034f086a2b52d65b9d3834d72aebe7f33dfe8f976da82648177d8e3022013105782e3d0cfe85c2778dec1a848b27ac0ae071aa6da341a9553a946b41e59", - "result" : "valid" - }, - { - "tcId" : 325, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33343437323533333433", - "sig" : "3045022100ae7935fb96ff246b7b5d5662870d1ba587b03d6e1360baf47988b5c02ccc1a5b02205f00c323272083782d4a59f2dfd65e49de0693627016900ef7e61428056664b3", - "result" : "valid" - }, - { - "tcId" : 326, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "333638323634333138", - "sig" : "3044022000a134b5c6ccbcefd4c882b945baeb4933444172795fa6796aae1490675470980220566e46105d24d890151e3eea3ebf88f5b92b3f5ec93a217765a6dcbd94f2c55b", - "result" : "valid" - }, - { - "tcId" : 327, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33323631313938363038", - "sig" : "304402202e4721363ad3992c139e5a1c26395d2c2d777824aa24fde075e0d7381171309d0220740f7c494418e1300dd4512f782a58800bff6a7abdfdd20fbbd4f05515ca1a4f", - "result" : "valid" - }, - { - "tcId" : 328, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "39363738373831303934", - "sig" : "304402206852e9d3cd9fe373c2d504877967d365ab1456707b6817a042864694e1960ccf0220064b27ea142b30887b84c86adccb2fa39a6911ad21fc7e819f593be52bc4f3bd", - "result" : "valid" - }, - { - "tcId" : 329, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "34393538383233383233", - "sig" : "30440220188a8c5648dc79eace158cf886c62b5468f05fd95f03a7635c5b4c31f09af4c5022036361a0b571a00c6cd5e686ccbfcfa703c4f97e48938346d0c103fdc76dc5867", - "result" : "valid" - }, - { - "tcId" : 330, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "383234363337383337", - "sig" : "3045022100a74f1fb9a8263f62fc4416a5b7d584f4206f3996bb91f6fc8e73b9e92bad0e1302206815032e8c7d76c3ab06a86f33249ce9940148cb36d1f417c2e992e801afa3fa", - "result" : "valid" - }, - { - "tcId" : 331, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "3131303230383333373736", - "sig" : "3044022007244865b72ff37e62e3146f0dc14682badd7197799135f0b00ade7671742bfe02200d80c2238edb4e4a7a86a8c57ca9af1711f406f7f5da0299aa04e2932d960754", - "result" : "valid" - }, - { - "tcId" : 332, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "313333383731363438", - "sig" : "3045022100da7fdd05b5badabd619d805c4ee7d9a84f84ddd5cf9c5bf4d4338140d689ef08022028f1cf4fa1c3c5862cfa149c0013cf5fe6cf5076cae000511063e7de25bb38e5", - "result" : "valid" - }, - { - "tcId" : 333, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "333232313434313632", - "sig" : "3045022100d3027c656f6d4fdfd8ede22093e3c303b0133c340d615e7756f6253aea927238022009aef060c8e4cef972974011558df144fed25ca69ae8d0b2eaf1a8feefbec417", - "result" : "valid" - }, - { - "tcId" : 334, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "3130363836363535353436", - "sig" : "304402200bf6c0188dc9571cd0e21eecac5fbb19d2434988e9cc10244593ef3a98099f6902204864a562661f9221ec88e3dd0bc2f6e27ac128c30cc1a80f79ec670a22b042ee", - "result" : "valid" - }, - { - "tcId" : 335, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "3632313535323436", - "sig" : "3045022100ae459640d5d1179be47a47fa538e16d94ddea5585e7a244804a51742c686443a02206c8e30e530a634fae80b3ceb062978b39edbe19777e0a24553b68886181fd897", - "result" : "valid" - }, - { - "tcId" : 336, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "37303330383138373734", - "sig" : "304402201cf3517ba3bf2ab8b9ead4ebb6e866cb88a1deacb6a785d3b63b483ca02ac4950220249a798b73606f55f5f1c70de67cb1a0cff95d7dc50b3a617df861bad3c6b1c9", - "result" : "valid" - }, - { - "tcId" : 337, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "35393234353233373434", - "sig" : "3045022100e69b5238265ea35d77e4dd172288d8cea19810a10292617d5976519dc5757cb802204b03c5bc47e826bdb27328abd38d3056d77476b2130f3df6ec4891af08ba1e29", - "result" : "valid" - }, - { - "tcId" : 338, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31343935353836363231", - "sig" : "304402205f9d7d7c870d085fc1d49fff69e4a275812800d2cf8973e7325866cb40fa2b6f02206d1f5491d9f717a597a15fd540406486d76a44697b3f0d9d6dcef6669f8a0a56", - "result" : "valid" - }, - { - "tcId" : 339, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "34303035333134343036", - "sig" : "304402200a7d5b1959f71df9f817146ee49bd5c89b431e7993e2fdecab6858957da685ae02200f8aad2d254690bdc13f34a4fec44a02fd745a422df05ccbb54635a8b86b9609", - "result" : "valid" - }, - { - "tcId" : 340, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "33303936343537353132", - "sig" : "3044022079e88bf576b74bc07ca142395fda28f03d3d5e640b0b4ff0752c6d94cd553408022032cea05bd2d706c8f6036a507e2ab7766004f0904e2e5c5862749c0073245d6a", - "result" : "valid" - }, - { - "tcId" : 341, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "32373834303235363230", - "sig" : "30450221009d54e037a00212b377bc8874798b8da080564bbdf7e07591b861285809d01488022018b4e557667a82bd95965f0706f81a29243fbdd86968a7ebeb43069db3b18c7f", - "result" : "valid" - }, - { - "tcId" : 342, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "32363138373837343138", - "sig" : "304402202664f1ffa982fedbcc7cab1b8bc6e2cb420218d2a6077ad08e591ba9feab33bd022049f5c7cb515e83872a3d41b4cdb85f242ad9d61a5bfc01debfbb52c6c84ba728", - "result" : "valid" - }, - { - "tcId" : 343, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "31363432363235323632", - "sig" : "304402205827518344844fd6a7de73cbb0a6befdea7b13d2dee4475317f0f18ffc81524b02204f5ccb4e0b488b5a5d760aacddb2d791970fe43da61eb30e2e90208a817e46db", - "result" : "valid" - }, - { - "tcId" : 344, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "36383234313839343336", - "sig" : "304502210097ab19bd139cac319325869218b1bce111875d63fb12098a04b0cd59b6fdd3a30220431d9cea3a243847303cebda56476431d034339f31d785ee8852db4f040d4921", - "result" : "valid" - }, - { - "tcId" : 345, - "comment" : "special case hash", - "flags" : [ - "SpecialCaseHash" - ], - "msg" : "343834323435343235", - "sig" : "3044022052c683144e44119ae2013749d4964ef67509278f6d38ba869adcfa69970e123d02203479910167408f45bda420a626ec9c4ec711c1274be092198b4187c018b562ca", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", - "wx" : "07310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc362", - "wy" : "26a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000407310f90a9eae149a08402f54194a0f7b4ac427bf8d9bd6c7681071dc47dc36226a6d37ac46d61fd600c0bf1bff87689ed117dda6b0e59318ae010a197a26ca0", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEBzEPkKnq4UmghAL1QZSg97SsQnv42b1s\ndoEHHcR9w2ImptN6xG1h/WAMC/G/+HaJ7RF92msOWTGK4BChl6JsoA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 346, - "comment" : "k*G has a large x-coordinate", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "30160211014551231950b75fc4402da1722fc9baeb020103", - "result" : "valid" - }, - { - "tcId" : 347, - "comment" : "r too large", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c020103", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", - "wx" : "00bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22", - "wy" : "705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bc97e7585eecad48e16683bc4091708e1a930c683fc47001d4b383594f2c4e22705989cf69daeadd4e4e4b8151ed888dfec20fb01728d89d56b3f38f2ae9c8c5", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvJfnWF7srUjhZoO8QJFwjhqTDGg/xHAB\n1LODWU8sTiJwWYnPadrq3U5OS4FR7YiN/sIPsBco2J1Ws/OPKunIxQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 348, - "comment" : "r,s are large", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f020103", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", - "wx" : "44ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252", - "wy" : "00b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000444ad339afbc21e9abf7b602a5ca535ea378135b6d10d81310bdd8293d1df3252b63ff7d0774770f8fe1d1722fa83acd02f434e4fc110a0cc8f6dddd37d56c463", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERK0zmvvCHpq/e2AqXKU16jeBNbbRDYEx\nC92Ck9HfMlK2P/fQd0dw+P4dFyL6g6zQL0NOT8EQoMyPbd3TfVbEYw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 349, - "comment" : "r and s^-1 have a large Hamming weight", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203e9a7582886089c62fb840cf3b83061cd1cff3ae4341808bb5bdee6191174177", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", - "wx" : "1260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c", - "wy" : "5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041260c2122c9e244e1af5151bede0c3ae23b54d7c596881d3eebad21f37dd878c5c9a0c1a9ade76737a8811bd6a7f9287c978ee396aa89c11e47229d2ccb552f0", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEmDCEiyeJE4a9RUb7eDDriO1TXxZaIHT\n7rrSHzfdh4xcmgwamt52c3qIEb1qf5KHyXjuOWqonBHkcinSzLVS8A==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 350, - "comment" : "r and s^-1 have a large Hamming weight", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022024238e70b431b1a64efdf9032669939d4b77f249503fc6905feb7540dea3e6d2", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", - "wx" : "1877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce", - "wy" : "00821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041877045be25d34a1d0600f9d5c00d0645a2a54379b6ceefad2e6bf5c2a3352ce821a532cc1751ee1d36d41c3d6ab4e9b143e44ec46d73478ea6a79a5c0e54159", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGHcEW+JdNKHQYA+dXADQZFoqVDebbO76\n0ua/XCozUs6CGlMswXUe4dNtQcPWq06bFD5E7EbXNHjqanmlwOVBWQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 351, - "comment" : "small r and s", - "flags" : [ - "SmallRandS", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3006020101020101", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", - "wx" : "455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50", - "wy" : "00aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004455439fcc3d2deeceddeaece60e7bd17304f36ebb602adf5a22e0b8f1db46a50aec38fb2baf221e9a8d1887c7bf6222dd1834634e77263315af6d23609d04f77", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERVQ5/MPS3uzt3q7OYOe9FzBPNuu2Aq31\noi4Ljx20alCuw4+yuvIh6ajRiHx79iIt0YNGNOdyYzFa9tI2CdBPdw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 352, - "comment" : "small r and s", - "flags" : [ - "SmallRandS", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3006020101020102", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", - "wx" : "2e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece718", - "wy" : "0449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042e1f466b024c0c3ace2437de09127fed04b706f94b19a21bb1c2acf35cece7180449ae3523d72534e964972cfd3b38af0bddd9619e5af223e4d1a40f34cf9f1d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELh9GawJMDDrOJDfeCRJ/7QS3BvlLGaIb\nscKs81zs5xgESa41I9clNOlklyz9OzivC93ZYZ5a8iPk0aQPNM+fHQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 353, - "comment" : "small r and s", - "flags" : [ - "SmallRandS", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3006020101020103", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "048e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a2337326ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3", - "wx" : "008e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a23373", - "wy" : "26ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048e7abdbbd18de7452374c1879a1c3b01d13261e7d4571c3b47a1c76c55a2337326ed897cd517a4f5349db809780f6d2f2b9f6299d8b5a89077f1119a718fd7b3", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjnq9u9GN50UjdMGHmhw7AdEyYefUVxw7\nR6HHbFWiM3Mm7Yl81Rek9TSduAl4D20vK59imdi1qJB38RGacY/Xsw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 354, - "comment" : "small r and s", - "flags" : [ - "SmallRandS", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3006020102020101", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "047b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af1942117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b", - "wx" : "7b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af19", - "wy" : "42117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200047b333d4340d3d718dd3e6aff7de7bbf8b72bfd616c8420056052842376b9af1942117c5afeac755d6f376fc6329a7d76051b87123a4a5d0bc4a539380f03de7b", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEezM9Q0DT1xjdPmr/fee7+Lcr/WFshCAF\nYFKEI3a5rxlCEXxa/qx1XW83b8Yymn12BRuHEjpKXQvEpTk4DwPeew==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 355, - "comment" : "small r and s", - "flags" : [ - "SmallRandS", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3006020102020102", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e503a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff", - "wx" : "00d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e5", - "wy" : "03a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d30ca4a0ddb6616c851d30ced682c40f83c62758a1f2759988d6763a88f1c0e503a80d5415650d41239784e8e2fb1235e9fe991d112ebb81186cbf0da2de3aff", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0wykoN22YWyFHTDO1oLED4PGJ1ih8nWZ\niNZ2OojxwOUDqA1UFWUNQSOXhOji+xI16f6ZHREuu4EYbL8Not46/w==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 356, - "comment" : "small r and s", - "flags" : [ - "SmallRandS", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3006020102020103", - "result" : "valid" - }, - { - "tcId" : 357, - "comment" : "r is larger than n", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3026022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143020103", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0448969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec", - "wx" : "48969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24", - "wy" : "00b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000448969b39991297b332a652d3ee6e01e909b39904e71fa2354a7830c7750baf24b4012d1b830d199ccb1fc972b32bfded55f09cd62d257e5e844e27e57a1594ec", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAESJabOZkSl7MyplLT7m4B6QmzmQTnH6I1\nSngwx3ULryS0AS0bgw0ZnMsfyXKzK/3tVfCc1i0lfl6ETiflehWU7A==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 358, - "comment" : "s is larger than n", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "30080201020203ed2979", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", - "wx" : "02ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee77", - "wy" : "7eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000402ef4d6d6cfd5a94f1d7784226e3e2a6c0a436c55839619f38fb4472b5f9ee777eb4acd4eebda5cd72875ffd2a2f26229c2dc6b46500919a432c86739f3ae866", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAu9NbWz9WpTx13hCJuPipsCkNsVYOWGf\nOPtEcrX57nd+tKzU7r2lzXKHX/0qLyYinC3GtGUAkZpDLIZznzroZg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 359, - "comment" : "small r and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "30260202010102203a74e9d3a74e9d3a74e9d3a74e9d3a749f8ab3732a0a89604a09bce5b2916da4", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", - "wx" : "464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584", - "wy" : "00b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004464f4ff715729cae5072ca3bd801d3195b67aec65e9b01aad20a2943dcbcb584b1afd29d31a39a11d570aa1597439b3b2d1971bf2f1abf15432d0207b10d1d08", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERk9P9xVynK5Qcso72AHTGVtnrsZemwGq\n0gopQ9y8tYSxr9KdMaOaEdVwqhWXQ5s7LRlxvy8avxVDLQIHsQ0dCA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 360, - "comment" : "smallish r and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "302b02072d9b4d347952cc02200343aefc2f25d98b882e86eb9e30d55a6eb508b516510b34024ae4b6362330b3", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", - "wx" : "157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4c", - "wy" : "00deadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004157f8fddf373eb5f49cfcf10d8b853cf91cbcd7d665c3522ba7dd738ddb79a4cdeadf1a5c448ea3c9f4191a8999abfcc757ac6d64567ef072c47fec613443b8f", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEFX+P3fNz619Jz88Q2LhTz5HLzX1mXDUi\nun3XON23mkzerfGlxEjqPJ9BkaiZmr/MdXrG1kVn7wcsR/7GE0Q7jw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 361, - "comment" : "100-bit r and small s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3031020d1033e67e37b32b445580bf4efc02206f906f906f906f906f906f906f906f8fe1cab5eefdb214061dce3b22789f1d6f", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", - "wx" : "0934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0", - "wy" : "00d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200040934a537466c07430e2c48feb990bb19fb78cecc9cee424ea4d130291aa237f0d4f92d23b462804b5b68c52558c01c9996dbf727fccabbeedb9621a400535afa", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAECTSlN0ZsB0MOLEj+uZC7Gft4zsyc7kJO\npNEwKRqiN/DU+S0jtGKAS1toxSVYwByZltv3J/zKu+7bliGkAFNa+g==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 362, - "comment" : "small r and 100 bit s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3026020201010220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", - "wx" : "00d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c65", - "wy" : "4a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d6ef20be66c893f741a9bf90d9b74675d1c2a31296397acb3ef174fd0b300c654a0c95478ca00399162d7f0f2dc89efdc2b28a30fbabe285857295a4b0c4e265", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1u8gvmbIk/dBqb+Q2bdGddHCoxKWOXrL\nPvF0/QswDGVKDJVHjKADmRYtfw8tyJ79wrKKMPur4oWFcpWksMTiZQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 363, - "comment" : "100-bit r and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3031020d062522bbd3ecbe7c39e93e7c260220783266e90f43dafe5cd9b3b0be86de22f9de83677d0f50713a468ec72fcf5d57", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", - "wx" : "00b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee06", - "wy" : "29c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004b7291d1404e0c0c07dab9372189f4bd58d2ceaa8d15ede544d9514545ba9ee0629c9a63d5e308769cc30ec276a410e6464a27eeafd9e599db10f053a4fe4a829", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEtykdFATgwMB9q5NyGJ9L1Y0s6qjRXt5U\nTZUUVFup7gYpyaY9XjCHacww7CdqQQ5kZKJ+6v2eWZ2xDwU6T+SoKQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 364, - "comment" : "r and s^-1 are close to n", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3045022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c1022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "046e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6", - "wx" : "6e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8", - "wy" : "186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e28303305d642ccb923b722ea86b2a0bc8e3735ecb26e849b19c9f76b2fdbb8186e80d64d8cab164f5238f5318461bf89d4d96ee6544c816c7566947774e0f6", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbigwMwXWQsy5I7ci6oayoLyONzXssm6E\nmxnJ92sv27gYboDWTYyrFk9SOPUxhGG/idTZbuZUTIFsdWaUd3Tg9g==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 365, - "comment" : "r and s are 64-bit integer", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "30160209009c44febf31c3594d020900839ed28247c2b06b", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd", - "wx" : "375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9", - "wy" : "00a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004375bda93f6af92fb5f8f4b1b5f0534e3bafab34cb7ad9fb9d0b722e4a5c302a9a00b9f387a5a396097aa2162fc5bbcf4a5263372f681c94da51e9799120990fd", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEN1vak/avkvtfj0sbXwU047r6s0y3rZ+5\n0Lci5KXDAqmgC584elo5YJeqIWL8W7z0pSYzcvaByU2lHpeZEgmQ/Q==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 366, - "comment" : "r and s are 100-bit integer", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "301e020d09df8b682430beef6f5fd7c7cf020d0fd0a62e13778f4222a0d61c8a", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44", - "wx" : "00d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197", - "wy" : "00da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d75b68216babe03ae257e94b4e3bf1c52f44e3df266d1524ff8c5ea69da73197da4bff9ed1c53f44917a67d7b978598e89df359e3d5913eaea24f3ae259abc44", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE11toIWur4DriV+lLTjvxxS9E498mbRUk\n/4xepp2nMZfaS/+e0cU/RJF6Z9e5eFmOid81nj1ZE+rqJPOuJZq8RA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 367, - "comment" : "r and s are 128-bit integer", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "30260211008a598e563a89f526c32ebec8de26367a02110084f633e2042630e99dd0f1e16f7a04bf", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0478bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e", - "wx" : "78bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653", - "wy" : "118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000478bcda140aed23d430cb23c3dc0d01f423db134ee94a3a8cb483f2deac2ac653118114f6f33045d4e9ed9107085007bfbddf8f58fe7a1a2445d66a990045476e", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeLzaFArtI9QwyyPD3A0B9CPbE07pSjqM\ntIPy3qwqxlMRgRT28zBF1OntkQcIUAe/vd+PWP56GiRF1mqZAEVHbg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 368, - "comment" : "r and s are 160-bit integer", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "302e021500aa6eeb5823f7fa31b466bb473797f0d0314c0bdf021500e2977c479e6d25703cebbc6bd561938cc9d1bfb9", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", - "wx" : "00bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c", - "wy" : "1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bb79f61857f743bfa1b6e7111ce4094377256969e4e15159123d9548acc3be6c1f9d9f8860dcffd3eb36dd6c31ff2e7226c2009c4c94d8d7d2b5686bf7abd677", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEu3n2GFf3Q7+htucRHOQJQ3claWnk4VFZ\nEj2VSKzDvmwfnZ+IYNz/0+s23Wwx/y5yJsIAnEyU2NfStWhr96vWdw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 369, - "comment" : "s == 1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020101", - "result" : "valid" - }, - { - "tcId" : 370, - "comment" : "s == 0", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3025022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1020100", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0493591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518", - "wx" : "0093591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36", - "wy" : "073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000493591827d9e6713b4e9faea62c72b28dfefa68e0c05160b5d6aae88fd2e36c36073f5545ad5af410af26afff68654cf72d45e493489311203247347a890f4518", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEk1kYJ9nmcTtOn66mLHKyjf76aODAUWC1\n1qroj9LjbDYHP1VFrVr0EK8mr/9oZUz3LUXkk0iTESAyRzR6iQ9FGA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 371, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220419d981c515af8cc82545aac0c85e9e308fbb2eab6acd7ed497e0b4145a18fd9", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0431ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0dada01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f", - "wx" : "31ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0da", - "wy" : "00da01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000431ed3081aefe001eb6402069ee2ccc1862937b85995144dba9503943587bf0dada01b8cc4df34f5ab3b1a359615208946e5ee35f98ee775b8ccecd86ccc1650f", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMe0wga7+AB62QCBp7izMGGKTe4WZUUTb\nqVA5Q1h78NraAbjMTfNPWrOxo1lhUgiUbl7jX5jud1uMzs2GzMFlDw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 372, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102201b21717ad71d23bbac60a9ad0baf75b063c9fdf52a00ebf99d022172910993c9", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "047dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea854c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4", - "wx" : "7dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea8", - "wy" : "54c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200047dff66fa98509ff3e2e51045f4390523dccda43a3bc2885e58c248090990eea854c76c2b9adeb6bb571823e07fd7c65c8639cf9d905260064c8e7675ce6d98b4", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEff9m+phQn/Pi5RBF9DkFI9zNpDo7wohe\nWMJICQmQ7qhUx2wrmt62u1cYI+B/18ZchjnPnZBSYAZMjnZ1zm2YtA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 373, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102202f588f66018f3dd14db3e28e77996487e32486b521ed8e5a20f06591951777e9", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "044280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1", - "wx" : "4280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a", - "wy" : "2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200044280509aab64edfc0b4a2967e4cbce849cb544e4a77313c8e6ece579fbd7420a2e89fe5cc1927d554e6a3bb14033ea7c922cd75cba2c7415fdab52f20b1860f1", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEQoBQmqtk7fwLSiln5MvOhJy1ROSncxPI\n5uzlefvXQgouif5cwZJ9VU5qO7FAM+p8kizXXLosdBX9q1LyCxhg8Q==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 374, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220091a08870ff4daf9123b30c20e8c4fc8505758dcf4074fcaff2170c9bfcf74f4", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "044f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db", - "wx" : "4f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb", - "wy" : "2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200044f8df145194e3c4fc3eea26d43ce75b402d6b17472ddcbb254b8a79b0bf3d9cb2aa20d82844cb266344e71ca78f2ad27a75a09e5bc0fa57e4efd9d465a0888db", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAET43xRRlOPE/D7qJtQ851tALWsXRy3cuy\nVLinmwvz2csqog2ChEyyZjROccp48q0np1oJ5bwPpX5O/Z1GWgiI2w==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 375, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102207c370dc0ce8c59a8b273cba44a7c1191fc3186dc03cab96b0567312df0d0b250", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "049598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207", - "wx" : "009598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14", - "wy" : "122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200049598a57dd67ec3e16b587a338aa3a10a3a3913b41a3af32e3ed3ff01358c6b14122819edf8074bbc521f7d4cdce82fef7a516706affba1d93d9dea9ccae1a207", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElZilfdZ+w+FrWHoziqOhCjo5E7QaOvMu\nPtP/ATWMaxQSKBnt+AdLvFIffUzc6C/velFnBq/7odk9neqcyuGiBw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 376, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022070b59a7d1ee77a2f9e0491c2a7cfcd0ed04df4a35192f6132dcc668c79a6160e", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "049171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330", - "wx" : "009171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e", - "wy" : "634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200049171fec3ca20806bc084f12f0760911b60990bd80e5b2a71ca03a048b20f837e634fd17863761b2958d2be4e149f8d3d7abbdc18be03f451ab6c17fa0a1f8330", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkXH+w8oggGvAhPEvB2CRG2CZC9gOWypx\nygOgSLIPg35jT9F4Y3YbKVjSvk4Un409ervcGL4D9FGrbBf6Ch+DMA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 377, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102202736d76e412246e097148e2bf62915614eb7c428913a58eb5e9cd4674a9423de", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d", - "wx" : "777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9", - "wy" : "00ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004777c8930b6e1d271100fe68ce93f163fa37612c5fff67f4a62fc3bafaf3d17a9ed73d86f60a51b5ed91353a3b054edc0aa92c9ebcbd0b75d188fdc882791d68d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEd3yJMLbh0nEQD+aM6T8WP6N2EsX/9n9K\nYvw7r689F6ntc9hvYKUbXtkTU6OwVO3AqpLJ68vQt10Yj9yIJ5HWjQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 378, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102204a1e12831fbe93627b02d6e7f24bccdd6ef4b2d0f46739eaf3b1eaf0ca117770", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf4700603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000", - "wx" : "00eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf470", - "wy" : "0603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004eabc248f626e0a63e1eb81c43d461a39a1dba881eb6ee2152b07c32d71bcf4700603caa8b9d33db13af44c6efbec8a198ed6124ac9eb17eaafd2824a545ec000", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE6rwkj2JuCmPh64HEPUYaOaHbqIHrbuIV\nKwfDLXG89HAGA8qoudM9sTr0TG777IoZjtYSSsnrF+qv0oJKVF7AAA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 379, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022006c778d4dfff7dee06ed88bc4e0ed34fc553aad67caf796f2a1c6487c1b2e877", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "049f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73", - "wx" : "009f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001", - "wy" : "00f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200049f7a13ada158a55f9ddf1a45f044f073d9b80030efdcfc9f9f58418fbceaf001f8ada0175090f80d47227d6713b6740f9a0091d88a837d0a1cd77b58a8f28d73", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEn3oTraFYpV+d3xpF8ETwc9m4ADDv3Pyf\nn1hBj7zq8AH4raAXUJD4DUcifWcTtnQPmgCR2IqDfQoc13tYqPKNcw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 380, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102204de459ef9159afa057feb3ec40fef01c45b809f4ab296ea48c206d4249a2b451", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0411c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4dbbbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb", - "wx" : "11c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4db", - "wy" : "00bbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000411c4f3e461cd019b5c06ea0cea4c4090c3cc3e3c5d9f3c6d65b436826da9b4dbbbeb7a77e4cbfda207097c43423705f72c80476da3dac40a483b0ab0f2ead1cb", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEEcTz5GHNAZtcBuoM6kxAkMPMPjxdnzxt\nZbQ2gm2ptNu763p35Mv9ogcJfENCNwX3LIBHbaPaxApIOwqw8urRyw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 381, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c10220745d294978007302033502e1acc48b63ae6500be43adbea1b258d6b423dbb416", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb", - "wx" : "00e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4", - "wy" : "161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004e2e18682d53123aa01a6c5d00b0c623d671b462ea80bddd65227fd5105988aa4161907b3fd25044a949ea41c8e2ea8459dc6f1654856b8b61b31543bb1b45bdb", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE4uGGgtUxI6oBpsXQCwxiPWcbRi6oC93W\nUif9UQWYiqQWGQez/SUESpSepByOLqhFncbxZUhWuLYbMVQ7sbRb2w==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 382, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102207b2a785e3896f59b2d69da57648e80ad3c133a750a2847fd2098ccd902042b6c", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0490f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197dafadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d", - "wx" : "0090f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197da", - "wy" : "00fadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000490f8d4ca73de08a6564aaf005247b6f0ffe978504dce52605f46b7c3e56197dafadbe528eb70d9ee7ea0e70702db54f721514c7b8604ac2cb214f1decb7e383d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkPjUynPeCKZWSq8AUke28P/peFBNzlJg\nX0a3w+Vhl9r62+Uo63DZ7n6g5wcC21T3IVFMe4YErCyyFPHey344PQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 383, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c1022071ae94a72ca896875e7aa4a4c3d29afdb4b35b6996273e63c47ac519256c5eb1", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc", - "wx" : "00824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e", - "wy" : "3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004824c195c73cffdf038d101bce1687b5c3b6146f395c885976f7753b2376b948e3cdefa6fc347d13e4dcbc63a0b03a165180cd2be1431a0cf74ce1ea25082d2bc", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEgkwZXHPP/fA40QG84Wh7XDthRvOVyIWX\nb3dTsjdrlI483vpvw0fRPk3LxjoLA6FlGAzSvhQxoM90zh6iUILSvA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 384, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102200fa527fa7343c0bc9ec35a6278bfbff4d83301b154fc4bd14aee7eb93445b5f9", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "042788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f", - "wx" : "2788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f", - "wy" : "30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042788a52f078eb3f202c4fa73e0d3386faf3df6be856003636f599922d4f5268f30b4f207c919bbdf5e67a8be4265a8174754b3aba8f16e575b77ff4d5a7eb64f", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJ4ilLweOs/ICxPpz4NM4b6899r6FYANj\nb1mZItT1Jo8wtPIHyRm7315nqL5CZagXR1Szq6jxbldbd/9NWn62Tw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 385, - "comment" : "edge case modular inverse", - "flags" : [ - "ModularInverse", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c102206539c0adadd0525ff42622164ce9314348bd0863b4c80e936b23ca0414264671", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", - "wx" : "00d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b4150874", - "wy" : "01b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d533b789a4af890fa7a82a1fae58c404f9a62a50b49adafab349c513b415087401b4171b803e76b34a9861e10f7bc289a066fd01bd29f84c987a10a5fb18c2d4", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE1TO3iaSviQ+nqCofrljEBPmmKlC0mtr6\ns0nFE7QVCHQBtBcbgD52s0qYYeEPe8KJoGb9Ab0p+EyYehCl+xjC1A==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 386, - "comment" : "point at infinity during verify", - "flags" : [ - "PointDuplication", - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", - "wx" : "3a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4", - "wy" : "221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200043a3150798c8af69d1e6e981f3a45402ba1d732f4be8330c5164f49e10ec555b4221bd842bc5e4d97eff37165f60e3998a424d72a450cf95ea477c78287d0343a", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOjFQeYyK9p0ebpgfOkVAK6HXMvS+gzDF\nFk9J4Q7FVbQiG9hCvF5Nl+/zcWX2DjmYpCTXKkUM+V6kd8eCh9A0Og==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 387, - "comment" : "edge case for signature malleability", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", - "wx" : "3b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e80", - "wy" : "0de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200043b37df5fb347c69a0f17d85c0c7ca83736883a825e13143d0fcfc8101e851e800de3c090b6ca21ba543517330c04b12f948c6badf14a63abffdf4ef8c7537026", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOzffX7NHxpoPF9hcDHyoNzaIOoJeExQ9\nD8/IEB6FHoAN48CQtsohulQ1FzMMBLEvlIxrrfFKY6v/3074x1NwJg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 388, - "comment" : "edge case for signature malleability", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a002207fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", - "wx" : "00feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82c", - "wy" : "00e87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004feb5163b0ece30ff3e03c7d55c4380fa2fa81ee2c0354942ff6f08c99d0cd82ce87de05ee1bda089d3e4e248fa0f721102acfffdf50e654be281433999df897e", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/rUWOw7OMP8+A8fVXEOA+i+oHuLANUlC\n/28IyZ0M2CzofeBe4b2gidPk4kj6D3IRAqz//fUOZUvigUM5md+Jfg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 389, - "comment" : "u1 == 1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", - "wx" : "238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd4149228976", - "wy" : "40683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004238ced001cf22b8853e02edc89cbeca5050ba7e042a7a77f9382cd414922897640683d3094643840f295890aa4c18aa39b41d77dd0fb3bb2700e4f9ec284ffc2", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEI4ztABzyK4hT4C7cicvspQULp+BCp6d/\nk4LNQUkiiXZAaD0wlGQ4QPKViQqkwYqjm0HXfdD7O7JwDk+ewoT/wg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 390, - "comment" : "u1 == n - 1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", - "wx" : "00961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35e", - "wy" : "00d2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004961cf64817c06c0e51b3c2736c922fde18bd8c4906fcd7f5ef66c4678508f35ed2c5d18168cfbe70f2f123bd7419232bb92dd69113e2941061889481c5a027bf", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAElhz2SBfAbA5Rs8JzbJIv3hi9jEkG/Nf1\n72bEZ4UI817SxdGBaM++cPLxI710GSMruS3WkRPilBBhiJSBxaAnvw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 391, - "comment" : "u2 == 1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", - "wx" : "13681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b10288", - "wy" : "16528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000413681eae168cd4ea7cf2e2a45d052742d10a9f64e796867dbdcb829fe0b1028816528760d177376c09df79de39557c329cc1753517acffe8fa2ec298026b8384", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEE2gerhaM1Op88uKkXQUnQtEKn2TnloZ9\nvcuCn+CxAogWUodg0Xc3bAnfed45VXwynMF1NRes/+j6LsKYAmuDhA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 392, - "comment" : "u2 == n - 1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215b8", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", - "wx" : "5aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c2", - "wy" : "0091c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200045aa7abfdb6b4086d543325e5d79c6e95ce42f866d2bb84909633a04bb1aa31c291c80088794905e1da33336d874e2f91ccf45cc59185bede5dd6f3f7acaae18b", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWqer/ba0CG1UMyXl15xulc5C+GbSu4SQ\nljOgS7GqMcKRyACIeUkF4dozM22HTi+RzPRcxZGFvt5d1vP3rKrhiw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 393, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022016e1e459457679df5b9434ae23f474b3e8d2a70bd6b5dbe692ba16da01f1fb0a", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", - "wx" : "277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e4", - "wy" : "64108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000400277791b305a45b2b39590b2f05d3392a6c8182cef4eb540120e0f5c206c3e464108233fb0b8c3ac892d79ef8e0fbf92ed133addb4554270132584dc52eef41", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEACd3kbMFpFsrOVkLLwXTOSpsgYLO9OtU\nASDg9cIGw+RkEIIz+wuMOsiS15744Pv5LtEzrdtFVCcBMlhNxS7vQQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 394, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02201c940f313f92647be257eccd7ed08b0baef3f0478f25871b53635302c5f6314a", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", - "wx" : "6efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1a", - "wy" : "00c75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046efa092b68de9460f0bcc919005a5f6e80e19de98968be3cd2c770a9949bfb1ac75e6e5087d6550d5f9beb1e79e5029307bc255235e2d5dc99241ac3ab886c49", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbvoJK2jelGDwvMkZAFpfboDhnemJaL48\n0sdwqZSb+xrHXm5Qh9ZVDV+b6x555QKTB7wlUjXi1dyZJBrDq4hsSQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 395, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022015d94a85077b493f91cb7101ec63e1b01be58b594e855f45050a8c14062d689b", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", - "wx" : "72d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058", - "wy" : "00e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000472d4a19c4f9d2cf5848ea40445b70d4696b5f02d632c0c654cc7d7eeb0c6d058e8c4cd9943e459174c7ac01fa742198e47e6c19a6bdb0c4f6c237831c1b3f942", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEctShnE+dLPWEjqQERbcNRpa18C1jLAxl\nTMfX7rDG0FjoxM2ZQ+RZF0x6wB+nQhmOR+bBmmvbDE9sI3gxwbP5Qg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 396, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205b1d27a7694c146244a5ad0bd0636d9d9ef3b9fb58385418d9c982105077d1b7", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", - "wx" : "2a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e7402", - "wy" : "58f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042a8ea2f50dcced0c217575bdfa7cd47d1c6f100041ec0e35512794c1be7e740258f8c17122ed303fda7143eb58bede70295b653266013b0b0ebd3f053137f6ec", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEKo6i9Q3M7QwhdXW9+nzUfRxvEABB7A41\nUSeUwb5+dAJY+MFxIu0wP9pxQ+tYvt5wKVtlMmYBOwsOvT8FMTf27A==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 397, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202d85896b3eb9dbb5a52f42f9c9261ed3fc46644ec65f06ade3fd78f257e43432", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", - "wx" : "0088de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b8", - "wy" : "0c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000488de689ce9af1e94be6a2089c8a8b1253ffdbb6c8e9c86249ba220001a4ad3b80c4998e54842f413b9edb1825acbb6335e81e4d184b2b01c8bebdc85d1f28946", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiN5onOmvHpS+aiCJyKixJT/9u2yOnIYk\nm6IgABpK07gMSZjlSEL0E7ntsYJay7YzXoHk0YSysByL69yF0fKJRg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 398, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205b0b12d67d73b76b4a5e85f3924c3da7f88cc89d8cbe0d5bc7faf1e4afc86864", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", - "wx" : "00fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7", - "wy" : "00b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004fea2d31f70f90d5fb3e00e186ac42ab3c1615cee714e0b4e1131b3d4d8225bf7b037a18df2ac15343f30f74067ddf29e817d5f77f8dce05714da59c094f0cda9", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE/qLTH3D5DV+z4A4YasQqs8FhXO5xTgtO\nETGz1NgiW/ewN6GN8qwVND8w90Bn3fKegX1fd/jc4FcU2lnAlPDNqQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 399, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220694c146244a5ad0bd0636d9e12bc9e09e60e68b90d0b5e6c5dddd0cb694d8799", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", - "wx" : "7258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db", - "wy" : "17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200047258911e3d423349166479dbe0b8341af7fbd03d0a7e10edccb36b6ceea5a3db17ac2b8992791128fa3b96dc2fbd4ca3bfa782ef2832fc6656943db18e7346b0", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEcliRHj1CM0kWZHnb4Lg0Gvf70D0KfhDt\nzLNrbO6lo9sXrCuJknkRKPo7ltwvvUyjv6eC7ygy/GZWlD2xjnNGsA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 400, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203d7f487c07bfc5f30846938a3dcef696444707cf9677254a92b06c63ab867d22", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", - "wx" : "4f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914", - "wy" : "00c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200044f28461dea64474d6bb34d1499c97d37b9e95633df1ceeeaacd45016c98b3914c8818810b8cc06ddb40e8a1261c528faa589455d5a6df93b77bc5e0e493c7470", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAETyhGHepkR01rs00Umcl9N7npVjPfHO7q\nrNRQFsmLORTIgYgQuMwG3bQOihJhxSj6pYlFXVpt+Tt3vF4OSTx0cA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 401, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206c7648fc0fbf8a06adb8b839f97b4ff7a800f11b1e37c593b261394599792ba4", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", - "wx" : "74f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66", - "wy" : "00eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000474f2a814fb5d8eca91a69b5e60712732b3937de32829be974ed7b68c5c2f5d66eff0f07c56f987a657f42196205f588c0f1d96fd8a63a5f238b48f478788fe3b", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEdPKoFPtdjsqRppteYHEnMrOTfeMoKb6X\nTte2jFwvXWbv8PB8VvmHplf0IZYgX1iMDx2W/YpjpfI4tI9Hh4j+Ow==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 402, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220641c9c5d790dc09cdd3dfabb62cdf453e69747a7e3d7aa1a714189ef53171a99", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", - "wx" : "195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6a", - "wy" : "00b2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004195b51a7cc4a21b8274a70a90de779814c3c8ca358328208c09a29f336b82d6ab2416b7c92fffdc29c3b1282dd2a77a4d04df7f7452047393d849989c5cee9ad", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGVtRp8xKIbgnSnCpDed5gUw8jKNYMoII\nwJop8za4LWqyQWt8kv/9wpw7EoLdKnek0E3390UgRzk9hJmJxc7prQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 403, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022029798c5c45bdf58b4a7b2fdc2c46ab4af1218c7eeb9f0f27a88f1267674de3b0", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", - "wx" : "622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa", - "wy" : "736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004622fc74732034bec2ddf3bc16d34b3d1f7a327dd2a8c19bab4bb4fe3a24b58aa736b2f2fae76f4dfaecc9096333b01328d51eb3fda9c9227e90d0b449983c4f0", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYi/HRzIDS+wt3zvBbTSz0fejJ90qjBm6\ntLtP46JLWKpzay8vrnb0367MkJYzOwEyjVHrP9qckifpDQtEmYPE8A==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 404, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02200b70f22ca2bb3cefadca1a5711fa3a59f4695385eb5aedf3495d0b6d00f8fd85", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", - "wx" : "1f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c7", - "wy" : "0827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041f7f85caf2d7550e7af9b65023ebb4dce3450311692309db269969b834b611c70827f45b78020ecbbaf484fdd5bfaae6870f1184c21581baf6ef82bd7b530f93", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH3+FyvLXVQ56+bZQI+u03ONFAxFpIwnb\nJplpuDS2EccIJ/RbeAIOy7r0hP3Vv6rmhw8RhMIVgbr274K9e1MPkw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 405, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022016e1e459457679df5b9434ae23f474b3e8d2a70bd6b5dbe692ba16da01f1fb0a", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", - "wx" : "49c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377a", - "wy" : "00efc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000449c197dc80ad1da47a4342b93893e8e1fb0bb94fc33a83e783c00b24c781377aefc20da92bac762951f72474becc734d4cc22ba81b895e282fdac4df7af0f37d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEScGX3ICtHaR6Q0K5OJPo4fsLuU/DOoPn\ng8ALJMeBN3rvwg2pK6x2KVH3JHS+zHNNTMIrqBuJXigv2sTfevDzfQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 406, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202252d685e831b6cf095e4f0535eeaf0ddd3bfa91c210c9d9dc17224702eaf88f", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", - "wx" : "00d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe", - "wy" : "7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d8cb68517b616a56400aa3868635e54b6f699598a2f6167757654980baf6acbe7ec8cf449c849aa03461a30efada41453c57c6e6fbc93bbc6fa49ada6dc0555c", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2MtoUXthalZACqOGhjXlS29plZii9hZ3\nV2VJgLr2rL5+yM9EnISaoDRhow762kFFPFfG5vvJO7xvpJrabcBVXA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 407, - "comment" : "edge case for u1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022075135abd7c425b60371a477f09ce0f274f64a8c6b061a07b5d63e93c65046c53", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", - "wx" : "030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3", - "wy" : "00b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004030713fb63f2aa6fe2cadf1b20efc259c77445dafa87dac398b84065ca347df3b227818de1a39b589cb071d83e5317cccdc2338e51e312fe31d8dc34a4801750", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAwcT+2Pyqm/iyt8bIO/CWcd0Rdr6h9rD\nmLhAZco0ffOyJ4GN4aObWJywcdg+UxfMzcIzjlHjEv4x2Nw0pIAXUA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 408, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3e3a49a23a6d8abe95461f8445676b17", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", - "wx" : "00babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7", - "wy" : "252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004babb3677b0955802d8e929a41355640eaf1ea1353f8a771331c4946e3480afa7252f196c87ed3d2a59d3b1b559137fed0013fecefc19fb5a92682b9bca51b950", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEurs2d7CVWALY6SmkE1VkDq8eoTU/incT\nMcSUbjSAr6clLxlsh+09KlnTsbVZE3/tABP+zvwZ+1qSaCubylG5UA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 409, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203e888377ac6c71ac9dec3fdb9b56c9feaf0cfaca9f827fc5eb65fc3eac811210", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", - "wx" : "1aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60", - "wy" : "00bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041aab2018793471111a8a0e9b143fde02fc95920796d3a63de329b424396fba60bbe4130705174792441b318d3aa31dfe8577821e9b446ec573d272e036c4ebe9", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGqsgGHk0cREaig6bFD/eAvyVkgeW06Y9\n4ym0JDlvumC75BMHBRdHkkQbMY06ox3+hXeCHptEbsVz0nLgNsTr6Q==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 410, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022030bbb794db588363b40679f6c182a50d3ce9679acdd3ffbe36d7813dacbdc818", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", - "wx" : "008cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff", - "wy" : "47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048cb0b909499c83ea806cd885b1dd467a0119f06a88a0276eb0cfda274535a8ff47b5428833bc3f2c8bf9d9041158cf33718a69961cd01729bc0011d1e586ab75", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjLC5CUmcg+qAbNiFsd1GegEZ8GqIoCdu\nsM/aJ0U1qP9HtUKIM7w/LIv52QQRWM8zcYpplhzQFym8ABHR5YardQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 411, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202c37fd995622c4fb7fffffffffffffffc7cee745110cb45ab558ed7c90c15a2f", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", - "wx" : "008f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d", - "wy" : "3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048f03cf1a42272bb1532723093f72e6feeac85e1700e9fbe9a6a2dd642d74bf5d3b89a7189dad8cf75fc22f6f158aa27f9c2ca00daca785be3358f2bda3862ca0", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjwPPGkInK7FTJyMJP3Lm/urIXhcA6fvp\npqLdZC10v107iacYna2M91/CL28ViqJ/nCygDaynhb4zWPK9o4YsoA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 412, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02207fd995622c4fb7ffffffffffffffffff5d883ffab5b32652ccdcaa290fccb97d", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", - "wx" : "44de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8ace", - "wy" : "00a2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000444de3b9c7a57a8c9e820952753421e7d987bb3d79f71f013805c897e018f8acea2460758c8f98d3fdce121a943659e372c326fff2e5fc2ae7fa3f79daae13c12", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAERN47nHpXqMnoIJUnU0IefZh7s9efcfAT\ngFyJfgGPis6iRgdYyPmNP9zhIalDZZ43LDJv/y5fwq5/o/edquE8Eg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 413, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304302207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc021f4cd53ba7608fffffffffffffffffffff9e5cf143e2539626190a3ab09cce47", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", - "wx" : "6fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a", - "wy" : "0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046fb8b2b48e33031268ad6a517484dc8839ea90f6669ea0c7ac3233e2ac31394a0ac8bbe7f73c2ff4df9978727ac1dfc2fd58647d20f31f99105316b64671f204", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEb7iytI4zAxJorWpRdITciDnqkPZmnqDH\nrDIz4qwxOUoKyLvn9zwv9N+ZeHJ6wd/C/VhkfSDzH5kQUxa2RnHyBA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 414, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02205622c4fb7fffffffffffffffffffffff928a8f1c7ac7bec1808b9f61c01ec327", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", - "wx" : "00bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6", - "wy" : "00f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004bea71122a048693e905ff602b3cf9dd18af69b9fc9d8431d2b1dd26b942c95e6f43c7b8b95eb62082c12db9dbda7fe38e45cbe4a4886907fb81bdb0c5ea9246c", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEvqcRIqBIaT6QX/YCs8+d0Yr2m5/J2EMd\nKx3Sa5Qsleb0PHuLletiCCwS2529p/445Fy+SkiGkH+4G9sMXqkkbA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 415, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc022044104104104104104104104104104103b87853fd3b7d3f8e175125b4382f25ed", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", - "wx" : "00da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156", - "wy" : "00e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004da918c731ba06a20cb94ef33b778e981a404a305f1941fe33666b45b03353156e2bb2694f575b45183be78e5c9b5210bf3bf488fd4c8294516d89572ca4f5391", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE2pGMcxugaiDLlO8zt3jpgaQEowXxlB/j\nNma0WwM1MVbiuyaU9XW0UYO+eOXJtSEL879Ij9TIKUUW2JVyyk9TkQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 416, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202739ce739ce739ce739ce739ce739ce705560298d1f2f08dc419ac273a5b54d9", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", - "wx" : "3007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d", - "wy" : "5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200043007e92c3937dade7964dfa35b0eff031f7eb02aed0a0314411106cdeb70fe3d5a7546fc0552997b20e3d6f413e75e2cb66e116322697114b79bac734bfc4dc5", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEMAfpLDk32t55ZN+jWw7/Ax9+sCrtCgMU\nQREGzetw/j1adUb8BVKZeyDj1vQT514stm4RYyJpcRS3m6xzS/xNxQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 417, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02204888888888888888888888888888888831c83ae82ebe0898776b4c69d11f88de", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", - "wx" : "60e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9b", - "wy" : "00d2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000460e734ef5624d3cbf0ddd375011bd663d6d6aebc644eb599fdf98dbdcd18ce9bd2d90b3ac31f139af832cccf6ccbbb2c6ea11fa97370dc9906da474d7d8a7567", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYOc071Yk08vw3dN1ARvWY9bWrrxkTrWZ\n/fmNvc0YzpvS2Qs6wx8TmvgyzM9sy7ssbqEfqXNw3JkG2kdNfYp1Zw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 418, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206492492492492492492492492492492406dd3a19b8d5fb875235963c593bd2d3", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", - "wx" : "0085a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba337", - "wy" : "69744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000485a900e97858f693c0b7dfa261e380dad6ea046d1f65ddeeedd5f7d8af0ba33769744d15add4f6c0bc3b0da2aec93b34cb8c65f9340ddf74e7b0009eeeccce3c", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEhakA6XhY9pPAt9+iYeOA2tbqBG0fZd3u\n7dX32K8LozdpdE0VrdT2wLw7DaKuyTs0y4xl+TQN33TnsACe7szOPA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 419, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02206aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3e3a49a23a6d8abe95461f8445676b15", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", - "wx" : "38066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046", - "wy" : "00a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000438066f75d88efc4c93de36f49e037b234cc18b1de5608750a62cab0345401046a3e84bed8cfcb819ef4d550444f2ce4b651766b69e2e2901f88836ff90034fed", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOAZvddiO/EyT3jb0ngN7I0zBix3lYIdQ\npiyrA0VAEEaj6EvtjPy4Ge9NVQRE8s5LZRdmtp4uKQH4iDb/kANP7Q==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 420, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02202aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3e3a49a23a6d8abe95461f8445676b17", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", - "wx" : "0098f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabf", - "wy" : "00a33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000498f68177dc95c1b4cbfa5245488ca523a7d5629470d035d621a443c72f39aabfa33d29546fa1c648f2c7d5ccf70cf1ce4ab79b5db1ac059dbecd068dbdff1b89", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmPaBd9yVwbTL+lJFSIylI6fVYpRw0DXW\nIaRDxy85qr+jPSlUb6HGSPLH1cz3DPHOSrebXbGsBZ2+zQaNvf8biQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 421, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02203ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", - "wx" : "5c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277", - "wy" : "00e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200045c2bbfa23c9b9ad07f038aa89b4930bf267d9401e4255de9e8da0a5078ec8277e3e882a31d5e6a379e0793983ccded39b95c4353ab2ff01ea5369ba47b0c3191", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEXCu/ojybmtB/A4qom0kwvyZ9lAHkJV3p\n6NoKUHjsgnfj6IKjHV5qN54Hk5g8ze05uVxDU6sv8B6lNpukewwxkQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 422, - "comment" : "edge case for u2", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0220185ddbca6dac41b1da033cfb60c152869e74b3cd66e9ffdf1b6bc09ed65ee40c", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", - "wx" : "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", - "wy" : "3547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a3853547808298448edb5e701ade84cd5fb1ac9567ba5e8fb68a6b933ec4b5cc84cc", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4U1R4CCmESO215wGt6EzV+xrJVnul6Ptoprkz7EtcyEzA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 423, - "comment" : "point duplication during verification", - "flags" : [ - "PointDuplication" - ], - "msg" : "313233343030", - "sig" : "3044022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022029ed3d67b3d505be95580d77d5b792b436881179b2b6b2e04c5fe592d38d82d9", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", - "wx" : "2ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385", - "wy" : "00cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200042ea7133432339c69d27f9b267281bd2ddd5f19d6338d400a05cd3647b157a385cab87f7d67bb7124a18fe5217b32a04e536a9845a1704975946cc13a4a337763", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELqcTNDIznGnSf5smcoG9Ld1fGdYzjUAK\nBc02R7FXo4XKuH99Z7txJKGP5SF7MqBOU2qYRaFwSXWUbME6SjN3Yw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 424, - "comment" : "duplication bug", - "flags" : [ - "PointDuplication" - ], - "msg" : "313233343030", - "sig" : "3044022032b0d10d8d0e04bc8d4d064d270699e87cffc9b49c5c20730e1c26f6105ddcda022029ed3d67b3d505be95580d77d5b792b436881179b2b6b2e04c5fe592d38d82d9", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", - "wx" : "008aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e", - "wy" : "1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048aa2c64fa9c6437563abfbcbd00b2048d48c18c152a2a6f49036de7647ebe82e1ce64387995c68a060fa3bc0399b05cc06eec7d598f75041a4917e692b7f51ff", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEiqLGT6nGQ3Vjq/vL0AsgSNSMGMFSoqb0\nkDbedkfr6C4c5kOHmVxooGD6O8A5mwXMBu7H1Zj3UEGkkX5pK39R/w==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 425, - "comment" : "comparison with point at infinity ", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0022033333333333333333333333333333332f222f8faefdb533f265d461c29a47373", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", - "wx" : "391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71f", - "wy" : "00dd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004391427ff7ee78013c14aec7d96a8a062209298a783835e94fd6549d502fff71fdd6624ec343ad9fcf4d9872181e59f842f9ba4cccae09a6c0972fb6ac6b4c6bd", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEORQn/37ngBPBSux9lqigYiCSmKeDg16U\n/WVJ1QL/9x/dZiTsNDrZ/PTZhyGB5Z+EL5ukzMrgmmwJcvtqxrTGvQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 426, - "comment" : "extreme value for k and edgecase s", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", - "wx" : "00e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138e", - "wy" : "00c1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004e762b8a219b4f180219cc7a9059245e4961bd191c03899789c7a34b89e8c138ec1533ef0419bb7376e0bfde9319d10a06968791d9ea0eed9c1ce6345aed9759e", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE52K4ohm08YAhnMepBZJF5JYb0ZHAOJl4\nnHo0uJ6ME47BUz7wQZu3N24L/ekxnRCgaWh5HZ6g7tnBzmNFrtl1ng==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 427, - "comment" : "extreme value for k and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", - "wx" : "009aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952", - "wy" : "00fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200049aedb0d281db164e130000c5697fae0f305ef848be6fffb43ac593fbb950e952fa6f633359bdcd82b56b0b9f965b037789d46b9a8141b791b2aefa713f96c175", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEmu2w0oHbFk4TAADFaX+uDzBe+Ei+b/+0\nOsWT+7lQ6VL6b2MzWb3NgrVrC5+WWwN3idRrmoFBt5GyrvpxP5bBdQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 428, - "comment" : "extreme value for k and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", - "wx" : "008ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee", - "wy" : "1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048ad445db62816260e4e687fd1884e48b9fc0636d031547d63315e792e19bfaee1de64f99d5f1cd8b6ec9cb0f787a654ae86993ba3db1008ef43cff0684cb22bd", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEitRF22KBYmDk5of9GITki5/AY20DFUfW\nMxXnkuGb+u4d5k+Z1fHNi27Jyw94emVK6GmTuj2xAI70PP8GhMsivQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 429, - "comment" : "extreme value for k and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", - "wx" : "1f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32", - "wy" : "00e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200041f5799c95be89063b24f26e40cb928c1a868a76fb0094607e8043db409c91c32e75724e813a4191e3a839007f08e2e897388b06d4a00de6de60e536d91fab566", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEH1eZyVvokGOyTybkDLkowahop2+wCUYH\n6AQ9tAnJHDLnVyToE6QZHjqDkAfwji6Jc4iwbUoA3m3mDlNtkfq1Zg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 430, - "comment" : "extreme value for k and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", - "wx" : "00a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc", - "wy" : "28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004a3331a4e1b4223ec2c027edd482c928a14ed358d93f1d4217d39abf69fcb5ccc28d684d2aaabcd6383775caa6239de26d4c6937bb603ecb4196082f4cffd509d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEozMaThtCI+wsAn7dSCySihTtNY2T8dQh\nfTmr9p/LXMwo1oTSqqvNY4N3XKpiOd4m1MaTe7YD7LQZYIL0z/1QnQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 431, - "comment" : "extreme value for k", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3045022100c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee502200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", - "wx" : "3f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb24818", - "wy" : "5ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200043f3952199774c7cf39b38b66cb1042a6260d8680803845e4d433adba3bb248185ea495b68cbc7ed4173ee63c9042dc502625c7eb7e21fb02ca9a9114e0a3a18d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEPzlSGZd0x885s4tmyxBCpiYNhoCAOEXk\n1DOtujuySBhepJW2jLx+1Bc+5jyQQtxQJiXH634h+wLKmpEU4KOhjQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 432, - "comment" : "extreme value for k and edgecase s", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022055555555555555555555555555555554e8e4f44ce51835693ff0ca2ef01215c0", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", - "wx" : "00cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e", - "wy" : "054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004cdfb8c0f422e144e137c2412c86c171f5fe3fa3f5bbb544e9076288f3ced786e054fd0721b77c11c79beacb3c94211b0a19bda08652efeaf92513a3b0a163698", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEzfuMD0IuFE4TfCQSyGwXH1/j+j9bu1RO\nkHYojzzteG4FT9ByG3fBHHm+rLPJQhGwoZvaCGUu/q+SUTo7ChY2mA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 433, - "comment" : "extreme value for k and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", - "wx" : "73598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3", - "wy" : "00cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000473598a6a1c68278fa6bfd0ce4064e68235bc1c0f6b20a928108be336730f87e3cbae612519b5032ecc85aed811271a95fe7939d5d3460140ba318f4d14aba31d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEc1mKahxoJ4+mv9DOQGTmgjW8HA9rIKko\nEIvjNnMPh+PLrmElGbUDLsyFrtgRJxqV/nk51dNGAUC6MY9NFKujHQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 434, - "comment" : "extreme value for k and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", - "wx" : "58debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a1", - "wy" : "6773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000458debd9a7ee2c9d59132478a5440ae4d5d7ed437308369f92ea86c82183f10a16773e76f5edbf4da0e4f1bdffac0f57257e1dfa465842931309a24245fda6a5d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEWN69mn7iydWRMkeKVECuTV1+1Dcwg2n5\nLqhsghg/EKFnc+dvXtv02g5PG9/6wPVyV+HfpGWEKTEwmiQkX9pqXQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 435, - "comment" : "extreme value for k and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022066666666666666666666666666666665e445f1f5dfb6a67e4cba8c385348e6e7", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", - "wx" : "008b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b", - "wy" : "00950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200048b904de47967340c5f8c3572a720924ef7578637feab1949acb241a5a6ac3f5b950904496f9824b1d63f3313bae21b89fae89afdfc811b5ece03fd5aa301864f", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEi5BN5HlnNAxfjDVypyCSTvdXhjf+qxlJ\nrLJBpaasP1uVCQRJb5gksdY/MxO64huJ+uia/fyBG17OA/1aowGGTw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 436, - "comment" : "extreme value for k and s^-1", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022049249249249249249249249249249248c79facd43214c011123c1b03a93412a5", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", - "wx" : "00f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a", - "wy" : "346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004f4892b6d525c771e035f2a252708f3784e48238604b4f94dc56eaa1e546d941a346b1aa0bce68b1c50e5b52f509fb5522e5c25e028bc8f863402edb7bcad8b1b", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE9IkrbVJcdx4DXyolJwjzeE5II4YEtPlN\nxW6qHlRtlBo0axqgvOaLHFDltS9Qn7VSLlwl4Ci8j4Y0Au23vK2LGw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 437, - "comment" : "extreme value for k", - "flags" : [ - "ArithmeticError" - ], - "msg" : "313233343030", - "sig" : "3044022079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179802200eb10e5ab95f2f275348d82ad2e4d7949c8193800d8c9c75df58e343f0ebba7b", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", - "wx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "wy" : "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio/Re0SKaFVBmcR9CP+xDUuA==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 438, - "comment" : "public key shares x-coordinate with generator", - "flags" : [ - "PointDuplication" - ], - "msg" : "313233343030", - "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", - "result" : "invalid" - }, - { - "tcId" : 439, - "comment" : "public key shares x-coordinate with generator", - "flags" : [ - "PointDuplication" - ], - "msg" : "313233343030", - "sig" : "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", - "wx" : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "wy" : "00b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeb5mfvncu6xVoGKVzocLBwKb/NstzijZ\nWfKBWxb4F5i3xSWI2Vw7mqJbBAPx7vdXAuhLt1l6q+ZjuC9vBO8ndw==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 440, - "comment" : "public key shares x-coordinate with generator", - "flags" : [ - "PointDuplication" - ], - "msg" : "313233343030", - "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502302202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", - "result" : "invalid" - }, - { - "tcId" : 441, - "comment" : "public key shares x-coordinate with generator", - "flags" : [ - "PointDuplication" - ], - "msg" : "313233343030", - "sig" : "3044022044a5ad0bd0636d9e12bc9e0a6bdd5e1bba77f523842193b3b82e448e05d5f11e02202492492492492492492492492492492463cfd66a190a6008891e0d81d49a0952", - "result" : "invalid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", - "wx" : "782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963", - "wy" : "00af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004782c8ed17e3b2a783b5464f33b09652a71c678e05ec51e84e2bcfc663a3de963af9acb4280b8c7f7c42f4ef9aba6245ec1ec1712fd38a0fa96418d8cd6aa6152", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEeCyO0X47Kng7VGTzOwllKnHGeOBexR6E\n4rz8Zjo96WOvmstCgLjH98QvTvmrpiRewewXEv04oPqWQY2M1qphUg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 442, - "comment" : "pseudorandom signature", - "flags" : [ - "ValidSignature" - ], - "msg" : "", - "sig" : "3045022100f80ae4f96cdbc9d853f83d47aae225bf407d51c56b7776cd67d0dc195d99a9dc02204cfc1d941e08cb9aceadde0f4ccead76b30d332fc442115d50e673e28686b70b", - "result" : "valid" - }, - { - "tcId" : 443, - "comment" : "pseudorandom signature", - "flags" : [ - "ValidSignature" - ], - "msg" : "4d7367", - "sig" : "30440220109cd8ae0374358984a8249c0a843628f2835ffad1df1a9a69aa2fe72355545c02205390ff250ac4274e1cb25cd6ca6491f6b91281e32f5b264d87977aed4a94e77b", - "result" : "valid" - }, - { - "tcId" : 444, - "comment" : "pseudorandom signature", - "flags" : [ - "ValidSignature" - ], - "msg" : "313233343030", - "sig" : "3045022100d035ee1f17fdb0b2681b163e33c359932659990af77dca632012b30b27a057b302201939d9f3b2858bc13e3474cb50e6a82be44faa71940f876c1cba4c3e989202b6", - "result" : "valid" - }, - { - "tcId" : 445, - "comment" : "pseudorandom signature", - "flags" : [ - "ValidSignature" - ], - "msg" : "0000000000000000000000000000000000000000", - "sig" : "304402204f053f563ad34b74fd8c9934ce59e79c2eb8e6eca0fef5b323ca67d5ac7ed23802204d4b05daa0719e773d8617dce5631c5fd6f59c9bdc748e4b55c970040af01be5", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", - "wx" : "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", - "wy" : "01060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff00000001060492d5a5673e0f25d8d50fb7e58c49d86d46d4216955e0aa3d40e1", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv8AAAABBgSS1aVnPg8l2NUPt+WMSdhtRtQhaVXgqj1A4Q==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 446, - "comment" : "y-coordinate of the public key is small", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "304402206d6a4f556ccce154e7fb9f19e76c3deca13d59cc2aeb4ecad968aab2ded45965022053b9fa74803ede0fc4441bf683d56c564d3e274e09ccf47390badd1471c05fb7", - "result" : "valid" - }, - { - "tcId" : 447, - "comment" : "y-coordinate of the public key is small", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3044022100aad503de9b9fd66b948e9acf596f0a0e65e700b28b26ec56e6e45e846489b3c4021f0ddc3a2f89abb817bb85c062ce02f823c63fc26b269e0bc9b84d81a5aa123d", - "result" : "valid" - }, - { - "tcId" : 448, - "comment" : "y-coordinate of the public key is small", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "30450221009182cebd3bb8ab572e167174397209ef4b1d439af3b200cdf003620089e43225022054477c982ea019d2e1000497fc25fcee1bccae55f2ac27530ae53b29c4b356a4", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", - "wx" : "6e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40caff", - "wy" : "00fffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046e823555452914099182c6b2c1d6f0b5d28d50ccd005af2ce1bba541aa40cafffffffffef9fb6d2a5a98c1f0da272af0481a73b62792b92bde96aa1e55c2bb4e", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEboI1VUUpFAmRgsaywdbwtdKNUMzQBa8s\n4bulQapAyv/////++fttKlqYwfDaJyrwSBpztieSuSvelqoeVcK7Tg==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 449, - "comment" : "y-coordinate of the public key is large", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "304402203854a3998aebdf2dbc28adac4181462ccac7873907ab7f212c42db0e69b56ed802203ed3f6b8a388d02f3e4df9f2ae9c1bd2c3916a686460dffcd42909cd7f82058e", - "result" : "valid" - }, - { - "tcId" : 450, - "comment" : "y-coordinate of the public key is large", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3045022100e94dbdc38795fe5c904d8f16d969d3b587f0a25d2de90b6d8c5c53ff887e360702207a947369c164972521bb8af406813b2d9f94d2aeaa53d4c215aaa0a2578a2c5d", - "result" : "valid" - }, - { - "tcId" : 451, - "comment" : "y-coordinate of the public key is large", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3044022049fc102a08ca47b60e0858cd0284d22cddd7233f94aaffbb2db1dd2cf08425e102205b16fca5a12cdb39701697ad8e39ffd6bdec0024298afaa2326aea09200b14d6", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", - "wx" : "013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0", - "wy" : "00f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004000000013fd22248d64d95f73c29b48ab48631850be503fd00f8468b5f0f70e0f6ee7aa43bc2c6fd25b1d8269241cbdd9dbb0dac96dc96231f430705f838717d", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAAAAAT/SIkjWTZX3PCm0irSGMYUL5QP9\nAPhGi18PcOD27nqkO8LG/SWx2CaSQcvdnbsNrJbcliMfQwcF+DhxfQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 452, - "comment" : "x-coordinate of the public key is small", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3044022041efa7d3f05a0010675fcb918a45c693da4b348df21a59d6f9cd73e0d831d67a02204454ada693e5e26b7bd693236d340f80545c834577b6f73d378c7bcc534244da", - "result" : "valid" - }, - { - "tcId" : 453, - "comment" : "x-coordinate of the public key is small", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3045022100b615698c358b35920dd883eca625a6c5f7563970cdfc378f8fe0cee17092144c022025f47b326b5be1fb610b885153ea84d41eb4716be66a994e8779989df1c863d4", - "result" : "valid" - }, - { - "tcId" : 454, - "comment" : "x-coordinate of the public key is small", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "304502210087cf8c0eb82d44f69c60a2ff5457d3aaa322e7ec61ae5aecfd678ae1c1932b0e02203add3b115815047d6eb340a3e008989eaa0f8708d1794814729094d08d2460d3", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "0425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", - "wx" : "25afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dffffffff", - "wy" : "00fa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a0342000425afd689acabaed67c1f296de59406f8c550f57146a0b4ec2c97876dfffffffffa46a76e520322dfbc491ec4f0cc197420fc4ea5883d8f6dd53c354bc4f67c35", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEJa/WiayrrtZ8Hylt5ZQG+MVQ9XFGoLTs\nLJeHbf/////6RqduUgMi37xJHsTwzBl0IPxOpYg9j23VPDVLxPZ8NQ==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 455, - "comment" : "x-coordinate of the public key has many trailing 1's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3044022062f48ef71ace27bf5a01834de1f7e3f948b9dce1ca1e911d5e13d3b104471d8202205ea8f33f0c778972c4582080deda9b341857dd64514f0849a05f6964c2e34022", - "result" : "valid" - }, - { - "tcId" : 456, - "comment" : "x-coordinate of the public key has many trailing 1's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3045022100f6b0e2f6fe020cf7c0c20137434344ed7add6c4be51861e2d14cbda472a6ffb402206416c8dd3e5c5282b306e8dc8ff34ab64cc99549232d678d714402eb6ca7aa0f", - "result" : "valid" - }, - { - "tcId" : 457, - "comment" : "x-coordinate of the public key has many trailing 1's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3045022100db09d8460f05eff23bc7e436b67da563fa4b4edb58ac24ce201fa8a358125057022046da116754602940c8999c8d665f786c50f5772c0a3cdbda075e77eabc64df16", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "04d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", - "wx" : "00d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb9", - "wy" : "3f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a03420004d12e6c66b67734c3c84d2601cf5d35dc097e27637f0aca4a4fdb74b6aadd3bb93f5bdff88bd5736df898e699006ed750f11cf07c5866cd7ad70c7121ffffffff", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE0S5sZrZ3NMPITSYBz1013Al+J2N/CspK\nT9t0tqrdO7k/W9/4i9VzbfiY5pkAbtdQ8RzwfFhmzXrXDHEh/////w==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 458, - "comment" : "y-coordinate of the public key has many trailing 1's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "30440220592c41e16517f12fcabd98267674f974b588e9f35d35406c1a7bb2ed1d19b7b802203e65a06bd9f83caaeb7b00f2368d7e0dece6b12221269a9b5b765198f840a3a1", - "result" : "valid" - }, - { - "tcId" : 459, - "comment" : "y-coordinate of the public key has many trailing 1's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3045022100be0d70887d5e40821a61b68047de4ea03debfdf51cdf4d4b195558b959a032b202207d994b2d8f1dbbeb13534eb3f6e5dccd85f5c4133c27d9e64271b1826ce1f67d", - "result" : "valid" - }, - { - "tcId" : 460, - "comment" : "y-coordinate of the public key has many trailing 1's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3045022100fae92dfcb2ee392d270af3a5739faa26d4f97bfd39ed3cbee4d29e26af3b206a02206c9ba37f9faa6a1fd3f65f23b4e853d4692a7274240a12db7ba3884830630d16", - "result" : "valid" - } - ] - }, - { - "type" : "EcdsaBitcoinVerify", - "publicKey" : { - "type" : "EcPublicKey", - "curve" : "secp256k1", - "keySize" : 256, - "uncompressed" : "046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", - "wx" : "6d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000", - "wy" : "00e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb" - }, - "publicKeyDer" : "3056301006072a8648ce3d020106052b8104000a034200046d4a7f60d4774a4f0aa8bbdedb953c7eea7909407e3164755664bc2800000000e659d34e4df38d9e8c9eaadfba36612c769195be86c77aac3f36e78b538680fb", - "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEbUp/YNR3Sk8KqLve25U8fup5CUB+MWR1\nVmS8KAAAAADmWdNOTfONnoyeqt+6NmEsdpGVvobHeqw/NueLU4aA+w==\n-----END PUBLIC KEY-----\n", - "sha" : "SHA-256", - "tests" : [ - { - "tcId" : 461, - "comment" : "x-coordinate of the public key has many trailing 0's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "30440220176a2557566ffa518b11226694eb9802ed2098bfe278e5570fe1d5d7af18a94302201291df6a0ed5fc0d15098e70bcf13a009284dfd0689d3bb4be6ceeb9be1487c4", - "result" : "valid" - }, - { - "tcId" : 462, - "comment" : "x-coordinate of the public key has many trailing 0's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3044022060be20c3dbc162dd34d26780621c104bbe5dace630171b2daef0d826409ee5c20220427f7e4d889d549170bda6a9409fb1cb8b0e763d13eea7bd97f64cf41dc6e497", - "result" : "valid" - }, - { - "tcId" : 463, - "comment" : "x-coordinate of the public key has many trailing 0's", - "flags" : [ - "EdgeCasePublicKey" - ], - "msg" : "4d657373616765", - "sig" : "3045022100edf03cf63f658883289a1a593d1007895b9f236d27c9c1f1313089aaed6b16ae02201a4dd6fc0814dc523d1fefa81c64fbf5e618e651e7096fccadbb94cd48e5e0cd", - "result" : "valid" - } - ] - } - ] -} diff --git a/external/secp256k1/tools/check-abi.sh b/external/secp256k1/tools/check-abi.sh deleted file mode 100755 index 601a64ba96..0000000000 --- a/external/secp256k1/tools/check-abi.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh - -set -eu - -default_base_version="$(git describe --match "v*.*.*" --abbrev=0)" -default_new_version="HEAD" - -display_help_and_exit() { - echo "Usage: $0 [ []]" - echo "" - echo "Description: This script uses the ABI Compliance Checker tool to determine if the ABI" - echo " of a new version of libsecp256k1 has changed in a backward-incompatible way." - echo "" - echo "Options:" - echo " base_ver Specify the base version as a git commit-ish" - echo " (default: most recent reachable tag matching \"v.*.*\", currently \"$default_base_version\")" - echo " new_ver Specify the new version as a git commit-ish" - echo " (default: $default_new_version)" - echo " -h, --help Display this help message" - exit 0 -} - -if [ "$#" -eq 0 ]; then - base_version="$default_base_version" - new_version="$default_new_version" -elif [ "$#" -eq 1 ] && { [ "$1" = "-h" ] || [ "$1" = "--help" ]; }; then - display_help_and_exit -elif [ "$#" -eq 1 ] || [ "$#" -eq 2 ]; then - base_version="$1" - if [ "$#" -eq 2 ]; then - new_version="$2" - fi -else - echo "Invalid usage. See help:" - echo "" - display_help_and_exit -fi - -checkout_and_build() { - _orig_dir="$(pwd)" - git worktree add --detach "$1" "$2" - cd "$1" - mkdir build && cd build - cmake -S .. --preset dev-mode \ - -DCMAKE_C_COMPILER=gcc -DCMAKE_BUILD_TYPE=None -DCMAKE_C_FLAGS="-g -Og -gdwarf-4" \ - -DSECP256K1_BUILD_BENCHMARK=OFF \ - -DSECP256K1_BUILD_TESTS=OFF \ - -DSECP256K1_BUILD_EXHAUSTIVE_TESTS=OFF \ - -DSECP256K1_BUILD_CTIME_TESTS=OFF \ - -DSECP256K1_BUILD_EXAMPLES=OFF - cmake --build . -j "$(nproc)" - # FIXME: Just set LIBPATH to lib/libsecp256k1.so once version 0.6.0 is - # released. - if [ -f "src/libsecp256k1.so" ]; then - LIBPATH="src/libsecp256k1.so" - else - LIBPATH="lib/libsecp256k1.so" - fi - abi-dumper $LIBPATH -o ABI.dump -lver "$2" -public-headers ../include/ - cd "$_orig_dir" -} - -echo "Comparing $base_version (base version) to $new_version (new version)" -echo - -base_source_dir="$(mktemp -d)" -checkout_and_build "$base_source_dir" "$base_version" - -new_source_dir="$(mktemp -d)" -checkout_and_build "$new_source_dir" "$new_version" - -abi-compliance-checker -lib libsecp256k1 -old "${base_source_dir}/build/ABI.dump" -new "${new_source_dir}/build/ABI.dump" -git worktree remove "$base_source_dir" -git worktree remove "$new_source_dir" diff --git a/external/secp256k1/tools/test_vectors_musig2_generate.py b/external/secp256k1/tools/test_vectors_musig2_generate.py deleted file mode 100755 index 97424419f3..0000000000 --- a/external/secp256k1/tools/test_vectors_musig2_generate.py +++ /dev/null @@ -1,656 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import json -import textwrap - -max_pubkeys = 0 - -if len(sys.argv) < 2: - print( - "This script converts BIP MuSig2 test vectors in a given directory to a C file that can be used in the test framework." - ) - print("Usage: %s " % sys.argv[0]) - sys.exit(1) - - -def hexstr_to_intarray(str): - return ", ".join([f"0x{b:02X}" for b in bytes.fromhex(str)]) - - -def create_init(name): - return """ -static const struct musig_%s_vector musig_%s_vector = { -""" % ( - name, - name, - ) - - -def init_array(key): - return textwrap.indent("{ %s },\n" % hexstr_to_intarray(data[key]), 4 * " ") - - -def init_arrays(key): - s = textwrap.indent("{\n", 4 * " ") - s += textwrap.indent( - ",\n".join(["{ %s }" % hexstr_to_intarray(x) for x in data[key]]), 8 * " " - ) - s += textwrap.indent("\n},\n", 4 * " ") - return s - - -def init_indices(array): - return " %d, { %s }" % ( - len(array), - ", ".join(map(str, array) if len(array) > 0 else "0"), - ) - - -def init_is_xonly(case): - if len(case["tweak_indices"]) > 0: - return ", ".join(map(lambda x: "1" if x else "0", case["is_xonly"])) - return "0" - - -def init_optional_expected(case): - return hexstr_to_intarray(case["expected"]) if "expected" in case else 0 - - -def init_cases(cases, f): - s = textwrap.indent("{\n", 4 * " ") - for (i, case) in enumerate(cases): - s += textwrap.indent("%s\n" % f(case), 8 * " ") - s += textwrap.indent("},\n", 4 * " ") - return s - - -def finish_init(): - return "};\n" - - -s = ( - """/** - * Automatically generated by %s. - * - * The test vectors for the KeySort function are included in this file. They can - * be found in src/modules/extrakeys/tests_impl.h. */ -""" - % sys.argv[0] -) - - -s += """ -enum MUSIG_ERROR { - MUSIG_PUBKEY, - MUSIG_TWEAK, - MUSIG_PUBNONCE, - MUSIG_AGGNONCE, - MUSIG_SECNONCE, - MUSIG_SIG, - MUSIG_SIG_VERIFY, - MUSIG_OTHER -}; -""" - -# key agg vectors -with open(sys.argv[1] + "/key_agg_vectors.json", "r") as f: - data = json.load(f) - - max_key_indices = max( - len(test_case["key_indices"]) for test_case in data["valid_test_cases"] - ) - max_tweak_indices = max( - len(test_case["tweak_indices"]) for test_case in data["error_test_cases"] - ) - num_pubkeys = len(data["pubkeys"]) - max_pubkeys = max(num_pubkeys, max_pubkeys) - num_tweaks = len(data["tweaks"]) - num_valid_cases = len(data["valid_test_cases"]) - num_error_cases = len(data["error_test_cases"]) - - # Add structures for valid and error cases - s += ( - """ -struct musig_key_agg_valid_test_case { - size_t key_indices_len; - size_t key_indices[%d]; - unsigned char expected[32]; -}; -""" - % max_key_indices - ) - s += """ -struct musig_key_agg_error_test_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t tweak_indices_len; - size_t tweak_indices[%d]; - int is_xonly[%d]; - enum MUSIG_ERROR error; -}; -""" % ( - max_key_indices, - max_tweak_indices, - max_tweak_indices, - ) - - # Add structure for entire vector - s += """ -struct musig_key_agg_vector { - unsigned char pubkeys[%d][33]; - unsigned char tweaks[%d][32]; - struct musig_key_agg_valid_test_case valid_case[%d]; - struct musig_key_agg_error_test_case error_case[%d]; -}; -""" % ( - num_pubkeys, - num_tweaks, - num_valid_cases, - num_error_cases, - ) - - s += create_init("key_agg") - # Add pubkeys and tweaks to the vector - s += init_arrays("pubkeys") - s += init_arrays("tweaks") - - # Add valid cases to the vector - s += init_cases( - data["valid_test_cases"], - lambda case: "{ %s, { %s }}," - % (init_indices(case["key_indices"]), hexstr_to_intarray(case["expected"])), - ) - - def comment_to_error(case): - comment = case["comment"] - if "public key" in comment.lower(): - return "MUSIG_PUBKEY" - elif "tweak" in comment.lower(): - return "MUSIG_TWEAK" - else: - sys.exit("Unknown error") - - # Add error cases to the vector - s += init_cases( - data["error_test_cases"], - lambda case: "{ %s, %s, { %s }, %s }," - % ( - init_indices(case["key_indices"]), - init_indices(case["tweak_indices"]), - init_is_xonly(case), - comment_to_error(case), - ), - ) - - s += finish_init() - -# nonce gen vectors -with open(sys.argv[1] + "/nonce_gen_vectors.json", "r") as f: - data = json.load(f) - - # The MuSig2 implementation only allows messages of length 32 - data["test_cases"] = list( - filter(lambda c: c["msg"] is None or len(c["msg"]) == 64, data["test_cases"]) - ) - - num_tests = len(data["test_cases"]) - - s += """ -struct musig_nonce_gen_test_case { - unsigned char rand_[32]; - int has_sk; - unsigned char sk[32]; - unsigned char pk[33]; - int has_aggpk; - unsigned char aggpk[32]; - int has_msg; - unsigned char msg[32]; - int has_extra_in; - unsigned char extra_in[32]; - unsigned char expected_secnonce[97]; - unsigned char expected_pubnonce[66]; -}; -""" - - s += ( - """ -struct musig_nonce_gen_vector { - struct musig_nonce_gen_test_case test_case[%d]; -}; -""" - % num_tests - ) - - s += create_init("nonce_gen") - - def init_array_maybe(array): - return "%d , { %s }" % ( - 0 if array is None else 1, - hexstr_to_intarray(array) if array is not None else 0, - ) - - s += init_cases( - data["test_cases"], - lambda case: "{ { %s }, %s, { %s }, %s, %s, %s, { %s }, { %s } }," - % ( - hexstr_to_intarray(case["rand_"]), - init_array_maybe(case["sk"]), - hexstr_to_intarray(case["pk"]), - init_array_maybe(case["aggpk"]), - init_array_maybe(case["msg"]), - init_array_maybe(case["extra_in"]), - hexstr_to_intarray(case["expected_secnonce"]), - hexstr_to_intarray(case["expected_pubnonce"]), - ), - ) - - s += finish_init() - -# nonce agg vectors -with open(sys.argv[1] + "/nonce_agg_vectors.json", "r") as f: - data = json.load(f) - - num_pnonces = len(data["pnonces"]) - num_valid_cases = len(data["valid_test_cases"]) - num_error_cases = len(data["error_test_cases"]) - - pnonce_indices_len = 2 - for case in data["valid_test_cases"] + data["error_test_cases"]: - assert len(case["pnonce_indices"]) == pnonce_indices_len - - # Add structures for valid and error cases - s += """ -struct musig_nonce_agg_test_case { - size_t pnonce_indices[2]; - /* if valid case */ - unsigned char expected[66]; - /* if error case */ - int invalid_nonce_idx; -}; -""" - # Add structure for entire vector - s += """ -struct musig_nonce_agg_vector { - unsigned char pnonces[%d][66]; - struct musig_nonce_agg_test_case valid_case[%d]; - struct musig_nonce_agg_test_case error_case[%d]; -}; -""" % ( - num_pnonces, - num_valid_cases, - num_error_cases, - ) - - s += create_init("nonce_agg") - s += init_arrays("pnonces") - - for cases in (data["valid_test_cases"], data["error_test_cases"]): - s += init_cases( - cases, - lambda case: "{ { %s }, { %s }, %d }," - % ( - ", ".join(map(str, case["pnonce_indices"])), - init_optional_expected(case), - case["error"]["signer"] if "error" in case else 0, - ), - ) - s += finish_init() - -# sign/verify vectors -with open(sys.argv[1] + "/sign_verify_vectors.json", "r") as f: - data = json.load(f) - - # The MuSig2 implementation only allows messages of length 32 - assert list(filter(lambda x: len(x) == 64, data["msgs"]))[0] == data["msgs"][0] - data["msgs"] = [data["msgs"][0]] - - def filter_msg32(k): - return list(filter(lambda x: x["msg_index"] == 0, data[k])) - - data["valid_test_cases"] = filter_msg32("valid_test_cases") - data["sign_error_test_cases"] = filter_msg32("sign_error_test_cases") - data["verify_error_test_cases"] = filter_msg32("verify_error_test_cases") - data["verify_fail_test_cases"] = filter_msg32("verify_fail_test_cases") - - num_pubkeys = len(data["pubkeys"]) - max_pubkeys = max(num_pubkeys, max_pubkeys) - num_secnonces = len(data["secnonces"]) - num_pubnonces = len(data["pnonces"]) - num_aggnonces = len(data["aggnonces"]) - num_msgs = len(data["msgs"]) - num_valid_cases = len(data["valid_test_cases"]) - num_sign_error_cases = len(data["sign_error_test_cases"]) - num_verify_fail_cases = len(data["verify_fail_test_cases"]) - num_verify_error_cases = len(data["verify_error_test_cases"]) - - all_cases = ( - data["valid_test_cases"] - + data["sign_error_test_cases"] - + data["verify_error_test_cases"] - + data["verify_fail_test_cases"] - ) - max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) - max_nonce_indices = max( - len(test_case["nonce_indices"]) if "nonce_indices" in test_case else 0 - for test_case in all_cases - ) - # Add structures for valid and error cases - s += ( - """ -/* Omit pubnonces in the test vectors because our partial signature verification - * implementation is able to accept the aggnonce directly. */ -struct musig_valid_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t aggnonce_index; - size_t msg_index; - size_t signer_index; - unsigned char expected[32]; -}; -""" - % max_key_indices - ) - - s += ( - """ -struct musig_sign_error_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t aggnonce_index; - size_t msg_index; - size_t secnonce_index; - enum MUSIG_ERROR error; -}; -""" - % max_key_indices - ) - - s += """ -struct musig_verify_fail_error_case { - unsigned char sig[32]; - size_t key_indices_len; - size_t key_indices[%d]; - size_t nonce_indices_len; - size_t nonce_indices[%d]; - size_t msg_index; - size_t signer_index; - enum MUSIG_ERROR error; -}; -""" % ( - max_key_indices, - max_nonce_indices, - ) - - # Add structure for entire vector - s += """ -struct musig_sign_verify_vector { - unsigned char sk[32]; - unsigned char pubkeys[%d][33]; - unsigned char secnonces[%d][194]; - unsigned char pubnonces[%d][194]; - unsigned char aggnonces[%d][66]; - unsigned char msgs[%d][32]; - struct musig_valid_case valid_case[%d]; - struct musig_sign_error_case sign_error_case[%d]; - struct musig_verify_fail_error_case verify_fail_case[%d]; - struct musig_verify_fail_error_case verify_error_case[%d]; -}; -""" % ( - num_pubkeys, - num_secnonces, - num_pubnonces, - num_aggnonces, - num_msgs, - num_valid_cases, - num_sign_error_cases, - num_verify_fail_cases, - num_verify_error_cases, - ) - - s += create_init("sign_verify") - s += init_array("sk") - s += init_arrays("pubkeys") - s += init_arrays("secnonces") - s += init_arrays("pnonces") - s += init_arrays("aggnonces") - s += init_arrays("msgs") - - s += init_cases( - data["valid_test_cases"], - lambda case: "{ %s, %d, %d, %d, { %s }}," - % ( - init_indices(case["key_indices"]), - case["aggnonce_index"], - case["msg_index"], - case["signer_index"], - init_optional_expected(case), - ), - ) - - def sign_error(case): - comment = case["comment"] - if "pubkey" in comment or "public key" in comment: - return "MUSIG_PUBKEY" - elif "Aggregate nonce" in comment: - return "MUSIG_AGGNONCE" - elif "Secnonce" in comment: - return "MUSIG_SECNONCE" - else: - sys.exit("Unknown sign error") - - s += init_cases( - data["sign_error_test_cases"], - lambda case: "{ %s, %d, %d, %d, %s }," - % ( - init_indices(case["key_indices"]), - case["aggnonce_index"], - case["msg_index"], - case["secnonce_index"], - sign_error(case), - ), - ) - - def verify_error(case): - comment = case["comment"] - if "exceeds" in comment: - return "MUSIG_SIG" - elif "Wrong signer" in comment or "Wrong signature" in comment: - return "MUSIG_SIG_VERIFY" - elif "pubnonce" in comment: - return "MUSIG_PUBNONCE" - elif "pubkey" in comment: - return "MUSIG_PUBKEY" - else: - sys.exit("Unknown verify error") - - for cases in ("verify_fail_test_cases", "verify_error_test_cases"): - s += init_cases( - data[cases], - lambda case: "{ { %s }, %s, %s, %d, %d, %s }," - % ( - hexstr_to_intarray(case["sig"]), - init_indices(case["key_indices"]), - init_indices(case["nonce_indices"]), - case["msg_index"], - case["signer_index"], - verify_error(case), - ), - ) - - s += finish_init() - -# tweak vectors -with open(sys.argv[1] + "/tweak_vectors.json", "r") as f: - data = json.load(f) - - num_pubkeys = len(data["pubkeys"]) - max_pubkeys = max(num_pubkeys, max_pubkeys) - num_pubnonces = len(data["pnonces"]) - num_tweaks = len(data["tweaks"]) - num_valid_cases = len(data["valid_test_cases"]) - num_error_cases = len(data["error_test_cases"]) - - all_cases = data["valid_test_cases"] + data["error_test_cases"] - max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) - max_tweak_indices = max(len(test_case["tweak_indices"]) for test_case in all_cases) - max_nonce_indices = max(len(test_case["nonce_indices"]) for test_case in all_cases) - # Add structures for valid and error cases - s += """ -struct musig_tweak_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t nonce_indices_len; - size_t nonce_indices[%d]; - size_t tweak_indices_len; - size_t tweak_indices[%d]; - int is_xonly[%d]; - size_t signer_index; - unsigned char expected[32]; -}; -""" % ( - max_key_indices, - max_nonce_indices, - max_tweak_indices, - max_tweak_indices, - ) - - # Add structure for entire vector - s += """ -struct musig_tweak_vector { - unsigned char sk[32]; - unsigned char secnonce[97]; - unsigned char aggnonce[66]; - unsigned char msg[32]; - unsigned char pubkeys[%d][33]; - unsigned char pubnonces[%d][194]; - unsigned char tweaks[%d][32]; - struct musig_tweak_case valid_case[%d]; - struct musig_tweak_case error_case[%d]; -}; -""" % ( - num_pubkeys, - num_pubnonces, - num_tweaks, - num_valid_cases, - num_error_cases, - ) - s += create_init("tweak") - s += init_array("sk") - s += init_array("secnonce") - s += init_array("aggnonce") - s += init_array("msg") - s += init_arrays("pubkeys") - s += init_arrays("pnonces") - s += init_arrays("tweaks") - - s += init_cases( - data["valid_test_cases"], - lambda case: "{ %s, %s, %s, { %s }, %d, { %s }}," - % ( - init_indices(case["key_indices"]), - init_indices(case["nonce_indices"]), - init_indices(case["tweak_indices"]), - init_is_xonly(case), - case["signer_index"], - init_optional_expected(case), - ), - ) - - s += init_cases( - data["error_test_cases"], - lambda case: "{ %s, %s, %s, { %s }, %d, { %s }}," - % ( - init_indices(case["key_indices"]), - init_indices(case["nonce_indices"]), - init_indices(case["tweak_indices"]), - init_is_xonly(case), - case["signer_index"], - init_optional_expected(case), - ), - ) - - s += finish_init() - -# sigagg vectors -with open(sys.argv[1] + "/sig_agg_vectors.json", "r") as f: - data = json.load(f) - - num_pubkeys = len(data["pubkeys"]) - max_pubkeys = max(num_pubkeys, max_pubkeys) - num_tweaks = len(data["tweaks"]) - num_psigs = len(data["psigs"]) - num_valid_cases = len(data["valid_test_cases"]) - num_error_cases = len(data["error_test_cases"]) - - all_cases = data["valid_test_cases"] + data["error_test_cases"] - max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) - max_tweak_indices = max(len(test_case["tweak_indices"]) for test_case in all_cases) - max_psig_indices = max(len(test_case["psig_indices"]) for test_case in all_cases) - - # Add structures for valid and error cases - s += """ -/* Omit pubnonces in the test vectors because they're only needed for - * implementations that do not directly accept an aggnonce. */ -struct musig_sig_agg_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t tweak_indices_len; - size_t tweak_indices[%d]; - int is_xonly[%d]; - unsigned char aggnonce[66]; - size_t psig_indices_len; - size_t psig_indices[%d]; - /* if valid case */ - unsigned char expected[64]; - /* if error case */ - int invalid_sig_idx; -}; -""" % ( - max_key_indices, - max_tweak_indices, - max_tweak_indices, - max_psig_indices, - ) - - # Add structure for entire vector - s += """ -struct musig_sig_agg_vector { - unsigned char pubkeys[%d][33]; - unsigned char tweaks[%d][32]; - unsigned char psigs[%d][32]; - unsigned char msg[32]; - struct musig_sig_agg_case valid_case[%d]; - struct musig_sig_agg_case error_case[%d]; -}; -""" % ( - num_pubkeys, - num_tweaks, - num_psigs, - num_valid_cases, - num_error_cases, - ) - - s += create_init("sig_agg") - s += init_arrays("pubkeys") - s += init_arrays("tweaks") - s += init_arrays("psigs") - s += init_array("msg") - - for cases in (data["valid_test_cases"], data["error_test_cases"]): - s += init_cases( - cases, - lambda case: "{ %s, %s, { %s }, { %s }, %s, { %s }, %d }," - % ( - init_indices(case["key_indices"]), - init_indices(case["tweak_indices"]), - init_is_xonly(case), - hexstr_to_intarray(case["aggnonce"]), - init_indices(case["psig_indices"]), - init_optional_expected(case), - case["error"]["signer"] if "error" in case else 0, - ), - ) - s += finish_init() -s += "enum { MUSIG_VECTORS_MAX_PUBKEYS = %d };" % max_pubkeys -print(s) diff --git a/external/secp256k1/tools/tests_wycheproof_generate.py b/external/secp256k1/tools/tests_wycheproof_generate.py deleted file mode 100755 index b26dfa89d6..0000000000 --- a/external/secp256k1/tools/tests_wycheproof_generate.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2023 Random "Randy" Lattice and Sean Andersen -# Distributed under the MIT software license, see the accompanying -# file COPYING or https://www.opensource.org/licenses/mit-license.php. -''' -Generate a C file with ECDSA testvectors from the Wycheproof project. -''' - -import json -import sys - -filename_input = sys.argv[1] - -with open(filename_input) as f: - doc = json.load(f) - -num_groups = len(doc['testGroups']) - -def to_c_array(x): - if x == "": - return "" - s = ',0x'.join(a+b for a,b in zip(x[::2], x[1::2])) - return "0x" + s - - -num_vectors = 0 -offset_msg_running, offset_pk_running, offset_sig = 0, 0, 0 -out = "" -messages = "" -signatures = "" -public_keys = "" -cache_msgs = {} -cache_public_keys = {} - -for i in range(num_groups): - group = doc['testGroups'][i] - num_tests = len(group['tests']) - public_key = group['publicKey'] - for j in range(num_tests): - test_vector = group['tests'][j] - # // 2 to convert hex to byte length - sig_size = len(test_vector['sig']) // 2 - msg_size = len(test_vector['msg']) // 2 - - if test_vector['result'] == "invalid": - expected_verify = 0 - elif test_vector['result'] == "valid": - expected_verify = 1 - else: - raise ValueError("invalid result field") - - if num_vectors != 0 and sig_size != 0: - signatures += ",\n " - - new_msg = False - msg = to_c_array(test_vector['msg']) - msg_offset = offset_msg_running - # check for repeated msg - if msg not in cache_msgs: - if num_vectors != 0 and msg_size != 0: - messages += ",\n " - cache_msgs[msg] = offset_msg_running - messages += msg - new_msg = True - else: - msg_offset = cache_msgs[msg] - - new_pk = False - pk = to_c_array(public_key['uncompressed']) - pk_offset = offset_pk_running - # check for repeated pk - if pk not in cache_public_keys: - if num_vectors != 0: - public_keys += ",\n " - cache_public_keys[pk] = offset_pk_running - public_keys += pk - new_pk = True - else: - pk_offset = cache_public_keys[pk] - - signatures += to_c_array(test_vector['sig']) - - out += " /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n" - out += f" {{{pk_offset}, {msg_offset}, {msg_size}, {offset_sig}, {sig_size}, {expected_verify} }},\n" - if new_msg: - offset_msg_running += msg_size - if new_pk: - offset_pk_running += 65 - offset_sig += sig_size - num_vectors += 1 - -struct_definition = """ -typedef struct { - size_t pk_offset; - size_t msg_offset; - size_t msg_len; - size_t sig_offset; - size_t sig_len; - int expected_verify; -} wycheproof_ecdsa_testvector; -""" - - -print("/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */") -print(f"#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})") - -print(struct_definition) - -print("static const unsigned char wycheproof_ecdsa_messages[] = { " + messages + "};\n") -print("static const unsigned char wycheproof_ecdsa_public_keys[] = { " + public_keys + "};\n") -print("static const unsigned char wycheproof_ecdsa_signatures[] = { " + signatures + "};\n") - -print("static const wycheproof_ecdsa_testvector testvectors[SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS] = {") -print(out) -print("};") diff --git a/include/xrpl/protocol/detail/secp256k1.h b/include/xrpl/protocol/detail/secp256k1.h index c93734a539..c0c3cd761b 100644 --- a/include/xrpl/protocol/detail/secp256k1.h +++ b/include/xrpl/protocol/detail/secp256k1.h @@ -1,6 +1,7 @@ #ifndef XRPL_PROTOCOL_SECP256K1_H_INCLUDED #define XRPL_PROTOCOL_SECP256K1_H_INCLUDED +#define SECP256K1_STATIC #include namespace ripple { diff --git a/src/libxrpl/protocol/PublicKey.cpp b/src/libxrpl/protocol/PublicKey.cpp index f1794331ad..5e3a0b651b 100644 --- a/src/libxrpl/protocol/PublicKey.cpp +++ b/src/libxrpl/protocol/PublicKey.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include diff --git a/src/libxrpl/protocol/SecretKey.cpp b/src/libxrpl/protocol/SecretKey.cpp index 8f07b4d03f..d4a958c600 100644 --- a/src/libxrpl/protocol/SecretKey.cpp +++ b/src/libxrpl/protocol/SecretKey.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include From 51f1fe5f9a42f8d7e3ab563db5a27b9ebf62dba4 Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 4 Dec 2025 09:40:00 -0500 Subject: [PATCH 030/105] ci: Re-enable linux and macos matrix (#6107) This change re-enables the Linux and macOS builds that were accidentally disabled in #6089 during testing. --- .github/workflows/on-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 9204cef5e8..ff3d25812a 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -112,7 +112,7 @@ jobs: strategy: fail-fast: false matrix: - os: [windows] + os: [linux, macos, windows] with: os: ${{ matrix.os }} secrets: From 020ea3f412b6a2a1b15bec53ddc7eb149554447e Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 4 Dec 2025 10:34:37 -0500 Subject: [PATCH 031/105] refactor: Update Conan dependencies: protobuf and grpc (#5589) This PR updates protobuf and grpc to their latest versions. The latest protobuf version no longer requires patches, so we can use it directly from the official Conan Center Index, while the latest grpc still needed a patch, which was added to our own Conan Center Index fork in XRPLF/conan-center-index#8. --- .gitignore | 3 +++ BUILD.md | 26 +++++++++----------------- conan.lock | 18 +++++++++--------- conan/profiles/default | 6 ------ conanfile.py | 16 +++++++++++++--- 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 5476f21a41..d8c6b8a5f8 100644 --- a/.gitignore +++ b/.gitignore @@ -111,3 +111,6 @@ bld.rippled/ # Suggested in-tree build directory /.build*/ + +# Locally patched Conan recipes +external/conan-center-index/ diff --git a/BUILD.md b/BUILD.md index a497db417a..153406535c 100644 --- a/BUILD.md +++ b/BUILD.md @@ -142,20 +142,25 @@ locally: ```bash cd external +mkdir -p conan-center-index +cd conan-center-index git init git remote add origin git@github.com:XRPLF/conan-center-index.git git sparse-checkout init git sparse-checkout set recipes/ed25519 +git sparse-checkout add recipes/grpc git sparse-checkout add recipes/secp256k1 git sparse-checkout add recipes/snappy git sparse-checkout add recipes/soci git fetch origin master git checkout master -conan export --version 2015.03 recipes/ed25519/all -conan export --version 0.7.0 recipes/secp256k1/all -conan export --version 1.1.10 recipes/snappy/all -conan export --version 4.0.3 recipes/soci/all rm -rf .git +cd ../.. +conan export --version 2015.03 external/conan-center-index/recipes/ed25519/all +conan export --version 1.72.0 external/conan-center-index/recipes/grpc/all +conan export --version 0.7.0 external/conan-center-index/recipes/secp256k1/all +conan export --version 1.1.10 external/conan-center-index/recipes/snappy/all +conan export --version 4.0.3 external/conan-center-index/recipes/soci/all ``` In the case we switch to a newer version of a dependency that still requires a @@ -385,19 +390,6 @@ tools.build:cxxflags=['-DBOOST_ASIO_DISABLE_CONCEPTS'] `--settings build_type=$BUILD_TYPE` or in the profile itself, under the section `[settings]` with the key `build_type`. - If you are using a Microsoft Visual C++ compiler, - then you will need to ensure consistency between the `build_type` setting - and the `compiler.runtime` setting. - - When `build_type` is `Release`, `compiler.runtime` should be `MT`. - - When `build_type` is `Debug`, `compiler.runtime` should be `MTd`. - - ``` - conan install .. --output-folder . --build missing --settings build_type=Release --settings compiler.runtime=MT - conan install .. --output-folder . --build missing --settings build_type=Debug --settings compiler.runtime=MTd - ``` - 3. Configure CMake and pass the toolchain file generated by Conan, located at `$OUTPUT_FOLDER/build/generators/conan_toolchain.cmake`. diff --git a/conan.lock b/conan.lock index d235e8d41a..410a04403b 100644 --- a/conan.lock +++ b/conan.lock @@ -9,7 +9,7 @@ "secp256k1/0.7.0#9210e4c655d0a665400378a663960d17%1764261276.764", "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1762797952.535", "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1764175362.029", - "protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456", + "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1759134873.45", "openssl/3.5.4#a1d5835cc6ed5c5b8f3cd5b9b5d24205%1760106486.594", "nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1763150366.909", "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999", @@ -17,19 +17,19 @@ "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03", "libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1764175360.142", "jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244", - "grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958", - "ed25519/2015.03#17c1f1910e769f368025267a53c23c13%1764259445.491", + "grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1763158050.628", + "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1764270189.893", "doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1762797941.757", "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1763584497.32", "c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1764175359.429", "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1764175359.429", "boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1756223752.326", - "abseil/20230802.1#90ba607d4ee8fb5fb157c3db540671fc%1764175359.429" + "abseil/20250127.0#9e8e8cfc89a1324139fc0ee3bd4d8c8c%1753819045.301" ], "build_requires": [ "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497", "strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1756234281.733", - "protobuf/3.21.12#44ee56c0a6eea0c19aeeaca680370b88%1764175361.456", + "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1759134873.45", "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1756234232.901", "msys2/cci.latest#5b73b10144f73cc5bfe0572ed9be39e1%1751977009.857", "m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846", @@ -37,13 +37,13 @@ "cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1764175359.429", "b2/5.3.3#107c15377719889654eb9a162a673975%1756234226.28", "automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56", - "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86" + "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86", + "abseil/20250127.0#9e8e8cfc89a1324139fc0ee3bd4d8c8c%1753819045.301" ], "python_requires": [], "overrides": { - "protobuf/3.21.12": [ - null, - "protobuf/3.21.12" + "protobuf/5.27.0": [ + "protobuf/6.32.1" ], "lz4/1.9.4": [ "lz4/1.10.0" diff --git a/conan/profiles/default b/conan/profiles/default index def2fffd6b..cde59f7f3b 100644 --- a/conan/profiles/default +++ b/conan/profiles/default @@ -20,12 +20,6 @@ compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}} {% endif %} [conf] -{% if compiler == "clang" and compiler_version >= 19 %} -grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw'] -{% endif %} -{% if compiler == "apple-clang" and compiler_version >= 17 %} -grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw'] -{% endif %} {% if compiler == "gcc" and compiler_version < 13 %} tools.build:cxxflags+=['-Wno-restrict'] {% endif %} diff --git a/conanfile.py b/conanfile.py index 2d3e090fa3..8dc09da0af 100644 --- a/conanfile.py +++ b/conanfile.py @@ -29,7 +29,7 @@ class Xrpl(ConanFile): requires = [ "ed25519/2015.03", - "grpc/1.50.1", + "grpc/1.72.0", "libarchive/3.8.1", "nudb/2.0.9", "openssl/3.5.4", @@ -43,7 +43,7 @@ class Xrpl(ConanFile): ] tool_requires = [ - "protobuf/3.21.12", + "protobuf/6.32.1", ] default_options = { @@ -61,6 +61,16 @@ class Xrpl(ConanFile): "ed25519/*:shared": False, "grpc/*:shared": False, "grpc/*:secure": True, + "grpc/*:codegen": True, + "grpc/*:cpp_plugin": True, + "grpc/*:csharp_ext": False, + "grpc/*:csharp_plugin": False, + "grpc/*:node_plugin": False, + "grpc/*:objective_c_plugin": False, + "grpc/*:php_plugin": False, + "grpc/*:python_plugin": False, + "grpc/*:ruby_plugin": False, + "grpc/*:otel_plugin": False, "libarchive/*:shared": False, "libarchive/*:with_acl": False, "libarchive/*:with_bzip2": False, @@ -118,7 +128,7 @@ class Xrpl(ConanFile): self.requires("boost/1.88.0", force=True, **transitive_headers_opt) self.requires("date/3.0.4", **transitive_headers_opt) self.requires("lz4/1.10.0", force=True) - self.requires("protobuf/3.21.12", force=True) + self.requires("protobuf/6.32.1", force=True) self.requires("sqlite3/3.49.1", force=True) if self.options.jemalloc: self.requires("jemalloc/5.3.0") From b986395ecc4a4543e0f0aa8be1bd8578f35da1e1 Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 5 Dec 2025 11:44:48 -0500 Subject: [PATCH 032/105] docs: Infer version of Conan dependency to export (#6112) This change updates a script in the documentation to automatically infer the version of a patched Conan dependency from the conan.lock file. --- BUILD.md | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/BUILD.md b/BUILD.md index 153406535c..54e02c6ae9 100644 --- a/BUILD.md +++ b/BUILD.md @@ -141,26 +141,37 @@ Alternatively, you can pull the patched recipes into the repository and use them locally: ```bash +# Extract the version number from the lockfile. +function extract_version { + version=$(cat conan.lock | sed -nE "s@.+${1}/(.+)#.+@\1@p" | head -n1) + echo ${version} +} + +# Define which recipes to export. +recipes=(ed25519 grpc secp256k1 snappy soci) + +# Selectively check out the recipes from our CCI fork. cd external mkdir -p conan-center-index cd conan-center-index git init git remote add origin git@github.com:XRPLF/conan-center-index.git git sparse-checkout init -git sparse-checkout set recipes/ed25519 -git sparse-checkout add recipes/grpc -git sparse-checkout add recipes/secp256k1 -git sparse-checkout add recipes/snappy -git sparse-checkout add recipes/soci +for recipe in ${recipes[@]}; do + echo "Checking out ${recipe}..." + git sparse-checkout add recipes/${recipe}/all +done git fetch origin master git checkout master -rm -rf .git cd ../.. -conan export --version 2015.03 external/conan-center-index/recipes/ed25519/all -conan export --version 1.72.0 external/conan-center-index/recipes/grpc/all -conan export --version 0.7.0 external/conan-center-index/recipes/secp256k1/all -conan export --version 1.1.10 external/conan-center-index/recipes/snappy/all -conan export --version 4.0.3 external/conan-center-index/recipes/soci/all + +# Export the recipes into the local cache. +for recipe in ${recipes[@]}; do + version=$(extract_version ${recipe}) + echo "Exporting ${recipe}/${version}..." + conan export --version $(extract_version ${recipe}) \ + external/conan-center-index/recipes/${recipe}/all +done ``` In the case we switch to a newer version of a dependency that still requires a From a4c60b41602c909919452607c546acf7708d2e17 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 8 Dec 2025 11:27:55 -0500 Subject: [PATCH 033/105] chore: Use updated secp256k1 recipe (#6118) This change updates the secp256k1 recipe that defines the SECP256K1_STATIC, so it no longer needs to be defined in the code here. Running the Conan update script also updated two other recipes in the lock file. --- conan.lock | 8 ++++---- include/xrpl/protocol/detail/secp256k1.h | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/conan.lock b/conan.lock index 410a04403b..1385ad05bd 100644 --- a/conan.lock +++ b/conan.lock @@ -6,10 +6,10 @@ "sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869", "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318", "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246", - "secp256k1/0.7.0#9210e4c655d0a665400378a663960d17%1764261276.764", + "secp256k1/0.7.0#9c4ab67bdc3860c16ea5b36aed8f74ea%1765202256.763", "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1762797952.535", "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1764175362.029", - "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1759134873.45", + "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1764863245.83", "openssl/3.5.4#a1d5835cc6ed5c5b8f3cd5b9b5d24205%1760106486.594", "nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1763150366.909", "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999", @@ -29,9 +29,9 @@ "build_requires": [ "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497", "strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1756234281.733", - "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1759134873.45", + "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1764863245.83", "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1756234232.901", - "msys2/cci.latest#5b73b10144f73cc5bfe0572ed9be39e1%1751977009.857", + "msys2/cci.latest#1996656c3c98e5765b25b60ff5cf77b4%1764840888.758", "m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846", "cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1764175359.44", "cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1764175359.429", diff --git a/include/xrpl/protocol/detail/secp256k1.h b/include/xrpl/protocol/detail/secp256k1.h index c0c3cd761b..c93734a539 100644 --- a/include/xrpl/protocol/detail/secp256k1.h +++ b/include/xrpl/protocol/detail/secp256k1.h @@ -1,7 +1,6 @@ #ifndef XRPL_PROTOCOL_SECP256K1_H_INCLUDED #define XRPL_PROTOCOL_SECP256K1_H_INCLUDED -#define SECP256K1_STATIC #include namespace ripple { From 9625514da8f979fe0ac399f4c30fae412098bd90 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 8 Dec 2025 12:35:23 -0500 Subject: [PATCH 034/105] chore: Clean up .gitignore and .gitattributes (#6001) The .gitignore and .gitattributes files contain references to files and directories that the current build no longer produces, so this change removes obsolete entries in these files, and does some general reorganizing of the remaining entries. --- .gitattributes | 4 -- .gitignore | 118 ++++++++++++++---------------------------------- docs/.gitignore | 3 -- 3 files changed, 35 insertions(+), 90 deletions(-) delete mode 100644 docs/.gitignore diff --git a/.gitattributes b/.gitattributes index 472cfb380c..bdfc989327 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,10 +1,6 @@ # Set default behaviour, in case users don't have core.autocrlf set. #* text=auto -# These annoying files -rippled.1 binary -LICENSE binary - # Visual Studio *.sln text eol=crlf *.vcproj text eol=crlf diff --git a/.gitignore b/.gitignore index d8c6b8a5f8..55844462e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,69 +1,46 @@ # .gitignore -bin/boostbook_catalog.xml -bin/config.log -bin/project-cache.jam - -# Ignore vim swap files. -*.swp - -# Ignore SCons support files. -.sconsign.dblite - -# Ignore python compiled files. -*.pyc - -# Ignore Macintosh Desktop Services Store files. +# Macintosh Desktop Services Store files. .DS_Store -# Ignore backup/temps +# Build, intermediate, and temporary artifacts. *~ - -# Ignore object files. *.o -.nih_c -tags -TAGS -GTAGS -GRTAGS -GPATH -bin/rippled -Debug/*.* -Release/*.* +*.pdb +*.swp +/.clangd +Debug/ +Release/ +/.build/ +/build/ +/db/ +/out.txt +/Testing/ +/tmp/ +CMakeSettings.json +CMakeUserPresets.json -# Ignore coverage files. +# Coverage files. *.gcno *.gcda *.gcov -# Levelization checking +# Profiling data. +gmon.out + +# Levelization data. .github/scripts/levelization/results/* !.github/scripts/levelization/results/loops.txt !.github/scripts/levelization/results/ordering.txt -# Ignore tmp directory. -tmp +# Customized configs. +/rippled.cfg +/validators.txt -# Ignore database directory. -db/ -db/*.db -db/*.db-* +# Locally patched Conan recipes +external/conan-center-index/ -# Ignore debug logs -debug_log.txt - -# Ignore customized configs -rippled.cfg -validators.txt - -# Doxygen generated documentation output -HtmlDocumentation -docs/html_doc - -# Xcode user-specific project settings -# Xcode -.DS_Store -/build/ +# XCode IDE. *.pbxuser !default.pbxuser *.mode1v3 @@ -76,41 +53,16 @@ xcuserdata profile *.moved-aside DerivedData -.idea/ *.hmap -# Intel Parallel Studio 2013 XE -My Amplifier XE Results - RippleD +# JetBrains IDE. +/.idea/ -# Compiler intermediate output -/out.txt +# Microsoft Visual Studio IDE. +/.vs/ +/.vscode/ -# Build Log -rippled-build.log - -# Profiling data -gmon.out - -Builds/VisualStudio2015/*.db -Builds/VisualStudio2015/*.user -Builds/VisualStudio2015/*.opendb -Builds/VisualStudio2015/*.sdf - -# MSVC -*.pdb -.vs/ -CMakeSettings.json -compile_commands.json -.clangd -packages -pkg_out -pkg -CMakeUserPresets.json -bld.rippled/ -.vscode - -# Suggested in-tree build directory -/.build*/ - -# Locally patched Conan recipes -external/conan-center-index/ +# AI tools. +/.augment +/.claude +/CLAUDE.md diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index b3ee85720f..0000000000 --- a/docs/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -html -temp -out.txt From 4565cc280bf2d91f8f88ef74cc807ece4c91a243 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 8 Dec 2025 13:39:38 -0500 Subject: [PATCH 035/105] chore: Fix docs readme and cmake (#6122) This change removes the unused `with_docs` option and fixes the README instructions on how to build the `docs` target. --- cmake/XrplDocs.cmake | 4 +--- docs/README.md | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cmake/XrplDocs.cmake b/cmake/XrplDocs.cmake index dda277bffa..a99bbe076b 100644 --- a/cmake/XrplDocs.cmake +++ b/cmake/XrplDocs.cmake @@ -2,9 +2,7 @@ docs target (optional) #]===================================================================] -option(with_docs "Include the docs target?" FALSE) - -if(NOT (with_docs OR only_docs)) +if(NOT only_docs) return() endif() diff --git a/docs/README.md b/docs/README.md index c95a871729..35fcbba2d1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -54,8 +54,8 @@ There is a `docs` target in the CMake configuration. ``` mkdir build cd build -cmake .. -cmake --build . --target docs +cmake -Donly_docs=ON .. +cmake --build . --target docs --parallel ``` The output will be in `build/docs/html`. From 42a432c5dc2af2754f4083b93f0ee0d616092681 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 10 Dec 2025 13:43:02 -0500 Subject: [PATCH 036/105] refactor: clean up `RPCHelpers` (#5684) This PR cleans up `RPCHelpers.h` and `RPCHelpers.cpp`. It splits out all the fetch-ledger functions to a new set of files, `RPCLedgerHelpers.h`/`RPCLedgerHelpers.cpp`, and moves the general-API functions to `ApiVersion.h`. There is no functionality change. --- include/xrpl/protocol/ApiVersion.h | 2 +- src/test/rpc/AccountCurrencies_test.cpp | 4 +- src/test/rpc/AccountLines_test.cpp | 38 ++- src/test/rpc/DepositAuthorized_test.cpp | 5 +- src/test/rpc/LedgerEntry_test.cpp | 8 +- src/test/rpc/LedgerRPC_test.cpp | 35 ++- ...estRPC_test.cpp => LedgerRequest_test.cpp} | 53 ++-- src/test/rpc/NoRippleCheck_test.cpp | 34 ++- src/xrpld/app/ledger/LedgerToJson.h | 4 +- src/xrpld/rpc/detail/Handler.cpp | 1 + src/xrpld/rpc/detail/RPCHelpers.cpp | 82 ------ src/xrpld/rpc/detail/RPCHelpers.h | 161 +++++++----- src/xrpld/rpc/detail/RPCLedgerHelpers.cpp | 235 +++++++++++------- src/xrpld/rpc/detail/RPCLedgerHelpers.h | 171 +++++++++---- src/xrpld/rpc/detail/ServerHandler.cpp | 8 + src/xrpld/rpc/handlers/AMMInfo.cpp | 22 +- src/xrpld/rpc/handlers/AccountInfo.cpp | 42 +++- src/xrpld/rpc/handlers/AccountObjects.cpp | 9 + src/xrpld/rpc/handlers/AccountTx.cpp | 6 +- src/xrpld/rpc/handlers/LedgerRequest.cpp | 12 +- 20 files changed, 579 insertions(+), 353 deletions(-) rename src/test/rpc/{LedgerRequestRPC_test.cpp => LedgerRequest_test.cpp} (89%) diff --git a/include/xrpl/protocol/ApiVersion.h b/include/xrpl/protocol/ApiVersion.h index 56d607a39b..d83884008d 100644 --- a/include/xrpl/protocol/ApiVersion.h +++ b/include/xrpl/protocol/ApiVersion.h @@ -95,7 +95,7 @@ setVersion(JsonObject& parent, unsigned int apiVersion, bool betaEnabled) * 3) the version number is unspecified and * APIVersionIfUnspecified is out of the supported range * - * @param jv a Json value that may or may not specifies + * @param jv a Json value that may or may not specify * the api version number * @param betaEnabled if the beta API version is enabled * @return the api version number diff --git a/src/test/rpc/AccountCurrencies_test.cpp b/src/test/rpc/AccountCurrencies_test.cpp index dd62d2fea4..c4833d11d4 100644 --- a/src/test/rpc/AccountCurrencies_test.cpp +++ b/src/test/rpc/AccountCurrencies_test.cpp @@ -26,7 +26,9 @@ class AccountCurrencies_test : public beast::unit_test::suite auto const result = env.rpc( "json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT(result[jss::error_message] == "ledgerHashNotString"); + BEAST_EXPECT( + result[jss::error_message] == + "Invalid field 'ledger_hash', not hex string."); } { // missing account field diff --git a/src/test/rpc/AccountLines_test.cpp b/src/test/rpc/AccountLines_test.cpp index d1bdc20687..e062959769 100644 --- a/src/test/rpc/AccountLines_test.cpp +++ b/src/test/rpc/AccountLines_test.cpp @@ -89,7 +89,7 @@ public: env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT( lines[jss::result][jss::error_message] == - "ledgerIndexMalformed"); + "Invalid field 'ledger_index', not string or number."); } { // Specify a different ledger that doesn't exist. @@ -190,16 +190,30 @@ public: testAccountLinesHistory(alice, ledger58Info, 52); { - // Surprisingly, it's valid to specify both index and hash, in - // which case the hash wins. + // Invalid to specify both index and hash Json::Value params; params[jss::account] = alice.human(); params[jss::ledger_hash] = to_string(ledger4Info.hash); params[jss::ledger_index] = ledger58Info.seq; - auto const lines = - env.rpc("json", "account_lines", to_string(params)); - BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); - BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26); + auto const lines = env.rpc( + "json", "account_lines", to_string(params))[jss::result]; + BEAST_EXPECT(lines[jss::error] == "invalidParams"); + BEAST_EXPECT( + lines[jss::error_message] == + "Exactly one of 'ledger_hash' or 'ledger_index' can be " + "specified."); + } + { + // Invalid index + Json::Value params; + params[jss::account] = alice.human(); + params[jss::ledger_index] = Json::objectValue; + auto const lines = env.rpc( + "json", "account_lines", to_string(params))[jss::result]; + BEAST_EXPECT(lines[jss::error] == "invalidParams"); + BEAST_EXPECT( + lines[jss::error_message] == + "Invalid field 'ledger_index', not string or number."); } { // alice should have 52 trust lines in the current ledger. @@ -839,7 +853,8 @@ public: request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); BEAST_EXPECT( - lines[jss::error][jss::message] == "ledgerIndexMalformed"); + lines[jss::error][jss::message] == + "Invalid field 'ledger_index', not string or number."); BEAST_EXPECT( lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); BEAST_EXPECT( @@ -994,8 +1009,11 @@ public: request[jss::id] = 5; request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); - BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); - BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26); + BEAST_EXPECT(lines[jss::error][jss::error] == "invalidParams"); + BEAST_EXPECT( + lines[jss::error][jss::message] == + "Exactly one of 'ledger_hash' or 'ledger_index' can be " + "specified."); BEAST_EXPECT( lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); BEAST_EXPECT( diff --git a/src/test/rpc/DepositAuthorized_test.cpp b/src/test/rpc/DepositAuthorized_test.cpp index b20f53592f..8ed52542d6 100644 --- a/src/test/rpc/DepositAuthorized_test.cpp +++ b/src/test/rpc/DepositAuthorized_test.cpp @@ -224,7 +224,10 @@ public: Json::Value args{depositAuthArgs(alice, becky, "-1")}; Json::Value const result{ env.rpc("json", "deposit_authorized", args.toStyledString())}; - verifyErr(result, "invalidParams", "ledgerIndexMalformed"); + verifyErr( + result, + "invalidParams", + "Invalid field 'ledger_index', not string or number."); } { // Request a ledger that doesn't exist yet as a string. diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index a0fde0f457..372f5676b0 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -477,10 +477,10 @@ class LedgerEntry_test : public beast::unit_test::suite "json", "ledger_entry", to_string(jvParams))[jss::result]; - auto const expectedErrMsg = fieldValue.isString() - ? "ledgerHashMalformed" - : "ledgerHashNotString"; - checkErrorValue(jrr, "invalidParams", expectedErrMsg); + checkErrorValue( + jrr, + "invalidParams", + "Invalid field 'ledger_hash', not hex string."); }; auto const& badValues = getBadValues(typeId); diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 57a20527d0..4a90793fa2 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -35,7 +35,10 @@ class LedgerRPC_test : public beast::unit_test::suite jv[jss::error_message] == ""); } else if (BEAST_EXPECT(jv.isMember(jss::error_message))) - BEAST_EXPECT(jv[jss::error_message] == msg); + BEAST_EXPECTS( + jv[jss::error_message] == msg, + "Expected error message \"" + msg + "\", received \"" + + jv[jss::error_message].asString() + "\""); } // Corrupt a valid address by replacing the 10th character with '!'. @@ -111,7 +114,10 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::ledger_index] = "potato"; auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; - checkErrorValue(jrr, "invalidParams", "ledgerIndexMalformed"); + checkErrorValue( + jrr, + "invalidParams", + "Invalid field 'ledger_index', not string or number."); } { @@ -120,7 +126,10 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::ledger_index] = -1; auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; - checkErrorValue(jrr, "invalidParams", "ledgerIndexMalformed"); + checkErrorValue( + jrr, + "invalidParams", + "Invalid field 'ledger_index', not string or number."); } { @@ -289,7 +298,9 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::ledger] = "invalid"; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT(jrr[jss::error_message] == "ledgerIndexMalformed"); + BEAST_EXPECT( + jrr[jss::error_message] == + "Invalid field 'ledger', not string or number."); // numeric index jvParams[jss::ledger] = 4; @@ -322,13 +333,17 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::ledger_hash] = "DEADBEEF" + hash3; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashMalformed"); + BEAST_EXPECT( + jrr[jss::error_message] == + "Invalid field 'ledger_hash', not hex string."); // request with non-string ledger_hash jvParams[jss::ledger_hash] = 2; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashNotString"); + BEAST_EXPECT( + jrr[jss::error_message] == + "Invalid field 'ledger_hash', not hex string."); // malformed (non hex) hash jvParams[jss::ledger_hash] = @@ -336,7 +351,9 @@ class LedgerRPC_test : public beast::unit_test::suite "7F2775F2F7485BB37307984C3C0F2340"; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT(jrr[jss::error_message] == "ledgerHashMalformed"); + BEAST_EXPECT( + jrr[jss::error_message] == + "Invalid field 'ledger_hash', not hex string."); // properly formed, but just doesn't exist jvParams[jss::ledger_hash] = @@ -374,7 +391,9 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::ledger_index] = "invalid"; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT(jrr[jss::error_message] == "ledgerIndexMalformed"); + BEAST_EXPECT( + jrr[jss::error_message] == + "Invalid field 'ledger_index', not string or number."); // numeric index for (auto i : {1, 2, 3, 4, 5, 6}) diff --git a/src/test/rpc/LedgerRequestRPC_test.cpp b/src/test/rpc/LedgerRequest_test.cpp similarity index 89% rename from src/test/rpc/LedgerRequestRPC_test.cpp rename to src/test/rpc/LedgerRequest_test.cpp index 0751b120aa..68d29d1901 100644 --- a/src/test/rpc/LedgerRequestRPC_test.cpp +++ b/src/test/rpc/LedgerRequest_test.cpp @@ -12,7 +12,7 @@ namespace ripple { namespace RPC { -class LedgerRequestRPC_test : public beast::unit_test::suite +class LedgerRequest_test : public beast::unit_test::suite { static constexpr char const* hash1 = "3020EB9E7BE24EF7D7A060CB051583EC117384636D1781AFB5B87F3E348DA489"; @@ -115,7 +115,7 @@ public: BEAST_EXPECT( RPC::contains_error(result[jss::result]) && result[jss::result][jss::error_message] == - "Invalid field 'ledger_hash'."); + "Invalid field 'ledger_hash', not hex string."); } { @@ -262,22 +262,43 @@ public: env.fund(XRP(100000), gw); env.close(); - Json::Value jvParams; - jvParams[jss::ledger_hash] = - "AB868A6CFEEC779C2FF845C0AF00A642259986AF40C01976A7F842B6918936C7"; - jvParams[jss::ledger_index] = "1"; - auto result = env.rpc( - "json", "ledger_request", jvParams.toStyledString())[jss::result]; - BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT(result[jss::status] == "error"); - BEAST_EXPECT( - result[jss::error_message] == - "Exactly one of ledger_hash and ledger_index can be set."); + { + Json::Value jvParams; + jvParams[jss::ledger_hash] = + "AB868A6CFEEC779C2FF845C0AF00A642259986AF40C01976A7F842B6918936" + "C7"; + jvParams[jss::ledger_index] = "1"; + auto const result = env.rpc( + "json", + "ledger_request", + jvParams.toStyledString())[jss::result]; + BEAST_EXPECT(result[jss::error] == "invalidParams"); + BEAST_EXPECT(result[jss::status] == "error"); + BEAST_EXPECT( + result[jss::error_message] == + "Exactly one of 'ledger_hash' or 'ledger_index' can be " + "specified."); + } + + { + Json::Value jvParams; + jvParams[jss::ledger_index] = "index"; + auto const result = env.rpc( + "json", + "ledger_request", + jvParams.toStyledString())[jss::result]; + BEAST_EXPECT(result[jss::error] == "invalidParams"); + BEAST_EXPECT(result[jss::status] == "error"); + BEAST_EXPECT( + result[jss::error_message] == + "Invalid field 'ledger_index', not number."); + } // the purpose in this test is to force the ledger expiration/out of // date check to trigger env.timeKeeper().adjustCloseTime(weeks{3}); - result = env.rpc(apiVersion, "ledger_request", "1")[jss::result]; + auto const result = + env.rpc(apiVersion, "ledger_request", "1")[jss::result]; BEAST_EXPECT(result[jss::status] == "error"); if (apiVersion == 1) { @@ -350,13 +371,13 @@ public: testLedgerRequest(); testEvolution(); forAllApiVersions( - std::bind_front(&LedgerRequestRPC_test::testBadInput, this)); + std::bind_front(&LedgerRequest_test::testBadInput, this)); testMoreThan256Closed(); testNonAdmin(); } }; -BEAST_DEFINE_TESTSUITE(LedgerRequestRPC, rpc, ripple); +BEAST_DEFINE_TESTSUITE(LedgerRequest, rpc, ripple); } // namespace RPC } // namespace ripple diff --git a/src/test/rpc/NoRippleCheck_test.cpp b/src/test/rpc/NoRippleCheck_test.cpp index 81ec097181..4d9af8524f 100644 --- a/src/test/rpc/NoRippleCheck_test.cpp +++ b/src/test/rpc/NoRippleCheck_test.cpp @@ -97,7 +97,9 @@ class NoRippleCheck_test : public beast::unit_test::suite auto const result = env.rpc( "json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT(result[jss::error_message] == "ledgerHashNotString"); + BEAST_EXPECT( + result[jss::error_message] == + "Invalid field 'ledger_hash', not hex string."); } { // account not found @@ -122,6 +124,36 @@ class NoRippleCheck_test : public beast::unit_test::suite BEAST_EXPECT(result[jss::error] == "actMalformed"); BEAST_EXPECT(result[jss::error_message] == "Account malformed."); } + + { + // ledger and ledger_hash are included + Json::Value params; + params[jss::account] = Account{"nobody"}.human(); + params[jss::role] = "user"; + params[jss::ledger] = "current"; + params[jss::ledger_hash] = "ABCDEF"; + auto const result = env.rpc( + "json", "noripple_check", to_string(params))[jss::result]; + BEAST_EXPECT(result[jss::error] == "invalidParams"); + BEAST_EXPECT( + result[jss::error_message] == + "Exactly one of 'ledger', 'ledger_hash', or 'ledger_index' can " + "be specified."); + } + + { + // invalid ledger + Json::Value params; + params[jss::account] = Account{"nobody"}.human(); + params[jss::role] = "user"; + params[jss::ledger] = Json::objectValue; + auto const result = env.rpc( + "json", "noripple_check", to_string(params))[jss::result]; + BEAST_EXPECT(result[jss::error] == "invalidParams"); + BEAST_EXPECT( + result[jss::error_message] == + "Invalid field 'ledger', not string or number."); + } } void diff --git a/src/xrpld/app/ledger/LedgerToJson.h b/src/xrpld/app/ledger/LedgerToJson.h index 6bc227ed43..cd3dcc9255 100644 --- a/src/xrpld/app/ledger/LedgerToJson.h +++ b/src/xrpld/app/ledger/LedgerToJson.h @@ -16,7 +16,7 @@ struct LedgerFill { LedgerFill( ReadView const& l, - RPC::Context* ctx, + RPC::Context const* ctx, int o = 0, std::vector q = {}) : ledger(l), options(o), txQueue(std::move(q)), context(ctx) @@ -38,7 +38,7 @@ struct LedgerFill ReadView const& ledger; int options; std::vector txQueue; - RPC::Context* context; + RPC::Context const* context; std::optional closeTime; }; diff --git a/src/xrpld/rpc/detail/Handler.cpp b/src/xrpld/rpc/detail/Handler.cpp index e05e9d0e6c..a4a1be3343 100644 --- a/src/xrpld/rpc/detail/Handler.cpp +++ b/src/xrpld/rpc/detail/Handler.cpp @@ -3,6 +3,7 @@ #include #include +#include #include diff --git a/src/xrpld/rpc/detail/RPCHelpers.cpp b/src/xrpld/rpc/detail/RPCHelpers.cpp index 6d1314ff51..a9c75a05e8 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCHelpers.cpp @@ -1,6 +1,3 @@ -#include -#include -#include #include #include #include @@ -21,60 +18,6 @@ namespace ripple { namespace RPC { -std::optional -accountFromStringStrict(std::string const& account) -{ - std::optional result; - - auto const publicKey = - parseBase58(TokenType::AccountPublic, account); - - if (publicKey) - result = calcAccountID(*publicKey); - else - result = parseBase58(account); - - return result; -} - -error_code_i -accountFromStringWithCode( - AccountID& result, - std::string const& strIdent, - bool bStrict) -{ - if (auto accountID = accountFromStringStrict(strIdent)) - { - result = *accountID; - return rpcSUCCESS; - } - - if (bStrict) - return rpcACT_MALFORMED; - - // We allow the use of the seeds which is poor practice - // and merely for debugging convenience. - auto const seed = parseGenericSeed(strIdent); - - if (!seed) - return rpcBAD_SEED; - - auto const keypair = generateKeyPair(KeyType::secp256k1, *seed); - - result = calcAccountID(keypair.first); - return rpcSUCCESS; -} - -Json::Value -accountFromString(AccountID& result, std::string const& strIdent, bool bStrict) -{ - error_code_i code = accountFromStringWithCode(result, strIdent, bStrict); - if (code != rpcSUCCESS) - return rpcError(code); - else - return Json::objectValue; -} - std::uint64_t getStartHint(std::shared_ptr const& sle, AccountID const& accountID) { @@ -146,31 +89,6 @@ parseAccountIds(Json::Value const& jvArray) return result; } -void -injectSLE(Json::Value& jv, SLE const& sle) -{ - jv = sle.getJson(JsonOptions::none); - if (sle.getType() == ltACCOUNT_ROOT) - { - if (sle.isFieldPresent(sfEmailHash)) - { - auto const& hash = sle.getFieldH128(sfEmailHash); - Blob const b(hash.begin(), hash.end()); - std::string md5 = strHex(makeSlice(b)); - boost::to_lower(md5); - // VFALCO TODO Give a name and move this constant - // to a more visible location. Also - // shouldn't this be https? - jv[jss::urlgravatar] = - str(boost::format("http://www.gravatar.com/avatar/%s") % md5); - } - } - else - { - jv[jss::Invalid] = true; - } -} - std::optional readLimitField( unsigned int& limit, diff --git a/src/xrpld/rpc/detail/RPCHelpers.h b/src/xrpld/rpc/detail/RPCHelpers.h index 808b975de3..3fa652d93b 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.h +++ b/src/xrpld/rpc/detail/RPCHelpers.h @@ -7,65 +7,45 @@ #include #include -#include #include #include #include #include -#include - -namespace Json { -class Value; -} namespace ripple { class ReadView; -class Transaction; namespace RPC { struct JsonContext; -/** Get an AccountID from an account ID or public key. */ -std::optional -accountFromStringStrict(std::string const&); - -// --> strIdent: public key, account ID, or regular seed. -// --> bStrict: Only allow account id or public key. -// -// Returns a Json::objectValue, containing error information if there was one. -Json::Value -accountFromString( - AccountID& result, - std::string const& strIdent, - bool bStrict = false); - -/** Decode account ID from string - @param[out] result account ID decoded from string - @param strIdent public key, account ID, or regular seed. - @param bStrict Only allow account id or public key. - @return code representing error, or rpcSUCCES on success -*/ -error_code_i -accountFromStringWithCode( - AccountID& result, - std::string const& strIdent, - bool bStrict = false); - -/** Gets the start hint for traversing account objects - * @param sle - Ledger entry defined by the marker passed into the RPC. - * @param accountID - The ID of the account whose objects you are traversing. +/** + * @brief Gets the start hint for traversing account objects. + * + * This function retrieves a hint value from the specified ledger entry (SLE) + * that can be used to optimize traversal of account objects for the given + * account ID. + * + * @param sle Shared pointer to the ledger entry (SLE) defined by the marker + * passed into the RPC. + * @param accountID The ID of the account whose objects are being traversed. + * @return A 64-bit unsigned integer representing the start hint for traversal. */ std::uint64_t getStartHint(std::shared_ptr const& sle, AccountID const& accountID); /** - * Tests if a SLE is owned by accountID. - * @param ledger - The ledger used to search for the sle. - * @param sle - The SLE to test for ownership. - * @param account - The account being tested for SLE ownership. + * @brief Tests if a ledger entry (SLE) is owned by the specified account. + * + * Determines whether the given SLE is related to or owned by the provided + * account ID within the context of the specified ledger. + * + * @param ledger The ledger view used to search for the SLE. + * @param sle Shared pointer to the SLE to test for ownership. + * @param accountID The account being tested for SLE ownership. + * @return true if the SLE is owned by the account, false otherwise. */ bool isRelatedToAccount( @@ -73,52 +53,105 @@ isRelatedToAccount( std::shared_ptr const& sle, AccountID const& accountID); +/** + * @brief Parses an array of account IDs from a JSON value. + * + * Extracts and returns a set of AccountID objects from the provided JSON array. + * + * @param jvArray The JSON value containing an array of account IDs. + * @return A hash_set containing the parsed AccountID objects. + */ hash_set parseAccountIds(Json::Value const& jvArray); -bool -isHexTxID(std::string const& txid); - -/** Inject JSON describing ledger entry - - Effects: - Adds the JSON description of `sle` to `jv`. - - If `sle` holds an account root, also adds the - urlgravatar field JSON if sfEmailHash is present. -*/ -void -injectSLE(Json::Value& jv, SLE const& sle); - -/** Retrieve the limit value from a JsonContext, or set a default - - then restrict the limit by max and min if not an ADMIN request. - - If there is an error, return it as JSON. -*/ +/** + * @brief Retrieves the limit value from a JsonContext or sets a default. + * + * Reads the "limit" field from the given JsonContext, applies default, minimum, + * and maximum constraints as appropriate, and returns an error as JSON if + * validation fails. + * + * @param limit Reference to the variable where the limit value will be stored. + * @param range The allowed range for the limit value. + * @param context The JSON context from which to read the limit. + * @return An optional JSON value containing an error if one occurred, or + * std::nullopt on success. + */ std::optional readLimitField( unsigned int& limit, - Tuning::LimitRange const&, - JsonContext const&); + Tuning::LimitRange const& range, + JsonContext const& context); +/** + * @brief Extracts a Seed from RPC parameters. + * + * Attempts to parse and return a Seed from the provided JSON RPC parameters. + * If parsing fails, an error is set in the provided error JSON value. + * + * @param params The JSON value containing RPC parameters. + * @param error Reference to a JSON value to be set with error information if + * parsing fails. + * @return An optional Seed if parsing is successful, or std::nullopt otherwise. + */ std::optional getSeedFromRPC(Json::Value const& params, Json::Value& error); +/** + * @brief Parses a RippleLib seed from RPC parameters. + * + * Attempts to extract and return a Seed from the provided JSON parameters using + * RippleLib conventions. + * + * @param params The JSON value containing RPC parameters. + * @return An optional Seed if parsing is successful, or std::nullopt otherwise. + */ std::optional parseRippleLibSeed(Json::Value const& params); +/** + * @brief Chooses the ledger entry type based on RPC parameters. + * + * Determines the appropriate LedgerEntryType to use based on the provided JSON + * parameters, and returns a pair containing the RPC status and the selected + * type. + * + * @param params The JSON value containing RPC parameters. + * @return A pair consisting of the RPC status and the chosen LedgerEntryType. + */ std::pair chooseLedgerEntryType(Json::Value const& params); /** - * Check if the type is a valid filtering type for account_objects method + * @brief Checks if the type is a valid filtering type for the account_objects + * method. * - * Since Amendments, DirectoryNode, FeeSettings, LedgerHashes can not be - * owned by an account, this function will return false in these situations. + * Determines whether the specified LedgerEntryType is valid for filtering in + * the account_objects RPC method. Types such as Amendments, DirectoryNode, + * FeeSettings, and LedgerHashes are not considered valid as they cannot be + * owned by an account. + * + * @param type The ledger entry type to check. + * @return true if the type is valid for account_objects filtering, false + * otherwise. */ bool isAccountObjectsValidType(LedgerEntryType const& type); +/** + * @brief Generates a keypair for signature from RPC parameters. + * + * Attempts to derive a public and secret key pair from the provided JSON RPC + * parameters. If an error occurs, it is set in the provided error JSON value. + * + * @param params The JSON value containing RPC parameters. + * @param error Reference to a JSON value to be set with error information if + * keypair generation fails. + * @param apiVersion The API version to use for keypair derivation (defaults to + * apiVersionIfUnspecified). + * @return An optional pair containing the public and secret keys if successful, + * or std::nullopt otherwise. + */ std::optional> keypairForSignature( Json::Value const& params, diff --git a/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp b/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp index 8ba7eeddcd..144378a1ec 100644 --- a/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp @@ -1,22 +1,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include -#include -#include #include -#include -#include #include -#include namespace ripple { namespace RPC { @@ -34,63 +24,123 @@ isValidatedOld(LedgerMaster& ledgerMaster, bool standalone) template Status -ledgerFromRequest(T& ledger, JsonContext& context) +ledgerFromHash( + T& ledger, + Json::Value hash, + Context const& context, + Json::StaticString const fieldName) +{ + uint256 ledgerHash; + if (!ledgerHash.parseHex(hash.asString())) + return { + rpcINVALID_PARAMS, expected_field_message(fieldName, "hex string")}; + return getLedger(ledger, ledgerHash, context); +} + +template +Status +ledgerFromIndex( + T& ledger, + Json::Value indexValue, + Context const& context, + Json::StaticString const fieldName) +{ + auto const index = indexValue.asString(); + + if (index == "current" || index.empty()) + return getLedger(ledger, LedgerShortcut::Current, context); + + if (index == "validated") + return getLedger(ledger, LedgerShortcut::Validated, context); + + if (index == "closed") + return getLedger(ledger, LedgerShortcut::Closed, context); + + std::uint32_t iVal; + if (!beast::lexicalCastChecked(iVal, index)) + return { + rpcINVALID_PARAMS, + expected_field_message(fieldName, "string or number")}; + + return getLedger(ledger, iVal, context); +} + +template +Status +ledgerFromRequest(T& ledger, JsonContext const& context) { ledger.reset(); auto& params = context.params; + auto const hasLedger = context.params.isMember(jss::ledger); + auto const hasHash = context.params.isMember(jss::ledger_hash); + auto const hasIndex = context.params.isMember(jss::ledger_index); - auto indexValue = params[jss::ledger_index]; - auto hashValue = params[jss::ledger_hash]; + if ((hasLedger + hasHash + hasIndex) > 1) + { + // while `ledger` is still supported, it is deprecated + // and therefore shouldn't be mentioned in the error message + if (hasLedger) + return { + rpcINVALID_PARAMS, + "Exactly one of 'ledger', 'ledger_hash', or " + "'ledger_index' can be specified."}; + return { + rpcINVALID_PARAMS, + "Exactly one of 'ledger_hash' or " + "'ledger_index' can be specified."}; + } // We need to support the legacy "ledger" field. - auto& legacyLedger = params[jss::ledger]; - if (legacyLedger) + if (hasLedger) { - if (legacyLedger.asString().size() > 12) - hashValue = legacyLedger; + auto& legacyLedger = params[jss::ledger]; + if (!legacyLedger.isString() && !legacyLedger.isUInt() && + !legacyLedger.isInt()) + { + return { + rpcINVALID_PARAMS, + expected_field_message(jss::ledger, "string or number")}; + } + if (legacyLedger.isString() && legacyLedger.asString().size() == 64) + return ledgerFromHash(ledger, legacyLedger, context, jss::ledger); else - indexValue = legacyLedger; + return ledgerFromIndex(ledger, legacyLedger, context, jss::ledger); } - if (!hashValue.isNull()) + if (hasHash) { - if (!hashValue.isString()) - return {rpcINVALID_PARAMS, "ledgerHashNotString"}; - - uint256 ledgerHash; - if (!ledgerHash.parseHex(hashValue.asString())) - return {rpcINVALID_PARAMS, "ledgerHashMalformed"}; - return getLedger(ledger, ledgerHash, context); + auto const& ledgerHash = params[jss::ledger_hash]; + if (!ledgerHash.isString()) + return { + rpcINVALID_PARAMS, + expected_field_message(jss::ledger_hash, "hex string")}; + return ledgerFromHash(ledger, ledgerHash, context, jss::ledger_hash); } - if (!indexValue.isConvertibleTo(Json::stringValue)) - return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; + if (hasIndex) + { + auto const& ledgerIndex = params[jss::ledger_index]; + if (!ledgerIndex.isString() && !ledgerIndex.isUInt() && + !ledgerIndex.isInt()) + { + return { + rpcINVALID_PARAMS, + expected_field_message(jss::ledger_index, "string or number")}; + } + return ledgerFromIndex(ledger, ledgerIndex, context, jss::ledger_index); + } - auto const index = indexValue.asString(); - - if (index == "current" || index.empty()) - return getLedger(ledger, LedgerShortcut::CURRENT, context); - - if (index == "validated") - return getLedger(ledger, LedgerShortcut::VALIDATED, context); - - if (index == "closed") - return getLedger(ledger, LedgerShortcut::CLOSED, context); - - std::uint32_t val; - if (!beast::lexicalCastChecked(val, index)) - return {rpcINVALID_PARAMS, "ledgerIndexMalformed"}; - - return getLedger(ledger, val, context); + // nothing specified, `index` has a default setting + return getLedger(ledger, LedgerShortcut::Current, context); } } // namespace template Status -ledgerFromRequest(T& ledger, GRPCContext& context) +ledgerFromRequest(T& ledger, GRPCContext const& context) { - R& request = context.params; + R const& request = context.params; return ledgerFromSpecifier(ledger, request.ledger(), context); } @@ -98,26 +148,26 @@ ledgerFromRequest(T& ledger, GRPCContext& context) template Status ledgerFromRequest<>( std::shared_ptr&, - GRPCContext&); + GRPCContext const&); // explicit instantiation of above function template Status ledgerFromRequest<>( std::shared_ptr&, - GRPCContext&); + GRPCContext const&); // explicit instantiation of above function template Status ledgerFromRequest<>( std::shared_ptr&, - GRPCContext&); + GRPCContext const&); template Status ledgerFromSpecifier( T& ledger, org::xrpl::rpc::v1::LedgerSpecifier const& specifier, - Context& context) + Context const& context) { ledger.reset(); @@ -141,7 +191,7 @@ ledgerFromSpecifier( if (shortcut == org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_VALIDATED) { - return getLedger(ledger, LedgerShortcut::VALIDATED, context); + return getLedger(ledger, LedgerShortcut::Validated, context); } else { @@ -151,13 +201,13 @@ ledgerFromSpecifier( org::xrpl::rpc::v1::LedgerSpecifier:: SHORTCUT_UNSPECIFIED) { - return getLedger(ledger, LedgerShortcut::CURRENT, context); + return getLedger(ledger, LedgerShortcut::Current, context); } else if ( shortcut == org::xrpl::rpc::v1::LedgerSpecifier::SHORTCUT_CLOSED) { - return getLedger(ledger, LedgerShortcut::CLOSED, context); + return getLedger(ledger, LedgerShortcut::Closed, context); } } } @@ -168,7 +218,7 @@ ledgerFromSpecifier( template Status -getLedger(T& ledger, uint256 const& ledgerHash, Context& context) +getLedger(T& ledger, uint256 const& ledgerHash, Context const& context) { ledger = context.ledgerMaster.getLedgerByHash(ledgerHash); if (ledger == nullptr) @@ -178,7 +228,7 @@ getLedger(T& ledger, uint256 const& ledgerHash, Context& context) template Status -getLedger(T& ledger, uint32_t ledgerIndex, Context& context) +getLedger(T& ledger, uint32_t ledgerIndex, Context const& context) { ledger = context.ledgerMaster.getLedgerBySeq(ledgerIndex); if (ledger == nullptr) @@ -207,7 +257,7 @@ getLedger(T& ledger, uint32_t ledgerIndex, Context& context) template Status -getLedger(T& ledger, LedgerShortcut shortcut, Context& context) +getLedger(T& ledger, LedgerShortcut shortcut, Context const& context) { if (isValidatedOld(context.ledgerMaster, context.app.config().standalone())) { @@ -216,7 +266,7 @@ getLedger(T& ledger, LedgerShortcut shortcut, Context& context) return {rpcNOT_SYNCED, "notSynced"}; } - if (shortcut == LedgerShortcut::VALIDATED) + if (shortcut == LedgerShortcut::Validated) { ledger = context.ledgerMaster.getValidatedLedger(); if (ledger == nullptr) @@ -231,13 +281,13 @@ getLedger(T& ledger, LedgerShortcut shortcut, Context& context) } else { - if (shortcut == LedgerShortcut::CURRENT) + if (shortcut == LedgerShortcut::Current) { ledger = context.ledgerMaster.getCurrentLedger(); XRPL_ASSERT( ledger->open(), "ripple::RPC::getLedger : current is open"); } - else if (shortcut == LedgerShortcut::CLOSED) + else if (shortcut == LedgerShortcut::Closed) { ledger = context.ledgerMaster.getClosedLedger(); XRPL_ASSERT( @@ -271,16 +321,16 @@ getLedger(T& ledger, LedgerShortcut shortcut, Context& context) // Explicit instantiation of above three functions template Status -getLedger<>(std::shared_ptr&, uint32_t, Context&); +getLedger<>(std::shared_ptr&, uint32_t, Context const&); template Status getLedger<>( std::shared_ptr&, LedgerShortcut shortcut, - Context&); + Context const&); template Status -getLedger<>(std::shared_ptr&, uint256 const&, Context&); +getLedger<>(std::shared_ptr&, uint256 const&, Context const&); // The previous version of the lookupLedger command would accept the // "ledger_index" argument as a string and silently treat it as a request to @@ -304,7 +354,7 @@ getLedger<>(std::shared_ptr&, uint256 const&, Context&); Status lookupLedger( std::shared_ptr& ledger, - JsonContext& context, + JsonContext const& context, Json::Value& result) { if (auto status = ledgerFromRequest(ledger, context)) @@ -327,7 +377,9 @@ lookupLedger( } Json::Value -lookupLedger(std::shared_ptr& ledger, JsonContext& context) +lookupLedger( + std::shared_ptr& ledger, + JsonContext const& context) { Json::Value result; if (auto status = lookupLedger(ledger, context, result)) @@ -336,8 +388,8 @@ lookupLedger(std::shared_ptr& ledger, JsonContext& context) return result; } -std::variant, Json::Value> -getLedgerByContext(RPC::JsonContext& context) +Expected, Json::Value> +getOrAcquireLedger(RPC::JsonContext const& context) { auto const hasHash = context.params.isMember(jss::ledger_hash); auto const hasIndex = context.params.isMember(jss::ledger_index); @@ -346,42 +398,45 @@ getLedgerByContext(RPC::JsonContext& context) auto& ledgerMaster = context.app.getLedgerMaster(); LedgerHash ledgerHash; - if ((hasHash && hasIndex) || !(hasHash || hasIndex)) + if ((hasHash + hasIndex) != 1) { - return RPC::make_param_error( - "Exactly one of ledger_hash and ledger_index can be set."); + return Unexpected( + RPC::make_param_error("Exactly one of 'ledger_hash' or " + "'ledger_index' can be specified.")); } - context.loadType = Resource::feeHeavyBurdenRPC; - if (hasHash) { - auto const& jsonHash = context.params[jss::ledger_hash]; + auto const& jsonHash = + context.params.get(jss::ledger_hash, Json::nullValue); if (!jsonHash.isString() || !ledgerHash.parseHex(jsonHash.asString())) - return RPC::invalid_field_error(jss::ledger_hash); + return Unexpected( + RPC::expected_field_error(jss::ledger_hash, "hex string")); } else { - auto const& jsonIndex = context.params[jss::ledger_index]; - if (!jsonIndex.isInt()) - return RPC::invalid_field_error(jss::ledger_index); + auto const& jsonIndex = + context.params.get(jss::ledger_index, Json::nullValue); + if (!jsonIndex.isInt() && !jsonIndex.isUInt()) + return Unexpected( + RPC::expected_field_error(jss::ledger_index, "number")); // We need a validated ledger to get the hash from the sequence if (ledgerMaster.getValidatedLedgerAge() > RPC::Tuning::maxValidatedLedgerAge) { if (context.apiVersion == 1) - return rpcError(rpcNO_CURRENT); - return rpcError(rpcNOT_SYNCED); + return Unexpected(rpcError(rpcNO_CURRENT)); + return Unexpected(rpcError(rpcNOT_SYNCED)); } ledgerIndex = jsonIndex.asInt(); auto ledger = ledgerMaster.getValidatedLedger(); if (ledgerIndex >= ledger->info().seq) - return RPC::make_param_error("Ledger index too large"); + return Unexpected(RPC::make_param_error("Ledger index too large")); if (ledgerIndex <= 0) - return RPC::make_param_error("Ledger index too small"); + return Unexpected(RPC::make_param_error("Ledger index too small")); auto const j = context.app.journal("RPCHandler"); // Try to get the hash of the desired ledger from the validated @@ -395,7 +450,7 @@ getLedgerByContext(RPC::JsonContext& context) auto refHash = hashOfSeq(*ledger, refIndex, j); XRPL_ASSERT( refHash, - "ripple::RPC::getLedgerByContext : nonzero ledger hash"); + "ripple::RPC::getOrAcquireLedger : nonzero ledger hash"); ledger = ledgerMaster.getLedgerByHash(*refHash); if (!ledger) @@ -411,7 +466,7 @@ getLedgerByContext(RPC::JsonContext& context) "acquiring ledger containing requested index"); jvResult[jss::acquiring] = getJson(LedgerFill(*il, &context)); - return jvResult; + return Unexpected(jvResult); } if (auto il = context.app.getInboundLedgers().find(*refHash)) @@ -420,18 +475,18 @@ getLedgerByContext(RPC::JsonContext& context) rpcLGR_NOT_FOUND, "acquiring ledger containing requested index"); jvResult[jss::acquiring] = il->getJson(0); - return jvResult; + return Unexpected(jvResult); } // Likely the app is shutting down - return Json::Value(); + return Unexpected(Json::Value()); } neededHash = hashOfSeq(*ledger, ledgerIndex, j); } XRPL_ASSERT( neededHash, - "ripple::RPC::getLedgerByContext : nonzero needed hash"); + "ripple::RPC::getOrAcquireLedger : nonzero needed hash"); ledgerHash = neededHash ? *neededHash : beast::zero; // kludge } @@ -448,10 +503,10 @@ getLedgerByContext(RPC::JsonContext& context) return ledger; if (auto il = context.app.getInboundLedgers().find(ledgerHash)) - return il->getJson(0); + return Unexpected(il->getJson(0)); - return RPC::make_error( - rpcNOT_READY, "findCreate failed to return an inbound ledger"); + return Unexpected(RPC::make_error( + rpcNOT_READY, "findCreate failed to return an inbound ledger")); } } // namespace RPC diff --git a/src/xrpld/rpc/detail/RPCLedgerHelpers.h b/src/xrpld/rpc/detail/RPCLedgerHelpers.h index 17382d3c53..0a070a16ab 100644 --- a/src/xrpld/rpc/detail/RPCLedgerHelpers.h +++ b/src/xrpld/rpc/detail/RPCLedgerHelpers.h @@ -7,17 +7,9 @@ #include #include -#include #include -#include -#include #include -#include - -namespace Json { -class Value; -} namespace ripple { @@ -28,66 +20,159 @@ namespace RPC { struct JsonContext; -/** Get ledger by hash - If there is no error in the return value, the ledger pointer will have - been filled -*/ +enum class LedgerShortcut { Current, Closed, Validated }; + +/** + * @brief Retrieves a ledger by its hash. + * + * This function attempts to find and fill the provided ledger pointer with the + * ledger corresponding to the specified hash. If the operation is successful, + * the ledger pointer will be set; otherwise, an error status is returned. + * + * @tparam T Type of the ledger pointer to be filled. + * @param ledger Reference to the ledger pointer to be filled. + * @param ledgerHash The hash of the ledger to retrieve. + * @param context The RPC context containing request parameters and environment. + * @return Status indicating success or failure of the operation. + */ template Status -getLedger(T& ledger, uint256 const& ledgerHash, Context& context); +getLedger(T& ledger, uint256 const& ledgerHash, Context const& context); -/** Get ledger by sequence - If there is no error in the return value, the ledger pointer will have - been filled -*/ +/** + * @brief Retrieves a ledger by its sequence index. + * + * This function attempts to find and fill the provided ledger pointer with the + * ledger corresponding to the specified sequence index. If the operation is + * successful, the ledger pointer will be set; otherwise, an error status is + * returned. + * + * @tparam T Type of the ledger pointer to be filled. + * @param ledger Reference to the ledger pointer to be filled. + * @param ledgerIndex The sequence index of the ledger to retrieve. + * @param context The RPC context containing request parameters and environment. + * @return Status indicating success or failure of the operation. + */ template Status -getLedger(T& ledger, uint32_t ledgerIndex, Context& context); +getLedger(T& ledger, uint32_t ledgerIndex, Context const& context); -enum LedgerShortcut { CURRENT, CLOSED, VALIDATED }; -/** Get ledger specified in shortcut. - If there is no error in the return value, the ledger pointer will have - been filled -*/ +/** + * @brief Retrieves a ledger specified by a `LedgerShortcut`. + * + * This function attempts to find and fill the provided ledger pointer with the + * ledger corresponding to the specified shortcut. If the operation is + * successful, the ledger pointer will be set; otherwise, an error status is + * returned. + * + * @tparam T Type of the ledger pointer to be filled. + * @param ledger Reference to the ledger pointer to be filled. + * @param shortcut The shortcut specifying which ledger to retrieve. + * @param context The RPC context containing request parameters and environment. + * @return Status indicating success or failure of the operation. + */ template Status -getLedger(T& ledger, LedgerShortcut shortcut, Context& context); +getLedger(T& ledger, LedgerShortcut shortcut, Context const& context); -/** Look up a ledger from a request and fill a Json::Result with either - an error, or data representing a ledger. - - If there is no error in the return value, then the ledger pointer will have - been filled. -*/ +/** + * @brief Looks up a ledger from a request and returns a Json::Value with either + * an error or ledger data. + * + * This function attempts to find a ledger based on the parameters in the given + * JsonContext. On success, the ledger pointer is filled and a Json::Value + * representing the ledger is returned. On failure, a Json::Value describing the + * error is returned. + * + * @param ledger Reference to a shared pointer to the ledger to be filled. + * @param context The RPC JsonContext containing request parameters and + * environment. + * @return Json::Value containing either the ledger data or an error + * description. + */ Json::Value -lookupLedger(std::shared_ptr&, JsonContext&); +lookupLedger(std::shared_ptr&, JsonContext const&); -/** Look up a ledger from a request and fill a Json::Result with the data - representing a ledger. - - If the returned Status is OK, the ledger pointer will have been filled. -*/ +/** + * @brief Looks up a ledger from a request and fills a Json::Value with ledger + * data. + * + * This function attempts to find a ledger based on the parameters in the given + * JsonContext. On success, the ledger pointer is filled and the result + * parameter is populated with ledger data. On failure, an error status is + * returned. + * + * @param ledger Reference to a shared pointer to the ledger to be filled. + * @param context The RPC JsonContext containing request parameters and + * environment. + * @param result Reference to a Json::Value to be filled with ledger data. + * @return Status indicating success or failure of the operation. + */ Status lookupLedger( std::shared_ptr&, - JsonContext&, + JsonContext const&, Json::Value& result); +/** + * @brief Retrieves a ledger from a gRPC request context. + * + * This function attempts to find and fill the provided ledger pointer based on + * the parameters in the given gRPC context. On success, the ledger pointer is + * filled. + * + * @tparam T Type of the ledger pointer to be filled. + * @tparam R Type of the gRPC request. + * @param ledger Reference to the ledger pointer to be filled. + * @param context The gRPC context containing request parameters and + * environment. + * @return Status indicating success or failure of the operation. + */ template Status -ledgerFromRequest(T& ledger, GRPCContext& context); +ledgerFromRequest(T& ledger, GRPCContext const& context); +/** + * @brief Retrieves a ledger based on a LedgerSpecifier. + * + * This function attempts to find and fill the provided ledger pointer based on + * the specified LedgerSpecifier. On success, the ledger pointer is filled. + * + * @tparam T Type of the ledger pointer to be filled. + * @param ledger Reference to the ledger pointer to be filled. + * @param specifier The LedgerSpecifier describing which ledger to retrieve. + * @param context The RPC context containing request parameters and environment. + * @return Status indicating success or failure of the operation. + */ template Status ledgerFromSpecifier( T& ledger, org::xrpl::rpc::v1::LedgerSpecifier const& specifier, - Context& context); + Context const& context); -/** Return a ledger based on ledger_hash or ledger_index, - or an RPC error */ -std::variant, Json::Value> -getLedgerByContext(RPC::JsonContext& context); +/** + * @brief Retrieves or acquires a ledger based on the parameters provided in the + * given JsonContext. + * + * This function differs from the other ledger getter functions in this file in + * that it attempts to either retrieve an existing ledger or acquire it if it is + * not already available, based on the context of the RPC request. It returns an + * Expected containing either a shared pointer to the requested immutable Ledger + * object or a Json::Value describing an error. Unlike the other getLedger or + * lookupLedger functions, which typically fill a provided ledger pointer or + * result object and return a Status, this function encapsulates both the result + * and error in a single return value, making it easier to handle success and + * failure cases in a unified way. + * + * @param context The RPC JsonContext containing request parameters and + * environment. + * @return Expected, Json::Value> + * On success, contains a shared pointer to the requested Ledger. + * On failure, contains a Json::Value describing the error. + */ +Expected, Json::Value> +getOrAcquireLedger(RPC::JsonContext const& context); } // namespace RPC diff --git a/src/xrpld/rpc/detail/ServerHandler.cpp b/src/xrpld/rpc/detail/ServerHandler.cpp index 4a7f1d9b7d..8a42153105 100644 --- a/src/xrpld/rpc/detail/ServerHandler.cpp +++ b/src/xrpld/rpc/detail/ServerHandler.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -31,10 +32,17 @@ #include #include +#include #include namespace ripple { +class Peer; +class LedgerMaster; +class Transaction; +class ValidatorKeys; +class CanonicalTXSet; + static bool isStatusRequest(http_request_type const& request) { diff --git a/src/xrpld/rpc/handlers/AMMInfo.cpp b/src/xrpld/rpc/handlers/AMMInfo.cpp index dda30fcfa7..0504adca02 100644 --- a/src/xrpld/rpc/handlers/AMMInfo.cpp +++ b/src/xrpld/rpc/handlers/AMMInfo.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -13,22 +12,6 @@ namespace ripple { -std::optional -getAccount(Json::Value const& v, Json::Value& result) -{ - std::string strIdent(v.asString()); - AccountID accountID; - - if (auto jv = RPC::accountFromString(accountID, strIdent)) - { - for (auto it = jv.begin(); it != jv.end(); ++it) - result[it.memberName()] = (*it); - - return std::nullopt; - } - return std::optional(accountID); -} - Expected getIssue(Json::Value const& v, beast::Journal j) { @@ -109,7 +92,8 @@ doAMMInfo(RPC::JsonContext& context) if (params.isMember(jss::amm_account)) { - auto const id = getAccount(params[jss::amm_account], result); + auto const id = + parseBase58((params[jss::amm_account].asString())); if (!id) return Unexpected(rpcACT_MALFORMED); auto const sle = ledger->read(keylet::account(*id)); @@ -122,7 +106,7 @@ doAMMInfo(RPC::JsonContext& context) if (params.isMember(jss::account)) { - accountID = getAccount(params[jss::account], result); + accountID = parseBase58(params[jss::account].asString()); if (!accountID || !ledger->read(keylet::account(*accountID))) return Unexpected(rpcACT_MALFORMED); } diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index e9f95d450b..1bf05276f2 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -12,8 +11,47 @@ #include #include +#include + namespace ripple { +/** + * @brief Injects JSON describing a ledger entry. + * + * @param jv The JSON value to populate. + * @param sle The ledger entry to describe. + * + * @details + * Populates the provided JSON value with the description of the specified + * ledger entry. If the entry is an account root and contains an email hash, + * adds a 'urlgravatar' field with the corresponding Gravatar URL. + * If the entry is not an account root, sets the 'Invalid' field to true. + */ +void +injectSLE(Json::Value& jv, SLE const& sle) +{ + jv = sle.getJson(JsonOptions::none); + if (sle.getType() == ltACCOUNT_ROOT) + { + if (sle.isFieldPresent(sfEmailHash)) + { + auto const& hash = sle.getFieldH128(sfEmailHash); + Blob const b(hash.begin(), hash.end()); + std::string md5 = strHex(makeSlice(b)); + boost::to_lower(md5); + // VFALCO TODO Give a name and move this constant + // to a more visible location. Also + // shouldn't this be https? + jv[jss::urlgravatar] = + str(boost::format("http://www.gravatar.com/avatar/%s") % md5); + } + } + else + { + jv[jss::Invalid] = true; + } +} + // { // account: , // ledger_hash : @@ -109,7 +147,7 @@ doAccountInfo(RPC::JsonContext& context) } Json::Value jvAccepted(Json::objectValue); - RPC::injectSLE(jvAccepted, *sleAccepted); + injectSLE(jvAccepted, *sleAccepted); result[jss::account_data] = jvAccepted; Json::Value acctFlags{Json::objectValue}; diff --git a/src/xrpld/rpc/handlers/AccountObjects.cpp b/src/xrpld/rpc/handlers/AccountObjects.cpp index 82ff1782e4..669d96a44f 100644 --- a/src/xrpld/rpc/handlers/AccountObjects.cpp +++ b/src/xrpld/rpc/handlers/AccountObjects.cpp @@ -159,6 +159,15 @@ doAccountNFTs(RPC::JsonContext& context) return result; } +/** Gathers all objects for an account in a ledger. + @param ledger Ledger to search account objects. + @param account AccountID to find objects for. + @param typeFilter Gathers objects of these types. empty gathers all types. + @param dirIndex Begin gathering account objects from this directory. + @param entryIndex Begin gathering objects from this directory node. + @param limit Maximum number of objects to find. + @param jvResult A JSON result that holds the request objects. +*/ bool getAccountObjects( ReadView const& ledger, diff --git a/src/xrpld/rpc/handlers/AccountTx.cpp b/src/xrpld/rpc/handlers/AccountTx.cpp index b3f1ec65ef..e248764194 100644 --- a/src/xrpld/rpc/handlers/AccountTx.cpp +++ b/src/xrpld/rpc/handlers/AccountTx.cpp @@ -92,11 +92,11 @@ parseLedgerArgs(RPC::Context& context, Json::Value const& params) std::string ledgerStr = params[jss::ledger_index].asString(); if (ledgerStr == "current" || ledgerStr.empty()) - ledger = LedgerShortcut::CURRENT; + ledger = LedgerShortcut::Current; else if (ledgerStr == "closed") - ledger = LedgerShortcut::CLOSED; + ledger = LedgerShortcut::Closed; else if (ledgerStr == "validated") - ledger = LedgerShortcut::VALIDATED; + ledger = LedgerShortcut::Validated; else { RPC::Status status{ diff --git a/src/xrpld/rpc/handlers/LedgerRequest.cpp b/src/xrpld/rpc/handlers/LedgerRequest.cpp index fd06ab30ba..2846bb9f08 100644 --- a/src/xrpld/rpc/handlers/LedgerRequest.cpp +++ b/src/xrpld/rpc/handlers/LedgerRequest.cpp @@ -4,8 +4,7 @@ #include #include - -#include +#include namespace ripple { @@ -16,12 +15,13 @@ namespace ripple { Json::Value doLedgerRequest(RPC::JsonContext& context) { - auto res = getLedgerByContext(context); + context.loadType = Resource::feeHeavyBurdenRPC; + auto res = RPC::getOrAcquireLedger(context); - if (std::holds_alternative(res)) - return std::get(res); + if (!res.has_value()) + return res.error(); - auto const& ledger = std::get>(res); + auto const& ledger = res.value(); Json::Value jvResult; jvResult[jss::ledger_index] = ledger->info().seq; From bff5954acf09bdbea6d89ad79c04ca6646d10b9f Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 10 Dec 2025 14:12:14 -0500 Subject: [PATCH 037/105] refactor: rename `LedgerInfo` to `LedgerHeader` (#6136) This PR renames `LedgerInfo` to `LedgerHeader`. Namely, `LedgerInfo` was already an alias for `LedgerHeader`, and the comments next to the alias suggested that it would make sense to rename it, since that makes it clearer what it is. --- include/xrpl/ledger/CachedView.h | 2 +- include/xrpl/ledger/OpenView.h | 6 +++--- include/xrpl/ledger/ReadView.h | 2 +- include/xrpl/ledger/detail/ApplyViewBase.h | 2 +- include/xrpl/protocol/LedgerHeader.h | 6 ------ src/libxrpl/ledger/ApplyViewBase.cpp | 2 +- src/libxrpl/ledger/OpenView.cpp | 2 +- src/test/app/SHAMapStore_test.cpp | 4 ++-- src/test/overlay/compression_test.cpp | 4 ++-- src/test/rpc/AccountLines_test.cpp | 16 +++++++-------- src/xrpld/app/ledger/Ledger.cpp | 16 +++++++-------- src/xrpld/app/ledger/Ledger.h | 14 ++++++------- src/xrpld/app/ledger/LedgerReplayer.h | 4 ++-- .../app/ledger/detail/LedgerDeltaAcquire.cpp | 2 +- .../app/ledger/detail/LedgerDeltaAcquire.h | 2 +- .../app/ledger/detail/LedgerReplayer.cpp | 4 ++-- src/xrpld/app/ledger/detail/LedgerToJson.cpp | 4 ++-- src/xrpld/app/rdb/RelationalDatabase.h | 6 +++--- src/xrpld/app/rdb/backend/SQLiteDatabase.h | 4 ++-- src/xrpld/app/rdb/backend/detail/Node.cpp | 14 ++++++------- src/xrpld/app/rdb/backend/detail/Node.h | 10 +++++----- .../app/rdb/backend/detail/SQLiteDatabase.cpp | 20 +++++++++---------- src/xrpld/overlay/detail/PeerImp.cpp | 2 +- 23 files changed, 71 insertions(+), 77 deletions(-) diff --git a/include/xrpl/ledger/CachedView.h b/include/xrpl/ledger/CachedView.h index 5e924d8bca..ad1125637b 100644 --- a/include/xrpl/ledger/CachedView.h +++ b/include/xrpl/ledger/CachedView.h @@ -47,7 +47,7 @@ public: return base_.open(); } - LedgerInfo const& + LedgerHeader const& info() const override { return base_.info(); diff --git a/include/xrpl/ledger/OpenView.h b/include/xrpl/ledger/OpenView.h index a1e9c201e8..9027f57b97 100644 --- a/include/xrpl/ledger/OpenView.h +++ b/include/xrpl/ledger/OpenView.h @@ -82,7 +82,7 @@ private: monotonic_resource_; txs_map txs_; Rules rules_; - LedgerInfo info_; + LedgerHeader info_; ReadView const* base_; detail::RawStateTable items_; std::shared_ptr hold_; @@ -158,7 +158,7 @@ public: Effects: - The LedgerInfo is copied from the base. + The LedgerHeader is copied from the base. The rules are inherited from the base. @@ -188,7 +188,7 @@ public: // ReadView - LedgerInfo const& + LedgerHeader const& info() const override; Fees const& diff --git a/include/xrpl/ledger/ReadView.h b/include/xrpl/ledger/ReadView.h index e8344ac4e2..4108b19967 100644 --- a/include/xrpl/ledger/ReadView.h +++ b/include/xrpl/ledger/ReadView.h @@ -80,7 +80,7 @@ public: } /** Returns information about the ledger. */ - virtual LedgerInfo const& + virtual LedgerHeader const& info() const = 0; /** Returns true if this reflects an open ledger. */ diff --git a/include/xrpl/ledger/detail/ApplyViewBase.h b/include/xrpl/ledger/detail/ApplyViewBase.h index e5564d1e33..7bf490cd9c 100644 --- a/include/xrpl/ledger/detail/ApplyViewBase.h +++ b/include/xrpl/ledger/detail/ApplyViewBase.h @@ -27,7 +27,7 @@ public: bool open() const override; - LedgerInfo const& + LedgerHeader const& info() const override; Fees const& diff --git a/include/xrpl/protocol/LedgerHeader.h b/include/xrpl/protocol/LedgerHeader.h index 69368f9e5e..80a481f7d1 100644 --- a/include/xrpl/protocol/LedgerHeader.h +++ b/include/xrpl/protocol/LedgerHeader.h @@ -53,12 +53,6 @@ struct LedgerHeader NetClock::time_point closeTime = {}; }; -// We call them "headers" in conversation -// but "info" in code. Unintuitive. -// This alias lets us give the "correct" name to the class -// without yet disturbing existing uses. -using LedgerInfo = LedgerHeader; - // ledger close flags static std::uint32_t const sLCF_NoConsensusTime = 0x01; diff --git a/src/libxrpl/ledger/ApplyViewBase.cpp b/src/libxrpl/ledger/ApplyViewBase.cpp index bb5e316669..f296c3cef2 100644 --- a/src/libxrpl/ledger/ApplyViewBase.cpp +++ b/src/libxrpl/ledger/ApplyViewBase.cpp @@ -16,7 +16,7 @@ ApplyViewBase::open() const return base_->open(); } -LedgerInfo const& +LedgerHeader const& ApplyViewBase::info() const { return base_->info(); diff --git a/src/libxrpl/ledger/OpenView.cpp b/src/libxrpl/ledger/OpenView.cpp index 36cde12f82..25b2ba8a0c 100644 --- a/src/libxrpl/ledger/OpenView.cpp +++ b/src/libxrpl/ledger/OpenView.cpp @@ -115,7 +115,7 @@ OpenView::apply(TxsRawView& to) const //--- -LedgerInfo const& +LedgerHeader const& OpenView::info() const { return info_; diff --git a/src/test/app/SHAMapStore_test.cpp b/src/test/app/SHAMapStore_test.cpp index e472685ec0..8ec5a6fd23 100644 --- a/src/test/app/SHAMapStore_test.cpp +++ b/src/test/app/SHAMapStore_test.cpp @@ -49,11 +49,11 @@ class SHAMapStore_test : public beast::unit_test::suite auto const seq = json[jss::result][jss::ledger_index].asUInt(); - std::optional oinfo = + std::optional oinfo = env.app().getRelationalDatabase().getLedgerInfoByIndex(seq); if (!oinfo) return false; - LedgerInfo const& info = oinfo.value(); + LedgerHeader const& info = oinfo.value(); std::string const outHash = to_string(info.hash); LedgerIndex const outSeq = info.seq; diff --git a/src/test/overlay/compression_test.cpp b/src/test/overlay/compression_test.cpp index 4cee6f8034..4e001115d1 100644 --- a/src/test/overlay/compression_test.cpp +++ b/src/test/overlay/compression_test.cpp @@ -38,7 +38,7 @@ using namespace ripple::test; using namespace ripple::test::jtx; static uint256 -ledgerHash(LedgerInfo const& info) +ledgerHash(LedgerHeader const& info) { return ripple::sha512Half( HashPrefix::ledgerMaster, @@ -252,7 +252,7 @@ public: for (int i = 0; i < n; i++) { - LedgerInfo info; + LedgerHeader info; info.seq = i; info.parentCloseTime = ct; info.hash = ripple::sha512Half(i); diff --git a/src/test/rpc/AccountLines_test.cpp b/src/test/rpc/AccountLines_test.cpp index e062959769..2bc6c38779 100644 --- a/src/test/rpc/AccountLines_test.cpp +++ b/src/test/rpc/AccountLines_test.cpp @@ -68,7 +68,7 @@ public: } env.fund(XRP(10000), alice); env.close(); - LedgerInfo const ledger3Info = env.closed()->info(); + LedgerHeader const ledger3Info = env.closed()->info(); BEAST_EXPECT(ledger3Info.seq == 3); { @@ -118,7 +118,7 @@ public: env(pay(gw1, alice, gw1Currency(50 + c))); } env.close(); - LedgerInfo const ledger4Info = env.closed()->info(); + LedgerHeader const ledger4Info = env.closed()->info(); BEAST_EXPECT(ledger4Info.seq == 4); // Add another set of trust lines in another ledger so we can see @@ -153,13 +153,13 @@ public: tfSetNoRipple | tfSetFreeze | tfSetDeepFreeze)); } env.close(); - LedgerInfo const ledger58Info = env.closed()->info(); + LedgerHeader const ledger58Info = env.closed()->info(); BEAST_EXPECT(ledger58Info.seq == 58); // A re-usable test for historic ledgers. auto testAccountLinesHistory = [this, &env]( Account const& account, - LedgerInfo const& info, + LedgerHeader const& info, int count) { // Get account_lines by ledger index. Json::Value paramsSeq; @@ -817,7 +817,7 @@ public: } env.fund(XRP(10000), alice); env.close(); - LedgerInfo const ledger3Info = env.closed()->info(); + LedgerHeader const ledger3Info = env.closed()->info(); BEAST_EXPECT(ledger3Info.seq == 3); { @@ -899,7 +899,7 @@ public: env(pay(gw1, alice, gw1Currency(50 + c))); } env.close(); - LedgerInfo const ledger4Info = env.closed()->info(); + LedgerHeader const ledger4Info = env.closed()->info(); BEAST_EXPECT(ledger4Info.seq == 4); // Add another set of trust lines in another ledger so we can see @@ -934,13 +934,13 @@ public: tfSetNoRipple | tfSetFreeze | tfSetDeepFreeze)); } env.close(); - LedgerInfo const ledger58Info = env.closed()->info(); + LedgerHeader const ledger58Info = env.closed()->info(); BEAST_EXPECT(ledger58Info.seq == 58); // A re-usable test for historic ledgers. auto testAccountLinesHistory = [this, &env]( Account const& account, - LedgerInfo const& info, + LedgerHeader const& info, int count) { // Get account_lines by ledger index. Json::Value paramsSeq; diff --git a/src/xrpld/app/ledger/Ledger.cpp b/src/xrpld/app/ledger/Ledger.cpp index 6bf3170f18..aaf71b2dc3 100644 --- a/src/xrpld/app/ledger/Ledger.cpp +++ b/src/xrpld/app/ledger/Ledger.cpp @@ -32,7 +32,7 @@ namespace ripple { create_genesis_t const create_genesis{}; uint256 -calculateLedgerHash(LedgerInfo const& info) +calculateLedgerHash(LedgerHeader const& info) { // VFALCO This has to match addRaw in View.h. return sha512Half( @@ -210,7 +210,7 @@ Ledger::Ledger( } Ledger::Ledger( - LedgerInfo const& info, + LedgerHeader const& info, bool& loaded, bool acquire, Config const& config, @@ -285,7 +285,7 @@ Ledger::Ledger(Ledger const& prevLedger, NetClock::time_point closeTime) } } -Ledger::Ledger(LedgerInfo const& info, Config const& config, Family& family) +Ledger::Ledger(LedgerHeader const& info, Config const& config, Family& family) : mImmutable(true) , txMap_(SHAMapType::TRANSACTION, info.txHash, family) , stateMap_(SHAMapType::STATE, info.accountHash, family) @@ -1042,13 +1042,13 @@ Ledger::invariants() const /* * Make ledger using info loaded from database. * - * @param LedgerInfo: Ledger information. + * @param LedgerHeader: Ledger information. * @param app: Link to the Application. * @param acquire: Acquire the ledger if not found locally. * @return Shared pointer to the ledger. */ std::shared_ptr -loadLedgerHelper(LedgerInfo const& info, Application& app, bool acquire) +loadLedgerHelper(LedgerHeader const& info, Application& app, bool acquire) { bool loaded; auto ledger = std::make_shared( @@ -1088,7 +1088,7 @@ finishLoadByIndexOrHash( std::tuple, std::uint32_t, uint256> getLatestLedger(Application& app) { - std::optional const info = + std::optional const info = app.getRelationalDatabase().getNewestLedgerInfo(); if (!info) return {std::shared_ptr(), {}, {}}; @@ -1098,7 +1098,7 @@ getLatestLedger(Application& app) std::shared_ptr loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire) { - if (std::optional info = + if (std::optional info = app.getRelationalDatabase().getLedgerInfoByIndex(ledgerIndex)) { std::shared_ptr ledger = loadLedgerHelper(*info, app, acquire); @@ -1111,7 +1111,7 @@ loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire) std::shared_ptr loadByHash(uint256 const& ledgerHash, Application& app, bool acquire) { - if (std::optional info = + if (std::optional info = app.getRelationalDatabase().getLedgerInfoByHash(ledgerHash)) { std::shared_ptr ledger = loadLedgerHelper(*info, app, acquire); diff --git a/src/xrpld/app/ledger/Ledger.h b/src/xrpld/app/ledger/Ledger.h index 30bedc0447..cc3bc43c50 100644 --- a/src/xrpld/app/ledger/Ledger.h +++ b/src/xrpld/app/ledger/Ledger.h @@ -88,14 +88,14 @@ public: std::vector const& amendments, Family& family); - Ledger(LedgerInfo const& info, Config const& config, Family& family); + Ledger(LedgerHeader const& info, Config const& config, Family& family); /** Used for ledgers loaded from JSON files @param acquire If true, acquires the ledger if not found locally */ Ledger( - LedgerInfo const& info, + LedgerHeader const& info, bool& loaded, bool acquire, Config const& config, @@ -129,14 +129,14 @@ public: return false; } - LedgerInfo const& + LedgerHeader const& info() const override { return info_; } void - setLedgerInfo(LedgerInfo const& info) + setLedgerInfo(LedgerHeader const& info) { info_ = info; } @@ -397,7 +397,7 @@ private: Fees fees_; Rules rules_; - LedgerInfo info_; + LedgerHeader info_; beast::Journal j_; }; @@ -423,7 +423,7 @@ pendSaveValidated( bool isCurrent); std::shared_ptr -loadLedgerHelper(LedgerInfo const& sinfo, Application& app, bool acquire); +loadLedgerHelper(LedgerHeader const& sinfo, Application& app, bool acquire); std::shared_ptr loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire = true); @@ -457,7 +457,7 @@ std::pair, std::shared_ptr> deserializeTxPlusMeta(SHAMapItem const& item); uint256 -calculateLedgerHash(LedgerInfo const& info); +calculateLedgerHash(LedgerHeader const& info); } // namespace ripple diff --git a/src/xrpld/app/ledger/LedgerReplayer.h b/src/xrpld/app/ledger/LedgerReplayer.h index b05d92d05d..68a1c0da1d 100644 --- a/src/xrpld/app/ledger/LedgerReplayer.h +++ b/src/xrpld/app/ledger/LedgerReplayer.h @@ -85,7 +85,7 @@ public: */ void gotSkipList( - LedgerInfo const& info, + LedgerHeader const& info, boost::intrusive_ptr const& data); /** @@ -96,7 +96,7 @@ public: */ void gotReplayDelta( - LedgerInfo const& info, + LedgerHeader const& info, std::map>&& txns); /** Remove completed tasks */ diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp index 4a91c597d5..91b1dca5e2 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp @@ -118,7 +118,7 @@ LedgerDeltaAcquire::pmDowncast() void LedgerDeltaAcquire::processData( - LedgerInfo const& info, + LedgerHeader const& info, std::map>&& orderedTxns) { ScopedLockType sl(mtx_); diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h index ece0ba44d5..a2c300c546 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h @@ -69,7 +69,7 @@ public: */ void processData( - LedgerInfo const& info, + LedgerHeader const& info, std::map>&& orderedTxns); /** diff --git a/src/xrpld/app/ledger/detail/LedgerReplayer.cpp b/src/xrpld/app/ledger/detail/LedgerReplayer.cpp index 04a3d21b8f..1f89b6c044 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayer.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayer.cpp @@ -152,7 +152,7 @@ LedgerReplayer::createDeltas(std::shared_ptr task) void LedgerReplayer::gotSkipList( - LedgerInfo const& info, + LedgerHeader const& info, boost::intrusive_ptr const& item) { std::shared_ptr skipList = {}; @@ -175,7 +175,7 @@ LedgerReplayer::gotSkipList( void LedgerReplayer::gotReplayDelta( - LedgerInfo const& info, + LedgerHeader const& info, std::map>&& txns) { std::shared_ptr delta = {}; diff --git a/src/xrpld/app/ledger/detail/LedgerToJson.cpp b/src/xrpld/app/ledger/detail/LedgerToJson.cpp index 85eb3feaf1..7e8ff9e541 100644 --- a/src/xrpld/app/ledger/detail/LedgerToJson.cpp +++ b/src/xrpld/app/ledger/detail/LedgerToJson.cpp @@ -37,7 +37,7 @@ void fillJson( Object& json, bool closed, - LedgerInfo const& info, + LedgerHeader const& info, bool bFull, unsigned apiVersion) { @@ -80,7 +80,7 @@ fillJson( template void -fillJsonBinary(Object& json, bool closed, LedgerInfo const& info) +fillJsonBinary(Object& json, bool closed, LedgerHeader const& info) { if (!closed) json[jss::closed] = false; diff --git a/src/xrpld/app/rdb/RelationalDatabase.h b/src/xrpld/app/rdb/RelationalDatabase.h index 18a5536cf6..102479544b 100644 --- a/src/xrpld/app/rdb/RelationalDatabase.h +++ b/src/xrpld/app/rdb/RelationalDatabase.h @@ -127,14 +127,14 @@ public: * @param ledgerSeq Ledger sequence. * @return The ledger if found, otherwise no value. */ - virtual std::optional + virtual std::optional getLedgerInfoByIndex(LedgerIndex ledgerSeq) = 0; /** * @brief getNewestLedgerInfo Returns the info of the newest saved ledger. * @return Ledger info if found, otherwise no value. */ - virtual std::optional + virtual std::optional getNewestLedgerInfo() = 0; /** @@ -143,7 +143,7 @@ public: * @param ledgerHash Hash of the ledger. * @return Ledger if found, otherwise no value. */ - virtual std::optional + virtual std::optional getLedgerInfoByHash(uint256 const& ledgerHash) = 0; /** diff --git a/src/xrpld/app/rdb/backend/SQLiteDatabase.h b/src/xrpld/app/rdb/backend/SQLiteDatabase.h index 4ebcb4390e..cf668137ea 100644 --- a/src/xrpld/app/rdb/backend/SQLiteDatabase.h +++ b/src/xrpld/app/rdb/backend/SQLiteDatabase.h @@ -100,7 +100,7 @@ public: * @param ledgerFirstIndex Minimum ledger sequence. * @return Ledger info if found, otherwise no value. */ - virtual std::optional + virtual std::optional getLimitedOldestLedgerInfo(LedgerIndex ledgerFirstIndex) = 0; /** @@ -110,7 +110,7 @@ public: * @param ledgerFirstIndex Minimum ledger sequence. * @return Ledger info if found, otherwise no value. */ - virtual std::optional + virtual std::optional getLimitedNewestLedgerInfo(LedgerIndex ledgerFirstIndex) = 0; /** diff --git a/src/xrpld/app/rdb/backend/detail/Node.cpp b/src/xrpld/app/rdb/backend/detail/Node.cpp index 04f328390d..a7b35a5305 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.cpp +++ b/src/xrpld/app/rdb/backend/detail/Node.cpp @@ -391,7 +391,7 @@ saveValidatedLedger( * @param j Journal. * @return Ledger info or no value if the ledger was not found. */ -static std::optional +static std::optional getLedgerInfo( soci::session& session, std::string const& sqlSuffix, @@ -425,7 +425,7 @@ getLedgerInfo( using time_point = NetClock::time_point; using duration = NetClock::duration; - LedgerInfo info; + LedgerHeader info; if (hash && !info.hash.parseHex(*hash)) { @@ -461,7 +461,7 @@ getLedgerInfo( return info; } -std::optional +std::optional getLedgerInfoByIndex( soci::session& session, LedgerIndex ledgerSeq, @@ -472,7 +472,7 @@ getLedgerInfoByIndex( return getLedgerInfo(session, s.str(), j); } -std::optional +std::optional getNewestLedgerInfo(soci::session& session, beast::Journal j) { std::ostringstream s; @@ -480,7 +480,7 @@ getNewestLedgerInfo(soci::session& session, beast::Journal j) return getLedgerInfo(session, s.str(), j); } -std::optional +std::optional getLimitedOldestLedgerInfo( soci::session& session, LedgerIndex ledgerFirstIndex, @@ -492,7 +492,7 @@ getLimitedOldestLedgerInfo( return getLedgerInfo(session, s.str(), j); } -std::optional +std::optional getLimitedNewestLedgerInfo( soci::session& session, LedgerIndex ledgerFirstIndex, @@ -504,7 +504,7 @@ getLimitedNewestLedgerInfo( return getLedgerInfo(session, s.str(), j); } -std::optional +std::optional getLedgerInfoByHash( soci::session& session, uint256 const& ledgerHash, diff --git a/src/xrpld/app/rdb/backend/detail/Node.h b/src/xrpld/app/rdb/backend/detail/Node.h index 2c0fd69445..fbf06083d6 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.h +++ b/src/xrpld/app/rdb/backend/detail/Node.h @@ -123,7 +123,7 @@ saveValidatedLedger( * @param j Journal. * @return Ledger or none if ledger not found. */ -std::optional +std::optional getLedgerInfoByIndex( soci::session& session, LedgerIndex ledgerSeq, @@ -135,7 +135,7 @@ getLedgerInfoByIndex( * @param j Journal. * @return Ledger info or none if ledger not found. */ -std::optional +std::optional getNewestLedgerInfo(soci::session& session, beast::Journal j); /** @@ -146,7 +146,7 @@ getNewestLedgerInfo(soci::session& session, beast::Journal j); * @param j Journal. * @return Ledger info or none if ledger not found. */ -std::optional +std::optional getLimitedOldestLedgerInfo( soci::session& session, LedgerIndex ledgerFirstIndex, @@ -160,7 +160,7 @@ getLimitedOldestLedgerInfo( * @param j Journal. * @return Ledger info or none if ledger not found. */ -std::optional +std::optional getLimitedNewestLedgerInfo( soci::session& session, LedgerIndex ledgerFirstIndex, @@ -173,7 +173,7 @@ getLimitedNewestLedgerInfo( * @param j Journal. * @return Ledger or none if ledger not found. */ -std::optional +std::optional getLedgerInfoByHash( soci::session& session, uint256 const& ledgerHash, diff --git a/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp b/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp index 944ed814f5..b789685211 100644 --- a/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp +++ b/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp @@ -73,19 +73,19 @@ public: std::shared_ptr const& ledger, bool current) override; - std::optional + std::optional getLedgerInfoByIndex(LedgerIndex ledgerSeq) override; - std::optional + std::optional getNewestLedgerInfo() override; - std::optional + std::optional getLimitedOldestLedgerInfo(LedgerIndex ledgerFirstIndex) override; - std::optional + std::optional getLimitedNewestLedgerInfo(LedgerIndex ledgerFirstIndex) override; - std::optional + std::optional getLedgerInfoByHash(uint256 const& ledgerHash) override; uint256 @@ -399,7 +399,7 @@ SQLiteDatabaseImp::saveValidatedLedger( return true; } -std::optional +std::optional SQLiteDatabaseImp::getLedgerInfoByIndex(LedgerIndex ledgerSeq) { if (existsLedger()) @@ -414,7 +414,7 @@ SQLiteDatabaseImp::getLedgerInfoByIndex(LedgerIndex ledgerSeq) return {}; } -std::optional +std::optional SQLiteDatabaseImp::getNewestLedgerInfo() { if (existsLedger()) @@ -429,7 +429,7 @@ SQLiteDatabaseImp::getNewestLedgerInfo() return {}; } -std::optional +std::optional SQLiteDatabaseImp::getLimitedOldestLedgerInfo(LedgerIndex ledgerFirstIndex) { if (existsLedger()) @@ -445,7 +445,7 @@ SQLiteDatabaseImp::getLimitedOldestLedgerInfo(LedgerIndex ledgerFirstIndex) return {}; } -std::optional +std::optional SQLiteDatabaseImp::getLimitedNewestLedgerInfo(LedgerIndex ledgerFirstIndex) { if (existsLedger()) @@ -461,7 +461,7 @@ SQLiteDatabaseImp::getLimitedNewestLedgerInfo(LedgerIndex ledgerFirstIndex) return {}; } -std::optional +std::optional SQLiteDatabaseImp::getLedgerInfoByHash(uint256 const& ledgerHash) { if (existsLedger()) diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index 0a973a9218..1a0995442b 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -3227,7 +3227,7 @@ PeerImp::sendLedgerBase( { JLOG(p_journal_.trace()) << "sendLedgerBase: Base data"; - Serializer s(sizeof(LedgerInfo)); + Serializer s(sizeof(LedgerHeader)); addRaw(ledger->info(), s); ledgerData.add_nodes()->set_nodedata(s.getDataPtr(), s.getLength()); From 62efecbfb11bf5892c679692be8e98a6a45d92e8 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 10 Dec 2025 16:04:37 -0500 Subject: [PATCH 038/105] refactor: rename info() to header() (#6138) This change renames all the `info()` functions to `header()`, since they return `LedgerHeader` structs. It also renames the underlying variables from `info_` to `header_`. --- include/xrpl/ledger/CachedView.h | 4 +- include/xrpl/ledger/OpenView.h | 4 +- include/xrpl/ledger/ReadView.h | 6 +- include/xrpl/ledger/detail/ApplyViewBase.h | 2 +- src/libxrpl/ledger/ApplyViewBase.cpp | 4 +- src/libxrpl/ledger/CredentialHelpers.cpp | 4 +- src/libxrpl/ledger/OpenView.cpp | 22 +-- src/libxrpl/ledger/View.cpp | 43 ++--- src/test/app/AMM_test.cpp | 2 +- src/test/app/AccountDelete_test.cpp | 2 +- src/test/app/Credentials_test.cpp | 8 +- src/test/app/DepositAuth_test.cpp | 8 +- src/test/app/LedgerHistory_test.cpp | 6 +- src/test/app/LedgerMaster_test.cpp | 4 +- src/test/app/LedgerReplay_test.cpp | 50 ++--- src/test/app/Loan_test.cpp | 4 +- src/test/app/NFToken_test.cpp | 5 +- src/test/app/NetworkID_test.cpp | 2 +- src/test/app/Offer_test.cpp | 5 +- src/test/app/Oracle_test.cpp | 6 +- src/test/app/PayChan_test.cpp | 16 +- src/test/app/PermissionedDEX_test.cpp | 4 +- src/test/app/RCLValidations_test.cpp | 4 +- src/test/app/Regression_test.cpp | 6 +- src/test/app/TxQ_test.cpp | 12 +- src/test/app/Vault_test.cpp | 2 +- src/test/consensus/NegativeUNL_test.cpp | 4 +- src/test/jtx/impl/Env.cpp | 7 +- src/test/jtx/impl/Oracle.cpp | 2 +- src/test/ledger/Directory_test.cpp | 2 +- src/test/ledger/SkipList_test.cpp | 29 +-- src/test/ledger/View_test.cpp | 4 +- src/test/rpc/AccountLines_test.cpp | 12 +- src/test/rpc/AccountTx_test.cpp | 24 +-- src/test/rpc/DepositAuthorized_test.cpp | 2 +- src/test/rpc/LedgerData_test.cpp | 2 +- src/test/rpc/LedgerEntry_test.cpp | 29 +-- src/test/rpc/LedgerRPC_test.cpp | 18 +- src/test/rpc/LedgerRequest_test.cpp | 2 +- src/test/rpc/Simulate_test.cpp | 2 +- src/test/rpc/Subscribe_test.cpp | 8 +- src/test/rpc/Transaction_test.cpp | 16 +- src/test/server/ServerStatus_test.cpp | 4 +- src/xrpld/app/consensus/RCLConsensus.cpp | 22 +-- src/xrpld/app/consensus/RCLCxLedger.h | 14 +- src/xrpld/app/consensus/RCLValidations.cpp | 4 +- src/xrpld/app/ledger/Ledger.cpp | 131 +++++++------- src/xrpld/app/ledger/Ledger.h | 18 +- src/xrpld/app/ledger/LedgerHistory.cpp | 36 ++-- src/xrpld/app/ledger/detail/BuildLedger.cpp | 10 +- src/xrpld/app/ledger/detail/InboundLedger.cpp | 53 +++--- src/xrpld/app/ledger/detail/LedgerCleaner.cpp | 14 +- .../app/ledger/detail/LedgerDeltaAcquire.cpp | 6 +- src/xrpld/app/ledger/detail/LedgerMaster.cpp | 171 +++++++++--------- .../ledger/detail/LedgerReplayMsgHandler.cpp | 4 +- .../app/ledger/detail/LedgerReplayTask.cpp | 4 +- src/xrpld/app/ledger/detail/LedgerToJson.cpp | 6 +- src/xrpld/app/ledger/detail/LocalTxs.cpp | 2 +- src/xrpld/app/main/Application.cpp | 26 +-- src/xrpld/app/misc/FeeVoteImpl.cpp | 2 +- src/xrpld/app/misc/NegativeUNLVote.cpp | 10 +- src/xrpld/app/misc/NetworkOPs.cpp | 84 +++++---- src/xrpld/app/misc/PermissionedDEXHelpers.cpp | 2 +- src/xrpld/app/misc/SHAMapStoreImp.cpp | 2 +- src/xrpld/app/misc/detail/AMMUtils.cpp | 9 +- src/xrpld/app/misc/detail/TxQ.cpp | 11 +- src/xrpld/app/paths/PathRequest.cpp | 2 +- src/xrpld/app/paths/RippleLineCache.cpp | 6 +- src/xrpld/app/rdb/backend/detail/Node.cpp | 39 ++-- src/xrpld/app/tx/detail/AMMBid.cpp | 2 +- src/xrpld/app/tx/detail/Credentials.cpp | 6 +- src/xrpld/app/tx/detail/Escrow.cpp | 6 +- src/xrpld/app/tx/detail/LoanSet.cpp | 2 +- src/xrpld/app/tx/detail/PayChan.cpp | 10 +- src/xrpld/app/tx/detail/SetOracle.cpp | 2 +- src/xrpld/overlay/detail/Handshake.cpp | 4 +- src/xrpld/overlay/detail/PeerImp.cpp | 10 +- src/xrpld/rpc/BookChanges.h | 8 +- src/xrpld/rpc/detail/DeliveredAmount.cpp | 2 +- src/xrpld/rpc/detail/RPCLedgerHelpers.cpp | 10 +- src/xrpld/rpc/handlers/AMMInfo.cpp | 4 +- src/xrpld/rpc/handlers/AccountTx.cpp | 7 +- src/xrpld/rpc/handlers/CanDelete.cpp | 2 +- src/xrpld/rpc/handlers/DepositAuthorized.cpp | 2 +- src/xrpld/rpc/handlers/LedgerClosed.cpp | 4 +- src/xrpld/rpc/handlers/LedgerData.cpp | 4 +- src/xrpld/rpc/handlers/LedgerHandler.cpp | 4 +- src/xrpld/rpc/handlers/LedgerHeader.cpp | 2 +- src/xrpld/rpc/handlers/LedgerRequest.cpp | 2 +- src/xrpld/rpc/handlers/Tx.cpp | 8 +- 90 files changed, 609 insertions(+), 582 deletions(-) diff --git a/include/xrpl/ledger/CachedView.h b/include/xrpl/ledger/CachedView.h index ad1125637b..b78c046f58 100644 --- a/include/xrpl/ledger/CachedView.h +++ b/include/xrpl/ledger/CachedView.h @@ -48,9 +48,9 @@ public: } LedgerHeader const& - info() const override + header() const override { - return base_.info(); + return base_.header(); } Fees const& diff --git a/include/xrpl/ledger/OpenView.h b/include/xrpl/ledger/OpenView.h index 9027f57b97..2b4bd8a31f 100644 --- a/include/xrpl/ledger/OpenView.h +++ b/include/xrpl/ledger/OpenView.h @@ -82,7 +82,7 @@ private: monotonic_resource_; txs_map txs_; Rules rules_; - LedgerHeader info_; + LedgerHeader header_; ReadView const* base_; detail::RawStateTable items_; std::shared_ptr hold_; @@ -189,7 +189,7 @@ public: // ReadView LedgerHeader const& - info() const override; + header() const override; Fees const& fees() const override; diff --git a/include/xrpl/ledger/ReadView.h b/include/xrpl/ledger/ReadView.h index 4108b19967..70a5fbc006 100644 --- a/include/xrpl/ledger/ReadView.h +++ b/include/xrpl/ledger/ReadView.h @@ -81,7 +81,7 @@ public: /** Returns information about the ledger. */ virtual LedgerHeader const& - info() const = 0; + header() const = 0; /** Returns true if this reflects an open ledger. */ virtual bool @@ -91,14 +91,14 @@ public: NetClock::time_point parentCloseTime() const { - return info().parentCloseTime; + return header().parentCloseTime; } /** Returns the sequence number of the base ledger. */ LedgerIndex seq() const { - return info().seq; + return header().seq; } /** Returns the fees for the base ledger. */ diff --git a/include/xrpl/ledger/detail/ApplyViewBase.h b/include/xrpl/ledger/detail/ApplyViewBase.h index 7bf490cd9c..a75f94ac16 100644 --- a/include/xrpl/ledger/detail/ApplyViewBase.h +++ b/include/xrpl/ledger/detail/ApplyViewBase.h @@ -28,7 +28,7 @@ public: open() const override; LedgerHeader const& - info() const override; + header() const override; Fees const& fees() const override; diff --git a/src/libxrpl/ledger/ApplyViewBase.cpp b/src/libxrpl/ledger/ApplyViewBase.cpp index f296c3cef2..554822acda 100644 --- a/src/libxrpl/ledger/ApplyViewBase.cpp +++ b/src/libxrpl/ledger/ApplyViewBase.cpp @@ -17,9 +17,9 @@ ApplyViewBase::open() const } LedgerHeader const& -ApplyViewBase::info() const +ApplyViewBase::header() const { - return base_->info(); + return base_->header(); } Fees const& diff --git a/src/libxrpl/ledger/CredentialHelpers.cpp b/src/libxrpl/ledger/CredentialHelpers.cpp index cbca7eb192..aea783b676 100644 --- a/src/libxrpl/ledger/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/CredentialHelpers.cpp @@ -22,7 +22,7 @@ checkExpired( bool removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j) { - auto const closeTime = view.info().parentCloseTime; + auto const closeTime = view.header().parentCloseTime; bool foundExpired = false; for (auto const& h : arr) @@ -181,7 +181,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject) if (!slePD) return tecOBJECT_NOT_FOUND; - auto const closeTime = view.info().parentCloseTime; + auto const closeTime = view.header().parentCloseTime; bool foundExpired = false; for (auto const& h : slePD->getFieldArray(sfAcceptedCredentials)) { diff --git a/src/libxrpl/ledger/OpenView.cpp b/src/libxrpl/ledger/OpenView.cpp index 25b2ba8a0c..8ddb11abd0 100644 --- a/src/libxrpl/ledger/OpenView.cpp +++ b/src/libxrpl/ledger/OpenView.cpp @@ -61,7 +61,7 @@ OpenView::OpenView(OpenView const& rhs) boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)} , txs_{rhs.txs_, monotonic_resource_.get()} , rules_{rhs.rules_} - , info_{rhs.info_} + , header_{rhs.header_} , base_{rhs.base_} , items_{rhs.items_} , hold_{rhs.hold_} @@ -76,15 +76,15 @@ OpenView::OpenView( boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)} , txs_{monotonic_resource_.get()} , rules_(rules) - , info_(base->info()) + , header_(base->header()) , base_(base) , hold_(std::move(hold)) { - info_.validated = false; - info_.accepted = false; - info_.seq = base_->info().seq + 1; - info_.parentCloseTime = base_->info().closeTime; - info_.parentHash = base_->info().hash; + header_.validated = false; + header_.accepted = false; + header_.seq = base_->header().seq + 1; + header_.parentCloseTime = base_->header().closeTime; + header_.parentHash = base_->header().hash; } OpenView::OpenView(ReadView const* base, std::shared_ptr hold) @@ -92,7 +92,7 @@ OpenView::OpenView(ReadView const* base, std::shared_ptr hold) boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)} , txs_{monotonic_resource_.get()} , rules_(base->rules()) - , info_(base->info()) + , header_(base->header()) , base_(base) , hold_(std::move(hold)) , open_(base->open()) @@ -116,9 +116,9 @@ OpenView::apply(TxsRawView& to) const //--- LedgerHeader const& -OpenView::info() const +OpenView::header() const { - return info_; + return header_; } Fees const& @@ -230,7 +230,7 @@ void OpenView::rawDestroyXRP(XRPAmount const& fee) { items_.destroyXRP(fee); - // VFALCO Deduct from info_.totalDrops ? + // VFALCO Deduct from header_.totalDrops ? // What about child views? } diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 33c6cf69ec..d5297479e8 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -907,14 +907,14 @@ areCompatible( { bool ret = true; - if (validLedger.info().seq < testLedger.info().seq) + if (validLedger.header().seq < testLedger.header().seq) { // valid -> ... -> test auto hash = hashOfSeq( testLedger, - validLedger.info().seq, + validLedger.header().seq, beast::Journal{beast::Journal::getNullSink()}); - if (hash && (*hash != validLedger.info().hash)) + if (hash && (*hash != validLedger.header().hash)) { JLOG(s) << reason << " incompatible with valid ledger"; @@ -923,14 +923,14 @@ areCompatible( ret = false; } } - else if (validLedger.info().seq > testLedger.info().seq) + else if (validLedger.header().seq > testLedger.header().seq) { // test -> ... -> valid auto hash = hashOfSeq( validLedger, - testLedger.info().seq, + testLedger.header().seq, beast::Journal{beast::Journal::getNullSink()}); - if (hash && (*hash != testLedger.info().hash)) + if (hash && (*hash != testLedger.header().hash)) { JLOG(s) << reason << " incompatible preceding ledger"; @@ -940,8 +940,8 @@ areCompatible( } } else if ( - (validLedger.info().seq == testLedger.info().seq) && - (validLedger.info().hash != testLedger.info().hash)) + (validLedger.header().seq == testLedger.header().seq) && + (validLedger.header().hash != testLedger.header().hash)) { // Same sequence number, different hash JLOG(s) << reason << " incompatible ledger"; @@ -951,11 +951,11 @@ areCompatible( if (!ret) { - JLOG(s) << "Val: " << validLedger.info().seq << " " - << to_string(validLedger.info().hash); + JLOG(s) << "Val: " << validLedger.header().seq << " " + << to_string(validLedger.header().hash); - JLOG(s) << "New: " << testLedger.info().seq << " " - << to_string(testLedger.info().hash); + JLOG(s) << "New: " << testLedger.header().seq << " " + << to_string(testLedger.header().hash); } return ret; @@ -971,7 +971,7 @@ areCompatible( { bool ret = true; - if (testLedger.info().seq > validIndex) + if (testLedger.header().seq > validIndex) { // Ledger we are testing follows last valid ledger auto hash = hashOfSeq( @@ -987,8 +987,8 @@ areCompatible( } } else if ( - (validIndex == testLedger.info().seq) && - (testLedger.info().hash != validHash)) + (validIndex == testLedger.header().seq) && + (testLedger.header().hash != validHash)) { JLOG(s) << reason << " incompatible ledger"; @@ -999,8 +999,8 @@ areCompatible( { JLOG(s) << "Val: " << validIndex << " " << to_string(validHash); - JLOG(s) << "New: " << testLedger.info().seq << " " - << to_string(testLedger.info().hash); + JLOG(s) << "New: " << testLedger.header().seq << " " + << to_string(testLedger.header().hash); } return ret; @@ -1071,9 +1071,9 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) return std::nullopt; } if (seq == ledger.seq()) - return ledger.info().hash; + return ledger.header().hash; if (seq == (ledger.seq() - 1)) - return ledger.info().parentHash; + return ledger.header().parentHash; if (int diff = ledger.seq() - seq; diff <= 256) { @@ -1095,7 +1095,7 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) else { JLOG(journal.warn()) - << "Ledger " << ledger.seq() << ":" << ledger.info().hash + << "Ledger " << ledger.seq() << ":" << ledger.header().hash << " missing normal list"; } } @@ -1180,7 +1180,8 @@ pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey) for (std::uint16_t i = 0; i < maxAccountAttempts; ++i) { ripesha_hasher rsh; - auto const hash = sha512Half(i, view.info().parentHash, pseudoOwnerKey); + auto const hash = + sha512Half(i, view.header().parentHash, pseudoOwnerKey); rsh(hash.data(), hash.size()); AccountID const ret{static_cast(rsh)}; if (!view.read(keylet::account(ret))) diff --git a/src/test/app/AMM_test.cpp b/src/test/app/AMM_test.cpp index 5a1816ebae..611932e825 100644 --- a/src/test/app/AMM_test.cpp +++ b/src/test/app/AMM_test.cpp @@ -3646,7 +3646,7 @@ private: auto const pk = carol.pk(); auto const settleDelay = 100s; NetClock::time_point const cancelAfter = - env.current()->info().parentCloseTime + 200s; + env.current()->header().parentCloseTime + 200s; env(paychan::create( carol, ammAlice.ammAccount(), diff --git a/src/test/app/AccountDelete_test.cpp b/src/test/app/AccountDelete_test.cpp index f22f9c4165..91164d3e4e 100644 --- a/src/test/app/AccountDelete_test.cpp +++ b/src/test/app/AccountDelete_test.cpp @@ -922,7 +922,7 @@ public: auto jv = credentials::create(john, carol, credType); uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() + 20; diff --git a/src/test/app/Credentials_test.cpp b/src/test/app/Credentials_test.cpp index fd4a7f41a6..c4a5ee1c7c 100644 --- a/src/test/app/Credentials_test.cpp +++ b/src/test/app/Credentials_test.cpp @@ -336,7 +336,7 @@ struct Credentials_test : public beast::unit_test::suite auto const credKey = credentials::keylet(subject, issuer, credType); auto jv = credentials::create(subject, issuer, credType); uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count(); jv[sfExpiration.jsonName] = t + 20; @@ -498,7 +498,7 @@ struct Credentials_test : public beast::unit_test::suite auto jv = credentials::create(subject, issuer, credType); // current time in ripple epoch - 1s uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() - 1; @@ -725,7 +725,7 @@ struct Credentials_test : public beast::unit_test::suite testcase("CredentialsAccept fail, expired credentials."); auto jv = credentials::create(subject, issuer, credType2); uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count(); jv[sfExpiration.jsonName] = t; @@ -870,7 +870,7 @@ struct Credentials_test : public beast::unit_test::suite auto jv = credentials::create(subject, issuer, credType); // current time in ripple epoch + 1000s uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() + 1000; diff --git a/src/test/app/DepositAuth_test.cpp b/src/test/app/DepositAuth_test.cpp index 54d5dd6254..ed727c2fa0 100644 --- a/src/test/app/DepositAuth_test.cpp +++ b/src/test/app/DepositAuth_test.cpp @@ -1107,7 +1107,7 @@ struct DepositPreauth_test : public beast::unit_test::suite // Current time in ripple epoch. // Every time ledger close, unittest timer increase by 10s uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() + 60; @@ -1122,7 +1122,7 @@ struct DepositPreauth_test : public beast::unit_test::suite // Create credential which not expired jv = credentials::create(alice, issuer, credType2); uint32_t const t2 = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() + 1000; @@ -1199,7 +1199,7 @@ struct DepositPreauth_test : public beast::unit_test::suite { auto jv = credentials::create(gw, issuer, credType); uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() + 40; @@ -1252,7 +1252,7 @@ struct DepositPreauth_test : public beast::unit_test::suite // Create credentials auto jv = credentials::create(zelda, issuer, credType); uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() + 50; diff --git a/src/test/app/LedgerHistory_test.cpp b/src/test/app/LedgerHistory_test.cpp index e286440679..3223e9e1d8 100644 --- a/src/test/app/LedgerHistory_test.cpp +++ b/src/test/app/LedgerHistory_test.cpp @@ -43,7 +43,7 @@ public: env.app().getNodeFamily()); } auto res = std::make_shared( - *prev, prev->info().closeTime + closeOffset); + *prev, prev->header().closeTime + closeOffset); if (stx) { @@ -62,8 +62,8 @@ public: // Accept ledger res->setAccepted( - res->info().closeTime, - res->info().closeTimeResolution, + res->header().closeTime, + res->header().closeTimeResolution, true /* close time correct*/); lh.insert(res, false); return res; diff --git a/src/test/app/LedgerMaster_test.cpp b/src/test/app/LedgerMaster_test.cpp index 5b815caeda..451e4f9068 100644 --- a/src/test/app/LedgerMaster_test.cpp +++ b/src/test/app/LedgerMaster_test.cpp @@ -37,7 +37,7 @@ class LedgerMaster_test : public beast::unit_test::suite // build ledgers std::vector> txns; std::vector> metas; - auto const startLegSeq = env.current()->info().seq; + auto const startLegSeq = env.current()->header().seq; for (int i = 0; i < 2; ++i) { env(noop(alice)); @@ -48,7 +48,7 @@ class LedgerMaster_test : public beast::unit_test::suite } // add last (empty) ledger env.close(); - auto const endLegSeq = env.closed()->info().seq; + auto const endLegSeq = env.closed()->header().seq; // test invalid range { diff --git a/src/test/app/LedgerReplay_test.cpp b/src/test/app/LedgerReplay_test.cpp index 9edaaec0a5..a468629de9 100644 --- a/src/test/app/LedgerReplay_test.cpp +++ b/src/test/app/LedgerReplay_test.cpp @@ -40,7 +40,7 @@ struct LedgerReplay_test : public beast::unit_test::suite LedgerMaster& ledgerMaster = env.app().getLedgerMaster(); auto const lastClosed = ledgerMaster.getClosedLedger(); auto const lastClosedParent = - ledgerMaster.getLedgerByHash(lastClosed->info().parentHash); + ledgerMaster.getLedgerByHash(lastClosed->header().parentHash); auto const replayed = buildLedger( LedgerReplay(lastClosedParent, lastClosed), @@ -48,7 +48,7 @@ struct LedgerReplay_test : public beast::unit_test::suite env.app(), env.journal); - BEAST_EXPECT(replayed->info().hash == lastClosed->info().hash); + BEAST_EXPECT(replayed->header().hash == lastClosed->header().hash); } }; @@ -610,7 +610,7 @@ public: auto const l = ledgerMaster.getLedgerByHash(hash); if (!l) return false; - hash = l->info().parentHash; + hash = l->header().parentHash; } return true; } @@ -890,7 +890,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite // request, missing key auto request = std::make_shared(); request->set_ledgerhash( - l->info().hash.data(), l->info().hash.size()); + l->header().hash.data(), l->header().hash.size()); request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE); auto reply = std::make_shared( server.msgHandler.processProofPathRequest(request)); @@ -914,7 +914,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite // good request auto request = std::make_shared(); request->set_ledgerhash( - l->info().hash.data(), l->info().hash.size()); + l->header().hash.data(), l->header().hash.size()); request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE); request->set_key( keylet::skip().key.data(), keylet::skip().key.size()); @@ -970,7 +970,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite // good request auto request = std::make_shared(); request->set_ledgerhash( - l->info().hash.data(), l->info().hash.size()); + l->header().hash.data(), l->header().hash.size()); auto reply = std::make_shared( server.msgHandler.processReplayDeltaRequest(request)); BEAST_EXPECT(!reply->has_error()); @@ -1132,7 +1132,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite NetworkOfTwo net(*this, {totalReplay + 1}, psBhvr, ilBhvr, peerFeature); auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; for (int i = 0; i < totalReplay; ++i) { BEAST_EXPECT(l); @@ -1140,7 +1140,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite { net.client.ledgerMaster.storeLedger(l); l = net.server.ledgerMaster.getLedgerByHash( - l->info().parentHash); + l->header().parentHash); } else break; @@ -1175,7 +1175,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite PeerFeature::None); auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash, totalReplay); @@ -1220,10 +1220,10 @@ struct LedgerReplayer_test : public beast::unit_test::suite // feed client with start ledger since InboundLedgers drops all auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; for (int i = 0; i < totalReplay - 1; ++i) { - l = net.server.ledgerMaster.getLedgerByHash(l->info().parentHash); + l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash); } net.client.ledgerMaster.storeLedger(l); @@ -1258,7 +1258,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite PeerFeature::LedgerReplayEnabled); auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash, totalReplay); @@ -1288,7 +1288,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite PeerFeature::LedgerReplayEnabled); auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash, totalReplay); @@ -1333,14 +1333,14 @@ struct LedgerReplayer_test : public beast::unit_test::suite PeerFeature::LedgerReplayEnabled); auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; net.client.ledgerMaster.storeLedger(l); net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash, totalReplay); - auto delta = net.client.findLedgerDeltaAcquire(l->info().parentHash); + auto delta = net.client.findLedgerDeltaAcquire(l->header().parentHash); delta->processData( - l->info(), // wrong ledger info + l->header(), // wrong ledger info std::map>()); BEAST_EXPECT(net.client.taskStatus(delta) == TaskStatus::Failed); BEAST_EXPECT( @@ -1367,7 +1367,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite InboundLedgersBehavior::Good, PeerFeature::LedgerReplayEnabled); auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash, totalReplay); std::vector deltaStatuses( @@ -1392,9 +1392,9 @@ struct LedgerReplayer_test : public beast::unit_test::suite // no overlap for (int i = 0; i < totalReplay + 2; ++i) { - l = net.server.ledgerMaster.getLedgerByHash(l->info().parentHash); + l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash); } - auto finalHash_early = l->info().hash; + auto finalHash_early = l->header().hash; net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash_early, totalReplay); BEAST_EXPECT(net.client.waitAndCheckStatus( @@ -1407,8 +1407,8 @@ struct LedgerReplayer_test : public beast::unit_test::suite BEAST_EXPECT(net.client.countsAsExpected(3, 2, 2 * (totalReplay - 1))); // partial overlap - l = net.server.ledgerMaster.getLedgerByHash(l->info().parentHash); - auto finalHash_moreEarly = l->info().parentHash; + l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash); + auto finalHash_moreEarly = l->header().parentHash; net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash_moreEarly, totalReplay); BEAST_EXPECT(net.client.waitAndCheckStatus( @@ -1479,7 +1479,7 @@ struct LedgerReplayerTimeout_test : public beast::unit_test::suite PeerFeature::LedgerReplayEnabled); auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash, totalReplay); @@ -1510,7 +1510,7 @@ struct LedgerReplayerTimeout_test : public beast::unit_test::suite PeerFeature::LedgerReplayEnabled); auto l = net.server.ledgerMaster.getClosedLedger(); - uint256 finalHash = l->info().hash; + uint256 finalHash = l->header().hash; net.client.ledgerMaster.storeLedger(l); net.client.replayer.replay( InboundLedger::Reason::GENERIC, finalHash, totalReplay); @@ -1558,11 +1558,11 @@ struct LedgerReplayerLong_test : public beast::unit_test::suite auto l = net.server.ledgerMaster.getClosedLedger(); for (int i = 0; i < rounds; ++i) { - finishHashes.push_back(l->info().hash); + finishHashes.push_back(l->header().hash); for (int j = 0; j < totalReplay; ++j) { l = net.server.ledgerMaster.getLedgerByHash( - l->info().parentHash); + l->header().parentHash); } } BEAST_EXPECT(finishHashes.size() == rounds); diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index b2ad47c2b4..f7672fd380 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -1398,7 +1398,7 @@ protected: env.close(); auto const startDate = - env.current()->info().parentCloseTime.time_since_epoch().count(); + env.current()->header().parentCloseTime.time_since_epoch().count(); if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); BEAST_EXPECT(brokerSle)) @@ -3761,7 +3761,7 @@ protected: env.close(); - auto const startDate = env.current()->info().parentCloseTime; + auto const startDate = env.current()->header().parentCloseTime; // Loan is successfully created { diff --git a/src/test/app/NFToken_test.cpp b/src/test/app/NFToken_test.cpp index 5f57322be1..5ff0ac17ae 100644 --- a/src/test/app/NFToken_test.cpp +++ b/src/test/app/NFToken_test.cpp @@ -57,7 +57,10 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite std::uint32_t lastClose(test::jtx::Env& env) { - return env.current()->info().parentCloseTime.time_since_epoch().count(); + return env.current() + ->header() + .parentCloseTime.time_since_epoch() + .count(); } void diff --git a/src/test/app/NetworkID_test.cpp b/src/test/app/NetworkID_test.cpp index 01db95835e..49ca453ebb 100644 --- a/src/test/app/NetworkID_test.cpp +++ b/src/test/app/NetworkID_test.cpp @@ -112,7 +112,7 @@ public: jvn[jss::TransactionType] = jss::AccountSet; jvn[jss::Fee] = to_string(env.current()->fees().base); jvn[jss::Sequence] = env.seq(alice); - jvn[jss::LastLedgerSequence] = env.current()->info().seq + 2; + jvn[jss::LastLedgerSequence] = env.current()->header().seq + 2; auto jt = env.jtnofill(jvn); Serializer s; jt.stx->add(s); diff --git a/src/test/app/Offer_test.cpp b/src/test/app/Offer_test.cpp index 2cbf2598e1..9cf8a7b1f2 100644 --- a/src/test/app/Offer_test.cpp +++ b/src/test/app/Offer_test.cpp @@ -20,7 +20,10 @@ class OfferBaseUtil_test : public beast::unit_test::suite std::uint32_t lastClose(jtx::Env& env) { - return env.current()->info().parentCloseTime.time_since_epoch().count(); + return env.current() + ->header() + .parentCloseTime.time_since_epoch() + .count(); } static auto diff --git a/src/test/app/Oracle_test.cpp b/src/test/app/Oracle_test.cpp index 42f2455f31..470bcd7950 100644 --- a/src/test/app/Oracle_test.cpp +++ b/src/test/app/Oracle_test.cpp @@ -252,7 +252,9 @@ private: static_cast(env.current()->fees().base.drops()); auto closeTime = [&]() { return duration_cast( - env.current()->info().closeTime.time_since_epoch() - + env.current() + ->header() + .closeTime.time_since_epoch() - 10'000s) .count(); }; @@ -559,7 +561,7 @@ private: BEAST_EXPECT(oracle.exists()); BEAST_EXPECT(oracle1.exists()); auto const index = env.closed()->seq(); - auto const hash = env.closed()->info().hash; + auto const hash = env.closed()->header().hash; for (int i = 0; i < 256; ++i) env.close(); env(acctdelete(owner, alice), fee(acctDelFee)); diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index 59c404ae28..3f350626ea 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -322,7 +322,7 @@ struct PayChan_test : public beast::unit_test::suite auto const pk = alice.pk(); auto const settleDelay = 100s; NetClock::time_point const cancelAfter = - env.current()->info().parentCloseTime + 3600s; + env.current()->header().parentCloseTime + 3600s; auto const channelFunds = XRP(1000); auto const chan = channel(alice, bob, env.seq(alice)); env(create(alice, bob, channelFunds, settleDelay, pk, cancelAfter)); @@ -354,7 +354,7 @@ struct PayChan_test : public beast::unit_test::suite auto const pk = alice.pk(); auto const settleDelay = 100s; NetClock::time_point const cancelAfter = - env.current()->info().parentCloseTime + 3600s; + env.current()->header().parentCloseTime + 3600s; auto const channelFunds = XRP(1000); auto const chan = channel(alice, bob, env.seq(alice)); env(create(alice, bob, channelFunds, settleDelay, pk, cancelAfter)); @@ -385,7 +385,7 @@ struct PayChan_test : public beast::unit_test::suite auto const settleDelay = 100s; auto const channelFunds = XRP(1000); NetClock::time_point const cancelAfter = - env.current()->info().parentCloseTime - 1s; + env.current()->header().parentCloseTime - 1s; auto const txResult = withFixPayChan ? ter(tecEXPIRED) : ter(tesSUCCESS); env(create( @@ -409,7 +409,7 @@ struct PayChan_test : public beast::unit_test::suite auto const settleDelay = 100s; auto const channelFunds = XRP(1000); NetClock::time_point const cancelAfter = - env.current()->info().parentCloseTime; + env.current()->header().parentCloseTime; env(create( alice, bob, channelFunds, settleDelay, pk, cancelAfter), ter(tesSUCCESS)); @@ -430,7 +430,7 @@ struct PayChan_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob, carol); auto const pk = alice.pk(); auto const settleDelay = 3600s; - auto const closeTime = env.current()->info().parentCloseTime; + auto const closeTime = env.current()->header().parentCloseTime; auto const minExpiration = closeTime + settleDelay; NetClock::time_point const cancelAfter = closeTime + 7200s; auto const channelFunds = XRP(1000); @@ -496,7 +496,7 @@ struct PayChan_test : public beast::unit_test::suite auto const pk = alice.pk(); auto const settleDelay = 3600s; NetClock::time_point const settleTimepoint = - env.current()->info().parentCloseTime + settleDelay; + env.current()->header().parentCloseTime + settleDelay; auto const channelFunds = XRP(1000); auto const chan = channel(alice, bob, env.seq(alice)); env(create(alice, bob, channelFunds, settleDelay, pk)); @@ -861,7 +861,7 @@ struct PayChan_test : public beast::unit_test::suite { // create credentials auto jv = credentials::create(alice, carol, credType); uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() + 100; @@ -1910,7 +1910,7 @@ struct PayChan_test : public beast::unit_test::suite env.close(); // settle delay hasn't elapsed. Channels should exist. BEAST_EXPECT(channelExists(*env.current(), chan)); - auto const closeTime = env.current()->info().parentCloseTime; + auto const closeTime = env.current()->header().parentCloseTime; auto const minExpiration = closeTime + settleDelay; env.close(minExpiration); env(claim(alice, chan), txflags(tfClose)); diff --git a/src/test/app/PermissionedDEX_test.cpp b/src/test/app/PermissionedDEX_test.cpp index 25d94a968b..4b7a1db1be 100644 --- a/src/test/app/PermissionedDEX_test.cpp +++ b/src/test/app/PermissionedDEX_test.cpp @@ -242,7 +242,7 @@ class PermissionedDEX_test : public beast::unit_test::suite auto jv = credentials::create(devin, domainOwner, credType); uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count(); jv[sfExpiration.jsonName] = t + 20; @@ -797,7 +797,7 @@ class PermissionedDEX_test : public beast::unit_test::suite auto jv = credentials::create(devin, domainOwner, credType); uint32_t const t = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count(); jv[sfExpiration.jsonName] = t + 20; diff --git a/src/test/app/RCLValidations_test.cpp b/src/test/app/RCLValidations_test.cpp index 2edf61c8c2..2d3c4f2af5 100644 --- a/src/test/app/RCLValidations_test.cpp +++ b/src/test/app/RCLValidations_test.cpp @@ -111,13 +111,13 @@ class RCLValidations_test : public beast::unit_test::suite { std::shared_ptr ledger = history.back(); RCLValidatedLedger a{ledger, env.journal}; - BEAST_EXPECT(a.seq() == ledger->info().seq); + BEAST_EXPECT(a.seq() == ledger->header().seq); BEAST_EXPECT(a.minSeq() == a.seq() - maxAncestors); // Ensure the ancestral 256 ledgers have proper ID for (Seq s = a.seq(); s > 0; s--) { if (s >= a.minSeq()) - BEAST_EXPECT(a[s] == history[s - 1]->info().hash); + BEAST_EXPECT(a[s] == history[s - 1]->header().hash); else BEAST_EXPECT(a[s] == ID{0}); } diff --git a/src/test/app/Regression_test.cpp b/src/test/app/Regression_test.cpp index 81184a595b..be51d9c96e 100644 --- a/src/test/app/Regression_test.cpp +++ b/src/test/app/Regression_test.cpp @@ -50,7 +50,7 @@ struct Regression_test : public beast::unit_test::suite std::vector{}, env.app().getNodeFamily()); auto expectedDrops = INITIAL_XRP; - BEAST_EXPECT(closed->info().drops == expectedDrops); + BEAST_EXPECT(closed->header().drops == expectedDrops); auto const aliceXRP = 400; auto const aliceAmount = XRP(aliceXRP); @@ -70,7 +70,7 @@ struct Regression_test : public beast::unit_test::suite accum.apply(*next); } expectedDrops -= next->fees().base; - BEAST_EXPECT(next->info().drops == expectedDrops); + BEAST_EXPECT(next->header().drops == expectedDrops); { auto const sle = next->read(keylet::account(Account("alice").id())); BEAST_EXPECT(sle); @@ -101,7 +101,7 @@ struct Regression_test : public beast::unit_test::suite BEAST_EXPECT(balance == XRP(0)); } expectedDrops -= aliceXRP * dropsPerXRP; - BEAST_EXPECT(next->info().drops == expectedDrops); + BEAST_EXPECT(next->header().drops == expectedDrops); } void diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index e59cf7deff..0af91f25a6 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -726,7 +726,7 @@ public: env(noop(daria)); checkMetrics(*this, env, 0, std::nullopt, 3, 2); - BEAST_EXPECT(env.current()->info().seq == 6); + BEAST_EXPECT(env.current()->header().seq == 6); // Fail to queue an item with a low LastLedgerSeq env(noop(alice), last_ledger_seq(7), ter(telCAN_NOT_QUEUE)); // Queue an item with a sufficient LastLedgerSeq. @@ -1075,7 +1075,7 @@ public: // Alice - fill up the queue std::int64_t aliceFee = 27; aliceSeq = env.seq(alice); - auto lastLedgerSeq = env.current()->info().seq + 2; + auto lastLedgerSeq = env.current()->header().seq + 2; for (auto i = 0; i < 7; i++) { env(noop(alice), @@ -2683,7 +2683,7 @@ public: checkMetrics(*this, env, 0, std::nullopt, 2, 1); auto const aliceSeq = env.seq(alice); - BEAST_EXPECT(env.current()->info().seq == 3); + BEAST_EXPECT(env.current()->header().seq == 3); env(noop(alice), seq(aliceSeq), last_ledger_seq(5), ter(terQUEUED)); env(noop(alice), seq(aliceSeq + 1), last_ledger_seq(5), ter(terQUEUED)); env(noop(alice), @@ -2779,7 +2779,7 @@ public: checkMetrics(*this, env, 0, std::nullopt, 2, 1); auto const aliceSeq = env.seq(alice); - BEAST_EXPECT(env.current()->info().seq == 3); + BEAST_EXPECT(env.current()->header().seq == 3); // Start by procuring tickets for alice to use to keep her queue full // without affecting the sequence gap that will appear later. @@ -2932,7 +2932,7 @@ public: // Queue up several transactions for alice sign-and-submit auto const aliceSeq = env.seq(alice); - auto const lastLedgerSeq = env.current()->info().seq + 2; + auto const lastLedgerSeq = env.current()->header().seq + 2; auto submitParams = Json::Value(Json::objectValue); for (int i = 0; i < 5; ++i) @@ -3073,7 +3073,7 @@ public: prevLedgerWithQueue[jss::account] = alice.human(); prevLedgerWithQueue[jss::queue] = true; prevLedgerWithQueue[jss::ledger_index] = 3; - BEAST_EXPECT(env.current()->info().seq > 3); + BEAST_EXPECT(env.current()->header().seq > 3); { // account_info without the "queue" argument. diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index ce76e06912..a07045743e 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -3520,7 +3520,7 @@ class Vault_test : public beast::unit_test::suite { testcase("private vault expired authorization"); uint32_t const closeTime = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count(); { diff --git a/src/test/consensus/NegativeUNL_test.cpp b/src/test/consensus/NegativeUNL_test.cpp index 5b7eebed2f..a1000c0d49 100644 --- a/src/test/consensus/NegativeUNL_test.cpp +++ b/src/test/consensus/NegativeUNL_test.cpp @@ -621,7 +621,7 @@ struct NetworkHistory keyPair.second, v, [&](STValidation& v) { - v.setFieldH256(sfLedgerHash, ledger->info().hash); + v.setFieldH256(sfLedgerHash, ledger->header().hash); v.setFieldU32(sfLedgerSequence, ledger->seq()); v.setFlag(vfFullValidation); }); @@ -1773,7 +1773,7 @@ class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite keys.second, calcNodeID(keys.first), [&](STValidation& v) { - v.setFieldH256(sfLedgerHash, l->info().hash); + v.setFieldH256(sfLedgerHash, l->header().hash); v.setFieldU32(sfLedgerSequence, l->seq()); v.setFlag(vfFullValidation); }); diff --git a/src/test/jtx/impl/Env.cpp b/src/test/jtx/impl/Env.cpp index 9ce76d01c9..311a5dde3a 100644 --- a/src/test/jtx/impl/Env.cpp +++ b/src/test/jtx/impl/Env.cpp @@ -67,7 +67,8 @@ Env::AppBundle::AppBundle( app->logs().threshold(thresh); if (!app->setup({})) Throw("Env::AppBundle: setup failed"); - timeKeeper->set(app->getLedgerMaster().getClosedLedger()->info().closeTime); + timeKeeper->set( + app->getLedgerMaster().getClosedLedger()->header().closeTime); app->start(false /*don't start timers*/); thread = std::thread([&]() { app->run(); }); @@ -107,7 +108,7 @@ Env::close( // Round up to next distinguishable value using namespace std::chrono_literals; bool res = true; - closeTime += closed()->info().closeTimeResolution - 1s; + closeTime += closed()->header().closeTimeResolution - 1s; timeKeeper().set(closeTime); // Go through the rpc interface unless we need to simulate // a specific consensus delay. @@ -130,7 +131,7 @@ Env::close( res = false; } } - timeKeeper().set(closed()->info().closeTime); + timeKeeper().set(closed()->header().closeTime); return res; } diff --git a/src/test/jtx/impl/Oracle.cpp b/src/test/jtx/impl/Oracle.cpp index 4c5fab3b61..e3396f3ebc 100644 --- a/src/test/jtx/impl/Oracle.cpp +++ b/src/test/jtx/impl/Oracle.cpp @@ -216,7 +216,7 @@ Oracle::set(UpdateArg const& arg) else jv[jss::LastUpdateTime] = to_string( duration_cast( - env_.current()->info().closeTime.time_since_epoch()) + env_.current()->header().closeTime.time_since_epoch()) .count() + epoch_offset.count()); Json::Value dataSeries(Json::arrayValue); diff --git a/src/test/ledger/Directory_test.cpp b/src/test/ledger/Directory_test.cpp index b927103f8f..68c3286660 100644 --- a/src/test/ledger/Directory_test.cpp +++ b/src/test/ledger/Directory_test.cpp @@ -436,7 +436,7 @@ struct Directory_test : public beast::unit_test::suite // exist env(offer(alice, XRP(1), USD(1))); auto const txID = to_string(env.tx()->getTransactionID()); - auto const ledgerSeq = env.current()->info().seq; + auto const ledgerSeq = env.current()->header().seq; env.close(); // Make sure the fields only exist if the object is touched env(noop(gw)); diff --git a/src/test/ledger/SkipList_test.cpp b/src/test/ledger/SkipList_test.cpp index b84f002503..4869036014 100644 --- a/src/test/ledger/SkipList_test.cpp +++ b/src/test/ledger/SkipList_test.cpp @@ -35,32 +35,35 @@ class SkipList_test : public beast::unit_test::suite { auto l = *(std::next(std::begin(history))); - BEAST_EXPECT((*std::begin(history))->info().seq < l->info().seq); BEAST_EXPECT( - !hashOfSeq(*l, l->info().seq + 1, env.journal).has_value()); + (*std::begin(history))->header().seq < l->header().seq); BEAST_EXPECT( - hashOfSeq(*l, l->info().seq, env.journal) == l->info().hash); + !hashOfSeq(*l, l->header().seq + 1, env.journal).has_value()); BEAST_EXPECT( - hashOfSeq(*l, l->info().seq - 1, env.journal) == - l->info().parentHash); - BEAST_EXPECT(!hashOfSeq(*history.back(), l->info().seq, env.journal) - .has_value()); + hashOfSeq(*l, l->header().seq, env.journal) == + l->header().hash); + BEAST_EXPECT( + hashOfSeq(*l, l->header().seq - 1, env.journal) == + l->header().parentHash); + BEAST_EXPECT( + !hashOfSeq(*history.back(), l->header().seq, env.journal) + .has_value()); } // ledger skip lists store up to the previous 256 hashes for (auto i = history.crbegin(); i != history.crend(); i += 256) { for (auto n = i; - n != std::next(i, (*i)->info().seq - 256 > 1 ? 257 : 256); + n != std::next(i, (*i)->header().seq - 256 > 1 ? 257 : 256); ++n) { BEAST_EXPECT( - hashOfSeq(**i, (*n)->info().seq, env.journal) == - (*n)->info().hash); + hashOfSeq(**i, (*n)->header().seq, env.journal) == + (*n)->header().hash); } // edge case accessing beyond 256 - BEAST_EXPECT(!hashOfSeq(**i, (*i)->info().seq - 258, env.journal) + BEAST_EXPECT(!hashOfSeq(**i, (*i)->header().seq - 258, env.journal) .has_value()); } @@ -71,8 +74,8 @@ class SkipList_test : public beast::unit_test::suite for (auto n = std::next(i, 512); n != history.crend(); n += 256) { BEAST_EXPECT( - hashOfSeq(**i, (*n)->info().seq, env.journal) == - (*n)->info().hash); + hashOfSeq(**i, (*n)->header().seq, env.journal) == + (*n)->header().hash); } } } diff --git a/src/test/ledger/View_test.cpp b/src/test/ledger/View_test.cpp index 9c7a5a286e..a8f3f7fc3b 100644 --- a/src/test/ledger/View_test.cpp +++ b/src/test/ledger/View_test.cpp @@ -1019,8 +1019,8 @@ class View_test : public beast::unit_test::suite // Try the other interface. // Note that the different interface has different outcomes. - auto const& iA3 = rdViewA3->info(); - auto const& iA4 = rdViewA4->info(); + auto const& iA3 = rdViewA3->header(); + auto const& iA4 = rdViewA4->header(); BEAST_EXPECT(areCompatible(iA3.hash, iA3.seq, *rdViewA4, jStream, "")); BEAST_EXPECT(areCompatible(iA4.hash, iA4.seq, *rdViewA3, jStream, "")); diff --git a/src/test/rpc/AccountLines_test.cpp b/src/test/rpc/AccountLines_test.cpp index 2bc6c38779..200331b9be 100644 --- a/src/test/rpc/AccountLines_test.cpp +++ b/src/test/rpc/AccountLines_test.cpp @@ -68,7 +68,7 @@ public: } env.fund(XRP(10000), alice); env.close(); - LedgerHeader const ledger3Info = env.closed()->info(); + LedgerHeader const ledger3Info = env.closed()->header(); BEAST_EXPECT(ledger3Info.seq == 3); { @@ -118,7 +118,7 @@ public: env(pay(gw1, alice, gw1Currency(50 + c))); } env.close(); - LedgerHeader const ledger4Info = env.closed()->info(); + LedgerHeader const ledger4Info = env.closed()->header(); BEAST_EXPECT(ledger4Info.seq == 4); // Add another set of trust lines in another ledger so we can see @@ -153,7 +153,7 @@ public: tfSetNoRipple | tfSetFreeze | tfSetDeepFreeze)); } env.close(); - LedgerHeader const ledger58Info = env.closed()->info(); + LedgerHeader const ledger58Info = env.closed()->header(); BEAST_EXPECT(ledger58Info.seq == 58); // A re-usable test for historic ledgers. @@ -817,7 +817,7 @@ public: } env.fund(XRP(10000), alice); env.close(); - LedgerHeader const ledger3Info = env.closed()->info(); + LedgerHeader const ledger3Info = env.closed()->header(); BEAST_EXPECT(ledger3Info.seq == 3); { @@ -899,7 +899,7 @@ public: env(pay(gw1, alice, gw1Currency(50 + c))); } env.close(); - LedgerHeader const ledger4Info = env.closed()->info(); + LedgerHeader const ledger4Info = env.closed()->header(); BEAST_EXPECT(ledger4Info.seq == 4); // Add another set of trust lines in another ledger so we can see @@ -934,7 +934,7 @@ public: tfSetNoRipple | tfSetFreeze | tfSetDeepFreeze)); } env.close(); - LedgerHeader const ledger58Info = env.closed()->info(); + LedgerHeader const ledger58Info = env.closed()->header(); BEAST_EXPECT(ledger58Info.seq == 58); // A re-usable test for historic ledgers. diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp index f55d053c9e..f9f21c5e87 100644 --- a/src/test/rpc/AccountTx_test.cpp +++ b/src/test/rpc/AccountTx_test.cpp @@ -242,7 +242,7 @@ class AccountTx_test : public beast::unit_test::suite env.rpc("json", "account_tx", to_string(p)), rpcLGR_IDX_MALFORMED)); - p[jss::ledger_index_min] = env.current()->info().seq; + p[jss::ledger_index_min] = env.current()->header().seq; BEAST_EXPECT(isErr( env.rpc("json", "account_tx", to_string(p)), (apiVersion == 1 ? rpcLGR_IDXS_INVALID @@ -256,7 +256,7 @@ class AccountTx_test : public beast::unit_test::suite BEAST_EXPECT(hasTxs( env.rpc(apiVersion, "json", "account_tx", to_string(p)))); - p[jss::ledger_index_max] = env.current()->info().seq; + p[jss::ledger_index_max] = env.current()->header().seq; if (apiVersion < 2u) BEAST_EXPECT(hasTxs( env.rpc(apiVersion, "json", "account_tx", to_string(p)))); @@ -269,11 +269,11 @@ class AccountTx_test : public beast::unit_test::suite BEAST_EXPECT(hasTxs( env.rpc(apiVersion, "json", "account_tx", to_string(p)))); - p[jss::ledger_index_max] = env.closed()->info().seq; + p[jss::ledger_index_max] = env.closed()->header().seq; BEAST_EXPECT(hasTxs( env.rpc(apiVersion, "json", "account_tx", to_string(p)))); - p[jss::ledger_index_max] = env.closed()->info().seq - 1; + p[jss::ledger_index_max] = env.closed()->header().seq - 1; BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); } @@ -281,19 +281,19 @@ class AccountTx_test : public beast::unit_test::suite { Json::Value p{jParams}; - p[jss::ledger_index] = env.closed()->info().seq; + p[jss::ledger_index] = env.closed()->header().seq; BEAST_EXPECT(hasTxs( env.rpc(apiVersion, "json", "account_tx", to_string(p)))); - p[jss::ledger_index] = env.closed()->info().seq - 1; + p[jss::ledger_index] = env.closed()->header().seq - 1; BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); - p[jss::ledger_index] = env.current()->info().seq; + p[jss::ledger_index] = env.current()->header().seq; BEAST_EXPECT(isErr( env.rpc("json", "account_tx", to_string(p)), rpcLGR_NOT_VALIDATED)); - p[jss::ledger_index] = env.current()->info().seq + 1; + p[jss::ledger_index] = env.current()->header().seq + 1; BEAST_EXPECT(isErr( env.rpc("json", "account_tx", to_string(p)), rpcLGR_NOT_FOUND)); } @@ -302,11 +302,11 @@ class AccountTx_test : public beast::unit_test::suite { Json::Value p{jParams}; - p[jss::ledger_hash] = to_string(env.closed()->info().hash); + p[jss::ledger_hash] = to_string(env.closed()->header().hash); BEAST_EXPECT(hasTxs( env.rpc(apiVersion, "json", "account_tx", to_string(p)))); - p[jss::ledger_hash] = to_string(env.closed()->info().parentHash); + p[jss::ledger_hash] = to_string(env.closed()->header().parentHash); BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); } @@ -333,7 +333,7 @@ class AccountTx_test : public beast::unit_test::suite // Ledger index max only { Json::Value p{jParams}; - p[jss::ledger_index_max] = env.current()->info().seq; + p[jss::ledger_index_max] = env.current()->header().seq; if (apiVersion < 2u) BEAST_EXPECT(hasTxs( env.rpc(apiVersion, "json", "account_tx", to_string(p)))); @@ -903,7 +903,7 @@ class AccountTx_test : public beast::unit_test::suite // // ledger hash should be fixed regardless any change to account history // BEAST_EXPECT( - // to_string(env.closed()->info().hash) == + // to_string(env.closed()->header().hash) == // "0BD507BB87D3C0E73B462485E6E381798A8C82FC49BF17FE39C60E08A1AF035D"); // alice authorizes bob diff --git a/src/test/rpc/DepositAuthorized_test.cpp b/src/test/rpc/DepositAuthorized_test.cpp index 8ed52542d6..6e46b077b8 100644 --- a/src/test/rpc/DepositAuthorized_test.cpp +++ b/src/test/rpc/DepositAuthorized_test.cpp @@ -557,7 +557,7 @@ public: // check expired credentials char const credType2[] = "fghijk"; std::uint32_t const x = env.current() - ->info() + ->header() .parentCloseTime.time_since_epoch() .count() + 40; diff --git a/src/test/rpc/LedgerData_test.cpp b/src/test/rpc/LedgerData_test.cpp index 3705133432..9ac61c277a 100644 --- a/src/test/rpc/LedgerData_test.cpp +++ b/src/test/rpc/LedgerData_test.cpp @@ -217,7 +217,7 @@ public: if (BEAST_EXPECT(jrr.isMember(jss::ledger))) BEAST_EXPECT( jrr[jss::ledger][jss::ledger_hash] == - to_string(env.closed()->info().hash)); + to_string(env.closed()->header().hash)); } { // Closed ledger with binary form diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index 372f5676b0..8e9be02dda 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -539,7 +539,7 @@ class LedgerEntry_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; { // Exercise ledger_closed along the way. Json::Value const jrr = env.rpc("ledger_closed")[jss::result]; @@ -646,7 +646,7 @@ class LedgerEntry_test : public beast::unit_test::suite env(check::create(env.master, alice, XRP(100))); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; { // Request a check. Json::Value jvParams; @@ -765,7 +765,7 @@ class LedgerEntry_test : public beast::unit_test::suite env.close(); env(delegate::set(alice, bob, {"Payment", "CheckCreate"})); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; std::string delegateIndex; { // Request by account and authorize @@ -823,7 +823,7 @@ class LedgerEntry_test : public beast::unit_test::suite env(deposit::auth(alice, becky)); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; std::string depositPreauthIndex; { // Request a depositPreauth by owner and authorized. @@ -1171,7 +1171,7 @@ class LedgerEntry_test : public beast::unit_test::suite } env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; { // Exercise ledger_closed along the way. Json::Value const jrr = env.rpc("ledger_closed")[jss::result]; @@ -1331,7 +1331,7 @@ class LedgerEntry_test : public beast::unit_test::suite env(escrowCreate(alice, alice, XRP(333), env.now() + 2s)); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; std::string escrowIndex; { // Request the escrow using owner and sequence. @@ -1379,7 +1379,7 @@ class LedgerEntry_test : public beast::unit_test::suite env(offer(alice, USD(321), XRP(322))); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; std::string offerIndex; { // Request the offer using owner and sequence. @@ -1443,7 +1443,7 @@ class LedgerEntry_test : public beast::unit_test::suite env(payChanCreate(alice, env.master, XRP(57), 18s, alice.pk())); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; uint256 const payChanIndex{ keylet::payChan(alice, env.master, env.seq(alice) - 1).key}; @@ -1495,7 +1495,8 @@ class LedgerEntry_test : public beast::unit_test::suite // check both aliases for (auto const& fieldName : {jss::ripple_state, jss::state}) { - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{ + to_string(env.closed()->header().hash)}; { // Request the trust line using the accounts and currency. Json::Value jvParams; @@ -1637,7 +1638,7 @@ class LedgerEntry_test : public beast::unit_test::suite env(ticket::create(env.master, 2)); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; // Request four tickets: one before the first one we created, the // two created tickets, and the ticket that would come after the // last created ticket. @@ -1734,7 +1735,7 @@ class LedgerEntry_test : public beast::unit_test::suite env(didCreate(alice)); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; { // Request the DID using its index. @@ -1865,7 +1866,7 @@ class LedgerEntry_test : public beast::unit_test::suite tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback}); mptAlice.authorize({.account = bob, .holderCount = 1}); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; std::string const badMptID = "00000193B9DDCAF401B5B3B26875986043F82CD0D13B4315"; @@ -2024,7 +2025,7 @@ class LedgerEntry_test : public beast::unit_test::suite env(check::create(env.master, alice, XRP(100))); env.close(); - std::string const ledgerHash{to_string(env.closed()->info().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; { // Request a check. Json::Value const jrr = @@ -2095,7 +2096,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, createBridgeObjects(mcEnv, scEnv); - std::string const ledgerHash{to_string(mcEnv.closed()->info().hash)}; + std::string const ledgerHash{to_string(mcEnv.closed()->header().hash)}; std::string bridge_index; Json::Value mcBridge; { diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 4a90793fa2..7728973045 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -60,7 +60,7 @@ class LedgerRPC_test : public beast::unit_test::suite Env env{*this}; env.close(); - BEAST_EXPECT(env.current()->info().seq == 4); + BEAST_EXPECT(env.current()->header().seq == 4); { Json::Value jvParams; @@ -87,9 +87,9 @@ class LedgerRPC_test : public beast::unit_test::suite BEAST_EXPECT(jrr[jss::ledger][jss::closed] == false); BEAST_EXPECT( jrr[jss::ledger][jss::ledger_index] == - std::to_string(env.current()->info().seq)); + std::to_string(env.current()->header().seq)); BEAST_EXPECT( - jrr[jss::ledger_current_index] == env.current()->info().seq); + jrr[jss::ledger_current_index] == env.current()->header().seq); } } @@ -182,12 +182,12 @@ class LedgerRPC_test : public beast::unit_test::suite Env env{*this}; env.close(); - BEAST_EXPECT(env.current()->info().seq == 4); + BEAST_EXPECT(env.current()->header().seq == 4); { auto const jrr = env.rpc("ledger_current")[jss::result]; BEAST_EXPECT( - jrr[jss::ledger_current_index] == env.current()->info().seq); + jrr[jss::ledger_current_index] == env.current()->header().seq); } } @@ -475,7 +475,7 @@ class LedgerRPC_test : public beast::unit_test::suite env(noop(alice)); } - BEAST_EXPECT(env.current()->info().seq == 5); + BEAST_EXPECT(env.current()->header().seq == 5); // Put some txs in the queue // Alice auto aliceSeq = env.seq(alice); @@ -508,7 +508,7 @@ class LedgerRPC_test : public beast::unit_test::suite env.close(); env.close(); env.close(); - BEAST_EXPECT(env.current()->info().seq == 8); + BEAST_EXPECT(env.current()->header().seq == 8); jrr = env.rpc("json", "ledger", to_string(jv))[jss::result]; BEAST_EXPECT(jrr[jss::queue_data].size() == 11); @@ -517,7 +517,7 @@ class LedgerRPC_test : public beast::unit_test::suite jrr = env.rpc("json", "ledger", to_string(jv))[jss::result]; std::string const txid0 = [&]() { - auto const& parentHash = env.current()->info().parentHash; + auto const& parentHash = env.current()->header().parentHash; if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2)) { std::string const txid1 = [&]() { @@ -559,7 +559,7 @@ class LedgerRPC_test : public beast::unit_test::suite jrr = env.rpc("json", "ledger", to_string(jv))[jss::result]; if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2)) { - auto const& parentHash = env.current()->info().parentHash; + auto const& parentHash = env.current()->header().parentHash; auto const txid1 = [&]() { auto const& txj = jrr[jss::queue_data][1u]; BEAST_EXPECT(txj[jss::account] == alice.human()); diff --git a/src/test/rpc/LedgerRequest_test.cpp b/src/test/rpc/LedgerRequest_test.cpp index 68d29d1901..013d4cbe0f 100644 --- a/src/test/rpc/LedgerRequest_test.cpp +++ b/src/test/rpc/LedgerRequest_test.cpp @@ -32,7 +32,7 @@ public: env.close(); env.close(); - BEAST_EXPECT(env.current()->info().seq == 5); + BEAST_EXPECT(env.current()->header().seq == 5); { // arbitrary text is converted to 0. diff --git a/src/test/rpc/Simulate_test.cpp b/src/test/rpc/Simulate_test.cpp index d7018fdbbc..61d3f1ce6e 100644 --- a/src/test/rpc/Simulate_test.cpp +++ b/src/test/rpc/Simulate_test.cpp @@ -1027,7 +1027,7 @@ class Simulate_test : public beast::unit_test::suite auto jv = credentials::create(subject, issuer, credType); uint32_t const t = - env.current()->info().parentCloseTime.time_since_epoch().count(); + env.current()->header().parentCloseTime.time_since_epoch().count(); jv[sfExpiration.jsonName] = t; env(jv); env.close(); diff --git a/src/test/rpc/Subscribe_test.cpp b/src/test/rpc/Subscribe_test.cpp index 98e86484f5..a4eea3f12c 100644 --- a/src/test/rpc/Subscribe_test.cpp +++ b/src/test/rpc/Subscribe_test.cpp @@ -469,11 +469,11 @@ public: return false; if (jv[jss::ledger_hash] != - to_string(env.closed()->info().hash)) + to_string(env.closed()->header().hash)) return false; if (jv[jss::ledger_index] != - std::to_string(env.closed()->info().seq)) + std::to_string(env.closed()->header().seq)) return false; if (jv[jss::flags] != (vfFullyCanonicalSig | vfFullValidation)) @@ -504,7 +504,7 @@ public: // Certain fields are only added on a flag ledger. bool const isFlagLedger = - (env.closed()->info().seq + 1) % 256 == 0; + (env.closed()->header().seq + 1) % 256 == 0; if (jv.isMember(jss::server_version) != isFlagLedger) return false; @@ -520,7 +520,7 @@ public: // Check stream update. Look at enough stream entries so we see // at least one flag ledger. - while (env.closed()->info().seq < 300) + while (env.closed()->header().seq < 300) { env.close(); using namespace std::chrono_literals; diff --git a/src/test/rpc/Transaction_test.cpp b/src/test/rpc/Transaction_test.cpp index f8ce2bc830..b1bea237f5 100644 --- a/src/test/rpc/Transaction_test.cpp +++ b/src/test/rpc/Transaction_test.cpp @@ -50,7 +50,7 @@ class Transaction_test : public beast::unit_test::suite std::vector> txns; std::vector> metas; - auto const startLegSeq = env.current()->info().seq; + auto const startLegSeq = env.current()->header().seq; for (int i = 0; i < 750; ++i) { env(noop(alice)); @@ -59,7 +59,7 @@ class Transaction_test : public beast::unit_test::suite metas.emplace_back( env.closed()->txRead(env.tx()->getTransactionID()).second); } - auto const endLegSeq = env.closed()->info().seq; + auto const endLegSeq = env.closed()->header().seq; // Find the existing transactions for (size_t i = 0; i < txns.size(); ++i) @@ -302,7 +302,7 @@ class Transaction_test : public beast::unit_test::suite std::vector> txns; std::vector> metas; - auto const startLegSeq = env.current()->info().seq; + auto const startLegSeq = env.current()->header().seq; for (int i = 0; i < 750; ++i) { env(noop(alice)); @@ -311,7 +311,7 @@ class Transaction_test : public beast::unit_test::suite metas.emplace_back( env.closed()->txRead(env.tx()->getTransactionID()).second); } - auto const endLegSeq = env.closed()->info().seq; + auto const endLegSeq = env.closed()->header().seq; // Find the existing transactions for (size_t i = 0; i < txns.size(); ++i) @@ -630,7 +630,7 @@ class Transaction_test : public beast::unit_test::suite auto const alice = Account("alice"); auto const bob = Account("bob"); - auto const startLegSeq = env.current()->info().seq; + auto const startLegSeq = env.current()->header().seq; env.fund(XRP(10000), alice, bob); env(pay(alice, bob, XRP(10))); env.close(); @@ -661,7 +661,7 @@ class Transaction_test : public beast::unit_test::suite Account const alice = Account("alice"); Account const bob = Account("bob"); - std::uint32_t const startLegSeq = env.current()->info().seq; + std::uint32_t const startLegSeq = env.current()->header().seq; env.fund(XRP(10000), alice, bob); env(pay(alice, bob, XRP(10))); env.close(); @@ -709,7 +709,7 @@ class Transaction_test : public beast::unit_test::suite env(pay(alice, bob, XRP(10))); env.close(); - auto const ledgerSeq = env.current()->info().seq; + auto const ledgerSeq = env.current()->header().seq; env(noop(alice), ter(tesSUCCESS)); env.close(); @@ -738,7 +738,7 @@ class Transaction_test : public beast::unit_test::suite auto const alice = Account("alice"); auto const bob = Account("bob"); - auto const startLegSeq = env.current()->info().seq; + auto const startLegSeq = env.current()->header().seq; env.fund(XRP(10000), alice, bob); env(pay(alice, bob, XRP(10))); env.close(); diff --git a/src/test/server/ServerStatus_test.cpp b/src/test/server/ServerStatus_test.cpp index 0a82c3b7e1..b93c3a30e7 100644 --- a/src/test/server/ServerStatus_test.cpp +++ b/src/test/server/ServerStatus_test.cpp @@ -842,7 +842,7 @@ class ServerStatus_test : public beast::unit_test::suite, // mark the Network as having an Amendment Warning, but won't fail env.app().getOPs().setAmendmentWarned(); - env.app().getOPs().beginConsensus(env.closed()->info().hash, {}); + env.app().getOPs().beginConsensus(env.closed()->header().hash, {}); // consensus doesn't change BEAST_EXPECT( @@ -973,7 +973,7 @@ class ServerStatus_test : public beast::unit_test::suite, // mark the Network as Amendment Blocked, but still won't fail until // ELB is enabled (next step) env.app().getOPs().setAmendmentBlocked(); - env.app().getOPs().beginConsensus(env.closed()->info().hash, {}); + env.app().getOPs().beginConsensus(env.closed()->header().hash, {}); // consensus now sees validation disabled BEAST_EXPECT( diff --git a/src/xrpld/app/consensus/RCLConsensus.cpp b/src/xrpld/app/consensus/RCLConsensus.cpp index 09584f2e77..4c2ecbac10 100644 --- a/src/xrpld/app/consensus/RCLConsensus.cpp +++ b/src/xrpld/app/consensus/RCLConsensus.cpp @@ -135,11 +135,11 @@ RCLConsensus::Adaptor::acquireLedger(LedgerHash const& hash) !built->open() && built->isImmutable(), "ripple::RCLConsensus::Adaptor::acquireLedger : valid ledger state"); XRPL_ASSERT( - built->info().hash == hash, + built->header().hash == hash, "ripple::RCLConsensus::Adaptor::acquireLedger : ledger hash match"); // Notify inbound transactions of the new ledger sequence number - inboundTransactions_.newRound(built->info().seq); + inboundTransactions_.newRound(built->header().seq); return RCLCxLedger(built); } @@ -309,7 +309,7 @@ RCLConsensus::Adaptor::onClose( ledgerMaster_.applyHeldTransactions(); // Tell the ledger master not to acquire the ledger we're probably building - ledgerMaster_.setBuildingLedger(prevLedger->info().seq + 1); + ledgerMaster_.setBuildingLedger(prevLedger->header().seq + 1); auto initialLedger = app_.openLedger().current(); @@ -338,7 +338,7 @@ RCLConsensus::Adaptor::onClose( // pseudo-transactions auto validations = app_.validators().negativeUNLFilter( app_.getValidations().getTrustedForLedger( - prevLedger->info().parentHash, prevLedger->seq() - 1)); + prevLedger->header().parentHash, prevLedger->seq() - 1)); if (validations.size() >= app_.validators().quorum()) { feeVote_->doVoting(prevLedger, validations, initialSet); @@ -364,7 +364,7 @@ RCLConsensus::Adaptor::onClose( if (!wrongLCL) { - LedgerIndex const seq = prevLedger->info().seq + 1; + LedgerIndex const seq = prevLedger->header().seq + 1; RCLCensorshipDetector::TxIDSeqVec proposed; initialSet->visitLeaves( @@ -382,7 +382,7 @@ RCLConsensus::Adaptor::onClose( return Result{ std::move(initialSet), RCLCxPeerPos::Proposal{ - initialLedger->info().parentHash, + initialLedger->header().parentHash, RCLCxPeerPos::Proposal::seqJoin, setHash, closeTime, @@ -663,10 +663,10 @@ RCLConsensus::Adaptor::doAccept( // Do these need to exist? XRPL_ASSERT( - ledgerMaster_.getClosedLedger()->info().hash == built.id(), + ledgerMaster_.getClosedLedger()->header().hash == built.id(), "ripple::RCLConsensus::Adaptor::doAccept : ledger hash match"); XRPL_ASSERT( - app_.openLedger().current()->info().parentHash == built.id(), + app_.openLedger().current()->header().parentHash == built.id(), "ripple::RCLConsensus::Adaptor::doAccept : parent hash match"); } @@ -764,7 +764,7 @@ RCLConsensus::Adaptor::buildLCL( if (auto const replayData = ledgerMaster_.releaseReplay()) { XRPL_ASSERT( - replayData->parent()->info().hash == previousLedger.id(), + replayData->parent()->header().hash == previousLedger.id(), "ripple::RCLConsensus::Adaptor::buildLCL : parent hash match"); return buildLedger(*replayData, tapNONE, app_, j_); } @@ -786,7 +786,7 @@ RCLConsensus::Adaptor::buildLCL( // And stash the ledger in the ledger master if (ledgerMaster_.storeLedger(built)) JLOG(j_.debug()) << "Consensus built ledger we already had"; - else if (app_.getInboundLedgers().find(built->info().hash)) + else if (app_.getInboundLedgers().find(built->header().hash)) JLOG(j_.debug()) << "Consensus built ledger we were acquiring"; else JLOG(j_.debug()) << "Consensus built new ledger"; @@ -833,7 +833,7 @@ RCLConsensus::Adaptor::validate( // validated ledger. This may be the hash of the ledger we are // validating here, and that's fine. if (auto const vl = ledgerMaster_.getValidatedLedger()) - v.setFieldH256(sfValidatedHash, vl->info().hash); + v.setFieldH256(sfValidatedHash, vl->header().hash); v.setFieldU64(sfCookie, valCookie_); diff --git a/src/xrpld/app/consensus/RCLCxLedger.h b/src/xrpld/app/consensus/RCLCxLedger.h index 93b55d76d3..5671fa988d 100644 --- a/src/xrpld/app/consensus/RCLCxLedger.h +++ b/src/xrpld/app/consensus/RCLCxLedger.h @@ -41,49 +41,49 @@ public: Seq const& seq() const { - return ledger_->info().seq; + return ledger_->header().seq; } //! Unique identifier (hash) of this ledger. ID const& id() const { - return ledger_->info().hash; + return ledger_->header().hash; } //! Unique identifier (hash) of this ledger's parent. ID const& parentID() const { - return ledger_->info().parentHash; + return ledger_->header().parentHash; } //! Resolution used when calculating this ledger's close time. NetClock::duration closeTimeResolution() const { - return ledger_->info().closeTimeResolution; + return ledger_->header().closeTimeResolution; } //! Whether consensus process agreed on close time of the ledger. bool closeAgree() const { - return ripple::getCloseAgree(ledger_->info()); + return ripple::getCloseAgree(ledger_->header()); } //! The close time of this ledger NetClock::time_point closeTime() const { - return ledger_->info().closeTime; + return ledger_->header().closeTime; } //! The close time of this ledger's parent. NetClock::time_point parentCloseTime() const { - return ledger_->info().parentCloseTime; + return ledger_->header().parentCloseTime; } //! JSON representation of this ledger. diff --git a/src/xrpld/app/consensus/RCLValidations.cpp b/src/xrpld/app/consensus/RCLValidations.cpp index d6a8747c20..d24f24a5f1 100644 --- a/src/xrpld/app/consensus/RCLValidations.cpp +++ b/src/xrpld/app/consensus/RCLValidations.cpp @@ -23,7 +23,7 @@ RCLValidatedLedger::RCLValidatedLedger(MakeGenesis) RCLValidatedLedger::RCLValidatedLedger( std::shared_ptr const& ledger, beast::Journal j) - : ledgerID_{ledger->info().hash}, ledgerSeq_{ledger->seq()}, j_{j} + : ledgerID_{ledger->header().hash}, ledgerSeq_{ledger->seq()}, j_{j} { auto const hashIndex = ledger->read(keylet::skip()); if (hashIndex) @@ -136,7 +136,7 @@ RCLValidationsAdaptor::acquire(LedgerHash const& hash) !ledger->open() && ledger->isImmutable(), "ripple::RCLValidationsAdaptor::acquire : valid ledger state"); XRPL_ASSERT( - ledger->info().hash == hash, + ledger->header().hash == hash, "ripple::RCLValidationsAdaptor::acquire : ledger hash match"); return RCLValidatedLedger(std::move(ledger), j_); diff --git a/src/xrpld/app/ledger/Ledger.cpp b/src/xrpld/app/ledger/Ledger.cpp index aaf71b2dc3..055d9ddc9d 100644 --- a/src/xrpld/app/ledger/Ledger.cpp +++ b/src/xrpld/app/ledger/Ledger.cpp @@ -157,9 +157,9 @@ Ledger::Ledger( , rules_{config.features} , j_(beast::Journal(beast::Journal::getNullSink())) { - info_.seq = 1; - info_.drops = INITIAL_XRP; - info_.closeTimeResolution = ledgerGenesisTimeResolution; + header_.seq = 1; + header_.drops = INITIAL_XRP; + header_.closeTimeResolution = ledgerGenesisTimeResolution; static auto const id = calcAccountID( generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")) @@ -168,7 +168,7 @@ Ledger::Ledger( auto const sle = std::make_shared(keylet::account(id)); sle->setFieldU32(sfSequence, 1); sle->setAccountID(sfAccount, id); - sle->setFieldAmount(sfBalance, info_.drops); + sle->setFieldAmount(sfBalance, header_.drops); rawInsert(sle); } @@ -220,23 +220,25 @@ Ledger::Ledger( , txMap_(SHAMapType::TRANSACTION, info.txHash, family) , stateMap_(SHAMapType::STATE, info.accountHash, family) , rules_(config.features) - , info_(info) + , header_(info) , j_(j) { loaded = true; - if (info_.txHash.isNonZero() && - !txMap_.fetchRoot(SHAMapHash{info_.txHash}, nullptr)) + if (header_.txHash.isNonZero() && + !txMap_.fetchRoot(SHAMapHash{header_.txHash}, nullptr)) { loaded = false; - JLOG(j.warn()) << "Don't have transaction root for ledger" << info_.seq; + JLOG(j.warn()) << "Don't have transaction root for ledger" + << header_.seq; } - if (info_.accountHash.isNonZero() && - !stateMap_.fetchRoot(SHAMapHash{info_.accountHash}, nullptr)) + if (header_.accountHash.isNonZero() && + !stateMap_.fetchRoot(SHAMapHash{header_.accountHash}, nullptr)) { loaded = false; - JLOG(j.warn()) << "Don't have state data root for ledger" << info_.seq; + JLOG(j.warn()) << "Don't have state data root for ledger" + << header_.seq; } txMap_.setImmutable(); @@ -248,9 +250,9 @@ Ledger::Ledger( if (!loaded) { - info_.hash = calculateLedgerHash(info_); + header_.hash = calculateLedgerHash(header_); if (acquire) - family.missingNodeAcquireByHash(info_.hash, info_.seq); + family.missingNodeAcquireByHash(header_.hash, header_.seq); } } @@ -263,25 +265,26 @@ Ledger::Ledger(Ledger const& prevLedger, NetClock::time_point closeTime) , rules_(prevLedger.rules_) , j_(beast::Journal(beast::Journal::getNullSink())) { - info_.seq = prevLedger.info_.seq + 1; - info_.parentCloseTime = prevLedger.info_.closeTime; - info_.hash = prevLedger.info().hash + uint256(1); - info_.drops = prevLedger.info().drops; - info_.closeTimeResolution = prevLedger.info_.closeTimeResolution; - info_.parentHash = prevLedger.info().hash; - info_.closeTimeResolution = getNextLedgerTimeResolution( - prevLedger.info_.closeTimeResolution, - getCloseAgree(prevLedger.info()), - info_.seq); + header_.seq = prevLedger.header_.seq + 1; + header_.parentCloseTime = prevLedger.header_.closeTime; + header_.hash = prevLedger.header().hash + uint256(1); + header_.drops = prevLedger.header().drops; + header_.closeTimeResolution = prevLedger.header_.closeTimeResolution; + header_.parentHash = prevLedger.header().hash; + header_.closeTimeResolution = getNextLedgerTimeResolution( + prevLedger.header_.closeTimeResolution, + getCloseAgree(prevLedger.header()), + header_.seq); - if (prevLedger.info_.closeTime == NetClock::time_point{}) + if (prevLedger.header_.closeTime == NetClock::time_point{}) { - info_.closeTime = roundCloseTime(closeTime, info_.closeTimeResolution); + header_.closeTime = + roundCloseTime(closeTime, header_.closeTimeResolution); } else { - info_.closeTime = - prevLedger.info_.closeTime + info_.closeTimeResolution; + header_.closeTime = + prevLedger.header_.closeTime + header_.closeTimeResolution; } } @@ -290,10 +293,10 @@ Ledger::Ledger(LedgerHeader const& info, Config const& config, Family& family) , txMap_(SHAMapType::TRANSACTION, info.txHash, family) , stateMap_(SHAMapType::STATE, info.accountHash, family) , rules_{config.features} - , info_(info) + , header_(info) , j_(beast::Journal(beast::Journal::getNullSink())) { - info_.hash = calculateLedgerHash(info_); + header_.hash = calculateLedgerHash(header_); } Ledger::Ledger( @@ -307,9 +310,9 @@ Ledger::Ledger( , rules_{config.features} , j_(beast::Journal(beast::Journal::getNullSink())) { - info_.seq = ledgerSeq; - info_.closeTime = closeTime; - info_.closeTimeResolution = ledgerDefaultTimeResolution; + header_.seq = ledgerSeq; + header_.closeTime = closeTime; + header_.closeTimeResolution = ledgerDefaultTimeResolution; defaultFees(config); setup(); } @@ -321,12 +324,12 @@ Ledger::setImmutable(bool rehash) // place the hash transitions to valid if (!mImmutable && rehash) { - info_.txHash = txMap_.getHash().as_uint256(); - info_.accountHash = stateMap_.getHash().as_uint256(); + header_.txHash = txMap_.getHash().as_uint256(); + header_.accountHash = stateMap_.getHash().as_uint256(); } if (rehash) - info_.hash = calculateLedgerHash(info_); + header_.hash = calculateLedgerHash(header_); mImmutable = true; txMap_.setImmutable(); @@ -343,9 +346,9 @@ Ledger::setAccepted( // Used when we witnessed the consensus. XRPL_ASSERT(!open(), "ripple::Ledger::setAccepted : valid ledger state"); - info_.closeTime = closeTime; - info_.closeTimeResolution = closeResolution; - info_.closeFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime; + header_.closeTime = closeTime; + header_.closeTimeResolution = closeResolution; + header_.closeFlags = correctCloseTime ? 0 : sLCF_NoConsensusTime; setImmutable(); } @@ -788,11 +791,11 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const std::vector missingNodes1; std::vector missingNodes2; - if (stateMap_.getHash().isZero() && !info_.accountHash.isZero() && - !stateMap_.fetchRoot(SHAMapHash{info_.accountHash}, nullptr)) + if (stateMap_.getHash().isZero() && !header_.accountHash.isZero() && + !stateMap_.fetchRoot(SHAMapHash{header_.accountHash}, nullptr)) { missingNodes1.emplace_back( - SHAMapType::STATE, SHAMapHash{info_.accountHash}); + SHAMapType::STATE, SHAMapHash{header_.accountHash}); } else { @@ -811,11 +814,11 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const } } - if (txMap_.getHash().isZero() && info_.txHash.isNonZero() && - !txMap_.fetchRoot(SHAMapHash{info_.txHash}, nullptr)) + if (txMap_.getHash().isZero() && header_.txHash.isNonZero() && + !txMap_.fetchRoot(SHAMapHash{header_.txHash}, nullptr)) { missingNodes2.emplace_back( - SHAMapType::TRANSACTION, SHAMapHash{info_.txHash}); + SHAMapType::TRANSACTION, SHAMapHash{header_.txHash}); } else { @@ -836,9 +839,9 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const bool Ledger::assertSensible(beast::Journal ledgerJ) const { - if (info_.hash.isNonZero() && info_.accountHash.isNonZero() && - (info_.accountHash == stateMap_.getHash().as_uint256()) && - (info_.txHash == txMap_.getHash().as_uint256())) + if (header_.hash.isNonZero() && header_.accountHash.isNonZero() && + (header_.accountHash == stateMap_.getHash().as_uint256()) && + (header_.txHash == txMap_.getHash().as_uint256())) { return true; } @@ -846,8 +849,8 @@ Ledger::assertSensible(beast::Journal ledgerJ) const // LCOV_EXCL_START Json::Value j = getJson({*this, {}}); - j[jss::accountTreeHash] = to_string(info_.accountHash); - j[jss::transTreeHash] = to_string(info_.txHash); + j[jss::accountTreeHash] = to_string(header_.accountHash); + j[jss::transTreeHash] = to_string(header_.txHash); JLOG(ledgerJ.fatal()) << "ledger is not sensible" << j; @@ -862,10 +865,10 @@ Ledger::assertSensible(beast::Journal ledgerJ) const void Ledger::updateSkipList() { - if (info_.seq == 0) // genesis ledger has no previous ledger + if (header_.seq == 0) // genesis ledger has no previous ledger return; - std::uint32_t prevIndex = info_.seq - 1; + std::uint32_t prevIndex = header_.seq - 1; // update record of every 256th ledger if ((prevIndex & 0xff) == 0) @@ -889,7 +892,7 @@ Ledger::updateSkipList() XRPL_ASSERT( hashes.size() <= 256, "ripple::Ledger::updateSkipList : first maximum hashes size"); - hashes.push_back(info_.parentHash); + hashes.push_back(header_.parentHash); sle->setFieldV256(sfHashes, STVector256(hashes)); sle->setFieldU32(sfLastLedgerSequence, prevIndex); if (created) @@ -918,7 +921,7 @@ Ledger::updateSkipList() "ripple::Ledger::updateSkipList : second maximum hashes size"); if (hashes.size() == 256) hashes.erase(hashes.begin()); - hashes.push_back(info_.parentHash); + hashes.push_back(header_.parentHash); sle->setFieldV256(sfHashes, STVector256(hashes)); sle->setFieldU32(sfLastLedgerSequence, prevIndex); if (created) @@ -930,12 +933,12 @@ Ledger::updateSkipList() bool Ledger::isFlagLedger() const { - return info_.seq % FLAG_LEDGER_INTERVAL == 0; + return header_.seq % FLAG_LEDGER_INTERVAL == 0; } bool Ledger::isVotingLedger() const { - return (info_.seq + 1) % FLAG_LEDGER_INTERVAL == 0; + return (header_.seq + 1) % FLAG_LEDGER_INTERVAL == 0; } bool @@ -951,7 +954,7 @@ saveValidatedLedger( bool current) { auto j = app.journal("Ledger"); - auto seq = ledger->info().seq; + auto seq = ledger->header().seq; if (!app.pendingSaves().startWork(seq)) { // The save was completed synchronously @@ -982,13 +985,13 @@ pendSaveValidated( bool isCurrent) { if (!app.getHashRouter().setFlags( - ledger->info().hash, HashRouterFlags::SAVED)) + ledger->header().hash, HashRouterFlags::SAVED)) { // We have tried to save this ledger recently auto stream = app.journal("Ledger").debug(); - JLOG(stream) << "Double pend save for " << ledger->info().seq; + JLOG(stream) << "Double pend save for " << ledger->header().seq; - if (!isSynchronous || !app.pendingSaves().pending(ledger->info().seq)) + if (!isSynchronous || !app.pendingSaves().pending(ledger->header().seq)) { // Either we don't need it to be finished // or it is finished @@ -999,11 +1002,11 @@ pendSaveValidated( XRPL_ASSERT( ledger->isImmutable(), "ripple::pendSaveValidated : immutable ledger"); - if (!app.pendingSaves().shouldWork(ledger->info().seq, isSynchronous)) + if (!app.pendingSaves().shouldWork(ledger->header().seq, isSynchronous)) { auto stream = app.journal("Ledger").debug(); JLOG(stream) << "Pend save with seq in pending saves " - << ledger->info().seq; + << ledger->header().seq; return true; } @@ -1075,12 +1078,12 @@ finishLoadByIndexOrHash( return; XRPL_ASSERT( - ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || + ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()), "ripple::finishLoadByIndexOrHash : valid ledger fees"); ledger->setImmutable(); - JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->info().hash); + JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->header().hash); ledger->setFull(); } @@ -1117,7 +1120,7 @@ loadByHash(uint256 const& ledgerHash, Application& app, bool acquire) std::shared_ptr ledger = loadLedgerHelper(*info, app, acquire); finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger")); XRPL_ASSERT( - !ledger || ledger->info().hash == ledgerHash, + !ledger || ledger->header().hash == ledgerHash, "ripple::loadByHash : ledger hash match if loaded"); return ledger; } diff --git a/src/xrpld/app/ledger/Ledger.h b/src/xrpld/app/ledger/Ledger.h index cc3bc43c50..0e849389fd 100644 --- a/src/xrpld/app/ledger/Ledger.h +++ b/src/xrpld/app/ledger/Ledger.h @@ -130,15 +130,15 @@ public: } LedgerHeader const& - info() const override + header() const override { - return info_; + return header_; } void setLedgerInfo(LedgerHeader const& info) { - info_ = info; + header_ = info; } Fees const& @@ -213,7 +213,7 @@ public: void rawDestroyXRP(XRPAmount const& fee) override { - info_.drops -= fee; + header_.drops -= fee; } // @@ -244,7 +244,7 @@ public: void setValidated() const { - info_.validated = true; + header_.validated = true; } void @@ -276,15 +276,15 @@ public: setFull() const { txMap_.setFull(); - txMap_.setLedgerSeq(info_.seq); + txMap_.setLedgerSeq(header_.seq); stateMap_.setFull(); - stateMap_.setLedgerSeq(info_.seq); + stateMap_.setLedgerSeq(header_.seq); } void setTotalDrops(std::uint64_t totDrops) { - info_.drops = totDrops; + header_.drops = totDrops; } SHAMap const& @@ -397,7 +397,7 @@ private: Fees fees_; Rules rules_; - LedgerHeader info_; + LedgerHeader header_; beast::Journal j_; }; diff --git a/src/xrpld/app/ledger/LedgerHistory.cpp b/src/xrpld/app/ledger/LedgerHistory.cpp index 4f2660c70a..c084297641 100644 --- a/src/xrpld/app/ledger/LedgerHistory.cpp +++ b/src/xrpld/app/ledger/LedgerHistory.cpp @@ -47,9 +47,9 @@ LedgerHistory::insert( std::unique_lock sl(m_ledgers_by_hash.peekMutex()); bool const alreadyHad = m_ledgers_by_hash.canonicalize_replace_cache( - ledger->info().hash, ledger); + ledger->header().hash, ledger); if (validated) - mLedgersByIndex[ledger->info().seq] = ledger->info().hash; + mLedgersByIndex[ledger->header().seq] = ledger->header().hash; return alreadyHad; } @@ -84,7 +84,7 @@ LedgerHistory::getLedgerBySeq(LedgerIndex index) return ret; XRPL_ASSERT( - ret->info().seq == index, + ret->header().seq == index, "ripple::LedgerHistory::getLedgerBySeq : result sequence match"); { @@ -94,9 +94,9 @@ LedgerHistory::getLedgerBySeq(LedgerIndex index) XRPL_ASSERT( ret->isImmutable(), "ripple::LedgerHistory::getLedgerBySeq : immutable result ledger"); - m_ledgers_by_hash.canonicalize_replace_client(ret->info().hash, ret); - mLedgersByIndex[ret->info().seq] = ret->info().hash; - return (ret->info().seq == index) ? ret : nullptr; + m_ledgers_by_hash.canonicalize_replace_client(ret->header().hash, ret); + mLedgersByIndex[ret->header().seq] = ret->header().hash; + return (ret->header().seq == index) ? ret : nullptr; } } @@ -112,7 +112,7 @@ LedgerHistory::getLedgerByHash(LedgerHash const& hash) "ripple::LedgerHistory::getLedgerByHash : immutable fetched " "ledger"); XRPL_ASSERT( - ret->info().hash == hash, + ret->header().hash == hash, "ripple::LedgerHistory::getLedgerByHash : fetched ledger hash " "match"); return ret; @@ -127,11 +127,11 @@ LedgerHistory::getLedgerByHash(LedgerHash const& hash) ret->isImmutable(), "ripple::LedgerHistory::getLedgerByHash : immutable loaded ledger"); XRPL_ASSERT( - ret->info().hash == hash, + ret->header().hash == hash, "ripple::LedgerHistory::getLedgerByHash : loaded ledger hash match"); - m_ledgers_by_hash.canonicalize_replace_client(ret->info().hash, ret); + m_ledgers_by_hash.canonicalize_replace_client(ret->header().hash, ret); XRPL_ASSERT( - ret->info().hash == hash, + ret->header().hash == hash, "ripple::LedgerHistory::getLedgerByHash : result hash match"); return ret; @@ -342,7 +342,7 @@ LedgerHistory::handleMismatch( } XRPL_ASSERT( - builtLedger->info().seq == validLedger->info().seq, + builtLedger->header().seq == validLedger->header().seq, "ripple::LedgerHistory::handleMismatch : sequence match"); if (auto stream = j_.debug()) @@ -356,14 +356,14 @@ LedgerHistory::handleMismatch( // failure from transaction processing difference // Disagreement over prior ledger indicates sync issue - if (builtLedger->info().parentHash != validLedger->info().parentHash) + if (builtLedger->header().parentHash != validLedger->header().parentHash) { JLOG(j_.error()) << "MISMATCH on prior ledger"; return; } // Disagreement over close time indicates Byzantine failure - if (builtLedger->info().closeTime != validLedger->info().closeTime) + if (builtLedger->header().closeTime != validLedger->header().closeTime) { JLOG(j_.error()) << "MISMATCH on close time"; return; @@ -434,8 +434,8 @@ LedgerHistory::builtLedger( uint256 const& consensusHash, Json::Value consensus) { - LedgerIndex index = ledger->info().seq; - LedgerHash hash = ledger->info().hash; + LedgerIndex index = ledger->header().seq; + LedgerHash hash = ledger->header().hash; XRPL_ASSERT( !hash.isZero(), "ripple::LedgerHistory::builtLedger : nonzero hash"); @@ -475,8 +475,8 @@ LedgerHistory::validatedLedger( std::shared_ptr const& ledger, std::optional const& consensusHash) { - LedgerIndex index = ledger->info().seq; - LedgerHash hash = ledger->info().hash; + LedgerIndex index = ledger->header().seq; + LedgerHash hash = ledger->header().hash; XRPL_ASSERT( !hash.isZero(), "ripple::LedgerHistory::validatedLedger : nonzero hash"); @@ -533,7 +533,7 @@ LedgerHistory::clearLedgerCachePrior(LedgerIndex seq) for (LedgerHash it : m_ledgers_by_hash.getKeys()) { auto const ledger = getLedgerByHash(it); - if (!ledger || ledger->info().seq < seq) + if (!ledger || ledger->header().seq < seq) m_ledgers_by_hash.del(it, false); } } diff --git a/src/xrpld/app/ledger/detail/BuildLedger.cpp b/src/xrpld/app/ledger/detail/BuildLedger.cpp index dd3593e1cf..d7153c0fe9 100644 --- a/src/xrpld/app/ledger/detail/BuildLedger.cpp +++ b/src/xrpld/app/ledger/detail/BuildLedger.cpp @@ -58,7 +58,7 @@ buildLedgerImpl( // Accept ledger XRPL_ASSERT( - built->info().seq < XRP_LEDGER_EARLIEST_FEES || + built->header().seq < XRP_LEDGER_EARLIEST_FEES || built->read(keylet::fees()), "ripple::buildLedgerImpl : valid ledger fees"); built->setAccepted(closeTime, closeResolution, closeTimeCorrect); @@ -213,13 +213,13 @@ buildLedger( { auto const& replayLedger = replayData.replay(); - JLOG(j.debug()) << "Report: Replay Ledger " << replayLedger->info().hash; + JLOG(j.debug()) << "Report: Replay Ledger " << replayLedger->header().hash; return buildLedgerImpl( replayData.parent(), - replayLedger->info().closeTime, - ((replayLedger->info().closeFlags & sLCF_NoConsensusTime) == 0), - replayLedger->info().closeTimeResolution, + replayLedger->header().closeTime, + ((replayLedger->header().closeFlags & sLCF_NoConsensusTime) == 0), + replayLedger->header().closeTimeResolution, app, j, [&](OpenView& accum, std::shared_ptr const& built) { diff --git a/src/xrpld/app/ledger/detail/InboundLedger.cpp b/src/xrpld/app/ledger/detail/InboundLedger.cpp index 5bfa9144d3..24de3cce14 100644 --- a/src/xrpld/app/ledger/detail/InboundLedger.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedger.cpp @@ -102,7 +102,7 @@ InboundLedger::init(ScopedLockType& collectionLock) JLOG(journal_.debug()) << "Acquiring ledger we already have in " << " local store. " << hash_; XRPL_ASSERT( - mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || + mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), "ripple::InboundLedger::init : valid ledger fees"); mLedger->setImmutable(); @@ -206,14 +206,15 @@ neededHashes( std::vector InboundLedger::neededTxHashes(int max, SHAMapSyncFilter* filter) const { - return neededHashes(mLedger->info().txHash, mLedger->txMap(), max, filter); + return neededHashes( + mLedger->header().txHash, mLedger->txMap(), max, filter); } std::vector InboundLedger::neededStateHashes(int max, SHAMapSyncFilter* filter) const { return neededHashes( - mLedger->info().accountHash, mLedger->stateMap(), max, filter); + mLedger->header().accountHash, mLedger->stateMap(), max, filter); } // See how much of the ledger data is stored locally @@ -229,8 +230,8 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) deserializePrefixedHeader(makeSlice(data)), app_.config(), app_.getNodeFamily()); - if (mLedger->info().hash != hash_ || - (mSeq != 0 && mSeq != mLedger->info().seq)) + if (mLedger->header().hash != hash_ || + (mSeq != 0 && mSeq != mLedger->header().seq)) { // We know for a fact the ledger can never be acquired JLOG(journal_.warn()) @@ -256,7 +257,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) { Blob blob{nodeObject->getData()}; dstDB.store( - hotLEDGER, std::move(blob), hash_, mLedger->info().seq); + hotLEDGER, std::move(blob), hash_, mLedger->header().seq); } } else @@ -274,11 +275,11 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) // Store the ledger header in the ledger's database mLedger->stateMap().family().db().store( - hotLEDGER, std::move(*data), hash_, mLedger->info().seq); + hotLEDGER, std::move(*data), hash_, mLedger->header().seq); } if (mSeq == 0) - mSeq = mLedger->info().seq; + mSeq = mLedger->header().seq; mLedger->stateMap().setLedgerSeq(mSeq); mLedger->txMap().setLedgerSeq(mSeq); mHaveHeader = true; @@ -286,7 +287,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) if (!mHaveTransactions) { - if (mLedger->info().txHash.isZero()) + if (mLedger->header().txHash.isZero()) { JLOG(journal_.trace()) << "No TXNs to fetch"; mHaveTransactions = true; @@ -296,7 +297,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) TransactionStateSF filter( mLedger->txMap().family().db(), app_.getLedgerMaster()); if (mLedger->txMap().fetchRoot( - SHAMapHash{mLedger->info().txHash}, &filter)) + SHAMapHash{mLedger->header().txHash}, &filter)) { if (neededTxHashes(1, &filter).empty()) { @@ -309,7 +310,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) if (!mHaveState) { - if (mLedger->info().accountHash.isZero()) + if (mLedger->header().accountHash.isZero()) { JLOG(journal_.fatal()) << "We are acquiring a ledger with a zero account hash"; @@ -319,7 +320,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) AccountStateSF filter( mLedger->stateMap().family().db(), app_.getLedgerMaster()); if (mLedger->stateMap().fetchRoot( - SHAMapHash{mLedger->info().accountHash}, &filter)) + SHAMapHash{mLedger->header().accountHash}, &filter)) { if (neededStateHashes(1, &filter).empty()) { @@ -334,7 +335,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) JLOG(journal_.debug()) << "Had everything locally"; complete_ = true; XRPL_ASSERT( - mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || + mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), "ripple::InboundLedger::tryDB : valid ledger fees"); mLedger->setImmutable(); @@ -437,7 +438,7 @@ InboundLedger::done() if (complete_ && !failed_ && mLedger) { XRPL_ASSERT( - mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || + mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), "ripple::InboundLedger::done : valid ledger fees"); mLedger->setImmutable(); @@ -582,7 +583,7 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) } if (mLedger) - tmGL.set_ledgerseq(mLedger->info().seq); + tmGL.set_ledgerseq(mLedger->header().seq); if (reason != TriggerReason::reply) { @@ -744,7 +745,7 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) { JLOG(journal_.debug()) << "Done:" << (complete_ ? " complete" : "") - << (failed_ ? " failed " : " ") << mLedger->info().seq; + << (failed_ ? " failed " : " ") << mLedger->header().seq; sl.unlock(); done(); } @@ -808,17 +809,17 @@ InboundLedger::takeHeader(std::string const& data) auto* f = &app_.getNodeFamily(); mLedger = std::make_shared( deserializeHeader(makeSlice(data)), app_.config(), *f); - if (mLedger->info().hash != hash_ || - (mSeq != 0 && mSeq != mLedger->info().seq)) + if (mLedger->header().hash != hash_ || + (mSeq != 0 && mSeq != mLedger->header().seq)) { JLOG(journal_.warn()) - << "Acquire hash mismatch: " << mLedger->info().hash + << "Acquire hash mismatch: " << mLedger->header().hash << "!=" << hash_; mLedger.reset(); return false; } if (mSeq == 0) - mSeq = mLedger->info().seq; + mSeq = mLedger->header().seq; mLedger->stateMap().setLedgerSeq(mSeq); mLedger->txMap().setLedgerSeq(mSeq); mHaveHeader = true; @@ -828,10 +829,10 @@ InboundLedger::takeHeader(std::string const& data) s.addRaw(data.data(), data.size()); f->db().store(hotLEDGER, std::move(s.modData()), hash_, mSeq); - if (mLedger->info().txHash.isZero()) + if (mLedger->header().txHash.isZero()) mHaveTransactions = true; - if (mLedger->info().accountHash.isZero()) + if (mLedger->header().accountHash.isZero()) mHaveState = true; mLedger->txMap().setSynching(); @@ -871,12 +872,12 @@ InboundLedger::receiveNode(protocol::TMLedgerData& packet, SHAMapAddNode& san) if (packet.type() == protocol::liTX_NODE) return { mLedger->txMap(), - SHAMapHash{mLedger->info().txHash}, + SHAMapHash{mLedger->header().txHash}, std::make_unique( mLedger->txMap().family().db(), app_.getLedgerMaster())}; return { mLedger->stateMap(), - SHAMapHash{mLedger->info().accountHash}, + SHAMapHash{mLedger->header().accountHash}, std::make_unique( mLedger->stateMap().family().db(), app_.getLedgerMaster())}; }(); @@ -953,7 +954,7 @@ InboundLedger::takeAsRootNode(Slice const& data, SHAMapAddNode& san) AccountStateSF filter( mLedger->stateMap().family().db(), app_.getLedgerMaster()); san += mLedger->stateMap().addRootNode( - SHAMapHash{mLedger->info().accountHash}, data, &filter); + SHAMapHash{mLedger->header().accountHash}, data, &filter); return san.isGood(); } @@ -980,7 +981,7 @@ InboundLedger::takeTxRootNode(Slice const& data, SHAMapAddNode& san) TransactionStateSF filter( mLedger->txMap().family().db(), app_.getLedgerMaster()); san += mLedger->txMap().addRootNode( - SHAMapHash{mLedger->info().txHash}, data, &filter); + SHAMapHash{mLedger->header().txHash}, data, &filter); return san.isGood(); } diff --git a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp index 5de811fc39..639d8250ac 100644 --- a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp +++ b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp @@ -233,10 +233,10 @@ private: catch (SHAMapMissingNode const& mn) { JLOG(j_.warn()) - << "Ledger #" << ledger->info().seq << ": " << mn.what(); + << "Ledger #" << ledger->header().seq << ": " << mn.what(); app_.getInboundLedgers().acquire( - ledger->info().hash, - ledger->info().seq, + ledger->header().hash, + ledger->header().seq, InboundLedger::Reason::GENERIC); } return hash ? *hash : beast::zero; // kludge @@ -268,8 +268,8 @@ private: } auto dbLedger = loadByIndex(ledgerIndex, app_); - if (!dbLedger || (dbLedger->info().hash != ledgerHash) || - (dbLedger->info().parentHash != nodeLedger->info().parentHash)) + if (!dbLedger || (dbLedger->header().hash != ledgerHash) || + (dbLedger->header().parentHash != nodeLedger->header().parentHash)) { // Ideally we'd also check for more than one ledger with that index JLOG(j_.debug()) @@ -314,7 +314,7 @@ private: { LedgerHash ledgerHash; - if (!referenceLedger || (referenceLedger->info().seq < ledgerIndex)) + if (!referenceLedger || (referenceLedger->header().seq < ledgerIndex)) { referenceLedger = app_.getLedgerMaster().getValidatedLedger(); if (!referenceLedger) @@ -324,7 +324,7 @@ private: } } - if (referenceLedger->info().seq >= ledgerIndex) + if (referenceLedger->header().seq >= ledgerIndex) { // See if the hash for the ledger we need is in the reference ledger ledgerHash = getLedgerHash(referenceLedger, ledgerIndex); diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp index 91b1dca5e2..c803c0bdd4 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp @@ -184,12 +184,12 @@ LedgerDeltaAcquire::tryBuild(std::shared_ptr const& parent) parent->seq() + 1 == replayTemp_->seq(), "ripple::LedgerDeltaAcquire::tryBuild : parent sequence match"); XRPL_ASSERT( - parent->info().hash == replayTemp_->info().parentHash, + parent->header().hash == replayTemp_->header().parentHash, "ripple::LedgerDeltaAcquire::tryBuild : parent hash match"); // build ledger LedgerReplay replayData(parent, replayTemp_, std::move(orderedTxns_)); fullLedger_ = buildLedger(replayData, tapNONE, app_, journal_); - if (fullLedger_ && fullLedger_->info().hash == hash_) + if (fullLedger_ && fullLedger_->header().hash == hash_) { JLOG(journal_.info()) << "Built " << hash_; onLedgerBuilt(sl); @@ -200,7 +200,7 @@ LedgerDeltaAcquire::tryBuild(std::shared_ptr const& parent) failed_ = true; complete_ = false; JLOG(journal_.error()) << "tryBuild failed " << hash_ << " with parent " - << parent->info().hash; + << parent->header().hash; Throw("Cannot replay ledger"); } } diff --git a/src/xrpld/app/ledger/detail/LedgerMaster.cpp b/src/xrpld/app/ledger/detail/LedgerMaster.cpp index 0c3b3266d9..3e75a28abd 100644 --- a/src/xrpld/app/ledger/detail/LedgerMaster.cpp +++ b/src/xrpld/app/ledger/detail/LedgerMaster.cpp @@ -103,7 +103,7 @@ LedgerMaster::LedgerMaster( LedgerIndex LedgerMaster::getCurrentLedgerIndex() { - return app_.openLedger().current()->info().seq; + return app_.openLedger().current()->header().seq; } LedgerIndex @@ -227,7 +227,7 @@ LedgerMaster::setValidLedger(std::shared_ptr const& l) { auto validations = app_.validators().negativeUNLFilter( app_.getValidations().getTrustedForLedger( - l->info().hash, l->info().seq)); + l->header().hash, l->header().seq)); times.reserve(validations.size()); for (auto const& val : validations) times.push_back(val->getSignTime()); @@ -248,18 +248,18 @@ LedgerMaster::setValidLedger(std::shared_ptr const& l) } else { - signTime = l->info().closeTime; + signTime = l->header().closeTime; } mValidLedger.set(l); mValidLedgerSign = signTime.time_since_epoch().count(); XRPL_ASSERT( mValidLedgerSeq || !app_.getMaxDisallowedLedger() || - l->info().seq + max_ledger_difference_ > + l->header().seq + max_ledger_difference_ > app_.getMaxDisallowedLedger(), "ripple::LedgerMaster::setValidLedger : valid ledger sequence"); (void)max_ledger_difference_; - mValidLedgerSeq = l->info().seq; + mValidLedgerSeq = l->header().seq; app_.getOPs().updateLocalTx(*l); app_.getSHAMapStore().onLedgerClosed(getValidatedLedger()); @@ -304,8 +304,8 @@ void LedgerMaster::setPubLedger(std::shared_ptr const& l) { mPubLedger = l; - mPubLedgerClose = l->info().closeTime.time_since_epoch().count(); - mPubLedgerSeq = l->info().seq; + mPubLedgerClose = l->header().closeTime.time_since_epoch().count(); + mPubLedgerSeq = l->header().seq; } void @@ -328,11 +328,11 @@ LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) // last validated ledger auto validLedger = getValidatedLedger(); - if (validLedger && (ledger->info().seq < validLedger->info().seq)) + if (validLedger && (ledger->header().seq < validLedger->header().seq)) { JLOG(m_journal.trace()) - << "Candidate for current ledger has low seq " << ledger->info().seq - << " < " << validLedger->info().seq; + << "Candidate for current ledger has low seq " + << ledger->header().seq << " < " << validLedger->header().seq; return false; } @@ -342,17 +342,17 @@ LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) // few ledgers as our clock can be off when we first start up auto closeTime = app_.timeKeeper().closeTime(); - auto ledgerClose = ledger->info().parentCloseTime; + auto ledgerClose = ledger->header().parentCloseTime; using namespace std::chrono_literals; - if ((validLedger || (ledger->info().seq > 10)) && + if ((validLedger || (ledger->header().seq > 10)) && ((std::max(closeTime, ledgerClose) - std::min(closeTime, ledgerClose)) > 5min)) { JLOG(m_journal.warn()) << "Candidate for current ledger has close time " << to_string(ledgerClose) << " at network time " - << to_string(closeTime) << " seq " << ledger->info().seq; + << to_string(closeTime) << " seq " << ledger->header().seq; return false; } @@ -363,25 +363,25 @@ LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) // every two seconds. The goal is to prevent a malicious ledger // from increasing our sequence unreasonably high - LedgerIndex maxSeq = validLedger->info().seq + 10; + LedgerIndex maxSeq = validLedger->header().seq + 10; - if (closeTime > validLedger->info().parentCloseTime) + if (closeTime > validLedger->header().parentCloseTime) maxSeq += std::chrono::duration_cast( - closeTime - validLedger->info().parentCloseTime) + closeTime - validLedger->header().parentCloseTime) .count() / 2; - if (ledger->info().seq > maxSeq) + if (ledger->header().seq > maxSeq) { JLOG(m_journal.warn()) << "Candidate for current ledger has high seq " - << ledger->info().seq << " > " << maxSeq; + << ledger->header().seq << " > " << maxSeq; return false; } JLOG(m_journal.trace()) - << "Acceptable seq range: " << validLedger->info().seq - << " <= " << ledger->info().seq << " <= " << maxSeq; + << "Acceptable seq range: " << validLedger->header().seq + << " <= " << ledger->header().seq << " <= " << maxSeq; } return true; @@ -422,7 +422,7 @@ LedgerMaster::fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash) bool LedgerMaster::storeLedger(std::shared_ptr ledger) { - bool validated = ledger->info().validated; + bool validated = ledger->header().validated; // Returns true if we already had the ledger return mLedgerHistory.insert(std::move(ledger), validated); } @@ -439,7 +439,7 @@ LedgerMaster::applyHeldTransactions() std::lock_guard sl(m_mutex); // VFALCO NOTE The hash for an open ledger is undefined so we use // something that is a reasonable substitute. - CanonicalTXSet set(app_.openLedger().current()->info().parentHash); + CanonicalTXSet set(app_.openLedger().current()->header().parentHash); std::swap(mHeldTransactions, set); return set; }(); @@ -482,10 +482,10 @@ LedgerMaster::isValidated(ReadView const& ledger) if (ledger.open()) return false; - if (ledger.info().validated) + if (ledger.header().validated) return true; - auto const seq = ledger.info().seq; + auto const seq = ledger.header().seq; try { // Use the skip list in the last validated ledger to see if ledger @@ -493,7 +493,7 @@ LedgerMaster::isValidated(ReadView const& ledger) // validated). auto const hash = walkHashBySeq(seq, InboundLedger::Reason::GENERIC); - if (!hash || ledger.info().hash != *hash) + if (!hash || ledger.header().hash != *hash) { // This ledger's hash is not the hash of the validated ledger if (hash) @@ -503,7 +503,7 @@ LedgerMaster::isValidated(ReadView const& ledger) "ripple::LedgerMaster::isValidated : nonzero hash"); uint256 valHash = app_.getRelationalDatabase().getHashByIndex(seq); - if (valHash == ledger.info().hash) + if (valHash == ledger.header().hash) { // SQL database doesn't match ledger chain clearLedger(seq); @@ -519,7 +519,7 @@ LedgerMaster::isValidated(ReadView const& ledger) } // Mark ledger as validated to save time if we see it again. - ledger.info().validated = true; + ledger.header().validated = true; return true; } @@ -597,7 +597,7 @@ LedgerMaster::getEarliestFetch() { // The earliest ledger we will let people fetch is ledger zero, // unless that creates a larger range than allowed - std::uint32_t e = getClosedLedger()->info().seq; + std::uint32_t e = getClosedLedger()->header().seq; if (e > fetch_depth_) e -= fetch_depth_; @@ -609,8 +609,8 @@ LedgerMaster::getEarliestFetch() void LedgerMaster::tryFill(std::shared_ptr ledger) { - std::uint32_t seq = ledger->info().seq; - uint256 prevHash = ledger->info().parentHash; + std::uint32_t seq = ledger->header().seq; + uint256 prevHash = ledger->header().parentHash; std::map ledgerHashes; @@ -732,7 +732,7 @@ LedgerMaster::fixMismatch(ReadView const& ledger) int invalidate = 0; std::optional hash; - for (std::uint32_t lSeq = ledger.info().seq - 1; lSeq > 0; --lSeq) + for (std::uint32_t lSeq = ledger.header().seq - 1; lSeq > 0; --lSeq) { if (haveLedger(lSeq)) { @@ -754,7 +754,7 @@ LedgerMaster::fixMismatch(ReadView const& ledger) // try to close the seam auto otherLedger = getLedgerBySeq(lSeq); - if (otherLedger && (otherLedger->info().hash == *hash)) + if (otherLedger && (otherLedger->header().hash == *hash)) { // we closed the seam if (invalidate != 0) @@ -788,8 +788,8 @@ LedgerMaster::setFullLedger( bool isCurrent) { // A new ledger has been accepted as part of the trusted chain - JLOG(m_journal.debug()) << "Ledger " << ledger->info().seq - << " accepted :" << ledger->info().hash; + JLOG(m_journal.debug()) << "Ledger " << ledger->header().seq + << " accepted :" << ledger->header().hash; XRPL_ASSERT( ledger->stateMap().getHash().isNonZero(), "ripple::LedgerMaster::setFullLedger : nonzero ledger state hash"); @@ -803,23 +803,23 @@ LedgerMaster::setFullLedger( { // Check the SQL database's entry for the sequence before this // ledger, if it's not this ledger's parent, invalidate it - uint256 prevHash = - app_.getRelationalDatabase().getHashByIndex(ledger->info().seq - 1); - if (prevHash.isNonZero() && prevHash != ledger->info().parentHash) - clearLedger(ledger->info().seq - 1); + uint256 prevHash = app_.getRelationalDatabase().getHashByIndex( + ledger->header().seq - 1); + if (prevHash.isNonZero() && prevHash != ledger->header().parentHash) + clearLedger(ledger->header().seq - 1); } pendSaveValidated(app_, ledger, isSynchronous, isCurrent); { std::lock_guard ml(mCompleteLock); - mCompleteLedgers.insert(ledger->info().seq); + mCompleteLedgers.insert(ledger->header().seq); } { std::lock_guard ml(m_mutex); - if (ledger->info().seq > mValidLedgerSeq) + if (ledger->header().seq > mValidLedgerSeq) setValidLedger(ledger); if (!mPubLedger) { @@ -827,13 +827,13 @@ LedgerMaster::setFullLedger( app_.getOrderBookDB().setup(ledger); } - if (ledger->info().seq != 0 && haveLedger(ledger->info().seq - 1)) + if (ledger->header().seq != 0 && haveLedger(ledger->header().seq - 1)) { // we think we have the previous ledger, double check - auto prevLedger = getLedgerBySeq(ledger->info().seq - 1); + auto prevLedger = getLedgerBySeq(ledger->header().seq - 1); if (!prevLedger || - (prevLedger->info().hash != ledger->info().parentHash)) + (prevLedger->header().hash != ledger->header().parentHash)) { JLOG(m_journal.warn()) << "Acquired ledger invalidates previous ledger: " @@ -926,23 +926,23 @@ LedgerMaster::checkAccept(std::shared_ptr const& ledger) // publish? std::lock_guard ml(m_mutex); - if (ledger->info().seq <= mValidLedgerSeq) + if (ledger->header().seq <= mValidLedgerSeq) return; auto const minVal = getNeededValidations(); auto validations = app_.validators().negativeUNLFilter( app_.getValidations().getTrustedForLedger( - ledger->info().hash, ledger->info().seq)); + ledger->header().hash, ledger->header().seq)); auto const tvc = validations.size(); if (tvc < minVal) // nothing we can do { JLOG(m_journal.trace()) - << "Only " << tvc << " validations for " << ledger->info().hash; + << "Only " << tvc << " validations for " << ledger->header().hash; return; } JLOG(m_journal.info()) << "Advancing accepted ledger to " - << ledger->info().seq << " with >= " << minVal + << ledger->header().seq << " with >= " << minVal << " validations"; ledger->setValidated(); @@ -956,10 +956,10 @@ LedgerMaster::checkAccept(std::shared_ptr const& ledger) } std::uint32_t const base = app_.getFeeTrack().getLoadBase(); - auto fees = app_.getValidations().fees(ledger->info().hash, base); + auto fees = app_.getValidations().fees(ledger->header().hash, base); { auto fees2 = - app_.getValidations().fees(ledger->info().parentHash, base); + app_.getValidations().fees(ledger->header().parentHash, base); fees.reserve(fees.size() + fees2.size()); std::copy(fees2.begin(), fees2.end(), std::back_inserter(fees)); } @@ -1007,7 +1007,7 @@ LedgerMaster::checkAccept(std::shared_ptr const& ledger) { // Have not printed the warning before, check if need to print. auto const vals = app_.getValidations().getTrustedForLedger( - ledger->info().parentHash, ledger->info().seq - 1); + ledger->header().parentHash, ledger->header().seq - 1); std::size_t higherVersionCount = 0; std::size_t rippledCount = 0; for (auto const& v : vals) @@ -1077,10 +1077,10 @@ LedgerMaster::consensusBuilt( mLedgerHistory.builtLedger(ledger, consensusHash, std::move(consensus)); - if (ledger->info().seq <= mValidLedgerSeq) + if (ledger->header().seq <= mValidLedgerSeq) { auto stream = app_.journal("LedgerConsensus").info(); - JLOG(stream) << "Consensus built old ledger: " << ledger->info().seq + JLOG(stream) << "Consensus built old ledger: " << ledger->header().seq << " <= " << mValidLedgerSeq; return; } @@ -1088,7 +1088,7 @@ LedgerMaster::consensusBuilt( // See if this ledger can be the new fully-validated ledger checkAccept(ledger); - if (ledger->info().seq <= mValidLedgerSeq) + if (ledger->header().seq <= mValidLedgerSeq) { auto stream = app_.journal("LedgerConsensus").debug(); JLOG(stream) << "Consensus ledger fully validated"; @@ -1134,7 +1134,7 @@ LedgerMaster::consensusBuilt( auto const neededValidations = getNeededValidations(); auto maxSeq = mValidLedgerSeq.load(); - auto maxLedger = ledger->info().hash; + auto maxLedger = ledger->header().hash; // Of the ledgers with sufficient validations, // find the one with the highest sequence @@ -1145,7 +1145,7 @@ LedgerMaster::consensusBuilt( if (v.second.ledgerSeq_ == 0) { if (auto l = getLedgerByHash(v.first)) - v.second.ledgerSeq_ = l->info().seq; + v.second.ledgerSeq_ = l->header().seq; } if (v.second.ledgerSeq_ > maxSeq) @@ -1172,7 +1172,7 @@ LedgerMaster::getLedgerHashForHistory( std::optional ret; auto const& l{mHistLedger}; - if (l && l->info().seq >= index) + if (l && l->header().seq >= index) { ret = hashOfSeq(*l, index, m_journal); if (!ret) @@ -1230,7 +1230,7 @@ LedgerMaster::findNewLedgersToPublish( auto pubSeq = mPubLedgerSeq + 1; // Next sequence to publish auto valLedger = mValidLedger.get(); - std::uint32_t valSeq = valLedger->info().seq; + std::uint32_t valSeq = valLedger->header().seq; scope_unlock sul{sl}; try @@ -1276,7 +1276,7 @@ LedgerMaster::findNewLedgersToPublish( } // Did we acquire the next ledger we need to publish? - if (ledger && (ledger->info().seq == pubSeq)) + if (ledger && (ledger->header().seq == pubSeq)) { ledger->setValidated(); ret.push_back(ledger); @@ -1307,7 +1307,7 @@ LedgerMaster::findNewLedgersToPublish( while (startLedger->seq() + 1 < finishLedger->seq()) { if (auto const parent = mLedgerHistory.getLedgerByHash( - finishLedger->info().parentHash); + finishLedger->header().parentHash); parent) { finishLedger = parent; @@ -1318,13 +1318,13 @@ LedgerMaster::findNewLedgersToPublish( finishLedger->seq() - startLedger->seq() + 1; JLOG(m_journal.debug()) << "Publish LedgerReplays " << numberLedgers - << " ledgers, from seq=" << startLedger->info().seq << ", " - << startLedger->info().hash - << " to seq=" << finishLedger->info().seq << ", " - << finishLedger->info().hash; + << " ledgers, from seq=" << startLedger->header().seq + << ", " << startLedger->header().hash + << " to seq=" << finishLedger->header().seq << ", " + << finishLedger->header().hash; app_.getLedgerReplayer().replay( InboundLedger::Reason::GENERIC, - finishLedger->info().hash, + finishLedger->header().hash, numberLedgers); break; } @@ -1390,7 +1390,8 @@ LedgerMaster::updatePaths() std::lock_guard ml(m_mutex); if (!mValidLedger.empty() && - (!mPathLedger || (mPathLedger->info().seq != mValidLedgerSeq))) + (!mPathLedger || + (mPathLedger->header().seq != mValidLedgerSeq))) { // We have a new valid ledger since the last full pathfinding mPathLedger = mValidLedger.get(); lastLedger = mPathLedger; @@ -1412,7 +1413,7 @@ LedgerMaster::updatePaths() { // don't pathfind with a ledger that's more than 60 seconds old using namespace std::chrono; auto age = time_point_cast(app_.timeKeeper().closeTime()) - - lastLedger->info().closeTime; + lastLedger->header().closeTime; if (age > 1min) { JLOG(m_journal.debug()) @@ -1461,16 +1462,16 @@ LedgerMaster::updatePaths() { // our parent is the problem app_.getInboundLedgers().acquire( - lastLedger->info().parentHash, - lastLedger->info().seq - 1, + lastLedger->header().parentHash, + lastLedger->header().seq - 1, InboundLedger::Reason::GENERIC); } else { // this ledger is the problem app_.getInboundLedgers().acquire( - lastLedger->info().hash, - lastLedger->info().seq, + lastLedger->header().hash, + lastLedger->header().seq, InboundLedger::Reason::GENERIC); } } @@ -1635,7 +1636,7 @@ LedgerMaster::walkHashBySeq( std::shared_ptr const& referenceLedger, InboundLedger::Reason reason) { - if (!referenceLedger || (referenceLedger->info().seq < index)) + if (!referenceLedger || (referenceLedger->header().seq < index)) { // Nothing we can do. No validated ledger. return std::nullopt; @@ -1693,7 +1694,7 @@ LedgerMaster::getLedgerBySeq(std::uint32_t index) // Always prefer a validated ledger if (auto valid = mValidLedger.get()) { - if (valid->info().seq == index) + if (valid->header().seq == index) return valid; try @@ -1714,7 +1715,7 @@ LedgerMaster::getLedgerBySeq(std::uint32_t index) return ret; auto ret = mClosedLedger.get(); - if (ret && (ret->info().seq == index)) + if (ret && (ret->header().seq == index)) return ret; clearLedger(index); @@ -1728,7 +1729,7 @@ LedgerMaster::getLedgerByHash(uint256 const& hash) return ret; auto ret = mClosedLedger.get(); - if (ret && (ret->info().hash == hash)) + if (ret && (ret->header().hash == hash)) return ret; return {}; @@ -1818,7 +1819,7 @@ LedgerMaster::fetchForHistory( } if (ledger) { - auto seq = ledger->info().seq; + auto seq = ledger->header().seq; XRPL_ASSERT( seq == missing, "ripple::LedgerMaster::fetchForHistory : sequence match"); @@ -1832,7 +1833,7 @@ LedgerMaster::fetchForHistory( } if (fillInProgress == 0 && app_.getRelationalDatabase().getHashByIndex(seq - 1) == - ledger->info().parentHash) + ledger->header().parentHash) { { // Previous ledger is in DB @@ -1919,7 +1920,7 @@ LedgerMaster::doAdvance(std::unique_lock& sl) std::lock_guard sll(mCompleteLock); missing = prevMissing( mCompleteLedgers, - mPubLedger->info().seq, + mPubLedger->header().seq, app_.getNodeStore().earliestLedgerSeq()); } if (missing) @@ -1966,7 +1967,7 @@ LedgerMaster::doAdvance(std::unique_lock& sl) { scope_unlock sul{sl}; JLOG(m_journal.debug()) - << "tryAdvance publishing seq " << ledger->info().seq; + << "tryAdvance publishing seq " << ledger->header().seq; setFullLedger(ledger, true, true); } @@ -2118,14 +2119,14 @@ LedgerMaster::makeFetchPack( return; } - if (have->info().seq < getEarliestFetch()) + if (have->header().seq < getEarliestFetch()) { JLOG(m_journal.debug()) << "Peer requests fetch pack that is too early"; peer->charge(Resource::feeMalformedRequest, "get_object ledger early"); return; } - auto want = getLedgerByHash(have->info().parentHash); + auto want = getLedgerByHash(have->header().parentHash); if (!want) { @@ -2160,19 +2161,19 @@ LedgerMaster::makeFetchPack( // the same process adding the previous ledger to the FetchPack. do { - std::uint32_t lSeq = want->info().seq; + std::uint32_t lSeq = want->header().seq; { // Serialize the ledger header: hdr.erase(); hdr.add32(HashPrefix::ledgerMaster); - addRaw(want->info(), hdr); + addRaw(want->header(), hdr); // Add the data protocol::TMIndexedObject* obj = reply.add_objects(); obj->set_hash( - want->info().hash.data(), want->info().hash.size()); + want->header().hash.data(), want->header().hash.size()); obj->set_data(hdr.getDataPtr(), hdr.getLength()); obj->set_ledgerseq(lSeq); } @@ -2182,14 +2183,14 @@ LedgerMaster::makeFetchPack( // We use nullptr here because transaction maps are per ledger // and so the requestor is unlikely to already have it. - if (want->info().txHash.isNonZero()) + if (want->header().txHash.isNonZero()) populateFetchPack(want->txMap(), nullptr, 512, &reply, lSeq); if (reply.objects().size() >= 512) break; have = std::move(want); - want = getLedgerByHash(have->info().parentHash); + want = getLedgerByHash(have->header().parentHash); } while (want && UptimeClock::now() <= uptime + 1s); auto msg = std::make_shared(reply, protocol::mtGET_OBJECTS); diff --git a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp index da7f7db23d..0a070fdeb0 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp @@ -72,7 +72,7 @@ LedgerReplayMsgHandler::processProofPathRequest( // pack header Serializer nData(128); - addRaw(ledger->info(), nData); + addRaw(ledger->header(), nData); reply.set_ledgerheader(nData.getDataPtr(), nData.getLength()); // pack path for (auto const& b : *path) @@ -185,7 +185,7 @@ LedgerReplayMsgHandler::processReplayDeltaRequest( // pack header Serializer nData(128); - addRaw(ledger->info(), nData); + addRaw(ledger->header(), nData); reply.set_ledgerheader(nData.getDataPtr(), nData.getLength()); // pack transactions auto const& txMap = ledger->txMap(); diff --git a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp index 4b068882c9..4e73b54d53 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp @@ -173,7 +173,7 @@ LedgerReplayTask::tryAdvance(ScopedLockType& sl) : ", waiting to fill parameter") << ", deltaIndex=" << deltaToBuild_ << ", totalDeltas=" << deltas_.size() << ", parent " - << (parent_ ? parent_->info().hash : uint256()); + << (parent_ ? parent_->header().hash : uint256()); bool shouldTry = parent_ && parameter_.full_ && parameter_.totalLedgers_ - 1 == deltas_.size(); @@ -191,7 +191,7 @@ LedgerReplayTask::tryAdvance(ScopedLockType& sl) if (auto l = delta->tryBuild(parent_); l) { JLOG(journal_.debug()) - << "Task " << hash_ << " got ledger " << l->info().hash + << "Task " << hash_ << " got ledger " << l->header().hash << " deltaIndex=" << deltaToBuild_ << " totalDeltas=" << deltas_.size(); parent_ = l; diff --git a/src/xrpld/app/ledger/detail/LedgerToJson.cpp b/src/xrpld/app/ledger/detail/LedgerToJson.cpp index 7e8ff9e541..f571669e5c 100644 --- a/src/xrpld/app/ledger/detail/LedgerToJson.cpp +++ b/src/xrpld/app/ledger/detail/LedgerToJson.cpp @@ -147,7 +147,7 @@ fillJsonTx( } if (!fill.ledger.open()) - txJson[jss::ledger_hash] = to_string(fill.ledger.info().hash); + txJson[jss::ledger_hash] = to_string(fill.ledger.header().hash); bool const validated = fill.context->ledgerMaster.isValidated(fill.ledger); @@ -305,12 +305,12 @@ fillJson(Object& json, LedgerFill const& fill) // Is there a way to report this back? auto bFull = isFull(fill); if (isBinary(fill)) - fillJsonBinary(json, !fill.ledger.open(), fill.ledger.info()); + fillJsonBinary(json, !fill.ledger.open(), fill.ledger.header()); else fillJson( json, !fill.ledger.open(), - fill.ledger.info(), + fill.ledger.header(), bFull, (fill.context ? fill.context->apiVersion : RPC::apiMaximumSupportedVersion)); diff --git a/src/xrpld/app/ledger/detail/LocalTxs.cpp b/src/xrpld/app/ledger/detail/LocalTxs.cpp index 557fde80ce..4d26b60a6f 100644 --- a/src/xrpld/app/ledger/detail/LocalTxs.cpp +++ b/src/xrpld/app/ledger/detail/LocalTxs.cpp @@ -126,7 +126,7 @@ public: std::lock_guard lock(m_lock); m_txns.remove_if([&view](auto const& txn) { - if (txn.isExpired(view.info().seq)) + if (txn.isExpired(view.header().seq)) return true; if (view.txExists(txn.getID())) return true; diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index 2ba6630945..79b48e42b1 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -1384,7 +1384,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) // start first consensus round if (!m_networkOPs->beginConsensus( - m_ledgerMaster->getClosedLedger()->info().hash, {})) + m_ledgerMaster->getClosedLedger()->header().hash, {})) { JLOG(m_journal.fatal()) << "Unable to start consensus"; return false; @@ -1699,7 +1699,7 @@ ApplicationImp::startGenesisLedger() std::make_shared(*genesis, timeKeeper().closeTime()); next->updateSkipList(); XRPL_ASSERT( - next->info().seq < XRP_LEDGER_EARLIEST_FEES || + next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()), "ripple::ApplicationImp::startGenesisLedger : valid ledger fees"); next->setImmutable(); @@ -1721,7 +1721,7 @@ ApplicationImp::getLastFullLedger() return ledger; XRPL_ASSERT( - ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || + ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()), "ripple::ApplicationImp::getLastFullLedger : valid ledger fees"); ledger->setImmutable(); @@ -1729,7 +1729,7 @@ ApplicationImp::getLastFullLedger() if (getLedgerMaster().haveLedger(seq)) ledger->setValidated(); - if (ledger->info().hash == hash) + if (ledger->header().hash == hash) { JLOG(j.trace()) << "Loaded ledger: " << hash; return ledger; @@ -1876,7 +1876,7 @@ ApplicationImp::loadLedgerFromFile(std::string const& name) loadLedger->stateMap().flushDirty(hotACCOUNT_NODE); XRPL_ASSERT( - loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || + loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()), "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees"); loadLedger->setAccepted( @@ -1955,7 +1955,7 @@ ApplicationImp::loadOldLedger( JLOG(m_journal.info()) << "Loading parent ledger"; - loadLedger = loadByHash(replayLedger->info().parentHash, *this); + loadLedger = loadByHash(replayLedger->header().parentHash, *this); if (!loadLedger) { JLOG(m_journal.info()) @@ -1964,7 +1964,7 @@ ApplicationImp::loadOldLedger( // Try to build the ledger from the back end auto il = std::make_shared( *this, - replayLedger->info().parentHash, + replayLedger->header().parentHash, 0, InboundLedger::Reason::GENERIC, stopwatch(), @@ -1989,7 +1989,7 @@ ApplicationImp::loadOldLedger( using namespace date; static constexpr NetClock::time_point ledgerWarnTimePoint{ sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}}; - if (loadLedger->info().closeTime < ledgerWarnTimePoint) + if (loadLedger->header().closeTime < ledgerWarnTimePoint) { JLOG(m_journal.fatal()) << "\n\n*** WARNING ***\n" @@ -2003,10 +2003,10 @@ ApplicationImp::loadOldLedger( "get the older rules.\n*** CONTINUING ***\n"; } - JLOG(m_journal.info()) << "Loading ledger " << loadLedger->info().hash - << " seq:" << loadLedger->info().seq; + JLOG(m_journal.info()) << "Loading ledger " << loadLedger->header().hash + << " seq:" << loadLedger->header().seq; - if (loadLedger->info().accountHash.isZero()) + if (loadLedger->header().accountHash.isZero()) { // LCOV_EXCL_START JLOG(m_journal.fatal()) << "Ledger is empty."; @@ -2039,7 +2039,7 @@ ApplicationImp::loadOldLedger( } m_ledgerMaster->setLedgerRangePresent( - loadLedger->info().seq, loadLedger->info().seq); + loadLedger->header().seq, loadLedger->header().seq); m_ledgerMaster->switchLCL(loadLedger); loadLedger->setValidated(); @@ -2081,7 +2081,7 @@ ApplicationImp::loadOldLedger( if (trapTxID && !trapTxID_) { JLOG(m_journal.fatal()) - << "Ledger " << replayLedger->info().seq + << "Ledger " << replayLedger->header().seq << " does not contain the transaction hash " << *trapTxID; return false; } diff --git a/src/xrpld/app/misc/FeeVoteImpl.cpp b/src/xrpld/app/misc/FeeVoteImpl.cpp index f116150681..88c33bd66b 100644 --- a/src/xrpld/app/misc/FeeVoteImpl.cpp +++ b/src/xrpld/app/misc/FeeVoteImpl.cpp @@ -266,7 +266,7 @@ FeeVoteImpl::doVoting( auto const baseReserve = baseReserveVote.getVotes(); auto const incReserve = incReserveVote.getVotes(); - auto const seq = lastClosedLedger->info().seq + 1; + auto const seq = lastClosedLedger->header().seq + 1; // add transactions to our position if (baseFee.second || baseReserve.second || incReserve.second) diff --git a/src/xrpld/app/misc/NegativeUNLVote.cpp b/src/xrpld/app/misc/NegativeUNLVote.cpp index e325403336..23d3248ba6 100644 --- a/src/xrpld/app/misc/NegativeUNLVote.cpp +++ b/src/xrpld/app/misc/NegativeUNLVote.cpp @@ -59,7 +59,7 @@ NegativeUNLVote::doVoting( } } - auto const seq = prevLedger->info().seq + 1; + auto const seq = prevLedger->header().seq + 1; purgeNewValidators(seq); // Process the table and find all candidates to disable or to re-enable @@ -69,8 +69,8 @@ NegativeUNLVote::doVoting( // Pick one to disable and one to re-enable if any, add ttUNL_MODIFY Tx if (!candidates.toDisableCandidates.empty()) { - auto n = - choose(prevLedger->info().hash, candidates.toDisableCandidates); + auto n = choose( + prevLedger->header().hash, candidates.toDisableCandidates); XRPL_ASSERT( nidToKeyMap.contains(n), "ripple::NegativeUNLVote::doVoting : found node to disable"); @@ -80,7 +80,7 @@ NegativeUNLVote::doVoting( if (!candidates.toReEnableCandidates.empty()) { auto n = choose( - prevLedger->info().hash, candidates.toReEnableCandidates); + prevLedger->header().hash, candidates.toReEnableCandidates); XRPL_ASSERT( nidToKeyMap.contains(n), "ripple::NegativeUNLVote::doVoting : found node to enable"); @@ -154,7 +154,7 @@ NegativeUNLVote::buildScoreTable( // Ask the validation container to keep enough validation message history // for next time. - auto const seq = prevLedger->info().seq + 1; + auto const seq = prevLedger->header().seq + 1; validations.setSeqToKeep(seq - 1, seq + FLAG_LEDGER_INTERVAL); // Find FLAG_LEDGER_INTERVAL (i.e. 256) previous ledger hashes diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index 157de028e5..1b0b4e5143 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -1514,7 +1514,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) std::optional validatedLedgerIndex; if (auto const l = m_ledgerMaster.getValidatedLedger()) - validatedLedgerIndex = l->info().seq; + validatedLedgerIndex = l->header().seq; auto newOL = app_.openLedger().current(); for (TransactionStatus& e : transactions) @@ -1882,8 +1882,8 @@ NetworkOPsImp::checkLastClosedLedger( if (!ourClosed) return false; - uint256 closedLedger = ourClosed->info().hash; - uint256 prevClosedLedger = ourClosed->info().parentHash; + uint256 closedLedger = ourClosed->header().hash; + uint256 prevClosedLedger = ourClosed->header().parentHash; JLOG(m_journal.trace()) << "OurClosed: " << closedLedger; JLOG(m_journal.trace()) << "PrevClosed: " << prevClosedLedger; @@ -1924,7 +1924,7 @@ NetworkOPsImp::checkLastClosedLedger( { // don't switch to our own previous ledger JLOG(m_journal.info()) << "We won't switch to our own previous ledger"; - networkClosed = ourClosed->info().hash; + networkClosed = ourClosed->header().hash; switchLedgers = false; } else @@ -1946,12 +1946,12 @@ NetworkOPsImp::checkLastClosedLedger( { // Don't switch to a ledger not on the validated chain // or with an invalid close time or sequence - networkClosed = ourClosed->info().hash; + networkClosed = ourClosed->header().hash; return false; } JLOG(m_journal.warn()) << "We are not running on the consensus ledger"; - JLOG(m_journal.info()) << "Our LCL: " << ourClosed->info().hash + JLOG(m_journal.info()) << "Our LCL: " << ourClosed->header().hash << getJson({*ourClosed, {}}); JLOG(m_journal.info()) << "Net LCL " << closedLedger; @@ -1977,7 +1977,7 @@ NetworkOPsImp::switchLastClosedLedger( { // set the newLCL as our last closed ledger -- this is abnormal code JLOG(m_journal.error()) - << "JUMP last closed ledger to " << newLCL->info().hash; + << "JUMP last closed ledger to " << newLCL->header().hash; clearNeedNetworkLedger(); @@ -2015,11 +2015,13 @@ NetworkOPsImp::switchLastClosedLedger( protocol::TMStatusChange s; s.set_newevent(protocol::neSWITCHED_LEDGER); - s.set_ledgerseq(newLCL->info().seq); + s.set_ledgerseq(newLCL->header().seq); s.set_networktime(app_.timeKeeper().now().time_since_epoch().count()); s.set_ledgerhashprevious( - newLCL->info().parentHash.begin(), newLCL->info().parentHash.size()); - s.set_ledgerhash(newLCL->info().hash.begin(), newLCL->info().hash.size()); + newLCL->header().parentHash.begin(), + newLCL->header().parentHash.size()); + s.set_ledgerhash( + newLCL->header().hash.begin(), newLCL->header().hash.size()); app_.overlay().foreach( send_always(std::make_shared(s, protocol::mtSTATUS_CHANGE))); @@ -2034,7 +2036,7 @@ NetworkOPsImp::beginConsensus( networkClosed.isNonZero(), "ripple::NetworkOPsImp::beginConsensus : nonzero input"); - auto closingInfo = m_ledgerMaster.getCurrentLedger()->info(); + auto closingInfo = m_ledgerMaster.getCurrentLedger()->header(); JLOG(m_journal.info()) << "Consensus time for #" << closingInfo.seq << " with LCL " << closingInfo.parentHash; @@ -2056,11 +2058,12 @@ NetworkOPsImp::beginConsensus( } XRPL_ASSERT( - prevLedger->info().hash == closingInfo.parentHash, + prevLedger->header().hash == closingInfo.parentHash, "ripple::NetworkOPsImp::beginConsensus : prevLedger hash matches " "parent"); XRPL_ASSERT( - closingInfo.parentHash == m_ledgerMaster.getClosedLedger()->info().hash, + closingInfo.parentHash == + m_ledgerMaster.getClosedLedger()->header().hash, "ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches " "hash"); @@ -2147,7 +2150,7 @@ NetworkOPsImp::mapComplete(std::shared_ptr const& map, bool fromAcquire) void NetworkOPsImp::endConsensus(std::unique_ptr const& clog) { - uint256 deadLedger = m_ledgerMaster.getClosedLedger()->info().parentHash; + uint256 deadLedger = m_ledgerMaster.getClosedLedger()->header().parentHash; for (auto const& it : app_.overlay().getActivePeers()) { @@ -2193,8 +2196,9 @@ NetworkOPsImp::endConsensus(std::unique_ptr const& clog) // Note: Do not go to FULL if we don't have the previous ledger // check if the ledger is bad enough to go to CONNECTE D -- TODO auto current = m_ledgerMaster.getCurrentLedger(); - if (app_.timeKeeper().now() < (current->info().parentCloseTime + - 2 * current->info().closeTimeResolution)) + if (app_.timeKeeper().now() < + (current->header().parentCloseTime + + 2 * current->header().closeTimeResolution)) { setMode(OperatingMode::FULL); } @@ -2911,8 +2915,8 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) { XRPAmount const baseFee = lpClosed->fees().base; Json::Value l(Json::objectValue); - l[jss::seq] = Json::UInt(lpClosed->info().seq); - l[jss::hash] = to_string(lpClosed->info().hash); + l[jss::seq] = Json::UInt(lpClosed->header().seq); + l[jss::hash] = to_string(lpClosed->header().hash); if (!human) { @@ -2920,7 +2924,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) l[jss::reserve_base] = lpClosed->fees().reserve.jsonClipped(); l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped(); l[jss::close_time] = Json::Value::UInt( - lpClosed->info().closeTime.time_since_epoch().count()); + lpClosed->header().closeTime.time_since_epoch().count()); } else { @@ -2942,7 +2946,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) } else { - auto lCloseTime = lpClosed->info().closeTime; + auto lCloseTime = lpClosed->header().closeTime; auto closeTime = app_.timeKeeper().closeTime(); if (lCloseTime <= closeTime) { @@ -2962,8 +2966,8 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) auto lpPublished = m_ledgerMaster.getPublishedLedger(); if (!lpPublished) info[jss::published_ledger] = "none"; - else if (lpPublished->info().seq != lpClosed->info().seq) - info[jss::published_ledger] = lpPublished->info().seq; + else if (lpPublished->header().seq != lpClosed->header().seq) + info[jss::published_ledger] = lpPublished->header().seq; } accounting_.json(info); @@ -3083,12 +3087,12 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) // Holes are filled across connection loss or other catastrophe std::shared_ptr alpAccepted = - app_.getAcceptedLedgerCache().fetch(lpAccepted->info().hash); + app_.getAcceptedLedgerCache().fetch(lpAccepted->header().hash); if (!alpAccepted) { alpAccepted = std::make_shared(lpAccepted, app_); app_.getAcceptedLedgerCache().canonicalize_replace_client( - lpAccepted->info().hash, alpAccepted); + lpAccepted->header().hash, alpAccepted); } XRPL_ASSERT( @@ -3097,8 +3101,8 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) { JLOG(m_journal.debug()) - << "Publishing ledger " << lpAccepted->info().seq << " " - << lpAccepted->info().hash; + << "Publishing ledger " << lpAccepted->header().seq << " " + << lpAccepted->header().hash; std::lock_guard sl(mSubLock); @@ -3107,10 +3111,10 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) Json::Value jvObj(Json::objectValue); jvObj[jss::type] = "ledgerClosed"; - jvObj[jss::ledger_index] = lpAccepted->info().seq; - jvObj[jss::ledger_hash] = to_string(lpAccepted->info().hash); + jvObj[jss::ledger_index] = lpAccepted->header().seq; + jvObj[jss::ledger_hash] = to_string(lpAccepted->header().hash); jvObj[jss::ledger_time] = Json::Value::UInt( - lpAccepted->info().closeTime.time_since_epoch().count()); + lpAccepted->header().closeTime.time_since_epoch().count()); jvObj[jss::network_id] = app_.config().NETWORK_ID; @@ -3273,27 +3277,27 @@ NetworkOPsImp::transJson( netID = transaction->getFieldU32(sfNetworkID); if (std::optional ctid = - RPC::encodeCTID(ledger->info().seq, txnSeq, netID); + RPC::encodeCTID(ledger->header().seq, txnSeq, netID); ctid) jvObj[jss::ctid] = *ctid; } if (!ledger->open()) - jvObj[jss::ledger_hash] = to_string(ledger->info().hash); + jvObj[jss::ledger_hash] = to_string(ledger->header().hash); if (validated) { - jvObj[jss::ledger_index] = ledger->info().seq; + jvObj[jss::ledger_index] = ledger->header().seq; jvObj[jss::transaction][jss::date] = - ledger->info().closeTime.time_since_epoch().count(); + ledger->header().closeTime.time_since_epoch().count(); jvObj[jss::validated] = true; - jvObj[jss::close_time_iso] = to_string_iso(ledger->info().closeTime); + jvObj[jss::close_time_iso] = to_string_iso(ledger->header().closeTime); // WRITEME: Put the account next seq here } else { jvObj[jss::validated] = false; - jvObj[jss::ledger_current_index] = ledger->info().seq; + jvObj[jss::ledger_current_index] = ledger->header().seq; } jvObj[jss::status] = validated ? "closed" : "proposed"; @@ -4177,9 +4181,9 @@ NetworkOPsImp::acceptLedger( // FIXME Could we improve on this and remove the need for a specialized // API in Consensus? - beginConsensus(m_ledgerMaster.getClosedLedger()->info().hash, {}); + beginConsensus(m_ledgerMaster.getClosedLedger()->header().hash, {}); mConsensus.simulate(app_.timeKeeper().closeTime(), consensusDelay); - return m_ledgerMaster.getCurrentLedger()->info().seq; + return m_ledgerMaster.getCurrentLedger()->header().seq; } // <-- bool: true=added, false=already there @@ -4188,10 +4192,10 @@ NetworkOPsImp::subLedger(InfoSub::ref isrListener, Json::Value& jvResult) { if (auto lpClosed = m_ledgerMaster.getValidatedLedger()) { - jvResult[jss::ledger_index] = lpClosed->info().seq; - jvResult[jss::ledger_hash] = to_string(lpClosed->info().hash); + jvResult[jss::ledger_index] = lpClosed->header().seq; + jvResult[jss::ledger_hash] = to_string(lpClosed->header().hash); jvResult[jss::ledger_time] = Json::Value::UInt( - lpClosed->info().closeTime.time_since_epoch().count()); + lpClosed->header().closeTime.time_since_epoch().count()); if (!lpClosed->rules().enabled(featureXRPFees)) jvResult[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED; jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped(); diff --git a/src/xrpld/app/misc/PermissionedDEXHelpers.cpp b/src/xrpld/app/misc/PermissionedDEXHelpers.cpp index d02ae8e180..bc90848428 100644 --- a/src/xrpld/app/misc/PermissionedDEXHelpers.cpp +++ b/src/xrpld/app/misc/PermissionedDEXHelpers.cpp @@ -29,7 +29,7 @@ accountInDomain( return false; return !credentials::checkExpired( - sleCred, view.info().parentCloseTime); + sleCred, view.header().parentCloseTime); }); return inDomain; diff --git a/src/xrpld/app/misc/SHAMapStoreImp.cpp b/src/xrpld/app/misc/SHAMapStoreImp.cpp index d771145540..79c75ca0cf 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.cpp +++ b/src/xrpld/app/misc/SHAMapStoreImp.cpp @@ -278,7 +278,7 @@ SHAMapStoreImp::run() continue; } - LedgerIndex const validatedSeq = validatedLedger->info().seq; + LedgerIndex const validatedSeq = validatedLedger->header().seq; if (!lastRotated) { lastRotated = validatedSeq; diff --git a/src/xrpld/app/misc/detail/AMMUtils.cpp b/src/xrpld/app/misc/detail/AMMUtils.cpp index 84236b0b6e..ab0aec41b1 100644 --- a/src/xrpld/app/misc/detail/AMMUtils.cpp +++ b/src/xrpld/app/misc/detail/AMMUtils.cpp @@ -171,7 +171,7 @@ getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account) // Not expired if (auto const expiration = auctionSlot[~sfExpiration]; duration_cast( - view.info().parentCloseTime.time_since_epoch()) + view.header().parentCloseTime.time_since_epoch()) .count() < expiration) { if (auctionSlot[~sfAccount] == account) @@ -347,9 +347,10 @@ initializeFeeAuctionVote( STObject& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot); auctionSlot.setAccountID(sfAccount, account); // current + sec in 24h - auto const expiration = std::chrono::duration_cast( - view.info().parentCloseTime.time_since_epoch()) - .count() + + auto const expiration = + std::chrono::duration_cast( + view.header().parentCloseTime.time_since_epoch()) + .count() + TOTAL_TIME_SLOT_SECS; auctionSlot.setFieldU32(sfExpiration, expiration); auctionSlot.setFieldAmount(sfPrice, STAmount{lptIssue, 0}); diff --git a/src/xrpld/app/misc/detail/TxQ.cpp b/src/xrpld/app/misc/detail/TxQ.cpp index fd975f9178..35ae25c82f 100644 --- a/src/xrpld/app/misc/detail/TxQ.cpp +++ b/src/xrpld/app/misc/detail/TxQ.cpp @@ -82,7 +82,8 @@ TxQ::FeeMetrics::update( "ripple::TxQ::FeeMetrics::update : fee levels size"); JLOG((timeLeap ? j_.warn() : j_.debug())) - << "Ledger " << view.info().seq << " has " << size << " transactions. " + << "Ledger " << view.header().seq << " has " << size + << " transactions. " << "Ledgers are processing " << (timeLeap ? "slowly" : "as expected") << ". Expected transactions is currently " << txnsExpected_ << " and multiplier is " << escalationMultiplier_; @@ -384,7 +385,7 @@ TxQ::canBeHeld( // a realistic chance of getting into a ledger. auto const lastValid = getLastLedgerSequence(tx); if (lastValid && - *lastValid < view.info().seq + setup_.minimumLastLedgerBuffer) + *lastValid < view.header().seq + setup_.minimumLastLedgerBuffer) return telCAN_NOT_QUEUE; } @@ -1349,7 +1350,7 @@ TxQ::processClosedLedger(Application& app, ReadView const& view, bool timeLeap) feeMetrics_.update(app, view, timeLeap, setup_); auto const& snapshot = feeMetrics_.getSnapshot(); - auto ledgerSeq = view.info().seq; + auto ledgerSeq = view.header().seq; if (!timeLeap) maxSize_ = std::max( @@ -1548,7 +1549,7 @@ TxQ::accept(Application& app, OpenView& view) // ledger have been. Rebuild the queue using the open ledger's // parent hash, so that transactions paying the same fee are // reordered. - LedgerHash const& parentHash = view.info().parentHash; + LedgerHash const& parentHash = view.header().parentHash; if (parentHash == parentHash_) JLOG(j_.warn()) << "Parent ledger hash unchanged from " << parentHash; else @@ -1851,7 +1852,7 @@ TxQ::doRPC(Application& app) const auto& levels = ret[jss::levels] = Json::objectValue; - ret[jss::ledger_current_index] = view->info().seq; + ret[jss::ledger_current_index] = view->header().seq; ret[jss::expected_ledger_size] = std::to_string(metrics.txPerLedger); ret[jss::current_ledger_size] = std::to_string(metrics.txInLedger); ret[jss::current_queue_size] = std::to_string(metrics.txCount); diff --git a/src/xrpld/app/paths/PathRequest.cpp b/src/xrpld/app/paths/PathRequest.cpp index 5ab7766e30..6b7b35e366 100644 --- a/src/xrpld/app/paths/PathRequest.cpp +++ b/src/xrpld/app/paths/PathRequest.cpp @@ -207,7 +207,7 @@ PathRequest::isValid(std::shared_ptr const& crCache) (sleDest->getFlags() & lsfRequireDestTag); } - jvStatus[jss::ledger_hash] = to_string(lrLedger->info().hash); + jvStatus[jss::ledger_hash] = to_string(lrLedger->header().hash); jvStatus[jss::ledger_index] = lrLedger->seq(); return true; } diff --git a/src/xrpld/app/paths/RippleLineCache.cpp b/src/xrpld/app/paths/RippleLineCache.cpp index 8e35b771fd..498b060cb3 100644 --- a/src/xrpld/app/paths/RippleLineCache.cpp +++ b/src/xrpld/app/paths/RippleLineCache.cpp @@ -8,12 +8,12 @@ RippleLineCache::RippleLineCache( beast::Journal j) : ledger_(ledger), journal_(j) { - JLOG(journal_.debug()) << "created for ledger " << ledger_->info().seq; + JLOG(journal_.debug()) << "created for ledger " << ledger_->header().seq; } RippleLineCache::~RippleLineCache() { - JLOG(journal_.debug()) << "destroyed for ledger " << ledger_->info().seq + JLOG(journal_.debug()) << "destroyed for ledger " << ledger_->header().seq << " with " << lines_.size() << " accounts and " << totalLineCount_ << " distinct trust lines."; } @@ -99,7 +99,7 @@ RippleLineCache::getRippleLines( "ripple::RippleLineCache::getRippleLines : null or nonempty lines"); auto const size = it->second ? it->second->size() : 0; JLOG(journal_.trace()) << "getRippleLines for ledger " - << ledger_->info().seq << " found " << size + << ledger_->header().seq << " found " << size << (key.direction_ == LineDirection::outgoing ? " outgoing" : " incoming") diff --git a/src/xrpld/app/rdb/backend/detail/Node.cpp b/src/xrpld/app/rdb/backend/detail/Node.cpp index a7b35a5305..c8458d15db 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.cpp +++ b/src/xrpld/app/rdb/backend/detail/Node.cpp @@ -177,13 +177,13 @@ saveValidatedLedger( bool current) { auto j = app.journal("Ledger"); - auto seq = ledger->info().seq; + auto seq = ledger->header().seq; // TODO(tom): Fix this hard-coded SQL! JLOG(j.trace()) << "saveValidatedLedger " << (current ? "" : "fromAcquire ") << seq; - if (!ledger->info().accountHash.isNonZero()) + if (!ledger->header().accountHash.isNonZero()) { // LCOV_EXCL_START JLOG(j.fatal()) << "AH is zero: " << getJson({*ledger, {}}); @@ -191,10 +191,11 @@ saveValidatedLedger( // LCOV_EXCL_STOP } - if (ledger->info().accountHash != ledger->stateMap().getHash().as_uint256()) + if (ledger->header().accountHash != + ledger->stateMap().getHash().as_uint256()) { // LCOV_EXCL_START - JLOG(j.fatal()) << "sAL: " << ledger->info().accountHash + JLOG(j.fatal()) << "sAL: " << ledger->header().accountHash << " != " << ledger->stateMap().getHash(); JLOG(j.fatal()) << "saveAcceptedLedger: seq=" << seq << ", current=" << current; @@ -204,33 +205,33 @@ saveValidatedLedger( } XRPL_ASSERT( - ledger->info().txHash == ledger->txMap().getHash().as_uint256(), + ledger->header().txHash == ledger->txMap().getHash().as_uint256(), "ripple::detail::saveValidatedLedger : transaction hash match"); // Save the ledger header in the hashed object store { Serializer s(128); s.add32(HashPrefix::ledgerMaster); - addRaw(ledger->info(), s); + addRaw(ledger->header(), s); app.getNodeStore().store( - hotLEDGER, std::move(s.modData()), ledger->info().hash, seq); + hotLEDGER, std::move(s.modData()), ledger->header().hash, seq); } std::shared_ptr aLedger; try { - aLedger = app.getAcceptedLedgerCache().fetch(ledger->info().hash); + aLedger = app.getAcceptedLedgerCache().fetch(ledger->header().hash); if (!aLedger) { aLedger = std::make_shared(ledger, app); app.getAcceptedLedgerCache().canonicalize_replace_client( - ledger->info().hash, aLedger); + ledger->header().hash, aLedger); } } catch (std::exception const&) { JLOG(j.warn()) << "An accepted ledger was missing nodes"; - app.getLedgerMaster().failedSave(seq, ledger->info().hash); + app.getLedgerMaster().failedSave(seq, ledger->header().hash); // Clients can now trust the database for information about this // ledger sequence. app.pendingSaves().finishWork(seq); @@ -357,18 +358,18 @@ saveValidatedLedger( soci::transaction tr(*db); - auto const hash = to_string(ledger->info().hash); - auto const parentHash = to_string(ledger->info().parentHash); - auto const drops = to_string(ledger->info().drops); + auto const hash = to_string(ledger->header().hash); + auto const parentHash = to_string(ledger->header().parentHash); + auto const drops = to_string(ledger->header().drops); auto const closeTime = - ledger->info().closeTime.time_since_epoch().count(); + ledger->header().closeTime.time_since_epoch().count(); auto const parentCloseTime = - ledger->info().parentCloseTime.time_since_epoch().count(); + ledger->header().parentCloseTime.time_since_epoch().count(); auto const closeTimeResolution = - ledger->info().closeTimeResolution.count(); - auto const closeFlags = ledger->info().closeFlags; - auto const accountHash = to_string(ledger->info().accountHash); - auto const txHash = to_string(ledger->info().txHash); + ledger->header().closeTimeResolution.count(); + auto const closeFlags = ledger->header().closeFlags; + auto const accountHash = to_string(ledger->header().accountHash); + auto const txHash = to_string(ledger->header().txHash); *db << addLedger, soci::use(hash), soci::use(seq), soci::use(parentHash), soci::use(drops), soci::use(closeTime), diff --git a/src/xrpld/app/tx/detail/AMMBid.cpp b/src/xrpld/app/tx/detail/AMMBid.cpp index 158f60e0e4..47b89417a3 100644 --- a/src/xrpld/app/tx/detail/AMMBid.cpp +++ b/src/xrpld/app/tx/detail/AMMBid.cpp @@ -180,7 +180,7 @@ applyBid( auto& auctionSlot = ammSle->peekFieldObject(sfAuctionSlot); auto const current = duration_cast( - ctx_.view().info().parentCloseTime.time_since_epoch()) + ctx_.view().header().parentCloseTime.time_since_epoch()) .count(); // Auction slot discounted fee auto const discountedFee = diff --git a/src/xrpld/app/tx/detail/Credentials.cpp b/src/xrpld/app/tx/detail/Credentials.cpp index e16a432656..274a25e0c6 100644 --- a/src/xrpld/app/tx/detail/Credentials.cpp +++ b/src/xrpld/app/tx/detail/Credentials.cpp @@ -104,7 +104,7 @@ CredentialCreate::doApply() if (optExp) { std::uint32_t const closeTime = - ctx_.view().info().parentCloseTime.time_since_epoch().count(); + ctx_.view().header().parentCloseTime.time_since_epoch().count(); if (closeTime > *optExp) { @@ -242,7 +242,7 @@ CredentialDelete::doApply() return tefINTERNAL; // LCOV_EXCL_LINE if ((subject != account_) && (issuer != account_) && - !checkExpired(sleCred, ctx_.view().info().parentCloseTime)) + !checkExpired(sleCred, ctx_.view().header().parentCloseTime)) { JLOG(j_.trace()) << "Can't delete non-expired credential."; return tecNO_PERMISSION; @@ -336,7 +336,7 @@ CredentialAccept::doApply() Keylet const credentialKey = keylet::credential(account_, issuer, credType); auto const sleCred = view().peek(credentialKey); // Checked in preclaim() - if (checkExpired(sleCred, view().info().parentCloseTime)) + if (checkExpired(sleCred, view().header().parentCloseTime)) { JLOG(j_.trace()) << "Credential is expired: " << sleCred->getText(); // delete expired credentials even if the transaction failed diff --git a/src/xrpld/app/tx/detail/Escrow.cpp b/src/xrpld/app/tx/detail/Escrow.cpp index c22b8145c6..e9aad6ad37 100644 --- a/src/xrpld/app/tx/detail/Escrow.cpp +++ b/src/xrpld/app/tx/detail/Escrow.cpp @@ -416,7 +416,7 @@ escrowLockApplyHelper( TER EscrowCreate::doApply() { - auto const closeTime = ctx_.view().info().parentCloseTime; + auto const closeTime = ctx_.view().header().parentCloseTime; if (ctx_.tx[~sfCancelAfter] && after(closeTime, ctx_.tx[sfCancelAfter])) return tecNO_PERMISSION; @@ -964,7 +964,7 @@ EscrowFinish::doApply() // If a cancel time is present, a finish operation should only succeed prior // to that time. - auto const now = ctx_.view().info().parentCloseTime; + auto const now = ctx_.view().header().parentCloseTime; // Too soon: can't execute before the finish time if ((*slep)[~sfFinishAfter] && !after(now, (*slep)[sfFinishAfter])) @@ -1226,7 +1226,7 @@ EscrowCancel::doApply() return tecNO_TARGET; } - auto const now = ctx_.view().info().parentCloseTime; + auto const now = ctx_.view().header().parentCloseTime; // No cancel time specified: can't execute at all. if (!(*slep)[~sfCancelAfter]) diff --git a/src/xrpld/app/tx/detail/LoanSet.cpp b/src/xrpld/app/tx/detail/LoanSet.cpp index 838e774cae..756ea53fc1 100644 --- a/src/xrpld/app/tx/detail/LoanSet.cpp +++ b/src/xrpld/app/tx/detail/LoanSet.cpp @@ -188,7 +188,7 @@ LoanSet::getValueFields() static std::uint32_t getStartDate(ReadView const& view) { - return view.info().closeTime.time_since_epoch().count(); + return view.header().closeTime.time_since_epoch().count(); } TER diff --git a/src/xrpld/app/tx/detail/PayChan.cpp b/src/xrpld/app/tx/detail/PayChan.cpp index ae47036ab6..40e760e5f5 100644 --- a/src/xrpld/app/tx/detail/PayChan.cpp +++ b/src/xrpld/app/tx/detail/PayChan.cpp @@ -231,7 +231,7 @@ PayChanCreate::doApply() if (ctx_.view().rules().enabled(fixPayChanCancelAfter)) { - auto const closeTime = ctx_.view().info().parentCloseTime; + auto const closeTime = ctx_.view().header().parentCloseTime; if (ctx_.tx[~sfCancelAfter] && after(closeTime, ctx_.tx[sfCancelAfter])) return tecEXPIRED; } @@ -324,7 +324,7 @@ PayChanFund::doApply() { auto const cancelAfter = (*slep)[~sfCancelAfter]; auto const closeTime = - ctx_.view().info().parentCloseTime.time_since_epoch().count(); + ctx_.view().header().parentCloseTime.time_since_epoch().count(); if ((cancelAfter && closeTime >= *cancelAfter) || (expiration && closeTime >= *expiration)) return closeChannel( @@ -338,7 +338,7 @@ PayChanFund::doApply() if (auto extend = ctx_.tx[~sfExpiration]) { auto minExpiration = - ctx_.view().info().parentCloseTime.time_since_epoch().count() + + ctx_.view().header().parentCloseTime.time_since_epoch().count() + (*slep)[sfSettleDelay]; if (expiration && *expiration < minExpiration) minExpiration = *expiration; @@ -481,7 +481,7 @@ PayChanClaim::doApply() { auto const cancelAfter = (*slep)[~sfCancelAfter]; auto const closeTime = - ctx_.view().info().parentCloseTime.time_since_epoch().count(); + ctx_.view().header().parentCloseTime.time_since_epoch().count(); if ((cancelAfter && closeTime >= *cancelAfter) || (curExpiration && closeTime >= *curExpiration)) return closeChannel( @@ -549,7 +549,7 @@ PayChanClaim::doApply() slep, ctx_.view(), k.key, ctx_.app.journal("View")); auto const settleExpiration = - ctx_.view().info().parentCloseTime.time_since_epoch().count() + + ctx_.view().header().parentCloseTime.time_since_epoch().count() + (*slep)[sfSettleDelay]; if (!curExpiration || *curExpiration > settleExpiration) diff --git a/src/xrpld/app/tx/detail/SetOracle.cpp b/src/xrpld/app/tx/detail/SetOracle.cpp index cecb623d82..453d799b0d 100644 --- a/src/xrpld/app/tx/detail/SetOracle.cpp +++ b/src/xrpld/app/tx/detail/SetOracle.cpp @@ -51,7 +51,7 @@ SetOracle::preclaim(PreclaimContext const& ctx) // of the last closed ledger using namespace std::chrono; std::size_t const closeTime = - duration_cast(ctx.view.info().closeTime.time_since_epoch()) + duration_cast(ctx.view.header().closeTime.time_since_epoch()) .count(); std::size_t const lastUpdateTime = ctx.tx[sfLastUpdateTime]; if (lastUpdateTime < epoch_offset.count()) diff --git a/src/xrpld/overlay/detail/Handshake.cpp b/src/xrpld/overlay/detail/Handshake.cpp index 469dab6d9a..45dc37f52c 100644 --- a/src/xrpld/overlay/detail/Handshake.cpp +++ b/src/xrpld/overlay/detail/Handshake.cpp @@ -199,8 +199,8 @@ buildHandshake( if (auto const cl = app.getLedgerMaster().getClosedLedger()) { - h.insert("Closed-Ledger", strHex(cl->info().hash)); - h.insert("Previous-Ledger", strHex(cl->info().parentHash)); + h.insert("Closed-Ledger", strHex(cl->header().hash)); + h.insert("Previous-Ledger", strHex(cl->header().parentHash)); } } diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index 1a0995442b..097eaae4d9 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -3228,7 +3228,7 @@ PeerImp::sendLedgerBase( JLOG(p_journal_.trace()) << "sendLedgerBase: Base data"; Serializer s(sizeof(LedgerHeader)); - addRaw(ledger->info(), s); + addRaw(ledger->header(), s); ledgerData.add_nodes()->set_nodedata(s.getDataPtr(), s.getLength()); auto const& stateMap{ledger->stateMap()}; @@ -3241,7 +3241,7 @@ PeerImp::sendLedgerBase( ledgerData.add_nodes()->set_nodedata( root.getDataPtr(), root.getLength()); - if (ledger->info().txHash != beast::zero) + if (ledger->header().txHash != beast::zero) { auto const& txMap{ledger->txMap()}; if (txMap.getHash() != beast::zero) @@ -3326,7 +3326,7 @@ PeerImp::getLedger(std::shared_ptr const& m) if (ledger) { // Validate retrieved ledger sequence - auto const ledgerSeq{ledger->info().seq}; + auto const ledgerSeq{ledger->header().seq}; if (m->has_ledgerseq()) { if (ledgerSeq != m->ledgerseq()) @@ -3440,9 +3440,9 @@ PeerImp::processLedgerRequest(std::shared_ptr const& m) return; // Fill out the reply - auto const ledgerHash{ledger->info().hash}; + auto const ledgerHash{ledger->header().hash}; ledgerData.set_ledgerhash(ledgerHash.begin(), ledgerHash.size()); - ledgerData.set_ledgerseq(ledger->info().seq); + ledgerData.set_ledgerseq(ledger->header().seq); ledgerData.set_type(itype); if (m->has_requestcookie()) ledgerData.set_requestcookie(m->requestcookie()); diff --git a/src/xrpld/rpc/BookChanges.h b/src/xrpld/rpc/BookChanges.h index 58e8c25dc1..c30dadb9fe 100644 --- a/src/xrpld/rpc/BookChanges.h +++ b/src/xrpld/rpc/BookChanges.h @@ -166,11 +166,11 @@ computeBookChanges(std::shared_ptr const& lpAccepted) jvObj[jss::type] = "bookChanges"; // retrieve validated information from LedgerHeader class - jvObj[jss::validated] = lpAccepted->info().validated; - jvObj[jss::ledger_index] = lpAccepted->info().seq; - jvObj[jss::ledger_hash] = to_string(lpAccepted->info().hash); + jvObj[jss::validated] = lpAccepted->header().validated; + jvObj[jss::ledger_index] = lpAccepted->header().seq; + jvObj[jss::ledger_hash] = to_string(lpAccepted->header().hash); jvObj[jss::ledger_time] = Json::Value::UInt( - lpAccepted->info().closeTime.time_since_epoch().count()); + lpAccepted->header().closeTime.time_since_epoch().count()); jvObj[jss::changes] = Json::arrayValue; diff --git a/src/xrpld/rpc/detail/DeliveredAmount.cpp b/src/xrpld/rpc/detail/DeliveredAmount.cpp index 2191d2b338..bcc7c4389d 100644 --- a/src/xrpld/rpc/detail/DeliveredAmount.cpp +++ b/src/xrpld/rpc/detail/DeliveredAmount.cpp @@ -88,7 +88,7 @@ insertDeliveredAmount( std::shared_ptr const& serializedTx, TxMeta const& transactionMeta) { - auto const info = ledger.info(); + auto const info = ledger.header(); if (canHaveDeliveredAmount(serializedTx, transactionMeta)) { diff --git a/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp b/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp index 144378a1ec..d2bf7d5349 100644 --- a/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp @@ -234,7 +234,7 @@ getLedger(T& ledger, uint32_t ledgerIndex, Context const& context) if (ledger == nullptr) { auto cur = context.ledgerMaster.getCurrentLedger(); - if (cur->info().seq == ledgerIndex) + if (cur->header().seq == ledgerIndex) { ledger = cur; } @@ -243,7 +243,7 @@ getLedger(T& ledger, uint32_t ledgerIndex, Context const& context) if (ledger == nullptr) return {rpcLGR_NOT_FOUND, "ledgerNotFound"}; - if (ledger->info().seq > context.ledgerMaster.getValidLedgerIndex() && + if (ledger->header().seq > context.ledgerMaster.getValidLedgerIndex() && isValidatedOld(context.ledgerMaster, context.app.config().standalone())) { ledger.reset(); @@ -307,7 +307,7 @@ getLedger(T& ledger, LedgerShortcut shortcut, Context const& context) static auto const minSequenceGap = 10; - if (ledger->info().seq + minSequenceGap < + if (ledger->header().seq + minSequenceGap < context.ledgerMaster.getValidLedgerIndex()) { ledger.reset(); @@ -360,7 +360,7 @@ lookupLedger( if (auto status = ledgerFromRequest(ledger, context)) return status; - auto& info = ledger->info(); + auto& info = ledger->header(); if (!ledger->open()) { @@ -433,7 +433,7 @@ getOrAcquireLedger(RPC::JsonContext const& context) ledgerIndex = jsonIndex.asInt(); auto ledger = ledgerMaster.getValidatedLedger(); - if (ledgerIndex >= ledger->info().seq) + if (ledgerIndex >= ledger->header().seq) return Unexpected(RPC::make_param_error("Ledger index too large")); if (ledgerIndex <= 0) return Unexpected(RPC::make_param_error("Ledger index too small")); diff --git a/src/xrpld/rpc/handlers/AMMInfo.cpp b/src/xrpld/rpc/handlers/AMMInfo.cpp index 0504adca02..5ea826fce5 100644 --- a/src/xrpld/rpc/handlers/AMMInfo.cpp +++ b/src/xrpld/rpc/handlers/AMMInfo.cpp @@ -194,7 +194,7 @@ doAMMInfo(RPC::JsonContext& context) { Json::Value auction; auto const timeSlot = ammAuctionTimeSlot( - ledger->info().parentCloseTime.time_since_epoch().count(), + ledger->header().parentCloseTime.time_since_epoch().count(), auctionSlot); auction[jss::time_interval] = timeSlot ? *timeSlot : AUCTION_SLOT_TIME_INTERVALS; @@ -230,7 +230,7 @@ doAMMInfo(RPC::JsonContext& context) result[jss::amm] = std::move(ammResult); if (!result.isMember(jss::ledger_index) && !result.isMember(jss::ledger_hash)) - result[jss::ledger_current_index] = ledger->info().seq; + result[jss::ledger_current_index] = ledger->header().seq; result[jss::validated] = context.ledgerMaster.isValidated(*ledger); return result; diff --git a/src/xrpld/rpc/handlers/AccountTx.cpp b/src/xrpld/rpc/handlers/AccountTx.cpp index e248764194..efb246b4d5 100644 --- a/src/xrpld/rpc/handlers/AccountTx.cpp +++ b/src/xrpld/rpc/handlers/AccountTx.cpp @@ -176,12 +176,13 @@ getLedgerRange( bool validated = context.ledgerMaster.isValidated(*ledgerView); - if (!validated || ledgerView->info().seq > uValidatedMax || - ledgerView->info().seq < uValidatedMin) + if (!validated || + ledgerView->header().seq > uValidatedMax || + ledgerView->header().seq < uValidatedMin) { return rpcLGR_NOT_VALIDATED; } - uLedgerMin = uLedgerMax = ledgerView->info().seq; + uLedgerMin = uLedgerMax = ledgerView->header().seq; } return RPC::Status::OK; }, diff --git a/src/xrpld/rpc/handlers/CanDelete.cpp b/src/xrpld/rpc/handlers/CanDelete.cpp index c950b7a23d..d07d344242 100644 --- a/src/xrpld/rpc/handlers/CanDelete.cpp +++ b/src/xrpld/rpc/handlers/CanDelete.cpp @@ -60,7 +60,7 @@ doCanDelete(RPC::JsonContext& context) if (!ledger) return RPC::make_error(rpcLGR_NOT_FOUND, "ledgerNotFound"); - canDeleteSeq = ledger->info().seq; + canDeleteSeq = ledger->header().seq; } else { diff --git a/src/xrpld/rpc/handlers/DepositAuthorized.cpp b/src/xrpld/rpc/handlers/DepositAuthorized.cpp index 707db63e36..7beaffaf99 100644 --- a/src/xrpld/rpc/handlers/DepositAuthorized.cpp +++ b/src/xrpld/rpc/handlers/DepositAuthorized.cpp @@ -135,7 +135,7 @@ doDepositAuthorized(RPC::JsonContext& context) } if (credentials::checkExpired( - sleCred, ledger->info().parentCloseTime)) + sleCred, ledger->header().parentCloseTime)) { RPC::inject_error( rpcBAD_CREDENTIALS, "credentials are expired", result); diff --git a/src/xrpld/rpc/handlers/LedgerClosed.cpp b/src/xrpld/rpc/handlers/LedgerClosed.cpp index d7911f6b5b..3628c0f8d6 100644 --- a/src/xrpld/rpc/handlers/LedgerClosed.cpp +++ b/src/xrpld/rpc/handlers/LedgerClosed.cpp @@ -14,8 +14,8 @@ doLedgerClosed(RPC::JsonContext& context) XRPL_ASSERT(ledger, "ripple::doLedgerClosed : non-null closed ledger"); Json::Value jvResult; - jvResult[jss::ledger_index] = ledger->info().seq; - jvResult[jss::ledger_hash] = to_string(ledger->info().hash); + jvResult[jss::ledger_index] = ledger->header().seq; + jvResult[jss::ledger_hash] = to_string(ledger->header().hash); return jvResult; } diff --git a/src/xrpld/rpc/handlers/LedgerData.cpp b/src/xrpld/rpc/handlers/LedgerData.cpp index c5e39f69b4..35e5055242 100644 --- a/src/xrpld/rpc/handlers/LedgerData.cpp +++ b/src/xrpld/rpc/handlers/LedgerData.cpp @@ -59,8 +59,8 @@ doLedgerData(RPC::JsonContext& context) if ((limit < 0) || ((limit > maxLimit) && (!isUnlimited(context.role)))) limit = maxLimit; - jvResult[jss::ledger_hash] = to_string(lpLedger->info().hash); - jvResult[jss::ledger_index] = lpLedger->info().seq; + jvResult[jss::ledger_hash] = to_string(lpLedger->header().hash); + jvResult[jss::ledger_index] = lpLedger->header().seq; if (!isMarker) { diff --git a/src/xrpld/rpc/handlers/LedgerHandler.cpp b/src/xrpld/rpc/handlers/LedgerHandler.cpp index 4483838fa0..14c6fc67d9 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.cpp +++ b/src/xrpld/rpc/handlers/LedgerHandler.cpp @@ -103,7 +103,7 @@ doLedgerGrpc(RPC::GRPCContext& context) } Serializer s; - addRaw(ledger->info(), s, true); + addRaw(ledger->header(), s, true); response.set_ledger_header(s.peekData().data(), s.getLength()); @@ -139,7 +139,7 @@ doLedgerGrpc(RPC::GRPCContext& context) { JLOG(context.j.error()) << __func__ << " - Error deserializing transaction in ledger " - << ledger->info().seq + << ledger->header().seq << " . skipping transaction and following transactions. You " "should look into this further"; } diff --git a/src/xrpld/rpc/handlers/LedgerHeader.cpp b/src/xrpld/rpc/handlers/LedgerHeader.cpp index ebbd6beb01..8c34b8a7cc 100644 --- a/src/xrpld/rpc/handlers/LedgerHeader.cpp +++ b/src/xrpld/rpc/handlers/LedgerHeader.cpp @@ -21,7 +21,7 @@ doLedgerHeader(RPC::JsonContext& context) return jvResult; Serializer s; - addRaw(lpLedger->info(), s); + addRaw(lpLedger->header(), s); jvResult[jss::ledger_data] = strHex(s.peekData()); // This information isn't verified: they should only use it if they trust diff --git a/src/xrpld/rpc/handlers/LedgerRequest.cpp b/src/xrpld/rpc/handlers/LedgerRequest.cpp index 2846bb9f08..8ae0e543f2 100644 --- a/src/xrpld/rpc/handlers/LedgerRequest.cpp +++ b/src/xrpld/rpc/handlers/LedgerRequest.cpp @@ -24,7 +24,7 @@ doLedgerRequest(RPC::JsonContext& context) auto const& ledger = res.value(); Json::Value jvResult; - jvResult[jss::ledger_index] = ledger->info().seq; + jvResult[jss::ledger_index] = ledger->header().seq; addJson(jvResult, {*ledger, &context, 0}); return jvResult; } diff --git a/src/xrpld/rpc/handlers/Tx.cpp b/src/xrpld/rpc/handlers/Tx.cpp index 7aba4d5f84..e7e812563d 100644 --- a/src/xrpld/rpc/handlers/Tx.cpp +++ b/src/xrpld/rpc/handlers/Tx.cpp @@ -26,7 +26,7 @@ isValidated(LedgerMaster& ledgerMaster, std::uint32_t seq, uint256 const& hash) if (!ledgerMaster.haveLedger(seq)) return false; - if (seq > ledgerMaster.getValidatedLedger()->info().seq) + if (seq > ledgerMaster.getValidatedLedger()->header().seq) return false; return ledgerMaster.getHashBySeq(seq) == hash; @@ -130,7 +130,7 @@ doTxHelp(RPC::Context& context, TxArgs args) context.ledgerMaster.getLedgerBySeq(txn->getLedger()); if (ledger && !ledger->open()) - result.ledgerHash = ledger->info().hash; + result.ledgerHash = ledger->header().hash; if (ledger && meta) { @@ -143,7 +143,7 @@ doTxHelp(RPC::Context& context, TxArgs args) result.meta = meta; } result.validated = isValidated( - context.ledgerMaster, ledger->info().seq, ledger->info().hash); + context.ledgerMaster, ledger->header().seq, ledger->header().hash); if (result.validated) result.closeTime = context.ledgerMaster.getCloseTimeBySeq(txn->getLedger()); @@ -151,7 +151,7 @@ doTxHelp(RPC::Context& context, TxArgs args) // compute outgoing CTID if (meta->getAsObject().isFieldPresent(sfTransactionIndex)) { - uint32_t lgrSeq = ledger->info().seq; + uint32_t lgrSeq = ledger->header().seq; uint32_t txnIdx = meta->getAsObject().getFieldU32(sfTransactionIndex); uint32_t netID = context.app.config().NETWORK_ID; From 9eb84a561ef8bb066d89f098bd9b4ac71baed67c Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 11 Dec 2025 08:54:23 -0500 Subject: [PATCH 039/105] refactor: Rename `rippled` binary to `xrpld` (#5983) Per [XLS-0095](https://xls.xrpl.org/xls/XLS-0095-rename-rippled-to-xrpld.html), we are taking steps to rename ripple(d) to xrpl(d). This change modifies the binary name from `rippled` to `xrpld`, and creates a symlink named `rippled` that points to the `xrpld` binary. Note that https://github.com/XRPLF/rippled/pull/5975 renamed any references to `rippled` in the CMake files and their contents, but explicitly maintained the `rippled` binary name by adding an exception. This change now undoes this exception and adds an explicit symlink instead. --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +- .github/scripts/rename/README.md | 4 ++ .github/scripts/rename/binary.sh | 54 ++++++++++++++++++ .../workflows/reusable-build-test-config.yml | 14 ++--- .../workflows/reusable-check-levelization.yml | 2 +- .github/workflows/reusable-check-rename.yml | 2 + BUILD.md | 56 +++++++++---------- CONTRIBUTING.md | 14 ++--- cmake/XrplCore.cmake | 2 - cmake/XrplInstall.cmake | 4 +- 10 files changed, 108 insertions(+), 50 deletions(-) create mode 100755 .github/scripts/rename/binary.sh diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index cc921f5a55..9d1f1f4e6b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,7 +1,7 @@ --- name: Bug Report -about: Create a report to help us improve rippled -title: "[Title with short description] (Version: [rippled version])" +about: Create a report to help us improve xrpld +title: "[Title with short description] (Version: [xrpld version])" labels: "" assignees: "" --- @@ -27,7 +27,7 @@ assignees: "" ## Environment - + ## Supporting Files diff --git a/.github/scripts/rename/README.md b/.github/scripts/rename/README.md index 7df661609b..836f3606ba 100644 --- a/.github/scripts/rename/README.md +++ b/.github/scripts/rename/README.md @@ -26,6 +26,9 @@ run from the repository root. references to `ripple` and `rippled` (with or without capital letters) to `xrpl` and `xrpld`, respectively. The name of the binary will remain as-is, and will only be renamed to `xrpld` by a later script. +4. `.github/scripts/rename/binary.sh`: This script will rename the binary from + `rippled` to `xrpld`, and reverses the symlink so that `rippled` points to + the `xrpld` binary. You can run all these scripts from the repository root as follows: @@ -33,4 +36,5 @@ You can run all these scripts from the repository root as follows: ./.github/scripts/rename/definitions.sh . ./.github/scripts/rename/copyright.sh . ./.github/scripts/rename/cmake.sh . +./.github/scripts/rename/binary.sh . ``` diff --git a/.github/scripts/rename/binary.sh b/.github/scripts/rename/binary.sh new file mode 100755 index 0000000000..deb4dd5fb4 --- /dev/null +++ b/.github/scripts/rename/binary.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Exit the script as soon as an error occurs. +set -e + +# On MacOS, ensure that GNU sed is installed and available as `gsed`. +SED_COMMAND=sed +if [[ "${OSTYPE}" == 'darwin'* ]]; then + if ! command -v gsed &> /dev/null; then + echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'." + exit 1 + fi + SED_COMMAND=gsed +fi + +# This script changes the binary name from `rippled` to `xrpld`, and reverses +# the symlink that currently points from `xrpld` to `rippled` so that it points +# from `rippled` to `xrpld` instead. +# Usage: .github/scripts/rename/binary.sh + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +DIRECTORY=$1 +echo "Processing directory: ${DIRECTORY}" +if [ ! -d "${DIRECTORY}" ]; then + echo "Error: Directory '${DIRECTORY}' does not exist." + exit 1 +fi +pushd ${DIRECTORY} + +# Remove the binary name override added by the cmake.sh script. +${SED_COMMAND} -z -i -E 's@\s+# For the time being.+"rippled"\)@@' cmake/XrplCore.cmake + +# Reverse the symlink. +${SED_COMMAND} -i -E 's@create_symbolic_link\(rippled@create_symbolic_link(xrpld@' cmake/XrplInstall.cmake +${SED_COMMAND} -i -E 's@/xrpld\$\{suffix\}@/rippled${suffix}@' cmake/XrplInstall.cmake + +# Rename references to the binary. +${SED_COMMAND} -i -E 's@rippled@xrpld@g' BUILD.md +${SED_COMMAND} -i -E 's@rippled@xrpld@g' CONTRIBUTING.md +${SED_COMMAND} -i -E 's@rippled@xrpld@g' .github/ISSUE_TEMPLATE/bug_report.md + +# Restore and/or fix certain renames. The pre-commit hook will update the +# formatting upon saving/committing. +${SED_COMMAND} -i -E 's@ripple/xrpld@XRPLF/rippled@g' BUILD.md +${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' BUILD.md +${SED_COMMAND} -i -E 's@xrpld \(`xrpld`\)@xrpld@g' BUILD.md +${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' CONTRIBUTING.md + +popd +echo "Processing complete." diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index 8ce810aa2e..70d4f93e16 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -129,14 +129,14 @@ jobs: --parallel "${BUILD_NPROC}" \ --target "${CMAKE_TARGET}" - - name: Upload rippled artifact (Linux) + - name: Upload the binary (Linux) if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }} uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 env: BUILD_DIR: ${{ inputs.build_dir }} with: - name: rippled-${{ inputs.config_name }} - path: ${{ env.BUILD_DIR }}/rippled + name: xrpld-${{ inputs.config_name }} + path: ${{ env.BUILD_DIR }}/xrpld retention-days: 3 if-no-files-found: error @@ -144,8 +144,8 @@ jobs: if: ${{ runner.os == 'Linux' }} working-directory: ${{ inputs.build_dir }} run: | - ldd ./rippled - if [ "$(ldd ./rippled | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then + ldd ./xrpld + if [ "$(ldd ./xrpld | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then echo 'The binary is statically linked.' else echo 'The binary is dynamically linked.' @@ -156,7 +156,7 @@ jobs: if: ${{ runner.os == 'Linux' && env.ENABLED_VOIDSTAR == 'true' }} working-directory: ${{ inputs.build_dir }} run: | - ./rippled --version | grep libvoidstar + ./xrpld --version | grep libvoidstar - name: Run the separate tests if: ${{ !inputs.build_only }} @@ -177,7 +177,7 @@ jobs: env: BUILD_NPROC: ${{ steps.nproc.outputs.nproc }} run: | - ./rippled --unittest --unittest-jobs "${BUILD_NPROC}" + ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" - name: Debug failure (Linux) if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }} diff --git a/.github/workflows/reusable-check-levelization.yml b/.github/workflows/reusable-check-levelization.yml index 3430ca28a2..29a1dc1480 100644 --- a/.github/workflows/reusable-check-levelization.yml +++ b/.github/workflows/reusable-check-levelization.yml @@ -25,7 +25,7 @@ jobs: env: MESSAGE: | - The dependency relationships between the modules in rippled have + The dependency relationships between the modules in xrpld have changed, which may be an improvement or a regression. A rule of thumb is that if your changes caused something to be diff --git a/.github/workflows/reusable-check-rename.yml b/.github/workflows/reusable-check-rename.yml index 0e42dc55ab..00ef7c6f14 100644 --- a/.github/workflows/reusable-check-rename.yml +++ b/.github/workflows/reusable-check-rename.yml @@ -25,6 +25,8 @@ jobs: run: .github/scripts/rename/copyright.sh . - name: Check CMake configs run: .github/scripts/rename/cmake.sh . + - name: Check binary name + run: .github/scripts/rename/binary.sh . - name: Check for differences env: MESSAGE: | diff --git a/BUILD.md b/BUILD.md index 54e02c6ae9..85b3e3ea74 100644 --- a/BUILD.md +++ b/BUILD.md @@ -10,7 +10,7 @@ ## Branches For a stable release, choose the `master` branch or one of the [tagged -releases](https://github.com/ripple/rippled/releases). +releases](https://github.com/XRPLF/rippled/releases). ```bash git checkout master @@ -33,7 +33,7 @@ git checkout develop See [System Requirements](https://xrpl.org/system-requirements.html). -Building rippled generally requires git, Python, Conan, CMake, and a C++ +Building xrpld generally requires git, Python, Conan, CMake, and a C++ compiler. Some guidance on setting up such a [C++ development environment can be found here](./docs/build/environment.md). @@ -45,7 +45,7 @@ found here](./docs/build/environment.md). It is possible to build with Conan 1.60+, but the instructions are significantly different, which is why we are not recommending it. -`rippled` is written in the C++20 dialect and includes the `` header. +`xrpld` is written in the C++20 dialect and includes the `` header. The [minimum compiler versions][2] required are: | Compiler | Version | @@ -66,7 +66,7 @@ Linux](./docs/build/environment.md#linux). ### Mac -Many rippled engineers use macOS for development. +Many xrpld engineers use macOS for development. Here are [sample instructions for setting up a C++ development environment on macOS](./docs/build/environment.md#macos). @@ -126,7 +126,7 @@ default profile. ### Patched recipes The recipes in Conan Center occasionally need to be patched for compatibility -with the latest version of `rippled`. We maintain a fork of the Conan Center +with the latest version of `xrpld`. We maintain a fork of the Conan Center [here](https://github.com/XRPLF/conan-center-index/) containing the patches. To ensure our patched recipes are used, you must add our Conan remote at a @@ -292,7 +292,7 @@ sed -i.bak -e 's|^compiler\.libcxx=.*$|compiler.libcxx=libstdc++11|' $(conan con to do that is to run the shortcut "x64 Native Tools Command Prompt" for the version of Visual Studio that you have installed. -Windows developers must also build `rippled` and its dependencies for the x64 +Windows developers must also build `xrpld` and its dependencies for the x64 architecture: ```bash @@ -422,9 +422,9 @@ tools.build:cxxflags=['-DBOOST_ASIO_DISABLE_CONCEPTS'] cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -Dxrpld=ON -Dtests=ON .. ``` - **Note:** You can pass build options for `rippled` in this step. + **Note:** You can pass build options for `xrpld` in this step. -4. Build `rippled`. +4. Build `xrpld`. For a single-configuration generator, it will build whatever configuration you passed for `CMAKE_BUILD_TYPE`. For a multi-configuration generator, you @@ -443,26 +443,26 @@ tools.build:cxxflags=['-DBOOST_ASIO_DISABLE_CONCEPTS'] cmake --build . --config Debug ``` -5. Test rippled. +5. Test xrpld. Single-config generators: ``` - ./rippled --unittest --unittest-jobs N + ./xrpld --unittest --unittest-jobs N ``` Multi-config generators: ``` - ./Release/rippled --unittest --unittest-jobs N - ./Debug/rippled --unittest --unittest-jobs N + ./Release/xrpld --unittest --unittest-jobs N + ./Debug/xrpld --unittest --unittest-jobs N ``` Replace the `--unittest-jobs` parameter N with the desired unit tests concurrency. Recommended setting is half of the number of available CPU cores. - The location of `rippled` binary in your build directory depends on your + The location of `xrpld` binary in your build directory depends on your CMake generator. Pass `--help` to see the rest of the command line options. ## Coverage report @@ -481,18 +481,18 @@ Prerequisites for the coverage report: A coverage report is created when the following steps are completed, in order: -1. `rippled` binary built with instrumentation data, enabled by the `coverage` +1. `xrpld` binary built with instrumentation data, enabled by the `coverage` option mentioned above 2. completed one or more run of the unit tests, which populates coverage capture data 3. completed run of the `gcovr` tool (which internally invokes either `gcov` or `llvm-cov`) to assemble both instrumentation data and the coverage capture data into a coverage report The last step of the above is automated into a single target `coverage`. The instrumented -`rippled` binary can also be used for regular development or testing work, at +`xrpld` binary can also be used for regular development or testing work, at the cost of extra disk space utilization and a small performance hit -(to store coverage capture data). Since `rippled` binary is simply a dependency of the +(to store coverage capture data). Since `xrpld` binary is simply a dependency of the coverage report target, it is possible to re-run the `coverage` target without -rebuilding the `rippled` binary. Note, running of the unit tests before the `coverage` +rebuilding the `xrpld` binary. Note, running of the unit tests before the `coverage` target is left to the developer. Each such run will append to the coverage data collected in the build directory. @@ -520,16 +520,16 @@ stored inside the build directory, as either of: ## Options -| Option | Default Value | Description | -| ---------- | ------------- | -------------------------------------------------------------------------- | -| `assert` | OFF | Enable assertions. | -| `coverage` | OFF | Prepare the coverage report. | -| `san` | N/A | Enable a sanitizer with Clang. Choices are `thread` and `address`. | -| `tests` | OFF | Build tests. | -| `unity` | OFF | Configure a unity build. | -| `xrpld` | OFF | Build the xrpld (`rippled`) application, and not just the libxrpl library. | -| `werr` | OFF | Treat compilation warnings as errors | -| `wextra` | OFF | Enable additional compilation warnings | +| Option | Default Value | Description | +| ---------- | ------------- | ------------------------------------------------------------------ | +| `assert` | OFF | Enable assertions. | +| `coverage` | OFF | Prepare the coverage report. | +| `san` | N/A | Enable a sanitizer with Clang. Choices are `thread` and `address`. | +| `tests` | OFF | Build tests. | +| `unity` | OFF | Configure a unity build. | +| `xrpld` | OFF | Build the xrpld application, and not just the libxrpl library. | +| `werr` | OFF | Treat compilation warnings as errors | +| `wextra` | OFF | Enable additional compilation warnings | [Unity builds][5] may be faster for the first build (at the cost of much more memory) since they concatenate sources into fewer @@ -573,7 +573,7 @@ you might have generated CMake files for a different `build_type` than the `CMAKE_BUILD_TYPE` you passed to Conan. ``` -/rippled/.build/pb-xrpl.libpb/xrpl/proto/xrpl.pb.h:10:10: fatal error: 'google/protobuf/port_def.inc' file not found +/xrpld/.build/pb-xrpl.libpb/xrpl/proto/xrpl.pb.h:10:10: fatal error: 'google/protobuf/port_def.inc' file not found 10 | #include | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 760e11bea6..86cfa9dc6d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ your verifying key. Please set up [signature verification][signing]. In general, external contributions should be developed in your personal [fork][forking]. Contributions from developers with write permissions -should be done in [the main repository][rippled] in a branch with +should be done in [the main repository][xrpld] in a branch with a permitted prefix. Permitted prefixes are: - XLS-[a-zA-Z0-9]+/.+ @@ -73,7 +73,7 @@ Ensure that your code compiles according to the build instructions in Please write tests for your code. If your test can be run offline, in under 60 seconds, then it can be an -automatic test run by `rippled --unittest`. +automatic test run by `xrpld --unittest`. Otherwise, it must be a manual test. If you create new source files, they must be organized as follows: @@ -256,13 +256,13 @@ pre-commit install We are using [Antithesis](https://antithesis.com/) for continuous fuzzing, and keep a copy of [Antithesis C++ SDK](https://github.com/antithesishq/antithesis-sdk-cpp/) in `external/antithesis-sdk`. One of the aims of fuzzing is to identify bugs -by finding external conditions which cause contracts violations inside `rippled`. +by finding external conditions which cause contracts violations inside `xrpld`. The contracts are expressed as `XRPL_ASSERT` or `UNREACHABLE` (defined in `include/xrpl/beast/utility/instrumentation.h`), which are effectively (outside of Antithesis) wrappers for `assert(...)` with added name. The purpose of name is to provide contracts with stable identity which does not rely on line numbers. -When `rippled` is built with the Antithesis instrumentation enabled +When `xrpld` is built with the Antithesis instrumentation enabled (using `voidstar` CMake option) and ran on the Antithesis platform, the contracts become [test properties](https://antithesis.com/docs/using_antithesis/properties.html); @@ -318,7 +318,7 @@ For this reason: To execute all unit tests: -`rippled --unittest --unittest-jobs=` +`xrpld --unittest --unittest-jobs=` (Note: Using multiple cores on a Mac M1 can cause spurious test failures. The cause is still under investigation. If you observe this problem, try specifying fewer jobs.) @@ -326,7 +326,7 @@ cause is still under investigation. If you observe this problem, try specifying To run a specific set of test suites: ``` -rippled --unittest TestSuiteName +xrpld --unittest TestSuiteName ``` Note: In this example, all tests with prefix `TestSuiteName` will be run, so if @@ -1075,7 +1075,7 @@ git fetch upstreams [contrib]: https://docs.github.com/en/get-started/quickstart/contributing-to-projects [squash]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-commits [forking]: https://github.com/XRPLF/rippled/fork -[rippled]: https://github.com/XRPLF/rippled +[xrpld]: https://github.com/XRPLF/rippled [signing]: https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification [setup-upstreams]: ./bin/git/setup-upstreams.sh [squash-branches]: ./bin/git/squash-branches.sh diff --git a/cmake/XrplCore.cmake b/cmake/XrplCore.cmake index 40b5535fc7..e4f97c46c3 100644 --- a/cmake/XrplCore.cmake +++ b/cmake/XrplCore.cmake @@ -223,6 +223,4 @@ if(xrpld) src/test/ledger/Invariants_test.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE) endif() - # For the time being, we will keep the name of the binary as it was. - set_target_properties(xrpld PROPERTIES OUTPUT_NAME "rippled") endif() diff --git a/cmake/XrplInstall.cmake b/cmake/XrplInstall.cmake index 05ace6eeea..ca3ad11d74 100644 --- a/cmake/XrplInstall.cmake +++ b/cmake/XrplInstall.cmake @@ -67,8 +67,8 @@ if (is_root_project AND TARGET xrpld) install(CODE " set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\") include(create_symbolic_link) - create_symbolic_link(rippled${suffix} \ - \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/xrpld${suffix}) + create_symbolic_link(xrpld${suffix} \ + \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/rippled${suffix}) ") endif () From 496efb71ca1049ca3314f2f49d02e1ea8c2bff75 Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Thu, 11 Dec 2025 15:30:54 +0000 Subject: [PATCH 040/105] refactor: Move JobQueue and related classes into xrpl.core module (#6121) --- .github/scripts/levelization/README.md | 52 +++++++++++++------ .../scripts/levelization/results/loops.txt | 6 --- .../scripts/levelization/results/ordering.txt | 18 +++++-- cmake/XrplCore.cmake | 11 +++- cmake/XrplInstall.cmake | 1 + .../xrpl}/core/ClosureCounter.h | 0 {src/xrpld => include/xrpl}/core/Coro.ipp | 0 {src/xrpld => include/xrpl}/core/Job.h | 5 +- {src/xrpld => include/xrpl}/core/JobQueue.h | 11 ++-- .../xrpld => include/xrpl}/core/JobTypeData.h | 3 +- .../xrpld => include/xrpl}/core/JobTypeInfo.h | 2 +- {src/xrpld => include/xrpl}/core/JobTypes.h | 4 +- {src/xrpld => include/xrpl}/core/LoadEvent.h | 0 .../xrpld => include/xrpl}/core/LoadMonitor.h | 3 +- .../perflog => include/xrpl/core}/PerfLog.h | 11 ++-- .../xrpl}/core/detail/Workers.h | 3 +- .../xrpl}/core/detail/semaphore.h | 0 src/{xrpld => libxrpl}/core/detail/Job.cpp | 3 +- .../core/detail/JobQueue.cpp | 5 +- .../core/detail/LoadEvent.cpp | 5 +- .../core/detail/LoadMonitor.cpp | 3 +- .../core/detail/Workers.cpp | 5 +- src/test/app/Path_test.cpp | 2 +- src/test/app/Transaction_ordering_test.cpp | 2 +- src/test/basics/PerfLog_test.cpp | 2 +- src/test/core/ClosureCounter_test.cpp | 3 +- src/test/core/Coroutine_test.cpp | 2 +- src/test/core/JobQueue_test.cpp | 3 +- src/test/core/Workers_test.cpp | 5 +- src/test/rpc/RobustTransaction_test.cpp | 3 +- src/xrpld/app/consensus/RCLConsensus.h | 2 +- src/xrpld/app/consensus/RCLValidations.cpp | 4 +- src/xrpld/app/ledger/ConsensusTransSetSF.cpp | 2 +- src/xrpld/app/ledger/Ledger.cpp | 2 +- src/xrpld/app/ledger/OrderBookDB.cpp | 2 +- src/xrpld/app/ledger/detail/InboundLedger.cpp | 2 +- .../app/ledger/detail/InboundLedgers.cpp | 4 +- .../app/ledger/detail/InboundTransactions.cpp | 2 +- .../app/ledger/detail/LedgerDeltaAcquire.cpp | 3 +- .../app/ledger/detail/TimeoutCounter.cpp | 3 +- src/xrpld/app/ledger/detail/TimeoutCounter.h | 2 +- src/xrpld/app/main/Application.cpp | 2 +- src/xrpld/app/main/GRPCServer.h | 2 +- src/xrpld/app/main/NodeStoreScheduler.h | 3 +- src/xrpld/app/misc/NetworkOPs.cpp | 2 +- src/xrpld/app/misc/NetworkOPs.h | 2 +- src/xrpld/app/paths/PathRequests.cpp | 2 +- src/xrpld/app/paths/Pathfinder.cpp | 2 +- src/xrpld/app/paths/Pathfinder.h | 2 +- src/xrpld/core/DatabaseCon.h | 3 +- src/xrpld/core/SociDB.h | 3 +- src/xrpld/overlay/detail/OverlayImpl.h | 2 +- src/xrpld/overlay/detail/PeerImp.cpp | 2 +- src/xrpld/overlay/detail/PeerSet.cpp | 3 +- src/xrpld/perflog/detail/PerfLogImp.cpp | 2 +- src/xrpld/perflog/detail/PerfLogImp.h | 2 +- src/xrpld/rpc/Context.h | 2 +- src/xrpld/rpc/RPCSub.h | 3 +- src/xrpld/rpc/ServerHandler.h | 2 +- src/xrpld/rpc/detail/LegacyPathFind.cpp | 5 +- src/xrpld/rpc/detail/RPCHandler.cpp | 4 +- src/xrpld/rpc/detail/ServerHandler.cpp | 2 +- src/xrpld/rpc/handlers/LogRotate.cpp | 2 +- 63 files changed, 139 insertions(+), 116 deletions(-) rename {src/xrpld => include/xrpl}/core/ClosureCounter.h (100%) rename {src/xrpld => include/xrpl}/core/Coro.ipp (100%) rename {src/xrpld => include/xrpl}/core/Job.h (98%) rename {src/xrpld => include/xrpl}/core/JobQueue.h (98%) rename {src/xrpld => include/xrpl}/core/JobTypeData.h (97%) rename {src/xrpld => include/xrpl}/core/JobTypeInfo.h (98%) rename {src/xrpld => include/xrpl}/core/JobTypes.h (99%) rename {src/xrpld => include/xrpl}/core/LoadEvent.h (100%) rename {src/xrpld => include/xrpl}/core/LoadMonitor.h (97%) rename {src/xrpld/perflog => include/xrpl/core}/PerfLog.h (96%) rename {src/xrpld => include/xrpl}/core/detail/Workers.h (99%) rename {src/xrpld => include/xrpl}/core/detail/semaphore.h (100%) rename src/{xrpld => libxrpl}/core/detail/Job.cpp (98%) rename src/{xrpld => libxrpl}/core/detail/JobQueue.cpp (99%) rename src/{xrpld => libxrpl}/core/detail/LoadEvent.cpp (94%) rename src/{xrpld => libxrpl}/core/detail/LoadMonitor.cpp (99%) rename src/{xrpld => libxrpl}/core/detail/Workers.cpp (98%) diff --git a/.github/scripts/levelization/README.md b/.github/scripts/levelization/README.md index f3ba1e2518..3b77a192b9 100644 --- a/.github/scripts/levelization/README.md +++ b/.github/scripts/levelization/README.md @@ -3,21 +3,26 @@ Levelization is the term used to describe efforts to prevent rippled from having or creating cyclic dependencies. -rippled code is organized into directories under `src/rippled` (and +rippled code is organized into directories under `src/xrpld`, `src/libxrpl` (and `src/test`) representing modules. The modules are intended to be organized into "tiers" or "levels" such that a module from one level can only include code from lower levels. Additionally, a module -in one level should never include code in an `impl` folder of any level +in one level should never include code in an `impl` or `detail` folder of any level other than it's own. +The codebase is split into two main areas: + +- **libxrpl** (`src/libxrpl`, `include/xrpl`): Reusable library modules with public interfaces +- **xrpld** (`src/xrpld`): Application-specific implementation code + Unfortunately, over time, enforcement of levelization has been inconsistent, so the current state of the code doesn't necessarily reflect these rules. Whenever possible, developers should refactor any levelization violations they find (by moving files or individual classes). At the very least, don't make things worse. -The table below summarizes the _desired_ division of modules, based on the -state of the rippled code when it was created. The levels are numbered from +The table below summarizes the _desired_ division of modules, based on the current +state of the rippled code. The levels are numbered from the bottom up with the lower level, lower numbered, more independent modules listed first, and the higher level, higher numbered modules with more dependencies listed later. @@ -25,18 +30,33 @@ more dependencies listed later. **tl;dr:** The modules listed first are more independent than the modules listed later. +## libxrpl Modules (Reusable Libraries) + +| Level / Tier | Module(s) | +| ------------ | ----------------------------------- | +| 01 | xrpl/beast | +| 02 | xrpl/basics | +| 03 | xrpl/json xrpl/crypto | +| 04 | xrpl/protocol | +| 05 | xrpl/core xrpl/resource xrpl/server | +| 06 | xrpl/ledger xrpl/nodestore xrpl/net | +| 07 | xrpl/shamap | + +## xrpld Modules (Application Implementation) + +| Level / Tier | Module(s) | +| ------------ | -------------------------------- | +| 05 | xrpld/conditions xrpld/consensus | +| 06 | xrpld/core xrpld/peerfinder | +| 07 | xrpld/shamap xrpld/overlay | +| 08 | xrpld/app | +| 09 | xrpld/rpc | +| 10 | xrpld/perflog | + +## Test Modules + | Level / Tier | Module(s) | | ------------ | -------------------------------------------------------------------------------------------------------- | -| 01 | ripple/beast ripple/unity | -| 02 | ripple/basics | -| 03 | ripple/json ripple/crypto | -| 04 | ripple/protocol | -| 05 | ripple/core ripple/conditions ripple/consensus ripple/resource ripple/server | -| 06 | ripple/peerfinder ripple/ledger ripple/nodestore ripple/net | -| 07 | ripple/shamap ripple/overlay | -| 08 | ripple/app | -| 09 | ripple/rpc | -| 10 | ripple/perflog | | 11 | test/jtx test/beast test/csf | | 12 | test/unit_test | | 13 | test/crypto test/conditions test/json test/resource test/shamap test/peerfinder test/basics test/overlay | @@ -45,8 +65,8 @@ listed later. | 16 | test/rpc test/app | (Note that `test` levelization is _much_ less important and _much_ less -strictly enforced than `ripple` levelization, other than the requirement -that `test` code should _never_ be included in `ripple` code.) +strictly enforced than `xrpl`/`xrpld` levelization, other than the requirement +that `test` code should _never_ be included in `xrpl` or `xrpld` code.) ## Validation diff --git a/.github/scripts/levelization/results/loops.txt b/.github/scripts/levelization/results/loops.txt index d057391be9..d15843ceb0 100644 --- a/.github/scripts/levelization/results/loops.txt +++ b/.github/scripts/levelization/results/loops.txt @@ -19,12 +19,6 @@ Loop: xrpld.app xrpld.rpc Loop: xrpld.app xrpld.shamap xrpld.shamap ~= xrpld.app -Loop: xrpld.core xrpld.perflog - xrpld.perflog == xrpld.core - Loop: xrpld.overlay xrpld.rpc xrpld.rpc ~= xrpld.overlay -Loop: xrpld.perflog xrpld.rpc - xrpld.rpc ~= xrpld.perflog - diff --git a/.github/scripts/levelization/results/ordering.txt b/.github/scripts/levelization/results/ordering.txt index 251e9c1957..c9c65fb0dd 100644 --- a/.github/scripts/levelization/results/ordering.txt +++ b/.github/scripts/levelization/results/ordering.txt @@ -1,4 +1,6 @@ libxrpl.basics > xrpl.basics +libxrpl.core > xrpl.basics +libxrpl.core > xrpl.core libxrpl.crypto > xrpl.basics libxrpl.json > xrpl.basics libxrpl.json > xrpl.json @@ -30,6 +32,7 @@ test.app > test.rpc test.app > test.toplevel test.app > test.unit_test test.app > xrpl.basics +test.app > xrpl.core test.app > xrpld.app test.app > xrpld.core test.app > xrpld.overlay @@ -42,7 +45,7 @@ test.app > xrpl.resource test.basics > test.jtx test.basics > test.unit_test test.basics > xrpl.basics -test.basics > xrpld.perflog +test.basics > xrpl.core test.basics > xrpld.rpc test.basics > xrpl.json test.basics > xrpl.protocol @@ -61,8 +64,8 @@ test.core > test.jtx test.core > test.toplevel test.core > test.unit_test test.core > xrpl.basics +test.core > xrpl.core test.core > xrpld.core -test.core > xrpld.perflog test.core > xrpl.json test.core > xrpl.server test.csf > xrpl.basics @@ -119,6 +122,7 @@ test.resource > xrpl.resource test.rpc > test.jtx test.rpc > test.toplevel test.rpc > xrpl.basics +test.rpc > xrpl.core test.rpc > xrpld.app test.rpc > xrpld.core test.rpc > xrpld.overlay @@ -146,6 +150,8 @@ test.unit_test > xrpl.basics tests.libxrpl > xrpl.basics tests.libxrpl > xrpl.json tests.libxrpl > xrpl.net +xrpl.core > xrpl.basics +xrpl.core > xrpl.json xrpl.json > xrpl.basics xrpl.ledger > xrpl.basics xrpl.ledger > xrpl.protocol @@ -165,9 +171,9 @@ xrpl.shamap > xrpl.nodestore xrpl.shamap > xrpl.protocol xrpld.app > test.unit_test xrpld.app > xrpl.basics +xrpld.app > xrpl.core xrpld.app > xrpld.conditions xrpld.app > xrpld.consensus -xrpld.app > xrpld.perflog xrpld.app > xrpl.json xrpld.app > xrpl.ledger xrpld.app > xrpl.net @@ -181,13 +187,14 @@ xrpld.consensus > xrpl.basics xrpld.consensus > xrpl.json xrpld.consensus > xrpl.protocol xrpld.core > xrpl.basics +xrpld.core > xrpl.core xrpld.core > xrpl.json xrpld.core > xrpl.net xrpld.core > xrpl.protocol xrpld.overlay > xrpl.basics +xrpld.overlay > xrpl.core xrpld.overlay > xrpld.core xrpld.overlay > xrpld.peerfinder -xrpld.overlay > xrpld.perflog xrpld.overlay > xrpl.json xrpld.overlay > xrpl.protocol xrpld.overlay > xrpl.resource @@ -196,8 +203,11 @@ xrpld.peerfinder > xrpl.basics xrpld.peerfinder > xrpld.core xrpld.peerfinder > xrpl.protocol xrpld.perflog > xrpl.basics +xrpld.perflog > xrpl.core +xrpld.perflog > xrpld.rpc xrpld.perflog > xrpl.json xrpld.rpc > xrpl.basics +xrpld.rpc > xrpl.core xrpld.rpc > xrpld.core xrpld.rpc > xrpl.json xrpld.rpc > xrpl.ledger diff --git a/cmake/XrplCore.cmake b/cmake/XrplCore.cmake index e4f97c46c3..12ba58d499 100644 --- a/cmake/XrplCore.cmake +++ b/cmake/XrplCore.cmake @@ -94,10 +94,18 @@ target_link_libraries(xrpl.libxrpl.protocol PUBLIC ) # Level 05 +add_module(xrpl core) +target_link_libraries(xrpl.libxrpl.core PUBLIC + xrpl.libxrpl.basics + xrpl.libxrpl.json + xrpl.libxrpl.protocol +) + +# Level 06 add_module(xrpl resource) target_link_libraries(xrpl.libxrpl.resource PUBLIC xrpl.libxrpl.protocol) -# Level 06 +# Level 07 add_module(xrpl net) target_link_libraries(xrpl.libxrpl.net PUBLIC xrpl.libxrpl.basics @@ -144,6 +152,7 @@ target_sources(xrpl.libxrpl PRIVATE ${sources}) target_link_modules(xrpl PUBLIC basics beast + core crypto json protocol diff --git a/cmake/XrplInstall.cmake b/cmake/XrplInstall.cmake index ca3ad11d74..67aca8f048 100644 --- a/cmake/XrplInstall.cmake +++ b/cmake/XrplInstall.cmake @@ -16,6 +16,7 @@ install ( xrpl.libxrpl xrpl.libxrpl.basics xrpl.libxrpl.beast + xrpl.libxrpl.core xrpl.libxrpl.crypto xrpl.libxrpl.json xrpl.libxrpl.ledger diff --git a/src/xrpld/core/ClosureCounter.h b/include/xrpl/core/ClosureCounter.h similarity index 100% rename from src/xrpld/core/ClosureCounter.h rename to include/xrpl/core/ClosureCounter.h diff --git a/src/xrpld/core/Coro.ipp b/include/xrpl/core/Coro.ipp similarity index 100% rename from src/xrpld/core/Coro.ipp rename to include/xrpl/core/Coro.ipp diff --git a/src/xrpld/core/Job.h b/include/xrpl/core/Job.h similarity index 98% rename from src/xrpld/core/Job.h rename to include/xrpl/core/Job.h index ac6278b3c8..35d42cfd0b 100644 --- a/src/xrpld/core/Job.h +++ b/include/xrpl/core/Job.h @@ -1,10 +1,9 @@ #ifndef XRPL_CORE_JOB_H_INCLUDED #define XRPL_CORE_JOB_H_INCLUDED -#include -#include - #include +#include +#include #include diff --git a/src/xrpld/core/JobQueue.h b/include/xrpl/core/JobQueue.h similarity index 98% rename from src/xrpld/core/JobQueue.h rename to include/xrpl/core/JobQueue.h index c5d36cd993..f8b727471b 100644 --- a/src/xrpld/core/JobQueue.h +++ b/include/xrpl/core/JobQueue.h @@ -1,12 +1,11 @@ #ifndef XRPL_CORE_JOBQUEUE_H_INCLUDED #define XRPL_CORE_JOBQUEUE_H_INCLUDED -#include -#include -#include -#include - #include +#include +#include +#include +#include #include #include @@ -385,7 +384,7 @@ private: } // namespace ripple -#include +#include namespace ripple { diff --git a/src/xrpld/core/JobTypeData.h b/include/xrpl/core/JobTypeData.h similarity index 97% rename from src/xrpld/core/JobTypeData.h rename to include/xrpl/core/JobTypeData.h index 337adcb0da..eb678d1a9a 100644 --- a/src/xrpld/core/JobTypeData.h +++ b/include/xrpl/core/JobTypeData.h @@ -1,10 +1,9 @@ #ifndef XRPL_CORE_JOBTYPEDATA_H_INCLUDED #define XRPL_CORE_JOBTYPEDATA_H_INCLUDED -#include - #include #include +#include namespace ripple { diff --git a/src/xrpld/core/JobTypeInfo.h b/include/xrpl/core/JobTypeInfo.h similarity index 98% rename from src/xrpld/core/JobTypeInfo.h rename to include/xrpl/core/JobTypeInfo.h index a58d5316a8..09c644fc23 100644 --- a/src/xrpld/core/JobTypeInfo.h +++ b/include/xrpl/core/JobTypeInfo.h @@ -1,7 +1,7 @@ #ifndef XRPL_CORE_JOBTYPEINFO_H_INCLUDED #define XRPL_CORE_JOBTYPEINFO_H_INCLUDED -#include +#include namespace ripple { diff --git a/src/xrpld/core/JobTypes.h b/include/xrpl/core/JobTypes.h similarity index 99% rename from src/xrpld/core/JobTypes.h rename to include/xrpl/core/JobTypes.h index bb5a8baf9c..d8e7b23bdf 100644 --- a/src/xrpld/core/JobTypes.h +++ b/include/xrpl/core/JobTypes.h @@ -1,8 +1,8 @@ #ifndef XRPL_CORE_JOBTYPES_H_INCLUDED #define XRPL_CORE_JOBTYPES_H_INCLUDED -#include -#include +#include +#include #include #include diff --git a/src/xrpld/core/LoadEvent.h b/include/xrpl/core/LoadEvent.h similarity index 100% rename from src/xrpld/core/LoadEvent.h rename to include/xrpl/core/LoadEvent.h diff --git a/src/xrpld/core/LoadMonitor.h b/include/xrpl/core/LoadMonitor.h similarity index 97% rename from src/xrpld/core/LoadMonitor.h rename to include/xrpl/core/LoadMonitor.h index a9ed66e0fe..539a4a0b99 100644 --- a/src/xrpld/core/LoadMonitor.h +++ b/include/xrpl/core/LoadMonitor.h @@ -1,10 +1,9 @@ #ifndef XRPL_CORE_LOADMONITOR_H_INCLUDED #define XRPL_CORE_LOADMONITOR_H_INCLUDED -#include - #include #include +#include #include #include diff --git a/src/xrpld/perflog/PerfLog.h b/include/xrpl/core/PerfLog.h similarity index 96% rename from src/xrpld/perflog/PerfLog.h rename to include/xrpl/core/PerfLog.h index f6c3d3b9ac..c74608d82a 100644 --- a/src/xrpld/perflog/PerfLog.h +++ b/include/xrpl/core/PerfLog.h @@ -1,9 +1,8 @@ -#ifndef XRPL_BASICS_PERFLOG_H -#define XRPL_BASICS_PERFLOG_H - -#include -#include +#ifndef XRPL_CORE_PERFLOG_H +#define XRPL_CORE_PERFLOG_H +#include +#include #include #include @@ -190,4 +189,4 @@ measureDurationAndLog( } // namespace perf } // namespace ripple -#endif // XRPL_BASICS_PERFLOG_H +#endif // XRPL_CORE_PERFLOG_H diff --git a/src/xrpld/core/detail/Workers.h b/include/xrpl/core/detail/Workers.h similarity index 99% rename from src/xrpld/core/detail/Workers.h rename to include/xrpl/core/detail/Workers.h index f6fe9226fc..5877638722 100644 --- a/src/xrpld/core/detail/Workers.h +++ b/include/xrpl/core/detail/Workers.h @@ -1,9 +1,8 @@ #ifndef XRPL_CORE_WORKERS_H_INCLUDED #define XRPL_CORE_WORKERS_H_INCLUDED -#include - #include +#include #include #include diff --git a/src/xrpld/core/detail/semaphore.h b/include/xrpl/core/detail/semaphore.h similarity index 100% rename from src/xrpld/core/detail/semaphore.h rename to include/xrpl/core/detail/semaphore.h diff --git a/src/xrpld/core/detail/Job.cpp b/src/libxrpl/core/detail/Job.cpp similarity index 98% rename from src/xrpld/core/detail/Job.cpp rename to src/libxrpl/core/detail/Job.cpp index e1e85d34eb..9caf8d180d 100644 --- a/src/xrpld/core/detail/Job.cpp +++ b/src/libxrpl/core/detail/Job.cpp @@ -1,6 +1,5 @@ -#include - #include +#include namespace ripple { diff --git a/src/xrpld/core/detail/JobQueue.cpp b/src/libxrpl/core/detail/JobQueue.cpp similarity index 99% rename from src/xrpld/core/detail/JobQueue.cpp rename to src/libxrpl/core/detail/JobQueue.cpp index ff5c2211ef..817744cbc1 100644 --- a/src/xrpld/core/detail/JobQueue.cpp +++ b/src/libxrpl/core/detail/JobQueue.cpp @@ -1,7 +1,6 @@ -#include -#include - #include +#include +#include #include diff --git a/src/xrpld/core/detail/LoadEvent.cpp b/src/libxrpl/core/detail/LoadEvent.cpp similarity index 94% rename from src/xrpld/core/detail/LoadEvent.cpp rename to src/libxrpl/core/detail/LoadEvent.cpp index 878bb92d11..3237daabcf 100644 --- a/src/xrpld/core/detail/LoadEvent.cpp +++ b/src/libxrpl/core/detail/LoadEvent.cpp @@ -1,7 +1,6 @@ -#include -#include - #include +#include +#include namespace ripple { diff --git a/src/xrpld/core/detail/LoadMonitor.cpp b/src/libxrpl/core/detail/LoadMonitor.cpp similarity index 99% rename from src/xrpld/core/detail/LoadMonitor.cpp rename to src/libxrpl/core/detail/LoadMonitor.cpp index 5a03ab607b..7a1cce05f3 100644 --- a/src/xrpld/core/detail/LoadMonitor.cpp +++ b/src/libxrpl/core/detail/LoadMonitor.cpp @@ -1,7 +1,6 @@ -#include - #include #include +#include namespace ripple { diff --git a/src/xrpld/core/detail/Workers.cpp b/src/libxrpl/core/detail/Workers.cpp similarity index 98% rename from src/xrpld/core/detail/Workers.cpp rename to src/libxrpl/core/detail/Workers.cpp index 29328533ae..b354353844 100644 --- a/src/xrpld/core/detail/Workers.cpp +++ b/src/libxrpl/core/detail/Workers.cpp @@ -1,8 +1,7 @@ -#include -#include - #include #include +#include +#include namespace ripple { diff --git a/src/test/app/Path_test.cpp b/src/test/app/Path_test.cpp index f84a87ac8c..e481bd673b 100644 --- a/src/test/app/Path_test.cpp +++ b/src/test/app/Path_test.cpp @@ -4,11 +4,11 @@ #include #include -#include #include #include #include +#include #include #include #include diff --git a/src/test/app/Transaction_ordering_test.cpp b/src/test/app/Transaction_ordering_test.cpp index 80e7d43de6..2f67d8b414 100644 --- a/src/test/app/Transaction_ordering_test.cpp +++ b/src/test/app/Transaction_ordering_test.cpp @@ -1,6 +1,6 @@ #include -#include +#include namespace ripple { namespace test { diff --git a/src/test/basics/PerfLog_test.cpp b/src/test/basics/PerfLog_test.cpp index 5862889354..dcb91d0fd3 100644 --- a/src/test/basics/PerfLog_test.cpp +++ b/src/test/basics/PerfLog_test.cpp @@ -1,12 +1,12 @@ #include #include -#include #include #include #include #include +#include #include #include diff --git a/src/test/core/ClosureCounter_test.cpp b/src/test/core/ClosureCounter_test.cpp index dbe846c02d..23359596fd 100644 --- a/src/test/core/ClosureCounter_test.cpp +++ b/src/test/core/ClosureCounter_test.cpp @@ -1,8 +1,7 @@ #include -#include - #include +#include #include #include diff --git a/src/test/core/Coroutine_test.cpp b/src/test/core/Coroutine_test.cpp index 2b9bd0a248..47bd74a4a6 100644 --- a/src/test/core/Coroutine_test.cpp +++ b/src/test/core/Coroutine_test.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include diff --git a/src/test/core/JobQueue_test.cpp b/src/test/core/JobQueue_test.cpp index 0b6bbb13ae..2451827bda 100644 --- a/src/test/core/JobQueue_test.cpp +++ b/src/test/core/JobQueue_test.cpp @@ -1,8 +1,7 @@ #include -#include - #include +#include namespace ripple { namespace test { diff --git a/src/test/core/Workers_test.cpp b/src/test/core/Workers_test.cpp index d8152d3ea8..2ba8c2a0e0 100644 --- a/src/test/core/Workers_test.cpp +++ b/src/test/core/Workers_test.cpp @@ -1,7 +1,6 @@ -#include -#include - #include +#include +#include #include #include diff --git a/src/test/rpc/RobustTransaction_test.cpp b/src/test/rpc/RobustTransaction_test.cpp index 29305092c4..d52e08f7ac 100644 --- a/src/test/rpc/RobustTransaction_test.cpp +++ b/src/test/rpc/RobustTransaction_test.cpp @@ -1,9 +1,8 @@ #include #include -#include - #include +#include #include namespace ripple { diff --git a/src/xrpld/app/consensus/RCLConsensus.h b/src/xrpld/app/consensus/RCLConsensus.h index b9580be08a..a6a15395a3 100644 --- a/src/xrpld/app/consensus/RCLConsensus.h +++ b/src/xrpld/app/consensus/RCLConsensus.h @@ -8,9 +8,9 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/xrpld/app/consensus/RCLValidations.cpp b/src/xrpld/app/consensus/RCLValidations.cpp index d24f24a5f1..827c417ba8 100644 --- a/src/xrpld/app/consensus/RCLValidations.cpp +++ b/src/xrpld/app/consensus/RCLValidations.cpp @@ -4,12 +4,12 @@ #include #include #include -#include #include -#include #include #include +#include +#include #include diff --git a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp index fbac9c8553..d248a36987 100644 --- a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp +++ b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp @@ -2,9 +2,9 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/xrpld/app/ledger/Ledger.cpp b/src/xrpld/app/ledger/Ledger.cpp index 055d9ddc9d..bf5f442eee 100644 --- a/src/xrpld/app/ledger/Ledger.cpp +++ b/src/xrpld/app/ledger/Ledger.cpp @@ -7,12 +7,12 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include diff --git a/src/xrpld/app/ledger/OrderBookDB.cpp b/src/xrpld/app/ledger/OrderBookDB.cpp index 1a407d0d3d..00907ee2ce 100644 --- a/src/xrpld/app/ledger/OrderBookDB.cpp +++ b/src/xrpld/app/ledger/OrderBookDB.cpp @@ -4,9 +4,9 @@ #include #include #include -#include #include +#include #include namespace ripple { diff --git a/src/xrpld/app/ledger/detail/InboundLedger.cpp b/src/xrpld/app/ledger/detail/InboundLedger.cpp index 24de3cce14..cd42b4fe82 100644 --- a/src/xrpld/app/ledger/detail/InboundLedger.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedger.cpp @@ -4,10 +4,10 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/xrpld/app/ledger/detail/InboundLedgers.cpp b/src/xrpld/app/ledger/detail/InboundLedgers.cpp index 7e1ba88094..fafcdb9161 100644 --- a/src/xrpld/app/ledger/detail/InboundLedgers.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedgers.cpp @@ -2,13 +2,13 @@ #include #include #include -#include -#include #include #include #include #include +#include +#include #include #include diff --git a/src/xrpld/app/ledger/detail/InboundTransactions.cpp b/src/xrpld/app/ledger/detail/InboundTransactions.cpp index 93e0fbdec0..b84a03e7bb 100644 --- a/src/xrpld/app/ledger/detail/InboundTransactions.cpp +++ b/src/xrpld/app/ledger/detail/InboundTransactions.cpp @@ -3,9 +3,9 @@ #include #include #include -#include #include +#include #include #include diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp index c803c0bdd4..9c190ee376 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp @@ -4,9 +4,10 @@ #include #include #include -#include #include +#include + namespace ripple { LedgerDeltaAcquire::LedgerDeltaAcquire( diff --git a/src/xrpld/app/ledger/detail/TimeoutCounter.cpp b/src/xrpld/app/ledger/detail/TimeoutCounter.cpp index 6db280ce8e..d4e7e9a73c 100644 --- a/src/xrpld/app/ledger/detail/TimeoutCounter.cpp +++ b/src/xrpld/app/ledger/detail/TimeoutCounter.cpp @@ -1,5 +1,6 @@ #include -#include + +#include namespace ripple { diff --git a/src/xrpld/app/ledger/detail/TimeoutCounter.h b/src/xrpld/app/ledger/detail/TimeoutCounter.h index e97882ef1e..1ce4c48415 100644 --- a/src/xrpld/app/ledger/detail/TimeoutCounter.h +++ b/src/xrpld/app/ledger/detail/TimeoutCounter.h @@ -2,9 +2,9 @@ #define XRPL_APP_LEDGER_TIMEOUTCOUNTER_H_INCLUDED #include -#include #include +#include #include diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index 79b48e42b1..e28cd559e9 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -41,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/src/xrpld/app/main/GRPCServer.h b/src/xrpld/app/main/GRPCServer.h index 1ea8706e40..eba666cc35 100644 --- a/src/xrpld/app/main/GRPCServer.h +++ b/src/xrpld/app/main/GRPCServer.h @@ -2,13 +2,13 @@ #define XRPL_CORE_GRPCSERVER_H_INCLUDED #include -#include #include #include #include #include #include +#include #include #include diff --git a/src/xrpld/app/main/NodeStoreScheduler.h b/src/xrpld/app/main/NodeStoreScheduler.h index c1234a84c4..6a5cb8e8ee 100644 --- a/src/xrpld/app/main/NodeStoreScheduler.h +++ b/src/xrpld/app/main/NodeStoreScheduler.h @@ -1,8 +1,7 @@ #ifndef XRPL_APP_MAIN_NODESTORESCHEDULER_H_INCLUDED #define XRPL_APP_MAIN_NODESTORESCHEDULER_H_INCLUDED -#include - +#include #include namespace ripple { diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index 1b0b4e5143..39ec0b78c9 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -39,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/src/xrpld/app/misc/NetworkOPs.h b/src/xrpld/app/misc/NetworkOPs.h index 544e6bfe93..15545153c7 100644 --- a/src/xrpld/app/misc/NetworkOPs.h +++ b/src/xrpld/app/misc/NetworkOPs.h @@ -3,9 +3,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/xrpld/app/paths/PathRequests.cpp b/src/xrpld/app/paths/PathRequests.cpp index d489dafcea..2d5b52d1f9 100644 --- a/src/xrpld/app/paths/PathRequests.cpp +++ b/src/xrpld/app/paths/PathRequests.cpp @@ -1,9 +1,9 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/xrpld/app/paths/Pathfinder.cpp b/src/xrpld/app/paths/Pathfinder.cpp index 2debdc76b2..d3ed3fc38c 100644 --- a/src/xrpld/app/paths/Pathfinder.cpp +++ b/src/xrpld/app/paths/Pathfinder.cpp @@ -4,10 +4,10 @@ #include #include #include -#include #include #include +#include #include #include diff --git a/src/xrpld/app/paths/Pathfinder.h b/src/xrpld/app/paths/Pathfinder.h index d019a8307e..91c0a033f1 100644 --- a/src/xrpld/app/paths/Pathfinder.h +++ b/src/xrpld/app/paths/Pathfinder.h @@ -3,9 +3,9 @@ #include #include -#include #include +#include #include #include diff --git a/src/xrpld/core/DatabaseCon.h b/src/xrpld/core/DatabaseCon.h index 84d2c375e0..b2f400780b 100644 --- a/src/xrpld/core/DatabaseCon.h +++ b/src/xrpld/core/DatabaseCon.h @@ -4,7 +4,8 @@ #include #include #include -#include + +#include #include diff --git a/src/xrpld/core/SociDB.h b/src/xrpld/core/SociDB.h index bf209d79f7..7e2c7323d8 100644 --- a/src/xrpld/core/SociDB.h +++ b/src/xrpld/core/SociDB.h @@ -14,9 +14,8 @@ #pragma clang diagnostic ignored "-Wdeprecated" #endif -#include - #include +#include #define SOCI_USE_BOOST #include diff --git a/src/xrpld/overlay/detail/OverlayImpl.h b/src/xrpld/overlay/detail/OverlayImpl.h index 765d2f38eb..18f2aa0c3f 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.h +++ b/src/xrpld/overlay/detail/OverlayImpl.h @@ -2,7 +2,6 @@ #define XRPL_OVERLAY_OVERLAYIMPL_H_INCLUDED #include -#include #include #include #include @@ -16,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index 097eaae4d9..7adfef4064 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -12,12 +12,12 @@ #include #include #include -#include #include #include #include #include +#include #include #include diff --git a/src/xrpld/overlay/detail/PeerSet.cpp b/src/xrpld/overlay/detail/PeerSet.cpp index ecf1164b2c..9f5b810ffc 100644 --- a/src/xrpld/overlay/detail/PeerSet.cpp +++ b/src/xrpld/overlay/detail/PeerSet.cpp @@ -1,8 +1,9 @@ #include -#include #include #include +#include + namespace ripple { class PeerSetImpl : public PeerSet diff --git a/src/xrpld/perflog/detail/PerfLogImp.cpp b/src/xrpld/perflog/detail/PerfLogImp.cpp index 170da708eb..8d6d68137a 100644 --- a/src/xrpld/perflog/detail/PerfLogImp.cpp +++ b/src/xrpld/perflog/detail/PerfLogImp.cpp @@ -1,9 +1,9 @@ -#include #include #include #include #include +#include #include #include diff --git a/src/xrpld/perflog/detail/PerfLogImp.h b/src/xrpld/perflog/detail/PerfLogImp.h index ec4c87c29d..d8e5e7943d 100644 --- a/src/xrpld/perflog/detail/PerfLogImp.h +++ b/src/xrpld/perflog/detail/PerfLogImp.h @@ -1,10 +1,10 @@ #ifndef XRPL_BASICS_PERFLOGIMP_H #define XRPL_BASICS_PERFLOGIMP_H -#include #include #include +#include #include diff --git a/src/xrpld/rpc/Context.h b/src/xrpld/rpc/Context.h index 0e15da3a39..1faafa1627 100644 --- a/src/xrpld/rpc/Context.h +++ b/src/xrpld/rpc/Context.h @@ -1,11 +1,11 @@ #ifndef XRPL_RPC_CONTEXT_H_INCLUDED #define XRPL_RPC_CONTEXT_H_INCLUDED -#include #include #include #include +#include namespace ripple { diff --git a/src/xrpld/rpc/RPCSub.h b/src/xrpld/rpc/RPCSub.h index db96ae79ee..ea0cc993e8 100644 --- a/src/xrpld/rpc/RPCSub.h +++ b/src/xrpld/rpc/RPCSub.h @@ -1,9 +1,10 @@ #ifndef XRPL_NET_RPCSUB_H_INCLUDED #define XRPL_NET_RPCSUB_H_INCLUDED -#include #include +#include + #include namespace ripple { diff --git a/src/xrpld/rpc/ServerHandler.h b/src/xrpld/rpc/ServerHandler.h index c499411366..4cf5a0ce88 100644 --- a/src/xrpld/rpc/ServerHandler.h +++ b/src/xrpld/rpc/ServerHandler.h @@ -3,9 +3,9 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/xrpld/rpc/detail/LegacyPathFind.cpp b/src/xrpld/rpc/detail/LegacyPathFind.cpp index 7bf4758e37..c3bcd928cd 100644 --- a/src/xrpld/rpc/detail/LegacyPathFind.cpp +++ b/src/xrpld/rpc/detail/LegacyPathFind.cpp @@ -1,10 +1,11 @@ #include #include -#include -#include #include #include +#include +#include + namespace ripple { namespace RPC { diff --git a/src/xrpld/rpc/detail/RPCHandler.cpp b/src/xrpld/rpc/detail/RPCHandler.cpp index c712430f92..fca926a1c7 100644 --- a/src/xrpld/rpc/detail/RPCHandler.cpp +++ b/src/xrpld/rpc/detail/RPCHandler.cpp @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include #include #include @@ -14,6 +12,8 @@ #include #include +#include +#include #include #include #include diff --git a/src/xrpld/rpc/detail/ServerHandler.cpp b/src/xrpld/rpc/detail/ServerHandler.cpp index 8a42153105..de44f93749 100644 --- a/src/xrpld/rpc/detail/ServerHandler.cpp +++ b/src/xrpld/rpc/detail/ServerHandler.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -16,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/src/xrpld/rpc/handlers/LogRotate.cpp b/src/xrpld/rpc/handlers/LogRotate.cpp index 379d694c0f..595d84b191 100644 --- a/src/xrpld/rpc/handlers/LogRotate.cpp +++ b/src/xrpld/rpc/handlers/LogRotate.cpp @@ -1,8 +1,8 @@ #include -#include #include #include +#include namespace ripple { From 1eb0fdac6543706b4b9ddca57fd4102928a1f871 Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 11 Dec 2025 11:51:49 -0500 Subject: [PATCH 041/105] refactor: Rename `ripple` namespace to `xrpl` (#5982) This change renames all occurrences of `namespace ripple` and `ripple::` to `namespace xrpl` and `xrpl::`, respectively, as well as the names of test suites. It also provides a script to allow developers to replicate the changes in their local branch or fork to avoid conflicts. --- .github/scripts/rename/README.md | 3 + .github/scripts/rename/namespace.sh | 58 +++++++++ .github/workflows/reusable-check-rename.yml | 2 + CONTRIBUTING.md | 2 +- include/xrpl/basics/Archive.h | 4 +- include/xrpl/basics/BasicConfig.h | 4 +- include/xrpl/basics/Blob.h | 4 +- include/xrpl/basics/Buffer.h | 6 +- include/xrpl/basics/ByteUtilities.h | 4 +- include/xrpl/basics/CompressionAlgorithms.h | 4 +- include/xrpl/basics/CountedObject.h | 4 +- include/xrpl/basics/DecayingSample.h | 4 +- include/xrpl/basics/Expected.h | 4 +- include/xrpl/basics/FileUtilities.h | 4 +- include/xrpl/basics/IntrusivePointer.h | 4 +- include/xrpl/basics/IntrusivePointer.ipp | 8 +- include/xrpl/basics/IntrusiveRefCounts.h | 26 ++-- include/xrpl/basics/KeyCache.h | 4 +- include/xrpl/basics/LocalValue.h | 4 +- include/xrpl/basics/Log.h | 4 +- include/xrpl/basics/MathUtilities.h | 4 +- include/xrpl/basics/Number.h | 4 +- include/xrpl/basics/README.md | 8 +- include/xrpl/basics/RangeSet.h | 6 +- include/xrpl/basics/Resolver.h | 4 +- include/xrpl/basics/ResolverAsio.h | 4 +- include/xrpl/basics/SHAMapHash.h | 4 +- include/xrpl/basics/SharedWeakCachePointer.h | 4 +- .../xrpl/basics/SharedWeakCachePointer.ipp | 4 +- include/xrpl/basics/SlabAllocator.h | 10 +- include/xrpl/basics/Slice.h | 6 +- include/xrpl/basics/StringUtilities.h | 4 +- include/xrpl/basics/TaggedCache.h | 4 +- include/xrpl/basics/TaggedCache.ipp | 4 +- include/xrpl/basics/ToString.h | 4 +- include/xrpl/basics/UnorderedContainers.h | 4 +- include/xrpl/basics/UptimeClock.h | 4 +- include/xrpl/basics/algorithm.h | 4 +- include/xrpl/basics/base64.h | 4 +- include/xrpl/basics/base_uint.h | 10 +- include/xrpl/basics/chrono.h | 4 +- include/xrpl/basics/comparators.h | 4 +- include/xrpl/basics/contract.h | 4 +- include/xrpl/basics/hardened_hash.h | 4 +- include/xrpl/basics/join.h | 4 +- include/xrpl/basics/make_SSLContext.h | 4 +- include/xrpl/basics/mulDiv.h | 4 +- .../xrpl/basics/partitioned_unordered_map.h | 6 +- include/xrpl/basics/random.h | 6 +- include/xrpl/basics/safe_cast.h | 4 +- include/xrpl/basics/scope.h | 6 +- include/xrpl/basics/spinlock.h | 6 +- include/xrpl/basics/strHex.h | 4 +- include/xrpl/basics/tagged_integer.h | 6 +- include/xrpl/core/ClosureCounter.h | 4 +- include/xrpl/core/Coro.ipp | 9 +- include/xrpl/core/Job.h | 4 +- include/xrpl/core/JobQueue.h | 8 +- include/xrpl/core/JobTypeData.h | 4 +- include/xrpl/core/JobTypeInfo.h | 4 +- include/xrpl/core/JobTypes.h | 10 +- include/xrpl/core/LoadEvent.h | 4 +- include/xrpl/core/LoadMonitor.h | 4 +- include/xrpl/core/PerfLog.h | 4 +- include/xrpl/core/detail/Workers.h | 4 +- include/xrpl/core/detail/semaphore.h | 6 +- include/xrpl/crypto/RFC1751.h | 4 +- include/xrpl/crypto/csprng.h | 4 +- include/xrpl/crypto/secure_erase.h | 4 +- include/xrpl/json/JsonPropertyStream.h | 4 +- include/xrpl/json/Writer.h | 2 +- include/xrpl/json/detail/json_assert.h | 2 +- include/xrpl/json/json_value.h | 4 +- include/xrpl/ledger/ApplyView.h | 6 +- include/xrpl/ledger/ApplyViewImpl.h | 4 +- include/xrpl/ledger/BookDirs.h | 4 +- include/xrpl/ledger/CachedSLEs.h | 2 +- include/xrpl/ledger/CachedView.h | 4 +- include/xrpl/ledger/CredentialHelpers.h | 4 +- include/xrpl/ledger/Dir.h | 4 +- include/xrpl/ledger/OpenView.h | 4 +- include/xrpl/ledger/PaymentSandbox.h | 4 +- include/xrpl/ledger/RawView.h | 4 +- include/xrpl/ledger/ReadView.h | 4 +- include/xrpl/ledger/Sandbox.h | 4 +- include/xrpl/ledger/View.h | 4 +- include/xrpl/ledger/detail/ApplyStateTable.h | 4 +- include/xrpl/ledger/detail/ApplyViewBase.h | 4 +- include/xrpl/ledger/detail/RawStateTable.h | 4 +- include/xrpl/ledger/detail/ReadViewFwdRange.h | 4 +- .../xrpl/ledger/detail/ReadViewFwdRange.ipp | 6 +- include/xrpl/net/AutoSocket.h | 2 +- include/xrpl/net/HTTPClient.h | 4 +- include/xrpl/net/HTTPClientSSLContext.h | 4 +- include/xrpl/net/RegisterSSLCerts.h | 4 +- include/xrpl/nodestore/Backend.h | 4 +- include/xrpl/nodestore/Database.h | 6 +- include/xrpl/nodestore/DatabaseRotating.h | 4 +- include/xrpl/nodestore/DummyScheduler.h | 4 +- include/xrpl/nodestore/Factory.h | 4 +- include/xrpl/nodestore/Manager.h | 4 +- include/xrpl/nodestore/NodeObject.h | 4 +- include/xrpl/nodestore/Scheduler.h | 4 +- include/xrpl/nodestore/Task.h | 4 +- include/xrpl/nodestore/Types.h | 4 +- include/xrpl/nodestore/detail/BatchWriter.h | 4 +- .../xrpl/nodestore/detail/DatabaseNodeImp.h | 6 +- .../nodestore/detail/DatabaseRotatingImp.h | 4 +- include/xrpl/nodestore/detail/DecodedBlob.h | 4 +- include/xrpl/nodestore/detail/EncodedBlob.h | 8 +- include/xrpl/nodestore/detail/ManagerImp.h | 4 +- include/xrpl/nodestore/detail/codec.h | 4 +- include/xrpl/nodestore/detail/varint.h | 4 +- include/xrpl/protocol/AMMCore.h | 4 +- include/xrpl/protocol/AccountID.h | 12 +- include/xrpl/protocol/AmountConversions.h | 15 +-- include/xrpl/protocol/ApiVersion.h | 6 +- include/xrpl/protocol/Asset.h | 4 +- include/xrpl/protocol/Batch.h | 4 +- include/xrpl/protocol/Book.h | 32 ++--- include/xrpl/protocol/BuildInfo.h | 4 +- include/xrpl/protocol/ErrorCodes.h | 4 +- include/xrpl/protocol/Feature.h | 10 +- include/xrpl/protocol/Fees.h | 4 +- include/xrpl/protocol/HashPrefix.h | 4 +- include/xrpl/protocol/IOUAmount.h | 4 +- include/xrpl/protocol/Indexes.h | 6 +- include/xrpl/protocol/InnerObjectFormats.h | 4 +- include/xrpl/protocol/Issue.h | 4 +- include/xrpl/protocol/KeyType.h | 4 +- include/xrpl/protocol/Keylet.h | 4 +- include/xrpl/protocol/KnownFormats.h | 4 +- include/xrpl/protocol/LedgerFormats.h | 4 +- include/xrpl/protocol/LedgerHeader.h | 4 +- include/xrpl/protocol/MPTAmount.h | 4 +- include/xrpl/protocol/MPTIssue.h | 4 +- include/xrpl/protocol/MultiApiJson.h | 8 +- .../xrpl/protocol/NFTSyntheticSerializer.h | 4 +- include/xrpl/protocol/NFTokenID.h | 4 +- include/xrpl/protocol/NFTokenOfferID.h | 4 +- include/xrpl/protocol/PayChan.h | 4 +- include/xrpl/protocol/Permissions.h | 4 +- include/xrpl/protocol/Protocol.h | 4 +- include/xrpl/protocol/PublicKey.h | 10 +- include/xrpl/protocol/Quality.h | 6 +- include/xrpl/protocol/QualityFunction.h | 4 +- include/xrpl/protocol/RPCErr.h | 4 +- include/xrpl/protocol/Rate.h | 4 +- include/xrpl/protocol/RippleLedgerHash.h | 2 +- include/xrpl/protocol/Rules.h | 4 +- include/xrpl/protocol/SField.h | 4 +- include/xrpl/protocol/SOTemplate.h | 4 +- include/xrpl/protocol/STAccount.h | 6 +- include/xrpl/protocol/STAmount.h | 12 +- include/xrpl/protocol/STArray.h | 4 +- include/xrpl/protocol/STBase.h | 4 +- include/xrpl/protocol/STBitString.h | 8 +- include/xrpl/protocol/STBlob.h | 4 +- include/xrpl/protocol/STCurrency.h | 4 +- include/xrpl/protocol/STExchange.h | 4 +- include/xrpl/protocol/STInteger.h | 10 +- include/xrpl/protocol/STIssue.h | 4 +- include/xrpl/protocol/STLedgerEntry.h | 4 +- include/xrpl/protocol/STNumber.h | 4 +- include/xrpl/protocol/STObject.h | 19 ++- include/xrpl/protocol/STParsedJSON.h | 4 +- include/xrpl/protocol/STPathSet.h | 8 +- include/xrpl/protocol/STTx.h | 4 +- include/xrpl/protocol/STValidation.h | 8 +- include/xrpl/protocol/STVector256.h | 4 +- include/xrpl/protocol/STXChainBridge.h | 4 +- include/xrpl/protocol/SecretKey.h | 4 +- include/xrpl/protocol/Seed.h | 4 +- include/xrpl/protocol/SeqProxy.h | 4 +- include/xrpl/protocol/Serializer.h | 9 +- include/xrpl/protocol/Sign.h | 4 +- include/xrpl/protocol/SystemParameters.h | 4 +- include/xrpl/protocol/TER.h | 4 +- include/xrpl/protocol/TxFlags.h | 4 +- include/xrpl/protocol/TxFormats.h | 4 +- include/xrpl/protocol/TxMeta.h | 4 +- include/xrpl/protocol/UintTypes.h | 12 +- include/xrpl/protocol/Units.h | 11 +- include/xrpl/protocol/XChainAttestations.h | 4 +- include/xrpl/protocol/XRPAmount.h | 4 +- include/xrpl/protocol/detail/STVar.h | 4 +- include/xrpl/protocol/detail/b58_utils.h | 12 +- include/xrpl/protocol/detail/secp256k1.h | 4 +- include/xrpl/protocol/detail/token_errors.h | 14 +- include/xrpl/protocol/digest.h | 4 +- include/xrpl/protocol/json_get_or_throw.h | 22 ++-- include/xrpl/protocol/jss.h | 4 +- include/xrpl/protocol/nft.h | 4 +- include/xrpl/protocol/nftPageMask.h | 4 +- include/xrpl/protocol/serialize.h | 4 +- include/xrpl/protocol/tokens.h | 4 +- include/xrpl/resource/Charge.h | 4 +- include/xrpl/resource/Consumer.h | 4 +- include/xrpl/resource/Disposition.h | 4 +- include/xrpl/resource/Fees.h | 4 +- include/xrpl/resource/Gossip.h | 4 +- include/xrpl/resource/ResourceManager.h | 4 +- include/xrpl/resource/Types.h | 4 +- include/xrpl/resource/detail/Entry.h | 4 +- include/xrpl/resource/detail/Import.h | 4 +- include/xrpl/resource/detail/Key.h | 4 +- include/xrpl/resource/detail/Kind.h | 4 +- include/xrpl/resource/detail/Logic.h | 8 +- include/xrpl/resource/detail/Tuning.h | 4 +- include/xrpl/server/Handoff.h | 4 +- include/xrpl/server/Port.h | 4 +- include/xrpl/server/Server.h | 4 +- include/xrpl/server/Session.h | 4 +- include/xrpl/server/SimpleWriter.h | 4 +- include/xrpl/server/WSSession.h | 4 +- include/xrpl/server/Writer.h | 4 +- include/xrpl/server/detail/BaseHTTPPeer.h | 4 +- include/xrpl/server/detail/BasePeer.h | 6 +- include/xrpl/server/detail/BaseWSPeer.h | 8 +- include/xrpl/server/detail/Door.h | 4 +- include/xrpl/server/detail/JSONRPCUtil.h | 4 +- include/xrpl/server/detail/LowestLayer.h | 4 +- include/xrpl/server/detail/PlainHTTPPeer.h | 4 +- include/xrpl/server/detail/PlainWSPeer.h | 4 +- include/xrpl/server/detail/SSLHTTPPeer.h | 4 +- include/xrpl/server/detail/SSLWSPeer.h | 4 +- include/xrpl/server/detail/ServerImpl.h | 4 +- include/xrpl/server/detail/Spawn.h | 4 +- include/xrpl/server/detail/io_list.h | 4 +- include/xrpl/shamap/Family.h | 4 +- include/xrpl/shamap/FullBelowCache.h | 4 +- include/xrpl/shamap/SHAMap.h | 11 +- .../xrpl/shamap/SHAMapAccountStateLeafNode.h | 4 +- include/xrpl/shamap/SHAMapAddNode.h | 4 +- include/xrpl/shamap/SHAMapInnerNode.h | 4 +- include/xrpl/shamap/SHAMapItem.h | 6 +- include/xrpl/shamap/SHAMapLeafNode.h | 4 +- include/xrpl/shamap/SHAMapMissingNode.h | 4 +- include/xrpl/shamap/SHAMapNodeID.h | 4 +- include/xrpl/shamap/SHAMapSyncFilter.h | 4 +- include/xrpl/shamap/SHAMapTreeNode.h | 4 +- include/xrpl/shamap/SHAMapTxLeafNode.h | 4 +- .../xrpl/shamap/SHAMapTxPlusMetaLeafNode.h | 4 +- include/xrpl/shamap/TreeNodeCache.h | 4 +- include/xrpl/shamap/detail/TaggedPointer.h | 4 +- include/xrpl/shamap/detail/TaggedPointer.ipp | 18 +-- src/libxrpl/basics/Archive.cpp | 4 +- src/libxrpl/basics/BasicConfig.cpp | 4 +- src/libxrpl/basics/CountedObject.cpp | 4 +- src/libxrpl/basics/FileUtilities.cpp | 4 +- src/libxrpl/basics/Log.cpp | 12 +- src/libxrpl/basics/Number.cpp | 17 ++- src/libxrpl/basics/ResolverAsio.cpp | 22 ++-- src/libxrpl/basics/StringUtilities.cpp | 4 +- src/libxrpl/basics/UptimeClock.cpp | 4 +- src/libxrpl/basics/base64.cpp | 4 +- src/libxrpl/basics/contract.cpp | 4 +- src/libxrpl/basics/make_SSLContext.cpp | 4 +- src/libxrpl/basics/mulDiv.cpp | 6 +- src/libxrpl/core/detail/Job.cpp | 4 +- src/libxrpl/core/detail/JobQueue.cpp | 50 ++++--- src/libxrpl/core/detail/LoadEvent.cpp | 6 +- src/libxrpl/core/detail/LoadMonitor.cpp | 4 +- src/libxrpl/core/detail/Workers.cpp | 6 +- src/libxrpl/crypto/RFC1751.cpp | 21 ++- src/libxrpl/crypto/csprng.cpp | 4 +- src/libxrpl/crypto/secure_erase.cpp | 4 +- src/libxrpl/json/JsonPropertyStream.cpp | 4 +- src/libxrpl/json/Object.cpp | 4 +- src/libxrpl/json/Writer.cpp | 4 +- src/libxrpl/json/json_reader.cpp | 2 +- src/libxrpl/json/json_value.cpp | 2 +- src/libxrpl/ledger/ApplyStateTable.cpp | 22 ++-- src/libxrpl/ledger/ApplyView.cpp | 10 +- src/libxrpl/ledger/ApplyViewBase.cpp | 4 +- src/libxrpl/ledger/ApplyViewImpl.cpp | 4 +- src/libxrpl/ledger/BookDirs.cpp | 18 +-- src/libxrpl/ledger/CachedView.cpp | 7 +- src/libxrpl/ledger/CredentialHelpers.cpp | 4 +- src/libxrpl/ledger/Dir.cpp | 14 +- src/libxrpl/ledger/OpenView.cpp | 4 +- src/libxrpl/ledger/PaymentSandbox.cpp | 14 +- src/libxrpl/ledger/RawStateTable.cpp | 11 +- src/libxrpl/ledger/ReadView.cpp | 4 +- src/libxrpl/ledger/View.cpp | 122 +++++++++--------- src/libxrpl/net/HTTPClient.cpp | 4 +- src/libxrpl/net/RegisterSSLCerts.cpp | 4 +- src/libxrpl/nodestore/BatchWriter.cpp | 6 +- src/libxrpl/nodestore/Database.cpp | 14 +- src/libxrpl/nodestore/DatabaseNodeImp.cpp | 4 +- src/libxrpl/nodestore/DatabaseRotatingImp.cpp | 4 +- src/libxrpl/nodestore/DecodedBlob.cpp | 6 +- src/libxrpl/nodestore/DummyScheduler.cpp | 4 +- src/libxrpl/nodestore/ManagerImp.cpp | 6 +- src/libxrpl/nodestore/NodeObject.cpp | 4 +- .../nodestore/backend/MemoryFactory.cpp | 10 +- src/libxrpl/nodestore/backend/NuDBFactory.cpp | 6 +- src/libxrpl/nodestore/backend/NullFactory.cpp | 4 +- .../nodestore/backend/RocksDBFactory.cpp | 13 +- src/libxrpl/protocol/AMMCore.cpp | 6 +- src/libxrpl/protocol/AccountID.cpp | 6 +- src/libxrpl/protocol/Asset.cpp | 4 +- src/libxrpl/protocol/Book.cpp | 4 +- src/libxrpl/protocol/BuildInfo.cpp | 4 +- src/libxrpl/protocol/ErrorCodes.cpp | 6 +- src/libxrpl/protocol/Feature.cpp | 16 +-- src/libxrpl/protocol/IOUAmount.cpp | 4 +- src/libxrpl/protocol/Indexes.cpp | 17 ++- src/libxrpl/protocol/InnerObjectFormats.cpp | 4 +- src/libxrpl/protocol/Issue.cpp | 4 +- src/libxrpl/protocol/Keylet.cpp | 6 +- src/libxrpl/protocol/LedgerFormats.cpp | 4 +- src/libxrpl/protocol/LedgerHeader.cpp | 4 +- src/libxrpl/protocol/MPTAmount.cpp | 4 +- src/libxrpl/protocol/MPTIssue.cpp | 4 +- .../protocol/NFTSyntheticSerializer.cpp | 4 +- src/libxrpl/protocol/NFTokenID.cpp | 4 +- src/libxrpl/protocol/NFTokenOfferID.cpp | 4 +- src/libxrpl/protocol/Permissions.cpp | 10 +- src/libxrpl/protocol/PublicKey.cpp | 4 +- src/libxrpl/protocol/Quality.cpp | 25 ++-- src/libxrpl/protocol/QualityFunction.cpp | 4 +- src/libxrpl/protocol/RPCErr.cpp | 4 +- src/libxrpl/protocol/Rate2.cpp | 16 +-- src/libxrpl/protocol/Rules.cpp | 10 +- src/libxrpl/protocol/SField.cpp | 12 +- src/libxrpl/protocol/SOTemplate.cpp | 4 +- src/libxrpl/protocol/STAccount.cpp | 8 +- src/libxrpl/protocol/STAmount.cpp | 38 +++--- src/libxrpl/protocol/STArray.cpp | 4 +- src/libxrpl/protocol/STBase.cpp | 14 +- src/libxrpl/protocol/STBlob.cpp | 8 +- src/libxrpl/protocol/STCurrency.cpp | 4 +- src/libxrpl/protocol/STInteger.cpp | 8 +- src/libxrpl/protocol/STIssue.cpp | 4 +- src/libxrpl/protocol/STLedgerEntry.cpp | 6 +- src/libxrpl/protocol/STNumber.cpp | 11 +- src/libxrpl/protocol/STObject.cpp | 6 +- src/libxrpl/protocol/STParsedJSON.cpp | 4 +- src/libxrpl/protocol/STPathSet.cpp | 8 +- src/libxrpl/protocol/STTx.cpp | 10 +- src/libxrpl/protocol/STValidation.cpp | 6 +- src/libxrpl/protocol/STVar.cpp | 6 +- src/libxrpl/protocol/STVector256.cpp | 8 +- src/libxrpl/protocol/STXChainBridge.cpp | 6 +- src/libxrpl/protocol/SecretKey.cpp | 4 +- src/libxrpl/protocol/Seed.cpp | 4 +- src/libxrpl/protocol/Serializer.cpp | 10 +- src/libxrpl/protocol/Sign.cpp | 4 +- src/libxrpl/protocol/TER.cpp | 4 +- src/libxrpl/protocol/TxFormats.cpp | 4 +- src/libxrpl/protocol/TxMeta.cpp | 23 ++-- src/libxrpl/protocol/UintTypes.cpp | 4 +- src/libxrpl/protocol/XChainAttestations.cpp | 6 +- src/libxrpl/protocol/digest.cpp | 4 +- src/libxrpl/protocol/tokens.cpp | 30 ++--- src/libxrpl/resource/Charge.cpp | 4 +- src/libxrpl/resource/Consumer.cpp | 13 +- src/libxrpl/resource/Fees.cpp | 4 +- src/libxrpl/resource/ResourceManager.cpp | 4 +- src/libxrpl/server/JSONRPCUtil.cpp | 4 +- src/libxrpl/server/Port.cpp | 4 +- src/libxrpl/shamap/SHAMap.cpp | 91 +++++++------ src/libxrpl/shamap/SHAMapDelta.cpp | 12 +- src/libxrpl/shamap/SHAMapInnerNode.cpp | 56 ++++---- src/libxrpl/shamap/SHAMapLeafNode.cpp | 14 +- src/libxrpl/shamap/SHAMapNodeID.cpp | 16 +-- src/libxrpl/shamap/SHAMapSync.cpp | 20 +-- src/libxrpl/shamap/SHAMapTreeNode.cpp | 4 +- src/test/app/AMMCalc_test.cpp | 6 +- src/test/app/AMMClawback_test.cpp | 6 +- src/test/app/AMMExtended_test.cpp | 6 +- src/test/app/AMM_test.cpp | 8 +- src/test/app/AccountDelete_test.cpp | 6 +- src/test/app/AccountTxPaging_test.cpp | 6 +- src/test/app/AmendmentTable_test.cpp | 8 +- src/test/app/Batch_test.cpp | 14 +- src/test/app/Check_test.cpp | 8 +- src/test/app/Clawback_test.cpp | 6 +- src/test/app/Credentials_test.cpp | 9 +- src/test/app/CrossingLimits_test.cpp | 6 +- src/test/app/DID_test.cpp | 6 +- src/test/app/DNS_test.cpp | 12 +- src/test/app/Delegate_test.cpp | 6 +- src/test/app/DeliverMin_test.cpp | 6 +- src/test/app/DepositAuth_test.cpp | 8 +- src/test/app/Discrepancy_test.cpp | 6 +- src/test/app/EscrowToken_test.cpp | 92 ++++++------- src/test/app/Escrow_test.cpp | 34 ++--- src/test/app/FeeVote_test.cpp | 6 +- src/test/app/FixNFTokenPageLinks_test.cpp | 6 +- src/test/app/Flow_test.cpp | 8 +- src/test/app/Freeze_test.cpp | 6 +- src/test/app/HashRouter_test.cpp | 6 +- src/test/app/Invariants_test.cpp | 18 +-- src/test/app/LPTokenTransfer_test.cpp | 6 +- src/test/app/LedgerHistory_test.cpp | 6 +- src/test/app/LedgerLoad_test.cpp | 6 +- src/test/app/LedgerMaster_test.cpp | 6 +- src/test/app/LedgerReplay_test.cpp | 17 ++- src/test/app/LoadFeeTrack_test.cpp | 6 +- src/test/app/LoanBroker_test.cpp | 8 +- src/test/app/Loan_test.cpp | 32 ++--- src/test/app/MPToken_test.cpp | 14 +- src/test/app/Manifest_test.cpp | 6 +- src/test/app/MultiSign_test.cpp | 10 +- src/test/app/NFTokenAuth_test.cpp | 6 +- src/test/app/NFTokenBurn_test.cpp | 6 +- src/test/app/NFTokenDir_test.cpp | 6 +- src/test/app/NFToken_test.cpp | 14 +- src/test/app/NetworkID_test.cpp | 6 +- src/test/app/NetworkOPs_test.cpp | 6 +- src/test/app/OfferStream_test.cpp | 6 +- src/test/app/Offer_test.cpp | 12 +- src/test/app/Oracle_test.cpp | 6 +- src/test/app/OversizeMeta_test.cpp | 12 +- src/test/app/Path_test.cpp | 6 +- src/test/app/PayChan_test.cpp | 10 +- src/test/app/PayStrand_test.cpp | 30 ++--- src/test/app/PermissionedDEX_test.cpp | 6 +- src/test/app/PermissionedDomains_test.cpp | 6 +- src/test/app/PseudoTx_test.cpp | 8 +- src/test/app/RCLValidations_test.cpp | 8 +- src/test/app/ReducedOffer_test.cpp | 6 +- src/test/app/Regression_test.cpp | 10 +- src/test/app/SHAMapStore_test.cpp | 6 +- src/test/app/SetAuth_test.cpp | 6 +- src/test/app/SetRegularKey_test.cpp | 6 +- src/test/app/SetTrust_test.cpp | 6 +- src/test/app/TheoreticalQuality_test.cpp | 6 +- src/test/app/Ticket_test.cpp | 6 +- src/test/app/Transaction_ordering_test.cpp | 6 +- src/test/app/TrustAndBalance_test.cpp | 6 +- src/test/app/TxQ_test.cpp | 30 ++--- src/test/app/ValidatorKeys_test.cpp | 6 +- src/test/app/ValidatorList_test.cpp | 8 +- src/test/app/ValidatorSite_test.cpp | 6 +- src/test/app/Vault_test.cpp | 36 +++--- src/test/app/XChain_test.cpp | 8 +- src/test/app/tx/apply_test.cpp | 6 +- src/test/basics/Buffer_test.cpp | 6 +- src/test/basics/DetectCrash_test.cpp | 4 +- src/test/basics/Expected_test.cpp | 6 +- src/test/basics/FileUtilities_test.cpp | 8 +- src/test/basics/IOUAmount_test.cpp | 8 +- src/test/basics/IntrusiveShared_test.cpp | 6 +- src/test/basics/KeyCache_test.cpp | 6 +- src/test/basics/Number_test.cpp | 6 +- src/test/basics/PerfLog_test.cpp | 8 +- src/test/basics/StringUtilities_test.cpp | 6 +- src/test/basics/TaggedCache_test.cpp | 6 +- src/test/basics/Units_test.cpp | 6 +- src/test/basics/XRPAmount_test.cpp | 8 +- src/test/basics/base58_test.cpp | 38 +++--- src/test/basics/base_uint_test.cpp | 10 +- src/test/basics/hardened_hash_test.cpp | 14 +- src/test/basics/join_test.cpp | 6 +- src/test/beast/IPEndpointCommon.h | 2 +- src/test/beast/IPEndpoint_test.cpp | 2 +- .../beast/beast_CurrentThreadName_test.cpp | 4 +- src/test/conditions/PreimageSha256_test.cpp | 6 +- .../consensus/ByzantineFailureSim_test.cpp | 6 +- src/test/consensus/Consensus_test.cpp | 6 +- .../DistributedValidatorsSim_test.cpp | 6 +- src/test/consensus/LedgerTiming_test.cpp | 6 +- src/test/consensus/LedgerTrie_test.cpp | 6 +- src/test/consensus/NegativeUNL_test.cpp | 20 +-- .../consensus/RCLCensorshipDetector_test.cpp | 6 +- src/test/consensus/ScaleFreeSim_test.cpp | 6 +- src/test/consensus/Validations_test.cpp | 6 +- src/test/core/ClosureCounter_test.cpp | 6 +- src/test/core/Config_test.cpp | 10 +- src/test/core/Coroutine_test.cpp | 6 +- src/test/core/JobQueue_test.cpp | 6 +- src/test/core/SociDB_test.cpp | 6 +- src/test/core/Workers_test.cpp | 6 +- src/test/csf/BasicNetwork.h | 4 +- src/test/csf/BasicNetwork_test.cpp | 6 +- src/test/csf/CollectorRef.h | 4 +- src/test/csf/Digraph.h | 4 +- src/test/csf/Digraph_test.cpp | 6 +- src/test/csf/Histogram.h | 4 +- src/test/csf/Histogram_test.cpp | 6 +- src/test/csf/Peer.h | 4 +- src/test/csf/PeerGroup.h | 4 +- src/test/csf/Proposal.h | 4 +- src/test/csf/Scheduler.h | 4 +- src/test/csf/Scheduler_test.cpp | 6 +- src/test/csf/Sim.h | 4 +- src/test/csf/SimTime.h | 4 +- src/test/csf/TrustGraph.h | 4 +- src/test/csf/Tx.h | 4 +- src/test/csf/Validation.h | 4 +- src/test/csf/collectors.h | 4 +- src/test/csf/events.h | 4 +- src/test/csf/impl/Sim.cpp | 4 +- src/test/csf/impl/ledgers.cpp | 4 +- src/test/csf/ledgers.h | 8 +- src/test/csf/random.h | 4 +- src/test/csf/submitters.h | 4 +- src/test/csf/timers.h | 4 +- src/test/json/Object_test.cpp | 4 +- src/test/json/TestOutputSuite.h | 4 +- src/test/jtx/AMM.h | 4 +- src/test/jtx/AMMTest.h | 4 +- src/test/jtx/AbstractClient.h | 4 +- src/test/jtx/Account.h | 4 +- src/test/jtx/CaptureLogs.h | 4 +- src/test/jtx/CheckMessageLogs.h | 4 +- src/test/jtx/Env.h | 4 +- src/test/jtx/Env_ss.h | 4 +- src/test/jtx/Env_test.cpp | 6 +- src/test/jtx/JSONRPCClient.h | 4 +- src/test/jtx/JTx.h | 4 +- src/test/jtx/ManualTimeKeeper.h | 4 +- src/test/jtx/Oracle.h | 4 +- src/test/jtx/PathSet.h | 4 +- src/test/jtx/SignerUtils.h | 4 +- src/test/jtx/TestHelpers.h | 4 +- src/test/jtx/TestSuite.h | 4 +- src/test/jtx/TrustedPublisherServer.h | 7 +- src/test/jtx/WSClient.h | 4 +- src/test/jtx/WSClient_test.cpp | 6 +- src/test/jtx/account_txn_id.h | 4 +- src/test/jtx/acctdelete.h | 4 +- src/test/jtx/amount.h | 22 ++-- src/test/jtx/attester.h | 4 +- src/test/jtx/balance.h | 4 +- src/test/jtx/basic_prop.h | 4 +- src/test/jtx/batch.h | 4 +- src/test/jtx/check.h | 4 +- src/test/jtx/credentials.h | 4 +- src/test/jtx/delegate.h | 4 +- src/test/jtx/delivermin.h | 4 +- src/test/jtx/deposit.h | 4 +- src/test/jtx/did.h | 4 +- src/test/jtx/directory.h | 4 +- src/test/jtx/domain.h | 4 +- src/test/jtx/envconfig.h | 6 +- src/test/jtx/escrow.h | 4 +- src/test/jtx/fee.h | 4 +- src/test/jtx/flags.h | 4 +- src/test/jtx/impl/AMM.cpp | 6 +- src/test/jtx/impl/AMMTest.cpp | 4 +- src/test/jtx/impl/Account.cpp | 4 +- src/test/jtx/impl/Env.cpp | 4 +- src/test/jtx/impl/JSONRPCClient.cpp | 4 +- src/test/jtx/impl/Oracle.cpp | 4 +- src/test/jtx/impl/TestHelpers.cpp | 4 +- src/test/jtx/impl/WSClient.cpp | 4 +- src/test/jtx/impl/account_txn_id.cpp | 4 +- src/test/jtx/impl/acctdelete.cpp | 4 +- src/test/jtx/impl/amount.cpp | 4 +- src/test/jtx/impl/attester.cpp | 4 +- src/test/jtx/impl/balance.cpp | 4 +- src/test/jtx/impl/batch.cpp | 8 +- src/test/jtx/impl/check.cpp | 4 +- src/test/jtx/impl/creds.cpp | 4 +- src/test/jtx/impl/delegate.cpp | 4 +- src/test/jtx/impl/delivermin.cpp | 4 +- src/test/jtx/impl/deposit.cpp | 4 +- src/test/jtx/impl/dids.cpp | 4 +- src/test/jtx/impl/directory.cpp | 4 +- src/test/jtx/impl/domain.cpp | 4 +- src/test/jtx/impl/envconfig.cpp | 4 +- src/test/jtx/impl/escrow.cpp | 6 +- src/test/jtx/impl/fee.cpp | 4 +- src/test/jtx/impl/flags.cpp | 4 +- src/test/jtx/impl/invoice_id.cpp | 4 +- src/test/jtx/impl/jtx_json.cpp | 4 +- src/test/jtx/impl/last_ledger_sequence.cpp | 4 +- src/test/jtx/impl/ledgerStateFixes.cpp | 4 +- src/test/jtx/impl/memo.cpp | 4 +- src/test/jtx/impl/mpt.cpp | 6 +- src/test/jtx/impl/multisign.cpp | 6 +- src/test/jtx/impl/offer.cpp | 4 +- src/test/jtx/impl/owners.cpp | 4 +- src/test/jtx/impl/paths.cpp | 4 +- src/test/jtx/impl/pay.cpp | 4 +- src/test/jtx/impl/permissioned_dex.cpp | 4 +- src/test/jtx/impl/permissioned_domains.cpp | 4 +- src/test/jtx/impl/quality2.cpp | 4 +- src/test/jtx/impl/rate.cpp | 4 +- src/test/jtx/impl/regkey.cpp | 4 +- src/test/jtx/impl/sendmax.cpp | 4 +- src/test/jtx/impl/seq.cpp | 4 +- src/test/jtx/impl/sig.cpp | 4 +- src/test/jtx/impl/tag.cpp | 4 +- src/test/jtx/impl/testline.cpp | 4 +- src/test/jtx/impl/ticket.cpp | 4 +- src/test/jtx/impl/token.cpp | 6 +- src/test/jtx/impl/trust.cpp | 4 +- src/test/jtx/impl/txflags.cpp | 4 +- src/test/jtx/impl/utility.cpp | 6 +- src/test/jtx/impl/vault.cpp | 4 +- src/test/jtx/impl/xchain_bridge.cpp | 4 +- src/test/jtx/invoice_id.h | 4 +- src/test/jtx/jtx_json.h | 4 +- src/test/jtx/last_ledger_sequence.h | 4 +- src/test/jtx/ledgerStateFix.h | 4 +- src/test/jtx/memo.h | 4 +- src/test/jtx/mpt.h | 4 +- src/test/jtx/multisign.h | 4 +- src/test/jtx/noop.h | 4 +- src/test/jtx/offer.h | 4 +- src/test/jtx/owners.h | 4 +- src/test/jtx/paths.h | 4 +- src/test/jtx/pay.h | 4 +- src/test/jtx/permissioned_dex.h | 4 +- src/test/jtx/permissioned_domains.h | 6 +- src/test/jtx/prop.h | 4 +- src/test/jtx/quality.h | 4 +- src/test/jtx/rate.h | 4 +- src/test/jtx/regkey.h | 4 +- src/test/jtx/require.h | 4 +- src/test/jtx/requires.h | 4 +- src/test/jtx/rpc.h | 4 +- src/test/jtx/sendmax.h | 4 +- src/test/jtx/seq.h | 4 +- src/test/jtx/sig.h | 4 +- src/test/jtx/tag.h | 4 +- src/test/jtx/tags.h | 4 +- src/test/jtx/ter.h | 4 +- src/test/jtx/testline.h | 4 +- src/test/jtx/ticket.h | 4 +- src/test/jtx/token.h | 4 +- src/test/jtx/trust.h | 4 +- src/test/jtx/txflags.h | 4 +- src/test/jtx/utility.h | 4 +- src/test/jtx/vault.h | 4 +- src/test/jtx/xchain_bridge.h | 4 +- src/test/ledger/BookDirs_test.cpp | 6 +- src/test/ledger/Directory_test.cpp | 6 +- src/test/ledger/PaymentSandbox_test.cpp | 6 +- src/test/ledger/PendingSaves_test.cpp | 6 +- src/test/ledger/SkipList_test.cpp | 6 +- src/test/ledger/View_test.cpp | 8 +- src/test/nodestore/Backend_test.cpp | 6 +- src/test/nodestore/Basics_test.cpp | 6 +- src/test/nodestore/Database_test.cpp | 10 +- src/test/nodestore/NuDBFactory_test.cpp | 6 +- src/test/nodestore/TestBase.h | 4 +- src/test/nodestore/Timing_test.cpp | 6 +- src/test/nodestore/import_test.cpp | 6 +- src/test/nodestore/varint_test.cpp | 6 +- src/test/overlay/ProtocolVersion_test.cpp | 6 +- src/test/overlay/cluster_test.cpp | 8 +- src/test/overlay/compression_test.cpp | 48 +++---- src/test/overlay/handshake_test.cpp | 6 +- src/test/overlay/reduce_relay_test.cpp | 12 +- src/test/overlay/short_read_test.cpp | 6 +- src/test/overlay/traffic_count_test.cpp | 6 +- src/test/overlay/tx_reduce_relay_test.cpp | 6 +- src/test/peerfinder/Livecache_test.cpp | 14 +- src/test/peerfinder/PeerFinder_test.cpp | 10 +- src/test/protocol/ApiVersion_test.cpp | 6 +- src/test/protocol/BuildInfo_test.cpp | 6 +- src/test/protocol/Hooks_test.cpp | 6 +- src/test/protocol/InnerObjectFormats_test.cpp | 6 +- src/test/protocol/Issue_test.cpp | 6 +- src/test/protocol/Memo_test.cpp | 6 +- src/test/protocol/MultiApiJson_test.cpp | 8 +- src/test/protocol/PublicKey_test.cpp | 6 +- src/test/protocol/Quality_test.cpp | 6 +- src/test/protocol/STAccount_test.cpp | 6 +- src/test/protocol/STAmount_test.cpp | 6 +- src/test/protocol/STInteger_test.cpp | 6 +- src/test/protocol/STIssue_test.cpp | 6 +- src/test/protocol/STNumber_test.cpp | 6 +- src/test/protocol/STObject_test.cpp | 8 +- src/test/protocol/STParsedJSON_test.cpp | 6 +- src/test/protocol/STTx_test.cpp | 36 +++--- src/test/protocol/STValidation_test.cpp | 14 +- src/test/protocol/SecretKey_test.cpp | 6 +- src/test/protocol/Seed_test.cpp | 6 +- src/test/protocol/SeqProxy_test.cpp | 6 +- src/test/protocol/Serializer_test.cpp | 6 +- src/test/protocol/TER_test.cpp | 6 +- src/test/resource/Logic_test.cpp | 6 +- src/test/rpc/AMMInfo_test.cpp | 6 +- src/test/rpc/AccountCurrencies_test.cpp | 6 +- src/test/rpc/AccountInfo_test.cpp | 9 +- src/test/rpc/AccountLines_test.cpp | 6 +- src/test/rpc/AccountObjects_test.cpp | 6 +- src/test/rpc/AccountOffers_test.cpp | 6 +- src/test/rpc/AccountSet_test.cpp | 9 +- src/test/rpc/AccountTx_test.cpp | 6 +- src/test/rpc/AmendmentBlocked_test.cpp | 6 +- src/test/rpc/BookChanges_test.cpp | 6 +- src/test/rpc/Book_test.cpp | 6 +- src/test/rpc/Connect_test.cpp | 6 +- src/test/rpc/DeliveredAmount_test.cpp | 6 +- src/test/rpc/DepositAuthorized_test.cpp | 6 +- src/test/rpc/Feature_test.cpp | 26 ++-- src/test/rpc/GRPCTestClientBase.h | 4 +- src/test/rpc/GatewayBalances_test.cpp | 6 +- src/test/rpc/GetAggregatePrice_test.cpp | 6 +- src/test/rpc/GetCounts_test.cpp | 6 +- src/test/rpc/Handler_test.cpp | 8 +- src/test/rpc/JSONRPC_test.cpp | 6 +- src/test/rpc/KeyGeneration_test.cpp | 8 +- src/test/rpc/LedgerClosed_test.cpp | 6 +- src/test/rpc/LedgerData_test.cpp | 6 +- src/test/rpc/LedgerEntry_test.cpp | 16 +-- src/test/rpc/LedgerHeader_test.cpp | 6 +- src/test/rpc/LedgerRPC_test.cpp | 6 +- src/test/rpc/LedgerRequest_test.cpp | 6 +- src/test/rpc/ManifestRPC_test.cpp | 6 +- src/test/rpc/NoRippleCheck_test.cpp | 12 +- src/test/rpc/NoRipple_test.cpp | 6 +- src/test/rpc/OwnerInfo_test.cpp | 6 +- src/test/rpc/Peers_test.cpp | 6 +- src/test/rpc/RPCCall_test.cpp | 6 +- src/test/rpc/RPCHelpers_test.cpp | 6 +- src/test/rpc/RPCOverload_test.cpp | 6 +- src/test/rpc/RobustTransaction_test.cpp | 6 +- src/test/rpc/Roles_test.cpp | 6 +- src/test/rpc/ServerDefinitions_test.cpp | 6 +- src/test/rpc/ServerInfo_test.cpp | 6 +- src/test/rpc/Simulate_test.cpp | 6 +- src/test/rpc/Status_test.cpp | 4 +- src/test/rpc/Subscribe_test.cpp | 6 +- src/test/rpc/TransactionEntry_test.cpp | 6 +- src/test/rpc/TransactionHistory_test.cpp | 6 +- src/test/rpc/Transaction_test.cpp | 6 +- src/test/rpc/ValidatorInfo_test.cpp | 6 +- src/test/rpc/ValidatorRPC_test.cpp | 6 +- src/test/rpc/Version_test.cpp | 6 +- src/test/server/ServerStatus_test.cpp | 6 +- src/test/server/Server_test.cpp | 6 +- src/test/shamap/FetchPack_test.cpp | 8 +- src/test/shamap/SHAMapSync_test.cpp | 6 +- src/test/shamap/SHAMap_test.cpp | 8 +- src/test/shamap/common.h | 4 +- src/test/unit_test/FileDirGuard.h | 4 +- src/test/unit_test/SuiteJournal.h | 4 +- src/test/unit_test/multi_runner.cpp | 4 +- src/test/unit_test/multi_runner.h | 4 +- src/tests/libxrpl/basics/RangeSet.cpp | 2 +- src/tests/libxrpl/basics/Slice.cpp | 2 +- src/tests/libxrpl/basics/base64.cpp | 2 +- src/tests/libxrpl/basics/contract.cpp | 2 +- src/tests/libxrpl/basics/mulDiv.cpp | 2 +- src/tests/libxrpl/basics/scope.cpp | 2 +- src/tests/libxrpl/basics/tagged_integer.cpp | 2 +- src/tests/libxrpl/crypto/csprng.cpp | 2 +- src/tests/libxrpl/json/Output.cpp | 2 +- src/tests/libxrpl/json/Value.cpp | 4 +- src/tests/libxrpl/json/Writer.cpp | 2 +- src/tests/libxrpl/net/HTTPClient.cpp | 2 +- .../app/consensus/RCLCensorshipDetector.h | 4 +- src/xrpld/app/consensus/RCLConsensus.cpp | 20 +-- src/xrpld/app/consensus/RCLConsensus.h | 4 +- src/xrpld/app/consensus/RCLCxLedger.h | 8 +- src/xrpld/app/consensus/RCLCxPeerPos.cpp | 6 +- src/xrpld/app/consensus/RCLCxPeerPos.h | 4 +- src/xrpld/app/consensus/RCLCxTx.h | 8 +- src/xrpld/app/consensus/RCLValidations.cpp | 12 +- src/xrpld/app/consensus/RCLValidations.h | 8 +- .../app/ledger/AbstractFetchPackContainer.h | 4 +- src/xrpld/app/ledger/AcceptedLedger.cpp | 4 +- src/xrpld/app/ledger/AcceptedLedger.h | 4 +- src/xrpld/app/ledger/AcceptedLedgerTx.cpp | 8 +- src/xrpld/app/ledger/AcceptedLedgerTx.h | 4 +- src/xrpld/app/ledger/AccountStateSF.cpp | 4 +- src/xrpld/app/ledger/AccountStateSF.h | 4 +- src/xrpld/app/ledger/BookListeners.cpp | 4 +- src/xrpld/app/ledger/BookListeners.h | 4 +- src/xrpld/app/ledger/BuildLedger.h | 4 +- src/xrpld/app/ledger/ConsensusTransSetSF.cpp | 8 +- src/xrpld/app/ledger/ConsensusTransSetSF.h | 4 +- src/xrpld/app/ledger/InboundLedger.h | 4 +- src/xrpld/app/ledger/InboundLedgers.h | 4 +- src/xrpld/app/ledger/InboundTransactions.h | 4 +- src/xrpld/app/ledger/Ledger.cpp | 26 ++-- src/xrpld/app/ledger/Ledger.h | 4 +- src/xrpld/app/ledger/LedgerCleaner.h | 4 +- src/xrpld/app/ledger/LedgerHistory.cpp | 32 +++-- src/xrpld/app/ledger/LedgerHistory.h | 4 +- src/xrpld/app/ledger/LedgerHolder.h | 4 +- src/xrpld/app/ledger/LedgerMaster.h | 4 +- src/xrpld/app/ledger/LedgerReplay.h | 4 +- src/xrpld/app/ledger/LedgerReplayTask.h | 4 +- src/xrpld/app/ledger/LedgerReplayer.h | 4 +- src/xrpld/app/ledger/LedgerToJson.h | 4 +- src/xrpld/app/ledger/LocalTxs.h | 4 +- src/xrpld/app/ledger/OpenLedger.h | 6 +- src/xrpld/app/ledger/OrderBookDB.cpp | 6 +- src/xrpld/app/ledger/OrderBookDB.h | 4 +- src/xrpld/app/ledger/PendingSaves.h | 4 +- src/xrpld/app/ledger/TransactionMaster.h | 4 +- src/xrpld/app/ledger/TransactionStateSF.cpp | 6 +- src/xrpld/app/ledger/TransactionStateSF.h | 4 +- src/xrpld/app/ledger/detail/BuildLedger.cpp | 10 +- src/xrpld/app/ledger/detail/InboundLedger.cpp | 21 ++- .../app/ledger/detail/InboundLedgers.cpp | 13 +- .../app/ledger/detail/InboundTransactions.cpp | 4 +- src/xrpld/app/ledger/detail/LedgerCleaner.cpp | 9 +- .../app/ledger/detail/LedgerDeltaAcquire.cpp | 10 +- .../app/ledger/detail/LedgerDeltaAcquire.h | 4 +- src/xrpld/app/ledger/detail/LedgerMaster.cpp | 30 ++--- src/xrpld/app/ledger/detail/LedgerReplay.cpp | 4 +- .../ledger/detail/LedgerReplayMsgHandler.cpp | 4 +- .../ledger/detail/LedgerReplayMsgHandler.h | 4 +- .../app/ledger/detail/LedgerReplayTask.cpp | 12 +- .../app/ledger/detail/LedgerReplayer.cpp | 6 +- src/xrpld/app/ledger/detail/LedgerToJson.cpp | 4 +- src/xrpld/app/ledger/detail/LocalTxs.cpp | 4 +- src/xrpld/app/ledger/detail/OpenLedger.cpp | 6 +- .../app/ledger/detail/SkipListAcquire.cpp | 8 +- src/xrpld/app/ledger/detail/SkipListAcquire.h | 8 +- .../app/ledger/detail/TimeoutCounter.cpp | 6 +- src/xrpld/app/ledger/detail/TimeoutCounter.h | 6 +- .../app/ledger/detail/TransactionAcquire.cpp | 4 +- .../app/ledger/detail/TransactionAcquire.h | 4 +- .../app/ledger/detail/TransactionMaster.cpp | 4 +- src/xrpld/app/main/Application.cpp | 35 +++-- src/xrpld/app/main/Application.h | 4 +- src/xrpld/app/main/CollectorManager.cpp | 4 +- src/xrpld/app/main/CollectorManager.h | 4 +- src/xrpld/app/main/DBInit.h | 4 +- src/xrpld/app/main/GRPCServer.cpp | 8 +- src/xrpld/app/main/GRPCServer.h | 4 +- src/xrpld/app/main/LoadManager.cpp | 7 +- src/xrpld/app/main/LoadManager.h | 4 +- src/xrpld/app/main/Main.cpp | 10 +- src/xrpld/app/main/NodeIdentity.cpp | 4 +- src/xrpld/app/main/NodeIdentity.h | 4 +- src/xrpld/app/main/NodeStoreScheduler.cpp | 4 +- src/xrpld/app/main/NodeStoreScheduler.h | 4 +- src/xrpld/app/main/Tuning.h | 4 +- src/xrpld/app/misc/AMMHelpers.h | 4 +- src/xrpld/app/misc/AMMUtils.h | 4 +- src/xrpld/app/misc/AmendmentTable.h | 4 +- src/xrpld/app/misc/CanonicalTXSet.cpp | 4 +- src/xrpld/app/misc/CanonicalTXSet.h | 4 +- src/xrpld/app/misc/DelegateUtils.h | 4 +- src/xrpld/app/misc/DeliverMax.h | 4 +- src/xrpld/app/misc/FeeVote.h | 4 +- src/xrpld/app/misc/FeeVoteImpl.cpp | 6 +- src/xrpld/app/misc/HashRouter.cpp | 6 +- src/xrpld/app/misc/HashRouter.h | 4 +- src/xrpld/app/misc/LendingHelpers.h | 6 +- src/xrpld/app/misc/LoadFeeTrack.h | 4 +- src/xrpld/app/misc/Manifest.h | 4 +- src/xrpld/app/misc/NegativeUNLVote.cpp | 11 +- src/xrpld/app/misc/NegativeUNLVote.h | 4 +- src/xrpld/app/misc/NetworkOPs.cpp | 53 ++++---- src/xrpld/app/misc/NetworkOPs.h | 4 +- src/xrpld/app/misc/PermissionedDEXHelpers.cpp | 4 +- src/xrpld/app/misc/PermissionedDEXHelpers.h | 4 +- src/xrpld/app/misc/SHAMapStore.h | 4 +- src/xrpld/app/misc/SHAMapStoreImp.cpp | 16 +-- src/xrpld/app/misc/SHAMapStoreImp.h | 4 +- src/xrpld/app/misc/Transaction.h | 4 +- src/xrpld/app/misc/TxQ.h | 4 +- src/xrpld/app/misc/ValidatorKeys.h | 4 +- src/xrpld/app/misc/ValidatorList.h | 9 +- src/xrpld/app/misc/ValidatorSite.h | 4 +- src/xrpld/app/misc/detail/AMMHelpers.cpp | 6 +- src/xrpld/app/misc/detail/AMMUtils.cpp | 6 +- src/xrpld/app/misc/detail/AccountTxPaging.cpp | 4 +- src/xrpld/app/misc/detail/AccountTxPaging.h | 4 +- src/xrpld/app/misc/detail/AmendmentTable.cpp | 12 +- src/xrpld/app/misc/detail/DelegateUtils.cpp | 4 +- src/xrpld/app/misc/detail/DeliverMax.cpp | 4 +- src/xrpld/app/misc/detail/LendingHelpers.cpp | 118 +++++++++-------- src/xrpld/app/misc/detail/LoadFeeTrack.cpp | 4 +- src/xrpld/app/misc/detail/Manifest.cpp | 13 +- src/xrpld/app/misc/detail/Transaction.cpp | 6 +- src/xrpld/app/misc/detail/TxQ.cpp | 62 +++++---- src/xrpld/app/misc/detail/ValidatorKeys.cpp | 4 +- src/xrpld/app/misc/detail/ValidatorList.cpp | 65 +++++----- src/xrpld/app/misc/detail/ValidatorSite.cpp | 8 +- src/xrpld/app/misc/detail/Work.h | 4 +- src/xrpld/app/misc/detail/WorkBase.h | 6 +- src/xrpld/app/misc/detail/WorkFile.h | 6 +- src/xrpld/app/misc/detail/WorkPlain.h | 4 +- src/xrpld/app/misc/detail/WorkSSL.cpp | 4 +- src/xrpld/app/misc/detail/WorkSSL.h | 4 +- src/xrpld/app/paths/AMMContext.h | 4 +- src/xrpld/app/paths/AMMLiquidity.h | 4 +- src/xrpld/app/paths/AMMOffer.h | 4 +- src/xrpld/app/paths/AccountCurrencies.cpp | 4 +- src/xrpld/app/paths/AccountCurrencies.h | 4 +- src/xrpld/app/paths/Credit.cpp | 12 +- src/xrpld/app/paths/Credit.h | 4 +- src/xrpld/app/paths/Flow.cpp | 6 +- src/xrpld/app/paths/Flow.h | 4 +- src/xrpld/app/paths/PathRequest.cpp | 7 +- src/xrpld/app/paths/PathRequest.h | 4 +- src/xrpld/app/paths/PathRequests.cpp | 4 +- src/xrpld/app/paths/PathRequests.h | 4 +- src/xrpld/app/paths/Pathfinder.cpp | 16 +-- src/xrpld/app/paths/Pathfinder.h | 4 +- src/xrpld/app/paths/RippleCalc.cpp | 4 +- src/xrpld/app/paths/RippleCalc.h | 4 +- src/xrpld/app/paths/RippleLineCache.cpp | 10 +- src/xrpld/app/paths/RippleLineCache.h | 6 +- src/xrpld/app/paths/TrustLine.cpp | 4 +- src/xrpld/app/paths/TrustLine.h | 4 +- src/xrpld/app/paths/detail/AMMLiquidity.cpp | 6 +- src/xrpld/app/paths/detail/AMMOffer.cpp | 4 +- src/xrpld/app/paths/detail/AmountSpec.h | 17 ++- src/xrpld/app/paths/detail/BookStep.cpp | 21 ++- src/xrpld/app/paths/detail/DirectStep.cpp | 14 +- src/xrpld/app/paths/detail/FlatSets.h | 4 +- src/xrpld/app/paths/detail/FlowDebugInfo.h | 12 +- src/xrpld/app/paths/detail/PathfinderUtils.h | 4 +- src/xrpld/app/paths/detail/PaySteps.cpp | 14 +- src/xrpld/app/paths/detail/StepChecks.h | 6 +- src/xrpld/app/paths/detail/Steps.h | 6 +- src/xrpld/app/paths/detail/StrandFlow.h | 20 +-- .../app/paths/detail/XRPEndpointStep.cpp | 10 +- src/xrpld/app/rdb/PeerFinder.h | 4 +- src/xrpld/app/rdb/RelationalDatabase.h | 6 +- src/xrpld/app/rdb/State.h | 4 +- src/xrpld/app/rdb/Vacuum.h | 4 +- src/xrpld/app/rdb/Wallet.h | 4 +- src/xrpld/app/rdb/backend/SQLiteDatabase.h | 4 +- src/xrpld/app/rdb/backend/detail/Node.cpp | 12 +- src/xrpld/app/rdb/backend/detail/Node.h | 4 +- .../app/rdb/backend/detail/SQLiteDatabase.cpp | 10 +- src/xrpld/app/rdb/detail/PeerFinder.cpp | 4 +- .../app/rdb/detail/RelationalDatabase.cpp | 4 +- src/xrpld/app/rdb/detail/State.cpp | 4 +- src/xrpld/app/rdb/detail/Vacuum.cpp | 4 +- src/xrpld/app/rdb/detail/Wallet.cpp | 4 +- src/xrpld/app/tx/apply.h | 4 +- src/xrpld/app/tx/applySteps.h | 4 +- src/xrpld/app/tx/detail/AMMBid.cpp | 8 +- src/xrpld/app/tx/detail/AMMBid.h | 4 +- src/xrpld/app/tx/detail/AMMClawback.cpp | 4 +- src/xrpld/app/tx/detail/AMMClawback.h | 4 +- src/xrpld/app/tx/detail/AMMCreate.cpp | 4 +- src/xrpld/app/tx/detail/AMMCreate.h | 4 +- src/xrpld/app/tx/detail/AMMDelete.cpp | 4 +- src/xrpld/app/tx/detail/AMMDelete.h | 4 +- src/xrpld/app/tx/detail/AMMDeposit.cpp | 6 +- src/xrpld/app/tx/detail/AMMDeposit.h | 4 +- src/xrpld/app/tx/detail/AMMVote.cpp | 6 +- src/xrpld/app/tx/detail/AMMVote.h | 4 +- src/xrpld/app/tx/detail/AMMWithdraw.cpp | 6 +- src/xrpld/app/tx/detail/AMMWithdraw.h | 4 +- src/xrpld/app/tx/detail/ApplyContext.cpp | 6 +- src/xrpld/app/tx/detail/ApplyContext.h | 4 +- src/xrpld/app/tx/detail/Batch.cpp | 8 +- src/xrpld/app/tx/detail/Batch.h | 4 +- src/xrpld/app/tx/detail/BookTip.cpp | 4 +- src/xrpld/app/tx/detail/BookTip.h | 4 +- src/xrpld/app/tx/detail/CancelCheck.cpp | 4 +- src/xrpld/app/tx/detail/CancelCheck.h | 4 +- src/xrpld/app/tx/detail/CancelOffer.cpp | 4 +- src/xrpld/app/tx/detail/CancelOffer.h | 4 +- src/xrpld/app/tx/detail/CashCheck.cpp | 4 +- src/xrpld/app/tx/detail/CashCheck.h | 4 +- src/xrpld/app/tx/detail/Change.cpp | 8 +- src/xrpld/app/tx/detail/Change.h | 4 +- src/xrpld/app/tx/detail/Clawback.cpp | 4 +- src/xrpld/app/tx/detail/Clawback.h | 4 +- src/xrpld/app/tx/detail/CreateCheck.cpp | 4 +- src/xrpld/app/tx/detail/CreateCheck.h | 4 +- src/xrpld/app/tx/detail/CreateOffer.cpp | 16 +-- src/xrpld/app/tx/detail/CreateOffer.h | 4 +- src/xrpld/app/tx/detail/CreateTicket.cpp | 4 +- src/xrpld/app/tx/detail/CreateTicket.h | 4 +- src/xrpld/app/tx/detail/Credentials.cpp | 4 +- src/xrpld/app/tx/detail/Credentials.h | 4 +- src/xrpld/app/tx/detail/DID.cpp | 4 +- src/xrpld/app/tx/detail/DID.h | 4 +- src/xrpld/app/tx/detail/DelegateSet.cpp | 4 +- src/xrpld/app/tx/detail/DelegateSet.h | 4 +- src/xrpld/app/tx/detail/DeleteAccount.cpp | 16 +-- src/xrpld/app/tx/detail/DeleteAccount.h | 4 +- src/xrpld/app/tx/detail/DeleteOracle.cpp | 4 +- src/xrpld/app/tx/detail/DeleteOracle.h | 4 +- src/xrpld/app/tx/detail/DepositPreauth.cpp | 4 +- src/xrpld/app/tx/detail/DepositPreauth.h | 4 +- src/xrpld/app/tx/detail/Escrow.cpp | 10 +- src/xrpld/app/tx/detail/Escrow.h | 4 +- src/xrpld/app/tx/detail/InvariantCheck.cpp | 76 ++++++----- src/xrpld/app/tx/detail/InvariantCheck.h | 6 +- src/xrpld/app/tx/detail/LedgerStateFix.cpp | 4 +- src/xrpld/app/tx/detail/LedgerStateFix.h | 4 +- .../app/tx/detail/LoanBrokerCoverClawback.cpp | 4 +- .../app/tx/detail/LoanBrokerCoverClawback.h | 4 +- .../app/tx/detail/LoanBrokerCoverDeposit.cpp | 4 +- .../app/tx/detail/LoanBrokerCoverDeposit.h | 4 +- .../app/tx/detail/LoanBrokerCoverWithdraw.cpp | 4 +- .../app/tx/detail/LoanBrokerCoverWithdraw.h | 4 +- src/xrpld/app/tx/detail/LoanBrokerDelete.cpp | 4 +- src/xrpld/app/tx/detail/LoanBrokerDelete.h | 4 +- src/xrpld/app/tx/detail/LoanBrokerSet.cpp | 4 +- src/xrpld/app/tx/detail/LoanBrokerSet.h | 4 +- src/xrpld/app/tx/detail/LoanDelete.cpp | 6 +- src/xrpld/app/tx/detail/LoanDelete.h | 4 +- src/xrpld/app/tx/detail/LoanManage.cpp | 4 +- src/xrpld/app/tx/detail/LoanManage.h | 4 +- src/xrpld/app/tx/detail/LoanPay.cpp | 44 +++---- src/xrpld/app/tx/detail/LoanPay.h | 4 +- src/xrpld/app/tx/detail/LoanSet.cpp | 16 +-- src/xrpld/app/tx/detail/LoanSet.h | 4 +- src/xrpld/app/tx/detail/MPTokenAuthorize.cpp | 4 +- src/xrpld/app/tx/detail/MPTokenAuthorize.h | 4 +- .../app/tx/detail/MPTokenIssuanceCreate.cpp | 4 +- .../app/tx/detail/MPTokenIssuanceCreate.h | 4 +- .../app/tx/detail/MPTokenIssuanceDestroy.cpp | 4 +- .../app/tx/detail/MPTokenIssuanceDestroy.h | 4 +- .../app/tx/detail/MPTokenIssuanceSet.cpp | 4 +- src/xrpld/app/tx/detail/MPTokenIssuanceSet.h | 4 +- .../app/tx/detail/NFTokenAcceptOffer.cpp | 4 +- src/xrpld/app/tx/detail/NFTokenAcceptOffer.h | 4 +- src/xrpld/app/tx/detail/NFTokenBurn.cpp | 4 +- src/xrpld/app/tx/detail/NFTokenBurn.h | 4 +- .../app/tx/detail/NFTokenCancelOffer.cpp | 4 +- src/xrpld/app/tx/detail/NFTokenCancelOffer.h | 4 +- .../app/tx/detail/NFTokenCreateOffer.cpp | 4 +- src/xrpld/app/tx/detail/NFTokenCreateOffer.h | 4 +- src/xrpld/app/tx/detail/NFTokenMint.cpp | 6 +- src/xrpld/app/tx/detail/NFTokenMint.h | 4 +- src/xrpld/app/tx/detail/NFTokenModify.cpp | 4 +- src/xrpld/app/tx/detail/NFTokenModify.h | 4 +- src/xrpld/app/tx/detail/NFTokenUtils.cpp | 22 ++-- src/xrpld/app/tx/detail/NFTokenUtils.h | 6 +- src/xrpld/app/tx/detail/Offer.h | 6 +- src/xrpld/app/tx/detail/OfferStream.cpp | 6 +- src/xrpld/app/tx/detail/OfferStream.h | 4 +- src/xrpld/app/tx/detail/PayChan.cpp | 8 +- src/xrpld/app/tx/detail/PayChan.h | 4 +- src/xrpld/app/tx/detail/Payment.cpp | 6 +- src/xrpld/app/tx/detail/Payment.h | 4 +- .../tx/detail/PermissionedDomainDelete.cpp | 10 +- .../app/tx/detail/PermissionedDomainDelete.h | 4 +- .../app/tx/detail/PermissionedDomainSet.cpp | 4 +- .../app/tx/detail/PermissionedDomainSet.h | 4 +- src/xrpld/app/tx/detail/SetAccount.cpp | 4 +- src/xrpld/app/tx/detail/SetAccount.h | 4 +- src/xrpld/app/tx/detail/SetOracle.cpp | 4 +- src/xrpld/app/tx/detail/SetOracle.h | 4 +- src/xrpld/app/tx/detail/SetRegularKey.cpp | 4 +- src/xrpld/app/tx/detail/SetRegularKey.h | 4 +- src/xrpld/app/tx/detail/SetSignerList.cpp | 16 +-- src/xrpld/app/tx/detail/SetSignerList.h | 4 +- src/xrpld/app/tx/detail/SetTrust.cpp | 14 +- src/xrpld/app/tx/detail/SetTrust.h | 4 +- src/xrpld/app/tx/detail/SignerEntries.cpp | 4 +- src/xrpld/app/tx/detail/SignerEntries.h | 4 +- src/xrpld/app/tx/detail/Transactor.cpp | 30 ++--- src/xrpld/app/tx/detail/Transactor.h | 6 +- src/xrpld/app/tx/detail/VaultClawback.cpp | 8 +- src/xrpld/app/tx/detail/VaultClawback.h | 4 +- src/xrpld/app/tx/detail/VaultCreate.cpp | 4 +- src/xrpld/app/tx/detail/VaultCreate.h | 4 +- src/xrpld/app/tx/detail/VaultDelete.cpp | 4 +- src/xrpld/app/tx/detail/VaultDelete.h | 4 +- src/xrpld/app/tx/detail/VaultDeposit.cpp | 8 +- src/xrpld/app/tx/detail/VaultDeposit.h | 4 +- src/xrpld/app/tx/detail/VaultSet.cpp | 4 +- src/xrpld/app/tx/detail/VaultSet.h | 4 +- src/xrpld/app/tx/detail/VaultWithdraw.cpp | 6 +- src/xrpld/app/tx/detail/VaultWithdraw.h | 4 +- src/xrpld/app/tx/detail/XChainBridge.cpp | 10 +- src/xrpld/app/tx/detail/XChainBridge.h | 4 +- src/xrpld/app/tx/detail/apply.cpp | 4 +- src/xrpld/app/tx/detail/applySteps.cpp | 15 +-- src/xrpld/conditions/Condition.h | 4 +- src/xrpld/conditions/Fulfillment.h | 4 +- src/xrpld/conditions/detail/Condition.cpp | 4 +- src/xrpld/conditions/detail/Fulfillment.cpp | 4 +- src/xrpld/conditions/detail/PreimageSha256.h | 4 +- src/xrpld/conditions/detail/error.cpp | 4 +- src/xrpld/conditions/detail/error.h | 6 +- src/xrpld/conditions/detail/utils.h | 4 +- src/xrpld/consensus/Consensus.cpp | 4 +- src/xrpld/consensus/Consensus.h | 23 ++-- src/xrpld/consensus/ConsensusParms.h | 6 +- src/xrpld/consensus/ConsensusProposal.h | 4 +- src/xrpld/consensus/ConsensusTypes.h | 6 +- src/xrpld/consensus/DisputedTx.h | 4 +- src/xrpld/consensus/LedgerTiming.h | 4 +- src/xrpld/consensus/LedgerTrie.h | 22 ++-- src/xrpld/consensus/Validations.h | 8 +- src/xrpld/core/Config.h | 4 +- src/xrpld/core/ConfigSections.h | 4 +- src/xrpld/core/DatabaseCon.h | 6 +- src/xrpld/core/SociDB.h | 4 +- src/xrpld/core/TimeKeeper.h | 4 +- src/xrpld/core/detail/Config.cpp | 27 ++-- src/xrpld/core/detail/DatabaseCon.cpp | 6 +- src/xrpld/core/detail/SociDB.cpp | 6 +- src/xrpld/overlay/Cluster.h | 4 +- src/xrpld/overlay/ClusterNode.h | 4 +- src/xrpld/overlay/Compression.h | 12 +- src/xrpld/overlay/Message.h | 4 +- src/xrpld/overlay/Overlay.h | 4 +- src/xrpld/overlay/Peer.h | 4 +- src/xrpld/overlay/PeerReservationTable.h | 4 +- src/xrpld/overlay/PeerSet.h | 4 +- src/xrpld/overlay/ReduceRelayCommon.h | 4 +- src/xrpld/overlay/Slot.h | 8 +- src/xrpld/overlay/Squelch.h | 4 +- src/xrpld/overlay/detail/Cluster.cpp | 4 +- src/xrpld/overlay/detail/ConnectAttempt.cpp | 10 +- src/xrpld/overlay/detail/ConnectAttempt.h | 4 +- src/xrpld/overlay/detail/Handshake.cpp | 8 +- src/xrpld/overlay/detail/Handshake.h | 4 +- src/xrpld/overlay/detail/Message.cpp | 14 +- src/xrpld/overlay/detail/OverlayImpl.cpp | 22 ++-- src/xrpld/overlay/detail/OverlayImpl.h | 8 +- src/xrpld/overlay/detail/PeerImp.cpp | 46 +++---- src/xrpld/overlay/detail/PeerImp.h | 6 +- .../overlay/detail/PeerReservationTable.cpp | 4 +- src/xrpld/overlay/detail/PeerSet.cpp | 6 +- src/xrpld/overlay/detail/ProtocolMessage.h | 12 +- src/xrpld/overlay/detail/ProtocolVersion.cpp | 4 +- src/xrpld/overlay/detail/ProtocolVersion.h | 4 +- src/xrpld/overlay/detail/TrafficCount.cpp | 4 +- src/xrpld/overlay/detail/TrafficCount.h | 6 +- src/xrpld/overlay/detail/Tuning.h | 4 +- src/xrpld/overlay/detail/TxMetrics.cpp | 4 +- src/xrpld/overlay/detail/TxMetrics.h | 4 +- src/xrpld/overlay/detail/ZeroCopyStream.h | 6 +- src/xrpld/overlay/make_Overlay.h | 4 +- src/xrpld/overlay/predicates.h | 4 +- src/xrpld/peerfinder/PeerfinderManager.h | 6 +- src/xrpld/peerfinder/Slot.h | 4 +- src/xrpld/peerfinder/detail/Bootcache.cpp | 4 +- src/xrpld/peerfinder/detail/Bootcache.h | 8 +- src/xrpld/peerfinder/detail/Checker.h | 4 +- src/xrpld/peerfinder/detail/Counts.h | 12 +- src/xrpld/peerfinder/detail/Endpoint.cpp | 4 +- src/xrpld/peerfinder/detail/Fixed.h | 4 +- src/xrpld/peerfinder/detail/Handouts.h | 6 +- src/xrpld/peerfinder/detail/Livecache.h | 10 +- src/xrpld/peerfinder/detail/Logic.h | 26 ++-- .../peerfinder/detail/PeerfinderConfig.cpp | 6 +- .../peerfinder/detail/PeerfinderManager.cpp | 4 +- src/xrpld/peerfinder/detail/SlotImp.cpp | 16 +-- src/xrpld/peerfinder/detail/SlotImp.h | 4 +- src/xrpld/peerfinder/detail/Source.h | 4 +- src/xrpld/peerfinder/detail/SourceStrings.cpp | 4 +- src/xrpld/peerfinder/detail/SourceStrings.h | 4 +- src/xrpld/peerfinder/detail/Store.h | 4 +- src/xrpld/peerfinder/detail/StoreSqdb.h | 4 +- src/xrpld/peerfinder/detail/Tuning.h | 4 +- src/xrpld/peerfinder/make_Manager.h | 4 +- src/xrpld/perflog/detail/PerfLogImp.cpp | 23 ++-- src/xrpld/perflog/detail/PerfLogImp.h | 6 +- src/xrpld/rpc/BookChanges.h | 4 +- src/xrpld/rpc/CTID.h | 4 +- src/xrpld/rpc/Context.h | 4 +- src/xrpld/rpc/DeliveredAmount.h | 4 +- src/xrpld/rpc/GRPCHandlers.h | 4 +- src/xrpld/rpc/InfoSub.h | 4 +- src/xrpld/rpc/MPTokenIssuanceID.h | 4 +- src/xrpld/rpc/Output.h | 4 +- src/xrpld/rpc/README.md | 2 +- src/xrpld/rpc/RPCCall.h | 4 +- src/xrpld/rpc/RPCHandler.h | 4 +- src/xrpld/rpc/RPCSub.h | 4 +- src/xrpld/rpc/Request.h | 4 +- src/xrpld/rpc/Role.h | 4 +- src/xrpld/rpc/ServerHandler.h | 4 +- src/xrpld/rpc/Status.h | 8 +- src/xrpld/rpc/detail/DeliveredAmount.cpp | 4 +- src/xrpld/rpc/detail/Handler.cpp | 12 +- src/xrpld/rpc/detail/Handler.h | 4 +- src/xrpld/rpc/detail/InfoSub.cpp | 6 +- src/xrpld/rpc/detail/LegacyPathFind.cpp | 4 +- src/xrpld/rpc/detail/LegacyPathFind.h | 4 +- src/xrpld/rpc/detail/MPTokenIssuanceID.cpp | 4 +- src/xrpld/rpc/detail/RPCCall.cpp | 12 +- src/xrpld/rpc/detail/RPCHandler.cpp | 4 +- src/xrpld/rpc/detail/RPCHelpers.cpp | 8 +- src/xrpld/rpc/detail/RPCHelpers.h | 4 +- src/xrpld/rpc/detail/RPCLedgerHelpers.cpp | 16 +-- src/xrpld/rpc/detail/RPCLedgerHelpers.h | 4 +- src/xrpld/rpc/detail/RPCSub.cpp | 4 +- src/xrpld/rpc/detail/Role.cpp | 6 +- src/xrpld/rpc/detail/ServerHandler.cpp | 4 +- src/xrpld/rpc/detail/Status.cpp | 8 +- src/xrpld/rpc/detail/TransactionSign.cpp | 8 +- src/xrpld/rpc/detail/TransactionSign.h | 4 +- src/xrpld/rpc/detail/Tuning.h | 4 +- src/xrpld/rpc/detail/WSInfoSub.h | 4 +- src/xrpld/rpc/handlers/AMMInfo.cpp | 10 +- src/xrpld/rpc/handlers/AccountChannels.cpp | 6 +- .../rpc/handlers/AccountCurrenciesHandler.cpp | 4 +- src/xrpld/rpc/handlers/AccountInfo.cpp | 6 +- src/xrpld/rpc/handlers/AccountLines.cpp | 6 +- src/xrpld/rpc/handlers/AccountObjects.cpp | 4 +- src/xrpld/rpc/handlers/AccountOffers.cpp | 6 +- src/xrpld/rpc/handlers/AccountTx.cpp | 11 +- src/xrpld/rpc/handlers/BlackList.cpp | 4 +- src/xrpld/rpc/handlers/BookOffers.cpp | 4 +- src/xrpld/rpc/handlers/CanDelete.cpp | 4 +- src/xrpld/rpc/handlers/Connect.cpp | 4 +- src/xrpld/rpc/handlers/ConsensusInfo.cpp | 4 +- src/xrpld/rpc/handlers/DepositAuthorized.cpp | 4 +- src/xrpld/rpc/handlers/DoManifest.cpp | 4 +- src/xrpld/rpc/handlers/Feature1.cpp | 4 +- src/xrpld/rpc/handlers/Fee1.cpp | 6 +- src/xrpld/rpc/handlers/FetchInfo.cpp | 4 +- src/xrpld/rpc/handlers/GatewayBalances.cpp | 4 +- src/xrpld/rpc/handlers/GetAggregatePrice.cpp | 4 +- src/xrpld/rpc/handlers/GetCounts.cpp | 4 +- src/xrpld/rpc/handlers/GetCounts.h | 2 +- src/xrpld/rpc/handlers/Handlers.h | 4 +- src/xrpld/rpc/handlers/LedgerAccept.cpp | 4 +- .../rpc/handlers/LedgerCleanerHandler.cpp | 4 +- src/xrpld/rpc/handlers/LedgerClosed.cpp | 6 +- src/xrpld/rpc/handlers/LedgerCurrent.cpp | 4 +- src/xrpld/rpc/handlers/LedgerData.cpp | 4 +- src/xrpld/rpc/handlers/LedgerDiff.cpp | 6 +- src/xrpld/rpc/handlers/LedgerEntry.cpp | 4 +- src/xrpld/rpc/handlers/LedgerEntryHelpers.h | 4 +- src/xrpld/rpc/handlers/LedgerHandler.cpp | 8 +- src/xrpld/rpc/handlers/LedgerHandler.h | 4 +- src/xrpld/rpc/handlers/LedgerHeader.cpp | 4 +- src/xrpld/rpc/handlers/LedgerRequest.cpp | 4 +- src/xrpld/rpc/handlers/LogLevel.cpp | 4 +- src/xrpld/rpc/handlers/LogRotate.cpp | 4 +- src/xrpld/rpc/handlers/NFTOffers.cpp | 4 +- src/xrpld/rpc/handlers/NoRippleCheck.cpp | 4 +- src/xrpld/rpc/handlers/OwnerInfo.cpp | 4 +- src/xrpld/rpc/handlers/PathFind.cpp | 4 +- src/xrpld/rpc/handlers/PayChanClaim.cpp | 6 +- src/xrpld/rpc/handlers/Peers.cpp | 4 +- src/xrpld/rpc/handlers/Ping.cpp | 4 +- src/xrpld/rpc/handlers/Print.cpp | 4 +- src/xrpld/rpc/handlers/Random.cpp | 4 +- src/xrpld/rpc/handlers/Reservations.cpp | 4 +- src/xrpld/rpc/handlers/RipplePathFind.cpp | 4 +- src/xrpld/rpc/handlers/ServerDefinitions.cpp | 8 +- src/xrpld/rpc/handlers/ServerInfo.cpp | 4 +- src/xrpld/rpc/handlers/ServerState.cpp | 4 +- src/xrpld/rpc/handlers/SignFor.cpp | 4 +- src/xrpld/rpc/handlers/SignHandler.cpp | 4 +- src/xrpld/rpc/handlers/Simulate.cpp | 4 +- src/xrpld/rpc/handlers/Stop.cpp | 4 +- src/xrpld/rpc/handlers/Submit.cpp | 4 +- src/xrpld/rpc/handlers/SubmitMultiSigned.cpp | 4 +- src/xrpld/rpc/handlers/Subscribe.cpp | 4 +- src/xrpld/rpc/handlers/TransactionEntry.cpp | 4 +- src/xrpld/rpc/handlers/Tx.cpp | 6 +- src/xrpld/rpc/handlers/TxHistory.cpp | 4 +- src/xrpld/rpc/handlers/TxReduceRelay.cpp | 4 +- src/xrpld/rpc/handlers/UnlList.cpp | 4 +- src/xrpld/rpc/handlers/Unsubscribe.cpp | 4 +- src/xrpld/rpc/handlers/ValidationCreate.cpp | 4 +- src/xrpld/rpc/handlers/ValidatorInfo.cpp | 4 +- src/xrpld/rpc/handlers/ValidatorListSites.cpp | 4 +- src/xrpld/rpc/handlers/Validators.cpp | 4 +- src/xrpld/rpc/handlers/VaultInfo.cpp | 4 +- src/xrpld/rpc/handlers/Version.h | 4 +- src/xrpld/rpc/handlers/WalletPropose.cpp | 4 +- src/xrpld/rpc/handlers/WalletPropose.h | 4 +- src/xrpld/rpc/json_body.h | 4 +- src/xrpld/shamap/NodeFamily.cpp | 4 +- src/xrpld/shamap/NodeFamily.h | 4 +- tests/conan/src/example.cpp | 2 +- 1261 files changed, 4220 insertions(+), 4235 deletions(-) create mode 100755 .github/scripts/rename/namespace.sh diff --git a/.github/scripts/rename/README.md b/.github/scripts/rename/README.md index 836f3606ba..392f0b1efc 100644 --- a/.github/scripts/rename/README.md +++ b/.github/scripts/rename/README.md @@ -29,6 +29,8 @@ run from the repository root. 4. `.github/scripts/rename/binary.sh`: This script will rename the binary from `rippled` to `xrpld`, and reverses the symlink so that `rippled` points to the `xrpld` binary. +5. `.github/scripts/rename/namespace.sh`: This script will rename the C++ + namespaces from `ripple` to `xrpl`. You can run all these scripts from the repository root as follows: @@ -37,4 +39,5 @@ You can run all these scripts from the repository root as follows: ./.github/scripts/rename/copyright.sh . ./.github/scripts/rename/cmake.sh . ./.github/scripts/rename/binary.sh . +./.github/scripts/rename/namespace.sh . ``` diff --git a/.github/scripts/rename/namespace.sh b/.github/scripts/rename/namespace.sh new file mode 100755 index 0000000000..30fd91bf2c --- /dev/null +++ b/.github/scripts/rename/namespace.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Exit the script as soon as an error occurs. +set -e + +# On MacOS, ensure that GNU sed is installed and available as `gsed`. +SED_COMMAND=sed +if [[ "${OSTYPE}" == 'darwin'* ]]; then + if ! command -v gsed &> /dev/null; then + echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'." + exit 1 + fi + SED_COMMAND=gsed +fi + +# This script renames the `ripple` namespace to `xrpl` in this project. +# Specifically, it renames all occurrences of `namespace ripple` and `ripple::` +# to `namespace xrpl` and `xrpl::`, respectively, by scanning all header and +# source files in the specified directory and its subdirectories, as well as any +# occurrences in the documentation. It also renames them in the test suites. +# Usage: .github/scripts/rename/namespace.sh + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +DIRECTORY=$1 +echo "Processing directory: ${DIRECTORY}" +if [ ! -d "${DIRECTORY}" ]; then + echo "Error: Directory '${DIRECTORY}' does not exist." + exit 1 +fi +pushd ${DIRECTORY} + +DIRECTORIES=("include" "src" "tests") +for DIRECTORY in "${DIRECTORIES[@]}"; do + echo "Processing directory: ${DIRECTORY}" + + find "${DIRECTORY}" -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.ipp" -o -name "*.cpp" \) | while read -r FILE; do + echo "Processing file: ${FILE}" + ${SED_COMMAND} -i 's/namespace ripple/namespace xrpl/g' "${FILE}" + ${SED_COMMAND} -i 's/ripple::/xrpl::/g' "${FILE}" + ${SED_COMMAND} -i -E 's/(BEAST_DEFINE_TESTSUITE.+)ripple(.+)/\1xrpl\2/g' "${FILE}" + done +done + +# Special case for NuDBFactory that has ripple twice in the test suite name. +${SED_COMMAND} -i -E 's/(BEAST_DEFINE_TESTSUITE.+)ripple(.+)/\1xrpl\2/g' src/test/nodestore/NuDBFactory_test.cpp + +DIRECTORY=$1 +find "${DIRECTORY}" -type f -name "*.md" | while read -r FILE; do + echo "Processing file: ${FILE}" + ${SED_COMMAND} -i 's/ripple::/xrpl::/g' "${FILE}" +done + +popd +echo "Renaming complete." diff --git a/.github/workflows/reusable-check-rename.yml b/.github/workflows/reusable-check-rename.yml index 00ef7c6f14..fb9ed2c6a8 100644 --- a/.github/workflows/reusable-check-rename.yml +++ b/.github/workflows/reusable-check-rename.yml @@ -27,6 +27,8 @@ jobs: run: .github/scripts/rename/cmake.sh . - name: Check binary name run: .github/scripts/rename/binary.sh . + - name: Check namespaces + run: .github/scripts/rename/namespace.sh . - name: Check for differences env: MESSAGE: | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 86cfa9dc6d..5b578b7f13 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -304,7 +304,7 @@ For this reason: - Example **bad** name `"RFC1751::insert(char* s, int x, int start, int length) : length is greater than or equal zero"` (missing namespace, unnecessary full function signature, description too verbose). - Good name: `"ripple::RFC1751::insert : minimum length"`. + Good name: `"xrpl::RFC1751::insert : minimum length"`. - In **few** well-justified cases a non-standard name can be used, in which case a comment should be placed to explain the rationale (example in `contract.cpp`) - Do **not** rename a contract without a good reason (e.g. the name no longer diff --git a/include/xrpl/basics/Archive.h b/include/xrpl/basics/Archive.h index 6dbb31f426..5f7c624084 100644 --- a/include/xrpl/basics/Archive.h +++ b/include/xrpl/basics/Archive.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Extract a tar archive compressed with lz4 @@ -17,6 +17,6 @@ extractTarLz4( boost::filesystem::path const& src, boost::filesystem::path const& dst); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/BasicConfig.h b/include/xrpl/basics/BasicConfig.h index 153936430a..573b26ae75 100644 --- a/include/xrpl/basics/BasicConfig.h +++ b/include/xrpl/basics/BasicConfig.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { using IniFileSections = std::unordered_map>; @@ -380,6 +380,6 @@ get_if_exists(Section const& section, std::string const& name, bool& v) return stat; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/Blob.h b/include/xrpl/basics/Blob.h index c87a834fd4..986f829371 100644 --- a/include/xrpl/basics/Blob.h +++ b/include/xrpl/basics/Blob.h @@ -3,13 +3,13 @@ #include -namespace ripple { +namespace xrpl { /** Storage for linear binary data. Blocks of binary data appear often in various idioms and structures. */ using Blob = std::vector; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/Buffer.h b/include/xrpl/basics/Buffer.h index c72ebba174..8ae745f6d1 100644 --- a/include/xrpl/basics/Buffer.h +++ b/include/xrpl/basics/Buffer.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Like std::vector but better. Meets the requirements of BufferFactory. @@ -96,7 +96,7 @@ public: XRPL_ASSERT( s.size() == 0 || size_ == 0 || s.data() < p_.get() || s.data() >= p_.get() + size_, - "ripple::Buffer::operator=(Slice) : input not a subset"); + "xrpl::Buffer::operator=(Slice) : input not a subset"); if (auto p = alloc(s.size())) std::memcpy(p, s.data(), s.size()); @@ -215,6 +215,6 @@ operator!=(Buffer const& lhs, Buffer const& rhs) noexcept return !(lhs == rhs); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/ByteUtilities.h b/include/xrpl/basics/ByteUtilities.h index 45df242720..88bb297346 100644 --- a/include/xrpl/basics/ByteUtilities.h +++ b/include/xrpl/basics/ByteUtilities.h @@ -1,7 +1,7 @@ #ifndef XRPL_BASICS_BYTEUTILITIES_H_INCLUDED #define XRPL_BASICS_BYTEUTILITIES_H_INCLUDED -namespace ripple { +namespace xrpl { template constexpr auto @@ -19,6 +19,6 @@ megabytes(T value) noexcept static_assert(kilobytes(2) == 2048, "kilobytes(2) == 2048"); static_assert(megabytes(3) == 3145728, "megabytes(3) == 3145728"); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/CompressionAlgorithms.h b/include/xrpl/basics/CompressionAlgorithms.h index 77747e1684..b373ac4605 100644 --- a/include/xrpl/basics/CompressionAlgorithms.h +++ b/include/xrpl/basics/CompressionAlgorithms.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace compression_algorithms { @@ -144,6 +144,6 @@ lz4Decompress( } // namespace compression_algorithms -} // namespace ripple +} // namespace xrpl #endif // XRPL_COMPRESSIONALGORITHMS_H_INCLUDED diff --git a/include/xrpl/basics/CountedObject.h b/include/xrpl/basics/CountedObject.h index d3a4f53caa..e464e470af 100644 --- a/include/xrpl/basics/CountedObject.h +++ b/include/xrpl/basics/CountedObject.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Manages all counted object types. */ class CountedObjects @@ -133,6 +133,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/DecayingSample.h b/include/xrpl/basics/DecayingSample.h index 78a50e9df2..c5e38d2e9a 100644 --- a/include/xrpl/basics/DecayingSample.h +++ b/include/xrpl/basics/DecayingSample.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Sampling function using exponential decay to provide a continuous value. @tparam The number of seconds in the decay window. @@ -131,6 +131,6 @@ private: time_point when_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/Expected.h b/include/xrpl/basics/Expected.h index 8f3d026d9c..8cf479c1b6 100644 --- a/include/xrpl/basics/Expected.h +++ b/include/xrpl/basics/Expected.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { /** Expected is an approximation of std::expected (hoped for in C++23) @@ -232,6 +232,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_EXPECTED_H_INCLUDED diff --git a/include/xrpl/basics/FileUtilities.h b/include/xrpl/basics/FileUtilities.h index 8fb1368bfd..c4bc2cbe68 100644 --- a/include/xrpl/basics/FileUtilities.h +++ b/include/xrpl/basics/FileUtilities.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { std::string getFileContents( @@ -20,6 +20,6 @@ writeFileContents( boost::filesystem::path const& destPath, std::string const& contents); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/IntrusivePointer.h b/include/xrpl/basics/IntrusivePointer.h index 9e34c901f3..24521b95a7 100644 --- a/include/xrpl/basics/IntrusivePointer.h +++ b/include/xrpl/basics/IntrusivePointer.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { //------------------------------------------------------------------------------ @@ -492,5 +492,5 @@ dynamic_pointer_cast(TT const& v) return SharedPtr(DynamicCastTagSharedIntrusive{}, v); } } // namespace intr_ptr -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/IntrusivePointer.ipp b/include/xrpl/basics/IntrusivePointer.ipp index 7b0787634c..cfebb559fd 100644 --- a/include/xrpl/basics/IntrusivePointer.ipp +++ b/include/xrpl/basics/IntrusivePointer.ipp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { template template @@ -608,7 +608,7 @@ SharedWeakUnion::convertToStrong() [[maybe_unused]] auto action = p->releaseWeakRef(); XRPL_ASSERT( (action == ReleaseWeakRefAction::noop), - "ripple::SharedWeakUnion::convertToStrong : " + "xrpl::SharedWeakUnion::convertToStrong : " "action is noop"); unsafeSetRawPtr(p, RefStrength::strong); return true; @@ -637,7 +637,7 @@ SharedWeakUnion::convertToWeak() // We just added a weak ref. How could we destroy? // LCOV_EXCL_START UNREACHABLE( - "ripple::SharedWeakUnion::convertToWeak : destroying freshly " + "xrpl::SharedWeakUnion::convertToWeak : destroying freshly " "added ref"); delete p; unsafeSetRawPtr(nullptr); @@ -719,5 +719,5 @@ SharedWeakUnion::unsafeReleaseNoStore() } } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/IntrusiveRefCounts.h b/include/xrpl/basics/IntrusiveRefCounts.h index 653d149843..630c08395d 100644 --- a/include/xrpl/basics/IntrusiveRefCounts.h +++ b/include/xrpl/basics/IntrusiveRefCounts.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Action to perform when releasing a strong pointer. @@ -34,7 +34,7 @@ enum class ReleaseWeakRefAction { noop, destroy }; /** Implement the strong count, weak count, and bit flags for an intrusive pointer. - A class can satisfy the requirements of a ripple::IntrusivePointer by + A class can satisfy the requirements of a xrpl::IntrusivePointer by inheriting from this class. */ struct IntrusiveRefCounts @@ -257,7 +257,7 @@ IntrusiveRefCounts::releaseStrongRef() const RefCountPair const prevVal{prevIntVal}; XRPL_ASSERT( (prevVal.strong >= strongDelta), - "ripple::IntrusiveRefCounts::releaseStrongRef : previous ref " + "xrpl::IntrusiveRefCounts::releaseStrongRef : previous ref " "higher than new"); auto nextIntVal = prevIntVal - strongDelta; ReleaseStrongRefAction action = noop; @@ -282,7 +282,7 @@ IntrusiveRefCounts::releaseStrongRef() const // twice. XRPL_ASSERT( (action == noop) || !(prevIntVal & partialDestroyStartedMask), - "ripple::IntrusiveRefCounts::releaseStrongRef : not in partial " + "xrpl::IntrusiveRefCounts::releaseStrongRef : not in partial " "destroy"); return action; } @@ -314,7 +314,7 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const // can't happen twice. XRPL_ASSERT( (!prevVal.partialDestroyStartedBit), - "ripple::IntrusiveRefCounts::addWeakReleaseStrongRef : not in " + "xrpl::IntrusiveRefCounts::addWeakReleaseStrongRef : not in " "partial destroy"); auto nextIntVal = prevIntVal + delta; @@ -336,7 +336,7 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const { XRPL_ASSERT( (!(prevIntVal & partialDestroyStartedMask)), - "ripple::IntrusiveRefCounts::addWeakReleaseStrongRef : not " + "xrpl::IntrusiveRefCounts::addWeakReleaseStrongRef : not " "started partial destroy"); return action; } @@ -408,11 +408,11 @@ inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept auto v = refCounts.load(std::memory_order_acquire); XRPL_ASSERT( (!(v & valueMask)), - "ripple::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero"); + "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero"); auto t = v & tagMask; XRPL_ASSERT( (!t || t == tagMask), - "ripple::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag"); + "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag"); #endif } @@ -427,7 +427,7 @@ inline IntrusiveRefCounts::RefCountPair::RefCountPair( { XRPL_ASSERT( (strong < checkStrongMaxValue && weak < checkWeakMaxValue), - "ripple::IntrusiveRefCounts::RefCountPair(FieldType) : inputs inside " + "xrpl::IntrusiveRefCounts::RefCountPair(FieldType) : inputs inside " "range"); } @@ -438,7 +438,7 @@ inline IntrusiveRefCounts::RefCountPair::RefCountPair( { XRPL_ASSERT( (strong < checkStrongMaxValue && weak < checkWeakMaxValue), - "ripple::IntrusiveRefCounts::RefCountPair(CountType, CountType) : " + "xrpl::IntrusiveRefCounts::RefCountPair(CountType, CountType) : " "inputs inside range"); } @@ -447,7 +447,7 @@ IntrusiveRefCounts::RefCountPair::combinedValue() const noexcept { XRPL_ASSERT( (strong < checkStrongMaxValue && weak < checkWeakMaxValue), - "ripple::IntrusiveRefCounts::RefCountPair::combinedValue : inputs " + "xrpl::IntrusiveRefCounts::RefCountPair::combinedValue : inputs " "inside range"); return (static_cast(weak) << IntrusiveRefCounts::StrongCountNumBits) | @@ -465,7 +465,7 @@ partialDestructorFinished(T** o) XRPL_ASSERT( (!p.partialDestroyFinishedBit && p.partialDestroyStartedBit && !p.strong), - "ripple::partialDestructorFinished : not a weak ref"); + "xrpl::partialDestructorFinished : not a weak ref"); if (!p.weak) { // There was a weak count before the partial destructor ran (or we would @@ -479,5 +479,5 @@ partialDestructorFinished(T** o) } //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/KeyCache.h b/include/xrpl/basics/KeyCache.h index 1ab908256f..038bf7b9b7 100644 --- a/include/xrpl/basics/KeyCache.h +++ b/include/xrpl/basics/KeyCache.h @@ -4,10 +4,10 @@ #include #include -namespace ripple { +namespace xrpl { using KeyCache = TaggedCache; -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_KEYCACHE_H diff --git a/include/xrpl/basics/LocalValue.h b/include/xrpl/basics/LocalValue.h index 56026231ac..cc7c646fb0 100644 --- a/include/xrpl/basics/LocalValue.h +++ b/include/xrpl/basics/LocalValue.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -109,6 +109,6 @@ LocalValue::operator*() .emplace(this, std::make_unique>(t_)) .first->second->get()); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/Log.h b/include/xrpl/basics/Log.h index 134f1695d3..9443e8afdf 100644 --- a/include/xrpl/basics/Log.h +++ b/include/xrpl/basics/Log.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { // DEPRECATED use beast::severities::Severity instead enum LogSeverity { @@ -271,6 +271,6 @@ setDebugLogSink(std::unique_ptr sink); beast::Journal debugLog(); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/MathUtilities.h b/include/xrpl/basics/MathUtilities.h index 99d99a15cd..bd8ea883fb 100644 --- a/include/xrpl/basics/MathUtilities.h +++ b/include/xrpl/basics/MathUtilities.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Calculate one number divided by another number in percentage. * The result is rounded up to the next integer, and capped in the range [0,100] @@ -44,6 +44,6 @@ static_assert(calculatePercent(50'000'000, 100'000'000) == 50); static_assert(calculatePercent(50'000'001, 100'000'000) == 51); static_assert(calculatePercent(99'999'999, 100'000'000) == 100); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/Number.h b/include/xrpl/basics/Number.h index 4a4ee1cacb..4420530239 100644 --- a/include/xrpl/basics/Number.h +++ b/include/xrpl/basics/Number.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class Number; @@ -402,6 +402,6 @@ public: operator=(NumberRoundModeGuard const&) = delete; }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_NUMBER_H_INCLUDED diff --git a/include/xrpl/basics/README.md b/include/xrpl/basics/README.md index 290bb7ad0c..f8b19522cd 100644 --- a/include/xrpl/basics/README.md +++ b/include/xrpl/basics/README.md @@ -21,11 +21,11 @@ ripple/basic should contain no dependencies on other modules. - `std::set` - For sorted containers. -- `ripple::hash_set` +- `xrpl::hash_set` - Where inserts and contains need to be O(1). - For "small" sets, `std::set` might be faster and smaller. -- `ripple::hardened_hash_set` +- `xrpl::hardened_hash_set` - For data sets where the key could be manipulated by an attacker in an attempt to mount an algorithmic complexity attack: see http://en.wikipedia.org/wiki/Algorithmic_complexity_attack @@ -33,5 +33,5 @@ ripple/basic should contain no dependencies on other modules. The following container is deprecated - `std::unordered_set` -- Use `ripple::hash_set` instead, which uses a better hashing algorithm. -- Or use `ripple::hardened_hash_set` to prevent algorithmic complexity attacks. +- Use `xrpl::hash_set` instead, which uses a better hashing algorithm. +- Or use `xrpl::hardened_hash_set` to prevent algorithmic complexity attacks. diff --git a/include/xrpl/basics/RangeSet.h b/include/xrpl/basics/RangeSet.h index a77c5b403e..ee95577271 100644 --- a/include/xrpl/basics/RangeSet.h +++ b/include/xrpl/basics/RangeSet.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A closed interval over the domain T. @@ -85,7 +85,7 @@ to_string(RangeSet const& rs) std::string s; for (auto const& interval : rs) - s += ripple::to_string(interval) + ","; + s += xrpl::to_string(interval) + ","; s.pop_back(); return s; @@ -172,6 +172,6 @@ prevMissing(RangeSet const& rs, T t, T minVal = 0) return boost::icl::last(tgt); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/Resolver.h b/include/xrpl/basics/Resolver.h index fc529887b0..088b2e1d5b 100644 --- a/include/xrpl/basics/Resolver.h +++ b/include/xrpl/basics/Resolver.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class Resolver { @@ -47,6 +47,6 @@ public: /** @} */ }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/ResolverAsio.h b/include/xrpl/basics/ResolverAsio.h index b609c11b1b..f2a3da0d58 100644 --- a/include/xrpl/basics/ResolverAsio.h +++ b/include/xrpl/basics/ResolverAsio.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { class ResolverAsio : public Resolver { @@ -17,6 +17,6 @@ public: New(boost::asio::io_context&, beast::Journal); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/SHAMapHash.h b/include/xrpl/basics/SHAMapHash.h index 12aef37dd0..eb635b516c 100644 --- a/include/xrpl/basics/SHAMapHash.h +++ b/include/xrpl/basics/SHAMapHash.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { // A SHAMapHash is the hash of a node in a SHAMap, and also the // type of the hash of the entire SHAMap. @@ -97,6 +97,6 @@ extract(SHAMapHash const& key) return *reinterpret_cast(key.as_uint256().data()); } -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_SHAMAP_HASH_H_INCLUDED diff --git a/include/xrpl/basics/SharedWeakCachePointer.h b/include/xrpl/basics/SharedWeakCachePointer.h index dbac85a2a9..49369265eb 100644 --- a/include/xrpl/basics/SharedWeakCachePointer.h +++ b/include/xrpl/basics/SharedWeakCachePointer.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A combination of a std::shared_ptr and a std::weak_pointer. @@ -112,5 +112,5 @@ public: private: std::variant, std::weak_ptr> combo_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/SharedWeakCachePointer.ipp b/include/xrpl/basics/SharedWeakCachePointer.ipp index 59f5882637..376bf73251 100644 --- a/include/xrpl/basics/SharedWeakCachePointer.ipp +++ b/include/xrpl/basics/SharedWeakCachePointer.ipp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { template SharedWeakCachePointer::SharedWeakCachePointer( SharedWeakCachePointer const& rhs) = default; @@ -169,5 +169,5 @@ SharedWeakCachePointer::convertToWeak() return false; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/SlabAllocator.h b/include/xrpl/basics/SlabAllocator.h index d27616ecdd..c67d1ee318 100644 --- a/include/xrpl/basics/SlabAllocator.h +++ b/include/xrpl/basics/SlabAllocator.h @@ -22,7 +22,7 @@ #include #endif -namespace ripple { +namespace xrpl { template class SlabAllocator @@ -128,7 +128,7 @@ class SlabAllocator { XRPL_ASSERT( own(ptr), - "ripple::SlabAllocator::SlabBlock::deallocate : own input"); + "xrpl::SlabAllocator::SlabBlock::deallocate : own input"); std::lock_guard l(m_); @@ -173,7 +173,7 @@ public: { XRPL_ASSERT( (itemAlignment_ & (itemAlignment_ - 1)) == 0, - "ripple::SlabAllocator::SlabAllocator : valid alignment"); + "xrpl::SlabAllocator::SlabAllocator : valid alignment"); } SlabAllocator(SlabAllocator const& other) = delete; @@ -285,7 +285,7 @@ public: { XRPL_ASSERT( ptr, - "ripple::SlabAllocator::SlabAllocator::deallocate : non-null " + "xrpl::SlabAllocator::SlabAllocator::deallocate : non-null " "input"); for (auto slab = slabs_.load(); slab != nullptr; slab = slab->next_) @@ -419,6 +419,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_SLABALLOCATOR_H_INCLUDED diff --git a/include/xrpl/basics/Slice.h b/include/xrpl/basics/Slice.h index 7733acab8e..aa98b0a358 100644 --- a/include/xrpl/basics/Slice.h +++ b/include/xrpl/basics/Slice.h @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { /** An immutable linear range of bytes. @@ -87,7 +87,7 @@ public: { XRPL_ASSERT( i < size_, - "ripple::Slice::operator[](std::size_t) const : valid input"); + "xrpl::Slice::operator[](std::size_t) const : valid input"); return data_[i]; } @@ -243,6 +243,6 @@ makeSlice(std::basic_string const& s) return Slice(s.data(), s.size()); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/StringUtilities.h b/include/xrpl/basics/StringUtilities.h index a38107909a..ebe07e43bc 100644 --- a/include/xrpl/basics/StringUtilities.h +++ b/include/xrpl/basics/StringUtilities.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Format arbitrary binary data as an SQLite "blob literal". @@ -132,6 +132,6 @@ to_uint64(std::string const& s); bool isProperlyFormedTomlDomain(std::string_view domain); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/TaggedCache.h b/include/xrpl/basics/TaggedCache.h index 77b8b3c6d4..c1d4d26800 100644 --- a/include/xrpl/basics/TaggedCache.h +++ b/include/xrpl/basics/TaggedCache.h @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Map/cache combination. This class implements a cache and a map. The cache keeps objects alive @@ -315,6 +315,6 @@ private: std::uint64_t m_misses; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/TaggedCache.ipp b/include/xrpl/basics/TaggedCache.ipp index 558198883c..5114479921 100644 --- a/include/xrpl/basics/TaggedCache.ipp +++ b/include/xrpl/basics/TaggedCache.ipp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { template < class Key, @@ -1005,6 +1005,6 @@ TaggedCache< }); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/ToString.h b/include/xrpl/basics/ToString.h index dc6903aa8a..fe3a6a0893 100644 --- a/include/xrpl/basics/ToString.h +++ b/include/xrpl/basics/ToString.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** to_string() generalizes std::to_string to handle bools, chars, and strings. @@ -43,6 +43,6 @@ to_string(char const* s) return s; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/UnorderedContainers.h b/include/xrpl/basics/UnorderedContainers.h index 3b847e4fbb..fdd2518b1e 100644 --- a/include/xrpl/basics/UnorderedContainers.h +++ b/include/xrpl/basics/UnorderedContainers.h @@ -22,7 +22,7 @@ * what container it is. */ -namespace ripple { +namespace xrpl { // hash containers @@ -102,6 +102,6 @@ template < using hardened_hash_multiset = std::unordered_multiset; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/UptimeClock.h b/include/xrpl/basics/UptimeClock.h index 36f4897663..9e1ef10d19 100644 --- a/include/xrpl/basics/UptimeClock.h +++ b/include/xrpl/basics/UptimeClock.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Tracks program uptime to seconds precision. @@ -45,6 +45,6 @@ private: start_clock(); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/algorithm.h b/include/xrpl/basics/algorithm.h index ad59e9c282..d62ff17a75 100644 --- a/include/xrpl/basics/algorithm.h +++ b/include/xrpl/basics/algorithm.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { // Requires: [first1, last1) and [first2, last2) are ordered ranges according to // comp. @@ -95,6 +95,6 @@ remove_if_intersect_or_match( return first1; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/base64.h b/include/xrpl/basics/base64.h index 0aa19e9e61..340e282f87 100644 --- a/include/xrpl/basics/base64.h +++ b/include/xrpl/basics/base64.h @@ -38,7 +38,7 @@ #include #include -namespace ripple { +namespace xrpl { std::string base64_encode(std::uint8_t const* data, std::size_t len); @@ -53,6 +53,6 @@ base64_encode(std::string const& s) std::string base64_decode(std::string_view data); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/base_uint.h b/include/xrpl/basics/base_uint.h index 4be4b35af3..a1ed223674 100644 --- a/include/xrpl/basics/base_uint.h +++ b/include/xrpl/basics/base_uint.h @@ -23,7 +23,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -275,7 +275,7 @@ public: { XRPL_ASSERT( c.size() * sizeof(typename Container::value_type) == size(), - "ripple::base_uint::base_uint(Container auto) : input size match"); + "xrpl::base_uint::base_uint(Container auto) : input size match"); std::memcpy(data_.data(), c.data(), size()); } @@ -288,7 +288,7 @@ public: { XRPL_ASSERT( c.size() * sizeof(typename Container::value_type) == size(), - "ripple::base_uint::operator=(Container auto) : input size match"); + "xrpl::base_uint::operator=(Container auto) : input size match"); std::memcpy(data_.data(), c.data(), size()); return *this; } @@ -648,12 +648,12 @@ static_assert(sizeof(uint192) == 192 / 8, "There should be no padding bytes"); static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes"); #endif -} // namespace ripple +} // namespace xrpl namespace beast { template -struct is_uniquely_represented> +struct is_uniquely_represented> : public std::true_type { explicit is_uniquely_represented() = default; diff --git a/include/xrpl/basics/chrono.h b/include/xrpl/basics/chrono.h index 46b36ffb57..e343e8b49f 100644 --- a/include/xrpl/basics/chrono.h +++ b/include/xrpl/basics/chrono.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { // A few handy aliases @@ -104,6 +104,6 @@ stopwatch() return beast::get_abstract_clock(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/comparators.h b/include/xrpl/basics/comparators.h index 4858a0ad74..7c848f0b3b 100644 --- a/include/xrpl/basics/comparators.h +++ b/include/xrpl/basics/comparators.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { #ifdef _MSC_VER @@ -52,6 +52,6 @@ using equal_to = std::equal_to; #endif -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/contract.h b/include/xrpl/basics/contract.h index a0409ee6d7..63d1bb5a84 100644 --- a/include/xrpl/basics/contract.h +++ b/include/xrpl/basics/contract.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /* Programming By Contract @@ -52,6 +52,6 @@ Throw(Args&&... args) [[noreturn]] void LogicError(std::string const& how) noexcept; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/hardened_hash.h b/include/xrpl/basics/hardened_hash.h index c21cd48053..a25dcb3c34 100644 --- a/include/xrpl/basics/hardened_hash.h +++ b/include/xrpl/basics/hardened_hash.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -92,6 +92,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/join.h b/include/xrpl/basics/join.h index a4a537d6d0..79f716ec43 100644 --- a/include/xrpl/basics/join.h +++ b/include/xrpl/basics/join.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { template Stream& @@ -85,6 +85,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/make_SSLContext.h b/include/xrpl/basics/make_SSLContext.h index 6e25cfcac1..fb91dd40a9 100644 --- a/include/xrpl/basics/make_SSLContext.h +++ b/include/xrpl/basics/make_SSLContext.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { /** Create a self-signed SSL context that allows anonymous Diffie Hellman. */ std::shared_ptr @@ -19,6 +19,6 @@ make_SSLContextAuthed( std::string const& chainFile, std::string const& cipherList); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/mulDiv.h b/include/xrpl/basics/mulDiv.h index 0ac9bb5ebc..fb38d0cd63 100644 --- a/include/xrpl/basics/mulDiv.h +++ b/include/xrpl/basics/mulDiv.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { auto constexpr muldiv_max = std::numeric_limits::max(); /** Return value*mul/div accurately. @@ -21,6 +21,6 @@ auto constexpr muldiv_max = std::numeric_limits::max(); std::optional mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/partitioned_unordered_map.h b/include/xrpl/basics/partitioned_unordered_map.h index 01872963fd..518686c533 100644 --- a/include/xrpl/basics/partitioned_unordered_map.h +++ b/include/xrpl/basics/partitioned_unordered_map.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { template static std::size_t @@ -242,7 +242,7 @@ public: map_.resize(partitions_); XRPL_ASSERT( partitions_, - "ripple::partitioned_unordered_map::partitioned_unordered_map : " + "xrpl::partitioned_unordered_map::partitioned_unordered_map : " "nonzero partitions"); } @@ -401,6 +401,6 @@ private: mutable partition_map_type map_{}; }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_PARTITIONED_UNORDERED_MAP_H diff --git a/include/xrpl/basics/random.h b/include/xrpl/basics/random.h index 19f8b57285..737b8fef59 100644 --- a/include/xrpl/basics/random.h +++ b/include/xrpl/basics/random.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { #ifndef __INTELLISENSE__ static_assert( @@ -95,7 +95,7 @@ std::enable_if_t< Integral> rand_int(Engine& engine, Integral min, Integral max) { - XRPL_ASSERT(max > min, "ripple::rand_int : max over min inputs"); + XRPL_ASSERT(max > min, "xrpl::rand_int : max over min inputs"); // This should have no state and constructing it should // be very cheap. If that turns out not to be the case @@ -186,6 +186,6 @@ rand_bool() } /** @} */ -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_RANDOM_H_INCLUDED diff --git a/include/xrpl/basics/safe_cast.h b/include/xrpl/basics/safe_cast.h index 1da44920ac..89de0eda6a 100644 --- a/include/xrpl/basics/safe_cast.h +++ b/include/xrpl/basics/safe_cast.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { // safe_cast adds compile-time checks to a static_cast to ensure that // the destination can hold all values of the source. This is particularly @@ -80,6 +80,6 @@ inline constexpr std:: return unsafe_cast(static_cast>(s)); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/scope.h b/include/xrpl/basics/scope.h index 710b31ec80..b7299a28fc 100644 --- a/include/xrpl/basics/scope.h +++ b/include/xrpl/basics/scope.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { // RAII scope helpers. As specified in Library Fundamental, Version 3 // Basic design of idea: https://www.youtube.com/watch?v=WjTrfoiB0MQ @@ -218,7 +218,7 @@ public: { XRPL_ASSERT( plock->owns_lock(), - "ripple::scope_unlock::scope_unlock : mutex must be locked"); + "xrpl::scope_unlock::scope_unlock : mutex must be locked"); plock->unlock(); } @@ -236,6 +236,6 @@ public: template scope_unlock(std::unique_lock&) -> scope_unlock; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/spinlock.h b/include/xrpl/basics/spinlock.h index 9ae7b0bb70..71ab29f381 100644 --- a/include/xrpl/basics/spinlock.h +++ b/include/xrpl/basics/spinlock.h @@ -13,7 +13,7 @@ #include #endif -namespace ripple { +namespace xrpl { namespace detail { /** Inform the processor that we are in a tight spin-wait loop. @@ -105,7 +105,7 @@ public: { XRPL_ASSERT( index >= 0 && (mask_ != 0), - "ripple::packed_spinlock::packed_spinlock : valid index and mask"); + "xrpl::packed_spinlock::packed_spinlock : valid index and mask"); } [[nodiscard]] bool @@ -206,6 +206,6 @@ public: }; /** @} */ -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/strHex.h b/include/xrpl/basics/strHex.h index bfba76003e..1c1d94bf32 100644 --- a/include/xrpl/basics/strHex.h +++ b/include/xrpl/basics/strHex.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { template std::string @@ -28,6 +28,6 @@ strHex(T const& from) return strHex(from.begin(), from.end()); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/basics/tagged_integer.h b/include/xrpl/basics/tagged_integer.h index 1ad5279469..1d40b31cce 100644 --- a/include/xrpl/basics/tagged_integer.h +++ b/include/xrpl/basics/tagged_integer.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A type-safe wrap around standard integral types @@ -197,11 +197,11 @@ public: } }; -} // namespace ripple +} // namespace xrpl namespace beast { template -struct is_contiguously_hashable, HashAlgorithm> +struct is_contiguously_hashable, HashAlgorithm> : public is_contiguously_hashable { explicit is_contiguously_hashable() = default; diff --git a/include/xrpl/core/ClosureCounter.h b/include/xrpl/core/ClosureCounter.h index 6050e32618..d2be76fa8c 100644 --- a/include/xrpl/core/ClosureCounter.h +++ b/include/xrpl/core/ClosureCounter.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** * The role of a `ClosureCounter` is to assist in shutdown by letting callers @@ -202,6 +202,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_CORE_CLOSURE_COUNTER_H_INCLUDED diff --git a/include/xrpl/core/Coro.ipp b/include/xrpl/core/Coro.ipp index 8e14e88592..9f73d80647 100644 --- a/include/xrpl/core/Coro.ipp +++ b/include/xrpl/core/Coro.ipp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { template JobQueue::Coro::Coro( @@ -34,7 +34,7 @@ JobQueue::Coro::Coro( inline JobQueue::Coro::~Coro() { #ifndef NDEBUG - XRPL_ASSERT(finished_, "ripple::JobQueue::Coro::~Coro : is finished"); + XRPL_ASSERT(finished_, "xrpl::JobQueue::Coro::~Coro : is finished"); #endif } @@ -85,8 +85,7 @@ JobQueue::Coro::resume() detail::getLocalValues().reset(&lvs_); std::lock_guard lock(mutex_); XRPL_ASSERT( - static_cast(coro_), - "ripple::JobQueue::Coro::resume : is runnable"); + static_cast(coro_), "xrpl::JobQueue::Coro::resume : is runnable"); coro_(); detail::getLocalValues().release(); detail::getLocalValues().reset(saved); @@ -129,6 +128,6 @@ JobQueue::Coro::join() cv_.wait(lk, [this]() { return running_ == false; }); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/Job.h b/include/xrpl/core/Job.h index 35d42cfd0b..cb597b3860 100644 --- a/include/xrpl/core/Job.h +++ b/include/xrpl/core/Job.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { // Note that this queue should only be used for CPU-bound jobs // It is primarily intended for signature checking @@ -131,6 +131,6 @@ private: using JobCounter = ClosureCounter; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/JobQueue.h b/include/xrpl/core/JobQueue.h index f8b727471b..2a22b7f5c9 100644 --- a/include/xrpl/core/JobQueue.h +++ b/include/xrpl/core/JobQueue.h @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { namespace perf { class PerfLog; @@ -382,11 +382,11 @@ private: lock is released which only happens after the coroutine completes. */ -} // namespace ripple +} // namespace xrpl #include -namespace ripple { +namespace xrpl { template std::shared_ptr @@ -408,6 +408,6 @@ JobQueue::postCoro(JobType t, std::string const& name, F&& f) return coro; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/JobTypeData.h b/include/xrpl/core/JobTypeData.h index eb678d1a9a..377309aa3c 100644 --- a/include/xrpl/core/JobTypeData.h +++ b/include/xrpl/core/JobTypeData.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { struct JobTypeData { @@ -83,6 +83,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/JobTypeInfo.h b/include/xrpl/core/JobTypeInfo.h index 09c644fc23..a726fb276b 100644 --- a/include/xrpl/core/JobTypeInfo.h +++ b/include/xrpl/core/JobTypeInfo.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Holds all the 'static' information about a job, which does not change */ class JobTypeInfo @@ -78,6 +78,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/JobTypes.h b/include/xrpl/core/JobTypes.h index d8e7b23bdf..f7952ca9a2 100644 --- a/include/xrpl/core/JobTypes.h +++ b/include/xrpl/core/JobTypes.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class JobTypes { @@ -35,7 +35,7 @@ private: std::chrono::milliseconds peakLatency) { XRPL_ASSERT( m_map.find(jt) == m_map.end(), - "ripple::JobTypes::JobTypes::add : unique job type input"); + "xrpl::JobTypes::JobTypes::add : unique job type input"); [[maybe_unused]] auto const inserted = m_map @@ -48,7 +48,7 @@ private: XRPL_ASSERT( inserted == true, - "ripple::JobTypes::JobTypes::add : input is inserted"); + "xrpl::JobTypes::JobTypes::add : input is inserted"); }; // clang-format off @@ -122,7 +122,7 @@ public: get(JobType jt) const { Map::const_iterator const iter(m_map.find(jt)); - XRPL_ASSERT(iter != m_map.end(), "ripple::JobTypes::get : valid input"); + XRPL_ASSERT(iter != m_map.end(), "xrpl::JobTypes::get : valid input"); if (iter != m_map.end()) return iter->second; @@ -170,6 +170,6 @@ public: Map m_map; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/LoadEvent.h b/include/xrpl/core/LoadEvent.h index b6cd0ab500..8422fe883e 100644 --- a/include/xrpl/core/LoadEvent.h +++ b/include/xrpl/core/LoadEvent.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class LoadMonitor; @@ -65,6 +65,6 @@ private: std::chrono::steady_clock::duration timeRunning_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/LoadMonitor.h b/include/xrpl/core/LoadMonitor.h index 539a4a0b99..54cd607d5b 100644 --- a/include/xrpl/core/LoadMonitor.h +++ b/include/xrpl/core/LoadMonitor.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { // Monitors load levels and response times @@ -67,6 +67,6 @@ private: beast::Journal const j_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/PerfLog.h b/include/xrpl/core/PerfLog.h index c74608d82a..eb009de433 100644 --- a/include/xrpl/core/PerfLog.h +++ b/include/xrpl/core/PerfLog.h @@ -17,7 +17,7 @@ namespace beast { class Journal; } -namespace ripple { +namespace xrpl { class Application; namespace perf { @@ -187,6 +187,6 @@ measureDurationAndLog( } } // namespace perf -} // namespace ripple +} // namespace xrpl #endif // XRPL_CORE_PERFLOG_H diff --git a/include/xrpl/core/detail/Workers.h b/include/xrpl/core/detail/Workers.h index 5877638722..3a77f9e769 100644 --- a/include/xrpl/core/detail/Workers.h +++ b/include/xrpl/core/detail/Workers.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace perf { class PerfLog; @@ -214,6 +214,6 @@ private: m_paused; // holds just paused workers }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/core/detail/semaphore.h b/include/xrpl/core/detail/semaphore.h index 8b784e3685..4249b3b860 100644 --- a/include/xrpl/core/detail/semaphore.h +++ b/include/xrpl/core/detail/semaphore.h @@ -1,6 +1,6 @@ /** * - * TODO: Remove ripple::basic_semaphore (and this file) and use + * TODO: Remove xrpl::basic_semaphore (and this file) and use * std::counting_semaphore. * * Background: @@ -32,7 +32,7 @@ #include #include -namespace ripple { +namespace xrpl { template class basic_semaphore @@ -87,6 +87,6 @@ public: using semaphore = basic_semaphore; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/crypto/RFC1751.h b/include/xrpl/crypto/RFC1751.h index 14c49d7fa9..a413c2ac8a 100644 --- a/include/xrpl/crypto/RFC1751.h +++ b/include/xrpl/crypto/RFC1751.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class RFC1751 { @@ -42,6 +42,6 @@ private: static char const* s_dictionary[]; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/crypto/csprng.h b/include/xrpl/crypto/csprng.h index cc5545750d..dc89da4f61 100644 --- a/include/xrpl/crypto/csprng.h +++ b/include/xrpl/crypto/csprng.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** A cryptographically secure random number engine @@ -70,6 +70,6 @@ public: csprng_engine& crypto_prng(); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/crypto/secure_erase.h b/include/xrpl/crypto/secure_erase.h index 586a8e50e6..3ecde0c7fa 100644 --- a/include/xrpl/crypto/secure_erase.h +++ b/include/xrpl/crypto/secure_erase.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Attempts to clear the given blob of memory. @@ -22,6 +22,6 @@ namespace ripple { void secure_erase(void* dest, std::size_t bytes); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/json/JsonPropertyStream.h b/include/xrpl/json/JsonPropertyStream.h index a7fe52dfb8..54cfcbfa04 100644 --- a/include/xrpl/json/JsonPropertyStream.h +++ b/include/xrpl/json/JsonPropertyStream.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A PropertyStream::Sink which produces a Json::Value of type objectValue. */ class JsonPropertyStream : public beast::PropertyStream @@ -66,6 +66,6 @@ protected: add(std::string const& v) override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/json/Writer.h b/include/xrpl/json/Writer.h index 12599a14d3..ab52427a5b 100644 --- a/include/xrpl/json/Writer.h +++ b/include/xrpl/json/Writer.h @@ -234,7 +234,7 @@ inline void check(bool condition, std::string const& message) { if (!condition) - ripple::Throw(message); + xrpl::Throw(message); } } // namespace Json diff --git a/include/xrpl/json/detail/json_assert.h b/include/xrpl/json/detail/json_assert.h index bd111ad90f..3092b65452 100644 --- a/include/xrpl/json/detail/json_assert.h +++ b/include/xrpl/json/detail/json_assert.h @@ -6,6 +6,6 @@ #define JSON_ASSERT_MESSAGE(condition, message) \ if (!(condition)) \ - ripple::Throw(message); + xrpl::Throw(message); #endif diff --git a/include/xrpl/json/json_value.h b/include/xrpl/json/json_value.h index c14d5d5127..2e38f2e75e 100644 --- a/include/xrpl/json/json_value.h +++ b/include/xrpl/json/json_value.h @@ -199,7 +199,7 @@ public: Value(UInt value); Value(double value); Value(char const* value); - Value(ripple::Number const& value); + Value(xrpl::Number const& value); /** \brief Constructs a value from a static string. * Like other value string constructor but do not duplicate the string for @@ -430,7 +430,7 @@ private: }; inline Value -to_json(ripple::Number const& number) +to_json(xrpl::Number const& number) { return to_string(number); } diff --git a/include/xrpl/ledger/ApplyView.h b/include/xrpl/ledger/ApplyView.h index 5e283641da..393af2a7fd 100644 --- a/include/xrpl/ledger/ApplyView.h +++ b/include/xrpl/ledger/ApplyView.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { enum ApplyFlags : std::uint32_t { tapNONE = 0x00, @@ -267,7 +267,7 @@ public: { // LCOV_EXCL_START UNREACHABLE( - "ripple::ApplyView::dirAppend : only Offers are appended to " + "xrpl::ApplyView::dirAppend : only Offers are appended to " "book directories"); // Only Offers are appended to book directories. Call dirInsert() // instead @@ -407,6 +407,6 @@ insertPage( std::function const&)> const& describe); } // namespace directory -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/ApplyViewImpl.h b/include/xrpl/ledger/ApplyViewImpl.h index c1e9ccd359..0c11726135 100644 --- a/include/xrpl/ledger/ApplyViewImpl.h +++ b/include/xrpl/ledger/ApplyViewImpl.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Editable, discardable view that can build metadata for one tx. @@ -75,6 +75,6 @@ private: std::optional deliver_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/BookDirs.h b/include/xrpl/ledger/BookDirs.h index 1019d02f52..daa1ef172a 100644 --- a/include/xrpl/ledger/BookDirs.h +++ b/include/xrpl/ledger/BookDirs.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class BookDirs { @@ -89,6 +89,6 @@ private: static beast::Journal j_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/CachedSLEs.h b/include/xrpl/ledger/CachedSLEs.h index 0bec37f233..b478b78b7d 100644 --- a/include/xrpl/ledger/CachedSLEs.h +++ b/include/xrpl/ledger/CachedSLEs.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { using CachedSLEs = TaggedCache; } diff --git a/include/xrpl/ledger/CachedView.h b/include/xrpl/ledger/CachedView.h index b78c046f58..c1d66ecfc9 100644 --- a/include/xrpl/ledger/CachedView.h +++ b/include/xrpl/ledger/CachedView.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -164,6 +164,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/CredentialHelpers.h b/include/xrpl/ledger/CredentialHelpers.h index 42376846ae..52ddfe33aa 100644 --- a/include/xrpl/ledger/CredentialHelpers.h +++ b/include/xrpl/ledger/CredentialHelpers.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace credentials { // These function will be used by the code that use DepositPreauth / Credentials @@ -93,6 +93,6 @@ verifyDepositPreauth( std::shared_ptr const& sleDst, beast::Journal j); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/Dir.h b/include/xrpl/ledger/Dir.h index b421ac85e6..4b7327a015 100644 --- a/include/xrpl/ledger/Dir.h +++ b/include/xrpl/ledger/Dir.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A class that simplifies iterating ledger directory pages @@ -108,6 +108,6 @@ private: std::vector::const_iterator it_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/OpenView.h b/include/xrpl/ledger/OpenView.h index 2b4bd8a31f..bd90dbef18 100644 --- a/include/xrpl/ledger/OpenView.h +++ b/include/xrpl/ledger/OpenView.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Open ledger construction tag. @@ -252,6 +252,6 @@ public: std::shared_ptr const& metaData) override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/PaymentSandbox.h b/include/xrpl/ledger/PaymentSandbox.h index 03f1ec2d00..e1d197380d 100644 --- a/include/xrpl/ledger/PaymentSandbox.h +++ b/include/xrpl/ledger/PaymentSandbox.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { @@ -188,6 +188,6 @@ private: PaymentSandbox const* ps_ = nullptr; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/RawView.h b/include/xrpl/ledger/RawView.h index 94668b42a1..c0e81fb833 100644 --- a/include/xrpl/ledger/RawView.h +++ b/include/xrpl/ledger/RawView.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Interface for ledger entry changes. @@ -87,6 +87,6 @@ public: std::shared_ptr const& metaData) = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/ReadView.h b/include/xrpl/ledger/ReadView.h index 70a5fbc006..d2b6796ec9 100644 --- a/include/xrpl/ledger/ReadView.h +++ b/include/xrpl/ledger/ReadView.h @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { //------------------------------------------------------------------------------ @@ -258,7 +258,7 @@ makeRulesGivenLedger( DigestAwareReadView const& ledger, std::unordered_set> const& presets); -} // namespace ripple +} // namespace xrpl #include diff --git a/include/xrpl/ledger/Sandbox.h b/include/xrpl/ledger/Sandbox.h index 9c341c15c4..1e4a816529 100644 --- a/include/xrpl/ledger/Sandbox.h +++ b/include/xrpl/ledger/Sandbox.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Discardable, editable view to a ledger. @@ -39,6 +39,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/View.h b/include/xrpl/ledger/View.h index fc16d53e61..767622596b 100644 --- a/include/xrpl/ledger/View.h +++ b/include/xrpl/ledger/View.h @@ -20,7 +20,7 @@ #include #include -namespace ripple { +namespace xrpl { enum class WaiveTransferFee : bool { No = false, Yes }; enum class SkipEntry : bool { No = false, Yes }; @@ -1197,6 +1197,6 @@ sharesToAssetsWithdraw( bool after(NetClock::time_point now, std::uint32_t mark); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/detail/ApplyStateTable.h b/include/xrpl/ledger/detail/ApplyStateTable.h index 887e2e7770..f5ec0c9f51 100644 --- a/include/xrpl/ledger/detail/ApplyStateTable.h +++ b/include/xrpl/ledger/detail/ApplyStateTable.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { // Helper class that buffers modifications @@ -139,6 +139,6 @@ private: }; } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/detail/ApplyViewBase.h b/include/xrpl/ledger/detail/ApplyViewBase.h index a75f94ac16..9992d73ad1 100644 --- a/include/xrpl/ledger/detail/ApplyViewBase.h +++ b/include/xrpl/ledger/detail/ApplyViewBase.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { class ApplyViewBase : public ApplyView, public RawView @@ -106,6 +106,6 @@ protected: }; } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/detail/RawStateTable.h b/include/xrpl/ledger/detail/RawStateTable.h index b89e6e58a9..19d2882a63 100644 --- a/include/xrpl/ledger/detail/RawStateTable.h +++ b/include/xrpl/ledger/detail/RawStateTable.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { // Helper class that buffers raw modifications @@ -118,6 +118,6 @@ private: }; } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/detail/ReadViewFwdRange.h b/include/xrpl/ledger/detail/ReadViewFwdRange.h index 66984c8665..557bba4987 100644 --- a/include/xrpl/ledger/detail/ReadViewFwdRange.h +++ b/include/xrpl/ledger/detail/ReadViewFwdRange.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class ReadView; @@ -130,6 +130,6 @@ protected: }; } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/ledger/detail/ReadViewFwdRange.ipp b/include/xrpl/ledger/detail/ReadViewFwdRange.ipp index 451d612486..e86246133a 100644 --- a/include/xrpl/ledger/detail/ReadViewFwdRange.ipp +++ b/include/xrpl/ledger/detail/ReadViewFwdRange.ipp @@ -1,7 +1,7 @@ #ifndef XRPL_LEDGER_READVIEWFWDRANGEINL_H_INCLUDED #define XRPL_LEDGER_READVIEWFWDRANGEINL_H_INCLUDED -namespace ripple { +namespace xrpl { namespace detail { template @@ -63,7 +63,7 @@ ReadViewFwdRange::iterator::operator==(iterator const& other) const { XRPL_ASSERT( view_ == other.view_, - "ripple::detail::ReadViewFwdRange::iterator::operator==(iterator) " + "xrpl::detail::ReadViewFwdRange::iterator::operator==(iterator) " "const : input view match"); if (impl_ != nullptr && other.impl_ != nullptr) @@ -115,6 +115,6 @@ ReadViewFwdRange::iterator::operator++(int) -> iterator } } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/net/AutoSocket.h b/include/xrpl/net/AutoSocket.h index 7cdef5ddd1..2fcba5780c 100644 --- a/include/xrpl/net/AutoSocket.h +++ b/include/xrpl/net/AutoSocket.h @@ -269,7 +269,7 @@ protected: error_code const& ec, size_t bytesTransferred) { - using namespace ripple; + using namespace xrpl; if (ec) { diff --git a/include/xrpl/net/HTTPClient.h b/include/xrpl/net/HTTPClient.h index fc0d416f02..6e4d4ce685 100644 --- a/include/xrpl/net/HTTPClient.h +++ b/include/xrpl/net/HTTPClient.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Provides an asynchronous HTTP client implementation with optional SSL. */ @@ -75,6 +75,6 @@ public: beast::Journal& j); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/net/HTTPClientSSLContext.h b/include/xrpl/net/HTTPClientSSLContext.h index a22ee839b8..b8dfbd3e09 100644 --- a/include/xrpl/net/HTTPClientSSLContext.h +++ b/include/xrpl/net/HTTPClientSSLContext.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { class HTTPClientSSLContext { @@ -176,6 +176,6 @@ private: bool const verify_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/net/RegisterSSLCerts.h b/include/xrpl/net/RegisterSSLCerts.h index 5b0879fe4d..f9b865c3aa 100644 --- a/include/xrpl/net/RegisterSSLCerts.h +++ b/include/xrpl/net/RegisterSSLCerts.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { /** Register default SSL certificates. Register the system default SSL root certificates. On linux/mac, @@ -19,6 +19,6 @@ registerSSLCerts( boost::system::error_code&, beast::Journal j); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/Backend.h b/include/xrpl/nodestore/Backend.h index 741145c9c9..0ea8835f61 100644 --- a/include/xrpl/nodestore/Backend.h +++ b/include/xrpl/nodestore/Backend.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { /** A backend used for the NodeStore. @@ -143,6 +143,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/Database.h b/include/xrpl/nodestore/Database.h index b27bccf0f1..474f873876 100644 --- a/include/xrpl/nodestore/Database.h +++ b/include/xrpl/nodestore/Database.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { @@ -230,7 +230,7 @@ protected: { XRPL_ASSERT( count <= sz, - "ripple::NodeStore::Database::storeStats : valid inputs"); + "xrpl::NodeStore::Database::storeStats : valid inputs"); storeCount_ += count; storeSz_ += sz; } @@ -291,6 +291,6 @@ private: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/DatabaseRotating.h b/include/xrpl/nodestore/DatabaseRotating.h index ea4a966dde..85202e7a84 100644 --- a/include/xrpl/nodestore/DatabaseRotating.h +++ b/include/xrpl/nodestore/DatabaseRotating.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { /* This class has two key-value store Backend objects for persisting SHAMap @@ -39,6 +39,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/DummyScheduler.h b/include/xrpl/nodestore/DummyScheduler.h index a8d6fcec18..9ffe5ad80d 100644 --- a/include/xrpl/nodestore/DummyScheduler.h +++ b/include/xrpl/nodestore/DummyScheduler.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { /** Simple NodeStore Scheduler that just peforms the tasks synchronously. */ @@ -21,6 +21,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/Factory.h b/include/xrpl/nodestore/Factory.h index 2309a0bf90..d6d33c4b64 100644 --- a/include/xrpl/nodestore/Factory.h +++ b/include/xrpl/nodestore/Factory.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { @@ -61,6 +61,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/Manager.h b/include/xrpl/nodestore/Manager.h index 6764967353..fe4b1c614e 100644 --- a/include/xrpl/nodestore/Manager.h +++ b/include/xrpl/nodestore/Manager.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { @@ -83,6 +83,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/NodeObject.h b/include/xrpl/nodestore/NodeObject.h index 6e4eae2c81..6a69245fd2 100644 --- a/include/xrpl/nodestore/NodeObject.h +++ b/include/xrpl/nodestore/NodeObject.h @@ -7,7 +7,7 @@ // VFALCO NOTE Intentionally not in the NodeStore namespace -namespace ripple { +namespace xrpl { /** The types of node objects. */ enum NodeObjectType : std::uint32_t { @@ -81,6 +81,6 @@ private: Blob const mData; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/Scheduler.h b/include/xrpl/nodestore/Scheduler.h index b9a9f8b5f4..0835e08fa2 100644 --- a/include/xrpl/nodestore/Scheduler.h +++ b/include/xrpl/nodestore/Scheduler.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { enum class FetchType { synchronous, async }; @@ -66,6 +66,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/Task.h b/include/xrpl/nodestore/Task.h index 44b28ec9c6..bd21e61975 100644 --- a/include/xrpl/nodestore/Task.h +++ b/include/xrpl/nodestore/Task.h @@ -1,7 +1,7 @@ #ifndef XRPL_NODESTORE_TASK_H_INCLUDED #define XRPL_NODESTORE_TASK_H_INCLUDED -namespace ripple { +namespace xrpl { namespace NodeStore { /** Derived classes perform scheduled tasks. */ @@ -17,6 +17,6 @@ struct Task }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/Types.h b/include/xrpl/nodestore/Types.h index 38481c14e8..6763196860 100644 --- a/include/xrpl/nodestore/Types.h +++ b/include/xrpl/nodestore/Types.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { enum { @@ -37,6 +37,6 @@ using Batch = std::vector>; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/detail/BatchWriter.h b/include/xrpl/nodestore/detail/BatchWriter.h index 3776029c25..f1faf0a612 100644 --- a/include/xrpl/nodestore/detail/BatchWriter.h +++ b/include/xrpl/nodestore/detail/BatchWriter.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { /** Batch-writing assist logic. @@ -78,6 +78,6 @@ private: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/detail/DatabaseNodeImp.h b/include/xrpl/nodestore/detail/DatabaseNodeImp.h index b70fbf640b..bf222129cc 100644 --- a/include/xrpl/nodestore/detail/DatabaseNodeImp.h +++ b/include/xrpl/nodestore/detail/DatabaseNodeImp.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { class DatabaseNodeImp : public Database @@ -59,7 +59,7 @@ public: XRPL_ASSERT( backend_, - "ripple::NodeStore::DatabaseNodeImp::DatabaseNodeImp : non-null " + "xrpl::NodeStore::DatabaseNodeImp::DatabaseNodeImp : non-null " "backend"); } @@ -138,6 +138,6 @@ private: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/detail/DatabaseRotatingImp.h b/include/xrpl/nodestore/detail/DatabaseRotatingImp.h index 847bc08dbc..63d628a30a 100644 --- a/include/xrpl/nodestore/detail/DatabaseRotatingImp.h +++ b/include/xrpl/nodestore/detail/DatabaseRotatingImp.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { class DatabaseRotatingImp : public DatabaseRotating @@ -79,6 +79,6 @@ private: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/detail/DecodedBlob.h b/include/xrpl/nodestore/detail/DecodedBlob.h index ed39bab39c..0eaa169269 100644 --- a/include/xrpl/nodestore/detail/DecodedBlob.h +++ b/include/xrpl/nodestore/detail/DecodedBlob.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { /** Parsed key/value blob into NodeObject components. @@ -43,6 +43,6 @@ private: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/detail/EncodedBlob.h b/include/xrpl/nodestore/detail/EncodedBlob.h index 64442bf8c6..2cd35a7b6f 100644 --- a/include/xrpl/nodestore/detail/EncodedBlob.h +++ b/include/xrpl/nodestore/detail/EncodedBlob.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { /** Convert a NodeObject from in-memory to database format. @@ -64,7 +64,7 @@ public: : size_([&obj]() { XRPL_ASSERT( obj, - "ripple::NodeStore::EncodedBlob::EncodedBlob : non-null input"); + "xrpl::NodeStore::EncodedBlob::EncodedBlob : non-null input"); if (!obj) throw std::runtime_error( @@ -87,7 +87,7 @@ public: XRPL_ASSERT( ((ptr_ == payload_.data()) && (size_ <= payload_.size())) || ((ptr_ != payload_.data()) && (size_ > payload_.size())), - "ripple::NodeStore::EncodedBlob::~EncodedBlob : valid payload " + "xrpl::NodeStore::EncodedBlob::~EncodedBlob : valid payload " "pointer"); if (ptr_ != payload_.data()) @@ -114,6 +114,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/detail/ManagerImp.h b/include/xrpl/nodestore/detail/ManagerImp.h index 139ca903c2..fd3de8a7ca 100644 --- a/include/xrpl/nodestore/detail/ManagerImp.h +++ b/include/xrpl/nodestore/detail/ManagerImp.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { @@ -50,6 +50,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/detail/codec.h b/include/xrpl/nodestore/detail/codec.h index f3e80c5a6a..e02d3963bd 100644 --- a/include/xrpl/nodestore/detail/codec.h +++ b/include/xrpl/nodestore/detail/codec.h @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { template @@ -322,6 +322,6 @@ filter_inner(void* in, std::size_t in_size) } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/nodestore/detail/varint.h b/include/xrpl/nodestore/detail/varint.h index a8f19d0871..7cf9fbaf4b 100644 --- a/include/xrpl/nodestore/detail/varint.h +++ b/include/xrpl/nodestore/detail/varint.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { // This is a variant of the base128 varint format from @@ -118,6 +118,6 @@ write(nudb::detail::ostream& os, std::size_t t) } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/AMMCore.h b/include/xrpl/protocol/AMMCore.h index a55ae5490d..e259089367 100644 --- a/include/xrpl/protocol/AMMCore.h +++ b/include/xrpl/protocol/AMMCore.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { std::uint16_t constexpr TRADING_FEE_THRESHOLD = 1000; // 1% @@ -102,6 +102,6 @@ feeMultHalf(std::uint16_t tfee) return 1 - getFee(tfee) / 2; } -} // namespace ripple +} // namespace xrpl #endif // XRPL_PROTOCOL_AMMCORE_H_INCLUDED diff --git a/include/xrpl/protocol/AccountID.h b/include/xrpl/protocol/AccountID.h index ddf044e2aa..d61938e2a7 100644 --- a/include/xrpl/protocol/AccountID.h +++ b/include/xrpl/protocol/AccountID.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -103,15 +103,15 @@ operator<<(std::ostream& os, AccountID const& x) void initAccountIdCache(std::size_t count); -} // namespace ripple +} // namespace xrpl //------------------------------------------------------------------------------ namespace Json { template <> -inline ripple::AccountID -getOrThrow(Json::Value const& v, ripple::SField const& field) +inline xrpl::AccountID +getOrThrow(Json::Value const& v, xrpl::SField const& field) { - using namespace ripple; + using namespace xrpl; std::string const b58 = getOrThrow(v, field); if (auto const r = parseBase58(b58)) @@ -127,7 +127,7 @@ namespace std { // DEPRECATED // VFALCO Use beast::uhash or a hardened container template <> -struct hash : ripple::AccountID::hasher +struct hash : xrpl::AccountID::hasher { hash() = default; }; diff --git a/include/xrpl/protocol/AmountConversions.h b/include/xrpl/protocol/AmountConversions.h index 3c870ed4b1..195e373fa0 100644 --- a/include/xrpl/protocol/AmountConversions.h +++ b/include/xrpl/protocol/AmountConversions.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { inline STAmount toSTAmount(IOUAmount const& iou, Issue const& iss) @@ -35,8 +35,7 @@ inline STAmount toSTAmount(XRPAmount const& xrp, Issue const& iss) { XRPL_ASSERT( - isXRP(iss.account) && isXRP(iss.currency), - "ripple::toSTAmount : is XRP"); + isXRP(iss.account) && isXRP(iss.currency), "xrpl::toSTAmount : is XRP"); return toSTAmount(xrp); } @@ -57,12 +56,12 @@ toAmount(STAmount const& amt) { XRPL_ASSERT( amt.mantissa() < std::numeric_limits::max(), - "ripple::toAmount : maximum mantissa"); + "xrpl::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); - XRPL_ASSERT(!isXRP(amt), "ripple::toAmount : is not XRP"); + XRPL_ASSERT(!isXRP(amt), "xrpl::toAmount : is not XRP"); return IOUAmount(sMant, amt.exponent()); } @@ -72,12 +71,12 @@ toAmount(STAmount const& amt) { XRPL_ASSERT( amt.mantissa() < std::numeric_limits::max(), - "ripple::toAmount : maximum mantissa"); + "xrpl::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); - XRPL_ASSERT(isXRP(amt), "ripple::toAmount : is XRP"); + XRPL_ASSERT(isXRP(amt), "xrpl::toAmount : is XRP"); return XRPAmount(sMant); } @@ -196,6 +195,6 @@ get(STAmount const& a) } } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/ApiVersion.h b/include/xrpl/protocol/ApiVersion.h index d83884008d..b2ee64621e 100644 --- a/include/xrpl/protocol/ApiVersion.h +++ b/include/xrpl/protocol/ApiVersion.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** * API version numbers used in later API versions @@ -64,7 +64,7 @@ setVersion(JsonObject& parent, unsigned int apiVersion, bool betaEnabled) { XRPL_ASSERT( apiVersion != apiInvalidVersion, - "ripple::RPC::setVersion : input is valid"); + "xrpl::RPC::setVersion : input is valid"); auto& retObj = addObject(parent, jss::version); if (apiVersion == apiVersionIfUnspecified) @@ -167,6 +167,6 @@ forAllApiVersions(Fn const& fn, Args&&... args) RPC::apiMaximumValidVersion>(fn, std::forward(args)...); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Asset.h b/include/xrpl/protocol/Asset.h index 7ad1e70256..b72c20d82c 100644 --- a/include/xrpl/protocol/Asset.h +++ b/include/xrpl/protocol/Asset.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class Asset; class STAmount; @@ -233,6 +233,6 @@ validJSONAsset(Json::Value const& jv); Asset assetFromJson(Json::Value const& jv); -} // namespace ripple +} // namespace xrpl #endif // XRPL_PROTOCOL_ASSET_H_INCLUDED diff --git a/include/xrpl/protocol/Batch.h b/include/xrpl/protocol/Batch.h index 73dd15e6e2..1404c8069f 100644 --- a/include/xrpl/protocol/Batch.h +++ b/include/xrpl/protocol/Batch.h @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { inline void serializeBatch( @@ -17,4 +17,4 @@ serializeBatch( msg.addBitString(txid); } -} // namespace ripple +} // namespace xrpl diff --git a/include/xrpl/protocol/Book.h b/include/xrpl/protocol/Book.h index cbc6e862b8..ddd315de30 100644 --- a/include/xrpl/protocol/Book.h +++ b/include/xrpl/protocol/Book.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { /** Specifies an order book. The order book is a pair of Issues called in and out. @@ -87,28 +87,28 @@ operator<=>(Book const& lhs, Book const& rhs) } /** @} */ -} // namespace ripple +} // namespace xrpl //------------------------------------------------------------------------------ namespace std { template <> -struct hash - : private boost::base_from_member, 0>, - private boost::base_from_member, 1> +struct hash + : private boost::base_from_member, 0>, + private boost::base_from_member, 1> { private: using currency_hash_type = - boost::base_from_member, 0>; + boost::base_from_member, 0>; using issuer_hash_type = - boost::base_from_member, 1>; + boost::base_from_member, 1>; public: hash() = default; using value_type = std::size_t; - using argument_type = ripple::Issue; + using argument_type = xrpl::Issue; value_type operator()(argument_type const& value) const @@ -124,11 +124,11 @@ public: //------------------------------------------------------------------------------ template <> -struct hash +struct hash { private: - using issue_hasher = std::hash; - using uint256_hasher = ripple::uint256::hasher; + using issue_hasher = std::hash; + using uint256_hasher = xrpl::uint256::hasher; issue_hasher m_issue_hasher; uint256_hasher m_uint256_hasher; @@ -137,7 +137,7 @@ public: hash() = default; using value_type = std::size_t; - using argument_type = ripple::Book; + using argument_type = xrpl::Book; value_type operator()(argument_type const& value) const @@ -159,21 +159,21 @@ public: namespace boost { template <> -struct hash : std::hash +struct hash : std::hash { hash() = default; - using Base = std::hash; + using Base = std::hash; // VFALCO NOTE broken in vs2012 // using Base::Base; // inherit ctors }; template <> -struct hash : std::hash +struct hash : std::hash { hash() = default; - using Base = std::hash; + using Base = std::hash; // VFALCO NOTE broken in vs2012 // using Base::Base; // inherit ctors }; diff --git a/include/xrpl/protocol/BuildInfo.h b/include/xrpl/protocol/BuildInfo.h index 8e692f7ca4..0b75f8b0a1 100644 --- a/include/xrpl/protocol/BuildInfo.h +++ b/include/xrpl/protocol/BuildInfo.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Versioning information for this build. */ // VFALCO The namespace is deprecated @@ -79,6 +79,6 @@ isNewerVersion(std::uint64_t version); } // namespace BuildInfo -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/ErrorCodes.h b/include/xrpl/protocol/ErrorCodes.h index 709a26093d..8d5d871aa1 100644 --- a/include/xrpl/protocol/ErrorCodes.h +++ b/include/xrpl/protocol/ErrorCodes.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { // VFALCO NOTE These are outside the RPC namespace @@ -360,6 +360,6 @@ error_code_http_status(error_code_i code); std::string rpcErrorString(Json::Value const& jv); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Feature.h b/include/xrpl/protocol/Feature.h index 193f0665dc..317bde3ee6 100644 --- a/include/xrpl/protocol/Feature.h +++ b/include/xrpl/protocol/Feature.h @@ -63,7 +63,7 @@ * */ -namespace ripple { +namespace xrpl { enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes }; enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported }; @@ -177,7 +177,7 @@ public: { XRPL_ASSERT( b.count() == count(), - "ripple::FeatureBitset::FeatureBitset(base) : count match"); + "xrpl::FeatureBitset::FeatureBitset(base) : count match"); } template @@ -186,7 +186,7 @@ public: initFromFeatures(f, std::forward(fs)...); XRPL_ASSERT( count() == (sizeof...(fs) + 1), - "ripple::FeatureBitset::FeatureBitset(uint256) : count and " + "xrpl::FeatureBitset::FeatureBitset(uint256) : count and " "sizeof... do match"); } @@ -197,7 +197,7 @@ public: set(featureToBitsetIndex(f)); XRPL_ASSERT( fs.size() == count(), - "ripple::FeatureBitset::FeatureBitset(Container auto) : count and " + "xrpl::FeatureBitset::FeatureBitset(Container auto) : count and " "size do match"); } @@ -365,6 +365,6 @@ foreachFeature(FeatureBitset bs, F&& f) #undef XRPL_FEATURE #pragma pop_macro("XRPL_FEATURE") -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Fees.h b/include/xrpl/protocol/Fees.h index 43ba6c9552..8c7cb51777 100644 --- a/include/xrpl/protocol/Fees.h +++ b/include/xrpl/protocol/Fees.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Reflects the fee settings for a particular ledger. @@ -33,6 +33,6 @@ struct Fees } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/HashPrefix.h b/include/xrpl/protocol/HashPrefix.h index 8c0cb53b5d..77529e9212 100644 --- a/include/xrpl/protocol/HashPrefix.h +++ b/include/xrpl/protocol/HashPrefix.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { @@ -82,6 +82,6 @@ hash_append(Hasher& h, HashPrefix const& hp) noexcept hash_append(h, static_cast(hp)); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/IOUAmount.h b/include/xrpl/protocol/IOUAmount.h index da2dbb3fa7..60a61a5825 100644 --- a/include/xrpl/protocol/IOUAmount.h +++ b/include/xrpl/protocol/IOUAmount.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Floating point representation of amounts with high dynamic range @@ -208,6 +208,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Indexes.h b/include/xrpl/protocol/Indexes.h index 69418fbd25..1cb22b4d6c 100644 --- a/include/xrpl/protocol/Indexes.h +++ b/include/xrpl/protocol/Indexes.h @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { class SeqProxy; /** Keylet computation funclets. @@ -203,7 +203,7 @@ inline Keylet page(Keylet const& root, std::uint64_t index = 0) noexcept { XRPL_ASSERT( - root.type == ltDIR_NODE, "ripple::keylet::page : valid root type"); + root.type == ltDIR_NODE, "xrpl::keylet::page : valid root type"); return page(root.key, index); } /** @} */ @@ -393,6 +393,6 @@ std::array, 6> const directAccountKeylets{ MPTID makeMptID(std::uint32_t sequence, AccountID const& account); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/InnerObjectFormats.h b/include/xrpl/protocol/InnerObjectFormats.h index 36ed515147..6d656d0065 100644 --- a/include/xrpl/protocol/InnerObjectFormats.h +++ b/include/xrpl/protocol/InnerObjectFormats.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Manages the list of known inner object formats. */ @@ -23,6 +23,6 @@ public: findSOTemplateBySField(SField const& sField) const; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Issue.h b/include/xrpl/protocol/Issue.h index c079f6d121..519d7a96f3 100644 --- a/include/xrpl/protocol/Issue.h +++ b/include/xrpl/protocol/Issue.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A currency issued by an account. @see Currency, AccountID, Issue, Book @@ -113,6 +113,6 @@ isXRP(Issue const& issue) return issue.native(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/KeyType.h b/include/xrpl/protocol/KeyType.h index 055c2c1efa..454c88780d 100644 --- a/include/xrpl/protocol/KeyType.h +++ b/include/xrpl/protocol/KeyType.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { enum class KeyType { secp256k1 = 0, @@ -42,6 +42,6 @@ operator<<(Stream& s, KeyType type) return s << to_string(type); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Keylet.h b/include/xrpl/protocol/Keylet.h index 0508287574..4380fdfdac 100644 --- a/include/xrpl/protocol/Keylet.h +++ b/include/xrpl/protocol/Keylet.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class STLedgerEntry; @@ -30,6 +30,6 @@ struct Keylet check(STLedgerEntry const&) const; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/KnownFormats.h b/include/xrpl/protocol/KnownFormats.h index ebb159163f..a928ed52be 100644 --- a/include/xrpl/protocol/KnownFormats.h +++ b/include/xrpl/protocol/KnownFormats.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Manages a list of known formats. @@ -183,6 +183,6 @@ private: boost::container::flat_map types_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/LedgerFormats.h b/include/xrpl/protocol/LedgerFormats.h index 64ae604f64..b52a25af17 100644 --- a/include/xrpl/protocol/LedgerFormats.h +++ b/include/xrpl/protocol/LedgerFormats.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Identifiers for on-ledger objects. @@ -210,6 +210,6 @@ public: getInstance(); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/LedgerHeader.h b/include/xrpl/protocol/LedgerHeader.h index 80a481f7d1..641f794cdb 100644 --- a/include/xrpl/protocol/LedgerHeader.h +++ b/include/xrpl/protocol/LedgerHeader.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Information about the notional ledger backing the view. */ struct LedgerHeader @@ -73,6 +73,6 @@ deserializeHeader(Slice data, bool hasHash = false); LedgerHeader deserializePrefixedHeader(Slice data, bool hasHash = false); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/MPTAmount.h b/include/xrpl/protocol/MPTAmount.h index af14786501..cc9528a923 100644 --- a/include/xrpl/protocol/MPTAmount.h +++ b/include/xrpl/protocol/MPTAmount.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { class MPTAmount : private boost::totally_ordered, private boost::additive, @@ -150,6 +150,6 @@ mulRatio( return MPTAmount(r.convert_to()); } -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_MPTAMOUNT_H_INCLUDED diff --git a/include/xrpl/protocol/MPTIssue.h b/include/xrpl/protocol/MPTIssue.h index b8e184d3cd..b89b59ee0d 100644 --- a/include/xrpl/protocol/MPTIssue.h +++ b/include/xrpl/protocol/MPTIssue.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /* Adapt MPTID to provide the same interface as Issue. Enables using static * polymorphism by Asset and other classes. MPTID is a 192-bit concatenation @@ -77,6 +77,6 @@ to_string(MPTIssue const& mptIssue); MPTIssue mptIssueFromJson(Json::Value const& jv); -} // namespace ripple +} // namespace xrpl #endif // XRPL_PROTOCOL_MPTISSUE_H_INCLUDED diff --git a/include/xrpl/protocol/MultiApiJson.h b/include/xrpl/protocol/MultiApiJson.h index e8738e2f9e..edf19b6f37 100644 --- a/include/xrpl/protocol/MultiApiJson.h +++ b/include/xrpl/protocol/MultiApiJson.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { template @@ -141,7 +141,7 @@ struct MultiApiJson { XRPL_ASSERT( valid(version) && index(version) >= 0 && index(version) < size, - "ripple::detail::MultiApiJson::operator() : valid " + "xrpl::detail::MultiApiJson::operator() : valid " "version"); return std::invoke( fn, @@ -161,7 +161,7 @@ struct MultiApiJson { XRPL_ASSERT( valid(version) && index(version) >= 0 && index(version) < size, - "ripple::detail::MultiApiJson::operator() : valid version"); + "xrpl::detail::MultiApiJson::operator() : valid version"); return std::invoke(fn, json.val[index(version)]); } } visitor = {}; @@ -217,6 +217,6 @@ struct MultiApiJson using MultiApiJson = detail:: MultiApiJson; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/NFTSyntheticSerializer.h b/include/xrpl/protocol/NFTSyntheticSerializer.h index 390d386410..7068ae34cd 100644 --- a/include/xrpl/protocol/NFTSyntheticSerializer.h +++ b/include/xrpl/protocol/NFTSyntheticSerializer.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { @@ -24,6 +24,6 @@ insertNFTSyntheticInJson( /** @} */ } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/NFTokenID.h b/include/xrpl/protocol/NFTokenID.h index 762af14d2f..03e30794d0 100644 --- a/include/xrpl/protocol/NFTokenID.h +++ b/include/xrpl/protocol/NFTokenID.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Add a `nftoken_ids` field to the `meta` output parameter. @@ -38,6 +38,6 @@ insertNFTokenID( TxMeta const& transactionMeta); /** @} */ -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/NFTokenOfferID.h b/include/xrpl/protocol/NFTokenOfferID.h index cf6427d201..5663653690 100644 --- a/include/xrpl/protocol/NFTokenOfferID.h +++ b/include/xrpl/protocol/NFTokenOfferID.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Add an `offer_id` field to the `meta` output parameter. @@ -33,6 +33,6 @@ insertNFTokenOfferID( TxMeta const& transactionMeta); /** @} */ -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/PayChan.h b/include/xrpl/protocol/PayChan.h index 5dcaa676a8..ad70913c45 100644 --- a/include/xrpl/protocol/PayChan.h +++ b/include/xrpl/protocol/PayChan.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { inline void serializePayChanAuthorization( @@ -19,6 +19,6 @@ serializePayChanAuthorization( msg.add64(amt.drops()); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Permissions.h b/include/xrpl/protocol/Permissions.h index 16ee729fe4..252605e641 100644 --- a/include/xrpl/protocol/Permissions.h +++ b/include/xrpl/protocol/Permissions.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** * We have both transaction type permissions and granular type permissions. * Since we will reuse the TransactionFormats to parse the Transaction @@ -83,6 +83,6 @@ public: permissionToTxType(uint32_t const& value) const; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Protocol.h b/include/xrpl/protocol/Protocol.h index ded16cad6d..fb315eace4 100644 --- a/include/xrpl/protocol/Protocol.h +++ b/include/xrpl/protocol/Protocol.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { /** Protocol specific constants. @@ -297,6 +297,6 @@ std::size_t constexpr permissionMaxSize = 10; /** The maximum number of transactions that can be in a batch. */ std::size_t constexpr maxBatchTxCount = 8; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/PublicKey.h b/include/xrpl/protocol/PublicKey.h index 8d8062408b..51a7683ebc 100644 --- a/include/xrpl/protocol/PublicKey.h +++ b/include/xrpl/protocol/PublicKey.h @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A public key. @@ -260,16 +260,16 @@ getFingerprint( } return ss.str(); } -} // namespace ripple +} // namespace xrpl //------------------------------------------------------------------------------ namespace Json { template <> -inline ripple::PublicKey -getOrThrow(Json::Value const& v, ripple::SField const& field) +inline xrpl::PublicKey +getOrThrow(Json::Value const& v, xrpl::SField const& field) { - using namespace ripple; + using namespace xrpl; std::string const b58 = getOrThrow(v, field); if (auto pubKeyBlob = strUnHex(b58); publicKeyType(makeSlice(*pubKeyBlob))) { diff --git a/include/xrpl/protocol/Quality.h b/include/xrpl/protocol/Quality.h index 0e748e9b26..1fafa5e321 100644 --- a/include/xrpl/protocol/Quality.h +++ b/include/xrpl/protocol/Quality.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Represents a pair of input and output currencies. @@ -281,7 +281,7 @@ public: { XRPL_ASSERT( q1.m_value > 0 && q2.m_value > 0, - "ripple::Quality::relativeDistance : minimum inputs"); + "xrpl::Quality::relativeDistance : minimum inputs"); if (q1.m_value == q2.m_value) // make expected common case fast return 0; @@ -395,6 +395,6 @@ Quality::ceil_out_strict( Quality composed_quality(Quality const& lhs, Quality const& rhs); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/QualityFunction.h b/include/xrpl/protocol/QualityFunction.h index 8013f0bf7b..b7ec11fa69 100644 --- a/include/xrpl/protocol/QualityFunction.h +++ b/include/xrpl/protocol/QualityFunction.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Average quality of a path as a function of `out`: q(out) = m * out + b, * where m = -1 / poolGets, b = poolPays / poolGets. If CLOB offer then @@ -83,6 +83,6 @@ QualityFunction::QualityFunction( b_ = amounts.out * cfee / amounts.in; } -} // namespace ripple +} // namespace xrpl #endif // XRPL_PROTOCOL_QUALITYFUNCTION_H_INCLUDED diff --git a/include/xrpl/protocol/RPCErr.h b/include/xrpl/protocol/RPCErr.h index 3436384d01..90df1562e7 100644 --- a/include/xrpl/protocol/RPCErr.h +++ b/include/xrpl/protocol/RPCErr.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { // VFALCO NOTE these are deprecated bool @@ -11,6 +11,6 @@ isRpcError(Json::Value jvResult); Json::Value rpcError(int iError); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Rate.h b/include/xrpl/protocol/Rate.h index b0c641c499..b8173a9392 100644 --- a/include/xrpl/protocol/Rate.h +++ b/include/xrpl/protocol/Rate.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Represents a transfer rate @@ -83,6 +83,6 @@ transferFeeAsRate(std::uint16_t fee); /** A transfer rate signifying a 1:1 exchange */ extern Rate const parityRate; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/RippleLedgerHash.h b/include/xrpl/protocol/RippleLedgerHash.h index 4653e1a558..516ab49029 100644 --- a/include/xrpl/protocol/RippleLedgerHash.h +++ b/include/xrpl/protocol/RippleLedgerHash.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { using LedgerHash = uint256; diff --git a/include/xrpl/protocol/Rules.h b/include/xrpl/protocol/Rules.h index 40b84d1d3f..0ae6680d07 100644 --- a/include/xrpl/protocol/Rules.h +++ b/include/xrpl/protocol/Rules.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { bool isFeatureEnabled(uint256 const& feature); @@ -111,5 +111,5 @@ private: std::optional saved_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/SField.h b/include/xrpl/protocol/SField.h index 82619b1ced..b1d353196d 100644 --- a/include/xrpl/protocol/SField.h +++ b/include/xrpl/protocol/SField.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /* @@ -374,6 +374,6 @@ extern SField const sfGeneric; #undef UNTYPED_SFIELD #pragma pop_macro("UNTYPED_SFIELD") -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/SOTemplate.h b/include/xrpl/protocol/SOTemplate.h index 35e3b356be..559117c274 100644 --- a/include/xrpl/protocol/SOTemplate.h +++ b/include/xrpl/protocol/SOTemplate.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Kind of element in each entry of an SOTemplate. */ enum SOEStyle { @@ -154,6 +154,6 @@ private: std::vector indices_; // field num -> index }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STAccount.h b/include/xrpl/protocol/STAccount.h index b981ef91c2..7c193d3425 100644 --- a/include/xrpl/protocol/STAccount.h +++ b/include/xrpl/protocol/STAccount.h @@ -7,14 +7,14 @@ #include -namespace ripple { +namespace xrpl { class STAccount final : public STBase, public CountedObject { private: // The original implementation of STAccount kept the value in an STBlob. // But an STAccount is always 160 bits, so we can store it with less - // overhead in a ripple::uint160. However, so the serialized format of the + // overhead in a xrpl::uint160. However, so the serialized format of the // STAccount stays unchanged, we serialize and deserialize like an STBlob. AccountID value_; bool default_; @@ -112,6 +112,6 @@ operator<(AccountID const& lhs, STAccount const& rhs) return lhs < rhs.value(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STAmount.h b/include/xrpl/protocol/STAmount.h index 3ea45cc05b..79cbf51436 100644 --- a/include/xrpl/protocol/STAmount.h +++ b/include/xrpl/protocol/STAmount.h @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { // Internal form: // 1: If amount is zero, then value is zero and offset is -100 @@ -347,7 +347,7 @@ STAmount::STAmount( // mValue is uint64, but needs to fit in the range of int64 XRPL_ASSERT( mValue <= std::numeric_limits::max(), - "ripple::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : " + "xrpl::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : " "maximum mantissa input"); canonicalize(); } @@ -748,15 +748,15 @@ canAdd(STAmount const& amt1, STAmount const& amt2); bool canSubtract(STAmount const& amt1, STAmount const& amt2); -} // namespace ripple +} // namespace xrpl //------------------------------------------------------------------------------ namespace Json { template <> -inline ripple::STAmount -getOrThrow(Json::Value const& v, ripple::SField const& field) +inline xrpl::STAmount +getOrThrow(Json::Value const& v, xrpl::SField const& field) { - using namespace ripple; + using namespace xrpl; Json::StaticString const& key = field.getJsonName(); if (!v.isMember(key)) Throw(key); diff --git a/include/xrpl/protocol/STArray.h b/include/xrpl/protocol/STArray.h index 88d2b04511..fb37e07226 100644 --- a/include/xrpl/protocol/STArray.h +++ b/include/xrpl/protocol/STArray.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class STArray final : public STBase, public CountedObject { @@ -291,6 +291,6 @@ STArray::erase(const_iterator first, const_iterator last) return v_.erase(first, last); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STBase.h b/include/xrpl/protocol/STBase.h index 64bd4f7ab8..f100b52426 100644 --- a/include/xrpl/protocol/STBase.h +++ b/include/xrpl/protocol/STBase.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { /// Note, should be treated as flags that can be | and & struct JsonOptions @@ -219,6 +219,6 @@ STBase::emplace(std::size_t n, void* buf, T&& val) return new (buf) U(std::forward(val)); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STBitString.h b/include/xrpl/protocol/STBitString.h index 10c6fd95a0..2d26fe4bd7 100644 --- a/include/xrpl/protocol/STBitString.h +++ b/include/xrpl/protocol/STBitString.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { // The template parameter could be an unsigned type, however there's a bug in // gdb (last checked in gdb 12.1) that prevents gdb from finding the RTTI @@ -152,10 +152,10 @@ void STBitString::add(Serializer& s) const { XRPL_ASSERT( - getFName().isBinary(), "ripple::STBitString::add : field is binary"); + getFName().isBinary(), "xrpl::STBitString::add : field is binary"); XRPL_ASSERT( getFName().fieldType == getSType(), - "ripple::STBitString::add : field type match"); + "xrpl::STBitString::add : field type match"); s.addBitString(value_); } @@ -187,6 +187,6 @@ STBitString::isDefault() const return value_ == beast::zero; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STBlob.h b/include/xrpl/protocol/STBlob.h index 46b91d6ebb..dc3f95e218 100644 --- a/include/xrpl/protocol/STBlob.h +++ b/include/xrpl/protocol/STBlob.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { // variable length byte string class STBlob : public STBase, public CountedObject @@ -126,6 +126,6 @@ STBlob::setValue(Buffer&& b) value_ = std::move(b); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STCurrency.h b/include/xrpl/protocol/STCurrency.h index acb0e40019..1c59d48beb 100644 --- a/include/xrpl/protocol/STCurrency.h +++ b/include/xrpl/protocol/STCurrency.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class STCurrency final : public STBase { @@ -114,6 +114,6 @@ operator<(STCurrency const& lhs, Currency const& rhs) return lhs.currency() < rhs; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STExchange.h b/include/xrpl/protocol/STExchange.h index 771f6bd109..5f7e405599 100644 --- a/include/xrpl/protocol/STExchange.h +++ b/include/xrpl/protocol/STExchange.h @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Convert between serialized type U and C++ type T. */ template @@ -155,6 +155,6 @@ erase(STObject& st, TypedField const& f) st.makeFieldAbsent(f); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STInteger.h b/include/xrpl/protocol/STInteger.h index 7513733e47..9c8af4c08c 100644 --- a/include/xrpl/protocol/STInteger.h +++ b/include/xrpl/protocol/STInteger.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { template class STInteger : public STBase, public CountedObject> @@ -54,7 +54,7 @@ private: STBase* move(std::size_t n, void* buf) override; - friend class ripple::detail::STVar; + friend class xrpl::detail::STVar; }; using STUInt8 = STInteger; @@ -94,10 +94,10 @@ inline void STInteger::add(Serializer& s) const { XRPL_ASSERT( - getFName().isBinary(), "ripple::STInteger::add : field is binary"); + getFName().isBinary(), "xrpl::STInteger::add : field is binary"); XRPL_ASSERT( getFName().fieldType == getSType(), - "ripple::STInteger::add : field type match"); + "xrpl::STInteger::add : field type match"); s.addInteger(value_); } @@ -144,6 +144,6 @@ inline STInteger::operator Integer() const return value_; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STIssue.h b/include/xrpl/protocol/STIssue.h index 4f8509710c..6480482d08 100644 --- a/include/xrpl/protocol/STIssue.h +++ b/include/xrpl/protocol/STIssue.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class STIssue final : public STBase, CountedObject { @@ -150,6 +150,6 @@ operator<=>(STIssue const& lhs, Asset const& rhs) return lhs.asset_ <=> rhs; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STLedgerEntry.h b/include/xrpl/protocol/STLedgerEntry.h index 20a5ceda54..83e0f2cd27 100644 --- a/include/xrpl/protocol/STLedgerEntry.h +++ b/include/xrpl/protocol/STLedgerEntry.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class Rules; namespace test { @@ -108,6 +108,6 @@ STLedgerEntry::getType() const return type_; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STNumber.h b/include/xrpl/protocol/STNumber.h index 2ec3d66fd1..dfdb16af93 100644 --- a/include/xrpl/protocol/STNumber.h +++ b/include/xrpl/protocol/STNumber.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { /** * A serializable number. @@ -84,6 +84,6 @@ partsFromString(std::string const& number); STNumber numberFromJson(SField const& field, Json::Value const& value); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STObject.h b/include/xrpl/protocol/STObject.h index 1a553e0fbf..c6ca133e89 100644 --- a/include/xrpl/protocol/STObject.h +++ b/include/xrpl/protocol/STObject.h @@ -24,7 +24,7 @@ #include #include -namespace ripple { +namespace xrpl { class STArray; @@ -772,7 +772,7 @@ STObject::Proxy::assign(U&& u) t = dynamic_cast(st_->getPField(*f_, true)); else t = dynamic_cast(st_->makeFieldPresent(*f_)); - XRPL_ASSERT(t, "ripple::STObject::Proxy::assign : type cast succeeded"); + XRPL_ASSERT(t, "xrpl::STObject::Proxy::assign : type cast succeeded"); *t = std::forward(u); } @@ -1064,18 +1064,17 @@ STObject::at(TypedField const& f) const return u->value(); XRPL_ASSERT( - mType, - "ripple::STObject::at(TypedField auto) : field template non-null"); + mType, "xrpl::STObject::at(TypedField auto) : field template non-null"); XRPL_ASSERT( b->getSType() == STI_NOTPRESENT, - "ripple::STObject::at(TypedField auto) : type not present"); + "xrpl::STObject::at(TypedField auto) : type not present"); if (mType->style(f) == soeOPTIONAL) Throw("Missing optional field: " + f.getName()); XRPL_ASSERT( mType->style(f) == soeDEFAULT, - "ripple::STObject::at(TypedField auto) : template style is default"); + "xrpl::STObject::at(TypedField auto) : template style is default"); // Used to help handle the case where value_type is a const reference, // otherwise we would return the address of a temporary. @@ -1095,16 +1094,16 @@ STObject::at(OptionaledField const& of) const { XRPL_ASSERT( mType, - "ripple::STObject::at(OptionaledField auto) : field template " + "xrpl::STObject::at(OptionaledField auto) : field template " "non-null"); XRPL_ASSERT( b->getSType() == STI_NOTPRESENT, - "ripple::STObject::at(OptionaledField auto) : type not present"); + "xrpl::STObject::at(OptionaledField auto) : type not present"); if (mType->style(*of.f) == soeOPTIONAL) return std::nullopt; XRPL_ASSERT( mType->style(*of.f) == soeDEFAULT, - "ripple::STObject::at(OptionaledField auto) : template style is " + "xrpl::STObject::at(OptionaledField auto) : template style is " "default"); return typename T::value_type{}; } @@ -1264,6 +1263,6 @@ STObject::peekField(SField const& field) return *cf; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STParsedJSON.h b/include/xrpl/protocol/STParsedJSON.h index 9bc8524f11..4be10840bd 100644 --- a/include/xrpl/protocol/STParsedJSON.h +++ b/include/xrpl/protocol/STParsedJSON.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { /** Holds the serialized result of parsing an input JSON object. This does validation and checking on the provided JSON. @@ -35,6 +35,6 @@ public: Json::Value error; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STPathSet.h b/include/xrpl/protocol/STPathSet.h index 4b16e9cb1f..cb7db2edf0 100644 --- a/include/xrpl/protocol/STPathSet.h +++ b/include/xrpl/protocol/STPathSet.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { class STPathElement final : public CountedObject { @@ -241,7 +241,7 @@ inline STPathElement::STPathElement( mType |= typeAccount; XRPL_ASSERT( mAccountID != noAccount(), - "ripple::STPathElement::STPathElement : account is set"); + "xrpl::STPathElement::STPathElement : account is set"); } if (currency) @@ -256,7 +256,7 @@ inline STPathElement::STPathElement( mType |= typeIssuer; XRPL_ASSERT( mIssuerID != noAccount(), - "ripple::STPathElement::STPathElement : issuer is set"); + "xrpl::STPathElement::STPathElement : issuer is set"); } hash_value_ = get_hash(*this); @@ -504,6 +504,6 @@ STPathSet::emplace_back(Args&&... args) value.emplace_back(std::forward(args)...); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STTx.h b/include/xrpl/protocol/STTx.h index 02f865e349..182e13433d 100644 --- a/include/xrpl/protocol/STTx.h +++ b/include/xrpl/protocol/STTx.h @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { enum TxnSql : char { txnSqlNew = 'N', @@ -201,6 +201,6 @@ STTx::getTransactionID() const return tid_; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STValidation.h b/include/xrpl/protocol/STValidation.h index 07aef8316c..4d09397eaa 100644 --- a/include/xrpl/protocol/STValidation.h +++ b/include/xrpl/protocol/STValidation.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { // Validation flags @@ -175,7 +175,7 @@ STValidation::STValidation( XRPL_ASSERT( nodeID_.isNonZero(), - "ripple::STValidation::STValidation(SerialIter) : nonzero node"); + "xrpl::STValidation::STValidation(SerialIter) : nonzero node"); } /** Construct, sign and trust a new STValidation issued by this node. @@ -200,7 +200,7 @@ STValidation::STValidation( { XRPL_ASSERT( nodeID_.isNonZero(), - "ripple::STValidation::STValidation(PublicKey, SecretKey) : nonzero " + "xrpl::STValidation::STValidation(PublicKey, SecretKey) : nonzero " "node"); // First, set our own public key: @@ -267,6 +267,6 @@ STValidation::setSeen(NetClock::time_point s) seenTime_ = s; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STVector256.h b/include/xrpl/protocol/STVector256.h index dc2276a250..94b16db90b 100644 --- a/include/xrpl/protocol/STVector256.h +++ b/include/xrpl/protocol/STVector256.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class STVector256 : public STBase, public CountedObject { @@ -237,6 +237,6 @@ STVector256::clear() noexcept return mValue.clear(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/STXChainBridge.h b/include/xrpl/protocol/STXChainBridge.h index e7e687c2c9..89c6d60c13 100644 --- a/include/xrpl/protocol/STXChainBridge.h +++ b/include/xrpl/protocol/STXChainBridge.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class Serializer; class STObject; @@ -212,6 +212,6 @@ STXChainBridge::dstChain(bool wasLockingChainSend) return ChainType::locking; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/SecretKey.h b/include/xrpl/protocol/SecretKey.h index fd36ce1a5b..d5f1ce303f 100644 --- a/include/xrpl/protocol/SecretKey.h +++ b/include/xrpl/protocol/SecretKey.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A secret key. */ class SecretKey @@ -162,6 +162,6 @@ sign(KeyType type, SecretKey const& sk, Slice const& message) } /** @} */ -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Seed.h b/include/xrpl/protocol/Seed.h index cda1a8e018..36b2bbfee3 100644 --- a/include/xrpl/protocol/Seed.h +++ b/include/xrpl/protocol/Seed.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Seeds are used to generate deterministic secret keys. */ class Seed @@ -117,6 +117,6 @@ toBase58(Seed const& seed) return encodeBase58Token(TokenType::FamilySeed, seed.data(), seed.size()); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/SeqProxy.h b/include/xrpl/protocol/SeqProxy.h index 8ed2c45289..8dde232e75 100644 --- a/include/xrpl/protocol/SeqProxy.h +++ b/include/xrpl/protocol/SeqProxy.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A type that represents either a sequence value or a ticket value. @@ -146,6 +146,6 @@ public: return os; } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Serializer.h b/include/xrpl/protocol/Serializer.h index 44c4498cb7..f46073a977 100644 --- a/include/xrpl/protocol/Serializer.h +++ b/include/xrpl/protocol/Serializer.h @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { class Serializer { @@ -38,7 +38,7 @@ public: { XRPL_ASSERT( data, - "ripple::Serializer::Serializer(void const*) : non-null input"); + "xrpl::Serializer::Serializer(void const*) : non-null input"); std::memcpy(mData.data(), data, size); } } @@ -314,8 +314,7 @@ Serializer::addVL(Iter begin, Iter end, int len) len -= begin->size(); #endif } - XRPL_ASSERT( - len == 0, "ripple::Serializer::addVL : length matches distance"); + XRPL_ASSERT(len == 0, "xrpl::Serializer::addVL : length matches distance"); return ret; } @@ -453,6 +452,6 @@ SerialIter::getBitString() return base_uint::fromVoid(x); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/Sign.h b/include/xrpl/protocol/Sign.h index 9a27290924..6df4c55b65 100644 --- a/include/xrpl/protocol/Sign.h +++ b/include/xrpl/protocol/Sign.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Sign an STObject @@ -67,6 +67,6 @@ finishMultiSigningData(AccountID const& signingID, Serializer& s) s.addBitString(signingID); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/SystemParameters.h b/include/xrpl/protocol/SystemParameters.h index de78b65265..c0732bc9fe 100644 --- a/include/xrpl/protocol/SystemParameters.h +++ b/include/xrpl/protocol/SystemParameters.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { // Various protocol and system specific constant globals. @@ -60,7 +60,7 @@ constexpr std::ratio<80, 100> amendmentMajorityCalcThreshold; /** The minimum amount of time an amendment must hold a majority */ constexpr std::chrono::seconds const defaultAmendmentMajorityTime = weeks{2}; -} // namespace ripple +} // namespace xrpl /** Default peer port (IANA registered) */ inline std::uint16_t constexpr DEFAULT_PEER_PORT{2459}; diff --git a/include/xrpl/protocol/TER.h b/include/xrpl/protocol/TER.h index ad0719dbb1..de2f596127 100644 --- a/include/xrpl/protocol/TER.h +++ b/include/xrpl/protocol/TER.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { // See https://xrpl.org/transaction-results.html // @@ -685,6 +685,6 @@ transHuman(TER code); std::optional transCode(std::string const& token); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/TxFlags.h b/include/xrpl/protocol/TxFlags.h index d4faed192c..194c4c6af1 100644 --- a/include/xrpl/protocol/TxFlags.h +++ b/include/xrpl/protocol/TxFlags.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { /** Transaction flags. @@ -294,6 +294,6 @@ constexpr std::uint32_t const tfLoanManageMask = ~(tfUniversal | tfLoanDefault | // clang-format on -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/TxFormats.h b/include/xrpl/protocol/TxFormats.h index cf60b5081d..05f03c5cdc 100644 --- a/include/xrpl/protocol/TxFormats.h +++ b/include/xrpl/protocol/TxFormats.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Transaction type identifiers. @@ -76,6 +76,6 @@ public: getInstance(); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/TxMeta.h b/include/xrpl/protocol/TxMeta.h index 3ab58c9d0a..5b6716e380 100644 --- a/include/xrpl/protocol/TxMeta.h +++ b/include/xrpl/protocol/TxMeta.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { class TxMeta { @@ -117,6 +117,6 @@ private: STArray nodes_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/UintTypes.h b/include/xrpl/protocol/UintTypes.h index 480d8640ca..daa66e8286 100644 --- a/include/xrpl/protocol/UintTypes.h +++ b/include/xrpl/protocol/UintTypes.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { class CurrencyTag @@ -96,30 +96,30 @@ operator<<(std::ostream& os, Currency const& x) return os; } -} // namespace ripple +} // namespace xrpl namespace std { template <> -struct hash : ripple::Currency::hasher +struct hash : xrpl::Currency::hasher { hash() = default; }; template <> -struct hash : ripple::NodeID::hasher +struct hash : xrpl::NodeID::hasher { hash() = default; }; template <> -struct hash : ripple::Directory::hasher +struct hash : xrpl::Directory::hasher { hash() = default; }; template <> -struct hash : ripple::uint256::hasher +struct hash : xrpl::uint256::hasher { hash() = default; }; diff --git a/include/xrpl/protocol/Units.h b/include/xrpl/protocol/Units.h index e41f93b5b0..72114ad8fe 100644 --- a/include/xrpl/protocol/Units.h +++ b/include/xrpl/protocol/Units.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace unit { @@ -388,11 +388,10 @@ mulDivU(Source1 value, Dest mul, Source2 div) // split the asserts so if one hits, the user can tell which // without a debugger. XRPL_ASSERT( - value.value() >= 0, "ripple::unit::mulDivU : minimum value input"); + value.value() >= 0, "xrpl::unit::mulDivU : minimum value input"); XRPL_ASSERT( - mul.value() >= 0, "ripple::unit::mulDivU : minimum mul input"); - XRPL_ASSERT( - div.value() > 0, "ripple::unit::mulDivU : minimum div input"); + mul.value() >= 0, "xrpl::unit::mulDivU : minimum mul input"); + XRPL_ASSERT(div.value() > 0, "xrpl::unit::mulDivU : minimum div input"); return std::nullopt; } @@ -532,6 +531,6 @@ unsafe_cast(Src s) noexcept return Dest{unsafe_cast(s)}; } -} // namespace ripple +} // namespace xrpl #endif // PROTOCOL_UNITS_H_INCLUDED diff --git a/include/xrpl/protocol/XChainAttestations.h b/include/xrpl/protocol/XChainAttestations.h index 0b368aaa58..4dc9cfcf6a 100644 --- a/include/xrpl/protocol/XChainAttestations.h +++ b/include/xrpl/protocol/XChainAttestations.h @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Attestations { @@ -478,6 +478,6 @@ class XChainCreateAccountAttestations final using TBase::TBase; }; -} // namespace ripple +} // namespace xrpl #endif // STXCHAINATTESTATIONS_H_ diff --git a/include/xrpl/protocol/XRPAmount.h b/include/xrpl/protocol/XRPAmount.h index e102a3707f..ef283f4154 100644 --- a/include/xrpl/protocol/XRPAmount.h +++ b/include/xrpl/protocol/XRPAmount.h @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { class XRPAmount : private boost::totally_ordered, private boost::additive, @@ -287,6 +287,6 @@ mulRatio( return XRPAmount(r.convert_to()); } -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_XRPAMOUNT_H_INCLUDED diff --git a/include/xrpl/protocol/detail/STVar.h b/include/xrpl/protocol/detail/STVar.h index 9a8d85717f..540ba2bf77 100644 --- a/include/xrpl/protocol/detail/STVar.h +++ b/include/xrpl/protocol/detail/STVar.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { struct defaultObject_t @@ -162,6 +162,6 @@ operator!=(STVar const& lhs, STVar const& rhs) } } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/detail/b58_utils.h b/include/xrpl/protocol/detail/b58_utils.h index b96e34ebc5..4ea00e6d5e 100644 --- a/include/xrpl/protocol/detail/b58_utils.h +++ b/include/xrpl/protocol/detail/b58_utils.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { template using Result = boost::outcome_v2::result; @@ -112,7 +112,7 @@ inplace_bigint_div_rem(std::span numerator, std::uint64_t divisor) // the a null set of numbers to be zero, so the remainder is also zero. // LCOV_EXCL_START UNREACHABLE( - "ripple::b58_fast::detail::inplace_bigint_div_rem : empty " + "xrpl::b58_fast::detail::inplace_bigint_div_rem : empty " "numerator"); return 0; // LCOV_EXCL_STOP @@ -132,11 +132,11 @@ inplace_bigint_div_rem(std::span numerator, std::uint64_t divisor) unsigned __int128 const r = num - (denom128 * d); XRPL_ASSERT( d >> 64 == 0, - "ripple::b58_fast::detail::inplace_bigint_div_rem::div_rem_64 : " + "xrpl::b58_fast::detail::inplace_bigint_div_rem::div_rem_64 : " "valid division result"); XRPL_ASSERT( r >> 64 == 0, - "ripple::b58_fast::detail::inplace_bigint_div_rem::div_rem_64 : " + "xrpl::b58_fast::detail::inplace_bigint_div_rem::div_rem_64 : " "valid remainder"); return {static_cast(d), static_cast(r)}; }; @@ -163,7 +163,7 @@ b58_10_to_b58_be(std::uint64_t input) 430804206899405824; // 58^10; XRPL_ASSERT( input < B_58_10, - "ripple::b58_fast::detail::b58_10_to_b58_be : valid input"); + "xrpl::b58_fast::detail::b58_10_to_b58_be : valid input"); constexpr std::size_t resultSize = 10; std::array result{}; int i = 0; @@ -181,5 +181,5 @@ b58_10_to_b58_be(std::uint64_t input) } // namespace b58_fast #endif -} // namespace ripple +} // namespace xrpl #endif // XRPL_PROTOCOL_B58_UTILS_H_INCLUDED diff --git a/include/xrpl/protocol/detail/secp256k1.h b/include/xrpl/protocol/detail/secp256k1.h index c93734a539..c3ac76d7ed 100644 --- a/include/xrpl/protocol/detail/secp256k1.h +++ b/include/xrpl/protocol/detail/secp256k1.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { template secp256k1_context const* @@ -27,6 +27,6 @@ secp256k1Context() return h.impl; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/detail/token_errors.h b/include/xrpl/protocol/detail/token_errors.h index a40e992aec..1d5276e78b 100644 --- a/include/xrpl/protocol/detail/token_errors.h +++ b/include/xrpl/protocol/detail/token_errors.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { enum class TokenCodecErrc { success = 0, inputTooLarge, @@ -20,12 +20,12 @@ enum class TokenCodecErrc { namespace std { template <> -struct is_error_code_enum : true_type +struct is_error_code_enum : true_type { }; } // namespace std -namespace ripple { +namespace xrpl { namespace detail { class TokenCodecErrcCategory : public std::error_category { @@ -67,17 +67,17 @@ public: }; } // namespace detail -inline ripple::detail::TokenCodecErrcCategory const& +inline xrpl::detail::TokenCodecErrcCategory const& TokenCodecErrcCategory() { - static ripple::detail::TokenCodecErrcCategory c; + static xrpl::detail::TokenCodecErrcCategory c; return c; } inline std::error_code -make_error_code(ripple::TokenCodecErrc e) +make_error_code(xrpl::TokenCodecErrc e) { return {static_cast(e), TokenCodecErrcCategory()}; } -} // namespace ripple +} // namespace xrpl #endif // TOKEN_ERRORS_H_ diff --git a/include/xrpl/protocol/digest.h b/include/xrpl/protocol/digest.h index c42fe479da..bafac699f5 100644 --- a/include/xrpl/protocol/digest.h +++ b/include/xrpl/protocol/digest.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { /** Message digest functions used in the codebase @@ -226,6 +226,6 @@ sha512Half_s(Args const&... args) return static_cast(h); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/json_get_or_throw.h b/include/xrpl/protocol/json_get_or_throw.h index 74d1779339..bdf572bed6 100644 --- a/include/xrpl/protocol/json_get_or_throw.h +++ b/include/xrpl/protocol/json_get_or_throw.h @@ -53,16 +53,16 @@ struct JsonTypeMismatchError : std::exception template T -getOrThrow(Json::Value const& v, ripple::SField const& field) +getOrThrow(Json::Value const& v, xrpl::SField const& field) { static_assert(sizeof(T) == -1, "This function must be specialized"); } template <> inline std::string -getOrThrow(Json::Value const& v, ripple::SField const& field) +getOrThrow(Json::Value const& v, xrpl::SField const& field) { - using namespace ripple; + using namespace xrpl; Json::StaticString const& key = field.getJsonName(); if (!v.isMember(key)) Throw(key); @@ -76,9 +76,9 @@ getOrThrow(Json::Value const& v, ripple::SField const& field) // Note, this allows integer numeric fields to act as bools template <> inline bool -getOrThrow(Json::Value const& v, ripple::SField const& field) +getOrThrow(Json::Value const& v, xrpl::SField const& field) { - using namespace ripple; + using namespace xrpl; Json::StaticString const& key = field.getJsonName(); if (!v.isMember(key)) Throw(key); @@ -93,9 +93,9 @@ getOrThrow(Json::Value const& v, ripple::SField const& field) template <> inline std::uint64_t -getOrThrow(Json::Value const& v, ripple::SField const& field) +getOrThrow(Json::Value const& v, xrpl::SField const& field) { - using namespace ripple; + using namespace xrpl; Json::StaticString const& key = field.getJsonName(); if (!v.isMember(key)) Throw(key); @@ -125,10 +125,10 @@ getOrThrow(Json::Value const& v, ripple::SField const& field) } template <> -inline ripple::Buffer -getOrThrow(Json::Value const& v, ripple::SField const& field) +inline xrpl::Buffer +getOrThrow(Json::Value const& v, xrpl::SField const& field) { - using namespace ripple; + using namespace xrpl; std::string const hex = getOrThrow(v, field); if (auto const r = strUnHex(hex)) { @@ -141,7 +141,7 @@ getOrThrow(Json::Value const& v, ripple::SField const& field) // This function may be used by external projects (like the witness server). template std::optional -getOptional(Json::Value const& v, ripple::SField const& field) +getOptional(Json::Value const& v, xrpl::SField const& field) { try { diff --git a/include/xrpl/protocol/jss.h b/include/xrpl/protocol/jss.h index b9a8945d21..d86ca9bf1f 100644 --- a/include/xrpl/protocol/jss.h +++ b/include/xrpl/protocol/jss.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace jss { // JSON static strings @@ -725,6 +725,6 @@ JSS(write_load); // out: GetCounts #undef JSS } // namespace jss -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/nft.h b/include/xrpl/protocol/nft.h index 2681be4aad..3a8cdcd6e2 100644 --- a/include/xrpl/protocol/nft.h +++ b/include/xrpl/protocol/nft.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace nft { // Separate taxons from regular integers. @@ -104,6 +104,6 @@ getIssuer(uint256 const& id) } } // namespace nft -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/nftPageMask.h b/include/xrpl/protocol/nftPageMask.h index 800899f7a7..4d23e45f53 100644 --- a/include/xrpl/protocol/nftPageMask.h +++ b/include/xrpl/protocol/nftPageMask.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace nft { // NFT directory pages order their contents based only on the low 96 bits of @@ -14,6 +14,6 @@ uint256 constexpr pageMask(std::string_view( "0000000000000000000000000000000000000000ffffffffffffffffffffffff")); } // namespace nft -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/serialize.h b/include/xrpl/protocol/serialize.h index ea93505736..eedf041baa 100644 --- a/include/xrpl/protocol/serialize.h +++ b/include/xrpl/protocol/serialize.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Serialize an object to a blob. */ template @@ -24,6 +24,6 @@ serializeHex(STObject const& o) return strHex(serializeBlob(o)); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/protocol/tokens.h b/include/xrpl/protocol/tokens.h index 5e3fc222e8..ac13a10e06 100644 --- a/include/xrpl/protocol/tokens.h +++ b/include/xrpl/protocol/tokens.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { template using B58Result = Expected; @@ -111,6 +111,6 @@ b58_to_b256_be(std::string_view input, std::span out); } // namespace b58_fast #endif // _MSC_VER -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/Charge.h b/include/xrpl/resource/Charge.h index 2236a60cd4..1edaca28b4 100644 --- a/include/xrpl/resource/Charge.h +++ b/include/xrpl/resource/Charge.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace Resource { /** A consumption charge. */ @@ -49,6 +49,6 @@ std::ostream& operator<<(std::ostream& os, Charge const& v); } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/Consumer.h b/include/xrpl/resource/Consumer.h index 903e0e97a5..6e973d824c 100644 --- a/include/xrpl/resource/Consumer.h +++ b/include/xrpl/resource/Consumer.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { struct Entry; @@ -81,6 +81,6 @@ std::ostream& operator<<(std::ostream& os, Consumer const& v); } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/Disposition.h b/include/xrpl/resource/Disposition.h index 5915b0059d..81675e8376 100644 --- a/include/xrpl/resource/Disposition.h +++ b/include/xrpl/resource/Disposition.h @@ -1,7 +1,7 @@ #ifndef XRPL_RESOURCE_DISPOSITION_H_INCLUDED #define XRPL_RESOURCE_DISPOSITION_H_INCLUDED -namespace ripple { +namespace xrpl { namespace Resource { /** The disposition of a consumer after applying a load charge. */ @@ -19,6 +19,6 @@ enum Disposition { }; } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/Fees.h b/include/xrpl/resource/Fees.h index 4a099b9019..643a8e624c 100644 --- a/include/xrpl/resource/Fees.h +++ b/include/xrpl/resource/Fees.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace Resource { // clang-format off @@ -40,6 +40,6 @@ extern Charge const feeDrop; // The cost of being dropped for // clang-format on } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/Gossip.h b/include/xrpl/resource/Gossip.h index 214e0e8c4d..dfd04288fc 100644 --- a/include/xrpl/resource/Gossip.h +++ b/include/xrpl/resource/Gossip.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace Resource { /** Data format for exchanging consumption information across peers. */ @@ -26,6 +26,6 @@ struct Gossip }; } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/ResourceManager.h b/include/xrpl/resource/ResourceManager.h index 7d29059292..19690d6bc4 100644 --- a/include/xrpl/resource/ResourceManager.h +++ b/include/xrpl/resource/ResourceManager.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace Resource { /** Tracks load and resource consumption. */ @@ -66,6 +66,6 @@ make_Manager( beast::Journal journal); } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/Types.h b/include/xrpl/resource/Types.h index 64628cf54a..8923933f0f 100644 --- a/include/xrpl/resource/Types.h +++ b/include/xrpl/resource/Types.h @@ -1,13 +1,13 @@ #ifndef XRPL_RESOURCE_TYPES_H_INCLUDED #define XRPL_RESOURCE_TYPES_H_INCLUDED -namespace ripple { +namespace xrpl { namespace Resource { struct Key; struct Entry; } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/detail/Entry.h b/include/xrpl/resource/detail/Entry.h index b89d85d1f3..ce55c46064 100644 --- a/include/xrpl/resource/detail/Entry.h +++ b/include/xrpl/resource/detail/Entry.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { using clock_type = beast::abstract_clock; @@ -93,6 +93,6 @@ operator<<(std::ostream& os, Entry const& v) } } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/detail/Import.h b/include/xrpl/resource/detail/Import.h index a9711be3fc..d33bd5f156 100644 --- a/include/xrpl/resource/detail/Import.h +++ b/include/xrpl/resource/detail/Import.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { /** A set of imported consumer data from a gossip origin. */ @@ -31,6 +31,6 @@ struct Import }; } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/detail/Key.h b/include/xrpl/resource/detail/Key.h index 3df47d5afb..e63d2827ea 100644 --- a/include/xrpl/resource/detail/Key.h +++ b/include/xrpl/resource/detail/Key.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { // The consumer key @@ -47,6 +47,6 @@ struct Key }; } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/detail/Kind.h b/include/xrpl/resource/detail/Kind.h index 0a04b8e627..0e55b65780 100644 --- a/include/xrpl/resource/detail/Kind.h +++ b/include/xrpl/resource/detail/Kind.h @@ -1,7 +1,7 @@ #ifndef XRPL_RESOURCE_KIND_H_INCLUDED #define XRPL_RESOURCE_KIND_H_INCLUDED -namespace ripple { +namespace xrpl { namespace Resource { /** @@ -15,6 +15,6 @@ namespace Resource { enum Kind { kindInbound, kindOutbound, kindUnlimited }; } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/detail/Logic.h b/include/xrpl/resource/detail/Logic.h index a0c541b300..b1f90e0282 100644 --- a/include/xrpl/resource/detail/Logic.h +++ b/include/xrpl/resource/detail/Logic.h @@ -16,7 +16,7 @@ #include -namespace ripple { +namespace xrpl { namespace Resource { class Logic @@ -385,7 +385,7 @@ public: Entry& entry(iter->second); XRPL_ASSERT( entry.refcount == 0, - "ripple::Resource::Logic::erase : entry not used"); + "xrpl::Resource::Logic::erase : entry not used"); inactive_.erase(inactive_.iterator_to(entry)); table_.erase(iter); } @@ -419,7 +419,7 @@ public: default: // LCOV_EXCL_START UNREACHABLE( - "ripple::Resource::Logic::release : invalid entry " + "xrpl::Resource::Logic::release : invalid entry " "kind"); break; // LCOV_EXCL_STOP @@ -568,6 +568,6 @@ public: }; } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/resource/detail/Tuning.h b/include/xrpl/resource/detail/Tuning.h index 3013bb0e45..9d7ba31303 100644 --- a/include/xrpl/resource/detail/Tuning.h +++ b/include/xrpl/resource/detail/Tuning.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace Resource { /** Tunable constants. */ @@ -32,6 +32,6 @@ std::chrono::seconds constexpr secondsUntilExpiration{300}; std::chrono::seconds constexpr gossipExpirationSeconds{30}; } // namespace Resource -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/Handoff.h b/include/xrpl/server/Handoff.h index 993d61aec8..49a5851251 100644 --- a/include/xrpl/server/Handoff.h +++ b/include/xrpl/server/Handoff.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { using http_request_type = boost::beast::http::request; @@ -36,6 +36,6 @@ struct Handoff } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/Port.h b/include/xrpl/server/Port.h index 37b130ae04..995401f8fd 100644 --- a/include/xrpl/server/Port.h +++ b/include/xrpl/server/Port.h @@ -24,7 +24,7 @@ class context; } // namespace asio } // namespace boost -namespace ripple { +namespace xrpl { /** Configuration information for a Server listening port. */ struct Port @@ -104,6 +104,6 @@ struct ParsedPort void parse_Port(ParsedPort& port, Section const& section, std::ostream& log); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/Server.h b/include/xrpl/server/Server.h index 5dc6face66..b553b9e72a 100644 --- a/include/xrpl/server/Server.h +++ b/include/xrpl/server/Server.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { /** Create the HTTP server using the specified handler. */ template @@ -21,6 +21,6 @@ make_Server( return std::make_unique>(handler, io_context, journal); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/Session.h b/include/xrpl/server/Session.h index 52aa37572a..4570e90f7e 100644 --- a/include/xrpl/server/Session.h +++ b/include/xrpl/server/Session.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Persistent state information for a connection session. These values are preserved between calls for efficiency. @@ -111,6 +111,6 @@ public: websocketUpgrade() = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/SimpleWriter.h b/include/xrpl/server/SimpleWriter.h index 96e834df6a..cf41f1c82a 100644 --- a/include/xrpl/server/SimpleWriter.h +++ b/include/xrpl/server/SimpleWriter.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { /// Deprecated: Writer that serializes a HTTP/1 message class SimpleWriter : public Writer @@ -55,6 +55,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/WSSession.h b/include/xrpl/server/WSSession.h index 05558f1774..fb8af7118c 100644 --- a/include/xrpl/server/WSSession.h +++ b/include/xrpl/server/WSSession.h @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { class WSMsg { @@ -125,6 +125,6 @@ struct WSSession complete() = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/Writer.h b/include/xrpl/server/Writer.h index 7948547279..7e0c304ea9 100644 --- a/include/xrpl/server/Writer.h +++ b/include/xrpl/server/Writer.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class Writer { @@ -37,6 +37,6 @@ public: data() = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/BaseHTTPPeer.h b/include/xrpl/server/detail/BaseHTTPPeer.h index c68b7d91ec..5b7327c6b9 100644 --- a/include/xrpl/server/detail/BaseHTTPPeer.h +++ b/include/xrpl/server/detail/BaseHTTPPeer.h @@ -26,7 +26,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Represents an active connection. */ template @@ -511,6 +511,6 @@ BaseHTTPPeer::close(bool graceful) boost::beast::get_lowest_layer(impl().stream_).close(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/BasePeer.h b/include/xrpl/server/detail/BasePeer.h index 3b524cbdd5..fa82a1bb37 100644 --- a/include/xrpl/server/detail/BasePeer.h +++ b/include/xrpl/server/detail/BasePeer.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { // Common part of all peers template @@ -85,9 +85,9 @@ BasePeer::close() return post( strand_, std::bind(&BasePeer::close, impl().shared_from_this())); error_code ec; - ripple::get_lowest_layer(impl().ws_).socket().close(ec); + xrpl::get_lowest_layer(impl().ws_).socket().close(ec); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/BaseWSPeer.h b/include/xrpl/server/detail/BaseWSPeer.h index dbf8d95cba..f0649b221c 100644 --- a/include/xrpl/server/detail/BaseWSPeer.h +++ b/include/xrpl/server/detail/BaseWSPeer.h @@ -19,7 +19,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Represents an active WebSocket connection. */ template @@ -508,17 +508,17 @@ BaseWSPeer::fail(error_code ec, String const& what) { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::BaseWSPeer::fail : strand in this thread"); + "xrpl::BaseWSPeer::fail : strand in this thread"); cancel_timer(); if (!ec_ && ec != boost::asio::error::operation_aborted) { ec_ = ec; JLOG(this->j_.trace()) << what << ": " << ec.message(); - ripple::get_lowest_layer(impl().ws_).socket().close(ec); + xrpl::get_lowest_layer(impl().ws_).socket().close(ec); } } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/Door.h b/include/xrpl/server/detail/Door.h index aef4b4d9d2..140afb1808 100644 --- a/include/xrpl/server/detail/Door.h +++ b/include/xrpl/server/detail/Door.h @@ -35,7 +35,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A listening socket. */ template @@ -500,6 +500,6 @@ Door::should_throttle_for_fds() #endif } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/JSONRPCUtil.h b/include/xrpl/server/detail/JSONRPCUtil.h index 8b2bfa4ac7..d75825a1ea 100644 --- a/include/xrpl/server/detail/JSONRPCUtil.h +++ b/include/xrpl/server/detail/JSONRPCUtil.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { void HTTPReply( @@ -14,6 +14,6 @@ HTTPReply( Json::Output const&, beast::Journal j); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/LowestLayer.h b/include/xrpl/server/detail/LowestLayer.h index c7430b5d9f..57647867e3 100644 --- a/include/xrpl/server/detail/LowestLayer.h +++ b/include/xrpl/server/detail/LowestLayer.h @@ -7,7 +7,7 @@ #include #endif -namespace ripple { +namespace xrpl { // Before boost 1.70, get_lowest_layer required an explicit templat parameter template @@ -21,6 +21,6 @@ get_lowest_layer(T& t) noexcept #endif } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/PlainHTTPPeer.h b/include/xrpl/server/detail/PlainHTTPPeer.h index cf2c871635..8f7d86f8e5 100644 --- a/include/xrpl/server/detail/PlainHTTPPeer.h +++ b/include/xrpl/server/detail/PlainHTTPPeer.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { template class PlainHTTPPeer @@ -154,6 +154,6 @@ PlainHTTPPeer::do_close() socket_.shutdown(socket_type::shutdown_send, ec); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/PlainWSPeer.h b/include/xrpl/server/detail/PlainWSPeer.h index 60223c896d..4d5c57533b 100644 --- a/include/xrpl/server/detail/PlainWSPeer.h +++ b/include/xrpl/server/detail/PlainWSPeer.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { template class PlainWSPeer : public BaseWSPeer>, @@ -58,6 +58,6 @@ PlainWSPeer::PlainWSPeer( { } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/SSLHTTPPeer.h b/include/xrpl/server/detail/SSLHTTPPeer.h index f60f7e82d9..56b2d1c52f 100644 --- a/include/xrpl/server/detail/SSLHTTPPeer.h +++ b/include/xrpl/server/detail/SSLHTTPPeer.h @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { template class SSLHTTPPeer : public BaseHTTPPeer>, @@ -204,6 +204,6 @@ SSLHTTPPeer::on_shutdown(error_code ec) stream_.next_layer().close(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/SSLWSPeer.h b/include/xrpl/server/detail/SSLWSPeer.h index c2076ed6a5..bb5da1c6e7 100644 --- a/include/xrpl/server/detail/SSLWSPeer.h +++ b/include/xrpl/server/detail/SSLWSPeer.h @@ -13,7 +13,7 @@ #include -namespace ripple { +namespace xrpl { template class SSLWSPeer : public BaseWSPeer>, @@ -67,6 +67,6 @@ SSLWSPeer::SSLWSPeer( { } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/ServerImpl.h b/include/xrpl/server/detail/ServerImpl.h index a42966edd6..6ff93e83cb 100644 --- a/include/xrpl/server/detail/ServerImpl.h +++ b/include/xrpl/server/detail/ServerImpl.h @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { using Endpoints = std::unordered_map; @@ -189,6 +189,6 @@ ServerImpl::closed() { return ios_.closed(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/server/detail/Spawn.h b/include/xrpl/server/detail/Spawn.h index 2e80393af6..4c424a1956 100644 --- a/include/xrpl/server/detail/Spawn.h +++ b/include/xrpl/server/detail/Spawn.h @@ -9,7 +9,7 @@ #include #include -namespace ripple::util { +namespace xrpl::util { namespace impl { template @@ -84,6 +84,6 @@ spawn(Ctx&& ctx, F&& func) } } -} // namespace ripple::util +} // namespace xrpl::util #endif diff --git a/include/xrpl/server/detail/io_list.h b/include/xrpl/server/detail/io_list.h index 6b8e440d40..0e67595dbe 100644 --- a/include/xrpl/server/detail/io_list.h +++ b/include/xrpl/server/detail/io_list.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Manages a set of objects performing asynchronous I/O. */ class io_list final @@ -243,6 +243,6 @@ io_list::join() cv_.wait(lock, [&] { return closed_ && n_ == 0; }); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/Family.h b/include/xrpl/shamap/Family.h index e566145bec..6638d67df8 100644 --- a/include/xrpl/shamap/Family.h +++ b/include/xrpl/shamap/Family.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class Family { @@ -65,6 +65,6 @@ public: reset() = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/FullBelowCache.h b/include/xrpl/shamap/FullBelowCache.h index 81061cef59..9434b40011 100644 --- a/include/xrpl/shamap/FullBelowCache.h +++ b/include/xrpl/shamap/FullBelowCache.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -129,6 +129,6 @@ private: using FullBelowCache = detail::BasicFullBelowCache; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMap.h b/include/xrpl/shamap/SHAMap.h index 07db489a8f..94fd926718 100644 --- a/include/xrpl/shamap/SHAMap.h +++ b/include/xrpl/shamap/SHAMap.h @@ -19,7 +19,7 @@ #include #include -namespace ripple { +namespace xrpl { class SHAMapNodeID; class SHAMapSyncFilter; @@ -584,7 +584,7 @@ SHAMap::setImmutable() { XRPL_ASSERT( state_ != SHAMapState::Invalid, - "ripple::SHAMap::setImmutable : state is valid"); + "xrpl::SHAMap::setImmutable : state is valid"); state_ = SHAMapState::Immutable; } @@ -666,8 +666,7 @@ private: inline SHAMap::const_iterator::const_iterator(SHAMap const* map) : map_(map) { XRPL_ASSERT( - map_, - "ripple::SHAMap::const_iterator::const_iterator : non-null input"); + map_, "xrpl::SHAMap::const_iterator::const_iterator : non-null input"); if (auto temp = map_->peekFirstItem(stack_)) item_ = temp->peekItem().get(); @@ -721,7 +720,7 @@ operator==(SHAMap::const_iterator const& x, SHAMap::const_iterator const& y) { XRPL_ASSERT( x.map_ == y.map_, - "ripple::operator==(SHAMap::const_iterator, SHAMap::const_iterator) : " + "xrpl::operator==(SHAMap::const_iterator, SHAMap::const_iterator) : " "inputs map do match"); return x.item_ == y.item_; } @@ -744,6 +743,6 @@ SHAMap::end() const return const_iterator(this, nullptr); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapAccountStateLeafNode.h b/include/xrpl/shamap/SHAMapAccountStateLeafNode.h index 2486432453..288fc416b5 100644 --- a/include/xrpl/shamap/SHAMapAccountStateLeafNode.h +++ b/include/xrpl/shamap/SHAMapAccountStateLeafNode.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A leaf node for a state object. */ class SHAMapAccountStateLeafNode final @@ -68,6 +68,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapAddNode.h b/include/xrpl/shamap/SHAMapAddNode.h index 73e7a2efac..0385f64f52 100644 --- a/include/xrpl/shamap/SHAMapAddNode.h +++ b/include/xrpl/shamap/SHAMapAddNode.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { // results of adding nodes class SHAMapAddNode @@ -161,6 +161,6 @@ SHAMapAddNode::get() const return ret; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapInnerNode.h b/include/xrpl/shamap/SHAMapInnerNode.h index 9488a12e6d..72a7fe52d4 100644 --- a/include/xrpl/shamap/SHAMapInnerNode.h +++ b/include/xrpl/shamap/SHAMapInnerNode.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { class SHAMapInnerNode final : public SHAMapTreeNode, public CountedObject @@ -202,5 +202,5 @@ SHAMapInnerNode::setFullBelowGen(std::uint32_t gen) fullBelowGen_ = gen; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapItem.h b/include/xrpl/shamap/SHAMapItem.h index f76a37e733..a69f40113d 100644 --- a/include/xrpl/shamap/SHAMapItem.h +++ b/include/xrpl/shamap/SHAMapItem.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { // an item stored in a SHAMap class SHAMapItem : public CountedObject @@ -143,7 +143,7 @@ make_shamapitem(uint256 const& tag, Slice data) { XRPL_ASSERT( data.size() <= megabytes(16), - "ripple::make_shamapitem : maximum input size"); + "xrpl::make_shamapitem : maximum input size"); std::uint8_t* raw = detail::slabber.allocate(data.size()); @@ -168,6 +168,6 @@ make_shamapitem(SHAMapItem const& other) return make_shamapitem(other.key(), other.slice()); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapLeafNode.h b/include/xrpl/shamap/SHAMapLeafNode.h index 127e8c3680..d87ede16ad 100644 --- a/include/xrpl/shamap/SHAMapLeafNode.h +++ b/include/xrpl/shamap/SHAMapLeafNode.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { class SHAMapLeafNode : public SHAMapTreeNode { @@ -59,6 +59,6 @@ public: getString(SHAMapNodeID const&) const final override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapMissingNode.h b/include/xrpl/shamap/SHAMapMissingNode.h index 18c2636654..0cb18238af 100644 --- a/include/xrpl/shamap/SHAMapMissingNode.h +++ b/include/xrpl/shamap/SHAMapMissingNode.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { enum class SHAMapType { TRANSACTION = 1, // A tree of transactions @@ -50,6 +50,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapNodeID.h b/include/xrpl/shamap/SHAMapNodeID.h index dfac4fceb6..2a9e4446f4 100644 --- a/include/xrpl/shamap/SHAMapNodeID.h +++ b/include/xrpl/shamap/SHAMapNodeID.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Identifies a node inside a SHAMap */ class SHAMapNodeID : public CountedObject @@ -139,6 +139,6 @@ deserializeSHAMapNodeID(std::string const& s) [[nodiscard]] unsigned int selectBranch(SHAMapNodeID const& id, uint256 const& hash); -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapSyncFilter.h b/include/xrpl/shamap/SHAMapSyncFilter.h index 88c7eeec99..16b2389745 100644 --- a/include/xrpl/shamap/SHAMapSyncFilter.h +++ b/include/xrpl/shamap/SHAMapSyncFilter.h @@ -6,7 +6,7 @@ #include /** Callback for filtering SHAMap during sync. */ -namespace ripple { +namespace xrpl { class SHAMapSyncFilter { @@ -30,6 +30,6 @@ public: getNode(SHAMapHash const& nodeHash) const = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapTreeNode.h b/include/xrpl/shamap/SHAMapTreeNode.h index 245f8c8a7a..75992a9bce 100644 --- a/include/xrpl/shamap/SHAMapTreeNode.h +++ b/include/xrpl/shamap/SHAMapTreeNode.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { // These are wire-protocol identifiers used during serialization to encode the // type of a node. They should not be arbitrarily be changed. @@ -170,6 +170,6 @@ private: makeTransactionWithMeta(Slice data, SHAMapHash const& hash, bool hashValid); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapTxLeafNode.h b/include/xrpl/shamap/SHAMapTxLeafNode.h index e7dbd10fd6..e7b73ecde9 100644 --- a/include/xrpl/shamap/SHAMapTxLeafNode.h +++ b/include/xrpl/shamap/SHAMapTxLeafNode.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A leaf node for a transaction. No metadata is included. */ class SHAMapTxLeafNode final : public SHAMapLeafNode, @@ -64,6 +64,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/SHAMapTxPlusMetaLeafNode.h b/include/xrpl/shamap/SHAMapTxPlusMetaLeafNode.h index 915c02e7f6..c38277ef73 100644 --- a/include/xrpl/shamap/SHAMapTxPlusMetaLeafNode.h +++ b/include/xrpl/shamap/SHAMapTxPlusMetaLeafNode.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A leaf node for a transaction and its associated metadata. */ class SHAMapTxPlusMetaLeafNode final @@ -68,6 +68,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/TreeNodeCache.h b/include/xrpl/shamap/TreeNodeCache.h index bb6120e4a6..bf9797c745 100644 --- a/include/xrpl/shamap/TreeNodeCache.h +++ b/include/xrpl/shamap/TreeNodeCache.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { using TreeNodeCache = TaggedCache< uint256, @@ -13,6 +13,6 @@ using TreeNodeCache = TaggedCache< /*IsKeyCache*/ false, intr_ptr::SharedWeakUnionPtr, intr_ptr::SharedPtr>; -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/detail/TaggedPointer.h b/include/xrpl/shamap/detail/TaggedPointer.h index f3a616c052..53a53960d4 100644 --- a/include/xrpl/shamap/detail/TaggedPointer.h +++ b/include/xrpl/shamap/detail/TaggedPointer.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** TaggedPointer is a combination of a pointer and a mask stored in the lowest two bits. @@ -226,6 +226,6 @@ popcnt16(std::uint16_t a) #endif } -} // namespace ripple +} // namespace xrpl #endif diff --git a/include/xrpl/shamap/detail/TaggedPointer.ipp b/include/xrpl/shamap/detail/TaggedPointer.ipp index f3bd561e06..e88b4b11c4 100644 --- a/include/xrpl/shamap/detail/TaggedPointer.ipp +++ b/include/xrpl/shamap/detail/TaggedPointer.ipp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace { // Sparse array size boundaries. @@ -61,7 +61,7 @@ numAllocatedChildren(std::uint8_t n) { XRPL_ASSERT( n <= SHAMapInnerNode::branchFactor, - "ripple::numAllocatedChildren : valid input"); + "xrpl::numAllocatedChildren : valid input"); return *std::lower_bound(boundaries.begin(), boundaries.end(), n); } @@ -70,7 +70,7 @@ boundariesIndex(std::uint8_t numChildren) { XRPL_ASSERT( numChildren <= SHAMapInnerNode::branchFactor, - "ripple::boundariesIndex : valid input"); + "xrpl::boundariesIndex : valid input"); return std::distance( boundaries.begin(), std::lower_bound(boundaries.begin(), boundaries.end(), numChildren)); @@ -142,7 +142,7 @@ deallocateArrays(std::uint8_t boundaryIndex, void* p) { XRPL_ASSERT( isFromArrayFuns[boundaryIndex](p), - "ripple::deallocateArrays : valid inputs"); + "xrpl::deallocateArrays : valid inputs"); freeArrayFuns[boundaryIndex](p); } @@ -258,12 +258,12 @@ inline TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t numChildren) auto [tag, p] = allocateArrays(numChildren); XRPL_ASSERT( tag < boundaries.size(), - "ripple::TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t) : " + "xrpl::TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t) : " "maximum tag"); XRPL_ASSERT( (reinterpret_cast(p) & ptrMask) == reinterpret_cast(p), - "ripple::TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t) : " + "xrpl::TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t) : " "valid pointer"); tp_ = reinterpret_cast(p) + tag; } @@ -276,7 +276,7 @@ inline TaggedPointer::TaggedPointer( { XRPL_ASSERT( toAllocate >= popcnt16(dstBranches), - "ripple::TaggedPointer::TaggedPointer(TaggedPointer&& ...) : minimum " + "xrpl::TaggedPointer::TaggedPointer(TaggedPointer&& ...) : minimum " "toAllocate input"); if (other.capacity() == numAllocatedChildren(toAllocate)) @@ -427,7 +427,7 @@ inline TaggedPointer::TaggedPointer( // If sparse, may need to run additional constructors XRPL_ASSERT( !dstIsDense || dstIndex == dstNumAllocated, - "ripple::TaggedPointer::TaggedPointer(TaggedPointer&& ...) : " + "xrpl::TaggedPointer::TaggedPointer(TaggedPointer&& ...) : " "non-sparse or valid sparse"); for (int i = dstIndex; i < dstNumAllocated; ++i) { @@ -575,4 +575,4 @@ inline TaggedPointer::~TaggedPointer() destroyHashesAndChildren(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/Archive.cpp b/src/libxrpl/basics/Archive.cpp index 14a043aff8..8ee23afda0 100644 --- a/src/libxrpl/basics/Archive.cpp +++ b/src/libxrpl/basics/Archive.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { void extractTarLz4( @@ -99,4 +99,4 @@ extractTarLz4( } } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/BasicConfig.cpp b/src/libxrpl/basics/BasicConfig.cpp index 63a001bcc3..a5ad7730dd 100644 --- a/src/libxrpl/basics/BasicConfig.cpp +++ b/src/libxrpl/basics/BasicConfig.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { Section::Section(std::string const& name) : name_(name) { @@ -183,4 +183,4 @@ operator<<(std::ostream& ss, BasicConfig const& c) return ss; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/CountedObject.cpp b/src/libxrpl/basics/CountedObject.cpp index 05ee345a54..bcdca9dfa4 100644 --- a/src/libxrpl/basics/CountedObject.cpp +++ b/src/libxrpl/basics/CountedObject.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { CountedObjects& CountedObjects::getInstance() noexcept @@ -36,4 +36,4 @@ CountedObjects::getCounts(int minimumThreshold) const return counts; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/FileUtilities.cpp b/src/libxrpl/basics/FileUtilities.cpp index 239a760999..981fdd5360 100644 --- a/src/libxrpl/basics/FileUtilities.cpp +++ b/src/libxrpl/basics/FileUtilities.cpp @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { std::string getFileContents( @@ -85,4 +85,4 @@ writeFileContents( } } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/Log.cpp b/src/libxrpl/basics/Log.cpp index 0a0bb20135..33d6f6559e 100644 --- a/src/libxrpl/basics/Log.cpp +++ b/src/libxrpl/basics/Log.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { Logs::Sink::Sink( std::string const& partition, @@ -222,7 +222,7 @@ Logs::fromSeverity(beast::severities::Severity level) // LCOV_EXCL_START default: - UNREACHABLE("ripple::Logs::fromSeverity : invalid severity"); + UNREACHABLE("xrpl::Logs::fromSeverity : invalid severity"); [[fallthrough]]; // LCOV_EXCL_STOP case kFatal: @@ -250,7 +250,7 @@ Logs::toSeverity(LogSeverity level) return kError; // LCOV_EXCL_START default: - UNREACHABLE("ripple::Logs::toSeverity : invalid severity"); + UNREACHABLE("xrpl::Logs::toSeverity : invalid severity"); [[fallthrough]]; // LCOV_EXCL_STOP case lsFATAL: @@ -279,7 +279,7 @@ Logs::toString(LogSeverity s) return "Fatal"; // LCOV_EXCL_START default: - UNREACHABLE("ripple::Logs::toString : invalid severity"); + UNREACHABLE("xrpl::Logs::toString : invalid severity"); return "Unknown"; // LCOV_EXCL_STOP } @@ -345,7 +345,7 @@ Logs::format( break; // LCOV_EXCL_START default: - UNREACHABLE("ripple::Logs::format : invalid severity"); + UNREACHABLE("xrpl::Logs::format : invalid severity"); [[fallthrough]]; // LCOV_EXCL_STOP case kFatal: @@ -459,4 +459,4 @@ debugLog() return beast::Journal(debugSink().get()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/Number.cpp b/src/libxrpl/basics/Number.cpp index 797ca83b67..96c13c9db8 100644 --- a/src/libxrpl/basics/Number.cpp +++ b/src/libxrpl/basics/Number.cpp @@ -20,7 +20,7 @@ using uint128_t = boost::multiprecision::uint128_t; using uint128_t = __uint128_t; #endif // !defined(_MSC_VER) -namespace ripple { +namespace xrpl { thread_local Number::rounding_mode Number::mode_ = Number::to_nearest; @@ -280,7 +280,7 @@ Number::operator+=(Number const& y) } XRPL_ASSERT( isnormal() && y.isnormal(), - "ripple::Number::operator+=(Number) : is normal"); + "xrpl::Number::operator+=(Number) : is normal"); auto xm = mantissa(); auto xe = exponent(); int xn = 1; @@ -396,7 +396,7 @@ Number::operator*=(Number const& y) } XRPL_ASSERT( isnormal() && y.isnormal(), - "ripple::Number::operator*=(Number) : is normal"); + "xrpl::Number::operator*=(Number) : is normal"); auto xm = mantissa(); auto xe = exponent(); int xn = 1; @@ -437,7 +437,7 @@ Number::operator*=(Number const& y) exponent_ = xe; XRPL_ASSERT( isnormal() || *this == Number{}, - "ripple::Number::operator*=(Number) : result is normal"); + "xrpl::Number::operator*=(Number) : result is normal"); return *this; } @@ -548,7 +548,7 @@ to_string(Number const& amount) } XRPL_ASSERT( - exponent + 43 > 0, "ripple::to_string(Number) : minimum exponent"); + exponent + 43 > 0, "xrpl::to_string(Number) : minimum exponent"); ptrdiff_t const pad_prefix = 27; ptrdiff_t const pad_suffix = 23; @@ -575,8 +575,7 @@ to_string(Number const& amount) pre_from += pad_prefix; XRPL_ASSERT( - post_to >= post_from, - "ripple::to_string(Number) : first distance check"); + post_to >= post_from, "xrpl::to_string(Number) : first distance check"); pre_from = std::find_if(pre_from, pre_to, [](char c) { return c != '0'; }); @@ -587,7 +586,7 @@ to_string(Number const& amount) XRPL_ASSERT( post_to >= post_from, - "ripple::to_string(Number) : second distance check"); + "xrpl::to_string(Number) : second distance check"); post_to = std::find_if( std::make_reverse_iterator(post_to), @@ -772,4 +771,4 @@ power(Number const& f, unsigned n, unsigned d) return root(power(f, n), d); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/ResolverAsio.cpp b/src/libxrpl/basics/ResolverAsio.cpp index d8275e0893..8b9b2a9c4c 100644 --- a/src/libxrpl/basics/ResolverAsio.cpp +++ b/src/libxrpl/basics/ResolverAsio.cpp @@ -26,7 +26,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Mix-in to track when all pending I/O is complete. Derived classes must be callable with this signature: @@ -46,7 +46,7 @@ public: // Destroying the object with I/O pending? Not a clean exit! XRPL_ASSERT( m_pending.load() == 0, - "ripple::AsyncObject::~AsyncObject : nothing pending"); + "xrpl::AsyncObject::~AsyncObject : nothing pending"); } /** RAII container that maintains the count of pending I/O. @@ -153,9 +153,9 @@ public: { XRPL_ASSERT( m_work.empty(), - "ripple::ResolverAsioImpl::~ResolverAsioImpl : no pending work"); + "xrpl::ResolverAsioImpl::~ResolverAsioImpl : no pending work"); XRPL_ASSERT( - m_stopped, "ripple::ResolverAsioImpl::~ResolverAsioImpl : stopped"); + m_stopped, "xrpl::ResolverAsioImpl::~ResolverAsioImpl : stopped"); } //------------------------------------------------------------------------- @@ -178,10 +178,10 @@ public: start() override { XRPL_ASSERT( - m_stopped == true, "ripple::ResolverAsioImpl::start : stopped"); + m_stopped == true, "xrpl::ResolverAsioImpl::start : stopped"); XRPL_ASSERT( m_stop_called == false, - "ripple::ResolverAsioImpl::start : not stopping"); + "xrpl::ResolverAsioImpl::start : not stopping"); if (m_stopped.exchange(false) == true) { @@ -229,10 +229,10 @@ public: { XRPL_ASSERT( m_stop_called == false, - "ripple::ResolverAsioImpl::resolve : not stopping"); + "xrpl::ResolverAsioImpl::resolve : not stopping"); XRPL_ASSERT( !names.empty(), - "ripple::ResolverAsioImpl::resolve : names non-empty"); + "xrpl::ResolverAsioImpl::resolve : names non-empty"); // TODO NIKB use rvalue references to construct and move // reducing cost. @@ -255,7 +255,7 @@ public: { XRPL_ASSERT( m_stop_called == true, - "ripple::ResolverAsioImpl::do_stop : stopping"); + "xrpl::ResolverAsioImpl::do_stop : stopping"); if (m_stopped.exchange(true) == false) { @@ -415,7 +415,7 @@ public: { XRPL_ASSERT( !names.empty(), - "ripple::ResolverAsioImpl::do_resolve : names non-empty"); + "xrpl::ResolverAsioImpl::do_resolve : names non-empty"); if (m_stop_called == false) { @@ -450,4 +450,4 @@ ResolverAsio::New(boost::asio::io_context& io_context, beast::Journal journal) //----------------------------------------------------------------------------- Resolver::~Resolver() = default; -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/StringUtilities.cpp b/src/libxrpl/basics/StringUtilities.cpp index 6d7ab326af..96b5cfdb9b 100644 --- a/src/libxrpl/basics/StringUtilities.cpp +++ b/src/libxrpl/basics/StringUtilities.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { std::string sqlBlobLiteral(Blob const& blob) @@ -136,4 +136,4 @@ isProperlyFormedTomlDomain(std::string_view domain) return boost::regex_match(domain.begin(), domain.end(), re); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/UptimeClock.cpp b/src/libxrpl/basics/UptimeClock.cpp index dbfc0046a2..521a6a1313 100644 --- a/src/libxrpl/basics/UptimeClock.cpp +++ b/src/libxrpl/basics/UptimeClock.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { std::atomic UptimeClock::now_{0}; // seconds since start std::atomic UptimeClock::stop_{false}; // stop update thread @@ -54,4 +54,4 @@ UptimeClock::now() return time_point{duration{now_}}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/base64.cpp b/src/libxrpl/basics/base64.cpp index d0d11c85bb..4a5cbacaef 100644 --- a/src/libxrpl/basics/base64.cpp +++ b/src/libxrpl/basics/base64.cpp @@ -40,7 +40,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace base64 { @@ -232,4 +232,4 @@ base64_decode(std::string_view data) return dest; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/contract.cpp b/src/libxrpl/basics/contract.cpp index 81674de3c8..562d3a0944 100644 --- a/src/libxrpl/basics/contract.cpp +++ b/src/libxrpl/basics/contract.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { void LogThrow(std::string const& title) @@ -30,4 +30,4 @@ LogicError(std::string const& s) noexcept // LCOV_EXCL_STOP } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/make_SSLContext.cpp b/src/libxrpl/basics/make_SSLContext.cpp index 000f4375ab..579edb0f71 100644 --- a/src/libxrpl/basics/make_SSLContext.cpp +++ b/src/libxrpl/basics/make_SSLContext.cpp @@ -24,7 +24,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace openssl { namespace detail { @@ -385,4 +385,4 @@ make_SSLContextAuthed( return context; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/basics/mulDiv.cpp b/src/libxrpl/basics/mulDiv.cpp index 993cff7eb6..d8988b474e 100644 --- a/src/libxrpl/basics/mulDiv.cpp +++ b/src/libxrpl/basics/mulDiv.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { std::optional mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div) @@ -17,10 +17,10 @@ mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div) result /= div; - if (result > ripple::muldiv_max) + if (result > xrpl::muldiv_max) return std::nullopt; return static_cast(result); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/core/detail/Job.cpp b/src/libxrpl/core/detail/Job.cpp index 9caf8d180d..3968c3ede4 100644 --- a/src/libxrpl/core/detail/Job.cpp +++ b/src/libxrpl/core/detail/Job.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { Job::Job() : mType(jtINVALID), mJobIndex(0) { @@ -100,4 +100,4 @@ Job::operator<=(Job const& j) const return mJobIndex <= j.mJobIndex; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/core/detail/JobQueue.cpp b/src/libxrpl/core/detail/JobQueue.cpp index 817744cbc1..7393278fef 100644 --- a/src/libxrpl/core/detail/JobQueue.cpp +++ b/src/libxrpl/core/detail/JobQueue.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { JobQueue::JobQueue( int threadCount, @@ -38,8 +38,7 @@ JobQueue::JobQueue( std::forward_as_tuple(jt.type()), std::forward_as_tuple(jt, m_collector, logs))); XRPL_ASSERT( - result.second == true, - "ripple::JobQueue::JobQueue : jobs added"); + result.second == true, "xrpl::JobQueue::JobQueue : jobs added"); (void)result.second; } } @@ -66,12 +65,12 @@ JobQueue::addRefCountedJob( { XRPL_ASSERT( type != jtINVALID, - "ripple::JobQueue::addRefCountedJob : valid input job type"); + "xrpl::JobQueue::addRefCountedJob : valid input job type"); auto iter(m_jobData.find(type)); XRPL_ASSERT( iter != m_jobData.end(), - "ripple::JobQueue::addRefCountedJob : job type found in jobs"); + "xrpl::JobQueue::addRefCountedJob : job type found in jobs"); if (iter == m_jobData.end()) return false; @@ -84,7 +83,7 @@ JobQueue::addRefCountedJob( XRPL_ASSERT( (type >= jtCLIENT && type <= jtCLIENT_WEBSOCKET) || m_workers.getNumberOfThreads() > 0, - "ripple::JobQueue::addRefCountedJob : threads available or job " + "xrpl::JobQueue::addRefCountedJob : threads available or job " "requires no threads"); { @@ -96,10 +95,10 @@ JobQueue::addRefCountedJob( JobType const type(job.getType()); XRPL_ASSERT( type != jtINVALID, - "ripple::JobQueue::addRefCountedJob : has valid job type"); + "xrpl::JobQueue::addRefCountedJob : has valid job type"); XRPL_ASSERT( m_jobSet.find(job) != m_jobSet.end(), - "ripple::JobQueue::addRefCountedJob : job found"); + "xrpl::JobQueue::addRefCountedJob : job found"); perfLog_.jobQueue(type); JobTypeData& data(getJobTypeData(type)); @@ -161,7 +160,7 @@ JobQueue::makeLoadEvent(JobType t, std::string const& name) JobDataMap::iterator iter(m_jobData.find(t)); XRPL_ASSERT( iter != m_jobData.end(), - "ripple::JobQueue::makeLoadEvent : valid job type input"); + "xrpl::JobQueue::makeLoadEvent : valid job type input"); if (iter == m_jobData.end()) return {}; @@ -178,7 +177,7 @@ JobQueue::addLoadEvents(JobType t, int count, std::chrono::milliseconds elapsed) JobDataMap::iterator iter(m_jobData.find(t)); XRPL_ASSERT( iter != m_jobData.end(), - "ripple::JobQueue::addLoadEvents : valid job type input"); + "xrpl::JobQueue::addLoadEvents : valid job type input"); iter->second.load().addSamples(count, elapsed); } @@ -205,7 +204,7 @@ JobQueue::getJson(int c) for (auto& x : m_jobData) { XRPL_ASSERT( - x.first != jtINVALID, "ripple::JobQueue::getJson : valid job type"); + x.first != jtINVALID, "xrpl::JobQueue::getJson : valid job type"); if (x.first == jtGENERIC) continue; @@ -262,7 +261,7 @@ JobQueue::getJobTypeData(JobType type) JobDataMap::iterator c(m_jobData.find(type)); XRPL_ASSERT( c != m_jobData.end(), - "ripple::JobQueue::getJobTypeData : valid job type input"); + "xrpl::JobQueue::getJobTypeData : valid job type input"); // NIKB: This is ugly and I hate it. We must remove jtINVALID completely // and use something sane. @@ -289,11 +288,11 @@ JobQueue::stop() lock, [this] { return m_processCount == 0 && m_jobSet.empty(); }); XRPL_ASSERT( m_processCount == 0, - "ripple::JobQueue::stop : all processes completed"); + "xrpl::JobQueue::stop : all processes completed"); XRPL_ASSERT( - m_jobSet.empty(), "ripple::JobQueue::stop : all jobs completed"); + m_jobSet.empty(), "xrpl::JobQueue::stop : all jobs completed"); XRPL_ASSERT( - nSuspend_ == 0, "ripple::JobQueue::stop : no coros suspended"); + nSuspend_ == 0, "xrpl::JobQueue::stop : no coros suspended"); stopped_ = true; } } @@ -308,26 +307,26 @@ void JobQueue::getNextJob(Job& job) { XRPL_ASSERT( - !m_jobSet.empty(), "ripple::JobQueue::getNextJob : non-empty jobs"); + !m_jobSet.empty(), "xrpl::JobQueue::getNextJob : non-empty jobs"); std::set::const_iterator iter; for (iter = m_jobSet.begin(); iter != m_jobSet.end(); ++iter) { JobType const type = iter->getType(); XRPL_ASSERT( - type != jtINVALID, "ripple::JobQueue::getNextJob : valid job type"); + type != jtINVALID, "xrpl::JobQueue::getNextJob : valid job type"); JobTypeData& data(getJobTypeData(type)); XRPL_ASSERT( data.running <= getJobLimit(type), - "ripple::JobQueue::getNextJob : maximum jobs running"); + "xrpl::JobQueue::getNextJob : maximum jobs running"); // Run this job if we're running below the limit. if (data.running < getJobLimit(data.type())) { XRPL_ASSERT( data.waiting > 0, - "ripple::JobQueue::getNextJob : positive data waiting"); + "xrpl::JobQueue::getNextJob : positive data waiting"); --data.waiting; ++data.running; break; @@ -335,8 +334,7 @@ JobQueue::getNextJob(Job& job) } XRPL_ASSERT( - iter != m_jobSet.end(), - "ripple::JobQueue::getNextJob : found next job"); + iter != m_jobSet.end(), "xrpl::JobQueue::getNextJob : found next job"); job = *iter; m_jobSet.erase(iter); } @@ -345,8 +343,7 @@ void JobQueue::finishJob(JobType type) { XRPL_ASSERT( - type != jtINVALID, - "ripple::JobQueue::finishJob : valid input job type"); + type != jtINVALID, "xrpl::JobQueue::finishJob : valid input job type"); JobTypeData& data = getJobTypeData(type); @@ -355,7 +352,7 @@ JobQueue::finishJob(JobType type) { XRPL_ASSERT( data.running + data.waiting >= getJobLimit(type), - "ripple::JobQueue::finishJob : job limit"); + "xrpl::JobQueue::finishJob : job limit"); --data.deferred; m_workers.addTask(); @@ -422,10 +419,9 @@ JobQueue::getJobLimit(JobType type) { JobTypeInfo const& j(JobTypes::instance().get(type)); XRPL_ASSERT( - j.type() != jtINVALID, - "ripple::JobQueue::getJobLimit : valid job type"); + j.type() != jtINVALID, "xrpl::JobQueue::getJobLimit : valid job type"); return j.limit(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/core/detail/LoadEvent.cpp b/src/libxrpl/core/detail/LoadEvent.cpp index 3237daabcf..43a2c491c3 100644 --- a/src/libxrpl/core/detail/LoadEvent.cpp +++ b/src/libxrpl/core/detail/LoadEvent.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { LoadEvent::LoadEvent( LoadMonitor& monitor, @@ -63,7 +63,7 @@ LoadEvent::start() void LoadEvent::stop() { - XRPL_ASSERT(running_, "ripple::LoadEvent::stop : is running"); + XRPL_ASSERT(running_, "xrpl::LoadEvent::stop : is running"); auto const now = std::chrono::steady_clock::now(); @@ -74,4 +74,4 @@ LoadEvent::stop() monitor_.addLoadSample(*this); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/core/detail/LoadMonitor.cpp b/src/libxrpl/core/detail/LoadMonitor.cpp index 7a1cce05f3..fe2bb9e359 100644 --- a/src/libxrpl/core/detail/LoadMonitor.cpp +++ b/src/libxrpl/core/detail/LoadMonitor.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { /* @@ -182,4 +182,4 @@ LoadMonitor::getStats() return stats; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/core/detail/Workers.cpp b/src/libxrpl/core/detail/Workers.cpp index b354353844..aa4731a0ff 100644 --- a/src/libxrpl/core/detail/Workers.cpp +++ b/src/libxrpl/core/detail/Workers.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { Workers::Workers( Callback& callback, @@ -102,7 +102,7 @@ Workers::stop() XRPL_ASSERT( numberOfCurrentlyRunningTasks() == 0, - "ripple::Workers::stop : zero running tasks"); + "xrpl::Workers::stop : zero running tasks"); } void @@ -260,4 +260,4 @@ Workers::Worker::run() } while (!shouldExit); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/crypto/RFC1751.cpp b/src/libxrpl/crypto/RFC1751.cpp index 2b41e2ef38..86ee8ad382 100644 --- a/src/libxrpl/crypto/RFC1751.cpp +++ b/src/libxrpl/crypto/RFC1751.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { // // RFC 1751 code converted to C++/Boost. @@ -260,12 +260,12 @@ RFC1751::extract(char const* s, int start, int length) unsigned char cr; unsigned long x; - XRPL_ASSERT(length <= 11, "ripple::RFC1751::extract : maximum length"); - XRPL_ASSERT(start >= 0, "ripple::RFC1751::extract : minimum start"); - XRPL_ASSERT(length >= 0, "ripple::RFC1751::extract : minimum length"); + XRPL_ASSERT(length <= 11, "xrpl::RFC1751::extract : maximum length"); + XRPL_ASSERT(start >= 0, "xrpl::RFC1751::extract : minimum start"); + XRPL_ASSERT(length >= 0, "xrpl::RFC1751::extract : minimum length"); XRPL_ASSERT( start + length <= 66, - "ripple::RFC1751::extract : maximum start + length"); + "xrpl::RFC1751::extract : maximum start + length"); int const shiftR = 24 - (length + (start % 8)); cl = s[start / 8]; // get components @@ -312,12 +312,11 @@ RFC1751::insert(char* s, int x, int start, int length) unsigned long y; int shift; - XRPL_ASSERT(length <= 11, "ripple::RFC1751::insert : maximum length"); - XRPL_ASSERT(start >= 0, "ripple::RFC1751::insert : minimum start"); - XRPL_ASSERT(length >= 0, "ripple::RFC1751::insert : minimum length"); + XRPL_ASSERT(length <= 11, "xrpl::RFC1751::insert : maximum length"); + XRPL_ASSERT(start >= 0, "xrpl::RFC1751::insert : minimum start"); + XRPL_ASSERT(length >= 0, "xrpl::RFC1751::insert : minimum length"); XRPL_ASSERT( - start + length <= 66, - "ripple::RFC1751::insert : maximum start + length"); + start + length <= 66, "xrpl::RFC1751::insert : maximum start + length"); shift = ((8 - ((start + length) % 8)) % 8); y = (long)x << shift; @@ -508,4 +507,4 @@ RFC1751::getWordFromBlob(void const* blob, size_t bytes) [hash % (sizeof(s_dictionary) / sizeof(s_dictionary[0]))]; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/crypto/csprng.cpp b/src/libxrpl/crypto/csprng.cpp index e89129bfb0..5ee1700d7f 100644 --- a/src/libxrpl/crypto/csprng.cpp +++ b/src/libxrpl/crypto/csprng.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { csprng_engine::csprng_engine() { @@ -87,4 +87,4 @@ crypto_prng() return engine; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/crypto/secure_erase.cpp b/src/libxrpl/crypto/secure_erase.cpp index 6e27de59d0..5b65b342ec 100644 --- a/src/libxrpl/crypto/secure_erase.cpp +++ b/src/libxrpl/crypto/secure_erase.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { void secure_erase(void* dest, std::size_t bytes) @@ -12,4 +12,4 @@ secure_erase(void* dest, std::size_t bytes) OPENSSL_cleanse(dest, bytes); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/json/JsonPropertyStream.cpp b/src/libxrpl/json/JsonPropertyStream.cpp index fd4c0d575d..fb5a7b32a4 100644 --- a/src/libxrpl/json/JsonPropertyStream.cpp +++ b/src/libxrpl/json/JsonPropertyStream.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { JsonPropertyStream::JsonPropertyStream() : m_top(Json::objectValue) { @@ -161,4 +161,4 @@ JsonPropertyStream::add(std::string const& v) m_stack.back()->append(v); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/json/Object.cpp b/src/libxrpl/json/Object.cpp index ee63acc327..ea5e5a32d8 100644 --- a/src/libxrpl/json/Object.cpp +++ b/src/libxrpl/json/Object.cpp @@ -52,9 +52,9 @@ void Collection::checkWritable(std::string const& label) { if (!enabled_) - ripple::Throw(label + ": not enabled"); + xrpl::Throw(label + ": not enabled"); if (!writer_) - ripple::Throw(label + ": not writable"); + xrpl::Throw(label + ": not writable"); } //------------------------------------------------------------------------------ diff --git a/src/libxrpl/json/Writer.cpp b/src/libxrpl/json/Writer.cpp index e1ca1900f0..fcdceb7253 100644 --- a/src/libxrpl/json/Writer.cpp +++ b/src/libxrpl/json/Writer.cpp @@ -263,14 +263,14 @@ Writer::output(Json::Value const& value) void Writer::output(float f) { - auto s = ripple::to_string(f); + auto s = xrpl::to_string(f); impl_->output({s.data(), lengthWithoutTrailingZeros(s)}); } void Writer::output(double f) { - auto s = ripple::to_string(f); + auto s = xrpl::to_string(f); impl_->output({s.data(), lengthWithoutTrailingZeros(s)}); } diff --git a/src/libxrpl/json/json_reader.cpp b/src/libxrpl/json/json_reader.cpp index 4af0ed6ef0..c0843ca929 100644 --- a/src/libxrpl/json/json_reader.cpp +++ b/src/libxrpl/json/json_reader.cpp @@ -941,7 +941,7 @@ operator>>(std::istream& sin, Value& root) // XRPL_ASSERT(ok, "Json::operator>>() : parse succeeded"); if (!ok) - ripple::Throw(reader.getFormatedErrorMessages()); + xrpl::Throw(reader.getFormatedErrorMessages()); return sin; } diff --git a/src/libxrpl/json/json_value.cpp b/src/libxrpl/json/json_value.cpp index 1580e68255..b738774d79 100644 --- a/src/libxrpl/json/json_value.cpp +++ b/src/libxrpl/json/json_value.cpp @@ -218,7 +218,7 @@ Value::Value(char const* value) : type_(stringValue), allocated_(true) value_.string_ = valueAllocator()->duplicateStringValue(value); } -Value::Value(ripple::Number const& value) : type_(stringValue), allocated_(true) +Value::Value(xrpl::Number const& value) : type_(stringValue), allocated_(true) { auto const tmp = to_string(value); value_.string_ = diff --git a/src/libxrpl/ledger/ApplyStateTable.cpp b/src/libxrpl/ledger/ApplyStateTable.cpp index c236f0d1b5..94fd9d7273 100644 --- a/src/libxrpl/ledger/ApplyStateTable.cpp +++ b/src/libxrpl/ledger/ApplyStateTable.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { void @@ -143,7 +143,7 @@ ApplyStateTable::apply( { XRPL_ASSERT( origNode && curNode, - "ripple::detail::ApplyStateTable::apply : valid nodes for " + "xrpl::detail::ApplyStateTable::apply : valid nodes for " "deletion"); threadOwners(to, meta, origNode, newMod, j); @@ -178,7 +178,7 @@ ApplyStateTable::apply( { XRPL_ASSERT( curNode && origNode, - "ripple::detail::ApplyStateTable::apply : valid nodes for " + "xrpl::detail::ApplyStateTable::apply : valid nodes for " "modification"); if (curNode->isThreadedType( @@ -216,7 +216,7 @@ ApplyStateTable::apply( { XRPL_ASSERT( curNode && !origNode, - "ripple::detail::ApplyStateTable::apply : valid nodes for " + "xrpl::detail::ApplyStateTable::apply : valid nodes for " "creation"); threadOwners(to, meta, curNode, newMod, j); @@ -242,7 +242,7 @@ ApplyStateTable::apply( { // LCOV_EXCL_START UNREACHABLE( - "ripple::detail::ApplyStateTable::apply : unsupported " + "xrpl::detail::ApplyStateTable::apply : unsupported " "operation type"); // LCOV_EXCL_STOP } @@ -547,7 +547,7 @@ ApplyStateTable::threadItem(TxMeta& meta, std::shared_ptr const& sle) { XRPL_ASSERT( node.getFieldIndex(sfPreviousTxnLgrSeq) == -1, - "ripple::ApplyStateTable::threadItem : previous ledger is not " + "xrpl::ApplyStateTable::threadItem : previous ledger is not " "set"); node.setFieldH256(sfPreviousTxnID, prevTxID); node.setFieldU32(sfPreviousTxnLgrSeq, prevLgrID); @@ -555,11 +555,11 @@ ApplyStateTable::threadItem(TxMeta& meta, std::shared_ptr const& sle) XRPL_ASSERT( node.getFieldH256(sfPreviousTxnID) == prevTxID, - "ripple::ApplyStateTable::threadItem : previous transaction is a " + "xrpl::ApplyStateTable::threadItem : previous transaction is a " "match"); XRPL_ASSERT( node.getFieldU32(sfPreviousTxnLgrSeq) == prevLgrID, - "ripple::ApplyStateTable::threadItem : previous ledger is a match"); + "xrpl::ApplyStateTable::threadItem : previous ledger is a match"); } } @@ -576,7 +576,7 @@ ApplyStateTable::getForMod( { XRPL_ASSERT( miter->second, - "ripple::ApplyStateTable::getForMod : non-null result"); + "xrpl::ApplyStateTable::getForMod : non-null result"); return miter->second; } } @@ -634,7 +634,7 @@ ApplyStateTable::threadTx( // threadItem only applied to AccountRoot XRPL_ASSERT( sle->isThreadedType(base.rules()), - "ripple::ApplyStateTable::threadTx : SLE is threaded"); + "xrpl::ApplyStateTable::threadTx : SLE is threaded"); threadItem(meta, sle); } @@ -671,4 +671,4 @@ ApplyStateTable::threadOwners( } } // namespace detail -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/ApplyView.cpp b/src/libxrpl/ledger/ApplyView.cpp index 911bec1722..cfdbbbcb4d 100644 --- a/src/libxrpl/ledger/ApplyView.cpp +++ b/src/libxrpl/ledger/ApplyView.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace directory { @@ -135,9 +135,7 @@ insertPage( if (page != 1) node->setFieldU64(sfIndexPrevious, page - 1); XRPL_ASSERT_PARTS( - !nextPage, - "ripple::directory::insertPage", - "nextPage has default value"); + !nextPage, "xrpl::directory::insertPage", "nextPage has default value"); /* Reserved for future use when directory pages may be inserted in * between two other pages instead of only at the end of the chain. if (nextPage) @@ -193,7 +191,7 @@ ApplyView::emptyDirDelete(Keylet const& directory) node->getFieldH256(sfRootIndex) != directory.key) { // LCOV_EXCL_START - UNREACHABLE("ripple::ApplyView::emptyDirDelete : invalid node type"); + UNREACHABLE("xrpl::ApplyView::emptyDirDelete : invalid node type"); return false; // LCOV_EXCL_STOP } @@ -435,4 +433,4 @@ ApplyView::dirDelete( return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/ApplyViewBase.cpp b/src/libxrpl/ledger/ApplyViewBase.cpp index 554822acda..51abd8e4a6 100644 --- a/src/libxrpl/ledger/ApplyViewBase.cpp +++ b/src/libxrpl/ledger/ApplyViewBase.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace detail { ApplyViewBase::ApplyViewBase(ReadView const* base, ApplyFlags flags) @@ -155,4 +155,4 @@ ApplyViewBase::rawDestroyXRP(XRPAmount const& fee) } } // namespace detail -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/ApplyViewImpl.cpp b/src/libxrpl/ledger/ApplyViewImpl.cpp index 90652dd45b..b0aeb70228 100644 --- a/src/libxrpl/ledger/ApplyViewImpl.cpp +++ b/src/libxrpl/ledger/ApplyViewImpl.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { ApplyViewImpl::ApplyViewImpl(ReadView const* base, ApplyFlags flags) : ApplyViewBase(base, flags) @@ -37,4 +37,4 @@ ApplyViewImpl::visit( items_.visit(to, func); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/BookDirs.cpp b/src/libxrpl/ledger/BookDirs.cpp index 72387650ec..6dda4ffe51 100644 --- a/src/libxrpl/ledger/BookDirs.cpp +++ b/src/libxrpl/ledger/BookDirs.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { BookDirs::BookDirs(ReadView const& view, Book const& book) : view_(&view) @@ -11,13 +11,13 @@ BookDirs::BookDirs(ReadView const& view, Book const& book) , key_(view_->succ(root_, next_quality_).value_or(beast::zero)) { XRPL_ASSERT( - root_ != beast::zero, "ripple::BookDirs::BookDirs : nonzero root"); + root_ != beast::zero, "xrpl::BookDirs::BookDirs : nonzero root"); if (key_ != beast::zero) { if (!cdirFirst(*view_, key_, sle_, entry_, index_)) { // LCOV_EXCL_START - UNREACHABLE("ripple::BookDirs::BookDirs : directory is empty"); + UNREACHABLE("xrpl::BookDirs::BookDirs : directory is empty"); // LCOV_EXCL_STOP } } @@ -55,7 +55,7 @@ BookDirs::const_iterator::operator==( XRPL_ASSERT( view_ == other.view_ && root_ == other.root_, - "ripple::BookDirs::const_iterator::operator== : views and roots are " + "xrpl::BookDirs::const_iterator::operator== : views and roots are " "matching"); return entry_ == other.entry_ && cur_key_ == other.cur_key_ && index_ == other.index_; @@ -66,7 +66,7 @@ BookDirs::const_iterator::operator*() const { XRPL_ASSERT( index_ != beast::zero, - "ripple::BookDirs::const_iterator::operator* : nonzero index"); + "xrpl::BookDirs::const_iterator::operator* : nonzero index"); if (!cache_) cache_ = view_->read(keylet::offer(index_)); return *cache_; @@ -79,7 +79,7 @@ BookDirs::const_iterator::operator++() XRPL_ASSERT( index_ != zero, - "ripple::BookDirs::const_iterator::operator++ : nonzero index"); + "xrpl::BookDirs::const_iterator::operator++ : nonzero index"); if (!cdirNext(*view_, cur_key_, sle_, entry_, index_)) { if (index_ != 0 || @@ -94,7 +94,7 @@ BookDirs::const_iterator::operator++() { // LCOV_EXCL_START UNREACHABLE( - "ripple::BookDirs::const_iterator::operator++ : directory is " + "xrpl::BookDirs::const_iterator::operator++ : directory is " "empty"); // LCOV_EXCL_STOP } @@ -109,10 +109,10 @@ BookDirs::const_iterator::operator++(int) { XRPL_ASSERT( index_ != beast::zero, - "ripple::BookDirs::const_iterator::operator++(int) : nonzero index"); + "xrpl::BookDirs::const_iterator::operator++(int) : nonzero index"); const_iterator tmp(*this); ++(*this); return tmp; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/CachedView.cpp b/src/libxrpl/ledger/CachedView.cpp index 6463779845..19d4baa861 100644 --- a/src/libxrpl/ledger/CachedView.cpp +++ b/src/libxrpl/ledger/CachedView.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { bool @@ -39,8 +39,7 @@ CachedViewImpl::read(Keylet const& k) const }); // If the sle is null, then a failure must have occurred in base_.read() XRPL_ASSERT( - sle || baseRead, - "ripple::CachedView::read : null SLE result from base"); + sle || baseRead, "xrpl::CachedView::read : null SLE result from base"); if (cacheHit && baseRead) hitsexpired.increment(); else if (cacheHit) @@ -62,4 +61,4 @@ CachedViewImpl::read(Keylet const& k) const } } // namespace detail -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/CredentialHelpers.cpp b/src/libxrpl/ledger/CredentialHelpers.cpp index aea783b676..a0f1dce7d8 100644 --- a/src/libxrpl/ledger/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/CredentialHelpers.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace credentials { bool @@ -374,4 +374,4 @@ verifyDepositPreauth( return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/Dir.cpp b/src/libxrpl/ledger/Dir.cpp index ef128b7c3d..d834216d24 100644 --- a/src/libxrpl/ledger/Dir.cpp +++ b/src/libxrpl/ledger/Dir.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { using const_iterator = Dir::const_iterator; @@ -43,7 +43,7 @@ const_iterator::operator==(const_iterator const& other) const XRPL_ASSERT( view_ == other.view_ && root_.key == other.root_.key, - "ripple::const_iterator::operator== : views and roots are matching"); + "xrpl::const_iterator::operator== : views and roots are matching"); return page_.key == other.page_.key && index_ == other.index_; } @@ -52,7 +52,7 @@ const_iterator::operator*() const { XRPL_ASSERT( index_ != beast::zero, - "ripple::const_iterator::operator* : nonzero index"); + "xrpl::const_iterator::operator* : nonzero index"); if (!cache_) cache_ = view_->read(keylet::child(index_)); return *cache_; @@ -63,7 +63,7 @@ const_iterator::operator++() { XRPL_ASSERT( index_ != beast::zero, - "ripple::const_iterator::operator++ : nonzero index"); + "xrpl::const_iterator::operator++ : nonzero index"); if (++it_ != std::end(*indexes_)) { index_ = *it_; @@ -79,7 +79,7 @@ const_iterator::operator++(int) { XRPL_ASSERT( index_ != beast::zero, - "ripple::const_iterator::operator++(int) : nonzero index"); + "xrpl::const_iterator::operator++(int) : nonzero index"); const_iterator tmp(*this); ++(*this); return tmp; @@ -98,7 +98,7 @@ const_iterator::next_page() { page_ = keylet::page(root_, next); sle_ = view_->read(page_); - XRPL_ASSERT(sle_, "ripple::const_iterator::next_page : non-null SLE"); + XRPL_ASSERT(sle_, "xrpl::const_iterator::next_page : non-null SLE"); indexes_ = &sle_->getFieldV256(sfIndexes); if (indexes_->empty()) { @@ -120,4 +120,4 @@ const_iterator::page_size() return indexes_->size(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/OpenView.cpp b/src/libxrpl/ledger/OpenView.cpp index 8ddb11abd0..5df3ed7cda 100644 --- a/src/libxrpl/ledger/OpenView.cpp +++ b/src/libxrpl/ledger/OpenView.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { class OpenView::txs_iter_impl : public txs_type::iter_base { @@ -250,4 +250,4 @@ OpenView::rawTxInsert( LogicError("rawTxInsert: duplicate TX id: " + to_string(key)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/PaymentSandbox.cpp b/src/libxrpl/ledger/PaymentSandbox.cpp index 94d30529bf..09600ae623 100644 --- a/src/libxrpl/ledger/PaymentSandbox.cpp +++ b/src/libxrpl/ledger/PaymentSandbox.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -28,10 +28,10 @@ DeferredCredits::credit( { XRPL_ASSERT( sender != receiver, - "ripple::detail::DeferredCredits::credit : sender is not receiver"); + "xrpl::detail::DeferredCredits::credit : sender is not receiver"); XRPL_ASSERT( !amount.negative(), - "ripple::detail::DeferredCredits::credit : positive amount"); + "xrpl::detail::DeferredCredits::credit : positive amount"); auto const k = makeKey(sender, receiver, amount.getCurrency()); auto i = credits_.find(k); @@ -234,14 +234,14 @@ PaymentSandbox::adjustOwnerCountHook( void PaymentSandbox::apply(RawView& to) { - XRPL_ASSERT(!ps_, "ripple::PaymentSandbox::apply : non-null sandbox"); + XRPL_ASSERT(!ps_, "xrpl::PaymentSandbox::apply : non-null sandbox"); items_.apply(to); } void PaymentSandbox::apply(PaymentSandbox& to) { - XRPL_ASSERT(ps_ == &to, "ripple::PaymentSandbox::apply : matching sandbox"); + XRPL_ASSERT(ps_ == &to, "xrpl::PaymentSandbox::apply : matching sandbox"); items_.apply(to); tab_.apply(to.tab_); } @@ -327,7 +327,7 @@ PaymentSandbox::balanceChanges(ReadView const& view) const auto const at = after->getType(); XRPL_ASSERT( at == before->getType(), - "ripple::PaymentSandbox::balanceChanges : after and before " + "xrpl::PaymentSandbox::balanceChanges : after and before " "types matching"); switch (at) { @@ -377,4 +377,4 @@ PaymentSandbox::xrpDestroyed() const return items_.dropsDestroyed(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/RawStateTable.cpp b/src/libxrpl/ledger/RawStateTable.cpp index 8ba97b76c2..b958e94c54 100644 --- a/src/libxrpl/ledger/RawStateTable.cpp +++ b/src/libxrpl/ledger/RawStateTable.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { class RawStateTable::sles_iter_impl : public ReadView::sles_type::iter_base @@ -46,7 +46,7 @@ public: { XRPL_ASSERT( end1_ == p->end1_ && end0_ == p->end0_, - "ripple::detail::RawStateTable::equal : matching end " + "xrpl::detail::RawStateTable::equal : matching end " "iterators"); return iter1_ == p->iter1_ && iter0_ == p->iter0_; } @@ -59,7 +59,7 @@ public: { XRPL_ASSERT( sle1_ || sle0_, - "ripple::detail::RawStateTable::increment : either SLE is " + "xrpl::detail::RawStateTable::increment : either SLE is " "non-null"); if (sle1_ && !sle0_) @@ -167,8 +167,7 @@ bool RawStateTable::exists(ReadView const& base, Keylet const& k) const { XRPL_ASSERT( - k.key.isNonZero(), - "ripple::detail::RawStateTable::exists : nonzero key"); + k.key.isNonZero(), "xrpl::detail::RawStateTable::exists : nonzero key"); auto const iter = items_.find(k.key); if (iter == items_.end()) return base.exists(k); @@ -339,4 +338,4 @@ RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const } } // namespace detail -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/ReadView.cpp b/src/libxrpl/ledger/ReadView.cpp index 0d72a80b3c..e0764d6c81 100644 --- a/src/libxrpl/ledger/ReadView.cpp +++ b/src/libxrpl/ledger/ReadView.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { ReadView::sles_type::sles_type(ReadView const& view) : ReadViewFwdRange(view) { @@ -68,4 +68,4 @@ makeRulesGivenLedger( return Rules(presets); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index d5297479e8..c817a85b65 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -19,7 +19,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -40,7 +40,7 @@ internalDirNext( auto const& svIndexes = page->getFieldV256(sfIndexes); XRPL_ASSERT( index <= svIndexes.size(), - "ripple::detail::internalDirNext : index inside range"); + "xrpl::detail::internalDirNext : index inside range"); if (index >= svIndexes.size()) { @@ -57,7 +57,7 @@ internalDirNext( else page = view.peek(keylet::page(root, next)); - XRPL_ASSERT(page, "ripple::detail::internalDirNext : non-null root"); + XRPL_ASSERT(page, "xrpl::detail::internalDirNext : non-null root"); if (!page) return false; @@ -307,7 +307,7 @@ isVaultPseudoAccountFrozen( if (mptIssuer == nullptr) { // LCOV_EXCL_START - UNREACHABLE("ripple::isVaultPseudoAccountFrozen : null MPToken issuer"); + UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null MPToken issuer"); return false; // LCOV_EXCL_STOP } @@ -319,7 +319,7 @@ isVaultPseudoAccountFrozen( view.read(keylet::vault(mptIssuer->getFieldH256(sfVaultID))); if (vault == nullptr) { // LCOV_EXCL_START - UNREACHABLE("ripple::isVaultPseudoAccountFrozen : null vault"); + UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null vault"); return false; // LCOV_EXCL_STOP } @@ -711,7 +711,7 @@ confineOwnerCount( << "Account " << *id << " owner count set below 0!"; } adjusted = 0; - XRPL_ASSERT(!id, "ripple::confineOwnerCount : id is not set"); + XRPL_ASSERT(!id, "xrpl::confineOwnerCount : id is not set"); } } return adjusted; @@ -761,8 +761,7 @@ forEachItem( Keylet const& root, std::function const&)> const& f) { - XRPL_ASSERT( - root.type == ltDIR_NODE, "ripple::forEachItem : valid root type"); + XRPL_ASSERT(root.type == ltDIR_NODE, "xrpl::forEachItem : valid root type"); if (root.type != ltDIR_NODE) return; @@ -793,7 +792,7 @@ forEachItemAfter( std::function const&)> const& f) { XRPL_ASSERT( - root.type == ltDIR_NODE, "ripple::forEachItemAfter : valid root type"); + root.type == ltDIR_NODE, "xrpl::forEachItemAfter : valid root type"); if (root.type != ltDIR_NODE) return false; @@ -1084,7 +1083,7 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) XRPL_ASSERT( hashIndex->getFieldU32(sfLastLedgerSequence) == (ledger.seq() - 1), - "ripple::hashOfSeq : matching ledger sequence"); + "xrpl::hashOfSeq : matching ledger sequence"); STVector256 vec = hashIndex->getFieldV256(sfHashes); if (vec.size() >= diff) return vec[vec.size() - diff]; @@ -1112,9 +1111,9 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) if (hashIndex) { auto const lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence); - XRPL_ASSERT(lastSeq >= seq, "ripple::hashOfSeq : minimum last ledger"); + XRPL_ASSERT(lastSeq >= seq, "xrpl::hashOfSeq : minimum last ledger"); XRPL_ASSERT( - (lastSeq & 0xff) == 0, "ripple::hashOfSeq : valid last ledger"); + (lastSeq & 0xff) == 0, "xrpl::hashOfSeq : valid last ledger"); auto const diff = (lastSeq - seq) >> 8; STVector256 vec = hashIndex->getFieldV256(sfHashes); if (vec.size() > diff) @@ -1140,7 +1139,7 @@ adjustOwnerCount( { if (!sle) return; - XRPL_ASSERT(amount, "ripple::adjustOwnerCount : nonzero amount input"); + XRPL_ASSERT(amount, "xrpl::adjustOwnerCount : nonzero amount input"); std::uint32_t const current{sle->getFieldU32(sfOwnerCount)}; AccountID const id = (*sle)[sfAccount]; std::uint32_t const adjusted = confineOwnerCount(current, amount, id, j); @@ -1205,7 +1204,7 @@ getPseudoAccountFields() { // LCOV_EXCL_START LogicError( - "ripple::getPseudoAccountFields : unable to find account root " + "xrpl::getPseudoAccountFields : unable to find account root " "ledger " "format"); // LCOV_EXCL_STOP @@ -1258,7 +1257,7 @@ createPseudoAccount( [&ownerField](SField const* sf) -> bool { return *sf == ownerField; }) == 1, - "ripple::createPseudoAccount : valid owner field"); + "xrpl::createPseudoAccount : valid owner field"); auto const accountId = pseudoAccountAddress(view, pseudoOwnerKey); if (accountId == beast::zero) @@ -1577,7 +1576,7 @@ authorizeMPToken( { // LCOV_EXCL_START UNREACHABLE( - "ripple::authorizeMPToken : invalid issuance or issuers token"); + "xrpl::authorizeMPToken : invalid issuance or issuers token"); if (view.rules().enabled(featureLendingProtocol)) return tecINTERNAL; // LCOV_EXCL_STOP @@ -1661,7 +1660,7 @@ trustCreate( if (uLowAccountID == uHighAccountID) { // LCOV_EXCL_START - UNREACHABLE("ripple::trustCreate : trust line to self"); + UNREACHABLE("xrpl::trustCreate : trust line to self"); if (view.rules().enabled(featureLendingProtocol)) return tecINTERNAL; // LCOV_EXCL_STOP @@ -1689,14 +1688,14 @@ trustCreate( bool const bSetDst = saLimit.getIssuer() == uDstAccountID; bool const bSetHigh = bSrcHigh ^ bSetDst; - XRPL_ASSERT(sleAccount, "ripple::trustCreate : non-null SLE"); + XRPL_ASSERT(sleAccount, "xrpl::trustCreate : non-null SLE"); if (!sleAccount) return tefINTERNAL; // LCOV_EXCL_LINE XRPL_ASSERT( sleAccount->getAccountID(sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID), - "ripple::trustCreate : matching account ID"); + "xrpl::trustCreate : matching account ID"); auto const slePeer = view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID)); if (!slePeer) @@ -1933,7 +1932,7 @@ offerDelete(ApplyView& view, std::shared_ptr const& sle, beast::Journal j) { XRPL_ASSERT( sle->isFlag(lsfHybrid) && sle->isFieldPresent(sfDomainID), - "ripple::offerDelete : should be a hybrid domain offer"); + "xrpl::offerDelete : should be a hybrid domain offer"); auto const& additionalBookDirs = sle->getFieldArray(sfAdditionalBooks); @@ -1976,23 +1975,23 @@ rippleCreditIOU( // Make sure issuer is involved. XRPL_ASSERT( !bCheckIssuer || uSenderID == issuer || uReceiverID == issuer, - "ripple::rippleCreditIOU : matching issuer or don't care"); + "xrpl::rippleCreditIOU : matching issuer or don't care"); (void)issuer; // Disallow sending to self. XRPL_ASSERT( uSenderID != uReceiverID, - "ripple::rippleCreditIOU : sender is not receiver"); + "xrpl::rippleCreditIOU : sender is not receiver"); bool const bSenderHigh = uSenderID > uReceiverID; auto const index = keylet::line(uSenderID, uReceiverID, currency); XRPL_ASSERT( !isXRP(uSenderID) && uSenderID != noAccount(), - "ripple::rippleCreditIOU : sender is not XRP"); + "xrpl::rippleCreditIOU : sender is not XRP"); XRPL_ASSERT( !isXRP(uReceiverID) && uReceiverID != noAccount(), - "ripple::rippleCreditIOU : receiver is not XRP"); + "xrpl::rippleCreditIOU : receiver is not XRP"); // If the line exists, modify it accordingly. if (auto const sleRippleState = view.peek(index)) @@ -2129,10 +2128,10 @@ rippleSendIOU( XRPL_ASSERT( !isXRP(uSenderID) && !isXRP(uReceiverID), - "ripple::rippleSendIOU : neither sender nor receiver is XRP"); + "xrpl::rippleSendIOU : neither sender nor receiver is XRP"); XRPL_ASSERT( uSenderID != uReceiverID, - "ripple::rippleSendIOU : sender is not receiver"); + "xrpl::rippleSendIOU : sender is not receiver"); if (uSenderID == issuer || uReceiverID == issuer || issuer == noAccount()) { @@ -2183,7 +2182,7 @@ rippleSendMultiIOU( auto const& issuer = issue.getIssuer(); XRPL_ASSERT( - !isXRP(senderID), "ripple::rippleSendMultiIOU : sender is not XRP"); + !isXRP(senderID), "xrpl::rippleSendMultiIOU : sender is not XRP"); // These may diverge STAmount takeFromSender{issue}; @@ -2203,7 +2202,7 @@ rippleSendMultiIOU( XRPL_ASSERT( !isXRP(receiverID), - "ripple::rippleSendMultiIOU : receiver is not XRP"); + "xrpl::rippleSendMultiIOU : receiver is not XRP"); if (senderID == issuer || receiverID == issuer || issuer == noAccount()) { @@ -2269,7 +2268,7 @@ accountSendIOU( // LCOV_EXCL_START XRPL_ASSERT( saAmount >= beast::zero && !saAmount.holds(), - "ripple::accountSendIOU : minimum amount and not MPT"); + "xrpl::accountSendIOU : minimum amount and not MPT"); // LCOV_EXCL_STOP } @@ -2383,7 +2382,7 @@ accountSendMultiIOU( { XRPL_ASSERT_PARTS( receivers.size() > 1, - "ripple::accountSendMultiIOU", + "xrpl::accountSendMultiIOU", "multiple recipients provided"); if (!issue.native()) @@ -2584,7 +2583,7 @@ rippleSendMPT( { XRPL_ASSERT( uSenderID != uReceiverID, - "ripple::rippleSendMPT : sender is not receiver"); + "xrpl::rippleSendMPT : sender is not receiver"); // Safe to get MPT since rippleSendMPT is only called by accountSendMPT auto const& issuer = saAmount.getIssuer(); @@ -2745,7 +2744,7 @@ accountSendMPT( { XRPL_ASSERT( saAmount >= beast::zero && saAmount.holds(), - "ripple::accountSendMPT : minimum amount and MPT"); + "xrpl::accountSendMPT : minimum amount and MPT"); /* If we aren't sending anything or if the sender is the same as the * receiver then we don't need to do anything. @@ -2806,7 +2805,7 @@ accountSendMulti( { XRPL_ASSERT_PARTS( receivers.size() > 1, - "ripple::accountSendMulti", + "xrpl::accountSendMulti", "multiple recipients provided"); return std::visit( [&](TIss const& issue) { @@ -2883,14 +2882,14 @@ issueIOU( { XRPL_ASSERT( !isXRP(account) && !isXRP(issue.account), - "ripple::issueIOU : neither account nor issuer is XRP"); + "xrpl::issueIOU : neither account nor issuer is XRP"); // Consistency check - XRPL_ASSERT(issue == amount.issue(), "ripple::issueIOU : matching issue"); + XRPL_ASSERT(issue == amount.issue(), "xrpl::issueIOU : matching issue"); // Can't send to self! XRPL_ASSERT( - issue.account != account, "ripple::issueIOU : not issuer account"); + issue.account != account, "xrpl::issueIOU : not issuer account"); JLOG(j.trace()) << "issueIOU: " << to_string(account) << ": " << amount.getFullText(); @@ -2983,14 +2982,14 @@ redeemIOU( { XRPL_ASSERT( !isXRP(account) && !isXRP(issue.account), - "ripple::redeemIOU : neither account nor issuer is XRP"); + "xrpl::redeemIOU : neither account nor issuer is XRP"); // Consistency check - XRPL_ASSERT(issue == amount.issue(), "ripple::redeemIOU : matching issue"); + XRPL_ASSERT(issue == amount.issue(), "xrpl::redeemIOU : matching issue"); // Can't send to self! XRPL_ASSERT( - issue.account != account, "ripple::redeemIOU : not issuer account"); + issue.account != account, "xrpl::redeemIOU : not issuer account"); JLOG(j.trace()) << "redeemIOU: " << to_string(account) << ": " << amount.getFullText(); @@ -3057,10 +3056,10 @@ transferXRP( beast::Journal j) { XRPL_ASSERT( - from != beast::zero, "ripple::transferXRP : nonzero from account"); - XRPL_ASSERT(to != beast::zero, "ripple::transferXRP : nonzero to account"); - XRPL_ASSERT(from != to, "ripple::transferXRP : sender is not receiver"); - XRPL_ASSERT(amount.native(), "ripple::transferXRP : amount is XRP"); + from != beast::zero, "xrpl::transferXRP : nonzero from account"); + XRPL_ASSERT(to != beast::zero, "xrpl::transferXRP : nonzero to account"); + XRPL_ASSERT(from != to, "xrpl::transferXRP : sender is not receiver"); + XRPL_ASSERT(amount.native(), "xrpl::transferXRP : amount is XRP"); SLE::pointer const sender = view.peek(keylet::account(from)); SLE::pointer const receiver = view.peek(keylet::account(to)); @@ -3194,7 +3193,7 @@ requireAuth( { XRPL_ASSERT( sleIssuance->getFieldU32(sfFlags) & lsfMPTRequireAuth, - "ripple::requireAuth : issuance requires authorization"); + "xrpl::requireAuth : issuance requires authorization"); // ter = tefINTERNAL | tecOBJECT_NOT_FOUND | tecNO_AUTH | tecEXPIRED if (auto const ter = credentials::validDomain(view, *maybeDomainID, account); @@ -3235,7 +3234,7 @@ enforceMPTokenAuthorization( XRPL_ASSERT( sleIssuance->isFlag(lsfMPTRequireAuth), - "ripple::enforceMPTokenAuthorization : authorization required"); + "xrpl::enforceMPTokenAuthorization : authorization required"); if (account == sleIssuance->at(sfIssuer)) return tefINTERNAL; // LCOV_EXCL_LINE @@ -3281,7 +3280,7 @@ enforceMPTokenAuthorization( // MPToken which requires authorization by the token issuer. XRPL_ASSERT( sleToken != nullptr && !maybeDomainID.has_value(), - "ripple::enforceMPTokenAuthorization : found MPToken"); + "xrpl::enforceMPTokenAuthorization : found MPToken"); if (sleToken->isFlag(lsfMPTAuthorized)) return tesSUCCESS; @@ -3293,7 +3292,7 @@ enforceMPTokenAuthorization( // lsfMPTAuthorized because it is meaningless. Return tesSUCCESS XRPL_ASSERT( maybeDomainID.has_value(), - "ripple::enforceMPTokenAuthorization : found MPToken for domain"); + "xrpl::enforceMPTokenAuthorization : found MPToken for domain"); return tesSUCCESS; } else if (authorizedByDomain) @@ -3302,7 +3301,7 @@ enforceMPTokenAuthorization( // authorized by domain. Proceed to create it, then return tesSUCCESS XRPL_ASSERT( maybeDomainID.has_value() && sleToken == nullptr, - "ripple::enforceMPTokenAuthorization : new MPToken for domain"); + "xrpl::enforceMPTokenAuthorization : new MPToken for domain"); if (auto const err = authorizeMPToken( view, priorBalance, // priorBalance @@ -3317,7 +3316,7 @@ enforceMPTokenAuthorization( // LCOV_EXCL_START UNREACHABLE( - "ripple::enforceMPTokenAuthorization : condition list is incomplete"); + "xrpl::enforceMPTokenAuthorization : condition list is incomplete"); return tefINTERNAL; // LCOV_EXCL_STOP } @@ -3441,7 +3440,7 @@ cleanupOnAccountDelete( // back to 'it' to "un-invalidate" the iterator. XRPL_ASSERT( uDirEntry >= 1, - "ripple::cleanupOnAccountDelete : minimum dir entries"); + "xrpl::cleanupOnAccountDelete : minimum dir entries"); if (uDirEntry == 0) { // LCOV_EXCL_START @@ -3529,8 +3528,7 @@ rippleCredit( else { XRPL_ASSERT( - !bCheckIssuer, - "ripple::rippleCredit : not checking issuer"); + !bCheckIssuer, "xrpl::rippleCredit : not checking issuer"); return rippleCreditMPT( view, uSenderID, uReceiverID, saAmount, j); } @@ -3546,10 +3544,10 @@ assetsToSharesDeposit( { XRPL_ASSERT( !assets.negative(), - "ripple::assetsToSharesDeposit : non-negative assets"); + "xrpl::assetsToSharesDeposit : non-negative assets"); XRPL_ASSERT( assets.asset() == vault->at(sfAsset), - "ripple::assetsToSharesDeposit : assets and vault match"); + "xrpl::assetsToSharesDeposit : assets and vault match"); if (assets.negative() || assets.asset() != vault->at(sfAsset)) return std::nullopt; // LCOV_EXCL_LINE @@ -3574,10 +3572,10 @@ sharesToAssetsDeposit( { XRPL_ASSERT( !shares.negative(), - "ripple::sharesToAssetsDeposit : non-negative shares"); + "xrpl::sharesToAssetsDeposit : non-negative shares"); XRPL_ASSERT( shares.asset() == vault->at(sfShareMPTID), - "ripple::sharesToAssetsDeposit : shares and vault match"); + "xrpl::sharesToAssetsDeposit : shares and vault match"); if (shares.negative() || shares.asset() != vault->at(sfShareMPTID)) return std::nullopt; // LCOV_EXCL_LINE @@ -3604,10 +3602,10 @@ assetsToSharesWithdraw( { XRPL_ASSERT( !assets.negative(), - "ripple::assetsToSharesDeposit : non-negative assets"); + "xrpl::assetsToSharesDeposit : non-negative assets"); XRPL_ASSERT( assets.asset() == vault->at(sfAsset), - "ripple::assetsToSharesWithdraw : assets and vault match"); + "xrpl::assetsToSharesWithdraw : assets and vault match"); if (assets.negative() || assets.asset() != vault->at(sfAsset)) return std::nullopt; // LCOV_EXCL_LINE @@ -3632,10 +3630,10 @@ sharesToAssetsWithdraw( { XRPL_ASSERT( !shares.negative(), - "ripple::sharesToAssetsDeposit : non-negative shares"); + "xrpl::sharesToAssetsDeposit : non-negative shares"); XRPL_ASSERT( shares.asset() == vault->at(sfShareMPTID), - "ripple::sharesToAssetsWithdraw : shares and vault match"); + "xrpl::sharesToAssetsWithdraw : shares and vault match"); if (shares.negative() || shares.asset() != vault->at(sfShareMPTID)) return std::nullopt; // LCOV_EXCL_LINE @@ -3758,7 +3756,7 @@ rippleUnlockEscrowMPT( if (!view.rules().enabled(fixTokenEscrowV1)) XRPL_ASSERT( netAmount == grossAmount, - "ripple::rippleUnlockEscrowMPT : netAmount == grossAmount"); + "xrpl::rippleUnlockEscrowMPT : netAmount == grossAmount"); auto const& issuer = netAmount.getIssuer(); auto const& mptIssue = netAmount.get(); @@ -3926,4 +3924,4 @@ after(NetClock::time_point now, std::uint32_t mark) return now.time_since_epoch().count() > mark; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/net/HTTPClient.cpp b/src/libxrpl/net/HTTPClient.cpp index 807b5f9823..6057d81a1e 100644 --- a/src/libxrpl/net/HTTPClient.cpp +++ b/src/libxrpl/net/HTTPClient.cpp @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { static std::optional httpClientSSLContext; @@ -605,4 +605,4 @@ HTTPClient::request( client->request(bSSL, deqSites, setRequest, timeout, complete); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/net/RegisterSSLCerts.cpp b/src/libxrpl/net/RegisterSSLCerts.cpp index b93e70463b..f489cf29a3 100644 --- a/src/libxrpl/net/RegisterSSLCerts.cpp +++ b/src/libxrpl/net/RegisterSSLCerts.cpp @@ -13,7 +13,7 @@ #include #endif -namespace ripple { +namespace xrpl { void registerSSLCerts( @@ -89,7 +89,7 @@ registerSSLCerts( #endif } -} // namespace ripple +} // namespace xrpl // There is a very unpleasant interaction between and // openssl x509 types (namely the former has macros that stomp diff --git a/src/libxrpl/nodestore/BatchWriter.cpp b/src/libxrpl/nodestore/BatchWriter.cpp index cb5f7bb436..3ce7900480 100644 --- a/src/libxrpl/nodestore/BatchWriter.cpp +++ b/src/libxrpl/nodestore/BatchWriter.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { BatchWriter::BatchWriter(Callback& callback, Scheduler& scheduler) @@ -66,7 +66,7 @@ BatchWriter::writeBatch() mWriteSet.swap(set); XRPL_ASSERT( mWriteSet.empty(), - "ripple::NodeStore::BatchWriter::writeBatch : writes not set"); + "xrpl::NodeStore::BatchWriter::writeBatch : writes not set"); mWriteLoad = set.size(); if (set.empty()) @@ -102,4 +102,4 @@ BatchWriter::waitForWriting() } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/Database.cpp b/src/libxrpl/nodestore/Database.cpp index e80efee115..41e8ac8632 100644 --- a/src/libxrpl/nodestore/Database.cpp +++ b/src/libxrpl/nodestore/Database.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { Database::Database( @@ -24,7 +24,7 @@ Database::Database( { XRPL_ASSERT( readThreads, - "ripple::NodeStore::Database::Database : nonzero threads input"); + "xrpl::NodeStore::Database::Database : nonzero threads input"); if (earliestLedgerSeq_ < 1) Throw("Invalid earliest_seq"); @@ -73,7 +73,7 @@ Database::Database( { XRPL_ASSERT( !it->second.empty(), - "ripple::NodeStore::Database::Database : non-empty " + "xrpl::NodeStore::Database::Database : non-empty " "data"); auto const& hash = it->first; @@ -150,7 +150,7 @@ Database::stop() { XRPL_ASSERT( steady_clock::now() - start < 30s, - "ripple::NodeStore::Database::stop : maximum stop duration"); + "xrpl::NodeStore::Database::stop : maximum stop duration"); std::this_thread::yield(); } @@ -203,7 +203,7 @@ Database::importInternal(Backend& dstBackend, Database& srcDB) srcDB.for_each([&](std::shared_ptr nodeObject) { XRPL_ASSERT( nodeObject, - "ripple::NodeStore::Database::importInternal : non-null node"); + "xrpl::NodeStore::Database::importInternal : non-null node"); if (!nodeObject) // This should never happen return; @@ -249,7 +249,7 @@ Database::getCountsJson(Json::Value& obj) { XRPL_ASSERT( obj.isObject(), - "ripple::NodeStore::Database::getCountsJson : valid input type"); + "xrpl::NodeStore::Database::getCountsJson : valid input type"); { std::unique_lock lock(readLock_); @@ -269,4 +269,4 @@ Database::getCountsJson(Json::Value& obj) } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/DatabaseNodeImp.cpp b/src/libxrpl/nodestore/DatabaseNodeImp.cpp index a83d531b66..0578351e58 100644 --- a/src/libxrpl/nodestore/DatabaseNodeImp.cpp +++ b/src/libxrpl/nodestore/DatabaseNodeImp.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { void @@ -194,4 +194,4 @@ DatabaseNodeImp::fetchBatch(std::vector const& hashes) } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/DatabaseRotatingImp.cpp b/src/libxrpl/nodestore/DatabaseRotatingImp.cpp index dabe38ec8b..f51771f023 100644 --- a/src/libxrpl/nodestore/DatabaseRotatingImp.cpp +++ b/src/libxrpl/nodestore/DatabaseRotatingImp.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { DatabaseRotatingImp::DatabaseRotatingImp( @@ -192,4 +192,4 @@ DatabaseRotatingImp::for_each( } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/DecodedBlob.cpp b/src/libxrpl/nodestore/DecodedBlob.cpp index 11387ed8c8..e3d54fae78 100644 --- a/src/libxrpl/nodestore/DecodedBlob.cpp +++ b/src/libxrpl/nodestore/DecodedBlob.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes) @@ -56,7 +56,7 @@ DecodedBlob::createObject() { XRPL_ASSERT( m_success, - "ripple::NodeStore::DecodedBlob::createObject : valid object type"); + "xrpl::NodeStore::DecodedBlob::createObject : valid object type"); std::shared_ptr object; @@ -72,4 +72,4 @@ DecodedBlob::createObject() } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/DummyScheduler.cpp b/src/libxrpl/nodestore/DummyScheduler.cpp index 9ba7c25cfb..21c1b5c92e 100644 --- a/src/libxrpl/nodestore/DummyScheduler.cpp +++ b/src/libxrpl/nodestore/DummyScheduler.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { void @@ -21,4 +21,4 @@ DummyScheduler::onBatchWrite(BatchWriteReport const& report) } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/ManagerImp.cpp b/src/libxrpl/nodestore/ManagerImp.cpp index 627550c4e9..b53d03e668 100644 --- a/src/libxrpl/nodestore/ManagerImp.cpp +++ b/src/libxrpl/nodestore/ManagerImp.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { @@ -95,7 +95,7 @@ ManagerImp::erase(Factory& factory) }); XRPL_ASSERT( iter != list_.end(), - "ripple::NodeStore::ManagerImp::erase : valid input"); + "xrpl::NodeStore::ManagerImp::erase : valid input"); list_.erase(iter); } @@ -121,4 +121,4 @@ Manager::instance() } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/NodeObject.cpp b/src/libxrpl/nodestore/NodeObject.cpp index 953a23b70e..3758862e18 100644 --- a/src/libxrpl/nodestore/NodeObject.cpp +++ b/src/libxrpl/nodestore/NodeObject.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { //------------------------------------------------------------------------------ @@ -40,4 +40,4 @@ NodeObject::getData() const return mData; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/backend/MemoryFactory.cpp b/src/libxrpl/nodestore/backend/MemoryFactory.cpp index d4f14b7560..923ae95ebb 100644 --- a/src/libxrpl/nodestore/backend/MemoryFactory.cpp +++ b/src/libxrpl/nodestore/backend/MemoryFactory.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { struct MemoryDB @@ -122,7 +122,7 @@ public: fetch(void const* key, std::shared_ptr* pObject) override { XRPL_ASSERT( - db_, "ripple::NodeStore::MemoryBackend::fetch : non-null database"); + db_, "xrpl::NodeStore::MemoryBackend::fetch : non-null database"); uint256 const hash(uint256::fromVoid(key)); std::lock_guard _(db_->mutex); @@ -159,7 +159,7 @@ public: store(std::shared_ptr const& object) override { XRPL_ASSERT( - db_, "ripple::NodeStore::MemoryBackend::store : non-null database"); + db_, "xrpl::NodeStore::MemoryBackend::store : non-null database"); std::lock_guard _(db_->mutex); db_->table.emplace(object->getHash(), object); } @@ -181,7 +181,7 @@ public: { XRPL_ASSERT( db_, - "ripple::NodeStore::MemoryBackend::for_each : non-null database"); + "xrpl::NodeStore::MemoryBackend::for_each : non-null database"); for (auto const& e : db_->table) f(e.second); } @@ -229,4 +229,4 @@ MemoryFactory::createInstance( } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/backend/NuDBFactory.cpp b/src/libxrpl/nodestore/backend/NuDBFactory.cpp index 9d4297ac27..71a5811162 100644 --- a/src/libxrpl/nodestore/backend/NuDBFactory.cpp +++ b/src/libxrpl/nodestore/backend/NuDBFactory.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { class NuDBBackend : public Backend @@ -113,7 +113,7 @@ public: { // LCOV_EXCL_START UNREACHABLE( - "ripple::NodeStore::NuDBBackend::open : database is already " + "xrpl::NodeStore::NuDBBackend::open : database is already " "open"); JLOG(j_.error()) << "database is already open"; return; @@ -455,4 +455,4 @@ registerNuDBFactory(Manager& manager) } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/backend/NullFactory.cpp b/src/libxrpl/nodestore/backend/NullFactory.cpp index f533693416..ffe1eb931f 100644 --- a/src/libxrpl/nodestore/backend/NullFactory.cpp +++ b/src/libxrpl/nodestore/backend/NullFactory.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { class NullBackend : public Backend @@ -126,4 +126,4 @@ registerNullFactory(Manager& manager) } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/nodestore/backend/RocksDBFactory.cpp b/src/libxrpl/nodestore/backend/RocksDBFactory.cpp index 01e87f338e..97d5484554 100644 --- a/src/libxrpl/nodestore/backend/RocksDBFactory.cpp +++ b/src/libxrpl/nodestore/backend/RocksDBFactory.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { class RocksDBEnv : public rocksdb::EnvWrapper @@ -213,7 +213,7 @@ public: { // LCOV_EXCL_START UNREACHABLE( - "ripple::NodeStore::RocksDBBackend::open : database is already " + "xrpl::NodeStore::RocksDBBackend::open : database is already " "open"); JLOG(m_journal.error()) << "database is already open"; return; @@ -261,8 +261,7 @@ public: fetch(void const* key, std::shared_ptr* pObject) override { XRPL_ASSERT( - m_db, - "ripple::NodeStore::RocksDBBackend::fetch : non-null database"); + m_db, "xrpl::NodeStore::RocksDBBackend::fetch : non-null database"); pObject->reset(); Status status(ok); @@ -340,7 +339,7 @@ public: { XRPL_ASSERT( m_db, - "ripple::NodeStore::RocksDBBackend::storeBatch : non-null " + "xrpl::NodeStore::RocksDBBackend::storeBatch : non-null " "database"); rocksdb::WriteBatch wb; @@ -375,7 +374,7 @@ public: { XRPL_ASSERT( m_db, - "ripple::NodeStore::RocksDBBackend::for_each : non-null database"); + "xrpl::NodeStore::RocksDBBackend::for_each : non-null database"); rocksdb::ReadOptions const options; std::unique_ptr it(m_db->NewIterator(options)); @@ -477,6 +476,6 @@ registerRocksDBFactory(Manager& manager) } } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/libxrpl/protocol/AMMCore.cpp b/src/libxrpl/protocol/AMMCore.cpp index a91da3ff6c..71ce6ea98e 100644 --- a/src/libxrpl/protocol/AMMCore.cpp +++ b/src/libxrpl/protocol/AMMCore.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { Currency ammLPTCurrency(Currency const& cur1, Currency const& cur2) @@ -93,7 +93,7 @@ ammAuctionTimeSlot(std::uint64_t current, STObject const& auctionSlot) auto const expiration = auctionSlot[sfExpiration]; XRPL_ASSERT( expiration >= TOTAL_TIME_SLOT_SECS, - "ripple::ammAuctionTimeSlot : minimum expiration"); + "xrpl::ammAuctionTimeSlot : minimum expiration"); if (expiration >= TOTAL_TIME_SLOT_SECS) { if (auto const start = expiration - TOTAL_TIME_SLOT_SECS; @@ -112,4 +112,4 @@ ammEnabled(Rules const& rules) return rules.enabled(featureAMM) && rules.enabled(fixUniversalNumber); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/AccountID.cpp b/src/libxrpl/protocol/AccountID.cpp index 4032d4f829..779018613f 100644 --- a/src/libxrpl/protocol/AccountID.cpp +++ b/src/libxrpl/protocol/AccountID.cpp @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -68,7 +68,7 @@ public: XRPL_ASSERT( ret.size() <= 38, - "ripple::detail::AccountIdCache : maximum result size"); + "xrpl::detail::AccountIdCache : maximum result size"); { std::lock_guard lock(sl); @@ -181,4 +181,4 @@ to_issuer(AccountID& issuer, std::string const& s) return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Asset.cpp b/src/libxrpl/protocol/Asset.cpp index 54c6732825..1a4a94f744 100644 --- a/src/libxrpl/protocol/Asset.cpp +++ b/src/libxrpl/protocol/Asset.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { AccountID const& Asset::getIssuer() const @@ -66,4 +66,4 @@ assetFromJson(Json::Value const& v) return mptIssueFromJson(v); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Book.cpp b/src/libxrpl/protocol/Book.cpp index 0315cf83ae..d26aaf3384 100644 --- a/src/libxrpl/protocol/Book.cpp +++ b/src/libxrpl/protocol/Book.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { bool isConsistent(Book const& book) @@ -32,4 +32,4 @@ reversed(Book const& book) return Book(book.out, book.in, book.domain); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/BuildInfo.cpp b/src/libxrpl/protocol/BuildInfo.cpp index 7690ae586b..472a8cb039 100644 --- a/src/libxrpl/protocol/BuildInfo.cpp +++ b/src/libxrpl/protocol/BuildInfo.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace BuildInfo { @@ -159,4 +159,4 @@ isNewerVersion(std::uint64_t version) } // namespace BuildInfo -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/ErrorCodes.cpp b/src/libxrpl/protocol/ErrorCodes.cpp index 5d7accb4a1..f37ba0c8e4 100644 --- a/src/libxrpl/protocol/ErrorCodes.cpp +++ b/src/libxrpl/protocol/ErrorCodes.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { namespace detail { @@ -205,8 +205,8 @@ rpcErrorString(Json::Value const& jv) { XRPL_ASSERT( RPC::contains_error(jv), - "ripple::RPC::rpcErrorString : input contains an error"); + "xrpl::RPC::rpcErrorString : input contains an error"); return jv[jss::error].asString() + jv[jss::error_message].asString(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Feature.cpp b/src/libxrpl/protocol/Feature.cpp index 10c42ccb8a..dc4fd105b5 100644 --- a/src/libxrpl/protocol/Feature.cpp +++ b/src/libxrpl/protocol/Feature.cpp @@ -19,10 +19,10 @@ #include #include -namespace ripple { +namespace xrpl { inline std::size_t -hash_value(ripple::uint256 const& feature) +hash_value(xrpl::uint256 const& feature) { std::size_t seed = 0; using namespace boost; @@ -205,7 +205,7 @@ public: FeatureCollections::FeatureCollections() { - features.reserve(ripple::detail::numFeatures); + features.reserve(xrpl::detail::numFeatures); } std::optional @@ -213,7 +213,7 @@ FeatureCollections::getRegisteredFeature(std::string const& name) const { XRPL_ASSERT( readOnly.load(), - "ripple::FeatureCollections::getRegisteredFeature : startup completed"); + "xrpl::FeatureCollections::getRegisteredFeature : startup completed"); Feature const* feature = getByName(name); if (feature) return feature->feature; @@ -294,7 +294,7 @@ FeatureCollections::featureToBitsetIndex(uint256 const& f) const { XRPL_ASSERT( readOnly.load(), - "ripple::FeatureCollections::featureToBitsetIndex : startup completed"); + "xrpl::FeatureCollections::featureToBitsetIndex : startup completed"); Feature const* feature = getByFeature(f); if (!feature) @@ -308,7 +308,7 @@ FeatureCollections::bitsetIndexToFeature(size_t i) const { XRPL_ASSERT( readOnly.load(), - "ripple::FeatureCollections::bitsetIndexToFeature : startup completed"); + "xrpl::FeatureCollections::bitsetIndexToFeature : startup completed"); Feature const& feature = getByIndex(i); return feature.feature; } @@ -318,7 +318,7 @@ FeatureCollections::featureToName(uint256 const& f) const { XRPL_ASSERT( readOnly.load(), - "ripple::FeatureCollections::featureToName : startup completed"); + "xrpl::FeatureCollections::featureToName : startup completed"); Feature const* feature = getByFeature(f); return feature ? feature->name : to_string(f); } @@ -452,4 +452,4 @@ featureToName(uint256 const& f) [[maybe_unused]] static bool const readOnlySet = featureCollections.registrationIsDone(); -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/IOUAmount.cpp b/src/libxrpl/protocol/IOUAmount.cpp index 3c893709d7..01283886e1 100644 --- a/src/libxrpl/protocol/IOUAmount.cpp +++ b/src/libxrpl/protocol/IOUAmount.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace { @@ -303,4 +303,4 @@ mulRatio( return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Indexes.cpp b/src/libxrpl/protocol/Indexes.cpp index b80f648c98..77fcd44a3e 100644 --- a/src/libxrpl/protocol/Indexes.cpp +++ b/src/libxrpl/protocol/Indexes.cpp @@ -25,7 +25,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Type-specific prefix for calculating ledger indices. @@ -97,8 +97,7 @@ indexHash(LedgerNameSpace space, Args const&... args) uint256 getBookBase(Book const& book) { - XRPL_ASSERT( - isConsistent(book), "ripple::getBookBase : input is consistent"); + XRPL_ASSERT(isConsistent(book), "xrpl::getBookBase : input is consistent"); auto const index = book.domain ? indexHash( LedgerNameSpace::BOOK_DIR, @@ -145,7 +144,7 @@ getTicketIndex(AccountID const& account, std::uint32_t ticketSeq) uint256 getTicketIndex(AccountID const& account, SeqProxy ticketSeq) { - XRPL_ASSERT(ticketSeq.isTicket(), "ripple::getTicketIndex : valid input"); + XRPL_ASSERT(ticketSeq.isTicket(), "xrpl::getTicketIndex : valid input"); return getTicketIndex(account, ticketSeq.value()); } @@ -232,7 +231,7 @@ line( // There is code in SetTrust that calls us with id0 == id1, to allow users // to locate and delete such "weird" trustlines. If we remove that code, we // could enable this assert: - // XRPL_ASSERT(id0 != id1, "ripple::keylet::line : accounts must be + // XRPL_ASSERT(id0 != id1, "xrpl::keylet::line : accounts must be // different"); // A trust line is shared between two accounts; while we typically think @@ -263,7 +262,7 @@ Keylet quality(Keylet const& k, std::uint64_t q) noexcept { XRPL_ASSERT( - k.type == ltDIR_NODE, "ripple::keylet::quality : valid input type"); + k.type == ltDIR_NODE, "xrpl::keylet::quality : valid input type"); // Indexes are stored in big endian format: they print as hex as stored. // Most significant bytes are first and the least significant bytes @@ -283,7 +282,7 @@ next_t::operator()(Keylet const& k) const { XRPL_ASSERT( k.type == ltDIR_NODE, - "ripple::keylet::next_t::operator() : valid input type"); + "xrpl::keylet::next_t::operator() : valid input type"); return {ltDIR_NODE, getQualityNext(k.key)}; } @@ -402,7 +401,7 @@ Keylet nftpage(Keylet const& k, uint256 const& token) { XRPL_ASSERT( - k.type == ltNFTOKEN_PAGE, "ripple::keylet::nftpage : valid input type"); + k.type == ltNFTOKEN_PAGE, "xrpl::keylet::nftpage : valid input type"); return {ltNFTOKEN_PAGE, (k.key & ~nft::pageMask) + (token & nft::pageMask)}; } @@ -577,4 +576,4 @@ permissionedDomain(uint256 const& domainID) noexcept } // namespace keylet -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/InnerObjectFormats.cpp b/src/libxrpl/protocol/InnerObjectFormats.cpp index d720c6c665..3eb73e7c9b 100644 --- a/src/libxrpl/protocol/InnerObjectFormats.cpp +++ b/src/libxrpl/protocol/InnerObjectFormats.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { InnerObjectFormats::InnerObjectFormats() { @@ -180,4 +180,4 @@ InnerObjectFormats::findSOTemplateBySField(SField const& sField) const return nullptr; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Issue.cpp b/src/libxrpl/protocol/Issue.cpp index 205648fe4d..b858a31e3e 100644 --- a/src/libxrpl/protocol/Issue.cpp +++ b/src/libxrpl/protocol/Issue.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { std::string Issue::getText() const @@ -132,4 +132,4 @@ operator<<(std::ostream& os, Issue const& x) return os; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Keylet.cpp b/src/libxrpl/protocol/Keylet.cpp index 9d2202e19b..2c65bb9ed4 100644 --- a/src/libxrpl/protocol/Keylet.cpp +++ b/src/libxrpl/protocol/Keylet.cpp @@ -3,14 +3,14 @@ #include #include -namespace ripple { +namespace xrpl { bool Keylet::check(STLedgerEntry const& sle) const { XRPL_ASSERT( sle.getType() != ltANY || sle.getType() != ltCHILD, - "ripple::Keylet::check : valid input type"); + "xrpl::Keylet::check : valid input type"); if (type == ltANY) return true; @@ -21,4 +21,4 @@ Keylet::check(STLedgerEntry const& sle) const return sle.getType() == type && sle.key() == key; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/LedgerFormats.cpp b/src/libxrpl/protocol/LedgerFormats.cpp index 908b28ae43..2056cfab7b 100644 --- a/src/libxrpl/protocol/LedgerFormats.cpp +++ b/src/libxrpl/protocol/LedgerFormats.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { LedgerFormats::LedgerFormats() { @@ -40,4 +40,4 @@ LedgerFormats::getInstance() return instance; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/LedgerHeader.cpp b/src/libxrpl/protocol/LedgerHeader.cpp index 84d026b613..5258bdbc22 100644 --- a/src/libxrpl/protocol/LedgerHeader.cpp +++ b/src/libxrpl/protocol/LedgerHeader.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { void addRaw(LedgerHeader const& info, Serializer& s, bool includeHash) @@ -52,4 +52,4 @@ deserializePrefixedHeader(Slice data, bool hasHash) return deserializeHeader(data + 4, hasHash); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/MPTAmount.cpp b/src/libxrpl/protocol/MPTAmount.cpp index 046e81199a..1950407ab5 100644 --- a/src/libxrpl/protocol/MPTAmount.cpp +++ b/src/libxrpl/protocol/MPTAmount.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { MPTAmount& MPTAmount::operator+=(MPTAmount const& other) @@ -46,4 +46,4 @@ MPTAmount::minPositiveAmount() return MPTAmount{1}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/MPTIssue.cpp b/src/libxrpl/protocol/MPTIssue.cpp index c7d54ee6d6..c92ac60b73 100644 --- a/src/libxrpl/protocol/MPTIssue.cpp +++ b/src/libxrpl/protocol/MPTIssue.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { MPTIssue::MPTIssue(MPTID const& issuanceID) : mptID_(issuanceID) { @@ -88,4 +88,4 @@ mptIssueFromJson(Json::Value const& v) return MPTIssue{id}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/NFTSyntheticSerializer.cpp b/src/libxrpl/protocol/NFTSyntheticSerializer.cpp index ee677b798c..e4ce3b7611 100644 --- a/src/libxrpl/protocol/NFTSyntheticSerializer.cpp +++ b/src/libxrpl/protocol/NFTSyntheticSerializer.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { void @@ -22,4 +22,4 @@ insertNFTSyntheticInJson( } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/NFTokenID.cpp b/src/libxrpl/protocol/NFTokenID.cpp index 50a6f30bf8..64fadce3c9 100644 --- a/src/libxrpl/protocol/NFTokenID.cpp +++ b/src/libxrpl/protocol/NFTokenID.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { bool canHaveNFTokenID( @@ -184,4 +184,4 @@ insertNFTokenID( } } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/NFTokenOfferID.cpp b/src/libxrpl/protocol/NFTokenOfferID.cpp index 77b836207f..b1a08081c0 100644 --- a/src/libxrpl/protocol/NFTokenOfferID.cpp +++ b/src/libxrpl/protocol/NFTokenOfferID.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { bool canHaveNFTokenOfferID( @@ -64,4 +64,4 @@ insertNFTokenOfferID( response[jss::offer_id] = to_string(result.value()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Permissions.cpp b/src/libxrpl/protocol/Permissions.cpp index c73e38304f..a5d447a23c 100644 --- a/src/libxrpl/protocol/Permissions.cpp +++ b/src/libxrpl/protocol/Permissions.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { Permission::Permission() { @@ -71,7 +71,7 @@ Permission::Permission() for ([[maybe_unused]] auto const& permission : granularPermissionMap_) XRPL_ASSERT( permission.second > UINT16_MAX, - "ripple::Permission::granularPermissionMap_ : granular permission " + "xrpl::Permission::granularPermissionMap_ : granular permission " "value must not exceed the maximum uint16_t value."); } @@ -134,7 +134,7 @@ Permission::getTxFeature(TxType txType) const auto const txFeaturesIt = txFeatureMap_.find(txType); XRPL_ASSERT( txFeaturesIt != txFeatureMap_.end(), - "ripple::Permissions::getTxFeature : tx exists in txFeatureMap_"); + "xrpl::Permissions::getTxFeature : tx exists in txFeatureMap_"); if (txFeaturesIt->second == uint256{}) return std::nullopt; @@ -161,7 +161,7 @@ Permission::isDelegatable( auto const txFeaturesIt = txFeatureMap_.find(txType); XRPL_ASSERT( txFeaturesIt != txFeatureMap_.end(), - "ripple::Permissions::isDelegatable : tx exists in txFeatureMap_"); + "xrpl::Permissions::isDelegatable : tx exists in txFeatureMap_"); // Delegation is only allowed if the required amendment for the transaction // is enabled. For transactions that do not require an amendment, delegation @@ -188,4 +188,4 @@ Permission::permissionToTxType(uint32_t const& value) const return static_cast(value - 1); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/PublicKey.cpp b/src/libxrpl/protocol/PublicKey.cpp index 5e3a0b651b..2dcf484adc 100644 --- a/src/libxrpl/protocol/PublicKey.cpp +++ b/src/libxrpl/protocol/PublicKey.cpp @@ -21,7 +21,7 @@ #include #include -namespace ripple { +namespace xrpl { std::ostream& operator<<(std::ostream& os, PublicKey const& pk) @@ -301,4 +301,4 @@ calcNodeID(PublicKey const& pk) return NodeID{static_cast(h)}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Quality.cpp b/src/libxrpl/protocol/Quality.cpp index f20145036b..cd56f237fc 100644 --- a/src/libxrpl/protocol/Quality.cpp +++ b/src/libxrpl/protocol/Quality.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { Quality::Quality(std::uint64_t value) : m_value(value) { @@ -21,7 +21,7 @@ Quality::Quality(Amounts const& amount) Quality& Quality::operator++() { - XRPL_ASSERT(m_value > 0, "ripple::Quality::operator++() : minimum value"); + XRPL_ASSERT(m_value > 0, "xrpl::Quality::operator++() : minimum value"); --m_value; return *this; } @@ -39,7 +39,7 @@ Quality::operator--() { XRPL_ASSERT( m_value < std::numeric_limits::max(), - "ripple::Quality::operator--() : maximum value"); + "xrpl::Quality::operator--() : maximum value"); ++m_value; return *this; } @@ -70,11 +70,10 @@ ceil_in_impl( if (result.out > amount.out) result.out = amount.out; XRPL_ASSERT( - result.in == limit, "ripple::ceil_in_impl : result matches limit"); + result.in == limit, "xrpl::ceil_in_impl : result matches limit"); return result; } - XRPL_ASSERT( - amount.in <= limit, "ripple::ceil_in_impl : result inside limit"); + XRPL_ASSERT(amount.in <= limit, "xrpl::ceil_in_impl : result inside limit"); return amount; } @@ -111,12 +110,11 @@ ceil_out_impl( if (result.in > amount.in) result.in = amount.in; XRPL_ASSERT( - result.out == limit, - "ripple::ceil_out_impl : result matches limit"); + result.out == limit, "xrpl::ceil_out_impl : result matches limit"); return result; } XRPL_ASSERT( - amount.out <= limit, "ripple::ceil_out_impl : result inside limit"); + amount.out <= limit, "xrpl::ceil_out_impl : result inside limit"); return amount; } @@ -140,13 +138,12 @@ composed_quality(Quality const& lhs, Quality const& rhs) { STAmount const lhs_rate(lhs.rate()); XRPL_ASSERT( - lhs_rate != beast::zero, - "ripple::composed_quality : nonzero left input"); + lhs_rate != beast::zero, "xrpl::composed_quality : nonzero left input"); STAmount const rhs_rate(rhs.rate()); XRPL_ASSERT( rhs_rate != beast::zero, - "ripple::composed_quality : nonzero right input"); + "xrpl::composed_quality : nonzero right input"); STAmount const rate(mulRound(lhs_rate, rhs_rate, lhs_rate.asset(), true)); @@ -155,7 +152,7 @@ composed_quality(Quality const& lhs, Quality const& rhs) XRPL_ASSERT( (stored_exponent > 0) && (stored_exponent <= 255), - "ripple::composed_quality : valid exponent"); + "xrpl::composed_quality : valid exponent"); return Quality((stored_exponent << (64 - 8)) | stored_mantissa); } @@ -192,4 +189,4 @@ Quality::round(int digits) const return Quality{(exponent << (64 - 8)) | mantissa}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/QualityFunction.cpp b/src/libxrpl/protocol/QualityFunction.cpp index 8273743cfa..b254e1af86 100644 --- a/src/libxrpl/protocol/QualityFunction.cpp +++ b/src/libxrpl/protocol/QualityFunction.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { QualityFunction::QualityFunction( Quality const& quality, @@ -42,4 +42,4 @@ QualityFunction::outFromAvgQ(Quality const& quality) return std::nullopt; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/RPCErr.cpp b/src/libxrpl/protocol/RPCErr.cpp index 4984f91279..658dd06b3d 100644 --- a/src/libxrpl/protocol/RPCErr.cpp +++ b/src/libxrpl/protocol/RPCErr.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { struct RPCErr; @@ -23,4 +23,4 @@ isRpcError(Json::Value jvResult) return jvResult.isObject() && jvResult.isMember(jss::error); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Rate2.cpp b/src/libxrpl/protocol/Rate2.cpp index 36c6ae37f9..511b28cc67 100644 --- a/src/libxrpl/protocol/Rate2.cpp +++ b/src/libxrpl/protocol/Rate2.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { Rate const parityRate(QUALITY_ONE); @@ -33,7 +33,7 @@ transferFeeAsRate(std::uint16_t fee) STAmount multiply(STAmount const& amount, Rate const& rate) { - XRPL_ASSERT(rate.value, "ripple::nft::multiply : nonzero rate input"); + XRPL_ASSERT(rate.value, "xrpl::nft::multiply : nonzero rate input"); if (rate == parityRate) return amount; @@ -44,7 +44,7 @@ multiply(STAmount const& amount, Rate const& rate) STAmount multiplyRound(STAmount const& amount, Rate const& rate, bool roundUp) { - XRPL_ASSERT(rate.value, "ripple::nft::multiplyRound : nonzero rate input"); + XRPL_ASSERT(rate.value, "xrpl::nft::multiplyRound : nonzero rate input"); if (rate == parityRate) return amount; @@ -60,7 +60,7 @@ multiplyRound( bool roundUp) { XRPL_ASSERT( - rate.value, "ripple::nft::multiplyRound(Issue) : nonzero rate input"); + rate.value, "xrpl::nft::multiplyRound(Issue) : nonzero rate input"); if (rate == parityRate) { @@ -73,7 +73,7 @@ multiplyRound( STAmount divide(STAmount const& amount, Rate const& rate) { - XRPL_ASSERT(rate.value, "ripple::nft::divide : nonzero rate input"); + XRPL_ASSERT(rate.value, "xrpl::nft::divide : nonzero rate input"); if (rate == parityRate) return amount; @@ -84,7 +84,7 @@ divide(STAmount const& amount, Rate const& rate) STAmount divideRound(STAmount const& amount, Rate const& rate, bool roundUp) { - XRPL_ASSERT(rate.value, "ripple::nft::divideRound : nonzero rate input"); + XRPL_ASSERT(rate.value, "xrpl::nft::divideRound : nonzero rate input"); if (rate == parityRate) return amount; @@ -100,7 +100,7 @@ divideRound( bool roundUp) { XRPL_ASSERT( - rate.value, "ripple::nft::divideRound(Issue) : nonzero rate input"); + rate.value, "xrpl::nft::divideRound(Issue) : nonzero rate input"); if (rate == parityRate) return amount; @@ -108,4 +108,4 @@ divideRound( return divRound(amount, detail::as_amount(rate), asset, roundUp); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Rules.cpp b/src/libxrpl/protocol/Rules.cpp index 7d84c4e7da..b1f2c2d631 100644 --- a/src/libxrpl/protocol/Rules.cpp +++ b/src/libxrpl/protocol/Rules.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace { // Use a static inside a function to help prevent order-of-initialization issues @@ -82,7 +82,7 @@ public: return false; XRPL_ASSERT( presets_ == other.presets_, - "ripple::Rules::Impl::operator==(Impl) const : input presets do " + "xrpl::Rules::Impl::operator==(Impl) const : input presets do " "match"); return *digest_ == *other.digest_; } @@ -110,7 +110,7 @@ Rules::presets() const bool Rules::enabled(uint256 const& feature) const { - XRPL_ASSERT(impl_, "ripple::Rules::enabled : initialized"); + XRPL_ASSERT(impl_, "xrpl::Rules::enabled : initialized"); return impl_->enabled(feature); } @@ -120,7 +120,7 @@ Rules::operator==(Rules const& other) const { XRPL_ASSERT( impl_ && other.impl_, - "ripple::Rules::operator==(Rules) const : both initialized"); + "xrpl::Rules::operator==(Rules) const : both initialized"); if (impl_.get() == other.impl_.get()) return true; return *impl_ == *other.impl_; @@ -139,4 +139,4 @@ isFeatureEnabled(uint256 const& feature) return rules && rules->enabled(feature); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/SField.cpp b/src/libxrpl/protocol/SField.cpp index 61d7aff930..54402ea6e2 100644 --- a/src/libxrpl/protocol/SField.cpp +++ b/src/libxrpl/protocol/SField.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { // Storage for static const members. SField::IsSigning const SField::notSigning; @@ -84,10 +84,10 @@ SField::SField( { XRPL_ASSERT( !knownCodeToField.contains(fieldCode), - "ripple::SField::SField(tid,fv,fn,meta,signing) : fieldCode is unique"); + "xrpl::SField::SField(tid,fv,fn,meta,signing) : fieldCode is unique"); XRPL_ASSERT( !knownNameToField.contains(fieldName), - "ripple::SField::SField(tid,fv,fn,meta,signing) : fieldName is unique"); + "xrpl::SField::SField(tid,fv,fn,meta,signing) : fieldName is unique"); knownCodeToField[fieldCode] = this; knownNameToField[fieldName] = this; } @@ -104,10 +104,10 @@ SField::SField(private_access_tag_t, int fc, char const* fn) { XRPL_ASSERT( !knownCodeToField.contains(fieldCode), - "ripple::SField::SField(fc,fn) : fieldCode is unique"); + "xrpl::SField::SField(fc,fn) : fieldCode is unique"); XRPL_ASSERT( !knownNameToField.contains(fieldName), - "ripple::SField::SField(fc,fn) : fieldName is unique"); + "xrpl::SField::SField(fc,fn) : fieldName is unique"); knownCodeToField[fieldCode] = this; knownNameToField[fieldName] = this; } @@ -152,4 +152,4 @@ SField::getField(std::string const& fieldName) return sfInvalid; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/SOTemplate.cpp b/src/libxrpl/protocol/SOTemplate.cpp index 6bd5b7a5c6..46edf98710 100644 --- a/src/libxrpl/protocol/SOTemplate.cpp +++ b/src/libxrpl/protocol/SOTemplate.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { SOTemplate::SOTemplate( std::initializer_list uniqueFields, @@ -50,4 +50,4 @@ SOTemplate::getIndex(SField const& sField) const return indices_[sField.getNum()]; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STAccount.cpp b/src/libxrpl/protocol/STAccount.cpp index b452be7ee4..728fb25f6c 100644 --- a/src/libxrpl/protocol/STAccount.cpp +++ b/src/libxrpl/protocol/STAccount.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { STAccount::STAccount() : STBase(), value_(beast::zero), default_(true) { @@ -74,10 +74,10 @@ void STAccount::add(Serializer& s) const { XRPL_ASSERT( - getFName().isBinary(), "ripple::STAccount::add : field is binary"); + getFName().isBinary(), "xrpl::STAccount::add : field is binary"); XRPL_ASSERT( getFName().fieldType == STI_ACCOUNT, - "ripple::STAccount::add : valid field type"); + "xrpl::STAccount::add : valid field type"); // Preserve the serialization behavior of an STBlob: // o If we are default (all zeros) serialize as an empty blob. @@ -107,4 +107,4 @@ STAccount::getText() const return toBase58(value()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STAmount.cpp b/src/libxrpl/protocol/STAmount.cpp index 8b714193cc..824453a4d3 100644 --- a/src/libxrpl/protocol/STAmount.cpp +++ b/src/libxrpl/protocol/STAmount.cpp @@ -47,7 +47,7 @@ #include #include -namespace ripple { +namespace xrpl { static std::uint64_t const tenTo14 = 100000000000000ull; static std::uint64_t const tenTo14m1 = tenTo14 - 1; @@ -60,13 +60,13 @@ getInt64Value(STAmount const& amount, bool valid, char const* error) if (!valid) Throw(error); XRPL_ASSERT( - amount.exponent() == 0, "ripple::getInt64Value : exponent is zero"); + amount.exponent() == 0, "xrpl::getInt64Value : exponent is zero"); auto ret = static_cast(amount.mantissa()); XRPL_ASSERT( static_cast(ret) == amount.mantissa(), - "ripple::getInt64Value : mantissa must roundtrip"); + "xrpl::getInt64Value : mantissa must roundtrip"); if (amount.negative()) ret = -ret; @@ -195,7 +195,7 @@ STAmount::STAmount(SField const& name, std::uint64_t mantissa, bool negative) { XRPL_ASSERT( mValue <= std::numeric_limits::max(), - "ripple::STAmount::STAmount(SField, std::uint64_t, bool) : maximum " + "xrpl::STAmount::STAmount(SField, std::uint64_t, bool) : maximum " "mantissa input"); } @@ -208,7 +208,7 @@ STAmount::STAmount(SField const& name, STAmount const& from) { XRPL_ASSERT( mValue <= std::numeric_limits::max(), - "ripple::STAmount::STAmount(SField, STAmount) : maximum input"); + "xrpl::STAmount::STAmount(SField, STAmount) : maximum input"); canonicalize(); } @@ -222,7 +222,7 @@ STAmount::STAmount(std::uint64_t mantissa, bool negative) { XRPL_ASSERT( mValue <= std::numeric_limits::max(), - "ripple::STAmount::STAmount(std::uint64_t, bool) : maximum mantissa " + "xrpl::STAmount::STAmount(std::uint64_t, bool) : maximum mantissa " "input"); } @@ -268,7 +268,7 @@ STAmount::xrp() const "Cannot return non-native STAmount as XRPAmount"); auto drops = static_cast(mValue); - XRPL_ASSERT(mOffset == 0, "ripple::STAmount::xrp : amount is canonical"); + XRPL_ASSERT(mOffset == 0, "xrpl::STAmount::xrp : amount is canonical"); if (mIsNegative) drops = -drops; @@ -298,7 +298,7 @@ STAmount::mpt() const Throw("Cannot return STAmount as MPTAmount"); auto value = static_cast(mValue); - XRPL_ASSERT(mOffset == 0, "ripple::STAmount::mpt : amount is canonical"); + XRPL_ASSERT(mOffset == 0, "xrpl::STAmount::mpt : amount is canonical"); if (mIsNegative) value = -value; @@ -310,8 +310,7 @@ STAmount& STAmount::operator=(IOUAmount const& iou) { XRPL_ASSERT( - native() == false, - "ripple::STAmount::operator=(IOUAmount) : is not XRP"); + native() == false, "xrpl::STAmount::operator=(IOUAmount) : is not XRP"); mOffset = iou.exponent(); mIsNegative = iou < beast::zero; if (mIsNegative) @@ -452,7 +451,7 @@ getRate(STAmount const& offerOut, STAmount const& offerIn) return 0; XRPL_ASSERT( (r.exponent() >= -100) && (r.exponent() <= 155), - "ripple::getRate : exponent inside range"); + "xrpl::getRate : exponent inside range"); std::uint64_t ret = r.exponent() + 100; return (ret << (64 - 8)) | r.mantissa(); } @@ -689,7 +688,7 @@ STAmount::getText() const return ret; } - XRPL_ASSERT(mOffset + 43 > 0, "ripple::STAmount::getText : minimum offset"); + XRPL_ASSERT(mOffset + 43 > 0, "xrpl::STAmount::getText : minimum offset"); size_t const pad_prefix = 27; size_t const pad_suffix = 23; @@ -714,8 +713,7 @@ STAmount::getText() const pre_from += pad_prefix; XRPL_ASSERT( - post_to >= post_from, - "ripple::STAmount::getText : first distance check"); + post_to >= post_from, "xrpl::STAmount::getText : first distance check"); pre_from = std::find_if(pre_from, pre_to, [](char c) { return c != '0'; }); @@ -726,7 +724,7 @@ STAmount::getText() const XRPL_ASSERT( post_to >= post_from, - "ripple::STAmount::getText : second distance check"); + "xrpl::STAmount::getText : second distance check"); post_to = std::find_if( std::make_reverse_iterator(post_to), @@ -762,7 +760,7 @@ STAmount::add(Serializer& s) const { if (native()) { - XRPL_ASSERT(mOffset == 0, "ripple::STAmount::add : zero offset"); + XRPL_ASSERT(mOffset == 0, "xrpl::STAmount::add : zero offset"); if (!mIsNegative) s.add64(mValue | cPositive); @@ -937,13 +935,13 @@ STAmount::canonicalize() XRPL_ASSERT( (mValue == 0) || ((mValue >= cMinValue) && (mValue <= cMaxValue)), - "ripple::STAmount::canonicalize : value inside range"); + "xrpl::STAmount::canonicalize : value inside range"); XRPL_ASSERT( (mValue == 0) || ((mOffset >= cMinOffset) && (mOffset <= cMaxOffset)), - "ripple::STAmount::canonicalize : offset inside range"); + "xrpl::STAmount::canonicalize : offset inside range"); XRPL_ASSERT( (mValue != 0) || (mOffset != -100), - "ripple::STAmount::canonicalize : value or offset set"); + "xrpl::STAmount::canonicalize : value or offset set"); } void @@ -1748,4 +1746,4 @@ divRoundStrict( return divRoundImpl(num, den, asset, roundUp); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STArray.cpp b/src/libxrpl/protocol/STArray.cpp index 4d60e6f5ce..de1e6905c6 100644 --- a/src/libxrpl/protocol/STArray.cpp +++ b/src/libxrpl/protocol/STArray.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { STArray::STArray(STArray&& other) : STBase(other.getFName()), v_(std::move(other.v_)) @@ -180,4 +180,4 @@ STArray::sort(bool (*compare)(STObject const&, STObject const&)) std::sort(v_.begin(), v_.end(), compare); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STBase.cpp b/src/libxrpl/protocol/STBase.cpp index 0cbe575a2a..d3faf090eb 100644 --- a/src/libxrpl/protocol/STBase.cpp +++ b/src/libxrpl/protocol/STBase.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { STBase::STBase() : fName(&sfGeneric) { @@ -17,7 +17,7 @@ STBase::STBase() : fName(&sfGeneric) STBase::STBase(SField const& n) : fName(&n) { - XRPL_ASSERT(fName, "ripple::STBase::STBase : field is set"); + XRPL_ASSERT(fName, "xrpl::STBase::STBase : field is set"); } STBase& @@ -94,7 +94,7 @@ STBase::add(Serializer& s) const { // Should never be called // LCOV_EXCL_START - UNREACHABLE("ripple::STBase::add : not implemented"); + UNREACHABLE("xrpl::STBase::add : not implemented"); // LCOV_EXCL_STOP } @@ -103,7 +103,7 @@ STBase::isEquivalent(STBase const& t) const { XRPL_ASSERT( getSType() == STI_NOTPRESENT, - "ripple::STBase::isEquivalent : type not present"); + "xrpl::STBase::isEquivalent : type not present"); return t.getSType() == STI_NOTPRESENT; } @@ -117,7 +117,7 @@ void STBase::setFName(SField const& n) { fName = &n; - XRPL_ASSERT(fName, "ripple::STBase::setFName : field is set"); + XRPL_ASSERT(fName, "xrpl::STBase::setFName : field is set"); } SField const& @@ -130,7 +130,7 @@ void STBase::addFieldID(Serializer& s) const { XRPL_ASSERT( - fName->isBinary(), "ripple::STBase::addFieldID : field is binary"); + fName->isBinary(), "xrpl::STBase::addFieldID : field is binary"); s.addFieldID(fName->fieldType, fName->fieldValue); } @@ -142,4 +142,4 @@ operator<<(std::ostream& out, STBase const& t) return out << t.getFullText(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STBlob.cpp b/src/libxrpl/protocol/STBlob.cpp index 5b46f941de..65670a6a9f 100644 --- a/src/libxrpl/protocol/STBlob.cpp +++ b/src/libxrpl/protocol/STBlob.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { STBlob::STBlob(SerialIter& st, SField const& name) : STBase(name), value_(st.getVLBuffer()) @@ -43,11 +43,11 @@ STBlob::getText() const void STBlob::add(Serializer& s) const { - XRPL_ASSERT(getFName().isBinary(), "ripple::STBlob::add : field is binary"); + XRPL_ASSERT(getFName().isBinary(), "xrpl::STBlob::add : field is binary"); XRPL_ASSERT( (getFName().fieldType == STI_VL) || (getFName().fieldType == STI_ACCOUNT), - "ripple::STBlob::add : valid field type"); + "xrpl::STBlob::add : valid field type"); s.addVL(value_.data(), value_.size()); } @@ -64,4 +64,4 @@ STBlob::isDefault() const return value_.empty(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STCurrency.cpp b/src/libxrpl/protocol/STCurrency.cpp index 3b30e1b757..d4c10b48d3 100644 --- a/src/libxrpl/protocol/STCurrency.cpp +++ b/src/libxrpl/protocol/STCurrency.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { STCurrency::STCurrency(SField const& name) : STBase{name} { @@ -102,4 +102,4 @@ currencyFromJson(SField const& name, Json::Value const& v) return STCurrency{name, currency}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STInteger.cpp b/src/libxrpl/protocol/STInteger.cpp index c71e70e1b2..e701fc4203 100644 --- a/src/libxrpl/protocol/STInteger.cpp +++ b/src/libxrpl/protocol/STInteger.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { template <> STInteger::STInteger(SerialIter& sit, SField const& name) @@ -210,14 +210,14 @@ STUInt64::getJson(JsonOptions) const auto convertToString = [](uint64_t const value, int const base) { XRPL_ASSERT( base == 10 || base == 16, - "ripple::STUInt64::getJson : base 10 or 16"); + "xrpl::STUInt64::getJson : base 10 or 16"); std::string str( base == 10 ? 20 : 16, 0); // Allocate space depending on base auto ret = std::to_chars(str.data(), str.data() + str.size(), value, base); XRPL_ASSERT( ret.ec == std::errc(), - "ripple::STUInt64::getJson : to_chars succeeded"); + "xrpl::STUInt64::getJson : to_chars succeeded"); str.resize(std::distance(str.data(), ret.ptr)); return str; }; @@ -259,4 +259,4 @@ STInt32::getJson(JsonOptions) const return value_; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STIssue.cpp b/src/libxrpl/protocol/STIssue.cpp index 346f73d5ae..213c8b7962 100644 --- a/src/libxrpl/protocol/STIssue.cpp +++ b/src/libxrpl/protocol/STIssue.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { STIssue::STIssue(SField const& name) : STBase{name} { @@ -139,4 +139,4 @@ issueFromJson(SField const& name, Json::Value const& v) return STIssue{name, assetFromJson(v)}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STLedgerEntry.cpp b/src/libxrpl/protocol/STLedgerEntry.cpp index 5665bc1508..8ee3669a24 100644 --- a/src/libxrpl/protocol/STLedgerEntry.cpp +++ b/src/libxrpl/protocol/STLedgerEntry.cpp @@ -26,7 +26,7 @@ #include #include -namespace ripple { +namespace xrpl { STLedgerEntry::STLedgerEntry(Keylet const& k) : STObject(sfLedgerEntry), key_(k.key), type_(k.type) @@ -157,7 +157,7 @@ STLedgerEntry::thread( // this transaction is already threaded XRPL_ASSERT( getFieldU32(sfPreviousTxnLgrSeq) == ledgerSeq, - "ripple::STLedgerEntry::thread : ledger sequence match"); + "xrpl::STLedgerEntry::thread : ledger sequence match"); return false; } @@ -168,4 +168,4 @@ STLedgerEntry::thread( return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STNumber.cpp b/src/libxrpl/protocol/STNumber.cpp index c353f6b795..f85bb48e0a 100644 --- a/src/libxrpl/protocol/STNumber.cpp +++ b/src/libxrpl/protocol/STNumber.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { STNumber::STNumber(SField const& field, Number const& value) : STBase(field), value_(value) @@ -45,11 +45,10 @@ STNumber::getText() const void STNumber::add(Serializer& s) const { - XRPL_ASSERT( - getFName().isBinary(), "ripple::STNumber::add : field is binary"); + XRPL_ASSERT(getFName().isBinary(), "xrpl::STNumber::add : field is binary"); XRPL_ASSERT( getFName().fieldType == getSType(), - "ripple::STNumber::add : field type match"); + "xrpl::STNumber::add : field type match"); s.add64(value_.mantissa()); s.add32(value_.exponent()); } @@ -83,7 +82,7 @@ STNumber::isEquivalent(STBase const& t) const { XRPL_ASSERT( t.getSType() == this->getSType(), - "ripple::STNumber::isEquivalent : field type match"); + "xrpl::STNumber::isEquivalent : field type match"); STNumber const& v = dynamic_cast(t); return value_ == v; } @@ -196,4 +195,4 @@ numberFromJson(SField const& field, Json::Value const& value) return STNumber{field, Number{mantissa, parts.exponent}}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STObject.cpp b/src/libxrpl/protocol/STObject.cpp index 1c39eb9108..6007753ed1 100644 --- a/src/libxrpl/protocol/STObject.cpp +++ b/src/libxrpl/protocol/STObject.cpp @@ -39,7 +39,7 @@ #include #include -namespace ripple { +namespace xrpl { STObject::STObject(STObject&& other) : STBase(other.getFName()), v_(std::move(other.v_)), mType(other.mType) @@ -904,7 +904,7 @@ STObject::add(Serializer& s, WhichFields whichFields) const XRPL_ASSERT( (sType != STI_OBJECT) || (field->getFName().fieldType == STI_OBJECT), - "ripple::STObject::add : valid field type"); + "xrpl::STObject::add : valid field type"); field->addFieldID(s); field->add(s); if (sType == STI_ARRAY || sType == STI_OBJECT) @@ -937,4 +937,4 @@ STObject::getSortedFields(STObject const& objToSort, WhichFields whichFields) return sf; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STParsedJSON.cpp b/src/libxrpl/protocol/STParsedJSON.cpp index 8443f92f75..34c8b70e45 100644 --- a/src/libxrpl/protocol/STParsedJSON.cpp +++ b/src/libxrpl/protocol/STParsedJSON.cpp @@ -41,7 +41,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace STParsedJSONDetail { template @@ -1190,4 +1190,4 @@ STParsedJSONObject::STParsedJSONObject( object = parseObject(name, json, sfGeneric, 0, error); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STPathSet.cpp b/src/libxrpl/protocol/STPathSet.cpp index 3132c81cc6..631fd51d8a 100644 --- a/src/libxrpl/protocol/STPathSet.cpp +++ b/src/libxrpl/protocol/STPathSet.cpp @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { std::size_t STPathElement::get_hash(STPathElement const& element) @@ -201,10 +201,10 @@ void STPathSet::add(Serializer& s) const { XRPL_ASSERT( - getFName().isBinary(), "ripple::STPathSet::add : field is binary"); + getFName().isBinary(), "xrpl::STPathSet::add : field is binary"); XRPL_ASSERT( getFName().fieldType == STI_PATHSET, - "ripple::STPathSet::add : valid field type"); + "xrpl::STPathSet::add : valid field type"); bool first = true; for (auto const& spPath : value) @@ -234,4 +234,4 @@ STPathSet::add(Serializer& s) const s.add8(STPathElement::typeNone); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STTx.cpp b/src/libxrpl/protocol/STTx.cpp index d3b3ab4a88..6640468bd4 100644 --- a/src/libxrpl/protocol/STTx.cpp +++ b/src/libxrpl/protocol/STTx.cpp @@ -51,7 +51,7 @@ #include #include -namespace ripple { +namespace xrpl { static auto getTxFormat(TxType type) @@ -150,7 +150,7 @@ STTx::getMentionedAccounts() const { XRPL_ASSERT( !sacc->isDefault(), - "ripple::STTx::getMentionedAccounts : account is set"); + "xrpl::STTx::getMentionedAccounts : account is set"); if (!sacc->isDefault()) list.insert(sacc->value()); } @@ -222,7 +222,7 @@ STTx::sign( { auto const data = getSigningData(*this); - auto const sig = ripple::sign(publicKey, secretKey, makeSlice(data)); + auto const sig = xrpl::sign(publicKey, secretKey, makeSlice(data)); if (signatureTarget) { @@ -375,7 +375,7 @@ STTx::getMetaSQL( std::string rTxn = sqlBlobLiteral(rawTxn.peekData()); auto format = TxFormats::getInstance().findByType(tx_type_); - XRPL_ASSERT(format, "ripple::STTx::getMetaSQL : non-null type format"); + XRPL_ASSERT(format, "xrpl::STTx::getMetaSQL : non-null type format"); return str( boost::format(bfTrans) % to_string(getTransactionID()) % @@ -819,4 +819,4 @@ isPseudoTx(STObject const& tx) return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STValidation.cpp b/src/libxrpl/protocol/STValidation.cpp index 3c89f31896..f6f89d43e9 100644 --- a/src/libxrpl/protocol/STValidation.cpp +++ b/src/libxrpl/protocol/STValidation.cpp @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { STBase* STValidation::copy(std::size_t n, void* buf) const @@ -101,7 +101,7 @@ STValidation::isValid() const noexcept { XRPL_ASSERT( publicKeyType(getSignerPublic()) == KeyType::secp256k1, - "ripple::STValidation::isValid : valid key type"); + "xrpl::STValidation::isValid : valid key type"); valid_ = verifyDigest( getSignerPublic(), @@ -133,4 +133,4 @@ STValidation::getSerialized() const return s.peekData(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STVar.cpp b/src/libxrpl/protocol/STVar.cpp index 2b0e59b4c3..e0df5d51a9 100644 --- a/src/libxrpl/protocol/STVar.cpp +++ b/src/libxrpl/protocol/STVar.cpp @@ -22,7 +22,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { defaultObject_t defaultObject; @@ -109,7 +109,7 @@ STVar::STVar(SerializedTypeID id, SField const& name) { XRPL_ASSERT( (id == STI_NOTPRESENT) || (id == name.fieldType), - "ripple::detail::STVar::STVar(SerializedTypeID) : valid type input"); + "xrpl::detail::STVar::STVar(SerializedTypeID) : valid type input"); constructST(id, 0, name); } @@ -225,4 +225,4 @@ STVar::constructST(SerializedTypeID id, int depth, Args&&... args) } } // namespace detail -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STVector256.cpp b/src/libxrpl/protocol/STVector256.cpp index ba7cf3252c..17b4895b62 100644 --- a/src/libxrpl/protocol/STVector256.cpp +++ b/src/libxrpl/protocol/STVector256.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { STVector256::STVector256(SerialIter& sit, SField const& name) : STBase(name) { @@ -59,10 +59,10 @@ void STVector256::add(Serializer& s) const { XRPL_ASSERT( - getFName().isBinary(), "ripple::STVector256::add : field is binary"); + getFName().isBinary(), "xrpl::STVector256::add : field is binary"); XRPL_ASSERT( getFName().fieldType == STI_VECTOR256, - "ripple::STVector256::add : valid field type"); + "xrpl::STVector256::add : valid field type"); s.addVL(mValue.begin(), mValue.end(), mValue.size() * (256 / 8)); } @@ -84,4 +84,4 @@ STVector256::getJson(JsonOptions) const return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/STXChainBridge.cpp b/src/libxrpl/protocol/STXChainBridge.cpp index aa10a87bbc..065b87558f 100644 --- a/src/libxrpl/protocol/STXChainBridge.cpp +++ b/src/libxrpl/protocol/STXChainBridge.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { STXChainBridge::STXChainBridge() : STBase{sfXChainBridge} { @@ -66,7 +66,7 @@ STXChainBridge::STXChainBridge(SField const& name, Json::Value const& v) auto checkExtra = [](Json::Value const& v) { static auto const jbridge = - ripple::STXChainBridge().getJson(ripple::JsonOptions::none); + xrpl::STXChainBridge().getJson(xrpl::JsonOptions::none); for (auto it = v.begin(); it != v.end(); ++it) { std::string const name = it.memberName(); @@ -207,4 +207,4 @@ STXChainBridge::move(std::size_t n, void* buf) { return emplace(n, buf, std::move(*this)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/SecretKey.cpp b/src/libxrpl/protocol/SecretKey.cpp index d4a958c600..88404a88a5 100644 --- a/src/libxrpl/protocol/SecretKey.cpp +++ b/src/libxrpl/protocol/SecretKey.cpp @@ -26,7 +26,7 @@ #include #include -namespace ripple { +namespace xrpl { SecretKey::~SecretKey() { @@ -381,4 +381,4 @@ parseBase58(TokenType type, std::string const& s) return SecretKey(makeSlice(result)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Seed.cpp b/src/libxrpl/protocol/Seed.cpp index 9c41a534b9..18e89ef6ca 100644 --- a/src/libxrpl/protocol/Seed.cpp +++ b/src/libxrpl/protocol/Seed.cpp @@ -20,7 +20,7 @@ #include #include -namespace ripple { +namespace xrpl { Seed::~Seed() { @@ -124,4 +124,4 @@ seedAs1751(Seed const& seed) return encodedKey; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Serializer.cpp b/src/libxrpl/protocol/Serializer.cpp index 7fbec19bd2..e6c1e6967f 100644 --- a/src/libxrpl/protocol/Serializer.cpp +++ b/src/libxrpl/protocol/Serializer.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { int Serializer::add16(std::uint16_t i) @@ -109,7 +109,7 @@ Serializer::addFieldID(int type, int name) int ret = mData.size(); XRPL_ASSERT( (type > 0) && (type < 256) && (name > 0) && (name < 256), - "ripple::Serializer::addFieldID : inputs inside range"); + "xrpl::Serializer::addFieldID : inputs inside range"); if (type < 16) { @@ -181,7 +181,7 @@ Serializer::addVL(Blob const& vector) XRPL_ASSERT( mData.size() == (ret + vector.size() + encodeLengthLength(vector.size())), - "ripple::Serializer::addVL : size matches expected"); + "xrpl::Serializer::addVL : size matches expected"); return ret; } @@ -486,7 +486,7 @@ SerialIter::getVLDataLength() else { XRPL_ASSERT( - lenLen == 3, "ripple::SerialIter::getVLDataLength : lenLen is 3"); + lenLen == 3, "xrpl::SerialIter::getVLDataLength : lenLen is 3"); int b2 = get8(); int b3 = get8(); datLen = Serializer::decodeVLLength(b1, b2, b3); @@ -519,4 +519,4 @@ SerialIter::getVLBuffer() return getRawHelper(getVLDataLength()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/Sign.cpp b/src/libxrpl/protocol/Sign.cpp index 3a6b52ac84..9edd2bbfa4 100644 --- a/src/libxrpl/protocol/Sign.cpp +++ b/src/libxrpl/protocol/Sign.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { void sign( @@ -90,4 +90,4 @@ startMultiSigningData(STObject const& obj) return s; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/TER.cpp b/src/libxrpl/protocol/TER.cpp index 8cdcced347..6871cf5700 100644 --- a/src/libxrpl/protocol/TER.cpp +++ b/src/libxrpl/protocol/TER.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { std::unordered_map< TERUnderlyingType, @@ -281,4 +281,4 @@ transCode(std::string const& token) return TER::fromInt(r->second); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/TxFormats.cpp b/src/libxrpl/protocol/TxFormats.cpp index 0b42f8cefb..12f92615cd 100644 --- a/src/libxrpl/protocol/TxFormats.cpp +++ b/src/libxrpl/protocol/TxFormats.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { TxFormats::TxFormats() { @@ -55,4 +55,4 @@ TxFormats::getInstance() return instance; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/TxMeta.cpp b/src/libxrpl/protocol/TxMeta.cpp index ebc1d87b14..f0077c7f92 100644 --- a/src/libxrpl/protocol/TxMeta.cpp +++ b/src/libxrpl/protocol/TxMeta.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj) : transactionID_(txid) @@ -31,8 +31,7 @@ TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj) auto affectedNodes = dynamic_cast(obj.peekAtPField(sfAffectedNodes)); XRPL_ASSERT( - affectedNodes, - "ripple::TxMeta::TxMeta(STObject) : type cast succeeded"); + affectedNodes, "xrpl::TxMeta::TxMeta(STObject) : type cast succeeded"); if (affectedNodes) nodes_ = *affectedNodes; @@ -84,7 +83,7 @@ TxMeta::setAffectedNode( XRPL_ASSERT( obj.getFName() == type, - "ripple::TxMeta::setAffectedNode : field type match"); + "xrpl::TxMeta::setAffectedNode : field type match"); obj.setFieldH256(sfLedgerIndex, node); obj.setFieldU16(sfLedgerEntryType, nodeType); } @@ -108,7 +107,7 @@ TxMeta::getAffectedAccounts() const dynamic_cast(&node.peekAtIndex(index)); XRPL_ASSERT( inner, - "ripple::getAffectedAccounts : STObject type cast succeeded"); + "xrpl::getAffectedAccounts : STObject type cast succeeded"); if (inner) { for (auto const& field : *inner) @@ -117,7 +116,7 @@ TxMeta::getAffectedAccounts() const { XRPL_ASSERT( !sa->isDefault(), - "ripple::getAffectedAccounts : account is set"); + "xrpl::getAffectedAccounts : account is set"); if (!sa->isDefault()) list.insert(sa->value()); } @@ -130,7 +129,7 @@ TxMeta::getAffectedAccounts() const auto lim = dynamic_cast(&field); XRPL_ASSERT( lim, - "ripple::getAffectedAccounts : STAmount type cast " + "xrpl::getAffectedAccounts : STAmount type cast " "succeeded"); if (lim != nullptr) @@ -175,7 +174,7 @@ TxMeta::getAffectedNode(SLE::ref node, SField const& type) XRPL_ASSERT( obj.getFName() == type, - "ripple::TxMeta::getAffectedNode(SLE::ref) : field type match"); + "xrpl::TxMeta::getAffectedNode(SLE::ref) : field type match"); obj.setFieldH256(sfLedgerIndex, index); obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType)); @@ -191,7 +190,7 @@ TxMeta::getAffectedNode(uint256 const& node) return n; } // LCOV_EXCL_START - UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found"); + UNREACHABLE("xrpl::TxMeta::getAffectedNode(uint256) : node not found"); Throw("Affected node not found"); return *(nodes_.begin()); // Silence compiler warning. // LCOV_EXCL_STOP @@ -201,7 +200,7 @@ STObject TxMeta::getAsObject() const { STObject metaData(sfTransactionMetaData); - XRPL_ASSERT(result_ != 255, "ripple::TxMeta::getAsObject : result_ is set"); + XRPL_ASSERT(result_ != 255, "xrpl::TxMeta::getAsObject : result_ is set"); metaData.setFieldU8(sfTransactionResult, result_); metaData.setFieldU32(sfTransactionIndex, index_); metaData.emplace_back(nodes_); @@ -221,7 +220,7 @@ TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index) index_ = index; XRPL_ASSERT( (result_ == 0) || ((result_ > 100) && (result_ <= 255)), - "ripple::TxMeta::addRaw : valid TER input"); + "xrpl::TxMeta::addRaw : valid TER input"); nodes_.sort([](STObject const& o1, STObject const& o2) { return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex); @@ -230,4 +229,4 @@ TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index) getAsObject().add(s); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/UintTypes.cpp b/src/libxrpl/protocol/UintTypes.cpp index ca7f09b5f5..6c799397ee 100644 --- a/src/libxrpl/protocol/UintTypes.cpp +++ b/src/libxrpl/protocol/UintTypes.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { // For details on the protocol-level serialization please visit // https://xrpl.org/serialization.html#currency-codes @@ -117,4 +117,4 @@ badCurrency() return currency; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/XChainAttestations.cpp b/src/libxrpl/protocol/XChainAttestations.cpp index da5f2d4ccb..89771b63b0 100644 --- a/src/libxrpl/protocol/XChainAttestations.cpp +++ b/src/libxrpl/protocol/XChainAttestations.cpp @@ -22,7 +22,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Attestations { AttestationBase::AttestationBase( @@ -83,7 +83,7 @@ bool AttestationBase::verify(STXChainBridge const& bridge) const { std::vector msg = message(bridge); - return ripple::verify(publicKey, makeSlice(msg), signature); + return xrpl::verify(publicKey, makeSlice(msg), signature); } AttestationBase::AttestationBase(STObject const& o) @@ -742,4 +742,4 @@ XChainAttestationsBase::toSTArray() const template class XChainAttestationsBase; template class XChainAttestationsBase; -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/digest.cpp b/src/libxrpl/protocol/digest.cpp index ca7bab7372..dd4ecd7688 100644 --- a/src/libxrpl/protocol/digest.cpp +++ b/src/libxrpl/protocol/digest.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { openssl_ripemd160_hasher::openssl_ripemd160_hasher() { @@ -86,4 +86,4 @@ openssl_sha256_hasher::operator result_type() noexcept return digest; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/protocol/tokens.cpp b/src/libxrpl/protocol/tokens.cpp index a9a9ddb110..d4253a2df1 100644 --- a/src/libxrpl/protocol/tokens.cpp +++ b/src/libxrpl/protocol/tokens.cpp @@ -119,7 +119,7 @@ of another base), and doing the multi-precision computations with larger coefficients sizes greatly speeds up the multi-precision computations. */ -namespace ripple { +namespace xrpl { static constexpr char const* alphabetForward = "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"; @@ -235,7 +235,7 @@ encodeBase58( carry /= 58; } XRPL_ASSERT( - carry == 0, "ripple::b58_ref::detail::encodeBase58 : zero carry"); + carry == 0, "xrpl::b58_ref::detail::encodeBase58 : zero carry"); pbegin++; } @@ -286,7 +286,7 @@ decodeBase58(std::string const& s) carry /= 256; } XRPL_ASSERT( - carry == 0, "ripple::b58_ref::detail::decodeBase58 : zero carry"); + carry == 0, "xrpl::b58_ref::detail::decodeBase58 : zero carry"); ++psz; --remain; } @@ -430,7 +430,7 @@ b256_to_b58_be(std::span input, std::span out) while (cur_2_64_end > 0) { base_58_10_coeff[num_58_10_coeffs] = - ripple::b58_fast::detail::inplace_bigint_div_rem( + xrpl::b58_fast::detail::inplace_bigint_div_rem( base_2_64_coeff.subspan(0, cur_2_64_end), B_58_10); num_58_10_coeffs += 1; if (base_2_64_coeff[cur_2_64_end - 1] == 0) @@ -442,7 +442,7 @@ b256_to_b58_be(std::span input, std::span out) // Translate the result into the alphabet // Put all the zeros at the beginning, then all the values from the output std::fill( - out.begin(), out.begin() + input_zeros, ::ripple::alphabetForward[0]); + out.begin(), out.begin() + input_zeros, ::xrpl::alphabetForward[0]); // iterate through the base 58^10 coeff // convert to base 58 big endian then @@ -461,7 +461,7 @@ b256_to_b58_be(std::span input, std::span out) return Unexpected(TokenCodecErrc::inputTooLarge); } std::array const b58_be = - ripple::b58_fast::detail::b58_10_to_b58_be(base_58_10_coeff[i]); + xrpl::b58_fast::detail::b58_10_to_b58_be(base_58_10_coeff[i]); std::size_t to_skip = 0; std::span b58_be_s{b58_be.data(), b58_be.size()}; if (skip_zeros) @@ -475,7 +475,7 @@ b256_to_b58_be(std::span input, std::span out) } for (auto b58_coeff : b58_be_s.subspan(to_skip)) { - out[out_index] = ::ripple::alphabetForward[b58_coeff]; + out[out_index] = ::xrpl::alphabetForward[b58_coeff]; out_index += 1; } } @@ -504,7 +504,7 @@ b58_to_b256_be(std::string_view input, std::span out) std::size_t count = 0; for (auto const& c : col) { - if (c != ::ripple::alphabetForward[0]) + if (c != ::xrpl::alphabetForward[0]) { return count; } @@ -520,15 +520,15 @@ b58_to_b256_be(std::string_view input, std::span out) // log(2^(38*8),58^10)) ~= 5.18. So 6 coeff are enough std::array b_58_10_coeff{}; auto [num_full_coeffs, partial_coeff_len] = - ripple::b58_fast::detail::div_rem(input.size(), 10); + xrpl::b58_fast::detail::div_rem(input.size(), 10); auto const num_partial_coeffs = partial_coeff_len ? 1 : 0; auto const num_b_58_10_coeffs = num_full_coeffs + num_partial_coeffs; XRPL_ASSERT( num_b_58_10_coeffs <= b_58_10_coeff.size(), - "ripple::b58_fast::detail::b58_to_b256_be : maximum coeff"); + "xrpl::b58_fast::detail::b58_to_b256_be : maximum coeff"); for (unsigned char c : input.substr(0, partial_coeff_len)) { - auto cur_val = ::ripple::alphabetReverse[c]; + auto cur_val = ::xrpl::alphabetReverse[c]; if (cur_val < 0) { return Unexpected(TokenCodecErrc::invalidEncodingChar); @@ -541,7 +541,7 @@ b58_to_b256_be(std::string_view input, std::span out) for (int j = 0; j < num_full_coeffs; ++j) { unsigned char c = input[partial_coeff_len + j * 10 + i]; - auto cur_val = ::ripple::alphabetReverse[c]; + auto cur_val = ::xrpl::alphabetReverse[c]; if (cur_val < 0) { return Unexpected(TokenCodecErrc::invalidEncodingChar); @@ -562,7 +562,7 @@ b58_to_b256_be(std::string_view input, std::span out) std::uint64_t const c = b_58_10_coeff[i]; { - auto code = ripple::b58_fast::detail::inplace_bigint_mul( + auto code = xrpl::b58_fast::detail::inplace_bigint_mul( std::span(&result[0], cur_result_size + 1), B_58_10); if (code != TokenCodecErrc::success) { @@ -570,7 +570,7 @@ b58_to_b256_be(std::string_view input, std::span out) } } { - auto code = ripple::b58_fast::detail::inplace_bigint_add( + auto code = xrpl::b58_fast::detail::inplace_bigint_add( std::span(&result[0], cur_result_size + 1), c); if (code != TokenCodecErrc::success) { @@ -732,4 +732,4 @@ decodeBase58Token(std::string const& s, TokenType type) } // namespace b58_fast #endif // _MSC_VER -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/resource/Charge.cpp b/src/libxrpl/resource/Charge.cpp index 43901d8985..1d88526b65 100644 --- a/src/libxrpl/resource/Charge.cpp +++ b/src/libxrpl/resource/Charge.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { Charge::Charge(value_type cost, std::string const& label) @@ -59,4 +59,4 @@ Charge::operator*(value_type m) const } } // namespace Resource -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/resource/Consumer.cpp b/src/libxrpl/resource/Consumer.cpp index 8f396c5012..c9d8ea6125 100644 --- a/src/libxrpl/resource/Consumer.cpp +++ b/src/libxrpl/resource/Consumer.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { Consumer::Consumer(Logic& logic, Entry& entry) @@ -97,7 +97,7 @@ Consumer::charge(Charge const& what, std::string const& context) bool Consumer::warn() { - XRPL_ASSERT(m_entry, "ripple::Resource::Consumer::warn : non-null entry"); + XRPL_ASSERT(m_entry, "xrpl::Resource::Consumer::warn : non-null entry"); return m_logic->warn(*m_entry); } @@ -105,7 +105,7 @@ bool Consumer::disconnect(beast::Journal const& j) { XRPL_ASSERT( - m_entry, "ripple::Resource::Consumer::disconnect : non-null entry"); + m_entry, "xrpl::Resource::Consumer::disconnect : non-null entry"); bool const d = m_logic->disconnect(*m_entry); if (d) { @@ -117,15 +117,14 @@ Consumer::disconnect(beast::Journal const& j) int Consumer::balance() { - XRPL_ASSERT( - m_entry, "ripple::Resource::Consumer::balance : non-null entry"); + XRPL_ASSERT(m_entry, "xrpl::Resource::Consumer::balance : non-null entry"); return m_logic->balance(*m_entry); } Entry& Consumer::entry() { - XRPL_ASSERT(m_entry, "ripple::Resource::Consumer::entry : non-null entry"); + XRPL_ASSERT(m_entry, "xrpl::Resource::Consumer::entry : non-null entry"); return *m_entry; } @@ -143,4 +142,4 @@ operator<<(std::ostream& os, Consumer const& v) } } // namespace Resource -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/resource/Fees.cpp b/src/libxrpl/resource/Fees.cpp index f300a70d7c..d5999458b7 100644 --- a/src/libxrpl/resource/Fees.cpp +++ b/src/libxrpl/resource/Fees.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { Charge const feeMalformedRequest(200, "malformed request"); @@ -26,4 +26,4 @@ Charge const feeDrop(6000, "dropped"); // See also Resource::Logic::charge for log level cutoff values } // namespace Resource -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/resource/ResourceManager.cpp b/src/libxrpl/resource/ResourceManager.cpp index 5e647cfce9..8582836611 100644 --- a/src/libxrpl/resource/ResourceManager.cpp +++ b/src/libxrpl/resource/ResourceManager.cpp @@ -22,7 +22,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { class ManagerImp : public Manager @@ -171,4 +171,4 @@ make_Manager( } } // namespace Resource -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/server/JSONRPCUtil.cpp b/src/libxrpl/server/JSONRPCUtil.cpp index 1a804677bd..845781374d 100644 --- a/src/libxrpl/server/JSONRPCUtil.cpp +++ b/src/libxrpl/server/JSONRPCUtil.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { std::string getHTTPHeaderTimestamp() @@ -139,4 +139,4 @@ HTTPReply( output("\r\n"); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/server/Port.cpp b/src/libxrpl/server/Port.cpp index 6c7ec04f6f..03a503e940 100644 --- a/src/libxrpl/server/Port.cpp +++ b/src/libxrpl/server/Port.cpp @@ -21,7 +21,7 @@ #include #include -namespace ripple { +namespace xrpl { bool Port::secure() const @@ -320,4 +320,4 @@ parse_Port(ParsedPort& port, Section const& section, std::ostream& log) port.pmd_options.memLevel = section.value_or("memory_level", 4); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/shamap/SHAMap.cpp b/src/libxrpl/shamap/SHAMap.cpp index ef27d37ed3..7cfa66b1ac 100644 --- a/src/libxrpl/shamap/SHAMap.cpp +++ b/src/libxrpl/shamap/SHAMap.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { [[nodiscard]] intr_ptr::SharedPtr makeTypedLeaf( @@ -85,10 +85,10 @@ SHAMap::dirtyUp( XRPL_ASSERT( (state_ != SHAMapState::Synching) && (state_ != SHAMapState::Immutable), - "ripple::SHAMap::dirtyUp : valid state"); + "xrpl::SHAMap::dirtyUp : valid state"); XRPL_ASSERT( child && (child->cowid() == cowid_), - "ripple::SHAMap::dirtyUp : valid child input"); + "xrpl::SHAMap::dirtyUp : valid child input"); while (!stack.empty()) { @@ -96,10 +96,10 @@ SHAMap::dirtyUp( intr_ptr::dynamic_pointer_cast(stack.top().first); SHAMapNodeID nodeID = stack.top().second; stack.pop(); - XRPL_ASSERT(node, "ripple::SHAMap::dirtyUp : non-null node"); + XRPL_ASSERT(node, "xrpl::SHAMap::dirtyUp : non-null node"); int branch = selectBranch(nodeID, target); - XRPL_ASSERT(branch >= 0, "ripple::SHAMap::dirtyUp : valid branch"); + XRPL_ASSERT(branch >= 0, "xrpl::SHAMap::dirtyUp : valid branch"); node = unshareNode(std::move(node), nodeID); node->setChild(branch, std::move(child)); @@ -113,7 +113,7 @@ SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const { XRPL_ASSERT( stack == nullptr || stack->empty(), - "ripple::SHAMap::walkTowardsKey : empty stack input"); + "xrpl::SHAMap::walkTowardsKey : empty stack input"); auto inNode = root_; SHAMapNodeID nodeID; @@ -149,7 +149,7 @@ SHAMap::findKey(uint256 const& id) const intr_ptr::SharedPtr SHAMap::fetchNodeFromDB(SHAMapHash const& hash) const { - XRPL_ASSERT(backed_, "ripple::SHAMap::fetchNodeFromDB : is backed"); + XRPL_ASSERT(backed_, "xrpl::SHAMap::fetchNodeFromDB : is backed"); auto obj = f_.db().fetchNodeObject(hash.as_uint256(), ledgerSeq_); return finishFetch(hash, obj); } @@ -159,7 +159,7 @@ SHAMap::finishFetch( SHAMapHash const& hash, std::shared_ptr const& object) const { - XRPL_ASSERT(backed_, "ripple::SHAMap::finishFetch : is backed"); + XRPL_ASSERT(backed_, "xrpl::SHAMap::finishFetch : is backed"); try { @@ -344,13 +344,13 @@ SHAMap::descend( SHAMapSyncFilter* filter) const { XRPL_ASSERT( - parent->isInner(), "ripple::SHAMap::descend : valid parent input"); + parent->isInner(), "xrpl::SHAMap::descend : valid parent input"); XRPL_ASSERT( (branch >= 0) && (branch < branchFactor), - "ripple::SHAMap::descend : valid branch input"); + "xrpl::SHAMap::descend : valid branch input"); XRPL_ASSERT( !parent->isEmptyBranch(branch), - "ripple::SHAMap::descend : parent branch is non-empty"); + "xrpl::SHAMap::descend : parent branch is non-empty"); SHAMapTreeNode* child = parent->getChildPointer(branch); @@ -420,13 +420,13 @@ SHAMap::unshareNode(intr_ptr::SharedPtr node, SHAMapNodeID const& nodeID) // make sure the node is suitable for the intended operation (copy on write) XRPL_ASSERT( node->cowid() <= cowid_, - "ripple::SHAMap::unshareNode : node valid for cowid"); + "xrpl::SHAMap::unshareNode : node valid for cowid"); if (node->cowid() != cowid_) { // have a CoW XRPL_ASSERT( state_ != SHAMapState::Immutable, - "ripple::SHAMap::unshareNode : not immutable"); + "xrpl::SHAMap::unshareNode : not immutable"); node = intr_ptr::static_pointer_cast(node->clone(cowid_)); if (nodeID.isRoot()) root_ = node; @@ -460,8 +460,7 @@ SHAMap::belowHelper( { node.adopt(descendThrow(inner.get(), i)); XRPL_ASSERT( - !stack.empty(), - "ripple::SHAMap::belowHelper : non-empty stack"); + !stack.empty(), "xrpl::SHAMap::belowHelper : non-empty stack"); if (node->isLeaf()) { auto n = intr_ptr::static_pointer_cast(node); @@ -526,7 +525,7 @@ SHAMap::onlyBelow(SHAMapTreeNode* node) const if (!nextNode) { // LCOV_EXCL_START - UNREACHABLE("ripple::SHAMap::onlyBelow : no next node"); + UNREACHABLE("xrpl::SHAMap::onlyBelow : no next node"); return no_item; // LCOV_EXCL_STOP } @@ -539,7 +538,7 @@ SHAMap::onlyBelow(SHAMapTreeNode* node) const auto const leaf = static_cast(node); XRPL_ASSERT( leaf->peekItem() || (leaf == root_.get()), - "ripple::SHAMap::onlyBelow : valid inner node"); + "xrpl::SHAMap::onlyBelow : valid inner node"); return leaf->peekItem(); } @@ -547,7 +546,7 @@ SHAMapLeafNode const* SHAMap::peekFirstItem(SharedPtrNodeStack& stack) const { XRPL_ASSERT( - stack.empty(), "ripple::SHAMap::peekFirstItem : empty stack input"); + stack.empty(), "xrpl::SHAMap::peekFirstItem : empty stack input"); SHAMapLeafNode* node = firstBelow(root_, stack); if (!node) { @@ -562,17 +561,17 @@ SHAMapLeafNode const* SHAMap::peekNextItem(uint256 const& id, SharedPtrNodeStack& stack) const { XRPL_ASSERT( - !stack.empty(), "ripple::SHAMap::peekNextItem : non-empty stack input"); + !stack.empty(), "xrpl::SHAMap::peekNextItem : non-empty stack input"); XRPL_ASSERT( stack.top().first->isLeaf(), - "ripple::SHAMap::peekNextItem : stack starts with leaf"); + "xrpl::SHAMap::peekNextItem : stack starts with leaf"); stack.pop(); while (!stack.empty()) { auto [node, nodeID] = stack.top(); XRPL_ASSERT( !node->isLeaf(), - "ripple::SHAMap::peekNextItem : another node is not leaf"); + "xrpl::SHAMap::peekNextItem : another node is not leaf"); auto inner = intr_ptr::static_pointer_cast(node); for (auto i = selectBranch(nodeID, id) + 1; i < branchFactor; ++i) { @@ -584,7 +583,7 @@ SHAMap::peekNextItem(uint256 const& id, SharedPtrNodeStack& stack) const Throw(type_, id); XRPL_ASSERT( leaf->isLeaf(), - "ripple::SHAMap::peekNextItem : leaf is valid"); + "xrpl::SHAMap::peekNextItem : leaf is valid"); return leaf; } } @@ -704,7 +703,7 @@ SHAMap::delItem(uint256 const& id) // delete the item with this ID XRPL_ASSERT( state_ != SHAMapState::Immutable, - "ripple::SHAMap::delItem : not immutable"); + "xrpl::SHAMap::delItem : not immutable"); SharedPtrNodeStack stack; walkTowardsKey(id, &stack); @@ -787,10 +786,10 @@ SHAMap::addGiveItem( { XRPL_ASSERT( state_ != SHAMapState::Immutable, - "ripple::SHAMap::addGiveItem : not immutable"); + "xrpl::SHAMap::addGiveItem : not immutable"); XRPL_ASSERT( type != SHAMapNodeType::tnINNER, - "ripple::SHAMap::addGiveItem : valid type input"); + "xrpl::SHAMap::addGiveItem : valid type input"); // add the specified item, does not update uint256 tag = item->key(); @@ -818,7 +817,7 @@ SHAMap::addGiveItem( int branch = selectBranch(nodeID, tag); XRPL_ASSERT( inner->isEmptyBranch(branch), - "ripple::SHAMap::addGiveItem : inner branch is empty"); + "xrpl::SHAMap::addGiveItem : inner branch is empty"); inner->setChild(branch, makeTypedLeaf(type, std::move(item), cowid_)); } else @@ -829,7 +828,7 @@ SHAMap::addGiveItem( auto otherItem = leaf->peekItem(); XRPL_ASSERT( otherItem && (tag != otherItem->key()), - "ripple::SHAMap::addGiveItem : non-null item"); + "xrpl::SHAMap::addGiveItem : non-null item"); node = intr_ptr::make_shared(node->cowid()); @@ -848,7 +847,7 @@ SHAMap::addGiveItem( // we can add the two leaf nodes here XRPL_ASSERT( - node->isInner(), "ripple::SHAMap::addGiveItem : node is inner"); + node->isInner(), "xrpl::SHAMap::addGiveItem : node is inner"); auto inner = static_cast(node.get()); inner->setChild(b1, makeTypedLeaf(type, std::move(item), cowid_)); @@ -889,7 +888,7 @@ SHAMap::updateGiveItem( XRPL_ASSERT( state_ != SHAMapState::Immutable, - "ripple::SHAMap::updateGiveItem : not immutable"); + "xrpl::SHAMap::updateGiveItem : not immutable"); SharedPtrNodeStack stack; walkTowardsKey(tag, &stack); @@ -905,7 +904,7 @@ SHAMap::updateGiveItem( if (!node || (node->peekItem()->key() != tag)) { // LCOV_EXCL_START - UNREACHABLE("ripple::SHAMap::updateGiveItem : invalid node"); + UNREACHABLE("xrpl::SHAMap::updateGiveItem : invalid node"); return false; // LCOV_EXCL_STOP } @@ -953,7 +952,7 @@ SHAMap::fetchRoot(SHAMapHash const& hash, SHAMapSyncFilter* filter) root_ = newRoot; XRPL_ASSERT( root_->getHash() == hash, - "ripple::SHAMap::fetchRoot : root hash do match"); + "xrpl::SHAMap::fetchRoot : root hash do match"); return true; } @@ -977,8 +976,8 @@ SHAMap::writeNode(NodeObjectType t, intr_ptr::SharedPtr node) const { XRPL_ASSERT( - node->cowid() == 0, "ripple::SHAMap::writeNode : valid input node"); - XRPL_ASSERT(backed_, "ripple::SHAMap::writeNode : is backed"); + node->cowid() == 0, "xrpl::SHAMap::writeNode : valid input node"); + XRPL_ASSERT(backed_, "xrpl::SHAMap::writeNode : is backed"); canonicalize(node->getHash(), node); @@ -998,8 +997,7 @@ SHAMap::preFlushNode(intr_ptr::SharedPtr node) const { // A shared node should never need to be flushed // because that would imply someone modified it - XRPL_ASSERT( - node->cowid(), "ripple::SHAMap::preFlushNode : valid input node"); + XRPL_ASSERT(node->cowid(), "xrpl::SHAMap::preFlushNode : valid input node"); if (node->cowid() != cowid_) { @@ -1027,8 +1025,7 @@ SHAMap::flushDirty(NodeObjectType t) int SHAMap::walkSubTree(bool doWrite, NodeObjectType t) { - XRPL_ASSERT( - !doWrite || backed_, "ripple::SHAMap::walkSubTree : valid input"); + XRPL_ASSERT(!doWrite || backed_, "xrpl::SHAMap::walkSubTree : valid input"); int flushed = 0; @@ -1105,7 +1102,7 @@ SHAMap::walkSubTree(bool doWrite, NodeObjectType t) XRPL_ASSERT( node->cowid() == cowid_, - "ripple::SHAMap::walkSubTree : node cowid do " + "xrpl::SHAMap::walkSubTree : node cowid do " "match"); child->updateHash(); child->unshare(); @@ -1141,7 +1138,7 @@ SHAMap::walkSubTree(bool doWrite, NodeObjectType t) // Hook this inner node to its parent XRPL_ASSERT( parent->cowid() == cowid_, - "ripple::SHAMap::walkSubTree : parent cowid do match"); + "xrpl::SHAMap::walkSubTree : parent cowid do match"); parent->shareChild(pos, node); // Continue with parent's next child, if any @@ -1187,7 +1184,7 @@ SHAMap::dump(bool hash) const { XRPL_ASSERT( child->getHash() == inner->getChildHash(i), - "ripple::SHAMap::dump : child hash do match"); + "xrpl::SHAMap::dump : child hash do match"); stack.push({child, nodeID.getChildNodeID(i)}); } } @@ -1206,7 +1203,7 @@ SHAMap::cacheLookup(SHAMapHash const& hash) const auto ret = f_.getTreeNodeCache()->fetch(hash.as_uint256()); XRPL_ASSERT( !ret || !ret->cowid(), - "ripple::SHAMap::cacheLookup : not found or zero cowid"); + "xrpl::SHAMap::cacheLookup : not found or zero cowid"); return ret; } @@ -1215,12 +1212,12 @@ SHAMap::canonicalize( SHAMapHash const& hash, intr_ptr::SharedPtr& node) const { - XRPL_ASSERT(backed_, "ripple::SHAMap::canonicalize : is backed"); + XRPL_ASSERT(backed_, "xrpl::SHAMap::canonicalize : is backed"); XRPL_ASSERT( - node->cowid() == 0, "ripple::SHAMap::canonicalize : valid node input"); + node->cowid() == 0, "xrpl::SHAMap::canonicalize : valid node input"); XRPL_ASSERT( node->getHash() == hash, - "ripple::SHAMap::canonicalize : node hash do match"); + "xrpl::SHAMap::canonicalize : node hash do match"); f_.getTreeNodeCache()->canonicalize_replace_client(hash.as_uint256(), node); } @@ -1230,9 +1227,9 @@ SHAMap::invariants() const { (void)getHash(); // update node hashes auto node = root_.get(); - XRPL_ASSERT(node, "ripple::SHAMap::invariants : non-null root node"); + XRPL_ASSERT(node, "xrpl::SHAMap::invariants : non-null root node"); XRPL_ASSERT( - !node->isLeaf(), "ripple::SHAMap::invariants : root node is not leaf"); + !node->isLeaf(), "xrpl::SHAMap::invariants : root node is not leaf"); SharedPtrNodeStack stack; for (auto leaf = peekFirstItem(stack); leaf != nullptr; leaf = peekNextItem(leaf->peekItem()->key(), stack)) @@ -1240,4 +1237,4 @@ SHAMap::invariants() const node->invariants(true); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/shamap/SHAMapDelta.cpp b/src/libxrpl/shamap/SHAMapDelta.cpp index 063c41993d..d7234bcbab 100644 --- a/src/libxrpl/shamap/SHAMapDelta.cpp +++ b/src/libxrpl/shamap/SHAMapDelta.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // This code is used to compare another node's transaction tree // to our own. It returns a map containing all items that are different @@ -112,7 +112,7 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const XRPL_ASSERT( isValid() && otherMap.isValid(), - "ripple::SHAMap::compare : valid state and valid input"); + "xrpl::SHAMap::compare : valid state and valid input"); if (getHash() == otherMap.getHash()) return true; @@ -130,7 +130,7 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const if (!ourNode || !otherNode) { // LCOV_EXCL_START - UNREACHABLE("ripple::SHAMap::compare : missing a node"); + UNREACHABLE("xrpl::SHAMap::compare : missing a node"); Throw(type_, uint256()); // LCOV_EXCL_STOP } @@ -214,7 +214,7 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const else { // LCOV_EXCL_START - UNREACHABLE("ripple::SHAMap::compare : invalid node"); + UNREACHABLE("xrpl::SHAMap::compare : invalid node"); // LCOV_EXCL_STOP } } @@ -315,7 +315,7 @@ SHAMap::walkMapParallel( std::move(nodeStack.top()); XRPL_ASSERT( node, - "ripple::SHAMap::walkMapParallel : non-null node"); + "xrpl::SHAMap::walkMapParallel : non-null node"); nodeStack.pop(); for (int i = 0; i < 16; ++i) @@ -366,4 +366,4 @@ SHAMap::walkMapParallel( return false; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/shamap/SHAMapInnerNode.cpp b/src/libxrpl/shamap/SHAMapInnerNode.cpp index f17f86bcb1..5d4a0fd27f 100644 --- a/src/libxrpl/shamap/SHAMapInnerNode.cpp +++ b/src/libxrpl/shamap/SHAMapInnerNode.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { SHAMapInnerNode::SHAMapInnerNode( std::uint32_t cowid, @@ -212,7 +212,7 @@ void SHAMapInnerNode::serializeForWire(Serializer& s) const { XRPL_ASSERT( - !isEmpty(), "ripple::SHAMapInnerNode::serializeForWire : is non-empty"); + !isEmpty(), "xrpl::SHAMapInnerNode::serializeForWire : is non-empty"); // If the node is sparse, then only send non-empty branches: if (getBranchCount() < 12) @@ -238,7 +238,7 @@ SHAMapInnerNode::serializeWithPrefix(Serializer& s) const { XRPL_ASSERT( !isEmpty(), - "ripple::SHAMapInnerNode::serializeWithPrefix : is non-empty"); + "xrpl::SHAMapInnerNode::serializeWithPrefix : is non-empty"); s.add32(HashPrefix::innerNode); iterChildren( @@ -265,11 +265,11 @@ SHAMapInnerNode::setChild(int m, intr_ptr::SharedPtr child) { XRPL_ASSERT( (m >= 0) && (m < branchFactor), - "ripple::SHAMapInnerNode::setChild : valid branch input"); - XRPL_ASSERT(cowid_, "ripple::SHAMapInnerNode::setChild : nonzero cowid"); + "xrpl::SHAMapInnerNode::setChild : valid branch input"); + XRPL_ASSERT(cowid_, "xrpl::SHAMapInnerNode::setChild : nonzero cowid"); XRPL_ASSERT( child.get() != this, - "ripple::SHAMapInnerNode::setChild : valid child input"); + "xrpl::SHAMapInnerNode::setChild : valid child input"); auto const dstIsBranch = [&] { if (child) @@ -298,7 +298,7 @@ SHAMapInnerNode::setChild(int m, intr_ptr::SharedPtr child) XRPL_ASSERT( getBranchCount() <= hashesAndChildren_.capacity(), - "ripple::SHAMapInnerNode::setChild : maximum branch count"); + "xrpl::SHAMapInnerNode::setChild : maximum branch count"); } // finished modifying, now make shareable @@ -309,17 +309,17 @@ SHAMapInnerNode::shareChild( { XRPL_ASSERT( (m >= 0) && (m < branchFactor), - "ripple::SHAMapInnerNode::shareChild : valid branch input"); - XRPL_ASSERT(cowid_, "ripple::SHAMapInnerNode::shareChild : nonzero cowid"); + "xrpl::SHAMapInnerNode::shareChild : valid branch input"); + XRPL_ASSERT(cowid_, "xrpl::SHAMapInnerNode::shareChild : nonzero cowid"); XRPL_ASSERT( - child, "ripple::SHAMapInnerNode::shareChild : non-null child input"); + child, "xrpl::SHAMapInnerNode::shareChild : non-null child input"); XRPL_ASSERT( child.get() != this, - "ripple::SHAMapInnerNode::shareChild : valid child input"); + "xrpl::SHAMapInnerNode::shareChild : valid child input"); XRPL_ASSERT( !isEmptyBranch(m), - "ripple::SHAMapInnerNode::shareChild : non-empty branch input"); + "xrpl::SHAMapInnerNode::shareChild : non-empty branch input"); hashesAndChildren_.getChildren()[*getChildIndex(m)] = child; } @@ -328,10 +328,10 @@ SHAMapInnerNode::getChildPointer(int branch) { XRPL_ASSERT( branch >= 0 && branch < branchFactor, - "ripple::SHAMapInnerNode::getChildPointer : valid branch input"); + "xrpl::SHAMapInnerNode::getChildPointer : valid branch input"); XRPL_ASSERT( !isEmptyBranch(branch), - "ripple::SHAMapInnerNode::getChildPointer : non-empty branch input"); + "xrpl::SHAMapInnerNode::getChildPointer : non-empty branch input"); auto const index = *getChildIndex(branch); @@ -345,10 +345,10 @@ SHAMapInnerNode::getChild(int branch) { XRPL_ASSERT( branch >= 0 && branch < branchFactor, - "ripple::SHAMapInnerNode::getChild : valid branch input"); + "xrpl::SHAMapInnerNode::getChild : valid branch input"); XRPL_ASSERT( !isEmptyBranch(branch), - "ripple::SHAMapInnerNode::getChild : non-empty branch input"); + "xrpl::SHAMapInnerNode::getChild : non-empty branch input"); auto const index = *getChildIndex(branch); @@ -362,7 +362,7 @@ SHAMapInnerNode::getChildHash(int m) const { XRPL_ASSERT( (m >= 0) && (m < branchFactor), - "ripple::SHAMapInnerNode::getChildHash : valid branch input"); + "xrpl::SHAMapInnerNode::getChildHash : valid branch input"); if (auto const i = getChildIndex(m)) return hashesAndChildren_.getHashes()[*i]; @@ -376,18 +376,18 @@ SHAMapInnerNode::canonicalizeChild( { XRPL_ASSERT( branch >= 0 && branch < branchFactor, - "ripple::SHAMapInnerNode::canonicalizeChild : valid branch input"); + "xrpl::SHAMapInnerNode::canonicalizeChild : valid branch input"); XRPL_ASSERT( node != nullptr, - "ripple::SHAMapInnerNode::canonicalizeChild : valid node input"); + "xrpl::SHAMapInnerNode::canonicalizeChild : valid node input"); XRPL_ASSERT( !isEmptyBranch(branch), - "ripple::SHAMapInnerNode::canonicalizeChild : non-empty branch input"); + "xrpl::SHAMapInnerNode::canonicalizeChild : non-empty branch input"); auto const childIndex = *getChildIndex(branch); auto [_, hashes, children] = hashesAndChildren_.getHashesAndChildren(); XRPL_ASSERT( node->getHash() == hashes[childIndex], - "ripple::SHAMapInnerNode::canonicalizeChild : node and branch inputs " + "xrpl::SHAMapInnerNode::canonicalizeChild : node and branch inputs " "hash do match"); packed_spinlock sl(lock_, childIndex); @@ -420,7 +420,7 @@ SHAMapInnerNode::invariants(bool is_root) const { XRPL_ASSERT( hashes[i].isNonZero(), - "ripple::SHAMapInnerNode::invariants : nonzero hash in branch"); + "xrpl::SHAMapInnerNode::invariants : nonzero hash in branch"); if (children[i] != nullptr) children[i]->invariants(); ++count; @@ -434,7 +434,7 @@ SHAMapInnerNode::invariants(bool is_root) const { XRPL_ASSERT( (isBranch_ & (1 << i)), - "ripple::SHAMapInnerNode::invariants : valid branch when " + "xrpl::SHAMapInnerNode::invariants : valid branch when " "nonzero hash"); if (children[i] != nullptr) children[i]->invariants(); @@ -444,7 +444,7 @@ SHAMapInnerNode::invariants(bool is_root) const { XRPL_ASSERT( (isBranch_ & (1 << i)) == 0, - "ripple::SHAMapInnerNode::invariants : valid branch when " + "xrpl::SHAMapInnerNode::invariants : valid branch when " "zero hash"); } } @@ -454,13 +454,13 @@ SHAMapInnerNode::invariants(bool is_root) const { XRPL_ASSERT( hash_.isNonZero(), - "ripple::SHAMapInnerNode::invariants : nonzero hash"); + "xrpl::SHAMapInnerNode::invariants : nonzero hash"); XRPL_ASSERT( - count >= 1, "ripple::SHAMapInnerNode::invariants : minimum count"); + count >= 1, "xrpl::SHAMapInnerNode::invariants : minimum count"); } XRPL_ASSERT( (count == 0) ? hash_.isZero() : hash_.isNonZero(), - "ripple::SHAMapInnerNode::invariants : hash and count do match"); + "xrpl::SHAMapInnerNode::invariants : hash and count do match"); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/shamap/SHAMapLeafNode.cpp b/src/libxrpl/shamap/SHAMapLeafNode.cpp index d2fd88ba5a..72e57cd737 100644 --- a/src/libxrpl/shamap/SHAMapLeafNode.cpp +++ b/src/libxrpl/shamap/SHAMapLeafNode.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { SHAMapLeafNode::SHAMapLeafNode( boost::intrusive_ptr item, @@ -9,7 +9,7 @@ SHAMapLeafNode::SHAMapLeafNode( { XRPL_ASSERT( item_->size() >= 12, - "ripple::SHAMapLeafNode::SHAMapLeafNode(boost::intrusive_ptr<" + "xrpl::SHAMapLeafNode::SHAMapLeafNode(boost::intrusive_ptr<" "SHAMapItem const>, std::uint32_t) : minimum input size"); } @@ -21,7 +21,7 @@ SHAMapLeafNode::SHAMapLeafNode( { XRPL_ASSERT( item_->size() >= 12, - "ripple::SHAMapLeafNode::SHAMapLeafNode(boost::intrusive_ptr<" + "xrpl::SHAMapLeafNode::SHAMapLeafNode(boost::intrusive_ptr<" "SHAMapItem const>, std::uint32_t, SHAMapHash const&) : minimum input " "size"); } @@ -35,7 +35,7 @@ SHAMapLeafNode::peekItem() const bool SHAMapLeafNode::setItem(boost::intrusive_ptr item) { - XRPL_ASSERT(cowid_, "ripple::SHAMapLeafNode::setItem : nonzero cowid"); + XRPL_ASSERT(cowid_, "xrpl::SHAMapLeafNode::setItem : nonzero cowid"); item_ = std::move(item); auto const oldHash = hash_; @@ -74,8 +74,8 @@ void SHAMapLeafNode::invariants(bool) const { XRPL_ASSERT( - hash_.isNonZero(), "ripple::SHAMapLeafNode::invariants : nonzero hash"); - XRPL_ASSERT(item_, "ripple::SHAMapLeafNode::invariants : non-null item"); + hash_.isNonZero(), "xrpl::SHAMapLeafNode::invariants : nonzero hash"); + XRPL_ASSERT(item_, "xrpl::SHAMapLeafNode::invariants : non-null item"); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/shamap/SHAMapNodeID.cpp b/src/libxrpl/shamap/SHAMapNodeID.cpp index 33d38ebb03..a32ff5c28e 100644 --- a/src/libxrpl/shamap/SHAMapNodeID.cpp +++ b/src/libxrpl/shamap/SHAMapNodeID.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { static uint256 const& depthMask(unsigned int depth) @@ -39,10 +39,10 @@ SHAMapNodeID::SHAMapNodeID(unsigned int depth, uint256 const& hash) { XRPL_ASSERT( depth <= SHAMap::leafDepth, - "ripple::SHAMapNodeID::SHAMapNodeID : maximum depth input"); + "xrpl::SHAMapNodeID::SHAMapNodeID : maximum depth input"); XRPL_ASSERT( id_ == (id_ & depthMask(depth)), - "ripple::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match"); + "xrpl::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match"); } std::string @@ -59,7 +59,7 @@ SHAMapNodeID::getChildNodeID(unsigned int m) const { XRPL_ASSERT( m < SHAMap::branchFactor, - "ripple::SHAMapNodeID::getChildNodeID : valid branch input"); + "xrpl::SHAMapNodeID::getChildNodeID : valid branch input"); // A SHAMap has exactly 65 levels, so nodes must not exceed that // depth; if they do, this breaks the invariant of never allowing @@ -71,7 +71,7 @@ SHAMapNodeID::getChildNodeID(unsigned int m) const // constructing a child node from them would break the above invariant. XRPL_ASSERT( depth_ <= SHAMap::leafDepth, - "ripple::SHAMapNodeID::getChildNodeID : maximum leaf depth"); + "xrpl::SHAMapNodeID::getChildNodeID : maximum leaf depth"); if (depth_ >= SHAMap::leafDepth) Throw( @@ -117,7 +117,7 @@ selectBranch(SHAMapNodeID const& id, uint256 const& hash) branch >>= 4; XRPL_ASSERT( - branch < SHAMap::branchFactor, "ripple::selectBranch : maximum result"); + branch < SHAMap::branchFactor, "xrpl::selectBranch : maximum result"); return branch; } @@ -126,8 +126,8 @@ SHAMapNodeID::createID(int depth, uint256 const& key) { XRPL_ASSERT( (depth >= 0) && (depth < 65), - "ripple::SHAMapNodeID::createID : valid branch input"); + "xrpl::SHAMapNodeID::createID : valid branch input"); return SHAMapNodeID(depth, key & depthMask(depth)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/shamap/SHAMapSync.cpp b/src/libxrpl/shamap/SHAMapSync.cpp index 3bc2d5561e..d9c0846fbf 100644 --- a/src/libxrpl/shamap/SHAMapSync.cpp +++ b/src/libxrpl/shamap/SHAMapSync.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { void SHAMap::visitLeaves( @@ -300,8 +300,8 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) { XRPL_ASSERT( root_->getHash().isNonZero(), - "ripple::SHAMap::getMissingNodes : nonzero root hash"); - XRPL_ASSERT(max > 0, "ripple::SHAMap::getMissingNodes : valid max input"); + "xrpl::SHAMap::getMissingNodes : nonzero root hash"); + XRPL_ASSERT(max > 0, "xrpl::SHAMap::getMissingNodes : valid max input"); MissingNodes mn( max, @@ -362,7 +362,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) } XRPL_ASSERT( node, - "ripple::SHAMap::getMissingNodes : first non-null node"); + "xrpl::SHAMap::getMissingNodes : first non-null node"); } } @@ -395,7 +395,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) mn.stack_.pop(); XRPL_ASSERT( node, - "ripple::SHAMap::getMissingNodes : second non-null node"); + "xrpl::SHAMap::getMissingNodes : second non-null node"); } } @@ -524,11 +524,11 @@ SHAMap::addRootNode( JLOG(journal_.trace()) << "got root node, already have one"; XRPL_ASSERT( root_->getHash() == hash, - "ripple::SHAMap::addRootNode : valid hash input"); + "xrpl::SHAMap::addRootNode : valid hash input"); return SHAMapAddNode::duplicate(); } - XRPL_ASSERT(cowid_ >= 1, "ripple::SHAMap::addRootNode : valid cowid"); + XRPL_ASSERT(cowid_ >= 1, "xrpl::SHAMap::addRootNode : valid cowid"); auto node = SHAMapTreeNode::makeFromWire(rootNode); if (!node || node->getHash() != hash) return SHAMapAddNode::invalid(); @@ -563,7 +563,7 @@ SHAMap::addKnownNode( SHAMapSyncFilter* filter) { XRPL_ASSERT( - !node.isRoot(), "ripple::SHAMap::addKnownNode : valid node input"); + !node.isRoot(), "xrpl::SHAMap::addKnownNode : valid node input"); if (!isSynching()) { @@ -580,7 +580,7 @@ SHAMap::addKnownNode( (currNodeID.getDepth() < node.getDepth())) { int const branch = selectBranch(currNodeID, node.getNodeID()); - XRPL_ASSERT(branch >= 0, "ripple::SHAMap::addKnownNode : valid branch"); + XRPL_ASSERT(branch >= 0, "xrpl::SHAMap::addKnownNode : valid branch"); auto inner = static_cast(currNode); if (inner->isEmptyBranch(branch)) { @@ -884,4 +884,4 @@ SHAMap::verifyProofPath( return false; } -} // namespace ripple +} // namespace xrpl diff --git a/src/libxrpl/shamap/SHAMapTreeNode.cpp b/src/libxrpl/shamap/SHAMapTreeNode.cpp index 453be08756..854b4c1097 100644 --- a/src/libxrpl/shamap/SHAMapTreeNode.cpp +++ b/src/libxrpl/shamap/SHAMapTreeNode.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { intr_ptr::SharedPtr SHAMapTreeNode::makeTransaction( @@ -164,4 +164,4 @@ SHAMapTreeNode::getString(SHAMapNodeID const& id) const return to_string(id); } -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/AMMCalc_test.cpp b/src/test/app/AMMCalc_test.cpp index 998642afb7..abfb548b64 100644 --- a/src/test/app/AMMCalc_test.cpp +++ b/src/test/app/AMMCalc_test.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { /** AMM Calculator. Uses AMM formulas to simulate the payment engine @@ -439,7 +439,7 @@ class AMMCalc_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE_MANUAL(AMMCalc, app, ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(AMMCalc, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/AMMClawback_test.cpp b/src/test/app/AMMClawback_test.cpp index 003bffae8f..e9882ef174 100644 --- a/src/test/app/AMMClawback_test.cpp +++ b/src/test/app/AMMClawback_test.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class AMMClawback_test : public beast::unit_test::suite { @@ -2447,6 +2447,6 @@ class AMMClawback_test : public beast::unit_test::suite } } }; -BEAST_DEFINE_TESTSUITE(AMMClawback, app, ripple); +BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/AMMExtended_test.cpp b/src/test/app/AMMExtended_test.cpp index 080b392ebe..c3bfb46043 100644 --- a/src/test/app/AMMExtended_test.cpp +++ b/src/test/app/AMMExtended_test.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { /** @@ -3822,7 +3822,7 @@ private: } }; -BEAST_DEFINE_TESTSUITE_PRIO(AMMExtended, app, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(AMMExtended, app, xrpl, 1); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/AMM_test.cpp b/src/test/app/AMM_test.cpp index 611932e825..8d64dfed2a 100644 --- a/src/test/app/AMM_test.cpp +++ b/src/test/app/AMM_test.cpp @@ -21,7 +21,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { /** @@ -7481,7 +7481,7 @@ private: for (int i = 0; i < 256; ++i) { AccountID const accountId = - ripple::pseudoAccountAddress(*env.current(), keylet.key); + xrpl::pseudoAccountAddress(*env.current(), keylet.key); env(pay(env.master.id(), accountId, XRP(1000)), seq(autofill), @@ -7952,7 +7952,7 @@ private: } }; -BEAST_DEFINE_TESTSUITE_PRIO(AMM, app, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(AMM, app, xrpl, 1); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/AccountDelete_test.cpp b/src/test/app/AccountDelete_test.cpp index 91164d3e4e..749ed33e28 100644 --- a/src/test/app/AccountDelete_test.cpp +++ b/src/test/app/AccountDelete_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class AccountDelete_test : public beast::unit_test::suite @@ -1104,7 +1104,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, ripple, 2); +BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, xrpl, 2); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/AccountTxPaging_test.cpp b/src/test/app/AccountTxPaging_test.cpp index fe72f1fe1f..5efe307812 100644 --- a/src/test/app/AccountTxPaging_test.cpp +++ b/src/test/app/AccountTxPaging_test.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { class AccountTxPaging_test : public beast::unit_test::suite { @@ -251,6 +251,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple); +BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/AmendmentTable_test.cpp b/src/test/app/AmendmentTable_test.cpp index 6aad3fa05f..9add892073 100644 --- a/src/test/app/AmendmentTable_test.cpp +++ b/src/test/app/AmendmentTable_test.cpp @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { class AmendmentTable_test final : public beast::unit_test::suite { @@ -534,7 +534,7 @@ public: } auto v = std::make_shared( - ripple::NetClock::time_point{}, + xrpl::NetClock::time_point{}, pub, sec, calcNodeID(pub), @@ -1271,6 +1271,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(AmendmentTable, app, ripple); +BEAST_DEFINE_TESTSUITE(AmendmentTable, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Batch_test.cpp b/src/test/app/Batch_test.cpp index f2fae58a9b..06cf5dee0c 100644 --- a/src/test/app/Batch_test.cpp +++ b/src/test/app/Batch_test.cpp @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Batch_test : public beast::unit_test::suite @@ -547,7 +547,7 @@ class Batch_test : public beast::unit_test::suite Serializer msg; serializeBatch( msg, tfAllOrNothing, jt.stx->getBatchTransactionIDs()); - auto const sig = ripple::sign(bob.pk(), bob.sk(), msg.slice()); + auto const sig = xrpl::sign(bob.pk(), bob.sk(), msg.slice()); jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName] [sfAccount.jsonName] = bob.human(); jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName] @@ -1378,7 +1378,7 @@ class Batch_test : public beast::unit_test::suite env.app().openLedger().modify( [&](OpenView& view, beast::Journal j) { auto const result = - ripple::apply(env.app(), view, *jt.stx, tapNONE, j); + xrpl::apply(env.app(), view, *jt.stx, tapNONE, j); BEAST_EXPECT( !result.applied && result.ter == temARRAY_TOO_LARGE); return result.applied; @@ -1424,7 +1424,7 @@ class Batch_test : public beast::unit_test::suite env.app().openLedger().modify( [&](OpenView& view, beast::Journal j) { auto const result = - ripple::apply(env.app(), view, *jt.stx, tapNONE, j); + xrpl::apply(env.app(), view, *jt.stx, tapNONE, j); BEAST_EXPECT( !result.applied && result.ter == temARRAY_TOO_LARGE); return result.applied; @@ -3592,7 +3592,7 @@ class Batch_test : public beast::unit_test::suite BEAST_EXPECT(!passesLocalChecks(stx, reason)); BEAST_EXPECT(reason == "Cannot submit pseudo transactions."); env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { - auto const result = ripple::apply(env.app(), view, stx, tapNONE, j); + auto const result = xrpl::apply(env.app(), view, stx, tapNONE, j); BEAST_EXPECT(!result.applied && result.ter == temINVALID_FLAG); return result.applied; }); @@ -4356,7 +4356,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Batch, app, ripple); +BEAST_DEFINE_TESTSUITE(Batch, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Check_test.cpp b/src/test/app/Check_test.cpp index b7d158041b..b3d8249dd0 100644 --- a/src/test/app/Check_test.cpp +++ b/src/test/app/Check_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -1911,7 +1911,7 @@ class Check_test : public beast::unit_test::suite return acct; } - operator ripple::AccountID() const + operator xrpl::AccountID() const { return acct.id(); } @@ -2585,6 +2585,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Check, app, ripple); +BEAST_DEFINE_TESTSUITE(Check, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Clawback_test.cpp b/src/test/app/Clawback_test.cpp index 933e9678aa..c8c4aea757 100644 --- a/src/test/app/Clawback_test.cpp +++ b/src/test/app/Clawback_test.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Clawback_test : public beast::unit_test::suite { @@ -937,5 +937,5 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Clawback, app, ripple); -} // namespace ripple +BEAST_DEFINE_TESTSUITE(Clawback, app, xrpl); +} // namespace xrpl diff --git a/src/test/app/Credentials_test.cpp b/src/test/app/Credentials_test.cpp index c4a5ee1c7c..7de34e05a1 100644 --- a/src/test/app/Credentials_test.cpp +++ b/src/test/app/Credentials_test.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { struct Credentials_test : public beast::unit_test::suite @@ -926,8 +926,7 @@ struct Credentials_test : public beast::unit_test::suite testcase("deleteSLE fail, bad SLE."); auto view = std::make_shared( env.current().get(), ApplyFlags::tapNONE); - auto ter = - ripple::credentials::deleteSLE(*view, {}, env.journal); + auto ter = xrpl::credentials::deleteSLE(*view, {}, env.journal); BEAST_EXPECT(ter == tecNO_ENTRY); } } @@ -1108,7 +1107,7 @@ struct Credentials_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(Credentials, app, ripple); +BEAST_DEFINE_TESTSUITE(Credentials, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/CrossingLimits_test.cpp b/src/test/app/CrossingLimits_test.cpp index 13d7aef505..9e9b1a3d45 100644 --- a/src/test/app/CrossingLimits_test.cpp +++ b/src/test/app/CrossingLimits_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class CrossingLimits_test : public beast::unit_test::suite @@ -492,7 +492,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(CrossingLimits, app, ripple, 10); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(CrossingLimits, app, xrpl, 10); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/DID_test.cpp b/src/test/app/DID_test.cpp index 20d4e3d34d..e7adfee178 100644 --- a/src/test/app/DID_test.cpp +++ b/src/test/app/DID_test.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { struct DID_test : public beast::unit_test::suite @@ -379,7 +379,7 @@ struct DID_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(DID, app, ripple); +BEAST_DEFINE_TESTSUITE(DID, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/DNS_test.cpp b/src/test/app/DNS_test.cpp index cf5bfb31f7..fc6917e15c 100644 --- a/src/test/app/DNS_test.cpp +++ b/src/test/app/DNS_test.cpp @@ -7,14 +7,14 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class DNS_test : public beast::unit_test::suite { using endpoint_type = boost::asio::ip::tcp::endpoint; using error_code = boost::system::error_code; - std::weak_ptr work_; + std::weak_ptr work_; endpoint_type lastEndpoint_{}; parsedURL pUrl_; std::string port_; @@ -33,14 +33,14 @@ public: { auto onFetch = [&](error_code const& errorCode, endpoint_type const& endpoint, - ripple::detail::response_type&& resp) { + xrpl::detail::response_type&& resp) { BEAST_EXPECT(!errorCode); lastEndpoint_ = endpoint; resolved_[endpoint.address().to_string()]++; cv_.notify_all(); }; - auto sp = std::make_shared( + auto sp = std::make_shared( pUrl_.domain, pUrl_.path, port_, @@ -110,7 +110,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(DNS, app, ripple, 20); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(DNS, app, xrpl, 20); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Delegate_test.cpp b/src/test/app/Delegate_test.cpp index e36ad9a550..7d58093e43 100644 --- a/src/test/app/Delegate_test.cpp +++ b/src/test/app/Delegate_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Delegate_test : public beast::unit_test::suite { @@ -1806,6 +1806,6 @@ class Delegate_test : public beast::unit_test::suite testTxReqireFeatures(all); } }; -BEAST_DEFINE_TESTSUITE(Delegate, app, ripple); +BEAST_DEFINE_TESTSUITE(Delegate, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/DeliverMin_test.cpp b/src/test/app/DeliverMin_test.cpp index 9a2bc9372e..4d643dfae1 100644 --- a/src/test/app/DeliverMin_test.cpp +++ b/src/test/app/DeliverMin_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class DeliverMin_test : public beast::unit_test::suite @@ -129,7 +129,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple); +BEAST_DEFINE_TESTSUITE(DeliverMin, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/DepositAuth_test.cpp b/src/test/app/DepositAuth_test.cpp index ed727c2fa0..4235c8c9ca 100644 --- a/src/test/app/DepositAuth_test.cpp +++ b/src/test/app/DepositAuth_test.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { // Helper function that returns the reserve on an account based on @@ -1462,8 +1462,8 @@ struct DepositPreauth_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(DepositAuth, app, ripple); -BEAST_DEFINE_TESTSUITE(DepositPreauth, app, ripple); +BEAST_DEFINE_TESTSUITE(DepositAuth, app, xrpl); +BEAST_DEFINE_TESTSUITE(DepositPreauth, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Discrepancy_test.cpp b/src/test/app/Discrepancy_test.cpp index b7ac66e1df..0e96f3aa1a 100644 --- a/src/test/app/Discrepancy_test.cpp +++ b/src/test/app/Discrepancy_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { class Discrepancy_test : public beast::unit_test::suite { @@ -133,6 +133,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Discrepancy, app, ripple); +BEAST_DEFINE_TESTSUITE(Discrepancy, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/EscrowToken_test.cpp b/src/test/app/EscrowToken_test.cpp index f1dc6155f4..ff8b2cfb49 100644 --- a/src/test/app/EscrowToken_test.cpp +++ b/src/test/app/EscrowToken_test.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct EscrowToken_test : public beast::unit_test::suite @@ -1000,14 +1000,14 @@ struct EscrowToken_test : public beast::unit_test::suite auto const aa = env.le(keylet::escrow(alice.id(), aseq)); BEAST_EXPECT(aa); { - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); BEAST_EXPECT( std::find(aod.begin(), aod.end(), aa) != aod.end()); } { - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 4); BEAST_EXPECT( std::find(iod.begin(), iod.end(), aa) != iod.end()); @@ -1024,14 +1024,14 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(bb); { - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) != bod.end()); } { - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 5); BEAST_EXPECT( std::find(iod.begin(), iod.end(), bb) != iod.end()); @@ -1045,17 +1045,17 @@ struct EscrowToken_test : public beast::unit_test::suite (*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), aa) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) != bod.end()); - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 4); BEAST_EXPECT( std::find(iod.begin(), iod.end(), bb) != iod.end()); @@ -1069,12 +1069,12 @@ struct EscrowToken_test : public beast::unit_test::suite (*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) == bod.end()); - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 3); BEAST_EXPECT( std::find(iod.begin(), iod.end(), bb) == iod.end()); @@ -1117,24 +1117,24 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(bc); { - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) != aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 3); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) != bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) != bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 2); BEAST_EXPECT( std::find(cod.begin(), cod.end(), bc) != cod.end()); - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 5); BEAST_EXPECT( std::find(iod.begin(), iod.end(), ab) != iod.end()); @@ -1148,22 +1148,22 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); BEAST_EXPECT(env.le(keylet::escrow(bob.id(), bseq))); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) == bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) != bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 2); - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 4); BEAST_EXPECT( std::find(iod.begin(), iod.end(), ab) == iod.end()); @@ -1177,22 +1177,22 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); BEAST_EXPECT(!env.le(keylet::escrow(bob.id(), bseq))); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) == bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) == bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 3); BEAST_EXPECT( std::find(iod.begin(), iod.end(), ab) == iod.end()); @@ -1232,15 +1232,15 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(ag); { - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ag) != aod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 3); BEAST_EXPECT( std::find(iod.begin(), iod.end(), ag) != iod.end()); @@ -1251,15 +1251,15 @@ struct EscrowToken_test : public beast::unit_test::suite { BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ag) == aod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 2); BEAST_EXPECT( std::find(iod.begin(), iod.end(), ag) == iod.end()); @@ -2265,7 +2265,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.fund(XRP(10'000), alice, bob, gw); env.close(); - auto const mpt = ripple::test::jtx::MPT( + auto const mpt = xrpl::test::jtx::MPT( alice.name(), makeMptID(env.seq(alice), alice)); Json::Value jv = escrow::create(alice, bob, mpt(2)); jv[jss::Amount][jss::mpt_issuance_id] = @@ -3209,14 +3209,14 @@ struct EscrowToken_test : public beast::unit_test::suite auto const aa = env.le(keylet::escrow(alice.id(), aseq)); BEAST_EXPECT(aa); { - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); BEAST_EXPECT( std::find(aod.begin(), aod.end(), aa) != aod.end()); } { - ripple::Dir iod(*env.current(), keylet::ownerDir(gw.id())); + xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 1); BEAST_EXPECT( std::find(iod.begin(), iod.end(), aa) == iod.end()); @@ -3233,7 +3233,7 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(bb); { - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) != bod.end()); @@ -3247,12 +3247,12 @@ struct EscrowToken_test : public beast::unit_test::suite (*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), aa) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) != bod.end()); @@ -3266,7 +3266,7 @@ struct EscrowToken_test : public beast::unit_test::suite (*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) == bod.end()); @@ -3314,19 +3314,19 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(bc); { - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) != aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 3); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) != bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) != bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 2); BEAST_EXPECT( std::find(cod.begin(), cod.end(), bc) != cod.end()); @@ -3338,19 +3338,19 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); BEAST_EXPECT(env.le(keylet::escrow(bob.id(), bseq))); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) == bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) != bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 2); } @@ -3360,19 +3360,19 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); BEAST_EXPECT(!env.le(keylet::escrow(bob.id(), bseq))); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bob.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) == bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) == bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); } } @@ -3930,7 +3930,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(EscrowToken, app, ripple); +BEAST_DEFINE_TESTSUITE(EscrowToken, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Escrow_test.cpp b/src/test/app/Escrow_test.cpp index e3b2340022..d4a9fc5b9d 100644 --- a/src/test/app/Escrow_test.cpp +++ b/src/test/app/Escrow_test.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct Escrow_test : public beast::unit_test::suite @@ -1144,7 +1144,7 @@ struct Escrow_test : public beast::unit_test::suite BEAST_EXPECT(aa); { - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), aa) != aod.end()); @@ -1161,7 +1161,7 @@ struct Escrow_test : public beast::unit_test::suite BEAST_EXPECT(bb); { - ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) != bod.end()); @@ -1175,12 +1175,12 @@ struct Escrow_test : public beast::unit_test::suite (*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0); BEAST_EXPECT( std::find(aod.begin(), aod.end(), aa) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) != bod.end()); @@ -1194,7 +1194,7 @@ struct Escrow_test : public beast::unit_test::suite (*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); - ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 0); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bb) == bod.end()); @@ -1229,19 +1229,19 @@ struct Escrow_test : public beast::unit_test::suite BEAST_EXPECT(bc); { - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) != aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) != bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) != bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); BEAST_EXPECT( std::find(cod.begin(), cod.end(), bc) != cod.end()); @@ -1253,19 +1253,19 @@ struct Escrow_test : public beast::unit_test::suite BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); BEAST_EXPECT(env.le(keylet::escrow(bruce.id(), bseq))); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) == bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) != bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); } @@ -1275,19 +1275,19 @@ struct Escrow_test : public beast::unit_test::suite BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); BEAST_EXPECT(!env.le(keylet::escrow(bruce.id(), bseq))); - ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id())); + xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0); BEAST_EXPECT( std::find(aod.begin(), aod.end(), ab) == aod.end()); - ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); + xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 0); BEAST_EXPECT( std::find(bod.begin(), bod.end(), ab) == bod.end()); BEAST_EXPECT( std::find(bod.begin(), bod.end(), bc) == bod.end()); - ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id())); + xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 0); } } @@ -1678,7 +1678,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Escrow, app, ripple); +BEAST_DEFINE_TESTSUITE(Escrow, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/FeeVote_test.cpp b/src/test/app/FeeVote_test.cpp index 94f753d8f3..c7f33544f9 100644 --- a/src/test/app/FeeVote_test.cpp +++ b/src/test/app/FeeVote_test.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct FeeSettingsFields @@ -780,7 +780,7 @@ class FeeVote_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(FeeVote, app, ripple); +BEAST_DEFINE_TESTSUITE(FeeVote, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/FixNFTokenPageLinks_test.cpp b/src/test/app/FixNFTokenPageLinks_test.cpp index 32d444eea2..baa33b2dc5 100644 --- a/src/test/app/FixNFTokenPageLinks_test.cpp +++ b/src/test/app/FixNFTokenPageLinks_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class FixNFTokenPageLinks_test : public beast::unit_test::suite { @@ -642,6 +642,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(FixNFTokenPageLinks, app, ripple); +BEAST_DEFINE_TESTSUITE(FixNFTokenPageLinks, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Flow_test.cpp b/src/test/app/Flow_test.cpp index 12dcc91b98..e16a48e02f 100644 --- a/src/test/app/Flow_test.cpp +++ b/src/test/app/Flow_test.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { bool @@ -1329,8 +1329,8 @@ struct Flow_manual_test : public Flow_test } }; -BEAST_DEFINE_TESTSUITE_PRIO(Flow, app, ripple, 2); -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Flow_manual, app, ripple, 4); +BEAST_DEFINE_TESTSUITE_PRIO(Flow, app, xrpl, 2); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Flow_manual, app, xrpl, 4); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Freeze_test.cpp b/src/test/app/Freeze_test.cpp index 43d7c6d1e4..85c2b5a924 100644 --- a/src/test/app/Freeze_test.cpp +++ b/src/test/app/Freeze_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class Freeze_test : public beast::unit_test::suite { @@ -2088,5 +2088,5 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Freeze, app, ripple); -} // namespace ripple +BEAST_DEFINE_TESTSUITE(Freeze, app, xrpl); +} // namespace xrpl diff --git a/src/test/app/HashRouter_test.cpp b/src/test/app/HashRouter_test.cpp index b3f692c2b0..c428917fdc 100644 --- a/src/test/app/HashRouter_test.cpp +++ b/src/test/app/HashRouter_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class HashRouter_test : public beast::unit_test::suite @@ -404,7 +404,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(HashRouter, app, ripple); +BEAST_DEFINE_TESTSUITE(HashRouter, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Invariants_test.cpp b/src/test/app/Invariants_test.cpp index 4e4632e49b..8eb3047dc8 100644 --- a/src/test/app/Invariants_test.cpp +++ b/src/test/app/Invariants_test.cpp @@ -20,7 +20,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class Invariants_test : public beast::unit_test::suite @@ -1991,7 +1991,7 @@ class Invariants_test : public beast::unit_test::suite { // Create the directory BEAST_EXPECT( - ::ripple::directory::createRoot( + ::xrpl::directory::createRoot( ac.view(), dirKeylet, loanBrokerKeylet.key, @@ -2018,7 +2018,7 @@ class Invariants_test : public beast::unit_test::suite describeOwnerDir(slePseudo->at(sfAccount)); BEAST_EXPECT( - ::ripple::directory::insertPage( + ::xrpl::directory::insertPage( ac.view(), 0, sleDir, @@ -2051,7 +2051,7 @@ class Invariants_test : public beast::unit_test::suite // Put some extra garbage into the directory for (auto const& key : {slePseudo->key(), sleDir->key()}) { - ::ripple::directory::insertKey( + ::xrpl::directory::insertKey( ac.view(), sleDir, 0, false, indexes, key); } @@ -2082,7 +2082,7 @@ class Invariants_test : public beast::unit_test::suite // Put one meaningless key into the directory auto const key = keylet::account(Account("random").id()).key; - ::ripple::directory::insertKey( + ::xrpl::directory::insertKey( ac.view(), sleDir, 0, false, indexes, key); return true; @@ -2108,7 +2108,7 @@ class Invariants_test : public beast::unit_test::suite // failure. STVector256 indexes; - ::ripple::directory::insertKey( + ::xrpl::directory::insertKey( ac.view(), sleDir, 0, false, indexes, slePseudo->key()); return true; @@ -2165,7 +2165,7 @@ class Invariants_test : public beast::unit_test::suite std::optional accountShares = {}; }; auto constexpr adjust = [&](ApplyView& ac, - ripple::Keylet keylet, + xrpl::Keylet keylet, Adjustments args) { auto sleVault = ac.peek(keylet); if (!sleVault) @@ -3914,7 +3914,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Invariants, app, ripple); +BEAST_DEFINE_TESTSUITE(Invariants, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/LPTokenTransfer_test.cpp b/src/test/app/LPTokenTransfer_test.cpp index acce2312ac..b2a6f39ddf 100644 --- a/src/test/app/LPTokenTransfer_test.cpp +++ b/src/test/app/LPTokenTransfer_test.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class LPTokenTransfer_test : public jtx::AMMTest @@ -462,6 +462,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LPTokenTransfer, app, ripple); +BEAST_DEFINE_TESTSUITE(LPTokenTransfer, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/LedgerHistory_test.cpp b/src/test/app/LedgerHistory_test.cpp index 3223e9e1d8..b69203f1e0 100644 --- a/src/test/app/LedgerHistory_test.cpp +++ b/src/test/app/LedgerHistory_test.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class LedgerHistory_test : public beast::unit_test::suite @@ -182,7 +182,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LedgerHistory, app, ripple); +BEAST_DEFINE_TESTSUITE(LedgerHistory, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/LedgerLoad_test.cpp b/src/test/app/LedgerLoad_test.cpp index ac0fcdba35..d5c37d0404 100644 --- a/src/test/app/LedgerLoad_test.cpp +++ b/src/test/app/LedgerLoad_test.cpp @@ -13,7 +13,7 @@ #include -namespace ripple { +namespace xrpl { class LedgerLoad_test : public beast::unit_test::suite { @@ -370,6 +370,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LedgerLoad, app, ripple); +BEAST_DEFINE_TESTSUITE(LedgerLoad, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/LedgerMaster_test.cpp b/src/test/app/LedgerMaster_test.cpp index 451e4f9068..59e02cbabb 100644 --- a/src/test/app/LedgerMaster_test.cpp +++ b/src/test/app/LedgerMaster_test.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class LedgerMaster_test : public beast::unit_test::suite @@ -116,7 +116,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LedgerMaster, app, ripple); +BEAST_DEFINE_TESTSUITE(LedgerMaster, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/LedgerReplay_test.cpp b/src/test/app/LedgerReplay_test.cpp index a468629de9..beb27817a1 100644 --- a/src/test/app/LedgerReplay_test.cpp +++ b/src/test/app/LedgerReplay_test.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct LedgerReplay_test : public beast::unit_test::suite @@ -1084,8 +1084,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite { testcase("handshake test"); auto handshake = [&](bool client, bool server, bool expecting) -> bool { - auto request = - ripple::makeRequest(true, false, client, false, false); + auto request = xrpl::makeRequest(true, false, client, false, false); http_request_type http_request; http_request.version(request.version()); http_request.base() = request.base(); @@ -1098,7 +1097,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite boost::asio::ip::make_address("172.1.1.100"); jtx::Env serverEnv(*this); serverEnv.app().config().LEDGER_REPLAY = server; - auto http_resp = ripple::makeResponse( + auto http_resp = xrpl::makeResponse( true, http_request, addr, @@ -1596,10 +1595,10 @@ struct LedgerReplayerLong_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(LedgerReplay, app, ripple); -BEAST_DEFINE_TESTSUITE_PRIO(LedgerReplayer, app, ripple, 1); -BEAST_DEFINE_TESTSUITE(LedgerReplayerTimeout, app, ripple); -BEAST_DEFINE_TESTSUITE_MANUAL(LedgerReplayerLong, app, ripple); +BEAST_DEFINE_TESTSUITE(LedgerReplay, app, xrpl); +BEAST_DEFINE_TESTSUITE_PRIO(LedgerReplayer, app, xrpl, 1); +BEAST_DEFINE_TESTSUITE(LedgerReplayerTimeout, app, xrpl); +BEAST_DEFINE_TESTSUITE_MANUAL(LedgerReplayerLong, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/LoadFeeTrack_test.cpp b/src/test/app/LoadFeeTrack_test.cpp index 10b51b5c0b..e0638b64bc 100644 --- a/src/test/app/LoadFeeTrack_test.cpp +++ b/src/test/app/LoadFeeTrack_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class LoadFeeTrack_test : public beast::unit_test::suite { @@ -68,6 +68,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LoadFeeTrack, app, ripple); +BEAST_DEFINE_TESTSUITE(LoadFeeTrack, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/LoanBroker_test.cpp b/src/test/app/LoanBroker_test.cpp index 597e2ea75b..72a732d043 100644 --- a/src/test/app/LoanBroker_test.cpp +++ b/src/test/app/LoanBroker_test.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class LoanBroker_test : public beast::unit_test::suite @@ -638,7 +638,7 @@ class LoanBroker_test : public beast::unit_test::suite } using namespace loanBroker; - using namespace ripple::Lending; + using namespace xrpl::Lending; TenthBips32 const tenthBipsZero{0}; @@ -1456,7 +1456,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LoanBroker, tx, ripple); +BEAST_DEFINE_TESTSUITE(LoanBroker, tx, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index f7672fd380..22159ba4bb 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Loan_test : public beast::unit_test::suite @@ -964,7 +964,7 @@ protected: Number totalFeesPaid = 0; std::size_t totalPaymentsMade = 0; - ripple::LoanState currentTrueState = computeRawLoanState( + xrpl::LoanState currentTrueState = computeRawLoanState( state.periodicPayment, periodicRate, state.paymentRemaining, @@ -1019,7 +1019,7 @@ protected: paymentComponents.trackedInterestPart() + paymentComponents.trackedManagementFeeDelta); - ripple::LoanState const nextTrueState = computeRawLoanState( + xrpl::LoanState const nextTrueState = computeRawLoanState( state.periodicPayment, periodicRate, state.paymentRemaining - 1, @@ -2705,7 +2705,7 @@ protected: Number totalInterestPaid = 0; std::size_t totalPaymentsMade = 0; - ripple::LoanState currentTrueState = computeRawLoanState( + xrpl::LoanState currentTrueState = computeRawLoanState( state.periodicPayment, periodicRate, state.paymentRemaining, @@ -2730,7 +2730,7 @@ protected: paymentComponents.trackedValueDelta <= roundedPeriodicPayment); - ripple::LoanState const nextTrueState = computeRawLoanState( + xrpl::LoanState const nextTrueState = computeRawLoanState( state.periodicPayment, periodicRate, state.paymentRemaining - 1, @@ -3873,7 +3873,7 @@ protected: Serializer ss; ss.add32(HashPrefix::txSign); parse(randomData).addWithoutSigningFields(ss); - auto const sig = ripple::sign(borrower.pk(), borrower.sk(), ss.slice()); + auto const sig = xrpl::sign(borrower.pk(), borrower.sk(), ss.slice()); sigObject[jss::TxnSignature] = strHex(Slice{sig.data(), sig.size()}); forgedLoanSet[Json::StaticString{"CounterpartySignature"}] = sigObject; @@ -3957,7 +3957,7 @@ protected: testLoanPayComputePeriodicPaymentValidRateInvariant() { // From FIND-012 - testcase << "LoanPay ripple::detail::computePeriodicPayment : " + testcase << "LoanPay xrpl::detail::computePeriodicPayment : " "valid rate"; using namespace jtx; @@ -4773,7 +4773,7 @@ protected: testAccountSendMptMinAmountInvariant() { // (From FIND-006) - testcase << "LoanSet trigger ripple::accountSendMPT : minimum amount " + testcase << "LoanSet trigger xrpl::accountSendMPT : minimum amount " "and MPT"; using namespace jtx; @@ -4835,7 +4835,7 @@ protected: testLoanPayDebtDecreaseInvariant() { // From FIND-007 - testcase << "LoanPay ripple::LoanPay::doApply : debtDecrease " + testcase << "LoanPay xrpl::LoanPay::doApply : debtDecrease " "rounding good"; using namespace jtx; @@ -4940,7 +4940,7 @@ protected: testLoanPayComputePeriodicPaymentValidTotalInterestInvariant() { // From FIND-010 - testcase << "ripple::loanComputePaymentParts : valid total interest"; + testcase << "xrpl::loanComputePaymentParts : valid total interest"; using namespace jtx; using namespace std::chrono_literals; @@ -5093,7 +5093,7 @@ protected: testLoanPayComputePeriodicPaymentValidTotalPrincipalPaidInvariant() { // From FIND-009 - testcase << "ripple::loanComputePaymentParts : totalPrincipalPaid " + testcase << "xrpl::loanComputePaymentParts : totalPrincipalPaid " "rounded"; using namespace jtx; @@ -5207,7 +5207,7 @@ protected: testLoanPayComputePeriodicPaymentValidTotalInterestPaidInvariant() { // From FIND-008 - testcase << "ripple::loanComputePaymentParts : loanValueChange rounded"; + testcase << "xrpl::loanComputePaymentParts : loanValueChange rounded"; using namespace jtx; using namespace std::chrono_literals; @@ -7207,9 +7207,9 @@ class LoanArbitrary_test : public LoanBatch_test } }; -BEAST_DEFINE_TESTSUITE(Loan, tx, ripple); -BEAST_DEFINE_TESTSUITE_MANUAL(LoanBatch, tx, ripple); -BEAST_DEFINE_TESTSUITE_MANUAL(LoanArbitrary, tx, ripple); +BEAST_DEFINE_TESTSUITE(Loan, tx, xrpl); +BEAST_DEFINE_TESTSUITE_MANUAL(LoanBatch, tx, xrpl); +BEAST_DEFINE_TESTSUITE_MANUAL(LoanArbitrary, tx, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index 7d0126bd65..1de142c2ab 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class MPToken_test : public beast::unit_test::suite @@ -2349,7 +2349,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); auto const USD = alice["USD"]; - auto const mpt = ripple::test::jtx::MPT( + auto const mpt = xrpl::test::jtx::MPT( alice.name(), makeMptID(env.seq(alice), alice)); env(claw(alice, bob["USD"](5), bob), ter(temMALFORMED)); @@ -2372,7 +2372,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); auto const USD = alice["USD"]; - auto const mpt = ripple::test::jtx::MPT( + auto const mpt = xrpl::test::jtx::MPT( alice.name(), makeMptID(env.seq(alice), alice)); // clawing back IOU from a MPT holder fails @@ -2431,7 +2431,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); MPTTester mptAlice(env, alice, {.holders = {bob}}); - auto const fakeMpt = ripple::test::jtx::MPT( + auto const fakeMpt = xrpl::test::jtx::MPT( alice.name(), makeMptID(env.seq(alice), alice)); // issuer tries to clawback MPT where issuance doesn't exist @@ -2470,7 +2470,7 @@ class MPToken_test : public beast::unit_test::suite env.fund(XRP(1000), alice, bob); env.close(); - auto const mpt = ripple::test::jtx::MPT( + auto const mpt = xrpl::test::jtx::MPT( alice.name(), makeMptID(env.seq(alice), alice)); Json::Value jv = claw(alice, mpt(1), bob); @@ -3675,7 +3675,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(MPToken, app, ripple, 2); +BEAST_DEFINE_TESTSUITE_PRIO(MPToken, app, xrpl, 2); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Manifest_test.cpp b/src/test/app/Manifest_test.cpp index b2c8c859fd..09054658c9 100644 --- a/src/test/app/Manifest_test.cpp +++ b/src/test/app/Manifest_test.cpp @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Manifest_test : public beast::unit_test::suite @@ -1066,7 +1066,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Manifest, app, ripple); +BEAST_DEFINE_TESTSUITE(Manifest, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/MultiSign_test.cpp b/src/test/app/MultiSign_test.cpp index 126413d8d0..6e30ed9c13 100644 --- a/src/test/app/MultiSign_test.cpp +++ b/src/test/app/MultiSign_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class MultiSign_test : public beast::unit_test::suite @@ -1481,8 +1481,8 @@ public: uint8_t tag2[] = "hello world some ascii 32b long"; // including 1 byte for NUL - uint256 bogie_tag = ripple::base_uint<256>::fromVoid(tag1); - uint256 demon_tag = ripple::base_uint<256>::fromVoid(tag2); + uint256 bogie_tag = xrpl::base_uint<256>::fromVoid(tag1); + uint256 demon_tag = xrpl::base_uint<256>::fromVoid(tag2); // Attach phantom signers to alice and use them for a transaction. env(signers(alice, 1, {{bogie, 1, bogie_tag}, {demon, 1, demon_tag}})); @@ -1632,7 +1632,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(MultiSign, app, ripple); +BEAST_DEFINE_TESTSUITE(MultiSign, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/NFTokenAuth_test.cpp b/src/test/app/NFTokenAuth_test.cpp index b22a99ce73..dce8da0042 100644 --- a/src/test/app/NFTokenAuth_test.cpp +++ b/src/test/app/NFTokenAuth_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenAuth_test : public beast::unit_test::suite { @@ -600,6 +600,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(NFTokenAuth, app, ripple, 2); +BEAST_DEFINE_TESTSUITE_PRIO(NFTokenAuth, app, xrpl, 2); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/NFTokenBurn_test.cpp b/src/test/app/NFTokenBurn_test.cpp index 319cdba564..828539f4b1 100644 --- a/src/test/app/NFTokenBurn_test.cpp +++ b/src/test/app/NFTokenBurn_test.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenBurn_test : public beast::unit_test::suite { @@ -1259,6 +1259,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurn, app, ripple, 3); +BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBurn, app, xrpl, 3); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/NFTokenDir_test.cpp b/src/test/app/NFTokenDir_test.cpp index fdc488d5da..9718a5d073 100644 --- a/src/test/app/NFTokenDir_test.cpp +++ b/src/test/app/NFTokenDir_test.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenDir_test : public beast::unit_test::suite { @@ -1060,9 +1060,9 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(NFTokenDir, app, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(NFTokenDir, app, xrpl, 1); -} // namespace ripple +} // namespace xrpl // Seed that produces an account with the low-32 bits == 0xFFFFFFFF in // case it is needed for future testing: diff --git a/src/test/app/NFToken_test.cpp b/src/test/app/NFToken_test.cpp index 5ff0ac17ae..75bf59e70d 100644 --- a/src/test/app/NFToken_test.cpp +++ b/src/test/app/NFToken_test.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenBaseUtil_test : public beast::unit_test::suite { @@ -7639,10 +7639,10 @@ class NFTokenAllFeatures_test : public NFTokenBaseUtil_test } }; -BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBaseUtil, app, ripple, 2); -BEAST_DEFINE_TESTSUITE_PRIO(NFTokenDisallowIncoming, app, ripple, 2); -BEAST_DEFINE_TESTSUITE_PRIO(NFTokenWOMintOffer, app, ripple, 2); -BEAST_DEFINE_TESTSUITE_PRIO(NFTokenWOModify, app, ripple, 2); -BEAST_DEFINE_TESTSUITE_PRIO(NFTokenAllFeatures, app, ripple, 2); +BEAST_DEFINE_TESTSUITE_PRIO(NFTokenBaseUtil, app, xrpl, 2); +BEAST_DEFINE_TESTSUITE_PRIO(NFTokenDisallowIncoming, app, xrpl, 2); +BEAST_DEFINE_TESTSUITE_PRIO(NFTokenWOMintOffer, app, xrpl, 2); +BEAST_DEFINE_TESTSUITE_PRIO(NFTokenWOModify, app, xrpl, 2); +BEAST_DEFINE_TESTSUITE_PRIO(NFTokenAllFeatures, app, xrpl, 2); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/NetworkID_test.cpp b/src/test/app/NetworkID_test.cpp index 49ca453ebb..d924710cb3 100644 --- a/src/test/app/NetworkID_test.cpp +++ b/src/test/app/NetworkID_test.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class NetworkID_test : public beast::unit_test::suite @@ -142,7 +142,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(NetworkID, app, ripple); +BEAST_DEFINE_TESTSUITE(NetworkID, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/NetworkOPs_test.cpp b/src/test/app/NetworkOPs_test.cpp index 3965778221..d5616009fa 100644 --- a/src/test/app/NetworkOPs_test.cpp +++ b/src/test/app/NetworkOPs_test.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class NetworkOPs_test : public beast::unit_test::suite @@ -55,7 +55,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(NetworkOPs, app, ripple); +BEAST_DEFINE_TESTSUITE(NetworkOPs, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/OfferStream_test.cpp b/src/test/app/OfferStream_test.cpp index fac5ab18ab..218653a5d4 100644 --- a/src/test/app/OfferStream_test.cpp +++ b/src/test/app/OfferStream_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { class OfferStream_test : public beast::unit_test::suite { @@ -20,6 +20,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(OfferStream, app, ripple); +BEAST_DEFINE_TESTSUITE(OfferStream, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Offer_test.cpp b/src/test/app/Offer_test.cpp index 9cf8a7b1f2..1117510a45 100644 --- a/src/test/app/Offer_test.cpp +++ b/src/test/app/Offer_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class OfferBaseUtil_test : public beast::unit_test::suite @@ -5300,10 +5300,10 @@ class Offer_manual_test : public OfferBaseUtil_test } }; -BEAST_DEFINE_TESTSUITE_PRIO(OfferBaseUtil, app, ripple, 2); -BEAST_DEFINE_TESTSUITE_PRIO(OfferWOSmallQOffers, app, ripple, 2); -BEAST_DEFINE_TESTSUITE_PRIO(OfferAllFeatures, app, ripple, 2); -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Offer_manual, app, ripple, 20); +BEAST_DEFINE_TESTSUITE_PRIO(OfferBaseUtil, app, xrpl, 2); +BEAST_DEFINE_TESTSUITE_PRIO(OfferWOSmallQOffers, app, xrpl, 2); +BEAST_DEFINE_TESTSUITE_PRIO(OfferAllFeatures, app, xrpl, 2); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Offer_manual, app, xrpl, 20); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Oracle_test.cpp b/src/test/app/Oracle_test.cpp index 470bcd7950..6708f56275 100644 --- a/src/test/app/Oracle_test.cpp +++ b/src/test/app/Oracle_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { namespace oracle { @@ -865,7 +865,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Oracle, app, ripple); +BEAST_DEFINE_TESTSUITE(Oracle, app, xrpl); } // namespace oracle @@ -873,4 +873,4 @@ BEAST_DEFINE_TESTSUITE(Oracle, app, ripple); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/OversizeMeta_test.cpp b/src/test/app/OversizeMeta_test.cpp index dbb5310e01..2eb300b095 100644 --- a/src/test/app/OversizeMeta_test.cpp +++ b/src/test/app/OversizeMeta_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { // Make sure "plump" order books don't have problems @@ -42,7 +42,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(PlumpBook, app, ripple, 5); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(PlumpBook, app, xrpl, 5); //------------------------------------------------------------------------------ @@ -57,7 +57,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ThinBook, app, ripple); +BEAST_DEFINE_TESTSUITE(ThinBook, app, xrpl); //------------------------------------------------------------------------------ @@ -100,7 +100,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(OversizeMeta, app, ripple, 3); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(OversizeMeta, app, xrpl, 3); //------------------------------------------------------------------------------ @@ -166,7 +166,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(FindOversizeCross, app, ripple, 50); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(FindOversizeCross, app, xrpl, 50); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Path_test.cpp b/src/test/app/Path_test.cpp index e481bd673b..8a80ecd6d8 100644 --- a/src/test/app/Path_test.cpp +++ b/src/test/app/Path_test.cpp @@ -23,7 +23,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { //------------------------------------------------------------------------------ @@ -2114,7 +2114,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Path, app, ripple); +BEAST_DEFINE_TESTSUITE(Path, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index 3f350626ea..20a433b5dd 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { using namespace jtx::paychan; @@ -1772,14 +1772,14 @@ struct PayChan_test : public beast::unit_test::suite auto inOwnerDir = [](ReadView const& view, Account const& acc, std::shared_ptr const& chan) -> bool { - ripple::Dir const ownerDir(view, keylet::ownerDir(acc.id())); + xrpl::Dir const ownerDir(view, keylet::ownerDir(acc.id())); return std::find(ownerDir.begin(), ownerDir.end(), chan) != ownerDir.end(); }; auto ownerDirCount = [](ReadView const& view, Account const& acc) -> std::size_t { - ripple::Dir const ownerDir(view, keylet::ownerDir(acc.id())); + xrpl::Dir const ownerDir(view, keylet::ownerDir(acc.id())); return std::distance(ownerDir.begin(), ownerDir.end()); }; @@ -2119,6 +2119,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(PayChan, app, ripple); +BEAST_DEFINE_TESTSUITE(PayChan, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/PayStrand_test.cpp b/src/test/app/PayStrand_test.cpp index 7f8f49ec07..8e0ff337b4 100644 --- a/src/test/app/PayStrand_test.cpp +++ b/src/test/app/PayStrand_test.cpp @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { struct DirectStepInfo @@ -86,7 +86,7 @@ equal(std::unique_ptr const& s1, XRPEndpointStepInfo const& xrpsi) } bool -equal(std::unique_ptr const& s1, ripple::Book const& bsi) +equal(std::unique_ptr const& s1, xrpl::Book const& bsi) { if (!s1) return false; @@ -300,7 +300,7 @@ public: struct ExistingElementPool { std::vector accounts; - std::vector currencies; + std::vector currencies; std::vector currencyNames; jtx::Account @@ -310,7 +310,7 @@ struct ExistingElementPool return accounts[id]; } - ripple::Currency + xrpl::Currency getCurrency(size_t id) { assert(id < currencies.size()); @@ -484,13 +484,13 @@ struct ExistingElementPool { std::vector> diffs; - auto xrpBalance = [](ReadView const& v, ripple::Keylet const& k) { + auto xrpBalance = [](ReadView const& v, xrpl::Keylet const& k) { auto const sle = v.read(k); if (!sle) return STAmount{}; return (*sle)[sfBalance]; }; - auto lineBalance = [](ReadView const& v, ripple::Keylet const& k) { + auto lineBalance = [](ReadView const& v, xrpl::Keylet const& k) { auto const sle = v.read(k); if (!sle) return STAmount{}; @@ -534,7 +534,7 @@ struct ExistingElementPool return getAccount(nextAvailAccount++); } - ripple::Currency + xrpl::Currency getAvailCurrency() { return getCurrency(nextAvailCurrency++); @@ -619,7 +619,7 @@ struct PayStrand_test : public beast::unit_test::suite auto const usdC = USD.currency; using D = DirectStepInfo; - using B = ripple::Book; + using B = xrpl::Book; using XRPS = XRPEndpointStepInfo; AMMContext ammContext(alice, false); @@ -1182,13 +1182,13 @@ struct PayStrand_test : public beast::unit_test::suite AccountID const srcAcc = alice.id(); AccountID dstAcc = bob.id(); STPathSet pathSet; - ::ripple::path::RippleCalc::Input inputs; + ::xrpl::path::RippleCalc::Input inputs; inputs.defaultPathsAllowed = true; try { PaymentSandbox sb{env.current().get(), tapNONE}; { - auto const r = ::ripple::path::RippleCalc::rippleCalculate( + auto const r = ::xrpl::path::RippleCalc::rippleCalculate( sb, sendMax, deliver, @@ -1201,7 +1201,7 @@ struct PayStrand_test : public beast::unit_test::suite BEAST_EXPECT(r.result() == temBAD_PATH); } { - auto const r = ::ripple::path::RippleCalc::rippleCalculate( + auto const r = ::xrpl::path::RippleCalc::rippleCalculate( sb, sendMax, deliver, @@ -1214,7 +1214,7 @@ struct PayStrand_test : public beast::unit_test::suite BEAST_EXPECT(r.result() == temBAD_PATH); } { - auto const r = ::ripple::path::RippleCalc::rippleCalculate( + auto const r = ::xrpl::path::RippleCalc::rippleCalculate( sb, noAccountAmount, deliver, @@ -1227,7 +1227,7 @@ struct PayStrand_test : public beast::unit_test::suite BEAST_EXPECT(r.result() == temBAD_PATH); } { - auto const r = ::ripple::path::RippleCalc::rippleCalculate( + auto const r = ::xrpl::path::RippleCalc::rippleCalculate( sb, sendMax, noAccountAmount, @@ -1264,7 +1264,7 @@ struct PayStrand_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(PayStrand, app, ripple); +BEAST_DEFINE_TESTSUITE(PayStrand, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/PermissionedDEX_test.cpp b/src/test/app/PermissionedDEX_test.cpp index 4b7a1db1be..b5db131db6 100644 --- a/src/test/app/PermissionedDEX_test.cpp +++ b/src/test/app/PermissionedDEX_test.cpp @@ -28,7 +28,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { using namespace jtx; @@ -1552,7 +1552,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(PermissionedDEX, app, ripple); +BEAST_DEFINE_TESTSUITE(PermissionedDEX, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/PermissionedDomains_test.cpp b/src/test/app/PermissionedDomains_test.cpp index ba1946ee66..a7dff84cff 100644 --- a/src/test/app/PermissionedDomains_test.cpp +++ b/src/test/app/PermissionedDomains_test.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { using namespace jtx; @@ -560,7 +560,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(PermissionedDomains, app, ripple); +BEAST_DEFINE_TESTSUITE(PermissionedDomains, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/PseudoTx_test.cpp b/src/test/app/PseudoTx_test.cpp index ea53b0bee5..f01ba616c8 100644 --- a/src/test/app/PseudoTx_test.cpp +++ b/src/test/app/PseudoTx_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct PseudoTx_test : public beast::unit_test::suite @@ -76,7 +76,7 @@ struct PseudoTx_test : public beast::unit_test::suite env.app().openLedger().modify( [&](OpenView& view, beast::Journal j) { auto const result = - ripple::apply(env.app(), view, stx, tapNONE, j); + xrpl::apply(env.app(), view, stx, tapNONE, j); BEAST_EXPECT(!result.applied && result.ter == temINVALID); return result.applied; }); @@ -107,7 +107,7 @@ struct PseudoTx_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(PseudoTx, app, ripple); +BEAST_DEFINE_TESTSUITE(PseudoTx, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/RCLValidations_test.cpp b/src/test/app/RCLValidations_test.cpp index 2d3c4f2af5..a4f0d6a7cb 100644 --- a/src/test/app/RCLValidations_test.cpp +++ b/src/test/app/RCLValidations_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class RCLValidations_test : public beast::unit_test::suite @@ -17,7 +17,7 @@ class RCLValidations_test : public beast::unit_test::suite testcase("Change validation trusted status"); auto keys = randomKeyPair(KeyType::secp256k1); auto v = std::make_shared( - ripple::NetClock::time_point{}, + xrpl::NetClock::time_point{}, keys.first, keys.second, calcNodeID(keys.first), @@ -308,7 +308,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(RCLValidations, app, ripple); +BEAST_DEFINE_TESTSUITE(RCLValidations, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/ReducedOffer_test.cpp b/src/test/app/ReducedOffer_test.cpp index f511721dda..8a395913b2 100644 --- a/src/test/app/ReducedOffer_test.cpp +++ b/src/test/app/ReducedOffer_test.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class ReducedOffer_test : public beast::unit_test::suite @@ -719,7 +719,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(ReducedOffer, app, ripple, 2); +BEAST_DEFINE_TESTSUITE_PRIO(ReducedOffer, app, xrpl, 2); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Regression_test.cpp b/src/test/app/Regression_test.cpp index be51d9c96e..56f0de9e07 100644 --- a/src/test/app/Regression_test.cpp +++ b/src/test/app/Regression_test.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct Regression_test : public beast::unit_test::suite @@ -63,7 +63,7 @@ struct Regression_test : public beast::unit_test::suite OpenView accum(&*next); auto const result = - ripple::apply(env.app(), accum, *jt.stx, tapNONE, env.journal); + xrpl::apply(env.app(), accum, *jt.stx, tapNONE, env.journal); BEAST_EXPECT(result.ter == tesSUCCESS); BEAST_EXPECT(result.applied); @@ -87,7 +87,7 @@ struct Regression_test : public beast::unit_test::suite OpenView accum(&*next); auto const result = - ripple::apply(env.app(), accum, *jt.stx, tapNONE, env.journal); + xrpl::apply(env.app(), accum, *jt.stx, tapNONE, env.journal); BEAST_EXPECT(result.ter == tecINSUFF_FEE); BEAST_EXPECT(result.applied); @@ -323,7 +323,7 @@ struct Regression_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(Regression, app, ripple); +BEAST_DEFINE_TESTSUITE(Regression, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/SHAMapStore_test.cpp b/src/test/app/SHAMapStore_test.cpp index 8ec5a6fd23..d9689dc977 100644 --- a/src/test/app/SHAMapStore_test.cpp +++ b/src/test/app/SHAMapStore_test.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class SHAMapStore_test : public beast::unit_test::suite @@ -637,7 +637,7 @@ public: }; // VFALCO This test fails because of thread asynchronous issues -BEAST_DEFINE_TESTSUITE(SHAMapStore, app, ripple); +BEAST_DEFINE_TESTSUITE(SHAMapStore, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/SetAuth_test.cpp b/src/test/app/SetAuth_test.cpp index 42766c87ff..29f1e46ca4 100644 --- a/src/test/app/SetAuth_test.cpp +++ b/src/test/app/SetAuth_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct SetAuth_test : public beast::unit_test::suite @@ -61,7 +61,7 @@ struct SetAuth_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(SetAuth, app, ripple); +BEAST_DEFINE_TESTSUITE(SetAuth, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/SetRegularKey_test.cpp b/src/test/app/SetRegularKey_test.cpp index 2065066ec3..308e5527f7 100644 --- a/src/test/app/SetRegularKey_test.cpp +++ b/src/test/app/SetRegularKey_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { class SetRegularKey_test : public beast::unit_test::suite { @@ -169,6 +169,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(SetRegularKey, app, ripple); +BEAST_DEFINE_TESTSUITE(SetRegularKey, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/SetTrust_test.cpp b/src/test/app/SetTrust_test.cpp index 07573cf13f..f8309c4271 100644 --- a/src/test/app/SetTrust_test.cpp +++ b/src/test/app/SetTrust_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -618,6 +618,6 @@ public: testWithFeats(sa); } }; -BEAST_DEFINE_TESTSUITE(SetTrust, app, ripple); +BEAST_DEFINE_TESTSUITE(SetTrust, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/TheoreticalQuality_test.cpp b/src/test/app/TheoreticalQuality_test.cpp index fe59ac6b1a..5cc03247ae 100644 --- a/src/test/app/TheoreticalQuality_test.cpp +++ b/src/test/app/TheoreticalQuality_test.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct RippleCalcTestParams @@ -533,7 +533,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(TheoreticalQuality, app, ripple, 3); +BEAST_DEFINE_TESTSUITE_PRIO(TheoreticalQuality, app, xrpl, 3); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Ticket_test.cpp b/src/test/app/Ticket_test.cpp index 4c3208af02..3136699103 100644 --- a/src/test/app/Ticket_test.cpp +++ b/src/test/app/Ticket_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class Ticket_test : public beast::unit_test::suite { @@ -908,6 +908,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Ticket, app, ripple); +BEAST_DEFINE_TESTSUITE(Ticket, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Transaction_ordering_test.cpp b/src/test/app/Transaction_ordering_test.cpp index 2f67d8b414..81c9ae196c 100644 --- a/src/test/app/Transaction_ordering_test.cpp +++ b/src/test/app/Transaction_ordering_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { struct Transaction_ordering_test : public beast::unit_test::suite @@ -143,7 +143,7 @@ struct Transaction_ordering_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(Transaction_ordering, app, ripple); +BEAST_DEFINE_TESTSUITE(Transaction_ordering, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/TrustAndBalance_test.cpp b/src/test/app/TrustAndBalance_test.cpp index 6cad68d584..25c22b823b 100644 --- a/src/test/app/TrustAndBalance_test.cpp +++ b/src/test/app/TrustAndBalance_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class TrustAndBalance_test : public beast::unit_test::suite { @@ -467,6 +467,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(TrustAndBalance, app, ripple); +BEAST_DEFINE_TESTSUITE(TrustAndBalance, app, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index 0af91f25a6..3e19fc2842 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -99,7 +99,7 @@ class TxQPosNegFlows_test : public beast::unit_test::suite // fee (1) and amendment (numUpVotedAmendments()) // pseudotransactions. The queue treats the fees on these // transactions as though they are ordinary transactions. - auto const flagPerLedger = 1 + ripple::detail::numUpVotedAmendments(); + auto const flagPerLedger = 1 + xrpl::detail::numUpVotedAmendments(); auto const flagMaxQueue = ledgersInQueue * flagPerLedger; checkMetrics(*this, env, 0, flagMaxQueue, 0, flagPerLedger); @@ -977,13 +977,13 @@ public: Env::ParsedResult parsed; - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) { - auto const result = ripple::apply( - env.app(), view, *jt.stx, tapNONE, env.journal); - parsed.ter = result.ter; - return result.applied; - }); + env.app().openLedger().modify([&](OpenView& view, + beast::Journal j) { + auto const result = + xrpl::apply(env.app(), view, *jt.stx, tapNONE, env.journal); + parsed.ter = result.ter; + return result.applied; + }); env.postconditions(jt, parsed); } checkMetrics(*this, env, 1, std::nullopt, 4, 2); @@ -4191,7 +4191,7 @@ public: auto const tx = env.jt(noop(alice), seq(aliceSeq), fee(openLedgerCost(env))); auto const result = - ripple::apply(env.app(), view, *tx.stx, tapUNLIMITED, j); + xrpl::apply(env.app(), view, *tx.stx, tapUNLIMITED, j); BEAST_EXPECT(result.ter == tesSUCCESS && result.applied); return result.applied; }); @@ -4263,7 +4263,7 @@ public: ticket::use(tktSeq0 + 1), fee(openLedgerCost(env))); auto const result = - ripple::apply(env.app(), view, *tx.stx, tapUNLIMITED, j); + xrpl::apply(env.app(), view, *tx.stx, tapUNLIMITED, j); BEAST_EXPECT(result.ter == tesSUCCESS && result.applied); return result.applied; }); @@ -4371,7 +4371,7 @@ public: if (!getMajorityAmendments(*env.closed()).empty()) break; } - auto expectedPerLedger = ripple::detail::numUpVotedAmendments() + 1; + auto expectedPerLedger = xrpl::detail::numUpVotedAmendments() + 1; checkMetrics( *this, env, @@ -5052,8 +5052,8 @@ class TxQMetaInfo_test : public TxQPosNegFlows_test } }; -BEAST_DEFINE_TESTSUITE_PRIO(TxQPosNegFlows, app, ripple, 1); -BEAST_DEFINE_TESTSUITE_PRIO(TxQMetaInfo, app, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(TxQPosNegFlows, app, xrpl, 1); +BEAST_DEFINE_TESTSUITE_PRIO(TxQMetaInfo, app, xrpl, 1); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/ValidatorKeys_test.cpp b/src/test/app/ValidatorKeys_test.cpp index 9770d6a0ff..943bf5231f 100644 --- a/src/test/app/ValidatorKeys_test.cpp +++ b/src/test/app/ValidatorKeys_test.cpp @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class ValidatorKeys_test : public beast::unit_test::suite @@ -171,7 +171,7 @@ public: } }; // namespace test -BEAST_DEFINE_TESTSUITE(ValidatorKeys, app, ripple); +BEAST_DEFINE_TESTSUITE(ValidatorKeys, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/ValidatorList_test.cpp b/src/test/app/ValidatorList_test.cpp index 2f88f0ea1e..163e4f632c 100644 --- a/src/test/app/ValidatorList_test.cpp +++ b/src/test/app/ValidatorList_test.cpp @@ -16,7 +16,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class ValidatorList_test : public beast::unit_test::suite @@ -2294,7 +2294,7 @@ private: { testcase("Sha512 hashing"); // Tests that ValidatorList hash_append helpers with a single blob - // returns the same result as ripple::Sha512Half used by the + // returns the same result as xrpl::Sha512Half used by the // TMValidatorList protocol message handler std::string const manifest = "This is not really a manifest"; std::string const blob = "This is not really a blob"; @@ -4145,7 +4145,7 @@ public: } }; // namespace test -BEAST_DEFINE_TESTSUITE(ValidatorList, app, ripple); +BEAST_DEFINE_TESTSUITE(ValidatorList, app, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/ValidatorSite_test.cpp b/src/test/app/ValidatorSite_test.cpp index be8ae8013f..71a5b7fa73 100644 --- a/src/test/app/ValidatorSite_test.cpp +++ b/src/test/app/ValidatorSite_test.cpp @@ -17,7 +17,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { constexpr char const* realValidatorContents() @@ -688,7 +688,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(ValidatorSite, app, ripple, 2); +BEAST_DEFINE_TESTSUITE_PRIO(ValidatorSite, app, xrpl, 2); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index a07045743e..fbe87ccb5d 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -29,12 +29,12 @@ #include -namespace ripple { +namespace xrpl { class Vault_test : public beast::unit_test::suite { - using PrettyAsset = ripple::test::jtx::PrettyAsset; - using PrettyAmount = ripple::test::jtx::PrettyAmount; + using PrettyAsset = xrpl::test::jtx::PrettyAsset; + using PrettyAmount = xrpl::test::jtx::PrettyAmount; static auto constexpr negativeAmount = [](PrettyAsset const& asset) -> PrettyAmount { @@ -2223,7 +2223,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - auto const issuanceId = [&env](ripple::Keylet keylet) -> MPTID { + auto const issuanceId = [&env](xrpl::Keylet keylet) -> MPTID { auto const vault = env.le(keylet); return vault->at(sfShareMPTID); }(keylet); @@ -2555,10 +2555,10 @@ class Vault_test : public beast::unit_test::suite Account const& owner, Account const& issuer, Account const& charlie, - std::function vaultAccount, + std::function vaultAccount, Vault& vault, PrettyAsset const& asset, - std::function issuanceId)> test, + std::function issuanceId)> test, CaseArgs args = {}) { Env env{*this, testable_amendments() | featureSingleAssetVault}; Account const owner{"owner"}; @@ -2590,10 +2590,10 @@ class Vault_test : public beast::unit_test::suite env.close(); auto const vaultAccount = - [&env](ripple::Keylet keylet) -> Account { + [&env](xrpl::Keylet keylet) -> Account { return Account("vault", env.le(keylet)->at(sfAccount)); }; - auto const issuanceId = [&env](ripple::Keylet keylet) -> MPTID { + auto const issuanceId = [&env](xrpl::Keylet keylet) -> MPTID { return env.le(keylet)->at(sfShareMPTID); }; @@ -2843,7 +2843,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // Withdraw to 3rd party works - auto const withdrawToCharlie = [&](ripple::Keylet keylet) { + auto const withdrawToCharlie = [&](xrpl::Keylet keylet) { auto tx = vault.withdraw( {.depositor = owner, .id = keylet.key, @@ -2914,7 +2914,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // Withdraw to 3rd party without trust line - auto const tx1 = [&](ripple::Keylet keylet) { + auto const tx1 = [&](xrpl::Keylet keylet) { auto tx = vault.withdraw( {.depositor = owner, .id = keylet.key, @@ -2953,7 +2953,7 @@ class Vault_test : public beast::unit_test::suite BEAST_EXPECT(trustline == nullptr); // Withdraw without trust line, will succeed - auto const tx1 = [&](ripple::Keylet keylet) { + auto const tx1 = [&](xrpl::Keylet keylet) { auto tx = vault.withdraw( {.depositor = owner, .id = keylet.key, @@ -2972,7 +2972,7 @@ class Vault_test : public beast::unit_test::suite auto vaultAccount, Vault& vault, PrettyAsset const& asset, - std::function issuanceId) { + std::function issuanceId) { testcase("IOU non-transferable"); auto [tx, keylet] = @@ -3250,7 +3250,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // Withdraw to 3rd party works - auto const withdrawToCharlie = [&](ripple::Keylet keylet) { + auto const withdrawToCharlie = [&](xrpl::Keylet keylet) { auto tx = vault.withdraw( {.depositor = owner, .id = keylet.key, @@ -3755,7 +3755,7 @@ class Vault_test : public beast::unit_test::suite for (int i = 0; i < 256; ++i) { AccountID const accountId = - ripple::pseudoAccountAddress(*env.current(), keylet.key); + xrpl::pseudoAccountAddress(*env.current(), keylet.key); env(pay(env.master.id(), accountId, XRP(1000)), seq(autofill), @@ -3783,7 +3783,7 @@ class Vault_test : public beast::unit_test::suite MPTIssue shares; PrettyAsset const& share; Vault& vault; - ripple::Keylet keylet; + xrpl::Keylet keylet; Issue assets; PrettyAsset const& asset; std::function)> peek; @@ -3813,7 +3813,7 @@ class Vault_test : public beast::unit_test::suite env(tx); auto const [vaultAccount, issuanceId] = - [&env](ripple::Keylet keylet) -> std::tuple { + [&env](xrpl::Keylet keylet) -> std::tuple { auto const vault = env.le(keylet); return { Account("vault", vault->at(sfAccount)), @@ -5264,6 +5264,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(Vault, app, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(Vault, app, xrpl, 1); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/app/XChain_test.cpp b/src/test/app/XChain_test.cpp index 158d913f46..619054b078 100644 --- a/src/test/app/XChain_test.cpp +++ b/src/test/app/XChain_test.cpp @@ -23,7 +23,7 @@ #include #include -namespace ripple::test { +namespace xrpl::test { // SEnv class - encapsulate jtx::Env to make it more user-friendly, // for example having APIs that return a *this reference so that calls can be @@ -5171,7 +5171,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(XChain, app, ripple); -BEAST_DEFINE_TESTSUITE(XChainSim, app, ripple); +BEAST_DEFINE_TESTSUITE(XChain, app, xrpl); +BEAST_DEFINE_TESTSUITE(XChainSim, app, xrpl); -} // namespace ripple::test +} // namespace xrpl::test diff --git a/src/test/app/tx/apply_test.cpp b/src/test/app/tx/apply_test.cpp index 308ad3d3b8..0b198dcd22 100644 --- a/src/test/app/tx/apply_test.cpp +++ b/src/test/app/tx/apply_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class Apply_test : public beast::unit_test::suite { @@ -53,6 +53,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Apply, tx, ripple); +BEAST_DEFINE_TESTSUITE(Apply, tx, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/Buffer_test.cpp b/src/test/basics/Buffer_test.cpp index f734741e0f..cb3c48484b 100644 --- a/src/test/basics/Buffer_test.cpp +++ b/src/test/basics/Buffer_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct Buffer_test : beast::unit_test::suite @@ -261,7 +261,7 @@ struct Buffer_test : beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(Buffer, basics, ripple); +BEAST_DEFINE_TESTSUITE(Buffer, basics, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/DetectCrash_test.cpp b/src/test/basics/DetectCrash_test.cpp index e2f7d39921..0dd2787dff 100644 --- a/src/test/basics/DetectCrash_test.cpp +++ b/src/test/basics/DetectCrash_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { struct DetectCrash_test : public beast::unit_test::suite @@ -25,4 +25,4 @@ struct DetectCrash_test : public beast::unit_test::suite BEAST_DEFINE_TESTSUITE_MANUAL(DetectCrash, basics, beast); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/Expected_test.cpp b/src/test/basics/Expected_test.cpp index 173e8302aa..010a6fbb8e 100644 --- a/src/test/basics/Expected_test.cpp +++ b/src/test/basics/Expected_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct Expected_test : beast::unit_test::suite @@ -224,7 +224,7 @@ struct Expected_test : beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(Expected, basics, ripple); +BEAST_DEFINE_TESTSUITE(Expected, basics, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/FileUtilities_test.cpp b/src/test/basics/FileUtilities_test.cpp index d3e70911b8..c655e4d1bc 100644 --- a/src/test/basics/FileUtilities_test.cpp +++ b/src/test/basics/FileUtilities_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class FileUtilities_test : public beast::unit_test::suite { @@ -12,7 +12,7 @@ public: void testGetFileContents() { - using namespace ripple::detail; + using namespace xrpl::detail; using namespace boost::system; constexpr char const* expectedContents = @@ -60,6 +60,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(FileUtilities, basics, ripple); +BEAST_DEFINE_TESTSUITE(FileUtilities, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/IOUAmount_test.cpp b/src/test/basics/IOUAmount_test.cpp index dd6389ed81..305f2c83a1 100644 --- a/src/test/basics/IOUAmount_test.cpp +++ b/src/test/basics/IOUAmount_test.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { class IOUAmount_test : public beast::unit_test::suite { @@ -239,7 +239,7 @@ public: IOUAmount big(maxMantissa, maxExponent); except([&] { mulRatio(big, 2, 0, true); }); } - } // namespace ripple + } // namespace xrpl //-------------------------------------------------------------------------- @@ -255,6 +255,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(IOUAmount, basics, ripple); +BEAST_DEFINE_TESTSUITE(IOUAmount, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/IntrusiveShared_test.cpp b/src/test/basics/IntrusiveShared_test.cpp index a3acc54d45..d5d5d75048 100644 --- a/src/test/basics/IntrusiveShared_test.cpp +++ b/src/test/basics/IntrusiveShared_test.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace tests { /** @@ -887,6 +887,6 @@ public: } }; // namespace tests -BEAST_DEFINE_TESTSUITE(IntrusiveShared, basics, ripple); +BEAST_DEFINE_TESTSUITE(IntrusiveShared, basics, xrpl); } // namespace tests -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/KeyCache_test.cpp b/src/test/basics/KeyCache_test.cpp index 3ba642682a..55b275ae09 100644 --- a/src/test/basics/KeyCache_test.cpp +++ b/src/test/basics/KeyCache_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class KeyCache_test : public beast::unit_test::suite { @@ -74,6 +74,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(KeyCache, basics, ripple); +BEAST_DEFINE_TESTSUITE(KeyCache, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/Number_test.cpp b/src/test/basics/Number_test.cpp index bb5262d028..b7c5ee45b7 100644 --- a/src/test/basics/Number_test.cpp +++ b/src/test/basics/Number_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class Number_test : public beast::unit_test::suite { @@ -859,6 +859,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Number, basics, ripple); +BEAST_DEFINE_TESTSUITE(Number, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/PerfLog_test.cpp b/src/test/basics/PerfLog_test.cpp index dcb91d0fd3..06944bb5ce 100644 --- a/src/test/basics/PerfLog_test.cpp +++ b/src/test/basics/PerfLog_test.cpp @@ -18,7 +18,7 @@ //------------------------------------------------------------------------------ -namespace ripple { +namespace xrpl { class PerfLog_test : public beast::unit_test::suite { @@ -293,7 +293,7 @@ public: // Get the all the labels we can use for RPC interfaces without // causing an assert. std::vector labels = - test::jtx::make_vector(ripple::RPC::getHandlerNames()); + test::jtx::make_vector(xrpl::RPC::getHandlerNames()); std::shuffle(labels.begin(), labels.end(), default_prng()); // Get two IDs to associate with each label. Errors tend to happen at @@ -1042,6 +1042,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(PerfLog, basics, ripple); +BEAST_DEFINE_TESTSUITE(PerfLog, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/StringUtilities_test.cpp b/src/test/basics/StringUtilities_test.cpp index 319eafe920..ec993b20c3 100644 --- a/src/test/basics/StringUtilities_test.cpp +++ b/src/test/basics/StringUtilities_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { class StringUtilities_test : public beast::unit_test::suite { @@ -303,6 +303,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(StringUtilities, basics, ripple); +BEAST_DEFINE_TESTSUITE(StringUtilities, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/TaggedCache_test.cpp b/src/test/basics/TaggedCache_test.cpp index be0eb5d77b..78dc25380b 100644 --- a/src/test/basics/TaggedCache_test.cpp +++ b/src/test/basics/TaggedCache_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /* I guess you can put some items in, make sure they're still there. Let some @@ -132,6 +132,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(TaggedCache, basics, ripple); +BEAST_DEFINE_TESTSUITE(TaggedCache, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/Units_test.cpp b/src/test/basics/Units_test.cpp index 7838926c87..d0193320bf 100644 --- a/src/test/basics/Units_test.cpp +++ b/src/test/basics/Units_test.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class units_test : public beast::unit_test::suite @@ -353,7 +353,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(units, basics, ripple); +BEAST_DEFINE_TESTSUITE(units, basics, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/XRPAmount_test.cpp b/src/test/basics/XRPAmount_test.cpp index a63f3bfd43..da03a3533f 100644 --- a/src/test/basics/XRPAmount_test.cpp +++ b/src/test/basics/XRPAmount_test.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { class XRPAmount_test : public beast::unit_test::suite { @@ -308,7 +308,7 @@ public: XRPAmount bigNegative(minXRP + 10); BEAST_EXPECT(mulRatio(bigNegative, 2, 1, true) == minXRP); } - } // namespace ripple + } // namespace xrpl //-------------------------------------------------------------------------- @@ -325,6 +325,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(XRPAmount, basics, ripple); +BEAST_DEFINE_TESTSUITE(XRPAmount, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/base58_test.cpp b/src/test/basics/base58_test.cpp index 1700255df6..16307bdb0f 100644 --- a/src/test/basics/base58_test.cpp +++ b/src/test/basics/base58_test.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace { @@ -30,13 +30,13 @@ randEngine() -> std::mt19937& constexpr int numTokenTypeIndexes = 9; [[nodiscard]] inline auto -tokenTypeAndSize(int i) -> std::tuple +tokenTypeAndSize(int i) -> std::tuple { assert(i < numTokenTypeIndexes); switch (i) { - using enum ripple::TokenType; + using enum xrpl::TokenType; case 0: return {None, 20}; case 1: @@ -63,9 +63,9 @@ tokenTypeAndSize(int i) -> std::tuple } [[nodiscard]] inline auto -randomTokenTypeAndSize() -> std::tuple +randomTokenTypeAndSize() -> std::tuple { - using namespace ripple; + using namespace xrpl; auto& rng = randEngine(); std::uniform_int_distribution<> d(0, 8); return tokenTypeAndSize(d(rng)); @@ -74,7 +74,7 @@ randomTokenTypeAndSize() -> std::tuple // Return the token type and subspan of `d` to use as test data. [[nodiscard]] inline auto randomB256TestData(std::span d) - -> std::tuple> + -> std::tuple> { auto& rng = randEngine(); std::uniform_int_distribution dist(0, 255); @@ -267,7 +267,7 @@ class base58_test : public beast::unit_test::suite std::span const outBuf{b58ResultBuf[i]}; if (i == 0) { - auto const r = ripple::b58_fast::detail::b256_to_b58_be( + auto const r = xrpl::b58_fast::detail::b256_to_b58_be( b256Data, outBuf); BEAST_EXPECT(r); b58Result[i] = r.value(); @@ -275,7 +275,7 @@ class base58_test : public beast::unit_test::suite else { std::array tmpBuf; - std::string const s = ripple::b58_ref::detail::encodeBase58( + std::string const s = xrpl::b58_ref::detail::encodeBase58( b256Data.data(), b256Data.size(), tmpBuf.data(), @@ -307,7 +307,7 @@ class base58_test : public beast::unit_test::suite b58Result[i].data(), b58Result[i].data() + b58Result[i].size()); auto const r = - ripple::b58_fast::detail::b58_to_b256_be(in, outBuf); + xrpl::b58_fast::detail::b58_to_b256_be(in, outBuf); BEAST_EXPECT(r); b256Result[i] = r.value(); } @@ -316,7 +316,7 @@ class base58_test : public beast::unit_test::suite std::string const st( b58Result[i].begin(), b58Result[i].end()); std::string const s = - ripple::b58_ref::detail::decodeBase58(st); + xrpl::b58_ref::detail::decodeBase58(st); BEAST_EXPECT(s.size()); b256Result[i] = outBuf.subspan(0, s.size()); std::copy(s.begin(), s.end(), b256Result[i].begin()); @@ -336,7 +336,7 @@ class base58_test : public beast::unit_test::suite } }; - auto testTokenEncode = [&](ripple::TokenType const tokType, + auto testTokenEncode = [&](xrpl::TokenType const tokType, std::span const& b256Data) { std::array b58ResultBuf[2]; std::array, 2> b58Result; @@ -349,14 +349,14 @@ class base58_test : public beast::unit_test::suite b58ResultBuf[i].data(), b58ResultBuf[i].size()}; if (i == 0) { - auto const r = ripple::b58_fast::encodeBase58Token( + auto const r = xrpl::b58_fast::encodeBase58Token( tokType, b256Data, outBuf); BEAST_EXPECT(r); b58Result[i] = r.value(); } else { - std::string const s = ripple::b58_ref::encodeBase58Token( + std::string const s = xrpl::b58_ref::encodeBase58Token( tokType, b256Data.data(), b256Data.size()); BEAST_EXPECT(s.size()); b58Result[i] = outBuf.subspan(0, s.size()); @@ -384,8 +384,8 @@ class base58_test : public beast::unit_test::suite std::string const in( b58Result[i].data(), b58Result[i].data() + b58Result[i].size()); - auto const r = ripple::b58_fast::decodeBase58Token( - tokType, in, outBuf); + auto const r = + xrpl::b58_fast::decodeBase58Token(tokType, in, outBuf); BEAST_EXPECT(r); b256Result[i] = r.value(); } @@ -394,7 +394,7 @@ class base58_test : public beast::unit_test::suite std::string const st( b58Result[i].begin(), b58Result[i].end()); std::string const s = - ripple::b58_ref::decodeBase58Token(st, tokType); + xrpl::b58_ref::decodeBase58Token(st, tokType); BEAST_EXPECT(s.size()); b256Result[i] = outBuf.subspan(0, s.size()); std::copy(s.begin(), s.end(), b256Result[i].begin()); @@ -414,7 +414,7 @@ class base58_test : public beast::unit_test::suite } }; - auto testIt = [&](ripple::TokenType const tokType, + auto testIt = [&](xrpl::TokenType const tokType, std::span const& b256Data) { testRawEncode(b256Data); testTokenEncode(tokType, b256Data); @@ -451,8 +451,8 @@ class base58_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(base58, basics, ripple); +BEAST_DEFINE_TESTSUITE(base58, basics, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl #endif // _MSC_VER diff --git a/src/test/basics/base_uint_test.cpp b/src/test/basics/base_uint_test.cpp index 0308fb4466..8f764fd58b 100644 --- a/src/test/basics/base_uint_test.cpp +++ b/src/test/basics/base_uint_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { // a non-hashing Hasher that just copies the bytes. @@ -59,7 +59,7 @@ struct base_uint_test : beast::unit_test::suite for (auto const& arg : test_args) { - ripple::base_uint<64> const u{arg.first}, v{arg.second}; + xrpl::base_uint<64> const u{arg.first}, v{arg.second}; BEAST_EXPECT(u < v); BEAST_EXPECT(u <= v); BEAST_EXPECT(u != v); @@ -92,7 +92,7 @@ struct base_uint_test : beast::unit_test::suite for (auto const& arg : test_args) { - ripple::base_uint<96> const u{arg.first}, v{arg.second}; + xrpl::base_uint<96> const u{arg.first}, v{arg.second}; BEAST_EXPECT(u < v); BEAST_EXPECT(u <= v); BEAST_EXPECT(u != v); @@ -352,7 +352,7 @@ struct base_uint_test : beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(base_uint, basics, ripple); +BEAST_DEFINE_TESTSUITE(base_uint, basics, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/hardened_hash_test.cpp b/src/test/basics/hardened_hash_test.cpp index 9cd40d6a60..f7eb78ce31 100644 --- a/src/test/basics/hardened_hash_test.cpp +++ b/src/test/basics/hardened_hash_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { template @@ -51,11 +51,11 @@ public: }; } // namespace detail -} // namespace ripple +} // namespace xrpl //------------------------------------------------------------------------------ -namespace ripple { +namespace xrpl { namespace detail { @@ -148,11 +148,11 @@ using sha256_t = unsigned_integer<256, std::size_t>; static_assert(sha256_t::bits == 256, "sha256_t must have 256 bits"); #endif -} // namespace ripple +} // namespace xrpl //------------------------------------------------------------------------------ -namespace ripple { +namespace xrpl { class hardened_hash_test : public beast::unit_test::suite { @@ -234,6 +234,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(hardened_hash, basics, ripple); +BEAST_DEFINE_TESTSUITE(hardened_hash, basics, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/basics/join_test.cpp b/src/test/basics/join_test.cpp index 751f0290f8..5354f2ab60 100644 --- a/src/test/basics/join_test.cpp +++ b/src/test/basics/join_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct join_test : beast::unit_test::suite @@ -80,7 +80,7 @@ struct join_test : beast::unit_test::suite } }; // namespace test -BEAST_DEFINE_TESTSUITE(join, basics, ripple); +BEAST_DEFINE_TESTSUITE(join, basics, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/beast/IPEndpointCommon.h b/src/test/beast/IPEndpointCommon.h index 83175834af..73cbe7d95b 100644 --- a/src/test/beast/IPEndpointCommon.h +++ b/src/test/beast/IPEndpointCommon.h @@ -7,7 +7,7 @@ namespace IP { inline Endpoint randomEP(bool v4 = true) { - using namespace ripple; + using namespace xrpl; auto dv4 = []() -> AddressV4::bytes_type { return { {static_cast(rand_int(1, UINT8_MAX)), diff --git a/src/test/beast/IPEndpoint_test.cpp b/src/test/beast/IPEndpoint_test.cpp index 3d4f2e7f02..1d451e94a2 100644 --- a/src/test/beast/IPEndpoint_test.cpp +++ b/src/test/beast/IPEndpoint_test.cpp @@ -380,7 +380,7 @@ public: float max_lf{0}; for (auto i = 0; i < items; ++i) { - eps.insert(randomEP(ripple::rand_int(0, 1) == 1)); + eps.insert(randomEP(xrpl::rand_int(0, 1) == 1)); max_lf = std::max(max_lf, eps.load_factor()); } BEAST_EXPECT(eps.bucket_count() >= items); diff --git a/src/test/beast/beast_CurrentThreadName_test.cpp b/src/test/beast/beast_CurrentThreadName_test.cpp index 9863c1bb3c..3d33ecb602 100644 --- a/src/test/beast/beast_CurrentThreadName_test.cpp +++ b/src/test/beast/beast_CurrentThreadName_test.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class CurrentThreadName_test : public beast::unit_test::suite @@ -70,4 +70,4 @@ public: BEAST_DEFINE_TESTSUITE(CurrentThreadName, beast, beast); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/conditions/PreimageSha256_test.cpp b/src/test/conditions/PreimageSha256_test.cpp index 08f9e5fb5b..71ba526be3 100644 --- a/src/test/conditions/PreimageSha256_test.cpp +++ b/src/test/conditions/PreimageSha256_test.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { class PreimageSha256_test : public beast::unit_test::suite @@ -167,8 +167,8 @@ class PreimageSha256_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(PreimageSha256, conditions, ripple); +BEAST_DEFINE_TESTSUITE(PreimageSha256, conditions, xrpl); } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/ByzantineFailureSim_test.cpp b/src/test/consensus/ByzantineFailureSim_test.cpp index f2a9a7d5c6..0a988f0473 100644 --- a/src/test/consensus/ByzantineFailureSim_test.cpp +++ b/src/test/consensus/ByzantineFailureSim_test.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class ByzantineFailureSim_test : public beast::unit_test::suite @@ -79,7 +79,7 @@ class ByzantineFailureSim_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE_MANUAL(ByzantineFailureSim, consensus, ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(ByzantineFailureSim, consensus, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/Consensus_test.cpp b/src/test/consensus/Consensus_test.cpp index 6318c86a12..85dd5e3957 100644 --- a/src/test/consensus/Consensus_test.cpp +++ b/src/test/consensus/Consensus_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Consensus_test : public beast::unit_test::suite @@ -1518,6 +1518,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Consensus, consensus, ripple); +BEAST_DEFINE_TESTSUITE(Consensus, consensus, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/DistributedValidatorsSim_test.cpp b/src/test/consensus/DistributedValidatorsSim_test.cpp index 6e093a91c5..006c1aab4e 100644 --- a/src/test/consensus/DistributedValidatorsSim_test.cpp +++ b/src/test/consensus/DistributedValidatorsSim_test.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { /** In progress simulations for diversifying and distributing validators @@ -254,7 +254,7 @@ class DistributedValidators_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(DistributedValidators, consensus, ripple, 2); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(DistributedValidators, consensus, xrpl, 2); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/LedgerTiming_test.cpp b/src/test/consensus/LedgerTiming_test.cpp index c3ce86b4b3..0ec3563c79 100644 --- a/src/test/consensus/LedgerTiming_test.cpp +++ b/src/test/consensus/LedgerTiming_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class LedgerTiming_test : public beast::unit_test::suite @@ -105,6 +105,6 @@ class LedgerTiming_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(LedgerTiming, consensus, ripple); +BEAST_DEFINE_TESTSUITE(LedgerTiming, consensus, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/LedgerTrie_test.cpp b/src/test/consensus/LedgerTrie_test.cpp index 5ad725fa73..586b9231f6 100644 --- a/src/test/consensus/LedgerTrie_test.cpp +++ b/src/test/consensus/LedgerTrie_test.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class LedgerTrie_test : public beast::unit_test::suite @@ -659,6 +659,6 @@ class LedgerTrie_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(LedgerTrie, consensus, ripple); +BEAST_DEFINE_TESTSUITE(LedgerTrie, consensus, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/NegativeUNL_test.cpp b/src/test/consensus/NegativeUNL_test.cpp index a1000c0d49..e10d6cbdd0 100644 --- a/src/test/consensus/NegativeUNL_test.cpp +++ b/src/test/consensus/NegativeUNL_test.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { /* @@ -1826,20 +1826,20 @@ class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(NegativeUNL, consensus, ripple); +BEAST_DEFINE_TESTSUITE(NegativeUNL, consensus, xrpl); -BEAST_DEFINE_TESTSUITE(NegativeUNLVoteInternal, consensus, ripple); -BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus, ripple); -BEAST_DEFINE_TESTSUITE_PRIO(NegativeUNLVoteGoodScore, consensus, ripple, 1); -BEAST_DEFINE_TESTSUITE(NegativeUNLVoteOffline, consensus, ripple); -BEAST_DEFINE_TESTSUITE(NegativeUNLVoteMaxListed, consensus, ripple); +BEAST_DEFINE_TESTSUITE(NegativeUNLVoteInternal, consensus, xrpl); +BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus, xrpl); +BEAST_DEFINE_TESTSUITE_PRIO(NegativeUNLVoteGoodScore, consensus, xrpl, 1); +BEAST_DEFINE_TESTSUITE(NegativeUNLVoteOffline, consensus, xrpl); +BEAST_DEFINE_TESTSUITE(NegativeUNLVoteMaxListed, consensus, xrpl); BEAST_DEFINE_TESTSUITE_PRIO( NegativeUNLVoteRetiredValidator, consensus, ripple, 1); -BEAST_DEFINE_TESTSUITE(NegativeUNLVoteNewValidator, consensus, ripple); -BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus, ripple); +BEAST_DEFINE_TESTSUITE(NegativeUNLVoteNewValidator, consensus, xrpl); +BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus, xrpl); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// @@ -1947,4 +1947,4 @@ createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey) } } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/RCLCensorshipDetector_test.cpp b/src/test/consensus/RCLCensorshipDetector_test.cpp index 9be73735f9..4093ffe900 100644 --- a/src/test/consensus/RCLCensorshipDetector_test.cpp +++ b/src/test/consensus/RCLCensorshipDetector_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class RCLCensorshipDetector_test : public beast::unit_test::suite @@ -79,6 +79,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(RCLCensorshipDetector, consensus, ripple); +BEAST_DEFINE_TESTSUITE(RCLCensorshipDetector, consensus, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/ScaleFreeSim_test.cpp b/src/test/consensus/ScaleFreeSim_test.cpp index 51b9ee542a..53c5030f29 100644 --- a/src/test/consensus/ScaleFreeSim_test.cpp +++ b/src/test/consensus/ScaleFreeSim_test.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class ScaleFreeSim_test : public beast::unit_test::suite @@ -100,7 +100,7 @@ class ScaleFreeSim_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(ScaleFreeSim, consensus, ripple, 80); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(ScaleFreeSim, consensus, xrpl, 80); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/consensus/Validations_test.cpp b/src/test/consensus/Validations_test.cpp index b1b5a46f38..906817add0 100644 --- a/src/test/consensus/Validations_test.cpp +++ b/src/test/consensus/Validations_test.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { class Validations_test : public beast::unit_test::suite @@ -1125,7 +1125,7 @@ class Validations_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(Validations, consensus, ripple); +BEAST_DEFINE_TESTSUITE(Validations, consensus, xrpl); } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/core/ClosureCounter_test.cpp b/src/test/core/ClosureCounter_test.cpp index 23359596fd..47f9d9a5d1 100644 --- a/src/test/core/ClosureCounter_test.cpp +++ b/src/test/core/ClosureCounter_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { //------------------------------------------------------------------------------ @@ -318,7 +318,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ClosureCounter, core, ripple); +BEAST_DEFINE_TESTSUITE(ClosureCounter, core, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/core/Config_test.cpp b/src/test/core/Config_test.cpp index 6f11877202..86f09e6c02 100644 --- a/src/test/core/Config_test.cpp +++ b/src/test/core/Config_test.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { std::string configContents(std::string const& dbPath, std::string const& validatorsFile) @@ -109,7 +109,7 @@ backend=sqlite /** Write a rippled config file and remove when done. */ -class RippledCfgGuard : public ripple::detail::FileDirGuard +class RippledCfgGuard : public xrpl::detail::FileDirGuard { private: path dataDir_; @@ -326,7 +326,7 @@ port_wss_admin { // read from file absolute path auto const cwd = current_path(); - ripple::detail::DirGuard const g0(*this, "test_db"); + xrpl::detail::DirGuard const g0(*this, "test_db"); path const dataDirRel("test_data_dir"); path const dataDirAbs(cwd / g0.subdir() / dataDirRel); detail::RippledCfgGuard const g( @@ -1497,6 +1497,6 @@ r.ripple.com:51235 } }; -BEAST_DEFINE_TESTSUITE(Config, core, ripple); +BEAST_DEFINE_TESTSUITE(Config, core, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/core/Coroutine_test.cpp b/src/test/core/Coroutine_test.cpp index 47bd74a4a6..72a4c02434 100644 --- a/src/test/core/Coroutine_test.cpp +++ b/src/test/core/Coroutine_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Coroutine_test : public beast::unit_test::suite @@ -165,7 +165,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Coroutine, core, ripple); +BEAST_DEFINE_TESTSUITE(Coroutine, core, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/core/JobQueue_test.cpp b/src/test/core/JobQueue_test.cpp index 2451827bda..641a5fa317 100644 --- a/src/test/core/JobQueue_test.cpp +++ b/src/test/core/JobQueue_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { //------------------------------------------------------------------------------ @@ -140,7 +140,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(JobQueue, core, ripple); +BEAST_DEFINE_TESTSUITE(JobQueue, core, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/core/SociDB_test.cpp b/src/test/core/SociDB_test.cpp index 2d38ac4697..fc3c86a994 100644 --- a/src/test/core/SociDB_test.cpp +++ b/src/test/core/SociDB_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { class SociDB_test final : public TestSuite { private: @@ -351,6 +351,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(SociDB, core, ripple); +BEAST_DEFINE_TESTSUITE(SociDB, core, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/core/Workers_test.cpp b/src/test/core/Workers_test.cpp index 2ba8c2a0e0..0a552e9d61 100644 --- a/src/test/core/Workers_test.cpp +++ b/src/test/core/Workers_test.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** * Dummy class for unit tests. @@ -154,6 +154,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Workers, core, ripple); +BEAST_DEFINE_TESTSUITE(Workers, core, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/csf/BasicNetwork.h b/src/test/csf/BasicNetwork.h index 7fce2e5f0e..cb4e691317 100644 --- a/src/test/csf/BasicNetwork.h +++ b/src/test/csf/BasicNetwork.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { /** Peer to peer network simulator. @@ -234,6 +234,6 @@ BasicNetwork::send(Peer const& from, Peer const& to, Function&& f) } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/BasicNetwork_test.cpp b/src/test/csf/BasicNetwork_test.cpp index e5a8c545e5..0b29f90ad3 100644 --- a/src/test/csf/BasicNetwork_test.cpp +++ b/src/test/csf/BasicNetwork_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class BasicNetwork_test : public beast::unit_test::suite @@ -127,7 +127,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(BasicNetwork, csf, ripple); +BEAST_DEFINE_TESTSUITE(BasicNetwork, csf, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/csf/CollectorRef.h b/src/test/csf/CollectorRef.h index 81aa048249..3aa2c6495f 100644 --- a/src/test/csf/CollectorRef.h +++ b/src/test/csf/CollectorRef.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -327,6 +327,6 @@ public: } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/Digraph.h b/src/test/csf/Digraph.h index 24ff820e1d..688d0528d3 100644 --- a/src/test/csf/Digraph.h +++ b/src/test/csf/Digraph.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { // Dummy class when no edge data needed for graph struct NoEdgeData @@ -231,5 +231,5 @@ public: } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/Digraph_test.cpp b/src/test/csf/Digraph_test.cpp index bd37fef80c..a0cb35323d 100644 --- a/src/test/csf/Digraph_test.cpp +++ b/src/test/csf/Digraph_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Digraph_test : public beast::unit_test::suite @@ -73,7 +73,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Digraph, csf, ripple); +BEAST_DEFINE_TESTSUITE(Digraph, csf, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/csf/Histogram.h b/src/test/csf/Histogram.h index 3a504557f2..b55af34846 100644 --- a/src/test/csf/Histogram.h +++ b/src/test/csf/Histogram.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -111,6 +111,6 @@ public: } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/Histogram_test.cpp b/src/test/csf/Histogram_test.cpp index 964c065bfc..b0a8d8490d 100644 --- a/src/test/csf/Histogram_test.cpp +++ b/src/test/csf/Histogram_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class Histogram_test : public beast::unit_test::suite @@ -62,7 +62,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Histogram, csf, ripple); +BEAST_DEFINE_TESTSUITE(Histogram, csf, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/csf/Peer.h b/src/test/csf/Peer.h index 5f6f006b0f..b2a0c3b3ed 100644 --- a/src/test/csf/Peer.h +++ b/src/test/csf/Peer.h @@ -20,7 +20,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -983,5 +983,5 @@ struct Peer } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/PeerGroup.h b/src/test/csf/PeerGroup.h index 8186b877c8..e674581546 100644 --- a/src/test/csf/PeerGroup.h +++ b/src/test/csf/PeerGroup.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -351,5 +351,5 @@ randomRankedConnect( } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/Proposal.h b/src/test/csf/Proposal.h index bb09bbdde1..0bcf838080 100644 --- a/src/test/csf/Proposal.h +++ b/src/test/csf/Proposal.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { /** Proposal is a position taken in the consensus process and is represented @@ -17,6 +17,6 @@ using Proposal = ConsensusProposal; } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/Scheduler.h b/src/test/csf/Scheduler.h index 7a44dda5da..2c250e6def 100644 --- a/src/test/csf/Scheduler.h +++ b/src/test/csf/Scheduler.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -434,6 +434,6 @@ Scheduler::step_for(std::chrono::duration const& amount) } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/Scheduler_test.cpp b/src/test/csf/Scheduler_test.cpp index 0975cc09d0..a0b57dd87f 100644 --- a/src/test/csf/Scheduler_test.cpp +++ b/src/test/csf/Scheduler_test.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class Scheduler_test : public beast::unit_test::suite @@ -64,7 +64,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Scheduler, csf, ripple); +BEAST_DEFINE_TESTSUITE(Scheduler, csf, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/csf/Sim.h b/src/test/csf/Sim.h index 53c3875624..ad0927e87e 100644 --- a/src/test/csf/Sim.h +++ b/src/test/csf/Sim.h @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -157,6 +157,6 @@ public: } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/SimTime.h b/src/test/csf/SimTime.h index d4ab34fe55..5d8c67b8f8 100644 --- a/src/test/csf/SimTime.h +++ b/src/test/csf/SimTime.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -19,6 +19,6 @@ using SimTime = typename SimClock::time_point; } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/TrustGraph.h b/src/test/csf/TrustGraph.h index 936e13b963..f5b8a9e755 100644 --- a/src/test/csf/TrustGraph.h +++ b/src/test/csf/TrustGraph.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -154,6 +154,6 @@ public: } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/Tx.h b/src/test/csf/Tx.h index e24c09be2f..cf3ee85940 100644 --- a/src/test/csf/Tx.h +++ b/src/test/csf/Tx.h @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -210,6 +210,6 @@ hash_append(Hasher& h, Tx const& tx) } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/Validation.h b/src/test/csf/Validation.h index 77ba81681d..907eca79d0 100644 --- a/src/test/csf/Validation.h +++ b/src/test/csf/Validation.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -183,6 +183,6 @@ public: } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/collectors.h b/src/test/csf/collectors.h index 53494dad44..3b6bc0e0f3 100644 --- a/src/test/csf/collectors.h +++ b/src/test/csf/collectors.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -699,6 +699,6 @@ struct JumpCollector } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/events.h b/src/test/csf/events.h index b25dc4b339..29f434f4ad 100644 --- a/src/test/csf/events.h +++ b/src/test/csf/events.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -129,6 +129,6 @@ struct FullyValidateLedger } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/impl/Sim.cpp b/src/test/csf/impl/Sim.cpp index c17ea26939..4fbee56f0f 100644 --- a/src/test/csf/impl/Sim.cpp +++ b/src/test/csf/impl/Sim.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -63,4 +63,4 @@ Sim::branches(PeerGroup const& g) const } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/csf/impl/ledgers.cpp b/src/test/csf/impl/ledgers.cpp index 681020c12e..09a098f2d6 100644 --- a/src/test/csf/impl/ledgers.cpp +++ b/src/test/csf/impl/ledgers.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -152,4 +152,4 @@ LedgerOracle::branches(std::set const& ledgers) const } } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/csf/ledgers.h b/src/test/csf/ledgers.h index 80e431c1e2..7614482635 100644 --- a/src/test/csf/ledgers.h +++ b/src/test/csf/ledgers.h @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -230,8 +230,8 @@ private: class LedgerOracle { using InstanceMap = boost::bimaps::bimap< - boost::bimaps::set_of>, - boost::bimaps::set_of>>; + boost::bimaps::set_of>, + boost::bimaps::set_of>>; using InstanceEntry = InstanceMap::value_type; // Set of all known ledgers; note this is never pruned @@ -341,6 +341,6 @@ struct LedgerHistoryHelper } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/random.h b/src/test/csf/random.h index c3ad9564ba..8b3ac7e971 100644 --- a/src/test/csf/random.h +++ b/src/test/csf/random.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -156,6 +156,6 @@ public: } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/submitters.h b/src/test/csf/submitters.h index 3cca62c10d..8a3632eb97 100644 --- a/src/test/csf/submitters.h +++ b/src/test/csf/submitters.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -109,6 +109,6 @@ makeSubmitter( } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/csf/timers.h b/src/test/csf/timers.h index c16beec885..b5902393c7 100644 --- a/src/test/csf/timers.h +++ b/src/test/csf/timers.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace csf { @@ -65,6 +65,6 @@ public: } // namespace csf } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/json/Object_test.cpp b/src/test/json/Object_test.cpp index 9d4f65492a..b74754db33 100644 --- a/src/test/json/Object_test.cpp +++ b/src/test/json/Object_test.cpp @@ -5,7 +5,7 @@ namespace Json { -class JsonObject_test : public ripple::test::TestOutputSuite +class JsonObject_test : public xrpl::test::TestOutputSuite { void setup(std::string const& testName) @@ -234,6 +234,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(JsonObject, json, ripple); +BEAST_DEFINE_TESTSUITE(JsonObject, json, xrpl); } // namespace Json diff --git a/src/test/json/TestOutputSuite.h b/src/test/json/TestOutputSuite.h index 0c1810bd39..934fe1de81 100644 --- a/src/test/json/TestOutputSuite.h +++ b/src/test/json/TestOutputSuite.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class TestOutputSuite : public TestSuite @@ -34,6 +34,6 @@ protected: }; } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/AMM.h b/src/test/jtx/AMM.h index 646d663f99..65c16ec627 100644 --- a/src/test/jtx/AMM.h +++ b/src/test/jtx/AMM.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -442,6 +442,6 @@ ammClawback( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif // XRPL_TEST_JTX_AMM_H_INCLUDED diff --git a/src/test/jtx/AMMTest.h b/src/test/jtx/AMMTest.h index 91a18bec2c..83366d61e2 100644 --- a/src/test/jtx/AMMTest.h +++ b/src/test/jtx/AMMTest.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -148,6 +148,6 @@ protected: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif // XRPL_TEST_JTX_AMMTEST_H_INCLUDED diff --git a/src/test/jtx/AbstractClient.h b/src/test/jtx/AbstractClient.h index 383586ce02..0bdfbd67de 100644 --- a/src/test/jtx/AbstractClient.h +++ b/src/test/jtx/AbstractClient.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { /* Abstract Ripple Client interface. @@ -40,6 +40,6 @@ public: }; } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/Account.h b/src/test/jtx/Account.h index 7545b620ee..af8870f22a 100644 --- a/src/test/jtx/Account.h +++ b/src/test/jtx/Account.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -152,6 +152,6 @@ operator<=>(Account const& lhs, Account const& rhs) noexcept } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/CaptureLogs.h b/src/test/jtx/CaptureLogs.h index 86f160c318..0ac855e402 100644 --- a/src/test/jtx/CaptureLogs.h +++ b/src/test/jtx/CaptureLogs.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { /** @@ -75,6 +75,6 @@ public: }; } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/CheckMessageLogs.h b/src/test/jtx/CheckMessageLogs.h index d71b09673e..b0e5f4c82e 100644 --- a/src/test/jtx/CheckMessageLogs.h +++ b/src/test/jtx/CheckMessageLogs.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { /** Log manager that searches for a specific message substring @@ -63,6 +63,6 @@ public: }; } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/Env.h b/src/test/jtx/Env.h index 9858e17078..26a664efbd 100644 --- a/src/test/jtx/Env.h +++ b/src/test/jtx/Env.h @@ -39,7 +39,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -819,6 +819,6 @@ Env::rpc(std::string const& cmd, Args&&... args) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/Env_ss.h b/src/test/jtx/Env_ss.h index 726fbb4fe0..734eca5819 100644 --- a/src/test/jtx/Env_ss.h +++ b/src/test/jtx/Env_ss.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -59,6 +59,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/Env_test.cpp b/src/test/jtx/Env_test.cpp index fbc4bd37a2..ba5a2ee8c5 100644 --- a/src/test/jtx/Env_test.cpp +++ b/src/test/jtx/Env_test.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Env_test : public beast::unit_test::suite @@ -928,7 +928,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Env, jtx, ripple); +BEAST_DEFINE_TESTSUITE(Env, jtx, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/JSONRPCClient.h b/src/test/jtx/JSONRPCClient.h index a351694c3b..0513b43a93 100644 --- a/src/test/jtx/JSONRPCClient.h +++ b/src/test/jtx/JSONRPCClient.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { /** Returns a client using JSON-RPC over HTTP/S. */ @@ -15,6 +15,6 @@ std::unique_ptr makeJSONRPCClient(Config const& cfg, unsigned rpc_version = 2); } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/JTx.h b/src/test/jtx/JTx.h index 2baaf8cd10..aa87ce333d 100644 --- a/src/test/jtx/JTx.h +++ b/src/test/jtx/JTx.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -159,6 +159,6 @@ private: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/ManualTimeKeeper.h b/src/test/jtx/ManualTimeKeeper.h index 251877986f..df3c7ff89a 100644 --- a/src/test/jtx/ManualTimeKeeper.h +++ b/src/test/jtx/ManualTimeKeeper.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class ManualTimeKeeper : public TimeKeeper @@ -30,6 +30,6 @@ public: }; } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/Oracle.h b/src/test/jtx/Oracle.h index cbf3975771..fc7dc89cd1 100644 --- a/src/test/jtx/Oracle.h +++ b/src/test/jtx/Oracle.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { namespace oracle { @@ -185,6 +185,6 @@ public: } // namespace oracle } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif // XRPL_TEST_JTX_ORACLE_H_INCLUDED diff --git a/src/test/jtx/PathSet.h b/src/test/jtx/PathSet.h index 25f58150bb..0c54b6fb77 100644 --- a/src/test/jtx/PathSet.h +++ b/src/test/jtx/PathSet.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { /** Count offer @@ -182,6 +182,6 @@ private: }; } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/SignerUtils.h b/src/test/jtx/SignerUtils.h index 07d12d8cea..272909c887 100644 --- a/src/test/jtx/SignerUtils.h +++ b/src/test/jtx/SignerUtils.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -51,6 +51,6 @@ sortSigners(std::vector& signers) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/TestHelpers.h b/src/test/jtx/TestHelpers.h index 5ae44acaac..f00b929967 100644 --- a/src/test/jtx/TestHelpers.h +++ b/src/test/jtx/TestHelpers.h @@ -25,7 +25,7 @@ using source_location = std::experimental::source_location; using std::source_location; #endif -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -828,6 +828,6 @@ pay(AccountID const& account, } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif // XRPL_TEST_JTX_TESTHELPERS_H_INCLUDED diff --git a/src/test/jtx/TestSuite.h b/src/test/jtx/TestSuite.h index 69ac910c54..69cbd2a210 100644 --- a/src/test/jtx/TestSuite.h +++ b/src/test/jtx/TestSuite.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { class TestSuite : public beast::unit_test::suite { @@ -119,6 +119,6 @@ private: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/TrustedPublisherServer.h b/src/test/jtx/TrustedPublisherServer.h index 0f88e42f3d..e7ddef7ac9 100644 --- a/src/test/jtx/TrustedPublisherServer.h +++ b/src/test/jtx/TrustedPublisherServer.h @@ -23,7 +23,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class TrustedPublisherServer @@ -164,8 +164,7 @@ public: bool immediateStart = true, int sequence = 1) : sock_{ioc} - , ep_{boost::asio::ip::make_address( - ripple::test::getEnvLocalhostAddr()), + , ep_{boost::asio::ip::make_address(xrpl::test::getEnvLocalhostAddr()), // 0 means let OS pick the port based on what's available 0} , acceptor_{ioc} @@ -715,5 +714,5 @@ make_TrustedPublisherServer( } } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/WSClient.h b/src/test/jtx/WSClient.h index 9e7370a0fd..2365e8ce40 100644 --- a/src/test/jtx/WSClient.h +++ b/src/test/jtx/WSClient.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class WSClient : public AbstractClient @@ -37,6 +37,6 @@ makeWSClient( std::unordered_map const& headers = {}); } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/WSClient_test.cpp b/src/test/jtx/WSClient_test.cpp index 27285b2021..206b550b87 100644 --- a/src/test/jtx/WSClient_test.cpp +++ b/src/test/jtx/WSClient_test.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class WSClient_test : public beast::unit_test::suite @@ -27,7 +27,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(WSClient, jtx, ripple); +BEAST_DEFINE_TESTSUITE(WSClient, jtx, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/account_txn_id.h b/src/test/jtx/account_txn_id.h index bec9a195d3..fb48941925 100644 --- a/src/test/jtx/account_txn_id.h +++ b/src/test/jtx/account_txn_id.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -22,5 +22,5 @@ public: }; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/acctdelete.h b/src/test/jtx/acctdelete.h index 73e7cb6e8d..71b8597db9 100644 --- a/src/test/jtx/acctdelete.h +++ b/src/test/jtx/acctdelete.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -26,6 +26,6 @@ incLgrSeqForAccDel( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index ed0fa57cbf..faf70921be 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { struct epsilon_multiple @@ -239,9 +239,9 @@ public: struct BookSpec { AccountID account; - ripple::Currency currency; + xrpl::Currency currency; - BookSpec(AccountID const& account_, ripple::Currency const& currency_) + BookSpec(AccountID const& account_, xrpl::Currency const& currency_) : account(account_), currency(currency_) { } @@ -383,9 +383,9 @@ class IOU { public: Account account; - ripple::Currency currency; + xrpl::Currency currency; - IOU(Account const& account_, ripple::Currency const& currency_) + IOU(Account const& account_, xrpl::Currency const& currency_) : account(account_), currency(currency_) { } @@ -465,14 +465,14 @@ class MPT { public: std::string name; - ripple::MPTID issuanceID; + xrpl::MPTID issuanceID; - MPT(std::string const& n, ripple::MPTID const& issuanceID_) + MPT(std::string const& n, xrpl::MPTID const& issuanceID_) : name(n), issuanceID(issuanceID_) { } - ripple::MPTID const& + xrpl::MPTID const& mpt() const { return issuanceID; @@ -480,7 +480,7 @@ public: /** Explicit conversion to MPTIssue or asset. */ - ripple::MPTIssue + xrpl::MPTIssue mptIssue() const { return MPTIssue{issuanceID}; @@ -496,7 +496,7 @@ public: This allows passing an MPT value where an MPTIssue is expected. */ - operator ripple::MPTIssue() const + operator xrpl::MPTIssue() const { return mptIssue(); } @@ -589,6 +589,6 @@ extern any_t const any; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/attester.h b/src/test/jtx/attester.h index 6aa69e23b5..345002f90a 100644 --- a/src/test/jtx/attester.h +++ b/src/test/jtx/attester.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class PublicKey; class SecretKey; @@ -43,6 +43,6 @@ sign_create_account_attestation( AccountID const& dst); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/balance.h b/src/test/jtx/balance.h index 8ca0f2fd47..999f6b7b0c 100644 --- a/src/test/jtx/balance.h +++ b/src/test/jtx/balance.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -45,6 +45,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/basic_prop.h b/src/test/jtx/basic_prop.h index 1ee7c04e08..32655e9f52 100644 --- a/src/test/jtx/basic_prop.h +++ b/src/test/jtx/basic_prop.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -41,6 +41,6 @@ struct prop_type : basic_prop } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/batch.h b/src/test/jtx/batch.h index 14122e3c01..dc9d30a420 100644 --- a/src/test/jtx/batch.h +++ b/src/test/jtx/batch.h @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -144,6 +144,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/check.h b/src/test/jtx/check.h index 863fce6f75..6152195f1f 100644 --- a/src/test/jtx/check.h +++ b/src/test/jtx/check.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -44,6 +44,6 @@ using checks = owner_count; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/credentials.h b/src/test/jtx/credentials.h index 2ae0d1737e..2b41b5e7ef 100644 --- a/src/test/jtx/credentials.h +++ b/src/test/jtx/credentials.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -91,6 +91,6 @@ ledgerEntry(jtx::Env& env, std::string const& credIdx); } // namespace credentials } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/delegate.h b/src/test/jtx/delegate.h index 11b13cb9be..19707584ad 100644 --- a/src/test/jtx/delegate.h +++ b/src/test/jtx/delegate.h @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -40,4 +40,4 @@ public: } // namespace delegate } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/delivermin.h b/src/test/jtx/delivermin.h index 9d7ca4eaa2..70f092c9dc 100644 --- a/src/test/jtx/delivermin.h +++ b/src/test/jtx/delivermin.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -26,6 +26,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/deposit.h b/src/test/jtx/deposit.h index 91897038b6..5ea1e5bf06 100644 --- a/src/test/jtx/deposit.h +++ b/src/test/jtx/deposit.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -62,6 +62,6 @@ unauthCredentials( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/did.h b/src/test/jtx/did.h index 883f1abe35..65407028eb 100644 --- a/src/test/jtx/did.h +++ b/src/test/jtx/did.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -80,6 +80,6 @@ del(jtx::Account const& account); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/directory.h b/src/test/jtx/directory.h index 3abcc0562d..6129b79d1c 100644 --- a/src/test/jtx/directory.h +++ b/src/test/jtx/directory.h @@ -10,7 +10,7 @@ #include #include -namespace ripple::test::jtx { +namespace xrpl::test::jtx { /** Directory operations. */ namespace directory { @@ -57,6 +57,6 @@ maximumPageIndex(Env const& env) -> std::uint64_t } // namespace directory -} // namespace ripple::test::jtx +} // namespace xrpl::test::jtx #endif diff --git a/src/test/jtx/domain.h b/src/test/jtx/domain.h index b7199a843c..cb67ce3622 100644 --- a/src/test/jtx/domain.h +++ b/src/test/jtx/domain.h @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -23,4 +23,4 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/envconfig.h b/src/test/jtx/envconfig.h index 4c8476d95f..d6276f2fba 100644 --- a/src/test/jtx/envconfig.h +++ b/src/test/jtx/envconfig.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { // frequently used macros defined here for convenience. @@ -44,7 +44,7 @@ envconfig() /// /// @param modfunc callable function or lambda to modify the default config. /// The first argument to the function must be std::unique_ptr to -/// ripple::Config. The function takes ownership of the unique_ptr and +/// xrpl::Config. The function takes ownership of the unique_ptr and /// relinquishes ownership by returning a unique_ptr. /// /// @param args additional arguments that will be passed to @@ -115,6 +115,6 @@ makeConfig( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/escrow.h b/src/test/jtx/escrow.h index d0d066c2d4..b8490d9534 100644 --- a/src/test/jtx/escrow.h +++ b/src/test/jtx/escrow.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -90,6 +90,6 @@ auto const fulfillment = JTxFieldWrapper(sfFulfillment); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/fee.h b/src/test/jtx/fee.h index 17269b1a38..1b3a6ac49c 100644 --- a/src/test/jtx/fee.h +++ b/src/test/jtx/fee.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -51,6 +51,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/flags.h b/src/test/jtx/flags.h index 7b6be9fe22..6b8c230a79 100644 --- a/src/test/jtx/flags.h +++ b/src/test/jtx/flags.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { class flags_helper @@ -140,6 +140,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/impl/AMM.cpp b/src/test/jtx/impl/AMM.cpp index 0fe9bd25df..b620126b0f 100644 --- a/src/test/jtx/impl/AMM.cpp +++ b/src/test/jtx/impl/AMM.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -59,7 +59,7 @@ AMM::AMM( , msig_(ms) , fee_(fee) , ammAccount_(create(tfee, flags, seq, ter)) - , lptIssue_(ripple::ammLPTIssue( + , lptIssue_(xrpl::ammLPTIssue( asset1_.issue().currency, asset2_.issue().currency, ammAccount_)) @@ -832,4 +832,4 @@ ammClawback( } // namespace amm } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/AMMTest.cpp b/src/test/jtx/impl/AMMTest.cpp index 3bdc8e041a..790762d3df 100644 --- a/src/test/jtx/impl/AMMTest.cpp +++ b/src/test/jtx/impl/AMMTest.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -280,4 +280,4 @@ AMMTest::find_paths( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/Account.cpp b/src/test/jtx/impl/Account.cpp index 6cab28245d..232c9d4e6c 100644 --- a/src/test/jtx/impl/Account.cpp +++ b/src/test/jtx/impl/Account.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -85,4 +85,4 @@ Account::operator[](std::string const& s) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/Env.cpp b/src/test/jtx/impl/Env.cpp index 311a5dde3a..ccef0f0398 100644 --- a/src/test/jtx/impl/Env.cpp +++ b/src/test/jtx/impl/Env.cpp @@ -28,7 +28,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -673,4 +673,4 @@ Env::disableFeature(uint256 const feature) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/JSONRPCClient.cpp b/src/test/jtx/impl/JSONRPCClient.cpp index 7374128e02..df41ed39be 100644 --- a/src/test/jtx/impl/JSONRPCClient.cpp +++ b/src/test/jtx/impl/JSONRPCClient.cpp @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class JSONRPCClient : public AbstractClient @@ -147,4 +147,4 @@ makeJSONRPCClient(Config const& cfg, unsigned rpc_version) } } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/Oracle.cpp b/src/test/jtx/impl/Oracle.cpp index e3396f3ebc..03271cc9ad 100644 --- a/src/test/jtx/impl/Oracle.cpp +++ b/src/test/jtx/impl/Oracle.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { namespace oracle { @@ -358,4 +358,4 @@ validDocumentID(AnyValue const& v) } // namespace oracle } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/TestHelpers.cpp b/src/test/jtx/impl/TestHelpers.cpp index 4dfc5fb7b1..4a9d425f01 100644 --- a/src/test/jtx/impl/TestHelpers.cpp +++ b/src/test/jtx/impl/TestHelpers.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -486,4 +486,4 @@ pay(AccountID const& account, } // namespace loan } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/WSClient.cpp b/src/test/jtx/impl/WSClient.cpp index 5f9f123f81..878846b41d 100644 --- a/src/test/jtx/impl/WSClient.cpp +++ b/src/test/jtx/impl/WSClient.cpp @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class WSClientImpl : public WSClient @@ -311,4 +311,4 @@ makeWSClient( } } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/account_txn_id.cpp b/src/test/jtx/impl/account_txn_id.cpp index e2c05b4bc7..ceda6e7b50 100644 --- a/src/test/jtx/impl/account_txn_id.cpp +++ b/src/test/jtx/impl/account_txn_id.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -13,4 +13,4 @@ account_txn_id::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/acctdelete.cpp b/src/test/jtx/impl/acctdelete.cpp index ab613671da..47ee1c39a6 100644 --- a/src/test/jtx/impl/acctdelete.cpp +++ b/src/test/jtx/impl/acctdelete.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -42,4 +42,4 @@ incLgrSeqForAccDel(jtx::Env& env, jtx::Account const& acc, std::uint32_t margin) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/amount.cpp b/src/test/jtx/impl/amount.cpp index 08836e4aa3..2548a4423b 100644 --- a/src/test/jtx/impl/amount.cpp +++ b/src/test/jtx/impl/amount.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -115,4 +115,4 @@ any_t const any{}; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/attester.cpp b/src/test/jtx/impl/attester.cpp index 2937aca785..1d00767f0c 100644 --- a/src/test/jtx/impl/attester.cpp +++ b/src/test/jtx/impl/attester.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -59,4 +59,4 @@ sign_create_account_attestation( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/balance.cpp b/src/test/jtx/impl/balance.cpp index e3ab97950b..4449be223c 100644 --- a/src/test/jtx/impl/balance.cpp +++ b/src/test/jtx/impl/balance.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -74,4 +74,4 @@ balance::operator()(Env& env) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/batch.cpp b/src/test/jtx/impl/batch.cpp index b728ff391b..e0a52d0218 100644 --- a/src/test/jtx/impl/batch.cpp +++ b/src/test/jtx/impl/batch.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -81,7 +81,7 @@ sig::operator()(Env& env, JTx& jt) const Serializer msg; serializeBatch(msg, stx.getFlags(), stx.getBatchTransactionIDs()); - auto const sig = ripple::sign( + auto const sig = xrpl::sign( *publicKeyType(e.sig.pk().slice()), e.sig.sk(), msg.slice()); jo[sfTxnSignature.getJsonName()] = strHex(Slice{sig.data(), sig.size()}); @@ -121,7 +121,7 @@ msig::operator()(Env& env, JTx& jt) const Serializer msg; serializeBatch(msg, stx.getFlags(), stx.getBatchTransactionIDs()); finishMultiSigningData(e.acct.id(), msg); - auto const sig = ripple::sign( + auto const sig = xrpl::sign( *publicKeyType(e.sig.pk().slice()), e.sig.sk(), msg.slice()); iso[sfTxnSignature.getJsonName()] = strHex(Slice{sig.data(), sig.size()}); @@ -132,4 +132,4 @@ msig::operator()(Env& env, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/check.cpp b/src/test/jtx/impl/check.cpp index f9de30a8ed..769771861d 100644 --- a/src/test/jtx/impl/check.cpp +++ b/src/test/jtx/impl/check.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -51,4 +51,4 @@ cancel(jtx::Account const& dest, uint256 const& checkId) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/creds.cpp b/src/test/jtx/impl/creds.cpp index b5b65c4445..f93d951e48 100644 --- a/src/test/jtx/impl/creds.cpp +++ b/src/test/jtx/impl/creds.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -84,4 +84,4 @@ ledgerEntry(jtx::Env& env, std::string const& credIdx) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/delegate.cpp b/src/test/jtx/impl/delegate.cpp index 62407776c4..7cca9aa738 100644 --- a/src/test/jtx/impl/delegate.cpp +++ b/src/test/jtx/impl/delegate.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -45,4 +45,4 @@ entry(jtx::Env& env, jtx::Account const& account, jtx::Account const& authorize) } // namespace delegate } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/delivermin.cpp b/src/test/jtx/impl/delivermin.cpp index 7ddccc9c91..5ad98edd09 100644 --- a/src/test/jtx/impl/delivermin.cpp +++ b/src/test/jtx/impl/delivermin.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -14,4 +14,4 @@ delivermin::operator()(Env& env, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/deposit.cpp b/src/test/jtx/impl/deposit.cpp index ba947f48fb..7a49bee06a 100644 --- a/src/test/jtx/impl/deposit.cpp +++ b/src/test/jtx/impl/deposit.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -74,4 +74,4 @@ unauthCredentials( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/dids.cpp b/src/test/jtx/impl/dids.cpp index 6257a0cddb..bb782bcd43 100644 --- a/src/test/jtx/impl/dids.cpp +++ b/src/test/jtx/impl/dids.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -43,4 +43,4 @@ del(jtx::Account const& account) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/directory.cpp b/src/test/jtx/impl/directory.cpp index 275ce2c7b3..bb44b8d782 100644 --- a/src/test/jtx/impl/directory.cpp +++ b/src/test/jtx/impl/directory.cpp @@ -2,7 +2,7 @@ #include -namespace ripple::test::jtx { +namespace xrpl::test::jtx { /** Directory operations. */ namespace directory { @@ -123,4 +123,4 @@ adjustOwnerNode(ApplyView& view, uint256 key, std::uint64_t page) } // namespace directory -} // namespace ripple::test::jtx +} // namespace xrpl::test::jtx diff --git a/src/test/jtx/impl/domain.cpp b/src/test/jtx/impl/domain.cpp index d186fb950c..91568783d2 100644 --- a/src/test/jtx/impl/domain.cpp +++ b/src/test/jtx/impl/domain.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -14,4 +14,4 @@ domain::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/envconfig.cpp b/src/test/jtx/impl/envconfig.cpp index 8cf416a4c5..67bbe3b457 100644 --- a/src/test/jtx/impl/envconfig.cpp +++ b/src/test/jtx/impl/envconfig.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { std::atomic envUseIPv4{false}; @@ -156,4 +156,4 @@ makeConfig( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/escrow.cpp b/src/test/jtx/impl/escrow.cpp index 742bea6afa..067c304178 100644 --- a/src/test/jtx/impl/escrow.cpp +++ b/src/test/jtx/impl/escrow.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -51,7 +51,7 @@ rate(Env& env, Account const& account, std::uint32_t const& seq) { auto const sle = env.le(keylet::escrow(account.id(), seq)); if (sle->isFieldPresent(sfTransferRate)) - return ripple::Rate((*sle)[sfTransferRate]); + return xrpl::Rate((*sle)[sfTransferRate]); return Rate{0}; } @@ -60,4 +60,4 @@ rate(Env& env, Account const& account, std::uint32_t const& seq) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/fee.cpp b/src/test/jtx/impl/fee.cpp index 8ce1dda6af..2b1ac6c398 100644 --- a/src/test/jtx/impl/fee.cpp +++ b/src/test/jtx/impl/fee.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -21,4 +21,4 @@ fee::operator()(Env& env, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/flags.cpp b/src/test/jtx/impl/flags.cpp index 8ee7e4cffa..11e7831f55 100644 --- a/src/test/jtx/impl/flags.cpp +++ b/src/test/jtx/impl/flags.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -45,4 +45,4 @@ nflags::operator()(Env& env) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/invoice_id.cpp b/src/test/jtx/impl/invoice_id.cpp index 47eff96cb2..6d6dae0fbf 100644 --- a/src/test/jtx/impl/invoice_id.cpp +++ b/src/test/jtx/impl/invoice_id.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -13,4 +13,4 @@ invoice_id::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/jtx_json.cpp b/src/test/jtx/impl/jtx_json.cpp index 1e39ec2dda..c39503d038 100644 --- a/src/test/jtx/impl/jtx_json.cpp +++ b/src/test/jtx/impl/jtx_json.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -32,4 +32,4 @@ json::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/last_ledger_sequence.cpp b/src/test/jtx/impl/last_ledger_sequence.cpp index 1a00f7d4d9..5f29282ad6 100644 --- a/src/test/jtx/impl/last_ledger_sequence.cpp +++ b/src/test/jtx/impl/last_ledger_sequence.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -12,4 +12,4 @@ last_ledger_seq::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/ledgerStateFixes.cpp b/src/test/jtx/impl/ledgerStateFixes.cpp index 704da218e8..f1e6b6eda1 100644 --- a/src/test/jtx/impl/ledgerStateFixes.cpp +++ b/src/test/jtx/impl/ledgerStateFixes.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -27,4 +27,4 @@ nftPageLinks(jtx::Account const& acct, jtx::Account const& owner) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/memo.cpp b/src/test/jtx/impl/memo.cpp index 10bcede507..c815b916d7 100644 --- a/src/test/jtx/impl/memo.cpp +++ b/src/test/jtx/impl/memo.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -81,4 +81,4 @@ memontype::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/mpt.cpp b/src/test/jtx/impl/mpt.cpp index fc831790f1..adffa8548a 100644 --- a/src/test/jtx/impl/mpt.cpp +++ b/src/test/jtx/impl/mpt.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -595,7 +595,7 @@ MPTTester::mpt(std::int64_t amount) const { if (!id_) Throw("MPT has not been created"); - return ripple::test::jtx::MPT(issuer_.name(), *id_)(amount); + return xrpl::test::jtx::MPT(issuer_.name(), *id_)(amount); } MPTTester::operator Asset() const @@ -651,4 +651,4 @@ MPTTester::operator()(std::uint64_t amount) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/multisign.cpp b/src/test/jtx/impl/multisign.cpp index 68662b114b..61af11fb3a 100644 --- a/src/test/jtx/impl/multisign.cpp +++ b/src/test/jtx/impl/multisign.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -78,7 +78,7 @@ msig::operator()(Env& env, JTx& jt) const jo[jss::SigningPubKey] = strHex(e.sig.pk().slice()); Serializer ss{buildMultiSigningData(*st, e.acct.id())}; - auto const sig = ripple::sign( + auto const sig = xrpl::sign( *publicKeyType(e.sig.pk().slice()), e.sig.sk(), ss.slice()); jo[sfTxnSignature.getJsonName()] = strHex(Slice{sig.data(), sig.size()}); @@ -92,4 +92,4 @@ msig::operator()(Env& env, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/offer.cpp b/src/test/jtx/impl/offer.cpp index 69ee933049..251b659f3b 100644 --- a/src/test/jtx/impl/offer.cpp +++ b/src/test/jtx/impl/offer.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -35,4 +35,4 @@ offer_cancel(Account const& account, std::uint32_t offerSeq) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/owners.cpp b/src/test/jtx/impl/owners.cpp index b3690563d2..ad449dab93 100644 --- a/src/test/jtx/impl/owners.cpp +++ b/src/test/jtx/impl/owners.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace detail { std::uint32_t @@ -38,4 +38,4 @@ owners::operator()(Env& env) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/paths.cpp b/src/test/jtx/impl/paths.cpp index 37b59773c0..fd93ebd841 100644 --- a/src/test/jtx/impl/paths.cpp +++ b/src/test/jtx/impl/paths.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -98,4 +98,4 @@ path::operator()(Env& env, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/pay.cpp b/src/test/jtx/impl/pay.cpp index 750a3f2abf..9e927c6270 100644 --- a/src/test/jtx/impl/pay.cpp +++ b/src/test/jtx/impl/pay.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -27,4 +27,4 @@ pay(Account const& account, Account const& to, AnyAmount amount) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/permissioned_dex.cpp b/src/test/jtx/impl/permissioned_dex.cpp index 46c7a58689..87b7896663 100644 --- a/src/test/jtx/impl/permissioned_dex.cpp +++ b/src/test/jtx/impl/permissioned_dex.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -63,4 +63,4 @@ PermissionedDEX::PermissionedDEX(Env& env) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/permissioned_domains.cpp b/src/test/jtx/impl/permissioned_domains.cpp index c57bde620e..aac9dcc05f 100644 --- a/src/test/jtx/impl/permissioned_domains.cpp +++ b/src/test/jtx/impl/permissioned_domains.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { namespace pdomain { @@ -158,4 +158,4 @@ getNewDomain(std::shared_ptr const& meta) } // namespace pdomain } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/quality2.cpp b/src/test/jtx/impl/quality2.cpp index dd2c900389..c202592b9d 100644 --- a/src/test/jtx/impl/quality2.cpp +++ b/src/test/jtx/impl/quality2.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -51,4 +51,4 @@ qualityOutPercent::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/rate.cpp b/src/test/jtx/impl/rate.cpp index 14901e37e4..b4e9b2cb60 100644 --- a/src/test/jtx/impl/rate.cpp +++ b/src/test/jtx/impl/rate.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -23,4 +23,4 @@ rate(Account const& account, double multiplier) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/regkey.cpp b/src/test/jtx/impl/regkey.cpp index 72d7331ce6..a2e2198eee 100644 --- a/src/test/jtx/impl/regkey.cpp +++ b/src/test/jtx/impl/regkey.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -27,4 +27,4 @@ regkey(Account const& account, Account const& signer) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/sendmax.cpp b/src/test/jtx/impl/sendmax.cpp index 4a920f5be0..f117458cfa 100644 --- a/src/test/jtx/impl/sendmax.cpp +++ b/src/test/jtx/impl/sendmax.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -14,4 +14,4 @@ sendmax::operator()(Env& env, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/seq.cpp b/src/test/jtx/impl/seq.cpp index c127029def..99c6ddbf0d 100644 --- a/src/test/jtx/impl/seq.cpp +++ b/src/test/jtx/impl/seq.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -18,4 +18,4 @@ seq::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/sig.cpp b/src/test/jtx/impl/sig.cpp index 6d8a0b42c7..3ea7f669a7 100644 --- a/src/test/jtx/impl/sig.cpp +++ b/src/test/jtx/impl/sig.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -31,4 +31,4 @@ sig::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/tag.cpp b/src/test/jtx/impl/tag.cpp index f9a6128c54..8321322f75 100644 --- a/src/test/jtx/impl/tag.cpp +++ b/src/test/jtx/impl/tag.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -18,4 +18,4 @@ stag::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/testline.cpp b/src/test/jtx/impl/testline.cpp index 722dc33bff..fbcb1d2de7 100644 --- a/src/test/jtx/impl/testline.cpp +++ b/src/test/jtx/impl/testline.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -12,4 +12,4 @@ testline::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/ticket.cpp b/src/test/jtx/impl/ticket.cpp index 60318469fb..2cb1826bbb 100644 --- a/src/test/jtx/impl/ticket.cpp +++ b/src/test/jtx/impl/ticket.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -30,4 +30,4 @@ use::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/token.cpp b/src/test/jtx/impl/token.cpp index 281d8543b9..f74b66f9ae 100644 --- a/src/test/jtx/impl/token.cpp +++ b/src/test/jtx/impl/token.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { namespace token { @@ -72,7 +72,7 @@ getID( // sequence number. nftSeq += env.le(issuer)->at(~sfFirstNFTokenSequence).value_or(env.seq(issuer)); - return ripple::NFTokenMint::createNFTokenID( + return xrpl::NFTokenMint::createNFTokenID( flags, xferFee, issuer, nft::toTaxon(nfTokenTaxon), nftSeq); } @@ -223,4 +223,4 @@ modify(jtx::Account const& account, uint256 const& nftokenID) } // namespace token } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/trust.cpp b/src/test/jtx/impl/trust.cpp index d53f87773c..a553efa7f2 100644 --- a/src/test/jtx/impl/trust.cpp +++ b/src/test/jtx/impl/trust.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -65,4 +65,4 @@ claw( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/txflags.cpp b/src/test/jtx/impl/txflags.cpp index a7f69116d5..7b49f9380b 100644 --- a/src/test/jtx/impl/txflags.cpp +++ b/src/test/jtx/impl/txflags.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -14,4 +14,4 @@ txflags::operator()(Env&, JTx& jt) const } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/utility.cpp b/src/test/jtx/impl/utility.cpp index 92f7b16c8d..81bce576ce 100644 --- a/src/test/jtx/impl/utility.cpp +++ b/src/test/jtx/impl/utility.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -31,7 +31,7 @@ sign(Json::Value& jv, Account const& account, Json::Value& sigObject) Serializer ss; ss.add32(HashPrefix::txSign); parse(jv).addWithoutSigningFields(ss); - auto const sig = ripple::sign(account.pk(), account.sk(), ss.slice()); + auto const sig = xrpl::sign(account.pk(), account.sk(), ss.slice()); sigObject[jss::TxnSignature] = strHex(Slice{sig.data(), sig.size()}); } @@ -97,4 +97,4 @@ cmdToJSONRPC( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/vault.cpp b/src/test/jtx/impl/vault.cpp index a1295ba887..90250aece0 100644 --- a/src/test/jtx/impl/vault.cpp +++ b/src/test/jtx/impl/vault.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -81,4 +81,4 @@ Vault::clawback(ClawbackArgs const& args) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/impl/xchain_bridge.cpp b/src/test/jtx/impl/xchain_bridge.cpp index 5cfb6e4a11..cc6be6c737 100644 --- a/src/test/jtx/impl/xchain_bridge.cpp +++ b/src/test/jtx/impl/xchain_bridge.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -486,4 +486,4 @@ XChainBridgeObjects::createBridgeObjects(Env& mcEnv, Env& scEnv) } } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/invoice_id.h b/src/test/jtx/invoice_id.h index 492bb4a500..bdf1aa4250 100644 --- a/src/test/jtx/invoice_id.h +++ b/src/test/jtx/invoice_id.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -22,5 +22,5 @@ public: }; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/jtx_json.h b/src/test/jtx/jtx_json.h index 4334db58f8..32fd3c8d30 100644 --- a/src/test/jtx/jtx_json.h +++ b/src/test/jtx/jtx_json.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -40,6 +40,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/last_ledger_sequence.h b/src/test/jtx/last_ledger_sequence.h index 59e4b9f401..6544294bd6 100644 --- a/src/test/jtx/last_ledger_sequence.h +++ b/src/test/jtx/last_ledger_sequence.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -23,6 +23,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/ledgerStateFix.h b/src/test/jtx/ledgerStateFix.h index c1ab04f249..f93c1bc3d8 100644 --- a/src/test/jtx/ledgerStateFix.h +++ b/src/test/jtx/ledgerStateFix.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -20,6 +20,6 @@ nftPageLinks(jtx::Account const& acct, jtx::Account const& owner); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/memo.h b/src/test/jtx/memo.h index 4a1990e079..377dcbec4e 100644 --- a/src/test/jtx/memo.h +++ b/src/test/jtx/memo.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -124,6 +124,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/mpt.h b/src/test/jtx/mpt.h index f9c58ebc9e..2f6bbb9ea8 100644 --- a/src/test/jtx/mpt.h +++ b/src/test/jtx/mpt.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -313,6 +313,6 @@ private: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/multisign.h b/src/test/jtx/multisign.h index 68dc35442b..8582b27a77 100644 --- a/src/test/jtx/multisign.h +++ b/src/test/jtx/multisign.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -118,6 +118,6 @@ using siglists = owner_count; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/noop.h b/src/test/jtx/noop.h index 70be63052a..3ef3a57c4b 100644 --- a/src/test/jtx/noop.h +++ b/src/test/jtx/noop.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -16,6 +16,6 @@ noop(Account const& account) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/offer.h b/src/test/jtx/offer.h index 45dd358375..8b01a9381b 100644 --- a/src/test/jtx/offer.h +++ b/src/test/jtx/offer.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -24,6 +24,6 @@ offer_cancel(Account const& account, std::uint32_t offerSeq); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/owners.h b/src/test/jtx/owners.h index 326835d507..fabaa148e4 100644 --- a/src/test/jtx/owners.h +++ b/src/test/jtx/owners.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { @@ -74,6 +74,6 @@ using offers = owner_count; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/paths.h b/src/test/jtx/paths.h index 2ea4b623fc..b603db3f7b 100644 --- a/src/test/jtx/paths.h +++ b/src/test/jtx/paths.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -94,6 +94,6 @@ path::append(T const& t, Args const&... args) } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/pay.h b/src/test/jtx/pay.h index 6ebcd25b0c..4ef13d72a3 100644 --- a/src/test/jtx/pay.h +++ b/src/test/jtx/pay.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -18,6 +18,6 @@ pay(Account const& account, Account const& to, AnyAmount amount); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/permissioned_dex.h b/src/test/jtx/permissioned_dex.h index b5c81a83ea..2023342ded 100644 --- a/src/test/jtx/permissioned_dex.h +++ b/src/test/jtx/permissioned_dex.h @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -31,4 +31,4 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/jtx/permissioned_domains.h b/src/test/jtx/permissioned_domains.h index 1cb81005c1..c0adacd0c5 100644 --- a/src/test/jtx/permissioned_domains.h +++ b/src/test/jtx/permissioned_domains.h @@ -5,13 +5,13 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { namespace pdomain { // Helpers for PermissionedDomains testing -using Credential = ripple::test::jtx::deposit::AuthorizeCredentials; +using Credential = xrpl::test::jtx::deposit::AuthorizeCredentials; using Credentials = std::vector; // helpers @@ -51,6 +51,6 @@ getNewDomain(std::shared_ptr const& meta); } // namespace pdomain } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/prop.h b/src/test/jtx/prop.h index 67a8e3f45c..3478e23d9b 100644 --- a/src/test/jtx/prop.h +++ b/src/test/jtx/prop.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -30,6 +30,6 @@ struct prop } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/quality.h b/src/test/jtx/quality.h index c05ccb0404..c112ad9934 100644 --- a/src/test/jtx/quality.h +++ b/src/test/jtx/quality.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -65,6 +65,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/rate.h b/src/test/jtx/rate.h index 1f0abd3e46..2ed8cec6f2 100644 --- a/src/test/jtx/rate.h +++ b/src/test/jtx/rate.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -15,6 +15,6 @@ rate(Account const& account, double multiplier); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/regkey.h b/src/test/jtx/regkey.h index 3f9d10596c..b3ab9a0ed9 100644 --- a/src/test/jtx/regkey.h +++ b/src/test/jtx/regkey.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -20,6 +20,6 @@ regkey(Account const& account, Account const& signer); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/require.h b/src/test/jtx/require.h index 3538df2cbc..21ff8a29ec 100644 --- a/src/test/jtx/require.h +++ b/src/test/jtx/require.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -63,6 +63,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/requires.h b/src/test/jtx/requires.h index 4e330c63cc..379c5ad67d 100644 --- a/src/test/jtx/requires.h +++ b/src/test/jtx/requires.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -15,6 +15,6 @@ using requires_t = std::vector; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/rpc.h b/src/test/jtx/rpc.h index a525b04e6b..5a7c205aac 100644 --- a/src/test/jtx/rpc.h +++ b/src/test/jtx/rpc.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -63,6 +63,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/sendmax.h b/src/test/jtx/sendmax.h index f1cc0b2d8c..9082ef9ddd 100644 --- a/src/test/jtx/sendmax.h +++ b/src/test/jtx/sendmax.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -26,6 +26,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/seq.h b/src/test/jtx/seq.h index 6e174b5f97..102961db0e 100644 --- a/src/test/jtx/seq.h +++ b/src/test/jtx/seq.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -36,6 +36,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/sig.h b/src/test/jtx/sig.h index 1b21607d4d..27d18b322e 100644 --- a/src/test/jtx/sig.h +++ b/src/test/jtx/sig.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -60,6 +60,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/tag.h b/src/test/jtx/tag.h index 586eae1f27..688d2e92c1 100644 --- a/src/test/jtx/tag.h +++ b/src/test/jtx/tag.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -41,6 +41,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/tags.h b/src/test/jtx/tags.h index 631d40bb89..445bdebcb4 100644 --- a/src/test/jtx/tags.h +++ b/src/test/jtx/tags.h @@ -1,7 +1,7 @@ #ifndef XRPL_TEST_JTX_TAGS_H_INCLUDED #define XRPL_TEST_JTX_TAGS_H_INCLUDED -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -43,6 +43,6 @@ static increment_t const increment; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/ter.h b/src/test/jtx/ter.h index 9200b2a265..f13c2a90e6 100644 --- a/src/test/jtx/ter.h +++ b/src/test/jtx/ter.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -35,6 +35,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/testline.h b/src/test/jtx/testline.h index 65dd3b7d92..beda870345 100644 --- a/src/test/jtx/testline.h +++ b/src/test/jtx/testline.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -29,6 +29,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/ticket.h b/src/test/jtx/ticket.h index 881757df5c..10cb772bbd 100644 --- a/src/test/jtx/ticket.h +++ b/src/test/jtx/ticket.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -47,6 +47,6 @@ using tickets = owner_count; } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/token.h b/src/test/jtx/token.h index 0f5921d080..5280799582 100644 --- a/src/test/jtx/token.h +++ b/src/test/jtx/token.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -227,6 +227,6 @@ modify(jtx::Account const& account, uint256 const& nftokenID); } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif // XRPL_TEST_JTX_NFT_H_INCLUDED diff --git a/src/test/jtx/trust.h b/src/test/jtx/trust.h index 667ecc9c2e..69a3e7ba53 100644 --- a/src/test/jtx/trust.h +++ b/src/test/jtx/trust.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -30,6 +30,6 @@ claw( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/txflags.h b/src/test/jtx/txflags.h index 26a89c0f76..75a0d2740b 100644 --- a/src/test/jtx/txflags.h +++ b/src/test/jtx/txflags.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -24,6 +24,6 @@ public: } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/utility.h b/src/test/jtx/utility.h index 25708d8bb3..a824f86c1a 100644 --- a/src/test/jtx/utility.h +++ b/src/test/jtx/utility.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -60,6 +60,6 @@ cmdToJSONRPC( } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/vault.h b/src/test/jtx/vault.h index 5ffcd620c1..485940f9f4 100644 --- a/src/test/jtx/vault.h +++ b/src/test/jtx/vault.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -85,6 +85,6 @@ struct Vault } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/jtx/xchain_bridge.h b/src/test/jtx/xchain_bridge.h index be5e4b4a5f..dfd6073ca4 100644 --- a/src/test/jtx/xchain_bridge.h +++ b/src/test/jtx/xchain_bridge.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { @@ -237,6 +237,6 @@ struct XChainBridgeObjects } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/ledger/BookDirs_test.cpp b/src/test/ledger/BookDirs_test.cpp index 7157d17301..4f5cf5cca2 100644 --- a/src/test/ledger/BookDirs_test.cpp +++ b/src/test/ledger/BookDirs_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct BookDirs_test : public beast::unit_test::suite @@ -91,7 +91,7 @@ struct BookDirs_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(BookDirs, ledger, ripple); +BEAST_DEFINE_TESTSUITE(BookDirs, ledger, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/ledger/Directory_test.cpp b/src/test/ledger/Directory_test.cpp index 68c3286660..721b919238 100644 --- a/src/test/ledger/Directory_test.cpp +++ b/src/test/ledger/Directory_test.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct Directory_test : public beast::unit_test::suite @@ -571,7 +571,7 @@ struct Directory_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE_PRIO(Directory, ledger, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(Directory, ledger, xrpl, 1); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/ledger/PaymentSandbox_test.cpp b/src/test/ledger/PaymentSandbox_test.cpp index 200aac76e2..b5acb38156 100644 --- a/src/test/ledger/PaymentSandbox_test.cpp +++ b/src/test/ledger/PaymentSandbox_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class PaymentSandbox_test : public beast::unit_test::suite @@ -406,7 +406,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(PaymentSandbox, ledger, ripple); +BEAST_DEFINE_TESTSUITE(PaymentSandbox, ledger, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/ledger/PendingSaves_test.cpp b/src/test/ledger/PendingSaves_test.cpp index 95b1cc8ab7..ddf371e913 100644 --- a/src/test/ledger/PendingSaves_test.cpp +++ b/src/test/ledger/PendingSaves_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { struct PendingSaves_test : public beast::unit_test::suite @@ -40,7 +40,7 @@ struct PendingSaves_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(PendingSaves, ledger, ripple); +BEAST_DEFINE_TESTSUITE(PendingSaves, ledger, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/ledger/SkipList_test.cpp b/src/test/ledger/SkipList_test.cpp index 4869036014..12fedea5c1 100644 --- a/src/test/ledger/SkipList_test.cpp +++ b/src/test/ledger/SkipList_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class SkipList_test : public beast::unit_test::suite @@ -87,7 +87,7 @@ class SkipList_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(SkipList, ledger, ripple); +BEAST_DEFINE_TESTSUITE(SkipList, ledger, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/ledger/View_test.cpp b/src/test/ledger/View_test.cpp index a8f3f7fc3b..a486792209 100644 --- a/src/test/ledger/View_test.cpp +++ b/src/test/ledger/View_test.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class View_test : public beast::unit_test::suite @@ -1145,8 +1145,8 @@ class GetAmendments_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(View, ledger, ripple); -BEAST_DEFINE_TESTSUITE(GetAmendments, ledger, ripple); +BEAST_DEFINE_TESTSUITE(View, ledger, xrpl); +BEAST_DEFINE_TESTSUITE(GetAmendments, ledger, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/nodestore/Backend_test.cpp b/src/test/nodestore/Backend_test.cpp index b65c138305..07b35ed9fc 100644 --- a/src/test/nodestore/Backend_test.cpp +++ b/src/test/nodestore/Backend_test.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { @@ -101,7 +101,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Backend, nodestore, ripple); +BEAST_DEFINE_TESTSUITE(Backend, nodestore, xrpl); } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/test/nodestore/Basics_test.cpp b/src/test/nodestore/Basics_test.cpp index 350c44ec5d..3a7c6a1fdd 100644 --- a/src/test/nodestore/Basics_test.cpp +++ b/src/test/nodestore/Basics_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { // Tests predictable batches, and NodeObject blob encoding @@ -66,7 +66,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(NodeStoreBasic, nodestore, ripple); +BEAST_DEFINE_TESTSUITE(NodeStoreBasic, nodestore, xrpl); } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/test/nodestore/Database_test.cpp b/src/test/nodestore/Database_test.cpp index 0efb1e7ba1..e5446374ec 100644 --- a/src/test/nodestore/Database_test.cpp +++ b/src/test/nodestore/Database_test.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { @@ -28,8 +28,8 @@ public: { testcase("Config"); - using namespace ripple::test; - using namespace ripple::test::jtx; + using namespace xrpl::test; + using namespace xrpl::test::jtx; auto const integrityWarning = "reducing the data integrity guarantees from the " @@ -746,7 +746,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Database, nodestore, ripple); +BEAST_DEFINE_TESTSUITE(Database, nodestore, xrpl); } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/test/nodestore/NuDBFactory_test.cpp b/src/test/nodestore/NuDBFactory_test.cpp index 951af7dd5b..b91425259c 100644 --- a/src/test/nodestore/NuDBFactory_test.cpp +++ b/src/test/nodestore/NuDBFactory_test.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { class NuDBFactory_test : public TestBase @@ -452,7 +452,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(NuDBFactory, ripple_core, ripple); +BEAST_DEFINE_TESTSUITE(NuDBFactory, xrpl_core, xrpl); } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/test/nodestore/TestBase.h b/src/test/nodestore/TestBase.h index 0675ad85d4..83db83b1df 100644 --- a/src/test/nodestore/TestBase.h +++ b/src/test/nodestore/TestBase.h @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { namespace NodeStore { /** Binary function that satisfies the strict-weak-ordering requirement. @@ -209,6 +209,6 @@ public: }; } // namespace NodeStore -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/nodestore/Timing_test.cpp b/src/test/nodestore/Timing_test.cpp index e6238925bb..9c91311416 100644 --- a/src/test/nodestore/Timing_test.cpp +++ b/src/test/nodestore/Timing_test.cpp @@ -27,7 +27,7 @@ #define NODESTORE_TIMING_DO_VERIFY 0 #endif -namespace ripple { +namespace xrpl { namespace NodeStore { std::unique_ptr @@ -759,7 +759,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Timing, nodestore, ripple, 1); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Timing, nodestore, xrpl, 1); } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/test/nodestore/import_test.cpp b/src/test/nodestore/import_test.cpp index 30aaaa2ea9..9a786801cb 100644 --- a/src/test/nodestore/import_test.cpp +++ b/src/test/nodestore/import_test.cpp @@ -40,7 +40,7 @@ multi(32gb): */ -namespace ripple { +namespace xrpl { namespace detail { @@ -530,11 +530,11 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL(import, nodestore, ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(import, nodestore, xrpl); #endif //------------------------------------------------------------------------------ } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/test/nodestore/varint_test.cpp b/src/test/nodestore/varint_test.cpp index 148d593aae..7ef624e777 100644 --- a/src/test/nodestore/varint_test.cpp +++ b/src/test/nodestore/varint_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace NodeStore { namespace tests { @@ -52,8 +52,8 @@ public: } }; -BEAST_DEFINE_TESTSUITE(varint, nodestore, ripple); +BEAST_DEFINE_TESTSUITE(varint, nodestore, xrpl); } // namespace tests } // namespace NodeStore -} // namespace ripple +} // namespace xrpl diff --git a/src/test/overlay/ProtocolVersion_test.cpp b/src/test/overlay/ProtocolVersion_test.cpp index d6bbe6282a..507a42eca0 100644 --- a/src/test/overlay/ProtocolVersion_test.cpp +++ b/src/test/overlay/ProtocolVersion_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { class ProtocolVersion_test : public beast::unit_test::suite { @@ -79,6 +79,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ProtocolVersion, overlay, ripple); +BEAST_DEFINE_TESTSUITE(ProtocolVersion, overlay, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/overlay/cluster_test.cpp b/src/test/overlay/cluster_test.cpp index d29e143cff..4638434233 100644 --- a/src/test/overlay/cluster_test.cpp +++ b/src/test/overlay/cluster_test.cpp @@ -6,10 +6,10 @@ #include #include -namespace ripple { +namespace xrpl { namespace tests { -class cluster_test : public ripple::TestSuite +class cluster_test : public xrpl::TestSuite { test::SuiteJournal journal_; @@ -248,7 +248,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(cluster, overlay, ripple); +BEAST_DEFINE_TESTSUITE(cluster, overlay, xrpl); } // namespace tests -} // namespace ripple +} // namespace xrpl diff --git a/src/test/overlay/compression_test.cpp b/src/test/overlay/compression_test.cpp index 4e001115d1..2be69a74c9 100644 --- a/src/test/overlay/compression_test.cpp +++ b/src/test/overlay/compression_test.cpp @@ -30,17 +30,17 @@ #include -namespace ripple { +namespace xrpl { namespace test { -using namespace ripple::test; -using namespace ripple::test::jtx; +using namespace xrpl::test; +using namespace xrpl::test::jtx; static uint256 ledgerHash(LedgerHeader const& info) { - return ripple::sha512Half( + return xrpl::sha512Half( HashPrefix::ledgerMaster, std::uint32_t(info.seq), std::uint64_t(info.drops.drops()), @@ -92,8 +92,8 @@ public: } boost::system::error_code ec; - auto header = ripple::detail::parseMessageHeader( - ec, buffers.data(), buffer.size()); + auto header = + xrpl::detail::parseMessageHeader(ec, buffers.data(), buffer.size()); BEAST_EXPECT(header); @@ -109,7 +109,7 @@ public: ZeroCopyInputStream stream(buffers.data()); stream.Skip(header->header_size); - auto decompressedSize = ripple::compression::decompress( + auto decompressedSize = xrpl::compression::decompress( stream, header->payload_wire_size, decompressed.data(), @@ -121,7 +121,7 @@ public: proto1->ParseFromArray(decompressed.data(), decompressedSize)); auto uncompressed = m.getBuffer(Compressed::Off); BEAST_EXPECT(std::equal( - uncompressed.begin() + ripple::compression::headerBytes, + uncompressed.begin() + xrpl::compression::headerBytes, uncompressed.end(), decompressed.begin())); } @@ -223,10 +223,10 @@ public: auto getLedger = std::make_shared(); getLedger->set_itype(protocol::liTS_CANDIDATE); getLedger->set_ltype(protocol::TMLedgerType::ltACCEPTED); - uint256 const hash(ripple::sha512Half(123456789)); + uint256 const hash(xrpl::sha512Half(123456789)); getLedger->set_ledgerhash(hash.begin(), hash.size()); getLedger->set_ledgerseq(123456789); - ripple::SHAMapNodeID sha(64, hash); + xrpl::SHAMapNodeID sha(64, hash); getLedger->add_nodeids(sha.getRawString()); getLedger->set_requestcookie(123456789); getLedger->set_querytype(protocol::qtINDIRECT); @@ -238,7 +238,7 @@ public: buildLedgerData(uint32_t n, Logs& logs) { auto ledgerData = std::make_shared(); - uint256 const hash(ripple::sha512Half(12356789)); + uint256 const hash(xrpl::sha512Half(12356789)); ledgerData->set_ledgerhash(hash.data(), hash.size()); ledgerData->set_ledgerseq(123456789); ledgerData->set_type(protocol::TMLedgerInfoType::liAS_NODE); @@ -255,9 +255,9 @@ public: LedgerHeader info; info.seq = i; info.parentCloseTime = ct; - info.hash = ripple::sha512Half(i); - info.txHash = ripple::sha512Half(i + 1); - info.accountHash = ripple::sha512Half(i + 2); + info.hash = xrpl::sha512Half(i); + info.txHash = xrpl::sha512Half(i + 1); + info.accountHash = xrpl::sha512Half(i + 2); info.parentHash = parentHash; info.drops = XRPAmount(10); info.closeTimeResolution = resolution; @@ -265,7 +265,7 @@ public: ct += resolution; parentHash = ledgerHash(info); Serializer nData; - ripple::addRaw(info, nData); + xrpl::addRaw(info, nData); ledgerData->add_nodes()->set_nodedata( nData.getDataPtr(), nData.getLength()); } @@ -282,15 +282,15 @@ public: TMGetObjectByHash_ObjectType_otTRANSACTION); getObject->set_query(true); getObject->set_seq(123456789); - uint256 hash(ripple::sha512Half(123456789)); + uint256 hash(xrpl::sha512Half(123456789)); getObject->set_ledgerhash(hash.data(), hash.size()); getObject->set_fat(true); for (int i = 0; i < 100; i++) { - uint256 hash(ripple::sha512Half(i)); + uint256 hash(xrpl::sha512Half(i)); auto object = getObject->add_objects(); object->set_hash(hash.data(), hash.size()); - ripple::SHAMapNodeID sha(64, hash); + xrpl::SHAMapNodeID sha(64, hash); object->set_nodeid(sha.getRawString()); object->set_index(""); object->set_data(""); @@ -323,7 +323,7 @@ public: list->set_manifest(s.data(), s.size()); list->set_version(3); STObject signature(sfSignature); - ripple::sign( + xrpl::sign( st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); Serializer s1; st.add(s1); @@ -356,7 +356,7 @@ public: list->set_manifest(s.data(), s.size()); list->set_version(4); STObject signature(sfSignature); - ripple::sign( + xrpl::sign( st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); Serializer s1; st.add(s1); @@ -469,7 +469,7 @@ public: boost::asio::ip::make_address("172.1.1.100"); auto env = getEnv(outboundEnable); - auto request = ripple::makeRequest( + auto request = xrpl::makeRequest( true, env->app().config().COMPRESSION, false, @@ -489,7 +489,7 @@ public: env.reset(); env = getEnv(inboundEnable); - auto http_resp = ripple::makeResponse( + auto http_resp = xrpl::makeResponse( true, http_request, addr, @@ -518,7 +518,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL(compression, overlay, ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(compression, overlay, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/overlay/handshake_test.cpp b/src/test/overlay/handshake_test.cpp index b3b7c261a7..8e2d5d5ec1 100644 --- a/src/test/overlay/handshake_test.cpp +++ b/src/test/overlay/handshake_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { @@ -40,7 +40,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(handshake, overlay, ripple); +BEAST_DEFINE_TESTSUITE(handshake, overlay, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/overlay/reduce_relay_test.cpp b/src/test/overlay/reduce_relay_test.cpp index 8447a9fc9f..6af27ea8f1 100644 --- a/src/test/overlay/reduce_relay_test.cpp +++ b/src/test/overlay/reduce_relay_test.cpp @@ -19,7 +19,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -1646,7 +1646,7 @@ vp_base_squelch_max_selected_peers=2 boost::asio::ip::make_address("172.1.1.100"); setEnv(outboundEnable); - auto request = ripple::makeRequest( + auto request = xrpl::makeRequest( true, env_.app().config().COMPRESSION, false, @@ -1665,7 +1665,7 @@ vp_base_squelch_max_selected_peers=2 BEAST_EXPECT(!(peerEnabled ^ inboundEnabled)); setEnv(inboundEnable); - auto http_resp = ripple::makeResponse( + auto http_resp = xrpl::makeResponse( true, http_request, addr, @@ -1736,9 +1736,9 @@ class reduce_relay_simulate_test : public reduce_relay_test } }; -BEAST_DEFINE_TESTSUITE(reduce_relay, overlay, ripple); -BEAST_DEFINE_TESTSUITE_MANUAL(reduce_relay_simulate, overlay, ripple); +BEAST_DEFINE_TESTSUITE(reduce_relay, overlay, xrpl); +BEAST_DEFINE_TESTSUITE_MANUAL(reduce_relay_simulate, overlay, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/overlay/short_read_test.cpp b/src/test/overlay/short_read_test.cpp index 05193e525c..2db35dd93e 100644 --- a/src/test/overlay/short_read_test.cpp +++ b/src/test/overlay/short_read_test.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { /* Findings from the test: @@ -638,6 +638,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(short_read, overlay, ripple); +BEAST_DEFINE_TESTSUITE(short_read, overlay, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/overlay/traffic_count_test.cpp b/src/test/overlay/traffic_count_test.cpp index d8c5636b59..a8948879d9 100644 --- a/src/test/overlay/traffic_count_test.cpp +++ b/src/test/overlay/traffic_count_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -132,7 +132,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(traffic_count, overlay, ripple); +BEAST_DEFINE_TESTSUITE(traffic_count, overlay, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/overlay/tx_reduce_relay_test.cpp b/src/test/overlay/tx_reduce_relay_test.cpp index 1ca9e7aac6..7286b3fd90 100644 --- a/src/test/overlay/tx_reduce_relay_test.cpp +++ b/src/test/overlay/tx_reduce_relay_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -265,6 +265,6 @@ private: } }; -BEAST_DEFINE_TESTSUITE(tx_reduce_relay, overlay, ripple); +BEAST_DEFINE_TESTSUITE(tx_reduce_relay, overlay, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/peerfinder/Livecache_test.cpp b/src/test/peerfinder/Livecache_test.cpp index 2218191b56..b9487d8ce7 100644 --- a/src/test/peerfinder/Livecache_test.cpp +++ b/src/test/peerfinder/Livecache_test.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { bool @@ -120,9 +120,7 @@ public: constexpr auto num_eps = 40; Livecache<> c(clock_, journal_); for (auto i = 0; i < num_eps; ++i) - add(beast::IP::randomEP(true), - c, - ripple::rand_int()); + add(beast::IP::randomEP(true), c, xrpl::rand_int()); auto h = c.hops.histogram(); if (!BEAST_EXPECT(!h.empty())) return; @@ -146,9 +144,9 @@ public: for (auto i = 0; i < 100; ++i) add(beast::IP::randomEP(true), c, - ripple::rand_int(Tuning::maxHops + 1)); + xrpl::rand_int(Tuning::maxHops + 1)); - using at_hop = std::vector; + using at_hop = std::vector; using all_hops = std::array; auto cmp_EP = [](Endpoint const& a, Endpoint const& b) { @@ -220,7 +218,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Livecache, peerfinder, ripple); +BEAST_DEFINE_TESTSUITE(Livecache, peerfinder, xrpl); } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl diff --git a/src/test/peerfinder/PeerFinder_test.cpp b/src/test/peerfinder/PeerFinder_test.cpp index 96052bdb1a..7ff1b9de01 100644 --- a/src/test/peerfinder/PeerFinder_test.cpp +++ b/src/test/peerfinder/PeerFinder_test.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { class PeerFinder_test : public beast::unit_test::suite @@ -395,7 +395,7 @@ public: std::uint16_t expectOut, std::uint16_t expectIn, std::uint16_t expectIpLimit) { - ripple::Config c; + xrpl::Config c; testcase(test); @@ -468,7 +468,7 @@ public: testcase("invalid config"); auto run = [&](std::string const& toLoad) { - ripple::Config c; + xrpl::Config c; try { c.loadFromString(toLoad); @@ -524,7 +524,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(PeerFinder, peerfinder, ripple); +BEAST_DEFINE_TESTSUITE(PeerFinder, peerfinder, xrpl); } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/ApiVersion_test.cpp b/src/test/protocol/ApiVersion_test.cpp index f9e897ad74..1dc8ef93f7 100644 --- a/src/test/protocol/ApiVersion_test.cpp +++ b/src/test/protocol/ApiVersion_test.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct ApiVersion_test : beast::unit_test::suite { @@ -49,7 +49,7 @@ struct ApiVersion_test : beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(ApiVersion, protocol, ripple); +BEAST_DEFINE_TESTSUITE(ApiVersion, protocol, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/BuildInfo_test.cpp b/src/test/protocol/BuildInfo_test.cpp index b153e03608..ae06511e85 100644 --- a/src/test/protocol/BuildInfo_test.cpp +++ b/src/test/protocol/BuildInfo_test.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { class BuildInfo_test : public beast::unit_test::suite { @@ -95,5 +95,5 @@ public: } }; -BEAST_DEFINE_TESTSUITE(BuildInfo, protocol, ripple); -} // namespace ripple +BEAST_DEFINE_TESTSUITE(BuildInfo, protocol, xrpl); +} // namespace xrpl diff --git a/src/test/protocol/Hooks_test.cpp b/src/test/protocol/Hooks_test.cpp index 9bbfc4850c..27f455f202 100644 --- a/src/test/protocol/Hooks_test.cpp +++ b/src/test/protocol/Hooks_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class Hooks_test : public beast::unit_test::suite { @@ -174,6 +174,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Hooks, protocol, ripple); +BEAST_DEFINE_TESTSUITE(Hooks, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/InnerObjectFormats_test.cpp b/src/test/protocol/InnerObjectFormats_test.cpp index 5593d4644d..c06524b90e 100644 --- a/src/test/protocol/InnerObjectFormats_test.cpp +++ b/src/test/protocol/InnerObjectFormats_test.cpp @@ -6,7 +6,7 @@ #include // RPC::containsError #include // STParsedJSONObject -namespace ripple { +namespace xrpl { namespace InnerObjectFormatsUnitTestDetail { @@ -182,6 +182,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(InnerObjectFormatsParsedJSON, protocol, ripple); +BEAST_DEFINE_TESTSUITE(InnerObjectFormatsParsedJSON, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/Issue_test.cpp b/src/test/protocol/Issue_test.cpp index cf0b6ff861..eec164f5b6 100644 --- a/src/test/protocol/Issue_test.cpp +++ b/src/test/protocol/Issue_test.cpp @@ -25,7 +25,7 @@ #endif #endif -namespace ripple { +namespace xrpl { class Issue_test : public beast::unit_test::suite { @@ -959,6 +959,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Issue, protocol, ripple); +BEAST_DEFINE_TESTSUITE(Issue, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/Memo_test.cpp b/src/test/protocol/Memo_test.cpp index 415d23190a..706ef79fe2 100644 --- a/src/test/protocol/Memo_test.cpp +++ b/src/test/protocol/Memo_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { class Memo_test : public beast::unit_test::suite { @@ -116,6 +116,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Memo, protocol, ripple); +BEAST_DEFINE_TESTSUITE(Memo, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/MultiApiJson_test.cpp b/src/test/protocol/MultiApiJson_test.cpp index fb1549f5fd..52daa0e0a6 100644 --- a/src/test/protocol/MultiApiJson_test.cpp +++ b/src/test/protocol/MultiApiJson_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { namespace { @@ -36,7 +36,7 @@ struct MultiApiJson_test : beast::unit_test::suite void run() override { - using ripple::detail::MultiApiJson; + using xrpl::detail::MultiApiJson; Json::Value const obj1 = makeJson("value", 1); Json::Value const obj2 = makeJson("value", 2); @@ -1049,7 +1049,7 @@ struct MultiApiJson_test : beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(MultiApiJson, protocol, ripple); +BEAST_DEFINE_TESTSUITE(MultiApiJson, protocol, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/PublicKey_test.cpp b/src/test/protocol/PublicKey_test.cpp index 3bc50f2d95..4af21cd037 100644 --- a/src/test/protocol/PublicKey_test.cpp +++ b/src/test/protocol/PublicKey_test.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { class PublicKey_test : public beast::unit_test::suite { @@ -450,6 +450,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(PublicKey, protocol, ripple); +BEAST_DEFINE_TESTSUITE(PublicKey, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/Quality_test.cpp b/src/test/protocol/Quality_test.cpp index 5c6af14312..840e903ed5 100644 --- a/src/test/protocol/Quality_test.cpp +++ b/src/test/protocol/Quality_test.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Quality_test : public beast::unit_test::suite { @@ -396,6 +396,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Quality, protocol, ripple); +BEAST_DEFINE_TESTSUITE(Quality, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STAccount_test.cpp b/src/test/protocol/STAccount_test.cpp index 397b150a6c..d469627d51 100644 --- a/src/test/protocol/STAccount_test.cpp +++ b/src/test/protocol/STAccount_test.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { struct STAccount_test : public beast::unit_test::suite { @@ -127,6 +127,6 @@ struct STAccount_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(STAccount, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STAccount, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STAmount_test.cpp b/src/test/protocol/STAmount_test.cpp index 694e351303..796ac91de1 100644 --- a/src/test/protocol/STAmount_test.cpp +++ b/src/test/protocol/STAmount_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class STAmount_test : public beast::unit_test::suite { @@ -1245,6 +1245,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(STAmount, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STAmount, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STInteger_test.cpp b/src/test/protocol/STInteger_test.cpp index 5852fc873c..73b4ca39ef 100644 --- a/src/test/protocol/STInteger_test.cpp +++ b/src/test/protocol/STInteger_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { struct STInteger_test : public beast::unit_test::suite { @@ -139,6 +139,6 @@ struct STInteger_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(STInteger, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STInteger, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STIssue_test.cpp b/src/test/protocol/STIssue_test.cpp index 110c544ec4..d64722712b 100644 --- a/src/test/protocol/STIssue_test.cpp +++ b/src/test/protocol/STIssue_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class STIssue_test : public beast::unit_test::suite @@ -140,7 +140,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(STIssue, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STIssue, protocol, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STNumber_test.cpp b/src/test/protocol/STNumber_test.cpp index af455c6592..1275c756cf 100644 --- a/src/test/protocol/STNumber_test.cpp +++ b/src/test/protocol/STNumber_test.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { struct STNumber_test : public beast::unit_test::suite { @@ -281,7 +281,7 @@ struct STNumber_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(STNumber, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STNumber, protocol, xrpl); void testCompile(std::ostream& out) @@ -290,4 +290,4 @@ testCompile(std::ostream& out) out << number; } -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STObject_test.cpp b/src/test/protocol/STObject_test.cpp index c0d0297e37..c01297b4e1 100644 --- a/src/test/protocol/STObject_test.cpp +++ b/src/test/protocol/STObject_test.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { class STObject_test : public beast::unit_test::suite { @@ -458,7 +458,7 @@ public: st[sf3] = std::vector{}; BEAST_EXPECT(cst[sf3].size() == 0); } - } // namespace ripple + } // namespace xrpl void testMalformed() @@ -503,6 +503,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(STObject, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STObject, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STParsedJSON_test.cpp b/src/test/protocol/STParsedJSON_test.cpp index 13983444da..9c3a08243b 100644 --- a/src/test/protocol/STParsedJSON_test.cpp +++ b/src/test/protocol/STParsedJSON_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class STParsedJSON_test : public beast::unit_test::suite { @@ -2332,6 +2332,6 @@ class STParsedJSON_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(STParsedJSON, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STParsedJSON, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STTx_test.cpp b/src/test/protocol/STTx_test.cpp index 50cd8c511f..1899b786f9 100644 --- a/src/test/protocol/STTx_test.cpp +++ b/src/test/protocol/STTx_test.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { /** * Return true if the string loosely matches the regex. @@ -1398,7 +1398,7 @@ public: SerialIter tenSit{tenDeep.slice()}; try { - auto stx = std::make_shared(tenSit); + auto stx = std::make_shared(tenSit); fail("STTx construction should have thrown."); } catch (std::runtime_error const& ex) @@ -1417,7 +1417,7 @@ public: SerialIter tooDeepSit{tooDeep.slice()}; try { - auto stx = std::make_shared(tooDeepSit); + auto stx = std::make_shared(tooDeepSit); fail("STTx construction should have thrown."); } catch (std::runtime_error const& ex) @@ -1463,7 +1463,7 @@ public: SerialIter nineSit{nineDeep.slice()}; try { - auto stx = std::make_shared(nineSit); + auto stx = std::make_shared(nineSit); fail("STTx construction should have thrown."); } catch (std::runtime_error const& ex) @@ -1483,7 +1483,7 @@ public: SerialIter tooDeepSit{tooDeep.slice()}; try { - auto stx = std::make_shared(tooDeepSit); + auto stx = std::make_shared(tooDeepSit); fail("STTx construction should have thrown."); } catch (std::runtime_error const& ex) @@ -1512,7 +1512,7 @@ public: { // Verify we have a valid transaction. SerialIter sit{serialized.slice()}; - auto stx = std::make_shared(sit); + auto stx = std::make_shared(sit); } // Tweak the serialized data to change the ClearFlag to @@ -1524,7 +1524,7 @@ public: SerialIter sit{serialized.slice()}; try { - auto stx = std::make_shared(sit); + auto stx = std::make_shared(sit); fail("An exception should have been thrown"); } catch (std::exception const& ex) @@ -1551,9 +1551,9 @@ public: // vary. BEAST_EXPECT(!tx2.ParseFromArray(payload1, sizeof(payload1))); - ripple::SerialIter sit(ripple::makeSlice(tx2.rawtransaction())); + xrpl::SerialIter sit(xrpl::makeSlice(tx2.rawtransaction())); - auto stx = std::make_shared(sit); + auto stx = std::make_shared(sit); fail("An exception should have been thrown"); } catch (std::exception const&) @@ -1563,8 +1563,8 @@ public: try { - ripple::SerialIter sit{payload2}; - auto stx = std::make_shared(sit); + xrpl::SerialIter sit{payload2}; + auto stx = std::make_shared(sit); fail("An exception should have been thrown"); } catch (std::exception const& ex) @@ -1574,8 +1574,8 @@ public: try { - ripple::SerialIter sit{payload3}; - auto stx = std::make_shared(sit); + xrpl::SerialIter sit{payload3}; + auto stx = std::make_shared(sit); fail("An exception should have been thrown"); } catch (std::exception const& ex) @@ -1586,8 +1586,8 @@ public: try { - ripple::SerialIter sit{payload4}; - auto stx = std::make_shared(sit); + xrpl::SerialIter sit{payload4}; + auto stx = std::make_shared(sit); fail("An exception should have been thrown"); } catch (std::exception const& ex) @@ -1837,7 +1837,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(STTx, protocol, ripple); -BEAST_DEFINE_TESTSUITE(InnerObjectFormatsSerializer, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STTx, protocol, xrpl); +BEAST_DEFINE_TESTSUITE(InnerObjectFormatsSerializer, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/STValidation_test.cpp b/src/test/protocol/STValidation_test.cpp index 88956ef2f6..3530d2f34a 100644 --- a/src/test/protocol/STValidation_test.cpp +++ b/src/test/protocol/STValidation_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { class STValidation_test : public beast::unit_test::suite { @@ -187,7 +187,7 @@ public: try { SerialIter sit{payload1}; - auto val = std::make_shared( + auto val = std::make_shared( sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("An exception should have been thrown"); } @@ -202,7 +202,7 @@ public: try { SerialIter sit{payload2}; - auto val = std::make_shared( + auto val = std::make_shared( sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("An exception should have been thrown"); } @@ -215,7 +215,7 @@ public: try { SerialIter sit{payload3}; - auto val = std::make_shared( + auto val = std::make_shared( sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("An exception should have been thrown"); } @@ -228,7 +228,7 @@ public: try { SerialIter sit{payload4}; - auto val = std::make_shared( + auto val = std::make_shared( sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("An exception should have been thrown"); } @@ -330,6 +330,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(STValidation, protocol, ripple); +BEAST_DEFINE_TESTSUITE(STValidation, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/SecretKey_test.cpp b/src/test/protocol/SecretKey_test.cpp index 803988e9d5..e7bdcc1916 100644 --- a/src/test/protocol/SecretKey_test.cpp +++ b/src/test/protocol/SecretKey_test.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { class SecretKey_test : public beast::unit_test::suite { @@ -1494,6 +1494,6 @@ inline static TestKeyData const ed25519TestVectors[] = { // clang-format on }; -BEAST_DEFINE_TESTSUITE(SecretKey, protocol, ripple); +BEAST_DEFINE_TESTSUITE(SecretKey, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/Seed_test.cpp b/src/test/protocol/Seed_test.cpp index dfac5416d9..65428295f8 100644 --- a/src/test/protocol/Seed_test.cpp +++ b/src/test/protocol/Seed_test.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { class Seed_test : public beast::unit_test::suite { @@ -339,6 +339,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Seed, protocol, ripple); +BEAST_DEFINE_TESTSUITE(Seed, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/SeqProxy_test.cpp b/src/test/protocol/SeqProxy_test.cpp index fefea5a638..d922dd1182 100644 --- a/src/test/protocol/SeqProxy_test.cpp +++ b/src/test/protocol/SeqProxy_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { struct SeqProxy_test : public beast::unit_test::suite { @@ -217,6 +217,6 @@ struct SeqProxy_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(SeqProxy, protocol, ripple); +BEAST_DEFINE_TESTSUITE(SeqProxy, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/Serializer_test.cpp b/src/test/protocol/Serializer_test.cpp index 1b99266dc4..c5b56c3029 100644 --- a/src/test/protocol/Serializer_test.cpp +++ b/src/test/protocol/Serializer_test.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { struct Serializer_test : public beast::unit_test::suite { @@ -45,6 +45,6 @@ struct Serializer_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(Serializer, protocol, ripple); +BEAST_DEFINE_TESTSUITE(Serializer, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/protocol/TER_test.cpp b/src/test/protocol/TER_test.cpp index 8c279a8c95..0d9c6cb96d 100644 --- a/src/test/protocol/TER_test.cpp +++ b/src/test/protocol/TER_test.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { struct TER_test : public beast::unit_test::suite { @@ -274,6 +274,6 @@ struct TER_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(TER, protocol, ripple); +BEAST_DEFINE_TESTSUITE(TER, protocol, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/resource/Logic_test.cpp b/src/test/resource/Logic_test.cpp index 2cb2625708..0e520d4983 100644 --- a/src/test/resource/Logic_test.cpp +++ b/src/test/resource/Logic_test.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace Resource { class ResourceManager_test : public beast::unit_test::suite @@ -272,7 +272,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ResourceManager, resource, ripple); +BEAST_DEFINE_TESTSUITE(ResourceManager, resource, xrpl); } // namespace Resource -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AMMInfo_test.cpp b/src/test/rpc/AMMInfo_test.cpp index 2e519d1fb2..c76fa15eb7 100644 --- a/src/test/rpc/AMMInfo_test.cpp +++ b/src/test/rpc/AMMInfo_test.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class AMMInfo_test : public jtx::AMMTestBase @@ -350,7 +350,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(AMMInfo, rpc, ripple); +BEAST_DEFINE_TESTSUITE(AMMInfo, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AccountCurrencies_test.cpp b/src/test/rpc/AccountCurrencies_test.cpp index c4833d11d4..b1417735be 100644 --- a/src/test/rpc/AccountCurrencies_test.cpp +++ b/src/test/rpc/AccountCurrencies_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { class AccountCurrencies_test : public beast::unit_test::suite { @@ -209,6 +209,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(AccountCurrencies, rpc, ripple); +BEAST_DEFINE_TESTSUITE(AccountCurrencies, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 5e2fc608b3..6370884124 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class AccountInfo_test : public beast::unit_test::suite @@ -693,15 +693,14 @@ public: testSignerListsApiVersion2(); testSignerListsV2(); - FeatureBitset const allFeatures{ - ripple::test::jtx::testable_amendments()}; + FeatureBitset const allFeatures{xrpl::test::jtx::testable_amendments()}; testAccountFlags(allFeatures); testAccountFlags(allFeatures - featureClawback); testAccountFlags(allFeatures - featureClawback - featureTokenEscrow); } }; -BEAST_DEFINE_TESTSUITE(AccountInfo, rpc, ripple); +BEAST_DEFINE_TESTSUITE(AccountInfo, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AccountLines_test.cpp b/src/test/rpc/AccountLines_test.cpp index 200331b9be..6d9b75a44e 100644 --- a/src/test/rpc/AccountLines_test.cpp +++ b/src/test/rpc/AccountLines_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { class AccountLines_test : public beast::unit_test::suite @@ -1400,7 +1400,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(AccountLines, rpc, ripple); +BEAST_DEFINE_TESTSUITE(AccountLines, rpc, xrpl); } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AccountObjects_test.cpp b/src/test/rpc/AccountObjects_test.cpp index 74c5a2c915..e438d50633 100644 --- a/src/test/rpc/AccountObjects_test.cpp +++ b/src/test/rpc/AccountObjects_test.cpp @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { static char const* bobs_account_objects[] = { @@ -1427,7 +1427,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(AccountObjects, rpc, ripple); +BEAST_DEFINE_TESTSUITE(AccountObjects, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AccountOffers_test.cpp b/src/test/rpc/AccountOffers_test.cpp index 500828d9d7..2c03239bd8 100644 --- a/src/test/rpc/AccountOffers_test.cpp +++ b/src/test/rpc/AccountOffers_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class AccountOffers_test : public beast::unit_test::suite @@ -320,7 +320,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(AccountOffers, rpc, ripple); +BEAST_DEFINE_TESTSUITE(AccountOffers, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AccountSet_test.cpp b/src/test/rpc/AccountSet_test.cpp index 3df3606a03..40ef4acba7 100644 --- a/src/test/rpc/AccountSet_test.cpp +++ b/src/test/rpc/AccountSet_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { class AccountSet_test : public beast::unit_test::suite { @@ -565,8 +565,7 @@ public: stx->at(sfSigningPubKey) = makeSlice(std::string("badkey")); env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { - auto const result = - ripple::apply(env.app(), view, *stx, tapNONE, j); + auto const result = xrpl::apply(env.app(), view, *stx, tapNONE, j); BEAST_EXPECT(result.ter == temBAD_SIGNATURE); BEAST_EXPECT(!result.applied); return result.applied; @@ -593,6 +592,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(AccountSet, rpc, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(AccountSet, rpc, xrpl, 1); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp index f9f21c5e87..e387e1bc4c 100644 --- a/src/test/rpc/AccountTx_test.cpp +++ b/src/test/rpc/AccountTx_test.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { @@ -938,7 +938,7 @@ public: testMPT(); } }; -BEAST_DEFINE_TESTSUITE(AccountTx, rpc, ripple); +BEAST_DEFINE_TESTSUITE(AccountTx, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/AmendmentBlocked_test.cpp b/src/test/rpc/AmendmentBlocked_test.cpp index 05fa4908f3..2c3f631ac8 100644 --- a/src/test/rpc/AmendmentBlocked_test.cpp +++ b/src/test/rpc/AmendmentBlocked_test.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { class AmendmentBlocked_test : public beast::unit_test::suite { @@ -236,6 +236,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(AmendmentBlocked, rpc, ripple); +BEAST_DEFINE_TESTSUITE(AmendmentBlocked, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/BookChanges_test.cpp b/src/test/rpc/BookChanges_test.cpp index 5f58dfc383..216f4bd895 100644 --- a/src/test/rpc/BookChanges_test.cpp +++ b/src/test/rpc/BookChanges_test.cpp @@ -4,7 +4,7 @@ #include "xrpl/beast/unit_test/suite.h" #include "xrpl/protocol/jss.h" -namespace ripple { +namespace xrpl { namespace test { class BookChanges_test : public beast::unit_test::suite @@ -124,7 +124,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(BookChanges, rpc, ripple); +BEAST_DEFINE_TESTSUITE(BookChanges, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Book_test.cpp b/src/test/rpc/Book_test.cpp index f2798671b0..3c7477745b 100644 --- a/src/test/rpc/Book_test.cpp +++ b/src/test/rpc/Book_test.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class Book_test : public beast::unit_test::suite @@ -2011,7 +2011,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(Book, rpc, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(Book, rpc, xrpl, 1); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Connect_test.cpp b/src/test/rpc/Connect_test.cpp index a01ee05ff2..8d5a2ca33f 100644 --- a/src/test/rpc/Connect_test.cpp +++ b/src/test/rpc/Connect_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { class Connect_test : public beast::unit_test::suite { @@ -36,6 +36,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Connect, rpc, ripple); +BEAST_DEFINE_TESTSUITE(Connect, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/DeliveredAmount_test.cpp b/src/test/rpc/DeliveredAmount_test.cpp index 79447af780..3e256aa03b 100644 --- a/src/test/rpc/DeliveredAmount_test.cpp +++ b/src/test/rpc/DeliveredAmount_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { // Helper class to track the expected number `delivered_amount` results. @@ -403,7 +403,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(DeliveredAmount, rpc, ripple); +BEAST_DEFINE_TESTSUITE(DeliveredAmount, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/DepositAuthorized_test.cpp b/src/test/rpc/DepositAuthorized_test.cpp index 6e46b077b8..968a3fd4dc 100644 --- a/src/test/rpc/DepositAuthorized_test.cpp +++ b/src/test/rpc/DepositAuthorized_test.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class DepositAuthorized_test : public beast::unit_test::suite @@ -622,7 +622,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(DepositAuthorized, rpc, ripple); +BEAST_DEFINE_TESTSUITE(DepositAuthorized, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Feature_test.cpp b/src/test/rpc/Feature_test.cpp index 058b4a9572..6b66da072e 100644 --- a/src/test/rpc/Feature_test.cpp +++ b/src/test/rpc/Feature_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class Feature_test : public beast::unit_test::suite { @@ -14,13 +14,13 @@ class Feature_test : public beast::unit_test::suite { testcase("internals"); - auto const& supportedAmendments = ripple::detail::supportedAmendments(); - auto const& allAmendments = ripple::allAmendments(); + auto const& supportedAmendments = xrpl::detail::supportedAmendments(); + auto const& allAmendments = xrpl::allAmendments(); BEAST_EXPECT( supportedAmendments.size() == - ripple::detail::numDownVotedAmendments() + - ripple::detail::numUpVotedAmendments()); + xrpl::detail::numDownVotedAmendments() + + xrpl::detail::numUpVotedAmendments()); { std::size_t up = 0, down = 0, obsolete = 0; for (auto const& [name, vote] : supportedAmendments) @@ -54,8 +54,8 @@ class Feature_test : public beast::unit_test::suite } } BEAST_EXPECT( - down + obsolete == ripple::detail::numDownVotedAmendments()); - BEAST_EXPECT(up == ripple::detail::numUpVotedAmendments()); + down + obsolete == xrpl::detail::numDownVotedAmendments()); + BEAST_EXPECT(up == xrpl::detail::numUpVotedAmendments()); } { std::size_t supported = 0, unsupported = 0, retired = 0; @@ -93,7 +93,7 @@ class Feature_test : public beast::unit_test::suite // Test all the supported features. In a perfect world, this would test // FeatureCollections::featureNames, but that's private. Leave it that // way. - auto const supported = ripple::detail::supportedAmendments(); + auto const supported = xrpl::detail::supportedAmendments(); for (auto const& [feature, vote] : supported) { @@ -139,7 +139,7 @@ class Feature_test : public beast::unit_test::suite Env env{*this}; std::map const& votes = - ripple::detail::supportedAmendments(); + xrpl::detail::supportedAmendments(); auto jrr = env.rpc("feature")[jss::result]; if (!BEAST_EXPECT(jrr.isMember(jss::features))) @@ -325,7 +325,7 @@ class Feature_test : public beast::unit_test::suite Env env{*this, FeatureBitset{}}; std::map const& votes = - ripple::detail::supportedAmendments(); + xrpl::detail::supportedAmendments(); auto jrr = env.rpc("feature")[jss::result]; if (!BEAST_EXPECT(jrr.isMember(jss::features))) @@ -423,7 +423,7 @@ class Feature_test : public beast::unit_test::suite // to avoid maintenance as more amendments are added in the future. BEAST_EXPECT(majorities.size() >= 2); std::map const& votes = - ripple::detail::supportedAmendments(); + xrpl::detail::supportedAmendments(); jrr = env.rpc("feature")[jss::result]; if (!BEAST_EXPECT(jrr.isMember(jss::features))) @@ -607,6 +607,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Feature, rpc, ripple); +BEAST_DEFINE_TESTSUITE(Feature, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/GRPCTestClientBase.h b/src/test/rpc/GRPCTestClientBase.h index b5e50b1c94..6cb806a562 100644 --- a/src/test/rpc/GRPCTestClientBase.h +++ b/src/test/rpc/GRPCTestClientBase.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { struct GRPCTestClientBase @@ -29,5 +29,5 @@ struct GRPCTestClientBase }; } // namespace test -} // namespace ripple +} // namespace xrpl #endif // XRPL_GRPCTESTCLIENTBASE_H diff --git a/src/test/rpc/GatewayBalances_test.cpp b/src/test/rpc/GatewayBalances_test.cpp index 23ac199b4e..40f56dfc81 100644 --- a/src/test/rpc/GatewayBalances_test.cpp +++ b/src/test/rpc/GatewayBalances_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class GatewayBalances_test : public beast::unit_test::suite @@ -243,7 +243,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(GatewayBalances, rpc, ripple); +BEAST_DEFINE_TESTSUITE(GatewayBalances, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/GetAggregatePrice_test.cpp b/src/test/rpc/GetAggregatePrice_test.cpp index a1a09ab592..52f82ffc6c 100644 --- a/src/test/rpc/GetAggregatePrice_test.cpp +++ b/src/test/rpc/GetAggregatePrice_test.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { namespace jtx { namespace oracle { @@ -327,9 +327,9 @@ public: } }; -BEAST_DEFINE_TESTSUITE(GetAggregatePrice, rpc, ripple); +BEAST_DEFINE_TESTSUITE(GetAggregatePrice, rpc, xrpl); } // namespace oracle } // namespace jtx } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/GetCounts_test.cpp b/src/test/rpc/GetCounts_test.cpp index ea8d7a896a..b9ad5ec254 100644 --- a/src/test/rpc/GetCounts_test.cpp +++ b/src/test/rpc/GetCounts_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class GetCounts_test : public beast::unit_test::suite { @@ -101,6 +101,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(GetCounts, rpc, ripple); +BEAST_DEFINE_TESTSUITE(GetCounts, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Handler_test.cpp b/src/test/rpc/Handler_test.cpp index b0f386b925..9a6f1b3aa1 100644 --- a/src/test/rpc/Handler_test.cpp +++ b/src/test/rpc/Handler_test.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple::test { +namespace xrpl::test { // NOTE: there should be no need for this function; // `std::cout << some_duration` should just work if built with a compliant @@ -82,7 +82,7 @@ class Handler_test : public beast::unit_test::suite std::ranlux48 prng(dev()); std::vector names = - test::jtx::make_vector(ripple::RPC::getHandlerNames()); + test::jtx::make_vector(xrpl::RPC::getHandlerNames()); std::uniform_int_distribution distr{0, names.size() - 1}; @@ -109,6 +109,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE_MANUAL(Handler, rpc, ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(Handler, rpc, xrpl); -} // namespace ripple::test +} // namespace xrpl::test diff --git a/src/test/rpc/JSONRPC_test.cpp b/src/test/rpc/JSONRPC_test.cpp index 7bcc26e3d3..4d3f0a5098 100644 --- a/src/test/rpc/JSONRPC_test.cpp +++ b/src/test/rpc/JSONRPC_test.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { @@ -2917,7 +2917,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(JSONRPC, rpc, ripple); +BEAST_DEFINE_TESTSUITE(JSONRPC, rpc, xrpl); } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/KeyGeneration_test.cpp b/src/test/rpc/KeyGeneration_test.cpp index b1bbac7340..23f2723d6a 100644 --- a/src/test/rpc/KeyGeneration_test.cpp +++ b/src/test/rpc/KeyGeneration_test.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { @@ -75,7 +75,7 @@ static key_strings const strong_brain_strings = { "attacks.", }; -class WalletPropose_test : public ripple::TestSuite +class WalletPropose_test : public xrpl::TestSuite { public: void @@ -875,7 +875,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(WalletPropose, rpc, ripple); +BEAST_DEFINE_TESTSUITE(WalletPropose, rpc, xrpl); } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/LedgerClosed_test.cpp b/src/test/rpc/LedgerClosed_test.cpp index ba25a115c3..2bc5c2b0c9 100644 --- a/src/test/rpc/LedgerClosed_test.cpp +++ b/src/test/rpc/LedgerClosed_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { class LedgerClosed_test : public beast::unit_test::suite { @@ -49,6 +49,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LedgerClosed, rpc, ripple); +BEAST_DEFINE_TESTSUITE(LedgerClosed, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/LedgerData_test.cpp b/src/test/rpc/LedgerData_test.cpp index 9ac61c277a..66be8486b4 100644 --- a/src/test/rpc/LedgerData_test.cpp +++ b/src/test/rpc/LedgerData_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { class LedgerData_test : public beast::unit_test::suite { @@ -473,6 +473,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE_PRIO(LedgerData, rpc, ripple, 1); +BEAST_DEFINE_TESTSUITE_PRIO(LedgerData, rpc, xrpl, 1); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index 8e9be02dda..ef5abdd800 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -19,7 +19,7 @@ using source_location = std::experimental::source_location; #include using std::source_location; #endif -namespace ripple { +namespace xrpl { namespace test { @@ -1775,8 +1775,8 @@ class LedgerEntry_test : public beast::unit_test::suite testInvalidOracleLedgerEntry() { testcase("Invalid Oracle Ledger Entry"); - using namespace ripple::test::jtx; - using namespace ripple::test::jtx::oracle; + using namespace xrpl::test::jtx; + using namespace xrpl::test::jtx::oracle; Env env(*this); Account const owner("owner"); @@ -1802,8 +1802,8 @@ class LedgerEntry_test : public beast::unit_test::suite testOracleLedgerEntry() { testcase("Oracle Ledger Entry"); - using namespace ripple::test::jtx; - using namespace ripple::test::jtx::oracle; + using namespace xrpl::test::jtx; + using namespace xrpl::test::jtx::oracle; Env env(*this); auto const baseFee = @@ -2368,8 +2368,8 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LedgerEntry, rpc, ripple); -BEAST_DEFINE_TESTSUITE(LedgerEntry_XChain, rpc, ripple); +BEAST_DEFINE_TESTSUITE(LedgerEntry, rpc, xrpl); +BEAST_DEFINE_TESTSUITE(LedgerEntry_XChain, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/LedgerHeader_test.cpp b/src/test/rpc/LedgerHeader_test.cpp index 7ebf7a8a94..3af82d683e 100644 --- a/src/test/rpc/LedgerHeader_test.cpp +++ b/src/test/rpc/LedgerHeader_test.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LedgerHeader_test : public beast::unit_test::suite { @@ -68,6 +68,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LedgerHeader, rpc, ripple); +BEAST_DEFINE_TESTSUITE(LedgerHeader, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 7728973045..583ff0a531 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -738,7 +738,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LedgerRPC, rpc, ripple); +BEAST_DEFINE_TESTSUITE(LedgerRPC, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/LedgerRequest_test.cpp b/src/test/rpc/LedgerRequest_test.cpp index 013d4cbe0f..153c6ad508 100644 --- a/src/test/rpc/LedgerRequest_test.cpp +++ b/src/test/rpc/LedgerRequest_test.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { @@ -377,7 +377,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(LedgerRequest, rpc, ripple); +BEAST_DEFINE_TESTSUITE(LedgerRequest, rpc, xrpl); } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/ManifestRPC_test.cpp b/src/test/rpc/ManifestRPC_test.cpp index a875ecb479..5d4f4900eb 100644 --- a/src/test/rpc/ManifestRPC_test.cpp +++ b/src/test/rpc/ManifestRPC_test.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class ManifestRPC_test : public beast::unit_test::suite @@ -73,6 +73,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ManifestRPC, rpc, ripple); +BEAST_DEFINE_TESTSUITE(ManifestRPC, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/NoRippleCheck_test.cpp b/src/test/rpc/NoRippleCheck_test.cpp index 4d9af8524f..7ed2cd8fd1 100644 --- a/src/test/rpc/NoRippleCheck_test.cpp +++ b/src/test/rpc/NoRippleCheck_test.cpp @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { class NoRippleCheck_test : public beast::unit_test::suite { @@ -289,7 +289,7 @@ class NoRippleCheckLimits_test : public beast::unit_test::suite // be better if we could add this functionality to Env somehow // or otherwise disable endpoint charging for certain test // cases. - using namespace ripple::Resource; + using namespace xrpl::Resource; using namespace std::chrono; using namespace beast::IP; auto c = env.app().getResourceManager().newInboundEndpoint( @@ -304,7 +304,7 @@ class NoRippleCheckLimits_test : public beast::unit_test::suite } }; - for (auto i = 0; i < ripple::RPC::Tuning::noRippleCheck.rmax + 5; ++i) + for (auto i = 0; i < xrpl::RPC::Tuning::noRippleCheck.rmax + 5; ++i) { if (!admin) checkBalance(); @@ -379,12 +379,12 @@ public: } }; -BEAST_DEFINE_TESTSUITE(NoRippleCheck, rpc, ripple); +BEAST_DEFINE_TESTSUITE(NoRippleCheck, rpc, xrpl); // These tests that deal with limit amounts are slow because of the // offer/account setup, so making them manual -- the additional coverage // provided by them is minimal -BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(NoRippleCheckLimits, rpc, ripple, 1); +BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(NoRippleCheckLimits, rpc, xrpl, 1); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/NoRipple_test.cpp b/src/test/rpc/NoRipple_test.cpp index 8e68df0e8b..040ceaaa29 100644 --- a/src/test/rpc/NoRipple_test.cpp +++ b/src/test/rpc/NoRipple_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -269,7 +269,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(NoRipple, rpc, ripple); +BEAST_DEFINE_TESTSUITE(NoRipple, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/OwnerInfo_test.cpp b/src/test/rpc/OwnerInfo_test.cpp index b3a4f6a0a4..b47b529680 100644 --- a/src/test/rpc/OwnerInfo_test.cpp +++ b/src/test/rpc/OwnerInfo_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class OwnerInfo_test : public beast::unit_test::suite { @@ -200,6 +200,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(OwnerInfo, rpc, ripple); +BEAST_DEFINE_TESTSUITE(OwnerInfo, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Peers_test.cpp b/src/test/rpc/Peers_test.cpp index a066a0a709..639f5e98cb 100644 --- a/src/test/rpc/Peers_test.cpp +++ b/src/test/rpc/Peers_test.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class Peers_test : public beast::unit_test::suite { @@ -73,6 +73,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Peers, rpc, ripple); +BEAST_DEFINE_TESTSUITE(Peers, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/RPCCall_test.cpp b/src/test/rpc/RPCCall_test.cpp index 7647dc5f65..682584f40b 100644 --- a/src/test/rpc/RPCCall_test.cpp +++ b/src/test/rpc/RPCCall_test.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { struct RPCCallTestData @@ -5990,7 +5990,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(RPCCall, rpc, ripple); +BEAST_DEFINE_TESTSUITE(RPCCall, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/RPCHelpers_test.cpp b/src/test/rpc/RPCHelpers_test.cpp index e2e5f5fcf9..f180bd5c1a 100644 --- a/src/test/rpc/RPCHelpers_test.cpp +++ b/src/test/rpc/RPCHelpers_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class RPCHelpers_test : public beast::unit_test::suite @@ -70,7 +70,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(RPCHelpers, rpc, ripple); +BEAST_DEFINE_TESTSUITE(RPCHelpers, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/RPCOverload_test.cpp b/src/test/rpc/RPCOverload_test.cpp index 3eef88ff2a..d05dba4606 100644 --- a/src/test/rpc/RPCOverload_test.cpp +++ b/src/test/rpc/RPCOverload_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class RPCOverload_test : public beast::unit_test::suite @@ -70,7 +70,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(RPCOverload, rpc, ripple); +BEAST_DEFINE_TESTSUITE(RPCOverload, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/RobustTransaction_test.cpp b/src/test/rpc/RobustTransaction_test.cpp index d52e08f7ac..b0d0cdafd5 100644 --- a/src/test/rpc/RobustTransaction_test.cpp +++ b/src/test/rpc/RobustTransaction_test.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class RobustTransaction_test : public beast::unit_test::suite @@ -490,7 +490,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(RobustTransaction, rpc, ripple); +BEAST_DEFINE_TESTSUITE(RobustTransaction, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Roles_test.cpp b/src/test/rpc/Roles_test.cpp index 777cf1e2a2..4fa99b432b 100644 --- a/src/test/rpc/Roles_test.cpp +++ b/src/test/rpc/Roles_test.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -370,8 +370,8 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Roles, rpc, ripple); +BEAST_DEFINE_TESTSUITE(Roles, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/ServerDefinitions_test.cpp b/src/test/rpc/ServerDefinitions_test.cpp index 051e9e00eb..ae2cccd908 100644 --- a/src/test/rpc/ServerDefinitions_test.cpp +++ b/src/test/rpc/ServerDefinitions_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -143,7 +143,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ServerDefinitions, rpc, ripple); +BEAST_DEFINE_TESTSUITE(ServerDefinitions, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/ServerInfo_test.cpp b/src/test/rpc/ServerInfo_test.cpp index d149a0899c..27b554e38b 100644 --- a/src/test/rpc/ServerInfo_test.cpp +++ b/src/test/rpc/ServerInfo_test.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { @@ -162,7 +162,7 @@ admin = 127.0.0.1 } }; -BEAST_DEFINE_TESTSUITE(ServerInfo, rpc, ripple); +BEAST_DEFINE_TESTSUITE(ServerInfo, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Simulate_test.cpp b/src/test/rpc/Simulate_test.cpp index 61d3f1ce6e..2a85e2a928 100644 --- a/src/test/rpc/Simulate_test.cpp +++ b/src/test/rpc/Simulate_test.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { @@ -1316,8 +1316,8 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Simulate, rpc, ripple); +BEAST_DEFINE_TESTSUITE(Simulate, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Status_test.cpp b/src/test/rpc/Status_test.cpp index 5e6ac1bca4..c2e9c836df 100644 --- a/src/test/rpc/Status_test.cpp +++ b/src/test/rpc/Status_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { class codeString_test : public beast::unit_test::suite @@ -202,4 +202,4 @@ public: BEAST_DEFINE_TESTSUITE(fillJson, rpc, RPC); } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Subscribe_test.cpp b/src/test/rpc/Subscribe_test.cpp index a4eea3f12c..1637554f5c 100644 --- a/src/test/rpc/Subscribe_test.cpp +++ b/src/test/rpc/Subscribe_test.cpp @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { class Subscribe_test : public beast::unit_test::suite @@ -1591,7 +1591,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Subscribe, rpc, ripple); +BEAST_DEFINE_TESTSUITE(Subscribe, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/TransactionEntry_test.cpp b/src/test/rpc/TransactionEntry_test.cpp index 052d45e43b..f81a04df6a 100644 --- a/src/test/rpc/TransactionEntry_test.cpp +++ b/src/test/rpc/TransactionEntry_test.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { class TransactionEntry_test : public beast::unit_test::suite { @@ -375,6 +375,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(TransactionEntry, rpc, ripple); +BEAST_DEFINE_TESTSUITE(TransactionEntry, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/TransactionHistory_test.cpp b/src/test/rpc/TransactionHistory_test.cpp index ca8d128962..1dec83584d 100644 --- a/src/test/rpc/TransactionHistory_test.cpp +++ b/src/test/rpc/TransactionHistory_test.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class TransactionHistory_test : public beast::unit_test::suite { @@ -151,6 +151,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(TransactionHistory, rpc, ripple); +BEAST_DEFINE_TESTSUITE(TransactionHistory, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Transaction_test.cpp b/src/test/rpc/Transaction_test.cpp index b1bea237f5..6947fc91c2 100644 --- a/src/test/rpc/Transaction_test.cpp +++ b/src/test/rpc/Transaction_test.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { class Transaction_test : public beast::unit_test::suite { @@ -938,6 +938,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Transaction, rpc, ripple); +BEAST_DEFINE_TESTSUITE(Transaction, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/ValidatorInfo_test.cpp b/src/test/rpc/ValidatorInfo_test.cpp index a115044194..a8fccc724b 100644 --- a/src/test/rpc/ValidatorInfo_test.cpp +++ b/src/test/rpc/ValidatorInfo_test.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class ValidatorInfo_test : public beast::unit_test::suite @@ -104,6 +104,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ValidatorInfo, rpc, ripple); +BEAST_DEFINE_TESTSUITE(ValidatorInfo, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/ValidatorRPC_test.cpp b/src/test/rpc/ValidatorRPC_test.cpp index df7180ed10..cf8741e507 100644 --- a/src/test/rpc/ValidatorRPC_test.cpp +++ b/src/test/rpc/ValidatorRPC_test.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace test { @@ -575,7 +575,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ValidatorRPC, rpc, ripple); +BEAST_DEFINE_TESTSUITE(ValidatorRPC, rpc, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/rpc/Version_test.cpp b/src/test/rpc/Version_test.cpp index 50004c2c54..fd4bfdd565 100644 --- a/src/test/rpc/Version_test.cpp +++ b/src/test/rpc/Version_test.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { class Version_test : public beast::unit_test::suite { @@ -277,6 +277,6 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Version, rpc, ripple); +BEAST_DEFINE_TESTSUITE(Version, rpc, xrpl); -} // namespace ripple +} // namespace xrpl diff --git a/src/test/server/ServerStatus_test.cpp b/src/test/server/ServerStatus_test.cpp index b93c3a30e7..9f35a9162d 100644 --- a/src/test/server/ServerStatus_test.cpp +++ b/src/test/server/ServerStatus_test.cpp @@ -24,7 +24,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class ServerStatus_test : public beast::unit_test::suite, @@ -1226,7 +1226,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(ServerStatus, server, ripple); +BEAST_DEFINE_TESTSUITE(ServerStatus, server, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/server/Server_test.cpp b/src/test/server/Server_test.cpp index 55a9b17ea0..2a4bb49d34 100644 --- a/src/test/server/Server_test.cpp +++ b/src/test/server/Server_test.cpp @@ -22,7 +22,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { using socket_type = boost::beast::tcp_stream; @@ -517,7 +517,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(Server, server, ripple); +BEAST_DEFINE_TESTSUITE(Server, server, xrpl); } // namespace test -} // namespace ripple +} // namespace xrpl diff --git a/src/test/shamap/FetchPack_test.cpp b/src/test/shamap/FetchPack_test.cpp index 13ea267da9..dc51616015 100644 --- a/src/test/shamap/FetchPack_test.cpp +++ b/src/test/shamap/FetchPack_test.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace tests { class FetchPack_test : public beast::unit_test::suite @@ -72,7 +72,7 @@ public: { Serializer s; for (int d = 0; d < 3; ++d) - s.add32(ripple::rand_int(r)); + s.add32(xrpl::rand_int(r)); return make_shamapitem(s.getSHA512Half(), s.slice()); } @@ -151,7 +151,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(FetchPack, shamap, ripple); +BEAST_DEFINE_TESTSUITE(FetchPack, shamap, xrpl); } // namespace tests -} // namespace ripple +} // namespace xrpl diff --git a/src/test/shamap/SHAMapSync_test.cpp b/src/test/shamap/SHAMapSync_test.cpp index c71ad53ce8..912768e618 100644 --- a/src/test/shamap/SHAMapSync_test.cpp +++ b/src/test/shamap/SHAMapSync_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace tests { class SHAMapSync_test : public beast::unit_test::suite @@ -168,7 +168,7 @@ public: } }; -BEAST_DEFINE_TESTSUITE(SHAMapSync, shamap, ripple); +BEAST_DEFINE_TESTSUITE(SHAMapSync, shamap, xrpl); } // namespace tests -} // namespace ripple +} // namespace xrpl diff --git a/src/test/shamap/SHAMap_test.cpp b/src/test/shamap/SHAMap_test.cpp index e3e541019b..ade7a692f8 100644 --- a/src/test/shamap/SHAMap_test.cpp +++ b/src/test/shamap/SHAMap_test.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace tests { #ifndef __INTELLISENSE__ @@ -382,7 +382,7 @@ class SHAMapPathProof_test : public beast::unit_test::suite } }; -BEAST_DEFINE_TESTSUITE(SHAMap, shamap, ripple); -BEAST_DEFINE_TESTSUITE(SHAMapPathProof, shamap, ripple); +BEAST_DEFINE_TESTSUITE(SHAMap, shamap, xrpl); +BEAST_DEFINE_TESTSUITE(SHAMapPathProof, shamap, xrpl); } // namespace tests -} // namespace ripple +} // namespace xrpl diff --git a/src/test/shamap/common.h b/src/test/shamap/common.h index ac9a716912..add2c79243 100644 --- a/src/test/shamap/common.h +++ b/src/test/shamap/common.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace tests { class TestNodeFamily : public Family @@ -109,6 +109,6 @@ public: }; } // namespace tests -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/unit_test/FileDirGuard.h b/src/test/unit_test/FileDirGuard.h index c5272015cc..94ca5948bd 100644 --- a/src/test/unit_test/FileDirGuard.h +++ b/src/test/unit_test/FileDirGuard.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { /** @@ -158,6 +158,6 @@ public: }; } // namespace detail -} // namespace ripple +} // namespace xrpl #endif // TEST_UNIT_TEST_DIRGUARD_H diff --git a/src/test/unit_test/SuiteJournal.h b/src/test/unit_test/SuiteJournal.h index d4883f4721..d64be9ea9b 100644 --- a/src/test/unit_test/SuiteJournal.h +++ b/src/test/unit_test/SuiteJournal.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { // A Journal::Sink intended for use with the beast unit test framework. @@ -140,6 +140,6 @@ public: }; } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/test/unit_test/multi_runner.cpp b/src/test/unit_test/multi_runner.cpp index f6f599977e..4b1a82cd3f 100644 --- a/src/test/unit_test/multi_runner.cpp +++ b/src/test/unit_test/multi_runner.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -636,4 +636,4 @@ template class multi_runner_base; template class multi_runner_base; } // namespace detail -} // namespace ripple +} // namespace xrpl diff --git a/src/test/unit_test/multi_runner.h b/src/test/unit_test/multi_runner.h index 8c302a8007..813af61572 100644 --- a/src/test/unit_test/multi_runner.h +++ b/src/test/unit_test/multi_runner.h @@ -20,7 +20,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -335,6 +335,6 @@ multi_runner_child::run_multi(Pred pred) } } // namespace test -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/tests/libxrpl/basics/RangeSet.cpp b/src/tests/libxrpl/basics/RangeSet.cpp index d6f3691d4b..8c43b26758 100644 --- a/src/tests/libxrpl/basics/RangeSet.cpp +++ b/src/tests/libxrpl/basics/RangeSet.cpp @@ -5,7 +5,7 @@ #include #include -using namespace ripple; +using namespace xrpl; TEST_SUITE_BEGIN("RangeSet"); diff --git a/src/tests/libxrpl/basics/Slice.cpp b/src/tests/libxrpl/basics/Slice.cpp index d85d7c03d7..03d89ff174 100644 --- a/src/tests/libxrpl/basics/Slice.cpp +++ b/src/tests/libxrpl/basics/Slice.cpp @@ -5,7 +5,7 @@ #include #include -using namespace ripple; +using namespace xrpl; static std::uint8_t const data[] = { 0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23, 0x71, 0x6d, 0x2a, diff --git a/src/tests/libxrpl/basics/base64.cpp b/src/tests/libxrpl/basics/base64.cpp index 1191319145..e4581126b4 100644 --- a/src/tests/libxrpl/basics/base64.cpp +++ b/src/tests/libxrpl/basics/base64.cpp @@ -4,7 +4,7 @@ #include -using namespace ripple; +using namespace xrpl; static void check(std::string const& in, std::string const& out) diff --git a/src/tests/libxrpl/basics/contract.cpp b/src/tests/libxrpl/basics/contract.cpp index c7be5f8ede..a1f6f0b777 100644 --- a/src/tests/libxrpl/basics/contract.cpp +++ b/src/tests/libxrpl/basics/contract.cpp @@ -5,7 +5,7 @@ #include #include -using namespace ripple; +using namespace xrpl; TEST_CASE("contract") { diff --git a/src/tests/libxrpl/basics/mulDiv.cpp b/src/tests/libxrpl/basics/mulDiv.cpp index 2a59ff81c6..d3c58ea2f4 100644 --- a/src/tests/libxrpl/basics/mulDiv.cpp +++ b/src/tests/libxrpl/basics/mulDiv.cpp @@ -5,7 +5,7 @@ #include #include -using namespace ripple; +using namespace xrpl; TEST_CASE("mulDiv") { diff --git a/src/tests/libxrpl/basics/scope.cpp b/src/tests/libxrpl/basics/scope.cpp index 2f8248ef9a..b3774d54bd 100644 --- a/src/tests/libxrpl/basics/scope.cpp +++ b/src/tests/libxrpl/basics/scope.cpp @@ -2,7 +2,7 @@ #include -using namespace ripple; +using namespace xrpl; TEST_CASE("scope_exit") { diff --git a/src/tests/libxrpl/basics/tagged_integer.cpp b/src/tests/libxrpl/basics/tagged_integer.cpp index 945eaf9156..45efc579ab 100644 --- a/src/tests/libxrpl/basics/tagged_integer.cpp +++ b/src/tests/libxrpl/basics/tagged_integer.cpp @@ -4,7 +4,7 @@ #include -using namespace ripple; +using namespace xrpl; struct Tag1 { diff --git a/src/tests/libxrpl/crypto/csprng.cpp b/src/tests/libxrpl/crypto/csprng.cpp index 88c55dc4d0..e59c8a555a 100644 --- a/src/tests/libxrpl/crypto/csprng.cpp +++ b/src/tests/libxrpl/crypto/csprng.cpp @@ -2,7 +2,7 @@ #include -using namespace ripple; +using namespace xrpl; TEST_CASE("get values") { diff --git a/src/tests/libxrpl/json/Output.cpp b/src/tests/libxrpl/json/Output.cpp index 4960171e56..6e6c20a0e5 100644 --- a/src/tests/libxrpl/json/Output.cpp +++ b/src/tests/libxrpl/json/Output.cpp @@ -6,7 +6,7 @@ #include -using namespace ripple; +using namespace xrpl; using namespace Json; TEST_SUITE_BEGIN("JsonOutput"); diff --git a/src/tests/libxrpl/json/Value.cpp b/src/tests/libxrpl/json/Value.cpp index df777c98fc..25bd2f548d 100644 --- a/src/tests/libxrpl/json/Value.cpp +++ b/src/tests/libxrpl/json/Value.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { TEST_SUITE_BEGIN("json_value"); @@ -1363,4 +1363,4 @@ TEST_CASE("memory leak") TEST_SUITE_END(); -} // namespace ripple +} // namespace xrpl diff --git a/src/tests/libxrpl/json/Writer.cpp b/src/tests/libxrpl/json/Writer.cpp index 46bfd61ae2..9637184c95 100644 --- a/src/tests/libxrpl/json/Writer.cpp +++ b/src/tests/libxrpl/json/Writer.cpp @@ -6,7 +6,7 @@ #include #include -using namespace ripple; +using namespace xrpl; using namespace Json; TEST_SUITE_BEGIN("JsonWriter"); diff --git a/src/tests/libxrpl/net/HTTPClient.cpp b/src/tests/libxrpl/net/HTTPClient.cpp index 5d46f68f0c..5a484c1f56 100644 --- a/src/tests/libxrpl/net/HTTPClient.cpp +++ b/src/tests/libxrpl/net/HTTPClient.cpp @@ -13,7 +13,7 @@ #include #include -using namespace ripple; +using namespace xrpl; namespace { diff --git a/src/xrpld/app/consensus/RCLCensorshipDetector.h b/src/xrpld/app/consensus/RCLCensorshipDetector.h index d53d1197db..97d2743dc1 100644 --- a/src/xrpld/app/consensus/RCLCensorshipDetector.h +++ b/src/xrpld/app/consensus/RCLCensorshipDetector.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { template class RCLCensorshipDetector @@ -122,6 +122,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/consensus/RCLConsensus.cpp b/src/xrpld/app/consensus/RCLConsensus.cpp index 4c2ecbac10..99cc140056 100644 --- a/src/xrpld/app/consensus/RCLConsensus.cpp +++ b/src/xrpld/app/consensus/RCLConsensus.cpp @@ -30,7 +30,7 @@ #include #include -namespace ripple { +namespace xrpl { RCLConsensus::RCLConsensus( Application& app, @@ -77,7 +77,7 @@ RCLConsensus::Adaptor::Adaptor( , nUnlVote_(validatorKeys_.nodeID, j_) { XRPL_ASSERT( - valCookie_, "ripple::RCLConsensus::Adaptor::Adaptor : nonzero cookie"); + valCookie_, "xrpl::RCLConsensus::Adaptor::Adaptor : nonzero cookie"); JLOG(j_.info()) << "Consensus engine started (cookie: " + std::to_string(valCookie_) + ")"; @@ -133,10 +133,10 @@ RCLConsensus::Adaptor::acquireLedger(LedgerHash const& hash) XRPL_ASSERT( !built->open() && built->isImmutable(), - "ripple::RCLConsensus::Adaptor::acquireLedger : valid ledger state"); + "xrpl::RCLConsensus::Adaptor::acquireLedger : valid ledger state"); XRPL_ASSERT( built->header().hash == hash, - "ripple::RCLConsensus::Adaptor::acquireLedger : ledger hash match"); + "xrpl::RCLConsensus::Adaptor::acquireLedger : ledger hash match"); // Notify inbound transactions of the new ledger sequence number inboundTransactions_.newRound(built->header().seq); @@ -193,8 +193,8 @@ void RCLConsensus::Adaptor::propose(RCLCxPeerPos::Proposal const& proposal) { JLOG(j_.trace()) << (proposal.isBowOut() ? "We bow out: " : "We propose: ") - << ripple::to_string(proposal.prevLedger()) << " -> " - << ripple::to_string(proposal.position()); + << xrpl::to_string(proposal.prevLedger()) << " -> " + << xrpl::to_string(proposal.position()); protocol::TMProposeSet prop; @@ -664,10 +664,10 @@ RCLConsensus::Adaptor::doAccept( // Do these need to exist? XRPL_ASSERT( ledgerMaster_.getClosedLedger()->header().hash == built.id(), - "ripple::RCLConsensus::Adaptor::doAccept : ledger hash match"); + "xrpl::RCLConsensus::Adaptor::doAccept : ledger hash match"); XRPL_ASSERT( app_.openLedger().current()->header().parentHash == built.id(), - "ripple::RCLConsensus::Adaptor::doAccept : parent hash match"); + "xrpl::RCLConsensus::Adaptor::doAccept : parent hash match"); } //------------------------------------------------------------------------- @@ -765,7 +765,7 @@ RCLConsensus::Adaptor::buildLCL( { XRPL_ASSERT( replayData->parent()->header().hash == previousLedger.id(), - "ripple::RCLConsensus::Adaptor::buildLCL : parent hash match"); + "xrpl::RCLConsensus::Adaptor::buildLCL : parent hash match"); return buildLedger(*replayData, tapNONE, app_, j_); } return buildLedger( @@ -1106,4 +1106,4 @@ RclConsensusLogger::~RclConsensusLogger() j_.sink().writeAlways(beast::severities::kInfo, outSs.str()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/consensus/RCLConsensus.h b/src/xrpld/app/consensus/RCLConsensus.h index a6a15395a3..e26cde9801 100644 --- a/src/xrpld/app/consensus/RCLConsensus.h +++ b/src/xrpld/app/consensus/RCLConsensus.h @@ -21,7 +21,7 @@ #include #include -namespace ripple { +namespace xrpl { class InboundTransactions; class LocalTxs; @@ -548,6 +548,6 @@ public: return ss_; } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/consensus/RCLCxLedger.h b/src/xrpld/app/consensus/RCLCxLedger.h index 5671fa988d..4413fee7fc 100644 --- a/src/xrpld/app/consensus/RCLCxLedger.h +++ b/src/xrpld/app/consensus/RCLCxLedger.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Represents a ledger in RCLConsensus. @@ -69,7 +69,7 @@ public: bool closeAgree() const { - return ripple::getCloseAgree(ledger_->header()); + return xrpl::getCloseAgree(ledger_->header()); } //! The close time of this ledger @@ -90,7 +90,7 @@ public: Json::Value getJson() const { - return ripple::getJson({*ledger_, {}}); + return xrpl::getJson({*ledger_, {}}); } /** The ledger instance. @@ -100,5 +100,5 @@ public: */ std::shared_ptr ledger_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/consensus/RCLCxPeerPos.cpp b/src/xrpld/app/consensus/RCLCxPeerPos.cpp index c1ebfc20e2..5f227b00a9 100644 --- a/src/xrpld/app/consensus/RCLCxPeerPos.cpp +++ b/src/xrpld/app/consensus/RCLCxPeerPos.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { // Used to construct received proposals RCLCxPeerPos::RCLCxPeerPos( @@ -19,7 +19,7 @@ RCLCxPeerPos::RCLCxPeerPos( // this elsewhere, but we want to be extra careful here: XRPL_ASSERT( signature.size() != 0 && signature.size() <= signature_.capacity(), - "ripple::RCLCxPeerPos::RCLCxPeerPos : valid signature size"); + "xrpl::RCLCxPeerPos::RCLCxPeerPos : valid signature size"); if (signature.size() != 0 && signature.size() <= signature_.capacity()) signature_.assign(signature.begin(), signature.end()); @@ -63,4 +63,4 @@ proposalUniqueId( return s.getSHA512Half(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/consensus/RCLCxPeerPos.h b/src/xrpld/app/consensus/RCLCxPeerPos.h index 7202503e76..08b93d4ba9 100644 --- a/src/xrpld/app/consensus/RCLCxPeerPos.h +++ b/src/xrpld/app/consensus/RCLCxPeerPos.h @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A peer's signed, proposed position for use in RCLConsensus. @@ -128,6 +128,6 @@ proposalUniqueId( Slice const& publicKey, Slice const& signature); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/consensus/RCLCxTx.h b/src/xrpld/app/consensus/RCLCxTx.h index 0a2f25dbd2..5e92aea8a6 100644 --- a/src/xrpld/app/consensus/RCLCxTx.h +++ b/src/xrpld/app/consensus/RCLCxTx.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Represents a transaction in RCLConsensus. @@ -90,7 +90,7 @@ public: RCLTxSet(std::shared_ptr m) : map_{std::move(m)} { XRPL_ASSERT( - map_, "ripple::RCLTxSet::MutableTxSet::RCLTxSet : non-null input"); + map_, "xrpl::RCLTxSet::MutableTxSet::RCLTxSet : non-null input"); } /** Constructor from a previously created MutableTxSet @@ -158,7 +158,7 @@ public: { XRPL_ASSERT( (v.first && !v.second) || (v.second && !v.first), - "ripple::RCLTxSet::compare : either side is set"); + "xrpl::RCLTxSet::compare : either side is set"); ret[k] = static_cast(v.first); } @@ -168,5 +168,5 @@ public: //! The SHAMap representing the transactions. std::shared_ptr map_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/consensus/RCLValidations.cpp b/src/xrpld/app/consensus/RCLValidations.cpp index 827c417ba8..eb10765ba3 100644 --- a/src/xrpld/app/consensus/RCLValidations.cpp +++ b/src/xrpld/app/consensus/RCLValidations.cpp @@ -13,7 +13,7 @@ #include -namespace ripple { +namespace xrpl { RCLValidatedLedger::RCLValidatedLedger(MakeGenesis) : ledgerID_{0}, ledgerSeq_{0}, j_{beast::Journal::getNullSink()} @@ -30,7 +30,7 @@ RCLValidatedLedger::RCLValidatedLedger( { XRPL_ASSERT( hashIndex->getFieldU32(sfLastLedgerSequence) == (seq() - 1), - "ripple::RCLValidatedLedger::RCLValidatedLedger(Ledger) : valid " + "xrpl::RCLValidatedLedger::RCLValidatedLedger(Ledger) : valid " "last ledger sequence"); ancestors_ = hashIndex->getFieldV256(sfHashes).value(); } @@ -134,10 +134,10 @@ RCLValidationsAdaptor::acquire(LedgerHash const& hash) XRPL_ASSERT( !ledger->open() && ledger->isImmutable(), - "ripple::RCLValidationsAdaptor::acquire : valid ledger state"); + "xrpl::RCLValidationsAdaptor::acquire : valid ledger state"); XRPL_ASSERT( ledger->header().hash == hash, - "ripple::RCLValidationsAdaptor::acquire : ledger hash match"); + "xrpl::RCLValidationsAdaptor::acquire : ledger hash match"); return RCLValidatedLedger(std::move(ledger), j_); } @@ -177,7 +177,7 @@ handleNewValidation( if (bypassAccept == BypassAccept::yes) { XRPL_ASSERT( - j, "ripple::handleNewValidation : journal is available"); + j, "xrpl::handleNewValidation : journal is available"); if (j.has_value()) { JLOG(j->trace()) << "Bypassing checkAccept for validation " @@ -228,4 +228,4 @@ handleNewValidation( } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/consensus/RCLValidations.h b/src/xrpld/app/consensus/RCLValidations.h index ef6d8e9423..62dd52b1dd 100644 --- a/src/xrpld/app/consensus/RCLValidations.h +++ b/src/xrpld/app/consensus/RCLValidations.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; @@ -26,8 +26,8 @@ class RCLValidation std::shared_ptr val_; public: - using NodeKey = ripple::PublicKey; - using NodeID = ripple::NodeID; + using NodeKey = xrpl::PublicKey; + using NodeID = xrpl::NodeID; /** Constructor @@ -238,6 +238,6 @@ handleNewValidation( BypassAccept const bypassAccept = BypassAccept::no, std::optional j = std::nullopt); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/AbstractFetchPackContainer.h b/src/xrpld/app/ledger/AbstractFetchPackContainer.h index d8826a14e3..85efe09e29 100644 --- a/src/xrpld/app/ledger/AbstractFetchPackContainer.h +++ b/src/xrpld/app/ledger/AbstractFetchPackContainer.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { /** An interface facilitating retrieval of fetch packs without an application or ledgermaster object. @@ -26,6 +26,6 @@ public: getFetchPack(uint256 const& nodeHash) = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/AcceptedLedger.cpp b/src/xrpld/app/ledger/AcceptedLedger.cpp index 85fc1dcb37..76099ff864 100644 --- a/src/xrpld/app/ledger/AcceptedLedger.cpp +++ b/src/xrpld/app/ledger/AcceptedLedger.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { AcceptedLedger::AcceptedLedger( std::shared_ptr const& ledger, @@ -28,4 +28,4 @@ AcceptedLedger::AcceptedLedger( }); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/AcceptedLedger.h b/src/xrpld/app/ledger/AcceptedLedger.h index 0d0fe19f10..41177e7078 100644 --- a/src/xrpld/app/ledger/AcceptedLedger.h +++ b/src/xrpld/app/ledger/AcceptedLedger.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** A ledger that has become irrevocable. @@ -57,6 +57,6 @@ private: std::vector> transactions_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/AcceptedLedgerTx.cpp b/src/xrpld/app/ledger/AcceptedLedgerTx.cpp index 18de7b5d06..d57246444f 100644 --- a/src/xrpld/app/ledger/AcceptedLedgerTx.cpp +++ b/src/xrpld/app/ledger/AcceptedLedgerTx.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { AcceptedLedgerTx::AcceptedLedgerTx( std::shared_ptr const& ledger, @@ -17,7 +17,7 @@ AcceptedLedgerTx::AcceptedLedgerTx( { XRPL_ASSERT( !ledger->open(), - "ripple::AcceptedLedgerTx::AcceptedLedgerTx : valid ledger state"); + "xrpl::AcceptedLedgerTx::AcceptedLedgerTx : valid ledger state"); Serializer s; met->add(s); @@ -62,8 +62,8 @@ AcceptedLedgerTx::getEscMeta() const { XRPL_ASSERT( !mRawMeta.empty(), - "ripple::AcceptedLedgerTx::getEscMeta : metadata is set"); + "xrpl::AcceptedLedgerTx::getEscMeta : metadata is set"); return sqlBlobLiteral(mRawMeta); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/AcceptedLedgerTx.h b/src/xrpld/app/ledger/AcceptedLedgerTx.h index aeac800c5c..efea5b9162 100644 --- a/src/xrpld/app/ledger/AcceptedLedgerTx.h +++ b/src/xrpld/app/ledger/AcceptedLedgerTx.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { class Logs; @@ -85,6 +85,6 @@ private: Json::Value mJson; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/AccountStateSF.cpp b/src/xrpld/app/ledger/AccountStateSF.cpp index 052f9f9a69..44f18b5cd3 100644 --- a/src/xrpld/app/ledger/AccountStateSF.cpp +++ b/src/xrpld/app/ledger/AccountStateSF.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { void AccountStateSF::gotNode( @@ -20,4 +20,4 @@ AccountStateSF::getNode(SHAMapHash const& nodeHash) const return fp_.getFetchPack(nodeHash.as_uint256()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/AccountStateSF.h b/src/xrpld/app/ledger/AccountStateSF.h index 13844e2417..84738f6e1f 100644 --- a/src/xrpld/app/ledger/AccountStateSF.h +++ b/src/xrpld/app/ledger/AccountStateSF.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // This class is only needed on add functions // sync filter for account state nodes during ledger sync @@ -34,6 +34,6 @@ private: AbstractFetchPackContainer& fp_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/BookListeners.cpp b/src/xrpld/app/ledger/BookListeners.cpp index 31b5d102ca..69d03058a9 100644 --- a/src/xrpld/app/ledger/BookListeners.cpp +++ b/src/xrpld/app/ledger/BookListeners.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { void BookListeners::addSubscriber(InfoSub::ref sub) @@ -44,4 +44,4 @@ BookListeners::publish( } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/BookListeners.h b/src/xrpld/app/ledger/BookListeners.h index ad9e0fe0c7..784172974e 100644 --- a/src/xrpld/app/ledger/BookListeners.h +++ b/src/xrpld/app/ledger/BookListeners.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Listen to public/subscribe messages from a book. */ class BookListeners @@ -50,6 +50,6 @@ private: hash_map mListeners; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/BuildLedger.h b/src/xrpld/app/ledger/BuildLedger.h index 8c127fb365..ad6aba3288 100644 --- a/src/xrpld/app/ledger/BuildLedger.h +++ b/src/xrpld/app/ledger/BuildLedger.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; class CanonicalTXSet; @@ -57,5 +57,5 @@ buildLedger( Application& app, beast::Journal j); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp index d248a36987..b52cee2927 100644 --- a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp +++ b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { ConsensusTransSetSF::ConsensusTransSetSF(Application& app, NodeCache& nodeCache) : app_(app), m_nodeCache(nodeCache), j_(app.journal("TransactionAcquire")) @@ -43,7 +43,7 @@ ConsensusTransSetSF::gotNode( auto stx = std::make_shared(std::ref(sit)); XRPL_ASSERT( stx->getTransactionID() == nodeHash.as_uint256(), - "ripple::ConsensusTransSetSF::gotNode : transaction hash " + "xrpl::ConsensusTransSetSF::gotNode : transaction hash " "match"); auto const pap = &app_; app_.getJobQueue().addJob(jtTRANSACTION, "TXS->TXN", [pap, stx]() { @@ -78,7 +78,7 @@ ConsensusTransSetSF::getNode(SHAMapHash const& nodeHash) const txn->getSTransaction()->add(s); XRPL_ASSERT( sha512Half(s.slice()) == nodeHash.as_uint256(), - "ripple::ConsensusTransSetSF::getNode : transaction hash match"); + "xrpl::ConsensusTransSetSF::getNode : transaction hash match"); nodeData = s.peekData(); return nodeData; } @@ -86,4 +86,4 @@ ConsensusTransSetSF::getNode(SHAMapHash const& nodeHash) const return std::nullopt; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/ConsensusTransSetSF.h b/src/xrpld/app/ledger/ConsensusTransSetSF.h index 23ee6b9fac..cdb1c47183 100644 --- a/src/xrpld/app/ledger/ConsensusTransSetSF.h +++ b/src/xrpld/app/ledger/ConsensusTransSetSF.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // Sync filters allow low-level SHAMapSync code to interact correctly with // higher-level structures such as caches and transaction stores @@ -38,6 +38,6 @@ private: beast::Journal const j_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/InboundLedger.h b/src/xrpld/app/ledger/InboundLedger.h index 0d5639909b..1b4353b260 100644 --- a/src/xrpld/app/ledger/InboundLedger.h +++ b/src/xrpld/app/ledger/InboundLedger.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { // A ledger we are trying to acquire class InboundLedger final : public TimeoutCounter, @@ -179,6 +179,6 @@ private: std::unique_ptr mPeerSet; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/InboundLedgers.h b/src/xrpld/app/ledger/InboundLedgers.h index 6eba2eec87..0e4d9996bb 100644 --- a/src/xrpld/app/ledger/InboundLedgers.h +++ b/src/xrpld/app/ledger/InboundLedgers.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { /** Manages the lifetime of inbound ledgers. @@ -84,6 +84,6 @@ make_InboundLedgers( InboundLedgers::clock_type& clock, beast::insight::Collector::ptr const& collector); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/InboundTransactions.h b/src/xrpld/app/ledger/InboundTransactions.h index 41dab5307e..6c0281e26f 100644 --- a/src/xrpld/app/ledger/InboundTransactions.h +++ b/src/xrpld/app/ledger/InboundTransactions.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class Application; @@ -78,6 +78,6 @@ make_InboundTransactions( beast::insight::Collector::ptr const& collector, std::function const&, bool)> gotSet); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/Ledger.cpp b/src/xrpld/app/ledger/Ledger.cpp index bf5f442eee..e21cbb6d54 100644 --- a/src/xrpld/app/ledger/Ledger.cpp +++ b/src/xrpld/app/ledger/Ledger.cpp @@ -27,7 +27,7 @@ #include #include -namespace ripple { +namespace xrpl { create_genesis_t const create_genesis{}; @@ -344,7 +344,7 @@ Ledger::setAccepted( bool correctCloseTime) { // Used when we witnessed the consensus. - XRPL_ASSERT(!open(), "ripple::Ledger::setAccepted : valid ledger state"); + XRPL_ASSERT(!open(), "xrpl::Ledger::setAccepted : valid ledger state"); header_.closeTime = closeTime; header_.closeTimeResolution = closeResolution; @@ -418,7 +418,7 @@ Ledger::read(Keylet const& k) const if (k.key == beast::zero) { // LCOV_EXCL_START - UNREACHABLE("ripple::Ledger::read : zero key"); + UNREACHABLE("xrpl::Ledger::read : zero key"); return nullptr; // LCOV_EXCL_STOP } @@ -540,7 +540,7 @@ Ledger::rawTxInsert( std::shared_ptr const& metaData) { XRPL_ASSERT( - metaData, "ripple::Ledger::rawTxInsert : non-null metadata input"); + metaData, "xrpl::Ledger::rawTxInsert : non-null metadata input"); // low-level - just add to table Serializer s(txn->getDataLength() + metaData->getDataLength() + 16); @@ -559,7 +559,7 @@ Ledger::rawTxInsertWithHash( { XRPL_ASSERT( metaData, - "ripple::Ledger::rawTxInsertWithHash : non-null metadata input"); + "xrpl::Ledger::rawTxInsertWithHash : non-null metadata input"); // low-level - just add to table Serializer s(txn->getDataLength() + metaData->getDataLength() + 16); @@ -657,7 +657,7 @@ Ledger::defaultFees(Config const& config) { XRPL_ASSERT( fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0, - "ripple::Ledger::defaultFees : zero fees"); + "xrpl::Ledger::defaultFees : zero fees"); if (fees_.base == 0) fees_.base = config.FEES.reference_fee; if (fees_.reserve == 0) @@ -854,7 +854,7 @@ Ledger::assertSensible(beast::Journal ledgerJ) const JLOG(ledgerJ.fatal()) << "ledger is not sensible" << j; - UNREACHABLE("ripple::Ledger::assertSensible : ledger is not sensible"); + UNREACHABLE("xrpl::Ledger::assertSensible : ledger is not sensible"); return false; // LCOV_EXCL_STOP @@ -891,7 +891,7 @@ Ledger::updateSkipList() XRPL_ASSERT( hashes.size() <= 256, - "ripple::Ledger::updateSkipList : first maximum hashes size"); + "xrpl::Ledger::updateSkipList : first maximum hashes size"); hashes.push_back(header_.parentHash); sle->setFieldV256(sfHashes, STVector256(hashes)); sle->setFieldU32(sfLastLedgerSequence, prevIndex); @@ -918,7 +918,7 @@ Ledger::updateSkipList() } XRPL_ASSERT( hashes.size() <= 256, - "ripple::Ledger::updateSkipList : second maximum hashes size"); + "xrpl::Ledger::updateSkipList : second maximum hashes size"); if (hashes.size() == 256) hashes.erase(hashes.begin()); hashes.push_back(header_.parentHash); @@ -1000,7 +1000,7 @@ pendSaveValidated( } XRPL_ASSERT( - ledger->isImmutable(), "ripple::pendSaveValidated : immutable ledger"); + ledger->isImmutable(), "xrpl::pendSaveValidated : immutable ledger"); if (!app.pendingSaves().shouldWork(ledger->header().seq, isSynchronous)) { @@ -1080,7 +1080,7 @@ finishLoadByIndexOrHash( XRPL_ASSERT( ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()), - "ripple::finishLoadByIndexOrHash : valid ledger fees"); + "xrpl::finishLoadByIndexOrHash : valid ledger fees"); ledger->setImmutable(); JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->header().hash); @@ -1121,10 +1121,10 @@ loadByHash(uint256 const& ledgerHash, Application& app, bool acquire) finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger")); XRPL_ASSERT( !ledger || ledger->header().hash == ledgerHash, - "ripple::loadByHash : ledger hash match if loaded"); + "xrpl::loadByHash : ledger hash match if loaded"); return ledger; } return {}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/Ledger.h b/src/xrpld/app/ledger/Ledger.h index 0e849389fd..a17281f2c7 100644 --- a/src/xrpld/app/ledger/Ledger.h +++ b/src/xrpld/app/ledger/Ledger.h @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; class Job; @@ -459,6 +459,6 @@ deserializeTxPlusMeta(SHAMapItem const& item); uint256 calculateLedgerHash(LedgerHeader const& info); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LedgerCleaner.h b/src/xrpld/app/ledger/LedgerCleaner.h index 66c8c070c9..2377485f22 100644 --- a/src/xrpld/app/ledger/LedgerCleaner.h +++ b/src/xrpld/app/ledger/LedgerCleaner.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Check the ledger/transaction databases to make sure they have continuity */ class LedgerCleaner : public beast::PropertyStream::Source @@ -43,6 +43,6 @@ public: std::unique_ptr make_LedgerCleaner(Application& app, beast::Journal journal); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LedgerHistory.cpp b/src/xrpld/app/ledger/LedgerHistory.cpp index c084297641..2654e25d7b 100644 --- a/src/xrpld/app/ledger/LedgerHistory.cpp +++ b/src/xrpld/app/ledger/LedgerHistory.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // FIXME: Need to clean up ledgers by index at some point @@ -42,7 +42,7 @@ LedgerHistory::insert( XRPL_ASSERT( ledger->stateMap().getHash().isNonZero(), - "ripple::LedgerHistory::insert : nonzero hash"); + "xrpl::LedgerHistory::insert : nonzero hash"); std::unique_lock sl(m_ledgers_by_hash.peekMutex()); @@ -85,7 +85,7 @@ LedgerHistory::getLedgerBySeq(LedgerIndex index) XRPL_ASSERT( ret->header().seq == index, - "ripple::LedgerHistory::getLedgerBySeq : result sequence match"); + "xrpl::LedgerHistory::getLedgerBySeq : result sequence match"); { // Add this ledger to the local tracking by index @@ -93,7 +93,7 @@ LedgerHistory::getLedgerBySeq(LedgerIndex index) XRPL_ASSERT( ret->isImmutable(), - "ripple::LedgerHistory::getLedgerBySeq : immutable result ledger"); + "xrpl::LedgerHistory::getLedgerBySeq : immutable result ledger"); m_ledgers_by_hash.canonicalize_replace_client(ret->header().hash, ret); mLedgersByIndex[ret->header().seq] = ret->header().hash; return (ret->header().seq == index) ? ret : nullptr; @@ -109,11 +109,11 @@ LedgerHistory::getLedgerByHash(LedgerHash const& hash) { XRPL_ASSERT( ret->isImmutable(), - "ripple::LedgerHistory::getLedgerByHash : immutable fetched " + "xrpl::LedgerHistory::getLedgerByHash : immutable fetched " "ledger"); XRPL_ASSERT( ret->header().hash == hash, - "ripple::LedgerHistory::getLedgerByHash : fetched ledger hash " + "xrpl::LedgerHistory::getLedgerByHash : fetched ledger hash " "match"); return ret; } @@ -125,14 +125,14 @@ LedgerHistory::getLedgerByHash(LedgerHash const& hash) XRPL_ASSERT( ret->isImmutable(), - "ripple::LedgerHistory::getLedgerByHash : immutable loaded ledger"); + "xrpl::LedgerHistory::getLedgerByHash : immutable loaded ledger"); XRPL_ASSERT( ret->header().hash == hash, - "ripple::LedgerHistory::getLedgerByHash : loaded ledger hash match"); + "xrpl::LedgerHistory::getLedgerByHash : loaded ledger hash match"); m_ledgers_by_hash.canonicalize_replace_client(ret->header().hash, ret); XRPL_ASSERT( ret->header().hash == hash, - "ripple::LedgerHistory::getLedgerByHash : result hash match"); + "xrpl::LedgerHistory::getLedgerByHash : result hash match"); return ret; } @@ -178,7 +178,7 @@ log_metadata_difference( XRPL_ASSERT( validMetaData || builtMetaData, - "ripple::log_metadata_difference : some metadata present"); + "xrpl::log_metadata_difference : some metadata present"); if (validMetaData && builtMetaData) { @@ -325,8 +325,7 @@ LedgerHistory::handleMismatch( Json::Value const& consensus) { XRPL_ASSERT( - built != valid, - "ripple::LedgerHistory::handleMismatch : unequal hashes"); + built != valid, "xrpl::LedgerHistory::handleMismatch : unequal hashes"); ++mismatch_counter_; auto builtLedger = getLedgerByHash(built); @@ -343,7 +342,7 @@ LedgerHistory::handleMismatch( XRPL_ASSERT( builtLedger->header().seq == validLedger->header().seq, - "ripple::LedgerHistory::handleMismatch : sequence match"); + "xrpl::LedgerHistory::handleMismatch : sequence match"); if (auto stream = j_.debug()) { @@ -437,7 +436,7 @@ LedgerHistory::builtLedger( LedgerIndex index = ledger->header().seq; LedgerHash hash = ledger->header().hash; XRPL_ASSERT( - !hash.isZero(), "ripple::LedgerHistory::builtLedger : nonzero hash"); + !hash.isZero(), "xrpl::LedgerHistory::builtLedger : nonzero hash"); std::unique_lock sl(m_consensus_validated.peekMutex()); @@ -478,8 +477,7 @@ LedgerHistory::validatedLedger( LedgerIndex index = ledger->header().seq; LedgerHash hash = ledger->header().hash; XRPL_ASSERT( - !hash.isZero(), - "ripple::LedgerHistory::validatedLedger : nonzero hash"); + !hash.isZero(), "xrpl::LedgerHistory::validatedLedger : nonzero hash"); std::unique_lock sl(m_consensus_validated.peekMutex()); @@ -538,4 +536,4 @@ LedgerHistory::clearLedgerCachePrior(LedgerIndex seq) } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/LedgerHistory.h b/src/xrpld/app/ledger/LedgerHistory.h index 02346265bd..279d009429 100644 --- a/src/xrpld/app/ledger/LedgerHistory.h +++ b/src/xrpld/app/ledger/LedgerHistory.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { // VFALCO TODO Rename to OldLedgers ? @@ -135,6 +135,6 @@ private: beast::Journal j_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LedgerHolder.h b/src/xrpld/app/ledger/LedgerHolder.h index 8925d688ac..c0a81778ae 100644 --- a/src/xrpld/app/ledger/LedgerHolder.h +++ b/src/xrpld/app/ledger/LedgerHolder.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { // Can std::atomic> make this lock free? @@ -53,6 +53,6 @@ private: std::shared_ptr m_heldLedger; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LedgerMaster.h b/src/xrpld/app/ledger/LedgerMaster.h index eba57894be..38dff835b7 100644 --- a/src/xrpld/app/ledger/LedgerMaster.h +++ b/src/xrpld/app/ledger/LedgerMaster.h @@ -21,7 +21,7 @@ #include #include -namespace ripple { +namespace xrpl { class Peer; class Transaction; @@ -401,6 +401,6 @@ private: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LedgerReplay.h b/src/xrpld/app/ledger/LedgerReplay.h index 5d26d36e99..29e8a835fe 100644 --- a/src/xrpld/app/ledger/LedgerReplay.h +++ b/src/xrpld/app/ledger/LedgerReplay.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class Ledger; class STTx; @@ -52,6 +52,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LedgerReplayTask.h b/src/xrpld/app/ledger/LedgerReplayTask.h index d7d24f86f2..623a193d93 100644 --- a/src/xrpld/app/ledger/LedgerReplayTask.h +++ b/src/xrpld/app/ledger/LedgerReplayTask.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { class InboundLedgers; class Ledger; class LedgerDeltaAcquire; @@ -161,6 +161,6 @@ private: friend class test::LedgerReplayClient; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LedgerReplayer.h b/src/xrpld/app/ledger/LedgerReplayer.h index 68a1c0da1d..b0e0692019 100644 --- a/src/xrpld/app/ledger/LedgerReplayer.h +++ b/src/xrpld/app/ledger/LedgerReplayer.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace test { class LedgerReplayClient; @@ -141,6 +141,6 @@ private: friend class test::LedgerReplayClient; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LedgerToJson.h b/src/xrpld/app/ledger/LedgerToJson.h index cd3dcc9255..7ebbfc655e 100644 --- a/src/xrpld/app/ledger/LedgerToJson.h +++ b/src/xrpld/app/ledger/LedgerToJson.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { struct LedgerFill { @@ -53,6 +53,6 @@ addJson(Json::Value&, LedgerFill const&); Json::Value getJson(LedgerFill const&); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/LocalTxs.h b/src/xrpld/app/ledger/LocalTxs.h index c60d3bce1a..d02e1027a0 100644 --- a/src/xrpld/app/ledger/LocalTxs.h +++ b/src/xrpld/app/ledger/LocalTxs.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { // Track transactions issued by local clients // Ensure we always apply them to our open ledger @@ -42,6 +42,6 @@ public: std::unique_ptr make_LocalTxs(); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/OpenLedger.h b/src/xrpld/app/ledger/OpenLedger.h index c21e858f44..45a3517168 100644 --- a/src/xrpld/app/ledger/OpenLedger.h +++ b/src/xrpld/app/ledger/OpenLedger.h @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { // How many total extra passes we make // We must ensure we make at least one non-retriable pass @@ -247,7 +247,7 @@ OpenLedger::apply( // If there are any transactions left, we must have // tried them in at least one final pass XRPL_ASSERT( - retries.empty() || !retry, "ripple::OpenLedger::apply : valid retries"); + retries.empty() || !retry, "xrpl::OpenLedger::apply : valid retries"); } //------------------------------------------------------------------------------ @@ -266,6 +266,6 @@ debugTostr(SHAMap const& set); std::string debugTostr(std::shared_ptr const& view); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/OrderBookDB.cpp b/src/xrpld/app/ledger/OrderBookDB.cpp index 00907ee2ce..47b04f3d2c 100644 --- a/src/xrpld/app/ledger/OrderBookDB.cpp +++ b/src/xrpld/app/ledger/OrderBookDB.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { OrderBookDB::OrderBookDB(Application& app) : app_(app), seq_(0), j_(app.journal("OrderBookDB")) @@ -249,7 +249,7 @@ OrderBookDB::makeBookListeners(Book const& book) mListeners[book] = ret; XRPL_ASSERT( getBookListeners(book) == ret, - "ripple::OrderBookDB::makeBookListeners : result roundtrip " + "xrpl::OrderBookDB::makeBookListeners : result roundtrip " "lookup"); } @@ -325,4 +325,4 @@ OrderBookDB::processTxn( } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/OrderBookDB.h b/src/xrpld/app/ledger/OrderBookDB.h index 9a1528c794..68bdf294a9 100644 --- a/src/xrpld/app/ledger/OrderBookDB.h +++ b/src/xrpld/app/ledger/OrderBookDB.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { class OrderBookDB { @@ -81,6 +81,6 @@ private: beast::Journal const j_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/PendingSaves.h b/src/xrpld/app/ledger/PendingSaves.h index 5082936ec8..24eb50e568 100644 --- a/src/xrpld/app/ledger/PendingSaves.h +++ b/src/xrpld/app/ledger/PendingSaves.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Keeps track of which ledgers haven't been fully saved. @@ -124,6 +124,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/TransactionMaster.h b/src/xrpld/app/ledger/TransactionMaster.h index 5fbf00a0d5..a9bf05065d 100644 --- a/src/xrpld/app/ledger/TransactionMaster.h +++ b/src/xrpld/app/ledger/TransactionMaster.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; class STTx; @@ -77,6 +77,6 @@ private: TaggedCache mCache; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/TransactionStateSF.cpp b/src/xrpld/app/ledger/TransactionStateSF.cpp index e861cbd2cc..af7dd8640a 100644 --- a/src/xrpld/app/ledger/TransactionStateSF.cpp +++ b/src/xrpld/app/ledger/TransactionStateSF.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { void TransactionStateSF::gotNode( @@ -13,7 +13,7 @@ TransactionStateSF::gotNode( { XRPL_ASSERT( type != SHAMapNodeType::tnTRANSACTION_NM, - "ripple::TransactionStateSF::gotNode : valid input"); + "xrpl::TransactionStateSF::gotNode : valid input"); db_.store( hotTRANSACTION_NODE, std::move(nodeData), @@ -27,4 +27,4 @@ TransactionStateSF::getNode(SHAMapHash const& nodeHash) const return fp_.getFetchPack(nodeHash.as_uint256()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/TransactionStateSF.h b/src/xrpld/app/ledger/TransactionStateSF.h index 50a77edc56..9950134e4b 100644 --- a/src/xrpld/app/ledger/TransactionStateSF.h +++ b/src/xrpld/app/ledger/TransactionStateSF.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // This class is only needed on add functions // sync filter for transactions tree during ledger sync @@ -34,6 +34,6 @@ private: AbstractFetchPackContainer& fp_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/detail/BuildLedger.cpp b/src/xrpld/app/ledger/detail/BuildLedger.cpp index d7153c0fe9..a716375f6b 100644 --- a/src/xrpld/app/ledger/detail/BuildLedger.cpp +++ b/src/xrpld/app/ledger/detail/BuildLedger.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { /* Generic buildLedgerImpl that dispatches to ApplyTxs invocable with signature void(OpenView&, std::shared_ptr const&) @@ -39,7 +39,7 @@ buildLedgerImpl( { OpenView accum(&*built); XRPL_ASSERT( - !accum.open(), "ripple::buildLedgerImpl : valid ledger state"); + !accum.open(), "xrpl::buildLedgerImpl : valid ledger state"); applyTxs(accum, built); accum.apply(*built); } @@ -60,7 +60,7 @@ buildLedgerImpl( XRPL_ASSERT( built->header().seq < XRP_LEDGER_EARLIEST_FEES || built->read(keylet::fees()), - "ripple::buildLedgerImpl : valid ledger fees"); + "xrpl::buildLedgerImpl : valid ledger fees"); built->setAccepted(closeTime, closeResolution, closeTimeCorrect); return built; @@ -154,7 +154,7 @@ applyTransactions( // tried them in at least one final pass XRPL_ASSERT( txns.empty() || !certainRetry, - "ripple::applyTransactions : retry transactions"); + "xrpl::applyTransactions : retry transactions"); return count; } @@ -228,4 +228,4 @@ buildLedger( }); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/InboundLedger.cpp b/src/xrpld/app/ledger/detail/InboundLedger.cpp index cd42b4fe82..1f5e5cc7b6 100644 --- a/src/xrpld/app/ledger/detail/InboundLedger.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedger.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { using namespace std::chrono_literals; @@ -104,7 +104,7 @@ InboundLedger::init(ScopedLockType& collectionLock) XRPL_ASSERT( mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), - "ripple::InboundLedger::init : valid ledger fees"); + "xrpl::InboundLedger::init : valid ledger fees"); mLedger->setImmutable(); if (mReason == Reason::HISTORY) @@ -337,7 +337,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) XRPL_ASSERT( mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), - "ripple::InboundLedger::tryDB : valid ledger fees"); + "xrpl::InboundLedger::tryDB : valid ledger fees"); mLedger->setImmutable(); } } @@ -432,15 +432,14 @@ InboundLedger::done() << mStats.get(); XRPL_ASSERT( - complete_ || failed_, - "ripple::InboundLedger::done : complete or failed"); + complete_ || failed_, "xrpl::InboundLedger::done : complete or failed"); if (complete_ && !failed_ && mLedger) { XRPL_ASSERT( mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), - "ripple::InboundLedger::done : valid ledger fees"); + "xrpl::InboundLedger::done : valid ledger fees"); mLedger->setImmutable(); switch (mReason) { @@ -604,7 +603,7 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) { XRPL_ASSERT( mLedger, - "ripple::InboundLedger::trigger : non-null ledger to read state " + "xrpl::InboundLedger::trigger : non-null ledger to read state " "from"); if (!mLedger->stateMap().isValid()) @@ -679,7 +678,7 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) { XRPL_ASSERT( mLedger, - "ripple::InboundLedger::trigger : non-null ledger to read " + "xrpl::InboundLedger::trigger : non-null ledger to read " "transactions from"); if (!mLedger->txMap().isValid()) @@ -946,7 +945,7 @@ InboundLedger::takeAsRootNode(Slice const& data, SHAMapAddNode& san) if (!mHaveHeader) { // LCOV_EXCL_START - UNREACHABLE("ripple::InboundLedger::takeAsRootNode : no ledger header"); + UNREACHABLE("xrpl::InboundLedger::takeAsRootNode : no ledger header"); return false; // LCOV_EXCL_STOP } @@ -973,7 +972,7 @@ InboundLedger::takeTxRootNode(Slice const& data, SHAMapAddNode& san) if (!mHaveHeader) { // LCOV_EXCL_START - UNREACHABLE("ripple::InboundLedger::takeTxRootNode : no ledger header"); + UNREACHABLE("xrpl::InboundLedger::takeTxRootNode : no ledger header"); return false; // LCOV_EXCL_STOP } @@ -1335,4 +1334,4 @@ InboundLedger::getJson(int) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/InboundLedgers.cpp b/src/xrpld/app/ledger/detail/InboundLedgers.cpp index fafcdb9161..445786eb63 100644 --- a/src/xrpld/app/ledger/detail/InboundLedgers.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedgers.cpp @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { class InboundLedgersImp : public InboundLedgers { @@ -56,7 +56,7 @@ public: auto doAcquire = [&, seq, reason]() -> std::shared_ptr { XRPL_ASSERT( hash.isNonZero(), - "ripple::InboundLedgersImp::acquire::doAcquire : nonzero hash"); + "xrpl::InboundLedgersImp::acquire::doAcquire : nonzero hash"); // probably not the right rule if (app_.getOPs().isNeedNetworkLedger() && @@ -146,8 +146,7 @@ public: find(uint256 const& hash) override { XRPL_ASSERT( - hash.isNonZero(), - "ripple::InboundLedgersImp::find : nonzero input"); + hash.isNonZero(), "xrpl::InboundLedgersImp::find : nonzero input"); std::shared_ptr ret; @@ -311,7 +310,7 @@ public: { XRPL_ASSERT( it.second, - "ripple::InboundLedgersImp::getInfo : non-null ledger"); + "xrpl::InboundLedgersImp::getInfo : non-null ledger"); acqs.push_back(it); } for (auto const& it : mRecentFailures) @@ -348,7 +347,7 @@ public: { XRPL_ASSERT( it.second, - "ripple::InboundLedgersImp::gotFetchPack : non-null " + "xrpl::InboundLedgersImp::gotFetchPack : non-null " "ledger"); acquires.push_back(it.second); } @@ -458,4 +457,4 @@ make_InboundLedgers( app, clock, collector, make_PeerSetBuilder(app)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/InboundTransactions.cpp b/src/xrpld/app/ledger/detail/InboundTransactions.cpp index b84a03e7bb..80906c45e7 100644 --- a/src/xrpld/app/ledger/detail/InboundTransactions.cpp +++ b/src/xrpld/app/ledger/detail/InboundTransactions.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { enum { // Ideal number of peers to start with @@ -258,4 +258,4 @@ make_InboundTransactions( app, collector, std::move(gotSet), make_PeerSetBuilder(app)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp index 639d8250ac..1eec2efc80 100644 --- a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp +++ b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { /* @@ -215,7 +215,7 @@ private: break; XRPL_ASSERT( state_ == State::cleaning, - "ripple::LedgerCleanerImp::run : is cleaning"); + "xrpl::LedgerCleanerImp::run : is cleaning"); } doLedgerCleaner(); } @@ -338,8 +338,7 @@ private: bool const nonzero(refHash.isNonZero()); XRPL_ASSERT( - nonzero, - "ripple::LedgerCleanerImp::getHash : nonzero hash"); + nonzero, "xrpl::LedgerCleanerImp::getHash : nonzero hash"); if (nonzero) { // We found the hash and sequence of a better reference @@ -443,4 +442,4 @@ make_LedgerCleaner(Application& app, beast::Journal journal) return std::make_unique(app, journal); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp index 9c190ee376..5b642ba3db 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { LedgerDeltaAcquire::LedgerDeltaAcquire( Application& app, @@ -183,10 +183,10 @@ LedgerDeltaAcquire::tryBuild(std::shared_ptr const& parent) XRPL_ASSERT( parent->seq() + 1 == replayTemp_->seq(), - "ripple::LedgerDeltaAcquire::tryBuild : parent sequence match"); + "xrpl::LedgerDeltaAcquire::tryBuild : parent sequence match"); XRPL_ASSERT( parent->header().hash == replayTemp_->header().parentHash, - "ripple::LedgerDeltaAcquire::tryBuild : parent hash match"); + "xrpl::LedgerDeltaAcquire::tryBuild : parent hash match"); // build ledger LedgerReplay replayData(parent, replayTemp_, std::move(orderedTxns_)); fullLedger_ = buildLedger(replayData, tapNONE, app_, journal_); @@ -248,7 +248,7 @@ LedgerDeltaAcquire::onLedgerBuilt( void LedgerDeltaAcquire::notify(ScopedLockType& sl) { - XRPL_ASSERT(isDone(), "ripple::LedgerDeltaAcquire::notify : is done"); + XRPL_ASSERT(isDone(), "xrpl::LedgerDeltaAcquire::notify : is done"); std::vector toCall; std::swap(toCall, dataReadyCallbacks_); auto const good = !failed_; @@ -262,4 +262,4 @@ LedgerDeltaAcquire::notify(ScopedLockType& sl) sl.lock(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h index a2c300c546..779bbfa85e 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { class InboundLedgers; class PeerSet; namespace test { @@ -142,6 +142,6 @@ private: friend class test::LedgerReplayClient; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/detail/LedgerMaster.cpp b/src/xrpld/app/ledger/detail/LedgerMaster.cpp index 3e75a28abd..2a2424995e 100644 --- a/src/xrpld/app/ledger/detail/LedgerMaster.cpp +++ b/src/xrpld/app/ledger/detail/LedgerMaster.cpp @@ -37,7 +37,7 @@ #include #include -namespace ripple { +namespace xrpl { // Don't catch up more than 100 ledgers (cannot exceed 256) static constexpr int MAX_LEDGER_GAP{100}; @@ -257,7 +257,7 @@ LedgerMaster::setValidLedger(std::shared_ptr const& l) mValidLedgerSeq || !app_.getMaxDisallowedLedger() || l->header().seq + max_ledger_difference_ > app_.getMaxDisallowedLedger(), - "ripple::LedgerMaster::setValidLedger : valid ledger sequence"); + "xrpl::LedgerMaster::setValidLedger : valid ledger sequence"); (void)max_ledger_difference_; mValidLedgerSeq = l->header().seq; @@ -322,7 +322,7 @@ LedgerMaster::addHeldTransaction( bool LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) { - XRPL_ASSERT(ledger, "ripple::LedgerMaster::canBeCurrent : non-null input"); + XRPL_ASSERT(ledger, "xrpl::LedgerMaster::canBeCurrent : non-null input"); // Never jump to a candidate ledger that precedes our // last validated ledger @@ -390,7 +390,7 @@ LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) void LedgerMaster::switchLCL(std::shared_ptr const& lastClosed) { - XRPL_ASSERT(lastClosed, "ripple::LedgerMaster::switchLCL : non-null input"); + XRPL_ASSERT(lastClosed, "xrpl::LedgerMaster::switchLCL : non-null input"); if (!lastClosed->isImmutable()) LogicError("mutable ledger in switchLCL"); @@ -500,7 +500,7 @@ LedgerMaster::isValidated(ReadView const& ledger) { XRPL_ASSERT( hash->isNonZero(), - "ripple::LedgerMaster::isValidated : nonzero hash"); + "xrpl::LedgerMaster::isValidated : nonzero hash"); uint256 valHash = app_.getRelationalDatabase().getHashByIndex(seq); if (valHash == ledger.header().hash) @@ -792,7 +792,7 @@ LedgerMaster::setFullLedger( << " accepted :" << ledger->header().hash; XRPL_ASSERT( ledger->stateMap().getHash().isNonZero(), - "ripple::LedgerMaster::setFullLedger : nonzero ledger state hash"); + "xrpl::LedgerMaster::setFullLedger : nonzero ledger state hash"); ledger->setValidated(); ledger->setFull(); @@ -1258,7 +1258,7 @@ LedgerMaster::findNewLedgersToPublish( JLOG(m_journal.fatal()) << "Ledger: " << valSeq << " does not have hash for " << seq; UNREACHABLE( - "ripple::LedgerMaster::findNewLedgersToPublish : ledger " + "xrpl::LedgerMaster::findNewLedgersToPublish : ledger " "not found"); // LCOV_EXCL_STOP } @@ -1349,7 +1349,7 @@ LedgerMaster::tryAdvance() XRPL_ASSERT( !mValidLedger.empty() && mAdvanceThread, - "ripple::LedgerMaster::tryAdvance : has valid ledger"); + "xrpl::LedgerMaster::tryAdvance : has valid ledger"); JLOG(m_journal.trace()) << "advanceThread<"; @@ -1651,7 +1651,7 @@ LedgerMaster::walkHashBySeq( // be located easily and should contain the hash. LedgerIndex refIndex = getCandidateLedger(index); auto const refHash = hashOfSeq(*referenceLedger, refIndex, m_journal); - XRPL_ASSERT(refHash, "ripple::LedgerMaster::walkHashBySeq : found ledger"); + XRPL_ASSERT(refHash, "xrpl::LedgerMaster::walkHashBySeq : found ledger"); if (refHash) { // Try the hash and sequence of a better reference ledger just found @@ -1678,7 +1678,7 @@ LedgerMaster::walkHashBySeq( ledgerHash = hashOfSeq(*l, index, m_journal); XRPL_ASSERT( ledgerHash, - "ripple::LedgerMaster::walkHashBySeq : has complete " + "xrpl::LedgerMaster::walkHashBySeq : has complete " "ledger"); } } @@ -1793,7 +1793,7 @@ LedgerMaster::fetchForHistory( { XRPL_ASSERT( hash->isNonZero(), - "ripple::LedgerMaster::fetchForHistory : found ledger"); + "xrpl::LedgerMaster::fetchForHistory : found ledger"); auto ledger = getLedgerByHash(*hash); if (!ledger) { @@ -1822,7 +1822,7 @@ LedgerMaster::fetchForHistory( auto seq = ledger->header().seq; XRPL_ASSERT( seq == missing, - "ripple::LedgerMaster::fetchForHistory : sequence match"); + "xrpl::LedgerMaster::fetchForHistory : sequence match"); JLOG(m_journal.trace()) << "fetchForHistory acquired " << seq; setFullLedger(ledger, false, false); int fillInProgress; @@ -1865,7 +1865,7 @@ LedgerMaster::fetchForHistory( { XRPL_ASSERT( h->isNonZero(), - "ripple::LedgerMaster::fetchForHistory : " + "xrpl::LedgerMaster::fetchForHistory : " "prefetched ledger"); app_.getInboundLedgers().acquire(*h, seq, reason); } @@ -2052,7 +2052,7 @@ populateFetchPack( std::uint32_t seq, bool withLeaves = true) { - XRPL_ASSERT(cnt, "ripple::populateFetchPack : nonzero count input"); + XRPL_ASSERT(cnt, "xrpl::populateFetchPack : nonzero count input"); Serializer s(1024); @@ -2242,4 +2242,4 @@ LedgerMaster::txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex) return {}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerReplay.cpp b/src/xrpld/app/ledger/detail/LedgerReplay.cpp index 85ec420bbf..5d7ce0e69f 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplay.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplay.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { LedgerReplay::LedgerReplay( std::shared_ptr parent, @@ -26,4 +26,4 @@ LedgerReplay::LedgerReplay( { } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp index 0a070fdeb0..e1eb51fda7 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { LedgerReplayMsgHandler::LedgerReplayMsgHandler( Application& app, LedgerReplayer& replayer) @@ -273,4 +273,4 @@ LedgerReplayMsgHandler::processReplayDeltaResponse( return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.h b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.h index 276bf316e1..fff3e75460 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.h +++ b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; class LedgerReplayer; @@ -54,6 +54,6 @@ private: beast::Journal journal_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp index 4e73b54d53..cd174b098f 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { LedgerReplayTask::TaskParameter::TaskParameter( InboundLedger::Reason r, @@ -14,7 +14,7 @@ LedgerReplayTask::TaskParameter::TaskParameter( { XRPL_ASSERT( finishLedgerHash.isNonZero() && totalNumLedgers > 0, - "ripple::LedgerReplayTask::TaskParameter::TaskParameter : valid " + "xrpl::LedgerReplayTask::TaskParameter::TaskParameter : valid " "inputs"); } @@ -33,7 +33,7 @@ LedgerReplayTask::TaskParameter::update( startHash_ = skipList_[skipList_.size() - totalLedgers_]; XRPL_ASSERT( startHash_.isNonZero(), - "ripple::LedgerReplayTask::TaskParameter::update : nonzero start hash"); + "xrpl::LedgerReplayTask::TaskParameter::update : nonzero start hash"); startSeq_ = finishSeq_ - totalLedgers_ + 1; full_ = true; return true; @@ -187,7 +187,7 @@ LedgerReplayTask::tryAdvance(ScopedLockType& sl) auto& delta = deltas_[deltaToBuild_]; XRPL_ASSERT( parent_->seq() + 1 == delta->ledgerSeq_, - "ripple::LedgerReplayTask::tryAdvance : consecutive sequence"); + "xrpl::LedgerReplayTask::tryAdvance : consecutive sequence"); if (auto l = delta->tryBuild(parent_); l) { JLOG(journal_.debug()) @@ -279,7 +279,7 @@ LedgerReplayTask::addDelta(std::shared_ptr const& delta) XRPL_ASSERT( deltas_.empty() || deltas_.back()->ledgerSeq_ + 1 == delta->ledgerSeq_, - "ripple::LedgerReplayTask::addDelta : no deltas or consecutive " + "xrpl::LedgerReplayTask::addDelta : no deltas or consecutive " "sequence"); deltas_.push_back(delta); } @@ -292,4 +292,4 @@ LedgerReplayTask::finished() const return isDone(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerReplayer.cpp b/src/xrpld/app/ledger/detail/LedgerReplayer.cpp index 1f89b6c044..1d1cdf3ec2 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayer.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayer.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { LedgerReplayer::LedgerReplayer( Application& app, @@ -30,7 +30,7 @@ LedgerReplayer::replay( XRPL_ASSERT( finishLedgerHash.isNonZero() && totalNumLedgers > 0 && totalNumLedgers <= LedgerReplayParameters::MAX_TASK_SIZE, - "ripple::LedgerReplayer::replay : valid inputs"); + "xrpl::LedgerReplayer::replay : valid inputs"); LedgerReplayTask::TaskParameter parameter( r, finishLedgerHash, totalNumLedgers); @@ -266,4 +266,4 @@ LedgerReplayer::stop() JLOG(j_.info()) << "Stopped"; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerToJson.cpp b/src/xrpld/app/ledger/detail/LedgerToJson.cpp index f571669e5c..8c9e21acde 100644 --- a/src/xrpld/app/ledger/detail/LedgerToJson.cpp +++ b/src/xrpld/app/ledger/detail/LedgerToJson.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace { @@ -342,4 +342,4 @@ getJson(LedgerFill const& fill) return json; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LocalTxs.cpp b/src/xrpld/app/ledger/detail/LocalTxs.cpp index 4d26b60a6f..1e9cfe0b9b 100644 --- a/src/xrpld/app/ledger/detail/LocalTxs.cpp +++ b/src/xrpld/app/ledger/detail/LocalTxs.cpp @@ -27,7 +27,7 @@ test-applied to all new open ledgers until seen in a fully- validated ledger */ -namespace ripple { +namespace xrpl { // This class wraps a pointer to a transaction along with // its expiration ledger. It also caches the issuing account. @@ -175,4 +175,4 @@ make_LocalTxs() return std::make_unique(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/OpenLedger.cpp b/src/xrpld/app/ledger/detail/OpenLedger.cpp index 14db13aad4..35f4b75157 100644 --- a/src/xrpld/app/ledger/detail/OpenLedger.cpp +++ b/src/xrpld/app/ledger/detail/OpenLedger.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { OpenLedger::OpenLedger( std::shared_ptr const& ledger, @@ -163,7 +163,7 @@ OpenLedger::apply_one( if (retry) flags = flags | tapRETRY; // If it's in anybody's proposed set, try to keep it in the ledger - auto const result = ripple::apply(app, view, *tx, flags, j); + auto const result = xrpl::apply(app, view, *tx, flags, j); if (result.applied || result.ter == terQUEUED) return Result::success; if (isTefFailure(result.ter) || isTemMalformed(result.ter) || @@ -220,4 +220,4 @@ debugTostr(std::shared_ptr const& view) return ss.str(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp index a6dbf40d4d..5f4b0dc339 100644 --- a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp +++ b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { SkipListAcquire::SkipListAcquire( Application& app, @@ -121,7 +121,7 @@ SkipListAcquire::processData( { XRPL_ASSERT( ledgerSeq != 0 && item, - "ripple::SkipListAcquire::processData : valid inputs"); + "xrpl::SkipListAcquire::processData : valid inputs"); ScopedLockType sl(mtx_); if (isDone()) return; @@ -206,7 +206,7 @@ SkipListAcquire::onSkipListAcquired( void SkipListAcquire::notify(ScopedLockType& sl) { - XRPL_ASSERT(isDone(), "ripple::SkipListAcquire::notify : is done"); + XRPL_ASSERT(isDone(), "xrpl::SkipListAcquire::notify : is done"); std::vector toCall; std::swap(toCall, dataReadyCallbacks_); auto const good = !failed_; @@ -220,4 +220,4 @@ SkipListAcquire::notify(ScopedLockType& sl) sl.lock(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/SkipListAcquire.h b/src/xrpld/app/ledger/detail/SkipListAcquire.h index 816bacc4cb..15c420a5cd 100644 --- a/src/xrpld/app/ledger/detail/SkipListAcquire.h +++ b/src/xrpld/app/ledger/detail/SkipListAcquire.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class InboundLedgers; class PeerSet; namespace test { @@ -36,11 +36,11 @@ public: struct SkipListData { std::uint32_t const ledgerSeq; - std::vector const skipList; + std::vector const skipList; SkipListData( std::uint32_t const ledgerSeq, - std::vector const& skipList) + std::vector const& skipList) : ledgerSeq(ledgerSeq), skipList(skipList) { } @@ -144,6 +144,6 @@ private: friend class test::LedgerReplayClient; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/detail/TimeoutCounter.cpp b/src/xrpld/app/ledger/detail/TimeoutCounter.cpp index d4e7e9a73c..3482725148 100644 --- a/src/xrpld/app/ledger/detail/TimeoutCounter.cpp +++ b/src/xrpld/app/ledger/detail/TimeoutCounter.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { using namespace std::chrono_literals; @@ -25,7 +25,7 @@ TimeoutCounter::TimeoutCounter( { XRPL_ASSERT( (timerInterval_ > 10ms) && (timerInterval_ < 30s), - "ripple::TimeoutCounter::TimeoutCounter : interval input inside range"); + "xrpl::TimeoutCounter::TimeoutCounter : interval input inside range"); } void @@ -107,4 +107,4 @@ TimeoutCounter::cancel() } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/TimeoutCounter.h b/src/xrpld/app/ledger/detail/TimeoutCounter.h index 1ce4c48415..c228d50aac 100644 --- a/src/xrpld/app/ledger/detail/TimeoutCounter.h +++ b/src/xrpld/app/ledger/detail/TimeoutCounter.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { /** This class is an "active" object. It maintains its own timer @@ -102,7 +102,7 @@ protected: } // Used in this class for access to boost::asio::io_context and - // ripple::Overlay. Used in subtypes for the kitchen sink. + // xrpl::Overlay. Used in subtypes for the kitchen sink. Application& app_; beast::Journal journal_; mutable std::recursive_mutex mtx_; @@ -130,6 +130,6 @@ private: boost::asio::basic_waitable_timer timer_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/detail/TransactionAcquire.cpp b/src/xrpld/app/ledger/detail/TransactionAcquire.cpp index 4c50c5087c..3cd0e84ef0 100644 --- a/src/xrpld/app/ledger/detail/TransactionAcquire.cpp +++ b/src/xrpld/app/ledger/detail/TransactionAcquire.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { using namespace std::chrono_literals; @@ -244,4 +244,4 @@ TransactionAcquire::stillNeed() failed_ = false; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/TransactionAcquire.h b/src/xrpld/app/ledger/detail/TransactionAcquire.h index 60afab7928..83f9b62f83 100644 --- a/src/xrpld/app/ledger/detail/TransactionAcquire.h +++ b/src/xrpld/app/ledger/detail/TransactionAcquire.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { // VFALCO TODO rename to PeerTxRequest // A transaction set we are trying to acquire @@ -54,6 +54,6 @@ private: pmDowncast() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/detail/TransactionMaster.cpp b/src/xrpld/app/ledger/detail/TransactionMaster.cpp index 266a067f66..e8580bcfc6 100644 --- a/src/xrpld/app/ledger/detail/TransactionMaster.cpp +++ b/src/xrpld/app/ledger/detail/TransactionMaster.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { TransactionMaster::TransactionMaster(Application& app) : mApp(app) @@ -151,4 +151,4 @@ TransactionMaster::getCache() return mCache; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index e28cd559e9..15abff9b14 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -66,7 +66,7 @@ #include #include -namespace ripple { +namespace xrpl { static void fixConfigPorts(Config& config, Endpoints const& endpoints); @@ -569,7 +569,7 @@ public: { XRPL_ASSERT( serverHandler_, - "ripple::ApplicationImp::getServerHandler : non-null server " + "xrpl::ApplicationImp::getServerHandler : non-null server " "handle"); return *serverHandler_; } @@ -777,7 +777,7 @@ public: overlay() override { XRPL_ASSERT( - overlay_, "ripple::ApplicationImp::overlay : non-null overlay"); + overlay_, "xrpl::ApplicationImp::overlay : non-null overlay"); return *overlay_; } @@ -785,8 +785,7 @@ public: getTxQ() override { XRPL_ASSERT( - txQ_, - "ripple::ApplicationImp::getTxQ : non-null transaction queue"); + txQ_, "xrpl::ApplicationImp::getTxQ : non-null transaction queue"); return *txQ_; } @@ -795,7 +794,7 @@ public: { XRPL_ASSERT( mRelationalDatabase, - "ripple::ApplicationImp::getRelationalDatabase : non-null " + "xrpl::ApplicationImp::getRelationalDatabase : non-null " "relational database"); return *mRelationalDatabase; } @@ -805,7 +804,7 @@ public: { XRPL_ASSERT( mWalletDB, - "ripple::ApplicationImp::getWalletDB : non-null wallet database"); + "xrpl::ApplicationImp::getWalletDB : non-null wallet database"); return *mWalletDB; } @@ -822,7 +821,7 @@ public: { XRPL_ASSERT( mWalletDB.get() == nullptr, - "ripple::ApplicationImp::initRelationalDatabase : null wallet " + "xrpl::ApplicationImp::initRelationalDatabase : null wallet " "database"); try @@ -1223,9 +1222,9 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) supported.reserve(amendments.size()); for (auto const& [a, vote] : amendments) { - auto const f = ripple::getRegisteredFeature(a); + auto const f = xrpl::getRegisteredFeature(a); XRPL_ASSERT( - f, "ripple::ApplicationImp::setup : registered feature"); + f, "xrpl::ApplicationImp::setup : registered feature"); if (f) supported.emplace_back(a, *f, vote); } @@ -1701,7 +1700,7 @@ ApplicationImp::startGenesisLedger() XRPL_ASSERT( next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()), - "ripple::ApplicationImp::startGenesisLedger : valid ledger fees"); + "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees"); next->setImmutable(); openLedger_.emplace(next, cachedSLEs_, logs_->journal("OpenLedger")); m_ledgerMaster->storeLedger(next); @@ -1723,7 +1722,7 @@ ApplicationImp::getLastFullLedger() XRPL_ASSERT( ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()), - "ripple::ApplicationImp::getLastFullLedger : valid ledger fees"); + "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees"); ledger->setImmutable(); if (getLedgerMaster().haveLedger(seq)) @@ -1878,7 +1877,7 @@ ApplicationImp::loadLedgerFromFile(std::string const& name) XRPL_ASSERT( loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()), - "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees"); + "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees"); loadLedger->setAccepted( closeTime, closeTimeResolution, !closeTimeEstimated); @@ -1978,7 +1977,7 @@ ApplicationImp::loadOldLedger( // LCOV_EXCL_START JLOG(m_journal.fatal()) << "Replay ledger missing/damaged"; UNREACHABLE( - "ripple::ApplicationImp::loadOldLedger : replay ledger " + "xrpl::ApplicationImp::loadOldLedger : replay ledger " "missing/damaged"); return false; // LCOV_EXCL_STOP @@ -2011,7 +2010,7 @@ ApplicationImp::loadOldLedger( // LCOV_EXCL_START JLOG(m_journal.fatal()) << "Ledger is empty."; UNREACHABLE( - "ripple::ApplicationImp::loadOldLedger : ledger is empty"); + "xrpl::ApplicationImp::loadOldLedger : ledger is empty"); return false; // LCOV_EXCL_STOP } @@ -2021,7 +2020,7 @@ ApplicationImp::loadOldLedger( // LCOV_EXCL_START JLOG(m_journal.fatal()) << "Ledger is missing nodes."; UNREACHABLE( - "ripple::ApplicationImp::loadOldLedger : ledger is missing " + "xrpl::ApplicationImp::loadOldLedger : ledger is missing " "nodes"); return false; // LCOV_EXCL_STOP @@ -2032,7 +2031,7 @@ ApplicationImp::loadOldLedger( // LCOV_EXCL_START JLOG(m_journal.fatal()) << "Ledger is not sensible."; UNREACHABLE( - "ripple::ApplicationImp::loadOldLedger : ledger is not " + "xrpl::ApplicationImp::loadOldLedger : ledger is not " "sensible"); return false; // LCOV_EXCL_STOP @@ -2206,4 +2205,4 @@ fixConfigPorts(Config& config, Endpoints const& endpoints) } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/main/Application.h b/src/xrpld/app/main/Application.h index d8cceb687b..ffb3cd9983 100644 --- a/src/xrpld/app/main/Application.h +++ b/src/xrpld/app/main/Application.h @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { namespace unl { class Manager; @@ -264,6 +264,6 @@ make_Application( std::unique_ptr logs, std::unique_ptr timeKeeper); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/main/CollectorManager.cpp b/src/xrpld/app/main/CollectorManager.cpp index d66b08db8c..110ea564d8 100644 --- a/src/xrpld/app/main/CollectorManager.cpp +++ b/src/xrpld/app/main/CollectorManager.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { class CollectorManagerImp : public CollectorManager { @@ -56,4 +56,4 @@ make_CollectorManager(Section const& params, beast::Journal journal) return std::make_unique(params, journal); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/main/CollectorManager.h b/src/xrpld/app/main/CollectorManager.h index d0cc35f94f..d0d202625c 100644 --- a/src/xrpld/app/main/CollectorManager.h +++ b/src/xrpld/app/main/CollectorManager.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Provides the beast::insight::Collector service. */ class CollectorManager @@ -22,6 +22,6 @@ public: std::unique_ptr make_CollectorManager(Section const& params, beast::Journal journal); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/main/DBInit.h b/src/xrpld/app/main/DBInit.h index 9219db715a..60ff4b498b 100644 --- a/src/xrpld/app/main/DBInit.h +++ b/src/xrpld/app/main/DBInit.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { //////////////////////////////////////////////////////////////////////////////// @@ -116,6 +116,6 @@ inline constexpr std::array WalletDBInit{ "END TRANSACTION;"}}; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/main/GRPCServer.cpp b/src/xrpld/app/main/GRPCServer.cpp index 03aa0f6612..e415ee14cf 100644 --- a/src/xrpld/app/main/GRPCServer.cpp +++ b/src/xrpld/app/main/GRPCServer.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace { @@ -249,7 +249,7 @@ template std::optional GRPCServerImpl::CallData::getClientEndpoint() { - return ripple::getEndpoint(ctx_.peer()); + return xrpl::getEndpoint(ctx_.peer()); } template @@ -601,7 +601,7 @@ GRPCServer::stop() GRPCServer::~GRPCServer() { - XRPL_ASSERT(!running_, "ripple::GRPCServer::~GRPCServer : is not running"); + XRPL_ASSERT(!running_, "xrpl::GRPCServer::~GRPCServer : is not running"); } boost::asio::ip::tcp::endpoint @@ -610,4 +610,4 @@ GRPCServer::getEndpoint() const return impl_.getEndpoint(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/main/GRPCServer.h b/src/xrpld/app/main/GRPCServer.h index eba666cc35..dab71303c4 100644 --- a/src/xrpld/app/main/GRPCServer.h +++ b/src/xrpld/app/main/GRPCServer.h @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { // Interface that CallData implements class Processor @@ -305,5 +305,5 @@ private: std::thread thread_; bool running_ = false; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/main/LoadManager.cpp b/src/xrpld/app/main/LoadManager.cpp index 92a4c49bf2..91afb67eb7 100644 --- a/src/xrpld/app/main/LoadManager.cpp +++ b/src/xrpld/app/main/LoadManager.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { LoadManager::LoadManager(Application& app, beast::Journal journal) : app_(app), journal_(journal), lastHeartbeat_(), armed_(false) @@ -56,8 +56,7 @@ LoadManager::start() { JLOG(journal_.debug()) << "Starting"; XRPL_ASSERT( - !thread_.joinable(), - "ripple::LoadManager::start : thread not joinable"); + !thread_.joinable(), "xrpl::LoadManager::start : thread not joinable"); thread_ = std::thread{&LoadManager::run, this}; } @@ -182,4 +181,4 @@ make_LoadManager(Application& app, beast::Journal journal) return std::unique_ptr{new LoadManager{app, journal}}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/main/LoadManager.h b/src/xrpld/app/main/LoadManager.h index bd3a72b80b..15caa9b0f0 100644 --- a/src/xrpld/app/main/LoadManager.h +++ b/src/xrpld/app/main/LoadManager.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; @@ -94,6 +94,6 @@ private: std::unique_ptr make_LoadManager(Application& app, beast::Journal journal); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/main/Main.cpp b/src/xrpld/app/main/Main.cpp index 2491149160..7c138168e4 100644 --- a/src/xrpld/app/main/Main.cpp +++ b/src/xrpld/app/main/Main.cpp @@ -53,7 +53,7 @@ namespace po = boost::program_options; -namespace ripple { +namespace xrpl { bool adjustDescriptorLimit(int needed, beast::Journal j) @@ -248,9 +248,9 @@ runUnitTests( char** argv) { using namespace beast::unit_test; - using namespace ripple::test; + using namespace xrpl::test; - ripple::test::envUseIPv4 = (!ipv6); + xrpl::test::envUseIPv4 = (!ipv6); if (!child && num_jobs == 1) { @@ -829,7 +829,7 @@ run(int argc, char** argv) // LCOV_EXCL_STOP } -} // namespace ripple +} // namespace xrpl int main(int argc, char** argv) @@ -854,5 +854,5 @@ main(int argc, char** argv) atexit(&google::protobuf::ShutdownProtobufLibrary); - return ripple::run(argc, argv); + return xrpl::run(argc, argv); } diff --git a/src/xrpld/app/main/NodeIdentity.cpp b/src/xrpld/app/main/NodeIdentity.cpp index 4c7148642c..73ef3f0152 100644 --- a/src/xrpld/app/main/NodeIdentity.cpp +++ b/src/xrpld/app/main/NodeIdentity.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { std::pair getNodeIdentity( @@ -46,4 +46,4 @@ getNodeIdentity( return getNodeIdentity(*db); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/main/NodeIdentity.h b/src/xrpld/app/main/NodeIdentity.h index fcef1d1d03..7fdb748033 100644 --- a/src/xrpld/app/main/NodeIdentity.h +++ b/src/xrpld/app/main/NodeIdentity.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { /** The cryptographic credentials identifying this server instance. @@ -20,6 +20,6 @@ getNodeIdentity( Application& app, boost::program_options::variables_map const& cmdline); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/main/NodeStoreScheduler.cpp b/src/xrpld/app/main/NodeStoreScheduler.cpp index ba9c2ff281..221c1f098e 100644 --- a/src/xrpld/app/main/NodeStoreScheduler.cpp +++ b/src/xrpld/app/main/NodeStoreScheduler.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { NodeStoreScheduler::NodeStoreScheduler(JobQueue& jobQueue) : jobQueue_(jobQueue) { @@ -44,4 +44,4 @@ NodeStoreScheduler::onBatchWrite(NodeStore::BatchWriteReport const& report) jobQueue_.addLoadEvents(jtNS_WRITE, report.writeCount, report.elapsed); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/main/NodeStoreScheduler.h b/src/xrpld/app/main/NodeStoreScheduler.h index 6a5cb8e8ee..0214b76660 100644 --- a/src/xrpld/app/main/NodeStoreScheduler.h +++ b/src/xrpld/app/main/NodeStoreScheduler.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { /** A NodeStore::Scheduler which uses the JobQueue. */ class NodeStoreScheduler : public NodeStore::Scheduler @@ -23,6 +23,6 @@ private: JobQueue& jobQueue_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/main/Tuning.h b/src/xrpld/app/main/Tuning.h index 6c7db8ea72..25cc2ef75d 100644 --- a/src/xrpld/app/main/Tuning.h +++ b/src/xrpld/app/main/Tuning.h @@ -3,13 +3,13 @@ #include -namespace ripple { +namespace xrpl { constexpr std::size_t fullBelowTargetSize = 524288; constexpr std::chrono::seconds fullBelowExpiration = std::chrono::minutes{10}; constexpr std::size_t maxPoppedTransactions = 10; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/AMMHelpers.h b/src/xrpld/app/misc/AMMHelpers.h index c300774553..3a33f49ee4 100644 --- a/src/xrpld/app/misc/AMMHelpers.h +++ b/src/xrpld/app/misc/AMMHelpers.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -761,6 +761,6 @@ adjustFracByTokens( STAmount const& tokens, Number const& frac); -} // namespace ripple +} // namespace xrpl #endif // XRPL_APP_MISC_AMMHELPERS_H_INCLUDED diff --git a/src/xrpld/app/misc/AMMUtils.h b/src/xrpld/app/misc/AMMUtils.h index 7369ee4998..266f50bb87 100644 --- a/src/xrpld/app/misc/AMMUtils.h +++ b/src/xrpld/app/misc/AMMUtils.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { class ReadView; class ApplyView; @@ -116,6 +116,6 @@ verifyAndAdjustLPTokenBalance( std::shared_ptr& ammSle, AccountID const& account); -} // namespace ripple +} // namespace xrpl #endif // XRPL_APP_MISC_AMMUTILS_H_INCLUDED diff --git a/src/xrpld/app/misc/AmendmentTable.h b/src/xrpld/app/misc/AmendmentTable.h index af436205fb..0265e0127f 100644 --- a/src/xrpld/app/misc/AmendmentTable.h +++ b/src/xrpld/app/misc/AmendmentTable.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { /** The amendment table stores the list of enabled and potential amendments. Individuals amendments are voted on by validators during the consensus @@ -177,6 +177,6 @@ make_AmendmentTable( Section const& vetoed, beast::Journal journal); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/CanonicalTXSet.cpp b/src/xrpld/app/misc/CanonicalTXSet.cpp index 311d120d4e..ac1b86e62f 100644 --- a/src/xrpld/app/misc/CanonicalTXSet.cpp +++ b/src/xrpld/app/misc/CanonicalTXSet.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { bool operator<(CanonicalTXSet::Key const& lhs, CanonicalTXSet::Key const& rhs) @@ -71,4 +71,4 @@ CanonicalTXSet::popAcctTransaction(std::shared_ptr const& tx) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/CanonicalTXSet.h b/src/xrpld/app/misc/CanonicalTXSet.h index 9a7d7fe171..8d0461a845 100644 --- a/src/xrpld/app/misc/CanonicalTXSet.h +++ b/src/xrpld/app/misc/CanonicalTXSet.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Holds transactions which were deferred to the next pass of consensus. @@ -156,6 +156,6 @@ private: uint256 salt_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/DelegateUtils.h b/src/xrpld/app/misc/DelegateUtils.h index 21b78ca71c..37d9195a82 100644 --- a/src/xrpld/app/misc/DelegateUtils.h +++ b/src/xrpld/app/misc/DelegateUtils.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { /** * Check if the delegate account has permission to execute the transaction. @@ -33,6 +33,6 @@ loadGranularPermission( TxType const& type, std::unordered_set& granularPermissions); -} // namespace ripple +} // namespace xrpl #endif // XRPL_APP_MISC_DELEGATEUTILS_H_INCLUDED diff --git a/src/xrpld/app/misc/DeliverMax.h b/src/xrpld/app/misc/DeliverMax.h index 0847bf185d..e9455354f8 100644 --- a/src/xrpld/app/misc/DeliverMax.h +++ b/src/xrpld/app/misc/DeliverMax.h @@ -7,7 +7,7 @@ namespace Json { class Value; } -namespace ripple { +namespace xrpl { namespace RPC { @@ -26,6 +26,6 @@ insertDeliverMax(Json::Value& tx_json, TxType txnType, unsigned int apiVersion); /** @} */ } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/FeeVote.h b/src/xrpld/app/misc/FeeVote.h index 15fd8e39fe..aed64be2c2 100644 --- a/src/xrpld/app/misc/FeeVote.h +++ b/src/xrpld/app/misc/FeeVote.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Manager to process fee votes. */ class FeeVote @@ -44,6 +44,6 @@ struct FeeSetup; std::unique_ptr make_FeeVote(FeeSetup const& setup, beast::Journal journal); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/FeeVoteImpl.cpp b/src/xrpld/app/misc/FeeVoteImpl.cpp index 88c33bd66b..a6b140f691 100644 --- a/src/xrpld/app/misc/FeeVoteImpl.cpp +++ b/src/xrpld/app/misc/FeeVoteImpl.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -182,7 +182,7 @@ FeeVoteImpl::doVoting( // LCL must be flag ledger XRPL_ASSERT( lastClosedLedger && isFlagLedger(lastClosedLedger->seq()), - "ripple::FeeVoteImpl::doVoting : has a flag ledger"); + "xrpl::FeeVoteImpl::doVoting : has a flag ledger"); detail::VotableValue baseFeeVote( lastClosedLedger->fees().base, target_.reference_fee); @@ -323,4 +323,4 @@ make_FeeVote(FeeSetup const& setup, beast::Journal journal) return std::make_unique(setup, journal); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/HashRouter.cpp b/src/xrpld/app/misc/HashRouter.cpp index da27158969..0cad01c27e 100644 --- a/src/xrpld/app/misc/HashRouter.cpp +++ b/src/xrpld/app/misc/HashRouter.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { auto HashRouter::emplace(uint256 const& key) -> std::pair @@ -87,7 +87,7 @@ bool HashRouter::setFlags(uint256 const& key, HashRouterFlags flags) { XRPL_ASSERT( - static_cast(flags), "ripple::HashRouter::setFlags : valid input"); + static_cast(flags), "xrpl::HashRouter::setFlags : valid input"); std::lock_guard lock(mutex_); @@ -149,4 +149,4 @@ setup_HashRouter(Config const& config) return setup; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/HashRouter.h b/src/xrpld/app/misc/HashRouter.h index f7ecb153fe..1b59797b28 100644 --- a/src/xrpld/app/misc/HashRouter.h +++ b/src/xrpld/app/misc/HashRouter.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { enum class HashRouterFlags : std::uint16_t { // Public flags @@ -270,6 +270,6 @@ private: HashRouter::Setup setup_HashRouter(Config const&); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/LendingHelpers.h b/src/xrpld/app/misc/LendingHelpers.h index 559af28a47..071466f05c 100644 --- a/src/xrpld/app/misc/LendingHelpers.h +++ b/src/xrpld/app/misc/LendingHelpers.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { struct PreflightContext; @@ -155,7 +155,7 @@ struct LoanState XRPL_ASSERT_PARTS( interestDue + managementFeeDue == valueOutstanding - principalOutstanding, - "ripple::LoanState::interestOutstanding", + "xrpl::LoanState::interestOutstanding", "other values add up correctly"); return interestDue + managementFeeDue; } @@ -439,6 +439,6 @@ loanMakePayment( LoanPaymentType const paymentType, beast::Journal j); -} // namespace ripple +} // namespace xrpl #endif // XRPL_APP_MISC_LENDINGHELPERS_H_INCLUDED diff --git a/src/xrpld/app/misc/LoadFeeTrack.h b/src/xrpld/app/misc/LoadFeeTrack.h index dfae110fb4..181fb0536e 100644 --- a/src/xrpld/app/misc/LoadFeeTrack.h +++ b/src/xrpld/app/misc/LoadFeeTrack.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { struct Fees; @@ -147,6 +147,6 @@ scaleFeeLoad( Fees const& fees, bool bUnlimited); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/Manifest.h b/src/xrpld/app/misc/Manifest.h index 49b345d095..24e4f5f71f 100644 --- a/src/xrpld/app/misc/Manifest.h +++ b/src/xrpld/app/misc/Manifest.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /* Validator key manifests @@ -443,6 +443,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/NegativeUNLVote.cpp b/src/xrpld/app/misc/NegativeUNLVote.cpp index 23d3248ba6..12467697fa 100644 --- a/src/xrpld/app/misc/NegativeUNLVote.cpp +++ b/src/xrpld/app/misc/NegativeUNLVote.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { NegativeUNLVote::NegativeUNLVote(NodeID const& myId, beast::Journal j) : myId_(myId), j_(j) @@ -73,7 +73,7 @@ NegativeUNLVote::doVoting( prevLedger->header().hash, candidates.toDisableCandidates); XRPL_ASSERT( nidToKeyMap.contains(n), - "ripple::NegativeUNLVote::doVoting : found node to disable"); + "xrpl::NegativeUNLVote::doVoting : found node to disable"); addTx(seq, nidToKeyMap.at(n), ToDisable, initialSet); } @@ -83,7 +83,7 @@ NegativeUNLVote::doVoting( prevLedger->header().hash, candidates.toReEnableCandidates); XRPL_ASSERT( nidToKeyMap.contains(n), - "ripple::NegativeUNLVote::doVoting : found node to enable"); + "xrpl::NegativeUNLVote::doVoting : found node to enable"); addTx(seq, nidToKeyMap.at(n), ToReEnable, initialSet); } } @@ -127,8 +127,7 @@ NegativeUNLVote::choose( std::vector const& candidates) { XRPL_ASSERT( - !candidates.empty(), - "ripple::NegativeUNLVote::choose : non-empty input"); + !candidates.empty(), "xrpl::NegativeUNLVote::choose : non-empty input"); static_assert(NodeID::bytes <= uint256::bytes); NodeID randomPad = NodeID::fromVoid(randomPadData.data()); NodeID txNodeID = candidates[0]; @@ -336,4 +335,4 @@ NegativeUNLVote::purgeNewValidators(LedgerIndex seq) } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/NegativeUNLVote.h b/src/xrpld/app/misc/NegativeUNLVote.h index 77b4035a0d..3146294923 100644 --- a/src/xrpld/app/misc/NegativeUNLVote.h +++ b/src/xrpld/app/misc/NegativeUNLVote.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { template class Validations; @@ -194,6 +194,6 @@ private: friend class test::NegativeUNLVoteScoreTable_test; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index 39ec0b78c9..084a584377 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -64,7 +64,7 @@ #include #include -namespace ripple { +namespace xrpl { class NetworkOPsImp final : public NetworkOPs { @@ -91,7 +91,7 @@ class NetworkOPsImp final : public NetworkOPs { XRPL_ASSERT( local || failType == FailHard::no, - "ripple::NetworkOPsImp::TransactionStatus::TransactionStatus : " + "xrpl::NetworkOPsImp::TransactionStatus::TransactionStatus : " "valid inputs"); } }; @@ -1267,7 +1267,7 @@ NetworkOPsImp::preProcessTransaction(std::shared_ptr& transaction) checkValidity(app_.getHashRouter(), sttx, view->rules(), app_.config()); XRPL_ASSERT( validity == Validity::Valid, - "ripple::NetworkOPsImp::processTransaction : valid validity"); + "xrpl::NetworkOPsImp::processTransaction : valid validity"); // Not concerned with local checks at this point. if (validity == Validity::SigBad) @@ -1442,7 +1442,7 @@ NetworkOPsImp::processTransactionSet(CanonicalTXSet const& set) doTransactionSyncBatch(lock, [&](std::unique_lock const&) { XRPL_ASSERT( lock.owns_lock(), - "ripple::NetworkOPsImp::processTransactionSet has lock"); + "xrpl::NetworkOPsImp::processTransactionSet has lock"); return std::any_of( mTransactions.begin(), mTransactions.end(), [](auto const& t) { return t.transaction->getApplying(); @@ -1472,10 +1472,10 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) mTransactions.swap(transactions); XRPL_ASSERT( !transactions.empty(), - "ripple::NetworkOPsImp::apply : non-empty transactions"); + "xrpl::NetworkOPsImp::apply : non-empty transactions"); XRPL_ASSERT( mDispatchState != DispatchState::running, - "ripple::NetworkOPsImp::apply : is not running"); + "xrpl::NetworkOPsImp::apply : is not running"); mDispatchState = DispatchState::running; @@ -1754,7 +1754,7 @@ NetworkOPsImp::getOwnerInfo( auto sleCur = lpLedger->read(keylet::child(uDirEntry)); XRPL_ASSERT( sleCur, - "ripple::NetworkOPsImp::getOwnerInfo : non-null child SLE"); + "xrpl::NetworkOPsImp::getOwnerInfo : non-null child SLE"); switch (sleCur->getType()) { @@ -1783,7 +1783,7 @@ NetworkOPsImp::getOwnerInfo( // LCOV_EXCL_START default: UNREACHABLE( - "ripple::NetworkOPsImp::getOwnerInfo : invalid " + "xrpl::NetworkOPsImp::getOwnerInfo : invalid " "type"); break; // LCOV_EXCL_STOP @@ -1797,7 +1797,7 @@ NetworkOPsImp::getOwnerInfo( sleNode = lpLedger->read(keylet::page(root, uNodeDir)); XRPL_ASSERT( sleNode, - "ripple::NetworkOPsImp::getOwnerInfo : read next page"); + "xrpl::NetworkOPsImp::getOwnerInfo : read next page"); } } while (uNodeDir); } @@ -2034,7 +2034,7 @@ NetworkOPsImp::beginConsensus( { XRPL_ASSERT( networkClosed.isNonZero(), - "ripple::NetworkOPsImp::beginConsensus : nonzero input"); + "xrpl::NetworkOPsImp::beginConsensus : nonzero input"); auto closingInfo = m_ledgerMaster.getCurrentLedger()->header(); @@ -2059,12 +2059,12 @@ NetworkOPsImp::beginConsensus( XRPL_ASSERT( prevLedger->header().hash == closingInfo.parentHash, - "ripple::NetworkOPsImp::beginConsensus : prevLedger hash matches " + "xrpl::NetworkOPsImp::beginConsensus : prevLedger hash matches " "parent"); XRPL_ASSERT( closingInfo.parentHash == m_ledgerMaster.getClosedLedger()->header().hash, - "ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches " + "xrpl::NetworkOPsImp::beginConsensus : closedLedger parent matches " "hash"); app_.validators().setNegativeUNL(prevLedger->negativeUNL()); @@ -2327,7 +2327,7 @@ NetworkOPsImp::pubServer() f.em->openLedgerFeeLevel, f.loadBaseServer, f.em->referenceFeeLevel) - .value_or(ripple::muldiv_max)); + .value_or(xrpl::muldiv_max)); jvObj[jss::load_factor] = trunc32(loadFactor); jvObj[jss::load_factor_fee_escalation] = @@ -2843,7 +2843,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) escalationMetrics.openLedgerFeeLevel, loadBaseServer, escalationMetrics.referenceFeeLevel) - .value_or(ripple::muldiv_max); + .value_or(xrpl::muldiv_max); auto const loadFactor = std::max( safe_cast(loadFactorServer), loadFactorFeeEscalation); @@ -3097,7 +3097,7 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) XRPL_ASSERT( alpAccepted->getLedger().get() == lpAccepted.get(), - "ripple::NetworkOPsImp::pubLedger : accepted input"); + "xrpl::NetworkOPsImp::pubLedger : accepted input"); { JLOG(m_journal.debug()) @@ -3149,7 +3149,7 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) if (!mStreamMaps[sBookChanges].empty()) { - Json::Value jvObj = ripple::RPC::computeBookChanges(lpAccepted); + Json::Value jvObj = xrpl::RPC::computeBookChanges(lpAccepted); auto it = mStreamMaps[sBookChanges].begin(); while (it != mStreamMaps[sBookChanges].end()) @@ -3519,7 +3519,7 @@ NetworkOPsImp::pubAccountTransaction( XRPL_ASSERT( jvObj.isMember(jss::account_history_tx_stream) == MultiApiJson::none, - "ripple::NetworkOPsImp::pubAccountTransaction : " + "xrpl::NetworkOPsImp::pubAccountTransaction : " "account_history_tx_stream not set"); for (auto& info : accountHistoryNotify) { @@ -3596,7 +3596,7 @@ NetworkOPsImp::pubProposedAccountTransaction( XRPL_ASSERT( jvObj.isMember(jss::account_history_tx_stream) == MultiApiJson::none, - "ripple::NetworkOPs::pubProposedAccountTransaction : " + "xrpl::NetworkOPs::pubProposedAccountTransaction : " "account_history_tx_stream not set"); for (auto& info : accountHistoryNotify) { @@ -3713,8 +3713,7 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) if (databaseType == DatabaseType::None) { // LCOV_EXCL_START - UNREACHABLE( - "ripple::NetworkOPsImp::addAccountHistoryJob : no database"); + UNREACHABLE("xrpl::NetworkOPsImp::addAccountHistoryJob : no database"); JLOG(m_journal.error()) << "AccountHistory job for account " << toBase58(subInfo.index_->accountId_) << " no database"; @@ -3824,7 +3823,7 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) // LCOV_EXCL_START default: { UNREACHABLE( - "ripple::NetworkOPsImp::addAccountHistoryJob : " + "xrpl::NetworkOPsImp::addAccountHistoryJob : " "getMoreTxns : invalid database type"); return {}; } @@ -3891,7 +3890,7 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) { // LCOV_EXCL_START UNREACHABLE( - "ripple::NetworkOPsImp::addAccountHistoryJob : " + "xrpl::NetworkOPsImp::addAccountHistoryJob : " "getMoreTxns failed"); JLOG(m_journal.debug()) << "AccountHistory job for account " @@ -3923,7 +3922,7 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) { // LCOV_EXCL_START UNREACHABLE( - "ripple::NetworkOPsImp::addAccountHistoryJob : " + "xrpl::NetworkOPsImp::addAccountHistoryJob : " "getLedgerBySeq failed"); JLOG(m_journal.debug()) << "AccountHistory job for account " @@ -4039,7 +4038,7 @@ NetworkOPsImp::subAccountHistoryStart( { // LCOV_EXCL_START UNREACHABLE( - "ripple::NetworkOPsImp::subAccountHistoryStart : failed to " + "xrpl::NetworkOPsImp::subAccountHistoryStart : failed to " "access genesis account"); return; // LCOV_EXCL_STOP @@ -4151,7 +4150,7 @@ NetworkOPsImp::subBook(InfoSub::ref isrListener, Book const& book) else { // LCOV_EXCL_START - UNREACHABLE("ripple::NetworkOPsImp::subBook : null book listeners"); + UNREACHABLE("xrpl::NetworkOPsImp::subBook : null book listeners"); // LCOV_EXCL_STOP } return true; @@ -4173,7 +4172,7 @@ NetworkOPsImp::acceptLedger( // This code-path is exclusively used when the server is in standalone // mode via `ledger_accept` XRPL_ASSERT( - m_standalone, "ripple::NetworkOPsImp::acceptLedger : is standalone"); + m_standalone, "xrpl::NetworkOPsImp::acceptLedger : is standalone"); if (!m_standalone) Throw( @@ -4894,4 +4893,4 @@ make_NetworkOPs( collector); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/NetworkOPs.h b/src/xrpld/app/misc/NetworkOPs.h index 15545153c7..800f473959 100644 --- a/src/xrpld/app/misc/NetworkOPs.h +++ b/src/xrpld/app/misc/NetworkOPs.h @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { // Operations that clients may wish to perform against the network // Master operational handler, server sequencer, network tracker @@ -275,6 +275,6 @@ make_NetworkOPs( beast::Journal journal, beast::insight::Collector::ptr const& collector); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/PermissionedDEXHelpers.cpp b/src/xrpld/app/misc/PermissionedDEXHelpers.cpp index bc90848428..0cf41ac6f0 100644 --- a/src/xrpld/app/misc/PermissionedDEXHelpers.cpp +++ b/src/xrpld/app/misc/PermissionedDEXHelpers.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace permissioned_dex { bool @@ -67,4 +67,4 @@ offerInDomain( } // namespace permissioned_dex -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/PermissionedDEXHelpers.h b/src/xrpld/app/misc/PermissionedDEXHelpers.h index 87c8e64bcd..9b6d23d09d 100644 --- a/src/xrpld/app/misc/PermissionedDEXHelpers.h +++ b/src/xrpld/app/misc/PermissionedDEXHelpers.h @@ -1,7 +1,7 @@ #pragma once #include -namespace ripple { +namespace xrpl { namespace permissioned_dex { // Check if an account is in a permissioned domain @@ -21,4 +21,4 @@ offerInDomain( } // namespace permissioned_dex -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/SHAMapStore.h b/src/xrpld/app/misc/SHAMapStore.h index a906966b37..26d6120f32 100644 --- a/src/xrpld/app/misc/SHAMapStore.h +++ b/src/xrpld/app/misc/SHAMapStore.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { class TransactionMaster; @@ -88,6 +88,6 @@ make_SHAMapStore( Application& app, NodeStore::Scheduler& scheduler, beast::Journal journal); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/SHAMapStoreImp.cpp b/src/xrpld/app/misc/SHAMapStoreImp.cpp index 79c75ca0cf..0e33a0bc10 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.cpp +++ b/src/xrpld/app/misc/SHAMapStoreImp.cpp @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { void SHAMapStoreImp::SavedStateDB::init( BasicConfig const& config, @@ -27,7 +27,7 @@ SHAMapStoreImp::SavedStateDB::getCanDelete() { std::lock_guard lock(mutex_); - return ripple::getCanDelete(sqlDb_); + return xrpl::getCanDelete(sqlDb_); } LedgerIndex @@ -35,7 +35,7 @@ SHAMapStoreImp::SavedStateDB::setCanDelete(LedgerIndex canDelete) { std::lock_guard lock(mutex_); - return ripple::setCanDelete(sqlDb_, canDelete); + return xrpl::setCanDelete(sqlDb_, canDelete); } SavedState @@ -43,21 +43,21 @@ SHAMapStoreImp::SavedStateDB::getState() { std::lock_guard lock(mutex_); - return ripple::getSavedState(sqlDb_); + return xrpl::getSavedState(sqlDb_); } void SHAMapStoreImp::SavedStateDB::setState(SavedState const& state) { std::lock_guard lock(mutex_); - ripple::setSavedState(sqlDb_, state); + xrpl::setSavedState(sqlDb_, state); } void SHAMapStoreImp::SavedStateDB::setLastRotated(LedgerIndex seq) { std::lock_guard lock(mutex_); - ripple::setLastRotated(sqlDb_, seq); + xrpl::setLastRotated(sqlDb_, seq); } //------------------------------------------------------------------------------ @@ -496,7 +496,7 @@ SHAMapStoreImp::clearSql( { XRPL_ASSERT( deleteInterval_, - "ripple::SHAMapStoreImp::clearSql : nonzero delete interval"); + "xrpl::SHAMapStoreImp::clearSql : nonzero delete interval"); LedgerIndex min = std::numeric_limits::max(); { @@ -669,4 +669,4 @@ make_SHAMapStore( return std::make_unique(app, scheduler, journal); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/SHAMapStoreImp.h b/src/xrpld/app/misc/SHAMapStoreImp.h index 12079b9fec..e5a7435b0a 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.h +++ b/src/xrpld/app/misc/SHAMapStoreImp.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { class NetworkOPs; @@ -225,6 +225,6 @@ public: stop() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/Transaction.h b/src/xrpld/app/misc/Transaction.h index 4f59377fe0..ac801a2cd0 100644 --- a/src/xrpld/app/misc/Transaction.h +++ b/src/xrpld/app/misc/Transaction.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { // // Transactions should be constructed in JSON with. Use STObject::parseJson to @@ -413,6 +413,6 @@ private: beast::Journal j_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/TxQ.h b/src/xrpld/app/misc/TxQ.h index 4c4bb3c923..aff7fc89db 100644 --- a/src/xrpld/app/misc/TxQ.h +++ b/src/xrpld/app/misc/TxQ.h @@ -15,7 +15,7 @@ #include -namespace ripple { +namespace xrpl { class Application; class Config; @@ -854,6 +854,6 @@ toFeeLevel(XRPAmount const& drops, XRPAmount const& baseFee) .value_or(FeeLevel64(std::numeric_limits::max())); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/ValidatorKeys.h b/src/xrpld/app/misc/ValidatorKeys.h index 8c5060b488..a1511c134a 100644 --- a/src/xrpld/app/misc/ValidatorKeys.h +++ b/src/xrpld/app/misc/ValidatorKeys.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class Config; @@ -59,6 +59,6 @@ private: bool configInvalid_ = false; //< Set to true if config was invalid }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/ValidatorList.h b/src/xrpld/app/misc/ValidatorList.h index 77793619ac..d6758f8877 100644 --- a/src/xrpld/app/misc/ValidatorList.h +++ b/src/xrpld/app/misc/ValidatorList.h @@ -21,7 +21,7 @@ class TMValidatorList; class TMValidatorListCollection; } // namespace protocol -namespace ripple { +namespace xrpl { class Overlay; class HashRouter; @@ -927,7 +927,7 @@ hash_append(Hasher& h, std::map const& blobs) } } -} // namespace ripple +} // namespace xrpl namespace protocol { @@ -945,10 +945,7 @@ hash_append(Hasher& h, TMValidatorListCollection const& msg) { using beast::hash_append; hash_append( - h, - msg.manifest(), - ripple::ValidatorList::parseBlobs(msg), - msg.version()); + h, msg.manifest(), xrpl::ValidatorList::parseBlobs(msg), msg.version()); } } // namespace protocol diff --git a/src/xrpld/app/misc/ValidatorSite.h b/src/xrpld/app/misc/ValidatorSite.h index 9f20bef07a..64b22f065d 100644 --- a/src/xrpld/app/misc/ValidatorSite.h +++ b/src/xrpld/app/misc/ValidatorSite.h @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Validator Sites @@ -242,6 +242,6 @@ private: missingSite(std::lock_guard const&); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/detail/AMMHelpers.cpp b/src/xrpld/app/misc/detail/AMMHelpers.cpp index 2d5adc8f44..0b741c8d36 100644 --- a/src/xrpld/app/misc/detail/AMMHelpers.cpp +++ b/src/xrpld/app/misc/detail/AMMHelpers.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { STAmount ammLPTokens( @@ -236,7 +236,7 @@ adjustAmountsByLPTokens( XRPL_ASSERT( lpTokensActual == lpTokens, - "ripple::adjustAmountsByLPTokens : LP tokens match actual"); + "xrpl::adjustAmountsByLPTokens : LP tokens match actual"); return {amount, amount2, lpTokensActual}; } @@ -390,4 +390,4 @@ adjustFracByTokens( return tokens / lptAMMBalance; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/AMMUtils.cpp b/src/xrpld/app/misc/detail/AMMUtils.cpp index ab0aec41b1..c0cda2bd73 100644 --- a/src/xrpld/app/misc/detail/AMMUtils.cpp +++ b/src/xrpld/app/misc/detail/AMMUtils.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { std::pair ammPoolHolds( @@ -163,7 +163,7 @@ getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account) XRPL_ASSERT( !view.rules().enabled(fixInnerObjTemplate) || ammSle.isFieldPresent(sfAuctionSlot), - "ripple::getTradingFee : auction present"); + "xrpl::getTradingFee : auction present"); if (ammSle.isFieldPresent(sfAuctionSlot)) { auto const& auctionSlot = @@ -475,4 +475,4 @@ verifyAndAdjustLPTokenBalance( return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/AccountTxPaging.cpp b/src/xrpld/app/misc/detail/AccountTxPaging.cpp index d58dace34c..e3fc2de4f8 100644 --- a/src/xrpld/app/misc/detail/AccountTxPaging.cpp +++ b/src/xrpld/app/misc/detail/AccountTxPaging.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { void convertBlobsToTxResult( @@ -44,4 +44,4 @@ saveLedgerAsync(Application& app, std::uint32_t seq) pendSaveValidated(app, l, false, false); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/AccountTxPaging.h b/src/xrpld/app/misc/detail/AccountTxPaging.h index b822d7186c..cbfe8c89bb 100644 --- a/src/xrpld/app/misc/detail/AccountTxPaging.h +++ b/src/xrpld/app/misc/detail/AccountTxPaging.h @@ -7,7 +7,7 @@ //------------------------------------------------------------------------------ -namespace ripple { +namespace xrpl { void convertBlobsToTxResult( @@ -21,6 +21,6 @@ convertBlobsToTxResult( void saveLedgerAsync(Application& app, std::uint32_t seq); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/detail/AmendmentTable.cpp b/src/xrpld/app/misc/detail/AmendmentTable.cpp index b857f82213..8ed9bc12c5 100644 --- a/src/xrpld/app/misc/detail/AmendmentTable.cpp +++ b/src/xrpld/app/misc/detail/AmendmentTable.cpp @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { static std::vector> parseSection(Section const& section) @@ -211,7 +211,7 @@ public: { XRPL_ASSERT( votes.second.upVotes.empty(), - "ripple::TrustedVotes::recordVotes : received no " + "xrpl::TrustedVotes::recordVotes : received no " "upvotes"); JLOG(j.debug()) << "recordVotes: Have not received any " @@ -230,7 +230,7 @@ public: { XRPL_ASSERT( votes.second.timeout < newTimeout, - "ripple::TrustedVotes::recordVotes : votes not " + "xrpl::TrustedVotes::recordVotes : votes not " "expired"); using namespace std::chrono; auto const age = duration_cast( @@ -254,7 +254,7 @@ public: XRPL_ASSERT( validatorVotes.second.timeout || validatorVotes.second.upVotes.empty(), - "ripple::TrustedVotes::getVotes : valid votes"); + "xrpl::TrustedVotes::getVotes : valid votes"); if (validatorVotes.second.timeout) ++available; for (uint256 const& amendment : validatorVotes.second.upVotes) @@ -688,7 +688,7 @@ AmendmentTableImpl::persistVote( { XRPL_ASSERT( vote != AmendmentVote::obsolete, - "ripple::AmendmentTableImpl::persistVote : valid vote input"); + "xrpl::AmendmentTableImpl::persistVote : valid vote input"); auto db = db_.checkoutDb(); voteAmendment(*db, amendment, name, vote); } @@ -1042,4 +1042,4 @@ make_AmendmentTable( app, majorityTime, supported, enabled, vetoed, journal); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/DelegateUtils.cpp b/src/xrpld/app/misc/detail/DelegateUtils.cpp index 04728005af..027f2f1cc6 100644 --- a/src/xrpld/app/misc/detail/DelegateUtils.cpp +++ b/src/xrpld/app/misc/detail/DelegateUtils.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { NotTEC checkTxPermission(std::shared_ptr const& delegate, STTx const& tx) { @@ -44,4 +44,4 @@ loadGranularPermission( } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/DeliverMax.cpp b/src/xrpld/app/misc/detail/DeliverMax.cpp index 3d0ef901ec..44500eec7e 100644 --- a/src/xrpld/app/misc/detail/DeliverMax.cpp +++ b/src/xrpld/app/misc/detail/DeliverMax.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { void @@ -20,4 +20,4 @@ insertDeliverMax(Json::Value& tx_json, TxType txnType, unsigned int apiVersion) } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/LendingHelpers.cpp b/src/xrpld/app/misc/detail/LendingHelpers.cpp index 8020b47ba9..51e0988bc4 100644 --- a/src/xrpld/app/misc/detail/LendingHelpers.cpp +++ b/src/xrpld/app/misc/detail/LendingHelpers.cpp @@ -2,7 +2,7 @@ // DO NOT REMOVE forces header file include to sort first #include -namespace ripple { +namespace xrpl { bool checkLendingProtocolDependencies(PreflightContext const& ctx) @@ -17,15 +17,15 @@ LoanPaymentParts::operator+=(LoanPaymentParts const& other) XRPL_ASSERT( other.principalPaid >= beast::zero, - "ripple::LoanPaymentParts::operator+= : other principal " + "xrpl::LoanPaymentParts::operator+= : other principal " "non-negative"); XRPL_ASSERT( other.interestPaid >= beast::zero, - "ripple::LoanPaymentParts::operator+= : other interest paid " + "xrpl::LoanPaymentParts::operator+= : other interest paid " "non-negative"); XRPL_ASSERT( other.feePaid >= beast::zero, - "ripple::LoanPaymentParts::operator+= : other fee paid " + "xrpl::LoanPaymentParts::operator+= : other fee paid " "non-negative"); principalPaid += other.principalPaid; @@ -288,23 +288,21 @@ doPayment( std::uint32_t paymentInterval) { XRPL_ASSERT_PARTS( - nextDueDateProxy, - "ripple::detail::doPayment", - "Next due date proxy set"); + nextDueDateProxy, "xrpl::detail::doPayment", "Next due date proxy set"); if (payment.specialCase == PaymentSpecialCase::final) { XRPL_ASSERT_PARTS( principalOutstandingProxy == payment.trackedPrincipalDelta, - "ripple::detail::doPayment", + "xrpl::detail::doPayment", "Full principal payment"); XRPL_ASSERT_PARTS( totalValueOutstandingProxy == payment.trackedValueDelta, - "ripple::detail::doPayment", + "xrpl::detail::doPayment", "Full value payment"); XRPL_ASSERT_PARTS( managementFeeOutstandingProxy == payment.trackedManagementFeeDelta, - "ripple::detail::doPayment", + "xrpl::detail::doPayment", "Full management fee payment"); // Mark the loan as complete @@ -336,17 +334,17 @@ doPayment( } XRPL_ASSERT_PARTS( principalOutstandingProxy > payment.trackedPrincipalDelta, - "ripple::detail::doPayment", + "xrpl::detail::doPayment", "Partial principal payment"); XRPL_ASSERT_PARTS( totalValueOutstandingProxy > payment.trackedValueDelta, - "ripple::detail::doPayment", + "xrpl::detail::doPayment", "Partial value payment"); // Management fees are expected to be relatively small, and could get to // zero before the loan is paid off XRPL_ASSERT_PARTS( managementFeeOutstandingProxy >= payment.trackedManagementFeeDelta, - "ripple::detail::doPayment", + "xrpl::detail::doPayment", "Valid management fee"); // Apply the payment deltas to reduce the outstanding balances @@ -361,14 +359,14 @@ doPayment( // ValueProxy or Number static_cast(principalOutstandingProxy) <= static_cast(totalValueOutstandingProxy), - "ripple::detail::doPayment", + "xrpl::detail::doPayment", "principal does not exceed total"); XRPL_ASSERT_PARTS( // Use an explicit cast because the template parameter can be // ValueProxy or Number static_cast(managementFeeOutstandingProxy) >= beast::zero, - "ripple::detail::doPayment", + "xrpl::detail::doPayment", "fee outstanding stays valid"); return LoanPaymentParts{ @@ -673,13 +671,13 @@ doOverpayment( XRPL_ASSERT_PARTS( overpaymentComponents.trackedPrincipalDelta == principalOutstandingProxy - principalOutstanding, - "ripple::detail::doOverpayment", + "xrpl::detail::doOverpayment", "principal change agrees"); XRPL_ASSERT_PARTS( overpaymentComponents.trackedManagementFeeDelta == managementFeeOutstandingProxy - managementFeeOutstanding, - "ripple::detail::doOverpayment", + "xrpl::detail::doOverpayment", "no fee change"); // I'm not 100% sure the following asserts are correct. If in doubt, and @@ -703,20 +701,20 @@ doOverpayment( (totalValueOutstandingProxy - overpaymentComponents.trackedPrincipalDelta) + overpaymentComponents.trackedInterestPart(), - "ripple::detail::doOverpayment", + "xrpl::detail::doOverpayment", "interest paid agrees"); XRPL_ASSERT_PARTS( overpaymentComponents.trackedPrincipalDelta == loanPaymentParts.principalPaid, - "ripple::detail::doOverpayment", + "xrpl::detail::doOverpayment", "principal payment matches"); XRPL_ASSERT_PARTS( loanPaymentParts.feePaid == overpaymentComponents.untrackedManagementFee + overpaymentComponents.trackedManagementFeeDelta, - "ripple::detail::doOverpayment", + "xrpl::detail::doOverpayment", "fee payment matches"); // All validations passed, so update the proxy objects (which will @@ -780,10 +778,10 @@ computeLatePayment( XRPL_ASSERT( roundedLateInterest >= 0, - "ripple::detail::computeLatePayment : valid late interest"); + "xrpl::detail::computeLatePayment : valid late interest"); XRPL_ASSERT_PARTS( periodic.specialCase != PaymentSpecialCase::extra, - "ripple::detail::computeLatePayment", + "xrpl::detail::computeLatePayment", "no extra parts to this payment"); // Create the late payment components by copying the regular periodic @@ -813,7 +811,7 @@ computeLatePayment( XRPL_ASSERT_PARTS( isRounded(asset, late.totalDue, loanScale), - "ripple::detail::computeLatePayment", + "xrpl::detail::computeLatePayment", "total due is rounded"); // Check that the borrower provided enough funds to cover the late payment. @@ -939,7 +937,7 @@ computeFullPayment( XRPL_ASSERT_PARTS( isRounded(asset, full.totalDue, loanScale), - "ripple::detail::computeFullPayment", + "xrpl::detail::computeFullPayment", "total due is rounded"); JLOG(j.trace()) << "computeFullPayment result: periodicPayment: " @@ -999,11 +997,11 @@ computePaymentComponents( isRounded(asset, totalValueOutstanding, scale) && isRounded(asset, principalOutstanding, scale) && isRounded(asset, managementFeeOutstanding, scale), - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "Outstanding values are rounded"); XRPL_ASSERT_PARTS( paymentRemaining > 0, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "some payments remaining"); auto const roundedPeriodicPayment = @@ -1054,7 +1052,7 @@ computePaymentComponents( XRPL_ASSERT_PARTS( deltas.principal <= currentLedgerState.principalOutstanding, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "principal delta not greater than outstanding"); // Cap each component to never exceed what's actually outstanding @@ -1063,7 +1061,7 @@ computePaymentComponents( XRPL_ASSERT_PARTS( deltas.interest <= currentLedgerState.interestDue, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "interest due delta not greater than outstanding"); // Cap interest to both the outstanding amount AND what's left of the @@ -1075,7 +1073,7 @@ computePaymentComponents( XRPL_ASSERT_PARTS( deltas.managementFee <= currentLedgerState.managementFeeDue, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "management fee due delta not greater than outstanding"); // Cap management fee to both the outstanding amount AND what's left of the @@ -1098,7 +1096,7 @@ computePaymentComponents( } XRPL_ASSERT_PARTS( excess >= beast::zero, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "excess non-negative"); }; // Helper to reduce deltas when they collectively exceed a limit. @@ -1120,7 +1118,7 @@ computePaymentComponents( { // LCOV_EXCL_START UNREACHABLE( - "ripple::detail::computePaymentComponents : payment exceeded loan " + "xrpl::detail::computePaymentComponents : payment exceeded loan " "state"); addressExcess(deltas, totalOverpayment); // LCOV_EXCL_STOP @@ -1131,7 +1129,7 @@ computePaymentComponents( XRPL_ASSERT_PARTS( isRounded(asset, shortage, scale), - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "shortage is rounded"); if (shortage < beast::zero) @@ -1147,35 +1145,35 @@ computePaymentComponents( // shortage < 0 would mean we're trying to pay more than allowed (bug). XRPL_ASSERT_PARTS( shortage >= beast::zero, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "no shortage or excess"); // Final validation that all components are valid XRPL_ASSERT_PARTS( deltas.total() == deltas.principal + deltas.interest + deltas.managementFee, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "total value adds up"); XRPL_ASSERT_PARTS( deltas.principal >= beast::zero && deltas.principal <= currentLedgerState.principalOutstanding, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "valid principal result"); XRPL_ASSERT_PARTS( deltas.interest >= beast::zero && deltas.interest <= currentLedgerState.interestDue, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "valid interest result"); XRPL_ASSERT_PARTS( deltas.managementFee >= beast::zero && deltas.managementFee <= currentLedgerState.managementFeeDue, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "valid fee result"); XRPL_ASSERT_PARTS( deltas.principal + deltas.interest + deltas.managementFee > beast::zero, - "ripple::detail::computePaymentComponents", + "xrpl::detail::computePaymentComponents", "payment parts add to payment"); // Final safety clamp to ensure no value exceeds its outstanding balance @@ -1218,7 +1216,7 @@ computeOverpaymentComponents( { XRPL_ASSERT( overpayment > 0 && isRounded(asset, overpayment, loanScale), - "ripple::detail::computeOverpaymentComponents : valid overpayment " + "xrpl::detail::computeOverpaymentComponents : valid overpayment " "amount"); // First, deduct the fixed overpayment fee from the total amount. @@ -1267,7 +1265,7 @@ computeOverpaymentComponents( roundedOverpaymentInterest}; XRPL_ASSERT_PARTS( result.trackedInterestPart() == roundedOverpaymentInterest, - "ripple::detail::computeOverpaymentComponents", + "xrpl::detail::computeOverpaymentComponents", "valid interest computation"); return result; } @@ -1418,7 +1416,7 @@ computeFullPaymentInterest( paymentInterval); XRPL_ASSERT( accruedInterest >= 0, - "ripple::detail::computeFullPaymentInterest : valid accrued " + "xrpl::detail::computeFullPaymentInterest : valid accrued " "interest"); // Equation (28) from XLS-66 spec, Section A-2 Equation Glossary @@ -1428,7 +1426,7 @@ computeFullPaymentInterest( XRPL_ASSERT( prepaymentPenalty >= 0, - "ripple::detail::computeFullPaymentInterest : valid prepayment " + "xrpl::detail::computeFullPaymentInterest : valid prepayment " "interest"); // Part of equation (27) from XLS-66 spec, Section A-2 Equation Glossary @@ -1616,7 +1614,7 @@ computeLoanProperties( auto const periodicRate = loanPeriodicRate(interestRate, paymentInterval); XRPL_ASSERT( interestRate == 0 || periodicRate > 0, - "ripple::computeLoanProperties : valid rate"); + "xrpl::computeLoanProperties : valid rate"); auto const periodicPayment = detail::loanPeriodicPayment( principalOutstanding, periodicRate, paymentsRemaining); @@ -1638,7 +1636,7 @@ computeLoanProperties( (amount.integral() && loanScale == 0) || (!amount.integral() && loanScale >= static_cast(amount).exponent()), - "ripple::computeLoanProperties", + "xrpl::computeLoanProperties", "loanScale value fits expectations"); // We may need to truncate the total value because of the minimum @@ -1752,11 +1750,11 @@ loanMakePayment( Number const periodicRate = loanPeriodicRate(interestRate, paymentInterval); XRPL_ASSERT( interestRate == 0 || periodicRate > 0, - "ripple::loanMakePayment : valid rate"); + "xrpl::loanMakePayment : valid rate"); XRPL_ASSERT( *totalValueOutstandingProxy > 0, - "ripple::loanMakePayment : valid total value"); + "xrpl::loanMakePayment : valid total value"); view.update(loan); @@ -1826,7 +1824,7 @@ loanMakePayment( return Unexpected(fullPaymentComponents.error()); // LCOV_EXCL_START - UNREACHABLE("ripple::loanMakePayment : invalid full payment result"); + UNREACHABLE("xrpl::loanMakePayment : invalid full payment result"); JLOG(j.error()) << "Full payment computation failed unexpectedly."; return Unexpected(tecINTERNAL); // LCOV_EXCL_STOP @@ -1849,7 +1847,7 @@ loanMakePayment( serviceFee}; XRPL_ASSERT_PARTS( periodic.trackedPrincipalDelta >= 0, - "ripple::loanMakePayment", + "xrpl::loanMakePayment", "regular payment valid principal"); // ------------------------------------------------------------- @@ -1890,7 +1888,7 @@ loanMakePayment( } // LCOV_EXCL_START - UNREACHABLE("ripple::loanMakePayment : invalid late payment result"); + UNREACHABLE("xrpl::loanMakePayment : invalid late payment result"); JLOG(j.error()) << "Late payment computation failed unexpectedly."; return Unexpected(tecINTERNAL); // LCOV_EXCL_STOP @@ -1902,7 +1900,7 @@ loanMakePayment( XRPL_ASSERT_PARTS( paymentType == LoanPaymentType::regular || paymentType == LoanPaymentType::overpayment, - "ripple::loanMakePayment", + "xrpl::loanMakePayment", "regular payment type"); // Keep a running total of the actual parts paid @@ -1917,7 +1915,7 @@ loanMakePayment( // Try to make more payments XRPL_ASSERT_PARTS( periodic.trackedPrincipalDelta >= 0, - "ripple::loanMakePayment", + "xrpl::loanMakePayment", "payment pays non-negative principal"); totalPaid += periodic.totalDue; @@ -1935,7 +1933,7 @@ loanMakePayment( XRPL_ASSERT_PARTS( (periodic.specialCase == detail::PaymentSpecialCase::final) == (paymentRemainingProxy == 0), - "ripple::loanMakePayment", + "xrpl::loanMakePayment", "final payment is the final payment"); // Don't compute the next payment if this was the last payment @@ -1967,11 +1965,11 @@ loanMakePayment( totalParts.principalPaid + totalParts.interestPaid + totalParts.feePaid == totalPaid, - "ripple::loanMakePayment", + "xrpl::loanMakePayment", "payment parts add up"); XRPL_ASSERT_PARTS( totalParts.valueChange == 0, - "ripple::loanMakePayment", + "xrpl::loanMakePayment", "no value change"); // ------------------------------------------------------------- @@ -2005,7 +2003,7 @@ loanMakePayment( { XRPL_ASSERT_PARTS( overpaymentComponents.untrackedInterest >= beast::zero, - "ripple::loanMakePayment", + "xrpl::loanMakePayment", "overpayment penalty did not reduce value of loan"); // Can't just use `periodicPayment` here, because it might // change @@ -2041,18 +2039,18 @@ loanMakePayment( XRPL_ASSERT( isRounded(asset, totalParts.principalPaid, loanScale) && totalParts.principalPaid >= beast::zero, - "ripple::loanMakePayment : total principal paid is valid"); + "xrpl::loanMakePayment : total principal paid is valid"); XRPL_ASSERT( isRounded(asset, totalParts.interestPaid, loanScale) && totalParts.interestPaid >= beast::zero, - "ripple::loanMakePayment : total interest paid is valid"); + "xrpl::loanMakePayment : total interest paid is valid"); XRPL_ASSERT( isRounded(asset, totalParts.valueChange, loanScale), - "ripple::loanMakePayment : loan value change is valid"); + "xrpl::loanMakePayment : loan value change is valid"); XRPL_ASSERT( isRounded(asset, totalParts.feePaid, loanScale) && totalParts.feePaid >= beast::zero, - "ripple::loanMakePayment : fee paid is valid"); + "xrpl::loanMakePayment : fee paid is valid"); return totalParts; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/LoadFeeTrack.cpp b/src/xrpld/app/misc/detail/LoadFeeTrack.cpp index 9434ed5d02..6166656aee 100644 --- a/src/xrpld/app/misc/detail/LoadFeeTrack.cpp +++ b/src/xrpld/app/misc/detail/LoadFeeTrack.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { bool LoadFeeTrack::raiseLocalFee() @@ -90,4 +90,4 @@ scaleFeeLoad( return *result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/Manifest.cpp b/src/xrpld/app/misc/detail/Manifest.cpp index 68d91599db..59a1325e32 100644 --- a/src/xrpld/app/misc/detail/Manifest.cpp +++ b/src/xrpld/app/misc/detail/Manifest.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { std::string to_string(Manifest const& m) @@ -187,11 +187,10 @@ Manifest::verify() const // Signing key and signature are not required for // master key revocations - if (!revoked() && !ripple::verify(st, HashPrefix::manifest, *signingKey)) + if (!revoked() && !xrpl::verify(st, HashPrefix::manifest, *signingKey)) return false; - return ripple::verify( - st, HashPrefix::manifest, masterKey, sfMasterSignature); + return xrpl::verify(st, HashPrefix::manifest, masterKey, sfMasterSignature); } uint256 @@ -374,7 +373,7 @@ ManifestCache::applyManifest(Manifest m) -> std::optional { XRPL_ASSERT( lock.owns_lock(), - "ripple::ManifestCache::applyManifest::prewriteCheck : locked"); + "xrpl::ManifestCache::applyManifest::prewriteCheck : locked"); (void)lock; // not used. parameter is present to ensure the mutex is // locked when the lambda is called. if (iter != map_.end() && m.sequence <= iter->second.sequence) @@ -525,7 +524,7 @@ void ManifestCache::load(DatabaseCon& dbCon, std::string const& dbTable) { auto db = dbCon.checkoutDb(); - ripple::getManifests(*db, dbTable, *this, j_); + xrpl::getManifests(*db, dbTable, *this, j_); } bool @@ -596,4 +595,4 @@ ManifestCache::save( saveManifests(*db, dbTable, isTrusted, map_, j_); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/Transaction.cpp b/src/xrpld/app/misc/detail/Transaction.cpp index 588bbc6fb7..77a8897d9c 100644 --- a/src/xrpld/app/misc/detail/Transaction.cpp +++ b/src/xrpld/app/misc/detail/Transaction.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { Transaction::Transaction( std::shared_ptr const& stx, @@ -71,7 +71,7 @@ Transaction::sqlTransactionStatus(boost::optional const& status) XRPL_ASSERT( c == txnSqlUnknown, - "ripple::Transaction::sqlTransactionStatus : unknown transaction " + "xrpl::Transaction::sqlTransactionStatus : unknown transaction " "status"); return INVALID; } @@ -183,4 +183,4 @@ Transaction::getJson(JsonOptions options, bool binary) const return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/TxQ.cpp b/src/xrpld/app/misc/detail/TxQ.cpp index 35ae25c82f..9f260e5f48 100644 --- a/src/xrpld/app/misc/detail/TxQ.cpp +++ b/src/xrpld/app/misc/detail/TxQ.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { ////////////////////////////////////////////////////////////////////////// @@ -34,7 +34,7 @@ getFeeLevelPaid(ReadView const& view, STTx const& tx) return std::pair{baseFee + mod, feePaid + mod}; }(); - XRPL_ASSERT(baseFee.signum() > 0, "ripple::getFeeLevelPaid : positive fee"); + XRPL_ASSERT(baseFee.signum() > 0, "xrpl::getFeeLevelPaid : positive fee"); if (effectiveFeePaid.signum() <= 0 || baseFee.signum() <= 0) { return FeeLevel64(0); @@ -56,7 +56,7 @@ static FeeLevel64 increase(FeeLevel64 level, std::uint32_t increasePercent) { return mulDiv(level, 100 + increasePercent, 100) - .value_or(static_cast(ripple::muldiv_max)); + .value_or(static_cast(xrpl::muldiv_max)); } ////////////////////////////////////////////////////////////////////////// @@ -79,7 +79,7 @@ TxQ::FeeMetrics::update( std::sort(feeLevels.begin(), feeLevels.end()); XRPL_ASSERT( size == feeLevels.size(), - "ripple::TxQ::FeeMetrics::update : fee levels size"); + "xrpl::TxQ::FeeMetrics::update : fee levels size"); JLOG((timeLeap ? j_.warn() : j_.debug())) << "Ledger " << view.header().seq << " has " << size @@ -96,10 +96,10 @@ TxQ::FeeMetrics::update( // upperLimit must be >= minimumTxnCount_ or std::clamp can give // unexpected results auto const upperLimit = std::max( - mulDiv(txnsExpected_, cutPct, 100).value_or(ripple::muldiv_max), + mulDiv(txnsExpected_, cutPct, 100).value_or(xrpl::muldiv_max), minimumTxnCount_); txnsExpected_ = std::clamp( - mulDiv(size, cutPct, 100).value_or(ripple::muldiv_max), + mulDiv(size, cutPct, 100).value_or(xrpl::muldiv_max), minimumTxnCount_, upperLimit); recentTxnCounts_.clear(); @@ -108,7 +108,7 @@ TxQ::FeeMetrics::update( { recentTxnCounts_.push_back( mulDiv(size, 100 + setup.normalConsensusIncreasePercent, 100) - .value_or(ripple::muldiv_max)); + .value_or(xrpl::muldiv_max)); auto const iter = std::max_element(recentTxnCounts_.begin(), recentTxnCounts_.end()); BOOST_ASSERT(iter != recentTxnCounts_.end()); @@ -167,7 +167,7 @@ TxQ::FeeMetrics::scaleFeeLevel(Snapshot const& snapshot, OpenView const& view) // Compute escalated fee level // Don't care about the overflow flag return mulDiv(multiplier, current * current, target * target) - .value_or(static_cast(ripple::muldiv_max)); + .value_or(static_cast(xrpl::muldiv_max)); } return baseLevel; @@ -234,7 +234,7 @@ TxQ::FeeMetrics::escalatedSeriesFeeLevel( XRPL_ASSERT( current > target, - "ripple::TxQ::FeeMetrics::escalatedSeriesFeeLevel : current over " + "xrpl::TxQ::FeeMetrics::escalatedSeriesFeeLevel : current over " "target"); /* Calculate (apologies for the terrible notation) @@ -281,7 +281,7 @@ TxQ::MaybeTx::apply(Application& app, OpenView& view, beast::Journal j) { // If the rules or flags change, preflight again XRPL_ASSERT( - pfresult, "ripple::TxQ::MaybeTx::apply : preflight result is set"); + pfresult, "xrpl::TxQ::MaybeTx::apply : preflight result is set"); NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)}; if (pfresult->rules != view.rules() || pfresult->flags != flags) @@ -326,10 +326,10 @@ TxQ::TxQAccount::add(MaybeTx&& txn) auto result = transactions.emplace(seqProx, std::move(txn)); XRPL_ASSERT( - result.second, "ripple::TxQ::TxQAccount::add : emplace succeeded"); + result.second, "xrpl::TxQ::TxQAccount::add : emplace succeeded"); XRPL_ASSERT( &result.first->second != &txn, - "ripple::TxQ::TxQAccount::add : transaction moved"); + "xrpl::TxQ::TxQAccount::add : transaction moved"); return result.first->second; } @@ -438,7 +438,7 @@ TxQ::erase(TxQ::FeeMultiSet::const_iterator_type candidateIter) // intrusive list remove it from the TxQAccount // so the memory can be freed. [[maybe_unused]] auto const found = txQAccount.remove(seqProx); - XRPL_ASSERT(found, "ripple::TxQ::erase : account removed"); + XRPL_ASSERT(found, "xrpl::TxQ::erase : account removed"); return newCandidateIter; } @@ -452,7 +452,7 @@ TxQ::eraseAndAdvance(TxQ::FeeMultiSet::const_iterator_type candidateIter) txQAccount.transactions.find(candidateIter->seqProxy); XRPL_ASSERT( accountIter != txQAccount.transactions.end(), - "ripple::TxQ::eraseAndAdvance : account found"); + "xrpl::TxQ::eraseAndAdvance : account found"); // Note that sequence-based transactions must be applied in sequence order // from smallest to largest. But ticket-based transactions can be @@ -460,10 +460,10 @@ TxQ::eraseAndAdvance(TxQ::FeeMultiSet::const_iterator_type candidateIter) XRPL_ASSERT( candidateIter->seqProxy.isTicket() || accountIter == txQAccount.transactions.begin(), - "ripple::TxQ::eraseAndAdvance : ticket or sequence"); + "xrpl::TxQ::eraseAndAdvance : ticket or sequence"); XRPL_ASSERT( byFee_.iterator_to(accountIter->second) == candidateIter, - "ripple::TxQ::eraseAndAdvance : found in byFee"); + "xrpl::TxQ::eraseAndAdvance : found in byFee"); auto const accountNextIter = std::next(accountIter); // Check if the next transaction for this account is earlier in the queue, @@ -512,7 +512,7 @@ TxQ::tryClearAccountQueueUpThruTx( SeqProxy const tSeqProx{tx.getSeqProxy()}; XRPL_ASSERT( beginTxIter != accountIter->second.transactions.end(), - "ripple::TxQ::tryClearAccountQueueUpThruTx : non-empty accounts input"); + "xrpl::TxQ::tryClearAccountQueueUpThruTx : non-empty accounts input"); // This check is only concerned with the range from // [aSeqProxy, tSeqProxy) @@ -994,8 +994,7 @@ TxQ::apply( // o The current first thing in the queue has a Ticket and // * The tx has a Ticket that precedes it or // * txSeqProx == acctSeqProx. - XRPL_ASSERT( - prevIter != txIter->end, "ripple::TxQ::apply : not end"); + XRPL_ASSERT(prevIter != txIter->end, "xrpl::TxQ::apply : not end"); if (prevIter == txIter->end || txSeqProx < prevIter->first) { // The first Sequence number in the queue must be the @@ -1120,7 +1119,7 @@ TxQ::apply( potentialTotalSpend > XRPAmount{0} || (potentialTotalSpend == XRPAmount{0} && multiTxn->applyView.fees().base == 0), - "ripple::TxQ::apply : total spend check"); + "xrpl::TxQ::apply : total spend check"); sleBump->setFieldAmount(sfBalance, balance - potentialTotalSpend); // The transaction's sequence/ticket will be valid when the other // transactions in the queue have been processed. If the tx has a @@ -1150,7 +1149,7 @@ TxQ::apply( return {pcresult.ter, false}; // Too low of a fee should get caught by preclaim - XRPL_ASSERT(feeLevelPaid >= baseLevel, "ripple::TxQ::apply : minimum fee"); + XRPL_ASSERT(feeLevelPaid >= baseLevel, "xrpl::TxQ::apply : minimum fee"); JLOG(j_.trace()) << "Transaction " << transactionID << " from account " << account << " has fee level of " << feeLevelPaid @@ -1277,7 +1276,7 @@ TxQ::apply( auto dropRIter = endAccount.transactions.rbegin(); XRPL_ASSERT( dropRIter->second.account == lastRIter->account, - "ripple::TxQ::apply : cheapest transaction found"); + "xrpl::TxQ::apply : cheapest transaction found"); JLOG(j_.info()) << "Removing last item of account " << lastRIter->account << " from queue with average fee of " << endEffectiveFeeLevel @@ -1306,7 +1305,7 @@ TxQ::apply( [[maybe_unused]] bool created = false; std::tie(accountIter, created) = byAccount_.emplace(account, TxQAccount(tx)); - XRPL_ASSERT(created, "ripple::TxQ::apply : account created"); + XRPL_ASSERT(created, "xrpl::TxQ::apply : account created"); } // Modify the flags for use when coming out of the queue. // These changes _may_ cause an extra `preflight`, but as long as @@ -1521,7 +1520,7 @@ TxQ::accept(Application& app, OpenView& view) auto dropRIter = account.transactions.rbegin(); XRPL_ASSERT( dropRIter->second.account == candidateIter->account, - "ripple::TxQ::accept : account check"); + "xrpl::TxQ::accept : account check"); JLOG(j_.info()) << "Queue is nearly full, and transaction " @@ -1576,8 +1575,7 @@ TxQ::accept(Application& app, OpenView& view) } } XRPL_ASSERT( - byFee_.size() == startingSize, - "ripple::TxQ::accept : byFee size match"); + byFee_.size() == startingSize, "xrpl::TxQ::accept : byFee size match"); return ledgerChanged; } @@ -1696,7 +1694,7 @@ TxQ::tryDirectApply( << " to open ledger."; auto const [txnResult, didApply, metadata] = - ripple::apply(app, view, *tx, flags, j); + xrpl::apply(app, view, *tx, flags, j); JLOG(j_.trace()) << "New transaction " << transactionID << (didApply ? " applied successfully with " @@ -1738,16 +1736,16 @@ TxQ::removeFromByFee( auto deleteIter = byFee_.iterator_to((*replacedTxIter)->second); XRPL_ASSERT( deleteIter != byFee_.end(), - "ripple::TxQ::removeFromByFee : found in byFee"); + "xrpl::TxQ::removeFromByFee : found in byFee"); XRPL_ASSERT( &(*replacedTxIter)->second == &*deleteIter, - "ripple::TxQ::removeFromByFee : matching transaction"); + "xrpl::TxQ::removeFromByFee : matching transaction"); XRPL_ASSERT( deleteIter->seqProxy == tx->getSeqProxy(), - "ripple::TxQ::removeFromByFee : matching sequence"); + "xrpl::TxQ::removeFromByFee : matching sequence"); XRPL_ASSERT( deleteIter->account == (*tx)[sfAccount], - "ripple::TxQ::removeFromByFee : matching account"); + "xrpl::TxQ::removeFromByFee : matching account"); erase(deleteIter); } @@ -1959,4 +1957,4 @@ setup_TxQ(Config const& config) return setup; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/ValidatorKeys.cpp b/src/xrpld/app/misc/detail/ValidatorKeys.cpp index 4b1e93a444..757a18aa47 100644 --- a/src/xrpld/app/misc/detail/ValidatorKeys.cpp +++ b/src/xrpld/app/misc/detail/ValidatorKeys.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { ValidatorKeys::ValidatorKeys(Config const& config, beast::Journal j) { if (config.exists(SECTION_VALIDATOR_TOKEN) && @@ -70,4 +70,4 @@ ValidatorKeys::ValidatorKeys(Config const& config, beast::Journal j) } } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/ValidatorList.cpp b/src/xrpld/app/misc/detail/ValidatorList.cpp index 566dfc06a0..db2ee980b8 100644 --- a/src/xrpld/app/misc/detail/ValidatorList.cpp +++ b/src/xrpld/app/misc/detail/ValidatorList.cpp @@ -20,7 +20,7 @@ #include #include -namespace ripple { +namespace xrpl { std::string to_string(ListDisposition disposition) @@ -181,7 +181,7 @@ ValidatorList::load( // This should be enforced by Config class XRPL_ASSERT( listThreshold_ > 0 && listThreshold_ <= publisherLists_.size(), - "ripple::ValidatorList::load : list threshold inside range"); + "xrpl::ValidatorList::load : list threshold inside range"); JLOG(j_.debug()) << "Validator list threshold set in configuration to " << listThreshold_; } @@ -293,7 +293,7 @@ ValidatorList::buildFileData( XRPL_ASSERT( pubCollection.rawVersion == 2 || pubCollection.remaining.empty(), - "ripple::ValidatorList::buildFileData : valid publisher list input"); + "xrpl::ValidatorList::buildFileData : valid publisher list input"); auto const effectiveVersion = forceVersion ? *forceVersion : pubCollection.rawVersion; @@ -395,7 +395,7 @@ ValidatorList::parseBlobs(std::uint32_t version, Json::Value const& body) info.signature = body[jss::signature].asString(); XRPL_ASSERT( result.size() == 1, - "ripple::ValidatorList::parseBlobs : single element result"); + "xrpl::ValidatorList::parseBlobs : single element result"); return result; } // Treat unknown versions as if they're the latest version. This @@ -432,7 +432,7 @@ ValidatorList::parseBlobs(std::uint32_t version, Json::Value const& body) } XRPL_ASSERT( result.size() == blobs.size(), - "ripple::ValidatorList::parseBlobs(version, Jason::Value) : " + "xrpl::ValidatorList::parseBlobs(version, Jason::Value) : " "result size matches"); return result; } @@ -466,7 +466,7 @@ ValidatorList::parseBlobs(protocol::TMValidatorListCollection const& body) } XRPL_ASSERT( result.size() == body.blobs_size(), - "ripple::ValidatorList::parseBlobs(TMValidatorList) : result size " + "xrpl::ValidatorList::parseBlobs(TMValidatorList) : result size " "match"); return result; } @@ -489,7 +489,7 @@ splitMessage( { if (begin == 0 && end == 0) end = largeMsg.blobs_size(); - XRPL_ASSERT(begin < end, "ripple::splitMessage : valid inputs"); + XRPL_ASSERT(begin < end, "xrpl::splitMessage : valid inputs"); if (end <= begin) return 0; @@ -525,7 +525,7 @@ splitMessageParts( XRPL_ASSERT( Message::totalSize(smallMsg) <= maximiumMessageSize, - "ripple::splitMessageParts : maximum message size"); + "xrpl::splitMessageParts : maximum message size"); messages.emplace_back( std::make_shared(smallMsg, protocol::mtVALIDATORLIST), @@ -575,7 +575,7 @@ buildValidatorListMessage( { XRPL_ASSERT( messages.empty(), - "ripple::buildValidatorListMessage(ValidatorBlobInfo) : empty messages " + "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : empty messages " "input"); protocol::TMValidatorList msg; auto const manifest = @@ -589,7 +589,7 @@ buildValidatorListMessage( XRPL_ASSERT( Message::totalSize(msg) <= maximiumMessageSize, - "ripple::buildValidatorListMessage(ValidatorBlobInfo) : maximum " + "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : maximum " "message size"); messages.emplace_back( std::make_shared(msg, protocol::mtVALIDATORLIST), @@ -611,7 +611,7 @@ buildValidatorListMessage( { XRPL_ASSERT( messages.empty(), - "ripple::buildValidatorListMessage(std::map) : empty messages input"); protocol::TMValidatorListCollection msg; auto const version = rawVersion < 2 ? 2 : rawVersion; @@ -630,7 +630,7 @@ buildValidatorListMessage( } XRPL_ASSERT( msg.blobs_size() > 0, - "ripple::buildValidatorListMessage(std::map) : minimum message blobs"); if (Message::totalSize(msg) > maxSize) { @@ -662,7 +662,7 @@ ValidatorList::buildValidatorListMessages( { XRPL_ASSERT( !blobInfos.empty(), - "ripple::ValidatorList::buildValidatorListMessages : empty messages " + "xrpl::ValidatorList::buildValidatorListMessages : empty messages " "input"); auto const& [currentSeq, currentBlob] = *blobInfos.begin(); auto numVLs = std::accumulate( @@ -748,7 +748,7 @@ ValidatorList::sendValidatorList( { XRPL_ASSERT( !messages.empty(), - "ripple::ValidatorList::sendValidatorList : non-empty messages " + "xrpl::ValidatorList::sendValidatorList : non-empty messages " "input"); // Don't send it next time. peer.setPublisherListSequence(publisherKey, newPeerSequence); @@ -767,7 +767,7 @@ ValidatorList::sendValidatorList( // thus there will only be one entry without a message XRPL_ASSERT( sent || messages.size() == 1, - "ripple::ValidatorList::sendValidatorList : sent or one message"); + "xrpl::ValidatorList::sendValidatorList : sent or one message"); if (sent) { if (messageVersion > 1) @@ -781,7 +781,7 @@ ValidatorList::sendValidatorList( { XRPL_ASSERT( numVLs == 1, - "ripple::ValidatorList::sendValidatorList : one validator " + "xrpl::ValidatorList::sendValidatorList : one validator " "list"); JLOG(j.debug()) << "Sent validator list for " << strHex(publisherKey) @@ -879,7 +879,7 @@ ValidatorList::broadcastBlobs( XRPL_ASSERT( lists.current.sequence == maxSequence || lists.remaining.count(maxSequence) == 1, - "ripple::ValidatorList::broadcastBlobs : valid sequence"); + "xrpl::ValidatorList::broadcastBlobs : valid sequence"); // Can't use overlay.foreach here because we need to modify // the peer, and foreach provides a const& for (auto& peer : overlay.getActivePeers()) @@ -1025,7 +1025,7 @@ ValidatorList::applyLists( auto next = std::next(iter); XRPL_ASSERT( next == remaining.end() || next->first > iter->first, - "ripple::ValidatorList::applyLists : next is valid"); + "xrpl::ValidatorList::applyLists : next is valid"); if (iter->first <= current.sequence || (next != remaining.end() && next->second.validFrom <= iter->second.validFrom)) @@ -1151,8 +1151,7 @@ ValidatorList::applyList( // we can only arrive here if the key used by the manifest matched one // of the loaded keys // LCOV_EXCL_START - UNREACHABLE( - "ripple::ValidatorList::applyList : invalid public key type"); + UNREACHABLE("xrpl::ValidatorList::applyList : invalid public key type"); return PublisherListStats{result}; // LCOV_EXCL_STOP } @@ -1213,7 +1212,7 @@ ValidatorList::applyList( // Done XRPL_ASSERT( publisher.sequence == sequence, - "ripple::ValidatorList::applyList : publisher sequence match"); + "xrpl::ValidatorList::applyList : publisher sequence match"); } else { @@ -1374,7 +1373,7 @@ ValidatorList::verify( auto const sig = strUnHex(signature); auto const data = base64_decode(blob); - if (!sig || !ripple::verify(*signingKey, makeSlice(data), makeSlice(*sig))) + if (!sig || !xrpl::verify(*signingKey, makeSlice(data), makeSlice(*sig))) return {ListDisposition::invalid, masterPubKey}; Json::Reader r; @@ -1508,7 +1507,7 @@ ValidatorList::removePublisherList( XRPL_ASSERT( reason != PublisherStatus::available && reason != PublisherStatus::unavailable, - "ripple::ValidatorList::removePublisherList : valid reason input"); + "xrpl::ValidatorList::removePublisherList : valid reason input"); auto const iList = publisherLists_.find(publisherKey); if (iList == publisherLists_.end()) return false; @@ -1697,7 +1696,7 @@ ValidatorList::getJson() const // Race conditions can happen, so make this check "fuzzy" XRPL_ASSERT( future.validFrom > timeKeeper_.now() + 600s, - "ripple::ValidatorList::getJson : minimum valid from"); + "xrpl::ValidatorList::getJson : minimum valid from"); } if (remaining.size()) curr[jss::remaining] = std::move(remaining); @@ -1764,7 +1763,7 @@ ValidatorList::for_each_available( continue; XRPL_ASSERT( plCollection.maxSequence != 0, - "ripple::ValidatorList::for_each_available : nonzero maxSequence"); + "xrpl::ValidatorList::for_each_available : nonzero maxSequence"); func( plCollection.rawManifest, plCollection.rawVersion, @@ -1854,7 +1853,7 @@ ValidatorList::calculateQuorum( publisherLists_.size() - listThreshold_ + 1); XRPL_ASSERT( errorThreshold > 0, - "ripple::ValidatorList::calculateQuorum : nonzero error threshold"); + "xrpl::ValidatorList::calculateQuorum : nonzero error threshold"); if (unavailable >= errorThreshold) return std::numeric_limits::max(); } @@ -1931,12 +1930,12 @@ ValidatorList::updateTrusted( { XRPL_ASSERT( std::next(iter) == next, - "ripple::ValidatorList::updateTrusted : sequential " + "xrpl::ValidatorList::updateTrusted : sequential " "remaining"); } XRPL_ASSERT( iter != remaining.end(), - "ripple::ValidatorList::updateTrusted : non-end of " + "xrpl::ValidatorList::updateTrusted : non-end of " "remaining"); // Rotate the pending list in to current @@ -1945,7 +1944,7 @@ ValidatorList::updateTrusted( auto& current = collection.current; XRPL_ASSERT( candidate.validFrom <= closeTime, - "ripple::ValidatorList::updateTrusted : maximum time"); + "xrpl::ValidatorList::updateTrusted : maximum time"); auto const oldList = current.list; current = std::move(candidate); @@ -1953,7 +1952,7 @@ ValidatorList::updateTrusted( collection.status = PublisherStatus::available; XRPL_ASSERT( current.sequence == sequence, - "ripple::ValidatorList::updateTrusted : sequence match"); + "xrpl::ValidatorList::updateTrusted : sequence match"); // If the list is expired, remove the validators so they don't // get processed in. The expiration check below will do the rest // of the work @@ -2012,7 +2011,7 @@ ValidatorList::updateTrusted( { XRPL_ASSERT( kit->second >= listThreshold_, - "ripple::ValidatorList::updateTrusted : count meets threshold"); + "xrpl::ValidatorList::updateTrusted : count meets threshold"); ++it; } } @@ -2039,7 +2038,7 @@ ValidatorList::updateTrusted( validatorManifests_.getSigningKey(k); XRPL_ASSERT( signingKey, - "ripple::ValidatorList::updateTrusted : found signing key"); + "xrpl::ValidatorList::updateTrusted : found signing key"); trustedSigningKeys_.insert(*signingKey); } } @@ -2153,4 +2152,4 @@ ValidatorList::negativeUNLFilter( return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/ValidatorSite.cpp b/src/xrpld/app/misc/detail/ValidatorSite.cpp index 74481e9a6b..a76980ac02 100644 --- a/src/xrpld/app/misc/detail/ValidatorSite.cpp +++ b/src/xrpld/app/misc/detail/ValidatorSite.cpp @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { auto constexpr default_refresh_interval = std::chrono::minutes{5}; auto constexpr error_retry_interval = std::chrono::seconds{30}; @@ -394,7 +394,7 @@ ValidatorSite::parseJsonResponse( auto const manifest = body[jss::manifest].asString(); XRPL_ASSERT( version == body[jss::version].asUInt(), - "ripple::ValidatorSite::parseJsonResponse : version match"); + "xrpl::ValidatorSite::parseJsonResponse : version match"); auto const& uri = sites_[siteIdx].activeResource->uri; auto const hash = sha512Half(manifest, blobs, version); auto const applyResult = app_.validators().applyListsAndBroadcast( @@ -571,7 +571,7 @@ ValidatorSite::onSiteFetch( processRedirect(res, siteIdx, lock_sites); XRPL_ASSERT( newLocation, - "ripple::ValidatorSite::onSiteFetch : non-null " + "xrpl::ValidatorSite::onSiteFetch : non-null " "validator"); // for perm redirects, also update our starting URI if (res.result() == status::moved_permanently || @@ -684,4 +684,4 @@ ValidatorSite::getJson() const } return jrr; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/Work.h b/src/xrpld/app/misc/detail/Work.h index 6855c68827..4d1547c4fb 100644 --- a/src/xrpld/app/misc/detail/Work.h +++ b/src/xrpld/app/misc/detail/Work.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -25,6 +25,6 @@ public: } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/detail/WorkBase.h b/src/xrpld/app/misc/detail/WorkBase.h index 03cd2398f5..6c46749f6d 100644 --- a/src/xrpld/app/misc/detail/WorkBase.h +++ b/src/xrpld/app/misc/detail/WorkBase.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -260,7 +260,7 @@ WorkBase::onResponse(error_code const& ec) return fail(ec); close(); - XRPL_ASSERT(cb_, "ripple::detail::WorkBase::onResponse : callback is set"); + XRPL_ASSERT(cb_, "xrpl::detail::WorkBase::onResponse : callback is set"); cb_(ec, lastEndpoint_, std::move(res_)); cb_ = nullptr; } @@ -281,6 +281,6 @@ WorkBase::close() } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/detail/WorkFile.h b/src/xrpld/app/misc/detail/WorkFile.h index 32dfca2b49..ac926ede1f 100644 --- a/src/xrpld/app/misc/detail/WorkFile.h +++ b/src/xrpld/app/misc/detail/WorkFile.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { @@ -78,7 +78,7 @@ WorkFile::run() error_code ec; auto const fileContents = getFileContents(ec, path_, megabytes(1)); - XRPL_ASSERT(cb_, "ripple::detail::WorkFile::run : callback is set"); + XRPL_ASSERT(cb_, "xrpl::detail::WorkFile::run : callback is set"); cb_(ec, fileContents); cb_ = nullptr; } @@ -91,6 +91,6 @@ WorkFile::cancel() } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/detail/WorkPlain.h b/src/xrpld/app/misc/detail/WorkPlain.h index 13ed9c7f1d..23bae20006 100644 --- a/src/xrpld/app/misc/detail/WorkPlain.h +++ b/src/xrpld/app/misc/detail/WorkPlain.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { @@ -60,6 +60,6 @@ WorkPlain::onConnect(error_code const& ec) } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/misc/detail/WorkSSL.cpp b/src/xrpld/app/misc/detail/WorkSSL.cpp index 6bd576cb18..6ccc83f595 100644 --- a/src/xrpld/app/misc/detail/WorkSSL.cpp +++ b/src/xrpld/app/misc/detail/WorkSSL.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace detail { WorkSSL::WorkSSL( @@ -56,4 +56,4 @@ WorkSSL::onHandshake(error_code const& ec) } // namespace detail -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/misc/detail/WorkSSL.h b/src/xrpld/app/misc/detail/WorkSSL.h index 5d17e6979f..7dd1a94c9e 100644 --- a/src/xrpld/app/misc/detail/WorkSSL.h +++ b/src/xrpld/app/misc/detail/WorkSSL.h @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { @@ -57,6 +57,6 @@ private: } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/AMMContext.h b/src/xrpld/app/paths/AMMContext.h index b84634c6dc..a272ba291e 100644 --- a/src/xrpld/app/paths/AMMContext.h +++ b/src/xrpld/app/paths/AMMContext.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { /** Maintains AMM info per overall payment engine execution and * individual iteration. @@ -95,6 +95,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_APP_PATHS_AMMCONTEXT_H_INCLUDED diff --git a/src/xrpld/app/paths/AMMLiquidity.h b/src/xrpld/app/paths/AMMLiquidity.h index 48388b378e..b5b865d80e 100644 --- a/src/xrpld/app/paths/AMMLiquidity.h +++ b/src/xrpld/app/paths/AMMLiquidity.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { template class AMMOffer; @@ -131,6 +131,6 @@ private: maxOffer(TAmounts const& balances, Rules const& rules) const; }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_APP_TX_AMMLIQUIDITY_H_INCLUDED diff --git a/src/xrpld/app/paths/AMMOffer.h b/src/xrpld/app/paths/AMMOffer.h index d669e60d99..07defc16b1 100644 --- a/src/xrpld/app/paths/AMMOffer.h +++ b/src/xrpld/app/paths/AMMOffer.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { template class AMMLiquidity; @@ -127,6 +127,6 @@ public: checkInvariant(TAmounts const& consumed, beast::Journal j) const; }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_APP_AMMOFFER_H_INCLUDED diff --git a/src/xrpld/app/paths/AccountCurrencies.cpp b/src/xrpld/app/paths/AccountCurrencies.cpp index 900ca04904..fbb9c63cd8 100644 --- a/src/xrpld/app/paths/AccountCurrencies.cpp +++ b/src/xrpld/app/paths/AccountCurrencies.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { hash_set accountSourceCurrencies( @@ -66,4 +66,4 @@ accountDestCurrencies( return currencies; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/AccountCurrencies.h b/src/xrpld/app/paths/AccountCurrencies.h index 39e4f8931f..de46a13808 100644 --- a/src/xrpld/app/paths/AccountCurrencies.h +++ b/src/xrpld/app/paths/AccountCurrencies.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { hash_set accountDestCurrencies( @@ -19,6 +19,6 @@ accountSourceCurrencies( std::shared_ptr const& lrLedger, bool includeXRP); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/Credit.cpp b/src/xrpld/app/paths/Credit.cpp index 8895e681dc..09798cef90 100644 --- a/src/xrpld/app/paths/Credit.cpp +++ b/src/xrpld/app/paths/Credit.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { STAmount creditLimit( @@ -25,10 +25,10 @@ creditLimit( XRPL_ASSERT( result.getIssuer() == account, - "ripple::creditLimit : result issuer match"); + "xrpl::creditLimit : result issuer match"); XRPL_ASSERT( result.getCurrency() == currency, - "ripple::creditLimit : result currency match"); + "xrpl::creditLimit : result currency match"); return result; } @@ -63,11 +63,11 @@ creditBalance( XRPL_ASSERT( result.getIssuer() == account, - "ripple::creditBalance : result issuer match"); + "xrpl::creditBalance : result issuer match"); XRPL_ASSERT( result.getCurrency() == currency, - "ripple::creditBalance : result currency match"); + "xrpl::creditBalance : result currency match"); return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/Credit.h b/src/xrpld/app/paths/Credit.h index 69594cf843..5bdcd70e74 100644 --- a/src/xrpld/app/paths/Credit.h +++ b/src/xrpld/app/paths/Credit.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Calculate the maximum amount of IOUs that an account can hold @param ledger the ledger to check against. @@ -45,6 +45,6 @@ creditBalance( Currency const& currency); /** @} */ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/Flow.cpp b/src/xrpld/app/paths/Flow.cpp index c9e16497e3..a102e44854 100644 --- a/src/xrpld/app/paths/Flow.cpp +++ b/src/xrpld/app/paths/Flow.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { template static auto @@ -172,7 +172,7 @@ flow( flowDebugInfo)); } - XRPL_ASSERT(!srcIsXRP && !dstIsXRP, "ripple::flow : neither is XRP"); + XRPL_ASSERT(!srcIsXRP && !dstIsXRP, "xrpl::flow : neither is XRP"); return finishFlow( sb, srcIssue, @@ -190,4 +190,4 @@ flow( flowDebugInfo)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/Flow.h b/src/xrpld/app/paths/Flow.h index ca1e538e3a..5fafe294db 100644 --- a/src/xrpld/app/paths/Flow.h +++ b/src/xrpld/app/paths/Flow.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace path { namespace detail { @@ -51,6 +51,6 @@ flow( beast::Journal j, path::detail::FlowDebugInfo* flowDebugInfo = nullptr); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/PathRequest.cpp b/src/xrpld/app/paths/PathRequest.cpp index 6b7b35e366..41bae4b178 100644 --- a/src/xrpld/app/paths/PathRequest.cpp +++ b/src/xrpld/app/paths/PathRequest.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { PathRequest::PathRequest( Application& app, @@ -139,8 +139,7 @@ PathRequest::updateComplete() { std::lock_guard sl(mIndexLock); - XRPL_ASSERT( - mInProgress, "ripple::PathRequest::updateComplete : in progress"); + XRPL_ASSERT(mInProgress, "xrpl::PathRequest::updateComplete : in progress"); mInProgress = false; if (fCompletion) @@ -762,4 +761,4 @@ PathRequest::getSubscriber() const return wpSubscriber.lock(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/PathRequest.h b/src/xrpld/app/paths/PathRequest.h index b71635cc7f..3d5564c069 100644 --- a/src/xrpld/app/paths/PathRequest.h +++ b/src/xrpld/app/paths/PathRequest.h @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { // A pathfinding request submitted by a client // The request issuer must maintain a strong pointer @@ -158,6 +158,6 @@ private: static unsigned int const max_paths_ = 4; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/PathRequests.cpp b/src/xrpld/app/paths/PathRequests.cpp index 2d5b52d1f9..cfe6080eac 100644 --- a/src/xrpld/app/paths/PathRequests.cpp +++ b/src/xrpld/app/paths/PathRequests.cpp @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { /** Get the current RippleLineCache, updating it if necessary. Get the correct ledger to use. @@ -300,4 +300,4 @@ PathRequests::doLegacyPathRequest( return std::move(jvRes); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/PathRequests.h b/src/xrpld/app/paths/PathRequests.h index 544ff2fec0..5c97bafa8a 100644 --- a/src/xrpld/app/paths/PathRequests.h +++ b/src/xrpld/app/paths/PathRequests.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { class PathRequests { @@ -100,6 +100,6 @@ private: std::recursive_mutex mutable mLock; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/Pathfinder.cpp b/src/xrpld/app/paths/Pathfinder.cpp index d3ed3fc38c..1d3be85d48 100644 --- a/src/xrpld/app/paths/Pathfinder.cpp +++ b/src/xrpld/app/paths/Pathfinder.cpp @@ -45,7 +45,7 @@ same path request (particularly if the search depth may change). */ -namespace ripple { +namespace xrpl { namespace { @@ -174,7 +174,7 @@ Pathfinder::Pathfinder( { XRPL_ASSERT( !uSrcIssuer || isXRP(uSrcCurrency) == isXRP(uSrcIssuer.value()), - "ripple::Pathfinder::Pathfinder : valid inputs"); + "xrpl::Pathfinder::Pathfinder : valid inputs"); } bool @@ -568,7 +568,7 @@ Pathfinder::getBestPaths( XRPL_ASSERT( fullLiquidityPath.empty(), - "ripple::Pathfinder::getBestPaths : first empty path result"); + "xrpl::Pathfinder::getBestPaths : first empty path result"); bool const issuerIsSender = isXRP(mSrcCurrency) || (srcIssuer == mSrcAccount); @@ -630,7 +630,7 @@ Pathfinder::getBestPaths( if (path.empty()) { // LCOV_EXCL_START - UNREACHABLE("ripple::Pathfinder::getBestPaths : path not found"); + UNREACHABLE("xrpl::Pathfinder::getBestPaths : path not found"); continue; // LCOV_EXCL_STOP } @@ -676,7 +676,7 @@ Pathfinder::getBestPaths( { XRPL_ASSERT( fullLiquidityPath.empty(), - "ripple::Pathfinder::getBestPaths : second empty path result"); + "xrpl::Pathfinder::getBestPaths : second empty path result"); JLOG(j_.info()) << "Paths could not send " << remaining << " of " << mDstAmount; } @@ -827,7 +827,7 @@ Pathfinder::addPathsForType( // Source must always be at the start, so pathsOut has to be empty. XRPL_ASSERT( pathsOut.empty(), - "ripple::Pathfinder::addPathsForType : empty paths"); + "xrpl::Pathfinder::addPathsForType : empty paths"); pathsOut.push_back(STPath()); break; @@ -1280,7 +1280,7 @@ void fillPaths(Pathfinder::PaymentType type, PathCostList const& costs) { auto& list = mPathTable[type]; - XRPL_ASSERT(list.empty(), "ripple::fillPaths : empty paths"); + XRPL_ASSERT(list.empty(), "xrpl::fillPaths : empty paths"); for (auto& cost : costs) list.push_back({cost.cost, makePath(cost.path)}); } @@ -1359,4 +1359,4 @@ Pathfinder::initPathTable() }); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/Pathfinder.h b/src/xrpld/app/paths/Pathfinder.h index 91c0a033f1..b269cc868b 100644 --- a/src/xrpld/app/paths/Pathfinder.h +++ b/src/xrpld/app/paths/Pathfinder.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Calculates payment paths. @@ -219,6 +219,6 @@ private: static std::uint32_t const afAC_LAST = 0x080; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/RippleCalc.cpp b/src/xrpld/app/paths/RippleCalc.cpp index a6751169d7..2b48a6ba5c 100644 --- a/src/xrpld/app/paths/RippleCalc.cpp +++ b/src/xrpld/app/paths/RippleCalc.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace path { RippleCalc::Output @@ -108,4 +108,4 @@ RippleCalc::rippleCalculate( } } // namespace path -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/RippleCalc.h b/src/xrpld/app/paths/RippleCalc.h index 1480a02bb7..0ef2641e36 100644 --- a/src/xrpld/app/paths/RippleCalc.h +++ b/src/xrpld/app/paths/RippleCalc.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class Config; namespace path { @@ -107,6 +107,6 @@ public: }; } // namespace path -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/RippleLineCache.cpp b/src/xrpld/app/paths/RippleLineCache.cpp index 498b060cb3..ece4c4149a 100644 --- a/src/xrpld/app/paths/RippleLineCache.cpp +++ b/src/xrpld/app/paths/RippleLineCache.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { RippleLineCache::RippleLineCache( std::shared_ptr const& ledger, @@ -61,7 +61,7 @@ RippleLineCache::getRippleLines( // for either value of outgoing. XRPL_ASSERT( size <= totalLineCount_, - "ripple::RippleLineCache::getRippleLines : maximum lines"); + "xrpl::RippleLineCache::getRippleLines : maximum lines"); totalLineCount_ -= size; lines_.erase(otheriter); } @@ -83,7 +83,7 @@ RippleLineCache::getRippleLines( { XRPL_ASSERT( it->second == nullptr, - "ripple::RippleLineCache::getRippleLines : null lines"); + "xrpl::RippleLineCache::getRippleLines : null lines"); auto lines = PathFindTrustLine::getItems(accountID, *ledger_, direction); if (lines.size()) @@ -96,7 +96,7 @@ RippleLineCache::getRippleLines( XRPL_ASSERT( !it->second || (it->second->size() > 0), - "ripple::RippleLineCache::getRippleLines : null or nonempty lines"); + "xrpl::RippleLineCache::getRippleLines : null or nonempty lines"); auto const size = it->second ? it->second->size() : 0; JLOG(journal_.trace()) << "getRippleLines for ledger " << ledger_->header().seq << " found " << size @@ -111,4 +111,4 @@ RippleLineCache::getRippleLines( return it->second; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/RippleLineCache.h b/src/xrpld/app/paths/RippleLineCache.h index 00614f08c2..c2763ca2b4 100644 --- a/src/xrpld/app/paths/RippleLineCache.h +++ b/src/xrpld/app/paths/RippleLineCache.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { // Used by Pathfinder class RippleLineCache final : public CountedObject @@ -46,7 +46,7 @@ public: private: std::mutex mLock; - ripple::hardened_hash<> hasher_; + xrpl::hardened_hash<> hasher_; std::shared_ptr ledger_; beast::Journal journal_; @@ -108,6 +108,6 @@ private: std::size_t totalLineCount_ = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/TrustLine.cpp b/src/xrpld/app/paths/TrustLine.cpp index 45c17bb893..b6ce9d74b0 100644 --- a/src/xrpld/app/paths/TrustLine.cpp +++ b/src/xrpld/app/paths/TrustLine.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { TrustLineBase::TrustLineBase( std::shared_ptr const& sle, @@ -103,4 +103,4 @@ RPCTrustLine::getItems(AccountID const& accountID, ReadView const& view) return detail::getTrustLineItems(accountID, view); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/TrustLine.h b/src/xrpld/app/paths/TrustLine.h index 8b944d84b1..a0a58c2bde 100644 --- a/src/xrpld/app/paths/TrustLine.h +++ b/src/xrpld/app/paths/TrustLine.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Describes how an account was found in a path, and how to find the next set of paths. "Outgoing" is defined as the source account, or an account found via a @@ -227,6 +227,6 @@ private: Rate highQualityOut_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/detail/AMMLiquidity.cpp b/src/xrpld/app/paths/detail/AMMLiquidity.cpp index 84a039bfc6..2042467923 100644 --- a/src/xrpld/app/paths/detail/AMMLiquidity.cpp +++ b/src/xrpld/app/paths/detail/AMMLiquidity.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { template AMMLiquidity::AMMLiquidity( @@ -60,7 +60,7 @@ AMMLiquidity::generateFibSeqOffer( XRPL_ASSERT( !ammContext_.maxItersReached(), - "ripple::AMMLiquidity::generateFibSeqOffer : maximum iterations"); + "xrpl::AMMLiquidity::generateFibSeqOffer : maximum iterations"); cur.out = toAmount( getIssue(balances.out), @@ -245,4 +245,4 @@ template class AMMLiquidity; template class AMMLiquidity; template class AMMLiquidity; -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/detail/AMMOffer.cpp b/src/xrpld/app/paths/detail/AMMOffer.cpp index 42592ee9c9..a58eafbdbf 100644 --- a/src/xrpld/app/paths/detail/AMMOffer.cpp +++ b/src/xrpld/app/paths/detail/AMMOffer.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { template AMMOffer::AMMOffer( @@ -155,4 +155,4 @@ template class AMMOffer; template class AMMOffer; template class AMMOffer; -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/detail/AmountSpec.h b/src/xrpld/app/paths/detail/AmountSpec.h index 09ebea9c8a..5249bd30e0 100644 --- a/src/xrpld/app/paths/detail/AmountSpec.h +++ b/src/xrpld/app/paths/detail/AmountSpec.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { struct AmountSpec { @@ -107,7 +107,7 @@ inline IOUAmount& get(EitherAmount& amt) { XRPL_ASSERT( - !amt.native, "ripple::get(EitherAmount&) : is not XRP"); + !amt.native, "xrpl::get(EitherAmount&) : is not XRP"); return amt.iou; } @@ -115,7 +115,7 @@ template <> inline XRPAmount& get(EitherAmount& amt) { - XRPL_ASSERT(amt.native, "ripple::get(EitherAmount&) : is XRP"); + XRPL_ASSERT(amt.native, "xrpl::get(EitherAmount&) : is XRP"); return amt.xrp; } @@ -132,8 +132,7 @@ inline IOUAmount const& get(EitherAmount const& amt) { XRPL_ASSERT( - !amt.native, - "ripple::get(EitherAmount const&) : is not XRP"); + !amt.native, "xrpl::get(EitherAmount const&) : is not XRP"); return amt.iou; } @@ -142,7 +141,7 @@ inline XRPAmount const& get(EitherAmount const& amt) { XRPL_ASSERT( - amt.native, "ripple::get(EitherAmount const&) : is XRP"); + amt.native, "xrpl::get(EitherAmount const&) : is XRP"); return amt.xrp; } @@ -151,7 +150,7 @@ toAmountSpec(STAmount const& amt) { XRPL_ASSERT( amt.mantissa() < std::numeric_limits::max(), - "ripple::toAmountSpec(STAmount const&) : maximum mantissa"); + "xrpl::toAmountSpec(STAmount const&) : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); @@ -188,7 +187,7 @@ toAmountSpec(EitherAmount const& ea, std::optional const& c) r.currency = c; XRPL_ASSERT( ea.native == r.native, - "ripple::toAmountSpec(EitherAmount const&&, std::optional) : " + "xrpl::toAmountSpec(EitherAmount const&&, std::optional) : " "matching native"); if (r.native) { @@ -201,6 +200,6 @@ toAmountSpec(EitherAmount const& ea, std::optional const& c) return r; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/detail/BookStep.cpp b/src/xrpld/app/paths/detail/BookStep.cpp index 6144f8adfa..baef42a492 100644 --- a/src/xrpld/app/paths/detail/BookStep.cpp +++ b/src/xrpld/app/paths/detail/BookStep.cpp @@ -20,7 +20,7 @@ #include #include -namespace ripple { +namespace xrpl { template class BookStep : public StepImp> @@ -356,7 +356,7 @@ private: // It's really a programming error if the quality is missing. XRPL_ASSERT( limitQuality, - "ripple::BookOfferCrossingStep::getQuality : nonzero quality"); + "xrpl::BookOfferCrossingStep::getQuality : nonzero quality"); if (!limitQuality) Throw(tefINTERNAL, "Offer requires quality."); return *limitQuality; @@ -1079,7 +1079,7 @@ BookStep::revImp( // LCOV_EXCL_START JLOG(j_.error()) << "BookStep remainingOut < 0 " << to_string(remainingOut); - UNREACHABLE("ripple::BookStep::revImp : remaining less than zero"); + UNREACHABLE("xrpl::BookStep::revImp : remaining less than zero"); cache_.emplace(beast::zero, beast::zero); return {beast::zero, beast::zero}; // LCOV_EXCL_STOP @@ -1103,7 +1103,7 @@ BookStep::fwdImp( boost::container::flat_set& ofrsToRm, TIn const& in) { - XRPL_ASSERT(cache_, "ripple::BookStep::fwdImp : cache is set"); + XRPL_ASSERT(cache_, "xrpl::BookStep::fwdImp : cache is set"); TAmounts result(beast::zero, beast::zero); @@ -1122,8 +1122,7 @@ BookStep::fwdImp( TOut const& ownerGives, std::uint32_t transferRateIn, std::uint32_t transferRateOut) mutable -> bool { - XRPL_ASSERT( - cache_, "ripple::BookStep::fwdImp::eachOffer : cache is set"); + XRPL_ASSERT(cache_, "xrpl::BookStep::fwdImp::eachOffer : cache is set"); if (remainingIn <= beast::zero) return false; @@ -1243,7 +1242,7 @@ BookStep::fwdImp( // something went very wrong JLOG(j_.error()) << "BookStep remainingIn < 0 " << to_string(remainingIn); - UNREACHABLE("ripple::BookStep::fwdImp : remaining less than zero"); + UNREACHABLE("xrpl::BookStep::fwdImp : remaining less than zero"); cache_.emplace(beast::zero, beast::zero); return {beast::zero, beast::zero}; // LCOV_EXCL_STOP @@ -1365,7 +1364,7 @@ namespace test { template static bool -equalHelper(Step const& step, ripple::Book const& book) +equalHelper(Step const& step, xrpl::Book const& book) { if (auto bs = dynamic_cast const*>(&step)) return book == bs->book(); @@ -1373,14 +1372,14 @@ equalHelper(Step const& step, ripple::Book const& book) } bool -bookStepEqual(Step const& step, ripple::Book const& book) +bookStepEqual(Step const& step, xrpl::Book const& book) { bool const inXRP = isXRP(book.in.currency); bool const outXRP = isXRP(book.out.currency); if (inXRP && outXRP) { // LCOV_EXCL_START - UNREACHABLE("ripple::test::bookStepEqual : no XRP to XRP book step"); + UNREACHABLE("xrpl::test::bookStepEqual : no XRP to XRP book step"); return false; // no such thing as xrp/xrp book step // LCOV_EXCL_STOP } @@ -1449,4 +1448,4 @@ make_BookStepXI(StrandContext const& ctx, Issue const& out) return make_BookStepHelper(ctx, xrpIssue(), out); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/detail/DirectStep.cpp b/src/xrpld/app/paths/detail/DirectStep.cpp index 2af467c820..5f9d0c86e7 100644 --- a/src/xrpld/app/paths/detail/DirectStep.cpp +++ b/src/xrpld/app/paths/detail/DirectStep.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { template class DirectStepI : public StepImp> @@ -499,7 +499,7 @@ DirectStepI::revImp( qualities(sb, srcDebtDir, StrandDirection::reverse); XRPL_ASSERT( static_cast(this)->verifyDstQualityIn(dstQIn), - "ripple::DirectStepI : valid destination quality"); + "xrpl::DirectStepI : valid destination quality"); Issue const srcToDstIss(currency_, redeems(srcDebtDir) ? dst_ : src_); @@ -618,7 +618,7 @@ DirectStepI::fwdImp( boost::container::flat_set& /*ofrsToRm*/, IOUAmount const& in) { - XRPL_ASSERT(cache_, "ripple::DirectStepI::fwdImp : cache is set"); + XRPL_ASSERT(cache_, "xrpl::DirectStepI::fwdImp : cache is set"); auto const [maxSrcToDst, srcDebtDir] = static_cast(this)->maxFlow(sb, cache_->srcToDst); @@ -705,7 +705,7 @@ DirectStepI::validFwd( auto const savCache = *cache_; - XRPL_ASSERT(!in.native, "ripple::DirectStepI::validFwd : input is not XRP"); + XRPL_ASSERT(!in.native, "xrpl::DirectStepI::validFwd : input is not XRP"); auto const [maxSrcToDst, srcDebtDir] = static_cast(this)->maxFlow(sb, cache_->srcToDst); @@ -772,7 +772,7 @@ DirectStepI::qualitiesSrcIssues( XRPL_ASSERT( static_cast(this)->verifyPrevStepDebtDirection( prevStepDebtDirection), - "ripple::DirectStepI::qualitiesSrcIssues : will prevStepDebtDirection " + "xrpl::DirectStepI::qualitiesSrcIssues : will prevStepDebtDirection " "issue"); std::uint32_t const srcQOut = redeems(prevStepDebtDirection) @@ -896,7 +896,7 @@ DirectStepI::check(StrandContext const& ctx) const { // LCOV_EXCL_START UNREACHABLE( - "ripple::DirectStepI::check : prev seen book without a " + "xrpl::DirectStepI::check : prev seen book without a " "prev step"); return temBAD_PATH_LOOP; // LCOV_EXCL_STOP @@ -975,4 +975,4 @@ make_DirectStepI( return {tesSUCCESS, std::move(r)}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/detail/FlatSets.h b/src/xrpld/app/paths/detail/FlatSets.h index 9438f71532..cb02a09d9a 100644 --- a/src/xrpld/app/paths/detail/FlatSets.h +++ b/src/xrpld/app/paths/detail/FlatSets.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Given two flat sets dst and src, compute dst = dst union src @@ -25,6 +25,6 @@ SetUnion( boost::container::ordered_unique_range_t{}, src.begin(), src.end()); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/detail/FlowDebugInfo.h b/src/xrpld/app/paths/detail/FlowDebugInfo.h index 1addb5acbd..6c0f0e8e00 100644 --- a/src/xrpld/app/paths/detail/FlowDebugInfo.h +++ b/src/xrpld/app/paths/detail/FlowDebugInfo.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace path { namespace detail { // Track performance information of a single payment @@ -73,7 +73,7 @@ struct FlowDebugInfo { XRPL_ASSERT( !liquiditySrcIn.empty(), - "ripple::path::detail::FlowDebugInfo::pushLiquiditySrc : " + "xrpl::path::detail::FlowDebugInfo::pushLiquiditySrc : " "non-empty liquidity source"); liquiditySrcIn.back().push_back(eIn); liquiditySrcOut.back().push_back(eOut); @@ -109,7 +109,7 @@ struct FlowDebugInfo { // LCOV_EXCL_START UNREACHABLE( - "ripple::path::detail::FlowDebugInfo::duration : timepoint not " + "xrpl::path::detail::FlowDebugInfo::duration : timepoint not " "found"); return std::chrono::duration(0); // LCOV_EXCL_STOP @@ -222,7 +222,7 @@ struct FlowDebugInfo std::vector const& amts, char delim = ';') { auto get_val = [](EitherAmount const& a) -> std::string { - return ripple::to_string(a.xrp); + return xrpl::to_string(a.xrp); }; write_list(amts, get_val, delim); }; @@ -230,7 +230,7 @@ struct FlowDebugInfo std::vector const& amts, char delim = ';') { auto get_val = [](EitherAmount const& a) -> std::string { - return ripple::to_string(a.iou); + return xrpl::to_string(a.iou); }; write_list(amts, get_val, delim); }; @@ -361,5 +361,5 @@ balanceDiffsToString(std::optional const& bd) } // namespace detail } // namespace path -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/detail/PathfinderUtils.h b/src/xrpld/app/paths/detail/PathfinderUtils.h index 42cc6f832f..5571cd4732 100644 --- a/src/xrpld/app/paths/detail/PathfinderUtils.h +++ b/src/xrpld/app/paths/detail/PathfinderUtils.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { inline STAmount largestAmount(STAmount const& amt) @@ -29,6 +29,6 @@ convertAllCheck(STAmount const& a) return a == largestAmount(a); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/detail/PaySteps.cpp b/src/xrpld/app/paths/detail/PaySteps.cpp index 8e189806fb..97d1dad4fa 100644 --- a/src/xrpld/app/paths/detail/PaySteps.cpp +++ b/src/xrpld/app/paths/detail/PaySteps.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { // Check equal with tolerance bool @@ -80,7 +80,7 @@ toStep( // should already be taken care of JLOG(j.error()) << "Found offer/account payment step. Aborting payment strand."; - UNREACHABLE("ripple::toStep : offer/account payment payment strand"); + UNREACHABLE("xrpl::toStep : offer/account payment payment strand"); return {temBAD_PATH, std::unique_ptr{}}; // LCOV_EXCL_STOP } @@ -88,7 +88,7 @@ toStep( XRPL_ASSERT( (e2->getNodeType() & STPathElement::typeCurrency) || (e2->getNodeType() & STPathElement::typeIssuer), - "ripple::toStep : currency or issuer"); + "xrpl::toStep : currency or issuer"); auto const outCurrency = e2->getNodeType() & STPathElement::typeCurrency ? e2->getCurrency() : curIssue.currency; @@ -102,7 +102,7 @@ toStep( return {temBAD_PATH, std::unique_ptr{}}; } - XRPL_ASSERT(e2->isOffer(), "ripple::toStep : is offer"); + XRPL_ASSERT(e2->isOffer(), "xrpl::toStep : is offer"); if (isXRP(outCurrency)) return make_BookStepIX(ctx, curIssue); @@ -376,7 +376,7 @@ toStrand( { // Should never happen // LCOV_EXCL_START - UNREACHABLE("ripple::toStrand : offer currency mismatch"); + UNREACHABLE("xrpl::toStrand : offer currency mismatch"); return {temBAD_PATH, Strand{}}; // LCOV_EXCL_STOP } @@ -444,7 +444,7 @@ toStrand( { // LCOV_EXCL_START JLOG(j.warn()) << "Flow check strand failed"; - UNREACHABLE("ripple::toStrand : invalid strand"); + UNREACHABLE("xrpl::toStrand : invalid strand"); return {temBAD_PATH, Strand{}}; // LCOV_EXCL_STOP } @@ -627,4 +627,4 @@ isDirectXrpToXrp(Strand const& strand); template bool isDirectXrpToXrp(Strand const& strand); -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/paths/detail/StepChecks.h b/src/xrpld/app/paths/detail/StepChecks.h index 7ba1e40d16..969aec2541 100644 --- a/src/xrpld/app/paths/detail/StepChecks.h +++ b/src/xrpld/app/paths/detail/StepChecks.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { inline TER checkFreeze( @@ -17,7 +17,7 @@ checkFreeze( AccountID const& dst, Currency const& currency) { - XRPL_ASSERT(src != dst, "ripple::checkFreeze : unequal input accounts"); + XRPL_ASSERT(src != dst, "xrpl::checkFreeze : unequal input accounts"); // check freeze if (auto sle = view.read(keylet::account(dst))) @@ -93,6 +93,6 @@ checkNoRipple( return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/detail/Steps.h b/src/xrpld/app/paths/detail/Steps.h index 6bdb30dd22..63254c228e 100644 --- a/src/xrpld/app/paths/detail/Steps.h +++ b/src/xrpld/app/paths/detail/Steps.h @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { class PaymentSandbox; class ReadView; class ApplyView; @@ -579,7 +579,7 @@ bool xrpEndpointStepEqual(Step const& step, AccountID const& acc); bool -bookStepEqual(Step const& step, ripple::Book const& book); +bookStepEqual(Step const& step, xrpl::Book const& book); } // namespace test std::pair> @@ -606,6 +606,6 @@ bool isDirectXrpToXrp(Strand const& strand); /// @endcond -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/detail/StrandFlow.h b/src/xrpld/app/paths/detail/StrandFlow.h index fb93f3fdb7..5e0a637858 100644 --- a/src/xrpld/app/paths/detail/StrandFlow.h +++ b/src/xrpld/app/paths/detail/StrandFlow.h @@ -21,7 +21,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Result of flow() execution of a single Strand. */ template @@ -154,7 +154,7 @@ flow( << to_string(get(r.first)) << " maxIn: " << to_string(*maxIn); UNREACHABLE( - "ripple::flow : first step re-executing the " + "xrpl::flow : first step re-executing the " "limiting step failed"); return Result{strand, std::move(ofrsToRm)}; // LCOV_EXCL_STOP @@ -194,7 +194,7 @@ flow( JLOG(j.fatal()) << "Re-executed limiting step failed"; #endif UNREACHABLE( - "ripple::flow : limiting step re-executing the " + "xrpl::flow : limiting step re-executing the " "limiting step failed"); return Result{strand, std::move(ofrsToRm)}; // LCOV_EXCL_STOP @@ -232,7 +232,7 @@ flow( JLOG(j.fatal()) << "Re-executed forward pass failed"; #endif UNREACHABLE( - "ripple::flow : non-limiting step re-executing the " + "xrpl::flow : non-limiting step re-executing the " "forward pass failed"); return Result{strand, std::move(ofrsToRm)}; // LCOV_EXCL_STOP @@ -487,7 +487,7 @@ public: if (i >= cur_.size()) { // LCOV_EXCL_START - UNREACHABLE("ripple::ActiveStrands::get : input out of range"); + UNREACHABLE("xrpl::ActiveStrands::get : input out of range"); return nullptr; // LCOV_EXCL_STOP } @@ -698,7 +698,7 @@ flow( XRPL_ASSERT( f.out <= remainingOut && f.sandbox && (!remainingIn || f.in <= *remainingIn), - "ripple::flow : remaining constraints"); + "xrpl::flow : remaining constraints"); Quality const q(f.out, f.in); @@ -719,7 +719,7 @@ flow( continue; } - XRPL_ASSERT(!best, "ripple::flow : best is unset"); + XRPL_ASSERT(!best, "xrpl::flow : best is unset"); if (!f.inactive) activeStrands.push(strand); best.emplace(f.in, f.out, std::move(*f.sandbox), *strand, q); @@ -805,7 +805,7 @@ flow( // running debug builds of rippled. While this issue still needs to // be resolved, the assert is causing more harm than good at this // point. - // UNREACHABLE("ripple::flow : rounding error"); + // UNREACHABLE("xrpl::flow : rounding error"); return {tefEXCEPTION, std::move(ofrsToRmOnFail)}; } @@ -842,7 +842,7 @@ flow( // Handles both cases 1. and 2. // fixFillOrKill amendment: // Handles 2. 1. is handled above and falls through for tfSell. - XRPL_ASSERT(remainingIn, "ripple::flow : nonzero remainingIn"); + XRPL_ASSERT(remainingIn, "xrpl::flow : nonzero remainingIn"); if (remainingIn && *remainingIn != beast::zero) return { tecPATH_PARTIAL, @@ -854,6 +854,6 @@ flow( return {actualIn, actualOut, std::move(sb), std::move(ofrsToRmOnFail)}; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/paths/detail/XRPEndpointStep.cpp b/src/xrpld/app/paths/detail/XRPEndpointStep.cpp index fb51a68fcc..83271321be 100644 --- a/src/xrpld/app/paths/detail/XRPEndpointStep.cpp +++ b/src/xrpld/app/paths/detail/XRPEndpointStep.cpp @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { template class XRPEndpointStep @@ -106,7 +106,7 @@ protected: XRPAmount xrpLiquidImpl(ReadView& sb, std::int32_t reserveReduction) const { - return ripple::xrpLiquid(sb, acc_, reserveReduction, j_); + return xrpl::xrpLiquid(sb, acc_, reserveReduction, j_); } std::string @@ -263,7 +263,7 @@ XRPEndpointStep::fwdImp( boost::container::flat_set& ofrsToRm, XRPAmount const& in) { - XRPL_ASSERT(cache_, "ripple::XRPEndpointStep::fwdImp : cache is set"); + XRPL_ASSERT(cache_, "xrpl::XRPEndpointStep::fwdImp : cache is set"); auto const balance = static_cast(this)->xrpLiquid(sb); auto const result = isLast_ ? in : std::min(balance, in); @@ -291,7 +291,7 @@ XRPEndpointStep::validFwd( return {false, EitherAmount(XRPAmount(beast::zero))}; } - XRPL_ASSERT(in.native, "ripple::XRPEndpointStep::validFwd : input is XRP"); + XRPL_ASSERT(in.native, "xrpl::XRPEndpointStep::validFwd : input is XRP"); auto const& xrpIn = in.xrp; auto const balance = static_cast(this)->xrpLiquid(sb); @@ -396,4 +396,4 @@ make_XRPEndpointStep(StrandContext const& ctx, AccountID const& acc) return {tesSUCCESS, std::move(r)}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/rdb/PeerFinder.h b/src/xrpld/app/rdb/PeerFinder.h index e5e3195b2f..6c1b2779a6 100644 --- a/src/xrpld/app/rdb/PeerFinder.h +++ b/src/xrpld/app/rdb/PeerFinder.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** * @brief initPeerFinderDB Opens a session with the peer finder database. @@ -52,6 +52,6 @@ savePeerFinderDB( soci::session& session, std::vector const& v); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/rdb/RelationalDatabase.h b/src/xrpld/app/rdb/RelationalDatabase.h index 102479544b..50cd420483 100644 --- a/src/xrpld/app/rdb/RelationalDatabase.h +++ b/src/xrpld/app/rdb/RelationalDatabase.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { struct LedgerHashPair { @@ -218,7 +218,7 @@ rangeCheckedCast(C c) { // This should never happen // LCOV_EXCL_START - UNREACHABLE("ripple::rangeCheckedCast : domain error"); + UNREACHABLE("xrpl::rangeCheckedCast : domain error"); JLOG(debugLog().error()) << "rangeCheckedCast domain error:" << " value = " << c << " min = " << std::numeric_limits::lowest() @@ -229,6 +229,6 @@ rangeCheckedCast(C c) return static_cast(c); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/rdb/State.h b/src/xrpld/app/rdb/State.h index 54e1f8219a..e8c14fdd29 100644 --- a/src/xrpld/app/rdb/State.h +++ b/src/xrpld/app/rdb/State.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { struct SavedState { @@ -74,6 +74,6 @@ setSavedState(soci::session& session, SavedState const& state); void setLastRotated(soci::session& session, LedgerIndex seq); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/rdb/Vacuum.h b/src/xrpld/app/rdb/Vacuum.h index 40c84796d2..d7ca5f8bce 100644 --- a/src/xrpld/app/rdb/Vacuum.h +++ b/src/xrpld/app/rdb/Vacuum.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** * @brief doVacuumDB Creates, initialises, and performs cleanup on a database. @@ -14,6 +14,6 @@ namespace ripple { bool doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/rdb/Wallet.h b/src/xrpld/app/rdb/Wallet.h index c1a17b39dd..961b12d7ef 100644 --- a/src/xrpld/app/rdb/Wallet.h +++ b/src/xrpld/app/rdb/Wallet.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { /** * @brief makeWalletDB Opens the wallet database and returns it. @@ -158,6 +158,6 @@ voteAmendment( std::string const& name, AmendmentVote vote); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/rdb/backend/SQLiteDatabase.h b/src/xrpld/app/rdb/backend/SQLiteDatabase.h index cf668137ea..22a4ed8b37 100644 --- a/src/xrpld/app/rdb/backend/SQLiteDatabase.h +++ b/src/xrpld/app/rdb/backend/SQLiteDatabase.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class SQLiteDatabase : public RelationalDatabase { @@ -289,6 +289,6 @@ public: closeTransactionDB() = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/rdb/backend/detail/Node.cpp b/src/xrpld/app/rdb/backend/detail/Node.cpp index c8458d15db..b112f46409 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.cpp +++ b/src/xrpld/app/rdb/backend/detail/Node.cpp @@ -16,7 +16,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { /** @@ -41,7 +41,7 @@ to_string(TableType type) return "AccountTransactions"; // LCOV_EXCL_START default: - UNREACHABLE("ripple::detail::to_string : invalid TableType"); + UNREACHABLE("xrpl::detail::to_string : invalid TableType"); return "Unknown"; // LCOV_EXCL_STOP } @@ -187,7 +187,7 @@ saveValidatedLedger( { // LCOV_EXCL_START JLOG(j.fatal()) << "AH is zero: " << getJson({*ledger, {}}); - UNREACHABLE("ripple::detail::saveValidatedLedger : zero account hash"); + UNREACHABLE("xrpl::detail::saveValidatedLedger : zero account hash"); // LCOV_EXCL_STOP } @@ -200,13 +200,13 @@ saveValidatedLedger( JLOG(j.fatal()) << "saveAcceptedLedger: seq=" << seq << ", current=" << current; UNREACHABLE( - "ripple::detail::saveValidatedLedger : mismatched account hash"); + "xrpl::detail::saveValidatedLedger : mismatched account hash"); // LCOV_EXCL_STOP } XRPL_ASSERT( ledger->header().txHash == ledger->txMap().getHash().as_uint256(), - "ripple::detail::saveValidatedLedger : transaction hash match"); + "xrpl::detail::saveValidatedLedger : transaction hash match"); // Save the ledger header in the hashed object store { @@ -1354,4 +1354,4 @@ dbHasSpace(soci::session& session, Config const& config, beast::Journal j) } } // namespace detail -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/rdb/backend/detail/Node.h b/src/xrpld/app/rdb/backend/detail/Node.h index fbf06083d6..37d028c035 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.h +++ b/src/xrpld/app/rdb/backend/detail/Node.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace detail { /* Need to change TableTypeCount if TableType is modified. */ @@ -436,6 +436,6 @@ bool dbHasSpace(soci::session& session, Config const& config, beast::Journal j); } // namespace detail -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp b/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp index b789685211..796b030a99 100644 --- a/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp +++ b/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { class SQLiteDatabaseImp final : public SQLiteDatabase { @@ -789,7 +789,7 @@ SQLiteDatabaseImp::getKBUsedAll() { if (existsLedger()) { - return ripple::getKBUsedAll(lgrdb_->getSession()); + return xrpl::getKBUsedAll(lgrdb_->getSession()); } return 0; @@ -800,7 +800,7 @@ SQLiteDatabaseImp::getKBUsedLedger() { if (existsLedger()) { - return ripple::getKBUsedDB(lgrdb_->getSession()); + return xrpl::getKBUsedDB(lgrdb_->getSession()); } return 0; @@ -814,7 +814,7 @@ SQLiteDatabaseImp::getKBUsedTransaction() if (existsTransaction()) { - return ripple::getKBUsedDB(txdb_->getSession()); + return xrpl::getKBUsedDB(txdb_->getSession()); } return 0; @@ -838,4 +838,4 @@ getSQLiteDatabase(Application& app, Config const& config, JobQueue& jobQueue) return std::make_unique(app, config, jobQueue); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/rdb/detail/PeerFinder.cpp b/src/xrpld/app/rdb/detail/PeerFinder.cpp index 7ac0a941e2..0c4b5d355c 100644 --- a/src/xrpld/app/rdb/detail/PeerFinder.cpp +++ b/src/xrpld/app/rdb/detail/PeerFinder.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { void initPeerFinderDB( @@ -249,4 +249,4 @@ savePeerFinderDB( tr.commit(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/rdb/detail/RelationalDatabase.cpp b/src/xrpld/app/rdb/detail/RelationalDatabase.cpp index a01f0583f6..37ee2a7703 100644 --- a/src/xrpld/app/rdb/detail/RelationalDatabase.cpp +++ b/src/xrpld/app/rdb/detail/RelationalDatabase.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { extern std::unique_ptr getSQLiteDatabase(Application& app, Config const& config, JobQueue& jobQueue); @@ -42,4 +42,4 @@ RelationalDatabase::init( return std::unique_ptr(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/rdb/detail/State.cpp b/src/xrpld/app/rdb/detail/State.cpp index d731c98b40..984c8824f2 100644 --- a/src/xrpld/app/rdb/detail/State.cpp +++ b/src/xrpld/app/rdb/detail/State.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { void initStateDB( @@ -108,4 +108,4 @@ setLastRotated(soci::session& session, LedgerIndex seq) soci::use(seq); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/rdb/detail/Vacuum.cpp b/src/xrpld/app/rdb/detail/Vacuum.cpp index 49e86ae281..8423f20992 100644 --- a/src/xrpld/app/rdb/detail/Vacuum.cpp +++ b/src/xrpld/app/rdb/detail/Vacuum.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { bool doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j) @@ -49,4 +49,4 @@ doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j) return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/rdb/detail/Wallet.cpp b/src/xrpld/app/rdb/detail/Wallet.cpp index 7dbaab6ef4..fc4f5ea89b 100644 --- a/src/xrpld/app/rdb/detail/Wallet.cpp +++ b/src/xrpld/app/rdb/detail/Wallet.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { std::unique_ptr makeWalletDB(DatabaseCon::Setup const& setup, beast::Journal j) @@ -284,4 +284,4 @@ voteAmendment( tr.commit(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/apply.h b/src/xrpld/app/tx/apply.h index 2e0cd538f2..d578334c31 100644 --- a/src/xrpld/app/tx/apply.h +++ b/src/xrpld/app/tx/apply.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { class Application; class HashRouter; @@ -138,6 +138,6 @@ applyTransaction( ApplyFlags flags, beast::Journal journal); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/applySteps.h b/src/xrpld/app/tx/applySteps.h index 6542a8d6ec..c0c530f3ac 100644 --- a/src/xrpld/app/tx/applySteps.h +++ b/src/xrpld/app/tx/applySteps.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; class STTx; @@ -347,6 +347,6 @@ calculateDefaultBaseFee(ReadView const& view, STTx const& tx); ApplyResult doApply(PreclaimResult const& preclaimResult, Application& app, OpenView& view); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/AMMBid.cpp b/src/xrpld/app/tx/detail/AMMBid.cpp index 47b89417a3..34b2c811c2 100644 --- a/src/xrpld/app/tx/detail/AMMBid.cpp +++ b/src/xrpld/app/tx/detail/AMMBid.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { bool AMMBid::checkExtraFeatures(PreflightContext const& ctx) @@ -173,7 +173,7 @@ applyBid( { XRPL_ASSERT( ammSle->isFieldPresent(sfAuctionSlot), - "ripple::applyBid : has auction slot"); + "xrpl::applyBid : has auction slot"); if (!ammSle->isFieldPresent(sfAuctionSlot)) return {tecINTERNAL, false}; } @@ -300,7 +300,7 @@ applyBid( { // Price the slot was purchased at. STAmount const pricePurchased = auctionSlot[sfPrice]; - XRPL_ASSERT(timeSlot, "ripple::applyBid : timeSlot is set"); + XRPL_ASSERT(timeSlot, "xrpl::applyBid : timeSlot is set"); auto const fractionUsed = (Number(*timeSlot) + 1) / AUCTION_SLOT_TIME_INTERVALS; auto const fractionRemaining = Number(1) - fractionUsed; @@ -362,4 +362,4 @@ AMMBid::doApply() return result.first; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/AMMBid.h b/src/xrpld/app/tx/detail/AMMBid.h index 25ad118e05..b402e82f9d 100644 --- a/src/xrpld/app/tx/detail/AMMBid.h +++ b/src/xrpld/app/tx/detail/AMMBid.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** AMMBid implements AMM bid Transactor. * This is a mechanism for an AMM instance to auction-off @@ -65,6 +65,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_AMMBID_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/AMMClawback.cpp b/src/xrpld/app/tx/detail/AMMClawback.cpp index ebde91b43d..5eaed55f23 100644 --- a/src/xrpld/app/tx/detail/AMMClawback.cpp +++ b/src/xrpld/app/tx/detail/AMMClawback.cpp @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { std::uint32_t AMMClawback::getFlagsMask(PreflightContext const& ctx) @@ -321,4 +321,4 @@ AMMClawback::equalWithdrawMatchingOneAmount( ctx_.journal); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/AMMClawback.h b/src/xrpld/app/tx/detail/AMMClawback.h index b1283c9427..0615234ffa 100644 --- a/src/xrpld/app/tx/detail/AMMClawback.h +++ b/src/xrpld/app/tx/detail/AMMClawback.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Sandbox; class AMMClawback : public Transactor { @@ -54,6 +54,6 @@ private: STAmount const& amount); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/AMMCreate.cpp b/src/xrpld/app/tx/detail/AMMCreate.cpp index 65357ad197..3a3ce4b1e1 100644 --- a/src/xrpld/app/tx/detail/AMMCreate.cpp +++ b/src/xrpld/app/tx/detail/AMMCreate.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { bool AMMCreate::checkExtraFeatures(PreflightContext const& ctx) @@ -330,4 +330,4 @@ AMMCreate::doApply() return result.first; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/AMMCreate.h b/src/xrpld/app/tx/detail/AMMCreate.h index 5be2cc264c..da77f79c5e 100644 --- a/src/xrpld/app/tx/detail/AMMCreate.h +++ b/src/xrpld/app/tx/detail/AMMCreate.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** AMMCreate implements Automatic Market Maker(AMM) creation Transactor. * It creates a new AMM instance with two tokens. Any trader, or Liquidity @@ -61,6 +61,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_AMMCREATE_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/AMMDelete.cpp b/src/xrpld/app/tx/detail/AMMDelete.cpp index 476b035bc0..a6cfaac586 100644 --- a/src/xrpld/app/tx/detail/AMMDelete.cpp +++ b/src/xrpld/app/tx/detail/AMMDelete.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { bool AMMDelete::checkExtraFeatures(PreflightContext const& ctx) @@ -53,4 +53,4 @@ AMMDelete::doApply() return ter; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/AMMDelete.h b/src/xrpld/app/tx/detail/AMMDelete.h index af0b33154b..a09b855c7c 100644 --- a/src/xrpld/app/tx/detail/AMMDelete.h +++ b/src/xrpld/app/tx/detail/AMMDelete.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** AMMDelete implements AMM delete transactor. This is a mechanism to * delete AMM in an empty state when the number of LP tokens is 0. @@ -33,6 +33,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_AMMDELETE_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/AMMDeposit.cpp b/src/xrpld/app/tx/detail/AMMDeposit.cpp index 3495ef03f5..36399d4e1c 100644 --- a/src/xrpld/app/tx/detail/AMMDeposit.cpp +++ b/src/xrpld/app/tx/detail/AMMDeposit.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { bool AMMDeposit::checkExtraFeatures(PreflightContext const& ctx) @@ -448,7 +448,7 @@ AMMDeposit::applyGuts(Sandbox& sb) { XRPL_ASSERT( newLPTokenBalance > beast::zero, - "ripple::AMMDeposit::applyGuts : valid new LP token balance"); + "xrpl::AMMDeposit::applyGuts : valid new LP token balance"); ammSle->setFieldAmount(sfLPTokenBalance, newLPTokenBalance); // LP depositing into AMM empty state gets the auction slot // and the voting @@ -1008,4 +1008,4 @@ AMMDeposit::equalDepositInEmptyState( tfee); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/AMMDeposit.h b/src/xrpld/app/tx/detail/AMMDeposit.h index fa0610fcd5..7fd50c4c4d 100644 --- a/src/xrpld/app/tx/detail/AMMDeposit.h +++ b/src/xrpld/app/tx/detail/AMMDeposit.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Sandbox; @@ -229,6 +229,6 @@ private: std::uint16_t tfee); }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_AMMDEPOSIT_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/AMMVote.cpp b/src/xrpld/app/tx/detail/AMMVote.cpp index ea11f543dd..ca57ce1f8c 100644 --- a/src/xrpld/app/tx/detail/AMMVote.cpp +++ b/src/xrpld/app/tx/detail/AMMVote.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { bool AMMVote::checkExtraFeatures(PreflightContext const& ctx) @@ -177,7 +177,7 @@ applyVote( XRPL_ASSERT( !ctx_.view().rules().enabled(fixInnerObjTemplate) || ammSle->isFieldPresent(sfAuctionSlot), - "ripple::applyVote : has auction slot"); + "xrpl::applyVote : has auction slot"); // Update the vote entries and the trading/discounted fee. ammSle->setFieldArray(sfVoteSlots, updatedVoteSlots); @@ -224,4 +224,4 @@ AMMVote::doApply() return result.first; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/AMMVote.h b/src/xrpld/app/tx/detail/AMMVote.h index b38beb56bc..1dec046c29 100644 --- a/src/xrpld/app/tx/detail/AMMVote.h +++ b/src/xrpld/app/tx/detail/AMMVote.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** AMMVote implements AMM vote Transactor. * This transactor allows for the TradingFee of the AMM instance be a votable @@ -50,6 +50,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_AMMVOTE_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/AMMWithdraw.cpp b/src/xrpld/app/tx/detail/AMMWithdraw.cpp index ac49298920..78da481b95 100644 --- a/src/xrpld/app/tx/detail/AMMWithdraw.cpp +++ b/src/xrpld/app/tx/detail/AMMWithdraw.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { bool AMMWithdraw::checkExtraFeatures(PreflightContext const& ctx) @@ -891,7 +891,7 @@ AMMWithdraw::equalWithdrawLimit( // LCOV_EXCL_START XRPL_ASSERT( amountWithdraw <= amount, - "ripple::AMMWithdraw::equalWithdrawLimit : maximum amountWithdraw"); + "xrpl::AMMWithdraw::equalWithdrawLimit : maximum amountWithdraw"); // LCOV_EXCL_STOP } else if (amountWithdraw > amount) @@ -1084,4 +1084,4 @@ AMMWithdraw::isWithdrawAll(STTx const& tx) return WithdrawAll::Yes; return WithdrawAll::No; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/AMMWithdraw.h b/src/xrpld/app/tx/detail/AMMWithdraw.h index 871f8e3a21..916621a5d0 100644 --- a/src/xrpld/app/tx/detail/AMMWithdraw.h +++ b/src/xrpld/app/tx/detail/AMMWithdraw.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { class Sandbox; @@ -293,6 +293,6 @@ private: isWithdrawAll(STTx const& tx); }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_AMMWITHDRAW_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/ApplyContext.cpp b/src/xrpld/app/tx/detail/ApplyContext.cpp index 4a7f72e2e3..d364950b44 100644 --- a/src/xrpld/app/tx/detail/ApplyContext.cpp +++ b/src/xrpld/app/tx/detail/ApplyContext.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { ApplyContext::ApplyContext( Application& app_, @@ -133,7 +133,7 @@ ApplyContext::checkInvariants(TER const result, XRPAmount const fee) { XRPL_ASSERT( isTesSuccess(result) || isTecClaim(result), - "ripple::ApplyContext::checkInvariants : is tesSUCCESS or tecCLAIM"); + "xrpl::ApplyContext::checkInvariants : is tesSUCCESS or tecCLAIM"); return checkInvariantsHelper( result, @@ -141,4 +141,4 @@ ApplyContext::checkInvariants(TER const result, XRPAmount const fee) std::make_index_sequence::value>{}); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/ApplyContext.h b/src/xrpld/app/tx/detail/ApplyContext.h index e045189146..4ae2f11a85 100644 --- a/src/xrpld/app/tx/detail/ApplyContext.h +++ b/src/xrpld/app/tx/detail/ApplyContext.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { /** State information when applying a tx. */ class ApplyContext @@ -140,6 +140,6 @@ private: std::optional parentBatchId_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/Batch.cpp b/src/xrpld/app/tx/detail/Batch.cpp index 8bf0c7fe02..277bd4e3b7 100644 --- a/src/xrpld/app/tx/detail/Batch.cpp +++ b/src/xrpld/app/tx/detail/Batch.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** * @brief Calculates the total base fee for a batch transaction. @@ -78,7 +78,7 @@ Batch::calculateBaseFee(ReadView const& view, STTx const& tx) } // LCOV_EXCL_STOP - auto const fee = ripple::calculateBaseFee(view, stx); + auto const fee = xrpl::calculateBaseFee(view, stx); // LCOV_EXCL_START if (txnFees > maxAmount - fee) { @@ -306,7 +306,7 @@ Batch::preflight(PreflightContext const& ctx) } auto const innerAccount = stx.getAccountID(sfAccount); - if (auto const preflightResult = ripple::preflight( + if (auto const preflightResult = xrpl::preflight( ctx.app, ctx.rules, parentBatchId, stx, tapBATCH, ctx.j); preflightResult.ter != tesSUCCESS) { @@ -521,4 +521,4 @@ Batch::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/Batch.h b/src/xrpld/app/tx/detail/Batch.h index 7889e91bdc..a8cfeadc6b 100644 --- a/src/xrpld/app/tx/detail/Batch.h +++ b/src/xrpld/app/tx/detail/Batch.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class Batch : public Transactor { @@ -55,6 +55,6 @@ public: }); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/BookTip.cpp b/src/xrpld/app/tx/detail/BookTip.cpp index 09a0091995..d3c8e69e01 100644 --- a/src/xrpld/app/tx/detail/BookTip.cpp +++ b/src/xrpld/app/tx/detail/BookTip.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { BookTip::BookTip(ApplyView& view, Book const& book) : view_(view) @@ -59,4 +59,4 @@ BookTip::step(beast::Journal j) return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/BookTip.h b/src/xrpld/app/tx/detail/BookTip.h index f6d05f1df5..51dc252835 100644 --- a/src/xrpld/app/tx/detail/BookTip.h +++ b/src/xrpld/app/tx/detail/BookTip.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { class Logs; @@ -61,6 +61,6 @@ public: step(beast::Journal j); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/CancelCheck.cpp b/src/xrpld/app/tx/detail/CancelCheck.cpp index daf4955d47..b673784655 100644 --- a/src/xrpld/app/tx/detail/CancelCheck.cpp +++ b/src/xrpld/app/tx/detail/CancelCheck.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC CancelCheck::preflight(PreflightContext const& ctx) @@ -101,4 +101,4 @@ CancelCheck::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/CancelCheck.h b/src/xrpld/app/tx/detail/CancelCheck.h index 6f0b5a969b..4be696520d 100644 --- a/src/xrpld/app/tx/detail/CancelCheck.h +++ b/src/xrpld/app/tx/detail/CancelCheck.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class CancelCheck : public Transactor { @@ -26,6 +26,6 @@ public: using CheckCancel = CancelCheck; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/CancelOffer.cpp b/src/xrpld/app/tx/detail/CancelOffer.cpp index 149d7e2d9c..1dc9ad0bde 100644 --- a/src/xrpld/app/tx/detail/CancelOffer.cpp +++ b/src/xrpld/app/tx/detail/CancelOffer.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC CancelOffer::preflight(PreflightContext const& ctx) @@ -61,4 +61,4 @@ CancelOffer::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/CancelOffer.h b/src/xrpld/app/tx/detail/CancelOffer.h index 3ae6afa935..33af365c4d 100644 --- a/src/xrpld/app/tx/detail/CancelOffer.h +++ b/src/xrpld/app/tx/detail/CancelOffer.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { class CancelOffer : public Transactor { @@ -28,6 +28,6 @@ public: using OfferCancel = CancelOffer; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/CashCheck.cpp b/src/xrpld/app/tx/detail/CashCheck.cpp index 4010aa0714..c32b7dfe4e 100644 --- a/src/xrpld/app/tx/detail/CashCheck.cpp +++ b/src/xrpld/app/tx/detail/CashCheck.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { NotTEC CashCheck::preflight(PreflightContext const& ctx) @@ -475,4 +475,4 @@ CashCheck::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/CashCheck.h b/src/xrpld/app/tx/detail/CashCheck.h index cfa0adbe1f..f27a45a0c4 100644 --- a/src/xrpld/app/tx/detail/CashCheck.h +++ b/src/xrpld/app/tx/detail/CashCheck.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class CashCheck : public Transactor { @@ -26,6 +26,6 @@ public: using CheckCash = CashCheck; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/Change.cpp b/src/xrpld/app/tx/detail/Change.cpp index 43c6f7c619..191d91863d 100644 --- a/src/xrpld/app/tx/detail/Change.cpp +++ b/src/xrpld/app/tx/detail/Change.cpp @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { template <> NotTEC @@ -131,7 +131,7 @@ Change::doApply() return applyUNLModify(); // LCOV_EXCL_START default: - UNREACHABLE("ripple::Change::doApply : invalid transaction type"); + UNREACHABLE("xrpl::Change::doApply : invalid transaction type"); return tefFAILURE; // LCOV_EXCL_STOP } @@ -141,7 +141,7 @@ void Change::preCompute() { XRPL_ASSERT( - account_ == beast::zero, "ripple::Change::preCompute : zero account"); + account_ == beast::zero, "xrpl::Change::preCompute : zero account"); } TER @@ -407,4 +407,4 @@ Change::applyUNLModify() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/Change.h b/src/xrpld/app/tx/detail/Change.h index 9ff37b1515..4d7b76ed78 100644 --- a/src/xrpld/app/tx/detail/Change.h +++ b/src/xrpld/app/tx/detail/Change.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Change : public Transactor { @@ -43,6 +43,6 @@ using EnableAmendment = Change; using SetFee = Change; using UNLModify = Change; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/Clawback.cpp b/src/xrpld/app/tx/detail/Clawback.cpp index 0d153771b5..24b1603aab 100644 --- a/src/xrpld/app/tx/detail/Clawback.cpp +++ b/src/xrpld/app/tx/detail/Clawback.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { template static NotTEC @@ -270,4 +270,4 @@ Clawback::doApply() ctx_.tx[sfAmount].asset().value()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/Clawback.h b/src/xrpld/app/tx/detail/Clawback.h index 95ebd0e74c..8db93fcc01 100644 --- a/src/xrpld/app/tx/detail/Clawback.h +++ b/src/xrpld/app/tx/detail/Clawback.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Clawback : public Transactor { @@ -27,6 +27,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/CreateCheck.cpp b/src/xrpld/app/tx/detail/CreateCheck.cpp index df859c4364..11613a5855 100644 --- a/src/xrpld/app/tx/detail/CreateCheck.cpp +++ b/src/xrpld/app/tx/detail/CreateCheck.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC CreateCheck::preflight(PreflightContext const& ctx) @@ -214,4 +214,4 @@ CreateCheck::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/CreateCheck.h b/src/xrpld/app/tx/detail/CreateCheck.h index b8b0add2f9..ac735eecb0 100644 --- a/src/xrpld/app/tx/detail/CreateCheck.h +++ b/src/xrpld/app/tx/detail/CreateCheck.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class CreateCheck : public Transactor { @@ -26,6 +26,6 @@ public: using CheckCreate = CreateCheck; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/CreateOffer.cpp b/src/xrpld/app/tx/detail/CreateOffer.cpp index fe96436f2f..f81afecd55 100644 --- a/src/xrpld/app/tx/detail/CreateOffer.cpp +++ b/src/xrpld/app/tx/detail/CreateOffer.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { TxConsequences CreateOffer::makeTxConsequences(PreflightContext const& ctx) { @@ -216,7 +216,7 @@ CreateOffer::checkAcceptAsset( // Only valid for custom currencies XRPL_ASSERT( !isXRP(issue.currency), - "ripple::CreateOffer::checkAcceptAsset : input is not XRP"); + "xrpl::CreateOffer::checkAcceptAsset : input is not XRP"); auto const issuerAccount = view.read(keylet::account(issue.account)); @@ -460,7 +460,7 @@ CreateOffer::flowCross( afterCross.out -= result.actualAmountOut; XRPL_ASSERT( afterCross.out >= beast::zero, - "ripple::CreateOffer::flowCross : minimum offer"); + "xrpl::CreateOffer::flowCross : minimum offer"); if (afterCross.out < beast::zero) afterCross.out.clear(); afterCross.in = mulRound( @@ -673,7 +673,7 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) // or give a tec. XRPL_ASSERT( result == tesSUCCESS || isTecClaim(result), - "ripple::CreateOffer::applyGuts : result is tesSUCCESS or " + "xrpl::CreateOffer::applyGuts : result is tesSUCCESS or " "tecCLAIM"); if (auto stream = j_.trace()) @@ -694,10 +694,10 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) XRPL_ASSERT( saTakerGets.issue() == place_offer.in.issue(), - "ripple::CreateOffer::applyGuts : taker gets issue match"); + "xrpl::CreateOffer::applyGuts : taker gets issue match"); XRPL_ASSERT( saTakerPays.issue() == place_offer.out.issue(), - "ripple::CreateOffer::applyGuts : taker pays issue match"); + "xrpl::CreateOffer::applyGuts : taker pays issue match"); if (takerAmount != place_offer) crossed = true; @@ -727,7 +727,7 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) XRPL_ASSERT( saTakerPays > zero && saTakerGets > zero, - "ripple::CreateOffer::applyGuts : taker pays and gets positive"); + "xrpl::CreateOffer::applyGuts : taker pays and gets positive"); if (result != tesSUCCESS) { @@ -907,4 +907,4 @@ CreateOffer::doApply() return result.first; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/CreateOffer.h b/src/xrpld/app/tx/detail/CreateOffer.h index 9593b9d1ad..5aaa60c20e 100644 --- a/src/xrpld/app/tx/detail/CreateOffer.h +++ b/src/xrpld/app/tx/detail/CreateOffer.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { class PaymentSandbox; class Sandbox; @@ -78,6 +78,6 @@ private: using OfferCreate = CreateOffer; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/CreateTicket.cpp b/src/xrpld/app/tx/detail/CreateTicket.cpp index 1a49209faf..6432d1b3d5 100644 --- a/src/xrpld/app/tx/detail/CreateTicket.cpp +++ b/src/xrpld/app/tx/detail/CreateTicket.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { TxConsequences CreateTicket::makeTxConsequences(PreflightContext const& ctx) @@ -125,4 +125,4 @@ CreateTicket::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/CreateTicket.h b/src/xrpld/app/tx/detail/CreateTicket.h index da5083c838..a41c7e2b1f 100644 --- a/src/xrpld/app/tx/detail/CreateTicket.h +++ b/src/xrpld/app/tx/detail/CreateTicket.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class CreateTicket : public Transactor { @@ -65,6 +65,6 @@ public: using TicketCreate = CreateTicket; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/Credentials.cpp b/src/xrpld/app/tx/detail/Credentials.cpp index 274a25e0c6..6d106535a2 100644 --- a/src/xrpld/app/tx/detail/Credentials.cpp +++ b/src/xrpld/app/tx/detail/Credentials.cpp @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { /* Credentials @@ -353,4 +353,4 @@ CredentialAccept::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/Credentials.h b/src/xrpld/app/tx/detail/Credentials.h index 704730e6ee..6723a2f0e4 100644 --- a/src/xrpld/app/tx/detail/Credentials.h +++ b/src/xrpld/app/tx/detail/Credentials.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class CredentialCreate : public Transactor { @@ -75,6 +75,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/DID.cpp b/src/xrpld/app/tx/detail/DID.cpp index b17d4ef1b7..e9b23a15eb 100644 --- a/src/xrpld/app/tx/detail/DID.cpp +++ b/src/xrpld/app/tx/detail/DID.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /* DID @@ -194,4 +194,4 @@ DIDDelete::doApply() return deleteSLE(ctx_, keylet::did(account_), account_); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/DID.h b/src/xrpld/app/tx/detail/DID.h index 9e9de22f84..934a9c9e6f 100644 --- a/src/xrpld/app/tx/detail/DID.h +++ b/src/xrpld/app/tx/detail/DID.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class DIDSet : public Transactor { @@ -49,6 +49,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/DelegateSet.cpp b/src/xrpld/app/tx/detail/DelegateSet.cpp index f8dd696fad..8c64547ae1 100644 --- a/src/xrpld/app/tx/detail/DelegateSet.cpp +++ b/src/xrpld/app/tx/detail/DelegateSet.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC DelegateSet::preflight(PreflightContext const& ctx) @@ -129,4 +129,4 @@ DelegateSet::deleteDelegate( return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/DelegateSet.h b/src/xrpld/app/tx/detail/DelegateSet.h index 2f340efb3b..1f9bc02944 100644 --- a/src/xrpld/app/tx/detail/DelegateSet.h +++ b/src/xrpld/app/tx/detail/DelegateSet.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class DelegateSet : public Transactor { @@ -32,6 +32,6 @@ public: beast::Journal j); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/DeleteAccount.cpp b/src/xrpld/app/tx/detail/DeleteAccount.cpp index c9fd0cc75e..422ed37e2f 100644 --- a/src/xrpld/app/tx/detail/DeleteAccount.cpp +++ b/src/xrpld/app/tx/detail/DeleteAccount.cpp @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { bool DeleteAccount::checkExtraFeatures(PreflightContext const& ctx) @@ -237,8 +237,7 @@ DeleteAccount::preclaim(PreclaimContext const& ctx) } auto sleAccount = ctx.view.read(keylet::account(account)); - XRPL_ASSERT( - sleAccount, "ripple::DeleteAccount::preclaim : non-null account"); + XRPL_ASSERT(sleAccount, "xrpl::DeleteAccount::preclaim : non-null account"); if (!sleAccount) return terNO_ACCOUNT; @@ -338,13 +337,12 @@ TER DeleteAccount::doApply() { auto src = view().peek(keylet::account(account_)); - XRPL_ASSERT( - src, "ripple::DeleteAccount::doApply : non-null source account"); + XRPL_ASSERT(src, "xrpl::DeleteAccount::doApply : non-null source account"); auto const dstID = ctx_.tx[sfDestination]; auto dst = view().peek(keylet::account(dstID)); XRPL_ASSERT( - dst, "ripple::DeleteAccount::doApply : non-null destination account"); + dst, "xrpl::DeleteAccount::doApply : non-null destination account"); if (!src || !dst) return tefBAD_LEDGER; // LCOV_EXCL_LINE @@ -374,7 +372,7 @@ DeleteAccount::doApply() // LCOV_EXCL_START UNREACHABLE( - "ripple::DeleteAccount::doApply : undeletable item not found " + "xrpl::DeleteAccount::doApply : undeletable item not found " "in preclaim"); JLOG(j_.error()) << "DeleteAccount undeletable item not " "found in preclaim."; @@ -392,7 +390,7 @@ DeleteAccount::doApply() XRPL_ASSERT( (*src)[sfBalance] == XRPAmount(0), - "ripple::DeleteAccount::doApply : source balance is zero"); + "xrpl::DeleteAccount::doApply : source balance is zero"); // If there's still an owner directory associated with the source account // delete it. @@ -413,4 +411,4 @@ DeleteAccount::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/DeleteAccount.h b/src/xrpld/app/tx/detail/DeleteAccount.h index bfab5591a0..357f87d566 100644 --- a/src/xrpld/app/tx/detail/DeleteAccount.h +++ b/src/xrpld/app/tx/detail/DeleteAccount.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class DeleteAccount : public Transactor { @@ -32,6 +32,6 @@ public: using AccountDelete = DeleteAccount; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/DeleteOracle.cpp b/src/xrpld/app/tx/detail/DeleteOracle.cpp index d635721b86..df7b737eed 100644 --- a/src/xrpld/app/tx/detail/DeleteOracle.cpp +++ b/src/xrpld/app/tx/detail/DeleteOracle.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC DeleteOracle::preflight(PreflightContext const& ctx) @@ -80,4 +80,4 @@ DeleteOracle::doApply() return tecINTERNAL; // LCOV_EXCL_LINE } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/DeleteOracle.h b/src/xrpld/app/tx/detail/DeleteOracle.h index a9fcd73ec2..48950cfad9 100644 --- a/src/xrpld/app/tx/detail/DeleteOracle.h +++ b/src/xrpld/app/tx/detail/DeleteOracle.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Price Oracle is a system that acts as a bridge between @@ -42,6 +42,6 @@ public: using OracleDelete = DeleteOracle; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_DELETEORACLE_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/DepositPreauth.cpp b/src/xrpld/app/tx/detail/DepositPreauth.cpp index 069b356e99..057e240fff 100644 --- a/src/xrpld/app/tx/detail/DepositPreauth.cpp +++ b/src/xrpld/app/tx/detail/DepositPreauth.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { bool DepositPreauth::checkExtraFeatures(PreflightContext const& ctx) @@ -299,4 +299,4 @@ DepositPreauth::removeFromLedger( return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/DepositPreauth.h b/src/xrpld/app/tx/detail/DepositPreauth.h index 4e0102952c..003d444bf3 100644 --- a/src/xrpld/app/tx/detail/DepositPreauth.h +++ b/src/xrpld/app/tx/detail/DepositPreauth.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class DepositPreauth : public Transactor { @@ -34,6 +34,6 @@ public: beast::Journal j); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/Escrow.cpp b/src/xrpld/app/tx/detail/Escrow.cpp index e9aad6ad37..4e5f41a427 100644 --- a/src/xrpld/app/tx/detail/Escrow.cpp +++ b/src/xrpld/app/tx/detail/Escrow.cpp @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { // During an EscrowFinish, the transaction must specify both // a condition and a fulfillment. We track whether that @@ -141,7 +141,7 @@ EscrowCreate::preflight(PreflightContext const& ctx) if (auto const cb = ctx.tx[~sfCondition]) { - using namespace ripple::cryptoconditions; + using namespace xrpl::cryptoconditions; std::error_code ec; @@ -546,7 +546,7 @@ EscrowCreate::doApply() static bool checkCondition(Slice f, Slice c) { - using namespace ripple::cryptoconditions; + using namespace xrpl::cryptoconditions; std::error_code ec; @@ -1072,7 +1072,7 @@ EscrowFinish::doApply() return temDISABLED; // LCOV_EXCL_LINE Rate lockedRate = slep->isFieldPresent(sfTransferRate) - ? ripple::Rate(slep->getFieldU32(sfTransferRate)) + ? xrpl::Rate(slep->getFieldU32(sfTransferRate)) : parityRate; auto const issuer = amount.getIssuer(); bool const createAsset = destID == account_; @@ -1321,4 +1321,4 @@ EscrowCancel::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/Escrow.h b/src/xrpld/app/tx/detail/Escrow.h index d2821bc45d..935fb27cd0 100644 --- a/src/xrpld/app/tx/detail/Escrow.h +++ b/src/xrpld/app/tx/detail/Escrow.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class EscrowCreate : public Transactor { @@ -78,6 +78,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/InvariantCheck.cpp b/src/xrpld/app/tx/detail/InvariantCheck.cpp index 27c87e074c..dadc5a7d74 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.cpp +++ b/src/xrpld/app/tx/detail/InvariantCheck.cpp @@ -25,7 +25,7 @@ #include #include -namespace ripple { +namespace xrpl { /* assert(enforce) @@ -525,7 +525,7 @@ AccountRootsDeletedClean::finalize( // assert. XRPL_ASSERT( enforce, - "ripple::AccountRootsDeletedClean::finalize::objectExists : " + "xrpl::AccountRootsDeletedClean::finalize::objectExists : " "account deletion left no objects behind"); return true; } @@ -542,7 +542,7 @@ AccountRootsDeletedClean::finalize( "behind a non-zero balance"; XRPL_ASSERT( enforce, - "ripple::AccountRootsDeletedClean::finalize : " + "xrpl::AccountRootsDeletedClean::finalize : " "deleted account has zero balance"); if (enforce) return false; @@ -554,7 +554,7 @@ AccountRootsDeletedClean::finalize( "behind a non-zero owner count"; XRPL_ASSERT( enforce, - "ripple::AccountRootsDeletedClean::finalize : " + "xrpl::AccountRootsDeletedClean::finalize : " "deleted account has zero owner count"); if (enforce) return false; @@ -796,7 +796,7 @@ TransfersNotFrozen::finalize( // assert. XRPL_ASSERT( enforce, - "ripple::TransfersNotFrozen::finalize : enforce " + "xrpl::TransfersNotFrozen::finalize : enforce " "invariant."); if (enforce) { @@ -820,8 +820,7 @@ TransfersNotFrozen::isValidEntry( std::shared_ptr const& after) { // `after` can never be null, even if the trust line is deleted. - XRPL_ASSERT( - after, "ripple::TransfersNotFrozen::isValidEntry : valid after."); + XRPL_ASSERT(after, "xrpl::TransfersNotFrozen::isValidEntry : valid after."); if (!after) { return false; @@ -877,7 +876,7 @@ TransfersNotFrozen::recordBalance(Issue const& issue, BalanceChange change) { XRPL_ASSERT( change.balanceChangeSign, - "ripple::TransfersNotFrozen::recordBalance : valid trustline " + "xrpl::TransfersNotFrozen::recordBalance : valid trustline " "balance sign."); auto& changes = balanceChanges_[issue]; if (change.balanceChangeSign < 0) @@ -996,7 +995,7 @@ TransfersNotFrozen::validateFrozenState( // The comment above starting with "assert(enforce)" explains this assert. XRPL_ASSERT( enforce, - "ripple::TransfersNotFrozen::validateFrozenState : enforce " + "xrpl::TransfersNotFrozen::validateFrozenState : enforce " "invariant."); if (enforce) @@ -1084,7 +1083,7 @@ ValidNewAccountRoot::finalize( JLOG(j.fatal()) << "Invariant failed: account root created illegally"; return false; -} // namespace ripple +} // namespace xrpl //------------------------------------------------------------------------------ @@ -1486,7 +1485,7 @@ ValidMPTIssuance::finalize( // assert. XRPL_ASSERT_PARTS( enforceCreatedByIssuer, - "ripple::ValidMPTIssuance::finalize", + "xrpl::ValidMPTIssuance::finalize", "no issuer MPToken"); if (enforceCreatedByIssuer) return false; @@ -1598,7 +1597,7 @@ ValidMPTIssuance::finalize( // non-amendment-gated side effects. XRPL_ASSERT_PARTS( !enforceEscrowFinish, - "ripple::ValidMPTIssuance::finalize", + "xrpl::ValidMPTIssuance::finalize", "not escrow finish tx"); return true; } @@ -1811,7 +1810,7 @@ ValidPseudoAccounts::finalize( bool const enforce = view.rules().enabled(featureSingleAssetVault); XRPL_ASSERT( errors_.empty() || enforce, - "ripple::ValidPseudoAccounts::finalize : no bad " + "xrpl::ValidPseudoAccounts::finalize : no bad " "changes or enforce invariant"); if (!errors_.empty()) { @@ -2089,8 +2088,8 @@ ValidAMM::finalizeDEX(bool enforce, beast::Journal const& j) const bool ValidAMM::generalInvariant( - ripple::STTx const& tx, - ripple::ReadView const& view, + xrpl::STTx const& tx, + xrpl::ReadView const& view, ZeroAllowed zeroAllowed, beast::Journal const& j) const { @@ -2135,8 +2134,8 @@ ValidAMM::generalInvariant( bool ValidAMM::finalizeDeposit( - ripple::STTx const& tx, - ripple::ReadView const& view, + xrpl::STTx const& tx, + xrpl::ReadView const& view, bool enforce, beast::Journal const& j) const { @@ -2156,8 +2155,8 @@ ValidAMM::finalizeDeposit( bool ValidAMM::finalizeWithdraw( - ripple::STTx const& tx, - ripple::ReadView const& view, + xrpl::STTx const& tx, + xrpl::ReadView const& view, bool enforce, beast::Journal const& j) const { @@ -2317,7 +2316,7 @@ NoModifiedUnmodifiableFields::finalize( } XRPL_ASSERT( !bad || enforce, - "ripple::NoModifiedUnmodifiableFields::finalize : no bad " + "xrpl::NoModifiedUnmodifiableFields::finalize : no bad " "changes or enforce invariant"); if (bad) { @@ -2657,7 +2656,7 @@ ValidVault::visitEntry( // `isDelete` indicates whether an object is being deleted or modified. XRPL_ASSERT( after != nullptr && (before != nullptr || !isDelete), - "ripple::ValidVault::visitEntry : some object is available"); + "xrpl::ValidVault::visitEntry : some object is available"); // Number balanceDelta will capture the difference (delta) between "before" // state (zero if created) and "after" state (zero if destroyed), so the @@ -2755,7 +2754,7 @@ ValidVault::finalize( "Invariant failed: vault operation succeeded without modifying " "a vault"; XRPL_ASSERT( - enforce, "ripple::ValidVault::finalize : vault noop invariant"); + enforce, "xrpl::ValidVault::finalize : vault noop invariant"); return !enforce; } @@ -2768,7 +2767,7 @@ ValidVault::finalize( "Invariant failed: vault updated by a wrong transaction type"; XRPL_ASSERT( enforce, - "ripple::ValidVault::finalize : illegal vault transaction " + "xrpl::ValidVault::finalize : illegal vault transaction " "invariant"); return !enforce; // Also not a vault operation } @@ -2778,7 +2777,7 @@ ValidVault::finalize( JLOG(j.fatal()) << // "Invariant failed: vault operation updated more than single vault"; XRPL_ASSERT( - enforce, "ripple::ValidVault::finalize : single vault invariant"); + enforce, "xrpl::ValidVault::finalize : single vault invariant"); return !enforce; // That's all we can do here } @@ -2794,7 +2793,7 @@ ValidVault::finalize( "Invariant failed: vault deleted by a wrong transaction type"; XRPL_ASSERT( enforce, - "ripple::ValidVault::finalize : illegal vault deletion " + "xrpl::ValidVault::finalize : illegal vault deletion " "invariant"); return !enforce; // That's all we can do here } @@ -2821,7 +2820,7 @@ ValidVault::finalize( "delete shares"; XRPL_ASSERT( enforce, - "ripple::ValidVault::finalize : shares deletion invariant"); + "xrpl::ValidVault::finalize : shares deletion invariant"); return !enforce; // That's all we can do here } @@ -2852,7 +2851,7 @@ ValidVault::finalize( JLOG(j.fatal()) << "Invariant failed: vault deletion succeeded without " "deleting a vault"; XRPL_ASSERT( - enforce, "ripple::ValidVault::finalize : vault deletion invariant"); + enforce, "xrpl::ValidVault::finalize : vault deletion invariant"); return !enforce; // That's all we can do here } @@ -2860,7 +2859,7 @@ ValidVault::finalize( auto const& afterVault = afterVault_[0]; XRPL_ASSERT( beforeVault_.empty() || beforeVault_[0].key == afterVault.key, - "ripple::ValidVault::finalize : single vault operation"); + "xrpl::ValidVault::finalize : single vault operation"); auto const updatedShares = [&]() -> std::optional { // At this moment we only know that a vault is being updated and there @@ -2901,8 +2900,7 @@ ValidVault::finalize( { JLOG(j.fatal()) << "Invariant failed: updated vault must have shares"; XRPL_ASSERT( - enforce, - "ripple::ValidVault::finalize : vault has shares invariant"); + enforce, "xrpl::ValidVault::finalize : vault has shares invariant"); return !enforce; // That's all we can do here } @@ -2972,7 +2970,7 @@ ValidVault::finalize( JLOG(j.fatal()) << // "Invariant failed: vault created by a wrong transaction type"; XRPL_ASSERT( - enforce, "ripple::ValidVault::finalize : vault creation invariant"); + enforce, "xrpl::ValidVault::finalize : vault creation invariant"); return !enforce; // That's all we can do here } @@ -3007,7 +3005,7 @@ ValidVault::finalize( JLOG(j.fatal()) << "Invariant failed: vault operation succeeded " "without updating shares"; XRPL_ASSERT( - enforce, "ripple::ValidVault::finalize : shares noop invariant"); + enforce, "xrpl::ValidVault::finalize : shares noop invariant"); return !enforce; // That's all we can do here } @@ -3137,7 +3135,7 @@ ValidVault::finalize( XRPL_ASSERT( !beforeVault_.empty(), - "ripple::ValidVault::finalize : set updated a vault"); + "xrpl::ValidVault::finalize : set updated a vault"); auto const& beforeVault = beforeVault_[0]; auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId); @@ -3189,7 +3187,7 @@ ValidVault::finalize( XRPL_ASSERT( !beforeVault_.empty(), - "ripple::ValidVault::finalize : deposit updated a vault"); + "xrpl::ValidVault::finalize : deposit updated a vault"); auto const& beforeVault = beforeVault_[0]; auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId); @@ -3316,7 +3314,7 @@ ValidVault::finalize( XRPL_ASSERT( !beforeVault_.empty(), - "ripple::ValidVault::finalize : withdrawal updated a " + "xrpl::ValidVault::finalize : withdrawal updated a " "vault"); auto const& beforeVault = beforeVault_[0]; @@ -3444,7 +3442,7 @@ ValidVault::finalize( XRPL_ASSERT( !beforeVault_.empty(), - "ripple::ValidVault::finalize : clawback updated a vault"); + "xrpl::ValidVault::finalize : clawback updated a vault"); auto const& beforeVault = beforeVault_[0]; if (vaultAsset.native() || @@ -3536,7 +3534,7 @@ ValidVault::finalize( default: // LCOV_EXCL_START UNREACHABLE( - "ripple::ValidVault::finalize : unknown transaction type"); + "xrpl::ValidVault::finalize : unknown transaction type"); return false; // LCOV_EXCL_STOP } @@ -3546,11 +3544,11 @@ ValidVault::finalize( { // The comment at the top of this file starting with "assert(enforce)" // explains this assert. - XRPL_ASSERT(enforce, "ripple::ValidVault::finalize : vault invariants"); + XRPL_ASSERT(enforce, "xrpl::ValidVault::finalize : vault invariants"); return !enforce; } return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/InvariantCheck.h b/src/xrpld/app/tx/detail/InvariantCheck.h index 09a84b1ab4..b7f91a1c46 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.h +++ b/src/xrpld/app/tx/detail/InvariantCheck.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { class ReadView; @@ -935,7 +935,7 @@ using InvariantChecks = std::tuple< * @return std::tuple of instances that implement the required invariant check * methods * - * @see ripple::InvariantChecker_PROTOTYPE + * @see xrpl::InvariantChecker_PROTOTYPE */ inline InvariantChecks getInvariantChecks() @@ -943,6 +943,6 @@ getInvariantChecks() return InvariantChecks{}; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LedgerStateFix.cpp b/src/xrpld/app/tx/detail/LedgerStateFix.cpp index ba750152e7..43001e2fbf 100644 --- a/src/xrpld/app/tx/detail/LedgerStateFix.cpp +++ b/src/xrpld/app/tx/detail/LedgerStateFix.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC LedgerStateFix::preflight(PreflightContext const& ctx) @@ -67,4 +67,4 @@ LedgerStateFix::doApply() return tecINTERNAL; // LCOV_EXCL_LINE } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LedgerStateFix.h b/src/xrpld/app/tx/detail/LedgerStateFix.h index 92f6a22303..e1a7f85ecc 100644 --- a/src/xrpld/app/tx/detail/LedgerStateFix.h +++ b/src/xrpld/app/tx/detail/LedgerStateFix.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LedgerStateFix : public Transactor { @@ -31,6 +31,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp index 26e978697c..32c8fecf20 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp @@ -2,7 +2,7 @@ // #include -namespace ripple { +namespace xrpl { bool LoanBrokerCoverClawback::checkExtraFeatures(PreflightContext const& ctx) @@ -337,4 +337,4 @@ LoanBrokerCoverClawback::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.h b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.h index 183d3c4479..3c4f997d95 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.h +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LoanBrokerCoverClawback : public Transactor { @@ -29,6 +29,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp index 4e9e0e9c05..c894df2c2b 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp @@ -2,7 +2,7 @@ // #include -namespace ripple { +namespace xrpl { bool LoanBrokerCoverDeposit::checkExtraFeatures(PreflightContext const& ctx) @@ -120,4 +120,4 @@ LoanBrokerCoverDeposit::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.h b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.h index 23863b479c..d2f17b1f1c 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.h +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LoanBrokerCoverDeposit : public Transactor { @@ -29,6 +29,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp index 1fd5a1a471..4c0b3e9af5 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { bool LoanBrokerCoverWithdraw::checkExtraFeatures(PreflightContext const& ctx) @@ -170,4 +170,4 @@ LoanBrokerCoverWithdraw::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h index eab2c9e60f..e0a9a2e51b 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LoanBrokerCoverWithdraw : public Transactor { @@ -29,6 +29,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp b/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp index f3dd781bb5..76773037fa 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp @@ -2,7 +2,7 @@ // #include -namespace ripple { +namespace xrpl { bool LoanBrokerDelete::checkExtraFeatures(PreflightContext const& ctx) @@ -194,4 +194,4 @@ LoanBrokerDelete::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanBrokerDelete.h b/src/xrpld/app/tx/detail/LoanBrokerDelete.h index 8466fe4f95..aaea2af81a 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerDelete.h +++ b/src/xrpld/app/tx/detail/LoanBrokerDelete.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LoanBrokerDelete : public Transactor { @@ -29,6 +29,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanBrokerSet.cpp b/src/xrpld/app/tx/detail/LoanBrokerSet.cpp index c2e6effd7a..7b12a6cf39 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerSet.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerSet.cpp @@ -2,7 +2,7 @@ // #include -namespace ripple { +namespace xrpl { bool LoanBrokerSet::checkExtraFeatures(PreflightContext const& ctx) @@ -212,4 +212,4 @@ LoanBrokerSet::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanBrokerSet.h b/src/xrpld/app/tx/detail/LoanBrokerSet.h index 39ed9bcd61..625c0adeb2 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerSet.h +++ b/src/xrpld/app/tx/detail/LoanBrokerSet.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LoanBrokerSet : public Transactor { @@ -29,6 +29,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanDelete.cpp b/src/xrpld/app/tx/detail/LoanDelete.cpp index 87ff4d594b..659f0bba8b 100644 --- a/src/xrpld/app/tx/detail/LoanDelete.cpp +++ b/src/xrpld/app/tx/detail/LoanDelete.cpp @@ -2,7 +2,7 @@ // #include -namespace ripple { +namespace xrpl { bool LoanDelete::checkExtraFeatures(PreflightContext const& ctx) @@ -117,7 +117,7 @@ LoanDelete::doApply() debtTotalProxy, getVaultScale(vaultSle), Number::towards_zero) == beast::zero, - "ripple::LoanDelete::doApply", + "xrpl::LoanDelete::doApply", "last loan, remaining debt rounds to zero"); debtTotalProxy = 0; } @@ -130,4 +130,4 @@ LoanDelete::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanDelete.h b/src/xrpld/app/tx/detail/LoanDelete.h index cbc37dec14..a1ebad340c 100644 --- a/src/xrpld/app/tx/detail/LoanDelete.h +++ b/src/xrpld/app/tx/detail/LoanDelete.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LoanDelete : public Transactor { @@ -29,6 +29,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanManage.cpp b/src/xrpld/app/tx/detail/LoanManage.cpp index adf08d71bf..2d405f204b 100644 --- a/src/xrpld/app/tx/detail/LoanManage.cpp +++ b/src/xrpld/app/tx/detail/LoanManage.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { bool LoanManage::checkExtraFeatures(PreflightContext const& ctx) @@ -417,4 +417,4 @@ LoanManage::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanManage.h b/src/xrpld/app/tx/detail/LoanManage.h index dde1023cad..7a02c7a16f 100644 --- a/src/xrpld/app/tx/detail/LoanManage.h +++ b/src/xrpld/app/tx/detail/LoanManage.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LoanManage : public Transactor { @@ -61,6 +61,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanPay.cpp b/src/xrpld/app/tx/detail/LoanPay.cpp index 43f19743a7..d34a766d70 100644 --- a/src/xrpld/app/tx/detail/LoanPay.cpp +++ b/src/xrpld/app/tx/detail/LoanPay.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { bool LoanPay::checkExtraFeatures(PreflightContext const& ctx) @@ -326,7 +326,7 @@ LoanPay::doApply() { XRPL_ASSERT_PARTS( paymentParts.error(), - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "payment error is an error"); return paymentParts.error(); } @@ -338,22 +338,20 @@ LoanPay::doApply() XRPL_ASSERT_PARTS( // It is possible to pay 0 principal paymentParts->principalPaid >= 0, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "valid principal paid"); XRPL_ASSERT_PARTS( // It is possible to pay 0 interest paymentParts->interestPaid >= 0, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "valid interest paid"); XRPL_ASSERT_PARTS( // It should not be possible to pay 0 total paymentParts->principalPaid + paymentParts->interestPaid > 0, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "valid total paid"); XRPL_ASSERT_PARTS( - paymentParts->feePaid >= 0, - "ripple::LoanPay::doApply", - "valid fee paid"); + paymentParts->feePaid >= 0, "xrpl::LoanPay::doApply", "valid fee paid"); if (paymentParts->principalPaid < 0 || paymentParts->interestPaid < 0 || paymentParts->feePaid < 0) @@ -387,7 +385,7 @@ LoanPay::doApply() roundToAsset(asset, totalPaidToVaultRaw, vaultScale, Number::downward); XRPL_ASSERT_PARTS( !asset.integral() || totalPaidToVaultRaw == totalPaidToVaultRounded, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "rounding does nothing for integral asset"); // Account for value changes when reducing the broker's debt: // - Positive value change (from full/late/overpayments): Subtract from the @@ -403,7 +401,7 @@ LoanPay::doApply() (totalPaidToVaultRaw + totalPaidToBroker) == (paymentParts->principalPaid + paymentParts->interestPaid + paymentParts->feePaid), - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "payments add up"); // Decrease LoanBroker Debt by the amount paid, add the Loan value change @@ -411,7 +409,7 @@ LoanPay::doApply() // increasing the debt XRPL_ASSERT_PARTS( isRounded(asset, totalPaidToVaultForDebt, loanScale), - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "totalPaidToVaultForDebt rounding good"); // Despite our best efforts, it's possible for rounding errors to accumulate // in the loan broker's debt total. This is because the broker may have more @@ -435,7 +433,7 @@ LoanPay::doApply() { XRPL_ASSERT_PARTS( assetsAvailableBefore == pseudoAccountBalanceBefore, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "vault pseudo balance agrees before"); assetsAvailableProxy += totalPaidToVaultRounded; @@ -443,7 +441,7 @@ LoanPay::doApply() XRPL_ASSERT_PARTS( *assetsAvailableProxy <= *assetsTotalProxy, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "assets available must not be greater than assets outstanding"); if (*assetsAvailableProxy > *assetsTotalProxy) @@ -463,7 +461,7 @@ LoanPay::doApply() // Move funds XRPL_ASSERT_PARTS( totalPaidToVaultRounded + totalPaidToBroker <= amount, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "amount is sufficient"); if (!sendBrokerFeeToOwner) @@ -541,7 +539,7 @@ LoanPay::doApply() j_); XRPL_ASSERT_PARTS( assetsAvailableAfter == pseudoAccountBalanceAfter, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "vault pseudo balance agrees after"); #if !NDEBUG @@ -564,33 +562,33 @@ LoanPay::doApply() XRPL_ASSERT_PARTS( accountBalanceBefore + vaultBalanceBefore + brokerBalanceBefore == accountBalanceAfter + vaultBalanceAfter + brokerBalanceAfter, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "funds are conserved (with rounding)"); XRPL_ASSERT_PARTS( accountBalanceAfter >= beast::zero, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "positive account balance"); XRPL_ASSERT_PARTS( accountBalanceAfter < accountBalanceBefore || account_ == asset.getIssuer(), - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "account balance decreased"); XRPL_ASSERT_PARTS( vaultBalanceAfter >= beast::zero && brokerBalanceAfter >= beast::zero, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "positive vault and broker balances"); XRPL_ASSERT_PARTS( vaultBalanceAfter >= vaultBalanceBefore, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "vault balance did not decrease"); XRPL_ASSERT_PARTS( brokerBalanceAfter >= brokerBalanceBefore, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "broker balance did not decrease"); XRPL_ASSERT_PARTS( vaultBalanceAfter > vaultBalanceBefore || brokerBalanceAfter > brokerBalanceBefore, - "ripple::LoanPay::doApply", + "xrpl::LoanPay::doApply", "vault and/or broker balance increased"); #endif @@ -599,4 +597,4 @@ LoanPay::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanPay.h b/src/xrpld/app/tx/detail/LoanPay.h index 3f8eb16d04..f951fdad5f 100644 --- a/src/xrpld/app/tx/detail/LoanPay.h +++ b/src/xrpld/app/tx/detail/LoanPay.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class LoanPay : public Transactor { @@ -35,6 +35,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/LoanSet.cpp b/src/xrpld/app/tx/detail/LoanSet.cpp index 756ea53fc1..e8fe76a48f 100644 --- a/src/xrpld/app/tx/detail/LoanSet.cpp +++ b/src/xrpld/app/tx/detail/LoanSet.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { bool LoanSet::checkExtraFeatures(PreflightContext const& ctx) @@ -50,8 +50,8 @@ LoanSet::preflight(PreflightContext const& ctx) if (counterPartySig) { - if (auto const ret = ripple::detail::preflightCheckSigningKey( - *counterPartySig, ctx.j)) + if (auto const ret = + xrpl::detail::preflightCheckSigningKey(*counterPartySig, ctx.j)) return ret; } @@ -97,7 +97,7 @@ LoanSet::preflight(PreflightContext const& ctx) // Copied from preflight2 if (counterPartySig) { - if (auto const ret = ripple::detail::preflightCheckSimulateKeys( + if (auto const ret = xrpl::detail::preflightCheckSimulateKeys( ctx.flags, *counterPartySig, ctx.j)) return *ret; } @@ -496,7 +496,7 @@ LoanSet::doApply() XRPL_ASSERT_PARTS( borrower == account_ || borrower == counterparty, - "ripple::LoanSet::doApply", + "xrpl::LoanSet::doApply", "borrower signed transaction"); if (auto const ter = addEmptyHolding( view, @@ -521,7 +521,7 @@ LoanSet::doApply() // The owner may have deleted their MPT / line at some point. XRPL_ASSERT_PARTS( brokerOwner == account_ || brokerOwner == counterparty, - "ripple::LoanSet::doApply", + "xrpl::LoanSet::doApply", "broker owner signed transaction"); if (auto const ter = addEmptyHolding( @@ -600,7 +600,7 @@ LoanSet::doApply() vaultTotalProxy += state.interestDue; XRPL_ASSERT_PARTS( *vaultAvailableProxy <= *vaultTotalProxy, - "ripple::LoanSet::doApply", + "xrpl::LoanSet::doApply", "assets available must not be greater than assets outstanding"); view.update(vaultSle); @@ -629,4 +629,4 @@ LoanSet::doApply() //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/LoanSet.h b/src/xrpld/app/tx/detail/LoanSet.h index 91f3960891..d3853fbbdd 100644 --- a/src/xrpld/app/tx/detail/LoanSet.h +++ b/src/xrpld/app/tx/detail/LoanSet.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { class LoanSet : public Transactor { @@ -54,6 +54,6 @@ public: //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/MPTokenAuthorize.cpp b/src/xrpld/app/tx/detail/MPTokenAuthorize.cpp index b6eaacb372..a563849a0b 100644 --- a/src/xrpld/app/tx/detail/MPTokenAuthorize.cpp +++ b/src/xrpld/app/tx/detail/MPTokenAuthorize.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { std::uint32_t MPTokenAuthorize::getFlagsMask(PreflightContext const& ctx) @@ -174,4 +174,4 @@ MPTokenAuthorize::doApply() tx[~sfHolder]); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/MPTokenAuthorize.h b/src/xrpld/app/tx/detail/MPTokenAuthorize.h index 0bac2f1843..6c0ade324c 100644 --- a/src/xrpld/app/tx/detail/MPTokenAuthorize.h +++ b/src/xrpld/app/tx/detail/MPTokenAuthorize.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { struct MPTAuthorizeArgs { @@ -43,6 +43,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp b/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp index 05b1720d3d..913c7cf53c 100644 --- a/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp +++ b/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { bool MPTokenIssuanceCreate::checkExtraFeatures(PreflightContext const& ctx) @@ -161,4 +161,4 @@ MPTokenIssuanceCreate::doApply() return result ? tesSUCCESS : result.error(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.h b/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.h index bff41c9180..5b5268265c 100644 --- a/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.h +++ b/src/xrpld/app/tx/detail/MPTokenIssuanceCreate.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { struct MPTCreateArgs { @@ -47,6 +47,6 @@ public: create(ApplyView& view, beast::Journal journal, MPTCreateArgs const& args); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.cpp b/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.cpp index 5b20a5a4b3..58b3cbea4f 100644 --- a/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.cpp +++ b/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { std::uint32_t MPTokenIssuanceDestroy::getFlagsMask(PreflightContext const& ctx) @@ -60,4 +60,4 @@ MPTokenIssuanceDestroy::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.h b/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.h index a764ecc652..5f59c9b1bd 100644 --- a/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.h +++ b/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class MPTokenIssuanceDestroy : public Transactor { @@ -27,6 +27,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/MPTokenIssuanceSet.cpp b/src/xrpld/app/tx/detail/MPTokenIssuanceSet.cpp index d46a7a2add..578e5f6564 100644 --- a/src/xrpld/app/tx/detail/MPTokenIssuanceSet.cpp +++ b/src/xrpld/app/tx/detail/MPTokenIssuanceSet.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { bool MPTokenIssuanceSet::checkExtraFeatures(PreflightContext const& ctx) @@ -337,4 +337,4 @@ MPTokenIssuanceSet::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/MPTokenIssuanceSet.h b/src/xrpld/app/tx/detail/MPTokenIssuanceSet.h index bc5d390f97..a687a37b47 100644 --- a/src/xrpld/app/tx/detail/MPTokenIssuanceSet.h +++ b/src/xrpld/app/tx/detail/MPTokenIssuanceSet.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class MPTokenIssuanceSet : public Transactor { @@ -33,6 +33,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/NFTokenAcceptOffer.cpp b/src/xrpld/app/tx/detail/NFTokenAcceptOffer.cpp index 2af0abfdac..f3205f6df3 100644 --- a/src/xrpld/app/tx/detail/NFTokenAcceptOffer.cpp +++ b/src/xrpld/app/tx/detail/NFTokenAcceptOffer.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { std::uint32_t NFTokenAcceptOffer::getFlagsMask(PreflightContext const& ctx) @@ -551,4 +551,4 @@ NFTokenAcceptOffer::doApply() return tecINTERNAL; // LCOV_EXCL_LINE } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/NFTokenAcceptOffer.h b/src/xrpld/app/tx/detail/NFTokenAcceptOffer.h index 4bc429fcfc..83cd71b734 100644 --- a/src/xrpld/app/tx/detail/NFTokenAcceptOffer.h +++ b/src/xrpld/app/tx/detail/NFTokenAcceptOffer.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenAcceptOffer : public Transactor { @@ -45,6 +45,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/NFTokenBurn.cpp b/src/xrpld/app/tx/detail/NFTokenBurn.cpp index 1e1d19679b..755e9e52c5 100644 --- a/src/xrpld/app/tx/detail/NFTokenBurn.cpp +++ b/src/xrpld/app/tx/detail/NFTokenBurn.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC NFTokenBurn::preflight(PreflightContext const& ctx) @@ -90,4 +90,4 @@ NFTokenBurn::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/NFTokenBurn.h b/src/xrpld/app/tx/detail/NFTokenBurn.h index 5a3e530c8c..5425f0902d 100644 --- a/src/xrpld/app/tx/detail/NFTokenBurn.h +++ b/src/xrpld/app/tx/detail/NFTokenBurn.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenBurn : public Transactor { @@ -24,6 +24,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/NFTokenCancelOffer.cpp b/src/xrpld/app/tx/detail/NFTokenCancelOffer.cpp index 45b93b64d6..94512b5e66 100644 --- a/src/xrpld/app/tx/detail/NFTokenCancelOffer.cpp +++ b/src/xrpld/app/tx/detail/NFTokenCancelOffer.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { std::uint32_t NFTokenCancelOffer::getFlagsMask(PreflightContext const& ctx) @@ -93,4 +93,4 @@ NFTokenCancelOffer::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/NFTokenCancelOffer.h b/src/xrpld/app/tx/detail/NFTokenCancelOffer.h index 98444e21d8..13a6ecc065 100644 --- a/src/xrpld/app/tx/detail/NFTokenCancelOffer.h +++ b/src/xrpld/app/tx/detail/NFTokenCancelOffer.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenCancelOffer : public Transactor { @@ -27,6 +27,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/NFTokenCreateOffer.cpp b/src/xrpld/app/tx/detail/NFTokenCreateOffer.cpp index 3b8758f25d..00e69ccc9f 100644 --- a/src/xrpld/app/tx/detail/NFTokenCreateOffer.cpp +++ b/src/xrpld/app/tx/detail/NFTokenCreateOffer.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { std::uint32_t NFTokenCreateOffer::getFlagsMask(PreflightContext const& ctx) @@ -82,4 +82,4 @@ NFTokenCreateOffer::doApply() ctx_.tx.getFlags()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/NFTokenCreateOffer.h b/src/xrpld/app/tx/detail/NFTokenCreateOffer.h index 4dd1ff93f1..704b253924 100644 --- a/src/xrpld/app/tx/detail/NFTokenCreateOffer.h +++ b/src/xrpld/app/tx/detail/NFTokenCreateOffer.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenCreateOffer : public Transactor { @@ -27,6 +27,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/NFTokenMint.cpp b/src/xrpld/app/tx/detail/NFTokenMint.cpp index 9a8d828215..fbba92b264 100644 --- a/src/xrpld/app/tx/detail/NFTokenMint.cpp +++ b/src/xrpld/app/tx/detail/NFTokenMint.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { static std::uint16_t extractNFTokenFlagsFromTxFlags(std::uint32_t txFlags) @@ -154,7 +154,7 @@ NFTokenMint::createNFTokenID( ptr += sizeof(tokenSeq); XRPL_ASSERT( std::distance(buf.data(), ptr) == buf.size(), - "ripple::NFTokenMint::createNFTokenID : data size matches the buffer"); + "xrpl::NFTokenMint::createNFTokenID : data size matches the buffer"); return uint256::fromVoid(buf.data()); } @@ -325,4 +325,4 @@ NFTokenMint::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/NFTokenMint.h b/src/xrpld/app/tx/detail/NFTokenMint.h index a4b8fb6fa3..a3b43b8269 100644 --- a/src/xrpld/app/tx/detail/NFTokenMint.h +++ b/src/xrpld/app/tx/detail/NFTokenMint.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenMint : public Transactor { @@ -42,6 +42,6 @@ public: std::uint32_t tokenSeq); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/NFTokenModify.cpp b/src/xrpld/app/tx/detail/NFTokenModify.cpp index 392d837c46..8ecf8de676 100644 --- a/src/xrpld/app/tx/detail/NFTokenModify.cpp +++ b/src/xrpld/app/tx/detail/NFTokenModify.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC NFTokenModify::preflight(PreflightContext const& ctx) @@ -59,4 +59,4 @@ NFTokenModify::doApply() return nft::changeTokenURI(view(), owner, nftokenID, ctx_.tx[~sfURI]); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/NFTokenModify.h b/src/xrpld/app/tx/detail/NFTokenModify.h index 0058b3a8ed..4353c3d58b 100644 --- a/src/xrpld/app/tx/detail/NFTokenModify.h +++ b/src/xrpld/app/tx/detail/NFTokenModify.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class NFTokenModify : public Transactor { @@ -24,6 +24,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/NFTokenUtils.cpp b/src/xrpld/app/tx/detail/NFTokenUtils.cpp index db2b00cb2c..c737855840 100644 --- a/src/xrpld/app/tx/detail/NFTokenUtils.cpp +++ b/src/xrpld/app/tx/detail/NFTokenUtils.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace nft { @@ -167,7 +167,7 @@ getPageForToken( auto np = std::make_shared(keylet::nftpage(base, tokenIDForNewPage)); XRPL_ASSERT( np->key() > base.key, - "ripple::nft::getPageForToken : valid NFT page index"); + "xrpl::nft::getPageForToken : valid NFT page index"); np->setFieldArray(sfNFTokens, narr); np->setFieldH256(sfNextPageMin, cp->key()); @@ -213,7 +213,7 @@ changeTokenURI( ApplyView& view, AccountID const& owner, uint256 const& nftokenID, - std::optional const& uri) + std::optional const& uri) { std::shared_ptr const page = locatePage(view, owner, nftokenID); @@ -247,7 +247,7 @@ insertToken(ApplyView& view, AccountID owner, STObject&& nft) { XRPL_ASSERT( nft.isFieldPresent(sfNFTokenID), - "ripple::nft::insertToken : has NFT token"); + "xrpl::nft::insertToken : has NFT token"); // First, we need to locate the page the NFT belongs to, creating it // if necessary. This operation may fail if it is impossible to insert @@ -789,7 +789,7 @@ repairNFTokenDirectoryLinks(ApplyView& view, AccountID const& owner) XRPL_ASSERT( nextPage, - "ripple::nft::repairNFTokenDirectoryLinks : next page is available"); + "xrpl::nft::repairNFTokenDirectoryLinks : next page is available"); if (nextPage->isFieldPresent(sfNextPageMin)) { didRepair = true; @@ -887,7 +887,7 @@ tokenOfferCreatePreclaim( { auto const root = view.read(keylet::account(nftIssuer)); XRPL_ASSERT( - root, "ripple::nft::tokenOfferCreatePreclaim : non-null account"); + root, "xrpl::nft::tokenOfferCreatePreclaim : non-null account"); if (auto minter = (*root)[~sfNFTokenMinter]; minter != acctID) return tefNFTOKEN_IS_NOT_TRANSFERABLE; @@ -1035,14 +1035,14 @@ checkTrustlineAuthorized( // Only valid for custom currencies XRPL_ASSERT( !isXRP(issue.currency), - "ripple::nft::checkTrustlineAuthorized : valid to check."); + "xrpl::nft::checkTrustlineAuthorized : valid to check."); if (view.rules().enabled(fixEnforceNFTokenTrustlineV2)) { auto const issuerAccount = view.read(keylet::account(issue.account)); if (!issuerAccount) { - JLOG(j.debug()) << "ripple::nft::checkTrustlineAuthorized: can't " + JLOG(j.debug()) << "xrpl::nft::checkTrustlineAuthorized: can't " "receive IOUs from non-existent issuer: " << to_string(issue.account); @@ -1091,14 +1091,14 @@ checkTrustlineDeepFrozen( // Only valid for custom currencies XRPL_ASSERT( !isXRP(issue.currency), - "ripple::nft::checkTrustlineDeepFrozen : valid to check."); + "xrpl::nft::checkTrustlineDeepFrozen : valid to check."); if (view.rules().enabled(featureDeepFreeze)) { auto const issuerAccount = view.read(keylet::account(issue.account)); if (!issuerAccount) { - JLOG(j.debug()) << "ripple::nft::checkTrustlineDeepFrozen: can't " + JLOG(j.debug()) << "xrpl::nft::checkTrustlineDeepFrozen: can't " "receive IOUs from non-existent issuer: " << to_string(issue.account); @@ -1136,4 +1136,4 @@ checkTrustlineDeepFrozen( } } // namespace nft -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/NFTokenUtils.h b/src/xrpld/app/tx/detail/NFTokenUtils.h index 0294724b51..640f12f9d2 100644 --- a/src/xrpld/app/tx/detail/NFTokenUtils.h +++ b/src/xrpld/app/tx/detail/NFTokenUtils.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace nft { @@ -91,7 +91,7 @@ changeTokenURI( ApplyView& view, AccountID const& owner, uint256 const& nftokenID, - std::optional const& uri); + std::optional const& uri); /** Preflight checks shared by NFTokenCreateOffer and NFTokenMint */ NotTEC @@ -149,6 +149,6 @@ checkTrustlineDeepFrozen( } // namespace nft -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_IMPL_DETAILS_NFTOKENUTILS_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/Offer.h b/src/xrpld/app/tx/detail/Offer.h index 64bc3f4cbf..b04049b657 100644 --- a/src/xrpld/app/tx/detail/Offer.h +++ b/src/xrpld/app/tx/detail/Offer.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { template class TOfferBase @@ -208,7 +208,7 @@ TOffer::setFieldAmounts() { // LCOV_EXCL_START #ifdef _MSC_VER - UNREACHABLE("ripple::TOffer::setFieldAmounts : must be specialized"); + UNREACHABLE("xrpl::TOffer::setFieldAmounts : must be specialized"); #else static_assert(sizeof(TOut) == -1, "Must be specialized"); #endif @@ -319,6 +319,6 @@ operator<<(std::ostream& os, TOffer const& offer) return os << offer.id(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/OfferStream.cpp b/src/xrpld/app/tx/detail/OfferStream.cpp index 93a26f71da..49e45976eb 100644 --- a/src/xrpld/app/tx/detail/OfferStream.cpp +++ b/src/xrpld/app/tx/detail/OfferStream.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace { bool @@ -37,7 +37,7 @@ TOfferStreamBase::TOfferStreamBase( , counter_(counter) { XRPL_ASSERT( - validBook_, "ripple::TOfferStreamBase::TOfferStreamBase : valid book"); + validBook_, "xrpl::TOfferStreamBase::TOfferStreamBase : valid book"); } // Handle the case where a directory item with no corresponding ledger entry @@ -403,4 +403,4 @@ template class TOfferStreamBase; template class TOfferStreamBase; template class TOfferStreamBase; template class TOfferStreamBase; -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/OfferStream.h b/src/xrpld/app/tx/detail/OfferStream.h index 3969cfb48f..cab5f1384d 100644 --- a/src/xrpld/app/tx/detail/OfferStream.h +++ b/src/xrpld/app/tx/detail/OfferStream.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { template class TOfferStreamBase @@ -174,6 +174,6 @@ public: return permToRemove_; } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/PayChan.cpp b/src/xrpld/app/tx/detail/PayChan.cpp index 40e760e5f5..163ea802a8 100644 --- a/src/xrpld/app/tx/detail/PayChan.cpp +++ b/src/xrpld/app/tx/detail/PayChan.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { /* PaymentChannel @@ -136,7 +136,7 @@ closeChannel( XRPL_ASSERT( (*slep)[sfAmount] >= (*slep)[sfBalance], - "ripple::closeChannel : minimum channel amount"); + "xrpl::closeChannel : minimum channel amount"); (*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount] - (*slep)[sfBalance]; adjustOwnerCount(view, sle, -1, j); @@ -527,7 +527,7 @@ PayChanClaim::doApply() XRPAmount const reqDelta = reqBalance - chanBalance; XRPL_ASSERT( reqDelta >= beast::zero, - "ripple::PayChanClaim::doApply : minimum balance delta"); + "xrpl::PayChanClaim::doApply : minimum balance delta"); (*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta; ctx_.view().update(sled); ctx_.view().update(slep); @@ -562,4 +562,4 @@ PayChanClaim::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/PayChan.h b/src/xrpld/app/tx/detail/PayChan.h index a68cae49f4..f42e9549b3 100644 --- a/src/xrpld/app/tx/detail/PayChan.h +++ b/src/xrpld/app/tx/detail/PayChan.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class PayChanCreate : public Transactor { @@ -81,6 +81,6 @@ public: using PaymentChannelClaim = PayChanClaim; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/Payment.cpp b/src/xrpld/app/tx/detail/Payment.cpp index 56aeb1b0aa..7a14cecc2d 100644 --- a/src/xrpld/app/tx/detail/Payment.cpp +++ b/src/xrpld/app/tx/detail/Payment.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { TxConsequences Payment::makeTxConsequences(PreflightContext const& ctx) @@ -569,7 +569,7 @@ Payment::doApply() return res; } - XRPL_ASSERT(dstAmount.native(), "ripple::Payment::doApply : amount is XRP"); + XRPL_ASSERT(dstAmount.native(), "xrpl::Payment::doApply : amount is XRP"); // Direct XRP payment. @@ -659,4 +659,4 @@ Payment::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/Payment.h b/src/xrpld/app/tx/detail/Payment.h index f41326ecf6..30c9a9e326 100644 --- a/src/xrpld/app/tx/detail/Payment.h +++ b/src/xrpld/app/tx/detail/Payment.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Payment : public Transactor { @@ -42,6 +42,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/PermissionedDomainDelete.cpp b/src/xrpld/app/tx/detail/PermissionedDomainDelete.cpp index 08bf778065..6301d6f892 100644 --- a/src/xrpld/app/tx/detail/PermissionedDomainDelete.cpp +++ b/src/xrpld/app/tx/detail/PermissionedDomainDelete.cpp @@ -3,7 +3,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC PermissionedDomainDelete::preflight(PreflightContext const& ctx) @@ -26,7 +26,7 @@ PermissionedDomainDelete::preclaim(PreclaimContext const& ctx) XRPL_ASSERT( sleDomain->isFieldPresent(sfOwner) && ctx.tx.isFieldPresent(sfAccount), - "ripple::PermissionedDomainDelete::preclaim : required fields present"); + "xrpl::PermissionedDomainDelete::preclaim : required fields present"); if (sleDomain->getAccountID(sfOwner) != ctx.tx.getAccountID(sfAccount)) return tecNO_PERMISSION; @@ -39,7 +39,7 @@ PermissionedDomainDelete::doApply() { XRPL_ASSERT( ctx_.tx.isFieldPresent(sfDomainID), - "ripple::PermissionedDomainDelete::doApply : required field present"); + "xrpl::PermissionedDomainDelete::doApply : required field present"); auto const slePd = view().peek({ltPERMISSIONED_DOMAIN, ctx_.tx.at(sfDomainID)}); @@ -57,11 +57,11 @@ PermissionedDomainDelete::doApply() auto const ownerSle = view().peek(keylet::account(account_)); XRPL_ASSERT( ownerSle && ownerSle->getFieldU32(sfOwnerCount) > 0, - "ripple::PermissionedDomainDelete::doApply : nonzero owner count"); + "xrpl::PermissionedDomainDelete::doApply : nonzero owner count"); adjustOwnerCount(view(), ownerSle, -1, ctx_.journal); view().erase(slePd); return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/PermissionedDomainDelete.h b/src/xrpld/app/tx/detail/PermissionedDomainDelete.h index 7ea0681279..3ae10a739f 100644 --- a/src/xrpld/app/tx/detail/PermissionedDomainDelete.h +++ b/src/xrpld/app/tx/detail/PermissionedDomainDelete.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class PermissionedDomainDelete : public Transactor { @@ -25,6 +25,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/PermissionedDomainSet.cpp b/src/xrpld/app/tx/detail/PermissionedDomainSet.cpp index d73d9f7322..3417f1fb0a 100644 --- a/src/xrpld/app/tx/detail/PermissionedDomainSet.cpp +++ b/src/xrpld/app/tx/detail/PermissionedDomainSet.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { bool PermissionedDomainSet::checkExtraFeatures(PreflightContext const& ctx) @@ -123,4 +123,4 @@ PermissionedDomainSet::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/PermissionedDomainSet.h b/src/xrpld/app/tx/detail/PermissionedDomainSet.h index 6df3448e10..fde06232a5 100644 --- a/src/xrpld/app/tx/detail/PermissionedDomainSet.h +++ b/src/xrpld/app/tx/detail/PermissionedDomainSet.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class PermissionedDomainSet : public Transactor { @@ -28,6 +28,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/SetAccount.cpp b/src/xrpld/app/tx/detail/SetAccount.cpp index e860eca22d..efdf63042c 100644 --- a/src/xrpld/app/tx/detail/SetAccount.cpp +++ b/src/xrpld/app/tx/detail/SetAccount.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { TxConsequences SetAccount::makeTxConsequences(PreflightContext const& ctx) @@ -640,4 +640,4 @@ SetAccount::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/SetAccount.h b/src/xrpld/app/tx/detail/SetAccount.h index 4c310b7fd1..fb8b4a0ccd 100644 --- a/src/xrpld/app/tx/detail/SetAccount.h +++ b/src/xrpld/app/tx/detail/SetAccount.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { class SetAccount : public Transactor { @@ -37,6 +37,6 @@ public: using AccountSet = SetAccount; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/SetOracle.cpp b/src/xrpld/app/tx/detail/SetOracle.cpp index 453d799b0d..10d40b7859 100644 --- a/src/xrpld/app/tx/detail/SetOracle.cpp +++ b/src/xrpld/app/tx/detail/SetOracle.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { static inline std::pair tokenPairKey(STObject const& pair) @@ -310,4 +310,4 @@ SetOracle::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/SetOracle.h b/src/xrpld/app/tx/detail/SetOracle.h index 5b69d80214..c1c9a3d3fb 100644 --- a/src/xrpld/app/tx/detail/SetOracle.h +++ b/src/xrpld/app/tx/detail/SetOracle.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { /** Price Oracle is a system that acts as a bridge between @@ -35,6 +35,6 @@ public: using OracleSet = SetOracle; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_SETORACLE_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/SetRegularKey.cpp b/src/xrpld/app/tx/detail/SetRegularKey.cpp index 2e8f01b355..ff1dbdf769 100644 --- a/src/xrpld/app/tx/detail/SetRegularKey.cpp +++ b/src/xrpld/app/tx/detail/SetRegularKey.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { XRPAmount SetRegularKey::calculateBaseFee(ReadView const& view, STTx const& tx) @@ -70,4 +70,4 @@ SetRegularKey::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/SetRegularKey.h b/src/xrpld/app/tx/detail/SetRegularKey.h index 97754af63c..735ac522fd 100644 --- a/src/xrpld/app/tx/detail/SetRegularKey.h +++ b/src/xrpld/app/tx/detail/SetRegularKey.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class SetRegularKey : public Transactor { @@ -24,6 +24,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/SetSignerList.cpp b/src/xrpld/app/tx/detail/SetSignerList.cpp index 449e0ff90c..f65c17e303 100644 --- a/src/xrpld/app/tx/detail/SetSignerList.cpp +++ b/src/xrpld/app/tx/detail/SetSignerList.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { // We're prepared for there to be multiple signer lists in the future, // but we don't need them yet. So for the time being we're manually @@ -116,7 +116,7 @@ SetSignerList::doApply() break; } // LCOV_EXCL_START - UNREACHABLE("ripple::SetSignerList::doApply : invalid operation"); + UNREACHABLE("xrpl::SetSignerList::doApply : invalid operation"); return temMALFORMED; // LCOV_EXCL_STOP } @@ -128,10 +128,10 @@ SetSignerList::preCompute() auto result = determineOperation(ctx_.tx, view().flags(), j_); XRPL_ASSERT( std::get<0>(result) == tesSUCCESS, - "ripple::SetSignerList::preCompute : result is tesSUCCESS"); + "xrpl::SetSignerList::preCompute : result is tesSUCCESS"); XRPL_ASSERT( std::get<3>(result) != unknown, - "ripple::SetSignerList::preCompute : result is known operation"); + "xrpl::SetSignerList::preCompute : result is known operation"); quorum_ = std::get<1>(result); signers_ = std::get<2>(result); @@ -162,10 +162,10 @@ signerCountBasedOwnerCountDelta(std::size_t entryCount, Rules const& rules) // We've got a lot of room to grow. XRPL_ASSERT( entryCount >= STTx::minMultiSigners, - "ripple::signerCountBasedOwnerCountDelta : minimum signers"); + "xrpl::signerCountBasedOwnerCountDelta : minimum signers"); XRPL_ASSERT( entryCount <= STTx::maxMultiSigners, - "ripple::signerCountBasedOwnerCountDelta : maximum signers"); + "xrpl::signerCountBasedOwnerCountDelta : maximum signers"); return 2 + static_cast(entryCount); } @@ -257,7 +257,7 @@ SetSignerList::validateQuorumAndSignerEntries( // Make sure there are no duplicate signers. XRPL_ASSERT( std::is_sorted(signers.begin(), signers.end()), - "ripple::SetSignerList::validateQuorumAndSignerEntries : sorted " + "xrpl::SetSignerList::validateQuorumAndSignerEntries : sorted " "signers"); if (std::adjacent_find(signers.begin(), signers.end()) != signers.end()) { @@ -412,4 +412,4 @@ SetSignerList::writeSignersToSLE( ledgerEntry->setFieldArray(sfSignerEntries, toLedger); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/SetSignerList.h b/src/xrpld/app/tx/detail/SetSignerList.h index 2ee9b4806a..f6f63d2b7d 100644 --- a/src/xrpld/app/tx/detail/SetSignerList.h +++ b/src/xrpld/app/tx/detail/SetSignerList.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { /** See the README.md for an overview of the SetSignerList transaction that @@ -79,6 +79,6 @@ private: using SignerListSet = SetSignerList; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/SetTrust.cpp b/src/xrpld/app/tx/detail/SetTrust.cpp index 4e8f20f3ae..77d7e6d9b5 100644 --- a/src/xrpld/app/tx/detail/SetTrust.cpp +++ b/src/xrpld/app/tx/detail/SetTrust.cpp @@ -24,21 +24,19 @@ computeFreezeFlags( { if (bSetFreeze && !bClearFreeze && !bNoFreeze) { - uFlags |= (bHigh ? ripple::lsfHighFreeze : ripple::lsfLowFreeze); + uFlags |= (bHigh ? xrpl::lsfHighFreeze : xrpl::lsfLowFreeze); } else if (bClearFreeze && !bSetFreeze) { - uFlags &= ~(bHigh ? ripple::lsfHighFreeze : ripple::lsfLowFreeze); + uFlags &= ~(bHigh ? xrpl::lsfHighFreeze : xrpl::lsfLowFreeze); } if (bSetDeepFreeze && !bClearDeepFreeze && !bNoFreeze) { - uFlags |= - (bHigh ? ripple::lsfHighDeepFreeze : ripple::lsfLowDeepFreeze); + uFlags |= (bHigh ? xrpl::lsfHighDeepFreeze : xrpl::lsfLowDeepFreeze); } else if (bClearDeepFreeze && !bSetDeepFreeze) { - uFlags &= - ~(bHigh ? ripple::lsfHighDeepFreeze : ripple::lsfLowDeepFreeze); + uFlags &= ~(bHigh ? xrpl::lsfHighDeepFreeze : xrpl::lsfLowDeepFreeze); } return uFlags; @@ -46,7 +44,7 @@ computeFreezeFlags( } // namespace -namespace ripple { +namespace xrpl { std::uint32_t SetTrust::getFlagsMask(PreflightContext const& ctx) @@ -689,4 +687,4 @@ SetTrust::doApply() return terResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/SetTrust.h b/src/xrpld/app/tx/detail/SetTrust.h index 5ae3f2ea23..b5776c6d33 100644 --- a/src/xrpld/app/tx/detail/SetTrust.h +++ b/src/xrpld/app/tx/detail/SetTrust.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { class SetTrust : public Transactor { @@ -34,6 +34,6 @@ public: using TrustSet = SetTrust; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/SignerEntries.cpp b/src/xrpld/app/tx/detail/SignerEntries.cpp index f9bc939190..128cc984e4 100644 --- a/src/xrpld/app/tx/detail/SignerEntries.cpp +++ b/src/xrpld/app/tx/detail/SignerEntries.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { Expected, NotTEC> SignerEntries::deserialize( @@ -48,4 +48,4 @@ SignerEntries::deserialize( return accountVec; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/SignerEntries.h b/src/xrpld/app/tx/detail/SignerEntries.h index f7a7823069..0a66fd33f5 100644 --- a/src/xrpld/app/tx/detail/SignerEntries.h +++ b/src/xrpld/app/tx/detail/SignerEntries.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { // Forward declarations class STObject; @@ -69,6 +69,6 @@ public: std::string_view annotation); }; -} // namespace ripple +} // namespace xrpl #endif // XRPL_TX_IMPL_SIGNER_ENTRIES_H_INCLUDED diff --git a/src/xrpld/app/tx/detail/Transactor.cpp b/src/xrpld/app/tx/detail/Transactor.cpp index 2ddef72c39..7b0cbbbdd4 100644 --- a/src/xrpld/app/tx/detail/Transactor.cpp +++ b/src/xrpld/app/tx/detail/Transactor.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Performs early sanity checks on the txid */ NotTEC @@ -307,7 +307,7 @@ Transactor::calculateOwnerReserveFee(ReadView const& view, STTx const& tx) // condition. XRPL_ASSERT( view.fees().increment > view.fees().base * 100, - "ripple::Transactor::calculateOwnerReserveFee : Owner reserve is " + "xrpl::Transactor::calculateOwnerReserveFee : Owner reserve is " "reasonable"); return view.fees().increment; } @@ -527,7 +527,7 @@ TER Transactor::consumeSeqProxy(SLE::pointer const& sleAccount) { XRPL_ASSERT( - sleAccount, "ripple::Transactor::consumeSeqProxy : non-null account"); + sleAccount, "xrpl::Transactor::consumeSeqProxy : non-null account"); SeqProxy const seqProx = ctx_.tx.getSeqProxy(); if (seqProx.isSeq()) { @@ -609,7 +609,7 @@ Transactor::preCompute() { XRPL_ASSERT( account_ != beast::zero, - "ripple::Transactor::preCompute : nonzero account"); + "xrpl::Transactor::preCompute : nonzero account"); } TER @@ -625,7 +625,7 @@ Transactor::apply() // that allow zero account. XRPL_ASSERT( sle != nullptr || account_ == beast::zero, - "ripple::Transactor::apply : non-null SLE or zero account"); + "xrpl::Transactor::apply : non-null SLE or zero account"); if (sle) { @@ -699,7 +699,7 @@ Transactor::checkSign( // Check Single Sign XRPL_ASSERT( - !pkSigner.empty(), "ripple::Transactor::checkSign : non-empty signer"); + !pkSigner.empty(), "xrpl::Transactor::checkSign : non-empty signer"); if (!publicKeyType(makeSlice(pkSigner))) { @@ -829,10 +829,10 @@ Transactor::checkMultiSign( // presence and defaulted value of the SignerListID field will enable that. XRPL_ASSERT( sleAccountSigners->isFieldPresent(sfSignerListID), - "ripple::Transactor::checkMultiSign : has signer list ID"); + "xrpl::Transactor::checkMultiSign : has signer list ID"); XRPL_ASSERT( sleAccountSigners->getFieldU32(sfSignerListID) == 0, - "ripple::Transactor::checkMultiSign : signer list ID is 0"); + "xrpl::Transactor::checkMultiSign : signer list ID is 0"); auto accountSigners = SignerEntries::deserialize(*sleAccountSigners, j, "ledger"); @@ -888,7 +888,7 @@ Transactor::checkMultiSign( XRPL_ASSERT( (flags & tapDRY_RUN) || !spk.empty(), - "ripple::Transactor::checkMultiSign : non-empty signer or " + "xrpl::Transactor::checkMultiSign : non-empty signer or " "simulation"); AccountID const signingAcctIDFromPubKey = spk.empty() ? txSignerAcctID @@ -1087,7 +1087,7 @@ Transactor::reset(XRPAmount fee) // balance should have already been checked in checkFee / preFlight. XRPL_ASSERT( balance != beast::zero && (!view().open() || balance >= fee), - "ripple::Transactor::reset : valid balance"); + "xrpl::Transactor::reset : valid balance"); // We retry/reject the transaction if the account balance is zero or // we're applying against an open ledger and the balance is less than @@ -1104,7 +1104,7 @@ Transactor::reset(XRPAmount fee) payerSle->setFieldAmount(sfBalance, balance - fee); TER const ter{consumeSeqProxy(txnAcct)}; XRPL_ASSERT( - isTesSuccess(ter), "ripple::Transactor::reset : result is tesSUCCESS"); + isTesSuccess(ter), "xrpl::Transactor::reset : result is tesSUCCESS"); if (isTesSuccess(ter)) { @@ -1149,7 +1149,7 @@ Transactor::operator()() JLOG(j_.info()) << to_string(ctx_.tx.getJson(JsonOptions::none)); JLOG(j_.fatal()) << s2.getJson(JsonOptions::none); UNREACHABLE( - "ripple::Transactor::operator() : transaction serdes mismatch"); + "xrpl::Transactor::operator() : transaction serdes mismatch"); // LCOV_EXCL_STOP } } @@ -1169,7 +1169,7 @@ Transactor::operator()() // and it can't be passed in from a preclaim. XRPL_ASSERT( result != temUNKNOWN, - "ripple::Transactor::operator() : result is not temUNKNOWN"); + "xrpl::Transactor::operator() : result is not temUNKNOWN"); if (auto stream = j_.trace()) stream << "preclaim result: " << transToken(result); @@ -1226,7 +1226,7 @@ Transactor::operator()() { XRPL_ASSERT( before && after, - "ripple::Transactor::operator()::visit : non-null SLE " + "xrpl::Transactor::operator()::visit : non-null SLE " "inputs"); if (doOffers && before && after && (before->getType() == ltOFFER) && @@ -1346,4 +1346,4 @@ Transactor::operator()() return {result, applied, metadata}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/Transactor.h b/src/xrpld/app/tx/detail/Transactor.h index ea3479ee6f..7d24df0a3b 100644 --- a/src/xrpld/app/tx/detail/Transactor.h +++ b/src/xrpld/app/tx/detail/Transactor.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** State information when preflighting a tx. */ struct PreflightContext @@ -247,7 +247,7 @@ protected: @param app The application hosting the server @param baseFee The base fee of a candidate transaction - @see ripple::calculateBaseFee + @see xrpl::calculateBaseFee @param fees Fee settings from the current ledger @param flags Transaction processing fees */ @@ -452,6 +452,6 @@ Transactor::validNumericMinimum( return validNumericMinimum(value, min.value()); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/VaultClawback.cpp b/src/xrpld/app/tx/detail/VaultClawback.cpp index 7c56ca1d60..cc7dec993a 100644 --- a/src/xrpld/app/tx/detail/VaultClawback.cpp +++ b/src/xrpld/app/tx/detail/VaultClawback.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC VaultClawback::preflight(PreflightContext const& ctx) @@ -144,14 +144,14 @@ VaultClawback::doApply() }(); XRPL_ASSERT( amount.asset() == vaultAsset, - "ripple::VaultClawback::doApply : matching asset"); + "xrpl::VaultClawback::doApply : matching asset"); auto assetsAvailable = vault->at(sfAssetsAvailable); auto assetsTotal = vault->at(sfAssetsTotal); [[maybe_unused]] auto const lossUnrealized = vault->at(sfLossUnrealized); XRPL_ASSERT( lossUnrealized <= (assetsTotal - assetsAvailable), - "ripple::VaultClawback::doApply : loss and assets do balance"); + "xrpl::VaultClawback::doApply : loss and assets do balance"); AccountID holder = tx[sfHolder]; MPTIssue const share{mptIssuanceID}; @@ -311,4 +311,4 @@ VaultClawback::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/VaultClawback.h b/src/xrpld/app/tx/detail/VaultClawback.h index 888ecf59bf..80a5f73ad0 100644 --- a/src/xrpld/app/tx/detail/VaultClawback.h +++ b/src/xrpld/app/tx/detail/VaultClawback.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class VaultClawback : public Transactor { @@ -24,6 +24,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/VaultCreate.cpp b/src/xrpld/app/tx/detail/VaultCreate.cpp index d8a2e7bc3b..893a1108fa 100644 --- a/src/xrpld/app/tx/detail/VaultCreate.cpp +++ b/src/xrpld/app/tx/detail/VaultCreate.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { bool VaultCreate::checkExtraFeatures(PreflightContext const& ctx) @@ -233,4 +233,4 @@ VaultCreate::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/VaultCreate.h b/src/xrpld/app/tx/detail/VaultCreate.h index 987bbe7df4..78593eb491 100644 --- a/src/xrpld/app/tx/detail/VaultCreate.h +++ b/src/xrpld/app/tx/detail/VaultCreate.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class VaultCreate : public Transactor { @@ -30,6 +30,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/VaultDelete.cpp b/src/xrpld/app/tx/detail/VaultDelete.cpp index 903b5a83a7..756e7b94e6 100644 --- a/src/xrpld/app/tx/detail/VaultDelete.cpp +++ b/src/xrpld/app/tx/detail/VaultDelete.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC VaultDelete::preflight(PreflightContext const& ctx) @@ -208,4 +208,4 @@ VaultDelete::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/VaultDelete.h b/src/xrpld/app/tx/detail/VaultDelete.h index 1144ebcc36..e7c71b408c 100644 --- a/src/xrpld/app/tx/detail/VaultDelete.h +++ b/src/xrpld/app/tx/detail/VaultDelete.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class VaultDelete : public Transactor { @@ -24,6 +24,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/VaultDeposit.cpp b/src/xrpld/app/tx/detail/VaultDeposit.cpp index aeaf890126..d9471a38f5 100644 --- a/src/xrpld/app/tx/detail/VaultDeposit.cpp +++ b/src/xrpld/app/tx/detail/VaultDeposit.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC VaultDeposit::preflight(PreflightContext const& ctx) @@ -179,7 +179,7 @@ VaultDeposit::doApply() // This follows from the reverse of the outer enclosing if condition XRPL_ASSERT( account_ == vault->at(sfOwner), - "ripple::VaultDeposit::doApply : account is owner"); + "xrpl::VaultDeposit::doApply : account is owner"); if (auto const err = authorizeMPToken( view(), mPriorBalance, // priorBalance @@ -236,7 +236,7 @@ VaultDeposit::doApply() XRPL_ASSERT( sharesCreated.asset() != assetsDeposited.asset(), - "ripple::VaultDeposit::doApply : assets are not shares"); + "xrpl::VaultDeposit::doApply : assets are not shares"); vault->at(sfAssetsTotal) += assetsDeposited; vault->at(sfAssetsAvailable) += assetsDeposited; @@ -287,4 +287,4 @@ VaultDeposit::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/VaultDeposit.h b/src/xrpld/app/tx/detail/VaultDeposit.h index 7d725fe6fe..1fd62b95ff 100644 --- a/src/xrpld/app/tx/detail/VaultDeposit.h +++ b/src/xrpld/app/tx/detail/VaultDeposit.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class VaultDeposit : public Transactor { @@ -24,6 +24,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/VaultSet.cpp b/src/xrpld/app/tx/detail/VaultSet.cpp index 97522dad12..648ac12c3d 100644 --- a/src/xrpld/app/tx/detail/VaultSet.cpp +++ b/src/xrpld/app/tx/detail/VaultSet.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { bool VaultSet::checkExtraFeatures(PreflightContext const& ctx) @@ -175,4 +175,4 @@ VaultSet::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/VaultSet.h b/src/xrpld/app/tx/detail/VaultSet.h index 0db0e0fd13..bfa38e5284 100644 --- a/src/xrpld/app/tx/detail/VaultSet.h +++ b/src/xrpld/app/tx/detail/VaultSet.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class VaultSet : public Transactor { @@ -27,6 +27,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/VaultWithdraw.cpp b/src/xrpld/app/tx/detail/VaultWithdraw.cpp index a3bef88d49..f8b7a1a739 100644 --- a/src/xrpld/app/tx/detail/VaultWithdraw.cpp +++ b/src/xrpld/app/tx/detail/VaultWithdraw.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { NotTEC VaultWithdraw::preflight(PreflightContext const& ctx) @@ -182,7 +182,7 @@ VaultWithdraw::doApply() [[maybe_unused]] auto const lossUnrealized = vault->at(sfLossUnrealized); XRPL_ASSERT( lossUnrealized <= (assetsTotal - assetsAvailable), - "ripple::VaultWithdraw::doApply : loss and assets do balance"); + "xrpl::VaultWithdraw::doApply : loss and assets do balance"); // The vault must have enough assets on hand. The vault may hold assets // that it has already pledged. That is why we look at AssetAvailable @@ -250,4 +250,4 @@ VaultWithdraw::doApply() j_); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/VaultWithdraw.h b/src/xrpld/app/tx/detail/VaultWithdraw.h index 4a6ee3b548..33463831e5 100644 --- a/src/xrpld/app/tx/detail/VaultWithdraw.h +++ b/src/xrpld/app/tx/detail/VaultWithdraw.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class VaultWithdraw : public Transactor { @@ -24,6 +24,6 @@ public: doApply() override; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/XChainBridge.cpp b/src/xrpld/app/tx/detail/XChainBridge.cpp index e555dca0a1..88cc236e0b 100644 --- a/src/xrpld/app/tx/detail/XChainBridge.cpp +++ b/src/xrpld/app/tx/detail/XChainBridge.cpp @@ -27,7 +27,7 @@ #include #include -namespace ripple { +namespace xrpl { /* Bridges connect two independent ledgers: a "locking chain" and an "issuing @@ -206,8 +206,8 @@ claimHelper( { // LCOV_EXCL_START UNREACHABLE( - "ripple::claimHelper : invalid inputs"); // should have already - // been checked + "xrpl::claimHelper : invalid inputs"); // should have already + // been checked continue; // LCOV_EXCL_STOP } @@ -423,7 +423,7 @@ transferHelper( if (amt.native()) { auto const sleSrc = psb.peek(keylet::account(src)); - XRPL_ASSERT(sleSrc, "ripple::transferHelper : non-null source account"); + XRPL_ASSERT(sleSrc, "xrpl::transferHelper : non-null source account"); if (!sleSrc) return tecINTERNAL; // LCOV_EXCL_LINE @@ -2238,4 +2238,4 @@ XChainCreateAccountCommit::doApply() return tesSUCCESS; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/XChainBridge.h b/src/xrpld/app/tx/detail/XChainBridge.h index 8636f4f30e..db1026ebb4 100644 --- a/src/xrpld/app/tx/detail/XChainBridge.h +++ b/src/xrpld/app/tx/detail/XChainBridge.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { constexpr size_t xbridgeMaxAccountCreateClaims = 128; @@ -239,6 +239,6 @@ using XChainAccountCreateCommit = XChainCreateAccountCommit; //------------------------------------------------------------------------------ -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/app/tx/detail/apply.cpp b/src/xrpld/app/tx/detail/apply.cpp index 06be378c2b..5209c46f8f 100644 --- a/src/xrpld/app/tx/detail/apply.cpp +++ b/src/xrpld/app/tx/detail/apply.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // These are the same flags defined as HashRouterFlags::PRIVATE1-4 in // HashRouter.h @@ -267,4 +267,4 @@ applyTransaction( } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/app/tx/detail/applySteps.cpp b/src/xrpld/app/tx/detail/applySteps.cpp index 81a930f562..7f0d971fdc 100644 --- a/src/xrpld/app/tx/detail/applySteps.cpp +++ b/src/xrpld/app/tx/detail/applySteps.cpp @@ -18,7 +18,7 @@ #include -namespace ripple { +namespace xrpl { namespace { @@ -113,7 +113,7 @@ invoke_preflight(PreflightContext const& ctx) // LCOV_EXCL_START JLOG(ctx.j.fatal()) << "Unknown transaction type in preflight: " << e.txnType; - UNREACHABLE("ripple::invoke_preflight : unknown transaction type"); + UNREACHABLE("xrpl::invoke_preflight : unknown transaction type"); return {temUNKNOWN, TxConsequences{temUNKNOWN}}; // LCOV_EXCL_STOP } @@ -177,7 +177,7 @@ invoke_preclaim(PreclaimContext const& ctx) // LCOV_EXCL_START JLOG(ctx.j.fatal()) << "Unknown transaction type in preclaim: " << e.txnType; - UNREACHABLE("ripple::invoke_preclaim : unknown transaction type"); + UNREACHABLE("xrpl::invoke_preclaim : unknown transaction type"); return temUNKNOWN; // LCOV_EXCL_STOP } @@ -211,8 +211,7 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx) catch (UnknownTxnType const& e) { // LCOV_EXCL_START - UNREACHABLE( - "ripple::invoke_calculateBaseFee : unknown transaction type"); + UNREACHABLE("xrpl::invoke_calculateBaseFee : unknown transaction type"); return XRPAmount{0}; // LCOV_EXCL_STOP } @@ -227,7 +226,7 @@ TxConsequences::TxConsequences(NotTEC pfresult) { XRPL_ASSERT( !isTesSuccess(pfresult), - "ripple::TxConsequences::TxConsequences : is not tesSUCCESS"); + "xrpl::TxConsequences::TxConsequences : is not tesSUCCESS"); } TxConsequences::TxConsequences(STTx const& tx) @@ -275,7 +274,7 @@ invoke_apply(ApplyContext& ctx) // LCOV_EXCL_START JLOG(ctx.journal.fatal()) << "Unknown transaction type in apply: " << e.txnType; - UNREACHABLE("ripple::invoke_apply : unknown transaction type"); + UNREACHABLE("xrpl::invoke_apply : unknown transaction type"); return {temUNKNOWN, false}; // LCOV_EXCL_STOP } @@ -426,4 +425,4 @@ doApply(PreclaimResult const& preclaimResult, Application& app, OpenView& view) } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/conditions/Condition.h b/src/xrpld/conditions/Condition.h index ff83f69afe..52a6bcd9bb 100644 --- a/src/xrpld/conditions/Condition.h +++ b/src/xrpld/conditions/Condition.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { enum class Type : std::uint8_t { @@ -94,6 +94,6 @@ operator!=(Condition const& lhs, Condition const& rhs) } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/conditions/Fulfillment.h b/src/xrpld/conditions/Fulfillment.h index 13144288d9..970aed121c 100644 --- a/src/xrpld/conditions/Fulfillment.h +++ b/src/xrpld/conditions/Fulfillment.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { struct Fulfillment @@ -122,6 +122,6 @@ bool validate(Fulfillment const& f, Condition const& c); } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/conditions/detail/Condition.cpp b/src/xrpld/conditions/detail/Condition.cpp index b6ba60e6d5..ebf61dd245 100644 --- a/src/xrpld/conditions/detail/Condition.cpp +++ b/src/xrpld/conditions/detail/Condition.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { namespace detail { @@ -212,4 +212,4 @@ Condition::deserialize(Slice s, std::error_code& ec) } } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/conditions/detail/Fulfillment.cpp b/src/xrpld/conditions/detail/Fulfillment.cpp index e8c5928fcf..9ecaa44ab8 100644 --- a/src/xrpld/conditions/detail/Fulfillment.cpp +++ b/src/xrpld/conditions/detail/Fulfillment.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { bool @@ -130,4 +130,4 @@ Fulfillment::deserialize(Slice s, std::error_code& ec) } } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/conditions/detail/PreimageSha256.h b/src/xrpld/conditions/detail/PreimageSha256.h index 62043f5a45..642a7afdc0 100644 --- a/src/xrpld/conditions/detail/PreimageSha256.h +++ b/src/xrpld/conditions/detail/PreimageSha256.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { class PreimageSha256 final : public Fulfillment @@ -130,6 +130,6 @@ public: }; } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/conditions/detail/error.cpp b/src/xrpld/conditions/detail/error.cpp index fbcd70d009..a74aa79e3f 100644 --- a/src/xrpld/conditions/detail/error.cpp +++ b/src/xrpld/conditions/detail/error.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { namespace detail { @@ -116,4 +116,4 @@ make_error_code(error ev) } } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/conditions/detail/error.h b/src/xrpld/conditions/detail/error.h index bd1f2413f3..65584e974a 100644 --- a/src/xrpld/conditions/detail/error.h +++ b/src/xrpld/conditions/detail/error.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { enum class error { @@ -30,12 +30,12 @@ std::error_code make_error_code(error ev); } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl namespace std { template <> -struct is_error_code_enum +struct is_error_code_enum { explicit is_error_code_enum() = default; diff --git a/src/xrpld/conditions/detail/utils.h b/src/xrpld/conditions/detail/utils.h index b03b393e43..b07b7b29e0 100644 --- a/src/xrpld/conditions/detail/utils.h +++ b/src/xrpld/conditions/detail/utils.h @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { namespace cryptoconditions { // A collection of functions to decode binary blobs @@ -208,6 +208,6 @@ parseInteger(Slice& s, std::size_t count, std::error_code& ec) } // namespace der } // namespace cryptoconditions -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/consensus/Consensus.cpp b/src/xrpld/consensus/Consensus.cpp index 8a0bec236e..b71a36d538 100644 --- a/src/xrpld/consensus/Consensus.cpp +++ b/src/xrpld/consensus/Consensus.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { bool shouldCloseLedger( @@ -250,4 +250,4 @@ checkConsensus( return ConsensusState::No; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/consensus/Consensus.h b/src/xrpld/consensus/Consensus.h index d1aed31870..01d4dfaedf 100644 --- a/src/xrpld/consensus/Consensus.h +++ b/src/xrpld/consensus/Consensus.h @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Determines whether the current ledger should close at this time. @@ -897,7 +897,7 @@ Consensus::gotTxSet( // so this txSet must differ XRPL_ASSERT( id != result_->position.position(), - "ripple::Consensus::gotTxSet : updated transaction set"); + "xrpl::Consensus::gotTxSet : updated transaction set"); bool any = false; for (auto const& [nodeId, peerPos] : currPeerPositions_) { @@ -1047,7 +1047,7 @@ Consensus::handleWrongLedger( CLOG(clog) << "handleWrongLedger. "; XRPL_ASSERT( lgrId != prevLedgerID_ || previousLedger_.id() != lgrId, - "ripple::Consensus::handleWrongLedger : have wrong ledger"); + "xrpl::Consensus::handleWrongLedger : have wrong ledger"); // Stop proposing because we are out of sync leaveConsensus(clog); @@ -1349,7 +1349,7 @@ Consensus::phaseEstablish( { CLOG(clog) << "phaseEstablish. "; // can only establish consensus if we already took a stance - XRPL_ASSERT(result_, "ripple::Consensus::phaseEstablish : result is set"); + XRPL_ASSERT(result_, "xrpl::Consensus::phaseEstablish : result is set"); ++peerUnchangedCounter_; ++establishCounter_; @@ -1415,7 +1415,7 @@ void Consensus::closeLedger(std::unique_ptr const& clog) { // We should not be closing if we already have a position - XRPL_ASSERT(!result_, "ripple::Consensus::closeLedger : result is not set"); + XRPL_ASSERT(!result_, "xrpl::Consensus::closeLedger : result is not set"); phase_ = ConsensusPhase::establish; JLOG(j_.debug()) << "transitioned to ConsensusPhase::establish"; @@ -1474,8 +1474,7 @@ Consensus::updateOurPositions( std::unique_ptr const& clog) { // We must have a position if we are updating it - XRPL_ASSERT( - result_, "ripple::Consensus::updateOurPositions : result is set"); + XRPL_ASSERT(result_, "xrpl::Consensus::updateOurPositions : result is set"); ConsensusParms const& parms = adaptor_.parms(); // Compute a cutoff time @@ -1664,7 +1663,7 @@ Consensus::haveConsensus( std::unique_ptr const& clog) { // Must have a stance if we are checking for consensus - XRPL_ASSERT(result_, "ripple::Consensus::haveConsensus : has result"); + XRPL_ASSERT(result_, "xrpl::Consensus::haveConsensus : has result"); // CHECKME: should possibly count unacquired TX sets as disagreeing int agree = 0, disagree = 0; @@ -1804,7 +1803,7 @@ Consensus::createDisputes( std::unique_ptr const& clog) { // Cannot create disputes without our stance - XRPL_ASSERT(result_, "ripple::Consensus::createDisputes : result is set"); + XRPL_ASSERT(result_, "xrpl::Consensus::createDisputes : result is set"); // Only create disputes if this is a new set auto const emplaced = result_->compares.emplace(o.id()).second; @@ -1835,7 +1834,7 @@ Consensus::createDisputes( XRPL_ASSERT( (inThisSet && result_->txns.find(txId) && !o.find(txId)) || (!inThisSet && !result_->txns.find(txId) && o.find(txId)), - "ripple::Consensus::createDisputes : has disputed transactions"); + "xrpl::Consensus::createDisputes : has disputed transactions"); Tx_t tx = inThisSet ? result_->txns.find(txId) : o.find(txId); auto txID = tx.id(); @@ -1873,7 +1872,7 @@ void Consensus::updateDisputes(NodeID_t const& node, TxSet_t const& other) { // Cannot updateDisputes without our stance - XRPL_ASSERT(result_, "ripple::Consensus::updateDisputes : result is set"); + XRPL_ASSERT(result_, "xrpl::Consensus::updateDisputes : result is set"); // Ensure we have created disputes against this set if we haven't seen // it before @@ -1895,6 +1894,6 @@ Consensus::asCloseTime(NetClock::time_point raw) const return roundCloseTime(raw, closeResolution_); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/consensus/ConsensusParms.h b/src/xrpld/consensus/ConsensusParms.h index 8015c2547b..bd1d866082 100644 --- a/src/xrpld/consensus/ConsensusParms.h +++ b/src/xrpld/consensus/ConsensusParms.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Consensus algorithm parameters @@ -170,7 +170,7 @@ getNeededWeight( // See if enough time has passed to move on to the next. XRPL_ASSERT( nextCutoff.consensusTime >= currentCutoff.consensusTime, - "ripple::getNeededWeight : next state valid"); + "xrpl::getNeededWeight : next state valid"); if (percentTime >= nextCutoff.consensusTime) { return {nextCutoff.consensusPct, currentCutoff.next}; @@ -179,5 +179,5 @@ getNeededWeight( return {currentCutoff.consensusPct, {}}; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/consensus/ConsensusProposal.h b/src/xrpld/consensus/ConsensusProposal.h index 344f87f0db..eadf3565f2 100644 --- a/src/xrpld/consensus/ConsensusProposal.h +++ b/src/xrpld/consensus/ConsensusProposal.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Represents a proposed position taken during a round of consensus. During consensus, peers seek agreement on a set of transactions to @@ -262,5 +262,5 @@ operator==( a.prevLedger() == b.prevLedger() && a.position() == b.position() && a.closeTime() == b.closeTime() && a.seenTime() == b.seenTime(); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/consensus/ConsensusTypes.h b/src/xrpld/consensus/ConsensusTypes.h index b2712f17e7..43fb4021b1 100644 --- a/src/xrpld/consensus/ConsensusTypes.h +++ b/src/xrpld/consensus/ConsensusTypes.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Represents how a node currently participates in Consensus. @@ -200,7 +200,7 @@ struct ConsensusResult { XRPL_ASSERT( txns.id() == position.position(), - "ripple::ConsensusResult : valid inputs"); + "xrpl::ConsensusResult : valid inputs"); } //! The set of transactions consensus agrees go in the ledger @@ -225,6 +225,6 @@ struct ConsensusResult // The number of peers proposing during the round std::size_t proposers = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/consensus/DisputedTx.h b/src/xrpld/consensus/DisputedTx.h index ce15b4b7f3..f4b841c795 100644 --- a/src/xrpld/consensus/DisputedTx.h +++ b/src/xrpld/consensus/DisputedTx.h @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { /** A transaction discovered to be in dispute during consensus. @@ -341,6 +341,6 @@ DisputedTx::getJson() const return ret; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/consensus/LedgerTiming.h b/src/xrpld/consensus/LedgerTiming.h index 869cf1980e..5d6348ffb6 100644 --- a/src/xrpld/consensus/LedgerTiming.h +++ b/src/xrpld/consensus/LedgerTiming.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { /** Possible ledger close time resolutions. @@ -149,5 +149,5 @@ effCloseTime( roundCloseTime(closeTime, resolution), (priorCloseTime + 1s)); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/consensus/LedgerTrie.h b/src/xrpld/consensus/LedgerTrie.h index 0f23a8ffc3..b8382c555f 100644 --- a/src/xrpld/consensus/LedgerTrie.h +++ b/src/xrpld/consensus/LedgerTrie.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { /** The tip of a span of ledger ancestry */ @@ -45,7 +45,7 @@ public: ID ancestor(Seq const& s) const { - XRPL_ASSERT(s <= seq, "ripple::SpanTip::ancestor : valid input"); + XRPL_ASSERT(s <= seq, "xrpl::SpanTip::ancestor : valid input"); return ledger[s]; } @@ -72,7 +72,7 @@ public: { // Require default ledger to be genesis seq XRPL_ASSERT( - ledger_.seq() == start_, "ripple::Span::Span : ledger is genesis"); + ledger_.seq() == start_, "xrpl::Span::Span : ledger is genesis"); } Span(Ledger ledger) @@ -141,7 +141,7 @@ private: : start_{start}, end_{end}, ledger_{l} { // Spans cannot be empty - XRPL_ASSERT(start < end, "ripple::Span::Span : non-empty span input"); + XRPL_ASSERT(start < end, "xrpl::Span::Span : non-empty span input"); } Seq @@ -214,7 +214,7 @@ struct Node [child](std::unique_ptr const& curr) { return curr.get() == child; }); - XRPL_ASSERT(it != children.end(), "ripple::Node::erase : valid input"); + XRPL_ASSERT(it != children.end(), "xrpl::Node::erase : valid input"); std::swap(*it, children.back()); children.pop_back(); } @@ -355,7 +355,7 @@ class LedgerTrie Node* curr = root.get(); // Root is always defined and is in common with all ledgers - XRPL_ASSERT(curr, "ripple::LedgerTrie::find : non-null root"); + XRPL_ASSERT(curr, "xrpl::LedgerTrie::find : non-null root"); Seq pos = curr->span.diff(ledger); bool done = false; @@ -436,7 +436,7 @@ public: auto const [loc, diffSeq] = find(ledger); // There is always a place to insert - XRPL_ASSERT(loc, "ripple::LedgerTrie::insert : valid input ledger"); + XRPL_ASSERT(loc, "xrpl::LedgerTrie::insert : valid input ledger"); // Node from which to start incrementing branchSupport Node* incNode = loc; @@ -473,12 +473,12 @@ public: newNode->children = std::move(loc->children); XRPL_ASSERT( loc->children.empty(), - "ripple::LedgerTrie::insert : moved-from children"); + "xrpl::LedgerTrie::insert : moved-from children"); for (std::unique_ptr& child : newNode->children) child->parent = newNode.get(); // Loc truncates to prefix and newNode is its child - XRPL_ASSERT(prefix, "ripple::LedgerTrie::insert : prefix is set"); + XRPL_ASSERT(prefix, "xrpl::LedgerTrie::insert : prefix is set"); loc->span = *prefix; newNode->parent = loc; loc->children.emplace_back(std::move(newNode)); @@ -533,7 +533,7 @@ public: auto const it = seqSupport.find(ledger.seq()); XRPL_ASSERT( it != seqSupport.end() && it->second >= count, - "ripple::LedgerTrie::remove : valid input ledger"); + "xrpl::LedgerTrie::remove : valid input ledger"); it->second -= count; if (it->second == 0) seqSupport.erase(it->first); @@ -830,5 +830,5 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/consensus/Validations.h b/src/xrpld/consensus/Validations.h index 830d05f188..15b33c89c4 100644 --- a/src/xrpld/consensus/Validations.h +++ b/src/xrpld/consensus/Validations.h @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Timing parameters to control validation staleness and expiration. @@ -418,7 +418,7 @@ private: { XRPL_ASSERT( val.trusted(), - "ripple::Validations::updateTrie : trusted input validation"); + "xrpl::Validations::updateTrie : trusted input validation"); // Clear any prior acquiring ledger for this node if (prior) @@ -698,7 +698,7 @@ public: { std::lock_guard lock{mutex_}; XRPL_ASSERT( - low < high, "ripple::Validations::setSeqToKeep : valid inputs"); + low < high, "xrpl::Validations::setSeqToKeep : valid inputs"); toKeep_ = {low, high}; } @@ -1156,5 +1156,5 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/core/Config.h b/src/xrpld/core/Config.h index f48f2765e3..cfd260787c 100644 --- a/src/xrpld/core/Config.h +++ b/src/xrpld/core/Config.h @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { class Rules; @@ -362,6 +362,6 @@ public: FeeSetup setup_FeeVote(Section const& section); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/core/ConfigSections.h b/src/xrpld/core/ConfigSections.h index 554362edd6..6f8a13a145 100644 --- a/src/xrpld/core/ConfigSections.h +++ b/src/xrpld/core/ConfigSections.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { // VFALCO DEPRECATED in favor of the BasicConfig interface struct ConfigSection @@ -78,6 +78,6 @@ struct ConfigSection #define SECTION_VETO_AMENDMENTS "veto_amendments" #define SECTION_WORKERS "workers" -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/core/DatabaseCon.h b/src/xrpld/core/DatabaseCon.h index b2f400780b..a7fc21bc38 100644 --- a/src/xrpld/core/DatabaseCon.h +++ b/src/xrpld/core/DatabaseCon.h @@ -17,7 +17,7 @@ namespace soci { class session; } -namespace ripple { +namespace xrpl { class LockedSociSession { @@ -83,7 +83,7 @@ public: { XRPL_ASSERT( !useGlobalPragma || globalPragma, - "ripple::DatabaseCon::Setup::commonPragma : consistent global " + "xrpl::DatabaseCon::Setup::commonPragma : consistent global " "pragma"); return useGlobalPragma && globalPragma ? globalPragma.get() : nullptr; @@ -242,6 +242,6 @@ setup_DatabaseCon( Config const& c, std::optional j = std::nullopt); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/core/SociDB.h b/src/xrpld/core/SociDB.h index 7e2c7323d8..fe3c15e26e 100644 --- a/src/xrpld/core/SociDB.h +++ b/src/xrpld/core/SociDB.h @@ -28,7 +28,7 @@ namespace sqlite_api { struct sqlite3; } -namespace ripple { +namespace xrpl { class BasicConfig; @@ -121,7 +121,7 @@ makeCheckpointer( JobQueue&, Logs&); -} // namespace ripple +} // namespace xrpl #if defined(__clang__) #pragma clang diagnostic pop diff --git a/src/xrpld/core/TimeKeeper.h b/src/xrpld/core/TimeKeeper.h index f5c14a67fd..67b389bf94 100644 --- a/src/xrpld/core/TimeKeeper.h +++ b/src/xrpld/core/TimeKeeper.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { /** Manages various times used by the server. */ class TimeKeeper : public beast::abstract_clock @@ -97,6 +97,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/core/detail/Config.cpp b/src/xrpld/core/detail/Config.cpp index 6a49416a45..e6c61e1471 100644 --- a/src/xrpld/core/detail/Config.cpp +++ b/src/xrpld/core/detail/Config.cpp @@ -26,7 +26,7 @@ #if BOOST_OS_WINDOWS #include -namespace ripple { +namespace xrpl { namespace detail { [[nodiscard]] std::uint64_t @@ -39,13 +39,13 @@ getMemorySize() } } // namespace detail -} // namespace ripple +} // namespace xrpl #endif #if BOOST_OS_LINUX #include -namespace ripple { +namespace xrpl { namespace detail { [[nodiscard]] std::uint64_t @@ -58,7 +58,7 @@ getMemorySize() } } // namespace detail -} // namespace ripple +} // namespace xrpl #endif @@ -66,7 +66,7 @@ getMemorySize() #include #include -namespace ripple { +namespace xrpl { namespace detail { [[nodiscard]] std::uint64_t @@ -83,10 +83,10 @@ getMemorySize() } } // namespace detail -} // namespace ripple +} // namespace xrpl #endif -namespace ripple { +namespace xrpl { // clang-format off // The configurable node sizes are "tiny", "small", "medium", "large", "huge" @@ -250,7 +250,7 @@ void Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone) { XRPL_ASSERT( - NODE_SIZE == 0, "ripple::Config::setupControl : node size not set"); + NODE_SIZE == 0, "xrpl::Config::setupControl : node size not set"); QUIET = bQuiet || bSilent; SILENT = bSilent; @@ -273,7 +273,7 @@ Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone) XRPL_ASSERT( ns != threshold.second.end(), - "ripple::Config::setupControl : valid node size"); + "xrpl::Config::setupControl : valid node size"); if (ns != threshold.second.end()) NODE_SIZE = std::distance(threshold.second.begin(), ns); @@ -285,7 +285,7 @@ Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone) } XRPL_ASSERT( - NODE_SIZE <= 4, "ripple::Config::setupControl : node size is set"); + NODE_SIZE <= 4, "xrpl::Config::setupControl : node size is set"); } void @@ -1099,10 +1099,9 @@ Config::getValueFor(SizedItem item, std::optional node) const auto const index = static_cast>(item); XRPL_ASSERT( index < sizedItems.size(), - "ripple::Config::getValueFor : valid index input"); + "xrpl::Config::getValueFor : valid index input"); XRPL_ASSERT( - !node || *node <= 4, - "ripple::Config::getValueFor : unset or valid node"); + !node || *node <= 4, "xrpl::Config::getValueFor : unset or valid node"); return sizedItems.at(index).second.at(node.value_or(NODE_SIZE)); } @@ -1126,4 +1125,4 @@ setup_FeeVote(Section const& section) return setup; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/core/detail/DatabaseCon.cpp b/src/xrpld/core/detail/DatabaseCon.cpp index efff0d8192..35eaf31898 100644 --- a/src/xrpld/core/detail/DatabaseCon.cpp +++ b/src/xrpld/core/detail/DatabaseCon.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { class CheckpointersCollection { @@ -215,7 +215,7 @@ setup_DatabaseCon(Config const& c, std::optional j) } XRPL_ASSERT( result->size() == 3, - "ripple::setup_DatabaseCon::globalPragma : result size is 3"); + "xrpl::setup_DatabaseCon::globalPragma : result size is 3"); return result; }(); } @@ -265,4 +265,4 @@ DatabaseCon::setupCheckpointing(JobQueue* q, Logs& l) checkpointer_ = checkpointers.create(session_, *q, l); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/core/detail/SociDB.cpp b/src/xrpld/core/detail/SociDB.cpp index 65294acc4c..a90e59beed 100644 --- a/src/xrpld/core/detail/SociDB.cpp +++ b/src/xrpld/core/detail/SociDB.cpp @@ -16,7 +16,7 @@ #include -namespace ripple { +namespace xrpl { static auto checkpointPageCount = 1000; @@ -206,7 +206,7 @@ public: { if (auto p = session_.lock()) { - return {ripple::getConnection(*p), p}; + return {xrpl::getConnection(*p), p}; } return {nullptr, std::shared_ptr{}}; } @@ -324,7 +324,7 @@ makeCheckpointer( id, std::move(session), queue, logs); } -} // namespace ripple +} // namespace xrpl #if defined(__clang__) #pragma clang diagnostic pop diff --git a/src/xrpld/overlay/Cluster.h b/src/xrpld/overlay/Cluster.h index ff0a1a97f5..30627f90ae 100644 --- a/src/xrpld/overlay/Cluster.h +++ b/src/xrpld/overlay/Cluster.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { class Cluster { @@ -94,6 +94,6 @@ public: load(Section const& nodes); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/ClusterNode.h b/src/xrpld/overlay/ClusterNode.h index a21f7a3870..03c294c736 100644 --- a/src/xrpld/overlay/ClusterNode.h +++ b/src/xrpld/overlay/ClusterNode.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class ClusterNode { @@ -54,6 +54,6 @@ private: NetClock::time_point mReportTime = {}; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/Compression.h b/src/xrpld/overlay/Compression.h index b13b009dcf..8f9b1e2a14 100644 --- a/src/xrpld/overlay/Compression.h +++ b/src/xrpld/overlay/Compression.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace compression { @@ -37,7 +37,7 @@ decompress( try { if (algorithm == Algorithm::LZ4) - return ripple::compression_algorithms::lz4Decompress( + return xrpl::compression_algorithms::lz4Decompress( in, inSize, decompressed, decompressedSize); else { @@ -46,7 +46,7 @@ decompress( << "decompress: invalid compression algorithm " << static_cast(algorithm); UNREACHABLE( - "ripple::compression::decompress : invalid compression " + "xrpl::compression::decompress : invalid compression " "algorithm"); // LCOV_EXCL_STOP } @@ -77,7 +77,7 @@ compress( try { if (algorithm == Algorithm::LZ4) - return ripple::compression_algorithms::lz4Compress( + return xrpl::compression_algorithms::lz4Compress( in, inSize, std::forward(bf)); else { @@ -85,7 +85,7 @@ compress( JLOG(debugLog().warn()) << "compress: invalid compression algorithm" << static_cast(algorithm); UNREACHABLE( - "ripple::compression::compress : invalid compression " + "xrpl::compression::compress : invalid compression " "algorithm"); // LCOV_EXCL_STOP } @@ -97,6 +97,6 @@ compress( } } // namespace compression -} // namespace ripple +} // namespace xrpl #endif // XRPL_COMPRESSION_H_INCLUDED diff --git a/src/xrpld/overlay/Message.h b/src/xrpld/overlay/Message.h index afa15657f0..f2b021840d 100644 --- a/src/xrpld/overlay/Message.h +++ b/src/xrpld/overlay/Message.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { constexpr std::size_t maximiumMessageSize = megabytes(64); @@ -117,6 +117,6 @@ private: getType(std::uint8_t const* in) const; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/Overlay.h b/src/xrpld/overlay/Overlay.h index 6eaf14b8df..c30d0f5205 100644 --- a/src/xrpld/overlay/Overlay.h +++ b/src/xrpld/overlay/Overlay.h @@ -23,7 +23,7 @@ class context; } // namespace asio } // namespace boost -namespace ripple { +namespace xrpl { /** Manages the set of connected peers. */ class Overlay : public beast::PropertyStream::Source @@ -215,6 +215,6 @@ public: txMetrics() const = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/Peer.h b/src/xrpld/overlay/Peer.h index abe18d48dc..35feb05271 100644 --- a/src/xrpld/overlay/Peer.h +++ b/src/xrpld/overlay/Peer.h @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace Resource { class Charge; @@ -119,6 +119,6 @@ public: txReduceRelayEnabled() const = 0; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/PeerReservationTable.h b/src/xrpld/overlay/PeerReservationTable.h index 1cabbb56f9..9ddf79aca9 100644 --- a/src/xrpld/overlay/PeerReservationTable.h +++ b/src/xrpld/overlay/PeerReservationTable.h @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { class DatabaseCon; @@ -97,6 +97,6 @@ private: std::unordered_set, KeyEqual> table_; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/PeerSet.h b/src/xrpld/overlay/PeerSet.h index f90d1670f4..850ba21c53 100644 --- a/src/xrpld/overlay/PeerSet.h +++ b/src/xrpld/overlay/PeerSet.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Supports data retrieval by managing a set of peers. @@ -73,6 +73,6 @@ make_PeerSetBuilder(Application& app); std::unique_ptr make_DummyPeerSet(Application& app); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/ReduceRelayCommon.h b/src/xrpld/overlay/ReduceRelayCommon.h index 207a279cd6..990e4b51d2 100644 --- a/src/xrpld/overlay/ReduceRelayCommon.h +++ b/src/xrpld/overlay/ReduceRelayCommon.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { // Blog post explaining the rationale behind reduction of flooding gossip // protocol: @@ -41,6 +41,6 @@ static constexpr std::size_t MAX_TX_QUEUE_SIZE = 10000; } // namespace reduce_relay -} // namespace ripple +} // namespace xrpl #endif // XRPL_REDUCERELAYCOMMON_H_INCLUDED diff --git a/src/xrpld/overlay/Slot.h b/src/xrpld/overlay/Slot.h index 388323d3c0..9e717fef9c 100644 --- a/src/xrpld/overlay/Slot.h +++ b/src/xrpld/overlay/Slot.h @@ -20,7 +20,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace reduce_relay { @@ -374,7 +374,7 @@ Slot::update( XRPL_ASSERT( peers_.size() >= maxSelectedPeers_, - "ripple::reduce_relay::Slot::update : minimum peers"); + "xrpl::reduce_relay::Slot::update : minimum peers"); // squelch peers which are not selected and // not already squelched @@ -417,7 +417,7 @@ Slot::getSquelchDuration(std::size_t npeers) JLOG(journal_.warn()) << "getSquelchDuration: unexpected squelch duration " << npeers; } - return seconds{ripple::rand_int(MIN_UNSQUELCH_EXPIRE / 1s, m / 1s)}; + return seconds{xrpl::rand_int(MIN_UNSQUELCH_EXPIRE / 1s, m / 1s)}; } template @@ -821,6 +821,6 @@ Slots::deleteIdlePeers() } // namespace reduce_relay -} // namespace ripple +} // namespace xrpl #endif // XRPL_OVERLAY_SLOT_H_INCLUDED diff --git a/src/xrpld/overlay/Squelch.h b/src/xrpld/overlay/Squelch.h index d935087fbc..486cb0073c 100644 --- a/src/xrpld/overlay/Squelch.h +++ b/src/xrpld/overlay/Squelch.h @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace reduce_relay { @@ -105,6 +105,6 @@ Squelch::expireSquelch(PublicKey const& validator) } // namespace reduce_relay -} // namespace ripple +} // namespace xrpl #endif // XRPL_SQUELCH_H diff --git a/src/xrpld/overlay/detail/Cluster.cpp b/src/xrpld/overlay/detail/Cluster.cpp index f4505116b1..606699b841 100644 --- a/src/xrpld/overlay/detail/Cluster.cpp +++ b/src/xrpld/overlay/detail/Cluster.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { Cluster::Cluster(beast::Journal j) : j_(j) { @@ -114,4 +114,4 @@ Cluster::load(Section const& nodes) return true; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/ConnectAttempt.cpp b/src/xrpld/overlay/detail/ConnectAttempt.cpp index 57565b5c19..bd18d96442 100644 --- a/src/xrpld/overlay/detail/ConnectAttempt.cpp +++ b/src/xrpld/overlay/detail/ConnectAttempt.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { ConnectAttempt::ConnectAttempt( Application& app, @@ -92,7 +92,7 @@ ConnectAttempt::shutdown() { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::ConnectAttempt::shutdown: strand in this thread"); + "xrpl::ConnectAttempt::shutdown: strand in this thread"); if (!socket_.is_open()) return; @@ -108,7 +108,7 @@ ConnectAttempt::tryAsyncShutdown() { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::ConnectAttempt::tryAsyncShutdown : strand in this thread"); + "xrpl::ConnectAttempt::tryAsyncShutdown : strand in this thread"); if (!shutdown_ || currentStep_ == ConnectionStep::ShutdownStarted) return; @@ -165,7 +165,7 @@ ConnectAttempt::close() { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::ConnectAttempt::close : strand in this thread"); + "xrpl::ConnectAttempt::close : strand in this thread"); if (!socket_.is_open()) return; @@ -619,4 +619,4 @@ ConnectAttempt::processResponse() } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/ConnectAttempt.h b/src/xrpld/overlay/detail/ConnectAttempt.h index 6f0a151383..69053f3bc1 100644 --- a/src/xrpld/overlay/detail/ConnectAttempt.h +++ b/src/xrpld/overlay/detail/ConnectAttempt.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { /** * @class ConnectAttempt @@ -273,6 +273,6 @@ private: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/Handshake.cpp b/src/xrpld/overlay/detail/Handshake.cpp index 45dc37f52c..411884dc12 100644 --- a/src/xrpld/overlay/detail/Handshake.cpp +++ b/src/xrpld/overlay/detail/Handshake.cpp @@ -14,7 +14,7 @@ // VFALCO Shouldn't we have to include the OpenSSL // headers or something for SSL_get_finished? -namespace ripple { +namespace xrpl { std::optional getFeatureValue( @@ -158,7 +158,7 @@ makeSharedValue(stream_type& ssl, beast::Journal journal) void buildHandshake( boost::beast::http::fields& h, - ripple::uint256 const& sharedValue, + xrpl::uint256 const& sharedValue, std::optional networkID, beast::IP::Address public_ip, beast::IP::Address remote_ip, @@ -207,7 +207,7 @@ buildHandshake( PublicKey verifyHandshake( boost::beast::http::fields const& headers, - ripple::uint256 const& sharedValue, + xrpl::uint256 const& sharedValue, std::optional networkID, beast::IP::Address public_ip, beast::IP::Address remote, @@ -402,4 +402,4 @@ makeResponse( return resp; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/Handshake.h b/src/xrpld/overlay/detail/Handshake.h index 52777d2bd8..95eb18394d 100644 --- a/src/xrpld/overlay/detail/Handshake.h +++ b/src/xrpld/overlay/detail/Handshake.h @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { using socket_type = boost::beast::tcp_stream; using stream_type = boost::beast::ssl_stream; @@ -233,6 +233,6 @@ makeFeaturesResponseHeader( bool txReduceRelayEnabled, bool vpReduceRelayEnabled); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/Message.cpp b/src/xrpld/overlay/detail/Message.cpp index b4cd4262aa..eb7b88894a 100644 --- a/src/xrpld/overlay/detail/Message.cpp +++ b/src/xrpld/overlay/detail/Message.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { Message::Message( ::google::protobuf::Message const& message, @@ -12,12 +12,12 @@ Message::Message( : category_(TrafficCount::categorize(message, type, false)) , validatorKey_(validator) { - using namespace ripple::compression; + using namespace xrpl::compression; auto const messageBytes = messageSize(message); XRPL_ASSERT( - messageBytes, "ripple::Message::Message : non-empty message input"); + messageBytes, "xrpl::Message::Message : non-empty message input"); buffer_.resize(headerBytes + messageBytes); @@ -28,7 +28,7 @@ Message::Message( XRPL_ASSERT( getBufferSize() == totalSize(message), - "ripple::Message::Message : message size matches the buffer"); + "xrpl::Message::Message : message size matches the buffer"); } // static @@ -52,7 +52,7 @@ Message::totalSize(::google::protobuf::Message const& message) void Message::compress() { - using namespace ripple::compression; + using namespace xrpl::compression; auto const messageBytes = buffer_.size() - headerBytes; auto type = getType(buffer_.data()); @@ -92,7 +92,7 @@ Message::compress() { auto payload = static_cast(buffer_.data() + headerBytes); - auto compressedSize = ripple::compression::compress( + auto compressedSize = xrpl::compression::compress( payload, messageBytes, [&](std::size_t inSize) { // size of required compressed buffer @@ -208,4 +208,4 @@ Message::getType(std::uint8_t const* in) const return type; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/OverlayImpl.cpp b/src/xrpld/overlay/detail/OverlayImpl.cpp index d2a994fa8e..e5f77021d7 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.cpp +++ b/src/xrpld/overlay/detail/OverlayImpl.cpp @@ -24,7 +24,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace CrawlOptions { enum { @@ -285,7 +285,7 @@ OverlayImpl::onHandoff( auto const result = m_peers.emplace(peer->slot(), peer); XRPL_ASSERT( result.second, - "ripple::OverlayImpl::onHandoff : peer is inserted"); + "xrpl::OverlayImpl::onHandoff : peer is inserted"); (void)result.second; } list_.emplace(peer.get(), peer); @@ -378,7 +378,7 @@ OverlayImpl::makeErrorResponse( void OverlayImpl::connect(beast::IP::Endpoint const& remote_endpoint) { - XRPL_ASSERT(work_, "ripple::OverlayImpl::connect : work is set"); + XRPL_ASSERT(work_, "xrpl::OverlayImpl::connect : work is set"); auto usage = resourceManager().newOutboundEndpoint(remote_endpoint); if (usage.disconnect(journal_)) @@ -425,8 +425,7 @@ OverlayImpl::add_active(std::shared_ptr const& peer) { auto const result = m_peers.emplace(peer->slot(), peer); XRPL_ASSERT( - result.second, - "ripple::OverlayImpl::add_active : peer is inserted"); + result.second, "xrpl::OverlayImpl::add_active : peer is inserted"); (void)result.second; } @@ -437,7 +436,7 @@ OverlayImpl::add_active(std::shared_ptr const& peer) std::make_tuple(peer)); XRPL_ASSERT( result.second, - "ripple::OverlayImpl::add_active : peer ID is inserted"); + "xrpl::OverlayImpl::add_active : peer ID is inserted"); (void)result.second; } @@ -457,7 +456,7 @@ OverlayImpl::remove(std::shared_ptr const& slot) std::lock_guard lock(mutex_); auto const iter = m_peers.find(slot); XRPL_ASSERT( - iter != m_peers.end(), "ripple::OverlayImpl::remove : valid input"); + iter != m_peers.end(), "xrpl::OverlayImpl::remove : valid input"); m_peers.erase(iter); } @@ -598,15 +597,14 @@ OverlayImpl::activate(std::shared_ptr const& peer) std::make_tuple(peer->id()), std::make_tuple(peer))); XRPL_ASSERT( - result.second, - "ripple::OverlayImpl::activate : peer ID is inserted"); + result.second, "xrpl::OverlayImpl::activate : peer ID is inserted"); (void)result.second; } JLOG(journal.debug()) << "activated"; // We just accepted this peer so we have non-zero active peers - XRPL_ASSERT(size(), "ripple::OverlayImpl::activate : nonzero peers"); + XRPL_ASSERT(size(), "xrpl::OverlayImpl::activate : nonzero peers"); } void @@ -647,7 +645,7 @@ OverlayImpl::onManifests( mo = deserializeManifest(serialized); XRPL_ASSERT( mo, - "ripple::OverlayImpl::onManifests : manifest " + "xrpl::OverlayImpl::onManifests : manifest " "deserialization succeeded"); app_.getOPs().pubManifest(*mo); @@ -1603,4 +1601,4 @@ make_Overlay( collector); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/OverlayImpl.h b/src/xrpld/overlay/detail/OverlayImpl.h index 18f2aa0c3f..dc7e4975a3 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.h +++ b/src/xrpld/overlay/detail/OverlayImpl.h @@ -35,7 +35,7 @@ #include #include -namespace ripple { +namespace xrpl { class PeerImp; class BasicConfig; @@ -595,7 +595,7 @@ private: std::lock_guard lock(m_statsMutex); XRPL_ASSERT( counts.size() == m_stats.trafficGauges.size(), - "ripple::OverlayImpl::collect_metrics : counts size do match"); + "xrpl::OverlayImpl::collect_metrics : counts size do match"); for (auto const& [key, value] : counts) { @@ -607,7 +607,7 @@ private: XRPL_ASSERT( gauge.name == value.name, - "ripple::OverlayImpl::collect_metrics : gauge and counter " + "xrpl::OverlayImpl::collect_metrics : gauge and counter " "match"); gauge.bytesIn = value.bytesIn; @@ -620,6 +620,6 @@ private: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index 7adfef4064..c92a95149e 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -33,7 +33,7 @@ using namespace std::chrono_literals; -namespace ripple { +namespace xrpl { namespace { /** The threshold above which we treat a peer connection as high latency */ @@ -562,7 +562,7 @@ PeerImp::fail(std::string const& name, error_code ec) { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::PeerImp::fail : strand in this thread"); + "xrpl::PeerImp::fail : strand in this thread"); if (!socket_.is_open()) return; @@ -601,7 +601,7 @@ PeerImp::tryAsyncShutdown() { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::PeerImp::tryAsyncShutdown : strand in this thread"); + "xrpl::PeerImp::tryAsyncShutdown : strand in this thread"); if (!shutdown_ || shutdownStarted_) return; @@ -625,7 +625,7 @@ PeerImp::shutdown() { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::PeerImp::shutdown: strand in this thread"); + "xrpl::PeerImp::shutdown: strand in this thread"); if (!socket_.is_open() || shutdown_) return; @@ -668,7 +668,7 @@ PeerImp::close() { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::PeerImp::close : strand in this thread"); + "xrpl::PeerImp::close : strand in this thread"); if (!socket_.is_open()) return; @@ -723,7 +723,7 @@ PeerImp::onTimer(error_code const& ec) { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::PeerImp::onTimer : strand in this thread"); + "xrpl::PeerImp::onTimer : strand in this thread"); if (!socket_.is_open()) return; @@ -804,7 +804,7 @@ PeerImp::doAccept() { XRPL_ASSERT( read_buffer_.size() == 0, - "ripple::PeerImp::doAccept : empty read buffer"); + "xrpl::PeerImp::doAccept : empty read buffer"); JLOG(journal_.debug()) << "doAccept"; @@ -933,7 +933,7 @@ PeerImp::onReadMessage(error_code ec, std::size_t bytes_transferred) { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::PeerImp::onReadMessage : strand in this thread"); + "xrpl::PeerImp::onReadMessage : strand in this thread"); readPending_ = false; @@ -1005,7 +1005,7 @@ PeerImp::onReadMessage(error_code ec, std::size_t bytes_transferred) readPending_ = true; XRPL_ASSERT( - !shutdownStarted_, "ripple::PeerImp::onReadMessage : shutdown started"); + !shutdownStarted_, "xrpl::PeerImp::onReadMessage : shutdown started"); // Timeout on writes only stream_.async_read_some( @@ -1024,7 +1024,7 @@ PeerImp::onWriteMessage(error_code ec, std::size_t bytes_transferred) { XRPL_ASSERT( strand_.running_in_this_thread(), - "ripple::PeerImp::onWriteMessage : strand in this thread"); + "xrpl::PeerImp::onWriteMessage : strand in this thread"); writePending_ = false; @@ -1051,7 +1051,7 @@ PeerImp::onWriteMessage(error_code ec, std::size_t bytes_transferred) XRPL_ASSERT( !send_queue_.empty(), - "ripple::PeerImp::onWriteMessage : non-empty send buffer"); + "xrpl::PeerImp::onWriteMessage : non-empty send buffer"); send_queue_.pop(); if (shutdown_) @@ -1062,7 +1062,7 @@ PeerImp::onWriteMessage(error_code ec, std::size_t bytes_transferred) writePending_ = true; XRPL_ASSERT( !shutdownStarted_, - "ripple::PeerImp::onWriteMessage : shutdown started"); + "xrpl::PeerImp::onWriteMessage : shutdown started"); // Timeout on writes only return boost::asio::async_write( @@ -1343,7 +1343,7 @@ PeerImp::handleTransaction( { XRPL_ASSERT( eraseTxQueue != batch, - ("ripple::PeerImp::handleTransaction : valid inputs")); + ("xrpl::PeerImp::handleTransaction : valid inputs")); if (tracking_.load() == Tracking::diverged) return; @@ -2186,7 +2186,7 @@ PeerImp::onValidatorListMessage( XRPL_ASSERT( applyResult.publisherKey, - "ripple::PeerImp::onValidatorListMessage : publisher key is " + "xrpl::PeerImp::onValidatorListMessage : publisher key is " "set"); auto const& pubKey = *applyResult.publisherKey; #ifndef NDEBUG @@ -2195,7 +2195,7 @@ PeerImp::onValidatorListMessage( { XRPL_ASSERT( iter->second < applyResult.sequence, - "ripple::PeerImp::onValidatorListMessage : lower sequence"); + "xrpl::PeerImp::onValidatorListMessage : lower sequence"); } #endif publisherListSequences_[pubKey] = applyResult.sequence; @@ -2208,12 +2208,12 @@ PeerImp::onValidatorListMessage( std::lock_guard sl(recentLock_); XRPL_ASSERT( applyResult.sequence && applyResult.publisherKey, - "ripple::PeerImp::onValidatorListMessage : nonzero sequence " + "xrpl::PeerImp::onValidatorListMessage : nonzero sequence " "and set publisher key"); XRPL_ASSERT( publisherListSequences_[*applyResult.publisherKey] <= applyResult.sequence, - "ripple::PeerImp::onValidatorListMessage : maximum sequence"); + "xrpl::PeerImp::onValidatorListMessage : maximum sequence"); } #endif // !NDEBUG @@ -2226,7 +2226,7 @@ PeerImp::onValidatorListMessage( // LCOV_EXCL_START default: UNREACHABLE( - "ripple::PeerImp::onValidatorListMessage : invalid best list " + "xrpl::PeerImp::onValidatorListMessage : invalid best list " "disposition"); // LCOV_EXCL_STOP } @@ -2272,7 +2272,7 @@ PeerImp::onValidatorListMessage( // LCOV_EXCL_START default: UNREACHABLE( - "ripple::PeerImp::onValidatorListMessage : invalid worst list " + "xrpl::PeerImp::onValidatorListMessage : invalid worst list " "disposition"); // LCOV_EXCL_STOP } @@ -2327,7 +2327,7 @@ PeerImp::onValidatorListMessage( // LCOV_EXCL_START default: UNREACHABLE( - "ripple::PeerImp::onValidatorListMessage : invalid list " + "xrpl::PeerImp::onValidatorListMessage : invalid list " "disposition"); // LCOV_EXCL_STOP } @@ -2986,7 +2986,7 @@ PeerImp::checkTransaction( auto tx = std::make_shared(stx, reason, app_); XRPL_ASSERT( tx->getStatus() == NEW, - "ripple::PeerImp::checkTransaction Transaction created " + "xrpl::PeerImp::checkTransaction Transaction created " "correctly"); if (tx->getStatus() == NEW) { @@ -3089,7 +3089,7 @@ PeerImp::checkPropose( JLOG(p_journal_.trace()) << "Checking " << (isTrusted ? "trusted" : "UNTRUSTED") << " proposal"; - XRPL_ASSERT(packet, "ripple::PeerImp::checkPropose : non-null packet"); + XRPL_ASSERT(packet, "xrpl::PeerImp::checkPropose : non-null packet"); if (!cluster() && !peerPos.checkSign()) { @@ -3655,4 +3655,4 @@ PeerImp::Metrics::total_bytes() const return totalBytes_; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/PeerImp.h b/src/xrpld/overlay/detail/PeerImp.h index 78f3e46509..565c3f9d0f 100644 --- a/src/xrpld/overlay/detail/PeerImp.h +++ b/src/xrpld/overlay/detail/PeerImp.h @@ -26,7 +26,7 @@ #include #include -namespace ripple { +namespace xrpl { struct ValidatorBlobInfo; class SHAMap; @@ -202,7 +202,7 @@ private: { XRPL_ASSERT( f >= fee, - "ripple::PeerImp::ChargeWithContext::update : fee increases"); + "xrpl::PeerImp::ChargeWithContext::update : fee increases"); fee = f; if (!context.empty()) { @@ -903,6 +903,6 @@ PeerImp::sendEndpoints(FwdIt first, FwdIt last) send(std::make_shared(tm, protocol::mtENDPOINTS)); } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/PeerReservationTable.cpp b/src/xrpld/overlay/detail/PeerReservationTable.cpp index 27cf749ab1..1e3452ca17 100644 --- a/src/xrpld/overlay/detail/PeerReservationTable.cpp +++ b/src/xrpld/overlay/detail/PeerReservationTable.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { auto PeerReservation::toJson() const -> Json::Value @@ -111,4 +111,4 @@ PeerReservationTable::erase(PublicKey const& nodeId) return previous; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/PeerSet.cpp b/src/xrpld/overlay/detail/PeerSet.cpp index 9f5b810ffc..f11a07f7a3 100644 --- a/src/xrpld/overlay/detail/PeerSet.cpp +++ b/src/xrpld/overlay/detail/PeerSet.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { class PeerSetImpl : public PeerSet { @@ -29,7 +29,7 @@ public: private: // Used in this class for access to boost::asio::io_context and - // ripple::Overlay. + // xrpl::Overlay. Application& app_; beast::Journal journal_; @@ -171,4 +171,4 @@ make_DummyPeerSet(Application& app) return std::make_unique(app); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/ProtocolMessage.h b/src/xrpld/overlay/detail/ProtocolMessage.h index 0eaa4ca720..1a35deb6f0 100644 --- a/src/xrpld/overlay/detail/ProtocolMessage.h +++ b/src/xrpld/overlay/detail/ProtocolMessage.h @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { inline protocol::MessageType protocolMessageType(protocol::TMGetLedger const&) @@ -152,13 +152,13 @@ parseMessageHeader( BufferSequence const& bufs, std::size_t size) { - using namespace ripple::compression; + using namespace xrpl::compression; MessageHeader hdr; auto iter = buffersBegin(bufs); XRPL_ASSERT( iter != buffersEnd(bufs), - "ripple::detail::parseMessageHeader : non-empty buffer"); + "xrpl::detail::parseMessageHeader : non-empty buffer"); // Check valid header compressed message: // - 4 bits are the compression algorithm, 1st bit is always set to 1 @@ -256,7 +256,7 @@ parseMessageContent(MessageHeader const& header, Buffers const& buffers) std::vector payload; payload.resize(header.uncompressed_size); - auto const payloadSize = ripple::compression::decompress( + auto const payloadSize = xrpl::compression::decompress( stream, header.payload_wire_size, payload.data(), @@ -285,7 +285,7 @@ invoke(MessageHeader const& header, Buffers const& buffers, Handler& handler) if (!m) return false; - using namespace ripple::compression; + using namespace xrpl::compression; handler.onMessageBegin( header.message_type, m, @@ -465,6 +465,6 @@ invokeProtocolMessage( return result; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/ProtocolVersion.cpp b/src/xrpld/overlay/detail/ProtocolVersion.cpp index 4a5c3d10b3..a99e38e8ea 100644 --- a/src/xrpld/overlay/detail/ProtocolVersion.cpp +++ b/src/xrpld/overlay/detail/ProtocolVersion.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** The list of protocol versions we speak and we prefer to use. @@ -164,4 +164,4 @@ isProtocolSupported(ProtocolVersion const& v) v); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/ProtocolVersion.h b/src/xrpld/overlay/detail/ProtocolVersion.h index 02b8720563..ff49c89f1a 100644 --- a/src/xrpld/overlay/detail/ProtocolVersion.h +++ b/src/xrpld/overlay/detail/ProtocolVersion.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Represents a particular version of the peer-to-peer protocol. @@ -58,6 +58,6 @@ supportedProtocolVersions(); bool isProtocolSupported(ProtocolVersion const& v); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/TrafficCount.cpp b/src/xrpld/overlay/detail/TrafficCount.cpp index 03b83d29de..6fb397ea71 100644 --- a/src/xrpld/overlay/detail/TrafficCount.cpp +++ b/src/xrpld/overlay/detail/TrafficCount.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { std::unordered_map const type_lookup = { @@ -127,4 +127,4 @@ TrafficCount::categorize( return TrafficCount::category::unknown; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/TrafficCount.h b/src/xrpld/overlay/detail/TrafficCount.h index c6d10ee286..7d005c22d0 100644 --- a/src/xrpld/overlay/detail/TrafficCount.h +++ b/src/xrpld/overlay/detail/TrafficCount.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /** TrafficCount is used to count ingress and egress wire bytes and number of @@ -196,7 +196,7 @@ public: { XRPL_ASSERT( cat <= category::unknown, - "ripple::TrafficCount::addCount : valid category input"); + "xrpl::TrafficCount::addCount : valid category input"); auto it = counts_.find(cat); @@ -355,5 +355,5 @@ protected: }; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/Tuning.h b/src/xrpld/overlay/detail/Tuning.h index c78ac20572..c18d17c359 100644 --- a/src/xrpld/overlay/detail/Tuning.h +++ b/src/xrpld/overlay/detail/Tuning.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace Tuning { @@ -47,6 +47,6 @@ std::size_t constexpr readBufferBytes = 16384; } // namespace Tuning -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/TxMetrics.cpp b/src/xrpld/overlay/detail/TxMetrics.cpp index 088137c58d..10f14183a3 100644 --- a/src/xrpld/overlay/detail/TxMetrics.cpp +++ b/src/xrpld/overlay/detail/TxMetrics.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace metrics { @@ -130,4 +130,4 @@ TxMetrics::json() const } // namespace metrics -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/TxMetrics.h b/src/xrpld/overlay/detail/TxMetrics.h index 2db755466c..3c34aaf9f9 100644 --- a/src/xrpld/overlay/detail/TxMetrics.h +++ b/src/xrpld/overlay/detail/TxMetrics.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace metrics { @@ -117,6 +117,6 @@ struct TxMetrics } // namespace metrics -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/detail/ZeroCopyStream.h b/src/xrpld/overlay/detail/ZeroCopyStream.h index 2f5279a6fe..2373ea16d0 100644 --- a/src/xrpld/overlay/detail/ZeroCopyStream.h +++ b/src/xrpld/overlay/detail/ZeroCopyStream.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { /** Implements ZeroCopyInputStream around a buffer sequence. @tparam Buffers A type meeting the requirements of ConstBufferSequence. @@ -188,13 +188,13 @@ void ZeroCopyOutputStream::BackUp(int count) { XRPL_ASSERT( - count <= commit_, "ripple::ZeroCopyOutputStream::BackUp : valid input"); + count <= commit_, "xrpl::ZeroCopyOutputStream::BackUp : valid input"); auto const n = commit_ - count; streambuf_.commit(n); count_ += n; commit_ = 0; } -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/make_Overlay.h b/src/xrpld/overlay/make_Overlay.h index 9bf867fba6..6c37c1c825 100644 --- a/src/xrpld/overlay/make_Overlay.h +++ b/src/xrpld/overlay/make_Overlay.h @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { Overlay::Setup setup_Overlay(BasicConfig const& config); @@ -25,6 +25,6 @@ make_Overlay( BasicConfig const& config, beast::insight::Collector::ptr const& collector); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/overlay/predicates.h b/src/xrpld/overlay/predicates.h index 36d0cf28b1..6683d8007f 100644 --- a/src/xrpld/overlay/predicates.h +++ b/src/xrpld/overlay/predicates.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { /** Sends a message to all peers */ struct send_always @@ -156,6 +156,6 @@ struct peer_in_set } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/PeerfinderManager.h b/src/xrpld/peerfinder/PeerfinderManager.h index bde9645efd..7a25edcce5 100644 --- a/src/xrpld/peerfinder/PeerfinderManager.h +++ b/src/xrpld/peerfinder/PeerfinderManager.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { using clock_type = beast::abstract_clock; @@ -86,7 +86,7 @@ struct Config */ static Config makeConfig( - ripple::Config const& config, + xrpl::Config const& config, std::uint16_t port, bool validationPublicKey, int ipLimit); @@ -303,6 +303,6 @@ public: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/Slot.h b/src/xrpld/peerfinder/Slot.h index 6a8515fc29..1d5d58884a 100644 --- a/src/xrpld/peerfinder/Slot.h +++ b/src/xrpld/peerfinder/Slot.h @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Properties and state associated with a peer to peer overlay connection. */ @@ -60,6 +60,6 @@ public: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Bootcache.cpp b/src/xrpld/peerfinder/detail/Bootcache.cpp index 3d11ee74ee..4505c02872 100644 --- a/src/xrpld/peerfinder/detail/Bootcache.cpp +++ b/src/xrpld/peerfinder/detail/Bootcache.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { Bootcache::Bootcache(Store& store, clock_type& clock, beast::Journal journal) @@ -270,4 +270,4 @@ Bootcache::flagForUpdate() } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/peerfinder/detail/Bootcache.h b/src/xrpld/peerfinder/detail/Bootcache.h index b0646a21d5..42867907c1 100644 --- a/src/xrpld/peerfinder/detail/Bootcache.h +++ b/src/xrpld/peerfinder/detail/Bootcache.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Stores IP addresses useful for gaining initial connections. @@ -68,8 +68,8 @@ private: using left_t = boost::bimaps::unordered_set_of< beast::IP::Endpoint, boost::hash, - ripple::equal_to>; - using right_t = boost::bimaps::multiset_of>; + xrpl::equal_to>; + using right_t = boost::bimaps::multiset_of>; using map_type = boost::bimap; using value_type = map_type::value_type; @@ -176,6 +176,6 @@ private: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Checker.h b/src/xrpld/peerfinder/detail/Checker.h index d8a3d667e4..277ce8c74d 100644 --- a/src/xrpld/peerfinder/detail/Checker.h +++ b/src/xrpld/peerfinder/detail/Checker.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Tests remote listening sockets to make sure they are connectible. */ @@ -210,6 +210,6 @@ Checker::remove(basic_async_op& op) } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Counts.h b/src/xrpld/peerfinder/detail/Counts.h index ec4b068802..7bb17278cc 100644 --- a/src/xrpld/peerfinder/detail/Counts.h +++ b/src/xrpld/peerfinder/detail/Counts.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Manages the count of available connections for the various slots. */ @@ -53,7 +53,7 @@ public: // Must be handshaked and in the right state XRPL_ASSERT( s.state() == Slot::connected || s.state() == Slot::accept, - "ripple::PeerFinder::Counts::can_activate : valid input state"); + "xrpl::PeerFinder::Counts::can_activate : valid input state"); if (s.fixed() || s.reserved()) return true; @@ -246,7 +246,7 @@ private: case Slot::accept: XRPL_ASSERT( s.inbound(), - "ripple::PeerFinder::Counts::adjust : input is inbound"); + "xrpl::PeerFinder::Counts::adjust : input is inbound"); m_acceptCount += n; break; @@ -254,7 +254,7 @@ private: case Slot::connected: XRPL_ASSERT( !s.inbound(), - "ripple::PeerFinder::Counts::adjust : input is not " + "xrpl::PeerFinder::Counts::adjust : input is not " "inbound"); m_attempts += n; break; @@ -279,7 +279,7 @@ private: // LCOV_EXCL_START default: UNREACHABLE( - "ripple::PeerFinder::Counts::adjust : invalid input state"); + "xrpl::PeerFinder::Counts::adjust : invalid input state"); break; // LCOV_EXCL_STOP }; @@ -322,6 +322,6 @@ private: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Endpoint.cpp b/src/xrpld/peerfinder/detail/Endpoint.cpp index 5ae3839cb5..46f4f28b88 100644 --- a/src/xrpld/peerfinder/detail/Endpoint.cpp +++ b/src/xrpld/peerfinder/detail/Endpoint.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { Endpoint::Endpoint(beast::IP::Endpoint const& ep, std::uint32_t hops_) @@ -10,4 +10,4 @@ Endpoint::Endpoint(beast::IP::Endpoint const& ep, std::uint32_t hops_) } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/peerfinder/detail/Fixed.h b/src/xrpld/peerfinder/detail/Fixed.h index c238c34477..4c89bc598e 100644 --- a/src/xrpld/peerfinder/detail/Fixed.h +++ b/src/xrpld/peerfinder/detail/Fixed.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Metadata for a Fixed slot. */ @@ -47,6 +47,6 @@ private: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Handouts.h b/src/xrpld/peerfinder/detail/Handouts.h index e88376d0d6..60789ae7ab 100644 --- a/src/xrpld/peerfinder/detail/Handouts.h +++ b/src/xrpld/peerfinder/detail/Handouts.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { namespace detail { @@ -25,7 +25,7 @@ handout_one(Target& t, HopContainer& h) { XRPL_ASSERT( !t.full(), - "ripple::PeerFinder::detail::handout_one : target is not full"); + "xrpl::PeerFinder::detail::handout_one : target is not full"); for (auto it = h.begin(); it != h.end(); ++it) { auto const& e = *it; @@ -340,6 +340,6 @@ ConnectHandouts::try_insert(beast::IP::Endpoint const& endpoint) } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Livecache.h b/src/xrpld/peerfinder/detail/Livecache.h index 2664d2cbf3..0927593ed1 100644 --- a/src/xrpld/peerfinder/detail/Livecache.h +++ b/src/xrpld/peerfinder/detail/Livecache.h @@ -15,7 +15,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { template @@ -417,7 +417,7 @@ Livecache::insert(Endpoint const& ep) // XRPL_ASSERT( ep.hops <= (Tuning::maxHops + 1), - "ripple::PeerFinder::Livecache::insert : maximum input hops"); + "xrpl::PeerFinder::Livecache::insert : maximum input hops"); auto result = m_cache.emplace(ep.address, ep); Element& e(result.first->second); if (result.second) @@ -517,7 +517,7 @@ Livecache::hops_t::insert(Element& e) { XRPL_ASSERT( e.endpoint.hops <= Tuning::maxHops + 1, - "ripple::PeerFinder::Livecache::hops_t::insert : maximum input hops"); + "xrpl::PeerFinder::Livecache::hops_t::insert : maximum input hops"); // This has security implications without a shuffle m_lists[e.endpoint.hops].push_front(e); ++m_hist[e.endpoint.hops]; @@ -529,7 +529,7 @@ Livecache::hops_t::reinsert(Element& e, std::uint32_t numHops) { XRPL_ASSERT( numHops <= Tuning::maxHops + 1, - "ripple::PeerFinder::Livecache::hops_t::reinsert : maximum hops input"); + "xrpl::PeerFinder::Livecache::hops_t::reinsert : maximum hops input"); auto& list = m_lists[e.endpoint.hops]; list.erase(list.iterator_to(e)); @@ -551,6 +551,6 @@ Livecache::hops_t::remove(Element& e) } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Logic.h b/src/xrpld/peerfinder/detail/Logic.h index a4ec77fd96..50026cc886 100644 --- a/src/xrpld/peerfinder/detail/Logic.h +++ b/src/xrpld/peerfinder/detail/Logic.h @@ -24,7 +24,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** The Logic for maintaining the list of Slot addresses. @@ -288,7 +288,7 @@ public: // Remote address must not already exist XRPL_ASSERT( result.second, - "ripple::PeerFinder::Logic::new_inbound_slot : remote endpoint " + "xrpl::PeerFinder::Logic::new_inbound_slot : remote endpoint " "inserted"); // Add to the connected address list connectedAddresses_.emplace(remote_endpoint.address()); @@ -326,7 +326,7 @@ public: // Remote address must not already exist XRPL_ASSERT( result.second, - "ripple::PeerFinder::Logic::new_outbound_slot : remote endpoint " + "xrpl::PeerFinder::Logic::new_outbound_slot : remote endpoint " "inserted"); // Add to the connected address list @@ -353,7 +353,7 @@ public: // The object must exist in our table XRPL_ASSERT( slots_.find(slot->remote_endpoint()) != slots_.end(), - "ripple::PeerFinder::Logic::onConnected : valid slot input"); + "xrpl::PeerFinder::Logic::onConnected : valid slot input"); // Assign the local endpoint now that it's known slot->local_endpoint(local_endpoint); @@ -364,7 +364,7 @@ public: { XRPL_ASSERT( iter->second->local_endpoint() == slot->remote_endpoint(), - "ripple::PeerFinder::Logic::onConnected : local and remote " + "xrpl::PeerFinder::Logic::onConnected : local and remote " "endpoints do match"); JLOG(journal.warn()) << "Logic dropping as self connect"; return false; @@ -393,11 +393,11 @@ public: // The object must exist in our table XRPL_ASSERT( slots_.find(slot->remote_endpoint()) != slots_.end(), - "ripple::PeerFinder::Logic::activate : valid slot input"); + "xrpl::PeerFinder::Logic::activate : valid slot input"); // Must be accepted or connected XRPL_ASSERT( slot->state() == Slot::accept || slot->state() == Slot::connected, - "ripple::PeerFinder::Logic::activate : valid slot state"); + "xrpl::PeerFinder::Logic::activate : valid slot state"); // Check for duplicate connection by key if (keys_.find(key) != keys_.end()) @@ -427,7 +427,7 @@ public: // Public key must not already exist XRPL_ASSERT( inserted, - "ripple::PeerFinder::Logic::activate : public key inserted"); + "xrpl::PeerFinder::Logic::activate : public key inserted"); } // Change state and update counts @@ -792,12 +792,12 @@ public: // The object must exist in our table XRPL_ASSERT( slots_.find(slot->remote_endpoint()) != slots_.end(), - "ripple::PeerFinder::Logic::on_endpoints : valid slot input"); + "xrpl::PeerFinder::Logic::on_endpoints : valid slot input"); // Must be handshaked! XRPL_ASSERT( slot->state() == Slot::active, - "ripple::PeerFinder::Logic::on_endpoints : valid slot state"); + "xrpl::PeerFinder::Logic::on_endpoints : valid slot state"); clock_type::time_point const now(m_clock.now()); @@ -811,7 +811,7 @@ public: { XRPL_ASSERT( ep.hops, - "ripple::PeerFinder::Logic::on_endpoints : nonzero hops"); + "xrpl::PeerFinder::Logic::on_endpoints : nonzero hops"); slot->recent.insert(ep.address, ep.hops); @@ -964,7 +964,7 @@ public: // LCOV_EXCL_START default: UNREACHABLE( - "ripple::PeerFinder::Logic::on_closed : invalid slot " + "xrpl::PeerFinder::Logic::on_closed : invalid slot " "state"); break; // LCOV_EXCL_STOP @@ -1264,6 +1264,6 @@ Logic::onRedirects( } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/PeerfinderConfig.cpp b/src/xrpld/peerfinder/detail/PeerfinderConfig.cpp index 44e4f64197..726c18fdc0 100644 --- a/src/xrpld/peerfinder/detail/PeerfinderConfig.cpp +++ b/src/xrpld/peerfinder/detail/PeerfinderConfig.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { Config::Config() @@ -68,7 +68,7 @@ Config::onWrite(beast::PropertyStream::Map& map) Config Config::makeConfig( - ripple::Config const& cfg, + xrpl::Config const& cfg, std::uint16_t port, bool validationPublicKey, int ipLimit) @@ -129,4 +129,4 @@ Config::makeConfig( } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/peerfinder/detail/PeerfinderManager.cpp b/src/xrpld/peerfinder/detail/PeerfinderManager.cpp index 05a9a89362..17faf35351 100644 --- a/src/xrpld/peerfinder/detail/PeerfinderManager.cpp +++ b/src/xrpld/peerfinder/detail/PeerfinderManager.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { class ManagerImp : public Manager @@ -266,4 +266,4 @@ make_Manager( } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/peerfinder/detail/SlotImp.cpp b/src/xrpld/peerfinder/detail/SlotImp.cpp index be08bcff7c..ac2ae25d46 100644 --- a/src/xrpld/peerfinder/detail/SlotImp.cpp +++ b/src/xrpld/peerfinder/detail/SlotImp.cpp @@ -2,7 +2,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { SlotImp::SlotImp( @@ -47,29 +47,29 @@ SlotImp::state(State state_) // Must go through activate() to set active state XRPL_ASSERT( state_ != active, - "ripple::PeerFinder::SlotImp::state : input state is not active"); + "xrpl::PeerFinder::SlotImp::state : input state is not active"); // The state must be different XRPL_ASSERT( state_ != m_state, - "ripple::PeerFinder::SlotImp::state : input state is different from " + "xrpl::PeerFinder::SlotImp::state : input state is different from " "current"); // You can't transition into the initial states XRPL_ASSERT( state_ != accept && state_ != connect, - "ripple::PeerFinder::SlotImp::state : input state is not an initial"); + "xrpl::PeerFinder::SlotImp::state : input state is not an initial"); // Can only become connected from outbound connect state XRPL_ASSERT( state_ != connected || (!m_inbound && m_state == connect), - "ripple::PeerFinder::SlotImp::state : input state is not connected an " + "xrpl::PeerFinder::SlotImp::state : input state is not connected an " "invalid state"); // Can't gracefully close on an outbound connection attempt XRPL_ASSERT( state_ != closing || m_state != connect, - "ripple::PeerFinder::SlotImp::state : input state is not closing an " + "xrpl::PeerFinder::SlotImp::state : input state is not closing an " "invalid state"); m_state = state_; @@ -81,7 +81,7 @@ SlotImp::activate(clock_type::time_point const& now) // Can only become active from the accept or connected state XRPL_ASSERT( m_state == accept || m_state == connected, - "ripple::PeerFinder::SlotImp::activate : valid state"); + "xrpl::PeerFinder::SlotImp::activate : valid state"); m_state = active; whenAcceptEndpoints = now; @@ -131,4 +131,4 @@ SlotImp::recent_t::expire() } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/peerfinder/detail/SlotImp.h b/src/xrpld/peerfinder/detail/SlotImp.h index 9898ca490d..cb5ce87202 100644 --- a/src/xrpld/peerfinder/detail/SlotImp.h +++ b/src/xrpld/peerfinder/detail/SlotImp.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { class SlotImp : public Slot @@ -195,6 +195,6 @@ public: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Source.h b/src/xrpld/peerfinder/detail/Source.h index b6971790b3..1fe33e053a 100644 --- a/src/xrpld/peerfinder/detail/Source.h +++ b/src/xrpld/peerfinder/detail/Source.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** A static or dynamic source of peer addresses. @@ -45,6 +45,6 @@ public: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/SourceStrings.cpp b/src/xrpld/peerfinder/detail/SourceStrings.cpp index 0c7431917a..772ec2d485 100644 --- a/src/xrpld/peerfinder/detail/SourceStrings.cpp +++ b/src/xrpld/peerfinder/detail/SourceStrings.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { class SourceStringsImp : public SourceStrings @@ -49,4 +49,4 @@ SourceStrings::New(std::string const& name, Strings const& strings) } } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/peerfinder/detail/SourceStrings.h b/src/xrpld/peerfinder/detail/SourceStrings.h index cbd03ed352..2babe1d616 100644 --- a/src/xrpld/peerfinder/detail/SourceStrings.h +++ b/src/xrpld/peerfinder/detail/SourceStrings.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Provides addresses from a static set of strings. */ @@ -21,6 +21,6 @@ public: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Store.h b/src/xrpld/peerfinder/detail/Store.h index 738462c9c3..d3b283eabf 100644 --- a/src/xrpld/peerfinder/detail/Store.h +++ b/src/xrpld/peerfinder/detail/Store.h @@ -1,7 +1,7 @@ #ifndef XRPL_PEERFINDER_STORE_H_INCLUDED #define XRPL_PEERFINDER_STORE_H_INCLUDED -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Abstract persistence for PeerFinder data. */ @@ -30,6 +30,6 @@ public: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/StoreSqdb.h b/src/xrpld/peerfinder/detail/StoreSqdb.h index 1d87545522..074428c0bc 100644 --- a/src/xrpld/peerfinder/detail/StoreSqdb.h +++ b/src/xrpld/peerfinder/detail/StoreSqdb.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Database persistence for PeerFinder using SQLite */ @@ -89,6 +89,6 @@ private: }; } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/detail/Tuning.h b/src/xrpld/peerfinder/detail/Tuning.h index 856a11a9fe..ba9cf9e615 100644 --- a/src/xrpld/peerfinder/detail/Tuning.h +++ b/src/xrpld/peerfinder/detail/Tuning.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Heuristically tuned constants. */ @@ -116,6 +116,6 @@ std::chrono::seconds constexpr recentAttemptDuration(60); /** @} */ } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/peerfinder/make_Manager.h b/src/xrpld/peerfinder/make_Manager.h index e4bd571261..a86e6d4ccb 100644 --- a/src/xrpld/peerfinder/make_Manager.h +++ b/src/xrpld/peerfinder/make_Manager.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace PeerFinder { /** Create a new Manager. */ @@ -20,6 +20,6 @@ make_Manager( beast::insight::Collector::ptr const& collector); } // namespace PeerFinder -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/perflog/detail/PerfLogImp.cpp b/src/xrpld/perflog/detail/PerfLogImp.cpp index 8d6d68137a..4c0c4d2f6f 100644 --- a/src/xrpld/perflog/detail/PerfLogImp.cpp +++ b/src/xrpld/perflog/detail/PerfLogImp.cpp @@ -18,7 +18,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace perf { PerfLogImp::Counters::Counters( @@ -36,7 +36,7 @@ PerfLogImp::Counters::Counters( // Ensure that no other function populates this entry. // LCOV_EXCL_START UNREACHABLE( - "ripple::perf::PerfLogImp::Counters::Counters : failed to " + "xrpl::perf::PerfLogImp::Counters::Counters : failed to " "insert label"); // LCOV_EXCL_STOP } @@ -53,7 +53,7 @@ PerfLogImp::Counters::Counters( // Ensure that no other function populates this entry. // LCOV_EXCL_START UNREACHABLE( - "ripple::perf::PerfLogImp::Counters::Counters : failed to " + "xrpl::perf::PerfLogImp::Counters::Counters : failed to " "insert job type"); // LCOV_EXCL_STOP } @@ -315,7 +315,7 @@ PerfLogImp::rpcStart(std::string const& method, std::uint64_t const requestId) if (counter == counters_.rpc_.end()) { // LCOV_EXCL_START - UNREACHABLE("ripple::perf::PerfLogImp::rpcStart : valid method input"); + UNREACHABLE("xrpl::perf::PerfLogImp::rpcStart : valid method input"); return; // LCOV_EXCL_STOP } @@ -339,7 +339,7 @@ PerfLogImp::rpcEnd( if (counter == counters_.rpc_.end()) { // LCOV_EXCL_START - UNREACHABLE("ripple::perf::PerfLogImp::rpcEnd : valid method input"); + UNREACHABLE("xrpl::perf::PerfLogImp::rpcEnd : valid method input"); return; // LCOV_EXCL_STOP } @@ -356,7 +356,7 @@ PerfLogImp::rpcEnd( { // LCOV_EXCL_START UNREACHABLE( - "ripple::perf::PerfLogImp::rpcEnd : valid requestId input"); + "xrpl::perf::PerfLogImp::rpcEnd : valid requestId input"); // LCOV_EXCL_STOP } } @@ -376,8 +376,7 @@ PerfLogImp::jobQueue(JobType const type) if (counter == counters_.jq_.end()) { // LCOV_EXCL_START - UNREACHABLE( - "ripple::perf::PerfLogImp::jobQueue : valid job type input"); + UNREACHABLE("xrpl::perf::PerfLogImp::jobQueue : valid job type input"); return; // LCOV_EXCL_STOP } @@ -396,8 +395,7 @@ PerfLogImp::jobStart( if (counter == counters_.jq_.end()) { // LCOV_EXCL_START - UNREACHABLE( - "ripple::perf::PerfLogImp::jobStart : valid job type input"); + UNREACHABLE("xrpl::perf::PerfLogImp::jobStart : valid job type input"); return; // LCOV_EXCL_STOP } @@ -419,8 +417,7 @@ PerfLogImp::jobFinish(JobType const type, microseconds dur, int instance) if (counter == counters_.jq_.end()) { // LCOV_EXCL_START - UNREACHABLE( - "ripple::perf::PerfLogImp::jobFinish : valid job type input"); + UNREACHABLE("xrpl::perf::PerfLogImp::jobFinish : valid job type input"); return; // LCOV_EXCL_STOP } @@ -511,4 +508,4 @@ make_PerfLog( } } // namespace perf -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/perflog/detail/PerfLogImp.h b/src/xrpld/perflog/detail/PerfLogImp.h index d8e5e7943d..740d7ea952 100644 --- a/src/xrpld/perflog/detail/PerfLogImp.h +++ b/src/xrpld/perflog/detail/PerfLogImp.h @@ -17,7 +17,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace perf { /** A box coupling data with a mutex for locking access to it. */ @@ -103,7 +103,7 @@ class PerfLogImp : public PerfLog Application& app_; beast::Journal const j_; std::function const signalStop_; - Counters counters_{ripple::RPC::getHandlerNames(), JobTypes::instance()}; + Counters counters_{xrpl::RPC::getHandlerNames(), JobTypes::instance()}; std::ofstream logFile_; std::thread thread_; std::mutex mutex_; @@ -185,6 +185,6 @@ public: }; } // namespace perf -} // namespace ripple +} // namespace xrpl #endif // XRPL_BASICS_PERFLOGIMP_H diff --git a/src/xrpld/rpc/BookChanges.h b/src/xrpld/rpc/BookChanges.h index c30dadb9fe..dc20b60c49 100644 --- a/src/xrpld/rpc/BookChanges.h +++ b/src/xrpld/rpc/BookChanges.h @@ -14,7 +14,7 @@ namespace Json { class Value; } -namespace ripple { +namespace xrpl { class ReadView; class Transaction; @@ -205,6 +205,6 @@ computeBookChanges(std::shared_ptr const& lpAccepted) } } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/CTID.h b/src/xrpld/rpc/CTID.h index 0fbd15601e..b7f25894ee 100644 --- a/src/xrpld/rpc/CTID.h +++ b/src/xrpld/rpc/CTID.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { @@ -113,6 +113,6 @@ decodeCTID(T const ctid) noexcept } } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/Context.h b/src/xrpld/rpc/Context.h index 1faafa1627..8bb0bd3cbc 100644 --- a/src/xrpld/rpc/Context.h +++ b/src/xrpld/rpc/Context.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; class NetworkOPs; @@ -53,6 +53,6 @@ struct GRPCContext : public Context }; } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/DeliveredAmount.h b/src/xrpld/rpc/DeliveredAmount.h index 25af5c084e..fbd2545963 100644 --- a/src/xrpld/rpc/DeliveredAmount.h +++ b/src/xrpld/rpc/DeliveredAmount.h @@ -11,7 +11,7 @@ namespace Json { class Value; } -namespace ripple { +namespace xrpl { class ReadView; class Transaction; @@ -62,6 +62,6 @@ getDeliveredAmount( /** @} */ } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/GRPCHandlers.h b/src/xrpld/rpc/GRPCHandlers.h index e9bce3ccbf..f3e8d74f9d 100644 --- a/src/xrpld/rpc/GRPCHandlers.h +++ b/src/xrpld/rpc/GRPCHandlers.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { /* * These handlers are for gRPC. They each take in a protobuf message that is @@ -32,6 +32,6 @@ std::pair doLedgerDiffGrpc( RPC::GRPCContext& context); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/InfoSub.h b/src/xrpld/rpc/InfoSub.h index f3affd40ae..97ff266364 100644 --- a/src/xrpld/rpc/InfoSub.h +++ b/src/xrpld/rpc/InfoSub.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { // Operations that clients may wish to perform against the network // Master operational handler, server sequencer, network tracker @@ -237,6 +237,6 @@ private: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/MPTokenIssuanceID.h b/src/xrpld/rpc/MPTokenIssuanceID.h index ad96c2b78b..85f44e79b8 100644 --- a/src/xrpld/rpc/MPTokenIssuanceID.h +++ b/src/xrpld/rpc/MPTokenIssuanceID.h @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { @@ -37,6 +37,6 @@ insertMPTokenIssuanceID( /** @} */ } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/Output.h b/src/xrpld/rpc/Output.h index 0b0d62bbf9..431cbb6bbf 100644 --- a/src/xrpld/rpc/Output.h +++ b/src/xrpld/rpc/Output.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { using Output = std::function; @@ -15,6 +15,6 @@ stringOutput(std::string& s) } } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/README.md b/src/xrpld/rpc/README.md index 5bb9655a76..749f3d0ed1 100644 --- a/src/xrpld/rpc/README.md +++ b/src/xrpld/rpc/README.md @@ -15,7 +15,7 @@ For this purpose, the rippled RPC handler allows _suspension with continuation_ ## The classes. -Suspension with continuation uses four `std::function`s in the `ripple::RPC` +Suspension with continuation uses four `std::function`s in the `xrpl::RPC` namespace: using Callback = std::function ; diff --git a/src/xrpld/rpc/RPCCall.h b/src/xrpld/rpc/RPCCall.h index b27e60c8ea..2ee9e33cf3 100644 --- a/src/xrpld/rpc/RPCCall.h +++ b/src/xrpld/rpc/RPCCall.h @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { // This a trusted interface, the user is expected to provide valid input to // perform valid requests. Error catching and reporting is not a requirement of @@ -66,6 +66,6 @@ rpcClient( unsigned int apiVersion, std::unordered_map const& headers = {}); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/RPCHandler.h b/src/xrpld/rpc/RPCHandler.h index c6f4dfc6bd..0b91528605 100644 --- a/src/xrpld/rpc/RPCHandler.h +++ b/src/xrpld/rpc/RPCHandler.h @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { struct JsonContext; @@ -17,6 +17,6 @@ Role roleRequired(unsigned int version, bool betaEnabled, std::string const& method); } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/RPCSub.h b/src/xrpld/rpc/RPCSub.h index ea0cc993e8..b6bb32aaf3 100644 --- a/src/xrpld/rpc/RPCSub.h +++ b/src/xrpld/rpc/RPCSub.h @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { /** Subscription object for JSON RPC. */ class RPCSub : public InfoSub @@ -33,6 +33,6 @@ make_RPCSub( std::string const& strPassword, Logs& logs); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/Request.h b/src/xrpld/rpc/Request.h index ceab2944d7..c7b2cedef0 100644 --- a/src/xrpld/rpc/Request.h +++ b/src/xrpld/rpc/Request.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { class Application; @@ -51,6 +51,6 @@ private: }; } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/Role.h b/src/xrpld/rpc/Role.h index 6967474f17..04b288600a 100644 --- a/src/xrpld/rpc/Role.h +++ b/src/xrpld/rpc/Role.h @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { /** Indicates the level of administrative permission to grant. * IDENTIFIED role has unlimited resources but cannot perform some @@ -70,6 +70,6 @@ ipAllowed( std::string_view forwardedFor(http_request_type const& request); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/ServerHandler.h b/src/xrpld/rpc/ServerHandler.h index 4cf5a0ce88..0ad3144caf 100644 --- a/src/xrpld/rpc/ServerHandler.h +++ b/src/xrpld/rpc/ServerHandler.h @@ -20,7 +20,7 @@ #include #include -namespace ripple { +namespace xrpl { inline bool operator<(Port const& lhs, Port const& rhs) @@ -210,6 +210,6 @@ make_ServerHandler( Resource::Manager&, CollectorManager& cm); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/Status.h b/src/xrpld/rpc/Status.h index 2ff804f17c..f4ffcae9b2 100644 --- a/src/xrpld/rpc/Status.h +++ b/src/xrpld/rpc/Status.h @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { /** Status represents the results of an operation that might fail. @@ -77,7 +77,7 @@ public: toTER() const { XRPL_ASSERT( - type_ == Type::TER, "ripple::RPC::Status::toTER : type is TER"); + type_ == Type::TER, "xrpl::RPC::Status::toTER : type is TER"); return TER::fromInt(code_); } @@ -88,7 +88,7 @@ public: { XRPL_ASSERT( type_ == Type::error_code_i, - "ripple::RPC::Status::toTER : type is error code"); + "xrpl::RPC::Status::toTER : type is error code"); return error_code_i(code_); } @@ -139,6 +139,6 @@ private: }; } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/detail/DeliveredAmount.cpp b/src/xrpld/rpc/detail/DeliveredAmount.cpp index bcc7c4389d..7a0629a42d 100644 --- a/src/xrpld/rpc/detail/DeliveredAmount.cpp +++ b/src/xrpld/rpc/detail/DeliveredAmount.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { /* @@ -186,4 +186,4 @@ insertDeliveredAmount( } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/Handler.cpp b/src/xrpld/rpc/detail/Handler.cpp index a4a1be3343..2000af5e81 100644 --- a/src/xrpld/rpc/detail/Handler.cpp +++ b/src/xrpld/rpc/detail/Handler.cpp @@ -7,7 +7,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { namespace { @@ -21,7 +21,7 @@ byRef(Function const& f) if (result.type() != Json::objectValue) { // LCOV_EXCL_START - UNREACHABLE("ripple::RPC::byRef : result is object"); + UNREACHABLE("xrpl::RPC::byRef : result is object"); result = RPC::makeObjectValue(result); // LCOV_EXCL_STOP } @@ -37,7 +37,7 @@ handle(JsonContext& context, Object& object) XRPL_ASSERT( context.apiVersion >= HandlerImpl::minApiVer && context.apiVersion <= HandlerImpl::maxApiVer, - "ripple::RPC::handle : valid API version"); + "xrpl::RPC::handle : valid API version"); HandlerImpl handler(context); auto status = handler.check(); @@ -193,10 +193,10 @@ private: { XRPL_ASSERT( minVer <= maxVer, - "ripple::RPC::HandlerTable : valid API version range"); + "xrpl::RPC::HandlerTable : valid API version range"); XRPL_ASSERT( maxVer <= RPC::apiMaximumValidVersion, - "ripple::RPC::HandlerTable : valid max API version"); + "xrpl::RPC::HandlerTable : valid max API version"); return std::any_of( range.first, @@ -304,4 +304,4 @@ getHandlerNames() } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/Handler.h b/src/xrpld/rpc/detail/Handler.h index 8178d83dee..dac18c966f 100644 --- a/src/xrpld/rpc/detail/Handler.h +++ b/src/xrpld/rpc/detail/Handler.h @@ -13,7 +13,7 @@ namespace Json { class Object; } -namespace ripple { +namespace xrpl { namespace RPC { // Under what condition can we call this RPC? @@ -121,6 +121,6 @@ conditionMet(Condition condition_required, T& context) } } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/detail/InfoSub.cpp b/src/xrpld/rpc/detail/InfoSub.cpp index 14696292f8..a0869b9d96 100644 --- a/src/xrpld/rpc/detail/InfoSub.cpp +++ b/src/xrpld/rpc/detail/InfoSub.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { // This is the primary interface into the "client" portion of the program. // Code that wants to do normal operations on the network such as @@ -126,8 +126,8 @@ unsigned int InfoSub::getApiVersion() const noexcept { XRPL_ASSERT( - apiVersion_ > 0, "ripple::InfoSub::getApiVersion : valid API version"); + apiVersion_ > 0, "xrpl::InfoSub::getApiVersion : valid API version"); return apiVersion_; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/LegacyPathFind.cpp b/src/xrpld/rpc/detail/LegacyPathFind.cpp index c3bcd928cd..e06ae4062d 100644 --- a/src/xrpld/rpc/detail/LegacyPathFind.cpp +++ b/src/xrpld/rpc/detail/LegacyPathFind.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { LegacyPathFind::LegacyPathFind(bool isAdmin, Application& app) : m_isOk(false) @@ -50,4 +50,4 @@ LegacyPathFind::~LegacyPathFind() std::atomic LegacyPathFind::inProgress(0); } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/LegacyPathFind.h b/src/xrpld/rpc/detail/LegacyPathFind.h index 40fc11aee8..d175e7c532 100644 --- a/src/xrpld/rpc/detail/LegacyPathFind.h +++ b/src/xrpld/rpc/detail/LegacyPathFind.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Application; @@ -28,6 +28,6 @@ private: }; } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/detail/MPTokenIssuanceID.cpp b/src/xrpld/rpc/detail/MPTokenIssuanceID.cpp index 440b783316..3c7f2c5fc3 100644 --- a/src/xrpld/rpc/detail/MPTokenIssuanceID.cpp +++ b/src/xrpld/rpc/detail/MPTokenIssuanceID.cpp @@ -1,6 +1,6 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { @@ -56,4 +56,4 @@ insertMPTokenIssuanceID( } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/RPCCall.cpp b/src/xrpld/rpc/detail/RPCCall.cpp index 185043302a..fa1a089efb 100644 --- a/src/xrpld/rpc/detail/RPCCall.cpp +++ b/src/xrpld/rpc/detail/RPCCall.cpp @@ -28,7 +28,7 @@ #include #include -namespace ripple { +namespace xrpl { class RPCParser; @@ -102,7 +102,7 @@ private: jvParseCurrencyIssuer(std::string const& strCurrencyIssuer) { // Matches a sequence of 3 characters from - // `ripple::detail::isoCharSet` (the currency), + // `xrpl::detail::isoCharSet` (the currency), // optionally followed by a forward slash and some other characters // (the issuer). // https://www.boost.org/doc/libs/1_82_0/libs/regex/doc/html/boost_regex/syntax/perl_syntax.html @@ -140,7 +140,7 @@ private: std::string const& strPk, TokenType type = TokenType::AccountPublic) { - if (parseBase58(type, strPk)) + if (parseBase58(type, strPk)) return true; auto pkHex = strUnHex(strPk); @@ -1033,7 +1033,7 @@ private: // Parameter count should have already been verified. XRPL_ASSERT( jvParams.size() == 2, - "ripple::RPCParser::parseTransactionEntry : valid parameter count"); + "xrpl::RPCParser::parseTransactionEntry : valid parameter count"); std::string const txHash = jvParams[0u].asString(); if (txHash.length() != 64) @@ -1516,7 +1516,7 @@ rpcClient( } else { - ripple::ServerHandler::Setup setup; + xrpl::ServerHandler::Setup setup; try { setup = setup_ServerHandler( @@ -1720,4 +1720,4 @@ fromNetwork( } // namespace RPCCall -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/RPCHandler.cpp b/src/xrpld/rpc/detail/RPCHandler.cpp index fca926a1c7..eb5b3f7340 100644 --- a/src/xrpld/rpc/detail/RPCHandler.cpp +++ b/src/xrpld/rpc/detail/RPCHandler.cpp @@ -22,7 +22,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { namespace { @@ -250,4 +250,4 @@ roleRequired(unsigned int version, bool betaEnabled, std::string const& method) } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/RPCHelpers.cpp b/src/xrpld/rpc/detail/RPCHelpers.cpp index a9c75a05e8..d10f4f9a5a 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCHelpers.cpp @@ -15,7 +15,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { std::uint64_t @@ -355,7 +355,7 @@ chooseLedgerEntryType(Json::Value const& params) rpcINVALID_PARAMS, "Invalid field 'type', not string."}; XRPL_ASSERT( result.first.type() == RPC::Status::Type::error_code_i, - "ripple::RPC::chooseLedgerEntryType : first valid result type"); + "xrpl::RPC::chooseLedgerEntryType : first valid result type"); return result; } @@ -374,7 +374,7 @@ chooseLedgerEntryType(Json::Value const& params) RPC::Status{rpcINVALID_PARAMS, "Invalid field 'type'."}; XRPL_ASSERT( result.first.type() == RPC::Status::Type::error_code_i, - "ripple::RPC::chooseLedgerEntryType : second valid result " + "xrpl::RPC::chooseLedgerEntryType : second valid result " "type"); return result; } @@ -400,4 +400,4 @@ isAccountObjectsValidType(LedgerEntryType const& type) } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/RPCHelpers.h b/src/xrpld/rpc/detail/RPCHelpers.h index 3fa652d93b..0f26ca8667 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.h +++ b/src/xrpld/rpc/detail/RPCHelpers.h @@ -13,7 +13,7 @@ #include -namespace ripple { +namespace xrpl { class ReadView; @@ -160,6 +160,6 @@ keypairForSignature( } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp b/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp index d2bf7d5349..c58a7ba561 100644 --- a/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCLedgerHelpers.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { namespace { @@ -277,7 +277,7 @@ getLedger(T& ledger, LedgerShortcut shortcut, Context const& context) } XRPL_ASSERT( - !ledger->open(), "ripple::RPC::getLedger : validated is not open"); + !ledger->open(), "xrpl::RPC::getLedger : validated is not open"); } else { @@ -285,13 +285,13 @@ getLedger(T& ledger, LedgerShortcut shortcut, Context const& context) { ledger = context.ledgerMaster.getCurrentLedger(); XRPL_ASSERT( - ledger->open(), "ripple::RPC::getLedger : current is open"); + ledger->open(), "xrpl::RPC::getLedger : current is open"); } else if (shortcut == LedgerShortcut::Closed) { ledger = context.ledgerMaster.getClosedLedger(); XRPL_ASSERT( - !ledger->open(), "ripple::RPC::getLedger : closed is not open"); + !ledger->open(), "xrpl::RPC::getLedger : closed is not open"); } else { @@ -449,8 +449,7 @@ getOrAcquireLedger(RPC::JsonContext const& context) auto const refIndex = getCandidateLedger(ledgerIndex); auto refHash = hashOfSeq(*ledger, refIndex, j); XRPL_ASSERT( - refHash, - "ripple::RPC::getOrAcquireLedger : nonzero ledger hash"); + refHash, "xrpl::RPC::getOrAcquireLedger : nonzero ledger hash"); ledger = ledgerMaster.getLedgerByHash(*refHash); if (!ledger) @@ -485,8 +484,7 @@ getOrAcquireLedger(RPC::JsonContext const& context) neededHash = hashOfSeq(*ledger, ledgerIndex, j); } XRPL_ASSERT( - neededHash, - "ripple::RPC::getOrAcquireLedger : nonzero needed hash"); + neededHash, "xrpl::RPC::getOrAcquireLedger : nonzero needed hash"); ledgerHash = neededHash ? *neededHash : beast::zero; // kludge } @@ -510,4 +508,4 @@ getOrAcquireLedger(RPC::JsonContext const& context) } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/RPCLedgerHelpers.h b/src/xrpld/rpc/detail/RPCLedgerHelpers.h index 0a070a16ab..8fe81ef024 100644 --- a/src/xrpld/rpc/detail/RPCLedgerHelpers.h +++ b/src/xrpld/rpc/detail/RPCLedgerHelpers.h @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { class ReadView; class Transaction; @@ -176,6 +176,6 @@ getOrAcquireLedger(RPC::JsonContext const& context); } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/detail/RPCSub.cpp b/src/xrpld/rpc/detail/RPCSub.cpp index 9477eab231..5d008e4ee6 100644 --- a/src/xrpld/rpc/detail/RPCSub.cpp +++ b/src/xrpld/rpc/detail/RPCSub.cpp @@ -8,7 +8,7 @@ #include -namespace ripple { +namespace xrpl { // Subscription object for JSON-RPC class RPCSubImp : public RPCSub @@ -205,4 +205,4 @@ make_RPCSub( logs); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/Role.cpp b/src/xrpld/rpc/detail/Role.cpp index 95549068a0..28d00245a5 100644 --- a/src/xrpld/rpc/detail/Role.cpp +++ b/src/xrpld/rpc/detail/Role.cpp @@ -5,14 +5,14 @@ #include -namespace ripple { +namespace xrpl { bool passwordUnrequiredOrSentCorrect(Port const& port, Json::Value const& params) { XRPL_ASSERT( !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty()), - "ripple::passwordUnrequiredOrSentCorrect : non-empty admin nets"); + "xrpl::passwordUnrequiredOrSentCorrect : non-empty admin nets"); bool const passwordRequired = (!port.admin_user.empty() || !port.admin_password.empty()); @@ -292,4 +292,4 @@ forwardedFor(http_request_type const& request) return {}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/ServerHandler.cpp b/src/xrpld/rpc/detail/ServerHandler.cpp index de44f93749..91b709bc06 100644 --- a/src/xrpld/rpc/detail/ServerHandler.cpp +++ b/src/xrpld/rpc/detail/ServerHandler.cpp @@ -35,7 +35,7 @@ #include #include -namespace ripple { +namespace xrpl { class Peer; class LedgerMaster; @@ -1276,4 +1276,4 @@ make_ServerHandler( cm); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/Status.cpp b/src/xrpld/rpc/detail/Status.cpp index 3b5aded8b2..ce3082f0fa 100644 --- a/src/xrpld/rpc/detail/Status.cpp +++ b/src/xrpld/rpc/detail/Status.cpp @@ -2,7 +2,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { std::string @@ -19,7 +19,7 @@ Status::codeString() const std::string s1, s2; [[maybe_unused]] auto const success = transResultInfo(toTER(), s1, s2); - XRPL_ASSERT(success, "ripple::RPC::codeString : valid TER result"); + XRPL_ASSERT(success, "xrpl::RPC::codeString : valid TER result"); return s1 + ": " + s2; } @@ -33,7 +33,7 @@ Status::codeString() const } // LCOV_EXCL_START - UNREACHABLE("ripple::RPC::codeString : invalid type"); + UNREACHABLE("xrpl::RPC::codeString : invalid type"); return ""; // LCOV_EXCL_STOP } @@ -80,4 +80,4 @@ Status::toString() const } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/TransactionSign.cpp b/src/xrpld/rpc/detail/TransactionSign.cpp index 8ca58d671e..252e5fc91e 100644 --- a/src/xrpld/rpc/detail/TransactionSign.cpp +++ b/src/xrpld/rpc/detail/TransactionSign.cpp @@ -24,7 +24,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { namespace detail { @@ -654,7 +654,7 @@ transactionPreProcessImpl( { Serializer s = buildMultiSigningData(*stTx, signingArgs.getSigner()); - auto multisig = ripple::sign(pk, sk, s.slice()); + auto multisig = xrpl::sign(pk, sk, s.slice()); signingArgs.moveMultiSignature(std::move(multisig)); } @@ -1206,7 +1206,7 @@ transactionSignFor( XRPL_ASSERT( signForParams.validMultiSign(), - "ripple::RPC::transactionSignFor : valid multi-signature"); + "xrpl::RPC::transactionSignFor : valid multi-signature"); { std::shared_ptr account_state = @@ -1452,4 +1452,4 @@ transactionSubmitMultiSigned( } } // namespace RPC -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/detail/TransactionSign.h b/src/xrpld/rpc/detail/TransactionSign.h index ba14ad0cdc..181737ad28 100644 --- a/src/xrpld/rpc/detail/TransactionSign.h +++ b/src/xrpld/rpc/detail/TransactionSign.h @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // Forward declarations class Application; @@ -126,6 +126,6 @@ transactionSubmitMultiSigned( ProcessTransactionFn const& processTransaction); } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/detail/Tuning.h b/src/xrpld/rpc/detail/Tuning.h index 902ba2ecf0..5837146b02 100644 --- a/src/xrpld/rpc/detail/Tuning.h +++ b/src/xrpld/rpc/detail/Tuning.h @@ -1,7 +1,7 @@ #ifndef XRPL_RPC_TUNING_H_INCLUDED #define XRPL_RPC_TUNING_H_INCLUDED -namespace ripple { +namespace xrpl { namespace RPC { /** Tuned constants. */ @@ -71,6 +71,6 @@ static int constexpr max_auto_src_cur = 88; /** @} */ } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/detail/WSInfoSub.h b/src/xrpld/rpc/detail/WSInfoSub.h index 707f81fb19..91dc47fa2b 100644 --- a/src/xrpld/rpc/detail/WSInfoSub.h +++ b/src/xrpld/rpc/detail/WSInfoSub.h @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { class WSInfoSub : public InfoSub { @@ -65,6 +65,6 @@ public: } }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/handlers/AMMInfo.cpp b/src/xrpld/rpc/handlers/AMMInfo.cpp index 5ea826fce5..7bf2dd7eae 100644 --- a/src/xrpld/rpc/handlers/AMMInfo.cpp +++ b/src/xrpld/rpc/handlers/AMMInfo.cpp @@ -10,7 +10,7 @@ #include -namespace ripple { +namespace xrpl { Expected getIssue(Json::Value const& v, beast::Journal j) @@ -118,12 +118,12 @@ doAMMInfo(RPC::JsonContext& context) XRPL_ASSERT( (issue1.has_value() == issue2.has_value()) && (issue1.has_value() != ammID.has_value()), - "ripple::doAMMInfo : issue1 and issue2 do match"); + "xrpl::doAMMInfo : issue1 and issue2 do match"); auto const ammKeylet = [&]() { if (issue1 && issue2) return keylet::amm(*issue1, *issue2); - XRPL_ASSERT(ammID, "ripple::doAMMInfo::ammKeylet : ammID is set"); + XRPL_ASSERT(ammID, "xrpl::doAMMInfo::ammKeylet : ammID is set"); return keylet::amm(*ammID); }(); auto const amm = ledger->read(ammKeylet); @@ -185,7 +185,7 @@ doAMMInfo(RPC::JsonContext& context) XRPL_ASSERT( !ledger->rules().enabled(fixInnerObjTemplate) || amm->isFieldPresent(sfAuctionSlot), - "ripple::doAMMInfo : auction slot is set"); + "xrpl::doAMMInfo : auction slot is set"); if (amm->isFieldPresent(sfAuctionSlot)) { auto const& auctionSlot = @@ -236,4 +236,4 @@ doAMMInfo(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/AccountChannels.cpp b/src/xrpld/rpc/handlers/AccountChannels.cpp index 281b0ec8c4..597a6f893a 100644 --- a/src/xrpld/rpc/handlers/AccountChannels.cpp +++ b/src/xrpld/rpc/handlers/AccountChannels.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { void addChannel(Json::Value& jsonLines, SLE const& line) @@ -149,7 +149,7 @@ doAccountChannels(RPC::JsonContext& context) if (!sleCur) { // LCOV_EXCL_START - UNREACHABLE("ripple::doAccountChannels : null SLE"); + UNREACHABLE("xrpl::doAccountChannels : null SLE"); return false; // LCOV_EXCL_STOP } @@ -194,4 +194,4 @@ doAccountChannels(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/AccountCurrenciesHandler.cpp b/src/xrpld/rpc/handlers/AccountCurrenciesHandler.cpp index 10f22ad654..cc43992723 100644 --- a/src/xrpld/rpc/handlers/AccountCurrenciesHandler.cpp +++ b/src/xrpld/rpc/handlers/AccountCurrenciesHandler.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doAccountCurrencies(RPC::JsonContext& context) @@ -76,4 +76,4 @@ doAccountCurrencies(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index 1bf05276f2..30d16e3099 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -13,7 +13,7 @@ #include -namespace ripple { +namespace xrpl { /** * @brief Injects JSON describing a ledger entry. @@ -179,7 +179,7 @@ doAccountInfo(RPC::JsonContext& context) name = name.substr(0, name.size() - 2); XRPL_ASSERT_PARTS( !name.empty(), - "ripple::doAccountInfo", + "xrpl::doAccountInfo", "name is not empty"); } // ValidPseudoAccounts invariant guarantees that only one field @@ -331,4 +331,4 @@ doAccountInfo(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/AccountLines.cpp b/src/xrpld/rpc/handlers/AccountLines.cpp index b28f4d7483..fc92707aa6 100644 --- a/src/xrpld/rpc/handlers/AccountLines.cpp +++ b/src/xrpld/rpc/handlers/AccountLines.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { void addLine(Json::Value& jsonLines, RPCTrustLine const& line) @@ -173,7 +173,7 @@ doAccountLines(RPC::JsonContext& context) if (!sleCur) { // LCOV_EXCL_START - UNREACHABLE("ripple::doAccountLines : null SLE"); + UNREACHABLE("xrpl::doAccountLines : null SLE"); return false; // LCOV_EXCL_STOP } @@ -240,4 +240,4 @@ doAccountLines(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/AccountObjects.cpp b/src/xrpld/rpc/handlers/AccountObjects.cpp index 669d96a44f..6440c78e58 100644 --- a/src/xrpld/rpc/handlers/AccountObjects.cpp +++ b/src/xrpld/rpc/handlers/AccountObjects.cpp @@ -15,7 +15,7 @@ #include -namespace ripple { +namespace xrpl { /** General RPC command that can retrieve objects in the account root. { @@ -482,4 +482,4 @@ doAccountObjects(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/AccountOffers.cpp b/src/xrpld/rpc/handlers/AccountOffers.cpp index e8bc2bcf79..c0f29b0b8f 100644 --- a/src/xrpld/rpc/handlers/AccountOffers.cpp +++ b/src/xrpld/rpc/handlers/AccountOffers.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { void appendOfferJson(std::shared_ptr const& offer, Json::Value& offers) @@ -125,7 +125,7 @@ doAccountOffers(RPC::JsonContext& context) if (!sle) { // LCOV_EXCL_START - UNREACHABLE("ripple::doAccountOffers : null SLE"); + UNREACHABLE("xrpl::doAccountOffers : null SLE"); return false; // LCOV_EXCL_STOP } @@ -164,4 +164,4 @@ doAccountOffers(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/AccountTx.cpp b/src/xrpld/rpc/handlers/AccountTx.cpp index efb246b4d5..362bdd0eaa 100644 --- a/src/xrpld/rpc/handlers/AccountTx.cpp +++ b/src/xrpld/rpc/handlers/AccountTx.cpp @@ -19,7 +19,7 @@ #include #include -namespace ripple { +namespace xrpl { using TxnsData = RelationalDatabase::AccountTxs; using TxnsDataBinary = RelationalDatabase::MetaTxsList; @@ -289,8 +289,7 @@ populateJsonResponse( if (auto txnsData = std::get_if(&result.transactions)) { XRPL_ASSERT( - !args.binary, - "ripple::populateJsonResponse : binary is not set"); + !args.binary, "xrpl::populateJsonResponse : binary is not set"); for (auto const& [txn, txnMeta] : *txnsData) { @@ -340,7 +339,7 @@ populateJsonResponse( { // LCOV_EXCL_START UNREACHABLE( - "ripple::populateJsonResponse : missing " + "xrpl::populateJsonResponse : missing " "transaction medatata"); // LCOV_EXCL_STOP } @@ -350,7 +349,7 @@ populateJsonResponse( else { XRPL_ASSERT( - args.binary, "ripple::populateJsonResponse : binary is set"); + args.binary, "xrpl::populateJsonResponse : binary is set"); for (auto const& binaryData : std::get(result.transactions)) @@ -466,4 +465,4 @@ doAccountTxJson(RPC::JsonContext& context) return populateJsonResponse(res, args, context); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/BlackList.cpp b/src/xrpld/rpc/handlers/BlackList.cpp index 859eb1fbce..102041b8d0 100644 --- a/src/xrpld/rpc/handlers/BlackList.cpp +++ b/src/xrpld/rpc/handlers/BlackList.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doBlackList(RPC::JsonContext& context) @@ -16,4 +16,4 @@ doBlackList(RPC::JsonContext& context) return rm.getJson(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/BookOffers.cpp b/src/xrpld/rpc/handlers/BookOffers.cpp index e82b2fa345..6cbefe5dc7 100644 --- a/src/xrpld/rpc/handlers/BookOffers.cpp +++ b/src/xrpld/rpc/handlers/BookOffers.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doBookOffers(RPC::JsonContext& context) @@ -212,4 +212,4 @@ doBookChanges(RPC::JsonContext& context) return RPC::computeBookChanges(ledger); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/CanDelete.cpp b/src/xrpld/rpc/handlers/CanDelete.cpp index d07d344242..ea19736bc2 100644 --- a/src/xrpld/rpc/handlers/CanDelete.cpp +++ b/src/xrpld/rpc/handlers/CanDelete.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { // can_delete [||now|always|never] Json::Value @@ -79,4 +79,4 @@ doCanDelete(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Connect.cpp b/src/xrpld/rpc/handlers/Connect.cpp index 2c6d67c3f0..2cd3b70149 100644 --- a/src/xrpld/rpc/handlers/Connect.cpp +++ b/src/xrpld/rpc/handlers/Connect.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // ip: , @@ -51,4 +51,4 @@ doConnect(RPC::JsonContext& context) " port: " + std::to_string(iPort)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/ConsensusInfo.cpp b/src/xrpld/rpc/handlers/ConsensusInfo.cpp index 8459cc6520..386ff99458 100644 --- a/src/xrpld/rpc/handlers/ConsensusInfo.cpp +++ b/src/xrpld/rpc/handlers/ConsensusInfo.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doConsensusInfo(RPC::JsonContext& context) @@ -17,4 +17,4 @@ doConsensusInfo(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/DepositAuthorized.cpp b/src/xrpld/rpc/handlers/DepositAuthorized.cpp index 7beaffaf99..8c2f7dce96 100644 --- a/src/xrpld/rpc/handlers/DepositAuthorized.cpp +++ b/src/xrpld/rpc/handlers/DepositAuthorized.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // source_account : @@ -182,4 +182,4 @@ doDepositAuthorized(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/DoManifest.cpp b/src/xrpld/rpc/handlers/DoManifest.cpp index eabdc51d56..5928947e21 100644 --- a/src/xrpld/rpc/handlers/DoManifest.cpp +++ b/src/xrpld/rpc/handlers/DoManifest.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doManifest(RPC::JsonContext& context) { @@ -56,4 +56,4 @@ doManifest(RPC::JsonContext& context) ret[jss::details] = details; return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Feature1.cpp b/src/xrpld/rpc/handlers/Feature1.cpp index f452f562c2..dc1ccaee6c 100644 --- a/src/xrpld/rpc/handlers/Feature1.cpp +++ b/src/xrpld/rpc/handlers/Feature1.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // feature : @@ -78,4 +78,4 @@ doFeature(RPC::JsonContext& context) return jvReply; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Fee1.cpp b/src/xrpld/rpc/handlers/Fee1.cpp index 8349c67875..49a36261f4 100644 --- a/src/xrpld/rpc/handlers/Fee1.cpp +++ b/src/xrpld/rpc/handlers/Fee1.cpp @@ -6,7 +6,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value doFee(RPC::JsonContext& context) { @@ -15,10 +15,10 @@ doFee(RPC::JsonContext& context) return result; // LCOV_EXCL_START - UNREACHABLE("ripple::doFee : invalid result type"); + UNREACHABLE("xrpl::doFee : invalid result type"); RPC::inject_error(rpcINTERNAL, context.params); return context.params; // LCOV_EXCL_STOP } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/FetchInfo.cpp b/src/xrpld/rpc/handlers/FetchInfo.cpp index 9e3f61495b..0c251fe9d6 100644 --- a/src/xrpld/rpc/handlers/FetchInfo.cpp +++ b/src/xrpld/rpc/handlers/FetchInfo.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doFetchInfo(RPC::JsonContext& context) @@ -24,4 +24,4 @@ doFetchInfo(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/GatewayBalances.cpp b/src/xrpld/rpc/handlers/GatewayBalances.cpp index 88411b020e..55959d8641 100644 --- a/src/xrpld/rpc/handlers/GatewayBalances.cpp +++ b/src/xrpld/rpc/handlers/GatewayBalances.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { // Query: // 1) Specify ledger to query. @@ -271,4 +271,4 @@ doGatewayBalances(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/GetAggregatePrice.cpp b/src/xrpld/rpc/handlers/GetAggregatePrice.cpp index c74a4331fd..6d40ee707b 100644 --- a/src/xrpld/rpc/handlers/GetAggregatePrice.cpp +++ b/src/xrpld/rpc/handlers/GetAggregatePrice.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { using namespace boost::bimaps; // sorted descending by lastUpdateTime, ascending by AssetPrice @@ -361,4 +361,4 @@ doGetAggregatePrice(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/GetCounts.cpp b/src/xrpld/rpc/handlers/GetCounts.cpp index 17b2c8565b..ad158a57a5 100644 --- a/src/xrpld/rpc/handlers/GetCounts.cpp +++ b/src/xrpld/rpc/handlers/GetCounts.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { static void textTime( @@ -126,4 +126,4 @@ doGetCounts(RPC::JsonContext& context) return getCountsJson(context.app, minCount); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/GetCounts.h b/src/xrpld/rpc/handlers/GetCounts.h index aed024ca1a..0d544a4f11 100644 --- a/src/xrpld/rpc/handlers/GetCounts.h +++ b/src/xrpld/rpc/handlers/GetCounts.h @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value getCountsJson(Application& app, int minObjectCount); diff --git a/src/xrpld/rpc/handlers/Handlers.h b/src/xrpld/rpc/handlers/Handlers.h index 6f4abfd421..773186237b 100644 --- a/src/xrpld/rpc/handlers/Handlers.h +++ b/src/xrpld/rpc/handlers/Handlers.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value doAccountCurrencies(RPC::JsonContext&); @@ -149,6 +149,6 @@ Json::Value doValidatorInfo(RPC::JsonContext&); Json::Value doVaultInfo(RPC::JsonContext&); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/handlers/LedgerAccept.cpp b/src/xrpld/rpc/handlers/LedgerAccept.cpp index 6221b2f7fc..8938e3f152 100644 --- a/src/xrpld/rpc/handlers/LedgerAccept.cpp +++ b/src/xrpld/rpc/handlers/LedgerAccept.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value doLedgerAccept(RPC::JsonContext& context) @@ -31,4 +31,4 @@ doLedgerAccept(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerCleanerHandler.cpp b/src/xrpld/rpc/handlers/LedgerCleanerHandler.cpp index 5926bfed8f..408cd16023 100644 --- a/src/xrpld/rpc/handlers/LedgerCleanerHandler.cpp +++ b/src/xrpld/rpc/handlers/LedgerCleanerHandler.cpp @@ -5,7 +5,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value doLedgerCleaner(RPC::JsonContext& context) @@ -14,4 +14,4 @@ doLedgerCleaner(RPC::JsonContext& context) return RPC::makeObjectValue("Cleaner configured"); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerClosed.cpp b/src/xrpld/rpc/handlers/LedgerClosed.cpp index 3628c0f8d6..3b93e0734f 100644 --- a/src/xrpld/rpc/handlers/LedgerClosed.cpp +++ b/src/xrpld/rpc/handlers/LedgerClosed.cpp @@ -5,13 +5,13 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doLedgerClosed(RPC::JsonContext& context) { auto ledger = context.ledgerMaster.getClosedLedger(); - XRPL_ASSERT(ledger, "ripple::doLedgerClosed : non-null closed ledger"); + XRPL_ASSERT(ledger, "xrpl::doLedgerClosed : non-null closed ledger"); Json::Value jvResult; jvResult[jss::ledger_index] = ledger->header().seq; @@ -20,4 +20,4 @@ doLedgerClosed(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerCurrent.cpp b/src/xrpld/rpc/handlers/LedgerCurrent.cpp index 84e9820ac5..21b72147c6 100644 --- a/src/xrpld/rpc/handlers/LedgerCurrent.cpp +++ b/src/xrpld/rpc/handlers/LedgerCurrent.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doLedgerCurrent(RPC::JsonContext& context) @@ -16,4 +16,4 @@ doLedgerCurrent(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerData.cpp b/src/xrpld/rpc/handlers/LedgerData.cpp index 35e5055242..5e0c9152e7 100644 --- a/src/xrpld/rpc/handlers/LedgerData.cpp +++ b/src/xrpld/rpc/handlers/LedgerData.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { // Get state nodes from a ledger // Inputs: @@ -192,4 +192,4 @@ doLedgerDataGrpc( return {response, status}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerDiff.cpp b/src/xrpld/rpc/handlers/LedgerDiff.cpp index 3628138329..61ab7da93f 100644 --- a/src/xrpld/rpc/handlers/LedgerDiff.cpp +++ b/src/xrpld/rpc/handlers/LedgerDiff.cpp @@ -1,7 +1,7 @@ #include #include -namespace ripple { +namespace xrpl { std::pair doLedgerDiffGrpc( RPC::GRPCContext& context) @@ -75,7 +75,7 @@ doLedgerDiffGrpc( { XRPL_ASSERT( inDesired->size() > 0, - "ripple::doLedgerDiffGrpc : non-empty desired"); + "xrpl::doLedgerDiffGrpc : non-empty desired"); diff->set_key(k.data(), k.size()); if (request.include_blobs()) { @@ -86,4 +86,4 @@ doLedgerDiffGrpc( return {response, status}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index 5a1dfb4ace..5b5db72c22 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { static Expected parseObjectID( @@ -918,4 +918,4 @@ doLedgerEntryGrpc( *(response.mutable_ledger()) = request.ledger(); return {response, status}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerEntryHelpers.h b/src/xrpld/rpc/handlers/LedgerEntryHelpers.h index d83b7e2896..0a4453c063 100644 --- a/src/xrpld/rpc/handlers/LedgerEntryHelpers.h +++ b/src/xrpld/rpc/handlers/LedgerEntryHelpers.h @@ -12,7 +12,7 @@ #include -namespace ripple { +namespace xrpl { namespace LedgerEntryHelpers { @@ -277,4 +277,4 @@ parseBridgeFields(Json::Value const& params) } // namespace LedgerEntryHelpers -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerHandler.cpp b/src/xrpld/rpc/handlers/LedgerHandler.cpp index 14c6fc67d9..2929776549 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.cpp +++ b/src/xrpld/rpc/handlers/LedgerHandler.cpp @@ -10,7 +10,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { LedgerHandler::LedgerHandler(JsonContext& context) : context_(context) @@ -114,7 +114,7 @@ doLedgerGrpc(RPC::GRPCContext& context) for (auto& i : ledger->txs) { XRPL_ASSERT( - i.first, "ripple::doLedgerGrpc : non-null transaction"); + i.first, "xrpl::doLedgerGrpc : non-null transaction"); if (request.expand()) { auto txn = response.mutable_transactions_list() @@ -192,7 +192,7 @@ doLedgerGrpc(RPC::GRPCContext& context) { XRPL_ASSERT( inDesired->size() > 0, - "ripple::doLedgerGrpc : non-empty desired"); + "xrpl::doLedgerGrpc : non-empty desired"); obj->set_data(inDesired->data(), inDesired->size()); } if (inBase && inDesired) @@ -298,4 +298,4 @@ doLedgerGrpc(RPC::GRPCContext& context) return {response, status}; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerHandler.h b/src/xrpld/rpc/handlers/LedgerHandler.h index e1a789b66f..fbf60fb22e 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.h +++ b/src/xrpld/rpc/handlers/LedgerHandler.h @@ -18,7 +18,7 @@ namespace Json { class Object; } -namespace ripple { +namespace xrpl { namespace RPC { struct JsonContext; @@ -103,6 +103,6 @@ LedgerHandler::writeResult(Object& value) } } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/handlers/LedgerHeader.cpp b/src/xrpld/rpc/handlers/LedgerHeader.cpp index 8c34b8a7cc..6b93594020 100644 --- a/src/xrpld/rpc/handlers/LedgerHeader.cpp +++ b/src/xrpld/rpc/handlers/LedgerHeader.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // ledger_hash : @@ -31,4 +31,4 @@ doLedgerHeader(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LedgerRequest.cpp b/src/xrpld/rpc/handlers/LedgerRequest.cpp index 8ae0e543f2..da29addd2d 100644 --- a/src/xrpld/rpc/handlers/LedgerRequest.cpp +++ b/src/xrpld/rpc/handlers/LedgerRequest.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // ledger_hash : @@ -29,4 +29,4 @@ doLedgerRequest(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LogLevel.cpp b/src/xrpld/rpc/handlers/LogLevel.cpp index cf5a1d2573..373db55fa0 100644 --- a/src/xrpld/rpc/handlers/LogLevel.cpp +++ b/src/xrpld/rpc/handlers/LogLevel.cpp @@ -9,7 +9,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value doLogLevel(RPC::JsonContext& context) @@ -64,4 +64,4 @@ doLogLevel(RPC::JsonContext& context) return rpcError(rpcINVALID_PARAMS); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/LogRotate.cpp b/src/xrpld/rpc/handlers/LogRotate.cpp index 595d84b191..3d52dc6538 100644 --- a/src/xrpld/rpc/handlers/LogRotate.cpp +++ b/src/xrpld/rpc/handlers/LogRotate.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doLogRotate(RPC::JsonContext& context) @@ -13,4 +13,4 @@ doLogRotate(RPC::JsonContext& context) return RPC::makeObjectValue(context.app.logs().rotate()); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/NFTOffers.cpp b/src/xrpld/rpc/handlers/NFTOffers.cpp index 51290a404c..3c6898b5c2 100644 --- a/src/xrpld/rpc/handlers/NFTOffers.cpp +++ b/src/xrpld/rpc/handlers/NFTOffers.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { static void appendNftOfferJson( @@ -157,4 +157,4 @@ doNFTBuyOffers(RPC::JsonContext& context) return enumerateNFTOffers(context, nftId, keylet::nft_buys(nftId)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/NoRippleCheck.cpp b/src/xrpld/rpc/handlers/NoRippleCheck.cpp index 9ff2757a40..521ba1599a 100644 --- a/src/xrpld/rpc/handlers/NoRippleCheck.cpp +++ b/src/xrpld/rpc/handlers/NoRippleCheck.cpp @@ -12,7 +12,7 @@ #include #include -namespace ripple { +namespace xrpl { static void fillTransaction( @@ -185,4 +185,4 @@ doNoRippleCheck(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/OwnerInfo.cpp b/src/xrpld/rpc/handlers/OwnerInfo.cpp index 8f43bfcc99..37a4ceb60d 100644 --- a/src/xrpld/rpc/handlers/OwnerInfo.cpp +++ b/src/xrpld/rpc/handlers/OwnerInfo.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // 'ident' : , @@ -40,4 +40,4 @@ doOwnerInfo(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/PathFind.cpp b/src/xrpld/rpc/handlers/PathFind.cpp index 430212fe46..55575b5513 100644 --- a/src/xrpld/rpc/handlers/PathFind.cpp +++ b/src/xrpld/rpc/handlers/PathFind.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doPathFind(RPC::JsonContext& context) @@ -63,4 +63,4 @@ doPathFind(RPC::JsonContext& context) return rpcError(rpcINVALID_PARAMS); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/PayChanClaim.cpp b/src/xrpld/rpc/handlers/PayChanClaim.cpp index 95c4ba5f3d..89eb1806b8 100644 --- a/src/xrpld/rpc/handlers/PayChanClaim.cpp +++ b/src/xrpld/rpc/handlers/PayChanClaim.cpp @@ -11,7 +11,7 @@ #include -namespace ripple { +namespace xrpl { // { // secret_key: @@ -45,7 +45,7 @@ doChannelAuthorize(RPC::JsonContext& context) XRPL_ASSERT( keyPair || RPC::contains_error(result), - "ripple::doChannelAuthorize : valid keyPair or an error"); + "xrpl::doChannelAuthorize : valid keyPair or an error"); if (!keyPair || RPC::contains_error(result)) return result; @@ -141,4 +141,4 @@ doChannelVerify(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Peers.cpp b/src/xrpld/rpc/handlers/Peers.cpp index ba9f459b41..5a34f4b557 100644 --- a/src/xrpld/rpc/handlers/Peers.cpp +++ b/src/xrpld/rpc/handlers/Peers.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doPeers(RPC::JsonContext& context) @@ -63,4 +63,4 @@ doPeers(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Ping.cpp b/src/xrpld/rpc/handlers/Ping.cpp index 459f743e86..cc3c558cd9 100644 --- a/src/xrpld/rpc/handlers/Ping.cpp +++ b/src/xrpld/rpc/handlers/Ping.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { struct JsonContext; @@ -41,4 +41,4 @@ doPing(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Print.cpp b/src/xrpld/rpc/handlers/Print.cpp index 2c3b886797..6ea1f355aa 100644 --- a/src/xrpld/rpc/handlers/Print.cpp +++ b/src/xrpld/rpc/handlers/Print.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doPrint(RPC::JsonContext& context) @@ -24,4 +24,4 @@ doPrint(RPC::JsonContext& context) return stream.top(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Random.cpp b/src/xrpld/rpc/handlers/Random.cpp index 7156e20f59..2fb8abf3c9 100644 --- a/src/xrpld/rpc/handlers/Random.cpp +++ b/src/xrpld/rpc/handlers/Random.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { namespace RPC { struct JsonContext; @@ -36,4 +36,4 @@ doRandom(RPC::JsonContext& context) } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Reservations.cpp b/src/xrpld/rpc/handlers/Reservations.cpp index 2c7ec2d8c9..195a5be453 100644 --- a/src/xrpld/rpc/handlers/Reservations.cpp +++ b/src/xrpld/rpc/handlers/Reservations.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doPeerReservationsAdd(RPC::JsonContext& context) @@ -108,4 +108,4 @@ doPeerReservationsList(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/RipplePathFind.cpp b/src/xrpld/rpc/handlers/RipplePathFind.cpp index 771c1cb95f..5baf6820f4 100644 --- a/src/xrpld/rpc/handlers/RipplePathFind.cpp +++ b/src/xrpld/rpc/handlers/RipplePathFind.cpp @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { // This interface is deprecated. Json::Value @@ -155,4 +155,4 @@ doRipplePathFind(RPC::JsonContext& context) return result; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/ServerDefinitions.cpp b/src/xrpld/rpc/handlers/ServerDefinitions.cpp index a25716066e..9fce4d5a5b 100644 --- a/src/xrpld/rpc/handlers/ServerDefinitions.cpp +++ b/src/xrpld/rpc/handlers/ServerDefinitions.cpp @@ -14,7 +14,7 @@ #include -namespace ripple { +namespace xrpl { namespace detail { @@ -214,7 +214,7 @@ ServerDefinitions::ServerDefinitions() : defs_{Json::objectValue} defs_[jss::FIELDS][i++] = a; } - for (auto const& [code, f] : ripple::SField::getKnownCodeToField()) + for (auto const& [code, f] : xrpl::SField::getKnownCodeToField()) { if (f->fieldName == "") continue; @@ -268,7 +268,7 @@ ServerDefinitions::ServerDefinitions() : defs_{Json::objectValue} // generate hash { std::string const out = Json::FastWriter().write(defs_); - defsHash_ = ripple::sha512Half(ripple::Slice{out.data(), out.size()}); + defsHash_ = xrpl::sha512Half(xrpl::Slice{out.data(), out.size()}); defs_[jss::hash] = to_string(defsHash_); } } @@ -298,4 +298,4 @@ doServerDefinitions(RPC::JsonContext& context) return defs.get(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/ServerInfo.cpp b/src/xrpld/rpc/handlers/ServerInfo.cpp index c13ebfe788..c7bd7f271d 100644 --- a/src/xrpld/rpc/handlers/ServerInfo.cpp +++ b/src/xrpld/rpc/handlers/ServerInfo.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doServerInfo(RPC::JsonContext& context) @@ -22,4 +22,4 @@ doServerInfo(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/ServerState.cpp b/src/xrpld/rpc/handlers/ServerState.cpp index 7769b32f71..4ec08540fb 100644 --- a/src/xrpld/rpc/handlers/ServerState.cpp +++ b/src/xrpld/rpc/handlers/ServerState.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doServerState(RPC::JsonContext& context) @@ -21,4 +21,4 @@ doServerState(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/SignFor.cpp b/src/xrpld/rpc/handlers/SignFor.cpp index 5750e20245..7926dd7c8e 100644 --- a/src/xrpld/rpc/handlers/SignFor.cpp +++ b/src/xrpld/rpc/handlers/SignFor.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // tx_json: , @@ -40,4 +40,4 @@ doSignFor(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/SignHandler.cpp b/src/xrpld/rpc/handlers/SignHandler.cpp index 5a6a5a2947..cab957d8c7 100644 --- a/src/xrpld/rpc/handlers/SignHandler.cpp +++ b/src/xrpld/rpc/handlers/SignHandler.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // tx_json: , @@ -41,4 +41,4 @@ doSign(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Simulate.cpp b/src/xrpld/rpc/handlers/Simulate.cpp index 42cdd66a69..09d9688ad0 100644 --- a/src/xrpld/rpc/handlers/Simulate.cpp +++ b/src/xrpld/rpc/handlers/Simulate.cpp @@ -16,7 +16,7 @@ #include #include -namespace ripple { +namespace xrpl { static Expected getAutofillSequence(Json::Value const& tx_json, RPC::JsonContext& context) @@ -369,4 +369,4 @@ doSimulate(RPC::JsonContext& context) // LCOV_EXCL_STOP } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Stop.cpp b/src/xrpld/rpc/handlers/Stop.cpp index 33221d601d..d2f1cd7a80 100644 --- a/src/xrpld/rpc/handlers/Stop.cpp +++ b/src/xrpld/rpc/handlers/Stop.cpp @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { struct JsonContext; @@ -16,4 +16,4 @@ doStop(RPC::JsonContext& context) return RPC::makeObjectValue(systemName() + " server stopping"); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Submit.cpp b/src/xrpld/rpc/handlers/Submit.cpp index 5cce61a1a6..e3888187ae 100644 --- a/src/xrpld/rpc/handlers/Submit.cpp +++ b/src/xrpld/rpc/handlers/Submit.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { static NetworkOPs::FailHard getFailHard(RPC::JsonContext const& context) @@ -173,4 +173,4 @@ doSubmit(RPC::JsonContext& context) } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/SubmitMultiSigned.cpp b/src/xrpld/rpc/handlers/SubmitMultiSigned.cpp index 614ba4abbf..52213e174a 100644 --- a/src/xrpld/rpc/handlers/SubmitMultiSigned.cpp +++ b/src/xrpld/rpc/handlers/SubmitMultiSigned.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // SigningAccounts , @@ -28,4 +28,4 @@ doSubmitMultiSigned(RPC::JsonContext& context) RPC::getProcessTxnFn(context.netOps)); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Subscribe.cpp b/src/xrpld/rpc/handlers/Subscribe.cpp index ab4f20d8ce..018268defb 100644 --- a/src/xrpld/rpc/handlers/Subscribe.cpp +++ b/src/xrpld/rpc/handlers/Subscribe.cpp @@ -13,7 +13,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doSubscribe(RPC::JsonContext& context) @@ -367,4 +367,4 @@ doSubscribe(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/TransactionEntry.cpp b/src/xrpld/rpc/handlers/TransactionEntry.cpp index 9553c2d41e..a554b242c5 100644 --- a/src/xrpld/rpc/handlers/TransactionEntry.cpp +++ b/src/xrpld/rpc/handlers/TransactionEntry.cpp @@ -6,7 +6,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // ledger_hash : , @@ -95,4 +95,4 @@ doTransactionEntry(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Tx.cpp b/src/xrpld/rpc/handlers/Tx.cpp index e7e812563d..c79f40ce3d 100644 --- a/src/xrpld/rpc/handlers/Tx.cpp +++ b/src/xrpld/rpc/handlers/Tx.cpp @@ -18,7 +18,7 @@ #include -namespace ripple { +namespace xrpl { static bool isValidated(LedgerMaster& ledgerMaster, std::uint32_t seq, uint256 const& hash) @@ -236,7 +236,7 @@ populateJsonResponse( if (auto blob = std::get_if(&result.meta)) { XRPL_ASSERT( - args.binary, "ripple::populateJsonResponse : binary is set"); + args.binary, "xrpl::populateJsonResponse : binary is set"); auto json_meta = (context.apiVersion > 1 ? jss::meta_blob : jss::meta); response[json_meta] = strHex(makeSlice(*blob)); @@ -327,4 +327,4 @@ doTxJson(RPC::JsonContext& context) return populateJsonResponse(res, args, context); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/TxHistory.cpp b/src/xrpld/rpc/handlers/TxHistory.cpp index 9c8c2faece..a210f61c54 100644 --- a/src/xrpld/rpc/handlers/TxHistory.cpp +++ b/src/xrpld/rpc/handlers/TxHistory.cpp @@ -11,7 +11,7 @@ #include #include -namespace ripple { +namespace xrpl { // { // start: @@ -49,4 +49,4 @@ doTxHistory(RPC::JsonContext& context) return obj; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/TxReduceRelay.cpp b/src/xrpld/rpc/handlers/TxReduceRelay.cpp index e2ef4c5b18..d269ef448e 100644 --- a/src/xrpld/rpc/handlers/TxReduceRelay.cpp +++ b/src/xrpld/rpc/handlers/TxReduceRelay.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value doTxReduceRelay(RPC::JsonContext& context) @@ -12,4 +12,4 @@ doTxReduceRelay(RPC::JsonContext& context) return context.app.overlay().txMetrics(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/UnlList.cpp b/src/xrpld/rpc/handlers/UnlList.cpp index 6a23daab58..8c28373a05 100644 --- a/src/xrpld/rpc/handlers/UnlList.cpp +++ b/src/xrpld/rpc/handlers/UnlList.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doUnlList(RPC::JsonContext& context) @@ -26,4 +26,4 @@ doUnlList(RPC::JsonContext& context) return obj; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Unsubscribe.cpp b/src/xrpld/rpc/handlers/Unsubscribe.cpp index f84ae00cfc..bc192510bf 100644 --- a/src/xrpld/rpc/handlers/Unsubscribe.cpp +++ b/src/xrpld/rpc/handlers/Unsubscribe.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doUnsubscribe(RPC::JsonContext& context) @@ -244,4 +244,4 @@ doUnsubscribe(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/ValidationCreate.cpp b/src/xrpld/rpc/handlers/ValidationCreate.cpp index fc7be5777c..c4bdf1b3de 100644 --- a/src/xrpld/rpc/handlers/ValidationCreate.cpp +++ b/src/xrpld/rpc/handlers/ValidationCreate.cpp @@ -5,7 +5,7 @@ #include #include -namespace ripple { +namespace xrpl { static std::optional validationSeed(Json::Value const& params) @@ -47,4 +47,4 @@ doValidationCreate(RPC::JsonContext& context) return obj; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/ValidatorInfo.cpp b/src/xrpld/rpc/handlers/ValidatorInfo.cpp index ba2f963851..20d07df866 100644 --- a/src/xrpld/rpc/handlers/ValidatorInfo.cpp +++ b/src/xrpld/rpc/handlers/ValidatorInfo.cpp @@ -9,7 +9,7 @@ #include #include -namespace ripple { +namespace xrpl { Json::Value doValidatorInfo(RPC::JsonContext& context) { @@ -43,4 +43,4 @@ doValidatorInfo(RPC::JsonContext& context) return ret; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/ValidatorListSites.cpp b/src/xrpld/rpc/handlers/ValidatorListSites.cpp index 22644d65e3..7acaa27168 100644 --- a/src/xrpld/rpc/handlers/ValidatorListSites.cpp +++ b/src/xrpld/rpc/handlers/ValidatorListSites.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value doValidatorListSites(RPC::JsonContext& context) @@ -12,4 +12,4 @@ doValidatorListSites(RPC::JsonContext& context) return context.app.validatorSites().getJson(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Validators.cpp b/src/xrpld/rpc/handlers/Validators.cpp index 67d1c60e3a..a83a6fe4b0 100644 --- a/src/xrpld/rpc/handlers/Validators.cpp +++ b/src/xrpld/rpc/handlers/Validators.cpp @@ -4,7 +4,7 @@ #include -namespace ripple { +namespace xrpl { Json::Value doValidators(RPC::JsonContext& context) @@ -12,4 +12,4 @@ doValidators(RPC::JsonContext& context) return context.app.validators().getJson(); } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/VaultInfo.cpp b/src/xrpld/rpc/handlers/VaultInfo.cpp index 7e040fef82..ca2c1d070f 100644 --- a/src/xrpld/rpc/handlers/VaultInfo.cpp +++ b/src/xrpld/rpc/handlers/VaultInfo.cpp @@ -8,7 +8,7 @@ #include #include -namespace ripple { +namespace xrpl { static std::optional parseVault(Json::Value const& params, Json::Value& jvResult) @@ -92,4 +92,4 @@ doVaultInfo(RPC::JsonContext& context) return jvResult; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Version.h b/src/xrpld/rpc/handlers/Version.h index 57c5abfd4b..8af2fd20bc 100644 --- a/src/xrpld/rpc/handlers/Version.h +++ b/src/xrpld/rpc/handlers/Version.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { namespace RPC { class VersionHandler @@ -43,6 +43,6 @@ private: }; } // namespace RPC -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/handlers/WalletPropose.cpp b/src/xrpld/rpc/handlers/WalletPropose.cpp index 575bb84322..c245d5546d 100644 --- a/src/xrpld/rpc/handlers/WalletPropose.cpp +++ b/src/xrpld/rpc/handlers/WalletPropose.cpp @@ -14,7 +14,7 @@ #include #include -namespace ripple { +namespace xrpl { double estimate_entropy(std::string const& input) @@ -158,4 +158,4 @@ walletPropose(Json::Value const& params) return obj; } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/rpc/handlers/WalletPropose.h b/src/xrpld/rpc/handlers/WalletPropose.h index e041b6608f..42c7973055 100644 --- a/src/xrpld/rpc/handlers/WalletPropose.h +++ b/src/xrpld/rpc/handlers/WalletPropose.h @@ -3,11 +3,11 @@ #include -namespace ripple { +namespace xrpl { Json::Value walletPropose(Json::Value const& params); -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/rpc/json_body.h b/src/xrpld/rpc/json_body.h index 4dd9142c09..af20ec17ac 100644 --- a/src/xrpld/rpc/json_body.h +++ b/src/xrpld/rpc/json_body.h @@ -7,7 +7,7 @@ #include #include -namespace ripple { +namespace xrpl { /// Body that holds JSON struct json_body @@ -91,6 +91,6 @@ struct json_body }; }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/src/xrpld/shamap/NodeFamily.cpp b/src/xrpld/shamap/NodeFamily.cpp index b9cca65d36..d43ab1d648 100644 --- a/src/xrpld/shamap/NodeFamily.cpp +++ b/src/xrpld/shamap/NodeFamily.cpp @@ -4,7 +4,7 @@ #include #include -namespace ripple { +namespace xrpl { NodeFamily::NodeFamily(Application& app, CollectorManager& cm) : app_(app) @@ -87,4 +87,4 @@ NodeFamily::acquire(uint256 const& hash, std::uint32_t seq) } } -} // namespace ripple +} // namespace xrpl diff --git a/src/xrpld/shamap/NodeFamily.h b/src/xrpld/shamap/NodeFamily.h index f8bb278ac9..14c2ebb093 100644 --- a/src/xrpld/shamap/NodeFamily.h +++ b/src/xrpld/shamap/NodeFamily.h @@ -3,7 +3,7 @@ #include -namespace ripple { +namespace xrpl { class Application; @@ -83,6 +83,6 @@ private: acquire(uint256 const& hash, std::uint32_t seq); }; -} // namespace ripple +} // namespace xrpl #endif diff --git a/tests/conan/src/example.cpp b/tests/conan/src/example.cpp index 41dcd62462..acfb253a7d 100644 --- a/tests/conan/src/example.cpp +++ b/tests/conan/src/example.cpp @@ -5,6 +5,6 @@ int main(int argc, char const** argv) { - std::printf("%s\n", ripple::BuildInfo::getVersionString().c_str()); + std::printf("%s\n", xrpl::BuildInfo::getVersionString().c_str()); return 0; } From cf748702af3a7cfe78171313832fdc0fb5ae8e4f Mon Sep 17 00:00:00 2001 From: liuyueyangxmu Date: Sat, 13 Dec 2025 00:06:17 +0800 Subject: [PATCH 042/105] chore: Fix some typos in comments (#6082) --- src/test/app/CrossingLimits_test.cpp | 4 ++-- src/test/app/Offer_test.cpp | 2 +- src/test/app/RCLValidations_test.cpp | 4 ++-- src/test/app/TxQ_test.cpp | 2 +- src/test/csf/Histogram.h | 4 ++-- src/test/csf/submitters.h | 2 +- src/xrpld/rpc/detail/TransactionSign.cpp | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/app/CrossingLimits_test.cpp b/src/test/app/CrossingLimits_test.cpp index 9e9b1a3d45..8c11dd6737 100644 --- a/src/test/app/CrossingLimits_test.cpp +++ b/src/test/app/CrossingLimits_test.cpp @@ -303,7 +303,7 @@ public: // offers unfunded. // b. Carol's remaining 800 offers are consumed as unfunded. // c. 199 of alice's XRP(1) to USD(3) offers are consumed. - // A book step is allowed to consume a maxium of 1000 offers + // A book step is allowed to consume a maximum of 1000 offers // at a given quality, and that limit is now reached. // d. Now the strand is dry, even though there are still funded // XRP(1) to USD(3) offers available. @@ -384,7 +384,7 @@ public: // offers unfunded. // b. Carol's remaining 800 offers are consumed as unfunded. // c. 199 of alice's XRP(1) to USD(3) offers are consumed. - // A book step is allowed to consume a maxium of 1000 offers + // A book step is allowed to consume a maximum of 1000 offers // at a given quality, and that limit is now reached. // d. Now the strand is dry, even though there are still funded // XRP(1) to USD(3) offers available. Bob has spent 400 EUR and diff --git a/src/test/app/Offer_test.cpp b/src/test/app/Offer_test.cpp index 1117510a45..46a2cabec1 100644 --- a/src/test/app/Offer_test.cpp +++ b/src/test/app/Offer_test.cpp @@ -1298,7 +1298,7 @@ public: testNegativeBalance(FeatureBitset features) { // This test creates an offer test for negative balance - // with transfer fees and miniscule funds. + // with transfer fees and minuscule funds. testcase("Negative Balance"); using namespace jtx; diff --git a/src/test/app/RCLValidations_test.cpp b/src/test/app/RCLValidations_test.cpp index a4f0d6a7cb..729f373738 100644 --- a/src/test/app/RCLValidations_test.cpp +++ b/src/test/app/RCLValidations_test.cpp @@ -254,7 +254,7 @@ class RCLValidations_test : public beast::unit_test::suite BEAST_EXPECT(trie.branchSupport(ledg_258) == 4); // Move three of the s258 ledgers to s259, which splits the trie - // due to the 256 ancestory limit + // due to the 256 ancestry limit BEAST_EXPECT(trie.remove(ledg_258, 3)); trie.insert(ledg_259, 3); trie.getPreferred(1); @@ -275,7 +275,7 @@ class RCLValidations_test : public beast::unit_test::suite // then verify the remove call works // past bug: remove had assumed the first child of a node in the trie // which matches is the *only* child in the trie which matches. - // This is **NOT** true with the limited 256 ledger ancestory + // This is **NOT** true with the limited 256 ledger ancestry // quirk of RCLValidation and prevents deleting the old support // for ledger 257 diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index 3e19fc2842..f6ab13e04f 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -3821,7 +3821,7 @@ public: return result; }; - testcase("straightfoward positive case"); + testcase("straightforward positive case"); { // Queue up some transactions at a too-low fee. auto aliceSeq = env.seq(alice); diff --git a/src/test/csf/Histogram.h b/src/test/csf/Histogram.h index b55af34846..e32fded2f2 100644 --- a/src/test/csf/Histogram.h +++ b/src/test/csf/Histogram.h @@ -18,14 +18,14 @@ namespace csf { - Comparison : T a, b; bool res = a < b - Addition: T a, b; T c = a + b; - Multiplication : T a, std::size_t b; T c = a * b; - - Divison: T a; std::size_t b; T c = a/b; + - Division: T a; std::size_t b; T c = a/b; */ template > class Histogram { - // TODO: Consider logarithimic bins around expected median if this becomes + // TODO: Consider logarithmic bins around expected median if this becomes // unscaleable std::map counts_; std::size_t samples = 0; diff --git a/src/test/csf/submitters.h b/src/test/csf/submitters.h index 8a3632eb97..0c5d46e075 100644 --- a/src/test/csf/submitters.h +++ b/src/test/csf/submitters.h @@ -31,7 +31,7 @@ struct Rate /** Submits transactions to a specified peer Submits successive transactions beginning at start, then spaced according - to succesive calls of distribution(), until stop. + to successive calls of distribution(), until stop. @tparam Distribution is a `UniformRandomBitGenerator` from the STL that is used by random distributions to generate random samples diff --git a/src/xrpld/rpc/detail/TransactionSign.cpp b/src/xrpld/rpc/detail/TransactionSign.cpp index 252e5fc91e..a4ac32ee17 100644 --- a/src/xrpld/rpc/detail/TransactionSign.cpp +++ b/src/xrpld/rpc/detail/TransactionSign.cpp @@ -277,7 +277,7 @@ checkPayment( app); if (pf.findPaths(app.config().PATH_SEARCH_OLD)) { - // 4 is the maxium paths + // 4 is the maximum paths pf.computePathRanks(4); STPath fullLiquidityPath; STPathSet paths; From f816ffa55ffac8d78e150cf13fa90cad8a4f6f0f Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 12 Dec 2025 14:47:34 -0500 Subject: [PATCH 043/105] ci: Update shared actions (#6147) The latest update to `cleanup-workspace`, `get-nproc`, and `prepare-runner` moved the action to the repository root directory, and also includes some ccache changes. In response, this change updates the various shared actions to the latest commit hash. --- .github/workflows/publish-docs.yml | 2 +- .github/workflows/reusable-build-test-config.yml | 6 +++--- .github/workflows/upload-conan-deps.yml | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 14a2ba2fc0..6f0927a2b3 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -36,7 +36,7 @@ jobs: uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Get number of processors - uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a + uses: XRPLF/actions/get-nproc@2ece4ec6ab7de266859a6f053571425b2bd684b6 id: nproc with: subtract: ${{ env.NPROC_SUBTRACT }} diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index 70d4f93e16..43acfab542 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -71,13 +71,13 @@ jobs: steps: - name: Cleanup workspace (macOS and Windows) if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }} - uses: XRPLF/actions/.github/actions/cleanup-workspace@01b244d2718865d427b499822fbd3f15e7197fcc + uses: XRPLF/actions/cleanup-workspace@2ece4ec6ab7de266859a6f053571425b2bd684b6 - name: Checkout repository uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Prepare runner - uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a + uses: XRPLF/actions/prepare-runner@2ece4ec6ab7de266859a6f053571425b2bd684b6 with: disable_ccache: false @@ -85,7 +85,7 @@ jobs: uses: ./.github/actions/print-env - name: Get number of processors - uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a + uses: XRPLF/actions/get-nproc@2ece4ec6ab7de266859a6f053571425b2bd684b6 id: nproc with: subtract: ${{ inputs.nproc_subtract }} diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml index 320396c899..ec283e564c 100644 --- a/.github/workflows/upload-conan-deps.yml +++ b/.github/workflows/upload-conan-deps.yml @@ -64,13 +64,13 @@ jobs: steps: - name: Cleanup workspace (macOS and Windows) if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }} - uses: XRPLF/actions/.github/actions/cleanup-workspace@01b244d2718865d427b499822fbd3f15e7197fcc + uses: XRPLF/actions/cleanup-workspace@2ece4ec6ab7de266859a6f053571425b2bd684b6 - name: Checkout repository uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Prepare runner - uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a + uses: XRPLF/actions/prepare-runner@2ece4ec6ab7de266859a6f053571425b2bd684b6 with: disable_ccache: false @@ -78,7 +78,7 @@ jobs: uses: ./.github/actions/print-env - name: Get number of processors - uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a + uses: XRPLF/actions/get-nproc@2ece4ec6ab7de266859a6f053571425b2bd684b6 id: nproc with: subtract: ${{ env.NPROC_SUBTRACT }} From 41c1be2baca43ee2b7a6f85fac3ee329a25ae2cc Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 15 Dec 2025 10:40:08 -0800 Subject: [PATCH 044/105] refactor: remove `Json::Object` and related files/classes (#5894) `Json::Object` and related objects are not used at all, so this change removes `include/xrpl/json/Object.h` and all downstream files. There are a number of minor downstream changes as well. Full list of deleted classes and functions: * `Json::Collections` * `Json::Object` * `Json::Array` * `Json::WriterObject` * `Json::setArray` * `Json::addObject` * `Json::appendArray` * `Json::appendObject` The last helper function, `copyFrom`, seemed a bit more complex and was actually used in a few places, so it was moved to `LedgerToJson.h` instead of deleting it. --- include/xrpl/json/Object.h | 445 ------------------- include/xrpl/protocol/ApiVersion.h | 8 +- include/xrpl/protocol/ErrorCodes.h | 26 +- include/xrpl/protocol/RPCErr.h | 2 +- src/libxrpl/json/Object.cpp | 233 ---------- src/libxrpl/protocol/ErrorCodes.cpp | 18 + src/libxrpl/protocol/RPCErr.cpp | 2 +- src/test/json/Object_test.cpp | 239 ---------- src/test/jtx/impl/utility.cpp | 3 +- src/xrpld/app/ledger/LedgerToJson.h | 8 +- src/xrpld/app/ledger/detail/LedgerToJson.cpp | 46 +- src/xrpld/rpc/Status.h | 3 +- src/xrpld/rpc/handlers/GetCounts.h | 2 - src/xrpld/rpc/handlers/LedgerHandler.cpp | 37 ++ src/xrpld/rpc/handlers/LedgerHandler.h | 47 +- src/xrpld/rpc/handlers/Version.h | 3 +- 16 files changed, 100 insertions(+), 1022 deletions(-) delete mode 100644 include/xrpl/json/Object.h delete mode 100644 src/libxrpl/json/Object.cpp delete mode 100644 src/test/json/Object_test.cpp diff --git a/include/xrpl/json/Object.h b/include/xrpl/json/Object.h deleted file mode 100644 index 754d0dcb08..0000000000 --- a/include/xrpl/json/Object.h +++ /dev/null @@ -1,445 +0,0 @@ -#ifndef XRPL_JSON_OBJECT_H_INCLUDED -#define XRPL_JSON_OBJECT_H_INCLUDED - -#include - -#include - -namespace Json { - -/** - Collection is a base class for Array and Object, classes which provide the - facade of JSON collections for the O(1) JSON writer, while still using no - heap memory and only a very small amount of stack. - - From http://json.org, JSON has two types of collection: array, and object. - Everything else is a *scalar* - a number, a string, a boolean, the special - value null, or a legacy Json::Value. - - Collections must write JSON "as-it-goes" in order to get the strong - performance guarantees. This puts restrictions upon API users: - - 1. Only one collection can be open for change at any one time. - - This condition is enforced automatically and a std::logic_error thrown if - it is violated. - - 2. A tag may only be used once in an Object. - - Some objects have many tags, so this condition might be a little - expensive. Enforcement of this condition is turned on in debug builds and - a std::logic_error is thrown when the tag is added for a second time. - - Code samples: - - Writer writer; - - // An empty object. - { - Object::Root (writer); - } - // Outputs {} - - // An object with one scalar value. - { - Object::Root root (writer); - write["hello"] = "world"; - } - // Outputs {"hello":"world"} - - // Same, using chaining. - { - Object::Root (writer)["hello"] = "world"; - } - // Output is the same. - - // Add several scalars, with chaining. - { - Object::Root (writer) - .set ("hello", "world") - .set ("flag", false) - .set ("x", 42); - } - // Outputs {"hello":"world","flag":false,"x":42} - - // Add an array. - { - Object::Root root (writer); - { - auto array = root.setArray ("hands"); - array.append ("left"); - array.append ("right"); - } - } - // Outputs {"hands":["left", "right"]} - - // Same, using chaining. - { - Object::Root (writer) - .setArray ("hands") - .append ("left") - .append ("right"); - } - // Output is the same. - - // Add an object. - { - Object::Root root (writer); - { - auto object = root.setObject ("hands"); - object["left"] = false; - object["right"] = true; - } - } - // Outputs {"hands":{"left":false,"right":true}} - - // Same, using chaining. - { - Object::Root (writer) - .setObject ("hands") - .set ("left", false) - .set ("right", true); - } - } - // Outputs {"hands":{"left":false,"right":true}} - - - Typical ways to make mistakes and get a std::logic_error: - - Writer writer; - Object::Root root (writer); - - // Repeat a tag. - { - root ["hello"] = "world"; - root ["hello"] = "there"; // THROWS! in a debug build. - } - - // Open a subcollection, then set something else. - { - auto object = root.setObject ("foo"); - root ["hello"] = "world"; // THROWS! - } - - // Open two subcollections at a time. - { - auto object = root.setObject ("foo"); - auto array = root.setArray ("bar"); // THROWS!! - } - - For more examples, check the unit tests. - */ - -class Collection -{ -public: - Collection(Collection&& c) noexcept; - Collection& - operator=(Collection&& c) noexcept; - Collection() = delete; - - ~Collection(); - -protected: - // A null parent means "no parent at all". - // Writers cannot be null. - Collection(Collection* parent, Writer*); - void - checkWritable(std::string const& label); - - Collection* parent_; - Writer* writer_; - bool enabled_; -}; - -class Array; - -//------------------------------------------------------------------------------ - -/** Represents a JSON object being written to a Writer. */ -class Object : protected Collection -{ -public: - /** Object::Root is the only Collection that has a public constructor. */ - class Root; - - /** Set a scalar value in the Object for a key. - - A JSON scalar is a single value - a number, string, boolean, nullptr or - a Json::Value. - - `set()` throws an exception if this object is disabled (which means that - one of its children is enabled). - - In a debug build, `set()` also throws an exception if the key has - already been set() before. - - An operator[] is provided to allow writing `object["key"] = scalar;`. - */ - template - void - set(std::string const& key, Scalar const&); - - void - set(std::string const& key, Json::Value const&); - - // Detail class and method used to implement operator[]. - class Proxy; - - Proxy - operator[](std::string const& key); - Proxy - operator[](Json::StaticString const& key); - - /** Make a new Object at a key and return it. - - This Object is disabled until that sub-object is destroyed. - Throws an exception if this Object was already disabled. - */ - Object - setObject(std::string const& key); - - /** Make a new Array at a key and return it. - - This Object is disabled until that sub-array is destroyed. - Throws an exception if this Object was already disabled. - */ - Array - setArray(std::string const& key); - -protected: - friend class Array; - Object(Collection* parent, Writer* w) : Collection(parent, w) - { - } -}; - -class Object::Root : public Object -{ -public: - /** Each Object::Root must be constructed with its own unique Writer. */ - Root(Writer&); -}; - -//------------------------------------------------------------------------------ - -/** Represents a JSON array being written to a Writer. */ -class Array : private Collection -{ -public: - /** Append a scalar to the Arrary. - - Throws an exception if this array is disabled (which means that one of - its sub-collections is enabled). - */ - template - void - append(Scalar const&); - - /** - Appends a Json::Value to an array. - Throws an exception if this Array was disabled. - */ - void - append(Json::Value const&); - - /** Append a new Object and return it. - - This Array is disabled until that sub-object is destroyed. - Throws an exception if this Array was disabled. - */ - Object - appendObject(); - - /** Append a new Array and return it. - - This Array is disabled until that sub-array is destroyed. - Throws an exception if this Array was already disabled. - */ - Array - appendArray(); - -protected: - friend class Object; - Array(Collection* parent, Writer* w) : Collection(parent, w) - { - } -}; - -//------------------------------------------------------------------------------ - -// Generic accessor functions to allow Json::Value and Collection to -// interoperate. - -/** Add a new subarray at a named key in a Json object. */ -Json::Value& -setArray(Json::Value&, Json::StaticString const& key); - -/** Add a new subarray at a named key in a Json object. */ -Array -setArray(Object&, Json::StaticString const& key); - -/** Add a new subobject at a named key in a Json object. */ -Json::Value& -addObject(Json::Value&, Json::StaticString const& key); - -/** Add a new subobject at a named key in a Json object. */ -Object -addObject(Object&, Json::StaticString const& key); - -/** Append a new subarray to a Json array. */ -Json::Value& -appendArray(Json::Value&); - -/** Append a new subarray to a Json array. */ -Array -appendArray(Array&); - -/** Append a new subobject to a Json object. */ -Json::Value& -appendObject(Json::Value&); - -/** Append a new subobject to a Json object. */ -Object -appendObject(Array&); - -/** Copy all the keys and values from one object into another. */ -void -copyFrom(Json::Value& to, Json::Value const& from); - -/** Copy all the keys and values from one object into another. */ -void -copyFrom(Object& to, Json::Value const& from); - -/** An Object that contains its own Writer. */ -class WriterObject -{ -public: - WriterObject(Output const& output) - : writer_(std::make_unique(output)) - , object_(std::make_unique(*writer_)) - { - } - - WriterObject(WriterObject&& other) = default; - - Object* - operator->() - { - return object_.get(); - } - - Object& - operator*() - { - return *object_; - } - -private: - std::unique_ptr writer_; - std::unique_ptr object_; -}; - -WriterObject -stringWriterObject(std::string&); - -//------------------------------------------------------------------------------ -// Implementation details. - -// Detail class for Object::operator[]. -class Object::Proxy -{ -private: - Object& object_; - std::string const key_; - -public: - Proxy(Object& object, std::string const& key); - - template - void - operator=(T const& t) - { - object_.set(key_, t); - // Note: This function shouldn't return *this, because it's a trap. - // - // In Json::Value, foo[jss::key] returns a reference to a - // mutable Json::Value contained _inside_ foo. But in the case of - // Json::Object, where we write once only, there isn't any such - // reference that can be returned. Returning *this would return an - // object "a level higher" than in Json::Value, leading to obscure bugs, - // particularly in generic code. - } -}; - -//------------------------------------------------------------------------------ - -template -void -Array::append(Scalar const& value) -{ - checkWritable("append"); - if (writer_) - writer_->append(value); -} - -template -void -Object::set(std::string const& key, Scalar const& value) -{ - checkWritable("set"); - if (writer_) - writer_->set(key, value); -} - -inline Json::Value& -setArray(Json::Value& json, Json::StaticString const& key) -{ - return (json[key] = Json::arrayValue); -} - -inline Array -setArray(Object& json, Json::StaticString const& key) -{ - return json.setArray(std::string(key)); -} - -inline Json::Value& -addObject(Json::Value& json, Json::StaticString const& key) -{ - return (json[key] = Json::objectValue); -} - -inline Object -addObject(Object& object, Json::StaticString const& key) -{ - return object.setObject(std::string(key)); -} - -inline Json::Value& -appendArray(Json::Value& json) -{ - return json.append(Json::arrayValue); -} - -inline Array -appendArray(Array& json) -{ - return json.appendArray(); -} - -inline Json::Value& -appendObject(Json::Value& json) -{ - return json.append(Json::objectValue); -} - -inline Object -appendObject(Array& json) -{ - return json.appendObject(); -} - -} // namespace Json - -#endif diff --git a/include/xrpl/protocol/ApiVersion.h b/include/xrpl/protocol/ApiVersion.h index b2ee64621e..d1a84e76b0 100644 --- a/include/xrpl/protocol/ApiVersion.h +++ b/include/xrpl/protocol/ApiVersion.h @@ -58,14 +58,14 @@ static_assert(apiMaximumSupportedVersion >= apiMinimumSupportedVersion); static_assert(apiBetaVersion >= apiMaximumSupportedVersion); static_assert(apiMaximumValidVersion >= apiMaximumSupportedVersion); -template -void -setVersion(JsonObject& parent, unsigned int apiVersion, bool betaEnabled) +inline void +setVersion(Json::Value& parent, unsigned int apiVersion, bool betaEnabled) { XRPL_ASSERT( apiVersion != apiInvalidVersion, "xrpl::RPC::setVersion : input is valid"); - auto& retObj = addObject(parent, jss::version); + + auto& retObj = parent[jss::version] = Json::objectValue; if (apiVersion == apiVersionIfUnspecified) { diff --git a/include/xrpl/protocol/ErrorCodes.h b/include/xrpl/protocol/ErrorCodes.h index 8d5d871aa1..3a2645347a 100644 --- a/include/xrpl/protocol/ErrorCodes.h +++ b/include/xrpl/protocol/ErrorCodes.h @@ -209,33 +209,11 @@ get_error_info(error_code_i code); /** Add or update the json update to reflect the error code. */ /** @{ */ -template void -inject_error(error_code_i code, JsonValue& json) -{ - ErrorInfo const& info(get_error_info(code)); - json[jss::error] = info.token; - json[jss::error_code] = info.code; - json[jss::error_message] = info.message; -} +inject_error(error_code_i code, Json::Value& json); -template void -inject_error(int code, JsonValue& json) -{ - inject_error(error_code_i(code), json); -} - -template -void -inject_error(error_code_i code, std::string const& message, JsonValue& json) -{ - ErrorInfo const& info(get_error_info(code)); - json[jss::error] = info.token; - json[jss::error_code] = info.code; - json[jss::error_message] = message; -} - +inject_error(error_code_i code, std::string const& message, Json::Value& json); /** @} */ /** Returns a new json object that reflects the error code. */ diff --git a/include/xrpl/protocol/RPCErr.h b/include/xrpl/protocol/RPCErr.h index 90df1562e7..fcca15747e 100644 --- a/include/xrpl/protocol/RPCErr.h +++ b/include/xrpl/protocol/RPCErr.h @@ -9,7 +9,7 @@ namespace xrpl { bool isRpcError(Json::Value jvResult); Json::Value -rpcError(int iError); +rpcError(error_code_i iError); } // namespace xrpl diff --git a/src/libxrpl/json/Object.cpp b/src/libxrpl/json/Object.cpp deleted file mode 100644 index ea5e5a32d8..0000000000 --- a/src/libxrpl/json/Object.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace Json { - -Collection::Collection(Collection* parent, Writer* writer) - : parent_(parent), writer_(writer), enabled_(true) -{ - checkWritable("Collection::Collection()"); - if (parent_) - { - check(parent_->enabled_, "Parent not enabled in constructor"); - parent_->enabled_ = false; - } -} - -Collection::~Collection() -{ - if (writer_) - writer_->finish(); - if (parent_) - parent_->enabled_ = true; -} - -Collection& -Collection::operator=(Collection&& that) noexcept -{ - parent_ = that.parent_; - writer_ = that.writer_; - enabled_ = that.enabled_; - - that.parent_ = nullptr; - that.writer_ = nullptr; - that.enabled_ = false; - - return *this; -} - -Collection::Collection(Collection&& that) noexcept -{ - *this = std::move(that); -} - -void -Collection::checkWritable(std::string const& label) -{ - if (!enabled_) - xrpl::Throw(label + ": not enabled"); - if (!writer_) - xrpl::Throw(label + ": not writable"); -} - -//------------------------------------------------------------------------------ - -Object::Root::Root(Writer& w) : Object(nullptr, &w) -{ - writer_->startRoot(Writer::object); -} - -Object -Object::setObject(std::string const& key) -{ - checkWritable("Object::setObject"); - if (writer_) - writer_->startSet(Writer::object, key); - return Object(this, writer_); -} - -Array -Object::setArray(std::string const& key) -{ - checkWritable("Object::setArray"); - if (writer_) - writer_->startSet(Writer::array, key); - return Array(this, writer_); -} - -//------------------------------------------------------------------------------ - -Object -Array::appendObject() -{ - checkWritable("Array::appendObject"); - if (writer_) - writer_->startAppend(Writer::object); - return Object(this, writer_); -} - -Array -Array::appendArray() -{ - checkWritable("Array::makeArray"); - if (writer_) - writer_->startAppend(Writer::array); - return Array(this, writer_); -} - -//------------------------------------------------------------------------------ - -Object::Proxy::Proxy(Object& object, std::string const& key) - : object_(object), key_(key) -{ -} - -Object::Proxy -Object::operator[](std::string const& key) -{ - return Proxy(*this, key); -} - -Object::Proxy -Object::operator[](Json::StaticString const& key) -{ - return Proxy(*this, std::string(key)); -} - -//------------------------------------------------------------------------------ - -void -Array::append(Json::Value const& v) -{ - auto t = v.type(); - switch (t) - { - case Json::nullValue: - return append(nullptr); - case Json::intValue: - return append(v.asInt()); - case Json::uintValue: - return append(v.asUInt()); - case Json::realValue: - return append(v.asDouble()); - case Json::stringValue: - return append(v.asString()); - case Json::booleanValue: - return append(v.asBool()); - - case Json::objectValue: { - auto object = appendObject(); - copyFrom(object, v); - return; - } - - case Json::arrayValue: { - auto array = appendArray(); - for (auto& item : v) - array.append(item); - return; - } - } - UNREACHABLE("Json::Array::append : invalid type"); // LCOV_EXCL_LINE -} - -void -Object::set(std::string const& k, Json::Value const& v) -{ - auto t = v.type(); - switch (t) - { - case Json::nullValue: - return set(k, nullptr); - case Json::intValue: - return set(k, v.asInt()); - case Json::uintValue: - return set(k, v.asUInt()); - case Json::realValue: - return set(k, v.asDouble()); - case Json::stringValue: - return set(k, v.asString()); - case Json::booleanValue: - return set(k, v.asBool()); - - case Json::objectValue: { - auto object = setObject(k); - copyFrom(object, v); - return; - } - - case Json::arrayValue: { - auto array = setArray(k); - for (auto& item : v) - array.append(item); - return; - } - } - UNREACHABLE("Json::Object::set : invalid type"); // LCOV_EXCL_LINE -} - -//------------------------------------------------------------------------------ - -namespace { - -template -void -doCopyFrom(Object& to, Json::Value const& from) -{ - XRPL_ASSERT(from.isObjectOrNull(), "Json::doCopyFrom : valid input type"); - auto members = from.getMemberNames(); - for (auto& m : members) - to[m] = from[m]; -} - -} // namespace - -void -copyFrom(Json::Value& to, Json::Value const& from) -{ - if (!to) // Short circuit this very common case. - to = from; - else - doCopyFrom(to, from); -} - -void -copyFrom(Object& to, Json::Value const& from) -{ - doCopyFrom(to, from); -} - -WriterObject -stringWriterObject(std::string& s) -{ - return WriterObject(stringOutput(s)); -} - -} // namespace Json diff --git a/src/libxrpl/protocol/ErrorCodes.cpp b/src/libxrpl/protocol/ErrorCodes.cpp index f37ba0c8e4..d78ff594e1 100644 --- a/src/libxrpl/protocol/ErrorCodes.cpp +++ b/src/libxrpl/protocol/ErrorCodes.cpp @@ -160,6 +160,24 @@ constexpr ErrorInfo unknownError; //------------------------------------------------------------------------------ +void +inject_error(error_code_i code, Json::Value& json) +{ + ErrorInfo const& info(get_error_info(code)); + json[jss::error] = info.token; + json[jss::error_code] = info.code; + json[jss::error_message] = info.message; +} + +void +inject_error(error_code_i code, std::string const& message, Json::Value& json) +{ + ErrorInfo const& info(get_error_info(code)); + json[jss::error] = info.token; + json[jss::error_code] = info.code; + json[jss::error_message] = message; +} + ErrorInfo const& get_error_info(error_code_i code) { diff --git a/src/libxrpl/protocol/RPCErr.cpp b/src/libxrpl/protocol/RPCErr.cpp index 658dd06b3d..e25b5e574b 100644 --- a/src/libxrpl/protocol/RPCErr.cpp +++ b/src/libxrpl/protocol/RPCErr.cpp @@ -9,7 +9,7 @@ struct RPCErr; // VFALCO NOTE Deprecated function Json::Value -rpcError(int iError) +rpcError(error_code_i iError) { Json::Value jvResult(Json::objectValue); RPC::inject_error(iError, jvResult); diff --git a/src/test/json/Object_test.cpp b/src/test/json/Object_test.cpp deleted file mode 100644 index b74754db33..0000000000 --- a/src/test/json/Object_test.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#include - -#include -#include - -namespace Json { - -class JsonObject_test : public xrpl::test::TestOutputSuite -{ - void - setup(std::string const& testName) - { - testcase(testName); - output_.clear(); - } - - std::unique_ptr writerObject_; - - Object& - makeRoot() - { - writerObject_ = - std::make_unique(stringWriterObject(output_)); - return **writerObject_; - } - - void - expectResult(std::string const& expected) - { - writerObject_.reset(); - TestOutputSuite::expectResult(expected); - } - -public: - void - testTrivial() - { - setup("trivial"); - - { - auto& root = makeRoot(); - (void)root; - } - expectResult("{}"); - } - - void - testSimple() - { - setup("simple"); - { - auto& root = makeRoot(); - root["hello"] = "world"; - root["skidoo"] = 23; - root["awake"] = false; - root["temperature"] = 98.6; - } - - expectResult( - "{\"hello\":\"world\"," - "\"skidoo\":23," - "\"awake\":false," - "\"temperature\":98.6}"); - } - - void - testOneSub() - { - setup("oneSub"); - { - auto& root = makeRoot(); - root.setArray("ar"); - } - expectResult("{\"ar\":[]}"); - } - - void - testSubs() - { - setup("subs"); - { - auto& root = makeRoot(); - - { - // Add an array with three entries. - auto array = root.setArray("ar"); - array.append(23); - array.append(false); - array.append(23.5); - } - - { - // Add an object with one entry. - auto obj = root.setObject("obj"); - obj["hello"] = "world"; - } - - { - // Add another object with two entries. - Json::Value value; - value["h"] = "w"; - value["f"] = false; - root["obj2"] = value; - } - } - - // Json::Value has an unstable order... - auto case1 = - "{\"ar\":[23,false,23.5]," - "\"obj\":{\"hello\":\"world\"}," - "\"obj2\":{\"h\":\"w\",\"f\":false}}"; - auto case2 = - "{\"ar\":[23,false,23.5]," - "\"obj\":{\"hello\":\"world\"}," - "\"obj2\":{\"f\":false,\"h\":\"w\"}}"; - writerObject_.reset(); - BEAST_EXPECT(output_ == case1 || output_ == case2); - } - - void - testSubsShort() - { - setup("subsShort"); - - { - auto& root = makeRoot(); - - { - // Add an array with three entries. - auto array = root.setArray("ar"); - array.append(23); - array.append(false); - array.append(23.5); - } - - // Add an object with one entry. - root.setObject("obj")["hello"] = "world"; - - { - // Add another object with two entries. - auto object = root.setObject("obj2"); - object.set("h", "w"); - object.set("f", false); - } - } - expectResult( - "{\"ar\":[23,false,23.5]," - "\"obj\":{\"hello\":\"world\"}," - "\"obj2\":{\"h\":\"w\",\"f\":false}}"); - } - - void - testFailureObject() - { - { - setup("object failure assign"); - auto& root = makeRoot(); - auto obj = root.setObject("o1"); - expectException([&]() { root["fail"] = "complete"; }); - } - { - setup("object failure object"); - auto& root = makeRoot(); - auto obj = root.setObject("o1"); - expectException([&]() { root.setObject("o2"); }); - } - { - setup("object failure Array"); - auto& root = makeRoot(); - auto obj = root.setArray("o1"); - expectException([&]() { root.setArray("o2"); }); - } - } - - void - testFailureArray() - { - { - setup("array failure append"); - auto& root = makeRoot(); - auto array = root.setArray("array"); - auto subarray = array.appendArray(); - auto fail = [&]() { array.append("fail"); }; - expectException(fail); - } - { - setup("array failure appendArray"); - auto& root = makeRoot(); - auto array = root.setArray("array"); - auto subarray = array.appendArray(); - auto fail = [&]() { array.appendArray(); }; - expectException(fail); - } - { - setup("array failure appendObject"); - auto& root = makeRoot(); - auto array = root.setArray("array"); - auto subarray = array.appendArray(); - auto fail = [&]() { array.appendObject(); }; - expectException(fail); - } - } - - void - testKeyFailure() - { - setup("repeating keys"); - auto& root = makeRoot(); - root.set("foo", "bar"); - root.set("baz", 0); - // setting key again throws in !NDEBUG builds - auto set_again = [&]() { root.set("foo", "bar"); }; -#ifdef NDEBUG - set_again(); - pass(); -#else - expectException(set_again); -#endif - } - - void - run() override - { - testTrivial(); - testSimple(); - - testOneSub(); - testSubs(); - testSubsShort(); - - testFailureObject(); - testFailureArray(); - testKeyFailure(); - } -}; - -BEAST_DEFINE_TESTSUITE(JsonObject, json, xrpl); - -} // namespace Json diff --git a/src/test/jtx/impl/utility.cpp b/src/test/jtx/impl/utility.cpp index 81bce576ce..920e715c16 100644 --- a/src/test/jtx/impl/utility.cpp +++ b/src/test/jtx/impl/utility.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -83,7 +82,7 @@ cmdToJSONRPC( // If paramsObj is not empty, put it in a [params] array. if (paramsObj.begin() != paramsObj.end()) { - auto& paramsArray = Json::setArray(jv, jss::params); + auto& paramsArray = jv[jss::params] = Json::arrayValue; paramsArray.append(paramsObj); } if (paramsObj.isMember(jss::jsonrpc)) diff --git a/src/xrpld/app/ledger/LedgerToJson.h b/src/xrpld/app/ledger/LedgerToJson.h index 7ebbfc655e..7b7e267d81 100644 --- a/src/xrpld/app/ledger/LedgerToJson.h +++ b/src/xrpld/app/ledger/LedgerToJson.h @@ -7,7 +7,6 @@ #include #include -#include #include namespace xrpl { @@ -42,10 +41,9 @@ struct LedgerFill std::optional closeTime; }; -/** Given a Ledger and options, fill a Json::Object or Json::Value with a +/** Given a Ledger and options, fill a Json::Value with a description of the ledger. */ - void addJson(Json::Value&, LedgerFill const&); @@ -53,6 +51,10 @@ addJson(Json::Value&, LedgerFill const&); Json::Value getJson(LedgerFill const&); +/** Copy all the keys and values from one object into another. */ +void +copyFrom(Json::Value& to, Json::Value const& from); + } // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/detail/LedgerToJson.cpp b/src/xrpld/app/ledger/detail/LedgerToJson.cpp index 8c9e21acde..b1f6d6b297 100644 --- a/src/xrpld/app/ledger/detail/LedgerToJson.cpp +++ b/src/xrpld/app/ledger/detail/LedgerToJson.cpp @@ -32,10 +32,9 @@ isBinary(LedgerFill const& fill) return fill.options & LedgerFill::binary; } -template void fillJson( - Object& json, + Json::Value& json, bool closed, LedgerHeader const& info, bool bFull, @@ -78,9 +77,8 @@ fillJson( } } -template void -fillJsonBinary(Object& json, bool closed, LedgerHeader const& info) +fillJsonBinary(Json::Value& json, bool closed, LedgerHeader const& info) { if (!closed) json[jss::closed] = false; @@ -207,11 +205,10 @@ fillJsonTx( return txJson; } -template void -fillJsonTx(Object& json, LedgerFill const& fill) +fillJsonTx(Json::Value& json, LedgerFill const& fill) { - auto&& txns = setArray(json, jss::transactions); + auto& txns = json[jss::transactions] = Json::arrayValue; auto bBinary = isBinary(fill); auto bExpanded = isExpanded(fill); @@ -238,12 +235,11 @@ fillJsonTx(Object& json, LedgerFill const& fill) } } -template void -fillJsonState(Object& json, LedgerFill const& fill) +fillJsonState(Json::Value& json, LedgerFill const& fill) { auto& ledger = fill.ledger; - auto&& array = Json::setArray(json, jss::accountState); + auto& array = json[jss::accountState] = Json::arrayValue; auto expanded = isExpanded(fill); auto binary = isBinary(fill); @@ -251,7 +247,7 @@ fillJsonState(Object& json, LedgerFill const& fill) { if (binary) { - auto&& obj = appendObject(array); + auto& obj = array.append(Json::objectValue); obj[jss::hash] = to_string(sle->key()); obj[jss::tx_blob] = serializeHex(*sle); } @@ -262,17 +258,16 @@ fillJsonState(Object& json, LedgerFill const& fill) } } -template void -fillJsonQueue(Object& json, LedgerFill const& fill) +fillJsonQueue(Json::Value& json, LedgerFill const& fill) { - auto&& queueData = Json::setArray(json, jss::queue_data); + auto& queueData = json[jss::queue_data] = Json::arrayValue; auto bBinary = isBinary(fill); auto bExpanded = isExpanded(fill); for (auto const& tx : fill.txQueue) { - auto&& txJson = appendObject(queueData); + auto& txJson = queueData.append(Json::objectValue); txJson[jss::fee_level] = to_string(tx.feeLevel); if (tx.lastValid) txJson[jss::LastLedgerSequence] = *tx.lastValid; @@ -297,9 +292,8 @@ fillJsonQueue(Object& json, LedgerFill const& fill) } } -template void -fillJson(Object& json, LedgerFill const& fill) +fillJson(Json::Value& json, LedgerFill const& fill) { // TODO: what happens if bBinary and bExtracted are both set? // Is there a way to report this back? @@ -327,7 +321,7 @@ fillJson(Object& json, LedgerFill const& fill) void addJson(Json::Value& json, LedgerFill const& fill) { - auto&& object = Json::addObject(json, jss::ledger); + auto& object = json[jss::ledger] = Json::objectValue; fillJson(object, fill); if ((fill.options & LedgerFill::dumpQueue) && !fill.txQueue.empty()) @@ -342,4 +336,20 @@ getJson(LedgerFill const& fill) return json; } +void +copyFrom(Json::Value& to, Json::Value const& from) +{ + if (!to) // Short circuit this very common case. + to = from; + else + { + // TODO: figure out if there is a way to remove this clause + // or check that it does/needs to do a deep copy + XRPL_ASSERT(from.isObjectOrNull(), "copyFrom : invalid input type"); + auto const members = from.getMemberNames(); + for (auto const& m : members) + to[m] = from[m]; + } +} + } // namespace xrpl diff --git a/src/xrpld/rpc/Status.h b/src/xrpld/rpc/Status.h index f4ffcae9b2..5d6175336e 100644 --- a/src/xrpld/rpc/Status.h +++ b/src/xrpld/rpc/Status.h @@ -94,9 +94,8 @@ public: /** Apply the Status to a JsonObject */ - template void - inject(Object& object) const + inject(Json::Value& object) const { if (auto ec = toErrorCode()) { diff --git a/src/xrpld/rpc/handlers/GetCounts.h b/src/xrpld/rpc/handlers/GetCounts.h index 0d544a4f11..de2c4f2f96 100644 --- a/src/xrpld/rpc/handlers/GetCounts.h +++ b/src/xrpld/rpc/handlers/GetCounts.h @@ -3,8 +3,6 @@ #include -#include - namespace xrpl { Json::Value diff --git a/src/xrpld/rpc/handlers/LedgerHandler.cpp b/src/xrpld/rpc/handlers/LedgerHandler.cpp index 2929776549..f8e8111aad 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.cpp +++ b/src/xrpld/rpc/handlers/LedgerHandler.cpp @@ -75,6 +75,43 @@ LedgerHandler::check() return Status::OK; } +void +LedgerHandler::writeResult(Json::Value& value) +{ + if (ledger_) + { + copyFrom(value, result_); + addJson(value, {*ledger_, &context_, options_, queueTxs_}); + } + else + { + auto& master = context_.app.getLedgerMaster(); + { + auto& closed = value[jss::closed] = Json::objectValue; + addJson(closed, {*master.getClosedLedger(), &context_, 0}); + } + { + auto& open = value[jss::open] = Json::objectValue; + addJson(open, {*master.getCurrentLedger(), &context_, 0}); + } + } + + Json::Value warnings{Json::arrayValue}; + if (context_.params.isMember(jss::type)) + { + Json::Value& w = warnings.append(Json::objectValue); + w[jss::id] = warnRPC_FIELDS_DEPRECATED; + w[jss::message] = + "Some fields from your request are deprecated. Please check the " + "documentation at " + "https://xrpl.org/docs/references/http-websocket-apis/ " + "and update your request. Field `type` is deprecated."; + } + + if (warnings.size()) + value[jss::warnings] = std::move(warnings); +} + } // namespace RPC std::pair diff --git a/src/xrpld/rpc/handlers/LedgerHandler.h b/src/xrpld/rpc/handlers/LedgerHandler.h index fbf60fb22e..3285118d11 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.h +++ b/src/xrpld/rpc/handlers/LedgerHandler.h @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -37,9 +36,8 @@ public: Status check(); - template void - writeResult(Object&); + writeResult(Json::Value&); static constexpr char name[] = "ledger"; @@ -59,49 +57,6 @@ private: int options_ = 0; }; -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// -// Implementation. - -template -void -LedgerHandler::writeResult(Object& value) -{ - if (ledger_) - { - Json::copyFrom(value, result_); - addJson(value, {*ledger_, &context_, options_, queueTxs_}); - } - else - { - auto& master = context_.app.getLedgerMaster(); - { - auto&& closed = Json::addObject(value, jss::closed); - addJson(closed, {*master.getClosedLedger(), &context_, 0}); - } - { - auto&& open = Json::addObject(value, jss::open); - addJson(open, {*master.getCurrentLedger(), &context_, 0}); - } - } - - Json::Value warnings{Json::arrayValue}; - if (context_.params.isMember(jss::type)) - { - Json::Value& w = warnings.append(Json::objectValue); - w[jss::id] = warnRPC_FIELDS_DEPRECATED; - w[jss::message] = - "Some fields from your request are deprecated. Please check the " - "documentation at " - "https://xrpl.org/docs/references/http-websocket-apis/ " - "and update your request. Field `type` is deprecated."; - } - - if (warnings.size()) - value[jss::warnings] = std::move(warnings); -} - } // namespace RPC } // namespace xrpl diff --git a/src/xrpld/rpc/handlers/Version.h b/src/xrpld/rpc/handlers/Version.h index 8af2fd20bc..b8f9512ef3 100644 --- a/src/xrpld/rpc/handlers/Version.h +++ b/src/xrpld/rpc/handlers/Version.h @@ -20,9 +20,8 @@ public: return Status::OK; } - template void - writeResult(Object& obj) + writeResult(Json::Value& obj) { setVersion(obj, apiVersion_, betaEnabled_); } From f059f0beda746b444d191a207b343ac457fd58db Mon Sep 17 00:00:00 2001 From: Bart Date: Wed, 17 Dec 2025 18:21:01 -0500 Subject: [PATCH 045/105] Set version to 3.2.0-b0 (#6153) --- src/libxrpl/protocol/BuildInfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libxrpl/protocol/BuildInfo.cpp b/src/libxrpl/protocol/BuildInfo.cpp index 472a8cb039..65caa9ecd3 100644 --- a/src/libxrpl/protocol/BuildInfo.cpp +++ b/src/libxrpl/protocol/BuildInfo.cpp @@ -17,7 +17,7 @@ namespace BuildInfo { // and follow the format described at http://semver.org/ //------------------------------------------------------------------------------ // clang-format off -char const* const versionString = "3.1.0-b0" +char const* const versionString = "3.2.0-b0" // clang-format on #if defined(DEBUG) || defined(SANITIZER) From 40198d9792af68df4f5a7610c614e8420c487d7b Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 22 Dec 2025 16:30:23 -0500 Subject: [PATCH 046/105] ci: Remove superfluous build directory creation (#6159) This change modifies the build directory structure from `build/build/xxx` or `.build/build/xxx` to just `build/xxx`. Namely, the `conanfile.py` has the CMake generators build directory hardcoded to `build/generators`. We may as well leverage the top-level build directory without introducing another layer of directory nesting. --- .github/actions/build-deps/action.yml | 9 +----- .github/workflows/publish-docs.yml | 2 +- .../workflows/reusable-build-test-config.yml | 29 +++++++++---------- .github/workflows/reusable-build-test.yml | 6 ---- .github/workflows/upload-conan-deps.yml | 1 - 5 files changed, 15 insertions(+), 32 deletions(-) diff --git a/.github/actions/build-deps/action.yml b/.github/actions/build-deps/action.yml index f20eb3a595..d1fb980dac 100644 --- a/.github/actions/build-deps/action.yml +++ b/.github/actions/build-deps/action.yml @@ -4,9 +4,6 @@ description: "Install Conan dependencies, optionally forcing a rebuild of all de # Note that actions do not support 'type' and all inputs are strings, see # https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax#inputs. inputs: - build_dir: - description: "The directory where to build." - required: true build_type: description: 'The build type to use ("Debug", "Release").' required: true @@ -28,17 +25,13 @@ runs: - name: Install Conan dependencies shell: bash env: - BUILD_DIR: ${{ inputs.build_dir }} BUILD_NPROC: ${{ inputs.build_nproc }} BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }} BUILD_TYPE: ${{ inputs.build_type }} LOG_VERBOSITY: ${{ inputs.log_verbosity }} run: | echo 'Installing dependencies.' - mkdir -p "${BUILD_DIR}" - cd "${BUILD_DIR}" conan install \ - --output-folder . \ --build="${BUILD_OPTION}" \ --options:host='&:tests=True' \ --options:host='&:xrpld=True' \ @@ -46,4 +39,4 @@ runs: --conf:all tools.build:jobs=${BUILD_NPROC} \ --conf:all tools.build:verbosity="${LOG_VERBOSITY}" \ --conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \ - .. + . diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 6f0927a2b3..c37a82a2f3 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -22,7 +22,7 @@ defaults: shell: bash env: - BUILD_DIR: .build + BUILD_DIR: build NPROC_SUBTRACT: 2 jobs: diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index 43acfab542..98bf107225 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -3,11 +3,6 @@ name: Build and test configuration on: workflow_call: inputs: - build_dir: - description: "The directory where to build." - required: true - type: string - build_only: description: 'Whether to only build or to build and test the code ("true", "false").' required: true @@ -59,6 +54,11 @@ defaults: run: shell: bash +env: + # Conan installs the generators in the build/generators directory, see the + # layout() method in conanfile.py. We then run CMake from the build directory. + BUILD_DIR: build + jobs: build-and-test: name: ${{ inputs.config_name }} @@ -96,7 +96,6 @@ jobs: - name: Build dependencies uses: ./.github/actions/build-deps with: - build_dir: ${{ inputs.build_dir }} build_nproc: ${{ steps.nproc.outputs.nproc }} build_type: ${{ inputs.build_type }} # Set the verbosity to "quiet" for Windows to avoid an excessive @@ -104,7 +103,7 @@ jobs: log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }} - name: Configure CMake - working-directory: ${{ inputs.build_dir }} + working-directory: ${{ env.BUILD_DIR }} env: BUILD_TYPE: ${{ inputs.build_type }} CMAKE_ARGS: ${{ inputs.cmake_args }} @@ -117,7 +116,7 @@ jobs: .. - name: Build the binary - working-directory: ${{ inputs.build_dir }} + working-directory: ${{ env.BUILD_DIR }} env: BUILD_NPROC: ${{ steps.nproc.outputs.nproc }} BUILD_TYPE: ${{ inputs.build_type }} @@ -132,8 +131,6 @@ jobs: - name: Upload the binary (Linux) if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }} uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - env: - BUILD_DIR: ${{ inputs.build_dir }} with: name: xrpld-${{ inputs.config_name }} path: ${{ env.BUILD_DIR }}/xrpld @@ -142,7 +139,7 @@ jobs: - name: Check linking (Linux) if: ${{ runner.os == 'Linux' }} - working-directory: ${{ inputs.build_dir }} + working-directory: ${{ env.BUILD_DIR }} run: | ldd ./xrpld if [ "$(ldd ./xrpld | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then @@ -154,13 +151,13 @@ jobs: - name: Verify presence of instrumentation (Linux) if: ${{ runner.os == 'Linux' && env.ENABLED_VOIDSTAR == 'true' }} - working-directory: ${{ inputs.build_dir }} + working-directory: ${{ env.BUILD_DIR }} run: | ./xrpld --version | grep libvoidstar - name: Run the separate tests if: ${{ !inputs.build_only }} - working-directory: ${{ inputs.build_dir }} + working-directory: ${{ env.BUILD_DIR }} # Windows locks some of the build files while running tests, and parallel jobs can collide env: BUILD_TYPE: ${{ inputs.build_type }} @@ -173,7 +170,7 @@ jobs: - name: Run the embedded tests if: ${{ !inputs.build_only }} - working-directory: ${{ runner.os == 'Windows' && format('{0}/{1}', inputs.build_dir, inputs.build_type) || inputs.build_dir }} + working-directory: ${{ runner.os == 'Windows' && format('{0}/{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }} env: BUILD_NPROC: ${{ steps.nproc.outputs.nproc }} run: | @@ -189,7 +186,7 @@ jobs: - name: Prepare coverage report if: ${{ !inputs.build_only && env.ENABLED_COVERAGE == 'true' }} - working-directory: ${{ inputs.build_dir }} + working-directory: ${{ env.BUILD_DIR }} env: BUILD_NPROC: ${{ steps.nproc.outputs.nproc }} BUILD_TYPE: ${{ inputs.build_type }} @@ -207,7 +204,7 @@ jobs: disable_search: true disable_telem: true fail_ci_if_error: true - files: ${{ inputs.build_dir }}/coverage.xml + files: ${{ env.BUILD_DIR }}/coverage.xml plugins: noop token: ${{ secrets.CODECOV_TOKEN }} verbose: true diff --git a/.github/workflows/reusable-build-test.yml b/.github/workflows/reusable-build-test.yml index c6e991df79..7f14aacb9b 100644 --- a/.github/workflows/reusable-build-test.yml +++ b/.github/workflows/reusable-build-test.yml @@ -8,11 +8,6 @@ name: Build and test on: workflow_call: inputs: - build_dir: - description: "The directory where to build." - required: false - type: string - default: ".build" os: description: 'The operating system to use for the build ("linux", "macos", "windows").' required: true @@ -46,7 +41,6 @@ jobs: matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} max-parallel: 10 with: - build_dir: ${{ inputs.build_dir }} build_only: ${{ matrix.build_only }} build_type: ${{ matrix.build_type }} cmake_args: ${{ matrix.cmake_args }} diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml index ec283e564c..5024666394 100644 --- a/.github/workflows/upload-conan-deps.yml +++ b/.github/workflows/upload-conan-deps.yml @@ -92,7 +92,6 @@ jobs: - name: Build dependencies uses: ./.github/actions/build-deps with: - build_dir: .build build_nproc: ${{ steps.nproc.outputs.nproc }} build_type: ${{ matrix.build_type }} force_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }} From b7139da4d09c55cae3f6ec69c092b1c87c34b631 Mon Sep 17 00:00:00 2001 From: Michael Legleux Date: Tue, 23 Dec 2025 16:38:35 -0800 Subject: [PATCH 047/105] fix: Remove cryptographic libs from libxrpl Conan package (#6163) * fix: rm crypto libs and fix protobuf path * update/rm comments --- conanfile.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/conanfile.py b/conanfile.py index 8dc09da0af..48e28cb275 100644 --- a/conanfile.py +++ b/conanfile.py @@ -182,12 +182,10 @@ class Xrpl(ConanFile): libxrpl.libs = [ "xrpl", "xrpl.libpb", - "ed25519", - "secp256k1", ] # TODO: Fix the protobufs to include each other relative to - # `include/`, not `include/ripple/proto/`. - libxrpl.includedirs = ["include", "include/ripple/proto"] + # `include/`, not `include/xrpl/proto/`. + libxrpl.includedirs = ["include", "include/xrpl/proto"] libxrpl.requires = [ "boost::headers", "boost::chrono", From 0f23ad820c84d0c8e97e2f0caa7c2e2690397207 Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Fri, 2 Jan 2026 16:53:33 +0000 Subject: [PATCH 048/105] chore: Pin ruamel.yaml<0.19 in pre-commit-hooks (#6166) See https://github.com/pre-commit/pre-commit-hooks/issues/1229 for more details. --- .pre-commit-config.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c85e0798f7..01b0e85930 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,10 +13,16 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0 hooks: + # https://github.com/pre-commit/pre-commit-hooks/issues/1229 + # regarding ruamel.yaml version - id: trailing-whitespace + additional_dependencies: [ruamel.yaml<0.19] - id: end-of-file-fixer + additional_dependencies: [ruamel.yaml<0.19] - id: mixed-line-ending + additional_dependencies: [ruamel.yaml<0.19] - id: check-merge-conflict + additional_dependencies: [ruamel.yaml<0.19] args: [--assume-in-merge] - repo: https://github.com/pre-commit/mirrors-clang-format From 0b87a26f04641b1d48a7738d6a2228bc02159e85 Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Mon, 5 Jan 2026 14:01:14 +0000 Subject: [PATCH 049/105] Revert "chore: Pin ruamel.yaml<0.19 in pre-commit-hooks (#6166)" (#6167) This reverts commit 0f23ad820c84d0c8e97e2f0caa7c2e2690397207. --- .pre-commit-config.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 01b0e85930..c85e0798f7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,16 +13,10 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0 hooks: - # https://github.com/pre-commit/pre-commit-hooks/issues/1229 - # regarding ruamel.yaml version - id: trailing-whitespace - additional_dependencies: [ruamel.yaml<0.19] - id: end-of-file-fixer - additional_dependencies: [ruamel.yaml<0.19] - id: mixed-line-ending - additional_dependencies: [ruamel.yaml<0.19] - id: check-merge-conflict - additional_dependencies: [ruamel.yaml<0.19] args: [--assume-in-merge] - repo: https://github.com/pre-commit/mirrors-clang-format From 3d1b3a49b3601a0a7037fa0b19d5df7b5e0e2fc1 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 5 Jan 2026 09:55:12 -0500 Subject: [PATCH 050/105] refactor: Rename `rippled.cfg` to `xrpld.cfg` (#6098) This change renames all occurrences of `rippled.cfg` to `xrpld.cfg`. It also provides a script to allow developers to replicate the changes in their local branch or fork to avoid conflicts. For the time being it maintains support for `rippled.cfg` as config file, if `xrpld.cfg` does not exist. --- .github/scripts/rename/README.md | 4 + .github/scripts/rename/config.sh | 72 ++++ .github/workflows/reusable-check-rename.yml | 2 + .gitignore | 1 + cfg/validators-example.txt | 2 +- ...{rippled-example.cfg => xrpld-example.cfg} | 108 +++--- cmake/XrplInstall.cmake | 2 +- include/xrpl/core/PerfLog.h | 2 +- include/xrpl/nodestore/README.md | 2 +- src/libxrpl/nodestore/ManagerImp.cpp | 4 +- src/test/core/Config_test.cpp | 310 +++++++++++++----- src/xrpld/app/misc/SHAMapStoreImp.h | 2 +- src/xrpld/core/Config.h | 1 + src/xrpld/core/detail/Config.cpp | 113 +++---- src/xrpld/overlay/README.md | 2 +- src/xrpld/overlay/detail/OverlayImpl.cpp | 2 +- 16 files changed, 433 insertions(+), 196 deletions(-) create mode 100755 .github/scripts/rename/config.sh rename cfg/{rippled-example.cfg => xrpld-example.cfg} (94%) diff --git a/.github/scripts/rename/README.md b/.github/scripts/rename/README.md index 392f0b1efc..8336f23bec 100644 --- a/.github/scripts/rename/README.md +++ b/.github/scripts/rename/README.md @@ -31,6 +31,9 @@ run from the repository root. the `xrpld` binary. 5. `.github/scripts/rename/namespace.sh`: This script will rename the C++ namespaces from `ripple` to `xrpl`. +6. `.github/scripts/rename/config.sh`: This script will rename the config from + `rippled.cfg` to `xrpld.cfg`, and updating the code accordingly. The old + filename will still be accepted. You can run all these scripts from the repository root as follows: @@ -40,4 +43,5 @@ You can run all these scripts from the repository root as follows: ./.github/scripts/rename/cmake.sh . ./.github/scripts/rename/binary.sh . ./.github/scripts/rename/namespace.sh . +./.github/scripts/rename/config.sh . ``` diff --git a/.github/scripts/rename/config.sh b/.github/scripts/rename/config.sh new file mode 100755 index 0000000000..7f36e8fd21 --- /dev/null +++ b/.github/scripts/rename/config.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Exit the script as soon as an error occurs. +set -e + +# On MacOS, ensure that GNU sed is installed and available as `gsed`. +SED_COMMAND=sed +if [[ "${OSTYPE}" == 'darwin'* ]]; then + if ! command -v gsed &> /dev/null; then + echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'." + exit 1 + fi + SED_COMMAND=gsed +fi + +# This script renames the config from `rippled.cfg` to `xrpld.cfg`, and updates +# the code accordingly. The old filename will still be accepted. +# Usage: .github/scripts/rename/config.sh + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +DIRECTORY=$1 +echo "Processing directory: ${DIRECTORY}" +if [ ! -d "${DIRECTORY}" ]; then + echo "Error: Directory '${DIRECTORY}' does not exist." + exit 1 +fi +pushd ${DIRECTORY} + +# Add the xrpld.cfg to the .gitignore. +if ! grep -q 'xrpld.cfg' .gitignore; then + ${SED_COMMAND} -i '/rippled.cfg/a\ +/xrpld.cfg' .gitignore +fi + +# Rename the files. +if [ -e rippled.cfg ]; then + mv rippled.cfg xrpld.cfg +fi +if [ -e cfg/rippled-example.cfg ]; then + mv cfg/rippled-example.cfg cfg/xrpld-example.cfg +fi + +# Rename inside the files. +DIRECTORIES=("cfg" "cmake" "include" "src") +for DIRECTORY in "${DIRECTORIES[@]}"; do + echo "Processing directory: ${DIRECTORY}" + + find "${DIRECTORY}" -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.ipp" -o -name "*.cpp" -o -name "*.cmake" -o -name "*.txt" -o -name "*.cfg" -o -name "*.md" \) | while read -r FILE; do + echo "Processing file: ${FILE}" + ${SED_COMMAND} -i -E 's/rippled(-example)?[ .]cfg/xrpld\1.cfg/g' "${FILE}" + done +done +${SED_COMMAND} -i 's/rippled/xrpld/g' cfg/xrpld-example.cfg +${SED_COMMAND} -i 's/rippled/xrpld/g' src/test/core/Config_test.cpp +${SED_COMMAND} -i 's/ripplevalidators/xrplvalidators/g' src/test/core/Config_test.cpp +${SED_COMMAND} -i 's/rippleConfig/xrpldConfig/g' src/test/core/Config_test.cpp +${SED_COMMAND} -i 's@ripple/@xrpld/@g' src/test/core/Config_test.cpp +${SED_COMMAND} -i 's/Rippled/File/g' src/test/core/Config_test.cpp + + +# Restore the old config file name in the code that maintains support for now. +${SED_COMMAND} -i 's/configLegacyName = "xrpld.cfg"/configLegacyName = "rippled.cfg"/g' src/xrpld/core/detail/Config.cpp + +# Restore an URL. +${SED_COMMAND} -i 's/connect-your-xrpld-to-the-xrp-test-net.html/connect-your-rippled-to-the-xrp-test-net.html/g' cfg/xrpld-example.cfg + +popd +echo "Renaming complete." diff --git a/.github/workflows/reusable-check-rename.yml b/.github/workflows/reusable-check-rename.yml index fb9ed2c6a8..af55084405 100644 --- a/.github/workflows/reusable-check-rename.yml +++ b/.github/workflows/reusable-check-rename.yml @@ -29,6 +29,8 @@ jobs: run: .github/scripts/rename/binary.sh . - name: Check namespaces run: .github/scripts/rename/namespace.sh . + - name: Check config name + run: .github/scripts/rename/config.sh . - name: Check for differences env: MESSAGE: | diff --git a/.gitignore b/.gitignore index 55844462e5..c4e81408bb 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ gmon.out # Customized configs. /rippled.cfg +/xrpld.cfg /validators.txt # Locally patched Conan recipes diff --git a/cfg/validators-example.txt b/cfg/validators-example.txt index dbcff90f12..6eb49da697 100644 --- a/cfg/validators-example.txt +++ b/cfg/validators-example.txt @@ -1,7 +1,7 @@ # # Default validators.txt # -# This file is located in the same folder as your rippled.cfg file +# This file is located in the same folder as your xrpld.cfg file # and defines which validators your server trusts not to collude. # # This file is UTF-8 with DOS, UNIX, or Mac style line endings. diff --git a/cfg/rippled-example.cfg b/cfg/xrpld-example.cfg similarity index 94% rename from cfg/rippled-example.cfg rename to cfg/xrpld-example.cfg index 5db008431d..b5180dce52 100644 --- a/cfg/rippled-example.cfg +++ b/cfg/xrpld-example.cfg @@ -29,18 +29,18 @@ # # Purpose # -# This file documents and provides examples of all rippled server process -# configuration options. When the rippled server instance is launched, it +# This file documents and provides examples of all xrpld server process +# configuration options. When the xrpld server instance is launched, it # looks for a file with the following name: # -# rippled.cfg +# xrpld.cfg # -# For more information on where the rippled server instance searches for the +# For more information on where the xrpld server instance searches for the # file, visit: # # https://xrpl.org/commandline-usage.html#generic-options # -# This file should be named rippled.cfg. This file is UTF-8 with DOS, UNIX, +# This file should be named xrpld.cfg. This file is UTF-8 with DOS, UNIX, # or Mac style end of lines. Blank lines and lines beginning with '#' are # ignored. Undefined sections are reserved. No escapes are currently defined. # @@ -89,8 +89,8 @@ # # # -# rippled offers various server protocols to clients making inbound -# connections. The listening ports rippled uses are "universal" ports +# xrpld offers various server protocols to clients making inbound +# connections. The listening ports xrpld uses are "universal" ports # which may be configured to handshake in one or more of the available # supported protocols. These universal ports simplify administration: # A single open port can be used for multiple protocols. @@ -103,7 +103,7 @@ # # A list of port names and key/value pairs. A port name must start with a # letter and contain only letters and numbers. The name is not case-sensitive. -# For each name in this list, rippled will look for a configuration file +# For each name in this list, xrpld will look for a configuration file # section with the same name and use it to create a listening port. The # name is informational only; the choice of name does not affect the function # of the listening port. @@ -134,7 +134,7 @@ # ip = 127.0.0.1 # protocol = http # -# When rippled is used as a command line client (for example, issuing a +# When xrpld is used as a command line client (for example, issuing a # server stop command), the first port advertising the http or https # protocol will be used to make the connection. # @@ -175,7 +175,7 @@ # same time. It is possible have both Websockets and Secure Websockets # together in one port. # -# NOTE If no ports support the peer protocol, rippled cannot +# NOTE If no ports support the peer protocol, xrpld cannot # receive incoming peer connections or become a superpeer. # # limit = @@ -194,7 +194,7 @@ # required. IP address restrictions, if any, will be checked in addition # to the credentials specified here. # -# When acting in the client role, rippled will supply these credentials +# When acting in the client role, xrpld will supply these credentials # using HTTP's Basic Authentication headers when making outbound HTTP/S # requests. # @@ -237,7 +237,7 @@ # WS, or WSS protocol interfaces. If administrative commands are # disabled for a port, these credentials have no effect. # -# When acting in the client role, rippled will supply these credentials +# When acting in the client role, xrpld will supply these credentials # in the submitted JSON for any administrative command requests when # invoking JSON-RPC commands on remote servers. # @@ -258,7 +258,7 @@ # resource controls will default to those for non-administrative users. # # The secure_gateway IP addresses are intended to represent -# proxies. Since rippled trusts these hosts, they must be +# proxies. Since xrpld trusts these hosts, they must be # responsible for properly authenticating the remote user. # # If some IP addresses are included for both "admin" and @@ -272,7 +272,7 @@ # Use the specified files when configuring SSL on the port. # # NOTE If no files are specified and secure protocols are selected, -# rippled will generate an internal self-signed certificate. +# xrpld will generate an internal self-signed certificate. # # The files have these meanings: # @@ -297,12 +297,12 @@ # Control the ciphers which the server will support over SSL on the port, # specified using the OpenSSL "cipher list format". # -# NOTE If unspecified, rippled will automatically configure a modern +# NOTE If unspecified, xrpld will automatically configure a modern # cipher suite. This default suite should be widely supported. # # You should not modify this string unless you have a specific # reason and cryptographic expertise. Incorrect modification may -# keep rippled from connecting to other instances of rippled or +# keep xrpld from connecting to other instances of xrpld or # prevent RPC and WebSocket clients from connecting. # # send_queue_limit = [1..65535] @@ -382,7 +382,7 @@ #----------------- # # These settings control security and access attributes of the Peer to Peer -# server section of the rippled process. Peer Protocol implements the +# server section of the xrpld process. Peer Protocol implements the # Ripple Payment protocol. It is over peer connections that transactions # and validations are passed from to machine to machine, to determine the # contents of validated ledgers. @@ -396,7 +396,7 @@ # true - enables compression # false - disables compression [default]. # -# The rippled server can save bandwidth by compressing its peer-to-peer communications, +# The xrpld server can save bandwidth by compressing its peer-to-peer communications, # at a cost of greater CPU usage. If you enable link compression, # the server automatically compresses communications with peer servers # that also have link compression enabled. @@ -432,7 +432,7 @@ # # [ips_fixed] # -# List of IP addresses or hostnames to which rippled should always attempt to +# List of IP addresses or hostnames to which xrpld should always attempt to # maintain peer connections with. This is useful for manually forming private # networks, for example to configure a validation server that connects to the # Ripple network through a public-facing server, or for building a set @@ -573,7 +573,7 @@ # # minimum_txn_in_ledger_standalone = # -# Like minimum_txn_in_ledger when rippled is running in standalone +# Like minimum_txn_in_ledger when xrpld is running in standalone # mode. Default: 1000. # # target_txn_in_ledger = @@ -710,7 +710,7 @@ # # [validator_token] # -# This is an alternative to [validation_seed] that allows rippled to perform +# This is an alternative to [validation_seed] that allows xrpld to perform # validation without having to store the validator keys on the network # connected server. The field should contain a single token in the form of a # base64-encoded blob. @@ -745,7 +745,7 @@ # # Specify the file by its name or path. # Unless an absolute path is specified, it will be considered relative to -# the folder in which the rippled.cfg file is located. +# the folder in which the xrpld.cfg file is located. # # Examples: # /home/ripple/validators.txt @@ -840,7 +840,7 @@ # # 0: Disable the ledger replay feature [default] # 1: Enable the ledger replay feature. With this feature enabled, when -# acquiring a ledger from the network, a rippled node only downloads +# acquiring a ledger from the network, a xrpld node only downloads # the ledger header and the transactions instead of the whole ledger. # And the ledger is built by applying the transactions to the parent # ledger. @@ -851,7 +851,7 @@ # #---------------- # -# The rippled server instance uses HTTPS GET requests in a variety of +# The xrpld server instance uses HTTPS GET requests in a variety of # circumstances, including but not limited to contacting trusted domains to # fetch information such as mapping an email address to a Ripple Payment # Network address. @@ -891,7 +891,7 @@ # #------------ # -# rippled creates 4 SQLite database to hold bookkeeping information +# xrpld creates 4 SQLite database to hold bookkeeping information # about transactions, local credentials, and various other things. # It also creates the NodeDB, which holds all the objects that # make up the current and historical ledgers. @@ -902,7 +902,7 @@ # the performance of the server. # # Partial pathnames will be considered relative to the location of -# the rippled.cfg file. +# the xrpld.cfg file. # # [node_db] Settings for the Node Database (required) # @@ -920,11 +920,11 @@ # type = NuDB # # NuDB is a high-performance database written by Ripple Labs and optimized -# for rippled and solid-state drives. +# for xrpld and solid-state drives. # # NuDB maintains its high speed regardless of the amount of history # stored. Online delete may be selected, but is not required. NuDB is -# available on all platforms that rippled runs on. +# available on all platforms that xrpld runs on. # # type = RocksDB # @@ -1049,7 +1049,7 @@ # # recovery_wait_seconds # The online delete process checks periodically -# that rippled is still in sync with the network, +# that xrpld is still in sync with the network, # and that the validated ledger is less than # 'age_threshold_seconds' old. If not, then continue # sleeping for this number of seconds and @@ -1069,8 +1069,8 @@ # The server creates and maintains 4 to 5 bookkeeping SQLite databases in # the 'database_path' location. If you omit this configuration setting, # the server creates a directory called "db" located in the same place as -# your rippled.cfg file. -# Partial pathnames are relative to the location of the rippled executable. +# your xrpld.cfg file. +# Partial pathnames are relative to the location of the xrpld executable. # # [sqlite] Tuning settings for the SQLite databases (optional) # @@ -1120,7 +1120,7 @@ # The default is "wal", which uses a write-ahead # log to implement database transactions. # Alternately, "memory" saves disk I/O, but if -# rippled crashes during a transaction, the +# xrpld crashes during a transaction, the # database is likely to be corrupted. # See https://www.sqlite.org/pragma.html#pragma_journal_mode # for more details about the available options. @@ -1130,7 +1130,7 @@ # synchronous Valid values: off, normal, full, extra # The default is "normal", which works well with # the "wal" journal mode. Alternatively, "off" -# allows rippled to continue as soon as data is +# allows xrpld to continue as soon as data is # passed to the OS, which can significantly # increase speed, but risks data corruption if # the host computer crashes before writing that @@ -1144,7 +1144,7 @@ # The default is "file", which will use files # for temporary database tables and indices. # Alternatively, "memory" may save I/O, but -# rippled does not currently use many, if any, +# xrpld does not currently use many, if any, # of these temporary objects. # See https://www.sqlite.org/pragma.html#pragma_temp_store # for more details about the available options. @@ -1173,7 +1173,7 @@ # # These settings are designed to help server administrators diagnose # problems, and obtain detailed information about the activities being -# performed by the rippled process. +# performed by the xrpld process. # # # @@ -1190,7 +1190,7 @@ # # Configuration parameters for the Beast. Insight stats collection module. # -# Insight is a module that collects information from the areas of rippled +# Insight is a module that collects information from the areas of xrpld # that have instrumentation. The configuration parameters control where the # collection metrics are sent. The parameters are expressed as key = value # pairs with no white space. The main parameter is the choice of server: @@ -1199,7 +1199,7 @@ # # Choice of server to send metrics to. Currently the only choice is # "statsd" which sends UDP packets to a StatsD daemon, which must be -# running while rippled is running. More information on StatsD is +# running while xrpld is running. More information on StatsD is # available here: # https://github.com/b/statsd_spec # @@ -1209,7 +1209,7 @@ # in the format, n.n.n.n:port. # # "prefix" A string prepended to each collected metric. This is used -# to distinguish between different running instances of rippled. +# to distinguish between different running instances of xrpld. # # If this section is missing, or the server type is unspecified or unknown, # statistics are not collected or reported. @@ -1236,7 +1236,7 @@ # # Example: # [perf] -# perf_log=/var/log/rippled/perf.log +# perf_log=/var/log/xrpld/perf.log # log_interval=2 # #------------------------------------------------------------------------------- @@ -1246,7 +1246,7 @@ #---------- # # The vote settings configure settings for the entire Ripple network. -# While a single instance of rippled cannot unilaterally enforce network-wide +# While a single instance of xrpld cannot unilaterally enforce network-wide # settings, these choices become part of the instance's vote during the # consensus process for each voting ledger. # @@ -1260,7 +1260,7 @@ # The reference transaction is the simplest form of transaction. # It represents an XRP payment between two parties. # -# If this parameter is unspecified, rippled will use an internal +# If this parameter is unspecified, xrpld will use an internal # default. Don't change this without understanding the consequences. # # Example: @@ -1272,7 +1272,7 @@ # account's XRP balance that is at or below the reserve may only be # spent on transaction fees, and not transferred out of the account. # -# If this parameter is unspecified, rippled will use an internal +# If this parameter is unspecified, xrpld will use an internal # default. Don't change this without understanding the consequences. # # Example: @@ -1284,7 +1284,7 @@ # each ledger item owned by the account. Ledger items an account may # own include trust lines, open orders, and tickets. # -# If this parameter is unspecified, rippled will use an internal +# If this parameter is unspecified, xrpld will use an internal # default. Don't change this without understanding the consequences. # # Example: @@ -1326,7 +1326,7 @@ # tool instead. # # This flag has no effect on the "sign" and "sign_for" command line options -# that rippled makes available. +# that xrpld makes available. # # The default value of this field is "false" # @@ -1405,7 +1405,7 @@ #-------------------- # # Administrators can use these values as a starting point for configuring -# their instance of rippled, but each value should be checked to make sure +# their instance of xrpld, but each value should be checked to make sure # it meets the business requirements for the organization. # # Server @@ -1415,7 +1415,7 @@ # "peer" # # Peer protocol open to everyone. This is required to accept -# incoming rippled connections. This does not affect automatic +# incoming xrpld connections. This does not affect automatic # or manual outgoing Peer protocol connections. # # "rpc" @@ -1432,7 +1432,7 @@ # # ETL commands for Clio. We recommend setting secure_gateway # in this section to a comma-separated list of the addresses -# of your Clio servers, in order to bypass rippled's rate limiting. +# of your Clio servers, in order to bypass xrpld's rate limiting. # # This port is commented out but can be enabled by removing # the '#' from each corresponding line including the entry under [server] @@ -1449,8 +1449,8 @@ # NOTE # # To accept connections on well known ports such as 80 (HTTP) or -# 443 (HTTPS), most operating systems will require rippled to -# run with administrator privileges, or else rippled will not start. +# 443 (HTTPS), most operating systems will require xrpld to +# run with administrator privileges, or else xrpld will not start. [server] port_rpc_admin_local @@ -1496,7 +1496,7 @@ secure_gateway = 127.0.0.1 #------------------------------------------------------------------------------- -# This is primary persistent datastore for rippled. This includes transaction +# This is primary persistent datastore for xrpld. This includes transaction # metadata, account states, and ledger headers. Helpful information can be # found at https://xrpl.org/capacity-planning.html#node-db-type # type=NuDB is recommended for non-validators with fast SSDs. Validators or @@ -1511,19 +1511,19 @@ secure_gateway = 127.0.0.1 # deletion. [node_db] type=NuDB -path=/var/lib/rippled/db/nudb +path=/var/lib/xrpld/db/nudb nudb_block_size=4096 online_delete=512 advisory_delete=0 [database_path] -/var/lib/rippled/db +/var/lib/xrpld/db # This needs to be an absolute directory reference, not a relative one. # Modify this value as required. [debug_logfile] -/var/log/rippled/debug.log +/var/log/xrpld/debug.log # To use the XRP test network # (see https://xrpl.org/connect-your-rippled-to-the-xrp-test-net.html), @@ -1533,7 +1533,7 @@ advisory_delete=0 # File containing trusted validator keys or validator list publishers. # Unless an absolute path is specified, it will be considered relative to the -# folder in which the rippled.cfg file is located. +# folder in which the xrpld.cfg file is located. [validators_file] validators.txt diff --git a/cmake/XrplInstall.cmake b/cmake/XrplInstall.cmake index 67aca8f048..310436998d 100644 --- a/cmake/XrplInstall.cmake +++ b/cmake/XrplInstall.cmake @@ -62,7 +62,7 @@ if (is_root_project AND TARGET xrpld) message (\"-- Skipping : \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}/\${NEWNAME}\") endif () endmacro() - copy_if_not_exists(\"${CMAKE_CURRENT_SOURCE_DIR}/cfg/rippled-example.cfg\" etc rippled.cfg) + copy_if_not_exists(\"${CMAKE_CURRENT_SOURCE_DIR}/cfg/xrpld-example.cfg\" etc xrpld.cfg) copy_if_not_exists(\"${CMAKE_CURRENT_SOURCE_DIR}/cfg/validators-example.txt\" etc validators.txt) ") install(CODE " diff --git a/include/xrpl/core/PerfLog.h b/include/xrpl/core/PerfLog.h index eb009de433..f8ca779963 100644 --- a/include/xrpl/core/PerfLog.h +++ b/include/xrpl/core/PerfLog.h @@ -40,7 +40,7 @@ public: using microseconds = std::chrono::microseconds; /** - * Configuration from [perf] section of rippled.cfg. + * Configuration from [perf] section of xrpld.cfg. */ struct Setup { diff --git a/include/xrpl/nodestore/README.md b/include/xrpl/nodestore/README.md index a5d1128d17..83da29d9ce 100644 --- a/include/xrpl/nodestore/README.md +++ b/include/xrpl/nodestore/README.md @@ -130,7 +130,7 @@ newer versions of RocksDB (TBD). ## Discussion RocksDBQuickFactory is intended to provide a testbed for comparing potential -rocksdb performance with the existing recommended configuration in rippled.cfg. +rocksdb performance with the existing recommended configuration in xrpld.cfg. Through various executions and profiling some conclusions are presented below. - If the write ahead log is enabled, insert speed soon clogs up under load. The diff --git a/src/libxrpl/nodestore/ManagerImp.cpp b/src/libxrpl/nodestore/ManagerImp.cpp index b53d03e668..58accd4108 100644 --- a/src/libxrpl/nodestore/ManagerImp.cpp +++ b/src/libxrpl/nodestore/ManagerImp.cpp @@ -18,8 +18,8 @@ void ManagerImp::missing_backend() { Throw( - "Your rippled.cfg is missing a [node_db] entry, " - "please see the rippled-example.cfg file!"); + "Your xrpld.cfg is missing a [node_db] entry, " + "please see the xrpld-example.cfg file!"); } // We shouldn't rely on global variables for lifetime management because their diff --git a/src/test/core/Config_test.cpp b/src/test/core/Config_test.cpp index 86f09e6c02..139e8702eb 100644 --- a/src/test/core/Config_test.cpp +++ b/src/test/core/Config_test.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -18,7 +19,7 @@ namespace detail { std::string configContents(std::string const& dbPath, std::string const& validatorsFile) { - static boost::format configContentsTemplate(R"rippleConfig( + static boost::format configContentsTemplate(R"xrpldConfig( [server] port_rpc port_peer @@ -51,14 +52,14 @@ protocol = wss [node_size] medium -# This is primary persistent datastore for rippled. This includes transaction +# This is primary persistent datastore for xrpld. This includes transaction # metadata, account states, and ledger headers. Helpful information can be # found on https://xrpl.org/capacity-planning.html#node-db-type # delete old ledgers while maintaining at least 2000. Do not require an # external administrative command to initiate deletion. [node_db] type=memory -path=/Users/dummy/ripple/config/db/rocksdb +path=/Users/dummy/xrpld/config/db/rocksdb open_files=2000 filter_bits=12 cache_mb=256 @@ -72,7 +73,7 @@ file_size_mult=2 # This needs to be an absolute directory reference, not a relative one. # Modify this value as required. [debug_logfile] -/Users/dummy/ripple/config/log/debug.log +/Users/dummy/xrpld/config/log/debug.log [sntp_servers] time.windows.com @@ -97,7 +98,7 @@ r.ripple.com 51235 [sqdb] backend=sqlite -)rippleConfig"); +)xrpldConfig"); std::string dbPathSection = dbPath.empty() ? "" : "[database_path]\n" + dbPath; @@ -107,9 +108,9 @@ backend=sqlite } /** - Write a rippled config file and remove when done. + Write a xrpld config file and remove when done. */ -class RippledCfgGuard : public xrpl::detail::FileDirGuard +class FileCfgGuard : public xrpl::detail::FileDirGuard { private: path dataDir_; @@ -119,17 +120,18 @@ private: Config config_; public: - RippledCfgGuard( + FileCfgGuard( beast::unit_test::suite& test, path subDir, path const& dbPath, + path const& configFile, path const& validatorsFile, bool useCounter = true, std::string confContents = "") : FileDirGuard( test, std::move(subDir), - path(Config::configFileName), + configFile, confContents.empty() ? configContents(dbPath.string(), validatorsFile.string()) : confContents, @@ -171,7 +173,7 @@ public: return fileExists(); } - ~RippledCfgGuard() + ~FileCfgGuard() { try { @@ -182,7 +184,7 @@ public: catch (std::exception& e) { // if we throw here, just let it die. - test_.log << "Error in ~RippledCfgGuard: " << e.what() << std::endl; + test_.log << "Error in ~FileCfgGuard: " << e.what() << std::endl; }; } }; @@ -190,7 +192,7 @@ public: std::string valFileContents() { - std::string configContents(R"rippleConfig( + std::string configContents(R"xrpldConfig( [validators] n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj @@ -204,8 +206,8 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8 nHUPDdcdb2Y5DZAJne4c2iabFuAP3F34xZUgYQT2NH7qfkdapgnz [validator_list_sites] -recommendedripplevalidators.com -moreripplevalidators.net +recommendedxrplvalidators.com +morexrplvalidators.net [validator_list_keys] 03E74EE14CB525AFBB9F1B7D86CD58ECC4B91452294B42AB4E78F260BD905C091D @@ -213,7 +215,7 @@ moreripplevalidators.net [validator_list_threshold] 2 -)rippleConfig"); +)xrpldConfig"); return configContents; } @@ -270,7 +272,7 @@ public: Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [server] port_rpc port_peer @@ -278,7 +280,7 @@ port_wss_admin [ssl_verify] 0 -)rippleConfig"); +)xrpldConfig"); c.loadFromString(toLoad); @@ -291,6 +293,126 @@ port_wss_admin BEAST_EXPECT(c.legacy("not_in_file") == "new_value"); } void + testConfigFile() + { + testcase("config_file"); + + using namespace boost::filesystem; + auto const cwd = current_path(); + + // Test both config file names. + char const* configFiles[] = { + Config::configFileName, Config::configLegacyName}; + + // Config file in current directory. + for (auto const& configFile : configFiles) + { + // Use a temporary directory for testing. + beast::temp_dir td; + current_path(td.path()); + path const f = td.file(configFile); + std::ofstream o(f.string()); + o << detail::configContents("", ""); + o.close(); + + // Load the config file from the current directory and verify it. + Config c; + c.setup("", true, false, true); + BEAST_EXPECT(c.section(SECTION_DEBUG_LOGFILE).values().size() == 1); + BEAST_EXPECT( + c.section(SECTION_DEBUG_LOGFILE).values()[0] == + "/Users/dummy/xrpld/config/log/debug.log"); + } + + // Config file in HOME or XDG_CONFIG_HOME directory. +#if BOOST_OS_LINUX || BOOST_OS_MACOS + for (auto const& configFile : configFiles) + { + // Point the current working directory to a temporary directory, so + // we don't pick up an actual config file from the repository root. + beast::temp_dir td; + current_path(td.path()); + + // The XDG config directory is set: the config file must be in a + // subdirectory named after the system. + { + beast::temp_dir tc; + + // Set the HOME and XDG_CONFIG_HOME environment variables. The + // HOME variable is not used when XDG_CONFIG_HOME is set, but + // must be set. + char const* h = getenv("HOME"); + setenv("HOME", tc.path().c_str(), 1); + char const* x = getenv("XDG_CONFIG_HOME"); + setenv("XDG_CONFIG_HOME", tc.path().c_str(), 1); + + // Create the config file in '${XDG_CONFIG_HOME}/[systemName]'. + path p = tc.file(systemName()); + create_directory(p); + p = tc.file(systemName() + "/" + configFile); + std::ofstream o(p.string()); + o << detail::configContents("", ""); + o.close(); + + // Load the config file from the config directory and verify it. + Config c; + c.setup("", true, false, true); + BEAST_EXPECT( + c.section(SECTION_DEBUG_LOGFILE).values().size() == 1); + BEAST_EXPECT( + c.section(SECTION_DEBUG_LOGFILE).values()[0] == + "/Users/dummy/xrpld/config/log/debug.log"); + + // Restore the environment variables. + h ? setenv("HOME", h, 1) : unsetenv("HOME"); + x ? setenv("XDG_CONFIG_HOME", x, 1) + : unsetenv("XDG_CONFIG_HOME"); + } + + // The XDG config directory is not set: the config file must be in a + // subdirectory named .config followed by the system name. + { + beast::temp_dir tc; + + // Set only the HOME environment variable. + char const* h = getenv("HOME"); + setenv("HOME", tc.path().c_str(), 1); + char const* x = getenv("XDG_CONFIG_HOME"); + unsetenv("XDG_CONFIG_HOME"); + + // Create the config file in '${HOME}/.config/[systemName]'. + std::string s = ".config"; + path p = tc.file(s); + create_directory(p); + s += "/" + systemName(); + p = tc.file(s); + create_directory(p); + p = tc.file(s + "/" + configFile); + std::ofstream o(p.string()); + o << detail::configContents("", ""); + o.close(); + + // Load the config file from the config directory and verify it. + Config c; + c.setup("", true, false, true); + BEAST_EXPECT( + c.section(SECTION_DEBUG_LOGFILE).values().size() == 1); + BEAST_EXPECT( + c.section(SECTION_DEBUG_LOGFILE).values()[0] == + "/Users/dummy/xrpld/config/log/debug.log"); + + // Restore the environment variables. + h ? setenv("HOME", h, 1) : unsetenv("HOME"); + if (x) + setenv("XDG_CONFIG_HOME", x, 1); + } + } +#endif + + // Restore the current working directory. + current_path(cwd); + } + void testDbPath() { testcase("database_path"); @@ -326,11 +448,16 @@ port_wss_admin { // read from file absolute path auto const cwd = current_path(); - xrpl::detail::DirGuard const g0(*this, "test_db"); + detail::DirGuard const g0(*this, "test_db"); path const dataDirRel("test_data_dir"); path const dataDirAbs(cwd / g0.subdir() / dataDirRel); - detail::RippledCfgGuard const g( - *this, g0.subdir(), dataDirAbs, "", false); + detail::FileCfgGuard const g( + *this, + g0.subdir(), + dataDirAbs, + Config::configFileName, + "", + false); auto const& c(g.config()); BEAST_EXPECT(g.dataDirExists()); BEAST_EXPECT(g.configFileExists()); @@ -339,7 +466,8 @@ port_wss_admin { // read from file relative path std::string const dbPath("my_db"); - detail::RippledCfgGuard const g(*this, "test_db", dbPath, ""); + detail::FileCfgGuard const g( + *this, "test_db", dbPath, Config::configFileName, ""); auto const& c(g.config()); std::string const nativeDbPath = absolute(path(dbPath)).string(); BEAST_EXPECT(g.dataDirExists()); @@ -348,7 +476,8 @@ port_wss_admin } { // read from file no path - detail::RippledCfgGuard const g(*this, "test_db", "", ""); + detail::FileCfgGuard const g( + *this, "test_db", "", Config::configFileName, ""); auto const& c(g.config()); std::string const nativeDbPath = absolute(g.subdir() / path(Config::databaseDirName)).string(); @@ -378,13 +507,13 @@ port_wss_admin { Config c; - static boost::format configTemplate(R"rippleConfig( + static boost::format configTemplate(R"xrpldConfig( [validation_seed] %1% [validator_token] %2% -)rippleConfig"); +)xrpldConfig"); std::string error; auto const expectedError = "Cannot have both [validation_seed] " @@ -410,10 +539,10 @@ port_wss_admin Config c; try { - c.loadFromString(R"rippleConfig( + c.loadFromString(R"xrpldConfig( [network_id] main -)rippleConfig"); +)xrpldConfig"); } catch (std::runtime_error& e) { @@ -425,8 +554,8 @@ main try { - c.loadFromString(R"rippleConfig( -)rippleConfig"); + c.loadFromString(R"xrpldConfig( +)xrpldConfig"); } catch (std::runtime_error& e) { @@ -438,10 +567,10 @@ main try { - c.loadFromString(R"rippleConfig( + c.loadFromString(R"xrpldConfig( [network_id] 255 -)rippleConfig"); +)xrpldConfig"); } catch (std::runtime_error& e) { @@ -453,10 +582,10 @@ main try { - c.loadFromString(R"rippleConfig( + c.loadFromString(R"xrpldConfig( [network_id] 10000 -)rippleConfig"); +)xrpldConfig"); } catch (std::runtime_error& e) { @@ -516,7 +645,7 @@ main { // load validators from config into single section Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [validators] n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj @@ -525,7 +654,7 @@ n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C [validator_keys] nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5 nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8 -)rippleConfig"); +)xrpldConfig"); c.loadFromString(toLoad); BEAST_EXPECT(c.legacy("validators_file").empty()); BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 5); @@ -534,9 +663,9 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8 { // load validator list sites and keys from config Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [validator_list_sites] -ripplevalidators.com +xrplvalidators.com trustthesevalidators.gov [validator_list_keys] @@ -544,13 +673,13 @@ trustthesevalidators.gov [validator_list_threshold] 1 -)rippleConfig"); +)xrpldConfig"); c.loadFromString(toLoad); BEAST_EXPECT( c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); BEAST_EXPECT( c.section(SECTION_VALIDATOR_LIST_SITES).values()[0] == - "ripplevalidators.com"); + "xrplvalidators.com"); BEAST_EXPECT( c.section(SECTION_VALIDATOR_LIST_SITES).values()[1] == "trustthesevalidators.gov"); @@ -570,9 +699,9 @@ trustthesevalidators.gov { // load validator list sites and keys from config Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [validator_list_sites] -ripplevalidators.com +xrplvalidators.com trustthesevalidators.gov [validator_list_keys] @@ -580,13 +709,13 @@ trustthesevalidators.gov [validator_list_threshold] 0 -)rippleConfig"); +)xrpldConfig"); c.loadFromString(toLoad); BEAST_EXPECT( c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); BEAST_EXPECT( c.section(SECTION_VALIDATOR_LIST_SITES).values()[0] == - "ripplevalidators.com"); + "xrplvalidators.com"); BEAST_EXPECT( c.section(SECTION_VALIDATOR_LIST_SITES).values()[1] == "trustthesevalidators.gov"); @@ -607,9 +736,9 @@ trustthesevalidators.gov // load should throw if [validator_list_threshold] is greater than // the number of [validator_list_keys] Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [validator_list_sites] -ripplevalidators.com +xrplvalidators.com trustthesevalidators.gov [validator_list_keys] @@ -617,7 +746,7 @@ trustthesevalidators.gov [validator_list_threshold] 2 -)rippleConfig"); +)xrpldConfig"); std::string error; auto const expectedError = "Value in config section [validator_list_threshold] exceeds " @@ -636,9 +765,9 @@ trustthesevalidators.gov { // load should throw if [validator_list_threshold] is malformed Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [validator_list_sites] -ripplevalidators.com +xrplvalidators.com trustthesevalidators.gov [validator_list_keys] @@ -646,7 +775,7 @@ trustthesevalidators.gov [validator_list_threshold] value = 2 -)rippleConfig"); +)xrpldConfig"); std::string error; auto const expectedError = "Config section [validator_list_threshold] should contain " @@ -665,9 +794,9 @@ value = 2 { // load should throw if [validator_list_threshold] is negative Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [validator_list_sites] -ripplevalidators.com +xrplvalidators.com trustthesevalidators.gov [validator_list_keys] @@ -675,7 +804,7 @@ trustthesevalidators.gov [validator_list_threshold] -1 -)rippleConfig"); +)xrpldConfig"); bool error = false; try { @@ -692,11 +821,11 @@ trustthesevalidators.gov // load should throw if [validator_list_sites] is configured but // [validator_list_keys] is not Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [validator_list_sites] -ripplevalidators.com +xrplvalidators.com trustthesevalidators.gov -)rippleConfig"); +)xrpldConfig"); std::string error; auto const expectedError = "[validator_list_keys] config section is missing"; @@ -736,8 +865,13 @@ trustthesevalidators.gov std::string const valFileName = "validators.txt"; detail::ValidatorsTxtGuard const vtg( *this, "test_cfg", valFileName); - detail::RippledCfgGuard const rcg( - *this, vtg.subdir(), "", valFileName, false); + detail::FileCfgGuard const rcg( + *this, + vtg.subdir(), + "", + Config::configFileName, + valFileName, + false); BEAST_EXPECT(vtg.validatorsFileExists()); BEAST_EXPECT(rcg.configFileExists()); auto const& c(rcg.config()); @@ -758,8 +892,13 @@ trustthesevalidators.gov detail::ValidatorsTxtGuard const vtg( *this, "test_cfg", "validators.txt"); auto const valFilePath = ".." / vtg.subdir() / "validators.txt"; - detail::RippledCfgGuard const rcg( - *this, vtg.subdir(), "", valFilePath, false); + detail::FileCfgGuard const rcg( + *this, + vtg.subdir(), + "", + Config::configFileName, + valFilePath, + false); BEAST_EXPECT(vtg.validatorsFileExists()); BEAST_EXPECT(rcg.configFileExists()); auto const& c(rcg.config()); @@ -778,8 +917,8 @@ trustthesevalidators.gov // load from validators file in default location detail::ValidatorsTxtGuard const vtg( *this, "test_cfg", "validators.txt"); - detail::RippledCfgGuard const rcg( - *this, vtg.subdir(), "", "", false); + detail::FileCfgGuard const rcg( + *this, vtg.subdir(), "", Config::configFileName, "", false); BEAST_EXPECT(vtg.validatorsFileExists()); BEAST_EXPECT(rcg.configFileExists()); auto const& c(rcg.config()); @@ -803,8 +942,13 @@ trustthesevalidators.gov detail::ValidatorsTxtGuard const vtgDefault( *this, vtg.subdir(), "validators.txt", false); BEAST_EXPECT(vtgDefault.validatorsFileExists()); - detail::RippledCfgGuard const rcg( - *this, vtg.subdir(), "", vtg.validatorsFile(), false); + detail::FileCfgGuard const rcg( + *this, + vtg.subdir(), + "", + Config::configFileName, + vtg.validatorsFile(), + false); BEAST_EXPECT(rcg.configFileExists()); auto const& c(rcg.config()); BEAST_EXPECT(c.legacy("validators_file") == vtg.validatorsFile()); @@ -821,7 +965,7 @@ trustthesevalidators.gov { // load validators from both config and validators file - boost::format cc(R"rippleConfig( + boost::format cc(R"xrpldConfig( [validators_file] %1% @@ -837,12 +981,12 @@ nHB1X37qrniVugfQcuBTAjswphC1drx7QjFFojJPZwKHHnt8kU7v nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB [validator_list_sites] -ripplevalidators.com +xrplvalidators.com trustthesevalidators.gov [validator_list_keys] 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566 -)rippleConfig"); +)xrpldConfig"); detail::ValidatorsTxtGuard const vtg( *this, "test_cfg", "validators.cfg"); BEAST_EXPECT(vtg.validatorsFileExists()); @@ -861,14 +1005,14 @@ trustthesevalidators.gov } { // load should throw if [validator_list_threshold] is present both - // in rippled cfg and validators file - boost::format cc(R"rippleConfig( + // in xrpld.cfg and validators file + boost::format cc(R"xrpldConfig( [validators_file] %1% [validator_list_threshold] 1 -)rippleConfig"); +)xrpldConfig"); std::string error; detail::ValidatorsTxtGuard const vtg( *this, "test_cfg", "validators.cfg"); @@ -890,7 +1034,7 @@ trustthesevalidators.gov } { // load should throw if [validators], [validator_keys] and - // [validator_list_keys] are missing from rippled cfg and + // [validator_list_keys] are missing from xrpld.cfg and // validators file Config c; boost::format cc("[validators_file]\n%1%\n"); @@ -920,9 +1064,13 @@ trustthesevalidators.gov void testSetup(bool explicitPath) { - detail::RippledCfgGuard const cfg( - *this, "testSetup", explicitPath ? "test_db" : "", ""); - /* RippledCfgGuard has a Config object that gets loaded on + detail::FileCfgGuard const cfg( + *this, + "testSetup", + explicitPath ? "test_db" : "", + Config::configFileName, + ""); + /* FileCfgGuard has a Config object that gets loaded on construction, but Config::setup is not reentrant, so we need a fresh config for every test case, so ignore it. */ @@ -1039,7 +1187,8 @@ trustthesevalidators.gov void testPort() { - detail::RippledCfgGuard const cfg(*this, "testPort", "", ""); + detail::FileCfgGuard const cfg( + *this, "testPort", "", Config::configFileName, ""); auto const& conf = cfg.config(); if (!BEAST_EXPECT(conf.exists("port_rpc"))) return; @@ -1065,8 +1214,14 @@ trustthesevalidators.gov try { - detail::RippledCfgGuard const cfg( - *this, "testPort", "", "", true, contents); + detail::FileCfgGuard const cfg( + *this, + "testPort", + "", + Config::configFileName, + "", + true, + contents); BEAST_EXPECT(false); } catch (std::exception const& ex) @@ -1377,9 +1532,9 @@ r.ripple.com:51235 for (auto& [unit, sec, val, shouldPass] : units) { Config c; - std::string toLoad(R"rippleConfig( + std::string toLoad(R"xrpldConfig( [amendment_majority_time] -)rippleConfig"); +)xrpldConfig"); toLoad += std::to_string(val) + space + unit; space = space == "" ? " " : ""; @@ -1480,6 +1635,7 @@ r.ripple.com:51235 run() override { testLegacy(); + testConfigFile(); testDbPath(); testValidatorKeys(); testValidatorsFile(); diff --git a/src/xrpld/app/misc/SHAMapStoreImp.h b/src/xrpld/app/misc/SHAMapStoreImp.h index e5a7435b0a..aed2343a49 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.h +++ b/src/xrpld/app/misc/SHAMapStoreImp.h @@ -87,7 +87,7 @@ private: /// If the node is out of sync during an online_delete healthWait() /// call, sleep the thread for this time, and continue checking until /// recovery. - /// See also: "recovery_wait_seconds" in rippled-example.cfg + /// See also: "recovery_wait_seconds" in xrpld-example.cfg std::chrono::seconds recoveryWaitTime_{5}; // these do not exist upon SHAMapStore creation, but do exist diff --git a/src/xrpld/core/Config.h b/src/xrpld/core/Config.h index cfd260787c..e25148aaa9 100644 --- a/src/xrpld/core/Config.h +++ b/src/xrpld/core/Config.h @@ -68,6 +68,7 @@ class Config : public BasicConfig public: // Settings related to the configuration file location and directories static char const* const configFileName; + static char const* const configLegacyName; static char const* const databaseDirName; static char const* const validatorsFileName; diff --git a/src/xrpld/core/detail/Config.cpp b/src/xrpld/core/detail/Config.cpp index e6c61e1471..1eb8d5984e 100644 --- a/src/xrpld/core/detail/Config.cpp +++ b/src/xrpld/core/detail/Config.cpp @@ -221,11 +221,12 @@ getSingleSection( //------------------------------------------------------------------------------ // -// Config (DEPRECATED) +// Config // //------------------------------------------------------------------------------ -char const* const Config::configFileName = "rippled.cfg"; +char const* const Config::configFileName = "xrpld.cfg"; +char const* const Config::configLegacyName = "rippled.cfg"; char const* const Config::databaseDirName = "db"; char const* const Config::validatorsFileName = "validators.txt"; @@ -295,76 +296,78 @@ Config::setup( bool bSilent, bool bStandalone) { - boost::filesystem::path dataDir; - std::string strDbPath, strConfFile; + setupControl(bQuiet, bSilent, bStandalone); // Determine the config and data directories. // If the config file is found in the current working // directory, use the current working directory as the // config directory and that with "db" as the data // directory. - - setupControl(bQuiet, bSilent, bStandalone); - - strDbPath = databaseDirName; - - if (!strConf.empty()) - strConfFile = strConf; - else - strConfFile = configFileName; + boost::filesystem::path dataDir; if (!strConf.empty()) { // --conf= : everything is relative that file. - CONFIG_FILE = strConfFile; + CONFIG_FILE = strConf; CONFIG_DIR = boost::filesystem::absolute(CONFIG_FILE); CONFIG_DIR.remove_filename(); - dataDir = CONFIG_DIR / strDbPath; + dataDir = CONFIG_DIR / databaseDirName; } else { - CONFIG_DIR = boost::filesystem::current_path(); - CONFIG_FILE = CONFIG_DIR / strConfFile; - dataDir = CONFIG_DIR / strDbPath; - - // Construct XDG config and data home. - // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html - auto const strHome = getEnvVar("HOME"); - auto strXdgConfigHome = getEnvVar("XDG_CONFIG_HOME"); - auto strXdgDataHome = getEnvVar("XDG_DATA_HOME"); - - if (boost::filesystem::exists(CONFIG_FILE) - // Can we figure out XDG dirs? - || (strHome.empty() && - (strXdgConfigHome.empty() || strXdgDataHome.empty()))) + do { - // Current working directory is fine, put dbs in a subdir. - } - else - { - if (strXdgConfigHome.empty()) + // Check if either of the config files exist in the current working + // directory, in which case the databases will be stored in a + // subdirectory. + CONFIG_DIR = boost::filesystem::current_path(); + dataDir = CONFIG_DIR / databaseDirName; + CONFIG_FILE = CONFIG_DIR / configFileName; + if (boost::filesystem::exists(CONFIG_FILE)) + break; + CONFIG_FILE = CONFIG_DIR / configLegacyName; + if (boost::filesystem::exists(CONFIG_FILE)) + break; + + // Check if the home directory is set, and optionally the XDG config + // and/or data directories, as the config may be there. See + // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html. + auto const strHome = getEnvVar("HOME"); + if (!strHome.empty()) { - // $XDG_CONFIG_HOME was not set, use default based on $HOME. - strXdgConfigHome = strHome + "/.config"; + auto strXdgConfigHome = getEnvVar("XDG_CONFIG_HOME"); + auto strXdgDataHome = getEnvVar("XDG_DATA_HOME"); + if (strXdgConfigHome.empty()) + { + // $XDG_CONFIG_HOME was not set, use default based on $HOME. + strXdgConfigHome = strHome + "/.config"; + } + if (strXdgDataHome.empty()) + { + // $XDG_DATA_HOME was not set, use default based on $HOME. + strXdgDataHome = strHome + "/.local/share"; + } + + // Check if either of the config files exist in the XDG config + // dir. + dataDir = strXdgDataHome + "/" + systemName(); + CONFIG_DIR = strXdgConfigHome + "/" + systemName(); + CONFIG_FILE = CONFIG_DIR / configFileName; + if (boost::filesystem::exists(CONFIG_FILE)) + break; + CONFIG_FILE = CONFIG_DIR / configLegacyName; + if (boost::filesystem::exists(CONFIG_FILE)) + break; } - if (strXdgDataHome.empty()) - { - // $XDG_DATA_HOME was not set, use default based on $HOME. - strXdgDataHome = strHome + "/.local/share"; - } - - CONFIG_DIR = strXdgConfigHome + "/" + systemName(); - CONFIG_FILE = CONFIG_DIR / strConfFile; - dataDir = strXdgDataHome + "/" + systemName(); - - if (!boost::filesystem::exists(CONFIG_FILE)) - { - CONFIG_DIR = "/etc/opt/" + systemName(); - CONFIG_FILE = CONFIG_DIR / strConfFile; - dataDir = "/var/opt/" + systemName(); - } - } + // As a last resort, check the system config directory. + dataDir = "/var/opt/" + systemName(); + CONFIG_DIR = "/etc/opt/" + systemName(); + CONFIG_FILE = CONFIG_DIR / configFileName; + if (boost::filesystem::exists(CONFIG_FILE)) + break; + CONFIG_FILE = CONFIG_DIR / configLegacyName; + } while (false); } // Update default values @@ -374,11 +377,9 @@ Config::setup( std::string const dbPath(legacy("database_path")); if (!dbPath.empty()) dataDir = boost::filesystem::path(dbPath); - else if (RUN_STANDALONE) - dataDir.clear(); } - if (!dataDir.empty()) + if (!RUN_STANDALONE) { boost::system::error_code ec; boost::filesystem::create_directories(dataDir, ec); diff --git a/src/xrpld/overlay/README.md b/src/xrpld/overlay/README.md index cd00488915..51eb96a001 100644 --- a/src/xrpld/overlay/README.md +++ b/src/xrpld/overlay/README.md @@ -373,7 +373,7 @@ command. The key is in the `pubkey_node` value, and is a text string beginning with the letter `n`. The key is maintained across runs in a database. -Cluster members are configured in the `rippled.cfg` file under +Cluster members are configured in the `xrpld.cfg` file under `[cluster_nodes]`. Each member should be configured on a line beginning with the node public key, followed optionally by a space and a friendly name. diff --git a/src/xrpld/overlay/detail/OverlayImpl.cpp b/src/xrpld/overlay/detail/OverlayImpl.cpp index e5f77021d7..7cd02c72e0 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.cpp +++ b/src/xrpld/overlay/detail/OverlayImpl.cpp @@ -514,7 +514,7 @@ OverlayImpl::start() m_peerFinder->addFallbackStrings(base + name, ips); }); - // Add the ips_fixed from the rippled.cfg file + // Add the ips_fixed from the xrpld.cfg file if (!app_.config().standalone() && !app_.config().IPS_FIXED.empty()) { m_resolver.resolve( From 44d21b8f6daf87b286473686c5e75b7b513c7db2 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 5 Jan 2026 10:54:24 -0500 Subject: [PATCH 051/105] test: add more tests for `ledger_entry` RPC (#5858) This change adds some basic tests for all the `ledger_entry` helper functions, so each ledger entry type is covered. There are further some minor refactors in `parseAMM` to provide better error messages. Finally, to improve readability, alphabetization was applied in the helper functions. --- src/test/rpc/LedgerEntry_test.cpp | 482 +++++++++++++++++--- src/xrpld/rpc/handlers/LedgerEntry.cpp | 23 +- src/xrpld/rpc/handlers/LedgerEntryHelpers.h | 23 + 3 files changed, 447 insertions(+), 81 deletions(-) diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index ef5abdd800..551e67dc5e 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -30,6 +30,7 @@ enum class FieldType { CurrencyField, HashField, HashOrObjectField, + IssueField, ObjectField, StringField, TwoAccountArrayField, @@ -40,6 +41,8 @@ enum class FieldType { std::vector> mappings{ {jss::account, FieldType::AccountField}, {jss::accounts, FieldType::TwoAccountArrayField}, + {jss::asset, FieldType::IssueField}, + {jss::asset2, FieldType::IssueField}, {jss::authorize, FieldType::AccountField}, {jss::authorized, FieldType::AccountField}, {jss::credential_type, FieldType::BlobField}, @@ -74,24 +77,26 @@ getTypeName(FieldType typeID) { switch (typeID) { - case FieldType::UInt32Field: - return "number"; - case FieldType::UInt64Field: - return "number"; - case FieldType::HashField: - return "hex string"; case FieldType::AccountField: return "AccountID"; + case FieldType::ArrayField: + return "array"; case FieldType::BlobField: return "hex string"; case FieldType::CurrencyField: return "Currency"; - case FieldType::ArrayField: - return "array"; + case FieldType::HashField: + return "hex string"; case FieldType::HashOrObjectField: return "hex string or object"; + case FieldType::IssueField: + return "Issue"; case FieldType::TwoAccountArrayField: return "length-2 array of Accounts"; + case FieldType::UInt32Field: + return "number"; + case FieldType::UInt64Field: + return "number"; default: Throw( "unknown type " + std::to_string(static_cast(typeID))); @@ -192,34 +197,37 @@ class LedgerEntry_test : public beast::unit_test::suite return values; }; - static auto const& badUInt32Values = remove({2, 3}); - static auto const& badUInt64Values = remove({2, 3}); - static auto const& badHashValues = remove({2, 3, 7, 8, 16}); static auto const& badAccountValues = remove({12}); + static auto const& badArrayValues = remove({17, 20}); static auto const& badBlobValues = remove({3, 7, 8, 16}); static auto const& badCurrencyValues = remove({14}); - static auto const& badArrayValues = remove({17, 20}); + static auto const& badHashValues = remove({2, 3, 7, 8, 16}); static auto const& badIndexValues = remove({12, 16, 18, 19}); + static auto const& badUInt32Values = remove({2, 3}); + static auto const& badUInt64Values = remove({2, 3}); + static auto const& badIssueValues = remove({}); switch (fieldType) { - case FieldType::UInt32Field: - return badUInt32Values; - case FieldType::UInt64Field: - return badUInt64Values; - case FieldType::HashField: - return badHashValues; case FieldType::AccountField: return badAccountValues; + case FieldType::ArrayField: + case FieldType::TwoAccountArrayField: + return badArrayValues; case FieldType::BlobField: return badBlobValues; case FieldType::CurrencyField: return badCurrencyValues; - case FieldType::ArrayField: - case FieldType::TwoAccountArrayField: - return badArrayValues; + case FieldType::HashField: + return badHashValues; case FieldType::HashOrObjectField: return badIndexValues; + case FieldType::IssueField: + return badIssueValues; + case FieldType::UInt32Field: + return badUInt32Values; + case FieldType::UInt64Field: + return badUInt64Values; default: Throw( "unknown type " + @@ -236,30 +244,37 @@ class LedgerEntry_test : public beast::unit_test::suite arr[1u] = "r4MrUGTdB57duTnRs6KbsRGQXgkseGb1b5"; return arr; }(); + static Json::Value const issueObject = []() { + Json::Value arr(Json::objectValue); + arr[jss::currency] = "XRP"; + return arr; + }(); auto const typeID = getFieldType(fieldName); switch (typeID) { - case FieldType::UInt32Field: - return 1; - case FieldType::UInt64Field: - return 1; - case FieldType::HashField: - return "5233D68B4D44388F98559DE42903767803EFA7C1F8D01413FC16EE6" - "B01403D6D"; case FieldType::AccountField: return "r4MrUGTdB57duTnRs6KbsRGQXgkseGb1b5"; + case FieldType::ArrayField: + return Json::arrayValue; case FieldType::BlobField: return "ABCDEF"; case FieldType::CurrencyField: return "USD"; - case FieldType::ArrayField: - return Json::arrayValue; + case FieldType::HashField: + return "5233D68B4D44388F98559DE42903767803EFA7C1F8D01413FC16EE6" + "B01403D6D"; + case FieldType::IssueField: + return issueObject; case FieldType::HashOrObjectField: return "5233D68B4D44388F98559DE42903767803EFA7C1F8D01413FC16EE6" "B01403D6D"; case FieldType::TwoAccountArrayField: return twoAccountArray; + case FieldType::UInt32Field: + return 1; + case FieldType::UInt64Field: + return 1; default: Throw( "unknown type " + @@ -444,7 +459,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryInvalid() + testInvalid() { testcase("Invalid requests"); using namespace test::jtx; @@ -526,7 +541,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryAccountRoot() + testAccountRoot() { testcase("AccountRoot"); using namespace test::jtx; @@ -632,7 +647,147 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryCheck() + testAmendments() + { + testcase("Amendments"); + using namespace test::jtx; + Env env{*this}; + + // positive test + { + Keylet const keylet = keylet::amendments(); + + // easier to hack an object into the ledger than generate it + // legitimately + { + auto const amendments = [&](OpenView& view, + beast::Journal) -> bool { + auto const sle = std::make_shared(keylet); + + // Create Amendments vector (enabled amendments) + std::vector enabledAmendments; + enabledAmendments.push_back( + uint256::fromVoid("42426C4D4F1009EE67080A9B7965B44656D7" + "714D104A72F9B4369F97ABF044EE")); + enabledAmendments.push_back( + uint256::fromVoid("4C97EBA926031A7CF7D7B36FDE3ED66DDA54" + "21192D63DE53FFB46E43B9DC8373")); + enabledAmendments.push_back( + uint256::fromVoid("03BDC0099C4E14163ADA272C1B6F6FABB448" + "CC3E51F522F978041E4B57D9158C")); + enabledAmendments.push_back( + uint256::fromVoid("35291ADD2D79EB6991343BDA0912269C817D" + "0F094B02226C1C14AD2858962ED4")); + sle->setFieldV256( + sfAmendments, STVector256(enabledAmendments)); + + // Create Majorities array + STArray majorities; + + auto majority1 = STObject::makeInnerObject(sfMajority); + majority1.setFieldH256( + sfAmendment, + uint256::fromVoid("7BB62DC13EC72B775091E9C71BF8CF97E122" + "647693B50C5E87A80DFD6FCFAC50")); + majority1.setFieldU32(sfCloseTime, 779561310); + majorities.push_back(std::move(majority1)); + + auto majority2 = STObject::makeInnerObject(sfMajority); + majority2.setFieldH256( + sfAmendment, + uint256::fromVoid("755C971C29971C9F20C6F080F2ED96F87884" + "E40AD19554A5EBECDCEC8A1F77FE")); + majority2.setFieldU32(sfCloseTime, 779561310); + majorities.push_back(std::move(majority2)); + + sle->setFieldArray(sfMajorities, majorities); + + view.rawInsert(sle); + return true; + }; + env.app().openLedger().modify(amendments); + } + + Json::Value jvParams; + jvParams[jss::amendments] = to_string(keylet.key); + Json::Value const jrr = env.rpc( + "json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT( + jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Amendments); + } + + // negative tests + runLedgerEntryTest(env, jss::amendments); + } + + void + testAMM() + { + testcase("AMM"); + using namespace test::jtx; + Env env{*this}; + + // positive test + Account const alice{"alice"}; + env.fund(XRP(10000), alice); + env.close(); + AMM amm(env, alice, XRP(10), alice["USD"](1000)); + env.close(); + + { + Json::Value jvParams; + jvParams[jss::amm] = to_string(amm.ammID()); + auto const result = + env.rpc("json", "ledger_entry", to_string(jvParams)); + BEAST_EXPECT( + result.isObject() && result.isMember(jss::result) && + !result[jss::result].isMember(jss::error) && + result[jss::result].isMember(jss::node) && + result[jss::result][jss::node].isMember( + sfLedgerEntryType.jsonName) && + result[jss::result][jss::node][sfLedgerEntryType.jsonName] == + jss::AMM); + } + + { + Json::Value jvParams; + Json::Value ammParams(Json::objectValue); + { + Json::Value obj(Json::objectValue); + obj[jss::currency] = "XRP"; + ammParams[jss::asset] = obj; + } + { + Json::Value obj(Json::objectValue); + obj[jss::currency] = "USD"; + obj[jss::issuer] = alice.human(); + ammParams[jss::asset2] = obj; + } + jvParams[jss::amm] = ammParams; + auto const result = + env.rpc("json", "ledger_entry", to_string(jvParams)); + BEAST_EXPECT( + result.isObject() && result.isMember(jss::result) && + !result[jss::result].isMember(jss::error) && + result[jss::result].isMember(jss::node) && + result[jss::result][jss::node].isMember( + sfLedgerEntryType.jsonName) && + result[jss::result][jss::node][sfLedgerEntryType.jsonName] == + jss::AMM); + } + + // negative tests + runLedgerEntryTest( + env, + jss::amm, + { + {jss::asset, "malformedRequest"}, + {jss::asset2, "malformedRequest"}, + }); + } + + void + testCheck() { testcase("Check"); using namespace test::jtx; @@ -684,7 +839,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryCredentials() + testCredentials() { testcase("Credentials"); @@ -752,7 +907,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryDelegate() + testDelegate() { testcase("Delegate"); @@ -807,7 +962,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryDepositPreauth() + testDepositPreauth() { testcase("Deposit Preauth"); @@ -868,7 +1023,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryDepositPreauthCred() + testDepositPreauthCred() { testcase("Deposit Preauth with credentials"); @@ -1149,7 +1304,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryDirectory() + testDirectory() { testcase("Directory"); using namespace test::jtx; @@ -1303,7 +1458,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryEscrow() + testEscrow() { testcase("Escrow"); using namespace test::jtx; @@ -1365,7 +1520,177 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryOffer() + testFeeSettings() + { + testcase("Fee Settings"); + using namespace test::jtx; + Env env{*this}; + + // positive test + { + Keylet const keylet = keylet::fees(); + Json::Value jvParams; + jvParams[jss::fee] = to_string(keylet.key); + Json::Value const jrr = env.rpc( + "json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT( + jrr[jss::node][sfLedgerEntryType.jsonName] == jss::FeeSettings); + } + + // negative tests + runLedgerEntryTest(env, jss::fee); + } + + void + testLedgerHashes() + { + testcase("Ledger Hashes"); + using namespace test::jtx; + Env env{*this}; + + // positive test + { + Keylet const keylet = keylet::skip(); + Json::Value jvParams; + jvParams[jss::hashes] = to_string(keylet.key); + Json::Value const jrr = env.rpc( + "json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT( + jrr[jss::node][sfLedgerEntryType.jsonName] == + jss::LedgerHashes); + } + + // negative tests + runLedgerEntryTest(env, jss::hashes); + } + + void + testNFTokenOffer() + { + testcase("NFT Offer"); + using namespace test::jtx; + Env env{*this}; + + // positive test + Account const issuer{"issuer"}; + Account const buyer{"buyer"}; + env.fund(XRP(1000), issuer, buyer); + + uint256 const nftokenID0 = + token::getNextID(env, issuer, 0, tfTransferable); + env(token::mint(issuer, 0), txflags(tfTransferable)); + env.close(); + uint256 const offerID = keylet::nftoffer(issuer, env.seq(issuer)).key; + env(token::createOffer(issuer, nftokenID0, drops(1)), + token::destination(buyer), + txflags(tfSellNFToken)); + + { + Json::Value jvParams; + jvParams[jss::nft_offer] = to_string(offerID); + Json::Value const jrr = env.rpc( + "json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT( + jrr[jss::node][sfLedgerEntryType.jsonName] == + jss::NFTokenOffer); + BEAST_EXPECT(jrr[jss::node][sfOwner.jsonName] == issuer.human()); + BEAST_EXPECT( + jrr[jss::node][sfNFTokenID.jsonName] == to_string(nftokenID0)); + BEAST_EXPECT(jrr[jss::node][sfAmount.jsonName] == "1"); + } + + // negative tests + runLedgerEntryTest(env, jss::nft_offer); + } + + void + testNFTokenPage() + { + testcase("NFT Page"); + using namespace test::jtx; + Env env{*this}; + + // positive test + Account const issuer{"issuer"}; + env.fund(XRP(1000), issuer); + + env(token::mint(issuer, 0), txflags(tfTransferable)); + env.close(); + + auto const nftpage = keylet::nftpage_max(issuer); + BEAST_EXPECT(env.le(nftpage) != nullptr); + + { + Json::Value jvParams; + jvParams[jss::nft_page] = to_string(nftpage.key); + Json::Value const jrr = env.rpc( + "json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT( + jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NFTokenPage); + } + + // negative tests + runLedgerEntryTest(env, jss::nft_page); + } + + void + testNegativeUNL() + { + testcase("Negative UNL"); + using namespace test::jtx; + Env env{*this}; + + // positive test + { + Keylet const keylet = keylet::negativeUNL(); + + // easier to hack an object into the ledger than generate it + // legitimately + { + auto const nUNL = [&](OpenView& view, beast::Journal) -> bool { + auto const sle = std::make_shared(keylet); + + // Create DisabledValidators array + STArray disabledValidators; + auto disabledValidator = + STObject::makeInnerObject(sfDisabledValidator); + auto pubKeyBlob = strUnHex( + "ED58F6770DB5DD77E59D28CB650EC3816E2FC95021BB56E720C9A1" + "2DA79C58A3AB"); + disabledValidator.setFieldVL(sfPublicKey, *pubKeyBlob); + disabledValidator.setFieldU32( + sfFirstLedgerSequence, 91371264); + disabledValidators.push_back(std::move(disabledValidator)); + + sle->setFieldArray( + sfDisabledValidators, disabledValidators); + sle->setFieldH256( + sfPreviousTxnID, + uint256::fromVoid("8D47FFE664BE6C335108DF689537625855A6" + "A95160CC6D351341B9" + "2624D9C5E3")); + sle->setFieldU32(sfPreviousTxnLgrSeq, 91442944); + + view.rawInsert(sle); + return true; + }; + env.app().openLedger().modify(nUNL); + } + + Json::Value jvParams; + jvParams[jss::nunl] = to_string(keylet.key); + Json::Value const jrr = env.rpc( + "json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT( + jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NegativeUNL); + } + + // negative tests + runLedgerEntryTest(env, jss::nunl); + } + + void + testOffer() { testcase("Offer"); using namespace test::jtx; @@ -1413,7 +1738,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryPayChan() + testPayChan() { testcase("Pay Chan"); using namespace test::jtx; @@ -1475,7 +1800,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryRippleState() + testRippleState() { testcase("RippleState"); using namespace test::jtx; @@ -1626,7 +1951,16 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryTicket() + testSignerList() + { + testcase("Signer List"); + using namespace test::jtx; + Env env{*this}; + runLedgerEntryTest(env, jss::signer_list); + } + + void + testTicket() { testcase("Ticket"); using namespace test::jtx; @@ -1711,7 +2045,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryDID() + testDID() { testcase("DID"); using namespace test::jtx; @@ -1848,7 +2182,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryMPT() + testMPT() { testcase("MPT"); using namespace test::jtx; @@ -1931,7 +2265,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryPermissionedDomain() + testPermissionedDomain() { testcase("PermissionedDomain"); @@ -2010,7 +2344,7 @@ class LedgerEntry_test : public beast::unit_test::suite } void - testLedgerEntryCLI() + testCLI() { testcase("command-line"); using namespace test::jtx; @@ -2040,25 +2374,33 @@ public: void run() override { - testLedgerEntryInvalid(); - testLedgerEntryAccountRoot(); - testLedgerEntryCheck(); - testLedgerEntryCredentials(); - testLedgerEntryDelegate(); - testLedgerEntryDepositPreauth(); - testLedgerEntryDepositPreauthCred(); - testLedgerEntryDirectory(); - testLedgerEntryEscrow(); - testLedgerEntryOffer(); - testLedgerEntryPayChan(); - testLedgerEntryRippleState(); - testLedgerEntryTicket(); - testLedgerEntryDID(); + testInvalid(); + testAccountRoot(); + testAmendments(); + testAMM(); + testCheck(); + testCredentials(); + testDelegate(); + testDepositPreauth(); + testDepositPreauthCred(); + testDirectory(); + testEscrow(); + testFeeSettings(); + testLedgerHashes(); + testNFTokenOffer(); + testNFTokenPage(); + testNegativeUNL(); + testOffer(); + testPayChan(); + testRippleState(); + testSignerList(); + testTicket(); + testDID(); testInvalidOracleLedgerEntry(); testOracleLedgerEntry(); - testLedgerEntryMPT(); - testLedgerEntryPermissionedDomain(); - testLedgerEntryCLI(); + testMPT(); + testPermissionedDomain(); + testCLI(); } }; @@ -2086,7 +2428,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, } void - testLedgerEntryBridge() + testBridge() { testcase("ledger_entry: bridge"); using namespace test::jtx; @@ -2177,7 +2519,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, } void - testLedgerEntryClaimID() + testClaimID() { testcase("ledger_entry: xchain_claim_id"); using namespace test::jtx; @@ -2235,7 +2577,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, } void - testLedgerEntryCreateAccountClaimID() + testCreateAccountClaimID() { testcase("ledger_entry: xchain_create_account_claim_id"); using namespace test::jtx; @@ -2362,9 +2704,9 @@ public: void run() override { - testLedgerEntryBridge(); - testLedgerEntryClaimID(); - testLedgerEntryCreateAccountClaimID(); + testBridge(); + testClaimID(); + testCreateAccountClaimID(); } }; diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index 5b5db72c22..2e9d5b35bf 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -71,16 +71,17 @@ parseAMM(Json::Value const& params, Json::StaticString const fieldName) return Unexpected(value.error()); } - try - { - auto const issue = issueFromJson(params[jss::asset]); - auto const issue2 = issueFromJson(params[jss::asset2]); - return keylet::amm(issue, issue2).key; - } - catch (std::runtime_error const&) - { - return LedgerEntryHelpers::malformedError("malformedRequest", ""); - } + auto const asset = LedgerEntryHelpers::requiredIssue( + params, jss::asset, "malformedRequest"); + if (!asset) + return Unexpected(asset.error()); + + auto const asset2 = LedgerEntryHelpers::requiredIssue( + params, jss::asset2, "malformedRequest"); + if (!asset2) + return Unexpected(asset2.error()); + + return keylet::amm(*asset, *asset2).key; } static Expected @@ -424,7 +425,7 @@ parseLoan(Json::Value const& params, Json::StaticString const fieldName) } auto const id = LedgerEntryHelpers::requiredUInt256( - params, jss::loan_broker_id, "malformedOwner"); + params, jss::loan_broker_id, "malformedLoanBrokerID"); if (!id) return Unexpected(id.error()); auto const seq = LedgerEntryHelpers::requiredUInt32( diff --git a/src/xrpld/rpc/handlers/LedgerEntryHelpers.h b/src/xrpld/rpc/handlers/LedgerEntryHelpers.h index 0a4453c063..4b656e6b05 100644 --- a/src/xrpld/rpc/handlers/LedgerEntryHelpers.h +++ b/src/xrpld/rpc/handlers/LedgerEntryHelpers.h @@ -218,6 +218,29 @@ requiredUInt192( return required(params, fieldName, err, "Hash192"); } +template <> +std::optional +parse(Json::Value const& param) +{ + try + { + return issueFromJson(param); + } + catch (std::runtime_error const&) + { + return std::nullopt; + } +} + +Expected +requiredIssue( + Json::Value const& params, + Json::StaticString const fieldName, + std::string const& err) +{ + return required(params, fieldName, err, "Issue"); +} + Expected parseBridgeFields(Json::Value const& params) { From d734c8ddddb5ad0e4322f45d7dc47b2d609175b1 Mon Sep 17 00:00:00 2001 From: Bart Date: Tue, 6 Jan 2026 20:34:21 -0500 Subject: [PATCH 052/105] ci: Use ccache to cache build objects for speeding up building (#6104) Right now, each pipeline invocation builds the source code from scratch. Although compiled Conan dependencies are cached in a remote server, the source build objects are not. We are able to further speed up our builds by leveraging `ccache`. This change enables caching of build objects using `ccache` on Linux, macOS, and Windows. --- .github/actions/print-env/action.yml | 24 ++++---- .github/scripts/strategy-matrix/generate.py | 2 + .github/scripts/strategy-matrix/linux.json | 56 +++++++++---------- .github/workflows/on-pr.yml | 3 + .github/workflows/on-trigger.yml | 6 ++ .../workflows/reusable-build-test-config.yml | 52 ++++++++++++++--- .github/workflows/reusable-build-test.yml | 9 +++ .github/workflows/upload-conan-deps.yml | 2 +- CMakeLists.txt | 3 + cmake/Ccache.cmake | 51 +++++++++++++++++ 10 files changed, 159 insertions(+), 49 deletions(-) create mode 100644 cmake/Ccache.cmake diff --git a/.github/actions/print-env/action.yml b/.github/actions/print-env/action.yml index 6019a6de2f..3527ca6f02 100644 --- a/.github/actions/print-env/action.yml +++ b/.github/actions/print-env/action.yml @@ -11,12 +11,6 @@ runs: echo 'Checking environment variables.' set - echo 'Checking CMake version.' - cmake --version - - echo 'Checking Conan version.' - conan --version - - name: Check configuration (Linux and macOS) if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }} shell: bash @@ -27,17 +21,23 @@ runs: echo 'Checking environment variables.' env | sort - echo 'Checking CMake version.' - cmake --version - echo 'Checking compiler version.' ${{ runner.os == 'Linux' && '${CC}' || 'clang' }} --version - echo 'Checking Conan version.' - conan --version - echo 'Checking Ninja version.' ninja --version echo 'Checking nproc version.' nproc --version + + - name: Check configuration (all) + shell: bash + run: | + echo 'Checking Ccache version.' + ccache --version + + echo 'Checking CMake version.' + cmake --version + + echo 'Checking Conan version.' + conan --version diff --git a/.github/scripts/strategy-matrix/generate.py b/.github/scripts/strategy-matrix/generate.py index 79530a1d75..c3d2da1f9f 100755 --- a/.github/scripts/strategy-matrix/generate.py +++ b/.github/scripts/strategy-matrix/generate.py @@ -232,6 +232,8 @@ def generate_strategy_matrix(all: bool, config: Config) -> list: f"-{architecture['platform'][architecture['platform'].find('/') + 1 :]}" ) config_name += f"-{build_type.lower()}" + if "-Dcoverage=ON" in cmake_args: + config_name += "-coverage" if "-Dunity=ON" in cmake_args: config_name += "-unity" diff --git a/.github/scripts/strategy-matrix/linux.json b/.github/scripts/strategy-matrix/linux.json index 748ee031c9..669754554c 100644 --- a/.github/scripts/strategy-matrix/linux.json +++ b/.github/scripts/strategy-matrix/linux.json @@ -15,196 +15,196 @@ "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "12", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "13", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "15", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "16", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "17", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "18", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "19", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "20", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "trixie", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "trixie", "compiler_name": "gcc", "compiler_version": "15", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "trixie", "compiler_name": "clang", "compiler_version": "20", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "debian", "distro_version": "trixie", "compiler_name": "clang", "compiler_version": "21", - "image_sha": "0525eae" + "image_sha": "cc09fd3" }, { "distro_name": "rhel", "distro_version": "8", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "rhel", "distro_version": "8", "compiler_name": "clang", "compiler_version": "any", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "rhel", "distro_version": "9", "compiler_name": "gcc", "compiler_version": "12", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "rhel", "distro_version": "9", "compiler_name": "gcc", "compiler_version": "13", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "rhel", "distro_version": "9", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "rhel", "distro_version": "9", "compiler_name": "clang", "compiler_version": "any", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "rhel", "distro_version": "10", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "rhel", "distro_version": "10", "compiler_name": "clang", "compiler_version": "any", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "ubuntu", "distro_version": "jammy", "compiler_name": "gcc", "compiler_version": "12", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "gcc", "compiler_version": "13", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "clang", "compiler_version": "16", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "clang", "compiler_version": "17", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "clang", "compiler_version": "18", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "clang", "compiler_version": "19", - "image_sha": "e1782cd" + "image_sha": "cc09fd3" } ], "build_type": ["Debug", "Release"], diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index ff3d25812a..3aa48ac070 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -114,6 +114,9 @@ jobs: matrix: os: [linux, macos, windows] with: + # Enable ccache only for events targeting the XRPLF repository, since + # other accounts will not have access to our remote cache storage. + ccache_enabled: ${{ github.repository_owner == 'XRPLF' }} os: ${{ matrix.os }} secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml index b5a56fb671..a95402ced7 100644 --- a/.github/workflows/on-trigger.yml +++ b/.github/workflows/on-trigger.yml @@ -66,6 +66,12 @@ jobs: strategy: fail-fast: ${{ github.event_name == 'merge_group' }} matrix: + # Enable ccache only for events targeting the XRPLF repository, since + # other accounts will not have access to our remote cache storage. + # However, we do not enable ccache for events targeting the master or a + # release branch, to protect against the rare case that the output + # produced by ccache is not identical to a regular compilation. + ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !(github.base_ref == 'master' || startsWith(github.base_ref, 'release')) }} os: [linux, macos, windows] with: os: ${{ matrix.os }} diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index 98bf107225..575984162e 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -10,8 +10,14 @@ on: build_type: description: 'The build type to use ("Debug", "Release").' - type: string required: true + type: string + + ccache_enabled: + description: "Whether to enable ccache." + required: false + type: boolean + default: false cmake_args: description: "Additional arguments to pass to CMake." @@ -21,8 +27,8 @@ on: cmake_target: description: "The CMake target to build." - type: string required: true + type: string runs_on: description: Runner to run the job on as a JSON string @@ -66,8 +72,25 @@ jobs: container: ${{ inputs.image != '' && inputs.image || null }} timeout-minutes: 60 env: - ENABLED_VOIDSTAR: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }} - ENABLED_COVERAGE: ${{ contains(inputs.cmake_args, '-Dcoverage=ON') }} + # Use a namespace to keep the objects separate for each configuration. + CCACHE_NAMESPACE: ${{ inputs.config_name }} + # Ccache supports both Redis and HTTP endpoints. + # * For Redis, use the following format: redis://ip:port, see + # https://github.com/ccache/ccache/wiki/Redis-storage. Note that TLS is + # not directly supported by ccache, and requires use of a proxy. + # * For HTTP use the following format: http://ip:port/cache when using + # nginx as backend or http://ip:port|layout=bazel when using Bazel + # Remote Cache, see https://github.com/ccache/ccache/wiki/HTTP-storage. + # Note that HTTPS is not directly supported by ccache. + CCACHE_REMOTE_ONLY: true + CCACHE_REMOTE_STORAGE: http://cache.dev.ripplex.io:8080|layout=bazel + # Ignore the creation and modification timestamps on files, since the + # header files are copied into separate directories by CMake, which will + # otherwise result in cache misses. + CCACHE_SLOPPINESS: include_file_ctime,include_file_mtime + # Determine if coverage and voidstar should be enabled. + COVERAGE_ENABLED: ${{ contains(inputs.cmake_args, '-Dcoverage=ON') }} + VOIDSTAR_ENABLED: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }} steps: - name: Cleanup workspace (macOS and Windows) if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }} @@ -79,7 +102,11 @@ jobs: - name: Prepare runner uses: XRPLF/actions/prepare-runner@2ece4ec6ab7de266859a6f053571425b2bd684b6 with: - disable_ccache: false + disable_ccache: ${{ !inputs.ccache_enabled }} + + - name: Set ccache log file + if: ${{ inputs.ccache_enabled && runner.debug == '1' }} + run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >> "${GITHUB_ENV}" - name: Print build environment uses: ./.github/actions/print-env @@ -128,6 +155,15 @@ jobs: --parallel "${BUILD_NPROC}" \ --target "${CMAKE_TARGET}" + - name: Show ccache statistics + if: ${{ inputs.ccache_enabled }} + run: | + ccache --show-stats -vv + if [ '${{ runner.debug }}' = '1' ]; then + cat "${CCACHE_LOGFILE}" + curl ${CCACHE_REMOTE_STORAGE%|*}/status || true + fi + - name: Upload the binary (Linux) if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }} uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 @@ -150,7 +186,7 @@ jobs: fi - name: Verify presence of instrumentation (Linux) - if: ${{ runner.os == 'Linux' && env.ENABLED_VOIDSTAR == 'true' }} + if: ${{ runner.os == 'Linux' && env.VOIDSTAR_ENABLED == 'true' }} working-directory: ${{ env.BUILD_DIR }} run: | ./xrpld --version | grep libvoidstar @@ -185,7 +221,7 @@ jobs: netstat -an - name: Prepare coverage report - if: ${{ !inputs.build_only && env.ENABLED_COVERAGE == 'true' }} + if: ${{ !inputs.build_only && env.COVERAGE_ENABLED == 'true' }} working-directory: ${{ env.BUILD_DIR }} env: BUILD_NPROC: ${{ steps.nproc.outputs.nproc }} @@ -198,7 +234,7 @@ jobs: --target coverage - name: Upload coverage report - if: ${{ github.repository_owner == 'XRPLF' && !inputs.build_only && env.ENABLED_COVERAGE == 'true' }} + if: ${{ github.repository_owner == 'XRPLF' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }} uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3 with: disable_search: true diff --git a/.github/workflows/reusable-build-test.yml b/.github/workflows/reusable-build-test.yml index 7f14aacb9b..2b4d38da61 100644 --- a/.github/workflows/reusable-build-test.yml +++ b/.github/workflows/reusable-build-test.yml @@ -8,16 +8,24 @@ name: Build and test on: workflow_call: inputs: + ccache_enabled: + description: "Whether to enable ccache." + required: false + type: boolean + default: false + os: description: 'The operating system to use for the build ("linux", "macos", "windows").' required: true type: string + strategy_matrix: # TODO: Support additional strategies, e.g. "ubuntu" for generating all Ubuntu configurations. description: 'The strategy matrix to use for generating the configurations ("minimal", "all").' required: false type: string default: "minimal" + secrets: CODECOV_TOKEN: description: "The Codecov token to use for uploading coverage reports." @@ -43,6 +51,7 @@ jobs: with: build_only: ${{ matrix.build_only }} build_type: ${{ matrix.build_type }} + ccache_enabled: ${{ inputs.ccache_enabled }} cmake_args: ${{ matrix.cmake_args }} cmake_target: ${{ matrix.cmake_target }} runs_on: ${{ toJSON(matrix.architecture.runner) }} diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml index 5024666394..8a9993d37a 100644 --- a/.github/workflows/upload-conan-deps.yml +++ b/.github/workflows/upload-conan-deps.yml @@ -72,7 +72,7 @@ jobs: - name: Prepare runner uses: XRPLF/actions/prepare-runner@2ece4ec6ab7de266859a6f053571425b2bd684b6 with: - disable_ccache: false + disable_ccache: true - name: Print build environment uses: ./.github/actions/print-env diff --git a/CMakeLists.txt b/CMakeLists.txt index ade9c2f995..70bc02c66d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,9 @@ elseif(MSVC) add_compile_options(/wd4068) # Ignore unknown pragmas endif() +# Enable ccache to speed up builds. +include(Ccache) + # make GIT_COMMIT_HASH define available to all sources find_package(Git) if(Git_FOUND) diff --git a/cmake/Ccache.cmake b/cmake/Ccache.cmake new file mode 100644 index 0000000000..092212075c --- /dev/null +++ b/cmake/Ccache.cmake @@ -0,0 +1,51 @@ +find_program(CCACHE_PATH "ccache") +if (NOT CCACHE_PATH) + return() +endif () + +# For Linux and macOS we can use the ccache binary directly. +if (NOT MSVC) + set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PATH}") + set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PATH}") + message(STATUS "Found ccache: ${CCACHE_PATH}") + return() +endif () + +# For Windows more effort is required. The code below is a modified version of +# https://github.com/ccache/ccache/wiki/MS-Visual-Studio#usage-with-cmake. +if ("${CCACHE_PATH}" MATCHES "chocolatey") + message(DEBUG "Ccache path: ${CCACHE_PATH}") + # Chocolatey uses a shim executable that we cannot use directly, in which + # case we have to find the executable it points to. If we cannot find the + # target executable then we cannot use ccache. + find_program(BASH_PATH "bash") + if (NOT BASH_PATH) + message(WARNING "Could not find bash.") + return() + endif () + + execute_process( + COMMAND bash -c "export LC_ALL='en_US.UTF-8'; ${CCACHE_PATH} --shimgen-noop | grep -oP 'path to executable: \\K.+' | head -c -1" + OUTPUT_VARIABLE CCACHE_PATH) + + if (NOT CCACHE_PATH) + message(WARNING "Could not find ccache target.") + return() + endif () + file(TO_CMAKE_PATH "${CCACHE_PATH}" CCACHE_PATH) +endif () +message(STATUS "Found ccache: ${CCACHE_PATH}") + +# Tell cmake to use ccache for compiling with Visual Studio. +file(COPY_FILE + ${CCACHE_PATH} ${CMAKE_BINARY_DIR}/cl.exe + ONLY_IF_DIFFERENT) +set(CMAKE_VS_GLOBALS + "CLToolExe=cl.exe" + "CLToolPath=${CMAKE_BINARY_DIR}" + "TrackFileAccess=false" + "UseMultiToolTask=true") + +# By default Visual Studio generators will use /Zi, which is not compatible with +# ccache, so tell it to use /Z7 instead. +set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") From f80059e4673ad96010229c14dcdf0ac6cb11d9a0 Mon Sep 17 00:00:00 2001 From: Bart Date: Wed, 7 Jan 2026 06:07:53 -0500 Subject: [PATCH 053/105] ci: Move variable into right place (#6179) This change moves the `enable_ccache` variable in the `on-trigger.yml` file to the correct location. --- .github/workflows/on-trigger.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml index a95402ced7..2c63c2baa5 100644 --- a/.github/workflows/on-trigger.yml +++ b/.github/workflows/on-trigger.yml @@ -66,14 +66,14 @@ jobs: strategy: fail-fast: ${{ github.event_name == 'merge_group' }} matrix: - # Enable ccache only for events targeting the XRPLF repository, since - # other accounts will not have access to our remote cache storage. - # However, we do not enable ccache for events targeting the master or a - # release branch, to protect against the rare case that the output - # produced by ccache is not identical to a regular compilation. - ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !(github.base_ref == 'master' || startsWith(github.base_ref, 'release')) }} os: [linux, macos, windows] with: + # Enable ccache only for events targeting the XRPLF repository, since + # other accounts will not have access to our remote cache storage. + # However, we do not enable ccache for events targeting the master or a + # release branch, to protect against the rare case that the output + # produced by ccache is not identical to a regular compilation. + ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !(github.base_ref == 'master' || startsWith(github.base_ref, 'release')) }} os: ${{ matrix.os }} strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }} secrets: From 3c9f5b62525cb1d6ca1153eeb10433db7d7379fd Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 7 Jan 2026 12:10:19 -0500 Subject: [PATCH 054/105] refactor: Fix typos in comments, configure cspell (#6164) This change sets up a `cspell `configuration and fixes lots of typos in comments. There are no other code changes. --- .config/cspell.config.yaml | 272 ++++++++++++++++++ .github/scripts/levelization/README.md | 2 +- .pre-commit-config.yaml | 15 + CONTRIBUTING.md | 12 +- SECURITY.md | 2 +- cfg/xrpld-example.cfg | 2 +- cmake/XrplCore.cmake | 2 +- docs/0001-negative-unl/README.md | 2 +- .../negativeUNLSqDiagram.puml | 4 +- docs/consensus.md | 4 +- include/xrpl/basics/IntrusiveRefCounts.h | 2 +- include/xrpl/basics/Log.h | 3 +- include/xrpl/beast/core/LexicalCast.h | 2 +- include/xrpl/json/json_reader.h | 4 +- include/xrpl/json/json_value.h | 2 +- include/xrpl/ledger/CredentialHelpers.h | 5 +- include/xrpl/nodestore/DummyScheduler.h | 2 +- include/xrpl/nodestore/README.md | 4 +- .../proto/org/xrpl/rpc/v1/xrp_ledger.proto | 2 +- include/xrpl/protocol/Indexes.h | 2 +- include/xrpl/protocol/Protocol.h | 2 +- include/xrpl/protocol/Quality.h | 2 +- include/xrpl/protocol/TxFlags.h | 2 +- include/xrpl/protocol/XChainAttestations.h | 6 +- include/xrpl/protocol/detail/STVar.h | 2 +- .../xrpl/protocol/detail/ledger_entries.macro | 4 +- include/xrpl/resource/README.md | 2 +- include/xrpl/resource/detail/Logic.h | 2 +- include/xrpl/server/detail/LowestLayer.h | 2 +- include/xrpl/shamap/README.md | 2 +- include/xrpl/shamap/SHAMapItem.h | 4 +- src/libxrpl/basics/Number.cpp | 4 +- src/libxrpl/basics/make_SSLContext.cpp | 4 +- src/libxrpl/json/Writer.cpp | 2 +- src/libxrpl/ledger/View.cpp | 2 +- src/libxrpl/protocol/IOUAmount.cpp | 2 +- src/libxrpl/protocol/STAmount.cpp | 2 +- src/libxrpl/protocol/tokens.cpp | 2 +- src/test/app/AccountDelete_test.cpp | 6 +- src/test/app/AmendmentTable_test.cpp | 2 +- src/test/app/DepositAuth_test.cpp | 20 +- src/test/app/Escrow_test.cpp | 4 +- src/test/app/FixNFTokenPageLinks_test.cpp | 2 +- src/test/app/Invariants_test.cpp | 10 +- src/test/app/LoanBroker_test.cpp | 2 +- src/test/app/MPToken_test.cpp | 8 +- src/test/app/NFTokenBurn_test.cpp | 2 +- src/test/app/NFToken_test.cpp | 14 +- src/test/app/PayChan_test.cpp | 6 +- src/test/app/PermissionedDEX_test.cpp | 2 +- src/test/app/ValidatorSite_test.cpp | 6 +- src/test/basics/IntrusiveShared_test.cpp | 2 +- src/test/basics/XRPAmount_test.cpp | 2 +- .../consensus/ByzantineFailureSim_test.cpp | 2 +- src/test/consensus/Consensus_test.cpp | 12 +- .../DistributedValidatorsSim_test.cpp | 4 +- src/test/consensus/ScaleFreeSim_test.cpp | 2 +- src/test/csf/CollectorRef.h | 2 +- src/test/csf/Histogram.h | 2 +- src/test/jtx/TestHelpers.h | 2 +- src/test/jtx/deposit.h | 2 +- src/test/jtx/rpc.h | 2 +- src/test/protocol/Seed_test.cpp | 2 +- src/test/rpc/AccountObjects_test.cpp | 2 +- src/test/rpc/ManifestRPC_test.cpp | 2 +- src/test/rpc/Subscribe_test.cpp | 2 +- src/tests/libxrpl/basics/base64.cpp | 2 + src/xrpld/app/consensus/RCLConsensus.h | 2 +- .../app/ledger/AbstractFetchPackContainer.h | 2 +- src/xrpld/app/ledger/BookListeners.cpp | 2 +- src/xrpld/app/ledger/README.md | 2 +- src/xrpld/app/main/GRPCServer.cpp | 2 +- src/xrpld/app/main/GRPCServer.h | 2 +- src/xrpld/app/misc/FeeEscalation.md | 4 +- src/xrpld/app/misc/HashRouter.cpp | 2 +- src/xrpld/app/misc/HashRouter.h | 2 +- src/xrpld/app/misc/Manifest.h | 2 +- src/xrpld/app/misc/NetworkOPs.cpp | 14 +- src/xrpld/app/misc/NetworkOPs.h | 6 +- src/xrpld/app/misc/SHAMapStoreImp.cpp | 2 +- src/xrpld/app/misc/Transaction.h | 2 +- src/xrpld/app/misc/TxQ.h | 2 +- src/xrpld/app/misc/detail/LendingHelpers.cpp | 2 +- src/xrpld/app/paths/Pathfinder.cpp | 4 +- src/xrpld/app/paths/detail/DirectStep.cpp | 2 +- src/xrpld/app/rdb/backend/detail/Node.h | 14 +- src/xrpld/app/tx/detail/CreateOffer.cpp | 4 +- src/xrpld/app/tx/detail/InvariantCheck.h | 2 +- src/xrpld/app/tx/detail/NFTokenUtils.cpp | 2 +- src/xrpld/app/tx/detail/Payment.cpp | 4 +- src/xrpld/conditions/detail/PreimageSha256.h | 2 +- src/xrpld/consensus/Consensus.cpp | 2 +- src/xrpld/core/Config.h | 2 +- src/xrpld/core/detail/SociDB.cpp | 2 +- src/xrpld/overlay/detail/PeerImp.cpp | 2 +- src/xrpld/peerfinder/PeerfinderManager.h | 2 +- src/xrpld/peerfinder/README.md | 14 +- src/xrpld/peerfinder/detail/Checker.h | 2 +- src/xrpld/peerfinder/detail/Fixed.h | 2 +- src/xrpld/rpc/GRPCHandlers.h | 2 +- src/xrpld/rpc/detail/Handler.cpp | 2 +- src/xrpld/rpc/detail/InfoSub.cpp | 6 +- src/xrpld/rpc/detail/RPCCall.cpp | 2 +- src/xrpld/rpc/detail/RPCSub.cpp | 2 +- src/xrpld/rpc/detail/TransactionSign.cpp | 4 +- src/xrpld/rpc/handlers/GatewayBalances.cpp | 2 +- src/xrpld/rpc/handlers/NoRippleCheck.cpp | 2 +- 107 files changed, 473 insertions(+), 182 deletions(-) create mode 100644 .config/cspell.config.yaml diff --git a/.config/cspell.config.yaml b/.config/cspell.config.yaml new file mode 100644 index 0000000000..969720a11d --- /dev/null +++ b/.config/cspell.config.yaml @@ -0,0 +1,272 @@ +ignorePaths: + - build/** + - src/libxrpl/crypto + - src/test/** # Will be removed in the future + - CMakeUserPresets.json + - Doxyfile + - docs/**/*.puml + - cmake/** + - LICENSE.md +language: en +allowCompoundWords: true +ignoreRandomStrings: true +minWordLength: 5 +dictionaries: + - cpp + - en_US + - en_GB +ignoreRegExpList: + - /[rs][1-9A-HJ-NP-Za-km-z]{25,34}/g # addresses and seeds + - /(XRPL|BEAST)_[A-Z_0-9]+_H_INCLUDED+/g # include guards + - /(XRPL|BEAST)_[A-Z_0-9]+_H+/g # include guards + - /::[a-z:_]+/g # things from other namespaces + - /lib[a-z]+/g # libraries + - /[0-9]{4}-[0-9]{2}-[0-9]{2}[,:][A-Za-zÀ-ÖØ-öø-ÿ.\s]+/g # copyright dates + - /[0-9]{4}[,:]?\s*[A-Za-zÀ-ÖØ-öø-ÿ.\s]+/g # copyright years + - /\[[A-Za-z0-9-]+\]\(https:\/\/github.com\/[A-Za-z0-9-]+\)/g # Github usernames + - /-[DWw][a-zA-Z0-9_-]+=/g # compile flags + - /[\['"`]-[DWw][a-zA-Z0-9_-]+['"`\]]/g # compile flags +suggestWords: + - xprl->xrpl + - unsynched->unsynced + - synched->synced + - synch->sync +words: + - abempty + - AMMID + - amt + - amts + - asnode + - asynchrony + - attestation + - authorises + - autobridge + - autobridged + - autobridging + - bimap + - bindir + - bookdir + - Bougalis + - Britto + - Btrfs + - canonicality + - checkme + - chrono + - citardauq + - clawback + - clawbacks + - coeffs + - coldwallet + - compr + - conanfile + - conanrun + - connectability + - coro + - coros + - cowid + - cryptocondition + - cryptoconditional + - cryptoconditions + - csprng + - ctid + - currenttxhash + - daria + - dcmake + - dearmor + - deleteme + - demultiplexer + - deserializaton + - desync + - desynced + - determ + - distro + - doxyfile + - dxrpl + - endmacro + - endpointv + - exceptioned + - Falco + - finalizers + - firewalled + - fmtdur + - funclets + - gcov + - gcovr + - Gnutella + - gpgcheck + - gpgkey + - hotwallet + - ifndef + - inequation + - insuf + - insuff + - iou + - ious + - isrdc + - jemalloc + - jlog + - keylet + - keylets + - keyvadb + - ledgerentry + - ledgerhash + - ledgerindex + - leftw + - legleux + - levelization + - levelized + - libpb + - libxrpl + - llection + - LOCALGOOD + - logwstream + - lseq + - lsmf + - ltype + - MEMORYSTATUSEX + - Merkle + - Metafuncton + - misprediction + - mptbalance + - mptflags + - mptid + - mptissuance + - mptissuanceid + - mptoken + - mptokenid + - mptokenissuance + - mptokens + - mpts + - multisig + - multisign + - multisigned + - Nakamoto + - nftid + - nftoffer + - nftoken + - nftokenid + - nftokenpages + - nftokens + - nftpage + - nikb + - nonxrp + - noripple + - nudb + - nullptr + - nunl + - Nyffenegger + - ostr + - partitioner + - paychan + - paychans + - permdex + - perminute + - permissioned + - pointee + - preauth + - preauthorization + - preauthorize + - preauthorizes + - preclaim + - protobuf + - protos + - ptrs + - pyenv + - qalloc + - queuable + - Raphson + - replayer + - rerere + - retriable + - RIPD + - ripdtop + - rippleci + - rippled + - ripplerpc + - rippletest + - RLUSD + - rngfill + - rocksdb + - Rohrs + - roundings + - sahyadri + - Satoshi + - secp + - sendq + - seqit + - sf + - shamap + - shamapitem + - sidechain + - SIGGOOD + - sle + - sles + - soci + - socidb + - sslws + - statsd + - STATSDCOLLECTOR + - stissue + - stnum + - stobj + - stobject + - stpath + - stpathset + - sttx + - stvar + - stvector + - stxchainattestations + - superpeer + - superpeers + - takergets + - takerpays + - ters + - tx + - txid + - txids + - txjson + - txn + - txns + - txs + - umant + - unacquired + - unambiguity + - unauthorizes + - unauthorizing + - unergonomic + - unfetched + - unflatten + - unfund + - unimpair + - unroutable + - unscalable + - unserviced + - unshareable + - unshares + - unsquelch + - unsquelched + - unsquelching + - unvalidated + - unveto + - unvetoed + - upvotes + - USDB + - variadics + - venv + - vfalco + - vinnie + - wextra + - wptr + - writeme + - wsrch + - wthread + - xbridge + - xchain + - ximinez + - XMACRO + - xrpkuwait + - xrpl + - xrpld + - xrplf + - xxhash + - xxhasher diff --git a/.github/scripts/levelization/README.md b/.github/scripts/levelization/README.md index 3b77a192b9..c8954b900e 100644 --- a/.github/scripts/levelization/README.md +++ b/.github/scripts/levelization/README.md @@ -81,7 +81,7 @@ It generates many files of [results](results): - `rawincludes.txt`: The raw dump of the `#includes` - `paths.txt`: A second dump grouping the source module - to the destination module, deduped, and with frequency counts. + to the destination module, de-duped, and with frequency counts. - `includes/`: A directory where each file represents a module and contains a list of modules and counts that the module _includes_. - `includedby/`: Similar to `includes/`, but the other way around. Each diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c85e0798f7..4a1dc159dc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,6 +36,21 @@ repos: hooks: - id: black + # - repo: https://github.com/streetsidesoftware/cspell-cli + # rev: v9.2.0 + # hooks: + # - id: cspell # Spell check changed files + # - id: cspell # Spell check the commit message + # name: check commit message spelling + # args: + # - --no-must-find-files + # - --no-progress + # - --no-summary + # - --files + # - .git/COMMIT_EDITMSG + # stages: [commit-msg] + # always_run: true # This might not be necessary. + exclude: | (?x)^( external/.*| diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5b578b7f13..4f99972713 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -555,16 +555,16 @@ Rippled uses a linear workflow model that can be summarized as: git fetch --multiple upstreams user1 user2 user3 [...] git checkout -B release-next --no-track upstream/develop -# Only do an ff-only merge if prbranch1 is either already +# Only do an ff-only merge if pr-branch1 is either already # squashed, or needs to be merged with separate commits, # and has no merge commits. -# Use -S on the ff-only merge if prbranch1 isn't signed. -git merge [-S] --ff-only user1/prbranch1 +# Use -S on the ff-only merge if pr-branch1 isn't signed. +git merge [-S] --ff-only user1/pr-branch1 -git merge --squash user2/prbranch2 +git merge --squash user2/pr-branch2 git commit -S # Use the commit message provided on the PR -git merge --squash user3/prbranch3 +git merge --squash user3/pr-branch3 git commit -S # Use the commit message provided on the PR [...] @@ -876,7 +876,7 @@ git push --delete upstream-push master-next #### Special cases: point releases, hotfixes, etc. -On occassion, a bug or issue is discovered in a version that already +On occasion, a bug or issue is discovered in a version that already had a final release. Most of the time, development will have started on the next version, and will usually have changes in `develop` and often in `release`. diff --git a/SECURITY.md b/SECURITY.md index 3fd85bad0a..18eec312ed 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -42,7 +42,7 @@ For more information on responsible disclosure, please read this [Wikipedia arti ## Report Handling Process -Please report the bug directly to us and limit further disclosure. If you want to prove that you knew the bug as of a given time, consider using a cryptographic precommitment: hash the content of your report and publish the hash on a medium of your choice (e.g. on Twitter or as a memo in a transaction) as "proof" that you had written the text at a given point in time. +Please report the bug directly to us and limit further disclosure. If you want to prove that you knew the bug as of a given time, consider using a cryptographic pre-commitment: hash the content of your report and publish the hash on a medium of your choice (e.g. on Twitter or as a memo in a transaction) as "proof" that you had written the text at a given point in time. Once we receive a report, we: diff --git a/cfg/xrpld-example.cfg b/cfg/xrpld-example.cfg index b5180dce52..93fab4a9ba 100644 --- a/cfg/xrpld-example.cfg +++ b/cfg/xrpld-example.cfg @@ -218,7 +218,7 @@ # administrative commands. # # NOTE A common configuration value for the admin field is "localhost". -# If you are listening on all IPv4/IPv6 addresses by specifing +# If you are listening on all IPv4/IPv6 addresses by specifying # ip = :: then you can use admin = ::ffff:127.0.0.1,::1 to allow # administrative access from both IPv4 and IPv6 localhost # connections. diff --git a/cmake/XrplCore.cmake b/cmake/XrplCore.cmake index 12ba58d499..0689fbe7b6 100644 --- a/cmake/XrplCore.cmake +++ b/cmake/XrplCore.cmake @@ -206,7 +206,7 @@ if(xrpld) ) exclude_if_included(xrpld) # define a macro for tests that might need to - # be exluded or run differently in CI environment + # be excluded or run differently in CI environment if(is_ci) target_compile_definitions(xrpld PRIVATE XRPL_RUNNING_IN_CI) endif () diff --git a/docs/0001-negative-unl/README.md b/docs/0001-negative-unl/README.md index f28ff63c6f..c863cab9da 100644 --- a/docs/0001-negative-unl/README.md +++ b/docs/0001-negative-unl/README.md @@ -134,7 +134,7 @@ validation messages (_PAV_) received from each validator on the node's UNL. Note that the node will only count the validation messages that agree with its own validations. -We define the **PAV** as the **P**ercentage of **A**greed **V**alidation +We define the **PAV** as the Percentage of Agreed Validation messages received for the last N ledgers, where N = 256 by default. When the PAV drops below the **_low-water mark_**, the validator is considered diff --git a/docs/0001-negative-unl/negativeUNLSqDiagram.puml b/docs/0001-negative-unl/negativeUNLSqDiagram.puml index 9f37d43903..d86b98c01f 100644 --- a/docs/0001-negative-unl/negativeUNLSqDiagram.puml +++ b/docs/0001-negative-unl/negativeUNLSqDiagram.puml @@ -43,14 +43,14 @@ alt phase == OPEN alt sqn%256==0 CA -[#green]> RM: getValidations CA -[#green]> CA: create UNLModify Tx - hnote over CA#lightgreen: use validatations of the last 256 ledgers\nto figure out UNLModify Tx candidates.\nIf any, create UNLModify Tx, and add to TxSet. + hnote over CA#lightgreen: use validations of the last 256 ledgers\nto figure out UNLModify Tx candidates.\nIf any, create UNLModify Tx, and add to TxSet. end CA -> GC GC -> CA: propose deactivate CA end else phase == ESTABLISH - hnote over GC: receive peer postions + hnote over GC: receive peer positions GC -> GC : update our position GC -> CA : propose \n(if position changed) GC -> GC : check if have consensus diff --git a/docs/consensus.md b/docs/consensus.md index 067e15d0c8..23e5e7d5be 100644 --- a/docs/consensus.md +++ b/docs/consensus.md @@ -189,7 +189,7 @@ validations. It checks this on every call to `timerEntry`. - _Wrong Ledger_ indicates the node is not working on the correct prior ledger and does not have it available. It requests that ledger from the network, but continues to work towards consensus this round while waiting. If it had been - _proposing_, it will send a special "bowout" proposal to its peers to indicate + _proposing_, it will send a special "bow-out" proposal to its peers to indicate its change in mode for the rest of this round. For the duration of the round, it defers to peer positions for determining the consensus outcome as if it were just _observing_. @@ -515,7 +515,7 @@ are excerpts of the generic consensus implementation and of helper types that wi interact with the concrete implementing class. ```{.cpp} -// Represents a transction under dispute this round +// Represents a transaction under dispute this round template class DisputedTx; // Represents how the node participates in Consensus this round diff --git a/include/xrpl/basics/IntrusiveRefCounts.h b/include/xrpl/basics/IntrusiveRefCounts.h index 630c08395d..440ecdd19c 100644 --- a/include/xrpl/basics/IntrusiveRefCounts.h +++ b/include/xrpl/basics/IntrusiveRefCounts.h @@ -301,7 +301,7 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const // change the counts and flags (the count could be atomically changed, but // the flags depend on the current value of the counts). // - // Note: If this becomes a perf bottleneck, the `partialDestoryStartedMask` + // Note: If this becomes a perf bottleneck, the `partialDestroyStartedMask` // may be able to be set non-atomically. But it is easier to reason about // the code if the flag is set atomically. while (1) diff --git a/include/xrpl/basics/Log.h b/include/xrpl/basics/Log.h index 9443e8afdf..f10f1ff64c 100644 --- a/include/xrpl/basics/Log.h +++ b/include/xrpl/basics/Log.h @@ -221,7 +221,8 @@ public: private: enum { // Maximum line length for log messages. - // If the message exceeds this length it will be truncated with elipses. + // If the message exceeds this length it will be truncated with + // ellipses. maximumMessageCharacters = 12 * 1024 }; diff --git a/include/xrpl/beast/core/LexicalCast.h b/include/xrpl/beast/core/LexicalCast.h index fea1c35f55..c5b7f5540a 100644 --- a/include/xrpl/beast/core/LexicalCast.h +++ b/include/xrpl/beast/core/LexicalCast.h @@ -18,7 +18,7 @@ namespace beast { namespace detail { -// These specializatons get called by the non-member functions to do the work +// These specializations get called by the non-member functions to do the work template struct LexicalCast; diff --git a/include/xrpl/json/json_reader.h b/include/xrpl/json/json_reader.h index a660d82e2a..963dc0f26e 100644 --- a/include/xrpl/json/json_reader.h +++ b/include/xrpl/json/json_reader.h @@ -1,8 +1,6 @@ #ifndef XRPL_JSON_JSON_READER_H_INCLUDED #define XRPL_JSON_JSON_READER_H_INCLUDED -#define CPPTL_JSON_READER_H_INCLUDED - #include #include @@ -231,4 +229,4 @@ operator>>(std::istream&, Value&); } // namespace Json -#endif // CPPTL_JSON_READER_H_INCLUDED +#endif // XRPL_JSON_JSON_READER_H_INCLUDED diff --git a/include/xrpl/json/json_value.h b/include/xrpl/json/json_value.h index 2e38f2e75e..3daf441592 100644 --- a/include/xrpl/json/json_value.h +++ b/include/xrpl/json/json_value.h @@ -682,4 +682,4 @@ public: } // namespace Json -#endif // CPPTL_JSON_H_INCLUDED +#endif // XRPL_JSON_JSON_VALUE_H_INCLUDED diff --git a/include/xrpl/ledger/CredentialHelpers.h b/include/xrpl/ledger/CredentialHelpers.h index 52ddfe33aa..b90aa44c0d 100644 --- a/include/xrpl/ledger/CredentialHelpers.h +++ b/include/xrpl/ledger/CredentialHelpers.h @@ -15,7 +15,7 @@ namespace xrpl { namespace credentials { // These function will be used by the code that use DepositPreauth / Credentials -// (and any future preauthorization modes) as part of authorization (all the +// (and any future pre-authorization modes) as part of authorization (all the // transfer funds transactions) // Check if credential sfExpiration field has passed ledger's parentCloseTime @@ -41,7 +41,8 @@ checkFields(STTx const& tx, beast::Journal j); // Accessing the ledger to check if provided credentials are valid. Do not use // in doApply (only in preclaim) since it does not remove expired credentials. -// If you call it in prelaim, you also must call verifyDepositPreauth in doApply +// If you call it in preclaim, you also must call verifyDepositPreauth in +// doApply TER valid( STTx const& tx, diff --git a/include/xrpl/nodestore/DummyScheduler.h b/include/xrpl/nodestore/DummyScheduler.h index 9ffe5ad80d..b31613480f 100644 --- a/include/xrpl/nodestore/DummyScheduler.h +++ b/include/xrpl/nodestore/DummyScheduler.h @@ -6,7 +6,7 @@ namespace xrpl { namespace NodeStore { -/** Simple NodeStore Scheduler that just peforms the tasks synchronously. */ +/** Simple NodeStore Scheduler that just performs the tasks synchronously. */ class DummyScheduler : public Scheduler { public: diff --git a/include/xrpl/nodestore/README.md b/include/xrpl/nodestore/README.md index 83da29d9ce..4b228bfc9a 100644 --- a/include/xrpl/nodestore/README.md +++ b/include/xrpl/nodestore/README.md @@ -96,7 +96,7 @@ Facebook's RocksDB database, builds on LevelDB. Use SQLite. -'path' speficies where the backend will store its data files. +'path' specifies where the backend will store its data files. Choices for 'compression' @@ -161,7 +161,7 @@ Through various executions and profiling some conclusions are presented below. - Multiple runs of the benchmarks can yield surprisingly different results. This can perhaps be attributed to the asynchronous nature of rocksdb's compaction - process. The benchmarks are artifical and create highly unlikely write load to + process. The benchmarks are artificial and create highly unlikely write load to create the dataset to measure different read access patterns. Therefore multiple runs of the benchmarks are required to get a feel for the effectiveness of the changes. This contrasts sharply with the keyvadb benchmarking were highly diff --git a/include/xrpl/proto/org/xrpl/rpc/v1/xrp_ledger.proto b/include/xrpl/proto/org/xrpl/rpc/v1/xrp_ledger.proto index 2b8dc471ce..942a4a2135 100644 --- a/include/xrpl/proto/org/xrpl/rpc/v1/xrp_ledger.proto +++ b/include/xrpl/proto/org/xrpl/rpc/v1/xrp_ledger.proto @@ -9,7 +9,7 @@ import "org/xrpl/rpc/v1/get_ledger_entry.proto"; import "org/xrpl/rpc/v1/get_ledger_data.proto"; import "org/xrpl/rpc/v1/get_ledger_diff.proto"; -// These methods are binary only methods for retrieiving arbitrary ledger state +// These methods are binary only methods for retrieving arbitrary ledger state // via gRPC. These methods are used by clio, but can also be // used by any client that wants to extract ledger state in an efficient manner. // They do not directly mimic the JSON equivalent methods. diff --git a/include/xrpl/protocol/Indexes.h b/include/xrpl/protocol/Indexes.h index 1cb22b4d6c..777c3b8aa9 100644 --- a/include/xrpl/protocol/Indexes.h +++ b/include/xrpl/protocol/Indexes.h @@ -18,7 +18,7 @@ namespace xrpl { class SeqProxy; -/** Keylet computation funclets. +/** Keylet computation functions. Entries in the ledger are located using 256-bit locators. The locators are calculated using a wide range of parameters specific to the entry whose diff --git a/include/xrpl/protocol/Protocol.h b/include/xrpl/protocol/Protocol.h index fb315eace4..0c72b80de4 100644 --- a/include/xrpl/protocol/Protocol.h +++ b/include/xrpl/protocol/Protocol.h @@ -179,7 +179,7 @@ static constexpr int loanPaymentsPerFeeIncrement = 5; * * This limit is enforced during the loan payment process, and thus is not * estimated. If the limit is hit, no further payments or overpayments will be - * processed, no matter how much of the transation Amount is left, but the + * processed, no matter how much of the transaction Amount is left, but the * transaction will succeed with the payments that have been processed up to * that point. * diff --git a/include/xrpl/protocol/Quality.h b/include/xrpl/protocol/Quality.h index 1fafa5e321..83a038490a 100644 --- a/include/xrpl/protocol/Quality.h +++ b/include/xrpl/protocol/Quality.h @@ -210,7 +210,7 @@ public: private: // The ceil_in and ceil_out methods that deal in TAmount all convert - // their arguments to STAoumout and convert the result back to TAmount. + // their arguments to STAmount and convert the result back to TAmount. // This helper function takes care of all the conversion operations. template < class In, diff --git a/include/xrpl/protocol/TxFlags.h b/include/xrpl/protocol/TxFlags.h index 194c4c6af1..5527a264e4 100644 --- a/include/xrpl/protocol/TxFlags.h +++ b/include/xrpl/protocol/TxFlags.h @@ -277,7 +277,7 @@ constexpr std::uint32_t const tfLoanOverpayment = 0x00010000; // interest and fees, or it will fail. False: Not a full payment. constexpr std::uint32_t const tfLoanFullPayment = 0x00020000; // tfLoanLatePayment: True, indicates that the payment is late, -// and includes late iterest and fees. If the loan is not late, +// and includes late interest and fees. If the loan is not late, // it will fail. False: not a late payment. If the current payment // is overdue, the transaction will fail. constexpr std::uint32_t const tfLoanLatePayment = 0x00040000; diff --git a/include/xrpl/protocol/XChainAttestations.h b/include/xrpl/protocol/XChainAttestations.h index 4dc9cfcf6a..bd76936b49 100644 --- a/include/xrpl/protocol/XChainAttestations.h +++ b/include/xrpl/protocol/XChainAttestations.h @@ -33,12 +33,12 @@ struct AttestationBase // Account on the sending chain that triggered the event (sent the // transaction) AccountID sendingAccount; - // Amount transfered on the sending chain + // Amount transferred on the sending chain STAmount sendingAmount; // Account on the destination chain that collects a share of the attestation // reward AccountID rewardAccount; - // Amount was transfered on the locking chain + // Amount was transferred on the locking chain bool wasLockingChainSend; explicit AttestationBase( @@ -354,7 +354,7 @@ struct XChainCreateAccountAttestation XChainCreateAccountAttestation const& rhs); }; -// Attestations from witness servers for a particular claimid and bridge. +// Attestations from witness servers for a particular claim ID and bridge. // Only one attestation per signature is allowed. template class XChainAttestationsBase diff --git a/include/xrpl/protocol/detail/STVar.h b/include/xrpl/protocol/detail/STVar.h index 540ba2bf77..219d1ed738 100644 --- a/include/xrpl/protocol/detail/STVar.h +++ b/include/xrpl/protocol/detail/STVar.h @@ -42,7 +42,7 @@ concept ValidConstructSTArgs = class STVar { private: - // The largest "small object" we can accomodate + // The largest "small object" we can accommodate static std::size_t constexpr max_size = 72; std::aligned_storage::type d_; diff --git a/include/xrpl/protocol/detail/ledger_entries.macro b/include/xrpl/protocol/detail/ledger_entries.macro index 1034c35895..de9c41bf52 100644 --- a/include/xrpl/protocol/detail/ledger_entries.macro +++ b/include/xrpl/protocol/detail/ledger_entries.macro @@ -237,7 +237,7 @@ LEDGER_ENTRY(ltOFFER, 0x006f, Offer, offer, ({ {sfAdditionalBooks, soeOPTIONAL}, })) -/** A ledger object which describes a deposit preauthorization. +/** A ledger object which describes a deposit pre-authorization. \sa keylet::depositPreauth */ @@ -577,7 +577,7 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({ // - TrueTotalLoanValue = PaymentRemaining * PeriodicPayment // The unrounded true total value of the loan. // - // - TrueTotalPrincialOutstanding can be computed using the algorithm + // - TrueTotalPrincipalOutstanding can be computed using the algorithm // in the ripple::detail::loanPrincipalFromPeriodicPayment function. // // - TrueTotalInterestOutstanding = TrueTotalLoanValue - diff --git a/include/xrpl/resource/README.md b/include/xrpl/resource/README.md index 253e3c7625..e525ce83e3 100644 --- a/include/xrpl/resource/README.md +++ b/include/xrpl/resource/README.md @@ -66,7 +66,7 @@ values over time: this is implemented by the DecayingSample class. Each server in a cluster creates a list of IP addresses of end points that are imposing a significant load. This list is called Gossip, which is passed to other nodes in that cluster. Gossip helps individual -servers in the cluster identify IP addreses that might be unduly loading +servers in the cluster identify IP addresses that might be unduly loading the entire cluster. Again the recourse of the individual servers is to drop connections to those IP addresses that occur commonly in the gossip. diff --git a/include/xrpl/resource/detail/Logic.h b/include/xrpl/resource/detail/Logic.h index b1f90e0282..5bcfa42f31 100644 --- a/include/xrpl/resource/detail/Logic.h +++ b/include/xrpl/resource/detail/Logic.h @@ -61,7 +61,7 @@ private: // List of all active admin entries EntryIntrusiveList admin_; - // List of all inactve entries + // List of all inactive entries EntryIntrusiveList inactive_; // All imported gossip data diff --git a/include/xrpl/server/detail/LowestLayer.h b/include/xrpl/server/detail/LowestLayer.h index 57647867e3..c45d948241 100644 --- a/include/xrpl/server/detail/LowestLayer.h +++ b/include/xrpl/server/detail/LowestLayer.h @@ -9,7 +9,7 @@ namespace xrpl { -// Before boost 1.70, get_lowest_layer required an explicit templat parameter +// Before boost 1.70, get_lowest_layer required an explicit template parameter template decltype(auto) get_lowest_layer(T& t) noexcept diff --git a/include/xrpl/shamap/README.md b/include/xrpl/shamap/README.md index 3bff74e67b..419918c0cb 100644 --- a/include/xrpl/shamap/README.md +++ b/include/xrpl/shamap/README.md @@ -226,7 +226,7 @@ The `fetchNodeNT()` method goes through three phases: Any SHAMapLeafNode that is immutable has a sequence number of zero (sharable). When a mutable `SHAMap` is created then its SHAMapTreeNodes are - given non-zero sequence numbers (unsharable). But all nodes in the + given non-zero sequence numbers (unshareable). But all nodes in the TreeNodeCache are immutable, so if one is found here, its sequence number will be 0. diff --git a/include/xrpl/shamap/SHAMapItem.h b/include/xrpl/shamap/SHAMapItem.h index a69f40113d..e8d95b0684 100644 --- a/include/xrpl/shamap/SHAMapItem.h +++ b/include/xrpl/shamap/SHAMapItem.h @@ -125,13 +125,13 @@ intrusive_ptr_release(SHAMapItem const* x) { auto p = reinterpret_cast(x); - // The SHAMapItem constuctor isn't trivial (because the destructor + // The SHAMapItem constructor isn't trivial (because the destructor // for CountedObject isn't) so we can't avoid calling it here, but // plan for a future where we might not need to. if constexpr (!std::is_trivially_destructible_v) std::destroy_at(x); - // If the slabber doens't claim this pointer, it was allocated + // If the slabber doesn't claim this pointer, it was allocated // manually, so we free it manually. if (!detail::slabber.deallocate(const_cast(p))) delete[] p; diff --git a/src/libxrpl/basics/Number.cpp b/src/libxrpl/basics/Number.cpp index 96c13c9db8..9984b26ffe 100644 --- a/src/libxrpl/basics/Number.cpp +++ b/src/libxrpl/basics/Number.cpp @@ -38,8 +38,8 @@ Number::setround(rounding_mode mode) // Guard -// The Guard class is used to tempoarily add extra digits of -// preicision to an operation. This enables the final result +// The Guard class is used to temporarily add extra digits of +// precision to an operation. This enables the final result // to be correctly rounded to the internal precision of Number. class Number::Guard diff --git a/src/libxrpl/basics/make_SSLContext.cpp b/src/libxrpl/basics/make_SSLContext.cpp index 579edb0f71..ef5996e051 100644 --- a/src/libxrpl/basics/make_SSLContext.cpp +++ b/src/libxrpl/basics/make_SSLContext.cpp @@ -28,7 +28,7 @@ namespace xrpl { namespace openssl { namespace detail { -/** The default strength of self-signed RSA certifices. +/** The default strength of self-signed RSA certificates. Per NIST Special Publication 800-57 Part 3, 2048-bit RSA is still considered acceptably secure. Generally, we would want to go above @@ -131,7 +131,7 @@ initAnonymous(boost::asio::ssl::context& context) LogicError("X509_new failed"); // According to the standards (X.509 et al), the value should be one - // less than the actualy certificate version we want. Since we want + // less than the actually certificate version we want. Since we want // version 3, we must use a 2. X509_set_version(x509, 2); diff --git a/src/libxrpl/json/Writer.cpp b/src/libxrpl/json/Writer.cpp index fcdceb7253..6da29211ca 100644 --- a/src/libxrpl/json/Writer.cpp +++ b/src/libxrpl/json/Writer.cpp @@ -193,7 +193,7 @@ public: } private: - // JSON collections are either arrrays, or objects. + // JSON collections are either arrays, or objects. struct Collection { explicit Collection() = default; diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index c817a85b65..329d3cfcae 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -3244,7 +3244,7 @@ enforceMPTokenAuthorization( auto const maybeDomainID = sleIssuance->at(~sfDomainID); bool expired = false; bool const authorizedByDomain = [&]() -> bool { - // NOTE: defensive here, shuld be checked in preclaim + // NOTE: defensive here, should be checked in preclaim if (!maybeDomainID.has_value()) return false; // LCOV_EXCL_LINE diff --git a/src/libxrpl/protocol/IOUAmount.cpp b/src/libxrpl/protocol/IOUAmount.cpp index 01283886e1..5c9ab1febc 100644 --- a/src/libxrpl/protocol/IOUAmount.cpp +++ b/src/libxrpl/protocol/IOUAmount.cpp @@ -18,7 +18,7 @@ namespace xrpl { namespace { -// Use a static inside a function to help prevent order-of-initialzation issues +// Use a static inside a function to help prevent order-of-initialization issues LocalValue& getStaticSTNumberSwitchover() { diff --git a/src/libxrpl/protocol/STAmount.cpp b/src/libxrpl/protocol/STAmount.cpp index 824453a4d3..ebccfb3e64 100644 --- a/src/libxrpl/protocol/STAmount.cpp +++ b/src/libxrpl/protocol/STAmount.cpp @@ -662,7 +662,7 @@ STAmount::getFullText() const std::string STAmount::getText() const { - // keep full internal accuracy, but make more human friendly if posible + // keep full internal accuracy, but make more human friendly if possible if (*this == beast::zero) return "0"; diff --git a/src/libxrpl/protocol/tokens.cpp b/src/libxrpl/protocol/tokens.cpp index d4253a2df1..420eb56df0 100644 --- a/src/libxrpl/protocol/tokens.cpp +++ b/src/libxrpl/protocol/tokens.cpp @@ -649,7 +649,7 @@ encodeBase58Token( return detail::b256_to_b58_be(b58Span, out); } // Convert from base 58 to base 256, largest coefficients first -// The input is encoded in XPRL format, with the token in the first +// The input is encoded in XRPL format, with the token in the first // byte and the checksum in the last four bytes. // The decoded base 256 value does not include the token type or checksum. // It is an error if the token type or checksum does not match. diff --git a/src/test/app/AccountDelete_test.cpp b/src/test/app/AccountDelete_test.cpp index 749ed33e28..44d484ac7a 100644 --- a/src/test/app/AccountDelete_test.cpp +++ b/src/test/app/AccountDelete_test.cpp @@ -103,7 +103,7 @@ public: env(trust(becky, gw["USD"](1000))); env.close(); - // Give carol a deposit preauthorization, an offer, a ticket, + // Give carol a deposit pre-authorization, an offer, a ticket, // a signer list, and a DID. Even with all that she's still deletable. env(deposit::auth(carol, becky)); std::uint32_t const carolOfferSeq{env.seq(carol)}; @@ -176,7 +176,7 @@ public: auto const carolOldBalance{env.balance(carol)}; // Verify that Carol's account, directory, deposit - // preauthorization, offer, ticket, and signer list exist. + // pre-authorization, offer, ticket, and signer list exist. BEAST_EXPECT(env.closed()->exists(keylet::account(carol.id()))); BEAST_EXPECT(env.closed()->exists(keylet::ownerDir(carol.id()))); BEAST_EXPECT(env.closed()->exists( @@ -886,7 +886,7 @@ public: env, eaton, carol, credType)[jss::result][jss::index] .asString(); - // fred make preauthorization through authorized account + // fred make pre-authorization through authorized account env(fset(fred, asfDepositAuth)); env.close(); env(deposit::auth(fred, eaton)); diff --git a/src/test/app/AmendmentTable_test.cpp b/src/test/app/AmendmentTable_test.cpp index 9add892073..a320bccfe8 100644 --- a/src/test/app/AmendmentTable_test.cpp +++ b/src/test/app/AmendmentTable_test.cpp @@ -506,7 +506,7 @@ public: // Parameters: // table: Our table of known and vetoed amendments - // validators: The addreses of validators we trust + // validators: The addresses of validators we trust // votes: Amendments and the number of validators who vote for them // ourVotes: The amendments we vote for in our validation // enabled: In/out enabled amendments diff --git a/src/test/app/DepositAuth_test.cpp b/src/test/app/DepositAuth_test.cpp index 4235c8c9ca..775d7b1e81 100644 --- a/src/test/app/DepositAuth_test.cpp +++ b/src/test/app/DepositAuth_test.cpp @@ -15,7 +15,7 @@ reserve(jtx::Env& env, std::uint32_t count) return env.current()->fees().accountReserve(count); } -// Helper function that returns true if acct has the lsfDepostAuth flag set. +// Helper function that returns true if acct has the lsfDepositAuth flag set. static bool hasDepositAuth(jtx::Env const& env, jtx::Account const& acct) { @@ -512,7 +512,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env.require(owners(carol, 1)); env.require(owners(becky, 0)); - // But carol can't meet the reserve for another preauthorization. + // But carol can't meet the reserve for another pre-authorization. env(deposit::auth(carol, alice), ter(tecINSUFFICIENT_RESERVE)); env.close(); env.require(owners(carol, 1)); @@ -724,7 +724,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env.fund(XRP(5000), issuer, bob, alice); env.close(); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); @@ -737,7 +737,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env(deposit::auth(bob, alice)); env.close(); - // And alice can't pay with any credentials, amendement is not + // And alice can't pay with any credentials, amendment is not // enabled std::string const invalidIdx = "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E" @@ -765,11 +765,11 @@ struct DepositPreauth_test : public beast::unit_test::suite credentials::ledgerEntry(env, alice, issuer, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); - // Bob will accept payements from accounts with credentials signed + // Bob will accept payments from accounts with credentials signed // by 'issuer' env(deposit::authCredentials(bob, {{issuer, credType}})); env.close(); @@ -838,12 +838,12 @@ struct DepositPreauth_test : public beast::unit_test::suite std::string const credIdx = jv[jss::result][jss::index].asString(); { - // Success as destination didn't enable preauthorization so + // Success as destination didn't enable pre-authorization so // valid credentials will not fail env(pay(alice, bob, XRP(100)), credentials::ids({credIdx})); } - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); @@ -1141,7 +1141,7 @@ struct DepositPreauth_test : public beast::unit_test::suite jv = credentials::ledgerEntry(env, alice, issuer, credType2); std::string const credIdx2 = jv[jss::result][jss::index].asString(); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); // Bob setup DepositPreauth object @@ -1268,7 +1268,7 @@ struct DepositPreauth_test : public beast::unit_test::suite jv = credentials::ledgerEntry(env, zelda, issuer, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); // Bob setup DepositPreauth object diff --git a/src/test/app/Escrow_test.cpp b/src/test/app/Escrow_test.cpp index d4a9fc5b9d..25bb03858e 100644 --- a/src/test/app/Escrow_test.cpp +++ b/src/test/app/Escrow_test.cpp @@ -1553,7 +1553,7 @@ struct Escrow_test : public beast::unit_test::suite escrow::finish_time(env.now() + 50s)); env.close(); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); @@ -1635,7 +1635,7 @@ struct Escrow_test : public beast::unit_test::suite escrow::finish_time(env.now() + 1s)); env.close(); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); env(deposit::authCredentials(bob, {{zelda, credType}})); diff --git a/src/test/app/FixNFTokenPageLinks_test.cpp b/src/test/app/FixNFTokenPageLinks_test.cpp index baa33b2dc5..ad457cc58b 100644 --- a/src/test/app/FixNFTokenPageLinks_test.cpp +++ b/src/test/app/FixNFTokenPageLinks_test.cpp @@ -135,7 +135,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // Preflight { - // Fail preflight1. Can't combine AcccountTxnID and ticket. + // Fail preflight1. Can't combine AccountTxnID and ticket. Json::Value tx = ledgerStateFix::nftPageLinks(alice, alice); tx[sfAccountTxnID.jsonName] = "00000000000000000000000000000000" diff --git a/src/test/app/Invariants_test.cpp b/src/test/app/Invariants_test.cpp index 8eb3047dc8..61b4e7ba76 100644 --- a/src/test/app/Invariants_test.cpp +++ b/src/test/app/Invariants_test.cpp @@ -888,7 +888,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { - // mpissuance outstanding is negative + // mptissuance outstanding is negative auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; @@ -906,7 +906,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { - // mpissuance locked is less than locked + // mptissuance locked is less than locked auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; @@ -924,7 +924,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { - // mpissuance outstanding is less than locked + // mptissuance outstanding is less than locked auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; @@ -3179,7 +3179,7 @@ class Invariants_test : public beast::unit_test::suite sleShares->at(sfSequence) = sequence; // sleVault->at(sfAccount) = pseudoId; - // Setting wrong pseudo acocunt ID + // Setting wrong pseudo account ID sleVault->at(sfAccount) = A2.id(); sleVault->at(sfFlags) = 0; sleVault->at(sfSequence) = sequence; @@ -3222,7 +3222,7 @@ class Invariants_test : public beast::unit_test::suite sleShares->setFieldU64(sfOwnerNode, *sharesPage); sleShares->at(sfFlags) = 0; - // Setting wrong pseudo acocunt ID + // Setting wrong pseudo account ID sleShares->at(sfIssuer) = AccountID(uint160(42)); sleShares->at(sfOutstandingAmount) = 0; sleShares->at(sfSequence) = sequence; diff --git a/src/test/app/LoanBroker_test.cpp b/src/test/app/LoanBroker_test.cpp index 72a732d043..5915ebae91 100644 --- a/src/test/app/LoanBroker_test.cpp +++ b/src/test/app/LoanBroker_test.cpp @@ -974,7 +974,7 @@ class LoanBroker_test : public beast::unit_test::suite return coverWithdraw(alice, brokerKeylet.key, asset(10)); }); - // preclaim: tecWRONG_ASSSET + // preclaim: tecWRONG_ASSET env(coverWithdraw(alice, brokerKeylet.key, issuer["BAD"](10)), ter(tecWRONG_ASSET), THISLINE); diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index 1de142c2ab..62531f2b8f 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -115,7 +115,7 @@ class MPToken_test : public beast::unit_test::suite .metadata = "", .err = temMALFORMED}); - // MaximumAmout of 0 returns error + // MaximumAmount of 0 returns error mptAlice.create( {.maxAmt = 0, .assetScale = 1, @@ -400,7 +400,7 @@ class MPToken_test : public beast::unit_test::suite // a mptoken yet mptAlice.authorize({.holder = bob, .err = tecOBJECT_NOT_FOUND}); - // alice specifys a holder acct that doesn't exist + // alice specifies a holder acct that doesn't exist mptAlice.authorize({.holder = cindy, .err = tecNO_DST}); // bob now holds a mptoken object @@ -1805,7 +1805,7 @@ class MPToken_test : public beast::unit_test::suite // alice authorizes bob to hold funds mptAlice.authorize({.account = alice, .holder = bob}); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); @@ -1884,7 +1884,7 @@ class MPToken_test : public beast::unit_test::suite // alice authorizes bob to hold funds mptAlice.authorize({.account = alice, .holder = bob}); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); diff --git a/src/test/app/NFTokenBurn_test.cpp b/src/test/app/NFTokenBurn_test.cpp index 828539f4b1..a1c6ffb6de 100644 --- a/src/test/app/NFTokenBurn_test.cpp +++ b/src/test/app/NFTokenBurn_test.cpp @@ -165,7 +165,7 @@ class NFTokenBurn_test : public beast::unit_test::suite // prevent alice's and minter's NFTs from clustering together // in becky's directory. // - // Use a default initialized mercenne_twister because we want the + // Use a default initialized mersenne_twister because we want the // effect of random numbers, but we want the test to run the same // way each time. std::mt19937 engine; diff --git a/src/test/app/NFToken_test.cpp b/src/test/app/NFToken_test.cpp index 75bf59e70d..59995a4078 100644 --- a/src/test/app/NFToken_test.cpp +++ b/src/test/app/NFToken_test.cpp @@ -429,7 +429,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite if (replacement->getFieldU32(sfMintedNFTokens) != 1) return false; // Unexpected test conditions. - // Wequence number is generated by sfFirstNFTokenSequence + + // Sequence number is generated by sfFirstNFTokenSequence + // sfMintedNFTokens. We can replace the two fields with any // numbers as long as they add up to the largest valid number. // In our case, sfFirstNFTokenSequence is set to the largest @@ -1423,7 +1423,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // minter1 is no longer alice's minter, so no longer has - // permisson to burn alice's nfts. + // permission to burn alice's nfts. env(token::burn(minter1, burnableID), token::owner(buyer), ter(tecNO_PERMISSION)); @@ -2003,7 +2003,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, becky) == 1); BEAST_EXPECT(ownerCount(env, minter) == 0); - // Just for tidyness, becky burns the token before shutting + // Just for tidiness, becky burns the token before shutting // things down. env(token::burn(becky, nftAliceID)); env.close(); @@ -5853,7 +5853,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice tries to delete her account, but is unsuccessful. // Due to authorized minting, alice's account sequence does not // advance while minter mints NFTokens for her. - // The new account deletion retriction enabled by this amendment will enforce // alice to wait for more ledgers to close before she can // delete her account, to prevent duplicate NFTokenIDs @@ -5955,7 +5955,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice tries to delete her account, but is unsuccessful. // Due to authorized minting, alice's account sequence does not // advance while minter mints NFTokens for her using tickets. - // The new account deletion retriction enabled by this amendment will enforce // alice to wait for more ledgers to close before she can // delete her account, to prevent duplicate NFTokenIDs @@ -6061,7 +6061,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice tries to delete her account, but is unsuccessful. // Due to authorized minting, alice's account sequence does not // advance while minter mints NFTokens for her using tickets. - // The new account deletion retriction enabled by this amendment will enforce // alice to wait for more ledgers to close before she can delete her // account, to prevent duplicate NFTokenIDs @@ -6388,7 +6388,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // // The values of these fields are dependent on the NFTokenID/OfferID // changed in its corresponding transaction. We want to validate each - // transaction to make sure the synethic fields hold the right values. + // transaction to make sure the synthetic fields hold the right values. testcase("Test synthetic fields from JSON response"); diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index 20a433b5dd..ed8c3c507e 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -763,7 +763,7 @@ struct PayChan_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(bob) == preBob + delta - baseFee); } { - // Explore the limits of deposit preauthorization. + // Explore the limits of deposit pre-authorization. auto const delta = XRP(600).value(); auto const sig = signClaimAuth(pk, alice.sk(), chan, delta); @@ -799,7 +799,7 @@ struct PayChan_test : public beast::unit_test::suite env.balance(bob) == preBob + delta - (3 * baseFee)); } { - // bob removes preauthorization of alice. Once again she + // bob removes pre-authorization of alice. Once again she // cannot submit a claim. auto const delta = XRP(800).value(); @@ -874,7 +874,7 @@ struct PayChan_test : public beast::unit_test::suite credentials::ledgerEntry(env, alice, carol, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); - // Bob require preauthorization + // Bob require pre-authorization env(fset(bob, asfDepositAuth)); env.close(); diff --git a/src/test/app/PermissionedDEX_test.cpp b/src/test/app/PermissionedDEX_test.cpp index b5db131db6..c29b5344e2 100644 --- a/src/test/app/PermissionedDEX_test.cpp +++ b/src/test/app/PermissionedDEX_test.cpp @@ -1534,7 +1534,7 @@ public: { FeatureBitset const all{jtx::testable_amendments()}; - // Test domain offer (w/o hyrbid) + // Test domain offer (w/o hybrid) testOfferCreate(all); testPayment(all); testBookStep(all); diff --git a/src/test/app/ValidatorSite_test.cpp b/src/test/app/ValidatorSite_test.cpp index 71a5b7fa73..1118818d7a 100644 --- a/src/test/app/ValidatorSite_test.cpp +++ b/src/test/app/ValidatorSite_test.cpp @@ -422,7 +422,7 @@ public: 1, detail::default_expires, std::chrono::seconds{-90}}}); - // fetch single site with undending redirect (fails to load) + // fetch single site with unending redirect (fails to load) testFetchList( good, {{"/redirect_forever/301", @@ -443,7 +443,7 @@ public: ssl, true, true}}); - // one undending redirect, one not + // one unending redirect, one not testFetchList( good, {{"/validators", "", ssl}, @@ -452,7 +452,7 @@ public: ssl, true, true}}); - // one undending redirect, one not + // one unending redirect, one not testFetchList( good, {{"/validators2", "", ssl}, diff --git a/src/test/basics/IntrusiveShared_test.cpp b/src/test/basics/IntrusiveShared_test.cpp index d5d5d75048..b77325efa9 100644 --- a/src/test/basics/IntrusiveShared_test.cpp +++ b/src/test/basics/IntrusiveShared_test.cpp @@ -394,7 +394,7 @@ public: { // strong goes out of scope while weak is still in scope // This checks that partialDelete has run to completion - // before the desturctor is called. A sleep is inserted + // before the destructor is called. A sleep is inserted // inside the partial delete to make sure the destructor is // given an opportunity to run durring partial delete. BEAST_EXPECT(cur == partiallyDeleted); diff --git a/src/test/basics/XRPAmount_test.cpp b/src/test/basics/XRPAmount_test.cpp index da03a3533f..3f4e68de6e 100644 --- a/src/test/basics/XRPAmount_test.cpp +++ b/src/test/basics/XRPAmount_test.cpp @@ -218,7 +218,7 @@ public: // multiply and divide by values that would overflow if done // naively, and check that it gives the correct answer - big -= 0xf; // Subtract a little so it's divisable by 4 + big -= 0xf; // Subtract a little so it's divisible by 4 BEAST_EXPECT( mulRatio(big, 3, 4, false).value() == (big.value() / 4) * 3); BEAST_EXPECT( diff --git a/src/test/consensus/ByzantineFailureSim_test.cpp b/src/test/consensus/ByzantineFailureSim_test.cpp index 0a988f0473..210333e303 100644 --- a/src/test/consensus/ByzantineFailureSim_test.cpp +++ b/src/test/consensus/ByzantineFailureSim_test.cpp @@ -63,7 +63,7 @@ class ByzantineFailureSim_test : public beast::unit_test::suite { peer->submit(Tx{0}); // Peers 0,1,2,6 will close the next ledger differently by injecting - // a non-consensus approved transaciton + // a non-consensus approved transaction if (byzantineNodes.contains(peer)) { peer->txInjections.emplace( diff --git a/src/test/consensus/Consensus_test.cpp b/src/test/consensus/Consensus_test.cpp index 85dd5e3957..b7bfb302bc 100644 --- a/src/test/consensus/Consensus_test.cpp +++ b/src/test/consensus/Consensus_test.cpp @@ -63,7 +63,7 @@ public: using namespace std::chrono_literals; testcase("check consensus"); - // Use default parameterss + // Use default parameters ConsensusParms const p{}; /////////////// @@ -74,7 +74,7 @@ public: ConsensusState::No == checkConsensus(10, 2, 2, 0, 3s, 2s, false, p, true, journal_)); - // If not enough peers have propsed, ensure + // If not enough peers have proposed, ensure // more time for proposals BEAST_EXPECT( ConsensusState::No == @@ -119,7 +119,7 @@ public: ConsensusState::No == checkConsensus(10, 2, 2, 0, 3s, 2s, true, p, true, journal_)); - // If not enough peers have propsed, ensure + // If not enough peers have proposed, ensure // more time for proposals BEAST_EXPECT( ConsensusState::No == @@ -661,7 +661,7 @@ public: // Run to the ledger *prior* to decreasing the resolution sim.run(increaseLedgerTimeResolutionEvery - 2); - // In order to create the discrepency, we want a case where if + // In order to create the discrepancy, we want a case where if // X = effCloseTime(closeTime, resolution, parentCloseTime) // X != effCloseTime(X, resolution, parentCloseTime) // @@ -906,7 +906,7 @@ public: // for B. // - The network reconnects and the validations for generation 3 ledgers // are observed (D and the 8 C's) - // - In the old approach, 2 votes for D outweights 1 vote for each C' + // - In the old approach, 2 votes for D outweighs 1 vote for each C' // so the network would avalanche towards D and fully validate it // EVEN though C was fully validated by one node // - In the new approach, 2 votes for D are not enough to outweight the @@ -1029,7 +1029,7 @@ public: // The "ahead" validators run normal speed and run ahead validating the // upper chain of ledgers. // - // Due to the uncommited support definition of the preferred branch + // Due to the uncommitted support definition of the preferred branch // protocol, even if the "behind" validators are a majority, the "ahead" // validators cannot jump to the proper branch until the "behind" // validators catch up to the same sequence number. For this test to diff --git a/src/test/consensus/DistributedValidatorsSim_test.cpp b/src/test/consensus/DistributedValidatorsSim_test.cpp index 006c1aab4e..1a088576ce 100644 --- a/src/test/consensus/DistributedValidatorsSim_test.cpp +++ b/src/test/consensus/DistributedValidatorsSim_test.cpp @@ -59,7 +59,7 @@ class DistributedValidators_test : public beast::unit_test::suite // Initial round to set prior state sim.run(1); - // Run for 10 minues, submitting 100 tx/second + // Run for 10 minutes, submitting 100 tx/second std::chrono::nanoseconds const simDuration = 10min; std::chrono::nanoseconds const quiet = 10s; Rate const rate{100, 1000ms}; @@ -163,7 +163,7 @@ class DistributedValidators_test : public beast::unit_test::suite // Initial round to set prior state sim.run(1); - // Run for 10 minues, submitting 100 tx/second + // Run for 10 minutes, submitting 100 tx/second std::chrono::nanoseconds simDuration = 10min; std::chrono::nanoseconds quiet = 10s; Rate rate{100, 1000ms}; diff --git a/src/test/consensus/ScaleFreeSim_test.cpp b/src/test/consensus/ScaleFreeSim_test.cpp index 53c5030f29..dee4c77268 100644 --- a/src/test/consensus/ScaleFreeSim_test.cpp +++ b/src/test/consensus/ScaleFreeSim_test.cpp @@ -56,7 +56,7 @@ class ScaleFreeSim_test : public beast::unit_test::suite // Initialize timers HeartbeatTimer heart(sim.scheduler, seconds(10s)); - // Run for 10 minues, submitting 100 tx/second + // Run for 10 minutes, submitting 100 tx/second std::chrono::nanoseconds const simDuration = 10min; std::chrono::nanoseconds const quiet = 10s; Rate const rate{100, 1000ms}; diff --git a/src/test/csf/CollectorRef.h b/src/test/csf/CollectorRef.h index 3aa2c6495f..022db01008 100644 --- a/src/test/csf/CollectorRef.h +++ b/src/test/csf/CollectorRef.h @@ -8,7 +8,7 @@ namespace xrpl { namespace test { namespace csf { -/** Holds a type-erased reference to an arbitray collector. +/** Holds a type-erased reference to an arbitrary collector. A collector is any class that implements diff --git a/src/test/csf/Histogram.h b/src/test/csf/Histogram.h index e32fded2f2..61ec680939 100644 --- a/src/test/csf/Histogram.h +++ b/src/test/csf/Histogram.h @@ -26,7 +26,7 @@ template > class Histogram { // TODO: Consider logarithmic bins around expected median if this becomes - // unscaleable + // unscalable std::map counts_; std::size_t samples = 0; diff --git a/src/test/jtx/TestHelpers.h b/src/test/jtx/TestHelpers.h index f00b929967..3096a902b1 100644 --- a/src/test/jtx/TestHelpers.h +++ b/src/test/jtx/TestHelpers.h @@ -29,7 +29,7 @@ namespace xrpl { namespace test { namespace jtx { -/** Generic helper class for helper clases that set a field on a JTx. +/** Generic helper class for helper classes that set a field on a JTx. Not every helper will be able to use this because of conversions and other issues, but for classes where it's straightforward, this can simplify things. diff --git a/src/test/jtx/deposit.h b/src/test/jtx/deposit.h index 5ea1e5bf06..e378366563 100644 --- a/src/test/jtx/deposit.h +++ b/src/test/jtx/deposit.h @@ -15,7 +15,7 @@ namespace deposit { Json::Value auth(Account const& account, Account const& auth); -/** Remove preauthorization for deposit. Invoke as deposit::unauth. */ +/** Remove pre-authorization for deposit. Invoke as deposit::unauth. */ Json::Value unauth(Account const& account, Account const& unauth); diff --git a/src/test/jtx/rpc.h b/src/test/jtx/rpc.h index 5a7c205aac..ba3c71074d 100644 --- a/src/test/jtx/rpc.h +++ b/src/test/jtx/rpc.h @@ -49,7 +49,7 @@ public: // always obtained from the lookup into the ErrorInfo lookup table. // // Take advantage of that fact to populate jt.rpcException. The - // check will be aware of whether the rpcExcpetion can be safely + // check will be aware of whether the rpcException can be safely // ignored. jt.rpcCode = { *code_, diff --git a/src/test/protocol/Seed_test.cpp b/src/test/protocol/Seed_test.cpp index 65428295f8..d33f397921 100644 --- a/src/test/protocol/Seed_test.cpp +++ b/src/test/protocol/Seed_test.cpp @@ -292,7 +292,7 @@ public: testcase("Parsing"); // account IDs and node and account public and private - // keys should not be parseable as seeds. + // keys should not be parsable as seeds. auto const node1 = randomKeyPair(KeyType::secp256k1); diff --git a/src/test/rpc/AccountObjects_test.cpp b/src/test/rpc/AccountObjects_test.cpp index e438d50633..4f3e1817e1 100644 --- a/src/test/rpc/AccountObjects_test.cpp +++ b/src/test/rpc/AccountObjects_test.cpp @@ -667,7 +667,7 @@ public: env(deposit::auth(gw, alice)); env.close(); { - // Find the preauthorization. + // Find the pre-authorization. Json::Value const resp = acctObjs(gw, jss::deposit_preauth); BEAST_EXPECT(acctObjsIsSize(resp, 1)); diff --git a/src/test/rpc/ManifestRPC_test.cpp b/src/test/rpc/ManifestRPC_test.cpp index 5d4f4900eb..96326e010f 100644 --- a/src/test/rpc/ManifestRPC_test.cpp +++ b/src/test/rpc/ManifestRPC_test.cpp @@ -30,7 +30,7 @@ public: "Missing field 'public_key'."); } { - // manifest with manlformed public key + // manifest with malformed public key auto const info = env.rpc( "json", "manifest", diff --git a/src/test/rpc/Subscribe_test.cpp b/src/test/rpc/Subscribe_test.cpp index 1637554f5c..5a58c27ea8 100644 --- a/src/test/rpc/Subscribe_test.cpp +++ b/src/test/rpc/Subscribe_test.cpp @@ -1362,7 +1362,7 @@ public: // // The values of these fields are dependent on the NFTokenID/OfferID // changed in its corresponding transaction. We want to validate each - // response to make sure the synethic fields hold the right values. + // response to make sure the synthetic fields hold the right values. testcase("Test synthetic fields from Subscribe response"); diff --git a/src/tests/libxrpl/basics/base64.cpp b/src/tests/libxrpl/basics/base64.cpp index e4581126b4..f6544105d8 100644 --- a/src/tests/libxrpl/basics/base64.cpp +++ b/src/tests/libxrpl/basics/base64.cpp @@ -16,6 +16,7 @@ check(std::string const& in, std::string const& out) TEST_CASE("base64") { + // cspell: disable check("", ""); check("f", "Zg=="); check("fo", "Zm8="); @@ -23,6 +24,7 @@ TEST_CASE("base64") check("foob", "Zm9vYg=="); check("fooba", "Zm9vYmE="); check("foobar", "Zm9vYmFy"); + // cspell: enable check( "Man is distinguished, not only by his reason, but by this " diff --git a/src/xrpld/app/consensus/RCLConsensus.h b/src/xrpld/app/consensus/RCLConsensus.h index e26cde9801..2e33bbae14 100644 --- a/src/xrpld/app/consensus/RCLConsensus.h +++ b/src/xrpld/app/consensus/RCLConsensus.h @@ -59,7 +59,7 @@ class RCLConsensus // The timestamp of the last validation we used NetClock::time_point lastValidationTime_; - // These members are queried via public accesors and are atomic for + // These members are queried via public accessors and are atomic for // thread safety. std::atomic validating_{false}; std::atomic prevProposers_{0}; diff --git a/src/xrpld/app/ledger/AbstractFetchPackContainer.h b/src/xrpld/app/ledger/AbstractFetchPackContainer.h index 85efe09e29..d2cdd1e920 100644 --- a/src/xrpld/app/ledger/AbstractFetchPackContainer.h +++ b/src/xrpld/app/ledger/AbstractFetchPackContainer.h @@ -16,7 +16,7 @@ class AbstractFetchPackContainer public: virtual ~AbstractFetchPackContainer() = default; - /** Retrieves partial ledger data of the coresponding hash from peers.` + /** Retrieves partial ledger data of the corresponding hash from peers.` @param nodeHash The 256-bit hash of the data to fetch. @return `std::nullopt` if the hash isn't cached, diff --git a/src/xrpld/app/ledger/BookListeners.cpp b/src/xrpld/app/ledger/BookListeners.cpp index 69d03058a9..ebd59c3fcc 100644 --- a/src/xrpld/app/ledger/BookListeners.cpp +++ b/src/xrpld/app/ledger/BookListeners.cpp @@ -30,7 +30,7 @@ BookListeners::publish( if (p) { - // Only publish jvObj if this is the first occurence + // Only publish jvObj if this is the first occurrence if (havePublished.emplace(p->getSeq()).second) { jvObj.visit( diff --git a/src/xrpld/app/ledger/README.md b/src/xrpld/app/ledger/README.md index d2afe01e71..cb935897b8 100644 --- a/src/xrpld/app/ledger/README.md +++ b/src/xrpld/app/ledger/README.md @@ -450,7 +450,7 @@ back as the database goes. If requested, it can additionally repair the SQLite entries for transactions in each checked ledger. This was primarily intended to repair incorrect -entries created by a bug (since fixed) that could cause transasctions from a +entries created by a bug (since fixed) that could cause transactions from a ledger other than the fully-validated ledger to appear in the SQLite databases in addition to the transactions from the correct ledger. diff --git a/src/xrpld/app/main/GRPCServer.cpp b/src/xrpld/app/main/GRPCServer.cpp index e415ee14cf..6ed902ec1e 100644 --- a/src/xrpld/app/main/GRPCServer.cpp +++ b/src/xrpld/app/main/GRPCServer.cpp @@ -413,7 +413,7 @@ GRPCServerImpl::handleRpcs() // tells us whether there is any kind of event or cq_ is shutting down. // When cq_.Next(...) returns false, all work has been completed and the // loop can exit. When the server is shutdown, each CallData object that is - // listening for a request is forceably cancelled, and is returned by + // listening for a request is forcibly cancelled, and is returned by // cq_->Next() with ok set to false. Then, each CallData object processing // a request must complete (by sending data to the client), each of which // will be returned from cq_->Next() with ok set to true. After all diff --git a/src/xrpld/app/main/GRPCServer.h b/src/xrpld/app/main/GRPCServer.h index dab71303c4..c2697e26c6 100644 --- a/src/xrpld/app/main/GRPCServer.h +++ b/src/xrpld/app/main/GRPCServer.h @@ -126,7 +126,7 @@ public: getEndpoint() const; private: - // Class encompasing the state and logic needed to serve a request. + // Class encompassing the state and logic needed to serve a request. template class CallData : public Processor, diff --git a/src/xrpld/app/misc/FeeEscalation.md b/src/xrpld/app/misc/FeeEscalation.md index 468ab2b528..7843620320 100644 --- a/src/xrpld/app/misc/FeeEscalation.md +++ b/src/xrpld/app/misc/FeeEscalation.md @@ -237,7 +237,7 @@ often coincides with new ledgers with zero transactions. recover if the problem is temporary. These exact values were chosen experimentally, and can easily change in the future. - _Minimum `lastLedgerMedianFeeLevel`_. The value of 500 was chosen to - ensure that the first escalated fee was more significant and noticable + ensure that the first escalated fee was more significant and noticeable than what the default would allow. This exact value was chosen experimentally, and can easily change in the future. - _Transaction queue size limit_. The limit is computed based on the @@ -291,7 +291,7 @@ single-singed reference transaction. It is up to the user to compute the necessary fees for other types of transactions. (E.g. multiply all drop values by 5 for a multi-signed transaction with 4 signatures.) -The `fee` result is always instantanteous, and relates to the open +The `fee` result is always instantaneous, and relates to the open ledger. It includes the sequence number of the current open ledger, but may not make sense if rippled is not synced to the network. diff --git a/src/xrpld/app/misc/HashRouter.cpp b/src/xrpld/app/misc/HashRouter.cpp index 0cad01c27e..a2ba41b361 100644 --- a/src/xrpld/app/misc/HashRouter.cpp +++ b/src/xrpld/app/misc/HashRouter.cpp @@ -14,7 +14,7 @@ HashRouter::emplace(uint256 const& key) -> std::pair return std::make_pair(std::ref(iter->second), false); } - // See if any supressions need to be expired + // See if any suppressions need to be expired expire(suppressionMap_, setup_.holdTime); return std::make_pair( diff --git a/src/xrpld/app/misc/HashRouter.h b/src/xrpld/app/misc/HashRouter.h index 1b59797b28..449097a387 100644 --- a/src/xrpld/app/misc/HashRouter.h +++ b/src/xrpld/app/misc/HashRouter.h @@ -193,7 +193,7 @@ public: virtual ~HashRouter() = default; - // VFALCO TODO Replace "Supression" terminology with something more + // VFALCO TODO Replace "Suppression" terminology with something more // semantically meaningful. void addSuppression(uint256 const& key); diff --git a/src/xrpld/app/misc/Manifest.h b/src/xrpld/app/misc/Manifest.h index 24e4f5f71f..c1a77be63b 100644 --- a/src/xrpld/app/misc/Manifest.h +++ b/src/xrpld/app/misc/Manifest.h @@ -303,7 +303,7 @@ public: std::optional getDomain(PublicKey const& pk) const; - /** Returns mainfest corresponding to a given public key + /** Returns manifest corresponding to a given public key @return manifest corresponding to Master public key if present, otherwise std::nullopt diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index 084a584377..d0f93577da 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -290,7 +290,7 @@ public: * transactions and wait for this transaction to complete. * * @param transaction Transaction object. - * @param bUnliimited Whether a privileged client connection submitted it. + * @param bUnlimited Whether a privileged client connection submitted it. * @param failType fail_hard setting from transaction submission. */ void @@ -1260,7 +1260,7 @@ NetworkOPsImp::preProcessTransaction(std::shared_ptr& transaction) return false; } - // NOTE eahennis - I think this check is redundant, + // NOTE ximinez - I think this check is redundant, // but I'm not 100% sure yet. // If so, only cost is looking up HashRouter flags. auto const [validity, reason] = @@ -2194,7 +2194,7 @@ NetworkOPsImp::endConsensus(std::unique_ptr const& clog) { // check if the ledger is good enough to go to FULL // Note: Do not go to FULL if we don't have the previous ledger - // check if the ledger is bad enough to go to CONNECTE D -- TODO + // check if the ledger is bad enough to go to CONNECTED -- TODO auto current = m_ledgerMaster.getCurrentLedger(); if (app_.timeKeeper().now() < (current->header().parentCloseTime + @@ -3638,7 +3638,7 @@ NetworkOPsImp::subAccount( auto simIterator = subMap.find(naAccountID); if (simIterator == subMap.end()) { - // Not found, note that account has a new single listner. + // Not found, note that account has a new single listener. SubMapType usisElement; usisElement[isrListener->getSeq()] = isrListener; // VFALCO NOTE This is making a needless copy of naAccountID @@ -4578,7 +4578,7 @@ NetworkOPsImp::getBookPage( Rate offerRate = parityRate; if (rate != parityRate - // Have a tranfer fee. + // Have a transfer fee. && uTakerID != book.out.account // Not taking offers of own IOUs. && book.out.account != uOfferOwnerID) @@ -4728,7 +4728,7 @@ NetworkOPsImp::getBookPage( Rate offerRate = parityRate; if (rate != parityRate - // Have a tranfer fee. + // Have a transfer fee. && uTakerID != book.out.account // Not taking offers of own IOUs. && book.out.account != uOfferOwnerID) @@ -4751,7 +4751,7 @@ NetworkOPsImp::getBookPage( saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]); - // TOOD(tom): The result of this expression is not used - what's + // TODO(tom): The result of this expression is not used - what's // going on here? std::min( saTakerPays, diff --git a/src/xrpld/app/misc/NetworkOPs.h b/src/xrpld/app/misc/NetworkOPs.h index 800f473959..5b92e4574b 100644 --- a/src/xrpld/app/misc/NetworkOPs.h +++ b/src/xrpld/app/misc/NetworkOPs.h @@ -31,9 +31,9 @@ class CanonicalTXSet; // should use this interface. The RPC code will primarily be a light wrapper // over this code. // -// Eventually, it will check the node's operating mode (synched, unsynched, -// etectera) and defer to the correct means of processing. The current -// code assumes this node is synched (and will continue to do so until +// Eventually, it will check the node's operating mode (synced, unsynced, +// etcetera) and defer to the correct means of processing. The current +// code assumes this node is synced (and will continue to do so until // there's a functional network. // diff --git a/src/xrpld/app/misc/SHAMapStoreImp.cpp b/src/xrpld/app/misc/SHAMapStoreImp.cpp index 0e33a0bc10..98be038554 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.cpp +++ b/src/xrpld/app/misc/SHAMapStoreImp.cpp @@ -104,7 +104,7 @@ SHAMapStoreImp::SHAMapStoreImp( get_if_exists(section, "delete_batch", deleteBatch_); std::uint32_t temp; if (get_if_exists(section, "back_off_milliseconds", temp) || - // Included for backward compaibility with an undocumented setting + // Included for backward compatibility with an undocumented setting get_if_exists(section, "backOff", temp)) { backOff_ = std::chrono::milliseconds{temp}; diff --git a/src/xrpld/app/misc/Transaction.h b/src/xrpld/app/misc/Transaction.h index ac801a2cd0..9f75387744 100644 --- a/src/xrpld/app/misc/Transaction.h +++ b/src/xrpld/app/misc/Transaction.h @@ -221,7 +221,7 @@ public: } /** - * @brief setQueued Set this flag once was put into heldtxns queue + * @brief setQueued Set this flag once was put into held-txns queue */ void setQueued() diff --git a/src/xrpld/app/misc/TxQ.h b/src/xrpld/app/misc/TxQ.h index aff7fc89db..fb1b10e886 100644 --- a/src/xrpld/app/misc/TxQ.h +++ b/src/xrpld/app/misc/TxQ.h @@ -95,7 +95,7 @@ public: allowing more than `maximumTxnInLedger` "cheap" transactions into the open ledger. - @todo eahennis. This setting seems to go against our goals and + @todo ximinez. This setting seems to go against our goals and values. Can it be removed? */ std::optional maximumTxnInLedger; diff --git a/src/xrpld/app/misc/detail/LendingHelpers.cpp b/src/xrpld/app/misc/detail/LendingHelpers.cpp index 51e0988bc4..37385583e7 100644 --- a/src/xrpld/app/misc/detail/LendingHelpers.cpp +++ b/src/xrpld/app/misc/detail/LendingHelpers.cpp @@ -1652,7 +1652,7 @@ computeLoanProperties( principalOutstanding = roundToAsset( asset, principalOutstanding, loanScale, Number::to_nearest); - // E diff --git a/src/xrpld/app/tx/detail/CreateOffer.cpp b/src/xrpld/app/tx/detail/CreateOffer.cpp index f81afecd55..848599943a 100644 --- a/src/xrpld/app/tx/detail/CreateOffer.cpp +++ b/src/xrpld/app/tx/detail/CreateOffer.cpp @@ -814,11 +814,11 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) Book const book{saTakerPays.issue(), saTakerGets.issue(), domainID}; // Add offer to order book, using the original rate - // before any crossing occured. + // before any crossing occurred. // // Regular offer - BookDirectory points to open directory // - // Domain offer (w/o hyrbid) - BookDirectory points to domain + // Domain offer (w/o hybrid) - BookDirectory points to domain // directory // // Hybrid domain offer - BookDirectory points to domain directory, diff --git a/src/xrpld/app/tx/detail/InvariantCheck.h b/src/xrpld/app/tx/detail/InvariantCheck.h index b7f91a1c46..ef9db373f5 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.h +++ b/src/xrpld/app/tx/detail/InvariantCheck.h @@ -613,7 +613,7 @@ public: }; /** - * @brief Invariants: Pseudo-accounts have valid and consisent properties + * @brief Invariants: Pseudo-accounts have valid and consistent properties * * Pseudo-accounts have certain properties, and some of those properties are * unique to pseudo-accounts. Check that all pseudo-accounts are following the diff --git a/src/xrpld/app/tx/detail/NFTokenUtils.cpp b/src/xrpld/app/tx/detail/NFTokenUtils.cpp index c737855840..3a43cda6f0 100644 --- a/src/xrpld/app/tx/detail/NFTokenUtils.cpp +++ b/src/xrpld/app/tx/detail/NFTokenUtils.cpp @@ -940,7 +940,7 @@ tokenOfferCreatePreclaim( { // If this is a sell offer, check that the account is allowed to // receive IOUs. If this is a buy offer, we have to check that trustline - // is authorized, even though we previosly checked it's balance via + // is authorized, even though we previously checked it's balance via // accountHolds. This is due to a possibility of existence of // unauthorized trustlines with balance auto const res = nft::checkTrustlineAuthorized( diff --git a/src/xrpld/app/tx/detail/Payment.cpp b/src/xrpld/app/tx/detail/Payment.cpp index 7a14cecc2d..59c7431f4c 100644 --- a/src/xrpld/app/tx/detail/Payment.cpp +++ b/src/xrpld/app/tx/detail/Payment.cpp @@ -316,7 +316,7 @@ Payment::preclaim(PreclaimContext const& ctx) << "Delay transaction: Destination account does not exist. " << "Insufficent payment to create account."; - // TODO: dedupe + // TODO: de-dupe // Another transaction could create the account and then this // transaction would succeed. return tecNO_DST_INSUF_XRP; @@ -558,7 +558,7 @@ Payment::doApply() // If the actual amount delivered is different from the original // amount due to partial payment or transfer fee, we need to update - // DelieveredAmount using the actual delivered amount + // DeliveredAmount using the actual delivered amount if (view().rules().enabled(fixMPTDeliveredAmount) && amountDeliver != dstAmount) ctx_.deliver(amountDeliver); diff --git a/src/xrpld/conditions/detail/PreimageSha256.h b/src/xrpld/conditions/detail/PreimageSha256.h index 642a7afdc0..f495885794 100644 --- a/src/xrpld/conditions/detail/PreimageSha256.h +++ b/src/xrpld/conditions/detail/PreimageSha256.h @@ -37,7 +37,7 @@ public: static std::unique_ptr deserialize(Slice s, std::error_code& ec) { - // Per the RFC, a preimage fulfulliment is defined as + // Per the RFC, a preimage fulfillment is defined as // follows: // // PreimageFulfillment ::= SEQUENCE { diff --git a/src/xrpld/consensus/Consensus.cpp b/src/xrpld/consensus/Consensus.cpp index b71a36d538..46038e9d53 100644 --- a/src/xrpld/consensus/Consensus.cpp +++ b/src/xrpld/consensus/Consensus.cpp @@ -122,7 +122,7 @@ checkConsensusReached( // We only get stalled when there are disputed transactions and all of them // unequivocally have 80% (minConsensusPct) agreement, either for or - // against. That is: either under 20% or over 80% consensus (repectively + // against. That is: either under 20% or over 80% consensus (respectively // "nay" or "yay"). This prevents manipulation by a minority of byzantine // peers of which transactions make the cut to get into the ledger. if (stalled) diff --git a/src/xrpld/core/Config.h b/src/xrpld/core/Config.h index e25148aaa9..29d799bd62 100644 --- a/src/xrpld/core/Config.h +++ b/src/xrpld/core/Config.h @@ -137,7 +137,7 @@ public: // Network parameters uint32_t NETWORK_ID = 0; - // DEPRECATED - Fee units for a reference transction. + // DEPRECATED - Fee units for a reference transaction. // Only provided for backwards compatibility in a couple of places static constexpr std::uint32_t FEE_UNITS_DEPRECATED = 10; diff --git a/src/xrpld/core/detail/SociDB.cpp b/src/xrpld/core/detail/SociDB.cpp index a90e59beed..c04beaff29 100644 --- a/src/xrpld/core/detail/SociDB.cpp +++ b/src/xrpld/core/detail/SociDB.cpp @@ -279,7 +279,7 @@ public: protected: std::uintptr_t const id_; // session is owned by the DatabaseCon parent that holds the checkpointer. - // It is possible (tho rare) for the DatabaseCon class to be destoryed + // It is possible (though rare) for the DatabaseCon class to be destroyed // before the checkpointer. std::weak_ptr session_; std::mutex mutex_; diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index c92a95149e..53237ed3ae 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -586,7 +586,7 @@ PeerImp::fail(std::string const& reason) if (!socket_.is_open()) return; - // Call to name() locks, log only if the message will be outputed + // Call to name() locks, log only if the message will be outputted if (journal_.active(beast::severities::kWarning)) { std::string const n = name(); diff --git a/src/xrpld/peerfinder/PeerfinderManager.h b/src/xrpld/peerfinder/PeerfinderManager.h index 7a25edcce5..fbb59eab0e 100644 --- a/src/xrpld/peerfinder/PeerfinderManager.h +++ b/src/xrpld/peerfinder/PeerfinderManager.h @@ -97,7 +97,7 @@ struct Config //------------------------------------------------------------------------------ -/** Describes a connectible peer address along with some metadata. */ +/** Describes a connectable peer address along with some metadata. */ struct Endpoint { Endpoint() = default; diff --git a/src/xrpld/peerfinder/README.md b/src/xrpld/peerfinder/README.md index a3f89fd446..806984035b 100644 --- a/src/xrpld/peerfinder/README.md +++ b/src/xrpld/peerfinder/README.md @@ -106,7 +106,7 @@ tuned heuristics. The fields are as follows: precision as an implementation defined percentage of `maxPeers` subject to an implementation defined floor. An instance of the PeerFinder rounds the fractional part up or down using a uniform random number generated at - program startup. This allows the outdegree of the overlay network to be + program startup. This allows the out-degree of the overlay network to be controlled with fractional precision, ensuring that all inbound network connection slots are not consumed (which would make it difficult for new participants to enter the network). @@ -138,7 +138,7 @@ connection test on that neighbor by initiating an outgoing connection to the remote IP address as seen on the connection combined with the port advertised in the Endpoint message. If the test fails, then the peer considers its neighbor firewalled (intentionally or due to misconfiguration) and not forward neighbor -endpoint in Endpoint messages. This prevents poor quality unconnectible +endpoint in Endpoint messages. This prevents poor quality un-connectable addresses from landing in the caches. If the incoming connection test passes, then the peer fills in the Endpoint message with the remote address as seen on the connection before storing it in its cache and forwarding it to other peers. @@ -150,7 +150,7 @@ it no longer has available inbound slots, its address will shortly after stop being handed out by other peers. Livecache entries are very likely to result in both a successful connection establishment and the acquisition of an active outbound slot. Compare this with Bootcache addresses, which are very likely to -be connectible but unlikely to have an open slot. +be connectable but unlikely to have an open slot. Because entries in the Livecache are ephemeral, they are not persisted across launches in the database. The Livecache is continually updated and expired as @@ -186,7 +186,7 @@ since they will have moved towards the core of the overlay over their high uptime. When a connected server is full it will return a handful of new addresses from its Livecache and gracefully close the connection. Addresses from the Livecache are highly likely to have inbound connection slots and be -connectible. +connectable. For security, all information that contributes to the ranking of Bootcache entries is observed locally. PeerFinder never trusts external sources of information. @@ -257,7 +257,7 @@ Slot properties may be combined and are not mutually exclusive. - **Superpeer** (forthcoming) A superpeer slot is a connection to a peer which can accept incoming - connections, meets certain resource availaibility requirements (such as + connections, meets certain resource availability requirements (such as bandwidth, CPU, and storage capacity), and operates full duplex in the overlay. Connections which are not superpeers are by definition leaves. A leaf slot is a connection to a peer which does not route overlay messages to @@ -321,7 +321,7 @@ stage remains active while: PeerFinder makes its best effort to exhaust addresses in the Livecache before moving on to the Bootcache, because Livecache addresses are highly likely -to be connectible (since they are known to have been online within the last +to be connectable (since they are known to have been online within the last minute), and highly likely to have an open slot for an incoming connection (because peers only advertise themselves in the Livecache when they have open slots). @@ -334,7 +334,7 @@ desired. The stage remains active while: - There are addresses in the cache that have not been tried recently. -Entries in the Bootcache are ranked, with highly connectible addresses preferred +Entries in the Bootcache are ranked, with highly connectable addresses preferred over others. Connection attempts to Bootcache addresses are very likely to succeed but unlikely to produce an active connection since the peers likely do not have open slots. Before the remote peer closes the connection it will send diff --git a/src/xrpld/peerfinder/detail/Checker.h b/src/xrpld/peerfinder/detail/Checker.h index 277ce8c74d..700768788a 100644 --- a/src/xrpld/peerfinder/detail/Checker.h +++ b/src/xrpld/peerfinder/detail/Checker.h @@ -14,7 +14,7 @@ namespace xrpl { namespace PeerFinder { -/** Tests remote listening sockets to make sure they are connectible. */ +/** Tests remote listening sockets to make sure they are connectable. */ template class Checker { diff --git a/src/xrpld/peerfinder/detail/Fixed.h b/src/xrpld/peerfinder/detail/Fixed.h index 4c89bc598e..4d4a407873 100644 --- a/src/xrpld/peerfinder/detail/Fixed.h +++ b/src/xrpld/peerfinder/detail/Fixed.h @@ -16,7 +16,7 @@ public: Fixed(Fixed const&) = default; - /** Returns the time after which we shoud allow a connection attempt. */ + /** Returns the time after which we should allow a connection attempt. */ clock_type::time_point const& when() const { diff --git a/src/xrpld/rpc/GRPCHandlers.h b/src/xrpld/rpc/GRPCHandlers.h index f3e8d74f9d..b98b3021a3 100644 --- a/src/xrpld/rpc/GRPCHandlers.h +++ b/src/xrpld/rpc/GRPCHandlers.h @@ -14,7 +14,7 @@ namespace xrpl { * nested inside RPC::GRPCContext, where T is the request type * The return value is the response type, as well as a status * If the status is not Status::OK (meaning an error occurred), then only - * the status will be sent to the client, and the response will be ommitted + * the status will be sent to the client, and the response will be omitted */ std::pair diff --git a/src/xrpld/rpc/detail/Handler.cpp b/src/xrpld/rpc/detail/Handler.cpp index 2000af5e81..1a60c137f7 100644 --- a/src/xrpld/rpc/detail/Handler.cpp +++ b/src/xrpld/rpc/detail/Handler.cpp @@ -173,7 +173,7 @@ Handler const handlerArray[]{ {"validator_info", byRef(&doValidatorInfo), Role::ADMIN, NO_CONDITION}, {"vault_info", byRef(&doVaultInfo), Role::USER, NO_CONDITION}, {"wallet_propose", byRef(&doWalletPropose), Role::ADMIN, NO_CONDITION}, - // Evented methods + // Event methods {"subscribe", byRef(&doSubscribe), Role::USER, NO_CONDITION}, {"unsubscribe", byRef(&doUnsubscribe), Role::USER, NO_CONDITION}, }; diff --git a/src/xrpld/rpc/detail/InfoSub.cpp b/src/xrpld/rpc/detail/InfoSub.cpp index a0869b9d96..c8917b3327 100644 --- a/src/xrpld/rpc/detail/InfoSub.cpp +++ b/src/xrpld/rpc/detail/InfoSub.cpp @@ -8,9 +8,9 @@ namespace xrpl { // should use this interface. The RPC code will primarily be a light wrapper // over this code. -// Eventually, it will check the node's operating mode (synched, unsynched, -// etectera) and defer to the correct means of processing. The current -// code assumes this node is synched (and will continue to do so until +// Eventually, it will check the node's operating mode (synced, unsynced, +// etcetera) and defer to the correct means of processing. The current +// code assumes this node is synced (and will continue to do so until // there's a functional network. InfoSub::InfoSub(Source& source) : m_source(source), mSeq(assign_id()) diff --git a/src/xrpld/rpc/detail/RPCCall.cpp b/src/xrpld/rpc/detail/RPCCall.cpp index fa1a089efb..5eb3943c28 100644 --- a/src/xrpld/rpc/detail/RPCCall.cpp +++ b/src/xrpld/rpc/detail/RPCCall.cpp @@ -1295,7 +1295,7 @@ public: {"wallet_propose", &RPCParser::parseWalletPropose, 0, 1}, {"internal", &RPCParser::parseInternal, 1, -1}, - // Evented methods + // Event methods {"path_find", &RPCParser::parseEvented, -1, -1}, {"subscribe", &RPCParser::parseEvented, -1, -1}, {"unsubscribe", &RPCParser::parseEvented, -1, -1}, diff --git a/src/xrpld/rpc/detail/RPCSub.cpp b/src/xrpld/rpc/detail/RPCSub.cpp index 5d008e4ee6..616911fdfa 100644 --- a/src/xrpld/rpc/detail/RPCSub.cpp +++ b/src/xrpld/rpc/detail/RPCSub.cpp @@ -171,7 +171,7 @@ private: int mSeq; // Next id to allocate. - bool mSending; // Sending threead is active. + bool mSending; // Sending thread is active. std::deque> mDeque; diff --git a/src/xrpld/rpc/detail/TransactionSign.cpp b/src/xrpld/rpc/detail/TransactionSign.cpp index a4ac32ee17..485765c133 100644 --- a/src/xrpld/rpc/detail/TransactionSign.cpp +++ b/src/xrpld/rpc/detail/TransactionSign.cpp @@ -1043,7 +1043,7 @@ transactionSubmit( // Finally, submit the transaction. try { - // FIXME: For performance, should use asynch interface + // FIXME: For performance, should use async interface processTransaction(txn.second, isUnlimited(role), true, failType); } catch (std::exception&) @@ -1439,7 +1439,7 @@ transactionSubmitMultiSigned( // Finally, submit the transaction. try { - // FIXME: For performance, should use asynch interface + // FIXME: For performance, should use async interface processTransaction(txn.second, isUnlimited(role), true, failType); } catch (std::exception&) diff --git a/src/xrpld/rpc/handlers/GatewayBalances.cpp b/src/xrpld/rpc/handlers/GatewayBalances.cpp index 55959d8641..57c73a53e0 100644 --- a/src/xrpld/rpc/handlers/GatewayBalances.cpp +++ b/src/xrpld/rpc/handlers/GatewayBalances.cpp @@ -29,7 +29,7 @@ namespace xrpl { // 3) Object of "assets" indicating accounts that owe the gateway. // (Gateways typically do not hold positive balances. This is unusual.) -// gateway_balances [] [ [] [ [ // limit: integer // optional, number of problems // role: gateway|user // account role to assume -// transactions: true // optional, reccommend transactions +// transactions: true // optional, recommend transactions // } Json::Value doNoRippleCheck(RPC::JsonContext& context) From 2c37ef7762f4b1948f8894bb3ce1541d33f8e05a Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 7 Jan 2026 14:26:14 -0500 Subject: [PATCH 055/105] refactor: Fix spelling issues in private/local variables and functions (#6182) This change fixes several typos in private/local variables and private functions. There is no functionality change. --- cmake/XrplCompiler.cmake | 2 +- include/xrpl/basics/IntrusivePointer.h | 2 +- include/xrpl/basics/Slice.h | 4 ++-- include/xrpl/basics/StringUtilities.h | 8 ++++---- .../detail/aged_unordered_container.h | 7 ++++--- include/xrpl/beast/hash/hash_append.h | 2 +- include/xrpl/beast/utility/PropertyStream.h | 2 +- include/xrpl/json/json_value.h | 2 +- include/xrpl/json/json_writer.h | 4 ++-- include/xrpl/nodestore/Manager.h | 2 +- include/xrpl/protocol/IOUAmount.h | 2 +- src/libxrpl/core/detail/LoadMonitor.cpp | 2 +- src/libxrpl/json/json_valueiterator.cpp | 18 +++++++++--------- src/libxrpl/json/json_writer.cpp | 8 ++++---- src/libxrpl/ledger/CredentialHelpers.cpp | 2 +- src/libxrpl/net/RegisterSSLCerts.cpp | 4 ++-- src/libxrpl/nodestore/Database.cpp | 2 +- src/libxrpl/protocol/BuildInfo.cpp | 2 +- src/libxrpl/protocol/Indexes.cpp | 4 ++-- src/xrpld/app/paths/Pathfinder.cpp | 2 +- 20 files changed, 41 insertions(+), 40 deletions(-) diff --git a/cmake/XrplCompiler.cmake b/cmake/XrplCompiler.cmake index 110478fadf..622b2d2f74 100644 --- a/cmake/XrplCompiler.cmake +++ b/cmake/XrplCompiler.cmake @@ -149,7 +149,7 @@ elseif (use_gold AND is_gcc) ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) #[=========================================================[ NOTE: THE gold linker inserts -rpath as DT_RUNPATH by - default intead of DT_RPATH, so you might have slightly + default instead of DT_RPATH, so you might have slightly unexpected runtime ld behavior if you were expecting DT_RPATH. Specify --disable-new-dtags to gold if you do not want the default DT_RUNPATH behavior. This rpath diff --git a/include/xrpl/basics/IntrusivePointer.h b/include/xrpl/basics/IntrusivePointer.h index 24521b95a7..101a4b6f16 100644 --- a/include/xrpl/basics/IntrusivePointer.h +++ b/include/xrpl/basics/IntrusivePointer.h @@ -58,7 +58,7 @@ concept CAdoptTag = std::is_same_v || When the strong pointer count goes to zero, the "partialDestructor" is called. This can be used to destroy as much of the object as possible while still retaining the reference counts. For example, for SHAMapInnerNodes the - children may be reset in that function. Note that std::shared_poiner WILL + children may be reset in that function. Note that std::shared_pointer WILL run the destructor when the strong count reaches zero, but may not free the memory used by the object until the weak count reaches zero. In rippled, we typically allocate shared pointers with the `make_shared` function. When diff --git a/include/xrpl/basics/Slice.h b/include/xrpl/basics/Slice.h index aa98b0a358..fba4b7733c 100644 --- a/include/xrpl/basics/Slice.h +++ b/include/xrpl/basics/Slice.h @@ -152,8 +152,8 @@ public: /** Return a "sub slice" of given length starting at the given position - Note that the subslice encompasses the range [pos, pos + rcount), - where rcount is the smaller of count and size() - pos. + Note that the subslice encompasses the range [pos, pos + rCount), + where rCount is the smaller of count and size() - pos. @param pos position of the first character @count requested length diff --git a/include/xrpl/basics/StringUtilities.h b/include/xrpl/basics/StringUtilities.h index ebe07e43bc..6314a56103 100644 --- a/include/xrpl/basics/StringUtilities.h +++ b/include/xrpl/basics/StringUtilities.h @@ -31,7 +31,7 @@ template std::optional strUnHex(std::size_t strSize, Iterator begin, Iterator end) { - static constexpr std::array const unxtab = []() { + static constexpr std::array const digitLookupTable = []() { std::array t{}; for (auto& x : t) @@ -57,7 +57,7 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end) if (strSize & 1) { - int c = unxtab[*iter++]; + int c = digitLookupTable[*iter++]; if (c < 0) return {}; @@ -67,12 +67,12 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end) while (iter != end) { - int cHigh = unxtab[*iter++]; + int cHigh = digitLookupTable[*iter++]; if (cHigh < 0) return {}; - int cLow = unxtab[*iter++]; + int cLow = digitLookupTable[*iter++]; if (cLow < 0) return {}; diff --git a/include/xrpl/beast/container/detail/aged_unordered_container.h b/include/xrpl/beast/container/detail/aged_unordered_container.h index 6807dad9f7..e2ee3b24e0 100644 --- a/include/xrpl/beast/container/detail/aged_unordered_container.h +++ b/include/xrpl/beast/container/detail/aged_unordered_container.h @@ -3189,11 +3189,12 @@ operator==(aged_unordered_container< { if (size() != other.size()) return false; - for (auto iter(cbegin()), last(cend()), olast(other.cend()); iter != last; + for (auto iter(cbegin()), last(cend()), otherLast(other.cend()); + iter != last; ++iter) { - auto oiter(other.find(extract(*iter))); - if (oiter == olast) + auto otherIter(other.find(extract(*iter))); + if (otherIter == otherLast) return false; } return true; diff --git a/include/xrpl/beast/hash/hash_append.h b/include/xrpl/beast/hash/hash_append.h index fdfedeb935..28444a1280 100644 --- a/include/xrpl/beast/hash/hash_append.h +++ b/include/xrpl/beast/hash/hash_append.h @@ -203,7 +203,7 @@ struct is_contiguously_hashable Throws: Never Effect: - Returns the reslting hash of all the input data. + Returns the resulting hash of all the input data. */ /** @{ */ diff --git a/include/xrpl/beast/utility/PropertyStream.h b/include/xrpl/beast/utility/PropertyStream.h index a5880fb8c6..de1fc567f3 100644 --- a/include/xrpl/beast/utility/PropertyStream.h +++ b/include/xrpl/beast/utility/PropertyStream.h @@ -376,7 +376,7 @@ public: print statement examples "parent.child" prints child and all of its children "parent.child." start at the parent and print down to child - "parent.grandchild" prints nothing- grandchild not direct discendent + "parent.grandchild" prints nothing- grandchild not direct descendent "parent.grandchild." starts at the parent and prints down to grandchild "parent.grandchild.*" starts at parent, print through grandchild children diff --git a/include/xrpl/json/json_value.h b/include/xrpl/json/json_value.h index 3daf441592..979e7fd788 100644 --- a/include/xrpl/json/json_value.h +++ b/include/xrpl/json/json_value.h @@ -44,7 +44,7 @@ enum ValueType { class StaticString { public: - constexpr explicit StaticString(char const* czstring) : str_(czstring) + constexpr explicit StaticString(char const* czString) : str_(czString) { } diff --git a/include/xrpl/json/json_writer.h b/include/xrpl/json/json_writer.h index 9512b17176..08e7b619b2 100644 --- a/include/xrpl/json/json_writer.h +++ b/include/xrpl/json/json_writer.h @@ -90,7 +90,7 @@ private: void writeArrayValue(Value const& value); bool - isMultineArray(Value const& value); + isMultilineArray(Value const& value); void pushValue(std::string const& value); void @@ -157,7 +157,7 @@ private: void writeArrayValue(Value const& value); bool - isMultineArray(Value const& value); + isMultilineArray(Value const& value); void pushValue(std::string const& value); void diff --git a/include/xrpl/nodestore/Manager.h b/include/xrpl/nodestore/Manager.h index fe4b1c614e..72edf2b47e 100644 --- a/include/xrpl/nodestore/Manager.h +++ b/include/xrpl/nodestore/Manager.h @@ -55,7 +55,7 @@ public: HyperLevelDB, LevelDBFactory, SQLite, MDB If the fastBackendParameter is omitted or empty, no ephemeral database - is used. If the scheduler parameter is omited or unspecified, a + is used. If the scheduler parameter is omitted or unspecified, a synchronous scheduler is used which performs all tasks immediately on the caller's thread. diff --git a/include/xrpl/protocol/IOUAmount.h b/include/xrpl/protocol/IOUAmount.h index 60a61a5825..c04cb5cf70 100644 --- a/include/xrpl/protocol/IOUAmount.h +++ b/include/xrpl/protocol/IOUAmount.h @@ -20,7 +20,7 @@ namespace xrpl { Arithmetic operations can throw std::overflow_error during normalization if the amount exceeds the largest representable amount, but underflows - will silently trunctate to zero. + will silently truncate to zero. */ class IOUAmount : private boost::totally_ordered, private boost::additive diff --git a/src/libxrpl/core/detail/LoadMonitor.cpp b/src/libxrpl/core/detail/LoadMonitor.cpp index fe2bb9e359..933fea5877 100644 --- a/src/libxrpl/core/detail/LoadMonitor.cpp +++ b/src/libxrpl/core/detail/LoadMonitor.cpp @@ -66,7 +66,7 @@ LoadMonitor::update() "Imagine if you add 10 to something every second. And you also reduce it by 1/4 every second. It will "idle" at 40, - correponding to 10 counts per second." + corresponding to 10 counts per second." */ do { diff --git a/src/libxrpl/json/json_valueiterator.cpp b/src/libxrpl/json/json_valueiterator.cpp index 7d20265af8..e9c22ac5f7 100644 --- a/src/libxrpl/json/json_valueiterator.cpp +++ b/src/libxrpl/json/json_valueiterator.cpp @@ -89,26 +89,26 @@ ValueIteratorBase::copy(SelfType const& other) Value ValueIteratorBase::key() const { - Value::CZString const czstring = (*current_).first; + Value::CZString const czString = (*current_).first; - if (czstring.c_str()) + if (czString.c_str()) { - if (czstring.isStaticString()) - return Value(StaticString(czstring.c_str())); + if (czString.isStaticString()) + return Value(StaticString(czString.c_str())); - return Value(czstring.c_str()); + return Value(czString.c_str()); } - return Value(czstring.index()); + return Value(czString.index()); } UInt ValueIteratorBase::index() const { - Value::CZString const czstring = (*current_).first; + Value::CZString const czString = (*current_).first; - if (!czstring.c_str()) - return czstring.index(); + if (!czString.c_str()) + return czString.index(); return Value::UInt(-1); } diff --git a/src/libxrpl/json/json_writer.cpp b/src/libxrpl/json/json_writer.cpp index 8983257003..25d09c511a 100644 --- a/src/libxrpl/json/json_writer.cpp +++ b/src/libxrpl/json/json_writer.cpp @@ -347,7 +347,7 @@ StyledWriter::writeArrayValue(Value const& value) pushValue("[]"); else { - bool isArrayMultiLine = isMultineArray(value); + bool isArrayMultiLine = isMultilineArray(value); if (isArrayMultiLine) { @@ -398,7 +398,7 @@ StyledWriter::writeArrayValue(Value const& value) } bool -StyledWriter::isMultineArray(Value const& value) +StyledWriter::isMultilineArray(Value const& value) { int size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; @@ -573,7 +573,7 @@ StyledStreamWriter::writeArrayValue(Value const& value) pushValue("[]"); else { - bool isArrayMultiLine = isMultineArray(value); + bool isArrayMultiLine = isMultilineArray(value); if (isArrayMultiLine) { @@ -624,7 +624,7 @@ StyledStreamWriter::writeArrayValue(Value const& value) } bool -StyledStreamWriter::isMultineArray(Value const& value) +StyledStreamWriter::isMultilineArray(Value const& value) { int size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; diff --git a/src/libxrpl/ledger/CredentialHelpers.cpp b/src/libxrpl/ledger/CredentialHelpers.cpp index a0f1dce7d8..82691238f9 100644 --- a/src/libxrpl/ledger/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/CredentialHelpers.cpp @@ -290,7 +290,7 @@ checkArray(STArray const& credentials, unsigned maxSize, beast::Journal j) if (!ins) { JLOG(j.trace()) << "Malformed transaction: " - "duplicates in credenentials."; + "duplicates in credentials."; return temMALFORMED; } } diff --git a/src/libxrpl/net/RegisterSSLCerts.cpp b/src/libxrpl/net/RegisterSSLCerts.cpp index f489cf29a3..a1321e4c61 100644 --- a/src/libxrpl/net/RegisterSSLCerts.cpp +++ b/src/libxrpl/net/RegisterSSLCerts.cpp @@ -49,11 +49,11 @@ registerSSLCerts( return; } - auto warn = [&](std::string const& mesg) { + auto warn = [&](std::string const& msg) { // Buffer based on asio recommended size char buf[256]; ::ERR_error_string_n(ec.value(), buf, sizeof(buf)); - JLOG(j.warn()) << mesg << " " << buf; + JLOG(j.warn()) << msg << " " << buf; ::ERR_clear_error(); }; diff --git a/src/libxrpl/nodestore/Database.cpp b/src/libxrpl/nodestore/Database.cpp index 41e8ac8632..9ea25785ff 100644 --- a/src/libxrpl/nodestore/Database.cpp +++ b/src/libxrpl/nodestore/Database.cpp @@ -158,7 +158,7 @@ Database::stop() << duration_cast( steady_clock::now() - start) .count() - << " millseconds"; + << " milliseconds"; } void diff --git a/src/libxrpl/protocol/BuildInfo.cpp b/src/libxrpl/protocol/BuildInfo.cpp index 65caa9ecd3..dc56987f3a 100644 --- a/src/libxrpl/protocol/BuildInfo.cpp +++ b/src/libxrpl/protocol/BuildInfo.cpp @@ -34,7 +34,7 @@ char const* const versionString = "3.2.0-b0" #endif #ifdef SANITIZER - BOOST_PP_STRINGIZE(SANITIZER) + BOOST_PP_STRINGIZE(SANITIZER) // cspell: disable-line #endif #endif diff --git a/src/libxrpl/protocol/Indexes.cpp b/src/libxrpl/protocol/Indexes.cpp index 77fcd44a3e..0bdfeefc4d 100644 --- a/src/libxrpl/protocol/Indexes.cpp +++ b/src/libxrpl/protocol/Indexes.cpp @@ -122,9 +122,9 @@ getBookBase(Book const& book) uint256 getQualityNext(uint256 const& uBase) { - static constexpr uint256 nextq( + static constexpr uint256 nextQuality( "0000000000000000000000000000000000000000000000010000000000000000"); - return uBase + nextq; + return uBase + nextQuality; } std::uint64_t diff --git a/src/xrpld/app/paths/Pathfinder.cpp b/src/xrpld/app/paths/Pathfinder.cpp index 546f3d25d9..c99467dade 100644 --- a/src/xrpld/app/paths/Pathfinder.cpp +++ b/src/xrpld/app/paths/Pathfinder.cpp @@ -40,7 +40,7 @@ final paths and the estimated cost are returned. The engine permits the search depth to be selected and the paths table includes the depth at which each path type is found. A search depth of zero causes no searching to be done. Extra paths can also be injected, and this -should be used to preserve previously-found paths across invokations for the +should be used to preserve previously-found paths across invocations for the same path request (particularly if the search depth may change). */ From 07ff532d306cb79e16376c830fad6c041af01132 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 7 Jan 2026 16:30:35 -0500 Subject: [PATCH 056/105] refactor: Fix spelling issues in all variables/functions (#6184) This change fixes many typos in comments, variables, and public functions. There is no functionality change. --- include/xrpl/json/json_reader.h | 2 +- include/xrpl/protocol/Permissions.h | 5 +- src/libxrpl/beast/net/IPAddressV4.cpp | 2 +- src/libxrpl/json/json_reader.cpp | 6 +- src/libxrpl/json/json_writer.cpp | 4 +- src/libxrpl/protocol/Permissions.cpp | 10 +- src/libxrpl/protocol/STXChainBridge.cpp | 4 +- src/libxrpl/protocol/TxFormats.cpp | 4 +- src/libxrpl/shamap/SHAMap.cpp | 2 +- src/test/app/AMMClawback_test.cpp | 2 +- src/test/app/AMMExtended_test.cpp | 22 +-- src/test/app/AMM_test.cpp | 20 +-- src/test/app/Check_test.cpp | 6 +- src/test/app/Delegate_test.cpp | 8 +- src/test/app/DeliverMin_test.cpp | 20 +-- src/test/app/EscrowToken_test.cpp | 4 +- src/test/app/Escrow_test.cpp | 4 +- src/test/app/Flow_test.cpp | 6 +- src/test/app/Invariants_test.cpp | 4 +- src/test/app/Loan_test.cpp | 2 +- src/test/app/MPToken_test.cpp | 10 +- src/test/app/MultiSign_test.cpp | 2 +- src/test/app/NetworkOPs_test.cpp | 6 +- src/test/app/Offer_test.cpp | 2 +- src/test/app/TheoreticalQuality_test.cpp | 2 +- src/test/app/TxQ_test.cpp | 4 +- src/test/app/Vault_test.cpp | 6 +- src/test/app/XChain_test.cpp | 28 ++-- src/test/app/tx/apply_test.cpp | 2 +- src/test/beast/xxhasher_test.cpp | 8 +- src/test/consensus/NegativeUNL_test.cpp | 6 +- src/test/core/Config_test.cpp | 4 +- src/test/csf/Digraph.h | 2 +- src/test/csf/Peer.h | 10 +- src/test/csf/PeerGroup.h | 2 +- src/test/jtx/Env_test.cpp | 15 +- src/test/jtx/Oracle.h | 4 +- src/test/jtx/amount.h | 2 +- src/test/jtx/delivermin.h | 4 +- src/test/jtx/impl/AMMTest.cpp | 6 +- src/test/jtx/impl/delivermin.cpp | 2 +- src/test/jtx/impl/memo.cpp | 39 +---- src/test/jtx/memo.h | 60 +------- src/test/protocol/TER_test.cpp | 30 ++-- src/test/rpc/AccountTx_test.cpp | 22 +-- src/test/rpc/Book_test.cpp | 2 +- src/test/rpc/DepositAuthorized_test.cpp | 2 +- src/test/rpc/JSONRPC_test.cpp | 138 +++++++++--------- src/test/rpc/RPCCall_test.cpp | 2 +- src/test/rpc/Simulate_test.cpp | 8 +- src/test/server/ServerStatus_test.cpp | 4 +- src/xrpld/app/ledger/detail/LedgerMaster.cpp | 2 +- src/xrpld/app/misc/FeeVoteImpl.cpp | 9 +- src/xrpld/app/misc/NetworkOPs.cpp | 8 +- src/xrpld/app/misc/SHAMapStoreImp.h | 2 +- src/xrpld/app/misc/TxQ.h | 14 +- src/xrpld/app/misc/ValidatorList.h | 4 +- src/xrpld/app/misc/detail/TxQ.cpp | 40 ++--- src/xrpld/app/misc/detail/ValidatorList.cpp | 6 +- src/xrpld/app/paths/AMMOffer.h | 8 +- src/xrpld/app/paths/PathRequest.h | 2 +- src/xrpld/app/paths/detail/AMMOffer.cpp | 10 +- src/xrpld/app/paths/detail/StrandFlow.h | 14 +- .../app/rdb/backend/detail/SQLiteDatabase.cpp | 17 ++- src/xrpld/app/tx/applySteps.h | 2 +- src/xrpld/app/tx/detail/DelegateSet.cpp | 2 +- src/xrpld/app/tx/detail/InvariantCheck.cpp | 4 +- src/xrpld/app/tx/detail/Offer.h | 18 ++- src/xrpld/app/tx/detail/OfferStream.cpp | 2 +- src/xrpld/app/tx/detail/Transactor.cpp | 2 +- src/xrpld/app/tx/detail/XChainBridge.cpp | 12 +- src/xrpld/app/tx/detail/applySteps.cpp | 16 +- src/xrpld/consensus/DisputedTx.h | 6 +- src/xrpld/consensus/Validations.h | 20 +-- src/xrpld/overlay/Message.h | 2 +- src/xrpld/overlay/Overlay.h | 2 +- src/xrpld/overlay/Slot.h | 6 +- src/xrpld/overlay/detail/OverlayImpl.cpp | 2 +- src/xrpld/overlay/detail/OverlayImpl.h | 2 +- src/xrpld/overlay/detail/PeerImp.h | 2 +- src/xrpld/overlay/detail/ProtocolMessage.h | 6 +- src/xrpld/overlay/detail/ProtocolVersion.h | 2 +- src/xrpld/overlay/detail/TxMetrics.cpp | 6 +- src/xrpld/overlay/detail/TxMetrics.h | 2 +- src/xrpld/peerfinder/detail/Livecache.h | 6 +- src/xrpld/peerfinder/detail/Logic.h | 6 +- src/xrpld/peerfinder/detail/iosformat.h | 8 +- src/xrpld/perflog/detail/PerfLogImp.cpp | 8 +- src/xrpld/rpc/detail/RPCCall.cpp | 8 +- src/xrpld/rpc/detail/RPCHelpers.cpp | 2 +- src/xrpld/rpc/detail/ServerHandler.cpp | 7 +- src/xrpld/rpc/detail/Tuning.h | 2 +- src/xrpld/rpc/handlers/AccountInfo.cpp | 6 +- src/xrpld/rpc/handlers/AccountTx.cpp | 2 +- src/xrpld/rpc/handlers/Subscribe.cpp | 2 +- 95 files changed, 400 insertions(+), 480 deletions(-) diff --git a/include/xrpl/json/json_reader.h b/include/xrpl/json/json_reader.h index 963dc0f26e..2a8ec5a3fe 100644 --- a/include/xrpl/json/json_reader.h +++ b/include/xrpl/json/json_reader.h @@ -66,7 +66,7 @@ public: * error occurred during parsing. */ std::string - getFormatedErrorMessages() const; + getFormattedErrorMessages() const; static constexpr unsigned nest_limit{25}; diff --git a/include/xrpl/protocol/Permissions.h b/include/xrpl/protocol/Permissions.h index 252605e641..319aeb1c28 100644 --- a/include/xrpl/protocol/Permissions.h +++ b/include/xrpl/protocol/Permissions.h @@ -38,7 +38,7 @@ private: std::unordered_map txFeatureMap_; - std::unordered_map delegatableTx_; + std::unordered_map delegableTx_; std::unordered_map granularPermissionMap_; @@ -71,8 +71,7 @@ public: getTxFeature(TxType txType) const; bool - isDelegatable(std::uint32_t const& permissionValue, Rules const& rules) - const; + isDelegable(std::uint32_t const& permissionValue, Rules const& rules) const; // for tx level permission, permission value is equal to tx type plus one uint32_t diff --git a/src/libxrpl/beast/net/IPAddressV4.cpp b/src/libxrpl/beast/net/IPAddressV4.cpp index b4d7181c45..fcb782133e 100644 --- a/src/libxrpl/beast/net/IPAddressV4.cpp +++ b/src/libxrpl/beast/net/IPAddressV4.cpp @@ -24,7 +24,7 @@ is_public(AddressV4 const& addr) char get_class(AddressV4 const& addr) { - static char const* table = "AAAABBCD"; + static char const* table = "AAAABBCD"; // cspell:disable-line return table[(addr.to_uint() & 0xE0000000) >> 29]; } diff --git a/src/libxrpl/json/json_reader.cpp b/src/libxrpl/json/json_reader.cpp index c0843ca929..ca0b5e5eee 100644 --- a/src/libxrpl/json/json_reader.cpp +++ b/src/libxrpl/json/json_reader.cpp @@ -241,7 +241,7 @@ Reader::readToken(Token& token) case 'f': token.type_ = tokenFalse; - ok = match("alse", 4); + ok = match("alse", 4); // cspell:disable-line break; case 'n': @@ -912,7 +912,7 @@ Reader::getLocationLineAndColumn(Location location) const } std::string -Reader::getFormatedErrorMessages() const +Reader::getFormattedErrorMessages() const { std::string formattedMessage; @@ -941,7 +941,7 @@ operator>>(std::istream& sin, Value& root) // XRPL_ASSERT(ok, "Json::operator>>() : parse succeeded"); if (!ok) - xrpl::Throw(reader.getFormatedErrorMessages()); + xrpl::Throw(reader.getFormattedErrorMessages()); return sin; } diff --git a/src/libxrpl/json/json_writer.cpp b/src/libxrpl/json/json_writer.cpp index 25d09c511a..2d0756852f 100644 --- a/src/libxrpl/json/json_writer.cpp +++ b/src/libxrpl/json/json_writer.cpp @@ -79,7 +79,7 @@ valueToString(double value) // of precision requested below. char buffer[32]; // Print into the buffer. We need not request the alternative representation - // that always has a decimal point because JSON doesn't distingish the + // that always has a decimal point because JSON doesn't distinguish the // concepts of reals and integers. #if defined(_MSC_VER) && \ defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 @@ -108,7 +108,7 @@ valueToQuotedString(char const* value) // We have to walk value and escape any special characters. // Appending to std::string is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) - unsigned maxsize = strlen(value) * 2 + 3; // allescaped+quotes+NULL + unsigned maxsize = strlen(value) * 2 + 3; // all-escaped+quotes+NULL std::string result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; diff --git a/src/libxrpl/protocol/Permissions.cpp b/src/libxrpl/protocol/Permissions.cpp index a5d447a23c..55b273e246 100644 --- a/src/libxrpl/protocol/Permissions.cpp +++ b/src/libxrpl/protocol/Permissions.cpp @@ -20,7 +20,7 @@ Permission::Permission() #pragma pop_macro("TRANSACTION") }; - delegatableTx_ = { + delegableTx_ = { #pragma push_macro("TRANSACTION") #undef TRANSACTION @@ -142,7 +142,7 @@ Permission::getTxFeature(TxType txType) const } bool -Permission::isDelegatable( +Permission::isDelegable( std::uint32_t const& permissionValue, Rules const& rules) const { @@ -153,15 +153,15 @@ Permission::isDelegatable( return true; auto const txType = permissionToTxType(permissionValue); - auto const it = delegatableTx_.find(txType); + auto const it = delegableTx_.find(txType); - if (it == delegatableTx_.end()) + if (it == delegableTx_.end()) return false; auto const txFeaturesIt = txFeatureMap_.find(txType); XRPL_ASSERT( txFeaturesIt != txFeatureMap_.end(), - "xrpl::Permissions::isDelegatable : tx exists in txFeatureMap_"); + "xrpl::Permissions::isDelegable : tx exists in txFeatureMap_"); // Delegation is only allowed if the required amendment for the transaction // is enabled. For transactions that do not require an amendment, delegation diff --git a/src/libxrpl/protocol/STXChainBridge.cpp b/src/libxrpl/protocol/STXChainBridge.cpp index 065b87558f..413094b0cd 100644 --- a/src/libxrpl/protocol/STXChainBridge.cpp +++ b/src/libxrpl/protocol/STXChainBridge.cpp @@ -65,12 +65,12 @@ STXChainBridge::STXChainBridge(SField const& name, Json::Value const& v) } auto checkExtra = [](Json::Value const& v) { - static auto const jbridge = + static auto const bridgeJson = xrpl::STXChainBridge().getJson(xrpl::JsonOptions::none); for (auto it = v.begin(); it != v.end(); ++it) { std::string const name = it.memberName(); - if (!jbridge.isMember(name)) + if (!bridgeJson.isMember(name)) { Throw( "STXChainBridge extra field detected: " + name); diff --git a/src/libxrpl/protocol/TxFormats.cpp b/src/libxrpl/protocol/TxFormats.cpp index 12f92615cd..c725c1da69 100644 --- a/src/libxrpl/protocol/TxFormats.cpp +++ b/src/libxrpl/protocol/TxFormats.cpp @@ -36,8 +36,8 @@ TxFormats::TxFormats() #undef TRANSACTION #define UNWRAP(...) __VA_ARGS__ -#define TRANSACTION( \ - tag, value, name, delegatable, amendment, privileges, fields) \ +#define TRANSACTION( \ + tag, value, name, delegable, amendment, privileges, fields) \ add(jss::name, tag, UNWRAP fields, commonFields); #include diff --git a/src/libxrpl/shamap/SHAMap.cpp b/src/libxrpl/shamap/SHAMap.cpp index 7cfa66b1ac..2a156dc2d4 100644 --- a/src/libxrpl/shamap/SHAMap.cpp +++ b/src/libxrpl/shamap/SHAMap.cpp @@ -186,7 +186,7 @@ SHAMap::finishFetch( catch (...) { JLOG(journal_.warn()) - << "finishFetch exception: unknonw exception: " << hash; + << "finishFetch exception: unknown exception: " << hash; } return {}; diff --git a/src/test/app/AMMClawback_test.cpp b/src/test/app/AMMClawback_test.cpp index e9882ef174..93fda8fe34 100644 --- a/src/test/app/AMMClawback_test.cpp +++ b/src/test/app/AMMClawback_test.cpp @@ -2043,7 +2043,7 @@ class AMMClawback_test : public beast::unit_test::suite void testSingleDepositAndClawback(FeatureBitset features) { - testcase("test single depoit and clawback"); + testcase("test single deposit and clawback"); using namespace jtx; std::string logs; diff --git a/src/test/app/AMMExtended_test.cpp b/src/test/app/AMMExtended_test.cpp index c3bfb46043..317f6cb63d 100644 --- a/src/test/app/AMMExtended_test.cpp +++ b/src/test/app/AMMExtended_test.cpp @@ -2922,29 +2922,29 @@ private: fund(env, gw, {alice, bob, carol}, XRP(10'000)); env.trust(USD(100), alice, bob, carol); env(pay(alice, bob, USD(10)), - delivermin(USD(10)), + deliver_min(USD(10)), ter(temBAD_AMOUNT)); env(pay(alice, bob, USD(10)), - delivermin(USD(-5)), + deliver_min(USD(-5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay(alice, bob, USD(10)), - delivermin(XRP(5)), + deliver_min(XRP(5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay(alice, bob, USD(10)), - delivermin(Account(carol)["USD"](5)), + deliver_min(Account(carol)["USD"](5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay(alice, bob, USD(10)), - delivermin(USD(15)), + deliver_min(USD(15)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay(gw, carol, USD(50))); AMM ammCarol(env, carol, XRP(10), USD(15)); env(pay(alice, bob, USD(10)), paths(XRP), - delivermin(USD(7)), + deliver_min(USD(7)), txflags(tfPartialPayment), sendmax(XRP(5)), ter(tecPATH_PARTIAL)); @@ -2962,7 +2962,7 @@ private: AMM ammBob(env, bob, XRP(1'000), USD(1'100)); env(pay(alice, alice, USD(10'000)), paths(XRP), - delivermin(USD(100)), + deliver_min(USD(100)), txflags(tfPartialPayment), sendmax(XRP(100))); env.require(balance(alice, USD(100))); @@ -2976,13 +2976,13 @@ private: AMM ammBob(env, bob, XRP(5'500), USD(1'200)); env(pay(alice, carol, USD(10'000)), paths(XRP), - delivermin(USD(200)), + deliver_min(USD(200)), txflags(tfPartialPayment), sendmax(XRP(1'000)), ter(tecPATH_PARTIAL)); env(pay(alice, carol, USD(10'000)), paths(XRP), - delivermin(USD(200)), + deliver_min(USD(200)), txflags(tfPartialPayment), sendmax(XRP(1'100))); BEAST_EXPECT( @@ -3005,7 +3005,7 @@ private: { env(pay(alice, carol, USD(10'000)), paths(XRP), - delivermin(USD(200)), + deliver_min(USD(200)), txflags(tfPartialPayment), sendmax(XRP(200))); env.require(balance(bob, USD(0))); @@ -3017,7 +3017,7 @@ private: { env(pay(alice, carol, USD(10'000)), paths(XRP), - delivermin(USD(200)), + deliver_min(USD(200)), txflags(tfPartialPayment), sendmax(XRPAmount(200'000'001))); env.require(balance(bob, USD(0))); diff --git a/src/test/app/AMM_test.cpp b/src/test/app/AMM_test.cpp index 8d64dfed2a..468d5b3ffd 100644 --- a/src/test/app/AMM_test.cpp +++ b/src/test/app/AMM_test.cpp @@ -831,10 +831,10 @@ private: // Tiny deposit testAMM( [&](AMM& ammAlice, Env& env) { - auto const enabledv1_3 = + auto const enabledV1_3 = env.current()->rules().enabled(fixAMMv1_3); auto const err = - !enabledv1_3 ? ter(temBAD_AMOUNT) : ter(tesSUCCESS); + !enabledV1_3 ? ter(temBAD_AMOUNT) : ter(tesSUCCESS); // Pre-amendment XRP deposit side is rounded to 0 // and deposit fails. // Post-amendment XRP deposit side is rounded to 1 @@ -2818,7 +2818,7 @@ private: BEAST_EXPECT(amm.expectAuctionSlot(100, 0, IOUAmount{0})); // gw burns all but one of its LPTokens through a bid transaction - // this transaction suceeds because the bid price is less than + // this transaction succeeds because the bid price is less than // the total outstanding LPToken balance env(amm.bid({ .account = gw, @@ -2872,7 +2872,7 @@ private: ter(temBAD_AMOUNT)); } - // Invlaid Min/Max combination + // Invalid Min/Max combination env(ammAlice.bid({ .account = carol, .bidMin = 200, @@ -3547,13 +3547,13 @@ private: { auto jtx = env.jt(tx, seq(1), fee(baseFee)); env.app().config().features.erase(featureAMM); - PreflightContext pfctx( + PreflightContext pfCtx( env.app(), *jtx.stx, env.current()->rules(), tapNONE, env.journal); - auto pf = Transactor::invokePreflight(pfctx); + auto pf = Transactor::invokePreflight(pfCtx); BEAST_EXPECT(pf == temDISABLED); env.app().config().features.insert(featureAMM); } @@ -3562,13 +3562,13 @@ private: auto jtx = env.jt(tx, seq(1), fee(baseFee)); jtx.jv["TxnSignature"] = "deadbeef"; jtx.stx = env.ust(jtx); - PreflightContext pfctx( + PreflightContext pfCtx( env.app(), *jtx.stx, env.current()->rules(), tapNONE, env.journal); - auto pf = Transactor::invokePreflight(pfctx); + auto pf = Transactor::invokePreflight(pfCtx); BEAST_EXPECT(pf != tesSUCCESS); } @@ -3577,13 +3577,13 @@ private: jtx.jv["Asset2"]["currency"] = "XRP"; jtx.jv["Asset2"].removeMember("issuer"); jtx.stx = env.ust(jtx); - PreflightContext pfctx( + PreflightContext pfCtx( env.app(), *jtx.stx, env.current()->rules(), tapNONE, env.journal); - auto pf = Transactor::invokePreflight(pfctx); + auto pf = Transactor::invokePreflight(pfCtx); BEAST_EXPECT(pf == temBAD_AMM_TOKENS); } } diff --git a/src/test/app/Check_test.cpp b/src/test/app/Check_test.cpp index b3d8249dd0..8eccdc4824 100644 --- a/src/test/app/Check_test.cpp +++ b/src/test/app/Check_test.cpp @@ -11,18 +11,18 @@ namespace jtx { class expiration { private: - std::uint32_t const expry_; + std::uint32_t const expiry_; public: explicit expiration(NetClock::time_point const& expiry) - : expry_{expiry.time_since_epoch().count()} + : expiry_{expiry.time_since_epoch().count()} { } void operator()(Env&, JTx& jt) const { - jt[sfExpiration.jsonName] = expry_; + jt[sfExpiration.jsonName] = expiry_; } }; diff --git a/src/test/app/Delegate_test.cpp b/src/test/app/Delegate_test.cpp index 7d58093e43..4039f60ef0 100644 --- a/src/test/app/Delegate_test.cpp +++ b/src/test/app/Delegate_test.cpp @@ -203,7 +203,7 @@ class Delegate_test : public beast::unit_test::suite ter(tecNO_TARGET)); } - // non-delegatable transaction + // non-delegable transaction { env(delegate::set(gw, alice, {"SetRegularKey"}), ter(temMALFORMED)); env(delegate::set(gw, alice, {"AccountSet"}), ter(temMALFORMED)); @@ -1693,13 +1693,13 @@ class Delegate_test : public beast::unit_test::suite } void - testTxReqireFeatures(FeatureBitset features) + testTxRequireFeatures(FeatureBitset features) { testcase("test delegate disabled tx"); using namespace jtx; // map of tx and required feature. - // non-delegatable tx are not included. + // non-delegable tx are not included. // NFTokenMint, NFTokenBurn, NFTokenCreateOffer, NFTokenCancelOffer, // NFTokenAcceptOffer are not included, they are tested separately. std::unordered_map txRequiredFeatures{ @@ -1803,7 +1803,7 @@ class Delegate_test : public beast::unit_test::suite testMultiSign(); testMultiSignQuorumNotMet(); testPermissionValue(all); - testTxReqireFeatures(all); + testTxRequireFeatures(all); } }; BEAST_DEFINE_TESTSUITE(Delegate, app, xrpl); diff --git a/src/test/app/DeliverMin_test.cpp b/src/test/app/DeliverMin_test.cpp index 4d643dfae1..c49f83b518 100644 --- a/src/test/app/DeliverMin_test.cpp +++ b/src/test/app/DeliverMin_test.cpp @@ -25,29 +25,29 @@ public: env.trust(USD(100), "alice", "bob", "carol"); env.close(); env(pay("alice", "bob", USD(10)), - delivermin(USD(10)), + deliver_min(USD(10)), ter(temBAD_AMOUNT)); env(pay("alice", "bob", USD(10)), - delivermin(USD(-5)), + deliver_min(USD(-5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay("alice", "bob", USD(10)), - delivermin(XRP(5)), + deliver_min(XRP(5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay("alice", "bob", USD(10)), - delivermin(Account("carol")["USD"](5)), + deliver_min(Account("carol")["USD"](5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay("alice", "bob", USD(10)), - delivermin(USD(15)), + deliver_min(USD(15)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay(gw, "carol", USD(50))); env(offer("carol", XRP(5), USD(5))); env(pay("alice", "bob", USD(10)), paths(XRP), - delivermin(USD(7)), + deliver_min(USD(7)), txflags(tfPartialPayment), sendmax(XRP(5)), ter(tecPATH_PARTIAL)); @@ -66,7 +66,7 @@ public: env(offer("bob", XRP(100), USD(100))); env(pay("alice", "alice", USD(10000)), paths(XRP), - delivermin(USD(100)), + deliver_min(USD(100)), txflags(tfPartialPayment), sendmax(XRP(100))); env.require(balance("alice", USD(100))); @@ -84,13 +84,13 @@ public: env(offer("bob", XRP(10000), USD(100))); env(pay("alice", "carol", USD(10000)), paths(XRP), - delivermin(USD(200)), + deliver_min(USD(200)), txflags(tfPartialPayment), sendmax(XRP(1000)), ter(tecPATH_PARTIAL)); env(pay("alice", "carol", USD(10000)), paths(XRP), - delivermin(USD(200)), + deliver_min(USD(200)), txflags(tfPartialPayment), sendmax(XRP(1100))); env.require(balance("bob", USD(0))); @@ -110,7 +110,7 @@ public: env(offer("dan", XRP(100), USD(100))); env(pay("alice", "carol", USD(10000)), paths(XRP), - delivermin(USD(200)), + deliver_min(USD(200)), txflags(tfPartialPayment), sendmax(XRP(200))); env.require(balance("bob", USD(0))); diff --git a/src/test/app/EscrowToken_test.cpp b/src/test/app/EscrowToken_test.cpp index ff8b2cfb49..955ca8f449 100644 --- a/src/test/app/EscrowToken_test.cpp +++ b/src/test/app/EscrowToken_test.cpp @@ -1591,7 +1591,7 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(bob, USD) == USD(10125)); } - // test cancel doesnt charge rate + // test cancel doesn't charge rate { Env env{*this, features}; auto const baseFee = env.current()->fees().base; @@ -1986,7 +1986,7 @@ struct EscrowToken_test : public beast::unit_test::suite void testIOUINSF(FeatureBitset features) { - testcase("IOU Insuficient Funds"); + testcase("IOU Insufficient Funds"); using namespace test::jtx; using namespace std::literals; diff --git a/src/test/app/Escrow_test.cpp b/src/test/app/Escrow_test.cpp index 25bb03858e..2b7297009a 100644 --- a/src/test/app/Escrow_test.cpp +++ b/src/test/app/Escrow_test.cpp @@ -1614,12 +1614,12 @@ struct Escrow_test : public beast::unit_test::suite env.close(); env.close(); - // Succeed, Bob doesn't require preauthorization + // Succeed, Bob doesn't require pre-authorization env(escrow::finish(carol, alice, seq), credentials::ids({credIdx})); env.close(); { - char const credType2[] = "fghijk"; + char const credType2[] = "random"; env(credentials::create(bob, zelda, credType2)); env.close(); diff --git a/src/test/app/Flow_test.cpp b/src/test/app/Flow_test.cpp index e16a48e02f..8c5a9615fa 100644 --- a/src/test/app/Flow_test.cpp +++ b/src/test/app/Flow_test.cpp @@ -952,9 +952,9 @@ struct Flow_test : public beast::unit_test::suite } void - testReexecuteDirectStep(FeatureBitset features) + testReExecuteDirectStep(FeatureBitset features) { - testcase("ReexecuteDirectStep"); + testcase("ReExecuteDirectStep"); using namespace jtx; Env env(*this, features); @@ -1291,7 +1291,7 @@ struct Flow_test : public beast::unit_test::suite testSelfFundedXRPEndpoint(false, features); testSelfFundedXRPEndpoint(true, features); testUnfundedOffer(features); - testReexecuteDirectStep(features); + testReExecuteDirectStep(features); testSelfPayLowQualityOffer(features); testTicketPay(features); } diff --git a/src/test/app/Invariants_test.cpp b/src/test/app/Invariants_test.cpp index 61b4e7ba76..9f70538778 100644 --- a/src/test/app/Invariants_test.cpp +++ b/src/test/app/Invariants_test.cpp @@ -1862,7 +1862,7 @@ class Invariants_test : public beast::unit_test::suite for (auto const& mod : mods) { doInvariantCheck( - {{"changed an unchangable field"}}, + {{"changed an unchangeable field"}}, [&](Account const& A1, Account const&, ApplyContext& ac) { auto sle = ac.view().peek(loanBrokerKeylet); if (!sle) @@ -1892,7 +1892,7 @@ class Invariants_test : public beast::unit_test::suite for (auto const& mod : mods) { doInvariantCheck( - {{"changed an unchangable field"}}, + {{"changed an unchangeable field"}}, [&](Account const& A1, Account const&, ApplyContext& ac) { auto sle = ac.view().peek(keylet::account(A1.id())); if (!sle) diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index 22159ba4bb..7c2e83aa19 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -2913,7 +2913,7 @@ protected: /* LoanPay fails with tecINVARIANT_FAILED error when loan_broker(also - borrower) tries to do the payment. Here's the sceanrio: Create a XRP + borrower) tries to do the payment. Here's the scenario: Create a XRP loan with loan broker as borrower, loan origination fee and loan service fee. Loan broker makes the first payment with periodic payment and loan service fee. diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index 62531f2b8f..ed6d861ffb 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -975,7 +975,7 @@ class MPToken_test : public beast::unit_test::suite sendmax(XRP(100)), ter(temMALFORMED)); env(pay(alice, carol, MPT(100)), - delivermin(XRP(100)), + deliver_min(XRP(100)), ter(temBAD_AMOUNT)); // sendMax MPT is invalid with IOU or XRP auto const USD = alice["USD"]; @@ -986,10 +986,10 @@ class MPToken_test : public beast::unit_test::suite sendmax(MPT(100)), ter(temMALFORMED)); env(pay(alice, carol, USD(100)), - delivermin(MPT(100)), + deliver_min(MPT(100)), ter(temBAD_AMOUNT)); env(pay(alice, carol, XRP(100)), - delivermin(MPT(100)), + deliver_min(MPT(100)), ter(temBAD_AMOUNT)); // sendmax and amount are different MPT issue test::jtx::MPT const MPT1( @@ -1535,13 +1535,13 @@ class MPToken_test : public beast::unit_test::suite // deliver amount < deliverMin env(pay(bob, alice, MPT(100)), sendmax(MPT(99)), - delivermin(MPT(100)), + deliver_min(MPT(100)), txflags(tfPartialPayment), ter(tecPATH_PARTIAL)); // Payment succeeds if deliver amount >= deliverMin env(pay(bob, alice, MPT(100)), sendmax(MPT(99)), - delivermin(MPT(99)), + deliver_min(MPT(99)), txflags(tfPartialPayment)); } diff --git a/src/test/app/MultiSign_test.cpp b/src/test/app/MultiSign_test.cpp index 6e30ed9c13..6950286b52 100644 --- a/src/test/app/MultiSign_test.cpp +++ b/src/test/app/MultiSign_test.cpp @@ -708,7 +708,7 @@ public: void testHeterogeneousSigners(FeatureBitset features) { - testcase("Heterogenious Signers"); + testcase("Heterogenous Signers"); using namespace jtx; Env env{*this, features}; diff --git a/src/test/app/NetworkOPs_test.cpp b/src/test/app/NetworkOPs_test.cpp index d5616009fa..582f9a8084 100644 --- a/src/test/app/NetworkOPs_test.cpp +++ b/src/test/app/NetworkOPs_test.cpp @@ -38,14 +38,14 @@ public: auto const jtx = env.jt(ticket::create(alice, 1), seq(1), fee(10)); - auto transacionId = jtx.stx->getTransactionID(); + auto transactionId = jtx.stx->getTransactionID(); env.app().getHashRouter().setFlags( - transacionId, HashRouterFlags::HELD); + transactionId, HashRouterFlags::HELD); env(jtx, json(jss::Sequence, 1), ter(terNO_ACCOUNT)); env.app().getHashRouter().setFlags( - transacionId, HashRouterFlags::BAD); + transactionId, HashRouterFlags::BAD); env.close(); } diff --git a/src/test/app/Offer_test.cpp b/src/test/app/Offer_test.cpp index 46a2cabec1..f1d68ece1e 100644 --- a/src/test/app/Offer_test.cpp +++ b/src/test/app/Offer_test.cpp @@ -2290,7 +2290,7 @@ public: // clang-format off TestData const tests[]{ - // acct fundXrp bookAmt preTrust offerAmt tec spentXrp balanceUSD offers owners + // acct fundXrp bookAmt preTrust offerAmount tec spentXrp balanceUSD offers owners {"ann", reserve(env, 0) + 0 * f, 1, noPreTrust, 1000, tecUNFUNDED_OFFER, f, USD( 0), 0, 0}, // Account is at the reserve, and will dip below once fees are subtracted. {"bev", reserve(env, 0) + 1 * f, 1, noPreTrust, 1000, tecUNFUNDED_OFFER, f, USD( 0), 0, 0}, // Account has just enough for the reserve and the fee. {"cam", reserve(env, 0) + 2 * f, 0, noPreTrust, 1000, tecINSUF_RESERVE_OFFER, f, USD( 0), 0, 0}, // Account has enough for the reserve, the fee and the offer, and a bit more, but not enough for the reserve after the offer is placed. diff --git a/src/test/app/TheoreticalQuality_test.cpp b/src/test/app/TheoreticalQuality_test.cpp index 5cc03247ae..ed4a62c4b0 100644 --- a/src/test/app/TheoreticalQuality_test.cpp +++ b/src/test/app/TheoreticalQuality_test.cpp @@ -277,7 +277,7 @@ class TheoreticalQuality_test : public beast::unit_test::suite if (actualQ != theoreticalQ && !compareClose(actualQ, theoreticalQ)) { BEAST_EXPECT(actualQ == theoreticalQ); // get the failure - log << "\nAcutal != Theoretical\n"; + log << "\nActual != Theoretical\n"; log << "\nTQ: " << prettyQuality(theoreticalQ) << "\n"; log << "AQ: " << prettyQuality(actualQ) << "\n"; logStrand(log, strand); diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index f6ab13e04f..9489bb7f04 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -4311,7 +4311,7 @@ public: } void - testReexecutePreflight() + testReExecutePreflight() { // The TxQ caches preflight results. But there are situations where // that cache must become invalidated, like if amendments change. @@ -5036,7 +5036,7 @@ public: testScaling(); testInLedgerSeq(); testInLedgerTicket(); - testReexecutePreflight(); + testReExecutePreflight(); testQueueFullDropPenalty(); testCancelQueuedOffers(); testZeroReferenceFee(); diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index fbe87ccb5d..f8d76623fd 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -1517,7 +1517,7 @@ class Vault_test : public beast::unit_test::suite auto const [asset1, asset2] = std::pair(XRP(10000), USD(10000)); - auto tofund = [&](STAmount const& a) -> STAmount { + auto toFund = [&](STAmount const& a) -> STAmount { if (a.native()) { auto const defXRP = XRP(30000); @@ -1530,8 +1530,8 @@ class Vault_test : public beast::unit_test::suite return defIOU; return a + STAmount{a.issue(), 1000}; }; - auto const toFund1 = tofund(asset1); - auto const toFund2 = tofund(asset2); + auto const toFund1 = toFund(asset1); + auto const toFund2 = toFund(asset2); BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2); if (!asset1.native() && !asset2.native()) diff --git a/src/test/app/XChain_test.cpp b/src/test/app/XChain_test.cpp index 619054b078..3b09845723 100644 --- a/src/test/app/XChain_test.cpp +++ b/src/test/app/XChain_test.cpp @@ -247,7 +247,7 @@ struct BalanceTransfer balance from_; balance to_; - balance payor_; // pays the rewards + balance payer_; // pays the rewards std::vector reward_accounts; // receives the reward XRPAmount txFees_; @@ -255,13 +255,13 @@ struct BalanceTransfer T& env, jtx::Account const& from_acct, jtx::Account const& to_acct, - jtx::Account const& payor, + jtx::Account const& payer, jtx::Account const* payees, size_t num_payees, bool withClaim) : from_(env, from_acct) , to_(env, to_acct) - , payor_(env, payor) + , payer_(env, payer) , reward_accounts([&]() { std::vector r; r.reserve(num_payees); @@ -277,14 +277,14 @@ struct BalanceTransfer T& env, jtx::Account const& from_acct, jtx::Account const& to_acct, - jtx::Account const& payor, + jtx::Account const& payer, std::vector const& payees, bool withClaim) : BalanceTransfer( env, from_acct, to_acct, - payor, + payer, &payees[0], payees.size(), withClaim) @@ -316,14 +316,14 @@ struct BalanceTransfer auto reward_cost = multiply(reward, STAmount(reward_accounts.size()), reward.issue()); return check_most_balances(amt, reward) && - (!check_payer || payor_.diff() == -(reward_cost + txFees_)); + (!check_payer || payer_.diff() == -(reward_cost + txFees_)); } bool has_not_happened() { return check_most_balances(STAmount(0), STAmount(0)) && - payor_.diff() <= txFees_; // could have paid fee for failed claim + payer_.diff() <= txFees_; // could have paid fee for failed claim } }; @@ -592,7 +592,7 @@ struct XChain_test : public beast::unit_test::suite, auto CEUR = C["EUR"]; auto GEUR = scGw["EUR"]; - // Accounts to own single brdiges + // Accounts to own single bridges Account const a1("a1"); Account const a2("a2"); Account const a3("a3"); @@ -2566,7 +2566,7 @@ struct XChain_test : public beast::unit_test::suite, } { // --B5: missing sfAttestationSignerAccount field - // Then submit the one with the field. Should rearch quorum. + // Then submit the one with the field. Should reach quorum. auto att = claim_attestation( scAttester, jvb, @@ -3825,7 +3825,7 @@ struct XChain_test : public beast::unit_test::suite, } // this also checks that only 3 * split_reward was deducted from - // scAlice (the payor account), since we passed alt_payees to + // scAlice (the payer account), since we passed alt_payees to // BalanceTransfer BEAST_EXPECT(transfer.has_happened(amt, split_reward_quorum)); } @@ -3884,7 +3884,7 @@ struct XChain_test : public beast::unit_test::suite, } // this also checks that only 3 * split_reward was deducted from - // scAlice (the payor account), since we passed payees.size() - + // scAlice (the payer account), since we passed payees.size() - // 1 to BalanceTransfer BEAST_EXPECT(transfer.has_happened(amt, split_reward_quorum)); @@ -4548,7 +4548,7 @@ private: enum SmState { st_initial, - st_claimid_created, + st_claim_id_created, st_attesting, st_attested, st_completed, @@ -4864,10 +4864,10 @@ private: { case st_initial: xfer.claim_id = create_claim_id(); - sm_state = st_claimid_created; + sm_state = st_claim_id_created; break; - case st_claimid_created: + case st_claim_id_created: commit(); sm_state = st_attesting; break; diff --git a/src/test/app/tx/apply_test.cpp b/src/test/app/tx/apply_test.cpp index 0b198dcd22..6f9473ce69 100644 --- a/src/test/app/tx/apply_test.cpp +++ b/src/test/app/tx/apply_test.cpp @@ -15,7 +15,7 @@ public: void run() override { - testcase("Require Fully Canonicial Signature"); + testcase("Require Fully Canonical Signature"); testFullyCanonicalSigs(); } diff --git a/src/test/beast/xxhasher_test.cpp b/src/test/beast/xxhasher_test.cpp index 7456fc73c4..f740bf0821 100644 --- a/src/test/beast/xxhasher_test.cpp +++ b/src/test/beast/xxhasher_test.cpp @@ -52,7 +52,7 @@ public: } void - testBigObjectWithMultiupleSmallUpdatesWithoutSeed() + testBigObjectWithMultipleSmallUpdatesWithoutSeed() { testcase("Big object with multiple small updates without seed"); xxhasher hasher{}; @@ -69,7 +69,7 @@ public: } void - testBigObjectWithMultiupleSmallUpdatesWithSeed() + testBigObjectWithMultipleSmallUpdatesWithSeed() { testcase("Big object with multiple small updates with seed"); xxhasher hasher{static_cast(103)}; @@ -199,8 +199,8 @@ public: testWithoutSeed(); testWithSeed(); testWithTwoSeeds(); - testBigObjectWithMultiupleSmallUpdatesWithoutSeed(); - testBigObjectWithMultiupleSmallUpdatesWithSeed(); + testBigObjectWithMultipleSmallUpdatesWithoutSeed(); + testBigObjectWithMultipleSmallUpdatesWithSeed(); testBigObjectWithSmallAndBigUpdatesWithoutSeed(); testBigObjectWithSmallAndBigUpdatesWithSeed(); testBigObjectWithOneUpdateWithoutSeed(); diff --git a/src/test/consensus/NegativeUNL_test.cpp b/src/test/consensus/NegativeUNL_test.cpp index e10d6cbdd0..535aec03bf 100644 --- a/src/test/consensus/NegativeUNL_test.cpp +++ b/src/test/consensus/NegativeUNL_test.cpp @@ -25,7 +25,7 @@ namespace test { /** * Test the size of the negative UNL in a ledger, - * also test if the ledger has ToDisalbe and/or ToReEnable + * also test if the ledger has ToDisable and/or ToReEnable * * @param l the ledger * @param size the expected negative UNL size @@ -553,11 +553,11 @@ struct NetworkHistory bool createLedgerHistory() { - static uint256 fake_amemdment; // So we have different genesis ledgers + static uint256 fake_amendment; // So we have different genesis ledgers auto l = std::make_shared( create_genesis, env.app().config(), - std::vector{fake_amemdment++}, + std::vector{fake_amendment++}, env.app().getNodeFamily()); history.push_back(l); diff --git a/src/test/core/Config_test.cpp b/src/test/core/Config_test.cpp index 139e8702eb..d6ec875982 100644 --- a/src/test/core/Config_test.cpp +++ b/src/test/core/Config_test.cpp @@ -206,8 +206,8 @@ nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8 nHUPDdcdb2Y5DZAJne4c2iabFuAP3F34xZUgYQT2NH7qfkdapgnz [validator_list_sites] -recommendedxrplvalidators.com -morexrplvalidators.net +recommended-xrpl-validators.com +more-xrpl-validators.net [validator_list_keys] 03E74EE14CB525AFBB9F1B7D86CD58ECC4B91452294B42AB4E78F260BD905C091D diff --git a/src/test/csf/Digraph.h b/src/test/csf/Digraph.h index 688d0528d3..a283f2f7cc 100644 --- a/src/test/csf/Digraph.h +++ b/src/test/csf/Digraph.h @@ -199,7 +199,7 @@ public: Save a GraphViz dot description of the graph @param fileName The output file (creates) - @param vertexName A invokable T vertexName(Vertex const &) that + @param vertexName A invocable T vertexName(Vertex const &) that returns the name target use for the vertex in the file T must be ostream-able */ diff --git a/src/test/csf/Peer.h b/src/test/csf/Peer.h index b2a0c3b3ed..b86991ba5f 100644 --- a/src/test/csf/Peer.h +++ b/src/test/csf/Peer.h @@ -722,7 +722,7 @@ struct Peer template struct BroadcastMesg { - M mesg; + M msg; std::size_t seq; PeerID origin; }; @@ -748,7 +748,7 @@ struct Peer // used on the other end if (link.target->router.lastObservedSeq[bm.origin] < bm.seq) { - issue(Relay{link.target->id, bm.mesg}); + issue(Relay{link.target->id, bm.msg}); net.send( this, link.target, @@ -765,12 +765,12 @@ struct Peer void receive(BroadcastMesg const& bm, PeerID from) { - issue(Receive{from, bm.mesg}); + issue(Receive{from, bm.msg}); if (router.lastObservedSeq[bm.origin] < bm.seq) { router.lastObservedSeq[bm.origin] = bm.seq; - schedule(delays.onReceive(bm.mesg), [this, bm, from] { - if (handle(bm.mesg)) + schedule(delays.onReceive(bm.msg), [this, bm, from] { + if (handle(bm.msg)) send(bm, from); }); } diff --git a/src/test/csf/PeerGroup.h b/src/test/csf/PeerGroup.h index e674581546..8a215eaf8d 100644 --- a/src/test/csf/PeerGroup.h +++ b/src/test/csf/PeerGroup.h @@ -193,7 +193,7 @@ public: /** Establish network connections based on trust relations For each peers in this group, create outbound network connection - to the set of peers it trusts. If a coonnection already exists, it is + to the set of peers it trusts. If a connection already exists, it is not recreated. @param delay The fixed messaging delay for all established connections diff --git a/src/test/jtx/Env_test.cpp b/src/test/jtx/Env_test.cpp index ba5a2ee8c5..fbe51c2a8d 100644 --- a/src/test/jtx/Env_test.cpp +++ b/src/test/jtx/Env_test.cpp @@ -33,7 +33,7 @@ public: { using namespace jtx; { - Account a("chenna"); + Account a("chad"); Account b(a); a = b; a = std::move(b); @@ -162,8 +162,8 @@ public: // flags env.fund(n, noripple("xavier")); env.require(nflags("xavier", asfDefaultRipple)); - env.fund(n, "yana"); - env.require(flags("yana", asfDefaultRipple)); + env.fund(n, "zachary"); + env.require(flags("zachary", asfDefaultRipple)); } // trust @@ -596,12 +596,9 @@ public: using namespace jtx; Env env(*this); env.fund(XRP(10000), "alice"); - env(noop("alice"), memodata("data")); - env(noop("alice"), memoformat("format")); - env(noop("alice"), memotype("type")); - env(noop("alice"), memondata("format", "type")); - env(noop("alice"), memonformat("data", "type")); - env(noop("alice"), memontype("data", "format")); + env(noop("alice"), memo_data("data")); + env(noop("alice"), memo_format("format")); + env(noop("alice"), memo_type("type")); env(noop("alice"), memo("data", "format", "type")); env(noop("alice"), memo("data1", "format1", "type1"), diff --git a/src/test/jtx/Oracle.h b/src/test/jtx/Oracle.h index fc7dc89cd1..17d72384f6 100644 --- a/src/test/jtx/Oracle.h +++ b/src/test/jtx/Oracle.h @@ -132,7 +132,7 @@ public: std::optional const& quoteAsset, std::optional const& oracles = std::nullopt, std::optional const& trim = std::nullopt, - std::optional const& timeTreshold = std::nullopt); + std::optional const& timeThreshold = std::nullopt); std::uint32_t documentID() const @@ -150,7 +150,7 @@ public: exists(Env& env, AccountID const& account, std::uint32_t documentID); [[nodiscard]] bool - expectPrice(DataSeries const& pricess) const; + expectPrice(DataSeries const& prices) const; [[nodiscard]] bool expectLastUpdateTime(std::uint32_t lastUpdateTime) const; diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index faf70921be..a310fc5b44 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -277,7 +277,7 @@ struct XRP_t } /** Returns an amount of XRP as PrettyAmount, - which is trivially convertable to STAmount + which is trivially convertible to STAmount @param v The Number of XRP (not drops). May be fractional. */ diff --git a/src/test/jtx/delivermin.h b/src/test/jtx/delivermin.h index 70f092c9dc..033b3f20b8 100644 --- a/src/test/jtx/delivermin.h +++ b/src/test/jtx/delivermin.h @@ -10,13 +10,13 @@ namespace test { namespace jtx { /** Sets the DeliverMin on a JTx. */ -class delivermin +class deliver_min { private: STAmount amount_; public: - delivermin(STAmount const& amount) : amount_(amount) + deliver_min(STAmount const& amount) : amount_(amount) { } diff --git a/src/test/jtx/impl/AMMTest.cpp b/src/test/jtx/impl/AMMTest.cpp index 790762d3df..de7ce5504b 100644 --- a/src/test/jtx/impl/AMMTest.cpp +++ b/src/test/jtx/impl/AMMTest.cpp @@ -112,7 +112,7 @@ AMMTestBase::testAMM( auto const [asset1, asset2] = arg.pool ? *arg.pool : std::make_pair(XRP(10000), USD(10000)); - auto tofund = [&](STAmount const& a) -> STAmount { + auto toFund = [&](STAmount const& a) -> STAmount { if (a.native()) { auto const defXRP = XRP(30000); @@ -125,8 +125,8 @@ AMMTestBase::testAMM( return defIOU; return a + STAmount{a.issue(), 1000}; }; - auto const toFund1 = tofund(asset1); - auto const toFund2 = tofund(asset2); + auto const toFund1 = toFund(asset1); + auto const toFund2 = toFund(asset2); BEAST_EXPECT(asset1 <= toFund1 && asset2 <= toFund2); if (!asset1.native() && !asset2.native()) diff --git a/src/test/jtx/impl/delivermin.cpp b/src/test/jtx/impl/delivermin.cpp index 5ad98edd09..a5c1414525 100644 --- a/src/test/jtx/impl/delivermin.cpp +++ b/src/test/jtx/impl/delivermin.cpp @@ -7,7 +7,7 @@ namespace test { namespace jtx { void -delivermin::operator()(Env& env, JTx& jt) const +deliver_min::operator()(Env& env, JTx& jt) const { jt.jv[jss::DeliverMin] = amount_.getJson(JsonOptions::none); } diff --git a/src/test/jtx/impl/memo.cpp b/src/test/jtx/impl/memo.cpp index c815b916d7..e503b9a073 100644 --- a/src/test/jtx/impl/memo.cpp +++ b/src/test/jtx/impl/memo.cpp @@ -17,7 +17,7 @@ memo::operator()(Env&, JTx& jt) const } void -memodata::operator()(Env&, JTx& jt) const +memo_data::operator()(Env&, JTx& jt) const { auto& jv = jt.jv; auto& ma = jv["Memos"]; @@ -27,7 +27,7 @@ memodata::operator()(Env&, JTx& jt) const } void -memoformat::operator()(Env&, JTx& jt) const +memo_format::operator()(Env&, JTx& jt) const { auto& jv = jt.jv; auto& ma = jv["Memos"]; @@ -37,7 +37,7 @@ memoformat::operator()(Env&, JTx& jt) const } void -memotype::operator()(Env&, JTx& jt) const +memo_type::operator()(Env&, JTx& jt) const { auto& jv = jt.jv; auto& ma = jv["Memos"]; @@ -46,39 +46,6 @@ memotype::operator()(Env&, JTx& jt) const m["MemoType"] = strHex(s_); } -void -memondata::operator()(Env&, JTx& jt) const -{ - auto& jv = jt.jv; - auto& ma = jv["Memos"]; - auto& mi = ma[ma.size()]; - auto& m = mi["Memo"]; - m["MemoFormat"] = strHex(format_); - m["MemoType"] = strHex(type_); -} - -void -memonformat::operator()(Env&, JTx& jt) const -{ - auto& jv = jt.jv; - auto& ma = jv["Memos"]; - auto& mi = ma[ma.size()]; - auto& m = mi["Memo"]; - m["MemoData"] = strHex(data_); - m["MemoType"] = strHex(type_); -} - -void -memontype::operator()(Env&, JTx& jt) const -{ - auto& jv = jt.jv; - auto& ma = jv["Memos"]; - auto& mi = ma[ma.size()]; - auto& m = mi["Memo"]; - m["MemoData"] = strHex(data_); - m["MemoFormat"] = strHex(format_); -} - } // namespace jtx } // namespace test } // namespace xrpl diff --git a/src/test/jtx/memo.h b/src/test/jtx/memo.h index 377dcbec4e..2506f063fc 100644 --- a/src/test/jtx/memo.h +++ b/src/test/jtx/memo.h @@ -32,13 +32,13 @@ public: operator()(Env&, JTx& jt) const; }; -class memodata +class memo_data { private: std::string s_; public: - memodata(std::string const& s) : s_(s) + memo_data(std::string const& s) : s_(s) { } @@ -46,13 +46,13 @@ public: operator()(Env&, JTx& jt) const; }; -class memoformat +class memo_format { private: std::string s_; public: - memoformat(std::string const& s) : s_(s) + memo_format(std::string const& s) : s_(s) { } @@ -60,61 +60,13 @@ public: operator()(Env&, JTx& jt) const; }; -class memotype +class memo_type { private: std::string s_; public: - memotype(std::string const& s) : s_(s) - { - } - - void - operator()(Env&, JTx& jt) const; -}; - -class memondata -{ -private: - std::string format_; - std::string type_; - -public: - memondata(std::string const& format, std::string const& type) - : format_(format), type_(type) - { - } - - void - operator()(Env&, JTx& jt) const; -}; - -class memonformat -{ -private: - std::string data_; - std::string type_; - -public: - memonformat(std::string const& data, std::string const& type) - : data_(data), type_(type) - { - } - - void - operator()(Env&, JTx& jt) const; -}; - -class memontype -{ -private: - std::string data_; - std::string format_; - -public: - memontype(std::string const& data, std::string const& format) - : data_(data), format_(format) + memo_type(std::string const& s) : s_(s) { } diff --git a/src/test/protocol/TER_test.cpp b/src/test/protocol/TER_test.cpp index 0d9c6cb96d..56b3b08051 100644 --- a/src/test/protocol/TER_test.cpp +++ b/src/test/protocol/TER_test.cpp @@ -137,7 +137,7 @@ struct TER_test : public beast::unit_test::suite testIterate(terEnums, *this); // Lambda that verifies assignability and convertibility. - auto isConvertable = [](auto from, auto to) { + auto isConvertible = [](auto from, auto to) { using From_t = std::decay_t; using To_t = std::decay_t; static_assert( @@ -150,12 +150,12 @@ struct TER_test : public beast::unit_test::suite // Verify the right types convert to NotTEC. NotTEC const notTec; - isConvertable(telLOCAL_ERROR, notTec); - isConvertable(temMALFORMED, notTec); - isConvertable(tefFAILURE, notTec); - isConvertable(terRETRY, notTec); - isConvertable(tesSUCCESS, notTec); - isConvertable(notTec, notTec); + isConvertible(telLOCAL_ERROR, notTec); + isConvertible(temMALFORMED, notTec); + isConvertible(tefFAILURE, notTec); + isConvertible(terRETRY, notTec); + isConvertible(tesSUCCESS, notTec); + isConvertible(notTec, notTec); // Lambda that verifies types and not assignable or convertible. auto notConvertible = [](auto from, auto to) { @@ -176,14 +176,14 @@ struct TER_test : public beast::unit_test::suite notConvertible(4, notTec); // Verify the right types convert to TER. - isConvertable(telLOCAL_ERROR, ter); - isConvertable(temMALFORMED, ter); - isConvertable(tefFAILURE, ter); - isConvertable(terRETRY, ter); - isConvertable(tesSUCCESS, ter); - isConvertable(tecCLAIM, ter); - isConvertable(notTec, ter); - isConvertable(ter, ter); + isConvertible(telLOCAL_ERROR, ter); + isConvertible(temMALFORMED, ter); + isConvertible(tefFAILURE, ter); + isConvertible(terRETRY, ter); + isConvertible(tesSUCCESS, ter); + isConvertible(tecCLAIM, ter); + isConvertible(notTec, ter); + isConvertible(ter, ter); // Verify that you can't convert from int to ter. notConvertible(4, ter); diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp index e387e1bc4c..36d29236d1 100644 --- a/src/test/rpc/AccountTx_test.cpp +++ b/src/test/rpc/AccountTx_test.cpp @@ -551,12 +551,12 @@ class AccountTx_test : public beast::unit_test::suite auto escrow = [](Account const& account, Account const& to, STAmount const& amount) { - Json::Value escro; - escro[jss::TransactionType] = jss::EscrowCreate; - escro[jss::Account] = account.human(); - escro[jss::Destination] = to.human(); - escro[jss::Amount] = amount.getJson(JsonOptions::none); - return escro; + Json::Value escrow; + escrow[jss::TransactionType] = jss::EscrowCreate; + escrow[jss::Account] = account.human(); + escrow[jss::Destination] = to.human(); + escrow[jss::Amount] = amount.getJson(JsonOptions::none); + return escrow; }; NetClock::time_point const nextTime{env.now() + 2s}; @@ -651,7 +651,7 @@ class AccountTx_test : public beast::unit_test::suite env.close(); } { - // Deposit preauthorization with a Ticket. + // Deposit pre-authorization with a Ticket. std::uint32_t const tktSeq{env.seq(alice) + 1}; env(ticket::create(alice, 1), sig(alie)); env.close(); @@ -788,19 +788,19 @@ class AccountTx_test : public beast::unit_test::suite BEAST_EXPECT(result[jss::result][jss::transactions].isArray()); // The first two transactions listed in sanity haven't happened yet. - constexpr unsigned int beckyDeletedOffest = 2; + constexpr unsigned int beckyDeletedOffset = 2; BEAST_EXPECT( std::size(sanity) == result[jss::result][jss::transactions].size() + - beckyDeletedOffest); + beckyDeletedOffset); Json::Value const& txs{result[jss::result][jss::transactions]}; - for (unsigned int index = beckyDeletedOffest; + for (unsigned int index = beckyDeletedOffset; index < std::size(sanity); ++index) { - checkSanity(txs[index - beckyDeletedOffest], sanity[index]); + checkSanity(txs[index - beckyDeletedOffset], sanity[index]); } } diff --git a/src/test/rpc/Book_test.cpp b/src/test/rpc/Book_test.cpp index 3c7477745b..ae2aff689d 100644 --- a/src/test/rpc/Book_test.cpp +++ b/src/test/rpc/Book_test.cpp @@ -1719,7 +1719,7 @@ public: BEAST_EXPECT(jrr[jss::offers].isArray()); BEAST_EXPECT( jrr[jss::offers].size() == - (asAdmin ? RPC::Tuning::bookOffers.rdefault : 0u)); + (asAdmin ? RPC::Tuning::bookOffers.rDefault : 0u)); } void diff --git a/src/test/rpc/DepositAuthorized_test.cpp b/src/test/rpc/DepositAuthorized_test.cpp index 968a3fd4dc..3e082a70a1 100644 --- a/src/test/rpc/DepositAuthorized_test.cpp +++ b/src/test/rpc/DepositAuthorized_test.cpp @@ -555,7 +555,7 @@ public: testcase("deposit_authorized with expired credentials"); // check expired credentials - char const credType2[] = "fghijk"; + char const credType2[] = "random"; std::uint32_t const x = env.current() ->header() .parentCloseTime.time_since_epoch() diff --git a/src/test/rpc/JSONRPC_test.cpp b/src/test/rpc/JSONRPC_test.cpp index 4d3f0a5098..6a9fae74a5 100644 --- a/src/test/rpc/JSONRPC_test.cpp +++ b/src/test/rpc/JSONRPC_test.cpp @@ -54,7 +54,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Minimal payment, no Amount only DeliverMax", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "secret": "masterpassphrase", "tx_json": { "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", @@ -71,7 +71,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Pass in Fee with minimal payment, both Amount and DeliverMax.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -91,7 +91,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Pass in Sequence, no Amount only DeliverMax", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -111,7 +111,7 @@ static constexpr TxnTestData txnTestArray[] = { "DeliverMax.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -133,7 +133,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Add 'fee_mult_max' field.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": 7, @@ -153,7 +153,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Add 'fee_mult_max' and 'fee_div_max' field.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": 7, @@ -174,7 +174,7 @@ static constexpr TxnTestData txnTestArray[] = { {"fee_mult_max is ignored if 'Fee' is present.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": 0, @@ -196,7 +196,7 @@ static constexpr TxnTestData txnTestArray[] = { {"fee_div_max is ignored if 'Fee' is present.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": 100, @@ -219,7 +219,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid 'fee_mult_max' field.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": "NotAFeeMultiplier", @@ -239,7 +239,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid 'fee_div_max' field.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": 5, @@ -260,7 +260,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid value for 'fee_mult_max' field.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": 0, @@ -280,7 +280,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid value for 'fee_div_max' field.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": 4, @@ -301,7 +301,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid zero value for 'fee_div_max' field.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "fee_mult_max": 4, @@ -322,7 +322,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'Amount'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -339,7 +339,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid 'Amount'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -357,7 +357,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'Destination'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -374,7 +374,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid 'Destination'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -392,7 +392,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Cannot create XRP to XRP paths.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "build_path": 1, @@ -411,7 +411,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Successful 'build_path'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "build_path": 1, @@ -434,7 +434,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Not valid to include both 'Paths' and 'build_path'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "build_path": 1, @@ -458,7 +458,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Successful 'SendMax'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "build_path": 1, @@ -486,7 +486,7 @@ static constexpr TxnTestData txnTestArray[] = { {"'Amount' may not be XRP for pathfinding, but 'SendMax' may be XRP.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "build_path": 1, @@ -510,7 +510,7 @@ static constexpr TxnTestData txnTestArray[] = { {"'secret' must be present.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "tx_json": { "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", @@ -527,7 +527,7 @@ static constexpr TxnTestData txnTestArray[] = { {"'secret' must be non-empty.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "", "tx_json": { @@ -545,7 +545,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Use 'seed' instead of 'secret'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi", "key_type": "ed25519", "seed": "sh1yJfwoi98zCygwijUzuHmJDeVKd", @@ -564,7 +564,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Malformed 'seed'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi", "key_type": "ed25519", "seed": "not a seed", @@ -583,7 +583,7 @@ static constexpr TxnTestData txnTestArray[] = { {"'tx_json' must be present.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "rx_json": { @@ -601,7 +601,7 @@ static constexpr TxnTestData txnTestArray[] = { {"'TransactionType' must be present.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -618,7 +618,7 @@ static constexpr TxnTestData txnTestArray[] = { {"The 'TransactionType' must be a pre-established transaction type.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -636,7 +636,7 @@ static constexpr TxnTestData txnTestArray[] = { {"The 'TransactionType' may be represented with an integer.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -654,7 +654,7 @@ static constexpr TxnTestData txnTestArray[] = { {"'Account' must be present.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -671,7 +671,7 @@ static constexpr TxnTestData txnTestArray[] = { {"'Account' must be well formed.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -689,7 +689,7 @@ static constexpr TxnTestData txnTestArray[] = { {"The 'offline' tag may be added to the transaction.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "offline": 0, @@ -708,7 +708,7 @@ static constexpr TxnTestData txnTestArray[] = { {"If 'offline' is true then a 'Sequence' field must be supplied.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "offline": 1, @@ -728,7 +728,7 @@ static constexpr TxnTestData txnTestArray[] = { {"If 'offline' is true then a 'Fee' field must be supplied.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "offline": 1, @@ -748,7 +748,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Valid transaction if 'offline' is true.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "offline": 1, @@ -770,7 +770,7 @@ static constexpr TxnTestData txnTestArray[] = { {"'offline' and 'build_path' are mutually exclusive.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "offline": 1, @@ -792,7 +792,7 @@ static constexpr TxnTestData txnTestArray[] = { {"A 'Flags' field may be specified.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -811,7 +811,7 @@ static constexpr TxnTestData txnTestArray[] = { {"The 'Flags' field must be numeric.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -830,7 +830,7 @@ static constexpr TxnTestData txnTestArray[] = { {"It's okay to add a 'debug_signing' field.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "debug_signing": 0, @@ -849,7 +849,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Single-sign a multisigned transaction.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux", "secret": "a", "tx_json": { @@ -879,7 +879,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Minimal sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -900,7 +900,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Minimal offline sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "offline": 1, @@ -919,7 +919,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Offline sign_for using 'seed' instead of 'secret'.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi", "key_type": "ed25519", "seed": "sh1yJfwoi98zCygwijUzuHmJDeVKd", @@ -939,7 +939,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Malformed seed in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rJrxi4Wxev4bnAGVNP9YCdKPdAoKfAmcsi", "key_type": "ed25519", "seed": "sh1yJfwoi98zCygwjUzuHmJDeVKd", @@ -962,7 +962,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'Account' in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -982,7 +982,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'Amount' in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1002,7 +1002,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'Destination' in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1022,7 +1022,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'Destination' in sign_for, use DeliverMax", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1042,7 +1042,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'Fee' in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1062,7 +1062,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'Sequence' in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1082,7 +1082,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'SigningPubKey' in sign_for is automatically filled in.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1102,7 +1102,7 @@ static constexpr TxnTestData txnTestArray[] = { {"In sign_for, an account may not sign for itself.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "secret": "a", "tx_json": { @@ -1123,7 +1123,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Cannot put duplicate accounts in Signers array", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1154,7 +1154,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Correctly append to pre-established Signers array", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux", "secret": "c", "tx_json": { @@ -1181,7 +1181,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Append to pre-established Signers array with bad signature", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux", "secret": "c", "tx_json": { @@ -1211,7 +1211,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Non-empty 'SigningPubKey' in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1232,7 +1232,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Missing 'TransactionType' in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": { @@ -1252,7 +1252,7 @@ static constexpr TxnTestData txnTestArray[] = { {"TxnSignature in sign_for.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rPcNzota6B8YBokhYtcTNqQVCngtbnWfux", "secret": "c", "tx_json": { @@ -1283,7 +1283,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid field 'tx_json': string instead of object", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": "" @@ -1296,7 +1296,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid field 'tx_json': integer instead of object", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": 20160331 @@ -1309,7 +1309,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Invalid field 'tx_json': array instead of object", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "tx_json": [ "hello", "world" ] @@ -1322,7 +1322,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Pass in Fee with minimal payment, both Amount and DeliverMax.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "r9zN9x52FiCFAcicCLMQKbj1nxYhxJbbSy", "secret": "ssgN6zTvtM1q9XV8DvJpWm8LBYWiY", "tx_json": { @@ -2003,7 +2003,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Payment cannot specify different DeliverMax and Amount.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "debug_signing": 0, @@ -2025,7 +2025,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Payment cannot specify bad DomainID.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "secret": "masterpassphrase", "debug_signing": 0, @@ -2048,7 +2048,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Minimal delegated transaction.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "secret": "a", "tx_json": { "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", @@ -2066,7 +2066,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Delegate not well formed.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "secret": "a", "tx_json": { "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", @@ -2084,7 +2084,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Delegate not in ledger.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "secret": "a", "tx_json": { "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", @@ -2102,7 +2102,7 @@ static constexpr TxnTestData txnTestArray[] = { {"Delegate and secret not match.", __LINE__, R"({ - "command": "doesnt_matter", + "command": "dummy_command", "secret": "aa", "tx_json": { "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", diff --git a/src/test/rpc/RPCCall_test.cpp b/src/test/rpc/RPCCall_test.cpp index 682584f40b..85402ff024 100644 --- a/src/test/rpc/RPCCall_test.cpp +++ b/src/test/rpc/RPCCall_test.cpp @@ -3921,7 +3921,7 @@ static RPCCallTestData const rpcCallTestArray[] = { } ] })"}, - {"log_level: partiton_name.", + {"log_level: partition_name.", __LINE__, {"log_level", "partition_name", "fatal"}, RPCCallTestData::no_exception, diff --git a/src/test/rpc/Simulate_test.cpp b/src/test/rpc/Simulate_test.cpp index 2a85e2a928..7fe90fb9a1 100644 --- a/src/test/rpc/Simulate_test.cpp +++ b/src/test/rpc/Simulate_test.cpp @@ -261,7 +261,7 @@ class Simulate_test : public beast::unit_test::suite { // `seed` field included Json::Value params = Json::objectValue; - params[jss::seed] = "doesnt_matter"; + params[jss::seed] = "random_data"; Json::Value tx_json = Json::objectValue; tx_json[jss::TransactionType] = jss::AccountSet; tx_json[jss::Account] = env.master.human(); @@ -274,7 +274,7 @@ class Simulate_test : public beast::unit_test::suite { // `secret` field included Json::Value params = Json::objectValue; - params[jss::secret] = "doesnt_matter"; + params[jss::secret] = "random_data"; Json::Value tx_json = Json::objectValue; tx_json[jss::TransactionType] = jss::AccountSet; tx_json[jss::Account] = env.master.human(); @@ -287,7 +287,7 @@ class Simulate_test : public beast::unit_test::suite { // `seed_hex` field included Json::Value params = Json::objectValue; - params[jss::seed_hex] = "doesnt_matter"; + params[jss::seed_hex] = "random_data"; Json::Value tx_json = Json::objectValue; tx_json[jss::TransactionType] = jss::AccountSet; tx_json[jss::Account] = env.master.human(); @@ -300,7 +300,7 @@ class Simulate_test : public beast::unit_test::suite { // `passphrase` field included Json::Value params = Json::objectValue; - params[jss::passphrase] = "doesnt_matter"; + params[jss::passphrase] = "random_data"; Json::Value tx_json = Json::objectValue; tx_json[jss::TransactionType] = jss::AccountSet; tx_json[jss::Account] = env.master.human(); diff --git a/src/test/server/ServerStatus_test.cpp b/src/test/server/ServerStatus_test.cpp index 9f35a9162d..a2516126de 100644 --- a/src/test/server/ServerStatus_test.cpp +++ b/src/test/server/ServerStatus_test.cpp @@ -1149,7 +1149,7 @@ class ServerStatus_test : public beast::unit_test::suite, doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); BEAST_EXPECT( resp.result() == boost::beast::http::status::bad_request); - BEAST_EXPECT(resp.body() == "params unparseable\r\n"); + BEAST_EXPECT(resp.body() == "params unparsable\r\n"); } { @@ -1159,7 +1159,7 @@ class ServerStatus_test : public beast::unit_test::suite, doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); BEAST_EXPECT( resp.result() == boost::beast::http::status::bad_request); - BEAST_EXPECT(resp.body() == "params unparseable\r\n"); + BEAST_EXPECT(resp.body() == "params unparsable\r\n"); } } diff --git a/src/xrpld/app/ledger/detail/LedgerMaster.cpp b/src/xrpld/app/ledger/detail/LedgerMaster.cpp index 2a2424995e..d176e85645 100644 --- a/src/xrpld/app/ledger/detail/LedgerMaster.cpp +++ b/src/xrpld/app/ledger/detail/LedgerMaster.cpp @@ -2204,7 +2204,7 @@ LedgerMaster::makeFetchPack( catch (std::exception const& ex) { JLOG(m_journal.warn()) - << "Exception building fetch pach. Exception: " << ex.what(); + << "Exception building fetch pack. Exception: " << ex.what(); } } diff --git a/src/xrpld/app/misc/FeeVoteImpl.cpp b/src/xrpld/app/misc/FeeVoteImpl.cpp index a6b140f691..08a9abf2db 100644 --- a/src/xrpld/app/misc/FeeVoteImpl.cpp +++ b/src/xrpld/app/misc/FeeVoteImpl.cpp @@ -230,12 +230,11 @@ FeeVoteImpl::doVoting( auto const& valueField) { if (auto const field = val->at(~valueField)) { - using xrptype = XRPAmount::value_type; + using XRPType = XRPAmount::value_type; auto const vote = *field; - if (vote <= std::numeric_limits::max() && - isLegalAmountSigned(XRPAmount{unsafe_cast(vote)})) - value.addVote( - XRPAmount{unsafe_cast(vote)}); + if (vote <= std::numeric_limits::max() && + isLegalAmountSigned(XRPAmount{unsafe_cast(vote)})) + value.addVote(XRPAmount{unsafe_cast(vote)}); else // Invalid amounts will be treated as if they're // not provided. Don't throw because this value is diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index d0f93577da..6a00354b15 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -3461,10 +3461,10 @@ NetworkOPsImp::pubAccountTransaction( } } - if (auto histoIt = mSubAccountHistory.find(affectedAccount); - histoIt != mSubAccountHistory.end()) + if (auto historyIt = mSubAccountHistory.find(affectedAccount); + historyIt != mSubAccountHistory.end()) { - auto& subs = histoIt->second; + auto& subs = historyIt->second; auto it = subs.begin(); while (it != subs.end()) { @@ -3487,7 +3487,7 @@ NetworkOPsImp::pubAccountTransaction( } } if (subs.empty()) - mSubAccountHistory.erase(histoIt); + mSubAccountHistory.erase(historyIt); } } } diff --git a/src/xrpld/app/misc/SHAMapStoreImp.h b/src/xrpld/app/misc/SHAMapStoreImp.h index aed2343a49..38997c2997 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.h +++ b/src/xrpld/app/misc/SHAMapStoreImp.h @@ -54,7 +54,7 @@ private: // name of state database std::string const dbName_ = "state"; // prefix of on-disk nodestore backend instances - std::string const dbPrefix_ = "rippledb"; + std::string const dbPrefix_ = "rippledb"; // cspell: disable-line // check health/stop status as records are copied std::uint64_t const checkHealthInterval_ = 1000; // minimum # of ledgers to maintain for health of network diff --git a/src/xrpld/app/misc/TxQ.h b/src/xrpld/app/misc/TxQ.h index fb1b10e886..10ed4adeea 100644 --- a/src/xrpld/app/misc/TxQ.h +++ b/src/xrpld/app/misc/TxQ.h @@ -537,12 +537,12 @@ private: /** Cached result of the `preflight` operation. Because `preflight` is expensive, minimize the number of times it needs to be done. - @invariant `pfresult` is never allowed to be empty. The + @invariant `pfResult` is never allowed to be empty. The `std::optional` is leveraged to allow `emplace`d construction and replacement without a copy assignment operation. */ - std::optional pfresult; + std::optional pfResult; /** Starting retry count for newly queued transactions. @@ -577,7 +577,7 @@ private: TxID const& txID, FeeLevel64 feeLevel, ApplyFlags const flags, - PreflightResult const& pfresult); + PreflightResult const& pfResult); /// Attempt to apply the queued transaction to the open ledger. ApplyResult @@ -588,7 +588,7 @@ private: TxConsequences const& consequences() const { - return pfresult->consequences; + return pfResult->consequences; } /// Return a TxDetails based on contained information. @@ -603,7 +603,7 @@ private: seqProxy, txn, retriesRemaining, - pfresult->ter, + pfResult->ter, lastResult}; } }; @@ -802,7 +802,7 @@ private: FeeMultiSet::iterator_type erase(FeeMultiSet::const_iterator_type); /** Erase and return the next entry for the account (if fee level is higher), or next entry in byFee_ (lower fee level). - Used to get the next "applyable" MaybeTx for accept(). + Used to get the next "applicable" MaybeTx for accept(). */ FeeMultiSet::iterator_type eraseAndAdvance( FeeMultiSet::const_iterator_type); @@ -826,7 +826,7 @@ private: AccountMap::iterator const& accountIter, TxQAccount::TxMap::iterator, FeeLevel64 feeLevelPaid, - PreflightResult const& pfresult, + PreflightResult const& pfResult, std::size_t const txExtraCount, ApplyFlags flags, FeeMetrics::Snapshot const& metricsSnapshot, diff --git a/src/xrpld/app/misc/ValidatorList.h b/src/xrpld/app/misc/ValidatorList.h index d6758f8877..45b24e8609 100644 --- a/src/xrpld/app/misc/ValidatorList.h +++ b/src/xrpld/app/misc/ValidatorList.h @@ -237,7 +237,7 @@ class ValidatorList // config file under the title of SECTION_VALIDATORS or [validators]. // This list is not associated with the masterKey of any publisher. - // Appropos PublisherListCollection fields, localPublisherList does not + // Apropos PublisherListCollection fields, localPublisherList does not // have any "remaining" manifests. It is assumed to be perennially // "available". The "validUntil" field is set to the highest possible // value of the field, hence this list is always valid. @@ -365,7 +365,7 @@ public: std::string const& rawManifest, std::map const& blobInfos, std::vector& messages, - std::size_t maxSize = maximiumMessageSize); + std::size_t maxSize = maximumMessageSize); /** Apply multiple published lists of public keys, then broadcast it to all peers that have not seen it or sent it. diff --git a/src/xrpld/app/misc/detail/TxQ.cpp b/src/xrpld/app/misc/detail/TxQ.cpp index 9f260e5f48..01abcc9c7d 100644 --- a/src/xrpld/app/misc/detail/TxQ.cpp +++ b/src/xrpld/app/misc/detail/TxQ.cpp @@ -263,7 +263,7 @@ TxQ::MaybeTx::MaybeTx( TxID const& txID_, FeeLevel64 feeLevel_, ApplyFlags const flags_, - PreflightResult const& pfresult_) + PreflightResult const& pfResult_) : txn(txn_) , feeLevel(feeLevel_) , txID(txID_) @@ -272,7 +272,7 @@ TxQ::MaybeTx::MaybeTx( , seqProxy(txn_->getSeqProxy()) , retriesRemaining(retriesAllowed) , flags(flags_) - , pfresult(pfresult_) + , pfResult(pfResult_) { } @@ -281,20 +281,20 @@ TxQ::MaybeTx::apply(Application& app, OpenView& view, beast::Journal j) { // If the rules or flags change, preflight again XRPL_ASSERT( - pfresult, "xrpl::TxQ::MaybeTx::apply : preflight result is set"); + pfResult, "xrpl::TxQ::MaybeTx::apply : preflight result is set"); NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)}; - if (pfresult->rules != view.rules() || pfresult->flags != flags) + if (pfResult->rules != view.rules() || pfResult->flags != flags) { JLOG(j.debug()) << "Queued transaction " << txID << " rules or flags have changed. Flags from " - << pfresult->flags << " to " << flags; + << pfResult->flags << " to " << flags; - pfresult.emplace( - preflight(app, view.rules(), pfresult->tx, flags, pfresult->j)); + pfResult.emplace( + preflight(app, view.rules(), pfResult->tx, flags, pfResult->j)); } - auto pcresult = preclaim(*pfresult, app, view); + auto pcresult = preclaim(*pfResult, app, view); return doApply(pcresult, app, view); } @@ -503,7 +503,7 @@ TxQ::tryClearAccountQueueUpThruTx( TxQ::AccountMap::iterator const& accountIter, TxQAccount::TxMap::iterator beginTxIter, FeeLevel64 feeLevelPaid, - PreflightResult const& pfresult, + PreflightResult const& pfResult, std::size_t const txExtraCount, ApplyFlags flags, FeeMetrics::Snapshot const& metricsSnapshot, @@ -578,7 +578,7 @@ TxQ::tryClearAccountQueueUpThruTx( } // Apply the current tx. Because the state of the view has been changed // by the queued txs, we also need to preclaim again. - auto const txResult = doApply(preclaim(pfresult, app, view), app, view); + auto const txResult = doApply(preclaim(pfResult, app, view), app, view); if (txResult.applied) { @@ -720,9 +720,9 @@ TxQ::apply( // See if the transaction is valid, properly formed, // etc. before doing potentially expensive queue // replace and multi-transaction operations. - auto const pfresult = preflight(app, view.rules(), *tx, flags, j); - if (pfresult.ter != tesSUCCESS) - return {pfresult.ter, false}; + auto const pfResult = preflight(app, view.rules(), *tx, flags, j); + if (pfResult.ter != tesSUCCESS) + return {pfResult.ter, false}; // See if the transaction paid a high enough fee that it can go straight // into the ledger. @@ -814,7 +814,7 @@ TxQ::apply( // 1. If the account's queue is empty or // 2. If the blocker replaces the only entry in the account's queue. auto const transactionID = tx->getTransactionID(); - if (pfresult.consequences.isBlocker()) + if (pfResult.consequences.isBlocker()) { if (acctTxCount > 1) { @@ -1040,8 +1040,8 @@ TxQ::apply( // The fee for the candidate transaction _should_ be // counted if it's replacing a transaction in the middle // of the queue. - totalFee += pfresult.consequences.fee(); - potentialSpend += pfresult.consequences.potentialSpend(); + totalFee += pfResult.consequences.fee(); + potentialSpend += pfResult.consequences.potentialSpend(); } } @@ -1144,7 +1144,7 @@ TxQ::apply( // is valid. So we use a special entry point that runs all of the // preclaim checks with the exception of the sequence check. auto const pcresult = - preclaim(pfresult, app, multiTxn ? multiTxn->openView : view); + preclaim(pfResult, app, multiTxn ? multiTxn->openView : view); if (!pcresult.likelyToClaimFee) return {pcresult.ter, false}; @@ -1187,7 +1187,7 @@ TxQ::apply( accountIter, txIter->first, feeLevelPaid, - pfresult, + pfResult, view.txCount(), flags, metricsSnapshot, @@ -1316,12 +1316,12 @@ TxQ::apply( flags &= ~tapRETRY; auto& candidate = accountIter->second.add( - {tx, transactionID, feeLevelPaid, flags, pfresult}); + {tx, transactionID, feeLevelPaid, flags, pfResult}); // Then index it into the byFee lookup. byFee_.insert(candidate); JLOG(j_.debug()) << "Added transaction " << candidate.txID - << " with result " << transToken(pfresult.ter) << " from " + << " with result " << transToken(pfResult.ter) << " from " << (accountIsInQueue ? "existing" : "new") << " account " << candidate.account << " to queue." << " Flags: " << flags; diff --git a/src/xrpld/app/misc/detail/ValidatorList.cpp b/src/xrpld/app/misc/detail/ValidatorList.cpp index db2ee980b8..12ba52fa36 100644 --- a/src/xrpld/app/misc/detail/ValidatorList.cpp +++ b/src/xrpld/app/misc/detail/ValidatorList.cpp @@ -524,7 +524,7 @@ splitMessageParts( smallMsg.set_manifest(blob.manifest()); XRPL_ASSERT( - Message::totalSize(smallMsg) <= maximiumMessageSize, + Message::totalSize(smallMsg) <= maximumMessageSize, "xrpl::splitMessageParts : maximum message size"); messages.emplace_back( @@ -588,7 +588,7 @@ buildValidatorListMessage( msg.set_version(version); XRPL_ASSERT( - Message::totalSize(msg) <= maximiumMessageSize, + Message::totalSize(msg) <= maximumMessageSize, "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : maximum " "message size"); messages.emplace_back( @@ -658,7 +658,7 @@ ValidatorList::buildValidatorListMessages( std::string const& rawManifest, std::map const& blobInfos, std::vector& messages, - std::size_t maxSize /*= maximiumMessageSize*/) + std::size_t maxSize /*= maximumMessageSize*/) { XRPL_ASSERT( !blobInfos.empty(), diff --git a/src/xrpld/app/paths/AMMOffer.h b/src/xrpld/app/paths/AMMOffer.h index 07defc16b1..7a81e53176 100644 --- a/src/xrpld/app/paths/AMMOffer.h +++ b/src/xrpld/app/paths/AMMOffer.h @@ -82,7 +82,7 @@ public: */ TAmounts limitOut( - TAmounts const& offrAmt, + TAmounts const& offerAmount, TOut const& limit, bool roundUp) const; @@ -91,8 +91,10 @@ public: * current quality. */ TAmounts - limitIn(TAmounts const& offrAmt, TIn const& limit, bool roundUp) - const; + limitIn( + TAmounts const& offerAmount, + TIn const& limit, + bool roundUp) const; QualityFunction getQualityFunc() const; diff --git a/src/xrpld/app/paths/PathRequest.h b/src/xrpld/app/paths/PathRequest.h index 3d5564c069..8f63cfa9a9 100644 --- a/src/xrpld/app/paths/PathRequest.h +++ b/src/xrpld/app/paths/PathRequest.h @@ -103,7 +103,7 @@ private: std::function const&); /** Finds and sets a PathSet in the JSON argument. - Returns false if the source currencies are inavlid. + Returns false if the source currencies are invalid. */ bool findPaths( diff --git a/src/xrpld/app/paths/detail/AMMOffer.cpp b/src/xrpld/app/paths/detail/AMMOffer.cpp index a58eafbdbf..1152b673da 100644 --- a/src/xrpld/app/paths/detail/AMMOffer.cpp +++ b/src/xrpld/app/paths/detail/AMMOffer.cpp @@ -61,7 +61,7 @@ AMMOffer::consume( template TAmounts AMMOffer::limitOut( - TAmounts const& offrAmt, + TAmounts const& offerAmount, TOut const& limit, bool roundUp) const { @@ -75,7 +75,7 @@ AMMOffer::limitOut( { // It turns out that the ceil_out implementation has some slop in // it, which ceil_out_strict removes. - return quality().ceil_out_strict(offrAmt, limit, roundUp); + return quality().ceil_out_strict(offerAmount, limit, roundUp); } // Change the offer size according to the conservation function. The offer // quality is increased in this case, but it doesn't matter since there is @@ -86,7 +86,7 @@ AMMOffer::limitOut( template TAmounts AMMOffer::limitIn( - TAmounts const& offrAmt, + TAmounts const& offerAmount, TIn const& limit, bool roundUp) const { @@ -95,9 +95,9 @@ AMMOffer::limitIn( { if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixReducedOffersV2)) - return quality().ceil_in_strict(offrAmt, limit, roundUp); + return quality().ceil_in_strict(offerAmount, limit, roundUp); - return quality().ceil_in(offrAmt, limit); + return quality().ceil_in(offerAmount, limit); } return {limit, swapAssetIn(balances_, limit, ammLiquidity_.tradingFee())}; } diff --git a/src/xrpld/app/paths/detail/StrandFlow.h b/src/xrpld/app/paths/detail/StrandFlow.h index 5e0a637858..fab92dca35 100644 --- a/src/xrpld/app/paths/detail/StrandFlow.h +++ b/src/xrpld/app/paths/detail/StrandFlow.h @@ -435,8 +435,8 @@ public: cur_.clear(); if (!next_.empty()) { - std::vector> strandQuals; - strandQuals.reserve(next_.size()); + std::vector> strandQualities; + strandQualities.reserve(next_.size()); if (next_.size() > 1) // no need to sort one strand { for (Strand const* strand : next_) @@ -458,21 +458,21 @@ public: // an unusual corner case. continue; } - strandQuals.push_back({*qual, strand}); + strandQualities.push_back({*qual, strand}); } } // must stable sort for deterministic order across different c++ // standard library implementations std::stable_sort( - strandQuals.begin(), - strandQuals.end(), + strandQualities.begin(), + strandQualities.end(), [](auto const& lhs, auto const& rhs) { // higher qualities first return std::get(lhs) > std::get(rhs); }); next_.clear(); - next_.reserve(strandQuals.size()); - for (auto const& sq : strandQuals) + next_.reserve(strandQualities.size()); + for (auto const& sq : strandQualities) { next_.push_back(std::get(sq)); } diff --git a/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp b/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp index 796b030a99..77757419dc 100644 --- a/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp +++ b/src/xrpld/app/rdb/backend/detail/SQLiteDatabase.cpp @@ -155,7 +155,7 @@ private: Application& app_; bool const useTxTables_; beast::Journal j_; - std::unique_ptr lgrdb_, txdb_; + std::unique_ptr ledgerDb_, txdb_; /** * @brief makeLedgerDBs Opens ledger and transaction databases for the node @@ -178,7 +178,7 @@ private: bool existsLedger() { - return static_cast(lgrdb_); + return static_cast(ledgerDb_); } /** @@ -200,7 +200,7 @@ private: auto checkoutLedger() { - return lgrdb_->checkoutDb(); + return ledgerDb_->checkoutDb(); } /** @@ -224,7 +224,7 @@ SQLiteDatabaseImp::makeLedgerDBs( auto [lgr, tx, res] = detail::makeLedgerDBs(config, setup, checkpointerSetup, j_); txdb_ = std::move(tx); - lgrdb_ = std::move(lgr); + ledgerDb_ = std::move(lgr); return res; } @@ -392,7 +392,8 @@ SQLiteDatabaseImp::saveValidatedLedger( { if (existsLedger()) { - if (!detail::saveValidatedLedger(*lgrdb_, txdb_, app_, ledger, current)) + if (!detail::saveValidatedLedger( + *ledgerDb_, txdb_, app_, ledger, current)) return false; } @@ -789,7 +790,7 @@ SQLiteDatabaseImp::getKBUsedAll() { if (existsLedger()) { - return xrpl::getKBUsedAll(lgrdb_->getSession()); + return xrpl::getKBUsedAll(ledgerDb_->getSession()); } return 0; @@ -800,7 +801,7 @@ SQLiteDatabaseImp::getKBUsedLedger() { if (existsLedger()) { - return xrpl::getKBUsedDB(lgrdb_->getSession()); + return xrpl::getKBUsedDB(ledgerDb_->getSession()); } return 0; @@ -823,7 +824,7 @@ SQLiteDatabaseImp::getKBUsedTransaction() void SQLiteDatabaseImp::closeLedgerDB() { - lgrdb_.reset(); + ledgerDb_.reset(); } void diff --git a/src/xrpld/app/tx/applySteps.h b/src/xrpld/app/tx/applySteps.h index c0c530f3ac..0ae3d8790e 100644 --- a/src/xrpld/app/tx/applySteps.h +++ b/src/xrpld/app/tx/applySteps.h @@ -64,7 +64,7 @@ private: public: // Constructor if preflight returns a value other than tesSUCCESS. // Asserts if tesSUCCESS is passed. - explicit TxConsequences(NotTEC pfresult); + explicit TxConsequences(NotTEC pfResult); /// Constructor if the STTx has no notable consequences for the TxQ. explicit TxConsequences(STTx const& tx); diff --git a/src/xrpld/app/tx/detail/DelegateSet.cpp b/src/xrpld/app/tx/detail/DelegateSet.cpp index 8c64547ae1..96d02bf2bc 100644 --- a/src/xrpld/app/tx/detail/DelegateSet.cpp +++ b/src/xrpld/app/tx/detail/DelegateSet.cpp @@ -26,7 +26,7 @@ DelegateSet::preflight(PreflightContext const& ctx) if (!permissionSet.insert(permission[sfPermissionValue]).second) return temMALFORMED; - if (!Permission::getInstance().isDelegatable( + if (!Permission::getInstance().isDelegable( permission[sfPermissionValue], ctx.rules)) return temMALFORMED; } diff --git a/src/xrpld/app/tx/detail/InvariantCheck.cpp b/src/xrpld/app/tx/detail/InvariantCheck.cpp index dadc5a7d74..eb751c817f 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.cpp +++ b/src/xrpld/app/tx/detail/InvariantCheck.cpp @@ -567,7 +567,7 @@ AccountRootsDeletedClean::finalize( } { - // NFT pages. ntfpage_min and nftpage_max were already explicitly + // NFT pages. nftpage_min and nftpage_max were already explicitly // checked above as entries in directAccountKeylets. This uses // view.succ() to check for any NFT pages in between the two // endpoints. @@ -2321,7 +2321,7 @@ NoModifiedUnmodifiableFields::finalize( if (bad) { JLOG(j.fatal()) - << "Invariant failed: changed an unchangable field for " + << "Invariant failed: changed an unchangeable field for " << tx.getTransactionID(); if (enforce) return false; diff --git a/src/xrpld/app/tx/detail/Offer.h b/src/xrpld/app/tx/detail/Offer.h index b04049b657..75e78e5758 100644 --- a/src/xrpld/app/tx/detail/Offer.h +++ b/src/xrpld/app/tx/detail/Offer.h @@ -121,13 +121,15 @@ public: TAmounts limitOut( - TAmounts const& offrAmt, + TAmounts const& offerAmount, TOut const& limit, bool roundUp) const; TAmounts - limitIn(TAmounts const& offrAmt, TIn const& limit, bool roundUp) - const; + limitIn( + TAmounts const& offerAmount, + TIn const& limit, + bool roundUp) const; template static TER @@ -218,19 +220,19 @@ TOffer::setFieldAmounts() template TAmounts TOffer::limitOut( - TAmounts const& offrAmt, + TAmounts const& offerAmount, TOut const& limit, bool roundUp) const { // It turns out that the ceil_out implementation has some slop in // it, which ceil_out_strict removes. - return quality().ceil_out_strict(offrAmt, limit, roundUp); + return quality().ceil_out_strict(offerAmount, limit, roundUp); } template TAmounts TOffer::limitIn( - TAmounts const& offrAmt, + TAmounts const& offerAmount, TIn const& limit, bool roundUp) const { @@ -240,8 +242,8 @@ TOffer::limitIn( // it. ceil_in_strict removes that slop. But removing that slop // affects transaction outcomes, so the change must be made using // an amendment. - return quality().ceil_in_strict(offrAmt, limit, roundUp); - return m_quality.ceil_in(offrAmt, limit); + return quality().ceil_in_strict(offerAmount, limit, roundUp); + return m_quality.ceil_in(offerAmount, limit); } template diff --git a/src/xrpld/app/tx/detail/OfferStream.cpp b/src/xrpld/app/tx/detail/OfferStream.cpp index 49e45976eb..587badf31a 100644 --- a/src/xrpld/app/tx/detail/OfferStream.cpp +++ b/src/xrpld/app/tx/detail/OfferStream.cpp @@ -341,7 +341,7 @@ TOfferStreamBase::step() } // LCOV_EXCL_START UNREACHABLE( - "rippls::TOfferStreamBase::step::rmSmallIncreasedQOffer : XRP " + "xrpl::TOfferStreamBase::step::rmSmallIncreasedQOffer : XRP " "vs XRP offer"); return false; // LCOV_EXCL_STOP diff --git a/src/xrpld/app/tx/detail/Transactor.cpp b/src/xrpld/app/tx/detail/Transactor.cpp index 7b0cbbbdd4..851712fe90 100644 --- a/src/xrpld/app/tx/detail/Transactor.cpp +++ b/src/xrpld/app/tx/detail/Transactor.cpp @@ -1133,7 +1133,7 @@ Transactor::operator()() // raii classes for the current ledger rules. // fixUniversalNumber predate the rulesGuard and should be replaced. NumberSO stNumberSO{view().rules().enabled(fixUniversalNumber)}; - CurrentTransactionRulesGuard currentTransctionRulesGuard(view().rules()); + CurrentTransactionRulesGuard currentTransactionRulesGuard(view().rules()); #ifdef DEBUG { diff --git a/src/xrpld/app/tx/detail/XChainBridge.cpp b/src/xrpld/app/tx/detail/XChainBridge.cpp index 88cc236e0b..ebfcc8a769 100644 --- a/src/xrpld/app/tx/detail/XChainBridge.cpp +++ b/src/xrpld/app/tx/detail/XChainBridge.cpp @@ -324,7 +324,7 @@ onNewAttestations( return {std::move(r.value()), changed}; }; -// Check if there is a quorurm of attestations for the given amount and +// Check if there is a quorum of attestations for the given amount and // chain. If so return the reward accounts, if not return the tec code (most // likely tecXCHAIN_CLAIM_NO_QUORUM) Expected, TER> @@ -434,7 +434,7 @@ transferHelper( auto const availableBalance = [&]() -> STAmount { STAmount const curBal = (*sleSrc)[sfBalance]; // Checking that account == src and postFeeBalance == curBal is - // not strictly nessisary, but helps protect against future + // not strictly necessary, but helps protect against future // changes if (!submittingAccountInfo || submittingAccountInfo->account != src || @@ -622,7 +622,7 @@ finalizeClaimHelper( // If distributing the reward pool fails, the mainFunds transfer should // be rolled back // - // If the claimid is removed, the rewards should be distributed + // If the claim ID is removed, the rewards should be distributed // even if the mainFunds fails. // // If OnTransferFail::removeClaim, the claim should be removed even if @@ -1190,7 +1190,7 @@ toClaim(STTx const& tx) template NotTEC -attestationpreflight(PreflightContext const& ctx) +attestationPreflight(PreflightContext const& ctx) { if (!publicKeyType(ctx.tx[sfPublicKey])) return temMALFORMED; @@ -2076,7 +2076,7 @@ XChainCreateClaimID::doApply() NotTEC XChainAddClaimAttestation::preflight(PreflightContext const& ctx) { - return attestationpreflight(ctx); + return attestationPreflight(ctx); } TER @@ -2096,7 +2096,7 @@ XChainAddClaimAttestation::doApply() NotTEC XChainAddAccountCreateAttestation::preflight(PreflightContext const& ctx) { - return attestationpreflight(ctx); + return attestationPreflight(ctx); } TER diff --git a/src/xrpld/app/tx/detail/applySteps.cpp b/src/xrpld/app/tx/detail/applySteps.cpp index 7f0d971fdc..e0bd9d0d2d 100644 --- a/src/xrpld/app/tx/detail/applySteps.cpp +++ b/src/xrpld/app/tx/detail/applySteps.cpp @@ -217,7 +217,7 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx) } } -TxConsequences::TxConsequences(NotTEC pfresult) +TxConsequences::TxConsequences(NotTEC pfResult) : isBlocker_(false) , fee_(beast::zero) , potentialSpend_(beast::zero) @@ -225,7 +225,7 @@ TxConsequences::TxConsequences(NotTEC pfresult) , sequencesConsumed_(0) { XRPL_ASSERT( - !isTesSuccess(pfresult), + !isTesSuccess(pfResult), "xrpl::TxConsequences::TxConsequences : is not tesSUCCESS"); } @@ -288,15 +288,15 @@ preflight( ApplyFlags flags, beast::Journal j) { - PreflightContext const pfctx(app, tx, rules, flags, j); + PreflightContext const pfCtx(app, tx, rules, flags, j); try { - return {pfctx, invoke_preflight(pfctx)}; + return {pfCtx, invoke_preflight(pfCtx)}; } catch (std::exception const& e) { JLOG(j.fatal()) << "apply (preflight): " << e.what(); - return {pfctx, {tefEXCEPTION, TxConsequences{tx}}}; + return {pfCtx, {tefEXCEPTION, TxConsequences{tx}}}; } } @@ -309,15 +309,15 @@ preflight( ApplyFlags flags, beast::Journal j) { - PreflightContext const pfctx(app, tx, parentBatchId, rules, flags, j); + PreflightContext const pfCtx(app, tx, parentBatchId, rules, flags, j); try { - return {pfctx, invoke_preflight(pfctx)}; + return {pfCtx, invoke_preflight(pfCtx)}; } catch (std::exception const& e) { JLOG(j.fatal()) << "apply (preflight): " << e.what(); - return {pfctx, {tefEXCEPTION, TxConsequences{tx}}}; + return {pfCtx, {tefEXCEPTION, TxConsequences{tx}}}; } } diff --git a/src/xrpld/consensus/DisputedTx.h b/src/xrpld/consensus/DisputedTx.h index f4b841c795..5207f9750e 100644 --- a/src/xrpld/consensus/DisputedTx.h +++ b/src/xrpld/consensus/DisputedTx.h @@ -332,10 +332,10 @@ DisputedTx::getJson() const if (!votes_.empty()) { - Json::Value votesj(Json::objectValue); + Json::Value votes(Json::objectValue); for (auto const& [nodeId, vote] : votes_) - votesj[to_string(nodeId)] = vote; - ret["votes"] = std::move(votesj); + votes[to_string(nodeId)] = vote; + ret["votes"] = std::move(votes); } return ret; diff --git a/src/xrpld/consensus/Validations.h b/src/xrpld/consensus/Validations.h index 15b33c89c4..339612cfe0 100644 --- a/src/xrpld/consensus/Validations.h +++ b/src/xrpld/consensus/Validations.h @@ -455,9 +455,9 @@ private: are checked and any stale validations are flushed from the trie. @param lock Existing lock of mutex_ - @param f Invokable with signature (LedgerTrie &) + @param f Invocable with signature (LedgerTrie &) - @warning The invokable `f` is expected to be a simple transformation of + @warning The invocable `f` is expected to be a simple transformation of its arguments and will be called with mutex_ under lock. */ @@ -476,14 +476,14 @@ private: Iterate current validations, flushing any which are stale. @param lock Existing lock of mutex_ - @param pre Invokable with signature (std::size_t) called prior to + @param pre Invocable with signature (std::size_t) called prior to looping. - @param f Invokable with signature (NodeID const &, Validations const &) + @param f Invocable with signature (NodeID const &, Validations const &) for each current validation. - @note The invokable `pre` is called _prior_ to checking for staleness + @note The invocable `pre` is called _prior_ to checking for staleness and reflects an upper-bound on the number of calls to `f. - @warning The invokable `f` is expected to be a simple transformation of + @warning The invocable `f` is expected to be a simple transformation of its arguments and will be called with mutex_ under lock. */ @@ -517,12 +517,12 @@ private: @param lock Existing lock on mutex_ @param ledgerID The identifier of the ledger - @param pre Invokable with signature(std::size_t) - @param f Invokable with signature (NodeID const &, Validation const &) + @param pre Invocable with signature(std::size_t) + @param f Invocable with signature (NodeID const &, Validation const &) - @note The invokable `pre` is called prior to iterating validations. The + @note The invocable `pre` is called prior to iterating validations. The argument is the number of times `f` will be called. - @warning The invokable f is expected to be a simple transformation of + @warning The invocable f is expected to be a simple transformation of its arguments and will be called with mutex_ under lock. */ template diff --git a/src/xrpld/overlay/Message.h b/src/xrpld/overlay/Message.h index f2b021840d..550c24eef3 100644 --- a/src/xrpld/overlay/Message.h +++ b/src/xrpld/overlay/Message.h @@ -12,7 +12,7 @@ namespace xrpl { -constexpr std::size_t maximiumMessageSize = megabytes(64); +constexpr std::size_t maximumMessageSize = megabytes(64); // VFALCO NOTE If we forward declare Message and write out shared_ptr // instead of using the in-class type alias, we can remove the diff --git a/src/xrpld/overlay/Overlay.h b/src/xrpld/overlay/Overlay.h index c30d0f5205..aaecd50eb6 100644 --- a/src/xrpld/overlay/Overlay.h +++ b/src/xrpld/overlay/Overlay.h @@ -94,7 +94,7 @@ public: size() const = 0; /** Return diagnostics on the status of all peers. - @deprecated This is superceded by PropertyStream + @deprecated This is superseded by PropertyStream */ virtual Json::Value json() = 0; diff --git a/src/xrpld/overlay/Slot.h b/src/xrpld/overlay/Slot.h index 9e717fef9c..66368b60b9 100644 --- a/src/xrpld/overlay/Slot.h +++ b/src/xrpld/overlay/Slot.h @@ -345,14 +345,14 @@ Slot::update( auto it = std::next(considered_.begin(), i); auto id = *it; considered_.erase(it); - auto const& itpeers = peers_.find(id); - if (itpeers == peers_.end()) + auto const& itPeers = peers_.find(id); + if (itPeers == peers_.end()) { JLOG(journal_.error()) << "update: peer not found " << Slice(validator) << " " << id; continue; } - if (now - itpeers->second.lastMessage < IDLED) + if (now - itPeers->second.lastMessage < IDLED) selected.insert(id); } diff --git a/src/xrpld/overlay/detail/OverlayImpl.cpp b/src/xrpld/overlay/detail/OverlayImpl.cpp index 7cd02c72e0..d1d2467b1e 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.cpp +++ b/src/xrpld/overlay/detail/OverlayImpl.cpp @@ -620,7 +620,7 @@ OverlayImpl::onManifests( std::shared_ptr const& from) { auto const n = m->list_size(); - auto const& journal = from->pjournal(); + auto const& journal = from->pJournal(); protocol::TMManifests relay; diff --git a/src/xrpld/overlay/detail/OverlayImpl.h b/src/xrpld/overlay/detail/OverlayImpl.h index dc7e4975a3..786f42184e 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.h +++ b/src/xrpld/overlay/detail/OverlayImpl.h @@ -461,7 +461,7 @@ private: /** Handles validator list requests. Using a /vl/ URL, will retrieve the - latest valdiator list (or UNL) that this node has for that + latest validator list (or UNL) that this node has for that public key, if the node trusts that public key. @return true if the request was handled. diff --git a/src/xrpld/overlay/detail/PeerImp.h b/src/xrpld/overlay/detail/PeerImp.h index 565c3f9d0f..1e28de0c31 100644 --- a/src/xrpld/overlay/detail/PeerImp.h +++ b/src/xrpld/overlay/detail/PeerImp.h @@ -323,7 +323,7 @@ public: virtual ~PeerImp(); beast::Journal const& - pjournal() const + pJournal() const { return p_journal_; } diff --git a/src/xrpld/overlay/detail/ProtocolMessage.h b/src/xrpld/overlay/detail/ProtocolMessage.h index 1a35deb6f0..51dfc1ac7c 100644 --- a/src/xrpld/overlay/detail/ProtocolMessage.h +++ b/src/xrpld/overlay/detail/ProtocolMessage.h @@ -114,7 +114,7 @@ struct MessageHeader std::uint16_t message_type = 0; /** Indicates which compression algorithm the payload is compressed with. - * Currenly only lz4 is supported. If None then the message is not + * Currently only lz4 is supported. If None then the message is not * compressed. */ compression::Algorithm algorithm = compression::Algorithm::None; @@ -340,8 +340,8 @@ invokeProtocolMessage( // whose size exceeds this may result in the connection being dropped. A // larger message size may be supported in the future or negotiated as // part of a protocol upgrade. - if (header->payload_wire_size > maximiumMessageSize || - header->uncompressed_size > maximiumMessageSize) + if (header->payload_wire_size > maximumMessageSize || + header->uncompressed_size > maximumMessageSize) { result.second = make_error_code(boost::system::errc::message_size); return result; diff --git a/src/xrpld/overlay/detail/ProtocolVersion.h b/src/xrpld/overlay/detail/ProtocolVersion.h index ff49c89f1a..9499cd1c1b 100644 --- a/src/xrpld/overlay/detail/ProtocolVersion.h +++ b/src/xrpld/overlay/detail/ProtocolVersion.h @@ -32,7 +32,7 @@ to_string(ProtocolVersion const& p); Given a comma-separated string, extract and return all those that look like valid protocol versions (i.e. XRPL/2.0 and later). Strings that are - not parseable as valid protocol strings are excluded from the result set. + not parsable as valid protocol strings are excluded from the result set. @return A list of all apparently valid protocol versions. diff --git a/src/xrpld/overlay/detail/TxMetrics.cpp b/src/xrpld/overlay/detail/TxMetrics.cpp index 10f14183a3..ba3e7e8ae0 100644 --- a/src/xrpld/overlay/detail/TxMetrics.cpp +++ b/src/xrpld/overlay/detail/TxMetrics.cpp @@ -83,11 +83,11 @@ SingleMetrics::addMetrics(std::uint32_t val) if (timeElapsedInSecs >= 1s) { auto const avg = accum / (perTimeUnit ? timeElapsedInSecs.count() : N); - rollingAvgAggreg.push_back(avg); + rollingAvgAggregate.push_back(avg); auto const total = std::accumulate( - rollingAvgAggreg.begin(), rollingAvgAggreg.end(), 0ull); - rollingAvg = total / rollingAvgAggreg.size(); + rollingAvgAggregate.begin(), rollingAvgAggregate.end(), 0ull); + rollingAvg = total / rollingAvgAggregate.size(); intervalStart = clock_type::now(); accum = 0; diff --git a/src/xrpld/overlay/detail/TxMetrics.h b/src/xrpld/overlay/detail/TxMetrics.h index 3c34aaf9f9..265c9251d7 100644 --- a/src/xrpld/overlay/detail/TxMetrics.h +++ b/src/xrpld/overlay/detail/TxMetrics.h @@ -34,7 +34,7 @@ struct SingleMetrics std::uint64_t rollingAvg{0}; std::uint32_t N{0}; bool perTimeUnit{true}; - boost::circular_buffer rollingAvgAggreg{30, 0ull}; + boost::circular_buffer rollingAvgAggregate{30, 0ull}; /** Add metrics value * @param val metrics value, either bytes or count */ diff --git a/src/xrpld/peerfinder/detail/Livecache.h b/src/xrpld/peerfinder/detail/Livecache.h index 0927593ed1..c04b46dc6d 100644 --- a/src/xrpld/peerfinder/detail/Livecache.h +++ b/src/xrpld/peerfinder/detail/Livecache.h @@ -165,14 +165,14 @@ protected: /** The Livecache holds the short-lived relayed Endpoint messages. Since peers only advertise themselves when they have open slots, - we want these messags to expire rather quickly after the peer becomes + we want these messages to expire rather quickly after the peer becomes full. Addresses added to the cache are not connection-tested to see if - they are connectible (with one small exception regarding neighbors). + they are connectable (with one small exception regarding neighbors). Therefore, these addresses are not suitable for persisting across launches or for bootstrapping, because they do not have verifiable - and locally observed uptime and connectibility information. + and locally observed uptime and connectability information. */ template > class Livecache : protected detail::LivecacheBase diff --git a/src/xrpld/peerfinder/detail/Logic.h b/src/xrpld/peerfinder/detail/Logic.h index 50026cc886..aa56c8098c 100644 --- a/src/xrpld/peerfinder/detail/Logic.h +++ b/src/xrpld/peerfinder/detail/Logic.h @@ -628,7 +628,7 @@ public: This is a temporary measure. Once we know our own IP address, the correct solution is to put it into the Livecache at hops 0, and go through the regular handout path. This way - we avoid handing our address out too frequenty, which this code + we avoid handing our address out too frequently, which this code suffers from. */ // Add an entry for ourselves if: @@ -903,7 +903,7 @@ public: // Address must exist if (iter == connectedAddresses_.end()) LogicError( - "PeerFinder::Logic::remove(): remote_endpont " + "PeerFinder::Logic::remove(): remote_endpoint " "address missing from connectedAddresses_"); connectedAddresses_.erase(iter); @@ -929,7 +929,7 @@ public: auto iter(fixed_.find(slot->remote_endpoint())); if (iter == fixed_.end()) LogicError( - "PeerFinder::Logic::on_closed(): remote_endpont " + "PeerFinder::Logic::on_closed(): remote_endpoint " "missing from fixed_"); iter->second.failure(m_clock.now()); diff --git a/src/xrpld/peerfinder/detail/iosformat.h b/src/xrpld/peerfinder/detail/iosformat.h index 323665c016..a1117f0935 100644 --- a/src/xrpld/peerfinder/detail/iosformat.h +++ b/src/xrpld/peerfinder/detail/iosformat.h @@ -60,7 +60,7 @@ struct divider } }; -/** Creates a padded field with an optiona fill character. */ +/** Creates a padded field with an optional fill character. */ struct fpad { explicit fpad(int width_, int pad_ = 0, char fill_ = ' ') @@ -172,7 +172,7 @@ field(T const& t, int width = 8, int pad = 0, bool right = false) template field_t -rfield( +rField( std::basic_string const& text, int width = 8, int pad = 0) @@ -182,7 +182,7 @@ rfield( template field_t -rfield(CharT const* text, int width = 8, int pad = 0) +rField(CharT const* text, int width = 8, int pad = 0) { return field_t, std::allocator>( std:: @@ -195,7 +195,7 @@ rfield(CharT const* text, int width = 8, int pad = 0) template field_t -rfield(T const& t, int width = 8, int pad = 0) +rField(T const& t, int width = 8, int pad = 0) { std::string const text(detail::to_string(t)); return field(text, width, pad, true); diff --git a/src/xrpld/perflog/detail/PerfLogImp.cpp b/src/xrpld/perflog/detail/PerfLogImp.cpp index 4c0c4d2f6f..ceacb41223 100644 --- a/src/xrpld/perflog/detail/PerfLogImp.cpp +++ b/src/xrpld/perflog/detail/PerfLogImp.cpp @@ -103,7 +103,7 @@ PerfLogImp::Counters::countersJson() const rpcobj[jss::total] = totalRpcJson; } - Json::Value jqobj(Json::objectValue); + Json::Value jobQueueObj(Json::objectValue); // totalJq represents all jobs. All enqueued, started, finished, etc. Jq totalJq; for (auto const& proc : jq_) @@ -132,7 +132,7 @@ PerfLogImp::Counters::countersJson() const j[jss::running_duration_us] = std::to_string(value.runningDuration.count()); totalJq.runningDuration += value.runningDuration; - jqobj[JobTypes::name(proc.first)] = j; + jobQueueObj[JobTypes::name(proc.first)] = j; } if (totalJq.queued) @@ -145,14 +145,14 @@ PerfLogImp::Counters::countersJson() const std::to_string(totalJq.queuedDuration.count()); totalJqJson[jss::running_duration_us] = std::to_string(totalJq.runningDuration.count()); - jqobj[jss::total] = totalJqJson; + jobQueueObj[jss::total] = totalJqJson; } Json::Value counters(Json::objectValue); // Be kind to reporting tools and let them expect rpc and jq objects // even if empty. counters[jss::rpc] = rpcobj; - counters[jss::job_queue] = jqobj; + counters[jss::job_queue] = jobQueueObj; return counters; } diff --git a/src/xrpld/rpc/detail/RPCCall.cpp b/src/xrpld/rpc/detail/RPCCall.cpp index 5eb3943c28..30dae16e29 100644 --- a/src/xrpld/rpc/detail/RPCCall.cpp +++ b/src/xrpld/rpc/detail/RPCCall.cpp @@ -434,7 +434,7 @@ private: return jvRequest; } - // Return an error for attemping to subscribe/unsubscribe via RPC. + // Return an error for attempting to subscribe/unsubscribe via RPC. Json::Value parseEvented(Json::Value const& jvParams) { @@ -1357,7 +1357,7 @@ JSONRPCRequest( namespace { // Special local exception type thrown when request can't be parsed. -class RequestNotParseable : public std::runtime_error +class RequestNotParsable : public std::runtime_error { using std::runtime_error::runtime_error; // Inherit constructors }; @@ -1399,7 +1399,7 @@ struct RPCCallImp JLOG(j.debug()) << "RPC reply: " << strData << std::endl; if (strData.find("Unable to parse request") == 0 || strData.find(jss::invalid_API_version.c_str()) == 0) - Throw(strData); + Throw(strData); Json::Reader reader; Json::Value jvReply; if (!reader.parse(strData, jvReply)) @@ -1618,7 +1618,7 @@ rpcClient( // YYY We could have a command line flag for single line output for // scripts. YYY We would intercept output here and simplify it. } - catch (RequestNotParseable& e) + catch (RequestNotParsable& e) { jvOutput = rpcError(rpcINVALID_PARAMS); jvOutput["error_what"] = e.what(); diff --git a/src/xrpld/rpc/detail/RPCHelpers.cpp b/src/xrpld/rpc/detail/RPCHelpers.cpp index d10f4f9a5a..187f06a78e 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCHelpers.cpp @@ -95,7 +95,7 @@ readLimitField( Tuning::LimitRange const& range, JsonContext const& context) { - limit = range.rdefault; + limit = range.rDefault; if (!context.params.isMember(jss::limit) || context.params[jss::limit].isNull()) return std::nullopt; diff --git a/src/xrpld/rpc/detail/ServerHandler.cpp b/src/xrpld/rpc/detail/ServerHandler.cpp index 91b709bc06..bb84b81566 100644 --- a/src/xrpld/rpc/detail/ServerHandler.cpp +++ b/src/xrpld/rpc/detail/ServerHandler.cpp @@ -619,7 +619,8 @@ ServerHandler::processRequest( { HTTPReply( 400, - "Unable to parse request: " + reader.getFormatedErrorMessages(), + "Unable to parse request: " + + reader.getFormattedErrorMessages(), output, rpcJ); return; @@ -814,7 +815,7 @@ ServerHandler::processRequest( else if (!params.isArray() || params.size() != 1) { usage.charge(Resource::feeMalformedRPC); - HTTPReply(400, "params unparseable", output, rpcJ); + HTTPReply(400, "params unparsable", output, rpcJ); return; } else @@ -823,7 +824,7 @@ ServerHandler::processRequest( if (!params.isObjectOrNull()) { usage.charge(Resource::feeMalformedRPC); - HTTPReply(400, "params unparseable", output, rpcJ); + HTTPReply(400, "params unparsable", output, rpcJ); return; } } diff --git a/src/xrpld/rpc/detail/Tuning.h b/src/xrpld/rpc/detail/Tuning.h index 5837146b02..c0b939a4fe 100644 --- a/src/xrpld/rpc/detail/Tuning.h +++ b/src/xrpld/rpc/detail/Tuning.h @@ -11,7 +11,7 @@ namespace Tuning { /** Represents RPC limit parameter values that have a min, default and max. */ struct LimitRange { - unsigned int rmin, rdefault, rmax; + unsigned int rmin, rDefault, rmax; }; /** Limits for the account_lines command. */ diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index 30d16e3099..61d0658b4a 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -216,7 +216,7 @@ doAccountInfo(RPC::JsonContext& context) // Documentation states this is returned as part of the account_info // response, but previously the code put it under account_data. We - // can move this to the documentated location from apiVersion 2 + // can move this to the documented location from apiVersion 2 // onwards. if (context.apiVersion == 1) { @@ -262,7 +262,7 @@ doAccountInfo(RPC::JsonContext& context) { XRPL_ASSERT( prevSeqProxy < tx.seqProxy, - "rpple::doAccountInfo : first sorted proxy"); + "doAccountInfo : first sorted proxy"); prevSeqProxy = tx.seqProxy; jvTx[jss::seq] = tx.seqProxy.value(); ++seqCount; @@ -274,7 +274,7 @@ doAccountInfo(RPC::JsonContext& context) { XRPL_ASSERT( prevSeqProxy < tx.seqProxy, - "rpple::doAccountInfo : second sorted proxy"); + "doAccountInfo : second sorted proxy"); prevSeqProxy = tx.seqProxy; jvTx[jss::ticket] = tx.seqProxy.value(); ++ticketCount; diff --git a/src/xrpld/rpc/handlers/AccountTx.cpp b/src/xrpld/rpc/handlers/AccountTx.cpp index 362bdd0eaa..77d388c190 100644 --- a/src/xrpld/rpc/handlers/AccountTx.cpp +++ b/src/xrpld/rpc/handlers/AccountTx.cpp @@ -340,7 +340,7 @@ populateJsonResponse( // LCOV_EXCL_START UNREACHABLE( "xrpl::populateJsonResponse : missing " - "transaction medatata"); + "transaction metadata"); // LCOV_EXCL_STOP } } diff --git a/src/xrpld/rpc/handlers/Subscribe.cpp b/src/xrpld/rpc/handlers/Subscribe.cpp index 018268defb..09d4a54e55 100644 --- a/src/xrpld/rpc/handlers/Subscribe.cpp +++ b/src/xrpld/rpc/handlers/Subscribe.cpp @@ -334,7 +334,7 @@ doSubscribe(RPC::JsonContext& context) field == jss::asks ? reversed(book) : book, takerID ? *takerID : noAccount(), false, - RPC::Tuning::bookOffers.rdefault, + RPC::Tuning::bookOffers.rDefault, jvMarker, jvOffers); From 17565d21d4836a5673cb5ec20c68aa0a376706ed Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 8 Jan 2026 08:29:59 -0500 Subject: [PATCH 057/105] refactor: Remove unused credentials signature hash prefix (#6186) This change removes the unused credentials signature hash prefix from `HashPrefix.h`. --- include/xrpl/protocol/HashPrefix.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/xrpl/protocol/HashPrefix.h b/include/xrpl/protocol/HashPrefix.h index 77529e9212..39e03bf94f 100644 --- a/include/xrpl/protocol/HashPrefix.h +++ b/include/xrpl/protocol/HashPrefix.h @@ -67,9 +67,6 @@ enum class HashPrefix : std::uint32_t { /** Payment Channel Claim */ paymentChannelClaim = detail::make_hash_prefix('C', 'L', 'M'), - /** Credentials signature */ - credential = detail::make_hash_prefix('C', 'R', 'D'), - /** Batch */ batch = detail::make_hash_prefix('B', 'C', 'H'), }; From 510c0d82e9b3f1a4ba1a455bece99502b52613d5 Mon Sep 17 00:00:00 2001 From: Denis Angell Date: Thu, 8 Jan 2026 08:48:39 -0500 Subject: [PATCH 058/105] fix: Reorder Batch Preflight Errors (#6176) This change fixes https://github.com/XRPLF/rippled/issues/6058. --- src/test/app/Batch_test.cpp | 32 +++++++++++++++++++++++++++++++ src/xrpld/app/tx/detail/Batch.cpp | 20 +++++++++---------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/test/app/Batch_test.cpp b/src/test/app/Batch_test.cpp index 06cf5dee0c..6fbec52a93 100644 --- a/src/test/app/Batch_test.cpp +++ b/src/test/app/Batch_test.cpp @@ -402,6 +402,38 @@ class Batch_test : public beast::unit_test::suite env.close(); } + // temBAD_FEE: Inner txn with negative fee + { + auto const seq = env.seq(alice); + auto const batchFee = batch::calcBatchFee(env, 0, 2); + auto tx1 = batch::inner(pay(alice, bob, XRP(1)), seq + 1); + tx1[jss::Fee] = "-1"; + env(batch::outer(alice, seq, batchFee, tfAllOrNothing), + tx1, + batch::inner(pay(alice, bob, XRP(2)), seq + 2), + ter(temBAD_FEE)); + env.close(); + } + + // temBAD_FEE: Inner txn with non-integer fee + { + auto const seq = env.seq(alice); + auto const batchFee = batch::calcBatchFee(env, 0, 2); + auto tx1 = batch::inner(pay(alice, bob, XRP(1)), seq + 1); + tx1[jss::Fee] = "1.5"; + try + { + env(batch::outer(alice, seq, batchFee, tfAllOrNothing), + tx1, + batch::inner(pay(alice, bob, XRP(2)), seq + 2)); + fail("Expected parse_error for fractional fee"); + } + catch (jtx::parse_error const&) + { + BEAST_EXPECT(true); + } + } + // temSEQ_AND_TICKET: Batch: inner txn cannot have both Sequence // and TicketSequence. { diff --git a/src/xrpld/app/tx/detail/Batch.cpp b/src/xrpld/app/tx/detail/Batch.cpp index 277bd4e3b7..a26bc52880 100644 --- a/src/xrpld/app/tx/detail/Batch.cpp +++ b/src/xrpld/app/tx/detail/Batch.cpp @@ -305,6 +305,16 @@ Batch::preflight(PreflightContext const& ctx) } } + // Check that the Fee is native asset (XRP) and zero + if (auto const fee = stx.getFieldAmount(sfFee); + !fee.native() || fee.xrp() != beast::zero) + { + JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: " + << "inner txn must have a fee of 0. " + << "txID: " << hash; + return temBAD_FEE; + } + auto const innerAccount = stx.getAccountID(sfAccount); if (auto const preflightResult = xrpl::preflight( ctx.app, ctx.rules, parentBatchId, stx, tapBATCH, ctx.j); @@ -317,16 +327,6 @@ Batch::preflight(PreflightContext const& ctx) return temINVALID_INNER_BATCH; } - // Check that the fee is zero - if (auto const fee = stx.getFieldAmount(sfFee); - !fee.native() || fee.xrp() != beast::zero) - { - JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: " - << "inner txn must have a fee of 0. " - << "txID: " << hash; - return temBAD_FEE; - } - // Check that Sequence and TicketSequence are not both present if (stx.isFieldPresent(sfTicketSequence) && stx.getFieldU32(sfSequence) != 0) From 53aa5ca90314b6a6ba7ebb43e20a40c09b6ffe60 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 8 Jan 2026 10:34:49 -0500 Subject: [PATCH 059/105] refactor: Fix typos, enable cspell pre-commit (#5719) This change fixes the last of the spelling issues, and enables the pre-commit (and CI) check for spelling. There are no functionality changes, but it does rename some enum values. --- .config/cspell.config.yaml | 4 +- .gitattributes | 1 + .github/scripts/levelization/README.md | 2 +- .github/scripts/levelization/generate.sh | 6 +- .github/scripts/rename/README.md | 2 +- .github/scripts/rename/config.sh | 2 +- .github/scripts/rename/copyright.sh | 12 +- .gitignore | 1 + .pre-commit-config.yaml | 28 ++-- include/xrpl/proto/xrpl.proto | 6 +- include/xrpl/protocol/Permissions.h | 2 +- .../xrpl/protocol/detail/transactions.macro | 152 +++++++++--------- src/libxrpl/protocol/Permissions.cpp | 6 +- src/test/app/ValidatorList_test.cpp | 5 +- src/test/overlay/compression_test.cpp | 4 +- .../ledger/detail/LedgerReplayMsgHandler.cpp | 2 +- src/xrpld/app/misc/detail/ValidatorList.cpp | 9 +- src/xrpld/app/tx/detail/InvariantCheck.cpp | 6 +- src/xrpld/overlay/detail/Message.cpp | 4 +- src/xrpld/overlay/detail/ProtocolMessage.h | 8 +- src/xrpld/overlay/detail/TrafficCount.cpp | 4 +- 21 files changed, 136 insertions(+), 130 deletions(-) diff --git a/.config/cspell.config.yaml b/.config/cspell.config.yaml index 969720a11d..0cac82807d 100644 --- a/.config/cspell.config.yaml +++ b/.config/cspell.config.yaml @@ -83,7 +83,6 @@ words: - doxyfile - dxrpl - endmacro - - endpointv - exceptioned - Falco - finalizers @@ -92,6 +91,7 @@ words: - funclets - gcov - gcovr + - ghead - Gnutella - gpgcheck - gpgkey @@ -221,6 +221,8 @@ words: - takergets - takerpays - ters + - TMEndpointv2 + - trixie - tx - txid - txids diff --git a/.gitattributes b/.gitattributes index bdfc989327..7a066d0967 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ # Set default behaviour, in case users don't have core.autocrlf set. #* text=auto +# cspell: disable # Visual Studio *.sln text eol=crlf diff --git a/.github/scripts/levelization/README.md b/.github/scripts/levelization/README.md index c8954b900e..c3e6ffa4a8 100644 --- a/.github/scripts/levelization/README.md +++ b/.github/scripts/levelization/README.md @@ -84,7 +84,7 @@ It generates many files of [results](results): to the destination module, de-duped, and with frequency counts. - `includes/`: A directory where each file represents a module and contains a list of modules and counts that the module _includes_. -- `includedby/`: Similar to `includes/`, but the other way around. Each +- `included_by/`: Similar to `includes/`, but the other way around. Each file represents a module and contains a list of modules and counts that _include_ the module. - [`loops.txt`](results/loops.txt): A list of direct loops detected diff --git a/.github/scripts/levelization/generate.sh b/.github/scripts/levelization/generate.sh index 775ddf789f..d700c7a206 100755 --- a/.github/scripts/levelization/generate.sh +++ b/.github/scripts/levelization/generate.sh @@ -29,7 +29,7 @@ pushd results oldifs=${IFS} IFS=: mkdir includes -mkdir includedby +mkdir included_by echo Build levelization paths exec 3< ${includes} # open rawincludes.txt for input while read -r -u 3 file include @@ -59,7 +59,7 @@ do echo $level $includelevel | tee -a paths.txt fi done -echo Sort and dedup paths +echo Sort and deduplicate paths sort -ds paths.txt | uniq -c | tee sortedpaths.txt mv sortedpaths.txt paths.txt exec 3>&- #close fd 3 @@ -71,7 +71,7 @@ exec 4&- #close fd 4 diff --git a/.github/scripts/rename/README.md b/.github/scripts/rename/README.md index 8336f23bec..cc004a335f 100644 --- a/.github/scripts/rename/README.md +++ b/.github/scripts/rename/README.md @@ -19,7 +19,7 @@ run from the repository root. 1. `.github/scripts/rename/definitions.sh`: This script will rename all definitions, such as include guards, from `RIPPLE_XXX` and `RIPPLED_XXX` to `XRPL_XXX`. -2. `.github/scripts/rename/copyright.sh`: This script will remove superflous +2. `.github/scripts/rename/copyright.sh`: This script will remove superfluous copyright notices. 3. `.github/scripts/rename/cmake.sh`: This script will rename all CMake files from `RippleXXX.cmake` or `RippledXXX.cmake` to `XrplXXX.cmake`, and any diff --git a/.github/scripts/rename/config.sh b/.github/scripts/rename/config.sh index 7f36e8fd21..f6e914f502 100755 --- a/.github/scripts/rename/config.sh +++ b/.github/scripts/rename/config.sh @@ -56,7 +56,7 @@ for DIRECTORY in "${DIRECTORIES[@]}"; do done ${SED_COMMAND} -i 's/rippled/xrpld/g' cfg/xrpld-example.cfg ${SED_COMMAND} -i 's/rippled/xrpld/g' src/test/core/Config_test.cpp -${SED_COMMAND} -i 's/ripplevalidators/xrplvalidators/g' src/test/core/Config_test.cpp +${SED_COMMAND} -i 's/ripplevalidators/xrplvalidators/g' src/test/core/Config_test.cpp # cspell: disable-line ${SED_COMMAND} -i 's/rippleConfig/xrpldConfig/g' src/test/core/Config_test.cpp ${SED_COMMAND} -i 's@ripple/@xrpld/@g' src/test/core/Config_test.cpp ${SED_COMMAND} -i 's/Rippled/File/g' src/test/core/Config_test.cpp diff --git a/.github/scripts/rename/copyright.sh b/.github/scripts/rename/copyright.sh index 41dbdc1f94..c5a9fb2cd3 100755 --- a/.github/scripts/rename/copyright.sh +++ b/.github/scripts/rename/copyright.sh @@ -50,11 +50,11 @@ for DIRECTORY in "${DIRECTORIES[@]}"; do # Handle the cases where the copyright notice is enclosed in /* ... */ # and usually surrounded by //---- and //======. ${SED_COMMAND} -z -i -E 's@^//-------+\n+@@' "${FILE}" - ${SED_COMMAND} -z -i -E 's@^.*Copyright.+(Ripple|Bougalis|Falco|Hinnant|Null|Ritchford|XRPLF).+PERFORMANCE OF THIS SOFTWARE\.\n\*/\n+@@' "${FILE}" + ${SED_COMMAND} -z -i -E 's@^.*Copyright.+(Ripple|Bougalis|Falco|Hinnant|Null|Ritchford|XRPLF).+PERFORMANCE OF THIS SOFTWARE\.\n\*/\n+@@' "${FILE}" # cspell: ignore Bougalis Falco Hinnant Ritchford ${SED_COMMAND} -z -i -E 's@^//=======+\n+@@' "${FILE}" # Handle the cases where the copyright notice is commented out with //. - ${SED_COMMAND} -z -i -E 's@^//\n// Copyright.+Falco \(vinnie dot falco at gmail dot com\)\n//\n+@@' "${FILE}" + ${SED_COMMAND} -z -i -E 's@^//\n// Copyright.+Falco \(vinnie dot falco at gmail dot com\)\n//\n+@@' "${FILE}" # cspell: ignore Vinnie Falco done done @@ -83,16 +83,16 @@ if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/ValidatorInfo.cpp; then echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/ValidatorInfo.cpp fi if ! grep -q 'Bougalis' include/xrpl/basics/SlabAllocator.h; then - echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis \n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h + echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis \n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb fi if ! grep -q 'Bougalis' include/xrpl/basics/spinlock.h; then - echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis \n\n$(cat include/xrpl/basics/spinlock.h)" > include/xrpl/basics/spinlock.h + echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis \n\n$(cat include/xrpl/basics/spinlock.h)" > include/xrpl/basics/spinlock.h # cspell: ignore Nikolaos Bougalis nikb fi if ! grep -q 'Bougalis' include/xrpl/basics/tagged_integer.h; then - echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis \n\n$(cat include/xrpl/basics/tagged_integer.h)" > include/xrpl/basics/tagged_integer.h + echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis \n\n$(cat include/xrpl/basics/tagged_integer.h)" > include/xrpl/basics/tagged_integer.h # cspell: ignore Nikolaos Bougalis nikb fi if ! grep -q 'Ritchford' include/xrpl/beast/utility/Zero.h; then - echo -e "// Copyright (c) 2014, Tom Ritchford \n\n$(cat include/xrpl/beast/utility/Zero.h)" > include/xrpl/beast/utility/Zero.h + echo -e "// Copyright (c) 2014, Tom Ritchford \n\n$(cat include/xrpl/beast/utility/Zero.h)" > include/xrpl/beast/utility/Zero.h # cspell: ignore Ritchford fi # Restore newlines and tabs in string literals in the affected file. diff --git a/.gitignore b/.gitignore index c4e81408bb..b899cf8436 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # .gitignore +# cspell: disable # Macintosh Desktop Services Store files. .DS_Store diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4a1dc159dc..00bec32ed6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,20 +36,20 @@ repos: hooks: - id: black - # - repo: https://github.com/streetsidesoftware/cspell-cli - # rev: v9.2.0 - # hooks: - # - id: cspell # Spell check changed files - # - id: cspell # Spell check the commit message - # name: check commit message spelling - # args: - # - --no-must-find-files - # - --no-progress - # - --no-summary - # - --files - # - .git/COMMIT_EDITMSG - # stages: [commit-msg] - # always_run: true # This might not be necessary. + - repo: https://github.com/streetsidesoftware/cspell-cli + rev: v9.2.0 + hooks: + - id: cspell # Spell check changed files + exclude: .config/cspell.config.yaml + - id: cspell # Spell check the commit message + name: check commit message spelling + args: + - --no-must-find-files + - --no-progress + - --no-summary + - --files + - .git/COMMIT_EDITMSG + stages: [commit-msg] exclude: | (?x)^( diff --git a/include/xrpl/proto/xrpl.proto b/include/xrpl/proto/xrpl.proto index f93ebbc72c..613ef70a1f 100644 --- a/include/xrpl/proto/xrpl.proto +++ b/include/xrpl/proto/xrpl.proto @@ -17,9 +17,9 @@ enum MessageType { mtHAVE_SET = 35; mtVALIDATION = 41; mtGET_OBJECTS = 42; - mtVALIDATORLIST = 54; + mtVALIDATOR_LIST = 54; mtSQUELCH = 55; - mtVALIDATORLISTCOLLECTION = 56; + mtVALIDATOR_LIST_COLLECTION = 56; mtPROOF_PATH_REQ = 57; mtPROOF_PATH_RESPONSE = 58; mtREPLAY_DELTA_REQ = 59; @@ -308,7 +308,7 @@ message TMSquelch { } enum TMLedgerMapType { - lmTRANASCTION = 1; // transaction map + lmTRANSACTION = 1; // transaction map lmACCOUNT_STATE = 2; // account state map } diff --git a/include/xrpl/protocol/Permissions.h b/include/xrpl/protocol/Permissions.h index 319aeb1c28..74f539a3bf 100644 --- a/include/xrpl/protocol/Permissions.h +++ b/include/xrpl/protocol/Permissions.h @@ -29,7 +29,7 @@ enum GranularPermissionType : std::uint32_t { #pragma pop_macro("PERMISSION") }; -enum Delegation { delegatable, notDelegatable }; +enum Delegation { delegable, notDelegable }; class Permission { diff --git a/include/xrpl/protocol/detail/transactions.macro b/include/xrpl/protocol/detail/transactions.macro index 6d2d833440..bc7eefedb5 100644 --- a/include/xrpl/protocol/detail/transactions.macro +++ b/include/xrpl/protocol/detail/transactions.macro @@ -3,7 +3,7 @@ #endif /** - * TRANSACTION(tag, value, name, delegatable, amendments, privileges, fields) + * TRANSACTION(tag, value, name, delegable, amendments, privileges, fields) * * To ease maintenance, you may replace any unneeded values with "..." * e.g. #define TRANSACTION(tag, value, name, ...) @@ -25,7 +25,7 @@ # include #endif TRANSACTION(ttPAYMENT, 0, Payment, - Delegation::delegatable, + Delegation::delegable, uint256{}, createAcct, ({ @@ -45,7 +45,7 @@ TRANSACTION(ttPAYMENT, 0, Payment, # include #endif TRANSACTION(ttESCROW_CREATE, 1, EscrowCreate, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -59,7 +59,7 @@ TRANSACTION(ttESCROW_CREATE, 1, EscrowCreate, /** This transaction type completes an existing escrow. */ TRANSACTION(ttESCROW_FINISH, 2, EscrowFinish, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -76,7 +76,7 @@ TRANSACTION(ttESCROW_FINISH, 2, EscrowFinish, # include #endif TRANSACTION(ttACCOUNT_SET, 3, AccountSet, - Delegation::notDelegatable, + Delegation::notDelegable, uint256{}, noPriv, ({ @@ -97,7 +97,7 @@ TRANSACTION(ttACCOUNT_SET, 3, AccountSet, # include #endif TRANSACTION(ttESCROW_CANCEL, 4, EscrowCancel, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -110,7 +110,7 @@ TRANSACTION(ttESCROW_CANCEL, 4, EscrowCancel, # include #endif TRANSACTION(ttREGULAR_KEY_SET, 5, SetRegularKey, - Delegation::notDelegatable, + Delegation::notDelegable, uint256{}, noPriv, ({ @@ -124,7 +124,7 @@ TRANSACTION(ttREGULAR_KEY_SET, 5, SetRegularKey, # include #endif TRANSACTION(ttOFFER_CREATE, 7, OfferCreate, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -140,7 +140,7 @@ TRANSACTION(ttOFFER_CREATE, 7, OfferCreate, # include #endif TRANSACTION(ttOFFER_CANCEL, 8, OfferCancel, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -154,7 +154,7 @@ TRANSACTION(ttOFFER_CANCEL, 8, OfferCancel, # include #endif TRANSACTION(ttTICKET_CREATE, 10, TicketCreate, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -170,7 +170,7 @@ TRANSACTION(ttTICKET_CREATE, 10, TicketCreate, # include #endif TRANSACTION(ttSIGNER_LIST_SET, 12, SignerListSet, - Delegation::notDelegatable, + Delegation::notDelegable, uint256{}, noPriv, ({ @@ -183,7 +183,7 @@ TRANSACTION(ttSIGNER_LIST_SET, 12, SignerListSet, # include #endif TRANSACTION(ttPAYCHAN_CREATE, 13, PaymentChannelCreate, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -197,7 +197,7 @@ TRANSACTION(ttPAYCHAN_CREATE, 13, PaymentChannelCreate, /** This transaction type funds an existing unidirectional XRP payment channel. */ TRANSACTION(ttPAYCHAN_FUND, 14, PaymentChannelFund, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -208,7 +208,7 @@ TRANSACTION(ttPAYCHAN_FUND, 14, PaymentChannelFund, /** This transaction type submits a claim against an existing unidirectional payment channel. */ TRANSACTION(ttPAYCHAN_CLAIM, 15, PaymentChannelClaim, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -225,7 +225,7 @@ TRANSACTION(ttPAYCHAN_CLAIM, 15, PaymentChannelClaim, # include #endif TRANSACTION(ttCHECK_CREATE, 16, CheckCreate, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -241,7 +241,7 @@ TRANSACTION(ttCHECK_CREATE, 16, CheckCreate, # include #endif TRANSACTION(ttCHECK_CASH, 17, CheckCash, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -255,7 +255,7 @@ TRANSACTION(ttCHECK_CASH, 17, CheckCash, # include #endif TRANSACTION(ttCHECK_CANCEL, 18, CheckCancel, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -267,7 +267,7 @@ TRANSACTION(ttCHECK_CANCEL, 18, CheckCancel, # include #endif TRANSACTION(ttDEPOSIT_PREAUTH, 19, DepositPreauth, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -282,7 +282,7 @@ TRANSACTION(ttDEPOSIT_PREAUTH, 19, DepositPreauth, # include #endif TRANSACTION(ttTRUST_SET, 20, TrustSet, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -296,7 +296,7 @@ TRANSACTION(ttTRUST_SET, 20, TrustSet, # include #endif TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete, - Delegation::notDelegatable, + Delegation::notDelegable, uint256{}, mustDeleteAcct, ({ @@ -312,7 +312,7 @@ TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete, # include #endif TRANSACTION(ttNFTOKEN_MINT, 25, NFTokenMint, - Delegation::delegatable, + Delegation::delegable, uint256{}, changeNFTCounts, ({ @@ -330,7 +330,7 @@ TRANSACTION(ttNFTOKEN_MINT, 25, NFTokenMint, # include #endif TRANSACTION(ttNFTOKEN_BURN, 26, NFTokenBurn, - Delegation::delegatable, + Delegation::delegable, uint256{}, changeNFTCounts, ({ @@ -343,7 +343,7 @@ TRANSACTION(ttNFTOKEN_BURN, 26, NFTokenBurn, # include #endif TRANSACTION(ttNFTOKEN_CREATE_OFFER, 27, NFTokenCreateOffer, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -359,7 +359,7 @@ TRANSACTION(ttNFTOKEN_CREATE_OFFER, 27, NFTokenCreateOffer, # include #endif TRANSACTION(ttNFTOKEN_CANCEL_OFFER, 28, NFTokenCancelOffer, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -371,7 +371,7 @@ TRANSACTION(ttNFTOKEN_CANCEL_OFFER, 28, NFTokenCancelOffer, # include #endif TRANSACTION(ttNFTOKEN_ACCEPT_OFFER, 29, NFTokenAcceptOffer, - Delegation::delegatable, + Delegation::delegable, uint256{}, noPriv, ({ @@ -385,7 +385,7 @@ TRANSACTION(ttNFTOKEN_ACCEPT_OFFER, 29, NFTokenAcceptOffer, # include #endif TRANSACTION(ttCLAWBACK, 30, Clawback, - Delegation::delegatable, + Delegation::delegable, featureClawback, noPriv, ({ @@ -398,7 +398,7 @@ TRANSACTION(ttCLAWBACK, 30, Clawback, # include #endif TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback, - Delegation::delegatable, + Delegation::delegable, featureAMMClawback, mayDeleteAcct | overrideFreeze, ({ @@ -413,7 +413,7 @@ TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback, # include #endif TRANSACTION(ttAMM_CREATE, 35, AMMCreate, - Delegation::delegatable, + Delegation::delegable, featureAMM, createPseudoAcct, ({ @@ -427,7 +427,7 @@ TRANSACTION(ttAMM_CREATE, 35, AMMCreate, # include #endif TRANSACTION(ttAMM_DEPOSIT, 36, AMMDeposit, - Delegation::delegatable, + Delegation::delegable, featureAMM, noPriv, ({ @@ -445,7 +445,7 @@ TRANSACTION(ttAMM_DEPOSIT, 36, AMMDeposit, # include #endif TRANSACTION(ttAMM_WITHDRAW, 37, AMMWithdraw, - Delegation::delegatable, + Delegation::delegable, featureAMM, mayDeleteAcct, ({ @@ -462,7 +462,7 @@ TRANSACTION(ttAMM_WITHDRAW, 37, AMMWithdraw, # include #endif TRANSACTION(ttAMM_VOTE, 38, AMMVote, - Delegation::delegatable, + Delegation::delegable, featureAMM, noPriv, ({ @@ -476,7 +476,7 @@ TRANSACTION(ttAMM_VOTE, 38, AMMVote, # include #endif TRANSACTION(ttAMM_BID, 39, AMMBid, - Delegation::delegatable, + Delegation::delegable, featureAMM, noPriv, ({ @@ -492,7 +492,7 @@ TRANSACTION(ttAMM_BID, 39, AMMBid, # include #endif TRANSACTION(ttAMM_DELETE, 40, AMMDelete, - Delegation::delegatable, + Delegation::delegable, featureAMM, mustDeleteAcct, ({ @@ -505,7 +505,7 @@ TRANSACTION(ttAMM_DELETE, 40, AMMDelete, # include #endif TRANSACTION(ttXCHAIN_CREATE_CLAIM_ID, 41, XChainCreateClaimID, - Delegation::delegatable, + Delegation::delegable, featureXChainBridge, noPriv, ({ @@ -516,7 +516,7 @@ TRANSACTION(ttXCHAIN_CREATE_CLAIM_ID, 41, XChainCreateClaimID, /** This transactions initiates a crosschain transaction */ TRANSACTION(ttXCHAIN_COMMIT, 42, XChainCommit, - Delegation::delegatable, + Delegation::delegable, featureXChainBridge, noPriv, ({ @@ -528,7 +528,7 @@ TRANSACTION(ttXCHAIN_COMMIT, 42, XChainCommit, /** This transaction completes a crosschain transaction */ TRANSACTION(ttXCHAIN_CLAIM, 43, XChainClaim, - Delegation::delegatable, + Delegation::delegable, featureXChainBridge, noPriv, ({ @@ -541,7 +541,7 @@ TRANSACTION(ttXCHAIN_CLAIM, 43, XChainClaim, /** This transaction initiates a crosschain account create transaction */ TRANSACTION(ttXCHAIN_ACCOUNT_CREATE_COMMIT, 44, XChainAccountCreateCommit, - Delegation::delegatable, + Delegation::delegable, featureXChainBridge, noPriv, ({ @@ -553,7 +553,7 @@ TRANSACTION(ttXCHAIN_ACCOUNT_CREATE_COMMIT, 44, XChainAccountCreateCommit, /** This transaction adds an attestation to a claim */ TRANSACTION(ttXCHAIN_ADD_CLAIM_ATTESTATION, 45, XChainAddClaimAttestation, - Delegation::delegatable, + Delegation::delegable, featureXChainBridge, createAcct, ({ @@ -574,7 +574,7 @@ TRANSACTION(ttXCHAIN_ADD_CLAIM_ATTESTATION, 45, XChainAddClaimAttestation, /** This transaction adds an attestation to an account */ TRANSACTION(ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION, 46, XChainAddAccountCreateAttestation, - Delegation::delegatable, + Delegation::delegable, featureXChainBridge, createAcct, ({ @@ -595,7 +595,7 @@ TRANSACTION(ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION, 46, /** This transaction modifies a sidechain */ TRANSACTION(ttXCHAIN_MODIFY_BRIDGE, 47, XChainModifyBridge, - Delegation::delegatable, + Delegation::delegable, featureXChainBridge, noPriv, ({ @@ -606,7 +606,7 @@ TRANSACTION(ttXCHAIN_MODIFY_BRIDGE, 47, XChainModifyBridge, /** This transactions creates a sidechain */ TRANSACTION(ttXCHAIN_CREATE_BRIDGE, 48, XChainCreateBridge, - Delegation::delegatable, + Delegation::delegable, featureXChainBridge, noPriv, ({ @@ -620,7 +620,7 @@ TRANSACTION(ttXCHAIN_CREATE_BRIDGE, 48, XChainCreateBridge, # include #endif TRANSACTION(ttDID_SET, 49, DIDSet, - Delegation::delegatable, + Delegation::delegable, featureDID, noPriv, ({ @@ -631,7 +631,7 @@ TRANSACTION(ttDID_SET, 49, DIDSet, /** This transaction type deletes a DID */ TRANSACTION(ttDID_DELETE, 50, DIDDelete, - Delegation::delegatable, + Delegation::delegable, featureDID, noPriv, ({})) @@ -641,7 +641,7 @@ TRANSACTION(ttDID_DELETE, 50, DIDDelete, # include #endif TRANSACTION(ttORACLE_SET, 51, OracleSet, - Delegation::delegatable, + Delegation::delegable, featurePriceOracle, noPriv, ({ @@ -658,7 +658,7 @@ TRANSACTION(ttORACLE_SET, 51, OracleSet, # include #endif TRANSACTION(ttORACLE_DELETE, 52, OracleDelete, - Delegation::delegatable, + Delegation::delegable, featurePriceOracle, noPriv, ({ @@ -670,7 +670,7 @@ TRANSACTION(ttORACLE_DELETE, 52, OracleDelete, # include #endif TRANSACTION(ttLEDGER_STATE_FIX, 53, LedgerStateFix, - Delegation::delegatable, + Delegation::delegable, fixNFTokenPageLinks, noPriv, ({ @@ -683,7 +683,7 @@ TRANSACTION(ttLEDGER_STATE_FIX, 53, LedgerStateFix, # include #endif TRANSACTION(ttMPTOKEN_ISSUANCE_CREATE, 54, MPTokenIssuanceCreate, - Delegation::delegatable, + Delegation::delegable, featureMPTokensV1, createMPTIssuance, ({ @@ -700,7 +700,7 @@ TRANSACTION(ttMPTOKEN_ISSUANCE_CREATE, 54, MPTokenIssuanceCreate, # include #endif TRANSACTION(ttMPTOKEN_ISSUANCE_DESTROY, 55, MPTokenIssuanceDestroy, - Delegation::delegatable, + Delegation::delegable, featureMPTokensV1, destroyMPTIssuance, ({ @@ -712,7 +712,7 @@ TRANSACTION(ttMPTOKEN_ISSUANCE_DESTROY, 55, MPTokenIssuanceDestroy, # include #endif TRANSACTION(ttMPTOKEN_ISSUANCE_SET, 56, MPTokenIssuanceSet, - Delegation::delegatable, + Delegation::delegable, featureMPTokensV1, noPriv, ({ @@ -729,7 +729,7 @@ TRANSACTION(ttMPTOKEN_ISSUANCE_SET, 56, MPTokenIssuanceSet, # include #endif TRANSACTION(ttMPTOKEN_AUTHORIZE, 57, MPTokenAuthorize, - Delegation::delegatable, + Delegation::delegable, featureMPTokensV1, mustAuthorizeMPT, ({ @@ -742,7 +742,7 @@ TRANSACTION(ttMPTOKEN_AUTHORIZE, 57, MPTokenAuthorize, # include #endif TRANSACTION(ttCREDENTIAL_CREATE, 58, CredentialCreate, - Delegation::delegatable, + Delegation::delegable, featureCredentials, noPriv, ({ @@ -754,7 +754,7 @@ TRANSACTION(ttCREDENTIAL_CREATE, 58, CredentialCreate, /** This transaction type accept an Credential object */ TRANSACTION(ttCREDENTIAL_ACCEPT, 59, CredentialAccept, - Delegation::delegatable, + Delegation::delegable, featureCredentials, noPriv, ({ @@ -764,7 +764,7 @@ TRANSACTION(ttCREDENTIAL_ACCEPT, 59, CredentialAccept, /** This transaction type delete an Credential object */ TRANSACTION(ttCREDENTIAL_DELETE, 60, CredentialDelete, - Delegation::delegatable, + Delegation::delegable, featureCredentials, noPriv, ({ @@ -778,7 +778,7 @@ TRANSACTION(ttCREDENTIAL_DELETE, 60, CredentialDelete, # include #endif TRANSACTION(ttNFTOKEN_MODIFY, 61, NFTokenModify, - Delegation::delegatable, + Delegation::delegable, featureDynamicNFT, noPriv, ({ @@ -792,7 +792,7 @@ TRANSACTION(ttNFTOKEN_MODIFY, 61, NFTokenModify, # include #endif TRANSACTION(ttPERMISSIONED_DOMAIN_SET, 62, PermissionedDomainSet, - Delegation::delegatable, + Delegation::delegable, featurePermissionedDomains, noPriv, ({ @@ -805,7 +805,7 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_SET, 62, PermissionedDomainSet, # include #endif TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 63, PermissionedDomainDelete, - Delegation::delegatable, + Delegation::delegable, featurePermissionedDomains, noPriv, ({ @@ -817,7 +817,7 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 63, PermissionedDomainDelete, # include #endif TRANSACTION(ttDELEGATE_SET, 64, DelegateSet, - Delegation::notDelegatable, + Delegation::notDelegable, featurePermissionDelegationV1_1, noPriv, ({ @@ -830,7 +830,7 @@ TRANSACTION(ttDELEGATE_SET, 64, DelegateSet, # include #endif TRANSACTION(ttVAULT_CREATE, 65, VaultCreate, - Delegation::delegatable, + Delegation::delegable, featureSingleAssetVault, createPseudoAcct | createMPTIssuance | mustModifyVault, ({ @@ -848,7 +848,7 @@ TRANSACTION(ttVAULT_CREATE, 65, VaultCreate, # include #endif TRANSACTION(ttVAULT_SET, 66, VaultSet, - Delegation::delegatable, + Delegation::delegable, featureSingleAssetVault, mustModifyVault, ({ @@ -863,7 +863,7 @@ TRANSACTION(ttVAULT_SET, 66, VaultSet, # include #endif TRANSACTION(ttVAULT_DELETE, 67, VaultDelete, - Delegation::delegatable, + Delegation::delegable, featureSingleAssetVault, mustDeleteAcct | destroyMPTIssuance | mustModifyVault, ({ @@ -875,7 +875,7 @@ TRANSACTION(ttVAULT_DELETE, 67, VaultDelete, # include #endif TRANSACTION(ttVAULT_DEPOSIT, 68, VaultDeposit, - Delegation::delegatable, + Delegation::delegable, featureSingleAssetVault, mayAuthorizeMPT | mustModifyVault, ({ @@ -888,7 +888,7 @@ TRANSACTION(ttVAULT_DEPOSIT, 68, VaultDeposit, # include #endif TRANSACTION(ttVAULT_WITHDRAW, 69, VaultWithdraw, - Delegation::delegatable, + Delegation::delegable, featureSingleAssetVault, mayDeleteMPT | mayAuthorizeMPT | mustModifyVault, ({ @@ -903,7 +903,7 @@ TRANSACTION(ttVAULT_WITHDRAW, 69, VaultWithdraw, # include #endif TRANSACTION(ttVAULT_CLAWBACK, 70, VaultClawback, - Delegation::delegatable, + Delegation::delegable, featureSingleAssetVault, mayDeleteMPT | mustModifyVault, ({ @@ -917,7 +917,7 @@ TRANSACTION(ttVAULT_CLAWBACK, 70, VaultClawback, # include #endif TRANSACTION(ttBATCH, 71, Batch, - Delegation::notDelegatable, + Delegation::notDelegable, featureBatch, noPriv, ({ @@ -932,7 +932,7 @@ TRANSACTION(ttBATCH, 71, Batch, # include #endif TRANSACTION(ttLOAN_BROKER_SET, 74, LoanBrokerSet, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, createPseudoAcct | mayAuthorizeMPT, ({ {sfVaultID, soeREQUIRED}, @@ -949,7 +949,7 @@ TRANSACTION(ttLOAN_BROKER_SET, 74, LoanBrokerSet, # include #endif TRANSACTION(ttLOAN_BROKER_DELETE, 75, LoanBrokerDelete, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, mustDeleteAcct | mayAuthorizeMPT, ({ {sfLoanBrokerID, soeREQUIRED}, @@ -960,7 +960,7 @@ TRANSACTION(ttLOAN_BROKER_DELETE, 75, LoanBrokerDelete, # include #endif TRANSACTION(ttLOAN_BROKER_COVER_DEPOSIT, 76, LoanBrokerCoverDeposit, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, noPriv, ({ {sfLoanBrokerID, soeREQUIRED}, @@ -972,7 +972,7 @@ TRANSACTION(ttLOAN_BROKER_COVER_DEPOSIT, 76, LoanBrokerCoverDeposit, # include #endif TRANSACTION(ttLOAN_BROKER_COVER_WITHDRAW, 77, LoanBrokerCoverWithdraw, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, mayAuthorizeMPT, ({ {sfLoanBrokerID, soeREQUIRED}, @@ -987,7 +987,7 @@ TRANSACTION(ttLOAN_BROKER_COVER_WITHDRAW, 77, LoanBrokerCoverWithdraw, # include #endif TRANSACTION(ttLOAN_BROKER_COVER_CLAWBACK, 78, LoanBrokerCoverClawback, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, noPriv, ({ {sfLoanBrokerID, soeOPTIONAL}, @@ -999,7 +999,7 @@ TRANSACTION(ttLOAN_BROKER_COVER_CLAWBACK, 78, LoanBrokerCoverClawback, # include #endif TRANSACTION(ttLOAN_SET, 80, LoanSet, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, mayAuthorizeMPT | mustModifyVault, ({ {sfLoanBrokerID, soeREQUIRED}, @@ -1026,7 +1026,7 @@ TRANSACTION(ttLOAN_SET, 80, LoanSet, # include #endif TRANSACTION(ttLOAN_DELETE, 81, LoanDelete, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, noPriv, ({ {sfLoanID, soeREQUIRED}, @@ -1037,7 +1037,7 @@ TRANSACTION(ttLOAN_DELETE, 81, LoanDelete, # include #endif TRANSACTION(ttLOAN_MANAGE, 82, LoanManage, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, // All of the LoanManage options will modify the vault, but the // transaction can succeed without options, essentially making it @@ -1051,7 +1051,7 @@ TRANSACTION(ttLOAN_MANAGE, 82, LoanManage, # include #endif TRANSACTION(ttLOAN_PAY, 84, LoanPay, - Delegation::delegatable, + Delegation::delegable, featureLendingProtocol, mayAuthorizeMPT | mustModifyVault, ({ {sfLoanID, soeREQUIRED}, @@ -1066,7 +1066,7 @@ TRANSACTION(ttLOAN_PAY, 84, LoanPay, # include #endif TRANSACTION(ttAMENDMENT, 100, EnableAmendment, - Delegation::notDelegatable, + Delegation::notDelegable, uint256{}, noPriv, ({ @@ -1078,7 +1078,7 @@ TRANSACTION(ttAMENDMENT, 100, EnableAmendment, For details, see: https://xrpl.org/fee-voting.html */ TRANSACTION(ttFEE, 101, SetFee, - Delegation::notDelegatable, + Delegation::notDelegable, uint256{}, noPriv, ({ @@ -1099,7 +1099,7 @@ TRANSACTION(ttFEE, 101, SetFee, For details, see: https://xrpl.org/negative-unl.html */ TRANSACTION(ttUNL_MODIFY, 102, UNLModify, - Delegation::notDelegatable, + Delegation::notDelegable, uint256{}, noPriv, ({ diff --git a/src/libxrpl/protocol/Permissions.cpp b/src/libxrpl/protocol/Permissions.cpp index 55b273e246..082a1792a4 100644 --- a/src/libxrpl/protocol/Permissions.cpp +++ b/src/libxrpl/protocol/Permissions.cpp @@ -11,7 +11,7 @@ Permission::Permission() #pragma push_macro("TRANSACTION") #undef TRANSACTION -#define TRANSACTION(tag, value, name, delegatable, amendment, ...) \ +#define TRANSACTION(tag, value, name, delegable, amendment, ...) \ {value, amendment}, #include @@ -24,7 +24,7 @@ Permission::Permission() #pragma push_macro("TRANSACTION") #undef TRANSACTION -#define TRANSACTION(tag, value, name, delegatable, ...) {value, delegatable}, +#define TRANSACTION(tag, value, name, delegable, ...) {value, delegable}, #include @@ -170,7 +170,7 @@ Permission::isDelegable( !rules.enabled(txFeaturesIt->second)) return false; - if (it->second == Delegation::notDelegatable) + if (it->second == Delegation::notDelegable) return false; return true; diff --git a/src/test/app/ValidatorList_test.cpp b/src/test/app/ValidatorList_test.cpp index 163e4f632c..fa3c836cca 100644 --- a/src/test/app/ValidatorList_test.cpp +++ b/src/test/app/ValidatorList_test.cpp @@ -2370,7 +2370,8 @@ private: &extractHeader](Message& message) { auto [header, buffers] = extractHeader(message); if (BEAST_EXPECT(header) && - BEAST_EXPECT(header->message_type == protocol::mtVALIDATORLIST)) + BEAST_EXPECT( + header->message_type == protocol::mtVALIDATOR_LIST)) { auto const msg = detail::parseMessageContent( @@ -2386,7 +2387,7 @@ private: if (BEAST_EXPECT(header) && BEAST_EXPECT( header->message_type == - protocol::mtVALIDATORLISTCOLLECTION)) + protocol::mtVALIDATOR_LIST_COLLECTION)) { auto const msg = detail::parseMessageContent< protocol::TMValidatorListCollection>( diff --git a/src/test/overlay/compression_test.cpp b/src/test/overlay/compression_test.cpp index 2be69a74c9..f2fe07cb33 100644 --- a/src/test/overlay/compression_test.cpp +++ b/src/test/overlay/compression_test.cpp @@ -436,12 +436,12 @@ public: // 895B doTest( buildValidatorList(), - protocol::mtVALIDATORLIST, + protocol::mtVALIDATOR_LIST, 4, "TMValidatorList"); doTest( buildValidatorListCollection(), - protocol::mtVALIDATORLISTCOLLECTION, + protocol::mtVALIDATOR_LIST_COLLECTION, 4, "TMValidatorListCollection"); } diff --git a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp index e1eb51fda7..9356f17af0 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp @@ -53,7 +53,7 @@ LedgerReplayMsgHandler::processProofPathRequest( { case protocol::lmACCOUNT_STATE: return ledger->stateMap().getProofPath(key); - case protocol::lmTRANASCTION: + case protocol::lmTRANSACTION: return ledger->txMap().getProofPath(key); default: // should not be here diff --git a/src/xrpld/app/misc/detail/ValidatorList.cpp b/src/xrpld/app/misc/detail/ValidatorList.cpp index 12ba52fa36..5c1c5e80a1 100644 --- a/src/xrpld/app/misc/detail/ValidatorList.cpp +++ b/src/xrpld/app/misc/detail/ValidatorList.cpp @@ -528,7 +528,7 @@ splitMessageParts( "xrpl::splitMessageParts : maximum message size"); messages.emplace_back( - std::make_shared(smallMsg, protocol::mtVALIDATORLIST), + std::make_shared(smallMsg, protocol::mtVALIDATOR_LIST), sha512Half(smallMsg), 1); return messages.back().numVLs; @@ -555,7 +555,7 @@ splitMessageParts( { messages.emplace_back( std::make_shared( - *smallMsg, protocol::mtVALIDATORLISTCOLLECTION), + *smallMsg, protocol::mtVALIDATOR_LIST_COLLECTION), sha512Half(*smallMsg), smallMsg->blobs_size()); return messages.back().numVLs; @@ -592,7 +592,7 @@ buildValidatorListMessage( "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : maximum " "message size"); messages.emplace_back( - std::make_shared(msg, protocol::mtVALIDATORLIST), + std::make_shared(msg, protocol::mtVALIDATOR_LIST), sha512Half(msg), 1); return 1; @@ -640,7 +640,8 @@ buildValidatorListMessage( else { messages.emplace_back( - std::make_shared(msg, protocol::mtVALIDATORLISTCOLLECTION), + std::make_shared( + msg, protocol::mtVALIDATOR_LIST_COLLECTION), sha512Half(msg), msg.blobs_size()); return messages.back().numVLs; diff --git a/src/xrpld/app/tx/detail/InvariantCheck.cpp b/src/xrpld/app/tx/detail/InvariantCheck.cpp index eb751c817f..0b237905e8 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.cpp +++ b/src/xrpld/app/tx/detail/InvariantCheck.cpp @@ -84,9 +84,9 @@ operator|(Privilege lhs, Privilege rhs) #pragma push_macro("TRANSACTION") #undef TRANSACTION -#define TRANSACTION(tag, value, name, delegatable, amendment, privileges, ...) \ - case tag: { \ - return (privileges) & priv; \ +#define TRANSACTION(tag, value, name, delegable, amendment, privileges, ...) \ + case tag: { \ + return (privileges) & priv; \ } bool diff --git a/src/xrpld/overlay/detail/Message.cpp b/src/xrpld/overlay/detail/Message.cpp index eb7b88894a..d03cd5e0da 100644 --- a/src/xrpld/overlay/detail/Message.cpp +++ b/src/xrpld/overlay/detail/Message.cpp @@ -68,8 +68,8 @@ Message::compress() case protocol::mtGET_LEDGER: case protocol::mtLEDGER_DATA: case protocol::mtGET_OBJECTS: - case protocol::mtVALIDATORLIST: - case protocol::mtVALIDATORLISTCOLLECTION: + case protocol::mtVALIDATOR_LIST: + case protocol::mtVALIDATOR_LIST_COLLECTION: case protocol::mtREPLAY_DELTA_RESPONSE: case protocol::mtTRANSACTIONS: return true; diff --git a/src/xrpld/overlay/detail/ProtocolMessage.h b/src/xrpld/overlay/detail/ProtocolMessage.h index 51dfc1ac7c..77ad368ccd 100644 --- a/src/xrpld/overlay/detail/ProtocolMessage.h +++ b/src/xrpld/overlay/detail/ProtocolMessage.h @@ -63,9 +63,9 @@ protocolMessageName(int type) return "status"; case protocol::mtHAVE_SET: return "have_set"; - case protocol::mtVALIDATORLIST: + case protocol::mtVALIDATOR_LIST: return "validator_list"; - case protocol::mtVALIDATORLISTCOLLECTION: + case protocol::mtVALIDATOR_LIST_COLLECTION: return "validator_list_collection"; case protocol::mtVALIDATION: return "validation"; @@ -411,11 +411,11 @@ invokeProtocolMessage( success = detail::invoke( *header, buffers, handler); break; - case protocol::mtVALIDATORLIST: + case protocol::mtVALIDATOR_LIST: success = detail::invoke( *header, buffers, handler); break; - case protocol::mtVALIDATORLISTCOLLECTION: + case protocol::mtVALIDATOR_LIST_COLLECTION: success = detail::invoke( *header, buffers, handler); break; diff --git a/src/xrpld/overlay/detail/TrafficCount.cpp b/src/xrpld/overlay/detail/TrafficCount.cpp index 6fb397ea71..21b4ba78a4 100644 --- a/src/xrpld/overlay/detail/TrafficCount.cpp +++ b/src/xrpld/overlay/detail/TrafficCount.cpp @@ -9,8 +9,8 @@ std::unordered_map const {protocol::mtMANIFESTS, TrafficCount::category::manifests}, {protocol::mtENDPOINTS, TrafficCount::category::overlay}, {protocol::mtTRANSACTION, TrafficCount::category::transaction}, - {protocol::mtVALIDATORLIST, TrafficCount::category::validatorlist}, - {protocol::mtVALIDATORLISTCOLLECTION, + {protocol::mtVALIDATOR_LIST, TrafficCount::category::validatorlist}, + {protocol::mtVALIDATOR_LIST_COLLECTION, TrafficCount::category::validatorlist}, {protocol::mtVALIDATION, TrafficCount::category::validation}, {protocol::mtPROPOSE_LEDGER, TrafficCount::category::proposal}, From e1d97bea12c6ebc3dc5cda19985c3c28987fb1fe Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 8 Jan 2026 15:02:59 -0500 Subject: [PATCH 060/105] ci: Use updated prepare-runner in actions and worfklows (#6188) This change updates the XRPLF pre-commit workflow and prepare-runner action to their latest versions. For naming consistency the prepare-runner action changed the disable_ccache variable into enable_ccache, which matches our naming. --- .github/workflows/pre-commit.yml | 2 +- .github/workflows/reusable-build-test-config.yml | 4 ++-- .github/workflows/upload-conan-deps.yml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index d0a657dd7e..41e82fb6bb 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -9,7 +9,7 @@ on: jobs: # Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks. run-hooks: - uses: XRPLF/actions/.github/workflows/pre-commit.yml@34790936fae4c6c751f62ec8c06696f9c1a5753a + uses: XRPLF/actions/.github/workflows/pre-commit.yml@5ca417783f0312ab26d6f48b85c78edf1de99bbd with: runs_on: ubuntu-latest container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }' diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index 575984162e..fc80bbd216 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -100,9 +100,9 @@ jobs: uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Prepare runner - uses: XRPLF/actions/prepare-runner@2ece4ec6ab7de266859a6f053571425b2bd684b6 + uses: XRPLF/actions/prepare-runner@65da1c59e81965eeb257caa3587b9d45066fb925 with: - disable_ccache: ${{ !inputs.ccache_enabled }} + enable_ccache: ${{ inputs.ccache_enabled }} - name: Set ccache log file if: ${{ inputs.ccache_enabled && runner.debug == '1' }} diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml index 8a9993d37a..55a9ab8864 100644 --- a/.github/workflows/upload-conan-deps.yml +++ b/.github/workflows/upload-conan-deps.yml @@ -70,9 +70,9 @@ jobs: uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Prepare runner - uses: XRPLF/actions/prepare-runner@2ece4ec6ab7de266859a6f053571425b2bd684b6 + uses: XRPLF/actions/prepare-runner@65da1c59e81965eeb257caa3587b9d45066fb925 with: - disable_ccache: true + enable_ccache: false - name: Print build environment uses: ./.github/actions/print-env From c24a6041f7fa8509a584de0c82c439b43197eddf Mon Sep 17 00:00:00 2001 From: oncecelll Date: Sat, 10 Jan 2026 02:15:05 +0800 Subject: [PATCH 061/105] docs: Fix minor spelling issues in comments (#6194) --- src/libxrpl/protocol/SecretKey.cpp | 4 ++-- src/test/app/HashRouter_test.cpp | 2 +- src/test/app/MPToken_test.cpp | 4 ++-- src/test/app/MultiSign_test.cpp | 2 +- src/test/basics/IntrusiveShared_test.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libxrpl/protocol/SecretKey.cpp b/src/libxrpl/protocol/SecretKey.cpp index 88404a88a5..2507269407 100644 --- a/src/libxrpl/protocol/SecretKey.cpp +++ b/src/libxrpl/protocol/SecretKey.cpp @@ -77,7 +77,7 @@ deriveDeterministicRootKey(Seed const& seed) std::array buf; std::copy(seed.begin(), seed.end(), buf.begin()); - // The odds that this loop executes more than once are neglible + // The odds that this loop executes more than once are negligible // but *just* in case someone managed to generate a key that required // more iterations loop a few times. for (std::uint32_t seq = 0; seq != 128; ++seq) @@ -137,7 +137,7 @@ private: std::copy(generator_.begin(), generator_.end(), buf.begin()); copy_uint32(buf.data() + 33, seq); - // The odds that this loop executes more than once are neglible + // The odds that this loop executes more than once are negligible // but we impose a maximum limit just in case. for (std::uint32_t subseq = 0; subseq != 128; ++subseq) { diff --git a/src/test/app/HashRouter_test.cpp b/src/test/app/HashRouter_test.cpp index c428917fdc..2d1d37c3e3 100644 --- a/src/test/app/HashRouter_test.cpp +++ b/src/test/app/HashRouter_test.cpp @@ -349,7 +349,7 @@ class HashRouter_test : public beast::unit_test::suite h.set("hold_time", "alice"); h.set("relay_time", "bob"); auto const setup = setup_HashRouter(cfg); - // The set function ignores values that don't covert, so the + // The set function ignores values that don't convert, so the // defaults are left unchanged BEAST_EXPECT(setup.holdTime == 300s); BEAST_EXPECT(setup.relayTime == 30s); diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index ed6d861ffb..747f78ef6b 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -2651,7 +2651,7 @@ class MPToken_test : public beast::unit_test::suite STAmount const amt3{asset3, 10'000}; { - testcase("Test STAmount MPT arithmetics"); + testcase("Test STAmount MPT arithmetic"); using namespace std::string_literals; STAmount res = multiply(amt1, amt2, asset3); BEAST_EXPECT(res == amt3); @@ -2688,7 +2688,7 @@ class MPToken_test : public beast::unit_test::suite } { - testcase("Test MPTAmount arithmetics"); + testcase("Test MPTAmount arithmetic"); MPTAmount mptAmt1{100}; MPTAmount const mptAmt2{100}; BEAST_EXPECT((mptAmt1 += mptAmt2) == MPTAmount{200}); diff --git a/src/test/app/MultiSign_test.cpp b/src/test/app/MultiSign_test.cpp index 6950286b52..5c5404c17e 100644 --- a/src/test/app/MultiSign_test.cpp +++ b/src/test/app/MultiSign_test.cpp @@ -708,7 +708,7 @@ public: void testHeterogeneousSigners(FeatureBitset features) { - testcase("Heterogenous Signers"); + testcase("Heterogeneous Signers"); using namespace jtx; Env env{*this, features}; diff --git a/src/test/basics/IntrusiveShared_test.cpp b/src/test/basics/IntrusiveShared_test.cpp index b77325efa9..500b6e7e39 100644 --- a/src/test/basics/IntrusiveShared_test.cpp +++ b/src/test/basics/IntrusiveShared_test.cpp @@ -396,7 +396,7 @@ public: // This checks that partialDelete has run to completion // before the destructor is called. A sleep is inserted // inside the partial delete to make sure the destructor is - // given an opportunity to run durring partial delete. + // given an opportunity to run during partial delete. BEAST_EXPECT(cur == partiallyDeleted); } if (next == partiallyDeletedStarted) From fc0072383699cf9718af35a22e46df1bad7799bb Mon Sep 17 00:00:00 2001 From: Zhanibek Bakin <50952098+janibakin@users.noreply.github.com> Date: Fri, 9 Jan 2026 23:37:55 +0500 Subject: [PATCH 062/105] fix: Truncate thread name to 15 chars on Linux (#5758) This change: * Truncates thread names if more than 15 chars with `snprintf`. * Adds warnings for truncated thread names if `-DTRUNCATED_THREAD_NAME_LOGS=ON`. * Add a static assert for string literals to stop compiling if > 15 chars. * Shortens `Resource::Manager` to `Resource::Mngr` to fix the static assert failure. * Updates `CurrentThreadName_test` unit test specifically for Linux to verify truncation. --- cmake/XrplSettings.cmake | 15 ++++ include/xrpl/beast/core/CurrentThreadName.h | 27 +++++++ src/libxrpl/beast/core/CurrentThreadName.cpp | 24 +++++- src/libxrpl/resource/ResourceManager.cpp | 2 +- .../beast/beast_CurrentThreadName_test.cpp | 74 ++++++++++++++----- 5 files changed, 121 insertions(+), 21 deletions(-) diff --git a/cmake/XrplSettings.cmake b/cmake/XrplSettings.cmake index a16513afc5..c3f013c575 100644 --- a/cmake/XrplSettings.cmake +++ b/cmake/XrplSettings.cmake @@ -68,6 +68,21 @@ if(is_linux) option(perf "Enables flags that assist with perf recording" OFF) option(use_gold "enables detection of gold (binutils) linker" ON) option(use_mold "enables detection of mold (binutils) linker" ON) + # Set a default value for the log flag based on the build type. + # This provides a sensible default (on for debug, off for release) + # while still allowing the user to override it for any build. + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(TRUNCATED_LOGS_DEFAULT ON) + else() + set(TRUNCATED_LOGS_DEFAULT OFF) + endif() + option(TRUNCATED_THREAD_NAME_LOGS + "Show warnings about truncated thread names on Linux." + ${TRUNCATED_LOGS_DEFAULT} + ) + if(TRUNCATED_THREAD_NAME_LOGS) + add_compile_definitions(TRUNCATED_THREAD_NAME_LOGS) + endif() else() # we are not ready to allow shared-libs on windows because it would require # export declarations. On macos it's more feasible, but static openssl diff --git a/include/xrpl/beast/core/CurrentThreadName.h b/include/xrpl/beast/core/CurrentThreadName.h index 8e9d58b649..703246a76a 100644 --- a/include/xrpl/beast/core/CurrentThreadName.h +++ b/include/xrpl/beast/core/CurrentThreadName.h @@ -5,6 +5,8 @@ #ifndef BEAST_CORE_CURRENT_THREAD_NAME_H_INCLUDED #define BEAST_CORE_CURRENT_THREAD_NAME_H_INCLUDED +#include + #include #include @@ -16,6 +18,31 @@ namespace beast { void setCurrentThreadName(std::string_view newThreadName); +#if BOOST_OS_LINUX + +// On Linux, thread names are limited to 16 bytes including the null terminator. +// Maximum number of characters is therefore 15. +constexpr std::size_t maxThreadNameLength = 15; + +/** Sets the name of the caller thread with compile-time size checking. + @tparam N The size of the string literal including null terminator + @param newThreadName A string literal to set as the thread name + + This template overload enforces that thread names are at most 16 characters + (including null terminator) at compile time, matching Linux's limit. +*/ +template +void +setCurrentThreadName(char const (&newThreadName)[N]) +{ + static_assert( + N <= maxThreadNameLength + 1, + "Thread name cannot exceed 15 characters"); + + setCurrentThreadName(std::string_view(newThreadName, N - 1)); +} +#endif + /** Returns the name of the caller thread. The name returned is the name as set by a call to setCurrentThreadName(). diff --git a/src/libxrpl/beast/core/CurrentThreadName.cpp b/src/libxrpl/beast/core/CurrentThreadName.cpp index 42dbb062b4..e8f7b629a7 100644 --- a/src/libxrpl/beast/core/CurrentThreadName.cpp +++ b/src/libxrpl/beast/core/CurrentThreadName.cpp @@ -1,7 +1,5 @@ #include -#include - #include #include @@ -73,12 +71,32 @@ setCurrentThreadNameImpl(std::string_view name) #if BOOST_OS_LINUX #include +#include + namespace beast::detail { inline void setCurrentThreadNameImpl(std::string_view name) { - pthread_setname_np(pthread_self(), name.data()); + // truncate and set the thread name. + char boundedName[maxThreadNameLength + 1]; + std::snprintf( + boundedName, + sizeof(boundedName), + "%.*s", + static_cast(maxThreadNameLength), + name.data()); + + pthread_setname_np(pthread_self(), boundedName); + +#ifdef TRUNCATED_THREAD_NAME_LOGS + if (name.size() > maxThreadNameLength) + { + std::cerr << "WARNING: Thread name \"" << name << "\" (length " + << name.size() << ") exceeds maximum of " + << maxThreadNameLength << " characters on Linux.\n"; + } +#endif } } // namespace beast::detail diff --git a/src/libxrpl/resource/ResourceManager.cpp b/src/libxrpl/resource/ResourceManager.cpp index 8582836611..15d31a558e 100644 --- a/src/libxrpl/resource/ResourceManager.cpp +++ b/src/libxrpl/resource/ResourceManager.cpp @@ -140,7 +140,7 @@ private: void run() { - beast::setCurrentThreadName("Resource::Manager"); + beast::setCurrentThreadName("Resource::Mngr"); for (;;) { logic_.periodicActivity(); diff --git a/src/test/beast/beast_CurrentThreadName_test.cpp b/src/test/beast/beast_CurrentThreadName_test.cpp index 3d33ecb602..dc12883a63 100644 --- a/src/test/beast/beast_CurrentThreadName_test.cpp +++ b/src/test/beast/beast_CurrentThreadName_test.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include namespace xrpl { @@ -37,33 +39,71 @@ private: if (beast::getCurrentThreadName() == myName) *state = 2; } +#if BOOST_OS_LINUX + // Helper function to test a specific name. + // It creates a thread, sets the name, and checks if the OS-level + // name matches the expected (potentially truncated) name. + void + testName(std::string const& nameToSet, std::string const& expectedName) + { + std::thread t([&] { + beast::setCurrentThreadName(nameToSet); + + // Initialize buffer to be safe. + char actualName[beast::maxThreadNameLength + 1] = {}; + pthread_getname_np(pthread_self(), actualName, sizeof(actualName)); + + BEAST_EXPECT(std::string(actualName) == expectedName); + }); + t.join(); + } +#endif public: void run() override { - // Make two different threads with two different names. Make sure - // that the expected thread names are still there when the thread - // exits. - std::atomic stop{false}; + // Make two different threads with two different names. + // Make sure that the expected thread names are still there + // when the thread exits. + { + std::atomic stop{false}; - std::atomic stateA{0}; - std::thread tA(exerciseName, "tA", &stop, &stateA); + std::atomic stateA{0}; + std::thread tA(exerciseName, "tA", &stop, &stateA); - std::atomic stateB{0}; - std::thread tB(exerciseName, "tB", &stop, &stateB); + std::atomic stateB{0}; + std::thread tB(exerciseName, "tB", &stop, &stateB); - // Wait until both threads have set their names. - while (stateA == 0 || stateB == 0) - ; + // Wait until both threads have set their names. + while (stateA == 0 || stateB == 0) + ; - stop = true; - tA.join(); - tB.join(); + stop = true; + tA.join(); + tB.join(); - // Both threads should still have the expected name when they exit. - BEAST_EXPECT(stateA == 2); - BEAST_EXPECT(stateB == 2); + // Both threads should still have the expected name when they exit. + BEAST_EXPECT(stateA == 2); + BEAST_EXPECT(stateB == 2); + } +#if BOOST_OS_LINUX + // On Linux, verify that thread names longer than 15 characters + // are truncated to 15 characters (the 16th character is reserved for + // the null terminator). + { + testName( + "123456789012345", + "123456789012345"); // 15 chars, no truncation + testName( + "1234567890123456", "123456789012345"); // 16 chars, truncated + testName( + "ThisIsAVeryLongThreadNameExceedingLimit", + "ThisIsAVeryLong"); // 39 chars, truncated + testName("", ""); // empty name + testName("short", "short"); // short name, no truncation + } +#endif } }; From 14467fba5e5652d4976fdea0d312d64e6fb61242 Mon Sep 17 00:00:00 2001 From: Vito Tumas <5780819+Tapanito@users.noreply.github.com> Date: Fri, 9 Jan 2026 20:58:02 +0100 Subject: [PATCH 063/105] VaultClawback: Burn shares of an empty vault (#6120) - Adds a mechanism for the vault owner to burn user shares when the vault is stuck. If the Vault has 0 AssetsAvailable and Total, the owner may submit a VaultClawback to reclaim the worthless fees, and thus allow the Vault to be deleted. The Amount must be left off (unless the owner is the asset issuer), specified as 0 Shares, or specified as the number of Shares held. --- src/test/app/Vault_test.cpp | 589 ++++++++++++++++++++- src/xrpld/app/tx/detail/InvariantCheck.cpp | 77 +-- src/xrpld/app/tx/detail/InvariantCheck.h | 1 + src/xrpld/app/tx/detail/VaultClawback.cpp | 473 +++++++++++------ src/xrpld/app/tx/detail/VaultClawback.h | 8 + 5 files changed, 931 insertions(+), 217 deletions(-) diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index f8d76623fd..d0a1450d6c 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -940,25 +939,6 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const& issuer, - Account const& owner, - Asset const& asset, - Vault& vault) { - testcase("clawback from self"); - - auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); - - { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = issuer, - .amount = asset(10)}); - env(tx, ter{temMALFORMED}); - } - }); - testCase([&](Env& env, Account const&, Account const& owner, @@ -1197,11 +1177,13 @@ class Vault_test : public beast::unit_test::suite auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); + // Preclaim only checks for native assets. + if (asset.native()) { auto tx = vault.clawback( - {.issuer = owner, + {.issuer = issuer, .id = keylet.key, - .holder = issuer, + .holder = owner, .amount = asset(50)}); env(tx, ter(temMALFORMED)); } @@ -1924,8 +1906,20 @@ class Vault_test : public beast::unit_test::suite env.close(); { - auto tx = vault.clawback( - {.issuer = owner, .id = keylet.key, .holder = depositor}); + auto tx = vault.clawback({ + .issuer = depositor, + .id = keylet.key, + .holder = depositor, + }); + env(tx, ter(tecNO_PERMISSION)); + } + + { + auto tx = vault.clawback({ + .issuer = owner, + .id = keylet.key, + .holder = depositor, + }); env(tx, ter(tecNO_PERMISSION)); } }); @@ -2377,6 +2371,15 @@ class Vault_test : public beast::unit_test::suite env(tx, ter(tecNO_AUTH)); } + { + // Cannot clawback if issuer is the holder + tx = vault.clawback( + {.issuer = issuer, + .id = keylet.key, + .holder = issuer, + .amount = asset(800)}); + env(tx, ter(tecNO_PERMISSION)); + } // Clawback works tx = vault.clawback( {.issuer = issuer, @@ -5243,6 +5246,542 @@ class Vault_test : public beast::unit_test::suite }); } + void + testVaultClawbackBurnShares() + { + using namespace test::jtx; + using namespace loanBroker; + using namespace loan; + Env env(*this, beast::severities::kWarning); + + auto const vaultAssetBalance = [&](Keylet const& vaultKeylet) { + auto const sleVault = env.le(vaultKeylet); + BEAST_EXPECT(sleVault != nullptr); + + return std::make_pair( + sleVault->at(sfAssetsAvailable), sleVault->at(sfAssetsTotal)); + }; + + auto const vaultShareBalance = [&](Keylet const& vaultKeylet) { + auto const sleVault = env.le(vaultKeylet); + BEAST_EXPECT(sleVault != nullptr); + + auto const sleIssuance = + env.le(keylet::mptIssuance(sleVault->at(sfShareMPTID))); + BEAST_EXPECT(sleIssuance != nullptr); + + return sleIssuance->at(sfOutstandingAmount); + }; + + auto const setupVault = + [&](PrettyAsset const& asset, + Account const& owner, + Account const& depositor) -> std::pair { + Vault vault{env}; + + auto const& [tx, vaultKeylet] = + vault.create({.owner = owner, .asset = asset}); + env(tx, ter(tesSUCCESS), THISLINE); + env.close(); + + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + + Asset share = vaultSle->at(sfShareMPTID); + + env(vault.deposit( + {.depositor = depositor, + .id = vaultKeylet.key, + .amount = asset(100)}), + ter(tesSUCCESS), + THISLINE); + env.close(); + + auto const& [availablePreDefault, totalPreDefault] = + vaultAssetBalance(vaultKeylet); + BEAST_EXPECT(availablePreDefault == totalPreDefault); + BEAST_EXPECT(availablePreDefault == asset(100).value()); + + // attempt to clawback shares while there are assets fails + env(vault.clawback( + {.issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = share(0).value()}), + ter(tecNO_PERMISSION), + THISLINE); + env.close(); + + auto const& sharesAvailable = vaultShareBalance(vaultKeylet); + auto const& brokerKeylet = + keylet::loanbroker(owner.id(), env.seq(owner)); + + env(set(owner, vaultKeylet.key), THISLINE); + env.close(); + + auto const& loanKeylet = keylet::loan(brokerKeylet.key, 1); + + // Create a simple Loan for the full amount of Vault assets + env(set(depositor, brokerKeylet.key, asset(100).value()), + loan::interestRate(TenthBips32(0)), + gracePeriod(10), + paymentInterval(120), + paymentTotal(10), + sig(sfCounterpartySignature, owner), + fee(env.current()->fees().base * 2), + ter(tesSUCCESS), + THISLINE); + env.close(); + + // attempt to clawback shares while there assetsAvailable == 0 and + // assetsTotal > 0 fails + env(vault.clawback( + {.issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = share(0).value()}), + ter(tecNO_PERMISSION), + THISLINE); + env.close(); + + env.close(std::chrono::seconds{120 + 10}); + + env(manage(owner, loanKeylet.key, tfLoanDefault), + ter(tesSUCCESS), + THISLINE); + + auto const& [availablePostDefault, totalPostDefault] = + vaultAssetBalance(vaultKeylet); + + BEAST_EXPECT(availablePostDefault == totalPostDefault); + BEAST_EXPECT(availablePostDefault == asset(0).value()); + BEAST_EXPECT(vaultShareBalance(vaultKeylet) == sharesAvailable); + + return std::make_pair(vault, vaultKeylet); + }; + + auto const testCase = [&](PrettyAsset const& asset, + std::string const& prefix, + Account const& owner, + Account const& depositor) { + { + testcase( + "VaultClawback (share) - " + prefix + + " owner asset clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = asset(100).value(), + }), + // when asset is XRP or owner is not issuer clawback fail + // when owner is issuer precision loss occurs as vault is + // empty + asset.native() ? ter(temMALFORMED) + : asset.raw().getIssuer() != owner.id() + ? ter(tecNO_PERMISSION) + : ter(tecPRECISION_LOSS), + THISLINE); + env.close(); + } + + { + testcase( + "VaultClawback (share) - " + prefix + + " owner incomplete share clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + if (!vaultSle) + return; + Asset share = vaultSle->at(sfShareMPTID); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = share(1).value(), + }), + ter(tecLIMIT_EXCEEDED), + THISLINE); + env.close(); + } + + { + testcase( + "VaultClawback (share) - " + prefix + + " owner implicit complete share clawback"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + }), + // when owner is issuer implicit clawback fails + asset.native() || asset.raw().getIssuer() != owner.id() + ? ter(tesSUCCESS) + : ter(tecWRONG_ASSET), + THISLINE); + env.close(); + } + + { + testcase( + "VaultClawback (share) - " + prefix + + " owner explicit complete share clawback succeeds"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + if (!vaultSle) + return; + Asset share = vaultSle->at(sfShareMPTID); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = share(vaultShareBalance(vaultKeylet)).value(), + }), + ter(tesSUCCESS), + THISLINE); + env.close(); + } + { + testcase( + "VaultClawback (share) - " + prefix + + " owner can clawback own shares"); + auto [vault, vaultKeylet] = setupVault(asset, owner, owner); + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + if (!vaultSle) + return; + Asset share = vaultSle->at(sfShareMPTID); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = owner, + .amount = share(vaultShareBalance(vaultKeylet)).value(), + }), + ter(tesSUCCESS), + THISLINE); + env.close(); + } + + { + testcase( + "VaultClawback (share) - " + prefix + + " empty vault share clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, owner); + auto const& vaultSle = env.le(vaultKeylet); + if (BEAST_EXPECT(vaultSle != nullptr)) + return; + Asset share = vaultSle->at(sfShareMPTID); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = owner, + .amount = share(vaultShareBalance(vaultKeylet)).value(), + }), + ter(tesSUCCESS), + THISLINE); + + // Now the vault is empty, clawback again fails + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = owner, + }), + ter(tecNO_PERMISSION), + THISLINE); + env.close(); + } + }; + + Account owner{"alice"}; + Account depositor{"bob"}; + Account issuer{"issuer"}; + + env.fund(XRP(10000), issuer, owner, depositor); + env.close(); + + // Test XRP + PrettyAsset xrp = xrpIssue(); + testCase(xrp, "XRP", owner, depositor); + testCase(xrp, "XRP (depositor is owner)", owner, owner); + + // Test IOU + PrettyAsset IOU = issuer["IOU"]; + env(fset(issuer, asfAllowTrustLineClawback)); + env.close(); + + env.trust(IOU(1000), owner); + env.trust(IOU(1000), depositor); + env(pay(issuer, owner, IOU(100))); + env(pay(issuer, depositor, IOU(100))); + env.close(); + testCase(IOU, "IOU", owner, depositor); + testCase(IOU, "IOU (owner is issuer)", issuer, depositor); + + // Test MPT + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + PrettyAsset MPT = mptt.issuanceID(); + mptt.authorize({.account = owner}); + mptt.authorize({.account = depositor}); + env(pay(issuer, owner, MPT(1000))); + env(pay(issuer, depositor, MPT(1000))); + env.close(); + testCase(MPT, "MPT", owner, depositor); + testCase(MPT, "MPT (owner is issuer)", issuer, depositor); + } + + void + testVaultClawbackAssets() + { + using namespace test::jtx; + using namespace loanBroker; + using namespace loan; + Env env(*this); + + auto const setupVault = + [&](PrettyAsset const& asset, + Account const& owner, + Account const& depositor, + Account const& issuer) -> std::pair { + Vault vault{env}; + + auto const& [tx, vaultKeylet] = + vault.create({.owner = owner, .asset = asset}); + env(tx, ter(tesSUCCESS), THISLINE); + env.close(); + + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + env(vault.deposit( + {.depositor = depositor, + .id = vaultKeylet.key, + .amount = asset(100)}), + ter(tesSUCCESS), + THISLINE); + env.close(); + + return std::make_pair(vault, vaultKeylet); + }; + + auto const testCase = [&](PrettyAsset const& asset, + std::string const& prefix, + Account const& owner, + Account const& depositor, + Account const& issuer) { + if (asset.native()) + { + testcase( + "VaultClawback (asset) - " + prefix + + " issuer XRP clawback fails"); + auto [vault, vaultKeylet] = + setupVault(asset, owner, depositor, issuer); + // If the asset is XRP, clawback with amount fails as malfored + // when asset is specified. + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = issuer, + .amount = asset(1).value(), + }), + ter(temMALFORMED), + THISLINE); + // When asset is implicit, clawback fails as no permission. + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = issuer, + }), + ter(tecNO_PERMISSION), + THISLINE); + return; + } + + { + testcase( + "VaultClawback (asset) - " + prefix + + " clawback for different asset fails"); + auto [vault, vaultKeylet] = + setupVault(asset, owner, depositor, issuer); + + Account issuer2{"issuer2"}; + PrettyAsset asset2 = issuer2["FOO"]; + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = depositor, + .amount = asset2(1).value(), + }), + ter(tecWRONG_ASSET), + THISLINE); + } + + { + testcase( + "VaultClawback (asset) - " + prefix + + " ambiguous owner/issuer asset clawback fails"); + auto [vault, vaultKeylet] = + setupVault(asset, issuer, depositor, issuer); + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = issuer, + }), + ter(tecWRONG_ASSET), + THISLINE); + } + + { + testcase( + "VaultClawback (asset) - " + prefix + + " non-issuer asset clawback fails"); + auto [vault, vaultKeylet] = + setupVault(asset, owner, depositor, issuer); + + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + }), + ter(tecNO_PERMISSION), + THISLINE); + + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = asset(1).value(), + }), + ter(tecNO_PERMISSION), + THISLINE); + } + + { + testcase( + "VaultClawback (asset) - " + prefix + + " issuer clawback from self fails"); + auto [vault, vaultKeylet] = + setupVault(asset, owner, issuer, issuer); + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = issuer, + }), + ter(tecNO_PERMISSION), + THISLINE); + } + + { + testcase( + "VaultClawback (asset) - " + prefix + + " issuer share clawback fails"); + auto [vault, vaultKeylet] = + setupVault(asset, owner, depositor, issuer); + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + if (!vaultSle) + return; + Asset share = vaultSle->at(sfShareMPTID); + + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = depositor, + .amount = share(1).value(), + }), + ter(tecNO_PERMISSION), + THISLINE); + } + + { + testcase( + "VaultClawback (asset) - " + prefix + + " partial issuer asset clawback succeeds"); + auto [vault, vaultKeylet] = + setupVault(asset, owner, depositor, issuer); + + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = depositor, + .amount = asset(1).value(), + }), + ter(tesSUCCESS), + THISLINE); + } + + { + testcase( + "VaultClawback (asset) - " + prefix + + " full issuer asset clawback succeeds"); + auto [vault, vaultKeylet] = + setupVault(asset, owner, depositor, issuer); + + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = depositor, + .amount = asset(100).value(), + }), + ter(tesSUCCESS), + THISLINE); + } + + { + testcase( + "VaultClawback (asset) - " + prefix + + " implicit full issuer asset clawback succeeds"); + auto [vault, vaultKeylet] = + setupVault(asset, owner, depositor, issuer); + + env(vault.clawback({ + .issuer = issuer, + .id = vaultKeylet.key, + .holder = depositor, + }), + ter(tesSUCCESS), + THISLINE); + } + }; + + Account owner{"alice"}; + Account depositor{"bob"}; + Account issuer{"issuer"}; + + env.fund(XRP(10000), issuer, owner, depositor); + env.close(); + + // Test XRP + PrettyAsset xrp = xrpIssue(); + testCase(xrp, "XRP", owner, depositor, issuer); + + // Test IOU + PrettyAsset IOU = issuer["IOU"]; + env(fset(issuer, asfAllowTrustLineClawback)); + env.close(); + env.trust(IOU(1000), owner); + env.trust(IOU(1000), depositor); + env(pay(issuer, owner, IOU(1000))); + env(pay(issuer, depositor, IOU(1000))); + env.close(); + testCase(IOU, "IOU", owner, depositor, issuer); + + // Test MPT + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + PrettyAsset MPT = mptt.issuanceID(); + mptt.authorize({.account = owner}); + mptt.authorize({.account = depositor}); + env(pay(issuer, depositor, MPT(1000))); + env.close(); + testCase(MPT, "MPT", owner, depositor, issuer); + } + public: void run() override @@ -5261,6 +5800,8 @@ public: testScaleIOU(); testRPC(); testDelegate(); + testVaultClawbackBurnShares(); + testVaultClawbackAssets(); } }; diff --git a/src/xrpld/app/tx/detail/InvariantCheck.cpp b/src/xrpld/app/tx/detail/InvariantCheck.cpp index 0b237905e8..2e0b3cbfab 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.cpp +++ b/src/xrpld/app/tx/detail/InvariantCheck.cpp @@ -95,6 +95,7 @@ hasPrivilege(STTx const& tx, Privilege priv) switch (tx.getTxnType()) { #include + // Deprecated types default: return false; @@ -2622,6 +2623,7 @@ ValidVault::Vault::make(SLE const& from) self.key = from.key(); self.asset = from.at(sfAsset); self.pseudoId = from.getAccountID(sfAccount); + self.owner = from.at(sfOwner); self.shareMPTID = from.getFieldH192(sfShareMPTID); self.assetsTotal = from.at(sfAssetsTotal); self.assetsAvailable = from.at(sfAssetsAvailable); @@ -3066,6 +3068,10 @@ ValidVault::finalize( : std::nullopt; }; + auto const vaultHoldsNoAssets = [&](Vault const& vault) { + return vault.assetsAvailable == 0 && vault.assetsTotal == 0; + }; + // Technically this does not need to be a lambda, but it's more // convenient thanks to early "return false"; the not-so-nice // alternatives are several layers of nested if/else or more complex @@ -3448,29 +3454,56 @@ ValidVault::finalize( if (vaultAsset.native() || vaultAsset.getIssuer() != tx[sfAccount]) { - JLOG(j.fatal()) << // - "Invariant failed: clawback may only be performed by " - "the asset issuer"; - return false; // That's all we can do + // The owner can use clawback to force-burn shares when the + // vault is empty but there are outstanding shares + if (!(beforeShares && beforeShares->sharesTotal > 0 && + vaultHoldsNoAssets(beforeVault) && + beforeVault.owner == tx[sfAccount])) + { + JLOG(j.fatal()) << // + "Invariant failed: clawback may only be performed " + "by the asset issuer, or by the vault owner of an " + "empty vault"; + return false; // That's all we can do + } } auto const vaultDeltaAssets = deltaAssets(afterVault.pseudoId); + if (vaultDeltaAssets) + { + if (*vaultDeltaAssets >= zero) + { + JLOG(j.fatal()) << // + "Invariant failed: clawback must decrease vault " + "balance"; + result = false; + } - if (!vaultDeltaAssets) + if (beforeVault.assetsTotal + *vaultDeltaAssets != + afterVault.assetsTotal) + { + JLOG(j.fatal()) << // + "Invariant failed: clawback and assets outstanding " + "must add up"; + result = false; + } + + if (beforeVault.assetsAvailable + *vaultDeltaAssets != + afterVault.assetsAvailable) + { + JLOG(j.fatal()) << // + "Invariant failed: clawback and assets available " + "must add up"; + result = false; + } + } + else if (!vaultHoldsNoAssets(beforeVault)) { JLOG(j.fatal()) << // "Invariant failed: clawback must change vault balance"; return false; // That's all we can do } - if (*vaultDeltaAssets >= zero) - { - JLOG(j.fatal()) << // - "Invariant failed: clawback must decrease vault " - "balance"; - result = false; - } - auto const accountDeltaShares = deltaShares(tx[sfHolder]); if (!accountDeltaShares) { @@ -3503,24 +3536,6 @@ ValidVault::finalize( result = false; } - if (beforeVault.assetsTotal + *vaultDeltaAssets != - afterVault.assetsTotal) - { - JLOG(j.fatal()) << // - "Invariant failed: clawback and assets outstanding " - "must add up"; - result = false; - } - - if (beforeVault.assetsAvailable + *vaultDeltaAssets != - afterVault.assetsAvailable) - { - JLOG(j.fatal()) << // - "Invariant failed: clawback and assets available must " - "add up"; - result = false; - } - return result; } diff --git a/src/xrpld/app/tx/detail/InvariantCheck.h b/src/xrpld/app/tx/detail/InvariantCheck.h index ef9db373f5..87a1afb623 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.h +++ b/src/xrpld/app/tx/detail/InvariantCheck.h @@ -861,6 +861,7 @@ class ValidVault uint256 key = beast::zero; Asset asset = {}; AccountID pseudoId = {}; + AccountID owner = {}; uint192 shareMPTID = beast::zero; Number assetsTotal = 0; Number assetsAvailable = 0; diff --git a/src/xrpld/app/tx/detail/VaultClawback.cpp b/src/xrpld/app/tx/detail/VaultClawback.cpp index cc7dec993a..2552e8c1ff 100644 --- a/src/xrpld/app/tx/detail/VaultClawback.cpp +++ b/src/xrpld/app/tx/detail/VaultClawback.cpp @@ -1,18 +1,17 @@ #include - +// #include #include #include -#include #include #include #include #include #include -#include + +#include namespace xrpl { - NotTEC VaultClawback::preflight(PreflightContext const& ctx) { @@ -22,15 +21,6 @@ VaultClawback::preflight(PreflightContext const& ctx) return temMALFORMED; } - AccountID const issuer = ctx.tx[sfAccount]; - AccountID const holder = ctx.tx[sfHolder]; - - if (issuer == holder) - { - JLOG(ctx.j.debug()) << "VaultClawback: issuer cannot be holder."; - return temMALFORMED; - } - auto const amount = ctx.tx[~sfAmount]; if (amount) { @@ -42,17 +32,27 @@ VaultClawback::preflight(PreflightContext const& ctx) JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback XRP."; return temMALFORMED; } - else if (amount->asset().getIssuer() != issuer) - { - JLOG(ctx.j.debug()) - << "VaultClawback: only asset issuer can clawback."; - return temMALFORMED; - } } return tesSUCCESS; } +[[nodiscard]] STAmount +clawbackAmount( + std::shared_ptr const& vault, + std::optional const& maybeAmount, + AccountID const& account) +{ + if (maybeAmount) + return *maybeAmount; + + Asset const share = MPTIssue{vault->at(sfShareMPTID)}; + if (account == vault->at(sfOwner)) + return STAmount{share}; + + return STAmount{vault->at(sfAsset)}; +} + TER VaultClawback::preclaim(PreclaimContext const& ctx) { @@ -60,61 +60,264 @@ VaultClawback::preclaim(PreclaimContext const& ctx) if (!vault) return tecNO_ENTRY; - auto account = ctx.tx[sfAccount]; - auto const issuer = ctx.view.read(keylet::account(account)); - if (!issuer) + Asset const vaultAsset = vault->at(sfAsset); + auto const account = ctx.tx[sfAccount]; + auto const holder = ctx.tx[sfHolder]; + auto const maybeAmount = ctx.tx[~sfAmount]; + auto const mptIssuanceID = vault->at(sfShareMPTID); + auto const sleShareIssuance = + ctx.view.read(keylet::mptIssuance(mptIssuanceID)); + if (!sleShareIssuance) { // LCOV_EXCL_START - JLOG(ctx.j.error()) << "VaultClawback: missing issuer account."; + JLOG(ctx.j.error()) + << "VaultClawback: missing issuance of vault shares."; return tefINTERNAL; // LCOV_EXCL_STOP } - Asset const vaultAsset = vault->at(sfAsset); - if (auto const amount = ctx.tx[~sfAmount]; - amount && vaultAsset != amount->asset()) + Asset const share = MPTIssue{mptIssuanceID}; + + // Ambiguous case: If Issuer is Owner they must specify the asset + if (!maybeAmount && !vaultAsset.native() && + vaultAsset.getIssuer() == vault->at(sfOwner)) + { + JLOG(ctx.j.debug()) + << "VaultClawback: must specify amount when issuer is owner."; return tecWRONG_ASSET; - - if (vaultAsset.native()) - { - JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback XRP."; - return tecNO_PERMISSION; // Cannot clawback XRP. - } - else if (vaultAsset.getIssuer() != account) - { - JLOG(ctx.j.debug()) << "VaultClawback: only asset issuer can clawback."; - return tecNO_PERMISSION; // Only issuers can clawback. } - if (vaultAsset.holds()) - { - auto const mpt = vaultAsset.get(); - auto const mptIssue = - ctx.view.read(keylet::mptIssuance(mpt.getMptID())); - if (mptIssue == nullptr) - return tecOBJECT_NOT_FOUND; + auto const amount = clawbackAmount(vault, maybeAmount, account); - std::uint32_t const issueFlags = mptIssue->getFieldU32(sfFlags); - if (!(issueFlags & lsfMPTCanClawback)) + // There is a special case that allows the VaultOwner to use clawback to + // burn shares when Vault assets total and available are zero, but + // shares remain. However, that case is handled in doApply() directly, + // so here we just enforce checks. + if (amount.asset() == share) + { + // Only the Vault Owner may clawback shares + if (account != vault->at(sfOwner)) { JLOG(ctx.j.debug()) - << "VaultClawback: cannot clawback MPT vault asset."; + << "VaultClawback: only vault owner can clawback shares."; return tecNO_PERMISSION; } - } - else if (vaultAsset.holds()) - { - std::uint32_t const issuerFlags = issuer->getFieldU32(sfFlags); - if (!(issuerFlags & lsfAllowTrustLineClawback) || - (issuerFlags & lsfNoFreeze)) + + auto const assetsTotal = vault->at(sfAssetsTotal); + auto const assetsAvailable = vault->at(sfAssetsAvailable); + auto const sharesTotal = sleShareIssuance->at(sfOutstandingAmount); + + // Owner can clawback funds when the vault has shares but no assets + if (sharesTotal == 0 || (assetsTotal != 0 || assetsAvailable != 0)) { JLOG(ctx.j.debug()) - << "VaultClawback: cannot clawback IOU vault asset."; + << "VaultClawback: vault owner can clawback shares only" + " when vault has no assets."; return tecNO_PERMISSION; } + + // If amount is non-zero, the VaultOwner must burn all shares + if (amount != beast::zero) + { + Number const& sharesHeld = accountHolds( + ctx.view, + holder, + share, + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + ctx.j); + + // The VaultOwner must burn all shares + if (amount != sharesHeld) + { + JLOG(ctx.j.debug()) + << "VaultClawback: vault owner must clawback all " + "shares."; + return tecLIMIT_EXCEEDED; + } + } + + return tesSUCCESS; } - return tesSUCCESS; + // The asset that is being clawed back is the vault asset + if (amount.asset() == vaultAsset) + { + // XRP cannot be clawed back + if (vaultAsset.native()) + { + JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback XRP."; + return tecNO_PERMISSION; + } + + // Only the Asset Issuer may clawback the asset + if (account != vaultAsset.getIssuer()) + { + JLOG(ctx.j.debug()) + << "VaultClawback: only asset issuer can clawback asset."; + return tecNO_PERMISSION; + } + + // The issuer cannot clawback from itself + if (account == holder) + { + JLOG(ctx.j.debug()) + << "VaultClawback: issuer cannot be the holder."; + return tecNO_PERMISSION; + } + + return std::visit( + [&](TIss const& issue) -> TER { + if constexpr (std::is_same_v) + { + auto const mptIssue = + ctx.view.read(keylet::mptIssuance(issue.getMptID())); + if (mptIssue == nullptr) + return tecOBJECT_NOT_FOUND; + + std::uint32_t const issueFlags = + mptIssue->getFieldU32(sfFlags); + if (!(issueFlags & lsfMPTCanClawback)) + { + JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback " + "MPT vault asset."; + return tecNO_PERMISSION; + } + } + else if constexpr (std::is_same_v) + { + auto const issuerSle = + ctx.view.read(keylet::account(account)); + if (!issuerSle) + { + // LCOV_EXCL_START + JLOG(ctx.j.error()) + << "VaultClawback: missing submitter account."; + return tefINTERNAL; + // LCOV_EXCL_STOP + } + + std::uint32_t const issuerFlags = + issuerSle->getFieldU32(sfFlags); + if (!(issuerFlags & lsfAllowTrustLineClawback) || + (issuerFlags & lsfNoFreeze)) + { + JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback " + "IOU vault asset."; + return tecNO_PERMISSION; + } + } + return tesSUCCESS; + }, + vaultAsset.value()); + } + + // Invalid asset + return tecWRONG_ASSET; +} + +Expected, TER> +VaultClawback::assetsToClawback( + std::shared_ptr const& vault, + std::shared_ptr const& sleShareIssuance, + AccountID const& holder, + STAmount const& clawbackAmount) +{ + if (clawbackAmount.asset() != vault->at(sfAsset)) + { + // preclaim should have blocked this , now it's an internal error + // LCOV_EXCL_START + JLOG(j_.error()) << "VaultClawback: asset mismatch in clawback."; + return Unexpected(tecINTERNAL); + // LCOV_EXCL_STOP + } + + auto const assetsAvailable = vault->at(sfAssetsAvailable); + auto const mptIssuanceID = *vault->at(sfShareMPTID); + MPTIssue const share{mptIssuanceID}; + + if (clawbackAmount == beast::zero) + { + auto const sharesDestroyed = accountHolds( + view(), + holder, + share, + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + j_); + auto const maybeAssets = + sharesToAssetsWithdraw(vault, sleShareIssuance, sharesDestroyed); + if (!maybeAssets) + return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE + + return std::make_pair(*maybeAssets, sharesDestroyed); + } + + STAmount sharesDestroyed; + STAmount assetsRecovered = clawbackAmount; + try + { + { + auto const maybeShares = assetsToSharesWithdraw( + vault, sleShareIssuance, assetsRecovered); + if (!maybeShares) + return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE + sharesDestroyed = *maybeShares; + } + + auto const maybeAssets = + sharesToAssetsWithdraw(vault, sleShareIssuance, sharesDestroyed); + if (!maybeAssets) + return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE + assetsRecovered = *maybeAssets; + + // Clamp to maximum. + if (assetsRecovered > *assetsAvailable) + { + assetsRecovered = *assetsAvailable; + // Note, it is important to truncate the number of shares, + // otherwise the corresponding assets might breach the + // AssetsAvailable + { + auto const maybeShares = assetsToSharesWithdraw( + vault, + sleShareIssuance, + assetsRecovered, + TruncateShares::yes); + if (!maybeShares) + return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE + sharesDestroyed = *maybeShares; + } + + auto const maybeAssets = sharesToAssetsWithdraw( + vault, sleShareIssuance, sharesDestroyed); + if (!maybeAssets) + return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE + assetsRecovered = *maybeAssets; + if (assetsRecovered > *assetsAvailable) + { + // LCOV_EXCL_START + JLOG(j_.error()) + << "VaultClawback: invalid rounding of shares."; + return Unexpected(tecINTERNAL); + // LCOV_EXCL_STOP + } + } + } + catch (std::overflow_error const&) + { + // It's easy to hit this exception from Number with large enough + // Scale so we avoid spamming the log and only use debug here. + JLOG(j_.debug()) // + << "VaultClawback: overflow error with" + << " scale=" << (int)vault->at(sfScale).value() // + << ", assetsTotal=" << vault->at(sfAssetsTotal).value() + << ", sharesTotal=" << sleShareIssuance->at(sfOutstandingAmount) + << ", amount=" << clawbackAmount.value(); + return Unexpected(tecPATH_DRY); + } + + return std::make_pair(assetsRecovered, sharesDestroyed); } TER @@ -125,7 +328,7 @@ VaultClawback::doApply() if (!vault) return tefINTERNAL; // LCOV_EXCL_LINE - auto const mptIssuanceID = *((*vault)[sfShareMPTID]); + auto const mptIssuanceID = *vault->at(sfShareMPTID); auto const sleIssuance = view().read(keylet::mptIssuance(mptIssuanceID)); if (!sleIssuance) { @@ -134,105 +337,47 @@ VaultClawback::doApply() return tefINTERNAL; // LCOV_EXCL_STOP } + MPTIssue const share{mptIssuanceID}; Asset const vaultAsset = vault->at(sfAsset); - STAmount const amount = [&]() -> STAmount { - auto const maybeAmount = tx[~sfAmount]; - if (maybeAmount) - return *maybeAmount; - return {sfAmount, vaultAsset, 0}; - }(); - XRPL_ASSERT( - amount.asset() == vaultAsset, - "xrpl::VaultClawback::doApply : matching asset"); + STAmount const amount = clawbackAmount(vault, tx[~sfAmount], account_); auto assetsAvailable = vault->at(sfAssetsAvailable); auto assetsTotal = vault->at(sfAssetsTotal); + [[maybe_unused]] auto const lossUnrealized = vault->at(sfLossUnrealized); XRPL_ASSERT( lossUnrealized <= (assetsTotal - assetsAvailable), "xrpl::VaultClawback::doApply : loss and assets do balance"); AccountID holder = tx[sfHolder]; - MPTIssue const share{mptIssuanceID}; STAmount sharesDestroyed = {share}; - STAmount assetsRecovered; - try + STAmount assetsRecovered = {vault->at(sfAsset)}; + + // The Owner is burning shares + if (account_ == vault->at(sfOwner) && amount.asset() == share) { - if (amount == beast::zero) - { - sharesDestroyed = accountHolds( - view(), - holder, - share, - FreezeHandling::fhIGNORE_FREEZE, - AuthHandling::ahIGNORE_AUTH, - j_); - - auto const maybeAssets = - sharesToAssetsWithdraw(vault, sleIssuance, sharesDestroyed); - if (!maybeAssets) - return tecINTERNAL; // LCOV_EXCL_LINE - assetsRecovered = *maybeAssets; - } - else - { - assetsRecovered = amount; - { - auto const maybeShares = - assetsToSharesWithdraw(vault, sleIssuance, assetsRecovered); - if (!maybeShares) - return tecINTERNAL; // LCOV_EXCL_LINE - sharesDestroyed = *maybeShares; - } - - auto const maybeAssets = - sharesToAssetsWithdraw(vault, sleIssuance, sharesDestroyed); - if (!maybeAssets) - return tecINTERNAL; // LCOV_EXCL_LINE - assetsRecovered = *maybeAssets; - } - - // Clamp to maximum. - if (assetsRecovered > *assetsAvailable) - { - assetsRecovered = *assetsAvailable; - // Note, it is important to truncate the number of shares, otherwise - // the corresponding assets might breach the AssetsAvailable - { - auto const maybeShares = assetsToSharesWithdraw( - vault, sleIssuance, assetsRecovered, TruncateShares::yes); - if (!maybeShares) - return tecINTERNAL; // LCOV_EXCL_LINE - sharesDestroyed = *maybeShares; - } - - auto const maybeAssets = - sharesToAssetsWithdraw(vault, sleIssuance, sharesDestroyed); - if (!maybeAssets) - return tecINTERNAL; // LCOV_EXCL_LINE - assetsRecovered = *maybeAssets; - if (assetsRecovered > *assetsAvailable) - { - // LCOV_EXCL_START - JLOG(j_.error()) - << "VaultClawback: invalid rounding of shares."; - return tecINTERNAL; - // LCOV_EXCL_STOP - } - } + sharesDestroyed = accountHolds( + view(), + holder, + share, + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + j_); } - catch (std::overflow_error const&) + else // The Issuer is clawbacking vault assets { - // It's easy to hit this exception from Number with large enough Scale - // so we avoid spamming the log and only use debug here. - JLOG(j_.debug()) // - << "VaultClawback: overflow error with" - << " scale=" << (int)vault->at(sfScale).value() // - << ", assetsTotal=" << vault->at(sfAssetsTotal).value() - << ", sharesTotal=" << sleIssuance->at(sfOutstandingAmount) - << ", amount=" << amount.value(); - return tecPATH_DRY; + XRPL_ASSERT( + amount.asset() == vaultAsset, + "xrpl::VaultClawback::doApply : matching asset"); + + auto const clawbackParts = + assetsToClawback(vault, sleIssuance, holder, amount); + if (!clawbackParts) + return clawbackParts.error(); + + assetsRecovered = clawbackParts->first; + sharesDestroyed = clawbackParts->second; } if (sharesDestroyed == beast::zero) @@ -282,30 +427,34 @@ VaultClawback::doApply() // else quietly ignore, holder balance is not zero } - // Transfer assets from vault to issuer. - if (auto const ter = accountSend( - view(), - vaultAccount, - account_, - assetsRecovered, - j_, - WaiveTransferFee::Yes); - !isTesSuccess(ter)) - return ter; - - // Sanity check - if (accountHolds( - view(), - vaultAccount, - assetsRecovered.asset(), - FreezeHandling::fhIGNORE_FREEZE, - AuthHandling::ahIGNORE_AUTH, - j_) < beast::zero) + if (assetsRecovered > beast::zero) { - // LCOV_EXCL_START - JLOG(j_.error()) << "VaultClawback: negative balance of vault assets."; - return tefINTERNAL; - // LCOV_EXCL_STOP + // Transfer assets from vault to issuer. + if (auto const ter = accountSend( + view(), + vaultAccount, + account_, + assetsRecovered, + j_, + WaiveTransferFee::Yes); + !isTesSuccess(ter)) + return ter; + + // Sanity check + if (accountHolds( + view(), + vaultAccount, + assetsRecovered.asset(), + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + j_) < beast::zero) + { + // LCOV_EXCL_START + JLOG(j_.error()) + << "VaultClawback: negative balance of vault assets."; + return tefINTERNAL; + // LCOV_EXCL_STOP + } } return tesSUCCESS; diff --git a/src/xrpld/app/tx/detail/VaultClawback.h b/src/xrpld/app/tx/detail/VaultClawback.h index 80a5f73ad0..d05f280e75 100644 --- a/src/xrpld/app/tx/detail/VaultClawback.h +++ b/src/xrpld/app/tx/detail/VaultClawback.h @@ -22,6 +22,14 @@ public: TER doApply() override; + +private: + Expected, TER> + assetsToClawback( + std::shared_ptr const& vault, + std::shared_ptr const& sleShareIssuance, + AccountID const& holder, + STAmount const& clawbackAmount); }; } // namespace xrpl From 7c1183547abb054878b24dd06fc2aab4e01ca350 Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 9 Jan 2026 16:44:43 -0500 Subject: [PATCH 064/105] chore: Change `/Zi` to `/Z7` for ccache, remove debug symbols in CI (#6198) As the `/Zi` compiler flag is unsupported by ccache, this change switches it to `/Z7` instead. For CI runs all debug info is omitted. --- .config/cspell.config.yaml | 1 + .github/workflows/reusable-build-test-config.yml | 2 +- cmake/Ccache.cmake | 12 +++++++++--- cmake/XrplCompiler.cmake | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.config/cspell.config.yaml b/.config/cspell.config.yaml index 0cac82807d..edcdcc92ba 100644 --- a/.config/cspell.config.yaml +++ b/.config/cspell.config.yaml @@ -51,6 +51,7 @@ words: - Btrfs - canonicality - checkme + - choco - chrono - citardauq - clawback diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index fc80bbd216..ae91a8bf20 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -100,7 +100,7 @@ jobs: uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Prepare runner - uses: XRPLF/actions/prepare-runner@65da1c59e81965eeb257caa3587b9d45066fb925 + uses: XRPLF/actions/prepare-runner@121d1de2775d486d46140b9a91b32d5002c08153 with: enable_ccache: ${{ inputs.ccache_enabled }} diff --git a/cmake/Ccache.cmake b/cmake/Ccache.cmake index 092212075c..aa8d3ac59d 100644 --- a/cmake/Ccache.cmake +++ b/cmake/Ccache.cmake @@ -46,6 +46,12 @@ set(CMAKE_VS_GLOBALS "TrackFileAccess=false" "UseMultiToolTask=true") -# By default Visual Studio generators will use /Zi, which is not compatible with -# ccache, so tell it to use /Z7 instead. -set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") +# By default Visual Studio generators will use /Zi to capture debug information, +# which is not compatible with ccache, so tell it to use /Z7 instead. +if (MSVC) + foreach (var_ + CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE) + string (REPLACE "/Zi" "/Z7" ${var_} "${${var_}}") + endforeach () +endif () diff --git a/cmake/XrplCompiler.cmake b/cmake/XrplCompiler.cmake index 622b2d2f74..0777bf948c 100644 --- a/cmake/XrplCompiler.cmake +++ b/cmake/XrplCompiler.cmake @@ -44,6 +44,7 @@ if (MSVC) # omit debug info completely under CI (not needed) if (is_ci) string (REPLACE "/Zi" " " ${var_} "${${var_}}") + string (REPLACE "/Z7" " " ${var_} "${${var_}}") endif () endforeach () From b2c5927b488fa0c306117de971f336c8d49317de Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Fri, 9 Jan 2026 23:10:04 -0400 Subject: [PATCH 065/105] fix: Inner batch transactions never have valid signatures (#6069) - Introduces amendment `fixBatchInnerSigs` - Update Batch unit tests - Fix all the Env instantiations to _use_ the "features" parameter. - testInnerSubmitRPC runs with Batch enabled and disabled. - Add a test to testInnerSubmitRPC for a correctly signed tx incorrectly using the tfInnerBatchTxn flag. - Generalize the submitAndValidate lambda in testInnerSubmitRPC. - With the fix amendment, a transaction never reaches the transaction engine (Transactor and derived classes.) - Test submitting a pseudo-transaction. Stopped before reaching the transaction engine, but with different errors. - The tests verify that without the amendment, a transaction with tfInnerBatchTxn is immediately rejected. Without the amendment, things are safe. The amendment just makes things safer and more future-proof. --- include/xrpl/protocol/detail/features.macro | 1 + src/test/app/Batch_test.cpp | 281 ++++++++++++++------ src/xrpld/app/misc/NetworkOPs.cpp | 2 +- src/xrpld/app/tx/detail/Transactor.cpp | 8 +- src/xrpld/app/tx/detail/apply.cpp | 21 +- 5 files changed, 221 insertions(+), 92 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 5c8d2aa198..932668c16f 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -16,6 +16,7 @@ // Add new amendments to the top of this list. // Keep it sorted in reverse chronological order. +XRPL_FIX (BatchInnerSigs, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(LendingProtocol, Supported::no, VoteBehavior::DefaultNo) XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo) XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo) diff --git a/src/test/app/Batch_test.cpp b/src/test/app/Batch_test.cpp index 6fbec52a93..68bf7e833b 100644 --- a/src/test/app/Batch_test.cpp +++ b/src/test/app/Batch_test.cpp @@ -148,15 +148,21 @@ class Batch_test : public beast::unit_test::suite void testEnable(FeatureBitset features) { - testcase("enabled"); - using namespace test::jtx; using namespace std::literals; + bool const withInnerSigFix = features[fixBatchInnerSigs]; + for (bool const withBatch : {true, false}) { + testcase << "enabled: Batch " + << (withBatch ? "enabled" : "disabled") + << ", Inner Sig Fix: " + << (withInnerSigFix ? "enabled" : "disabled"); + auto const amend = withBatch ? features : features - featureBatch; - test::jtx::Env env{*this, envconfig(), amend}; + + test::jtx::Env env{*this, amend}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -179,7 +185,7 @@ class Batch_test : public beast::unit_test::suite // tfInnerBatchTxn // If the feature is disabled, the transaction fails with - // temINVALID_FLAG If the feature is enabled, the transaction fails + // temINVALID_FLAG. If the feature is enabled, the transaction fails // early in checkValidity() { auto const txResult = @@ -205,7 +211,7 @@ class Batch_test : public beast::unit_test::suite //---------------------------------------------------------------------- // preflight - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -617,7 +623,7 @@ class Batch_test : public beast::unit_test::suite //---------------------------------------------------------------------- // preclaim - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -858,7 +864,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -949,7 +955,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1187,7 +1193,7 @@ class Batch_test : public beast::unit_test::suite // Bad Fee Without Signer { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1209,7 +1215,7 @@ class Batch_test : public beast::unit_test::suite // Bad Fee With MultiSign { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1236,7 +1242,7 @@ class Batch_test : public beast::unit_test::suite // Bad Fee With MultiSign + BatchSigners { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1265,7 +1271,7 @@ class Batch_test : public beast::unit_test::suite // Bad Fee With MultiSign + BatchSigners.Signers { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1297,7 +1303,7 @@ class Batch_test : public beast::unit_test::suite // Bad Fee With BatchSigners { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1321,7 +1327,7 @@ class Batch_test : public beast::unit_test::suite // Bad Fee Dynamic Fee Calculation { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1361,7 +1367,7 @@ class Batch_test : public beast::unit_test::suite // telENV_RPC_FAILED: Batch: txns array exceeds 8 entries. { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1386,7 +1392,7 @@ class Batch_test : public beast::unit_test::suite // temARRAY_TOO_LARGE: Batch: txns array exceeds 8 entries. { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1419,7 +1425,7 @@ class Batch_test : public beast::unit_test::suite // telENV_RPC_FAILED: Batch: signers array exceeds 8 entries. { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1438,7 +1444,7 @@ class Batch_test : public beast::unit_test::suite // temARRAY_TOO_LARGE: Batch: signers array exceeds 8 entries. { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1472,7 +1478,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1608,7 +1614,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -1840,7 +1846,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2062,7 +2068,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2248,14 +2254,26 @@ class Batch_test : public beast::unit_test::suite } void - testInnerSubmitRPC(FeatureBitset features) + doTestInnerSubmitRPC(FeatureBitset features, bool withBatch) { - testcase("inner submit rpc"); + bool const withInnerSigFix = features[fixBatchInnerSigs]; + + std::string const testName = [&]() { + std::stringstream ss; + ss << "inner submit rpc: batch " + << (withBatch ? "enabled" : "disabled") << ", inner sig fix: " + << (withInnerSigFix ? "enabled" : "disabled") << ": "; + return ss.str(); + }(); + + auto const amend = withBatch ? features : features - featureBatch; using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, amend}; + if (!BEAST_EXPECT(amend[featureBatch] == withBatch)) + return; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2263,75 +2281,170 @@ class Batch_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob); env.close(); - auto submitAndValidate = [&](Slice const& slice) { - auto const jrr = env.rpc("submit", strHex(slice))[jss::result]; - BEAST_EXPECT( - jrr[jss::status] == "error" && - jrr[jss::error] == "invalidTransaction" && - jrr[jss::error_exception] == - "fails local checks: Malformed: Invalid inner batch " - "transaction."); - env.close(); - }; + auto submitAndValidate = + [&](std::string caseName, + Slice const& slice, + int line, + std::optional expectedEnabled = std::nullopt, + std::optional expectedDisabled = std::nullopt, + bool expectInvalidFlag = false) { + testcase << testName << caseName + << (expectInvalidFlag + ? " - Expected to reach tx engine!" + : ""); + auto const jrr = env.rpc("submit", strHex(slice))[jss::result]; + auto const expected = withBatch + ? expectedEnabled.value_or( + "fails local checks: Malformed: Invalid inner batch " + "transaction.") + : expectedDisabled.value_or( + "fails local checks: Empty SigningPubKey."); + if (expectInvalidFlag) + { + expect( + jrr[jss::status] == "success" && + jrr[jss::engine_result] == "temINVALID_FLAG", + pretty(jrr), + __FILE__, + line); + } + else + { + expect( + jrr[jss::status] == "error" && + jrr[jss::error] == "invalidTransaction" && + jrr[jss::error_exception] == expected, + pretty(jrr), + __FILE__, + line); + } + env.close(); + }; // Invalid RPC Submission: TxnSignature - // - has `TxnSignature` field + // + has `TxnSignature` field // - has no `SigningPubKey` field // - has no `Signers` field - // - has `tfInnerBatchTxn` flag + // + has `tfInnerBatchTxn` flag { auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice)); txn[sfTxnSignature] = "DEADBEEF"; STParsedJSONObject parsed("test", txn.getTxn()); Serializer s; parsed.object->add(s); - submitAndValidate(s.slice()); + submitAndValidate("TxnSignature set", s.slice(), __LINE__); } // Invalid RPC Submission: SigningPubKey // - has no `TxnSignature` field - // - has `SigningPubKey` field + // + has `SigningPubKey` field // - has no `Signers` field - // - has `tfInnerBatchTxn` flag + // + has `tfInnerBatchTxn` flag { auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice)); txn[sfSigningPubKey] = strHex(alice.pk()); STParsedJSONObject parsed("test", txn.getTxn()); Serializer s; parsed.object->add(s); - submitAndValidate(s.slice()); + submitAndValidate( + "SigningPubKey set", + s.slice(), + __LINE__, + std::nullopt, + "fails local checks: Invalid signature."); } // Invalid RPC Submission: Signers // - has no `TxnSignature` field - // - has empty `SigningPubKey` field - // - has `Signers` field - // - has `tfInnerBatchTxn` flag + // + has empty `SigningPubKey` field + // + has `Signers` field + // + has `tfInnerBatchTxn` flag { auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice)); txn[sfSigners] = Json::arrayValue; STParsedJSONObject parsed("test", txn.getTxn()); Serializer s; parsed.object->add(s); - submitAndValidate(s.slice()); + submitAndValidate( + "Signers set", + s.slice(), + __LINE__, + std::nullopt, + "fails local checks: Invalid Signers array size."); + } + + { + // Fully signed inner batch transaction + auto const txn = + batch::inner(pay(alice, bob, XRP(1)), env.seq(alice)); + auto const jt = env.jt(txn.getTxn()); + + STParsedJSONObject parsed("test", jt.jv); + Serializer s; + parsed.object->add(s); + submitAndValidate( + "Fully signed", + s.slice(), + __LINE__, + std::nullopt, + std::nullopt, + !withBatch); } // Invalid RPC Submission: tfInnerBatchTxn // - has no `TxnSignature` field - // - has empty `SigningPubKey` field + // + has empty `SigningPubKey` field // - has no `Signers` field - // - has `tfInnerBatchTxn` flag + // + has `tfInnerBatchTxn` flag { auto txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice)); STParsedJSONObject parsed("test", txn.getTxn()); Serializer s; parsed.object->add(s); - auto const jrr = env.rpc("submit", strHex(s.slice()))[jss::result]; - BEAST_EXPECT( - jrr[jss::status] == "success" && - jrr[jss::engine_result] == "temINVALID_FLAG"); + submitAndValidate( + "No signing fields set", + s.slice(), + __LINE__, + "fails local checks: Empty SigningPubKey.", + "fails local checks: Empty SigningPubKey.", + withBatch && !withInnerSigFix); + } - env.close(); + // Invalid RPC Submission: tfInnerBatchTxn pseudo-transaction + // - has no `TxnSignature` field + // + has empty `SigningPubKey` field + // - has no `Signers` field + // + has `tfInnerBatchTxn` flag + { + STTx amendTx( + ttAMENDMENT, [seq = env.closed()->header().seq + 1](auto& obj) { + obj.setAccountID(sfAccount, AccountID()); + obj.setFieldH256(sfAmendment, fixBatchInnerSigs); + obj.setFieldU32(sfLedgerSequence, seq); + obj.setFieldU32(sfFlags, tfInnerBatchTxn); + }); + auto txn = batch::inner( + amendTx.getJson(JsonOptions::none), env.seq(alice)); + STParsedJSONObject parsed("test", txn.getTxn()); + Serializer s; + parsed.object->add(s); + submitAndValidate( + "Pseudo-transaction", + s.slice(), + __LINE__, + withInnerSigFix + ? "fails local checks: Empty SigningPubKey." + : "fails local checks: Cannot submit pseudo transactions.", + "fails local checks: Empty SigningPubKey."); + } + } + + void + testInnerSubmitRPC(FeatureBitset features) + { + for (bool const withBatch : {true, false}) + { + doTestInnerSubmitRPC(features, withBatch); } } @@ -2343,7 +2456,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2390,7 +2503,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2443,7 +2556,7 @@ class Batch_test : public beast::unit_test::suite // tfIndependent: account delete success { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2484,7 +2597,7 @@ class Batch_test : public beast::unit_test::suite // tfIndependent: account delete fails { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2529,7 +2642,7 @@ class Batch_test : public beast::unit_test::suite // tfAllOrNothing: account delete fails { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2581,7 +2694,6 @@ class Batch_test : public beast::unit_test::suite test::jtx::Env env{ *this, - envconfig(), features | featureSingleAssetVault | featureLendingProtocol | featureMPTokensV1}; @@ -2776,7 +2888,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2889,7 +3001,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -2947,7 +3059,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -3009,7 +3121,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -3058,7 +3170,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -3106,7 +3218,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -3169,7 +3281,7 @@ class Batch_test : public beast::unit_test::suite // overwritten by the payment in the batch transaction. Because the // terPRE_SEQ is outside of the batch this noop transaction will ge // reapplied in the following ledger - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob, carol); env.close(); @@ -3216,7 +3328,7 @@ class Batch_test : public beast::unit_test::suite // IMPORTANT: The batch txn is applied first, then the noop txn. // Because of this ordering, the noop txn is not applied and is // overwritten by the payment in the batch transaction. - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob); env.close(); @@ -3258,7 +3370,7 @@ class Batch_test : public beast::unit_test::suite // IMPORTANT: The batch txn is applied first, then the noop txn. // Because of this ordering, the noop txn is not applied and is // overwritten by the payment in the batch transaction. - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob); env.close(); @@ -3295,7 +3407,7 @@ class Batch_test : public beast::unit_test::suite // Outer Batch terPRE_SEQ { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob, carol); env.close(); @@ -3353,7 +3465,7 @@ class Batch_test : public beast::unit_test::suite // IMPORTANT: The batch txn is applied first, then the noop txn. // Because of this ordering, the noop txn is not applied and is // overwritten by the payment in the batch transaction. - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob); env.close(); @@ -3402,7 +3514,7 @@ class Batch_test : public beast::unit_test::suite // IMPORTANT: The batch txn is applied first, then the noop txn. // Because of this ordering, the noop txn is not applied and is // overwritten by the payment in the batch transaction. - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob); env.close(); @@ -3464,7 +3576,7 @@ class Batch_test : public beast::unit_test::suite // batch will run in the close ledger process. The batch will be // allied and then retry this transaction in the current ledger. - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob); env.close(); @@ -3511,7 +3623,7 @@ class Batch_test : public beast::unit_test::suite // Create Object Before Batch Txn { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob); env.close(); @@ -3558,7 +3670,7 @@ class Batch_test : public beast::unit_test::suite // batch will run in the close ledger process. The batch will be // applied and then retry this transaction in the current ledger. - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; env.fund(XRP(10000), alice, bob); env.close(); @@ -3605,7 +3717,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -3644,7 +3756,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; XRPAmount const baseFee = env.current()->fees().base; auto const alice = Account("alice"); @@ -3725,6 +3837,7 @@ class Batch_test : public beast::unit_test::suite *this, makeSmallQueueConfig( {{"minimum_txn_in_ledger_standalone", "2"}}), + features, nullptr, beast::severities::kError}; @@ -3785,6 +3898,7 @@ class Batch_test : public beast::unit_test::suite *this, makeSmallQueueConfig( {{"minimum_txn_in_ledger_standalone", "2"}}), + features, nullptr, beast::severities::kError}; @@ -3892,7 +4006,7 @@ class Batch_test : public beast::unit_test::suite // delegated non atomic inner { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -3937,7 +4051,7 @@ class Batch_test : public beast::unit_test::suite // delegated atomic inner { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -3989,7 +4103,7 @@ class Batch_test : public beast::unit_test::suite // this also makes sure tfInnerBatchTxn won't block delegated AccountSet // with granular permission { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); @@ -4038,7 +4152,7 @@ class Batch_test : public beast::unit_test::suite // this also makes sure tfInnerBatchTxn won't block delegated // MPTokenIssuanceSet with granular permission { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; Account alice{"alice"}; Account bob{"bob"}; env.fund(XRP(100000), alice, bob); @@ -4094,7 +4208,7 @@ class Batch_test : public beast::unit_test::suite // this also makes sure tfInnerBatchTxn won't block delegated TrustSet // with granular permission { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; Account gw{"gw"}; Account alice{"alice"}; Account bob{"bob"}; @@ -4134,7 +4248,7 @@ class Batch_test : public beast::unit_test::suite // inner transaction not authorized by the delegating account. { - test::jtx::Env env{*this, envconfig()}; + test::jtx::Env env{*this, features}; Account gw{"gw"}; Account alice{"alice"}; Account bob{"bob"}; @@ -4182,7 +4296,7 @@ class Batch_test : public beast::unit_test::suite testcase("Validate RPC response"); using namespace jtx; - Env env(*this); + Env env(*this, features); Account const alice("alice"); Account const bob("bob"); env.fund(XRP(10000), alice, bob); @@ -4259,7 +4373,7 @@ class Batch_test : public beast::unit_test::suite testBatchCalculateBaseFee(FeatureBitset features) { using namespace jtx; - Env env(*this); + Env env(*this, features); Account const alice("alice"); Account const bob("bob"); Account const carol("carol"); @@ -4384,6 +4498,7 @@ public: { using namespace test::jtx; auto const sa = testable_amendments(); + testWithFeats(sa - fixBatchInnerSigs); testWithFeats(sa); } }; diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index 6a00354b15..2422ec4ae6 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -1681,7 +1681,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) // only be set if the Batch feature is enabled. If Batch is // not enabled, the flag is always invalid, so don't relay // it regardless. - !sttx.isFlag(tfInnerBatchTxn)) + !(sttx.isFlag(tfInnerBatchTxn))) { protocol::TMTransaction tx; Serializer s; diff --git a/src/xrpld/app/tx/detail/Transactor.cpp b/src/xrpld/app/tx/detail/Transactor.cpp index 851712fe90..a834f7c6c3 100644 --- a/src/xrpld/app/tx/detail/Transactor.cpp +++ b/src/xrpld/app/tx/detail/Transactor.cpp @@ -204,8 +204,14 @@ Transactor::preflight2(PreflightContext const& ctx) // regardless of success or failure return *ret; + // It should be impossible for the InnerBatchTxn flag to be set without + // featureBatch being enabled + XRPL_ASSERT_PARTS( + !ctx.tx.isFlag(tfInnerBatchTxn) || ctx.rules.enabled(featureBatch), + "xrpl::Transactor::preflight2", + "InnerBatch flag only set if feature enabled"); // Skip signature check on batch inner transactions - if (ctx.tx.isFlag(tfInnerBatchTxn) && !ctx.rules.enabled(featureBatch)) + if (ctx.tx.isFlag(tfInnerBatchTxn) && ctx.rules.enabled(featureBatch)) return tesSUCCESS; // Do not add any checks after this point that are relevant for // batch inner transactions. They will be skipped. diff --git a/src/xrpld/app/tx/detail/apply.cpp b/src/xrpld/app/tx/detail/apply.cpp index 5209c46f8f..a75f0cc967 100644 --- a/src/xrpld/app/tx/detail/apply.cpp +++ b/src/xrpld/app/tx/detail/apply.cpp @@ -41,15 +41,22 @@ checkValidity( Validity::SigBad, "Malformed: Invalid inner batch transaction."}; - std::string reason; - if (!passesLocalChecks(tx, reason)) + // This block should probably have never been included in the + // original `Batch` implementation. An inner transaction never + // has a valid signature. + bool const neverValid = rules.enabled(fixBatchInnerSigs); + if (!neverValid) { - router.setFlags(id, SF_LOCALBAD); - return {Validity::SigGoodOnly, reason}; - } + std::string reason; + if (!passesLocalChecks(tx, reason)) + { + router.setFlags(id, SF_LOCALBAD); + return {Validity::SigGoodOnly, reason}; + } - router.setFlags(id, SF_SIGGOOD); - return {Validity::Valid, ""}; + router.setFlags(id, SF_SIGGOOD); + return {Validity::Valid, ""}; + } } if (any(flags & SF_SIGBAD)) From 92d40de4cbb787474f90d6aa6a959963f8299992 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 12 Jan 2026 12:53:46 -0500 Subject: [PATCH 066/105] chore: Pin pre-commit hooks to commit hashes (#6205) This change updates and pins the Black and CSpell pre-commit hooks. --- .config/cspell.config.yaml | 4 ++++ .pre-commit-config.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.config/cspell.config.yaml b/.config/cspell.config.yaml index edcdcc92ba..8f782d9960 100644 --- a/.config/cspell.config.yaml +++ b/.config/cspell.config.yaml @@ -69,6 +69,7 @@ words: - cryptoconditional - cryptoconditions - csprng + - ctest - ctid - currenttxhash - daria @@ -104,6 +105,7 @@ words: - iou - ious - isrdc + - itype - jemalloc - jlog - keylet @@ -192,10 +194,12 @@ words: - roundings - sahyadri - Satoshi + - scons - secp - sendq - seqit - sf + - SFIELD - shamap - shamapitem - sidechain diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 00bec32ed6..603cf39375 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,12 +32,12 @@ repos: - id: prettier - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.11.0 + rev: 831207fd435b47aeffdf6af853097e64322b4d44 # frozen: v25.12.0 hooks: - id: black - repo: https://github.com/streetsidesoftware/cspell-cli - rev: v9.2.0 + rev: 1cfa010f078c354f3ffb8413616280cc28f5ba21 # frozen: v9.4.0 hooks: - id: cspell # Spell check changed files exclude: .config/cspell.config.yaml From 4755bb86068d056258d643274f8e75c878560685 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 12 Jan 2026 19:14:39 -0500 Subject: [PATCH 067/105] refactor: Remove unnecessary version number and options in cmake find_package (#6169) This change removes unnecessary version numbers in the OpenSSL and Boost `find_package` CMake statements. An unnecessary OpenSSL definition is removed, while Conan options for SSL are updated to disable insecure ciphers. Moreover, the statements are now ordered alphabetically and more logically. --- BUILD.md | 19 ++++++++----- CMakeLists.txt | 37 ++++++++++--------------- cmake/deps/Boost.cmake | 2 +- conan.lock | 62 +++++++++++++++++++++--------------------- conanfile.py | 6 ++++ 5 files changed, 65 insertions(+), 61 deletions(-) diff --git a/BUILD.md b/BUILD.md index 85b3e3ea74..2d1ac9b134 100644 --- a/BUILD.md +++ b/BUILD.md @@ -148,7 +148,8 @@ function extract_version { } # Define which recipes to export. -recipes=(ed25519 grpc secp256k1 snappy soci) +recipes=('ed25519' 'grpc' 'openssl' 'secp256k1' 'snappy' 'soci') +folders=('all' 'all' '3.x.x' 'all' 'all' 'all') # Selectively check out the recipes from our CCI fork. cd external @@ -157,20 +158,24 @@ cd conan-center-index git init git remote add origin git@github.com:XRPLF/conan-center-index.git git sparse-checkout init -for recipe in ${recipes[@]}; do - echo "Checking out ${recipe}..." - git sparse-checkout add recipes/${recipe}/all +for ((index = 1; index <= ${#recipes[@]}; index++)); do + recipe=${recipes[index]} + folder=${folders[index]} + echo "Checking out recipe '${recipe}' from folder '${folder}'..." + git sparse-checkout add recipes/${recipe}/${folder} done git fetch origin master git checkout master cd ../.. # Export the recipes into the local cache. -for recipe in ${recipes[@]}; do +for ((index = 1; index <= ${#recipes[@]}; index++)); do + recipe=${recipes[index]} + folder=${folders[index]} version=$(extract_version ${recipe}) - echo "Exporting ${recipe}/${version}..." + echo "Exporting '${recipe}/${version}' from '${recipe}/${folder}'..." conan export --version $(extract_version ${recipe}) \ - external/conan-center-index/recipes/${recipe}/all + external/conan-center-index/recipes/${recipe}/${folder} done ``` diff --git a/CMakeLists.txt b/CMakeLists.txt index 70bc02c66d..26fc310d39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,34 +88,18 @@ endif() ### include(deps/Boost) -find_package(OpenSSL 1.1.1 REQUIRED) -set_target_properties(OpenSSL::SSL PROPERTIES - INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2 -) add_subdirectory(external/antithesis-sdk) -find_package(gRPC REQUIRED) -find_package(lz4 REQUIRED) -# Target names with :: are not allowed in a generator expression. -# We need to pull the include directories and imported location properties -# from separate targets. -find_package(LibArchive REQUIRED) -find_package(SOCI REQUIRED) -find_package(SQLite3 REQUIRED) - -option(rocksdb "Enable RocksDB" ON) -if(rocksdb) - find_package(RocksDB REQUIRED) - set_target_properties(RocksDB::rocksdb PROPERTIES - INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1 - ) - target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb) -endif() - find_package(date REQUIRED) find_package(ed25519 REQUIRED) +find_package(gRPC REQUIRED) +find_package(LibArchive REQUIRED) +find_package(lz4 REQUIRED) find_package(nudb REQUIRED) +find_package(OpenSSL REQUIRED) find_package(secp256k1 REQUIRED) +find_package(SOCI REQUIRED) +find_package(SQLite3 REQUIRED) find_package(xxHash REQUIRED) target_link_libraries(xrpl_libs INTERFACE @@ -128,6 +112,15 @@ target_link_libraries(xrpl_libs INTERFACE SQLite::SQLite3 ) +option(rocksdb "Enable RocksDB" ON) +if(rocksdb) + find_package(RocksDB REQUIRED) + set_target_properties(RocksDB::rocksdb PROPERTIES + INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1 + ) + target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb) +endif() + # Work around changes to Conan recipe for now. if(TARGET nudb::core) set(nudb nudb::core) diff --git a/cmake/deps/Boost.cmake b/cmake/deps/Boost.cmake index 475c1033b2..19263e0ac9 100644 --- a/cmake/deps/Boost.cmake +++ b/cmake/deps/Boost.cmake @@ -1,4 +1,4 @@ -find_package(Boost 1.82 REQUIRED +find_package(Boost REQUIRED COMPONENTS chrono container diff --git a/conan.lock b/conan.lock index 1385ad05bd..99522e79b2 100644 --- a/conan.lock +++ b/conan.lock @@ -1,44 +1,44 @@ { "version": "0.5", "requires": [ - "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497", - "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1756234289.683", - "sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869", - "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318", - "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246", - "secp256k1/0.7.0#9c4ab67bdc3860c16ea5b36aed8f74ea%1765202256.763", - "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1762797952.535", - "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1764175362.029", - "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1764863245.83", - "openssl/3.5.4#a1d5835cc6ed5c5b8f3cd5b9b5d24205%1760106486.594", - "nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1763150366.909", - "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999", - "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64", - "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03", - "libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1764175360.142", + "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075", + "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987", + "sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926", + "soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46", + "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878", + "secp256k1/0.7.0#9c4ab67bdc3860c16ea5b36aed8f74ea%1765850147.928", + "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86", + "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103", + "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038", + "openssl/3.5.4#58f5173c2ee51d6fc0f0c61b4eddadbb%1768259092.666", + "nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1765850143.957", + "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914", + "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492", + "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03", + "libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736", "jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244", - "grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1763158050.628", - "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1764270189.893", - "doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1762797941.757", - "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1763584497.32", - "c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1764175359.429", - "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1764175359.429", - "boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1756223752.326", - "abseil/20250127.0#9e8e8cfc89a1324139fc0ee3bd4d8c8c%1753819045.301" + "grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1765850193.734", + "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772", + "doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1765850143.95", + "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772", + "c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336", + "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837", + "boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1765850172.862", + "abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993" ], "build_requires": [ - "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497", - "strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1756234281.733", - "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1764863245.83", - "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1756234232.901", + "zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075", + "strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1765850165.196", + "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038", + "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707", "msys2/cci.latest#1996656c3c98e5765b25b60ff5cf77b4%1764840888.758", "m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846", - "cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1764175359.44", - "cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1764175359.429", - "b2/5.3.3#107c15377719889654eb9a162a673975%1756234226.28", + "cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1765850153.937", + "cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479", + "b2/5.3.3#107c15377719889654eb9a162a673975%1765850144.355", "automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56", "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86", - "abseil/20250127.0#9e8e8cfc89a1324139fc0ee3bd4d8c8c%1753819045.301" + "abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993" ], "python_requires": [], "overrides": { diff --git a/conanfile.py b/conanfile.py index 48e28cb275..96e3384979 100644 --- a/conanfile.py +++ b/conanfile.py @@ -87,7 +87,13 @@ class Xrpl(ConanFile): "libarchive/*:with_xattr": False, "libarchive/*:with_zlib": False, "lz4/*:shared": False, + "openssl/*:no_dtls": True, + "openssl/*:no_ssl": True, + "openssl/*:no_ssl3": True, + "openssl/*:no_tls1": True, + "openssl/*:no_tls1_1": True, "openssl/*:shared": False, + "openssl/*:tls_security_level": 2, "protobuf/*:shared": False, "protobuf/*:with_zlib": True, "rocksdb/*:enable_sse": False, From 0efae5d16e433d504064ff6f6174ed02a37c61ea Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Tue, 13 Jan 2026 16:52:10 +0000 Subject: [PATCH 068/105] ci: Update actions/images to use cmake 4.2.1 and conan 2.24.0 (#6209) --- .github/scripts/strategy-matrix/linux.json | 56 +++++++++---------- .github/workflows/pre-commit.yml | 4 +- .../workflows/reusable-build-test-config.yml | 2 +- .github/workflows/upload-conan-deps.yml | 2 +- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/scripts/strategy-matrix/linux.json b/.github/scripts/strategy-matrix/linux.json index 669754554c..e64a05f925 100644 --- a/.github/scripts/strategy-matrix/linux.json +++ b/.github/scripts/strategy-matrix/linux.json @@ -15,196 +15,196 @@ "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "12", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "13", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "gcc", "compiler_version": "15", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "16", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "17", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "18", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "19", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "bookworm", "compiler_name": "clang", "compiler_version": "20", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "trixie", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "trixie", "compiler_name": "gcc", "compiler_version": "15", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "trixie", "compiler_name": "clang", "compiler_version": "20", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "debian", "distro_version": "trixie", "compiler_name": "clang", "compiler_version": "21", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "rhel", "distro_version": "8", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "rhel", "distro_version": "8", "compiler_name": "clang", "compiler_version": "any", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "rhel", "distro_version": "9", "compiler_name": "gcc", "compiler_version": "12", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "rhel", "distro_version": "9", "compiler_name": "gcc", "compiler_version": "13", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "rhel", "distro_version": "9", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "rhel", "distro_version": "9", "compiler_name": "clang", "compiler_version": "any", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "rhel", "distro_version": "10", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "rhel", "distro_version": "10", "compiler_name": "clang", "compiler_version": "any", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "ubuntu", "distro_version": "jammy", "compiler_name": "gcc", "compiler_version": "12", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "gcc", "compiler_version": "13", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "gcc", "compiler_version": "14", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "clang", "compiler_version": "16", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "clang", "compiler_version": "17", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "clang", "compiler_version": "18", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" }, { "distro_name": "ubuntu", "distro_version": "noble", "compiler_name": "clang", "compiler_version": "19", - "image_sha": "cc09fd3" + "image_sha": "ab4d1f0" } ], "build_type": ["Debug", "Release"], diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 41e82fb6bb..00754e5eae 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -9,7 +9,7 @@ on: jobs: # Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks. run-hooks: - uses: XRPLF/actions/.github/workflows/pre-commit.yml@5ca417783f0312ab26d6f48b85c78edf1de99bbd + uses: XRPLF/actions/.github/workflows/pre-commit.yml@282890f46d6921249d5659dd38babcb0bd8aef48 with: runs_on: ubuntu-latest - container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }' + container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-ab4d1f0" }' diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index ae91a8bf20..bc0717e1a5 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -100,7 +100,7 @@ jobs: uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Prepare runner - uses: XRPLF/actions/prepare-runner@121d1de2775d486d46140b9a91b32d5002c08153 + uses: XRPLF/actions/prepare-runner@f05cab7b8541eee6473aa42beb9d2fe35608a190 with: enable_ccache: ${{ inputs.ccache_enabled }} diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml index 55a9ab8864..29ae95fce5 100644 --- a/.github/workflows/upload-conan-deps.yml +++ b/.github/workflows/upload-conan-deps.yml @@ -70,7 +70,7 @@ jobs: uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Prepare runner - uses: XRPLF/actions/prepare-runner@65da1c59e81965eeb257caa3587b9d45066fb925 + uses: XRPLF/actions/prepare-runner@f05cab7b8541eee6473aa42beb9d2fe35608a190 with: enable_ccache: false From 96866049632f9691372ab3cce2a877664db7c056 Mon Sep 17 00:00:00 2001 From: Bart Date: Tue, 13 Jan 2026 12:29:04 -0500 Subject: [PATCH 069/105] fix: Update Conan lock file with changed OpenSSL recipe (#6211) This change updates the `conan.lock` file with a changed OpenSSL recipe that contains a fix regarding options passed to the compiler --- conan.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conan.lock b/conan.lock index 99522e79b2..44dc9031d2 100644 --- a/conan.lock +++ b/conan.lock @@ -10,7 +10,7 @@ "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86", "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103", "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038", - "openssl/3.5.4#58f5173c2ee51d6fc0f0c61b4eddadbb%1768259092.666", + "openssl/3.5.4#1b986e61b38fdfda3b40bebc1b234393%1768312656.257", "nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1765850143.957", "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914", "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492", From 2601442e16c11b8b174d154758abb8ac4a9a6564 Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Tue, 13 Jan 2026 15:42:58 -0400 Subject: [PATCH 070/105] Improve and fix bugs in Lending Protocol (#6102) - Spec: XLS-66 Fix overpayment asserts (#6084) MPTTester::operator() parameter should be std::int64_t - Originally defined as uint64_t, but the testIssuerLoan() test called it with a negative number, causing an overflow to a very large number that in some circumstances could be silently cast back to an int64_t, but might not be. I believe this is UB, and we don't want to rely on that. Review feedback from @Tapanito: overpayment value change - In overpayment results, the management fee was being calculated twice: once as part of the value change, and as part of the fees paid. Exclude it from the value change. Fix Overpayment Calculation (#6087) - Adds additional unit tests to cover math calculations. - Removes unused methods. Review feedback from @shawnxie999: even more rounding - Round the initial total value computation upward, unless there is 0-interest. - Rename getVaultScale to getAssetsTotalScale, and convert one incorrect computation to use it. - Use adjustImpreciseNumber for LossUnrealized. - Add some logging to computeLoanProperties. Fix LoanBrokerSet debtMaximum limits (#6116) Fix some minor bugs in Lending Protocol (#6101) - add nodiscard to unimpairLoan, and check result in LoanPay - add a check to verify that issuer exists - improve LoanManage error code for dust amounts Check permissions in LoanSet and LoanPay (#6108) Disallow pseudo accounts to be Destination for LoanBrokerCoverWithdraw (#6106) Ensure vault asset cap is not exceeded (#6124) Fix Overpayment ValueChange calculation in Lending Protocol (#6114) - Adds loan state to LoanProperties. - Cleans up computeLoanProperties. - Fixes missing management fee from overpayment. fix: Enable LP Deposits when the broker is the asset issuer (#6119) * Replace accountHolds with accountSpendable when checking for account funds in VaultDeposit and LoanBrokerCoverDeposit Add a few minor changes (#6158) - Updates or fixes a couple of things I noticed while reviewing changes to the spec. - Rename sfPreviousPaymentDate to sfPreviousPaymentDueDate. - Make the vault asset cap check added in #6124 a little more robust: 1. Check in preflight if the vault is _already_ over the limit. 2. Prevent overflow when checking with the loan value. (Subtract instead of adding, in case the values are near maxint. Both return the same result. Also add a unit test so each case is covered. Add minimum grace period validation (#6133) Fix bugs: frozen pseudo-account, and FLC cutoff (#6170) refactor: Rename raw state to theoretical state (#6187) Check if a withdrawal amount exceeds any applicable receiving limit. (#6117) Fix overpayment result calculation (#6195) Address review feedback from Lending Protocol re-review (#6161) --------- Co-authored-by: Gregory Tsipenyuk Co-authored-by: Bronek Kozicki Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com> Co-authored-by: Shawn Xie <35279399+shawnxie999@users.noreply.github.com> Co-authored-by: Jingchen --- .../paths => include/xrpl/ledger}/Credit.h | 4 +- include/xrpl/ledger/View.h | 86 +- .../xrpl/protocol/detail/ledger_entries.macro | 2 +- include/xrpl/protocol/detail/sfields.macro | 2 +- .../app/paths => libxrpl/ledger}/Credit.cpp | 0 src/libxrpl/ledger/View.cpp | 219 +-- src/test/app/LendingHelpers_test.cpp | 1351 +++++++++++++++++ src/test/app/LoanBroker_test.cpp | 468 ++++++ src/test/app/Loan_test.cpp | 765 ++++++++-- src/test/app/Vault_test.cpp | 4 +- src/test/jtx/impl/mpt.cpp | 2 +- src/test/jtx/mpt.h | 2 +- src/xrpld/app/misc/LendingHelpers.h | 180 ++- src/xrpld/app/misc/detail/LendingHelpers.cpp | 526 +++---- src/xrpld/app/paths/Flow.cpp | 2 +- src/xrpld/app/paths/detail/DirectStep.cpp | 2 +- src/xrpld/app/paths/detail/StrandFlow.h | 2 +- .../app/paths/detail/XRPEndpointStep.cpp | 2 +- .../app/tx/detail/LoanBrokerCoverClawback.cpp | 12 +- .../app/tx/detail/LoanBrokerCoverDeposit.cpp | 3 +- .../app/tx/detail/LoanBrokerCoverWithdraw.cpp | 5 + src/xrpld/app/tx/detail/LoanBrokerDelete.cpp | 44 +- src/xrpld/app/tx/detail/LoanBrokerSet.cpp | 19 + src/xrpld/app/tx/detail/LoanDelete.cpp | 2 +- src/xrpld/app/tx/detail/LoanManage.cpp | 78 +- src/xrpld/app/tx/detail/LoanManage.h | 4 +- src/xrpld/app/tx/detail/LoanPay.cpp | 128 +- src/xrpld/app/tx/detail/LoanSet.cpp | 69 +- src/xrpld/app/tx/detail/VaultDeposit.cpp | 8 +- src/xrpld/rpc/handlers/LedgerEntry.cpp | 2 +- 30 files changed, 3242 insertions(+), 751 deletions(-) rename {src/xrpld/app/paths => include/xrpl/ledger}/Credit.h (93%) rename src/{xrpld/app/paths => libxrpl/ledger}/Credit.cpp (100%) create mode 100644 src/test/app/LendingHelpers_test.cpp diff --git a/src/xrpld/app/paths/Credit.h b/include/xrpl/ledger/Credit.h similarity index 93% rename from src/xrpld/app/paths/Credit.h rename to include/xrpl/ledger/Credit.h index 5bdcd70e74..09b65b3dde 100644 --- a/src/xrpld/app/paths/Credit.h +++ b/include/xrpl/ledger/Credit.h @@ -1,5 +1,5 @@ -#ifndef XRPL_APP_PATHS_CREDIT_H_INCLUDED -#define XRPL_APP_PATHS_CREDIT_H_INCLUDED +#ifndef XRPL_LEDGER_CREDIT_H_INCLUDED +#define XRPL_LEDGER_CREDIT_H_INCLUDED #include #include diff --git a/include/xrpl/ledger/View.h b/include/xrpl/ledger/View.h index 767622596b..707a08b890 100644 --- a/include/xrpl/ledger/View.h +++ b/include/xrpl/ledger/View.h @@ -61,6 +61,9 @@ enum FreezeHandling { fhIGNORE_FREEZE, fhZERO_IF_FROZEN }; /** Controls the treatment of unauthorized MPT balances */ enum AuthHandling { ahIGNORE_AUTH, ahZERO_IF_UNAUTHORIZED }; +/** Controls whether to include the account's full spendable balance */ +enum SpendableHandling { shSIMPLE_BALANCE, shFULL_BALANCE }; + [[nodiscard]] bool isGlobalFrozen(ReadView const& view, AccountID const& issuer); @@ -305,86 +308,57 @@ isLPTokenFrozen( Issue const& asset, Issue const& asset2); -// Returns the amount an account can spend without going into debt. +// Returns the amount an account can spend. // -// <-- saAmount: amount of currency held by account. May be negative. -[[nodiscard]] STAmount -accountHolds( - ReadView const& view, - AccountID const& account, - Currency const& currency, - AccountID const& issuer, - FreezeHandling zeroIfFrozen, - beast::Journal j); - -[[nodiscard]] STAmount -accountHolds( - ReadView const& view, - AccountID const& account, - Issue const& issue, - FreezeHandling zeroIfFrozen, - beast::Journal j); - -[[nodiscard]] STAmount -accountHolds( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue, - FreezeHandling zeroIfFrozen, - AuthHandling zeroIfUnauthorized, - beast::Journal j); - -[[nodiscard]] STAmount -accountHolds( - ReadView const& view, - AccountID const& account, - Asset const& asset, - FreezeHandling zeroIfFrozen, - AuthHandling zeroIfUnauthorized, - beast::Journal j); - -// Returns the amount an account can spend total. +// If shSIMPLE_BALANCE is specified, this is the amount the account can spend +// without going into debt. // -// These functions use accountHolds, but unlike accountHolds: -// * The account can go into debt. -// * If the account is the asset issuer the only limit is defined by the asset / +// If shFULL_BALANCE is specified, this is the amount the account can spend +// total. Specifically: +// * The account can go into debt if using a trust line, and the other side has +// a non-zero limit. +// * If the account is the asset issuer the limit is defined by the asset / // issuance. // // <-- saAmount: amount of currency held by account. May be negative. [[nodiscard]] STAmount -accountSpendable( +accountHolds( ReadView const& view, AccountID const& account, Currency const& currency, AccountID const& issuer, FreezeHandling zeroIfFrozen, - beast::Journal j); + beast::Journal j, + SpendableHandling includeFullBalance = shSIMPLE_BALANCE); [[nodiscard]] STAmount -accountSpendable( +accountHolds( ReadView const& view, AccountID const& account, Issue const& issue, FreezeHandling zeroIfFrozen, - beast::Journal j); + beast::Journal j, + SpendableHandling includeFullBalance = shSIMPLE_BALANCE); [[nodiscard]] STAmount -accountSpendable( +accountHolds( ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, FreezeHandling zeroIfFrozen, AuthHandling zeroIfUnauthorized, - beast::Journal j); + beast::Journal j, + SpendableHandling includeFullBalance = shSIMPLE_BALANCE); [[nodiscard]] STAmount -accountSpendable( +accountHolds( ReadView const& view, AccountID const& account, Asset const& asset, FreezeHandling zeroIfFrozen, AuthHandling zeroIfUnauthorized, - beast::Journal j); + beast::Journal j, + SpendableHandling includeFullBalance = shSIMPLE_BALANCE); // Returns the amount an account can spend of the currency type saDefault, or // returns saDefault if this account is the issuer of the currency in @@ -655,7 +629,7 @@ createPseudoAccount( uint256 const& pseudoOwnerKey, SField const& ownerField); -// Returns true iff sleAcct is a pseudo-account or specific +// Returns true if and only if sleAcct is a pseudo-account or specific // pseudo-accounts in pseudoFieldFilter. // // Returns false if sleAcct is @@ -710,13 +684,16 @@ checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag); * - If withdrawing to self, succeed. * - If not, checks if the receiver requires deposit authorization, and if * the sender has it. + * - Checks that the receiver will not exceed the limit (IOU trustline limit + * or MPT MaximumAmount). */ [[nodiscard]] TER canWithdraw( - AccountID const& from, ReadView const& view, + AccountID const& from, AccountID const& to, SLE::const_ref toSle, + STAmount const& amount, bool hasDestinationTag); /** Checks that can withdraw funds from an object to itself or a destination. @@ -730,12 +707,15 @@ canWithdraw( * - If withdrawing to self, succeed. * - If not, checks if the receiver requires deposit authorization, and if * the sender has it. + * - Checks that the receiver will not exceed the limit (IOU trustline limit + * or MPT MaximumAmount). */ [[nodiscard]] TER canWithdraw( - AccountID const& from, ReadView const& view, + AccountID const& from, AccountID const& to, + STAmount const& amount, bool hasDestinationTag); /** Checks that can withdraw funds from an object to itself or a destination. @@ -749,6 +729,8 @@ canWithdraw( * - If withdrawing to self, succeed. * - If not, checks if the receiver requires deposit authorization, and if * the sender has it. + * - Checks that the receiver will not exceed the limit (IOU trustline limit + * or MPT MaximumAmount). */ [[nodiscard]] TER canWithdraw(ReadView const& view, STTx const& tx); diff --git a/include/xrpl/protocol/detail/ledger_entries.macro b/include/xrpl/protocol/detail/ledger_entries.macro index de9c41bf52..216f404bec 100644 --- a/include/xrpl/protocol/detail/ledger_entries.macro +++ b/include/xrpl/protocol/detail/ledger_entries.macro @@ -541,7 +541,7 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({ {sfStartDate, soeREQUIRED}, {sfPaymentInterval, soeREQUIRED}, {sfGracePeriod, soeDEFAULT}, - {sfPreviousPaymentDate, soeDEFAULT}, + {sfPreviousPaymentDueDate, soeDEFAULT}, {sfNextPaymentDueDate, soeDEFAULT}, // The loan object tracks these values: // diff --git a/include/xrpl/protocol/detail/sfields.macro b/include/xrpl/protocol/detail/sfields.macro index d5c5d9447f..d0736469e4 100644 --- a/include/xrpl/protocol/detail/sfields.macro +++ b/include/xrpl/protocol/detail/sfields.macro @@ -102,7 +102,7 @@ TYPED_SFIELD(sfMutableFlags, UINT32, 53) TYPED_SFIELD(sfStartDate, UINT32, 54) TYPED_SFIELD(sfPaymentInterval, UINT32, 55) TYPED_SFIELD(sfGracePeriod, UINT32, 56) -TYPED_SFIELD(sfPreviousPaymentDate, UINT32, 57) +TYPED_SFIELD(sfPreviousPaymentDueDate, UINT32, 57) TYPED_SFIELD(sfNextPaymentDueDate, UINT32, 58) TYPED_SFIELD(sfPaymentRemaining, UINT32, 59) TYPED_SFIELD(sfPaymentTotal, UINT32, 60) diff --git a/src/xrpld/app/paths/Credit.cpp b/src/libxrpl/ledger/Credit.cpp similarity index 100% rename from src/xrpld/app/paths/Credit.cpp rename to src/libxrpl/ledger/Credit.cpp diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 329d3cfcae..14246baf17 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -464,7 +465,8 @@ accountHolds( Currency const& currency, AccountID const& issuer, FreezeHandling zeroIfFrozen, - beast::Journal j) + beast::Journal j, + SpendableHandling includeFullBalance) { STAmount amount; if (isXRP(currency)) @@ -472,11 +474,19 @@ accountHolds( return {xrpLiquid(view, account, 0, j)}; } + bool const returnSpendable = (includeFullBalance == shFULL_BALANCE); + if (returnSpendable && account == issuer) + // If the account is the issuer, then their limit is effectively + // infinite + return STAmount{ + Issue{currency, issuer}, STAmount::cMaxValue, STAmount::cMaxOffset}; + // IOU: Return balance on trust line modulo freeze SLE::const_pointer const sle = getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j); - return getTrustLineBalance(view, sle, account, currency, issuer, false, j); + return getTrustLineBalance( + view, sle, account, currency, issuer, returnSpendable, j); } STAmount @@ -485,10 +495,17 @@ accountHolds( AccountID const& account, Issue const& issue, FreezeHandling zeroIfFrozen, - beast::Journal j) + beast::Journal j, + SpendableHandling includeFullBalance) { return accountHolds( - view, account, issue.currency, issue.account, zeroIfFrozen, j); + view, + account, + issue.currency, + issue.account, + zeroIfFrozen, + j, + includeFullBalance); } STAmount @@ -498,8 +515,28 @@ accountHolds( MPTIssue const& mptIssue, FreezeHandling zeroIfFrozen, AuthHandling zeroIfUnauthorized, - beast::Journal j) + beast::Journal j, + SpendableHandling includeFullBalance) { + bool const returnSpendable = (includeFullBalance == shFULL_BALANCE); + + if (returnSpendable && account == mptIssue.getIssuer()) + { + // if the account is the issuer, and the issuance exists, their limit is + // the issuance limit minus the outstanding value + auto const issuance = + view.read(keylet::mptIssuance(mptIssue.getMptID())); + + if (!issuance) + { + return STAmount{mptIssue}; + } + return STAmount{ + mptIssue, + issuance->at(~sfMaximumAmount).value_or(maxMPTokenAmount) - + issuance->at(sfOutstandingAmount)}; + } + STAmount amount; auto const sleMpt = @@ -547,108 +584,27 @@ accountHolds( Asset const& asset, FreezeHandling zeroIfFrozen, AuthHandling zeroIfUnauthorized, - beast::Journal j) + beast::Journal j, + SpendableHandling includeFullBalance) { return std::visit( - [&](auto const& value) { - if constexpr (std::is_same_v< - std::remove_cvref_t, - Issue>) + [&](TIss const& value) { + if constexpr (std::is_same_v) { - return accountHolds(view, account, value, zeroIfFrozen, j); + return accountHolds( + view, account, value, zeroIfFrozen, j, includeFullBalance); } - return accountHolds( - view, account, value, zeroIfFrozen, zeroIfUnauthorized, j); - }, - asset.value()); -} - -STAmount -accountSpendable( - ReadView const& view, - AccountID const& account, - Currency const& currency, - AccountID const& issuer, - FreezeHandling zeroIfFrozen, - beast::Journal j) -{ - if (isXRP(currency)) - return accountHolds(view, account, currency, issuer, zeroIfFrozen, j); - - if (account == issuer) - // If the account is the issuer, then their limit is effectively - // infinite - return STAmount{ - Issue{currency, issuer}, STAmount::cMaxValue, STAmount::cMaxOffset}; - - // IOU: Return balance on trust line modulo freeze - SLE::const_pointer const sle = - getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j); - - return getTrustLineBalance(view, sle, account, currency, issuer, true, j); -} - -STAmount -accountSpendable( - ReadView const& view, - AccountID const& account, - Issue const& issue, - FreezeHandling zeroIfFrozen, - beast::Journal j) -{ - return accountSpendable( - view, account, issue.currency, issue.account, zeroIfFrozen, j); -} - -STAmount -accountSpendable( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue, - FreezeHandling zeroIfFrozen, - AuthHandling zeroIfUnauthorized, - beast::Journal j) -{ - if (account == mptIssue.getIssuer()) - { - // if the account is the issuer, and the issuance exists, their limit is - // the issuance limit minus the outstanding value - auto const issuance = - view.read(keylet::mptIssuance(mptIssue.getMptID())); - - if (!issuance) - { - return STAmount{mptIssue}; - } - return STAmount{ - mptIssue, - issuance->at(~sfMaximumAmount).value_or(maxMPTokenAmount) - - issuance->at(sfOutstandingAmount)}; - } - - return accountHolds( - view, account, mptIssue, zeroIfFrozen, zeroIfUnauthorized, j); -} - -[[nodiscard]] STAmount -accountSpendable( - ReadView const& view, - AccountID const& account, - Asset const& asset, - FreezeHandling zeroIfFrozen, - AuthHandling zeroIfUnauthorized, - beast::Journal j) -{ - return std::visit( - [&](auto const& value) { - if constexpr (std::is_same_v< - std::remove_cvref_t, - Issue>) + else if constexpr (std::is_same_v) { - return accountSpendable(view, account, value, zeroIfFrozen, j); + return accountHolds( + view, + account, + value, + zeroIfFrozen, + zeroIfUnauthorized, + j, + includeFullBalance); } - return accountSpendable( - view, account, value, zeroIfFrozen, zeroIfUnauthorized, j); }, asset.value()); } @@ -1205,8 +1161,7 @@ getPseudoAccountFields() // LCOV_EXCL_START LogicError( "xrpl::getPseudoAccountFields : unable to find account root " - "ledger " - "format"); + "ledger format"); // LCOV_EXCL_STOP } auto const& soTemplate = ar->getSOTemplate(); @@ -1342,12 +1297,58 @@ checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag) return tesSUCCESS; } +/* + * Checks if a withdrawal amount into the destination account exceeds + * any applicable receiving limit. + * Called by VaultWithdraw and LoanBrokerCoverWithdraw. + * + * IOU : Performs the trustline check against the destination account's + * credit limit to ensure the account's trust maximum is not exceeded. + * + * MPT: The limit check is effectively skipped (returns true). This is + * because MPT MaximumAmount relates to token supply, and withdrawal does not + * involve minting new tokens that could exceed the global cap. + * On withdrawal, tokens are simply transferred from the vault's pseudo-account + * to the destination account. Since no new MPT tokens are minted during this + * transfer, the withdrawal cannot violate the MPT MaximumAmount/supply cap + * even if `from` is the issuer. + */ +static TER +withdrawToDestExceedsLimit( + ReadView const& view, + AccountID const& from, + AccountID const& to, + STAmount const& amount) +{ + auto const& issuer = amount.getIssuer(); + if (from == to || to == issuer || isXRP(issuer)) + return tesSUCCESS; + + return std::visit( + [&](TIss const& issue) -> TER { + if constexpr (std::is_same_v) + { + auto const& currency = issue.currency; + auto const owed = creditBalance(view, to, issuer, currency); + if (owed <= beast::zero) + { + auto const limit = creditLimit(view, to, issuer, currency); + if (-owed >= limit || amount > (limit + owed)) + return tecNO_LINE; + } + } + return tesSUCCESS; + }, + amount.asset().value()); +} + [[nodiscard]] TER canWithdraw( - AccountID const& from, ReadView const& view, + AccountID const& from, AccountID const& to, SLE::const_ref toSle, + STAmount const& amount, bool hasDestinationTag) { if (auto const ret = checkDestinationAndTag(toSle, hasDestinationTag)) @@ -1362,19 +1363,20 @@ canWithdraw( return tecNO_PERMISSION; } - return tesSUCCESS; + return withdrawToDestExceedsLimit(view, from, to, amount); } [[nodiscard]] TER canWithdraw( - AccountID const& from, ReadView const& view, + AccountID const& from, AccountID const& to, + STAmount const& amount, bool hasDestinationTag) { auto const toSle = view.read(keylet::account(to)); - return canWithdraw(from, view, to, toSle, hasDestinationTag); + return canWithdraw(view, from, to, toSle, amount, hasDestinationTag); } [[nodiscard]] TER @@ -1383,7 +1385,8 @@ canWithdraw(ReadView const& view, STTx const& tx) auto const from = tx[sfAccount]; auto const to = tx[~sfDestination].value_or(from); - return canWithdraw(from, view, to, tx.isFieldPresent(sfDestinationTag)); + return canWithdraw( + view, from, to, tx[sfAmount], tx.isFieldPresent(sfDestinationTag)); } TER diff --git a/src/test/app/LendingHelpers_test.cpp b/src/test/app/LendingHelpers_test.cpp new file mode 100644 index 0000000000..50efe0ebe3 --- /dev/null +++ b/src/test/app/LendingHelpers_test.cpp @@ -0,0 +1,1351 @@ +#include +// DO NOT REMOVE +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace xrpl { +namespace test { + +class LendingHelpers_test : public beast::unit_test::suite +{ + void + testComputeRaisedRate() + { + using namespace jtx; + using namespace xrpl::detail; + struct TestCase + { + std::string name; + Number periodicRate; + std::uint32_t paymentsRemaining; + Number expectedRaisedRate; + }; + + auto const testCases = std::vector{ + { + .name = "Zero payments remaining", + .periodicRate = Number{5, -2}, + .paymentsRemaining = 0, + .expectedRaisedRate = Number{1}, // (1 + r)^0 = 1 + }, + { + .name = "One payment remaining", + .periodicRate = Number{5, -2}, + .paymentsRemaining = 1, + .expectedRaisedRate = Number{105, -2}, + }, // 1.05^1 + { + .name = "Multiple payments remaining", + .periodicRate = Number{5, -2}, + .paymentsRemaining = 3, + .expectedRaisedRate = Number{1157625, -6}, + }, // 1.05^3 + { + .name = "Zero periodic rate", + .periodicRate = Number{0}, + .paymentsRemaining = 5, + .expectedRaisedRate = Number{1}, // (1 + 0)^5 = 1 + }}; + + for (auto const& tc : testCases) + { + testcase("computeRaisedRate: " + tc.name); + + auto const computedRaisedRate = + computeRaisedRate(tc.periodicRate, tc.paymentsRemaining); + BEAST_EXPECTS( + computedRaisedRate == tc.expectedRaisedRate, + "Raised rate mismatch: expected " + + to_string(tc.expectedRaisedRate) + ", got " + + to_string(computedRaisedRate)); + } + } + + void + testComputePaymentFactor() + { + using namespace jtx; + using namespace xrpl::detail; + struct TestCase + { + std::string name; + Number periodicRate; + std::uint32_t paymentsRemaining; + Number expectedPaymentFactor; + }; + + auto const testCases = std::vector{ + { + .name = "Zero periodic rate", + .periodicRate = Number{0}, + .paymentsRemaining = 4, + .expectedPaymentFactor = Number{25, -2}, + }, // 1/4 = 0.25 + { + .name = "One payment remaining", + .periodicRate = Number{5, -2}, + .paymentsRemaining = 1, + .expectedPaymentFactor = Number{105, -2}, + }, // 0.05/1 = 1.05 + { + .name = "Multiple payments remaining", + .periodicRate = Number{5, -2}, + .paymentsRemaining = 3, + .expectedPaymentFactor = Number{367208564631245, -15}, + }, // from calc + { + .name = "Zero payments remaining", + .periodicRate = Number{5, -2}, + .paymentsRemaining = 0, + .expectedPaymentFactor = Number{0}, + } // edge case + }; + + for (auto const& tc : testCases) + { + testcase("computePaymentFactor: " + tc.name); + + auto const computedPaymentFactor = + computePaymentFactor(tc.periodicRate, tc.paymentsRemaining); + BEAST_EXPECTS( + computedPaymentFactor == tc.expectedPaymentFactor, + "Payment factor mismatch: expected " + + to_string(tc.expectedPaymentFactor) + ", got " + + to_string(computedPaymentFactor)); + } + } + + void + testLoanPeriodicPayment() + { + using namespace jtx; + using namespace xrpl::detail; + + struct TestCase + { + std::string name; + Number principalOutstanding; + Number periodicRate; + std::uint32_t paymentsRemaining; + Number expectedPeriodicPayment; + }; + + auto const testCases = std::vector{ + { + .name = "Zero principal outstanding", + .principalOutstanding = Number{0}, + .periodicRate = Number{5, -2}, + .paymentsRemaining = 5, + .expectedPeriodicPayment = Number{0}, + }, + { + .name = "Zero payments remaining", + .principalOutstanding = Number{1'000}, + .periodicRate = Number{5, -2}, + .paymentsRemaining = 0, + .expectedPeriodicPayment = Number{0}, + }, + { + .name = "Zero periodic rate", + .principalOutstanding = Number{1'000}, + .periodicRate = Number{0}, + .paymentsRemaining = 4, + .expectedPeriodicPayment = Number{250}, + }, + { + .name = "Standard case", + .principalOutstanding = Number{1'000}, + .periodicRate = + loanPeriodicRate(TenthBips32(100'000), 30 * 24 * 60 * 60), + .paymentsRemaining = 3, + .expectedPeriodicPayment = + Number{3895690663961231, -13}, // from calc + }, + }; + + for (auto const& tc : testCases) + { + testcase("loanPeriodicPayment: " + tc.name); + + auto const computedPeriodicPayment = loanPeriodicPayment( + tc.principalOutstanding, tc.periodicRate, tc.paymentsRemaining); + BEAST_EXPECTS( + computedPeriodicPayment == tc.expectedPeriodicPayment, + "Periodic payment mismatch: expected " + + to_string(tc.expectedPeriodicPayment) + ", got " + + to_string(computedPeriodicPayment)); + } + } + + void + testLoanPrincipalFromPeriodicPayment() + { + using namespace jtx; + using namespace xrpl::detail; + + struct TestCase + { + std::string name; + Number periodicPayment; + Number periodicRate; + std::uint32_t paymentsRemaining; + Number expectedPrincipalOutstanding; + }; + + auto const testCases = std::vector{ + { + .name = "Zero periodic payment", + .periodicPayment = Number{0}, + .periodicRate = Number{5, -2}, + .paymentsRemaining = 5, + .expectedPrincipalOutstanding = Number{0}, + }, + { + .name = "Zero payments remaining", + .periodicPayment = Number{1'000}, + .periodicRate = Number{5, -2}, + .paymentsRemaining = 0, + .expectedPrincipalOutstanding = Number{0}, + }, + { + .name = "Zero periodic rate", + .periodicPayment = Number{250}, + .periodicRate = Number{0}, + .paymentsRemaining = 4, + .expectedPrincipalOutstanding = Number{1'000}, + }, + { + .name = "Standard case", + .periodicPayment = Number{3895690663961231, -13}, // from calc + .periodicRate = + loanPeriodicRate(TenthBips32(100'000), 30 * 24 * 60 * 60), + .paymentsRemaining = 3, + .expectedPrincipalOutstanding = Number{1'000}, + }, + }; + + for (auto const& tc : testCases) + { + testcase("loanPrincipalFromPeriodicPayment: " + tc.name); + + auto const computedPrincipalOutstanding = + loanPrincipalFromPeriodicPayment( + tc.periodicPayment, tc.periodicRate, tc.paymentsRemaining); + BEAST_EXPECTS( + computedPrincipalOutstanding == tc.expectedPrincipalOutstanding, + "Principal outstanding mismatch: expected " + + to_string(tc.expectedPrincipalOutstanding) + ", got " + + to_string(computedPrincipalOutstanding)); + } + } + + void + testComputeOverpaymentComponents() + { + testcase("computeOverpaymentComponents"); + using namespace jtx; + using namespace xrpl::detail; + + Account const issuer{"issuer"}; + PrettyAsset const IOU = issuer["IOU"]; + int32_t const loanScale = 1; + auto const overpayment = Number{1'000}; + auto const overpaymentInterestRate = TenthBips32{10'000}; // 10% + auto const overpaymentFeeRate = TenthBips32{50'000}; // 50% + auto const managementFeeRate = TenthBips16{10'000}; // 10% + + auto const expectedOverpaymentFee = Number{500}; // 50% of 1,000 + auto const expectedOverpaymentInterestGross = + Number{100}; // 10% of 1,000 + auto const expectedOverpaymentInterestNet = + Number{90}; // 100 - 10% of 100 + auto const expectedOverpaymentManagementFee = Number{10}; // 10% of 100 + auto const expectedPrincipalPortion = Number{400}; // 1,000 - 100 - 500 + + auto const components = detail::computeOverpaymentComponents( + IOU, + loanScale, + overpayment, + overpaymentInterestRate, + overpaymentFeeRate, + managementFeeRate); + + BEAST_EXPECT( + components.untrackedManagementFee == expectedOverpaymentFee); + + BEAST_EXPECT( + components.untrackedInterest == expectedOverpaymentInterestNet); + + BEAST_EXPECT( + components.trackedInterestPart() == expectedOverpaymentInterestNet); + + BEAST_EXPECT( + components.trackedManagementFeeDelta == + expectedOverpaymentManagementFee); + BEAST_EXPECT( + components.trackedPrincipalDelta == expectedPrincipalPortion); + BEAST_EXPECT( + components.trackedManagementFeeDelta + + components.untrackedInterest == + expectedOverpaymentInterestGross); + + BEAST_EXPECT( + components.trackedManagementFeeDelta + + components.untrackedInterest + + components.trackedPrincipalDelta + + components.untrackedManagementFee == + overpayment); + } + + void + testComputeInterestAndFeeParts() + { + using namespace jtx; + using namespace xrpl::detail; + + struct TestCase + { + std::string name; + Number interest; + TenthBips16 managementFeeRate; + Number expectedInterestPart; + Number expectedFeePart; + }; + + Account const issuer{"issuer"}; + PrettyAsset const IOU = issuer["IOU"]; + std::int32_t const loanScale = 1; + + auto const testCases = std::vector{ + {.name = "Zero interest", + .interest = Number{0}, + .managementFeeRate = TenthBips16{10'000}, + .expectedInterestPart = Number{0}, + .expectedFeePart = Number{0}}, + {.name = "Zero fee rate", + .interest = Number{1'000}, + .managementFeeRate = TenthBips16{0}, + .expectedInterestPart = Number{1'000}, + .expectedFeePart = Number{0}}, + {.name = "10% fee rate", + .interest = Number{1'000}, + .managementFeeRate = TenthBips16{10'000}, + .expectedInterestPart = Number{900}, + .expectedFeePart = Number{100}}, + }; + + for (auto const& tc : testCases) + { + testcase("computeInterestAndFeeParts: " + tc.name); + + auto const [computedInterestPart, computedFeePart] = + computeInterestAndFeeParts( + IOU, tc.interest, tc.managementFeeRate, loanScale); + BEAST_EXPECTS( + computedInterestPart == tc.expectedInterestPart, + "Interest part mismatch: expected " + + to_string(tc.expectedInterestPart) + ", got " + + to_string(computedInterestPart)); + BEAST_EXPECTS( + computedFeePart == tc.expectedFeePart, + "Fee part mismatch: expected " + to_string(tc.expectedFeePart) + + ", got " + to_string(computedFeePart)); + } + } + + void + testLoanLatePaymentInterest() + { + using namespace jtx; + using namespace xrpl::detail; + struct TestCase + { + std::string name; + Number principalOutstanding; + TenthBips32 lateInterestRate; + NetClock::time_point parentCloseTime; + std::uint32_t nextPaymentDueDate; + Number expectedLateInterest; + }; + + auto const testCases = std::vector{ + { + .name = "On-time payment", + .principalOutstanding = Number{1'000}, + .lateInterestRate = TenthBips32{10'000}, // 10% + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .nextPaymentDueDate = 3'000, + .expectedLateInterest = Number{0}, + }, + { + .name = "Early payment", + .principalOutstanding = Number{1'000}, + .lateInterestRate = TenthBips32{10'000}, // 10% + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .nextPaymentDueDate = 4'000, + .expectedLateInterest = Number{0}, + }, + { + .name = "No principal outstanding", + .principalOutstanding = Number{0}, + .lateInterestRate = TenthBips32{10'000}, // 10% + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .nextPaymentDueDate = 2'000, + .expectedLateInterest = Number{0}, + }, + { + .name = "No late interest rate", + .principalOutstanding = Number{1'000}, + .lateInterestRate = TenthBips32{0}, // 0% + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .nextPaymentDueDate = 2'000, + .expectedLateInterest = Number{0}, + }, + { + .name = "Late payment", + .principalOutstanding = Number{1'000}, + .lateInterestRate = TenthBips32{100'000}, // 100% + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .nextPaymentDueDate = 2'000, + .expectedLateInterest = + Number{3170979198376459, -17}, // from calc + }, + }; + + for (auto const& tc : testCases) + { + testcase("loanLatePaymentInterest: " + tc.name); + + auto const computedLateInterest = loanLatePaymentInterest( + tc.principalOutstanding, + tc.lateInterestRate, + tc.parentCloseTime, + tc.nextPaymentDueDate); + BEAST_EXPECTS( + computedLateInterest == tc.expectedLateInterest, + "Late interest mismatch: expected " + + to_string(tc.expectedLateInterest) + ", got " + + to_string(computedLateInterest)); + } + } + + void + testLoanAccruedInterest() + { + using namespace jtx; + using namespace xrpl::detail; + struct TestCase + { + std::string name; + Number principalOutstanding; + Number periodicRate; + NetClock::time_point parentCloseTime; + std::uint32_t startDate; + std::uint32_t prevPaymentDate; + std::uint32_t paymentInterval; + Number expectedAccruedInterest; + }; + + auto const testCases = std::vector{ + { + .name = "Zero principal outstanding", + .principalOutstanding = Number{0}, + .periodicRate = Number{5, -2}, + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .startDate = 2'000, + .prevPaymentDate = 2'500, + .paymentInterval = 30 * 24 * 60 * 60, + .expectedAccruedInterest = Number{0}, + }, + { + .name = "Before start date", + .principalOutstanding = Number{1'000}, + .periodicRate = Number{5, -2}, + .parentCloseTime = + NetClock::time_point{NetClock::duration{1'000}}, + .startDate = 2'000, + .prevPaymentDate = 1'500, + .paymentInterval = 30 * 24 * 60 * 60, + .expectedAccruedInterest = Number{0}, + }, + { + .name = "Zero periodic rate", + .principalOutstanding = Number{1'000}, + .periodicRate = Number{0}, + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .startDate = 2'000, + .prevPaymentDate = 2'500, + .paymentInterval = 30 * 24 * 60 * 60, + .expectedAccruedInterest = Number{0}, + }, + { + .name = "Zero payment interval", + .principalOutstanding = Number{1'000}, + .periodicRate = Number{5, -2}, + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .startDate = 2'000, + .prevPaymentDate = 2'500, + .paymentInterval = 0, + .expectedAccruedInterest = Number{0}, + }, + { + .name = "Standard case", + .principalOutstanding = Number{1'000}, + .periodicRate = Number{5, -2}, + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .startDate = 1'000, + .prevPaymentDate = 2'000, + .paymentInterval = 30 * 24 * 60 * 60, + .expectedAccruedInterest = + Number{1929012345679012, -17}, // from calc + }, + }; + + for (auto const& tc : testCases) + { + testcase("loanAccruedInterest: " + tc.name); + + auto const computedAccruedInterest = loanAccruedInterest( + tc.principalOutstanding, + tc.periodicRate, + tc.parentCloseTime, + tc.startDate, + tc.prevPaymentDate, + tc.paymentInterval); + BEAST_EXPECTS( + computedAccruedInterest == tc.expectedAccruedInterest, + "Accrued interest mismatch: expected " + + to_string(tc.expectedAccruedInterest) + ", got " + + to_string(computedAccruedInterest)); + } + } + + // This test overlaps with testLoanAccruedInterest, the test cases only + // exercise the computeFullPaymentInterest parts unique to it. + void + testComputeFullPaymentInterest() + { + using namespace jtx; + using namespace xrpl::detail; + + struct TestCase + { + std::string name; + Number rawPrincipalOutstanding; + Number periodicRate; + NetClock::time_point parentCloseTime; + std::uint32_t paymentInterval; + std::uint32_t prevPaymentDate; + std::uint32_t startDate; + TenthBips32 closeInterestRate; + Number expectedFullPaymentInterest; + }; + + auto const testCases = std::vector{ + { + .name = "Zero principal outstanding", + .rawPrincipalOutstanding = Number{0}, + .periodicRate = Number{5, -2}, + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .paymentInterval = 30 * 24 * 60 * 60, + .prevPaymentDate = 2'000, + .startDate = 1'000, + .closeInterestRate = TenthBips32{10'000}, + .expectedFullPaymentInterest = Number{0}, + }, + { + .name = "Zero close interest rate", + .rawPrincipalOutstanding = Number{1'000}, + .periodicRate = Number{5, -2}, + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .paymentInterval = 30 * 24 * 60 * 60, + .prevPaymentDate = 2'000, + .startDate = 1'000, + .closeInterestRate = TenthBips32{0}, + .expectedFullPaymentInterest = + Number{1929012345679012, -17}, // from calc + }, + { + .name = "Standard case", + .rawPrincipalOutstanding = Number{1'000}, + .periodicRate = Number{5, -2}, + .parentCloseTime = + NetClock::time_point{NetClock::duration{3'000}}, + .paymentInterval = 30 * 24 * 60 * 60, + .prevPaymentDate = 2'000, + .startDate = 1'000, + .closeInterestRate = TenthBips32{10'000}, + .expectedFullPaymentInterest = + Number{1000192901234568, -13}, // from calc + }, + }; + + for (auto const& tc : testCases) + { + testcase("computeFullPaymentInterest: " + tc.name); + + auto const computedFullPaymentInterest = computeFullPaymentInterest( + tc.rawPrincipalOutstanding, + tc.periodicRate, + tc.parentCloseTime, + tc.paymentInterval, + tc.prevPaymentDate, + tc.startDate, + tc.closeInterestRate); + BEAST_EXPECTS( + computedFullPaymentInterest == tc.expectedFullPaymentInterest, + "Full payment interest mismatch: expected " + + to_string(tc.expectedFullPaymentInterest) + ", got " + + to_string(computedFullPaymentInterest)); + } + } + + void + testTryOverpaymentNoInterestNoFee() + { + // This test ensures that overpayment with no interest works correctly. + testcase("tryOverpayment - No Interest No Fee"); + + using namespace jtx; + using namespace xrpl::detail; + + Env env{*this}; + Account const issuer{"issuer"}; + PrettyAsset const asset = issuer["USD"]; + std::int32_t const loanScale = -5; + TenthBips16 const managementFeeRate{0}; // 0% + TenthBips32 const loanInterestRate{0}; // 0% + Number const loanPrincipal{1'000}; + std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; + std::uint32_t const paymentsRemaining = 10; + auto const periodicRate = + loanPeriodicRate(loanInterestRate, paymentInterval); + Number const overpaymentAmount{50}; + + ExtendedPaymentComponents const overpaymentComponents = + computeOverpaymentComponents( + asset, + loanScale, + overpaymentAmount, + TenthBips32(0), + TenthBips32(0), + managementFeeRate); + + auto const loanProperites = computeLoanProperties( + asset, + loanPrincipal, + loanInterestRate, + paymentInterval, + paymentsRemaining, + managementFeeRate, + loanScale); + + Number const periodicPayment = loanProperites.periodicPayment; + + auto const ret = tryOverpayment( + asset, + loanScale, + overpaymentComponents, + loanProperites.loanState, + periodicPayment, + periodicRate, + paymentsRemaining, + managementFeeRate, + env.journal); + + BEAST_EXPECT(ret); + + auto const& [actualPaymentParts, newLoanProperties] = *ret; + auto const& newState = newLoanProperties.loanState; + + // =========== VALIDATE PAYMENT PARTS =========== + BEAST_EXPECTS( + actualPaymentParts.valueChange == 0, + " valueChange mismatch: expected 0, got " + + to_string(actualPaymentParts.valueChange)); + + BEAST_EXPECTS( + actualPaymentParts.feePaid == 0, + " feePaid mismatch: expected 0, got " + + to_string(actualPaymentParts.feePaid)); + + BEAST_EXPECTS( + actualPaymentParts.interestPaid == 0, + " interestPaid mismatch: expected 0, got " + + to_string(actualPaymentParts.interestPaid)); + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == overpaymentAmount, + " principalPaid mismatch: expected " + + to_string(overpaymentAmount) + ", got " + + to_string(actualPaymentParts.principalPaid)); + + // =========== VALIDATE STATE CHANGES =========== + BEAST_EXPECTS( + loanProperites.loanState.interestDue - newState.interestDue == 0, + " interest change mismatch: expected 0, got " + + to_string( + loanProperites.loanState.interestDue - + newState.interestDue)); + + BEAST_EXPECTS( + loanProperites.loanState.managementFeeDue - + newState.managementFeeDue == + 0, + " management fee change mismatch: expected 0, got " + + to_string( + loanProperites.loanState.managementFeeDue - + newState.managementFeeDue)); + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding, + " principalPaid mismatch: expected " + + to_string( + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding) + + ", got " + to_string(actualPaymentParts.principalPaid)); + } + + void + testTryOverpaymentNoInterestOverpaymentFee() + { + testcase("tryOverpayment - No Interest With Overpayment Fee"); + + using namespace jtx; + using namespace xrpl::detail; + + Env env{*this}; + Account const issuer{"issuer"}; + PrettyAsset const asset = issuer["USD"]; + std::int32_t const loanScale = -5; + TenthBips16 const managementFeeRate{0}; // 0% + TenthBips32 const loanInterestRate{0}; // 0% + Number const loanPrincipal{1'000}; + std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; + std::uint32_t const paymentsRemaining = 10; + auto const periodicRate = + loanPeriodicRate(loanInterestRate, paymentInterval); + + ExtendedPaymentComponents const overpaymentComponents = + computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(0), + TenthBips32(10'000), // 10% overpayment fee + managementFeeRate); + + auto const loanProperites = computeLoanProperties( + asset, + loanPrincipal, + loanInterestRate, + paymentInterval, + paymentsRemaining, + managementFeeRate, + loanScale); + + Number const periodicPayment = loanProperites.periodicPayment; + + auto const ret = tryOverpayment( + asset, + loanScale, + overpaymentComponents, + loanProperites.loanState, + periodicPayment, + periodicRate, + paymentsRemaining, + managementFeeRate, + env.journal); + + BEAST_EXPECT(ret); + + auto const& [actualPaymentParts, newLoanProperties] = *ret; + auto const& newState = newLoanProperties.loanState; + + // =========== VALIDATE PAYMENT PARTS =========== + BEAST_EXPECTS( + actualPaymentParts.valueChange == 0, + " valueChange mismatch: expected 0, got " + + to_string(actualPaymentParts.valueChange)); + + BEAST_EXPECTS( + actualPaymentParts.feePaid == 5, + " feePaid mismatch: expected 5, got " + + to_string(actualPaymentParts.feePaid)); + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == 45, + " principalPaid mismatch: expected 45, got `" + + to_string(actualPaymentParts.principalPaid)); + + BEAST_EXPECTS( + actualPaymentParts.interestPaid == 0, + " interestPaid mismatch: expected 0, got " + + to_string(actualPaymentParts.interestPaid)); + + // =========== VALIDATE STATE CHANGES =========== + // With no Loan interest, interest outstanding should not change + BEAST_EXPECTS( + loanProperites.loanState.interestDue - newState.interestDue == 0, + " interest change mismatch: expected 0, got " + + to_string( + loanProperites.loanState.interestDue - + newState.interestDue)); + + // With no Loan management fee, management fee due should not change + BEAST_EXPECTS( + loanProperites.loanState.managementFeeDue - + newState.managementFeeDue == + 0, + " management fee change mismatch: expected 0, got " + + to_string( + loanProperites.loanState.managementFeeDue - + newState.managementFeeDue)); + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding, + " principalPaid mismatch: expected " + + to_string( + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding) + + ", got " + to_string(actualPaymentParts.principalPaid)); + } + + void + testTryOverpaymentLoanInterestNoOverpaymentFees() + { + testcase("tryOverpayment - Loan Interest, No Overpayment Fees"); + + using namespace jtx; + using namespace xrpl::detail; + + Env env{*this}; + Account const issuer{"issuer"}; + PrettyAsset const asset = issuer["USD"]; + std::int32_t const loanScale = -5; + TenthBips16 const managementFeeRate{0}; // 0% + TenthBips32 const loanInterestRate{10'000}; // 10% + Number const loanPrincipal{1'000}; + std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; + std::uint32_t const paymentsRemaining = 10; + auto const periodicRate = + loanPeriodicRate(loanInterestRate, paymentInterval); + + ExtendedPaymentComponents const overpaymentComponents = + computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(0), // no overpayment interest + TenthBips32(0), // 0% overpayment fee + managementFeeRate); + + auto const loanProperites = computeLoanProperties( + asset, + loanPrincipal, + loanInterestRate, + paymentInterval, + paymentsRemaining, + managementFeeRate, + loanScale); + + Number const periodicPayment = loanProperites.periodicPayment; + + auto const ret = tryOverpayment( + asset, + loanScale, + overpaymentComponents, + loanProperites.loanState, + periodicPayment, + periodicRate, + paymentsRemaining, + managementFeeRate, + env.journal); + + BEAST_EXPECT(ret); + + auto const& [actualPaymentParts, newLoanProperties] = *ret; + auto const& newState = newLoanProperties.loanState; + + // =========== VALIDATE PAYMENT PARTS =========== + // with no overpayment interest portion, value change should equal + // interest decrease + BEAST_EXPECTS( + (actualPaymentParts.valueChange == Number{-228802, -5}), + " valueChange mismatch: expected " + + to_string(Number{-228802, -5}) + ", got " + + to_string(actualPaymentParts.valueChange)); + + // with no fee portion, fee paid should be zero + BEAST_EXPECTS( + actualPaymentParts.feePaid == 0, + " feePaid mismatch: expected 0, got " + + to_string(actualPaymentParts.feePaid)); + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == 50, + " principalPaid mismatch: expected 50, got `" + + to_string(actualPaymentParts.principalPaid)); + + // with no interest portion, interest paid should be zero + BEAST_EXPECTS( + actualPaymentParts.interestPaid == 0, + " interestPaid mismatch: expected 0, got " + + to_string(actualPaymentParts.interestPaid)); + + // =========== VALIDATE STATE CHANGES =========== + BEAST_EXPECTS( + actualPaymentParts.principalPaid == + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding, + " principalPaid mismatch: expected " + + to_string( + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding) + + ", got " + to_string(actualPaymentParts.principalPaid)); + + BEAST_EXPECTS( + actualPaymentParts.valueChange == + newState.interestDue - loanProperites.loanState.interestDue, + " valueChange mismatch: expected " + + to_string( + newState.interestDue - + loanProperites.loanState.interestDue) + + ", got " + to_string(actualPaymentParts.valueChange)); + + // With no Loan management fee, management fee due should not change + BEAST_EXPECTS( + loanProperites.loanState.managementFeeDue - + newState.managementFeeDue == + 0, + " management fee change mismatch: expected 0, got " + + to_string( + loanProperites.loanState.managementFeeDue - + newState.managementFeeDue)); + } + + void + testTryOverpaymentLoanInterestOverpaymentInterest() + { + testcase( + "tryOverpayment - Loan Interest, Overpayment Interest, No Fee"); + + using namespace jtx; + using namespace xrpl::detail; + + Env env{*this}; + Account const issuer{"issuer"}; + PrettyAsset const asset = issuer["USD"]; + std::int32_t const loanScale = -5; + TenthBips16 const managementFeeRate{0}; // 0% + TenthBips32 const loanInterestRate{10'000}; // 10% + Number const loanPrincipal{1'000}; + std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; + std::uint32_t const paymentsRemaining = 10; + auto const periodicRate = + loanPeriodicRate(loanInterestRate, paymentInterval); + + ExtendedPaymentComponents const overpaymentComponents = + computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(10'000), // 10% overpayment interest + TenthBips32(0), // 0% overpayment fee + managementFeeRate); + + auto const loanProperites = computeLoanProperties( + asset, + loanPrincipal, + loanInterestRate, + paymentInterval, + paymentsRemaining, + managementFeeRate, + loanScale); + + Number const periodicPayment = loanProperites.periodicPayment; + + auto const ret = tryOverpayment( + asset, + loanScale, + overpaymentComponents, + loanProperites.loanState, + periodicPayment, + periodicRate, + paymentsRemaining, + managementFeeRate, + env.journal); + + BEAST_EXPECT(ret); + + auto const& [actualPaymentParts, newLoanProperties] = *ret; + auto const& newState = newLoanProperties.loanState; + + // =========== VALIDATE PAYMENT PARTS =========== + // with overpayment interest portion, interest paid should be 5 + BEAST_EXPECTS( + actualPaymentParts.interestPaid == 5, + " interestPaid mismatch: expected 5, got " + + to_string(actualPaymentParts.interestPaid)); + + // With overpayment interest portion, value change should equal the + // interest decrease plus overpayment interest portion + BEAST_EXPECTS( + (actualPaymentParts.valueChange == + Number{-205922, -5} + actualPaymentParts.interestPaid), + " valueChange mismatch: expected " + + to_string( + actualPaymentParts.valueChange - + actualPaymentParts.interestPaid) + + ", got " + to_string(actualPaymentParts.valueChange)); + + // with no fee portion, fee paid should be zero + BEAST_EXPECTS( + actualPaymentParts.feePaid == 0, + " feePaid mismatch: expected 0, got " + + to_string(actualPaymentParts.feePaid)); + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == 45, + " principalPaid mismatch: expected 45, got `" + + to_string(actualPaymentParts.principalPaid)); + + // =========== VALIDATE STATE CHANGES =========== + BEAST_EXPECTS( + actualPaymentParts.principalPaid == + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding, + " principalPaid mismatch: expected " + + to_string( + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding) + + ", got " + to_string(actualPaymentParts.principalPaid)); + + // The change in interest is equal to the value change sans the + // overpayment interest + BEAST_EXPECTS( + actualPaymentParts.valueChange - actualPaymentParts.interestPaid == + newState.interestDue - loanProperites.loanState.interestDue, + " valueChange mismatch: expected " + + to_string( + newState.interestDue - + loanProperites.loanState.interestDue + + actualPaymentParts.interestPaid) + + ", got " + to_string(actualPaymentParts.valueChange)); + + // With no Loan management fee, management fee due should not change + BEAST_EXPECTS( + loanProperites.loanState.managementFeeDue - + newState.managementFeeDue == + 0, + " management fee change mismatch: expected 0, got " + + to_string( + loanProperites.loanState.managementFeeDue - + newState.managementFeeDue)); + } + + void + testTryOverpaymentLoanInterestFeeOverpaymentInterestNoFee() + { + testcase( + "tryOverpayment - Loan Interest and Fee, Overpayment Interest, No " + "Fee"); + + using namespace jtx; + using namespace xrpl::detail; + + Env env{*this}; + Account const issuer{"issuer"}; + PrettyAsset const asset = issuer["USD"]; + std::int32_t const loanScale = -5; + TenthBips16 const managementFeeRate{10'000}; // 10% + TenthBips32 const loanInterestRate{10'000}; // 10% + Number const loanPrincipal{1'000}; + std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; + std::uint32_t const paymentsRemaining = 10; + auto const periodicRate = + loanPeriodicRate(loanInterestRate, paymentInterval); + + ExtendedPaymentComponents const overpaymentComponents = + computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(10'000), // 10% overpayment interest + TenthBips32(0), // 0% overpayment fee + managementFeeRate); + + auto const loanProperites = computeLoanProperties( + asset, + loanPrincipal, + loanInterestRate, + paymentInterval, + paymentsRemaining, + managementFeeRate, + loanScale); + + Number const periodicPayment = loanProperites.periodicPayment; + + auto const ret = tryOverpayment( + asset, + loanScale, + overpaymentComponents, + loanProperites.loanState, + periodicPayment, + periodicRate, + paymentsRemaining, + managementFeeRate, + env.journal); + + BEAST_EXPECT(ret); + + auto const& [actualPaymentParts, newLoanProperties] = *ret; + auto const& newState = newLoanProperties.loanState; + + // =========== VALIDATE PAYMENT PARTS =========== + + // Since there is loan management fee, the fee is charged against + // overpayment interest portion first, so interest paid remains 4.5 + BEAST_EXPECTS( + (actualPaymentParts.interestPaid == Number{45, -1}), + " interestPaid mismatch: expected 4.5, got " + + to_string(actualPaymentParts.interestPaid)); + + // With overpayment interest portion, value change should equal the + // interest decrease plus overpayment interest portion + BEAST_EXPECTS( + (actualPaymentParts.valueChange == + Number{-18533, -4} + actualPaymentParts.interestPaid), + " valueChange mismatch: expected " + + to_string( + Number{-18533, -4} + actualPaymentParts.interestPaid) + + ", got " + to_string(actualPaymentParts.valueChange)); + + // While there is no overpayment fee, fee paid should equal the + // management fee charged against the overpayment interest portion + BEAST_EXPECTS( + (actualPaymentParts.feePaid == Number{5, -1}), + " feePaid mismatch: expected 0.5, got " + + to_string(actualPaymentParts.feePaid)); + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == 45, + " principalPaid mismatch: expected 45, got `" + + to_string(actualPaymentParts.principalPaid)); + + // =========== VALIDATE STATE CHANGES =========== + BEAST_EXPECTS( + actualPaymentParts.principalPaid == + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding, + " principalPaid mismatch: expected " + + to_string( + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding) + + ", got " + to_string(actualPaymentParts.principalPaid)); + + // Note that the management fee value change is not captured, as this + // value is not needed to correctly update the Vault state. + BEAST_EXPECTS( + (newState.managementFeeDue - + loanProperites.loanState.managementFeeDue == + Number{-20592, -5}), + " management fee change mismatch: expected " + + to_string(Number{-20592, -5}) + ", got " + + to_string( + newState.managementFeeDue - + loanProperites.loanState.managementFeeDue)); + + BEAST_EXPECTS( + actualPaymentParts.valueChange - actualPaymentParts.interestPaid == + newState.interestDue - loanProperites.loanState.interestDue, + " valueChange mismatch: expected " + + to_string( + newState.interestDue - + loanProperites.loanState.interestDue) + + ", got " + + to_string( + actualPaymentParts.valueChange - + actualPaymentParts.interestPaid)); + } + + void + testTryOverpaymentLoanInterestFeeOverpaymentInterestFee() + { + testcase( + "tryOverpayment - Loan Interest, Fee, Overpayment Interest, Fee"); + + using namespace jtx; + using namespace xrpl::detail; + + Env env{*this}; + Account const issuer{"issuer"}; + PrettyAsset const asset = issuer["USD"]; + std::int32_t const loanScale = -5; + TenthBips16 const managementFeeRate{10'000}; // 10% + TenthBips32 const loanInterestRate{10'000}; // 10% + Number const loanPrincipal{1'000}; + std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; + std::uint32_t const paymentsRemaining = 10; + auto const periodicRate = + loanPeriodicRate(loanInterestRate, paymentInterval); + + ExtendedPaymentComponents const overpaymentComponents = + computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(10'000), // 10% overpayment interest + TenthBips32(10'000), // 10% overpayment fee + managementFeeRate); + + auto const loanProperites = computeLoanProperties( + asset, + loanPrincipal, + loanInterestRate, + paymentInterval, + paymentsRemaining, + managementFeeRate, + loanScale); + + Number const periodicPayment = loanProperites.periodicPayment; + + auto const ret = tryOverpayment( + asset, + loanScale, + overpaymentComponents, + loanProperites.loanState, + periodicPayment, + periodicRate, + paymentsRemaining, + managementFeeRate, + env.journal); + + BEAST_EXPECT(ret); + + auto const& [actualPaymentParts, newLoanProperties] = *ret; + auto const& newState = newLoanProperties.loanState; + + // =========== VALIDATE PAYMENT PARTS =========== + + // Since there is loan management fee, the fee is charged against + // overpayment interest portion first, so interest paid remains 4.5 + BEAST_EXPECTS( + (actualPaymentParts.interestPaid == Number{45, -1}), + " interestPaid mismatch: expected 4.5, got " + + to_string(actualPaymentParts.interestPaid)); + + // With overpayment interest portion, value change should equal the + // interest decrease plus overpayment interest portion + BEAST_EXPECTS( + (actualPaymentParts.valueChange == + Number{-164737, -5} + actualPaymentParts.interestPaid), + " valueChange mismatch: expected " + + to_string( + Number{-164737, -5} + actualPaymentParts.interestPaid) + + ", got " + to_string(actualPaymentParts.valueChange)); + + // While there is no overpayment fee, fee paid should equal the + // management fee charged against the overpayment interest portion + BEAST_EXPECTS( + (actualPaymentParts.feePaid == Number{55, -1}), + " feePaid mismatch: expected 5.5, got " + + to_string(actualPaymentParts.feePaid)); + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == 40, + " principalPaid mismatch: expected 40, got `" + + to_string(actualPaymentParts.principalPaid)); + + // =========== VALIDATE STATE CHANGES =========== + + BEAST_EXPECTS( + actualPaymentParts.principalPaid == + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding, + " principalPaid mismatch: expected " + + to_string( + loanProperites.loanState.principalOutstanding - + newState.principalOutstanding) + + ", got " + to_string(actualPaymentParts.principalPaid)); + + // Note that the management fee value change is not captured, as this + // value is not needed to correctly update the Vault state. + BEAST_EXPECTS( + (newState.managementFeeDue - + loanProperites.loanState.managementFeeDue == + Number{-18304, -5}), + " management fee change mismatch: expected " + + to_string(Number{-18304, -5}) + ", got " + + to_string( + newState.managementFeeDue - + loanProperites.loanState.managementFeeDue)); + + BEAST_EXPECTS( + actualPaymentParts.valueChange - actualPaymentParts.interestPaid == + newState.interestDue - loanProperites.loanState.interestDue, + " valueChange mismatch: expected " + + to_string( + newState.interestDue - + loanProperites.loanState.interestDue) + + ", got " + + to_string( + actualPaymentParts.valueChange - + actualPaymentParts.interestPaid)); + } + +public: + void + run() override + { + testTryOverpaymentNoInterestNoFee(); + testTryOverpaymentNoInterestOverpaymentFee(); + testTryOverpaymentLoanInterestNoOverpaymentFees(); + testTryOverpaymentLoanInterestOverpaymentInterest(); + testTryOverpaymentLoanInterestFeeOverpaymentInterestNoFee(); + testTryOverpaymentLoanInterestFeeOverpaymentInterestFee(); + + testComputeFullPaymentInterest(); + testLoanAccruedInterest(); + testLoanLatePaymentInterest(); + testLoanPeriodicPayment(); + testLoanPrincipalFromPeriodicPayment(); + testComputeRaisedRate(); + testComputePaymentFactor(); + testComputeOverpaymentComponents(); + testComputeInterestAndFeeParts(); + } +}; + +BEAST_DEFINE_TESTSUITE(LendingHelpers, app, xrpl); + +} // namespace test +} // namespace xrpl diff --git a/src/test/app/LoanBroker_test.cpp b/src/test/app/LoanBroker_test.cpp index 5915ebae91..93be28e9e9 100644 --- a/src/test/app/LoanBroker_test.cpp +++ b/src/test/app/LoanBroker_test.cpp @@ -1024,6 +1024,12 @@ class LoanBroker_test : public beast::unit_test::suite destination(dest), ter(tecFROZEN), THISLINE); + + // preclaim: tecPSEUDO_ACCOUNT + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), + destination(vaultInfo.pseudoAccount), + ter(tecPSEUDO_ACCOUNT), + THISLINE); } if (brokerTest == CoverClawback) @@ -1436,10 +1442,467 @@ class LoanBroker_test : public beast::unit_test::suite }); } + void + testLoanBrokerSetDebtMaximum() + { + testcase("testLoanBrokerSetDebtMaximum"); + using namespace jtx; + using namespace loanBroker; + Account const issuer{"issuer"}; + Account const alice{"alice"}; + Env env(*this); + Vault vault{env}; + + env.fund(XRP(100'000), issuer, alice); + env.close(); + + PrettyAsset const asset = [&]() { + env(trust(alice, issuer["IOU"](1'000'000)), THISLINE); + env.close(); + return PrettyAsset(issuer["IOU"]); + }(); + + env(pay(issuer, alice, asset(100'000)), THISLINE); + env.close(); + + auto [tx, vaultKeylet] = vault.create({.owner = alice, .asset = asset}); + env(tx, THISLINE); + env.close(); + auto const le = env.le(vaultKeylet); + VaultInfo vaultInfo = [&]() { + if (BEAST_EXPECT(le)) + return VaultInfo{asset, vaultKeylet.key, le->at(sfAccount)}; + return VaultInfo{asset, {}, {}}; + }(); + if (vaultInfo.vaultID == uint256{}) + return; + + env(vault.deposit( + {.depositor = alice, + .id = vaultKeylet.key, + .amount = asset(50)}), + THISLINE); + env.close(); + + auto const brokerKeylet = + keylet::loanbroker(alice.id(), env.seq(alice)); + env(set(alice, vaultInfo.vaultID), THISLINE); + env.close(); + + Account const borrower{"borrower"}; + env.fund(XRP(1'000), borrower); + env(loan::set(borrower, brokerKeylet.key, asset(50).value()), + sig(sfCounterpartySignature, alice), + fee(env.current()->fees().base * 2), + THISLINE); + auto const broker = env.le(brokerKeylet); + if (!BEAST_EXPECT(broker)) + return; + + BEAST_EXPECT(broker->at(sfDebtTotal) == 50); + auto debtTotal = broker->at(sfDebtTotal); + + auto tx2 = set(alice, vaultInfo.vaultID); + tx2[sfLoanBrokerID] = to_string(brokerKeylet.key); + tx2[sfDebtMaximum] = debtTotal - 1; + env(tx2, ter(tecLIMIT_EXCEEDED), THISLINE); + + tx2[sfDebtMaximum] = debtTotal + 1; + env(tx2, ter(tesSUCCESS), THISLINE); + + tx2[sfDebtMaximum] = 0; + env(tx2, ter(tesSUCCESS), THISLINE); + } + + void + testRIPD4323() + { + testcase << "RIPD-4323"; + using namespace jtx; + Account const issuer("issuer"); + Account const holder("holder"); + Account const& broker = issuer; + + auto test = [&](auto&& getToken) { + Env env(*this); + + env.fund(XRP(1'000), issuer, holder); + env.close(); + + auto const [token, deposit, err] = getToken(env); + + Vault vault(env); + auto const [tx, keylet] = + vault.create({.owner = broker, .asset = token.asset()}); + env(tx); + env.close(); + + env(vault.deposit( + {.depositor = broker, .id = keylet.key, .amount = deposit}), + ter(err)); + env.close(); + + auto const brokerKeylet = + keylet::loanbroker(broker, env.seq(broker)); + + env(loanBroker::set(broker, keylet.key)); + env.close(); + + env(loanBroker::coverDeposit(broker, brokerKeylet.key, deposit), + ter(err)); + env.close(); + }; + + test([&](Env&) { + // issuer can issue any amount + auto const token = issuer["IOU"]; + return std::make_tuple(token, token(1'000), tesSUCCESS); + }); + std::vector, // max amount + std::uint64_t, // deposit amount + TER>> // expected error + mptTests = { + // issuer can issue up to 2'000 tokens + {2'000, 4'000, 1'000, tesSUCCESS}, + // issuer can issue 500 tokens (250 VaultDeposit + + // 250 LoanBrokerCoverDeposit) + {2'000, 2'500, 250, tesSUCCESS}, + // issuer can issue 500 tokens (250 VaultDeposit + + // 250 LoanBrokerCoverDeposit). MaximumAmount is default. + {maxMPTokenAmount - 500, std::nullopt, 250, tesSUCCESS}, + // issuer can issue 500, and fails on depositing 1'000 + {2'000, 2'500, 1'000, tecINSUFFICIENT_FUNDS}, + // issuer has already issued MaximumAmount + {2'000, 2'000, 1'000, tecINSUFFICIENT_FUNDS}, + // issuer has already issued MaximumAmount. MaximumAmount is + // default. + {maxMPTokenAmount, std::nullopt, 250, tecINSUFFICIENT_FUNDS}, + }; + for (auto const& [pay, max, deposit, err] : mptTests) + { + test([&](Env& env) -> std::tuple { + MPT const token = MPTTester( + {.env = env, + .issuer = issuer, + .holders = {holder}, + .pay = pay, + .flags = MPTDEXFlags, + .maxAmt = max}); + return std::make_tuple(token, token(deposit), err); + }); + } + } + + void + testAMB06_VaultFreezeCheckMissing() + { + testcase << "RIPD-4466 - LoanBrokerSet disallows frozen vaults"; + using namespace jtx; + Env env(*this); + + Account const issuer{"issuer"}, lender{"lender"}, borrower{"borrower"}; + env.fund(XRP(20'000), issuer, lender, borrower); + auto const IOU = issuer["IOU"]; + + Vault vault{env}; + auto [tx, vaultKeylet] = + vault.create({.owner = lender, .asset = IOU.asset()}); + env(tx); + env.close(); + + // Get vault pseudo-account and FREEZE it + auto const vaultSle = env.le(vaultKeylet); + auto const vaultPseudo = vaultSle->at(sfAccount); + auto const vaultPseudoAcct = Account("VaultPseudo", vaultPseudo); + env(trust(issuer, vaultPseudoAcct["IOU"](0), tfSetFreeze)); + + env(loanBroker::set(lender, vaultKeylet.key), ter(tecFROZEN)); + } + + void + testRIPD4274IOU() + { + using namespace jtx; + Account issuer("broker"); + Account broker("issuer"); + Account dest("destination"); + auto const token = issuer["IOU"]; + + enum TrustState { + RequireAuth, + ZeroLimit, + ReachedLimit, + NearLimit, + NoTrustLine, + }; + + auto test = [&](TrustState trustState) { + Env env(*this); + + testcase << "RIPD-4274 IOU with state: " + << static_cast(trustState); + + auto setTrustLine = [&](Account const& acct, TrustState state) { + switch (state) + { + case RequireAuth: + env(trust(issuer, token(0), acct, tfSetfAuth)); + break; + case ZeroLimit: { + auto jv = trust(acct, token(0)); + // set QualityIn so that the trustline is not + // auto-deleted + jv[sfQualityIn] = 10'000'000; + env(jv); + } + break; + case ReachedLimit: { + env(trust(acct, token(1'000))); + env(pay(issuer, acct, token(1'000))); + env.close(); + } + break; + case NearLimit: { + env(trust(acct, token(1'000))); + env(pay(issuer, acct, token(950))); + env.close(); + } + break; + case NoTrustLine: + // don't create a trustline + break; + default: + BEAST_EXPECT(false); + } + env.close(); + }; + + env.fund(XRP(1'000), issuer, broker, dest); + env.close(); + + if (trustState == RequireAuth) + { + env(fset(issuer, asfRequireAuth)); + env.close(); + + setTrustLine(broker, RequireAuth); + } + + setTrustLine(dest, trustState); + + env(trust(broker, token(2'000), 0)); + env(pay(issuer, broker, token(2'000))); + env.close(); + + Vault vault(env); + auto const [tx, keylet] = + vault.create({.owner = broker, .asset = token.asset()}); + env(tx); + env.close(); + + // Test Vault withdraw + env(vault.deposit( + {.depositor = broker, + .id = keylet.key, + .amount = token(1'000)})); + env.close(); + + env(vault.withdraw( + {.depositor = broker, + .id = keylet.key, + .amount = token(1'000)}), + loanBroker::destination(dest), + ter(std::ignore)); + BEAST_EXPECT(env.ter() == tecNO_LINE); + env.close(); + + env(vault.withdraw( + {.depositor = broker, + .id = keylet.key, + .amount = token(1'000)})); + + // Test LoanBroker withdraw + auto const brokerKeylet = + keylet::loanbroker(broker, env.seq(broker)); + + env(loanBroker::set(broker, keylet.key)); + env.close(); + + env(loanBroker::coverDeposit( + broker, brokerKeylet.key, token(1'000))); + env.close(); + + env(loanBroker::coverWithdraw(broker, brokerKeylet.key, token(100)), + loanBroker::destination(dest), + ter(std::ignore)); + BEAST_EXPECT(env.ter() == tecNO_LINE); + env.close(); + + // Clearing RequireAuth shouldn't change the result + if (trustState == RequireAuth) + { + env(fclear(issuer, asfRequireAuth)); + env.close(); + + env(loanBroker::coverWithdraw( + broker, brokerKeylet.key, token(100)), + loanBroker::destination(dest), + ter(std::ignore)); + BEAST_EXPECT(env.ter() == tecNO_LINE); + env.close(); + } + }; + + test(RequireAuth); + test(ZeroLimit); + test(ReachedLimit); + test(NearLimit); + test(NoTrustLine); + } + + void + testRIPD4274MPT() + { + using namespace jtx; + Account issuer("broker"); + Account broker("issuer"); + Account dest("destination"); + + enum MPTState { + RequireAuth, + ReachedMAX, + NoMPT, + }; + + auto test = [&](MPTState MPTState) { + Env env(*this); + + testcase << "RIPD-4274 MPT with state: " + << static_cast(MPTState); + + env.fund(XRP(1'000), issuer, broker, dest); + env.close(); + + auto const maybeToken = [&]() -> std::optional { + switch (MPTState) + { + case RequireAuth: { + auto tester = MPTTester( + {.env = env, + .issuer = issuer, + .holders = {broker, dest}, + .pay = 2'000, + .flags = MPTDEXFlags | tfMPTRequireAuth, + .authHolder = true, + .maxAmt = 5'000}); + // unauthorize dest + tester.authorize( + {.account = issuer, + .holder = dest, + .flags = tfMPTUnauthorize}); + return tester; + } + case ReachedMAX: { + auto tester = MPTTester( + {.env = env, + .issuer = issuer, + .holders = {broker, dest}, + .pay = 2'000, + .flags = MPTDEXFlags, + .maxAmt = 4'000}); + BEAST_EXPECT( + env.balance(issuer, tester) == tester(-4'000)); + return tester; + } + case NoMPT: { + return MPTTester( + {.env = env, + .issuer = issuer, + .holders = {broker}, + .pay = 2'000, + .flags = MPTDEXFlags, + .maxAmt = 4'000}); + } + default: + return std::nullopt; + } + }(); + if (!BEAST_EXPECT(maybeToken)) + return; + + auto const& token = *maybeToken; + + Vault vault(env); + auto const [tx, keylet] = + vault.create({.owner = broker, .asset = token.asset()}); + env(tx); + env.close(); + + // Test Vault withdraw + env(vault.deposit( + {.depositor = broker, + .id = keylet.key, + .amount = token(1'000)})); + env.close(); + + env(vault.withdraw( + {.depositor = broker, + .id = keylet.key, + .amount = token(1'000)}), + loanBroker::destination(dest), + ter(std::ignore)); + + // Shouldn't fail if at MaximumAmount since no new tokens are issued + TER const err = + MPTState == ReachedMAX ? TER(tesSUCCESS) : tecNO_AUTH; + BEAST_EXPECT(env.ter() == err); + env.close(); + + if (err != tesSUCCESS) + { + env(vault.withdraw( + {.depositor = broker, + .id = keylet.key, + .amount = token(1'000)})); + } + + // Test LoanBroker withdraw + auto const brokerKeylet = + keylet::loanbroker(broker, env.seq(broker)); + + env(loanBroker::set(broker, keylet.key)); + env.close(); + + env(loanBroker::coverDeposit( + broker, brokerKeylet.key, token(1'000))); + env.close(); + + env(loanBroker::coverWithdraw(broker, brokerKeylet.key, token(100)), + loanBroker::destination(dest), + ter(std::ignore)); + BEAST_EXPECT(env.ter() == err); + env.close(); + }; + + test(RequireAuth); + test(ReachedMAX); + test(NoMPT); + } + + void + testRIPD4274() + { + testRIPD4274IOU(); + testRIPD4274MPT(); + } + public: void run() override { + testLoanBrokerSetDebtMaximum(); testLoanBrokerCoverDepositNullVault(); testDisabled(); @@ -1451,6 +1914,11 @@ public: testInvalidLoanBrokerSet(); testRequireAuth(); + testRIPD4323(); + testAMB06_VaultFreezeCheckMissing(); + + testRIPD4274(); + // TODO: Write clawback failure tests with an issuer / MPT that doesn't // have the right flags set. } diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index 7c2e83aa19..e4f5360043 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -11,6 +11,8 @@ #include #include +#include + namespace xrpl { namespace test { @@ -141,7 +143,7 @@ protected: using namespace jtx; auto const vaultSle = env.le(keylet::vault(vaultID)); - return getVaultScale(vaultSle); + return getAssetsTotalScale(vaultSle); } }; @@ -372,7 +374,7 @@ protected: if (auto loan = env.le(loanKeylet); env.test.BEAST_EXPECT(loan)) { env.test.BEAST_EXPECT( - loan->at(sfPreviousPaymentDate) == previousPaymentDate); + loan->at(sfPreviousPaymentDueDate) == previousPaymentDate); env.test.BEAST_EXPECT( loan->at(sfPaymentRemaining) == paymentRemaining); env.test.BEAST_EXPECT( @@ -507,7 +509,7 @@ protected: if (auto loan = env.le(loanKeylet); BEAST_EXPECT(loan)) { return LoanState{ - .previousPaymentDate = loan->at(sfPreviousPaymentDate), + .previousPaymentDate = loan->at(sfPreviousPaymentDueDate), .startDate = tp{d{loan->at(sfStartDate)}}, .nextPaymentDate = loan->at(sfNextPaymentDueDate), .paymentRemaining = loan->at(sfPaymentRemaining), @@ -551,12 +553,15 @@ protected: broker.vaultScale(env), state.principalOutstanding.exponent()))); BEAST_EXPECT(state.paymentInterval == 600); - BEAST_EXPECT( - state.totalValue == - roundToAsset( - broker.asset, - state.periodicPayment * state.paymentRemaining, - state.loanScale)); + { + NumberRoundModeGuard mg(Number::upward); + BEAST_EXPECT( + state.totalValue == + roundToAsset( + broker.asset, + state.periodicPayment * state.paymentRemaining, + state.loanScale)); + } BEAST_EXPECT( state.managementFeeOutstanding == computeManagementFee( @@ -589,7 +594,7 @@ protected: auto const unrealizedLoss = vaultSle->at(sfLossUnrealized) + state.totalValue - state.managementFeeOutstanding; - if (unrealizedLoss > assetsUnavailable) + if (!BEAST_EXPECT(unrealizedLoss <= assetsUnavailable)) { return false; } @@ -705,8 +710,9 @@ protected: << "\tManagement Fee Rate: " << feeRate << std::endl << "\tTotal Payments: " << total << std::endl << "\tPeriodic Payment: " << props.periodicPayment << std::endl - << "\tTotal Value: " << props.totalValueOutstanding << std::endl - << "\tManagement Fee: " << props.managementFeeOwedToBroker + << "\tTotal Value: " << props.loanState.valueOutstanding + << std::endl + << "\tManagement Fee: " << props.loanState.managementFeeDue << std::endl << "\tLoan Scale: " << props.loanScale << std::endl << "\tFirst payment principal: " << props.firstPaymentPrincipal @@ -856,9 +862,6 @@ protected: using namespace std::chrono_literals; using d = NetClock::duration; - // Account const evan{"evan"}; - // Account const alice{"alice"}; - bool const showStepBalances = paymentParams.showStepBalances; auto const currencyLabel = getCurrencyLabel(broker.asset); @@ -911,7 +914,7 @@ protected: state.principalOutstanding, state.managementFeeOutstanding); { - auto const raw = computeRawLoanState( + auto const raw = computeTheoreticalLoanState( state.periodicPayment, periodicRate, state.paymentRemaining, @@ -964,7 +967,7 @@ protected: Number totalFeesPaid = 0; std::size_t totalPaymentsMade = 0; - xrpl::LoanState currentTrueState = computeRawLoanState( + xrpl::LoanState currentTrueState = computeTheoreticalLoanState( state.periodicPayment, periodicRate, state.paymentRemaining, @@ -1019,7 +1022,7 @@ protected: paymentComponents.trackedInterestPart() + paymentComponents.trackedManagementFeeDelta); - xrpl::LoanState const nextTrueState = computeRawLoanState( + xrpl::LoanState const nextTrueState = computeTheoreticalLoanState( state.periodicPayment, periodicRate, state.paymentRemaining - 1, @@ -1271,7 +1274,8 @@ protected: verifyLoanStatus, issuer, lender, - borrower); + borrower, + PaymentParameters{.showStepBalances = true}); } /** Runs through the complete lifecycle of a loan @@ -1452,7 +1456,7 @@ protected: BEAST_EXPECT( loan->at(sfPaymentInterval) == *loanParams.payInterval); BEAST_EXPECT(loan->at(sfGracePeriod) == *loanParams.gracePd); - BEAST_EXPECT(loan->at(sfPreviousPaymentDate) == 0); + BEAST_EXPECT(loan->at(sfPreviousPaymentDueDate) == 0); BEAST_EXPECT( loan->at(sfNextPaymentDueDate) == startDate + *loanParams.payInterval); @@ -1484,9 +1488,9 @@ protected: startDate + *loanParams.payInterval, *loanParams.payTotal, state.loanScale, - loanProperties.totalValueOutstanding, + loanProperties.loanState.valueOutstanding, principalRequestAmount, - loanProperties.managementFeeOwedToBroker, + loanProperties.loanState.managementFeeDue, loanProperties.periodicPayment, loanFlags | 0); @@ -1541,9 +1545,9 @@ protected: nextDueDate, *loanParams.payTotal, loanProperties.loanScale, - loanProperties.totalValueOutstanding, + loanProperties.loanState.valueOutstanding, principalRequestAmount, - loanProperties.managementFeeOwedToBroker, + loanProperties.loanState.managementFeeDue, loanProperties.periodicPayment, loanFlags | 0); @@ -2448,13 +2452,18 @@ protected: // Make all the payments in one transaction // service fee is 2 auto const startingPayments = state.paymentRemaining; - auto const rawPayoff = startingPayments * - (state.periodicPayment + broker.asset(2).value()); - STAmount const payoffAmount{broker.asset, rawPayoff}; - BEAST_EXPECT( - payoffAmount == - broker.asset(Number(1024014840139457, -12))); - BEAST_EXPECT(payoffAmount > state.principalOutstanding); + STAmount const payoffAmount = [&]() { + NumberRoundModeGuard mg(Number::upward); + auto const rawPayoff = startingPayments * + (state.periodicPayment + broker.asset(2).value()); + STAmount const payoffAmount{broker.asset, rawPayoff}; + BEAST_EXPECTS( + payoffAmount == + broker.asset(Number(1024014840139457, -12)), + to_string(payoffAmount)); + BEAST_EXPECT(payoffAmount > state.principalOutstanding); + return payoffAmount; + }(); singlePayment( loanKeylet, @@ -2662,7 +2671,7 @@ protected: Number::upward)); { - auto const raw = computeRawLoanState( + auto const raw = computeTheoreticalLoanState( state.periodicPayment, periodicRate, state.paymentRemaining, @@ -2705,7 +2714,7 @@ protected: Number totalInterestPaid = 0; std::size_t totalPaymentsMade = 0; - xrpl::LoanState currentTrueState = computeRawLoanState( + xrpl::LoanState currentTrueState = computeTheoreticalLoanState( state.periodicPayment, periodicRate, state.paymentRemaining, @@ -2730,11 +2739,12 @@ protected: paymentComponents.trackedValueDelta <= roundedPeriodicPayment); - xrpl::LoanState const nextTrueState = computeRawLoanState( - state.periodicPayment, - periodicRate, - state.paymentRemaining - 1, - broker.params.managementFeeRate); + xrpl::LoanState const nextTrueState = + computeTheoreticalLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining - 1, + broker.params.managementFeeRate); detail::LoanStateDeltas const deltas = currentTrueState - nextTrueState; @@ -3453,11 +3463,12 @@ protected: ter{tecNO_AUTH}); env.close(); - // Can create loan without origination fee + // Cannot create loan, even without an origination fee env(set(borrower, broker.brokerID, principalRequest), counterparty(lender), sig(sfCounterpartySignature, lender), - fee(env.current()->fees().base * 5)); + fee(env.current()->fees().base * 5), + ter{tecNO_AUTH}); env.close(); // No MPToken for lender - no authorization and no payment @@ -3578,6 +3589,52 @@ protected: fee(env.current()->fees().base * 5)); }, CaseArgs{.requireAuth = true, .authorizeBorrower = true}); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, auto&) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + Vault vault{env}; + auto tx = vault.set({.owner = lender, .id = broker.vaultID}); + tx[sfAssetsMaximum] = BrokerParameters::defaults().vaultDeposit; + env(tx); + env.close(); + + testcase("Vault at maximum value"); + env(set(issuer, broker.brokerID, principalRequest), + counterparty(lender), + interestRate(TenthBips32(10'000)), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + ter(tecLIMIT_EXCEEDED), + THISLINE); + }, + nullptr); + + testCase( + [&, this](Env& env, BrokerInfo const& broker, auto&) { + using namespace loan; + Number const principalRequest = broker.asset(1'000).value(); + Vault vault{env}; + auto tx = vault.set({.owner = lender, .id = broker.vaultID}); + tx[sfAssetsMaximum] = + BrokerParameters::defaults().vaultDeposit + + broker.asset(1).number(); + env(tx); + env.close(); + + testcase("Vault maximum value exceeded"); + env(set(issuer, broker.brokerID, principalRequest), + counterparty(lender), + interestRate(TenthBips32(100'000)), + sig(sfCounterpartySignature, lender), + fee(env.current()->fees().base * 5), + paymentTotal(2), + paymentInterval(3600 * 24), + ter(tecLIMIT_EXCEEDED), + THISLINE); + }, + nullptr); } void @@ -3813,7 +3870,7 @@ protected: BEAST_EXPECT(loan[sfPaymentInterval] == 60); BEAST_EXPECT(loan[sfPeriodicPayment] == "1000000000"); BEAST_EXPECT(loan[sfPaymentRemaining] == 1); - BEAST_EXPECT(!loan.isMember(sfPreviousPaymentDate)); + BEAST_EXPECT(!loan.isMember(sfPreviousPaymentDueDate)); BEAST_EXPECT(loan[sfPrincipalOutstanding] == "1000000000"); BEAST_EXPECT(loan[sfTotalValueOutstanding] == "1000000000"); BEAST_EXPECT(!loan.isMember(sfLoanScale)); @@ -3994,7 +4051,6 @@ protected: createJson["CloseInterestRate"] = 55374; createJson["ClosePaymentFee"] = "3825205248"; - createJson["GracePeriod"] = 0; createJson["LatePaymentFee"] = "237"; createJson["LoanOriginationFee"] = "0"; createJson["OverpaymentFee"] = 35167; @@ -4009,7 +4065,7 @@ protected: createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); // Fails in preclaim because principal requested can't be // represented as XRP - env(createJson, ter(tecPRECISION_LOSS)); + env(createJson, ter(tecPRECISION_LOSS), THISLINE); env.close(); BEAST_EXPECT(!env.le(keylet)); @@ -4021,7 +4077,7 @@ protected: createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); // Fails in doApply because the payment is too small to be // represented as XRP. - env(createJson, ter(tecPRECISION_LOSS)); + env(createJson, ter(tecPRECISION_LOSS), THISLINE); env.close(); } @@ -4455,15 +4511,6 @@ protected: }; } - void - testBasicMath() - { - // Test the functions defined in LendingHelpers.h - testcase("Basic Math"); - - pass(); - } - void testIssuerLoan() { @@ -4679,7 +4726,30 @@ protected: jtx::fee const& loanSetFee, Number const& debtMaximumRequest) { // first temBAD_SIGNER: TODO + // invalid grace period + { + // zero grace period + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + gracePeriod(0), + loanSetFee, + ter(temINVALID)); + // grace period less than default minimum + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + gracePeriod(LoanSet::defaultGracePeriod - 1), + loanSetFee, + ter(temINVALID)); + + // grace period greater than payment interval + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + paymentInterval(120), + gracePeriod(121), + loanSetFee, + ter(temINVALID)); + } // empty/zero broker ID { auto jv = set(borrower, uint256{}, debtMaximumRequest); @@ -4980,7 +5050,6 @@ protected: createJson["CloseInterestRate"] = 47299; createJson["ClosePaymentFee"] = "3985819770"; - createJson["GracePeriod"] = 0; createJson["InterestRate"] = 92; createJson["LatePaymentFee"] = "3866894865"; createJson["LoanOriginationFee"] = "0"; @@ -4996,7 +5065,7 @@ protected: auto const keylet = keylet::loan(broker.brokerID, loanSequence); createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); - env(createJson, ter(tecPRECISION_LOSS)); + env(createJson, ter(tecPRECISION_LOSS), THISLINE); env.close(startDate); auto loanPayTx = env.json( @@ -5133,7 +5202,6 @@ protected: json(sfCounterpartySignature, Json::objectValue)); createJson["ClosePaymentFee"] = "0"; - createJson["GracePeriod"] = 0; createJson["InterestRate"] = 24346; createJson["LateInterestRate"] = 65535; createJson["LatePaymentFee"] = "0"; @@ -5253,7 +5321,6 @@ protected: json(sfCounterpartySignature, Json::objectValue)); createJson["ClosePaymentFee"] = "0"; - createJson["GracePeriod"] = 0; createJson["InterestRate"] = 12833; createJson["LateInterestRate"] = 77048; createJson["LatePaymentFee"] = "0"; @@ -5347,7 +5414,7 @@ protected: set(borrower, broker.brokerID, Number{55524'81, -2}), fee(loanSetFee), closePaymentFee(0), - gracePeriod(0), + gracePeriod(LoanSet::defaultGracePeriod), interestRate(TenthBips32(12833)), lateInterestRate(TenthBips32(77048)), latePaymentFee(0), @@ -5851,7 +5918,7 @@ protected: auto const periodicRate = loanPeriodicRate(interestRateValue, state.paymentInterval); - auto const rawLoanState = computeRawLoanState( + auto const rawLoanState = computeTheoreticalLoanState( state.periodicPayment, periodicRate, state.paymentRemaining, @@ -6029,7 +6096,7 @@ protected: { // --- PoC Summary ---------------------------------------------------- // Scenario: Borrower makes one periodic payment early (before next due) - // so doPayment sets sfPreviousPaymentDate to the (future) + // so doPayment sets sfPreviousPaymentDueDate to the (future) // sfNextPaymentDueDate and advances sfNextPaymentDueDate by one // interval. Borrower then immediately performs a full-payment // (tfLoanFullPayment). Why it matters: Full-payment interest accrual @@ -6144,15 +6211,16 @@ protected: // Accrued + prepayment-penalty interest based on current periodic // schedule auto const fullPaymentInterest = computeFullPaymentInterest( - after.periodicPayment, + detail::loanPrincipalFromPeriodicPayment( + after.periodicPayment, periodicRate2, after.paymentRemaining), periodicRate2, - after.paymentRemaining, env.current()->parentCloseTime(), after.paymentInterval, after.previousPaymentDate, static_cast( after.startDate.time_since_epoch().count()), closeInterestRate); + // Round to asset scale and split interest/fee parts auto const roundedInterest = roundToAsset(asset.raw(), fullPaymentInterest, after.loanScale); @@ -6180,9 +6248,9 @@ protected: // window by clamping prevPaymentDate to 'now' for the full-pay path. auto const prevClamped = std::min(after.previousPaymentDate, nowSecs); auto const fullPaymentInterestClamped = computeFullPaymentInterest( - after.periodicPayment, + detail::loanPrincipalFromPeriodicPayment( + after.periodicPayment, periodicRate2, after.paymentRemaining), periodicRate2, - after.paymentRemaining, env.current()->parentCloseTime(), after.paymentInterval, prevClamped, @@ -6436,8 +6504,7 @@ protected: .lateFee = Number{200, -6}, .interest = TenthBips32{50'000}, .payTotal = 10, - .payInterval = 150, - .gracePd = 0}; + .payInterval = 150}; auto const assetType = AssetType::XRP; @@ -6458,9 +6525,6 @@ protected: auto state = getCurrentState(env, broker, loanKeylet); if (auto loan = env.le(loanKeylet); BEAST_EXPECT(loan)) { - // log << "loan after create: " << to_string(loan->getJson()) - // << std::endl; - env.close(tp{d{ loan->at(sfNextPaymentDueDate) + loan->at(sfGracePeriod) + 1}}); } @@ -6475,16 +6539,10 @@ protected: { auto const submitParam = to_string(jv); - // log << "about to submit: " << submitParam << std::endl; auto const jr = env.rpc("submit", borrower.name(), submitParam); - // log << jr << std::endl; BEAST_EXPECT(jr.isMember(jss::result)); auto const jResult = jr[jss::result]; - // BEAST_EXPECT(jResult[jss::error] == "invalidTransaction"); - // BEAST_EXPECT( - // jResult[jss::error_exception] == - // "fails local checks: Transaction has bad signature."); } env.close(); @@ -6520,8 +6578,7 @@ protected: .counter = borrower, .principalRequest = Number{100'000, -4}, .interest = TenthBips32{100'000}, - .payTotal = 10, - .gracePd = 0}; + .payTotal = 10}; auto const assetType = AssetType::MPT; @@ -7007,11 +7064,8 @@ protected: env.close(); PaymentParameters paymentParams{ - //.overpaymentFactor = Number{15, -1}, - //.overpaymentExtra = Number{1, -6}, - //.flags = tfLoanOverpayment, - .showStepBalances = true, - //.validateBalances = false, + .showStepBalances = false, + .validateBalances = true, }; makeLoanPayments( @@ -7026,6 +7080,532 @@ protected: paymentParams); } + void + testOverpaymentManagementFee() + { + testcase("testOverpaymentManagementFee"); + + using namespace jtx; + using namespace loan; + + Env env(*this, all); + + Account const lender{"lender"}, borrower{"borrower"}; + + env.fund(XRP(10'000'000), lender, borrower); + env.close(); + + PrettyAsset const asset{xrpIssue(), 1000}; + + auto const result = createVaultAndBroker( + env, + asset, + lender, + { + .vaultDeposit = asset(100'000).value(), + .managementFeeRate = TenthBips16(10'000), + }); + + auto const loanSetFee = fee(env.current()->fees().base * 2); + + auto const loanKeylet = keylet::loan( + result.brokerKeylet().key, + (env.le(result.brokerKeylet()))->at(sfLoanSequence)); + env(loan::set( + borrower, + result.brokerKeylet().key, + asset(10'000).value(), + tfLoanOverpayment), + sig(sfCounterpartySignature, lender), + loan::paymentInterval(86400 * 30), + loan::paymentTotal(3), + loan::overpaymentInterestRate( + TenthBips32(percentageToTenthBips(20))), + loanSetFee); + + // From calculator + auto const expectedOverpaymentManagementFee = Number{33333, 0}; + auto const loanBrokerBalanceBefore = env.balance(lender); + + auto const loanPayFee = fee(env.current()->fees().base * 2); + env(pay(borrower, + loanKeylet.key, + asset(5'000).value(), + tfLoanOverpayment), + loanPayFee); + env.close(); + + BEAST_EXPECTS( + env.balance(lender) - loanBrokerBalanceBefore == + expectedOverpaymentManagementFee, + "overpayment management fee missmatch; expected:" + + to_string(expectedOverpaymentManagementFee) + " got: " + + to_string(env.balance(lender) - loanBrokerBalanceBefore)); + } + + void + testLoanPayBrokerOwnerMissingTrustline() + { + testcase << "LoanPay Broker Owner Missing Trustline (PoC)"; + using namespace jtx; + using namespace loan; + Account const issuer("issuer"); + Account const borrower("borrower"); + Account const broker("broker"); + auto const IOU = issuer["IOU"]; + Env env(*this, all); + env.fund(XRP(20'000), issuer, broker, borrower); + env.close(); + // Set up trustlines and fund accounts + env(trust(broker, IOU(20'000'000))); + env(trust(borrower, IOU(20'000'000))); + env(pay(issuer, broker, IOU(10'000'000))); + env(pay(issuer, borrower, IOU(1'000))); + env.close(); + // Create vault and broker + auto const brokerInfo = createVaultAndBroker(env, IOU, broker); + // Create a loan first (this creates debt) + auto const keylet = keylet::loan(brokerInfo.brokerID, 1); + env(set(borrower, brokerInfo.brokerID, 10'000), + sig(sfCounterpartySignature, broker), + loanServiceFee(IOU(100).value()), + paymentInterval(100), + fee(XRP(100))); + env.close(); + // Ensure broker has sufficient cover so brokerPayee == brokerOwner + // We need coverAvailable >= (debtTotal * coverRateMinimum) + // Deposit enough cover to ensure the fee goes to broker owner + // The default coverRateMinimum is 10%, so for a 10,000 loan we need + // at least 1,000 cover. Default cover is 1,000, so we add more to be + // safe. + auto const additionalCover = IOU(50'000).value(); + env(loanBroker::coverDeposit( + broker, brokerInfo.brokerID, STAmount{IOU, additionalCover})); + env.close(); + // Verify broker owner has a trustline + auto const brokerTrustline = keylet::line(broker, IOU); + BEAST_EXPECT(env.le(brokerTrustline) != nullptr); + // Broker owner deletes their trustline + // First, pay any positive balance to issuer to zero it out + auto const brokerBalance = env.balance(broker, IOU); + env(pay(broker, issuer, brokerBalance)); + env.close(); + // Remove the trustline by setting limit to 0 + env(trust(broker, IOU(0))); + env.close(); + // Verify trustline is deleted + BEAST_EXPECT(env.le(brokerTrustline) == nullptr); + // Now borrower tries to make a payment + // We should get a tesSUCCESS instead of a tecNO_LINE. + env(pay(borrower, keylet.key, IOU(10'100)), + fee(XRP(100)), + ter(tesSUCCESS)); + env.close(); + // Verify trustline is still deleted + BEAST_EXPECT(env.le(brokerTrustline) == nullptr); + // Verify the service fee went to the broker pseudo-account + if (auto const brokerSle = + env.le(keylet::loanbroker(brokerInfo.brokerID)); + BEAST_EXPECT(brokerSle)) + { + Account const pseudo("pseudo-account", brokerSle->at(sfAccount)); + auto const balance = env.balance(pseudo, IOU); + // 1,000 default + 50,000 extra + 100 service fee from LoanPay + BEAST_EXPECTS( + balance == IOU(51'100), to_string(Json::Value(balance))); + } + } + + void + testLoanPayBrokerOwnerUnauthorizedMPT() + { + testcase << "LoanPay Broker Owner MPT unauthorized"; + using namespace jtx; + using namespace loan; + + Account const issuer("issuer"); + Account const borrower("borrower"); + Account const broker("broker"); + + Env env(*this, all); + env.fund(XRP(20'000), issuer, broker, borrower); + env.close(); + + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + + PrettyAsset const MPT{mptt.issuanceID()}; + + // Authorize broker and borrower + mptt.authorize({.account = broker}); + mptt.authorize({.account = borrower}); + + env.close(); + + // Fund accounts + env(pay(issuer, broker, MPT(10'000'000))); + env(pay(issuer, borrower, MPT(1'000))); + env.close(); + + // Create vault and broker + auto const brokerInfo = createVaultAndBroker(env, MPT, broker); + // Create a loan first (this creates debt) + auto const keylet = keylet::loan(brokerInfo.brokerID, 1); + env(set(borrower, brokerInfo.brokerID, 10'000), + sig(sfCounterpartySignature, broker), + loanServiceFee(MPT(100).value()), + paymentInterval(100), + fee(XRP(100))); + env.close(); + // Ensure broker has sufficient cover so brokerPayee == brokerOwner + // We need coverAvailable >= (debtTotal * coverRateMinimum) + // Deposit enough cover to ensure the fee goes to broker owner + // The default coverRateMinimum is 10%, so for a 10,000 loan we need + // at least 1,000 cover. Default cover is 1,000, so we add more to be + // safe. + auto const additionalCover = MPT(50'000).value(); + env(loanBroker::coverDeposit( + broker, brokerInfo.brokerID, STAmount{MPT, additionalCover})); + env.close(); + // Verify broker owner is authorized + auto const brokerMpt = keylet::mptoken(mptt.issuanceID(), broker); + BEAST_EXPECT(env.le(brokerMpt) != nullptr); + // Broker owner unauthorizes. + // First, pay any positive balance to issuer to zero it out + auto const brokerBalance = env.balance(broker, MPT); + env(pay(broker, issuer, brokerBalance)); + env.close(); + // Then, unauthorize the MPT. + mptt.authorize({.account = broker, .flags = tfMPTUnauthorize}); + env.close(); + // Verify the MPT is unauthorized. + BEAST_EXPECT(env.le(brokerMpt) == nullptr); + // Now borrower tries to make a payment + // We should get a tesSUCCESS instead of a tecNO_AUTH. + auto const borrowerBalance = env.balance(borrower, MPT); + env(pay(borrower, keylet.key, MPT(10'100)), + fee(XRP(100)), + ter(tesSUCCESS)); + env.close(); + // Verify the MPT is still unauthorized. + BEAST_EXPECT(env.le(brokerMpt) == nullptr); + // Verify the service fee went to the broker pseudo-account + if (auto const brokerSle = + env.le(keylet::loanbroker(brokerInfo.brokerID)); + BEAST_EXPECT(brokerSle)) + { + Account const pseudo("pseudo-account", brokerSle->at(sfAccount)); + auto const balance = env.balance(pseudo, MPT); + // 1,000 default + 50,000 extra + 100 service fee from LoanPay + BEAST_EXPECTS( + balance == MPT(51'100), to_string(Json::Value(balance))); + } + } + + void + testLoanPayBrokerOwnerNoPermissionedDomainMPT() + { + testcase + << "LoanPay Broker Owner without permissioned domain of the MPT"; + using namespace jtx; + using namespace loan; + + Account const issuer("issuer"); + Account const borrower("borrower"); + Account const broker("broker"); + + Env env(*this, all); + env.fund(XRP(20'000), issuer, broker, borrower); + env.close(); + + auto credType = "credential1"; + + pdomain::Credentials const credentials1{{issuer, credType}}; + env(pdomain::setTx(issuer, credentials1)); + env.close(); + + auto domainID = pdomain::getNewDomain(env.meta()); + + env(credentials::create(broker, issuer, credType)); + env(credentials::accept(broker, issuer, credType)); + env.close(); + + env(credentials::create(borrower, issuer, credType)); + env(credentials::accept(borrower, issuer, credType)); + env.close(); + + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create({ + .flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer | + tfMPTCanLock, + .domainID = domainID, + }); + + PrettyAsset const MPT{mptt.issuanceID()}; + + // Authorize broker and borrower + mptt.authorize({.account = broker}); + mptt.authorize({.account = borrower}); + + env.close(); + + // Fund accounts + env(pay(issuer, broker, MPT(10'000'000))); + env(pay(issuer, borrower, MPT(1'000))); + env.close(); + + // Create vault and broker + auto const brokerInfo = createVaultAndBroker(env, MPT, broker); + // Create a loan first (this creates debt) + auto const keylet = keylet::loan(brokerInfo.brokerID, 1); + env(set(borrower, brokerInfo.brokerID, 10'000), + sig(sfCounterpartySignature, broker), + loanServiceFee(MPT(100).value()), + paymentInterval(100), + fee(XRP(100))); + env.close(); + // Ensure broker has sufficient cover so brokerPayee == brokerOwner + // We need coverAvailable >= (debtTotal * coverRateMinimum) + // Deposit enough cover to ensure the fee goes to broker owner + // The default coverRateMinimum is 10%, so for a 10,000 loan we need + // at least 1,000 cover. Default cover is 1,000, so we add more to be + // safe. + auto const additionalCover = MPT(50'000).value(); + env(loanBroker::coverDeposit( + broker, brokerInfo.brokerID, STAmount{MPT, additionalCover})); + env.close(); + // Verify broker owner is authorized + auto const brokerMpt = keylet::mptoken(mptt.issuanceID(), broker); + BEAST_EXPECT(env.le(brokerMpt) != nullptr); + // Remove the credentials for the Broker owner. + // First, pay any positive balance to issuer to zero it out + auto const brokerBalance = env.balance(broker, MPT); + env(pay(broker, issuer, brokerBalance)); + env.close(); + + env(credentials::deleteCred(broker, broker, issuer, credType)); + env.close(); + + // Make sure the broker is not authorized to hold the MPT after we + // deleted the credentials + env(pay(issuer, broker, MPT(1'000)), ter(tecNO_AUTH)); + + // Now borrower tries to make a payment + // We should get a tesSUCCESS instead of a tecNO_AUTH. + auto const borrowerBalance = env.balance(borrower, MPT); + env(pay(borrower, keylet.key, MPT(10'100)), + fee(XRP(100)), + ter(tesSUCCESS)); + env.close(); + // Verify broker is still not authorized + env(pay(issuer, broker, MPT(1'000)), ter(tecNO_AUTH)); + // Verify the service fee went to the broker pseudo-account + if (auto const brokerSle = + env.le(keylet::loanbroker(brokerInfo.brokerID)); + BEAST_EXPECT(brokerSle)) + { + Account const pseudo("pseudo-account", brokerSle->at(sfAccount)); + auto const balance = env.balance(pseudo, MPT); + // 1,000 default + 50,000 extra + 100 service fee from LoanPay + BEAST_EXPECTS( + balance == MPT(51'100), to_string(Json::Value(balance))); + } + } + + void + testLoanSetBrokerOwnerNoPermissionedDomainMPT() + { + testcase + << "LoanSet Broker Owner without permissioned domain of the MPT"; + using namespace jtx; + using namespace loan; + + Account const issuer("issuer"); + Account const borrower("borrower"); + Account const broker("broker"); + + Env env(*this, all); + env.fund(XRP(20'000), issuer, broker, borrower); + env.close(); + + auto credType = "credential1"; + + pdomain::Credentials const credentials1{{issuer, credType}}; + env(pdomain::setTx(issuer, credentials1)); + env.close(); + + auto domainID = pdomain::getNewDomain(env.meta()); + + // Add credentials for the broker and borrower + env(credentials::create(broker, issuer, credType)); + env(credentials::accept(broker, issuer, credType)); + env.close(); + + env(credentials::create(borrower, issuer, credType)); + env(credentials::accept(borrower, issuer, credType)); + env.close(); + + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create({ + .flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer | + tfMPTCanLock, + .domainID = domainID, + }); + + PrettyAsset const MPT{mptt.issuanceID()}; + + // Authorize broker and borrower + mptt.authorize({.account = broker}); + mptt.authorize({.account = borrower}); + env.close(); + + // Fund accounts + env(pay(issuer, broker, MPT(10'000'000))); + env(pay(issuer, borrower, MPT(1'000))); + env.close(); + + // Create vault and broker + auto const brokerInfo = createVaultAndBroker(env, MPT, broker); + + // Remove the credentials for the Broker owner. + // Clear the balance first. + auto const brokerBalance = env.balance(broker, MPT); + env(pay(broker, issuer, brokerBalance)); + env.close(); + // Delete the credentials + env(credentials::deleteCred(broker, broker, issuer, credType)); + env.close(); + + // Create a loan, this should fail for tecNO_AUTH + env(set(borrower, brokerInfo.brokerID, 10'000), + sig(sfCounterpartySignature, broker), + loanServiceFee(MPT(100).value()), + paymentInterval(100), + fee(XRP(100)), + ter(tecNO_AUTH)); + env.close(); + } + + void + testSequentialFLCDepletion() + { + testcase << "First-Loss Capital Depletion on Sequential Defaults"; + + using namespace jtx; + using namespace loan; + using namespace loanBroker; + + Env env(*this, all); + + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrowerA{"borrowerA"}; + Account const borrowerB{"borrowerB"}; + + env.fund(XRP(1'000'000), issuer, lender, borrowerA, borrowerB); + env.close(); + + PrettyAsset const asset = xrpIssue(); + auto const vaultDepositAmount = + asset(200'000); // Enough for 2 x 50k loans plus interest/fees + + auto const brokerInfo = createVaultAndBroker( + env, + asset, + lender, + { + .vaultDeposit = vaultDepositAmount.value(), + .debtMax = 0, + .coverRateMin = TenthBips32(20000), // 20% + .coverDeposit = 21'000, + .managementFeeRate = TenthBips16(100), // 0.1% + .coverRateLiquidation = TenthBips32(100000), + }); + auto const brokerKeylet = brokerInfo.brokerKeylet(); + + // Create two identical loans: each 50,000 XRP principal (scaled down to + // avoid funding issues) Total DebtTotal will be ~100,000 XRP (principal + // + interest) Formula will calculate cover as: 100% × (20% × 100,000) = + // 20,000 XRP So we need FLC = 20,000 XRP to be fully consumed by first + // default + auto const principalAmount = Number(50'000); + auto const loanPaymentInterval = 2592000; // 30 days + auto const loanGracePeriod = 604800; // 7 days + + // Create Loan A + auto loanATx = env.jt( + set(borrowerA, brokerKeylet.key, principalAmount), + sig(sfCounterpartySignature, lender), + interestRate(TenthBips32(500)), // 5% + paymentTotal(12), + loan::paymentInterval(loanPaymentInterval), + loan::gracePeriod(loanGracePeriod), + fee(XRP(10))); // Sufficient fee for multi-sig transaction + env(loanATx); + env.close(); + + auto const loanAKeylet = keylet::loan(brokerKeylet.key, 1); + + // Create Loan B + auto loanBTx = env.jt( + set(borrowerB, brokerKeylet.key, principalAmount), + sig(sfCounterpartySignature, lender), + interestRate(TenthBips32(500)), // 5% + paymentTotal(12), + loan::paymentInterval(loanPaymentInterval), + loan::gracePeriod(loanGracePeriod), + fee(XRP(10))); // Sufficient fee for multi-sig transaction + env(loanBTx); + env.close(); + + auto const loanBKeylet = keylet::loan(brokerKeylet.key, 2); + + auto loanASle = env.le(loanAKeylet); + if (!BEAST_EXPECT(loanASle)) + return; + + // Advance time past grace period for both loans to be defaultable + auto const loanANextDue = loanASle->at(sfNextPaymentDueDate); + auto const loanAGrace = loanASle->at(sfGracePeriod); + env.close(std::chrono::seconds{loanANextDue + loanAGrace + 60}); + + env(manage(lender, loanAKeylet.key, tfLoanDefault), ter(tesSUCCESS)); + env.close(); + + // Verify Loan A is defaulted + loanASle = env.le(loanAKeylet); + if (!BEAST_EXPECT(loanASle)) + return; + BEAST_EXPECT(loanASle->isFlag(lsfLoanDefault)); + BEAST_EXPECT(loanASle->at(sfPaymentRemaining) == 0); + + // Check broker state after first default (from committed ledger) + auto brokerSle = env.le(brokerKeylet); + if (!BEAST_EXPECT(brokerSle)) + return; + auto const afterFirstDebtTotal = brokerSle->at(sfDebtTotal); + auto const afterFirstCoverAvailable = brokerSle->at(sfCoverAvailable); + + // DebtTotal should have decreased by Loan A's debt + BEAST_EXPECT(afterFirstDebtTotal == 50'134); + + // CoverAvailable should have decreased significantly + BEAST_EXPECT(afterFirstCoverAvailable == 946); + + env(manage(lender, loanBKeylet.key, tfLoanDefault), ter(tesSUCCESS)); + + brokerSle = env.le(brokerKeylet); + if (!BEAST_EXPECT(brokerSle)) + return; + auto const afterSecondDebtTotal = brokerSle->at(sfDebtTotal); + auto const afterSecondCoverAvailable = brokerSle->at(sfCoverAvailable); + + BEAST_EXPECT(afterSecondDebtTotal == 0); + + BEAST_EXPECT(afterSecondCoverAvailable == 0); + } + public: void run() override @@ -7034,6 +7614,8 @@ public: testLoanPayLateFullPaymentBypassesPenalties(); testLoanCoverMinimumRoundingExploit(); #endif + testInvalidLoanSet(); + testCoverDepositWithdrawNonTransferableMPT(); testPoC_UnsignedUnderflowOnFullPayAfterEarlyPeriodic(); @@ -7045,12 +7627,9 @@ public: testServiceFeeOnBrokerDeepFreeze(); testRPC(); - testBasicMath(); - testInvalidLoanDelete(); testInvalidLoanManage(); testInvalidLoanPay(); - testInvalidLoanSet(); testBatchBypassCounterparty(); testLoanPayComputePeriodicPaymentValidRateInvariant(); @@ -7074,6 +7653,12 @@ public: testBorrowerIsBroker(); testIssuerIsBorrower(); testLimitExceeded(); + testOverpaymentManagementFee(); + testLoanPayBrokerOwnerMissingTrustline(); + testLoanPayBrokerOwnerUnauthorizedMPT(); + testLoanPayBrokerOwnerNoPermissionedDomainMPT(); + testLoanSetBrokerOwnerNoPermissionedDomainMPT(); + testSequentialFLCDepletion(); } }; @@ -7193,15 +7778,15 @@ class LoanArbitrary_test : public LoanBatch_test .vaultDeposit = 10000, .debtMax = 0, .coverRateMin = TenthBips32{0}, - // .managementFeeRate = TenthBips16{5919}, + .managementFeeRate = TenthBips16{0}, .coverRateLiquidation = TenthBips32{0}}; LoanParameters const loanParams{ .account = Account("lender"), .counter = Account("borrower"), - .principalRequest = Number{10000, 0}, - // .interest = TenthBips32{0}, - // .payTotal = 5816, - .payInterval = 150}; + .principalRequest = Number{200000, -6}, + .interest = TenthBips32{50000}, + .payTotal = 2, + .payInterval = 200}; runLoan(AssetType::XRP, brokerParams, loanParams); } diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index d0a1450d6c..a6d08b6531 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -5324,7 +5324,7 @@ class Vault_test : public beast::unit_test::suite // Create a simple Loan for the full amount of Vault assets env(set(depositor, brokerKeylet.key, asset(100).value()), loan::interestRate(TenthBips32(0)), - gracePeriod(10), + gracePeriod(60), paymentInterval(120), paymentTotal(10), sig(sfCounterpartySignature, owner), @@ -5344,7 +5344,7 @@ class Vault_test : public beast::unit_test::suite THISLINE); env.close(); - env.close(std::chrono::seconds{120 + 10}); + env.close(std::chrono::seconds{120 + 60}); env(manage(owner, loanKeylet.key, tfLoanDefault), ter(tesSUCCESS), diff --git a/src/test/jtx/impl/mpt.cpp b/src/test/jtx/impl/mpt.cpp index adffa8548a..ceb60eb319 100644 --- a/src/test/jtx/impl/mpt.cpp +++ b/src/test/jtx/impl/mpt.cpp @@ -644,7 +644,7 @@ MPTTester::operator[](std::string const& name) const } PrettyAmount -MPTTester::operator()(std::uint64_t amount) const +MPTTester::operator()(std::int64_t amount) const { return MPT("", issuanceID())(amount); } diff --git a/src/test/jtx/mpt.h b/src/test/jtx/mpt.h index 2f6bbb9ea8..3eea362b58 100644 --- a/src/test/jtx/mpt.h +++ b/src/test/jtx/mpt.h @@ -272,7 +272,7 @@ public: operator[](std::string const& name) const; PrettyAmount - operator()(std::uint64_t amount) const; + operator()(std::int64_t amount) const; operator Asset() const; diff --git a/src/xrpld/app/misc/LendingHelpers.h b/src/xrpld/app/misc/LendingHelpers.h index 071466f05c..79fc617569 100644 --- a/src/xrpld/app/misc/LendingHelpers.h +++ b/src/xrpld/app/misc/LendingHelpers.h @@ -84,50 +84,10 @@ struct LoanPaymentParts operator==(LoanPaymentParts const& other) const; }; -/* Describes the initial computed properties of a loan. - * - * This structure contains the fundamental calculated values that define a - * loan's payment structure and amortization schedule. These properties are - * computed: - * - At loan creation (LoanSet transaction) - * - When loan terms change (e.g., after an overpayment that reduces the loan - * balance) - */ -struct LoanProperties -{ - // The unrounded amount to be paid at each regular payment period. - // Calculated using the standard amortization formula based on principal, - // interest rate, and number of payments. - // The actual amount paid in the LoanPay transaction must be rounded up to - // the precision of the asset and loan. - Number periodicPayment; - - // The total amount the borrower will pay over the life of the loan. - // Equal to periodicPayment * paymentsRemaining. - // This includes principal, interest, and management fees. - Number totalValueOutstanding; - - // The total management fee that will be paid to the broker over the - // loan's lifetime. This is a percentage of the total interest (gross) - // as specified by the broker's management fee rate. - Number managementFeeOwedToBroker; - - // The scale (decimal places) used for rounding all loan amounts. - // This is the maximum of: - // - The asset's native scale - // - A minimum scale required to represent the periodic payment accurately - // All loan state values (principal, interest, fees) are rounded to this - // scale. - std::int32_t loanScale; - - // The principal portion of the first payment. - Number firstPaymentPrincipal; -}; - /** This structure captures the parts of a loan state. * - * Whether the values are raw (unrounded) or rounded will depend on how it was - * computed. + * Whether the values are theoretical (unrounded) or rounded will depend on how + * it was computed. * * Many of the fields can be derived from each other, but they're all provided * here to reduce code duplication and possible mistakes. @@ -161,6 +121,39 @@ struct LoanState } }; +/* Describes the initial computed properties of a loan. + * + * This structure contains the fundamental calculated values that define a + * loan's payment structure and amortization schedule. These properties are + * computed: + * - At loan creation (LoanSet transaction) + * - When loan terms change (e.g., after an overpayment that reduces the loan + * balance) + */ +struct LoanProperties +{ + // The unrounded amount to be paid at each regular payment period. + // Calculated using the standard amortization formula based on principal, + // interest rate, and number of payments. + // The actual amount paid in the LoanPay transaction must be rounded up to + // the precision of the asset and loan. + Number periodicPayment; + + // The loan's current state, with all values rounded to the loan's scale. + LoanState loanState; + + // The scale (decimal places) used for rounding all loan amounts. + // This is the maximum of: + // - The asset's native scale + // - A minimum scale required to represent the periodic payment accurately + // All loan state values (principal, interest, fees) are rounded to this + // scale. + std::int32_t loanScale; + + // The principal portion of the first payment. + Number firstPaymentPrincipal; +}; + // Some values get re-rounded to the vault scale any time they are adjusted. In // addition, they are prevented from ever going below zero. This helps avoid // accumulated rounding errors and leftover dust amounts. @@ -179,11 +172,12 @@ adjustImpreciseNumber( } inline int -getVaultScale(SLE::const_ref vaultSle) +getAssetsTotalScale(SLE::const_ref vaultSle) { if (!vaultSle) return Number::minExponent - 1; // LCOV_EXCL_LINE - return vaultSle->at(sfAssetsTotal).exponent(); + return STAmount{vaultSle->at(sfAsset), vaultSle->at(sfAssetsTotal)} + .exponent(); } TER @@ -196,20 +190,12 @@ checkLoanGuards( beast::Journal j); LoanState -computeRawLoanState( +computeTheoreticalLoanState( Number const& periodicPayment, Number const& periodicRate, std::uint32_t const paymentRemaining, TenthBips32 const managementFeeRate); -LoanState -computeRawLoanState( - Number const& periodicPayment, - TenthBips32 interestRate, - std::uint32_t paymentInterval, - std::uint32_t const paymentRemaining, - TenthBips32 const managementFeeRate); - // Constructs a valid LoanState object from arbitrary inputs LoanState constructLoanState( @@ -231,7 +217,7 @@ computeManagementFee( Number computeFullPaymentInterest( - Number const& rawPrincipalOutstanding, + Number const& theoreticalPrincipalOutstanding, Number const& periodicRate, NetClock::time_point parentCloseTime, std::uint32_t paymentInterval, @@ -239,17 +225,6 @@ computeFullPaymentInterest( std::uint32_t startDate, TenthBips32 closeInterestRate); -Number -computeFullPaymentInterest( - Number const& periodicPayment, - Number const& periodicRate, - std::uint32_t paymentRemaining, - NetClock::time_point parentCloseTime, - std::uint32_t paymentInterval, - std::uint32_t prevPaymentDate, - std::uint32_t startDate, - TenthBips32 closeInterestRate); - namespace detail { // These classes and functions should only be accessed by LendingHelper // functions and unit tests @@ -387,6 +362,70 @@ struct LoanStateDeltas nonNegative(); }; +Expected, TER> +tryOverpayment( + Asset const& asset, + std::int32_t loanScale, + ExtendedPaymentComponents const& overpaymentComponents, + LoanState const& roundedLoanState, + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t paymentRemaining, + TenthBips16 const managementFeeRate, + beast::Journal j); + +Number +computeRaisedRate(Number const& periodicRate, std::uint32_t paymentsRemaining); + +Number +computePaymentFactor( + Number const& periodicRate, + std::uint32_t paymentsRemaining); + +std::pair +computeInterestAndFeeParts( + Asset const& asset, + Number const& interest, + TenthBips16 managementFeeRate, + std::int32_t loanScale); + +Number +loanPeriodicPayment( + Number const& principalOutstanding, + Number const& periodicRate, + std::uint32_t paymentsRemaining); + +Number +loanPrincipalFromPeriodicPayment( + Number const& periodicPayment, + Number const& periodicRate, + std::uint32_t paymentsRemaining); + +Number +loanLatePaymentInterest( + Number const& principalOutstanding, + TenthBips32 lateInterestRate, + NetClock::time_point parentCloseTime, + std::uint32_t nextPaymentDueDate); + +Number +loanAccruedInterest( + Number const& principalOutstanding, + Number const& periodicRate, + NetClock::time_point parentCloseTime, + std::uint32_t startDate, + std::uint32_t prevPaymentDate, + std::uint32_t paymentInterval); + +ExtendedPaymentComponents +computeOverpaymentComponents( + Asset const& asset, + int32_t const loanScale, + Number const& overpayment, + TenthBips32 const overpaymentInterestRate, + TenthBips32 const overpaymentFeeRate, + TenthBips16 const managementFeeRate); + PaymentComponents computePaymentComponents( Asset const& asset, @@ -413,13 +452,22 @@ operator+(LoanState const& lhs, detail::LoanStateDeltas const& rhs); LoanProperties computeLoanProperties( Asset const& asset, - Number principalOutstanding, + Number const& principalOutstanding, TenthBips32 interestRate, std::uint32_t paymentInterval, std::uint32_t paymentsRemaining, TenthBips32 managementFeeRate, std::int32_t minimumScale); +LoanProperties +computeLoanProperties( + Asset const& asset, + Number const& principalOutstanding, + Number const& periodicRate, + std::uint32_t paymentsRemaining, + TenthBips32 managementFeeRate, + std::int32_t minimumScale); + bool isRounded(Asset const& asset, Number const& value, std::int32_t scale); diff --git a/src/xrpld/app/misc/detail/LendingHelpers.cpp b/src/xrpld/app/misc/detail/LendingHelpers.cpp index 37385583e7..a8354ff049 100644 --- a/src/xrpld/app/misc/detail/LendingHelpers.cpp +++ b/src/xrpld/app/misc/detail/LendingHelpers.cpp @@ -100,6 +100,9 @@ computePaymentFactor( Number const& periodicRate, std::uint32_t paymentsRemaining) { + if (paymentsRemaining == 0) + return numZero; + // For zero interest, payment factor is simply 1/paymentsRemaining if (periodicRate == beast::zero) return Number{1} / paymentsRemaining; @@ -132,27 +135,6 @@ loanPeriodicPayment( computePaymentFactor(periodicRate, paymentsRemaining); } -/* Calculates the periodic payment amount from annualized interest rate. - * Converts the annual rate to periodic rate before computing payment. - * - * Equation (7) from XLS-66 spec, Section A-2 Equation Glossary - */ -Number -loanPeriodicPayment( - Number const& principalOutstanding, - TenthBips32 interestRate, - std::uint32_t paymentInterval, - std::uint32_t paymentsRemaining) -{ - if (principalOutstanding == 0 || paymentsRemaining == 0) - return 0; - - Number const periodicRate = loanPeriodicRate(interestRate, paymentInterval); - - return loanPeriodicPayment( - principalOutstanding, periodicRate, paymentsRemaining); -} - /* Reverse-calculates principal from periodic payment amount. * Used to determine theoretical principal at any point in the schedule. * @@ -164,6 +146,9 @@ loanPrincipalFromPeriodicPayment( Number const& periodicRate, std::uint32_t paymentsRemaining) { + if (paymentsRemaining == 0) + return numZero; + if (periodicRate == 0) return periodicPayment * paymentsRemaining; @@ -171,21 +156,6 @@ loanPrincipalFromPeriodicPayment( computePaymentFactor(periodicRate, paymentsRemaining); } -/* Splits gross interest into net interest (to vault) and management fee (to - * broker). Returns pair of (net interest, management fee). - * - * Equation (33) from XLS-66 spec, Section A-2 Equation Glossary - */ -std::pair -computeInterestAndFeeParts( - Number const& interest, - TenthBips16 managementFeeRate) -{ - auto const fee = tenthBipsOfValue(interest, managementFeeRate); - - return std::make_pair(interest - fee, fee); -} - /* * Computes the interest and management fee parts from interest amount. * @@ -216,6 +186,12 @@ loanLatePaymentInterest( NetClock::time_point parentCloseTime, std::uint32_t nextPaymentDueDate) { + if (principalOutstanding == beast::zero) + return numZero; + + if (lateInterestRate == TenthBips32{0}) + return numZero; + auto const now = parentCloseTime.time_since_epoch().count(); // If the payment is not late by any amount of time, then there's no late @@ -248,6 +224,9 @@ loanAccruedInterest( if (periodicRate == beast::zero) return numZero; + if (paymentInterval == 0) + return numZero; + auto const lastPaymentDate = std::max(prevPaymentDate, startDate); auto const now = parentCloseTime.time_since_epoch().count(); @@ -401,42 +380,33 @@ doPayment( * The function preserves accumulated rounding errors across the re-amortization * to ensure the loan state remains consistent with its payment history. */ -Expected +Expected, TER> tryOverpayment( Asset const& asset, std::int32_t loanScale, ExtendedPaymentComponents const& overpaymentComponents, - Number& totalValueOutstanding, - Number& principalOutstanding, - Number& managementFeeOutstanding, - Number& periodicPayment, - TenthBips32 interestRate, - std::uint32_t paymentInterval, + LoanState const& roundedOldState, + Number const& periodicPayment, Number const& periodicRate, std::uint32_t paymentRemaining, - std::uint32_t prevPaymentDate, - std::optional nextDueDate, TenthBips16 const managementFeeRate, beast::Journal j) { // Calculate what the loan state SHOULD be theoretically (at full precision) - auto const raw = computeRawLoanState( + auto const theoreticalState = computeTheoreticalLoanState( periodicPayment, periodicRate, paymentRemaining, managementFeeRate); - // Get the actual loan state (with accumulated rounding from past payments) - auto const rounded = constructLoanState( - totalValueOutstanding, principalOutstanding, managementFeeOutstanding); - // Calculate the accumulated rounding errors. These need to be preserved // across the re-amortization to maintain consistency with the loan's // payment history. Without preserving these errors, the loan could end // up with a different total value than what the borrower has actually paid. - auto const errors = rounded - raw; + auto const errors = roundedOldState - theoreticalState; - // Compute the new principal by applying the overpayment to the raw - // (theoretical) principal. Use max with 0 to ensure we never go negative. - auto const newRawPrincipal = std::max( - raw.principalOutstanding - overpaymentComponents.trackedPrincipalDelta, + // Compute the new principal by applying the overpayment to the theoretical + // principal. Use max with 0 to ensure we never go negative. + auto const newTheoreticalPrincipal = std::max( + theoreticalState.principalOutstanding - + overpaymentComponents.trackedPrincipalDelta, Number{0}); // Compute new loan properties based on the reduced principal. This @@ -444,9 +414,8 @@ tryOverpayment( // for the remaining payment schedule. auto newLoanProperties = computeLoanProperties( asset, - newRawPrincipal, - interestRate, - paymentInterval, + newTheoreticalPrincipal, + periodicRate, paymentRemaining, managementFeeRate, loanScale); @@ -454,56 +423,60 @@ tryOverpayment( JLOG(j.debug()) << "new periodic payment: " << newLoanProperties.periodicPayment << ", new total value: " - << newLoanProperties.totalValueOutstanding + << newLoanProperties.loanState.valueOutstanding << ", first payment principal: " << newLoanProperties.firstPaymentPrincipal; // Calculate what the new loan state should be with the new periodic payment - auto const newRaw = computeRawLoanState( - newLoanProperties.periodicPayment, - periodicRate, - paymentRemaining, - managementFeeRate) + + // including rounding errors + auto const newTheoreticalState = computeTheoreticalLoanState( + newLoanProperties.periodicPayment, + periodicRate, + paymentRemaining, + managementFeeRate) + errors; - JLOG(j.debug()) << "new raw value: " << newRaw.valueOutstanding - << ", principal: " << newRaw.principalOutstanding - << ", interest gross: " << newRaw.interestOutstanding(); - // Update the loan state variables with the new values PLUS the preserved - // rounding errors. This ensures the loan's tracked state remains - // consistent with its payment history. + JLOG(j.debug()) << "new theoretical value: " + << newTheoreticalState.valueOutstanding << ", principal: " + << newTheoreticalState.principalOutstanding + << ", interest gross: " + << newTheoreticalState.interestOutstanding(); - principalOutstanding = std::clamp( - roundToAsset( - asset, newRaw.principalOutstanding, loanScale, Number::upward), - numZero, - rounded.principalOutstanding); - totalValueOutstanding = std::clamp( + // Update the loan state variables with the new values that include the + // preserved rounding errors. This ensures the loan's tracked state remains + // consistent with its payment history. + auto const principalOutstanding = std::clamp( roundToAsset( asset, - principalOutstanding + newRaw.interestOutstanding(), + newTheoreticalState.principalOutstanding, loanScale, Number::upward), numZero, - rounded.valueOutstanding); - managementFeeOutstanding = std::clamp( - roundToAsset(asset, newRaw.managementFeeDue, loanScale), + roundedOldState.principalOutstanding); + auto const totalValueOutstanding = std::clamp( + roundToAsset( + asset, + principalOutstanding + newTheoreticalState.interestOutstanding(), + loanScale, + Number::upward), numZero, - rounded.managementFeeDue); + roundedOldState.valueOutstanding); + auto const managementFeeOutstanding = std::clamp( + roundToAsset(asset, newTheoreticalState.managementFeeDue, loanScale), + numZero, + roundedOldState.managementFeeDue); - auto const newRounded = constructLoanState( + auto const roundedNewState = constructLoanState( totalValueOutstanding, principalOutstanding, managementFeeOutstanding); // Update newLoanProperties so that checkLoanGuards can make an accurate // evaluation. - newLoanProperties.totalValueOutstanding = newRounded.valueOutstanding; + newLoanProperties.loanState = roundedNewState; - JLOG(j.debug()) << "new rounded value: " << newRounded.valueOutstanding - << ", principal: " << newRounded.principalOutstanding - << ", interest gross: " << newRounded.interestOutstanding(); - - // Update the periodic payment to reflect the re-amortized schedule - periodicPayment = newLoanProperties.periodicPayment; + JLOG(j.debug()) << "new rounded value: " << roundedNewState.valueOutstanding + << ", principal: " << roundedNewState.principalOutstanding + << ", interest gross: " + << roundedNewState.interestOutstanding(); // check that the loan is still valid if (auto const ter = checkLoanGuards( @@ -513,7 +486,7 @@ tryOverpayment( // small interest amounts, that may have already been paid // off. Check what's still outstanding. This should // guarantee that the interest checks pass. - newRounded.interestOutstanding() != beast::zero, + roundedNewState.interestOutstanding() != beast::zero, paymentRemaining, newLoanProperties, j)) @@ -527,32 +500,40 @@ tryOverpayment( // Validate that all computed properties are reasonable. These checks should // never fail under normal circumstances, but we validate defensively. if (newLoanProperties.periodicPayment <= 0 || - newLoanProperties.totalValueOutstanding <= 0 || - newLoanProperties.managementFeeOwedToBroker < 0) + newLoanProperties.loanState.valueOutstanding <= 0 || + newLoanProperties.loanState.managementFeeDue < 0) { // LCOV_EXCL_START JLOG(j.warn()) << "Overpayment not allowed: Computed loan " "properties are invalid. Does " "not compute. TotalValueOutstanding: " - << newLoanProperties.totalValueOutstanding + << newLoanProperties.loanState.valueOutstanding << ", PeriodicPayment : " << newLoanProperties.periodicPayment << ", ManagementFeeOwedToBroker: " - << newLoanProperties.managementFeeOwedToBroker; + << newLoanProperties.loanState.managementFeeDue; return Unexpected(tesSUCCESS); // LCOV_EXCL_STOP } - auto const deltas = rounded - newRounded; + auto const deltas = roundedOldState - roundedNewState; - auto const hypotheticalValueOutstanding = - rounded.valueOutstanding - deltas.principal; + // The change in loan management fee is equal to the change between the old + // and the new outstanding management fees + XRPL_ASSERT_PARTS( + deltas.managementFee == + roundedOldState.managementFeeDue - managementFeeOutstanding, + "xrpl::detail::tryOverpayment", + "no fee change"); // Calculate how the loan's value changed due to the overpayment. // This should be negative (value decreased) or zero. A principal // overpayment should never increase the loan's value. - auto const valueChange = - newRounded.valueOutstanding - hypotheticalValueOutstanding; + // The value change is derived from the reduction in interest due to + // the lower principal. + // We do not consider the change in management fee here, since + // management fees are excluded from the valueOutstanding. + auto const valueChange = -deltas.interest; if (valueChange > 0) { JLOG(j.warn()) << "Principal overpayment would increase the value of " @@ -560,21 +541,23 @@ tryOverpayment( return Unexpected(tesSUCCESS); } - return LoanPaymentParts{ - // Principal paid is the reduction in principal outstanding - .principalPaid = deltas.principal, - // Interest paid is the reduction in interest due - .interestPaid = - deltas.interest + overpaymentComponents.untrackedInterest, - // Value change includes both the reduction from paying down principal - // (negative) and any untracked interest penalties (positive, e.g., if - // the overpayment itself incurs a fee) - .valueChange = - valueChange + overpaymentComponents.trackedInterestPart(), - // Fee paid includes both the reduction in tracked management fees and - // any untracked fees on the overpayment itself - .feePaid = deltas.managementFee + - overpaymentComponents.untrackedManagementFee}; + return std::make_pair( + LoanPaymentParts{ + // Principal paid is the reduction in principal outstanding + .principalPaid = deltas.principal, + // Interest paid is the reduction in interest due + .interestPaid = overpaymentComponents.untrackedInterest, + // Value change includes both the reduction from paying down + // principal (negative) and any untracked interest penalties + // (positive, e.g., if the overpayment itself incurs a fee) + .valueChange = + valueChange + overpaymentComponents.untrackedInterest, + // Fee paid includes both the reduction in tracked management fees + // and any untracked fees on the overpayment itself + .feePaid = overpaymentComponents.untrackedManagementFee + + overpaymentComponents.trackedManagementFeeDelta, + }, + newLoanProperties); } /* Validates and applies an overpayment to the loan state. @@ -598,23 +581,16 @@ doOverpayment( NumberProxy& principalOutstandingProxy, NumberProxy& managementFeeOutstandingProxy, NumberProxy& periodicPaymentProxy, - TenthBips32 const interestRate, - std::uint32_t const paymentInterval, Number const& periodicRate, std::uint32_t const paymentRemaining, - std::uint32_t const prevPaymentDate, - std::optional const nextDueDate, TenthBips16 const managementFeeRate, beast::Journal j) { - // Create temporary copies of the loan state that can be safely modified - // and discarded if the overpayment doesn't work out. This prevents - // corrupting the actual ledger data if validation fails. - Number totalValueOutstanding = totalValueOutstandingProxy; - Number principalOutstanding = principalOutstandingProxy; - Number managementFeeOutstanding = managementFeeOutstandingProxy; - Number periodicPayment = periodicPaymentProxy; - + auto const loanState = constructLoanState( + totalValueOutstandingProxy, + principalOutstandingProxy, + managementFeeOutstandingProxy); + auto const periodicPayment = periodicPaymentProxy; JLOG(j.debug()) << "overpayment components:" << ", totalValue before: " << *totalValueOutstandingProxy @@ -633,33 +609,28 @@ doOverpayment( asset, loanScale, overpaymentComponents, - totalValueOutstanding, - principalOutstanding, - managementFeeOutstanding, + loanState, periodicPayment, - interestRate, - paymentInterval, periodicRate, paymentRemaining, - prevPaymentDate, - nextDueDate, managementFeeRate, j); if (!ret) return Unexpected(ret.error()); - auto const& loanPaymentParts = *ret; + auto const& [loanPaymentParts, newLoanProperties] = *ret; + auto const newRoundedLoanState = newLoanProperties.loanState; // Safety check: the principal must have decreased. If it didn't (or // increased!), something went wrong in the calculation and we should // reject the overpayment. - if (principalOutstandingProxy <= principalOutstanding) + if (principalOutstandingProxy <= newRoundedLoanState.principalOutstanding) { // LCOV_EXCL_START JLOG(j.warn()) << "Overpayment not allowed: principal " << "outstanding did not decrease. Before: " - << *principalOutstandingProxy - << ". After: " << principalOutstanding; + << *principalOutstandingProxy << ". After: " + << newRoundedLoanState.principalOutstanding; return Unexpected(tesSUCCESS); // LCOV_EXCL_STOP } @@ -670,34 +641,29 @@ doOverpayment( XRPL_ASSERT_PARTS( overpaymentComponents.trackedPrincipalDelta == - principalOutstandingProxy - principalOutstanding, + principalOutstandingProxy - + newRoundedLoanState.principalOutstanding, "xrpl::detail::doOverpayment", "principal change agrees"); - XRPL_ASSERT_PARTS( - overpaymentComponents.trackedManagementFeeDelta == - managementFeeOutstandingProxy - managementFeeOutstanding, - "xrpl::detail::doOverpayment", - "no fee change"); - // I'm not 100% sure the following asserts are correct. If in doubt, and // everything else works, remove any that cause trouble. - JLOG(j.debug()) << "valueChange: " << loanPaymentParts.valueChange - << ", totalValue before: " << *totalValueOutstandingProxy - << ", totalValue after: " << totalValueOutstanding - << ", totalValue delta: " - << (totalValueOutstandingProxy - totalValueOutstanding) - << ", principalDelta: " - << overpaymentComponents.trackedPrincipalDelta - << ", principalPaid: " << loanPaymentParts.principalPaid - << ", Computed difference: " - << overpaymentComponents.trackedPrincipalDelta - - (totalValueOutstandingProxy - totalValueOutstanding); + JLOG(j.debug()) + << "valueChange: " << loanPaymentParts.valueChange + << ", totalValue before: " << *totalValueOutstandingProxy + << ", totalValue after: " << newRoundedLoanState.valueOutstanding + << ", totalValue delta: " + << (totalValueOutstandingProxy - newRoundedLoanState.valueOutstanding) + << ", principalDelta: " << overpaymentComponents.trackedPrincipalDelta + << ", principalPaid: " << loanPaymentParts.principalPaid + << ", Computed difference: " + << overpaymentComponents.trackedPrincipalDelta - + (totalValueOutstandingProxy - newRoundedLoanState.valueOutstanding); XRPL_ASSERT_PARTS( loanPaymentParts.valueChange == - totalValueOutstanding - + newRoundedLoanState.valueOutstanding - (totalValueOutstandingProxy - overpaymentComponents.trackedPrincipalDelta) + overpaymentComponents.trackedInterestPart(), @@ -710,19 +676,12 @@ doOverpayment( "xrpl::detail::doOverpayment", "principal payment matches"); - XRPL_ASSERT_PARTS( - loanPaymentParts.feePaid == - overpaymentComponents.untrackedManagementFee + - overpaymentComponents.trackedManagementFeeDelta, - "xrpl::detail::doOverpayment", - "fee payment matches"); - // All validations passed, so update the proxy objects (which will // modify the actual Loan ledger object) - totalValueOutstandingProxy = totalValueOutstanding; - principalOutstandingProxy = principalOutstanding; - managementFeeOutstandingProxy = managementFeeOutstanding; - periodicPaymentProxy = periodicPayment; + totalValueOutstandingProxy = newRoundedLoanState.valueOutstanding; + principalOutstandingProxy = newRoundedLoanState.principalOutstanding; + managementFeeOutstandingProxy = newRoundedLoanState.managementFeeDue; + periodicPaymentProxy = newLoanProperties.periodicPayment; return loanPaymentParts; } @@ -789,25 +748,21 @@ computeLatePayment( // this to keep the logic clear. This preserves all the other fields without // having to enumerate them. - ExtendedPaymentComponents const late = [&]() { - auto inner = periodic; + ExtendedPaymentComponents const late{ + periodic, + // Untracked management fee includes: + // 1. Regular service fee (from periodic.untrackedManagementFee) + // 2. Late payment fee (fixed penalty) + // 3. Management fee portion of late interest + periodic.untrackedManagementFee + latePaymentFee + + roundedLateManagementFee, - return ExtendedPaymentComponents{ - inner, - // Untracked management fee includes: - // 1. Regular service fee (from periodic.untrackedManagementFee) - // 2. Late payment fee (fixed penalty) - // 3. Management fee portion of late interest - periodic.untrackedManagementFee + latePaymentFee + - roundedLateManagementFee, - - // Untracked interest includes: - // 1. Any untracked interest from the regular payment (usually 0) - // 2. Late penalty interest (increases loan value) - // This positive value indicates the loan's value increased due - // to the late payment. - periodic.untrackedInterest + roundedLateInterest}; - }(); + // Untracked interest includes: + // 1. Any untracked interest from the regular payment (usually 0) + // 2. Late penalty interest (increases loan value) + // This positive value indicates the loan's value increased due + // to the late payment. + periodic.untrackedInterest + roundedLateInterest}; XRPL_ASSERT_PARTS( isRounded(asset, late.totalDue, loanScale), @@ -875,15 +830,16 @@ computeFullPayment( } // Calculate the theoretical principal based on the payment schedule. - // This raw (unrounded) value is used to compute interest and penalties - // accurately. - Number const rawPrincipalOutstanding = loanPrincipalFromPeriodicPayment( - periodicPayment, periodicRate, paymentRemaining); + // This theoretical (unrounded) value is used to compute interest and + // penalties accurately. + Number const theoreticalPrincipalOutstanding = + loanPrincipalFromPeriodicPayment( + periodicPayment, periodicRate, paymentRemaining); // Full payment interest includes both accrued interest (time since last // payment) and prepayment penalty (for closing early). auto const fullPaymentInterest = computeFullPaymentInterest( - rawPrincipalOutstanding, + theoreticalPrincipalOutstanding, periodicRate, view.parentCloseTime(), paymentInterval, @@ -896,9 +852,8 @@ computeFullPayment( auto const [roundedFullInterest, roundedFullManagementFee] = [&]() { auto const interest = roundToAsset( asset, fullPaymentInterest, loanScale, Number::downward); - auto const parts = computeInterestAndFeeParts( + return computeInterestAndFeeParts( asset, interest, managementFeeRate, loanScale); - return std::make_tuple(parts.first, parts.second); }(); ExtendedPaymentComponents const full{ @@ -943,7 +898,8 @@ computeFullPayment( JLOG(j.trace()) << "computeFullPayment result: periodicPayment: " << periodicPayment << ", periodicRate: " << periodicRate << ", paymentRemaining: " << paymentRemaining - << ", rawPrincipalOutstanding: " << rawPrincipalOutstanding + << ", theoreticalPrincipalOutstanding: " + << theoreticalPrincipalOutstanding << ", fullPaymentInterest: " << fullPaymentInterest << ", roundedFullInterest: " << roundedFullInterest << ", roundedFullManagementFee: " @@ -980,6 +936,8 @@ PaymentComponents::trackedInterestPart() const * * Special handling for the final payment: all remaining balances are paid off * regardless of the periodic payment amount. + * + * Implements the pseudo-code function `compute_payment_due()`. */ PaymentComponents computePaymentComponents( @@ -1023,7 +981,7 @@ computePaymentComponents( // Calculate what the loan state SHOULD be after this payment (the target). // This is computed at full precision using the theoretical amortization. - LoanState const trueTarget = computeRawLoanState( + LoanState const trueTarget = computeTheoreticalLoanState( periodicPayment, periodicRate, paymentRemaining - 1, managementFeeRate); // Round the target to the loan's scale to match how actual loan values @@ -1229,17 +1187,12 @@ computeOverpaymentComponents( // This interest doesn't follow the normal amortization schedule - it's // a one-time charge for paying early. // Equation (20) and (21) from XLS-66 spec, Section A-2 Equation Glossary - auto const [rawOverpaymentInterest, _] = [&]() { - Number const interest = - tenthBipsOfValue(overpayment, overpaymentInterestRate); - return detail::computeInterestAndFeeParts(interest, managementFeeRate); - }(); - - // Round the penalty interest components to the loan scale auto const [roundedOverpaymentInterest, roundedOverpaymentManagementFee] = [&]() { - Number const interest = - roundToAsset(asset, rawOverpaymentInterest, loanScale); + auto const interest = roundToAsset( + asset, + tenthBipsOfValue(overpayment, overpaymentInterestRate), + loanScale); return detail::computeInterestAndFeeParts( asset, interest, managementFeeRate, loanScale); }(); @@ -1256,12 +1209,11 @@ computeOverpaymentComponents( .specialCase = detail::PaymentSpecialCase::extra}, // Untracked management fee is the fixed overpayment fee overpaymentFee, - // Untracked interest is the penalty interest charged for - // overpaying. - // This is positive, representing a one-time cost, but it's - // typically - // much smaller than the interest savings from reducing - // principal. + // Untracked interest is the penalty interest charged for overpaying. + // This is positive, representing a one-time cost, but it's typically + // much smaller than the interest savings from reducing principal. + // It is equal to the paymentComponents.trackedInterestPart() + // but is kept separate for clarity. roundedOverpaymentInterest}; XRPL_ASSERT_PARTS( result.trackedInterestPart() == roundedOverpaymentInterest, @@ -1320,7 +1272,7 @@ checkLoanGuards( beast::Journal j) { auto const totalInterestOutstanding = - properties.totalValueOutstanding - principalRequested; + properties.loanState.valueOutstanding - principalRequested; // Guard 1: if there is no computed total interest over the life of the // loan for a non-zero interest rate, we cannot properly amortize the // loan @@ -1375,13 +1327,13 @@ checkLoanGuards( NumberRoundModeGuard mg(Number::upward); if (std::int64_t const computedPayments{ - properties.totalValueOutstanding / roundedPayment}; + properties.loanState.valueOutstanding / roundedPayment}; computedPayments != paymentTotal) { JLOG(j.warn()) << "Loan Periodic payment (" << properties.periodicPayment << ") rounding (" << roundedPayment << ") on a total value of " - << properties.totalValueOutstanding + << properties.loanState.valueOutstanding << " can not complete the loan in the specified " "number of payments (" << computedPayments << " != " << paymentTotal << ")"; @@ -1399,7 +1351,7 @@ checkLoanGuards( */ Number computeFullPaymentInterest( - Number const& rawPrincipalOutstanding, + Number const& theoreticalPrincipalOutstanding, Number const& periodicRate, NetClock::time_point parentCloseTime, std::uint32_t paymentInterval, @@ -1408,7 +1360,7 @@ computeFullPaymentInterest( TenthBips32 closeInterestRate) { auto const accruedInterest = detail::loanAccruedInterest( - rawPrincipalOutstanding, + theoreticalPrincipalOutstanding, periodicRate, parentCloseTime, startDate, @@ -1422,7 +1374,7 @@ computeFullPaymentInterest( // Equation (28) from XLS-66 spec, Section A-2 Equation Glossary auto const prepaymentPenalty = closeInterestRate == beast::zero ? Number{} - : tenthBipsOfValue(rawPrincipalOutstanding, closeInterestRate); + : tenthBipsOfValue(theoreticalPrincipalOutstanding, closeInterestRate); XRPL_ASSERT( prepaymentPenalty >= 0, @@ -1433,42 +1385,17 @@ computeFullPaymentInterest( return accruedInterest + prepaymentPenalty; } -Number -computeFullPaymentInterest( - Number const& periodicPayment, - Number const& periodicRate, - std::uint32_t paymentRemaining, - NetClock::time_point parentCloseTime, - std::uint32_t paymentInterval, - std::uint32_t prevPaymentDate, - std::uint32_t startDate, - TenthBips32 closeInterestRate) -{ - Number const rawPrincipalOutstanding = - detail::loanPrincipalFromPeriodicPayment( - periodicPayment, periodicRate, paymentRemaining); - - return computeFullPaymentInterest( - rawPrincipalOutstanding, - periodicRate, - parentCloseTime, - paymentInterval, - prevPaymentDate, - startDate, - closeInterestRate); -} - /* Calculates the theoretical loan state at maximum precision for a given point * in the amortization schedule. * * This function computes what the loan's outstanding balances should be based * on the periodic payment amount and number of payments remaining, * without considering any rounding that may have been applied to the actual - * Loan object's state. This "raw" (unrounded) state is used as a target for - * computing payment components and validating that the loan's tracked state + * Loan object's state. This "theoretical" (unrounded) state is used as a target + * for computing payment components and validating that the loan's tracked state * hasn't drifted too far from the theoretical values. * - * The raw state serves several purposes: + * The theoretical state serves several purposes: * 1. Computing the expected payment breakdown (principal, interest, fees) * 2. Detecting and correcting rounding errors that accumulate over time * 3. Validating that overpayments are calculated correctly @@ -1476,9 +1403,12 @@ computeFullPaymentInterest( * * If paymentRemaining is 0, returns a fully zeroed-out LoanState, * representing a completely paid-off loan. + * + * Implements the `calculate_true_loan_state` function from the XLS-66 spec + * section 3.2.4.4 Transaction Pseudo-code */ LoanState -computeRawLoanState( +computeTheoreticalLoanState( Number const& periodicPayment, Number const& periodicRate, std::uint32_t const paymentRemaining, @@ -1494,55 +1424,42 @@ computeRawLoanState( } // Equation (30) from XLS-66 spec, Section A-2 Equation Glossary - Number const rawTotalValueOutstanding = periodicPayment * paymentRemaining; + Number const totalValueOutstanding = periodicPayment * paymentRemaining; - Number const rawPrincipalOutstanding = + Number const principalOutstanding = detail::loanPrincipalFromPeriodicPayment( periodicPayment, periodicRate, paymentRemaining); // Equation (31) from XLS-66 spec, Section A-2 Equation Glossary - Number const rawInterestOutstandingGross = - rawTotalValueOutstanding - rawPrincipalOutstanding; + Number const interestOutstandingGross = + totalValueOutstanding - principalOutstanding; // Equation (32) from XLS-66 spec, Section A-2 Equation Glossary - Number const rawManagementFeeOutstanding = - tenthBipsOfValue(rawInterestOutstandingGross, managementFeeRate); + Number const managementFeeOutstanding = + tenthBipsOfValue(interestOutstandingGross, managementFeeRate); // Equation (33) from XLS-66 spec, Section A-2 Equation Glossary - Number const rawInterestOutstandingNet = - rawInterestOutstandingGross - rawManagementFeeOutstanding; + Number const interestOutstandingNet = + interestOutstandingGross - managementFeeOutstanding; return LoanState{ - .valueOutstanding = rawTotalValueOutstanding, - .principalOutstanding = rawPrincipalOutstanding, - .interestDue = rawInterestOutstandingNet, - .managementFeeDue = rawManagementFeeOutstanding}; + .valueOutstanding = totalValueOutstanding, + .principalOutstanding = principalOutstanding, + .interestDue = interestOutstandingNet, + .managementFeeDue = managementFeeOutstanding, + }; }; -LoanState -computeRawLoanState( - Number const& periodicPayment, - TenthBips32 interestRate, - std::uint32_t paymentInterval, - std::uint32_t const paymentRemaining, - TenthBips32 const managementFeeRate) -{ - return computeRawLoanState( - periodicPayment, - loanPeriodicRate(interestRate, paymentInterval), - paymentRemaining, - managementFeeRate); -} - /* Constructs a LoanState from rounded Loan ledger object values. * * This function creates a LoanState structure from the three tracked values - * stored in a Loan ledger object. Unlike calculateRawLoanState(), which + * stored in a Loan ledger object. Unlike calculateTheoreticalLoanState(), which * computes theoretical unrounded values, this function works with values * that have already been rounded to the loan's scale. * - * The key difference from calculateRawLoanState(): - * - calculateRawLoanState: Computes theoretical values at full precision + * The key difference from calculateTheoreticalLoanState(): + * - calculateTheoreticalLoanState: Computes theoretical values at full + * precision * - constructRoundedLoanState: Builds state from actual rounded ledger values * * The interestDue field is derived from the other three values rather than @@ -1600,11 +1517,16 @@ computeManagementFee( /* * Given the loan parameters, compute the derived properties of the loan. + * + * Pulls together several formulas from the XLS-66 spec, which are noted at each + * step, plus the concepts from 3.2.4.3 Conceptual Loan Value. They are used for + * to check some of the conditions in 3.2.1.5 Failure Conditions for the LoanSet + * transaction. */ LoanProperties computeLoanProperties( Asset const& asset, - Number principalOutstanding, + Number const& principalOutstanding, TenthBips32 interestRate, std::uint32_t paymentInterval, std::uint32_t paymentsRemaining, @@ -1615,12 +1537,39 @@ computeLoanProperties( XRPL_ASSERT( interestRate == 0 || periodicRate > 0, "xrpl::computeLoanProperties : valid rate"); + return computeLoanProperties( + asset, + principalOutstanding, + periodicRate, + paymentsRemaining, + managementFeeRate, + minimumScale); +} +/* + * Given the loan parameters, compute the derived properties of the loan. + * + * Pulls together several formulas from the XLS-66 spec, which are noted at each + * step, plus the concepts from 3.2.4.3 Conceptual Loan Value. They are used for + * to check some of the conditions in 3.2.1.5 Failure Conditions for the LoanSet + * transaction. + */ +LoanProperties +computeLoanProperties( + Asset const& asset, + Number const& principalOutstanding, + Number const& periodicRate, + std::uint32_t paymentsRemaining, + TenthBips32 managementFeeRate, + std::int32_t minimumScale) +{ auto const periodicPayment = detail::loanPeriodicPayment( principalOutstanding, periodicRate, paymentsRemaining); auto const [totalValueOutstanding, loanScale] = [&]() { - NumberRoundModeGuard mg(Number::to_nearest); + // only round up if there should be interest + NumberRoundModeGuard mg( + periodicRate == 0 ? Number::to_nearest : Number::upward); // Use STAmount's internal rounding instead of roundToAsset, because // we're going to use this result to determine the scale for all the // other rounding. @@ -1641,7 +1590,7 @@ computeLoanProperties( // We may need to truncate the total value because of the minimum // scale - amount = roundToAsset(asset, amount, loanScale, Number::to_nearest); + amount = roundToAsset(asset, amount, loanScale); return std::make_pair(amount, loanScale); }(); @@ -1649,12 +1598,12 @@ computeLoanProperties( // Since we just figured out the loan scale, we haven't been able to // validate that the principal fits in it, so to allow this function to // succeed, round it here, and let the caller do the validation. - principalOutstanding = roundToAsset( + auto const roundedPrincipalOutstanding = roundToAsset( asset, principalOutstanding, loanScale, Number::to_nearest); // Equation (31) from XLS-66 spec, Section A-2 Equation Glossary auto const totalInterestOutstanding = - totalValueOutstanding - principalOutstanding; + totalValueOutstanding - roundedPrincipalOutstanding; auto const feeOwedToBroker = computeManagementFee( asset, totalInterestOutstanding, managementFeeRate, loanScale); @@ -1664,13 +1613,13 @@ computeLoanProperties( auto const firstPaymentPrincipal = [&]() { // Compute the parts for the first payment. Ensure that the // principal payment will actually change the principal. - auto const startingState = computeRawLoanState( + auto const startingState = computeTheoreticalLoanState( periodicPayment, periodicRate, paymentsRemaining, managementFeeRate); - auto const firstPaymentState = computeRawLoanState( + auto const firstPaymentState = computeTheoreticalLoanState( periodicPayment, periodicRate, paymentsRemaining - 1, @@ -1684,10 +1633,13 @@ computeLoanProperties( return LoanProperties{ .periodicPayment = periodicPayment, - .totalValueOutstanding = totalValueOutstanding, - .managementFeeOwedToBroker = feeOwedToBroker, + .loanState = constructLoanState( + totalValueOutstanding, + roundedPrincipalOutstanding, + feeOwedToBroker), .loanScale = loanScale, - .firstPaymentPrincipal = firstPaymentPrincipal}; + .firstPaymentPrincipal = firstPaymentPrincipal, + }; } /* @@ -1740,7 +1692,7 @@ loanMakePayment( Number const periodicPayment = loan->at(sfPeriodicPayment); - auto prevPaymentDateProxy = loan->at(sfPreviousPaymentDate); + auto prevPaymentDateProxy = loan->at(sfPreviousPaymentDueDate); std::uint32_t const startDate = loan->at(sfStartDate); std::uint32_t const paymentInterval = loan->at(sfPaymentInterval); @@ -2016,12 +1968,8 @@ loanMakePayment( principalOutstandingProxy, managementFeeOutstandingProxy, periodicPaymentProxy, - interestRate, - paymentInterval, periodicRate, paymentRemainingProxy, - prevPaymentDateProxy, - nextDueDateProxy, managementFeeRate, j)) totalParts += *overResult; diff --git a/src/xrpld/app/paths/Flow.cpp b/src/xrpld/app/paths/Flow.cpp index a102e44854..b5088d15b3 100644 --- a/src/xrpld/app/paths/Flow.cpp +++ b/src/xrpld/app/paths/Flow.cpp @@ -1,11 +1,11 @@ #include -#include #include #include #include #include #include +#include #include #include diff --git a/src/xrpld/app/paths/detail/DirectStep.cpp b/src/xrpld/app/paths/detail/DirectStep.cpp index 4e701d348f..3d3a76f42d 100644 --- a/src/xrpld/app/paths/detail/DirectStep.cpp +++ b/src/xrpld/app/paths/detail/DirectStep.cpp @@ -1,8 +1,8 @@ -#include #include #include #include +#include #include #include #include diff --git a/src/xrpld/app/paths/detail/StrandFlow.h b/src/xrpld/app/paths/detail/StrandFlow.h index fab92dca35..ca4b18f0a3 100644 --- a/src/xrpld/app/paths/detail/StrandFlow.h +++ b/src/xrpld/app/paths/detail/StrandFlow.h @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -11,6 +10,7 @@ #include #include +#include #include #include #include diff --git a/src/xrpld/app/paths/detail/XRPEndpointStep.cpp b/src/xrpld/app/paths/detail/XRPEndpointStep.cpp index 83271321be..ed1866bf24 100644 --- a/src/xrpld/app/paths/detail/XRPEndpointStep.cpp +++ b/src/xrpld/app/paths/detail/XRPEndpointStep.cpp @@ -1,9 +1,9 @@ -#include #include #include #include #include +#include #include #include #include diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp index 32c8fecf20..1cc6b1f5ae 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp @@ -270,7 +270,7 @@ LoanBrokerCoverClawback::preclaim(PreclaimContext const& ctx) JLOG(ctx.j.warn()) << "LoanBroker cover is already at minimum."; return findClawAmount.error(); } - STAmount const clawAmount = *findClawAmount; + STAmount const& clawAmount = *findClawAmount; // Explicitly check the balance of the trust line / MPT to make sure the // balance is actually there. It should always match `sfCoverAvailable`, so @@ -287,6 +287,14 @@ LoanBrokerCoverClawback::preclaim(PreclaimContext const& ctx) // Check if the vault asset issuer has the correct flags auto const sleIssuer = ctx.view.read(keylet::account(vaultAsset.getIssuer())); + if (!sleIssuer) + { + // LCOV_EXCL_START + JLOG(ctx.j.fatal()) << "Issuer account does not exist."; + return tefBAD_LEDGER; + // LCOV_EXCL_STOP + } + return std::visit( [&](T const&) { return preclaimHelper(ctx, *sleIssuer, clawAmount); @@ -321,7 +329,7 @@ LoanBrokerCoverClawback::doApply() determineClawAmount(*sleBroker, vaultAsset, amount); if (!findClawAmount) return tecINTERNAL; // LCOV_EXCL_LINE - STAmount const clawAmount = *findClawAmount; + STAmount const& clawAmount = *findClawAmount; // Just for paranoia's sake if (clawAmount.native()) return tecINTERNAL; // LCOV_EXCL_LINE diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp index c894df2c2b..b68cf46a00 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp @@ -81,7 +81,8 @@ LoanBrokerCoverDeposit::preclaim(PreclaimContext const& ctx) vaultAsset, FreezeHandling::fhZERO_IF_FROZEN, AuthHandling::ahZERO_IF_UNAUTHORIZED, - ctx.j) < amount) + ctx.j, + SpendableHandling::shFULL_BALANCE) < amount) return tecINSUFFICIENT_FUNDS; return tesSUCCESS; diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp index 4c0b3e9af5..830f9e26c1 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp @@ -48,6 +48,11 @@ LoanBrokerCoverWithdraw::preclaim(PreclaimContext const& ctx) auto const dstAcct = tx[~sfDestination].value_or(account); + if (isPseudoAccount(ctx.view, dstAcct)) + { + JLOG(ctx.j.warn()) << "Trying to withdraw into a pseudo-account."; + return tecPSEUDO_ACCOUNT; + } auto const sleBroker = ctx.view.read(keylet::loanbroker(brokerID)); if (!sleBroker) { diff --git a/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp b/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp index 76773037fa..227bad10a9 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp @@ -46,30 +46,6 @@ LoanBrokerDelete::preclaim(PreclaimContext const& ctx) JLOG(ctx.j.warn()) << "LoanBrokerDelete: Owner count is " << ownerCount; return tecHAS_OBLIGATIONS; } - if (auto const debtTotal = sleBroker->at(sfDebtTotal); - debtTotal != beast::zero) - { - // Any remaining debt should have been wiped out by the last Loan - // Delete. This check is purely defensive. - auto const vault = - ctx.view.read(keylet::vault(sleBroker->at(sfVaultID))); - if (!vault) - return tefINTERNAL; // LCOV_EXCL_LINE - auto const asset = vault->at(sfAsset); - auto const scale = getVaultScale(vault); - - auto const rounded = - roundToAsset(asset, debtTotal, scale, Number::towards_zero); - - if (rounded != beast::zero) - { - // LCOV_EXCL_START - JLOG(ctx.j.warn()) << "LoanBrokerDelete: Debt total is " - << debtTotal << ", which rounds to " << rounded; - return tecHAS_OBLIGATIONS; - // LCOV_EXCL_START - } - } auto const vault = ctx.view.read(keylet::vault(sleBroker->at(sfVaultID))); if (!vault) @@ -82,6 +58,26 @@ LoanBrokerDelete::preclaim(PreclaimContext const& ctx) Asset const asset = vault->at(sfAsset); + if (auto const debtTotal = sleBroker->at(sfDebtTotal); + debtTotal != beast::zero) + { + // Any remaining debt should have been wiped out by the last Loan + // Delete. This check is purely defensive. + auto const scale = getAssetsTotalScale(vault); + + auto const rounded = + roundToAsset(asset, debtTotal, scale, Number::towards_zero); + + if (rounded != beast::zero) + { + // LCOV_EXCL_START + JLOG(ctx.j.warn()) << "LoanBrokerDelete: Debt total is " + << debtTotal << ", which rounds to " << rounded; + return tecHAS_OBLIGATIONS; + // LCOV_EXCL_STOP + } + } + auto const coverAvailable = STAmount{asset, sleBroker->at(sfCoverAvailable)}; // If there are assets in the cover, broker will receive them on deletion. diff --git a/src/xrpld/app/tx/detail/LoanBrokerSet.cpp b/src/xrpld/app/tx/detail/LoanBrokerSet.cpp index 7b12a6cf39..0cbae4d779 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerSet.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerSet.cpp @@ -89,6 +89,18 @@ LoanBrokerSet::preclaim(PreclaimContext const& ctx) JLOG(ctx.j.warn()) << "Account is not the owner of the LoanBroker."; return tecNO_PERMISSION; } + + if (auto const debtMax = tx[~sfDebtMaximum]) + { + // Can't reduce the debt maximum below the current total debt + auto const currentDebtTotal = sleBroker->at(sfDebtTotal); + if (*debtMax != 0 && *debtMax < currentDebtTotal) + { + JLOG(ctx.j.warn()) + << "Cannot reduce DebtMaximum below current DebtTotal."; + return tecLIMIT_EXCEEDED; + } + } } else { @@ -105,6 +117,13 @@ LoanBrokerSet::preclaim(PreclaimContext const& ctx) } if (auto const ter = canAddHolding(ctx.view, sleVault->at(sfAsset))) return ter; + + if (auto const ter = checkFrozen( + ctx.view, sleVault->at(sfAccount), sleVault->at(sfAsset))) + { + JLOG(ctx.j.warn()) << "Vault pseudo-account is frozen."; + return ter; + } } return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/LoanDelete.cpp b/src/xrpld/app/tx/detail/LoanDelete.cpp index 659f0bba8b..3643e6331b 100644 --- a/src/xrpld/app/tx/detail/LoanDelete.cpp +++ b/src/xrpld/app/tx/detail/LoanDelete.cpp @@ -115,7 +115,7 @@ LoanDelete::doApply() roundToAsset( vaultSle->at(sfAsset), debtTotalProxy, - getVaultScale(vaultSle), + getAssetsTotalScale(vaultSle), Number::towards_zero) == beast::zero, "xrpl::LoanDelete::doApply", "last loan, remaining debt rounds to zero"); diff --git a/src/xrpld/app/tx/detail/LoanManage.cpp b/src/xrpld/app/tx/detail/LoanManage.cpp index 2d405f204b..bd0539ae4e 100644 --- a/src/xrpld/app/tx/detail/LoanManage.cpp +++ b/src/xrpld/app/tx/detail/LoanManage.cpp @@ -106,7 +106,7 @@ LoanManage::preclaim(PreclaimContext const& ctx) if (loanBrokerSle->at(sfOwner) != account) { JLOG(ctx.j.warn()) - << "LoanBroker for Loan does not belong to the account. LoanModify " + << "LoanBroker for Loan does not belong to the account. LoanManage " "can only be submitted by the Loan Broker."; return tecNO_PERMISSION; } @@ -158,7 +158,7 @@ LoanManage::defaultLoan( auto const minimumCover = tenthBipsOfValue(brokerDebtTotalProxy.value(), coverRateMinimum); // Round the liquidation amount up, too - return roundToAsset( + auto const covered = roundToAsset( vaultAsset, /* * This formula is from the XLS-66 spec, section 3.2.3.2 (State @@ -169,6 +169,9 @@ LoanManage::defaultLoan( tenthBipsOfValue(minimumCover, coverRateLiquidation), totalDefaultAmount), loanScale); + auto const coverAvailable = *brokerSle->at(sfCoverAvailable); + + return std::min(covered, coverAvailable); }(); auto const vaultDefaultAmount = totalDefaultAmount - defaultCovered; @@ -178,7 +181,7 @@ LoanManage::defaultLoan( // The vault may be at a different scale than the loan. Reduce rounding // errors during the accounting by rounding some of the values to that // scale. - auto const vaultScale = getVaultScale(vaultSle); + auto const vaultScale = getAssetsTotalScale(vaultSle); { // Decrease the Total Value of the Vault: @@ -223,11 +226,13 @@ LoanManage::defaultLoan( } if (*vaultAvailableProxy > *vaultTotalProxy) { - JLOG(j.warn()) << "Vault assets available must not be greater " - "than assets outstanding. Available: " - << *vaultAvailableProxy - << ", Total: " << *vaultTotalProxy; - return tecLIMIT_EXCEEDED; + // LCOV_EXCL_START + JLOG(j.fatal()) + << "Vault assets available must not be greater " + "than assets outstanding. Available: " + << *vaultAvailableProxy << ", Total: " << *vaultTotalProxy; + return tecINTERNAL; + // LCOV_EXCL_STOP } // The loss has been realized @@ -242,7 +247,11 @@ LoanManage::defaultLoan( return tefBAD_LEDGER; // LCOV_EXCL_STOP } - vaultLossUnrealizedProxy -= totalDefaultAmount; + adjustImpreciseNumber( + vaultLossUnrealizedProxy, + -totalDefaultAmount, + vaultAsset, + vaultScale); } view.update(vaultSle); } @@ -250,11 +259,9 @@ LoanManage::defaultLoan( // Update the LoanBroker object: { - auto const asset = *vaultSle->at(sfAsset); - // Decrease the Debt of the LoanBroker: adjustImpreciseNumber( - brokerDebtTotalProxy, -totalDefaultAmount, asset, vaultScale); + brokerDebtTotalProxy, -totalDefaultAmount, vaultAsset, vaultScale); // Decrease the First-Loss Capital Cover Available: auto coverAvailableProxy = brokerSle->at(sfCoverAvailable); if (coverAvailableProxy < defaultCovered) @@ -297,13 +304,20 @@ LoanManage::impairLoan( ApplyView& view, SLE::ref loanSle, SLE::ref vaultSle, + Asset const& vaultAsset, beast::Journal j) { Number const lossUnrealized = owedToVault(loanSle); + // The vault may be at a different scale than the loan. Reduce rounding + // errors during the accounting by rounding some of the values to that + // scale. + auto const vaultScale = getAssetsTotalScale(vaultSle); + // Update the Vault object(set "paper loss") auto vaultLossUnrealizedProxy = vaultSle->at(sfLossUnrealized); - vaultLossUnrealizedProxy += lossUnrealized; + adjustImpreciseNumber( + vaultLossUnrealizedProxy, lossUnrealized, vaultAsset, vaultScale); if (vaultLossUnrealizedProxy > vaultSle->at(sfAssetsTotal) - vaultSle->at(sfAssetsAvailable)) { @@ -329,13 +343,19 @@ LoanManage::impairLoan( return tesSUCCESS; } -TER +[[nodiscard]] TER LoanManage::unimpairLoan( ApplyView& view, SLE::ref loanSle, SLE::ref vaultSle, + Asset const& vaultAsset, beast::Journal j) { + // The vault may be at a different scale than the loan. Reduce rounding + // errors during the accounting by rounding some of the values to that + // scale. + auto const vaultScale = getAssetsTotalScale(vaultSle); + // Update the Vault object(clear "paper loss") auto vaultLossUnrealizedProxy = vaultSle->at(sfLossUnrealized); Number const lossReversed = owedToVault(loanSle); @@ -347,14 +367,18 @@ LoanManage::unimpairLoan( return tefBAD_LEDGER; // LCOV_EXCL_STOP } - vaultLossUnrealizedProxy -= lossReversed; + // Reverse the "paper loss" + adjustImpreciseNumber( + vaultLossUnrealizedProxy, -lossReversed, vaultAsset, vaultScale); + view.update(vaultSle); // Update the Loan object loanSle->clearFlag(lsfLoanImpaired); auto const paymentInterval = loanSle->at(sfPaymentInterval); auto const normalPaymentDueDate = - std::max(loanSle->at(sfPreviousPaymentDate), loanSle->at(sfStartDate)) + + std::max( + loanSle->at(sfPreviousPaymentDueDate), loanSle->at(sfStartDate)) + paymentInterval; if (!hasExpired(view, normalPaymentDueDate)) { @@ -396,22 +420,12 @@ LoanManage::doApply() // Valid flag combinations are checked in preflight. No flags is valid - // just a noop. if (tx.isFlag(tfLoanDefault)) - { - if (auto const ter = - defaultLoan(view, loanSle, brokerSle, vaultSle, vaultAsset, j_)) - return ter; - } - else if (tx.isFlag(tfLoanImpair)) - { - if (auto const ter = impairLoan(view, loanSle, vaultSle, j_)) - return ter; - } - else if (tx.isFlag(tfLoanUnimpair)) - { - if (auto const ter = unimpairLoan(view, loanSle, vaultSle, j_)) - return ter; - } - + return defaultLoan(view, loanSle, brokerSle, vaultSle, vaultAsset, j_); + if (tx.isFlag(tfLoanImpair)) + return impairLoan(view, loanSle, vaultSle, vaultAsset, j_); + if (tx.isFlag(tfLoanUnimpair)) + return unimpairLoan(view, loanSle, vaultSle, vaultAsset, j_); + // Noop, as described above. return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/LoanManage.h b/src/xrpld/app/tx/detail/LoanManage.h index 7a02c7a16f..155611580f 100644 --- a/src/xrpld/app/tx/detail/LoanManage.h +++ b/src/xrpld/app/tx/detail/LoanManage.h @@ -44,15 +44,17 @@ public: ApplyView& view, SLE::ref loanSle, SLE::ref vaultSle, + Asset const& vaultAsset, beast::Journal j); /** Helper function that might be needed by other transactors */ - static TER + [[nodiscard]] static TER unimpairLoan( ApplyView& view, SLE::ref loanSle, SLE::ref vaultSle, + Asset const& vaultAsset, beast::Journal j); TER diff --git a/src/xrpld/app/tx/detail/LoanPay.cpp b/src/xrpld/app/tx/detail/LoanPay.cpp index d34a766d70..f3973d9488 100644 --- a/src/xrpld/app/tx/detail/LoanPay.cpp +++ b/src/xrpld/app/tx/detail/LoanPay.cpp @@ -152,9 +152,7 @@ LoanPay::preclaim(PreclaimContext const& ctx) } auto const principalOutstanding = loanSle->at(sfPrincipalOutstanding); - TenthBips32 const interestRate{loanSle->at(sfInterestRate)}; auto const paymentRemaining = loanSle->at(sfPaymentRemaining); - TenthBips32 const lateInterestRate{loanSle->at(sfLateInterestRate)}; if (paymentRemaining == 0 || principalOutstanding == 0) { @@ -211,13 +209,14 @@ LoanPay::preclaim(PreclaimContext const& ctx) // Do not support "partial payments" - if the transaction says to pay X, // then the account must have X available, even if the loan payment takes // less. - if (auto const balance = accountSpendable( + if (auto const balance = accountHolds( ctx.view, account, asset, fhZERO_IF_FROZEN, ahZERO_IF_UNAUTHORIZED, - ctx.j); + ctx.j, + SpendableHandling::shFULL_BALANCE); balance < amount) { JLOG(ctx.j.warn()) << "Payment amount too large. Amount: " @@ -262,11 +261,12 @@ LoanPay::doApply() auto debtTotalProxy = brokerSle->at(sfDebtTotal); // Send the broker fee to the owner if they have sufficient cover available, - // _and_ if the owner can receive funds. If not, so as not to block the - // payment, add it to the cover balance (send it to the broker pseudo - // account). + // _and_ if the owner can receive funds + // _and_ if the broker is authorized to hold funds. If not, so as not to + // block the payment, add it to the cover balance (send it to the broker + // pseudo account). // - // Normally freeze status is checked in preflight, but we do it here to + // Normally freeze status is checked in preclaim, but we do it here to // avoid duplicating the check. It'll claim a fee either way. bool const sendBrokerFeeToOwner = [&]() { // Round the minimum required cover up to be conservative. This ensures @@ -278,7 +278,8 @@ LoanPay::doApply() asset, tenthBipsOfValue(debtTotalProxy.value(), coverRateMinimum), loanScale) && - !isDeepFrozen(view, brokerOwner, asset); + !isDeepFrozen(view, brokerOwner, asset) && + !requireAuth(view, asset, brokerOwner, AuthType::StrongAuth); }(); auto const brokerPayee = @@ -305,7 +306,12 @@ LoanPay::doApply() // change will be discarded. if (loanSle->isFlag(lsfLoanImpaired)) { - LoanManage::unimpairLoan(view, loanSle, vaultSle, j_); + if (auto const ret = + LoanManage::unimpairLoan(view, loanSle, vaultSle, asset, j_)) + { + JLOG(j_.fatal()) << "Failed to unimpair loan before payment."; + return ret; // LCOV_EXCL_LINE + } } LoanPaymentType const paymentType = [&tx]() { @@ -377,7 +383,7 @@ LoanPay::doApply() // The vault may be at a different scale than the loan. Reduce rounding // errors during the payment by rounding some of the values to that scale. - auto const vaultScale = assetsTotalProxy.value().exponent(); + auto const vaultScale = getAssetsTotalScale(vaultSle); auto const totalPaidToVaultRaw = paymentParts->principalPaid + paymentParts->interestPaid; @@ -421,35 +427,41 @@ LoanPay::doApply() // Vault object state changes view.update(vaultSle); - Number const assetsAvailableBefore = *assetsAvailableProxy; - Number const pseudoAccountBalanceBefore = accountHolds( - view, - vaultPseudoAccount, - asset, - FreezeHandling::fhIGNORE_FREEZE, - AuthHandling::ahIGNORE_AUTH, - j_); - +#if !NDEBUG { + Number const assetsAvailableBefore = *assetsAvailableProxy; + Number const pseudoAccountBalanceBefore = accountHolds( + view, + vaultPseudoAccount, + asset, + FreezeHandling::fhIGNORE_FREEZE, + AuthHandling::ahIGNORE_AUTH, + j_); + XRPL_ASSERT_PARTS( assetsAvailableBefore == pseudoAccountBalanceBefore, "xrpl::LoanPay::doApply", "vault pseudo balance agrees before"); + } +#endif - assetsAvailableProxy += totalPaidToVaultRounded; - assetsTotalProxy += paymentParts->valueChange; + assetsAvailableProxy += totalPaidToVaultRounded; + assetsTotalProxy += paymentParts->valueChange; - XRPL_ASSERT_PARTS( - *assetsAvailableProxy <= *assetsTotalProxy, - "xrpl::LoanPay::doApply", - "assets available must not be greater than assets outstanding"); + XRPL_ASSERT_PARTS( + *assetsAvailableProxy <= *assetsTotalProxy, + "xrpl::LoanPay::doApply", + "assets available must not be greater than assets outstanding"); - if (*assetsAvailableProxy > *assetsTotalProxy) - { - // LCOV_EXCL_START - return tecINTERNAL; - // LCOV_EXCL_STOP - } + if (*assetsAvailableProxy > *assetsTotalProxy) + { + // LCOV_EXCL_START + JLOG(j_.fatal()) << "Vault assets available must not be greater " + "than assets outstanding. Available: " + << *assetsAvailableProxy + << ", Total: " << *assetsTotalProxy; + return tecINTERNAL; + // LCOV_EXCL_STOP } JLOG(j_.debug()) << "total paid to vault raw: " << totalPaidToVaultRaw @@ -474,21 +486,34 @@ LoanPay::doApply() } #if !NDEBUG - auto const accountBalanceBefore = accountSpendable( - view, account_, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_); + auto const accountBalanceBefore = accountHolds( + view, + account_, + asset, + fhIGNORE_FREEZE, + ahIGNORE_AUTH, + j_, + SpendableHandling::shFULL_BALANCE); auto const vaultBalanceBefore = account_ == vaultPseudoAccount ? STAmount{asset, 0} - : accountSpendable( + : accountHolds( view, vaultPseudoAccount, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, - j_); + j_, + SpendableHandling::shFULL_BALANCE); auto const brokerBalanceBefore = account_ == brokerPayee ? STAmount{asset, 0} - : accountSpendable( - view, brokerPayee, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_); + : accountHolds( + view, + brokerPayee, + asset, + fhIGNORE_FREEZE, + ahIGNORE_AUTH, + j_, + SpendableHandling::shFULL_BALANCE); #endif if (totalPaidToVaultRounded != beast::zero) @@ -529,6 +554,7 @@ LoanPay::doApply() WaiveTransferFee::Yes)) return ter; +#if !NDEBUG Number const assetsAvailableAfter = *assetsAvailableProxy; Number const pseudoAccountBalanceAfter = accountHolds( view, @@ -542,22 +568,34 @@ LoanPay::doApply() "xrpl::LoanPay::doApply", "vault pseudo balance agrees after"); -#if !NDEBUG - auto const accountBalanceAfter = accountSpendable( - view, account_, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_); + auto const accountBalanceAfter = accountHolds( + view, + account_, + asset, + fhIGNORE_FREEZE, + ahIGNORE_AUTH, + j_, + SpendableHandling::shFULL_BALANCE); auto const vaultBalanceAfter = account_ == vaultPseudoAccount ? STAmount{asset, 0} - : accountSpendable( + : accountHolds( view, vaultPseudoAccount, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, - j_); + j_, + SpendableHandling::shFULL_BALANCE); auto const brokerBalanceAfter = account_ == brokerPayee ? STAmount{asset, 0} - : accountSpendable( - view, brokerPayee, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_); + : accountHolds( + view, + brokerPayee, + asset, + fhIGNORE_FREEZE, + ahIGNORE_AUTH, + j_, + SpendableHandling::shFULL_BALANCE); XRPL_ASSERT_PARTS( accountBalanceBefore + vaultBalanceBefore + brokerBalanceBefore == diff --git a/src/xrpld/app/tx/detail/LoanSet.cpp b/src/xrpld/app/tx/detail/LoanSet.cpp index e8fe76a48f..4c14cde421 100644 --- a/src/xrpld/app/tx/detail/LoanSet.cpp +++ b/src/xrpld/app/tx/detail/LoanSet.cpp @@ -88,10 +88,12 @@ LoanSet::preflight(PreflightContext const& ctx) if (auto const paymentInterval = tx[~sfPaymentInterval]; !validNumericMinimum(paymentInterval, LoanSet::minPaymentInterval)) return temINVALID; - - else if (!validNumericRange( - tx[~sfGracePeriod], - paymentInterval.value_or(LoanSet::defaultPaymentInterval))) + // Grace period is between min default value and payment interval + else if (auto const gracePeriod = tx[~sfGracePeriod]; // + !validNumericRange( + gracePeriod, + paymentInterval.value_or(LoanSet::defaultPaymentInterval), + defaultGracePeriod)) return temINVALID; // Copied from preflight2 @@ -282,6 +284,15 @@ LoanSet::preclaim(PreclaimContext const& ctx) if (!vault) // Should be impossible return tefBAD_LEDGER; // LCOV_EXCL_LINE + + if (vault->at(sfAssetsMaximum) != 0 && + vault->at(sfAssetsTotal) >= vault->at(sfAssetsMaximum)) + { + JLOG(ctx.j.warn()) + << "Vault at maximum assets limit. Can't add another loan."; + return tecLIMIT_EXCEEDED; + } + Asset const asset = vault->at(sfAsset); auto const vaultPseudo = vault->at(sfAccount); @@ -383,7 +394,7 @@ LoanSet::doApply() auto vaultAvailableProxy = vaultSle->at(sfAssetsAvailable); auto vaultTotalProxy = vaultSle->at(sfAssetsTotal); - auto const vaultScale = getVaultScale(vaultSle); + auto const vaultScale = getAssetsTotalScale(vaultSle); if (vaultAvailableProxy < principalRequested) { JLOG(j_.warn()) @@ -406,6 +417,21 @@ LoanSet::doApply() TenthBips16{brokerSle->at(sfManagementFeeRate)}, vaultScale); + LoanState const state = constructLoanState( + properties.loanState.valueOutstanding, + principalRequested, + properties.loanState.managementFeeDue); + + auto const vaultMaximum = *vaultSle->at(sfAssetsMaximum); + XRPL_ASSERT_PARTS( + vaultMaximum == 0 || vaultMaximum > *vaultTotalProxy, + "xrpl::LoanSet::doApply", + "Vault is below maximum limit"); + if (vaultMaximum != 0 && state.interestDue > vaultMaximum - vaultTotalProxy) + { + JLOG(j_.warn()) << "Loan would exceed the maximum assets of the vault"; + return tecLIMIT_EXCEEDED; + } // Check that relevant values won't lose precision. This is mostly only // relevant for IOU assets. { @@ -417,8 +443,8 @@ LoanSet::doApply() JLOG(j_.warn()) << field.f->getName() << " (" << *value << ") has too much precision. Total loan value is " - << properties.totalValueOutstanding << " with a scale of " - << properties.loanScale; + << properties.loanState.valueOutstanding + << " with a scale of " << properties.loanScale; return tecPRECISION_LOSS; } } @@ -434,22 +460,20 @@ LoanSet::doApply() return ret; // Check that the other computed values are valid - if (properties.managementFeeOwedToBroker < 0 || - properties.totalValueOutstanding <= 0 || + if (properties.loanState.managementFeeDue < 0 || + properties.loanState.valueOutstanding <= 0 || properties.periodicPayment <= 0) { // LCOV_EXCL_START JLOG(j_.warn()) - << "Computed loan properties are invalid. Does not compute."; + << "Computed loan properties are invalid. Does not compute." + << " Management fee: " << properties.loanState.managementFeeDue + << ". Total Value: " << properties.loanState.valueOutstanding + << ". PeriodicPayment: " << properties.periodicPayment; return tecINTERNAL; // LCOV_EXCL_STOP } - LoanState const state = constructLoanState( - properties.totalValueOutstanding, - principalRequested, - properties.managementFeeOwedToBroker); - auto const originationFee = tx[~sfLoanOriginationFee].value_or(Number{}); auto const loanAssetsToBorrower = principalRequested - originationFee; @@ -534,12 +558,12 @@ LoanSet::doApply() // ignore tecDUPLICATE. That means the holding already exists, // and is fine here return ter; - - if (auto const ter = requireAuth( - view, vaultAsset, brokerOwner, AuthType::StrongAuth)) - return ter; } + if (auto const ter = + requireAuth(view, vaultAsset, brokerOwner, AuthType::StrongAuth)) + return ter; + if (auto const ter = accountSendMulti( view, vaultPseudo, @@ -588,9 +612,10 @@ LoanSet::doApply() // Set dynamic / computed fields to their initial values loan->at(sfPrincipalOutstanding) = principalRequested; loan->at(sfPeriodicPayment) = properties.periodicPayment; - loan->at(sfTotalValueOutstanding) = properties.totalValueOutstanding; - loan->at(sfManagementFeeOutstanding) = properties.managementFeeOwedToBroker; - loan->at(sfPreviousPaymentDate) = 0; + loan->at(sfTotalValueOutstanding) = properties.loanState.valueOutstanding; + loan->at(sfManagementFeeOutstanding) = + properties.loanState.managementFeeDue; + loan->at(sfPreviousPaymentDueDate) = 0; loan->at(sfNextPaymentDueDate) = startDate + paymentInterval; loan->at(sfPaymentRemaining) = paymentTotal; view.insert(loan); diff --git a/src/xrpld/app/tx/detail/VaultDeposit.cpp b/src/xrpld/app/tx/detail/VaultDeposit.cpp index d9471a38f5..51b38afc36 100644 --- a/src/xrpld/app/tx/detail/VaultDeposit.cpp +++ b/src/xrpld/app/tx/detail/VaultDeposit.cpp @@ -115,16 +115,14 @@ VaultDeposit::preclaim(PreclaimContext const& ctx) !isTesSuccess(ter)) return ter; - // Asset issuer does not have any balance, they can just create funds by - // depositing in the vault. - if ((vaultAsset.native() || vaultAsset.getIssuer() != account) && - accountHolds( + if (accountHolds( ctx.view, account, vaultAsset, FreezeHandling::fhZERO_IF_FROZEN, AuthHandling::ahZERO_IF_UNAUTHORIZED, - ctx.j) < assets) + ctx.j, + SpendableHandling::shFULL_BALANCE) < assets) return tecINSUFFICIENT_FUNDS; return tesSUCCESS; diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index 2e9d5b35bf..d9ae357b1a 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -425,7 +425,7 @@ parseLoan(Json::Value const& params, Json::StaticString const fieldName) } auto const id = LedgerEntryHelpers::requiredUInt256( - params, jss::loan_broker_id, "malformedLoanBrokerID"); + params, jss::loan_broker_id, "malformedBroker"); if (!id) return Unexpected(id.error()); auto const seq = LedgerEntryHelpers::requiredUInt32( From 33f4c92b6122ef9072b189ff8e49d161229dd7c0 Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Tue, 13 Jan 2026 17:01:11 -0400 Subject: [PATCH 071/105] Expand Number to support the full integer range (#6025) - Refactor Number internals away from int64 to uint64 & a sign flag - ctors and accessors use `rep`. Very few things expose `internalrep`. - An exception is "unchecked" and the new "normalized", which explicitly take an internalrep. But with those special control flags, it's easier to distinguish and control when they are used. - For now, skip the larger mantissas in AMM transactions and tests - Remove trailing zeros from scientific notation Number strings - Update tests. This has the happy side effect of making some of the string representations _more_ consistent between the small and large mantissa ranges. - Add semi-automatic rounding of STNumbers based on Asset types - Create a new SField metadata enum, sMD_NeedsAsset, which indicates the field should be associated with an Asset so it can be rounded. - Add a new STTakesAsset intermediate class to handle the Asset association to a derived ST class. Currently only used in STNumber, but could be used by other types in the future. - Add "associateAsset" which takes an SLE and an Asset, finds the sMD_NeedsAsset fields, and associates the Asset to them. In the case of STNumber, that both stores the Asset, and rounds the value immediately. - Transactors only need to add a call to associateAsset _after_ all of the STNumbers have been set. Unfortunately, the inner workings of STObject do not do the association correctly with uninitialized fields. - When serializing an STNumber that has an Asset, round it before serializing. - Add an override of roundToAsset, which rounds a Number value in place to an Asset, but without any additional scale. - Update and fix a bunch of Loan-related tests to accommodate the expanded Number class. --------- Co-authored-by: Vito <5780819+Tapanito@users.noreply.github.com> --- include/xrpl/basics/Number.h | 529 ++++++- include/xrpl/protocol/AmountConversions.h | 2 +- include/xrpl/protocol/IOUAmount.h | 21 +- include/xrpl/protocol/Issue.h | 3 + include/xrpl/protocol/MPTIssue.h | 6 + include/xrpl/protocol/Protocol.h | 1 + include/xrpl/protocol/SField.h | 5 +- include/xrpl/protocol/STAmount.h | 71 +- include/xrpl/protocol/STNumber.h | 17 +- include/xrpl/protocol/STTakesAsset.h | 63 + include/xrpl/protocol/SystemParameters.h | 2 + include/xrpl/protocol/detail/sfields.macro | 20 +- src/libxrpl/basics/Number.cpp | 677 ++++++-- src/libxrpl/protocol/IOUAmount.cpp | 32 +- src/libxrpl/protocol/Issue.cpp | 6 + src/libxrpl/protocol/Rules.cpp | 14 +- src/libxrpl/protocol/STAmount.cpp | 39 +- src/libxrpl/protocol/STNumber.cpp | 94 +- src/libxrpl/protocol/STTakesAsset.cpp | 29 + src/test/app/AMMClawback_test.cpp | 5 +- src/test/app/AMMExtended_test.cpp | 42 +- src/test/app/AMM_test.cpp | 53 +- src/test/app/EscrowToken_test.cpp | 20 +- src/test/app/LendingHelpers_test.cpp | 15 +- src/test/app/LoanBroker_test.cpp | 89 +- src/test/app/Loan_test.cpp | 91 +- src/test/app/MPToken_test.cpp | 4 +- src/test/basics/IOUAmount_test.cpp | 31 +- src/test/basics/Number_test.cpp | 1402 ++++++++++++++--- src/test/jtx/AMMTest.h | 16 +- src/test/jtx/amount.h | 16 + src/test/jtx/impl/AMMTest.cpp | 7 +- src/test/protocol/STNumber_test.cpp | 59 +- src/test/rpc/GetAggregatePrice_test.cpp | 68 +- .../app/tx/detail/LoanBrokerCoverClawback.cpp | 4 + .../app/tx/detail/LoanBrokerCoverDeposit.cpp | 10 + .../app/tx/detail/LoanBrokerCoverWithdraw.cpp | 9 + src/xrpld/app/tx/detail/LoanBrokerDelete.cpp | 4 + src/xrpld/app/tx/detail/LoanBrokerSet.cpp | 66 +- src/xrpld/app/tx/detail/LoanBrokerSet.h | 3 + src/xrpld/app/tx/detail/LoanDelete.cpp | 10 +- src/xrpld/app/tx/detail/LoanManage.cpp | 8 +- src/xrpld/app/tx/detail/LoanPay.cpp | 11 + src/xrpld/app/tx/detail/LoanSet.cpp | 40 +- src/xrpld/app/tx/detail/Transactor.cpp | 6 +- src/xrpld/app/tx/detail/VaultClawback.cpp | 3 + src/xrpld/app/tx/detail/VaultCreate.cpp | 3 + src/xrpld/app/tx/detail/VaultDelete.cpp | 4 + src/xrpld/app/tx/detail/VaultDeposit.cpp | 4 + src/xrpld/app/tx/detail/VaultSet.cpp | 5 + src/xrpld/app/tx/detail/VaultWithdraw.cpp | 4 + src/xrpld/app/tx/detail/applySteps.cpp | 118 +- 52 files changed, 3151 insertions(+), 710 deletions(-) create mode 100644 include/xrpl/protocol/STTakesAsset.h create mode 100644 src/libxrpl/protocol/STTakesAsset.cpp diff --git a/include/xrpl/basics/Number.h b/include/xrpl/basics/Number.h index 4420530239..d1ef749784 100644 --- a/include/xrpl/basics/Number.h +++ b/include/xrpl/basics/Number.h @@ -1,8 +1,11 @@ #ifndef XRPL_BASICS_NUMBER_H_INCLUDED #define XRPL_BASICS_NUMBER_H_INCLUDED +#include + #include #include +#include #include #include @@ -13,42 +16,252 @@ class Number; std::string to_string(Number const& amount); +template +constexpr std::optional +logTen(T value) +{ + int log = 0; + while (value >= 10 && value % 10 == 0) + { + value /= 10; + ++log; + } + if (value == 1) + return log; + return std::nullopt; +} + template constexpr bool isPowerOfTen(T value) { - while (value >= 10 && value % 10 == 0) - value /= 10; - return value == 1; + return logTen(value).has_value(); } +/** MantissaRange defines a range for the mantissa of a normalized Number. + * + * The mantissa is in the range [min, max], where + * * min is a power of 10, and + * * max = min * 10 - 1. + * + * The mantissa_scale enum indicates whether the range is "small" or "large". + * This intentionally restricts the number of MantissaRanges that can be + * instantiated to two: one for each scale. + * + * The "small" scale is based on the behavior of STAmount for IOUs. It has a min + * value of 10^15, and a max value of 10^16-1. This was sufficient for + * uses before Lending Protocol was implemented, mostly related to AMM. + * + * However, it does not have sufficient precision to represent the full integer + * range of int64_t values (-2^63 to 2^63-1), which are needed for XRP and MPT + * values. The implementation of SingleAssetVault, and LendingProtocol need to + * represent those integer values accurately and precisely, both for the + * STNumber field type, and for internal calculations. That necessitated the + * "large" scale. + * + * The "large" scale is intended to represent all values that can be represented + * by an STAmount - IOUs, XRP, and MPTs. It has a min value of 10^18, and a max + * value of 10^19-1. + * + * Note that if the mentioned amendments are eventually retired, this class + * should be left in place, but the "small" scale option should be removed. This + * will allow for future expansion beyond 64-bits if it is ever needed. + */ +struct MantissaRange +{ + using rep = std::uint64_t; + enum mantissa_scale { small, large }; + + explicit constexpr MantissaRange(mantissa_scale scale_) + : min(getMin(scale_)) + , max(min * 10 - 1) + , log(logTen(min).value_or(-1)) + , scale(scale_) + { + } + + rep min; + rep max; + int log; + mantissa_scale scale; + +private: + static constexpr rep + getMin(mantissa_scale scale_) + { + switch (scale_) + { + case small: + return 1'000'000'000'000'000ULL; + case large: + return 1'000'000'000'000'000'000ULL; + default: + // Since this can never be called outside a non-constexpr + // context, this throw assures that the build fails if an + // invalid scale is used. + throw std::runtime_error("Unknown mantissa scale"); + } + } +}; + +// Like std::integral, but only 64-bit integral types. +template +concept Integral64 = + std::is_same_v || std::is_same_v; + +/** Number is a floating point type that can represent a wide range of values. + * + * It can represent all values that can be represented by an STAmount - + * regardless of asset type - XRPAmount, MPTAmount, and IOUAmount, with at least + * as much precision as those types require. + * + * ---- Internal Representation ---- + * + * Internally, Number is represented with three values: + * 1. a bool sign flag, + * 2. a std::uint64_t mantissa, + * 3. an int exponent. + * + * The internal mantissa is an unsigned integer in the range defined by the + * current MantissaRange. The exponent is an integer in the range + * [minExponent, maxExponent]. + * + * See the description of MantissaRange for more details on the ranges. + * + * A non-zero mantissa is (almost) always normalized, meaning it and the + * exponent are grown or shrunk until the mantissa is in the range + * [MantissaRange.min, MantissaRange.max]. + * + * Note: + * 1. Normalization can be disabled by using the "unchecked" ctor tag. This + * should only be used at specific conversion points, some constexpr + * values, and in unit tests. + * 2. The max of the "large" range, 10^19-1, is the largest 10^X-1 value that + * fits in an unsigned 64-bit number. (10^19-1 < 2^64-1 and + * 10^20-1 > 2^64-1). This avoids under- and overflows. + * + * ---- External Interface ---- + * + * The external interface of Number consists of a std::int64_t mantissa, which + * is restricted to 63-bits, and an int exponent, which must be in the range + * [minExponent, maxExponent]. The range of the mantissa depends on which + * MantissaRange is currently active. For the "short" range, the mantissa will + * be between 10^15 and 10^16-1. For the "large" range, the mantissa will be + * between -(2^63-1) and 2^63-1. As noted above, the "large" range is needed to + * represent the full range of valid XRP and MPT integer values accurately. + * + * Note: + * 1. 2^63-1 is between 10^18 and 10^19-1, which are the limits of the "large" + * mantissa range. + * 2. The functions mantissa() and exponent() return the external view of the + * Number value, specifically using a signed 63-bit mantissa. This may + * require altering the internal representation to fit into that range + * before the value is returned. The interface guarantees consistency of + * the two values. + * 3. Number cannot represent -2^63 (std::numeric_limits::min()) + * as an exact integer, but it doesn't need to, because all asset values + * on-ledger are non-negative. This is due to implementation details of + * several operations which use unsigned arithmetic internally. This is + * sufficient to represent all valid XRP values (where the absolute value + * can not exceed INITIAL_XRP: 10^17), and MPT values (where the absolute + * value can not exceed maxMPTokenAmount: 2^63-1). + * + * ---- Mantissa Range Switching ---- + * + * The mantissa range may be changed at runtime via setMantissaScale(). The + * default mantissa range is "large". The range is updated whenever transaction + * processing begins, based on whether SingleAssetVault or LendingProtocol are + * enabled. If either is enabled, the mantissa range is set to "large". If not, + * it is set to "small", preserving backward compatibility and correct + * "amendment-gating". + * + * It is extremely unlikely that any more calls to setMantissaScale() will be + * needed outside of unit tests. + * + * ---- Usage With Different Ranges ---- + * + * Outside of unit tests, and existing checks, code that uses Number should not + * know or care which mantissa range is active. + * + * The results of computations using Numbers with a small mantissa may differ + * from computations using Numbers with a large mantissa, specifically as it + * effects the results after rounding. That is why the large mantissa range is + * amendment gated in transaction processing. + * + * It is extremely unlikely that any more calls to getMantissaScale() will be + * needed outside of unit tests. + * + * Code that uses Number should not assume or check anything about the + * mantissa() or exponent() except that they fit into the "large" range + * specified in the "External Interface" section. + * + * ----- Unit Tests ----- + * + * Within unit tests, it may be useful to explicitly switch between the two + * ranges, or to check which range is active when checking the results of + * computations. If the test is doing the math directly, the + * set/getMantissaScale() functions may be most appropriate. However, if the + * test has anything to do with transaction processing, it should enable or + * disable the amendments that control the mantissa range choice + * (SingleAssetVault and LendingProtocol), and/or check if either of those + * amendments are enabled to determine which result to expect. + * + */ class Number { using rep = std::int64_t; - rep mantissa_{0}; + using internalrep = MantissaRange::rep; + + bool negative_{false}; + internalrep mantissa_{0}; int exponent_{std::numeric_limits::lowest()}; public: - // The range for the mantissa when normalized - constexpr static std::int64_t minMantissa = 1'000'000'000'000'000LL; - static_assert(isPowerOfTen(minMantissa)); - constexpr static std::int64_t maxMantissa = minMantissa * 10 - 1; - static_assert(maxMantissa == 9'999'999'999'999'999LL); - // The range for the exponent when normalized constexpr static int minExponent = -32768; constexpr static int maxExponent = 32768; + constexpr static internalrep maxRep = std::numeric_limits::max(); + static_assert(maxRep == 9'223'372'036'854'775'807); + static_assert(-maxRep == std::numeric_limits::min() + 1); + + // May need to make unchecked private struct unchecked { explicit unchecked() = default; }; + // Like unchecked, normalized is used with the ctors that take an + // internalrep mantissa. Unlike unchecked, those ctors will normalize the + // value. + // Only unit tests are expected to use this class + struct normalized + { + explicit normalized() = default; + }; + explicit constexpr Number() = default; Number(rep mantissa); explicit Number(rep mantissa, int exponent); - explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept; + explicit constexpr Number( + bool negative, + internalrep mantissa, + int exponent, + unchecked) noexcept; + // Assume unsigned values are... unsigned. i.e. positive + explicit constexpr Number( + internalrep mantissa, + int exponent, + unchecked) noexcept; + // Only unit tests are expected to use this ctor + explicit Number( + bool negative, + internalrep mantissa, + int exponent, + normalized); + // Assume unsigned values are... unsigned. i.e. positive + explicit Number(internalrep mantissa, int exponent, normalized); constexpr rep mantissa() const noexcept; @@ -78,11 +291,11 @@ public: Number& operator/=(Number const& x); - static constexpr Number + static Number min() noexcept; - static constexpr Number + static Number max() noexcept; - static constexpr Number + static Number lowest() noexcept; /** Conversions to Number are implicit and conversions away from Number @@ -96,7 +309,8 @@ public: friend constexpr bool operator==(Number const& x, Number const& y) noexcept { - return x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_; + return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ && + x.exponent_ == y.exponent_; } friend constexpr bool @@ -110,8 +324,8 @@ public: { // If the two amounts have different signs (zero is treated as positive) // then the comparison is true iff the left is negative. - bool const lneg = x.mantissa_ < 0; - bool const rneg = y.mantissa_ < 0; + bool const lneg = x.negative_; + bool const rneg = y.negative_; if (lneg != rneg) return lneg; @@ -139,7 +353,7 @@ public: constexpr int signum() const noexcept { - return (mantissa_ < 0) ? -1 : (mantissa_ ? 1 : 0); + return negative_ ? -1 : (mantissa_ ? 1 : 0); } Number @@ -169,6 +383,15 @@ public: return os << to_string(x); } + friend std::string + to_string(Number const& amount); + + friend Number + root(Number f, unsigned d); + + friend Number + root2(Number f); + // Thread local rounding control. Default is to_nearest enum rounding_mode { to_nearest, towards_zero, downward, upward }; static rounding_mode @@ -177,44 +400,206 @@ public: static rounding_mode setround(rounding_mode mode); + /** Returns which mantissa scale is currently in use for normalization. + * + * If you think you need to call this outside of unit tests, no you don't. + */ + static MantissaRange::mantissa_scale + getMantissaScale(); + /** Changes which mantissa scale is used for normalization. + * + * If you think you need to call this outside of unit tests, no you don't. + */ + static void + setMantissaScale(MantissaRange::mantissa_scale scale); + + inline static internalrep + minMantissa() + { + return range_.get().min; + } + + inline static internalrep + maxMantissa() + { + return range_.get().max; + } + + inline static int + mantissaLog() + { + return range_.get().log; + } + + /// oneSmall is needed because the ranges are private + constexpr static Number + oneSmall(); + /// oneLarge is needed because the ranges are private + constexpr static Number + oneLarge(); + + // And one is needed because it needs to choose between oneSmall and + // oneLarge based on the current range + static Number + one(); + + template + [[nodiscard]] + std::pair + normalizeToRange(T minMantissa, T maxMantissa) const; + private: static thread_local rounding_mode mode_; + // The available ranges for mantissa + + constexpr static MantissaRange smallRange{MantissaRange::small}; + static_assert(isPowerOfTen(smallRange.min)); + static_assert(smallRange.min == 1'000'000'000'000'000LL); + static_assert(smallRange.max == 9'999'999'999'999'999LL); + static_assert(smallRange.log == 15); + static_assert(smallRange.min < maxRep); + static_assert(smallRange.max < maxRep); + constexpr static MantissaRange largeRange{MantissaRange::large}; + static_assert(isPowerOfTen(largeRange.min)); + static_assert(largeRange.min == 1'000'000'000'000'000'000ULL); + static_assert(largeRange.max == internalrep(9'999'999'999'999'999'999ULL)); + static_assert(largeRange.log == 18); + static_assert(largeRange.min < maxRep); + static_assert(largeRange.max > maxRep); + + // The range for the mantissa when normalized. + // Use reference_wrapper to avoid making copies, and prevent accidentally + // changing the values inside the range. + static thread_local std::reference_wrapper range_; void normalize(); - constexpr bool + + /** Normalize Number components to an arbitrary range. + * + * min/maxMantissa are parameters because this function is used by both + * normalize(), which reads from range_, and by normalizeToRange, + * which is public and can accept an arbitrary range from the caller. + */ + template + static void + normalize( + bool& negative, + T& mantissa, + int& exponent, + internalrep const& minMantissa, + internalrep const& maxMantissa); + + template + friend void + doNormalize( + bool& negative, + T& mantissa_, + int& exponent_, + MantissaRange::rep const& minMantissa, + MantissaRange::rep const& maxMantissa); + + bool isnormal() const noexcept; + // Copy the number, but modify the exponent by "exponentDelta". Because the + // mantissa doesn't change, the result will be "mostly" normalized, but the + // exponent could go out of range, so it will be checked. + Number + shiftExponent(int exponentDelta) const; + + // Safely convert rep (int64) mantissa to internalrep (uint64). If the rep + // is negative, returns the positive value. This takes a little extra work + // because converting std::numeric_limits::min() flirts with + // UB, and can vary across compilers. + static internalrep + externalToInternal(rep mantissa); + class Guard; }; +inline constexpr Number::Number( + bool negative, + internalrep mantissa, + int exponent, + unchecked) noexcept + : negative_(negative), mantissa_{mantissa}, exponent_{exponent} +{ +} + +inline constexpr Number::Number( + internalrep mantissa, + int exponent, + unchecked) noexcept + : Number(false, mantissa, exponent, unchecked{}) +{ +} + constexpr static Number numZero{}; -inline constexpr Number::Number(rep mantissa, int exponent, unchecked) noexcept - : mantissa_{mantissa}, exponent_{exponent} +inline Number::Number( + bool negative, + internalrep mantissa, + int exponent, + normalized) + : Number(negative, mantissa, exponent, unchecked{}) +{ + normalize(); +} + +inline Number::Number(internalrep mantissa, int exponent, normalized) + : Number(false, mantissa, exponent, normalized{}) { } inline Number::Number(rep mantissa, int exponent) - : mantissa_{mantissa}, exponent_{exponent} + : Number(mantissa < 0, externalToInternal(mantissa), exponent, normalized{}) { - normalize(); } inline Number::Number(rep mantissa) : Number{mantissa, 0} { } +/** Returns the mantissa of the external view of the Number. + * + * Please see the "---- External Interface ----" section of the class + * documentation for an explanation of why the internal value may be modified. + */ inline constexpr Number::rep Number::mantissa() const noexcept { - return mantissa_; + auto m = mantissa_; + if (m > maxRep) + { + XRPL_ASSERT_PARTS( + !isnormal() || (m % 10 == 0 && m / 10 <= maxRep), + "xrpl::Number::mantissa", + "large normalized mantissa has no remainder"); + m /= 10; + } + auto const sign = negative_ ? -1 : 1; + return sign * static_cast(m); } +/** Returns the exponent of the external view of the Number. + * + * Please see the "---- External Interface ----" section of the class + * documentation for an explanation of why the internal value may be modified. + */ inline constexpr int Number::exponent() const noexcept { - return exponent_; + auto e = exponent_; + if (mantissa_ > maxRep) + { + XRPL_ASSERT_PARTS( + !isnormal() || (mantissa_ % 10 == 0 && mantissa_ / 10 <= maxRep), + "xrpl::Number::exponent", + "large normalized mantissa has no remainder"); + ++e; + } + return e; } inline constexpr Number @@ -226,15 +611,17 @@ Number::operator+() const noexcept inline constexpr Number Number::operator-() const noexcept { + if (mantissa_ == 0) + return Number{}; auto x = *this; - x.mantissa_ = -x.mantissa_; + x.negative_ = !x.negative_; return x; } inline Number& Number::operator++() { - *this += Number{1000000000000000, -15, unchecked{}}; + *this += one(); return *this; } @@ -249,7 +636,7 @@ Number::operator++(int) inline Number& Number::operator--() { - *this -= Number{1000000000000000, -15, unchecked{}}; + *this -= one(); return *this; } @@ -299,30 +686,54 @@ operator/(Number const& x, Number const& y) return z; } -inline constexpr Number +inline Number Number::min() noexcept { - return Number{minMantissa, minExponent, unchecked{}}; + return Number{false, range_.get().min, minExponent, unchecked{}}; } -inline constexpr Number +inline Number Number::max() noexcept { - return Number{maxMantissa, maxExponent, unchecked{}}; + return Number{ + false, std::min(range_.get().max, maxRep), maxExponent, unchecked{}}; } -inline constexpr Number +inline Number Number::lowest() noexcept { - return -Number{maxMantissa, maxExponent, unchecked{}}; + return Number{ + true, std::min(range_.get().max, maxRep), maxExponent, unchecked{}}; } -inline constexpr bool +inline bool Number::isnormal() const noexcept { - auto const abs_m = mantissa_ < 0 ? -mantissa_ : mantissa_; - return minMantissa <= abs_m && abs_m <= maxMantissa && - minExponent <= exponent_ && exponent_ <= maxExponent; + MantissaRange const& range = range_; + auto const abs_m = mantissa_; + return *this == Number{} || + (range.min <= abs_m && abs_m <= range.max && + (abs_m <= maxRep || abs_m % 10 == 0) && minExponent <= exponent_ && + exponent_ <= maxExponent); +} + +template +std::pair +Number::normalizeToRange(T minMantissa, T maxMantissa) const +{ + bool negative = negative_; + internalrep mantissa = mantissa_; + int exponent = exponent_; + + if constexpr (std::is_unsigned_v) + XRPL_ASSERT_PARTS( + !negative, + "xrpl::Number::normalizeToRange", + "Number is non-negative for unsigned range."); + Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa); + + auto const sign = negative ? -1 : 1; + return std::make_pair(static_cast(sign * mantissa), exponent); } inline constexpr Number @@ -364,6 +775,20 @@ squelch(Number const& x, Number const& limit) noexcept return x; } +inline std::string +to_string(MantissaRange::mantissa_scale const& scale) +{ + switch (scale) + { + case MantissaRange::small: + return "small"; + case MantissaRange::large: + return "large"; + default: + throw std::runtime_error("Bad scale"); + } +} + class saveNumberRoundMode { Number::rounding_mode mode_; @@ -402,6 +827,34 @@ public: operator=(NumberRoundModeGuard const&) = delete; }; +/** Sets the new scale and restores the old scale when it leaves scope. + * + * If you think you need to use this class outside of unit tests, no you don't. + * + */ +class NumberMantissaScaleGuard +{ + MantissaRange::mantissa_scale const saved_; + +public: + explicit NumberMantissaScaleGuard( + MantissaRange::mantissa_scale scale) noexcept + : saved_{Number::getMantissaScale()} + { + Number::setMantissaScale(scale); + } + + ~NumberMantissaScaleGuard() + { + Number::setMantissaScale(saved_); + } + + NumberMantissaScaleGuard(NumberMantissaScaleGuard const&) = delete; + + NumberMantissaScaleGuard& + operator=(NumberMantissaScaleGuard const&) = delete; +}; + } // namespace xrpl #endif // XRPL_BASICS_NUMBER_H_INCLUDED diff --git a/include/xrpl/protocol/AmountConversions.h b/include/xrpl/protocol/AmountConversions.h index 195e373fa0..2cdccecabb 100644 --- a/include/xrpl/protocol/AmountConversions.h +++ b/include/xrpl/protocol/AmountConversions.h @@ -121,7 +121,7 @@ toAmount( { if (isXRP(issue)) return STAmount(issue, static_cast(n)); - return STAmount(issue, n.mantissa(), n.exponent()); + return STAmount(issue, n); } else { diff --git a/include/xrpl/protocol/IOUAmount.h b/include/xrpl/protocol/IOUAmount.h index c04cb5cf70..405de18e29 100644 --- a/include/xrpl/protocol/IOUAmount.h +++ b/include/xrpl/protocol/IOUAmount.h @@ -26,8 +26,10 @@ class IOUAmount : private boost::totally_ordered, private boost::additive { private: - std::int64_t mantissa_; - int exponent_; + using mantissa_type = std::int64_t; + using exponent_type = int; + mantissa_type mantissa_; + exponent_type exponent_; /** Adjusts the mantissa and exponent to the proper range. @@ -38,11 +40,14 @@ private: void normalize(); + static IOUAmount + fromNumber(Number const& number); + public: IOUAmount() = default; explicit IOUAmount(Number const& other); IOUAmount(beast::Zero); - IOUAmount(std::int64_t mantissa, int exponent); + IOUAmount(mantissa_type mantissa, exponent_type exponent); IOUAmount& operator=(beast::Zero); @@ -71,10 +76,10 @@ public: int signum() const noexcept; - int + exponent_type exponent() const noexcept; - std::int64_t + mantissa_type mantissa() const noexcept; static IOUAmount @@ -92,7 +97,7 @@ inline IOUAmount::IOUAmount(beast::Zero) *this = beast::zero; } -inline IOUAmount::IOUAmount(std::int64_t mantissa, int exponent) +inline IOUAmount::IOUAmount(mantissa_type mantissa, exponent_type exponent) : mantissa_(mantissa), exponent_(exponent) { normalize(); @@ -149,13 +154,13 @@ IOUAmount::signum() const noexcept return (mantissa_ < 0) ? -1 : (mantissa_ ? 1 : 0); } -inline int +inline IOUAmount::exponent_type IOUAmount::exponent() const noexcept { return exponent_; } -inline std::int64_t +inline IOUAmount::mantissa_type IOUAmount::mantissa() const noexcept { return mantissa_; diff --git a/include/xrpl/protocol/Issue.h b/include/xrpl/protocol/Issue.h index 519d7a96f3..a76b7a8316 100644 --- a/include/xrpl/protocol/Issue.h +++ b/include/xrpl/protocol/Issue.h @@ -37,6 +37,9 @@ public: bool native() const; + bool + integral() const; + friend constexpr std::weak_ordering operator<=>(Issue const& lhs, Issue const& rhs); }; diff --git a/include/xrpl/protocol/MPTIssue.h b/include/xrpl/protocol/MPTIssue.h index b89b59ee0d..ca81548a29 100644 --- a/include/xrpl/protocol/MPTIssue.h +++ b/include/xrpl/protocol/MPTIssue.h @@ -46,6 +46,12 @@ public: { return false; } + + bool + integral() const + { + return true; + } }; constexpr bool diff --git a/include/xrpl/protocol/Protocol.h b/include/xrpl/protocol/Protocol.h index 0c72b80de4..43be9d3b45 100644 --- a/include/xrpl/protocol/Protocol.h +++ b/include/xrpl/protocol/Protocol.h @@ -233,6 +233,7 @@ std::size_t constexpr maxMPTokenMetadataLength = 1024; /** The maximum amount of MPTokenIssuance */ std::uint64_t constexpr maxMPTokenAmount = 0x7FFF'FFFF'FFFF'FFFFull; +static_assert(Number::maxRep >= maxMPTokenAmount); /** The maximum length of Data payload */ std::size_t constexpr maxDataPayloadLength = 256; diff --git a/include/xrpl/protocol/SField.h b/include/xrpl/protocol/SField.h index b1d353196d..7f404b4d5f 100644 --- a/include/xrpl/protocol/SField.h +++ b/include/xrpl/protocol/SField.h @@ -135,7 +135,10 @@ public: sMD_Always = 0x10, // value when node containing it is affected at all sMD_BaseTen = 0x20, // value is treated as base 10, overriding behavior sMD_PseudoAccount = 0x40, // if this field is set in an ACCOUNT_ROOT - // _only_, then it is a pseudo-account + // _only_, then it is a pseudo-account + sMD_NeedsAsset = 0x80, // This field needs to be associated with an + // asset before it is serialized as a ledger + // object. Intended for STNumber. sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create }; diff --git a/include/xrpl/protocol/STAmount.h b/include/xrpl/protocol/STAmount.h index 79cbf51436..4d86aed2ec 100644 --- a/include/xrpl/protocol/STAmount.h +++ b/include/xrpl/protocol/STAmount.h @@ -138,7 +138,7 @@ public: template STAmount(A const& asset, Number const& number) - : STAmount(asset, number.mantissa(), number.exponent()) + : STAmount(fromNumber(asset, number)) { } @@ -282,6 +282,10 @@ public: mpt() const; private: + template + static STAmount + fromNumber(A const& asset, Number const& number); + static std::unique_ptr construct(SerialIter&, SField const& name); @@ -345,10 +349,19 @@ STAmount::STAmount( , mIsNegative(negative) { // mValue is uint64, but needs to fit in the range of int64 - XRPL_ASSERT( - mValue <= std::numeric_limits::max(), - "xrpl::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : " - "maximum mantissa input"); + if (Number::getMantissaScale() == MantissaRange::small) + { + XRPL_ASSERT( + mValue <= std::numeric_limits::max(), + "xrpl::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : " + "maximum mantissa input"); + } + else + { + if (integral() && mValue > std::numeric_limits::max()) + throw std::overflow_error( + "STAmount mantissa is too large " + std::to_string(mantissa)); + } canonicalize(); } @@ -542,14 +555,23 @@ STAmount::operator=(XRPAmount const& amount) return *this; } -inline STAmount& -STAmount::operator=(Number const& number) +template +inline STAmount +STAmount::fromNumber(A const& a, Number const& number) { - mIsNegative = number.mantissa() < 0; - mValue = mIsNegative ? -number.mantissa() : number.mantissa(); - mOffset = number.exponent(); - canonicalize(); - return *this; + bool const negative = number.mantissa() < 0; + Number const working{negative ? -number : number}; + Asset asset{a}; + if (asset.integral()) + { + std::uint64_t const intValue = static_cast(working); + return STAmount{asset, intValue, 0, negative}; + } + + auto const [mantissa, exponent] = + working.normalizeToRange(cMinValue, cMaxValue); + + return STAmount{asset, mantissa, exponent, negative}; } inline void @@ -699,17 +721,32 @@ getRate(STAmount const& offerOut, STAmount const& offerIn); * @param rounding Optional Number rounding mode * */ -STAmount +[[nodiscard]] STAmount roundToScale( STAmount const& value, std::int32_t scale, Number::rounding_mode rounding = Number::getround()); +/** Round an arbitrary precision Number IN PLACE to the precision of a given + * Asset. + * + * This is used to ensure that calculations do not collect dust for IOUs, or + * fractional amounts for the integral types XRP and MPT. + * + * @param asset The relevant asset + * @param value The lvalue to be rounded + */ +template +void +roundToAsset(A const& asset, Number& value) +{ + value = STAmount{asset, value}; +} + /** Round an arbitrary precision Number to the precision of a given Asset. * - * This is used to ensure that calculations do not collect dust beyond the - * precision of the reference value for IOUs, or fractional amounts for the - * integral types XRP and MPT. + * This is used to ensure that calculations do not collect dust beyond specified + * scale for IOUs, or fractional amounts for the integral types XRP and MPT. * * @param asset The relevant asset * @param value The value to be rounded @@ -718,7 +755,7 @@ roundToScale( * @param rounding Optional Number rounding mode */ template -Number +[[nodiscard]] Number roundToAsset( A const& asset, Number const& value, diff --git a/include/xrpl/protocol/STNumber.h b/include/xrpl/protocol/STNumber.h index dfdb16af93..39b0c3b042 100644 --- a/include/xrpl/protocol/STNumber.h +++ b/include/xrpl/protocol/STNumber.h @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -19,8 +20,19 @@ namespace xrpl { * it can represent a value of any token type (XRP, IOU, or MPT) * without paying the storage cost of duplicating asset information * that may be deduced from the context. + * + * STNumber derives from STTakesAsset, so that it can be associated with the + * related Asset during transaction processing. Which asset is relevant depends + * on the object and transaction. As of this writing, only Vault, LoanBroker, + * and Loan objects use STNumber fields. All of those fields represent amounts + * of the Vault's Asset, so they should be associated with the Vault's Asset. + * + * e.g. + * associateAsset(*loanSle, asset); + * associateAsset(*brokerSle, asset); + * associateAsset(*vaultSle, asset); */ -class STNumber : public STBase, public CountedObject +class STNumber : public STTakesAsset, public CountedObject { private: Number value_; @@ -56,6 +68,9 @@ public: bool isDefault() const override; + void + associateAsset(Asset const& a) override; + operator Number() const { return value_; diff --git a/include/xrpl/protocol/STTakesAsset.h b/include/xrpl/protocol/STTakesAsset.h new file mode 100644 index 0000000000..767223b97d --- /dev/null +++ b/include/xrpl/protocol/STTakesAsset.h @@ -0,0 +1,63 @@ +#ifndef XRPL_PROTOCOL_STTAKESASSET_H_INCLUDED +#define XRPL_PROTOCOL_STTAKESASSET_H_INCLUDED + +#include +#include + +namespace xrpl { + +/** Intermediate class for any STBase-derived class to store an Asset. + * + * In the class definition, this class should be specified as a base class + * _instead_ of STBase. + * + * Specifically, the Asset is only stored and used at runtime. It should not be + * serialized to the ledger. + * + * The derived class decides what to do with the Asset, and when. It will not + * necessarily be set at any given time. As of this writing, only STNumber uses + * it to round the stored Number to the Asset's precision both when associated, + * and when serializing the Number. + */ +class STTakesAsset : public STBase +{ +protected: + std::optional asset_; + +public: + using STBase::STBase; + using STBase::operator=; + + virtual void + associateAsset(Asset const& a); +}; + +inline void +STTakesAsset::associateAsset(Asset const& a) +{ + asset_.emplace(a); +} + +class STLedgerEntry; + +/** Associate an Asset with all sMD_NeedsAsset fields in a ledger entry. + * + * This function iterates over all fields in the given ledger entry. For each + * field that is set and has the SField::sMD_NeedsAsset metadata flag, it calls + * `associateAsset` on that field with the given Asset. Such field must be + * derived from STTakesAsset - if it is not, the conversion will throw. + * + * Typically, associateAsset should be called near the end of doApply() of any + * Transactor classes on the SLEs of any new or modified ledger entries + * containing STNumber fields, after doing all of the modifications t the SLEs. + * + * @param sle The ledger entry whose fields will be updated. + * @param asset The Asset to associate with the relevant fields. + * + */ +void +associateAsset(STLedgerEntry& sle, Asset const& asset); + +} // namespace xrpl + +#endif diff --git a/include/xrpl/protocol/SystemParameters.h b/include/xrpl/protocol/SystemParameters.h index c0732bc9fe..c2f66e9ea1 100644 --- a/include/xrpl/protocol/SystemParameters.h +++ b/include/xrpl/protocol/SystemParameters.h @@ -23,6 +23,8 @@ systemName() /** Number of drops in the genesis account. */ constexpr XRPAmount INITIAL_XRP{100'000'000'000 * DROPS_PER_XRP}; +static_assert(INITIAL_XRP.drops() == 100'000'000'000'000'000); +static_assert(Number::maxRep >= INITIAL_XRP.drops()); /** Returns true if the amount does not exceed the initial XRP in existence. */ inline bool diff --git a/include/xrpl/protocol/detail/sfields.macro b/include/xrpl/protocol/detail/sfields.macro index d0736469e4..712cf568af 100644 --- a/include/xrpl/protocol/detail/sfields.macro +++ b/include/xrpl/protocol/detail/sfields.macro @@ -207,22 +207,22 @@ TYPED_SFIELD(sfLoanID, UINT256, 38) // number (common) TYPED_SFIELD(sfNumber, NUMBER, 1) -TYPED_SFIELD(sfAssetsAvailable, NUMBER, 2) -TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3) -TYPED_SFIELD(sfAssetsTotal, NUMBER, 4) -TYPED_SFIELD(sfLossUnrealized, NUMBER, 5) -TYPED_SFIELD(sfDebtTotal, NUMBER, 6) -TYPED_SFIELD(sfDebtMaximum, NUMBER, 7) -TYPED_SFIELD(sfCoverAvailable, NUMBER, 8) +TYPED_SFIELD(sfAssetsAvailable, NUMBER, 2, SField::sMD_NeedsAsset | SField::sMD_Default) +TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3, SField::sMD_NeedsAsset | SField::sMD_Default) +TYPED_SFIELD(sfAssetsTotal, NUMBER, 4, SField::sMD_NeedsAsset | SField::sMD_Default) +TYPED_SFIELD(sfLossUnrealized, NUMBER, 5, SField::sMD_NeedsAsset | SField::sMD_Default) +TYPED_SFIELD(sfDebtTotal, NUMBER, 6, SField::sMD_NeedsAsset | SField::sMD_Default) +TYPED_SFIELD(sfDebtMaximum, NUMBER, 7, SField::sMD_NeedsAsset | SField::sMD_Default) +TYPED_SFIELD(sfCoverAvailable, NUMBER, 8, SField::sMD_NeedsAsset | SField::sMD_Default) TYPED_SFIELD(sfLoanOriginationFee, NUMBER, 9) TYPED_SFIELD(sfLoanServiceFee, NUMBER, 10) TYPED_SFIELD(sfLatePaymentFee, NUMBER, 11) TYPED_SFIELD(sfClosePaymentFee, NUMBER, 12) -TYPED_SFIELD(sfPrincipalOutstanding, NUMBER, 13) +TYPED_SFIELD(sfPrincipalOutstanding, NUMBER, 13, SField::sMD_NeedsAsset | SField::sMD_Default) TYPED_SFIELD(sfPrincipalRequested, NUMBER, 14) -TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15) +TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15, SField::sMD_NeedsAsset | SField::sMD_Default) TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16) -TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17) +TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17, SField::sMD_NeedsAsset | SField::sMD_Default) // int32 TYPED_SFIELD(sfLoanScale, INT32, 1) diff --git a/src/libxrpl/basics/Number.cpp b/src/libxrpl/basics/Number.cpp index 9984b26ffe..436ebf6779 100644 --- a/src/libxrpl/basics/Number.cpp +++ b/src/libxrpl/basics/Number.cpp @@ -1,4 +1,6 @@ #include +// Keep Number.h first to ensure it can build without hidden dependencies +#include #include #include @@ -13,16 +15,20 @@ #include #ifdef _MSC_VER -#pragma message("Using boost::multiprecision::uint128_t") +#pragma message("Using boost::multiprecision::uint128_t and int128_t") #include using uint128_t = boost::multiprecision::uint128_t; +using int128_t = boost::multiprecision::int128_t; #else // !defined(_MSC_VER) using uint128_t = __uint128_t; +using int128_t = __int128_t; #endif // !defined(_MSC_VER) namespace xrpl { thread_local Number::rounding_mode Number::mode_ = Number::to_nearest; +thread_local std::reference_wrapper Number::range_ = + largeRange; Number::rounding_mode Number::getround() @@ -36,12 +42,30 @@ Number::setround(rounding_mode mode) return std::exchange(mode_, mode); } +MantissaRange::mantissa_scale +Number::getMantissaScale() +{ + return range_.get().scale; +} + +void +Number::setMantissaScale(MantissaRange::mantissa_scale scale) +{ + if (scale != MantissaRange::small && scale != MantissaRange::large) + LogicError("Unknown mantissa scale"); + range_ = scale == MantissaRange::small ? smallRange : largeRange; +} + // Guard // The Guard class is used to temporarily add extra digits of // precision to an operation. This enables the final result // to be correctly rounded to the internal precision of Number. +template +concept UnsignedMantissa = + std::is_unsigned_v || std::is_same_v; + class Number::Guard { std::uint64_t digits_; // 16 decimal guard digits @@ -62,8 +86,9 @@ public: is_negative() const noexcept; // add a digit + template void - push(unsigned d) noexcept; + push(T d) noexcept; // recover a digit unsigned @@ -76,16 +101,40 @@ public: round() noexcept; // Modify the result to the correctly rounded value + template void - doRoundUp(rep& mantissa, int& exponent, std::string location); + doRoundUp( + bool& negative, + T& mantissa, + int& exponent, + internalrep const& minMantissa, + internalrep const& maxMantissa, + std::string location); + + // Modify the result to the correctly rounded value + template + void + doRoundDown( + bool& negative, + T& mantissa, + int& exponent, + internalrep const& minMantissa); // Modify the result to the correctly rounded value void - doRoundDown(rep& mantissa, int& exponent); + doRound(rep& drops, std::string location); - // Modify the result to the correctly rounded value +private: void - doRound(rep& drops); + doPush(unsigned d) noexcept; + + template + void + bringIntoRange( + bool& negative, + T& mantissa, + int& exponent, + internalrep const& minMantissa); }; inline void @@ -107,13 +156,20 @@ Number::Guard::is_negative() const noexcept } inline void -Number::Guard::push(unsigned d) noexcept +Number::Guard::doPush(unsigned d) noexcept { - xbit_ = xbit_ || (digits_ & 0x0000'0000'0000'000F) != 0; + xbit_ = xbit_ || ((digits_ & 0x0000'0000'0000'000F) != 0); digits_ >>= 4; digits_ |= (d & 0x0000'0000'0000'000FULL) << 60; } +template +inline void +Number::Guard::push(T d) noexcept +{ + doPush(static_cast(d)); +} + inline unsigned Number::Guard::pop() noexcept { @@ -163,30 +219,65 @@ Number::Guard::round() noexcept return 0; } +template void -Number::Guard::doRoundUp(rep& mantissa, int& exponent, std::string location) +Number::Guard::bringIntoRange( + bool& negative, + T& mantissa, + int& exponent, + internalrep const& minMantissa) +{ + // Bring mantissa back into the minMantissa / maxMantissa range AFTER + // rounding + if (mantissa < minMantissa) + { + mantissa *= 10; + --exponent; + } + if (exponent < minExponent) + { + constexpr Number zero = Number{}; + + negative = zero.negative_; + mantissa = zero.mantissa_; + exponent = zero.exponent_; + } +} + +template +void +Number::Guard::doRoundUp( + bool& negative, + T& mantissa, + int& exponent, + internalrep const& minMantissa, + internalrep const& maxMantissa, + std::string location) { auto r = round(); if (r == 1 || (r == 0 && (mantissa & 1) == 1)) { ++mantissa; - if (mantissa > maxMantissa) + // Ensure mantissa after incrementing fits within both the + // min/maxMantissa range and is a valid "rep". + if (mantissa > maxMantissa || mantissa > maxRep) { mantissa /= 10; ++exponent; } } - if (exponent < minExponent) - { - mantissa = 0; - exponent = Number{}.exponent_; - } + bringIntoRange(negative, mantissa, exponent, minMantissa); if (exponent > maxExponent) throw std::overflow_error(location); } +template void -Number::Guard::doRoundDown(rep& mantissa, int& exponent) +Number::Guard::doRoundDown( + bool& negative, + T& mantissa, + int& exponent, + internalrep const& minMantissa) { auto r = round(); if (r == 1 || (r == 0 && (mantissa & 1) == 1)) @@ -198,20 +289,27 @@ Number::Guard::doRoundDown(rep& mantissa, int& exponent) --exponent; } } - if (exponent < minExponent) - { - mantissa = 0; - exponent = Number{}.exponent_; - } + bringIntoRange(negative, mantissa, exponent, minMantissa); } // Modify the result to the correctly rounded value void -Number::Guard::doRound(rep& drops) +Number::Guard::doRound(rep& drops, std::string location) { auto r = round(); if (r == 1 || (r == 0 && (drops & 1) == 1)) { + if (drops >= maxRep) + { + static_assert(sizeof(internalrep) == sizeof(rep)); + // This should be impossible, because it's impossible to represent + // "maxRep + 0.6" in Number, regardless of the scale. There aren't + // enough digits available. You'd either get a mantissa of "maxRep" + // or "(maxRep + 1) / 10", neither of which will round up when + // converting to rep, though the latter might overflow _before_ + // rounding. + throw std::overflow_error(location); // LCOV_EXCL_LINE + } ++drops; } if (is_negative()) @@ -220,20 +318,88 @@ Number::Guard::doRound(rep& drops) // Number -constexpr Number one{1000000000000000, -15, Number::unchecked{}}; - -void -Number::normalize() +// Safely convert rep (int64) mantissa to internalrep (uint64). If the rep is +// negative, returns the positive value. This takes a little extra work because +// converting std::numeric_limits::min() flirts with UB, and can +// vary across compilers. +Number::internalrep +Number::externalToInternal(rep mantissa) { + // If the mantissa is already positive, just return it + if (mantissa >= 0) + return mantissa; + // If the mantissa is negative, but fits within the positive range of rep, + // return it negated + if (mantissa >= -std::numeric_limits::max()) + return -mantissa; + + // If the mantissa doesn't fit within the positive range, convert to + // int128_t, negate that, and cast it back down to the internalrep + // In practice, this is only going to cover the case of + // std::numeric_limits::min(). + int128_t temp = mantissa; + return static_cast(-temp); +} + +constexpr Number +Number::oneSmall() +{ + return Number{ + false, + Number::smallRange.min, + -Number::smallRange.log, + Number::unchecked{}}; +}; + +constexpr Number oneSml = Number::oneSmall(); + +constexpr Number +Number::oneLarge() +{ + return Number{ + false, + Number::largeRange.min, + -Number::largeRange.log, + Number::unchecked{}}; +}; + +constexpr Number oneLrg = Number::oneLarge(); + +Number +Number::one() +{ + if (&range_.get() == &smallRange) + return oneSml; + XRPL_ASSERT(&range_.get() == &largeRange, "Number::one() : valid range_"); + return oneLrg; +} + +// Use the member names in this static function for now so the diff is cleaner +// TODO: Rename the function parameters to get rid of the "_" suffix +template +void +doNormalize( + bool& negative, + T& mantissa_, + int& exponent_, + MantissaRange::rep const& minMantissa, + MantissaRange::rep const& maxMantissa) +{ + auto constexpr minExponent = Number::minExponent; + auto constexpr maxExponent = Number::maxExponent; + auto constexpr maxRep = Number::maxRep; + + using Guard = Number::Guard; + + constexpr Number zero = Number{}; if (mantissa_ == 0) { - *this = Number{}; + mantissa_ = zero.mantissa_; + exponent_ = zero.exponent_; + negative = zero.negative_; return; } - bool const negative = (mantissa_ < 0); - auto m = static_cast>(mantissa_); - if (negative) - m = -m; + auto m = mantissa_; while ((m < minMantissa) && (exponent_ > minExponent)) { m *= 10; @@ -250,57 +416,161 @@ Number::normalize() m /= 10; ++exponent_; } - mantissa_ = m; - if ((exponent_ < minExponent) || (mantissa_ < minMantissa)) + if ((exponent_ < minExponent) || (m < minMantissa)) { - *this = Number{}; + mantissa_ = zero.mantissa_; + exponent_ = zero.exponent_; + negative = zero.negative_; return; } - g.doRoundUp(mantissa_, exponent_, "Number::normalize 2"); + // When using the largeRange, "m" needs fit within an int64, even if + // the final mantissa_ is going to end up larger to fit within the + // MantissaRange. Cut it down here so that the rounding will be done while + // it's smaller. + // + // Example: 9,900,000,000,000,123,456 > 9,223,372,036,854,775,807, + // so "m" will be modified to 990,000,000,000,012,345. Then that value + // will be rounded to 990,000,000,000,012,345 or + // 990,000,000,000,012,346, depending on the rounding mode. Finally, + // mantissa_ will be "m*10" so it fits within the range, and end up as + // 9,900,000,000,000,123,450 or 9,900,000,000,000,123,460. + // mantissa() will return mantissa_ / 10, and exponent() will return + // exponent_ + 1. + if (m > maxRep) + { + if (exponent_ >= maxExponent) + throw std::overflow_error("Number::normalize 1.5"); + g.push(m % 10); + m /= 10; + ++exponent_; + } + // Before modification, m should be within the min/max range. After + // modification, it must be less than maxRep. In other words, the original + // value should have been no more than maxRep * 10. + // (maxRep * 10 > maxMantissa) + XRPL_ASSERT_PARTS( + m <= maxRep, + "xrpl::doNormalize", + "intermediate mantissa fits in int64"); + mantissa_ = m; - if (negative) - mantissa_ = -mantissa_; + g.doRoundUp( + negative, + mantissa_, + exponent_, + minMantissa, + maxMantissa, + "Number::normalize 2"); + XRPL_ASSERT_PARTS( + mantissa_ >= minMantissa && mantissa_ <= maxMantissa, + "xrpl::doNormalize", + "final mantissa fits in range"); +} + +template <> +void +Number::normalize( + bool& negative, + uint128_t& mantissa, + int& exponent, + internalrep const& minMantissa, + internalrep const& maxMantissa) +{ + doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa); +} + +template <> +void +Number::normalize( + bool& negative, + unsigned long long& mantissa, + int& exponent, + internalrep const& minMantissa, + internalrep const& maxMantissa) +{ + doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa); +} + +template <> +void +Number::normalize( + bool& negative, + unsigned long& mantissa, + int& exponent, + internalrep const& minMantissa, + internalrep const& maxMantissa) +{ + doNormalize(negative, mantissa, exponent, minMantissa, maxMantissa); +} + +void +Number::normalize() +{ + auto const& range = range_.get(); + normalize(negative_, mantissa_, exponent_, range.min, range.max); +} + +// Copy the number, but set a new exponent. Because the mantissa doesn't change, +// the result will be "mostly" normalized, but the exponent could go out of +// range. +Number +Number::shiftExponent(int exponentDelta) const +{ + XRPL_ASSERT_PARTS(isnormal(), "xrpl::Number::shiftExponent", "normalized"); + auto const newExponent = exponent_ + exponentDelta; + if (newExponent >= maxExponent) + throw std::overflow_error("Number::shiftExponent"); + if (newExponent < minExponent) + { + return Number{}; + } + Number const result{negative_, mantissa_, newExponent, unchecked{}}; + XRPL_ASSERT_PARTS( + result.isnormal(), + "xrpl::Number::shiftExponent", + "result is normalized"); + return result; } Number& Number::operator+=(Number const& y) { - if (y == Number{}) + constexpr Number zero = Number{}; + if (y == zero) return *this; - if (*this == Number{}) + if (*this == zero) { *this = y; return *this; } if (*this == -y) { - *this = Number{}; + *this = zero; return *this; } + XRPL_ASSERT( isnormal() && y.isnormal(), "xrpl::Number::operator+=(Number) : is normal"); - auto xm = mantissa(); - auto xe = exponent(); - int xn = 1; - if (xm < 0) - { - xm = -xm; - xn = -1; - } - auto ym = y.mantissa(); - auto ye = y.exponent(); - int yn = 1; - if (ym < 0) - { - ym = -ym; - yn = -1; - } + // *n = negative + // *s = sign + // *m = mantissa + // *e = exponent + + // Need to use uint128_t, because large mantissas can overflow when added + // together. + bool xn = negative_; + uint128_t xm = mantissa_; + auto xe = exponent_; + + bool yn = y.negative_; + uint128_t ym = y.mantissa_; + auto ye = y.exponent_; Guard g; if (xe < ye) { - if (xn == -1) + if (xn) g.set_negative(); do { @@ -311,7 +581,7 @@ Number::operator+=(Number const& y) } else if (xe > ye) { - if (yn == -1) + if (yn) g.set_negative(); do { @@ -320,16 +590,22 @@ Number::operator+=(Number const& y) ++ye; } while (xe > ye); } + + auto const& range = range_.get(); + auto const& minMantissa = range.min; + auto const& maxMantissa = range.max; + if (xn == yn) { xm += ym; - if (xm > maxMantissa) + if (xm > maxMantissa || xm > maxRep) { g.push(xm % 10); xm /= 10; ++xe; } - g.doRoundUp(xm, xe, "Number::addition overflow"); + g.doRoundUp( + xn, xm, xe, minMantissa, maxMantissa, "Number::addition overflow"); } else { @@ -343,16 +619,19 @@ Number::operator+=(Number const& y) xe = ye; xn = yn; } - while (xm < minMantissa) + while (xm < minMantissa && xm * 10 <= maxRep) { xm *= 10; xm -= g.pop(); --xe; } - g.doRoundDown(xm, xe); + g.doRoundDown(xn, xm, xe, minMantissa); } - mantissa_ = xm * xn; + + negative_ = xn; + mantissa_ = static_cast(xm); exponent_ = xe; + normalize(); return *this; } @@ -387,39 +666,42 @@ divu10(uint128_t& u) Number& Number::operator*=(Number const& y) { - if (*this == Number{}) + constexpr Number zero = Number{}; + if (*this == zero) return *this; - if (y == Number{}) + if (y == zero) { *this = y; return *this; } - XRPL_ASSERT( - isnormal() && y.isnormal(), - "xrpl::Number::operator*=(Number) : is normal"); - auto xm = mantissa(); - auto xe = exponent(); - int xn = 1; - if (xm < 0) - { - xm = -xm; - xn = -1; - } - auto ym = y.mantissa(); - auto ye = y.exponent(); - int yn = 1; - if (ym < 0) - { - ym = -ym; - yn = -1; - } + // *n = negative + // *s = sign + // *m = mantissa + // *e = exponent + + bool xn = negative_; + int xs = xn ? -1 : 1; + internalrep xm = mantissa_; + auto xe = exponent_; + + bool yn = y.negative_; + int ys = yn ? -1 : 1; + internalrep ym = y.mantissa_; + auto ye = y.exponent_; + auto zm = uint128_t(xm) * uint128_t(ym); auto ze = xe + ye; - auto zn = xn * yn; + auto zs = xs * ys; + bool zn = (zs == -1); Guard g; - if (zn == -1) + if (zn) g.set_negative(); - while (zm > maxMantissa) + + auto const& range = range_.get(); + auto const& minMantissa = range.min; + auto const& maxMantissa = range.max; + + while (zm > maxMantissa || zm > maxRep) { // The following is optimization for: // g.push(static_cast(zm % 10)); @@ -427,61 +709,129 @@ Number::operator*=(Number const& y) g.push(divu10(zm)); ++ze; } - xm = static_cast(zm); + xm = static_cast(zm); xe = ze; g.doRoundUp( + zn, xm, xe, + minMantissa, + maxMantissa, "Number::multiplication overflow : exponent is " + std::to_string(xe)); - mantissa_ = xm * zn; + negative_ = zn; + mantissa_ = xm; exponent_ = xe; - XRPL_ASSERT( - isnormal() || *this == Number{}, - "xrpl::Number::operator*=(Number) : result is normal"); + + normalize(); return *this; } Number& Number::operator/=(Number const& y) { - if (y == Number{}) + constexpr Number zero = Number{}; + if (y == zero) throw std::overflow_error("Number: divide by 0"); - if (*this == Number{}) + if (*this == zero) return *this; - int np = 1; - auto nm = mantissa(); - auto ne = exponent(); - if (nm < 0) + // n* = numerator + // d* = denominator + // *p = negative (positive?) + // *s = sign + // *m = mantissa + // *e = exponent + + bool np = negative_; + int ns = (np ? -1 : 1); + auto nm = mantissa_; + auto ne = exponent_; + + bool dp = y.negative_; + int ds = (dp ? -1 : 1); + auto dm = y.mantissa_; + auto de = y.exponent_; + + auto const& range = range_.get(); + auto const& minMantissa = range.min; + auto const& maxMantissa = range.max; + + // Shift by 10^17 gives greatest precision while not overflowing + // uint128_t or the cast back to int64_t + // TODO: Can/should this be made bigger for largeRange? + // log(2^128,10) ~ 38.5 + // largeRange.log = 18, fits in 10^19 + // f can be up to 10^(38-19) = 10^19 safely + static_assert(smallRange.log == 15); + static_assert(largeRange.log == 18); + bool small = Number::getMantissaScale() == MantissaRange::small; + uint128_t const f = + small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL; + XRPL_ASSERT_PARTS( + f >= minMantissa * 10, "Number::operator/=", "factor expected size"); + + // unsigned denominator + auto const dmu = static_cast(dm); + // correctionFactor can be anything between 10 and f, depending on how much + // extra precision we want to only use for rounding with the + // largeRange. Three digits seems like plenty, and is more than + // the smallRange uses. + uint128_t const correctionFactor = 1'000; + + auto const numerator = uint128_t(nm) * f; + + auto zm = numerator / dmu; + auto ze = ne - de - (small ? 17 : 19); + bool zn = (ns * ds) < 0; + if (!small) { - nm = -nm; - np = -1; + // Virtually multiply numerator by correctionFactor. Since that would + // overflow in the existing uint128_t, we'll do that part separately. + // The math for this would work for small mantissas, but we need to + // preserve existing behavior. + // + // Consider: + // ((numerator * correctionFactor) / dmu) / correctionFactor + // = ((numerator / dmu) * correctionFactor) / correctionFactor) + // + // But that assumes infinite precision. With integer math, this is + // equivalent to + // + // = ((numerator / dmu * correctionFactor) + // + ((numerator % dmu) * correctionFactor) / dmu) / correctionFactor + // + // We have already set `mantissa_ = numerator / dmu`. Now we + // compute `remainder = numerator % dmu`, and if it is + // nonzero, we do the rest of the arithmetic. If it's zero, we can skip + // it. + auto const remainder = (numerator % dmu); + if (remainder != 0) + { + zm *= correctionFactor; + auto const correction = remainder * correctionFactor / dmu; + zm += correction; + // divide by 1000 by moving the exponent, so we don't lose the + // integer value we just computed + ze -= 3; + } } - int dp = 1; - auto dm = y.mantissa(); - auto de = y.exponent(); - if (dm < 0) - { - dm = -dm; - dp = -1; - } - // Shift by 10^17 gives greatest precision while not overflowing uint128_t - // or the cast back to int64_t - uint128_t const f = 100'000'000'000'000'000; - mantissa_ = static_cast(uint128_t(nm) * f / uint128_t(dm)); - exponent_ = ne - de - 17; - mantissa_ *= np * dp; - normalize(); + normalize(zn, zm, ze, minMantissa, maxMantissa); + negative_ = zn; + mantissa_ = static_cast(zm); + exponent_ = ze; + XRPL_ASSERT_PARTS( + isnormal(), "xrpl::Number::operator/=", "result is normalized"); + return *this; } Number::operator rep() const { - rep drops = mantissa_; - int offset = exponent_; + rep drops = mantissa(); + int offset = exponent(); Guard g; if (drops != 0) { - if (drops < 0) + if (negative_) { g.set_negative(); drops = -drops; @@ -493,11 +843,11 @@ Number::operator rep() const } for (; offset > 0; --offset) { - if (drops > std::numeric_limits::max() / 10) + if (drops > maxRep / 10) throw std::overflow_error("Number::operator rep() overflow"); drops *= 10; } - g.doRound(drops); + g.doRound(drops, "Number::operator rep() rounding overflow"); } return drops; } @@ -524,34 +874,37 @@ std::string to_string(Number const& amount) { // keep full internal accuracy, but make more human friendly if possible - if (amount == Number{}) + constexpr Number zero = Number{}; + if (amount == zero) return "0"; - auto const exponent = amount.exponent(); - auto mantissa = amount.mantissa(); + auto exponent = amount.exponent_; + auto mantissa = amount.mantissa_; + bool const negative = amount.negative_; // Use scientific notation for exponents that are too small or too large - if (((exponent != 0) && ((exponent < -25) || (exponent > -5)))) + auto const rangeLog = Number::mantissaLog(); + if (((exponent != 0) && + ((exponent < -(rangeLog + 10)) || (exponent > -(rangeLog - 10))))) { - std::string ret = std::to_string(mantissa); + while (mantissa != 0 && mantissa % 10 == 0 && + exponent < Number::maxExponent) + { + mantissa /= 10; + ++exponent; + } + std::string ret = negative ? "-" : ""; + ret.append(std::to_string(mantissa)); ret.append(1, 'e'); ret.append(std::to_string(exponent)); return ret; } - bool negative = false; - - if (mantissa < 0) - { - mantissa = -mantissa; - negative = true; - } - XRPL_ASSERT( exponent + 43 > 0, "xrpl::to_string(Number) : minimum exponent"); - ptrdiff_t const pad_prefix = 27; - ptrdiff_t const pad_suffix = 23; + ptrdiff_t const pad_prefix = rangeLog + 12; + ptrdiff_t const pad_suffix = rangeLog + 8; std::string const raw_value(std::to_string(mantissa)); std::string val; @@ -561,7 +914,7 @@ to_string(Number const& amount) val.append(raw_value); val.append(pad_suffix, '0'); - ptrdiff_t const offset(exponent + 43); + ptrdiff_t const offset(exponent + pad_prefix + rangeLog + 1); auto pre_from(val.begin()); auto const pre_to(val.begin() + offset); @@ -621,7 +974,7 @@ Number power(Number const& f, unsigned n) { if (n == 0) - return one; + return Number::one(); if (n == 1) return f; auto r = power(f, n / 2); @@ -643,6 +996,9 @@ power(Number const& f, unsigned n) Number root(Number f, unsigned d) { + constexpr Number zero = Number{}; + auto const one = Number::one(); + if (f == one || d == 1) return f; if (d == 0) @@ -650,16 +1006,16 @@ root(Number f, unsigned d) if (f == -one) return one; if (abs(f) < one) - return Number{}; + return zero; throw std::overflow_error("Number::root infinity"); } - if (f < Number{} && d % 2 == 0) + if (f < zero && d % 2 == 0) throw std::overflow_error("Number::root nan"); - if (f == Number{}) + if (f == zero) return f; // Scale f into the range (0, 1) such that f's exponent is a multiple of d - auto e = f.exponent() + 16; + auto e = f.exponent_ + Number::mantissaLog() + 1; auto const di = static_cast(d); auto ex = [e = e, di = di]() // Euclidean remainder of e/d { @@ -670,9 +1026,12 @@ root(Number f, unsigned d) return di - k2; }(); e += ex; - f = Number{f.mantissa(), f.exponent() - e}; // f /= 10^e; + f = f.shiftExponent(-e); // f /= 10^e; + + XRPL_ASSERT_PARTS( + f.isnormal(), "xrpl::root(Number, unsigned)", "f is normalized"); bool neg = false; - if (f < Number{}) + if (f < zero) { neg = true; f = -f; @@ -702,24 +1061,33 @@ root(Number f, unsigned d) } while (r != rm1 && r != rm2); // return r * 10^(e/d) to reverse scaling - return Number{r.mantissa(), r.exponent() + e / di}; + auto const result = r.shiftExponent(e / di); + XRPL_ASSERT_PARTS( + result.isnormal(), + "xrpl::root(Number, unsigned)", + "result is normalized"); + return result; } Number root2(Number f) { + constexpr Number zero = Number{}; + auto const one = Number::one(); + if (f == one) return f; - if (f < Number{}) + if (f < zero) throw std::overflow_error("Number::root nan"); - if (f == Number{}) + if (f == zero) return f; // Scale f into the range (0, 1) such that f's exponent is a multiple of d - auto e = f.exponent() + 16; + auto e = f.exponent_ + Number::mantissaLog() + 1; if (e % 2 != 0) ++e; - f = Number{f.mantissa(), f.exponent() - e}; // f /= 10^e; + f = f.shiftExponent(-e); // f /= 10^e; + XRPL_ASSERT_PARTS(f.isnormal(), "xrpl::root2(Number)", "f is normalized"); // Quadratic least squares curve fit of f^(1/d) in the range [0, 1] auto const D = 105; @@ -740,7 +1108,11 @@ root2(Number f) } while (r != rm1 && r != rm2); // return r * 10^(e/2) to reverse scaling - return Number{r.mantissa(), r.exponent() + e / 2}; + auto const result = r.shiftExponent(e / 2); + XRPL_ASSERT_PARTS( + result.isnormal(), "xrpl::root2(Number)", "result is normalized"); + + return result; } // Returns f^(n/d) @@ -748,6 +1120,9 @@ root2(Number f) Number power(Number const& f, unsigned n, unsigned d) { + constexpr Number zero = Number{}; + auto const one = Number::one(); + if (f == one) return f; auto g = std::gcd(n, d); @@ -758,7 +1133,7 @@ power(Number const& f, unsigned n, unsigned d) if (f == -one) return one; if (abs(f) < one) - return Number{}; + return zero; // abs(f) > one throw std::overflow_error("Number::power infinity"); } @@ -766,7 +1141,7 @@ power(Number const& f, unsigned n, unsigned d) return one; n /= g; d /= g; - if ((n % 2) == 1 && (d % 2) == 0 && f < Number{}) + if ((n % 2) == 1 && (d % 2) == 0 && f < zero) throw std::overflow_error("Number::power nan"); return root(power(f, n), d); } diff --git a/src/libxrpl/protocol/IOUAmount.cpp b/src/libxrpl/protocol/IOUAmount.cpp index 5c9ab1febc..297c2bac12 100644 --- a/src/libxrpl/protocol/IOUAmount.cpp +++ b/src/libxrpl/protocol/IOUAmount.cpp @@ -1,8 +1,11 @@ +#include +// Do not remove. Forces IOUAmount.h to stay first, to verify it can compile +// without any hidden dependencies #include #include #include #include -#include +#include #include @@ -40,11 +43,24 @@ setSTNumberSwitchover(bool v) } /* The range for the mantissa when normalized */ -static std::int64_t constexpr minMantissa = 1000000000000000ull; -static std::int64_t constexpr maxMantissa = 9999999999999999ull; +// log(2^63,10) ~ 18.96 +// +static std::int64_t constexpr minMantissa = STAmount::cMinValue; +static std::int64_t constexpr maxMantissa = STAmount::cMaxValue; /* The range for the exponent when normalized */ -static int constexpr minExponent = -96; -static int constexpr maxExponent = 80; +static int constexpr minExponent = STAmount::cMinOffset; +static int constexpr maxExponent = STAmount::cMaxOffset; + +IOUAmount +IOUAmount::fromNumber(Number const& number) +{ + // Need to create a default IOUAmount and assign directly so it doesn't try + // to normalize, which calls fromNumber + IOUAmount result{}; + std::tie(result.mantissa_, result.exponent_) = + number.normalizeToRange(minMantissa, maxMantissa); + return result; +} IOUAmount IOUAmount::minPositiveAmount() @@ -64,8 +80,7 @@ IOUAmount::normalize() if (getSTNumberSwitchover()) { Number const v{mantissa_, exponent_}; - mantissa_ = v.mantissa(); - exponent_ = v.exponent(); + *this = fromNumber(v); if (exponent_ > maxExponent) Throw("value overflow"); if (exponent_ < minExponent) @@ -106,8 +121,7 @@ IOUAmount::normalize() mantissa_ = -mantissa_; } -IOUAmount::IOUAmount(Number const& other) - : mantissa_(other.mantissa()), exponent_(other.exponent()) +IOUAmount::IOUAmount(Number const& other) : IOUAmount(fromNumber(other)) { if (exponent_ > maxExponent) Throw("value overflow"); diff --git a/src/libxrpl/protocol/Issue.cpp b/src/libxrpl/protocol/Issue.cpp index b858a31e3e..ca5bf35e8b 100644 --- a/src/libxrpl/protocol/Issue.cpp +++ b/src/libxrpl/protocol/Issue.cpp @@ -49,6 +49,12 @@ Issue::native() const return *this == xrpIssue(); } +bool +Issue::integral() const +{ + return native(); +} + bool isConsistent(Issue const& ac) { diff --git a/src/libxrpl/protocol/Rules.cpp b/src/libxrpl/protocol/Rules.cpp index b1f2c2d631..3710322699 100644 --- a/src/libxrpl/protocol/Rules.cpp +++ b/src/libxrpl/protocol/Rules.cpp @@ -1,10 +1,13 @@ +#include +// Do not remove. Forces Rules.h to stay first, to verify it can compile +// without any hidden dependencies #include +#include #include #include #include #include #include -#include #include #include @@ -33,6 +36,15 @@ getCurrentTransactionRules() void setCurrentTransactionRules(std::optional r) { + // Make global changes associated with the rules before the value is moved. + // Push the appropriate setting, instead of having the class pull every time + // the value is needed. That could get expensive fast. + bool enableLargeNumbers = !r || + (r->enabled(featureSingleAssetVault) || + r->enabled(featureLendingProtocol)); + Number::setMantissaScale( + enableLargeNumbers ? MantissaRange::large : MantissaRange::small); + *getCurrentTransactionRulesRef() = std::move(r); } diff --git a/src/libxrpl/protocol/STAmount.cpp b/src/libxrpl/protocol/STAmount.cpp index ebccfb3e64..ec60971e63 100644 --- a/src/libxrpl/protocol/STAmount.cpp +++ b/src/libxrpl/protocol/STAmount.cpp @@ -11,11 +11,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -310,7 +312,8 @@ STAmount& STAmount::operator=(IOUAmount const& iou) { XRPL_ASSERT( - native() == false, "xrpl::STAmount::operator=(IOUAmount) : is not XRP"); + integral() == false, + "xrpl::STAmount::operator=(IOUAmount) : is not integral"); mOffset = iou.exponent(); mIsNegative = iou < beast::zero; if (mIsNegative) @@ -320,6 +323,26 @@ STAmount::operator=(IOUAmount const& iou) return *this; } +STAmount& +STAmount::operator=(Number const& number) +{ + if (!getCurrentTransactionRules() || + isFeatureEnabled(featureSingleAssetVault) || + isFeatureEnabled(featureLendingProtocol)) + { + *this = fromNumber(mAsset, number); + } + else + { + auto const originalMantissa = number.mantissa(); + mIsNegative = originalMantissa < 0; + mValue = mIsNegative ? -originalMantissa : originalMantissa; + mOffset = number.exponent(); + } + canonicalize(); + return *this; +} + //------------------------------------------------------------------------------ // // Operators @@ -849,11 +872,11 @@ STAmount::canonicalize() if (getSTNumberSwitchover()) { - Number num( - mIsNegative ? -mValue : mValue, mOffset, Number::unchecked{}); + Number num(mIsNegative, mValue, mOffset, Number::unchecked{}); auto set = [&](auto const& val) { - mIsNegative = val.value() < 0; - mValue = mIsNegative ? -val.value() : val.value(); + auto const value = val.value(); + mIsNegative = value < 0; + mValue = mIsNegative ? -value : value; }; if (native()) set(XRPAmount{num}); @@ -1323,7 +1346,7 @@ multiply(STAmount const& v1, STAmount const& v2, Asset const& asset) if (getSTNumberSwitchover()) { auto const r = Number{v1} * Number{v2}; - return STAmount{asset, r.mantissa(), r.exponent()}; + return STAmount{asset, r}; } std::uint64_t value1 = v1.mantissa(); @@ -1471,6 +1494,10 @@ roundToScale( if (value.integral()) return value; + // Nothing to do for zero. + if (value == beast::zero) + return value; + // If the value's exponent is greater than or equal to the scale, then // rounding will do nothing, and might even lose precision, so just return // the value. diff --git a/src/libxrpl/protocol/STNumber.cpp b/src/libxrpl/protocol/STNumber.cpp index f85bb48e0a..2f2dae7493 100644 --- a/src/libxrpl/protocol/STNumber.cpp +++ b/src/libxrpl/protocol/STNumber.cpp @@ -1,9 +1,13 @@ +#include +// Do not remove. Keep STNumber.h first #include #include #include +#include #include +#include #include -#include +#include #include #include @@ -17,11 +21,11 @@ namespace xrpl { STNumber::STNumber(SField const& field, Number const& value) - : STBase(field), value_(value) + : STTakesAsset(field), value_(value) { } -STNumber::STNumber(SerialIter& sit, SField const& field) : STBase(field) +STNumber::STNumber(SerialIter& sit, SField const& field) : STTakesAsset(field) { // We must call these methods in separate statements // to guarantee their order of execution. @@ -42,6 +46,19 @@ STNumber::getText() const return to_string(value_); } +void +STNumber::associateAsset(Asset const& a) +{ + STTakesAsset::associateAsset(a); + + XRPL_ASSERT_PARTS( + getFName().shouldMeta(SField::sMD_NeedsAsset), + "STNumber::associateAsset", + "field needs asset"); + + roundToAsset(a, value_); +} + void STNumber::add(Serializer& s) const { @@ -49,8 +66,49 @@ STNumber::add(Serializer& s) const XRPL_ASSERT( getFName().fieldType == getSType(), "xrpl::STNumber::add : field type match"); - s.add64(value_.mantissa()); - s.add32(value_.exponent()); + + auto value = value_; + auto const mantissa = value.mantissa(); + auto const exponent = value.exponent(); + + SField const& field = getFName(); + if (field.shouldMeta(SField::sMD_NeedsAsset)) + { + // asset is defined in the STTakesAsset base class + if (asset_) + { + // The number should be rounded to the asset's precision, but round + // it here if it has an asset assigned. + roundToAsset(*asset_, value); + XRPL_ASSERT_PARTS( + value_ == value, + "xrpl::STNumber::add", + "value is already rounded"); + } + else + { +#if !NDEBUG + // There are circumstances where an already-rounded Number is + // serialized without being touched by a transactor, and thus + // without an asset. We can't know if it's rounded, because it could + // represent _anything_, particularly when serializing user-provided + // Json. Regardless, the only time we should be serializing an + // STNumber is when the scale is large. + XRPL_ASSERT_PARTS( + Number::getMantissaScale() == MantissaRange::large, + "xrpl::STNumber::add", + "STNumber only used with large mantissa scale"); +#endif + } + } + + XRPL_ASSERT_PARTS( + mantissa <= std::numeric_limits::max() && + mantissa >= std::numeric_limits::min(), + "xrpl::STNumber::add", + "mantissa in valid range"); + s.add64(mantissa); + s.add32(exponent); } Number const& @@ -179,20 +237,30 @@ numberFromJson(SField const& field, Json::Value const& value) else if (value.isString()) { parts = partsFromString(value.asString()); - // Only strings can represent out-of-range values. - if (parts.mantissa > std::numeric_limits::max()) - Throw("too high"); + + XRPL_ASSERT_PARTS( + !getCurrentTransactionRules(), + "xrpld::numberFromJson", + "Not in a Transactor context"); + + // Number mantissas are much bigger than the allowable parsed values, so + // it can't be out of range. + static_assert( + std::numeric_limits::max() >= + std::numeric_limits::max()); } else { Throw("not a number"); } - std::int64_t mantissa = parts.mantissa; - if (parts.negative) - mantissa = -mantissa; - - return STNumber{field, Number{mantissa, parts.exponent}}; + return STNumber{ + field, + Number{ + parts.negative, + parts.mantissa, + parts.exponent, + Number::normalized{}}}; } } // namespace xrpl diff --git a/src/libxrpl/protocol/STTakesAsset.cpp b/src/libxrpl/protocol/STTakesAsset.cpp new file mode 100644 index 0000000000..d43e7b04a1 --- /dev/null +++ b/src/libxrpl/protocol/STTakesAsset.cpp @@ -0,0 +1,29 @@ +#include +// Do not remove. Force STTakesAsset.h first +#include + +namespace xrpl { + +void +associateAsset(SLE& sle, Asset const& asset) +{ + // Iterating by offset is the only way to get non-const references + for (int i = 0; i < sle.getCount(); ++i) + { + STBase& entry = sle.getIndex(i); + SField const& field = entry.getFName(); + if (field.shouldMeta(SField::sMD_NeedsAsset)) + { + auto const type = entry.getSType(); + // If the field is not set or present, skip it. + if (type == STI_NOTPRESENT) + continue; + // If the type doesn't downcast, then the flag shouldn't be on the + // SField + auto& ta = entry.downcast(); + ta.associateAsset(asset); + } + } +} + +} // namespace xrpl diff --git a/src/test/app/AMMClawback_test.cpp b/src/test/app/AMMClawback_test.cpp index 93fda8fe34..52f05f9ed5 100644 --- a/src/test/app/AMMClawback_test.cpp +++ b/src/test/app/AMMClawback_test.cpp @@ -2425,7 +2425,10 @@ class AMMClawback_test : public beast::unit_test::suite void run() override { - FeatureBitset const all = jtx::testable_amendments(); + // For now, just disable SAV entirely, which locks in the small Number + // mantissas + FeatureBitset const all = jtx::testable_amendments() - + featureSingleAssetVault - featureLendingProtocol; testInvalidRequest(); testFeatureDisabled(all - featureAMMClawback); diff --git a/src/test/app/AMMExtended_test.cpp b/src/test/app/AMMExtended_test.cpp index 317f6cb63d..d1816df51b 100644 --- a/src/test/app/AMMExtended_test.cpp +++ b/src/test/app/AMMExtended_test.cpp @@ -26,6 +26,9 @@ namespace test { */ struct AMMExtended_test : public jtx::AMMTest { + // Use small Number mantissas for the life of this test. + NumberMantissaScaleGuard const sg_{xrpl::MantissaRange::small}; + private: void testRmFundedOffer(FeatureBitset features) @@ -42,6 +45,7 @@ private: // funded and not used for the payment. using namespace jtx; + Env env{*this, features}; fund( @@ -1418,7 +1422,12 @@ private: testOffers() { using namespace jtx; - FeatureBitset const all{testable_amendments()}; + // For now, just disable SAV entirely, which locks in the small Number + // mantissas + FeatureBitset const all{ + testable_amendments() - featureSingleAssetVault - + featureLendingProtocol}; + testRmFundedOffer(all); testRmFundedOffer(all - fixAMMv1_1 - fixAMMv1_3); testEnforceNoRipple(all); @@ -3746,7 +3755,11 @@ private: testFlow() { using namespace jtx; - FeatureBitset const all{testable_amendments()}; + // For now, just disable SAV entirely, which locks in the small Number + // mantissas in the transaction engine + FeatureBitset const all{ + testable_amendments() - featureSingleAssetVault - + featureLendingProtocol}; testFalseDry(all); testBookStep(all); @@ -3760,7 +3773,11 @@ private: testCrossingLimits() { using namespace jtx; - FeatureBitset const all{testable_amendments()}; + // For now, just disable SAV entirely, which locks in the small Number + // mantissas in the transaction engine + FeatureBitset const all{ + testable_amendments() - featureSingleAssetVault - + featureLendingProtocol}; testStepLimit(all); testStepLimit(all - fixAMMv1_1 - fixAMMv1_3); } @@ -3769,7 +3786,11 @@ private: testDeliverMin() { using namespace jtx; - FeatureBitset const all{testable_amendments()}; + // For now, just disable SAV entirely, which locks in the small Number + // mantissas in the transaction engine + FeatureBitset const all{ + testable_amendments() - featureSingleAssetVault - + featureLendingProtocol}; test_convert_all_of_an_asset(all); test_convert_all_of_an_asset(all - fixAMMv1_1 - fixAMMv1_3); } @@ -3777,7 +3798,12 @@ private: void testDepositAuth() { - testPayment(jtx::testable_amendments()); + // For now, just disable SAV entirely, which locks in the small Number + // mantissas in the transaction engine + FeatureBitset const all{ + jtx::testable_amendments() - featureSingleAssetVault - + featureLendingProtocol}; + testPayment(all); testPayIOU(); } @@ -3785,7 +3811,11 @@ private: testFreeze() { using namespace test::jtx; - auto const sa = testable_amendments(); + // For now, just disable SAV entirely, which locks in the small Number + // mantissas in the transaction engine + FeatureBitset const sa{ + testable_amendments() - featureSingleAssetVault - + featureLendingProtocol}; testRippleState(sa); testGlobalFreeze(sa); testOffersWhenFrozen(sa); diff --git a/src/test/app/AMM_test.cpp b/src/test/app/AMM_test.cpp index 468d5b3ffd..55bf4aa0a3 100644 --- a/src/test/app/AMM_test.cpp +++ b/src/test/app/AMM_test.cpp @@ -30,7 +30,19 @@ namespace test { */ struct AMM_test : public jtx::AMMTest { + // Use small Number mantissas for the life of this test. + NumberMantissaScaleGuard const sg_{xrpl::MantissaRange::small}; + private: + static FeatureBitset + testable_amendments() + { + // For now, just disable SAV entirely, which locks in the small Number + // mantissas + return jtx::testable_amendments() - featureSingleAssetVault - + featureLendingProtocol; + } + void testInstanceCreate() { @@ -38,6 +50,7 @@ private: using namespace jtx; +#if NUMBERTODO // XRP to IOU, with featureSingleAssetVault testAMM( [&](AMM& ammAlice, Env&) { @@ -48,6 +61,7 @@ private: 0, {}, {testable_amendments() | featureSingleAssetVault}); +#endif // XRP to IOU, without featureSingleAssetVault testAMM( @@ -1365,8 +1379,8 @@ private: { testcase("Deposit"); - using namespace jtx; auto const all = testable_amendments(); + using namespace jtx; // Equal deposit: 1000000 tokens, 10% of the current pool testAMM([&](AMM& ammAlice, Env& env) { @@ -1384,15 +1398,14 @@ private: // equal asset deposit: unit test to exercise the rounding-down of // LPTokens in the AMMHelpers.cpp: adjustLPTokens calculations // The LPTokens need to have 16 significant digits and a fractional part - for (Number const deltaLPTokens : + for (Number const& deltaLPTokens : {Number{UINT64_C(100000'0000000009), -10}, Number{UINT64_C(100000'0000000001), -10}}) { testAMM([&](AMM& ammAlice, Env& env) { // initial LPToken balance IOUAmount const initLPToken = ammAlice.getLPTokensBalance(); - IOUAmount const newLPTokens{ - deltaLPTokens.mantissa(), deltaLPTokens.exponent()}; + IOUAmount const newLPTokens{deltaLPTokens}; // carol performs a two-asset deposit ammAlice.deposit( @@ -1417,11 +1430,9 @@ private: Number const deltaXRP = fr * 1e10; Number const deltaUSD = fr * 1e4; - STAmount const depositUSD = - STAmount{USD, deltaUSD.mantissa(), deltaUSD.exponent()}; + STAmount const depositUSD = STAmount{USD, deltaUSD}; - STAmount const depositXRP = - STAmount{XRP, deltaXRP.mantissa(), deltaXRP.exponent()}; + STAmount const depositXRP = STAmount{XRP, deltaXRP}; // initial LPTokens (1e7) + newLPTokens BEAST_EXPECT(ammAlice.expectBalances( @@ -1487,7 +1498,7 @@ private: }); // Single deposit: 100000 tokens worth of XRP - testAMM([&](AMM& ammAlice, Env&) { + testAMM([&](AMM& ammAlice, Env& env) { ammAlice.deposit(carol, 100'000, XRP(205)); BEAST_EXPECT(ammAlice.expectBalances( XRP(10'201), USD(10'000), IOUAmount{10'100'000, 0})); @@ -1668,8 +1679,8 @@ private: { testcase("Invalid Withdraw"); - using namespace jtx; auto const all = testable_amendments(); + using namespace jtx; testAMM( [&](AMM& ammAlice, Env& env) { @@ -2248,8 +2259,8 @@ private: { testcase("Withdraw"); - using namespace jtx; auto const all = testable_amendments(); + using namespace jtx; // Equal withdrawal by Carol: 1000000 of tokens, 10% of the current // pool @@ -2669,8 +2680,8 @@ private: testFeeVote() { testcase("Fee Vote"); - using namespace jtx; auto const all = testable_amendments(); + using namespace jtx; // One vote sets fee to 1%. testAMM([&](AMM& ammAlice, Env& env) { @@ -3014,6 +3025,10 @@ private: using namespace jtx; using namespace std::chrono; + // For now, just disable SAV entirely, which locks in the small Number + // mantissas + features = features - featureSingleAssetVault - featureLendingProtocol; + // Auction slot initially is owned by AMM creator, who pays 0 price. // Bid 110 tokens. Pay bidMin. @@ -3758,6 +3773,11 @@ private: testcase("Basic Payment"); using namespace jtx; + // For now, just disable SAV entirely, which locks in the small Number + // mantissas + features = features - featureSingleAssetVault - featureLendingProtocol - + featureLendingProtocol; + // Payment 100USD for 100XRP. // Force one path with tfNoRippleDirect. testAMM( @@ -4836,12 +4856,12 @@ private: testAmendment() { testcase("Amendment"); - using namespace jtx; FeatureBitset const all{testable_amendments()}; FeatureBitset const noAMM{all - featureAMM}; FeatureBitset const noNumber{all - fixUniversalNumber}; FeatureBitset const noAMMAndNumber{ all - featureAMM - fixUniversalNumber}; + using namespace jtx; for (auto const& feature : {noAMM, noNumber, noAMMAndNumber}) { @@ -6476,6 +6496,8 @@ private: Env env(*this, features, std::make_unique(&logs)); auto rules = env.current()->rules(); CurrentTransactionRulesGuard rg(rules); + NumberMantissaScaleGuard sg(MantissaRange::small); + for (auto const& t : tests) { auto getPool = [&](std::string const& v, bool isXRP) { @@ -7025,7 +7047,7 @@ private: {{xrpPool, iouPool}}, 889, std::nullopt, - {jtx::testable_amendments() | fixAMMv1_1}); + {testable_amendments() | fixAMMv1_1}); } void @@ -7566,6 +7588,7 @@ private: { auto const [amount, amount2, lptBalance] = amm.balances(GBP, EUR); + NumberMantissaScaleGuard sg(MantissaRange::small); NumberRoundModeGuard g( env.enabled(fixAMMv1_3) ? Number::upward : Number::getround()); auto const res = root2(amount * amount2); @@ -7880,7 +7903,7 @@ private: void run() override { - FeatureBitset const all{jtx::testable_amendments()}; + FeatureBitset const all{testable_amendments()}; testInvalidInstance(); testInstanceCreate(); testInvalidDeposit(all); diff --git a/src/test/app/EscrowToken_test.cpp b/src/test/app/EscrowToken_test.cpp index 955ca8f449..589a8b474e 100644 --- a/src/test/app/EscrowToken_test.cpp +++ b/src/test/app/EscrowToken_test.cpp @@ -559,12 +559,15 @@ struct EscrowToken_test : public beast::unit_test::suite env(pay(gw, bob, USD(1))); env.close(); + bool const largeMantissa = features[featureSingleAssetVault] || + features[featureLendingProtocol]; + // alice cannot create escrow for 1/10 iou - precision loss env(escrow::create(alice, bob, USD(1)), escrow::condition(escrow::cb1), escrow::finish_time(env.now() + 1s), fee(baseFee * 150), - ter(tecPRECISION_LOSS)); + ter(largeMantissa ? (TER)tesSUCCESS : (TER)tecPRECISION_LOSS)); env.close(); } } @@ -2076,12 +2079,15 @@ struct EscrowToken_test : public beast::unit_test::suite env(pay(gw, bob, USD(1))); env.close(); + bool const largeMantissa = features[featureSingleAssetVault] || + features[featureLendingProtocol]; + // alice cannot create escrow for 1/10 iou - precision loss env(escrow::create(alice, bob, USD(1)), escrow::condition(escrow::cb1), escrow::finish_time(env.now() + 1s), fee(baseFee * 150), - ter(tecPRECISION_LOSS)); + ter(largeMantissa ? (TER)tesSUCCESS : (TER)tecPRECISION_LOSS)); env.close(); auto const seq1 = env.seq(alice); @@ -3924,9 +3930,13 @@ public: { using namespace test::jtx; FeatureBitset const all{testable_amendments()}; - testIOUWithFeats(all); - testMPTWithFeats(all); - testMPTWithFeats(all - fixTokenEscrowV1); + for (FeatureBitset const& feats : + {all - featureSingleAssetVault - featureLendingProtocol, all}) + { + testIOUWithFeats(feats); + testMPTWithFeats(feats); + testMPTWithFeats(feats - fixTokenEscrowV1); + } } }; diff --git a/src/test/app/LendingHelpers_test.cpp b/src/test/app/LendingHelpers_test.cpp index 50efe0ebe3..55fffad6b0 100644 --- a/src/test/app/LendingHelpers_test.cpp +++ b/src/test/app/LendingHelpers_test.cpp @@ -104,7 +104,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Multiple payments remaining", .periodicRate = Number{5, -2}, .paymentsRemaining = 3, - .expectedPaymentFactor = Number{367208564631245, -15}, + .expectedPaymentFactor = Number{3672085646312450436, -19}, }, // from calc { .name = "Zero payments remaining", @@ -172,7 +172,7 @@ class LendingHelpers_test : public beast::unit_test::suite loanPeriodicRate(TenthBips32(100'000), 30 * 24 * 60 * 60), .paymentsRemaining = 3, .expectedPeriodicPayment = - Number{3895690663961231, -13}, // from calc + Number{389569066396123265, -15}, // from calc }, }; @@ -229,7 +229,8 @@ class LendingHelpers_test : public beast::unit_test::suite }, { .name = "Standard case", - .periodicPayment = Number{3895690663961231, -13}, // from calc + .periodicPayment = + Number{389569066396123265, -15}, // from calc .periodicRate = loanPeriodicRate(TenthBips32(100'000), 30 * 24 * 60 * 60), .paymentsRemaining = 3, @@ -426,7 +427,7 @@ class LendingHelpers_test : public beast::unit_test::suite NetClock::time_point{NetClock::duration{3'000}}, .nextPaymentDueDate = 2'000, .expectedLateInterest = - Number{3170979198376459, -17}, // from calc + Number{317097919837645865, -19}, // from calc }, }; @@ -519,7 +520,7 @@ class LendingHelpers_test : public beast::unit_test::suite .prevPaymentDate = 2'000, .paymentInterval = 30 * 24 * 60 * 60, .expectedAccruedInterest = - Number{1929012345679012, -17}, // from calc + Number{1929012345679012346, -20}, // from calc }, }; @@ -587,7 +588,7 @@ class LendingHelpers_test : public beast::unit_test::suite .startDate = 1'000, .closeInterestRate = TenthBips32{0}, .expectedFullPaymentInterest = - Number{1929012345679012, -17}, // from calc + Number{1929012345679012346, -20}, // from calc }, { .name = "Standard case", @@ -600,7 +601,7 @@ class LendingHelpers_test : public beast::unit_test::suite .startDate = 1'000, .closeInterestRate = TenthBips32{10'000}, .expectedFullPaymentInterest = - Number{1000192901234568, -13}, // from calc + Number{1000192901234567901, -16}, // from calc }, }; diff --git a/src/test/app/LoanBroker_test.cpp b/src/test/app/LoanBroker_test.cpp index 93be28e9e9..769ed40321 100644 --- a/src/test/app/LoanBroker_test.cpp +++ b/src/test/app/LoanBroker_test.cpp @@ -752,30 +752,36 @@ class LoanBroker_test : public beast::unit_test::suite // LoanBrokerID env(set(alice, vault.vaultID), loanBrokerID(nextKeylet.key), - ter(tecNO_ENTRY)); + ter(tecNO_ENTRY), + THISLINE); // VaultID env(set(alice, nextKeylet.key), loanBrokerID(broker->key()), - ter(tecNO_PERMISSION)); + ter(tecNO_ENTRY), + THISLINE); // Owner env(set(evan, vault.vaultID), loanBrokerID(broker->key()), - ter(tecNO_PERMISSION)); + ter(tecNO_PERMISSION), + THISLINE); // ManagementFeeRate env(set(alice, vault.vaultID), loanBrokerID(broker->key()), managementFeeRate(maxManagementFeeRate), - ter(temINVALID)); + ter(temINVALID), + THISLINE); // CoverRateMinimum env(set(alice, vault.vaultID), loanBrokerID(broker->key()), coverRateMinimum(maxManagementFeeRate), - ter(temINVALID)); + ter(temINVALID), + THISLINE); // CoverRateLiquidation env(set(alice, vault.vaultID), loanBrokerID(broker->key()), coverRateLiquidation(maxManagementFeeRate), - ter(temINVALID)); + ter(temINVALID), + THISLINE); // fields that can be changed testData = "Test Data 1234"; @@ -783,23 +789,43 @@ class LoanBroker_test : public beast::unit_test::suite env(set(alice, vault.vaultID), loanBrokerID(broker->key()), data(std::string(maxDataPayloadLength + 1, 'W')), - ter(temINVALID)); + ter(temINVALID), + THISLINE); // Bad debt maximum env(set(alice, vault.vaultID), loanBrokerID(broker->key()), debtMaximum(Number(-175, -1)), - ter(temINVALID)); + ter(temINVALID), + THISLINE); + Number debtMax{175, -1}; + if (vault.asset.integral()) + { + env(set(alice, vault.vaultID), + loanBrokerID(broker->key()), + data(testData), + debtMaximum(debtMax), + ter(tecPRECISION_LOSS), + THISLINE); + roundToAsset(vault.asset, debtMax); + } // Data & Debt maximum env(set(alice, vault.vaultID), loanBrokerID(broker->key()), data(testData), - debtMaximum(Number(175, -1))); + debtMaximum(debtMax), + THISLINE); }, [&](SLE::const_ref broker) { // Check the updated fields BEAST_EXPECT(checkVL(broker->at(sfData), testData)); - BEAST_EXPECT(broker->at(sfDebtMaximum) == Number(175, -1)); + Number const expected = + STAmount{vault.asset, Number(175, -1)}; + auto const actual = broker->at(sfDebtMaximum); + BEAST_EXPECTS( + actual == expected, + "Expected: " + to_string(expected) + + ", Actual: " + to_string(actual)); }); lifecycle( @@ -1457,9 +1483,14 @@ class LoanBroker_test : public beast::unit_test::suite env.close(); PrettyAsset const asset = [&]() { - env(trust(alice, issuer["IOU"](1'000'000)), THISLINE); + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); env.close(); - return PrettyAsset(issuer["IOU"]); + PrettyAsset const mptAsset = mptt["MPT"]; + mptt.authorize({.account = alice}); + env.close(); + return mptAsset; }(); env(pay(issuer, alice, asset(100'000)), THISLINE); @@ -1512,6 +1543,40 @@ class LoanBroker_test : public beast::unit_test::suite tx2[sfDebtMaximum] = 0; env(tx2, ter(tesSUCCESS), THISLINE); + + tx2[sfDebtMaximum] = Json::Value::maxInt; + env(tx2, ter(tesSUCCESS), THISLINE); + + { + auto const dm = power(2, 64) - 1; + BEAST_EXPECT(dm > maxMPTokenAmount); + tx2[sfDebtMaximum] = dm; + env(tx2, ter(temINVALID), THISLINE); + } + + { + auto const dm = power(2, 63) - 1; + BEAST_EXPECTS(dm > maxMPTokenAmount, to_string(dm)); + tx2[sfDebtMaximum] = dm; + env(tx2, ter(temINVALID), THISLINE); + } + + { + auto const dm = power(2, 63) - 3; + BEAST_EXPECTS(dm == maxMPTokenAmount, to_string(dm)); + tx2[sfDebtMaximum] = dm; + env(tx2, ter(tesSUCCESS), THISLINE); + } + + { + auto const dm = 2 * (power(2, 62) - 1) + 1; + BEAST_EXPECTS(dm == maxMPTokenAmount, to_string(dm)); + tx2[sfDebtMaximum] = dm; + env(tx2, ter(tesSUCCESS), THISLINE); + } + + tx2[sfDebtMaximum] = Number{9223372036854775807, 0}; + env(tx2, ter(tesSUCCESS), THISLINE); } void diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index e4f5360043..e9780211de 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -352,8 +352,14 @@ protected: env.balance(account, broker.asset) - (balanceBefore - balanceChangeAmount), borrowerScale); - env.test.BEAST_EXPECT( - roundToScale(difference, loanScale) >= beast::zero); + env.test.expect( + roundToScale(difference, loanScale) >= beast::zero, + "Balance before: " + to_string(balanceBefore.value()) + + ", expected change: " + to_string(balanceChangeAmount) + + ", difference (balance after - expected): " + + to_string(difference), + __FILE__, + __LINE__); } } @@ -2396,7 +2402,7 @@ protected: interval * Number(12, -2) / secondsInYear; BEAST_EXPECT( periodicRate == - Number(2283105022831050, -21, Number::unchecked{})); + Number(2283105022831050228ULL, -24, Number::normalized{})); STAmount const principalOutstanding{ broker.asset, state.principalOutstanding}; STAmount const accruedInterest{ @@ -2449,6 +2455,10 @@ protected: getCurrentState(env, broker, loanKeylet, verifyLoanStatus); env.close(); + BEAST_EXPECT( + STAmount(broker.asset, state.periodicPayment) == + broker.asset(Number(8333457002039338267, -17))); + // Make all the payments in one transaction // service fee is 2 auto const startingPayments = state.paymentRemaining; @@ -2456,15 +2466,28 @@ protected: NumberRoundModeGuard mg(Number::upward); auto const rawPayoff = startingPayments * (state.periodicPayment + broker.asset(2).value()); - STAmount const payoffAmount{broker.asset, rawPayoff}; + STAmount payoffAmount{broker.asset, rawPayoff}; BEAST_EXPECTS( payoffAmount == - broker.asset(Number(1024014840139457, -12)), + broker.asset(Number(1024014840244721, -12)), to_string(payoffAmount)); BEAST_EXPECT(payoffAmount > state.principalOutstanding); + + payoffAmount = roundToScale(payoffAmount, state.loanScale); + return payoffAmount; }(); + auto const totalPayoffValue = state.totalValue + + startingPayments * broker.asset(2).value(); + STAmount const totalPayoffAmount{ + broker.asset, totalPayoffValue}; + + BEAST_EXPECTS( + totalPayoffAmount == payoffAmount, + "Payoff amount: " + to_string(payoffAmount) + + ". Total Value: " + to_string(totalPayoffAmount)); + singlePayment( loanKeylet, verifyLoanStatus, @@ -2633,7 +2656,7 @@ protected: interval * Number(12, -2) / secondsInYear; BEAST_EXPECT( periodicRate == - Number(2283105022831050, -21, Number::unchecked{})); + Number(2283105022831050228, -24, Number::normalized{})); STAmount const roundedPeriodicPayment{ broker.asset, roundPeriodicPayment( @@ -2651,7 +2674,7 @@ protected: roundedPeriodicPayment == roundToScale( broker.asset( - Number(8333457001162141, -14), Number::upward), + Number(8333457002039338267, -17), Number::upward), state.loanScale, Number::upward)); // 83334570.01162141 @@ -2666,7 +2689,7 @@ protected: totalDue == roundToScale( broker.asset( - Number(8533457001162141, -14), Number::upward), + Number(8533457002039338267, -17), Number::upward), state.loanScale, Number::upward)); @@ -2702,7 +2725,7 @@ protected: transactionAmount == roundToScale( broker.asset( - Number(9533457001162141, -14), Number::upward), + Number(9533457002039400, -14), Number::upward), state.loanScale, Number::upward)); @@ -2735,9 +2758,15 @@ protected: state.paymentRemaining, broker.params.managementFeeRate); - BEAST_EXPECT( - paymentComponents.trackedValueDelta <= - roundedPeriodicPayment); + BEAST_EXPECTS( + paymentComponents.specialCase == + detail::PaymentSpecialCase::final || + paymentComponents.trackedValueDelta <= + roundedPeriodicPayment, + "Delta: " + + to_string(paymentComponents.trackedValueDelta) + + ", periodic payment: " + + to_string(roundedPeriodicPayment)); xrpl::LoanState const nextTrueState = computeTheoreticalLoanState( @@ -2792,8 +2821,10 @@ protected: paymentComponents.trackedInterestPart() + paymentComponents.trackedManagementFeeDelta); BEAST_EXPECT( + paymentComponents.specialCase == + detail::PaymentSpecialCase::final || paymentComponents.trackedValueDelta <= - roundedPeriodicPayment); + roundedPeriodicPayment); BEAST_EXPECT( state.paymentRemaining < 12 || @@ -2804,7 +2835,7 @@ protected: Number::upward) == roundToScale( broker.asset( - Number(8333228695260180, -14), + Number(8333228691531218890, -17), Number::upward), state.loanScale, Number::upward)); @@ -3689,7 +3720,7 @@ protected: env(pay(issuer, borrower, mptAsset(10'000))); env.close(); - std::array const assets{xrpAsset, mptAsset, iouAsset}; + std::array const assets{iouAsset, xrpAsset, mptAsset}; // Create vaults and loan brokers std::vector brokers; @@ -5041,7 +5072,6 @@ protected: auto const loanSetFee = fee(env.current()->fees().base * 2); Number const principalRequest{1, 3}; - auto const startDate = env.now() + 60s; auto createJson = env.json( set(borrower, broker.brokerID, principalRequest), @@ -5065,13 +5095,13 @@ protected: auto const keylet = keylet::loan(broker.brokerID, loanSequence); createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); - env(createJson, ter(tecPRECISION_LOSS), THISLINE); - env.close(startDate); + env(createJson, THISLINE); + env.close(); auto loanPayTx = env.json( pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); loanPayTx["Amount"]["value"] = "0.000281284125490196"; - env(loanPayTx, ter(tecNO_ENTRY)); + env(loanPayTx, ter(tecINSUFFICIENT_PAYMENT), THISLINE); env.close(); } @@ -5640,21 +5670,26 @@ protected: BEAST_EXPECT(beforeState.periodicPayment > 0); // pay all but the last payment - Number const payment = beforeState.periodicPayment * (total - 1); - XRPAmount const payFee{ - baseFee * ((total - 1) / loanPaymentsPerFeeIncrement + 1)}; - auto loanPayTx = env.json( - pay(borrower, keylet.key, STAmount{broker.asset, payment}), - fee(payFee)); - env(loanPayTx, ter(tesSUCCESS)); - env.close(); + { + NumberRoundModeGuard mg{Number::upward}; + Number const payment = + beforeState.periodicPayment * (total - 1); + XRPAmount const payFee{ + baseFee * ((total - 1) / loanPaymentsPerFeeIncrement + 1)}; + STAmount const paymentAmount = roundToScale( + STAmount{broker.asset, payment}, beforeState.loanScale); + auto loanPayTx = env.json( + pay(borrower, keylet.key, paymentAmount), fee(payFee)); + env(loanPayTx, ter(tesSUCCESS)); + env.close(); + } // The loan is on the last payment auto const afterState = getCurrentState(env, broker, keylet); + BEAST_EXPECT(afterState.paymentRemaining == 1); BEAST_EXPECT(afterState.nextPaymentDate == maxTime - grace); BEAST_EXPECT( afterState.previousPaymentDate == maxTime - grace - interval); - BEAST_EXPECT(afterState.paymentRemaining == 1); } } diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index 747f78ef6b..65cb753755 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -1594,7 +1594,7 @@ class MPToken_test : public beast::unit_test::suite jv[jss::secret] = alice.name(); jv[jss::tx_json] = pay(alice, bob, mpt); jv[jss::tx_json][jss::Amount][jss::value] = - to_string(maxMPTokenAmount + 1); + std::to_string(maxMPTokenAmount + 1); auto const jrr = env.rpc("json", "submit", to_string(jv)); BEAST_EXPECT(jrr[jss::result][jss::error] == "invalidParams"); } @@ -2474,7 +2474,7 @@ class MPToken_test : public beast::unit_test::suite alice.name(), makeMptID(env.seq(alice), alice)); Json::Value jv = claw(alice, mpt(1), bob); - jv[jss::Amount][jss::value] = to_string(maxMPTokenAmount + 1); + jv[jss::Amount][jss::value] = std::to_string(maxMPTokenAmount + 1); Json::Value jv1; jv1[jss::secret] = alice.name(); jv1[jss::tx_json] = jv; diff --git a/src/test/basics/IOUAmount_test.cpp b/src/test/basics/IOUAmount_test.cpp index 305f2c83a1..d299f439d4 100644 --- a/src/test/basics/IOUAmount_test.cpp +++ b/src/test/basics/IOUAmount_test.cpp @@ -141,15 +141,28 @@ public: { testcase("IOU strings"); - BEAST_EXPECT(to_string(IOUAmount(-2, 0)) == "-2"); - BEAST_EXPECT(to_string(IOUAmount(0, 0)) == "0"); - BEAST_EXPECT(to_string(IOUAmount(2, 0)) == "2"); - BEAST_EXPECT(to_string(IOUAmount(25, -3)) == "0.025"); - BEAST_EXPECT(to_string(IOUAmount(-25, -3)) == "-0.025"); - BEAST_EXPECT(to_string(IOUAmount(25, 1)) == "250"); - BEAST_EXPECT(to_string(IOUAmount(-25, 1)) == "-250"); - BEAST_EXPECT(to_string(IOUAmount(2, 20)) == "2000000000000000e5"); - BEAST_EXPECT(to_string(IOUAmount(-2, -20)) == "-2000000000000000e-35"); + auto test = [this](IOUAmount const& n, std::string const& expected) { + auto const result = to_string(n); + std::stringstream ss; + ss << "to_string(" << result << "). Expected: " << expected; + BEAST_EXPECTS(result == expected, ss.str()); + }; + + for (auto const mantissaSize : + {MantissaRange::small, MantissaRange::large}) + { + NumberMantissaScaleGuard mg(mantissaSize); + + test(IOUAmount(-2, 0), "-2"); + test(IOUAmount(0, 0), "0"); + test(IOUAmount(2, 0), "2"); + test(IOUAmount(25, -3), "0.025"); + test(IOUAmount(-25, -3), "-0.025"); + test(IOUAmount(25, 1), "250"); + test(IOUAmount(-25, 1), "-250"); + test(IOUAmount(2, 20), "2e20"); + test(IOUAmount(-2, -20), "-2e-20"); + } } void diff --git a/src/test/basics/Number_test.cpp b/src/test/basics/Number_test.cpp index b7c5ee45b7..1fa5ae6e8f 100644 --- a/src/test/basics/Number_test.cpp +++ b/src/test/basics/Number_test.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -14,46 +15,84 @@ public: void testZero() { - testcase("zero"); + testcase << "zero " << to_string(Number::getMantissaScale()); - Number const z{0, 0}; + for (Number const& z : {Number{0, 0}, Number{0}}) + { + BEAST_EXPECT(z.mantissa() == 0); + BEAST_EXPECT(z.exponent() == Number{}.exponent()); - BEAST_EXPECT(z.mantissa() == 0); - BEAST_EXPECT(z.exponent() == Number{}.exponent()); - - BEAST_EXPECT((z + z) == z); - BEAST_EXPECT((z - z) == z); - BEAST_EXPECT(z == -z); + BEAST_EXPECT((z + z) == z); + BEAST_EXPECT((z - z) == z); + BEAST_EXPECT(z == -z); + } } void test_limits() { - testcase("test_limits"); + auto const scale = Number::getMantissaScale(); + testcase << "test_limits " << to_string(scale); bool caught = false; + auto const minMantissa = Number::minMantissa(); try { - Number x{10'000'000'000'000'000, 32768}; + Number x = + Number{false, minMantissa * 10, 32768, Number::normalized{}}; } catch (std::overflow_error const&) { caught = true; } BEAST_EXPECT(caught); - Number x{10'000'000'000'000'000, 32767}; - BEAST_EXPECT((x == Number{1'000'000'000'000'000, 32768})); - Number z{1'000'000'000'000'000, -32769}; - BEAST_EXPECT(z == Number{}); - Number y{1'000'000'000'000'001'500, 32000}; - BEAST_EXPECT((y == Number{1'000'000'000'000'002, 32003})); - Number m{std::numeric_limits::min()}; - BEAST_EXPECT((m == Number{-9'223'372'036'854'776, 3})); - Number M{std::numeric_limits::max()}; - BEAST_EXPECT((M == Number{9'223'372'036'854'776, 3})); + + auto test = [this](auto const& x, auto const& y, int line) { + auto const result = x == y; + std::stringstream ss; + ss << x << " == " << y << " -> " << (result ? "true" : "false"); + expect(result, ss.str(), __FILE__, line); + }; + + test( + Number{false, minMantissa * 10, 32767, Number::normalized{}}, + Number{false, minMantissa, 32768, Number::normalized{}}, + __LINE__); + test( + Number{false, minMantissa, -32769, Number::normalized{}}, + Number{}, + __LINE__); + test( + Number{false, minMantissa, 32000, Number::normalized{}} * 1'000 + + Number{false, 1'500, 32000, Number::normalized{}}, + Number{false, minMantissa + 2, 32003, Number::normalized{}}, + __LINE__); + // 9,223,372,036,854,775,808 + + test( + Number{std::numeric_limits::min()}, + scale == MantissaRange::small + ? Number{-9'223'372'036'854'776, 3} + : Number{true, 9'223'372'036'854'775'808ULL, 0, Number::normalized{}}, + __LINE__); + test( + Number{std::numeric_limits::min() + 1}, + scale == MantissaRange::small ? Number{-9'223'372'036'854'776, 3} + : Number{-9'223'372'036'854'775'807}, + __LINE__); + test( + Number{std::numeric_limits::max()}, + Number{ + scale == MantissaRange::small + ? 9'223'372'036'854'776 + : std::numeric_limits::max(), + 18 - Number::mantissaLog()}, + __LINE__); caught = false; try { - Number q{99'999'999'999'999'999, 32767}; + [[maybe_unused]] + Number q = + Number{false, minMantissa, 32767, Number::normalized{}} * 100; } catch (std::overflow_error const&) { @@ -65,76 +104,307 @@ public: void test_add() { - testcase("test_add"); + auto const scale = Number::getMantissaScale(); + testcase << "test_add " << to_string(scale); + using Case = std::tuple; - Case c[]{ - {Number{1'000'000'000'000'000, -15}, - Number{6'555'555'555'555'555, -29}, - Number{1'000'000'000'000'066, -15}}, - {Number{-1'000'000'000'000'000, -15}, - Number{-6'555'555'555'555'555, -29}, - Number{-1'000'000'000'000'066, -15}}, - {Number{-1'000'000'000'000'000, -15}, - Number{6'555'555'555'555'555, -29}, - Number{-9'999'999'999'999'344, -16}}, - {Number{-6'555'555'555'555'555, -29}, - Number{1'000'000'000'000'000, -15}, - Number{9'999'999'999'999'344, -16}}, - {Number{}, Number{5}, Number{5}}, - {Number{5'555'555'555'555'555, -32768}, - Number{-5'555'555'555'555'554, -32768}, - Number{0}}, - {Number{-9'999'999'999'999'999, -31}, - Number{1'000'000'000'000'000, -15}, - Number{9'999'999'999'999'990, -16}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x + y == z); - bool caught = false; - try + auto const cSmall = std::to_array( + {{Number{1'000'000'000'000'000, -15}, + Number{6'555'555'555'555'555, -29}, + Number{1'000'000'000'000'066, -15}}, + {Number{-1'000'000'000'000'000, -15}, + Number{-6'555'555'555'555'555, -29}, + Number{-1'000'000'000'000'066, -15}}, + {Number{-1'000'000'000'000'000, -15}, + Number{6'555'555'555'555'555, -29}, + Number{-9'999'999'999'999'344, -16}}, + {Number{-6'555'555'555'555'555, -29}, + Number{1'000'000'000'000'000, -15}, + Number{9'999'999'999'999'344, -16}}, + {Number{}, Number{5}, Number{5}}, + {Number{5}, Number{}, Number{5}}, + {Number{5'555'555'555'555'555, -32768}, + Number{-5'555'555'555'555'554, -32768}, + Number{0}}, + {Number{-9'999'999'999'999'999, -31}, + Number{1'000'000'000'000'000, -15}, + Number{9'999'999'999'999'990, -16}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items from C + // with larger mantissa + { + {Number{1'000'000'000'000'000, -15}, + Number{6'555'555'555'555'555, -29}, + Number{1'000'000'000'000'065'556, -18}}, + {Number{-1'000'000'000'000'000, -15}, + Number{-6'555'555'555'555'555, -29}, + Number{-1'000'000'000'000'065'556, -18}}, + {Number{-1'000'000'000'000'000, -15}, + Number{6'555'555'555'555'555, -29}, + Number{ + true, + 9'999'999'999'999'344'444ULL, + -19, + Number::normalized{}}}, + {Number{-6'555'555'555'555'555, -29}, + Number{1'000'000'000'000'000, -15}, + Number{ + false, + 9'999'999'999'999'344'444ULL, + -19, + Number::normalized{}}}, + {Number{}, Number{5}, Number{5}}, + {Number{5}, Number{}, Number{5}}, + {Number{5'555'555'555'555'555'000, -32768}, + Number{-5'555'555'555'555'554'000, -32768}, + Number{0}}, + {Number{-9'999'999'999'999'999, -31}, + Number{1'000'000'000'000'000, -15}, + Number{9'999'999'999'999'990, -16}}, + // Items from cSmall expanded for the larger mantissa + {Number{1'000'000'000'000'000'000, -18}, + Number{6'555'555'555'555'555'555, -35}, + Number{1'000'000'000'000'000'066, -18}}, + {Number{-1'000'000'000'000'000'000, -18}, + Number{-6'555'555'555'555'555'555, -35}, + Number{-1'000'000'000'000'000'066, -18}}, + {Number{-1'000'000'000'000'000'000, -18}, + Number{6'555'555'555'555'555'555, -35}, + Number{ + true, + 9'999'999'999'999'999'344ULL, + -19, + Number::normalized{}}}, + {Number{-6'555'555'555'555'555'555, -35}, + Number{1'000'000'000'000'000'000, -18}, + Number{ + false, + 9'999'999'999'999'999'344ULL, + -19, + Number::normalized{}}}, + {Number{}, Number{5}, Number{5}}, + {Number{5'555'555'555'555'555'555, -32768}, + Number{-5'555'555'555'555'555'554, -32768}, + Number{0}}, + {Number{ + true, + 9'999'999'999'999'999'999ULL, + -37, + Number::normalized{}}, + Number{1'000'000'000'000'000'000, -18}, + Number{ + false, + 9'999'999'999'999'999'990ULL, + -19, + Number::normalized{}}}, + {Number{Number::maxRep}, + Number{6, -1}, + Number{Number::maxRep / 10, 1}}, + {Number{Number::maxRep - 1}, + Number{1, 0}, + Number{Number::maxRep}}, + // Test extremes + { + // Each Number operand rounds up, so the actual mantissa is + // minMantissa + Number{ + false, + 9'999'999'999'999'999'999ULL, + 0, + Number::normalized{}}, + Number{ + false, + 9'999'999'999'999'999'999ULL, + 0, + Number::normalized{}}, + Number{2, 19}, + }, + { + // Does not round. Mantissas are going to be > maxRep, so if + // added together as uint64_t's, the result will overflow. + // With addition using uint128_t, there's no problem. After + // normalizing, the resulting mantissa ends up less than + // maxRep. + Number{ + false, + 9'999'999'999'999'999'990ULL, + 0, + Number::normalized{}}, + Number{ + false, + 9'999'999'999'999'999'990ULL, + 0, + Number::normalized{}}, + Number{ + false, + 1'999'999'999'999'999'998ULL, + 1, + Number::normalized{}}, + }, + }); + auto test = [this](auto const& c) { + for (auto const& [x, y, z] : c) + { + auto const result = x + y; + std::stringstream ss; + ss << x << " + " << y << " = " << result << ". Expected: " << z; + BEAST_EXPECTS(result == z, ss.str()); + } + }; + if (scale == MantissaRange::small) + test(cSmall); + else + test(cLarge); { - Number{9'999'999'999'999'999, 32768} + - Number{5'000'000'000'000'000, 32767}; + bool caught = false; + try + { + Number{ + false, Number::maxMantissa(), 32768, Number::normalized{}} + + Number{ + false, + Number::minMantissa(), + 32767, + Number::normalized{}} * + 5; + } + catch (std::overflow_error const&) + { + caught = true; + } + BEAST_EXPECT(caught); } - catch (std::overflow_error const&) - { - caught = true; - } - BEAST_EXPECT(caught); } void test_sub() { - testcase("test_sub"); + auto const scale = Number::getMantissaScale(); + testcase << "test_sub " << to_string(scale); + using Case = std::tuple; - Case c[]{ - {Number{1'000'000'000'000'000, -15}, - Number{6'555'555'555'555'555, -29}, - Number{9'999'999'999'999'344, -16}}, - {Number{6'555'555'555'555'555, -29}, - Number{1'000'000'000'000'000, -15}, - Number{-9'999'999'999'999'344, -16}}, - {Number{1'000'000'000'000'000, -15}, - Number{1'000'000'000'000'000, -15}, - Number{0}}, - {Number{1'000'000'000'000'000, -15}, - Number{1'000'000'000'000'001, -15}, - Number{-1'000'000'000'000'000, -30}}, - {Number{1'000'000'000'000'001, -15}, - Number{1'000'000'000'000'000, -15}, - Number{1'000'000'000'000'000, -30}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x - y == z); + auto const cSmall = std::to_array( + {{Number{1'000'000'000'000'000, -15}, + Number{6'555'555'555'555'555, -29}, + Number{9'999'999'999'999'344, -16}}, + {Number{6'555'555'555'555'555, -29}, + Number{1'000'000'000'000'000, -15}, + Number{-9'999'999'999'999'344, -16}}, + {Number{1'000'000'000'000'000, -15}, + Number{1'000'000'000'000'000, -15}, + Number{0}}, + {Number{1'000'000'000'000'000, -15}, + Number{1'000'000'000'000'001, -15}, + Number{-1'000'000'000'000'000, -30}}, + {Number{1'000'000'000'000'001, -15}, + Number{1'000'000'000'000'000, -15}, + Number{1'000'000'000'000'000, -30}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items from C + // with larger mantissa + { + {Number{1'000'000'000'000'000, -15}, + Number{6'555'555'555'555'555, -29}, + Number{ + false, + 9'999'999'999'999'344'444ULL, + -19, + Number::normalized{}}}, + {Number{6'555'555'555'555'555, -29}, + Number{1'000'000'000'000'000, -15}, + Number{ + true, + 9'999'999'999'999'344'444ULL, + -19, + Number::normalized{}}}, + {Number{1'000'000'000'000'000, -15}, + Number{1'000'000'000'000'000, -15}, + Number{0}}, + {Number{1'000'000'000'000'000, -15}, + Number{1'000'000'000'000'001, -15}, + Number{-1'000'000'000'000'000, -30}}, + {Number{1'000'000'000'000'001, -15}, + Number{1'000'000'000'000'000, -15}, + Number{1'000'000'000'000'000, -30}}, + // Items from cSmall expanded for the larger mantissa + {Number{1'000'000'000'000'000'000, -18}, + Number{6'555'555'555'555'555'555, -32}, + Number{ + false, + 9'999'999'999'999'344'444ULL, + -19, + Number::normalized{}}}, + {Number{6'555'555'555'555'555'555, -32}, + Number{1'000'000'000'000'000'000, -18}, + Number{ + true, + 9'999'999'999'999'344'444ULL, + -19, + Number::normalized{}}}, + {Number{1'000'000'000'000'000'000, -18}, + Number{1'000'000'000'000'000'000, -18}, + Number{0}}, + {Number{1'000'000'000'000'000'000, -18}, + Number{1'000'000'000'000'000'001, -18}, + Number{-1'000'000'000'000'000'000, -36}}, + {Number{1'000'000'000'000'000'001, -18}, + Number{1'000'000'000'000'000'000, -18}, + Number{1'000'000'000'000'000'000, -36}}, + {Number{Number::maxRep}, + Number{6, -1}, + Number{Number::maxRep - 1}}, + {Number{false, Number::maxRep + 1, 0, Number::normalized{}}, + Number{1, 0}, + Number{Number::maxRep / 10 + 1, 1}}, + {Number{false, Number::maxRep + 1, 0, Number::normalized{}}, + Number{3, 0}, + Number{Number::maxRep}}, + {power(2, 63), Number{3, 0}, Number{Number::maxRep}}, + }); + auto test = [this](auto const& c) { + for (auto const& [x, y, z] : c) + { + auto const result = x - y; + std::stringstream ss; + ss << x << " - " << y << " = " << result << ". Expected: " << z; + BEAST_EXPECTS(result == z, ss.str()); + } + }; + if (scale == MantissaRange::small) + test(cSmall); + else + test(cLarge); } void test_mul() { - testcase("test_mul"); + auto const scale = Number::getMantissaScale(); + testcase << "test_mul " << to_string(scale); + using Case = std::tuple; + auto test = [this](auto const& c) { + for (auto const& [x, y, z] : c) + { + auto const result = x * y; + std::stringstream ss; + ss << x << " * " << y << " = " << result << ". Expected: " << z; + BEAST_EXPECTS(result == z, ss.str()); + } + }; + auto tests = [&](auto const& cSmall, auto const& cLarge) { + if (scale == MantissaRange::small) + test(cSmall); + else + test(cLarge); + }; + auto const maxMantissa = Number::maxMantissa(); + saveNumberRoundMode save{Number::setround(Number::to_nearest)}; { - Case c[]{ + auto const cSmall = std::to_array({ {Number{7}, Number{8}, Number{56}}, {Number{1414213562373095, -15}, Number{1414213562373095, -15}, @@ -150,166 +420,520 @@ public: Number{1000000000000000, -14}}, {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, - Number{0}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x * y == z); + Number{0}}, + // Maximum mantissa range + {Number{9'999'999'999'999'999, 0}, + Number{9'999'999'999'999'999, 0}, + Number{9'999'999'999'999'998, 16}}, + }); + auto const cLarge = std::to_array({ + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items + // from C with larger mantissa + {Number{7}, Number{8}, Number{56}}, + {Number{1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{1999999999999999862, -18}}, + {Number{-1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{-1999999999999999862, -18}}, + {Number{-1414213562373095, -15}, + Number{-1414213562373095, -15}, + Number{1999999999999999862, -18}}, + {Number{3214285714285706, -15}, + Number{3111111111111119, -15}, + Number{ + false, + 9'999'999'999'999'999'579ULL, + -18, + Number::normalized{}}}, + {Number{1000000000000000000, -32768}, + Number{1000000000000000000, -32768}, + Number{0}}, + // Items from cSmall expanded for the larger mantissa, + // except duplicates. Sadly, it looks like sqrt(2)^2 != 2 + // with higher precision + {Number{1414213562373095049, -18}, + Number{1414213562373095049, -18}, + Number{2000000000000000001, -18}}, + {Number{-1414213562373095048, -18}, + Number{1414213562373095048, -18}, + Number{-1999999999999999998, -18}}, + {Number{-1414213562373095048, -18}, + Number{-1414213562373095049, -18}, + Number{1999999999999999999, -18}}, + {Number{3214285714285714278, -18}, + Number{3111111111111111119, -18}, + Number{10, 0}}, + // Maximum mantissa range - rounds up to 1e19 + {Number{false, maxMantissa, 0, Number::normalized{}}, + Number{false, maxMantissa, 0, Number::normalized{}}, + Number{1, 38}}, + // Maximum int64 range + {Number{Number::maxRep, 0}, + Number{Number::maxRep, 0}, + Number{85'070'591'730'234'615'85, 19}}, + }); + tests(cSmall, cLarge); } Number::setround(Number::towards_zero); + testcase << "test_mul " << to_string(Number::getMantissaScale()) + << " towards_zero"; { - Case c[]{ - {Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{1999999999999999, -15}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-1999999999999999, -15}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{1999999999999999, -15}}, - {Number{3214285714285706, -15}, - Number{3111111111111119, -15}, - Number{9999999999999999, -15}}, - {Number{1000000000000000, -32768}, - Number{1000000000000000, -32768}, - Number{0}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x * y == z); + auto const cSmall = std::to_array( + {{Number{7}, Number{8}, Number{56}}, + {Number{1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{1999999999999999, -15}}, + {Number{-1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{-1999999999999999, -15}}, + {Number{-1414213562373095, -15}, + Number{-1414213562373095, -15}, + Number{1999999999999999, -15}}, + {Number{3214285714285706, -15}, + Number{3111111111111119, -15}, + Number{9999999999999999, -15}}, + {Number{1000000000000000, -32768}, + Number{1000000000000000, -32768}, + Number{0}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items + // from C with larger mantissa + { + {Number{7}, Number{8}, Number{56}}, + {Number{1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{1999999999999999861, -18}}, + {Number{-1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{-1999999999999999861, -18}}, + {Number{-1414213562373095, -15}, + Number{-1414213562373095, -15}, + Number{1999999999999999861, -18}}, + {Number{3214285714285706, -15}, + Number{3111111111111119, -15}, + Number{ + false, + 9999999999999999579ULL, + -18, + Number::normalized{}}}, + {Number{1000000000000000000, -32768}, + Number{1000000000000000000, -32768}, + Number{0}}, + // Items from cSmall expanded for the larger mantissa, + // except duplicates. Sadly, it looks like sqrt(2)^2 != 2 + // with higher precision + {Number{1414213562373095049, -18}, + Number{1414213562373095049, -18}, + Number{2, 0}}, + {Number{-1414213562373095048, -18}, + Number{1414213562373095048, -18}, + Number{-1999999999999999997, -18}}, + {Number{-1414213562373095048, -18}, + Number{-1414213562373095049, -18}, + Number{1999999999999999999, -18}}, + {Number{3214285714285714278, -18}, + Number{3111111111111111119, -18}, + Number{10, 0}}, + // Maximum mantissa range - rounds down to maxMantissa/10e1 + // 99'999'999'999'999'999'800'000'000'000'000'000'100 + {Number{false, maxMantissa, 0, Number::normalized{}}, + Number{false, maxMantissa, 0, Number::normalized{}}, + Number{ + false, + maxMantissa / 10 - 1, + 20, + Number::normalized{}}}, + // Maximum int64 range + // 85'070'591'730'234'615'847'396'907'784'232'501'249 + {Number{Number::maxRep, 0}, + Number{Number::maxRep, 0}, + Number{85'070'591'730'234'615'84, 19}}, + }); + tests(cSmall, cLarge); } Number::setround(Number::downward); + testcase << "test_mul " << to_string(Number::getMantissaScale()) + << " downward"; { - Case c[]{ - {Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{1999999999999999, -15}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-2000000000000000, -15}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{1999999999999999, -15}}, - {Number{3214285714285706, -15}, - Number{3111111111111119, -15}, - Number{9999999999999999, -15}}, - {Number{1000000000000000, -32768}, - Number{1000000000000000, -32768}, - Number{0}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x * y == z); + auto const cSmall = std::to_array( + {{Number{7}, Number{8}, Number{56}}, + {Number{1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{1999999999999999, -15}}, + {Number{-1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{-2000000000000000, -15}}, + {Number{-1414213562373095, -15}, + Number{-1414213562373095, -15}, + Number{1999999999999999, -15}}, + {Number{3214285714285706, -15}, + Number{3111111111111119, -15}, + Number{9999999999999999, -15}}, + {Number{1000000000000000, -32768}, + Number{1000000000000000, -32768}, + Number{0}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items + // from C with larger mantissa + { + {Number{7}, Number{8}, Number{56}}, + {Number{1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{1999999999999999861, -18}}, + {Number{-1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{-1999999999999999862, -18}}, + {Number{-1414213562373095, -15}, + Number{-1414213562373095, -15}, + Number{1999999999999999861, -18}}, + {Number{3214285714285706, -15}, + Number{3111111111111119, -15}, + Number{ + false, + 9'999'999'999'999'999'579ULL, + -18, + Number::normalized{}}}, + {Number{1000000000000000000, -32768}, + Number{1000000000000000000, -32768}, + Number{0}}, + // Items from cSmall expanded for the larger mantissa, + // except duplicates. Sadly, it looks like sqrt(2)^2 != 2 + // with higher precision + {Number{1414213562373095049, -18}, + Number{1414213562373095049, -18}, + Number{2, 0}}, + {Number{-1414213562373095048, -18}, + Number{1414213562373095048, -18}, + Number{-1999999999999999998, -18}}, + {Number{-1414213562373095048, -18}, + Number{-1414213562373095049, -18}, + Number{1999999999999999999, -18}}, + {Number{3214285714285714278, -18}, + Number{3111111111111111119, -18}, + Number{10, 0}}, + // Maximum mantissa range - rounds down to maxMantissa/10e1 + // 99'999'999'999'999'999'800'000'000'000'000'000'100 + {Number{false, maxMantissa, 0, Number::normalized{}}, + Number{false, maxMantissa, 0, Number::normalized{}}, + Number{ + false, + maxMantissa / 10 - 1, + 20, + Number::normalized{}}}, + // Maximum int64 range + // 85'070'591'730'234'615'847'396'907'784'232'501'249 + {Number{Number::maxRep, 0}, + Number{Number::maxRep, 0}, + Number{85'070'591'730'234'615'84, 19}}, + }); + tests(cSmall, cLarge); } Number::setround(Number::upward); + testcase << "test_mul " << to_string(Number::getMantissaScale()) + << " upward"; { - Case c[]{ - {Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{2000000000000000, -15}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-1999999999999999, -15}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{2000000000000000, -15}}, - {Number{3214285714285706, -15}, - Number{3111111111111119, -15}, - Number{1000000000000000, -14}}, - {Number{1000000000000000, -32768}, - Number{1000000000000000, -32768}, - Number{0}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x * y == z); + auto const cSmall = std::to_array( + {{Number{7}, Number{8}, Number{56}}, + {Number{1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{2000000000000000, -15}}, + {Number{-1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{-1999999999999999, -15}}, + {Number{-1414213562373095, -15}, + Number{-1414213562373095, -15}, + Number{2000000000000000, -15}}, + {Number{3214285714285706, -15}, + Number{3111111111111119, -15}, + Number{1000000000000000, -14}}, + {Number{1000000000000000, -32768}, + Number{1000000000000000, -32768}, + Number{0}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items + // from C with larger mantissa + { + {Number{7}, Number{8}, Number{56}}, + {Number{1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{1999999999999999862, -18}}, + {Number{-1414213562373095, -15}, + Number{1414213562373095, -15}, + Number{-1999999999999999861, -18}}, + {Number{-1414213562373095, -15}, + Number{-1414213562373095, -15}, + Number{1999999999999999862, -18}}, + {Number{3214285714285706, -15}, + Number{3111111111111119, -15}, + Number{999999999999999958, -17}}, + {Number{1000000000000000000, -32768}, + Number{1000000000000000000, -32768}, + Number{0}}, + // Items from cSmall expanded for the larger mantissa, + // except duplicates. Sadly, it looks like sqrt(2)^2 != 2 + // with higher precision + {Number{1414213562373095049, -18}, + Number{1414213562373095049, -18}, + Number{2000000000000000001, -18}}, + {Number{-1414213562373095048, -18}, + Number{1414213562373095048, -18}, + Number{-1999999999999999997, -18}}, + {Number{-1414213562373095048, -18}, + Number{-1414213562373095049, -18}, + Number{2, 0}}, + {Number{3214285714285714278, -18}, + Number{3111111111111111119, -18}, + Number{1000000000000000001, -17}}, + // Maximum mantissa range - rounds up to minMantissa*10 + // 1e19*1e19=1e38 + {Number{false, maxMantissa, 0, Number::normalized{}}, + Number{false, maxMantissa, 0, Number::normalized{}}, + Number{1, 38}}, + // Maximum int64 range + // 85'070'591'730'234'615'847'396'907'784'232'501'249 + {Number{Number::maxRep, 0}, + Number{Number::maxRep, 0}, + Number{85'070'591'730'234'615'85, 19}}, + }); + tests(cSmall, cLarge); } - bool caught = false; - try + testcase << "test_mul " << to_string(Number::getMantissaScale()) + << " overflow"; { - Number{9'999'999'999'999'999, 32768} * - Number{5'000'000'000'000'000, 32767}; + bool caught = false; + try + { + Number{false, maxMantissa, 32768, Number::normalized{}} * + Number{ + false, + Number::minMantissa() * 5, + 32767, + Number::normalized{}}; + } + catch (std::overflow_error const&) + { + caught = true; + } + BEAST_EXPECT(caught); } - catch (std::overflow_error const&) - { - caught = true; - } - BEAST_EXPECT(caught); } void test_div() { - testcase("test_div"); + auto const scale = Number::getMantissaScale(); + testcase << "test_div " << to_string(scale); + using Case = std::tuple; + auto test = [this](auto const& c) { + for (auto const& [x, y, z] : c) + { + auto const result = x / y; + std::stringstream ss; + ss << x << " / " << y << " = " << result << ". Expected: " << z; + BEAST_EXPECTS(result == z, ss.str()); + } + }; + auto const maxMantissa = Number::maxMantissa(); + auto tests = [&](auto const& cSmall, auto const& cLarge) { + if (scale == MantissaRange::small) + test(cSmall); + else + test(cLarge); + }; saveNumberRoundMode save{Number::setround(Number::to_nearest)}; { - Case c[]{ - {Number{1}, Number{2}, Number{5, -1}}, - {Number{1}, Number{10}, Number{1, -1}}, - {Number{1}, Number{-10}, Number{-1, -1}}, - {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, - {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}}, - {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x / y == z); + auto const cSmall = std::to_array( + {{Number{1}, Number{2}, Number{5, -1}}, + {Number{1}, Number{10}, Number{1, -1}}, + {Number{1}, Number{-10}, Number{-1, -1}}, + {Number{0}, Number{100}, Number{0}}, + {Number{1414213562373095, -10}, + Number{1414213562373095, -10}, + Number{1}}, + {Number{9'999'999'999'999'999}, + Number{1'000'000'000'000'000}, + Number{9'999'999'999'999'999, -15}}, + {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}}, + {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}}, + {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items + // from C with larger mantissa + {{Number{1}, Number{2}, Number{5, -1}}, + {Number{1}, Number{10}, Number{1, -1}}, + {Number{1}, Number{-10}, Number{-1, -1}}, + {Number{0}, Number{100}, Number{0}}, + {Number{1414213562373095, -10}, + Number{1414213562373095, -10}, + Number{1}}, + {Number{9'999'999'999'999'999}, + Number{1'000'000'000'000'000}, + Number{9'999'999'999'999'999, -15}}, + {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}}, + {Number{-2}, + Number{3}, + Number{-6'666'666'666'666'666'667, -19}}, + {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}}, + // Items from cSmall expanded for the larger mantissa, except + // duplicates. + {Number{1414213562373095049, -13}, + Number{1414213562373095049, -13}, + Number{1}}, + {Number{false, maxMantissa, 0, Number::normalized{}}, + Number{1'000'000'000'000'000'000}, + Number{false, maxMantissa, -18, Number::normalized{}}}}); + tests(cSmall, cLarge); } + testcase << "test_div " << to_string(Number::getMantissaScale()) + << " towards_zero"; Number::setround(Number::towards_zero); { - Case c[]{ - {Number{1}, Number{2}, Number{5, -1}}, - {Number{1}, Number{10}, Number{1, -1}}, - {Number{1}, Number{-10}, Number{-1, -1}}, - {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, - {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}}, - {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x / y == z); + auto const cSmall = std::to_array( + {{Number{1}, Number{2}, Number{5, -1}}, + {Number{1}, Number{10}, Number{1, -1}}, + {Number{1}, Number{-10}, Number{-1, -1}}, + {Number{0}, Number{100}, Number{0}}, + {Number{1414213562373095, -10}, + Number{1414213562373095, -10}, + Number{1}}, + {Number{9'999'999'999'999'999}, + Number{1'000'000'000'000'000}, + Number{9'999'999'999'999'999, -15}}, + {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}}, + {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}}, + {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items + // from C with larger mantissa + {{Number{1}, Number{2}, Number{5, -1}}, + {Number{1}, Number{10}, Number{1, -1}}, + {Number{1}, Number{-10}, Number{-1, -1}}, + {Number{0}, Number{100}, Number{0}}, + {Number{1414213562373095, -10}, + Number{1414213562373095, -10}, + Number{1}}, + {Number{9'999'999'999'999'999}, + Number{1'000'000'000'000'000}, + Number{9'999'999'999'999'999, -15}}, + {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}}, + {Number{-2}, + Number{3}, + Number{-6'666'666'666'666'666'666, -19}}, + {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}}, + // Items from cSmall expanded for the larger mantissa, except + // duplicates. + {Number{1414213562373095049, -13}, + Number{1414213562373095049, -13}, + Number{1}}, + {Number{false, maxMantissa, 0, Number::normalized{}}, + Number{1'000'000'000'000'000'000}, + Number{false, maxMantissa, -18, Number::normalized{}}}}); + tests(cSmall, cLarge); } + testcase << "test_div " << to_string(Number::getMantissaScale()) + << " downward"; Number::setround(Number::downward); { - Case c[]{ - {Number{1}, Number{2}, Number{5, -1}}, - {Number{1}, Number{10}, Number{1, -1}}, - {Number{1}, Number{-10}, Number{-1, -1}}, - {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, - {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}}, - {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x / y == z); + auto const cSmall = std::to_array( + {{Number{1}, Number{2}, Number{5, -1}}, + {Number{1}, Number{10}, Number{1, -1}}, + {Number{1}, Number{-10}, Number{-1, -1}}, + {Number{0}, Number{100}, Number{0}}, + {Number{1414213562373095, -10}, + Number{1414213562373095, -10}, + Number{1}}, + {Number{9'999'999'999'999'999}, + Number{1'000'000'000'000'000}, + Number{9'999'999'999'999'999, -15}}, + {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}}, + {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}}, + {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items + // from C with larger mantissa + {{Number{1}, Number{2}, Number{5, -1}}, + {Number{1}, Number{10}, Number{1, -1}}, + {Number{1}, Number{-10}, Number{-1, -1}}, + {Number{0}, Number{100}, Number{0}}, + {Number{1414213562373095, -10}, + Number{1414213562373095, -10}, + Number{1}}, + {Number{9'999'999'999'999'999}, + Number{1'000'000'000'000'000}, + Number{9'999'999'999'999'999, -15}}, + {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}}, + {Number{-2}, + Number{3}, + Number{-6'666'666'666'666'666'667, -19}}, + {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}}, + // Items from cSmall expanded for the larger mantissa, except + // duplicates. + {Number{1414213562373095049, -13}, + Number{1414213562373095049, -13}, + Number{1}}, + {Number{false, maxMantissa, 0, Number::normalized{}}, + Number{1'000'000'000'000'000'000}, + Number{false, maxMantissa, -18, Number::normalized{}}}}); + tests(cSmall, cLarge); } + testcase << "test_div " << to_string(Number::getMantissaScale()) + << " upward"; Number::setround(Number::upward); { - Case c[]{ - {Number{1}, Number{2}, Number{5, -1}}, - {Number{1}, Number{10}, Number{1, -1}}, - {Number{1}, Number{-10}, Number{-1, -1}}, - {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, - {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}}, - {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT(x / y == z); + auto const cSmall = std::to_array( + {{Number{1}, Number{2}, Number{5, -1}}, + {Number{1}, Number{10}, Number{1, -1}}, + {Number{1}, Number{-10}, Number{-1, -1}}, + {Number{0}, Number{100}, Number{0}}, + {Number{1414213562373095, -10}, + Number{1414213562373095, -10}, + Number{1}}, + {Number{9'999'999'999'999'999}, + Number{1'000'000'000'000'000}, + Number{9'999'999'999'999'999, -15}}, + {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}}, + {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}}, + {Number{1}, Number{7}, Number{1'428'571'428'571'429, -16}}}); + auto const cLarge = std::to_array( + // Note that items with extremely large mantissas need to be + // calculated, because otherwise they overflow uint64. Items + // from C with larger mantissa + {{Number{1}, Number{2}, Number{5, -1}}, + {Number{1}, Number{10}, Number{1, -1}}, + {Number{1}, Number{-10}, Number{-1, -1}}, + {Number{0}, Number{100}, Number{0}}, + {Number{1414213562373095, -10}, + Number{1414213562373095, -10}, + Number{1}}, + {Number{9'999'999'999'999'999}, + Number{1'000'000'000'000'000}, + Number{9'999'999'999'999'999, -15}}, + {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}}, + {Number{-2}, + Number{3}, + Number{-6'666'666'666'666'666'666, -19}}, + {Number{1}, Number{7}, Number{1'428'571'428'571'428'572, -19}}, + // Items from cSmall expanded for the larger mantissa, except + // duplicates. + {Number{1414213562373095049, -13}, + Number{1414213562373095049, -13}, + Number{1}}, + {Number{false, maxMantissa, 0, Number::normalized{}}, + Number{1'000'000'000'000'000'000}, + Number{false, maxMantissa, -18, Number::normalized{}}}}); + tests(cSmall, cLarge); } + testcase << "test_div " << to_string(Number::getMantissaScale()) + << " overflow"; bool caught = false; try { @@ -325,20 +949,59 @@ public: void test_root() { - testcase("test_root"); + auto const scale = Number::getMantissaScale(); + testcase << "test_root " << to_string(scale); + using Case = std::tuple; - Case c[]{ - {Number{2}, 2, Number{1414213562373095, -15}}, - {Number{2'000'000}, 2, Number{1414213562373095, -12}}, - {Number{2, -30}, 2, Number{1414213562373095, -30}}, - {Number{-27}, 3, Number{-3}}, - {Number{1}, 5, Number{1}}, - {Number{-1}, 0, Number{1}}, - {Number{5, -1}, 0, Number{0}}, - {Number{0}, 5, Number{0}}, - {Number{5625, -4}, 2, Number{75, -2}}}; - for (auto const& [x, y, z] : c) - BEAST_EXPECT((root(x, y) == z)); + auto test = [this](auto const& c) { + for (auto const& [x, y, z] : c) + { + auto const result = root(x, y); + std::stringstream ss; + ss << "root(" << x << ", " << y << ") = " << result + << ". Expected: " << z; + BEAST_EXPECTS(result == z, ss.str()); + } + }; + /* + auto tests = [&](auto const& cSmall, auto const& cLarge) { + test(cSmall); + if (scale != MantissaRange::small) + test(cLarge); + }; + */ + + auto const cSmall = std::to_array( + {{Number{2}, 2, Number{1414213562373095049, -18}}, + {Number{2'000'000}, 2, Number{1414213562373095049, -15}}, + {Number{2, -30}, 2, Number{1414213562373095049, -33}}, + {Number{-27}, 3, Number{-3}}, + {Number{1}, 5, Number{1}}, + {Number{-1}, 0, Number{1}}, + {Number{5, -1}, 0, Number{0}}, + {Number{0}, 5, Number{0}}, + {Number{5625, -4}, 2, Number{75, -2}}}); + auto const cLarge = std::to_array({ + {Number{false, Number::maxMantissa() - 9, -1, Number::normalized{}}, + 2, + Number{false, 999'999'999'999'999'999, -9, Number::normalized{}}}, + {Number{false, Number::maxMantissa() - 9, 0, Number::normalized{}}, + 2, + Number{ + false, 3'162'277'660'168'379'330, -9, Number::normalized{}}}, + {Number{Number::maxRep}, + 2, + Number{false, 3'037'000'499'976049692, -9, Number::normalized{}}}, + {Number{Number::maxRep}, + 4, + Number{false, 55'108'98747006743627, -14, Number::normalized{}}}, + }); + test(cSmall); + if (Number::getMantissaScale() != MantissaRange::small) + { + NumberRoundModeGuard mg(Number::towards_zero); + test(cLarge); + } bool caught = false; try { @@ -361,10 +1024,52 @@ public: BEAST_EXPECT(caught); } + void + test_root2() + { + auto const scale = Number::getMantissaScale(); + testcase << "test_root2 " << to_string(scale); + + auto test = [this](auto const& c) { + for (auto const& x : c) + { + auto const expected = root(x, 2); + auto const result = root2(x); + std::stringstream ss; + ss << "root2(" << x << ") = " << result + << ". Expected: " << expected; + BEAST_EXPECTS(result == expected, ss.str()); + } + }; + + auto const cSmall = std::to_array({ + Number{2}, + Number{2'000'000}, + Number{2, -30}, + Number{27}, + Number{1}, + Number{5, -1}, + Number{0}, + Number{5625, -4}, + Number{Number::maxRep}, + }); + test(cSmall); + bool caught = false; + try + { + (void)root2(Number{-2}); + } + catch (std::overflow_error const&) + { + caught = true; + } + BEAST_EXPECT(caught); + } + void test_power1() { - testcase("test_power1"); + testcase << "test_power1 " << to_string(Number::getMantissaScale()); using Case = std::tuple; Case c[]{ {Number{64}, 0, Number{1}}, @@ -372,7 +1077,13 @@ public: {Number{64}, 2, Number{4096}}, {Number{-64}, 2, Number{4096}}, {Number{64}, 3, Number{262144}}, - {Number{-64}, 3, Number{-262144}}}; + {Number{-64}, 3, Number{-262144}}, + {Number{64}, + 11, + Number{false, 7378697629483820646ULL, 1, Number::normalized{}}}, + {Number{-64}, + 11, + Number{true, 7378697629483820646ULL, 1, Number::normalized{}}}}; for (auto const& [x, y, z] : c) BEAST_EXPECT((power(x, y) == z)); } @@ -380,7 +1091,7 @@ public: void test_power2() { - testcase("test_power2"); + testcase << "test_power2 " << to_string(Number::getMantissaScale()); using Case = std::tuple; Case c[]{ {Number{1}, 3, 7, Number{1}}, @@ -426,7 +1137,7 @@ public: void testConversions() { - testcase("testConversions"); + testcase << "testConversions " << to_string(Number::getMantissaScale()); IOUAmount x{5, 6}; Number y = x; @@ -452,7 +1163,7 @@ public: void test_to_integer() { - testcase("test_to_integer"); + testcase << "test_to_integer " << to_string(Number::getMantissaScale()); using Case = std::tuple; saveNumberRoundMode save{Number::setround(Number::to_nearest)}; { @@ -620,7 +1331,7 @@ public: void test_squelch() { - testcase("test_squelch"); + testcase << "test_squelch " << to_string(Number::getMantissaScale()); Number limit{1, -6}; BEAST_EXPECT((squelch(Number{2, -6}, limit) == Number{2, -6})); BEAST_EXPECT((squelch(Number{1, -6}, limit) == Number{1, -6})); @@ -633,22 +1344,129 @@ public: void testToString() { - testcase("testToString"); - BEAST_EXPECT(to_string(Number(-2, 0)) == "-2"); - BEAST_EXPECT(to_string(Number(0, 0)) == "0"); - BEAST_EXPECT(to_string(Number(2, 0)) == "2"); - BEAST_EXPECT(to_string(Number(25, -3)) == "0.025"); - BEAST_EXPECT(to_string(Number(-25, -3)) == "-0.025"); - BEAST_EXPECT(to_string(Number(25, 1)) == "250"); - BEAST_EXPECT(to_string(Number(-25, 1)) == "-250"); - BEAST_EXPECT(to_string(Number(2, 20)) == "2000000000000000e5"); - BEAST_EXPECT(to_string(Number(-2, -20)) == "-2000000000000000e-35"); + auto const scale = Number::getMantissaScale(); + testcase << "testToString " << to_string(scale); + + auto test = [this](Number const& n, std::string const& expected) { + auto const result = to_string(n); + std::stringstream ss; + ss << "to_string(" << result << "). Expected: " << expected; + BEAST_EXPECTS(result == expected, ss.str()); + }; + + test(Number(-2, 0), "-2"); + test(Number(0, 0), "0"); + test(Number(2, 0), "2"); + test(Number(25, -3), "0.025"); + test(Number(-25, -3), "-0.025"); + test(Number(25, 1), "250"); + test(Number(-25, 1), "-250"); + test(Number(2, 20), "2e20"); + test(Number(-2, -20), "-2e-20"); + // Test the edges + // ((exponent < -(25)) || (exponent > -(5))))) + // or ((exponent < -(28)) || (exponent > -(8))))) + test(Number(2, -10), "0.0000000002"); + test(Number(2, -11), "2e-11"); + + test(Number(-2, 10), "-20000000000"); + test(Number(-2, 11), "-2e11"); + + switch (scale) + { + case MantissaRange::small: + + test(Number::min(), "1e-32753"); + test(Number::max(), "9999999999999999e32768"); + test(Number::lowest(), "-9999999999999999e32768"); + { + NumberRoundModeGuard mg(Number::towards_zero); + + auto const maxMantissa = Number::maxMantissa(); + BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999); + test( + Number{ + false, + maxMantissa * 1000 + 999, + -3, + Number::normalized()}, + "9999999999999999"); + test( + Number{ + true, + maxMantissa * 1000 + 999, + -3, + Number::normalized()}, + "-9999999999999999"); + + test( + Number{std::numeric_limits::max(), -3}, + "9223372036854775"); + test( + -(Number{std::numeric_limits::max(), -3}), + "-9223372036854775"); + + test( + Number{std::numeric_limits::min(), 0}, + "-9223372036854775e3"); + test( + -(Number{std::numeric_limits::min(), 0}), + "9223372036854775e3"); + } + break; + case MantissaRange::large: + // Test the edges + // ((exponent < -(28)) || (exponent > -(8))))) + test(Number::min(), "1e-32750"); + test(Number::max(), "9223372036854775807e32768"); + test(Number::lowest(), "-9223372036854775807e32768"); + { + NumberRoundModeGuard mg(Number::towards_zero); + + auto const maxMantissa = Number::maxMantissa(); + BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999'999ULL); + test( + Number{false, maxMantissa, 0, Number::normalized{}}, + "9999999999999999990"); + test( + Number{true, maxMantissa, 0, Number::normalized{}}, + "-9999999999999999990"); + + test( + Number{std::numeric_limits::max(), 0}, + "9223372036854775807"); + test( + -(Number{std::numeric_limits::max(), 0}), + "-9223372036854775807"); + + // Because the absolute value of min is larger than max, it + // will be scaled down to fit under max. Since we're + // rounding towards zero, the 8 at the end is dropped. + test( + Number{std::numeric_limits::min(), 0}, + "-9223372036854775800"); + test( + -(Number{std::numeric_limits::min(), 0}), + "9223372036854775800"); + } + + test( + Number{std::numeric_limits::max(), 0} + 1, + "9223372036854775810"); + test( + -(Number{std::numeric_limits::max(), 0} + 1), + "-9223372036854775810"); + break; + default: + BEAST_EXPECT(false); + } } void test_relationals() { - testcase("test_relationals"); + testcase << "test_relationals " + << to_string(Number::getMantissaScale()); BEAST_EXPECT(!(Number{100} < Number{10})); BEAST_EXPECT(Number{100} > Number{10}); BEAST_EXPECT(Number{100} >= Number{10}); @@ -658,7 +1476,7 @@ public: void test_stream() { - testcase("test_stream"); + testcase << "test_stream " << to_string(Number::getMantissaScale()); Number x{100}; std::ostringstream os; os << x; @@ -668,7 +1486,7 @@ public: void test_inc_dec() { - testcase("test_inc_dec"); + testcase << "test_inc_dec " << to_string(Number::getMantissaScale()); Number x{100}; Number y = +x; BEAST_EXPECT(x == y); @@ -685,19 +1503,19 @@ public: Issue const issue; Number const n{7'518'783'80596, -5}; saveNumberRoundMode const save{Number::setround(Number::to_nearest)}; - auto res2 = STAmount{issue, n.mantissa(), n.exponent()}; + auto res2 = STAmount{issue, n}; BEAST_EXPECT(res2 == STAmount{7518784}); Number::setround(Number::towards_zero); - res2 = STAmount{issue, n.mantissa(), n.exponent()}; + res2 = STAmount{issue, n}; BEAST_EXPECT(res2 == STAmount{7518783}); Number::setround(Number::downward); - res2 = STAmount{issue, n.mantissa(), n.exponent()}; + res2 = STAmount{issue, n}; BEAST_EXPECT(res2 == STAmount{7518783}); Number::setround(Number::upward); - res2 = STAmount{issue, n.mantissa(), n.exponent()}; + res2 = STAmount{issue, n}; BEAST_EXPECT(res2 == STAmount{7518784}); } @@ -834,28 +1652,94 @@ public: } } + void + testInt64() + { + auto const scale = Number::getMantissaScale(); + testcase << "std::int64_t " << to_string(scale); + + // Control case + BEAST_EXPECT(Number::maxMantissa() > 10); + Number ten{10}; + BEAST_EXPECT(ten.exponent() <= 0); + + if (scale == MantissaRange::small) + { + BEAST_EXPECT( + std::numeric_limits::max() > INITIAL_XRP.drops()); + BEAST_EXPECT(Number::maxMantissa() < INITIAL_XRP.drops()); + Number const initalXrp{INITIAL_XRP}; + BEAST_EXPECT(initalXrp.exponent() > 0); + + Number const maxInt64{Number::maxRep}; + BEAST_EXPECT(maxInt64.exponent() > 0); + // 85'070'591'730'234'615'865'843'651'857'942'052'864 - 38 digits + BEAST_EXPECT( + (power(maxInt64, 2) == Number{85'070'591'730'234'62, 22})); + + Number const max = + Number{false, Number::maxMantissa(), 0, Number::normalized{}}; + BEAST_EXPECT(max.exponent() <= 0); + // 99'999'999'999'999'980'000'000'000'000'001 - 32 digits + BEAST_EXPECT((power(max, 2) == Number{99'999'999'999'999'98, 16})); + } + else + { + BEAST_EXPECT( + std::numeric_limits::max() > INITIAL_XRP.drops()); + BEAST_EXPECT(Number::maxMantissa() > INITIAL_XRP.drops()); + Number const initalXrp{INITIAL_XRP}; + BEAST_EXPECT(initalXrp.exponent() <= 0); + + Number const maxInt64{Number::maxRep}; + BEAST_EXPECT(maxInt64.exponent() <= 0); + // 85'070'591'730'234'615'847'396'907'784'232'501'249 - 38 digits + BEAST_EXPECT( + (power(maxInt64, 2) == Number{85'070'591'730'234'615'85, 19})); + + NumberRoundModeGuard mg(Number::towards_zero); + + auto const maxMantissa = Number::maxMantissa(); + Number const max = + Number{false, maxMantissa, 0, Number::normalized{}}; + BEAST_EXPECT(max.mantissa() == maxMantissa / 10); + BEAST_EXPECT(max.exponent() == 1); + // 99'999'999'999'999'999'800'000'000'000'000'000'100 - also 38 + // digits + BEAST_EXPECT(( + power(max, 2) == + Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}})); + } + } + void run() override { - testZero(); - test_limits(); - test_add(); - test_sub(); - test_mul(); - test_div(); - test_root(); - test_power1(); - test_power2(); - testConversions(); - test_to_integer(); - test_squelch(); - testToString(); - test_relationals(); - test_stream(); - test_inc_dec(); - test_toSTAmount(); - test_truncate(); - testRounding(); + for (auto const scale : {MantissaRange::small, MantissaRange::large}) + { + NumberMantissaScaleGuard sg(scale); + testZero(); + test_limits(); + testToString(); + test_add(); + test_sub(); + test_mul(); + test_div(); + test_root(); + test_root2(); + test_power1(); + test_power2(); + testConversions(); + test_to_integer(); + test_squelch(); + test_relationals(); + test_stream(); + test_inc_dec(); + test_toSTAmount(); + test_truncate(); + testRounding(); + testInt64(); + } } }; diff --git a/src/test/jtx/AMMTest.h b/src/test/jtx/AMMTest.h index 83366d61e2..208e3c4e5f 100644 --- a/src/test/jtx/AMMTest.h +++ b/src/test/jtx/AMMTest.h @@ -21,7 +21,12 @@ struct TestAMMArg std::optional> pool = std::nullopt; std::uint16_t tfee = 0; std::optional ter = std::nullopt; - std::vector features = {testable_amendments()}; + std::vector features = { + // For now, just disable SAV entirely, which locks in the small Number + // mantissas + jtx::testable_amendments() - featureSingleAssetVault - + featureLendingProtocol}; + bool noLog = false; }; @@ -66,6 +71,15 @@ protected: public: AMMTestBase(); + static FeatureBitset + testable_amendments() + { + // For now, just disable SAV entirely, which locks in the small Number + // mantissas + return jtx::testable_amendments() - featureSingleAssetVault - + featureLendingProtocol; + } + protected: /** testAMM() funds 30,000XRP and 30,000IOU * for each non-XRP asset to Alice and Carol diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index a310fc5b44..147307f7b7 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -261,6 +261,12 @@ struct XRP_t return xrpIssue(); } + bool + integral() const + { + return true; + } + /** Returns an amount of XRP as PrettyAmount, which is trivially convertible to STAmount @@ -400,6 +406,11 @@ public: { return issue(); } + bool + integral() const + { + return issue().integral(); + } /** Implicit conversion to Issue or Asset. @@ -490,6 +501,11 @@ public: { return mptIssue(); } + bool + integral() const + { + return true; + } /** Implicit conversion to MPTIssue or asset. diff --git a/src/test/jtx/impl/AMMTest.cpp b/src/test/jtx/impl/AMMTest.cpp index de7ce5504b..139b9113b9 100644 --- a/src/test/jtx/impl/AMMTest.cpp +++ b/src/test/jtx/impl/AMMTest.cpp @@ -105,9 +105,14 @@ AMMTestBase::testAMM( for (auto const& features : arg.features) { + // Use small Number mantissas for the life of this test. + NumberMantissaScaleGuard const sg{xrpl::MantissaRange::small}; + + // For now, just disable SAV entirely, which locks in the small Number + // mantissas Env env{ *this, - features, + features - featureSingleAssetVault - featureLendingProtocol, arg.noLog ? std::make_unique(&logs) : nullptr}; auto const [asset1, asset2] = diff --git a/src/test/protocol/STNumber_test.cpp b/src/test/protocol/STNumber_test.cpp index 1275c756cf..4e7a8388ee 100644 --- a/src/test/protocol/STNumber_test.cpp +++ b/src/test/protocol/STNumber_test.cpp @@ -29,10 +29,8 @@ struct STNumber_test : public beast::unit_test::suite } void - run() override + doRun() { - static_assert(!std::is_convertible_v); - { STNumber const stnum{sfNumber}; BEAST_EXPECT(stnum.getSType() == STI_NUMBER); @@ -127,6 +125,41 @@ struct STNumber_test : public beast::unit_test::suite BEAST_EXPECT( numberFromJson(sfNumber, "-0.000e6") == STNumber(sfNumber, 0)); + { + NumberRoundModeGuard mg(Number::towards_zero); + // maxint64 9,223,372,036,854,775,807 + auto const maxInt = + std::to_string(std::numeric_limits::max()); + // minint64 -9,223,372,036,854,775,808 + auto const minInt = + std::to_string(std::numeric_limits::min()); + if (Number::getMantissaScale() == MantissaRange::small) + { + BEAST_EXPECT( + numberFromJson(sfNumber, maxInt) == + STNumber(sfNumber, Number{9'223'372'036'854'775, 3})); + BEAST_EXPECT( + numberFromJson(sfNumber, minInt) == + STNumber(sfNumber, Number{-9'223'372'036'854'775, 3})); + } + else + { + BEAST_EXPECT( + numberFromJson(sfNumber, maxInt) == + STNumber( + sfNumber, Number{9'223'372'036'854'775'807, 0})); + BEAST_EXPECT( + numberFromJson(sfNumber, minInt) == + STNumber( + sfNumber, + Number{ + true, + 9'223'372'036'854'775'808ULL, + 0, + Number::normalized{}})); + } + } + constexpr auto imin = std::numeric_limits::min(); BEAST_EXPECT( numberFromJson(sfNumber, imin) == @@ -279,15 +312,21 @@ struct STNumber_test : public beast::unit_test::suite } } } + + void + run() override + { + static_assert(!std::is_convertible_v); + + for (auto const scale : {MantissaRange::small, MantissaRange::large}) + { + NumberMantissaScaleGuard sg(scale); + testcase << to_string(Number::getMantissaScale()); + doRun(); + } + } }; BEAST_DEFINE_TESTSUITE(STNumber, protocol, xrpl); -void -testCompile(std::ostream& out) -{ - STNumber number{sfNumber, 42}; - out << number; -} - } // namespace xrpl diff --git a/src/test/rpc/GetAggregatePrice_test.cpp b/src/test/rpc/GetAggregatePrice_test.cpp index 52f82ffc6c..0ffefc6cb6 100644 --- a/src/test/rpc/GetAggregatePrice_test.cpp +++ b/src/test/rpc/GetAggregatePrice_test.cpp @@ -191,18 +191,38 @@ public: // Aggregate data set includes all price oracle instances, no trimming // or time threshold { - Env env(*this); - OraclesData oracles; - prep(env, oracles); - // entire and trimmed stats - auto ret = Oracle::aggregatePrice(env, "XRP", "USD", oracles); - BEAST_EXPECT(ret[jss::entire_set][jss::mean] == "74.45"); - BEAST_EXPECT(ret[jss::entire_set][jss::size].asUInt() == 10); - BEAST_EXPECT( - ret[jss::entire_set][jss::standard_deviation] == - "0.3027650354097492"); - BEAST_EXPECT(ret[jss::median] == "74.45"); - BEAST_EXPECT(ret[jss::time] == 946694900); + auto const all = testable_amendments(); + for (auto const& feats : + {all - featureSingleAssetVault - featureLendingProtocol, all}) + { + for (auto const mantissaSize : + {MantissaRange::small, MantissaRange::large}) + { + // Regardless of the features enabled, RPC is controlled by + // the global mantissa size. And since it's a thread-local, + // overriding it locally won't make a difference either. + // This will mean all RPC will use the default of "large". + NumberMantissaScaleGuard mg(mantissaSize); + + Env env(*this, feats); + OraclesData oracles; + prep(env, oracles); + // entire and trimmed stats + auto ret = + Oracle::aggregatePrice(env, "XRP", "USD", oracles); + BEAST_EXPECT(ret[jss::entire_set][jss::mean] == "74.45"); + BEAST_EXPECT( + ret[jss::entire_set][jss::size].asUInt() == 10); + // Short: 0.3027650354097492 + BEAST_EXPECTS( + ret[jss::entire_set][jss::standard_deviation] == + "0.3027650354097491666", + ret[jss::entire_set][jss::standard_deviation] + .asString()); + BEAST_EXPECT(ret[jss::median] == "74.45"); + BEAST_EXPECT(ret[jss::time] == 946694900); + } + } } // Aggregate data set includes all price oracle instances @@ -215,15 +235,19 @@ public: Oracle::aggregatePrice(env, "XRP", "USD", oracles, 20, 100); BEAST_EXPECT(ret[jss::entire_set][jss::mean] == "74.45"); BEAST_EXPECT(ret[jss::entire_set][jss::size].asUInt() == 10); - BEAST_EXPECT( + // Short: "0.3027650354097492", + BEAST_EXPECTS( ret[jss::entire_set][jss::standard_deviation] == - "0.3027650354097492"); + "0.3027650354097491666", + ret[jss::entire_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::median] == "74.45"); BEAST_EXPECT(ret[jss::trimmed_set][jss::mean] == "74.45"); BEAST_EXPECT(ret[jss::trimmed_set][jss::size].asUInt() == 6); - BEAST_EXPECT( + // Short: "0.187082869338697", + BEAST_EXPECTS( ret[jss::trimmed_set][jss::standard_deviation] == - "0.187082869338697"); + "0.1870828693386970693", + ret[jss::trimmed_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::time] == 946694900); } @@ -274,15 +298,19 @@ public: Oracle::aggregatePrice(env, "XRP", "USD", oracles, 20, "200"); BEAST_EXPECT(ret[jss::entire_set][jss::mean] == "74.6"); BEAST_EXPECT(ret[jss::entire_set][jss::size].asUInt() == 7); - BEAST_EXPECT( + // Short: 0.2160246899469287 + BEAST_EXPECTS( ret[jss::entire_set][jss::standard_deviation] == - "0.2160246899469287"); + "0.2160246899469286744", + ret[jss::entire_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::median] == "74.6"); BEAST_EXPECT(ret[jss::trimmed_set][jss::mean] == "74.6"); BEAST_EXPECT(ret[jss::trimmed_set][jss::size].asUInt() == 5); - BEAST_EXPECT( + // Short: 0.158113883008419 + BEAST_EXPECTS( ret[jss::trimmed_set][jss::standard_deviation] == - "0.158113883008419"); + "0.1581138830084189666", + ret[jss::trimmed_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::time] == 946694900); } diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp index 1cc6b1f5ae..c61145dda1 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverClawback.cpp @@ -2,6 +2,8 @@ // #include +#include + namespace xrpl { bool @@ -338,6 +340,8 @@ LoanBrokerCoverClawback::doApply() sleBroker->at(sfCoverAvailable) -= clawAmount; view().update(sleBroker); + associateAsset(*sleBroker, vaultAsset); + // Transfer assets from pseudo-account to depositor. return accountSend( view(), brokerPseudoID, account, clawAmount, j_, WaiveTransferFee::Yes); diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp index b68cf46a00..ed47d40631 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverDeposit.cpp @@ -2,6 +2,8 @@ // #include +#include + namespace xrpl { bool @@ -100,6 +102,12 @@ LoanBrokerCoverDeposit::doApply() if (!broker) return tecINTERNAL; // LCOV_EXCL_LINE + auto const vault = view().read(keylet::vault(broker->at(sfVaultID))); + if (!vault) + return tecINTERNAL; // LCOV_EXCL_LINE + + auto const vaultAsset = vault->at(sfAsset); + auto const brokerPseudoID = broker->at(sfAccount); // Transfer assets from depositor to pseudo-account. @@ -116,6 +124,8 @@ LoanBrokerCoverDeposit::doApply() broker->at(sfCoverAvailable) += amount; view().update(broker); + associateAsset(*broker, vaultAsset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp index 830f9e26c1..5d4d2053ed 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerCoverWithdraw.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace xrpl { @@ -156,12 +157,20 @@ LoanBrokerCoverWithdraw::doApply() if (!broker) return tecINTERNAL; // LCOV_EXCL_LINE + auto const vault = view().read(keylet::vault(broker->at(sfVaultID))); + if (!vault) + return tecINTERNAL; // LCOV_EXCL_LINE + + auto const vaultAsset = vault->at(sfAsset); + auto const brokerPseudoID = *broker->at(sfAccount); // Decrease the LoanBroker's CoverAvailable by Amount broker->at(sfCoverAvailable) -= amount; view().update(broker); + associateAsset(*broker, vaultAsset); + return doWithdraw( view(), tx, diff --git a/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp b/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp index 227bad10a9..f3f57f8659 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerDelete.cpp @@ -2,6 +2,8 @@ // #include +#include + namespace xrpl { bool @@ -185,6 +187,8 @@ LoanBrokerDelete::doApply() adjustOwnerCount(view(), owner, -2, j_); } + associateAsset(*broker, vaultAsset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/LoanBrokerSet.cpp b/src/xrpld/app/tx/detail/LoanBrokerSet.cpp index 0cbae4d779..b7e9e4c79f 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerSet.cpp +++ b/src/xrpld/app/tx/detail/LoanBrokerSet.cpp @@ -2,6 +2,8 @@ // #include +#include + namespace xrpl { bool @@ -62,6 +64,15 @@ LoanBrokerSet::preflight(PreflightContext const& ctx) return tesSUCCESS; } +std::vector> const& +LoanBrokerSet::getValueFields() +{ + static std::vector> const valueFields{ + ~sfDebtMaximum}; + + return valueFields; +} + TER LoanBrokerSet::preclaim(PreclaimContext const& ctx) { @@ -70,8 +81,24 @@ LoanBrokerSet::preclaim(PreclaimContext const& ctx) auto const account = tx[sfAccount]; auto const vaultID = tx[sfVaultID]; + auto const sleVault = ctx.view.read(keylet::vault(vaultID)); + if (!sleVault) + { + JLOG(ctx.j.warn()) << "Vault does not exist."; + return tecNO_ENTRY; + } + Asset const asset = sleVault->at(sfAsset); + + if (account != sleVault->at(sfOwner)) + { + JLOG(ctx.j.warn()) << "Account is not the owner of the Vault."; + return tecNO_PERMISSION; + } + if (auto const brokerID = tx[~sfLoanBrokerID]) { + // Updating an existing Broker + auto const sleBroker = ctx.view.read(keylet::loanbroker(*brokerID)); if (!sleBroker) { @@ -104,18 +131,7 @@ LoanBrokerSet::preclaim(PreclaimContext const& ctx) } else { - auto const sleVault = ctx.view.read(keylet::vault(vaultID)); - if (!sleVault) - { - JLOG(ctx.j.warn()) << "Vault does not exist."; - return tecNO_ENTRY; - } - if (account != sleVault->at(sfOwner)) - { - JLOG(ctx.j.warn()) << "Account is not the owner of the Vault."; - return tecNO_PERMISSION; - } - if (auto const ter = canAddHolding(ctx.view, sleVault->at(sfAsset))) + if (auto const ter = canAddHolding(ctx.view, asset)) return ter; if (auto const ter = checkFrozen( @@ -125,6 +141,21 @@ LoanBrokerSet::preclaim(PreclaimContext const& ctx) return ter; } } + + // Check that relevant values can be represented as the vault asset + // type. This is mostly only relevant for integral (non-IOU) types + for (auto const& field : getValueFields()) + { + if (auto const value = tx[field]; + value && STAmount{asset, *value} != *value) + { + JLOG(ctx.j.warn()) << field.f->getName() << " (" << *value + << ") can not be represented as a(n) " + << to_string(asset) << "."; + return tecPRECISION_LOSS; + } + } + return tesSUCCESS; } @@ -147,12 +178,20 @@ LoanBrokerSet::doApply() // LCOV_EXCL_STOP } + auto const vault = view.read(keylet::vault(broker->at(sfVaultID))); + if (!vault) + return tecINTERNAL; // LCOV_EXCL_LINE + + auto const vaultAsset = vault->at(sfAsset); + if (auto const data = tx[~sfData]) broker->at(sfData) = *data; if (auto const debtMax = tx[~sfDebtMaximum]) broker->at(sfDebtMaximum) = *debtMax; view.update(broker); + + associateAsset(*broker, vaultAsset); } else { @@ -168,6 +207,7 @@ LoanBrokerSet::doApply() // LCOV_EXCL_STOP } auto const vaultPseudoID = sleVault->at(sfAccount); + auto const vaultAsset = sleVault->at(sfAsset); auto const sequence = tx.getSeqValue(); auto owner = view.peek(keylet::account(account_)); @@ -224,6 +264,8 @@ LoanBrokerSet::doApply() broker->at(sfCoverRateLiquidation) = *coverLiq; view.insert(broker); + + associateAsset(*broker, vaultAsset); } return tesSUCCESS; diff --git a/src/xrpld/app/tx/detail/LoanBrokerSet.h b/src/xrpld/app/tx/detail/LoanBrokerSet.h index 625c0adeb2..57170b9cb9 100644 --- a/src/xrpld/app/tx/detail/LoanBrokerSet.h +++ b/src/xrpld/app/tx/detail/LoanBrokerSet.h @@ -20,6 +20,9 @@ public: static NotTEC preflight(PreflightContext const& ctx); + static std::vector> const& + getValueFields(); + static TER preclaim(PreclaimContext const& ctx); diff --git a/src/xrpld/app/tx/detail/LoanDelete.cpp b/src/xrpld/app/tx/detail/LoanDelete.cpp index 3643e6331b..ddb286db12 100644 --- a/src/xrpld/app/tx/detail/LoanDelete.cpp +++ b/src/xrpld/app/tx/detail/LoanDelete.cpp @@ -2,6 +2,8 @@ // #include +#include + namespace xrpl { bool @@ -78,9 +80,10 @@ LoanDelete::doApply() return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const brokerPseudoAccount = brokerSle->at(sfAccount); - auto const vaultSle = view.peek(keylet ::vault(brokerSle->at(sfVaultID))); + auto const vaultSle = view.peek(keylet::vault(brokerSle->at(sfVaultID))); if (!vaultSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE + auto const vaultAsset = vaultSle->at(sfAsset); // Remove LoanID from Directory of the LoanBroker pseudo-account. if (!view.dirRemove( @@ -125,6 +128,11 @@ LoanDelete::doApply() // Decrement the borrower's owner count adjustOwnerCount(view, borrowerSle, -1, j_); + // These associations shouldn't do anything, but do them just to be safe + associateAsset(*loanSle, vaultAsset); + associateAsset(*brokerSle, vaultAsset); + associateAsset(*vaultSle, vaultAsset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/LoanManage.cpp b/src/xrpld/app/tx/detail/LoanManage.cpp index bd0539ae4e..17dee8ffe8 100644 --- a/src/xrpld/app/tx/detail/LoanManage.cpp +++ b/src/xrpld/app/tx/detail/LoanManage.cpp @@ -2,6 +2,7 @@ // #include +#include #include namespace xrpl { @@ -412,7 +413,7 @@ LoanManage::doApply() if (!brokerSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE - auto const vaultSle = view.peek(keylet ::vault(brokerSle->at(sfVaultID))); + auto const vaultSle = view.peek(keylet::vault(brokerSle->at(sfVaultID))); if (!vaultSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const vaultAsset = vaultSle->at(sfAsset); @@ -426,6 +427,11 @@ LoanManage::doApply() if (tx.isFlag(tfLoanUnimpair)) return unimpairLoan(view, loanSle, vaultSle, vaultAsset, j_); // Noop, as described above. + + associateAsset(*loanSle, vaultAsset); + associateAsset(*brokerSle, vaultAsset); + associateAsset(*vaultSle, vaultAsset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/LoanPay.cpp b/src/xrpld/app/tx/detail/LoanPay.cpp index f3973d9488..13f62d4c0d 100644 --- a/src/xrpld/app/tx/detail/LoanPay.cpp +++ b/src/xrpld/app/tx/detail/LoanPay.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -485,6 +486,16 @@ LoanPay::doApply() coverAvailableProxy += totalPaidToBroker; } + associateAsset(*loanSle, asset); + associateAsset(*brokerSle, asset); + associateAsset(*vaultSle, asset); + + // Duplicate some checks after rounding + XRPL_ASSERT_PARTS( + *assetsAvailableProxy <= *assetsTotalProxy, + "xrpl::LoanPay::doApply", + "assets available must not be greater than assets outstanding"); + #if !NDEBUG auto const accountBalanceBefore = accountHolds( view, diff --git a/src/xrpld/app/tx/detail/LoanSet.cpp b/src/xrpld/app/tx/detail/LoanSet.cpp index 4c14cde421..0b83d3009f 100644 --- a/src/xrpld/app/tx/detail/LoanSet.cpp +++ b/src/xrpld/app/tx/detail/LoanSet.cpp @@ -2,6 +2,7 @@ // #include +#include #include namespace xrpl { @@ -301,17 +302,15 @@ LoanSet::preclaim(PreclaimContext const& ctx) // This check is almost duplicated in doApply, but that check is done after // the overall loan scale is known. This is mostly only relevant for // integral (non-IOU) types + for (auto const& field : getValueFields()) { - for (auto const& field : getValueFields()) + if (auto const value = tx[field]; + value && STAmount{asset, *value} != *value) { - if (auto const value = tx[field]; - value && STAmount{asset, *value} != *value) - { - JLOG(ctx.j.warn()) << field.f->getName() << " (" << *value - << ") can not be represented as a(n) " - << to_string(asset) << "."; - return tecPRECISION_LOSS; - } + JLOG(ctx.j.warn()) << field.f->getName() << " (" << *value + << ") can not be represented as a(n) " + << to_string(asset) << "."; + return tecPRECISION_LOSS; } } @@ -434,19 +433,16 @@ LoanSet::doApply() } // Check that relevant values won't lose precision. This is mostly only // relevant for IOU assets. + for (auto const& field : getValueFields()) { - for (auto const& field : getValueFields()) + if (auto const value = tx[field]; + value && !isRounded(vaultAsset, *value, properties.loanScale)) { - if (auto const value = tx[field]; - value && !isRounded(vaultAsset, *value, properties.loanScale)) - { - JLOG(j_.warn()) - << field.f->getName() << " (" << *value - << ") has too much precision. Total loan value is " - << properties.loanState.valueOutstanding - << " with a scale of " << properties.loanScale; - return tecPRECISION_LOSS; - } + JLOG(j_.warn()) << field.f->getName() << " (" << *value + << ") has too much precision. Total loan value is " + << properties.loanState.valueOutstanding + << " with a scale of " << properties.loanScale; + return tecPRECISION_LOSS; } } @@ -649,6 +645,10 @@ LoanSet::doApply() if (auto const ter = dirLink(view, borrower, loan, sfOwnerNode)) return ter; + associateAsset(*vaultSle, vaultAsset); + associateAsset(*brokerSle, vaultAsset); + associateAsset(*loan, vaultAsset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/Transactor.cpp b/src/xrpld/app/tx/detail/Transactor.cpp index a834f7c6c3..691443ed93 100644 --- a/src/xrpld/app/tx/detail/Transactor.cpp +++ b/src/xrpld/app/tx/detail/Transactor.cpp @@ -1136,6 +1136,10 @@ Transactor::operator()() { JLOG(j_.trace()) << "apply: " << ctx_.tx.getTransactionID(); + // These global updates really should have been for every Transaction + // step: preflight, preclaim, and doApply. And even calculateBaseFee. See + // with_txn_type(). + // // raii classes for the current ledger rules. // fixUniversalNumber predate the rulesGuard and should be replaced. NumberSO stNumberSO{view().rules().enabled(fixUniversalNumber)}; @@ -1152,7 +1156,7 @@ Transactor::operator()() { // LCOV_EXCL_START JLOG(j_.fatal()) << "Transaction serdes mismatch"; - JLOG(j_.info()) << to_string(ctx_.tx.getJson(JsonOptions::none)); + JLOG(j_.fatal()) << ctx_.tx.getJson(JsonOptions::none); JLOG(j_.fatal()) << s2.getJson(JsonOptions::none); UNREACHABLE( "xrpl::Transactor::operator() : transaction serdes mismatch"); diff --git a/src/xrpld/app/tx/detail/VaultClawback.cpp b/src/xrpld/app/tx/detail/VaultClawback.cpp index 2552e8c1ff..dbdf4440ec 100644 --- a/src/xrpld/app/tx/detail/VaultClawback.cpp +++ b/src/xrpld/app/tx/detail/VaultClawback.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -457,6 +458,8 @@ VaultClawback::doApply() } } + associateAsset(*vault, vaultAsset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/VaultCreate.cpp b/src/xrpld/app/tx/detail/VaultCreate.cpp index 893a1108fa..402d877a00 100644 --- a/src/xrpld/app/tx/detail/VaultCreate.cpp +++ b/src/xrpld/app/tx/detail/VaultCreate.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -230,6 +231,8 @@ VaultCreate::doApply() return err; } + associateAsset(*vault, asset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/VaultDelete.cpp b/src/xrpld/app/tx/detail/VaultDelete.cpp index 756e7b94e6..9b63c7766b 100644 --- a/src/xrpld/app/tx/detail/VaultDelete.cpp +++ b/src/xrpld/app/tx/detail/VaultDelete.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,7 @@ VaultDelete::doApply() // Destroy the asset holding. auto asset = vault->at(sfAsset); + if (auto ter = removeEmptyHolding(view(), vault->at(sfAccount), asset, j_); !isTesSuccess(ter)) return ter; @@ -205,6 +207,8 @@ VaultDelete::doApply() // Destroy the vault. view().erase(vault); + associateAsset(*vault, asset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/VaultDeposit.cpp b/src/xrpld/app/tx/detail/VaultDeposit.cpp index 51b38afc36..02ef4afad1 100644 --- a/src/xrpld/app/tx/detail/VaultDeposit.cpp +++ b/src/xrpld/app/tx/detail/VaultDeposit.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -134,6 +135,7 @@ VaultDeposit::doApply() auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID])); if (!vault) return tefINTERNAL; // LCOV_EXCL_LINE + auto const vaultAsset = vault->at(sfAsset); auto const amount = ctx_.tx[sfAmount]; // Make sure the depositor can hold shares. @@ -282,6 +284,8 @@ VaultDeposit::doApply() !isTesSuccess(ter)) return ter; + associateAsset(*vault, vaultAsset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/VaultSet.cpp b/src/xrpld/app/tx/detail/VaultSet.cpp index 648ac12c3d..13c8ad5db8 100644 --- a/src/xrpld/app/tx/detail/VaultSet.cpp +++ b/src/xrpld/app/tx/detail/VaultSet.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,8 @@ VaultSet::doApply() if (!vault) return tefINTERNAL; // LCOV_EXCL_LINE + auto const vaultAsset = vault->at(sfAsset); + auto const mptIssuanceID = (*vault)[sfShareMPTID]; auto const sleIssuance = view().peek(keylet::mptIssuance(mptIssuanceID)); if (!sleIssuance) @@ -172,6 +175,8 @@ VaultSet::doApply() // to verify the operation. view().update(vault); + associateAsset(*vault, vaultAsset); + return tesSUCCESS; } diff --git a/src/xrpld/app/tx/detail/VaultWithdraw.cpp b/src/xrpld/app/tx/detail/VaultWithdraw.cpp index f8b7a1a739..9a4334e435 100644 --- a/src/xrpld/app/tx/detail/VaultWithdraw.cpp +++ b/src/xrpld/app/tx/detail/VaultWithdraw.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -115,6 +116,7 @@ VaultWithdraw::doApply() auto const amount = ctx_.tx[sfAmount]; Asset const vaultAsset = vault->at(sfAsset); + MPTIssue const share{mptIssuanceID}; STAmount sharesRedeemed = {share}; STAmount assetsWithdrawn; @@ -239,6 +241,8 @@ VaultWithdraw::doApply() auto const dstAcct = ctx_.tx[~sfDestination].value_or(account_); + associateAsset(*vault, vaultAsset); + return doWithdraw( view(), ctx_.tx, diff --git a/src/xrpld/app/tx/detail/applySteps.cpp b/src/xrpld/app/tx/detail/applySteps.cpp index e0bd9d0d2d..0fae1a15e0 100644 --- a/src/xrpld/app/tx/detail/applySteps.cpp +++ b/src/xrpld/app/tx/detail/applySteps.cpp @@ -34,8 +34,38 @@ struct UnknownTxnType : std::exception // throw an "UnknownTxnType" exception on error template auto -with_txn_type(TxType txnType, F&& f) +with_txn_type(Rules const& rules, TxType txnType, F&& f) { + // These global updates really should have been for every Transaction + // step: preflight, preclaim, calculateBaseFee, and doApply. Unfortunately, + // they were only included in doApply (via Transactor::operator()). That may + // have been sufficient when the changes were only related to operations + // that mutated data, but some features will now change how they read data, + // so these need to be more global. + // + // To prevent unintentional side effects on existing checks, they will be + // set for every operation only once SingleAssetVault (or later + // LendingProtocol) are enabled. + // + // See also Transactor::operator(). + // + std::optional stNumberSO; + std::optional rulesGuard; + std::optional mantissaScaleGuard; + if (rules.enabled(featureSingleAssetVault) || + rules.enabled(featureLendingProtocol)) + { + // raii classes for the current ledger rules. + // fixUniversalNumber predates the rulesGuard and should be replaced. + stNumberSO.emplace(rules.enabled(fixUniversalNumber)); + rulesGuard.emplace(rules); + } + else + { + // Without those features enabled, always use the old number rules. + mantissaScaleGuard.emplace(MantissaRange::small); + } + switch (txnType) { #pragma push_macro("TRANSACTION") @@ -99,7 +129,7 @@ invoke_preflight(PreflightContext const& ctx) { try { - return with_txn_type(ctx.tx.getTxnType(), [&]() { + return with_txn_type(ctx.rules, ctx.tx.getTxnType(), [&]() { auto const tec = Transactor::invokePreflight(ctx); return std::make_pair( tec, @@ -126,50 +156,51 @@ invoke_preclaim(PreclaimContext const& ctx) { // use name hiding to accomplish compile-time polymorphism of static // class functions for Transactor and derived classes. - return with_txn_type(ctx.tx.getTxnType(), [&]() -> TER { - // preclaim functionality is divided into two sections: - // 1. Up to and including the signature check: returns NotTEC. - // All transaction checks before and including checkSign - // MUST return NotTEC, or something more restrictive. - // Allowing tec results in these steps risks theft or - // destruction of funds, as a fee will be charged before the - // signature is checked. - // 2. After the signature check: returns TER. + return with_txn_type( + ctx.view.rules(), ctx.tx.getTxnType(), [&]() -> TER { + // preclaim functionality is divided into two sections: + // 1. Up to and including the signature check: returns NotTEC. + // All transaction checks before and including checkSign + // MUST return NotTEC, or something more restrictive. + // Allowing tec results in these steps risks theft or + // destruction of funds, as a fee will be charged before the + // signature is checked. + // 2. After the signature check: returns TER. - // If the transactor requires a valid account and the - // transaction doesn't list one, preflight will have already - // a flagged a failure. - auto const id = ctx.tx.getAccountID(sfAccount); + // If the transactor requires a valid account and the + // transaction doesn't list one, preflight will have already + // a flagged a failure. + auto const id = ctx.tx.getAccountID(sfAccount); - if (id != beast::zero) - { - if (NotTEC const preSigResult = [&]() -> NotTEC { - if (NotTEC const result = - T::checkSeqProxy(ctx.view, ctx.tx, ctx.j)) - return result; + if (id != beast::zero) + { + if (NotTEC const preSigResult = [&]() -> NotTEC { + if (NotTEC const result = + T::checkSeqProxy(ctx.view, ctx.tx, ctx.j)) + return result; - if (NotTEC const result = - T::checkPriorTxAndLastLedger(ctx)) - return result; + if (NotTEC const result = + T::checkPriorTxAndLastLedger(ctx)) + return result; - if (NotTEC const result = - T::checkPermission(ctx.view, ctx.tx)) - return result; + if (NotTEC const result = + T::checkPermission(ctx.view, ctx.tx)) + return result; - if (NotTEC const result = T::checkSign(ctx)) - return result; + if (NotTEC const result = T::checkSign(ctx)) + return result; - return tesSUCCESS; - }()) - return preSigResult; + return tesSUCCESS; + }()) + return preSigResult; - if (TER const result = - T::checkFee(ctx, calculateBaseFee(ctx.view, ctx.tx))) - return result; - } + if (TER const result = T::checkFee( + ctx, calculateBaseFee(ctx.view, ctx.tx))) + return result; + } - return T::preclaim(ctx); - }); + return T::preclaim(ctx); + }); } catch (UnknownTxnType const& e) { @@ -204,7 +235,7 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx) { try { - return with_txn_type(tx.getTxnType(), [&]() { + return with_txn_type(view.rules(), tx.getTxnType(), [&]() { return T::calculateBaseFee(view, tx); }); } @@ -263,10 +294,11 @@ invoke_apply(ApplyContext& ctx) { try { - return with_txn_type(ctx.tx.getTxnType(), [&]() { - T p(ctx); - return p(); - }); + return with_txn_type( + ctx.view().rules(), ctx.tx.getTxnType(), [&]() { + T p(ctx); + return p(); + }); } catch (UnknownTxnType const& e) { From efa57e872badfacc82e4d95c65b64d0b95dc6bf3 Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Tue, 13 Jan 2026 17:53:40 -0400 Subject: [PATCH 072/105] Change LendingProtocol feature and dependencies to supported (#6146) --- include/xrpl/protocol/detail/features.macro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 932668c16f..0c952bf59b 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -17,7 +17,7 @@ // Keep it sorted in reverse chronological order. XRPL_FIX (BatchInnerSigs, Supported::yes, VoteBehavior::DefaultNo) -XRPL_FEATURE(LendingProtocol, Supported::no, VoteBehavior::DefaultNo) +XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo) XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (IncludeKeyletFields, Supported::yes, VoteBehavior::DefaultNo) @@ -31,7 +31,7 @@ XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo) -XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo) +XRPL_FEATURE(SingleAssetVault, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo) // Check flags in Credential transactions XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo) From ebcfd6645db82e0485fdb380ecdf9f413a4c1044 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 14 Jan 2026 14:40:07 -0500 Subject: [PATCH 073/105] test: Replace `failed` string in Vault test case (#6214) The word `failed` in the test case makes it hard to search through the test logs when an actual test failure occurs, so this change renames the word to just `fail` instead. --- src/test/app/Vault_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index a6d08b6531..41a4fc2b3b 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -2076,7 +2076,7 @@ class Vault_test : public beast::unit_test::suite PrettyAsset const& asset, Vault& vault, MPTTester& mptt) { - testcase("MPT failed reserve to re-create MPToken"); + testcase("MPT fail reserve to re-create MPToken"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); From c9458b72cab68d3cbbf533cc87d14309c2eb93b7 Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Wed, 14 Jan 2026 19:45:00 -0400 Subject: [PATCH 074/105] test: Suppress "parse failed" message in Batch tests (#6207) --- src/test/app/Batch_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/app/Batch_test.cpp b/src/test/app/Batch_test.cpp index 68bf7e833b..67b0933ae2 100644 --- a/src/test/app/Batch_test.cpp +++ b/src/test/app/Batch_test.cpp @@ -427,6 +427,7 @@ class Batch_test : public beast::unit_test::suite auto const batchFee = batch::calcBatchFee(env, 0, 2); auto tx1 = batch::inner(pay(alice, bob, XRP(1)), seq + 1); tx1[jss::Fee] = "1.5"; + env.set_parse_failure_expected(true); try { env(batch::outer(alice, seq, batchFee, tfAllOrNothing), @@ -438,6 +439,7 @@ class Batch_test : public beast::unit_test::suite { BEAST_EXPECT(true); } + env.set_parse_failure_expected(false); } // temSEQ_AND_TICKET: Batch: inner txn cannot have both Sequence From ec44347ffc23db2dba3332c730a94e73e22054a6 Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Thu, 15 Jan 2026 13:36:13 +0000 Subject: [PATCH 075/105] test: Use gtest instead of doctest (#6216) This change switches over the doctest framework to the gtest framework. --- .config/cspell.config.yaml | 1 + conan.lock | 2 +- conanfile.py | 2 +- src/tests/README.md | 4 +- src/tests/libxrpl/CMakeLists.txt | 4 +- src/tests/libxrpl/basics/RangeSet.cpp | 100 +- src/tests/libxrpl/basics/Slice.cpp | 42 +- src/tests/libxrpl/basics/base64.cpp | 10 +- src/tests/libxrpl/basics/contract.cpp | 12 +- src/tests/libxrpl/basics/main.cpp | 10 +- src/tests/libxrpl/basics/mulDiv.cpp | 38 +- src/tests/libxrpl/basics/scope.cpp | 44 +- src/tests/libxrpl/basics/tagged_integer.cpp | 98 +- src/tests/libxrpl/crypto/csprng.cpp | 8 +- src/tests/libxrpl/crypto/main.cpp | 10 +- src/tests/libxrpl/json/Output.cpp | 16 +- src/tests/libxrpl/json/Value.cpp | 1061 +++++++++---------- src/tests/libxrpl/json/Writer.cpp | 40 +- src/tests/libxrpl/json/main.cpp | 10 +- src/tests/libxrpl/net/HTTPClient.cpp | 40 +- src/tests/libxrpl/net/main.cpp | 10 +- 21 files changed, 782 insertions(+), 780 deletions(-) diff --git a/.config/cspell.config.yaml b/.config/cspell.config.yaml index 8f782d9960..3bd295c14b 100644 --- a/.config/cspell.config.yaml +++ b/.config/cspell.config.yaml @@ -270,6 +270,7 @@ words: - xbridge - xchain - ximinez + - EXPECT_STREQ - XMACRO - xrpkuwait - xrpl diff --git a/conan.lock b/conan.lock index 44dc9031d2..f3fa1e5f6e 100644 --- a/conan.lock +++ b/conan.lock @@ -17,9 +17,9 @@ "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03", "libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736", "jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244", + "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152", "grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1765850193.734", "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772", - "doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1765850143.95", "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772", "c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336", "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837", diff --git a/conanfile.py b/conanfile.py index 96e3384979..8501909ce3 100644 --- a/conanfile.py +++ b/conanfile.py @@ -39,7 +39,7 @@ class Xrpl(ConanFile): ] test_requires = [ - "doctest/2.4.12", + "gtest/1.17.0", ] tool_requires = [ diff --git a/src/tests/README.md b/src/tests/README.md index 7c4cc5edf8..2a642a7633 100644 --- a/src/tests/README.md +++ b/src/tests/README.md @@ -1,5 +1,5 @@ # Unit tests This directory contains unit tests for the project. The difference from existing `src/test` folder -is that we switch to 3rd party testing framework (doctest). We intend to gradually move existing tests -from our own framework to doctest and such tests will be moved to this new folder. +is that we switch to 3rd party testing framework (`gtest`). We intend to gradually move existing tests +from our own framework to `gtest` and such tests will be moved to this new folder. diff --git a/src/tests/libxrpl/CMakeLists.txt b/src/tests/libxrpl/CMakeLists.txt index a2374698d9..74dc184700 100644 --- a/src/tests/libxrpl/CMakeLists.txt +++ b/src/tests/libxrpl/CMakeLists.txt @@ -1,14 +1,14 @@ include(XrplAddTest) # Test requirements. -find_package(doctest REQUIRED) +find_package(GTest REQUIRED) # Custom target for all tests defined in this file add_custom_target(xrpl.tests) # Common library dependencies for the rest of the tests. add_library(xrpl.imports.test INTERFACE) -target_link_libraries(xrpl.imports.test INTERFACE doctest::doctest xrpl.libxrpl) +target_link_libraries(xrpl.imports.test INTERFACE gtest::gtest xrpl.libxrpl) # One test for each module. xrpl_add_test(basics) diff --git a/src/tests/libxrpl/basics/RangeSet.cpp b/src/tests/libxrpl/basics/RangeSet.cpp index 8c43b26758..d0fc656368 100644 --- a/src/tests/libxrpl/basics/RangeSet.cpp +++ b/src/tests/libxrpl/basics/RangeSet.cpp @@ -1,15 +1,13 @@ #include -#include +#include #include #include using namespace xrpl; -TEST_SUITE_BEGIN("RangeSet"); - -TEST_CASE("prevMissing") +TEST(RangeSet, prevMissing) { // Set will include: // [ 0, 5] @@ -31,80 +29,78 @@ TEST_CASE("prevMissing") expected = ((i % 10) > 6) ? (i - 1) : oneBelowRange; } - CHECK(prevMissing(set, i) == expected); + EXPECT_EQ(prevMissing(set, i), expected); } } -TEST_CASE("toString") +TEST(RangeSet, toString) { RangeSet set; - CHECK(to_string(set) == "empty"); + EXPECT_EQ(to_string(set), "empty"); set.insert(1); - CHECK(to_string(set) == "1"); + EXPECT_EQ(to_string(set), "1"); set.insert(range(4u, 6u)); - CHECK(to_string(set) == "1,4-6"); + EXPECT_EQ(to_string(set), "1,4-6"); set.insert(2); - CHECK(to_string(set) == "1-2,4-6"); + EXPECT_EQ(to_string(set), "1-2,4-6"); set.erase(range(4u, 5u)); - CHECK(to_string(set) == "1-2,6"); + EXPECT_EQ(to_string(set), "1-2,6"); } -TEST_CASE("fromString") +TEST(RangeSet, fromString) { RangeSet set; - CHECK(!from_string(set, "")); - CHECK(boost::icl::length(set) == 0); + EXPECT_FALSE(from_string(set, "")); + EXPECT_EQ(boost::icl::length(set), 0); - CHECK(!from_string(set, "#")); - CHECK(boost::icl::length(set) == 0); + EXPECT_FALSE(from_string(set, "#")); + EXPECT_EQ(boost::icl::length(set), 0); - CHECK(!from_string(set, ",")); - CHECK(boost::icl::length(set) == 0); + EXPECT_FALSE(from_string(set, ",")); + EXPECT_EQ(boost::icl::length(set), 0); - CHECK(!from_string(set, ",-")); - CHECK(boost::icl::length(set) == 0); + EXPECT_FALSE(from_string(set, ",-")); + EXPECT_EQ(boost::icl::length(set), 0); - CHECK(!from_string(set, "1,,2")); - CHECK(boost::icl::length(set) == 0); + EXPECT_FALSE(from_string(set, "1,,2")); + EXPECT_EQ(boost::icl::length(set), 0); - CHECK(from_string(set, "1")); - CHECK(boost::icl::length(set) == 1); - CHECK(boost::icl::first(set) == 1); + EXPECT_TRUE(from_string(set, "1")); + EXPECT_EQ(boost::icl::length(set), 1); + EXPECT_EQ(boost::icl::first(set), 1); - CHECK(from_string(set, "1,1")); - CHECK(boost::icl::length(set) == 1); - CHECK(boost::icl::first(set) == 1); + EXPECT_TRUE(from_string(set, "1,1")); + EXPECT_EQ(boost::icl::length(set), 1); + EXPECT_EQ(boost::icl::first(set), 1); - CHECK(from_string(set, "1-1")); - CHECK(boost::icl::length(set) == 1); - CHECK(boost::icl::first(set) == 1); + EXPECT_TRUE(from_string(set, "1-1")); + EXPECT_EQ(boost::icl::length(set), 1); + EXPECT_EQ(boost::icl::first(set), 1); - CHECK(from_string(set, "1,4-6")); - CHECK(boost::icl::length(set) == 4); - CHECK(boost::icl::first(set) == 1); - CHECK(!boost::icl::contains(set, 2)); - CHECK(!boost::icl::contains(set, 3)); - CHECK(boost::icl::contains(set, 4)); - CHECK(boost::icl::contains(set, 5)); - CHECK(boost::icl::last(set) == 6); + EXPECT_TRUE(from_string(set, "1,4-6")); + EXPECT_EQ(boost::icl::length(set), 4); + EXPECT_EQ(boost::icl::first(set), 1); + EXPECT_FALSE(boost::icl::contains(set, 2)); + EXPECT_FALSE(boost::icl::contains(set, 3)); + EXPECT_TRUE(boost::icl::contains(set, 4)); + EXPECT_TRUE(boost::icl::contains(set, 5)); + EXPECT_EQ(boost::icl::last(set), 6); - CHECK(from_string(set, "1-2,4-6")); - CHECK(boost::icl::length(set) == 5); - CHECK(boost::icl::first(set) == 1); - CHECK(boost::icl::contains(set, 2)); - CHECK(boost::icl::contains(set, 4)); - CHECK(boost::icl::last(set) == 6); + EXPECT_TRUE(from_string(set, "1-2,4-6")); + EXPECT_EQ(boost::icl::length(set), 5); + EXPECT_EQ(boost::icl::first(set), 1); + EXPECT_TRUE(boost::icl::contains(set, 2)); + EXPECT_TRUE(boost::icl::contains(set, 4)); + EXPECT_EQ(boost::icl::last(set), 6); - CHECK(from_string(set, "1-2,6")); - CHECK(boost::icl::length(set) == 3); - CHECK(boost::icl::first(set) == 1); - CHECK(boost::icl::contains(set, 2)); - CHECK(boost::icl::last(set) == 6); + EXPECT_TRUE(from_string(set, "1-2,6")); + EXPECT_EQ(boost::icl::length(set), 3); + EXPECT_EQ(boost::icl::first(set), 1); + EXPECT_TRUE(boost::icl::contains(set, 2)); + EXPECT_EQ(boost::icl::last(set), 6); } - -TEST_SUITE_END(); diff --git a/src/tests/libxrpl/basics/Slice.cpp b/src/tests/libxrpl/basics/Slice.cpp index 03d89ff174..b36abe596d 100644 --- a/src/tests/libxrpl/basics/Slice.cpp +++ b/src/tests/libxrpl/basics/Slice.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -12,37 +12,35 @@ static std::uint8_t const data[] = { 0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c, 0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3}; -TEST_SUITE_BEGIN("Slice"); - -TEST_CASE("equality & inequality") +TEST(Slice, equality_and_inequality) { Slice const s0{}; - CHECK(s0.size() == 0); - CHECK(s0.data() == nullptr); - CHECK(s0 == s0); + EXPECT_EQ(s0.size(), 0); + EXPECT_EQ(s0.data(), nullptr); + EXPECT_EQ(s0, s0); // Test slices of equal and unequal size pointing to same data: for (std::size_t i = 0; i != sizeof(data); ++i) { Slice const s1{data, i}; - CHECK(s1.size() == i); - CHECK(s1.data() != nullptr); + EXPECT_EQ(s1.size(), i); + EXPECT_NE(s1.data(), nullptr); if (i == 0) - CHECK(s1 == s0); + EXPECT_EQ(s1, s0); else - CHECK(s1 != s0); + EXPECT_NE(s1, s0); for (std::size_t j = 0; j != sizeof(data); ++j) { Slice const s2{data, j}; if (i == j) - CHECK(s1 == s2); + EXPECT_EQ(s1, s2); else - CHECK(s1 != s2); + EXPECT_NE(s1, s2); } } @@ -53,22 +51,22 @@ TEST_CASE("equality & inequality") for (std::size_t i = 0; i != sizeof(data); ++i) a[i] = b[i] = data[i]; - CHECK(makeSlice(a) == makeSlice(b)); + EXPECT_EQ(makeSlice(a), makeSlice(b)); b[7]++; - CHECK(makeSlice(a) != makeSlice(b)); + EXPECT_NE(makeSlice(a), makeSlice(b)); a[7]++; - CHECK(makeSlice(a) == makeSlice(b)); + EXPECT_EQ(makeSlice(a), makeSlice(b)); } -TEST_CASE("indexing") +TEST(Slice, indexing) { Slice const s{data, sizeof(data)}; for (std::size_t i = 0; i != sizeof(data); ++i) - CHECK(s[i] == data[i]); + EXPECT_EQ(s[i], data[i]); } -TEST_CASE("advancing") +TEST(Slice, advancing) { for (std::size_t i = 0; i < sizeof(data); ++i) { @@ -77,10 +75,8 @@ TEST_CASE("advancing") Slice s(data + i, sizeof(data) - i); s += j; - CHECK(s.data() == data + i + j); - CHECK(s.size() == sizeof(data) - i - j); + EXPECT_EQ(s.data(), data + i + j); + EXPECT_EQ(s.size(), sizeof(data) - i - j); } } } - -TEST_SUITE_END(); diff --git a/src/tests/libxrpl/basics/base64.cpp b/src/tests/libxrpl/basics/base64.cpp index f6544105d8..cfffadf660 100644 --- a/src/tests/libxrpl/basics/base64.cpp +++ b/src/tests/libxrpl/basics/base64.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include @@ -10,11 +10,11 @@ static void check(std::string const& in, std::string const& out) { auto const encoded = base64_encode(in); - CHECK(encoded == out); - CHECK(base64_decode(encoded) == in); + EXPECT_EQ(encoded, out); + EXPECT_EQ(base64_decode(encoded), in); } -TEST_CASE("base64") +TEST(base64, base64) { // cspell: disable check("", ""); @@ -46,5 +46,5 @@ TEST_CASE("base64") std::string const notBase64 = "not_base64!!"; std::string const truncated = "not"; - CHECK(base64_decode(notBase64) == base64_decode(truncated)); + EXPECT_EQ(base64_decode(notBase64), base64_decode(truncated)); } diff --git a/src/tests/libxrpl/basics/contract.cpp b/src/tests/libxrpl/basics/contract.cpp index a1f6f0b777..d9b729e85d 100644 --- a/src/tests/libxrpl/basics/contract.cpp +++ b/src/tests/libxrpl/basics/contract.cpp @@ -1,13 +1,13 @@ #include -#include +#include #include #include using namespace xrpl; -TEST_CASE("contract") +TEST(contract, contract) { try { @@ -15,7 +15,7 @@ TEST_CASE("contract") } catch (std::runtime_error const& e1) { - CHECK(std::string(e1.what()) == "Throw test"); + EXPECT_STREQ(e1.what(), "Throw test"); try { @@ -23,15 +23,15 @@ TEST_CASE("contract") } catch (std::runtime_error const& e2) { - CHECK(std::string(e2.what()) == "Throw test"); + EXPECT_STREQ(e2.what(), "Throw test"); } catch (...) { - CHECK(false); + FAIL() << "std::runtime_error should have been re-caught"; } } catch (...) { - CHECK(false); + FAIL() << "std::runtime_error should have been caught the first time"; } } diff --git a/src/tests/libxrpl/basics/main.cpp b/src/tests/libxrpl/basics/main.cpp index 0a3f254ea8..5142bbe08a 100644 --- a/src/tests/libxrpl/basics/main.cpp +++ b/src/tests/libxrpl/basics/main.cpp @@ -1,2 +1,8 @@ -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include +#include + +int +main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/tests/libxrpl/basics/mulDiv.cpp b/src/tests/libxrpl/basics/mulDiv.cpp index d3c58ea2f4..c98c3fd61a 100644 --- a/src/tests/libxrpl/basics/mulDiv.cpp +++ b/src/tests/libxrpl/basics/mulDiv.cpp @@ -1,45 +1,45 @@ #include -#include +#include #include #include using namespace xrpl; -TEST_CASE("mulDiv") +TEST(mulDiv, mulDiv) { auto const max = std::numeric_limits::max(); std::uint64_t const max32 = std::numeric_limits::max(); auto result = mulDiv(85, 20, 5); - REQUIRE(result); - CHECK(*result == 340); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(*result, 340); result = mulDiv(20, 85, 5); - REQUIRE(result); - CHECK(*result == 340); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(*result, 340); result = mulDiv(0, max - 1, max - 3); - REQUIRE(result); - CHECK(*result == 0); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(*result, 0); result = mulDiv(max - 1, 0, max - 3); - REQUIRE(result); - CHECK(*result == 0); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(*result, 0); result = mulDiv(max, 2, max / 2); - REQUIRE(result); - CHECK(*result == 4); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(*result, 4); result = mulDiv(max, 1000, max / 1000); - REQUIRE(result); - CHECK(*result == 1000000); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(*result, 1000000); result = mulDiv(max, 1000, max / 1001); - REQUIRE(result); - CHECK(*result == 1001000); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(*result, 1001000); result = mulDiv(max32 + 1, max32 + 1, 5); - REQUIRE(result); - CHECK(*result == 3689348814741910323); + ASSERT_TRUE(result.has_value()); + EXPECT_EQ(*result, 3689348814741910323); // Overflow result = mulDiv(max - 1, max - 2, 5); - CHECK(!result); + EXPECT_FALSE(result.has_value()); } diff --git a/src/tests/libxrpl/basics/scope.cpp b/src/tests/libxrpl/basics/scope.cpp index b3774d54bd..309a41ec04 100644 --- a/src/tests/libxrpl/basics/scope.cpp +++ b/src/tests/libxrpl/basics/scope.cpp @@ -1,10 +1,10 @@ #include -#include +#include using namespace xrpl; -TEST_CASE("scope_exit") +TEST(scope, scope_exit) { // scope_exit always executes the functor on destruction, // unless release() is called @@ -12,23 +12,23 @@ TEST_CASE("scope_exit") { scope_exit x{[&i]() { i = 1; }}; } - CHECK(i == 1); + EXPECT_EQ(i, 1); { scope_exit x{[&i]() { i = 2; }}; x.release(); } - CHECK(i == 1); + EXPECT_EQ(i, 1); { scope_exit x{[&i]() { i += 2; }}; auto x2 = std::move(x); } - CHECK(i == 3); + EXPECT_EQ(i, 3); { scope_exit x{[&i]() { i = 4; }}; x.release(); auto x2 = std::move(x); } - CHECK(i == 3); + EXPECT_EQ(i, 3); { try { @@ -39,7 +39,7 @@ TEST_CASE("scope_exit") { } } - CHECK(i == 5); + EXPECT_EQ(i, 5); { try { @@ -51,10 +51,10 @@ TEST_CASE("scope_exit") { } } - CHECK(i == 5); + EXPECT_EQ(i, 5); } -TEST_CASE("scope_fail") +TEST(scope, scope_fail) { // scope_fail executes the functor on destruction only // if an exception is unwinding, unless release() is called @@ -62,23 +62,23 @@ TEST_CASE("scope_fail") { scope_fail x{[&i]() { i = 1; }}; } - CHECK(i == 0); + EXPECT_EQ(i, 0); { scope_fail x{[&i]() { i = 2; }}; x.release(); } - CHECK(i == 0); + EXPECT_EQ(i, 0); { scope_fail x{[&i]() { i = 3; }}; auto x2 = std::move(x); } - CHECK(i == 0); + EXPECT_EQ(i, 0); { scope_fail x{[&i]() { i = 4; }}; x.release(); auto x2 = std::move(x); } - CHECK(i == 0); + EXPECT_EQ(i, 0); { try { @@ -89,7 +89,7 @@ TEST_CASE("scope_fail") { } } - CHECK(i == 5); + EXPECT_EQ(i, 5); { try { @@ -101,10 +101,10 @@ TEST_CASE("scope_fail") { } } - CHECK(i == 5); + EXPECT_EQ(i, 5); } -TEST_CASE("scope_success") +TEST(scope, scope_success) { // scope_success executes the functor on destruction only // if an exception is not unwinding, unless release() is called @@ -112,23 +112,23 @@ TEST_CASE("scope_success") { scope_success x{[&i]() { i = 1; }}; } - CHECK(i == 1); + EXPECT_EQ(i, 1); { scope_success x{[&i]() { i = 2; }}; x.release(); } - CHECK(i == 1); + EXPECT_EQ(i, 1); { scope_success x{[&i]() { i += 2; }}; auto x2 = std::move(x); } - CHECK(i == 3); + EXPECT_EQ(i, 3); { scope_success x{[&i]() { i = 4; }}; x.release(); auto x2 = std::move(x); } - CHECK(i == 3); + EXPECT_EQ(i, 3); { try { @@ -139,7 +139,7 @@ TEST_CASE("scope_success") { } } - CHECK(i == 3); + EXPECT_EQ(i, 3); { try { @@ -151,5 +151,5 @@ TEST_CASE("scope_success") { } } - CHECK(i == 3); + EXPECT_EQ(i, 3); } diff --git a/src/tests/libxrpl/basics/tagged_integer.cpp b/src/tests/libxrpl/basics/tagged_integer.cpp index 45efc579ab..09f8b6787b 100644 --- a/src/tests/libxrpl/basics/tagged_integer.cpp +++ b/src/tests/libxrpl/basics/tagged_integer.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include @@ -102,127 +102,123 @@ static_assert( !std::is_convertible::value, "TagUInt2 should not be convertible to a TagUInt3"); -TEST_SUITE_BEGIN("tagged_integer"); - using TagInt = tagged_integer; -TEST_CASE("comparison operators") +TEST(tagged_integer, comparison_operators) { TagInt const zero(0); TagInt const one(1); - CHECK(one == one); - CHECK(!(one == zero)); + EXPECT_TRUE(one == one); + EXPECT_FALSE(one == zero); - CHECK(one != zero); - CHECK(!(one != one)); + EXPECT_TRUE(one != zero); + EXPECT_FALSE(one != one); - CHECK(zero < one); - CHECK(!(one < zero)); + EXPECT_TRUE(zero < one); + EXPECT_FALSE(one < zero); - CHECK(one > zero); - CHECK(!(zero > one)); + EXPECT_TRUE(one > zero); + EXPECT_FALSE(zero > one); - CHECK(one >= one); - CHECK(one >= zero); - CHECK(!(zero >= one)); + EXPECT_TRUE(one >= one); + EXPECT_TRUE(one >= zero); + EXPECT_FALSE(zero >= one); - CHECK(zero <= one); - CHECK(zero <= zero); - CHECK(!(one <= zero)); + EXPECT_TRUE(zero <= one); + EXPECT_TRUE(zero <= zero); + EXPECT_FALSE(one <= zero); } -TEST_CASE("increment / decrement operators") +TEST(tagged_integer, increment_decrement_operators) { TagInt const zero(0); TagInt const one(1); TagInt a{0}; ++a; - CHECK(a == one); + EXPECT_EQ(a, one); --a; - CHECK(a == zero); + EXPECT_EQ(a, zero); a++; - CHECK(a == one); + EXPECT_EQ(a, one); a--; - CHECK(a == zero); + EXPECT_EQ(a, zero); } -TEST_CASE("arithmetic operators") +TEST(tagged_integer, arithmetic_operators) { TagInt a{-2}; - CHECK(+a == TagInt{-2}); - CHECK(-a == TagInt{2}); - CHECK(TagInt{-3} + TagInt{4} == TagInt{1}); - CHECK(TagInt{-3} - TagInt{4} == TagInt{-7}); - CHECK(TagInt{-3} * TagInt{4} == TagInt{-12}); - CHECK(TagInt{8} / TagInt{4} == TagInt{2}); - CHECK(TagInt{7} % TagInt{4} == TagInt{3}); + EXPECT_EQ(+a, TagInt{-2}); + EXPECT_EQ(-a, TagInt{2}); + EXPECT_EQ(TagInt{-3} + TagInt{4}, TagInt{1}); + EXPECT_EQ(TagInt{-3} - TagInt{4}, TagInt{-7}); + EXPECT_EQ(TagInt{-3} * TagInt{4}, TagInt{-12}); + EXPECT_EQ(TagInt{8} / TagInt{4}, TagInt{2}); + EXPECT_EQ(TagInt{7} % TagInt{4}, TagInt{3}); - CHECK(~TagInt{8} == TagInt{~TagInt::value_type{8}}); - CHECK((TagInt{6} & TagInt{3}) == TagInt{2}); - CHECK((TagInt{6} | TagInt{3}) == TagInt{7}); - CHECK((TagInt{6} ^ TagInt{3}) == TagInt{5}); + EXPECT_EQ(~TagInt{8}, TagInt{~TagInt::value_type{8}}); + EXPECT_EQ((TagInt{6} & TagInt{3}), TagInt{2}); + EXPECT_EQ((TagInt{6} | TagInt{3}), TagInt{7}); + EXPECT_EQ((TagInt{6} ^ TagInt{3}), TagInt{5}); - CHECK((TagInt{4} << TagInt{2}) == TagInt{16}); - CHECK((TagInt{16} >> TagInt{2}) == TagInt{4}); + EXPECT_EQ((TagInt{4} << TagInt{2}), TagInt{16}); + EXPECT_EQ((TagInt{16} >> TagInt{2}), TagInt{4}); } -TEST_CASE("assignment operators") +TEST(tagged_integer, assignment_operators) { TagInt a{-2}; TagInt b{0}; b = a; - CHECK(b == TagInt{-2}); + EXPECT_EQ(b, TagInt{-2}); // -3 + 4 == 1 a = TagInt{-3}; a += TagInt{4}; - CHECK(a == TagInt{1}); + EXPECT_EQ(a, TagInt{1}); // -3 - 4 == -7 a = TagInt{-3}; a -= TagInt{4}; - CHECK(a == TagInt{-7}); + EXPECT_EQ(a, TagInt{-7}); // -3 * 4 == -12 a = TagInt{-3}; a *= TagInt{4}; - CHECK(a == TagInt{-12}); + EXPECT_EQ(a, TagInt{-12}); // 8/4 == 2 a = TagInt{8}; a /= TagInt{4}; - CHECK(a == TagInt{2}); + EXPECT_EQ(a, TagInt{2}); // 7 % 4 == 3 a = TagInt{7}; a %= TagInt{4}; - CHECK(a == TagInt{3}); + EXPECT_EQ(a, TagInt{3}); // 6 & 3 == 2 a = TagInt{6}; a /= TagInt{3}; - CHECK(a == TagInt{2}); + EXPECT_EQ(a, TagInt{2}); // 6 | 3 == 7 a = TagInt{6}; a |= TagInt{3}; - CHECK(a == TagInt{7}); + EXPECT_EQ(a, TagInt{7}); // 6 ^ 3 == 5 a = TagInt{6}; a ^= TagInt{3}; - CHECK(a == TagInt{5}); + EXPECT_EQ(a, TagInt{5}); // 4 << 2 == 16 a = TagInt{4}; a <<= TagInt{2}; - CHECK(a == TagInt{16}); + EXPECT_EQ(a, TagInt{16}); // 16 >> 2 == 4 a = TagInt{16}; a >>= TagInt{2}; - CHECK(a == TagInt{4}); + EXPECT_EQ(a, TagInt{4}); } - -TEST_SUITE_END(); diff --git a/src/tests/libxrpl/crypto/csprng.cpp b/src/tests/libxrpl/crypto/csprng.cpp index e59c8a555a..41dcfd57a9 100644 --- a/src/tests/libxrpl/crypto/csprng.cpp +++ b/src/tests/libxrpl/crypto/csprng.cpp @@ -1,15 +1,15 @@ #include -#include +#include using namespace xrpl; -TEST_CASE("get values") +TEST(csprng, get_values) { auto& engine = crypto_prng(); auto rand_val = engine(); - CHECK(rand_val >= engine.min()); - CHECK(rand_val <= engine.max()); + EXPECT_GE(rand_val, engine.min()); + EXPECT_LE(rand_val, engine.max()); uint16_t twoByte{0}; engine(&twoByte, sizeof(uint16_t)); } diff --git a/src/tests/libxrpl/crypto/main.cpp b/src/tests/libxrpl/crypto/main.cpp index 0a3f254ea8..5142bbe08a 100644 --- a/src/tests/libxrpl/crypto/main.cpp +++ b/src/tests/libxrpl/crypto/main.cpp @@ -1,2 +1,8 @@ -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include +#include + +int +main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/tests/libxrpl/json/Output.cpp b/src/tests/libxrpl/json/Output.cpp index 6e6c20a0e5..96d7369d51 100644 --- a/src/tests/libxrpl/json/Output.cpp +++ b/src/tests/libxrpl/json/Output.cpp @@ -2,31 +2,29 @@ #include #include -#include +#include #include using namespace xrpl; using namespace Json; -TEST_SUITE_BEGIN("JsonOutput"); - static void checkOutput(std::string const& valueDesc) { std::string output; Json::Value value; - REQUIRE(Json::Reader().parse(valueDesc, value)); + ASSERT_TRUE(Json::Reader().parse(valueDesc, value)); auto out = stringOutput(output); outputJson(value, out); auto expected = Json::FastWriter().write(value); - CHECK(output == expected); - CHECK(output == valueDesc); - CHECK(output == jsonAsString(value)); + EXPECT_EQ(output, expected); + EXPECT_EQ(output, valueDesc); + EXPECT_EQ(output, jsonAsString(value)); } -TEST_CASE("output cases") +TEST(JsonOutput, output_cases) { checkOutput("{}"); checkOutput("[]"); @@ -36,5 +34,3 @@ TEST_CASE("output cases") checkOutput("[[]]"); checkOutput(R"({"array":[{"12":23},{},null,false,0.5]})"); } - -TEST_SUITE_END(); diff --git a/src/tests/libxrpl/json/Value.cpp b/src/tests/libxrpl/json/Value.cpp index 25bd2f548d..4db1274a4d 100644 --- a/src/tests/libxrpl/json/Value.cpp +++ b/src/tests/libxrpl/json/Value.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -14,9 +14,7 @@ namespace xrpl { -TEST_SUITE_BEGIN("json_value"); - -TEST_CASE("limits") +TEST(json_value, limits) { using namespace Json; static_assert(Value::minInt == Int(~(UInt(-1) / 2))); @@ -24,31 +22,31 @@ TEST_CASE("limits") static_assert(Value::maxUInt == UInt(-1)); } -TEST_CASE("construct and compare Json::StaticString") +TEST(json_value, construct_and_compare_Json_StaticString) { static constexpr char sample[]{"Contents of a Json::StaticString"}; static constexpr Json::StaticString test1(sample); char const* addrTest1{test1}; - CHECK(addrTest1 == &sample[0]); - CHECK(test1.c_str() == &sample[0]); + EXPECT_EQ(addrTest1, &sample[0]); + EXPECT_EQ(test1.c_str(), &sample[0]); static constexpr Json::StaticString test2{ "Contents of a Json::StaticString"}; static constexpr Json::StaticString test3{"Another StaticString"}; - CHECK(test1 == test2); - CHECK(test1 != test3); + EXPECT_EQ(test1, test2); + EXPECT_NE(test1, test3); std::string str{sample}; - CHECK(str == test2); - CHECK(str != test3); - CHECK(test2 == str); - CHECK(test3 != str); + EXPECT_EQ(str, test2); + EXPECT_NE(str, test3); + EXPECT_EQ(test2, str); + EXPECT_NE(test3, str); } -TEST_CASE("different types") +TEST(json_value, different_types) { // Exercise ValueType constructor static constexpr Json::StaticString staticStr{"staticStr"}; @@ -56,166 +54,166 @@ TEST_CASE("different types") auto testCopy = [](Json::ValueType typ) { Json::Value val{typ}; Json::Value cpy{val}; - CHECK(val.type() == typ); - CHECK(cpy.type() == typ); + EXPECT_EQ(val.type(), typ); + EXPECT_EQ(cpy.type(), typ); return val; }; { Json::Value const nullV{testCopy(Json::nullValue)}; - CHECK(nullV.isNull()); - CHECK(!nullV.isBool()); - CHECK(!nullV.isInt()); - CHECK(!nullV.isUInt()); - CHECK(!nullV.isIntegral()); - CHECK(!nullV.isDouble()); - CHECK(!nullV.isNumeric()); - CHECK(!nullV.isString()); - CHECK(!nullV.isArray()); - CHECK(nullV.isArrayOrNull()); - CHECK(!nullV.isObject()); - CHECK(nullV.isObjectOrNull()); + EXPECT_TRUE(nullV.isNull()); + EXPECT_FALSE(nullV.isBool()); + EXPECT_FALSE(nullV.isInt()); + EXPECT_FALSE(nullV.isUInt()); + EXPECT_FALSE(nullV.isIntegral()); + EXPECT_FALSE(nullV.isDouble()); + EXPECT_FALSE(nullV.isNumeric()); + EXPECT_FALSE(nullV.isString()); + EXPECT_FALSE(nullV.isArray()); + EXPECT_TRUE(nullV.isArrayOrNull()); + EXPECT_FALSE(nullV.isObject()); + EXPECT_TRUE(nullV.isObjectOrNull()); } { Json::Value const intV{testCopy(Json::intValue)}; - CHECK(!intV.isNull()); - CHECK(!intV.isBool()); - CHECK(intV.isInt()); - CHECK(!intV.isUInt()); - CHECK(intV.isIntegral()); - CHECK(!intV.isDouble()); - CHECK(intV.isNumeric()); - CHECK(!intV.isString()); - CHECK(!intV.isArray()); - CHECK(!intV.isArrayOrNull()); - CHECK(!intV.isObject()); - CHECK(!intV.isObjectOrNull()); + EXPECT_FALSE(intV.isNull()); + EXPECT_FALSE(intV.isBool()); + EXPECT_TRUE(intV.isInt()); + EXPECT_FALSE(intV.isUInt()); + EXPECT_TRUE(intV.isIntegral()); + EXPECT_FALSE(intV.isDouble()); + EXPECT_TRUE(intV.isNumeric()); + EXPECT_FALSE(intV.isString()); + EXPECT_FALSE(intV.isArray()); + EXPECT_FALSE(intV.isArrayOrNull()); + EXPECT_FALSE(intV.isObject()); + EXPECT_FALSE(intV.isObjectOrNull()); } { Json::Value const uintV{testCopy(Json::uintValue)}; - CHECK(!uintV.isNull()); - CHECK(!uintV.isBool()); - CHECK(!uintV.isInt()); - CHECK(uintV.isUInt()); - CHECK(uintV.isIntegral()); - CHECK(!uintV.isDouble()); - CHECK(uintV.isNumeric()); - CHECK(!uintV.isString()); - CHECK(!uintV.isArray()); - CHECK(!uintV.isArrayOrNull()); - CHECK(!uintV.isObject()); - CHECK(!uintV.isObjectOrNull()); + EXPECT_FALSE(uintV.isNull()); + EXPECT_FALSE(uintV.isBool()); + EXPECT_FALSE(uintV.isInt()); + EXPECT_TRUE(uintV.isUInt()); + EXPECT_TRUE(uintV.isIntegral()); + EXPECT_FALSE(uintV.isDouble()); + EXPECT_TRUE(uintV.isNumeric()); + EXPECT_FALSE(uintV.isString()); + EXPECT_FALSE(uintV.isArray()); + EXPECT_FALSE(uintV.isArrayOrNull()); + EXPECT_FALSE(uintV.isObject()); + EXPECT_FALSE(uintV.isObjectOrNull()); } { Json::Value const realV{testCopy(Json::realValue)}; - CHECK(!realV.isNull()); - CHECK(!realV.isBool()); - CHECK(!realV.isInt()); - CHECK(!realV.isUInt()); - CHECK(!realV.isIntegral()); - CHECK(realV.isDouble()); - CHECK(realV.isNumeric()); - CHECK(!realV.isString()); - CHECK(!realV.isArray()); - CHECK(!realV.isArrayOrNull()); - CHECK(!realV.isObject()); - CHECK(!realV.isObjectOrNull()); + EXPECT_FALSE(realV.isNull()); + EXPECT_FALSE(realV.isBool()); + EXPECT_FALSE(realV.isInt()); + EXPECT_FALSE(realV.isUInt()); + EXPECT_FALSE(realV.isIntegral()); + EXPECT_TRUE(realV.isDouble()); + EXPECT_TRUE(realV.isNumeric()); + EXPECT_FALSE(realV.isString()); + EXPECT_FALSE(realV.isArray()); + EXPECT_FALSE(realV.isArrayOrNull()); + EXPECT_FALSE(realV.isObject()); + EXPECT_FALSE(realV.isObjectOrNull()); } { Json::Value const stringV{testCopy(Json::stringValue)}; - CHECK(!stringV.isNull()); - CHECK(!stringV.isBool()); - CHECK(!stringV.isInt()); - CHECK(!stringV.isUInt()); - CHECK(!stringV.isIntegral()); - CHECK(!stringV.isDouble()); - CHECK(!stringV.isNumeric()); - CHECK(stringV.isString()); - CHECK(!stringV.isArray()); - CHECK(!stringV.isArrayOrNull()); - CHECK(!stringV.isObject()); - CHECK(!stringV.isObjectOrNull()); + EXPECT_FALSE(stringV.isNull()); + EXPECT_FALSE(stringV.isBool()); + EXPECT_FALSE(stringV.isInt()); + EXPECT_FALSE(stringV.isUInt()); + EXPECT_FALSE(stringV.isIntegral()); + EXPECT_FALSE(stringV.isDouble()); + EXPECT_FALSE(stringV.isNumeric()); + EXPECT_TRUE(stringV.isString()); + EXPECT_FALSE(stringV.isArray()); + EXPECT_FALSE(stringV.isArrayOrNull()); + EXPECT_FALSE(stringV.isObject()); + EXPECT_FALSE(stringV.isObjectOrNull()); } { Json::Value const staticStrV{staticStr}; { Json::Value cpy{staticStrV}; - CHECK(staticStrV.type() == Json::stringValue); - CHECK(cpy.type() == Json::stringValue); + EXPECT_EQ(staticStrV.type(), Json::stringValue); + EXPECT_EQ(cpy.type(), Json::stringValue); } - CHECK(!staticStrV.isNull()); - CHECK(!staticStrV.isBool()); - CHECK(!staticStrV.isInt()); - CHECK(!staticStrV.isUInt()); - CHECK(!staticStrV.isIntegral()); - CHECK(!staticStrV.isDouble()); - CHECK(!staticStrV.isNumeric()); - CHECK(staticStrV.isString()); - CHECK(!staticStrV.isArray()); - CHECK(!staticStrV.isArrayOrNull()); - CHECK(!staticStrV.isObject()); - CHECK(!staticStrV.isObjectOrNull()); + EXPECT_FALSE(staticStrV.isNull()); + EXPECT_FALSE(staticStrV.isBool()); + EXPECT_FALSE(staticStrV.isInt()); + EXPECT_FALSE(staticStrV.isUInt()); + EXPECT_FALSE(staticStrV.isIntegral()); + EXPECT_FALSE(staticStrV.isDouble()); + EXPECT_FALSE(staticStrV.isNumeric()); + EXPECT_TRUE(staticStrV.isString()); + EXPECT_FALSE(staticStrV.isArray()); + EXPECT_FALSE(staticStrV.isArrayOrNull()); + EXPECT_FALSE(staticStrV.isObject()); + EXPECT_FALSE(staticStrV.isObjectOrNull()); } { Json::Value const boolV{testCopy(Json::booleanValue)}; - CHECK(!boolV.isNull()); - CHECK(boolV.isBool()); - CHECK(!boolV.isInt()); - CHECK(!boolV.isUInt()); - CHECK(boolV.isIntegral()); - CHECK(!boolV.isDouble()); - CHECK(boolV.isNumeric()); - CHECK(!boolV.isString()); - CHECK(!boolV.isArray()); - CHECK(!boolV.isArrayOrNull()); - CHECK(!boolV.isObject()); - CHECK(!boolV.isObjectOrNull()); + EXPECT_FALSE(boolV.isNull()); + EXPECT_TRUE(boolV.isBool()); + EXPECT_FALSE(boolV.isInt()); + EXPECT_FALSE(boolV.isUInt()); + EXPECT_TRUE(boolV.isIntegral()); + EXPECT_FALSE(boolV.isDouble()); + EXPECT_TRUE(boolV.isNumeric()); + EXPECT_FALSE(boolV.isString()); + EXPECT_FALSE(boolV.isArray()); + EXPECT_FALSE(boolV.isArrayOrNull()); + EXPECT_FALSE(boolV.isObject()); + EXPECT_FALSE(boolV.isObjectOrNull()); } { Json::Value const arrayV{testCopy(Json::arrayValue)}; - CHECK(!arrayV.isNull()); - CHECK(!arrayV.isBool()); - CHECK(!arrayV.isInt()); - CHECK(!arrayV.isUInt()); - CHECK(!arrayV.isIntegral()); - CHECK(!arrayV.isDouble()); - CHECK(!arrayV.isNumeric()); - CHECK(!arrayV.isString()); - CHECK(arrayV.isArray()); - CHECK(arrayV.isArrayOrNull()); - CHECK(!arrayV.isObject()); - CHECK(!arrayV.isObjectOrNull()); + EXPECT_FALSE(arrayV.isNull()); + EXPECT_FALSE(arrayV.isBool()); + EXPECT_FALSE(arrayV.isInt()); + EXPECT_FALSE(arrayV.isUInt()); + EXPECT_FALSE(arrayV.isIntegral()); + EXPECT_FALSE(arrayV.isDouble()); + EXPECT_FALSE(arrayV.isNumeric()); + EXPECT_FALSE(arrayV.isString()); + EXPECT_TRUE(arrayV.isArray()); + EXPECT_TRUE(arrayV.isArrayOrNull()); + EXPECT_FALSE(arrayV.isObject()); + EXPECT_FALSE(arrayV.isObjectOrNull()); } { Json::Value const objectV{testCopy(Json::objectValue)}; - CHECK(!objectV.isNull()); - CHECK(!objectV.isBool()); - CHECK(!objectV.isInt()); - CHECK(!objectV.isUInt()); - CHECK(!objectV.isIntegral()); - CHECK(!objectV.isDouble()); - CHECK(!objectV.isNumeric()); - CHECK(!objectV.isString()); - CHECK(!objectV.isArray()); - CHECK(!objectV.isArrayOrNull()); - CHECK(objectV.isObject()); - CHECK(objectV.isObjectOrNull()); + EXPECT_FALSE(objectV.isNull()); + EXPECT_FALSE(objectV.isBool()); + EXPECT_FALSE(objectV.isInt()); + EXPECT_FALSE(objectV.isUInt()); + EXPECT_FALSE(objectV.isIntegral()); + EXPECT_FALSE(objectV.isDouble()); + EXPECT_FALSE(objectV.isNumeric()); + EXPECT_FALSE(objectV.isString()); + EXPECT_FALSE(objectV.isArray()); + EXPECT_FALSE(objectV.isArrayOrNull()); + EXPECT_TRUE(objectV.isObject()); + EXPECT_TRUE(objectV.isObjectOrNull()); } } -TEST_CASE("compare strings") +TEST(json_value, compare_strings) { auto doCompare = [&](Json::Value const& lhs, Json::Value const& rhs, bool lhsEqRhs, bool lhsLtRhs, int line) { - CAPTURE(line); - CHECK((lhs == rhs) == lhsEqRhs); - CHECK((lhs != rhs) != lhsEqRhs); - CHECK((lhs < rhs) == (!(lhsEqRhs || !lhsLtRhs))); - CHECK((lhs <= rhs) == (lhsEqRhs || lhsLtRhs)); - CHECK((lhs >= rhs) == (lhsEqRhs || !lhsLtRhs)); - CHECK((lhs > rhs) == (!(lhsEqRhs || lhsLtRhs))); + SCOPED_TRACE(line); + EXPECT_EQ((lhs == rhs), lhsEqRhs); + EXPECT_NE((lhs != rhs), lhsEqRhs); + EXPECT_EQ((lhs < rhs), (!(lhsEqRhs || !lhsLtRhs))); + EXPECT_EQ((lhs <= rhs), (lhsEqRhs || lhsLtRhs)); + EXPECT_EQ((lhs >= rhs), (lhsEqRhs || !lhsLtRhs)); + EXPECT_EQ((lhs > rhs), (!(lhsEqRhs || lhsLtRhs))); }; Json::Value const null0; @@ -556,40 +554,40 @@ TEST_CASE("compare strings") #pragma pop_macro("DO_COMPARE") } -TEST_CASE("bool") +TEST(json_value, bool) { - CHECK(!Json::Value()); + EXPECT_FALSE(Json::Value()); - CHECK(!Json::Value("")); + EXPECT_FALSE(Json::Value("")); - CHECK(bool(Json::Value("empty"))); - CHECK(bool(Json::Value(false))); - CHECK(bool(Json::Value(true))); - CHECK(bool(Json::Value(0))); - CHECK(bool(Json::Value(1))); + EXPECT_TRUE(bool(Json::Value("empty"))); + EXPECT_TRUE(bool(Json::Value(false))); + EXPECT_TRUE(bool(Json::Value(true))); + EXPECT_TRUE(bool(Json::Value(0))); + EXPECT_TRUE(bool(Json::Value(1))); Json::Value array(Json::arrayValue); - CHECK(!array); + EXPECT_FALSE(array); array.append(0); - CHECK(bool(array)); + EXPECT_TRUE(bool(array)); Json::Value object(Json::objectValue); - CHECK(!object); + EXPECT_FALSE(object); object[""] = false; - CHECK(bool(object)); + EXPECT_TRUE(bool(object)); } -TEST_CASE("bad json") +TEST(json_value, bad_json) { char const* s(R"({"method":"ledger","params":[{"ledger_index":1e300}]})"); Json::Value j; Json::Reader r; - CHECK(r.parse(s, j)); + EXPECT_TRUE(r.parse(s, j)); } -TEST_CASE("edge cases") +TEST(json_value, edge_cases) { std::uint32_t max_uint = std::numeric_limits::max(); std::int32_t max_int = std::numeric_limits::max(); @@ -611,28 +609,27 @@ TEST_CASE("edge cases") Json::Value j1; Json::Reader r1; - CHECK(r1.parse(json, j1)); - CHECK(j1["max_uint"].asUInt() == max_uint); - CHECK(j1["max_uint"].asAbsUInt() == max_uint); - CHECK(j1["max_int"].asInt() == max_int); - CHECK(j1["max_int"].asAbsUInt() == max_int); - CHECK(j1["min_int"].asInt() == min_int); - CHECK( - j1["min_int"].asAbsUInt() == - static_cast(min_int) * -1); - CHECK(j1["a_uint"].asUInt() == a_uint); - CHECK(j1["a_uint"].asAbsUInt() == a_uint); - CHECK(j1["a_uint"] > a_large_int); - CHECK(j1["a_uint"] > a_small_int); - CHECK(j1["a_large_int"].asInt() == a_large_int); - CHECK(j1["a_large_int"].asAbsUInt() == a_large_int); - CHECK(j1["a_large_int"].asUInt() == a_large_int); - CHECK(j1["a_large_int"] < a_uint); - CHECK(j1["a_small_int"].asInt() == a_small_int); - CHECK( - j1["a_small_int"].asAbsUInt() == + EXPECT_TRUE(r1.parse(json, j1)); + EXPECT_EQ(j1["max_uint"].asUInt(), max_uint); + EXPECT_EQ(j1["max_uint"].asAbsUInt(), max_uint); + EXPECT_EQ(j1["max_int"].asInt(), max_int); + EXPECT_EQ(j1["max_int"].asAbsUInt(), max_int); + EXPECT_EQ(j1["min_int"].asInt(), min_int); + EXPECT_EQ( + j1["min_int"].asAbsUInt(), static_cast(min_int) * -1); + EXPECT_EQ(j1["a_uint"].asUInt(), a_uint); + EXPECT_EQ(j1["a_uint"].asAbsUInt(), a_uint); + EXPECT_GT(j1["a_uint"], a_large_int); + EXPECT_GT(j1["a_uint"], a_small_int); + EXPECT_EQ(j1["a_large_int"].asInt(), a_large_int); + EXPECT_EQ(j1["a_large_int"].asAbsUInt(), a_large_int); + EXPECT_EQ(j1["a_large_int"].asUInt(), a_large_int); + EXPECT_LT(j1["a_large_int"], a_uint); + EXPECT_EQ(j1["a_small_int"].asInt(), a_small_int); + EXPECT_EQ( + j1["a_small_int"].asAbsUInt(), static_cast(a_small_int) * -1); - CHECK(j1["a_small_int"] < a_uint); + EXPECT_LT(j1["a_small_int"], a_uint); } std::uint64_t overflow = std::uint64_t(max_uint) + 1; @@ -644,7 +641,7 @@ TEST_CASE("edge cases") Json::Value j2; Json::Reader r2; - CHECK(!r2.parse(json, j2)); + EXPECT_FALSE(r2.parse(json, j2)); } std::int64_t underflow = std::int64_t(min_int) - 1; @@ -656,167 +653,167 @@ TEST_CASE("edge cases") Json::Value j3; Json::Reader r3; - CHECK(!r3.parse(json, j3)); + EXPECT_FALSE(r3.parse(json, j3)); } { Json::Value intString{std::to_string(overflow)}; - CHECK_THROWS_AS(intString.asUInt(), beast::BadLexicalCast); - CHECK_THROWS_AS(intString.asAbsUInt(), Json::error); + EXPECT_THROW(intString.asUInt(), beast::BadLexicalCast); + EXPECT_THROW(intString.asAbsUInt(), Json::error); intString = "4294967295"; - CHECK(intString.asUInt() == 4294967295u); - CHECK(intString.asAbsUInt() == 4294967295u); + EXPECT_EQ(intString.asUInt(), 4294967295u); + EXPECT_EQ(intString.asAbsUInt(), 4294967295u); intString = "0"; - CHECK(intString.asUInt() == 0); - CHECK(intString.asAbsUInt() == 0); + EXPECT_EQ(intString.asUInt(), 0); + EXPECT_EQ(intString.asAbsUInt(), 0); intString = "-1"; - CHECK_THROWS_AS(intString.asUInt(), beast::BadLexicalCast); - CHECK(intString.asAbsUInt() == 1); + EXPECT_THROW(intString.asUInt(), beast::BadLexicalCast); + EXPECT_EQ(intString.asAbsUInt(), 1); intString = "-4294967295"; - CHECK(intString.asAbsUInt() == 4294967295); + EXPECT_EQ(intString.asAbsUInt(), 4294967295); intString = "-4294967296"; - CHECK_THROWS_AS(intString.asAbsUInt(), Json::error); + EXPECT_THROW(intString.asAbsUInt(), Json::error); intString = "2147483648"; - CHECK_THROWS_AS(intString.asInt(), beast::BadLexicalCast); - CHECK(intString.asAbsUInt() == 2147483648); + EXPECT_THROW(intString.asInt(), beast::BadLexicalCast); + EXPECT_EQ(intString.asAbsUInt(), 2147483648); intString = "2147483647"; - CHECK(intString.asInt() == 2147483647); - CHECK(intString.asAbsUInt() == 2147483647); + EXPECT_EQ(intString.asInt(), 2147483647); + EXPECT_EQ(intString.asAbsUInt(), 2147483647); intString = "-2147483648"; - CHECK(intString.asInt() == -2147483648LL); // MSVC wants the LL - CHECK(intString.asAbsUInt() == 2147483648LL); + EXPECT_EQ(intString.asInt(), -2147483648LL); // MSVC wants the LL + EXPECT_EQ(intString.asAbsUInt(), 2147483648LL); intString = "-2147483649"; - CHECK_THROWS_AS(intString.asInt(), beast::BadLexicalCast); - CHECK(intString.asAbsUInt() == 2147483649); + EXPECT_THROW(intString.asInt(), beast::BadLexicalCast); + EXPECT_EQ(intString.asAbsUInt(), 2147483649); } { Json::Value intReal{4294967297.0}; - CHECK_THROWS_AS(intReal.asUInt(), Json::error); - CHECK_THROWS_AS(intReal.asAbsUInt(), Json::error); + EXPECT_THROW(intReal.asUInt(), Json::error); + EXPECT_THROW(intReal.asAbsUInt(), Json::error); intReal = 4294967295.0; - CHECK(intReal.asUInt() == 4294967295u); - CHECK(intReal.asAbsUInt() == 4294967295u); + EXPECT_EQ(intReal.asUInt(), 4294967295u); + EXPECT_EQ(intReal.asAbsUInt(), 4294967295u); intReal = 0.0; - CHECK(intReal.asUInt() == 0); - CHECK(intReal.asAbsUInt() == 0); + EXPECT_EQ(intReal.asUInt(), 0); + EXPECT_EQ(intReal.asAbsUInt(), 0); intReal = -1.0; - CHECK_THROWS_AS(intReal.asUInt(), Json::error); - CHECK(intReal.asAbsUInt() == 1); + EXPECT_THROW(intReal.asUInt(), Json::error); + EXPECT_EQ(intReal.asAbsUInt(), 1); intReal = -4294967295.0; - CHECK(intReal.asAbsUInt() == 4294967295); + EXPECT_EQ(intReal.asAbsUInt(), 4294967295); intReal = -4294967296.0; - CHECK_THROWS_AS(intReal.asAbsUInt(), Json::error); + EXPECT_THROW(intReal.asAbsUInt(), Json::error); intReal = 2147483648.0; - CHECK_THROWS_AS(intReal.asInt(), Json::error); - CHECK(intReal.asAbsUInt() == 2147483648); + EXPECT_THROW(intReal.asInt(), Json::error); + EXPECT_EQ(intReal.asAbsUInt(), 2147483648); intReal = 2147483647.0; - CHECK(intReal.asInt() == 2147483647); - CHECK(intReal.asAbsUInt() == 2147483647); + EXPECT_EQ(intReal.asInt(), 2147483647); + EXPECT_EQ(intReal.asAbsUInt(), 2147483647); intReal = -2147483648.0; - CHECK(intReal.asInt() == -2147483648LL); // MSVC wants the LL - CHECK(intReal.asAbsUInt() == 2147483648LL); + EXPECT_EQ(intReal.asInt(), -2147483648LL); // MSVC wants the LL + EXPECT_EQ(intReal.asAbsUInt(), 2147483648LL); intReal = -2147483649.0; - CHECK_THROWS_AS(intReal.asInt(), Json::error); - CHECK(intReal.asAbsUInt() == 2147483649); + EXPECT_THROW(intReal.asInt(), Json::error); + EXPECT_EQ(intReal.asAbsUInt(), 2147483649); } } -TEST_CASE("copy") +TEST(json_value, copy) { Json::Value v1{2.5}; - CHECK(v1.isDouble()); - CHECK(v1.asDouble() == 2.5); + EXPECT_TRUE(v1.isDouble()); + EXPECT_EQ(v1.asDouble(), 2.5); Json::Value v2 = v1; - CHECK(v1.isDouble()); - CHECK(v1.asDouble() == 2.5); - CHECK(v2.isDouble()); - CHECK(v2.asDouble() == 2.5); - CHECK(v1 == v2); + EXPECT_TRUE(v1.isDouble()); + EXPECT_EQ(v1.asDouble(), 2.5); + EXPECT_TRUE(v2.isDouble()); + EXPECT_EQ(v2.asDouble(), 2.5); + EXPECT_EQ(v1, v2); v1 = v2; - CHECK(v1.isDouble()); - CHECK(v1.asDouble() == 2.5); - CHECK(v2.isDouble()); - CHECK(v2.asDouble() == 2.5); - CHECK(v1 == v2); + EXPECT_TRUE(v1.isDouble()); + EXPECT_EQ(v1.asDouble(), 2.5); + EXPECT_TRUE(v2.isDouble()); + EXPECT_EQ(v2.asDouble(), 2.5); + EXPECT_EQ(v1, v2); } -TEST_CASE("move") +TEST(json_value, move) { Json::Value v1{2.5}; - CHECK(v1.isDouble()); - CHECK(v1.asDouble() == 2.5); + EXPECT_TRUE(v1.isDouble()); + EXPECT_EQ(v1.asDouble(), 2.5); Json::Value v2 = std::move(v1); - CHECK(!v1); - CHECK(v2.isDouble()); - CHECK(v2.asDouble() == 2.5); - CHECK(v1 != v2); + EXPECT_FALSE(v1); + EXPECT_TRUE(v2.isDouble()); + EXPECT_EQ(v2.asDouble(), 2.5); + EXPECT_NE(v1, v2); v1 = std::move(v2); - CHECK(v1.isDouble()); - CHECK(v1.asDouble() == 2.5); - CHECK(!v2); - CHECK(v1 != v2); + EXPECT_TRUE(v1.isDouble()); + EXPECT_EQ(v1.asDouble(), 2.5); + EXPECT_FALSE(v2); + EXPECT_NE(v1, v2); } -TEST_CASE("comparisons") +TEST(json_value, comparisons) { Json::Value a, b; auto testEquals = [&](std::string const& name) { - CHECK(a == b); - CHECK(a <= b); - CHECK(a >= b); + EXPECT_TRUE(a == b); + EXPECT_TRUE(a <= b); + EXPECT_TRUE(a >= b); - CHECK(!(a != b)); - CHECK(!(a < b)); - CHECK(!(a > b)); + EXPECT_FALSE(a != b); + EXPECT_FALSE(a < b); + EXPECT_FALSE(a > b); - CHECK(b == a); - CHECK(b <= a); - CHECK(b >= a); + EXPECT_TRUE(b == a); + EXPECT_TRUE(b <= a); + EXPECT_TRUE(b >= a); - CHECK(!(b != a)); - CHECK(!(b < a)); - CHECK(!(b > a)); + EXPECT_FALSE(b != a); + EXPECT_FALSE(b < a); + EXPECT_FALSE(b > a); }; auto testGreaterThan = [&](std::string const& name) { - CHECK(!(a == b)); - CHECK(!(a <= b)); - CHECK(a >= b); + EXPECT_FALSE(a == b); + EXPECT_FALSE(a <= b); + EXPECT_TRUE(a >= b); - CHECK(a != b); - CHECK(!(a < b)); - CHECK(a > b); + EXPECT_TRUE(a != b); + EXPECT_FALSE(a < b); + EXPECT_TRUE(a > b); - CHECK(!(b == a)); - CHECK(b <= a); - CHECK(!(b >= a)); + EXPECT_FALSE(b == a); + EXPECT_TRUE(b <= a); + EXPECT_FALSE(b >= a); - CHECK(b != a); - CHECK(b < a); - CHECK(!(b > a)); + EXPECT_TRUE(b != a); + EXPECT_TRUE(b < a); + EXPECT_FALSE(b > a); }; a["a"] = Json::UInt(0); @@ -835,7 +832,7 @@ TEST_CASE("comparisons") testGreaterThan("big"); } -TEST_CASE("compact") +TEST(json_value, compact) { Json::Value j; Json::Reader r; @@ -847,20 +844,20 @@ TEST_CASE("compact") }); }; - CHECK(r.parse(s, j)); + EXPECT_TRUE(r.parse(s, j)); { std::stringstream ss; ss << j; - CHECK(countLines(ss.str()) > 1); + EXPECT_GT(countLines(ss.str()), 1); } { std::stringstream ss; ss << Json::Compact(std::move(j)); - CHECK(countLines(ss.str()) == 1); + EXPECT_EQ(countLines(ss.str()), 1); } } -TEST_CASE("conversions") +TEST(json_value, conversions) { // We have Json::Int, but not Json::Double or Json::Real. // We have Json::Int, Json::Value::Int, and Json::ValueType::intValue. @@ -869,336 +866,336 @@ TEST_CASE("conversions") { // null Json::Value val; - CHECK(val.isNull()); + EXPECT_TRUE(val.isNull()); // val.asCString() should trigger an assertion failure - CHECK(val.asString() == ""); - CHECK(val.asInt() == 0); - CHECK(val.asUInt() == 0); - CHECK(val.asAbsUInt() == 0); - CHECK(val.asDouble() == 0.0); - CHECK(val.asBool() == false); + EXPECT_EQ(val.asString(), ""); + EXPECT_EQ(val.asInt(), 0); + EXPECT_EQ(val.asUInt(), 0); + EXPECT_EQ(val.asAbsUInt(), 0); + EXPECT_EQ(val.asDouble(), 0.0); + EXPECT_FALSE(val.asBool()); - CHECK(val.isConvertibleTo(Json::nullValue)); - CHECK(val.isConvertibleTo(Json::intValue)); - CHECK(val.isConvertibleTo(Json::uintValue)); - CHECK(val.isConvertibleTo(Json::realValue)); - CHECK(val.isConvertibleTo(Json::stringValue)); - CHECK(val.isConvertibleTo(Json::booleanValue)); - CHECK(val.isConvertibleTo(Json::arrayValue)); - CHECK(val.isConvertibleTo(Json::objectValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::nullValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::intValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::uintValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::realValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::stringValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::objectValue)); } { // int Json::Value val = -1234; - CHECK(val.isInt()); + EXPECT_TRUE(val.isInt()); // val.asCString() should trigger an assertion failure - CHECK(val.asString() == "-1234"); - CHECK(val.asInt() == -1234); - CHECK_THROWS_AS(val.asUInt(), Json::error); - CHECK(val.asAbsUInt() == 1234u); - CHECK(val.asDouble() == -1234.0); - CHECK(val.asBool() == true); + EXPECT_EQ(val.asString(), "-1234"); + EXPECT_EQ(val.asInt(), -1234); + EXPECT_THROW(val.asUInt(), Json::error); + EXPECT_EQ(val.asAbsUInt(), 1234u); + EXPECT_EQ(val.asDouble(), -1234.0); + EXPECT_TRUE(val.asBool()); - CHECK(!val.isConvertibleTo(Json::nullValue)); - CHECK(val.isConvertibleTo(Json::intValue)); - CHECK(!val.isConvertibleTo(Json::uintValue)); - CHECK(val.isConvertibleTo(Json::realValue)); - CHECK(val.isConvertibleTo(Json::stringValue)); - CHECK(val.isConvertibleTo(Json::booleanValue)); - CHECK(!val.isConvertibleTo(Json::arrayValue)); - CHECK(!val.isConvertibleTo(Json::objectValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::nullValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::intValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::uintValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::realValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::stringValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::objectValue)); } { // uint Json::Value val = 1234U; - CHECK(val.isUInt()); + EXPECT_TRUE(val.isUInt()); // val.asCString() should trigger an assertion failure - CHECK(val.asString() == "1234"); - CHECK(val.asInt() == 1234); - CHECK(val.asUInt() == 1234u); - CHECK(val.asAbsUInt() == 1234u); - CHECK(val.asDouble() == 1234.0); - CHECK(val.asBool() == true); + EXPECT_EQ(val.asString(), "1234"); + EXPECT_EQ(val.asInt(), 1234); + EXPECT_EQ(val.asUInt(), 1234u); + EXPECT_EQ(val.asAbsUInt(), 1234u); + EXPECT_EQ(val.asDouble(), 1234.0); + EXPECT_TRUE(val.asBool()); - CHECK(!val.isConvertibleTo(Json::nullValue)); - CHECK(val.isConvertibleTo(Json::intValue)); - CHECK(val.isConvertibleTo(Json::uintValue)); - CHECK(val.isConvertibleTo(Json::realValue)); - CHECK(val.isConvertibleTo(Json::stringValue)); - CHECK(val.isConvertibleTo(Json::booleanValue)); - CHECK(!val.isConvertibleTo(Json::arrayValue)); - CHECK(!val.isConvertibleTo(Json::objectValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::nullValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::intValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::uintValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::realValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::stringValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::objectValue)); } { // real Json::Value val = 2.0; - CHECK(val.isDouble()); + EXPECT_TRUE(val.isDouble()); // val.asCString() should trigger an assertion failure - CHECK(std::regex_match(val.asString(), std::regex("^2\\.0*$"))); - CHECK(val.asInt() == 2); - CHECK(val.asUInt() == 2u); - CHECK(val.asAbsUInt() == 2u); - CHECK(val.asDouble() == 2.0); - CHECK(val.asBool() == true); + EXPECT_TRUE(std::regex_match(val.asString(), std::regex("^2\\.0*$"))); + EXPECT_EQ(val.asInt(), 2); + EXPECT_EQ(val.asUInt(), 2u); + EXPECT_EQ(val.asAbsUInt(), 2u); + EXPECT_EQ(val.asDouble(), 2.0); + EXPECT_TRUE(val.asBool()); - CHECK(!val.isConvertibleTo(Json::nullValue)); - CHECK(val.isConvertibleTo(Json::intValue)); - CHECK(val.isConvertibleTo(Json::uintValue)); - CHECK(val.isConvertibleTo(Json::realValue)); - CHECK(val.isConvertibleTo(Json::stringValue)); - CHECK(val.isConvertibleTo(Json::booleanValue)); - CHECK(!val.isConvertibleTo(Json::arrayValue)); - CHECK(!val.isConvertibleTo(Json::objectValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::nullValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::intValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::uintValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::realValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::stringValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::objectValue)); } { // numeric string Json::Value val = "54321"; - CHECK(val.isString()); - CHECK(strcmp(val.asCString(), "54321") == 0); - CHECK(val.asString() == "54321"); - CHECK(val.asInt() == 54321); - CHECK(val.asUInt() == 54321u); - CHECK(val.asAbsUInt() == 54321); - CHECK_THROWS_AS(val.asDouble(), Json::error); - CHECK(val.asBool() == true); + EXPECT_TRUE(val.isString()); + EXPECT_EQ(strcmp(val.asCString(), "54321"), 0); + EXPECT_EQ(val.asString(), "54321"); + EXPECT_EQ(val.asInt(), 54321); + EXPECT_EQ(val.asUInt(), 54321u); + EXPECT_EQ(val.asAbsUInt(), 54321); + EXPECT_THROW(val.asDouble(), Json::error); + EXPECT_TRUE(val.asBool()); - CHECK(!val.isConvertibleTo(Json::nullValue)); - CHECK(!val.isConvertibleTo(Json::intValue)); - CHECK(!val.isConvertibleTo(Json::uintValue)); - CHECK(!val.isConvertibleTo(Json::realValue)); - CHECK(val.isConvertibleTo(Json::stringValue)); - CHECK(!val.isConvertibleTo(Json::booleanValue)); - CHECK(!val.isConvertibleTo(Json::arrayValue)); - CHECK(!val.isConvertibleTo(Json::objectValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::nullValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::intValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::uintValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::realValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::stringValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::objectValue)); } { // non-numeric string Json::Value val(Json::stringValue); - CHECK(val.isString()); - CHECK(val.asCString() == nullptr); - CHECK(val.asString() == ""); - CHECK_THROWS_AS(val.asInt(), std::exception); - CHECK_THROWS_AS(val.asUInt(), std::exception); - CHECK_THROWS_AS(val.asAbsUInt(), std::exception); - CHECK_THROWS_AS(val.asDouble(), std::exception); - CHECK(val.asBool() == false); + EXPECT_TRUE(val.isString()); + EXPECT_EQ(val.asCString(), nullptr); + EXPECT_EQ(val.asString(), ""); + EXPECT_THROW(val.asInt(), std::exception); + EXPECT_THROW(val.asUInt(), std::exception); + EXPECT_THROW(val.asAbsUInt(), std::exception); + EXPECT_THROW(val.asDouble(), std::exception); + EXPECT_TRUE(val.asBool() == false); - CHECK(val.isConvertibleTo(Json::nullValue)); - CHECK(!val.isConvertibleTo(Json::intValue)); - CHECK(!val.isConvertibleTo(Json::uintValue)); - CHECK(!val.isConvertibleTo(Json::realValue)); - CHECK(val.isConvertibleTo(Json::stringValue)); - CHECK(!val.isConvertibleTo(Json::booleanValue)); - CHECK(!val.isConvertibleTo(Json::arrayValue)); - CHECK(!val.isConvertibleTo(Json::objectValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::nullValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::intValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::uintValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::realValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::stringValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::objectValue)); } { // bool false Json::Value val = false; - CHECK(val.isBool()); + EXPECT_TRUE(val.isBool()); // val.asCString() should trigger an assertion failure - CHECK(val.asString() == "false"); - CHECK(val.asInt() == 0); - CHECK(val.asUInt() == 0); - CHECK(val.asAbsUInt() == 0); - CHECK(val.asDouble() == 0.0); - CHECK(val.asBool() == false); + EXPECT_EQ(val.asString(), "false"); + EXPECT_EQ(val.asInt(), 0); + EXPECT_EQ(val.asUInt(), 0); + EXPECT_EQ(val.asAbsUInt(), 0); + EXPECT_EQ(val.asDouble(), 0.0); + EXPECT_FALSE(val.asBool()); - CHECK(val.isConvertibleTo(Json::nullValue)); - CHECK(val.isConvertibleTo(Json::intValue)); - CHECK(val.isConvertibleTo(Json::uintValue)); - CHECK(val.isConvertibleTo(Json::realValue)); - CHECK(val.isConvertibleTo(Json::stringValue)); - CHECK(val.isConvertibleTo(Json::booleanValue)); - CHECK(!val.isConvertibleTo(Json::arrayValue)); - CHECK(!val.isConvertibleTo(Json::objectValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::nullValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::intValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::uintValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::realValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::stringValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::objectValue)); } { // bool true Json::Value val = true; - CHECK(val.isBool()); + EXPECT_TRUE(val.isBool()); // val.asCString() should trigger an assertion failure - CHECK(val.asString() == "true"); - CHECK(val.asInt() == 1); - CHECK(val.asUInt() == 1); - CHECK(val.asAbsUInt() == 1); - CHECK(val.asDouble() == 1.0); - CHECK(val.asBool() == true); + EXPECT_EQ(val.asString(), "true"); + EXPECT_EQ(val.asInt(), 1); + EXPECT_EQ(val.asUInt(), 1); + EXPECT_EQ(val.asAbsUInt(), 1); + EXPECT_EQ(val.asDouble(), 1.0); + EXPECT_TRUE(val.asBool()); - CHECK(!val.isConvertibleTo(Json::nullValue)); - CHECK(val.isConvertibleTo(Json::intValue)); - CHECK(val.isConvertibleTo(Json::uintValue)); - CHECK(val.isConvertibleTo(Json::realValue)); - CHECK(val.isConvertibleTo(Json::stringValue)); - CHECK(val.isConvertibleTo(Json::booleanValue)); - CHECK(!val.isConvertibleTo(Json::arrayValue)); - CHECK(!val.isConvertibleTo(Json::objectValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::nullValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::intValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::uintValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::realValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::stringValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::objectValue)); } { // array type Json::Value val(Json::arrayValue); - CHECK(val.isArray()); + EXPECT_TRUE(val.isArray()); // val.asCString should trigger an assertion failure - CHECK_THROWS_AS(val.asString(), Json::error); - CHECK_THROWS_AS(val.asInt(), Json::error); - CHECK_THROWS_AS(val.asUInt(), Json::error); - CHECK_THROWS_AS(val.asAbsUInt(), Json::error); - CHECK_THROWS_AS(val.asDouble(), Json::error); - CHECK(val.asBool() == false); // empty or not + EXPECT_THROW(val.asString(), Json::error); + EXPECT_THROW(val.asInt(), Json::error); + EXPECT_THROW(val.asUInt(), Json::error); + EXPECT_THROW(val.asAbsUInt(), Json::error); + EXPECT_THROW(val.asDouble(), Json::error); + EXPECT_FALSE(val.asBool()); // empty or not - CHECK(val.isConvertibleTo(Json::nullValue)); - CHECK(!val.isConvertibleTo(Json::intValue)); - CHECK(!val.isConvertibleTo(Json::uintValue)); - CHECK(!val.isConvertibleTo(Json::realValue)); - CHECK(!val.isConvertibleTo(Json::stringValue)); - CHECK(!val.isConvertibleTo(Json::booleanValue)); - CHECK(val.isConvertibleTo(Json::arrayValue)); - CHECK(!val.isConvertibleTo(Json::objectValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::nullValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::intValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::uintValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::realValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::stringValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::objectValue)); } { // object type Json::Value val(Json::objectValue); - CHECK(val.isObject()); + EXPECT_TRUE(val.isObject()); // val.asCString should trigger an assertion failure - CHECK_THROWS_AS(val.asString(), Json::error); - CHECK_THROWS_AS(val.asInt(), Json::error); - CHECK_THROWS_AS(val.asUInt(), Json::error); - CHECK_THROWS_AS(val.asAbsUInt(), Json::error); - CHECK_THROWS_AS(val.asDouble(), Json::error); - CHECK(val.asBool() == false); // empty or not + EXPECT_THROW(val.asString(), Json::error); + EXPECT_THROW(val.asInt(), Json::error); + EXPECT_THROW(val.asUInt(), Json::error); + EXPECT_THROW(val.asAbsUInt(), Json::error); + EXPECT_THROW(val.asDouble(), Json::error); + EXPECT_FALSE(val.asBool()); // empty or not - CHECK(val.isConvertibleTo(Json::nullValue)); - CHECK(!val.isConvertibleTo(Json::intValue)); - CHECK(!val.isConvertibleTo(Json::uintValue)); - CHECK(!val.isConvertibleTo(Json::realValue)); - CHECK(!val.isConvertibleTo(Json::stringValue)); - CHECK(!val.isConvertibleTo(Json::booleanValue)); - CHECK(!val.isConvertibleTo(Json::arrayValue)); - CHECK(val.isConvertibleTo(Json::objectValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::nullValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::intValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::uintValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::realValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::stringValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::booleanValue)); + EXPECT_FALSE(val.isConvertibleTo(Json::arrayValue)); + EXPECT_TRUE(val.isConvertibleTo(Json::objectValue)); } } -TEST_CASE("access members") +TEST(json_value, access_members) { Json::Value val; - CHECK(val.type() == Json::nullValue); - CHECK(val.size() == 0); - CHECK(!val.isValidIndex(0)); - CHECK(!val.isMember("key")); + EXPECT_EQ(val.type(), Json::nullValue); + EXPECT_EQ(val.size(), 0); + EXPECT_FALSE(val.isValidIndex(0)); + EXPECT_FALSE(val.isMember("key")); { Json::Value const constVal = val; - CHECK(constVal[7u].type() == Json::nullValue); - CHECK(!constVal.isMember("key")); - CHECK(constVal["key"].type() == Json::nullValue); - CHECK(constVal.getMemberNames().empty()); - CHECK(constVal.get(1u, "default0") == "default0"); - CHECK(constVal.get(std::string("not"), "oh") == "oh"); - CHECK(constVal.get("missing", "default2") == "default2"); + EXPECT_EQ(constVal[7u].type(), Json::nullValue); + EXPECT_FALSE(constVal.isMember("key")); + EXPECT_EQ(constVal["key"].type(), Json::nullValue); + EXPECT_TRUE(constVal.getMemberNames().empty()); + EXPECT_EQ(constVal.get(1u, "default0"), "default0"); + EXPECT_EQ(constVal.get(std::string("not"), "oh"), "oh"); + EXPECT_EQ(constVal.get("missing", "default2"), "default2"); } val = -7; - CHECK(val.type() == Json::intValue); - CHECK(val.size() == 0); - CHECK(!val.isValidIndex(0)); - CHECK(!val.isMember("key")); + EXPECT_EQ(val.type(), Json::intValue); + EXPECT_EQ(val.size(), 0); + EXPECT_FALSE(val.isValidIndex(0)); + EXPECT_FALSE(val.isMember("key")); val = 42u; - CHECK(val.type() == Json::uintValue); - CHECK(val.size() == 0); - CHECK(!val.isValidIndex(0)); - CHECK(!val.isMember("key")); + EXPECT_EQ(val.type(), Json::uintValue); + EXPECT_EQ(val.size(), 0); + EXPECT_FALSE(val.isValidIndex(0)); + EXPECT_FALSE(val.isMember("key")); val = 3.14159; - CHECK(val.type() == Json::realValue); - CHECK(val.size() == 0); - CHECK(!val.isValidIndex(0)); - CHECK(!val.isMember("key")); + EXPECT_EQ(val.type(), Json::realValue); + EXPECT_EQ(val.size(), 0); + EXPECT_FALSE(val.isValidIndex(0)); + EXPECT_FALSE(val.isMember("key")); val = true; - CHECK(val.type() == Json::booleanValue); - CHECK(val.size() == 0); - CHECK(!val.isValidIndex(0)); - CHECK(!val.isMember("key")); + EXPECT_EQ(val.type(), Json::booleanValue); + EXPECT_EQ(val.size(), 0); + EXPECT_FALSE(val.isValidIndex(0)); + EXPECT_FALSE(val.isMember("key")); val = "string"; - CHECK(val.type() == Json::stringValue); - CHECK(val.size() == 0); - CHECK(!val.isValidIndex(0)); - CHECK(!val.isMember("key")); + EXPECT_EQ(val.type(), Json::stringValue); + EXPECT_EQ(val.size(), 0); + EXPECT_FALSE(val.isValidIndex(0)); + EXPECT_FALSE(val.isMember("key")); val = Json::Value(Json::objectValue); - CHECK(val.type() == Json::objectValue); - CHECK(val.size() == 0); + EXPECT_EQ(val.type(), Json::objectValue); + EXPECT_EQ(val.size(), 0); static Json::StaticString const staticThree("three"); val[staticThree] = 3; val["two"] = 2; - CHECK(val.size() == 2); - CHECK(val.isValidIndex(1)); - CHECK(!val.isValidIndex(2)); - CHECK(val[staticThree] == 3); - CHECK(val.isMember("two")); - CHECK(val.isMember(staticThree)); - CHECK(!val.isMember("key")); + EXPECT_EQ(val.size(), 2); + EXPECT_TRUE(val.isValidIndex(1)); + EXPECT_FALSE(val.isValidIndex(2)); + EXPECT_EQ(val[staticThree], 3); + EXPECT_TRUE(val.isMember("two")); + EXPECT_TRUE(val.isMember(staticThree)); + EXPECT_FALSE(val.isMember("key")); { Json::Value const constVal = val; - CHECK(constVal["two"] == 2); - CHECK(constVal["four"].type() == Json::nullValue); - CHECK(constVal[staticThree] == 3); - CHECK(constVal.isMember("two")); - CHECK(constVal.isMember(staticThree)); - CHECK(!constVal.isMember("key")); - CHECK(val.get(std::string("two"), "backup") == 2); - CHECK(val.get("missing", "default2") == "default2"); + EXPECT_EQ(constVal["two"], 2); + EXPECT_EQ(constVal["four"].type(), Json::nullValue); + EXPECT_EQ(constVal[staticThree], 3); + EXPECT_TRUE(constVal.isMember("two")); + EXPECT_TRUE(constVal.isMember(staticThree)); + EXPECT_FALSE(constVal.isMember("key")); + EXPECT_EQ(val.get(std::string("two"), "backup"), 2); + EXPECT_EQ(val.get("missing", "default2"), "default2"); } val = Json::Value(Json::arrayValue); - CHECK(val.type() == Json::arrayValue); - CHECK(val.size() == 0); + EXPECT_EQ(val.type(), Json::arrayValue); + EXPECT_EQ(val.size(), 0); val[0u] = "zero"; val[1u] = "one"; - CHECK(val.size() == 2); - CHECK(val.isValidIndex(1)); - CHECK(!val.isValidIndex(2)); - CHECK(val[20u].type() == Json::nullValue); - CHECK(!val.isMember("key")); + EXPECT_EQ(val.size(), 2); + EXPECT_TRUE(val.isValidIndex(1)); + EXPECT_FALSE(val.isValidIndex(2)); + EXPECT_EQ(val[20u].type(), Json::nullValue); + EXPECT_FALSE(val.isMember("key")); { Json::Value const constVal = val; - CHECK(constVal[0u] == "zero"); - CHECK(constVal[2u].type() == Json::nullValue); - CHECK(!constVal.isMember("key")); - CHECK(val.get(1u, "default0") == "one"); - CHECK(val.get(3u, "default1") == "default1"); + EXPECT_EQ(constVal[0u], "zero"); + EXPECT_EQ(constVal[2u].type(), Json::nullValue); + EXPECT_FALSE(constVal.isMember("key")); + EXPECT_EQ(val.get(1u, "default0"), "one"); + EXPECT_EQ(val.get(3u, "default1"), "default1"); } } -TEST_CASE("remove members") +TEST(json_value, remove_members) { Json::Value val; - CHECK(val.removeMember(std::string("member")).type() == Json::nullValue); + EXPECT_EQ(val.removeMember(std::string("member")).type(), Json::nullValue); val = Json::Value(Json::objectValue); static Json::StaticString const staticThree("three"); val[staticThree] = 3; val["two"] = 2; - CHECK(val.size() == 2); + EXPECT_EQ(val.size(), 2); - CHECK(val.removeMember(std::string("six")).type() == Json::nullValue); - CHECK(val.size() == 2); + EXPECT_EQ(val.removeMember(std::string("six")).type(), Json::nullValue); + EXPECT_EQ(val.size(), 2); - CHECK(val.removeMember(staticThree) == 3); - CHECK(val.size() == 1); + EXPECT_EQ(val.removeMember(staticThree), 3); + EXPECT_EQ(val.size(), 1); - CHECK(val.removeMember(staticThree).type() == Json::nullValue); - CHECK(val.size() == 1); + EXPECT_EQ(val.removeMember(staticThree).type(), Json::nullValue); + EXPECT_EQ(val.size(), 1); - CHECK(val.removeMember(std::string("two")) == 2); - CHECK(val.size() == 0); + EXPECT_EQ(val.removeMember(std::string("two")), 2); + EXPECT_EQ(val.size(), 0); - CHECK(val.removeMember(std::string("two")).type() == Json::nullValue); - CHECK(val.size() == 0); + EXPECT_EQ(val.removeMember(std::string("two")).type(), Json::nullValue); + EXPECT_EQ(val.size(), 0); } -TEST_CASE("iterator") +TEST(json_value, iterator) { { // Iterating an array. @@ -1215,27 +1212,27 @@ TEST_CASE("iterator") Json::ValueIterator i2 = e; --i2; - // key(), index(), and memberName() on an object iterator. - CHECK(b != e); - CHECK(!(b == e)); - CHECK(i1.key() == 0); - CHECK(i2.key() == 3); - CHECK(i1.index() == 0); - CHECK(i2.index() == 3); - CHECK(std::strcmp(i1.memberName(), "") == 0); - CHECK(std::strcmp(i2.memberName(), "") == 0); + // key(), index(), and memberName() on an array iterator. + EXPECT_TRUE(b != e); + EXPECT_FALSE(b == e); + EXPECT_EQ(i1.key(), 0); + EXPECT_EQ(i2.key(), 3); + EXPECT_EQ(i1.index(), 0); + EXPECT_EQ(i2.index(), 3); + EXPECT_STREQ(i1.memberName(), ""); + EXPECT_STREQ(i2.memberName(), ""); // Pre and post increment and decrement. *i1++ = "0"; - CHECK(*i1 == "one"); + EXPECT_EQ(*i1, "one"); *i1 = "1"; ++i1; *i2-- = "3"; - CHECK(*i2 == "two"); - CHECK(i1 == i2); + EXPECT_EQ(*i2, "two"); + EXPECT_EQ(i1, i2); *i2 = "2"; - CHECK(*i1 == "2"); + EXPECT_EQ(*i1, "2"); } { // Iterating a const object. @@ -1253,38 +1250,38 @@ TEST_CASE("iterator") --i2; // key(), index(), and memberName() on an object iterator. - CHECK(i1 != i2); - CHECK(!(i1 == i2)); - CHECK(i1.key() == "0"); - CHECK(i2.key() == "3"); - CHECK(i1.index() == -1); - CHECK(i2.index() == -1); - CHECK(std::strcmp(i1.memberName(), "0") == 0); - CHECK(std::strcmp(i2.memberName(), "3") == 0); + EXPECT_TRUE(i1 != i2); + EXPECT_FALSE(i1 == i2); + EXPECT_EQ(i1.key(), "0"); + EXPECT_EQ(i2.key(), "3"); + EXPECT_EQ(i1.index(), -1); + EXPECT_EQ(i2.index(), -1); + EXPECT_STREQ(i1.memberName(), "0"); + EXPECT_STREQ(i2.memberName(), "3"); // Pre and post increment and decrement. - CHECK(*i1++ == 0); - CHECK(*i1 == 1); + EXPECT_EQ(*i1++, 0); + EXPECT_EQ(*i1, 1); ++i1; - CHECK(*i2-- == 3); - CHECK(*i2 == 2); - CHECK(i1 == i2); - CHECK(*i1 == 2); + EXPECT_EQ(*i2--, 3); + EXPECT_EQ(*i2, 2); + EXPECT_EQ(i1, i2); + EXPECT_EQ(*i1, 2); } { // Iterating a non-const null object. Json::Value nul{}; - CHECK(nul.begin() == nul.end()); + EXPECT_EQ(nul.begin(), nul.end()); } { // Iterating a const Int. Json::Value const i{-3}; - CHECK(i.begin() == i.end()); + EXPECT_EQ(i.begin(), i.end()); } } -TEST_CASE("nest limits") +TEST(json_value, nest_limits) { Json::Reader r; { @@ -1302,14 +1299,14 @@ TEST_CASE("nest limits") // Within object nest limit auto json{nest(std::min(10u, Json::Reader::nest_limit))}; Json::Value j; - CHECK(r.parse(json, j)); + EXPECT_TRUE(r.parse(json, j)); } { // Exceed object nest limit auto json{nest(Json::Reader::nest_limit + 1)}; Json::Value j; - CHECK(!r.parse(json, j)); + EXPECT_FALSE(r.parse(json, j)); } } @@ -1326,41 +1323,39 @@ TEST_CASE("nest limits") // Exceed array nest limit auto json{nest(Json::Reader::nest_limit + 1)}; Json::Value j; - CHECK(!r.parse(json, j)); + EXPECT_FALSE(r.parse(json, j)); } } -TEST_CASE("memory leak") +TEST(json_value, memory_leak) { // When run with the address sanitizer, this test confirms there is no // memory leak with the scenarios below. { Json::Value a; a[0u] = 1; - CHECK(a.type() == Json::arrayValue); - CHECK(a[0u].type() == Json::intValue); + EXPECT_EQ(a.type(), Json::arrayValue); + EXPECT_EQ(a[0u].type(), Json::intValue); a = std::move(a[0u]); - CHECK(a.type() == Json::intValue); + EXPECT_EQ(a.type(), Json::intValue); } { Json::Value b; Json::Value temp; temp["a"] = "Probably avoids the small string optimization"; temp["b"] = "Also probably avoids the small string optimization"; - CHECK(temp.type() == Json::objectValue); + EXPECT_EQ(temp.type(), Json::objectValue); b.append(temp); - CHECK(temp.type() == Json::objectValue); - CHECK(b.size() == 1); + EXPECT_EQ(temp.type(), Json::objectValue); + EXPECT_EQ(b.size(), 1); b.append(std::move(temp)); - CHECK(b.size() == 2); + EXPECT_EQ(b.size(), 2); // Note that the type() == nullValue check is implementation // specific and not guaranteed to be valid in the future. - CHECK(temp.type() == Json::nullValue); + EXPECT_EQ(temp.type(), Json::nullValue); } } -TEST_SUITE_END(); - } // namespace xrpl diff --git a/src/tests/libxrpl/json/Writer.cpp b/src/tests/libxrpl/json/Writer.cpp index 9637184c95..7016b4322d 100644 --- a/src/tests/libxrpl/json/Writer.cpp +++ b/src/tests/libxrpl/json/Writer.cpp @@ -1,7 +1,7 @@ #include -#include #include +#include #include #include @@ -9,14 +9,14 @@ using namespace xrpl; using namespace Json; -TEST_SUITE_BEGIN("JsonWriter"); - -struct WriterFixture +class WriterFixture : public ::testing::Test { +protected: std::string output; std::unique_ptr writer; - WriterFixture() + void + SetUp() override { writer = std::make_unique(stringOutput(output)); } @@ -31,7 +31,7 @@ struct WriterFixture void expectOutput(std::string const& expected) const { - CHECK(output == expected); + EXPECT_EQ(output, expected); } void @@ -42,20 +42,20 @@ struct WriterFixture } }; -TEST_CASE_FIXTURE(WriterFixture, "trivial") +TEST_F(WriterFixture, trivial) { - CHECK(output.empty()); + EXPECT_TRUE(output.empty()); checkOutputAndReset(""); } -TEST_CASE_FIXTURE(WriterFixture, "near trivial") +TEST_F(WriterFixture, near_trivial) { - CHECK(output.empty()); + EXPECT_TRUE(output.empty()); writer->output(0); checkOutputAndReset("0"); } -TEST_CASE_FIXTURE(WriterFixture, "primitives") +TEST_F(WriterFixture, primitives) { writer->output(true); checkOutputAndReset("true"); @@ -79,7 +79,7 @@ TEST_CASE_FIXTURE(WriterFixture, "primitives") checkOutputAndReset("null"); } -TEST_CASE_FIXTURE(WriterFixture, "empty") +TEST_F(WriterFixture, empty) { writer->startRoot(Writer::array); writer->finish(); @@ -90,7 +90,7 @@ TEST_CASE_FIXTURE(WriterFixture, "empty") checkOutputAndReset("{}"); } -TEST_CASE_FIXTURE(WriterFixture, "escaping") +TEST_F(WriterFixture, escaping) { writer->output("\\"); checkOutputAndReset(R"("\\")"); @@ -108,7 +108,7 @@ TEST_CASE_FIXTURE(WriterFixture, "escaping") checkOutputAndReset(R"("\b\f\n\r\t")"); } -TEST_CASE_FIXTURE(WriterFixture, "array") +TEST_F(WriterFixture, array) { writer->startRoot(Writer::array); writer->append(12); @@ -116,7 +116,7 @@ TEST_CASE_FIXTURE(WriterFixture, "array") checkOutputAndReset("[12]"); } -TEST_CASE_FIXTURE(WriterFixture, "long array") +TEST_F(WriterFixture, long_array) { writer->startRoot(Writer::array); writer->append(12); @@ -126,7 +126,7 @@ TEST_CASE_FIXTURE(WriterFixture, "long array") checkOutputAndReset(R"([12,true,"hello"])"); } -TEST_CASE_FIXTURE(WriterFixture, "embedded array simple") +TEST_F(WriterFixture, embedded_array_simple) { writer->startRoot(Writer::array); writer->startAppend(Writer::array); @@ -135,7 +135,7 @@ TEST_CASE_FIXTURE(WriterFixture, "embedded array simple") checkOutputAndReset("[[]]"); } -TEST_CASE_FIXTURE(WriterFixture, "object") +TEST_F(WriterFixture, object) { writer->startRoot(Writer::object); writer->set("hello", "world"); @@ -143,7 +143,7 @@ TEST_CASE_FIXTURE(WriterFixture, "object") checkOutputAndReset(R"({"hello":"world"})"); } -TEST_CASE_FIXTURE(WriterFixture, "complex object") +TEST_F(WriterFixture, complex_object) { writer->startRoot(Writer::object); writer->set("hello", "world"); @@ -160,7 +160,7 @@ TEST_CASE_FIXTURE(WriterFixture, "complex object") R"({"hello":"world","array":[true,12,[{"goodbye":"cruel world.","subarray":[23.5]}]]})"); } -TEST_CASE_FIXTURE(WriterFixture, "json value") +TEST_F(WriterFixture, json_value) { Json::Value value(Json::objectValue); value["foo"] = 23; @@ -169,5 +169,3 @@ TEST_CASE_FIXTURE(WriterFixture, "json value") writer->finish(); checkOutputAndReset(R"({"hello":{"foo":23}})"); } - -TEST_SUITE_END(); diff --git a/src/tests/libxrpl/json/main.cpp b/src/tests/libxrpl/json/main.cpp index 0a3f254ea8..5142bbe08a 100644 --- a/src/tests/libxrpl/json/main.cpp +++ b/src/tests/libxrpl/json/main.cpp @@ -1,2 +1,8 @@ -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include +#include + +int +main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/tests/libxrpl/net/HTTPClient.cpp b/src/tests/libxrpl/net/HTTPClient.cpp index 5a484c1f56..cfd206edde 100644 --- a/src/tests/libxrpl/net/HTTPClient.cpp +++ b/src/tests/libxrpl/net/HTTPClient.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include @@ -217,7 +217,7 @@ runHTTPTest( } // anonymous namespace -TEST_CASE("HTTPClient case insensitive Content-Length") +TEST(HTTPClient, case_insensitive_content_length) { // Test different cases of Content-Length header std::vector header_cases = { @@ -249,14 +249,14 @@ TEST_CASE("HTTPClient case insensitive Content-Length") result_error); // Verify results - CHECK(test_completed); - CHECK(!result_error); - CHECK(result_status == 200); - CHECK(result_data == test_body); + EXPECT_TRUE(test_completed); + EXPECT_FALSE(result_error); + EXPECT_EQ(result_status, 200); + EXPECT_EQ(result_data, test_body); } } -TEST_CASE("HTTPClient basic HTTP request") +TEST(HTTPClient, basic_http_request) { TestHTTPServer server; std::string test_body = "Test response body"; @@ -271,13 +271,13 @@ TEST_CASE("HTTPClient basic HTTP request") bool test_completed = runHTTPTest( server, "/basic", completed, result_status, result_data, result_error); - CHECK(test_completed); - CHECK(!result_error); - CHECK(result_status == 200); - CHECK(result_data == test_body); + EXPECT_TRUE(test_completed); + EXPECT_FALSE(result_error); + EXPECT_EQ(result_status, 200); + EXPECT_EQ(result_data, test_body); } -TEST_CASE("HTTPClient empty response") +TEST(HTTPClient, empty_response) { TestHTTPServer server; server.setResponseBody(""); // Empty body @@ -291,13 +291,13 @@ TEST_CASE("HTTPClient empty response") bool test_completed = runHTTPTest( server, "/empty", completed, result_status, result_data, result_error); - CHECK(test_completed); - CHECK(!result_error); - CHECK(result_status == 200); - CHECK(result_data.empty()); + EXPECT_TRUE(test_completed); + EXPECT_FALSE(result_error); + EXPECT_EQ(result_status, 200); + EXPECT_TRUE(result_data.empty()); } -TEST_CASE("HTTPClient different status codes") +TEST(HTTPClient, different_status_codes) { std::vector status_codes = {200, 404, 500}; @@ -320,8 +320,8 @@ TEST_CASE("HTTPClient different status codes") result_data, result_error); - CHECK(test_completed); - CHECK(!result_error); - CHECK(result_status == static_cast(status)); + EXPECT_TRUE(test_completed); + EXPECT_FALSE(result_error); + EXPECT_EQ(result_status, static_cast(status)); } } diff --git a/src/tests/libxrpl/net/main.cpp b/src/tests/libxrpl/net/main.cpp index 0a3f254ea8..5142bbe08a 100644 --- a/src/tests/libxrpl/net/main.cpp +++ b/src/tests/libxrpl/net/main.cpp @@ -1,2 +1,8 @@ -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include +#include + +int +main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 96d17b7f664e593fb8e7c10dfa65a3d655a1011d Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:18:14 +0000 Subject: [PATCH 076/105] ci: Add sanitizers to CI builds (#5996) This change adds support for sanitizer build options in CI builds workflow. Currently `asan+ubsan` is enabled, while `tsan+ubsan` is left disabled as more changes are required. --- .config/cspell.config.yaml | 6 + .github/actions/build-deps/action.yml | 6 + .github/actions/setup-conan/action.yml | 2 +- .github/scripts/strategy-matrix/generate.py | 60 ++++- .../workflows/reusable-build-test-config.yml | 19 +- .github/workflows/reusable-build-test.yml | 1 + BUILD.md | 38 ++- CMakeLists.txt | 9 +- cmake/CompilationEnv.cmake | 54 ++++ cmake/XrplCompiler.cmake | 13 +- cmake/XrplInterface.cmake | 18 +- cmake/XrplSanitizers.cmake | 198 +++++++++++++++ cmake/XrplSanity.cmake | 13 +- cmake/XrplSettings.cmake | 35 +-- cmake/deps/Boost.cmake | 5 +- conan/profiles/ci | 1 + conan/profiles/sanitizers | 59 +++++ docs/build/sanitizers.md | 207 +++++++++++++++ sanitizers/suppressions/asan.supp | 29 +++ sanitizers/suppressions/lsan.supp | 16 ++ .../suppressions/sanitizer-ignorelist.txt | 29 +++ sanitizers/suppressions/tsan.supp | 102 ++++++++ sanitizers/suppressions/ubsan.supp | 237 ++++++++++++++++++ src/libxrpl/ledger/View.cpp | 10 +- src/libxrpl/protocol/BuildInfo.cpp | 10 +- 25 files changed, 1076 insertions(+), 101 deletions(-) create mode 100644 cmake/CompilationEnv.cmake create mode 100644 cmake/XrplSanitizers.cmake create mode 100644 conan/profiles/ci create mode 100644 conan/profiles/sanitizers create mode 100644 docs/build/sanitizers.md create mode 100644 sanitizers/suppressions/asan.supp create mode 100644 sanitizers/suppressions/lsan.supp create mode 100644 sanitizers/suppressions/sanitizer-ignorelist.txt create mode 100644 sanitizers/suppressions/tsan.supp create mode 100644 sanitizers/suppressions/ubsan.supp diff --git a/.config/cspell.config.yaml b/.config/cspell.config.yaml index 3bd295c14b..73b0417d79 100644 --- a/.config/cspell.config.yaml +++ b/.config/cspell.config.yaml @@ -28,6 +28,7 @@ ignoreRegExpList: - /[\['"`]-[DWw][a-zA-Z0-9_-]+['"`\]]/g # compile flags suggestWords: - xprl->xrpl + - xprld->xrpld - unsynched->unsynced - synched->synced - synch->sync @@ -61,6 +62,7 @@ words: - compr - conanfile - conanrun + - confs - connectability - coro - coros @@ -90,6 +92,7 @@ words: - finalizers - firewalled - fmtdur + - fsanitize - funclets - gcov - gcovr @@ -126,6 +129,7 @@ words: - lseq - lsmf - ltype + - mcmodel - MEMORYSTATUSEX - Merkle - Metafuncton @@ -235,6 +239,8 @@ words: - txn - txns - txs + - UBSAN + - ubsan - umant - unacquired - unambiguity diff --git a/.github/actions/build-deps/action.yml b/.github/actions/build-deps/action.yml index d1fb980dac..9d52be1998 100644 --- a/.github/actions/build-deps/action.yml +++ b/.github/actions/build-deps/action.yml @@ -18,6 +18,10 @@ inputs: description: "The logging verbosity." required: false default: "verbose" + sanitizers: + description: "The sanitizers to enable." + required: false + default: "" runs: using: composite @@ -29,9 +33,11 @@ runs: BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }} BUILD_TYPE: ${{ inputs.build_type }} LOG_VERBOSITY: ${{ inputs.log_verbosity }} + SANITIZERS: ${{ inputs.sanitizers }} run: | echo 'Installing dependencies.' conan install \ + --profile ci \ --build="${BUILD_OPTION}" \ --options:host='&:tests=True' \ --options:host='&:xrpld=True' \ diff --git a/.github/actions/setup-conan/action.yml b/.github/actions/setup-conan/action.yml index 1184cfd3d9..dedf53f109 100644 --- a/.github/actions/setup-conan/action.yml +++ b/.github/actions/setup-conan/action.yml @@ -28,7 +28,7 @@ runs: shell: bash run: | echo 'Installing profile.' - conan config install conan/profiles/default -tf $(conan config home)/profiles/ + conan config install conan/profiles/ -tf $(conan config home)/profiles/ echo 'Conan profile:' conan profile show diff --git a/.github/scripts/strategy-matrix/generate.py b/.github/scripts/strategy-matrix/generate.py index c3d2da1f9f..bf5bf5d3ba 100755 --- a/.github/scripts/strategy-matrix/generate.py +++ b/.github/scripts/strategy-matrix/generate.py @@ -229,7 +229,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list: if (n := os["compiler_version"]) != "": config_name += f"-{n}" config_name += ( - f"-{architecture['platform'][architecture['platform'].find('/') + 1 :]}" + f"-{architecture['platform'][architecture['platform'].find('/')+1:]}" ) config_name += f"-{build_type.lower()}" if "-Dcoverage=ON" in cmake_args: @@ -240,17 +240,53 @@ def generate_strategy_matrix(all: bool, config: Config) -> list: # Add the configuration to the list, with the most unique fields first, # so that they are easier to identify in the GitHub Actions UI, as long # names get truncated. - configurations.append( - { - "config_name": config_name, - "cmake_args": cmake_args, - "cmake_target": cmake_target, - "build_only": build_only, - "build_type": build_type, - "os": os, - "architecture": architecture, - } - ) + # Add Address and Thread (both coupled with UB) sanitizers for specific bookworm distros. + # GCC-Asan rippled-embedded tests are failing because of https://github.com/google/sanitizers/issues/856 + if ( + os["distro_version"] == "bookworm" + and f"{os['compiler_name']}-{os['compiler_version']}" == "clang-20" + ): + # Add ASAN + UBSAN configuration. + configurations.append( + { + "config_name": config_name + "-asan-ubsan", + "cmake_args": cmake_args, + "cmake_target": cmake_target, + "build_only": build_only, + "build_type": build_type, + "os": os, + "architecture": architecture, + "sanitizers": "address,undefinedbehavior", + } + ) + # TSAN is deactivated due to seg faults with latest compilers. + activate_tsan = False + if activate_tsan: + configurations.append( + { + "config_name": config_name + "-tsan-ubsan", + "cmake_args": cmake_args, + "cmake_target": cmake_target, + "build_only": build_only, + "build_type": build_type, + "os": os, + "architecture": architecture, + "sanitizers": "thread,undefinedbehavior", + } + ) + else: + configurations.append( + { + "config_name": config_name, + "cmake_args": cmake_args, + "cmake_target": cmake_target, + "build_only": build_only, + "build_type": build_type, + "os": os, + "architecture": architecture, + "sanitizers": "", + } + ) return configurations diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index bc0717e1a5..b8c82aa94d 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -51,6 +51,12 @@ on: type: number default: 2 + sanitizers: + description: "The sanitizers to enable." + required: false + type: string + default: "" + secrets: CODECOV_TOKEN: description: "The Codecov token to use for uploading coverage reports." @@ -91,6 +97,7 @@ jobs: # Determine if coverage and voidstar should be enabled. COVERAGE_ENABLED: ${{ contains(inputs.cmake_args, '-Dcoverage=ON') }} VOIDSTAR_ENABLED: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }} + SANITIZERS_ENABLED: ${{ inputs.sanitizers != '' }} steps: - name: Cleanup workspace (macOS and Windows) if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }} @@ -128,11 +135,13 @@ jobs: # Set the verbosity to "quiet" for Windows to avoid an excessive # amount of logs. For other OSes, the "verbose" logs are more useful. log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }} + sanitizers: ${{ inputs.sanitizers }} - name: Configure CMake working-directory: ${{ env.BUILD_DIR }} env: BUILD_TYPE: ${{ inputs.build_type }} + SANITIZERS: ${{ inputs.sanitizers }} CMAKE_ARGS: ${{ inputs.cmake_args }} run: | cmake \ @@ -174,7 +183,7 @@ jobs: if-no-files-found: error - name: Check linking (Linux) - if: ${{ runner.os == 'Linux' }} + if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }} working-directory: ${{ env.BUILD_DIR }} run: | ldd ./xrpld @@ -191,6 +200,14 @@ jobs: run: | ./xrpld --version | grep libvoidstar + - name: Set sanitizer options + if: ${{ !inputs.build_only && env.SANITIZERS_ENABLED == 'true' }} + run: | + echo "ASAN_OPTIONS=print_stacktrace=1:detect_container_overflow=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp" >> ${GITHUB_ENV} + echo "TSAN_OPTIONS=second_deadlock_stack=1:halt_on_error=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV} + echo "UBSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV} + echo "LSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV} + - name: Run the separate tests if: ${{ !inputs.build_only }} working-directory: ${{ env.BUILD_DIR }} diff --git a/.github/workflows/reusable-build-test.yml b/.github/workflows/reusable-build-test.yml index 2b4d38da61..0086cbbfb5 100644 --- a/.github/workflows/reusable-build-test.yml +++ b/.github/workflows/reusable-build-test.yml @@ -57,5 +57,6 @@ jobs: runs_on: ${{ toJSON(matrix.architecture.runner) }} image: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{4}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version, matrix.os.image_sha) || '' }} config_name: ${{ matrix.config_name }} + sanitizers: ${{ matrix.sanitizers }} secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/BUILD.md b/BUILD.md index 2d1ac9b134..b239b10be6 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,5 +1,5 @@ -| :warning: **WARNING** :warning: -|---| +| :warning: **WARNING** :warning: | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | These instructions assume you have a C++ development environment ready with Git, Python, Conan, CMake, and a C++ compiler. For help setting one up on Linux, macOS, or Windows, [see this guide](./docs/build/environment.md). | > These instructions also assume a basic familiarity with Conan and CMake. @@ -523,18 +523,32 @@ stored inside the build directory, as either of: - file named `coverage.`_extension_, with a suitable extension for the report format, or - directory named `coverage`, with the `index.html` and other files inside, for the `html-details` or `html-nested` report formats. +## Sanitizers + +To build dependencies and xrpld with sanitizer instrumentation, set the +`SANITIZERS` environment variable (only once before running conan and cmake) and use the `sanitizers` profile in conan: + +```bash +export SANITIZERS=address,undefinedbehavior + +conan install .. --output-folder . --profile:all sanitizers --build missing --settings build_type=Debug + +cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -Dxrpld=ON -Dtests=ON .. +``` + +See [Sanitizers docs](./docs/build/sanitizers.md) for more details. + ## Options -| Option | Default Value | Description | -| ---------- | ------------- | ------------------------------------------------------------------ | -| `assert` | OFF | Enable assertions. | -| `coverage` | OFF | Prepare the coverage report. | -| `san` | N/A | Enable a sanitizer with Clang. Choices are `thread` and `address`. | -| `tests` | OFF | Build tests. | -| `unity` | OFF | Configure a unity build. | -| `xrpld` | OFF | Build the xrpld application, and not just the libxrpl library. | -| `werr` | OFF | Treat compilation warnings as errors | -| `wextra` | OFF | Enable additional compilation warnings | +| Option | Default Value | Description | +| ---------- | ------------- | -------------------------------------------------------------- | +| `assert` | OFF | Enable assertions. | +| `coverage` | OFF | Prepare the coverage report. | +| `tests` | OFF | Build tests. | +| `unity` | OFF | Configure a unity build. | +| `xrpld` | OFF | Build the xrpld application, and not just the libxrpl library. | +| `werr` | OFF | Treat compilation warnings as errors | +| `wextra` | OFF | Enable additional compilation warnings | [Unity builds][5] may be faster for the first build (at the cost of much more memory) since they concatenate sources into fewer diff --git a/CMakeLists.txt b/CMakeLists.txt index 26fc310d39..ee0484e79d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,14 +16,16 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") +include(CompilationEnv) + +if(is_gcc) # GCC-specific fixes add_compile_options(-Wno-unknown-pragmas -Wno-subobject-linkage) # -Wno-subobject-linkage can be removed when we upgrade GCC version to at least 13.3 -elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") +elseif(is_clang) # Clang-specific fixes add_compile_options(-Wno-unknown-warning-option) # Ignore unknown warning options -elseif(MSVC) +elseif(is_msvc) # MSVC-specific fixes add_compile_options(/wd4068) # Ignore unknown pragmas endif() @@ -77,6 +79,7 @@ if (packages_only) return () endif () include(XrplCompiler) +include(XrplSanitizers) include(XrplInterface) option(only_docs "Include only the docs target?" FALSE) diff --git a/cmake/CompilationEnv.cmake b/cmake/CompilationEnv.cmake new file mode 100644 index 0000000000..345e4cdd62 --- /dev/null +++ b/cmake/CompilationEnv.cmake @@ -0,0 +1,54 @@ + # Shared detection of compiler, operating system, and architecture. + # + # This module centralizes environment detection so that other + # CMake modules can use the same variables instead of repeating + # checks on CMAKE_* and built-in platform variables. + +# Only run once per configure step. +include_guard(GLOBAL) + +# -------------------------------------------------------------------- +# Compiler detection (C++) +# -------------------------------------------------------------------- +set(is_clang FALSE) +set(is_gcc FALSE) +set(is_msvc FALSE) + +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # Clang or AppleClang + set(is_clang TRUE) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(is_gcc TRUE) +elseif(MSVC) + set(is_msvc TRUE) +else() + message(FATAL_ERROR "Unsupported C++ compiler: ${CMAKE_CXX_COMPILER_ID}") +endif() + + +# -------------------------------------------------------------------- +# Operating system detection +# -------------------------------------------------------------------- +set(is_linux FALSE) +set(is_windows FALSE) +set(is_macos FALSE) + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(is_linux TRUE) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(is_windows TRUE) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(is_macos TRUE) +endif() + +# -------------------------------------------------------------------- +# Architecture +# -------------------------------------------------------------------- +set(is_amd64 FALSE) +set(is_arm64 FALSE) +if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") + set(is_amd64 TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") + set(is_arm64 TRUE) +else() + message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}") +endif() diff --git a/cmake/XrplCompiler.cmake b/cmake/XrplCompiler.cmake index 0777bf948c..a7c5ff0423 100644 --- a/cmake/XrplCompiler.cmake +++ b/cmake/XrplCompiler.cmake @@ -2,16 +2,23 @@ setup project-wide compiler settings #]===================================================================] +include(CompilationEnv) + #[=========================================================[ TODO some/most of these common settings belong in a toolchain file, especially the ABI-impacting ones #]=========================================================] add_library (common INTERFACE) add_library (Xrpl::common ALIAS common) +include(XrplSanitizers) # add a single global dependency on this interface lib link_libraries (Xrpl::common) +# Respect CMAKE_POSITION_INDEPENDENT_CODE setting (may be set by Conan toolchain) +if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() set_target_properties (common - PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON) + PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE}) set(CMAKE_CXX_EXTENSIONS OFF) target_compile_definitions (common INTERFACE @@ -116,8 +123,8 @@ else () # link to static libc/c++ iff: # * static option set and # * NOT APPLE (AppleClang does not support static libc/c++) and - # * NOT san (sanitizers typically don't work with static libc/c++) - $<$,$>,$>>: + # * NOT SANITIZERS (sanitizers typically don't work with static libc/c++) + $<$,$>,$>>: -static-libstdc++ -static-libgcc >) diff --git a/cmake/XrplInterface.cmake b/cmake/XrplInterface.cmake index 9847f39fba..6e0203c099 100644 --- a/cmake/XrplInterface.cmake +++ b/cmake/XrplInterface.cmake @@ -2,6 +2,8 @@ xrpld compile options/settings via an interface library #]===================================================================] +include(CompilationEnv) + add_library (opts INTERFACE) add_library (Xrpl::opts ALIAS opts) target_compile_definitions (opts @@ -42,22 +44,6 @@ if(jemalloc) target_link_libraries(opts INTERFACE jemalloc::jemalloc) endif () -if (san) - target_compile_options (opts - INTERFACE - # sanitizers recommend minimum of -O1 for reasonable performance - $<$:-O1> - ${SAN_FLAG} - -fno-omit-frame-pointer) - target_compile_definitions (opts - INTERFACE - $<$:SANITIZER=ASAN> - $<$:SANITIZER=TSAN> - $<$:SANITIZER=MSAN> - $<$:SANITIZER=UBSAN>) - target_link_libraries (opts INTERFACE ${SAN_FLAG} ${SAN_LIB}) -endif () - #[===================================================================[ xrpld transitive library deps via an interface library #]===================================================================] diff --git a/cmake/XrplSanitizers.cmake b/cmake/XrplSanitizers.cmake new file mode 100644 index 0000000000..050a5ef6f0 --- /dev/null +++ b/cmake/XrplSanitizers.cmake @@ -0,0 +1,198 @@ +#[===================================================================[ + Configure sanitizers based on environment variables. + + This module reads the following environment variables: + - SANITIZERS: The sanitizers to enable. Possible values: + - "address" + - "address,undefinedbehavior" + - "thread" + - "thread,undefinedbehavior" + - "undefinedbehavior" + + The compiler type and platform are detected in CompilationEnv.cmake. + The sanitizer compile options are applied to the 'common' interface library + which is linked to all targets in the project. + + Internal flag variables set by this module: + + - SANITIZER_TYPES: List of sanitizer types to enable (e.g., "address", + "thread", "undefined"). And two more flags for undefined behavior sanitizer (e.g., "float-divide-by-zero", "unsigned-integer-overflow"). + This list is joined with commas and passed to -fsanitize=. + + - SANITIZERS_COMPILE_FLAGS: Compiler flags for sanitizer instrumentation. + Includes: + * -fno-omit-frame-pointer: Preserves frame pointers for stack traces + * -O1: Minimum optimization for reasonable performance + * -fsanitize=: Enables sanitizer instrumentation + * -fsanitize-ignorelist=: (Clang only) Compile-time ignorelist + * -mcmodel=large/medium: (GCC only) Code model for large binaries + * -Wno-stringop-overflow: (GCC only) Suppresses false positive warnings + * -Wno-tsan: (For GCC TSAN combination only) Suppresses atomic_thread_fence warnings + + - SANITIZERS_LINK_FLAGS: Linker flags for sanitizer runtime libraries. + Includes: + * -fsanitize=: Links sanitizer runtime libraries + * -mcmodel=large/medium: (GCC only) Matches compile-time code model + + - SANITIZERS_RELOCATION_FLAGS: (GCC only) Code model flags for linking. + Used to handle large instrumented binaries on x86_64: + * -mcmodel=large: For AddressSanitizer (prevents relocation errors) + * -mcmodel=medium: For ThreadSanitizer (large model is incompatible) +#]===================================================================] + +include(CompilationEnv) + +# Read environment variable +set(SANITIZERS $ENV{SANITIZERS}) + +# Set SANITIZERS_ENABLED flag for use in other modules +if(SANITIZERS MATCHES "address|thread|undefinedbehavior") + set(SANITIZERS_ENABLED TRUE) +else() + set(SANITIZERS_ENABLED FALSE) + return() +endif() + +# Sanitizers are not supported on Windows/MSVC +if(is_msvc) + message(FATAL_ERROR "Sanitizers are not supported on Windows/MSVC. " + "Please unset the SANITIZERS environment variable.") +endif() + +message(STATUS "Configuring sanitizers: ${SANITIZERS}") + +# Parse SANITIZERS value to determine which sanitizers to enable +set(enable_asan FALSE) +set(enable_tsan FALSE) +set(enable_ubsan FALSE) + +# Normalize SANITIZERS into a list +set(san_list "${SANITIZERS}") +string(REPLACE "," ";" san_list "${san_list}") +separate_arguments(san_list) + +foreach(san IN LISTS san_list) + if(san STREQUAL "address") + set(enable_asan TRUE) + elseif(san STREQUAL "thread") + set(enable_tsan TRUE) + elseif(san STREQUAL "undefinedbehavior") + set(enable_ubsan TRUE) + else() + message(FATAL_ERROR "Unsupported sanitizer type: ${san}" + "Supported: address, thread, undefinedbehavior and their combinations.") + endif() +endforeach() + +# Validate sanitizer compatibility +if(enable_asan AND enable_tsan) + message(FATAL_ERROR "AddressSanitizer and ThreadSanitizer are incompatible and cannot be enabled simultaneously. " + "Use 'address' or 'thread', optionally with 'undefinedbehavior'.") +endif() + +# Frame pointer is required for meaningful stack traces. Sanitizers recommend minimum of -O1 for reasonable performance +set(SANITIZERS_COMPILE_FLAGS "-fno-omit-frame-pointer" "-O1") + +# Build the sanitizer flags list +set(SANITIZER_TYPES) + +if(enable_asan) + list(APPEND SANITIZER_TYPES "address") +elseif(enable_tsan) + list(APPEND SANITIZER_TYPES "thread") +endif() + +if(enable_ubsan) + # UB sanitizer flags + list(APPEND SANITIZER_TYPES "undefined" "float-divide-by-zero") + if(is_clang) + # Clang supports additional UB checks. More info here https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html + list(APPEND SANITIZER_TYPES "unsigned-integer-overflow") + endif() +endif() + +# Configure code model for GCC on amd64 +# Use large code model for ASAN to avoid relocation errors +# Use medium code model for TSAN (large is not compatible with TSAN) +set(SANITIZERS_RELOCATION_FLAGS) + +# Compiler-specific configuration +if(is_gcc) + # Disable mold, gold and lld linkers for GCC with sanitizers + # Use default linker (bfd/ld) which is more lenient with mixed code models + # This is needed since the size of instrumented binary exceeds the limits set by mold, lld and gold linkers + set(use_mold OFF CACHE BOOL "Use mold linker" FORCE) + set(use_gold OFF CACHE BOOL "Use gold linker" FORCE) + set(use_lld OFF CACHE BOOL "Use lld linker" FORCE) + message(STATUS " Disabled mold, gold, and lld linkers for GCC with sanitizers") + + # Suppress false positive warnings in GCC with stringop-overflow + list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-stringop-overflow") + + if(is_amd64 AND enable_asan) + message(STATUS " Using large code model (-mcmodel=large)") + list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=large") + list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=large") + elseif(enable_tsan) + # GCC doesn't support atomic_thread_fence with tsan. Suppress warnings. + list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-tsan") + message(STATUS " Using medium code model (-mcmodel=medium)") + list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=medium") + list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=medium") + endif() + + # Join sanitizer flags with commas for -fsanitize option + list(JOIN SANITIZER_TYPES "," SANITIZER_TYPES_STR) + + # Add sanitizer to compile and link flags + list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}") + set(SANITIZERS_LINK_FLAGS "${SANITIZERS_RELOCATION_FLAGS}" "-fsanitize=${SANITIZER_TYPES_STR}") + +elseif(is_clang) + # Add ignorelist for Clang (GCC doesn't support this) + # Use CMAKE_SOURCE_DIR to get the path to the ignorelist + set(IGNORELIST_PATH "${CMAKE_SOURCE_DIR}/sanitizers/suppressions/sanitizer-ignorelist.txt") + if(NOT EXISTS "${IGNORELIST_PATH}") + message(FATAL_ERROR "Sanitizer ignorelist not found: ${IGNORELIST_PATH}") + endif() + + list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize-ignorelist=${IGNORELIST_PATH}") + message(STATUS " Using sanitizer ignorelist: ${IGNORELIST_PATH}") + + # Join sanitizer flags with commas for -fsanitize option + list(JOIN SANITIZER_TYPES "," SANITIZER_TYPES_STR) + + # Add sanitizer to compile and link flags + list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}") + set(SANITIZERS_LINK_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}") +endif() + +message(STATUS " Compile flags: ${SANITIZERS_COMPILE_FLAGS}") +message(STATUS " Link flags: ${SANITIZERS_LINK_FLAGS}") + +# Apply the sanitizer flags to the 'common' interface library +# This is the same library used by XrplCompiler.cmake +target_compile_options(common INTERFACE + $<$:${SANITIZERS_COMPILE_FLAGS}> + $<$:${SANITIZERS_COMPILE_FLAGS}> +) + +# Apply linker flags +target_link_options(common INTERFACE ${SANITIZERS_LINK_FLAGS}) + +# Define SANITIZERS macro for BuildInfo.cpp +set(sanitizers_list) +if(enable_asan) + list(APPEND sanitizers_list "ASAN") +endif() +if(enable_tsan) + list(APPEND sanitizers_list "TSAN") +endif() +if(enable_ubsan) + list(APPEND sanitizers_list "UBSAN") +endif() + +if(sanitizers_list) + list(JOIN sanitizers_list "." sanitizers_str) + target_compile_definitions(common INTERFACE SANITIZERS=${sanitizers_str}) +endif() diff --git a/cmake/XrplSanity.cmake b/cmake/XrplSanity.cmake index db983da73d..7464ca396c 100644 --- a/cmake/XrplSanity.cmake +++ b/cmake/XrplSanity.cmake @@ -2,6 +2,8 @@ sanity checks #]===================================================================] +include(CompilationEnv) + get_property(is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) set (CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) @@ -16,14 +18,12 @@ if (NOT is_multiconfig) endif () endif () -if ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") # both Clang and AppleClang - set (is_clang TRUE) +if (is_clang) # both Clang and AppleClang if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0) message (FATAL_ERROR "This project requires clang 16 or later") endif () -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set (is_gcc TRUE) +elseif (is_gcc) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0) message (FATAL_ERROR "This project requires GCC 12 or later") endif () @@ -40,11 +40,6 @@ if (MSVC AND CMAKE_GENERATOR_PLATFORM STREQUAL "Win32") message (FATAL_ERROR "Visual Studio 32-bit build is not supported.") endif () -if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) - message (FATAL_ERROR "Xrpld requires a 64 bit target architecture.\n" - "The most likely cause of this warning is trying to build xrpld with a 32-bit OS.") -endif () - if (APPLE AND NOT HOMEBREW) find_program (HOMEBREW brew) endif () diff --git a/cmake/XrplSettings.cmake b/cmake/XrplSettings.cmake index c3f013c575..647e95837d 100644 --- a/cmake/XrplSettings.cmake +++ b/cmake/XrplSettings.cmake @@ -2,11 +2,7 @@ declare options and variables #]===================================================================] -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set (is_linux TRUE) -else() - set(is_linux FALSE) -endif() +include(CompilationEnv) if("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true") set(is_ci TRUE) @@ -62,7 +58,7 @@ else() set(wextra OFF CACHE BOOL "gcc/clang only" FORCE) endif() -if(is_linux) +if(is_linux AND NOT SANITIZER) option(BUILD_SHARED_LIBS "build shared xrpl libraries" OFF) option(static "link protobuf, openssl, libc++, and boost statically" ON) option(perf "Enables flags that assist with perf recording" OFF) @@ -107,33 +103,6 @@ option(local_protobuf option(local_grpc "Force a local build of gRPC instead of looking for an installed version." OFF) -# this one is a string and therefore can't be an option -set(san "" CACHE STRING "On gcc & clang, add sanitizer instrumentation") -set_property(CACHE san PROPERTY STRINGS ";undefined;memory;address;thread") -if(san) - string(TOLOWER ${san} san) - set(SAN_FLAG "-fsanitize=${san}") - set(SAN_LIB "") - if(is_gcc) - if(san STREQUAL "address") - set(SAN_LIB "asan") - elseif(san STREQUAL "thread") - set(SAN_LIB "tsan") - elseif(san STREQUAL "memory") - set(SAN_LIB "msan") - elseif(san STREQUAL "undefined") - set(SAN_LIB "ubsan") - endif() - endif() - set(_saved_CRL ${CMAKE_REQUIRED_LIBRARIES}) - set(CMAKE_REQUIRED_LIBRARIES "${SAN_FLAG};${SAN_LIB}") - check_cxx_compiler_flag(${SAN_FLAG} COMPILER_SUPPORTS_SAN) - set(CMAKE_REQUIRED_LIBRARIES ${_saved_CRL}) - if(NOT COMPILER_SUPPORTS_SAN) - message(FATAL_ERROR "${san} sanitizer does not seem to be supported by your compiler") - endif() -endif() - # the remaining options are obscure and rarely used option(beast_no_unit_test_inline "Prevents unit test definitions from being inserted into global table" diff --git a/cmake/deps/Boost.cmake b/cmake/deps/Boost.cmake index 19263e0ac9..b73698efd8 100644 --- a/cmake/deps/Boost.cmake +++ b/cmake/deps/Boost.cmake @@ -1,3 +1,6 @@ +include(CompilationEnv) +include(XrplSanitizers) + find_package(Boost REQUIRED COMPONENTS chrono @@ -32,7 +35,7 @@ target_link_libraries(xrpl_boost if(Boost_COMPILER) target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking) endif() -if(san AND is_clang) +if(SANITIZERS_ENABLED AND is_clang) # TODO: gcc does not support -fsanitize-blacklist...can we do something else # for gcc ? if(NOT Boost_INCLUDE_DIRS AND TARGET Boost::headers) diff --git a/conan/profiles/ci b/conan/profiles/ci new file mode 100644 index 0000000000..c4c0898ad5 --- /dev/null +++ b/conan/profiles/ci @@ -0,0 +1 @@ + include(sanitizers) diff --git a/conan/profiles/sanitizers b/conan/profiles/sanitizers new file mode 100644 index 0000000000..d7a622359a --- /dev/null +++ b/conan/profiles/sanitizers @@ -0,0 +1,59 @@ +include(default) +{% set compiler, version, compiler_exe = detect_api.detect_default_compiler() %} +{% set sanitizers = os.getenv("SANITIZERS") %} + +[conf] +{% if sanitizers %} + {% if compiler == "gcc" %} + {% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %} + {% set sanitizer_list = [] %} + {% set model_code = "" %} + {% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1", "-Wno-stringop-overflow"] %} + + {% if "address" in sanitizers %} + {% set _ = sanitizer_list.append("address") %} + {% set model_code = "-mcmodel=large" %} + {% elif "thread" in sanitizers %} + {% set _ = sanitizer_list.append("thread") %} + {% set model_code = "-mcmodel=medium" %} + {% set _ = extra_cxxflags.append("-Wno-tsan") %} + {% endif %} + + {% if "undefinedbehavior" in sanitizers %} + {% set _ = sanitizer_list.append("undefined") %} + {% set _ = sanitizer_list.append("float-divide-by-zero") %} + {% endif %} + + {% set sanitizer_flags = "-fsanitize=" ~ ",".join(sanitizer_list) ~ " " ~ model_code %} + + tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}'] + tools.build:sharedlinkflags+=['{{sanitizer_flags}}'] + tools.build:exelinkflags+=['{{sanitizer_flags}}'] + {% endif %} + {% elif compiler == "apple-clang" or compiler == "clang" %} + {% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %} + {% set sanitizer_list = [] %} + {% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1"] %} + + {% if "address" in sanitizers %} + {% set _ = sanitizer_list.append("address") %} + {% elif "thread" in sanitizers %} + {% set _ = sanitizer_list.append("thread") %} + {% endif %} + + {% if "undefinedbehavior" in sanitizers %} + {% set _ = sanitizer_list.append("undefined") %} + {% set _ = sanitizer_list.append("float-divide-by-zero") %} + {% set _ = sanitizer_list.append("unsigned-integer-overflow") %} + {% endif %} + + {% set sanitizer_flags = "-fsanitize=" ~ ",".join(sanitizer_list) %} + + tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}'] + tools.build:sharedlinkflags+=['{{sanitizer_flags}}'] + tools.build:exelinkflags+=['{{sanitizer_flags}}'] + {% endif %} + {% endif %} +{% endif %} + +tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"] diff --git a/docs/build/sanitizers.md b/docs/build/sanitizers.md new file mode 100644 index 0000000000..3f9809ae98 --- /dev/null +++ b/docs/build/sanitizers.md @@ -0,0 +1,207 @@ +# Sanitizer Configuration for Rippled + +This document explains how to properly configure and run sanitizers (AddressSanitizer, undefinedbehaviorSanitizer, ThreadSanitizer) with the xrpld project. +Corresponding suppression files are located in the `sanitizers/suppressions` directory. + +- [Sanitizer Configuration for Rippled](#sanitizer-configuration-for-rippled) + - [Building with Sanitizers](#building-with-sanitizers) + - [Summary](#summary) + - [Build steps:](#build-steps) + - [Install dependencies](#install-dependencies) + - [Call CMake](#call-cmake) + - [Build](#build) + - [Running Tests with Sanitizers](#running-tests-with-sanitizers) + - [AddressSanitizer (ASAN)](#addresssanitizer-asan) + - [ThreadSanitizer (TSan)](#threadsanitizer-tsan) + - [LeakSanitizer (LSan)](#leaksanitizer-lsan) + - [UndefinedBehaviorSanitizer (UBSan)](#undefinedbehaviorsanitizer-ubsan) + - [Suppression Files](#suppression-files) + - [`asan.supp`](#asansupp) + - [`lsan.supp`](#lsansupp) + - [`ubsan.supp`](#ubsansupp) + - [`tsan.supp`](#tsansupp) + - [`sanitizer-ignorelist.txt`](#sanitizer-ignorelisttxt) + - [Troubleshooting](#troubleshooting) + - ["ASAN is ignoring requested \_\_asan_handle_no_return" warnings](#asan-is-ignoring-requested-__asan_handle_no_return-warnings) + - [Sanitizer Mismatch Errors](#sanitizer-mismatch-errors) + - [References](#references) + +## Building with Sanitizers + +### Summary + +Follow the same instructions as mentioned in [BUILD.md](../../BUILD.md) but with the following changes: + +1. Make sure you have a clean build directory. +2. Set the `SANITIZERS` environment variable before calling conan install and cmake. Only set it once. Make sure both conan and cmake read the same values. + Example: `export SANITIZERS=address,undefinedbehavior` +3. Optionally use `--profile:all sanitizers` with Conan to build dependencies with sanitizer instrumentation. [!NOTE]Building with sanitizer-instrumented dependencies is slower but produces fewer false positives. +4. Set `ASAN_OPTIONS`, `LSAN_OPTIONS`, `UBSAN_OPTIONS` and `TSAN_OPTIONS` environment variables to configure sanitizer behavior when running executables. [More details below](#running-tests-with-sanitizers). + +--- + +### Build steps: + +```bash +cd /path/to/rippled +rm -rf .build +mkdir .build +cd .build +``` + +#### Install dependencies + +The `SANITIZERS` environment variable is used by both Conan and CMake. + +```bash +export SANITIZERS=address,undefinedbehavior +# Standard build (without instrumenting dependencies) +conan install .. --output-folder . --build missing --settings build_type=Debug + +# Or with sanitizer-instrumented dependencies (takes longer but fewer false positives) +conan install .. --output-folder . --profile:all sanitizers --build missing --settings build_type=Debug +``` + +[!CAUTION] +Do not mix Address and Thread sanitizers - they are incompatible. + +Since you already set the `SANITIZERS` environment variable when running Conan, same values will be read for the next part. + +#### Call CMake + +```bash +cmake .. -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Debug \ + -Dtests=ON -Dxrpld=ON +``` + +#### Build + +```bash +cmake --build . --parallel 4 +``` + +## Running Tests with Sanitizers + +### AddressSanitizer (ASAN) + +**IMPORTANT**: ASAN with Boost produces many false positives. Use these options: + +```bash +export ASAN_OPTIONS="print_stacktrace=1:detect_container_overflow=0:suppressions=path/to/asan.supp:halt_on_error=0:log_path=asan.log" +export LSAN_OPTIONS="suppressions=path/to/lsan.supp:halt_on_error=0:log_path=lsan.log" + +# Run tests +./xrpld --unittest --unittest-jobs=5 +``` + +**Why `detect_container_overflow=0`?** + +- Boost intrusive containers (used in `aged_unordered_container`) trigger false positives +- Boost context switching (used in `Workers.cpp`) confuses ASAN's stack tracking +- Since we usually don't build Boost (because we don't want to instrument Boost and detect issues in Boost code) with ASAN but use Boost containers in ASAN instrumented rippled code, it generates false positives. +- Building dependencies with ASAN instrumentation reduces false positives. But we don't want to instrument dependencies like Boost with ASAN because it is slow (to compile as well as run tests) and not necessary. +- See: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow +- More such flags are detailed [here](https://github.com/google/sanitizers/wiki/AddressSanitizerFlags) + +### ThreadSanitizer (TSan) + +```bash +export TSAN_OPTIONS="suppressions=path/to/tsan.supp halt_on_error=0 log_path=tsan.log" + +# Run tests +./xrpld --unittest --unittest-jobs=5 +``` + +More details [here](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual). + +### LeakSanitizer (LSan) + +LSan is automatically enabled with ASAN. To disable it: + +```bash +export ASAN_OPTIONS="detect_leaks=0" +``` + +More details [here](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer). + +### UndefinedBehaviorSanitizer (UBSan) + +```bash +export UBSAN_OPTIONS="suppressions=path/to/ubsan.supp:print_stacktrace=1:halt_on_error=0:log_path=ubsan.log" + +# Run tests +./xrpld --unittest --unittest-jobs=5 +``` + +More details [here](https://clang.llvm.org/docs/undefinedbehaviorSanitizer.html). + +## Suppression Files + +[!NOTE] Attached files contain more details. + +### [`asan.supp`](../../sanitizers/suppressions/asan.supp) + +- **Purpose**: Suppress AddressSanitizer (ASAN) errors only +- **Format**: `interceptor_name:` where pattern matches file names. Supported suppression types are: + - interceptor_name + - interceptor_via_fun + - interceptor_via_lib + - odr_violation +- **More info**: [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) +- **Note**: Cannot suppress stack-buffer-overflow, container-overflow, etc. + +### [`lsan.supp`](../../sanitizers/suppressions/lsan.supp) + +- **Purpose**: Suppress LeakSanitizer (LSan) errors only +- **Format**: `leak:` where pattern matches function/file names +- **More info**: [LeakSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer) + +### [`ubsan.supp`](../../sanitizers/suppressions/ubsan.supp) + +- **Purpose**: Suppress undefinedbehaviorSanitizer errors +- **Format**: `:` (e.g., `unsigned-integer-overflow:protobuf`) +- **Covers**: Intentional overflows in sanitizers/suppressions libraries (protobuf, gRPC, stdlib) +- More info [UBSan suppressions](https://clang.llvm.org/docs/SanitizerSpecialCaseList.html). + +### [`tsan.supp`](../../sanitizers/suppressions/tsan.supp) + +- **Purpose**: Suppress ThreadSanitizer data race warnings +- **Format**: `race:` where pattern matches function/file names +- **More info**: [ThreadSanitizer suppressions](https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions) + +### [`sanitizer-ignorelist.txt`](../../sanitizers/suppressions/sanitizer-ignorelist.txt) + +- **Purpose**: Compile-time ignorelist for all sanitizers +- **Usage**: Passed via `-fsanitize-ignorelist=absolute/path/to/sanitizer-ignorelist.txt` +- **Format**: `:` (e.g., `src:Workers.cpp`) + +## Troubleshooting + +### "ASAN is ignoring requested \_\_asan_handle_no_return" warnings + +These warnings appear when using Boost context switching and are harmless. They indicate potential false positives. + +### Sanitizer Mismatch Errors + +If you see undefined symbols like `___tsan_atomic_load` when building with ASAN: + +**Problem**: Dependencies were built with a different sanitizer than the main project. + +**Solution**: Rebuild everything with the same sanitizer: + +```bash +rm -rf .build +# Then follow the build instructions above +``` + +Then review the log files: `asan.log.*`, `ubsan.log.*`, `tsan.log.*` + +## References + +- [AddressSanitizer Wiki](https://github.com/google/sanitizers/wiki/AddressSanitizer) +- [AddressSanitizer Flags](https://github.com/google/sanitizers/wiki/AddressSanitizerFlags) +- [Container Overflow Detection](https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow) +- [UndefinedBehavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) +- [ThreadSanitizer](https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual) diff --git a/sanitizers/suppressions/asan.supp b/sanitizers/suppressions/asan.supp new file mode 100644 index 0000000000..7ba98766bd --- /dev/null +++ b/sanitizers/suppressions/asan.supp @@ -0,0 +1,29 @@ +# The idea is to empty this file gradually by fixing the underlying issues and removing suppressions. +# +# ASAN_OPTIONS="print_stacktrace=1:detect_container_overflow=0:suppressions=sanitizers/suppressions/asan.supp:halt_on_error=0" +# +# The detect_container_overflow=0 option disables false positives from: +# - Boost intrusive containers (slist_iterator.hpp, hashtable.hpp, aged_unordered_container.h) +# - Boost context/coroutine stack switching (Workers.cpp, thread.h) +# +# See: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow + +# Boost +interceptor_name:boost/asio + +# Leaks in Doctest tests: xrpl.test.* +interceptor_name:src/libxrpl/net/HTTPClient.cpp +interceptor_name:src/libxrpl/net/RegisterSSLCerts.cpp +interceptor_name:src/tests/libxrpl/net/HTTPClient.cpp +interceptor_name:xrpl/net/AutoSocket.h +interceptor_name:xrpl/net/HTTPClient.h +interceptor_name:xrpl/net/HTTPClientSSLContext.h +interceptor_name:xrpl/net/RegisterSSLCerts.h + +# Suppress false positive stack-buffer errors in thread stack allocation +# Related to ASan's __asan_handle_no_return warnings (github.com/google/sanitizers/issues/189) +# These occur during multi-threaded test initialization on macOS +interceptor_name:memcpy +interceptor_name:__bzero +interceptor_name:__asan_memset +interceptor_name:__asan_memcpy diff --git a/sanitizers/suppressions/lsan.supp b/sanitizers/suppressions/lsan.supp new file mode 100644 index 0000000000..a81d7d89fa --- /dev/null +++ b/sanitizers/suppressions/lsan.supp @@ -0,0 +1,16 @@ +# The idea is to empty this file gradually by fixing the underlying issues and removing suppresions. + +# Suppress leaks detected by asan in rippled code. +leak:src/libxrpl/net/HTTPClient.cpp +leak:src/libxrpl/net/RegisterSSLCerts.cpp +leak:src/tests/libxrpl/net/HTTPClient.cpp +leak:xrpl/net/AutoSocket.h +leak:xrpl/net/HTTPClient.h +leak:xrpl/net/HTTPClientSSLContext.h +leak:xrpl/net/RegisterSSLCerts.h +leak:ripple::HTTPClient +leak:ripple::HTTPClientImp + +# Suppress leaks detected by asan in boost code. +leak:boost::asio +leak:boost/asio diff --git a/sanitizers/suppressions/sanitizer-ignorelist.txt b/sanitizers/suppressions/sanitizer-ignorelist.txt new file mode 100644 index 0000000000..5dbead48a2 --- /dev/null +++ b/sanitizers/suppressions/sanitizer-ignorelist.txt @@ -0,0 +1,29 @@ +# We were seeing some false positives and some repeated errors(since these are library files) in following files. +# Clang will skip instrumenting the files added here. +# We should fix the underlying issues(if any) and remove these entries. + +deadlock:libxrpl/beast/utility/beast_Journal.cpp +deadlock:libxrpl/beast/utility/beast_PropertyStream.cpp +deadlock:test/beast/beast_PropertyStream_test.cpp +deadlock:xrpld/core/detail/Workers.cpp +deadlock:xrpld/core/JobQueue.cpp + +race:libxrpl/beast/utility/beast_Journal.cpp +race:libxrpl/beast/utility/beast_PropertyStream.cpp +race:test/beast/beast_PropertyStream_test.cpp +race:xrpld/core/detail/Workers.cpp +race:xrpld/core/JobQueue.cpp + +signal:libxrpl/beast/utility/beast_Journal.cpp +signal:libxrpl/beast/utility/beast_PropertyStream.cpp +signal:test/beast/beast_PropertyStream_test.cpp +signal:xrpld/core/detail/Workers.cpp +signal:xrpld/core/JobQueue.cpp + +src:beast/utility/beast_Journal.cpp +src:beast/utility/beast_PropertyStream.cpp +src:core/detail/Workers.cpp +src:core/JobQueue.cpp +src:libxrpl/beast/utility/beast_Journal.cpp +src:test/beast/beast_PropertyStream_test.cpp +src:src/test/app/Invariants_test.cpp diff --git a/sanitizers/suppressions/tsan.supp b/sanitizers/suppressions/tsan.supp new file mode 100644 index 0000000000..74f3371e68 --- /dev/null +++ b/sanitizers/suppressions/tsan.supp @@ -0,0 +1,102 @@ +# The idea is to empty this file gradually by fixing the underlying issues and removing suppresions. + +# Suppress race in Boost ASIO scheduler detected by GCC-15 +# This is a false positive in Boost's internal pipe() synchronization +race:boost/asio/ +race:boost/context/ +race:boost/asio/executor.hpp +race:boost::asio + +# Suppress tsan related issues in rippled code. +race:src/libxrpl/basics/make_SSLContext.cpp +race:src/libxrpl/basics/Number.cpp +race:src/libxrpl/json/json_value.cpp +race:src/libxrpl/json/to_string.cpp +race:src/libxrpl/ledger/OpenView.cpp +race:src/libxrpl/net/HTTPClient.cpp +race:src/libxrpl/nodestore/backend/NuDBFactory.cpp +race:src/libxrpl/protocol/InnerObjectFormats.cpp +race:src/libxrpl/protocol/STParsedJSON.cpp +race:src/libxrpl/resource/ResourceManager.cpp +race:src/test/app/Flow_test.cpp +race:src/test/app/LedgerReplay_test.cpp +race:src/test/app/NFToken_test.cpp +race:src/test/app/Offer_test.cpp +race:src/test/app/ValidatorSite_test.cpp +race:src/test/consensus/NegativeUNL_test.cpp +race:src/test/jtx/impl/Env.cpp +race:src/test/jtx/impl/JSONRPCClient.cpp +race:src/test/jtx/impl/pay.cpp +race:src/test/jtx/impl/token.cpp +race:src/test/rpc/Book_test.cpp +race:src/xrpld/app/ledger/detail/InboundTransactions.cpp +race:src/xrpld/app/main/Application.cpp +race:src/xrpld/app/main/BasicApp.cpp +race:src/xrpld/app/main/GRPCServer.cpp +race:src/xrpld/app/misc/detail/AmendmentTable.cpp +race:src/xrpld/app/misc/FeeVoteImpl.cpp +race:src/xrpld/app/rdb/detail/Wallet.cpp +race:src/xrpld/overlay/detail/OverlayImpl.cpp +race:src/xrpld/peerfinder/detail/PeerfinderManager.cpp +race:src/xrpld/peerfinder/detail/SourceStrings.cpp +race:src/xrpld/rpc/detail/ServerHandler.cpp +race:xrpl/server/detail/Door.h +race:xrpl/server/detail/Spawn.h +race:xrpl/server/detail/ServerImpl.h +race:xrpl/nodestore/detail/DatabaseNodeImp.h +race:src/libxrpl/beast/utility/beast_Journal.cpp +race:src/test/beast/LexicalCast_test.cpp +race:ripple::ServerHandler + +# More suppressions in external library code. +race:crtstuff.c +race:pipe + +# Deadlock / lock-order-inversion suppressions +# Note: GCC's TSAN may not fully support all deadlock suppression patterns +deadlock:src/libxrpl/beast/utility/beast_Journal.cpp +deadlock:src/libxrpl/beast/utility/beast_PropertyStream.cpp +deadlock:src/test/beast/beast_PropertyStream_test.cpp +deadlock:src/xrpld/core/detail/Workers.cpp +deadlock:src/xrpld/app/misc/detail/Manifest.cpp +deadlock:src/xrpld/app/misc/detail/ValidatorList.cpp +deadlock:src/xrpld/app/misc/detail/ValidatorSite.cpp + +signal:src/libxrpl/beast/utility/beast_Journal.cpp +signal:src/xrpld/core/detail/Workers.cpp +signal:src/xrpld/core/JobQueue.cpp +signal:ripple::Workers::Worker + +# Aggressive suppressing of deadlock tsan errors +deadlock:pthread_create +deadlock:pthread_rwlock_rdlock +deadlock:boost::asio + +# Suppress SEGV crashes in TSAN itself during stringbuf operations +# This appears to be a GCC-15 TSAN instrumentation issue with basic_stringbuf::str() +# Commonly triggered in beast::Journal::ScopedStream destructor +signal:std::__cxx11::basic_stringbuf +signal:basic_stringbuf +signal:basic_ostringstream + +called_from_lib:libclang_rt +race:ostreambuf_iterator +race:basic_ostream + +# Suppress SEGV in Boost ASIO memory allocation with GCC-15 TSAN +signal:boost::asio::aligned_new +signal:boost::asio::detail::memory + +# Suppress SEGV in execute_native_thread_routine +signal:execute_native_thread_routine + +# Suppress data race in Boost Context fiber management +# This is a false positive in Boost's exception state management during fiber context switching +race:__cxxabiv1::manage_exception_state +race:boost::context::fiber::resume +race:boost::asio::detail::spawned_fiber_thread +race:boost::asio::detail::spawned_fiber_thread::suspend_with +race:boost::asio::detail::spawned_fiber_thread::destroy + +# Suppress data race in __tsan_memcpy called from Boost fiber operations +race:__tsan_memcpy diff --git a/sanitizers/suppressions/ubsan.supp b/sanitizers/suppressions/ubsan.supp new file mode 100644 index 0000000000..1504ef685f --- /dev/null +++ b/sanitizers/suppressions/ubsan.supp @@ -0,0 +1,237 @@ +# The idea is to empty this file gradually by fixing the underlying issues and removing suppresions. + +# Suppress UBSan errors in external code by source file path +# This matches any source file under the external/ directory +alignment:external +bool:external +bounds:external +cfi:external +enum:external +float-cast-overflow:external +float-divide-by-zero:external +function:external +implicit-integer-sign-change:external +implicit-signed-integer-truncation::external +implicit-signed-integer-truncation:external +implicit-unsigned-integer-truncation:external +integer-divide-by-zero:external +invalid-builtin-use:external +invalid-objc-cast:external +nonnull-attribute:external +null:external +nullability-arg:external +nullability-assign:external +nullability-return:external +object-size:external +pointer-overflow:external +return:external +returns-nonnull-attribute:external +shift-base:external +shift-exponent:external +signed-integer-overflow:external +undefined:external +unreachable:external +unsigned-integer-overflow:external +vla-bound:external +vptr_check:external +vptr:external + +# Suppress all UBSan errors in Boost libraries +# This matches any files containing "boost" in its path or name +alignment:boost +bool:boost +bounds:boost +cfi:boost +enum:boost +float-cast-overflow:boost +float-divide-by-zero:boost +function:boost +implicit-integer-sign-change:boost +implicit-signed-integer-truncation:boost +implicit-unsigned-integer-truncation:boost +integer-divide-by-zero:boost +invalid-builtin-use:boost +invalid-objc-cast:boost +nonnull-attribute:boost +null:boost +nullability-arg:boost +nullability-assign:boost +nullability-return:boost +object-size:boost +pointer-overflow:boost +return:boost +returns-nonnull-attribute:boost +shift-base:boost +shift-exponent:boost +signed-integer-overflow:boost +undefined:boost +unreachable:boost +unsigned-integer-overflow:boost +vla-bound:boost +vptr_check:boost +vptr:boost + +# Google protobuf +undefined:protobuf + +# Suppress UBSan errors in rippled code by source file path +undefined:src/libxrpl/basics/base64.cpp +undefined:src/libxrpl/basics/Number.cpp +undefined:src/libxrpl/beast/utility/beast_Journal.cpp +undefined:src/libxrpl/crypto/RFC1751.cpp +undefined:src/libxrpl/ledger/ApplyView.cpp +undefined:src/libxrpl/ledger/View.cpp +undefined:src/libxrpl/protocol/Permissions.cpp +undefined:src/libxrpl/protocol/STAmount.cpp +undefined:src/libxrpl/protocol/STPathSet.cpp +undefined:src/libxrpl/protocol/tokens.cpp +undefined:src/libxrpl/shamap/SHAMap.cpp +undefined:src/test/app/Batch_test.cpp +undefined:src/test/app/Invariants_test.cpp +undefined:src/test/app/NFToken_test.cpp +undefined:src/test/app/Offer_test.cpp +undefined:src/test/app/Path_test.cpp +undefined:src/test/basics/XRPAmount_test.cpp +undefined:src/test/beast/LexicalCast_test.cpp +undefined:src/test/jtx/impl/acctdelete.cpp +undefined:src/test/ledger/SkipList_test.cpp +undefined:src/test/rpc/Subscribe_test.cpp +undefined:src/tests/libxrpl/basics/RangeSet.cpp +undefined:src/xrpld/app/main/BasicApp.cpp +undefined:src/xrpld/app/main/BasicApp.cpp +undefined:src/xrpld/app/misc/detail/AmendmentTable.cpp +undefined:src/xrpld/app/misc/NetworkOPs.cpp +undefined:src/libxrpl/json/json_value.cpp +undefined:src/xrpld/app/paths/detail/StrandFlow.h +undefined:src/xrpld/app/tx/detail/NFTokenMint.cpp +undefined:src/xrpld/app/tx/detail/SetOracle.cpp +undefined:src/xrpld/core/detail/JobQueue.cpp +undefined:src/xrpld/core/detail/Workers.cpp +undefined:src/xrpld/rpc/detail/Role.cpp +undefined:src/xrpld/rpc/handlers/GetAggregatePrice.cpp +undefined:xrpl/basics/base_uint.h +undefined:xrpl/basics/DecayingSample.h +undefined:xrpl/beast/test/yield_to.h +undefined:xrpl/beast/xor_shift_engine.h +undefined:xrpl/nodestore/detail/varint.h +undefined:xrpl/peerfinder/detail/Counts.h +undefined:xrpl/protocol/nft.h + +# basic_string.h:483:51: runtime error: unsigned integer overflow +unsigned-integer-overflow:basic_string.h +unsigned-integer-overflow:bits/chrono.h +unsigned-integer-overflow:bits/random.h +unsigned-integer-overflow:bits/random.tcc +unsigned-integer-overflow:bits/stl_algobase.h +unsigned-integer-overflow:bits/uniform_int_dist.h +unsigned-integer-overflow:string_view + +# runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'std::size_t' (aka 'unsigned long') +unsigned-integer-overflow:src/libxrpl/basics/base64.cpp +unsigned-integer-overflow:src/libxrpl/basics/Number.cpp +unsigned-integer-overflow:src/libxrpl/crypto/RFC1751.cpp +unsigned-integer-overflow:rc/libxrpl/json/json_value.cpp +unsigned-integer-overflow:src/libxrpl/ledger/ApplyView.cpp +unsigned-integer-overflow:src/libxrpl/ledger/View.cpp +unsigned-integer-overflow:src/libxrpl/protocol/Permissions.cpp +unsigned-integer-overflow:src/libxrpl/protocol/STAmount.cpp +unsigned-integer-overflow:src/libxrpl/protocol/STPathSet.cpp +unsigned-integer-overflow:src/libxrpl/protocol/tokens.cpp +unsigned-integer-overflow:src/libxrpl/shamap/SHAMap.cpp +unsigned-integer-overflow:src/test/app/Batch_test.cpp +unsigned-integer-overflow:src/test/app/Invariants_test.cpp +unsigned-integer-overflow:src/test/app/NFToken_test.cpp +unsigned-integer-overflow:src/test/app/Offer_test.cpp +unsigned-integer-overflow:src/test/app/Path_test.cpp +unsigned-integer-overflow:src/test/basics/XRPAmount_test.cpp +unsigned-integer-overflow:src/test/beast/LexicalCast_test.cpp +unsigned-integer-overflow:src/test/jtx/impl/acctdelete.cpp +unsigned-integer-overflow:src/test/ledger/SkipList_test.cpp +unsigned-integer-overflow:src/test/rpc/Subscribe_test.cpp +unsigned-integer-overflow:src/tests/libxrpl/basics/RangeSet.cpp +unsigned-integer-overflow:src/xrpld/app/main/BasicApp.cpp +unsigned-integer-overflow:src/xrpld/app/misc/detail/AmendmentTable.cpp +unsigned-integer-overflow:src/xrpld/app/misc/NetworkOPs.cpp +unsigned-integer-overflow:src/xrpld/app/paths/detail/StrandFlow.h +unsigned-integer-overflow:src/xrpld/app/tx/detail/NFTokenMint.cpp +unsigned-integer-overflow:src/xrpld/app/tx/detail/SetOracle.cpp +unsigned-integer-overflow:src/xrpld/rpc/detail/Role.cpp +unsigned-integer-overflow:src/xrpld/rpc/handlers/GetAggregatePrice.cpp +unsigned-integer-overflow:xrpl/basics/base_uint.h +unsigned-integer-overflow:xrpl/basics/DecayingSample.h +unsigned-integer-overflow:xrpl/beast/test/yield_to.h +unsigned-integer-overflow:xrpl/beast/xor_shift_engine.h +unsigned-integer-overflow:xrpl/nodestore/detail/varint.h +unsigned-integer-overflow:xrpl/peerfinder/detail/Counts.h +unsigned-integer-overflow:xrpl/protocol/nft.h + +# Rippled intentional overflows and operations +# STAmount uses intentional negation of INT64_MIN and overflow in arithmetic +signed-integer-overflow:src/libxrpl/protocol/STAmount.cpp +unsigned-integer-overflow:src/libxrpl/protocol/STAmount.cpp + +# XRPAmount test intentional overflows +signed-integer-overflow:src/test/basics/XRPAmount_test.cpp + +# Peerfinder intentional overflow in counter arithmetic +unsigned-integer-overflow:src/xrpld/peerfinder/detail/Counts.h + +# Signed integer overflow suppressions +signed-integer-overflow:src/test/beast/LexicalCast_test.cpp + +# External library suppressions +unsigned-integer-overflow:nudb/detail/xxhash.hpp + +# Protobuf intentional overflows in hash functions +# Protobuf uses intentional unsigned overflow for hash computation (stringpiece.h:393) +unsigned-integer-overflow:google/protobuf/stubs/stringpiece.h + +# gRPC intentional overflows +# gRPC uses intentional overflow in timer calculations +unsigned-integer-overflow:grpc +unsigned-integer-overflow:timer_manager.cc + +# Standard library intentional overflows +# These are intentional overflows in random number generation and character conversion +unsigned-integer-overflow:__random/seed_seq.h +unsigned-integer-overflow:__charconv/traits.h + + +# Suppress errors in RocksDB +# RocksDB uses intentional unsigned integer overflows in hash functions and CRC calculations +unsigned-integer-overflow:rocks*/*/util/xxhash.h +unsigned-integer-overflow:rocks*/*/util/xxph3.h +unsigned-integer-overflow:rocks*/*/util/hash.cc +unsigned-integer-overflow:rocks*/*/util/crc32c.cc +unsigned-integer-overflow:rocks*/*/util/crc32c.h +unsigned-integer-overflow:rocks*/*/include/rocksdb/utilities/options_type.h +unsigned-integer-overflow:rocks*/*/table/format.h +unsigned-integer-overflow:rocks*/*/table/format.cc +unsigned-integer-overflow:rocks*/*/table/block_based/block_based_table_builder.cc +unsigned-integer-overflow:rocks*/*/table/block_based/reader_common.cc +unsigned-integer-overflow:rocks*/*/db/version_set.cc + +# RocksDB misaligned loads (intentional for performance on ARM64) +alignment:rocks*/*/util/crc32c_arm64.cc + +# nudb intentional overflows in hash functions +unsigned-integer-overflow:nudb/detail/xxhash.hpp +alignment:nudb/detail/xxhash.hpp + +# Snappy compression library intentional overflows +unsigned-integer-overflow:snappy.cc + +# Abseil intentional overflows +unsigned-integer-overflow:absl/strings/numbers.cc +unsigned-integer-overflow:absl/strings/internal/cord_rep_flat.h +unsigned-integer-overflow:absl/base/internal/low_level_alloc.cc +unsigned-integer-overflow:absl/hash/internal/hash.h +unsigned-integer-overflow:absl/container/internal/raw_hash_set.h + +# Standard library intentional overflows in chrono duration arithmetic +unsigned-integer-overflow:__chrono/duration.h + +# Suppress undefined errors in RocksDB and nudb +undefined:rocks.*/*/util/crc32c_arm64.cc +undefined:rocks.*/*/util/xxhash.h +undefined:nudb diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 14246baf17..16ec23ffab 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -451,9 +451,8 @@ getTrustLineBalance( amount.clear(Issue{currency, issuer}); } - JLOG(j.trace()) << "getTrustLineBalance:" - << " account=" << to_string(account) - << " amount=" << amount.getFullText(); + JLOG(j.trace()) << "getTrustLineBalance:" << " account=" + << to_string(account) << " amount=" << amount.getFullText(); return view.balanceHook(account, issuer, amount); } @@ -700,8 +699,7 @@ xrpLiquid( STAmount const amount = (balance < reserve) ? STAmount{0} : balance - reserve; - JLOG(j.trace()) << "accountHolds:" - << " account=" << to_string(id) + JLOG(j.trace()) << "accountHolds:" << " account=" << to_string(id) << " amount=" << amount.getFullText() << " fullBalance=" << fullBalance.getFullText() << " balance=" << balance.getFullText() @@ -1107,7 +1105,7 @@ adjustOwnerCount( std::function describeOwnerDir(AccountID const& account) { - return [&account](std::shared_ptr const& sle) { + return [account](std::shared_ptr const& sle) { (*sle)[sfOwner] = account; }; } diff --git a/src/libxrpl/protocol/BuildInfo.cpp b/src/libxrpl/protocol/BuildInfo.cpp index dc56987f3a..b5e2354165 100644 --- a/src/libxrpl/protocol/BuildInfo.cpp +++ b/src/libxrpl/protocol/BuildInfo.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include #include #include @@ -20,7 +22,7 @@ namespace BuildInfo { char const* const versionString = "3.2.0-b0" // clang-format on -#if defined(DEBUG) || defined(SANITIZER) +#if defined(DEBUG) || defined(SANITIZERS) "+" #ifdef GIT_COMMIT_HASH GIT_COMMIT_HASH @@ -28,13 +30,13 @@ char const* const versionString = "3.2.0-b0" #endif #ifdef DEBUG "DEBUG" -#ifdef SANITIZER +#ifdef SANITIZERS "." #endif #endif -#ifdef SANITIZER - BOOST_PP_STRINGIZE(SANITIZER) // cspell: disable-line +#ifdef SANITIZERS + BOOST_PP_STRINGIZE(SANITIZERS) // cspell: disable-line #endif #endif From 00d3cee6ccc5dd87c6005c55ace5bf3ce064a8c5 Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Fri, 16 Jan 2026 13:26:30 -0400 Subject: [PATCH 077/105] Improve ledger_entry lookups for fee, amendments, NUNL, and hashes (#5644) These "fixed location" objects can be found in multiple ways: 1. The lookup parameters use the same format as other ledger objects, but the only valid value is true or the valid index of the object: - Amendments: "amendments" : true - FeeSettings: "fee" : true - NegativeUNL: "nunl" : true - LedgerHashes: "hashes" : true (For the "short" list. See below.) 2. With RPC API >= 3, using special case values to "index", such as "index" : "amendments". Uses the same names as above. Note that for "hashes", this option will only return the recent ledger hashes / "short" skip list. 3. LedgerHashes has two types: "short", which stores recent ledger hashes, and "long", which stores the flag ledger hashes for a particular ledger range. - To find a "long" LedgerHashes object, request '"hashes" : '. must be a number that evaluates to an unsigned integer. - To find the "short" LedgerHashes object, request "hashes": true as with the other fixed objects. The following queries are all functionally equivalent: - "amendments" : true - "index" : "amendments" (API >=3 only) - "amendments" : "7DB0788C020F02780A673DC74757F23823FA3014C1866E72CC4CD8B226CD6EF4" - "index" : "7DB0788C020F02780A673DC74757F23823FA3014C1866E72CC4CD8B226CD6EF4" Finally, whether the object is found or not, if a valid index is computed, that index will be returned. This can be used to confirm the query was valid, or to save the index for future use. --- src/test/rpc/LedgerEntry_test.cpp | 469 ++++++++++++++++++++++++- src/xrpld/rpc/handlers/LedgerEntry.cpp | 237 ++++++++++--- 2 files changed, 649 insertions(+), 57 deletions(-) diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index 551e67dc5e..1b7079341c 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include #include @@ -30,6 +32,7 @@ enum class FieldType { CurrencyField, HashField, HashOrObjectField, + FixedHashField, IssueField, ObjectField, StringField, @@ -86,6 +89,7 @@ getTypeName(FieldType typeID) case FieldType::CurrencyField: return "Currency"; case FieldType::HashField: + case FieldType::FixedHashField: return "hex string"; case FieldType::HashOrObjectField: return "hex string or object"; @@ -202,6 +206,7 @@ class LedgerEntry_test : public beast::unit_test::suite static auto const& badBlobValues = remove({3, 7, 8, 16}); static auto const& badCurrencyValues = remove({14}); static auto const& badHashValues = remove({2, 3, 7, 8, 16}); + static auto const& badFixedHashValues = remove({1, 2, 3, 4, 7, 8, 16}); static auto const& badIndexValues = remove({12, 16, 18, 19}); static auto const& badUInt32Values = remove({2, 3}); static auto const& badUInt64Values = remove({2, 3}); @@ -222,6 +227,8 @@ class LedgerEntry_test : public beast::unit_test::suite return badHashValues; case FieldType::HashOrObjectField: return badIndexValues; + case FieldType::FixedHashField: + return badFixedHashValues; case FieldType::IssueField: return badIssueValues; case FieldType::UInt32Field: @@ -717,7 +724,12 @@ class LedgerEntry_test : public beast::unit_test::suite } // negative tests - runLedgerEntryTest(env, jss::amendments); + testMalformedField( + env, + Json::Value{}, + jss::amendments, + FieldType::FixedHashField, + "malformedRequest"); } void @@ -1538,7 +1550,12 @@ class LedgerEntry_test : public beast::unit_test::suite } // negative tests - runLedgerEntryTest(env, jss::fee); + testMalformedField( + env, + Json::Value{}, + jss::fee, + FieldType::FixedHashField, + "malformedRequest"); } void @@ -1561,7 +1578,12 @@ class LedgerEntry_test : public beast::unit_test::suite } // negative tests - runLedgerEntryTest(env, jss::hashes); + testMalformedField( + env, + Json::Value{}, + jss::hashes, + FieldType::FixedHashField, + "malformedRequest"); } void @@ -1686,7 +1708,12 @@ class LedgerEntry_test : public beast::unit_test::suite } // negative tests - runLedgerEntryTest(env, jss::nunl); + testMalformedField( + env, + Json::Value{}, + jss::nunl, + FieldType::FixedHashField, + "malformedRequest"); } void @@ -2343,6 +2370,438 @@ class LedgerEntry_test : public beast::unit_test::suite } } + /// Test the ledger entry types that don't take parameters + void + testFixed() + { + using namespace test::jtx; + + Account const alice{"alice"}; + Account const bob{"bob"}; + + Env env{*this, envconfig([](auto cfg) { + cfg->START_UP = Config::FRESH; + return cfg; + })}; + + env.close(); + + /** Verifies that the RPC result has the expected data + * + * @param good: Indicates that the request should have succeeded + * and returned a ledger object of `expectedType` type. + * @param jv: The RPC result Json value + * @param expectedType: The type that the ledger object should + * have if "good". + * @param expectedError: Optional. The expected error if not + * good. Defaults to "entryNotFound". + */ + auto checkResult = + [&](bool good, + Json::Value const& jv, + Json::StaticString const& expectedType, + std::optional const& expectedError = {}) { + if (good) + { + BEAST_EXPECTS( + jv.isObject() && jv.isMember(jss::result) && + !jv[jss::result].isMember(jss::error) && + jv[jss::result].isMember(jss::node) && + jv[jss::result][jss::node].isMember( + sfLedgerEntryType.jsonName) && + jv[jss::result][jss::node] + [sfLedgerEntryType.jsonName] == expectedType, + to_string(jv)); + } + else + { + BEAST_EXPECTS( + jv.isObject() && jv.isMember(jss::result) && + jv[jss::result].isMember(jss::error) && + !jv[jss::result].isMember(jss::node) && + jv[jss::result][jss::error] == + expectedError.value_or("entryNotFound"), + to_string(jv)); + } + }; + + /** Runs a series of tests for a given fixed-position ledger + * entry. + * + * @param field: The Json request field to use. + * @param expectedType: The type that the ledger object should + * have if "good". + * @param expectedKey: The keylet of the fixed object. + * @param good: Indicates whether the object is expected to + * exist. + */ + auto test = [&](Json::StaticString const& field, + Json::StaticString const& expectedType, + Keylet const& expectedKey, + bool good) { + testcase << expectedType.c_str() << (good ? "" : " not") + << " found"; + + auto const hexKey = strHex(expectedKey.key); + + { + // Test bad values + // "field":null + Json::Value params; + params[jss::ledger_index] = jss::validated; + params[field] = Json::nullValue; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, expectedType, "malformedRequest"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + { + Json::Value params; + // "field":"string" + params[jss::ledger_index] = jss::validated; + params[field] = "arbitrary string"; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, expectedType, "malformedRequest"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + { + Json::Value params; + // "field":false + params[jss::ledger_index] = jss::validated; + params[field] = false; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, expectedType, "invalidParams"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + { + Json::Value params; + + // "field":[incorrect index hash] + auto const badKey = strHex(expectedKey.key + uint256{1}); + params[jss::ledger_index] = jss::validated; + params[field] = badKey; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, expectedType, "entryNotFound"); + BEAST_EXPECTS( + jv[jss::result][jss::index] == badKey, to_string(jv)); + } + + { + Json::Value params; + // "index":"field" using API 2 + params[jss::ledger_index] = jss::validated; + params[jss::index] = field; + params[jss::api_version] = 2; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, expectedType, "malformedRequest"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + std::string const pdIdx = [&]() { + { + Json::Value params; + // Test good values + // Use the "field":true notation + params[jss::ledger_index] = jss::validated; + params[field] = true; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + // Index will always be returned for valid parameters. + std::string const pdIdx = + jv[jss::result][jss::index].asString(); + BEAST_EXPECTS(hexKey == pdIdx, to_string(jv)); + checkResult(good, jv, expectedType); + + return pdIdx; + } + }(); + + { + Json::Value params; + // "field":"[index hash]" + params[jss::ledger_index] = jss::validated; + params[field] = hexKey; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(good, jv, expectedType); + BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey); + } + + { + // Bad value + // Use the "index":"field" notation with API 2 + Json::Value params; + params[jss::ledger_index] = jss::validated; + params[jss::index] = field; + params[jss::api_version] = 2; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, expectedType, "malformedRequest"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + { + Json::Value params; + // Use the "index":"field" notation with API 3 + params[jss::ledger_index] = jss::validated; + params[jss::index] = field; + params[jss::api_version] = 3; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + // Index is correct either way + BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey); + checkResult(good, jv, expectedType); + } + + { + Json::Value params; + // Use the "index":"[index hash]" notation + params[jss::ledger_index] = jss::validated; + params[jss::index] = pdIdx; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + // Index is correct either way + BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey); + checkResult(good, jv, expectedType); + } + }; + + test(jss::amendments, jss::Amendments, keylet::amendments(), true); + test(jss::fee, jss::FeeSettings, keylet::fees(), true); + // There won't be an nunl + test(jss::nunl, jss::NegativeUNL, keylet::negativeUNL(), false); + // Can only get the short skip list this way + test(jss::hashes, jss::LedgerHashes, keylet::skip(), true); + } + + void + testHashes() + { + using namespace test::jtx; + + Account const alice{"alice"}; + Account const bob{"bob"}; + + Env env{*this, envconfig([](auto cfg) { + cfg->START_UP = Config::FRESH; + return cfg; + })}; + + env.close(); + + /** Verifies that the RPC result has the expected data + * + * @param good: Indicates that the request should have succeeded + * and returned a ledger object of `expectedType` type. + * @param jv: The RPC result Json value + * @param expectedCount: The number of Hashes expected in the + * object if "good". + * @param expectedError: Optional. The expected error if not + * good. Defaults to "entryNotFound". + */ + auto checkResult = + [&](bool good, + Json::Value const& jv, + int expectedCount, + std::optional const& expectedError = {}) { + if (good) + { + BEAST_EXPECTS( + jv.isObject() && jv.isMember(jss::result) && + !jv[jss::result].isMember(jss::error) && + jv[jss::result].isMember(jss::node) && + jv[jss::result][jss::node].isMember( + sfLedgerEntryType.jsonName) && + jv[jss::result][jss::node] + [sfLedgerEntryType.jsonName] == jss::LedgerHashes, + to_string(jv)); + BEAST_EXPECTS( + jv[jss::result].isMember(jss::node) && + jv[jss::result][jss::node].isMember("Hashes") && + jv[jss::result][jss::node]["Hashes"].size() == + expectedCount, + to_string(jv[jss::result][jss::node]["Hashes"].size())); + } + else + { + BEAST_EXPECTS( + jv.isObject() && jv.isMember(jss::result) && + jv[jss::result].isMember(jss::error) && + !jv[jss::result].isMember(jss::node) && + jv[jss::result][jss::error] == + expectedError.value_or("entryNotFound"), + to_string(jv)); + } + }; + + /** Runs a series of tests for a given ledger index. + * + * @param ledger: The ledger index value of the "hashes" request + * parameter. May not necessarily be a number. + * @param expectedKey: The expected keylet of the object. + * @param good: Indicates whether the object is expected to + * exist. + * @param expectedCount: The number of Hashes expected in the + * object if "good". + */ + auto test = [&](Json::Value ledger, + Keylet const& expectedKey, + bool good, + int expectedCount = 0) { + testcase << "LedgerHashes: seq: " << env.current()->header().seq + << " \"hashes\":" << to_string(ledger) + << (good ? "" : " not") << " found"; + + auto const hexKey = strHex(expectedKey.key); + + { + // Test bad values + // "hashes":null + Json::Value params; + params[jss::ledger_index] = jss::validated; + params[jss::hashes] = Json::nullValue; + auto jv = env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, 0, "malformedRequest"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + { + Json::Value params; + // "hashes":"non-uint string" + params[jss::ledger_index] = jss::validated; + params[jss::hashes] = "arbitrary string"; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, 0, "malformedRequest"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + { + Json::Value params; + // "hashes":"uint string" is invalid, too + params[jss::ledger_index] = jss::validated; + params[jss::hashes] = "10"; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, 0, "malformedRequest"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + { + Json::Value params; + // "hashes":false + params[jss::ledger_index] = jss::validated; + params[jss::hashes] = false; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, 0, "invalidParams"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + { + Json::Value params; + // "hashes":-1 + params[jss::ledger_index] = jss::validated; + params[jss::hashes] = -1; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, 0, "internal"); + BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); + } + + // "hashes":[incorrect index hash] + { + Json::Value params; + auto const badKey = strHex(expectedKey.key + uint256{1}); + params[jss::ledger_index] = jss::validated; + params[jss::hashes] = badKey; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(false, jv, 0, "entryNotFound"); + BEAST_EXPECT(jv[jss::result][jss::index] == badKey); + } + + { + Json::Value params; + // Test good values + // Use the "hashes":ledger notation + params[jss::ledger_index] = jss::validated; + params[jss::hashes] = ledger; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(good, jv, expectedCount); + // Index will always be returned for valid parameters. + std::string const pdIdx = + jv[jss::result][jss::index].asString(); + BEAST_EXPECTS(hexKey == pdIdx, strHex(pdIdx)); + } + + { + Json::Value params; + // "hashes":"[index hash]" + params[jss::ledger_index] = jss::validated; + params[jss::hashes] = hexKey; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(good, jv, expectedCount); + // Index is correct either way + BEAST_EXPECTS( + hexKey == jv[jss::result][jss::index].asString(), + strHex(jv[jss::result][jss::index].asString())); + } + + { + Json::Value params; + // Use the "index":"[index hash]" notation + params[jss::ledger_index] = jss::validated; + params[jss::index] = hexKey; + auto const jv = + env.rpc("json", "ledger_entry", to_string(params)); + checkResult(good, jv, expectedCount); + // Index is correct either way + BEAST_EXPECTS( + hexKey == jv[jss::result][jss::index].asString(), + strHex(jv[jss::result][jss::index].asString())); + } + }; + + // short skip list + test(true, keylet::skip(), true, 2); + // long skip list at index 0 + test(1, keylet::skip(1), false); + // long skip list at index 1 + test(1 << 17, keylet::skip(1 << 17), false); + + // Close more ledgers, but stop short of the flag ledger + for (auto i = env.current()->seq(); i <= 250; ++i) + env.close(); + + // short skip list + test(true, keylet::skip(), true, 249); + // long skip list at index 0 + test(1, keylet::skip(1), false); + // long skip list at index 1 + test(1 << 17, keylet::skip(1 << 17), false); + + // Close a flag ledger so the first "long" skip list is created + for (auto i = env.current()->seq(); i <= 260; ++i) + env.close(); + + // short skip list + test(true, keylet::skip(), true, 256); + // long skip list at index 0 + test(1, keylet::skip(1), true, 1); + // long skip list at index 1 + test(1 << 17, keylet::skip(1 << 17), false); + } + void testCLI() { @@ -2400,6 +2859,8 @@ public: testOracleLedgerEntry(); testMPT(); testPermissionedDomain(); + testFixed(); + testHashes(); testCLI(); } }; diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index d9ae357b1a..17d8e5e7bc 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -18,6 +18,32 @@ namespace xrpl { +using FunctionType = std::function( + Json::Value const&, + Json::StaticString const, + unsigned const apiVersion)>; + +static Expected +parseFixed( + Keylet const& keylet, + Json::Value const& params, + Json::StaticString const& fieldName, + unsigned const apiVersion); + +// Helper function to return FunctionType for objects that have a fixed +// location. That is, they don't take parameters to compute the index. +// e.g. amendments, fees, negative UNL, etc. +static FunctionType +fixed(Keylet const& keylet) +{ + return [keylet]( + Json::Value const& params, + Json::StaticString const fieldName, + unsigned const apiVersion) -> Expected { + return parseFixed(keylet, params, fieldName, apiVersion); + }; +} + static Expected parseObjectID( Json::Value const& params, @@ -33,13 +59,33 @@ parseObjectID( } static Expected -parseIndex(Json::Value const& params, Json::StaticString const fieldName) +parseIndex( + Json::Value const& params, + Json::StaticString const fieldName, + unsigned const apiVersion) { + if (apiVersion > 2u && params.isString()) + { + std::string const index = params.asString(); + if (index == jss::amendments.c_str()) + return keylet::amendments().key; + if (index == jss::fee.c_str()) + return keylet::fees().key; + if (index == jss::nunl) + return keylet::negativeUNL().key; + if (index == jss::hashes) + // Note this only finds the "short" skip list. Use "hashes":index to + // get the long list. + return keylet::skip().key; + } return parseObjectID(params, fieldName, "hex string"); } static Expected -parseAccountRoot(Json::Value const& params, Json::StaticString const fieldName) +parseAccountRoot( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (auto const account = LedgerEntryHelpers::parse(params)) { @@ -50,14 +96,13 @@ parseAccountRoot(Json::Value const& params, Json::StaticString const fieldName) "malformedAddress", fieldName, "AccountID"); } -static Expected -parseAmendments(Json::Value const& params, Json::StaticString const fieldName) -{ - return parseObjectID(params, fieldName, "hex string"); -} +auto const parseAmendments = fixed(keylet::amendments()); static Expected -parseAMM(Json::Value const& params, Json::StaticString const fieldName) +parseAMM( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -85,7 +130,10 @@ parseAMM(Json::Value const& params, Json::StaticString const fieldName) } static Expected -parseBridge(Json::Value const& params, Json::StaticString const fieldName) +parseBridge( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isMember(jss::bridge)) { @@ -116,13 +164,19 @@ parseBridge(Json::Value const& params, Json::StaticString const fieldName) } static Expected -parseCheck(Json::Value const& params, Json::StaticString const fieldName) +parseCheck( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { return parseObjectID(params, fieldName, "hex string"); } static Expected -parseCredential(Json::Value const& cred, Json::StaticString const fieldName) +parseCredential( + Json::Value const& cred, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!cred.isObject()) { @@ -153,7 +207,10 @@ parseCredential(Json::Value const& cred, Json::StaticString const fieldName) } static Expected -parseDelegate(Json::Value const& params, Json::StaticString const fieldName) +parseDelegate( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -244,7 +301,10 @@ parseAuthorizeCredentials(Json::Value const& jv) } static Expected -parseDepositPreauth(Json::Value const& dp, Json::StaticString const fieldName) +parseDepositPreauth( + Json::Value const& dp, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!dp.isObject()) { @@ -297,7 +357,10 @@ parseDepositPreauth(Json::Value const& dp, Json::StaticString const fieldName) } static Expected -parseDID(Json::Value const& params, Json::StaticString const fieldName) +parseDID( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { auto const account = LedgerEntryHelpers::parse(params); if (!account) @@ -312,7 +375,8 @@ parseDID(Json::Value const& params, Json::StaticString const fieldName) static Expected parseDirectoryNode( Json::Value const& params, - Json::StaticString const fieldName) + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -365,7 +429,10 @@ parseDirectoryNode( } static Expected -parseEscrow(Json::Value const& params, Json::StaticString const fieldName) +parseEscrow( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -384,20 +451,53 @@ parseEscrow(Json::Value const& params, Json::StaticString const fieldName) return keylet::escrow(*id, *seq).key; } +auto const parseFeeSettings = fixed(keylet::fees()); + static Expected -parseFeeSettings(Json::Value const& params, Json::StaticString const fieldName) +parseFixed( + Keylet const& keylet, + Json::Value const& params, + Json::StaticString const& fieldName, + [[maybe_unused]] unsigned const apiVersion) { - return parseObjectID(params, fieldName, "hex string"); + if (!params.isBool()) + { + return parseObjectID(params, fieldName, "hex string"); + } + if (!params.asBool()) + { + return LedgerEntryHelpers::invalidFieldError( + "invalidParams", fieldName, "true"); + } + + return keylet.key; } static Expected -parseLedgerHashes(Json::Value const& params, Json::StaticString const fieldName) +parseLedgerHashes( + Json::Value const& params, + Json::StaticString const fieldName, + unsigned const apiVersion) { - return parseObjectID(params, fieldName, "hex string"); + if (params.isUInt() || params.isInt()) + { + // If the index doesn't parse as a UInt, throw + auto const index = params.asUInt(); + + // Return the "long" skip list for the given ledger index. + auto const keylet = keylet::skip(index); + return keylet.key; + } + // Return the key in `params` or the "short" skip list, which contains + // hashes since the last flag ledger. + return parseFixed(keylet::skip(), params, fieldName, apiVersion); } static Expected -parseLoanBroker(Json::Value const& params, Json::StaticString const fieldName) +parseLoanBroker( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -417,7 +517,10 @@ parseLoanBroker(Json::Value const& params, Json::StaticString const fieldName) } static Expected -parseLoan(Json::Value const& params, Json::StaticString const fieldName) +parseLoan( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -437,7 +540,10 @@ parseLoan(Json::Value const& params, Json::StaticString const fieldName) } static Expected -parseMPToken(Json::Value const& params, Json::StaticString const fieldName) +parseMPToken( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -460,7 +566,8 @@ parseMPToken(Json::Value const& params, Json::StaticString const fieldName) static Expected parseMPTokenIssuance( Json::Value const& params, - Json::StaticString const fieldName) + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { auto const mptIssuanceID = LedgerEntryHelpers::parse(params); if (!mptIssuanceID) @@ -471,25 +578,30 @@ parseMPTokenIssuance( } static Expected -parseNFTokenOffer(Json::Value const& params, Json::StaticString const fieldName) +parseNFTokenOffer( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { return parseObjectID(params, fieldName, "hex string"); } static Expected -parseNFTokenPage(Json::Value const& params, Json::StaticString const fieldName) +parseNFTokenPage( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { return parseObjectID(params, fieldName, "hex string"); } -static Expected -parseNegativeUNL(Json::Value const& params, Json::StaticString const fieldName) -{ - return parseObjectID(params, fieldName, "hex string"); -} +auto const parseNegativeUNL = fixed(keylet::negativeUNL()); static Expected -parseOffer(Json::Value const& params, Json::StaticString const fieldName) +parseOffer( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -510,7 +622,10 @@ parseOffer(Json::Value const& params, Json::StaticString const fieldName) } static Expected -parseOracle(Json::Value const& params, Json::StaticString const fieldName) +parseOracle( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -531,7 +646,10 @@ parseOracle(Json::Value const& params, Json::StaticString const fieldName) } static Expected -parsePayChannel(Json::Value const& params, Json::StaticString const fieldName) +parsePayChannel( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { return parseObjectID(params, fieldName, "hex string"); } @@ -539,7 +657,8 @@ parsePayChannel(Json::Value const& params, Json::StaticString const fieldName) static Expected parsePermissionedDomain( Json::Value const& pd, - Json::StaticString const fieldName) + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (pd.isString()) { @@ -568,7 +687,8 @@ parsePermissionedDomain( static Expected parseRippleState( Json::Value const& jvRippleState, - Json::StaticString const fieldName) + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { Currency uCurrency; @@ -618,13 +738,19 @@ parseRippleState( } static Expected -parseSignerList(Json::Value const& params, Json::StaticString const fieldName) +parseSignerList( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { return parseObjectID(params, fieldName, "hex string"); } static Expected -parseTicket(Json::Value const& params, Json::StaticString const fieldName) +parseTicket( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -645,7 +771,10 @@ parseTicket(Json::Value const& params, Json::StaticString const fieldName) } static Expected -parseVault(Json::Value const& params, Json::StaticString const fieldName) +parseVault( + Json::Value const& params, + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!params.isObject()) { @@ -668,7 +797,8 @@ parseVault(Json::Value const& params, Json::StaticString const fieldName) static Expected parseXChainOwnedClaimID( Json::Value const& claim_id, - Json::StaticString const fieldName) + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!claim_id.isObject()) { @@ -693,7 +823,8 @@ parseXChainOwnedClaimID( static Expected parseXChainOwnedCreateAccountClaimID( Json::Value const& claim_id, - Json::StaticString const fieldName) + Json::StaticString const fieldName, + [[maybe_unused]] unsigned const apiVersion) { if (!claim_id.isObject()) { @@ -717,10 +848,6 @@ parseXChainOwnedCreateAccountClaimID( return keylet.key; } -using FunctionType = Expected (*)( - Json::Value const&, - Json::StaticString const); - struct LedgerEntry { Json::StaticString fieldName; @@ -753,7 +880,7 @@ doLedgerEntry(RPC::JsonContext& context) {jss::ripple_state, parseRippleState, ltRIPPLE_STATE}, }); - auto hasMoreThanOneMember = [&]() { + auto const hasMoreThanOneMember = [&]() { int count = 0; for (auto const& ledgerEntry : ledgerEntryParsers) @@ -797,8 +924,8 @@ doLedgerEntry(RPC::JsonContext& context) Json::Value const& params = ledgerEntry.fieldName == jss::bridge ? context.params : context.params[ledgerEntry.fieldName]; - auto const result = - ledgerEntry.parseFunction(params, ledgerEntry.fieldName); + auto const result = ledgerEntry.parseFunction( + params, ledgerEntry.fieldName, context.apiVersion); if (!result) return result.error(); @@ -829,9 +956,13 @@ doLedgerEntry(RPC::JsonContext& context) throw; } + // Return the computed index regardless of whether the node exists. + jvResult[jss::index] = to_string(uNodeIndex); + if (uNodeIndex.isZero()) { - return RPC::make_error(rpcENTRY_NOT_FOUND); + RPC::inject_error(rpcENTRY_NOT_FOUND, jvResult); + return jvResult; } auto const sleNode = lpLedger->read(keylet::unchecked(uNodeIndex)); @@ -843,12 +974,14 @@ doLedgerEntry(RPC::JsonContext& context) if (!sleNode) { // Not found. - return RPC::make_error(rpcENTRY_NOT_FOUND); + RPC::inject_error(rpcENTRY_NOT_FOUND, jvResult); + return jvResult; } if ((expectedType != ltANY) && (expectedType != sleNode->getType())) { - return RPC::make_error(rpcUNEXPECTED_LEDGER_TYPE); + RPC::inject_error(rpcUNEXPECTED_LEDGER_TYPE, jvResult); + return jvResult; } if (bNodeBinary) @@ -858,12 +991,10 @@ doLedgerEntry(RPC::JsonContext& context) sleNode->add(s); jvResult[jss::node_binary] = strHex(s.peekData()); - jvResult[jss::index] = to_string(uNodeIndex); } else { jvResult[jss::node] = sleNode->getJson(JsonOptions::none); - jvResult[jss::index] = to_string(uNodeIndex); } return jvResult; From 12c0d67ff62f141f4c1d25ece56800f22cb3861e Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 16 Jan 2026 15:01:53 -0500 Subject: [PATCH 078/105] ci: remove 'master' branch as a trigger (#6234) This change removes the `master` branch as a trigger for the CI pipelines, and updates comments accordingly. It also fixes the pre-commit workflow, so it will run on all release branches. --- .github/scripts/strategy-matrix/generate.py | 4 ++-- .github/workflows/on-pr.yml | 2 +- .github/workflows/on-trigger.yml | 20 +++++++++----------- .github/workflows/pre-commit.yml | 4 +++- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/scripts/strategy-matrix/generate.py b/.github/scripts/strategy-matrix/generate.py index bf5bf5d3ba..0e44b1be54 100755 --- a/.github/scripts/strategy-matrix/generate.py +++ b/.github/scripts/strategy-matrix/generate.py @@ -20,8 +20,8 @@ class Config: Generate a strategy matrix for GitHub Actions CI. On each PR commit we will build a selection of Debian, RHEL, Ubuntu, MacOS, and -Windows configurations, while upon merge into the develop, release, or master -branches, we will build all configurations, and test most of them. +Windows configurations, while upon merge into the develop or release branches, +we will build all configurations, and test most of them. We will further set additional CMake arguments as follows: - All builds will have the `tests`, `werr`, and `xrpld` options. diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 3aa48ac070..dad211f94f 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -125,7 +125,7 @@ jobs: needs: - should-run - build-test - if: ${{ needs.should-run.outputs.go == 'true' && (startsWith(github.base_ref, 'release') || github.base_ref == 'master') }} + if: ${{ needs.should-run.outputs.go == 'true' && startsWith(github.ref, 'refs/heads/release') }} uses: ./.github/workflows/reusable-notify-clio.yml secrets: clio_notify_token: ${{ secrets.CLIO_NOTIFY_TOKEN }} diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml index 2c63c2baa5..ef7bf41fa2 100644 --- a/.github/workflows/on-trigger.yml +++ b/.github/workflows/on-trigger.yml @@ -1,9 +1,8 @@ -# This workflow runs all workflows to build the dependencies required for the -# project on various Linux flavors, as well as on MacOS and Windows, on a -# scheduled basis, on merge into the 'develop', 'release', or 'master' branches, -# or manually. The missing commits check is only run when the code is merged -# into the 'develop' or 'release' branches, and the documentation is built when -# the code is merged into the 'develop' branch. +# This workflow runs all workflows to build and test the code on various Linux +# flavors, as well as on MacOS and Windows, on a scheduled basis, on merge into +# the 'develop' or 'release*' branches, or when requested manually. Upon +# successful completion, it also uploads the built libxrpl package to the Conan +# remote. name: Trigger on: @@ -11,7 +10,6 @@ on: branches: - "develop" - "release*" - - "master" paths: # These paths are unique to `on-trigger.yml`. - ".github/workflows/on-trigger.yml" @@ -70,10 +68,10 @@ jobs: with: # Enable ccache only for events targeting the XRPLF repository, since # other accounts will not have access to our remote cache storage. - # However, we do not enable ccache for events targeting the master or a - # release branch, to protect against the rare case that the output - # produced by ccache is not identical to a regular compilation. - ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !(github.base_ref == 'master' || startsWith(github.base_ref, 'release')) }} + # However, we do not enable ccache for events targeting a release branch, + # to protect against the rare case that the output produced by ccache is + # not identical to a regular compilation. + ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !startsWith(github.ref, 'refs/heads/release') }} os: ${{ matrix.os }} strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }} secrets: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 00754e5eae..6b8fd9955e 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -3,7 +3,9 @@ name: Run pre-commit hooks on: pull_request: push: - branches: [develop, release, master] + branches: + - "develop" + - "release*" workflow_dispatch: jobs: From 5e808794d875b9ea3fe894d17995a6f348dea148 Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Wed, 21 Jan 2026 14:19:53 +0000 Subject: [PATCH 079/105] Limit reply size on `TMGetObjectByHash` queries (#6110) `PeerImp` processes `TMGetObjectByHash` queries with an unbounded per-request loop, which performs a `NodeStore` fetch and then appends retrieved data to the reply for each queried object without a local count cap or reply-byte budget. However, the `Nodestore` fetches are expensive when high in numbers, which might slow down the process overall. Hence this code change adds an upper cap on the response size. --- .../scripts/levelization/results/ordering.txt | 1 + src/test/overlay/TMGetObjectByHash_test.cpp | 211 ++++++++++++++++++ src/xrpld/overlay/detail/PeerImp.cpp | 14 +- 3 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 src/test/overlay/TMGetObjectByHash_test.cpp diff --git a/.github/scripts/levelization/results/ordering.txt b/.github/scripts/levelization/results/ordering.txt index c9c65fb0dd..8d17e1167f 100644 --- a/.github/scripts/levelization/results/ordering.txt +++ b/.github/scripts/levelization/results/ordering.txt @@ -104,6 +104,7 @@ test.overlay > xrpl.basics test.overlay > xrpld.app test.overlay > xrpld.overlay test.overlay > xrpld.peerfinder +test.overlay > xrpl.nodestore test.overlay > xrpl.protocol test.overlay > xrpl.shamap test.peerfinder > test.beast diff --git a/src/test/overlay/TMGetObjectByHash_test.cpp b/src/test/overlay/TMGetObjectByHash_test.cpp new file mode 100644 index 0000000000..71a485416d --- /dev/null +++ b/src/test/overlay/TMGetObjectByHash_test.cpp @@ -0,0 +1,211 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace xrpl { +namespace test { + +using namespace jtx; + +/** + * Test for TMGetObjectByHash reply size limiting. + * + * This verifies the fix that limits TMGetObjectByHash replies to + * Tuning::hardMaxReplyNodes to prevent excessive memory usage and + * potential DoS attacks from peers requesting large numbers of objects. + */ +class TMGetObjectByHash_test : public beast::unit_test::suite +{ + using middle_type = boost::beast::tcp_stream; + using stream_type = boost::beast::ssl_stream; + using socket_type = boost::asio::ip::tcp::socket; + using shared_context = std::shared_ptr; + /** + * Test peer that captures sent messages for verification. + */ + class PeerTest : public PeerImp + { + public: + PeerTest( + Application& app, + std::shared_ptr const& slot, + http_request_type&& request, + PublicKey const& publicKey, + ProtocolVersion protocol, + Resource::Consumer consumer, + std::unique_ptr&& stream_ptr, + OverlayImpl& overlay) + : PeerImp( + app, + id_++, + slot, + std::move(request), + publicKey, + protocol, + consumer, + std::move(stream_ptr), + overlay) + { + } + + ~PeerTest() = default; + + void + run() override + { + } + + void + send(std::shared_ptr const& m) override + { + lastSentMessage_ = m; + } + + std::shared_ptr + getLastSentMessage() const + { + return lastSentMessage_; + } + + static void + resetId() + { + id_ = 0; + } + + private: + inline static Peer::id_t id_ = 0; + std::shared_ptr lastSentMessage_; + }; + + shared_context context_{make_SSLContext("")}; + ProtocolVersion protocolVersion_{1, 7}; + + std::shared_ptr + createPeer(jtx::Env& env) + { + auto& overlay = dynamic_cast(env.app().overlay()); + boost::beast::http::request request; + auto stream_ptr = std::make_unique( + socket_type(env.app().getIOContext()), *context_); + + beast::IP::Endpoint local( + boost::asio::ip::make_address("172.1.1.1"), 51235); + beast::IP::Endpoint remote( + boost::asio::ip::make_address("172.1.1.2"), 51235); + + PublicKey key(std::get<0>(randomKeyPair(KeyType::ed25519))); + auto consumer = overlay.resourceManager().newInboundEndpoint(remote); + auto [slot, _] = overlay.peerFinder().new_inbound_slot(local, remote); + + auto peer = std::make_shared( + env.app(), + slot, + std::move(request), + key, + protocolVersion_, + consumer, + std::move(stream_ptr), + overlay); + + overlay.add_active(peer); + return peer; + } + + std::shared_ptr + createRequest(size_t const numObjects, Env& env) + { + // Store objects in the NodeStore that will be found during the query + auto& nodeStore = env.app().getNodeStore(); + + // Create and store objects + std::vector hashes; + hashes.reserve(numObjects); + for (int i = 0; i < numObjects; ++i) + { + uint256 hash(xrpl::sha512Half(i)); + hashes.push_back(hash); + + Blob data(100, static_cast(i % 256)); + nodeStore.store( + hotLEDGER, + std::move(data), + hash, + nodeStore.earliestLedgerSeq()); + } + + // Create a request with more objects than hardMaxReplyNodes + auto request = std::make_shared(); + request->set_type(protocol::TMGetObjectByHash_ObjectType_otLEDGER); + request->set_query(true); + + for (int i = 0; i < numObjects; ++i) + { + auto object = request->add_objects(); + object->set_hash(hashes[i].data(), hashes[i].size()); + object->set_ledgerseq(i); + } + return request; + } + + /** + * Test that reply is limited to hardMaxReplyNodes when more objects + * are requested than the limit allows. + */ + void + testReplyLimit(size_t const numObjects, int const expectedReplySize) + { + testcase("Reply Limit"); + + Env env(*this); + PeerTest::resetId(); + + auto peer = createPeer(env); + + auto request = createRequest(numObjects, env); + // Call the onMessage handler + peer->onMessage(request); + + // Verify that a reply was sent + auto sentMessage = peer->getLastSentMessage(); + BEAST_EXPECT(sentMessage != nullptr); + + // Parse the reply message + auto const& buffer = + sentMessage->getBuffer(compression::Compressed::Off); + + BEAST_EXPECT(buffer.size() > 6); + // Skip the message header (6 bytes: 4 for size, 2 for type) + protocol::TMGetObjectByHash reply; + BEAST_EXPECT( + reply.ParseFromArray(buffer.data() + 6, buffer.size() - 6) == true); + + // Verify the reply is limited to expectedReplySize + BEAST_EXPECT(reply.objects_size() == expectedReplySize); + } + + void + run() override + { + int const limit = static_cast(Tuning::hardMaxReplyNodes); + testReplyLimit(limit + 1, limit); + testReplyLimit(limit, limit); + testReplyLimit(limit - 1, limit - 1); + } +}; + +BEAST_DEFINE_TESTSUITE(TMGetObjectByHash, overlay, xrpl); + +} // namespace test +} // namespace xrpl diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index 53237ed3ae..b64227288c 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -1351,8 +1351,8 @@ PeerImp::handleTransaction( { // If we've never been in synch, there's nothing we can do // with a transaction - JLOG(p_journal_.debug()) << "Ignoring incoming transaction: " - << "Need network ledger"; + JLOG(p_journal_.debug()) + << "Ignoring incoming transaction: Need network ledger"; return; } @@ -2618,6 +2618,16 @@ PeerImp::onMessage(std::shared_ptr const& m) newObj.set_ledgerseq(obj.ledgerseq()); // VFALCO NOTE "seq" in the message is obsolete + + // Check if by adding this object, reply has reached its + // limit + if (reply.objects_size() >= Tuning::hardMaxReplyNodes) + { + fee_.update( + Resource::feeModerateBurdenPeer, + " Reply limit reached. Truncating reply."); + break; + } } } } From a37c5560798cbe186c63c464bfc206cefb67ecd8 Mon Sep 17 00:00:00 2001 From: Bart Date: Wed, 21 Jan 2026 17:31:44 -0500 Subject: [PATCH 080/105] ci: Upload Conan recipe for merges into develop and commits to release (#6235) This change uploads the `libxrpl` library as a Conan recipe to our remote when (i) merging into the `develop` branch, (ii) committing to a PR that targets a `release*` branch, and (iii) a versioned tag is applied. Clio is only notified in the second case. The user and channel are no longer used when uploading the recipe. Specific changes are: * A `generate-version` action is added, which extracts the build version from `BuildInfo.cpp` and appends the short 7-character commit hash to it for merges into the `develop` branch and for commits to a PR that targets a `release*` branch. When a tag is applied, however, the tag itself is used as the version. This functionality has been turned into a separate action as we will use the same versioning logic for creating .rpm and .deb packages, as well as Docker images. * An `upload-recipe` action is added, which calls the `generate-version` action and further handles the uploading of the recipe to Conan. * This action is called by both the `on-pr` and `on-trigger` workflows, and a new `on-tag` workflow. The reason for this change is that we have downstream uses for the `libxrpl` library, but currently only upload the recipe to check for compatibility with Clio when making commits to a PR that targets the release branch. --- .github/actions/generate-version/action.yml | 41 +++++++++ .github/actions/setup-conan/action.yml | 12 +-- .github/workflows/on-pr.yml | 39 +++++++-- .github/workflows/on-tag.yml | 25 ++++++ .github/workflows/on-trigger.yml | 15 +++- .github/workflows/reusable-notify-clio.yml | 91 -------------------- .github/workflows/reusable-upload-recipe.yml | 78 +++++++++++++++++ .github/workflows/upload-conan-deps.yml | 4 +- 8 files changed, 194 insertions(+), 111 deletions(-) create mode 100644 .github/actions/generate-version/action.yml create mode 100644 .github/workflows/on-tag.yml delete mode 100644 .github/workflows/reusable-notify-clio.yml create mode 100644 .github/workflows/reusable-upload-recipe.yml diff --git a/.github/actions/generate-version/action.yml b/.github/actions/generate-version/action.yml new file mode 100644 index 0000000000..f0a63f02df --- /dev/null +++ b/.github/actions/generate-version/action.yml @@ -0,0 +1,41 @@ +name: Generate build version number +description: "Generate build version number." + +outputs: + version: + description: "The generated build version number." + value: ${{ steps.version.outputs.version }} + +runs: + using: composite + steps: + # When a tag is pushed, the version is used as-is. + - name: Generate version for tag event + if: ${{ github.event_name == 'tag' }} + shell: bash + env: + VERSION: ${{ github.ref_name }} + run: echo "VERSION=${VERSION}" >> "${GITHUB_ENV}" + + # When a tag is not pushed, then the version is extracted from the + # BuildInfo.cpp file and the shortened commit hash appended to it. + - name: Generate version for non-tag event + if: ${{ github.event_name != 'tag' }} + shell: bash + run: | + echo 'Extracting version from BuildInfo.cpp.' + VERSION="$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" + if [[ -z "${VERSION}" ]]; then + echo 'Unable to extract version from BuildInfo.cpp.' + exit 1 + fi + + echo 'Appending shortened commit hash to version.' + VERSION="${VERSION}-${COMMIT_HASH:0:7}" + + echo "VERSION=${VERSION}" >> "${GITHUB_ENV}" + + - name: Output version + id: version + shell: bash + run: echo "version=${VERSION}" >> "${GITHUB_OUTPUT}" diff --git a/.github/actions/setup-conan/action.yml b/.github/actions/setup-conan/action.yml index dedf53f109..37956c5f21 100644 --- a/.github/actions/setup-conan/action.yml +++ b/.github/actions/setup-conan/action.yml @@ -2,11 +2,11 @@ name: Setup Conan description: "Set up Conan configuration, profile, and remote." inputs: - conan_remote_name: + remote_name: description: "The name of the Conan remote to use." required: false default: xrplf - conan_remote_url: + remote_url: description: "The URL of the Conan endpoint to use." required: false default: https://conan.ripplex.io @@ -36,11 +36,11 @@ runs: - name: Set up Conan remote shell: bash env: - CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }} - CONAN_REMOTE_URL: ${{ inputs.conan_remote_url }} + REMOTE_NAME: ${{ inputs.remote_name }} + REMOTE_URL: ${{ inputs.remote_url }} run: | - echo "Adding Conan remote '${CONAN_REMOTE_NAME}' at '${CONAN_REMOTE_URL}'." - conan remote add --index 0 --force "${CONAN_REMOTE_NAME}" "${CONAN_REMOTE_URL}" + echo "Adding Conan remote '${REMOTE_NAME}' at '${REMOTE_URL}'." + conan remote add --index 0 --force "${REMOTE_NAME}" "${REMOTE_URL}" echo 'Listing Conan remotes.' conan remote list diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index dad211f94f..61639485d9 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -1,7 +1,8 @@ # This workflow runs all workflows to check, build and test the project on # various Linux flavors, as well as on MacOS and Windows, on every push to a # user branch. However, it will not run if the pull request is a draft unless it -# has the 'DraftRunCI' label. +# has the 'DraftRunCI' label. For commits to PRs that target a release branch, +# it also uploads the libxrpl recipe to the Conan remote. name: PR on: @@ -53,7 +54,6 @@ jobs: .github/scripts/rename/** .github/workflows/reusable-check-levelization.yml .github/workflows/reusable-check-rename.yml - .github/workflows/reusable-notify-clio.yml .github/workflows/on-pr.yml # Keep the paths below in sync with those in `on-trigger.yml`. @@ -66,6 +66,7 @@ jobs: .github/workflows/reusable-build-test.yml .github/workflows/reusable-strategy-matrix.yml .github/workflows/reusable-test.yml + .github/workflows/reusable-upload-recipe.yml .codecov.yml cmake/** conan/** @@ -121,22 +122,42 @@ jobs: secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - notify-clio: + upload-recipe: needs: - should-run - build-test - if: ${{ needs.should-run.outputs.go == 'true' && startsWith(github.ref, 'refs/heads/release') }} - uses: ./.github/workflows/reusable-notify-clio.yml + # Only run when committing to a PR that targets a release branch in the + # XRPLF repository. + if: ${{ github.repository_owner == 'XRPLF' && needs.should-run.outputs.go == 'true' && startsWith(github.ref, 'refs/heads/release') }} + uses: ./.github/workflows/reusable-upload-recipe.yml secrets: - clio_notify_token: ${{ secrets.CLIO_NOTIFY_TOKEN }} - conan_remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }} - conan_remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }} + remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }} + remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }} + + notify-clio: + needs: upload-recipe + runs-on: ubuntu-latest + steps: + # Notify the Clio repository about the newly proposed release version, so + # it can be checked for compatibility before the release is actually made. + - name: Notify Clio + env: + GH_TOKEN: ${{ secrets.CLIO_NOTIFY_TOKEN }} + PR_URL: ${{ github.event.pull_request.html_url }} + run: | + gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \ + -F "client_payload[ref]=${{ needs.upload-recipe.outputs.recipe_ref }}" \ + -F "client_payload[pr_url]=${PR_URL}" passed: if: failure() || cancelled() needs: - - build-test - check-levelization + - check-rename + - build-test + - upload-recipe + - notify-clio runs-on: ubuntu-latest steps: - name: Fail diff --git a/.github/workflows/on-tag.yml b/.github/workflows/on-tag.yml new file mode 100644 index 0000000000..c6361b4016 --- /dev/null +++ b/.github/workflows/on-tag.yml @@ -0,0 +1,25 @@ +# This workflow uploads the libxrpl recipe to the Conan remote when a versioned +# tag is pushed. +name: Tag + +on: + push: + tags: + - "v*" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +jobs: + upload-recipe: + # Only run when a tag is pushed to the XRPLF repository. + if: ${{ github.repository_owner == 'XRPLF' }} + uses: ./.github/workflows/reusable-upload-recipe.yml + secrets: + remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }} + remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }} diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml index ef7bf41fa2..7f54a9977e 100644 --- a/.github/workflows/on-trigger.yml +++ b/.github/workflows/on-trigger.yml @@ -1,8 +1,7 @@ # This workflow runs all workflows to build and test the code on various Linux # flavors, as well as on MacOS and Windows, on a scheduled basis, on merge into -# the 'develop' or 'release*' branches, or when requested manually. Upon -# successful completion, it also uploads the built libxrpl package to the Conan -# remote. +# the 'develop' or 'release*' branches, or when requested manually. Upon pushes +# to the develop branch it also uploads the libxrpl recipe to the Conan remote. name: Trigger on: @@ -24,6 +23,7 @@ on: - ".github/workflows/reusable-build-test.yml" - ".github/workflows/reusable-strategy-matrix.yml" - ".github/workflows/reusable-test.yml" + - ".github/workflows/reusable-upload-recipe.yml" - ".codecov.yml" - "cmake/**" - "conan/**" @@ -76,3 +76,12 @@ jobs: strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }} secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + upload-recipe: + needs: build-test + # Only run when pushing to the develop branch in the XRPLF repository. + if: ${{ github.repository_owner == 'XRPLF' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }} + uses: ./.github/workflows/reusable-upload-recipe.yml + secrets: + remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }} + remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }} diff --git a/.github/workflows/reusable-notify-clio.yml b/.github/workflows/reusable-notify-clio.yml deleted file mode 100644 index 0941d5f2e3..0000000000 --- a/.github/workflows/reusable-notify-clio.yml +++ /dev/null @@ -1,91 +0,0 @@ -# This workflow exports the built libxrpl package to the Conan remote on a -# a channel named after the pull request, and notifies the Clio repository about -# the new version so it can check for compatibility. -name: Notify Clio - -# This workflow can only be triggered by other workflows. -on: - workflow_call: - inputs: - conan_remote_name: - description: "The name of the Conan remote to use." - required: false - type: string - default: xrplf - conan_remote_url: - description: "The URL of the Conan endpoint to use." - required: false - type: string - default: https://conan.ripplex.io - secrets: - clio_notify_token: - description: "The GitHub token to notify Clio about new versions." - required: true - conan_remote_username: - description: "The username for logging into the Conan remote." - required: true - conan_remote_password: - description: "The password for logging into the Conan remote." - required: true - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-clio - cancel-in-progress: true - -defaults: - run: - shell: bash - -jobs: - upload: - if: ${{ github.event.pull_request.head.repo.full_name == github.repository }} - runs-on: ubuntu-latest - container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13-sha-5dd7158 - steps: - - name: Checkout repository - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - - name: Generate outputs - id: generate - env: - PR_NUMBER: ${{ github.event.pull_request.number }} - run: | - echo 'Generating user and channel.' - echo "user=clio" >> "${GITHUB_OUTPUT}" - echo "channel=pr_${PR_NUMBER}" >> "${GITHUB_OUTPUT}" - echo 'Extracting version.' - echo "version=$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" >> "${GITHUB_OUTPUT}" - - name: Calculate conan reference - id: conan_ref - run: | - echo "conan_ref=${{ steps.generate.outputs.version }}@${{ steps.generate.outputs.user }}/${{ steps.generate.outputs.channel }}" >> "${GITHUB_OUTPUT}" - - name: Set up Conan - uses: ./.github/actions/setup-conan - with: - conan_remote_name: ${{ inputs.conan_remote_name }} - conan_remote_url: ${{ inputs.conan_remote_url }} - - name: Log into Conan remote - env: - CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }} - run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}" - - name: Upload package - env: - CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }} - run: | - conan export --user=${{ steps.generate.outputs.user }} --channel=${{ steps.generate.outputs.channel }} . - conan upload --confirm --check --remote="${CONAN_REMOTE_NAME}" xrpl/${{ steps.conan_ref.outputs.conan_ref }} - outputs: - conan_ref: ${{ steps.conan_ref.outputs.conan_ref }} - - notify: - needs: upload - runs-on: ubuntu-latest - steps: - - name: Notify Clio - env: - GH_TOKEN: ${{ secrets.clio_notify_token }} - PR_URL: ${{ github.event.pull_request.html_url }} - run: | - gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \ - /repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \ - -F "client_payload[conan_ref]=${{ needs.upload.outputs.conan_ref }}" \ - -F "client_payload[pr_url]=${PR_URL}" diff --git a/.github/workflows/reusable-upload-recipe.yml b/.github/workflows/reusable-upload-recipe.yml new file mode 100644 index 0000000000..9b25481f6a --- /dev/null +++ b/.github/workflows/reusable-upload-recipe.yml @@ -0,0 +1,78 @@ +# This workflow exports the built libxrpl package to the Conan remote. +name: Upload Conan recipe + +# This workflow can only be triggered by other workflows. +on: + workflow_call: + inputs: + remote_name: + description: "The name of the Conan remote to use." + required: false + type: string + default: xrplf + remote_url: + description: "The URL of the Conan endpoint to use." + required: false + type: string + default: https://conan.ripplex.io + + secrets: + remote_username: + description: "The username for logging into the Conan remote." + required: true + remote_password: + description: "The password for logging into the Conan remote." + required: true + + outputs: + recipe_ref: + description: "The Conan recipe reference ('name/version') that was uploaded." + value: ${{ jobs.upload.outputs.ref }} + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-upload-recipe + cancel-in-progress: true + +defaults: + run: + shell: bash + +jobs: + upload: + runs-on: ubuntu-latest + container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13-sha-5dd7158 + steps: + - name: Checkout repository + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + + - name: Generate build version number + id: version + uses: ./.github/actions/generate-version + + - name: Determine recipe reference + id: ref + run: echo "ref=xrpl/${{ steps.version.outputs.version }}" >> "${GITHUB_OUTPUT}" + + - name: Set up Conan + uses: ./.github/actions/setup-conan + with: + remote_name: ${{ inputs.remote_name }} + remote_url: ${{ inputs.remote_url }} + + - name: Log into Conan remote + env: + REMOTE_NAME: ${{ inputs.remote_name }} + REMOTE_USERNAME: ${{ inputs.remote_username }} + REMOTE_PASSWORD: ${{ inputs.remote_password }} + run: conan remote login "${REMOTE_NAME}" "${REMOTE_USERNAME}" --password "${REMOTE_PASSWORD}" + + - name: Upload Conan recipe + env: + RECIPE_REF: ${{ steps.ref.outputs.ref }} + REMOTE_NAME: ${{ inputs.remote_name }} + run: | + conan export . + conan upload --confirm --check --remote="${REMOTE_NAME}" ${RECIPE_REF} + + outputs: + ref: ${{ steps.ref.outputs.ref }} diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml index 29ae95fce5..711354d490 100644 --- a/.github/workflows/upload-conan-deps.yml +++ b/.github/workflows/upload-conan-deps.yml @@ -86,8 +86,8 @@ jobs: - name: Setup Conan uses: ./.github/actions/setup-conan with: - conan_remote_name: ${{ env.CONAN_REMOTE_NAME }} - conan_remote_url: ${{ env.CONAN_REMOTE_URL }} + remote_name: ${{ env.CONAN_REMOTE_NAME }} + remote_url: ${{ env.CONAN_REMOTE_URL }} - name: Build dependencies uses: ./.github/actions/build-deps From 4cd6cc3e01eac7c6437163cfe2173739fbc2e35f Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 21 Jan 2026 23:52:22 +0000 Subject: [PATCH 081/105] fix: Include `` header in `Number.h` (#6254) The `Number.h` header file now has `std::reference_wrapper` from ``, but the include is missing, causing downstream build problems. This change adds the header. --- include/xrpl/basics/Number.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/xrpl/basics/Number.h b/include/xrpl/basics/Number.h index d1ef749784..2f467fb036 100644 --- a/include/xrpl/basics/Number.h +++ b/include/xrpl/basics/Number.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include From 4fd4e93b3ec3774d5d22c41ef8d98457f2107e04 Mon Sep 17 00:00:00 2001 From: Bart Date: Wed, 21 Jan 2026 19:17:05 -0500 Subject: [PATCH 082/105] ci: Add missing commit hash to Conan recipe version (#6256) During several iterations of development of https://github.com/XRPLF/rippled/pull/6235, the commit hash was supposed to be moved into the `run:` statement, but it slipped through the cracks and did not get added. This change adds the commit hash as suffix to the Conan recipe version. --- .github/actions/generate-version/action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/generate-version/action.yml b/.github/actions/generate-version/action.yml index f0a63f02df..4f176fcb91 100644 --- a/.github/actions/generate-version/action.yml +++ b/.github/actions/generate-version/action.yml @@ -31,7 +31,8 @@ runs: fi echo 'Appending shortened commit hash to version.' - VERSION="${VERSION}-${COMMIT_HASH:0:7}" + SHA='${{ github.sha }}' + VERSION="${VERSION}-${SHA:0:7}" echo "VERSION=${VERSION}" >> "${GITHUB_ENV}" From 211054baff6a344b8eda65c07b6a25dba8f42284 Mon Sep 17 00:00:00 2001 From: David Fuelling Date: Wed, 21 Jan 2026 17:55:56 -0700 Subject: [PATCH 083/105] docs: Update Ripple Bug Bounty public key (#6258) The Ripple Bug Bounty program recently changed the public keys that security researchers can use to encrypt vulnerabilities and messages for submission to the program. This information was updated on https://ripple.com/legal/bug-bounty/ and this PR updates the `SECURITY.md` to align. --- SECURITY.md | 113 ++++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 62 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 18eec312ed..1be412ae2a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -78,72 +78,61 @@ To report a qualifying bug, please send a detailed report to: | Email Address | bugs@ripple.com | | :-----------: | :-------------------------------------------------- | -| Short Key ID | `0xC57929BE` | -| Long Key ID | `0xCD49A0AFC57929BE` | -| Fingerprint | `24E6 3B02 37E0 FA9C 5E96 8974 CD49 A0AF C579 29BE` | +| Short Key ID | `0xA9F514E0` | +| Long Key ID | `0xD900855AA9F514E0` | +| Fingerprint | `B72C 0654 2F2A E250 2763 A268 D900 855A A9F5 14E0` | The full PGP key for this address, which is also available on several key servers (e.g. on [keyserver.ubuntu.com](https://keyserver.ubuntu.com)), is: ``` -----BEGIN PGP PUBLIC KEY BLOCK----- -mQINBFUwGHYBEAC0wpGpBPkd8W1UdQjg9+cEFzeIEJRaoZoeuJD8mofwI5Ejnjdt -kCpUYEDal0ygkKobu8SzOoATcDl18iCrScX39VpTm96vISFZMhmOryYCIp4QLJNN -4HKc2ZdBj6W4igNi6vj5Qo6JMyGpLY2mz4CZskbt0TNuUxWrGood+UrCzpY8x7/N -a93fcvNw+prgCr0rCH3hAPmAFfsOBbtGzNnmq7xf3jg5r4Z4sDiNIF1X1y53DAfV -rWDx49IKsuCEJfPMp1MnBSvDvLaQ2hKXs+cOpx1BCZgHn3skouEUxxgqbtTzBLt1 -xXpmuijsaltWngPnGO7mOAzbpZSdBm82/Emrk9bPMuD0QaLQjWr7HkTSUs6ZsKt4 -7CLPdWqxyY/QVw9UaxeHEtWGQGMIQGgVJGh1fjtUr5O1sC9z9jXcQ0HuIHnRCTls -GP7hklJmfH5V4SyAJQ06/hLuEhUJ7dn+BlqCsT0tLmYTgZYNzNcLHcqBFMEZHvHw -9GENMx/tDXgajKql4bJnzuTK0iGU/YepanANLd1JHECJ4jzTtmKOus9SOGlB2/l1 -0t0ADDYAS3eqOdOcUvo9ElSLCI5vSVHhShSte/n2FMWU+kMUboTUisEG8CgQnrng -g2CvvQvqDkeOtZeqMcC7HdiZS0q3LJUWtwA/ViwxrVlBDCxiTUXCotyBWwARAQAB -tDBSaXBwbGUgTGFicyBCdWcgQm91bnR5IFByb2dyYW0gPGJ1Z3NAcmlwcGxlLmNv -bT6JAjcEEwEKACEFAlUwGHYCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ -zUmgr8V5Kb6R0g//SwY/mVJY59k87iL26/KayauSoOcz7xjcST26l4ZHVVX85gOY -HYZl8k0+m8X3zxeYm9a3QAoAml8sfoaFRFQP8ynnefRrLUPaZ2MjbJ0SACMwZNef -T6o7Mi8LBAaiNZdYVyIfX1oM6YXtqYkuJdav6ZCyvVYqc9OvMJPY2ZzJYuI/ZtvQ -/lTndxCeg9ALNX/iezOLGdfMpf4HuIFVwcPPlwGi+HDlB9/bggDEHC8z434SXVFc -aQatXAPcDkjMUweU7y0CZtYEj00HITd4pSX6MqGiHrxlDZTqinCOPs1Ieqp7qufs -MzlM6irLGucxj1+wa16ieyYvEtGaPIsksUKkywx0O7cf8N2qKg+eIkUk6O0Uc6eO -CszizmiXIXy4O6OiLlVHGKkXHMSW9Nwe9GE95O8G9WR8OZCEuDv+mHPAutO+IjdP -PDAAUvy+3XnkceO+HGWRpVvJZfFP2YH4A33InFL5yqlJmSoR/yVingGLxk55bZDM -+HYGR3VeMb8Xj1rf/02qERsZyccMCFdAvKDbTwmvglyHdVLu5sPmktxbBYiemfyJ -qxMxmYXCc9S0hWrWZW7edktBa9NpE58z1mx+hRIrDNbS2sDHrib9PULYCySyVYcF -P+PWEe1CAS5jqkR2ker5td2/pHNnJIycynBEs7l6zbc9fu+nktFJz0q2B+GJAhwE -EAEKAAYFAlUwGaQACgkQ+tiY1qQ2QkjMFw//f2hNY3BPNe+1qbhzumMDCnbTnGif -kLuAGl9OKt81VHG1f6RnaGiLpR696+6Ja45KzH15cQ5JJl5Bgs1YkR/noTGX8IAD -c70eNwiFu8JXTaaeeJrsmFkF9Tueufb364risYkvPP8tNUD3InBFEZT3WN7JKwix -coD4/BwekUwOZVDd/uCFEyhlhZsROxdKNisNo3VtAq2s+3tIBAmTrriFUl0K+ZC5 -zgavcpnPN57zMtW9aK+VO3wXqAKYLYmtgxkVzSLUZt2M7JuwOaAdyuYWAneKZPCu -1AXkmyo+d84sd5mZaKOr5xArAFiNMWPUcZL4rkS1Fq4dKtGAqzzR7a7hWtA5o27T -6vynuxZ1n0PPh0er2O/zF4znIjm5RhTlfjp/VmhZdQfpulFEQ/dMxxGkQ9z5IYbX -mTlSDbCSb+FMsanRBJ7Drp5EmBIudVGY6SHI5Re1RQiEh7GoDfUMUwZO+TVDII5R -Ra7WyuimYleJgDo/+7HyfuIyGDaUCVj6pwVtYtYIdOI3tTw1R1Mr0V8yaNVnJghL -CHcEJQL+YHSmiMM3ySil3O6tm1By6lFz8bVe/rgG/5uklQrnjMR37jYboi1orCC4 -yeIoQeV0ItlxeTyBwYIV/o1DBNxDevTZvJabC93WiGLw2XFjpZ0q/9+zI2rJUZJh -qxmKP+D4e27lCI65Ag0EVTAYdgEQAMvttYNqeRNBRpSX8fk45WVIV8Fb21fWdwk6 -2SkZnJURbiC0LxQnOi7wrtii7DeFZtwM2kFHihS1VHekBnIKKZQSgGoKuFAQMGyu -a426H4ZsSmA9Ufd7kRbvdtEcp7/RTAanhrSL4lkBhaKJrXlxBJ27o3nd7/rh7r3a -OszbPY6DJ5bWClX3KooPTDl/RF2lHn+fweFk58UvuunHIyo4BWJUdilSXIjLun+P -Qaik4ZAsZVwNhdNz05d+vtai4AwbYoO7adboMLRkYaXSQwGytkm+fM6r7OpXHYuS -cR4zB/OK5hxCVEpWfiwN71N2NMvnEMaWd/9uhqxJzyvYgkVUXV9274TUe16pzXnW -ZLfmitjwc91e7mJBBfKNenDdhaLEIlDRwKTLj7k58f9srpMnyZFacntu5pUMNblB -cjXwWxz5ZaQikLnKYhIvrIEwtWPyjqOzNXNvYfZamve/LJ8HmWGCKao3QHoAIDvB -9XBxrDyTJDpxbog6Qu4SY8AdgVlan6c/PsLDc7EUegeYiNTzsOK+eq3G5/E92eIu -TsUXlciypFcRm1q8vLRr+HYYe2mJDo4GetB1zLkAFBcYJm/x9iJQbu0hn5NxJvZO -R0Y5nOJQdyi+muJzKYwhkuzaOlswzqVXkq/7+QCjg7QsycdcwDjiQh3OrsgXHrwl -M7gyafL9ABEBAAGJAh8EGAEKAAkFAlUwGHYCGwwACgkQzUmgr8V5Kb50BxAAhj9T -TwmNrgRldTHszj+Qc+v8RWqV6j+R+zc0cn5XlUa6XFaXI1OFFg71H4dhCPEiYeN0 -IrnocyMNvCol+eKIlPKbPTmoixjQ4udPTR1DC1Bx1MyW5FqOrsgBl5t0e1VwEViM -NspSStxu5Hsr6oWz2GD48lXZWJOgoL1RLs+uxjcyjySD/em2fOKASwchYmI+ezRv -plfhAFIMKTSCN2pgVTEOaaz13M0U+MoprThqF1LWzkGkkC7n/1V1f5tn83BWiagG -2N2Q4tHLfyouzMUKnX28kQ9sXfxwmYb2sA9FNIgxy+TdKU2ofLxivoWT8zS189z/ -Yj9fErmiMjns2FzEDX+bipAw55X4D/RsaFgC+2x2PDbxeQh6JalRA2Wjq32Ouubx -u+I4QhEDJIcVwt9x6LPDuos1F+M5QW0AiUhKrZJ17UrxOtaquh/nPUL9T3l2qPUn -1ChrZEEEhHO6vA8+jn0+cV9n5xEz30Str9iHnDQ5QyR5LyV4UBPgTdWyQzNVKA69 -KsSr9lbHEtQFRzGuBKwt6UlSFv9vPWWJkJit5XDKAlcKuGXj0J8OlltToocGElkF -+gEBZfoOWi/IBjRLrFW2cT3p36DTR5O1Ud/1DLnWRqgWNBLrbs2/KMKE6EnHttyD -7Tz8SQkuxltX/yBXMV3Ddy0t6nWV2SZEfuxJAQI= -=spg4 +mQINBGkSZAQBEACprU199OhgdsOsygNjiQV4msuN3vDOUooehL+NwfsGfW79Tbqq +Q2u7uQ3NZjW+M2T4nsDwuhkr7pe7xSReR5W8ssaczvtUyxkvbMClilcgZ2OSCAuC +N9tzJsqOqkwBvXoNXkn//T2jnPz0ZU2wSF+NrEibq5FeuyGdoX3yXXBxq9pW9HzK +HkQll63QSl6BzVSGRQq+B6lGgaZGLwf3mzmIND9Z5VGLNK2jKynyz9z091whNG/M +kV+E7/r/bujHk7WIVId07G5/COTXmSr7kFnNEkd2Umw42dkgfiNKvlmJ9M7c1wLK +KbL9Eb4ADuW6rRc5k4s1e6GT8R4/VPliWbCl9SE32hXH8uTkqVIFZP2eyM5WRRHs +aKzitkQG9UK9gcb0kdgUkxOvvgPHAe5IuZlcHFzU4y0dBbU1VEFWVpiLU0q+IuNw +5BRemeHc59YNsngkmAZ+/9zouoShRusZmC8Wzotv75C2qVBcjijPvmjWAUz0Zunm +Lsr+O71vqHE73pERjD07wuD/ISjiYRYYE/bVrXtXLZijC7qAH4RE3nID+2ojcZyO +/2jMQvt7un56RsGH4UBHi3aBHi9bUoDGCXKiQY981cEuNaOxpou7Mh3x/ONzzSvk +sTV6nl1LOZHykN1JyKwaNbTSAiuyoN+7lOBqbV04DNYAHL88PrT21P83aQARAQAB +tB1SaXBwbGUgTGFicyA8YnVnc0ByaXBwbGUuY29tPokCTgQTAQgAOBYhBLcsBlQv +KuJQJ2OiaNkAhVqp9RTgBQJpEmQEAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA +AAoJENkAhVqp9RTgBzgP/i7y+aDWl1maig1XMdyb+o0UGusumFSW4Hmj278wlKVv +usgLPihYgHE0PKrv6WRyKOMC1tQEcYYN93M+OeQ1vFhS2YyURq6RCMmh4zq/awXG +uZbG36OURB5NH8lGBOHiN/7O+nY0CgenBT2JWm+GW3nEOAVOVm4+r5GlpPlv+Dp1 +NPBThcKXFMnH73++NpSQoDzTfRYHPxhDAX3jkLi/moXfSanOLlR6l94XNNN0jBHW +Quao0rzf4WSXq9g6AS224xhAA5JyIcFl8TX7hzj5HaFn3VWo3COoDu4U7H+BM0fl +85yqiMQypp7EhN2gxpMMWaHY5TFM85U/bFXFYfEgihZ4/gt4uoIzsNI9jlX7mYvG +KFdDij+oTlRsuOxdIy60B3dKcwOH9nZZCz0SPsN/zlRWgKzK4gDKdGhFkU9OlvPu +94ZqscanoiWKDoZkF96+sjgfjkuHsDK7Lwc1Xi+T4drHG/3aVpkYabXox+lrKB/S +yxZjeqOIQzWPhnLgCaLyvsKo5hxKzL0w3eURu8F3IS7RgOOlljv4M+Me9sEVcdNV +aN3/tQwbaomSX1X5D5YXqhBwC3rU3wXwamsscRTGEpkV+JCX6KUqGP7nWmxCpAly +FL05XuOd5SVHJjXLeuje0JqLUpN514uL+bThWwDbDTdAdwW3oK/2WbXz7IfJRLBj +uQINBGkSZAQBEADdI3SL2F72qkrgFqXWE6HSRBu9bsAvTE5QrRPWk7ux6at537r4 +S4sIw2dOwLvbyIrDgKNq3LQ5wCK88NO/NeCOFm4AiCJSl3pJHXYnTDoUxTrrxx+o +vSRI4I3fHEql/MqzgiAb0YUezjgFdh3vYheMPp/309PFbOLhiFqEcx80Mx5h06UH +gDzu1qNj3Ec+31NLic5zwkrAkvFvD54d6bqYR3SEgMau6aYEewpGHbWBi2pLqSi2 +lQcAeOFixqGpTwDmAnYR8YtjBYepy0MojEAdTHcQQlOYSDk4q4elG+io2N8vECfU +rD6ORecN48GXdZINYWTAdslrUeanmBdgQrYkSpce8TSghgT9P01SNaXxmyaehVUO +lqI4pcg5G2oojAE8ncNS3TwDtt7daTaTC3bAdr4PXDVAzNAiewjMNZPB7xidkDGQ +Y4W1LxTMXyJVWxehYOH7tsbBRKninlfRnLgYzmtIbNRAAvNcsxU6ihv3AV0WFknN +YbSzotEv1Xq/5wk309x8zCDe+sP0cQicvbXafXmUzPAZzeqFg+VLFn7F9MP1WGlW +B1u7VIvBF1Mp9Nd3EAGBAoLRdRu+0dVWIjPTQuPIuD9cCatJA0wVaKUrjYbBMl88 +a12LixNVGeSFS9N7ADHx0/o7GNT6l88YbaLP6zggUHpUD/bR+cDN7vllIQARAQAB +iQI2BBgBCAAgFiEEtywGVC8q4lAnY6Jo2QCFWqn1FOAFAmkSZAQCGwwACgkQ2QCF +Wqn1FOAfAA/8CYq4p0p4bobY20CKEMsZrkBTFJyPDqzFwMeTjgpzqbD7Y3Qq5QCK +OBbvY02GWdiIsNOzKdBxiuam2xYP9WHZj4y7/uWEvT0qlPVmDFu+HXjoJ43oxwFd +CUp2gMuQ4cSL3X94VRJ3BkVL+tgBm8CNY0vnTLLOO3kum/R69VsGJS1JSGUWjNM+ +4qwS3mz+73xJu1HmERyN2RZF/DGIZI2PyONQQ6aH85G1Dd2ohu2/DBAkQAMBrPbj +FrbDaBLyFhODxU3kTWqnfLlaElSm2EGdIU2yx7n4BggEa//NZRMm5kyeo4vzhtlQ +YIVUMLAOLZvnEqDnsLKp+22FzNR/O+htBQC4lPywl53oYSALdhz1IQlcAC1ru5KR +XPzhIXV6IIzkcx9xNkEclZxmsuy5ERXyKEmLbIHAlzFmnrldlt2ZgXDtzaorLmxj +klKibxd5tF50qOpOivz+oPtFo7n+HmFa1nlVAMxlDCUdM0pEVeYDKI5zfVwalyhZ +NnjpakdZSXMwgc7NP/hH9buF35hKDp7EckT2y3JNYwHsDdy1icXN2q40XZw5tSIn +zkPWdu3OUY8PISohN6Pw4h0RH4ZmoX97E8sEfmdKaT58U4Hf2aAv5r9IWCSrAVqY +u5jvac29CzQR9Kal0A+8phHAXHNFD83SwzIC0syaT9ficAguwGH8X6Q= +=nGuD -----END PGP PUBLIC KEY BLOCK----- ``` From 68c9d5ca0f5329a96aebce642687ae4e08644cf5 Mon Sep 17 00:00:00 2001 From: Valentin Balaschenko <13349202+vlntb@users.noreply.github.com> Date: Thu, 22 Jan 2026 13:19:29 +0000 Subject: [PATCH 084/105] refactor: Enforce 15-char limit and simplify labels for thread naming (#6212) This change continues the thread naming work from #5691 and #5758, which enables more useful lock contention profiling by ensuring threads/jobs have short, stable, human-readable names (rather than being truncated/failing due to OS limits). This changes diagnostic naming only (thread names and job/load-event labels), not behavior. Specific modifications are: * Shortens all thread/job names used with `beast::setCurrentThreadName`, so the effective Linux thread name stays within the 15-character limit. * Removes per-ledger sequence numbers from job/thread names to avoid long labels. This improves aggregation in lock contention profiling for short-lived job executions. --- src/libxrpl/beast/core/CurrentThreadName.cpp | 6 + src/libxrpl/core/detail/Job.cpp | 2 +- .../beast/beast_CurrentThreadName_test.cpp | 15 +-- src/test/core/Coroutine_test.cpp | 10 +- src/xrpld/app/consensus/RCLConsensus.cpp | 6 +- src/xrpld/app/consensus/RCLValidations.cpp | 12 +- src/xrpld/app/ledger/ConsensusTransSetSF.cpp | 2 +- src/xrpld/app/ledger/OrderBookDB.cpp | 6 +- src/xrpld/app/ledger/detail/InboundLedger.cpp | 2 +- .../app/ledger/detail/InboundLedgers.cpp | 4 +- .../app/ledger/detail/LedgerDeltaAcquire.cpp | 4 +- src/xrpld/app/ledger/detail/LedgerMaster.cpp | 12 +- .../app/ledger/detail/LedgerReplayTask.cpp | 2 +- .../app/ledger/detail/SkipListAcquire.cpp | 2 +- .../app/ledger/detail/TransactionAcquire.cpp | 4 +- src/xrpld/app/main/Main.cpp | 3 +- src/xrpld/app/main/NodeStoreScheduler.cpp | 5 +- src/xrpld/app/misc/NetworkOPs.cpp | 23 ++-- src/xrpld/overlay/detail/PeerImp.cpp | 118 ++++++++---------- src/xrpld/rpc/detail/RPCSub.cpp | 2 +- 20 files changed, 107 insertions(+), 133 deletions(-) diff --git a/src/libxrpl/beast/core/CurrentThreadName.cpp b/src/libxrpl/beast/core/CurrentThreadName.cpp index e8f7b629a7..34e8603afa 100644 --- a/src/libxrpl/beast/core/CurrentThreadName.cpp +++ b/src/libxrpl/beast/core/CurrentThreadName.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -95,6 +96,11 @@ setCurrentThreadNameImpl(std::string_view name) std::cerr << "WARNING: Thread name \"" << name << "\" (length " << name.size() << ") exceeds maximum of " << maxThreadNameLength << " characters on Linux.\n"; + + XRPL_ASSERT( + false, + "beast::detail::setCurrentThreadNameImpl : Thread name exceeds " + "maximum length for Linux"); } #endif } diff --git a/src/libxrpl/core/detail/Job.cpp b/src/libxrpl/core/detail/Job.cpp index 3968c3ede4..358441010b 100644 --- a/src/libxrpl/core/detail/Job.cpp +++ b/src/libxrpl/core/detail/Job.cpp @@ -41,7 +41,7 @@ Job::queue_time() const void Job::doJob() { - beast::setCurrentThreadName("doJob: " + mName); + beast::setCurrentThreadName("j:" + mName); m_loadEvent->start(); m_loadEvent->setName(mName); diff --git a/src/test/beast/beast_CurrentThreadName_test.cpp b/src/test/beast/beast_CurrentThreadName_test.cpp index dc12883a63..918d426979 100644 --- a/src/test/beast/beast_CurrentThreadName_test.cpp +++ b/src/test/beast/beast_CurrentThreadName_test.cpp @@ -88,20 +88,15 @@ public: BEAST_EXPECT(stateB == 2); } #if BOOST_OS_LINUX - // On Linux, verify that thread names longer than 15 characters - // are truncated to 15 characters (the 16th character is reserved for - // the null terminator). + // On Linux, verify that thread names within the 15 character limit + // are set correctly (the 16th character is reserved for the null + // terminator). { testName( "123456789012345", - "123456789012345"); // 15 chars, no truncation - testName( - "1234567890123456", "123456789012345"); // 16 chars, truncated - testName( - "ThisIsAVeryLongThreadNameExceedingLimit", - "ThisIsAVeryLong"); // 39 chars, truncated + "123456789012345"); // 15 chars, maximum allowed testName("", ""); // empty name - testName("short", "short"); // short name, no truncation + testName("short", "short"); // short name } #endif } diff --git a/src/test/core/Coroutine_test.cpp b/src/test/core/Coroutine_test.cpp index 72a4c02434..761fd46915 100644 --- a/src/test/core/Coroutine_test.cpp +++ b/src/test/core/Coroutine_test.cpp @@ -56,7 +56,7 @@ public: gate g1, g2; std::shared_ptr c; env.app().getJobQueue().postCoro( - jtCLIENT, "Coroutine-Test", [&](auto const& cr) { + jtCLIENT, "CoroTest", [&](auto const& cr) { c = cr; g1.signal(); c->yield(); @@ -83,7 +83,7 @@ public: gate g; env.app().getJobQueue().postCoro( - jtCLIENT, "Coroutine-Test", [&](auto const& c) { + jtCLIENT, "CoroTest", [&](auto const& c) { c->post(); c->yield(); g.signal(); @@ -109,7 +109,7 @@ public: BEAST_EXPECT(*lv == -1); gate g; - jq.addJob(jtCLIENT, "LocalValue-Test", [&]() { + jq.addJob(jtCLIENT, "LocalValTest", [&]() { this->BEAST_EXPECT(*lv == -1); *lv = -2; this->BEAST_EXPECT(*lv == -2); @@ -120,7 +120,7 @@ public: for (int i = 0; i < N; ++i) { - jq.postCoro(jtCLIENT, "Coroutine-Test", [&, id = i](auto const& c) { + jq.postCoro(jtCLIENT, "CoroTest", [&, id = i](auto const& c) { a[id] = c; g.signal(); c->yield(); @@ -148,7 +148,7 @@ public: c->join(); } - jq.addJob(jtCLIENT, "LocalValue-Test", [&]() { + jq.addJob(jtCLIENT, "LocalValTest", [&]() { this->BEAST_EXPECT(*lv == -2); g.signal(); }); diff --git a/src/xrpld/app/consensus/RCLConsensus.cpp b/src/xrpld/app/consensus/RCLConsensus.cpp index 99cc140056..654c2a8990 100644 --- a/src/xrpld/app/consensus/RCLConsensus.cpp +++ b/src/xrpld/app/consensus/RCLConsensus.cpp @@ -119,9 +119,7 @@ RCLConsensus::Adaptor::acquireLedger(LedgerHash const& hash) acquiringLedger_ = hash; app_.getJobQueue().addJob( - jtADVANCE, - "getConsensusLedger1", - [id = hash, &app = app_, this]() { + jtADVANCE, "GetConsL1", [id = hash, &app = app_, this]() { JLOG(j_.debug()) << "JOB advanceLedger getConsensusLedger1 started"; app.getInboundLedgers().acquireAsync( @@ -420,7 +418,7 @@ RCLConsensus::Adaptor::onAccept( { app_.getJobQueue().addJob( jtACCEPT, - "acceptLedger", + "AcceptLedger", [=, this, cj = std::move(consensusJson)]() mutable { // Note that no lock is held or acquired during this job. // This is because generic Consensus guarantees that once a ledger diff --git a/src/xrpld/app/consensus/RCLValidations.cpp b/src/xrpld/app/consensus/RCLValidations.cpp index eb10765ba3..6438334106 100644 --- a/src/xrpld/app/consensus/RCLValidations.cpp +++ b/src/xrpld/app/consensus/RCLValidations.cpp @@ -122,13 +122,11 @@ RCLValidationsAdaptor::acquire(LedgerHash const& hash) Application* pApp = &app_; - app_.getJobQueue().addJob( - jtADVANCE, "getConsensusLedger2", [pApp, hash, this]() { - JLOG(j_.debug()) - << "JOB advanceLedger getConsensusLedger2 started"; - pApp->getInboundLedgers().acquireAsync( - hash, 0, InboundLedger::Reason::CONSENSUS); - }); + app_.getJobQueue().addJob(jtADVANCE, "GetConsL2", [pApp, hash, this]() { + JLOG(j_.debug()) << "JOB advanceLedger getConsensusLedger2 started"; + pApp->getInboundLedgers().acquireAsync( + hash, 0, InboundLedger::Reason::CONSENSUS); + }); return std::nullopt; } diff --git a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp index b52cee2927..6678ee6334 100644 --- a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp +++ b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp @@ -46,7 +46,7 @@ ConsensusTransSetSF::gotNode( "xrpl::ConsensusTransSetSF::gotNode : transaction hash " "match"); auto const pap = &app_; - app_.getJobQueue().addJob(jtTRANSACTION, "TXS->TXN", [pap, stx]() { + app_.getJobQueue().addJob(jtTRANSACTION, "TxsToTxn", [pap, stx]() { pap->getOPs().submitTransaction(stx); }); } diff --git a/src/xrpld/app/ledger/OrderBookDB.cpp b/src/xrpld/app/ledger/OrderBookDB.cpp index 47b04f3d2c..5963c00c5a 100644 --- a/src/xrpld/app/ledger/OrderBookDB.cpp +++ b/src/xrpld/app/ledger/OrderBookDB.cpp @@ -48,9 +48,9 @@ OrderBookDB::setup(std::shared_ptr const& ledger) update(ledger); else app_.getJobQueue().addJob( - jtUPDATE_PF, - "OrderBookDB::update: " + std::to_string(ledger->seq()), - [this, ledger]() { update(ledger); }); + jtUPDATE_PF, "OrderBookUpd", [this, ledger]() { + update(ledger); + }); } } diff --git a/src/xrpld/app/ledger/detail/InboundLedger.cpp b/src/xrpld/app/ledger/detail/InboundLedger.cpp index 1f5e5cc7b6..710173cd17 100644 --- a/src/xrpld/app/ledger/detail/InboundLedger.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedger.cpp @@ -454,7 +454,7 @@ InboundLedger::done() // We hold the PeerSet lock, so must dispatch app_.getJobQueue().addJob( - jtLEDGER_DATA, "AcquisitionDone", [self = shared_from_this()]() { + jtLEDGER_DATA, "AcqDone", [self = shared_from_this()]() { if (self->complete_ && !self->failed_) { self->app_.getLedgerMaster().checkAccept(self->getLedger()); diff --git a/src/xrpld/app/ledger/detail/InboundLedgers.cpp b/src/xrpld/app/ledger/detail/InboundLedgers.cpp index 445786eb63..fd2cde698e 100644 --- a/src/xrpld/app/ledger/detail/InboundLedgers.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedgers.cpp @@ -192,7 +192,7 @@ public: // dispatch if (ledger->gotData(std::weak_ptr(peer), packet)) app_.getJobQueue().addJob( - jtLEDGER_DATA, "processLedgerData", [ledger]() { + jtLEDGER_DATA, "ProcessLData", [ledger]() { ledger->runData(); }); @@ -207,7 +207,7 @@ public: if (packet->type() == protocol::liAS_NODE) { app_.getJobQueue().addJob( - jtLEDGER_DATA, "gotStaleData", [this, packet]() { + jtLEDGER_DATA, "GotStaleData", [this, packet]() { gotStaleData(packet); }); } diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp index 5b642ba3db..6909c45328 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp @@ -21,7 +21,7 @@ LedgerDeltaAcquire::LedgerDeltaAcquire( ledgerHash, LedgerReplayParameters::SUB_TASK_TIMEOUT, {jtREPLAY_TASK, - "LedgerReplayDelta", + "LedReplDelta", LedgerReplayParameters::MAX_QUEUED_TASKS}, app.journal("LedgerReplayDelta")) , inboundLedgers_(inboundLedgers) @@ -225,7 +225,7 @@ LedgerDeltaAcquire::onLedgerBuilt( } app_.getJobQueue().addJob( jtREPLAY_TASK, - "onLedgerBuilt", + "OnLedBuilt", [=, ledger = this->fullLedger_, &app = this->app_]() { for (auto reason : reasons) { diff --git a/src/xrpld/app/ledger/detail/LedgerMaster.cpp b/src/xrpld/app/ledger/detail/LedgerMaster.cpp index d176e85645..65421c9bd8 100644 --- a/src/xrpld/app/ledger/detail/LedgerMaster.cpp +++ b/src/xrpld/app/ledger/detail/LedgerMaster.cpp @@ -1344,7 +1344,7 @@ LedgerMaster::tryAdvance() if (!mAdvanceThread && !mValidLedger.empty()) { mAdvanceThread = true; - app_.getJobQueue().addJob(jtADVANCE, "advanceLedger", [this]() { + app_.getJobQueue().addJob(jtADVANCE, "AdvanceLedger", [this]() { std::unique_lock sl(m_mutex); XRPL_ASSERT( @@ -1482,7 +1482,7 @@ bool LedgerMaster::newPathRequest() { std::unique_lock ml(m_mutex); - mPathFindNewRequest = newPFWork("pf:newRequest", ml); + mPathFindNewRequest = newPFWork("PthFindNewReq", ml); return mPathFindNewRequest; } @@ -1503,7 +1503,7 @@ LedgerMaster::newOrderBookDB() std::unique_lock ml(m_mutex); mPathLedger.reset(); - return newPFWork("pf:newOBDB", ml); + return newPFWork("PthFindOBDB", ml); } /** A thread needs to be dispatched to handle pathfinding work of some kind. @@ -1841,7 +1841,7 @@ LedgerMaster::fetchForHistory( mFillInProgress = seq; } app_.getJobQueue().addJob( - jtADVANCE, "tryFill", [this, ledger]() { + jtADVANCE, "TryFill", [this, ledger]() { tryFill(ledger); }); } @@ -1980,7 +1980,7 @@ LedgerMaster::doAdvance(std::unique_lock& sl) } app_.getOPs().clearNeedNetworkLedger(); - progress = newPFWork("pf:newLedger", sl); + progress = newPFWork("PthFindNewLed", sl); } if (progress) mAdvanceWork = true; @@ -2011,7 +2011,7 @@ LedgerMaster::gotFetchPack(bool progress, std::uint32_t seq) { if (!mGotFetchPackThread.test_and_set(std::memory_order_acquire)) { - app_.getJobQueue().addJob(jtLEDGER_DATA, "gotFetchPack", [&]() { + app_.getJobQueue().addJob(jtLEDGER_DATA, "GotFetchPack", [&]() { app_.getInboundLedgers().gotFetchPack(); mGotFetchPackThread.clear(std::memory_order_release); }); diff --git a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp index cd174b098f..c31aba6c43 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp @@ -77,7 +77,7 @@ LedgerReplayTask::LedgerReplayTask( parameter.finishHash_, LedgerReplayParameters::TASK_TIMEOUT, {jtREPLAY_TASK, - "LedgerReplayTask", + "LedReplTask", LedgerReplayParameters::MAX_QUEUED_TASKS}, app.journal("LedgerReplayTask")) , inboundLedgers_(inboundLedgers) diff --git a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp index 5f4b0dc339..09d0ba1ea6 100644 --- a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp +++ b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp @@ -16,7 +16,7 @@ SkipListAcquire::SkipListAcquire( ledgerHash, LedgerReplayParameters::SUB_TASK_TIMEOUT, {jtREPLAY_TASK, - "SkipListAcquire", + "SkipListAcq", LedgerReplayParameters::MAX_QUEUED_TASKS}, app.journal("LedgerReplaySkipList")) , inboundLedgers_(inboundLedgers) diff --git a/src/xrpld/app/ledger/detail/TransactionAcquire.cpp b/src/xrpld/app/ledger/detail/TransactionAcquire.cpp index 3cd0e84ef0..6b22c6ca8b 100644 --- a/src/xrpld/app/ledger/detail/TransactionAcquire.cpp +++ b/src/xrpld/app/ledger/detail/TransactionAcquire.cpp @@ -27,7 +27,7 @@ TransactionAcquire::TransactionAcquire( app, hash, TX_ACQUIRE_TIMEOUT, - {jtTXN_DATA, "TransactionAcquire", {}}, + {jtTXN_DATA, "TxAcq", {}}, app.journal("TransactionAcquire")) , mHaveRoot(false) , mPeerSet(std::move(peerSet)) @@ -60,7 +60,7 @@ TransactionAcquire::done() // just updates the consensus and related structures when we acquire // a transaction set. No need to update them if we're shutting down. app_.getJobQueue().addJob( - jtTXN_DATA, "completeAcquire", [pap, hash, map]() { + jtTXN_DATA, "ComplAcquire", [pap, hash, map]() { pap->getInboundTransactions().giveSet(hash, map, true); }); } diff --git a/src/xrpld/app/main/Main.cpp b/src/xrpld/app/main/Main.cpp index 7c138168e4..d8bc601744 100644 --- a/src/xrpld/app/main/Main.cpp +++ b/src/xrpld/app/main/Main.cpp @@ -331,8 +331,7 @@ run(int argc, char** argv) { using namespace std; - beast::setCurrentThreadName( - "rippled: main " + BuildInfo::getVersionString()); + beast::setCurrentThreadName("main"); po::variables_map vm; diff --git a/src/xrpld/app/main/NodeStoreScheduler.cpp b/src/xrpld/app/main/NodeStoreScheduler.cpp index 221c1f098e..0e02a092f8 100644 --- a/src/xrpld/app/main/NodeStoreScheduler.cpp +++ b/src/xrpld/app/main/NodeStoreScheduler.cpp @@ -12,9 +12,8 @@ NodeStoreScheduler::scheduleTask(NodeStore::Task& task) if (jobQueue_.isStopped()) return; - if (!jobQueue_.addJob(jtWRITE, "NodeObject::store", [&task]() { - task.performScheduledTask(); - })) + if (!jobQueue_.addJob( + jtWRITE, "NObjStore", [&task]() { task.performScheduledTask(); })) { // Job not added, presumably because we're shutting down. // Recover by executing the task synchronously. diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index 2422ec4ae6..696512b5f4 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -981,7 +981,7 @@ NetworkOPsImp::setHeartbeatTimer() heartbeatTimer_, mConsensus.parms().ledgerGRANULARITY, [this]() { - m_job_queue.addJob(jtNETOP_TIMER, "NetOPs.heartbeat", [this]() { + m_job_queue.addJob(jtNETOP_TIMER, "NetHeart", [this]() { processHeartbeatTimer(); }); }, @@ -997,7 +997,7 @@ NetworkOPsImp::setClusterTimer() clusterTimer_, 10s, [this]() { - m_job_queue.addJob(jtNETOP_CLUSTER, "NetOPs.cluster", [this]() { + m_job_queue.addJob(jtNETOP_CLUSTER, "NetCluster", [this]() { processClusterTimer(); }); }, @@ -1225,7 +1225,7 @@ NetworkOPsImp::submitTransaction(std::shared_ptr const& iTrans) auto tx = std::make_shared(trans, reason, app_); - m_job_queue.addJob(jtTRANSACTION, "submitTxn", [this, tx]() { + m_job_queue.addJob(jtTRANSACTION, "SubmitTxn", [this, tx]() { auto t = tx; processTransaction(t, false, false, FailHard::no); }); @@ -1323,7 +1323,7 @@ NetworkOPsImp::doTransactionAsync( if (mDispatchState == DispatchState::none) { if (m_job_queue.addJob( - jtBATCH, "transactionBatch", [this]() { transactionBatch(); })) + jtBATCH, "TxBatchAsync", [this]() { transactionBatch(); })) { mDispatchState = DispatchState::scheduled; } @@ -1370,7 +1370,7 @@ NetworkOPsImp::doTransactionSyncBatch( if (mTransactions.size()) { // More transactions need to be applied, but by another job. - if (m_job_queue.addJob(jtBATCH, "transactionBatch", [this]() { + if (m_job_queue.addJob(jtBATCH, "TxBatchSync", [this]() { transactionBatch(); })) { @@ -3208,19 +3208,16 @@ NetworkOPsImp::reportFeeChange() if (f != mLastFeeSummary) { m_job_queue.addJob( - jtCLIENT_FEE_CHANGE, "reportFeeChange->pubServer", [this]() { - pubServer(); - }); + jtCLIENT_FEE_CHANGE, "PubFee", [this]() { pubServer(); }); } } void NetworkOPsImp::reportConsensusStateChange(ConsensusPhase phase) { - m_job_queue.addJob( - jtCLIENT_CONSENSUS, - "reportConsensusStateChange->pubConsensus", - [this, phase]() { pubConsensus(phase); }); + m_job_queue.addJob(jtCLIENT_CONSENSUS, "PubCons", [this, phase]() { + pubConsensus(phase); + }); } inline void @@ -3728,7 +3725,7 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) app_.getJobQueue().addJob( jtCLIENT_ACCT_HIST, - "AccountHistoryTxStream", + "HistTxStream", [this, dbType = databaseType, subInfo]() { auto const& accountId = subInfo.index_->accountId_; auto& lastLedgerSeq = subInfo.index_->historyLastLedgerSeq_; diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index b64227288c..327a5a4f21 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -1158,7 +1158,7 @@ PeerImp::onMessage(std::shared_ptr const& m) fee_.update(Resource::feeModerateBurdenPeer, "oversize"); app_.getJobQueue().addJob( - jtMANIFEST, "receiveManifests", [this, that = shared_from_this(), m]() { + jtMANIFEST, "RcvManifests", [this, that = shared_from_this(), m]() { overlay_.onManifests(m, that); }); } @@ -1452,7 +1452,7 @@ PeerImp::handleTransaction( { app_.getJobQueue().addJob( jtTRANSACTION, - "recvTransaction->checkTransaction", + "RcvCheckTx", [weak = std::weak_ptr(shared_from_this()), flags, checkSignature, @@ -1555,7 +1555,7 @@ PeerImp::onMessage(std::shared_ptr const& m) // Queue a job to process the request std::weak_ptr weak = shared_from_this(); - app_.getJobQueue().addJob(jtLEDGER_REQ, "recvGetLedger", [weak, m]() { + app_.getJobQueue().addJob(jtLEDGER_REQ, "RcvGetLedger", [weak, m]() { if (auto peer = weak.lock()) peer->processLedgerRequest(m); }); @@ -1575,29 +1575,27 @@ PeerImp::onMessage(std::shared_ptr const& m) fee_.update( Resource::feeModerateBurdenPeer, "received a proof path request"); std::weak_ptr weak = shared_from_this(); - app_.getJobQueue().addJob( - jtREPLAY_REQ, "recvProofPathRequest", [weak, m]() { - if (auto peer = weak.lock()) + app_.getJobQueue().addJob(jtREPLAY_REQ, "RcvProofPReq", [weak, m]() { + if (auto peer = weak.lock()) + { + auto reply = + peer->ledgerReplayMsgHandler_.processProofPathRequest(m); + if (reply.has_error()) { - auto reply = - peer->ledgerReplayMsgHandler_.processProofPathRequest(m); - if (reply.has_error()) - { - if (reply.error() == protocol::TMReplyError::reBAD_REQUEST) - peer->charge( - Resource::feeMalformedRequest, - "proof_path_request"); - else - peer->charge( - Resource::feeRequestNoReply, "proof_path_request"); - } + if (reply.error() == protocol::TMReplyError::reBAD_REQUEST) + peer->charge( + Resource::feeMalformedRequest, "proof_path_request"); else - { - peer->send(std::make_shared( - reply, protocol::mtPROOF_PATH_RESPONSE)); - } + peer->charge( + Resource::feeRequestNoReply, "proof_path_request"); } - }); + else + { + peer->send(std::make_shared( + reply, protocol::mtPROOF_PATH_RESPONSE)); + } + } + }); } void @@ -1629,30 +1627,27 @@ PeerImp::onMessage(std::shared_ptr const& m) fee_.fee = Resource::feeModerateBurdenPeer; std::weak_ptr weak = shared_from_this(); - app_.getJobQueue().addJob( - jtREPLAY_REQ, "recvReplayDeltaRequest", [weak, m]() { - if (auto peer = weak.lock()) + app_.getJobQueue().addJob(jtREPLAY_REQ, "RcvReplDReq", [weak, m]() { + if (auto peer = weak.lock()) + { + auto reply = + peer->ledgerReplayMsgHandler_.processReplayDeltaRequest(m); + if (reply.has_error()) { - auto reply = - peer->ledgerReplayMsgHandler_.processReplayDeltaRequest(m); - if (reply.has_error()) - { - if (reply.error() == protocol::TMReplyError::reBAD_REQUEST) - peer->charge( - Resource::feeMalformedRequest, - "replay_delta_request"); - else - peer->charge( - Resource::feeRequestNoReply, - "replay_delta_request"); - } + if (reply.error() == protocol::TMReplyError::reBAD_REQUEST) + peer->charge( + Resource::feeMalformedRequest, "replay_delta_request"); else - { - peer->send(std::make_shared( - reply, protocol::mtREPLAY_DELTA_RESPONSE)); - } + peer->charge( + Resource::feeRequestNoReply, "replay_delta_request"); } - }); + else + { + peer->send(std::make_shared( + reply, protocol::mtREPLAY_DELTA_RESPONSE)); + } + } + }); } void @@ -1748,7 +1743,7 @@ PeerImp::onMessage(std::shared_ptr const& m) { std::weak_ptr weak{shared_from_this()}; app_.getJobQueue().addJob( - jtTXN_DATA, "recvPeerData", [weak, ledgerHash, m]() { + jtTXN_DATA, "RcvPeerData", [weak, ledgerHash, m]() { if (auto peer = weak.lock()) { peer->app_.getInboundTransactions().gotData( @@ -1876,7 +1871,7 @@ PeerImp::onMessage(std::shared_ptr const& m) std::weak_ptr weak = shared_from_this(); app_.getJobQueue().addJob( isTrusted ? jtPROPOSAL_t : jtPROPOSAL_ut, - "recvPropose->checkPropose", + "checkPropose", [weak, isTrusted, m, proposal]() { if (auto peer = weak.lock()) peer->checkPropose(isTrusted, m, proposal); @@ -2490,18 +2485,7 @@ PeerImp::onMessage(std::shared_ptr const& m) } else if (isTrusted || !app_.getFeeTrack().isLoadedLocal()) { - std::string const name = [isTrusted, val]() { - std::string ret = - isTrusted ? "Trusted validation" : "Untrusted validation"; - -#ifdef DEBUG - ret += " " + - std::to_string(val->getFieldU32(sfLedgerSequence)) + ": " + - to_string(val->getNodeID()); -#endif - - return ret; - }(); + std::string const name = isTrusted ? "ChkTrust" : "ChkUntrust"; std::weak_ptr weak = shared_from_this(); app_.getJobQueue().addJob( @@ -2561,11 +2545,10 @@ PeerImp::onMessage(std::shared_ptr const& m) } std::weak_ptr weak = shared_from_this(); - app_.getJobQueue().addJob( - jtREQUESTED_TXN, "doTransactions", [weak, m]() { - if (auto peer = weak.lock()) - peer->doTransactions(m); - }); + app_.getJobQueue().addJob(jtREQUESTED_TXN, "DoTxs", [weak, m]() { + if (auto peer = weak.lock()) + peer->doTransactions(m); + }); return; } @@ -2705,11 +2688,10 @@ PeerImp::onMessage(std::shared_ptr const& m) } std::weak_ptr weak = shared_from_this(); - app_.getJobQueue().addJob( - jtMISSING_TXN, "handleHaveTransactions", [weak, m]() { - if (auto peer = weak.lock()) - peer->handleHaveTransactions(m); - }); + app_.getJobQueue().addJob(jtMISSING_TXN, "HandleHaveTxs", [weak, m]() { + if (auto peer = weak.lock()) + peer->handleHaveTransactions(m); + }); } void diff --git a/src/xrpld/rpc/detail/RPCSub.cpp b/src/xrpld/rpc/detail/RPCSub.cpp index 616911fdfa..877b894885 100644 --- a/src/xrpld/rpc/detail/RPCSub.cpp +++ b/src/xrpld/rpc/detail/RPCSub.cpp @@ -72,7 +72,7 @@ public: JLOG(j_.info()) << "RPCCall::fromNetwork start"; mSending = m_jobQueue.addJob( - jtCLIENT_SUBSCRIBE, "RPCSub::sendThread", [this]() { + jtCLIENT_SUBSCRIBE, "RPCSubSendThr", [this]() { sendThread(); }); } From 8695313565188f549277ed418cc832af199671fb Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 22 Jan 2026 08:48:50 -0500 Subject: [PATCH 085/105] ci: Run on-trigger and on-pr when generate-version is modified (#6257) This change ensures that the `on-pr` and `on-trigger` workflows run when the generate-version action is modified. --- .github/workflows/on-pr.yml | 1 + .github/workflows/on-trigger.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 61639485d9..46f6b7500a 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -59,6 +59,7 @@ jobs: # Keep the paths below in sync with those in `on-trigger.yml`. .github/actions/build-deps/** .github/actions/build-test/** + .github/actions/generate-version/** .github/actions/setup-conan/** .github/scripts/strategy-matrix/** .github/workflows/reusable-build.yml diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml index 7f54a9977e..210670f5a1 100644 --- a/.github/workflows/on-trigger.yml +++ b/.github/workflows/on-trigger.yml @@ -16,6 +16,7 @@ on: # Keep the paths below in sync with those in `on-pr.yml`. - ".github/actions/build-deps/**" - ".github/actions/build-test/**" + - ".github/actions/generate-version/**" - ".github/actions/setup-conan/**" - ".github/scripts/strategy-matrix/**" - ".github/workflows/reusable-build.yml" From a4f8aa623fe2fc20218644ce7a847fa70746b3b3 Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Thu, 22 Jan 2026 16:16:18 +0000 Subject: [PATCH 086/105] chore: Detect uninitialized variables in CMake files (#6247) There were a few uninitialized variables in CMake files. This change will make sure we always check if a variable has been initialized before using them, or in come cases initialize them by default. This change will raise an error on CI if a developer introduced an uninitialized variable in CMake files. --- CMakeLists.txt | 4 +++- cmake/CompilationEnv.cmake | 6 ++++++ cmake/XrplCore.cmake | 8 ++++---- cmake/XrplInstall.cmake | 6 ++++++ cmake/XrplInterface.cmake | 13 +++++++++---- cmake/XrplSanitizers.cmake | 5 ++++- cmake/XrplSettings.cmake | 9 +++++---- 7 files changed, 37 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee0484e79d..c24b27adb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,9 @@ if(POLICY CMP0077) endif() # Fix "unrecognized escape" issues when passing CMAKE_MODULE_PATH on Windows. -file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH) +if(DEFINED CMAKE_MODULE_PATH) + file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH) +endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") project(xrpl) diff --git a/cmake/CompilationEnv.cmake b/cmake/CompilationEnv.cmake index 345e4cdd62..2d97f94615 100644 --- a/cmake/CompilationEnv.cmake +++ b/cmake/CompilationEnv.cmake @@ -13,6 +13,7 @@ include_guard(GLOBAL) set(is_clang FALSE) set(is_gcc FALSE) set(is_msvc FALSE) +set(is_xcode FALSE) if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # Clang or AppleClang set(is_clang TRUE) @@ -24,6 +25,11 @@ else() message(FATAL_ERROR "Unsupported C++ compiler: ${CMAKE_CXX_COMPILER_ID}") endif() +# Xcode generator detection +if(CMAKE_GENERATOR STREQUAL "Xcode") + set(is_xcode TRUE) +endif() + # -------------------------------------------------------------------- # Operating system detection diff --git a/cmake/XrplCore.cmake b/cmake/XrplCore.cmake index 0689fbe7b6..2e50cd2f7a 100644 --- a/cmake/XrplCore.cmake +++ b/cmake/XrplCore.cmake @@ -32,14 +32,14 @@ target_protobuf_sources(xrpl.libpb xrpl/proto target_compile_options(xrpl.libpb PUBLIC - $<$:-wd4996> - $<$: + $<$:-wd4996> + $<$: --system-header-prefix="google/protobuf" -Wno-deprecated-dynamic-exception-spec > PRIVATE - $<$:-wd4065> - $<$>:-Wno-deprecated-declarations> + $<$:-wd4065> + $<$>:-Wno-deprecated-declarations> ) target_link_libraries(xrpl.libpb diff --git a/cmake/XrplInstall.cmake b/cmake/XrplInstall.cmake index 310436998d..0599a8268c 100644 --- a/cmake/XrplInstall.cmake +++ b/cmake/XrplInstall.cmake @@ -4,6 +4,12 @@ include(create_symbolic_link) +# If no suffix is defined for executables (e.g. Windows uses .exe but Linux +# and macOS use none), then explicitly set it to the empty string. +if(NOT DEFINED suffix) + set(suffix "") +endif() + install ( TARGETS common diff --git a/cmake/XrplInterface.cmake b/cmake/XrplInterface.cmake index 6e0203c099..f53b2dac26 100644 --- a/cmake/XrplInterface.cmake +++ b/cmake/XrplInterface.cmake @@ -4,6 +4,11 @@ include(CompilationEnv) +# Set defaults for optional variables to avoid uninitialized variable warnings +if(NOT DEFINED voidstar) + set(voidstar OFF) +endif() + add_library (opts INTERFACE) add_library (Xrpl::opts ALIAS opts) target_compile_definitions (opts @@ -52,7 +57,7 @@ add_library (xrpl_syslibs INTERFACE) add_library (Xrpl::syslibs ALIAS xrpl_syslibs) target_link_libraries (xrpl_syslibs INTERFACE - $<$: + $<$: legacy_stdio_definitions.lib Shlwapi kernel32 @@ -69,10 +74,10 @@ target_link_libraries (xrpl_syslibs odbccp32 crypt32 > - $<$>:dl> - $<$,$>>:rt>) + $<$>:dl> + $<$,$>>:rt>) -if (NOT MSVC) +if (NOT is_msvc) set (THREADS_PREFER_PTHREAD_FLAG ON) find_package (Threads) target_link_libraries (xrpl_syslibs INTERFACE Threads::Threads) diff --git a/cmake/XrplSanitizers.cmake b/cmake/XrplSanitizers.cmake index 050a5ef6f0..fc31e4a3ec 100644 --- a/cmake/XrplSanitizers.cmake +++ b/cmake/XrplSanitizers.cmake @@ -43,7 +43,10 @@ include(CompilationEnv) # Read environment variable -set(SANITIZERS $ENV{SANITIZERS}) +set(SANITIZERS "") +if(DEFINED ENV{SANITIZERS}) + set(SANITIZERS "$ENV{SANITIZERS}") +endif() # Set SANITIZERS_ENABLED flag for use in other modules if(SANITIZERS MATCHES "address|thread|undefinedbehavior") diff --git a/cmake/XrplSettings.cmake b/cmake/XrplSettings.cmake index 647e95837d..3724ea2b4f 100644 --- a/cmake/XrplSettings.cmake +++ b/cmake/XrplSettings.cmake @@ -4,10 +4,11 @@ include(CompilationEnv) -if("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true") - set(is_ci TRUE) -else() - set(is_ci FALSE) +set(is_ci FALSE) +if(DEFINED ENV{CI}) + if("$ENV{CI}" STREQUAL "true") + set(is_ci TRUE) + endif() endif() get_directory_property(has_parent PARENT_DIRECTORY) From 4e3f953fc49d832e18271be148d5c78118188fd3 Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 22 Jan 2026 11:42:53 -0500 Subject: [PATCH 087/105] ci: Use plus instead of hyphen for Conan recipe version suffix (#6261) Conan recipes use semantic versioning, and since our version already contains a hyphen the second hyphen causes Conan to ignore it. The plus sign is a valid separator we can use instead, so this change uses a `+` to separate a version suffix (commit hash) instead of a `-`. --- .github/actions/generate-version/action.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/actions/generate-version/action.yml b/.github/actions/generate-version/action.yml index 4f176fcb91..6b84aac2f3 100644 --- a/.github/actions/generate-version/action.yml +++ b/.github/actions/generate-version/action.yml @@ -17,8 +17,10 @@ runs: VERSION: ${{ github.ref_name }} run: echo "VERSION=${VERSION}" >> "${GITHUB_ENV}" - # When a tag is not pushed, then the version is extracted from the - # BuildInfo.cpp file and the shortened commit hash appended to it. + # When a tag is not pushed, then the version (e.g. 1.2.3-b0) is extracted + # from the BuildInfo.cpp file and the shortened commit hash appended to it. + # We use a plus sign instead of a hyphen because Conan recipe versions do + # not support two hyphens. - name: Generate version for non-tag event if: ${{ github.event_name != 'tag' }} shell: bash @@ -32,7 +34,7 @@ runs: echo 'Appending shortened commit hash to version.' SHA='${{ github.sha }}' - VERSION="${VERSION}-${SHA:0:7}" + VERSION="${VERSION}+${SHA:0:7}" echo "VERSION=${VERSION}" >> "${GITHUB_ENV}" From c57ffdbcb874db3a1c61c83cceda7faeef0a9008 Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 22 Jan 2026 14:05:59 -0500 Subject: [PATCH 088/105] ci: Explicitly set version when exporting the Conan recipe (#6264) By default the Conan recipe extracts the version from `BuildInfo.cpp`, but in some of the cases we want to upload a recipe with a suffix derived from the commit hash. This currently then results in the uploading to fail, since there is a version mismatch. Here we explicitly set the version, and then simplify the steps in the upload workflow since we now need the recipe name (embedded within the conanfile.py but also needed when uploading), the recipe version, and the recipe ref (name/version). --- .github/workflows/reusable-upload-recipe.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/reusable-upload-recipe.yml b/.github/workflows/reusable-upload-recipe.yml index 9b25481f6a..b5b8798f09 100644 --- a/.github/workflows/reusable-upload-recipe.yml +++ b/.github/workflows/reusable-upload-recipe.yml @@ -49,10 +49,6 @@ jobs: id: version uses: ./.github/actions/generate-version - - name: Determine recipe reference - id: ref - run: echo "ref=xrpl/${{ steps.version.outputs.version }}" >> "${GITHUB_OUTPUT}" - - name: Set up Conan uses: ./.github/actions/setup-conan with: @@ -68,11 +64,10 @@ jobs: - name: Upload Conan recipe env: - RECIPE_REF: ${{ steps.ref.outputs.ref }} REMOTE_NAME: ${{ inputs.remote_name }} run: | - conan export . - conan upload --confirm --check --remote="${REMOTE_NAME}" ${RECIPE_REF} + conan export . --version=${{ steps.version.outputs.version }} + conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }} outputs: - ref: ${{ steps.ref.outputs.ref }} + ref: xrpl/${{ steps.version.outputs.version }} From 66158d786f309a64fc85a86eacf3c269c17eae28 Mon Sep 17 00:00:00 2001 From: Bart Date: Thu, 22 Jan 2026 16:05:15 -0500 Subject: [PATCH 089/105] ci: Properly propagate Conan credentials (#6265) The export and upload steps were initially in a separate action, where GitHub Actions does not support the `secrets` keyword, but only `inputs` for the credentials. After they were moved to a reusable workflow, only part of the references to the credentials were updated. This change correctly references to the Conan credentials via `secrets` instead of `inputs`. --- .github/workflows/reusable-upload-recipe.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable-upload-recipe.yml b/.github/workflows/reusable-upload-recipe.yml index b5b8798f09..156659392e 100644 --- a/.github/workflows/reusable-upload-recipe.yml +++ b/.github/workflows/reusable-upload-recipe.yml @@ -58,8 +58,8 @@ jobs: - name: Log into Conan remote env: REMOTE_NAME: ${{ inputs.remote_name }} - REMOTE_USERNAME: ${{ inputs.remote_username }} - REMOTE_PASSWORD: ${{ inputs.remote_password }} + REMOTE_USERNAME: ${{ secrets.remote_username }} + REMOTE_PASSWORD: ${{ secrets.remote_password }} run: conan remote login "${REMOTE_NAME}" "${REMOTE_USERNAME}" --password "${REMOTE_PASSWORD}" - name: Upload Conan recipe From 0586b5678e6f4051f89402c7873a94a4c139a5f5 Mon Sep 17 00:00:00 2001 From: Bart Date: Fri, 23 Jan 2026 06:40:55 -0500 Subject: [PATCH 090/105] ci: Pass missing sanitizers input to actions (#6266) The `upload-conan-deps` workflow that's triggered on push is supposed to upload the Conan dependencies to our remote, so future PR commits can pull those dependencies from the remote. However, as the `sanitize` argument is missing, it was building different dependencies than what the PRs are building for the asan/tsan/ubsan job, so the latter would not find anything in the remote that they could use. This change sets the missing `sanitizers` input variable when running the `build-deps` action. Separately, the `setup-conan` action showed the default profile, while we are using the `ci` profile. To ensure the profile is correctly printed when sanitizers are enabled, the environment variable the profile uses is set before calling the action. --- .github/actions/setup-conan/action.yml | 2 +- .github/workflows/reusable-build-test-config.yml | 2 ++ .github/workflows/upload-conan-deps.yml | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-conan/action.yml b/.github/actions/setup-conan/action.yml index 37956c5f21..9d834884d2 100644 --- a/.github/actions/setup-conan/action.yml +++ b/.github/actions/setup-conan/action.yml @@ -31,7 +31,7 @@ runs: conan config install conan/profiles/ -tf $(conan config home)/profiles/ echo 'Conan profile:' - conan profile show + conan profile show --profile ci - name: Set up Conan remote shell: bash diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index b8c82aa94d..d298c85726 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -125,6 +125,8 @@ jobs: subtract: ${{ inputs.nproc_subtract }} - name: Setup Conan + env: + SANITIZERS: ${{ inputs.sanitizers }} uses: ./.github/actions/setup-conan - name: Build dependencies diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml index 711354d490..2dada1ef08 100644 --- a/.github/workflows/upload-conan-deps.yml +++ b/.github/workflows/upload-conan-deps.yml @@ -84,6 +84,8 @@ jobs: subtract: ${{ env.NPROC_SUBTRACT }} - name: Setup Conan + env: + SANITIZERS: ${{ matrix.sanitizers }} uses: ./.github/actions/setup-conan with: remote_name: ${{ env.CONAN_REMOTE_NAME }} @@ -98,6 +100,7 @@ jobs: # Set the verbosity to "quiet" for Windows to avoid an excessive # amount of logs. For other OSes, the "verbose" logs are more useful. log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }} + sanitizers: ${{ matrix.sanitizers }} - name: Log into Conan remote if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }} From 778da954b4c38274fce90fef6e876fa0cc207eb9 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 23 Jan 2026 14:09:00 -0500 Subject: [PATCH 091/105] refactor: clean up uses of `std::source_location` (#6272) Since the minimum Clang version we support is 16, the checks for version < 15 are no longer necessary. This change therefore removes the macros checking if the clang version is < 15 and simplifies uses of `std::source_location`. --- src/test/jtx/TestHelpers.h | 11 ++--------- src/test/rpc/LedgerEntry_test.cpp | 16 +++++----------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/test/jtx/TestHelpers.h b/src/test/jtx/TestHelpers.h index 3096a902b1..8149c2d464 100644 --- a/src/test/jtx/TestHelpers.h +++ b/src/test/jtx/TestHelpers.h @@ -15,15 +15,8 @@ #include #include -#include - -#if (defined(__clang_major__) && __clang_major__ < 15) -#include -using source_location = std::experimental::source_location; -#else #include -using std::source_location; -#endif +#include namespace xrpl { namespace test { @@ -640,7 +633,7 @@ checkMetrics( std::size_t expectedPerLedger, std::uint64_t expectedMinFeeLevel = baseFeeLevel.fee(), std::uint64_t expectedMedFeeLevel = minEscalationFeeLevel.fee(), - source_location const location = source_location::current()) + std::source_location const location = std::source_location::current()) { int line = location.line(); char const* file = location.file_name(); diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index 1b7079341c..cc6d958a2d 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -14,13 +14,7 @@ #include #include -#if (defined(__clang_major__) && __clang_major__ < 15) -#include -using source_location = std::experimental::source_location; -#else #include -using std::source_location; -#endif namespace xrpl { namespace test { @@ -114,7 +108,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value const& jv, std::string const& err, std::string const& msg, - source_location const location = source_location::current()) + std::source_location const location = std::source_location::current()) { if (BEAST_EXPECT(jv.isMember(jss::status))) BEAST_EXPECTS( @@ -297,7 +291,7 @@ class LedgerEntry_test : public beast::unit_test::suite FieldType const typeID, std::string const& expectedError, bool required = true, - source_location const location = source_location::current()) + std::source_location const location = std::source_location::current()) { forAllApiVersions([&, this](unsigned apiVersion) { if (required) @@ -350,7 +344,7 @@ class LedgerEntry_test : public beast::unit_test::suite FieldType typeID, std::string const& expectedError, bool required = true, - source_location const location = source_location::current()) + std::source_location const location = std::source_location::current()) { forAllApiVersions([&, this](unsigned apiVersion) { if (required) @@ -407,7 +401,7 @@ class LedgerEntry_test : public beast::unit_test::suite runLedgerEntryTest( test::jtx::Env& env, Json::StaticString const& parentField, - source_location const location = source_location::current()) + std::source_location const location = std::source_location::current()) { testMalformedField( env, @@ -431,7 +425,7 @@ class LedgerEntry_test : public beast::unit_test::suite test::jtx::Env& env, Json::StaticString const& parentField, std::vector const& subfields, - source_location const location = source_location::current()) + std::source_location const location = std::source_location::current()) { testMalformedField( env, From 847e87563571ea88333f9440bba1df5cd9443110 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 26 Jan 2026 18:54:43 +0000 Subject: [PATCH 092/105] refactor: Update Boost to 1.90 (#6280) Upcoming feature work requires functionality present in a newer Boost version. These newer versions also have improvements for sanitizers. --- BUILD.md | 4 ++-- cmake/deps/Boost.cmake | 1 - conan.lock | 14 +++++++++----- conanfile.py | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/BUILD.md b/BUILD.md index b239b10be6..f90aa0c148 100644 --- a/BUILD.md +++ b/BUILD.md @@ -148,8 +148,8 @@ function extract_version { } # Define which recipes to export. -recipes=('ed25519' 'grpc' 'openssl' 'secp256k1' 'snappy' 'soci') -folders=('all' 'all' '3.x.x' 'all' 'all' 'all') +recipes=('ed25519' 'grpc' 'nudb' 'openssl' 'secp256k1' 'snappy' 'soci') +folders=('all' 'all' 'all' '3.x.x' 'all' 'all' 'all') # Selectively check out the recipes from our CCI fork. cd external diff --git a/cmake/deps/Boost.cmake b/cmake/deps/Boost.cmake index b73698efd8..49025ae342 100644 --- a/cmake/deps/Boost.cmake +++ b/cmake/deps/Boost.cmake @@ -30,7 +30,6 @@ target_link_libraries(xrpl_boost Boost::process Boost::program_options Boost::regex - Boost::system Boost::thread) if(Boost_COMPILER) target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking) diff --git a/conan.lock b/conan.lock index f3fa1e5f6e..64def2e916 100644 --- a/conan.lock +++ b/conan.lock @@ -11,7 +11,7 @@ "re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103", "protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038", "openssl/3.5.4#1b986e61b38fdfda3b40bebc1b234393%1768312656.257", - "nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1765850143.957", + "nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32", "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914", "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492", "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03", @@ -23,7 +23,7 @@ "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772", "c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336", "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837", - "boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1765850172.862", + "boost/1.90.0#d5e8defe7355494953be18524a7f135b%1765955095.179", "abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993" ], "build_requires": [ @@ -42,18 +42,22 @@ ], "python_requires": [], "overrides": { + "boost/1.90.0#d5e8defe7355494953be18524a7f135b": [ + null, + "boost/1.90.0" + ], "protobuf/5.27.0": [ "protobuf/6.32.1" ], "lz4/1.9.4": [ "lz4/1.10.0" ], - "boost/1.83.0": [ - "boost/1.88.0" - ], "sqlite3/3.44.2": [ "sqlite3/3.49.1" ], + "boost/1.83.0": [ + "boost/1.90.0" + ], "lz4/[>=1.9.4 <2]": [ "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504" ] diff --git a/conanfile.py b/conanfile.py index 8501909ce3..84ef1e2aa7 100644 --- a/conanfile.py +++ b/conanfile.py @@ -131,7 +131,7 @@ class Xrpl(ConanFile): transitive_headers_opt = ( {"transitive_headers": True} if conan_version.split(".")[0] == "2" else {} ) - self.requires("boost/1.88.0", force=True, **transitive_headers_opt) + self.requires("boost/1.90.0", force=True, **transitive_headers_opt) self.requires("date/3.0.4", **transitive_headers_opt) self.requires("lz4/1.10.0", force=True) self.requires("protobuf/6.32.1", force=True) From a2f1973574d4a370ffbbcad8e8d6590425657924 Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Mon, 26 Jan 2026 15:58:12 -0400 Subject: [PATCH 093/105] fix: Remove DEFAULT fields that change to the default in associateAsset (#6259) (#6273) - Add Vault creation tests for showing valid range for AssetsMaximum --- include/xrpl/protocol/STObject.h | 3 + src/libxrpl/protocol/STAmount.cpp | 2 + src/libxrpl/protocol/STObject.cpp | 6 + src/libxrpl/protocol/STTakesAsset.cpp | 18 ++ src/test/app/Vault_test.cpp | 258 ++++++++++++++++++++++++++ 5 files changed, 287 insertions(+) diff --git a/include/xrpl/protocol/STObject.h b/include/xrpl/protocol/STObject.h index c6ca133e89..d282e9bf01 100644 --- a/include/xrpl/protocol/STObject.h +++ b/include/xrpl/protocol/STObject.h @@ -397,6 +397,9 @@ public: void delField(int index); + SOEStyle + getStyle(SField const& field) const; + bool hasMatchingEntry(STBase const&); diff --git a/src/libxrpl/protocol/STAmount.cpp b/src/libxrpl/protocol/STAmount.cpp index ec60971e63..91ad029dda 100644 --- a/src/libxrpl/protocol/STAmount.cpp +++ b/src/libxrpl/protocol/STAmount.cpp @@ -100,6 +100,8 @@ areComparable(STAmount const& v1, STAmount const& v2) return false; } +static_assert(INITIAL_XRP.drops() == STAmount::cMaxNativeN); + STAmount::STAmount(SerialIter& sit, SField const& name) : STBase(name) { std::uint64_t value = sit.get64(); diff --git a/src/libxrpl/protocol/STObject.cpp b/src/libxrpl/protocol/STObject.cpp index 6007753ed1..a45eb4b7c7 100644 --- a/src/libxrpl/protocol/STObject.cpp +++ b/src/libxrpl/protocol/STObject.cpp @@ -580,6 +580,12 @@ STObject::delField(int index) v_.erase(v_.begin() + index); } +SOEStyle +STObject::getStyle(SField const& field) const +{ + return mType ? mType->style(field) : soeINVALID; +} + unsigned char STObject::getFieldU8(SField const& field) const { diff --git a/src/libxrpl/protocol/STTakesAsset.cpp b/src/libxrpl/protocol/STTakesAsset.cpp index d43e7b04a1..9167c6ace0 100644 --- a/src/libxrpl/protocol/STTakesAsset.cpp +++ b/src/libxrpl/protocol/STTakesAsset.cpp @@ -18,10 +18,28 @@ associateAsset(SLE& sle, Asset const& asset) // If the field is not set or present, skip it. if (type == STI_NOTPRESENT) continue; + // If the type doesn't downcast, then the flag shouldn't be on the // SField auto& ta = entry.downcast(); + auto const style = sle.getStyle(ta.getFName()); + XRPL_ASSERT_PARTS( + style != soeINVALID, + "xrpl::associateAsset", + "valid template element style"); + + XRPL_ASSERT_PARTS( + style != soeDEFAULT || !ta.isDefault(), + "xrpl::associateAsset", + "non-default value"); ta.associateAsset(asset); + + // associateAsset in derived classes may change the underlying + // value, but it won't know anything about how the value relates to + // the SLE. If the template element is soeDEFAULT, and the value + // changed to the default value, remove the field. + if (style == soeDEFAULT && ta.isDefault()) + sle.makeFieldAbsent(field); } } } diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index 41a4fc2b3b..d8bfa71d46 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -5782,6 +5782,263 @@ class Vault_test : public beast::unit_test::suite testCase(MPT, "MPT", owner, depositor, issuer); } + void + testAssetsMaximum() + { + testcase("Assets Maximum"); + + using namespace test::jtx; + + Env env{*this, testable_amendments() | featureSingleAssetVault}; + Account const owner{"owner"}; + Account const issuer{"issuer"}; + + Vault vault{env}; + env.fund(XRP(1'000'000), issuer, owner); + env.close(); + + auto const maxInt64 = + std::to_string(std::numeric_limits::max()); + BEAST_EXPECT(maxInt64 == "9223372036854775807"); + + // Naming things is hard + auto const maxInt64Plus1 = std::to_string( + static_cast( + std::numeric_limits::max()) + + 1); + BEAST_EXPECT(maxInt64Plus1 == "9223372036854775808"); + + auto const initialXRP = to_string(INITIAL_XRP); + BEAST_EXPECT(initialXRP == "100000000000000000"); + + auto const initialXRPPlus1 = to_string(INITIAL_XRP + 1); + BEAST_EXPECT(initialXRPPlus1 == "100000000000000001"); + + { + testcase("Assets Maximum: XRP"); + + PrettyAsset const xrpAsset = xrpIssue(); + + auto [tx, keylet] = + vault.create({.owner = owner, .asset = xrpAsset}); + tx[sfData] = "4D65746144617461"; + + tx[sfAssetsMaximum] = maxInt64; + env(tx, ter(tefEXCEPTION), THISLINE); + env.close(); + + tx[sfAssetsMaximum] = initialXRPPlus1; + env(tx, ter(tefEXCEPTION), THISLINE); + env.close(); + + tx[sfAssetsMaximum] = initialXRP; + env(tx, THISLINE); + env.close(); + + tx[sfAssetsMaximum] = maxInt64Plus1; + env(tx, ter(tefEXCEPTION), THISLINE); + env.close(); + + // This value will be rounded + auto const insertAt = maxInt64Plus1.size() - 3; + auto const decimalTest = maxInt64Plus1.substr(0, insertAt) + "." + + maxInt64Plus1.substr(insertAt); // (max int64+1) / 1000 + BEAST_EXPECT(decimalTest == "9223372036854775.808"); + tx[sfAssetsMaximum] = decimalTest; + auto const newKeylet = keylet::vault(owner.id(), env.seq(owner)); + env(tx, THISLINE); + env.close(); + + auto const vaultSle = env.le(newKeylet); + if (!BEAST_EXPECT(vaultSle)) + return; + + BEAST_EXPECT(vaultSle->at(sfAssetsMaximum) == 9223372036854776); + } + + { + testcase("Assets Maximum: MPT"); + + PrettyAsset const mptAsset = [&]() { + MPTTester mptt{env, issuer, mptInitNoFund}; + mptt.create( + {.flags = + tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + env.close(); + PrettyAsset const mptAsset = mptt["MPT"]; + mptt.authorize({.account = owner}); + env.close(); + return mptAsset; + }(); + + env(pay(issuer, owner, mptAsset(100'000)), THISLINE); + env.close(); + + auto [tx, keylet] = + vault.create({.owner = owner, .asset = mptAsset}); + tx[sfData] = "4D65746144617461"; + + tx[sfAssetsMaximum] = maxInt64; + env(tx, THISLINE); + env.close(); + + tx[sfAssetsMaximum] = initialXRPPlus1; + env(tx, THISLINE); + env.close(); + + tx[sfAssetsMaximum] = initialXRP; + env(tx, THISLINE); + env.close(); + + tx[sfAssetsMaximum] = maxInt64Plus1; + env(tx, ter(tefEXCEPTION), THISLINE); + env.close(); + + // This value will be rounded + auto const insertAt = maxInt64Plus1.size() - 1; + auto const decimalTest = maxInt64Plus1.substr(0, insertAt) + "." + + maxInt64Plus1.substr(insertAt); // (max int64+1) / 10 + BEAST_EXPECT(decimalTest == "922337203685477580.8"); + tx[sfAssetsMaximum] = decimalTest; + auto const newKeylet = keylet::vault(owner.id(), env.seq(owner)); + env(tx, THISLINE); + env.close(); + + auto const vaultSle = env.le(newKeylet); + if (!BEAST_EXPECT(vaultSle)) + return; + + BEAST_EXPECT(vaultSle->at(sfAssetsMaximum) == 922337203685477581); + } + + { + testcase("Assets Maximum: IOU"); + + // Almost anything goes with IOUs + PrettyAsset iouAsset = issuer["IOU"]; + env.trust(iouAsset(1000), owner); + env(pay(issuer, owner, iouAsset(200))); + env.close(); + + auto [tx, keylet] = + vault.create({.owner = owner, .asset = iouAsset}); + tx[sfData] = "4D65746144617461"; + + tx[sfAssetsMaximum] = maxInt64; + env(tx, THISLINE); + env.close(); + + tx[sfAssetsMaximum] = initialXRPPlus1; + env(tx, THISLINE); + env.close(); + + tx[sfAssetsMaximum] = initialXRP; + env(tx, THISLINE); + env.close(); + + tx[sfAssetsMaximum] = maxInt64Plus1; + env(tx, THISLINE); + env.close(); + + tx[sfAssetsMaximum] = "1000000000000000e80"; + env.close(); + + tx[sfAssetsMaximum] = "1000000000000000e-96"; + env.close(); + + // These values will be rounded to 15 significant digits + { + auto const insertAt = maxInt64Plus1.size() - 1; + auto const decimalTest = maxInt64Plus1.substr(0, insertAt) + + "." + maxInt64Plus1.substr(insertAt); // (max int64+1) / 10 + BEAST_EXPECT(decimalTest == "922337203685477580.8"); + tx[sfAssetsMaximum] = decimalTest; + auto const newKeylet = + keylet::vault(owner.id(), env.seq(owner)); + env(tx, THISLINE); + env.close(); + + auto const vaultSle = env.le(newKeylet); + if (!BEAST_EXPECT(vaultSle)) + return; + + BEAST_EXPECT( + (vaultSle->at(sfAssetsMaximum) == + Number{9223372036854776, 2, Number::normalized{}})); + } + { + tx[sfAssetsMaximum] = + "9223372036854775807e40"; // max int64 * 10^40 + auto const newKeylet = + keylet::vault(owner.id(), env.seq(owner)); + env(tx, THISLINE); + env.close(); + + auto const vaultSle = env.le(newKeylet); + if (!BEAST_EXPECT(vaultSle)) + return; + + BEAST_EXPECT( + (vaultSle->at(sfAssetsMaximum) == + Number{9223372036854776, 43, Number::normalized{}})); + } + { + tx[sfAssetsMaximum] = + "9223372036854775807e-40"; // max int64 * 10^-40 + auto const newKeylet = + keylet::vault(owner.id(), env.seq(owner)); + env(tx, THISLINE); + env.close(); + + auto const vaultSle = env.le(newKeylet); + if (!BEAST_EXPECT(vaultSle)) + return; + + BEAST_EXPECT( + (vaultSle->at(sfAssetsMaximum) == + Number{9223372036854776, -37, Number::normalized{}})); + } + { + tx[sfAssetsMaximum] = + "9223372036854775807e-100"; // max int64 * 10^-100 + auto const newKeylet = + keylet::vault(owner.id(), env.seq(owner)); + env(tx, THISLINE); + env.close(); + + // Field 'AssetsMaximum' may not be explicitly set to default. + auto const vaultSle = env.le(newKeylet); + if (!BEAST_EXPECT(vaultSle)) + return; + + BEAST_EXPECT(vaultSle->at(sfAssetsMaximum) == numZero); + } + + // What _can't_ IOUs do? + // 1. Exceed maximum exponent / offset + tx[sfAssetsMaximum] = "1000000000000000e81"; + env(tx, ter(tefEXCEPTION), THISLINE); + env.close(); + + // 2. Mantissa larger than uint64 max + try + { + tx[sfAssetsMaximum] = + "18446744073709551617e5"; // uint64 max + 1 + env(tx, THISLINE); + BEAST_EXPECT(false); + } + catch (parse_error const& e) + { + using namespace std::string_literals; + BEAST_EXPECT( + e.what() == + "invalidParamsField 'tx_json.AssetsMaximum' has invalid " + "data."s); + } + } + } + public: void run() override @@ -5802,6 +6059,7 @@ public: testDelegate(); testVaultClawbackBurnShares(); testVaultClawbackAssets(); + testAssetsMaximum(); } }; From bb529d03175fc988a9d7b593bf60e21b6803cbb7 Mon Sep 17 00:00:00 2001 From: Jingchen Date: Mon, 26 Jan 2026 21:39:28 +0000 Subject: [PATCH 094/105] fix: Stop embedded tests from hanging on ARM by using `atomic_flag` (#6248) This change replaces the mutex `stoppingMutex_`, the `atomic_bool` variable `isTimeToStop`, and the conditional variable `stoppingCondition_` with an `atomic_flag` variable. When `xrpld` is running the embedded tests as a child process, it has a control thread (the app bundle thread) that starts the application, and an application thread (the thread that executes `app_->run()`). Due to the relaxed memory ordering on ARM, it's not guaranteed that the application thread can see the change of the value resulting from the `isTimeToStop.exchange(true)` call before it is notified by `stoppingCondition_.notify_all()`, even though they do happen in the right order in the app bundle thread in `ApplicationImp::signalStop`. We therefore often get into the situation where `isTimeToStop` is `true`, but the application thread is waiting for `stoppingCondition_` to notify, because the app bundle thread may have already notified before the application thread actually starts waiting. Switching to a single `atomic_flag` variable makes sure that there's only one synchronisation object and then the memory order guarantee provided by c++ can make sure that `notify_all` gets synchronised after `test_and_set` does. Fixing this issue will stop the unit tests hanging forever and then we should see less (or hopefully no) time out errors in daily github action runs --- src/xrpld/app/main/Application.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index 15abff9b14..785b02dbb8 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -203,11 +203,7 @@ public: boost::asio::signal_set m_signals; - // Once we get C++20, we could use `std::atomic_flag` for `isTimeToStop` - // and eliminate the need for the condition variable and the mutex. - std::condition_variable stoppingCondition_; - mutable std::mutex stoppingMutex_; - std::atomic isTimeToStop = false; + std::atomic_flag isTimeToStop; std::atomic checkSigs_; @@ -1539,10 +1535,7 @@ ApplicationImp::run() getLoadManager().activateStallDetector(); } - { - std::unique_lock lk{stoppingMutex_}; - stoppingCondition_.wait(lk, [this] { return isTimeToStop.load(); }); - } + isTimeToStop.wait(false, std::memory_order_relaxed); JLOG(m_journal.debug()) << "Application stopping"; @@ -1629,14 +1622,14 @@ ApplicationImp::run() void ApplicationImp::signalStop(std::string msg) { - if (!isTimeToStop.exchange(true)) + if (!isTimeToStop.test_and_set(std::memory_order_acquire)) { if (msg.empty()) JLOG(m_journal.warn()) << "Server stopping"; else JLOG(m_journal.warn()) << "Server stopping: " << msg; - stoppingCondition_.notify_all(); + isTimeToStop.notify_all(); } } @@ -1655,7 +1648,7 @@ ApplicationImp::checkSigs(bool check) bool ApplicationImp::isStopping() const { - return isTimeToStop.load(); + return isTimeToStop.test(std::memory_order_relaxed); } int From b90a843dddeb6df2acdc6a04b74386cbb892e8ff Mon Sep 17 00:00:00 2001 From: Bart Date: Wed, 28 Jan 2026 10:02:34 +0000 Subject: [PATCH 095/105] ci: Upload Conan recipes for develop, release candidates, and releases (#6286) To allow developers to consume the latest unstable and (near-)stable versions of our `xrpl` Conan recipe, we should export and upload it whenever a push occurs to the corresponding branch or a release tag has been created. This way, developers do not have to figure out themselves what the most recent shortened commit hash was to determine the latest unstable recipe version (e.g. `3.2.0-b0+a1b2c3d`) or what the most recent release (candidate) was to determine the latest (near-)stable recipe version (e.g. `3.1.0-rc2`). Now, pushes to the `develop` branch will produce the `develop` recipe version, pushes to the `release` branch will produce the `rc` recipe version, and creation of versioned tags will produce the `release` recipe version. --- .github/workflows/reusable-upload-recipe.yml | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/reusable-upload-recipe.yml b/.github/workflows/reusable-upload-recipe.yml index 156659392e..79af516fb3 100644 --- a/.github/workflows/reusable-upload-recipe.yml +++ b/.github/workflows/reusable-upload-recipe.yml @@ -62,12 +62,36 @@ jobs: REMOTE_PASSWORD: ${{ secrets.remote_password }} run: conan remote login "${REMOTE_NAME}" "${REMOTE_USERNAME}" --password "${REMOTE_PASSWORD}" - - name: Upload Conan recipe + - name: Upload Conan recipe (version) env: REMOTE_NAME: ${{ inputs.remote_name }} run: | conan export . --version=${{ steps.version.outputs.version }} conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }} + - name: Upload Conan recipe (develop) + if: ${{ github.ref == 'refs/heads/develop' }} + env: + REMOTE_NAME: ${{ inputs.remote_name }} + run: | + conan export . --version=develop + conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/develop + + - name: Upload Conan recipe (rc) + if: ${{ startsWith(github.ref, 'refs/heads/release') }} + env: + REMOTE_NAME: ${{ inputs.remote_name }} + run: | + conan export . --version=rc + conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/rc + + - name: Upload Conan recipe (release) + if: ${{ github.event_name == 'tag' }} + env: + REMOTE_NAME: ${{ inputs.remote_name }} + run: | + conan export . --version=release + conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/release + outputs: ref: xrpl/${{ steps.version.outputs.version }} From 92046785d1fea5f9efe5a770d636792ea6cab78b Mon Sep 17 00:00:00 2001 From: Jingchen Date: Wed, 28 Jan 2026 15:14:35 +0000 Subject: [PATCH 096/105] test: Fix the `xrpl.net` unit test using async read (#6241) This change makes the `read` function call in `handleConnection` async, adds a new class `TestSink` to help debugging, and adds a new target `xrpl.tests.helpers` to put the helper class in. --- src/tests/libxrpl/CMakeLists.txt | 12 +- src/tests/libxrpl/helpers/TestSink.cpp | 127 ++++++++++++ src/tests/libxrpl/helpers/TestSink.h | 27 +++ src/tests/libxrpl/net/HTTPClient.cpp | 273 ++++++++++++++----------- 4 files changed, 313 insertions(+), 126 deletions(-) create mode 100644 src/tests/libxrpl/helpers/TestSink.cpp create mode 100644 src/tests/libxrpl/helpers/TestSink.h diff --git a/src/tests/libxrpl/CMakeLists.txt b/src/tests/libxrpl/CMakeLists.txt index 74dc184700..72d7d0fa92 100644 --- a/src/tests/libxrpl/CMakeLists.txt +++ b/src/tests/libxrpl/CMakeLists.txt @@ -6,9 +6,19 @@ find_package(GTest REQUIRED) # Custom target for all tests defined in this file add_custom_target(xrpl.tests) +# Test helpers +add_library(xrpl.helpers.test STATIC) +target_sources(xrpl.helpers.test PRIVATE + helpers/TestSink.cpp +) +target_include_directories(xrpl.helpers.test PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) +target_link_libraries(xrpl.helpers.test PRIVATE xrpl.libxrpl) + # Common library dependencies for the rest of the tests. add_library(xrpl.imports.test INTERFACE) -target_link_libraries(xrpl.imports.test INTERFACE gtest::gtest xrpl.libxrpl) +target_link_libraries(xrpl.imports.test INTERFACE gtest::gtest xrpl.libxrpl xrpl.helpers.test) # One test for each module. xrpl_add_test(basics) diff --git a/src/tests/libxrpl/helpers/TestSink.cpp b/src/tests/libxrpl/helpers/TestSink.cpp new file mode 100644 index 0000000000..a71e9f7cc0 --- /dev/null +++ b/src/tests/libxrpl/helpers/TestSink.cpp @@ -0,0 +1,127 @@ +#include + +#include + +#include // for getenv + +#if BOOST_OS_WINDOWS +#include // for _isatty, _fileno +#include // for stdout +#else +#include // for isatty, STDOUT_FILENO +#endif + +#include + +namespace xrpl { + +TestSink::TestSink(beast::severities::Severity threshold) + : Sink(threshold, false) +{ +} + +void +TestSink::write(beast::severities::Severity level, std::string const& text) +{ + if (level < threshold()) + return; + writeAlways(level, text); +} + +void +TestSink::writeAlways( + beast::severities::Severity level, + std::string const& text) +{ + auto supportsColor = [] { + // 1. Check for "NO_COLOR" environment variable (Standard convention) + if (std::getenv("NO_COLOR") != nullptr) + { + return false; + } + + // 2. Check for "CLICOLOR_FORCE" (Force color) + if (std::getenv("CLICOLOR_FORCE") != nullptr) + { + return true; + } + + // 3. Platform-specific check to see if stdout is a terminal +#if BOOST_OS_WINDOWS + // Windows: Check if the output handle is a character device + // _fileno(stdout) is usually 1 + // _isatty returns non-zero if the handle is a character device, 0 + // otherwise. + return _isatty(_fileno(stdout)) != 0; +#else + // Linux/macOS: Check if file descriptor 1 (stdout) is a TTY + // STDOUT_FILENO is 1 + // isatty returns 1 if the file descriptor is a TTY, 0 otherwise. + return isatty(STDOUT_FILENO) != 0; +#endif + }(); + + auto color = [level]() { + switch (level) + { + case beast::severities::kTrace: + return "\033[34m"; // blue + case beast::severities::kDebug: + return "\033[32m"; // green + case beast::severities::kInfo: + return "\033[36m"; // cyan + case beast::severities::kWarning: + return "\033[33m"; // yellow + case beast::severities::kError: + return "\033[31m"; // red + case beast::severities::kFatal: + default: + break; + } + return "\033[31m"; // red + }(); + + auto prefix = [level]() { + switch (level) + { + case beast::severities::kTrace: + return "TRC:"; + case beast::severities::kDebug: + return "DBG:"; + case beast::severities::kInfo: + return "INF:"; + case beast::severities::kWarning: + return "WRN:"; + case beast::severities::kError: + return "ERR:"; + case beast::severities::kFatal: + default: + break; + } + return "FTL:"; + }(); + + auto& stream = [level]() -> std::ostream& { + switch (level) + { + case beast::severities::kError: + case beast::severities::kFatal: + return std::cerr; + default: + return std::cout; + } + }(); + + constexpr auto reset = "\033[0m"; + + if (supportsColor) + { + stream << color << prefix << " " << text << reset << std::endl; + } + else + { + stream << prefix << " " << text << std::endl; + } +} + +} // namespace xrpl diff --git a/src/tests/libxrpl/helpers/TestSink.h b/src/tests/libxrpl/helpers/TestSink.h new file mode 100644 index 0000000000..fc3223b04b --- /dev/null +++ b/src/tests/libxrpl/helpers/TestSink.h @@ -0,0 +1,27 @@ +#ifndef XRPL_DEBUGSINK_H +#define XRPL_DEBUGSINK_H + +#include + +namespace xrpl { +class TestSink : public beast::Journal::Sink +{ +public: + static TestSink& + instance() + { + static TestSink sink{}; + return sink; + } + + TestSink(beast::severities::Severity threshold = beast::severities::kDebug); + + void + write(beast::severities::Severity level, std::string const& text) override; + + void + writeAlways(beast::severities::Severity level, std::string const& text) + override; +}; +} // namespace xrpl +#endif // XRPL_DEBUGSINK_H diff --git a/src/tests/libxrpl/net/HTTPClient.cpp b/src/tests/libxrpl/net/HTTPClient.cpp index cfd206edde..5ff0bfc336 100644 --- a/src/tests/libxrpl/net/HTTPClient.cpp +++ b/src/tests/libxrpl/net/HTTPClient.cpp @@ -2,15 +2,22 @@ #include #include +#include +#include #include +#include +#include #include #include #include #include +#include #include #include +#include +#include #include using namespace xrpl; @@ -24,16 +31,19 @@ private: boost::asio::io_context ioc_; boost::asio::ip::tcp::acceptor acceptor_; boost::asio::ip::tcp::endpoint endpoint_; - std::atomic running_{true}; + bool running_{true}; + bool finished_{false}; unsigned short port_; // Custom headers to return - std::map custom_headers_; - std::string response_body_; - unsigned int status_code_{200}; + std::map customHeaders_; + std::string responseBody_; + unsigned int statusCode_{200}; + + beast::Journal j_; public: - TestHTTPServer() : acceptor_(ioc_), port_(0) + TestHTTPServer() : acceptor_(ioc_), port_(0), j_(TestSink::instance()) { // Bind to any available port endpoint_ = {boost::asio::ip::tcp::v4(), 0}; @@ -45,12 +55,19 @@ public: // Get the actual port that was assigned port_ = acceptor_.local_endpoint().port(); - accept(); + // Start the accept coroutine + boost::asio::co_spawn(ioc_, accept(), boost::asio::detached); } + TestHTTPServer(TestHTTPServer&&) = delete; + TestHTTPServer& + operator=(TestHTTPServer&&) = delete; + ~TestHTTPServer() { - stop(); + XRPL_ASSERT( + finished(), + "xrpl::TestHTTPServer::~TestHTTPServer : accept future ready"); } boost::asio::io_context& @@ -68,22 +85,21 @@ public: void setHeader(std::string const& name, std::string const& value) { - custom_headers_[name] = value; + customHeaders_[name] = value; } void setResponseBody(std::string const& body) { - response_body_ = body; + responseBody_ = body; } void setStatusCode(unsigned int code) { - status_code_ = code; + statusCode_ = code; } -private: void stop() { @@ -91,78 +107,84 @@ private: acceptor_.close(); } - void - accept() + bool + finished() const { - if (!running_) - return; - - acceptor_.async_accept( - ioc_, - endpoint_, - [&](boost::system::error_code const& error, - boost::asio::ip::tcp::socket peer) { - if (!running_) - return; - - if (!error) - { - handleConnection(std::move(peer)); - } - }); + return finished_; } - void +private: + boost::asio::awaitable + accept() + { + while (running_) + { + try + { + auto socket = + co_await acceptor_.async_accept(boost::asio::use_awaitable); + + if (!running_) + break; + + // Handle this connection + co_await handleConnection(std::move(socket)); + } + catch (std::exception const& e) + { + // Accept or handle failed, stop accepting + JLOG(j_.debug()) << "Error: " << e.what(); + break; + } + } + + finished_ = true; + } + + boost::asio::awaitable handleConnection(boost::asio::ip::tcp::socket socket) { try { - // Read the HTTP request boost::beast::flat_buffer buffer; boost::beast::http::request req; - boost::beast::http::read(socket, buffer, req); + + // Read the HTTP request asynchronously + co_await boost::beast::http::async_read( + socket, buffer, req, boost::asio::use_awaitable); // Create response boost::beast::http::response res; res.version(req.version()); - res.result(status_code_); + res.result(statusCode_); res.set(boost::beast::http::field::server, "TestServer"); - // Add custom headers - for (auto const& [name, value] : custom_headers_) + // Set body and prepare payload first + res.body() = responseBody_; + res.prepare_payload(); + + // Override Content-Length with custom headers after + // prepare_payload. This allows us to test case-insensitive + // header parsing. + for (auto const& [name, value] : customHeaders_) { res.set(name, value); } - // Set body and prepare payload first - res.body() = response_body_; - res.prepare_payload(); - - // Override Content-Length with custom headers after prepare_payload - // This allows us to test case-insensitive header parsing - for (auto const& [name, value] : custom_headers_) - { - if (boost::iequals(name, "Content-Length")) - { - res.erase(boost::beast::http::field::content_length); - res.set(name, value); - } - } - - // Send response - boost::beast::http::write(socket, res); + // Send response asynchronously + co_await boost::beast::http::async_write( + socket, res, boost::asio::use_awaitable); // Shutdown socket gracefully - boost::system::error_code ec; - socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); + boost::system::error_code shutdownEc; + socket.shutdown( + boost::asio::ip::tcp::socket::shutdown_send, shutdownEc); } - catch (std::exception const&) + catch (std::exception const& e) { - // Connection handling errors are expected + // Error reading or writing, just close the connection + JLOG(j_.debug()) << "Connection error: " << e.what(); } - - if (running_) - accept(); } }; @@ -171,13 +193,13 @@ bool runHTTPTest( TestHTTPServer& server, std::string const& path, - std::atomic& completed, - std::atomic& result_status, - std::string& result_data, - boost::system::error_code& result_error) + bool& completed, + int& resultStatus, + std::string& resultData, + boost::system::error_code& resultError) { // Create a null journal for testing - beast::Journal j{beast::Journal::getNullSink()}; + beast::Journal j{TestSink::instance()}; // Initialize HTTPClient SSL context HTTPClient::initializeSSLContext("", "", false, j); @@ -193,9 +215,9 @@ runHTTPTest( [&](boost::system::error_code const& ec, int status, std::string const& data) -> bool { - result_error = ec; - result_status = status; - result_data = data; + resultError = ec; + resultStatus = status; + resultData = data; completed = true; return false; // don't retry }, @@ -203,13 +225,19 @@ runHTTPTest( // Run the IO context until completion auto start = std::chrono::steady_clock::now(); - while (!completed && - std::chrono::steady_clock::now() - start < std::chrono::seconds(10)) + while (server.ioc().run_one() != 0) { - if (server.ioc().run_one() == 0) + if (std::chrono::steady_clock::now() - start >= + std::chrono::seconds(10) || + server.finished()) { break; } + + if (completed) + { + server.stop(); + } } return completed; @@ -220,7 +248,7 @@ runHTTPTest( TEST(HTTPClient, case_insensitive_content_length) { // Test different cases of Content-Length header - std::vector header_cases = { + std::vector headerCases = { "Content-Length", // Standard case "content-length", // Lowercase - this tests the regex icase fix "CONTENT-LENGTH", // Uppercase @@ -228,53 +256,48 @@ TEST(HTTPClient, case_insensitive_content_length) "content-Length" // Mixed case 2 }; - for (auto const& header_name : header_cases) + for (auto const& headerName : headerCases) { TestHTTPServer server; - std::string test_body = "Hello World!"; - server.setResponseBody(test_body); - server.setHeader(header_name, std::to_string(test_body.size())); + std::string testBody = "Hello World!"; + server.setResponseBody(testBody); + server.setHeader(headerName, std::to_string(testBody.size())); - std::atomic completed{false}; - std::atomic result_status{0}; - std::string result_data; - boost::system::error_code result_error; + bool completed{false}; + int resultStatus{0}; + std::string resultData; + boost::system::error_code resultError; - bool test_completed = runHTTPTest( - server, - "/test", - completed, - result_status, - result_data, - result_error); + bool testCompleted = runHTTPTest( + server, "/test", completed, resultStatus, resultData, resultError); // Verify results - EXPECT_TRUE(test_completed); - EXPECT_FALSE(result_error); - EXPECT_EQ(result_status, 200); - EXPECT_EQ(result_data, test_body); + EXPECT_TRUE(testCompleted); + EXPECT_FALSE(resultError); + EXPECT_EQ(resultStatus, 200); + EXPECT_EQ(resultData, testBody); } } TEST(HTTPClient, basic_http_request) { TestHTTPServer server; - std::string test_body = "Test response body"; - server.setResponseBody(test_body); + std::string testBody = "Test response body"; + server.setResponseBody(testBody); server.setHeader("Content-Type", "text/plain"); - std::atomic completed{false}; - std::atomic result_status{0}; - std::string result_data; - boost::system::error_code result_error; + bool completed{false}; + int resultStatus{0}; + std::string resultData; + boost::system::error_code resultError; - bool test_completed = runHTTPTest( - server, "/basic", completed, result_status, result_data, result_error); + bool testCompleted = runHTTPTest( + server, "/basic", completed, resultStatus, resultData, resultError); - EXPECT_TRUE(test_completed); - EXPECT_FALSE(result_error); - EXPECT_EQ(result_status, 200); - EXPECT_EQ(result_data, test_body); + EXPECT_TRUE(testCompleted); + EXPECT_FALSE(resultError); + EXPECT_EQ(resultStatus, 200); + EXPECT_EQ(resultData, testBody); } TEST(HTTPClient, empty_response) @@ -283,45 +306,45 @@ TEST(HTTPClient, empty_response) server.setResponseBody(""); // Empty body server.setHeader("Content-Length", "0"); - std::atomic completed{false}; - std::atomic result_status{0}; - std::string result_data; - boost::system::error_code result_error; + bool completed{false}; + int resultStatus{0}; + std::string resultData; + boost::system::error_code resultError; - bool test_completed = runHTTPTest( - server, "/empty", completed, result_status, result_data, result_error); + bool testCompleted = runHTTPTest( + server, "/empty", completed, resultStatus, resultData, resultError); - EXPECT_TRUE(test_completed); - EXPECT_FALSE(result_error); - EXPECT_EQ(result_status, 200); - EXPECT_TRUE(result_data.empty()); + EXPECT_TRUE(testCompleted); + EXPECT_FALSE(resultError); + EXPECT_EQ(resultStatus, 200); + EXPECT_TRUE(resultData.empty()); } TEST(HTTPClient, different_status_codes) { - std::vector status_codes = {200, 404, 500}; + std::vector statusCodes = {200, 404, 500}; - for (auto status : status_codes) + for (auto status : statusCodes) { TestHTTPServer server; server.setStatusCode(status); server.setResponseBody("Status " + std::to_string(status)); - std::atomic completed{false}; - std::atomic result_status{0}; - std::string result_data; - boost::system::error_code result_error; + bool completed{false}; + int resultStatus{0}; + std::string resultData; + boost::system::error_code resultError; - bool test_completed = runHTTPTest( + bool testCompleted = runHTTPTest( server, "/status", completed, - result_status, - result_data, - result_error); + resultStatus, + resultData, + resultError); - EXPECT_TRUE(test_completed); - EXPECT_FALSE(result_error); - EXPECT_EQ(result_status, static_cast(status)); + EXPECT_TRUE(testCompleted); + EXPECT_FALSE(resultError); + EXPECT_EQ(resultStatus, static_cast(status)); } } From 5f638f55536def0d88b970d1018a465a238e55f4 Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 28 Jan 2026 18:09:50 +0000 Subject: [PATCH 097/105] chore: Set ColumnLimit to 120 in clang-format (#6288) This change updates the ColumnLimit from 80 to 120, and applies clang-format to reformat the code. --- .clang-format | 2 +- include/xrpl/basics/Archive.h | 4 +- include/xrpl/basics/BasicConfig.h | 24 +- include/xrpl/basics/Buffer.h | 9 +- include/xrpl/basics/CompressionAlgorithms.h | 24 +- include/xrpl/basics/DecayingSample.h | 4 +- include/xrpl/basics/Expected.h | 12 +- include/xrpl/basics/FileUtilities.h | 5 +- include/xrpl/basics/IntrusivePointer.h | 20 +- include/xrpl/basics/IntrusivePointer.ipp | 37 +- include/xrpl/basics/IntrusiveRefCounts.h | 53 +- include/xrpl/basics/LocalValue.h | 7 +- include/xrpl/basics/Log.h | 27 +- include/xrpl/basics/Number.h | 72 +- include/xrpl/basics/Resolver.h | 7 +- .../xrpl/basics/SharedWeakCachePointer.ipp | 16 +- include/xrpl/basics/SlabAllocator.h | 66 +- include/xrpl/basics/Slice.h | 25 +- include/xrpl/basics/StringUtilities.h | 3 +- include/xrpl/basics/TaggedCache.h | 40 +- include/xrpl/basics/TaggedCache.ipp | 378 +- include/xrpl/basics/UnorderedContainers.h | 12 +- include/xrpl/basics/algorithm.h | 8 +- include/xrpl/basics/base64.h | 3 +- include/xrpl/basics/base_uint.h | 40 +- include/xrpl/basics/chrono.h | 16 +- include/xrpl/basics/contract.h | 9 +- include/xrpl/basics/join.h | 12 +- .../xrpl/basics/partitioned_unordered_map.h | 25 +- include/xrpl/basics/random.h | 29 +- include/xrpl/basics/safe_cast.h | 46 +- include/xrpl/basics/scope.h | 47 +- include/xrpl/basics/spinlock.h | 12 +- include/xrpl/basics/strHex.h | 4 +- include/xrpl/basics/tagged_integer.h | 12 +- include/xrpl/beast/asio/io_latency_probe.h | 41 +- include/xrpl/beast/clock/manual_clock.h | 10 +- .../beast/container/aged_container_utility.h | 8 +- include/xrpl/beast/container/aged_map.h | 3 +- include/xrpl/beast/container/aged_multimap.h | 3 +- include/xrpl/beast/container/aged_multiset.h | 3 +- include/xrpl/beast/container/aged_set.h | 3 +- .../xrpl/beast/container/aged_unordered_map.h | 10 +- .../beast/container/aged_unordered_multimap.h | 10 +- .../beast/container/aged_unordered_multiset.h | 11 +- .../xrpl/beast/container/aged_unordered_set.h | 10 +- .../detail/aged_container_iterator.h | 31 +- .../container/detail/aged_ordered_container.h | 1143 ++----- .../detail/aged_unordered_container.h | 1944 ++--------- .../detail/empty_base_optimization.h | 9 +- include/xrpl/beast/core/CurrentThreadName.h | 4 +- include/xrpl/beast/core/LexicalCast.h | 21 +- include/xrpl/beast/core/List.h | 3 +- include/xrpl/beast/core/LockFreeStack.h | 34 +- include/xrpl/beast/hash/hash_append.h | 93 +- include/xrpl/beast/hash/xxhasher.h | 14 +- include/xrpl/beast/insight/StatsDCollector.h | 4 +- include/xrpl/beast/rfc2616.h | 34 +- include/xrpl/beast/test/yield_to.h | 7 +- include/xrpl/beast/unit_test/global_suites.h | 7 +- include/xrpl/beast/unit_test/match.h | 3 +- include/xrpl/beast/unit_test/reporter.h | 18 +- include/xrpl/beast/unit_test/results.h | 3 +- include/xrpl/beast/unit_test/suite.h | 37 +- include/xrpl/beast/unit_test/suite_info.h | 28 +- include/xrpl/beast/unit_test/suite_list.h | 17 +- include/xrpl/beast/unit_test/thread.h | 3 +- include/xrpl/beast/utility/Journal.h | 21 +- include/xrpl/beast/utility/WrappedSink.h | 8 +- include/xrpl/beast/utility/instrumentation.h | 3 +- include/xrpl/beast/utility/maybe_const.h | 6 +- include/xrpl/beast/utility/rngfill.h | 5 +- include/xrpl/core/ClosureCounter.h | 15 +- include/xrpl/core/Coro.ipp | 17 +- include/xrpl/core/Job.h | 6 +- include/xrpl/core/JobQueue.h | 15 +- include/xrpl/core/JobTypeData.h | 15 +- include/xrpl/core/JobTypeInfo.h | 6 +- include/xrpl/core/JobTypes.h | 19 +- include/xrpl/core/LoadMonitor.h | 4 +- include/xrpl/core/PerfLog.h | 18 +- include/xrpl/core/detail/Workers.h | 27 +- include/xrpl/json/Output.h | 4 +- include/xrpl/json/json_reader.h | 17 +- include/xrpl/json/json_value.h | 6 +- include/xrpl/json/json_writer.h | 5 +- include/xrpl/ledger/ApplyView.h | 48 +- include/xrpl/ledger/ApplyViewImpl.h | 8 +- include/xrpl/ledger/BookDirs.h | 5 +- include/xrpl/ledger/CachedView.h | 7 +- include/xrpl/ledger/CredentialHelpers.h | 26 +- include/xrpl/ledger/Credit.h | 18 +- include/xrpl/ledger/OpenView.h | 25 +- include/xrpl/ledger/PaymentSandbox.h | 37 +- include/xrpl/ledger/ReadView.h | 16 +- include/xrpl/ledger/View.h | 290 +- include/xrpl/ledger/detail/ApplyStateTable.h | 18 +- include/xrpl/ledger/detail/ApplyViewBase.h | 4 +- include/xrpl/ledger/detail/RawStateTable.h | 22 +- include/xrpl/ledger/detail/ReadViewFwdRange.h | 4 +- .../xrpl/ledger/detail/ReadViewFwdRange.ipp | 18 +- include/xrpl/net/AutoSocket.h | 73 +- include/xrpl/net/HTTPClient.h | 21 +- include/xrpl/net/HTTPClientSSLContext.h | 53 +- include/xrpl/net/RegisterSSLCerts.h | 5 +- include/xrpl/nodestore/Backend.h | 4 +- include/xrpl/nodestore/Database.h | 28 +- include/xrpl/nodestore/DatabaseRotating.h | 10 +- include/xrpl/nodestore/Manager.h | 6 +- include/xrpl/nodestore/NodeObject.h | 6 +- .../xrpl/nodestore/detail/DatabaseNodeImp.h | 27 +- .../nodestore/detail/DatabaseRotatingImp.h | 13 +- include/xrpl/nodestore/detail/EncodedBlob.h | 16 +- include/xrpl/nodestore/detail/ManagerImp.h | 7 +- include/xrpl/nodestore/detail/codec.h | 58 +- include/xrpl/protocol/AMMCore.h | 12 +- include/xrpl/protocol/AmountConversions.h | 28 +- include/xrpl/protocol/ApiVersion.h | 41 +- include/xrpl/protocol/Asset.h | 25 +- include/xrpl/protocol/Batch.h | 5 +- include/xrpl/protocol/Book.h | 22 +- include/xrpl/protocol/ErrorCodes.h | 25 +- include/xrpl/protocol/Feature.h | 13 +- include/xrpl/protocol/HashPrefix.h | 3 +- include/xrpl/protocol/IOUAmount.h | 12 +- include/xrpl/protocol/Indexes.h | 17 +- include/xrpl/protocol/Issue.h | 3 +- include/xrpl/protocol/KnownFormats.h | 10 +- include/xrpl/protocol/MPTAmount.h | 6 +- include/xrpl/protocol/MultiApiJson.h | 87 +- .../xrpl/protocol/NFTSyntheticSerializer.h | 5 +- include/xrpl/protocol/NFTokenID.h | 9 +- include/xrpl/protocol/NFTokenOfferID.h | 4 +- include/xrpl/protocol/PayChan.h | 5 +- include/xrpl/protocol/Permissions.h | 3 +- include/xrpl/protocol/Protocol.h | 3 +- include/xrpl/protocol/PublicKey.h | 9 +- include/xrpl/protocol/Quality.h | 80 +- include/xrpl/protocol/QualityFunction.h | 10 +- include/xrpl/protocol/Rate.h | 12 +- include/xrpl/protocol/Rules.h | 11 +- include/xrpl/protocol/SField.h | 24 +- include/xrpl/protocol/SOTemplate.h | 15 +- include/xrpl/protocol/STAmount.h | 106 +- include/xrpl/protocol/STArray.h | 11 +- include/xrpl/protocol/STBitString.h | 13 +- include/xrpl/protocol/STBlob.h | 9 +- include/xrpl/protocol/STExchange.h | 8 +- include/xrpl/protocol/STInteger.h | 10 +- include/xrpl/protocol/STIssue.h | 9 +- include/xrpl/protocol/STLedgerEntry.h | 12 +- include/xrpl/protocol/STObject.h | 63 +- include/xrpl/protocol/STPathSet.h | 39 +- include/xrpl/protocol/STTx.h | 12 +- include/xrpl/protocol/STValidation.h | 45 +- include/xrpl/protocol/STVector256.h | 12 +- include/xrpl/protocol/STXChainBridge.h | 24 +- include/xrpl/protocol/SecretKey.h | 3 +- include/xrpl/protocol/Serializer.h | 12 +- include/xrpl/protocol/Sign.h | 13 +- include/xrpl/protocol/TER.h | 53 +- include/xrpl/protocol/Units.h | 48 +- include/xrpl/protocol/XChainAttestations.h | 31 +- include/xrpl/protocol/XRPAmount.h | 12 +- include/xrpl/protocol/detail/b58_utils.h | 17 +- include/xrpl/protocol/detail/secp256k1.h | 4 +- include/xrpl/protocol/json_get_or_throw.h | 6 +- include/xrpl/protocol/nftPageMask.h | 3 +- include/xrpl/protocol/tokens.h | 20 +- include/xrpl/resource/ResourceManager.h | 9 +- include/xrpl/resource/detail/Entry.h | 6 +- include/xrpl/resource/detail/Logic.h | 53 +- include/xrpl/server/Handoff.h | 6 +- include/xrpl/server/Server.h | 5 +- include/xrpl/server/Session.h | 4 +- include/xrpl/server/SimpleWriter.h | 3 +- include/xrpl/server/WSSession.h | 3 +- include/xrpl/server/detail/BaseHTTPPeer.h | 101 +- include/xrpl/server/detail/BasePeer.h | 3 +- include/xrpl/server/detail/BaseWSPeer.h | 125 +- include/xrpl/server/detail/Door.h | 135 +- include/xrpl/server/detail/JSONRPCUtil.h | 6 +- include/xrpl/server/detail/PlainHTTPPeer.h | 27 +- include/xrpl/server/detail/SSLHTTPPeer.h | 50 +- include/xrpl/server/detail/ServerImpl.h | 20 +- include/xrpl/server/detail/Spawn.h | 12 +- include/xrpl/server/detail/io_list.h | 3 +- include/xrpl/shamap/FullBelowCache.h | 3 +- include/xrpl/shamap/SHAMap.h | 122 +- .../xrpl/shamap/SHAMapAccountStateLeafNode.h | 19 +- include/xrpl/shamap/SHAMapAddNode.h | 3 +- include/xrpl/shamap/SHAMapInnerNode.h | 7 +- include/xrpl/shamap/SHAMapItem.h | 12 +- include/xrpl/shamap/SHAMapLeafNode.h | 9 +- include/xrpl/shamap/SHAMapMissingNode.h | 9 +- include/xrpl/shamap/SHAMapNodeID.h | 3 +- include/xrpl/shamap/SHAMapSyncFilter.h | 8 +- include/xrpl/shamap/SHAMapTreeNode.h | 5 +- include/xrpl/shamap/SHAMapTxLeafNode.h | 15 +- .../xrpl/shamap/SHAMapTxPlusMetaLeafNode.h | 19 +- include/xrpl/shamap/detail/TaggedPointer.h | 14 +- include/xrpl/shamap/detail/TaggedPointer.ipp | 87 +- src/libxrpl/basics/Archive.cpp | 28 +- src/libxrpl/basics/BasicConfig.cpp | 16 +- src/libxrpl/basics/FileUtilities.cpp | 12 +- src/libxrpl/basics/Log.cpp | 24 +- src/libxrpl/basics/Number.cpp | 122 +- src/libxrpl/basics/ResolverAsio.cpp | 124 +- src/libxrpl/basics/base64.cpp | 55 +- src/libxrpl/basics/make_SSLContext.cpp | 54 +- .../beast/clock/basic_seconds_clock.cpp | 7 +- src/libxrpl/beast/core/CurrentThreadName.cpp | 13 +- src/libxrpl/beast/core/SemanticVersion.cpp | 49 +- src/libxrpl/beast/insight/Groups.cpp | 9 +- src/libxrpl/beast/insight/StatsDCollector.cpp | 140 +- src/libxrpl/beast/net/IPAddressV4.cpp | 9 +- src/libxrpl/beast/net/IPAddressV6.cpp | 4 +- src/libxrpl/beast/net/IPEndpoint.cpp | 10 +- src/libxrpl/beast/utility/beast_Journal.cpp | 10 +- .../beast/utility/beast_PropertyStream.cpp | 29 +- src/libxrpl/core/detail/Job.cpp | 13 +- src/libxrpl/core/detail/JobQueue.cpp | 101 +- src/libxrpl/core/detail/LoadEvent.cpp | 5 +- src/libxrpl/core/detail/LoadMonitor.cpp | 21 +- src/libxrpl/core/detail/Workers.cpp | 21 +- src/libxrpl/crypto/RFC1751.cpp | 400 +-- src/libxrpl/crypto/csprng.cpp | 8 +- src/libxrpl/json/Writer.cpp | 5 +- src/libxrpl/json/json_reader.cpp | 115 +- src/libxrpl/json/json_value.cpp | 134 +- src/libxrpl/json/json_valueiterator.cpp | 20 +- src/libxrpl/json/json_writer.cpp | 38 +- src/libxrpl/ledger/ApplyStateTable.cpp | 99 +- src/libxrpl/ledger/ApplyView.cpp | 31 +- src/libxrpl/ledger/ApplyViewBase.cpp | 9 +- src/libxrpl/ledger/ApplyViewImpl.cpp | 3 +- src/libxrpl/ledger/BookDirs.cpp | 28 +- src/libxrpl/ledger/CachedView.cpp | 3 +- src/libxrpl/ledger/CredentialHelpers.cpp | 65 +- src/libxrpl/ledger/Credit.cpp | 37 +- src/libxrpl/ledger/Dir.cpp | 15 +- src/libxrpl/ledger/OpenView.cpp | 33 +- src/libxrpl/ledger/PaymentSandbox.cpp | 43 +- src/libxrpl/ledger/RawStateTable.cpp | 35 +- src/libxrpl/ledger/ReadView.cpp | 4 +- src/libxrpl/ledger/View.cpp | 1065 ++---- src/libxrpl/net/HTTPClient.cpp | 190 +- src/libxrpl/net/RegisterSSLCerts.cpp | 21 +- src/libxrpl/nodestore/BatchWriter.cpp | 13 +- src/libxrpl/nodestore/Database.cpp | 51 +- src/libxrpl/nodestore/DatabaseNodeImp.cpp | 53 +- src/libxrpl/nodestore/DatabaseRotatingImp.cpp | 19 +- src/libxrpl/nodestore/DecodedBlob.cpp | 7 +- src/libxrpl/nodestore/ManagerImp.cpp | 26 +- src/libxrpl/nodestore/NodeObject.cpp | 9 +- .../nodestore/backend/MemoryFactory.cpp | 18 +- src/libxrpl/nodestore/backend/NuDBFactory.cpp | 68 +- src/libxrpl/nodestore/backend/NullFactory.cpp | 7 +- .../nodestore/backend/RocksDBFactory.cpp | 87 +- src/libxrpl/protocol/AMMCore.cpp | 29 +- src/libxrpl/protocol/AccountID.cpp | 7 +- src/libxrpl/protocol/Asset.cpp | 10 +- src/libxrpl/protocol/Book.cpp | 3 +- src/libxrpl/protocol/BuildInfo.cpp | 13 +- src/libxrpl/protocol/ErrorCodes.cpp | 4 +- src/libxrpl/protocol/Feature.cpp | 68 +- src/libxrpl/protocol/IOUAmount.cpp | 21 +- src/libxrpl/protocol/Indexes.cpp | 128 +- src/libxrpl/protocol/InnerObjectFormats.cpp | 4 +- src/libxrpl/protocol/Issue.cpp | 9 +- src/libxrpl/protocol/Keylet.cpp | 4 +- src/libxrpl/protocol/LedgerFormats.cpp | 3 +- src/libxrpl/protocol/LedgerHeader.cpp | 3 +- src/libxrpl/protocol/MPTIssue.cpp | 9 +- src/libxrpl/protocol/NFTokenID.cpp | 62 +- src/libxrpl/protocol/NFTokenOfferID.cpp | 10 +- src/libxrpl/protocol/Permissions.cpp | 24 +- src/libxrpl/protocol/PublicKey.cpp | 50 +- src/libxrpl/protocol/Quality.cpp | 63 +- src/libxrpl/protocol/QualityFunction.cpp | 5 +- src/libxrpl/protocol/Rate2.cpp | 18 +- src/libxrpl/protocol/Rules.cpp | 17 +- src/libxrpl/protocol/SField.cpp | 38 +- src/libxrpl/protocol/SOTemplate.cpp | 4 +- src/libxrpl/protocol/STAccount.cpp | 16 +- src/libxrpl/protocol/STAmount.cpp | 269 +- src/libxrpl/protocol/STArray.cpp | 9 +- src/libxrpl/protocol/STBase.cpp | 7 +- src/libxrpl/protocol/STBlob.cpp | 6 +- src/libxrpl/protocol/STCurrency.cpp | 9 +- src/libxrpl/protocol/STInteger.cpp | 53 +- src/libxrpl/protocol/STIssue.cpp | 11 +- src/libxrpl/protocol/STLedgerEntry.cpp | 35 +- src/libxrpl/protocol/STNumber.cpp | 40 +- src/libxrpl/protocol/STObject.cpp | 75 +- src/libxrpl/protocol/STParsedJSON.cpp | 252 +- src/libxrpl/protocol/STPathSet.cpp | 21 +- src/libxrpl/protocol/STTakesAsset.cpp | 10 +- src/libxrpl/protocol/STTx.cpp | 84 +- src/libxrpl/protocol/STValidation.cpp | 8 +- src/libxrpl/protocol/STVar.cpp | 17 +- src/libxrpl/protocol/STVector256.cpp | 11 +- src/libxrpl/protocol/STXChainBridge.cpp | 52 +- src/libxrpl/protocol/SecretKey.cpp | 45 +- src/libxrpl/protocol/Seed.cpp | 6 +- src/libxrpl/protocol/Serializer.cpp | 29 +- src/libxrpl/protocol/Sign.cpp | 16 +- src/libxrpl/protocol/TER.cpp | 12 +- src/libxrpl/protocol/TxFormats.cpp | 3 +- src/libxrpl/protocol/TxMeta.cpp | 50 +- src/libxrpl/protocol/UintTypes.cpp | 12 +- src/libxrpl/protocol/XChainAttestations.cpp | 138 +- src/libxrpl/protocol/digest.cpp | 17 +- src/libxrpl/protocol/tokens.cpp | 83 +- src/libxrpl/resource/Charge.cpp | 3 +- src/libxrpl/resource/Consumer.cpp | 9 +- src/libxrpl/resource/ResourceManager.cpp | 22 +- src/libxrpl/server/JSONRPCUtil.cpp | 12 +- src/libxrpl/server/Port.cpp | 50 +- src/libxrpl/shamap/SHAMap.cpp | 257 +- src/libxrpl/shamap/SHAMapDelta.cpp | 91 +- src/libxrpl/shamap/SHAMapInnerNode.cpp | 145 +- src/libxrpl/shamap/SHAMapLeafNode.cpp | 12 +- src/libxrpl/shamap/SHAMapNodeID.cpp | 29 +- src/libxrpl/shamap/SHAMapSync.cpp | 176 +- src/libxrpl/shamap/SHAMapTreeNode.cpp | 49 +- src/test/app/AMMCalc_test.cpp | 39 +- src/test/app/AMMClawback_test.cpp | 885 ++--- src/test/app/AMMExtended_test.cpp | 851 ++--- src/test/app/AMM_test.cpp | 3048 ++++------------- src/test/app/AccountDelete_test.cpp | 194 +- src/test/app/AccountTxPaging_test.cpp | 4 +- src/test/app/AmendmentTable_test.cpp | 393 +-- src/test/app/Batch_test.cpp | 447 +-- src/test/app/Check_test.cpp | 415 +-- src/test/app/Clawback_test.cpp | 4 +- src/test/app/Credentials_test.cpp | 369 +- src/test/app/CrossingLimits_test.cpp | 12 +- src/test/app/DID_test.cpp | 24 +- src/test/app/DNS_test.cpp | 18 +- src/test/app/Delegate_test.cpp | 399 +-- src/test/app/DeliverMin_test.cpp | 22 +- src/test/app/DepositAuth_test.cpp | 353 +- src/test/app/Discrepancy_test.cpp | 29 +- src/test/app/EscrowToken_test.cpp | 555 +-- src/test/app/Escrow_test.cpp | 338 +- src/test/app/FeeVote_test.cpp | 261 +- src/test/app/FixNFTokenPageLinks_test.cpp | 164 +- src/test/app/Flow_test.cpp | 189 +- src/test/app/Freeze_test.cpp | 403 +-- src/test/app/HashRouter_test.cpp | 4 +- src/test/app/Invariants_test.cpp | 1239 +++---- src/test/app/LPTokenTransfer_test.cpp | 98 +- src/test/app/LedgerHistory_test.cpp | 54 +- src/test/app/LedgerLoad_test.cpp | 103 +- src/test/app/LedgerMaster_test.cpp | 21 +- src/test/app/LedgerReplay_test.cpp | 357 +- src/test/app/LendingHelpers_test.cpp | 554 +-- src/test/app/LoadFeeTrack_test.cpp | 30 +- src/test/app/LoanBroker_test.cpp | 562 +-- src/test/app/Loan_test.cpp | 2724 +++++---------- src/test/app/MPToken_test.cpp | 998 ++---- src/test/app/Manifest_test.cpp | 425 +-- src/test/app/MultiSign_test.cpp | 325 +- src/test/app/NFTokenAuth_test.cpp | 82 +- src/test/app/NFTokenBurn_test.cpp | 383 +-- src/test/app/NFTokenDir_test.cpp | 610 ++-- src/test/app/NFToken_test.cpp | 2353 ++++--------- src/test/app/NetworkID_test.cpp | 9 +- src/test/app/NetworkOPs_test.cpp | 15 +- src/test/app/Offer_test.cpp | 534 +-- src/test/app/Oracle_test.cpp | 330 +- src/test/app/OversizeMeta_test.cpp | 3 +- src/test/app/Path_test.cpp | 674 +--- src/test/app/PayChan_test.cpp | 529 +-- src/test/app/PayStrand_test.cpp | 189 +- src/test/app/PermissionedDEX_test.cpp | 574 +--- src/test/app/PermissionedDomains_test.cpp | 125 +- src/test/app/PseudoTx_test.cpp | 18 +- src/test/app/RCLValidations_test.cpp | 37 +- src/test/app/ReducedOffer_test.cpp | 215 +- src/test/app/Regression_test.cpp | 60 +- src/test/app/SHAMapStore_test.cpp | 151 +- src/test/app/SetAuth_test.cpp | 11 +- src/test/app/SetRegularKey_test.cpp | 24 +- src/test/app/SetTrust_test.cpp | 69 +- src/test/app/TheoreticalQuality_test.cpp | 112 +- src/test/app/Ticket_test.cpp | 198 +- src/test/app/Transaction_ordering_test.cpp | 39 +- src/test/app/TrustAndBalance_test.cpp | 89 +- src/test/app/TxQ_test.cpp | 1198 ++----- src/test/app/ValidatorKeys_test.cpp | 21 +- src/test/app/ValidatorList_test.cpp | 1308 ++----- src/test/app/ValidatorSite_test.cpp | 279 +- src/test/app/Vault_test.cpp | 2477 ++++---------- src/test/app/XChain_test.cpp | 1587 ++------- src/test/app/tx/apply_test.cpp | 3 +- src/test/basics/Buffer_test.cpp | 10 +- src/test/basics/Expected_test.cpp | 47 +- src/test/basics/FileUtilities_test.cpp | 12 +- src/test/basics/IOUAmount_test.cpp | 15 +- src/test/basics/IntrusiveShared_test.cpp | 87 +- src/test/basics/Number_test.cpp | 714 +--- src/test/basics/PerfLog_test.cpp | 196 +- src/test/basics/StringUtilities_test.cpp | 9 +- src/test/basics/Units_test.cpp | 62 +- src/test/basics/XRPAmount_test.cpp | 40 +- src/test/basics/base58_test.cpp | 131 +- src/test/basics/base_uint_test.cpp | 48 +- src/test/basics/hardened_hash_test.cpp | 17 +- src/test/basics/join_test.cpp | 21 +- src/test/beast/IPEndpointCommon.h | 4 +- src/test/beast/IPEndpoint_test.cpp | 44 +- src/test/beast/SemanticVersion_test.cpp | 10 +- .../beast/aged_associative_container_test.cpp | 263 +- .../beast/beast_CurrentThreadName_test.cpp | 14 +- src/test/beast/beast_PropertyStream_test.cpp | 21 +- src/test/beast/beast_abstract_clock_test.cpp | 10 +- .../beast/beast_io_latency_probe_test.cpp | 44 +- src/test/beast/define_print.cpp | 7 +- src/test/beast/xxhasher_test.cpp | 39 +- .../consensus/ByzantineFailureSim_test.cpp | 15 +- src/test/consensus/Consensus_test.cpp | 341 +- .../DistributedValidatorsSim_test.cpp | 47 +- src/test/consensus/LedgerTiming_test.cpp | 3 +- src/test/consensus/NegativeUNL_test.cpp | 519 +-- src/test/consensus/ScaleFreeSim_test.cpp | 23 +- src/test/consensus/Validations_test.cpp | 300 +- src/test/core/ClosureCounter_test.cpp | 21 +- src/test/core/Config_test.cpp | 295 +- src/test/core/Coroutine_test.cpp | 24 +- src/test/core/JobQueue_test.cpp | 23 +- src/test/core/SociDB_test.cpp | 57 +- src/test/core/Workers_test.cpp | 13 +- src/test/csf/BasicNetwork.h | 27 +- src/test/csf/BasicNetwork_test.cpp | 8 +- src/test/csf/Digraph.h | 8 +- src/test/csf/Peer.h | 129 +- src/test/csf/PeerGroup.h | 22 +- src/test/csf/Scheduler.h | 21 +- src/test/csf/Sim.h | 20 +- src/test/csf/TrustGraph.h | 13 +- src/test/csf/Tx.h | 6 +- src/test/csf/Validation.h | 10 +- src/test/csf/collectors.h | 211 +- src/test/csf/impl/ledgers.cpp | 3 +- src/test/csf/ledgers.h | 18 +- src/test/csf/random.h | 6 +- src/test/csf/submitters.h | 19 +- src/test/csf/timers.h | 11 +- src/test/jtx/AMM.h | 50 +- src/test/jtx/AMMTest.h | 10 +- src/test/jtx/Account.h | 12 +- src/test/jtx/CaptureLogs.h | 22 +- src/test/jtx/CheckMessageLogs.h | 14 +- src/test/jtx/Env.h | 73 +- src/test/jtx/Env_test.cpp | 179 +- src/test/jtx/JTx.h | 3 +- src/test/jtx/Oracle.h | 13 +- src/test/jtx/PathSet.h | 54 +- src/test/jtx/SignerUtils.h | 11 +- src/test/jtx/TestHelpers.h | 207 +- src/test/jtx/TestSuite.h | 14 +- src/test/jtx/TrustedPublisherServer.h | 176 +- src/test/jtx/WSClient.h | 8 +- src/test/jtx/acctdelete.h | 5 +- src/test/jtx/amount.h | 42 +- src/test/jtx/balance.h | 9 +- src/test/jtx/batch.h | 22 +- src/test/jtx/check.h | 5 +- src/test/jtx/credentials.h | 30 +- src/test/jtx/delegate.h | 9 +- src/test/jtx/deposit.h | 8 +- src/test/jtx/directory.h | 3 +- src/test/jtx/envconfig.h | 8 +- src/test/jtx/escrow.h | 33 +- src/test/jtx/fee.h | 3 +- src/test/jtx/flags.h | 6 +- src/test/jtx/impl/AMM.cpp | 283 +- src/test/jtx/impl/AMMTest.cpp | 25 +- src/test/jtx/impl/Account.cpp | 22 +- src/test/jtx/impl/Env.cpp | 99 +- src/test/jtx/impl/JSONRPCClient.cpp | 3 +- src/test/jtx/impl/Oracle.cpp | 42 +- src/test/jtx/impl/TestHelpers.cpp | 117 +- src/test/jtx/impl/WSClient.cpp | 67 +- src/test/jtx/impl/acctdelete.cpp | 4 +- src/test/jtx/impl/amount.cpp | 9 +- src/test/jtx/impl/attester.cpp | 17 +- src/test/jtx/impl/balance.cpp | 19 +- src/test/jtx/impl/batch.cpp | 23 +- src/test/jtx/impl/check.cpp | 5 +- src/test/jtx/impl/creds.cpp | 22 +- src/test/jtx/impl/delegate.cpp | 4 +- src/test/jtx/impl/deposit.cpp | 8 +- src/test/jtx/impl/directory.cpp | 143 +- src/test/jtx/impl/envconfig.cpp | 11 +- src/test/jtx/impl/mpt.cpp | 128 +- src/test/jtx/impl/multisign.cpp | 11 +- src/test/jtx/impl/offer.cpp | 6 +- src/test/jtx/impl/owners.cpp | 15 +- src/test/jtx/impl/paths.cpp | 3 +- src/test/jtx/impl/permissioned_domains.cpp | 25 +- src/test/jtx/impl/quality2.cpp | 6 +- src/test/jtx/impl/token.cpp | 27 +- src/test/jtx/impl/trust.cpp | 11 +- src/test/jtx/impl/utility.cpp | 9 +- src/test/jtx/impl/xchain_bridge.cpp | 70 +- src/test/jtx/memo.h | 5 +- src/test/jtx/mpt.h | 31 +- src/test/jtx/multisign.h | 38 +- src/test/jtx/offer.h | 6 +- src/test/jtx/owners.h | 12 +- src/test/jtx/paths.h | 3 +- src/test/jtx/permissioned_domains.h | 9 +- src/test/jtx/prop.h | 3 +- src/test/jtx/rpc.h | 11 +- src/test/jtx/sig.h | 6 +- src/test/jtx/token.h | 18 +- src/test/jtx/trust.h | 11 +- src/test/jtx/utility.h | 5 +- src/test/jtx/xchain_bridge.h | 25 +- src/test/ledger/BookDirs_test.cpp | 16 +- src/test/ledger/Directory_test.cpp | 58 +- src/test/ledger/PaymentSandbox_test.cpp | 122 +- src/test/ledger/SkipList_test.cpp | 46 +- src/test/ledger/View_test.cpp | 254 +- src/test/nodestore/Backend_test.cpp | 13 +- src/test/nodestore/Basics_test.cpp | 6 +- src/test/nodestore/Database_test.cpp | 135 +- src/test/nodestore/NuDBFactory_test.cpp | 74 +- src/test/nodestore/TestBase.h | 29 +- src/test/nodestore/Timing_test.cpp | 141 +- src/test/nodestore/import_test.cpp | 47 +- src/test/overlay/ProtocolVersion_test.cpp | 16 +- src/test/overlay/TMGetObjectByHash_test.cpp | 30 +- src/test/overlay/cluster_test.cpp | 20 +- src/test/overlay/compression_test.cpp | 158 +- src/test/overlay/reduce_relay_test.cpp | 346 +- src/test/overlay/short_read_test.cpp | 127 +- src/test/overlay/traffic_count_test.cpp | 31 +- src/test/overlay/tx_reduce_relay_test.cpp | 47 +- src/test/peerfinder/Livecache_test.cpp | 45 +- src/test/peerfinder/PeerFinder_test.cpp | 61 +- src/test/protocol/ApiVersion_test.cpp | 10 +- src/test/protocol/BuildInfo_test.cpp | 17 +- src/test/protocol/Hooks_test.cpp | 3 +- src/test/protocol/InnerObjectFormats_test.cpp | 3 +- src/test/protocol/Issue_test.cpp | 132 +- src/test/protocol/Memo_test.cpp | 19 +- src/test/protocol/MultiApiJson_test.cpp | 440 +-- src/test/protocol/PublicKey_test.cpp | 35 +- src/test/protocol/Quality_test.cpp | 34 +- src/test/protocol/STAccount_test.cpp | 12 +- src/test/protocol/STAmount_test.cpp | 175 +- src/test/protocol/STInteger_test.cpp | 7 +- src/test/protocol/STIssue_test.cpp | 8 +- src/test/protocol/STNumber_test.cpp | 136 +- src/test/protocol/STObject_test.cpp | 48 +- src/test/protocol/STParsedJSON_test.cpp | 254 +- src/test/protocol/STTx_test.cpp | 2198 +++++------- src/test/protocol/STValidation_test.cpp | 264 +- src/test/protocol/SecretKey_test.cpp | 83 +- src/test/protocol/Seed_test.cpp | 123 +- src/test/protocol/SeqProxy_test.cpp | 18 +- src/test/protocol/Serializer_test.cpp | 12 +- src/test/protocol/TER_test.cpp | 100 +- src/test/resource/Logic_test.cpp | 38 +- src/test/rpc/AMMInfo_test.cpp | 137 +- src/test/rpc/AccountCurrencies_test.cpp | 75 +- src/test/rpc/AccountInfo_test.cpp | 257 +- src/test/rpc/AccountLines_test.cpp | 480 +-- src/test/rpc/AccountObjects_test.cpp | 298 +- src/test/rpc/AccountOffers_test.cpp | 94 +- src/test/rpc/AccountSet_test.cpp | 73 +- src/test/rpc/AccountTx_test.cpp | 303 +- src/test/rpc/AmendmentBlocked_test.cpp | 55 +- src/test/rpc/BookChanges_test.cpp | 21 +- src/test/rpc/Book_test.cpp | 667 ++-- src/test/rpc/Connect_test.cpp | 4 +- src/test/rpc/DeliveredAmount_test.cpp | 71 +- src/test/rpc/DepositAuthorized_test.cpp | 250 +- src/test/rpc/Feature_test.cpp | 234 +- src/test/rpc/GRPCTestClientBase.h | 10 +- src/test/rpc/GatewayBalances_test.cpp | 13 +- src/test/rpc/GetAggregatePrice_test.cpp | 142 +- src/test/rpc/GetCounts_test.cpp | 18 +- src/test/rpc/Handler_test.cpp | 9 +- src/test/rpc/JSONRPC_test.cpp | 419 +-- src/test/rpc/KeyGeneration_test.cpp | 202 +- src/test/rpc/LedgerClosed_test.cpp | 8 +- src/test/rpc/LedgerData_test.cpp | 97 +- src/test/rpc/LedgerEntry_test.cpp | 1049 ++---- src/test/rpc/LedgerHeader_test.cpp | 9 +- src/test/rpc/LedgerRPC_test.cpp | 147 +- src/test/rpc/LedgerRequest_test.cpp | 112 +- src/test/rpc/ManifestRPC_test.cpp | 10 +- src/test/rpc/NoRippleCheck_test.cpp | 118 +- src/test/rpc/NoRipple_test.cpp | 25 +- src/test/rpc/OwnerInfo_test.cpp | 101 +- src/test/rpc/Peers_test.cpp | 16 +- src/test/rpc/RPCCall_test.cpp | 257 +- src/test/rpc/RPCOverload_test.cpp | 8 +- src/test/rpc/RobustTransaction_test.cpp | 178 +- src/test/rpc/Roles_test.cpp | 86 +- src/test/rpc/ServerDefinitions_test.cpp | 45 +- src/test/rpc/ServerInfo_test.cpp | 26 +- src/test/rpc/Simulate_test.cpp | 485 +-- src/test/rpc/Status_test.cpp | 28 +- src/test/rpc/Subscribe_test.cpp | 416 +-- src/test/rpc/TransactionEntry_test.cpp | 88 +- src/test/rpc/TransactionHistory_test.cpp | 24 +- src/test/rpc/Transaction_test.cpp | 279 +- src/test/rpc/ValidatorInfo_test.cpp | 12 +- src/test/rpc/ValidatorRPC_test.cpp | 168 +- src/test/rpc/Version_test.cpp | 103 +- src/test/server/ServerStatus_test.cpp | 380 +- src/test/server/Server_test.cpp | 134 +- src/test/shamap/FetchPack_test.cpp | 6 +- src/test/shamap/SHAMapSync_test.cpp | 20 +- src/test/shamap/SHAMap_test.cpp | 37 +- src/test/shamap/common.h | 22 +- src/test/unit_test/FileDirGuard.h | 15 +- src/test/unit_test/SuiteJournal.h | 18 +- src/test/unit_test/multi_runner.cpp | 92 +- src/test/unit_test/multi_runner.h | 6 +- src/tests/libxrpl/basics/Slice.cpp | 7 +- src/tests/libxrpl/basics/tagged_integer.cpp | 32 +- src/tests/libxrpl/helpers/TestSink.cpp | 7 +- src/tests/libxrpl/helpers/TestSink.h | 3 +- src/tests/libxrpl/json/Value.cpp | 20 +- src/tests/libxrpl/json/Writer.cpp | 3 +- src/tests/libxrpl/net/HTTPClient.cpp | 41 +- .../app/consensus/RCLCensorshipDetector.h | 3 +- src/xrpld/app/consensus/RCLConsensus.cpp | 339 +- src/xrpld/app/consensus/RCLConsensus.h | 47 +- src/xrpld/app/consensus/RCLCxPeerPos.cpp | 7 +- src/xrpld/app/consensus/RCLCxPeerPos.h | 6 +- src/xrpld/app/consensus/RCLCxTx.h | 6 +- src/xrpld/app/consensus/RCLValidations.cpp | 64 +- src/xrpld/app/consensus/RCLValidations.h | 4 +- src/xrpld/app/ledger/AcceptedLedger.cpp | 17 +- src/xrpld/app/ledger/AcceptedLedger.h | 4 +- src/xrpld/app/ledger/AcceptedLedgerTx.cpp | 20 +- src/xrpld/app/ledger/AccountStateSF.cpp | 11 +- src/xrpld/app/ledger/AccountStateSF.h | 11 +- src/xrpld/app/ledger/BookListeners.cpp | 4 +- src/xrpld/app/ledger/BuildLedger.h | 6 +- src/xrpld/app/ledger/ConsensusTransSetSF.cpp | 15 +- src/xrpld/app/ledger/ConsensusTransSetSF.h | 8 +- src/xrpld/app/ledger/InboundLedger.h | 15 +- src/xrpld/app/ledger/InboundLedgers.h | 10 +- src/xrpld/app/ledger/InboundTransactions.h | 10 +- src/xrpld/app/ledger/Ledger.cpp | 182 +- src/xrpld/app/ledger/Ledger.h | 26 +- src/xrpld/app/ledger/LedgerHistory.cpp | 206 +- src/xrpld/app/ledger/LedgerHistory.h | 13 +- src/xrpld/app/ledger/LedgerMaster.h | 23 +- src/xrpld/app/ledger/LedgerReplay.h | 4 +- src/xrpld/app/ledger/LedgerReplayTask.h | 22 +- src/xrpld/app/ledger/LedgerReplayer.h | 18 +- src/xrpld/app/ledger/LedgerToJson.h | 16 +- src/xrpld/app/ledger/OpenLedger.h | 11 +- src/xrpld/app/ledger/OrderBookDB.cpp | 46 +- src/xrpld/app/ledger/OrderBookDB.h | 16 +- src/xrpld/app/ledger/TransactionMaster.h | 24 +- src/xrpld/app/ledger/TransactionStateSF.cpp | 10 +- src/xrpld/app/ledger/TransactionStateSF.h | 11 +- src/xrpld/app/ledger/detail/BuildLedger.cpp | 57 +- src/xrpld/app/ledger/detail/InboundLedger.cpp | 286 +- .../app/ledger/detail/InboundLedgers.cpp | 84 +- .../app/ledger/detail/InboundTransactions.cpp | 29 +- src/xrpld/app/ledger/detail/LedgerCleaner.cpp | 59 +- .../app/ledger/detail/LedgerDeltaAcquire.cpp | 80 +- .../app/ledger/detail/LedgerDeltaAcquire.h | 18 +- src/xrpld/app/ledger/detail/LedgerMaster.cpp | 410 +-- src/xrpld/app/ledger/detail/LedgerReplay.cpp | 8 +- .../ledger/detail/LedgerReplayMsgHandler.cpp | 77 +- .../ledger/detail/LedgerReplayMsgHandler.h | 12 +- .../app/ledger/detail/LedgerReplayTask.cpp | 97 +- .../app/ledger/detail/LedgerReplayer.cpp | 75 +- src/xrpld/app/ledger/detail/LedgerToJson.cpp | 67 +- src/xrpld/app/ledger/detail/LocalTxs.cpp | 9 +- src/xrpld/app/ledger/detail/OpenLedger.cpp | 24 +- .../app/ledger/detail/SkipListAcquire.cpp | 61 +- src/xrpld/app/ledger/detail/SkipListAcquire.h | 27 +- .../app/ledger/detail/TimeoutCounter.cpp | 36 +- .../app/ledger/detail/TransactionAcquire.cpp | 37 +- .../app/ledger/detail/TransactionAcquire.h | 16 +- .../app/ledger/detail/TransactionMaster.cpp | 35 +- src/xrpld/app/main/Application.cpp | 554 +-- src/xrpld/app/main/Application.h | 5 +- src/xrpld/app/main/BasicApp.cpp | 3 +- src/xrpld/app/main/BasicApp.h | 4 +- src/xrpld/app/main/CollectorManager.cpp | 9 +- src/xrpld/app/main/GRPCServer.cpp | 122 +- src/xrpld/app/main/GRPCServer.h | 14 +- src/xrpld/app/main/LoadManager.cpp | 34 +- src/xrpld/app/main/Main.cpp | 267 +- src/xrpld/app/main/NodeIdentity.cpp | 10 +- src/xrpld/app/main/NodeIdentity.h | 4 +- src/xrpld/app/main/NodeStoreScheduler.cpp | 8 +- src/xrpld/app/misc/AMMHelpers.h | 172 +- src/xrpld/app/misc/AMMUtils.h | 27 +- src/xrpld/app/misc/AmendmentTable.h | 28 +- src/xrpld/app/misc/CanonicalTXSet.cpp | 11 +- src/xrpld/app/misc/CanonicalTXSet.h | 3 +- src/xrpld/app/misc/FeeVote.h | 5 +- src/xrpld/app/misc/FeeVoteImpl.cpp | 159 +- src/xrpld/app/misc/HashRouter.cpp | 17 +- src/xrpld/app/misc/HashRouter.h | 25 +- src/xrpld/app/misc/LendingHelpers.h | 40 +- src/xrpld/app/misc/LoadFeeTrack.h | 34 +- src/xrpld/app/misc/Manifest.h | 33 +- src/xrpld/app/misc/NegativeUNLVote.cpp | 83 +- src/xrpld/app/misc/NegativeUNLVote.h | 15 +- src/xrpld/app/misc/NetworkOPs.cpp | 1437 +++----- src/xrpld/app/misc/NetworkOPs.h | 25 +- src/xrpld/app/misc/PermissionedDEXHelpers.cpp | 32 +- src/xrpld/app/misc/PermissionedDEXHelpers.h | 11 +- src/xrpld/app/misc/SHAMapStore.h | 5 +- src/xrpld/app/misc/SHAMapStoreImp.cpp | 173 +- src/xrpld/app/misc/SHAMapStoreImp.h | 11 +- src/xrpld/app/misc/Transaction.h | 52 +- src/xrpld/app/misc/TxQ.h | 60 +- src/xrpld/app/misc/ValidatorKeys.h | 9 +- src/xrpld/app/misc/ValidatorList.h | 55 +- src/xrpld/app/misc/ValidatorSite.h | 28 +- src/xrpld/app/misc/detail/AMMHelpers.cpp | 73 +- src/xrpld/app/misc/detail/AMMUtils.cpp | 145 +- src/xrpld/app/misc/detail/AmendmentTable.cpp | 185 +- src/xrpld/app/misc/detail/DelegateUtils.cpp | 6 +- src/xrpld/app/misc/detail/LendingHelpers.cpp | 570 +-- src/xrpld/app/misc/detail/LoadFeeTrack.cpp | 15 +- src/xrpld/app/misc/detail/Manifest.cpp | 89 +- src/xrpld/app/misc/detail/Transaction.cpp | 32 +- src/xrpld/app/misc/detail/TxQ.cpp | 472 +-- src/xrpld/app/misc/detail/ValidatorKeys.cpp | 25 +- src/xrpld/app/misc/detail/ValidatorList.cpp | 472 +-- src/xrpld/app/misc/detail/ValidatorSite.cpp | 200 +- src/xrpld/app/misc/detail/Work.h | 3 +- src/xrpld/app/misc/detail/WorkBase.h | 42 +- src/xrpld/app/misc/detail/WorkFile.h | 22 +- src/xrpld/app/misc/detail/WorkPlain.h | 3 +- src/xrpld/app/misc/detail/WorkSSL.cpp | 9 +- src/xrpld/app/misc/detail/WorkSSL.h | 3 +- src/xrpld/app/paths/AMMContext.h | 3 +- src/xrpld/app/paths/AMMLiquidity.h | 3 +- src/xrpld/app/paths/AMMOffer.h | 10 +- src/xrpld/app/paths/AccountCurrencies.cpp | 23 +- src/xrpld/app/paths/AccountCurrencies.h | 10 +- src/xrpld/app/paths/Flow.cpp | 9 +- src/xrpld/app/paths/PathRequest.cpp | 141 +- src/xrpld/app/paths/PathRequest.h | 6 +- src/xrpld/app/paths/PathRequests.cpp | 92 +- src/xrpld/app/paths/PathRequests.h | 9 +- src/xrpld/app/paths/Pathfinder.cpp | 302 +- src/xrpld/app/paths/Pathfinder.h | 27 +- src/xrpld/app/paths/RippleCalc.cpp | 18 +- src/xrpld/app/paths/RippleLineCache.cpp | 67 +- src/xrpld/app/paths/RippleLineCache.h | 18 +- src/xrpld/app/paths/TrustLine.cpp | 44 +- src/xrpld/app/paths/TrustLine.h | 25 +- src/xrpld/app/paths/detail/AMMLiquidity.cpp | 79 +- src/xrpld/app/paths/detail/AMMOffer.cpp | 55 +- src/xrpld/app/paths/detail/AmountSpec.h | 12 +- src/xrpld/app/paths/detail/BookStep.cpp | 307 +- src/xrpld/app/paths/detail/DirectStep.cpp | 280 +- src/xrpld/app/paths/detail/FlatSets.h | 7 +- src/xrpld/app/paths/detail/FlowDebugInfo.h | 129 +- src/xrpld/app/paths/detail/PaySteps.cpp | 138 +- src/xrpld/app/paths/detail/StepChecks.h | 18 +- src/xrpld/app/paths/detail/Steps.h | 44 +- src/xrpld/app/paths/detail/StrandFlow.h | 159 +- .../app/paths/detail/XRPEndpointStep.cpp | 62 +- src/xrpld/app/rdb/PeerFinder.h | 18 +- src/xrpld/app/rdb/RelationalDatabase.h | 19 +- src/xrpld/app/rdb/State.h | 5 +- src/xrpld/app/rdb/Wallet.h | 22 +- src/xrpld/app/rdb/backend/SQLiteDatabase.h | 9 +- src/xrpld/app/rdb/backend/detail/Node.cpp | 359 +- src/xrpld/app/rdb/backend/detail/Node.h | 55 +- .../app/rdb/backend/detail/SQLiteDatabase.cpp | 137 +- src/xrpld/app/rdb/detail/PeerFinder.cpp | 33 +- .../app/rdb/detail/RelationalDatabase.cpp | 9 +- src/xrpld/app/rdb/detail/State.cpp | 29 +- src/xrpld/app/rdb/detail/Vacuum.cpp | 17 +- src/xrpld/app/rdb/detail/Wallet.cpp | 65 +- src/xrpld/app/tx/apply.h | 13 +- src/xrpld/app/tx/applySteps.h | 19 +- src/xrpld/app/tx/detail/AMMBid.cpp | 83 +- src/xrpld/app/tx/detail/AMMClawback.cpp | 92 +- src/xrpld/app/tx/detail/AMMCreate.cpp | 92 +- src/xrpld/app/tx/detail/AMMDelete.cpp | 6 +- src/xrpld/app/tx/detail/AMMDeposit.cpp | 283 +- src/xrpld/app/tx/detail/AMMVote.cpp | 43 +- src/xrpld/app/tx/detail/AMMWithdraw.cpp | 387 +-- src/xrpld/app/tx/detail/ApplyContext.cpp | 48 +- src/xrpld/app/tx/detail/ApplyContext.h | 18 +- src/xrpld/app/tx/detail/Batch.cpp | 132 +- src/xrpld/app/tx/detail/BookTip.cpp | 5 +- src/xrpld/app/tx/detail/CancelCheck.cpp | 12 +- src/xrpld/app/tx/detail/CashCheck.cpp | 91 +- src/xrpld/app/tx/detail/Change.cpp | 80 +- src/xrpld/app/tx/detail/Clawback.cpp | 73 +- src/xrpld/app/tx/detail/CreateCheck.cpp | 42 +- src/xrpld/app/tx/detail/CreateOffer.cpp | 139 +- src/xrpld/app/tx/detail/CreateTicket.cpp | 26 +- src/xrpld/app/tx/detail/Credentials.cpp | 57 +- src/xrpld/app/tx/detail/DID.cpp | 41 +- src/xrpld/app/tx/detail/DID.h | 6 +- src/xrpld/app/tx/detail/DelegateSet.cpp | 14 +- src/xrpld/app/tx/detail/DelegateSet.h | 6 +- src/xrpld/app/tx/detail/DeleteAccount.cpp | 47 +- src/xrpld/app/tx/detail/DeleteOracle.cpp | 18 +- src/xrpld/app/tx/detail/DeleteOracle.h | 6 +- src/xrpld/app/tx/detail/DepositPreauth.cpp | 76 +- src/xrpld/app/tx/detail/DepositPreauth.h | 5 +- src/xrpld/app/tx/detail/Escrow.cpp | 234 +- src/xrpld/app/tx/detail/InvariantCheck.cpp | 1586 ++++----- src/xrpld/app/tx/detail/InvariantCheck.h | 341 +- .../app/tx/detail/LoanBrokerCoverClawback.cpp | 58 +- .../app/tx/detail/LoanBrokerCoverDeposit.cpp | 14 +- .../app/tx/detail/LoanBrokerCoverWithdraw.cpp | 17 +- src/xrpld/app/tx/detail/LoanBrokerDelete.cpp | 41 +- src/xrpld/app/tx/detail/LoanBrokerSet.cpp | 39 +- src/xrpld/app/tx/detail/LoanDelete.cpp | 24 +- src/xrpld/app/tx/detail/LoanManage.cpp | 116 +- src/xrpld/app/tx/detail/LoanManage.h | 14 +- src/xrpld/app/tx/detail/LoanPay.cpp | 208 +- src/xrpld/app/tx/detail/LoanSet.cpp | 185 +- src/xrpld/app/tx/detail/MPTokenAuthorize.cpp | 32 +- src/xrpld/app/tx/detail/MPTokenAuthorize.h | 6 +- .../app/tx/detail/MPTokenIssuanceCreate.cpp | 28 +- .../app/tx/detail/MPTokenIssuanceDestroy.cpp | 9 +- .../app/tx/detail/MPTokenIssuanceSet.cpp | 73 +- .../app/tx/detail/NFTokenAcceptOffer.cpp | 132 +- src/xrpld/app/tx/detail/NFTokenAcceptOffer.h | 9 +- src/xrpld/app/tx/detail/NFTokenBurn.cpp | 25 +- .../app/tx/detail/NFTokenCancelOffer.cpp | 58 +- .../app/tx/detail/NFTokenCreateOffer.cpp | 5 +- src/xrpld/app/tx/detail/NFTokenMint.cpp | 50 +- src/xrpld/app/tx/detail/NFTokenModify.cpp | 9 +- src/xrpld/app/tx/detail/NFTokenUtils.cpp | 241 +- src/xrpld/app/tx/detail/NFTokenUtils.h | 36 +- src/xrpld/app/tx/detail/Offer.h | 43 +- src/xrpld/app/tx/detail/OfferStream.cpp | 100 +- src/xrpld/app/tx/detail/OfferStream.h | 3 +- src/xrpld/app/tx/detail/PayChan.cpp | 84 +- src/xrpld/app/tx/detail/Payment.cpp | 166 +- .../tx/detail/PermissionedDomainDelete.cpp | 10 +- .../app/tx/detail/PermissionedDomainSet.cpp | 25 +- src/xrpld/app/tx/detail/SetAccount.cpp | 102 +- src/xrpld/app/tx/detail/SetOracle.cpp | 59 +- src/xrpld/app/tx/detail/SetRegularKey.cpp | 6 +- src/xrpld/app/tx/detail/SetSignerList.cpp | 88 +- src/xrpld/app/tx/detail/SetSignerList.h | 15 +- src/xrpld/app/tx/detail/SetTrust.cpp | 145 +- src/xrpld/app/tx/detail/SignerEntries.cpp | 11 +- src/xrpld/app/tx/detail/SignerEntries.h | 10 +- src/xrpld/app/tx/detail/Transactor.cpp | 278 +- src/xrpld/app/tx/detail/Transactor.h | 58 +- src/xrpld/app/tx/detail/VaultClawback.cpp | 132 +- src/xrpld/app/tx/detail/VaultCreate.cpp | 33 +- src/xrpld/app/tx/detail/VaultDelete.cpp | 22 +- src/xrpld/app/tx/detail/VaultDeposit.cpp | 64 +- src/xrpld/app/tx/detail/VaultSet.cpp | 16 +- src/xrpld/app/tx/detail/VaultWithdraw.cpp | 58 +- src/xrpld/app/tx/detail/XChainBridge.cpp | 342 +- src/xrpld/app/tx/detail/XChainBridge.h | 3 +- src/xrpld/app/tx/detail/apply.cpp | 95 +- src/xrpld/app/tx/detail/applySteps.cpp | 136 +- src/xrpld/conditions/Condition.h | 10 +- src/xrpld/conditions/Fulfillment.h | 3 +- src/xrpld/conditions/detail/Condition.cpp | 3 +- src/xrpld/conditions/detail/error.cpp | 6 +- src/xrpld/consensus/Consensus.cpp | 61 +- src/xrpld/consensus/Consensus.h | 329 +- src/xrpld/consensus/ConsensusParms.h | 18 +- src/xrpld/consensus/ConsensusProposal.h | 21 +- src/xrpld/consensus/ConsensusTypes.h | 12 +- src/xrpld/consensus/DisputedTx.h | 41 +- src/xrpld/consensus/LedgerTiming.h | 29 +- src/xrpld/consensus/LedgerTrie.h | 62 +- src/xrpld/consensus/Validations.h | 156 +- src/xrpld/core/Config.h | 15 +- src/xrpld/core/DatabaseCon.h | 23 +- src/xrpld/core/SociDB.h | 11 +- src/xrpld/core/TimeKeeper.h | 3 +- src/xrpld/core/detail/Config.cpp | 271 +- src/xrpld/core/detail/DatabaseCon.cpp | 82 +- src/xrpld/core/detail/SociDB.cpp | 64 +- src/xrpld/overlay/Compression.h | 19 +- src/xrpld/overlay/Overlay.h | 10 +- src/xrpld/overlay/PeerReservationTable.h | 3 +- src/xrpld/overlay/Slot.h | 157 +- src/xrpld/overlay/Squelch.h | 14 +- src/xrpld/overlay/detail/Cluster.cpp | 9 +- src/xrpld/overlay/detail/ConnectAttempt.cpp | 135 +- src/xrpld/overlay/detail/ConnectAttempt.h | 12 +- src/xrpld/overlay/detail/Handshake.cpp | 57 +- src/xrpld/overlay/detail/Handshake.h | 33 +- src/xrpld/overlay/detail/Message.cpp | 23 +- src/xrpld/overlay/detail/OverlayImpl.cpp | 292 +- src/xrpld/overlay/detail/OverlayImpl.h | 61 +- src/xrpld/overlay/detail/PeerImp.cpp | 928 ++--- src/xrpld/overlay/detail/PeerImp.h | 90 +- src/xrpld/overlay/detail/PeerSet.cpp | 9 +- src/xrpld/overlay/detail/ProtocolMessage.h | 104 +- src/xrpld/overlay/detail/ProtocolVersion.cpp | 11 +- src/xrpld/overlay/detail/TrafficCount.cpp | 123 +- src/xrpld/overlay/detail/TrafficCount.h | 12 +- src/xrpld/overlay/detail/TxMetrics.cpp | 11 +- src/xrpld/overlay/detail/TxMetrics.h | 5 +- src/xrpld/overlay/detail/ZeroCopyStream.h | 16 +- src/xrpld/overlay/predicates.h | 6 +- src/xrpld/peerfinder/PeerfinderManager.h | 39 +- src/xrpld/peerfinder/detail/Bootcache.cpp | 63 +- src/xrpld/peerfinder/detail/Bootcache.h | 15 +- src/xrpld/peerfinder/detail/Checker.h | 33 +- src/xrpld/peerfinder/detail/Counts.h | 12 +- src/xrpld/peerfinder/detail/Fixed.h | 6 +- src/xrpld/peerfinder/detail/Handouts.h | 24 +- src/xrpld/peerfinder/detail/Livecache.h | 91 +- src/xrpld/peerfinder/detail/Logic.h | 245 +- .../peerfinder/detail/PeerfinderConfig.cpp | 21 +- .../peerfinder/detail/PeerfinderManager.cpp | 41 +- src/xrpld/peerfinder/detail/SlotImp.cpp | 16 +- src/xrpld/peerfinder/detail/SlotImp.h | 5 +- src/xrpld/peerfinder/detail/SourceStrings.cpp | 6 +- src/xrpld/peerfinder/detail/StoreSqdb.h | 10 +- src/xrpld/peerfinder/detail/Tuning.h | 6 +- src/xrpld/peerfinder/detail/iosformat.h | 51 +- src/xrpld/perflog/detail/PerfLogImp.cpp | 81 +- src/xrpld/perflog/detail/PerfLogImp.h | 17 +- src/xrpld/rpc/BookChanges.h | 39 +- src/xrpld/rpc/CTID.h | 13 +- src/xrpld/rpc/DeliveredAmount.h | 12 +- src/xrpld/rpc/GRPCHandlers.h | 9 +- src/xrpld/rpc/InfoSub.h | 25 +- src/xrpld/rpc/MPTokenIssuanceID.h | 4 +- src/xrpld/rpc/RPCCall.h | 14 +- src/xrpld/rpc/Request.h | 12 +- src/xrpld/rpc/ServerHandler.h | 19 +- src/xrpld/rpc/Status.h | 23 +- src/xrpld/rpc/detail/DeliveredAmount.cpp | 38 +- src/xrpld/rpc/detail/Handler.cpp | 113 +- src/xrpld/rpc/detail/Handler.h | 30 +- src/xrpld/rpc/detail/InfoSub.cpp | 6 +- src/xrpld/rpc/detail/LegacyPathFind.cpp | 8 +- src/xrpld/rpc/detail/MPTokenIssuanceID.cpp | 13 +- src/xrpld/rpc/detail/RPCCall.cpp | 166 +- src/xrpld/rpc/detail/RPCHandler.cpp | 46 +- src/xrpld/rpc/detail/RPCHelpers.cpp | 80 +- src/xrpld/rpc/detail/RPCHelpers.h | 15 +- src/xrpld/rpc/detail/RPCLedgerHelpers.cpp | 138 +- src/xrpld/rpc/detail/RPCLedgerHelpers.h | 10 +- src/xrpld/rpc/detail/RPCSub.cpp | 34 +- src/xrpld/rpc/detail/Role.cpp | 55 +- src/xrpld/rpc/detail/ServerHandler.cpp | 259 +- src/xrpld/rpc/detail/TransactionSign.cpp | 356 +- src/xrpld/rpc/detail/TransactionSign.h | 12 +- src/xrpld/rpc/detail/WSInfoSub.h | 9 +- src/xrpld/rpc/handlers/AMMInfo.cpp | 66 +- src/xrpld/rpc/handlers/AccountChannels.cpp | 12 +- .../rpc/handlers/AccountCurrenciesHandler.cpp | 6 +- src/xrpld/rpc/handlers/AccountInfo.cpp | 85 +- src/xrpld/rpc/handlers/AccountLines.cpp | 29 +- src/xrpld/rpc/handlers/AccountObjects.cpp | 45 +- src/xrpld/rpc/handlers/AccountOffers.cpp | 9 +- src/xrpld/rpc/handlers/AccountTx.cpp | 99 +- src/xrpld/rpc/handlers/BookOffers.cpp | 41 +- src/xrpld/rpc/handlers/CanDelete.cpp | 6 +- src/xrpld/rpc/handlers/Connect.cpp | 7 +- src/xrpld/rpc/handlers/DepositAuthorized.cpp | 64 +- src/xrpld/rpc/handlers/Feature1.cpp | 3 +- src/xrpld/rpc/handlers/FetchInfo.cpp | 3 +- src/xrpld/rpc/handlers/GatewayBalances.cpp | 193 +- src/xrpld/rpc/handlers/GetAggregatePrice.cpp | 80 +- src/xrpld/rpc/handlers/GetCounts.cpp | 21 +- src/xrpld/rpc/handlers/LedgerAccept.cpp | 3 +- src/xrpld/rpc/handlers/LedgerCurrent.cpp | 3 +- src/xrpld/rpc/handlers/LedgerData.cpp | 27 +- src/xrpld/rpc/handlers/LedgerDiff.cpp | 34 +- src/xrpld/rpc/handlers/LedgerEntry.cpp | 329 +- src/xrpld/rpc/handlers/LedgerEntryHelpers.h | 58 +- src/xrpld/rpc/handlers/LedgerHandler.cpp | 136 +- src/xrpld/rpc/handlers/LogLevel.cpp | 9 +- src/xrpld/rpc/handlers/NFTOffers.cpp | 17 +- src/xrpld/rpc/handlers/NoRippleCheck.cpp | 104 +- src/xrpld/rpc/handlers/OwnerInfo.cpp | 18 +- src/xrpld/rpc/handlers/PathFind.cpp | 6 +- src/xrpld/rpc/handlers/PayChanClaim.cpp | 24 +- src/xrpld/rpc/handlers/Peers.cpp | 26 +- src/xrpld/rpc/handlers/Reservations.cpp | 9 +- src/xrpld/rpc/handlers/RipplePathFind.cpp | 12 +- src/xrpld/rpc/handlers/ServerDefinitions.cpp | 22 +- src/xrpld/rpc/handlers/ServerInfo.cpp | 3 +- src/xrpld/rpc/handlers/ServerState.cpp | 3 +- src/xrpld/rpc/handlers/SignFor.cpp | 3 +- src/xrpld/rpc/handlers/SignHandler.cpp | 8 +- src/xrpld/rpc/handlers/Simulate.cpp | 74 +- src/xrpld/rpc/handlers/Submit.cpp | 36 +- src/xrpld/rpc/handlers/Subscribe.cpp | 67 +- src/xrpld/rpc/handlers/TransactionEntry.cpp | 21 +- src/xrpld/rpc/handlers/Tx.cpp | 78 +- src/xrpld/rpc/handlers/TxHistory.cpp | 3 +- src/xrpld/rpc/handlers/UnlList.cpp | 14 +- src/xrpld/rpc/handlers/Unsubscribe.cpp | 35 +- src/xrpld/rpc/handlers/ValidationCreate.cpp | 7 +- src/xrpld/rpc/handlers/ValidatorInfo.cpp | 3 +- src/xrpld/rpc/handlers/VaultInfo.cpp | 6 +- src/xrpld/rpc/handlers/Version.h | 3 +- src/xrpld/rpc/handlers/WalletPropose.cpp | 6 +- src/xrpld/rpc/json_body.h | 17 +- src/xrpld/shamap/NodeFamily.cpp | 6 +- 1016 files changed, 26918 insertions(+), 66660 deletions(-) diff --git a/.clang-format b/.clang-format index bd446022df..46e7bbce94 100644 --- a/.clang-format +++ b/.clang-format @@ -37,7 +37,7 @@ BinPackParameters: false BreakBeforeBinaryOperators: false BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: true -ColumnLimit: 80 +ColumnLimit: 120 CommentPragmas: "^ IWYU pragma:" ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 diff --git a/include/xrpl/basics/Archive.h b/include/xrpl/basics/Archive.h index 5f7c624084..84af8a7c7d 100644 --- a/include/xrpl/basics/Archive.h +++ b/include/xrpl/basics/Archive.h @@ -13,9 +13,7 @@ namespace xrpl { @throws runtime_error */ void -extractTarLz4( - boost::filesystem::path const& src, - boost::filesystem::path const& dst); +extractTarLz4(boost::filesystem::path const& src, boost::filesystem::path const& dst); } // namespace xrpl diff --git a/include/xrpl/basics/BasicConfig.h b/include/xrpl/basics/BasicConfig.h index 573b26ae75..9aa7f3e612 100644 --- a/include/xrpl/basics/BasicConfig.h +++ b/include/xrpl/basics/BasicConfig.h @@ -14,8 +14,7 @@ namespace xrpl { -using IniFileSections = - std::unordered_map>; +using IniFileSections = std::unordered_map>; //------------------------------------------------------------------------------ @@ -86,8 +85,7 @@ public: if (lines_.empty()) return ""; if (lines_.size() > 1) - Throw( - "A legacy value must have exactly one line. Section: " + name_); + Throw("A legacy value must have exactly one line. Section: " + name_); return lines_[0]; } @@ -233,10 +231,7 @@ public: The previous value, if any, is overwritten. */ void - overwrite( - std::string const& section, - std::string const& key, - std::string const& value); + overwrite(std::string const& section, std::string const& key, std::string const& value); /** Remove all the key/value pairs from the section. */ @@ -274,9 +269,7 @@ public: bool had_trailing_comments() const { - return std::any_of(map_.cbegin(), map_.cend(), [](auto s) { - return s.second.had_trailing_comments(); - }); + return std::any_of(map_.cbegin(), map_.cend(), [](auto s) { return s.second.had_trailing_comments(); }); } protected: @@ -315,10 +308,7 @@ set(T& target, std::string const& name, Section const& section) */ template bool -set(T& target, - T const& defaultValue, - std::string const& name, - Section const& section) +set(T& target, T const& defaultValue, std::string const& name, Section const& section) { bool found_and_valid = set(target, name, section); if (!found_and_valid) @@ -333,9 +323,7 @@ set(T& target, // NOTE This routine might be more clumsy than the previous two template T -get(Section const& section, - std::string const& name, - T const& defaultValue = T{}) +get(Section const& section, std::string const& name, T const& defaultValue = T{}) { try { diff --git a/include/xrpl/basics/Buffer.h b/include/xrpl/basics/Buffer.h index 8ae745f6d1..b7e0878477 100644 --- a/include/xrpl/basics/Buffer.h +++ b/include/xrpl/basics/Buffer.h @@ -25,8 +25,7 @@ public: Buffer() = default; /** Create an uninitialized buffer with the given size. */ - explicit Buffer(std::size_t size) - : p_(size ? new std::uint8_t[size] : nullptr), size_(size) + explicit Buffer(std::size_t size) : p_(size ? new std::uint8_t[size] : nullptr), size_(size) { } @@ -62,8 +61,7 @@ public: /** Move-construct. The other buffer is reset. */ - Buffer(Buffer&& other) noexcept - : p_(std::move(other.p_)), size_(other.size_) + Buffer(Buffer&& other) noexcept : p_(std::move(other.p_)), size_(other.size_) { other.size_ = 0; } @@ -94,8 +92,7 @@ public: { // Ensure the slice isn't a subset of the buffer. XRPL_ASSERT( - s.size() == 0 || size_ == 0 || s.data() < p_.get() || - s.data() >= p_.get() + size_, + s.size() == 0 || size_ == 0 || s.data() < p_.get() || s.data() >= p_.get() + size_, "xrpl::Buffer::operator=(Slice) : input not a subset"); if (auto p = alloc(s.size())) diff --git a/include/xrpl/basics/CompressionAlgorithms.h b/include/xrpl/basics/CompressionAlgorithms.h index b373ac4605..52dc406d5d 100644 --- a/include/xrpl/basics/CompressionAlgorithms.h +++ b/include/xrpl/basics/CompressionAlgorithms.h @@ -36,10 +36,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf) auto compressed = bf(outCapacity); auto compressedSize = LZ4_compress_default( - reinterpret_cast(in), - reinterpret_cast(compressed), - inSize, - outCapacity); + reinterpret_cast(in), reinterpret_cast(compressed), inSize, outCapacity); if (compressedSize == 0) Throw("lz4 compress: failed"); @@ -70,10 +67,8 @@ lz4Decompress( Throw("lz4Decompress: integer overflow (output)"); if (LZ4_decompress_safe( - reinterpret_cast(in), - reinterpret_cast(decompressed), - inSize, - decompressedSize) != decompressedSize) + reinterpret_cast(in), reinterpret_cast(decompressed), inSize, decompressedSize) != + decompressedSize) Throw("lz4Decompress: failed"); return decompressedSize; @@ -89,11 +84,7 @@ lz4Decompress( */ template std::size_t -lz4Decompress( - InputStream& in, - std::size_t inSize, - std::uint8_t* decompressed, - std::size_t decompressedSize) +lz4Decompress(InputStream& in, std::size_t inSize, std::uint8_t* decompressed, std::size_t decompressedSize) { std::vector compressed; std::uint8_t const* chunk = nullptr; @@ -116,9 +107,7 @@ lz4Decompress( compressed.resize(inSize); } - chunkSize = chunkSize < (inSize - copiedInSize) - ? chunkSize - : (inSize - copiedInSize); + chunkSize = chunkSize < (inSize - copiedInSize) ? chunkSize : (inSize - copiedInSize); std::copy(chunk, chunk + chunkSize, compressed.data() + copiedInSize); @@ -135,8 +124,7 @@ lz4Decompress( if (in.ByteCount() > (currentBytes + copiedInSize)) in.BackUp(in.ByteCount() - currentBytes - copiedInSize); - if ((copiedInSize == 0 && chunkSize < inSize) || - (copiedInSize > 0 && copiedInSize != inSize)) + if ((copiedInSize == 0 && chunkSize < inSize) || (copiedInSize > 0 && copiedInSize != inSize)) Throw("lz4 decompress: insufficient input size"); return lz4Decompress(chunk, inSize, decompressed, decompressedSize); diff --git a/include/xrpl/basics/DecayingSample.h b/include/xrpl/basics/DecayingSample.h index c5e38d2e9a..3b5e947f1f 100644 --- a/include/xrpl/basics/DecayingSample.h +++ b/include/xrpl/basics/DecayingSample.h @@ -56,9 +56,7 @@ private: if (m_value != value_type()) { - std::size_t elapsed = - std::chrono::duration_cast(now - m_when) - .count(); + std::size_t elapsed = std::chrono::duration_cast(now - m_when).count(); // A span larger than four times the window decays the // value to an insignificant amount so just reset it. diff --git a/include/xrpl/basics/Expected.h b/include/xrpl/basics/Expected.h index 8cf479c1b6..9ce771dc23 100644 --- a/include/xrpl/basics/Expected.h +++ b/include/xrpl/basics/Expected.h @@ -108,23 +108,20 @@ Unexpected(E (&)[N]) -> Unexpected; // Definition of Expected. All of the machinery comes from boost::result. template -class [[nodiscard]] Expected - : private boost::outcome_v2::result +class [[nodiscard]] Expected : private boost::outcome_v2::result { using Base = boost::outcome_v2::result; public: template requires std::convertible_to - constexpr Expected(U&& r) - : Base(boost::outcome_v2::in_place_type_t{}, std::forward(r)) + constexpr Expected(U&& r) : Base(boost::outcome_v2::in_place_type_t{}, std::forward(r)) { } template requires std::convertible_to && (!std::is_reference_v) - constexpr Expected(Unexpected e) - : Base(boost::outcome_v2::in_place_type_t{}, std::move(e.value())) + constexpr Expected(Unexpected e) : Base(boost::outcome_v2::in_place_type_t{}, std::move(e.value())) { } @@ -195,8 +192,7 @@ public: // Specialization of Expected. Allows returning either success // (without a value) or the reason for the failure. template -class [[nodiscard]] Expected - : private boost::outcome_v2::result +class [[nodiscard]] Expected : private boost::outcome_v2::result { using Base = boost::outcome_v2::result; diff --git a/include/xrpl/basics/FileUtilities.h b/include/xrpl/basics/FileUtilities.h index c4bc2cbe68..03013da63a 100644 --- a/include/xrpl/basics/FileUtilities.h +++ b/include/xrpl/basics/FileUtilities.h @@ -15,10 +15,7 @@ getFileContents( std::optional maxSize = std::nullopt); void -writeFileContents( - boost::system::error_code& ec, - boost::filesystem::path const& destPath, - std::string const& contents); +writeFileContents(boost::system::error_code& ec, boost::filesystem::path const& destPath, std::string const& contents); } // namespace xrpl diff --git a/include/xrpl/basics/IntrusivePointer.h b/include/xrpl/basics/IntrusivePointer.h index 101a4b6f16..366392885b 100644 --- a/include/xrpl/basics/IntrusivePointer.h +++ b/include/xrpl/basics/IntrusivePointer.h @@ -45,8 +45,8 @@ struct SharedIntrusiveAdoptNoIncrementTag // template -concept CAdoptTag = std::is_same_v || - std::is_same_v; +concept CAdoptTag = + std::is_same_v || std::is_same_v; //------------------------------------------------------------------------------ @@ -122,9 +122,7 @@ public: controlled by the rhs param. */ template - SharedIntrusive( - StaticCastTagSharedIntrusive, - SharedIntrusive const& rhs); + SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive const& rhs); /** Create a new SharedIntrusive by statically casting the pointer controlled by the rhs param. @@ -136,9 +134,7 @@ public: controlled by the rhs param. */ template - SharedIntrusive( - DynamicCastTagSharedIntrusive, - SharedIntrusive const& rhs); + SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive const& rhs); /** Create a new SharedIntrusive by dynamically casting the pointer controlled by the rhs param. @@ -304,9 +300,7 @@ class SharedWeakUnion // Tagged pointer. Low bit determines if this is a strong or a weak // pointer. The low bit must be masked to zero when converting back to a // pointer. If the low bit is '1', this is a weak pointer. - static_assert( - alignof(T) >= 2, - "Bad alignment: Combo pointer requires low bit to be zero"); + static_assert(alignof(T) >= 2, "Bad alignment: Combo pointer requires low bit to be zero"); public: SharedWeakUnion() = default; @@ -450,9 +444,7 @@ make_SharedIntrusive(Args&&... args) auto p = new TT(std::forward(args)...); static_assert( - noexcept(SharedIntrusive( - std::declval(), - std::declval())), + noexcept(SharedIntrusive(std::declval(), std::declval())), "SharedIntrusive constructor should not throw or this can leak " "memory"); diff --git a/include/xrpl/basics/IntrusivePointer.ipp b/include/xrpl/basics/IntrusivePointer.ipp index cfebb559fd..85eda5cb16 100644 --- a/include/xrpl/basics/IntrusivePointer.ipp +++ b/include/xrpl/basics/IntrusivePointer.ipp @@ -12,9 +12,7 @@ template template SharedIntrusive::SharedIntrusive(T* p, TAdoptTag) noexcept : ptr_{p} { - if constexpr (std::is_same_v< - TAdoptTag, - SharedIntrusiveAdoptIncrementStrongTag>) + if constexpr (std::is_same_v) { if (p) p->addStrongRef(); @@ -46,16 +44,14 @@ SharedIntrusive::SharedIntrusive(SharedIntrusive const& rhs) } template -SharedIntrusive::SharedIntrusive(SharedIntrusive&& rhs) - : ptr_{rhs.unsafeExchange(nullptr)} +SharedIntrusive::SharedIntrusive(SharedIntrusive&& rhs) : ptr_{rhs.unsafeExchange(nullptr)} { } template template requires std::convertible_to -SharedIntrusive::SharedIntrusive(SharedIntrusive&& rhs) - : ptr_{rhs.unsafeExchange(nullptr)} +SharedIntrusive::SharedIntrusive(SharedIntrusive&& rhs) : ptr_{rhs.unsafeExchange(nullptr)} { } template @@ -112,9 +108,7 @@ requires std::convertible_to SharedIntrusive& SharedIntrusive::operator=(SharedIntrusive&& rhs) { - static_assert( - !std::is_same_v, - "This overload should not be instantiated for T == TT"); + static_assert(!std::is_same_v, "This overload should not be instantiated for T == TT"); unsafeReleaseAndStore(rhs.unsafeExchange(nullptr)); return *this; @@ -139,9 +133,7 @@ template void SharedIntrusive::adopt(T* p) { - if constexpr (std::is_same_v< - TAdoptTag, - SharedIntrusiveAdoptIncrementStrongTag>) + if constexpr (std::is_same_v) { if (p) p->addStrongRef(); @@ -157,9 +149,7 @@ SharedIntrusive::~SharedIntrusive() template template -SharedIntrusive::SharedIntrusive( - StaticCastTagSharedIntrusive, - SharedIntrusive const& rhs) +SharedIntrusive::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive const& rhs) : ptr_{[&] { auto p = static_cast(rhs.unsafeGetRawPtr()); if (p) @@ -171,18 +161,14 @@ SharedIntrusive::SharedIntrusive( template template -SharedIntrusive::SharedIntrusive( - StaticCastTagSharedIntrusive, - SharedIntrusive&& rhs) +SharedIntrusive::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive&& rhs) : ptr_{static_cast(rhs.unsafeExchange(nullptr))} { } template template -SharedIntrusive::SharedIntrusive( - DynamicCastTagSharedIntrusive, - SharedIntrusive const& rhs) +SharedIntrusive::SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive const& rhs) : ptr_{[&] { auto p = dynamic_cast(rhs.unsafeGetRawPtr()); if (p) @@ -194,9 +180,7 @@ SharedIntrusive::SharedIntrusive( template template -SharedIntrusive::SharedIntrusive( - DynamicCastTagSharedIntrusive, - SharedIntrusive&& rhs) +SharedIntrusive::SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive&& rhs) { // This can be simplified without the `exchange`, but the `exchange` is kept // in anticipation of supporting atomic operations. @@ -315,8 +299,7 @@ WeakIntrusive::WeakIntrusive(WeakIntrusive&& rhs) : ptr_{rhs.ptr_} } template -WeakIntrusive::WeakIntrusive(SharedIntrusive const& rhs) - : ptr_{rhs.unsafeGetRawPtr()} +WeakIntrusive::WeakIntrusive(SharedIntrusive const& rhs) : ptr_{rhs.unsafeGetRawPtr()} { if (ptr_) ptr_->addWeakRef(); diff --git a/include/xrpl/basics/IntrusiveRefCounts.h b/include/xrpl/basics/IntrusiveRefCounts.h index 440ecdd19c..e9214a5adc 100644 --- a/include/xrpl/basics/IntrusiveRefCounts.h +++ b/include/xrpl/basics/IntrusiveRefCounts.h @@ -160,22 +160,19 @@ private: See description of the `refCounts` field for a fuller description of this field. */ - static constexpr FieldType partialDestroyStartedMask = - (one << (FieldTypeBits - 1)); + static constexpr FieldType partialDestroyStartedMask = (one << (FieldTypeBits - 1)); /** Flag that is set when the partialDestroy function has finished running See description of the `refCounts` field for a fuller description of this field. */ - static constexpr FieldType partialDestroyFinishedMask = - (one << (FieldTypeBits - 2)); + static constexpr FieldType partialDestroyFinishedMask = (one << (FieldTypeBits - 2)); /** Mask that will zero out all the `count` bits and leave the tag bits unchanged. */ - static constexpr FieldType tagMask = - partialDestroyStartedMask | partialDestroyFinishedMask; + static constexpr FieldType tagMask = partialDestroyStartedMask | partialDestroyFinishedMask; /** Mask that will zero out the `tag` bits and leave the count bits unchanged. @@ -184,13 +181,11 @@ private: /** Mask that will zero out everything except the strong count. */ - static constexpr FieldType strongMask = - ((one << StrongCountNumBits) - 1) & valueMask; + static constexpr FieldType strongMask = ((one << StrongCountNumBits) - 1) & valueMask; /** Mask that will zero out everything except the weak count. */ - static constexpr FieldType weakMask = - (((one << WeakCountNumBits) - 1) << StrongCountNumBits) & valueMask; + static constexpr FieldType weakMask = (((one << WeakCountNumBits) - 1) << StrongCountNumBits) & valueMask; /** Unpack the count and tag fields from the packed atomic integer form. */ struct RefCountPair @@ -215,10 +210,8 @@ private: FieldType combinedValue() const noexcept; - static constexpr CountType maxStrongValue = - static_cast((one << StrongCountNumBits) - 1); - static constexpr CountType maxWeakValue = - static_cast((one << WeakCountNumBits) - 1); + static constexpr CountType maxStrongValue = static_cast((one << StrongCountNumBits) - 1); + static constexpr CountType maxWeakValue = static_cast((one << WeakCountNumBits) - 1); /** Put an extra margin to detect when running up against limits. This is only used in debug code, and is useful if we reduce the number of bits in the strong and weak counts (to 16 and 14 bits). @@ -274,8 +267,7 @@ IntrusiveRefCounts::releaseStrongRef() const } } - if (refCounts.compare_exchange_weak( - prevIntVal, nextIntVal, std::memory_order_acq_rel)) + if (refCounts.compare_exchange_weak(prevIntVal, nextIntVal, std::memory_order_acq_rel)) { // Can't be in partial destroy because only decrementing the strong // count to zero can start a partial destroy, and that can't happen @@ -331,8 +323,7 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const action = partialDestroy; } } - if (refCounts.compare_exchange_weak( - prevIntVal, nextIntVal, std::memory_order_acq_rel)) + if (refCounts.compare_exchange_weak(prevIntVal, nextIntVal, std::memory_order_acq_rel)) { XRPL_ASSERT( (!(prevIntVal & partialDestroyStartedMask)), @@ -376,8 +367,7 @@ IntrusiveRefCounts::checkoutStrongRefFromWeak() const noexcept auto curValue = RefCountPair{1, 1}.combinedValue(); auto desiredValue = RefCountPair{2, 1}.combinedValue(); - while (!refCounts.compare_exchange_weak( - curValue, desiredValue, std::memory_order_acq_rel)) + while (!refCounts.compare_exchange_weak(curValue, desiredValue, std::memory_order_acq_rel)) { RefCountPair const prev{curValue}; if (!prev.strong) @@ -406,20 +396,15 @@ inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept { #ifndef NDEBUG auto v = refCounts.load(std::memory_order_acquire); - XRPL_ASSERT( - (!(v & valueMask)), - "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero"); + XRPL_ASSERT((!(v & valueMask)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero"); auto t = v & tagMask; - XRPL_ASSERT( - (!t || t == tagMask), - "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag"); + XRPL_ASSERT((!t || t == tagMask), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag"); #endif } //------------------------------------------------------------------------------ -inline IntrusiveRefCounts::RefCountPair::RefCountPair( - IntrusiveRefCounts::FieldType v) noexcept +inline IntrusiveRefCounts::RefCountPair::RefCountPair(IntrusiveRefCounts::FieldType v) noexcept : strong{static_cast(v & strongMask)} , weak{static_cast((v & weakMask) >> StrongCountNumBits)} , partialDestroyStartedBit{v & partialDestroyStartedMask} @@ -449,10 +434,8 @@ IntrusiveRefCounts::RefCountPair::combinedValue() const noexcept (strong < checkStrongMaxValue && weak < checkWeakMaxValue), "xrpl::IntrusiveRefCounts::RefCountPair::combinedValue : inputs " "inside range"); - return (static_cast(weak) - << IntrusiveRefCounts::StrongCountNumBits) | - static_cast(strong) | - partialDestroyStartedBit | partialDestroyFinishedBit; + return (static_cast(weak) << IntrusiveRefCounts::StrongCountNumBits) | + static_cast(strong) | partialDestroyStartedBit | partialDestroyFinishedBit; } template @@ -460,11 +443,9 @@ inline void partialDestructorFinished(T** o) { T& self = **o; - IntrusiveRefCounts::RefCountPair p = - self.refCounts.fetch_or(IntrusiveRefCounts::partialDestroyFinishedMask); + IntrusiveRefCounts::RefCountPair p = self.refCounts.fetch_or(IntrusiveRefCounts::partialDestroyFinishedMask); XRPL_ASSERT( - (!p.partialDestroyFinishedBit && p.partialDestroyStartedBit && - !p.strong), + (!p.partialDestroyFinishedBit && p.partialDestroyStartedBit && !p.strong), "xrpl::partialDestructorFinished : not a weak ref"); if (!p.weak) { diff --git a/include/xrpl/basics/LocalValue.h b/include/xrpl/basics/LocalValue.h index cc7c646fb0..8c664116c3 100644 --- a/include/xrpl/basics/LocalValue.h +++ b/include/xrpl/basics/LocalValue.h @@ -55,8 +55,7 @@ template boost::thread_specific_ptr& getLocalValues() { - static boost::thread_specific_ptr tsp( - &detail::LocalValues::cleanup); + static boost::thread_specific_ptr tsp(&detail::LocalValues::cleanup); return tsp; } @@ -105,9 +104,7 @@ LocalValue::operator*() } return *reinterpret_cast( - lvs->values - .emplace(this, std::make_unique>(t_)) - .first->second->get()); + lvs->values.emplace(this, std::make_unique>(t_)).first->second->get()); } } // namespace xrpl diff --git a/include/xrpl/basics/Log.h b/include/xrpl/basics/Log.h index f10f1ff64c..92fd2c0e9c 100644 --- a/include/xrpl/basics/Log.h +++ b/include/xrpl/basics/Log.h @@ -39,22 +39,17 @@ private: std::string partition_; public: - Sink( - std::string const& partition, - beast::severities::Severity thresh, - Logs& logs); + Sink(std::string const& partition, beast::severities::Severity thresh, Logs& logs); Sink(Sink const&) = delete; Sink& operator=(Sink const&) = delete; void - write(beast::severities::Severity level, std::string const& text) - override; + write(beast::severities::Severity level, std::string const& text) override; void - writeAlways(beast::severities::Severity level, std::string const& text) - override; + writeAlways(beast::severities::Severity level, std::string const& text) override; }; /** Manages a system file containing logged output. @@ -140,11 +135,7 @@ private: }; std::mutex mutable mutex_; - std::map< - std::string, - std::unique_ptr, - boost::beast::iless> - sinks_; + std::map, boost::beast::iless> sinks_; beast::severities::Severity thresh_; File file_; bool silent_ = false; @@ -180,11 +171,7 @@ public: partition_severities() const; void - write( - beast::severities::Severity level, - std::string const& partition, - std::string const& text, - bool console); + write(beast::severities::Severity level, std::string const& partition, std::string const& text, bool console); std::string rotate(); @@ -201,9 +188,7 @@ public: } virtual std::unique_ptr - makeSink( - std::string const& partition, - beast::severities::Severity startingLevel); + makeSink(std::string const& partition, beast::severities::Severity startingLevel); public: static LogSeverity diff --git a/include/xrpl/basics/Number.h b/include/xrpl/basics/Number.h index 2f467fb036..cdd971d8b0 100644 --- a/include/xrpl/basics/Number.h +++ b/include/xrpl/basics/Number.h @@ -74,10 +74,7 @@ struct MantissaRange enum mantissa_scale { small, large }; explicit constexpr MantissaRange(mantissa_scale scale_) - : min(getMin(scale_)) - , max(min * 10 - 1) - , log(logTen(min).value_or(-1)) - , scale(scale_) + : min(getMin(scale_)), max(min * 10 - 1), log(logTen(min).value_or(-1)), scale(scale_) { } @@ -107,8 +104,7 @@ private: // Like std::integral, but only 64-bit integral types. template -concept Integral64 = - std::is_same_v || std::is_same_v; +concept Integral64 = std::is_same_v || std::is_same_v; /** Number is a floating point type that can represent a wide range of values. * @@ -245,22 +241,11 @@ public: Number(rep mantissa); explicit Number(rep mantissa, int exponent); - explicit constexpr Number( - bool negative, - internalrep mantissa, - int exponent, - unchecked) noexcept; + explicit constexpr Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept; // Assume unsigned values are... unsigned. i.e. positive - explicit constexpr Number( - internalrep mantissa, - int exponent, - unchecked) noexcept; + explicit constexpr Number(internalrep mantissa, int exponent, unchecked) noexcept; // Only unit tests are expected to use this ctor - explicit Number( - bool negative, - internalrep mantissa, - int exponent, - normalized); + explicit Number(bool negative, internalrep mantissa, int exponent, normalized); // Assume unsigned values are... unsigned. i.e. positive explicit Number(internalrep mantissa, int exponent, normalized); @@ -310,8 +295,7 @@ public: friend constexpr bool operator==(Number const& x, Number const& y) noexcept { - return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ && - x.exponent_ == y.exponent_; + return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_; } friend constexpr bool @@ -519,37 +503,25 @@ private: class Guard; }; -inline constexpr Number::Number( - bool negative, - internalrep mantissa, - int exponent, - unchecked) noexcept +inline constexpr Number::Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept : negative_(negative), mantissa_{mantissa}, exponent_{exponent} { } -inline constexpr Number::Number( - internalrep mantissa, - int exponent, - unchecked) noexcept +inline constexpr Number::Number(internalrep mantissa, int exponent, unchecked) noexcept : Number(false, mantissa, exponent, unchecked{}) { } constexpr static Number numZero{}; -inline Number::Number( - bool negative, - internalrep mantissa, - int exponent, - normalized) +inline Number::Number(bool negative, internalrep mantissa, int exponent, normalized) : Number(negative, mantissa, exponent, unchecked{}) { normalize(); } -inline Number::Number(internalrep mantissa, int exponent, normalized) - : Number(false, mantissa, exponent, normalized{}) +inline Number::Number(internalrep mantissa, int exponent, normalized) : Number(false, mantissa, exponent, normalized{}) { } @@ -696,15 +668,13 @@ Number::min() noexcept inline Number Number::max() noexcept { - return Number{ - false, std::min(range_.get().max, maxRep), maxExponent, unchecked{}}; + return Number{false, std::min(range_.get().max, maxRep), maxExponent, unchecked{}}; } inline Number Number::lowest() noexcept { - return Number{ - true, std::min(range_.get().max, maxRep), maxExponent, unchecked{}}; + return Number{true, std::min(range_.get().max, maxRep), maxExponent, unchecked{}}; } inline bool @@ -713,8 +683,7 @@ Number::isnormal() const noexcept MantissaRange const& range = range_; auto const abs_m = mantissa_; return *this == Number{} || - (range.min <= abs_m && abs_m <= range.max && - (abs_m <= maxRep || abs_m % 10 == 0) && minExponent <= exponent_ && + (range.min <= abs_m && abs_m <= range.max && (abs_m <= maxRep || abs_m % 10 == 0) && minExponent <= exponent_ && exponent_ <= maxExponent); } @@ -727,10 +696,7 @@ Number::normalizeToRange(T minMantissa, T maxMantissa) const int exponent = exponent_; if constexpr (std::is_unsigned_v) - XRPL_ASSERT_PARTS( - !negative, - "xrpl::Number::normalizeToRange", - "Number is non-negative for unsigned range."); + XRPL_ASSERT_PARTS(!negative, "xrpl::Number::normalizeToRange", "Number is non-negative for unsigned range."); Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa); auto const sign = negative ? -1 : 1; @@ -799,8 +765,7 @@ public: { Number::setround(mode_); } - explicit saveNumberRoundMode(Number::rounding_mode mode) noexcept - : mode_{mode} + explicit saveNumberRoundMode(Number::rounding_mode mode) noexcept : mode_{mode} { } saveNumberRoundMode(saveNumberRoundMode const&) = delete; @@ -817,8 +782,7 @@ class NumberRoundModeGuard saveNumberRoundMode saved_; public: - explicit NumberRoundModeGuard(Number::rounding_mode mode) noexcept - : saved_{Number::setround(mode)} + explicit NumberRoundModeGuard(Number::rounding_mode mode) noexcept : saved_{Number::setround(mode)} { } @@ -838,9 +802,7 @@ class NumberMantissaScaleGuard MantissaRange::mantissa_scale const saved_; public: - explicit NumberMantissaScaleGuard( - MantissaRange::mantissa_scale scale) noexcept - : saved_{Number::getMantissaScale()} + explicit NumberMantissaScaleGuard(MantissaRange::mantissa_scale scale) noexcept : saved_{Number::getMantissaScale()} { Number::setMantissaScale(scale); } diff --git a/include/xrpl/basics/Resolver.h b/include/xrpl/basics/Resolver.h index 088b2e1d5b..b66f4a5ed5 100644 --- a/include/xrpl/basics/Resolver.h +++ b/include/xrpl/basics/Resolver.h @@ -11,8 +11,7 @@ namespace xrpl { class Resolver { public: - using HandlerType = - std::function)>; + using HandlerType = std::function)>; virtual ~Resolver() = 0; @@ -41,9 +40,7 @@ public: } virtual void - resolve( - std::vector const& names, - HandlerType const& handler) = 0; + resolve(std::vector const& names, HandlerType const& handler) = 0; /** @} */ }; diff --git a/include/xrpl/basics/SharedWeakCachePointer.ipp b/include/xrpl/basics/SharedWeakCachePointer.ipp index 376bf73251..eeb1a1927b 100644 --- a/include/xrpl/basics/SharedWeakCachePointer.ipp +++ b/include/xrpl/basics/SharedWeakCachePointer.ipp @@ -5,34 +5,28 @@ namespace xrpl { template -SharedWeakCachePointer::SharedWeakCachePointer( - SharedWeakCachePointer const& rhs) = default; +SharedWeakCachePointer::SharedWeakCachePointer(SharedWeakCachePointer const& rhs) = default; template template requires std::convertible_to -SharedWeakCachePointer::SharedWeakCachePointer( - std::shared_ptr const& rhs) - : combo_{rhs} +SharedWeakCachePointer::SharedWeakCachePointer(std::shared_ptr const& rhs) : combo_{rhs} { } template -SharedWeakCachePointer::SharedWeakCachePointer( - SharedWeakCachePointer&& rhs) = default; +SharedWeakCachePointer::SharedWeakCachePointer(SharedWeakCachePointer&& rhs) = default; template template requires std::convertible_to -SharedWeakCachePointer::SharedWeakCachePointer(std::shared_ptr&& rhs) - : combo_{std::move(rhs)} +SharedWeakCachePointer::SharedWeakCachePointer(std::shared_ptr&& rhs) : combo_{std::move(rhs)} { } template SharedWeakCachePointer& -SharedWeakCachePointer::operator=(SharedWeakCachePointer const& rhs) = - default; +SharedWeakCachePointer::operator=(SharedWeakCachePointer const& rhs) = default; template template diff --git a/include/xrpl/basics/SlabAllocator.h b/include/xrpl/basics/SlabAllocator.h index c67d1ee318..199eaf3bcc 100644 --- a/include/xrpl/basics/SlabAllocator.h +++ b/include/xrpl/basics/SlabAllocator.h @@ -51,11 +51,7 @@ class SlabAllocator // The extent of the underlying memory block: std::size_t const size_; - SlabBlock( - SlabBlock* next, - std::uint8_t* data, - std::size_t size, - std::size_t item) + SlabBlock(SlabBlock* next, std::uint8_t* data, std::size_t size, std::size_t item) : next_(next), p_(data), size_(size) { // We don't need to grab the mutex here, since we're the only @@ -126,9 +122,7 @@ class SlabAllocator void deallocate(std::uint8_t* ptr) noexcept { - XRPL_ASSERT( - own(ptr), - "xrpl::SlabAllocator::SlabBlock::deallocate : own input"); + XRPL_ASSERT(own(ptr), "xrpl::SlabAllocator::SlabBlock::deallocate : own input"); std::lock_guard l(m_); @@ -162,18 +156,13 @@ public: contexts (e.g. when minimal memory usage is needed) and allows for graceful failure. */ - constexpr explicit SlabAllocator( - std::size_t extra, - std::size_t alloc = 0, - std::size_t align = 0) + constexpr explicit SlabAllocator(std::size_t extra, std::size_t alloc = 0, std::size_t align = 0) : itemAlignment_(align ? align : alignof(Type)) - , itemSize_( - boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_)) + , itemSize_(boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_)) , slabSize_(alloc) { XRPL_ASSERT( - (itemAlignment_ & (itemAlignment_ - 1)) == 0, - "xrpl::SlabAllocator::SlabAllocator : valid alignment"); + (itemAlignment_ & (itemAlignment_ - 1)) == 0, "xrpl::SlabAllocator::SlabAllocator : valid alignment"); } SlabAllocator(SlabAllocator const& other) = delete; @@ -222,8 +211,7 @@ public: // We want to allocate the memory at a 2 MiB boundary, to make it // possible to use hugepage mappings on Linux: - auto buf = - boost::alignment::aligned_alloc(megabytes(std::size_t(2)), size); + auto buf = boost::alignment::aligned_alloc(megabytes(std::size_t(2)), size); // clang-format off if (!buf) [[unlikely]] @@ -241,31 +229,21 @@ public: // We need to carve out a bit of memory for the slab header // and then align the rest appropriately: - auto slabData = reinterpret_cast( - reinterpret_cast(buf) + sizeof(SlabBlock)); + auto slabData = reinterpret_cast(reinterpret_cast(buf) + sizeof(SlabBlock)); auto slabSize = size - sizeof(SlabBlock); // This operation is essentially guaranteed not to fail but // let's be careful anyways. - if (!boost::alignment::align( - itemAlignment_, itemSize_, slabData, slabSize)) + if (!boost::alignment::align(itemAlignment_, itemSize_, slabData, slabSize)) { boost::alignment::aligned_free(buf); return nullptr; } - slab = new (buf) SlabBlock( - slabs_.load(), - reinterpret_cast(slabData), - slabSize, - itemSize_); + slab = new (buf) SlabBlock(slabs_.load(), reinterpret_cast(slabData), slabSize, itemSize_); // Link the new slab - while (!slabs_.compare_exchange_weak( - slab->next_, - slab, - std::memory_order_release, - std::memory_order_relaxed)) + while (!slabs_.compare_exchange_weak(slab->next_, slab, std::memory_order_release, std::memory_order_relaxed)) { ; // Nothing to do } @@ -322,10 +300,7 @@ public: std::size_t align; public: - constexpr SlabConfig( - std::size_t extra_, - std::size_t alloc_ = 0, - std::size_t align_ = alignof(Type)) + constexpr SlabConfig(std::size_t extra_, std::size_t alloc_ = 0, std::size_t align_ = alignof(Type)) : extra(extra_), alloc(alloc_), align(align_) { } @@ -336,23 +311,14 @@ public: // Ensure that the specified allocators are sorted from smallest to // largest by size: std::sort( - std::begin(cfg), - std::end(cfg), - [](SlabConfig const& a, SlabConfig const& b) { - return a.extra < b.extra; - }); + std::begin(cfg), std::end(cfg), [](SlabConfig const& a, SlabConfig const& b) { return a.extra < b.extra; }); // We should never have two slabs of the same size - if (std::adjacent_find( - std::begin(cfg), - std::end(cfg), - [](SlabConfig const& a, SlabConfig const& b) { - return a.extra == b.extra; - }) != cfg.end()) + if (std::adjacent_find(std::begin(cfg), std::end(cfg), [](SlabConfig const& a, SlabConfig const& b) { + return a.extra == b.extra; + }) != cfg.end()) { - throw std::runtime_error( - "SlabAllocatorSet<" + beast::type_name() + - ">: duplicate slab size"); + throw std::runtime_error("SlabAllocatorSet<" + beast::type_name() + ">: duplicate slab size"); } for (auto const& c : cfg) diff --git a/include/xrpl/basics/Slice.h b/include/xrpl/basics/Slice.h index fba4b7733c..b8990cb1bb 100644 --- a/include/xrpl/basics/Slice.h +++ b/include/xrpl/basics/Slice.h @@ -41,8 +41,7 @@ public: operator=(Slice const&) noexcept = default; /** Create a slice pointing to existing memory. */ - Slice(void const* data, std::size_t size) noexcept - : data_(reinterpret_cast(data)), size_(size) + Slice(void const* data, std::size_t size) noexcept : data_(reinterpret_cast(data)), size_(size) { } @@ -85,9 +84,7 @@ public: std::uint8_t operator[](std::size_t i) const noexcept { - XRPL_ASSERT( - i < size_, - "xrpl::Slice::operator[](std::size_t) const : valid input"); + XRPL_ASSERT(i < size_, "xrpl::Slice::operator[](std::size_t) const : valid input"); return data_[i]; } @@ -162,9 +159,7 @@ public: @throws std::out_of_range if pos > size() */ Slice - substr( - std::size_t pos, - std::size_t count = std::numeric_limits::max()) const + substr(std::size_t pos, std::size_t count = std::numeric_limits::max()) const { if (pos > size()) throw std::out_of_range("Requested sub-slice is out of bounds"); @@ -203,11 +198,7 @@ operator!=(Slice const& lhs, Slice const& rhs) noexcept inline bool operator<(Slice const& lhs, Slice const& rhs) noexcept { - return std::lexicographical_compare( - lhs.data(), - lhs.data() + lhs.size(), - rhs.data(), - rhs.data() + rhs.size()); + return std::lexicographical_compare(lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size()); } template @@ -219,18 +210,14 @@ operator<<(Stream& s, Slice const& v) } template -std::enable_if_t< - std::is_same::value || std::is_same::value, - Slice> +std::enable_if_t::value || std::is_same::value, Slice> makeSlice(std::array const& a) { return Slice(a.data(), a.size()); } template -std::enable_if_t< - std::is_same::value || std::is_same::value, - Slice> +std::enable_if_t::value || std::is_same::value, Slice> makeSlice(std::vector const& v) { return Slice(v.data(), v.size()); diff --git a/include/xrpl/basics/StringUtilities.h b/include/xrpl/basics/StringUtilities.h index 6314a56103..3d5a18f120 100644 --- a/include/xrpl/basics/StringUtilities.h +++ b/include/xrpl/basics/StringUtilities.h @@ -109,8 +109,7 @@ struct parsedURL bool operator==(parsedURL const& other) const { - return scheme == other.scheme && domain == other.domain && - port == other.port && path == other.path; + return scheme == other.scheme && domain == other.domain && port == other.port && path == other.path; } }; diff --git a/include/xrpl/basics/TaggedCache.h b/include/xrpl/basics/TaggedCache.h index c1d4d26800..2b82f63a00 100644 --- a/include/xrpl/basics/TaggedCache.h +++ b/include/xrpl/basics/TaggedCache.h @@ -56,8 +56,7 @@ public: clock_type::duration expiration, clock_type& clock, beast::Journal journal, - beast::insight::Collector::ptr const& collector = - beast::insight::NullCollector::New()); + beast::insight::Collector::ptr const& collector = beast::insight::NullCollector::New()); public: /** Return the clock associated with the cache. */ @@ -114,15 +113,10 @@ public: */ template bool - canonicalize( - key_type const& key, - SharedPointerType& data, - R&& replaceCallback); + canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback); bool - canonicalize_replace_cache( - key_type const& key, - SharedPointerType const& data); + canonicalize_replace_cache(key_type const& key, SharedPointerType const& data); bool canonicalize_replace_client(key_type const& key, SharedPointerType& data); @@ -136,8 +130,7 @@ public: */ template auto - insert(key_type const& key, T const& value) - -> std::enable_if_t; + insert(key_type const& key, T const& value) -> std::enable_if_t; template auto @@ -183,10 +176,7 @@ private: struct Stats { template - Stats( - std::string const& prefix, - Handler const& handler, - beast::insight::Collector::ptr const& collector) + Stats(std::string const& prefix, Handler const& handler, beast::insight::Collector::ptr const& collector) : hook(collector->make_hook(handler)) , size(collector->make_gauge(prefix, "size")) , hit_rate(collector->make_gauge(prefix, "hit_rate")) @@ -208,8 +198,7 @@ private: public: clock_type::time_point last_access; - explicit KeyOnlyEntry(clock_type::time_point const& last_access_) - : last_access(last_access_) + explicit KeyOnlyEntry(clock_type::time_point const& last_access_) : last_access(last_access_) { } @@ -226,9 +215,7 @@ private: shared_weak_combo_pointer_type ptr; clock_type::time_point last_access; - ValueEntry( - clock_type::time_point const& last_access_, - shared_pointer_type const& ptr_) + ValueEntry(clock_type::time_point const& last_access_, shared_pointer_type const& ptr_) : ptr(ptr_), last_access(last_access_) { } @@ -262,18 +249,13 @@ private: } }; - typedef - typename std::conditional::type - Entry; + typedef typename std::conditional::type Entry; - using KeyOnlyCacheType = - hardened_partitioned_hash_map; + using KeyOnlyCacheType = hardened_partitioned_hash_map; - using KeyValueCacheType = - hardened_partitioned_hash_map; + using KeyValueCacheType = hardened_partitioned_hash_map; - using cache_type = - hardened_partitioned_hash_map; + using cache_type = hardened_partitioned_hash_map; [[nodiscard]] std::thread sweepHelper( diff --git a/include/xrpl/basics/TaggedCache.ipp b/include/xrpl/basics/TaggedCache.ipp index 5114479921..837db67c32 100644 --- a/include/xrpl/basics/TaggedCache.ipp +++ b/include/xrpl/basics/TaggedCache.ipp @@ -15,22 +15,13 @@ template < class Hash, class KeyEqual, class Mutex> -inline TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>:: - TaggedCache( - std::string const& name, - int size, - clock_type::duration expiration, - clock_type& clock, - beast::Journal journal, - beast::insight::Collector::ptr const& collector) +inline TaggedCache::TaggedCache( + std::string const& name, + int size, + clock_type::duration expiration, + clock_type& clock, + beast::Journal journal, + beast::insight::Collector::ptr const& collector) : m_journal(journal) , m_clock(clock) , m_stats(name, std::bind(&TaggedCache::collect_metrics, this), collector) @@ -53,15 +44,8 @@ template < class KeyEqual, class Mutex> inline auto -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::clock() -> clock_type& +TaggedCache::clock() + -> clock_type& { return m_clock; } @@ -76,15 +60,7 @@ template < class KeyEqual, class Mutex> inline std::size_t -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::size() const +TaggedCache::size() const { std::lock_guard lock(m_mutex); return m_cache.size(); @@ -100,15 +76,7 @@ template < class KeyEqual, class Mutex> inline int -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::getCacheSize() const +TaggedCache::getCacheSize() const { std::lock_guard lock(m_mutex); return m_cache_count; @@ -124,15 +92,7 @@ template < class KeyEqual, class Mutex> inline int -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::getTrackSize() const +TaggedCache::getTrackSize() const { std::lock_guard lock(m_mutex); return m_cache.size(); @@ -148,15 +108,7 @@ template < class KeyEqual, class Mutex> inline float -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::getHitRate() +TaggedCache::getHitRate() { std::lock_guard lock(m_mutex); auto const total = static_cast(m_hits + m_misses); @@ -173,15 +125,7 @@ template < class KeyEqual, class Mutex> inline void -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::clear() +TaggedCache::clear() { std::lock_guard lock(m_mutex); m_cache.clear(); @@ -198,15 +142,7 @@ template < class KeyEqual, class Mutex> inline void -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::reset() +TaggedCache::reset() { std::lock_guard lock(m_mutex); m_cache.clear(); @@ -226,15 +162,8 @@ template < class Mutex> template inline bool -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::touch_if_exists(KeyComparable const& key) +TaggedCache::touch_if_exists( + KeyComparable const& key) { std::lock_guard lock(m_mutex); auto const iter(m_cache.find(key)); @@ -258,15 +187,7 @@ template < class KeyEqual, class Mutex> inline void -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::sweep() +TaggedCache::sweep() { // Keep references to all the stuff we sweep // For performance, each worker thread should exit before the swept data @@ -280,8 +201,7 @@ TaggedCache< { std::lock_guard lock(m_mutex); - if (m_target_size == 0 || - (static_cast(m_cache.size()) <= m_target_size)) + if (m_target_size == 0 || (static_cast(m_cache.size()) <= m_target_size)) { when_expire = now - m_target_age; } @@ -293,10 +213,8 @@ TaggedCache< if (when_expire > (now - minimumAge)) when_expire = now - minimumAge; - JLOG(m_journal.trace()) - << m_name << " is growing fast " << m_cache.size() << " of " - << m_target_size << " aging at " << (now - when_expire).count() - << " of " << m_target_age.count(); + JLOG(m_journal.trace()) << m_name << " is growing fast " << m_cache.size() << " of " << m_target_size + << " aging at " << (now - when_expire).count() << " of " << m_target_age.count(); } std::vector workers; @@ -305,13 +223,7 @@ TaggedCache< for (std::size_t p = 0; p < m_cache.partitions(); ++p) { - workers.push_back(sweepHelper( - when_expire, - now, - m_cache.map()[p], - allStuffToSweep[p], - allRemovals, - lock)); + workers.push_back(sweepHelper(when_expire, now, m_cache.map()[p], allStuffToSweep[p], allRemovals, lock)); } for (std::thread& worker : workers) worker.join(); @@ -322,9 +234,7 @@ TaggedCache< // and decrement the reference count on each strong pointer. JLOG(m_journal.debug()) << m_name << " TaggedCache sweep lock duration " - << std::chrono::duration_cast( - std::chrono::steady_clock::now() - start) - .count() + << std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count() << "ms"; } @@ -338,15 +248,9 @@ template < class KeyEqual, class Mutex> inline bool -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::del(key_type const& key, bool valid) +TaggedCache::del( + key_type const& key, + bool valid) { // Remove from cache, if !valid, remove from map too. Returns true if // removed from cache @@ -385,19 +289,10 @@ template < class Mutex> template inline bool -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>:: - canonicalize( - key_type const& key, - SharedPointerType& data, - R&& replaceCallback) +TaggedCache::canonicalize( + key_type const& key, + SharedPointerType& data, + R&& replaceCallback) { // Return canonical value, store if needed, refresh in cache // Return values: true=we had the data already @@ -408,9 +303,7 @@ TaggedCache< if (cit == m_cache.end()) { m_cache.emplace( - std::piecewise_construct, - std::forward_as_tuple(key), - std::forward_as_tuple(m_clock.now(), data)); + std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(m_clock.now(), data)); ++m_cache_count; return false; } @@ -480,21 +373,10 @@ template < class KeyEqual, class Mutex> inline bool -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>:: - canonicalize_replace_cache( - key_type const& key, - SharedPointerType const& data) +TaggedCache:: + canonicalize_replace_cache(key_type const& key, SharedPointerType const& data) { - return canonicalize( - key, const_cast(data), []() { return true; }); + return canonicalize(key, const_cast(data), []() { return true; }); } template < @@ -507,15 +389,7 @@ template < class KeyEqual, class Mutex> inline bool -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>:: +TaggedCache:: canonicalize_replace_client(key_type const& key, SharedPointerType& data) { return canonicalize(key, data, []() { return false; }); @@ -531,15 +405,8 @@ template < class KeyEqual, class Mutex> inline SharedPointerType -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::fetch(key_type const& key) +TaggedCache::fetch( + key_type const& key) { std::lock_guard l(m_mutex); auto ret = initialFetch(key, l); @@ -559,16 +426,9 @@ template < class Mutex> template inline auto -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::insert(key_type const& key, T const& value) - -> std::enable_if_t +TaggedCache::insert( + key_type const& key, + T const& value) -> std::enable_if_t { static_assert( std::is_same_v, SharedPointerType> || @@ -597,23 +457,13 @@ template < class Mutex> template inline auto -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::insert(key_type const& key) - -> std::enable_if_t +TaggedCache::insert( + key_type const& key) -> std::enable_if_t { std::lock_guard lock(m_mutex); clock_type::time_point const now(m_clock.now()); - auto [it, inserted] = m_cache.emplace( - std::piecewise_construct, - std::forward_as_tuple(key), - std::forward_as_tuple(now)); + auto [it, inserted] = + m_cache.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now)); if (!inserted) it->second.last_access = now; return inserted; @@ -629,15 +479,9 @@ template < class KeyEqual, class Mutex> inline bool -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::retrieve(key_type const& key, T& data) +TaggedCache::retrieve( + key_type const& key, + T& data) { // retrieve the value of the stored data auto entry = fetch(key); @@ -659,15 +503,8 @@ template < class KeyEqual, class Mutex> inline auto -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::peekMutex() -> mutex_type& +TaggedCache::peekMutex() + -> mutex_type& { return m_mutex; } @@ -682,15 +519,8 @@ template < class KeyEqual, class Mutex> inline auto -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::getKeys() const -> std::vector +TaggedCache::getKeys() const + -> std::vector { std::vector v; @@ -714,15 +544,7 @@ template < class KeyEqual, class Mutex> inline double -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::rate() const +TaggedCache::rate() const { std::lock_guard lock(m_mutex); auto const tot = m_hits + m_misses; @@ -742,15 +564,9 @@ template < class Mutex> template inline SharedPointerType -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::fetch(key_type const& digest, Handler const& h) +TaggedCache::fetch( + key_type const& digest, + Handler const& h) { { std::lock_guard l(m_mutex); @@ -764,8 +580,7 @@ TaggedCache< std::lock_guard l(m_mutex); ++m_misses; - auto const [it, inserted] = - m_cache.emplace(digest, Entry(m_clock.now(), std::move(sle))); + auto const [it, inserted] = m_cache.emplace(digest, Entry(m_clock.now(), std::move(sle))); if (!inserted) it->second.touch(m_clock.now()); return it->second.ptr.getStrong(); @@ -782,16 +597,9 @@ template < class KeyEqual, class Mutex> inline SharedPointerType -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>:: - initialFetch(key_type const& key, std::lock_guard const& l) +TaggedCache::initialFetch( + key_type const& key, + std::lock_guard const& l) { auto cit = m_cache.find(key); if (cit == m_cache.end()) @@ -827,15 +635,7 @@ template < class KeyEqual, class Mutex> inline void -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>::collect_metrics() +TaggedCache::collect_metrics() { m_stats.size.set(getCacheSize()); @@ -861,22 +661,13 @@ template < class KeyEqual, class Mutex> inline std::thread -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>:: - sweepHelper( - clock_type::time_point const& when_expire, - [[maybe_unused]] clock_type::time_point const& now, - typename KeyValueCacheType::map_type& partition, - SweptPointersVector& stuffToSweep, - std::atomic& allRemovals, - std::lock_guard const&) +TaggedCache::sweepHelper( + clock_type::time_point const& when_expire, + [[maybe_unused]] clock_type::time_point const& now, + typename KeyValueCacheType::map_type& partition, + SweptPointersVector& stuffToSweep, + std::atomic& allRemovals, + std::lock_guard const&) { return std::thread([&, this]() { int cacheRemovals = 0; @@ -930,10 +721,8 @@ TaggedCache< if (mapRemovals || cacheRemovals) { - JLOG(m_journal.debug()) - << "TaggedCache partition sweep " << m_name - << ": cache = " << partition.size() << "-" << cacheRemovals - << ", map-=" << mapRemovals; + JLOG(m_journal.debug()) << "TaggedCache partition sweep " << m_name << ": cache = " << partition.size() + << "-" << cacheRemovals << ", map-=" << mapRemovals; } allRemovals += cacheRemovals; @@ -950,22 +739,13 @@ template < class KeyEqual, class Mutex> inline std::thread -TaggedCache< - Key, - T, - IsKeyCache, - SharedWeakUnionPointer, - SharedPointerType, - Hash, - KeyEqual, - Mutex>:: - sweepHelper( - clock_type::time_point const& when_expire, - clock_type::time_point const& now, - typename KeyOnlyCacheType::map_type& partition, - SweptPointersVector&, - std::atomic& allRemovals, - std::lock_guard const&) +TaggedCache::sweepHelper( + clock_type::time_point const& when_expire, + clock_type::time_point const& now, + typename KeyOnlyCacheType::map_type& partition, + SweptPointersVector&, + std::atomic& allRemovals, + std::lock_guard const&) { return std::thread([&, this]() { int cacheRemovals = 0; @@ -995,10 +775,8 @@ TaggedCache< if (mapRemovals || cacheRemovals) { - JLOG(m_journal.debug()) - << "TaggedCache partition sweep " << m_name - << ": cache = " << partition.size() << "-" << cacheRemovals - << ", map-=" << mapRemovals; + JLOG(m_journal.debug()) << "TaggedCache partition sweep " << m_name << ": cache = " << partition.size() + << "-" << cacheRemovals << ", map-=" << mapRemovals; } allRemovals += cacheRemovals; diff --git a/include/xrpl/basics/UnorderedContainers.h b/include/xrpl/basics/UnorderedContainers.h index fdd2518b1e..75d1fdb8da 100644 --- a/include/xrpl/basics/UnorderedContainers.h +++ b/include/xrpl/basics/UnorderedContainers.h @@ -40,8 +40,7 @@ template < class Hash = beast::uhash<>, class Pred = std::equal_to, class Allocator = std::allocator>> -using hash_multimap = - std::unordered_multimap; +using hash_multimap = std::unordered_multimap; template < class Value, @@ -75,8 +74,7 @@ template < class Hash = hardened_hash, class Pred = std::equal_to, class Allocator = std::allocator>> -using hardened_partitioned_hash_map = - partitioned_unordered_map; +using hardened_partitioned_hash_map = partitioned_unordered_map; template < class Key, @@ -84,8 +82,7 @@ template < class Hash = hardened_hash, class Pred = std::equal_to, class Allocator = std::allocator>> -using hardened_hash_multimap = - std::unordered_multimap; +using hardened_hash_multimap = std::unordered_multimap; template < class Value, @@ -99,8 +96,7 @@ template < class Hash = hardened_hash, class Pred = std::equal_to, class Allocator = std::allocator> -using hardened_hash_multiset = - std::unordered_multiset; +using hardened_hash_multiset = std::unordered_multiset; } // namespace xrpl diff --git a/include/xrpl/basics/algorithm.h b/include/xrpl/basics/algorithm.h index d62ff17a75..1f536764db 100644 --- a/include/xrpl/basics/algorithm.h +++ b/include/xrpl/basics/algorithm.h @@ -52,13 +52,7 @@ generalized_set_intersection( // std::set_intersection. template FwdIter1 -remove_if_intersect_or_match( - FwdIter1 first1, - FwdIter1 last1, - InputIter2 first2, - InputIter2 last2, - Pred pred, - Comp comp) +remove_if_intersect_or_match(FwdIter1 first1, FwdIter1 last1, InputIter2 first2, InputIter2 last2, Pred pred, Comp comp) { // [original-first1, current-first1) is the set of elements to be preserved. // [current-first1, i) is the set of elements that have been removed. diff --git a/include/xrpl/basics/base64.h b/include/xrpl/basics/base64.h index 340e282f87..508196cf11 100644 --- a/include/xrpl/basics/base64.h +++ b/include/xrpl/basics/base64.h @@ -46,8 +46,7 @@ base64_encode(std::uint8_t const* data, std::size_t len); inline std::string base64_encode(std::string const& s) { - return base64_encode( - reinterpret_cast(s.data()), s.size()); + return base64_encode(reinterpret_cast(s.data()), s.size()); } std::string diff --git a/include/xrpl/basics/base_uint.h b/include/xrpl/basics/base_uint.h index a1ed223674..32d6ad20fc 100644 --- a/include/xrpl/basics/base_uint.h +++ b/include/xrpl/basics/base_uint.h @@ -65,13 +65,9 @@ struct is_contiguous_container : std::true_type template class base_uint { - static_assert( - (Bits % 32) == 0, - "The length of a base_uint in bits must be a multiple of 32."); + static_assert((Bits % 32) == 0, "The length of a base_uint in bits must be a multiple of 32."); - static_assert( - Bits >= 64, - "The length of a base_uint in bits must be at least 64."); + static_assert(Bits >= 64, "The length of a base_uint in bits must be at least 64."); static constexpr std::size_t WIDTH = Bits / 32; @@ -182,9 +178,7 @@ private: { // Local lambda that converts a single hex char to four bits and // ORs those bits into a uint32_t. - auto hexCharToUInt = [](char c, - std::uint32_t shift, - std::uint32_t& accum) -> ParseResult { + auto hexCharToUInt = [](char c, std::uint32_t shift, std::uint32_t& accum) -> ParseResult { std::uint32_t nibble = 0xFFu; if (c < '0' || c > 'f') return ParseResult::badChar; @@ -221,8 +215,7 @@ private: std::uint32_t accum = {}; for (std::uint32_t shift : {4u, 0u, 12u, 8u, 20u, 16u, 28u, 24u}) { - if (auto const result = hexCharToUInt(*in++, shift, accum); - result != ParseResult::okay) + if (auto const result = hexCharToUInt(*in++, shift, accum); result != ParseResult::okay) return Unexpected(result); } ret[i++] = accum; @@ -261,8 +254,7 @@ public: // This constructor is intended to be used at compile time since it might // throw at runtime. Consider declaring this constructor consteval once // we get to C++23. - explicit constexpr base_uint(std::string_view sv) noexcept(false) - : data_(parseFromStringViewThrows(sv)) + explicit constexpr base_uint(std::string_view sv) noexcept(false) : data_(parseFromStringViewThrows(sv)) { } @@ -387,8 +379,7 @@ public: // prefix operator for (int i = WIDTH - 1; i >= 0; --i) { - data_[i] = boost::endian::native_to_big( - boost::endian::big_to_native(data_[i]) + 1); + data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) + 1); if (data_[i] != 0) break; } @@ -412,8 +403,7 @@ public: for (int i = WIDTH - 1; i >= 0; --i) { auto prev = data_[i]; - data_[i] = boost::endian::native_to_big( - boost::endian::big_to_native(data_[i]) - 1); + data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) - 1); if (prev != 0) break; @@ -453,11 +443,9 @@ public: for (int i = WIDTH; i--;) { - std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) + - boost::endian::big_to_native(b.data_[i]); + std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) + boost::endian::big_to_native(b.data_[i]); - data_[i] = - boost::endian::native_to_big(static_cast(n)); + data_[i] = boost::endian::native_to_big(static_cast(n)); carry = n >> 32; } @@ -557,8 +545,7 @@ operator<=>(base_uint const& lhs, base_uint const& rhs) if (ret.first == lhs.cend()) return std::strong_ordering::equivalent; - return (*ret.first > *ret.second) ? std::strong_ordering::greater - : std::strong_ordering::less; + return (*ret.first > *ret.second) ? std::strong_ordering::greater : std::strong_ordering::less; } template @@ -617,9 +604,7 @@ template inline std::string to_short_string(base_uint const& a) { - static_assert( - base_uint::bytes > 4, - "For 4 bytes or less, use a native type"); + static_assert(base_uint::bytes > 4, "For 4 bytes or less, use a native type"); return strHex(a.cbegin(), a.cbegin() + 4) + "..."; } @@ -653,8 +638,7 @@ static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes"); namespace beast { template -struct is_uniquely_represented> - : public std::true_type +struct is_uniquely_represented> : public std::true_type { explicit is_uniquely_represented() = default; }; diff --git a/include/xrpl/basics/chrono.h b/include/xrpl/basics/chrono.h index e343e8b49f..b542d1ded2 100644 --- a/include/xrpl/basics/chrono.h +++ b/include/xrpl/basics/chrono.h @@ -16,12 +16,9 @@ namespace xrpl { // A few handy aliases -using days = std::chrono::duration< - int, - std::ratio_multiply>>; +using days = std::chrono::duration>>; -using weeks = std::chrono:: - duration>>; +using weeks = std::chrono::duration>>; /** Clock for measuring the network time. @@ -34,8 +31,7 @@ using weeks = std::chrono:: */ constexpr static std::chrono::seconds epoch_offset = - date::sys_days{date::year{2000} / 1 / 1} - - date::sys_days{date::year{1970} / 1 / 1}; + date::sys_days{date::year{2000} / 1 / 1} - date::sys_days{date::year{1970} / 1 / 1}; static_assert(epoch_offset.count() == 946684800); @@ -64,8 +60,7 @@ to_string(NetClock::time_point tp) { // 2000-01-01 00:00:00 UTC is 946684800s from 1970-01-01 00:00:00 UTC using namespace std::chrono; - return to_string( - system_clock::time_point{tp.time_since_epoch() + epoch_offset}); + return to_string(system_clock::time_point{tp.time_since_epoch() + epoch_offset}); } template @@ -82,8 +77,7 @@ to_string_iso(NetClock::time_point tp) // 2000-01-01 00:00:00 UTC is 946684800s from 1970-01-01 00:00:00 UTC // Note, NetClock::duration is seconds, as checked by static_assert static_assert(std::is_same_v>); - return to_string_iso(date::sys_time{ - tp.time_since_epoch() + epoch_offset}); + return to_string_iso(date::sys_time{tp.time_since_epoch() + epoch_offset}); } /** A clock for measuring elapsed time. diff --git a/include/xrpl/basics/contract.h b/include/xrpl/basics/contract.h index 63d1bb5a84..bd2025dd17 100644 --- a/include/xrpl/basics/contract.h +++ b/include/xrpl/basics/contract.h @@ -36,15 +36,10 @@ template [[noreturn]] inline void Throw(Args&&... args) { - static_assert( - std::is_convertible::value, - "Exception must derive from std::exception."); + static_assert(std::is_convertible::value, "Exception must derive from std::exception."); E e(std::forward(args)...); - LogThrow( - std::string( - "Throwing exception of type " + beast::type_name() + ": ") + - e.what()); + LogThrow(std::string("Throwing exception of type " + beast::type_name() + ": ") + e.what()); throw e; } diff --git a/include/xrpl/basics/join.h b/include/xrpl/basics/join.h index 79f716ec43..890b6fdc10 100644 --- a/include/xrpl/basics/join.h +++ b/include/xrpl/basics/join.h @@ -24,8 +24,7 @@ public: Collection const& collection; std::string const delimiter; - explicit CollectionAndDelimiter(Collection const& c, std::string delim) - : collection(c), delimiter(std::move(delim)) + explicit CollectionAndDelimiter(Collection const& c, std::string delim) : collection(c), delimiter(std::move(delim)) { } @@ -33,11 +32,7 @@ public: friend Stream& operator<<(Stream& s, CollectionAndDelimiter const& cd) { - return join( - s, - std::begin(cd.collection), - std::end(cd.collection), - cd.delimiter); + return join(s, std::begin(cd.collection), std::end(cd.collection), cd.delimiter); } }; @@ -69,8 +64,7 @@ public: char const* collection; std::string const delimiter; - explicit CollectionAndDelimiter(char const c[N], std::string delim) - : collection(c), delimiter(std::move(delim)) + explicit CollectionAndDelimiter(char const c[N], std::string delim) : collection(c), delimiter(std::move(delim)) { } diff --git a/include/xrpl/basics/partitioned_unordered_map.h b/include/xrpl/basics/partitioned_unordered_map.h index 518686c533..f011fb9508 100644 --- a/include/xrpl/basics/partitioned_unordered_map.h +++ b/include/xrpl/basics/partitioned_unordered_map.h @@ -51,8 +51,7 @@ public: using const_reference = value_type const&; using pointer = value_type*; using const_pointer = value_type const*; - using map_type = std:: - unordered_map; + using map_type = std::unordered_map; using partition_map_type = std::vector; struct iterator @@ -113,8 +112,7 @@ public: friend bool operator==(iterator const& lhs, iterator const& rhs) { - return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ && - lhs.mit_ == rhs.mit_; + return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ && lhs.mit_ == rhs.mit_; } friend bool @@ -190,8 +188,7 @@ public: friend bool operator==(const_iterator const& lhs, const_iterator const& rhs) { - return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ && - lhs.mit_ == rhs.mit_; + return lhs.map_ == rhs.map_ && lhs.ait_ == rhs.ait_ && lhs.mit_ == rhs.mit_; } friend bool @@ -231,14 +228,11 @@ private: } public: - partitioned_unordered_map( - std::optional partitions = std::nullopt) + partitioned_unordered_map(std::optional partitions = std::nullopt) { // Set partitions to the number of hardware threads if the parameter // is either empty or set to 0. - partitions_ = partitions && *partitions - ? *partitions - : std::thread::hardware_concurrency(); + partitions_ = partitions && *partitions ? *partitions : std::thread::hardware_concurrency(); map_.resize(partitions_); XRPL_ASSERT( partitions_, @@ -337,10 +331,8 @@ public: auto const& key = std::get<0>(keyTuple); iterator it(&map_); it.ait_ = it.map_->begin() + partitioner(key); - auto [eit, inserted] = it.ait_->emplace( - std::piecewise_construct, - std::forward(keyTuple), - std::forward(valueTuple)); + auto [eit, inserted] = + it.ait_->emplace(std::piecewise_construct, std::forward(keyTuple), std::forward(valueTuple)); it.mit_ = eit; return {it, inserted}; } @@ -351,8 +343,7 @@ public: { iterator it(&map_); it.ait_ = it.map_->begin() + partitioner(key); - auto [eit, inserted] = - it.ait_->emplace(std::forward(key), std::forward(val)); + auto [eit, inserted] = it.ait_->emplace(std::forward(key), std::forward(val)); it.mit_ = eit; return {it, inserted}; } diff --git a/include/xrpl/basics/random.h b/include/xrpl/basics/random.h index 737b8fef59..74ec14c742 100644 --- a/include/xrpl/basics/random.h +++ b/include/xrpl/basics/random.h @@ -20,8 +20,7 @@ static_assert( "The Ripple default PRNG engine must return an unsigned integral type."); static_assert( - std::numeric_limits::max() >= - std::numeric_limits::max(), + std::numeric_limits::max() >= std::numeric_limits::max(), "The Ripple default PRNG engine return must be at least 64 bits wide."); #endif @@ -90,9 +89,7 @@ default_prng() */ /** @{ */ template -std::enable_if_t< - std::is_integral::value && detail::is_engine::value, - Integral> +std::enable_if_t::value && detail::is_engine::value, Integral> rand_int(Engine& engine, Integral min, Integral max) { XRPL_ASSERT(max > min, "xrpl::rand_int : max over min inputs"); @@ -111,9 +108,7 @@ rand_int(Integral min, Integral max) } template -std::enable_if_t< - std::is_integral::value && detail::is_engine::value, - Integral> +std::enable_if_t::value && detail::is_engine::value, Integral> rand_int(Engine& engine, Integral max) { return rand_int(engine, Integral(0), max); @@ -127,9 +122,7 @@ rand_int(Integral max) } template -std::enable_if_t< - std::is_integral::value && detail::is_engine::value, - Integral> +std::enable_if_t::value && detail::is_engine::value, Integral> rand_int(Engine& engine) { return rand_int(engine, std::numeric_limits::max()); @@ -147,23 +140,17 @@ rand_int() /** @{ */ template std::enable_if_t< - (std::is_same::value || - std::is_same::value) && + (std::is_same::value || std::is_same::value) && detail::is_engine::value, Byte> rand_byte(Engine& engine) { - return static_cast(rand_int( - engine, - std::numeric_limits::min(), - std::numeric_limits::max())); + return static_cast( + rand_int(engine, std::numeric_limits::min(), std::numeric_limits::max())); } template -std::enable_if_t< - (std::is_same::value || - std::is_same::value), - Byte> +std::enable_if_t<(std::is_same::value || std::is_same::value), Byte> rand_byte() { return rand_byte(default_prng()); diff --git a/include/xrpl/basics/safe_cast.h b/include/xrpl/basics/safe_cast.h index 89de0eda6a..903f916194 100644 --- a/include/xrpl/basics/safe_cast.h +++ b/include/xrpl/basics/safe_cast.h @@ -12,38 +12,29 @@ namespace xrpl { template concept SafeToCast = (std::is_integral_v && std::is_integral_v) && (std::is_signed::value || std::is_unsigned::value) && - (std::is_signed::value != std::is_signed::value - ? sizeof(Dest) > sizeof(Src) - : sizeof(Dest) >= sizeof(Src)); + (std::is_signed::value != std::is_signed::value ? sizeof(Dest) > sizeof(Src) + : sizeof(Dest) >= sizeof(Src)); template -inline constexpr std:: - enable_if_t && std::is_integral_v, Dest> - safe_cast(Src s) noexcept +inline constexpr std::enable_if_t && std::is_integral_v, Dest> +safe_cast(Src s) noexcept { - static_assert( - std::is_signed_v || std::is_unsigned_v, - "Cannot cast signed to unsigned"); - constexpr unsigned not_same = - std::is_signed_v != std::is_signed_v; - static_assert( - sizeof(Dest) >= sizeof(Src) + not_same, - "Destination is too small to hold all values of source"); + static_assert(std::is_signed_v || std::is_unsigned_v, "Cannot cast signed to unsigned"); + constexpr unsigned not_same = std::is_signed_v != std::is_signed_v; + static_assert(sizeof(Dest) >= sizeof(Src) + not_same, "Destination is too small to hold all values of source"); return static_cast(s); } template -inline constexpr std:: - enable_if_t && std::is_integral_v, Dest> - safe_cast(Src s) noexcept +inline constexpr std::enable_if_t && std::is_integral_v, Dest> +safe_cast(Src s) noexcept { return static_cast(safe_cast>(s)); } template -inline constexpr std:: - enable_if_t && std::is_enum_v, Dest> - safe_cast(Src s) noexcept +inline constexpr std::enable_if_t && std::is_enum_v, Dest> +safe_cast(Src s) noexcept { return safe_cast(static_cast>(s)); } @@ -53,9 +44,8 @@ inline constexpr std:: // underlying types become safe, it can be converted to a safe_cast. template -inline constexpr std:: - enable_if_t && std::is_integral_v, Dest> - unsafe_cast(Src s) noexcept +inline constexpr std::enable_if_t && std::is_integral_v, Dest> +unsafe_cast(Src s) noexcept { static_assert( !SafeToCast, @@ -65,17 +55,15 @@ inline constexpr std:: } template -inline constexpr std:: - enable_if_t && std::is_integral_v, Dest> - unsafe_cast(Src s) noexcept +inline constexpr std::enable_if_t && std::is_integral_v, Dest> +unsafe_cast(Src s) noexcept { return static_cast(unsafe_cast>(s)); } template -inline constexpr std:: - enable_if_t && std::is_enum_v, Dest> - unsafe_cast(Src s) noexcept +inline constexpr std::enable_if_t && std::is_enum_v, Dest> +unsafe_cast(Src s) noexcept { return unsafe_cast(static_cast>(s)); } diff --git a/include/xrpl/basics/scope.h b/include/xrpl/basics/scope.h index b7299a28fc..f0643c420c 100644 --- a/include/xrpl/basics/scope.h +++ b/include/xrpl/basics/scope.h @@ -36,10 +36,8 @@ public: } scope_exit(scope_exit&& rhs) noexcept( - std::is_nothrow_move_constructible_v || - std::is_nothrow_copy_constructible_v) - : exit_function_{std::forward(rhs.exit_function_)} - , execute_on_destruction_{rhs.execute_on_destruction_} + std::is_nothrow_move_constructible_v || std::is_nothrow_copy_constructible_v) + : exit_function_{std::forward(rhs.exit_function_)}, execute_on_destruction_{rhs.execute_on_destruction_} { rhs.release(); } @@ -50,14 +48,11 @@ public: template explicit scope_exit( EFP&& f, - std::enable_if_t< - !std::is_same_v, scope_exit> && - std::is_constructible_v>* = 0) noexcept + std::enable_if_t, scope_exit> && std::is_constructible_v>* = + 0) noexcept : exit_function_{std::forward(f)} { - static_assert( - std:: - is_nothrow_constructible_v(f))>); + static_assert(std::is_nothrow_constructible_v(f))>); } void @@ -80,14 +75,12 @@ class scope_fail public: ~scope_fail() { - if (execute_on_destruction_ && - std::uncaught_exceptions() > uncaught_on_creation_) + if (execute_on_destruction_ && std::uncaught_exceptions() > uncaught_on_creation_) exit_function_(); } scope_fail(scope_fail&& rhs) noexcept( - std::is_nothrow_move_constructible_v || - std::is_nothrow_copy_constructible_v) + std::is_nothrow_move_constructible_v || std::is_nothrow_copy_constructible_v) : exit_function_{std::forward(rhs.exit_function_)} , execute_on_destruction_{rhs.execute_on_destruction_} , uncaught_on_creation_{rhs.uncaught_on_creation_} @@ -101,14 +94,11 @@ public: template explicit scope_fail( EFP&& f, - std::enable_if_t< - !std::is_same_v, scope_fail> && - std::is_constructible_v>* = 0) noexcept + std::enable_if_t, scope_fail> && std::is_constructible_v>* = + 0) noexcept : exit_function_{std::forward(f)} { - static_assert( - std:: - is_nothrow_constructible_v(f))>); + static_assert(std::is_nothrow_constructible_v(f))>); } void @@ -131,14 +121,12 @@ class scope_success public: ~scope_success() noexcept(noexcept(exit_function_())) { - if (execute_on_destruction_ && - std::uncaught_exceptions() <= uncaught_on_creation_) + if (execute_on_destruction_ && std::uncaught_exceptions() <= uncaught_on_creation_) exit_function_(); } scope_success(scope_success&& rhs) noexcept( - std::is_nothrow_move_constructible_v || - std::is_nothrow_copy_constructible_v) + std::is_nothrow_move_constructible_v || std::is_nothrow_copy_constructible_v) : exit_function_{std::forward(rhs.exit_function_)} , execute_on_destruction_{rhs.execute_on_destruction_} , uncaught_on_creation_{rhs.uncaught_on_creation_} @@ -152,9 +140,7 @@ public: template explicit scope_success( EFP&& f, - std::enable_if_t< - !std::is_same_v, scope_success> && - std::is_constructible_v>* = + std::enable_if_t, scope_success> && std::is_constructible_v>* = 0) noexcept(std::is_nothrow_constructible_v || std::is_nothrow_constructible_v) : exit_function_{std::forward(f)} { @@ -213,12 +199,9 @@ class scope_unlock std::unique_lock* plock; public: - explicit scope_unlock(std::unique_lock& lock) noexcept(true) - : plock(&lock) + explicit scope_unlock(std::unique_lock& lock) noexcept(true) : plock(&lock) { - XRPL_ASSERT( - plock->owns_lock(), - "xrpl::scope_unlock::scope_unlock : mutex must be locked"); + XRPL_ASSERT(plock->owns_lock(), "xrpl::scope_unlock::scope_unlock : mutex must be locked"); plock->unlock(); } diff --git a/include/xrpl/basics/spinlock.h b/include/xrpl/basics/spinlock.h index 71ab29f381..f612aaf548 100644 --- a/include/xrpl/basics/spinlock.h +++ b/include/xrpl/basics/spinlock.h @@ -100,12 +100,9 @@ public: @note For performance reasons, you should strive to have `lock` be on a cacheline by itself. */ - packed_spinlock(std::atomic& lock, int index) - : bits_(lock), mask_(static_cast(1) << index) + packed_spinlock(std::atomic& lock, int index) : bits_(lock), mask_(static_cast(1) << index) { - XRPL_ASSERT( - index >= 0 && (mask_ != 0), - "xrpl::packed_spinlock::packed_spinlock : valid index and mask"); + XRPL_ASSERT(index >= 0 && (mask_ != 0), "xrpl::packed_spinlock::packed_spinlock : valid index and mask"); } [[nodiscard]] bool @@ -178,10 +175,7 @@ public: T expected = 0; return lock_.compare_exchange_weak( - expected, - std::numeric_limits::max(), - std::memory_order_acquire, - std::memory_order_relaxed); + expected, std::numeric_limits::max(), std::memory_order_acquire, std::memory_order_relaxed); } void diff --git a/include/xrpl/basics/strHex.h b/include/xrpl/basics/strHex.h index 1c1d94bf32..38b9a15668 100644 --- a/include/xrpl/basics/strHex.h +++ b/include/xrpl/basics/strHex.h @@ -11,9 +11,7 @@ std::string strHex(FwdIt begin, FwdIt end) { static_assert( - std::is_convertible< - typename std::iterator_traits::iterator_category, - std::forward_iterator_tag>::value, + std::is_convertible::iterator_category, std::forward_iterator_tag>::value, "FwdIt must be a forward iterator"); std::string result; result.reserve(2 * std::distance(begin, end)); diff --git a/include/xrpl/basics/tagged_integer.h b/include/xrpl/basics/tagged_integer.h index 1d40b31cce..a44daf1342 100644 --- a/include/xrpl/basics/tagged_integer.h +++ b/include/xrpl/basics/tagged_integer.h @@ -31,9 +31,7 @@ class tagged_integer tagged_integer, boost::bitwise< tagged_integer, - boost::unit_steppable< - tagged_integer, - boost::shiftable>>>>> + boost::unit_steppable, boost::shiftable>>>>> { private: Int m_value; @@ -46,14 +44,10 @@ public: template < class OtherInt, - class = typename std::enable_if< - std::is_integral::value && - sizeof(OtherInt) <= sizeof(Int)>::type> + class = typename std::enable_if::value && sizeof(OtherInt) <= sizeof(Int)>::type> explicit constexpr tagged_integer(OtherInt value) noexcept : m_value(value) { - static_assert( - sizeof(tagged_integer) == sizeof(Int), - "tagged_integer is adding padding"); + static_assert(sizeof(tagged_integer) == sizeof(Int), "tagged_integer is adding padding"); } bool diff --git a/include/xrpl/beast/asio/io_latency_probe.h b/include/xrpl/beast/asio/io_latency_probe.h index 726e8e1c76..8ee4fdb89a 100644 --- a/include/xrpl/beast/asio/io_latency_probe.h +++ b/include/xrpl/beast/asio/io_latency_probe.h @@ -32,11 +32,7 @@ private: public: io_latency_probe(duration const& period, boost::asio::io_context& ios) - : m_count(1) - , m_period(period) - , m_ios(ios) - , m_timer(m_ios) - , m_cancel(false) + : m_count(1), m_period(period), m_ios(ios), m_timer(m_ios), m_cancel(false) { } @@ -91,10 +87,7 @@ public: std::lock_guard lock(m_mutex); if (m_cancel) throw std::logic_error("io_latency_probe is canceled"); - boost::asio::post( - m_ios, - sample_op( - std::forward(handler), Clock::now(), false, this)); + boost::asio::post(m_ios, sample_op(std::forward(handler), Clock::now(), false, this)); } /** Initiate continuous i/o latency sampling. @@ -108,10 +101,7 @@ public: std::lock_guard lock(m_mutex); if (m_cancel) throw std::logic_error("io_latency_probe is canceled"); - boost::asio::post( - m_ios, - sample_op( - std::forward(handler), Clock::now(), true, this)); + boost::asio::post(m_ios, sample_op(std::forward(handler), Clock::now(), true, this)); } private: @@ -151,15 +141,8 @@ private: bool m_repeat; io_latency_probe* m_probe; - sample_op( - Handler const& handler, - time_point const& start, - bool repeat, - io_latency_probe* probe) - : m_handler(handler) - , m_start(start) - , m_repeat(repeat) - , m_probe(probe) + sample_op(Handler const& handler, time_point const& start, bool repeat, io_latency_probe* probe) + : m_handler(handler), m_start(start), m_repeat(repeat), m_probe(probe) { XRPL_ASSERT( m_probe, @@ -214,23 +197,19 @@ private: // Calculate when we want to sample again, and // adjust for the expected latency. // - typename Clock::time_point const when( - now + m_probe->m_period - 2 * elapsed); + typename Clock::time_point const when(now + m_probe->m_period - 2 * elapsed); if (when <= now) { // The latency is too high to maintain the desired // period so don't bother with a timer. // - boost::asio::post( - m_probe->m_ios, - sample_op(m_handler, now, m_repeat, m_probe)); + boost::asio::post(m_probe->m_ios, sample_op(m_handler, now, m_repeat, m_probe)); } else { m_probe->m_timer.expires_after(when - now); - m_probe->m_timer.async_wait( - sample_op(m_handler, now, m_repeat, m_probe)); + m_probe->m_timer.async_wait(sample_op(m_handler, now, m_repeat, m_probe)); } } } @@ -241,9 +220,7 @@ private: if (!m_probe) return; typename Clock::time_point const now(Clock::now()); - boost::asio::post( - m_probe->m_ios, - sample_op(m_handler, now, m_repeat, m_probe)); + boost::asio::post(m_probe->m_ios, sample_op(m_handler, now, m_repeat, m_probe)); } }; }; diff --git a/include/xrpl/beast/clock/manual_clock.h b/include/xrpl/beast/clock/manual_clock.h index b3c98846f1..975656cf63 100644 --- a/include/xrpl/beast/clock/manual_clock.h +++ b/include/xrpl/beast/clock/manual_clock.h @@ -29,8 +29,7 @@ private: time_point now_; public: - explicit manual_clock(time_point const& now = time_point(duration(0))) - : now_(now) + explicit manual_clock(time_point const& now = time_point(duration(0))) : now_(now) { } @@ -44,9 +43,7 @@ public: void set(time_point const& when) { - XRPL_ASSERT( - !Clock::is_steady || when >= now_, - "beast::manual_clock::set(time_point) : forward input"); + XRPL_ASSERT(!Clock::is_steady || when >= now_, "beast::manual_clock::set(time_point) : forward input"); now_ = when; } @@ -64,8 +61,7 @@ public: advance(std::chrono::duration const& elapsed) { XRPL_ASSERT( - !Clock::is_steady || (now_ + elapsed) >= now_, - "beast::manual_clock::advance(duration) : forward input"); + !Clock::is_steady || (now_ + elapsed) >= now_, "beast::manual_clock::advance(duration) : forward input"); now_ += elapsed; } diff --git a/include/xrpl/beast/container/aged_container_utility.h b/include/xrpl/beast/container/aged_container_utility.h index cc1b3a8479..8847fcb321 100644 --- a/include/xrpl/beast/container/aged_container_utility.h +++ b/include/xrpl/beast/container/aged_container_utility.h @@ -10,14 +10,12 @@ namespace beast { /** Expire aged container items past the specified age. */ template -typename std::enable_if::value, std::size_t>:: - type - expire(AgedContainer& c, std::chrono::duration const& age) +typename std::enable_if::value, std::size_t>::type +expire(AgedContainer& c, std::chrono::duration const& age) { std::size_t n(0); auto const expired(c.clock().now() - age); - for (auto iter(c.chronological.cbegin()); - iter != c.chronological.cend() && iter.when() <= expired;) + for (auto iter(c.chronological.cbegin()); iter != c.chronological.cend() && iter.when() <= expired;) { iter = c.erase(iter); ++n; diff --git a/include/xrpl/beast/container/aged_map.h b/include/xrpl/beast/container/aged_map.h index 5f07f67260..f3bc59943d 100644 --- a/include/xrpl/beast/container/aged_map.h +++ b/include/xrpl/beast/container/aged_map.h @@ -15,8 +15,7 @@ template < class Clock = std::chrono::steady_clock, class Compare = std::less, class Allocator = std::allocator>> -using aged_map = detail:: - aged_ordered_container; +using aged_map = detail::aged_ordered_container; } diff --git a/include/xrpl/beast/container/aged_multimap.h b/include/xrpl/beast/container/aged_multimap.h index e0fa8abe97..3602996602 100644 --- a/include/xrpl/beast/container/aged_multimap.h +++ b/include/xrpl/beast/container/aged_multimap.h @@ -15,8 +15,7 @@ template < class Clock = std::chrono::steady_clock, class Compare = std::less, class Allocator = std::allocator>> -using aged_multimap = detail:: - aged_ordered_container; +using aged_multimap = detail::aged_ordered_container; } diff --git a/include/xrpl/beast/container/aged_multiset.h b/include/xrpl/beast/container/aged_multiset.h index 222bed71c4..851dd8fa6e 100644 --- a/include/xrpl/beast/container/aged_multiset.h +++ b/include/xrpl/beast/container/aged_multiset.h @@ -14,8 +14,7 @@ template < class Clock = std::chrono::steady_clock, class Compare = std::less, class Allocator = std::allocator> -using aged_multiset = detail:: - aged_ordered_container; +using aged_multiset = detail::aged_ordered_container; } diff --git a/include/xrpl/beast/container/aged_set.h b/include/xrpl/beast/container/aged_set.h index cd792c9e84..99b2c58bf6 100644 --- a/include/xrpl/beast/container/aged_set.h +++ b/include/xrpl/beast/container/aged_set.h @@ -14,8 +14,7 @@ template < class Clock = std::chrono::steady_clock, class Compare = std::less, class Allocator = std::allocator> -using aged_set = detail:: - aged_ordered_container; +using aged_set = detail::aged_ordered_container; } diff --git a/include/xrpl/beast/container/aged_unordered_map.h b/include/xrpl/beast/container/aged_unordered_map.h index 4434e858da..26e41534d3 100644 --- a/include/xrpl/beast/container/aged_unordered_map.h +++ b/include/xrpl/beast/container/aged_unordered_map.h @@ -16,15 +16,7 @@ template < class Hash = std::hash, class KeyEqual = std::equal_to, class Allocator = std::allocator>> -using aged_unordered_map = detail::aged_unordered_container< - false, - true, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>; +using aged_unordered_map = detail::aged_unordered_container; } diff --git a/include/xrpl/beast/container/aged_unordered_multimap.h b/include/xrpl/beast/container/aged_unordered_multimap.h index 9c903d7865..3202aef27d 100644 --- a/include/xrpl/beast/container/aged_unordered_multimap.h +++ b/include/xrpl/beast/container/aged_unordered_multimap.h @@ -16,15 +16,7 @@ template < class Hash = std::hash, class KeyEqual = std::equal_to, class Allocator = std::allocator>> -using aged_unordered_multimap = detail::aged_unordered_container< - true, - true, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>; +using aged_unordered_multimap = detail::aged_unordered_container; } diff --git a/include/xrpl/beast/container/aged_unordered_multiset.h b/include/xrpl/beast/container/aged_unordered_multiset.h index 04f64f7032..b42cad6a2f 100644 --- a/include/xrpl/beast/container/aged_unordered_multiset.h +++ b/include/xrpl/beast/container/aged_unordered_multiset.h @@ -15,15 +15,8 @@ template < class Hash = std::hash, class KeyEqual = std::equal_to, class Allocator = std::allocator> -using aged_unordered_multiset = detail::aged_unordered_container< - true, - false, - Key, - void, - Clock, - Hash, - KeyEqual, - Allocator>; +using aged_unordered_multiset = + detail::aged_unordered_container; } diff --git a/include/xrpl/beast/container/aged_unordered_set.h b/include/xrpl/beast/container/aged_unordered_set.h index e0373cc0d8..d095408849 100644 --- a/include/xrpl/beast/container/aged_unordered_set.h +++ b/include/xrpl/beast/container/aged_unordered_set.h @@ -15,15 +15,7 @@ template < class Hash = std::hash, class KeyEqual = std::equal_to, class Allocator = std::allocator> -using aged_unordered_set = detail::aged_unordered_container< - false, - false, - Key, - void, - Clock, - Hash, - KeyEqual, - Allocator>; +using aged_unordered_set = detail::aged_unordered_container; } diff --git a/include/xrpl/beast/container/detail/aged_container_iterator.h b/include/xrpl/beast/container/detail/aged_container_iterator.h index 1e302cfc2c..5cee583d74 100644 --- a/include/xrpl/beast/container/detail/aged_container_iterator.h +++ b/include/xrpl/beast/container/detail/aged_container_iterator.h @@ -16,14 +16,12 @@ template class aged_container_iterator { public: - using iterator_category = - typename std::iterator_traits::iterator_category; + using iterator_category = typename std::iterator_traits::iterator_category; using value_type = typename std::conditional< is_const, typename Iterator::value_type::stashed::value_type const, typename Iterator::value_type::stashed::value_type>::type; - using difference_type = - typename std::iterator_traits::difference_type; + using difference_type = typename std::iterator_traits::difference_type; using pointer = value_type*; using reference = value_type&; using time_point = typename Iterator::value_type::stashed::time_point; @@ -38,31 +36,22 @@ public: class = typename std::enable_if< (other_is_const == false || is_const == true) && std::is_same::value == false>::type> - explicit aged_container_iterator( - aged_container_iterator const& other) + explicit aged_container_iterator(aged_container_iterator const& other) : m_iter(other.m_iter) { } // Disable constructing a const_iterator from a non-const_iterator. - template < - bool other_is_const, - class = typename std::enable_if< - other_is_const == false || is_const == true>::type> - aged_container_iterator( - aged_container_iterator const& other) - : m_iter(other.m_iter) + template ::type> + aged_container_iterator(aged_container_iterator const& other) : m_iter(other.m_iter) { } // Disable assigning a const_iterator to a non-const iterator template auto - operator=( - aged_container_iterator const& other) -> - typename std::enable_if< - other_is_const == false || is_const == true, - aged_container_iterator&>::type + operator=(aged_container_iterator const& other) -> + typename std::enable_if::type { m_iter = other.m_iter; return *this; @@ -70,16 +59,14 @@ public: template bool - operator==(aged_container_iterator const& - other) const + operator==(aged_container_iterator const& other) const { return m_iter == other.m_iter; } template bool - operator!=(aged_container_iterator const& - other) const + operator!=(aged_container_iterator const& other) const { return m_iter != other.m_iter; } diff --git a/include/xrpl/beast/container/detail/aged_ordered_container.h b/include/xrpl/beast/container/detail/aged_ordered_container.h index e9bac2879c..d4ba81f0b8 100644 --- a/include/xrpl/beast/container/detail/aged_ordered_container.h +++ b/include/xrpl/beast/container/detail/aged_ordered_container.h @@ -30,8 +30,7 @@ struct is_boost_reverse_iterator : std::false_type }; template -struct is_boost_reverse_iterator> - : std::true_type +struct is_boost_reverse_iterator> : std::true_type { explicit is_boost_reverse_iterator() = default; }; @@ -59,8 +58,7 @@ template < class T, class Clock = std::chrono::steady_clock, class Compare = std::less, - class Allocator = std::allocator< - typename std::conditional, Key>::type>> + class Allocator = std::allocator, Key>::type>> class aged_ordered_container { public: @@ -69,8 +67,7 @@ public: using duration = typename clock_type::duration; using key_type = Key; using mapped_type = T; - using value_type = - typename std::conditional, Key>::type; + using value_type = typename std::conditional, Key>::type; using size_type = std::size_t; using difference_type = std::ptrdiff_t; @@ -87,11 +84,8 @@ private: } // VFALCO TODO hoist to remove template argument dependencies - struct element - : boost::intrusive::set_base_hook< - boost::intrusive::link_mode>, - boost::intrusive::list_base_hook< - boost::intrusive::link_mode> + struct element : boost::intrusive::set_base_hook>, + boost::intrusive::list_base_hook> { // Stash types here so the iterator doesn't // need to see the container declaration. @@ -103,22 +97,18 @@ private: using time_point = typename aged_ordered_container::time_point; }; - element(time_point const& when_, value_type const& value_) - : value(value_), when(when_) + element(time_point const& when_, value_type const& value_) : value(value_), when(when_) { } - element(time_point const& when_, value_type&& value_) - : value(std::move(value_)), when(when_) + element(time_point const& when_, value_type&& value_) : value(std::move(value_)), when(when_) { } template < class... Args, - class = typename std::enable_if< - std::is_constructible::value>::type> - element(time_point const& when_, Args&&... args) - : value(std::forward(args)...), when(when_) + class = typename std::enable_if::value>::type> + element(time_point const& when_, Args&&... args) : value(std::forward(args)...), when(when_) { } @@ -202,8 +192,7 @@ private: } }; - using list_type = typename boost::intrusive:: - make_list>::type; + using list_type = typename boost::intrusive::make_list>::type; using cont_type = typename std::conditional< IsMulti, @@ -211,51 +200,39 @@ private: element, boost::intrusive::constant_time_size, boost::intrusive::compare>::type, - typename boost::intrusive::make_set< - element, - boost::intrusive::constant_time_size, - boost::intrusive::compare>::type>::type; + typename boost::intrusive:: + make_set, boost::intrusive::compare>:: + type>::type; - using ElementAllocator = typename std::allocator_traits< - Allocator>::template rebind_alloc; + using ElementAllocator = typename std::allocator_traits::template rebind_alloc; using ElementAllocatorTraits = std::allocator_traits; - class config_t - : private KeyValueCompare, - public beast::detail::empty_base_optimization + class config_t : private KeyValueCompare, public beast::detail::empty_base_optimization { public: explicit config_t(clock_type& clock_) : clock(clock_) { } - config_t(clock_type& clock_, Compare const& comp) - : KeyValueCompare(comp), clock(clock_) + config_t(clock_type& clock_, Compare const& comp) : KeyValueCompare(comp), clock(clock_) { } config_t(clock_type& clock_, Allocator const& alloc_) - : beast::detail::empty_base_optimization(alloc_) - , clock(clock_) + : beast::detail::empty_base_optimization(alloc_), clock(clock_) { } - config_t( - clock_type& clock_, - Compare const& comp, - Allocator const& alloc_) - : KeyValueCompare(comp) - , beast::detail::empty_base_optimization(alloc_) - , clock(clock_) + config_t(clock_type& clock_, Compare const& comp, Allocator const& alloc_) + : KeyValueCompare(comp), beast::detail::empty_base_optimization(alloc_), clock(clock_) { } config_t(config_t const& other) : KeyValueCompare(other.key_compare()) , beast::detail::empty_base_optimization( - ElementAllocatorTraits::select_on_container_copy_construction( - other.alloc())) + ElementAllocatorTraits::select_on_container_copy_construction(other.alloc())) , clock(other.clock) { } @@ -269,8 +246,7 @@ private: config_t(config_t&& other) : KeyValueCompare(std::move(other.key_compare())) - , beast::detail::empty_base_optimization( - std::move(other)) + , beast::detail::empty_base_optimization(std::move(other)) , clock(other.clock) { } @@ -330,15 +306,13 @@ private: ElementAllocator& alloc() { - return beast::detail::empty_base_optimization< - ElementAllocator>::member(); + return beast::detail::empty_base_optimization::member(); } ElementAllocator const& alloc() const { - return beast::detail::empty_base_optimization< - ElementAllocator>::member(); + return beast::detail::empty_base_optimization::member(); } std::reference_wrapper clock; @@ -363,13 +337,8 @@ private: }; std::unique_ptr p( - ElementAllocatorTraits::allocate(m_config.alloc(), 1), - Deleter(m_config.alloc())); - ElementAllocatorTraits::construct( - m_config.alloc(), - p.get(), - clock().now(), - std::forward(args)...); + ElementAllocatorTraits::allocate(m_config.alloc(), 1), Deleter(m_config.alloc())); + ElementAllocatorTraits::construct(m_config.alloc(), p.get(), clock().now(), std::forward(args)...); return p.release(); } @@ -377,8 +346,7 @@ private: delete_element(element const* p) { ElementAllocatorTraits::destroy(m_config.alloc(), p); - ElementAllocatorTraits::deallocate( - m_config.alloc(), const_cast(p), 1); + ElementAllocatorTraits::deallocate(m_config.alloc(), const_cast(p), 1); } void @@ -391,25 +359,19 @@ private: public: using key_compare = Compare; - using value_compare = - typename std::conditional::type; + using value_compare = typename std::conditional::type; using allocator_type = Allocator; using reference = value_type&; using const_reference = value_type const&; using pointer = typename std::allocator_traits::pointer; - using const_pointer = - typename std::allocator_traits::const_pointer; + using const_pointer = typename std::allocator_traits::const_pointer; // A set iterator (IsMap==false) is always const // because the elements of a set are immutable. - using iterator = beast::detail:: - aged_container_iterator; - using const_iterator = beast::detail:: - aged_container_iterator; - using reverse_iterator = beast::detail:: - aged_container_iterator; - using const_reverse_iterator = beast::detail:: - aged_container_iterator; + using iterator = beast::detail::aged_container_iterator; + using const_iterator = beast::detail::aged_container_iterator; + using reverse_iterator = beast::detail::aged_container_iterator; + using const_reverse_iterator = beast::detail::aged_container_iterator; //-------------------------------------------------------------------------- // @@ -425,15 +387,11 @@ public: public: // A set iterator (IsMap==false) is always const // because the elements of a set are immutable. - using iterator = beast::detail:: - aged_container_iterator; - using const_iterator = beast::detail:: - aged_container_iterator; - using reverse_iterator = beast::detail::aged_container_iterator< - !IsMap, - typename list_type::reverse_iterator>; - using const_reverse_iterator = beast::detail:: - aged_container_iterator; + using iterator = beast::detail::aged_container_iterator; + using const_iterator = beast::detail::aged_container_iterator; + using reverse_iterator = beast::detail::aged_container_iterator; + using const_reverse_iterator = + beast::detail::aged_container_iterator; iterator begin() @@ -510,23 +468,17 @@ public: iterator iterator_to(value_type& value) { - static_assert( - std::is_standard_layout::value, - "must be standard layout"); + static_assert(std::is_standard_layout::value, "must be standard layout"); return list.iterator_to(*reinterpret_cast( - reinterpret_cast(&value) - - ((std::size_t)std::addressof(((element*)0)->member)))); + reinterpret_cast(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); } const_iterator iterator_to(value_type const& value) const { - static_assert( - std::is_standard_layout::value, - "must be standard layout"); + static_assert(std::is_standard_layout::value, "must be standard layout"); return list.iterator_to(*reinterpret_cast( - reinterpret_cast(&value) - - ((std::size_t)std::addressof(((element*)0)->member)))); + reinterpret_cast(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); } private: @@ -555,61 +507,33 @@ public: aged_ordered_container(clock_type& clock, Allocator const& alloc); - aged_ordered_container( - clock_type& clock, - Compare const& comp, - Allocator const& alloc); + aged_ordered_container(clock_type& clock, Compare const& comp, Allocator const& alloc); template aged_ordered_container(InputIt first, InputIt last, clock_type& clock); template - aged_ordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Compare const& comp); + aged_ordered_container(InputIt first, InputIt last, clock_type& clock, Compare const& comp); template - aged_ordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Allocator const& alloc); + aged_ordered_container(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc); template - aged_ordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Compare const& comp, - Allocator const& alloc); + aged_ordered_container(InputIt first, InputIt last, clock_type& clock, Compare const& comp, Allocator const& alloc); aged_ordered_container(aged_ordered_container const& other); - aged_ordered_container( - aged_ordered_container const& other, - Allocator const& alloc); + aged_ordered_container(aged_ordered_container const& other, Allocator const& alloc); aged_ordered_container(aged_ordered_container&& other); - aged_ordered_container( - aged_ordered_container&& other, - Allocator const& alloc); + aged_ordered_container(aged_ordered_container&& other, Allocator const& alloc); - aged_ordered_container( - std::initializer_list init, - clock_type& clock); + aged_ordered_container(std::initializer_list init, clock_type& clock); - aged_ordered_container( - std::initializer_list init, - clock_type& clock, - Compare const& comp); + aged_ordered_container(std::initializer_list init, clock_type& clock, Compare const& comp); - aged_ordered_container( - std::initializer_list init, - clock_type& clock, - Allocator const& alloc); + aged_ordered_container(std::initializer_list init, clock_type& clock, Allocator const& alloc); aged_ordered_container( std::initializer_list init, @@ -763,21 +687,17 @@ public: iterator iterator_to(value_type& value) { - static_assert( - std::is_standard_layout::value, "must be standard layout"); + static_assert(std::is_standard_layout::value, "must be standard layout"); return m_cont.iterator_to(*reinterpret_cast( - reinterpret_cast(&value) - - ((std::size_t)std::addressof(((element*)0)->member)))); + reinterpret_cast(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); } const_iterator iterator_to(value_type const& value) const { - static_assert( - std::is_standard_layout::value, "must be standard layout"); + static_assert(std::is_standard_layout::value, "must be standard layout"); return m_cont.iterator_to(*reinterpret_cast( - reinterpret_cast(&value) - - ((std::size_t)std::addressof(((element*)0)->member)))); + reinterpret_cast(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); } //-------------------------------------------------------------------------- @@ -816,35 +736,29 @@ public: // map, set template auto - insert(value_type const& value) -> - typename std::enable_if>::type; + insert(value_type const& value) -> typename std::enable_if>::type; // multimap, multiset template auto - insert(value_type const& value) -> - typename std::enable_if::type; + insert(value_type const& value) -> typename std::enable_if::type; // set template auto - insert(value_type&& value) -> typename std::enable_if< - !maybe_multi && !maybe_map, - std::pair>::type; + insert(value_type&& value) -> typename std::enable_if>::type; // multiset template auto - insert(value_type&& value) -> - typename std::enable_if::type; + insert(value_type&& value) -> typename std::enable_if::type; //--- // map, set template auto - insert(const_iterator hint, value_type const& value) -> - typename std::enable_if::type; + insert(const_iterator hint, value_type const& value) -> typename std::enable_if::type; // multimap, multiset template @@ -858,8 +772,7 @@ public: // map, set template auto - insert(const_iterator hint, value_type&& value) -> - typename std::enable_if::type; + insert(const_iterator hint, value_type&& value) -> typename std::enable_if::type; // multimap, multiset template @@ -874,10 +787,8 @@ public: template typename std::enable_if< maybe_map && std::is_constructible::value, - typename std:: - conditional>::type>:: - type - insert(P&& value) + typename std::conditional>::type>::type + insert(P&& value) { return emplace(std::forward

(value)); } @@ -886,10 +797,8 @@ public: template typename std::enable_if< maybe_map && std::is_constructible::value, - typename std:: - conditional>::type>:: - type - insert(const_iterator hint, P&& value) + typename std::conditional>::type>::type + insert(const_iterator hint, P&& value) { return emplace_hint(hint, std::forward

(value)); } @@ -911,14 +820,12 @@ public: // map, set template auto - emplace(Args&&... args) -> - typename std::enable_if>::type; + emplace(Args&&... args) -> typename std::enable_if>::type; // multiset, multimap template auto - emplace(Args&&... args) -> - typename std::enable_if::type; + emplace(Args&&... args) -> typename std::enable_if::type; // map, set template @@ -936,19 +843,13 @@ public: } // enable_if prevents erase (reverse_iterator pos) from compiling - template < - bool is_const, - class Iterator, - class = std::enable_if_t::value>> + template ::value>> beast::detail::aged_container_iterator erase(beast::detail::aged_container_iterator pos); // enable_if prevents erase (reverse_iterator first, reverse_iterator last) // from compiling - template < - bool is_const, - class Iterator, - class = std::enable_if_t::value>> + template ::value>> beast::detail::aged_container_iterator erase( beast::detail::aged_container_iterator first, @@ -964,10 +865,7 @@ public: //-------------------------------------------------------------------------- // enable_if prevents touch (reverse_iterator pos) from compiling - template < - bool is_const, - class Iterator, - class = std::enable_if_t::value>> + template ::value>> void touch(beast::detail::aged_container_iterator pos) { @@ -1005,8 +903,7 @@ public: const_iterator find(K const& k) const { - return const_iterator( - m_cont.find(k, std::cref(m_config.key_compare()))); + return const_iterator(m_cont.find(k, std::cref(m_config.key_compare()))); } // VFALCO TODO Respect is_transparent (c++14) @@ -1024,8 +921,7 @@ public: equal_range(K const& k) const { auto const r(m_cont.equal_range(k, std::cref(m_config.key_compare()))); - return std::make_pair( - const_iterator(r.first), const_iterator(r.second)); + return std::make_pair(const_iterator(r.first), const_iterator(r.second)); } // VFALCO TODO Respect is_transparent (c++14) @@ -1033,8 +929,7 @@ public: iterator lower_bound(K const& k) { - return iterator( - m_cont.lower_bound(k, std::cref(m_config.key_compare()))); + return iterator(m_cont.lower_bound(k, std::cref(m_config.key_compare()))); } // VFALCO TODO Respect is_transparent (c++14) @@ -1042,8 +937,7 @@ public: const_iterator lower_bound(K const& k) const { - return const_iterator( - m_cont.lower_bound(k, std::cref(m_config.key_compare()))); + return const_iterator(m_cont.lower_bound(k, std::cref(m_config.key_compare()))); } // VFALCO TODO Respect is_transparent (c++14) @@ -1051,8 +945,7 @@ public: iterator upper_bound(K const& k) { - return iterator( - m_cont.upper_bound(k, std::cref(m_config.key_compare()))); + return iterator(m_cont.upper_bound(k, std::cref(m_config.key_compare()))); } // VFALCO TODO Respect is_transparent (c++14) @@ -1060,8 +953,7 @@ public: const_iterator upper_bound(K const& k) const { - return const_iterator( - m_cont.upper_bound(k, std::cref(m_config.key_compare()))); + return const_iterator(m_cont.upper_bound(k, std::cref(m_config.key_compare()))); } //-------------------------------------------------------------------------- @@ -1093,139 +985,69 @@ public: // is only done on the key portion of the value type, ignoring // the mapped type. // - template < - bool OtherIsMulti, - bool OtherIsMap, - class OtherT, - class OtherDuration, - class OtherAllocator> + template bool - operator==(aged_ordered_container< - OtherIsMulti, - OtherIsMap, - Key, - OtherT, - OtherDuration, - Compare, - OtherAllocator> const& other) const; + operator==( + aged_ordered_container const& + other) const; - template < - bool OtherIsMulti, - bool OtherIsMap, - class OtherT, - class OtherDuration, - class OtherAllocator> + template bool - operator!=(aged_ordered_container< - OtherIsMulti, - OtherIsMap, - Key, - OtherT, - OtherDuration, - Compare, - OtherAllocator> const& other) const + operator!=( + aged_ordered_container const& + other) const { return !(this->operator==(other)); } - template < - bool OtherIsMulti, - bool OtherIsMap, - class OtherT, - class OtherDuration, - class OtherAllocator> + template bool - operator<(aged_ordered_container< - OtherIsMulti, - OtherIsMap, - Key, - OtherT, - OtherDuration, - Compare, - OtherAllocator> const& other) const + operator<( + aged_ordered_container const& + other) const { value_compare const comp(value_comp()); - return std::lexicographical_compare( - cbegin(), cend(), other.cbegin(), other.cend(), comp); + return std::lexicographical_compare(cbegin(), cend(), other.cbegin(), other.cend(), comp); } - template < - bool OtherIsMulti, - bool OtherIsMap, - class OtherT, - class OtherDuration, - class OtherAllocator> + template bool - operator<=(aged_ordered_container< - OtherIsMulti, - OtherIsMap, - Key, - OtherT, - OtherDuration, - Compare, - OtherAllocator> const& other) const + operator<=( + aged_ordered_container const& + other) const { return !(other < *this); } - template < - bool OtherIsMulti, - bool OtherIsMap, - class OtherT, - class OtherDuration, - class OtherAllocator> + template bool - operator>(aged_ordered_container< - OtherIsMulti, - OtherIsMap, - Key, - OtherT, - OtherDuration, - Compare, - OtherAllocator> const& other) const + operator>( + aged_ordered_container const& + other) const { return other < *this; } - template < - bool OtherIsMulti, - bool OtherIsMap, - class OtherT, - class OtherDuration, - class OtherAllocator> + template bool - operator>=(aged_ordered_container< - OtherIsMulti, - OtherIsMap, - Key, - OtherT, - OtherDuration, - Compare, - OtherAllocator> const& other) const + operator>=( + aged_ordered_container const& + other) const { return !(*this < other); } private: // enable_if prevents erase (reverse_iterator pos, now) from compiling - template < - bool is_const, - class Iterator, - class = std::enable_if_t::value>> + template ::value>> void - touch( - beast::detail::aged_container_iterator pos, - typename clock_type::time_point const& now); + touch(beast::detail::aged_container_iterator pos, typename clock_type::time_point const& now); - template < - bool maybe_propagate = std::allocator_traits< - Allocator>::propagate_on_container_swap::value> + template ::propagate_on_container_swap::value> typename std::enable_if::type swap_data(aged_ordered_container& other) noexcept; - template < - bool maybe_propagate = std::allocator_traits< - Allocator>::propagate_on_container_swap::value> + template ::propagate_on_container_swap::value> typename std::enable_if::type swap_data(aged_ordered_container& other) noexcept; @@ -1236,152 +1058,88 @@ private: //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container(clock_type& clock) +template +aged_ordered_container::aged_ordered_container(clock_type& clock) : m_config(clock) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container(clock_type& clock, Compare const& comp) +template +aged_ordered_container::aged_ordered_container( + clock_type& clock, + Compare const& comp) : m_config(clock, comp), m_cont(comp) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container(clock_type& clock, Allocator const& alloc) +template +aged_ordered_container::aged_ordered_container( + clock_type& clock, + Allocator const& alloc) : m_config(clock, alloc) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container( - clock_type& clock, - Compare const& comp, - Allocator const& alloc) +template +aged_ordered_container::aged_ordered_container( + clock_type& clock, + Compare const& comp, + Allocator const& alloc) : m_config(clock, comp, alloc), m_cont(comp) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template -aged_ordered_container:: - aged_ordered_container(InputIt first, InputIt last, clock_type& clock) +aged_ordered_container::aged_ordered_container( + InputIt first, + InputIt last, + clock_type& clock) : m_config(clock) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template -aged_ordered_container:: - aged_ordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Compare const& comp) +aged_ordered_container::aged_ordered_container( + InputIt first, + InputIt last, + clock_type& clock, + Compare const& comp) : m_config(clock, comp), m_cont(comp) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template -aged_ordered_container:: - aged_ordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Allocator const& alloc) +aged_ordered_container::aged_ordered_container( + InputIt first, + InputIt last, + clock_type& clock, + Allocator const& alloc) : m_config(clock, alloc) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template -aged_ordered_container:: - aged_ordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Compare const& comp, - Allocator const& alloc) +aged_ordered_container::aged_ordered_container( + InputIt first, + InputIt last, + clock_type& clock, + Compare const& comp, + Allocator const& alloc) : m_config(clock, comp, alloc), m_cont(comp) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container(aged_ordered_container const& other) +template +aged_ordered_container::aged_ordered_container( + aged_ordered_container const& other) : m_config(other.m_config) #if BOOST_VERSION >= 108000 , m_cont(other.m_cont.get_comp()) @@ -1392,18 +1150,10 @@ aged_ordered_container:: insert(other.cbegin(), other.cend()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container( - aged_ordered_container const& other, - Allocator const& alloc) +template +aged_ordered_container::aged_ordered_container( + aged_ordered_container const& other, + Allocator const& alloc) : m_config(other.m_config, alloc) #if BOOST_VERSION >= 108000 , m_cont(other.m_cont.get_comp()) @@ -1414,33 +1164,18 @@ aged_ordered_container:: insert(other.cbegin(), other.cend()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container(aged_ordered_container&& other) +template +aged_ordered_container::aged_ordered_container( + aged_ordered_container&& other) : m_config(std::move(other.m_config)), m_cont(std::move(other.m_cont)) { chronological.list = std::move(other.chronological.list); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container( - aged_ordered_container&& other, - Allocator const& alloc) +template +aged_ordered_container::aged_ordered_container( + aged_ordered_container&& other, + Allocator const& alloc) : m_config(std::move(other.m_config), alloc) #if BOOST_VERSION >= 108000 , m_cont(std::move(other.m_cont.get_comp())) @@ -1453,103 +1188,56 @@ aged_ordered_container:: other.clear(); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container( - std::initializer_list init, - clock_type& clock) +template +aged_ordered_container::aged_ordered_container( + std::initializer_list init, + clock_type& clock) : m_config(clock) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container( - std::initializer_list init, - clock_type& clock, - Compare const& comp) +template +aged_ordered_container::aged_ordered_container( + std::initializer_list init, + clock_type& clock, + Compare const& comp) : m_config(clock, comp), m_cont(comp) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container( - std::initializer_list init, - clock_type& clock, - Allocator const& alloc) +template +aged_ordered_container::aged_ordered_container( + std::initializer_list init, + clock_type& clock, + Allocator const& alloc) : m_config(clock, alloc) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - aged_ordered_container( - std::initializer_list init, - clock_type& clock, - Compare const& comp, - Allocator const& alloc) +template +aged_ordered_container::aged_ordered_container( + std::initializer_list init, + clock_type& clock, + Compare const& comp, + Allocator const& alloc) : m_config(clock, comp, alloc), m_cont(comp) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -aged_ordered_container:: - ~aged_ordered_container() +template +aged_ordered_container::~aged_ordered_container() { clear(); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template auto -aged_ordered_container:: -operator=(aged_ordered_container const& other) -> aged_ordered_container& +aged_ordered_container::operator=( + aged_ordered_container const& other) -> aged_ordered_container& { if (this != &other) { @@ -1560,17 +1248,10 @@ operator=(aged_ordered_container const& other) -> aged_ordered_container& return *this; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template auto -aged_ordered_container:: -operator=(aged_ordered_container&& other) -> aged_ordered_container& +aged_ordered_container::operator=(aged_ordered_container&& other) + -> aged_ordered_container& { clear(); this->m_config = std::move(other.m_config); @@ -1579,17 +1260,10 @@ operator=(aged_ordered_container&& other) -> aged_ordered_container& return *this; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template auto -aged_ordered_container:: -operator=(std::initializer_list init) -> aged_ordered_container& +aged_ordered_container::operator=( + std::initializer_list init) -> aged_ordered_container& { clear(); insert(init); @@ -1598,18 +1272,10 @@ operator=(std::initializer_list init) -> aged_ordered_container& //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template typename std::conditional::type& -aged_ordered_container::at( - K const& k) +aged_ordered_container::at(K const& k) { auto const iter(m_cont.find(k, std::cref(m_config.key_compare()))); if (iter == m_cont.end()) @@ -1617,18 +1283,10 @@ aged_ordered_container::at( return iter->value.second; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template typename std::conditional::type const& -aged_ordered_container::at( - K const& k) const +aged_ordered_container::at(K const& k) const { auto const iter(m_cont.find(k, std::cref(m_config.key_compare()))); if (iter == m_cont.end()) @@ -1636,28 +1294,16 @@ aged_ordered_container::at( return iter->value.second; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template typename std::conditional::type& -aged_ordered_container:: -operator[](Key const& key) +aged_ordered_container::operator[](Key const& key) { typename cont_type::insert_commit_data d; - auto const result( - m_cont.insert_check(key, std::cref(m_config.key_compare()), d)); + auto const result(m_cont.insert_check(key, std::cref(m_config.key_compare()), d)); if (result.second) { - element* const p(new_element( - std::piecewise_construct, - std::forward_as_tuple(key), - std::forward_as_tuple())); + element* const p(new_element(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple())); m_cont.insert_commit(*p, d); chronological.list.push_back(*p); return p->value.second; @@ -1665,28 +1311,17 @@ operator[](Key const& key) return result.first->value.second; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template typename std::conditional::type& -aged_ordered_container:: -operator[](Key&& key) +aged_ordered_container::operator[](Key&& key) { typename cont_type::insert_commit_data d; - auto const result( - m_cont.insert_check(key, std::cref(m_config.key_compare()), d)); + auto const result(m_cont.insert_check(key, std::cref(m_config.key_compare()), d)); if (result.second) { - element* const p(new_element( - std::piecewise_construct, - std::forward_as_tuple(std::move(key)), - std::forward_as_tuple())); + element* const p( + new_element(std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::forward_as_tuple())); m_cont.insert_commit(*p, d); chronological.list.push_back(*p); return p->value.second; @@ -1696,43 +1331,25 @@ operator[](Key&& key) //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template void -aged_ordered_container:: - clear() +aged_ordered_container::clear() { - for (auto iter(chronological.list.begin()); - iter != chronological.list.end();) + for (auto iter(chronological.list.begin()); iter != chronological.list.end();) delete_element(&*iter++); chronological.list.clear(); m_cont.clear(); } // map, set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - insert(value_type const& value) -> +aged_ordered_container::insert(value_type const& value) -> typename std::enable_if>::type { typename cont_type::insert_commit_data d; - auto const result(m_cont.insert_check( - extract(value), std::cref(m_config.key_compare()), d)); + auto const result(m_cont.insert_check(extract(value), std::cref(m_config.key_compare()), d)); if (result.second) { element* const p(new_element(value)); @@ -1744,22 +1361,13 @@ aged_ordered_container:: } // multimap, multiset -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - insert(value_type const& value) -> +aged_ordered_container::insert(value_type const& value) -> typename std::enable_if::type { - auto const before( - m_cont.upper_bound(extract(value), std::cref(m_config.key_compare()))); + auto const before(m_cont.upper_bound(extract(value), std::cref(m_config.key_compare()))); element* const p(new_element(value)); chronological.list.push_back(*p); auto const iter(m_cont.insert_before(before, *p)); @@ -1767,24 +1375,14 @@ aged_ordered_container:: } // set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - insert(value_type&& value) -> - typename std:: - enable_if>::type +aged_ordered_container::insert(value_type&& value) -> + typename std::enable_if>::type { typename cont_type::insert_commit_data d; - auto const result(m_cont.insert_check( - extract(value), std::cref(m_config.key_compare()), d)); + auto const result(m_cont.insert_check(extract(value), std::cref(m_config.key_compare()), d)); if (result.second) { element* const p(new_element(std::move(value))); @@ -1796,22 +1394,13 @@ aged_ordered_container:: } // multiset -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - insert(value_type&& value) -> +aged_ordered_container::insert(value_type&& value) -> typename std::enable_if::type { - auto const before( - m_cont.upper_bound(extract(value), std::cref(m_config.key_compare()))); + auto const before(m_cont.upper_bound(extract(value), std::cref(m_config.key_compare()))); element* const p(new_element(std::move(value))); chronological.list.push_back(*p); auto const iter(m_cont.insert_before(before, *p)); @@ -1821,23 +1410,15 @@ aged_ordered_container:: //--- // map, set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - insert(const_iterator hint, value_type const& value) -> - typename std::enable_if::type +aged_ordered_container::insert( + const_iterator hint, + value_type const& value) -> typename std::enable_if::type { typename cont_type::insert_commit_data d; - auto const result(m_cont.insert_check( - hint.iterator(), extract(value), std::cref(m_config.key_compare()), d)); + auto const result(m_cont.insert_check(hint.iterator(), extract(value), std::cref(m_config.key_compare()), d)); if (result.second) { element* const p(new_element(value)); @@ -1849,23 +1430,15 @@ aged_ordered_container:: } // map, set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - insert(const_iterator hint, value_type&& value) -> - typename std::enable_if::type +aged_ordered_container::insert( + const_iterator hint, + value_type&& value) -> typename std::enable_if::type { typename cont_type::insert_commit_data d; - auto const result(m_cont.insert_check( - hint.iterator(), extract(value), std::cref(m_config.key_compare()), d)); + auto const result(m_cont.insert_check(hint.iterator(), extract(value), std::cref(m_config.key_compare()), d)); if (result.second) { element* const p(new_element(std::move(value))); @@ -1877,26 +1450,17 @@ aged_ordered_container:: } // map, set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - emplace(Args&&... args) -> +aged_ordered_container::emplace(Args&&... args) -> typename std::enable_if>::type { // VFALCO NOTE Its unfortunate that we need to // construct element here element* const p(new_element(std::forward(args)...)); typename cont_type::insert_commit_data d; - auto const result(m_cont.insert_check( - extract(p->value), std::cref(m_config.key_compare()), d)); + auto const result(m_cont.insert_check(extract(p->value), std::cref(m_config.key_compare()), d)); if (result.second) { auto const iter(m_cont.insert_commit(*p, d)); @@ -1908,52 +1472,32 @@ aged_ordered_container:: } // multiset, multimap -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - emplace(Args&&... args) -> +aged_ordered_container::emplace(Args&&... args) -> typename std::enable_if::type { element* const p(new_element(std::forward(args)...)); - auto const before(m_cont.upper_bound( - extract(p->value), std::cref(m_config.key_compare()))); + auto const before(m_cont.upper_bound(extract(p->value), std::cref(m_config.key_compare()))); chronological.list.push_back(*p); auto const iter(m_cont.insert_before(before, *p)); return iterator(iter); } // map, set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - emplace_hint(const_iterator hint, Args&&... args) -> - typename std::enable_if>::type +aged_ordered_container::emplace_hint( + const_iterator hint, + Args&&... args) -> typename std::enable_if>::type { // VFALCO NOTE Its unfortunate that we need to // construct element here element* const p(new_element(std::forward(args)...)); typename cont_type::insert_commit_data d; - auto const result(m_cont.insert_check( - hint.iterator(), - extract(p->value), - std::cref(m_config.key_compare()), - d)); + auto const result(m_cont.insert_check(hint.iterator(), extract(p->value), std::cref(m_config.key_compare()), d)); if (result.second) { auto const iter(m_cont.insert_commit(*p, d)); @@ -1964,58 +1508,33 @@ aged_ordered_container:: return std::make_pair(iterator(result.first), false); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template beast::detail::aged_container_iterator -aged_ordered_container:: - erase(beast::detail::aged_container_iterator pos) +aged_ordered_container::erase( + beast::detail::aged_container_iterator pos) { unlink_and_delete_element(&*((pos++).iterator())); - return beast::detail::aged_container_iterator( - pos.iterator()); + return beast::detail::aged_container_iterator(pos.iterator()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template beast::detail::aged_container_iterator -aged_ordered_container:: - erase( - beast::detail::aged_container_iterator first, - beast::detail::aged_container_iterator last) +aged_ordered_container::erase( + beast::detail::aged_container_iterator first, + beast::detail::aged_container_iterator last) { for (; first != last;) unlink_and_delete_element(&*((first++).iterator())); - return beast::detail::aged_container_iterator( - first.iterator()); + return beast::detail::aged_container_iterator(first.iterator()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - erase(K const& k) -> size_type +aged_ordered_container::erase(K const& k) -> size_type { auto iter(m_cont.find(k, std::cref(m_config.key_compare()))); if (iter == m_cont.end()) @@ -2033,17 +1552,9 @@ aged_ordered_container:: return n; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template void -aged_ordered_container::swap( - aged_ordered_container& other) noexcept +aged_ordered_container::swap(aged_ordered_container& other) noexcept { swap_data(other); std::swap(chronological, other.chronological); @@ -2052,18 +1563,10 @@ aged_ordered_container::swap( //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template auto -aged_ordered_container:: - touch(K const& k) -> size_type +aged_ordered_container::touch(K const& k) -> size_type { auto const now(clock().now()); size_type n(0); @@ -2078,39 +1581,14 @@ aged_ordered_container:: //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -template < - bool OtherIsMulti, - bool OtherIsMap, - class OtherT, - class OtherDuration, - class OtherAllocator> +template +template bool -aged_ordered_container:: -operator==(aged_ordered_container< - OtherIsMulti, - OtherIsMap, - Key, - OtherT, - OtherDuration, - Compare, - OtherAllocator> const& other) const +aged_ordered_container::operator==( + aged_ordered_container const& other) + const { - using Other = aged_ordered_container< - OtherIsMulti, - OtherIsMap, - Key, - OtherT, - OtherDuration, - Compare, - OtherAllocator>; + using Other = aged_ordered_container; if (size() != other.size()) return false; std::equal_to eq; @@ -2119,28 +1597,19 @@ operator==(aged_ordered_container< cend(), other.cbegin(), other.cend(), - [&eq, &other]( - value_type const& lhs, typename Other::value_type const& rhs) { + [&eq, &other](value_type const& lhs, typename Other::value_type const& rhs) { return eq(extract(lhs), other.extract(rhs)); }); } //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template void -aged_ordered_container:: - touch( - beast::detail::aged_container_iterator pos, - typename clock_type::time_point const& now) +aged_ordered_container::touch( + beast::detail::aged_container_iterator pos, + typename clock_type::time_point const& now) { auto& e(*pos.iterator()); e.when = now; @@ -2148,36 +1617,22 @@ aged_ordered_container:: chronological.list.push_back(e); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template typename std::enable_if::type -aged_ordered_container:: - swap_data(aged_ordered_container& other) noexcept +aged_ordered_container::swap_data( + aged_ordered_container& other) noexcept { std::swap(m_config.key_compare(), other.m_config.key_compare()); std::swap(m_config.alloc(), other.m_config.alloc()); std::swap(m_config.clock, other.m_config.clock); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template template typename std::enable_if::type -aged_ordered_container:: - swap_data(aged_ordered_container& other) noexcept +aged_ordered_container::swap_data( + aged_ordered_container& other) noexcept { std::swap(m_config.key_compare(), other.m_config.key_compare()); std::swap(m_config.clock, other.m_config.clock); @@ -2187,54 +1642,20 @@ aged_ordered_container:: //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> -struct is_aged_container> : std::true_type +template +struct is_aged_container> + : std::true_type { explicit is_aged_container() = default; }; // Free functions -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Compare, - class Allocator> +template void swap( - beast::detail::aged_ordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Compare, - Allocator>& lhs, - beast::detail::aged_ordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Compare, - Allocator>& rhs) noexcept + beast::detail::aged_ordered_container& lhs, + beast::detail::aged_ordered_container& rhs) noexcept { lhs.swap(rhs); } @@ -2252,20 +1673,12 @@ template < class Period> std::size_t expire( - detail::aged_ordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Compare, - Allocator>& c, + detail::aged_ordered_container& c, std::chrono::duration const& age) { std::size_t n(0); auto const expired(c.clock().now() - age); - for (auto iter(c.chronological.cbegin()); - iter != c.chronological.cend() && iter.when() <= expired;) + for (auto iter(c.chronological.cbegin()); iter != c.chronological.cend() && iter.when() <= expired;) { iter = c.erase(iter); ++n; diff --git a/include/xrpl/beast/container/detail/aged_unordered_container.h b/include/xrpl/beast/container/detail/aged_unordered_container.h index e2ee3b24e0..96dd196f32 100644 --- a/include/xrpl/beast/container/detail/aged_unordered_container.h +++ b/include/xrpl/beast/container/detail/aged_unordered_container.h @@ -63,8 +63,7 @@ template < class Clock = std::chrono::steady_clock, class Hash = std::hash, class KeyEqual = std::equal_to, - class Allocator = std::allocator< - typename std::conditional, Key>::type>> + class Allocator = std::allocator, Key>::type>> class aged_unordered_container { public: @@ -73,8 +72,7 @@ public: using duration = typename clock_type::duration; using key_type = Key; using mapped_type = T; - using value_type = - typename std::conditional, Key>::type; + using value_type = typename std::conditional, Key>::type; using size_type = std::size_t; using difference_type = std::ptrdiff_t; @@ -92,10 +90,8 @@ private: // VFALCO TODO hoist to remove template argument dependencies struct element - : boost::intrusive::unordered_set_base_hook< - boost::intrusive::link_mode>, - boost::intrusive::list_base_hook< - boost::intrusive::link_mode> + : boost::intrusive::unordered_set_base_hook>, + boost::intrusive::list_base_hook> { // Stash types here so the iterator doesn't // need to see the container declaration. @@ -107,22 +103,18 @@ private: using time_point = typename aged_unordered_container::time_point; }; - element(time_point const& when_, value_type const& value_) - : value(value_), when(when_) + element(time_point const& when_, value_type const& value_) : value(value_), when(when_) { } - element(time_point const& when_, value_type&& value_) - : value(std::move(value_)), when(when_) + element(time_point const& when_, value_type&& value_) : value(std::move(value_)), when(when_) { } template < class... Args, - class = typename std::enable_if< - std::is_constructible::value>::type> - element(time_point const& when_, Args&&... args) - : value(std::forward(args)...), when(when_) + class = typename std::enable_if::value>::type> + element(time_point const& when_, Args&&... args) : value(std::forward(args)...), when(when_) { } @@ -212,8 +204,7 @@ private: } }; - using list_type = typename boost::intrusive:: - make_list>::type; + using list_type = typename boost::intrusive::make_list>::type; using cont_type = typename std::conditional< IsMulti, @@ -233,39 +224,33 @@ private: using bucket_type = typename cont_type::bucket_type; using bucket_traits = typename cont_type::bucket_traits; - using ElementAllocator = typename std::allocator_traits< - Allocator>::template rebind_alloc; + using ElementAllocator = typename std::allocator_traits::template rebind_alloc; using ElementAllocatorTraits = std::allocator_traits; - using BucketAllocator = typename std::allocator_traits< - Allocator>::template rebind_alloc; + using BucketAllocator = typename std::allocator_traits::template rebind_alloc; using BucketAllocatorTraits = std::allocator_traits; - class config_t - : private ValueHash, - private KeyValueEqual, - private beast::detail::empty_base_optimization + class config_t : private ValueHash, + private KeyValueEqual, + private beast::detail::empty_base_optimization { public: explicit config_t(clock_type& clock_) : clock(clock_) { } - config_t(clock_type& clock_, Hash const& hash) - : ValueHash(hash), clock(clock_) + config_t(clock_type& clock_, Hash const& hash) : ValueHash(hash), clock(clock_) { } - config_t(clock_type& clock_, KeyEqual const& keyEqual) - : KeyValueEqual(keyEqual), clock(clock_) + config_t(clock_type& clock_, KeyEqual const& keyEqual) : KeyValueEqual(keyEqual), clock(clock_) { } config_t(clock_type& clock_, Allocator const& alloc_) - : beast::detail::empty_base_optimization(alloc_) - , clock(clock_) + : beast::detail::empty_base_optimization(alloc_), clock(clock_) { } @@ -275,27 +260,16 @@ private: } config_t(clock_type& clock_, Hash const& hash, Allocator const& alloc_) - : ValueHash(hash) - , beast::detail::empty_base_optimization(alloc_) - , clock(clock_) + : ValueHash(hash), beast::detail::empty_base_optimization(alloc_), clock(clock_) { } - config_t( - clock_type& clock_, - KeyEqual const& keyEqual, - Allocator const& alloc_) - : KeyValueEqual(keyEqual) - , beast::detail::empty_base_optimization(alloc_) - , clock(clock_) + config_t(clock_type& clock_, KeyEqual const& keyEqual, Allocator const& alloc_) + : KeyValueEqual(keyEqual), beast::detail::empty_base_optimization(alloc_), clock(clock_) { } - config_t( - clock_type& clock_, - Hash const& hash, - KeyEqual const& keyEqual, - Allocator const& alloc_) + config_t(clock_type& clock_, Hash const& hash, KeyEqual const& keyEqual, Allocator const& alloc_) : ValueHash(hash) , KeyValueEqual(keyEqual) , beast::detail::empty_base_optimization(alloc_) @@ -307,8 +281,7 @@ private: : ValueHash(other.hash_function()) , KeyValueEqual(other.key_eq()) , beast::detail::empty_base_optimization( - ElementAllocatorTraits::select_on_container_copy_construction( - other.alloc())) + ElementAllocatorTraits::select_on_container_copy_construction(other.alloc())) , clock(other.clock) { } @@ -324,8 +297,7 @@ private: config_t(config_t&& other) : ValueHash(std::move(other.hash_function())) , KeyValueEqual(std::move(other.key_eq())) - , beast::detail::empty_base_optimization( - std::move(other.alloc())) + , beast::detail::empty_base_optimization(std::move(other.alloc())) , clock(other.clock) { } @@ -409,15 +381,13 @@ private: ElementAllocator& alloc() { - return beast::detail::empty_base_optimization< - ElementAllocator>::member(); + return beast::detail::empty_base_optimization::member(); } ElementAllocator const& alloc() const { - return beast::detail::empty_base_optimization< - ElementAllocator>::member(); + return beast::detail::empty_base_optimization::member(); } std::reference_wrapper clock; @@ -426,10 +396,8 @@ private: class Buckets { public: - using vec_type = std::vector< - bucket_type, - typename std::allocator_traits::template rebind_alloc< - bucket_type>>; + using vec_type = + std::vector::template rebind_alloc>; Buckets() : m_max_load_factor(1.f), m_vec() { @@ -508,8 +476,7 @@ private: void resize(size_type n, Container& c) { - size_type const suggested( - cont_type::suggested_upper_bucket_count(n)); + size_type const suggested(cont_type::suggested_upper_bucket_count(n)); rehash(suggested, c); } @@ -537,13 +504,8 @@ private: }; std::unique_ptr p( - ElementAllocatorTraits::allocate(m_config.alloc(), 1), - Deleter(m_config.alloc())); - ElementAllocatorTraits::construct( - m_config.alloc(), - p.get(), - clock().now(), - std::forward(args)...); + ElementAllocatorTraits::allocate(m_config.alloc(), 1), Deleter(m_config.alloc())); + ElementAllocatorTraits::construct(m_config.alloc(), p.get(), clock().now(), std::forward(args)...); return p.release(); } @@ -551,8 +513,7 @@ private: delete_element(element const* p) { ElementAllocatorTraits::destroy(m_config.alloc(), p); - ElementAllocatorTraits::deallocate( - m_config.alloc(), const_cast(p), 1); + ElementAllocatorTraits::deallocate(m_config.alloc(), const_cast(p), 1); } void @@ -570,20 +531,15 @@ public: using reference = value_type&; using const_reference = value_type const&; using pointer = typename std::allocator_traits::pointer; - using const_pointer = - typename std::allocator_traits::const_pointer; + using const_pointer = typename std::allocator_traits::const_pointer; // A set iterator (IsMap==false) is always const // because the elements of a set are immutable. - using iterator = beast::detail:: - aged_container_iterator; - using const_iterator = beast::detail:: - aged_container_iterator; + using iterator = beast::detail::aged_container_iterator; + using const_iterator = beast::detail::aged_container_iterator; - using local_iterator = beast::detail:: - aged_container_iterator; - using const_local_iterator = beast::detail:: - aged_container_iterator; + using local_iterator = beast::detail::aged_container_iterator; + using const_local_iterator = beast::detail::aged_container_iterator; //-------------------------------------------------------------------------- // @@ -599,15 +555,11 @@ public: public: // A set iterator (IsMap==false) is always const // because the elements of a set are immutable. - using iterator = beast::detail:: - aged_container_iterator; - using const_iterator = beast::detail:: - aged_container_iterator; - using reverse_iterator = beast::detail::aged_container_iterator< - !IsMap, - typename list_type::reverse_iterator>; - using const_reverse_iterator = beast::detail:: - aged_container_iterator; + using iterator = beast::detail::aged_container_iterator; + using const_iterator = beast::detail::aged_container_iterator; + using reverse_iterator = beast::detail::aged_container_iterator; + using const_reverse_iterator = + beast::detail::aged_container_iterator; iterator begin() @@ -684,23 +636,17 @@ public: iterator iterator_to(value_type& value) { - static_assert( - std::is_standard_layout::value, - "must be standard layout"); + static_assert(std::is_standard_layout::value, "must be standard layout"); return list.iterator_to(*reinterpret_cast( - reinterpret_cast(&value) - - ((std::size_t)std::addressof(((element*)0)->member)))); + reinterpret_cast(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); } const_iterator iterator_to(value_type const& value) const { - static_assert( - std::is_standard_layout::value, - "must be standard layout"); + static_assert(std::is_standard_layout::value, "must be standard layout"); return list.iterator_to(*reinterpret_cast( - reinterpret_cast(&value) - - ((std::size_t)std::addressof(((element*)0)->member)))); + reinterpret_cast(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); } private: @@ -731,66 +677,31 @@ public: aged_unordered_container(clock_type& clock, Allocator const& alloc); - aged_unordered_container( - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq); + aged_unordered_container(clock_type& clock, Hash const& hash, KeyEqual const& key_eq); - aged_unordered_container( - clock_type& clock, - Hash const& hash, - Allocator const& alloc); + aged_unordered_container(clock_type& clock, Hash const& hash, Allocator const& alloc); - aged_unordered_container( - clock_type& clock, - KeyEqual const& key_eq, - Allocator const& alloc); + aged_unordered_container(clock_type& clock, KeyEqual const& key_eq, Allocator const& alloc); - aged_unordered_container( - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq, - Allocator const& alloc); + aged_unordered_container(clock_type& clock, Hash const& hash, KeyEqual const& key_eq, Allocator const& alloc); template aged_unordered_container(InputIt first, InputIt last, clock_type& clock); template - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Hash const& hash); + aged_unordered_container(InputIt first, InputIt last, clock_type& clock, Hash const& hash); template - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - KeyEqual const& key_eq); + aged_unordered_container(InputIt first, InputIt last, clock_type& clock, KeyEqual const& key_eq); template - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Allocator const& alloc); + aged_unordered_container(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc); template - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq); + aged_unordered_container(InputIt first, InputIt last, clock_type& clock, Hash const& hash, KeyEqual const& key_eq); template - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Hash const& hash, - Allocator const& alloc); + aged_unordered_container(InputIt first, InputIt last, clock_type& clock, Hash const& hash, Allocator const& alloc); template aged_unordered_container( @@ -811,34 +722,19 @@ public: aged_unordered_container(aged_unordered_container const& other); - aged_unordered_container( - aged_unordered_container const& other, - Allocator const& alloc); + aged_unordered_container(aged_unordered_container const& other, Allocator const& alloc); aged_unordered_container(aged_unordered_container&& other); - aged_unordered_container( - aged_unordered_container&& other, - Allocator const& alloc); + aged_unordered_container(aged_unordered_container&& other, Allocator const& alloc); - aged_unordered_container( - std::initializer_list init, - clock_type& clock); + aged_unordered_container(std::initializer_list init, clock_type& clock); - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - Hash const& hash); + aged_unordered_container(std::initializer_list init, clock_type& clock, Hash const& hash); - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - KeyEqual const& key_eq); + aged_unordered_container(std::initializer_list init, clock_type& clock, KeyEqual const& key_eq); - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - Allocator const& alloc); + aged_unordered_container(std::initializer_list init, clock_type& clock, Allocator const& alloc); aged_unordered_container( std::initializer_list init, @@ -975,21 +871,17 @@ public: iterator iterator_to(value_type& value) { - static_assert( - std::is_standard_layout::value, "must be standard layout"); + static_assert(std::is_standard_layout::value, "must be standard layout"); return m_cont.iterator_to(*reinterpret_cast( - reinterpret_cast(&value) - - ((std::size_t)std::addressof(((element*)0)->member)))); + reinterpret_cast(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); } const_iterator iterator_to(value_type const& value) const { - static_assert( - std::is_standard_layout::value, "must be standard layout"); + static_assert(std::is_standard_layout::value, "must be standard layout"); return m_cont.iterator_to(*reinterpret_cast( - reinterpret_cast(&value) - - ((std::size_t)std::addressof(((element*)0)->member)))); + reinterpret_cast(&value) - ((std::size_t)std::addressof(((element*)0)->member)))); } //-------------------------------------------------------------------------- @@ -1028,27 +920,22 @@ public: // map, set template auto - insert(value_type const& value) -> - typename std::enable_if>::type; + insert(value_type const& value) -> typename std::enable_if>::type; // multimap, multiset template auto - insert(value_type const& value) -> - typename std::enable_if::type; + insert(value_type const& value) -> typename std::enable_if::type; // map, set template auto - insert(value_type&& value) -> typename std::enable_if< - !maybe_multi && !maybe_map, - std::pair>::type; + insert(value_type&& value) -> typename std::enable_if>::type; // multimap, multiset template auto - insert(value_type&& value) -> - typename std::enable_if::type; + insert(value_type&& value) -> typename std::enable_if::type; // map, set template @@ -1094,10 +981,8 @@ public: template typename std::enable_if< maybe_map && std::is_constructible::value, - typename std:: - conditional>::type>:: - type - insert(P&& value) + typename std::conditional>::type>::type + insert(P&& value) { return emplace(std::forward

(value)); } @@ -1106,10 +991,8 @@ public: template typename std::enable_if< maybe_map && std::is_constructible::value, - typename std:: - conditional>::type>:: - type - insert(const_iterator hint, P&& value) + typename std::conditional>::type>::type + insert(const_iterator hint, P&& value) { return emplace_hint(hint, std::forward

(value)); } @@ -1118,10 +1001,7 @@ public: void insert(InputIt first, InputIt last) { - insert( - first, - last, - typename std::iterator_traits::iterator_category()); + insert(first, last, typename std::iterator_traits::iterator_category()); } void @@ -1133,14 +1013,12 @@ public: // set, map template auto - emplace(Args&&... args) -> - typename std::enable_if>::type; + emplace(Args&&... args) -> typename std::enable_if>::type; // multiset, multimap template auto - emplace(Args&&... args) -> - typename std::enable_if::type; + emplace(Args&&... args) -> typename std::enable_if::type; // set, map template @@ -1197,10 +1075,7 @@ public: size_type count(K const& k) const { - return m_cont.count( - k, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal())); + return m_cont.count(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal())); } // VFALCO TODO Respect is_transparent (c++14) @@ -1208,10 +1083,7 @@ public: iterator find(K const& k) { - return iterator(m_cont.find( - k, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()))); + return iterator(m_cont.find(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()))); } // VFALCO TODO Respect is_transparent (c++14) @@ -1219,10 +1091,8 @@ public: const_iterator find(K const& k) const { - return const_iterator(m_cont.find( - k, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()))); + return const_iterator( + m_cont.find(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()))); } // VFALCO TODO Respect is_transparent (c++14) @@ -1230,10 +1100,7 @@ public: std::pair equal_range(K const& k) { - auto const r(m_cont.equal_range( - k, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()))); + auto const r(m_cont.equal_range(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()))); return std::make_pair(iterator(r.first), iterator(r.second)); } @@ -1242,12 +1109,8 @@ public: std::pair equal_range(K const& k) const { - auto const r(m_cont.equal_range( - k, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()))); - return std::make_pair( - const_iterator(r.first), const_iterator(r.second)); + auto const r(m_cont.equal_range(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()))); + return std::make_pair(const_iterator(r.first), const_iterator(r.second)); } //-------------------------------------------------------------------------- @@ -1466,14 +1329,12 @@ private: // map, set template auto - insert_unchecked(value_type const& value) -> - typename std::enable_if>::type; + insert_unchecked(value_type const& value) -> typename std::enable_if>::type; // multimap, multiset template auto - insert_unchecked(value_type const& value) -> - typename std::enable_if::type; + insert_unchecked(value_type const& value) -> typename std::enable_if::type; template void @@ -1502,9 +1363,7 @@ private: template void - touch( - beast::detail::aged_container_iterator pos, - typename clock_type::time_point const& now) + touch(beast::detail::aged_container_iterator pos, typename clock_type::time_point const& now) { auto& e(*pos.iterator()); e.when = now; @@ -1512,9 +1371,7 @@ private: chronological.list.push_back(e); } - template < - bool maybe_propagate = std::allocator_traits< - Allocator>::propagate_on_container_swap::value> + template ::propagate_on_container_swap::value> typename std::enable_if::type swap_data(aged_unordered_container& other) noexcept { @@ -1523,9 +1380,7 @@ private: std::swap(m_config.clock, other.m_config.clock); } - template < - bool maybe_propagate = std::allocator_traits< - Allocator>::propagate_on_container_swap::value> + template ::propagate_on_container_swap::value> typename std::enable_if::type swap_data(aged_unordered_container& other) noexcept { @@ -1541,920 +1396,336 @@ private: //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::aged_unordered_container(clock_type& clock) - : m_config(clock) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +template +aged_unordered_container::aged_unordered_container( + clock_type& clock) + : m_config(clock), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::aged_unordered_container(clock_type& clock, Hash const& hash) - : m_config(clock, hash) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +template +aged_unordered_container::aged_unordered_container( + clock_type& clock, + Hash const& hash) + : m_config(clock, hash), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container(clock_type& clock, KeyEqual const& key_eq) - : m_config(clock, key_eq) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +template +aged_unordered_container::aged_unordered_container( + clock_type& clock, + KeyEqual const& key_eq) + : m_config(clock, key_eq), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container(clock_type& clock, Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + clock_type& clock, + Allocator const& alloc) : m_config(clock, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq) +template +aged_unordered_container::aged_unordered_container( + clock_type& clock, + Hash const& hash, + KeyEqual const& key_eq) : m_config(clock, hash, key_eq) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - clock_type& clock, - Hash const& hash, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + clock_type& clock, + Hash const& hash, + Allocator const& alloc) : m_config(clock, hash, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - clock_type& clock, - KeyEqual const& key_eq, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + clock_type& clock, + KeyEqual const& key_eq, + Allocator const& alloc) : m_config(clock, key_eq, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + clock_type& clock, + Hash const& hash, + KeyEqual const& key_eq, + Allocator const& alloc) : m_config(clock, hash, key_eq, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container(InputIt first, InputIt last, clock_type& clock) - : m_config(clock) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +aged_unordered_container::aged_unordered_container( + InputIt first, + InputIt last, + clock_type& clock) + : m_config(clock), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Hash const& hash) - : m_config(clock, hash) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +aged_unordered_container::aged_unordered_container( + InputIt first, + InputIt last, + clock_type& clock, + Hash const& hash) + : m_config(clock, hash), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - KeyEqual const& key_eq) - : m_config(clock, key_eq) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +aged_unordered_container::aged_unordered_container( + InputIt first, + InputIt last, + clock_type& clock, + KeyEqual const& key_eq) + : m_config(clock, key_eq), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Allocator const& alloc) +aged_unordered_container::aged_unordered_container( + InputIt first, + InputIt last, + clock_type& clock, + Allocator const& alloc) : m_config(clock, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq) +aged_unordered_container::aged_unordered_container( + InputIt first, + InputIt last, + clock_type& clock, + Hash const& hash, + KeyEqual const& key_eq) : m_config(clock, hash, key_eq) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Hash const& hash, - Allocator const& alloc) +aged_unordered_container::aged_unordered_container( + InputIt first, + InputIt last, + clock_type& clock, + Hash const& hash, + Allocator const& alloc) : m_config(clock, hash, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - KeyEqual const& key_eq, - Allocator const& alloc) +aged_unordered_container::aged_unordered_container( + InputIt first, + InputIt last, + clock_type& clock, + KeyEqual const& key_eq, + Allocator const& alloc) : m_config(clock, key_eq, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - InputIt first, - InputIt last, - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq, - Allocator const& alloc) +aged_unordered_container::aged_unordered_container( + InputIt first, + InputIt last, + clock_type& clock, + Hash const& hash, + KeyEqual const& key_eq, + Allocator const& alloc) : m_config(clock, hash, key_eq, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(first, last); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::aged_unordered_container(aged_unordered_container const& other) +template +aged_unordered_container::aged_unordered_container( + aged_unordered_container const& other) : m_config(other.m_config) , m_buck(m_config.alloc()) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(other.cbegin(), other.cend()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - aged_unordered_container const& other, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + aged_unordered_container const& other, + Allocator const& alloc) : m_config(other.m_config, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(other.cbegin(), other.cend()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::aged_unordered_container(aged_unordered_container&& other) - : m_config(std::move(other.m_config)) - , m_buck(std::move(other.m_buck)) - , m_cont(std::move(other.m_cont)) +template +aged_unordered_container::aged_unordered_container( + aged_unordered_container&& other) + : m_config(std::move(other.m_config)), m_buck(std::move(other.m_buck)), m_cont(std::move(other.m_cont)) { chronological.list = std::move(other.chronological.list); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - aged_unordered_container&& other, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + aged_unordered_container&& other, + Allocator const& alloc) : m_config(std::move(other.m_config), alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(other.cbegin(), other.cend()); other.clear(); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - std::initializer_list init, - clock_type& clock) - : m_config(clock) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +template +aged_unordered_container::aged_unordered_container( + std::initializer_list init, + clock_type& clock) + : m_config(clock), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - Hash const& hash) - : m_config(clock, hash) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +template +aged_unordered_container::aged_unordered_container( + std::initializer_list init, + clock_type& clock, + Hash const& hash) + : m_config(clock, hash), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - KeyEqual const& key_eq) - : m_config(clock, key_eq) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) +template +aged_unordered_container::aged_unordered_container( + std::initializer_list init, + clock_type& clock, + KeyEqual const& key_eq) + : m_config(clock, key_eq), m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + std::initializer_list init, + clock_type& clock, + Allocator const& alloc) : m_config(clock, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq) +template +aged_unordered_container::aged_unordered_container( + std::initializer_list init, + clock_type& clock, + Hash const& hash, + KeyEqual const& key_eq) : m_config(clock, hash, key_eq) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - Hash const& hash, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + std::initializer_list init, + clock_type& clock, + Hash const& hash, + Allocator const& alloc) : m_config(clock, hash, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - KeyEqual const& key_eq, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + std::initializer_list init, + clock_type& clock, + KeyEqual const& key_eq, + Allocator const& alloc) : m_config(clock, key_eq, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - aged_unordered_container( - std::initializer_list init, - clock_type& clock, - Hash const& hash, - KeyEqual const& key_eq, - Allocator const& alloc) +template +aged_unordered_container::aged_unordered_container( + std::initializer_list init, + clock_type& clock, + Hash const& hash, + KeyEqual const& key_eq, + Allocator const& alloc) : m_config(clock, hash, key_eq, alloc) , m_buck(alloc) - , m_cont( - m_buck, - std::cref(m_config.value_hash()), - std::cref(m_config.key_value_equal())) + , m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal())) { insert(init.begin(), init.end()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::~aged_unordered_container() +template +aged_unordered_container::~aged_unordered_container() { clear(); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::operator=(aged_unordered_container const& other) - -> aged_unordered_container& +aged_unordered_container::operator=( + aged_unordered_container const& other) -> aged_unordered_container& { if (this != &other) { @@ -2468,26 +1739,10 @@ aged_unordered_container< return *this; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::operator=(aged_unordered_container&& other) - -> aged_unordered_container& +aged_unordered_container::operator=( + aged_unordered_container&& other) -> aged_unordered_container& { size_type const n(other.size()); clear(); @@ -2499,26 +1754,10 @@ aged_unordered_container< return *this; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::operator=(std::initializer_list init) - -> aged_unordered_container& +aged_unordered_container::operator=( + std::initializer_list init) -> aged_unordered_container& { clear(); insert(init); @@ -2527,100 +1766,40 @@ aged_unordered_container< //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template typename std::conditional::type& -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::at(K const& k) +aged_unordered_container::at(K const& k) { - auto const iter(m_cont.find( - k, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()))); + auto const iter(m_cont.find(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()))); if (iter == m_cont.end()) throw std::out_of_range("key not found"); return iter->value.second; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template typename std::conditional::type const& -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::at(K const& k) const +aged_unordered_container::at(K const& k) const { - auto const iter(m_cont.find( - k, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()))); + auto const iter(m_cont.find(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()))); if (iter == m_cont.end()) throw std::out_of_range("key not found"); return iter->value.second; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template typename std::conditional::type& -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::operator[](Key const& key) +aged_unordered_container::operator[](Key const& key) { maybe_rehash(1); typename cont_type::insert_commit_data d; - auto const result(m_cont.insert_check( - key, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()), - d)); + auto const result( + m_cont.insert_check(key, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d)); if (result.second) { - element* const p(new_element( - std::piecewise_construct, - std::forward_as_tuple(key), - std::forward_as_tuple())); + element* const p(new_element(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple())); m_cont.insert_commit(*p, d); chronological.list.push_back(*p); return p->value.second; @@ -2628,40 +1807,19 @@ aged_unordered_container< return result.first->value.second; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template typename std::conditional::type& -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::operator[](Key&& key) +aged_unordered_container::operator[](Key&& key) { maybe_rehash(1); typename cont_type::insert_commit_data d; - auto const result(m_cont.insert_check( - key, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()), - d)); + auto const result( + m_cont.insert_check(key, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d)); if (result.second) { - element* const p(new_element( - std::piecewise_construct, - std::forward_as_tuple(std::move(key)), - std::forward_as_tuple())); + element* const p( + new_element(std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::forward_as_tuple())); m_cont.insert_commit(*p, d); chronological.list.push_back(*p); return p->value.second; @@ -2671,28 +1829,11 @@ aged_unordered_container< //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template void -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::clear() +aged_unordered_container::clear() { - for (auto iter(chronological.list.begin()); - iter != chronological.list.end();) + for (auto iter(chronological.list.begin()); iter != chronological.list.end();) unlink_and_delete_element(&*iter++); chronological.list.clear(); m_cont.clear(); @@ -2700,35 +1841,16 @@ aged_unordered_container< } // map, set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::insert(value_type const& value) -> +aged_unordered_container::insert(value_type const& value) -> typename std::enable_if>::type { maybe_rehash(1); typename cont_type::insert_commit_data d; auto const result(m_cont.insert_check( - extract(value), - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()), - d)); + extract(value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d)); if (result.second) { element* const p(new_element(value)); @@ -2740,26 +1862,10 @@ aged_unordered_container< } // multimap, multiset -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::insert(value_type const& value) -> +aged_unordered_container::insert(value_type const& value) -> typename std::enable_if::type { maybe_rehash(1); @@ -2770,36 +1876,16 @@ aged_unordered_container< } // map, set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::insert(value_type&& value) -> - typename std:: - enable_if>::type +aged_unordered_container::insert(value_type&& value) -> + typename std::enable_if>::type { maybe_rehash(1); typename cont_type::insert_commit_data d; auto const result(m_cont.insert_check( - extract(value), - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()), - d)); + extract(value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d)); if (result.second) { element* const p(new_element(std::move(value))); @@ -2811,26 +1897,10 @@ aged_unordered_container< } // multimap, multiset -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::insert(value_type&& value) -> +aged_unordered_container::insert(value_type&& value) -> typename std::enable_if::type { maybe_rehash(1); @@ -2842,26 +1912,10 @@ aged_unordered_container< #if 1 // Use insert() instead of insert_check() insert_commit() // set, map -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::emplace(Args&&... args) -> +aged_unordered_container::emplace(Args&&... args) -> typename std::enable_if>::type { maybe_rehash(1); @@ -2879,26 +1933,10 @@ aged_unordered_container< } #else // As original, use insert_check() / insert_commit () pair. // set, map -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::emplace(Args&&... args) -> +aged_unordered_container::emplace(Args&&... args) -> typename std::enable_if>::type { maybe_rehash(1); @@ -2907,10 +1945,7 @@ aged_unordered_container< element* const p(new_element(std::forward(args)...)); typename cont_type::insert_commit_data d; auto const result(m_cont.insert_check( - extract(p->value), - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()), - d)); + extract(p->value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d)); if (result.second) { auto const iter(m_cont.insert_commit(*p, d)); @@ -2923,26 +1958,10 @@ aged_unordered_container< #endif // 0 // multiset, multimap -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::emplace(Args&&... args) -> +aged_unordered_container::emplace(Args&&... args) -> typename std::enable_if::type { maybe_rehash(1); @@ -2953,27 +1972,12 @@ aged_unordered_container< } // set, map -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::emplace_hint(const_iterator /*hint*/, Args&&... args) -> - typename std::enable_if>::type +aged_unordered_container::emplace_hint( + const_iterator /*hint*/, + Args&&... args) -> typename std::enable_if>::type { maybe_rehash(1); // VFALCO NOTE Its unfortunate that we need to @@ -2981,10 +1985,7 @@ aged_unordered_container< element* const p(new_element(std::forward(args)...)); typename cont_type::insert_commit_data d; auto const result(m_cont.insert_check( - extract(p->value), - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()), - d)); + extract(p->value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d)); if (result.second) { auto const iter(m_cont.insert_commit(*p, d)); @@ -2995,89 +1996,35 @@ aged_unordered_container< return std::make_pair(iterator(result.first), false); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template beast::detail::aged_container_iterator -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::erase(beast::detail::aged_container_iterator - pos) +aged_unordered_container::erase( + beast::detail::aged_container_iterator pos) { unlink_and_delete_element(&*((pos++).iterator())); - return beast::detail::aged_container_iterator( - pos.iterator()); + return beast::detail::aged_container_iterator(pos.iterator()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template beast::detail::aged_container_iterator -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: - erase( - beast::detail::aged_container_iterator first, - beast::detail::aged_container_iterator last) +aged_unordered_container::erase( + beast::detail::aged_container_iterator first, + beast::detail::aged_container_iterator last) { for (; first != last;) unlink_and_delete_element(&*((first++).iterator())); - return beast::detail::aged_container_iterator( - first.iterator()); + return beast::detail::aged_container_iterator(first.iterator()); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::erase(K const& k) -> size_type +aged_unordered_container::erase(K const& k) -> size_type { - auto iter(m_cont.find( - k, - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()))); + auto iter(m_cont.find(k, std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()))); if (iter == m_cont.end()) return 0; size_type n(0); @@ -3093,51 +2040,20 @@ aged_unordered_container< return n; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template void -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::swap(aged_unordered_container& other) noexcept +aged_unordered_container::swap( + aged_unordered_container& other) noexcept { swap_data(other); std::swap(chronological, other.chronological); std::swap(m_cont, other.m_cont); } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::touch(K const& k) -> size_type +aged_unordered_container::touch(K const& k) -> size_type { auto const now(clock().now()); size_type n(0); @@ -3150,15 +2066,7 @@ aged_unordered_container< return n; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template < bool OtherIsMap, class OtherKey, @@ -3168,30 +2076,20 @@ template < class OtherAllocator, bool maybe_multi> typename std::enable_if::type -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: -operator==(aged_unordered_container< - false, - OtherIsMap, - OtherKey, - OtherT, - OtherDuration, - OtherHash, - KeyEqual, - OtherAllocator> const& other) const +aged_unordered_container::operator==( + aged_unordered_container< + false, + OtherIsMap, + OtherKey, + OtherT, + OtherDuration, + OtherHash, + KeyEqual, + OtherAllocator> const& other) const { if (size() != other.size()) return false; - for (auto iter(cbegin()), last(cend()), otherLast(other.cend()); - iter != last; - ++iter) + for (auto iter(cbegin()), last(cend()), otherLast(other.cend()); iter != last; ++iter) { auto otherIter(other.find(extract(*iter))); if (otherIter == otherLast) @@ -3200,15 +2098,7 @@ operator==(aged_unordered_container< return true; } -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template < bool OtherIsMap, class OtherKey, @@ -3218,24 +2108,16 @@ template < class OtherAllocator, bool maybe_multi> typename std::enable_if::type -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>:: -operator==(aged_unordered_container< - true, - OtherIsMap, - OtherKey, - OtherT, - OtherDuration, - OtherHash, - KeyEqual, - OtherAllocator> const& other) const +aged_unordered_container::operator==( + aged_unordered_container< + true, + OtherIsMap, + OtherKey, + OtherT, + OtherDuration, + OtherHash, + KeyEqual, + OtherAllocator> const& other) const { if (size() != other.size()) return false; @@ -3245,8 +2127,7 @@ operator==(aged_unordered_container< auto const eq(equal_range(k)); auto const oeq(other.equal_range(k)); #if BEAST_NO_CXX14_IS_PERMUTATION - if (std::distance(eq.first, eq.second) != - std::distance(oeq.first, oeq.second) || + if (std::distance(eq.first, eq.second) != std::distance(oeq.first, oeq.second) || !std::is_permutation(eq.first, eq.second, oeq.first)) return false; #else @@ -3261,34 +2142,15 @@ operator==(aged_unordered_container< //------------------------------------------------------------------------------ // map, set -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::insert_unchecked(value_type const& value) -> - typename std::enable_if>::type +aged_unordered_container::insert_unchecked( + value_type const& value) -> typename std::enable_if>::type { typename cont_type::insert_commit_data d; auto const result(m_cont.insert_check( - extract(value), - std::cref(m_config.hash_function()), - std::cref(m_config.key_value_equal()), - d)); + extract(value), std::cref(m_config.hash_function()), std::cref(m_config.key_value_equal()), d)); if (result.second) { element* const p(new_element(value)); @@ -3300,27 +2162,11 @@ aged_unordered_container< } // multimap, multiset -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template template auto -aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>::insert_unchecked(value_type const& value) -> - typename std::enable_if::type +aged_unordered_container::insert_unchecked( + value_type const& value) -> typename std::enable_if::type { element* const p(new_element(value)); chronological.list.push_back(*p); @@ -3334,59 +2180,20 @@ aged_unordered_container< //------------------------------------------------------------------------------ -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> -struct is_aged_container> : std::true_type +template +struct is_aged_container< + beast::detail::aged_unordered_container> : std::true_type { explicit is_aged_container() = default; }; // Free functions -template < - bool IsMulti, - bool IsMap, - class Key, - class T, - class Clock, - class Hash, - class KeyEqual, - class Allocator> +template void swap( - beast::detail::aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>& lhs, - beast::detail::aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>& rhs) noexcept + beast::detail::aged_unordered_container& lhs, + beast::detail::aged_unordered_container& rhs) noexcept { lhs.swap(rhs); } @@ -3405,21 +2212,12 @@ template < class Period> std::size_t expire( - beast::detail::aged_unordered_container< - IsMulti, - IsMap, - Key, - T, - Clock, - Hash, - KeyEqual, - Allocator>& c, + beast::detail::aged_unordered_container& c, std::chrono::duration const& age) noexcept { std::size_t n(0); auto const expired(c.clock().now() - age); - for (auto iter(c.chronological.cbegin()); - iter != c.chronological.cend() && iter.when() <= expired;) + for (auto iter(c.chronological.cbegin()); iter != c.chronological.cend() && iter.when() <= expired;) { iter = c.erase(iter); ++n; diff --git a/include/xrpl/beast/container/detail/empty_base_optimization.h b/include/xrpl/beast/container/detail/empty_base_optimization.h index 30f87a9bd2..9f3a2ffdf2 100644 --- a/include/xrpl/beast/container/detail/empty_base_optimization.h +++ b/include/xrpl/beast/container/detail/empty_base_optimization.h @@ -17,16 +17,11 @@ namespace detail { template struct is_empty_base_optimization_derived - : std::integral_constant< - bool, - std::is_empty::value && !boost::is_final::value> + : std::integral_constant::value && !boost::is_final::value> { }; -template < - class T, - int UniqueID = 0, - bool isDerived = is_empty_base_optimization_derived::value> +template ::value> class empty_base_optimization : private T { public: diff --git a/include/xrpl/beast/core/CurrentThreadName.h b/include/xrpl/beast/core/CurrentThreadName.h index 703246a76a..87fa042f81 100644 --- a/include/xrpl/beast/core/CurrentThreadName.h +++ b/include/xrpl/beast/core/CurrentThreadName.h @@ -35,9 +35,7 @@ template void setCurrentThreadName(char const (&newThreadName)[N]) { - static_assert( - N <= maxThreadNameLength + 1, - "Thread name cannot exceed 15 characters"); + static_assert(N <= maxThreadNameLength + 1, "Thread name cannot exceed 15 characters"); setCurrentThreadName(std::string_view(newThreadName, N - 1)); } diff --git a/include/xrpl/beast/core/LexicalCast.h b/include/xrpl/beast/core/LexicalCast.h index c5b7f5540a..b0322614b5 100644 --- a/include/xrpl/beast/core/LexicalCast.h +++ b/include/xrpl/beast/core/LexicalCast.h @@ -40,8 +40,7 @@ struct LexicalCast std::enable_if_t, bool> operator()(std::string& out, Enumeration in) { - out = std::to_string( - static_cast>(in)); + out = std::to_string(static_cast>(in)); return true; } }; @@ -52,14 +51,10 @@ struct LexicalCast { explicit LexicalCast() = default; - static_assert( - std::is_integral_v, - "beast::LexicalCast can only be used with integral types"); + static_assert(std::is_integral_v, "beast::LexicalCast can only be used with integral types"); template - std::enable_if_t< - std::is_integral_v && !std::is_same_v, - bool> + std::enable_if_t && !std::is_same_v, bool> operator()(Integral& out, std::string_view in) const { auto first = in.data(); @@ -79,10 +74,9 @@ struct LexicalCast std::string result; // Convert the input to lowercase - std::transform( - in.begin(), in.end(), std::back_inserter(result), [](auto c) { - return std::tolower(static_cast(c)); - }); + std::transform(in.begin(), in.end(), std::back_inserter(result), [](auto c) { + return std::tolower(static_cast(c)); + }); if (result == "1" || result == "true") { @@ -140,8 +134,7 @@ struct LexicalCast bool operator()(Out& out, char const* in) const { - XRPL_ASSERT( - in, "beast::detail::LexicalCast(char const*) : non-null input"); + XRPL_ASSERT(in, "beast::detail::LexicalCast(char const*) : non-null input"); return LexicalCast()(out, in); } }; diff --git a/include/xrpl/beast/core/List.h b/include/xrpl/beast/core/List.h index 9ea7994ffc..edd1b4530f 100644 --- a/include/xrpl/beast/core/List.h +++ b/include/xrpl/beast/core/List.h @@ -55,8 +55,7 @@ class ListIterator { public: using iterator_category = std::bidirectional_iterator_tag; - using value_type = - typename beast::detail::CopyConst::type; + using value_type = typename beast::detail::CopyConst::type; using difference_type = std::ptrdiff_t; using pointer = value_type*; using reference = value_type&; diff --git a/include/xrpl/beast/core/LockFreeStack.h b/include/xrpl/beast/core/LockFreeStack.h index 0d64667a76..7e358dccbd 100644 --- a/include/xrpl/beast/core/LockFreeStack.h +++ b/include/xrpl/beast/core/LockFreeStack.h @@ -14,21 +14,16 @@ class LockFreeStackIterator { protected: using Node = typename Container::Node; - using NodePtr = - typename std::conditional::type; + using NodePtr = typename std::conditional::type; public: using iterator_category = std::forward_iterator_tag; using value_type = typename Container::value_type; using difference_type = typename Container::difference_type; - using pointer = typename std::conditional< - IsConst, - typename Container::const_pointer, - typename Container::pointer>::type; - using reference = typename std::conditional< - IsConst, - typename Container::const_reference, - typename Container::reference>::type; + using pointer = + typename std::conditional::type; + using reference = + typename std::conditional::type; LockFreeStackIterator() : m_node() { @@ -39,9 +34,7 @@ public: } template - explicit LockFreeStackIterator( - LockFreeStackIterator const& other) - : m_node(other.m_node) + explicit LockFreeStackIterator(LockFreeStackIterator const& other) : m_node(other.m_node) { } @@ -160,8 +153,7 @@ public: using size_type = std::size_t; using difference_type = std::ptrdiff_t; using iterator = LockFreeStackIterator, false>; - using const_iterator = - LockFreeStackIterator, true>; + using const_iterator = LockFreeStackIterator, true>; LockFreeStack() : m_end(nullptr), m_head(&m_end) { @@ -199,11 +191,7 @@ public: { first = (old_head == &m_end); node->m_next = old_head; - } while (!m_head.compare_exchange_strong( - old_head, - node, - std::memory_order_release, - std::memory_order_relaxed)); + } while (!m_head.compare_exchange_strong(old_head, node, std::memory_order_release, std::memory_order_relaxed)); return first; } @@ -226,11 +214,7 @@ public: if (node == &m_end) return nullptr; new_head = node->m_next.load(); - } while (!m_head.compare_exchange_strong( - node, - new_head, - std::memory_order_release, - std::memory_order_relaxed)); + } while (!m_head.compare_exchange_strong(node, new_head, std::memory_order_release, std::memory_order_relaxed)); return static_cast(node); } diff --git a/include/xrpl/beast/hash/hash_append.h b/include/xrpl/beast/hash/hash_append.h index 28444a1280..f69931cb96 100644 --- a/include/xrpl/beast/hash/hash_append.h +++ b/include/xrpl/beast/hash/hash_append.h @@ -27,8 +27,7 @@ template inline void reverse_bytes(T& t) { - unsigned char* bytes = static_cast( - std::memmove(std::addressof(t), std::addressof(t), sizeof(T))); + unsigned char* bytes = static_cast(std::memmove(std::addressof(t), std::addressof(t), sizeof(T))); for (unsigned i = 0; i < sizeof(T) / 2; ++i) std::swap(bytes[i], bytes[sizeof(T) - 1 - i]); } @@ -53,11 +52,7 @@ template inline void maybe_reverse_bytes(T& t, Hasher&) { - maybe_reverse_bytes( - t, - std::integral_constant< - bool, - Hasher::endian != boost::endian::order::native>{}); + maybe_reverse_bytes(t, std::integral_constant{}); } } // namespace detail @@ -71,10 +66,8 @@ maybe_reverse_bytes(T& t, Hasher&) template struct is_uniquely_represented - : public std::integral_constant< - bool, - std::is_integral::value || std::is_enum::value || - std::is_pointer::value> + : public std:: + integral_constant::value || std::is_enum::value || std::is_pointer::value> { explicit is_uniquely_represented() = default; }; @@ -92,8 +85,7 @@ struct is_uniquely_represented : public is_uniquely_represented }; template -struct is_uniquely_represented - : public is_uniquely_represented +struct is_uniquely_represented : public is_uniquely_represented { explicit is_uniquely_represented() = default; }; @@ -104,8 +96,7 @@ template struct is_uniquely_represented> : public std::integral_constant< bool, - is_uniquely_represented::value && - is_uniquely_represented::value && + is_uniquely_represented::value && is_uniquely_represented::value && sizeof(T) + sizeof(U) == sizeof(std::pair)> { explicit is_uniquely_represented() = default; @@ -117,8 +108,7 @@ template struct is_uniquely_represented> : public std::integral_constant< bool, - std::conjunction_v...> && - sizeof(std::tuple) == (sizeof(T) + ...)> + std::conjunction_v...> && sizeof(std::tuple) == (sizeof(T) + ...)> { explicit is_uniquely_represented() = default; }; @@ -135,10 +125,8 @@ struct is_uniquely_represented : public is_uniquely_represented template struct is_uniquely_represented> - : public std::integral_constant< - bool, - is_uniquely_represented::value && - sizeof(T) * N == sizeof(std::array)> + : public std:: + integral_constant::value && sizeof(T) * N == sizeof(std::array)> { explicit is_uniquely_represented() = default; }; @@ -158,12 +146,10 @@ struct is_uniquely_represented> */ /** @{ */ template -struct is_contiguously_hashable - : public std::integral_constant< - bool, - is_uniquely_represented::value && - (sizeof(T) == 1 || - HashAlgorithm::endian == boost::endian::order::native)> +struct is_contiguously_hashable : public std::integral_constant< + bool, + is_uniquely_represented::value && + (sizeof(T) == 1 || HashAlgorithm::endian == boost::endian::order::native)> { explicit is_contiguously_hashable() = default; }; @@ -173,8 +159,7 @@ struct is_contiguously_hashable : public std::integral_constant< bool, is_uniquely_represented::value && - (sizeof(T) == 1 || - HashAlgorithm::endian == boost::endian::order::native)> + (sizeof(T) == 1 || HashAlgorithm::endian == boost::endian::order::native)> { explicit is_contiguously_hashable() = default; }; @@ -219,8 +204,7 @@ hash_append(Hasher& h, T const& t) noexcept template inline std::enable_if_t< !is_contiguously_hashable::value && - (std::is_integral::value || std::is_pointer::value || - std::is_enum::value)> + (std::is_integral::value || std::is_pointer::value || std::is_enum::value)> hash_append(Hasher& h, T t) noexcept { detail::reverse_bytes(t); @@ -254,15 +238,11 @@ hash_append(Hasher& h, T (&a)[N]) noexcept; template std::enable_if_t::value> -hash_append( - Hasher& h, - std::basic_string const& s) noexcept; +hash_append(Hasher& h, std::basic_string const& s) noexcept; template std::enable_if_t::value> -hash_append( - Hasher& h, - std::basic_string const& s) noexcept; +hash_append(Hasher& h, std::basic_string const& s) noexcept; template std::enable_if_t, Hasher>::value> @@ -294,14 +274,10 @@ hash_append(Hasher& h, std::unordered_set const& s); template std::enable_if_t::value> -hash_append( - Hasher& h, - boost::container::flat_set const& v) noexcept; +hash_append(Hasher& h, boost::container::flat_set const& v) noexcept; template std::enable_if_t::value> -hash_append( - Hasher& h, - boost::container::flat_set const& v) noexcept; +hash_append(Hasher& h, boost::container::flat_set const& v) noexcept; template void hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept; @@ -320,9 +296,7 @@ hash_append(Hasher& h, T (&a)[N]) noexcept template inline std::enable_if_t::value> -hash_append( - Hasher& h, - std::basic_string const& s) noexcept +hash_append(Hasher& h, std::basic_string const& s) noexcept { for (auto c : s) hash_append(h, c); @@ -331,9 +305,7 @@ hash_append( template inline std::enable_if_t::value> -hash_append( - Hasher& h, - std::basic_string const& s) noexcept +hash_append(Hasher& h, std::basic_string const& s) noexcept { h(s.data(), s.size() * sizeof(CharT)); hash_append(h, s.size()); @@ -342,8 +314,7 @@ hash_append( // pair template -inline std::enable_if_t< - !is_contiguously_hashable, Hasher>::value> +inline std::enable_if_t, Hasher>::value> hash_append(Hasher& h, std::pair const& p) noexcept { hash_append(h, p.first, p.second); @@ -380,18 +351,14 @@ hash_append(Hasher& h, std::array const& a) noexcept template std::enable_if_t::value> -hash_append( - Hasher& h, - boost::container::flat_set const& v) noexcept +hash_append(Hasher& h, boost::container::flat_set const& v) noexcept { for (auto const& t : v) hash_append(h, t); } template std::enable_if_t::value> -hash_append( - Hasher& h, - boost::container::flat_set const& v) noexcept +hash_append(Hasher& h, boost::container::flat_set const& v) noexcept { h(&(v.begin()), v.size() * sizeof(Key)); } @@ -414,10 +381,7 @@ hash_one(Hasher& h, T const& t) noexcept template inline void -tuple_hash( - Hasher& h, - std::tuple const& t, - std::index_sequence) noexcept +tuple_hash(Hasher& h, std::tuple const& t, std::index_sequence) noexcept { for_each_item(hash_one(h, std::get(t))...); } @@ -425,8 +389,7 @@ tuple_hash( } // namespace detail template -inline std::enable_if_t< - !is_contiguously_hashable, Hasher>::value> +inline std::enable_if_t, Hasher>::value> hash_append(Hasher& h, std::tuple const& t) noexcept { detail::tuple_hash(h, t, std::index_sequence_for{}); @@ -452,9 +415,7 @@ hash_append(Hasher& h, std::chrono::duration const& d) noexcept template inline void -hash_append( - Hasher& h, - std::chrono::time_point const& tp) noexcept +hash_append(Hasher& h, std::chrono::time_point const& tp) noexcept { hash_append(h, tp.time_since_epoch()); } diff --git a/include/xrpl/beast/hash/xxhasher.h b/include/xrpl/beast/hash/xxhasher.h index 67169f85ec..098551f02e 100644 --- a/include/xrpl/beast/hash/xxhasher.h +++ b/include/xrpl/beast/hash/xxhasher.h @@ -49,8 +49,7 @@ private: { std::memcpy(writeBuffer_.data(), data, len); writeBuffer_ = writeBuffer_.subspan(len); - readBuffer_ = std::span{ - std::begin(buffer_), buffer_.size() - writeBuffer_.size()}; + readBuffer_ = std::span{std::begin(buffer_), buffer_.size() - writeBuffer_.size()}; } } @@ -98,8 +97,7 @@ private: { if (seed_.has_value()) { - return XXH3_64bits_withSeed( - readBuffer_.data(), readBuffer_.size(), *seed_); + return XXH3_64bits_withSeed(readBuffer_.data(), readBuffer_.size(), *seed_); } else { @@ -128,17 +126,13 @@ public: } } - template < - class Seed, - std::enable_if_t::value>* = nullptr> + template ::value>* = nullptr> explicit xxhasher(Seed seed) : seed_(seed) { resetBuffers(); } - template < - class Seed, - std::enable_if_t::value>* = nullptr> + template ::value>* = nullptr> xxhasher(Seed seed, Seed) : seed_(seed) { resetBuffers(); diff --git a/include/xrpl/beast/insight/StatsDCollector.h b/include/xrpl/beast/insight/StatsDCollector.h index 092b008709..9c63ab4ed9 100644 --- a/include/xrpl/beast/insight/StatsDCollector.h +++ b/include/xrpl/beast/insight/StatsDCollector.h @@ -23,9 +23,7 @@ public: @param journal Destination for logging output. */ static std::shared_ptr - New(IP::Endpoint const& address, - std::string const& prefix, - Journal journal); + New(IP::Endpoint const& address, std::string const& prefix, Journal journal); }; } // namespace insight diff --git a/include/xrpl/beast/rfc2616.h b/include/xrpl/beast/rfc2616.h index 145a22bad1..922e4a7dc4 100644 --- a/include/xrpl/beast/rfc2616.h +++ b/include/xrpl/beast/rfc2616.h @@ -26,8 +26,7 @@ struct ci_equal_pred operator()(char c1, char c2) { // VFALCO TODO Use a table lookup here - return std::tolower(static_cast(c1)) == - std::tolower(static_cast(c2)); + return std::tolower(static_cast(c1)) == std::tolower(static_cast(c2)); } }; @@ -97,8 +96,7 @@ trim_right(String const& s) */ template < class FwdIt, - class Result = std::vector< - std::basic_string::value_type>>, + class Result = std::vector::value_type>>, class Char> Result split(FwdIt first, FwdIt last, Char delim) @@ -172,10 +170,7 @@ split(FwdIt first, FwdIt last, Char delim) return result; } -template < - class FwdIt, - class Result = std::vector< - std::basic_string::value_type>>> +template ::value_type>>> Result split_commas(FwdIt first, FwdIt last) { @@ -223,8 +218,7 @@ public: bool operator==(list_iterator const& other) const { - return other.it_ == it_ && other.end_ == end_ && - other.value_.size() == value_.size(); + return other.it_ == it_ && other.end_ == end_ && other.value_.size() == value_.size(); } bool @@ -288,14 +282,12 @@ list_iterator::increment() ++it_; if (it_ == end_) { - value_ = boost::string_ref( - &*start, std::distance(start, it_)); + value_ = boost::string_ref(&*start, std::distance(start, it_)); return; } if (*it_ == '"') { - value_ = boost::string_ref( - &*start, std::distance(start, it_)); + value_ = boost::string_ref(&*start, std::distance(start, it_)); ++it_; return; } @@ -321,8 +313,7 @@ list_iterator::increment() ++it_; if (it_ == end_ || *it_ == ',' || is_lws(*it_)) { - value_ = - boost::string_ref(&*start, std::distance(start, it_)); + value_ = boost::string_ref(&*start, std::distance(start, it_)); return; } } @@ -344,8 +335,7 @@ inline boost::iterator_range make_list(boost::string_ref const& field) { return boost::iterator_range{ - list_iterator{field.begin(), field.end()}, - list_iterator{field.end(), field.end()}}; + list_iterator{field.begin(), field.end()}, list_iterator{field.end(), field.end()}}; } /** Returns true if the specified token exists in the list. @@ -367,12 +357,8 @@ bool is_keep_alive(boost::beast::http::message const& m) { if (m.version() <= 10) - return boost::beast::http::token_list{ - m[boost::beast::http::field::connection]} - .exists("keep-alive"); - return !boost::beast::http::token_list{ - m[boost::beast::http::field::connection]} - .exists("close"); + return boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists("keep-alive"); + return !boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists("close"); } } // namespace rfc2616 diff --git a/include/xrpl/beast/test/yield_to.h b/include/xrpl/beast/test/yield_to.h index 037c33e470..b20661bdca 100644 --- a/include/xrpl/beast/test/yield_to.h +++ b/include/xrpl/beast/test/yield_to.h @@ -31,9 +31,7 @@ protected: boost::asio::io_context ios_; private: - boost::optional> - work_; + boost::optional> work_; std::vector threads_; std::mutex m_; std::condition_variable cv_; @@ -43,8 +41,7 @@ public: /// The type of yield context passed to functions. using yield_context = boost::asio::yield_context; - explicit enable_yield_to(std::size_t concurrency = 1) - : work_(boost::asio::make_work_guard(ios_)) + explicit enable_yield_to(std::size_t concurrency = 1) : work_(boost::asio::make_work_guard(ios_)) { threads_.reserve(concurrency); while (concurrency--) diff --git a/include/xrpl/beast/unit_test/global_suites.h b/include/xrpl/beast/unit_test/global_suites.h index 5bcba5fa68..0492d5fb4b 100644 --- a/include/xrpl/beast/unit_test/global_suites.h +++ b/include/xrpl/beast/unit_test/global_suites.h @@ -23,12 +23,7 @@ global_suites() template struct insert_suite { - insert_suite( - char const* name, - char const* module, - char const* library, - bool manual, - int priority) + insert_suite(char const* name, char const* module, char const* library, bool manual, int priority) { global_suites().insert(name, module, library, manual, priority); } diff --git a/include/xrpl/beast/unit_test/match.h b/include/xrpl/beast/unit_test/match.h index 0556aaab27..d88ccb7497 100644 --- a/include/xrpl/beast/unit_test/match.h +++ b/include/xrpl/beast/unit_test/match.h @@ -53,8 +53,7 @@ public: //------------------------------------------------------------------------------ template -selector::selector(mode_t mode, std::string const& pattern) - : mode_(mode), pat_(pattern) +selector::selector(mode_t mode, std::string const& pattern) : mode_(mode), pat_(pattern) { if (mode_ == automatch && pattern.empty()) mode_ = all; diff --git a/include/xrpl/beast/unit_test/reporter.h b/include/xrpl/beast/unit_test/reporter.h index 4ea662e30e..adec49c8d4 100644 --- a/include/xrpl/beast/unit_test/reporter.h +++ b/include/xrpl/beast/unit_test/reporter.h @@ -140,10 +140,7 @@ reporter<_>::results::add(suite_results const& r) if (elapsed >= std::chrono::seconds{1}) { auto const iter = std::lower_bound( - top.begin(), - top.end(), - elapsed, - [](run_time const& t1, typename clock_type::duration const& t2) { + top.begin(), top.end(), elapsed, [](run_time const& t1, typename clock_type::duration const& t2) { return t1.second > t2; }); if (iter != top.end()) @@ -176,10 +173,8 @@ reporter<_>::~reporter() os_ << std::setw(8) << fmtdur(i.second) << " " << i.first << '\n'; } auto const elapsed = clock_type::now() - results_.start; - os_ << fmtdur(elapsed) << ", " << amount{results_.suites, "suite"} << ", " - << amount{results_.cases, "case"} << ", " - << amount{results_.total, "test"} << " total, " - << amount{results_.failed, "failure"} << std::endl; + os_ << fmtdur(elapsed) << ", " << amount{results_.suites, "suite"} << ", " << amount{results_.cases, "case"} << ", " + << amount{results_.total, "test"} << " total, " << amount{results_.failed, "failure"} << std::endl; } template @@ -214,9 +209,7 @@ void reporter<_>::on_case_begin(std::string const& name) { case_results_ = case_results(name); - os_ << suite_results_.name - << (case_results_.name.empty() ? "" : (" " + case_results_.name)) - << std::endl; + os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name)) << std::endl; } template @@ -239,8 +232,7 @@ reporter<_>::on_fail(std::string const& reason) { ++case_results_.failed; ++case_results_.total; - os_ << "#" << case_results_.total << " failed" - << (reason.empty() ? "" : ": ") << reason << std::endl; + os_ << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason << std::endl; } template diff --git a/include/xrpl/beast/unit_test/results.h b/include/xrpl/beast/unit_test/results.h index 5cc0d3fc5c..478812eff9 100644 --- a/include/xrpl/beast/unit_test/results.h +++ b/include/xrpl/beast/unit_test/results.h @@ -24,8 +24,7 @@ public: { } - test(bool pass_, std::string const& reason_) - : pass(pass_), reason(reason_) + test(bool pass_, std::string const& reason_) : pass(pass_), reason(reason_) { } diff --git a/include/xrpl/beast/unit_test/suite.h b/include/xrpl/beast/unit_test/suite.h index c80b336cfe..70c2d49fbd 100644 --- a/include/xrpl/beast/unit_test/suite.h +++ b/include/xrpl/beast/unit_test/suite.h @@ -92,17 +92,13 @@ private: } }; - template < - class CharT, - class Traits = std::char_traits, - class Allocator = std::allocator> + template , class Allocator = std::allocator> class log_os : public std::basic_ostream { log_buf buf_; public: - explicit log_os(suite& self) - : std::basic_ostream(&buf_), buf_(self) + explicit log_os(suite& self) : std::basic_ostream(&buf_), buf_(self) { } }; @@ -241,11 +237,7 @@ public: template bool - expect( - Condition const& shouldBeTrue, - String const& reason, - char const* file, - int line); + expect(Condition const& shouldBeTrue, String const& reason, char const* file, int line); /** @} */ // @@ -349,8 +341,7 @@ public: } template - scoped_testcase(suite& self, std::stringstream& ss, T const& t) - : suite_(self), ss_(ss) + scoped_testcase(suite& self, std::stringstream& ss, T const& t) : suite_(self), ss_(ss) { ss_.clear(); ss_.str({}); @@ -423,11 +414,7 @@ suite::expect(Condition const& shouldBeTrue, String const& reason) template bool -suite::expect( - Condition const& shouldBeTrue, - String const& reason, - char const* file, - int line) +suite::expect(Condition const& shouldBeTrue, String const& reason, char const* file, int line) { if (shouldBeTrue) { @@ -576,8 +563,7 @@ suite::run(runner& r) If the condition is false, the file and line number are reported. */ -#define BEAST_EXPECTS(cond, reason) \ - ((cond) ? (pass(), true) : (fail((reason), __FILE__, __LINE__), false)) +#define BEAST_EXPECTS(cond, reason) ((cond) ? (pass(), true) : (fail((reason), __FILE__, __LINE__), false)) #endif } // namespace unit_test @@ -587,11 +573,9 @@ suite::run(runner& r) // detail: // This inserts the suite with the given manual flag -#define BEAST_DEFINE_TESTSUITE_INSERT( \ - Class, Module, Library, manual, priority) \ - static beast::unit_test::detail::insert_suite \ - Library##Module##Class##_test_instance( \ - #Class, #Module, #Library, manual, priority) +#define BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, manual, priority) \ + static beast::unit_test::detail::insert_suite Library##Module##Class##_test_instance( \ + #Class, #Module, #Library, manual, priority) //------------------------------------------------------------------------------ @@ -646,8 +630,7 @@ suite::run(runner& r) #else #include -#define BEAST_DEFINE_TESTSUITE(Class, Module, Library) \ - BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, false, 0) +#define BEAST_DEFINE_TESTSUITE(Class, Module, Library) BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, false, 0) #define BEAST_DEFINE_TESTSUITE_MANUAL(Class, Module, Library) \ BEAST_DEFINE_TESTSUITE_INSERT(Class, Module, Library, true, 0) #define BEAST_DEFINE_TESTSUITE_PRIO(Class, Module, Library, Priority) \ diff --git a/include/xrpl/beast/unit_test/suite_info.h b/include/xrpl/beast/unit_test/suite_info.h index 078886a86e..5297c0e807 100644 --- a/include/xrpl/beast/unit_test/suite_info.h +++ b/include/xrpl/beast/unit_test/suite_info.h @@ -28,13 +28,7 @@ class suite_info run_type run_; public: - suite_info( - std::string name, - std::string module, - std::string library, - bool manual, - int priority, - run_type run) + suite_info(std::string name, std::string module, std::string library, bool manual, int priority, run_type run) : name_(std::move(name)) , module_(std::move(module)) , library_(std::move(library)) @@ -88,10 +82,8 @@ public: { // we want higher priority suites sorted first, thus the negation // of priority value here - return std::forward_as_tuple( - -lhs.priority_, lhs.library_, lhs.module_, lhs.name_) < - std::forward_as_tuple( - -rhs.priority_, rhs.library_, rhs.module_, rhs.name_); + return std::forward_as_tuple(-lhs.priority_, lhs.library_, lhs.module_, lhs.name_) < + std::forward_as_tuple(-rhs.priority_, rhs.library_, rhs.module_, rhs.name_); } }; @@ -100,20 +92,10 @@ public: /// Convenience for producing suite_info for a given test type. template suite_info -make_suite_info( - std::string name, - std::string module, - std::string library, - bool manual, - int priority) +make_suite_info(std::string name, std::string module, std::string library, bool manual, int priority) { return suite_info( - std::move(name), - std::move(module), - std::move(library), - manual, - priority, - [](runner& r) { Suite{}(r); }); + std::move(name), std::move(module), std::move(library), manual, priority, [](runner& r) { Suite{}(r); }); } } // namespace unit_test diff --git a/include/xrpl/beast/unit_test/suite_list.h b/include/xrpl/beast/unit_test/suite_list.h index be265e6145..49bf37cbc6 100644 --- a/include/xrpl/beast/unit_test/suite_list.h +++ b/include/xrpl/beast/unit_test/suite_list.h @@ -33,24 +33,14 @@ public: */ template void - insert( - char const* name, - char const* module, - char const* library, - bool manual, - int priority); + insert(char const* name, char const* module, char const* library, bool manual, int priority); }; //------------------------------------------------------------------------------ template void -suite_list::insert( - char const* name, - char const* module, - char const* library, - bool manual, - int priority) +suite_list::insert(char const* name, char const* module, char const* library, bool manual, int priority) { #ifndef NDEBUG { @@ -65,8 +55,7 @@ suite_list::insert( BOOST_ASSERT(result.second); // Duplicate type } #endif - cont().emplace( - make_suite_info(name, module, library, manual, priority)); + cont().emplace(make_suite_info(name, module, library, manual, priority)); } } // namespace unit_test diff --git a/include/xrpl/beast/unit_test/thread.h b/include/xrpl/beast/unit_test/thread.h index 4b70c308d1..27c3f85920 100644 --- a/include/xrpl/beast/unit_test/thread.h +++ b/include/xrpl/beast/unit_test/thread.h @@ -45,8 +45,7 @@ public: template explicit thread(suite& s, F&& f, Args&&... args) : s_(&s) { - std::function b = - std::bind(std::forward(f), std::forward(args)...); + std::function b = std::bind(std::forward(f), std::forward(args)...); t_ = std::thread(&thread::run, this, std::move(b)); } diff --git a/include/xrpl/beast/utility/Journal.h b/include/xrpl/beast/utility/Journal.h index a02a62fc45..7eaf4a627a 100644 --- a/include/xrpl/beast/utility/Journal.h +++ b/include/xrpl/beast/utility/Journal.h @@ -130,8 +130,7 @@ public: class ScopedStream { public: - ScopedStream(ScopedStream const& other) - : ScopedStream(other.m_sink, other.m_level) + ScopedStream(ScopedStream const& other) : ScopedStream(other.m_sink, other.m_level) { } @@ -167,16 +166,12 @@ public: }; #ifndef __INTELLISENSE__ - static_assert( - std::is_default_constructible::value == false, - ""); + static_assert(std::is_default_constructible::value == false, ""); static_assert(std::is_copy_constructible::value == true, ""); static_assert(std::is_move_constructible::value == true, ""); static_assert(std::is_copy_assignable::value == false, ""); static_assert(std::is_move_assignable::value == false, ""); - static_assert( - std::is_nothrow_destructible::value == true, - ""); + static_assert(std::is_nothrow_destructible::value == true, ""); #endif //-------------------------------------------------------------------------- @@ -186,8 +181,7 @@ public: { public: /** Create a stream which produces no output. */ - explicit Stream() - : m_sink(getNullSink()), m_level(severities::kDisabled) + explicit Stream() : m_sink(getNullSink()), m_level(severities::kDisabled) { } @@ -197,9 +191,7 @@ public: */ Stream(Sink& sink, Severity level) : m_sink(sink), m_level(level) { - XRPL_ASSERT( - m_level < severities::kDisabled, - "beast::Journal::Stream::Stream : maximum level"); + XRPL_ASSERT(m_level < severities::kDisabled, "beast::Journal::Stream::Stream : maximum level"); } /** Construct or copy another Stream. */ @@ -430,8 +422,7 @@ class basic_logstream : public std::basic_ostream detail::logstream_buf buf_; public: - explicit basic_logstream(beast::Journal::Stream const& strm) - : std::basic_ostream(&buf_), buf_(strm) + explicit basic_logstream(beast::Journal::Stream const& strm) : std::basic_ostream(&buf_), buf_(strm) { } }; diff --git a/include/xrpl/beast/utility/WrappedSink.h b/include/xrpl/beast/utility/WrappedSink.h index eb2f103c17..7819134e01 100644 --- a/include/xrpl/beast/utility/WrappedSink.h +++ b/include/xrpl/beast/utility/WrappedSink.h @@ -18,16 +18,12 @@ private: std::string prefix_; public: - explicit WrappedSink( - beast::Journal::Sink& sink, - std::string const& prefix = "") + explicit WrappedSink(beast::Journal::Sink& sink, std::string const& prefix = "") : Sink(sink), sink_(sink), prefix_(prefix) { } - explicit WrappedSink( - beast::Journal const& journal, - std::string const& prefix = "") + explicit WrappedSink(beast::Journal const& journal, std::string const& prefix = "") : WrappedSink(journal.sink(), prefix) { } diff --git a/include/xrpl/beast/utility/instrumentation.h b/include/xrpl/beast/utility/instrumentation.h index 3c364b64e6..b2dcd23a3a 100644 --- a/include/xrpl/beast/utility/instrumentation.h +++ b/include/xrpl/beast/utility/instrumentation.h @@ -20,8 +20,7 @@ #endif #define XRPL_ASSERT ALWAYS_OR_UNREACHABLE -#define XRPL_ASSERT_PARTS(cond, function, description, ...) \ - XRPL_ASSERT(cond, function " : " description) +#define XRPL_ASSERT_PARTS(cond, function, description, ...) XRPL_ASSERT(cond, function " : " description) // How to use the instrumentation macros: // diff --git a/include/xrpl/beast/utility/maybe_const.h b/include/xrpl/beast/utility/maybe_const.h index bc5f4fe83a..6c577d3c76 100644 --- a/include/xrpl/beast/utility/maybe_const.h +++ b/include/xrpl/beast/utility/maybe_const.h @@ -10,10 +10,8 @@ template struct maybe_const { explicit maybe_const() = default; - using type = typename std::conditional< - IsConst, - typename std::remove_const::type const, - typename std::remove_const::type>::type; + using type = typename std:: + conditional::type const, typename std::remove_const::type>::type; }; /** Alias for omitting `typename`. */ diff --git a/include/xrpl/beast/utility/rngfill.h b/include/xrpl/beast/utility/rngfill.h index 3fd0c12f0d..ba596b789b 100644 --- a/include/xrpl/beast/utility/rngfill.h +++ b/include/xrpl/beast/utility/rngfill.h @@ -36,10 +36,7 @@ rngfill(void* const buffer, std::size_t const bytes, Generator& g) } } -template < - class Generator, - std::size_t N, - class = std::enable_if_t> +template > void rngfill(std::array& a, Generator& g) { diff --git a/include/xrpl/core/ClosureCounter.h b/include/xrpl/core/ClosureCounter.h index d2be76fa8c..4127960276 100644 --- a/include/xrpl/core/ClosureCounter.h +++ b/include/xrpl/core/ClosureCounter.h @@ -76,21 +76,18 @@ private: std::remove_reference_t closure_; static_assert( - std::is_same()...)), Ret_t>:: - value, + std::is_same()...)), Ret_t>::value, "Closure arguments don't match ClosureCounter Ret_t or Args_t"); public: Substitute() = delete; - Substitute(Substitute const& rhs) - : counter_(rhs.counter_), closure_(rhs.closure_) + Substitute(Substitute const& rhs) : counter_(rhs.counter_), closure_(rhs.closure_) { ++counter_; } - Substitute(Substitute&& rhs) noexcept( - std::is_nothrow_move_constructible::value) + Substitute(Substitute&& rhs) noexcept(std::is_nothrow_move_constructible::value) : counter_(rhs.counter_), closure_(std::move(rhs.closure_)) { ++counter_; @@ -150,13 +147,11 @@ public: waitForClosures_ = true; if (closureCount_ > 0) { - if (!allClosuresDoneCond_.wait_for( - lock, wait, [this] { return closureCount_ == 0; })) + if (!allClosuresDoneCond_.wait_for(lock, wait, [this] { return closureCount_ == 0; })) { if (auto stream = j.error()) stream << name << " waiting for ClosureCounter::join()."; - allClosuresDoneCond_.wait( - lock, [this] { return closureCount_ == 0; }); + allClosuresDoneCond_.wait(lock, [this] { return closureCount_ == 0; }); } } } diff --git a/include/xrpl/core/Coro.ipp b/include/xrpl/core/Coro.ipp index 9f73d80647..40067a77e9 100644 --- a/include/xrpl/core/Coro.ipp +++ b/include/xrpl/core/Coro.ipp @@ -6,20 +6,13 @@ namespace xrpl { template -JobQueue::Coro::Coro( - Coro_create_t, - JobQueue& jq, - JobType type, - std::string const& name, - F&& f) +JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string const& name, F&& f) : jq_(jq) , type_(type) , name_(name) , running_(false) , coro_( - [this, fn = std::forward(f)]( - boost::coroutines::asymmetric_coroutine::push_type& - do_yield) { + [this, fn = std::forward(f)](boost::coroutines::asymmetric_coroutine::push_type& do_yield) { yield_ = &do_yield; yield(); fn(shared_from_this()); @@ -57,8 +50,7 @@ JobQueue::Coro::post() } // sp keeps 'this' alive - if (jq_.addJob( - type_, name_, [this, sp = shared_from_this()]() { resume(); })) + if (jq_.addJob(type_, name_, [this, sp = shared_from_this()]() { resume(); })) { return true; } @@ -84,8 +76,7 @@ JobQueue::Coro::resume() auto saved = detail::getLocalValues().release(); detail::getLocalValues().reset(&lvs_); std::lock_guard lock(mutex_); - XRPL_ASSERT( - static_cast(coro_), "xrpl::JobQueue::Coro::resume : is runnable"); + XRPL_ASSERT(static_cast(coro_), "xrpl::JobQueue::Coro::resume : is runnable"); coro_(); detail::getLocalValues().release(); detail::getLocalValues().reset(saved); diff --git a/include/xrpl/core/Job.h b/include/xrpl/core/Job.h index cb597b3860..dd60391635 100644 --- a/include/xrpl/core/Job.h +++ b/include/xrpl/core/Job.h @@ -93,11 +93,7 @@ public: Job(JobType type, std::uint64_t index); // VFALCO TODO try to remove the dependency on LoadMonitor. - Job(JobType type, - std::string const& name, - std::uint64_t index, - LoadMonitor& lm, - std::function const& job); + Job(JobType type, std::string const& name, std::uint64_t index, LoadMonitor& lm, std::function const& job); JobType getType() const; diff --git a/include/xrpl/core/JobQueue.h b/include/xrpl/core/JobQueue.h index 2a22b7f5c9..48c92146f2 100644 --- a/include/xrpl/core/JobQueue.h +++ b/include/xrpl/core/JobQueue.h @@ -141,14 +141,11 @@ public: */ template < typename JobHandler, - typename = std::enable_if_t()()), - void>::value>> + typename = std::enable_if_t()()), void>::value>> bool addJob(JobType type, std::string const& name, JobHandler&& jobHandler) { - if (auto optionalCountedJob = - jobCounter_.wrap(std::forward(jobHandler))) + if (auto optionalCountedJob = jobCounter_.wrap(std::forward(jobHandler))) { return addRefCountedJob(type, name, std::move(*optionalCountedJob)); } @@ -264,10 +261,7 @@ private: // // return true if func added to queue. bool - addRefCountedJob( - JobType type, - std::string const& name, - JobFunction const& func); + addRefCountedJob(JobType type, std::string const& name, JobFunction const& func); // Returns the next Job we should run now. // @@ -396,8 +390,7 @@ JobQueue::postCoro(JobType t, std::string const& name, F&& f) Last param is the function the coroutine runs. Signature of void(std::shared_ptr). */ - auto coro = std::make_shared( - Coro_create_t{}, *this, t, name, std::forward(f)); + auto coro = std::make_shared(Coro_create_t{}, *this, t, name, std::forward(f)); if (!coro->post()) { // The Coro was not successfully posted. Disable it so it's destructor diff --git a/include/xrpl/core/JobTypeData.h b/include/xrpl/core/JobTypeData.h index 377309aa3c..e15e161e0e 100644 --- a/include/xrpl/core/JobTypeData.h +++ b/include/xrpl/core/JobTypeData.h @@ -32,19 +32,10 @@ public: beast::insight::Event dequeue; beast::insight::Event execute; - JobTypeData( - JobTypeInfo const& info_, - beast::insight::Collector::ptr const& collector, - Logs& logs) noexcept - : m_load(logs.journal("LoadMonitor")) - , m_collector(collector) - , info(info_) - , waiting(0) - , running(0) - , deferred(0) + JobTypeData(JobTypeInfo const& info_, beast::insight::Collector::ptr const& collector, Logs& logs) noexcept + : m_load(logs.journal("LoadMonitor")), m_collector(collector), info(info_), waiting(0), running(0), deferred(0) { - m_load.setTargetLatency( - info.getAverageLatency(), info.getPeakLatency()); + m_load.setTargetLatency(info.getAverageLatency(), info.getPeakLatency()); if (!info.special()) { diff --git a/include/xrpl/core/JobTypeInfo.h b/include/xrpl/core/JobTypeInfo.h index a726fb276b..e9525fed81 100644 --- a/include/xrpl/core/JobTypeInfo.h +++ b/include/xrpl/core/JobTypeInfo.h @@ -33,11 +33,7 @@ public: int limit, std::chrono::milliseconds avgLatency, std::chrono::milliseconds peakLatency) - : m_type(type) - , m_name(std::move(name)) - , m_limit(limit) - , m_avgLatency(avgLatency) - , m_peakLatency(peakLatency) + : m_type(type), m_name(std::move(name)), m_limit(limit), m_avgLatency(avgLatency), m_peakLatency(peakLatency) { } diff --git a/include/xrpl/core/JobTypes.h b/include/xrpl/core/JobTypes.h index f7952ca9a2..4a779507f1 100644 --- a/include/xrpl/core/JobTypes.h +++ b/include/xrpl/core/JobTypes.h @@ -16,13 +16,7 @@ public: using const_iterator = Map::const_iterator; private: - JobTypes() - : m_unknown( - jtINVALID, - "invalid", - 0, - std::chrono::milliseconds{0}, - std::chrono::milliseconds{0}) + JobTypes() : m_unknown(jtINVALID, "invalid", 0, std::chrono::milliseconds{0}, std::chrono::milliseconds{0}) { using namespace std::chrono_literals; int maxLimit = std::numeric_limits::max(); @@ -33,22 +27,17 @@ private: int limit, std::chrono::milliseconds avgLatency, std::chrono::milliseconds peakLatency) { - XRPL_ASSERT( - m_map.find(jt) == m_map.end(), - "xrpl::JobTypes::JobTypes::add : unique job type input"); + XRPL_ASSERT(m_map.find(jt) == m_map.end(), "xrpl::JobTypes::JobTypes::add : unique job type input"); [[maybe_unused]] auto const inserted = m_map .emplace( std::piecewise_construct, std::forward_as_tuple(jt), - std::forward_as_tuple( - jt, name, limit, avgLatency, peakLatency)) + std::forward_as_tuple(jt, name, limit, avgLatency, peakLatency)) .second; - XRPL_ASSERT( - inserted == true, - "xrpl::JobTypes::JobTypes::add : input is inserted"); + XRPL_ASSERT(inserted == true, "xrpl::JobTypes::JobTypes::add : input is inserted"); }; // clang-format off diff --git a/include/xrpl/core/LoadMonitor.h b/include/xrpl/core/LoadMonitor.h index 54cd607d5b..3b79a0ea23 100644 --- a/include/xrpl/core/LoadMonitor.h +++ b/include/xrpl/core/LoadMonitor.h @@ -27,9 +27,7 @@ public: addSamples(int count, std::chrono::milliseconds latency); void - setTargetLatency( - std::chrono::milliseconds avg, - std::chrono::milliseconds pk); + setTargetLatency(std::chrono::milliseconds avg, std::chrono::milliseconds pk); bool isOverTarget(std::chrono::milliseconds avg, std::chrono::milliseconds peak); diff --git a/include/xrpl/core/PerfLog.h b/include/xrpl/core/PerfLog.h index f8ca779963..bc788f86b8 100644 --- a/include/xrpl/core/PerfLog.h +++ b/include/xrpl/core/PerfLog.h @@ -105,11 +105,7 @@ public: * @param instance JobQueue worker thread instance */ virtual void - jobStart( - JobType const type, - microseconds dur, - steady_time_point startTime, - int instance) = 0; + jobStart(JobType const type, microseconds dur, steady_time_point startTime, int instance) = 0; /** * Log job finishing @@ -156,11 +152,7 @@ PerfLog::Setup setup_PerfLog(Section const& section, boost::filesystem::path const& configDir); std::unique_ptr -make_PerfLog( - PerfLog::Setup const& setup, - Application& app, - beast::Journal journal, - std::function&& signalStop); +make_PerfLog(PerfLog::Setup const& setup, Application& app, beast::Journal journal, std::function&& signalStop); template auto @@ -175,12 +167,10 @@ measureDurationAndLog( auto result = func(); auto end_time = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast( - end_time - start_time); + auto duration = std::chrono::duration_cast(end_time - start_time); if (duration > maxDelay) { - JLOG(journal.warn()) - << actionDescription << " took " << duration.count() << " ms"; + JLOG(journal.warn()) << actionDescription << " took " << duration.count() << " ms"; } return result; diff --git a/include/xrpl/core/detail/Workers.h b/include/xrpl/core/detail/Workers.h index 3a77f9e769..185586e859 100644 --- a/include/xrpl/core/detail/Workers.h +++ b/include/xrpl/core/detail/Workers.h @@ -95,8 +95,7 @@ public: Callback& callback, perf::PerfLog* perfLog, std::string const& threadNames = "Worker", - int numberOfThreads = - static_cast(std::thread::hardware_concurrency())); + int numberOfThreads = static_cast(std::thread::hardware_concurrency())); ~Workers(); @@ -162,14 +161,10 @@ private: Idle: Active, but blocked on waiting for a task. Paused: Blocked waiting to exit or become active. */ - class Worker : public beast::LockFreeStack::Node, - public beast::LockFreeStack::Node + class Worker : public beast::LockFreeStack::Node, public beast::LockFreeStack::Node { public: - Worker( - Workers& workers, - std::string const& threadName, - int const instance); + Worker(Workers& workers, std::string const& threadName, int const instance); ~Worker(); @@ -203,15 +198,13 @@ private: std::condition_variable m_cv; // signaled when all threads paused std::mutex m_mut; bool m_allPaused; - semaphore m_semaphore; // each pending task is 1 resource - int m_numberOfThreads; // how many we want active now - std::atomic m_activeCount; // to know when all are paused - std::atomic m_pauseCount; // how many threads need to pause now - std::atomic - m_runningTaskCount; // how many calls to processTask() active - beast::LockFreeStack m_everyone; // holds all created workers - beast::LockFreeStack - m_paused; // holds just paused workers + semaphore m_semaphore; // each pending task is 1 resource + int m_numberOfThreads; // how many we want active now + std::atomic m_activeCount; // to know when all are paused + std::atomic m_pauseCount; // how many threads need to pause now + std::atomic m_runningTaskCount; // how many calls to processTask() active + beast::LockFreeStack m_everyone; // holds all created workers + beast::LockFreeStack m_paused; // holds just paused workers }; } // namespace xrpl diff --git a/include/xrpl/json/Output.h b/include/xrpl/json/Output.h index cdfa674014..db990ab364 100644 --- a/include/xrpl/json/Output.h +++ b/include/xrpl/json/Output.h @@ -15,9 +15,7 @@ using Output = std::function; inline Output stringOutput(std::string& s) { - return [&](boost::beast::string_view const& b) { - s.append(b.data(), b.size()); - }; + return [&](boost::beast::string_view const& b) { s.append(b.data(), b.size()); }; } /** Writes a minimal representation of a Json value to an Output in O(n) time. diff --git a/include/xrpl/json/json_reader.h b/include/xrpl/json/json_reader.h index 2a8ec5a3fe..814d62dd88 100644 --- a/include/xrpl/json/json_reader.h +++ b/include/xrpl/json/json_reader.h @@ -144,26 +144,15 @@ private: bool decodeDouble(Token& token); bool - decodeUnicodeCodePoint( - Token& token, - Location& current, - Location end, - unsigned int& unicode); + decodeUnicodeCodePoint(Token& token, Location& current, Location end, unsigned int& unicode); bool - decodeUnicodeEscapeSequence( - Token& token, - Location& current, - Location end, - unsigned int& unicode); + decodeUnicodeEscapeSequence(Token& token, Location& current, Location end, unsigned int& unicode); bool addError(std::string const& message, Token& token, Location extra = 0); bool recoverFromError(TokenType skipUntilToken); bool - addErrorAndRecover( - std::string const& message, - Token& token, - TokenType skipUntilToken); + addErrorAndRecover(std::string const& message, Token& token, TokenType skipUntilToken); void skipUntilSpace(); Value& diff --git a/include/xrpl/json/json_value.h b/include/xrpl/json/json_value.h index 979e7fd788..4a7b1d869a 100644 --- a/include/xrpl/json/json_value.h +++ b/include/xrpl/json/json_value.h @@ -148,11 +148,7 @@ private: class CZString { public: - enum DuplicationPolicy { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; + enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; CZString(int index); CZString(char const* cstr, DuplicationPolicy allocate); CZString(CZString const& other); diff --git a/include/xrpl/json/json_writer.h b/include/xrpl/json/json_writer.h index 08e7b619b2..9049520a98 100644 --- a/include/xrpl/json/json_writer.h +++ b/include/xrpl/json/json_writer.h @@ -316,10 +316,7 @@ public: operator<<(std::ostream& o, Compact const& cJv) { detail::write_value( - [&o](void const* data, std::size_t n) { - o.write(static_cast(data), n); - }, - cJv.jv_); + [&o](void const* data, std::size_t n) { o.write(static_cast(data), n); }, cJv.jv_); return o; } }; diff --git a/include/xrpl/ledger/ApplyView.h b/include/xrpl/ledger/ApplyView.h index 393af2a7fd..c2eabf00bd 100644 --- a/include/xrpl/ledger/ApplyView.h +++ b/include/xrpl/ledger/ApplyView.h @@ -34,23 +34,17 @@ constexpr ApplyFlags operator|(ApplyFlags const& lhs, ApplyFlags const& rhs) { return safe_cast( - safe_cast>(lhs) | - safe_cast>(rhs)); + safe_cast>(lhs) | safe_cast>(rhs)); } -static_assert( - (tapFAIL_HARD | tapRETRY) == safe_cast(0x30u), - "ApplyFlags operator |"); -static_assert( - (tapRETRY | tapFAIL_HARD) == safe_cast(0x30u), - "ApplyFlags operator |"); +static_assert((tapFAIL_HARD | tapRETRY) == safe_cast(0x30u), "ApplyFlags operator |"); +static_assert((tapRETRY | tapFAIL_HARD) == safe_cast(0x30u), "ApplyFlags operator |"); constexpr ApplyFlags operator&(ApplyFlags const& lhs, ApplyFlags const& rhs) { return safe_cast( - safe_cast>(lhs) & - safe_cast>(rhs)); + safe_cast>(lhs) & safe_cast>(rhs)); } static_assert((tapFAIL_HARD & tapRETRY) == tapNONE, "ApplyFlags operator &"); @@ -59,13 +53,10 @@ static_assert((tapRETRY & tapFAIL_HARD) == tapNONE, "ApplyFlags operator &"); constexpr ApplyFlags operator~(ApplyFlags const& flags) { - return safe_cast( - ~safe_cast>(flags)); + return safe_cast(~safe_cast>(flags)); } -static_assert( - ~tapRETRY == safe_cast(0xFFFFFFDFu), - "ApplyFlags operator ~"); +static_assert(~tapRETRY == safe_cast(0xFFFFFFDFu), "ApplyFlags operator ~"); inline ApplyFlags operator|=(ApplyFlags& lhs, ApplyFlags const& rhs) @@ -221,21 +212,14 @@ public: // Called when a credit is made to an account // This is required to support PaymentSandbox virtual void - creditHook( - AccountID const& from, - AccountID const& to, - STAmount const& amount, - STAmount const& preCreditBalance) + creditHook(AccountID const& from, AccountID const& to, STAmount const& amount, STAmount const& preCreditBalance) { } // Called when the owner count changes // This is required to support PaymentSandbox virtual void - adjustOwnerCountHook( - AccountID const& account, - std::uint32_t cur, - std::uint32_t next) + adjustOwnerCountHook(AccountID const& account, std::uint32_t cur, std::uint32_t next) { } @@ -332,18 +316,10 @@ public: */ /** @{ */ bool - dirRemove( - Keylet const& directory, - std::uint64_t page, - uint256 const& key, - bool keepRoot); + dirRemove(Keylet const& directory, std::uint64_t page, uint256 const& key, bool keepRoot); bool - dirRemove( - Keylet const& directory, - std::uint64_t page, - Keylet const& key, - bool keepRoot) + dirRemove(Keylet const& directory, std::uint64_t page, Keylet const& key, bool keepRoot) { return dirRemove(directory, page, key.key, keepRoot); } @@ -351,9 +327,7 @@ public: /** Remove the specified directory, invoking the callback for every node. */ bool - dirDelete( - Keylet const& directory, - std::function const&); + dirDelete(Keylet const& directory, std::function const&); /** Remove the specified directory, if it is empty. diff --git a/include/xrpl/ledger/ApplyViewImpl.h b/include/xrpl/ledger/ApplyViewImpl.h index 0c11726135..c2b824f196 100644 --- a/include/xrpl/ledger/ApplyViewImpl.h +++ b/include/xrpl/ledger/ApplyViewImpl.h @@ -34,13 +34,7 @@ public: destructor. */ std::optional - apply( - OpenView& to, - STTx const& tx, - TER ter, - std::optional parentBatchId, - bool isDryRun, - beast::Journal j); + apply(OpenView& to, STTx const& tx, TER ter, std::optional parentBatchId, bool isDryRun, beast::Journal j); /** Set the amount of currency delivered. diff --git a/include/xrpl/ledger/BookDirs.h b/include/xrpl/ledger/BookDirs.h index daa1ef172a..23b9557f37 100644 --- a/include/xrpl/ledger/BookDirs.h +++ b/include/xrpl/ledger/BookDirs.h @@ -68,10 +68,7 @@ public: private: friend class BookDirs; - const_iterator( - ReadView const& view, - uint256 const& root, - uint256 const& dir_key) + const_iterator(ReadView const& view, uint256 const& root, uint256 const& dir_key) : view_(&view), root_(root), key_(dir_key), cur_key_(dir_key) { } diff --git a/include/xrpl/ledger/CachedView.h b/include/xrpl/ledger/CachedView.h index c1d66ecfc9..9a93c5f743 100644 --- a/include/xrpl/ledger/CachedView.h +++ b/include/xrpl/ledger/CachedView.h @@ -26,8 +26,7 @@ public: CachedViewImpl& operator=(CachedViewImpl const&) = delete; - CachedViewImpl(DigestAwareReadView const* base, CachedSLEs& cache) - : base_(*base), cache_(cache) + CachedViewImpl(DigestAwareReadView const* base, CachedSLEs& cache) : base_(*base), cache_(cache) { } @@ -66,9 +65,7 @@ public: } std::optional - succ( - key_type const& key, - std::optional const& last = std::nullopt) const override + succ(key_type const& key, std::optional const& last = std::nullopt) const override { return base_.succ(key, last); } diff --git a/include/xrpl/ledger/CredentialHelpers.h b/include/xrpl/ledger/CredentialHelpers.h index b90aa44c0d..09b4d63da0 100644 --- a/include/xrpl/ledger/CredentialHelpers.h +++ b/include/xrpl/ledger/CredentialHelpers.h @@ -20,9 +20,7 @@ namespace credentials { // Check if credential sfExpiration field has passed ledger's parentCloseTime bool -checkExpired( - std::shared_ptr const& sleCredential, - NetClock::time_point const& closed); +checkExpired(std::shared_ptr const& sleCredential, NetClock::time_point const& closed); // Return true if any expired credential was found in arr (and deleted) bool @@ -30,10 +28,7 @@ removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j); // Actually remove a credentials object from the ledger TER -deleteSLE( - ApplyView& view, - std::shared_ptr const& sleCredential, - beast::Journal j); +deleteSLE(ApplyView& view, std::shared_ptr const& sleCredential, beast::Journal j); // Amendment and parameters checks for sfCredentialIDs field NotTEC @@ -44,11 +39,7 @@ checkFields(STTx const& tx, beast::Journal j); // If you call it in preclaim, you also must call verifyDepositPreauth in // doApply TER -valid( - STTx const& tx, - ReadView const& view, - AccountID const& src, - beast::Journal j); +valid(STTx const& tx, ReadView const& view, AccountID const& src, beast::Journal j); // Check if subject has any credential maching the given domain. If you call it // in preclaim and it returns tecEXPIRED, you should call verifyValidDomain in @@ -59,10 +50,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject); // This function is only called when we about to return tecNO_PERMISSION // because all the checks for the DepositPreauth authorization failed. TER -authorizedDepositPreauth( - ApplyView const& view, - STVector256 const& ctx, - AccountID const& dst); +authorizedDepositPreauth(ApplyView const& view, STVector256 const& ctx, AccountID const& dst); // Sort credentials array, return empty set if there are duplicates std::set> @@ -78,11 +66,7 @@ checkArray(STArray const& credentials, unsigned maxSize, beast::Journal j); // Check expired credentials and for credentials maching DomainID of the ledger // object TER -verifyValidDomain( - ApplyView& view, - AccountID const& account, - uint256 domainID, - beast::Journal j); +verifyValidDomain(ApplyView& view, AccountID const& account, uint256 domainID, beast::Journal j); // Check expired credentials and for existing DepositPreauth ledger object TER diff --git a/include/xrpl/ledger/Credit.h b/include/xrpl/ledger/Credit.h index 09b65b3dde..e64c6015aa 100644 --- a/include/xrpl/ledger/Credit.h +++ b/include/xrpl/ledger/Credit.h @@ -16,18 +16,10 @@ namespace xrpl { */ /** @{ */ STAmount -creditLimit( - ReadView const& view, - AccountID const& account, - AccountID const& issuer, - Currency const& currency); +creditLimit(ReadView const& view, AccountID const& account, AccountID const& issuer, Currency const& currency); IOUAmount -creditLimit2( - ReadView const& v, - AccountID const& acc, - AccountID const& iss, - Currency const& cur); +creditLimit2(ReadView const& v, AccountID const& acc, AccountID const& iss, Currency const& cur); /** @} */ /** Returns the amount of IOUs issued by issuer that are held by an account @@ -38,11 +30,7 @@ creditLimit2( */ /** @{ */ STAmount -creditBalance( - ReadView const& view, - AccountID const& account, - AccountID const& issuer, - Currency const& currency); +creditBalance(ReadView const& view, AccountID const& account, AccountID const& issuer, Currency const& currency); /** @} */ } // namespace xrpl diff --git a/include/xrpl/ledger/OpenView.h b/include/xrpl/ledger/OpenView.h index bd90dbef18..5441d35a0e 100644 --- a/include/xrpl/ledger/OpenView.h +++ b/include/xrpl/ledger/OpenView.h @@ -58,9 +58,7 @@ private: std::shared_ptr meta; // Constructor needed for emplacement in std::map - txData( - std::shared_ptr const& txn_, - std::shared_ptr const& meta_) + txData(std::shared_ptr const& txn_, std::shared_ptr const& meta_) : txn(txn_), meta(meta_) { } @@ -73,13 +71,11 @@ private: key_type, txData, std::less, - boost::container::pmr::polymorphic_allocator< - std::pair>>; + boost::container::pmr::polymorphic_allocator>>; // monotonic_resource_ must outlive `items_`. Make a pointer so it may be // easily moved. - std::unique_ptr - monotonic_resource_; + std::unique_ptr monotonic_resource_; txs_map txs_; Rules rules_; LedgerHeader header_; @@ -135,16 +131,9 @@ public: The tx list starts empty and will contain all newly inserted tx. */ - OpenView( - open_ledger_t, - ReadView const* base, - Rules const& rules, - std::shared_ptr hold = nullptr); + OpenView(open_ledger_t, ReadView const* base, Rules const& rules, std::shared_ptr hold = nullptr); - OpenView( - open_ledger_t, - Rules const& rules, - std::shared_ptr const& base) + OpenView(open_ledger_t, Rules const& rules, std::shared_ptr const& base) : OpenView(open_ledger, &*base, rules, base) { } @@ -201,9 +190,7 @@ public: exists(Keylet const& k) const override; std::optional - succ( - key_type const& key, - std::optional const& last = std::nullopt) const override; + succ(key_type const& key, std::optional const& last = std::nullopt) const override; std::shared_ptr read(Keylet const& k) const override; diff --git a/include/xrpl/ledger/PaymentSandbox.h b/include/xrpl/ledger/PaymentSandbox.h index e1d197380d..fd77d154d8 100644 --- a/include/xrpl/ledger/PaymentSandbox.h +++ b/include/xrpl/ledger/PaymentSandbox.h @@ -19,8 +19,7 @@ class DeferredCredits public: struct Adjustment { - Adjustment(STAmount const& d, STAmount const& c, STAmount const& b) - : debits(d), credits(c), origBalance(b) + Adjustment(STAmount const& d, STAmount const& c, STAmount const& b) : debits(d), credits(c), origBalance(b) { } STAmount debits; @@ -31,10 +30,7 @@ public: // Get the adjustments for the balance between main and other. // Returns the debits, credits and the original balance std::optional - adjustments( - AccountID const& main, - AccountID const& other, - Currency const& currency) const; + adjustments(AccountID const& main, AccountID const& other, Currency const& currency) const; void credit( @@ -102,8 +98,7 @@ public: PaymentSandbox(PaymentSandbox&&) = default; - PaymentSandbox(ReadView const* base, ApplyFlags flags) - : ApplyViewBase(base, flags) + PaymentSandbox(ReadView const* base, ApplyFlags flags) : ApplyViewBase(base, flags) { } @@ -125,39 +120,27 @@ public: // or a PaymentSandbox-derived class, we MUST go through // one of these constructors or invariants will be broken. /** @{ */ - explicit PaymentSandbox(PaymentSandbox const* base) - : ApplyViewBase(base, base->flags()), ps_(base) + explicit PaymentSandbox(PaymentSandbox const* base) : ApplyViewBase(base, base->flags()), ps_(base) { } - explicit PaymentSandbox(PaymentSandbox* base) - : ApplyViewBase(base, base->flags()), ps_(base) + explicit PaymentSandbox(PaymentSandbox* base) : ApplyViewBase(base, base->flags()), ps_(base) { } /** @} */ STAmount - balanceHook( - AccountID const& account, - AccountID const& issuer, - STAmount const& amount) const override; + balanceHook(AccountID const& account, AccountID const& issuer, STAmount const& amount) const override; void - creditHook( - AccountID const& from, - AccountID const& to, - STAmount const& amount, - STAmount const& preCreditBalance) override; + creditHook(AccountID const& from, AccountID const& to, STAmount const& amount, STAmount const& preCreditBalance) + override; void - adjustOwnerCountHook( - AccountID const& account, - std::uint32_t cur, - std::uint32_t next) override; + adjustOwnerCountHook(AccountID const& account, std::uint32_t cur, std::uint32_t next) override; std::uint32_t - ownerCountHook(AccountID const& account, std::uint32_t count) - const override; + ownerCountHook(AccountID const& account, std::uint32_t count) const override; /** Apply changes to base view. diff --git a/include/xrpl/ledger/ReadView.h b/include/xrpl/ledger/ReadView.h index d2b6796ec9..5e33e7b4ba 100644 --- a/include/xrpl/ledger/ReadView.h +++ b/include/xrpl/ledger/ReadView.h @@ -31,8 +31,7 @@ namespace xrpl { class ReadView { public: - using tx_type = - std::pair, std::shared_ptr>; + using tx_type = std::pair, std::shared_ptr>; using key_type = uint256; @@ -130,9 +129,7 @@ public: interval (key, last). */ virtual std::optional - succ( - key_type const& key, - std::optional const& last = std::nullopt) const = 0; + succ(key_type const& key, std::optional const& last = std::nullopt) const = 0; /** Return the state item associated with a key. @@ -156,10 +153,7 @@ public: // balances so newly acquired assets are not counted toward the balance. // This is required to support PaymentSandbox. virtual STAmount - balanceHook( - AccountID const& account, - AccountID const& issuer, - STAmount const& amount) const + balanceHook(AccountID const& account, AccountID const& issuer, STAmount const& amount) const { return amount; } @@ -254,9 +248,7 @@ Rules makeRulesGivenLedger(DigestAwareReadView const& ledger, Rules const& current); Rules -makeRulesGivenLedger( - DigestAwareReadView const& ledger, - std::unordered_set> const& presets); +makeRulesGivenLedger(DigestAwareReadView const& ledger, std::unordered_set> const& presets); } // namespace xrpl diff --git a/include/xrpl/ledger/View.h b/include/xrpl/ledger/View.h index 707a08b890..7bf833fbad 100644 --- a/include/xrpl/ledger/View.h +++ b/include/xrpl/ledger/View.h @@ -75,70 +75,37 @@ isGlobalFrozen(ReadView const& view, Asset const& asset); // Note, depth parameter is used to limit the recursion depth [[nodiscard]] bool -isVaultPseudoAccountFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptShare, - int depth); +isVaultPseudoAccountFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptShare, int depth); [[nodiscard]] bool -isIndividualFrozen( - ReadView const& view, - AccountID const& account, - Currency const& currency, - AccountID const& issuer); +isIndividualFrozen(ReadView const& view, AccountID const& account, Currency const& currency, AccountID const& issuer); [[nodiscard]] inline bool -isIndividualFrozen( - ReadView const& view, - AccountID const& account, - Issue const& issue) +isIndividualFrozen(ReadView const& view, AccountID const& account, Issue const& issue) { return isIndividualFrozen(view, account, issue.currency, issue.account); } [[nodiscard]] bool -isIndividualFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue); +isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue); [[nodiscard]] inline bool -isIndividualFrozen( - ReadView const& view, - AccountID const& account, - Asset const& asset) +isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset) { - return std::visit( - [&](auto const& issue) { - return isIndividualFrozen(view, account, issue); - }, - asset.value()); + return std::visit([&](auto const& issue) { return isIndividualFrozen(view, account, issue); }, asset.value()); } [[nodiscard]] bool -isFrozen( - ReadView const& view, - AccountID const& account, - Currency const& currency, - AccountID const& issuer); +isFrozen(ReadView const& view, AccountID const& account, Currency const& currency, AccountID const& issuer); [[nodiscard]] inline bool -isFrozen( - ReadView const& view, - AccountID const& account, - Issue const& issue, - int = 0 /*ignored*/) +isFrozen(ReadView const& view, AccountID const& account, Issue const& issue, int = 0 /*ignored*/) { return isFrozen(view, account, issue.currency, issue.account); } [[nodiscard]] bool -isFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue, - int depth = 0); +isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth = 0); /** * isFrozen check is recursive for MPT shares in a vault, descending to @@ -146,17 +113,9 @@ isFrozen( * purely defensive, as we currently do not allow such vaults to be created. */ [[nodiscard]] inline bool -isFrozen( - ReadView const& view, - AccountID const& account, - Asset const& asset, - int depth = 0) +isFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0) { - return std::visit( - [&](auto const& issue) { - return isFrozen(view, account, issue, depth); - }, - asset.value()); + return std::visit([&](auto const& issue) { return isFrozen(view, account, issue, depth); }, asset.value()); } [[nodiscard]] inline TER @@ -166,10 +125,7 @@ checkFrozen(ReadView const& view, AccountID const& account, Issue const& issue) } [[nodiscard]] inline TER -checkFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue) +checkFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue) { return isFrozen(view, account, mptIssue) ? (TER)tecLOCKED : (TER)tesSUCCESS; } @@ -177,9 +133,7 @@ checkFrozen( [[nodiscard]] inline TER checkFrozen(ReadView const& view, AccountID const& account, Asset const& asset) { - return std::visit( - [&](auto const& issue) { return checkFrozen(view, account, issue); }, - asset.value()); + return std::visit([&](auto const& issue) { return checkFrozen(view, account, issue); }, asset.value()); } [[nodiscard]] bool @@ -190,10 +144,7 @@ isAnyFrozen( int depth = 0); [[nodiscard]] inline bool -isAnyFrozen( - ReadView const& view, - std::initializer_list const& accounts, - Issue const& issue) +isAnyFrozen(ReadView const& view, std::initializer_list const& accounts, Issue const& issue) { for (auto const& account : accounts) { @@ -204,11 +155,7 @@ isAnyFrozen( } [[nodiscard]] inline bool -isAnyFrozen( - ReadView const& view, - std::initializer_list const& accounts, - Asset const& asset, - int depth = 0) +isAnyFrozen(ReadView const& view, std::initializer_list const& accounts, Asset const& asset, int depth = 0) { return std::visit( [&](TIss const& issue) { @@ -221,28 +168,16 @@ isAnyFrozen( } [[nodiscard]] bool -isDeepFrozen( - ReadView const& view, - AccountID const& account, - Currency const& currency, - AccountID const& issuer); +isDeepFrozen(ReadView const& view, AccountID const& account, Currency const& currency, AccountID const& issuer); [[nodiscard]] inline bool -isDeepFrozen( - ReadView const& view, - AccountID const& account, - Issue const& issue, - int = 0 /*ignored*/) +isDeepFrozen(ReadView const& view, AccountID const& account, Issue const& issue, int = 0 /*ignored*/) { return isDeepFrozen(view, account, issue.currency, issue.account); } [[nodiscard]] inline bool -isDeepFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue, - int depth = 0) +isDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth = 0) { // Unlike IOUs, frozen / locked MPTs are not allowed to send or receive // funds, so checking "deep frozen" is the same as checking "frozen". @@ -255,58 +190,31 @@ isDeepFrozen( * purely defensive, as we currently do not allow such vaults to be created. */ [[nodiscard]] inline bool -isDeepFrozen( - ReadView const& view, - AccountID const& account, - Asset const& asset, - int depth = 0) +isDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0) { - return std::visit( - [&](auto const& issue) { - return isDeepFrozen(view, account, issue, depth); - }, - asset.value()); + return std::visit([&](auto const& issue) { return isDeepFrozen(view, account, issue, depth); }, asset.value()); } [[nodiscard]] inline TER -checkDeepFrozen( - ReadView const& view, - AccountID const& account, - Issue const& issue) +checkDeepFrozen(ReadView const& view, AccountID const& account, Issue const& issue) { - return isDeepFrozen(view, account, issue) ? (TER)tecFROZEN - : (TER)tesSUCCESS; + return isDeepFrozen(view, account, issue) ? (TER)tecFROZEN : (TER)tesSUCCESS; } [[nodiscard]] inline TER -checkDeepFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue) +checkDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue) { - return isDeepFrozen(view, account, mptIssue) ? (TER)tecLOCKED - : (TER)tesSUCCESS; + return isDeepFrozen(view, account, mptIssue) ? (TER)tecLOCKED : (TER)tesSUCCESS; } [[nodiscard]] inline TER -checkDeepFrozen( - ReadView const& view, - AccountID const& account, - Asset const& asset) +checkDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset) { - return std::visit( - [&](auto const& issue) { - return checkDeepFrozen(view, account, issue); - }, - asset.value()); + return std::visit([&](auto const& issue) { return checkDeepFrozen(view, account, issue); }, asset.value()); } [[nodiscard]] bool -isLPTokenFrozen( - ReadView const& view, - AccountID const& account, - Issue const& asset, - Issue const& asset2); +isLPTokenFrozen(ReadView const& view, AccountID const& account, Issue const& asset, Issue const& asset2); // Returns the amount an account can spend. // @@ -380,18 +288,11 @@ accountFunds( // // @param ownerCountAdj positive to add to count, negative to reduce count. [[nodiscard]] XRPAmount -xrpLiquid( - ReadView const& view, - AccountID const& id, - std::int32_t ownerCountAdj, - beast::Journal j); +xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j); /** Iterate all items in the given directory. */ void -forEachItem( - ReadView const& view, - Keylet const& root, - std::function const&)> const& f); +forEachItem(ReadView const& view, Keylet const& root, std::function const&)> const& f); /** Iterate all items after an item in the given directory. @param after The key of the item to start after @@ -410,10 +311,7 @@ forEachItemAfter( /** Iterate all items in an account's owner directory. */ inline void -forEachItem( - ReadView const& view, - AccountID const& id, - std::function const&)> const& f) +forEachItem(ReadView const& view, AccountID const& id, std::function const&)> const& f) { return forEachItem(view, keylet::ownerDir(id), f); } @@ -510,11 +408,7 @@ getCandidateLedger(LedgerIndex requested) use the second form if you have not acquired the valid ledger yet */ [[nodiscard]] bool -areCompatible( - ReadView const& validLedger, - ReadView const& testLedger, - beast::Journal::Stream& s, - char const* reason); +areCompatible(ReadView const& validLedger, ReadView const& testLedger, beast::Journal::Stream& s, char const* reason); [[nodiscard]] bool areCompatible( @@ -532,11 +426,7 @@ areCompatible( /** Adjust the owner count up or down. */ void -adjustOwnerCount( - ApplyView& view, - std::shared_ptr const& sle, - std::int32_t amount, - beast::Journal j); +adjustOwnerCount(ApplyView& view, std::shared_ptr const& sle, std::int32_t amount, beast::Journal j); /** @{ */ /** Returns the first entry in the directory, advancing the index @@ -562,12 +452,7 @@ cdirFirst( uint256& entry); bool -dirFirst( - ApplyView& view, - uint256 const& root, - std::shared_ptr& page, - unsigned int& index, - uint256& entry); +dirFirst(ApplyView& view, uint256 const& root, std::shared_ptr& page, unsigned int& index, uint256& entry); /** @} */ /** @{ */ @@ -594,23 +479,14 @@ cdirNext( uint256& entry); bool -dirNext( - ApplyView& view, - uint256 const& root, - std::shared_ptr& page, - unsigned int& index, - uint256& entry); +dirNext(ApplyView& view, uint256 const& root, std::shared_ptr& page, unsigned int& index, uint256& entry); /** @} */ [[nodiscard]] std::function describeOwnerDir(AccountID const& account); [[nodiscard]] TER -dirLink( - ApplyView& view, - AccountID const& owner, - std::shared_ptr& object, - SF_UINT64 const& node = sfOwnerNode); +dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr& object, SF_UINT64 const& node = sfOwnerNode); AccountID pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey); @@ -624,10 +500,7 @@ pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey); * field. The amendment check is **not** performed in createPseudoAccount. */ [[nodiscard]] Expected, TER> -createPseudoAccount( - ApplyView& view, - uint256 const& pseudoOwnerKey, - SField const& ownerField); +createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField); // Returns true if and only if sleAcct is a pseudo-account or specific // pseudo-accounts in pseudoFieldFilter. @@ -637,9 +510,7 @@ createPseudoAccount( // * NOT a ltACCOUNT_ROOT OR // * null pointer [[nodiscard]] bool -isPseudoAccount( - std::shared_ptr sleAcct, - std::set const& pseudoFieldFilter = {}); +isPseudoAccount(std::shared_ptr sleAcct, std::set const& pseudoFieldFilter = {}); // Returns the list of fields that define an ACCOUNT_ROOT as a pseudo-account if // set @@ -653,13 +524,9 @@ isPseudoAccount( getPseudoAccountFields(); [[nodiscard]] inline bool -isPseudoAccount( - ReadView const& view, - AccountID const& accountId, - std::set const& pseudoFieldFilter = {}) +isPseudoAccount(ReadView const& view, AccountID const& accountId, std::set const& pseudoFieldFilter = {}) { - return isPseudoAccount( - view.read(keylet::account(accountId)), pseudoFieldFilter); + return isPseudoAccount(view.read(keylet::account(accountId)), pseudoFieldFilter); } [[nodiscard]] TER @@ -774,8 +641,7 @@ addEmptyHolding( { return std::visit( [&](TIss const& issue) -> TER { - return addEmptyHolding( - view, accountID, priorBalance, issue, journal); + return addEmptyHolding(view, accountID, priorBalance, issue, journal); }, asset.value()); } @@ -818,25 +684,13 @@ trustCreate( beast::Journal j); [[nodiscard]] TER -removeEmptyHolding( - ApplyView& view, - AccountID const& accountID, - Issue const& issue, - beast::Journal journal); +removeEmptyHolding(ApplyView& view, AccountID const& accountID, Issue const& issue, beast::Journal journal); [[nodiscard]] TER -removeEmptyHolding( - ApplyView& view, - AccountID const& accountID, - MPTIssue const& mptIssue, - beast::Journal journal); +removeEmptyHolding(ApplyView& view, AccountID const& accountID, MPTIssue const& mptIssue, beast::Journal journal); [[nodiscard]] inline TER -removeEmptyHolding( - ApplyView& view, - AccountID const& accountID, - Asset const& asset, - beast::Journal journal) +removeEmptyHolding(ApplyView& view, AccountID const& accountID, Asset const& asset, beast::Journal journal) { return std::visit( [&](TIss const& issue) -> TER { @@ -888,11 +742,7 @@ rippleCredit( beast::Journal j); TER -rippleLockEscrowMPT( - ApplyView& view, - AccountID const& uGrantorID, - STAmount const& saAmount, - beast::Journal j); +rippleLockEscrowMPT(ApplyView& view, AccountID const& uGrantorID, STAmount const& saAmount, beast::Journal j); TER rippleUnlockEscrowMPT( @@ -932,28 +782,13 @@ accountSendMulti( WaiveTransferFee waiveFee = WaiveTransferFee::No); [[nodiscard]] TER -issueIOU( - ApplyView& view, - AccountID const& account, - STAmount const& amount, - Issue const& issue, - beast::Journal j); +issueIOU(ApplyView& view, AccountID const& account, STAmount const& amount, Issue const& issue, beast::Journal j); [[nodiscard]] TER -redeemIOU( - ApplyView& view, - AccountID const& account, - STAmount const& amount, - Issue const& issue, - beast::Journal j); +redeemIOU(ApplyView& view, AccountID const& account, STAmount const& amount, Issue const& issue, beast::Journal j); [[nodiscard]] TER -transferXRP( - ApplyView& view, - AccountID const& from, - AccountID const& to, - STAmount const& amount, - beast::Journal j); +transferXRP(ApplyView& view, AccountID const& from, AccountID const& to, STAmount const& amount, beast::Journal j); /* Check if MPToken (for MPT) or trust line (for IOU) exists: * - StrongAuth - before checking if authorization is required @@ -984,11 +819,7 @@ enum class AuthType { StrongAuth, WeakAuth, Legacy }; * The default "Legacy" auth type is equivalent to WeakAuth. */ [[nodiscard]] TER -requireAuth( - ReadView const& view, - Issue const& issue, - AccountID const& account, - AuthType authType = AuthType::Legacy); +requireAuth(ReadView const& view, Issue const& issue, AccountID const& account, AuthType authType = AuthType::Legacy); /** Check if the account lacks required authorization. * @@ -1028,9 +859,7 @@ requireAuth( AuthType authType = AuthType::Legacy) { return std::visit( - [&](TIss const& issue_) { - return requireAuth(view, issue_, account, authType); - }, + [&](TIss const& issue_) { return requireAuth(view, issue_, account, authType); }, asset.value()); } @@ -1070,18 +899,10 @@ enforceMPTokenAuthorization( * and tesSUCCESS otherwise. */ [[nodiscard]] TER -canTransfer( - ReadView const& view, - MPTIssue const& mptIssue, - AccountID const& from, - AccountID const& to); +canTransfer(ReadView const& view, MPTIssue const& mptIssue, AccountID const& from, AccountID const& to); [[nodiscard]] TER -canTransfer( - ReadView const& view, - Issue const& issue, - AccountID const& from, - AccountID const& to); +canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, AccountID const& to); [[nodiscard]] TER inline canTransfer( ReadView const& view, @@ -1090,9 +911,7 @@ canTransfer( AccountID const& to) { return std::visit( - [&](TIss const& issue) -> TER { - return canTransfer(view, issue, from, to); - }, + [&](TIss const& issue) -> TER { return canTransfer(view, issue, from, to); }, asset.value()); } @@ -1100,10 +919,7 @@ canTransfer( * (if should not be skipped) and if the entry should be skipped. The status * is always tesSUCCESS if the entry should be skipped. */ -using EntryDeleter = std::function( - LedgerEntryType, - uint256 const&, - std::shared_ptr&)>; +using EntryDeleter = std::function(LedgerEntryType, uint256 const&, std::shared_ptr&)>; /** Cleanup owner directory entries on account delete. * Used for a regular and AMM accounts deletion. The caller * has to provide the deleter function, which handles details of diff --git a/include/xrpl/ledger/detail/ApplyStateTable.h b/include/xrpl/ledger/detail/ApplyStateTable.h index f5ec0c9f51..9fb7b64fe8 100644 --- a/include/xrpl/ledger/detail/ApplyStateTable.h +++ b/include/xrpl/ledger/detail/ApplyStateTable.h @@ -60,10 +60,7 @@ public: exists(ReadView const& base, Keylet const& k) const; std::optional - succ( - ReadView const& base, - key_type const& key, - std::optional const& last) const; + succ(ReadView const& base, key_type const& key, std::optional const& last) const; std::shared_ptr read(ReadView const& base, Keylet const& k) const; @@ -115,19 +112,10 @@ private: threadItem(TxMeta& meta, std::shared_ptr const& to); std::shared_ptr - getForMod( - ReadView const& base, - key_type const& key, - Mods& mods, - beast::Journal j); + getForMod(ReadView const& base, key_type const& key, Mods& mods, beast::Journal j); void - threadTx( - ReadView const& base, - TxMeta& meta, - AccountID const& to, - Mods& mods, - beast::Journal j); + threadTx(ReadView const& base, TxMeta& meta, AccountID const& to, Mods& mods, beast::Journal j); void threadOwners( diff --git a/include/xrpl/ledger/detail/ApplyViewBase.h b/include/xrpl/ledger/detail/ApplyViewBase.h index 9992d73ad1..9c048c6d90 100644 --- a/include/xrpl/ledger/detail/ApplyViewBase.h +++ b/include/xrpl/ledger/detail/ApplyViewBase.h @@ -40,9 +40,7 @@ public: exists(Keylet const& k) const override; std::optional - succ( - key_type const& key, - std::optional const& last = std::nullopt) const override; + succ(key_type const& key, std::optional const& last = std::nullopt) const override; std::shared_ptr read(Keylet const& k) const override; diff --git a/include/xrpl/ledger/detail/RawStateTable.h b/include/xrpl/ledger/detail/RawStateTable.h index 19d2882a63..881d00be53 100644 --- a/include/xrpl/ledger/detail/RawStateTable.h +++ b/include/xrpl/ledger/detail/RawStateTable.h @@ -24,15 +24,11 @@ public: static constexpr size_t initialBufferSize = kilobytes(256); RawStateTable() - : monotonic_resource_{std::make_unique< - boost::container::pmr::monotonic_buffer_resource>( - initialBufferSize)} + : monotonic_resource_{std::make_unique(initialBufferSize)} , items_{monotonic_resource_.get()} {}; RawStateTable(RawStateTable const& rhs) - : monotonic_resource_{std::make_unique< - boost::container::pmr::monotonic_buffer_resource>( - initialBufferSize)} + : monotonic_resource_{std::make_unique(initialBufferSize)} , items_{rhs.items_, monotonic_resource_.get()} , dropsDestroyed_{rhs.dropsDestroyed_} {}; @@ -50,10 +46,7 @@ public: exists(ReadView const& base, Keylet const& k) const; std::optional - succ( - ReadView const& base, - key_type const& key, - std::optional const& last) const; + succ(ReadView const& base, key_type const& key, std::optional const& last) const; void erase(std::shared_ptr const& sle); @@ -94,8 +87,7 @@ private: std::shared_ptr sle; // Constructor needed for emplacement in std::map - sleAction(Action action_, std::shared_ptr const& sle_) - : action(action_), sle(sle_) + sleAction(Action action_, std::shared_ptr const& sle_) : action(action_), sle(sle_) { } }; @@ -106,12 +98,10 @@ private: key_type, sleAction, std::less, - boost::container::pmr::polymorphic_allocator< - std::pair>>; + boost::container::pmr::polymorphic_allocator>>; // monotonic_resource_ must outlive `items_`. Make a pointer so it may be // easily moved. - std::unique_ptr - monotonic_resource_; + std::unique_ptr monotonic_resource_; items_t items_; XRPAmount dropsDestroyed_{0}; diff --git a/include/xrpl/ledger/detail/ReadViewFwdRange.h b/include/xrpl/ledger/detail/ReadViewFwdRange.h index 557bba4987..05d2b79a50 100644 --- a/include/xrpl/ledger/detail/ReadViewFwdRange.h +++ b/include/xrpl/ledger/detail/ReadViewFwdRange.h @@ -73,9 +73,7 @@ public: iterator(iterator&& other) noexcept; // Used by the implementation - explicit iterator( - ReadView const* view, - std::unique_ptr impl); + explicit iterator(ReadView const* view, std::unique_ptr impl); iterator& operator=(iterator const& other); diff --git a/include/xrpl/ledger/detail/ReadViewFwdRange.ipp b/include/xrpl/ledger/detail/ReadViewFwdRange.ipp index e86246133a..6978d3abad 100644 --- a/include/xrpl/ledger/detail/ReadViewFwdRange.ipp +++ b/include/xrpl/ledger/detail/ReadViewFwdRange.ipp @@ -6,32 +6,25 @@ namespace detail { template ReadViewFwdRange::iterator::iterator(iterator const& other) - : view_(other.view_) - , impl_(other.impl_ ? other.impl_->copy() : nullptr) - , cache_(other.cache_) + : view_(other.view_), impl_(other.impl_ ? other.impl_->copy() : nullptr), cache_(other.cache_) { } template ReadViewFwdRange::iterator::iterator(iterator&& other) noexcept - : view_(other.view_) - , impl_(std::move(other.impl_)) - , cache_(std::move(other.cache_)) + : view_(other.view_), impl_(std::move(other.impl_)), cache_(std::move(other.cache_)) { } template -ReadViewFwdRange::iterator::iterator( - ReadView const* view, - std::unique_ptr impl) +ReadViewFwdRange::iterator::iterator(ReadView const* view, std::unique_ptr impl) : view_(view), impl_(std::move(impl)) { } template auto -ReadViewFwdRange::iterator::operator=(iterator const& other) - -> iterator& +ReadViewFwdRange::iterator::operator=(iterator const& other) -> iterator& { if (this != &other) { @@ -44,8 +37,7 @@ ReadViewFwdRange::iterator::operator=(iterator const& other) template auto -ReadViewFwdRange::iterator::operator=(iterator&& other) noexcept - -> iterator& +ReadViewFwdRange::iterator::operator=(iterator&& other) noexcept -> iterator& { if (this != &other) { diff --git a/include/xrpl/net/AutoSocket.h b/include/xrpl/net/AutoSocket.h index 2fcba5780c..da4d3c30e5 100644 --- a/include/xrpl/net/AutoSocket.h +++ b/include/xrpl/net/AutoSocket.h @@ -27,20 +27,13 @@ public: using callback = std::function; public: - AutoSocket( - boost::asio::io_context& s, - boost::asio::ssl::context& c, - bool secureOnly, - bool plainOnly) - : mSecure(secureOnly) - , mBuffer((plainOnly || secureOnly) ? 0 : 4) - , j_{beast::Journal::getNullSink()} + AutoSocket(boost::asio::io_context& s, boost::asio::ssl::context& c, bool secureOnly, bool plainOnly) + : mSecure(secureOnly), mBuffer((plainOnly || secureOnly) ? 0 : 4), j_{beast::Journal::getNullSink()} { mSocket = std::make_unique(s, c); } - AutoSocket(boost::asio::io_context& s, boost::asio::ssl::context& c) - : AutoSocket(s, c, false, false) + AutoSocket(boost::asio::io_context& s, boost::asio::ssl::context& c) : AutoSocket(s, c, false, false) { } @@ -105,9 +98,7 @@ public: { // must be plain mSecure = false; - post( - mSocket->get_executor(), - boost::beast::bind_handler(cbFunc, error_code())); + post(mSocket->get_executor(), boost::beast::bind_handler(cbFunc, error_code())); } else { @@ -115,12 +106,7 @@ public: mSocket->next_layer().async_receive( boost::asio::buffer(mBuffer), boost::asio::socket_base::message_peek, - std::bind( - &AutoSocket::handle_autodetect, - this, - cbFunc, - std::placeholders::_1, - std::placeholders::_2)); + std::bind(&AutoSocket::handle_autodetect, this, cbFunc, std::placeholders::_1, std::placeholders::_2)); } } @@ -141,9 +127,7 @@ public: { ec = e.code(); } - post( - mSocket->get_executor(), - boost::beast::bind_handler(handler, ec)); + post(mSocket->get_executor(), boost::beast::bind_handler(handler, ec)); } } @@ -162,39 +146,29 @@ public: async_read_until(Seq const& buffers, Condition condition, Handler handler) { if (isSecure()) - boost::asio::async_read_until( - *mSocket, buffers, condition, handler); + boost::asio::async_read_until(*mSocket, buffers, condition, handler); else - boost::asio::async_read_until( - PlainSocket(), buffers, condition, handler); + boost::asio::async_read_until(PlainSocket(), buffers, condition, handler); } template void - async_read_until( - boost::asio::basic_streambuf& buffers, - std::string const& delim, - Handler handler) + async_read_until(boost::asio::basic_streambuf& buffers, std::string const& delim, Handler handler) { if (isSecure()) boost::asio::async_read_until(*mSocket, buffers, delim, handler); else - boost::asio::async_read_until( - PlainSocket(), buffers, delim, handler); + boost::asio::async_read_until(PlainSocket(), buffers, delim, handler); } template void - async_read_until( - boost::asio::basic_streambuf& buffers, - MatchCondition cond, - Handler handler) + async_read_until(boost::asio::basic_streambuf& buffers, MatchCondition cond, Handler handler) { if (isSecure()) boost::asio::async_read_until(*mSocket, buffers, cond, handler); else - boost::asio::async_read_until( - PlainSocket(), buffers, cond, handler); + boost::asio::async_read_until(PlainSocket(), buffers, cond, handler); } template @@ -209,9 +183,7 @@ public: template void - async_write( - boost::asio::basic_streambuf& buffers, - Handler handler) + async_write(boost::asio::basic_streambuf& buffers, Handler handler) { if (isSecure()) boost::asio::async_write(*mSocket, buffers, handler); @@ -231,10 +203,7 @@ public: template void - async_read( - boost::asio::basic_streambuf& buffers, - Condition cond, - Handler handler) + async_read(boost::asio::basic_streambuf& buffers, Condition cond, Handler handler) { if (isSecure()) boost::asio::async_read(*mSocket, buffers, cond, handler); @@ -264,10 +233,7 @@ public: protected: void - handle_autodetect( - callback cbFunc, - error_code const& ec, - size_t bytesTransferred) + handle_autodetect(callback cbFunc, error_code const& ec, size_t bytesTransferred) { using namespace xrpl; @@ -278,12 +244,9 @@ protected: } else if ( (mBuffer[0] < 127) && (mBuffer[0] > 31) && - ((bytesTransferred < 2) || - ((mBuffer[1] < 127) && (mBuffer[1] > 31))) && - ((bytesTransferred < 3) || - ((mBuffer[2] < 127) && (mBuffer[2] > 31))) && - ((bytesTransferred < 4) || - ((mBuffer[3] < 127) && (mBuffer[3] > 31)))) + ((bytesTransferred < 2) || ((mBuffer[1] < 127) && (mBuffer[1] > 31))) && + ((bytesTransferred < 3) || ((mBuffer[2] < 127) && (mBuffer[2] > 31))) && + ((bytesTransferred < 4) || ((mBuffer[3] < 127) && (mBuffer[3] > 31)))) { // not ssl JLOG(j_.trace()) << "non-SSL"; diff --git a/include/xrpl/net/HTTPClient.h b/include/xrpl/net/HTTPClient.h index 6e4d4ce685..0e1a56e42d 100644 --- a/include/xrpl/net/HTTPClient.h +++ b/include/xrpl/net/HTTPClient.h @@ -38,10 +38,8 @@ public: std::string const& strPath, std::size_t responseMax, // if no Content-Length header std::chrono::seconds timeout, - std::function complete, + std::function + complete, beast::Journal& j); static void @@ -52,10 +50,8 @@ public: std::string const& strPath, std::size_t responseMax, // if no Content-Length header std::chrono::seconds timeout, - std::function complete, + std::function + complete, beast::Journal& j); static void @@ -64,14 +60,11 @@ public: boost::asio::io_context& io_context, std::string strSite, unsigned short const port, - std::function< - void(boost::asio::streambuf& sb, std::string const& strHost)> build, + std::function build, std::size_t responseMax, // if no Content-Length header std::chrono::seconds timeout, - std::function complete, + std::function + complete, beast::Journal& j); }; diff --git a/include/xrpl/net/HTTPClientSSLContext.h b/include/xrpl/net/HTTPClientSSLContext.h index b8dfbd3e09..f195b031da 100644 --- a/include/xrpl/net/HTTPClientSSLContext.h +++ b/include/xrpl/net/HTTPClientSSLContext.h @@ -21,8 +21,7 @@ public: std::string const& sslVerifyFile, bool sslVerify, beast::Journal j, - boost::asio::ssl::context_base::method method = - boost::asio::ssl::context::sslv23) + boost::asio::ssl::context_base::method method = boost::asio::ssl::context::sslv23) : ssl_context_{method}, j_(j), verify_{sslVerify} { boost::system::error_code ec; @@ -32,9 +31,8 @@ public: registerSSLCerts(ssl_context_, ec, j_); if (ec && sslVerifyDir.empty()) - Throw(boost::str( - boost::format("Failed to set_default_verify_paths: %s") % - ec.message())); + Throw( + boost::str(boost::format("Failed to set_default_verify_paths: %s") % ec.message())); } else { @@ -46,9 +44,7 @@ public: ssl_context_.add_verify_path(sslVerifyDir, ec); if (ec) - Throw(boost::str( - boost::format("Failed to add verify path: %s") % - ec.message())); + Throw(boost::str(boost::format("Failed to add verify path: %s") % ec.message())); } } @@ -79,23 +75,15 @@ public: template < class T, class = std::enable_if_t< - std::is_same< - T, - boost::asio::ssl::stream>:: - value || - std::is_same< - T, - boost::asio::ssl::stream>:: - value>> + std::is_same>::value || + std::is_same>::value>> boost::system::error_code preConnectVerify(T& strm, std::string const& host) { boost::system::error_code ec; if (!SSL_set_tlsext_host_name(strm.native_handle(), host.c_str())) { - ec.assign( - static_cast(::ERR_get_error()), - boost::asio::error::get_ssl_category()); + ec.assign(static_cast(::ERR_get_error()), boost::asio::error::get_ssl_category()); } else if (!sslVerify()) { @@ -107,14 +95,8 @@ public: template < class T, class = std::enable_if_t< - std::is_same< - T, - boost::asio::ssl::stream>:: - value || - std::is_same< - T, - boost::asio::ssl::stream>:: - value>> + std::is_same>::value || + std::is_same>::value>> /** * @brief invoked after connect/async_connect but before sending data * on an ssl stream - to setup name verification. @@ -133,13 +115,7 @@ public: if (!ec) { strm.set_verify_callback( - std::bind( - &rfc6125_verify, - host, - std::placeholders::_1, - std::placeholders::_2, - j_), - ec); + std::bind(&rfc6125_verify, host, std::placeholders::_1, std::placeholders::_2, j_), ec); } } @@ -156,17 +132,12 @@ public: * @param j journal for logging */ static bool - rfc6125_verify( - std::string const& domain, - bool preverified, - boost::asio::ssl::verify_context& ctx, - beast::Journal j) + rfc6125_verify(std::string const& domain, bool preverified, boost::asio::ssl::verify_context& ctx, beast::Journal j) { if (boost::asio::ssl::host_name_verification(domain)(preverified, ctx)) return true; - JLOG(j.warn()) << "Outbound SSL connection to " << domain - << " fails certificate verification"; + JLOG(j.warn()) << "Outbound SSL connection to " << domain << " fails certificate verification"; return false; } diff --git a/include/xrpl/net/RegisterSSLCerts.h b/include/xrpl/net/RegisterSSLCerts.h index f9b865c3aa..273d1966d1 100644 --- a/include/xrpl/net/RegisterSSLCerts.h +++ b/include/xrpl/net/RegisterSSLCerts.h @@ -14,10 +14,7 @@ namespace xrpl { store accessible via CryptoAPI. */ void -registerSSLCerts( - boost::asio::ssl::context&, - boost::system::error_code&, - beast::Journal j); +registerSSLCerts(boost::asio::ssl::context&, boost::system::error_code&, beast::Journal j); } // namespace xrpl diff --git a/include/xrpl/nodestore/Backend.h b/include/xrpl/nodestore/Backend.h index 0ea8835f61..d3b995b6ed 100644 --- a/include/xrpl/nodestore/Backend.h +++ b/include/xrpl/nodestore/Backend.h @@ -64,9 +64,7 @@ public: virtual void open(bool createIfMissing, uint64_t appType, uint64_t uid, uint64_t salt) { - Throw( - "Deterministic appType/uid/salt not supported by backend " + - getName()); + Throw("Deterministic appType/uid/salt not supported by backend " + getName()); } /** Close the backend. diff --git a/include/xrpl/nodestore/Database.h b/include/xrpl/nodestore/Database.h index 474f873876..a1de865241 100644 --- a/include/xrpl/nodestore/Database.h +++ b/include/xrpl/nodestore/Database.h @@ -40,11 +40,7 @@ public: @param config The configuration settings @param journal Destination for logging output. */ - Database( - Scheduler& scheduler, - int readThreads, - Section const& config, - beast::Journal j); + Database(Scheduler& scheduler, int readThreads, Section const& config, beast::Journal j); /** Destroy the node store. All pending operations are completed, pending writes flushed, @@ -82,11 +78,7 @@ public: @return `true` if the object was stored? */ virtual void - store( - NodeObjectType type, - Blob&& data, - uint256 const& hash, - std::uint32_t ledgerSeq) = 0; + store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t ledgerSeq) = 0; /* Check if two ledgers are in the same database @@ -228,9 +220,7 @@ protected: void storeStats(std::uint64_t count, std::uint64_t sz) { - XRPL_ASSERT( - count <= sz, - "xrpl::NodeStore::Database::storeStats : valid inputs"); + XRPL_ASSERT(count <= sz, "xrpl::NodeStore::Database::storeStats : valid inputs"); storeCount_ += count; storeSz_ += sz; } @@ -258,11 +248,7 @@ private: std::condition_variable readCondVar_; // reads to do - std::map< - uint256, - std::vector const&)>>>> + std::map const&)>>>> read_; std::atomic readStopping_ = false; @@ -270,11 +256,7 @@ private: std::atomic runningThreads_ = 0; virtual std::shared_ptr - fetchNodeObject( - uint256 const& hash, - std::uint32_t ledgerSeq, - FetchReport& fetchReport, - bool duplicate) = 0; + fetchNodeObject(uint256 const& hash, std::uint32_t ledgerSeq, FetchReport& fetchReport, bool duplicate) = 0; /** Visit every object in the database This is usually called during import. diff --git a/include/xrpl/nodestore/DatabaseRotating.h b/include/xrpl/nodestore/DatabaseRotating.h index 85202e7a84..89e2ae8c0c 100644 --- a/include/xrpl/nodestore/DatabaseRotating.h +++ b/include/xrpl/nodestore/DatabaseRotating.h @@ -14,11 +14,7 @@ namespace NodeStore { class DatabaseRotating : public Database { public: - DatabaseRotating( - Scheduler& scheduler, - int readThreads, - Section const& config, - beast::Journal journal) + DatabaseRotating(Scheduler& scheduler, int readThreads, Section const& config, beast::Journal journal) : Database(scheduler, readThreads, config, journal) { } @@ -33,9 +29,7 @@ public: virtual void rotate( std::unique_ptr&& newBackend, - std::function const& f) = 0; + std::function const& f) = 0; }; } // namespace NodeStore diff --git a/include/xrpl/nodestore/Manager.h b/include/xrpl/nodestore/Manager.h index 72edf2b47e..e6d62fbc4a 100644 --- a/include/xrpl/nodestore/Manager.h +++ b/include/xrpl/nodestore/Manager.h @@ -39,11 +39,7 @@ public: /** Create a backend. */ virtual std::unique_ptr - make_Backend( - Section const& parameters, - std::size_t burstSize, - Scheduler& scheduler, - beast::Journal journal) = 0; + make_Backend(Section const& parameters, std::size_t burstSize, Scheduler& scheduler, beast::Journal journal) = 0; /** Construct a NodeStore database. diff --git a/include/xrpl/nodestore/NodeObject.h b/include/xrpl/nodestore/NodeObject.h index 6a69245fd2..1926d1791c 100644 --- a/include/xrpl/nodestore/NodeObject.h +++ b/include/xrpl/nodestore/NodeObject.h @@ -43,11 +43,7 @@ private: public: // This constructor is private, use createObject instead. - NodeObject( - NodeObjectType type, - Blob&& data, - uint256 const& hash, - PrivateAccess); + NodeObject(NodeObjectType type, Blob&& data, uint256 const& hash, PrivateAccess); /** Create an object from fields. diff --git a/include/xrpl/nodestore/detail/DatabaseNodeImp.h b/include/xrpl/nodestore/detail/DatabaseNodeImp.h index bf222129cc..900d6a5a59 100644 --- a/include/xrpl/nodestore/detail/DatabaseNodeImp.h +++ b/include/xrpl/nodestore/detail/DatabaseNodeImp.h @@ -22,8 +22,7 @@ public: std::shared_ptr backend, Section const& config, beast::Journal j) - : Database(scheduler, readThreads, config, j) - , backend_(std::move(backend)) + : Database(scheduler, readThreads, config, j), backend_(std::move(backend)) { std::optional cacheSize, cacheAge; @@ -32,8 +31,7 @@ public: cacheSize = get(config, "cache_size"); if (cacheSize.value() < 0) { - Throw( - "Specified negative value for cache_size"); + Throw("Specified negative value for cache_size"); } } @@ -42,19 +40,14 @@ public: cacheAge = get(config, "cache_age"); if (cacheAge.value() < 0) { - Throw( - "Specified negative value for cache_age"); + Throw("Specified negative value for cache_age"); } } if (cacheSize != 0 || cacheAge != 0) { cache_ = std::make_shared>( - "DatabaseNodeImp", - cacheSize.value_or(0), - std::chrono::minutes(cacheAge.value_or(0)), - stopwatch(), - j); + "DatabaseNodeImp", cacheSize.value_or(0), std::chrono::minutes(cacheAge.value_or(0)), stopwatch(), j); } XRPL_ASSERT( @@ -87,8 +80,7 @@ public: } void - store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t) - override; + store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t) override; bool isSameDB(std::uint32_t, std::uint32_t) override @@ -110,8 +102,7 @@ public: asyncFetch( uint256 const& hash, std::uint32_t ledgerSeq, - std::function const&)>&& callback) - override; + std::function const&)>&& callback) override; void sweep() override; @@ -124,11 +115,7 @@ private: std::shared_ptr backend_; std::shared_ptr - fetchNodeObject( - uint256 const& hash, - std::uint32_t, - FetchReport& fetchReport, - bool duplicate) override; + fetchNodeObject(uint256 const& hash, std::uint32_t, FetchReport& fetchReport, bool duplicate) override; void for_each(std::function)> f) override diff --git a/include/xrpl/nodestore/detail/DatabaseRotatingImp.h b/include/xrpl/nodestore/detail/DatabaseRotatingImp.h index 63d628a30a..31c9ebbaec 100644 --- a/include/xrpl/nodestore/detail/DatabaseRotatingImp.h +++ b/include/xrpl/nodestore/detail/DatabaseRotatingImp.h @@ -32,9 +32,7 @@ public: void rotate( std::unique_ptr&& newBackend, - std::function const& f) override; + std::function const& f) override; std::string getName() const override; @@ -53,8 +51,7 @@ public: } void - store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t) - override; + store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t) override; void sync() override; @@ -68,11 +65,7 @@ private: mutable std::mutex mutex_; std::shared_ptr - fetchNodeObject( - uint256 const& hash, - std::uint32_t, - FetchReport& fetchReport, - bool duplicate) override; + fetchNodeObject(uint256 const& hash, std::uint32_t, FetchReport& fetchReport, bool duplicate) override; void for_each(std::function)> f) override; diff --git a/include/xrpl/nodestore/detail/EncodedBlob.h b/include/xrpl/nodestore/detail/EncodedBlob.h index 2cd35a7b6f..a4c553cf71 100644 --- a/include/xrpl/nodestore/detail/EncodedBlob.h +++ b/include/xrpl/nodestore/detail/EncodedBlob.h @@ -44,10 +44,7 @@ class EncodedBlob 1024 more bytes. The precise size is calculated automatically at compile time so as to avoid wasting space on padding bytes. */ - std::array< - std::uint8_t, - boost::alignment::align_up(9 + 1024, alignof(std::uint32_t))> - payload_; + std::array payload_; /** The size of the serialized data. */ std::uint32_t size_; @@ -62,19 +59,14 @@ class EncodedBlob public: explicit EncodedBlob(std::shared_ptr const& obj) : size_([&obj]() { - XRPL_ASSERT( - obj, - "xrpl::NodeStore::EncodedBlob::EncodedBlob : non-null input"); + XRPL_ASSERT(obj, "xrpl::NodeStore::EncodedBlob::EncodedBlob : non-null input"); if (!obj) - throw std::runtime_error( - "EncodedBlob: unseated std::shared_ptr used."); + throw std::runtime_error("EncodedBlob: unseated std::shared_ptr used."); return obj->getData().size() + 9; }()) - , ptr_( - (size_ <= payload_.size()) ? payload_.data() - : new std::uint8_t[size_]) + , ptr_((size_ <= payload_.size()) ? payload_.data() : new std::uint8_t[size_]) { std::fill_n(ptr_, 8, std::uint8_t{0}); ptr_[8] = static_cast(obj->getType()); diff --git a/include/xrpl/nodestore/detail/ManagerImp.h b/include/xrpl/nodestore/detail/ManagerImp.h index fd3de8a7ca..eb3ee21db4 100644 --- a/include/xrpl/nodestore/detail/ManagerImp.h +++ b/include/xrpl/nodestore/detail/ManagerImp.h @@ -34,11 +34,8 @@ public: erase(Factory& factory) override; std::unique_ptr - make_Backend( - Section const& parameters, - std::size_t burstSize, - Scheduler& scheduler, - beast::Journal journal) override; + make_Backend(Section const& parameters, std::size_t burstSize, Scheduler& scheduler, beast::Journal journal) + override; std::unique_ptr make_Database( diff --git a/include/xrpl/nodestore/detail/codec.h b/include/xrpl/nodestore/detail/codec.h index e02d3963bd..adbf214ce5 100644 --- a/include/xrpl/nodestore/detail/codec.h +++ b/include/xrpl/nodestore/detail/codec.h @@ -30,8 +30,7 @@ lz4_decompress(void const* in, std::size_t in_size, BufferFactory&& bf) std::size_t outSize = 0; - auto const n = read_varint( - reinterpret_cast(in), in_size, outSize); + auto const n = read_varint(reinterpret_cast(in), in_size, outSize); if (n == 0 || n >= in_size) Throw("lz4_decompress: invalid blob"); @@ -64,11 +63,8 @@ lz4_compress(void const* in, std::size_t in_size, BufferFactory&& bf) std::uint8_t* out = reinterpret_cast(bf(n + out_max)); result.first = out; std::memcpy(out, vi.data(), n); - auto const out_size = LZ4_compress_default( - reinterpret_cast(in), - reinterpret_cast(out + n), - in_size, - out_max); + auto const out_size = + LZ4_compress_default(reinterpret_cast(in), reinterpret_cast(out + n), in_size, out_max); if (out_size == 0) Throw("lz4 compress"); result.second = n + out_size; @@ -119,9 +115,8 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf) auto const hs = field::size; // Mask if (in_size < hs + 32) Throw( - "nodeobject codec v1: short inner node size: " + - std::string("in_size = ") + std::to_string(in_size) + - " hs = " + std::to_string(hs)); + "nodeobject codec v1: short inner node size: " + std::string("in_size = ") + + std::to_string(in_size) + " hs = " + std::to_string(hs)); istream is(p, in_size); std::uint16_t mask; read(is, mask); // Mask @@ -133,11 +128,9 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf) write(os, 0); write(os, 0); write(os, hotUNKNOWN); - write( - os, static_cast(HashPrefix::innerNode)); + write(os, static_cast(HashPrefix::innerNode)); if (mask == 0) - Throw( - "nodeobject codec v1: empty inner node"); + Throw("nodeobject codec v1: empty inner node"); std::uint16_t bit = 0x8000; for (int i = 16; i--; bit >>= 1) { @@ -145,10 +138,8 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf) { if (in_size < 32) Throw( - "nodeobject codec v1: short inner node subsize: " + - std::string("in_size = ") + - std::to_string(in_size) + - " i = " + std::to_string(i)); + "nodeobject codec v1: short inner node subsize: " + std::string("in_size = ") + + std::to_string(in_size) + " i = " + std::to_string(i)); std::memcpy(os.data(32), is(32), 32); in_size -= 32; } @@ -158,17 +149,14 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf) } } if (in_size > 0) - Throw( - "nodeobject codec v1: long inner node, in_size = " + - std::to_string(in_size)); + Throw("nodeobject codec v1: long inner node, in_size = " + std::to_string(in_size)); break; } case 3: // full v1 inner node { if (in_size != 16 * 32) // hashes Throw( - "nodeobject codec v1: short full inner node, in_size = " + - std::to_string(in_size)); + "nodeobject codec v1: short full inner node, in_size = " + std::to_string(in_size)); istream is(p, in_size); result.second = 525; void* const out = bf(result.second); @@ -177,14 +165,12 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf) write(os, 0); write(os, 0); write(os, hotUNKNOWN); - write( - os, static_cast(HashPrefix::innerNode)); + write(os, static_cast(HashPrefix::innerNode)); write(os, is(512), 512); break; } default: - Throw( - "nodeobject codec: bad type=" + std::to_string(type)); + Throw("nodeobject codec: bad type=" + std::to_string(type)); }; return result; } @@ -238,8 +224,7 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf) auto const vs = size_varint(type); result.second = vs + field::size + // mask n * 32; // hashes - std::uint8_t* out = - reinterpret_cast(bf(result.second)); + std::uint8_t* out = reinterpret_cast(bf(result.second)); result.first = out; ostream os(out, result.second); write(os, type); @@ -251,8 +236,7 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf) auto const type = 3U; auto const vs = size_varint(type); result.second = vs + n * 32; // hashes - std::uint8_t* out = - reinterpret_cast(bf(result.second)); + std::uint8_t* out = reinterpret_cast(bf(result.second)); result.first = out; ostream os(out, result.second); write(os, type); @@ -272,19 +256,17 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf) case 1: // lz4 { std::uint8_t* p; - auto const lzr = NodeStore::lz4_compress( - in, in_size, [&p, &vn, &bf](std::size_t n) { - p = reinterpret_cast(bf(vn + n)); - return p + vn; - }); + auto const lzr = NodeStore::lz4_compress(in, in_size, [&p, &vn, &bf](std::size_t n) { + p = reinterpret_cast(bf(vn + n)); + return p + vn; + }); std::memcpy(p, vi.data(), vn); result.first = p; result.second = vn + lzr.second; break; } default: - Throw( - "nodeobject codec: unknown=" + std::to_string(codecType)); + Throw("nodeobject codec: unknown=" + std::to_string(codecType)); }; return result; } diff --git a/include/xrpl/protocol/AMMCore.h b/include/xrpl/protocol/AMMCore.h index e259089367..cdd99c65eb 100644 --- a/include/xrpl/protocol/AMMCore.h +++ b/include/xrpl/protocol/AMMCore.h @@ -18,8 +18,7 @@ std::uint16_t constexpr AUCTION_SLOT_MAX_AUTH_ACCOUNTS = 4; std::uint32_t constexpr AUCTION_SLOT_FEE_SCALE_FACTOR = 100000; std::uint32_t constexpr AUCTION_SLOT_DISCOUNTED_FEE_FRACTION = 10; std::uint32_t constexpr AUCTION_SLOT_MIN_FEE_FRACTION = 25; -std::uint32_t constexpr AUCTION_SLOT_INTERVAL_DURATION = - TOTAL_TIME_SLOT_SECS / AUCTION_SLOT_TIME_INTERVALS; +std::uint32_t constexpr AUCTION_SLOT_INTERVAL_DURATION = TOTAL_TIME_SLOT_SECS / AUCTION_SLOT_TIME_INTERVALS; // Votes std::uint16_t constexpr VOTE_MAX_SLOTS = 8; @@ -37,10 +36,7 @@ ammLPTCurrency(Currency const& cur1, Currency const& cur2); /** Calculate LPT Issue from AMM asset pair. */ Issue -ammLPTIssue( - Currency const& cur1, - Currency const& cur2, - AccountID const& ammAccountID); +ammLPTIssue(Currency const& cur1, Currency const& cur2, AccountID const& ammAccountID); /** Validate the amount. * If validZero is false and amount is beast::zero then invalid amount. @@ -54,9 +50,7 @@ invalidAMMAmount( bool validZero = false); NotTEC -invalidAMMAsset( - Issue const& issue, - std::optional> const& pair = std::nullopt); +invalidAMMAsset(Issue const& issue, std::optional> const& pair = std::nullopt); NotTEC invalidAMMAssetPair( diff --git a/include/xrpl/protocol/AmountConversions.h b/include/xrpl/protocol/AmountConversions.h index 2cdccecabb..d4a66c5d94 100644 --- a/include/xrpl/protocol/AmountConversions.h +++ b/include/xrpl/protocol/AmountConversions.h @@ -34,8 +34,7 @@ toSTAmount(XRPAmount const& xrp) inline STAmount toSTAmount(XRPAmount const& xrp, Issue const& iss) { - XRPL_ASSERT( - isXRP(iss.account) && isXRP(iss.currency), "xrpl::toSTAmount : is XRP"); + XRPL_ASSERT(isXRP(iss.account) && isXRP(iss.currency), "xrpl::toSTAmount : is XRP"); return toSTAmount(xrp); } @@ -55,11 +54,9 @@ inline IOUAmount toAmount(STAmount const& amt) { XRPL_ASSERT( - amt.mantissa() < std::numeric_limits::max(), - "xrpl::toAmount : maximum mantissa"); + amt.mantissa() < std::numeric_limits::max(), "xrpl::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); - std::int64_t const sMant = - isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); + std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); XRPL_ASSERT(!isXRP(amt), "xrpl::toAmount : is not XRP"); return IOUAmount(sMant, amt.exponent()); @@ -70,11 +67,9 @@ inline XRPAmount toAmount(STAmount const& amt) { XRPL_ASSERT( - amt.mantissa() < std::numeric_limits::max(), - "xrpl::toAmount : maximum mantissa"); + amt.mantissa() < std::numeric_limits::max(), "xrpl::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); - std::int64_t const sMant = - isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); + std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); XRPL_ASSERT(isXRP(amt), "xrpl::toAmount : is XRP"); return XRPAmount(sMant); @@ -104,10 +99,7 @@ toAmount(XRPAmount const& amt) template T -toAmount( - Issue const& issue, - Number const& n, - Number::rounding_mode mode = Number::getround()) +toAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Number::getround()) { saveNumberRoundMode rm(Number::getround()); if (isXRP(issue)) @@ -141,8 +133,7 @@ toMaxAmount(Issue const& issue) else if constexpr (std::is_same_v) { if (isXRP(issue)) - return STAmount( - issue, static_cast(STAmount::cMaxNativeN)); + return STAmount(issue, static_cast(STAmount::cMaxNativeN)); return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset); } else @@ -153,10 +144,7 @@ toMaxAmount(Issue const& issue) } inline STAmount -toSTAmount( - Issue const& issue, - Number const& n, - Number::rounding_mode mode = Number::getround()) +toSTAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Number::getround()) { return toAmount(issue, n, mode); } diff --git a/include/xrpl/protocol/ApiVersion.h b/include/xrpl/protocol/ApiVersion.h index d1a84e76b0..b8dc8ecb20 100644 --- a/include/xrpl/protocol/ApiVersion.h +++ b/include/xrpl/protocol/ApiVersion.h @@ -42,18 +42,15 @@ constexpr static auto apiInvalidVersion = apiVersion<0>; constexpr static auto apiMinimumSupportedVersion = apiVersion<1>; constexpr static auto apiMaximumSupportedVersion = apiVersion<2>; constexpr static auto apiVersionIfUnspecified = apiVersion<1>; -constexpr static auto apiCommandLineVersion = - apiVersion<1>; // TODO Bump to 2 later +constexpr static auto apiCommandLineVersion = apiVersion<1>; // TODO Bump to 2 later constexpr static auto apiBetaVersion = apiVersion<3>; constexpr static auto apiMaximumValidVersion = apiBetaVersion; static_assert(apiInvalidVersion < apiMinimumSupportedVersion); static_assert( - apiVersionIfUnspecified >= apiMinimumSupportedVersion && - apiVersionIfUnspecified <= apiMaximumSupportedVersion); + apiVersionIfUnspecified >= apiMinimumSupportedVersion && apiVersionIfUnspecified <= apiMaximumSupportedVersion); static_assert( - apiCommandLineVersion >= apiMinimumSupportedVersion && - apiCommandLineVersion <= apiMaximumSupportedVersion); + apiCommandLineVersion >= apiMinimumSupportedVersion && apiCommandLineVersion <= apiMaximumSupportedVersion); static_assert(apiMaximumSupportedVersion >= apiMinimumSupportedVersion); static_assert(apiBetaVersion >= apiMaximumSupportedVersion); static_assert(apiMaximumValidVersion >= apiMaximumSupportedVersion); @@ -61,9 +58,7 @@ static_assert(apiMaximumValidVersion >= apiMaximumSupportedVersion); inline void setVersion(Json::Value& parent, unsigned int apiVersion, bool betaEnabled) { - XRPL_ASSERT( - apiVersion != apiInvalidVersion, - "xrpl::RPC::setVersion : input is valid"); + XRPL_ASSERT(apiVersion != apiInvalidVersion, "xrpl::RPC::setVersion : input is valid"); auto& retObj = parent[jss::version] = Json::objectValue; @@ -81,8 +76,7 @@ setVersion(Json::Value& parent, unsigned int apiVersion, bool betaEnabled) else { retObj[jss::first] = apiMinimumSupportedVersion.value; - retObj[jss::last] = - betaEnabled ? apiBetaVersion : apiMaximumSupportedVersion; + retObj[jss::last] = betaEnabled ? apiBetaVersion : apiMaximumSupportedVersion; } } @@ -104,8 +98,7 @@ inline unsigned int getAPIVersionNumber(Json::Value const& jv, bool betaEnabled) { static Json::Value const minVersion(RPC::apiMinimumSupportedVersion); - Json::Value const maxVersion( - betaEnabled ? RPC::apiBetaVersion : RPC::apiMaximumSupportedVersion); + Json::Value const maxVersion(betaEnabled ? RPC::apiBetaVersion : RPC::apiMaximumSupportedVersion); if (jv.isObject()) { @@ -117,8 +110,7 @@ getAPIVersionNumber(Json::Value const& jv, bool betaEnabled) return RPC::apiInvalidVersion; } auto const specifiedVersionInt = specifiedVersion.asInt(); - if (specifiedVersionInt < minVersion || - specifiedVersionInt > maxVersion) + if (specifiedVersionInt < minVersion || specifiedVersionInt > maxVersion) { return RPC::apiInvalidVersion; } @@ -138,18 +130,13 @@ forApiVersions(Fn const& fn, Args&&... args) (maxVer >= minVer) && // (minVer >= RPC::apiMinimumSupportedVersion) && // (RPC::apiMaximumValidVersion >= maxVer) && requires { - fn(std::integral_constant{}, - std::forward(args)...); - fn(std::integral_constant{}, - std::forward(args)...); + fn(std::integral_constant{}, std::forward(args)...); + fn(std::integral_constant{}, std::forward(args)...); } { constexpr auto size = maxVer + 1 - minVer; [&](std::index_sequence) { - (((void)fn( - std::integral_constant{}, - std::forward(args)...)), - ...); + (((void)fn(std::integral_constant{}, std::forward(args)...)), ...); }(std::make_index_sequence{}); } @@ -157,14 +144,10 @@ template void forAllApiVersions(Fn const& fn, Args&&... args) requires requires { - forApiVersions< - RPC::apiMinimumSupportedVersion, - RPC::apiMaximumValidVersion>(fn, std::forward(args)...); + forApiVersions(fn, std::forward(args)...); } { - forApiVersions< - RPC::apiMinimumSupportedVersion, - RPC::apiMaximumValidVersion>(fn, std::forward(args)...); + forApiVersions(fn, std::forward(args)...); } } // namespace xrpl diff --git a/include/xrpl/protocol/Asset.h b/include/xrpl/protocol/Asset.h index b72c20d82c..e7852cdefe 100644 --- a/include/xrpl/protocol/Asset.h +++ b/include/xrpl/protocol/Asset.h @@ -12,12 +12,10 @@ class Asset; class STAmount; template -concept ValidIssueType = - std::is_same_v || std::is_same_v; +concept ValidIssueType = std::is_same_v || std::is_same_v; template -concept AssetType = - std::is_convertible_v || std::is_convertible_v || +concept AssetType = std::is_convertible_v || std::is_convertible_v || std::is_convertible_v || std::is_convertible_v; /* Asset is an abstraction of three different issue types: XRP, IOU, MPT. @@ -163,8 +161,7 @@ constexpr bool operator==(Asset const& lhs, Asset const& rhs) { return std::visit( - [&]( - TLhs const& issLhs, TRhs const& issRhs) { + [&](TLhs const& issLhs, TRhs const& issRhs) { if constexpr (std::is_same_v) return issLhs == issRhs; else @@ -178,12 +175,10 @@ constexpr std::weak_ordering operator<=>(Asset const& lhs, Asset const& rhs) { return std::visit( - []( - TLhs const& lhs_, TRhs const& rhs_) { + [](TLhs const& lhs_, TRhs const& rhs_) { if constexpr (std::is_same_v) return std::weak_ordering(lhs_ <=> rhs_); - else if constexpr ( - std::is_same_v && std::is_same_v) + else if constexpr (std::is_same_v && std::is_same_v) return std::weak_ordering::greater; else return std::weak_ordering::less; @@ -202,14 +197,10 @@ constexpr bool equalTokens(Asset const& lhs, Asset const& rhs) { return std::visit( - [&]( - TLhs const& issLhs, TRhs const& issRhs) { - if constexpr ( - std::is_same_v && std::is_same_v) + [&](TLhs const& issLhs, TRhs const& issRhs) { + if constexpr (std::is_same_v && std::is_same_v) return issLhs.currency == issRhs.currency; - else if constexpr ( - std::is_same_v && - std::is_same_v) + else if constexpr (std::is_same_v && std::is_same_v) return issLhs.getMptID() == issRhs.getMptID(); else return false; diff --git a/include/xrpl/protocol/Batch.h b/include/xrpl/protocol/Batch.h index 1404c8069f..91fb8e5a9d 100644 --- a/include/xrpl/protocol/Batch.h +++ b/include/xrpl/protocol/Batch.h @@ -5,10 +5,7 @@ namespace xrpl { inline void -serializeBatch( - Serializer& msg, - std::uint32_t const& flags, - std::vector const& txids) +serializeBatch(Serializer& msg, std::uint32_t const& flags, std::vector const& txids) { msg.add32(HashPrefix::batch); msg.add32(flags); diff --git a/include/xrpl/protocol/Book.h b/include/xrpl/protocol/Book.h index ddd315de30..9e26af9f79 100644 --- a/include/xrpl/protocol/Book.h +++ b/include/xrpl/protocol/Book.h @@ -24,10 +24,7 @@ public: { } - Book( - Issue const& in_, - Issue const& out_, - std::optional const& domain_) + Book(Issue const& in_, Issue const& out_, std::optional const& domain_) : in(in_), out(out_), domain(domain_) { } @@ -60,8 +57,7 @@ reversed(Book const& book); [[nodiscard]] inline constexpr bool operator==(Book const& lhs, Book const& rhs) { - return (lhs.in == rhs.in) && (lhs.out == rhs.out) && - (lhs.domain == rhs.domain); + return (lhs.in == rhs.in) && (lhs.out == rhs.out) && (lhs.domain == rhs.domain); } /** @} */ @@ -94,15 +90,12 @@ operator<=>(Book const& lhs, Book const& rhs) namespace std { template <> -struct hash - : private boost::base_from_member, 0>, - private boost::base_from_member, 1> +struct hash : private boost::base_from_member, 0>, + private boost::base_from_member, 1> { private: - using currency_hash_type = - boost::base_from_member, 0>; - using issuer_hash_type = - boost::base_from_member, 1>; + using currency_hash_type = boost::base_from_member, 0>; + using issuer_hash_type = boost::base_from_member, 1>; public: hash() = default; @@ -115,8 +108,7 @@ public: { value_type result(currency_hash_type::member(value.currency)); if (!isXRP(value.currency)) - boost::hash_combine( - result, issuer_hash_type::member(value.account)); + boost::hash_combine(result, issuer_hash_type::member(value.account)); return result; } }; diff --git a/include/xrpl/protocol/ErrorCodes.h b/include/xrpl/protocol/ErrorCodes.h index 3a2645347a..172c3fd57f 100644 --- a/include/xrpl/protocol/ErrorCodes.h +++ b/include/xrpl/protocol/ErrorCodes.h @@ -142,8 +142,7 @@ enum error_code_i { rpcENTRY_NOT_FOUND = 98, rpcUNEXPECTED_LEDGER_TYPE = 99, - rpcLAST = - rpcUNEXPECTED_LEDGER_TYPE // rpcLAST should always equal the last code. + rpcLAST = rpcUNEXPECTED_LEDGER_TYPE // rpcLAST should always equal the last code. }; /** Codes returned in the `warnings` array of certain RPC commands. @@ -169,31 +168,17 @@ namespace RPC { struct ErrorInfo { // Default ctor needed to produce an empty std::array during constexpr eval. - constexpr ErrorInfo() - : code(rpcUNKNOWN) - , token("unknown") - , message("An unknown error code.") - , http_status(200) + constexpr ErrorInfo() : code(rpcUNKNOWN), token("unknown"), message("An unknown error code."), http_status(200) { } - constexpr ErrorInfo( - error_code_i code_, - char const* token_, - char const* message_) + constexpr ErrorInfo(error_code_i code_, char const* token_, char const* message_) : code(code_), token(token_), message(message_), http_status(200) { } - constexpr ErrorInfo( - error_code_i code_, - char const* token_, - char const* message_, - int http_status_) - : code(code_) - , token(token_) - , message(message_) - , http_status(http_status_) + constexpr ErrorInfo(error_code_i code_, char const* token_, char const* message_, int http_status_) + : code(code_), token(token_), message(message_), http_status(http_status_) { } diff --git a/include/xrpl/protocol/Feature.h b/include/xrpl/protocol/Feature.h index 317bde3ee6..fac6627b1c 100644 --- a/include/xrpl/protocol/Feature.h +++ b/include/xrpl/protocol/Feature.h @@ -175,9 +175,7 @@ public: explicit FeatureBitset(base const& b) : base(b) { - XRPL_ASSERT( - b.count() == count(), - "xrpl::FeatureBitset::FeatureBitset(base) : count match"); + XRPL_ASSERT(b.count() == count(), "xrpl::FeatureBitset::FeatureBitset(base) : count match"); } template @@ -257,8 +255,7 @@ public: friend FeatureBitset operator&(FeatureBitset const& lhs, FeatureBitset const& rhs) { - return FeatureBitset{ - static_cast(lhs) & static_cast(rhs)}; + return FeatureBitset{static_cast(lhs) & static_cast(rhs)}; } friend FeatureBitset @@ -276,8 +273,7 @@ public: friend FeatureBitset operator|(FeatureBitset const& lhs, FeatureBitset const& rhs) { - return FeatureBitset{ - static_cast(lhs) | static_cast(rhs)}; + return FeatureBitset{static_cast(lhs) | static_cast(rhs)}; } friend FeatureBitset @@ -295,8 +291,7 @@ public: friend FeatureBitset operator^(FeatureBitset const& lhs, FeatureBitset const& rhs) { - return FeatureBitset{ - static_cast(lhs) ^ static_cast(rhs)}; + return FeatureBitset{static_cast(lhs) ^ static_cast(rhs)}; } friend FeatureBitset diff --git a/include/xrpl/protocol/HashPrefix.h b/include/xrpl/protocol/HashPrefix.h index 39e03bf94f..babba3f7bd 100644 --- a/include/xrpl/protocol/HashPrefix.h +++ b/include/xrpl/protocol/HashPrefix.h @@ -12,8 +12,7 @@ namespace detail { constexpr std::uint32_t make_hash_prefix(char a, char b, char c) { - return (static_cast(a) << 24) + - (static_cast(b) << 16) + + return (static_cast(a) << 24) + (static_cast(b) << 16) + (static_cast(c) << 8); } diff --git a/include/xrpl/protocol/IOUAmount.h b/include/xrpl/protocol/IOUAmount.h index 405de18e29..960f8c4521 100644 --- a/include/xrpl/protocol/IOUAmount.h +++ b/include/xrpl/protocol/IOUAmount.h @@ -22,8 +22,7 @@ namespace xrpl { if the amount exceeds the largest representable amount, but underflows will silently truncate to zero. */ -class IOUAmount : private boost::totally_ordered, - private boost::additive +class IOUAmount : private boost::totally_ordered, private boost::additive { private: using mantissa_type = std::int64_t; @@ -97,8 +96,7 @@ inline IOUAmount::IOUAmount(beast::Zero) *this = beast::zero; } -inline IOUAmount::IOUAmount(mantissa_type mantissa, exponent_type exponent) - : mantissa_(mantissa), exponent_(exponent) +inline IOUAmount::IOUAmount(mantissa_type mantissa, exponent_type exponent) : mantissa_(mantissa), exponent_(exponent) { normalize(); } @@ -175,11 +173,7 @@ to_string(IOUAmount const& amount); dividing by den. */ IOUAmount -mulRatio( - IOUAmount const& amt, - std::uint32_t num, - std::uint32_t den, - bool roundUp); +mulRatio(IOUAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundUp); // Since many uses of the number class do not have access to a ledger, // getSTNumberSwitchover needs to be globally accessible. diff --git a/include/xrpl/protocol/Indexes.h b/include/xrpl/protocol/Indexes.h index 777c3b8aa9..2ce3b7ad6b 100644 --- a/include/xrpl/protocol/Indexes.h +++ b/include/xrpl/protocol/Indexes.h @@ -94,10 +94,7 @@ static book_t const book{}; */ /** @{ */ Keylet -line( - AccountID const& id0, - AccountID const& id1, - Currency const& currency) noexcept; +line(AccountID const& id0, AccountID const& id1, Currency const& currency) noexcept; inline Keylet line(AccountID const& id, Issue const& issue) noexcept @@ -173,9 +170,7 @@ Keylet depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept; Keylet -depositPreauth( - AccountID const& owner, - std::set> const& authCreds) noexcept; +depositPreauth(AccountID const& owner, std::set> const& authCreds) noexcept; inline Keylet depositPreauth(uint256 const& key) noexcept @@ -202,8 +197,7 @@ page(uint256 const& root, std::uint64_t index = 0) noexcept; inline Keylet page(Keylet const& root, std::uint64_t index = 0) noexcept { - XRPL_ASSERT( - root.type == ltDIR_NODE, "xrpl::keylet::page : valid root type"); + XRPL_ASSERT(root.type == ltDIR_NODE, "xrpl::keylet::page : valid root type"); return page(root.key, index); } /** @} */ @@ -283,10 +277,7 @@ Keylet oracle(AccountID const& account, std::uint32_t const& documentID) noexcept; Keylet -credential( - AccountID const& subject, - AccountID const& issuer, - Slice const& credType) noexcept; +credential(AccountID const& subject, AccountID const& issuer, Slice const& credType) noexcept; inline Keylet credential(uint256 const& key) noexcept diff --git a/include/xrpl/protocol/Issue.h b/include/xrpl/protocol/Issue.h index a76b7a8316..f7da457986 100644 --- a/include/xrpl/protocol/Issue.h +++ b/include/xrpl/protocol/Issue.h @@ -72,8 +72,7 @@ hash_append(Hasher& h, Issue const& r) [[nodiscard]] inline constexpr bool operator==(Issue const& lhs, Issue const& rhs) { - return (lhs.currency == rhs.currency) && - (isXRP(lhs.currency) || lhs.account == rhs.account); + return (lhs.currency == rhs.currency) && (isXRP(lhs.currency) || lhs.account == rhs.account); } /** @} */ diff --git a/include/xrpl/protocol/KnownFormats.h b/include/xrpl/protocol/KnownFormats.h index a928ed52be..58a2710bef 100644 --- a/include/xrpl/protocol/KnownFormats.h +++ b/include/xrpl/protocol/KnownFormats.h @@ -37,8 +37,7 @@ public: { // Verify that KeyType is appropriate. static_assert( - std::is_enum::value || - std::is_integral::value, + std::is_enum::value || std::is_integral::value, "KnownFormats KeyType must be integral or enum."); } @@ -100,8 +99,7 @@ public: if (auto const result = findByName(name)) return result->getType(); Throw( - name_ + ": Unknown format name '" + - name.substr(0, std::min(name.size(), std::size_t(32))) + "'"); + name_ + ": Unknown format name '" + name.substr(0, std::min(name.size(), std::size_t(32))) + "'"); } /** Retrieve a format based on its type. @@ -157,9 +155,7 @@ protected: { if (auto const item = findByType(type)) { - LogicError( - std::string("Duplicate key for item '") + name + - "': already maps to " + item->getName()); + LogicError(std::string("Duplicate key for item '") + name + "': already maps to " + item->getName()); } formats_.emplace_front(name, type, uniqueFields, commonFields); diff --git a/include/xrpl/protocol/MPTAmount.h b/include/xrpl/protocol/MPTAmount.h index cc9528a923..be24d4de7f 100644 --- a/include/xrpl/protocol/MPTAmount.h +++ b/include/xrpl/protocol/MPTAmount.h @@ -123,11 +123,7 @@ to_string(MPTAmount const& amount) } inline MPTAmount -mulRatio( - MPTAmount const& amt, - std::uint32_t num, - std::uint32_t den, - bool roundUp) +mulRatio(MPTAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundUp) { using namespace boost::multiprecision; diff --git a/include/xrpl/protocol/MultiApiJson.h b/include/xrpl/protocol/MultiApiJson.h index edf19b6f37..9fdb85f648 100644 --- a/include/xrpl/protocol/MultiApiJson.h +++ b/include/xrpl/protocol/MultiApiJson.h @@ -84,80 +84,48 @@ struct MultiApiJson static constexpr struct visitor_t final { // integral_constant version, extra arguments - template < - typename Json, - unsigned int Version, - typename... Args, - typename Fn> + template requires std::same_as, MultiApiJson> auto - operator()( - Json& json, - std::integral_constant const version, - Fn fn, - Args&&... args) const - -> std::invoke_result_t< - Fn, - decltype(json.val[0]), - std::integral_constant, - Args&&...> + operator()(Json& json, std::integral_constant const version, Fn fn, Args&&... args) const + -> std::invoke_result_t, Args&&...> { - static_assert( - valid(Version) && index(Version) >= 0 && index(Version) < size); - return std::invoke( - fn, - json.val[index(Version)], - version, - std::forward(args)...); + static_assert(valid(Version) && index(Version) >= 0 && index(Version) < size); + return std::invoke(fn, json.val[index(Version)], version, std::forward(args)...); } // integral_constant version, Json only template requires std::same_as, MultiApiJson> auto - operator()( - Json& json, - std::integral_constant const, - Fn fn) const -> std::invoke_result_t + operator()(Json& json, std::integral_constant const, Fn fn) const + -> std::invoke_result_t { - static_assert( - valid(Version) && index(Version) >= 0 && index(Version) < size); + static_assert(valid(Version) && index(Version) >= 0 && index(Version) < size); return std::invoke(fn, json.val[index(Version)]); } // unsigned int version, extra arguments - template < - typename Json, - typename Version, - typename... Args, - typename Fn> - requires(!some_integral_constant) && - std::convertible_to && + template + requires(!some_integral_constant) && std::convertible_to && std::same_as, MultiApiJson> auto operator()(Json& json, Version version, Fn fn, Args&&... args) const - -> std:: - invoke_result_t + -> std::invoke_result_t { XRPL_ASSERT( valid(version) && index(version) >= 0 && index(version) < size, "xrpl::detail::MultiApiJson::operator() : valid " "version"); - return std::invoke( - fn, - json.val[index(version)], - version, - std::forward(args)...); + return std::invoke(fn, json.val[index(version)], version, std::forward(args)...); } // unsigned int version, Json only template - requires(!some_integral_constant) && - std::convertible_to && + requires(!some_integral_constant) && std::convertible_to && std::same_as, MultiApiJson> auto - operator()(Json& json, Version version, Fn fn) const - -> std::invoke_result_t + operator()(Json& json, Version version, Fn fn) const -> std::invoke_result_t { XRPL_ASSERT( valid(version) && index(version) >= 0 && index(version) < size, @@ -170,11 +138,7 @@ struct MultiApiJson visit() { return [self = this](auto... args) - requires requires { - visitor( - std::declval(), - std::declval()...); - } + requires requires { visitor(std::declval(), std::declval()...); } { return visitor(*self, std::forward(args)...); }; } @@ -182,30 +146,22 @@ struct MultiApiJson visit() const { return [self = this](auto... args) - requires requires { - visitor( - std::declval(), - std::declval()...); - } + requires requires { visitor(std::declval(), std::declval()...); } { return visitor(*self, std::forward(args)...); }; } template auto - visit(Args... args) - -> std::invoke_result_t - requires(sizeof...(args) > 0) && - requires { visitor(*this, std::forward(args)...); } + visit(Args... args) -> std::invoke_result_t + requires(sizeof...(args) > 0) && requires { visitor(*this, std::forward(args)...); } { return visitor(*this, std::forward(args)...); } template auto - visit(Args... args) const - -> std::invoke_result_t - requires(sizeof...(args) > 0) && - requires { visitor(*this, std::forward(args)...); } + visit(Args... args) const -> std::invoke_result_t + requires(sizeof...(args) > 0) && requires { visitor(*this, std::forward(args)...); } { return visitor(*this, std::forward(args)...); } @@ -214,8 +170,7 @@ struct MultiApiJson } // namespace detail // Wrapper for Json for all supported API versions. -using MultiApiJson = detail:: - MultiApiJson; +using MultiApiJson = detail::MultiApiJson; } // namespace xrpl diff --git a/include/xrpl/protocol/NFTSyntheticSerializer.h b/include/xrpl/protocol/NFTSyntheticSerializer.h index 7068ae34cd..5f7e061454 100644 --- a/include/xrpl/protocol/NFTSyntheticSerializer.h +++ b/include/xrpl/protocol/NFTSyntheticSerializer.h @@ -17,10 +17,7 @@ namespace RPC { @{ */ void -insertNFTSyntheticInJson( - Json::Value&, - std::shared_ptr const&, - TxMeta const&); +insertNFTSyntheticInJson(Json::Value&, std::shared_ptr const&, TxMeta const&); /** @} */ } // namespace RPC diff --git a/include/xrpl/protocol/NFTokenID.h b/include/xrpl/protocol/NFTokenID.h index 03e30794d0..0cddfa6d55 100644 --- a/include/xrpl/protocol/NFTokenID.h +++ b/include/xrpl/protocol/NFTokenID.h @@ -21,9 +21,7 @@ namespace xrpl { @{ */ bool -canHaveNFTokenID( - std::shared_ptr const& serializedTx, - TxMeta const& transactionMeta); +canHaveNFTokenID(std::shared_ptr const& serializedTx, TxMeta const& transactionMeta); std::optional getNFTokenIDFromPage(TxMeta const& transactionMeta); @@ -32,10 +30,7 @@ std::vector getNFTokenIDFromDeletedOffer(TxMeta const& transactionMeta); void -insertNFTokenID( - Json::Value& response, - std::shared_ptr const& transaction, - TxMeta const& transactionMeta); +insertNFTokenID(Json::Value& response, std::shared_ptr const& transaction, TxMeta const& transactionMeta); /** @} */ } // namespace xrpl diff --git a/include/xrpl/protocol/NFTokenOfferID.h b/include/xrpl/protocol/NFTokenOfferID.h index 5663653690..da358a9b84 100644 --- a/include/xrpl/protocol/NFTokenOfferID.h +++ b/include/xrpl/protocol/NFTokenOfferID.h @@ -19,9 +19,7 @@ namespace xrpl { @{ */ bool -canHaveNFTokenOfferID( - std::shared_ptr const& serializedTx, - TxMeta const& transactionMeta); +canHaveNFTokenOfferID(std::shared_ptr const& serializedTx, TxMeta const& transactionMeta); std::optional getOfferIDFromCreatedOffer(TxMeta const& transactionMeta); diff --git a/include/xrpl/protocol/PayChan.h b/include/xrpl/protocol/PayChan.h index ad70913c45..a991f124ff 100644 --- a/include/xrpl/protocol/PayChan.h +++ b/include/xrpl/protocol/PayChan.h @@ -9,10 +9,7 @@ namespace xrpl { inline void -serializePayChanAuthorization( - Serializer& msg, - uint256 const& key, - XRPAmount const& amt) +serializePayChanAuthorization(Serializer& msg, uint256 const& key, XRPAmount const& amt) { msg.add32(HashPrefix::paymentChannelClaim); msg.addBitString(key); diff --git a/include/xrpl/protocol/Permissions.h b/include/xrpl/protocol/Permissions.h index 74f539a3bf..0e3bb970bd 100644 --- a/include/xrpl/protocol/Permissions.h +++ b/include/xrpl/protocol/Permissions.h @@ -40,8 +40,7 @@ private: std::unordered_map delegableTx_; - std::unordered_map - granularPermissionMap_; + std::unordered_map granularPermissionMap_; std::unordered_map granularNameMap_; diff --git a/include/xrpl/protocol/Protocol.h b/include/xrpl/protocol/Protocol.h index 43be9d3b45..99e224cb91 100644 --- a/include/xrpl/protocol/Protocol.h +++ b/include/xrpl/protocol/Protocol.h @@ -115,8 +115,7 @@ namespace Lending { Valid values are between 0 and 10% inclusive. */ -TenthBips16 constexpr maxManagementFeeRate( - unsafe_cast(percentageToTenthBips(10).value())); +TenthBips16 constexpr maxManagementFeeRate(unsafe_cast(percentageToTenthBips(10).value())); static_assert(maxManagementFeeRate == TenthBips16(std::uint16_t(10'000u))); /** The maximum coverage rate required of a loan broker in 1/10 bips. diff --git a/include/xrpl/protocol/PublicKey.h b/include/xrpl/protocol/PublicKey.h index 51a7683ebc..0d95fa5818 100644 --- a/include/xrpl/protocol/PublicKey.h +++ b/include/xrpl/protocol/PublicKey.h @@ -126,11 +126,7 @@ operator==(PublicKey const& lhs, PublicKey const& rhs) inline bool operator<(PublicKey const& lhs, PublicKey const& rhs) { - return std::lexicographical_compare( - lhs.data(), - lhs.data() + lhs.size(), - rhs.data(), - rhs.data() + rhs.size()); + return std::lexicographical_compare(lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size()); } template @@ -275,8 +271,7 @@ getOrThrow(Json::Value const& v, xrpl::SField const& field) { return PublicKey{makeSlice(*pubKeyBlob)}; } - for (auto const tokenType : - {TokenType::NodePublic, TokenType::AccountPublic}) + for (auto const tokenType : {TokenType::NodePublic, TokenType::AccountPublic}) { if (auto const pk = parseBase58(tokenType, b58)) return *pk; diff --git a/include/xrpl/protocol/Quality.h b/include/xrpl/protocol/Quality.h index 83a038490a..d8101d7c1e 100644 --- a/include/xrpl/protocol/Quality.h +++ b/include/xrpl/protocol/Quality.h @@ -115,15 +115,13 @@ public: /** Create a quality from the ratio of two amounts. */ template - explicit Quality(TAmounts const& amount) - : Quality(Amounts(toSTAmount(amount.in), toSTAmount(amount.out))) + explicit Quality(TAmounts const& amount) : Quality(Amounts(toSTAmount(amount.in), toSTAmount(amount.out))) { } /** Create a quality from the ratio of two amounts. */ template - Quality(Out const& out, In const& in) - : Quality(Amounts(toSTAmount(in), toSTAmount(out))) + Quality(Out const& out, In const& in) : Quality(Amounts(toSTAmount(in), toSTAmount(out))) { } @@ -173,15 +171,11 @@ public: // low order bits that could influence rounding decisions. This "strict" // method uses underlying functions that pay attention to all the bits. [[nodiscard]] Amounts - ceil_in_strict(Amounts const& amount, STAmount const& limit, bool roundUp) - const; + ceil_in_strict(Amounts const& amount, STAmount const& limit, bool roundUp) const; template [[nodiscard]] TAmounts - ceil_in_strict( - TAmounts const& amount, - In const& limit, - bool roundUp) const; + ceil_in_strict(TAmounts const& amount, In const& limit, bool roundUp) const; /** Returns the scaled amount with out capped. Math is avoided if the result is exact. The input is clamped @@ -198,26 +192,17 @@ public: // low order bits that could influence rounding decisions. This "strict" // method uses underlying functions that pay attention to all the bits. [[nodiscard]] Amounts - ceil_out_strict(Amounts const& amount, STAmount const& limit, bool roundUp) - const; + ceil_out_strict(Amounts const& amount, STAmount const& limit, bool roundUp) const; template [[nodiscard]] TAmounts - ceil_out_strict( - TAmounts const& amount, - Out const& limit, - bool roundUp) const; + ceil_out_strict(TAmounts const& amount, Out const& limit, bool roundUp) const; private: // The ceil_in and ceil_out methods that deal in TAmount all convert // their arguments to STAmount and convert the result back to TAmount. // This helper function takes care of all the conversion operations. - template < - class In, - class Out, - class Lim, - typename FnPtr, - std::same_as... Round> + template ... Round> [[nodiscard]] TAmounts ceil_TAmounts_helper( TAmounts const& amount, @@ -279,29 +264,22 @@ public: friend double relativeDistance(Quality const& q1, Quality const& q2) { - XRPL_ASSERT( - q1.m_value > 0 && q2.m_value > 0, - "xrpl::Quality::relativeDistance : minimum inputs"); + XRPL_ASSERT(q1.m_value > 0 && q2.m_value > 0, "xrpl::Quality::relativeDistance : minimum inputs"); if (q1.m_value == q2.m_value) // make expected common case fast return 0; auto const [minV, maxV] = std::minmax(q1.m_value, q2.m_value); - auto mantissa = [](std::uint64_t rate) { - return rate & ~(255ull << (64 - 8)); - }; - auto exponent = [](std::uint64_t rate) { - return static_cast(rate >> (64 - 8)) - 100; - }; + auto mantissa = [](std::uint64_t rate) { return rate & ~(255ull << (64 - 8)); }; + auto exponent = [](std::uint64_t rate) { return static_cast(rate >> (64 - 8)) - 100; }; auto const minVMantissa = mantissa(minV); auto const maxVMantissa = mantissa(maxV); auto const expDiff = exponent(maxV) - exponent(minV); double const minVD = static_cast(minVMantissa); - double const maxVD = expDiff ? maxVMantissa * pow(10, expDiff) - : static_cast(maxVMantissa); + double const maxVD = expDiff ? maxVMantissa * pow(10, expDiff) : static_cast(maxVMantissa); // maxVD and minVD are scaled so they have the same exponents. Dividing // cancels out the exponents, so we only need to deal with the (scaled) @@ -310,12 +288,7 @@ public: } }; -template < - class In, - class Out, - class Lim, - typename FnPtr, - std::same_as... Round> +template ... Round> TAmounts Quality::ceil_TAmounts_helper( TAmounts const& amount, @@ -340,25 +313,20 @@ TAmounts Quality::ceil_in(TAmounts const& amount, In const& limit) const { // Construct a function pointer to the function we want to call. - static constexpr Amounts (Quality::*ceil_in_fn_ptr)( - Amounts const&, STAmount const&) const = &Quality::ceil_in; + static constexpr Amounts (Quality::*ceil_in_fn_ptr)(Amounts const&, STAmount const&) const = &Quality::ceil_in; return ceil_TAmounts_helper(amount, limit, amount.in, ceil_in_fn_ptr); } template TAmounts -Quality::ceil_in_strict( - TAmounts const& amount, - In const& limit, - bool roundUp) const +Quality::ceil_in_strict(TAmounts const& amount, In const& limit, bool roundUp) const { // Construct a function pointer to the function we want to call. - static constexpr Amounts (Quality::*ceil_in_fn_ptr)( - Amounts const&, STAmount const&, bool) const = &Quality::ceil_in_strict; + static constexpr Amounts (Quality::*ceil_in_fn_ptr)(Amounts const&, STAmount const&, bool) const = + &Quality::ceil_in_strict; - return ceil_TAmounts_helper( - amount, limit, amount.in, ceil_in_fn_ptr, roundUp); + return ceil_TAmounts_helper(amount, limit, amount.in, ceil_in_fn_ptr, roundUp); } template @@ -366,26 +334,20 @@ TAmounts Quality::ceil_out(TAmounts const& amount, Out const& limit) const { // Construct a function pointer to the function we want to call. - static constexpr Amounts (Quality::*ceil_out_fn_ptr)( - Amounts const&, STAmount const&) const = &Quality::ceil_out; + static constexpr Amounts (Quality::*ceil_out_fn_ptr)(Amounts const&, STAmount const&) const = &Quality::ceil_out; return ceil_TAmounts_helper(amount, limit, amount.out, ceil_out_fn_ptr); } template TAmounts -Quality::ceil_out_strict( - TAmounts const& amount, - Out const& limit, - bool roundUp) const +Quality::ceil_out_strict(TAmounts const& amount, Out const& limit, bool roundUp) const { // Construct a function pointer to the function we want to call. - static constexpr Amounts (Quality::*ceil_out_fn_ptr)( - Amounts const&, STAmount const&, bool) const = + static constexpr Amounts (Quality::*ceil_out_fn_ptr)(Amounts const&, STAmount const&, bool) const = &Quality::ceil_out_strict; - return ceil_TAmounts_helper( - amount, limit, amount.out, ceil_out_fn_ptr, roundUp); + return ceil_TAmounts_helper(amount, limit, amount.out, ceil_out_fn_ptr, roundUp); } /** Calculate the quality of a two-hop path given the two hops. diff --git a/include/xrpl/protocol/QualityFunction.h b/include/xrpl/protocol/QualityFunction.h index b7ec11fa69..2414d86583 100644 --- a/include/xrpl/protocol/QualityFunction.h +++ b/include/xrpl/protocol/QualityFunction.h @@ -38,10 +38,7 @@ public: }; QualityFunction(Quality const& quality, CLOBLikeTag); template - QualityFunction( - TAmounts const& amounts, - std::uint32_t tfee, - AMMTag); + QualityFunction(TAmounts const& amounts, std::uint32_t tfee, AMMTag); /** Combines QF with the next step QF */ @@ -71,10 +68,7 @@ public: }; template -QualityFunction::QualityFunction( - TAmounts const& amounts, - std::uint32_t tfee, - QualityFunction::AMMTag) +QualityFunction::QualityFunction(TAmounts const& amounts, std::uint32_t tfee, QualityFunction::AMMTag) { if (amounts.in <= beast::zero || amounts.out <= beast::zero) Throw("QualityFunction amounts are 0."); diff --git a/include/xrpl/protocol/Rate.h b/include/xrpl/protocol/Rate.h index b8173a9392..86033e9a38 100644 --- a/include/xrpl/protocol/Rate.h +++ b/include/xrpl/protocol/Rate.h @@ -54,11 +54,7 @@ STAmount multiplyRound(STAmount const& amount, Rate const& rate, bool roundUp); STAmount -multiplyRound( - STAmount const& amount, - Rate const& rate, - Asset const& asset, - bool roundUp); +multiplyRound(STAmount const& amount, Rate const& rate, Asset const& asset, bool roundUp); STAmount divide(STAmount const& amount, Rate const& rate); @@ -67,11 +63,7 @@ STAmount divideRound(STAmount const& amount, Rate const& rate, bool roundUp); STAmount -divideRound( - STAmount const& amount, - Rate const& rate, - Asset const& asset, - bool roundUp); +divideRound(STAmount const& amount, Rate const& rate, Asset const& asset, bool roundUp); namespace nft { /** Given a transfer fee (in basis points) convert it to a transfer rate. */ diff --git a/include/xrpl/protocol/Rules.h b/include/xrpl/protocol/Rules.h index 0ae6680d07..8f622c3f1d 100644 --- a/include/xrpl/protocol/Rules.h +++ b/include/xrpl/protocol/Rules.h @@ -47,14 +47,10 @@ public: private: // Allow a friend function to construct Rules. friend Rules - makeRulesGivenLedger( - DigestAwareReadView const& ledger, - Rules const& current); + makeRulesGivenLedger(DigestAwareReadView const& ledger, Rules const& current); friend Rules - makeRulesGivenLedger( - DigestAwareReadView const& ledger, - std::unordered_set> const& presets); + makeRulesGivenLedger(DigestAwareReadView const& ledger, std::unordered_set> const& presets); Rules( std::unordered_set> const& presets, @@ -91,8 +87,7 @@ setCurrentTransactionRules(std::optional r); class CurrentTransactionRulesGuard { public: - explicit CurrentTransactionRulesGuard(Rules r) - : saved_(getCurrentTransactionRules()) + explicit CurrentTransactionRulesGuard(Rules r) : saved_(getCurrentTransactionRules()) { setCurrentTransactionRules(std::move(r)); } diff --git a/include/xrpl/protocol/SField.h b/include/xrpl/protocol/SField.h index 7f404b4d5f..3ca8dbf898 100644 --- a/include/xrpl/protocol/SField.h +++ b/include/xrpl/protocol/SField.h @@ -128,19 +128,18 @@ class SField public: enum { sMD_Never = 0x00, - sMD_ChangeOrig = 0x01, // original value when it changes - sMD_ChangeNew = 0x02, // new value when it changes - sMD_DeleteFinal = 0x04, // final value when it is deleted - sMD_Create = 0x08, // value when it's created - sMD_Always = 0x10, // value when node containing it is affected at all - sMD_BaseTen = 0x20, // value is treated as base 10, overriding behavior + sMD_ChangeOrig = 0x01, // original value when it changes + sMD_ChangeNew = 0x02, // new value when it changes + sMD_DeleteFinal = 0x04, // final value when it is deleted + sMD_Create = 0x08, // value when it's created + sMD_Always = 0x10, // value when node containing it is affected at all + sMD_BaseTen = 0x20, // value is treated as base 10, overriding behavior sMD_PseudoAccount = 0x40, // if this field is set in an ACCOUNT_ROOT // _only_, then it is a pseudo-account sMD_NeedsAsset = 0x80, // This field needs to be associated with an // asset before it is serialized as a ledger // object. Intended for STNumber. - sMD_Default = - sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create + sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create }; enum class IsSigning : unsigned char { no, yes }; @@ -267,8 +266,7 @@ public: bool shouldInclude(bool withSigningField) const { - return (fieldValue < 256) && - (withSigningField || (signingField == IsSigning::yes)); + return (fieldValue < 256) && (withSigningField || (signingField == IsSigning::yes)); } bool @@ -362,10 +360,8 @@ using SF_XCHAIN_BRIDGE = TypedField; #pragma push_macro("TYPED_SFIELD") #undef TYPED_SFIELD -#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \ - extern SField const sfName; -#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \ - extern SF_##stiSuffix const sfName; +#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) extern SField const sfName; +#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) extern SF_##stiSuffix const sfName; extern SField const sfInvalid; extern SField const sfGeneric; diff --git a/include/xrpl/protocol/SOTemplate.h b/include/xrpl/protocol/SOTemplate.h index 559117c274..35be09c5d5 100644 --- a/include/xrpl/protocol/SOTemplate.h +++ b/include/xrpl/protocol/SOTemplate.h @@ -42,24 +42,19 @@ private: auto nm = std::to_string(fieldName.getCode()); if (fieldName.hasName()) nm += ": '" + fieldName.getName() + "'"; - Throw( - "SField (" + nm + ") in SOElement must be useful."); + Throw("SField (" + nm + ") in SOElement must be useful."); } } public: - SOElement(SField const& fieldName, SOEStyle style) - : sField_(fieldName), style_(style) + SOElement(SField const& fieldName, SOEStyle style) : sField_(fieldName), style_(style) { init(fieldName); } template requires(std::is_same_v || std::is_same_v) - SOElement( - TypedField const& fieldName, - SOEStyle style, - SOETxMPTIssue supportMpt = soeMPTNotSupported) + SOElement(TypedField const& fieldName, SOEStyle style, SOETxMPTIssue supportMpt = soeMPTNotSupported) : sField_(fieldName), style_(style), supportMpt_(supportMpt) { init(fieldName); @@ -103,9 +98,7 @@ public: After creating the template fields cannot be added, modified, or removed. */ - SOTemplate( - std::initializer_list uniqueFields, - std::initializer_list commonFields = {}); + SOTemplate(std::initializer_list uniqueFields, std::initializer_list commonFields = {}); /* Provide for the enumeration of fields */ std::vector::const_iterator diff --git a/include/xrpl/protocol/STAmount.h b/include/xrpl/protocol/STAmount.h index 4d86aed2ec..c678205882 100644 --- a/include/xrpl/protocol/STAmount.h +++ b/include/xrpl/protocol/STAmount.h @@ -81,12 +81,7 @@ public: unchecked); template - STAmount( - A const& asset, - mantissa_type mantissa, - exponent_type exponent, - bool negative, - unchecked); + STAmount(A const& asset, mantissa_type mantissa, exponent_type exponent, bool negative, unchecked); // Call canonicalize template @@ -99,36 +94,22 @@ public: STAmount(SField const& name, std::int64_t mantissa); - STAmount( - SField const& name, - std::uint64_t mantissa = 0, - bool negative = false); + STAmount(SField const& name, std::uint64_t mantissa = 0, bool negative = false); explicit STAmount(std::uint64_t mantissa = 0, bool negative = false); explicit STAmount(SField const& name, STAmount const& amt); template - STAmount( - A const& asset, - std::uint64_t mantissa = 0, - int exponent = 0, - bool negative = false) - : mAsset(asset) - , mValue(mantissa) - , mOffset(exponent) - , mIsNegative(negative) + STAmount(A const& asset, std::uint64_t mantissa = 0, int exponent = 0, bool negative = false) + : mAsset(asset), mValue(mantissa), mOffset(exponent), mIsNegative(negative) { canonicalize(); } // VFALCO Is this needed when we have the previous signature? template - STAmount( - A const& asset, - std::uint32_t mantissa, - int exponent = 0, - bool negative = false); + STAmount(A const& asset, std::uint32_t mantissa, int exponent = 0, bool negative = false); template STAmount(A const& asset, std::int64_t mantissa, int exponent = 0); @@ -137,8 +118,7 @@ public: STAmount(A const& asset, int mantissa, int exponent = 0); template - STAmount(A const& asset, Number const& number) - : STAmount(fromNumber(asset, number)) + STAmount(A const& asset, Number const& number) : STAmount(fromNumber(asset, number)) { } @@ -316,37 +296,19 @@ STAmount::STAmount( exponent_type exponent, bool negative, unchecked) - : STBase(name) - , mAsset(asset) - , mValue(mantissa) - , mOffset(exponent) - , mIsNegative(negative) + : STBase(name), mAsset(asset), mValue(mantissa), mOffset(exponent), mIsNegative(negative) { } template -STAmount::STAmount( - A const& asset, - mantissa_type mantissa, - exponent_type exponent, - bool negative, - unchecked) +STAmount::STAmount(A const& asset, mantissa_type mantissa, exponent_type exponent, bool negative, unchecked) : mAsset(asset), mValue(mantissa), mOffset(exponent), mIsNegative(negative) { } template -STAmount::STAmount( - SField const& name, - A const& asset, - std::uint64_t mantissa, - int exponent, - bool negative) - : STBase(name) - , mAsset(asset) - , mValue(mantissa) - , mOffset(exponent) - , mIsNegative(negative) +STAmount::STAmount(SField const& name, A const& asset, std::uint64_t mantissa, int exponent, bool negative) + : STBase(name), mAsset(asset), mValue(mantissa), mOffset(exponent), mIsNegative(negative) { // mValue is uint64, but needs to fit in the range of int64 if (Number::getMantissaScale() == MantissaRange::small) @@ -359,26 +321,20 @@ STAmount::STAmount( else { if (integral() && mValue > std::numeric_limits::max()) - throw std::overflow_error( - "STAmount mantissa is too large " + std::to_string(mantissa)); + throw std::overflow_error("STAmount mantissa is too large " + std::to_string(mantissa)); } canonicalize(); } template -STAmount::STAmount(A const& asset, std::int64_t mantissa, int exponent) - : mAsset(asset), mOffset(exponent) +STAmount::STAmount(A const& asset, std::int64_t mantissa, int exponent) : mAsset(asset), mOffset(exponent) { set(mantissa); canonicalize(); } template -STAmount::STAmount( - A const& asset, - std::uint32_t mantissa, - int exponent, - bool negative) +STAmount::STAmount(A const& asset, std::uint32_t mantissa, int exponent, bool negative) : STAmount(asset, safe_cast(mantissa), exponent, negative) { } @@ -391,9 +347,7 @@ STAmount::STAmount(A const& asset, int mantissa, int exponent) // Legacy support for new-style amounts inline STAmount::STAmount(IOUAmount const& amount, Issue const& issue) - : mAsset(issue) - , mOffset(amount.exponent()) - , mIsNegative(amount < beast::zero) + : mAsset(issue), mOffset(amount.exponent()), mIsNegative(amount < beast::zero) { if (mIsNegative) mValue = unsafe_cast(-amount.mantissa()); @@ -568,8 +522,7 @@ STAmount::fromNumber(A const& a, Number const& number) return STAmount{asset, intValue, 0, negative}; } - auto const [mantissa, exponent] = - working.normalizeToRange(cMinValue, cMaxValue); + auto const [mantissa, exponent] = working.normalizeToRange(cMinValue, cMaxValue); return STAmount{asset, mantissa, exponent, negative}; } @@ -673,35 +626,19 @@ multiply(STAmount const& v1, STAmount const& v2, Asset const& asset); // multiply rounding result in specified direction STAmount -mulRound( - STAmount const& v1, - STAmount const& v2, - Asset const& asset, - bool roundUp); +mulRound(STAmount const& v1, STAmount const& v2, Asset const& asset, bool roundUp); // multiply following the rounding directions more precisely. STAmount -mulRoundStrict( - STAmount const& v1, - STAmount const& v2, - Asset const& asset, - bool roundUp); +mulRoundStrict(STAmount const& v1, STAmount const& v2, Asset const& asset, bool roundUp); // divide rounding result in specified direction STAmount -divRound( - STAmount const& v1, - STAmount const& v2, - Asset const& asset, - bool roundUp); +divRound(STAmount const& v1, STAmount const& v2, Asset const& asset, bool roundUp); // divide following the rounding directions more precisely. STAmount -divRoundStrict( - STAmount const& v1, - STAmount const& v2, - Asset const& asset, - bool roundUp); +divRoundStrict(STAmount const& v1, STAmount const& v2, Asset const& asset, bool roundUp); // Someone is offering X for Y, what is the rate? // Rate: smaller is better, the taker wants the most out: in/out @@ -722,10 +659,7 @@ getRate(STAmount const& offerOut, STAmount const& offerIn); * */ [[nodiscard]] STAmount -roundToScale( - STAmount const& value, - std::int32_t scale, - Number::rounding_mode rounding = Number::getround()); +roundToScale(STAmount const& value, std::int32_t scale, Number::rounding_mode rounding = Number::getround()); /** Round an arbitrary precision Number IN PLACE to the precision of a given * Asset. diff --git a/include/xrpl/protocol/STArray.h b/include/xrpl/protocol/STArray.h index fb37e07226..d413e7bdc0 100644 --- a/include/xrpl/protocol/STArray.h +++ b/include/xrpl/protocol/STArray.h @@ -24,16 +24,12 @@ public: template < class Iter, - class = std::enable_if_t::reference, - STObject>>> + class = std::enable_if_t::reference, STObject>>> explicit STArray(Iter first, Iter last); template < class Iter, - class = std::enable_if_t::reference, - STObject>>> + class = std::enable_if_t::reference, STObject>>> STArray(SField const& f, Iter first, Iter last); STArray& @@ -153,8 +149,7 @@ STArray::STArray(Iter first, Iter last) : v_(first, last) } template -STArray::STArray(SField const& f, Iter first, Iter last) - : STBase(f), v_(first, last) +STArray::STArray(SField const& f, Iter first, Iter last) : STBase(f), v_(first, last) { } diff --git a/include/xrpl/protocol/STBitString.h b/include/xrpl/protocol/STBitString.h index 2d26fe4bd7..0229d99698 100644 --- a/include/xrpl/protocol/STBitString.h +++ b/include/xrpl/protocol/STBitString.h @@ -79,14 +79,12 @@ inline STBitString::STBitString(value_type const& v) : value_(v) } template -inline STBitString::STBitString(SField const& n, value_type const& v) - : STBase(n), value_(v) +inline STBitString::STBitString(SField const& n, value_type const& v) : STBase(n), value_(v) { } template -inline STBitString::STBitString(SerialIter& sit, SField const& name) - : STBitString(name, sit.getBitString()) +inline STBitString::STBitString(SerialIter& sit, SField const& name) : STBitString(name, sit.getBitString()) { } @@ -151,11 +149,8 @@ template void STBitString::add(Serializer& s) const { - XRPL_ASSERT( - getFName().isBinary(), "xrpl::STBitString::add : field is binary"); - XRPL_ASSERT( - getFName().fieldType == getSType(), - "xrpl::STBitString::add : field type match"); + XRPL_ASSERT(getFName().isBinary(), "xrpl::STBitString::add : field is binary"); + XRPL_ASSERT(getFName().fieldType == getSType(), "xrpl::STBitString::add : field type match"); s.addBitString(value_); } diff --git a/include/xrpl/protocol/STBlob.h b/include/xrpl/protocol/STBlob.h index dc3f95e218..bb9b8a44f8 100644 --- a/include/xrpl/protocol/STBlob.h +++ b/include/xrpl/protocol/STBlob.h @@ -69,18 +69,15 @@ private: friend class detail::STVar; }; -inline STBlob::STBlob(STBlob const& rhs) - : STBase(rhs), CountedObject(rhs), value_(rhs.data(), rhs.size()) +inline STBlob::STBlob(STBlob const& rhs) : STBase(rhs), CountedObject(rhs), value_(rhs.data(), rhs.size()) { } -inline STBlob::STBlob(SField const& f, void const* data, std::size_t size) - : STBase(f), value_(data, size) +inline STBlob::STBlob(SField const& f, void const* data, std::size_t size) : STBase(f), value_(data, size) { } -inline STBlob::STBlob(SField const& f, Buffer&& b) - : STBase(f), value_(std::move(b)) +inline STBlob::STBlob(SField const& f, Buffer&& b) : STBase(f), value_(std::move(b)) { } diff --git a/include/xrpl/protocol/STExchange.h b/include/xrpl/protocol/STExchange.h index 5f7e405599..daf5a0e1f2 100644 --- a/include/xrpl/protocol/STExchange.h +++ b/include/xrpl/protocol/STExchange.h @@ -124,8 +124,7 @@ template void set(STObject& st, TypedField const& f, T&& t) { - st.set(STExchange::type>::set( - f, std::forward(t))); + st.set(STExchange::type>::set(f, std::forward(t))); } /** Set a blob field using an init function. */ @@ -139,10 +138,7 @@ set(STObject& st, TypedField const& f, std::size_t size, Init&& init) /** Set a blob field from data. */ template void -set(STObject& st, - TypedField const& f, - void const* data, - std::size_t size) +set(STObject& st, TypedField const& f, void const* data, std::size_t size) { st.set(std::make_unique(f, data, size)); } diff --git a/include/xrpl/protocol/STInteger.h b/include/xrpl/protocol/STInteger.h index 9c8af4c08c..e79f88808e 100644 --- a/include/xrpl/protocol/STInteger.h +++ b/include/xrpl/protocol/STInteger.h @@ -70,8 +70,7 @@ inline STInteger::STInteger(Integer v) : value_(v) } template -inline STInteger::STInteger(SField const& n, Integer v) - : STBase(n), value_(v) +inline STInteger::STInteger(SField const& n, Integer v) : STBase(n), value_(v) { } @@ -93,11 +92,8 @@ template inline void STInteger::add(Serializer& s) const { - XRPL_ASSERT( - getFName().isBinary(), "xrpl::STInteger::add : field is binary"); - XRPL_ASSERT( - getFName().fieldType == getSType(), - "xrpl::STInteger::add : field type match"); + XRPL_ASSERT(getFName().isBinary(), "xrpl::STInteger::add : field is binary"); + XRPL_ASSERT(getFName().fieldType == getSType(), "xrpl::STInteger::add : field type match"); s.addInteger(value_); } diff --git a/include/xrpl/protocol/STIssue.h b/include/xrpl/protocol/STIssue.h index 6480482d08..404e60578c 100644 --- a/include/xrpl/protocol/STIssue.h +++ b/include/xrpl/protocol/STIssue.h @@ -83,12 +83,10 @@ private: }; template -STIssue::STIssue(SField const& name, A const& asset) - : STBase{name}, asset_{asset} +STIssue::STIssue(SField const& name, A const& asset) : STBase{name}, asset_{asset} { if (holds() && !isConsistent(asset_.get())) - Throw( - "Invalid asset: currency and account native mismatch"); + Throw("Invalid asset: currency and account native mismatch"); } STIssue @@ -120,8 +118,7 @@ inline void STIssue::setIssue(Asset const& asset) { if (holds() && !isConsistent(asset_.get())) - Throw( - "Invalid asset: currency and account native mismatch"); + Throw("Invalid asset: currency and account native mismatch"); asset_ = asset; } diff --git a/include/xrpl/protocol/STLedgerEntry.h b/include/xrpl/protocol/STLedgerEntry.h index 83e0f2cd27..24efab5f86 100644 --- a/include/xrpl/protocol/STLedgerEntry.h +++ b/include/xrpl/protocol/STLedgerEntry.h @@ -56,11 +56,7 @@ public: isThreadedType(Rules const& rules) const; bool - thread( - uint256 const& txID, - std::uint32_t ledgerSeq, - uint256& prevTxID, - std::uint32_t& prevLedgerID); + thread(uint256 const& txID, std::uint32_t ledgerSeq, uint256& prevTxID, std::uint32_t& prevLedgerID); private: /* Make STObject comply with the template for this SLE type @@ -82,13 +78,11 @@ private: using SLE = STLedgerEntry; -inline STLedgerEntry::STLedgerEntry(LedgerEntryType type, uint256 const& key) - : STLedgerEntry(Keylet(type, key)) +inline STLedgerEntry::STLedgerEntry(LedgerEntryType type, uint256 const& key) : STLedgerEntry(Keylet(type, key)) { } -inline STLedgerEntry::STLedgerEntry(SerialIter&& sit, uint256 const& index) - : STLedgerEntry(sit, index) +inline STLedgerEntry::STLedgerEntry(SerialIter&& sit, uint256 const& index) : STLedgerEntry(sit, index) { } diff --git a/include/xrpl/protocol/STObject.h b/include/xrpl/protocol/STObject.h index d282e9bf01..0a2c37356a 100644 --- a/include/xrpl/protocol/STObject.h +++ b/include/xrpl/protocol/STObject.h @@ -61,15 +61,13 @@ class STObject : public STBase, public CountedObject SOTemplate const* mType; public: - using iterator = boost:: - transform_iterator; + using iterator = boost::transform_iterator; virtual ~STObject() = default; STObject(STObject const&) = default; template - STObject(SOTemplate const& type, SField const& name, F&& f) - : STObject(type, name) + STObject(SOTemplate const& type, SField const& name, F&& f) : STObject(type, name) { f(*this); } @@ -434,8 +432,8 @@ private: // by value. template < typename T, - typename V = typename std::remove_cv().value())>::type>::type> + typename V = + typename std::remove_cv().value())>::type>::type> V getFieldByValue(SField const& field) const; @@ -510,26 +508,19 @@ protected: // Constraint += and -= ValueProxy operators // to value types that support arithmetic operations template -concept IsArithmeticNumber = std::is_arithmetic_v || - std::is_same_v || std::is_same_v; -template < - typename U, - typename Value = typename U::value_type, - typename Unit = typename U::unit_type> +concept IsArithmeticNumber = std::is_arithmetic_v || std::is_same_v || std::is_same_v; +template concept IsArithmeticValueUnit = - std::is_same_v> && - IsArithmeticNumber && std::is_class_v; + std::is_same_v> && IsArithmeticNumber && std::is_class_v; template concept IsArithmeticST = !IsArithmeticValueUnit && IsArithmeticNumber; template -concept IsArithmetic = - IsArithmeticNumber || IsArithmeticST || IsArithmeticValueUnit; +concept IsArithmetic = IsArithmeticNumber || IsArithmeticST || IsArithmeticValueUnit; template concept Addable = requires(T t, U u) { t = t + u; }; template -concept IsArithmeticCompatible = - IsArithmetic && Addable; +concept IsArithmeticCompatible = IsArithmetic && Addable; template class STObject::ValueProxy : public Proxy @@ -708,8 +699,7 @@ STObject::Proxy::Proxy(STObject* st, TypedField const* f) : st_(st), f_(f) { // STObject has associated template if (!st_->peekAtPField(*f_)) - Throw( - "Template field error '" + this->f_->getName() + "'"); + Throw("Template field error '" + this->f_->getName() + "'"); style_ = st_->mType->style(*f_); } else @@ -731,8 +721,7 @@ STObject::Proxy::value() const -> value_type } if (style_ != soeDEFAULT) { - Throw( - "Missing field '" + this->f_->getName() + "'"); + Throw("Missing field '" + this->f_->getName() + "'"); } return value_type{}; } @@ -817,8 +806,7 @@ STObject::ValueProxy::operator value_type() const } template -STObject::ValueProxy::ValueProxy(STObject* st, TypedField const* f) - : Proxy(st, f) +STObject::ValueProxy::ValueProxy(STObject* st, TypedField const* f) : Proxy(st, f) { } @@ -831,8 +819,7 @@ STObject::OptionalProxy::operator bool() const noexcept } template -STObject::OptionalProxy::operator typename STObject::OptionalProxy< - T>::optional_type() const +STObject::OptionalProxy::operator typename STObject::OptionalProxy::optional_type() const { return optional_value(); } @@ -884,8 +871,7 @@ STObject::OptionalProxy::operator=(U&& u) } template -STObject::OptionalProxy::OptionalProxy(STObject* st, TypedField const* f) - : Proxy(st, f) +STObject::OptionalProxy::OptionalProxy(STObject* st, TypedField const* f) : Proxy(st, f) { } @@ -901,8 +887,7 @@ void STObject::OptionalProxy::disengage() { if (this->style_ == soeREQUIRED || this->style_ == soeDEFAULT) - Throw( - "Template field error '" + this->f_->getName() + "'"); + Throw("Template field error '" + this->f_->getName() + "'"); if (this->style_ == soeINVALID) this->st_->delField(*this->f_); else @@ -935,8 +920,7 @@ STObject::Transform::operator()(detail::STVar const& e) const //------------------------------------------------------------------------------ -inline STObject::STObject(SerialIter&& sit, SField const& name) - : STObject(sit, name) +inline STObject::STObject(SerialIter&& sit, SField const& name) : STObject(sit, name) { } @@ -1066,18 +1050,13 @@ STObject::at(TypedField const& f) const if (auto const u = dynamic_cast(b)) return u->value(); - XRPL_ASSERT( - mType, "xrpl::STObject::at(TypedField auto) : field template non-null"); - XRPL_ASSERT( - b->getSType() == STI_NOTPRESENT, - "xrpl::STObject::at(TypedField auto) : type not present"); + XRPL_ASSERT(mType, "xrpl::STObject::at(TypedField auto) : field template non-null"); + XRPL_ASSERT(b->getSType() == STI_NOTPRESENT, "xrpl::STObject::at(TypedField auto) : type not present"); if (mType->style(f) == soeOPTIONAL) Throw("Missing optional field: " + f.getName()); - XRPL_ASSERT( - mType->style(f) == soeDEFAULT, - "xrpl::STObject::at(TypedField auto) : template style is default"); + XRPL_ASSERT(mType->style(f) == soeDEFAULT, "xrpl::STObject::at(TypedField auto) : template style is default"); // Used to help handle the case where value_type is a const reference, // otherwise we would return the address of a temporary. @@ -1099,9 +1078,7 @@ STObject::at(OptionaledField const& of) const mType, "xrpl::STObject::at(OptionaledField auto) : field template " "non-null"); - XRPL_ASSERT( - b->getSType() == STI_NOTPRESENT, - "xrpl::STObject::at(OptionaledField auto) : type not present"); + XRPL_ASSERT(b->getSType() == STI_NOTPRESENT, "xrpl::STObject::at(OptionaledField auto) : type not present"); if (mType->style(*of.f) == soeOPTIONAL) return std::nullopt; XRPL_ASSERT( diff --git a/include/xrpl/protocol/STPathSet.h b/include/xrpl/protocol/STPathSet.h index cb7db2edf0..55e2aebe2d 100644 --- a/include/xrpl/protocol/STPathSet.h +++ b/include/xrpl/protocol/STPathSet.h @@ -26,8 +26,7 @@ class STPathElement final : public CountedObject public: enum Type { typeNone = 0x00, - typeAccount = - 0x01, // Rippling through an account (vs taking an offer). + typeAccount = 0x01, // Rippling through an account (vs taking an offer). typeCurrency = 0x10, // Currency follows. typeIssuer = 0x20, // Issuer follows. typeBoundary = 0xFF, // Boundary between alternate paths. @@ -51,11 +50,7 @@ public: AccountID const& issuer, bool forceCurrency = false); - STPathElement( - unsigned int uType, - AccountID const& account, - Currency const& currency, - AccountID const& issuer); + STPathElement(unsigned int uType, AccountID const& account, Currency const& currency, AccountID const& issuer); auto getNodeType() const; @@ -120,10 +115,7 @@ public: emplace_back(Args&&... args); bool - hasSeen( - AccountID const& account, - Currency const& currency, - AccountID const& issuer) const; + hasSeen(AccountID const& account, Currency const& currency, AccountID const& issuer) const; Json::Value getJson(JsonOptions) const; @@ -239,9 +231,7 @@ inline STPathElement::STPathElement( is_offer_ = false; mAccountID = *account; mType |= typeAccount; - XRPL_ASSERT( - mAccountID != noAccount(), - "xrpl::STPathElement::STPathElement : account is set"); + XRPL_ASSERT(mAccountID != noAccount(), "xrpl::STPathElement::STPathElement : account is set"); } if (currency) @@ -254,9 +244,7 @@ inline STPathElement::STPathElement( { mIssuerID = *issuer; mType |= typeIssuer; - XRPL_ASSERT( - mIssuerID != noAccount(), - "xrpl::STPathElement::STPathElement : issuer is set"); + XRPL_ASSERT(mIssuerID != noAccount(), "xrpl::STPathElement::STPathElement : issuer is set"); } hash_value_ = get_hash(*this); @@ -267,11 +255,7 @@ inline STPathElement::STPathElement( Currency const& currency, AccountID const& issuer, bool forceCurrency) - : mType(typeNone) - , mAccountID(account) - , mCurrencyID(currency) - , mIssuerID(issuer) - , is_offer_(isXRP(mAccountID)) + : mType(typeNone), mAccountID(account), mCurrencyID(currency), mIssuerID(issuer), is_offer_(isXRP(mAccountID)) { if (!is_offer_) mType |= typeAccount; @@ -290,11 +274,7 @@ inline STPathElement::STPathElement( AccountID const& account, Currency const& currency, AccountID const& issuer) - : mType(uType) - , mAccountID(account) - , mCurrencyID(currency) - , mIssuerID(issuer) - , is_offer_(isXRP(mAccountID)) + : mType(uType), mAccountID(account), mCurrencyID(currency), mIssuerID(issuer), is_offer_(isXRP(mAccountID)) { hash_value_ = get_hash(*this); } @@ -358,9 +338,8 @@ STPathElement::getIssuerID() const inline bool STPathElement::operator==(STPathElement const& t) const { - return (mType & typeAccount) == (t.mType & typeAccount) && - hash_value_ == t.hash_value_ && mAccountID == t.mAccountID && - mCurrencyID == t.mCurrencyID && mIssuerID == t.mIssuerID; + return (mType & typeAccount) == (t.mType & typeAccount) && hash_value_ == t.hash_value_ && + mAccountID == t.mAccountID && mCurrencyID == t.mCurrencyID && mIssuerID == t.mIssuerID; } inline bool diff --git a/include/xrpl/protocol/STTx.h b/include/xrpl/protocol/STTx.h index 182e13433d..f6ee91623f 100644 --- a/include/xrpl/protocol/STTx.h +++ b/include/xrpl/protocol/STTx.h @@ -100,8 +100,7 @@ public: sign( PublicKey const& publicKey, SecretKey const& secretKey, - std::optional> signatureTarget = - {}); + std::optional> signatureTarget = {}); /** Check the signature. @param rules The current ledger rules. @@ -118,15 +117,10 @@ public: getMetaSQLInsertReplaceHeader(); std::string - getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData) - const; + getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData) const; std::string - getMetaSQL( - Serializer rawTxn, - std::uint32_t inLedger, - char status, - std::string const& escapedMetaData) const; + getMetaSQL(Serializer rawTxn, std::uint32_t inLedger, char status, std::string const& escapedMetaData) const; std::vector const& getBatchTransactionIDs() const; diff --git a/include/xrpl/protocol/STValidation.h b/include/xrpl/protocol/STValidation.h index 4d09397eaa..6f071acda1 100644 --- a/include/xrpl/protocol/STValidation.h +++ b/include/xrpl/protocol/STValidation.h @@ -54,10 +54,7 @@ public: @note Throws if the object is not valid */ template - STValidation( - SerialIter& sit, - LookupNodeID&& lookupNodeID, - bool checkSignature); + STValidation(SerialIter& sit, LookupNodeID&& lookupNodeID, bool checkSignature); /** Construct, sign and trust a new STValidation issued by this node. @@ -68,12 +65,7 @@ public: @param f callback function to "fill" the validation with necessary data */ template - STValidation( - NetClock::time_point signTime, - PublicKey const& pk, - SecretKey const& sk, - NodeID const& nodeID, - F&& f); + STValidation(NetClock::time_point signTime, PublicKey const& pk, SecretKey const& sk, NodeID const& nodeID, F&& f); // Hash of the validated ledger uint256 @@ -126,14 +118,10 @@ public: render() const { std::stringstream ss; - ss << "validation: " << " ledger_hash: " << getLedgerHash() - << " consensus_hash: " << getConsensusHash() - << " sign_time: " << to_string(getSignTime()) - << " seen_time: " << to_string(getSeenTime()) - << " signer_public_key: " << getSignerPublic() - << " node_id: " << getNodeID() << " is_valid: " << isValid() - << " is_full: " << isFull() << " is_trusted: " << isTrusted() - << " signing_hash: " << getSigningHash() + ss << "validation: " << " ledger_hash: " << getLedgerHash() << " consensus_hash: " << getConsensusHash() + << " sign_time: " << to_string(getSignTime()) << " seen_time: " << to_string(getSeenTime()) + << " signer_public_key: " << getSignerPublic() << " node_id: " << getNodeID() << " is_valid: " << isValid() + << " is_full: " << isFull() << " is_trusted: " << isTrusted() << " signing_hash: " << getSigningHash() << " base58: " << toBase58(TokenType::NodePublic, getSignerPublic()); return ss.str(); } @@ -151,10 +139,7 @@ private: }; template -STValidation::STValidation( - SerialIter& sit, - LookupNodeID&& lookupNodeID, - bool checkSignature) +STValidation::STValidation(SerialIter& sit, LookupNodeID&& lookupNodeID, bool checkSignature) : STObject(validationFormat(), sit, sfValidation) , signingPubKey_([this]() { auto const spk = getFieldVL(sfSigningPubKey); @@ -168,14 +153,11 @@ STValidation::STValidation( { if (checkSignature && !isValid()) { - JLOG(debugLog().error()) << "Invalid signature in validation: " - << getJson(JsonOptions::none); + JLOG(debugLog().error()) << "Invalid signature in validation: " << getJson(JsonOptions::none); Throw("Invalid signature in validation"); } - XRPL_ASSERT( - nodeID_.isNonZero(), - "xrpl::STValidation::STValidation(SerialIter) : nonzero node"); + XRPL_ASSERT(nodeID_.isNonZero(), "xrpl::STValidation::STValidation(SerialIter) : nonzero node"); } /** Construct, sign and trust a new STValidation issued by this node. @@ -193,10 +175,7 @@ STValidation::STValidation( SecretKey const& sk, NodeID const& nodeID, F&& f) - : STObject(validationFormat(), sfValidation) - , signingPubKey_(pk) - , nodeID_(nodeID) - , seenTime_(signTime) + : STObject(validationFormat(), sfValidation), signingPubKey_(pk), nodeID_(nodeID), seenTime_(signTime) { XRPL_ASSERT( nodeID_.isNonZero(), @@ -222,9 +201,7 @@ STValidation::STValidation( for (auto const& e : validationFormat()) { if (e.style() == soeREQUIRED && !isFieldPresent(e.sField())) - LogicError( - "Required field '" + e.sField().getName() + - "' missing from validation."); + LogicError("Required field '" + e.sField().getName() + "' missing from validation."); } // We just signed this, so it should be valid. diff --git a/include/xrpl/protocol/STVector256.h b/include/xrpl/protocol/STVector256.h index 94b16db90b..884fd70c7c 100644 --- a/include/xrpl/protocol/STVector256.h +++ b/include/xrpl/protocol/STVector256.h @@ -107,15 +107,11 @@ inline STVector256::STVector256(SField const& n) : STBase(n) { } -inline STVector256::STVector256(std::vector const& vector) - : mValue(vector) +inline STVector256::STVector256(std::vector const& vector) : mValue(vector) { } -inline STVector256::STVector256( - SField const& n, - std::vector const& vector) - : STBase(n), mValue(vector) +inline STVector256::STVector256(SField const& n, std::vector const& vector) : STBase(n), mValue(vector) { } @@ -182,9 +178,7 @@ STVector256::value() const } inline std::vector::iterator -STVector256::insert( - std::vector::const_iterator pos, - uint256 const& value) +STVector256::insert(std::vector::const_iterator pos, uint256 const& value) { return mValue.insert(pos, value); } diff --git a/include/xrpl/protocol/STXChainBridge.h b/include/xrpl/protocol/STXChainBridge.h index 89c6d60c13..fdaed22594 100644 --- a/include/xrpl/protocol/STXChainBridge.h +++ b/include/xrpl/protocol/STXChainBridge.h @@ -115,31 +115,15 @@ private: inline bool operator==(STXChainBridge const& lhs, STXChainBridge const& rhs) { - return std::tie( - lhs.lockingChainDoor_, - lhs.lockingChainIssue_, - lhs.issuingChainDoor_, - lhs.issuingChainIssue_) == - std::tie( - rhs.lockingChainDoor_, - rhs.lockingChainIssue_, - rhs.issuingChainDoor_, - rhs.issuingChainIssue_); + return std::tie(lhs.lockingChainDoor_, lhs.lockingChainIssue_, lhs.issuingChainDoor_, lhs.issuingChainIssue_) == + std::tie(rhs.lockingChainDoor_, rhs.lockingChainIssue_, rhs.issuingChainDoor_, rhs.issuingChainIssue_); } inline bool operator<(STXChainBridge const& lhs, STXChainBridge const& rhs) { - return std::tie( - lhs.lockingChainDoor_, - lhs.lockingChainIssue_, - lhs.issuingChainDoor_, - lhs.issuingChainIssue_) < - std::tie( - rhs.lockingChainDoor_, - rhs.lockingChainIssue_, - rhs.issuingChainDoor_, - rhs.issuingChainIssue_); + return std::tie(lhs.lockingChainDoor_, lhs.lockingChainIssue_, lhs.issuingChainDoor_, lhs.issuingChainIssue_) < + std::tie(rhs.lockingChainDoor_, rhs.lockingChainIssue_, rhs.issuingChainDoor_, rhs.issuingChainIssue_); } inline AccountID const& diff --git a/include/xrpl/protocol/SecretKey.h b/include/xrpl/protocol/SecretKey.h index d5f1ce303f..146e9a7105 100644 --- a/include/xrpl/protocol/SecretKey.h +++ b/include/xrpl/protocol/SecretKey.h @@ -81,8 +81,7 @@ public: inline bool operator==(SecretKey const& lhs, SecretKey const& rhs) { - return lhs.size() == rhs.size() && - std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0; + return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0; } inline bool diff --git a/include/xrpl/protocol/Serializer.h b/include/xrpl/protocol/Serializer.h index f46073a977..7e294bd3a8 100644 --- a/include/xrpl/protocol/Serializer.h +++ b/include/xrpl/protocol/Serializer.h @@ -36,9 +36,7 @@ public: if (size) { - XRPL_ASSERT( - data, - "xrpl::Serializer::Serializer(void const*) : non-null input"); + XRPL_ASSERT(data, "xrpl::Serializer::Serializer(void const*) : non-null input"); std::memcpy(mData.data(), data, size); } } @@ -68,9 +66,7 @@ public: add16(std::uint16_t i); template - requires(std::is_same_v< - std::make_unsigned_t>, - std::uint32_t>) + requires(std::is_same_v>, std::uint32_t>) int add32(T i) { @@ -86,9 +82,7 @@ public: add32(HashPrefix p); template - requires(std::is_same_v< - std::make_unsigned_t>, - std::uint64_t>) + requires(std::is_same_v>, std::uint64_t>) int add64(T i) { diff --git a/include/xrpl/protocol/Sign.h b/include/xrpl/protocol/Sign.h index 6df4c55b65..d9af89b774 100644 --- a/include/xrpl/protocol/Sign.h +++ b/include/xrpl/protocol/Sign.h @@ -20,12 +20,7 @@ namespace xrpl { @note If a signature already exists, it is overwritten. */ void -sign( - STObject& st, - HashPrefix const& prefix, - KeyType type, - SecretKey const& sk, - SF_VL const& sigField = sfSignature); +sign(STObject& st, HashPrefix const& prefix, KeyType type, SecretKey const& sk, SF_VL const& sigField = sfSignature); /** Returns `true` if STObject contains valid signature @@ -36,11 +31,7 @@ sign( If not specified the value defaults to `sfSignature`. */ bool -verify( - STObject const& st, - HashPrefix const& prefix, - PublicKey const& pk, - SF_VL const& sigField = sfSignature); +verify(STObject const& st, HashPrefix const& prefix, PublicKey const& pk, SF_VL const& sigField = sfSignature); /** Return a Serializer suitable for computing a multisigning TxnSignature. */ Serializer diff --git a/include/xrpl/protocol/TER.h b/include/xrpl/protocol/TER.h index de2f596127..65a339231d 100644 --- a/include/xrpl/protocol/TER.h +++ b/include/xrpl/protocol/TER.h @@ -193,19 +193,19 @@ enum TERcodes : TERUnderlyingType { // - Hold // - Makes hole in sequence which jams transactions. terRETRY = -99, - terFUNDS_SPENT, // DEPRECATED. - terINSUF_FEE_B, // Can't pay fee, therefore don't burden network. - terNO_ACCOUNT, // Can't pay fee, therefore don't burden network. - terNO_AUTH, // Not authorized to hold IOUs. - terNO_LINE, // Internal flag. - terOWNERS, // Can't succeed with non-zero owner count. - terPRE_SEQ, // Can't pay fee, no point in forwarding, so don't - // burden network. - terLAST, // DEPRECATED. - terNO_RIPPLE, // Rippling not allowed - terQUEUED, // Transaction is being held in TxQ until fee drops - terPRE_TICKET, // Ticket is not yet in ledger but might be on its way - terNO_AMM, // AMM doesn't exist for the asset pair + terFUNDS_SPENT, // DEPRECATED. + terINSUF_FEE_B, // Can't pay fee, therefore don't burden network. + terNO_ACCOUNT, // Can't pay fee, therefore don't burden network. + terNO_AUTH, // Not authorized to hold IOUs. + terNO_LINE, // Internal flag. + terOWNERS, // Can't succeed with non-zero owner count. + terPRE_SEQ, // Can't pay fee, no point in forwarding, so don't + // burden network. + terLAST, // DEPRECATED. + terNO_RIPPLE, // Rippling not allowed + terQUEUED, // Transaction is being held in TxQ until fee drops + terPRE_TICKET, // Ticket is not yet in ledger but might be on its way + terNO_AMM, // AMM doesn't exist for the asset pair terADDRESS_COLLISION, // Failed to allocate AccountID when trying to // create a pseudo-account terNO_DELEGATE_PERMISSION, // Delegate does not have permission @@ -417,10 +417,7 @@ public: } // Trait tells enable_if which types are allowed for construction. - template < - typename T, - typename = std::enable_if_t< - Trait>>::value>> + template >>::value>> constexpr TERSubset(T rhs) : code_(TERtoInt(rhs)) { } @@ -490,8 +487,7 @@ template constexpr auto operator==(L const& lhs, R const& rhs) -> std::enable_if_t< - std::is_same::value && - std::is_same::value, + std::is_same::value && std::is_same::value, bool> { return TERtoInt(lhs) == TERtoInt(rhs); @@ -501,8 +497,7 @@ template constexpr auto operator!=(L const& lhs, R const& rhs) -> std::enable_if_t< - std::is_same::value && - std::is_same::value, + std::is_same::value && std::is_same::value, bool> { return TERtoInt(lhs) != TERtoInt(rhs); @@ -512,8 +507,7 @@ template constexpr auto operator<(L const& lhs, R const& rhs) -> std::enable_if_t< - std::is_same::value && - std::is_same::value, + std::is_same::value && std::is_same::value, bool> { return TERtoInt(lhs) < TERtoInt(rhs); @@ -523,8 +517,7 @@ template constexpr auto operator<=(L const& lhs, R const& rhs) -> std::enable_if_t< - std::is_same::value && - std::is_same::value, + std::is_same::value && std::is_same::value, bool> { return TERtoInt(lhs) <= TERtoInt(rhs); @@ -534,8 +527,7 @@ template constexpr auto operator>(L const& lhs, R const& rhs) -> std::enable_if_t< - std::is_same::value && - std::is_same::value, + std::is_same::value && std::is_same::value, bool> { return TERtoInt(lhs) > TERtoInt(rhs); @@ -545,8 +537,7 @@ template constexpr auto operator>=(L const& lhs, R const& rhs) -> std::enable_if_t< - std::is_same::value && - std::is_same::value, + std::is_same::value && std::is_same::value, bool> { return TERtoInt(lhs) >= TERtoInt(rhs); @@ -668,9 +659,7 @@ isTecClaim(TER x) noexcept return ((x) >= tecCLAIM); } -std::unordered_map< - TERUnderlyingType, - std::pair> const& +std::unordered_map> const& transResults(); bool diff --git a/include/xrpl/protocol/Units.h b/include/xrpl/protocol/Units.h index 72114ad8fe..e52fbefe46 100644 --- a/include/xrpl/protocol/Units.h +++ b/include/xrpl/protocol/Units.h @@ -36,8 +36,8 @@ class TenthBipsTag; // namespace. template -concept Valid = std::is_class_v && std::is_object_v && - std::is_object_v; +concept Valid = + std::is_class_v && std::is_object_v && std::is_object_v; /** `Usable` is checked to ensure that only values with known valid type tags can be used (sometimes transparently) in @@ -48,15 +48,12 @@ concept Valid = std::is_class_v && std::is_object_v && */ template concept Usable = Valid && - (std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || + (std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || std::is_same_v); template -concept Compatible = Valid && std::is_arithmetic_v && - std::is_arithmetic_v && +concept Compatible = Valid && std::is_arithmetic_v && std::is_arithmetic_v && std::is_convertible_v; template @@ -66,8 +63,8 @@ template concept IntegralValue = Integral; template -concept CastableValue = IntegralValue && IntegralValue && - std::is_same_v; +concept CastableValue = + IntegralValue && IntegralValue && std::is_same_v; template class ValueUnit : private boost::totally_ordered>, @@ -221,8 +218,7 @@ public: ValueUnit operator-() const { - static_assert( - std::is_signed_v, "- operator illegal on unsigned value types"); + static_assert(std::is_signed_v, "- operator illegal on unsigned value types"); return ValueUnit{-value_}; } @@ -297,10 +293,7 @@ public: { if constexpr (std::is_integral_v) { - using jsontype = std::conditional_t< - std::is_signed_v, - Json::Int, - Json::UInt>; + using jsontype = std::conditional_t, Json::Int, Json::UInt>; constexpr auto min = std::numeric_limits::min(); constexpr auto max = std::numeric_limits::max(); @@ -351,8 +344,7 @@ to_string(ValueUnit const& amount) } template -concept muldivSource = Valid && - std::is_convertible_v; +concept muldivSource = Valid && std::is_convertible_v; template concept muldivDest = muldivSource && // Dest is also a source @@ -368,8 +360,8 @@ concept muldivable = muldivSources && muldivDest; // Source and Dest can be the same by default template -concept muldivCommutable = muldivable && - !std::is_same_v; +concept muldivCommutable = + muldivable && !std::is_same_v; template ValueUnit @@ -387,10 +379,8 @@ mulDivU(Source1 value, Dest mul, Source2 div) { // split the asserts so if one hits, the user can tell which // without a debugger. - XRPL_ASSERT( - value.value() >= 0, "xrpl::unit::mulDivU : minimum value input"); - XRPL_ASSERT( - mul.value() >= 0, "xrpl::unit::mulDivU : minimum mul input"); + XRPL_ASSERT(value.value() >= 0, "xrpl::unit::mulDivU : minimum value input"); + XRPL_ASSERT(mul.value() >= 0, "xrpl::unit::mulDivU : minimum mul input"); XRPL_ASSERT(div.value() > 0, "xrpl::unit::mulDivU : minimum div input"); return std::nullopt; } @@ -411,10 +401,7 @@ mulDivU(Source1 value, Dest mul, Source2 div) using namespace boost::multiprecision; uint128_t product; - product = multiply( - product, - static_cast(value.value()), - static_cast(mul.value())); + product = multiply(product, static_cast(value.value()), static_cast(mul.value())); auto quotient = product / div.value(); @@ -449,10 +436,7 @@ mulDiv(Source1 value, Dest mul, Source2 div) return unit::mulDivU(value, mul, div); } -template < - class Source1, - class Source2, - unit::muldivCommutable Dest> +template Dest> std::optional mulDiv(Dest value, Source1 mul, Source2 div) { diff --git a/include/xrpl/protocol/XChainAttestations.h b/include/xrpl/protocol/XChainAttestations.h index bd76936b49..c5415e518b 100644 --- a/include/xrpl/protocol/XChainAttestations.h +++ b/include/xrpl/protocol/XChainAttestations.h @@ -197,9 +197,7 @@ struct AttestationCreateAccount : AttestationBase sameEvent(AttestationCreateAccount const& rhs) const; friend bool - operator==( - AttestationCreateAccount const& lhs, - AttestationCreateAccount const& rhs); + operator==(AttestationCreateAccount const& lhs, AttestationCreateAccount const& rhs); [[nodiscard]] static std::vector message( @@ -223,9 +221,7 @@ private: struct CmpByCreateCount { bool - operator()( - AttestationCreateAccount const& lhs, - AttestationCreateAccount const& rhs) const + operator()(AttestationCreateAccount const& lhs, AttestationCreateAccount const& rhs) const { return lhs.createCount < rhs.createCount; } @@ -261,10 +257,7 @@ struct XChainClaimAttestation bool wasLockingChainSend; std::optional dst; MatchFields(TSignedAttestation const& att); - MatchFields( - STAmount const& a, - bool b, - std::optional const& d) + MatchFields(STAmount const& a, bool b, std::optional const& d) : amount{a}, wasLockingChainSend{b}, dst{d} { } @@ -299,9 +292,7 @@ struct XChainClaimAttestation toSTObject() const; friend bool - operator==( - XChainClaimAttestation const& lhs, - XChainClaimAttestation const& rhs); + operator==(XChainClaimAttestation const& lhs, XChainClaimAttestation const& rhs); }; struct XChainCreateAccountAttestation @@ -349,9 +340,7 @@ struct XChainCreateAccountAttestation match(MatchFields const& rhs) const; friend bool - operator==( - XChainCreateAccountAttestation const& lhs, - XChainCreateAccountAttestation const& rhs); + operator==(XChainCreateAccountAttestation const& lhs, XChainCreateAccountAttestation const& rhs); }; // Attestations from witness servers for a particular claim ID and bridge. @@ -420,9 +409,7 @@ public: template [[nodiscard]] inline bool -operator==( - XChainAttestationsBase const& lhs, - XChainAttestationsBase const& rhs) +operator==(XChainAttestationsBase const& lhs, XChainAttestationsBase const& rhs) { return lhs.attestations() == rhs.attestations(); } @@ -464,15 +451,13 @@ XChainAttestationsBase::empty() const return attestations_.empty(); } -class XChainClaimAttestations final - : public XChainAttestationsBase +class XChainClaimAttestations final : public XChainAttestationsBase { using TBase = XChainAttestationsBase; using TBase::TBase; }; -class XChainCreateAccountAttestations final - : public XChainAttestationsBase +class XChainCreateAccountAttestations final : public XChainAttestationsBase { using TBase = XChainAttestationsBase; using TBase::TBase; diff --git a/include/xrpl/protocol/XRPAmount.h b/include/xrpl/protocol/XRPAmount.h index ef283f4154..55b9df115c 100644 --- a/include/xrpl/protocol/XRPAmount.h +++ b/include/xrpl/protocol/XRPAmount.h @@ -167,10 +167,8 @@ public: std::optional dropsAs() const { - if ((drops_ > std::numeric_limits::max()) || - (!std::numeric_limits::is_signed && drops_ < 0) || - (std::numeric_limits::is_signed && - drops_ < std::numeric_limits::lowest())) + if ((drops_ > std::numeric_limits::max()) || (!std::numeric_limits::is_signed && drops_ < 0) || + (std::numeric_limits::is_signed && drops_ < std::numeric_limits::lowest())) { return std::nullopt; } @@ -260,11 +258,7 @@ to_string(XRPAmount const& amount) } inline XRPAmount -mulRatio( - XRPAmount const& amt, - std::uint32_t num, - std::uint32_t den, - bool roundUp) +mulRatio(XRPAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundUp) { using namespace boost::multiprecision; diff --git a/include/xrpl/protocol/detail/b58_utils.h b/include/xrpl/protocol/detail/b58_utils.h index 4ea00e6d5e..1dce148aed 100644 --- a/include/xrpl/protocol/detail/b58_utils.h +++ b/include/xrpl/protocol/detail/b58_utils.h @@ -118,15 +118,12 @@ inplace_bigint_div_rem(std::span numerator, std::uint64_t divisor) // LCOV_EXCL_STOP } - auto to_u128 = [](std::uint64_t high, - std::uint64_t low) -> unsigned __int128 { + auto to_u128 = [](std::uint64_t high, std::uint64_t low) -> unsigned __int128 { unsigned __int128 const high128 = high; unsigned __int128 const low128 = low; return ((high128 << 64) | low128); }; - auto div_rem_64 = - [](unsigned __int128 num, - std::uint64_t denom) -> std::tuple { + auto div_rem_64 = [](unsigned __int128 num, std::uint64_t denom) -> std::tuple { unsigned __int128 const denom128 = denom; unsigned __int128 const d = num / denom128; unsigned __int128 const r = num - (denom128 * d); @@ -143,8 +140,7 @@ inplace_bigint_div_rem(std::span numerator, std::uint64_t divisor) std::uint64_t prev_rem = 0; int const last_index = numerator.size() - 1; - std::tie(numerator[last_index], prev_rem) = - div_rem(numerator[last_index], divisor); + std::tie(numerator[last_index], prev_rem) = div_rem(numerator[last_index], divisor); for (int i = last_index - 1; i >= 0; --i) { unsigned __int128 const cur_num = to_u128(prev_rem, numerator[i]); @@ -159,11 +155,8 @@ inplace_bigint_div_rem(std::span numerator, std::uint64_t divisor) [[nodiscard]] inline std::array b58_10_to_b58_be(std::uint64_t input) { - [[maybe_unused]] static constexpr std::uint64_t B_58_10 = - 430804206899405824; // 58^10; - XRPL_ASSERT( - input < B_58_10, - "xrpl::b58_fast::detail::b58_10_to_b58_be : valid input"); + [[maybe_unused]] static constexpr std::uint64_t B_58_10 = 430804206899405824; // 58^10; + XRPL_ASSERT(input < B_58_10, "xrpl::b58_fast::detail::b58_10_to_b58_be : valid input"); constexpr std::size_t resultSize = 10; std::array result{}; int i = 0; diff --git a/include/xrpl/protocol/detail/secp256k1.h b/include/xrpl/protocol/detail/secp256k1.h index c3ac76d7ed..0a2d5fcd8f 100644 --- a/include/xrpl/protocol/detail/secp256k1.h +++ b/include/xrpl/protocol/detail/secp256k1.h @@ -12,9 +12,7 @@ secp256k1Context() struct holder { secp256k1_context* impl; - holder() - : impl(secp256k1_context_create( - SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN)) + holder() : impl(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN)) { } diff --git a/include/xrpl/protocol/json_get_or_throw.h b/include/xrpl/protocol/json_get_or_throw.h index bdf572bed6..8bc89805d3 100644 --- a/include/xrpl/protocol/json_get_or_throw.h +++ b/include/xrpl/protocol/json_get_or_throw.h @@ -35,8 +35,7 @@ struct JsonTypeMismatchError : std::exception char const* const key; std::string const expectedType; mutable std::string msg; - JsonTypeMismatchError(Json::StaticString const& k, std::string et) - : key{k.c_str()}, expectedType{std::move(et)} + JsonTypeMismatchError(Json::StaticString const& k, std::string et) : key{k.c_str()}, expectedType{std::move(et)} { } char const* @@ -44,8 +43,7 @@ struct JsonTypeMismatchError : std::exception { if (msg.empty()) { - msg = std::string("Type mismatch on json key: ") + key + - "; expected type: " + expectedType; + msg = std::string("Type mismatch on json key: ") + key + "; expected type: " + expectedType; } return msg.c_str(); } diff --git a/include/xrpl/protocol/nftPageMask.h b/include/xrpl/protocol/nftPageMask.h index 4d23e45f53..0877d4976d 100644 --- a/include/xrpl/protocol/nftPageMask.h +++ b/include/xrpl/protocol/nftPageMask.h @@ -10,8 +10,7 @@ namespace nft { // NFT directory pages order their contents based only on the low 96 bits of // the NFToken value. This mask provides easy access to the necessary mask. -uint256 constexpr pageMask(std::string_view( - "0000000000000000000000000000000000000000ffffffffffffffffffffffff")); +uint256 constexpr pageMask(std::string_view("0000000000000000000000000000000000000000ffffffffffffffffffffffff")); } // namespace nft } // namespace xrpl diff --git a/include/xrpl/protocol/tokens.h b/include/xrpl/protocol/tokens.h index ac13a10e06..96b311a366 100644 --- a/include/xrpl/protocol/tokens.h +++ b/include/xrpl/protocol/tokens.h @@ -63,11 +63,7 @@ decodeBase58Token(std::string const& s, TokenType type); namespace detail { // Expose detail functions for unit tests only std::string -encodeBase58( - void const* message, - std::size_t size, - void* temp, - std::size_t temp_size); +encodeBase58(void const* message, std::size_t size, void* temp, std::size_t temp_size); std::string decodeBase58(std::string const& s); @@ -79,16 +75,10 @@ namespace b58_fast { // Use the fast version (10-15x faster) is using gcc extensions (int128 in // particular) [[nodiscard]] B58Result> -encodeBase58Token( - TokenType token_type, - std::span input, - std::span out); +encodeBase58Token(TokenType token_type, std::span input, std::span out); [[nodiscard]] B58Result> -decodeBase58Token( - TokenType type, - std::string_view s, - std::span outBuf); +decodeBase58Token(TokenType type, std::string_view s, std::span outBuf); // This interface matches the old interface, but requires additional allocation [[nodiscard]] std::string @@ -101,9 +91,7 @@ decodeBase58Token(std::string const& s, TokenType type); namespace detail { // Expose detail functions for unit tests only B58Result> -b256_to_b58_be( - std::span input, - std::span out); +b256_to_b58_be(std::span input, std::span out); B58Result> b58_to_b256_be(std::string_view input, std::span out); diff --git a/include/xrpl/resource/ResourceManager.h b/include/xrpl/resource/ResourceManager.h index 19690d6bc4..4f331913ef 100644 --- a/include/xrpl/resource/ResourceManager.h +++ b/include/xrpl/resource/ResourceManager.h @@ -28,10 +28,7 @@ public: virtual Consumer newInboundEndpoint(beast::IP::Endpoint const& address) = 0; virtual Consumer - newInboundEndpoint( - beast::IP::Endpoint const& address, - bool const proxy, - std::string_view forwardedFor) = 0; + newInboundEndpoint(beast::IP::Endpoint const& address, bool const proxy, std::string_view forwardedFor) = 0; /** Create a new endpoint keyed by outbound IP address and port. */ virtual Consumer @@ -61,9 +58,7 @@ public: //------------------------------------------------------------------------------ std::unique_ptr -make_Manager( - beast::insight::Collector::ptr const& collector, - beast::Journal journal); +make_Manager(beast::insight::Collector::ptr const& collector, beast::Journal journal); } // namespace Resource } // namespace xrpl diff --git a/include/xrpl/resource/detail/Entry.h b/include/xrpl/resource/detail/Entry.h index ce55c46064..11f8a08511 100644 --- a/include/xrpl/resource/detail/Entry.h +++ b/include/xrpl/resource/detail/Entry.h @@ -23,11 +23,7 @@ struct Entry : public beast::List::Node @param now Construction time of Entry. */ explicit Entry(clock_type::time_point const now) - : refcount(0) - , local_balance(now) - , remote_balance(0) - , lastWarningTime() - , whenExpires() + : refcount(0), local_balance(now), remote_balance(0), lastWarningTime(), whenExpires() { } diff --git a/include/xrpl/resource/detail/Logic.h b/include/xrpl/resource/detail/Logic.h index 5bcfa42f31..e12d02b996 100644 --- a/include/xrpl/resource/detail/Logic.h +++ b/include/xrpl/resource/detail/Logic.h @@ -69,10 +69,7 @@ private: //-------------------------------------------------------------------------- public: - Logic( - beast::insight::Collector::ptr const& collector, - clock_type& clock, - beast::Journal journal) + Logic(beast::insight::Collector::ptr const& collector, clock_type& clock, beast::Journal journal) : m_stats(collector), m_clock(clock), m_journal(journal) { } @@ -199,8 +196,7 @@ public: int localBalance = inboundEntry.local_balance.value(now); if ((localBalance + inboundEntry.remote_balance) >= threshold) { - Json::Value& entry = - (ret[inboundEntry.to_string()] = Json::objectValue); + Json::Value& entry = (ret[inboundEntry.to_string()] = Json::objectValue); entry[jss::local] = localBalance; entry[jss::remote] = inboundEntry.remote_balance; entry[jss::type] = "inbound"; @@ -211,8 +207,7 @@ public: int localBalance = outboundEntry.local_balance.value(now); if ((localBalance + outboundEntry.remote_balance) >= threshold) { - Json::Value& entry = - (ret[outboundEntry.to_string()] = Json::objectValue); + Json::Value& entry = (ret[outboundEntry.to_string()] = Json::objectValue); entry[jss::local] = localBalance; entry[jss::remote] = outboundEntry.remote_balance; entry[jss::type] = "outbound"; @@ -223,8 +218,7 @@ public: int localBalance = adminEntry.local_balance.value(now); if ((localBalance + adminEntry.remote_balance) >= threshold) { - Json::Value& entry = - (ret[adminEntry.to_string()] = Json::objectValue); + Json::Value& entry = (ret[adminEntry.to_string()] = Json::objectValue); entry[jss::local] = localBalance; entry[jss::remote] = adminEntry.remote_balance; entry[jss::type] = "admin"; @@ -268,9 +262,8 @@ public: std::lock_guard _(lock_); auto [resultIt, resultInserted] = importTable_.emplace( std::piecewise_construct, - std::make_tuple(origin), // Key - std::make_tuple( - m_clock.now().time_since_epoch().count())); // Import + std::make_tuple(origin), // Key + std::make_tuple(m_clock.now().time_since_epoch().count())); // Import if (resultInserted) { @@ -348,12 +341,9 @@ public: Import& import(iter->second); if (iter->second.whenExpires <= elapsed) { - for (auto item_iter(import.items.begin()); - item_iter != import.items.end(); - ++item_iter) + for (auto item_iter(import.items.begin()); item_iter != import.items.end(); ++item_iter) { - item_iter->consumer.entry().remote_balance -= - item_iter->balance; + item_iter->consumer.entry().remote_balance -= item_iter->balance; } iter = importTable_.erase(iter); @@ -383,9 +373,7 @@ public: { std::lock_guard _(lock_); Entry& entry(iter->second); - XRPL_ASSERT( - entry.refcount == 0, - "xrpl::Resource::Logic::erase : entry not used"); + XRPL_ASSERT(entry.refcount == 0, "xrpl::Resource::Logic::erase : entry not used"); inactive_.erase(inactive_.iterator_to(entry)); table_.erase(iter); } @@ -435,12 +423,9 @@ public: static constexpr Charge::value_type feeLogAsWarn = 3000; static constexpr Charge::value_type feeLogAsInfo = 1000; static constexpr Charge::value_type feeLogAsDebug = 100; - static_assert( - feeLogAsWarn > feeLogAsInfo && feeLogAsInfo > feeLogAsDebug && - feeLogAsDebug > 10); + static_assert(feeLogAsWarn > feeLogAsInfo && feeLogAsInfo > feeLogAsDebug && feeLogAsDebug > 10); - static auto getStream = [](Resource::Charge::value_type cost, - beast::Journal& journal) { + static auto getStream = [](Resource::Charge::value_type cost, beast::Journal& journal) { if (cost >= feeLogAsWarn) return journal.warn(); if (cost >= feeLogAsInfo) @@ -456,8 +441,7 @@ public: std::lock_guard _(lock_); clock_type::time_point const now(m_clock.now()); int const balance(entry.add(fee.cost(), now)); - JLOG(getStream(fee.cost(), m_journal)) - << "Charging " << entry << " for " << fee << context; + JLOG(getStream(fee.cost(), m_journal)) << "Charging " << entry << " for " << fee << context; return disposition(balance); } @@ -470,8 +454,7 @@ public: std::lock_guard _(lock_); bool notify(false); auto const elapsed = m_clock.now(); - if (entry.balance(m_clock.now()) >= warningThreshold && - elapsed != entry.lastWarningTime) + if (entry.balance(m_clock.now()) >= warningThreshold && elapsed != entry.lastWarningTime) { charge(entry, feeWarning); notify = true; @@ -497,9 +480,8 @@ public: int const balance(entry.balance(now)); if (balance >= dropThreshold) { - JLOG(m_journal.warn()) - << "Consumer entry " << entry << " dropped with balance " - << balance << " at or above drop threshold " << dropThreshold; + JLOG(m_journal.warn()) << "Consumer entry " << entry << " dropped with balance " << balance + << " at or above drop threshold " << dropThreshold; // Adding feeDrop at this point keeps the dropped connection // from re-connecting for at least a little while after it is @@ -521,10 +503,7 @@ public: //-------------------------------------------------------------------------- void - writeList( - clock_type::time_point const now, - beast::PropertyStream::Set& items, - EntryIntrusiveList& list) + writeList(clock_type::time_point const now, beast::PropertyStream::Set& items, EntryIntrusiveList& list) { for (auto& entry : list) { diff --git a/include/xrpl/server/Handoff.h b/include/xrpl/server/Handoff.h index 49a5851251..2edb6e2203 100644 --- a/include/xrpl/server/Handoff.h +++ b/include/xrpl/server/Handoff.h @@ -10,11 +10,9 @@ namespace xrpl { -using http_request_type = - boost::beast::http::request; +using http_request_type = boost::beast::http::request; -using http_response_type = - boost::beast::http::response; +using http_response_type = boost::beast::http::response; /** Used to indicate the result of a server connection handoff. */ struct Handoff diff --git a/include/xrpl/server/Server.h b/include/xrpl/server/Server.h index b553b9e72a..7bc7765cea 100644 --- a/include/xrpl/server/Server.h +++ b/include/xrpl/server/Server.h @@ -13,10 +13,7 @@ namespace xrpl { /** Create the HTTP server using the specified handler. */ template std::unique_ptr -make_Server( - Handler& handler, - boost::asio::io_context& io_context, - beast::Journal journal) +make_Server(Handler& handler, boost::asio::io_context& io_context, beast::Journal journal) { return std::make_unique>(handler, io_context, journal); } diff --git a/include/xrpl/server/Session.h b/include/xrpl/server/Session.h index 4570e90f7e..e2c640b827 100644 --- a/include/xrpl/server/Session.h +++ b/include/xrpl/server/Session.h @@ -64,9 +64,7 @@ public: void write(BufferSequence const& buffers) { - for (typename BufferSequence::const_iterator iter(buffers.begin()); - iter != buffers.end(); - ++iter) + for (typename BufferSequence::const_iterator iter(buffers.begin()); iter != buffers.end(); ++iter) { typename BufferSequence::value_type const& buffer(*iter); write(buffer.data(), boost::asio::buffer_size(buffer)); diff --git a/include/xrpl/server/SimpleWriter.h b/include/xrpl/server/SimpleWriter.h index cf41f1c82a..75af7169fc 100644 --- a/include/xrpl/server/SimpleWriter.h +++ b/include/xrpl/server/SimpleWriter.h @@ -19,8 +19,7 @@ class SimpleWriter : public Writer public: template - explicit SimpleWriter( - boost::beast::http::message const& msg) + explicit SimpleWriter(boost::beast::http::message const& msg) { boost::beast::ostream(sb_) << msg; } diff --git a/include/xrpl/server/WSSession.h b/include/xrpl/server/WSSession.h index fb8af7118c..b2d116bb45 100644 --- a/include/xrpl/server/WSSession.h +++ b/include/xrpl/server/WSSession.h @@ -78,8 +78,7 @@ public: done = true; } auto const pb = boost::beast::buffers_prefix(n_, sb_.data()); - std::vector vb( - std::distance(pb.begin(), pb.end())); + std::vector vb(std::distance(pb.begin(), pb.end())); std::copy(pb.begin(), pb.end(), std::back_inserter(vb)); return {done, vb}; } diff --git a/include/xrpl/server/detail/BaseHTTPPeer.h b/include/xrpl/server/detail/BaseHTTPPeer.h index 5b7327c6b9..2a2c523e2b 100644 --- a/include/xrpl/server/detail/BaseHTTPPeer.h +++ b/include/xrpl/server/detail/BaseHTTPPeer.h @@ -49,8 +49,7 @@ protected: struct buffer { - buffer(void const* ptr, std::size_t len) - : data(new char[len]), bytes(len), used(0) + buffer(void const* ptr, std::size_t len) : data(new char[len]), bytes(len), used(0) { memcpy(data.get(), ptr, len); } @@ -132,10 +131,7 @@ protected: on_write(error_code const& ec, std::size_t bytes_transferred); void - do_writer( - std::shared_ptr const& writer, - bool keep_alive, - yield_context do_yield); + do_writer(std::shared_ptr const& writer, bool keep_alive, yield_context do_yield); virtual void do_request() = 0; @@ -203,8 +199,7 @@ BaseHTTPPeer::BaseHTTPPeer( , remote_address_(remote_address) , journal_(journal) { - read_buf_.commit(boost::asio::buffer_copy( - read_buf_.prepare(boost::asio::buffer_size(buffers)), buffers)); + read_buf_.commit(boost::asio::buffer_copy(read_buf_.prepare(boost::asio::buffer_size(buffers)), buffers)); static std::atomic sid; nid_ = ++sid; id_ = std::string("#") + std::to_string(nid_) + " "; @@ -216,8 +211,7 @@ BaseHTTPPeer::~BaseHTTPPeer() { handler_.onClose(session(), ec_); JLOG(journal_.trace()) << id_ << "destroyed: " << request_count_ - << ((request_count_ == 1) ? " request" - : " requests"); + << ((request_count_ == 1) ? " request" : " requests"); } template @@ -225,11 +219,7 @@ void BaseHTTPPeer::close() { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind( - (void(BaseHTTPPeer::*)(void)) & BaseHTTPPeer::close, - impl().shared_from_this())); + return post(strand_, std::bind((void(BaseHTTPPeer::*)(void)) & BaseHTTPPeer::close, impl().shared_from_this())); boost::beast::get_lowest_layer(impl().stream_).close(); } @@ -242,8 +232,7 @@ BaseHTTPPeer::fail(error_code ec, char const* what) if (!ec_ && ec != boost::asio::error::operation_aborted) { ec_ = ec; - JLOG(journal_.trace()) - << id_ << std::string(what) << ": " << ec.message(); + JLOG(journal_.trace()) << id_ << std::string(what) << ": " << ec.message(); boost::beast::get_lowest_layer(impl().stream_).close(); } } @@ -253,9 +242,8 @@ void BaseHTTPPeer::start_timer() { boost::beast::get_lowest_layer(impl().stream_) - .expires_after(std::chrono::seconds( - remote_address_.address().is_loopback() ? timeoutSecondsLocal - : timeoutSeconds)); + .expires_after( + std::chrono::seconds(remote_address_.address().is_loopback() ? timeoutSecondsLocal : timeoutSeconds)); } // Convenience for discarding the error code @@ -271,8 +259,7 @@ template void BaseHTTPPeer::on_timer() { - auto ec = - boost::system::errc::make_error_code(boost::system::errc::timed_out); + auto ec = boost::system::errc::make_error_code(boost::system::errc::timed_out); fail(ec, "timer"); } @@ -285,8 +272,7 @@ BaseHTTPPeer::do_read(yield_context do_yield) complete_ = false; error_code ec; start_timer(); - boost::beast::http::async_read( - impl().stream_, read_buf_, message_, do_yield[ec]); + boost::beast::http::async_read(impl().stream_, read_buf_, message_, do_yield[ec]); cancel_timer(); if (ec == boost::beast::http::error::end_of_stream) return do_close(); @@ -301,9 +287,7 @@ BaseHTTPPeer::do_read(yield_context do_yield) // The write queue must not be empty upon entry. template void -BaseHTTPPeer::on_write( - error_code const& ec, - std::size_t bytes_transferred) +BaseHTTPPeer::on_write(error_code const& ec, std::size_t bytes_transferred) { cancel_timer(); if (ec == boost::beast::error::timeout) @@ -330,29 +314,19 @@ BaseHTTPPeer::on_write( bind_executor( strand_, std::bind( - &BaseHTTPPeer::on_write, - impl().shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + &BaseHTTPPeer::on_write, impl().shared_from_this(), std::placeholders::_1, std::placeholders::_2))); } if (!complete_) return; if (graceful_) return do_close(); util::spawn( - strand_, - std::bind( - &BaseHTTPPeer::do_read, - impl().shared_from_this(), - std::placeholders::_1)); + strand_, std::bind(&BaseHTTPPeer::do_read, impl().shared_from_this(), std::placeholders::_1)); } template void -BaseHTTPPeer::do_writer( - std::shared_ptr const& writer, - bool keep_alive, - yield_context do_yield) +BaseHTTPPeer::do_writer(std::shared_ptr const& writer, bool keep_alive, yield_context do_yield) { std::function resume; { @@ -360,12 +334,7 @@ BaseHTTPPeer::do_writer( resume = std::function([this, p, writer, keep_alive]() { util::spawn( strand_, - std::bind( - &BaseHTTPPeer::do_writer, - p, - writer, - keep_alive, - std::placeholders::_1)); + std::bind(&BaseHTTPPeer::do_writer, p, writer, keep_alive, std::placeholders::_1)); }); } @@ -374,11 +343,8 @@ BaseHTTPPeer::do_writer( if (!writer->prepare(bufferSize, resume)) return; error_code ec; - auto const bytes_transferred = boost::asio::async_write( - impl().stream_, - writer->data(), - boost::asio::transfer_at_least(1), - do_yield[ec]); + auto const bytes_transferred = + boost::asio::async_write(impl().stream_, writer->data(), boost::asio::transfer_at_least(1), do_yield[ec]); if (ec) return fail(ec, "writer"); writer->consume(bytes_transferred); @@ -390,11 +356,7 @@ BaseHTTPPeer::do_writer( return do_close(); util::spawn( - strand_, - std::bind( - &BaseHTTPPeer::do_read, - impl().shared_from_this(), - std::placeholders::_1)); + strand_, std::bind(&BaseHTTPPeer::do_read, impl().shared_from_this(), std::placeholders::_1)); } //------------------------------------------------------------------------------ @@ -413,13 +375,7 @@ BaseHTTPPeer::write(void const* buf, std::size_t bytes) }()) { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind( - &BaseHTTPPeer::on_write, - impl().shared_from_this(), - error_code{}, - 0)); + return post(strand_, std::bind(&BaseHTTPPeer::on_write, impl().shared_from_this(), error_code{}, 0)); else return on_write(error_code{}, 0); } @@ -427,9 +383,7 @@ BaseHTTPPeer::write(void const* buf, std::size_t bytes) template void -BaseHTTPPeer::write( - std::shared_ptr const& writer, - bool keep_alive) +BaseHTTPPeer::write(std::shared_ptr const& writer, bool keep_alive) { util::spawn( strand_, @@ -457,11 +411,7 @@ void BaseHTTPPeer::complete() { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind( - &BaseHTTPPeer::complete, - impl().shared_from_this())); + return post(strand_, std::bind(&BaseHTTPPeer::complete, impl().shared_from_this())); message_ = {}; complete_ = true; @@ -474,11 +424,7 @@ BaseHTTPPeer::complete() // keep-alive util::spawn( - strand_, - std::bind( - &BaseHTTPPeer::do_read, - impl().shared_from_this(), - std::placeholders::_1)); + strand_, std::bind(&BaseHTTPPeer::do_read, impl().shared_from_this(), std::placeholders::_1)); } // DEPRECATED @@ -491,8 +437,7 @@ BaseHTTPPeer::close(bool graceful) return post( strand_, std::bind( - (void(BaseHTTPPeer::*)(bool)) & - BaseHTTPPeer::close, + (void(BaseHTTPPeer::*)(bool)) & BaseHTTPPeer::close, impl().shared_from_this(), graceful)); diff --git a/include/xrpl/server/detail/BasePeer.h b/include/xrpl/server/detail/BasePeer.h index fa82a1bb37..cbd8ac2c8d 100644 --- a/include/xrpl/server/detail/BasePeer.h +++ b/include/xrpl/server/detail/BasePeer.h @@ -82,8 +82,7 @@ void BasePeer::close() { if (!strand_.running_in_this_thread()) - return post( - strand_, std::bind(&BasePeer::close, impl().shared_from_this())); + return post(strand_, std::bind(&BasePeer::close, impl().shared_from_this())); error_code ec; xrpl::get_lowest_layer(impl().ws_).socket().close(ec); } diff --git a/include/xrpl/server/detail/BaseWSPeer.h b/include/xrpl/server/detail/BaseWSPeer.h index f0649b221c..435930e476 100644 --- a/include/xrpl/server/detail/BaseWSPeer.h +++ b/include/xrpl/server/detail/BaseWSPeer.h @@ -49,9 +49,7 @@ private: bool ping_active_ = false; boost::beast::websocket::ping_data payload_; error_code ec_; - std::function< - void(boost::beast::websocket::frame_type, boost::beast::string_view)> - control_callback_; + std::function control_callback_; public: template @@ -139,9 +137,7 @@ protected: on_ping(error_code const& ec); void - on_ping_pong( - boost::beast::websocket::frame_type kind, - boost::beast::string_view payload); + on_ping_pong(boost::beast::websocket::frame_type kind, boost::beast::string_view payload); void on_timer(error_code ec); @@ -175,33 +171,20 @@ void BaseWSPeer::run() { if (!strand_.running_in_this_thread()) - return post( - strand_, std::bind(&BaseWSPeer::run, impl().shared_from_this())); + return post(strand_, std::bind(&BaseWSPeer::run, impl().shared_from_this())); impl().ws_.set_option(port().pmd_options); // Must manage the control callback memory outside of the `control_callback` // function - control_callback_ = std::bind( - &BaseWSPeer::on_ping_pong, - this, - std::placeholders::_1, - std::placeholders::_2); + control_callback_ = std::bind(&BaseWSPeer::on_ping_pong, this, std::placeholders::_1, std::placeholders::_2); impl().ws_.control_callback(control_callback_); start_timer(); close_on_timer_ = true; - impl().ws_.set_option( - boost::beast::websocket::stream_base::decorator([](auto& res) { - res.set( - boost::beast::http::field::server, - BuildInfo::getFullVersionString()); - })); + impl().ws_.set_option(boost::beast::websocket::stream_base::decorator( + [](auto& res) { res.set(boost::beast::http::field::server, BuildInfo::getFullVersionString()); })); impl().ws_.async_accept( request_, bind_executor( - strand_, - std::bind( - &BaseWSPeer::on_ws_handshake, - impl().shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&BaseWSPeer::on_ws_handshake, impl().shared_from_this(), std::placeholders::_1))); } template @@ -209,16 +192,12 @@ void BaseWSPeer::send(std::shared_ptr w) { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind( - &BaseWSPeer::send, impl().shared_from_this(), std::move(w))); + return post(strand_, std::bind(&BaseWSPeer::send, impl().shared_from_this(), std::move(w))); if (do_close_) return; if (wq_.size() > port().ws_queue_limit) { - cr_.code = safe_cast( - boost::beast::websocket::close_code::policy_error); + cr_.code = safe_cast(boost::beast::websocket::close_code::policy_error); cr_.reason = "Policy error: client is too slow."; JLOG(this->j_.info()) << cr_.reason; wq_.erase(std::next(wq_.begin()), wq_.end()); @@ -239,26 +218,19 @@ BaseWSPeer::close() template void -BaseWSPeer::close( - boost::beast::websocket::close_reason const& reason) +BaseWSPeer::close(boost::beast::websocket::close_reason const& reason) { if (!strand_.running_in_this_thread()) - return post(strand_, [self = impl().shared_from_this(), reason] { - self->close(reason); - }); + return post(strand_, [self = impl().shared_from_this(), reason] { self->close(reason); }); if (do_close_) return; do_close_ = true; if (wq_.empty()) { impl().ws_.async_close( - reason, - bind_executor( - strand_, - [self = impl().shared_from_this()]( - boost::beast::error_code const& ec) { - self->on_close(ec); - })); + reason, bind_executor(strand_, [self = impl().shared_from_this()](boost::beast::error_code const& ec) { + self->on_close(ec); + })); } else { @@ -271,9 +243,7 @@ void BaseWSPeer::complete() { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind(&BaseWSPeer::complete, impl().shared_from_this())); + return post(strand_, std::bind(&BaseWSPeer::complete, impl().shared_from_this())); do_read(); } @@ -292,9 +262,7 @@ void BaseWSPeer::do_write() { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind(&BaseWSPeer::do_write, impl().shared_from_this())); + return post(strand_, std::bind(&BaseWSPeer::do_write, impl().shared_from_this())); on_write({}); } @@ -305,8 +273,7 @@ BaseWSPeer::on_write(error_code const& ec) if (ec) return fail(ec, "write"); auto& w = *wq_.front(); - auto const result = w.prepare( - 65536, std::bind(&BaseWSPeer::do_write, impl().shared_from_this())); + auto const result = w.prepare(65536, std::bind(&BaseWSPeer::do_write, impl().shared_from_this())); if (boost::indeterminate(result.first)) return; start_timer(); @@ -314,22 +281,13 @@ BaseWSPeer::on_write(error_code const& ec) impl().ws_.async_write_some( static_cast(result.first), result.second, - bind_executor( - strand_, - std::bind( - &BaseWSPeer::on_write, - impl().shared_from_this(), - std::placeholders::_1))); + bind_executor(strand_, std::bind(&BaseWSPeer::on_write, impl().shared_from_this(), std::placeholders::_1))); else impl().ws_.async_write_some( static_cast(result.first), result.second, bind_executor( - strand_, - std::bind( - &BaseWSPeer::on_write_fin, - impl().shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&BaseWSPeer::on_write_fin, impl().shared_from_this(), std::placeholders::_1))); } template @@ -343,12 +301,7 @@ BaseWSPeer::on_write_fin(error_code const& ec) { impl().ws_.async_close( cr_, - bind_executor( - strand_, - std::bind( - &BaseWSPeer::on_close, - impl().shared_from_this(), - std::placeholders::_1))); + bind_executor(strand_, std::bind(&BaseWSPeer::on_close, impl().shared_from_this(), std::placeholders::_1))); } else if (!wq_.empty()) on_write({}); @@ -359,17 +312,9 @@ void BaseWSPeer::do_read() { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind(&BaseWSPeer::do_read, impl().shared_from_this())); + return post(strand_, std::bind(&BaseWSPeer::do_read, impl().shared_from_this())); impl().ws_.async_read( - rb_, - bind_executor( - strand_, - std::bind( - &BaseWSPeer::on_read, - impl().shared_from_this(), - std::placeholders::_1))); + rb_, bind_executor(strand_, std::bind(&BaseWSPeer::on_read, impl().shared_from_this(), std::placeholders::_1))); } template @@ -405,8 +350,7 @@ BaseWSPeer::start_timer() try { - timer_.expires_after( - remote_endpoint().address().is_loopback() ? timeoutLocal : timeout); + timer_.expires_after(remote_endpoint().address().is_loopback() ? timeoutLocal : timeout); } catch (boost::system::system_error const& e) { @@ -414,11 +358,7 @@ BaseWSPeer::start_timer() } timer_.async_wait(bind_executor( - strand_, - std::bind( - &BaseWSPeer::on_timer, - impl().shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&BaseWSPeer::on_timer, impl().shared_from_this(), std::placeholders::_1))); } // Convenience for discarding the error code @@ -450,9 +390,7 @@ BaseWSPeer::on_ping(error_code const& ec) template void -BaseWSPeer::on_ping_pong( - boost::beast::websocket::frame_type kind, - boost::beast::string_view payload) +BaseWSPeer::on_ping_pong(boost::beast::websocket::frame_type kind, boost::beast::string_view payload) { if (kind == boost::beast::websocket::frame_type::pong) { @@ -487,16 +425,11 @@ BaseWSPeer::on_timer(error_code ec) impl().ws_.async_ping( payload_, bind_executor( - strand_, - std::bind( - &BaseWSPeer::on_ping, - impl().shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&BaseWSPeer::on_ping, impl().shared_from_this(), std::placeholders::_1))); JLOG(this->j_.trace()) << "sent ping"; return; } - ec = boost::system::errc::make_error_code( - boost::system::errc::timed_out); + ec = boost::system::errc::make_error_code(boost::system::errc::timed_out); } fail(ec, "timer"); } @@ -506,9 +439,7 @@ template void BaseWSPeer::fail(error_code ec, String const& what) { - XRPL_ASSERT( - strand_.running_in_this_thread(), - "xrpl::BaseWSPeer::fail : strand in this thread"); + XRPL_ASSERT(strand_.running_in_this_thread(), "xrpl::BaseWSPeer::fail : strand in this thread"); cancel_timer(); if (!ec_ && ec != boost::asio::error::operation_aborted) diff --git a/include/xrpl/server/detail/Door.h b/include/xrpl/server/detail/Door.h index 140afb1808..9177d373bc 100644 --- a/include/xrpl/server/detail/Door.h +++ b/include/xrpl/server/detail/Door.h @@ -39,8 +39,7 @@ namespace xrpl { /** A listening socket. */ template -class Door : public io_list::work, - public std::enable_shared_from_this> +class Door : public io_list::work, public std::enable_shared_from_this> { private: using clock_type = std::chrono::steady_clock; @@ -54,8 +53,7 @@ private: using stream_type = boost::beast::tcp_stream; // Detects SSL on a socket - class Detector : public io_list::work, - public std::enable_shared_from_this + class Detector : public io_list::work, public std::enable_shared_from_this { private: Port const& port_; @@ -115,11 +113,7 @@ private: should_throttle_for_fds(); public: - Door( - Handler& handler, - boost::asio::io_context& io_context, - Port const& port, - beast::Journal j); + Door(Handler& handler, boost::asio::io_context& io_context, Port const& port, beast::Journal j); // Work-around because we can't call shared_from_this in ctor void @@ -143,11 +137,7 @@ public: private: template void - create( - bool ssl, - ConstBufferSequence const& buffers, - stream_type&& stream, - endpoint_type remote_address); + create(bool ssl, ConstBufferSequence const& buffers, stream_type&& stream, endpoint_type remote_address); void do_accept(yield_context yield); @@ -176,12 +166,7 @@ template void Door::Detector::run() { - util::spawn( - strand_, - std::bind( - &Detector::do_detect, - this->shared_from_this(), - std::placeholders::_1)); + util::spawn(strand_, std::bind(&Detector::do_detect, this->shared_from_this(), std::placeholders::_1)); } template @@ -205,31 +190,18 @@ Door::Detector::do_detect(boost::asio::yield_context do_yield) if (ssl) { if (auto sp = ios().template emplace>( - port_, - handler_, - ioc_, - j_, - remote_address_, - buf.data(), - std::move(stream_))) + port_, handler_, ioc_, j_, remote_address_, buf.data(), std::move(stream_))) sp->run(); return; } if (auto sp = ios().template emplace>( - port_, - handler_, - ioc_, - j_, - remote_address_, - buf.data(), - std::move(stream_))) + port_, handler_, ioc_, j_, remote_address_, buf.data(), std::move(stream_))) sp->run(); return; } if (ec != boost::asio::error::operation_aborted) { - JLOG(j_.trace()) << "Error detecting ssl: " << ec.message() << " from " - << remote_address_; + JLOG(j_.trace()) << "Error detecting ssl: " << ec.message() << " from " << remote_address_; } } @@ -247,8 +219,7 @@ Door::reOpen() if (ec) { std::stringstream ss; - ss << "Can't close acceptor: " << port_.name << ", " - << ec.message(); + ss << "Can't close acceptor: " << port_.name << ", " << ec.message(); JLOG(j_.error()) << ss.str(); Throw(ss.str()); } @@ -259,33 +230,28 @@ Door::reOpen() acceptor_.open(local_address.protocol(), ec); if (ec) { - JLOG(j_.error()) << "Open port '" << port_.name - << "' failed:" << ec.message(); + JLOG(j_.error()) << "Open port '" << port_.name << "' failed:" << ec.message(); Throw(); } - acceptor_.set_option( - boost::asio::ip::tcp::acceptor::reuse_address(true), ec); + acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), ec); if (ec) { - JLOG(j_.error()) << "Option for port '" << port_.name - << "' failed:" << ec.message(); + JLOG(j_.error()) << "Option for port '" << port_.name << "' failed:" << ec.message(); Throw(); } acceptor_.bind(local_address, ec); if (ec) { - JLOG(j_.error()) << "Bind port '" << port_.name - << "' failed:" << ec.message(); + JLOG(j_.error()) << "Bind port '" << port_.name << "' failed:" << ec.message(); Throw(); } acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec); if (ec) { - JLOG(j_.error()) << "Listen on port '" << port_.name - << "' failed:" << ec.message(); + JLOG(j_.error()) << "Listen on port '" << port_.name << "' failed:" << ec.message(); Throw(); } @@ -293,11 +259,7 @@ Door::reOpen() } template -Door::Door( - Handler& handler, - boost::asio::io_context& io_context, - Port const& port, - beast::Journal j) +Door::Door(Handler& handler, boost::asio::io_context& io_context, Port const& port, beast::Journal j) : j_(j) , port_(port) , handler_(handler) @@ -305,12 +267,9 @@ Door::Door( , acceptor_(io_context) , strand_(boost::asio::make_strand(io_context)) , ssl_( - port_.protocol.count("https") > 0 || - port_.protocol.count("wss") > 0 || port_.protocol.count("wss2") > 0 || + port_.protocol.count("https") > 0 || port_.protocol.count("wss") > 0 || port_.protocol.count("wss2") > 0 || port_.protocol.count("peer") > 0) - , plain_( - port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 || - port_.protocol.count("ws2")) + , plain_(port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 || port_.protocol.count("ws2")) , backoff_timer_(io_context) { reOpen(); @@ -320,12 +279,7 @@ template void Door::run() { - util::spawn( - strand_, - std::bind( - &Door::do_accept, - this->shared_from_this(), - std::placeholders::_1)); + util::spawn(strand_, std::bind(&Door::do_accept, this->shared_from_this(), std::placeholders::_1)); } template @@ -333,9 +287,7 @@ void Door::close() { if (!strand_.running_in_this_thread()) - return boost::asio::post( - strand_, - std::bind(&Door::close, this->shared_from_this())); + return boost::asio::post(strand_, std::bind(&Door::close, this->shared_from_this())); backoff_timer_.cancel(); error_code ec; acceptor_.close(ec); @@ -346,33 +298,17 @@ Door::close() template template void -Door::create( - bool ssl, - ConstBufferSequence const& buffers, - stream_type&& stream, - endpoint_type remote_address) +Door::create(bool ssl, ConstBufferSequence const& buffers, stream_type&& stream, endpoint_type remote_address) { if (ssl) { if (auto sp = ios().template emplace>( - port_, - handler_, - ioc_, - j_, - remote_address, - buffers, - std::move(stream))) + port_, handler_, ioc_, j_, remote_address, buffers, std::move(stream))) sp->run(); return; } if (auto sp = ios().template emplace>( - port_, - handler_, - ioc_, - j_, - remote_address, - buffers, - std::move(stream))) + port_, handler_, ioc_, j_, remote_address, buffers, std::move(stream))) sp->run(); } @@ -388,8 +324,7 @@ Door::do_accept(boost::asio::yield_context do_yield) boost::system::error_code tec; backoff_timer_.async_wait(do_yield[tec]); accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY); - JLOG(j_.warn()) << "Throttling do_accept for " - << accept_delay_.count() << "ms."; + JLOG(j_.warn()) << "Throttling do_accept for " << accept_delay_.count() << "ms."; continue; } @@ -403,11 +338,9 @@ Door::do_accept(boost::asio::yield_context do_yield) if (ec == boost::asio::error::operation_aborted) break; - if (ec == boost::asio::error::no_descriptors || - ec == boost::asio::error::no_buffer_space) + if (ec == boost::asio::error::no_descriptors || ec == boost::asio::error::no_buffer_space) { - JLOG(j_.warn()) << "accept: Too many open files. Pausing for " - << accept_delay_.count() << "ms."; + JLOG(j_.warn()) << "accept: Too many open files. Pausing for " << accept_delay_.count() << "ms."; backoff_timer_.expires_after(accept_delay_); boost::system::error_code tec; @@ -426,22 +359,13 @@ Door::do_accept(boost::asio::yield_context do_yield) if (ssl_ && plain_) { - if (auto sp = ios().template emplace( - port_, - handler_, - ioc_, - std::move(stream), - remote_address, - j_)) + if (auto sp = + ios().template emplace(port_, handler_, ioc_, std::move(stream), remote_address, j_)) sp->run(); } else if (ssl_ || plain_) { - create( - ssl_, - boost::asio::null_buffers{}, - std::move(stream), - remote_address); + create(ssl_, boost::asio::null_buffers{}, std::move(stream), remote_address); } } } @@ -490,8 +414,7 @@ Door::should_throttle_for_fds() auto const& s = *stats; auto const free = (s.limit > s.used) ? (s.limit - s.used) : 0ull; - double const free_ratio = - static_cast(free) / static_cast(s.limit); + double const free_ratio = static_cast(free) / static_cast(s.limit); if (free_ratio < FREE_FD_THRESHOLD) { return true; diff --git a/include/xrpl/server/detail/JSONRPCUtil.h b/include/xrpl/server/detail/JSONRPCUtil.h index d75825a1ea..2d4f6a6771 100644 --- a/include/xrpl/server/detail/JSONRPCUtil.h +++ b/include/xrpl/server/detail/JSONRPCUtil.h @@ -8,11 +8,7 @@ namespace xrpl { void -HTTPReply( - int nStatus, - std::string const& strMsg, - Json::Output const&, - beast::Journal j); +HTTPReply(int nStatus, std::string const& strMsg, Json::Output const&, beast::Journal j); } // namespace xrpl diff --git a/include/xrpl/server/detail/PlainHTTPPeer.h b/include/xrpl/server/detail/PlainHTTPPeer.h index 8f7d86f8e5..834a99aae8 100644 --- a/include/xrpl/server/detail/PlainHTTPPeer.h +++ b/include/xrpl/server/detail/PlainHTTPPeer.h @@ -12,9 +12,8 @@ namespace xrpl { template -class PlainHTTPPeer - : public BaseHTTPPeer>, - public std::enable_shared_from_this> +class PlainHTTPPeer : public BaseHTTPPeer>, + public std::enable_shared_from_this> { private: friend class BaseHTTPPeer; @@ -62,13 +61,7 @@ PlainHTTPPeer::PlainHTTPPeer( endpoint_type remote_endpoint, ConstBufferSequence const& buffers, stream_type&& stream) - : BaseHTTPPeer( - port, - handler, - ioc.get_executor(), - journal, - remote_endpoint, - buffers) + : BaseHTTPPeer(port, handler, ioc.get_executor(), journal, remote_endpoint, buffers) , stream_(std::move(stream)) , socket_(stream_.socket()) { @@ -86,21 +79,14 @@ PlainHTTPPeer::run() { if (!this->handler_.onAccept(this->session(), this->remote_address_)) { - util::spawn( - this->strand_, - std::bind(&PlainHTTPPeer::do_close, this->shared_from_this())); + util::spawn(this->strand_, std::bind(&PlainHTTPPeer::do_close, this->shared_from_this())); return; } if (!socket_.is_open()) return; - util::spawn( - this->strand_, - std::bind( - &PlainHTTPPeer::do_read, - this->shared_from_this(), - std::placeholders::_1)); + util::spawn(this->strand_, std::bind(&PlainHTTPPeer::do_read, this->shared_from_this(), std::placeholders::_1)); } template @@ -122,8 +108,7 @@ void PlainHTTPPeer::do_request() { ++this->request_count_; - auto const what = this->handler_.onHandoff( - this->session(), std::move(this->message_), this->remote_address_); + auto const what = this->handler_.onHandoff(this->session(), std::move(this->message_), this->remote_address_); if (what.moved) return; boost::system::error_code ec; diff --git a/include/xrpl/server/detail/SSLHTTPPeer.h b/include/xrpl/server/detail/SSLHTTPPeer.h index 56b2d1c52f..b0102ac24b 100644 --- a/include/xrpl/server/detail/SSLHTTPPeer.h +++ b/include/xrpl/server/detail/SSLHTTPPeer.h @@ -74,16 +74,8 @@ SSLHTTPPeer::SSLHTTPPeer( endpoint_type remote_address, ConstBufferSequence const& buffers, middle_type&& stream) - : BaseHTTPPeer( - port, - handler, - ioc.get_executor(), - journal, - remote_address, - buffers) - , stream_ptr_(std::make_unique( - middle_type(std::move(stream)), - *port.context)) + : BaseHTTPPeer(port, handler, ioc.get_executor(), journal, remote_address, buffers) + , stream_ptr_(std::make_unique(middle_type(std::move(stream)), *port.context)) , stream_(*stream_ptr_) , socket_(stream_.next_layer().socket()) { @@ -96,19 +88,12 @@ SSLHTTPPeer::run() { if (!this->handler_.onAccept(this->session(), this->remote_address_)) { - util::spawn( - this->strand_, - std::bind(&SSLHTTPPeer::do_close, this->shared_from_this())); + util::spawn(this->strand_, std::bind(&SSLHTTPPeer::do_close, this->shared_from_this())); return; } if (!socket_.is_open()) return; - util::spawn( - this->strand_, - std::bind( - &SSLHTTPPeer::do_handshake, - this->shared_from_this(), - std::placeholders::_1)); + util::spawn(this->strand_, std::bind(&SSLHTTPPeer::do_handshake, this->shared_from_this(), std::placeholders::_1)); } template @@ -132,25 +117,17 @@ SSLHTTPPeer::do_handshake(yield_context do_yield) boost::system::error_code ec; stream_.set_verify_mode(boost::asio::ssl::verify_none); this->start_timer(); - this->read_buf_.consume(stream_.async_handshake( - stream_type::server, this->read_buf_.data(), do_yield[ec])); + this->read_buf_.consume(stream_.async_handshake(stream_type::server, this->read_buf_.data(), do_yield[ec])); this->cancel_timer(); if (ec == boost::beast::error::timeout) return this->on_timer(); if (ec) return this->fail(ec, "handshake"); - bool const http = this->port().protocol.count("peer") > 0 || - this->port().protocol.count("wss") > 0 || - this->port().protocol.count("wss2") > 0 || - this->port().protocol.count("https") > 0; + bool const http = this->port().protocol.count("peer") > 0 || this->port().protocol.count("wss") > 0 || + this->port().protocol.count("wss2") > 0 || this->port().protocol.count("https") > 0; if (http) { - util::spawn( - this->strand_, - std::bind( - &SSLHTTPPeer::do_read, - this->shared_from_this(), - std::placeholders::_1)); + util::spawn(this->strand_, std::bind(&SSLHTTPPeer::do_read, this->shared_from_this(), std::placeholders::_1)); return; } // `this` will be destroyed @@ -162,10 +139,7 @@ SSLHTTPPeer::do_request() { ++this->request_count_; auto const what = this->handler_.onHandoff( - this->session(), - std::move(stream_ptr_), - std::move(this->message_), - this->remote_address_); + this->session(), std::move(stream_ptr_), std::move(this->message_), this->remote_address_); if (what.moved) return; if (what.response) @@ -180,11 +154,7 @@ SSLHTTPPeer::do_close() { this->start_timer(); stream_.async_shutdown(bind_executor( - this->strand_, - std::bind( - &SSLHTTPPeer::on_shutdown, - this->shared_from_this(), - std::placeholders::_1))); + this->strand_, std::bind(&SSLHTTPPeer::on_shutdown, this->shared_from_this(), std::placeholders::_1))); } template diff --git a/include/xrpl/server/detail/ServerImpl.h b/include/xrpl/server/detail/ServerImpl.h index 6ff93e83cb..e341eac849 100644 --- a/include/xrpl/server/detail/ServerImpl.h +++ b/include/xrpl/server/detail/ServerImpl.h @@ -18,8 +18,7 @@ namespace xrpl { -using Endpoints = - std::unordered_map; +using Endpoints = std::unordered_map; /** A multi-protocol server. @@ -70,9 +69,7 @@ private: beast::Journal const j_; boost::asio::io_context& io_context_; boost::asio::strand strand_; - std::optional> - work_; + std::optional> work_; std::mutex m_; std::vector ports_; @@ -83,10 +80,7 @@ private: io_list ios_; public: - ServerImpl( - Handler& handler, - boost::asio::io_context& io_context, - beast::Journal journal); + ServerImpl(Handler& handler, boost::asio::io_context& io_context, beast::Journal journal); ~ServerImpl(); @@ -123,10 +117,7 @@ private: }; template -ServerImpl::ServerImpl( - Handler& handler, - boost::asio::io_context& io_context, - beast::Journal journal) +ServerImpl::ServerImpl(Handler& handler, boost::asio::io_context& io_context, beast::Journal journal) : handler_(handler) , j_(journal) , io_context_(io_context) @@ -157,8 +148,7 @@ ServerImpl::ports(std::vector const& ports) { ports_.push_back(port); auto& internalPort = ports_.back(); - if (auto sp = ios_.emplace>( - handler_, io_context_, internalPort, j_)) + if (auto sp = ios_.emplace>(handler_, io_context_, internalPort, j_)) { list_.push_back(sp); diff --git a/include/xrpl/server/detail/Spawn.h b/include/xrpl/server/detail/Spawn.h index 4c424a1956..1fbf9e7003 100644 --- a/include/xrpl/server/detail/Spawn.h +++ b/include/xrpl/server/detail/Spawn.h @@ -13,9 +13,7 @@ namespace xrpl::util { namespace impl { template -concept IsStrand = std::same_as< - std::decay_t, - boost::asio::strand::inner_executor_type>>; +concept IsStrand = std::same_as, boost::asio::strand::inner_executor_type>>; /** * @brief A completion handler that restores `boost::asio::spawn`'s behaviour @@ -69,16 +67,12 @@ spawn(Ctx&& ctx, F&& func) { if constexpr (impl::IsStrand) { - boost::asio::spawn( - std::forward(ctx), - std::forward(func), - impl::kPROPAGATE_EXCEPTIONS); + boost::asio::spawn(std::forward(ctx), std::forward(func), impl::kPROPAGATE_EXCEPTIONS); } else { boost::asio::spawn( - boost::asio::make_strand( - boost::asio::get_associated_executor(std::forward(ctx))), + boost::asio::make_strand(boost::asio::get_associated_executor(std::forward(ctx))), std::forward(func), impl::kPROPAGATE_EXCEPTIONS); } diff --git a/include/xrpl/server/detail/io_list.h b/include/xrpl/server/detail/io_list.h index 0e67595dbe..e60c33d084 100644 --- a/include/xrpl/server/detail/io_list.h +++ b/include/xrpl/server/detail/io_list.h @@ -190,8 +190,7 @@ template std::shared_ptr io_list::emplace(Args&&... args) { - static_assert( - std::is_base_of::value, "T must derive from io_list::work"); + static_assert(std::is_base_of::value, "T must derive from io_list::work"); if (closed_) return nullptr; auto sp = std::make_shared(std::forward(args)...); diff --git a/include/xrpl/shamap/FullBelowCache.h b/include/xrpl/shamap/FullBelowCache.h index 9434b40011..4b7a9aae67 100644 --- a/include/xrpl/shamap/FullBelowCache.h +++ b/include/xrpl/shamap/FullBelowCache.h @@ -39,8 +39,7 @@ public: std::string const& name, clock_type& clock, beast::Journal j, - beast::insight::Collector::ptr const& collector = - beast::insight::NullCollector::New(), + beast::insight::Collector::ptr const& collector = beast::insight::NullCollector::New(), std::size_t target_size = defaultCacheTargetSize, std::chrono::seconds expiration = std::chrono::minutes{2}) : m_cache(name, target_size, expiration, clock, j, collector), m_gen(1) diff --git a/include/xrpl/shamap/SHAMap.h b/include/xrpl/shamap/SHAMap.h index 94fd926718..9013b3cc9c 100644 --- a/include/xrpl/shamap/SHAMap.h +++ b/include/xrpl/shamap/SHAMap.h @@ -95,15 +95,12 @@ private: public: /** Number of children each non-leaf node has (the 'radix tree' part of the * map) */ - static inline constexpr unsigned int branchFactor = - SHAMapInnerNode::branchFactor; + static inline constexpr unsigned int branchFactor = SHAMapInnerNode::branchFactor; /** The depth of the hash map: data is only present in the leaves */ static inline constexpr unsigned int leafDepth = 64; - using DeltaItem = std::pair< - boost::intrusive_ptr, - boost::intrusive_ptr>; + using DeltaItem = std::pair, boost::intrusive_ptr>; using Delta = std::map; SHAMap() = delete; @@ -183,14 +180,10 @@ public: // save a copy if you have a temporary anyway bool - updateGiveItem( - SHAMapNodeType type, - boost::intrusive_ptr item); + updateGiveItem(SHAMapNodeType type, boost::intrusive_ptr item); bool - addGiveItem( - SHAMapNodeType type, - boost::intrusive_ptr item); + addGiveItem(SHAMapNodeType type, boost::intrusive_ptr item); // Save a copy if you need to extend the life // of the SHAMapItem beyond this SHAMap @@ -233,18 +226,14 @@ public: If function returns false, visitDifferences exits. */ void - visitDifferences( - SHAMap const* have, - std::function const&) const; + visitDifferences(SHAMap const* have, std::function const&) const; /** Visit every leaf node in this SHAMap @param function called with every non inner node visited. */ void - visitLeaves( - std::function< - void(boost::intrusive_ptr const&)> const&) const; + visitLeaves(std::function const&)> const&) const; // comparison/sync functions @@ -285,25 +274,16 @@ public: * @return true if verified successfully */ static bool - verifyProofPath( - uint256 const& rootHash, - uint256 const& key, - std::vector const& path); + verifyProofPath(uint256 const& rootHash, uint256 const& key, std::vector const& path); /** Serializes the root in a format appropriate for sending over the wire */ void serializeRoot(Serializer& s) const; SHAMapAddNode - addRootNode( - SHAMapHash const& hash, - Slice const& rootNode, - SHAMapSyncFilter* filter); + addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFilter* filter); SHAMapAddNode - addKnownNode( - SHAMapNodeID const& nodeID, - Slice const& rawNode, - SHAMapSyncFilter* filter); + addKnownNode(SHAMapNodeID const& nodeID, Slice const& rawNode, SHAMapSyncFilter* filter); // status functions void @@ -333,9 +313,7 @@ public: void walkMap(std::vector& missingNodes, int maxMissing) const; bool - walkMapParallel( - std::vector& missingNodes, - int maxMissing) const; + walkMapParallel(std::vector& missingNodes, int maxMissing) const; bool deepCompare(SHAMap& other) const; // Intended for debug/test only @@ -348,19 +326,15 @@ public: invariants() const; private: - using SharedPtrNodeStack = std::stack< - std::pair, SHAMapNodeID>>; - using DeltaRef = std::pair< - boost::intrusive_ptr, - boost::intrusive_ptr>; + using SharedPtrNodeStack = std::stack, SHAMapNodeID>>; + using DeltaRef = std::pair, boost::intrusive_ptr>; // tree node cache operations intr_ptr::SharedPtr cacheLookup(SHAMapHash const& hash) const; void - canonicalize(SHAMapHash const& hash, intr_ptr::SharedPtr&) - const; + canonicalize(SHAMapHash const& hash, intr_ptr::SharedPtr&) const; // database operations intr_ptr::SharedPtr @@ -376,17 +350,13 @@ private: /** Update hashes up to the root */ void - dirtyUp( - SharedPtrNodeStack& stack, - uint256 const& target, - intr_ptr::SharedPtr terminal); + dirtyUp(SharedPtrNodeStack& stack, uint256 const& target, intr_ptr::SharedPtr terminal); /** Walk towards the specified id, returning the node. Caller must check if the return is nullptr, and if not, if the node->peekItem()->key() == id */ SHAMapLeafNode* - walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack = nullptr) - const; + walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack = nullptr) const; /** Return nullptr if key not found */ SHAMapLeafNode* findKey(uint256 const& id) const; @@ -407,17 +377,11 @@ private: // returns the first item at or below this node SHAMapLeafNode* - firstBelow( - intr_ptr::SharedPtr, - SharedPtrNodeStack& stack, - int branch = 0) const; + firstBelow(intr_ptr::SharedPtr, SharedPtrNodeStack& stack, int branch = 0) const; // returns the last item at or below this node SHAMapLeafNode* - lastBelow( - intr_ptr::SharedPtr node, - SharedPtrNodeStack& stack, - int branch = branchFactor) const; + lastBelow(intr_ptr::SharedPtr node, SharedPtrNodeStack& stack, int branch = branchFactor) const; // helper function for firstBelow and lastBelow SHAMapLeafNode* @@ -425,10 +389,7 @@ private: intr_ptr::SharedPtr node, SharedPtrNodeStack& stack, int branch, - std::tuple< - int, - std::function, - std::function> const& loopParams) const; + std::tuple, std::function> const& loopParams) const; // Simple descent // Get a child of the specified node @@ -443,22 +404,12 @@ private: // Descend with filter // If pending, callback is called as if it called fetchNodeNT - using descendCallback = std::function< - void(intr_ptr::SharedPtr, SHAMapHash const&)>; + using descendCallback = std::function, SHAMapHash const&)>; SHAMapTreeNode* - descendAsync( - SHAMapInnerNode* parent, - int branch, - SHAMapSyncFilter* filter, - bool& pending, - descendCallback&&) const; + descendAsync(SHAMapInnerNode* parent, int branch, SHAMapSyncFilter* filter, bool& pending, descendCallback&&) const; std::pair - descend( - SHAMapInnerNode* parent, - SHAMapNodeID const& parentID, - int branch, - SHAMapSyncFilter* filter) const; + descend(SHAMapInnerNode* parent, SHAMapNodeID const& parentID, int branch, SHAMapSyncFilter* filter) const; // Non-storing // Does not hook the returned node to its parent @@ -538,16 +489,8 @@ private: // reads std::map resumes_; - MissingNodes( - int max, - SHAMapSyncFilter* filter, - int maxDefer, - std::uint32_t generation) - : max_(max) - , filter_(filter) - , maxDefer_(maxDefer) - , generation_(generation) - , deferred_(0) + MissingNodes(int max, SHAMapSyncFilter* filter, int maxDefer, std::uint32_t generation) + : max_(max), filter_(filter), maxDefer_(maxDefer), generation_(generation), deferred_(0) { missingNodes_.reserve(max); finishedReads_.reserve(maxDefer); @@ -562,9 +505,7 @@ private: // fetch from DB helper function intr_ptr::SharedPtr - finishFetch( - SHAMapHash const& hash, - std::shared_ptr const& object) const; + finishFetch(SHAMapHash const& hash, std::shared_ptr const& object) const; }; inline void @@ -582,9 +523,7 @@ SHAMap::setLedgerSeq(std::uint32_t lseq) inline void SHAMap::setImmutable() { - XRPL_ASSERT( - state_ != SHAMapState::Invalid, - "xrpl::SHAMap::setImmutable : state is valid"); + XRPL_ASSERT(state_ != SHAMapState::Invalid, "xrpl::SHAMap::setImmutable : state is valid"); state_ = SHAMapState::Immutable; } @@ -665,22 +604,17 @@ private: inline SHAMap::const_iterator::const_iterator(SHAMap const* map) : map_(map) { - XRPL_ASSERT( - map_, "xrpl::SHAMap::const_iterator::const_iterator : non-null input"); + XRPL_ASSERT(map_, "xrpl::SHAMap::const_iterator::const_iterator : non-null input"); if (auto temp = map_->peekFirstItem(stack_)) item_ = temp->peekItem().get(); } -inline SHAMap::const_iterator::const_iterator(SHAMap const* map, std::nullptr_t) - : map_(map) +inline SHAMap::const_iterator::const_iterator(SHAMap const* map, std::nullptr_t) : map_(map) { } -inline SHAMap::const_iterator::const_iterator( - SHAMap const* map, - pointer item, - SharedPtrNodeStack&& stack) +inline SHAMap::const_iterator::const_iterator(SHAMap const* map, pointer item, SharedPtrNodeStack&& stack) : stack_(std::move(stack)), map_(map), item_(item) { } diff --git a/include/xrpl/shamap/SHAMapAccountStateLeafNode.h b/include/xrpl/shamap/SHAMapAccountStateLeafNode.h index 288fc416b5..c622d68a1f 100644 --- a/include/xrpl/shamap/SHAMapAccountStateLeafNode.h +++ b/include/xrpl/shamap/SHAMapAccountStateLeafNode.h @@ -10,23 +10,16 @@ namespace xrpl { /** A leaf node for a state object. */ -class SHAMapAccountStateLeafNode final - : public SHAMapLeafNode, - public CountedObject +class SHAMapAccountStateLeafNode final : public SHAMapLeafNode, public CountedObject { public: - SHAMapAccountStateLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid) + SHAMapAccountStateLeafNode(boost::intrusive_ptr item, std::uint32_t cowid) : SHAMapLeafNode(std::move(item), cowid) { updateHash(); } - SHAMapAccountStateLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid, - SHAMapHash const& hash) + SHAMapAccountStateLeafNode(boost::intrusive_ptr item, std::uint32_t cowid, SHAMapHash const& hash) : SHAMapLeafNode(std::move(item), cowid, hash) { } @@ -34,8 +27,7 @@ public: intr_ptr::SharedPtr clone(std::uint32_t cowid) const final override { - return intr_ptr::make_shared( - item_, cowid, hash_); + return intr_ptr::make_shared(item_, cowid, hash_); } SHAMapNodeType @@ -47,8 +39,7 @@ public: void updateHash() final override { - hash_ = SHAMapHash{ - sha512Half(HashPrefix::leafNode, item_->slice(), item_->key())}; + hash_ = SHAMapHash{sha512Half(HashPrefix::leafNode, item_->slice(), item_->key())}; } void diff --git a/include/xrpl/shamap/SHAMapAddNode.h b/include/xrpl/shamap/SHAMapAddNode.h index 0385f64f52..2dc3d15486 100644 --- a/include/xrpl/shamap/SHAMapAddNode.h +++ b/include/xrpl/shamap/SHAMapAddNode.h @@ -52,8 +52,7 @@ inline SHAMapAddNode::SHAMapAddNode() : mGood(0), mBad(0), mDuplicate(0) { } -inline SHAMapAddNode::SHAMapAddNode(int good, int bad, int duplicate) - : mGood(good), mBad(bad), mDuplicate(duplicate) +inline SHAMapAddNode::SHAMapAddNode(int good, int bad, int duplicate) : mGood(good), mBad(bad), mDuplicate(duplicate) { } diff --git a/include/xrpl/shamap/SHAMapInnerNode.h b/include/xrpl/shamap/SHAMapInnerNode.h index 72a7fe52d4..eab60f0348 100644 --- a/include/xrpl/shamap/SHAMapInnerNode.h +++ b/include/xrpl/shamap/SHAMapInnerNode.h @@ -12,8 +12,7 @@ namespace xrpl { -class SHAMapInnerNode final : public SHAMapTreeNode, - public CountedObject +class SHAMapInnerNode final : public SHAMapTreeNode, public CountedObject { public: /** Each inner node has 16 children (the 'radix tree' part of the map) */ @@ -78,9 +77,7 @@ private: iterNonEmptyChildIndexes(F&& f) const; public: - explicit SHAMapInnerNode( - std::uint32_t cowid, - std::uint8_t numAllocatedChildren = 2); + explicit SHAMapInnerNode(std::uint32_t cowid, std::uint8_t numAllocatedChildren = 2); SHAMapInnerNode(SHAMapInnerNode const&) = delete; SHAMapInnerNode& diff --git a/include/xrpl/shamap/SHAMapItem.h b/include/xrpl/shamap/SHAMapItem.h index e8d95b0684..a67dfd866c 100644 --- a/include/xrpl/shamap/SHAMapItem.h +++ b/include/xrpl/shamap/SHAMapItem.h @@ -43,13 +43,9 @@ private: // the only way to properly create one is to first allocate enough memory // so we limit this constructor to codepaths that do this right and limit // arbitrary construction. - SHAMapItem(uint256 const& tag, Slice data) - : tag_(tag), size_(static_cast(data.size())) + SHAMapItem(uint256 const& tag, Slice data) : tag_(tag), size_(static_cast(data.size())) { - std::memcpy( - reinterpret_cast(this) + sizeof(*this), - data.data(), - data.size()); + std::memcpy(reinterpret_cast(this) + sizeof(*this), data.data(), data.size()); } public: @@ -141,9 +137,7 @@ intrusive_ptr_release(SHAMapItem const* x) inline boost::intrusive_ptr make_shamapitem(uint256 const& tag, Slice data) { - XRPL_ASSERT( - data.size() <= megabytes(16), - "xrpl::make_shamapitem : maximum input size"); + XRPL_ASSERT(data.size() <= megabytes(16), "xrpl::make_shamapitem : maximum input size"); std::uint8_t* raw = detail::slabber.allocate(data.size()); diff --git a/include/xrpl/shamap/SHAMapLeafNode.h b/include/xrpl/shamap/SHAMapLeafNode.h index d87ede16ad..4d18fc9108 100644 --- a/include/xrpl/shamap/SHAMapLeafNode.h +++ b/include/xrpl/shamap/SHAMapLeafNode.h @@ -13,14 +13,9 @@ class SHAMapLeafNode : public SHAMapTreeNode protected: boost::intrusive_ptr item_; - SHAMapLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid); + SHAMapLeafNode(boost::intrusive_ptr item, std::uint32_t cowid); - SHAMapLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid, - SHAMapHash const& hash); + SHAMapLeafNode(boost::intrusive_ptr item, std::uint32_t cowid, SHAMapHash const& hash); public: SHAMapLeafNode(SHAMapLeafNode const&) = delete; diff --git a/include/xrpl/shamap/SHAMapMissingNode.h b/include/xrpl/shamap/SHAMapMissingNode.h index 0cb18238af..2b9e71dfed 100644 --- a/include/xrpl/shamap/SHAMapMissingNode.h +++ b/include/xrpl/shamap/SHAMapMissingNode.h @@ -29,8 +29,7 @@ to_string(SHAMapType t) case SHAMapType::FREE: return "Free Tree"; default: - return std::to_string( - safe_cast>(t)); + return std::to_string(safe_cast>(t)); } } @@ -38,14 +37,12 @@ class SHAMapMissingNode : public std::runtime_error { public: SHAMapMissingNode(SHAMapType t, SHAMapHash const& hash) - : std::runtime_error( - "Missing Node: " + to_string(t) + ": hash " + to_string(hash)) + : std::runtime_error("Missing Node: " + to_string(t) + ": hash " + to_string(hash)) { } SHAMapMissingNode(SHAMapType t, uint256 const& id) - : std::runtime_error( - "Missing Node: " + to_string(t) + ": id " + to_string(id)) + : std::runtime_error("Missing Node: " + to_string(t) + ": id " + to_string(id)) { } }; diff --git a/include/xrpl/shamap/SHAMapNodeID.h b/include/xrpl/shamap/SHAMapNodeID.h index 2a9e4446f4..9155b6db39 100644 --- a/include/xrpl/shamap/SHAMapNodeID.h +++ b/include/xrpl/shamap/SHAMapNodeID.h @@ -106,8 +106,7 @@ to_string(SHAMapNodeID const& node) if (node.isRoot()) return "NodeID(root)"; - return "NodeID(" + std::to_string(node.getDepth()) + "," + - to_string(node.getNodeID()) + ")"; + return "NodeID(" + std::to_string(node.getDepth()) + "," + to_string(node.getNodeID()) + ")"; } inline std::ostream& diff --git a/include/xrpl/shamap/SHAMapSyncFilter.h b/include/xrpl/shamap/SHAMapSyncFilter.h index 16b2389745..32923c741a 100644 --- a/include/xrpl/shamap/SHAMapSyncFilter.h +++ b/include/xrpl/shamap/SHAMapSyncFilter.h @@ -19,12 +19,8 @@ public: // Note that the nodeData is overwritten by this call virtual void - gotNode( - bool fromFilter, - SHAMapHash const& nodeHash, - std::uint32_t ledgerSeq, - Blob&& nodeData, - SHAMapNodeType type) const = 0; + gotNode(bool fromFilter, SHAMapHash const& nodeHash, std::uint32_t ledgerSeq, Blob&& nodeData, SHAMapNodeType type) + const = 0; virtual std::optional getNode(SHAMapHash const& nodeHash) const = 0; diff --git a/include/xrpl/shamap/SHAMapTreeNode.h b/include/xrpl/shamap/SHAMapTreeNode.h index 75992a9bce..91adc8a88e 100644 --- a/include/xrpl/shamap/SHAMapTreeNode.h +++ b/include/xrpl/shamap/SHAMapTreeNode.h @@ -56,10 +56,7 @@ protected: { } - explicit SHAMapTreeNode( - std::uint32_t cowid, - SHAMapHash const& hash) noexcept - : hash_(hash), cowid_(cowid) + explicit SHAMapTreeNode(std::uint32_t cowid, SHAMapHash const& hash) noexcept : hash_(hash), cowid_(cowid) { } /** @} */ diff --git a/include/xrpl/shamap/SHAMapTxLeafNode.h b/include/xrpl/shamap/SHAMapTxLeafNode.h index e7b73ecde9..0552a86759 100644 --- a/include/xrpl/shamap/SHAMapTxLeafNode.h +++ b/include/xrpl/shamap/SHAMapTxLeafNode.h @@ -10,22 +10,16 @@ namespace xrpl { /** A leaf node for a transaction. No metadata is included. */ -class SHAMapTxLeafNode final : public SHAMapLeafNode, - public CountedObject +class SHAMapTxLeafNode final : public SHAMapLeafNode, public CountedObject { public: - SHAMapTxLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid) + SHAMapTxLeafNode(boost::intrusive_ptr item, std::uint32_t cowid) : SHAMapLeafNode(std::move(item), cowid) { updateHash(); } - SHAMapTxLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid, - SHAMapHash const& hash) + SHAMapTxLeafNode(boost::intrusive_ptr item, std::uint32_t cowid, SHAMapHash const& hash) : SHAMapLeafNode(std::move(item), cowid, hash) { } @@ -45,8 +39,7 @@ public: void updateHash() final override { - hash_ = - SHAMapHash{sha512Half(HashPrefix::transactionID, item_->slice())}; + hash_ = SHAMapHash{sha512Half(HashPrefix::transactionID, item_->slice())}; } void diff --git a/include/xrpl/shamap/SHAMapTxPlusMetaLeafNode.h b/include/xrpl/shamap/SHAMapTxPlusMetaLeafNode.h index c38277ef73..4d1dbf0a3a 100644 --- a/include/xrpl/shamap/SHAMapTxPlusMetaLeafNode.h +++ b/include/xrpl/shamap/SHAMapTxPlusMetaLeafNode.h @@ -10,23 +10,16 @@ namespace xrpl { /** A leaf node for a transaction and its associated metadata. */ -class SHAMapTxPlusMetaLeafNode final - : public SHAMapLeafNode, - public CountedObject +class SHAMapTxPlusMetaLeafNode final : public SHAMapLeafNode, public CountedObject { public: - SHAMapTxPlusMetaLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid) + SHAMapTxPlusMetaLeafNode(boost::intrusive_ptr item, std::uint32_t cowid) : SHAMapLeafNode(std::move(item), cowid) { updateHash(); } - SHAMapTxPlusMetaLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid, - SHAMapHash const& hash) + SHAMapTxPlusMetaLeafNode(boost::intrusive_ptr item, std::uint32_t cowid, SHAMapHash const& hash) : SHAMapLeafNode(std::move(item), cowid, hash) { } @@ -34,8 +27,7 @@ public: intr_ptr::SharedPtr clone(std::uint32_t cowid) const override { - return intr_ptr::make_shared( - item_, cowid, hash_); + return intr_ptr::make_shared(item_, cowid, hash_); } SHAMapNodeType @@ -47,8 +39,7 @@ public: void updateHash() final override { - hash_ = SHAMapHash{ - sha512Half(HashPrefix::txNode, item_->slice(), item_->key())}; + hash_ = SHAMapHash{sha512Half(HashPrefix::txNode, item_->slice(), item_->key())}; } void diff --git a/include/xrpl/shamap/detail/TaggedPointer.h b/include/xrpl/shamap/detail/TaggedPointer.h index 53a53960d4..e66568035b 100644 --- a/include/xrpl/shamap/detail/TaggedPointer.h +++ b/include/xrpl/shamap/detail/TaggedPointer.h @@ -40,9 +40,7 @@ namespace xrpl { class TaggedPointer { private: - static_assert( - alignof(SHAMapHash) >= 4, - "Bad alignment: Tag pointer requires low two bits to be zero."); + static_assert(alignof(SHAMapHash) >= 4, "Bad alignment: Tag pointer requires low two bits to be zero."); /** Upper bits are the pointer, lowest two bits are the tag A moved-from object will have a tp_ of zero. */ @@ -92,10 +90,7 @@ public: @param toAllocate allocate space for at least this number of children (must be <= branchFactor) */ - explicit TaggedPointer( - TaggedPointer&& other, - std::uint16_t isBranch, - std::uint8_t toAllocate); + explicit TaggedPointer(TaggedPointer&& other, std::uint16_t isBranch, std::uint8_t toAllocate); /** Given `other` with the specified children in `srcBranches`, create a new TaggedPointer with the allocated number of children and the @@ -152,9 +147,8 @@ public: /** Get the number of elements in each array and a pointer to the start of each array. */ - [[nodiscard]] std:: - tuple*> - getHashesAndChildren() const; + [[nodiscard]] std::tuple*> + getHashesAndChildren() const; /** Get the `hashes` array */ [[nodiscard]] SHAMapHash* diff --git a/include/xrpl/shamap/detail/TaggedPointer.ipp b/include/xrpl/shamap/detail/TaggedPointer.ipp index e88b4b11c4..bedb33a733 100644 --- a/include/xrpl/shamap/detail/TaggedPointer.ipp +++ b/include/xrpl/shamap/detail/TaggedPointer.ipp @@ -13,11 +13,7 @@ namespace { // Given n children, an array of size `*std::lower_bound(boundaries.begin(), // boundaries.end(), n);` is used to store the children. Note that the last // element must be the number of children in a dense array. -constexpr std::array boundaries{ - 2, - 4, - 6, - SHAMapInnerNode::branchFactor}; +constexpr std::array boundaries{2, 4, 6, SHAMapInnerNode::branchFactor}; static_assert( boundaries.size() <= 4, "The hashesAndChildren member uses a tagged array format with two bits " @@ -29,8 +25,7 @@ static_assert( // Terminology: A chunk is the memory being allocated from a block. A block // contains multiple chunks. This is the terminology the boost documentation // uses. Pools use "Simple Segregated Storage" as their storage format. -constexpr size_t elementSizeBytes = - (sizeof(SHAMapHash) + sizeof(intr_ptr::SharedPtr)); +constexpr size_t elementSizeBytes = (sizeof(SHAMapHash) + sizeof(intr_ptr::SharedPtr)); constexpr size_t blockSizeBytes = kilobytes(512); @@ -42,8 +37,7 @@ initArrayChunkSizeBytes(std::index_sequence) boundaries[I] * elementSizeBytes..., }; } -constexpr auto arrayChunkSizeBytes = - initArrayChunkSizeBytes(std::make_index_sequence{}); +constexpr auto arrayChunkSizeBytes = initArrayChunkSizeBytes(std::make_index_sequence{}); template constexpr std::array @@ -53,27 +47,20 @@ initArrayChunksPerBlock(std::index_sequence) blockSizeBytes / arrayChunkSizeBytes[I]..., }; } -constexpr auto chunksPerBlock = - initArrayChunksPerBlock(std::make_index_sequence{}); +constexpr auto chunksPerBlock = initArrayChunksPerBlock(std::make_index_sequence{}); [[nodiscard]] inline std::uint8_t numAllocatedChildren(std::uint8_t n) { - XRPL_ASSERT( - n <= SHAMapInnerNode::branchFactor, - "xrpl::numAllocatedChildren : valid input"); + XRPL_ASSERT(n <= SHAMapInnerNode::branchFactor, "xrpl::numAllocatedChildren : valid input"); return *std::lower_bound(boundaries.begin(), boundaries.end(), n); } [[nodiscard]] inline std::size_t boundariesIndex(std::uint8_t numChildren) { - XRPL_ASSERT( - numChildren <= SHAMapInnerNode::branchFactor, - "xrpl::boundariesIndex : valid input"); - return std::distance( - boundaries.begin(), - std::lower_bound(boundaries.begin(), boundaries.end(), numChildren)); + XRPL_ASSERT(numChildren <= SHAMapInnerNode::branchFactor, "xrpl::boundariesIndex : valid input"); + return std::distance(boundaries.begin(), std::lower_bound(boundaries.begin(), boundaries.end(), numChildren)); } template @@ -124,9 +111,8 @@ initIsFromArrayFuns(std::index_sequence) chunksPerBlock[I]>::is_from..., }; } -std::array, boundaries.size()> const - isFromArrayFuns = - initIsFromArrayFuns(std::make_index_sequence{}); +std::array, boundaries.size()> const isFromArrayFuns = + initIsFromArrayFuns(std::make_index_sequence{}); // This function returns an untagged pointer [[nodiscard]] inline std::pair @@ -140,9 +126,7 @@ allocateArrays(std::uint8_t numChildren) inline void deallocateArrays(std::uint8_t boundaryIndex, void* p) { - XRPL_ASSERT( - isFromArrayFuns[boundaryIndex](p), - "xrpl::deallocateArrays : valid inputs"); + XRPL_ASSERT(isFromArrayFuns[boundaryIndex](p), "xrpl::deallocateArrays : valid inputs"); freeArrayFuns[boundaryIndex](p); } @@ -261,8 +245,7 @@ inline TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t numChildren) "xrpl::TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t) : " "maximum tag"); XRPL_ASSERT( - (reinterpret_cast(p) & ptrMask) == - reinterpret_cast(p), + (reinterpret_cast(p) & ptrMask) == reinterpret_cast(p), "xrpl::TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t) : " "valid pointer"); tp_ = reinterpret_cast(p) + tag; @@ -283,8 +266,7 @@ inline TaggedPointer::TaggedPointer( { // in place *this = std::move(other); - auto [srcDstNumAllocated, srcDstHashes, srcDstChildren] = - getHashesAndChildren(); + auto [srcDstNumAllocated, srcDstHashes, srcDstChildren] = getHashesAndChildren(); bool const srcDstIsDense = isDense(); int srcDstIndex = 0; for (int i = 0; i < SHAMapInnerNode::branchFactor; ++i) @@ -358,13 +340,11 @@ inline TaggedPointer::TaggedPointer( { // not in place TaggedPointer dst{RawAllocateTag{}, toAllocate}; - auto [dstNumAllocated, dstHashes, dstChildren] = - dst.getHashesAndChildren(); + auto [dstNumAllocated, dstHashes, dstChildren] = dst.getHashesAndChildren(); // Move `other` into a local var so it's not in a partially moved from // state after this function runs TaggedPointer src(std::move(other)); - auto [srcNumAllocated, srcHashes, srcChildren] = - src.getHashesAndChildren(); + auto [srcNumAllocated, srcHashes, srcChildren] = src.getHashesAndChildren(); bool const srcIsDense = src.isDense(); bool const dstIsDense = dst.isDense(); int srcIndex = 0, dstIndex = 0; @@ -378,9 +358,7 @@ inline TaggedPointer::TaggedPointer( // keep new (&dstHashes[dstIndex]) SHAMapHash{srcHashes[srcIndex]}; - new (&dstChildren[dstIndex]) - intr_ptr::SharedPtr{ - std::move(srcChildren[srcIndex])}; + new (&dstChildren[dstIndex]) intr_ptr::SharedPtr{std::move(srcChildren[srcIndex])}; ++dstIndex; ++srcIndex; } @@ -391,8 +369,7 @@ inline TaggedPointer::TaggedPointer( if (dstIsDense) { new (&dstHashes[dstIndex]) SHAMapHash{}; - new (&dstChildren[dstIndex]) - intr_ptr::SharedPtr{}; + new (&dstChildren[dstIndex]) intr_ptr::SharedPtr{}; ++dstIndex; } } @@ -400,8 +377,7 @@ inline TaggedPointer::TaggedPointer( { // add new (&dstHashes[dstIndex]) SHAMapHash{}; - new (&dstChildren[dstIndex]) - intr_ptr::SharedPtr{}; + new (&dstChildren[dstIndex]) intr_ptr::SharedPtr{}; ++dstIndex; if (srcIsDense) { @@ -414,8 +390,7 @@ inline TaggedPointer::TaggedPointer( if (dstIsDense) { new (&dstHashes[dstIndex]) SHAMapHash{}; - new (&dstChildren[dstIndex]) - intr_ptr::SharedPtr{}; + new (&dstChildren[dstIndex]) intr_ptr::SharedPtr{}; ++dstIndex; } if (srcIsDense) @@ -438,10 +413,7 @@ inline TaggedPointer::TaggedPointer( } } -inline TaggedPointer::TaggedPointer( - TaggedPointer&& other, - std::uint16_t isBranch, - std::uint8_t toAllocate) +inline TaggedPointer::TaggedPointer(TaggedPointer&& other, std::uint16_t isBranch, std::uint8_t toAllocate) : TaggedPointer(std::move(other)) { auto const oldNumAllocated = capacity(); @@ -455,8 +427,7 @@ inline TaggedPointer::TaggedPointer( intr_ptr::SharedPtr*newChildren, *oldChildren; std::uint8_t newNumAllocated; // structured bindings can't be captured in c++ 17; use tie instead - std::tie(newNumAllocated, newHashes, newChildren) = - newHashesAndChildren.getHashesAndChildren(); + std::tie(newNumAllocated, newHashes, newChildren) = newHashesAndChildren.getHashesAndChildren(); std::tie(std::ignore, oldHashes, oldChildren) = getHashesAndChildren(); if (newNumAllocated == SHAMapInnerNode::branchFactor) @@ -464,8 +435,7 @@ inline TaggedPointer::TaggedPointer( // new arrays are dense, old arrays are sparse iterNonEmptyChildIndexes(isBranch, [&](auto branchNum, auto indexNum) { new (&newHashes[branchNum]) SHAMapHash{oldHashes[indexNum]}; - new (&newChildren[branchNum]) intr_ptr::SharedPtr{ - std::move(oldChildren[indexNum])}; + new (&newChildren[branchNum]) intr_ptr::SharedPtr{std::move(oldChildren[indexNum])}; }); // Run the constructors for the remaining elements for (int i = 0; i < SHAMapInnerNode::branchFactor; ++i) @@ -481,11 +451,9 @@ inline TaggedPointer::TaggedPointer( // new arrays are sparse, old arrays may be sparse or dense int curCompressedIndex = 0; iterNonEmptyChildIndexes(isBranch, [&](auto branchNum, auto indexNum) { - new (&newHashes[curCompressedIndex]) - SHAMapHash{oldHashes[indexNum]}; + new (&newHashes[curCompressedIndex]) SHAMapHash{oldHashes[indexNum]}; new (&newChildren[curCompressedIndex]) - intr_ptr::SharedPtr{ - std::move(oldChildren[indexNum])}; + intr_ptr::SharedPtr{std::move(oldChildren[indexNum])}; ++curCompressedIndex; }); // Run the constructors for the remaining elements @@ -544,16 +512,13 @@ TaggedPointer::isDense() const return (tp_ & tagMask) == boundaries.size() - 1; } -[[nodiscard]] inline std:: - tuple*> - TaggedPointer::getHashesAndChildren() const +[[nodiscard]] inline std::tuple*> +TaggedPointer::getHashesAndChildren() const { auto const [tag, ptr] = decode(); auto const hashes = reinterpret_cast(ptr); std::uint8_t numAllocated = boundaries[tag]; - auto const children = - reinterpret_cast*>( - hashes + numAllocated); + auto const children = reinterpret_cast*>(hashes + numAllocated); return {numAllocated, hashes, children}; }; diff --git a/src/libxrpl/basics/Archive.cpp b/src/libxrpl/basics/Archive.cpp index 8ee23afda0..a4100e8196 100644 --- a/src/libxrpl/basics/Archive.cpp +++ b/src/libxrpl/basics/Archive.cpp @@ -14,17 +14,13 @@ namespace xrpl { void -extractTarLz4( - boost::filesystem::path const& src, - boost::filesystem::path const& dst) +extractTarLz4(boost::filesystem::path const& src, boost::filesystem::path const& dst) { if (!is_regular_file(src)) Throw("Invalid source file"); - using archive_ptr = - std::unique_ptr; - archive_ptr ar{ - archive_read_new(), [](struct archive* a) { archive_read_free(a); }}; + using archive_ptr = std::unique_ptr; + archive_ptr ar{archive_read_new(), [](struct archive* a) { archive_read_free(a); }}; if (!ar) Throw("Failed to allocate archive"); @@ -35,22 +31,18 @@ extractTarLz4( Throw(archive_error_string(ar.get())); // Examples suggest this block size - if (archive_read_open_filename(ar.get(), src.string().c_str(), 10240) < - ARCHIVE_OK) + if (archive_read_open_filename(ar.get(), src.string().c_str(), 10240) < ARCHIVE_OK) { Throw(archive_error_string(ar.get())); } - archive_ptr aw{archive_write_disk_new(), [](struct archive* a) { - archive_write_free(a); - }}; + archive_ptr aw{archive_write_disk_new(), [](struct archive* a) { archive_write_free(a); }}; if (!aw) Throw("Failed to allocate archive"); if (archive_write_disk_set_options( - aw.get(), - ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | - ARCHIVE_EXTRACT_FFLAGS) < ARCHIVE_OK) + aw.get(), ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS) < + ARCHIVE_OK) { Throw(archive_error_string(aw.get())); } @@ -68,8 +60,7 @@ extractTarLz4( if (result < ARCHIVE_OK) Throw(archive_error_string(ar.get())); - archive_entry_set_pathname( - entry, (dst / archive_entry_pathname(entry)).string().c_str()); + archive_entry_set_pathname(entry, (dst / archive_entry_pathname(entry)).string().c_str()); if (archive_write_header(aw.get(), entry) < ARCHIVE_OK) Throw(archive_error_string(aw.get())); @@ -86,8 +77,7 @@ extractTarLz4( if (result < ARCHIVE_OK) Throw(archive_error_string(ar.get())); - if (archive_write_data_block(aw.get(), buf, sz, offset) < - ARCHIVE_OK) + if (archive_write_data_block(aw.get(), buf, sz, offset) < ARCHIVE_OK) { Throw(archive_error_string(aw.get())); } diff --git a/src/libxrpl/basics/BasicConfig.cpp b/src/libxrpl/basics/BasicConfig.cpp index a5ad7730dd..64e80c63ec 100644 --- a/src/libxrpl/basics/BasicConfig.cpp +++ b/src/libxrpl/basics/BasicConfig.cpp @@ -130,15 +130,9 @@ BasicConfig::section(std::string const& name) const } void -BasicConfig::overwrite( - std::string const& section, - std::string const& key, - std::string const& value) +BasicConfig::overwrite(std::string const& section, std::string const& key, std::string const& value) { - auto const result = map_.emplace( - std::piecewise_construct, - std::make_tuple(section), - std::make_tuple(section)); + auto const result = map_.emplace(std::piecewise_construct, std::make_tuple(section), std::make_tuple(section)); result.first->second.set(key, value); } @@ -167,10 +161,8 @@ BasicConfig::build(IniFileSections const& ifs) { for (auto const& entry : ifs) { - auto const result = map_.emplace( - std::piecewise_construct, - std::make_tuple(entry.first), - std::make_tuple(entry.first)); + auto const result = + map_.emplace(std::piecewise_construct, std::make_tuple(entry.first), std::make_tuple(entry.first)); result.first->second.append(entry.second); } } diff --git a/src/libxrpl/basics/FileUtilities.cpp b/src/libxrpl/basics/FileUtilities.cpp index 981fdd5360..35cc4350ef 100644 --- a/src/libxrpl/basics/FileUtilities.cpp +++ b/src/libxrpl/basics/FileUtilities.cpp @@ -45,9 +45,7 @@ getFileContents( return {}; } - std::string const result{ - std::istreambuf_iterator{fileStream}, - std::istreambuf_iterator{}}; + std::string const result{std::istreambuf_iterator{fileStream}, std::istreambuf_iterator{}}; if (fileStream.bad()) { @@ -59,16 +57,12 @@ getFileContents( } void -writeFileContents( - boost::system::error_code& ec, - boost::filesystem::path const& destPath, - std::string const& contents) +writeFileContents(boost::system::error_code& ec, boost::filesystem::path const& destPath, std::string const& contents) { using namespace boost::filesystem; using namespace boost::system::errc; - std::ofstream fileStream( - destPath.string(), std::ios::out | std::ios::trunc); + std::ofstream fileStream(destPath.string(), std::ios::out | std::ios::trunc); if (!fileStream) { diff --git a/src/libxrpl/basics/Log.cpp b/src/libxrpl/basics/Log.cpp index 33d6f6559e..fc5100a152 100644 --- a/src/libxrpl/basics/Log.cpp +++ b/src/libxrpl/basics/Log.cpp @@ -19,10 +19,7 @@ namespace xrpl { -Logs::Sink::Sink( - std::string const& partition, - beast::severities::Severity thresh, - Logs& logs) +Logs::Sink::Sink(std::string const& partition, beast::severities::Severity thresh, Logs& logs) : beast::Journal::Sink(thresh, false), logs_(logs), partition_(partition) { } @@ -37,9 +34,7 @@ Logs::Sink::write(beast::severities::Severity level, std::string const& text) } void -Logs::Sink::writeAlways( - beast::severities::Severity level, - std::string const& text) +Logs::Sink::writeAlways(beast::severities::Severity level, std::string const& text) { logs_.write(level, partition_, text, console()); } @@ -64,8 +59,7 @@ Logs::File::open(boost::filesystem::path const& path) bool wasOpened = false; // VFALCO TODO Make this work with Unicode file paths - std::unique_ptr stream( - new std::ofstream(path.c_str(), std::fstream::app)); + std::unique_ptr stream(new std::ofstream(path.c_str(), std::fstream::app)); if (stream->good()) { @@ -112,8 +106,7 @@ Logs::File::writeln(char const* text) //------------------------------------------------------------------------------ -Logs::Logs(beast::severities::Severity thresh) - : thresh_(thresh) // default severity +Logs::Logs(beast::severities::Severity thresh) : thresh_(thresh) // default severity { } @@ -170,11 +163,7 @@ Logs::partition_severities() const } void -Logs::write( - beast::severities::Severity level, - std::string const& partition, - std::string const& text, - bool console) +Logs::write(beast::severities::Severity level, std::string const& partition, std::string const& text, bool console) { std::string s; format(s, text, level, partition); @@ -297,8 +286,7 @@ Logs::fromString(std::string const& s) if (boost::iequals(s, "info") || boost::iequals(s, "information")) return lsINFO; - if (boost::iequals(s, "warn") || boost::iequals(s, "warning") || - boost::iequals(s, "warnings")) + if (boost::iequals(s, "warn") || boost::iequals(s, "warning") || boost::iequals(s, "warnings")) return lsWARNING; if (boost::iequals(s, "error") || boost::iequals(s, "errors")) diff --git a/src/libxrpl/basics/Number.cpp b/src/libxrpl/basics/Number.cpp index 436ebf6779..1651e8aba2 100644 --- a/src/libxrpl/basics/Number.cpp +++ b/src/libxrpl/basics/Number.cpp @@ -27,8 +27,7 @@ using int128_t = __int128_t; namespace xrpl { thread_local Number::rounding_mode Number::mode_ = Number::to_nearest; -thread_local std::reference_wrapper Number::range_ = - largeRange; +thread_local std::reference_wrapper Number::range_ = largeRange; Number::rounding_mode Number::getround() @@ -63,8 +62,7 @@ Number::setMantissaScale(MantissaRange::mantissa_scale scale) // to be correctly rounded to the internal precision of Number. template -concept UnsignedMantissa = - std::is_unsigned_v || std::is_same_v; +concept UnsignedMantissa = std::is_unsigned_v || std::is_same_v; class Number::Guard { @@ -114,11 +112,7 @@ public: // Modify the result to the correctly rounded value template void - doRoundDown( - bool& negative, - T& mantissa, - int& exponent, - internalrep const& minMantissa); + doRoundDown(bool& negative, T& mantissa, int& exponent, internalrep const& minMantissa); // Modify the result to the correctly rounded value void @@ -130,11 +124,7 @@ private: template void - bringIntoRange( - bool& negative, - T& mantissa, - int& exponent, - internalrep const& minMantissa); + bringIntoRange(bool& negative, T& mantissa, int& exponent, internalrep const& minMantissa); }; inline void @@ -221,11 +211,7 @@ Number::Guard::round() noexcept template void -Number::Guard::bringIntoRange( - bool& negative, - T& mantissa, - int& exponent, - internalrep const& minMantissa) +Number::Guard::bringIntoRange(bool& negative, T& mantissa, int& exponent, internalrep const& minMantissa) { // Bring mantissa back into the minMantissa / maxMantissa range AFTER // rounding @@ -273,11 +259,7 @@ Number::Guard::doRoundUp( template void -Number::Guard::doRoundDown( - bool& negative, - T& mantissa, - int& exponent, - internalrep const& minMantissa) +Number::Guard::doRoundDown(bool& negative, T& mantissa, int& exponent, internalrep const& minMantissa) { auto r = round(); if (r == 1 || (r == 0 && (mantissa & 1) == 1)) @@ -344,11 +326,7 @@ Number::externalToInternal(rep mantissa) constexpr Number Number::oneSmall() { - return Number{ - false, - Number::smallRange.min, - -Number::smallRange.log, - Number::unchecked{}}; + return Number{false, Number::smallRange.min, -Number::smallRange.log, Number::unchecked{}}; }; constexpr Number oneSml = Number::oneSmall(); @@ -356,11 +334,7 @@ constexpr Number oneSml = Number::oneSmall(); constexpr Number Number::oneLarge() { - return Number{ - false, - Number::largeRange.min, - -Number::largeRange.log, - Number::unchecked{}}; + return Number{false, Number::largeRange.min, -Number::largeRange.log, Number::unchecked{}}; }; constexpr Number oneLrg = Number::oneLarge(); @@ -449,23 +423,12 @@ doNormalize( // modification, it must be less than maxRep. In other words, the original // value should have been no more than maxRep * 10. // (maxRep * 10 > maxMantissa) - XRPL_ASSERT_PARTS( - m <= maxRep, - "xrpl::doNormalize", - "intermediate mantissa fits in int64"); + XRPL_ASSERT_PARTS(m <= maxRep, "xrpl::doNormalize", "intermediate mantissa fits in int64"); mantissa_ = m; - g.doRoundUp( - negative, - mantissa_, - exponent_, - minMantissa, - maxMantissa, - "Number::normalize 2"); + g.doRoundUp(negative, mantissa_, exponent_, minMantissa, maxMantissa, "Number::normalize 2"); XRPL_ASSERT_PARTS( - mantissa_ >= minMantissa && mantissa_ <= maxMantissa, - "xrpl::doNormalize", - "final mantissa fits in range"); + mantissa_ >= minMantissa && mantissa_ <= maxMantissa, "xrpl::doNormalize", "final mantissa fits in range"); } template <> @@ -526,10 +489,7 @@ Number::shiftExponent(int exponentDelta) const return Number{}; } Number const result{negative_, mantissa_, newExponent, unchecked{}}; - XRPL_ASSERT_PARTS( - result.isnormal(), - "xrpl::Number::shiftExponent", - "result is normalized"); + XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::Number::shiftExponent", "result is normalized"); return result; } @@ -550,9 +510,7 @@ Number::operator+=(Number const& y) return *this; } - XRPL_ASSERT( - isnormal() && y.isnormal(), - "xrpl::Number::operator+=(Number) : is normal"); + XRPL_ASSERT(isnormal() && y.isnormal(), "xrpl::Number::operator+=(Number) : is normal"); // *n = negative // *s = sign // *m = mantissa @@ -604,8 +562,7 @@ Number::operator+=(Number const& y) xm /= 10; ++xe; } - g.doRoundUp( - xn, xm, xe, minMantissa, maxMantissa, "Number::addition overflow"); + g.doRoundUp(xn, xm, xe, minMantissa, maxMantissa, "Number::addition overflow"); } else { @@ -712,12 +669,7 @@ Number::operator*=(Number const& y) xm = static_cast(zm); xe = ze; g.doRoundUp( - zn, - xm, - xe, - minMantissa, - maxMantissa, - "Number::multiplication overflow : exponent is " + std::to_string(xe)); + zn, xm, xe, minMantissa, maxMantissa, "Number::multiplication overflow : exponent is " + std::to_string(xe)); negative_ = zn; mantissa_ = xm; exponent_ = xe; @@ -764,10 +716,8 @@ Number::operator/=(Number const& y) static_assert(smallRange.log == 15); static_assert(largeRange.log == 18); bool small = Number::getMantissaScale() == MantissaRange::small; - uint128_t const f = - small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL; - XRPL_ASSERT_PARTS( - f >= minMantissa * 10, "Number::operator/=", "factor expected size"); + uint128_t const f = small ? 100'000'000'000'000'000 : 10'000'000'000'000'000'000ULL; + XRPL_ASSERT_PARTS(f >= minMantissa * 10, "Number::operator/=", "factor expected size"); // unsigned denominator auto const dmu = static_cast(dm); @@ -818,8 +768,7 @@ Number::operator/=(Number const& y) negative_ = zn; mantissa_ = static_cast(zm); exponent_ = ze; - XRPL_ASSERT_PARTS( - isnormal(), "xrpl::Number::operator/=", "result is normalized"); + XRPL_ASSERT_PARTS(isnormal(), "xrpl::Number::operator/=", "result is normalized"); return *this; } @@ -884,11 +833,9 @@ to_string(Number const& amount) // Use scientific notation for exponents that are too small or too large auto const rangeLog = Number::mantissaLog(); - if (((exponent != 0) && - ((exponent < -(rangeLog + 10)) || (exponent > -(rangeLog - 10))))) + if (((exponent != 0) && ((exponent < -(rangeLog + 10)) || (exponent > -(rangeLog - 10))))) { - while (mantissa != 0 && mantissa % 10 == 0 && - exponent < Number::maxExponent) + while (mantissa != 0 && mantissa % 10 == 0 && exponent < Number::maxExponent) { mantissa /= 10; ++exponent; @@ -900,8 +847,7 @@ to_string(Number const& amount) return ret; } - XRPL_ASSERT( - exponent + 43 > 0, "xrpl::to_string(Number) : minimum exponent"); + XRPL_ASSERT(exponent + 43 > 0, "xrpl::to_string(Number) : minimum exponent"); ptrdiff_t const pad_prefix = rangeLog + 12; ptrdiff_t const pad_suffix = rangeLog + 8; @@ -927,8 +873,7 @@ to_string(Number const& amount) if (std::distance(pre_from, pre_to) > pad_prefix) pre_from += pad_prefix; - XRPL_ASSERT( - post_to >= post_from, "xrpl::to_string(Number) : first distance check"); + XRPL_ASSERT(post_to >= post_from, "xrpl::to_string(Number) : first distance check"); pre_from = std::find_if(pre_from, pre_to, [](char c) { return c != '0'; }); @@ -937,15 +882,11 @@ to_string(Number const& amount) if (std::distance(post_from, post_to) > pad_suffix) post_to -= pad_suffix; - XRPL_ASSERT( - post_to >= post_from, - "xrpl::to_string(Number) : second distance check"); + XRPL_ASSERT(post_to >= post_from, "xrpl::to_string(Number) : second distance check"); - post_to = std::find_if( - std::make_reverse_iterator(post_to), - std::make_reverse_iterator(post_from), - [](char c) { return c != '0'; }) - .base(); + post_to = std::find_if(std::make_reverse_iterator(post_to), std::make_reverse_iterator(post_from), [](char c) { + return c != '0'; + }).base(); std::string ret; @@ -1028,8 +969,7 @@ root(Number f, unsigned d) e += ex; f = f.shiftExponent(-e); // f /= 10^e; - XRPL_ASSERT_PARTS( - f.isnormal(), "xrpl::root(Number, unsigned)", "f is normalized"); + XRPL_ASSERT_PARTS(f.isnormal(), "xrpl::root(Number, unsigned)", "f is normalized"); bool neg = false; if (f < zero) { @@ -1062,10 +1002,7 @@ root(Number f, unsigned d) // return r * 10^(e/d) to reverse scaling auto const result = r.shiftExponent(e / di); - XRPL_ASSERT_PARTS( - result.isnormal(), - "xrpl::root(Number, unsigned)", - "result is normalized"); + XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::root(Number, unsigned)", "result is normalized"); return result; } @@ -1109,8 +1046,7 @@ root2(Number f) // return r * 10^(e/2) to reverse scaling auto const result = r.shiftExponent(e / 2); - XRPL_ASSERT_PARTS( - result.isnormal(), "xrpl::root2(Number)", "result is normalized"); + XRPL_ASSERT_PARTS(result.isnormal(), "xrpl::root2(Number)", "result is normalized"); return result; } diff --git a/src/libxrpl/basics/ResolverAsio.cpp b/src/libxrpl/basics/ResolverAsio.cpp index 8b9b2a9c4c..78346870a7 100644 --- a/src/libxrpl/basics/ResolverAsio.cpp +++ b/src/libxrpl/basics/ResolverAsio.cpp @@ -44,9 +44,7 @@ public: ~AsyncObject() { // Destroying the object with I/O pending? Not a clean exit! - XRPL_ASSERT( - m_pending.load() == 0, - "xrpl::AsyncObject::~AsyncObject : nothing pending"); + XRPL_ASSERT(m_pending.load() == 0, "xrpl::AsyncObject::~AsyncObject : nothing pending"); } /** RAII container that maintains the count of pending I/O. @@ -61,8 +59,7 @@ public: ++m_owner->m_pending; } - CompletionCounter(CompletionCounter const& other) - : m_owner(other.m_owner) + CompletionCounter(CompletionCounter const& other) : m_owner(other.m_owner) { ++m_owner->m_pending; } @@ -98,8 +95,7 @@ private: std::atomic m_pending; }; -class ResolverAsioImpl : public ResolverAsio, - public AsyncObject +class ResolverAsioImpl : public ResolverAsio, public AsyncObject { public: using HostAndPort = std::pair; @@ -124,21 +120,17 @@ public: HandlerType handler; template - Work(StringSequence const& names_, HandlerType const& handler_) - : handler(handler_) + Work(StringSequence const& names_, HandlerType const& handler_) : handler(handler_) { names.reserve(names_.size()); - std::reverse_copy( - names_.begin(), names_.end(), std::back_inserter(names)); + std::reverse_copy(names_.begin(), names_.end(), std::back_inserter(names)); } }; std::deque m_work; - ResolverAsioImpl( - boost::asio::io_context& io_context, - beast::Journal journal) + ResolverAsioImpl(boost::asio::io_context& io_context, beast::Journal journal) : m_journal(journal) , m_io_context(io_context) , m_strand(boost::asio::make_strand(io_context)) @@ -151,11 +143,8 @@ public: ~ResolverAsioImpl() override { - XRPL_ASSERT( - m_work.empty(), - "xrpl::ResolverAsioImpl::~ResolverAsioImpl : no pending work"); - XRPL_ASSERT( - m_stopped, "xrpl::ResolverAsioImpl::~ResolverAsioImpl : stopped"); + XRPL_ASSERT(m_work.empty(), "xrpl::ResolverAsioImpl::~ResolverAsioImpl : no pending work"); + XRPL_ASSERT(m_stopped, "xrpl::ResolverAsioImpl::~ResolverAsioImpl : stopped"); } //------------------------------------------------------------------------- @@ -177,11 +166,8 @@ public: void start() override { - XRPL_ASSERT( - m_stopped == true, "xrpl::ResolverAsioImpl::start : stopped"); - XRPL_ASSERT( - m_stop_called == false, - "xrpl::ResolverAsioImpl::start : not stopping"); + XRPL_ASSERT(m_stopped == true, "xrpl::ResolverAsioImpl::start : stopped"); + XRPL_ASSERT(m_stop_called == false, "xrpl::ResolverAsioImpl::start : not stopping"); if (m_stopped.exchange(false) == true) { @@ -201,11 +187,7 @@ public: boost::asio::dispatch( m_io_context, boost::asio::bind_executor( - m_strand, - std::bind( - &ResolverAsioImpl::do_stop, - this, - CompletionCounter(this)))); + m_strand, std::bind(&ResolverAsioImpl::do_stop, this, CompletionCounter(this)))); JLOG(m_journal.debug()) << "Queued a stop request"; } @@ -224,28 +206,17 @@ public: } void - resolve(std::vector const& names, HandlerType const& handler) - override + resolve(std::vector const& names, HandlerType const& handler) override { - XRPL_ASSERT( - m_stop_called == false, - "xrpl::ResolverAsioImpl::resolve : not stopping"); - XRPL_ASSERT( - !names.empty(), - "xrpl::ResolverAsioImpl::resolve : names non-empty"); + XRPL_ASSERT(m_stop_called == false, "xrpl::ResolverAsioImpl::resolve : not stopping"); + XRPL_ASSERT(!names.empty(), "xrpl::ResolverAsioImpl::resolve : names non-empty"); // TODO NIKB use rvalue references to construct and move // reducing cost. boost::asio::dispatch( m_io_context, boost::asio::bind_executor( - m_strand, - std::bind( - &ResolverAsioImpl::do_resolve, - this, - names, - handler, - CompletionCounter(this)))); + m_strand, std::bind(&ResolverAsioImpl::do_resolve, this, names, handler, CompletionCounter(this)))); } //------------------------------------------------------------------------- @@ -253,9 +224,7 @@ public: void do_stop(CompletionCounter) { - XRPL_ASSERT( - m_stop_called == true, - "xrpl::ResolverAsioImpl::do_stop : stopping"); + XRPL_ASSERT(m_stop_called == true, "xrpl::ResolverAsioImpl::do_stop : stopping"); if (m_stopped.exchange(true) == false) { @@ -286,8 +255,7 @@ public: { while (iter != results.end()) { - addresses.push_back( - beast::IPAddressConversion::from_asio(*iter)); + addresses.push_back(beast::IPAddressConversion::from_asio(*iter)); ++iter; } } @@ -296,12 +264,7 @@ public: boost::asio::post( m_io_context, - boost::asio::bind_executor( - m_strand, - std::bind( - &ResolverAsioImpl::do_work, - this, - CompletionCounter(this)))); + boost::asio::bind_executor(m_strand, std::bind(&ResolverAsioImpl::do_work, this, CompletionCounter(this)))); } HostAndPort @@ -312,8 +275,7 @@ public: if (auto const result = beast::IP::Endpoint::from_string_checked(str)) { - return make_pair( - result->address().to_string(), std::to_string(result->port())); + return make_pair(result->address().to_string(), std::to_string(result->port())); } // generic name/port parsing, which doesn't work for @@ -321,16 +283,12 @@ public: // a port separator // Attempt to find the first and last non-whitespace - auto const find_whitespace = std::bind( - &std::isspace, - std::placeholders::_1, - std::locale()); + auto const find_whitespace = + std::bind(&std::isspace, std::placeholders::_1, std::locale()); - auto host_first = - std::find_if_not(str.begin(), str.end(), find_whitespace); + auto host_first = std::find_if_not(str.begin(), str.end(), find_whitespace); - auto port_last = - std::find_if_not(str.rbegin(), str.rend(), find_whitespace).base(); + auto port_last = std::find_if_not(str.rbegin(), str.rend(), find_whitespace).base(); // This should only happen for all-whitespace strings if (host_first >= port_last) @@ -347,15 +305,11 @@ public: return false; }; - auto host_last = - std::find_if(host_first, port_last, find_port_separator); + auto host_last = std::find_if(host_first, port_last, find_port_separator); - auto port_first = - std::find_if_not(host_last, port_last, find_port_separator); + auto port_first = std::find_if_not(host_last, port_last, find_port_separator); - return make_pair( - std::string(host_first, host_last), - std::string(port_first, port_last)); + return make_pair(std::string(host_first, host_last), std::string(port_first, port_last)); } void @@ -385,11 +339,7 @@ public: boost::asio::post( m_io_context, boost::asio::bind_executor( - m_strand, - std::bind( - &ResolverAsioImpl::do_work, - this, - CompletionCounter(this)))); + m_strand, std::bind(&ResolverAsioImpl::do_work, this, CompletionCounter(this)))); return; } @@ -408,33 +358,23 @@ public: } void - do_resolve( - std::vector const& names, - HandlerType const& handler, - CompletionCounter) + do_resolve(std::vector const& names, HandlerType const& handler, CompletionCounter) { - XRPL_ASSERT( - !names.empty(), - "xrpl::ResolverAsioImpl::do_resolve : names non-empty"); + XRPL_ASSERT(!names.empty(), "xrpl::ResolverAsioImpl::do_resolve : names non-empty"); if (m_stop_called == false) { m_work.emplace_back(names, handler); - JLOG(m_journal.debug()) - << "Queued new job with " << names.size() << " tasks. " - << m_work.size() << " jobs outstanding."; + JLOG(m_journal.debug()) << "Queued new job with " << names.size() << " tasks. " << m_work.size() + << " jobs outstanding."; if (m_work.size() > 0) { boost::asio::post( m_io_context, boost::asio::bind_executor( - m_strand, - std::bind( - &ResolverAsioImpl::do_work, - this, - CompletionCounter(this)))); + m_strand, std::bind(&ResolverAsioImpl::do_work, this, CompletionCounter(this)))); } } } diff --git a/src/libxrpl/basics/base64.cpp b/src/libxrpl/basics/base64.cpp index 4a5cbacaef..3b692bc743 100644 --- a/src/libxrpl/basics/base64.cpp +++ b/src/libxrpl/basics/base64.cpp @@ -47,8 +47,7 @@ namespace base64 { inline char const* get_alphabet() { - static char constexpr tab[] = { - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}; + static char constexpr tab[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"}; return &tab[0]; } @@ -56,38 +55,22 @@ inline signed char const* get_inverse() { static signed char constexpr tab[] = { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 0-15 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 16-31 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 62, -1, -1, -1, 63, // 32-47 - 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, -1, -1, -1, -1, -1, -1, // 48-63 - -1, 0, 1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 - 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, -1, -1, -1, -1, -1, // 80-95 - -1, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, // 96-111 - 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, -1, -1, -1, -1, -1, // 112-127 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 128-143 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 144-159 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 160-175 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 176-191 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 192-207 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 208-223 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, // 224-239 - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 // 240-255 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47 + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63 + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95 + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111 + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255 }; return &tab[0]; } @@ -206,9 +189,7 @@ decode(void* dest, char const* src, std::size_t len) *out++ = c3[j]; } - return { - out - static_cast(dest), - in - reinterpret_cast(src)}; + return {out - static_cast(dest), in - reinterpret_cast(src)}; } } // namespace base64 diff --git a/src/libxrpl/basics/make_SSLContext.cpp b/src/libxrpl/basics/make_SSLContext.cpp index ef5996e051..57cbf7a24a 100644 --- a/src/libxrpl/basics/make_SSLContext.cpp +++ b/src/libxrpl/basics/make_SSLContext.cpp @@ -115,8 +115,7 @@ initAnonymous(boost::asio::ssl::context& context) // We need to up the reference count of here, since we are retaining a // copy of the key for (potential) reuse. if (RSA_up_ref(defaultRSA) != 1) - LogicError( - "EVP_PKEY_assign_RSA: incrementing reference count failed"); + LogicError("EVP_PKEY_assign_RSA: incrementing reference count failed"); if (!EVP_PKEY_assign_RSA(pkey, defaultRSA)) LogicError("EVP_PKEY_assign_RSA failed"); @@ -141,8 +140,7 @@ initAnonymous(boost::asio::ssl::context& context) auto const ts = std::time(nullptr) - (25 * 60 * 60); - int ret = std::strftime( - buf, sizeof(buf) - 1, "%y%m%d000000Z", std::gmtime(&ts)); + int ret = std::strftime(buf, sizeof(buf) - 1, "%y%m%d000000Z", std::gmtime(&ts)); buf[ret] = 0; @@ -176,32 +174,25 @@ initAnonymous(boost::asio::ssl::context& context) X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, x509, x509, nullptr, nullptr, 0); - if (auto ext = X509V3_EXT_conf_nid( - nullptr, &ctx, NID_basic_constraints, "critical,CA:FALSE")) + if (auto ext = X509V3_EXT_conf_nid(nullptr, &ctx, NID_basic_constraints, "critical,CA:FALSE")) { X509_add_ext(x509, ext, -1); X509_EXTENSION_free(ext); } - if (auto ext = X509V3_EXT_conf_nid( - nullptr, - &ctx, - NID_ext_key_usage, - "critical,serverAuth,clientAuth")) + if (auto ext = X509V3_EXT_conf_nid(nullptr, &ctx, NID_ext_key_usage, "critical,serverAuth,clientAuth")) { X509_add_ext(x509, ext, -1); X509_EXTENSION_free(ext); } - if (auto ext = X509V3_EXT_conf_nid( - nullptr, &ctx, NID_key_usage, "critical,digitalSignature")) + if (auto ext = X509V3_EXT_conf_nid(nullptr, &ctx, NID_key_usage, "critical,digitalSignature")) { X509_add_ext(x509, ext, -1); X509_EXTENSION_free(ext); } - if (auto ext = X509V3_EXT_conf_nid( - nullptr, &ctx, NID_subject_key_identifier, "hash")) + if (auto ext = X509V3_EXT_conf_nid(nullptr, &ctx, NID_subject_key_identifier, "hash")) { X509_add_ext(x509, ext, -1); X509_EXTENSION_free(ext); @@ -245,8 +236,7 @@ initAuthenticated( { boost::system::error_code ec; - context.use_certificate_file( - cert_file, boost::asio::ssl::context::pem, ec); + context.use_certificate_file(cert_file, boost::asio::ssl::context::pem, ec); if (ec) LogicError("Problem with SSL certificate file" + fmt_error(ec)); @@ -263,8 +253,7 @@ initAuthenticated( { LogicError( "Problem opening SSL chain file" + - fmt_error(boost::system::error_code( - errno, boost::system::generic_category()))); + fmt_error(boost::system::error_code(errno, boost::system::generic_category()))); } try @@ -297,10 +286,7 @@ initAuthenticated( catch (std::exception const& ex) { fclose(f); - LogicError( - std::string( - "Reading the SSL chain file generated an exception: ") + - ex.what()); + LogicError(std::string("Reading the SSL chain file generated an exception: ") + ex.what()); } } @@ -308,13 +294,11 @@ initAuthenticated( { boost::system::error_code ec; - context.use_private_key_file( - key_file, boost::asio::ssl::context::pem, ec); + context.use_private_key_file(key_file, boost::asio::ssl::context::pem, ec); if (ec) { - LogicError( - "Problem using the SSL private key file" + fmt_error(ec)); + LogicError("Problem using the SSL private key file" + fmt_error(ec)); } } @@ -327,24 +311,18 @@ initAuthenticated( std::shared_ptr get_context(std::string cipherList) { - auto c = std::make_shared( - boost::asio::ssl::context::sslv23); + auto c = std::make_shared(boost::asio::ssl::context::sslv23); c->set_options( - boost::asio::ssl::context::default_workarounds | - boost::asio::ssl::context::no_sslv2 | - boost::asio::ssl::context::no_sslv3 | - boost::asio::ssl::context::no_tlsv1 | - boost::asio::ssl::context::no_tlsv1_1 | - boost::asio::ssl::context::single_dh_use | + boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::no_sslv3 | boost::asio::ssl::context::no_tlsv1 | + boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::single_dh_use | boost::asio::ssl::context::no_compression); if (cipherList.empty()) cipherList = defaultCipherList; - if (auto result = - SSL_CTX_set_cipher_list(c->native_handle(), cipherList.c_str()); - result != 1) + if (auto result = SSL_CTX_set_cipher_list(c->native_handle(), cipherList.c_str()); result != 1) LogicError("SSL_CTX_set_cipher_list failed"); c->use_tmp_dh({std::addressof(detail::defaultDH), sizeof(defaultDH)}); diff --git a/src/libxrpl/beast/clock/basic_seconds_clock.cpp b/src/libxrpl/beast/clock/basic_seconds_clock.cpp index 3ab6bd72cd..27fb7b78c9 100644 --- a/src/libxrpl/beast/clock/basic_seconds_clock.cpp +++ b/src/libxrpl/beast/clock/basic_seconds_clock.cpp @@ -38,9 +38,7 @@ static_assert(std::atomic::is_always_lock_free); seconds_clock_thread::~seconds_clock_thread() { - XRPL_ASSERT( - thread_.joinable(), - "beast::seconds_clock_thread::~seconds_clock_thread : thread joinable"); + XRPL_ASSERT(thread_.joinable(), "beast::seconds_clock_thread::~seconds_clock_thread : thread joinable"); { std::lock_guard lock(mut_); stop_ = true; @@ -49,8 +47,7 @@ seconds_clock_thread::~seconds_clock_thread() thread_.join(); } -seconds_clock_thread::seconds_clock_thread() - : stop_{false}, tp_{Clock::now().time_since_epoch().count()} +seconds_clock_thread::seconds_clock_thread() : stop_{false}, tp_{Clock::now().time_since_epoch().count()} { thread_ = std::thread(&seconds_clock_thread::run, this); } diff --git a/src/libxrpl/beast/core/CurrentThreadName.cpp b/src/libxrpl/beast/core/CurrentThreadName.cpp index 34e8603afa..9d8d4e4bf2 100644 --- a/src/libxrpl/beast/core/CurrentThreadName.cpp +++ b/src/libxrpl/beast/core/CurrentThreadName.cpp @@ -42,8 +42,7 @@ setCurrentThreadNameImpl(std::string_view name) #pragma warning(disable : 6320 6322) __try { - RaiseException( - 0x406d1388, 0, sizeof(ni) / sizeof(ULONG_PTR), (ULONG_PTR*)&ni); + RaiseException(0x406d1388, 0, sizeof(ni) / sizeof(ULONG_PTR), (ULONG_PTR*)&ni); } __except (EXCEPTION_CONTINUE_EXECUTION) { @@ -81,20 +80,14 @@ setCurrentThreadNameImpl(std::string_view name) { // truncate and set the thread name. char boundedName[maxThreadNameLength + 1]; - std::snprintf( - boundedName, - sizeof(boundedName), - "%.*s", - static_cast(maxThreadNameLength), - name.data()); + std::snprintf(boundedName, sizeof(boundedName), "%.*s", static_cast(maxThreadNameLength), name.data()); pthread_setname_np(pthread_self(), boundedName); #ifdef TRUNCATED_THREAD_NAME_LOGS if (name.size() > maxThreadNameLength) { - std::cerr << "WARNING: Thread name \"" << name << "\" (length " - << name.size() << ") exceeds maximum of " + std::cerr << "WARNING: Thread name \"" << name << "\" (length " << name.size() << ") exceeds maximum of " << maxThreadNameLength << " characters on Linux.\n"; XRPL_ASSERT( diff --git a/src/libxrpl/beast/core/SemanticVersion.cpp b/src/libxrpl/beast/core/SemanticVersion.cpp index 2a42a3b7ab..d22211cc7d 100644 --- a/src/libxrpl/beast/core/SemanticVersion.cpp +++ b/src/libxrpl/beast/core/SemanticVersion.cpp @@ -59,9 +59,7 @@ chopUInt(int& value, int limit, std::string& input) return false; auto left_iter = std::find_if_not( - input.begin(), input.end(), [](std::string::value_type c) { - return std::isdigit(c, std::locale::classic()); - }); + input.begin(), input.end(), [](std::string::value_type c) { return std::isdigit(c, std::locale::classic()); }); std::string item(input.begin(), left_iter); @@ -90,10 +88,7 @@ chopUInt(int& value, int limit, std::string& input) } bool -extract_identifier( - std::string& value, - bool allowLeadingZeroes, - std::string& input) +extract_identifier(std::string& value, bool allowLeadingZeroes, std::string& input) { // Must not be empty if (input.empty()) @@ -103,8 +98,7 @@ extract_identifier( if (!allowLeadingZeroes && input[0] == '0') return false; - auto last = input.find_first_not_of( - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-"); + auto last = input.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-"); // Must not be empty if (last == 0) @@ -116,10 +110,7 @@ extract_identifier( } bool -extract_identifiers( - SemanticVersion::identifier_list& identifiers, - bool allowLeadingZeroes, - std::string& input) +extract_identifiers(SemanticVersion::identifier_list& identifiers, bool allowLeadingZeroes, std::string& input) { if (input.empty()) return false; @@ -138,8 +129,7 @@ extract_identifiers( //------------------------------------------------------------------------------ -SemanticVersion::SemanticVersion() - : majorVersion(0), minorVersion(0), patchVersion(0) +SemanticVersion::SemanticVersion() : majorVersion(0), minorVersion(0), patchVersion(0) { } @@ -154,17 +144,11 @@ SemanticVersion::parse(std::string const& input) { // May not have leading or trailing whitespace auto left_iter = std::find_if_not( - input.begin(), input.end(), [](std::string::value_type c) { - return std::isspace(c, std::locale::classic()); - }); + input.begin(), input.end(), [](std::string::value_type c) { return std::isspace(c, std::locale::classic()); }); - auto right_iter = std::find_if_not( - input.rbegin(), - input.rend(), - [](std::string::value_type c) { - return std::isspace(c, std::locale::classic()); - }) - .base(); + auto right_iter = std::find_if_not(input.rbegin(), input.rend(), [](std::string::value_type c) { + return std::isspace(c, std::locale::classic()); + }).base(); // Must not be empty! if (left_iter >= right_iter) @@ -222,8 +206,7 @@ SemanticVersion::print() const { std::string s; - s = std::to_string(majorVersion) + "." + std::to_string(minorVersion) + - "." + std::to_string(patchVersion); + s = std::to_string(majorVersion) + "." + std::to_string(minorVersion) + "." + std::to_string(patchVersion); if (!preReleaseIdentifiers.empty()) { @@ -267,10 +250,7 @@ compare(SemanticVersion const& lhs, SemanticVersion const& rhs) return -1; // Compare pre-release identifiers - for (int i = 0; i < - std::max(lhs.preReleaseIdentifiers.size(), - rhs.preReleaseIdentifiers.size()); - ++i) + for (int i = 0; i < std::max(lhs.preReleaseIdentifiers.size(), rhs.preReleaseIdentifiers.size()); ++i) { // A larger list of identifiers has a higher precedence if (i >= rhs.preReleaseIdentifiers.size()) @@ -289,8 +269,7 @@ compare(SemanticVersion const& lhs, SemanticVersion const& rhs) if (isNumeric(left)) { - XRPL_ASSERT( - isNumeric(right), "beast::compare : both inputs numeric"); + XRPL_ASSERT(isNumeric(right), "beast::compare : both inputs numeric"); int const iLeft(lexicalCastThrow(left)); int const iRight(lexicalCastThrow(right)); @@ -302,9 +281,7 @@ compare(SemanticVersion const& lhs, SemanticVersion const& rhs) } else { - XRPL_ASSERT( - !isNumeric(right), - "beast::compare : both inputs non-numeric"); + XRPL_ASSERT(!isNumeric(right), "beast::compare : both inputs non-numeric"); int result = left.compare(right); diff --git a/src/libxrpl/beast/insight/Groups.cpp b/src/libxrpl/beast/insight/Groups.cpp index 78d43067c2..1ff8dbc4c1 100644 --- a/src/libxrpl/beast/insight/Groups.cpp +++ b/src/libxrpl/beast/insight/Groups.cpp @@ -25,8 +25,7 @@ public: std::string const m_name; Collector::ptr m_collector; - GroupImp(std::string const& name_, Collector::ptr const& collector) - : m_name(name_), m_collector(collector) + GroupImp(std::string const& name_, Collector::ptr const& collector) : m_name(name_), m_collector(collector) { } @@ -84,8 +83,7 @@ private: class GroupsImp : public Groups { public: - using Items = - std::unordered_map, uhash<>>; + using Items = std::unordered_map, uhash<>>; Collector::ptr m_collector; Items m_items; @@ -99,8 +97,7 @@ public: Group::ptr const& get(std::string const& name) override { - std::pair result( - m_items.emplace(name, Group::ptr())); + std::pair result(m_items.emplace(name, Group::ptr())); Group::ptr& group(result.first->second); if (result.second) group = std::make_shared(name, m_collector); diff --git a/src/libxrpl/beast/insight/StatsDCollector.cpp b/src/libxrpl/beast/insight/StatsDCollector.cpp index 33bef8ac16..e005a0b177 100644 --- a/src/libxrpl/beast/insight/StatsDCollector.cpp +++ b/src/libxrpl/beast/insight/StatsDCollector.cpp @@ -64,9 +64,7 @@ public: class StatsDHookImpl : public HookImpl, public StatsDMetricBase { public: - StatsDHookImpl( - HandlerType const& handler, - std::shared_ptr const& impl); + StatsDHookImpl(HandlerType const& handler, std::shared_ptr const& impl); ~StatsDHookImpl() override; @@ -86,9 +84,7 @@ private: class StatsDCounterImpl : public CounterImpl, public StatsDMetricBase { public: - StatsDCounterImpl( - std::string const& name, - std::shared_ptr const& impl); + StatsDCounterImpl(std::string const& name, std::shared_ptr const& impl); ~StatsDCounterImpl() override; @@ -117,9 +113,7 @@ private: class StatsDEventImpl : public EventImpl { public: - StatsDEventImpl( - std::string const& name, - std::shared_ptr const& impl); + StatsDEventImpl(std::string const& name, std::shared_ptr const& impl); ~StatsDEventImpl() = default; @@ -144,9 +138,7 @@ private: class StatsDGaugeImpl : public GaugeImpl, public StatsDMetricBase { public: - StatsDGaugeImpl( - std::string const& name, - std::shared_ptr const& impl); + StatsDGaugeImpl(std::string const& name, std::shared_ptr const& impl); ~StatsDGaugeImpl() override; @@ -180,9 +172,7 @@ private: class StatsDMeterImpl : public MeterImpl, public StatsDMetricBase { public: - explicit StatsDMeterImpl( - std::string const& name, - std::shared_ptr const& impl); + explicit StatsDMeterImpl(std::string const& name, std::shared_ptr const& impl); ~StatsDMeterImpl() override; @@ -208,9 +198,7 @@ private: //------------------------------------------------------------------------------ -class StatsDCollectorImp - : public StatsDCollector, - public std::enable_shared_from_this +class StatsDCollectorImp : public StatsDCollector, public std::enable_shared_from_this { private: enum { @@ -222,9 +210,7 @@ private: IP::Endpoint m_address; std::string m_prefix; boost::asio::io_context m_io_context; - std::optional> - m_work; + std::optional> m_work; boost::asio::strand m_strand; boost::asio::basic_waitable_timer m_timer; boost::asio::ip::udp::socket m_socket; @@ -242,10 +228,7 @@ private: } public: - StatsDCollectorImp( - IP::Endpoint const& address, - std::string const& prefix, - Journal journal) + StatsDCollectorImp(IP::Endpoint const& address, std::string const& prefix, Journal journal) : m_journal(journal) , m_address(address) , m_prefix(prefix) @@ -275,36 +258,31 @@ public: Hook make_hook(HookImpl::HandlerType const& handler) override { - return Hook(std::make_shared( - handler, shared_from_this())); + return Hook(std::make_shared(handler, shared_from_this())); } Counter make_counter(std::string const& name) override { - return Counter(std::make_shared( - name, shared_from_this())); + return Counter(std::make_shared(name, shared_from_this())); } Event make_event(std::string const& name) override { - return Event(std::make_shared( - name, shared_from_this())); + return Event(std::make_shared(name, shared_from_this())); } Gauge make_gauge(std::string const& name) override { - return Gauge(std::make_shared( - name, shared_from_this())); + return Gauge(std::make_shared(name, shared_from_this())); } Meter make_meter(std::string const& name) override { - return Meter(std::make_shared( - name, shared_from_this())); + return Meter(std::make_shared(name, shared_from_this())); } //-------------------------------------------------------------------------- @@ -349,20 +327,13 @@ public: boost::asio::dispatch( m_io_context, boost::asio::bind_executor( - m_strand, - std::bind( - &StatsDCollectorImp::do_post_buffer, - this, - std::move(buffer)))); + m_strand, std::bind(&StatsDCollectorImp::do_post_buffer, this, std::move(buffer)))); } // The keepAlive parameter makes sure the buffers sent to // boost::asio::async_send do not go away until the call is finished void - on_send( - std::shared_ptr> /*keepAlive*/, - boost::system::error_code ec, - std::size_t) + on_send(std::shared_ptr> /*keepAlive*/, boost::system::error_code ec, std::size_t) { if (ec == boost::asio::error::operation_aborted) return; @@ -382,8 +353,7 @@ public: #if BEAST_STATSDCOLLECTOR_TRACING_ENABLED for (auto const& buffer : buffers) { - std::string const s( - buffer.data(), boost::asio::buffer_size(buffer)); + std::string const s(buffer.data(), boost::asio::buffer_size(buffer)); std::cerr << s; } std::cerr << '\n'; @@ -404,8 +374,7 @@ public: buffers.reserve(m_data.size()); std::size_t size(0); - auto keepAlive = - std::make_shared>(std::move(m_data)); + auto keepAlive = std::make_shared>(std::move(m_data)); m_data.clear(); for (auto const& s : *keepAlive) @@ -421,11 +390,7 @@ public: m_socket.async_send( buffers, std::bind( - &StatsDCollectorImp::on_send, - this, - keepAlive, - std::placeholders::_1, - std::placeholders::_2)); + &StatsDCollectorImp::on_send, this, keepAlive, std::placeholders::_1, std::placeholders::_2)); buffers.clear(); size = 0; } @@ -439,12 +404,7 @@ public: log(buffers); m_socket.async_send( buffers, - std::bind( - &StatsDCollectorImp::on_send, - this, - keepAlive, - std::placeholders::_1, - std::placeholders::_2)); + std::bind(&StatsDCollectorImp::on_send, this, keepAlive, std::placeholders::_1, std::placeholders::_2)); } } @@ -453,8 +413,7 @@ public: { using namespace std::chrono_literals; m_timer.expires_after(1s); - m_timer.async_wait(std::bind( - &StatsDCollectorImp::on_timer, this, std::placeholders::_1)); + m_timer.async_wait(std::bind(&StatsDCollectorImp::on_timer, this, std::placeholders::_1)); } void @@ -506,9 +465,7 @@ public: //------------------------------------------------------------------------------ -StatsDHookImpl::StatsDHookImpl( - HandlerType const& handler, - std::shared_ptr const& impl) +StatsDHookImpl::StatsDHookImpl(HandlerType const& handler, std::shared_ptr const& impl) : m_impl(impl), m_handler(handler) { m_impl->add(*this); @@ -527,9 +484,7 @@ StatsDHookImpl::do_process() //------------------------------------------------------------------------------ -StatsDCounterImpl::StatsDCounterImpl( - std::string const& name, - std::shared_ptr const& impl) +StatsDCounterImpl::StatsDCounterImpl(std::string const& name, std::shared_ptr const& impl) : m_impl(impl), m_name(name), m_value(0), m_dirty(false) { m_impl->add(*this); @@ -546,9 +501,7 @@ StatsDCounterImpl::increment(CounterImpl::value_type amount) boost::asio::dispatch( m_impl->get_io_context(), std::bind( - &StatsDCounterImpl::do_increment, - std::static_pointer_cast(shared_from_this()), - amount)); + &StatsDCounterImpl::do_increment, std::static_pointer_cast(shared_from_this()), amount)); } void @@ -580,9 +533,7 @@ StatsDCounterImpl::do_process() //------------------------------------------------------------------------------ -StatsDEventImpl::StatsDEventImpl( - std::string const& name, - std::shared_ptr const& impl) +StatsDEventImpl::StatsDEventImpl(std::string const& name, std::shared_ptr const& impl) : m_impl(impl), m_name(name) { } @@ -592,10 +543,7 @@ StatsDEventImpl::notify(EventImpl::value_type const& value) { boost::asio::dispatch( m_impl->get_io_context(), - std::bind( - &StatsDEventImpl::do_notify, - std::static_pointer_cast(shared_from_this()), - value)); + std::bind(&StatsDEventImpl::do_notify, std::static_pointer_cast(shared_from_this()), value)); } void @@ -609,9 +557,7 @@ StatsDEventImpl::do_notify(EventImpl::value_type const& value) //------------------------------------------------------------------------------ -StatsDGaugeImpl::StatsDGaugeImpl( - std::string const& name, - std::shared_ptr const& impl) +StatsDGaugeImpl::StatsDGaugeImpl(std::string const& name, std::shared_ptr const& impl) : m_impl(impl), m_name(name), m_last_value(0), m_value(0), m_dirty(false) { m_impl->add(*this); @@ -627,10 +573,7 @@ StatsDGaugeImpl::set(GaugeImpl::value_type value) { boost::asio::dispatch( m_impl->get_io_context(), - std::bind( - &StatsDGaugeImpl::do_set, - std::static_pointer_cast(shared_from_this()), - value)); + std::bind(&StatsDGaugeImpl::do_set, std::static_pointer_cast(shared_from_this()), value)); } void @@ -639,9 +582,7 @@ StatsDGaugeImpl::increment(GaugeImpl::difference_type amount) boost::asio::dispatch( m_impl->get_io_context(), std::bind( - &StatsDGaugeImpl::do_increment, - std::static_pointer_cast(shared_from_this()), - amount)); + &StatsDGaugeImpl::do_increment, std::static_pointer_cast(shared_from_this()), amount)); } void @@ -676,17 +617,14 @@ StatsDGaugeImpl::do_increment(GaugeImpl::difference_type amount) if (amount > 0) { - GaugeImpl::value_type const d( - static_cast(amount)); - value += - (d >= std::numeric_limits::max() - m_value) + GaugeImpl::value_type const d(static_cast(amount)); + value += (d >= std::numeric_limits::max() - m_value) ? std::numeric_limits::max() - m_value : d; } else if (amount < 0) { - GaugeImpl::value_type const d( - static_cast(-amount)); + GaugeImpl::value_type const d(static_cast(-amount)); value = (d >= value) ? 0 : value - d; } @@ -701,9 +639,7 @@ StatsDGaugeImpl::do_process() //------------------------------------------------------------------------------ -StatsDMeterImpl::StatsDMeterImpl( - std::string const& name, - std::shared_ptr const& impl) +StatsDMeterImpl::StatsDMeterImpl(std::string const& name, std::shared_ptr const& impl) : m_impl(impl), m_name(name), m_value(0), m_dirty(false) { m_impl->add(*this); @@ -720,9 +656,7 @@ StatsDMeterImpl::increment(MeterImpl::value_type amount) boost::asio::dispatch( m_impl->get_io_context(), std::bind( - &StatsDMeterImpl::do_increment, - std::static_pointer_cast(shared_from_this()), - amount)); + &StatsDMeterImpl::do_increment, std::static_pointer_cast(shared_from_this()), amount)); } void @@ -757,13 +691,9 @@ StatsDMeterImpl::do_process() //------------------------------------------------------------------------------ std::shared_ptr -StatsDCollector::New( - IP::Endpoint const& address, - std::string const& prefix, - Journal journal) +StatsDCollector::New(IP::Endpoint const& address, std::string const& prefix, Journal journal) { - return std::make_shared( - address, prefix, journal); + return std::make_shared(address, prefix, journal); } } // namespace insight diff --git a/src/libxrpl/beast/net/IPAddressV4.cpp b/src/libxrpl/beast/net/IPAddressV4.cpp index fcb782133e..021b7588d9 100644 --- a/src/libxrpl/beast/net/IPAddressV4.cpp +++ b/src/libxrpl/beast/net/IPAddressV4.cpp @@ -6,12 +6,9 @@ namespace IP { bool is_private(AddressV4 const& addr) { - return ((addr.to_uint() & 0xff000000) == - 0x0a000000) || // Prefix /8, 10. #.#.# - ((addr.to_uint() & 0xfff00000) == - 0xac100000) || // Prefix /12 172. 16.#.# - 172.31.#.# - ((addr.to_uint() & 0xffff0000) == - 0xc0a80000) || // Prefix /16 192.168.#.# + return ((addr.to_uint() & 0xff000000) == 0x0a000000) || // Prefix /8, 10. #.#.# + ((addr.to_uint() & 0xfff00000) == 0xac100000) || // Prefix /12 172. 16.#.# - 172.31.#.# + ((addr.to_uint() & 0xffff0000) == 0xc0a80000) || // Prefix /16 192.168.#.# addr.is_loopback(); } diff --git a/src/libxrpl/beast/net/IPAddressV6.cpp b/src/libxrpl/beast/net/IPAddressV6.cpp index 9ac51875eb..b1db5ae09c 100644 --- a/src/libxrpl/beast/net/IPAddressV6.cpp +++ b/src/libxrpl/beast/net/IPAddressV6.cpp @@ -11,9 +11,7 @@ is_private(AddressV6 const& addr) { return ( (addr.to_bytes()[0] & 0xfd) || // TODO fc00::/8 too ? - (addr.is_v4_mapped() && - is_private(boost::asio::ip::make_address_v4( - boost::asio::ip::v4_mapped, addr)))); + (addr.is_v4_mapped() && is_private(boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped, addr)))); } bool diff --git a/src/libxrpl/beast/net/IPEndpoint.cpp b/src/libxrpl/beast/net/IPEndpoint.cpp index 701181ef88..a79b0d750c 100644 --- a/src/libxrpl/beast/net/IPEndpoint.cpp +++ b/src/libxrpl/beast/net/IPEndpoint.cpp @@ -50,9 +50,7 @@ std::string Endpoint::to_string() const { std::string s; - s.reserve( - (address().is_v6() ? INET6_ADDRSTRLEN - 1 : 15) + - (port() == 0 ? 0 : 6 + (address().is_v6() ? 2 : 0))); + s.reserve((address().is_v6() ? INET6_ADDRSTRLEN - 1 : 15) + (port() == 0 ? 0 : 6 + (address().is_v6() ? 2 : 0))); if (port() != 0 && address().is_v6()) s += '['; @@ -110,14 +108,12 @@ operator>>(std::istream& is, Endpoint& endpoint) if (isspace(static_cast(i)) || (readTo && i == readTo)) break; - if ((i == '.') || (i >= '0' && i <= ':') || (i >= 'a' && i <= 'f') || - (i >= 'A' && i <= 'F')) + if ((i == '.') || (i >= '0' && i <= ':') || (i >= 'a' && i <= 'f') || (i >= 'A' && i <= 'F')) { addrStr += i; // don't exceed a reasonable length... - if (addrStr.size() == INET6_ADDRSTRLEN || - (readTo && readTo == ':' && addrStr.size() > 15)) + if (addrStr.size() == INET6_ADDRSTRLEN || (readTo && readTo == ':' && addrStr.size() > 15)) { is.setstate(std::ios_base::failbit); return is; diff --git a/src/libxrpl/beast/utility/beast_Journal.cpp b/src/libxrpl/beast/utility/beast_Journal.cpp index 24e17b18c6..f9ee0cdb73 100644 --- a/src/libxrpl/beast/utility/beast_Journal.cpp +++ b/src/libxrpl/beast/utility/beast_Journal.cpp @@ -68,8 +68,7 @@ Journal::getNullSink() //------------------------------------------------------------------------------ -Journal::Sink::Sink(Severity thresh, bool console) - : thresh_(thresh), m_console(console) +Journal::Sink::Sink(Severity thresh, bool console) : thresh_(thresh), m_console(console) { } @@ -107,16 +106,13 @@ Journal::Sink::threshold(Severity thresh) //------------------------------------------------------------------------------ -Journal::ScopedStream::ScopedStream(Sink& sink, Severity level) - : m_sink(sink), m_level(level) +Journal::ScopedStream::ScopedStream(Sink& sink, Severity level) : m_sink(sink), m_level(level) { // Modifiers applied from all ctors m_ostream << std::boolalpha << std::showbase; } -Journal::ScopedStream::ScopedStream( - Stream const& stream, - std::ostream& manip(std::ostream&)) +Journal::ScopedStream::ScopedStream(Stream const& stream, std::ostream& manip(std::ostream&)) : ScopedStream(stream.sink(), stream.level()) { m_ostream << manip; diff --git a/src/libxrpl/beast/utility/beast_PropertyStream.cpp b/src/libxrpl/beast/utility/beast_PropertyStream.cpp index 991dbaef51..daf6bc4526 100644 --- a/src/libxrpl/beast/utility/beast_PropertyStream.cpp +++ b/src/libxrpl/beast/utility/beast_PropertyStream.cpp @@ -43,13 +43,11 @@ PropertyStream::Item::operator*() const // //------------------------------------------------------------------------------ -PropertyStream::Proxy::Proxy(Map const& map, std::string const& key) - : m_map(&map), m_key(key) +PropertyStream::Proxy::Proxy(Map const& map, std::string const& key) : m_map(&map), m_key(key) { } -PropertyStream::Proxy::Proxy(Proxy const& other) - : m_map(other.m_map), m_key(other.m_key) +PropertyStream::Proxy::Proxy(Proxy const& other) : m_map(other.m_map), m_key(other.m_key) { } @@ -81,14 +79,12 @@ PropertyStream::Map::Map(Set& parent) : m_stream(parent.stream()) m_stream.map_begin(); } -PropertyStream::Map::Map(std::string const& key, Map& map) - : m_stream(map.stream()) +PropertyStream::Map::Map(std::string const& key, Map& map) : m_stream(map.stream()) { m_stream.map_begin(key); } -PropertyStream::Map::Map(std::string const& key, PropertyStream& stream) - : m_stream(stream) +PropertyStream::Map::Map(std::string const& key, PropertyStream& stream) : m_stream(stream) { m_stream.map_begin(key); } @@ -122,14 +118,12 @@ PropertyStream::Map::operator[](std::string const& key) // //------------------------------------------------------------------------------ -PropertyStream::Set::Set(std::string const& key, Map& map) - : m_stream(map.stream()) +PropertyStream::Set::Set(std::string const& key, Map& map) : m_stream(map.stream()) { m_stream.array_begin(key); } -PropertyStream::Set::Set(std::string const& key, PropertyStream& stream) - : m_stream(stream) +PropertyStream::Set::Set(std::string const& key, PropertyStream& stream) : m_stream(stream) { m_stream.array_begin(key); } @@ -157,8 +151,7 @@ PropertyStream::Set::stream() const // //------------------------------------------------------------------------------ -PropertyStream::Source::Source(std::string const& name) - : m_name(name), item_(this), parent_(nullptr) +PropertyStream::Source::Source(std::string const& name) : m_name(name), item_(this), parent_(nullptr) { } @@ -183,9 +176,7 @@ PropertyStream::Source::add(Source& source) std::lock_guard lk1(lock_, std::adopt_lock); std::lock_guard lk2(source.lock_, std::adopt_lock); - XRPL_ASSERT( - source.parent_ == nullptr, - "beast::PropertyStream::Source::add : null source parent"); + XRPL_ASSERT(source.parent_ == nullptr, "beast::PropertyStream::Source::add : null source parent"); children_.push_back(source.item_); source.parent_ = this; } @@ -197,9 +188,7 @@ PropertyStream::Source::remove(Source& child) std::lock_guard lk1(lock_, std::adopt_lock); std::lock_guard lk2(child.lock_, std::adopt_lock); - XRPL_ASSERT( - child.parent_ == this, - "beast::PropertyStream::Source::remove : child parent match"); + XRPL_ASSERT(child.parent_ == this, "beast::PropertyStream::Source::remove : child parent match"); children_.erase(children_.iterator_to(child.item_)); child.parent_ = nullptr; } diff --git a/src/libxrpl/core/detail/Job.cpp b/src/libxrpl/core/detail/Job.cpp index 358441010b..4e957b9619 100644 --- a/src/libxrpl/core/detail/Job.cpp +++ b/src/libxrpl/core/detail/Job.cpp @@ -11,17 +11,8 @@ Job::Job(JobType type, std::uint64_t index) : mType(type), mJobIndex(index) { } -Job::Job( - JobType type, - std::string const& name, - std::uint64_t index, - LoadMonitor& lm, - std::function const& job) - : mType(type) - , mJobIndex(index) - , mJob(job) - , mName(name) - , m_queue_time(clock_type::now()) +Job::Job(JobType type, std::string const& name, std::uint64_t index, LoadMonitor& lm, std::function const& job) + : mType(type), mJobIndex(index), mJob(job), mName(name), m_queue_time(clock_type::now()) { m_loadEvent = std::make_shared(std::ref(lm), name, false); } diff --git a/src/libxrpl/core/detail/JobQueue.cpp b/src/libxrpl/core/detail/JobQueue.cpp index 7393278fef..37e5402946 100644 --- a/src/libxrpl/core/detail/JobQueue.cpp +++ b/src/libxrpl/core/detail/JobQueue.cpp @@ -37,8 +37,7 @@ JobQueue::JobQueue( std::piecewise_construct, std::forward_as_tuple(jt.type()), std::forward_as_tuple(jt, m_collector, logs))); - XRPL_ASSERT( - result.second == true, "xrpl::JobQueue::JobQueue : jobs added"); + XRPL_ASSERT(result.second == true, "xrpl::JobQueue::JobQueue : jobs added"); (void)result.second; } } @@ -58,47 +57,33 @@ JobQueue::collect() } bool -JobQueue::addRefCountedJob( - JobType type, - std::string const& name, - JobFunction const& func) +JobQueue::addRefCountedJob(JobType type, std::string const& name, JobFunction const& func) { - XRPL_ASSERT( - type != jtINVALID, - "xrpl::JobQueue::addRefCountedJob : valid input job type"); + XRPL_ASSERT(type != jtINVALID, "xrpl::JobQueue::addRefCountedJob : valid input job type"); auto iter(m_jobData.find(type)); - XRPL_ASSERT( - iter != m_jobData.end(), - "xrpl::JobQueue::addRefCountedJob : job type found in jobs"); + XRPL_ASSERT(iter != m_jobData.end(), "xrpl::JobQueue::addRefCountedJob : job type found in jobs"); if (iter == m_jobData.end()) return false; - JLOG(m_journal.debug()) - << __func__ << " : Adding job : " << name << " : " << type; + JLOG(m_journal.debug()) << __func__ << " : Adding job : " << name << " : " << type; JobTypeData& data(iter->second); // FIXME: Workaround incorrect client shutdown ordering // do not add jobs to a queue with no threads XRPL_ASSERT( - (type >= jtCLIENT && type <= jtCLIENT_WEBSOCKET) || - m_workers.getNumberOfThreads() > 0, + (type >= jtCLIENT && type <= jtCLIENT_WEBSOCKET) || m_workers.getNumberOfThreads() > 0, "xrpl::JobQueue::addRefCountedJob : threads available or job " "requires no threads"); { std::lock_guard lock(m_mutex); - auto result = - m_jobSet.emplace(type, name, ++m_lastJob, data.load(), func); + auto result = m_jobSet.emplace(type, name, ++m_lastJob, data.load(), func); auto const& job = *result.first; JobType const type(job.getType()); - XRPL_ASSERT( - type != jtINVALID, - "xrpl::JobQueue::addRefCountedJob : has valid job type"); - XRPL_ASSERT( - m_jobSet.find(job) != m_jobSet.end(), - "xrpl::JobQueue::addRefCountedJob : job found"); + XRPL_ASSERT(type != jtINVALID, "xrpl::JobQueue::addRefCountedJob : has valid job type"); + XRPL_ASSERT(m_jobSet.find(job) != m_jobSet.end(), "xrpl::JobQueue::addRefCountedJob : job found"); perfLog_.jobQueue(type); JobTypeData& data(getJobTypeData(type)); @@ -158,9 +143,7 @@ std::unique_ptr JobQueue::makeLoadEvent(JobType t, std::string const& name) { JobDataMap::iterator iter(m_jobData.find(t)); - XRPL_ASSERT( - iter != m_jobData.end(), - "xrpl::JobQueue::makeLoadEvent : valid job type input"); + XRPL_ASSERT(iter != m_jobData.end(), "xrpl::JobQueue::makeLoadEvent : valid job type input"); if (iter == m_jobData.end()) return {}; @@ -175,18 +158,14 @@ JobQueue::addLoadEvents(JobType t, int count, std::chrono::milliseconds elapsed) LogicError("JobQueue::addLoadEvents() called after JobQueue stopped"); JobDataMap::iterator iter(m_jobData.find(t)); - XRPL_ASSERT( - iter != m_jobData.end(), - "xrpl::JobQueue::addLoadEvents : valid job type input"); + XRPL_ASSERT(iter != m_jobData.end(), "xrpl::JobQueue::addLoadEvents : valid job type input"); iter->second.load().addSamples(count, elapsed); } bool JobQueue::isOverloaded() { - return std::any_of(m_jobData.begin(), m_jobData.end(), [](auto& entry) { - return entry.second.load().isOver(); - }); + return std::any_of(m_jobData.begin(), m_jobData.end(), [](auto& entry) { return entry.second.load().isOver(); }); } Json::Value @@ -203,8 +182,7 @@ JobQueue::getJson(int c) for (auto& x : m_jobData) { - XRPL_ASSERT( - x.first != jtINVALID, "xrpl::JobQueue::getJson : valid job type"); + XRPL_ASSERT(x.first != jtINVALID, "xrpl::JobQueue::getJson : valid job type"); if (x.first == jtGENERIC) continue; @@ -216,8 +194,7 @@ JobQueue::getJson(int c) int waiting(data.waiting); int running(data.running); - if ((stats.count != 0) || (waiting != 0) || - (stats.latencyPeak != 0ms) || (running != 0)) + if ((stats.count != 0) || (waiting != 0) || (stats.latencyPeak != 0ms) || (running != 0)) { Json::Value& pri = priorities.append(Json::objectValue); @@ -259,9 +236,7 @@ JobTypeData& JobQueue::getJobTypeData(JobType type) { JobDataMap::iterator c(m_jobData.find(type)); - XRPL_ASSERT( - c != m_jobData.end(), - "xrpl::JobQueue::getJobTypeData : valid job type input"); + XRPL_ASSERT(c != m_jobData.end(), "xrpl::JobQueue::getJobTypeData : valid job type input"); // NIKB: This is ugly and I hate it. We must remove jtINVALID completely // and use something sane. @@ -284,15 +259,10 @@ JobQueue::stop() // `Job::doJob` and the return of `JobQueue::processTask`. That is why // we must wait on the condition variable to make these assertions. std::unique_lock lock(m_mutex); - cv_.wait( - lock, [this] { return m_processCount == 0 && m_jobSet.empty(); }); - XRPL_ASSERT( - m_processCount == 0, - "xrpl::JobQueue::stop : all processes completed"); - XRPL_ASSERT( - m_jobSet.empty(), "xrpl::JobQueue::stop : all jobs completed"); - XRPL_ASSERT( - nSuspend_ == 0, "xrpl::JobQueue::stop : no coros suspended"); + cv_.wait(lock, [this] { return m_processCount == 0 && m_jobSet.empty(); }); + XRPL_ASSERT(m_processCount == 0, "xrpl::JobQueue::stop : all processes completed"); + XRPL_ASSERT(m_jobSet.empty(), "xrpl::JobQueue::stop : all jobs completed"); + XRPL_ASSERT(nSuspend_ == 0, "xrpl::JobQueue::stop : no coros suspended"); stopped_ = true; } } @@ -306,35 +276,28 @@ JobQueue::isStopped() const void JobQueue::getNextJob(Job& job) { - XRPL_ASSERT( - !m_jobSet.empty(), "xrpl::JobQueue::getNextJob : non-empty jobs"); + XRPL_ASSERT(!m_jobSet.empty(), "xrpl::JobQueue::getNextJob : non-empty jobs"); std::set::const_iterator iter; for (iter = m_jobSet.begin(); iter != m_jobSet.end(); ++iter) { JobType const type = iter->getType(); - XRPL_ASSERT( - type != jtINVALID, "xrpl::JobQueue::getNextJob : valid job type"); + XRPL_ASSERT(type != jtINVALID, "xrpl::JobQueue::getNextJob : valid job type"); JobTypeData& data(getJobTypeData(type)); - XRPL_ASSERT( - data.running <= getJobLimit(type), - "xrpl::JobQueue::getNextJob : maximum jobs running"); + XRPL_ASSERT(data.running <= getJobLimit(type), "xrpl::JobQueue::getNextJob : maximum jobs running"); // Run this job if we're running below the limit. if (data.running < getJobLimit(data.type())) { - XRPL_ASSERT( - data.waiting > 0, - "xrpl::JobQueue::getNextJob : positive data waiting"); + XRPL_ASSERT(data.waiting > 0, "xrpl::JobQueue::getNextJob : positive data waiting"); --data.waiting; ++data.running; break; } } - XRPL_ASSERT( - iter != m_jobSet.end(), "xrpl::JobQueue::getNextJob : found next job"); + XRPL_ASSERT(iter != m_jobSet.end(), "xrpl::JobQueue::getNextJob : found next job"); job = *iter; m_jobSet.erase(iter); } @@ -342,17 +305,14 @@ JobQueue::getNextJob(Job& job) void JobQueue::finishJob(JobType type) { - XRPL_ASSERT( - type != jtINVALID, "xrpl::JobQueue::finishJob : valid input job type"); + XRPL_ASSERT(type != jtINVALID, "xrpl::JobQueue::finishJob : valid input job type"); JobTypeData& data = getJobTypeData(type); // Queue a deferred task if possible if (data.deferred > 0) { - XRPL_ASSERT( - data.running + data.waiting >= getJobLimit(type), - "xrpl::JobQueue::finishJob : job limit"); + XRPL_ASSERT(data.running + data.waiting >= getJobLimit(type), "xrpl::JobQueue::finishJob : job limit"); --data.deferred; m_workers.addTask(); @@ -381,15 +341,13 @@ JobQueue::processTask(int instance) JLOG(m_journal.trace()) << "Doing " << data.name() << "job"; // The amount of time that the job was in the queue - auto const q_time = - ceil(start_time - job.queue_time()); + auto const q_time = ceil(start_time - job.queue_time()); perfLog_.jobStart(type, q_time, start_time, instance); job.doJob(); // The amount of time it took to execute the job - auto const x_time = - ceil(Job::clock_type::now() - start_time); + auto const x_time = ceil(Job::clock_type::now() - start_time); if (x_time >= 10ms || q_time >= 10ms) { @@ -418,8 +376,7 @@ int JobQueue::getJobLimit(JobType type) { JobTypeInfo const& j(JobTypes::instance().get(type)); - XRPL_ASSERT( - j.type() != jtINVALID, "xrpl::JobQueue::getJobLimit : valid job type"); + XRPL_ASSERT(j.type() != jtINVALID, "xrpl::JobQueue::getJobLimit : valid job type"); return j.limit(); } diff --git a/src/libxrpl/core/detail/LoadEvent.cpp b/src/libxrpl/core/detail/LoadEvent.cpp index 43a2c491c3..1370e9089f 100644 --- a/src/libxrpl/core/detail/LoadEvent.cpp +++ b/src/libxrpl/core/detail/LoadEvent.cpp @@ -4,10 +4,7 @@ namespace xrpl { -LoadEvent::LoadEvent( - LoadMonitor& monitor, - std::string const& name, - bool shouldStart) +LoadEvent::LoadEvent(LoadMonitor& monitor, std::string const& name, bool shouldStart) : monitor_(monitor) , running_(shouldStart) , name_(name) diff --git a/src/libxrpl/core/detail/LoadMonitor.cpp b/src/libxrpl/core/detail/LoadMonitor.cpp index 933fea5877..376b25c178 100644 --- a/src/libxrpl/core/detail/LoadMonitor.cpp +++ b/src/libxrpl/core/detail/LoadMonitor.cpp @@ -15,8 +15,7 @@ TODO //------------------------------------------------------------------------------ -LoadMonitor::Stats::Stats() - : count(0), latencyAvg(0), latencyPeak(0), isOverloaded(false) +LoadMonitor::Stats::Stats() : count(0), latencyAvg(0), latencyPeak(0), isOverloaded(false) { } @@ -90,10 +89,8 @@ LoadMonitor::addLoadSample(LoadEvent const& s) if (latency > 500ms) { auto mj = (latency > 1s) ? j_.warn() : j_.info(); - JLOG(mj) << "Job: " << s.name() - << " run: " << round(s.runTime()).count() << "ms" - << " wait: " << round(s.waitTime()).count() - << "ms"; + JLOG(mj) << "Job: " << s.name() << " run: " << round(s.runTime()).count() << "ms" + << " wait: " << round(s.waitTime()).count() << "ms"; } addSamples(1, latency); @@ -121,18 +118,14 @@ LoadMonitor::addSamples(int count, std::chrono::milliseconds latency) } void -LoadMonitor::setTargetLatency( - std::chrono::milliseconds avg, - std::chrono::milliseconds pk) +LoadMonitor::setTargetLatency(std::chrono::milliseconds avg, std::chrono::milliseconds pk) { mTargetLatencyAvg = avg; mTargetLatencyPk = pk; } bool -LoadMonitor::isOverTarget( - std::chrono::milliseconds avg, - std::chrono::milliseconds peak) +LoadMonitor::isOverTarget(std::chrono::milliseconds avg, std::chrono::milliseconds peak) { using namespace std::chrono_literals; return (mTargetLatencyPk > 0ms && (peak > mTargetLatencyPk)) || @@ -149,9 +142,7 @@ LoadMonitor::isOver() if (mLatencyEvents == 0) return 0; - return isOverTarget( - mLatencyMSAvg / (mLatencyEvents * 4), - mLatencyMSPeak / (mLatencyEvents * 4)); + return isOverTarget(mLatencyMSAvg / (mLatencyEvents * 4), mLatencyMSPeak / (mLatencyEvents * 4)); } LoadMonitor::Stats diff --git a/src/libxrpl/core/detail/Workers.cpp b/src/libxrpl/core/detail/Workers.cpp index aa4731a0ff..27103d765d 100644 --- a/src/libxrpl/core/detail/Workers.cpp +++ b/src/libxrpl/core/detail/Workers.cpp @@ -5,11 +5,7 @@ namespace xrpl { -Workers::Workers( - Callback& callback, - perf::PerfLog* perfLog, - std::string const& threadNames, - int numberOfThreads) +Workers::Workers(Callback& callback, perf::PerfLog* perfLog, std::string const& threadNames, int numberOfThreads) : m_callback(callback) , perfLog_(perfLog) , m_threadNames(threadNames) @@ -100,9 +96,7 @@ Workers::stop() m_cv.wait(lk, [this] { return m_allPaused; }); lk.unlock(); - XRPL_ASSERT( - numberOfCurrentlyRunningTasks() == 0, - "xrpl::Workers::stop : zero running tasks"); + XRPL_ASSERT(numberOfCurrentlyRunningTasks() == 0, "xrpl::Workers::stop : zero running tasks"); } void @@ -138,15 +132,8 @@ Workers::deleteWorkers(beast::LockFreeStack& stack) //------------------------------------------------------------------------------ -Workers::Worker::Worker( - Workers& workers, - std::string const& threadName, - int const instance) - : m_workers{workers} - , threadName_{threadName} - , instance_{instance} - , wakeCount_{0} - , shouldExit_{false} +Workers::Worker::Worker(Workers& workers, std::string const& threadName, int const instance) + : m_workers{workers}, threadName_{threadName}, instance_{instance}, wakeCount_{0}, shouldExit_{false} { thread_ = std::thread{&Workers::Worker::run, this}; } diff --git a/src/libxrpl/crypto/RFC1751.cpp b/src/libxrpl/crypto/RFC1751.cpp index 86ee8ad382..dc841fca83 100644 --- a/src/libxrpl/crypto/RFC1751.cpp +++ b/src/libxrpl/crypto/RFC1751.cpp @@ -21,234 +21,153 @@ namespace xrpl { // char const* RFC1751::s_dictionary[2048] = { - "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", "AGO", "AID", - "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA", "AND", - "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", - "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", - "AVE", "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", - "BAH", "BAM", "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", - "BEG", "BEN", "BET", "BEY", "BIB", "BID", "BIG", "BIN", "BIT", - "BOB", "BOG", "BON", "BOO", "BOP", "BOW", "BOY", "BUB", "BUD", - "BUG", "BUM", "BUN", "BUS", "BUT", "BUY", "BY", "BYE", "CAB", - "CAL", "CAM", "CAN", "CAP", "CAR", "CAT", "CAW", "COD", "COG", - "COL", "CON", "COO", "COP", "COT", "COW", "COY", "CRY", "CUB", - "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", "DAR", - "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG", - "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", - "DUB", "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", - "EGG", "EGO", "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", - "ETC", "EVA", "EVE", "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", - "FAY", "FED", "FEE", "FEW", "FIB", "FIG", "FIN", "FIR", "FIT", - "FLO", "FLY", "FOE", "FOG", "FOR", "FRY", "FUM", "FUN", "FUR", - "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", "GAS", "GAY", "GEE", - "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO", "GOT", "GUM", - "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD", "HAL", - "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", - "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", - "HIT", "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", - "HUB", "HUE", "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", - "IF", "IKE", "ILL", "INK", "INN", "IO", "ION", "IQ", "IRA", - "IRE", "IRK", "IS", "IT", "ITS", "IVY", "JAB", "JAG", "JAM", - "JAN", "JAR", "JAW", "JAY", "JET", "JIG", "JIM", "JO", "JOB", - "JOE", "JOG", "JOT", "JOY", "JUG", "JUT", "KAY", "KEG", "KEN", - "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC", "LAD", - "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG", - "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT", - "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", - "LUG", "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", - "MAT", "MAW", "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", - "MID", "MIN", "MIT", "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", - "MOT", "MOW", "MUD", "MUG", "MUM", "MY", "NAB", "NAG", "NAN", - "NAP", "NAT", "NAY", "NE", "NED", "NEE", "NET", "NEW", "NIB", - "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON", "NOR", "NOT", - "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF", "OAK", "OAR", - "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK", - "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", - "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", - "PAD", "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", - "PEA", "PEG", "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", - "PIE", "PIN", "PIT", "PLY", "PO", "POD", "POE", "POP", "POT", - "POW", "PRO", "PRY", "PUB", "PUG", "PUN", "PUP", "PUT", "QUO", - "RAG", "RAM", "RAN", "RAP", "RAT", "RAW", "RAY", "REB", "RED", - "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO", "RIP", "ROB", - "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE", "RUG", - "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM", "SAN", - "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET", - "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", - "SKY", "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", - "SPA", "SPY", "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", - "TAD", "TAG", "TAN", "TAP", "TAR", "TEA", "TED", "TEE", "TEN", - "THE", "THY", "TIC", "TIE", "TIM", "TIN", "TIP", "TO", "TOE", - "TOG", "TOM", "TON", "TOO", "TOP", "TOW", "TOY", "TRY", "TUB", - "TUG", "TUM", "TUN", "TWO", "UN", "UP", "US", "USE", "VAN", - "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS", "WAY", "WE", - "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK", - "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", - "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT", - "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", - "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", - "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", "ALOE", - "ALSO", "ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", - "AMOS", "AMRA", "ANDY", "ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", - "ARAB", "ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", - "ASKS", "ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", - "AVOW", "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL", - "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", - "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", - "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", "BAWD", "BAWL", "BEAD", - "BEAK", "BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", - "BEER", "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", - "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", - "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", - "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", - "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", "BOHR", - "BOIL", "BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", - "BONN", "BONY", "BOOK", "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", - "BOSE", "BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", - "BRAN", "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", - "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG", "BURL", - "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", - "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", - "CANE", "CANT", "CARD", "CARE", "CARL", "CARR", "CART", "CASE", "CASH", - "CASK", "CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", - "CHAT", "CHAW", "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", - "CHUB", "CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", - "CLAY", "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", - "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN", "COKE", - "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", "COON", - "COOT", "CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", - "CRAG", "CRAM", "CRAY", "CREW", "CRIB", "CROW", "CRUD", "CUBA", "CUBE", - "CUFF", "CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", - "CUTS", "DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", - "DARK", "DARN", "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", - "DAYS", "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", - "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", - "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT", "DIRE", "DIRT", - "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", - "DOME", "DONE", "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", - "DOVE", "DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", "DRUB", "DRUG", - "DRUM", "DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", - "DUNE", "DUNK", "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", - "EAST", "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT", - "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", - "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED", "FACE", "FACT", - "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", - "FAST", "FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", - "FELT", "FEND", "FERN", "FEST", "FEUD", "FIEF", "FIGS", "FILE", "FILL", - "FILM", "FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", - "FITS", "FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", - "FLEW", "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM", - "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", - "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", - "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", "FROM", "FUEL", - "FULL", "FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", - "GAIL", "GAIN", "GAIT", "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", - "GARB", "GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", - "GELD", "GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", - "GILT", "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN", - "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", - "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", - "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB", "GRAD", "GRAY", "GREG", - "GREW", "GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", - "GULL", "GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", - "HACK", "HAIL", "HAIR", "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", - "HANG", "HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", - "HATE", "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", - "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL", "HELM", - "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", - "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", - "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", "HONE", - "HONK", "HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", - "HOVE", "HOWE", "HOWL", "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", - "HUGO", "HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", - "HYDE", "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", - "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE", "ITCH", - "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", - "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", - "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", "JOIN", "JOKE", "JOLT", "JOVE", - "JUDD", "JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", - "JUNO", "JURY", "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", - "KATE", "KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", - "KILL", "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", - "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", - "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", "LAKE", - "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", - "LATE", "LAUD", "LAVA", "LAWN", "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", - "LEAN", "LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", - "LESK", "LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", - "LIES", "LIEU", "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", - "LIMB", "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", - "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", - "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD", "LORE", "LOSE", - "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", - "LULU", "LUND", "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", - "LYNN", "LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", "MAIL", "MAIN", - "MAKE", "MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", - "MARE", "MARK", "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", - "MATE", "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK", - "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", - "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT", "MIMI", "MIND", - "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", - "MOAN", "MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", - "MONK", "MONT", "MOOD", "MOON", "MOOR", "MOOT", "MORE", "MORN", "MORT", - "MOSS", "MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", - "MULL", "MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", - "NAIL", "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR", - "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", - "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", - "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", "NOSE", "NOTE", - "NOUN", "NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", - "OHIO", "OILY", "OINT", "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", - "OMEN", "OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", - "OSLO", "OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", - "OWLY", "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT", - "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", - "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", - "REEF", "REEK", "REEL", "REID", "REIN", "RENA", "REND", "RENT", "REST", - "RICE", "RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", - "RISE", "RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", - "ROIL", "ROLL", "ROME", "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", - "ROSE", "ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", - "RUBY", "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", - "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE", "SAID", - "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", - "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", - "SEAM", "SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", "SELF", - "SELL", "SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", - "SHED", "SHIM", "SHIN", "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", - "SICK", "SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", - "SINE", "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", - "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY", "SLED", - "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", - "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", - "SOAK", "SOAR", "SOCK", "SODA", "SOFA", "SOFT", "SOIL", "SOLD", "SOME", - "SONG", "SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", - "STAG", "STAN", "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", - "STUN", "SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", - "SURF", "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", - "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", - "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", "TEET", - "TELL", "TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", - "THEE", "THEM", "THEN", "THEY", "THIN", "THIS", "THUD", "THUG", "TICK", - "TIDE", "TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", - "TINE", "TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", - "TONE", "TONG", "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", - "TOUR", "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", - "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", - "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK", "TWIG", "TWIN", - "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", - "VAIN", "VALE", "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", - "VEND", "VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", "VINE", "VISE", - "VOID", "VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", - "WALE", "WALK", "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", - "WARM", "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY", - "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", - "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM", "WHAT", "WHEE", - "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", - "WINE", "WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", - "WONT", "WOOD", "WOOL", "WORD", "WORE", "WORK", "WORM", "WORN", "WOVE", - "WRIT", "WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", - "YEAH", "YEAR", "YELL", "YOGA", "YOKE"}; + "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD", "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", + "AMY", "AN", "ANA", "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK", "ARM", + "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE", "AWE", "AWK", "AWL", "AWN", "AX", + "AYE", "BAD", "BAG", "BAH", "BAM", "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", + "BET", "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO", "BOP", "BOW", "BOY", + "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT", "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", + "CAP", "CAR", "CAT", "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY", "CRY", + "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN", "DAR", "DAY", "DEE", "DEL", "DEN", + "DES", "DEW", "DID", "DIE", "DIG", "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", + "DUB", "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO", "ELI", "ELK", "ELM", + "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE", "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", + "FED", "FEE", "FEW", "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR", "FRY", + "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP", "GAS", "GAY", "GEE", "GEL", "GEM", + "GET", "GIG", "GIL", "GIN", "GO", "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", + "HAD", "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM", "HEN", "HER", "HEW", + "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT", "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", + "HOW", "HUB", "HUE", "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL", "INK", + "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT", "ITS", "IVY", "JAB", "JAG", "JAM", + "JAN", "JAR", "JAW", "JAY", "JET", "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", + "JUT", "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC", "LAD", "LAG", + "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE", "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", + "LIN", "LIP", "LIT", "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG", "LYE", + "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY", "ME", "MEG", "MEL", "MEN", + "MET", "MEW", "MID", "MIN", "MIT", "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", + "MUG", "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED", "NEE", "NET", "NEW", + "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", + "NUT", "O", "OAF", "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL", "OK", + "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT", "OUR", "OUT", "OVA", "OW", "OWE", + "OWL", "OWN", "OX", "PA", "PAD", "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", + "PEG", "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT", "PLY", "PO", "POD", + "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB", "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", + "RAN", "RAP", "RAT", "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM", "RIO", + "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB", "RUE", "RUG", "RUM", "RUN", "RYE", + "SAC", "SAD", "SAG", "SAL", "SAM", "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", + "SET", "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY", "SLY", "SO", "SOB", + "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY", "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", + "TAD", "TAG", "TAN", "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM", + "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP", "TOW", "TOY", "TRY", "TUB", "TUG", + "TUM", "TUN", "TWO", "UN", "UP", "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", + "WAS", "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK", "WON", "WOO", + "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE", "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", + "ABLE", "ABUT", "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS", "ADEN", "AFAR", "AFRO", "AGEE", + "AHEM", "AHOY", "AIDA", "AIDE", "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA", "ALLY", "ALMA", + "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW", + "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", + "ASKS", "ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW", "AWAY", "AWRY", "BABE", "BABY", + "BACH", "BACK", "BADE", "BAIL", "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM", "BAND", "BANE", + "BANG", "BANK", "BARB", "BARD", "BARE", "BARK", "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH", + "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER", "BEET", + "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", + "BIDE", "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB", "BLAT", "BLED", "BLEW", + "BLOB", "BLOC", "BLOT", "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", "BODE", "BODY", "BOGY", + "BOHR", "BOIL", "BOLD", "BOLO", "BOLT", "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK", "BOOM", + "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS", "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", + "BRAN", "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD", "BUFF", "BULB", "BULK", "BULL", "BUNK", + "BUNT", "BUOY", "BURG", "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST", "BUSY", "BYTE", "CADY", + "CAFE", "CAGE", "CAIN", "CAKE", "CALF", "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL", "CARR", + "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL", "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", + "CHEF", "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG", "CHUM", "CITE", "CITY", "CLAD", "CLAM", + "CLAN", "CLAW", "CLAY", "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA", "COCK", "COCO", "CODA", + "CODE", "CODY", "COED", "COIL", "COIN", "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK", "COOL", + "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST", "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", + "CRIB", "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY", "CURB", "CURD", "CURE", "CURL", "CURT", + "CUTS", "DADE", "DALE", "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN", "DART", "DASH", "DATA", + "DATE", "DAVE", "DAVY", "DAWN", "DAYS", "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED", "DEEM", + "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK", "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", + "DINT", "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES", "DOLE", "DOLL", "DOLT", "DOME", "DONE", + "DOOM", "DOOR", "DORA", "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG", "DRAM", "DRAW", "DREW", + "DRUB", "DRUG", "DRUM", "DUAL", "DUCK", "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK", "DUSK", + "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST", "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", + "EDIT", "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT", "EMMA", "ENDS", "ERIC", "EROS", "EVEN", + "EVER", "EVIL", "EYED", "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL", "FAME", "FANG", "FARM", + "FAST", "FATE", "FAWN", "FEAR", "FEAT", "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST", "FEUD", + "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE", "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", + "FIVE", "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW", "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", + "FLUE", "FOAL", "FOAM", "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL", "FOOT", "FORD", "FORE", + "FORK", "FORM", "FORT", "FOSS", "FOUL", "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY", "FROG", + "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY", "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", + "GALA", "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH", "GATE", "GAUL", "GAUR", "GAVE", "GAWK", + "GEAR", "GELD", "GENE", "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT", "GINA", "GIRD", "GIRL", + "GIST", "GIVE", "GLAD", "GLEE", "GLEN", "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD", "GOAL", + "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG", "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", + "GRAB", "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN", "GRIT", "GROW", "GRUB", "GULF", "GULL", + "GUNK", "GURU", "GUSH", "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR", "HALE", "HALF", "HALL", + "HALO", "HALT", "HAND", "HANG", "HANK", "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE", "HATH", + "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR", "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", + "HELL", "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN", "HICK", "HIDE", "HIGH", "HIKE", "HILL", + "HILT", "HIND", "HINT", "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE", "HOLM", "HOLT", "HOME", + "HONE", "HONK", "HOOD", "HOOF", "HOOK", "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL", "HOYT", + "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK", "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", + "HYDE", "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH", "INTO", "IONS", "IOTA", "IOWA", "IRIS", + "IRMA", "IRON", "ISLE", "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE", "JAVA", "JEAN", "JEFF", + "JERK", "JESS", "JEST", "JIBE", "JILL", "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN", "JOIN", + "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY", "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", + "JUST", "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL", "KEEN", "KENO", "KENT", "KERN", "KERR", + "KEYS", "KICK", "KILL", "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW", "KNIT", "KNOB", "KNOT", + "KNOW", "KOCH", "KONG", "KUDO", "KURD", "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN", "LAIR", + "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD", "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", + "LAWS", "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER", "LEFT", "LEND", "LENS", "LENT", "LEON", + "LESK", "LESS", "LEST", "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU", "LIFE", "LIFT", "LIKE", + "LILA", "LILT", "LILY", "LIMA", "LIMB", "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST", "LIVE", + "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE", "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", + "LORD", "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK", "LUCY", "LUGE", "LUKE", "LULU", "LUND", + "LUNG", "LURA", "LURE", "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE", "MADE", "MAGI", "MAID", + "MAIL", "MAIN", "MAKE", "MALE", "MALI", "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK", "MARS", + "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE", "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", + "MEEK", "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH", "MESS", "MICE", "MIKE", "MILD", "MILE", + "MILK", "MILL", "MILT", "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS", "MIST", "MITE", "MITT", + "MOAN", "MOAT", "MOCK", "MODE", "MOLD", "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON", "MOOR", + "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH", "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", + "MURK", "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL", "NAIR", "NAME", "NARY", "NASH", "NAVE", + "NAVY", "NEAL", "NEAR", "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS", "NEST", "NEWS", "NEWT", + "NIBS", "NICE", "NICK", "NILE", "NINA", "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON", "NORM", + "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB", "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", + "OKAY", "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE", "ONES", "ONLY", "ONTO", "ONUS", "ORAL", + "ORGY", "OSLO", "OTIS", "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY", "OWNS", "QUAD", "QUIT", + "QUOD", "RACE", "RACK", "RACY", "RAFT", "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE", "RASH", + "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR", "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", + "RENA", "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT", "RILL", "RIME", "RING", "RINK", "RISE", + "RISK", "RITE", "ROAD", "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME", "ROOD", "ROOF", "ROOK", + "ROOM", "ROOT", "ROSA", "ROSE", "ROSS", "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY", "RUDE", + "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE", "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", + "SAGE", "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE", "SANG", "SANK", "SARA", "SAUL", "SAVE", + "SAYS", "SCAN", "SCAR", "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK", "SEEM", "SEEN", "SEES", + "SELF", "SELL", "SEND", "SENT", "SETS", "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN", "SHOD", + "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE", "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", + "SINE", "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW", "SKID", "SKIM", "SKIN", "SKIT", "SLAB", + "SLAM", "SLAT", "SLAY", "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT", "SLOW", "SLUG", "SLUM", + "SLUR", "SMOG", "SMUG", "SNAG", "SNOB", "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA", "SOFT", + "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE", "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", + "STAR", "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH", "SUDS", "SUIT", "SULK", "SUMS", "SUNG", + "SUNK", "SURE", "SURF", "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM", "TACK", "TACT", "TAIL", + "TAKE", "TALE", "TALK", "TALL", "TANK", "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM", "TEEN", + "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS", "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", + "THIN", "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER", "TILE", "TILL", "TILT", "TIME", "TINA", + "TINE", "TINT", "TINY", "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG", "TONY", "TOOK", "TOOL", + "TOOT", "TORE", "TORN", "TOTE", "TOUR", "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG", "TRIM", + "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE", "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", + "TUSK", "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER", "USES", "UTAH", "VAIL", "VAIN", "VALE", + "VARY", "VASE", "VAST", "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY", "VETO", "VICE", "VIEW", + "VINE", "VISE", "VOID", "VOLT", "VOTE", "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK", "WALL", + "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM", "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", + "WAVY", "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR", "WELD", "WELL", "WELT", "WENT", "WERE", + "WERT", "WEST", "WHAM", "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE", "WILD", "WILL", "WIND", + "WINE", "WING", "WINK", "WINO", "WIRE", "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD", "WORE", + "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE", "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", + "YEAR", "YELL", "YOGA", "YOKE"}; /* Extract 'length' bits from the char array 's' starting with bit 'start' */ @@ -263,9 +182,7 @@ RFC1751::extract(char const* s, int start, int length) XRPL_ASSERT(length <= 11, "xrpl::RFC1751::extract : maximum length"); XRPL_ASSERT(start >= 0, "xrpl::RFC1751::extract : minimum start"); XRPL_ASSERT(length >= 0, "xrpl::RFC1751::extract : minimum length"); - XRPL_ASSERT( - start + length <= 66, - "xrpl::RFC1751::extract : maximum start + length"); + XRPL_ASSERT(start + length <= 66, "xrpl::RFC1751::extract : maximum start + length"); int const shiftR = 24 - (length + (start % 8)); cl = s[start / 8]; // get components @@ -295,12 +212,9 @@ RFC1751::btoe(std::string& strHuman, std::string const& strData) caBuffer[8] = char(p) << 6; - strHuman = std::string() + s_dictionary[extract(caBuffer, 0, 11)] + " " + - s_dictionary[extract(caBuffer, 11, 11)] + " " + - s_dictionary[extract(caBuffer, 22, 11)] + " " + - s_dictionary[extract(caBuffer, 33, 11)] + " " + - s_dictionary[extract(caBuffer, 44, 11)] + " " + - s_dictionary[extract(caBuffer, 55, 11)]; + strHuman = std::string() + s_dictionary[extract(caBuffer, 0, 11)] + " " + s_dictionary[extract(caBuffer, 11, 11)] + + " " + s_dictionary[extract(caBuffer, 22, 11)] + " " + s_dictionary[extract(caBuffer, 33, 11)] + " " + + s_dictionary[extract(caBuffer, 44, 11)] + " " + s_dictionary[extract(caBuffer, 55, 11)]; } void @@ -315,8 +229,7 @@ RFC1751::insert(char* s, int x, int start, int length) XRPL_ASSERT(length <= 11, "xrpl::RFC1751::insert : maximum length"); XRPL_ASSERT(start >= 0, "xrpl::RFC1751::insert : minimum start"); XRPL_ASSERT(length >= 0, "xrpl::RFC1751::insert : minimum length"); - XRPL_ASSERT( - start + length <= 66, "xrpl::RFC1751::insert : maximum start + length"); + XRPL_ASSERT(start + length <= 66, "xrpl::RFC1751::insert : maximum start + length"); shift = ((8 - ((start + length) % 8)) % 8); y = (long)x << shift; @@ -450,11 +363,7 @@ RFC1751::getKeyFromEnglish(std::string& strKey, std::string const& strHuman) boost::algorithm::trim(strTrimmed); - boost::algorithm::split( - vWords, - strTrimmed, - boost::algorithm::is_space(), - boost::algorithm::token_compress_on); + boost::algorithm::split(vWords, strTrimmed, boost::algorithm::is_space(), boost::algorithm::token_compress_on); rc = 12 == vWords.size() ? 1 : -1; @@ -503,8 +412,7 @@ RFC1751::getWordFromBlob(void const* blob, size_t bytes) hash ^= (hash >> 11); hash += (hash << 15); - return s_dictionary - [hash % (sizeof(s_dictionary) / sizeof(s_dictionary[0]))]; + return s_dictionary[hash % (sizeof(s_dictionary) / sizeof(s_dictionary[0]))]; } } // namespace xrpl diff --git a/src/libxrpl/crypto/csprng.cpp b/src/libxrpl/crypto/csprng.cpp index 5ee1700d7f..7858d4089c 100644 --- a/src/libxrpl/crypto/csprng.cpp +++ b/src/libxrpl/crypto/csprng.cpp @@ -46,10 +46,7 @@ csprng_engine::mix_entropy(void* buffer, std::size_t count) // We add data to the pool, but we conservatively assume that // it contributes no actual entropy. - RAND_add( - entropy.data(), - entropy.size() * sizeof(std::random_device::result_type), - 0); + RAND_add(entropy.data(), entropy.size() * sizeof(std::random_device::result_type), 0); if (buffer != nullptr && count != 0) RAND_add(buffer, count, 0); @@ -65,8 +62,7 @@ csprng_engine::operator()(void* ptr, std::size_t count) std::lock_guard lock(mutex_); #endif - auto const result = - RAND_bytes(reinterpret_cast(ptr), count); + auto const result = RAND_bytes(reinterpret_cast(ptr), count); if (result != 1) Throw("CSPRNG: Insufficient entropy"); diff --git a/src/libxrpl/json/Writer.cpp b/src/libxrpl/json/Writer.cpp index 6da29211ca..be9595b088 100644 --- a/src/libxrpl/json/Writer.cpp +++ b/src/libxrpl/json/Writer.cpp @@ -134,10 +134,7 @@ public: auto t = stack_.top().type; if (t != type) { - check( - false, - "Not an " + - ((type == array ? "array: " : "object: ") + message)); + check(false, "Not an " + ((type == array ? "array: " : "object: ") + message)); } if (stack_.top().isFirst) stack_.top().isFirst = false; diff --git a/src/libxrpl/json/json_reader.cpp b/src/libxrpl/json/json_reader.cpp index ca0b5e5eee..22df530b7e 100644 --- a/src/libxrpl/json/json_reader.cpp +++ b/src/libxrpl/json/json_reader.cpp @@ -104,9 +104,7 @@ Reader::parse(char const* beginDoc, char const* endDoc, Value& root) token.type_ = tokenError; token.start_ = beginDoc; token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); + addError("A valid JSON document must be either an array or an object value.", token); return false; } @@ -157,8 +155,7 @@ Reader::readValue(unsigned depth) break; default: - return addError( - "Syntax error: value, object or array expected.", token); + return addError("Syntax error: value, object or array expected.", token); } return successful; @@ -361,10 +358,7 @@ Reader::readNumber() { if (!std::isdigit(static_cast(*current_))) { - auto ret = std::find( - std::begin(extended_tokens), - std::end(extended_tokens), - *current_); + auto ret = std::find(std::begin(extended_tokens), std::end(extended_tokens), *current_); if (ret == std::end(extended_tokens)) break; @@ -429,8 +423,7 @@ Reader::readObject(Token& tokenStart, unsigned depth) if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); + return addErrorAndRecover("Missing ':' after object member name", colon, tokenObjectEnd); } // Reject duplicate names @@ -448,13 +441,9 @@ Reader::readObject(Token& tokenStart, unsigned depth) Token comma; if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && - comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", - comma, - tokenObjectEnd); + return addErrorAndRecover("Missing ',' or '}' in object declaration", comma, tokenObjectEnd); } bool finalizeTokenOk = true; @@ -466,8 +455,7 @@ Reader::readObject(Token& tokenStart, unsigned depth) return true; } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); + return addErrorAndRecover("Missing '}' or object member name", tokenName, tokenObjectEnd); } bool @@ -504,16 +492,11 @@ Reader::readArray(Token& tokenStart, unsigned depth) ok = readToken(token); } - bool badTokenType = - (token.type_ != tokenArraySeparator && - token.type_ != tokenArrayEnd); + bool badTokenType = (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", - token, - tokenArrayEnd); + return addErrorAndRecover("Missing ',' or ']' in array declaration", token, tokenArrayEnd); } if (token.type_ == tokenArrayEnd) @@ -534,19 +517,14 @@ Reader::decodeNumber(Token& token) if (current == token.end_) { - return addError( - "'" + std::string(token.start_, token.end_) + - "' is not a valid number.", - token); + return addError("'" + std::string(token.start_, token.end_) + "' is not a valid number.", token); } // The existing Json integers are 32-bit so using a 64-bit value here avoids // overflows in the conversion code below. std::int64_t value = 0; - static_assert( - sizeof(value) > sizeof(Value::maxUInt), - "The JSON integer overflow logic will need to be reworked."); + static_assert(sizeof(value) > sizeof(Value::maxUInt), "The JSON integer overflow logic will need to be reworked."); while (current < token.end_ && (value <= Value::maxUInt)) { @@ -554,10 +532,7 @@ Reader::decodeNumber(Token& token) if (c < '0' || c > '9') { - return addError( - "'" + std::string(token.start_, token.end_) + - "' is not a number.", - token); + return addError("'" + std::string(token.start_, token.end_) + "' is not a number.", token); } value = (value * 10) + (c - '0'); @@ -566,10 +541,7 @@ Reader::decodeNumber(Token& token) // More tokens left -> input is larger than largest possible return value if (current != token.end_) { - return addError( - "'" + std::string(token.start_, token.end_) + - "' exceeds the allowable range.", - token); + return addError("'" + std::string(token.start_, token.end_) + "' exceeds the allowable range.", token); } if (isNegative) @@ -578,10 +550,7 @@ Reader::decodeNumber(Token& token) if (value < Value::minInt || value > Value::maxInt) { - return addError( - "'" + std::string(token.start_, token.end_) + - "' exceeds the allowable range.", - token); + return addError("'" + std::string(token.start_, token.end_) + "' exceeds the allowable range.", token); } currentValue() = static_cast(value); @@ -590,10 +559,7 @@ Reader::decodeNumber(Token& token) { if (value > Value::maxUInt) { - return addError( - "'" + std::string(token.start_, token.end_) + - "' exceeds the allowable range.", - token); + return addError("'" + std::string(token.start_, token.end_) + "' exceeds the allowable range.", token); } // If it's representable as a signed integer, construct it as one. @@ -637,9 +603,7 @@ Reader::decodeDouble(Token& token) count = sscanf(buffer.c_str(), format, &value); } if (count != 1) - return addError( - "'" + std::string(token.start_, token.end_) + "' is not a number.", - token); + return addError("'" + std::string(token.start_, token.end_) + "' is not a number.", token); currentValue() = value; return true; } @@ -672,8 +636,7 @@ Reader::decodeString(Token& token, std::string& decoded) else if (c == '\\') { if (current == end) - return addError( - "Empty escape sequence in string", token, current); + return addError("Empty escape sequence in string", token, current); Char escape = *current++; @@ -722,8 +685,7 @@ Reader::decodeString(Token& token, std::string& decoded) break; default: - return addError( - "Bad escape sequence in string", token, current); + return addError("Bad escape sequence in string", token, current); } } else @@ -736,11 +698,7 @@ Reader::decodeString(Token& token, std::string& decoded) } bool -Reader::decodeUnicodeCodePoint( - Token& token, - Location& current, - Location end, - unsigned int& unicode) +Reader::decodeUnicodeCodePoint(Token& token, Location& current, Location end, unsigned int& unicode) { if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) return false; @@ -761,8 +719,7 @@ Reader::decodeUnicodeCodePoint( { if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + - (surrogatePair & 0x3FF); + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); } else return false; @@ -779,17 +736,10 @@ Reader::decodeUnicodeCodePoint( } bool -Reader::decodeUnicodeEscapeSequence( - Token& token, - Location& current, - Location end, - unsigned int& unicode) +Reader::decodeUnicodeEscapeSequence(Token& token, Location& current, Location end, unsigned int& unicode) { if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, - current); + return addError("Bad unicode escape sequence in string: four digits expected.", token, current); unicode = 0; @@ -846,10 +796,7 @@ Reader::recoverFromError(TokenType skipUntilToken) } bool -Reader::addErrorAndRecover( - std::string const& message, - Token& token, - TokenType skipUntilToken) +Reader::addErrorAndRecover(std::string const& message, Token& token, TokenType skipUntilToken) { addError(message, token); return recoverFromError(skipUntilToken); @@ -871,8 +818,7 @@ Reader::getNextChar() } void -Reader::getLocationLineAndColumn(Location location, int& line, int& column) - const +Reader::getLocationLineAndColumn(Location location, int& line, int& column) const { Location current = begin_; Location lastLineStart = current; @@ -907,8 +853,7 @@ Reader::getLocationLineAndColumn(Location location) const { int line, column; getLocationLineAndColumn(location, line, column); - return "Line " + std::to_string(line) + ", Column " + - std::to_string(column); + return "Line " + std::to_string(line) + ", Column " + std::to_string(column); } std::string @@ -916,18 +861,14 @@ Reader::getFormattedErrorMessages() const { std::string formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) + for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError) { ErrorInfo const& error = *itError; - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; formattedMessage += " " + error.message_ + "\n"; if (error.extra_) - formattedMessage += "See " + - getLocationLineAndColumn(error.extra_) + " for detail.\n"; + formattedMessage += "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; } return formattedMessage; diff --git a/src/libxrpl/json/json_value.cpp b/src/libxrpl/json/json_value.cpp index b738774d79..edbbafc1eb 100644 --- a/src/libxrpl/json/json_value.cpp +++ b/src/libxrpl/json/json_value.cpp @@ -33,8 +33,7 @@ public: } char* - duplicateStringValue(char const* value, unsigned int length = unknown) - override + duplicateStringValue(char const* value, unsigned int length = unknown) override { //@todo investigate this old optimization // if ( !value || value[0] == 0 ) @@ -90,21 +89,15 @@ Value::CZString::CZString(int index) : cstr_(0), index_(index) } Value::CZString::CZString(char const* cstr, DuplicationPolicy allocate) - : cstr_( - allocate == duplicate ? valueAllocator()->makeMemberName(cstr) : cstr) - , index_(allocate) + : cstr_(allocate == duplicate ? valueAllocator()->makeMemberName(cstr) : cstr), index_(allocate) { } Value::CZString::CZString(CZString const& other) : cstr_( - other.index_ != noDuplication && other.cstr_ != 0 - ? valueAllocator()->makeMemberName(other.cstr_) - : other.cstr_) - , index_( - other.cstr_ - ? (other.index_ == noDuplication ? noDuplication : duplicate) - : other.index_) + other.index_ != noDuplication && other.cstr_ != 0 ? valueAllocator()->makeMemberName(other.cstr_) + : other.cstr_) + , index_(other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) : other.index_) { } @@ -221,14 +214,12 @@ Value::Value(char const* value) : type_(stringValue), allocated_(true) Value::Value(xrpl::Number const& value) : type_(stringValue), allocated_(true) { auto const tmp = to_string(value); - value_.string_ = - valueAllocator()->duplicateStringValue(tmp.c_str(), tmp.length()); + value_.string_ = valueAllocator()->duplicateStringValue(tmp.c_str(), tmp.length()); } Value::Value(std::string const& value) : type_(stringValue), allocated_(true) { - value_.string_ = valueAllocator()->duplicateStringValue( - value.c_str(), (unsigned int)value.length()); + value_.string_ = valueAllocator()->duplicateStringValue(value.c_str(), (unsigned int)value.length()); } Value::Value(StaticString const& value) : type_(stringValue), allocated_(false) @@ -256,8 +247,7 @@ Value::Value(Value const& other) : type_(other.type_) case stringValue: if (other.value_.string_) { - value_.string_ = valueAllocator()->duplicateStringValue( - other.value_.string_); + value_.string_ = valueAllocator()->duplicateStringValue(other.value_.string_); allocated_ = true; } else @@ -315,8 +305,7 @@ Value::operator=(Value const& other) return *this; } -Value::Value(Value&& other) noexcept - : value_(other.value_), type_(other.type_), allocated_(other.allocated_) +Value::Value(Value&& other) noexcept : value_(other.value_), type_(other.type_), allocated_(other.allocated_) { other.type_ = nullValue; other.allocated_ = 0; @@ -392,8 +381,7 @@ operator<(Value const& x, Value const& y) case stringValue: return (x.value_.string_ == 0 && y.value_.string_) || - (y.value_.string_ && x.value_.string_ && - strcmp(x.value_.string_, y.value_.string_) < 0); + (y.value_.string_ && x.value_.string_ && strcmp(x.value_.string_, y.value_.string_) < 0); case arrayValue: case objectValue: { @@ -443,13 +431,11 @@ operator==(Value const& x, Value const& y) case stringValue: return x.value_.string_ == y.value_.string_ || - (y.value_.string_ && x.value_.string_ && - !strcmp(x.value_.string_, y.value_.string_)); + (y.value_.string_ && x.value_.string_ && !strcmp(x.value_.string_, y.value_.string_)); case arrayValue: case objectValue: - return x.value_.map_->size() == y.value_.map_->size() && - *x.value_.map_ == *y.value_.map_; + return x.value_.map_->size() == y.value_.map_->size() && *x.value_.map_ == *y.value_.map_; // LCOV_EXCL_START default: @@ -515,15 +501,11 @@ Value::asInt() const return value_.int_; case uintValue: - JSON_ASSERT_MESSAGE( - value_.uint_ < (unsigned)maxInt, - "integer out of signed integer range"); + JSON_ASSERT_MESSAGE(value_.uint_ < (unsigned)maxInt, "integer out of signed integer range"); return value_.uint_; case realValue: - JSON_ASSERT_MESSAGE( - value_.real_ >= minInt && value_.real_ <= maxInt, - "Real out of signed integer range"); + JSON_ASSERT_MESSAGE(value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range"); return Int(value_.real_); case booleanValue: @@ -569,13 +551,10 @@ Value::asAbsUInt() const case realValue: { if (value_.real_ < 0) { - JSON_ASSERT_MESSAGE( - -1 * value_.real_ <= maxUInt, - "Real out of unsigned integer range"); + JSON_ASSERT_MESSAGE(-1 * value_.real_ <= maxUInt, "Real out of unsigned integer range"); return UInt(-1 * value_.real_); } - JSON_ASSERT_MESSAGE( - value_.real_ <= maxUInt, "Real out of unsigned integer range"); + JSON_ASSERT_MESSAGE(value_.real_ <= maxUInt, "Real out of unsigned integer range"); return UInt(value_.real_); } @@ -587,13 +566,10 @@ Value::asAbsUInt() const auto const temp = beast::lexicalCastThrow(str); if (temp < 0) { - JSON_ASSERT_MESSAGE( - -1 * temp <= maxUInt, - "String out of unsigned integer range"); + JSON_ASSERT_MESSAGE(-1 * temp <= maxUInt, "String out of unsigned integer range"); return -1 * temp; } - JSON_ASSERT_MESSAGE( - temp <= maxUInt, "String out of unsigned integer range"); + JSON_ASSERT_MESSAGE(temp <= maxUInt, "String out of unsigned integer range"); return temp; } @@ -619,18 +595,14 @@ Value::asUInt() const return 0; case intValue: - JSON_ASSERT_MESSAGE( - value_.int_ >= 0, - "Negative integer can not be converted to unsigned integer"); + JSON_ASSERT_MESSAGE(value_.int_ >= 0, "Negative integer can not be converted to unsigned integer"); return value_.int_; case uintValue: return value_.uint_; case realValue: - JSON_ASSERT_MESSAGE( - value_.real_ >= 0 && value_.real_ <= maxUInt, - "Real out of unsigned integer range"); + JSON_ASSERT_MESSAGE(value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range"); return UInt(value_.real_); case booleanValue: @@ -731,45 +703,34 @@ Value::isConvertibleTo(ValueType other) const return true; case intValue: - return (other == nullValue && value_.int_ == 0) || - other == intValue || (other == uintValue && value_.int_ >= 0) || - other == realValue || other == stringValue || + return (other == nullValue && value_.int_ == 0) || other == intValue || + (other == uintValue && value_.int_ >= 0) || other == realValue || other == stringValue || other == booleanValue; case uintValue: return (other == nullValue && value_.uint_ == 0) || - (other == intValue && value_.uint_ <= (unsigned)maxInt) || - other == uintValue || other == realValue || + (other == intValue && value_.uint_ <= (unsigned)maxInt) || other == uintValue || other == realValue || other == stringValue || other == booleanValue; case realValue: return (other == nullValue && value_.real_ == 0.0) || - (other == intValue && value_.real_ >= minInt && - value_.real_ <= maxInt) || - (other == uintValue && value_.real_ >= 0 && - value_.real_ <= maxUInt && - std::fabs(round(value_.real_) - value_.real_) < - std::numeric_limits::epsilon()) || - other == realValue || other == stringValue || - other == booleanValue; + (other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt) || + (other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt && + std::fabs(round(value_.real_) - value_.real_) < std::numeric_limits::epsilon()) || + other == realValue || other == stringValue || other == booleanValue; case booleanValue: - return (other == nullValue && value_.bool_ == false) || - other == intValue || other == uintValue || other == realValue || - other == stringValue || other == booleanValue; + return (other == nullValue && value_.bool_ == false) || other == intValue || other == uintValue || + other == realValue || other == stringValue || other == booleanValue; case stringValue: - return other == stringValue || - (other == nullValue && - (!value_.string_ || value_.string_[0] == 0)); + return other == stringValue || (other == nullValue && (!value_.string_ || value_.string_[0] == 0)); case arrayValue: - return other == arrayValue || - (other == nullValue && value_.map_->size() == 0); + return other == arrayValue || (other == nullValue && value_.map_->size() == 0); case objectValue: - return other == objectValue || - (other == nullValue && value_.map_->size() == 0); + return other == objectValue || (other == nullValue && value_.map_->size() == 0); // LCOV_EXCL_START default: @@ -833,9 +794,7 @@ Value::operator bool() const void Value::clear() { - XRPL_ASSERT( - type_ == nullValue || type_ == arrayValue || type_ == objectValue, - "Json::Value::clear : valid type"); + XRPL_ASSERT(type_ == nullValue || type_ == arrayValue || type_ == objectValue, "Json::Value::clear : valid type"); switch (type_) { @@ -852,9 +811,7 @@ Value::clear() Value& Value::operator[](UInt index) { - XRPL_ASSERT( - type_ == nullValue || type_ == arrayValue, - "Json::Value::operator[](UInt) : valid type"); + XRPL_ASSERT(type_ == nullValue || type_ == arrayValue, "Json::Value::operator[](UInt) : valid type"); if (type_ == nullValue) *this = Value(arrayValue); @@ -873,9 +830,7 @@ Value::operator[](UInt index) Value const& Value::operator[](UInt index) const { - XRPL_ASSERT( - type_ == nullValue || type_ == arrayValue, - "Json::Value::operator[](UInt) const : valid type"); + XRPL_ASSERT(type_ == nullValue || type_ == arrayValue, "Json::Value::operator[](UInt) const : valid type"); if (type_ == nullValue) return null; @@ -898,15 +853,12 @@ Value::operator[](char const* key) Value& Value::resolveReference(char const* key, bool isStatic) { - XRPL_ASSERT( - type_ == nullValue || type_ == objectValue, - "Json::Value::resolveReference : valid type"); + XRPL_ASSERT(type_ == nullValue || type_ == objectValue, "Json::Value::resolveReference : valid type"); if (type_ == nullValue) *this = Value(objectValue); - CZString actualKey( - key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); + CZString actualKey(key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); ObjectValues::iterator it = value_.map_->lower_bound(actualKey); if (it != value_.map_->end() && (*it).first == actualKey) @@ -934,9 +886,7 @@ Value::isValidIndex(UInt index) const Value const& Value::operator[](char const* key) const { - XRPL_ASSERT( - type_ == nullValue || type_ == objectValue, - "Json::Value::operator[](const char*) const : valid type"); + XRPL_ASSERT(type_ == nullValue || type_ == objectValue, "Json::Value::operator[](const char*) const : valid type"); if (type_ == nullValue) return null; @@ -1002,9 +952,7 @@ Value::get(std::string const& key, Value const& defaultValue) const Value Value::removeMember(char const* key) { - XRPL_ASSERT( - type_ == nullValue || type_ == objectValue, - "Json::Value::removeMember : valid type"); + XRPL_ASSERT(type_ == nullValue || type_ == objectValue, "Json::Value::removeMember : valid type"); if (type_ == nullValue) return null; @@ -1051,9 +999,7 @@ Value::isMember(StaticString const& key) const Value::Members Value::getMemberNames() const { - XRPL_ASSERT( - type_ == nullValue || type_ == objectValue, - "Json::Value::getMemberNames : valid type"); + XRPL_ASSERT(type_ == nullValue || type_ == objectValue, "Json::Value::getMemberNames : valid type"); if (type_ == nullValue) return Value::Members(); diff --git a/src/libxrpl/json/json_valueiterator.cpp b/src/libxrpl/json/json_valueiterator.cpp index e9c22ac5f7..90a1ebe44b 100644 --- a/src/libxrpl/json/json_valueiterator.cpp +++ b/src/libxrpl/json/json_valueiterator.cpp @@ -17,9 +17,7 @@ ValueIteratorBase::ValueIteratorBase() : current_(), isNull_(true) { } -ValueIteratorBase::ValueIteratorBase( - Value::ObjectValues::iterator const& current) - : current_(current), isNull_(false) +ValueIteratorBase::ValueIteratorBase(Value::ObjectValues::iterator const& current) : current_(current), isNull_(false) { } @@ -60,8 +58,7 @@ ValueIteratorBase::computeDistance(SelfType const& other) const // return difference_type( std::distance( current_, other.current_ ) ); difference_type myDistance = 0; - for (Value::ObjectValues::iterator it = current_; it != other.current_; - ++it) + for (Value::ObjectValues::iterator it = current_; it != other.current_; ++it) { ++myDistance; } @@ -128,9 +125,7 @@ ValueIteratorBase::memberName() const // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -ValueConstIterator::ValueConstIterator( - Value::ObjectValues::iterator const& current) - : ValueIteratorBase(current) +ValueConstIterator::ValueConstIterator(Value::ObjectValues::iterator const& current) : ValueIteratorBase(current) { } @@ -149,18 +144,15 @@ ValueConstIterator::operator=(ValueIteratorBase const& other) // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -ValueIterator::ValueIterator(Value::ObjectValues::iterator const& current) - : ValueIteratorBase(current) +ValueIterator::ValueIterator(Value::ObjectValues::iterator const& current) : ValueIteratorBase(current) { } -ValueIterator::ValueIterator(ValueConstIterator const& other) - : ValueIteratorBase(other) +ValueIterator::ValueIterator(ValueConstIterator const& other) : ValueIteratorBase(other) { } -ValueIterator::ValueIterator(ValueIterator const& other) - : ValueIteratorBase(other) +ValueIterator::ValueIterator(ValueIterator const& other) : ValueIteratorBase(other) { } diff --git a/src/libxrpl/json/json_writer.cpp b/src/libxrpl/json/json_writer.cpp index 2d0756852f..e36cf72b1c 100644 --- a/src/libxrpl/json/json_writer.cpp +++ b/src/libxrpl/json/json_writer.cpp @@ -81,9 +81,8 @@ valueToString(double value) // Print into the buffer. We need not request the alternative representation // that always has a decimal point because JSON doesn't distinguish the // concepts of reals and integers. -#if defined(_MSC_VER) && \ - defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 - // to avoid warning. +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 + // to avoid warning. sprintf_s(buffer, sizeof(buffer), "%.16g", value); #else snprintf(buffer, sizeof(buffer), "%.16g", value); @@ -101,8 +100,7 @@ std::string valueToQuotedString(char const* value) { // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == nullptr && - !containsControlCharacter(value)) + if (strpbrk(value, "\"\\\b\f\n\r\t") == nullptr && !containsControlCharacter(value)) return std::string("\"") + value + "\""; // We have to walk value and escape any special characters. @@ -156,8 +154,7 @@ valueToQuotedString(char const* value) if (isControlCharacter(*c)) { std::ostringstream oss; - oss << "\\u" << std::hex << std::uppercase - << std::setfill('0') << std::setw(4) + oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast(*c); result += oss.str(); } @@ -234,9 +231,7 @@ FastWriter::writeValue(Value const& value) Value::Members members(value.getMemberNames()); document_ += "{"; - for (Value::Members::iterator it = members.begin(); - it != members.end(); - ++it) + for (Value::Members::iterator it = members.begin(); it != members.end(); ++it) { std::string const& name = *it; @@ -379,9 +374,7 @@ StyledWriter::writeArrayValue(Value const& value) } else // output on a single line { - XRPL_ASSERT( - childValues_.size() == size, - "Json::StyledWriter::writeArrayValue : child size match"); + XRPL_ASSERT(childValues_.size() == size, "Json::StyledWriter::writeArrayValue : child size match"); document_ += "[ "; for (unsigned index = 0; index < size; ++index) @@ -407,9 +400,7 @@ StyledWriter::isMultilineArray(Value const& value) for (int index = 0; index < size && !isMultiLine; ++index) { Value const& childValue = value[index]; - isMultiLine = isMultiLine || - ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + isMultiLine = isMultiLine || ((childValue.isArray() || childValue.isObject()) && childValue.size() > 0); } if (!isMultiLine) // check if line length > max line length @@ -473,9 +464,7 @@ StyledWriter::indent() void StyledWriter::unindent() { - XRPL_ASSERT( - int(indentString_.size()) >= indentSize_, - "Json::StyledWriter::unindent : maximum indent size"); + XRPL_ASSERT(int(indentString_.size()) >= indentSize_, "Json::StyledWriter::unindent : maximum indent size"); indentString_.resize(indentString_.size() - indentSize_); } @@ -605,9 +594,7 @@ StyledStreamWriter::writeArrayValue(Value const& value) } else // output on a single line { - XRPL_ASSERT( - childValues_.size() == size, - "Json::StyledStreamWriter::writeArrayValue : child size match"); + XRPL_ASSERT(childValues_.size() == size, "Json::StyledStreamWriter::writeArrayValue : child size match"); *document_ << "[ "; for (unsigned index = 0; index < size; ++index) @@ -633,9 +620,7 @@ StyledStreamWriter::isMultilineArray(Value const& value) for (int index = 0; index < size && !isMultiLine; ++index) { Value const& childValue = value[index]; - isMultiLine = isMultiLine || - ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + isMultiLine = isMultiLine || ((childValue.isArray() || childValue.isObject()) && childValue.size() > 0); } if (!isMultiLine) // check if line length > max line length @@ -701,8 +686,7 @@ void StyledStreamWriter::unindent() { XRPL_ASSERT( - indentString_.size() >= indentation_.size(), - "Json::StyledStreamWriter::unindent : maximum indent size"); + indentString_.size() >= indentation_.size(), "Json::StyledStreamWriter::unindent : maximum indent size"); indentString_.resize(indentString_.size() - indentation_.size()); } diff --git a/src/libxrpl/ledger/ApplyStateTable.cpp b/src/libxrpl/ledger/ApplyStateTable.cpp index 94fd9d7273..9892951e15 100644 --- a/src/libxrpl/ledger/ApplyStateTable.cpp +++ b/src/libxrpl/ledger/ApplyStateTable.cpp @@ -65,11 +65,7 @@ ApplyStateTable::visit( switch (item.second.first) { case Action::erase: - func( - item.first, - true, - to.read(keylet::unchecked(item.first)), - item.second.second); + func(item.first, true, to.read(keylet::unchecked(item.first)), item.second.second); break; case Action::insert: @@ -77,11 +73,7 @@ ApplyStateTable::visit( break; case Action::modify: - func( - item.first, - false, - to.read(keylet::unchecked(item.first)), - item.second.second); + func(item.first, false, to.read(keylet::unchecked(item.first)), item.second.second); break; default: @@ -135,9 +127,8 @@ ApplyStateTable::apply( auto curNode = item.second.second; if ((type == &sfModifiedNode) && (*curNode == *origNode)) continue; - std::uint16_t nodeType = curNode - ? curNode->getFieldU16(sfLedgerEntryType) - : origNode->getFieldU16(sfLedgerEntryType); + std::uint16_t nodeType = + curNode ? curNode->getFieldU16(sfLedgerEntryType) : origNode->getFieldU16(sfLedgerEntryType); meta.setAffectedNode(item.first, *type, nodeType); if (type == &sfDeletedNode) { @@ -152,27 +143,23 @@ ApplyStateTable::apply( { // go through the original node for // modified fields saved on modification - if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && - !curNode->hasMatchingEntry(obj)) + if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj)) prevs.emplace_back(obj); } if (!prevs.empty()) - meta.getAffectedNode(item.first) - .emplace_back(std::move(prevs)); + meta.getAffectedNode(item.first).emplace_back(std::move(prevs)); STObject finals(sfFinalFields); for (auto const& obj : *curNode) { // go through the final node for final fields - if (obj.getFName().shouldMeta( - SField::sMD_Always | SField::sMD_DeleteFinal)) + if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_DeleteFinal)) finals.emplace_back(obj); } if (!finals.empty()) - meta.getAffectedNode(item.first) - .emplace_back(std::move(finals)); + meta.getAffectedNode(item.first).emplace_back(std::move(finals)); } else if (type == &sfModifiedNode) { @@ -181,36 +168,31 @@ ApplyStateTable::apply( "xrpl::detail::ApplyStateTable::apply : valid nodes for " "modification"); - if (curNode->isThreadedType( - to.rules())) // thread transaction to node - // item modified + if (curNode->isThreadedType(to.rules())) // thread transaction to node + // item modified threadItem(meta, curNode); STObject prevs(sfPreviousFields); for (auto const& obj : *origNode) { // search the original node for values saved on modify - if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && - !curNode->hasMatchingEntry(obj)) + if (obj.getFName().shouldMeta(SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry(obj)) prevs.emplace_back(obj); } if (!prevs.empty()) - meta.getAffectedNode(item.first) - .emplace_back(std::move(prevs)); + meta.getAffectedNode(item.first).emplace_back(std::move(prevs)); STObject finals(sfFinalFields); for (auto const& obj : *curNode) { // search the final node for values saved always - if (obj.getFName().shouldMeta( - SField::sMD_Always | SField::sMD_ChangeNew)) + if (obj.getFName().shouldMeta(SField::sMD_Always | SField::sMD_ChangeNew)) finals.emplace_back(obj); } if (!finals.empty()) - meta.getAffectedNode(item.first) - .emplace_back(std::move(finals)); + meta.getAffectedNode(item.first).emplace_back(std::move(finals)); } else if (type == &sfCreatedNode) // if created, thread to owner(s) { @@ -220,23 +202,19 @@ ApplyStateTable::apply( "creation"); threadOwners(to, meta, curNode, newMod, j); - if (curNode->isThreadedType( - to.rules())) // always thread to self + if (curNode->isThreadedType(to.rules())) // always thread to self threadItem(meta, curNode); STObject news(sfNewFields); for (auto const& obj : *curNode) { // save non-default values - if (!obj.isDefault() && - obj.getFName().shouldMeta( - SField::sMD_Create | SField::sMD_Always)) + if (!obj.isDefault() && obj.getFName().shouldMeta(SField::sMD_Create | SField::sMD_Always)) news.emplace_back(obj); } if (!news.empty()) - meta.getAffectedNode(item.first) - .emplace_back(std::move(news)); + meta.getAffectedNode(item.first).emplace_back(std::move(news)); } else { @@ -298,10 +276,8 @@ ApplyStateTable::exists(ReadView const& base, Keylet const& k) const } auto -ApplyStateTable::succ( - ReadView const& base, - key_type const& key, - std::optional const& last) const -> std::optional +ApplyStateTable::succ(ReadView const& base, key_type const& key, std::optional const& last) const + -> std::optional { std::optional next = key; items_t::const_iterator iter; @@ -416,10 +392,8 @@ void ApplyStateTable::rawErase(ReadView const& base, std::shared_ptr const& sle) { using namespace std; - auto const result = items_.emplace( - piecewise_construct, - forward_as_tuple(sle->key()), - forward_as_tuple(Action::erase, sle)); + auto const result = + items_.emplace(piecewise_construct, forward_as_tuple(sle->key()), forward_as_tuple(Action::erase, sle)); if (result.second) return; auto& item = result.first->second; @@ -447,10 +421,7 @@ ApplyStateTable::insert(ReadView const& base, std::shared_ptr const& sle) { using namespace std; items_.emplace_hint( - iter, - piecewise_construct, - forward_as_tuple(sle->key()), - forward_as_tuple(Action::insert, sle)); + iter, piecewise_construct, forward_as_tuple(sle->key()), forward_as_tuple(Action::insert, sle)); return; } auto& item = iter->second; @@ -477,10 +448,7 @@ ApplyStateTable::replace(ReadView const& base, std::shared_ptr const& sle) { using namespace std; items_.emplace_hint( - iter, - piecewise_construct, - forward_as_tuple(sle->key()), - forward_as_tuple(Action::modify, sle)); + iter, piecewise_construct, forward_as_tuple(sle->key()), forward_as_tuple(Action::modify, sle)); return; } auto& item = iter->second; @@ -564,19 +532,13 @@ ApplyStateTable::threadItem(TxMeta& meta, std::shared_ptr const& sle) } std::shared_ptr -ApplyStateTable::getForMod( - ReadView const& base, - key_type const& key, - Mods& mods, - beast::Journal j) +ApplyStateTable::getForMod(ReadView const& base, key_type const& key, Mods& mods, beast::Journal j) { { auto miter = mods.find(key); if (miter != mods.end()) { - XRPL_ASSERT( - miter->second, - "xrpl::ApplyStateTable::getForMod : non-null result"); + XRPL_ASSERT(miter->second, "xrpl::ApplyStateTable::getForMod : non-null result"); return miter->second; } } @@ -615,12 +577,7 @@ ApplyStateTable::getForMod( } void -ApplyStateTable::threadTx( - ReadView const& base, - TxMeta& meta, - AccountID const& to, - Mods& mods, - beast::Journal j) +ApplyStateTable::threadTx(ReadView const& base, TxMeta& meta, AccountID const& to, Mods& mods, beast::Journal j) { auto const sle = getForMod(base, keylet::account(to).key, mods, j); if (!sle) @@ -632,9 +589,7 @@ ApplyStateTable::threadTx( return; } // threadItem only applied to AccountRoot - XRPL_ASSERT( - sle->isThreadedType(base.rules()), - "xrpl::ApplyStateTable::threadTx : SLE is threaded"); + XRPL_ASSERT(sle->isThreadedType(base.rules()), "xrpl::ApplyStateTable::threadTx : SLE is threaded"); threadItem(meta, sle); } diff --git a/src/libxrpl/ledger/ApplyView.cpp b/src/libxrpl/ledger/ApplyView.cpp index cfdbbbcb4d..fc35ff5119 100644 --- a/src/libxrpl/ledger/ApplyView.cpp +++ b/src/libxrpl/ledger/ApplyView.cpp @@ -110,8 +110,7 @@ insertPage( // Check whether we're out of pages. if (page == 0) return std::nullopt; - if (!view.rules().enabled(fixDirectoryLimit) && - page >= dirNodeMaxPages) // Old pages limit + if (!view.rules().enabled(fixDirectoryLimit) && page >= dirNodeMaxPages) // Old pages limit return std::nullopt; // We are about to create a new node; we'll link it to @@ -134,8 +133,7 @@ insertPage( // it's the default. if (page != 1) node->setFieldU64(sfIndexPrevious, page - 1); - XRPL_ASSERT_PARTS( - !nextPage, "xrpl::directory::insertPage", "nextPage has default value"); + XRPL_ASSERT_PARTS(!nextPage, "xrpl::directory::insertPage", "nextPage has default value"); /* Reserved for future use when directory pages may be inserted in * between two other pages instead of only at the end of the chain. if (nextPage) @@ -164,18 +162,15 @@ ApplyView::dirAdd( return directory::createRoot(*this, directory, key, describe); } - auto [page, node, indexes] = - directory::findPreviousPage(*this, directory, root); + auto [page, node, indexes] = directory::findPreviousPage(*this, directory, root); // If there's space, we use it: if (indexes.size() < dirNodeMaxEntries) { - return directory::insertKey( - *this, node, page, preserveOrder, indexes, key); + return directory::insertKey(*this, node, page, preserveOrder, indexes, key); } - return directory::insertPage( - *this, page, node, 0, root, key, directory, describe); + return directory::insertPage(*this, page, node, 0, root, key, directory, describe); } bool @@ -187,8 +182,7 @@ ApplyView::emptyDirDelete(Keylet const& directory) return false; // Verify that the passed directory node is the directory root. - if (directory.type != ltDIR_NODE || - node->getFieldH256(sfRootIndex) != directory.key) + if (directory.type != ltDIR_NODE || node->getFieldH256(sfRootIndex) != directory.key) { // LCOV_EXCL_START UNREACHABLE("xrpl::ApplyView::emptyDirDelete : invalid node type"); @@ -248,11 +242,7 @@ ApplyView::emptyDirDelete(Keylet const& directory) } bool -ApplyView::dirRemove( - Keylet const& directory, - std::uint64_t page, - uint256 const& key, - bool keepRoot) +ApplyView::dirRemove(Keylet const& directory, std::uint64_t page, uint256 const& key, bool keepRoot) { auto node = peek(keylet::page(directory, page)); @@ -373,8 +363,7 @@ ApplyView::dirRemove( // Check whether the next page is the last page and, if // so, whether it's empty. If it is, delete it. - if (nextPage != rootPage && next->getFieldU64(sfIndexNext) == rootPage && - next->getFieldV256(sfIndexes).empty()) + if (nextPage != rootPage && next->getFieldU64(sfIndexNext) == rootPage && next->getFieldV256(sfIndexes).empty()) { // Since next doesn't point to the root, it // can't be pointing to prev. @@ -409,9 +398,7 @@ ApplyView::dirRemove( } bool -ApplyView::dirDelete( - Keylet const& directory, - std::function const& callback) +ApplyView::dirDelete(Keylet const& directory, std::function const& callback) { std::optional pi; diff --git a/src/libxrpl/ledger/ApplyViewBase.cpp b/src/libxrpl/ledger/ApplyViewBase.cpp index 51abd8e4a6..ecb5180557 100644 --- a/src/libxrpl/ledger/ApplyViewBase.cpp +++ b/src/libxrpl/ledger/ApplyViewBase.cpp @@ -3,8 +3,7 @@ namespace xrpl { namespace detail { -ApplyViewBase::ApplyViewBase(ReadView const* base, ApplyFlags flags) - : flags_(flags), base_(base) +ApplyViewBase::ApplyViewBase(ReadView const* base, ApplyFlags flags) : flags_(flags), base_(base) { } @@ -41,8 +40,7 @@ ApplyViewBase::exists(Keylet const& k) const } auto -ApplyViewBase::succ(key_type const& key, std::optional const& last) - const -> std::optional +ApplyViewBase::succ(key_type const& key, std::optional const& last) const -> std::optional { return items_.succ(*base_, key, last); } @@ -66,8 +64,7 @@ ApplyViewBase::slesEnd() const -> std::unique_ptr } auto -ApplyViewBase::slesUpperBound(uint256 const& key) const - -> std::unique_ptr +ApplyViewBase::slesUpperBound(uint256 const& key) const -> std::unique_ptr { return base_->slesUpperBound(key); } diff --git a/src/libxrpl/ledger/ApplyViewImpl.cpp b/src/libxrpl/ledger/ApplyViewImpl.cpp index b0aeb70228..eca9043db8 100644 --- a/src/libxrpl/ledger/ApplyViewImpl.cpp +++ b/src/libxrpl/ledger/ApplyViewImpl.cpp @@ -2,8 +2,7 @@ namespace xrpl { -ApplyViewImpl::ApplyViewImpl(ReadView const* base, ApplyFlags flags) - : ApplyViewBase(base, flags) +ApplyViewImpl::ApplyViewImpl(ReadView const* base, ApplyFlags flags) : ApplyViewBase(base, flags) { } diff --git a/src/libxrpl/ledger/BookDirs.cpp b/src/libxrpl/ledger/BookDirs.cpp index 6dda4ffe51..03dd0b0e13 100644 --- a/src/libxrpl/ledger/BookDirs.cpp +++ b/src/libxrpl/ledger/BookDirs.cpp @@ -10,8 +10,7 @@ BookDirs::BookDirs(ReadView const& view, Book const& book) , next_quality_(getQualityNext(root_)) , key_(view_->succ(root_, next_quality_).value_or(beast::zero)) { - XRPL_ASSERT( - root_ != beast::zero, "xrpl::BookDirs::BookDirs : nonzero root"); + XRPL_ASSERT(root_ != beast::zero, "xrpl::BookDirs::BookDirs : nonzero root"); if (key_ != beast::zero) { if (!cdirFirst(*view_, key_, sle_, entry_, index_)) @@ -43,12 +42,10 @@ BookDirs::end() const -> BookDirs::const_iterator return BookDirs::const_iterator(*view_, root_, key_); } -beast::Journal BookDirs::const_iterator::j_ = - beast::Journal{beast::Journal::getNullSink()}; +beast::Journal BookDirs::const_iterator::j_ = beast::Journal{beast::Journal::getNullSink()}; bool -BookDirs::const_iterator::operator==( - BookDirs::const_iterator const& other) const +BookDirs::const_iterator::operator==(BookDirs::const_iterator const& other) const { if (view_ == nullptr || other.view_ == nullptr) return false; @@ -57,16 +54,13 @@ BookDirs::const_iterator::operator==( view_ == other.view_ && root_ == other.root_, "xrpl::BookDirs::const_iterator::operator== : views and roots are " "matching"); - return entry_ == other.entry_ && cur_key_ == other.cur_key_ && - index_ == other.index_; + return entry_ == other.entry_ && cur_key_ == other.cur_key_ && index_ == other.index_; } BookDirs::const_iterator::reference BookDirs::const_iterator::operator*() const { - XRPL_ASSERT( - index_ != beast::zero, - "xrpl::BookDirs::const_iterator::operator* : nonzero index"); + XRPL_ASSERT(index_ != beast::zero, "xrpl::BookDirs::const_iterator::operator* : nonzero index"); if (!cache_) cache_ = view_->read(keylet::offer(index_)); return *cache_; @@ -77,14 +71,10 @@ BookDirs::const_iterator::operator++() { using beast::zero; - XRPL_ASSERT( - index_ != zero, - "xrpl::BookDirs::const_iterator::operator++ : nonzero index"); + XRPL_ASSERT(index_ != zero, "xrpl::BookDirs::const_iterator::operator++ : nonzero index"); if (!cdirNext(*view_, cur_key_, sle_, entry_, index_)) { - if (index_ != 0 || - (cur_key_ = - view_->succ(++cur_key_, next_quality_).value_or(zero)) == zero) + if (index_ != 0 || (cur_key_ = view_->succ(++cur_key_, next_quality_).value_or(zero)) == zero) { cur_key_ = key_; entry_ = 0; @@ -107,9 +97,7 @@ BookDirs::const_iterator::operator++() BookDirs::const_iterator BookDirs::const_iterator::operator++(int) { - XRPL_ASSERT( - index_ != beast::zero, - "xrpl::BookDirs::const_iterator::operator++(int) : nonzero index"); + XRPL_ASSERT(index_ != beast::zero, "xrpl::BookDirs::const_iterator::operator++(int) : nonzero index"); const_iterator tmp(*this); ++(*this); return tmp; diff --git a/src/libxrpl/ledger/CachedView.cpp b/src/libxrpl/ledger/CachedView.cpp index 19d4baa861..12704d227e 100644 --- a/src/libxrpl/ledger/CachedView.cpp +++ b/src/libxrpl/ledger/CachedView.cpp @@ -38,8 +38,7 @@ CachedViewImpl::read(Keylet const& k) const return base_.read(k); }); // If the sle is null, then a failure must have occurred in base_.read() - XRPL_ASSERT( - sle || baseRead, "xrpl::CachedView::read : null SLE result from base"); + XRPL_ASSERT(sle || baseRead, "xrpl::CachedView::read : null SLE result from base"); if (cacheHit && baseRead) hitsexpired.increment(); else if (cacheHit) diff --git a/src/libxrpl/ledger/CredentialHelpers.cpp b/src/libxrpl/ledger/CredentialHelpers.cpp index 82691238f9..c737d42f07 100644 --- a/src/libxrpl/ledger/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/CredentialHelpers.cpp @@ -9,12 +9,9 @@ namespace xrpl { namespace credentials { bool -checkExpired( - std::shared_ptr const& sleCredential, - NetClock::time_point const& closed) +checkExpired(std::shared_ptr const& sleCredential, NetClock::time_point const& closed) { - std::uint32_t const exp = (*sleCredential)[~sfExpiration].value_or( - std::numeric_limits::max()); + std::uint32_t const exp = (*sleCredential)[~sfExpiration].value_or(std::numeric_limits::max()); std::uint32_t const now = closed.time_since_epoch().count(); return now > exp; } @@ -33,8 +30,7 @@ removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j) if (sleCred && checkExpired(sleCred, closeTime)) { - JLOG(j.trace()) - << "Credentials are expired. Cred: " << sleCred->getText(); + JLOG(j.trace()) << "Credentials are expired. Cred: " << sleCred->getText(); // delete expired credentials even if the transaction failed deleteSLE(view, sleCred, j); foundExpired = true; @@ -45,17 +41,12 @@ removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j) } TER -deleteSLE( - ApplyView& view, - std::shared_ptr const& sleCredential, - beast::Journal j) +deleteSLE(ApplyView& view, std::shared_ptr const& sleCredential, beast::Journal j) { if (!sleCredential) return tecNO_ENTRY; - auto delSLE = - [&view, &sleCredential, j]( - AccountID const& account, SField const& node, bool isOwner) -> TER { + auto delSLE = [&view, &sleCredential, j](AccountID const& account, SField const& node, bool isOwner) -> TER { auto const sleAccount = view.peek(keylet::account(account)); if (!sleAccount) { @@ -67,8 +58,7 @@ deleteSLE( // Remove object from owner directory std::uint64_t const page = sleCredential->getFieldU64(node); - if (!view.dirRemove( - keylet::ownerDir(account), page, sleCredential->key(), false)) + if (!view.dirRemove(keylet::ownerDir(account), page, sleCredential->key(), false)) { // LCOV_EXCL_START JLOG(j.fatal()) << "Unable to delete Credential from owner."; @@ -112,9 +102,7 @@ checkFields(STTx const& tx, beast::Journal j) auto const& credentials = tx.getFieldV256(sfCredentialIDs); if (credentials.empty() || (credentials.size() > maxCredentialsArraySize)) { - JLOG(j.trace()) - << "Malformed transaction: Credentials array size is invalid: " - << credentials.size(); + JLOG(j.trace()) << "Malformed transaction: Credentials array size is invalid: " << credentials.size(); return temMALFORMED; } @@ -124,8 +112,7 @@ checkFields(STTx const& tx, beast::Journal j) auto [it, ins] = duplicates.insert(cred); if (!ins) { - JLOG(j.trace()) - << "Malformed transaction: duplicates in credentials."; + JLOG(j.trace()) << "Malformed transaction: duplicates in credentials."; return temMALFORMED; } } @@ -134,11 +121,7 @@ checkFields(STTx const& tx, beast::Journal j) } TER -valid( - STTx const& tx, - ReadView const& view, - AccountID const& src, - beast::Journal j) +valid(STTx const& tx, ReadView const& view, AccountID const& src, beast::Journal j) { if (!tx.isFieldPresent(sfCredentialIDs)) return tesSUCCESS; @@ -155,9 +138,7 @@ valid( if (sleCred->getAccountID(sfSubject) != src) { - JLOG(j.trace()) - << "Credential doesn't belong to the source account. Cred: " - << h; + JLOG(j.trace()) << "Credential doesn't belong to the source account. Cred: " << h; return tecBAD_CREDENTIALS; } @@ -187,8 +168,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject) { auto const issuer = h.getAccountID(sfIssuer); auto const type = h.getFieldVL(sfCredentialType); - auto const keyletCredential = - keylet::credential(subject, issuer, makeSlice(type)); + auto const keyletCredential = keylet::credential(subject, issuer, makeSlice(type)); auto const sleCredential = view.read(keyletCredential); // We cannot delete expired credentials, that would require ApplyView& @@ -214,10 +194,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject) } TER -authorizedDepositPreauth( - ApplyView const& view, - STVector256 const& credIDs, - AccountID const& dst) +authorizedDepositPreauth(ApplyView const& view, STVector256 const& credIDs, AccountID const& dst) { std::set> sorted; std::vector> lifeExtender; @@ -228,8 +205,7 @@ authorizedDepositPreauth( if (!sleCred) // already checked in preclaim return tefINTERNAL; // LCOV_EXCL_LINE - auto [it, ins] = - sorted.emplace((*sleCred)[sfIssuer], (*sleCred)[sfCredentialType]); + auto [it, ins] = sorted.emplace((*sleCred)[sfIssuer], (*sleCred)[sfCredentialType]); if (!ins) return tefINTERNAL; // LCOV_EXCL_LINE lifeExtender.push_back(std::move(sleCred)); @@ -301,11 +277,7 @@ checkArray(STArray const& credentials, unsigned maxSize, beast::Journal j) } // namespace credentials TER -verifyValidDomain( - ApplyView& view, - AccountID const& account, - uint256 domainID, - beast::Journal j) +verifyValidDomain(ApplyView& view, AccountID const& account, uint256 domainID, beast::Journal j) { auto const slePD = view.read(keylet::permissionedDomain(domainID)); if (!slePD) @@ -318,8 +290,7 @@ verifyValidDomain( { auto const issuer = h.getAccountID(sfIssuer); auto const type = h.getFieldVL(sfCredentialType); - auto const keyletCredential = - keylet::credential(account, issuer, makeSlice(type)); + auto const keyletCredential = keylet::credential(account, issuer, makeSlice(type)); if (view.exists(keyletCredential)) credentials.push_back(keyletCredential.key); } @@ -355,8 +326,7 @@ verifyDepositPreauth( bool const credentialsPresent = tx.isFieldPresent(sfCredentialIDs); - if (credentialsPresent && - credentials::removeExpired(view, tx.getFieldV256(sfCredentialIDs), j)) + if (credentialsPresent && credentials::removeExpired(view, tx.getFieldV256(sfCredentialIDs), j)) return tecEXPIRED; if (sleDst && (sleDst->getFlags() & lsfDepositAuth)) @@ -366,8 +336,7 @@ verifyDepositPreauth( if (!view.exists(keylet::depositPreauth(dst, src))) return !credentialsPresent ? tecNO_PERMISSION - : credentials::authorizedDepositPreauth( - view, tx.getFieldV256(sfCredentialIDs), dst); + : credentials::authorizedDepositPreauth(view, tx.getFieldV256(sfCredentialIDs), dst); } } diff --git a/src/libxrpl/ledger/Credit.cpp b/src/libxrpl/ledger/Credit.cpp index 09798cef90..064fcdaf3b 100644 --- a/src/libxrpl/ledger/Credit.cpp +++ b/src/libxrpl/ledger/Credit.cpp @@ -6,11 +6,7 @@ namespace xrpl { STAmount -creditLimit( - ReadView const& view, - AccountID const& account, - AccountID const& issuer, - Currency const& currency) +creditLimit(ReadView const& view, AccountID const& account, AccountID const& issuer, Currency const& currency) { STAmount result(Issue{currency, account}); @@ -18,36 +14,23 @@ creditLimit( if (sleRippleState) { - result = sleRippleState->getFieldAmount( - account < issuer ? sfLowLimit : sfHighLimit); + result = sleRippleState->getFieldAmount(account < issuer ? sfLowLimit : sfHighLimit); result.setIssuer(account); } - XRPL_ASSERT( - result.getIssuer() == account, - "xrpl::creditLimit : result issuer match"); - XRPL_ASSERT( - result.getCurrency() == currency, - "xrpl::creditLimit : result currency match"); + XRPL_ASSERT(result.getIssuer() == account, "xrpl::creditLimit : result issuer match"); + XRPL_ASSERT(result.getCurrency() == currency, "xrpl::creditLimit : result currency match"); return result; } IOUAmount -creditLimit2( - ReadView const& v, - AccountID const& acc, - AccountID const& iss, - Currency const& cur) +creditLimit2(ReadView const& v, AccountID const& acc, AccountID const& iss, Currency const& cur) { return toAmount(creditLimit(v, acc, iss, cur)); } STAmount -creditBalance( - ReadView const& view, - AccountID const& account, - AccountID const& issuer, - Currency const& currency) +creditBalance(ReadView const& view, AccountID const& account, AccountID const& issuer, Currency const& currency) { STAmount result(Issue{currency, account}); @@ -61,12 +44,8 @@ creditBalance( result.setIssuer(account); } - XRPL_ASSERT( - result.getIssuer() == account, - "xrpl::creditBalance : result issuer match"); - XRPL_ASSERT( - result.getCurrency() == currency, - "xrpl::creditBalance : result currency match"); + XRPL_ASSERT(result.getIssuer() == account, "xrpl::creditBalance : result issuer match"); + XRPL_ASSERT(result.getCurrency() == currency, "xrpl::creditBalance : result currency match"); return result; } diff --git a/src/libxrpl/ledger/Dir.cpp b/src/libxrpl/ledger/Dir.cpp index d834216d24..cf0b01aa7f 100644 --- a/src/libxrpl/ledger/Dir.cpp +++ b/src/libxrpl/ledger/Dir.cpp @@ -4,8 +4,7 @@ namespace xrpl { using const_iterator = Dir::const_iterator; -Dir::Dir(ReadView const& view, Keylet const& key) - : view_(&view), root_(key), sle_(view_->read(root_)) +Dir::Dir(ReadView const& view, Keylet const& key) : view_(&view), root_(key), sle_(view_->read(root_)) { if (sle_ != nullptr) indexes_ = &sle_->getFieldV256(sfIndexes); @@ -50,9 +49,7 @@ const_iterator::operator==(const_iterator const& other) const const_iterator::reference const_iterator::operator*() const { - XRPL_ASSERT( - index_ != beast::zero, - "xrpl::const_iterator::operator* : nonzero index"); + XRPL_ASSERT(index_ != beast::zero, "xrpl::const_iterator::operator* : nonzero index"); if (!cache_) cache_ = view_->read(keylet::child(index_)); return *cache_; @@ -61,9 +58,7 @@ const_iterator::operator*() const const_iterator& const_iterator::operator++() { - XRPL_ASSERT( - index_ != beast::zero, - "xrpl::const_iterator::operator++ : nonzero index"); + XRPL_ASSERT(index_ != beast::zero, "xrpl::const_iterator::operator++ : nonzero index"); if (++it_ != std::end(*indexes_)) { index_ = *it_; @@ -77,9 +72,7 @@ const_iterator::operator++() const_iterator const_iterator::operator++(int) { - XRPL_ASSERT( - index_ != beast::zero, - "xrpl::const_iterator::operator++(int) : nonzero index"); + XRPL_ASSERT(index_ != beast::zero, "xrpl::const_iterator::operator++(int) : nonzero index"); const_iterator tmp(*this); ++(*this); return tmp; diff --git a/src/libxrpl/ledger/OpenView.cpp b/src/libxrpl/ledger/OpenView.cpp index 5df3ed7cda..73bd3e16ea 100644 --- a/src/libxrpl/ledger/OpenView.cpp +++ b/src/libxrpl/ledger/OpenView.cpp @@ -10,8 +10,7 @@ private: txs_map::const_iterator iter_; public: - explicit txs_iter_impl(bool metadata, txs_map::const_iterator iter) - : metadata_(metadata), iter_(iter) + explicit txs_iter_impl(bool metadata, txs_map::const_iterator iter) : metadata_(metadata), iter_(iter) { } @@ -57,8 +56,7 @@ public: OpenView::OpenView(OpenView const& rhs) : ReadView(rhs) , TxsRawView(rhs) - , monotonic_resource_{std::make_unique< - boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)} + , monotonic_resource_{std::make_unique(initialBufferSize)} , txs_{rhs.txs_, monotonic_resource_.get()} , rules_{rhs.rules_} , header_{rhs.header_} @@ -67,13 +65,8 @@ OpenView::OpenView(OpenView const& rhs) , hold_{rhs.hold_} , open_{rhs.open_} {}; -OpenView::OpenView( - open_ledger_t, - ReadView const* base, - Rules const& rules, - std::shared_ptr hold) - : monotonic_resource_{std::make_unique< - boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)} +OpenView::OpenView(open_ledger_t, ReadView const* base, Rules const& rules, std::shared_ptr hold) + : monotonic_resource_{std::make_unique(initialBufferSize)} , txs_{monotonic_resource_.get()} , rules_(rules) , header_(base->header()) @@ -88,8 +81,7 @@ OpenView::OpenView( } OpenView::OpenView(ReadView const* base, std::shared_ptr hold) - : monotonic_resource_{std::make_unique< - boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)} + : monotonic_resource_{std::make_unique(initialBufferSize)} , txs_{monotonic_resource_.get()} , rules_(base->rules()) , header_(base->header()) @@ -140,8 +132,7 @@ OpenView::exists(Keylet const& k) const } auto -OpenView::succ(key_type const& key, std::optional const& last) const - -> std::optional +OpenView::succ(key_type const& key, std::optional const& last) const -> std::optional { return items_.succ(*base_, key, last); } @@ -165,8 +156,7 @@ OpenView::slesEnd() const -> std::unique_ptr } auto -OpenView::slesUpperBound(uint256 const& key) const - -> std::unique_ptr +OpenView::slesUpperBound(uint256 const& key) const -> std::unique_ptr { return items_.slesUpperBound(*base_, key); } @@ -199,8 +189,7 @@ OpenView::txRead(key_type const& key) const -> tx_type auto stx = std::make_shared(SerialIter{item.txn->slice()}); decltype(tx_type::second) sto; if (item.meta) - sto = std::make_shared( - SerialIter{item.meta->slice()}, sfMetadata); + sto = std::make_shared(SerialIter{item.meta->slice()}, sfMetadata); else sto = nullptr; return {std::move(stx), std::move(sto)}; @@ -242,10 +231,8 @@ OpenView::rawTxInsert( std::shared_ptr const& txn, std::shared_ptr const& metaData) { - auto const result = txs_.emplace( - std::piecewise_construct, - std::forward_as_tuple(key), - std::forward_as_tuple(txn, metaData)); + auto const result = + txs_.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(txn, metaData)); if (!result.second) LogicError("rawTxInsert: duplicate TX id: " + to_string(key)); } diff --git a/src/libxrpl/ledger/PaymentSandbox.cpp b/src/libxrpl/ledger/PaymentSandbox.cpp index 09600ae623..67492142da 100644 --- a/src/libxrpl/ledger/PaymentSandbox.cpp +++ b/src/libxrpl/ledger/PaymentSandbox.cpp @@ -8,10 +8,7 @@ namespace xrpl { namespace detail { auto -DeferredCredits::makeKey( - AccountID const& a1, - AccountID const& a2, - Currency const& c) -> Key +DeferredCredits::makeKey(AccountID const& a1, AccountID const& a2, Currency const& c) -> Key { if (a1 < a2) return std::make_tuple(a1, a2, c); @@ -26,12 +23,8 @@ DeferredCredits::credit( STAmount const& amount, STAmount const& preCreditSenderBalance) { - XRPL_ASSERT( - sender != receiver, - "xrpl::detail::DeferredCredits::credit : sender is not receiver"); - XRPL_ASSERT( - !amount.negative(), - "xrpl::detail::DeferredCredits::credit : positive amount"); + XRPL_ASSERT(sender != receiver, "xrpl::detail::DeferredCredits::credit : sender is not receiver"); + XRPL_ASSERT(!amount.negative(), "xrpl::detail::DeferredCredits::credit : positive amount"); auto const k = makeKey(sender, receiver, amount.getCurrency()); auto i = credits_.find(k); @@ -66,10 +59,7 @@ DeferredCredits::credit( } void -DeferredCredits::ownerCount( - AccountID const& id, - std::uint32_t cur, - std::uint32_t next) +DeferredCredits::ownerCount(AccountID const& id, std::uint32_t cur, std::uint32_t next) { auto const v = std::max(cur, next); auto r = ownerCounts_.emplace(std::make_pair(id, v)); @@ -91,10 +81,8 @@ DeferredCredits::ownerCount(AccountID const& id) const // Get the adjustments for the balance between main and other. auto -DeferredCredits::adjustments( - AccountID const& main, - AccountID const& other, - Currency const& currency) const -> std::optional +DeferredCredits::adjustments(AccountID const& main, AccountID const& other, Currency const& currency) const + -> std::optional { std::optional result; @@ -107,14 +95,12 @@ DeferredCredits::adjustments( if (main < other) { - result.emplace( - v.highAcctCredits, v.lowAcctCredits, v.lowAcctOrigBalance); + result.emplace(v.highAcctCredits, v.lowAcctCredits, v.lowAcctOrigBalance); return result; } else { - result.emplace( - v.lowAcctCredits, v.highAcctCredits, -v.lowAcctOrigBalance); + result.emplace(v.lowAcctCredits, v.highAcctCredits, -v.lowAcctOrigBalance); return result; } } @@ -150,10 +136,7 @@ DeferredCredits::apply(DeferredCredits& to) } // namespace detail STAmount -PaymentSandbox::balanceHook( - AccountID const& account, - AccountID const& issuer, - STAmount const& amount) const +PaymentSandbox::balanceHook(AccountID const& account, AccountID const& issuer, STAmount const& amount) const { /* There are two algorithms here. The pre-switchover algorithm takes the @@ -200,8 +183,7 @@ PaymentSandbox::balanceHook( } std::uint32_t -PaymentSandbox::ownerCountHook(AccountID const& account, std::uint32_t count) - const +PaymentSandbox::ownerCountHook(AccountID const& account, std::uint32_t count) const { std::uint32_t result = count; for (auto curSB = this; curSB; curSB = curSB->ps_) @@ -223,10 +205,7 @@ PaymentSandbox::creditHook( } void -PaymentSandbox::adjustOwnerCountHook( - AccountID const& account, - std::uint32_t cur, - std::uint32_t next) +PaymentSandbox::adjustOwnerCountHook(AccountID const& account, std::uint32_t cur, std::uint32_t next) { tab_.ownerCount(account, cur, next); } diff --git a/src/libxrpl/ledger/RawStateTable.cpp b/src/libxrpl/ledger/RawStateTable.cpp index b958e94c54..4b5f6837b2 100644 --- a/src/libxrpl/ledger/RawStateTable.cpp +++ b/src/libxrpl/ledger/RawStateTable.cpp @@ -126,8 +126,7 @@ private: void skip() { - while (iter1_ != end1_ && iter1_->second.action == Action::erase && - sle0_->key() == sle1_->key()) + while (iter1_ != end1_ && iter1_->second.action == Action::erase && sle0_->key() == sle1_->key()) { inc1(); inc0(); @@ -166,8 +165,7 @@ RawStateTable::apply(RawView& to) const bool RawStateTable::exists(ReadView const& base, Keylet const& k) const { - XRPL_ASSERT( - k.key.isNonZero(), "xrpl::detail::RawStateTable::exists : nonzero key"); + XRPL_ASSERT(k.key.isNonZero(), "xrpl::detail::RawStateTable::exists : nonzero key"); auto const iter = items_.find(k.key); if (iter == items_.end()) return base.exists(k); @@ -184,10 +182,8 @@ RawStateTable::exists(ReadView const& base, Keylet const& k) const the lower of the two. */ auto -RawStateTable::succ( - ReadView const& base, - key_type const& key, - std::optional const& last) const -> std::optional +RawStateTable::succ(ReadView const& base, key_type const& key, std::optional const& last) const + -> std::optional { std::optional next = key; items_t::const_iterator iter; @@ -223,9 +219,7 @@ RawStateTable::erase(std::shared_ptr const& sle) { // The base invariant is checked during apply auto const result = items_.emplace( - std::piecewise_construct, - std::forward_as_tuple(sle->key()), - std::forward_as_tuple(Action::erase, sle)); + std::piecewise_construct, std::forward_as_tuple(sle->key()), std::forward_as_tuple(Action::erase, sle)); if (result.second) return; auto& item = result.first->second; @@ -248,9 +242,7 @@ void RawStateTable::insert(std::shared_ptr const& sle) { auto const result = items_.emplace( - std::piecewise_construct, - std::forward_as_tuple(sle->key()), - std::forward_as_tuple(Action::insert, sle)); + std::piecewise_construct, std::forward_as_tuple(sle->key()), std::forward_as_tuple(Action::insert, sle)); if (result.second) return; auto& item = result.first->second; @@ -273,9 +265,7 @@ void RawStateTable::replace(std::shared_ptr const& sle) { auto const result = items_.emplace( - std::piecewise_construct, - std::forward_as_tuple(sle->key()), - std::forward_as_tuple(Action::replace, sle)); + std::piecewise_construct, std::forward_as_tuple(sle->key()), std::forward_as_tuple(Action::replace, sle)); if (result.second) return; auto& item = result.first->second; @@ -316,25 +306,20 @@ RawStateTable::destroyXRP(XRPAmount const& fee) std::unique_ptr RawStateTable::slesBegin(ReadView const& base) const { - return std::make_unique( - items_.begin(), items_.end(), base.sles.begin(), base.sles.end()); + return std::make_unique(items_.begin(), items_.end(), base.sles.begin(), base.sles.end()); } std::unique_ptr RawStateTable::slesEnd(ReadView const& base) const { - return std::make_unique( - items_.end(), items_.end(), base.sles.end(), base.sles.end()); + return std::make_unique(items_.end(), items_.end(), base.sles.end(), base.sles.end()); } std::unique_ptr RawStateTable::slesUpperBound(ReadView const& base, uint256 const& key) const { return std::make_unique( - items_.upper_bound(key), - items_.end(), - base.sles.upper_bound(key), - base.sles.end()); + items_.upper_bound(key), items_.end(), base.sles.upper_bound(key), base.sles.end()); } } // namespace detail diff --git a/src/libxrpl/ledger/ReadView.cpp b/src/libxrpl/ledger/ReadView.cpp index e0764d6c81..d6674ba0da 100644 --- a/src/libxrpl/ledger/ReadView.cpp +++ b/src/libxrpl/ledger/ReadView.cpp @@ -53,9 +53,7 @@ makeRulesGivenLedger(DigestAwareReadView const& ledger, Rules const& current) } Rules -makeRulesGivenLedger( - DigestAwareReadView const& ledger, - std::unordered_set> const& presets) +makeRulesGivenLedger(DigestAwareReadView const& ledger, std::unordered_set> const& presets) { Keylet const k = keylet::amendments(); std::optional digest = ledger.digest(k.key); diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 16ec23ffab..72df44ec4a 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -27,21 +27,12 @@ namespace detail { template < class V, class N, - class = std::enable_if_t< - std::is_same_v, SLE> && - std::is_base_of_v>> + class = std::enable_if_t, SLE> && std::is_base_of_v>> bool -internalDirNext( - V& view, - uint256 const& root, - std::shared_ptr& page, - unsigned int& index, - uint256& entry) +internalDirNext(V& view, uint256 const& root, std::shared_ptr& page, unsigned int& index, uint256& entry) { auto const& svIndexes = page->getFieldV256(sfIndexes); - XRPL_ASSERT( - index <= svIndexes.size(), - "xrpl::detail::internalDirNext : index inside range"); + XRPL_ASSERT(index <= svIndexes.size(), "xrpl::detail::internalDirNext : index inside range"); if (index >= svIndexes.size()) { @@ -75,16 +66,9 @@ internalDirNext( template < class V, class N, - class = std::enable_if_t< - std::is_same_v, SLE> && - std::is_base_of_v>> + class = std::enable_if_t, SLE> && std::is_base_of_v>> bool -internalDirFirst( - V& view, - uint256 const& root, - std::shared_ptr& page, - unsigned int& index, - uint256& entry) +internalDirFirst(V& view, uint256 const& root, std::shared_ptr& page, unsigned int& index, uint256& entry) { if constexpr (std::is_const_v) page = view.read(keylet::page(root)); @@ -102,23 +86,13 @@ internalDirFirst( } // namespace detail bool -dirFirst( - ApplyView& view, - uint256 const& root, - std::shared_ptr& page, - unsigned int& index, - uint256& entry) +dirFirst(ApplyView& view, uint256 const& root, std::shared_ptr& page, unsigned int& index, uint256& entry) { return detail::internalDirFirst(view, root, page, index, entry); } bool -dirNext( - ApplyView& view, - uint256 const& root, - std::shared_ptr& page, - unsigned int& index, - uint256& entry) +dirNext(ApplyView& view, uint256 const& root, std::shared_ptr& page, unsigned int& index, uint256& entry) { return detail::internalDirNext(view, root, page, index, entry); } @@ -192,11 +166,7 @@ isGlobalFrozen(ReadView const& view, Asset const& asset) } bool -isIndividualFrozen( - ReadView const& view, - AccountID const& account, - Currency const& currency, - AccountID const& issuer) +isIndividualFrozen(ReadView const& view, AccountID const& account, Currency const& currency, AccountID const& issuer) { if (isXRP(currency)) return false; @@ -204,21 +174,16 @@ isIndividualFrozen( { // Check if the issuer froze the line auto const sle = view.read(keylet::line(account, issuer, currency)); - if (sle && - sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze)) + if (sle && sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze)) return true; } return false; } bool -isIndividualFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue) +isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue) { - if (auto const sle = - view.read(keylet::mptoken(mptIssue.getMptID(), account))) + if (auto const sle = view.read(keylet::mptoken(mptIssue.getMptID(), account))) return sle->isFlag(lsfMPTLocked); return false; } @@ -226,11 +191,7 @@ isIndividualFrozen( // Can the specified account spend the specified currency issued by // the specified issuer or does the freeze flag prohibit it? bool -isFrozen( - ReadView const& view, - AccountID const& account, - Currency const& currency, - AccountID const& issuer) +isFrozen(ReadView const& view, AccountID const& account, Currency const& currency, AccountID const& issuer) { if (isXRP(currency)) return false; @@ -241,31 +202,21 @@ isFrozen( { // Check if the issuer froze the line sle = view.read(keylet::line(account, issuer, currency)); - if (sle && - sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze)) + if (sle && sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze)) return true; } return false; } bool -isFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptIssue, - int depth) +isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth) { - return isGlobalFrozen(view, mptIssue) || - isIndividualFrozen(view, account, mptIssue) || + return isGlobalFrozen(view, mptIssue) || isIndividualFrozen(view, account, mptIssue) || isVaultPseudoAccountFrozen(view, account, mptIssue, depth); } [[nodiscard]] bool -isAnyFrozen( - ReadView const& view, - std::initializer_list const& accounts, - MPTIssue const& mptIssue, - int depth) +isAnyFrozen(ReadView const& view, std::initializer_list const& accounts, MPTIssue const& mptIssue, int depth) { if (isGlobalFrozen(view, mptIssue)) return true; @@ -286,11 +237,7 @@ isAnyFrozen( } bool -isVaultPseudoAccountFrozen( - ReadView const& view, - AccountID const& account, - MPTIssue const& mptShare, - int depth) +isVaultPseudoAccountFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptShare, int depth) { if (!view.rules().enabled(featureSingleAssetVault)) return false; @@ -298,8 +245,7 @@ isVaultPseudoAccountFrozen( if (depth >= maxAssetCheckDepth) return true; // LCOV_EXCL_LINE - auto const mptIssuance = - view.read(keylet::mptIssuance(mptShare.getMptID())); + auto const mptIssuance = view.read(keylet::mptIssuance(mptShare.getMptID())); if (mptIssuance == nullptr) return false; // zero MPToken won't block deletion of MPTokenIssuance @@ -316,8 +262,7 @@ isVaultPseudoAccountFrozen( if (!mptIssuer->isFieldPresent(sfVaultID)) return false; // not a Vault pseudo-account, common case - auto const vault = - view.read(keylet::vault(mptIssuer->getFieldH256(sfVaultID))); + auto const vault = view.read(keylet::vault(mptIssuer->getFieldH256(sfVaultID))); if (vault == nullptr) { // LCOV_EXCL_START UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null vault"); @@ -329,11 +274,7 @@ isVaultPseudoAccountFrozen( } bool -isDeepFrozen( - ReadView const& view, - AccountID const& account, - Currency const& currency, - AccountID const& issuer) +isDeepFrozen(ReadView const& view, AccountID const& account, Currency const& currency, AccountID const& issuer) { if (isXRP(currency)) { @@ -355,11 +296,7 @@ isDeepFrozen( } bool -isLPTokenFrozen( - ReadView const& view, - AccountID const& account, - Issue const& asset, - Issue const& asset2) +isLPTokenFrozen(ReadView const& view, AccountID const& account, Issue const& asset, Issue const& asset2) { return isFrozen(view, account, asset.currency, asset.account) || isFrozen(view, account, asset2.currency, asset2.account); @@ -383,8 +320,7 @@ getLineIfUsable( if (zeroIfFrozen == fhZERO_IF_FROZEN) { - if (isFrozen(view, account, currency, issuer) || - isDeepFrozen(view, account, currency, issuer)) + if (isFrozen(view, account, currency, issuer) || isDeepFrozen(view, account, currency, issuer)) { return nullptr; } @@ -400,15 +336,10 @@ getLineIfUsable( } else if (sleIssuer->isFieldPresent(sfAMMID)) { - auto const sleAmm = - view.read(keylet::amm((*sleIssuer)[sfAMMID])); + auto const sleAmm = view.read(keylet::amm((*sleIssuer)[sfAMMID])); if (!sleAmm || - isLPTokenFrozen( - view, - account, - (*sleAmm)[sfAsset].get(), - (*sleAmm)[sfAsset2].get())) + isLPTokenFrozen(view, account, (*sleAmm)[sfAsset].get(), (*sleAmm)[sfAsset2].get())) { return nullptr; } @@ -451,8 +382,8 @@ getTrustLineBalance( amount.clear(Issue{currency, issuer}); } - JLOG(j.trace()) << "getTrustLineBalance:" << " account=" - << to_string(account) << " amount=" << amount.getFullText(); + JLOG(j.trace()) << "getTrustLineBalance:" << " account=" << to_string(account) + << " amount=" << amount.getFullText(); return view.balanceHook(account, issuer, amount); } @@ -477,15 +408,12 @@ accountHolds( if (returnSpendable && account == issuer) // If the account is the issuer, then their limit is effectively // infinite - return STAmount{ - Issue{currency, issuer}, STAmount::cMaxValue, STAmount::cMaxOffset}; + return STAmount{Issue{currency, issuer}, STAmount::cMaxValue, STAmount::cMaxOffset}; // IOU: Return balance on trust line modulo freeze - SLE::const_pointer const sle = - getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j); + SLE::const_pointer const sle = getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j); - return getTrustLineBalance( - view, sle, account, currency, issuer, returnSpendable, j); + return getTrustLineBalance(view, sle, account, currency, issuer, returnSpendable, j); } STAmount @@ -497,14 +425,7 @@ accountHolds( beast::Journal j, SpendableHandling includeFullBalance) { - return accountHolds( - view, - account, - issue.currency, - issue.account, - zeroIfFrozen, - j, - includeFullBalance); + return accountHolds(view, account, issue.currency, issue.account, zeroIfFrozen, j, includeFullBalance); } STAmount @@ -523,28 +444,23 @@ accountHolds( { // if the account is the issuer, and the issuance exists, their limit is // the issuance limit minus the outstanding value - auto const issuance = - view.read(keylet::mptIssuance(mptIssue.getMptID())); + auto const issuance = view.read(keylet::mptIssuance(mptIssue.getMptID())); if (!issuance) { return STAmount{mptIssue}; } return STAmount{ - mptIssue, - issuance->at(~sfMaximumAmount).value_or(maxMPTokenAmount) - - issuance->at(sfOutstandingAmount)}; + mptIssue, issuance->at(~sfMaximumAmount).value_or(maxMPTokenAmount) - issuance->at(sfOutstandingAmount)}; } STAmount amount; - auto const sleMpt = - view.read(keylet::mptoken(mptIssue.getMptID(), account)); + auto const sleMpt = view.read(keylet::mptoken(mptIssue.getMptID(), account)); if (!sleMpt) amount.clear(mptIssue); - else if ( - zeroIfFrozen == fhZERO_IF_FROZEN && isFrozen(view, account, mptIssue)) + else if (zeroIfFrozen == fhZERO_IF_FROZEN && isFrozen(view, account, mptIssue)) amount.clear(mptIssue); else { @@ -552,23 +468,18 @@ accountHolds( // Only if auth check is needed, as it needs to do an additional read // operation. Note featureSingleAssetVault will affect error codes. - if (zeroIfUnauthorized == ahZERO_IF_UNAUTHORIZED && - view.rules().enabled(featureSingleAssetVault)) + if (zeroIfUnauthorized == ahZERO_IF_UNAUTHORIZED && view.rules().enabled(featureSingleAssetVault)) { - if (auto const err = - requireAuth(view, mptIssue, account, AuthType::StrongAuth); - !isTesSuccess(err)) + if (auto const err = requireAuth(view, mptIssue, account, AuthType::StrongAuth); !isTesSuccess(err)) amount.clear(mptIssue); } else if (zeroIfUnauthorized == ahZERO_IF_UNAUTHORIZED) { - auto const sleIssuance = - view.read(keylet::mptIssuance(mptIssue.getMptID())); + auto const sleIssuance = view.read(keylet::mptIssuance(mptIssue.getMptID())); // if auth is enabled on the issuance and mpt is not authorized, // clear amount - if (sleIssuance && sleIssuance->isFlag(lsfMPTRequireAuth) && - !sleMpt->isFlag(lsfMPTAuthorized)) + if (sleIssuance && sleIssuance->isFlag(lsfMPTRequireAuth) && !sleMpt->isFlag(lsfMPTAuthorized)) amount.clear(mptIssue); } } @@ -590,19 +501,11 @@ accountHolds( [&](TIss const& value) { if constexpr (std::is_same_v) { - return accountHolds( - view, account, value, zeroIfFrozen, j, includeFullBalance); + return accountHolds(view, account, value, zeroIfFrozen, j, includeFullBalance); } else if constexpr (std::is_same_v) { - return accountHolds( - view, - account, - value, - zeroIfFrozen, - zeroIfUnauthorized, - j, - includeFullBalance); + return accountHolds(view, account, value, zeroIfFrozen, zeroIfUnauthorized, j, includeFullBalance); } }, asset.value()); @@ -619,13 +522,7 @@ accountFunds( if (!saDefault.native() && saDefault.getIssuer() == id) return saDefault; - return accountHolds( - view, - id, - saDefault.getCurrency(), - saDefault.getIssuer(), - freezeHandling, - j); + return accountHolds(view, id, saDefault.getCurrency(), saDefault.getIssuer(), freezeHandling, j); } // Prevent ownerCount from wrapping under error conditions. @@ -649,8 +546,7 @@ confineOwnerCount( { if (id) { - JLOG(j.fatal()) - << "Account " << *id << " owner count exceeds max!"; + JLOG(j.fatal()) << "Account " << *id << " owner count exceeds max!"; } adjusted = std::numeric_limits::max(); } @@ -662,8 +558,7 @@ confineOwnerCount( { if (id) { - JLOG(j.fatal()) - << "Account " << *id << " owner count set below 0!"; + JLOG(j.fatal()) << "Account " << *id << " owner count set below 0!"; } adjusted = 0; XRPL_ASSERT(!id, "xrpl::confineOwnerCount : id is not set"); @@ -673,47 +568,34 @@ confineOwnerCount( } XRPAmount -xrpLiquid( - ReadView const& view, - AccountID const& id, - std::int32_t ownerCountAdj, - beast::Journal j) +xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j) { auto const sle = view.read(keylet::account(id)); if (sle == nullptr) return beast::zero; // Return balance minus reserve - std::uint32_t const ownerCount = confineOwnerCount( - view.ownerCountHook(id, sle->getFieldU32(sfOwnerCount)), ownerCountAdj); + std::uint32_t const ownerCount = + confineOwnerCount(view.ownerCountHook(id, sle->getFieldU32(sfOwnerCount)), ownerCountAdj); // Pseudo-accounts have no reserve requirement - auto const reserve = isPseudoAccount(sle) - ? XRPAmount{0} - : view.fees().accountReserve(ownerCount); + auto const reserve = isPseudoAccount(sle) ? XRPAmount{0} : view.fees().accountReserve(ownerCount); auto const fullBalance = sle->getFieldAmount(sfBalance); auto const balance = view.balanceHook(id, xrpAccount(), fullBalance); - STAmount const amount = - (balance < reserve) ? STAmount{0} : balance - reserve; + STAmount const amount = (balance < reserve) ? STAmount{0} : balance - reserve; - JLOG(j.trace()) << "accountHolds:" << " account=" << to_string(id) - << " amount=" << amount.getFullText() - << " fullBalance=" << fullBalance.getFullText() - << " balance=" << balance.getFullText() - << " reserve=" << reserve << " ownerCount=" << ownerCount - << " ownerCountAdj=" << ownerCountAdj; + JLOG(j.trace()) << "accountHolds:" << " account=" << to_string(id) << " amount=" << amount.getFullText() + << " fullBalance=" << fullBalance.getFullText() << " balance=" << balance.getFullText() + << " reserve=" << reserve << " ownerCount=" << ownerCount << " ownerCountAdj=" << ownerCountAdj; return amount.xrp(); } void -forEachItem( - ReadView const& view, - Keylet const& root, - std::function const&)> const& f) +forEachItem(ReadView const& view, Keylet const& root, std::function const&)> const& f) { XRPL_ASSERT(root.type == ltDIR_NODE, "xrpl::forEachItem : valid root type"); @@ -745,8 +627,7 @@ forEachItemAfter( unsigned int limit, std::function const&)> const& f) { - XRPL_ASSERT( - root.type == ltDIR_NODE, "xrpl::forEachItemAfter : valid root type"); + XRPL_ASSERT(root.type == ltDIR_NODE, "xrpl::forEachItemAfter : valid root type"); if (root.type != ltDIR_NODE) return false; @@ -831,8 +712,7 @@ transferRate(ReadView const& view, MPTID const& issuanceID) // fee is 0-50,000 (0-50%), rate is 1,000,000,000-2,000,000,000 // For example, if transfer fee is 50% then 10,000 * 50,000 = 500,000 // which represents 50% of 1,000,000,000 - if (auto const sle = view.read(keylet::mptIssuance(issuanceID)); - sle && sle->isFieldPresent(sfTransferFee)) + if (auto const sle = view.read(keylet::mptIssuance(issuanceID)); sle && sle->isFieldPresent(sfTransferFee)) return Rate{1'000'000'000u + 10'000 * sle->getFieldU16(sfTransferFee)}; return parityRate; @@ -852,21 +732,14 @@ transferRate(ReadView const& view, STAmount const& amount) } bool -areCompatible( - ReadView const& validLedger, - ReadView const& testLedger, - beast::Journal::Stream& s, - char const* reason) +areCompatible(ReadView const& validLedger, ReadView const& testLedger, beast::Journal::Stream& s, char const* reason) { bool ret = true; if (validLedger.header().seq < testLedger.header().seq) { // valid -> ... -> test - auto hash = hashOfSeq( - testLedger, - validLedger.header().seq, - beast::Journal{beast::Journal::getNullSink()}); + auto hash = hashOfSeq(testLedger, validLedger.header().seq, beast::Journal{beast::Journal::getNullSink()}); if (hash && (*hash != validLedger.header().hash)) { JLOG(s) << reason << " incompatible with valid ledger"; @@ -879,10 +752,7 @@ areCompatible( else if (validLedger.header().seq > testLedger.header().seq) { // test -> ... -> valid - auto hash = hashOfSeq( - validLedger, - testLedger.header().seq, - beast::Journal{beast::Journal::getNullSink()}); + auto hash = hashOfSeq(validLedger, testLedger.header().seq, beast::Journal{beast::Journal::getNullSink()}); if (hash && (*hash != testLedger.header().hash)) { JLOG(s) << reason << " incompatible preceding ledger"; @@ -904,11 +774,9 @@ areCompatible( if (!ret) { - JLOG(s) << "Val: " << validLedger.header().seq << " " - << to_string(validLedger.header().hash); + JLOG(s) << "Val: " << validLedger.header().seq << " " << to_string(validLedger.header().hash); - JLOG(s) << "New: " << testLedger.header().seq << " " - << to_string(testLedger.header().hash); + JLOG(s) << "New: " << testLedger.header().seq << " " << to_string(testLedger.header().hash); } return ret; @@ -927,10 +795,7 @@ areCompatible( if (testLedger.header().seq > validIndex) { // Ledger we are testing follows last valid ledger - auto hash = hashOfSeq( - testLedger, - validIndex, - beast::Journal{beast::Journal::getNullSink()}); + auto hash = hashOfSeq(testLedger, validIndex, beast::Journal{beast::Journal::getNullSink()}); if (hash && (*hash != validHash)) { JLOG(s) << reason << " incompatible following ledger"; @@ -939,9 +804,7 @@ areCompatible( ret = false; } } - else if ( - (validIndex == testLedger.header().seq) && - (testLedger.header().hash != validHash)) + else if ((validIndex == testLedger.header().seq) && (testLedger.header().hash != validHash)) { JLOG(s) << reason << " incompatible ledger"; @@ -952,8 +815,7 @@ areCompatible( { JLOG(s) << "Val: " << validIndex << " " << to_string(validHash); - JLOG(s) << "New: " << testLedger.header().seq << " " - << to_string(testLedger.header().hash); + JLOG(s) << "New: " << testLedger.header().seq << " " << to_string(testLedger.header().hash); } return ret; @@ -1005,8 +867,7 @@ getMajorityAmendments(ReadView const& view) auto const majorities = sle->getFieldArray(sfMajorities); for (auto const& m : majorities) - ret[m.getFieldH256(sfAmendment)] = - tp(d(m.getFieldU32(sfCloseTime))); + ret[m.getFieldH256(sfAmendment)] = tp(d(m.getFieldU32(sfCloseTime))); } } @@ -1019,8 +880,7 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) // Easy cases... if (seq > ledger.seq()) { - JLOG(journal.warn()) - << "Can't get seq " << seq << " from " << ledger.seq() << " future"; + JLOG(journal.warn()) << "Can't get seq " << seq << " from " << ledger.seq() << " future"; return std::nullopt; } if (seq == ledger.seq()) @@ -1035,28 +895,23 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) if (hashIndex) { XRPL_ASSERT( - hashIndex->getFieldU32(sfLastLedgerSequence) == - (ledger.seq() - 1), + hashIndex->getFieldU32(sfLastLedgerSequence) == (ledger.seq() - 1), "xrpl::hashOfSeq : matching ledger sequence"); STVector256 vec = hashIndex->getFieldV256(sfHashes); if (vec.size() >= diff) return vec[vec.size() - diff]; - JLOG(journal.warn()) - << "Ledger " << ledger.seq() << " missing hash for " << seq - << " (" << vec.size() << "," << diff << ")"; + JLOG(journal.warn()) << "Ledger " << ledger.seq() << " missing hash for " << seq << " (" << vec.size() + << "," << diff << ")"; } else { - JLOG(journal.warn()) - << "Ledger " << ledger.seq() << ":" << ledger.header().hash - << " missing normal list"; + JLOG(journal.warn()) << "Ledger " << ledger.seq() << ":" << ledger.header().hash << " missing normal list"; } } if ((seq & 0xff) != 0) { - JLOG(journal.debug()) - << "Can't get seq " << seq << " from " << ledger.seq() << " past"; + JLOG(journal.debug()) << "Can't get seq " << seq << " from " << ledger.seq() << " past"; return std::nullopt; } @@ -1066,15 +921,13 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) { auto const lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence); XRPL_ASSERT(lastSeq >= seq, "xrpl::hashOfSeq : minimum last ledger"); - XRPL_ASSERT( - (lastSeq & 0xff) == 0, "xrpl::hashOfSeq : valid last ledger"); + XRPL_ASSERT((lastSeq & 0xff) == 0, "xrpl::hashOfSeq : valid last ledger"); auto const diff = (lastSeq - seq) >> 8; STVector256 vec = hashIndex->getFieldV256(sfHashes); if (vec.size() > diff) return vec[vec.size() - diff - 1]; } - JLOG(journal.warn()) << "Can't get seq " << seq << " from " << ledger.seq() - << " error"; + JLOG(journal.warn()) << "Can't get seq " << seq << " from " << ledger.seq() << " error"; return std::nullopt; } @@ -1085,11 +938,7 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) //------------------------------------------------------------------------------ void -adjustOwnerCount( - ApplyView& view, - std::shared_ptr const& sle, - std::int32_t amount, - beast::Journal j) +adjustOwnerCount(ApplyView& view, std::shared_ptr const& sle, std::int32_t amount, beast::Journal j) { if (!sle) return; @@ -1105,20 +954,13 @@ adjustOwnerCount( std::function describeOwnerDir(AccountID const& account) { - return [account](std::shared_ptr const& sle) { - (*sle)[sfOwner] = account; - }; + return [account](std::shared_ptr const& sle) { (*sle)[sfOwner] = account; }; } TER -dirLink( - ApplyView& view, - AccountID const& owner, - std::shared_ptr& object, - SF_UINT64 const& node) +dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr& object, SF_UINT64 const& node) { - auto const page = view.dirInsert( - keylet::ownerDir(owner), object->key(), describeOwnerDir(owner)); + auto const page = view.dirInsert(keylet::ownerDir(owner), object->key(), describeOwnerDir(owner)); if (!page) return tecDIR_FULL; // LCOV_EXCL_LINE object->setFieldU64(node, *page); @@ -1133,8 +975,7 @@ pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey) for (std::uint16_t i = 0; i < maxAccountAttempts; ++i) { ripesha_hasher rsh; - auto const hash = - sha512Half(i, view.header().parentHash, pseudoOwnerKey); + auto const hash = sha512Half(i, view.header().parentHash, pseudoOwnerKey); rsh(hash.data(), hash.size()); AccountID const ret{static_cast(rsh)}; if (!view.read(keylet::account(ret))) @@ -1176,40 +1017,26 @@ getPseudoAccountFields() } [[nodiscard]] bool -isPseudoAccount( - std::shared_ptr sleAcct, - std::set const& pseudoFieldFilter) +isPseudoAccount(std::shared_ptr sleAcct, std::set const& pseudoFieldFilter) { auto const& fields = getPseudoAccountFields(); // Intentionally use defensive coding here because it's cheap and makes the // semantics of true return value clean. return sleAcct && sleAcct->getType() == ltACCOUNT_ROOT && - std::count_if( - fields.begin(), - fields.end(), - [&sleAcct, &pseudoFieldFilter](SField const* sf) -> bool { - return sleAcct->isFieldPresent(*sf) && - (pseudoFieldFilter.empty() || - pseudoFieldFilter.contains(sf)); - }) > 0; + std::count_if(fields.begin(), fields.end(), [&sleAcct, &pseudoFieldFilter](SField const* sf) -> bool { + return sleAcct->isFieldPresent(*sf) && (pseudoFieldFilter.empty() || pseudoFieldFilter.contains(sf)); + }) > 0; } Expected, TER> -createPseudoAccount( - ApplyView& view, - uint256 const& pseudoOwnerKey, - SField const& ownerField) +createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField) { [[maybe_unused]] auto const& fields = getPseudoAccountFields(); XRPL_ASSERT( std::count_if( - fields.begin(), - fields.end(), - [&ownerField](SField const* sf) -> bool { - return *sf == ownerField; - }) == 1, + fields.begin(), fields.end(), [&ownerField](SField const* sf) -> bool { return *sf == ownerField; }) == 1, "xrpl::createPseudoAccount : valid owner field"); auto const accountId = pseudoAccountAddress(view, pseudoOwnerKey); @@ -1233,8 +1060,7 @@ createPseudoAccount( // Ignore reserves requirement, disable the master key, allow default // rippling, and enable deposit authorization to prevent payments into // pseudo-account. - account->setFieldU32( - sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth); + account->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth); // Link the pseudo-account with its owner object. account->setFieldH256(ownerField, pseudoOwnerKey); @@ -1275,10 +1101,7 @@ canAddHolding(ReadView const& view, MPTIssue const& mptIssue) canAddHolding(ReadView const& view, Asset const& asset) { return std::visit( - [&](TIss const& issue) -> TER { - return canAddHolding(view, issue); - }, - asset.value()); + [&](TIss const& issue) -> TER { return canAddHolding(view, issue); }, asset.value()); } [[nodiscard]] TER @@ -1312,11 +1135,7 @@ checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag) * even if `from` is the issuer. */ static TER -withdrawToDestExceedsLimit( - ReadView const& view, - AccountID const& from, - AccountID const& to, - STAmount const& amount) +withdrawToDestExceedsLimit(ReadView const& view, AccountID const& from, AccountID const& to, STAmount const& amount) { auto const& issuer = amount.getIssuer(); if (from == to || to == issuer || isXRP(issuer)) @@ -1383,8 +1202,7 @@ canWithdraw(ReadView const& view, STTx const& tx) auto const from = tx[sfAccount]; auto const to = tx[~sfDestination].value_or(from); - return canWithdraw( - view, from, to, tx[sfAmount], tx.isFieldPresent(sfDestinationTag)); + return canWithdraw(view, from, to, tx[sfAmount], tx.isFieldPresent(sfDestinationTag)); } TER @@ -1401,27 +1219,20 @@ doWithdraw( // Create trust line or MPToken for the receiving account if (dstAcct == senderAcct) { - if (auto const ter = addEmptyHolding( - view, senderAcct, priorBalance, amount.asset(), j); + if (auto const ter = addEmptyHolding(view, senderAcct, priorBalance, amount.asset(), j); !isTesSuccess(ter) && ter != tecDUPLICATE) return ter; } else { auto dstSle = view.peek(keylet::account(dstAcct)); - if (auto err = - verifyDepositPreauth(tx, view, senderAcct, dstAcct, dstSle, j)) + if (auto err = verifyDepositPreauth(tx, view, senderAcct, dstAcct, dstSle, j)) return err; } // Sanity check if (accountHolds( - view, - sourceAcct, - amount.asset(), - FreezeHandling::fhIGNORE_FREEZE, - AuthHandling::ahIGNORE_AUTH, - j) < amount) + view, sourceAcct, amount.asset(), FreezeHandling::fhIGNORE_FREEZE, AuthHandling::ahIGNORE_AUTH, j) < amount) { // LCOV_EXCL_START JLOG(j.error()) << "LoanBrokerCoverWithdraw: negative balance of " @@ -1432,8 +1243,7 @@ doWithdraw( // Move the funds directly from the broker's pseudo-account to the // dstAcct - return accountSend( - view, sourceAcct, dstAcct, amount, j, WaiveTransferFee::Yes); + return accountSend(view, sourceAcct, dstAcct, amount, j, WaiveTransferFee::Yes); } [[nodiscard]] TER @@ -1541,11 +1351,7 @@ authorizeMPToken( if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0) return tecINTERNAL; // LCOV_EXCL_LINE - if (!view.dirRemove( - keylet::ownerDir(account), - (*sleMpt)[sfOwnerNode], - sleMpt->key(), - false)) + if (!view.dirRemove(keylet::ownerDir(account), (*sleMpt)[sfOwnerNode], sleMpt->key(), false)) return tecINTERNAL; // LCOV_EXCL_LINE adjustOwnerCount(view, sleAcct, -1, journal); @@ -1565,8 +1371,7 @@ authorizeMPToken( // items. This is similar to the reserve requirements of trust lines. std::uint32_t const uOwnerCount = sleAcct->getFieldU32(sfOwnerCount); XRPAmount const reserveCreate( - (uOwnerCount < 2) ? XRPAmount(beast::zero) - : view.fees().accountReserve(uOwnerCount + 1)); + (uOwnerCount < 2) ? XRPAmount(beast::zero) : view.fees().accountReserve(uOwnerCount + 1)); if (priorBalance < reserveCreate) return tecINSUFFICIENT_RESERVE; @@ -1576,8 +1381,7 @@ authorizeMPToken( if (!mpt || mpt->getAccountID(sfIssuer) == account) { // LCOV_EXCL_START - UNREACHABLE( - "xrpl::authorizeMPToken : invalid issuance or issuers token"); + UNREACHABLE("xrpl::authorizeMPToken : invalid issuance or issuers token"); if (view.rules().enabled(featureLendingProtocol)) return tecINTERNAL; // LCOV_EXCL_STOP @@ -1652,8 +1456,7 @@ trustCreate( std::uint32_t uQualityOut, beast::Journal j) { - JLOG(j.trace()) << "trustCreate: " << to_string(uSrcAccountID) << ", " - << to_string(uDstAccountID) << ", " + JLOG(j.trace()) << "trustCreate: " << to_string(uSrcAccountID) << ", " << to_string(uDstAccountID) << ", " << saBalance.getFullText(); auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID; @@ -1670,18 +1473,14 @@ trustCreate( auto const sleRippleState = std::make_shared(ltRIPPLE_STATE, uIndex); view.insert(sleRippleState); - auto lowNode = view.dirInsert( - keylet::ownerDir(uLowAccountID), - sleRippleState->key(), - describeOwnerDir(uLowAccountID)); + auto lowNode = + view.dirInsert(keylet::ownerDir(uLowAccountID), sleRippleState->key(), describeOwnerDir(uLowAccountID)); if (!lowNode) return tecDIR_FULL; // LCOV_EXCL_LINE - auto highNode = view.dirInsert( - keylet::ownerDir(uHighAccountID), - sleRippleState->key(), - describeOwnerDir(uHighAccountID)); + auto highNode = + view.dirInsert(keylet::ownerDir(uHighAccountID), sleRippleState->key(), describeOwnerDir(uHighAccountID)); if (!highNode) return tecDIR_FULL; // LCOV_EXCL_LINE @@ -1694,11 +1493,9 @@ trustCreate( return tefINTERNAL; // LCOV_EXCL_LINE XRPL_ASSERT( - sleAccount->getAccountID(sfAccount) == - (bSetHigh ? uHighAccountID : uLowAccountID), + sleAccount->getAccountID(sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID), "xrpl::trustCreate : matching account ID"); - auto const slePeer = - view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID)); + auto const slePeer = view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID)); if (!slePeer) return tecNO_TARGET; @@ -1706,20 +1503,16 @@ trustCreate( sleRippleState->setFieldU64(sfLowNode, *lowNode); sleRippleState->setFieldU64(sfHighNode, *highNode); - sleRippleState->setFieldAmount( - bSetHigh ? sfHighLimit : sfLowLimit, saLimit); + sleRippleState->setFieldAmount(bSetHigh ? sfHighLimit : sfLowLimit, saLimit); sleRippleState->setFieldAmount( bSetHigh ? sfLowLimit : sfHighLimit, - STAmount(Issue{ - saBalance.getCurrency(), bSetDst ? uSrcAccountID : uDstAccountID})); + STAmount(Issue{saBalance.getCurrency(), bSetDst ? uSrcAccountID : uDstAccountID})); if (uQualityIn) - sleRippleState->setFieldU32( - bSetHigh ? sfHighQualityIn : sfLowQualityIn, uQualityIn); + sleRippleState->setFieldU32(bSetHigh ? sfHighQualityIn : sfLowQualityIn, uQualityIn); if (uQualityOut) - sleRippleState->setFieldU32( - bSetHigh ? sfHighQualityOut : sfLowQualityOut, uQualityOut); + sleRippleState->setFieldU32(bSetHigh ? sfHighQualityOut : sfLowQualityOut, uQualityOut); std::uint32_t uFlags = bSetHigh ? lsfHighReserve : lsfLowReserve; @@ -1750,21 +1543,15 @@ trustCreate( adjustOwnerCount(view, sleAccount, 1, j); // ONLY: Create ripple balance. - sleRippleState->setFieldAmount( - sfBalance, bSetHigh ? -saBalance : saBalance); + sleRippleState->setFieldAmount(sfBalance, bSetHigh ? -saBalance : saBalance); - view.creditHook( - uSrcAccountID, uDstAccountID, saBalance, saBalance.zeroed()); + view.creditHook(uSrcAccountID, uDstAccountID, saBalance, saBalance.zeroed()); return tesSUCCESS; } [[nodiscard]] TER -removeEmptyHolding( - ApplyView& view, - AccountID const& accountID, - Issue const& issue, - beast::Journal journal) +removeEmptyHolding(ApplyView& view, AccountID const& accountID, Issue const& issue, beast::Journal journal) { if (issue.native()) { @@ -1793,8 +1580,7 @@ removeEmptyHolding( if (line->isFlag(lsfLowReserve)) { // Clear reserve for low account. - auto sleLowAccount = - view.peek(keylet::account(line->at(sfLowLimit)->getIssuer())); + auto sleLowAccount = view.peek(keylet::account(line->at(sfLowLimit)->getIssuer())); if (!sleLowAccount) return tecINTERNAL; // LCOV_EXCL_LINE @@ -1808,8 +1594,7 @@ removeEmptyHolding( if (line->isFlag(lsfHighReserve)) { // Clear reserve for high account. - auto sleHighAccount = - view.peek(keylet::account(line->at(sfHighLimit)->getIssuer())); + auto sleHighAccount = view.peek(keylet::account(line->at(sfHighLimit)->getIssuer())); if (!sleHighAccount) return tecINTERNAL; // LCOV_EXCL_LINE @@ -1820,20 +1605,11 @@ removeEmptyHolding( line->clearFlag(lsfHighReserve); } - return trustDelete( - view, - line, - line->at(sfLowLimit)->getIssuer(), - line->at(sfHighLimit)->getIssuer(), - journal); + return trustDelete(view, line, line->at(sfLowLimit)->getIssuer(), line->at(sfHighLimit)->getIssuer(), journal); } [[nodiscard]] TER -removeEmptyHolding( - ApplyView& view, - AccountID const& accountID, - MPTIssue const& mptIssue, - beast::Journal journal) +removeEmptyHolding(ApplyView& view, AccountID const& accountID, MPTIssue const& mptIssue, beast::Journal journal) { // If the account is the issuer, then no token should exist. MPTs do not // have the legacy ability to create such a situation, but check anyway. If @@ -1874,22 +1650,14 @@ trustDelete( JLOG(j.trace()) << "trustDelete: Deleting ripple line: low"; - if (!view.dirRemove( - keylet::ownerDir(uLowAccountID), - uLowNode, - sleRippleState->key(), - false)) + if (!view.dirRemove(keylet::ownerDir(uLowAccountID), uLowNode, sleRippleState->key(), false)) { return tefBAD_LEDGER; // LCOV_EXCL_LINE } JLOG(j.trace()) << "trustDelete: Deleting ripple line: high"; - if (!view.dirRemove( - keylet::ownerDir(uHighAccountID), - uHighNode, - sleRippleState->key(), - false)) + if (!view.dirRemove(keylet::ownerDir(uHighAccountID), uHighNode, sleRippleState->key(), false)) { return tefBAD_LEDGER; // LCOV_EXCL_LINE } @@ -1911,20 +1679,12 @@ offerDelete(ApplyView& view, std::shared_ptr const& sle, beast::Journal j) // Detect legacy directories. uint256 uDirectory = sle->getFieldH256(sfBookDirectory); - if (!view.dirRemove( - keylet::ownerDir(owner), - sle->getFieldU64(sfOwnerNode), - offerIndex, - false)) + if (!view.dirRemove(keylet::ownerDir(owner), sle->getFieldU64(sfOwnerNode), offerIndex, false)) { return tefBAD_LEDGER; // LCOV_EXCL_LINE } - if (!view.dirRemove( - keylet::page(uDirectory), - sle->getFieldU64(sfBookNode), - offerIndex, - false)) + if (!view.dirRemove(keylet::page(uDirectory), sle->getFieldU64(sfBookNode), offerIndex, false)) { return tefBAD_LEDGER; // LCOV_EXCL_LINE } @@ -1942,8 +1702,7 @@ offerDelete(ApplyView& view, std::shared_ptr const& sle, beast::Journal j) auto const& dirIndex = bookDir.getFieldH256(sfBookDirectory); auto const& dirNode = bookDir.getFieldU64(sfBookNode); - if (!view.dirRemove( - keylet::page(dirIndex), dirNode, offerIndex, false)) + if (!view.dirRemove(keylet::page(dirIndex), dirNode, offerIndex, false)) { return tefBAD_LEDGER; // LCOV_EXCL_LINE } @@ -1980,19 +1739,13 @@ rippleCreditIOU( (void)issuer; // Disallow sending to self. - XRPL_ASSERT( - uSenderID != uReceiverID, - "xrpl::rippleCreditIOU : sender is not receiver"); + XRPL_ASSERT(uSenderID != uReceiverID, "xrpl::rippleCreditIOU : sender is not receiver"); bool const bSenderHigh = uSenderID > uReceiverID; auto const index = keylet::line(uSenderID, uReceiverID, currency); - XRPL_ASSERT( - !isXRP(uSenderID) && uSenderID != noAccount(), - "xrpl::rippleCreditIOU : sender is not XRP"); - XRPL_ASSERT( - !isXRP(uReceiverID) && uReceiverID != noAccount(), - "xrpl::rippleCreditIOU : receiver is not XRP"); + XRPL_ASSERT(!isXRP(uSenderID) && uSenderID != noAccount(), "xrpl::rippleCreditIOU : sender is not XRP"); + XRPL_ASSERT(!isXRP(uReceiverID) && uReceiverID != noAccount(), "xrpl::rippleCreditIOU : receiver is not XRP"); // If the line exists, modify it accordingly. if (auto const sleRippleState = view.peek(index)) @@ -2008,10 +1761,8 @@ rippleCreditIOU( saBalance -= saAmount; - JLOG(j.trace()) << "rippleCreditIOU: " << to_string(uSenderID) << " -> " - << to_string(uReceiverID) - << " : before=" << saBefore.getFullText() - << " amount=" << saAmount.getFullText() + JLOG(j.trace()) << "rippleCreditIOU: " << to_string(uSenderID) << " -> " << to_string(uReceiverID) + << " : before=" << saBefore.getFullText() << " amount=" << saAmount.getFullText() << " after=" << saBalance.getFullText(); std::uint32_t const uFlags(sleRippleState->getFieldU32(sfFlags)); @@ -2025,31 +1776,21 @@ rippleCreditIOU( // Sender is zero or negative. && (uFlags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) // Sender reserve is set. - && - static_cast( - uFlags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) != - static_cast( - view.read(keylet::account(uSenderID))->getFlags() & - lsfDefaultRipple) && + && static_cast(uFlags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) != + static_cast(view.read(keylet::account(uSenderID))->getFlags() & lsfDefaultRipple) && !(uFlags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) && - !sleRippleState->getFieldAmount( - !bSenderHigh ? sfLowLimit : sfHighLimit) + !sleRippleState->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit) // Sender trust limit is 0. - && !sleRippleState->getFieldU32( - !bSenderHigh ? sfLowQualityIn : sfHighQualityIn) + && !sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn) // Sender quality in is 0. - && !sleRippleState->getFieldU32( - !bSenderHigh ? sfLowQualityOut : sfHighQualityOut)) + && !sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut)) // Sender quality out is 0. { // Clear the reserve of the sender, possibly delete the line! - adjustOwnerCount( - view, view.peek(keylet::account(uSenderID)), -1, j); + adjustOwnerCount(view, view.peek(keylet::account(uSenderID)), -1, j); // Clear reserve flag. - sleRippleState->setFieldU32( - sfFlags, - uFlags & (!bSenderHigh ? ~lsfLowReserve : ~lsfHighReserve)); + sleRippleState->setFieldU32(sfFlags, uFlags & (!bSenderHigh ? ~lsfLowReserve : ~lsfHighReserve)); // Balance is zero, receiver reserve is clear. bDelete = !saBalance // Balance is zero. @@ -2067,11 +1808,7 @@ rippleCreditIOU( if (bDelete) { return trustDelete( - view, - sleRippleState, - bSenderHigh ? uReceiverID : uSenderID, - !bSenderHigh ? uReceiverID : uSenderID, - j); + view, sleRippleState, bSenderHigh ? uReceiverID : uSenderID, !bSenderHigh ? uReceiverID : uSenderID, j); } view.update(sleRippleState); @@ -2085,8 +1822,7 @@ rippleCreditIOU( JLOG(j.debug()) << "rippleCreditIOU: " "create line: " - << to_string(uSenderID) << " -> " << to_string(uReceiverID) - << " : " << saAmount.getFullText(); + << to_string(uSenderID) << " -> " << to_string(uReceiverID) << " : " << saAmount.getFullText(); auto const sleAccount = view.peek(keylet::account(uReceiverID)); if (!sleAccount) @@ -2127,18 +1863,13 @@ rippleSendIOU( { auto const& issuer = saAmount.getIssuer(); - XRPL_ASSERT( - !isXRP(uSenderID) && !isXRP(uReceiverID), - "xrpl::rippleSendIOU : neither sender nor receiver is XRP"); - XRPL_ASSERT( - uSenderID != uReceiverID, - "xrpl::rippleSendIOU : sender is not receiver"); + XRPL_ASSERT(!isXRP(uSenderID) && !isXRP(uReceiverID), "xrpl::rippleSendIOU : neither sender nor receiver is XRP"); + XRPL_ASSERT(uSenderID != uReceiverID, "xrpl::rippleSendIOU : sender is not receiver"); if (uSenderID == issuer || uReceiverID == issuer || issuer == noAccount()) { // Direct send: redeeming IOUs and/or sending own IOUs. - auto const ter = - rippleCreditIOU(view, uSenderID, uReceiverID, saAmount, false, j); + auto const ter = rippleCreditIOU(view, uSenderID, uReceiverID, saAmount, false, j); if (ter != tesSUCCESS) return ter; saActual = saAmount; @@ -2149,17 +1880,12 @@ rippleSendIOU( // Calculate the amount to transfer accounting // for any transfer fees if the fee is not waived: - saActual = (waiveFee == WaiveTransferFee::Yes) - ? saAmount - : multiply(saAmount, transferRate(view, issuer)); + saActual = (waiveFee == WaiveTransferFee::Yes) ? saAmount : multiply(saAmount, transferRate(view, issuer)); - JLOG(j.debug()) << "rippleSendIOU> " << to_string(uSenderID) << " - > " - << to_string(uReceiverID) - << " : deliver=" << saAmount.getFullText() - << " cost=" << saActual.getFullText(); + JLOG(j.debug()) << "rippleSendIOU> " << to_string(uSenderID) << " - > " << to_string(uReceiverID) + << " : deliver=" << saAmount.getFullText() << " cost=" << saActual.getFullText(); - TER terResult = - rippleCreditIOU(view, issuer, uReceiverID, saAmount, true, j); + TER terResult = rippleCreditIOU(view, issuer, uReceiverID, saAmount, true, j); if (tesSUCCESS == terResult) terResult = rippleCreditIOU(view, uSenderID, issuer, saActual, true, j); @@ -2182,8 +1908,7 @@ rippleSendMultiIOU( { auto const& issuer = issue.getIssuer(); - XRPL_ASSERT( - !isXRP(senderID), "xrpl::rippleSendMultiIOU : sender is not XRP"); + XRPL_ASSERT(!isXRP(senderID), "xrpl::rippleSendMultiIOU : sender is not XRP"); // These may diverge STAmount takeFromSender{issue}; @@ -2201,15 +1926,12 @@ rippleSendMultiIOU( if (!amount || (senderID == receiverID)) continue; - XRPL_ASSERT( - !isXRP(receiverID), - "xrpl::rippleSendMultiIOU : receiver is not XRP"); + XRPL_ASSERT(!isXRP(receiverID), "xrpl::rippleSendMultiIOU : receiver is not XRP"); if (senderID == issuer || receiverID == issuer || issuer == noAccount()) { // Direct send: redeeming IOUs and/or sending own IOUs. - if (auto const ter = rippleCreditIOU( - view, senderID, receiverID, amount, false, j)) + if (auto const ter = rippleCreditIOU(view, senderID, receiverID, amount, false, j)) return ter; actual += amount; // Do not add amount to takeFromSender, because rippleCreditIOU took @@ -2222,26 +1944,21 @@ rippleSendMultiIOU( // Calculate the amount to transfer accounting // for any transfer fees if the fee is not waived: - STAmount actualSend = (waiveFee == WaiveTransferFee::Yes) - ? amount - : multiply(amount, transferRate(view, issuer)); + STAmount actualSend = + (waiveFee == WaiveTransferFee::Yes) ? amount : multiply(amount, transferRate(view, issuer)); actual += actualSend; takeFromSender += actualSend; - JLOG(j.debug()) << "rippleSendMultiIOU> " << to_string(senderID) - << " - > " << to_string(receiverID) - << " : deliver=" << amount.getFullText() - << " cost=" << actual.getFullText(); + JLOG(j.debug()) << "rippleSendMultiIOU> " << to_string(senderID) << " - > " << to_string(receiverID) + << " : deliver=" << amount.getFullText() << " cost=" << actual.getFullText(); - if (TER const terResult = - rippleCreditIOU(view, issuer, receiverID, amount, true, j)) + if (TER const terResult = rippleCreditIOU(view, issuer, receiverID, amount, true, j)) return terResult; } if (senderID != issuer && takeFromSender) { - if (TER const terResult = rippleCreditIOU( - view, senderID, issuer, takeFromSender, true, j)) + if (TER const terResult = rippleCreditIOU(view, senderID, issuer, takeFromSender, true, j)) return terResult; } @@ -2283,12 +2000,10 @@ accountSendIOU( { STAmount saActual; - JLOG(j.trace()) << "accountSendIOU: " << to_string(uSenderID) << " -> " - << to_string(uReceiverID) << " : " + JLOG(j.trace()) << "accountSendIOU: " << to_string(uSenderID) << " -> " << to_string(uReceiverID) << " : " << saAmount.getFullText(); - return rippleSendIOU( - view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee); + return rippleSendIOU(view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee); } /* XRP send which does not check reserve and can do pure adjustment. @@ -2298,12 +2013,8 @@ accountSendIOU( */ TER terResult(tesSUCCESS); - SLE::pointer sender = uSenderID != beast::zero - ? view.peek(keylet::account(uSenderID)) - : SLE::pointer(); - SLE::pointer receiver = uReceiverID != beast::zero - ? view.peek(keylet::account(uReceiverID)) - : SLE::pointer(); + SLE::pointer sender = uSenderID != beast::zero ? view.peek(keylet::account(uSenderID)) : SLE::pointer(); + SLE::pointer receiver = uReceiverID != beast::zero ? view.peek(keylet::account(uReceiverID)) : SLE::pointer(); if (auto stream = j.trace()) { @@ -2316,9 +2027,8 @@ accountSendIOU( if (receiver) receiver_bal = receiver->getFieldAmount(sfBalance).getFullText(); - stream << "accountSendIOU> " << to_string(uSenderID) << " (" - << sender_bal << ") -> " << to_string(uReceiverID) << " (" - << receiver_bal << ") : " << saAmount.getFullText(); + stream << "accountSendIOU> " << to_string(uSenderID) << " (" << sender_bal << ") -> " << to_string(uReceiverID) + << " (" << receiver_bal << ") : " << saAmount.getFullText(); } if (sender) @@ -2328,8 +2038,7 @@ accountSendIOU( // VFALCO Its laborious to have to mutate the // TER based on params everywhere // LCOV_EXCL_START - terResult = view.open() ? TER{telFAILED_PROCESSING} - : TER{tecFAILED_PROCESSING}; + terResult = view.open() ? TER{telFAILED_PROCESSING} : TER{tecFAILED_PROCESSING}; // LCOV_EXCL_STOP } else @@ -2364,9 +2073,8 @@ accountSendIOU( if (receiver) receiver_bal = receiver->getFieldAmount(sfBalance).getFullText(); - stream << "accountSendIOU< " << to_string(uSenderID) << " (" - << sender_bal << ") -> " << to_string(uReceiverID) << " (" - << receiver_bal << ") : " << saAmount.getFullText(); + stream << "accountSendIOU< " << to_string(uSenderID) << " (" << sender_bal << ") -> " << to_string(uReceiverID) + << " (" << receiver_bal << ") : " << saAmount.getFullText(); } return terResult; @@ -2381,19 +2089,14 @@ accountSendMultiIOU( beast::Journal j, WaiveTransferFee waiveFee) { - XRPL_ASSERT_PARTS( - receivers.size() > 1, - "xrpl::accountSendMultiIOU", - "multiple recipients provided"); + XRPL_ASSERT_PARTS(receivers.size() > 1, "xrpl::accountSendMultiIOU", "multiple recipients provided"); if (!issue.native()) { STAmount actual; - JLOG(j.trace()) << "accountSendMultiIOU: " << to_string(senderID) - << " sending " << receivers.size() << " IOUs"; + JLOG(j.trace()) << "accountSendMultiIOU: " << to_string(senderID) << " sending " << receivers.size() << " IOUs"; - return rippleSendMultiIOU( - view, senderID, issue, receivers, actual, j, waiveFee); + return rippleSendMultiIOU(view, senderID, issue, receivers, actual, j, waiveFee); } /* XRP send which does not check reserve and can do pure adjustment. @@ -2402,9 +2105,7 @@ accountSendMultiIOU( * ensure that transfers are balanced. */ - SLE::pointer sender = senderID != beast::zero - ? view.peek(keylet::account(senderID)) - : SLE::pointer(); + SLE::pointer sender = senderID != beast::zero ? view.peek(keylet::account(senderID)) : SLE::pointer(); if (auto stream = j.trace()) { @@ -2413,8 +2114,8 @@ accountSendMultiIOU( if (sender) sender_bal = sender->getFieldAmount(sfBalance).getFullText(); - stream << "accountSendMultiIOU> " << to_string(senderID) << " (" - << sender_bal << ") -> " << receivers.size() << " receivers."; + stream << "accountSendMultiIOU> " << to_string(senderID) << " (" << sender_bal << ") -> " << receivers.size() + << " receivers."; } // Failures return immediately. @@ -2435,21 +2136,17 @@ accountSendMultiIOU( if (!amount || (senderID == receiverID)) continue; - SLE::pointer receiver = receiverID != beast::zero - ? view.peek(keylet::account(receiverID)) - : SLE::pointer(); + SLE::pointer receiver = receiverID != beast::zero ? view.peek(keylet::account(receiverID)) : SLE::pointer(); if (auto stream = j.trace()) { std::string receiver_bal("-"); if (receiver) - receiver_bal = - receiver->getFieldAmount(sfBalance).getFullText(); + receiver_bal = receiver->getFieldAmount(sfBalance).getFullText(); - stream << "accountSendMultiIOU> " << to_string(senderID) << " -> " - << to_string(receiverID) << " (" << receiver_bal - << ") : " << amount.getFullText(); + stream << "accountSendMultiIOU> " << to_string(senderID) << " -> " << to_string(receiverID) << " (" + << receiver_bal << ") : " << amount.getFullText(); } if (receiver) @@ -2470,12 +2167,10 @@ accountSendMultiIOU( std::string receiver_bal("-"); if (receiver) - receiver_bal = - receiver->getFieldAmount(sfBalance).getFullText(); + receiver_bal = receiver->getFieldAmount(sfBalance).getFullText(); - stream << "accountSendMultiIOU< " << to_string(senderID) << " -> " - << to_string(receiverID) << " (" << receiver_bal - << ") : " << amount.getFullText(); + stream << "accountSendMultiIOU< " << to_string(senderID) << " -> " << to_string(receiverID) << " (" + << receiver_bal << ") : " << amount.getFullText(); } } @@ -2504,8 +2199,8 @@ accountSendMultiIOU( if (sender) sender_bal = sender->getFieldAmount(sfBalance).getFullText(); - stream << "accountSendMultiIOU< " << to_string(senderID) << " (" - << sender_bal << ") -> " << receivers.size() << " receivers."; + stream << "accountSendMultiIOU< " << to_string(senderID) << " (" << sender_bal << ") -> " << receivers.size() + << " receivers."; } return tesSUCCESS; } @@ -2582,15 +2277,12 @@ rippleSendMPT( beast::Journal j, WaiveTransferFee waiveFee) { - XRPL_ASSERT( - uSenderID != uReceiverID, - "xrpl::rippleSendMPT : sender is not receiver"); + XRPL_ASSERT(uSenderID != uReceiverID, "xrpl::rippleSendMPT : sender is not receiver"); // Safe to get MPT since rippleSendMPT is only called by accountSendMPT auto const& issuer = saAmount.getIssuer(); - auto const sle = - view.read(keylet::mptIssuance(saAmount.get().getMptID())); + auto const sle = view.read(keylet::mptIssuance(saAmount.get().getMptID())); if (!sle) return tecOBJECT_NOT_FOUND; @@ -2601,17 +2293,13 @@ rippleSendMPT( if (uSenderID == issuer) { auto const sendAmount = saAmount.mpt().value(); - auto const maximumAmount = - sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount); - if (sendAmount > maximumAmount || - sle->getFieldU64(sfOutstandingAmount) > - maximumAmount - sendAmount) + auto const maximumAmount = sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount); + if (sendAmount > maximumAmount || sle->getFieldU64(sfOutstandingAmount) > maximumAmount - sendAmount) return tecPATH_DRY; } // Direct send: redeeming MPTs and/or sending own MPTs. - auto const ter = - rippleCreditMPT(view, uSenderID, uReceiverID, saAmount, j); + auto const ter = rippleCreditMPT(view, uSenderID, uReceiverID, saAmount, j); if (ter != tesSUCCESS) return ter; saActual = saAmount; @@ -2621,18 +2309,12 @@ rippleSendMPT( // Sending 3rd party MPTs: transit. saActual = (waiveFee == WaiveTransferFee::Yes) ? saAmount - : multiply( - saAmount, - transferRate(view, saAmount.get().getMptID())); + : multiply(saAmount, transferRate(view, saAmount.get().getMptID())); - JLOG(j.debug()) << "rippleSendMPT> " << to_string(uSenderID) << " - > " - << to_string(uReceiverID) - << " : deliver=" << saAmount.getFullText() - << " cost=" << saActual.getFullText(); + JLOG(j.debug()) << "rippleSendMPT> " << to_string(uSenderID) << " - > " << to_string(uReceiverID) + << " : deliver=" << saAmount.getFullText() << " cost=" << saActual.getFullText(); - if (auto const terResult = - rippleCreditMPT(view, issuer, uReceiverID, saAmount, j); - terResult != tesSUCCESS) + if (auto const terResult = rippleCreditMPT(view, issuer, uReceiverID, saAmount, j); terResult != tesSUCCESS) return terResult; return rippleCreditMPT(view, uSenderID, issuer, saActual, j); @@ -2687,17 +2369,13 @@ rippleSendMultiMPT( "rippler::rippleSendMultiMPT", "sender == issuer, takeFromSender == zero"); auto const sendAmount = amount.mpt().value(); - auto const maximumAmount = - sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount); - if (sendAmount > maximumAmount || - sle->getFieldU64(sfOutstandingAmount) > - maximumAmount - sendAmount) + auto const maximumAmount = sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount); + if (sendAmount > maximumAmount || sle->getFieldU64(sfOutstandingAmount) > maximumAmount - sendAmount) return tecPATH_DRY; } // Direct send: redeeming MPTs and/or sending own MPTs. - if (auto const ter = - rippleCreditMPT(view, senderID, receiverID, amount, j)) + if (auto const ter = rippleCreditMPT(view, senderID, receiverID, amount, j)) return ter; actual += amount; // Do not add amount to takeFromSender, because rippleCreditMPT took @@ -2709,25 +2387,19 @@ rippleSendMultiMPT( // Sending 3rd party MPTs: transit. STAmount actualSend = (waiveFee == WaiveTransferFee::Yes) ? amount - : multiply( - amount, - transferRate(view, amount.get().getMptID())); + : multiply(amount, transferRate(view, amount.get().getMptID())); actual += actualSend; takeFromSender += actualSend; - JLOG(j.debug()) << "rippleSendMultiMPT> " << to_string(senderID) - << " - > " << to_string(receiverID) - << " : deliver=" << amount.getFullText() - << " cost=" << actualSend.getFullText(); + JLOG(j.debug()) << "rippleSendMultiMPT> " << to_string(senderID) << " - > " << to_string(receiverID) + << " : deliver=" << amount.getFullText() << " cost=" << actualSend.getFullText(); - if (auto const terResult = - rippleCreditMPT(view, issuer, receiverID, amount, j)) + if (auto const terResult = rippleCreditMPT(view, issuer, receiverID, amount, j)) return terResult; } if (senderID != issuer && takeFromSender) { - if (TER const terResult = - rippleCreditMPT(view, senderID, issuer, takeFromSender, j)) + if (TER const terResult = rippleCreditMPT(view, senderID, issuer, takeFromSender, j)) return terResult; } @@ -2743,9 +2415,7 @@ accountSendMPT( beast::Journal j, WaiveTransferFee waiveFee) { - XRPL_ASSERT( - saAmount >= beast::zero && saAmount.holds(), - "xrpl::accountSendMPT : minimum amount and MPT"); + XRPL_ASSERT(saAmount >= beast::zero && saAmount.holds(), "xrpl::accountSendMPT : minimum amount and MPT"); /* If we aren't sending anything or if the sender is the same as the * receiver then we don't need to do anything. @@ -2755,8 +2425,7 @@ accountSendMPT( STAmount saActual{saAmount.asset()}; - return rippleSendMPT( - view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee); + return rippleSendMPT(view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee); } static TER @@ -2770,8 +2439,7 @@ accountSendMultiMPT( { STAmount actual; - return rippleSendMultiMPT( - view, senderID, mptIssue, receivers, actual, j, waiveFee); + return rippleSendMultiMPT(view, senderID, mptIssue, receivers, actual, j, waiveFee); } TER @@ -2786,11 +2454,9 @@ accountSend( return std::visit( [&](TIss const& issue) { if constexpr (std::is_same_v) - return accountSendIOU( - view, uSenderID, uReceiverID, saAmount, j, waiveFee); + return accountSendIOU(view, uSenderID, uReceiverID, saAmount, j, waiveFee); else - return accountSendMPT( - view, uSenderID, uReceiverID, saAmount, j, waiveFee); + return accountSendMPT(view, uSenderID, uReceiverID, saAmount, j, waiveFee); }, saAmount.asset().value()); } @@ -2804,18 +2470,13 @@ accountSendMulti( beast::Journal j, WaiveTransferFee waiveFee) { - XRPL_ASSERT_PARTS( - receivers.size() > 1, - "xrpl::accountSendMulti", - "multiple recipients provided"); + XRPL_ASSERT_PARTS(receivers.size() > 1, "xrpl::accountSendMulti", "multiple recipients provided"); return std::visit( [&](TIss const& issue) { if constexpr (std::is_same_v) - return accountSendMultiIOU( - view, senderID, issue, receivers, j, waiveFee); + return accountSendMultiIOU(view, senderID, issue, receivers, j, waiveFee); else - return accountSendMultiMPT( - view, senderID, issue, receivers, j, waiveFee); + return accountSendMultiMPT(view, senderID, issue, receivers, j, waiveFee); }, asset.value()); } @@ -2845,16 +2506,14 @@ updateTrustLine( // Sender is zero or negative. && (flags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) // Sender reserve is set. - && static_cast( - flags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) != + && static_cast(flags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) != static_cast(sle->getFlags() & lsfDefaultRipple) && !(flags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) && !state->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit) // Sender trust limit is 0. && !state->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn) // Sender quality in is 0. - && - !state->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut)) + && !state->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut)) // Sender quality out is 0. { // VFALCO Where is the line being deleted? @@ -2862,8 +2521,7 @@ updateTrustLine( adjustOwnerCount(view, sle, -1, j); // Clear reserve flag. - state->setFieldU32( - sfFlags, flags & (!bSenderHigh ? ~lsfLowReserve : ~lsfHighReserve)); + state->setFieldU32(sfFlags, flags & (!bSenderHigh ? ~lsfLowReserve : ~lsfHighReserve)); // Balance is zero, receiver reserve is clear. if (!after // Balance is zero. @@ -2874,26 +2532,17 @@ updateTrustLine( } TER -issueIOU( - ApplyView& view, - AccountID const& account, - STAmount const& amount, - Issue const& issue, - beast::Journal j) +issueIOU(ApplyView& view, AccountID const& account, STAmount const& amount, Issue const& issue, beast::Journal j) { - XRPL_ASSERT( - !isXRP(account) && !isXRP(issue.account), - "xrpl::issueIOU : neither account nor issuer is XRP"); + XRPL_ASSERT(!isXRP(account) && !isXRP(issue.account), "xrpl::issueIOU : neither account nor issuer is XRP"); // Consistency check XRPL_ASSERT(issue == amount.issue(), "xrpl::issueIOU : matching issue"); // Can't send to self! - XRPL_ASSERT( - issue.account != account, "xrpl::issueIOU : not issuer account"); + XRPL_ASSERT(issue.account != account, "xrpl::issueIOU : not issuer account"); - JLOG(j.trace()) << "issueIOU: " << to_string(account) << ": " - << amount.getFullText(); + JLOG(j.trace()) << "issueIOU: " << to_string(account) << ": " << amount.getFullText(); bool bSenderHigh = issue.account > account; @@ -2910,14 +2559,8 @@ issueIOU( final_balance -= amount; - auto const must_delete = updateTrustLine( - view, - state, - bSenderHigh, - issue.account, - start_balance, - final_balance, - j); + auto const must_delete = + updateTrustLine(view, state, bSenderHigh, issue.account, start_balance, final_balance, j); view.creditHook(issue.account, account, amount, start_balance); @@ -2930,11 +2573,7 @@ issueIOU( state->setFieldAmount(sfBalance, final_balance); if (must_delete) return trustDelete( - view, - state, - bSenderHigh ? account : issue.account, - bSenderHigh ? issue.account : account, - j); + view, state, bSenderHigh ? account : issue.account, bSenderHigh ? issue.account : account, j); view.update(state); @@ -2974,31 +2613,21 @@ issueIOU( } TER -redeemIOU( - ApplyView& view, - AccountID const& account, - STAmount const& amount, - Issue const& issue, - beast::Journal j) +redeemIOU(ApplyView& view, AccountID const& account, STAmount const& amount, Issue const& issue, beast::Journal j) { - XRPL_ASSERT( - !isXRP(account) && !isXRP(issue.account), - "xrpl::redeemIOU : neither account nor issuer is XRP"); + XRPL_ASSERT(!isXRP(account) && !isXRP(issue.account), "xrpl::redeemIOU : neither account nor issuer is XRP"); // Consistency check XRPL_ASSERT(issue == amount.issue(), "xrpl::redeemIOU : matching issue"); // Can't send to self! - XRPL_ASSERT( - issue.account != account, "xrpl::redeemIOU : not issuer account"); + XRPL_ASSERT(issue.account != account, "xrpl::redeemIOU : not issuer account"); - JLOG(j.trace()) << "redeemIOU: " << to_string(account) << ": " - << amount.getFullText(); + JLOG(j.trace()) << "redeemIOU: " << to_string(account) << ": " << amount.getFullText(); bool bSenderHigh = account > issue.account; - if (auto state = - view.peek(keylet::line(account, issue.account, issue.currency))) + if (auto state = view.peek(keylet::line(account, issue.account, issue.currency))) { STAmount final_balance = state->getFieldAmount(sfBalance); @@ -3009,8 +2638,7 @@ redeemIOU( final_balance -= amount; - auto const must_delete = updateTrustLine( - view, state, bSenderHigh, account, start_balance, final_balance, j); + auto const must_delete = updateTrustLine(view, state, bSenderHigh, account, start_balance, final_balance, j); view.creditHook(account, issue.account, amount, start_balance); @@ -3025,11 +2653,7 @@ redeemIOU( if (must_delete) { return trustDelete( - view, - state, - bSenderHigh ? issue.account : account, - bSenderHigh ? account : issue.account, - j); + view, state, bSenderHigh ? issue.account : account, bSenderHigh ? account : issue.account, j); } view.update(state); @@ -3040,8 +2664,7 @@ redeemIOU( // balance. If it doesn't, then something is very wrong. Don't try // to continue. // LCOV_EXCL_START - JLOG(j.fatal()) << "redeemIOU: " << to_string(account) - << " attempts to redeem " << amount.getFullText() + JLOG(j.fatal()) << "redeemIOU: " << to_string(account) << " attempts to redeem " << amount.getFullText() << " but no trust line exists!"; return tefINTERNAL; @@ -3049,15 +2672,9 @@ redeemIOU( } TER -transferXRP( - ApplyView& view, - AccountID const& from, - AccountID const& to, - STAmount const& amount, - beast::Journal j) +transferXRP(ApplyView& view, AccountID const& from, AccountID const& to, STAmount const& amount, beast::Journal j) { - XRPL_ASSERT( - from != beast::zero, "xrpl::transferXRP : nonzero from account"); + XRPL_ASSERT(from != beast::zero, "xrpl::transferXRP : nonzero from account"); XRPL_ASSERT(to != beast::zero, "xrpl::transferXRP : nonzero to account"); XRPL_ASSERT(from != to, "xrpl::transferXRP : sender is not receiver"); XRPL_ASSERT(amount.native(), "xrpl::transferXRP : amount is XRP"); @@ -3067,8 +2684,7 @@ transferXRP( if (!sender || !receiver) return tefINTERNAL; // LCOV_EXCL_LINE - JLOG(j.trace()) << "transferXRP: " << to_string(from) << " -> " - << to_string(to) << ") : " << amount.getFullText(); + JLOG(j.trace()) << "transferXRP: " << to_string(from) << " -> " << to_string(to) << ") : " << amount.getFullText(); if (sender->getFieldAmount(sfBalance) < amount) { @@ -3076,35 +2692,27 @@ transferXRP( // mutating these TER everywhere // FIXME: this logic should be moved to callers maybe? // LCOV_EXCL_START - return view.open() ? TER{telFAILED_PROCESSING} - : TER{tecFAILED_PROCESSING}; + return view.open() ? TER{telFAILED_PROCESSING} : TER{tecFAILED_PROCESSING}; // LCOV_EXCL_STOP } // Decrement XRP balance. - sender->setFieldAmount( - sfBalance, sender->getFieldAmount(sfBalance) - amount); + sender->setFieldAmount(sfBalance, sender->getFieldAmount(sfBalance) - amount); view.update(sender); - receiver->setFieldAmount( - sfBalance, receiver->getFieldAmount(sfBalance) + amount); + receiver->setFieldAmount(sfBalance, receiver->getFieldAmount(sfBalance) + amount); view.update(receiver); return tesSUCCESS; } TER -requireAuth( - ReadView const& view, - Issue const& issue, - AccountID const& account, - AuthType authType) +requireAuth(ReadView const& view, Issue const& issue, AccountID const& account, AuthType authType) { if (isXRP(issue) || issue.account == account) return tesSUCCESS; - auto const trustLine = - view.read(keylet::line(account, issue.account, issue.currency)); + auto const trustLine = view.read(keylet::line(account, issue.account, issue.currency)); // If account has no line, and this is a strong check, fail if (!trustLine && authType == AuthType::StrongAuth) return tecNO_LINE; @@ -3115,10 +2723,8 @@ requireAuth( issuerAccount && (*issuerAccount)[sfFlags] & lsfRequireAuth) { if (trustLine) - return ((*trustLine)[sfFlags] & - ((account > issue.account) ? lsfLowAuth : lsfHighAuth)) - ? tesSUCCESS - : TER{tecNO_AUTH}; + return ((*trustLine)[sfFlags] & ((account > issue.account) ? lsfLowAuth : lsfHighAuth)) ? tesSUCCESS + : TER{tecNO_AUTH}; return TER{tecNO_LINE}; } @@ -3126,12 +2732,7 @@ requireAuth( } TER -requireAuth( - ReadView const& view, - MPTIssue const& mptIssue, - AccountID const& account, - AuthType authType, - int depth) +requireAuth(ReadView const& view, MPTIssue const& mptIssue, AccountID const& account, AuthType authType, int depth) { auto const mptID = keylet::mptIssuance(mptIssue.getMptID()); auto const sleIssuance = view.read(mptID); @@ -3144,8 +2745,7 @@ requireAuth( if (mptIssuer == account) // Issuer won't have MPToken return tesSUCCESS; - bool const featureSAVEnabled = - view.rules().enabled(featureSingleAssetVault); + bool const featureSAVEnabled = view.rules().enabled(featureSingleAssetVault); if (featureSAVEnabled) { @@ -3159,8 +2759,7 @@ requireAuth( if (sleIssuer->isFieldPresent(sfVaultID)) { - auto const sleVault = - view.read(keylet::vault(sleIssuer->getFieldH256(sfVaultID))); + auto const sleVault = view.read(keylet::vault(sleIssuer->getFieldH256(sfVaultID))); if (!sleVault) return tefINTERNAL; // LCOV_EXCL_LINE @@ -3170,8 +2769,7 @@ requireAuth( if constexpr (std::is_same_v) return requireAuth(view, issue, account, authType); else - return requireAuth( - view, issue, account, authType, depth + 1); + return requireAuth(view, issue, account, authType, depth + 1); }, asset.value()); !isTesSuccess(err)) @@ -3183,8 +2781,7 @@ requireAuth( auto const sleToken = view.read(mptokenID); // if account has no MPToken, fail - if (!sleToken && - (authType == AuthType::StrongAuth || authType == AuthType::Legacy)) + if (!sleToken && (authType == AuthType::StrongAuth || authType == AuthType::Legacy)) return tecNO_AUTH; // Note, this check is not amendment-gated because DomainID will be always @@ -3196,9 +2793,7 @@ requireAuth( sleIssuance->getFieldU32(sfFlags) & lsfMPTRequireAuth, "xrpl::requireAuth : issuance requires authorization"); // ter = tefINTERNAL | tecOBJECT_NOT_FOUND | tecNO_AUTH | tecEXPIRED - if (auto const ter = - credentials::validDomain(view, *maybeDomainID, account); - isTesSuccess(ter)) + if (auto const ter = credentials::validDomain(view, *maybeDomainID, account); isTesSuccess(ter)) return ter; // Note: sleToken might be null else if (!sleToken) return ter; @@ -3214,8 +2809,7 @@ requireAuth( } // mptoken must be authorized if issuance enabled requireAuth - if (sleIssuance->isFlag(lsfMPTRequireAuth) && - (!sleToken || !sleToken->isFlag(lsfMPTAuthorized))) + if (sleIssuance->isFlag(lsfMPTRequireAuth) && (!sleToken || !sleToken->isFlag(lsfMPTAuthorized))) return tecNO_AUTH; return tesSUCCESS; // Note: sleToken might be null @@ -3233,9 +2827,7 @@ enforceMPTokenAuthorization( if (!sleIssuance) return tefINTERNAL; // LCOV_EXCL_LINE - XRPL_ASSERT( - sleIssuance->isFlag(lsfMPTRequireAuth), - "xrpl::enforceMPTokenAuthorization : authorization required"); + XRPL_ASSERT(sleIssuance->isFlag(lsfMPTRequireAuth), "xrpl::enforceMPTokenAuthorization : authorization required"); if (account == sleIssuance->at(sfIssuer)) return tefINTERNAL; // LCOV_EXCL_LINE @@ -3280,8 +2872,7 @@ enforceMPTokenAuthorization( // We found an MPToken, but sfDomainID is not set, so this is a classic // MPToken which requires authorization by the token issuer. XRPL_ASSERT( - sleToken != nullptr && !maybeDomainID.has_value(), - "xrpl::enforceMPTokenAuthorization : found MPToken"); + sleToken != nullptr && !maybeDomainID.has_value(), "xrpl::enforceMPTokenAuthorization : found MPToken"); if (sleToken->isFlag(lsfMPTAuthorized)) return tesSUCCESS; @@ -3291,9 +2882,7 @@ enforceMPTokenAuthorization( { // Found an MPToken, authorized by the domain. Ignore authorization flag // lsfMPTAuthorized because it is meaningless. Return tesSUCCESS - XRPL_ASSERT( - maybeDomainID.has_value(), - "xrpl::enforceMPTokenAuthorization : found MPToken for domain"); + XRPL_ASSERT(maybeDomainID.has_value(), "xrpl::enforceMPTokenAuthorization : found MPToken for domain"); return tesSUCCESS; } else if (authorizedByDomain) @@ -3316,18 +2905,13 @@ enforceMPTokenAuthorization( } // LCOV_EXCL_START - UNREACHABLE( - "xrpl::enforceMPTokenAuthorization : condition list is incomplete"); + UNREACHABLE("xrpl::enforceMPTokenAuthorization : condition list is incomplete"); return tefINTERNAL; // LCOV_EXCL_STOP } TER -canTransfer( - ReadView const& view, - MPTIssue const& mptIssue, - AccountID const& from, - AccountID const& to) +canTransfer(ReadView const& view, MPTIssue const& mptIssue, AccountID const& from, AccountID const& to) { auto const mptID = keylet::mptIssuance(mptIssue.getMptID()); auto const sleIssuance = view.read(mptID); @@ -3343,11 +2927,7 @@ canTransfer( } [[nodiscard]] TER -canTransfer( - ReadView const& view, - Issue const& issue, - AccountID const& from, - AccountID const& to) +canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, AccountID const& to) { if (issue.native()) return tesSUCCESS; @@ -3392,8 +2972,7 @@ cleanupOnAccountDelete( uint256 dirEntry{beast::zero}; std::uint32_t deleted = 0; - if (view.exists(ownerDirKeylet) && - dirFirst(view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry)) + if (view.exists(ownerDirKeylet) && dirFirst(view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry)) { do { @@ -3406,16 +2985,13 @@ cleanupOnAccountDelete( { // Directory node has an invalid index. Bail out. // LCOV_EXCL_START - JLOG(j.fatal()) - << "DeleteAccount: Directory node in ledger " << view.seq() - << " has index to object that is missing: " - << to_string(dirEntry); + JLOG(j.fatal()) << "DeleteAccount: Directory node in ledger " << view.seq() + << " has index to object that is missing: " << to_string(dirEntry); return tefBAD_LEDGER; // LCOV_EXCL_STOP } - LedgerEntryType const nodeType{safe_cast( - sleItem->getFieldU16(sfLedgerEntryType))}; + LedgerEntryType const nodeType{safe_cast(sleItem->getFieldU16(sfLedgerEntryType))}; // Deleter handles the details of specific account-owned object // deletion @@ -3439,22 +3015,18 @@ cleanupOnAccountDelete( // // 3. So we verify that uDirEntry is indeed 'it'+1. Then we jam it // back to 'it' to "un-invalidate" the iterator. - XRPL_ASSERT( - uDirEntry >= 1, - "xrpl::cleanupOnAccountDelete : minimum dir entries"); + XRPL_ASSERT(uDirEntry >= 1, "xrpl::cleanupOnAccountDelete : minimum dir entries"); if (uDirEntry == 0) { // LCOV_EXCL_START - JLOG(j.error()) - << "DeleteAccount iterator re-validation failed."; + JLOG(j.error()) << "DeleteAccount iterator re-validation failed."; return tefBAD_LEDGER; // LCOV_EXCL_STOP } if (skipEntry == SkipEntry::No) uDirEntry--; - } while ( - dirNext(view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry)); + } while (dirNext(view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry)); } return tesSUCCESS; @@ -3471,8 +3043,7 @@ deleteAMMTrustLine( return tecINTERNAL; // LCOV_EXCL_LINE auto const& [low, high] = std::minmax( - sleState->getFieldAmount(sfLowLimit).getIssuer(), - sleState->getFieldAmount(sfHighLimit).getIssuer()); + sleState->getFieldAmount(sfLowLimit).getIssuer(), sleState->getFieldAmount(sfHighLimit).getIssuer()); auto sleLow = view.peek(keylet::account(low)); auto sleHigh = view.peek(keylet::account(high)); if (!sleLow || !sleHigh) @@ -3493,11 +3064,9 @@ deleteAMMTrustLine( if (ammAccountID && (low != *ammAccountID && high != *ammAccountID)) return terNO_AMM; - if (auto const ter = trustDelete(view, sleState, low, high, j); - ter != tesSUCCESS) + if (auto const ter = trustDelete(view, sleState, low, high, j); ter != tesSUCCESS) { - JLOG(j.error()) - << "deleteAMMTrustLine: failed to delete the trustline."; + JLOG(j.error()) << "deleteAMMTrustLine: failed to delete the trustline."; return ter; } @@ -3523,15 +3092,12 @@ rippleCredit( [&](TIss const& issue) { if constexpr (std::is_same_v) { - return rippleCreditIOU( - view, uSenderID, uReceiverID, saAmount, bCheckIssuer, j); + return rippleCreditIOU(view, uSenderID, uReceiverID, saAmount, bCheckIssuer, j); } else { - XRPL_ASSERT( - !bCheckIssuer, "xrpl::rippleCredit : not checking issuer"); - return rippleCreditMPT( - view, uSenderID, uReceiverID, saAmount, j); + XRPL_ASSERT(!bCheckIssuer, "xrpl::rippleCredit : not checking issuer"); + return rippleCreditMPT(view, uSenderID, uReceiverID, saAmount, j); } }, saAmount.asset().value()); @@ -3543,22 +3109,15 @@ assetsToSharesDeposit( std::shared_ptr const& issuance, STAmount const& assets) { - XRPL_ASSERT( - !assets.negative(), - "xrpl::assetsToSharesDeposit : non-negative assets"); - XRPL_ASSERT( - assets.asset() == vault->at(sfAsset), - "xrpl::assetsToSharesDeposit : assets and vault match"); + XRPL_ASSERT(!assets.negative(), "xrpl::assetsToSharesDeposit : non-negative assets"); + XRPL_ASSERT(assets.asset() == vault->at(sfAsset), "xrpl::assetsToSharesDeposit : assets and vault match"); if (assets.negative() || assets.asset() != vault->at(sfAsset)) return std::nullopt; // LCOV_EXCL_LINE Number const assetTotal = vault->at(sfAssetsTotal); STAmount shares{vault->at(sfShareMPTID)}; if (assetTotal == 0) - return STAmount{ - shares.asset(), - Number(assets.mantissa(), assets.exponent() + vault->at(sfScale)) - .truncate()}; + return STAmount{shares.asset(), Number(assets.mantissa(), assets.exponent() + vault->at(sfScale)).truncate()}; Number const shareTotal = issuance->at(sfOutstandingAmount); shares = ((shareTotal * assets) / assetTotal).truncate(); @@ -3571,23 +3130,15 @@ sharesToAssetsDeposit( std::shared_ptr const& issuance, STAmount const& shares) { - XRPL_ASSERT( - !shares.negative(), - "xrpl::sharesToAssetsDeposit : non-negative shares"); - XRPL_ASSERT( - shares.asset() == vault->at(sfShareMPTID), - "xrpl::sharesToAssetsDeposit : shares and vault match"); + XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares"); + XRPL_ASSERT(shares.asset() == vault->at(sfShareMPTID), "xrpl::sharesToAssetsDeposit : shares and vault match"); if (shares.negative() || shares.asset() != vault->at(sfShareMPTID)) return std::nullopt; // LCOV_EXCL_LINE Number const assetTotal = vault->at(sfAssetsTotal); STAmount assets{vault->at(sfAsset)}; if (assetTotal == 0) - return STAmount{ - assets.asset(), - shares.mantissa(), - shares.exponent() - vault->at(sfScale), - false}; + return STAmount{assets.asset(), shares.mantissa(), shares.exponent() - vault->at(sfScale), false}; Number const shareTotal = issuance->at(sfOutstandingAmount); assets = (assetTotal * shares) / shareTotal; @@ -3601,12 +3152,8 @@ assetsToSharesWithdraw( STAmount const& assets, TruncateShares truncate) { - XRPL_ASSERT( - !assets.negative(), - "xrpl::assetsToSharesDeposit : non-negative assets"); - XRPL_ASSERT( - assets.asset() == vault->at(sfAsset), - "xrpl::assetsToSharesWithdraw : assets and vault match"); + XRPL_ASSERT(!assets.negative(), "xrpl::assetsToSharesDeposit : non-negative assets"); + XRPL_ASSERT(assets.asset() == vault->at(sfAsset), "xrpl::assetsToSharesWithdraw : assets and vault match"); if (assets.negative() || assets.asset() != vault->at(sfAsset)) return std::nullopt; // LCOV_EXCL_LINE @@ -3629,12 +3176,8 @@ sharesToAssetsWithdraw( std::shared_ptr const& issuance, STAmount const& shares) { - XRPL_ASSERT( - !shares.negative(), - "xrpl::sharesToAssetsDeposit : non-negative shares"); - XRPL_ASSERT( - shares.asset() == vault->at(sfShareMPTID), - "xrpl::sharesToAssetsWithdraw : shares and vault match"); + XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares"); + XRPL_ASSERT(shares.asset() == vault->at(sfShareMPTID), "xrpl::sharesToAssetsWithdraw : shares and vault match"); if (shares.negative() || shares.asset() != vault->at(sfShareMPTID)) return std::nullopt; // LCOV_EXCL_LINE @@ -3649,26 +3192,20 @@ sharesToAssetsWithdraw( } TER -rippleLockEscrowMPT( - ApplyView& view, - AccountID const& sender, - STAmount const& amount, - beast::Journal j) +rippleLockEscrowMPT(ApplyView& view, AccountID const& sender, STAmount const& amount, beast::Journal j) { auto const mptIssue = amount.get(); auto const mptID = keylet::mptIssuance(mptIssue.getMptID()); auto sleIssuance = view.peek(mptID); if (!sleIssuance) { // LCOV_EXCL_START - JLOG(j.error()) << "rippleLockEscrowMPT: MPT issuance not found for " - << mptIssue.getMptID(); + JLOG(j.error()) << "rippleLockEscrowMPT: MPT issuance not found for " << mptIssue.getMptID(); return tecOBJECT_NOT_FOUND; } // LCOV_EXCL_STOP if (amount.getIssuer() == sender) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleLockEscrowMPT: sender is the issuer, cannot lock MPTs."; + JLOG(j.error()) << "rippleLockEscrowMPT: sender is the issuer, cannot lock MPTs."; return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3679,8 +3216,7 @@ rippleLockEscrowMPT( auto sle = view.peek(mptokenID); if (!sle) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleLockEscrowMPT: MPToken not found for " << sender; + JLOG(j.error()) << "rippleLockEscrowMPT: MPToken not found for " << sender; return tecOBJECT_NOT_FOUND; } // LCOV_EXCL_STOP @@ -3690,9 +3226,8 @@ rippleLockEscrowMPT( // Underflow check for subtraction if (!canSubtract(STAmount(mptIssue, amt), STAmount(mptIssue, pay))) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleLockEscrowMPT: insufficient MPTAmount for " - << to_string(sender) << ": " << amt << " < " << pay; + JLOG(j.error()) << "rippleLockEscrowMPT: insufficient MPTAmount for " << to_string(sender) << ": " << amt + << " < " << pay; return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3703,9 +3238,8 @@ rippleLockEscrowMPT( if (!canAdd(STAmount(mptIssue, locked), STAmount(mptIssue, pay))) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleLockEscrowMPT: overflow on locked amount for " - << to_string(sender) << ": " << locked << " + " << pay; + JLOG(j.error()) << "rippleLockEscrowMPT: overflow on locked amount for " << to_string(sender) << ": " + << locked << " + " << pay; return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3720,18 +3254,15 @@ rippleLockEscrowMPT( // 1. Increase the Issuance EscrowedAmount // 2. DO NOT change the Issuance OutstandingAmount { - uint64_t const issuanceEscrowed = - (*sleIssuance)[~sfLockedAmount].value_or(0); + uint64_t const issuanceEscrowed = (*sleIssuance)[~sfLockedAmount].value_or(0); auto const pay = amount.mpt().value(); // Overflow check for addition - if (!canAdd( - STAmount(mptIssue, issuanceEscrowed), STAmount(mptIssue, pay))) + if (!canAdd(STAmount(mptIssue, issuanceEscrowed), STAmount(mptIssue, pay))) { // LCOV_EXCL_START JLOG(j.error()) << "rippleLockEscrowMPT: overflow on issuance " "locked amount for " - << mptIssue.getMptID() << ": " << issuanceEscrowed - << " + " << pay; + << mptIssue.getMptID() << ": " << issuanceEscrowed << " + " << pay; return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3755,9 +3286,7 @@ rippleUnlockEscrowMPT( beast::Journal j) { if (!view.rules().enabled(fixTokenEscrowV1)) - XRPL_ASSERT( - netAmount == grossAmount, - "xrpl::rippleUnlockEscrowMPT : netAmount == grossAmount"); + XRPL_ASSERT(netAmount == grossAmount, "xrpl::rippleUnlockEscrowMPT : netAmount == grossAmount"); auto const& issuer = netAmount.getIssuer(); auto const& mptIssue = netAmount.get(); @@ -3765,8 +3294,7 @@ rippleUnlockEscrowMPT( auto sleIssuance = view.peek(mptID); if (!sleIssuance) { // LCOV_EXCL_START - JLOG(j.error()) << "rippleUnlockEscrowMPT: MPT issuance not found for " - << mptIssue.getMptID(); + JLOG(j.error()) << "rippleUnlockEscrowMPT: MPT issuance not found for " << mptIssue.getMptID(); return tecOBJECT_NOT_FOUND; } // LCOV_EXCL_STOP @@ -3774,9 +3302,7 @@ rippleUnlockEscrowMPT( { if (!sleIssuance->isFieldPresent(sfLockedAmount)) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: no locked amount in issuance for " - << mptIssue.getMptID(); + JLOG(j.error()) << "rippleUnlockEscrowMPT: no locked amount in issuance for " << mptIssue.getMptID(); return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3784,12 +3310,10 @@ rippleUnlockEscrowMPT( auto const redeem = grossAmount.mpt().value(); // Underflow check for subtraction - if (!canSubtract( - STAmount(mptIssue, locked), STAmount(mptIssue, redeem))) + if (!canSubtract(STAmount(mptIssue, locked), STAmount(mptIssue, redeem))) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: insufficient locked amount for " - << mptIssue.getMptID() << ": " << locked << " < " << redeem; + JLOG(j.error()) << "rippleUnlockEscrowMPT: insufficient locked amount for " << mptIssue.getMptID() << ": " + << locked << " < " << redeem; return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3808,8 +3332,7 @@ rippleUnlockEscrowMPT( auto sle = view.peek(mptokenID); if (!sle) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: MPToken not found for " << receiver; + JLOG(j.error()) << "rippleUnlockEscrowMPT: MPToken not found for " << receiver; return tecOBJECT_NOT_FOUND; } // LCOV_EXCL_STOP @@ -3819,9 +3342,8 @@ rippleUnlockEscrowMPT( // Overflow check for addition if (!canAdd(STAmount(mptIssue, current), STAmount(mptIssue, delta))) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: overflow on MPTAmount for " - << to_string(receiver) << ": " << current << " + " << delta; + JLOG(j.error()) << "rippleUnlockEscrowMPT: overflow on MPTAmount for " << to_string(receiver) << ": " + << current << " + " << delta; return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3835,13 +3357,10 @@ rippleUnlockEscrowMPT( auto const redeem = netAmount.mpt().value(); // Underflow check for subtraction - if (!canSubtract( - STAmount(mptIssue, outstanding), STAmount(mptIssue, redeem))) + if (!canSubtract(STAmount(mptIssue, outstanding), STAmount(mptIssue, redeem))) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: insufficient outstanding amount for " - << mptIssue.getMptID() << ": " << outstanding << " < " - << redeem; + JLOG(j.error()) << "rippleUnlockEscrowMPT: insufficient outstanding amount for " << mptIssue.getMptID() + << ": " << outstanding << " < " << redeem; return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3862,16 +3381,13 @@ rippleUnlockEscrowMPT( auto sle = view.peek(mptokenID); if (!sle) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: MPToken not found for " << sender; + JLOG(j.error()) << "rippleUnlockEscrowMPT: MPToken not found for " << sender; return tecOBJECT_NOT_FOUND; } // LCOV_EXCL_STOP if (!sle->isFieldPresent(sfLockedAmount)) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: no locked amount in MPToken for " - << to_string(sender); + JLOG(j.error()) << "rippleUnlockEscrowMPT: no locked amount in MPToken for " << to_string(sender); return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3881,9 +3397,8 @@ rippleUnlockEscrowMPT( // Underflow check for subtraction if (!canSubtract(STAmount(mptIssue, locked), STAmount(mptIssue, delta))) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: insufficient locked amount for " - << to_string(sender) << ": " << locked << " < " << delta; + JLOG(j.error()) << "rippleUnlockEscrowMPT: insufficient locked amount for " << to_string(sender) << ": " + << locked << " < " << delta; return tecINTERNAL; } // LCOV_EXCL_STOP @@ -3904,12 +3419,10 @@ rippleUnlockEscrowMPT( { auto const outstanding = sleIssuance->getFieldU64(sfOutstandingAmount); // Underflow check for subtraction - if (!canSubtract( - STAmount(mptIssue, outstanding), STAmount(mptIssue, diff))) + if (!canSubtract(STAmount(mptIssue, outstanding), STAmount(mptIssue, diff))) { // LCOV_EXCL_START - JLOG(j.error()) - << "rippleUnlockEscrowMPT: insufficient outstanding amount for " - << mptIssue.getMptID() << ": " << outstanding << " < " << diff; + JLOG(j.error()) << "rippleUnlockEscrowMPT: insufficient outstanding amount for " << mptIssue.getMptID() + << ": " << outstanding << " < " << diff; return tecINTERNAL; } // LCOV_EXCL_STOP diff --git a/src/libxrpl/net/HTTPClient.cpp b/src/libxrpl/net/HTTPClient.cpp index 6057d81a1e..e5a1196cb0 100644 --- a/src/libxrpl/net/HTTPClient.cpp +++ b/src/libxrpl/net/HTTPClient.cpp @@ -32,8 +32,7 @@ HTTPClient::initializeSSLContext( // //------------------------------------------------------------------------------ -class HTTPClientImp : public std::enable_shared_from_this, - public HTTPClient +class HTTPClientImp : public std::enable_shared_from_this, public HTTPClient { public: HTTPClientImp( @@ -54,10 +53,7 @@ public: //-------------------------------------------------------------------------- void - makeGet( - std::string const& strPath, - boost::asio::streambuf& sb, - std::string const& strHost) + makeGet(std::string const& strPath, boost::asio::streambuf& sb, std::string const& strHost) { std::ostream osRequest(&sb); @@ -76,13 +72,10 @@ public: request( bool bSSL, std::deque deqSites, - std::function< - void(boost::asio::streambuf& sb, std::string const& strHost)> build, + std::function build, std::chrono::seconds timeout, - std::function complete) + std::function + complete) { mSSL = bSSL; mDeqSites = deqSites; @@ -100,10 +93,8 @@ public: std::deque deqSites, std::string const& strPath, std::chrono::seconds timeout, - std::function complete) + std::function + complete) { mComplete = complete; mTimeout = timeout; @@ -112,11 +103,7 @@ public: bSSL, deqSites, std::bind( - &HTTPClientImp::makeGet, - shared_from_this(), - strPath, - std::placeholders::_1, - std::placeholders::_2), + &HTTPClientImp::makeGet, shared_from_this(), strPath, std::placeholders::_1, std::placeholders::_2), timeout, complete); } @@ -129,9 +116,7 @@ public: JLOG(j_.trace()) << "Fetch: " << mDeqSites[0]; auto query = std::make_shared( - mDeqSites[0], - std::to_string(mPort), - boost::asio::ip::resolver_query_base::numeric_service); + mDeqSites[0], std::to_string(mPort), boost::asio::ip::resolver_query_base::numeric_service); mQuery = query; try @@ -143,10 +128,7 @@ public: mShutdown = e.code(); JLOG(j_.trace()) << "expires_after: " << mShutdown.message(); - mDeadline.async_wait(std::bind( - &HTTPClientImp::handleDeadline, - shared_from_this(), - std::placeholders::_1)); + mDeadline.async_wait(std::bind(&HTTPClientImp::handleDeadline, shared_from_this(), std::placeholders::_1)); } if (!mShutdown) @@ -158,10 +140,7 @@ public: mQuery->port, mQuery->flags, std::bind( - &HTTPClientImp::handleResolve, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2)); + &HTTPClientImp::handleResolve, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } if (mShutdown) @@ -180,8 +159,7 @@ public: } else if (ecResult) { - JLOG(j_.trace()) << "Deadline error: " << mDeqSites[0] << ": " - << ecResult.message(); + JLOG(j_.trace()) << "Deadline error: " << mDeqSites[0] << ": " << ecResult.message(); // Can't do anything sound. abort(); @@ -192,18 +170,14 @@ public: // Mark us as shutting down. // XXX Use our own error code. - mShutdown = boost::system::error_code{ - boost::system::errc::bad_address, - boost::system::system_category()}; + mShutdown = boost::system::error_code{boost::system::errc::bad_address, boost::system::system_category()}; // Cancel any resolving. mResolver.cancel(); // Stop the transaction. - mSocket.async_shutdown(std::bind( - &HTTPClientImp::handleShutdown, - shared_from_this(), - std::placeholders::_1)); + mSocket.async_shutdown( + std::bind(&HTTPClientImp::handleShutdown, shared_from_this(), std::placeholders::_1)); } } @@ -212,27 +186,21 @@ public: { if (ecResult) { - JLOG(j_.trace()) << "Shutdown error: " << mDeqSites[0] << ": " - << ecResult.message(); + JLOG(j_.trace()) << "Shutdown error: " << mDeqSites[0] << ": " << ecResult.message(); } } void - handleResolve( - boost::system::error_code const& ecResult, - boost::asio::ip::tcp::resolver::results_type result) + handleResolve(boost::system::error_code const& ecResult, boost::asio::ip::tcp::resolver::results_type result) { if (!mShutdown) { - mShutdown = ecResult ? ecResult - : httpClientSSLContext->preConnectVerify( - mSocket.SSLSocket(), mDeqSites[0]); + mShutdown = ecResult ? ecResult : httpClientSSLContext->preConnectVerify(mSocket.SSLSocket(), mDeqSites[0]); } if (mShutdown) { - JLOG(j_.trace()) << "Resolve error: " << mDeqSites[0] << ": " - << mShutdown.message(); + JLOG(j_.trace()) << "Resolve error: " << mDeqSites[0] << ": " << mShutdown.message(); invokeComplete(mShutdown); } @@ -243,10 +211,7 @@ public: boost::asio::async_connect( mSocket.lowest_layer(), result, - std::bind( - &HTTPClientImp::handleConnect, - shared_from_this(), - std::placeholders::_1)); + std::bind(&HTTPClientImp::handleConnect, shared_from_this(), std::placeholders::_1)); } } @@ -265,13 +230,11 @@ public: { JLOG(j_.trace()) << "Connected."; - mShutdown = httpClientSSLContext->postConnectVerify( - mSocket.SSLSocket(), mDeqSites[0]); + mShutdown = httpClientSSLContext->postConnectVerify(mSocket.SSLSocket(), mDeqSites[0]); if (mShutdown) { - JLOG(j_.trace()) << "postConnectVerify: " << mDeqSites[0] - << ": " << mShutdown.message(); + JLOG(j_.trace()) << "postConnectVerify: " << mDeqSites[0] << ": " << mShutdown.message(); } } @@ -283,10 +246,7 @@ public: { mSocket.async_handshake( AutoSocket::ssl_socket::client, - std::bind( - &HTTPClientImp::handleRequest, - shared_from_this(), - std::placeholders::_1)); + std::bind(&HTTPClientImp::handleRequest, shared_from_this(), std::placeholders::_1)); } else { @@ -315,17 +275,12 @@ public: mSocket.async_write( mRequest, std::bind( - &HTTPClientImp::handleWrite, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2)); + &HTTPClientImp::handleWrite, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } } void - handleWrite( - boost::system::error_code const& ecResult, - std::size_t bytes_transferred) + handleWrite(boost::system::error_code const& ecResult, std::size_t bytes_transferred) { if (!mShutdown) mShutdown = ecResult; @@ -344,27 +299,18 @@ public: mHeader, "\r\n\r\n", std::bind( - &HTTPClientImp::handleHeader, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2)); + &HTTPClientImp::handleHeader, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } } void - handleHeader( - boost::system::error_code const& ecResult, - std::size_t bytes_transferred) + handleHeader(boost::system::error_code const& ecResult, std::size_t bytes_transferred) { - std::string strHeader{ - {std::istreambuf_iterator(&mHeader)}, - std::istreambuf_iterator()}; + std::string strHeader{{std::istreambuf_iterator(&mHeader)}, std::istreambuf_iterator()}; JLOG(j_.trace()) << "Header: \"" << strHeader << "\""; - static boost::regex reStatus{ - "\\`HTTP/1\\S+ (\\d{3}) .*\\'"}; // HTTP/1.1 200 OK - static boost::regex reSize{ - "\\`.*\\r\\nContent-Length:\\s+([0-9]+).*\\'", boost::regex::icase}; + static boost::regex reStatus{"\\`HTTP/1\\S+ (\\d{3}) .*\\'"}; // HTTP/1.1 200 OK + static boost::regex reSize{"\\`.*\\r\\nContent-Length:\\s+([0-9]+).*\\'", boost::regex::icase}; static boost::regex reBody{"\\`.*\\r\\n\\r\\n(.*)\\'"}; boost::smatch smMatch; @@ -373,9 +319,8 @@ public: { // XXX Use our own error code. JLOG(j_.trace()) << "No status code"; - invokeComplete(boost::system::error_code{ - boost::system::errc::bad_address, - boost::system::system_category()}); + invokeComplete( + boost::system::error_code{boost::system::errc::bad_address, boost::system::system_category()}); return; } @@ -386,17 +331,15 @@ public: std::size_t const responseSize = [&] { if (boost::regex_match(strHeader, smMatch, reSize)) - return beast::lexicalCast( - std::string(smMatch[1]), maxResponseSize_); + return beast::lexicalCast(std::string(smMatch[1]), maxResponseSize_); return maxResponseSize_; }(); if (responseSize > maxResponseSize_) { JLOG(j_.trace()) << "Response field too large"; - invokeComplete(boost::system::error_code{ - boost::system::errc::value_too_large, - boost::system::system_category()}); + invokeComplete( + boost::system::error_code{boost::system::errc::value_too_large, boost::system::system_category()}); return; } @@ -416,17 +359,12 @@ public: mResponse.prepare(responseSize - mBody.size()), boost::asio::transfer_all(), std::bind( - &HTTPClientImp::handleData, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2)); + &HTTPClientImp::handleData, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } } void - handleData( - boost::system::error_code const& ecResult, - std::size_t bytes_transferred) + handleData(boost::system::error_code const& ecResult, std::size_t bytes_transferred) { if (!mShutdown) mShutdown = ecResult; @@ -446,9 +384,7 @@ public: else { mResponse.commit(bytes_transferred); - std::string strBody{ - {std::istreambuf_iterator(&mResponse)}, - std::istreambuf_iterator()}; + std::string strBody{{std::istreambuf_iterator(&mResponse)}, std::istreambuf_iterator()}; invokeComplete(ecResult, mStatus, mBody + strBody); } } @@ -456,10 +392,7 @@ public: // Call cancel the deadline timer and invoke the completion routine. void - invokeComplete( - boost::system::error_code const& ecResult, - int iStatus = 0, - std::string const& strData = "") + invokeComplete(boost::system::error_code const& ecResult, int iStatus = 0, std::string const& strData = "") { boost::system::error_code ecCancel; try @@ -468,13 +401,11 @@ public: } catch (boost::system::system_error const& e) { - JLOG(j_.trace()) - << "invokeComplete: Deadline cancel error: " << e.what(); + JLOG(j_.trace()) << "invokeComplete: Deadline cancel error: " << e.what(); ecCancel = e.code(); } - JLOG(j_.debug()) << "invokeComplete: Deadline popping: " - << mDeqSites.size(); + JLOG(j_.debug()) << "invokeComplete: Deadline popping: " << mDeqSites.size(); if (!mDeqSites.empty()) { @@ -488,8 +419,7 @@ public: // ecResult: !0 = had an error, last entry // iStatus: result, if no error // strData: data, if no error - bAgain = mComplete && - mComplete(ecResult ? ecResult : ecCancel, iStatus, strData); + bAgain = mComplete && mComplete(ecResult ? ecResult : ecCancel, iStatus, strData); } if (!mDeqSites.empty() && bAgain) @@ -520,13 +450,8 @@ private: unsigned short const mPort; std::size_t const maxResponseSize_; int mStatus; - std::function - mBuild; - std::function - mComplete; + std::function mBuild; + std::function mComplete; boost::asio::basic_waitable_timer mDeadline; @@ -549,14 +474,10 @@ HTTPClient::get( std::string const& strPath, std::size_t responseMax, std::chrono::seconds timeout, - std::function complete, + std::function complete, beast::Journal& j) { - auto client = - std::make_shared(io_context, port, responseMax, j); + auto client = std::make_shared(io_context, port, responseMax, j); client->get(bSSL, deqSites, strPath, timeout, complete); } @@ -569,16 +490,12 @@ HTTPClient::get( std::string const& strPath, std::size_t responseMax, std::chrono::seconds timeout, - std::function complete, + std::function complete, beast::Journal& j) { std::deque deqSites(1, strSite); - auto client = - std::make_shared(io_context, port, responseMax, j); + auto client = std::make_shared(io_context, port, responseMax, j); client->get(bSSL, deqSites, strPath, timeout, complete); } @@ -588,20 +505,15 @@ HTTPClient::request( boost::asio::io_context& io_context, std::string strSite, unsigned short const port, - std::function - setRequest, + std::function setRequest, std::size_t responseMax, std::chrono::seconds timeout, - std::function complete, + std::function complete, beast::Journal& j) { std::deque deqSites(1, strSite); - auto client = - std::make_shared(io_context, port, responseMax, j); + auto client = std::make_shared(io_context, port, responseMax, j); client->request(bSSL, deqSites, setRequest, timeout, complete); } diff --git a/src/libxrpl/net/RegisterSSLCerts.cpp b/src/libxrpl/net/RegisterSSLCerts.cpp index a1321e4c61..a15472969e 100644 --- a/src/libxrpl/net/RegisterSSLCerts.cpp +++ b/src/libxrpl/net/RegisterSSLCerts.cpp @@ -16,36 +16,28 @@ namespace xrpl { void -registerSSLCerts( - boost::asio::ssl::context& ctx, - boost::system::error_code& ec, - beast::Journal j) +registerSSLCerts(boost::asio::ssl::context& ctx, boost::system::error_code& ec, beast::Journal j) { #if BOOST_OS_WINDOWS auto certStoreDelete = [](void* h) { if (h != nullptr) CertCloseStore(h, 0); }; - std::unique_ptr hStore{ - CertOpenSystemStore(0, "ROOT"), certStoreDelete}; + std::unique_ptr hStore{CertOpenSystemStore(0, "ROOT"), certStoreDelete}; if (!hStore) { - ec = boost::system::error_code( - GetLastError(), boost::system::system_category()); + ec = boost::system::error_code(GetLastError(), boost::system::system_category()); return; } ERR_clear_error(); - std::unique_ptr store{ - X509_STORE_new(), X509_STORE_free}; + std::unique_ptr store{X509_STORE_new(), X509_STORE_free}; if (!store) { - ec = boost::system::error_code( - static_cast(::ERR_get_error()), - boost::asio::error::get_ssl_category()); + ec = boost::system::error_code(static_cast(::ERR_get_error()), boost::asio::error::get_ssl_category()); return; } @@ -58,8 +50,7 @@ registerSSLCerts( }; PCCERT_CONTEXT pContext = NULL; - while ((pContext = CertEnumCertificatesInStore(hStore.get(), pContext)) != - NULL) + while ((pContext = CertEnumCertificatesInStore(hStore.get(), pContext)) != NULL) { unsigned char const* pbCertEncoded = pContext->pbCertEncoded; std::unique_ptr x509{ diff --git a/src/libxrpl/nodestore/BatchWriter.cpp b/src/libxrpl/nodestore/BatchWriter.cpp index 3ce7900480..73213fe3ba 100644 --- a/src/libxrpl/nodestore/BatchWriter.cpp +++ b/src/libxrpl/nodestore/BatchWriter.cpp @@ -4,10 +4,7 @@ namespace xrpl { namespace NodeStore { BatchWriter::BatchWriter(Callback& callback, Scheduler& scheduler) - : m_callback(callback) - , m_scheduler(scheduler) - , mWriteLoad(0) - , mWritePending(false) + : m_callback(callback), m_scheduler(scheduler), mWriteLoad(0), mWritePending(false) { mWriteSet.reserve(batchWritePreallocationSize); } @@ -64,9 +61,7 @@ BatchWriter::writeBatch() std::lock_guard sl(mWriteMutex); mWriteSet.swap(set); - XRPL_ASSERT( - mWriteSet.empty(), - "xrpl::NodeStore::BatchWriter::writeBatch : writes not set"); + XRPL_ASSERT(mWriteSet.empty(), "xrpl::NodeStore::BatchWriter::writeBatch : writes not set"); mWriteLoad = set.size(); if (set.empty()) @@ -85,8 +80,8 @@ BatchWriter::writeBatch() m_callback.writeBatch(set); - report.elapsed = std::chrono::duration_cast( - std::chrono::steady_clock::now() - before); + report.elapsed = + std::chrono::duration_cast(std::chrono::steady_clock::now() - before); m_scheduler.onBatchWrite(report); } diff --git a/src/libxrpl/nodestore/Database.cpp b/src/libxrpl/nodestore/Database.cpp index 9ea25785ff..f393bf27c9 100644 --- a/src/libxrpl/nodestore/Database.cpp +++ b/src/libxrpl/nodestore/Database.cpp @@ -10,21 +10,14 @@ namespace xrpl { namespace NodeStore { -Database::Database( - Scheduler& scheduler, - int readThreads, - Section const& config, - beast::Journal journal) +Database::Database(Scheduler& scheduler, int readThreads, Section const& config, beast::Journal journal) : j_(journal) , scheduler_(scheduler) - , earliestLedgerSeq_( - get(config, "earliest_seq", XRP_LEDGER_EARLIEST_SEQ)) + , earliestLedgerSeq_(get(config, "earliest_seq", XRP_LEDGER_EARLIEST_SEQ)) , requestBundle_(get(config, "rq_bundle", 4)) , readThreads_(std::max(1, readThreads)) { - XRPL_ASSERT( - readThreads, - "xrpl::NodeStore::Database::Database : nonzero threads input"); + XRPL_ASSERT(readThreads, "xrpl::NodeStore::Database::Database : nonzero threads input"); if (earliestLedgerSeq_ < 1) Throw("Invalid earliest_seq"); @@ -38,8 +31,7 @@ Database::Database( [this](int i) { runningThreads_++; - beast::setCurrentThreadName( - "db prefetch #" + std::to_string(i)); + beast::setCurrentThreadName("db prefetch #" + std::to_string(i)); decltype(read_) read; @@ -63,9 +55,7 @@ Database::Database( // extract multiple object at a time to minimize the // overhead of acquiring the mutex. - for (int cnt = 0; - !read_.empty() && cnt != requestBundle_; - ++cnt) + for (int cnt = 0; !read_.empty() && cnt != requestBundle_; ++cnt) read.insert(read_.extract(read_.begin())); } @@ -80,8 +70,7 @@ Database::Database( auto const& data = it->second; auto const seqn = data[0].first; - auto obj = - fetchNodeObject(hash, seqn, FetchType::async); + auto obj = fetchNodeObject(hash, seqn, FetchType::async); // This could be further optimized: if there are // multiple requests for sequence numbers mapping to @@ -93,8 +82,7 @@ Database::Database( req.second( (seqn == req.first) || isSameDB(req.first, seqn) ? obj - : fetchNodeObject( - hash, req.first, FetchType::async)); + : fetchNodeObject(hash, req.first, FetchType::async)); } } @@ -148,16 +136,12 @@ Database::stop() while (readThreads_.load() != 0) { - XRPL_ASSERT( - steady_clock::now() - start < 30s, - "xrpl::NodeStore::Database::stop : maximum stop duration"); + XRPL_ASSERT(steady_clock::now() - start < 30s, "xrpl::NodeStore::Database::stop : maximum stop duration"); std::this_thread::yield(); } JLOG(j_.debug()) << "Stop request completed in " - << duration_cast( - steady_clock::now() - start) - .count() + << duration_cast(steady_clock::now() - start).count() << " milliseconds"; } @@ -188,8 +172,7 @@ Database::importInternal(Backend& dstBackend, Database& srcDB) } catch (std::exception const& e) { - JLOG(j_.error()) << "Exception caught in function " << fname - << ". Error: " << e.what(); + JLOG(j_.error()) << "Exception caught in function " << fname << ". Error: " << e.what(); return; } @@ -201,9 +184,7 @@ Database::importInternal(Backend& dstBackend, Database& srcDB) }; srcDB.for_each([&](std::shared_ptr nodeObject) { - XRPL_ASSERT( - nodeObject, - "xrpl::NodeStore::Database::importInternal : non-null node"); + XRPL_ASSERT(nodeObject, "xrpl::NodeStore::Database::importInternal : non-null node"); if (!nodeObject) // This should never happen return; @@ -218,11 +199,7 @@ Database::importInternal(Backend& dstBackend, Database& srcDB) // Perform a fetch and report the time it took std::shared_ptr -Database::fetchNodeObject( - uint256 const& hash, - std::uint32_t ledgerSeq, - FetchType fetchType, - bool duplicate) +Database::fetchNodeObject(uint256 const& hash, std::uint32_t ledgerSeq, FetchType fetchType, bool duplicate) { FetchReport fetchReport(fetchType); @@ -247,9 +224,7 @@ Database::fetchNodeObject( void Database::getCountsJson(Json::Value& obj) { - XRPL_ASSERT( - obj.isObject(), - "xrpl::NodeStore::Database::getCountsJson : valid input type"); + XRPL_ASSERT(obj.isObject(), "xrpl::NodeStore::Database::getCountsJson : valid input type"); { std::unique_lock lock(readLock_); diff --git a/src/libxrpl/nodestore/DatabaseNodeImp.cpp b/src/libxrpl/nodestore/DatabaseNodeImp.cpp index 0578351e58..f49867514c 100644 --- a/src/libxrpl/nodestore/DatabaseNodeImp.cpp +++ b/src/libxrpl/nodestore/DatabaseNodeImp.cpp @@ -4,11 +4,7 @@ namespace xrpl { namespace NodeStore { void -DatabaseNodeImp::store( - NodeObjectType type, - Blob&& data, - uint256 const& hash, - std::uint32_t) +DatabaseNodeImp::store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t) { storeStats(1, data.size()); @@ -17,10 +13,7 @@ DatabaseNodeImp::store( if (cache_) { // After the store, replace a negative cache entry if there is one - cache_->canonicalize( - hash, obj, [](std::shared_ptr const& n) { - return n->getType() == hotDUMMY; - }); + cache_->canonicalize(hash, obj, [](std::shared_ptr const& n) { return n->getType() == hotDUMMY; }); } } @@ -50,19 +43,13 @@ DatabaseNodeImp::sweep() } std::shared_ptr -DatabaseNodeImp::fetchNodeObject( - uint256 const& hash, - std::uint32_t, - FetchReport& fetchReport, - bool duplicate) +DatabaseNodeImp::fetchNodeObject(uint256 const& hash, std::uint32_t, FetchReport& fetchReport, bool duplicate) { - std::shared_ptr nodeObject = - cache_ ? cache_->fetch(hash) : nullptr; + std::shared_ptr nodeObject = cache_ ? cache_->fetch(hash) : nullptr; if (!nodeObject) { - JLOG(j_.trace()) << "fetchNodeObject " << hash << ": record not " - << (cache_ ? "cached" : "found"); + JLOG(j_.trace()) << "fetchNodeObject " << hash << ": record not " << (cache_ ? "cached" : "found"); Status status; @@ -72,9 +59,7 @@ DatabaseNodeImp::fetchNodeObject( } catch (std::exception const& e) { - JLOG(j_.fatal()) - << "fetchNodeObject " << hash - << ": Exception fetching from backend: " << e.what(); + JLOG(j_.fatal()) << "fetchNodeObject " << hash << ": Exception fetching from backend: " << e.what(); Rethrow(); } @@ -87,8 +72,7 @@ DatabaseNodeImp::fetchNodeObject( cache_->canonicalize_replace_client(hash, nodeObject); else { - auto notFound = - NodeObject::createObject(hotDUMMY, {}, hash); + auto notFound = NodeObject::createObject(hotDUMMY, {}, hash); cache_->canonicalize_replace_client(hash, notFound); if (notFound->getType() != hotDUMMY) nodeObject = notFound; @@ -98,20 +82,16 @@ DatabaseNodeImp::fetchNodeObject( case notFound: break; case dataCorrupt: - JLOG(j_.fatal()) << "fetchNodeObject " << hash - << ": nodestore data is corrupted"; + JLOG(j_.fatal()) << "fetchNodeObject " << hash << ": nodestore data is corrupted"; break; default: - JLOG(j_.warn()) - << "fetchNodeObject " << hash - << ": backend returns unknown result " << status; + JLOG(j_.warn()) << "fetchNodeObject " << hash << ": backend returns unknown result " << status; break; } } else { - JLOG(j_.trace()) << "fetchNodeObject " << hash - << ": record found in cache"; + JLOG(j_.trace()) << "fetchNodeObject " << hash << ": record found in cache"; if (nodeObject->getType() == hotDUMMY) nodeObject.reset(); } @@ -152,8 +132,7 @@ DatabaseNodeImp::fetchBatch(std::vector const& hashes) } } - JLOG(j_.debug()) << "fetchBatch - cache hits = " - << (hashes.size() - cacheMisses.size()) + JLOG(j_.debug()) << "fetchBatch - cache hits = " << (hashes.size() - cacheMisses.size()) << " - cache misses = " << cacheMisses.size(); auto dbResults = backend_->fetchBatch(cacheMisses).first; @@ -171,9 +150,8 @@ DatabaseNodeImp::fetchBatch(std::vector const& hashes) } else { - JLOG(j_.error()) - << "fetchBatch - " - << "record not found in db or cache. hash = " << strHex(hash); + JLOG(j_.error()) << "fetchBatch - " + << "record not found in db or cache. hash = " << strHex(hash); if (cache_) { auto notFound = NodeObject::createObject(hotDUMMY, {}, hash); @@ -185,10 +163,7 @@ DatabaseNodeImp::fetchBatch(std::vector const& hashes) results[index] = std::move(nObj); } - auto fetchDurationUs = - std::chrono::duration_cast( - steady_clock::now() - before) - .count(); + auto fetchDurationUs = std::chrono::duration_cast(steady_clock::now() - before).count(); updateFetchMetrics(fetches, hits, fetchDurationUs); return results; } diff --git a/src/libxrpl/nodestore/DatabaseRotatingImp.cpp b/src/libxrpl/nodestore/DatabaseRotatingImp.cpp index f51771f023..2e72dca969 100644 --- a/src/libxrpl/nodestore/DatabaseRotatingImp.cpp +++ b/src/libxrpl/nodestore/DatabaseRotatingImp.cpp @@ -23,9 +23,7 @@ DatabaseRotatingImp::DatabaseRotatingImp( void DatabaseRotatingImp::rotate( std::unique_ptr&& newBackend, - std::function const& f) + std::function const& f) { // Pass these two names to the callback function std::string const newWritableBackendName = newBackend->getName(); @@ -82,11 +80,7 @@ DatabaseRotatingImp::sync() } void -DatabaseRotatingImp::store( - NodeObjectType type, - Blob&& data, - uint256 const& hash, - std::uint32_t) +DatabaseRotatingImp::store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t) { auto nObj = NodeObject::createObject(type, std::move(data), hash); @@ -106,11 +100,7 @@ DatabaseRotatingImp::sweep() } std::shared_ptr -DatabaseRotatingImp::fetchNodeObject( - uint256 const& hash, - std::uint32_t, - FetchReport& fetchReport, - bool duplicate) +DatabaseRotatingImp::fetchNodeObject(uint256 const& hash, std::uint32_t, FetchReport& fetchReport, bool duplicate) { auto fetch = [&](std::shared_ptr const& backend) { Status status; @@ -176,8 +166,7 @@ DatabaseRotatingImp::fetchNodeObject( } void -DatabaseRotatingImp::for_each( - std::function)> f) +DatabaseRotatingImp::for_each(std::function)> f) { auto [writable, archive] = [&] { std::lock_guard lock(mutex_); diff --git a/src/libxrpl/nodestore/DecodedBlob.cpp b/src/libxrpl/nodestore/DecodedBlob.cpp index e3d54fae78..ad704cb84e 100644 --- a/src/libxrpl/nodestore/DecodedBlob.cpp +++ b/src/libxrpl/nodestore/DecodedBlob.cpp @@ -54,9 +54,7 @@ DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes) std::shared_ptr DecodedBlob::createObject() { - XRPL_ASSERT( - m_success, - "xrpl::NodeStore::DecodedBlob::createObject : valid object type"); + XRPL_ASSERT(m_success, "xrpl::NodeStore::DecodedBlob::createObject : valid object type"); std::shared_ptr object; @@ -64,8 +62,7 @@ DecodedBlob::createObject() { Blob data(m_objectData, m_objectData + m_dataBytes); - object = NodeObject::createObject( - m_objectType, std::move(data), uint256::fromVoid(m_key)); + object = NodeObject::createObject(m_objectType, std::move(data), uint256::fromVoid(m_key)); } return object; diff --git a/src/libxrpl/nodestore/ManagerImp.cpp b/src/libxrpl/nodestore/ManagerImp.cpp index 58accd4108..9d78097aae 100644 --- a/src/libxrpl/nodestore/ManagerImp.cpp +++ b/src/libxrpl/nodestore/ManagerImp.cpp @@ -44,11 +44,7 @@ ManagerImp::ManagerImp() } std::unique_ptr -ManagerImp::make_Backend( - Section const& parameters, - std::size_t burstSize, - Scheduler& scheduler, - beast::Journal journal) +ManagerImp::make_Backend(Section const& parameters, std::size_t burstSize, Scheduler& scheduler, beast::Journal journal) { std::string const type{get(parameters, "type")}; if (type.empty()) @@ -60,8 +56,7 @@ ManagerImp::make_Backend( missing_backend(); } - return factory->createInstance( - NodeObject::keyBytes, parameters, burstSize, scheduler, journal); + return factory->createInstance(NodeObject::keyBytes, parameters, burstSize, scheduler, journal); } std::unique_ptr @@ -74,8 +69,7 @@ ManagerImp::make_Database( { auto backend{make_Backend(config, burstSize, scheduler, journal)}; backend->open(); - return std::make_unique( - scheduler, readThreads, std::move(backend), config, journal); + return std::make_unique(scheduler, readThreads, std::move(backend), config, journal); } void @@ -90,12 +84,8 @@ ManagerImp::erase(Factory& factory) { std::lock_guard _(mutex_); auto const iter = - std::find_if(list_.begin(), list_.end(), [&factory](Factory* other) { - return other == &factory; - }); - XRPL_ASSERT( - iter != list_.end(), - "xrpl::NodeStore::ManagerImp::erase : valid input"); + std::find_if(list_.begin(), list_.end(), [&factory](Factory* other) { return other == &factory; }); + XRPL_ASSERT(iter != list_.end(), "xrpl::NodeStore::ManagerImp::erase : valid input"); list_.erase(iter); } @@ -103,10 +93,8 @@ Factory* ManagerImp::find(std::string const& name) { std::lock_guard _(mutex_); - auto const iter = - std::find_if(list_.begin(), list_.end(), [&name](Factory* other) { - return boost::iequals(name, other->getName()); - }); + auto const iter = std::find_if( + list_.begin(), list_.end(), [&name](Factory* other) { return boost::iequals(name, other->getName()); }); if (iter == list_.end()) return nullptr; return *iter; diff --git a/src/libxrpl/nodestore/NodeObject.cpp b/src/libxrpl/nodestore/NodeObject.cpp index 3758862e18..2e40989e7c 100644 --- a/src/libxrpl/nodestore/NodeObject.cpp +++ b/src/libxrpl/nodestore/NodeObject.cpp @@ -6,11 +6,7 @@ namespace xrpl { //------------------------------------------------------------------------------ -NodeObject::NodeObject( - NodeObjectType type, - Blob&& data, - uint256 const& hash, - PrivateAccess) +NodeObject::NodeObject(NodeObjectType type, Blob&& data, uint256 const& hash, PrivateAccess) : mType(type), mHash(hash), mData(std::move(data)) { } @@ -18,8 +14,7 @@ NodeObject::NodeObject( std::shared_ptr NodeObject::createObject(NodeObjectType type, Blob&& data, uint256 const& hash) { - return std::make_shared( - type, std::move(data), hash, PrivateAccess()); + return std::make_shared(type, std::move(data), hash, PrivateAccess()); } NodeObjectType diff --git a/src/libxrpl/nodestore/backend/MemoryFactory.cpp b/src/libxrpl/nodestore/backend/MemoryFactory.cpp index 923ae95ebb..3cb8fb7f5e 100644 --- a/src/libxrpl/nodestore/backend/MemoryFactory.cpp +++ b/src/libxrpl/nodestore/backend/MemoryFactory.cpp @@ -46,8 +46,7 @@ public: open(std::string const& path) { std::lock_guard _(mutex_); - auto const result = map_.emplace( - std::piecewise_construct, std::make_tuple(path), std::make_tuple()); + auto const result = map_.emplace(std::piecewise_construct, std::make_tuple(path), std::make_tuple()); MemoryDB& db = result.first->second; if (db.open) Throw("already open"); @@ -76,10 +75,7 @@ private: MemoryDB* db_{nullptr}; public: - MemoryBackend( - size_t keyBytes, - Section const& keyValues, - beast::Journal journal) + MemoryBackend(size_t keyBytes, Section const& keyValues, beast::Journal journal) : name_(get(keyValues, "path")), journal_(journal) { boost::ignore_unused(journal_); // Keep unused journal_ just in case. @@ -121,8 +117,7 @@ public: Status fetch(void const* key, std::shared_ptr* pObject) override { - XRPL_ASSERT( - db_, "xrpl::NodeStore::MemoryBackend::fetch : non-null database"); + XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::fetch : non-null database"); uint256 const hash(uint256::fromVoid(key)); std::lock_guard _(db_->mutex); @@ -158,8 +153,7 @@ public: void store(std::shared_ptr const& object) override { - XRPL_ASSERT( - db_, "xrpl::NodeStore::MemoryBackend::store : non-null database"); + XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::store : non-null database"); std::lock_guard _(db_->mutex); db_->table.emplace(object->getHash(), object); } @@ -179,9 +173,7 @@ public: void for_each(std::function)> f) override { - XRPL_ASSERT( - db_, - "xrpl::NodeStore::MemoryBackend::for_each : non-null database"); + XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::for_each : non-null database"); for (auto const& e : db_->table) f(e.second); } diff --git a/src/libxrpl/nodestore/backend/NuDBFactory.cpp b/src/libxrpl/nodestore/backend/NuDBFactory.cpp index 71a5811162..eb3ccb3181 100644 --- a/src/libxrpl/nodestore/backend/NuDBFactory.cpp +++ b/src/libxrpl/nodestore/backend/NuDBFactory.cpp @@ -53,8 +53,7 @@ public: , scheduler_(scheduler) { if (name_.empty()) - Throw( - "nodestore: Missing path in NuDB backend"); + Throw("nodestore: Missing path in NuDB backend"); } NuDBBackend( @@ -74,8 +73,7 @@ public: , scheduler_(scheduler) { if (name_.empty()) - Throw( - "nodestore: Missing path in NuDB backend"); + Throw("nodestore: Missing path in NuDB backend"); } ~NuDBBackend() override @@ -105,8 +103,7 @@ public: } void - open(bool createIfMissing, uint64_t appType, uint64_t uid, uint64_t salt) - override + open(bool createIfMissing, uint64_t appType, uint64_t uid, uint64_t salt) override { using namespace boost::filesystem; if (db_.is_open()) @@ -127,17 +124,7 @@ public: if (createIfMissing) { create_directories(folder); - nudb::create( - dp, - kp, - lp, - appType, - uid, - salt, - keyBytes_, - blockSize_, - 0.50, - ec); + nudb::create(dp, kp, lp, appType, uid, salt, keyBytes_, blockSize_, 0.50, ec); if (ec == nudb::errc::file_exists) ec = {}; if (ec) @@ -183,8 +170,7 @@ public: boost::filesystem::remove_all(name_, ec); if (ec) { - JLOG(j_.fatal()) << "Filesystem remove_all of " << name_ - << " failed with: " << ec.message(); + JLOG(j_.fatal()) << "Filesystem remove_all of " << name_ << " failed with: " << ec.message(); } } } @@ -255,8 +241,8 @@ public: report.writeCount = 1; auto const start = std::chrono::steady_clock::now(); do_insert(no); - report.elapsed = std::chrono::duration_cast( - std::chrono::steady_clock::now() - start); + report.elapsed = + std::chrono::duration_cast(std::chrono::steady_clock::now() - start); scheduler_.onBatchWrite(report); } @@ -268,8 +254,8 @@ public: auto const start = std::chrono::steady_clock::now(); for (auto const& e : batch) do_insert(e); - report.elapsed = std::chrono::duration_cast( - std::chrono::steady_clock::now() - start); + report.elapsed = + std::chrono::duration_cast(std::chrono::steady_clock::now() - start); scheduler_.onBatchWrite(report); } @@ -291,11 +277,7 @@ public: Throw(ec); nudb::visit( dp, - [&](void const* key, - std::size_t key_bytes, - void const* data, - std::size_t size, - nudb::error_code&) { + [&](void const* key, std::size_t key_bytes, void const* data, std::size_t size, nudb::error_code&) { nudb::detail::buffer bf; auto const result = nodeobject_decompress(data, size, bf); DecodedBlob decoded(key, result.first, result.second); @@ -354,17 +336,13 @@ public: private: static std::size_t - parseBlockSize( - std::string const& name, - Section const& keyValues, - beast::Journal journal) + parseBlockSize(std::string const& name, Section const& keyValues, beast::Journal journal) { using namespace boost::filesystem; auto const folder = path(name); auto const kp = (folder / "nudb.key").string(); - std::size_t const defaultSize = - nudb::block_size(kp); // Default 4K from NuDB + std::size_t const defaultSize = nudb::block_size(kp); // Default 4K from NuDB std::size_t blockSize = defaultSize; std::string blockSizeStr; @@ -375,29 +353,23 @@ private: try { - std::size_t const parsedBlockSize = - beast::lexicalCastThrow(blockSizeStr); + std::size_t const parsedBlockSize = beast::lexicalCastThrow(blockSizeStr); // Validate: must be power of 2 between 4K and 32K - if (parsedBlockSize < 4096 || parsedBlockSize > 32768 || - (parsedBlockSize & (parsedBlockSize - 1)) != 0) + if (parsedBlockSize < 4096 || parsedBlockSize > 32768 || (parsedBlockSize & (parsedBlockSize - 1)) != 0) { std::stringstream s; - s << "Invalid nudb_block_size: " << parsedBlockSize - << ". Must be power of 2 between 4096 and 32768."; + s << "Invalid nudb_block_size: " << parsedBlockSize << ". Must be power of 2 between 4096 and 32768."; Throw(s.str()); } - JLOG(journal.info()) - << "Using custom NuDB block size: " << parsedBlockSize - << " bytes"; + JLOG(journal.info()) << "Using custom NuDB block size: " << parsedBlockSize << " bytes"; return parsedBlockSize; } catch (std::exception const& e) { std::stringstream s; - s << "Invalid nudb_block_size value: " << blockSizeStr - << ". Error: " << e.what(); + s << "Invalid nudb_block_size value: " << blockSizeStr << ". Error: " << e.what(); Throw(s.str()); } } @@ -430,8 +402,7 @@ public: Scheduler& scheduler, beast::Journal journal) override { - return std::make_unique( - keyBytes, keyValues, burstSize, scheduler, journal); + return std::make_unique(keyBytes, keyValues, burstSize, scheduler, journal); } std::unique_ptr @@ -443,8 +414,7 @@ public: nudb::context& context, beast::Journal journal) override { - return std::make_unique( - keyBytes, keyValues, burstSize, scheduler, context, journal); + return std::make_unique(keyBytes, keyValues, burstSize, scheduler, context, journal); } }; diff --git a/src/libxrpl/nodestore/backend/NullFactory.cpp b/src/libxrpl/nodestore/backend/NullFactory.cpp index ffe1eb931f..4ecca46a9a 100644 --- a/src/libxrpl/nodestore/backend/NullFactory.cpp +++ b/src/libxrpl/nodestore/backend/NullFactory.cpp @@ -108,12 +108,7 @@ public: } std::unique_ptr - createInstance( - size_t, - Section const&, - std::size_t, - Scheduler&, - beast::Journal) override + createInstance(size_t, Section const&, std::size_t, Scheduler&, beast::Journal) override { return std::make_unique(); } diff --git a/src/libxrpl/nodestore/backend/RocksDBFactory.cpp b/src/libxrpl/nodestore/backend/RocksDBFactory.cpp index 97d5484554..a35f737528 100644 --- a/src/libxrpl/nodestore/backend/RocksDBFactory.cpp +++ b/src/libxrpl/nodestore/backend/RocksDBFactory.cpp @@ -81,10 +81,7 @@ public: Scheduler& scheduler, beast::Journal journal, RocksDBEnv* env) - : m_deletePath(false) - , m_journal(journal) - , m_keyBytes(keyBytes) - , m_batch(*this, scheduler) + : m_deletePath(false), m_journal(journal), m_keyBytes(keyBytes), m_batch(*this, scheduler) { if (!get_if_exists(keyValues, "path", m_name)) Throw("Missing path in RocksDBFactory backend"); @@ -92,8 +89,7 @@ public: rocksdb::BlockBasedTableOptions table_options; m_options.env = env; - bool hard_set = - keyValues.exists("hard_set") && get(keyValues, "hard_set"); + bool hard_set = keyValues.exists("hard_set") && get(keyValues, "hard_set"); if (keyValues.exists("cache_mb")) { @@ -107,10 +103,8 @@ public: if (auto const v = get(keyValues, "filter_bits")) { - bool const filter_blocks = !keyValues.exists("filter_full") || - (get(keyValues, "filter_full") == 0); - table_options.filter_policy.reset( - rocksdb::NewBloomFilterPolicy(v, filter_blocks)); + bool const filter_blocks = !keyValues.exists("filter_full") || (get(keyValues, "filter_full") == 0); + table_options.filter_policy.reset(rocksdb::NewBloomFilterPolicy(v, filter_blocks)); } if (get_if_exists(keyValues, "open_files", m_options.max_open_files)) @@ -129,25 +123,21 @@ public: file_size_mb = 256; m_options.target_file_size_base = megabytes(file_size_mb); - m_options.max_bytes_for_level_base = - 5 * m_options.target_file_size_base; + m_options.max_bytes_for_level_base = 5 * m_options.target_file_size_base; m_options.write_buffer_size = 2 * m_options.target_file_size_base; } - get_if_exists( - keyValues, "file_size_mult", m_options.target_file_size_multiplier); + get_if_exists(keyValues, "file_size_mult", m_options.target_file_size_multiplier); if (keyValues.exists("bg_threads")) { - m_options.env->SetBackgroundThreads( - get(keyValues, "bg_threads"), rocksdb::Env::LOW); + m_options.env->SetBackgroundThreads(get(keyValues, "bg_threads"), rocksdb::Env::LOW); } if (keyValues.exists("high_threads")) { auto const highThreads = get(keyValues, "high_threads"); - m_options.env->SetBackgroundThreads( - highThreads, rocksdb::Env::HIGH); + m_options.env->SetBackgroundThreads(highThreads, rocksdb::Env::HIGH); // If we have high-priority threads, presumably we want to // use them for background flushes @@ -159,8 +149,7 @@ public: get_if_exists(keyValues, "block_size", table_options.block_size); - if (keyValues.exists("universal_compaction") && - (get(keyValues, "universal_compaction") != 0)) + if (keyValues.exists("universal_compaction") && (get(keyValues, "universal_compaction") != 0)) { m_options.compaction_style = rocksdb::kCompactionStyleUniversal; m_options.min_write_buffer_number_to_merge = 2; @@ -172,26 +161,18 @@ public: { rocksdb::ConfigOptions config_options; auto const s = rocksdb::GetBlockBasedTableOptionsFromString( - config_options, - table_options, - get(keyValues, "bbt_options"), - &table_options); + config_options, table_options, get(keyValues, "bbt_options"), &table_options); if (!s.ok()) - Throw( - std::string("Unable to set RocksDB bbt_options: ") + - s.ToString()); + Throw(std::string("Unable to set RocksDB bbt_options: ") + s.ToString()); } m_options.table_factory.reset(NewBlockBasedTableFactory(table_options)); if (keyValues.exists("options")) { - auto const s = rocksdb::GetOptionsFromString( - m_options, get(keyValues, "options"), &m_options); + auto const s = rocksdb::GetOptionsFromString(m_options, get(keyValues, "options"), &m_options); if (!s.ok()) - Throw( - std::string("Unable to set RocksDB options: ") + - s.ToString()); + Throw(std::string("Unable to set RocksDB options: ") + s.ToString()); } std::string s1, s2; @@ -223,9 +204,7 @@ public: m_options.create_if_missing = createIfMissing; rocksdb::Status status = rocksdb::DB::Open(m_options, m_name, &db); if (!status.ok() || !db) - Throw( - std::string("Unable to open/create RocksDB: ") + - status.ToString()); + Throw(std::string("Unable to open/create RocksDB: ") + status.ToString()); m_db.reset(db); } @@ -260,8 +239,7 @@ public: Status fetch(void const* key, std::shared_ptr* pObject) override { - XRPL_ASSERT( - m_db, "xrpl::NodeStore::RocksDBBackend::fetch : non-null database"); + XRPL_ASSERT(m_db, "xrpl::NodeStore::RocksDBBackend::fetch : non-null database"); pObject->reset(); Status status(ok); @@ -300,8 +278,7 @@ public: } else { - status = - Status(customCode + unsafe_cast(getStatus.code())); + status = Status(customCode + unsafe_cast(getStatus.code())); JLOG(m_journal.error()) << getStatus.ToString(); } @@ -348,12 +325,8 @@ public: EncodedBlob encoded(e); wb.Put( - rocksdb::Slice( - reinterpret_cast(encoded.getKey()), - m_keyBytes), - rocksdb::Slice( - reinterpret_cast(encoded.getData()), - encoded.getSize())); + rocksdb::Slice(reinterpret_cast(encoded.getKey()), m_keyBytes), + rocksdb::Slice(reinterpret_cast(encoded.getData()), encoded.getSize())); } rocksdb::WriteOptions const options; @@ -372,9 +345,7 @@ public: void for_each(std::function)> f) override { - XRPL_ASSERT( - m_db, - "xrpl::NodeStore::RocksDBBackend::for_each : non-null database"); + XRPL_ASSERT(m_db, "xrpl::NodeStore::RocksDBBackend::for_each : non-null database"); rocksdb::ReadOptions const options; std::unique_ptr it(m_db->NewIterator(options)); @@ -383,8 +354,7 @@ public: { if (it->key().size() == m_keyBytes) { - DecodedBlob decoded( - it->key().data(), it->value().data(), it->value().size()); + DecodedBlob decoded(it->key().data(), it->value().data(), it->value().size()); if (decoded.wasOk()) { @@ -393,16 +363,14 @@ public: else { // Uh oh, corrupted data! - JLOG(m_journal.fatal()) - << "Corrupt NodeObject #" << it->key().ToString(true); + JLOG(m_journal.fatal()) << "Corrupt NodeObject #" << it->key().ToString(true); } } else { // VFALCO NOTE What does it mean to find an // incorrectly sized key? Corruption? - JLOG(m_journal.fatal()) - << "Bad key size = " << it->key().size(); + JLOG(m_journal.fatal()) << "Bad key size = " << it->key().size(); } } } @@ -457,15 +425,10 @@ public: } std::unique_ptr - createInstance( - size_t keyBytes, - Section const& keyValues, - std::size_t, - Scheduler& scheduler, - beast::Journal journal) override + createInstance(size_t keyBytes, Section const& keyValues, std::size_t, Scheduler& scheduler, beast::Journal journal) + override { - return std::make_unique( - keyBytes, keyValues, scheduler, journal, &m_env); + return std::make_unique(keyBytes, keyValues, scheduler, journal, &m_env); } }; diff --git a/src/libxrpl/protocol/AMMCore.cpp b/src/libxrpl/protocol/AMMCore.cpp index 71ce6ea98e..bb83be2724 100644 --- a/src/libxrpl/protocol/AMMCore.cpp +++ b/src/libxrpl/protocol/AMMCore.cpp @@ -29,24 +29,18 @@ ammLPTCurrency(Currency const& cur1, Currency const& cur2) auto const hash = sha512Half(minC, maxC); Currency currency; *currency.begin() = AMMCurrencyCode; - std::copy( - hash.begin(), hash.begin() + currency.size() - 1, currency.begin() + 1); + std::copy(hash.begin(), hash.begin() + currency.size() - 1, currency.begin() + 1); return currency; } Issue -ammLPTIssue( - Currency const& cur1, - Currency const& cur2, - AccountID const& ammAccountID) +ammLPTIssue(Currency const& cur1, Currency const& cur2, AccountID const& ammAccountID) { return Issue(ammLPTCurrency(cur1, cur2), ammAccountID); } NotTEC -invalidAMMAsset( - Issue const& issue, - std::optional> const& pair) +invalidAMMAsset(Issue const& issue, std::optional> const& pair) { if (badCurrency() == issue.currency) return temBAD_CURRENCY; @@ -58,10 +52,7 @@ invalidAMMAsset( } NotTEC -invalidAMMAssetPair( - Issue const& issue1, - Issue const& issue2, - std::optional> const& pair) +invalidAMMAssetPair(Issue const& issue1, Issue const& issue2, std::optional> const& pair) { if (issue1 == issue2) return temBAD_AMM_TOKENS; @@ -73,10 +64,7 @@ invalidAMMAssetPair( } NotTEC -invalidAMMAmount( - STAmount const& amount, - std::optional> const& pair, - bool validZero) +invalidAMMAmount(STAmount const& amount, std::optional> const& pair, bool validZero) { if (auto const res = invalidAMMAsset(amount.issue(), pair)) return res; @@ -91,13 +79,10 @@ ammAuctionTimeSlot(std::uint64_t current, STObject const& auctionSlot) // It should be impossible for expiration to be < TOTAL_TIME_SLOT_SECS, // but check just to be safe auto const expiration = auctionSlot[sfExpiration]; - XRPL_ASSERT( - expiration >= TOTAL_TIME_SLOT_SECS, - "xrpl::ammAuctionTimeSlot : minimum expiration"); + XRPL_ASSERT(expiration >= TOTAL_TIME_SLOT_SECS, "xrpl::ammAuctionTimeSlot : minimum expiration"); if (expiration >= TOTAL_TIME_SLOT_SECS) { - if (auto const start = expiration - TOTAL_TIME_SLOT_SECS; - current >= start) + if (auto const start = expiration - TOTAL_TIME_SLOT_SECS; current >= start) { if (auto const diff = current - start; diff < TOTAL_TIME_SLOT_SECS) return diff / AUCTION_SLOT_INTERVAL_DURATION; diff --git a/src/libxrpl/protocol/AccountID.cpp b/src/libxrpl/protocol/AccountID.cpp index 779018613f..4edbf5c0e7 100644 --- a/src/libxrpl/protocol/AccountID.cpp +++ b/src/libxrpl/protocol/AccountID.cpp @@ -63,12 +63,9 @@ public: return cache_[index].encoding; } - auto ret = - encodeBase58Token(TokenType::AccountID, id.data(), id.size()); + auto ret = encodeBase58Token(TokenType::AccountID, id.data(), id.size()); - XRPL_ASSERT( - ret.size() <= 38, - "xrpl::detail::AccountIdCache : maximum result size"); + XRPL_ASSERT(ret.size() <= 38, "xrpl::detail::AccountIdCache : maximum result size"); { std::lock_guard lock(sl); diff --git a/src/libxrpl/protocol/Asset.cpp b/src/libxrpl/protocol/Asset.cpp index 1a4a94f744..0076da6570 100644 --- a/src/libxrpl/protocol/Asset.cpp +++ b/src/libxrpl/protocol/Asset.cpp @@ -16,9 +16,7 @@ namespace xrpl { AccountID const& Asset::getIssuer() const { - return std::visit( - [&](auto&& issue) -> AccountID const& { return issue.getIssuer(); }, - issue_); + return std::visit([&](auto&& issue) -> AccountID const& { return issue.getIssuer(); }, issue_); } std::string @@ -42,8 +40,7 @@ Asset::operator()(Number const& number) const std::string to_string(Asset const& asset) { - return std::visit( - [&](auto const& issue) { return to_string(issue); }, asset.value()); + return std::visit([&](auto const& issue) { return to_string(issue); }, asset.value()); } bool @@ -58,8 +55,7 @@ Asset assetFromJson(Json::Value const& v) { if (!v.isMember(jss::currency) && !v.isMember(jss::mpt_issuance_id)) - Throw( - "assetFromJson must contain currency or mpt_issuance_id"); + Throw("assetFromJson must contain currency or mpt_issuance_id"); if (v.isMember(jss::currency)) return issueFromJson(v); diff --git a/src/libxrpl/protocol/Book.cpp b/src/libxrpl/protocol/Book.cpp index d26aaf3384..59ad739c11 100644 --- a/src/libxrpl/protocol/Book.cpp +++ b/src/libxrpl/protocol/Book.cpp @@ -9,8 +9,7 @@ namespace xrpl { bool isConsistent(Book const& book) { - return isConsistent(book.in) && isConsistent(book.out) && - book.in != book.out; + return isConsistent(book.in) && isConsistent(book.out) && book.in != book.out; } std::string diff --git a/src/libxrpl/protocol/BuildInfo.cpp b/src/libxrpl/protocol/BuildInfo.cpp index b5e2354165..c86ef17449 100644 --- a/src/libxrpl/protocol/BuildInfo.cpp +++ b/src/libxrpl/protocol/BuildInfo.cpp @@ -67,10 +67,8 @@ getFullVersionString() return value; } -static constexpr std::uint64_t implementationVersionIdentifier = - 0x183B'0000'0000'0000LLU; -static constexpr std::uint64_t implementationVersionIdentifierMask = - 0xFFFF'0000'0000'0000LLU; +static constexpr std::uint64_t implementationVersionIdentifier = 0x183B'0000'0000'0000LLU; +static constexpr std::uint64_t implementationVersionIdentifierMask = 0xFFFF'0000'0000'0000LLU; std::uint64_t encodeSoftwareVersion(char const* const versionStr) @@ -109,9 +107,7 @@ encodeSoftwareVersion(char const* const versionStr) if (prefix != identifier.substr(0, prefix.length())) return 0; - if (!beast::lexicalCastChecked( - ret, - std::string(identifier.substr(prefix.length())))) + if (!beast::lexicalCastChecked(ret, std::string(identifier.substr(prefix.length())))) return 0; if (std::clamp(ret, lok, hik) != ret) @@ -147,8 +143,7 @@ getEncodedVersion() bool isRippledVersion(std::uint64_t version) { - return (version & implementationVersionIdentifierMask) == - implementationVersionIdentifier; + return (version & implementationVersionIdentifierMask) == implementationVersionIdentifier; } bool diff --git a/src/libxrpl/protocol/ErrorCodes.cpp b/src/libxrpl/protocol/ErrorCodes.cpp index d78ff594e1..33ec869db6 100644 --- a/src/libxrpl/protocol/ErrorCodes.cpp +++ b/src/libxrpl/protocol/ErrorCodes.cpp @@ -221,9 +221,7 @@ error_code_http_status(error_code_i code) std::string rpcErrorString(Json::Value const& jv) { - XRPL_ASSERT( - RPC::contains_error(jv), - "xrpl::RPC::rpcErrorString : input contains an error"); + XRPL_ASSERT(RPC::contains_error(jv), "xrpl::RPC::rpcErrorString : input contains an error"); return jv[jss::error].asString() + jv[jss::error_message].asString(); } diff --git a/src/libxrpl/protocol/Feature.cpp b/src/libxrpl/protocol/Feature.cpp index dc4fd105b5..834341f8d6 100644 --- a/src/libxrpl/protocol/Feature.cpp +++ b/src/libxrpl/protocol/Feature.cpp @@ -70,8 +70,7 @@ class FeatureCollections uint256 feature; Feature() = delete; - explicit Feature(std::string const& name_, uint256 const& feature_) - : name(name_), feature(feature_) + explicit Feature(std::string const& name_, uint256 const& feature_) : name(name_), feature(feature_) { } @@ -91,21 +90,18 @@ class FeatureCollections // Intermediate types to help with readability template - using feature_hashed_unique = boost::multi_index::hashed_unique< - boost::multi_index::tag, - boost::multi_index::member>; + using feature_hashed_unique = boost::multi_index:: + hashed_unique, boost::multi_index::member>; // Intermediate types to help with readability using feature_indexing = boost::multi_index::indexed_by< - boost::multi_index::random_access< - boost::multi_index::tag>, + boost::multi_index::random_access>, feature_hashed_unique, feature_hashed_unique>; // This multi_index_container provides access to the features collection by // name, index, and uint256 feature identifier - boost::multi_index::multi_index_container - features; + boost::multi_index::multi_index_container features; std::map all; std::map supported; std::size_t upVotes = 0; @@ -152,10 +148,7 @@ public: getRegisteredFeature(std::string const& name) const; uint256 - registerFeature( - std::string const& name, - Supported support, - VoteBehavior vote); + registerFeature(std::string const& name, Supported support, VoteBehavior vote); /** Tell FeatureCollections when registration is complete. */ bool @@ -211,9 +204,7 @@ FeatureCollections::FeatureCollections() std::optional FeatureCollections::getRegisteredFeature(std::string const& name) const { - XRPL_ASSERT( - readOnly.load(), - "xrpl::FeatureCollections::getRegisteredFeature : startup completed"); + XRPL_ASSERT(readOnly.load(), "xrpl::FeatureCollections::getRegisteredFeature : startup completed"); Feature const* feature = getByName(name); if (feature) return feature->feature; @@ -228,10 +219,7 @@ check(bool condition, char const* logicErrorMessage) } uint256 -FeatureCollections::registerFeature( - std::string const& name, - Supported support, - VoteBehavior vote) +FeatureCollections::registerFeature(std::string const& name, Supported support, VoteBehavior vote) { check(!readOnly, "Attempting to register a feature after startup."); check( @@ -240,9 +228,7 @@ FeatureCollections::registerFeature( Feature const* i = getByName(name); if (!i) { - check( - features.size() < detail::numFeatures, - "More features defined than allocated."); + check(features.size() < detail::numFeatures, "More features defined than allocated."); auto const f = sha512Half(Slice(name.data(), name.size())); @@ -251,8 +237,7 @@ FeatureCollections::registerFeature( auto const getAmendmentSupport = [=]() { if (vote == VoteBehavior::Obsolete) return AmendmentSupport::Retired; - return support == Supported::yes ? AmendmentSupport::Supported - : AmendmentSupport::Unsupported; + return support == Supported::yes ? AmendmentSupport::Supported : AmendmentSupport::Unsupported; }; all.emplace(name, getAmendmentSupport()); @@ -265,15 +250,9 @@ FeatureCollections::registerFeature( else ++downVotes; } - check( - upVotes + downVotes == supported.size(), - "Feature counting logic broke"); - check( - supported.size() <= features.size(), - "More supported features than defined features"); - check( - features.size() == all.size(), - "The 'all' features list is populated incorrectly"); + check(upVotes + downVotes == supported.size(), "Feature counting logic broke"); + check(supported.size() <= features.size(), "More supported features than defined features"); + check(features.size() == all.size(), "The 'all' features list is populated incorrectly"); return f; } else @@ -292,9 +271,7 @@ FeatureCollections::registrationIsDone() size_t FeatureCollections::featureToBitsetIndex(uint256 const& f) const { - XRPL_ASSERT( - readOnly.load(), - "xrpl::FeatureCollections::featureToBitsetIndex : startup completed"); + XRPL_ASSERT(readOnly.load(), "xrpl::FeatureCollections::featureToBitsetIndex : startup completed"); Feature const* feature = getByFeature(f); if (!feature) @@ -306,9 +283,7 @@ FeatureCollections::featureToBitsetIndex(uint256 const& f) const uint256 const& FeatureCollections::bitsetIndexToFeature(size_t i) const { - XRPL_ASSERT( - readOnly.load(), - "xrpl::FeatureCollections::bitsetIndexToFeature : startup completed"); + XRPL_ASSERT(readOnly.load(), "xrpl::FeatureCollections::bitsetIndexToFeature : startup completed"); Feature const& feature = getByIndex(i); return feature.feature; } @@ -316,9 +291,7 @@ FeatureCollections::bitsetIndexToFeature(size_t i) const std::string FeatureCollections::featureToName(uint256 const& f) const { - XRPL_ASSERT( - readOnly.load(), - "xrpl::FeatureCollections::featureToName : startup completed"); + XRPL_ASSERT(readOnly.load(), "xrpl::FeatureCollections::featureToName : startup completed"); Feature const* feature = getByFeature(f); return feature ? feature->name : to_string(f); } @@ -416,10 +389,8 @@ featureToName(uint256 const& f) #pragma push_macro("XRPL_RETIRE_FIX") #undef XRPL_RETIRE_FIX -#define XRPL_FEATURE(name, supported, vote) \ - uint256 const feature##name = registerFeature(#name, supported, vote); -#define XRPL_FIX(name, supported, vote) \ - uint256 const fix##name = registerFeature("fix" #name, supported, vote); +#define XRPL_FEATURE(name, supported, vote) uint256 const feature##name = registerFeature(#name, supported, vote); +#define XRPL_FIX(name, supported, vote) uint256 const fix##name = registerFeature("fix" #name, supported, vote); // clang-format off #define XRPL_RETIRE_FEATURE(name) \ @@ -449,7 +420,6 @@ featureToName(uint256 const& f) // // Use initialization of one final static variable to set // featureCollections::readOnly. -[[maybe_unused]] static bool const readOnlySet = - featureCollections.registrationIsDone(); +[[maybe_unused]] static bool const readOnlySet = featureCollections.registrationIsDone(); } // namespace xrpl diff --git a/src/libxrpl/protocol/IOUAmount.cpp b/src/libxrpl/protocol/IOUAmount.cpp index 297c2bac12..cfad753edc 100644 --- a/src/libxrpl/protocol/IOUAmount.cpp +++ b/src/libxrpl/protocol/IOUAmount.cpp @@ -57,8 +57,7 @@ IOUAmount::fromNumber(Number const& number) // Need to create a default IOUAmount and assign directly so it doesn't try // to normalize, which calls fromNumber IOUAmount result{}; - std::tie(result.mantissa_, result.exponent_) = - number.normalizeToRange(minMantissa, maxMantissa); + std::tie(result.mantissa_, result.exponent_) = number.normalizeToRange(minMantissa, maxMantissa); return result; } @@ -182,11 +181,7 @@ to_string(IOUAmount const& amount) } IOUAmount -mulRatio( - IOUAmount const& amt, - std::uint32_t num, - std::uint32_t den, - bool roundUp) +mulRatio(IOUAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundUp) { using namespace boost::multiprecision; @@ -213,8 +208,7 @@ mulRatio( static auto log10Floor = [](uint128_t const& v) { // Find the index of the first element >= the requested element, the // index is the log of the element in the log table. - auto const l = - std::lower_bound(powerTable.begin(), powerTable.end(), v); + auto const l = std::lower_bound(powerTable.begin(), powerTable.end(), v); int index = std::distance(powerTable.begin(), l); // If we're not equal, subtract to get the floor if (*l != v) @@ -226,20 +220,17 @@ mulRatio( static auto log10Ceil = [](uint128_t const& v) { // Find the index of the first element >= the requested element, the // index is the log of the element in the log table. - auto const l = - std::lower_bound(powerTable.begin(), powerTable.end(), v); + auto const l = std::lower_bound(powerTable.begin(), powerTable.end(), v); return int(std::distance(powerTable.begin(), l)); }; - static auto const fl64 = - log10Floor(std::numeric_limits::max()); + static auto const fl64 = log10Floor(std::numeric_limits::max()); bool const neg = amt.mantissa() < 0; uint128_t const den128(den); // a 32 value * a 64 bit value and stored in a 128 bit value. This will // never overflow - uint128_t const mul = - uint128_t(neg ? -amt.mantissa() : amt.mantissa()) * uint128_t(num); + uint128_t const mul = uint128_t(neg ? -amt.mantissa() : amt.mantissa()) * uint128_t(num); auto low = mul / den128; uint128_t rem(mul - low * den128); diff --git a/src/libxrpl/protocol/Indexes.cpp b/src/libxrpl/protocol/Indexes.cpp index 0bdfeefc4d..33c836eab6 100644 --- a/src/libxrpl/protocol/Indexes.cpp +++ b/src/libxrpl/protocol/Indexes.cpp @@ -99,19 +99,15 @@ getBookBase(Book const& book) { XRPL_ASSERT(isConsistent(book), "xrpl::getBookBase : input is consistent"); - auto const index = book.domain ? indexHash( - LedgerNameSpace::BOOK_DIR, - book.in.currency, - book.out.currency, - book.in.account, - book.out.account, - *(book.domain)) - : indexHash( - LedgerNameSpace::BOOK_DIR, - book.in.currency, - book.out.currency, - book.in.account, - book.out.account); + auto const index = book.domain + ? indexHash( + LedgerNameSpace::BOOK_DIR, + book.in.currency, + book.out.currency, + book.in.account, + book.out.account, + *(book.domain)) + : indexHash(LedgerNameSpace::BOOK_DIR, book.in.currency, book.out.currency, book.in.account, book.out.account); // Return with quality 0. auto k = keylet::quality({ltDIR_NODE, index}, 0); @@ -122,8 +118,7 @@ getBookBase(Book const& book) uint256 getQualityNext(uint256 const& uBase) { - static constexpr uint256 nextQuality( - "0000000000000000000000000000000000000000000000010000000000000000"); + static constexpr uint256 nextQuality("0000000000000000000000000000000000000000000000010000000000000000"); return uBase + nextQuality; } @@ -137,8 +132,7 @@ getQuality(uint256 const& uBase) uint256 getTicketIndex(AccountID const& account, std::uint32_t ticketSeq) { - return indexHash( - LedgerNameSpace::TICKET, account, std::uint32_t(ticketSeq)); + return indexHash(LedgerNameSpace::TICKET, account, std::uint32_t(ticketSeq)); } uint256 @@ -177,8 +171,7 @@ child(uint256 const& key) noexcept Keylet const& skip() noexcept { - static Keylet const ret{ - ltLEDGER_HASHES, indexHash(LedgerNameSpace::SKIP_LIST)}; + static Keylet const ret{ltLEDGER_HASHES, indexHash(LedgerNameSpace::SKIP_LIST)}; return ret; } @@ -187,32 +180,27 @@ skip(LedgerIndex ledger) noexcept { return { ltLEDGER_HASHES, - indexHash( - LedgerNameSpace::SKIP_LIST, - std::uint32_t(static_cast(ledger) >> 16))}; + indexHash(LedgerNameSpace::SKIP_LIST, std::uint32_t(static_cast(ledger) >> 16))}; } Keylet const& amendments() noexcept { - static Keylet const ret{ - ltAMENDMENTS, indexHash(LedgerNameSpace::AMENDMENTS)}; + static Keylet const ret{ltAMENDMENTS, indexHash(LedgerNameSpace::AMENDMENTS)}; return ret; } Keylet const& fees() noexcept { - static Keylet const ret{ - ltFEE_SETTINGS, indexHash(LedgerNameSpace::FEE_SETTINGS)}; + static Keylet const ret{ltFEE_SETTINGS, indexHash(LedgerNameSpace::FEE_SETTINGS)}; return ret; } Keylet const& negativeUNL() noexcept { - static Keylet const ret{ - ltNEGATIVE_UNL, indexHash(LedgerNameSpace::NEGATIVE_UNL)}; + static Keylet const ret{ltNEGATIVE_UNL, indexHash(LedgerNameSpace::NEGATIVE_UNL)}; return ret; } @@ -223,10 +211,7 @@ book_t::operator()(Book const& b) const } Keylet -line( - AccountID const& id0, - AccountID const& id1, - Currency const& currency) noexcept +line(AccountID const& id0, AccountID const& id1, Currency const& currency) noexcept { // There is code in SetTrust that calls us with id0 == id1, to allow users // to locate and delete such "weird" trustlines. If we remove that code, we @@ -243,13 +228,7 @@ line( // two accounts (smallest then largest) and hash them in that order: auto const accounts = std::minmax(id0, id1); - return { - ltRIPPLE_STATE, - indexHash( - LedgerNameSpace::TRUST_LINE, - accounts.first, - accounts.second, - currency)}; + return {ltRIPPLE_STATE, indexHash(LedgerNameSpace::TRUST_LINE, accounts.first, accounts.second, currency)}; } Keylet @@ -261,8 +240,7 @@ offer(AccountID const& id, std::uint32_t seq) noexcept Keylet quality(Keylet const& k, std::uint64_t q) noexcept { - XRPL_ASSERT( - k.type == ltDIR_NODE, "xrpl::keylet::quality : valid input type"); + XRPL_ASSERT(k.type == ltDIR_NODE, "xrpl::keylet::quality : valid input type"); // Indexes are stored in big endian format: they print as hex as stored. // Most significant bytes are first and the least significant bytes @@ -280,9 +258,7 @@ quality(Keylet const& k, std::uint64_t q) noexcept Keylet next_t::operator()(Keylet const& k) const { - XRPL_ASSERT( - k.type == ltDIR_NODE, - "xrpl::keylet::next_t::operator() : valid input type"); + XRPL_ASSERT(k.type == ltDIR_NODE, "xrpl::keylet::next_t::operator() : valid input type"); return {ltDIR_NODE, getQualityNext(k.key)}; } @@ -304,8 +280,7 @@ ticket_t::operator()(AccountID const& id, SeqProxy ticketSeq) const static Keylet signers(AccountID const& account, std::uint32_t page) noexcept { - return { - ltSIGNER_LIST, indexHash(LedgerNameSpace::SIGNER_LIST, account, page)}; + return {ltSIGNER_LIST, indexHash(LedgerNameSpace::SIGNER_LIST, account, page)}; } Keylet @@ -323,25 +298,19 @@ check(AccountID const& id, std::uint32_t seq) noexcept Keylet depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept { - return { - ltDEPOSIT_PREAUTH, - indexHash(LedgerNameSpace::DEPOSIT_PREAUTH, owner, preauthorized)}; + return {ltDEPOSIT_PREAUTH, indexHash(LedgerNameSpace::DEPOSIT_PREAUTH, owner, preauthorized)}; } // Credentials should be sorted here, use credentials::makeSorted Keylet -depositPreauth( - AccountID const& owner, - std::set> const& authCreds) noexcept +depositPreauth(AccountID const& owner, std::set> const& authCreds) noexcept { std::vector hashes; hashes.reserve(authCreds.size()); for (auto const& o : authCreds) hashes.emplace_back(sha512Half(o.first, o.second)); - return { - ltDEPOSIT_PREAUTH, - indexHash(LedgerNameSpace::DEPOSIT_PREAUTH_CREDENTIALS, owner, hashes)}; + return {ltDEPOSIT_PREAUTH, indexHash(LedgerNameSpace::DEPOSIT_PREAUTH_CREDENTIALS, owner, hashes)}; } //------------------------------------------------------------------------------ @@ -376,9 +345,7 @@ escrow(AccountID const& src, std::uint32_t seq) noexcept Keylet payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept { - return { - ltPAYCHAN, - indexHash(LedgerNameSpace::XRP_PAYMENT_CHANNEL, src, dst, seq)}; + return {ltPAYCHAN, indexHash(LedgerNameSpace::XRP_PAYMENT_CHANNEL, src, dst, seq)}; } Keylet @@ -400,16 +367,14 @@ nftpage_max(AccountID const& owner) Keylet nftpage(Keylet const& k, uint256 const& token) { - XRPL_ASSERT( - k.type == ltNFTOKEN_PAGE, "xrpl::keylet::nftpage : valid input type"); + XRPL_ASSERT(k.type == ltNFTOKEN_PAGE, "xrpl::keylet::nftpage : valid input type"); return {ltNFTOKEN_PAGE, (k.key & ~nft::pageMask) + (token & nft::pageMask)}; } Keylet nftoffer(AccountID const& owner, std::uint32_t seq) { - return { - ltNFTOKEN_OFFER, indexHash(LedgerNameSpace::NFTOKEN_OFFER, owner, seq)}; + return {ltNFTOKEN_OFFER, indexHash(LedgerNameSpace::NFTOKEN_OFFER, owner, seq)}; } Keylet @@ -427,14 +392,8 @@ nft_sells(uint256 const& id) noexcept Keylet amm(Asset const& issue1, Asset const& issue2) noexcept { - auto const& [minI, maxI] = - std::minmax(issue1.get(), issue2.get()); - return amm(indexHash( - LedgerNameSpace::AMM, - minI.account, - minI.currency, - maxI.account, - maxI.currency)); + auto const& [minI, maxI] = std::minmax(issue1.get(), issue2.get()); + return amm(indexHash(LedgerNameSpace::AMM, minI.account, minI.currency, maxI.account, maxI.currency)); } Keylet @@ -446,9 +405,7 @@ amm(uint256 const& id) noexcept Keylet delegate(AccountID const& account, AccountID const& authorizedAccount) noexcept { - return { - ltDELEGATE, - indexHash(LedgerNameSpace::DELEGATE, account, authorizedAccount)}; + return {ltDELEGATE, indexHash(LedgerNameSpace::DELEGATE, account, authorizedAccount)}; } Keylet @@ -458,10 +415,7 @@ bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType) // there can only be one bridge per lockingChainCurrency. On the issuing // chain there can only be one bridge per issuingChainCurrency. auto const& issue = bridge.issue(chainType); - return { - ltBRIDGE, - indexHash( - LedgerNameSpace::BRIDGE, bridge.door(chainType), issue.currency)}; + return {ltBRIDGE, indexHash(LedgerNameSpace::BRIDGE, bridge.door(chainType), issue.currency)}; } Keylet @@ -513,9 +467,7 @@ mptIssuance(std::uint32_t seq, AccountID const& issuer) noexcept Keylet mptIssuance(MPTID const& issuanceID) noexcept { - return { - ltMPTOKEN_ISSUANCE, - indexHash(LedgerNameSpace::MPTOKEN_ISSUANCE, issuanceID)}; + return {ltMPTOKEN_ISSUANCE, indexHash(LedgerNameSpace::MPTOKEN_ISSUANCE, issuanceID)}; } Keylet @@ -527,19 +479,13 @@ mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept Keylet mptoken(uint256 const& issuanceKey, AccountID const& holder) noexcept { - return { - ltMPTOKEN, indexHash(LedgerNameSpace::MPTOKEN, issuanceKey, holder)}; + return {ltMPTOKEN, indexHash(LedgerNameSpace::MPTOKEN, issuanceKey, holder)}; } Keylet -credential( - AccountID const& subject, - AccountID const& issuer, - Slice const& credType) noexcept +credential(AccountID const& subject, AccountID const& issuer, Slice const& credType) noexcept { - return { - ltCREDENTIAL, - indexHash(LedgerNameSpace::CREDENTIAL, subject, issuer, credType)}; + return {ltCREDENTIAL, indexHash(LedgerNameSpace::CREDENTIAL, subject, issuer, credType)}; } Keylet @@ -563,9 +509,7 @@ loan(uint256 const& loanBrokerID, std::uint32_t loanSeq) noexcept Keylet permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept { - return { - ltPERMISSIONED_DOMAIN, - indexHash(LedgerNameSpace::PERMISSIONED_DOMAIN, account, seq)}; + return {ltPERMISSIONED_DOMAIN, indexHash(LedgerNameSpace::PERMISSIONED_DOMAIN, account, seq)}; } Keylet diff --git a/src/libxrpl/protocol/InnerObjectFormats.cpp b/src/libxrpl/protocol/InnerObjectFormats.cpp index 3eb73e7c9b..8139ef0f55 100644 --- a/src/libxrpl/protocol/InnerObjectFormats.cpp +++ b/src/libxrpl/protocol/InnerObjectFormats.cpp @@ -136,9 +136,7 @@ InnerObjectFormats::InnerObjectFormats() {sfCredentialType, soeREQUIRED}, }); - add(sfPermission.jsonName.c_str(), - sfPermission.getCode(), - {{sfPermissionValue, soeREQUIRED}}); + add(sfPermission.jsonName.c_str(), sfPermission.getCode(), {{sfPermissionValue, soeREQUIRED}}); add(sfBatchSigner.jsonName.c_str(), sfBatchSigner.getCode(), diff --git a/src/libxrpl/protocol/Issue.cpp b/src/libxrpl/protocol/Issue.cpp index ca5bf35e8b..f540b52050 100644 --- a/src/libxrpl/protocol/Issue.cpp +++ b/src/libxrpl/protocol/Issue.cpp @@ -83,14 +83,12 @@ issueFromJson(Json::Value const& v) { if (!v.isObject()) { - Throw( - "issueFromJson can only be specified with an 'object' Json value"); + Throw("issueFromJson can only be specified with an 'object' Json value"); } if (v.isMember(jss::mpt_issuance_id)) { - Throw( - "issueFromJson, Issue should not have mpt_issuance_id"); + Throw("issueFromJson, Issue should not have mpt_issuance_id"); } Json::Value const curStr = v[jss::currency]; @@ -98,8 +96,7 @@ issueFromJson(Json::Value const& v) if (!curStr.isString()) { - Throw( - "issueFromJson currency must be a string Json value"); + Throw("issueFromJson currency must be a string Json value"); } auto const currency = to_currency(curStr.asString()); diff --git a/src/libxrpl/protocol/Keylet.cpp b/src/libxrpl/protocol/Keylet.cpp index 2c65bb9ed4..18bd76440a 100644 --- a/src/libxrpl/protocol/Keylet.cpp +++ b/src/libxrpl/protocol/Keylet.cpp @@ -8,9 +8,7 @@ namespace xrpl { bool Keylet::check(STLedgerEntry const& sle) const { - XRPL_ASSERT( - sle.getType() != ltANY || sle.getType() != ltCHILD, - "xrpl::Keylet::check : valid input type"); + XRPL_ASSERT(sle.getType() != ltANY || sle.getType() != ltCHILD, "xrpl::Keylet::check : valid input type"); if (type == ltANY) return true; diff --git a/src/libxrpl/protocol/LedgerFormats.cpp b/src/libxrpl/protocol/LedgerFormats.cpp index 2056cfab7b..8d9a24f741 100644 --- a/src/libxrpl/protocol/LedgerFormats.cpp +++ b/src/libxrpl/protocol/LedgerFormats.cpp @@ -22,8 +22,7 @@ LedgerFormats::LedgerFormats() #undef LEDGER_ENTRY #define UNWRAP(...) __VA_ARGS__ -#define LEDGER_ENTRY(tag, value, name, rpcName, fields) \ - add(jss::name, tag, UNWRAP fields, commonFields); +#define LEDGER_ENTRY(tag, value, name, rpcName, fields) add(jss::name, tag, UNWRAP fields, commonFields); #include diff --git a/src/libxrpl/protocol/LedgerHeader.cpp b/src/libxrpl/protocol/LedgerHeader.cpp index 5258bdbc22..270833c6fa 100644 --- a/src/libxrpl/protocol/LedgerHeader.cpp +++ b/src/libxrpl/protocol/LedgerHeader.cpp @@ -34,8 +34,7 @@ deserializeHeader(Slice data, bool hasHash) header.parentHash = sit.get256(); header.txHash = sit.get256(); header.accountHash = sit.get256(); - header.parentCloseTime = - NetClock::time_point{NetClock::duration{sit.get32()}}; + header.parentCloseTime = NetClock::time_point{NetClock::duration{sit.get32()}}; header.closeTime = NetClock::time_point{NetClock::duration{sit.get32()}}; header.closeTimeResolution = NetClock::duration{sit.get8()}; header.closeFlags = sit.get8(); diff --git a/src/libxrpl/protocol/MPTIssue.cpp b/src/libxrpl/protocol/MPTIssue.cpp index c92ac60b73..9673d6071f 100644 --- a/src/libxrpl/protocol/MPTIssue.cpp +++ b/src/libxrpl/protocol/MPTIssue.cpp @@ -23,8 +23,7 @@ MPTIssue::getIssuer() const // MPTID is concatenation of sequence + account static_assert(sizeof(MPTID) == (sizeof(std::uint32_t) + sizeof(AccountID))); // copy from id skipping the sequence - AccountID const* account = reinterpret_cast( - mptID_.data() + sizeof(std::uint32_t)); + AccountID const* account = reinterpret_cast(mptID_.data() + sizeof(std::uint32_t)); return *account; } @@ -67,16 +66,14 @@ mptIssueFromJson(Json::Value const& v) if (v.isMember(jss::currency) || v.isMember(jss::issuer)) { - Throw( - "mptIssueFromJson, MPTIssue should not have currency or issuer"); + Throw("mptIssueFromJson, MPTIssue should not have currency or issuer"); } Json::Value const& idStr = v[jss::mpt_issuance_id]; if (!idStr.isString()) { - Throw( - "mptIssueFromJson MPTID must be a string Json value"); + Throw("mptIssueFromJson MPTID must be a string Json value"); } MPTID id; diff --git a/src/libxrpl/protocol/NFTokenID.cpp b/src/libxrpl/protocol/NFTokenID.cpp index 64fadce3c9..deed26360a 100644 --- a/src/libxrpl/protocol/NFTokenID.cpp +++ b/src/libxrpl/protocol/NFTokenID.cpp @@ -20,16 +20,13 @@ namespace xrpl { bool -canHaveNFTokenID( - std::shared_ptr const& serializedTx, - TxMeta const& transactionMeta) +canHaveNFTokenID(std::shared_ptr const& serializedTx, TxMeta const& transactionMeta) { if (!serializedTx) return false; TxType const tt = serializedTx->getTxnType(); - if (tt != ttNFTOKEN_MINT && tt != ttNFTOKEN_ACCEPT_OFFER && - tt != ttNFTOKEN_CANCEL_OFFER) + if (tt != ttNFTOKEN_MINT && tt != ttNFTOKEN_ACCEPT_OFFER && tt != ttNFTOKEN_CANCEL_OFFER) return false; // if the transaction failed nothing could have been delivered. @@ -56,14 +53,9 @@ getNFTokenIDFromPage(TxMeta const& transactionMeta) SField const& fName = node.getFName(); if (fName == sfCreatedNode) { - STArray const& toAddPrevNFTs = node.peekAtField(sfNewFields) - .downcast() - .getFieldArray(sfNFTokens); + STArray const& toAddPrevNFTs = node.peekAtField(sfNewFields).downcast().getFieldArray(sfNFTokens); std::transform( - toAddPrevNFTs.begin(), - toAddPrevNFTs.end(), - std::back_inserter(finalIDs), - [](STObject const& nft) { + toAddPrevNFTs.begin(), toAddPrevNFTs.end(), std::back_inserter(finalIDs), [](STObject const& nft) { return nft.getFieldH256(sfNFTokenID); }); } @@ -78,29 +70,20 @@ getNFTokenIDFromPage(TxMeta const& transactionMeta) // However, there will always be NFTs listed in the final fields, // as rippled outputs all fields in final fields even if they were // not changed. - STObject const& previousFields = - node.peekAtField(sfPreviousFields).downcast(); + STObject const& previousFields = node.peekAtField(sfPreviousFields).downcast(); if (!previousFields.isFieldPresent(sfNFTokens)) continue; - STArray const& toAddPrevNFTs = - previousFields.getFieldArray(sfNFTokens); + STArray const& toAddPrevNFTs = previousFields.getFieldArray(sfNFTokens); std::transform( - toAddPrevNFTs.begin(), - toAddPrevNFTs.end(), - std::back_inserter(prevIDs), - [](STObject const& nft) { + toAddPrevNFTs.begin(), toAddPrevNFTs.end(), std::back_inserter(prevIDs), [](STObject const& nft) { return nft.getFieldH256(sfNFTokenID); }); - STArray const& toAddFinalNFTs = node.peekAtField(sfFinalFields) - .downcast() - .getFieldArray(sfNFTokens); + STArray const& toAddFinalNFTs = + node.peekAtField(sfFinalFields).downcast().getFieldArray(sfNFTokens); std::transform( - toAddFinalNFTs.begin(), - toAddFinalNFTs.end(), - std::back_inserter(finalIDs), - [](STObject const& nft) { + toAddFinalNFTs.begin(), toAddFinalNFTs.end(), std::back_inserter(finalIDs), [](STObject const& nft) { return nft.getFieldH256(sfNFTokenID); }); } @@ -113,8 +96,7 @@ getNFTokenIDFromPage(TxMeta const& transactionMeta) // Find the first NFT ID that doesn't match. We're looking for an // added NFT, so the one we want will be the mismatch in finalIDs. - auto const diff = std::mismatch( - finalIDs.begin(), finalIDs.end(), prevIDs.begin(), prevIDs.end()); + auto const diff = std::mismatch(finalIDs.begin(), finalIDs.end(), prevIDs.begin(), prevIDs.end()); // There should always be a difference so the returned finalIDs // iterator should never be end(). But better safe than sorry. @@ -130,30 +112,22 @@ getNFTokenIDFromDeletedOffer(TxMeta const& transactionMeta) std::vector tokenIDResult; for (STObject const& node : transactionMeta.getNodes()) { - if (node.getFieldU16(sfLedgerEntryType) != ltNFTOKEN_OFFER || - node.getFName() != sfDeletedNode) + if (node.getFieldU16(sfLedgerEntryType) != ltNFTOKEN_OFFER || node.getFName() != sfDeletedNode) continue; - auto const& toAddNFT = node.peekAtField(sfFinalFields) - .downcast() - .getFieldH256(sfNFTokenID); + auto const& toAddNFT = node.peekAtField(sfFinalFields).downcast().getFieldH256(sfNFTokenID); tokenIDResult.push_back(toAddNFT); } // Deduplicate the NFT IDs because multiple offers could affect the same NFT // and hence we would get duplicate NFT IDs sort(tokenIDResult.begin(), tokenIDResult.end()); - tokenIDResult.erase( - unique(tokenIDResult.begin(), tokenIDResult.end()), - tokenIDResult.end()); + tokenIDResult.erase(unique(tokenIDResult.begin(), tokenIDResult.end()), tokenIDResult.end()); return tokenIDResult; } void -insertNFTokenID( - Json::Value& response, - std::shared_ptr const& transaction, - TxMeta const& transactionMeta) +insertNFTokenID(Json::Value& response, std::shared_ptr const& transaction, TxMeta const& transactionMeta) { if (!canHaveNFTokenID(transaction, transactionMeta)) return; @@ -167,16 +141,14 @@ insertNFTokenID( } else if (type == ttNFTOKEN_ACCEPT_OFFER) { - std::vector result = - getNFTokenIDFromDeletedOffer(transactionMeta); + std::vector result = getNFTokenIDFromDeletedOffer(transactionMeta); if (result.size() > 0) response[jss::nftoken_id] = to_string(result.front()); } else if (type == ttNFTOKEN_CANCEL_OFFER) { - std::vector result = - getNFTokenIDFromDeletedOffer(transactionMeta); + std::vector result = getNFTokenIDFromDeletedOffer(transactionMeta); response[jss::nftoken_ids] = Json::Value(Json::arrayValue); for (auto const& nftID : result) diff --git a/src/libxrpl/protocol/NFTokenOfferID.cpp b/src/libxrpl/protocol/NFTokenOfferID.cpp index b1a08081c0..bbd67d710c 100644 --- a/src/libxrpl/protocol/NFTokenOfferID.cpp +++ b/src/libxrpl/protocol/NFTokenOfferID.cpp @@ -16,16 +16,13 @@ namespace xrpl { bool -canHaveNFTokenOfferID( - std::shared_ptr const& serializedTx, - TxMeta const& transactionMeta) +canHaveNFTokenOfferID(std::shared_ptr const& serializedTx, TxMeta const& transactionMeta) { if (!serializedTx) return false; TxType const tt = serializedTx->getTxnType(); - if (!(tt == ttNFTOKEN_MINT && serializedTx->isFieldPresent(sfAmount)) && - tt != ttNFTOKEN_CREATE_OFFER) + if (!(tt == ttNFTOKEN_MINT && serializedTx->isFieldPresent(sfAmount)) && tt != ttNFTOKEN_CREATE_OFFER) return false; // if the transaction failed nothing could have been delivered. @@ -40,8 +37,7 @@ getOfferIDFromCreatedOffer(TxMeta const& transactionMeta) { for (STObject const& node : transactionMeta.getNodes()) { - if (node.getFieldU16(sfLedgerEntryType) != ltNFTOKEN_OFFER || - node.getFName() != sfCreatedNode) + if (node.getFieldU16(sfLedgerEntryType) != ltNFTOKEN_OFFER || node.getFName() != sfCreatedNode) continue; return node.getFieldH256(sfLedgerIndex); diff --git a/src/libxrpl/protocol/Permissions.cpp b/src/libxrpl/protocol/Permissions.cpp index 082a1792a4..7e592fdc7f 100644 --- a/src/libxrpl/protocol/Permissions.cpp +++ b/src/libxrpl/protocol/Permissions.cpp @@ -11,8 +11,7 @@ Permission::Permission() #pragma push_macro("TRANSACTION") #undef TRANSACTION -#define TRANSACTION(tag, value, name, delegable, amendment, ...) \ - {value, amendment}, +#define TRANSACTION(tag, value, name, delegable, amendment, ...) {value, amendment}, #include @@ -91,8 +90,7 @@ Permission::getPermissionName(std::uint32_t const value) const // not a granular permission, check if it maps to a transaction type auto const txType = permissionToTxType(value); - if (auto const* item = TxFormats::getInstance().findByType(txType); - item != nullptr) + if (auto const* item = TxFormats::getInstance().findByType(txType); item != nullptr) return item->getName(); return std::nullopt; @@ -132,9 +130,7 @@ std::optional> const Permission::getTxFeature(TxType txType) const { auto const txFeaturesIt = txFeatureMap_.find(txType); - XRPL_ASSERT( - txFeaturesIt != txFeatureMap_.end(), - "xrpl::Permissions::getTxFeature : tx exists in txFeatureMap_"); + XRPL_ASSERT(txFeaturesIt != txFeatureMap_.end(), "xrpl::Permissions::getTxFeature : tx exists in txFeatureMap_"); if (txFeaturesIt->second == uint256{}) return std::nullopt; @@ -142,12 +138,9 @@ Permission::getTxFeature(TxType txType) const } bool -Permission::isDelegable( - std::uint32_t const& permissionValue, - Rules const& rules) const +Permission::isDelegable(std::uint32_t const& permissionValue, Rules const& rules) const { - auto const granularPermission = - getGranularName(static_cast(permissionValue)); + auto const granularPermission = getGranularName(static_cast(permissionValue)); if (granularPermission) // granular permissions are always allowed to be delegated return true; @@ -159,15 +152,12 @@ Permission::isDelegable( return false; auto const txFeaturesIt = txFeatureMap_.find(txType); - XRPL_ASSERT( - txFeaturesIt != txFeatureMap_.end(), - "xrpl::Permissions::isDelegable : tx exists in txFeatureMap_"); + XRPL_ASSERT(txFeaturesIt != txFeatureMap_.end(), "xrpl::Permissions::isDelegable : tx exists in txFeatureMap_"); // Delegation is only allowed if the required amendment for the transaction // is enabled. For transactions that do not require an amendment, delegation // is always allowed. - if (txFeaturesIt->second != uint256{} && - !rules.enabled(txFeaturesIt->second)) + if (txFeaturesIt->second != uint256{} && !rules.enabled(txFeaturesIt->second)) return false; if (it->second == Delegation::notDelegable) diff --git a/src/libxrpl/protocol/PublicKey.cpp b/src/libxrpl/protocol/PublicKey.cpp index 2dcf484adc..b336b2d4b5 100644 --- a/src/libxrpl/protocol/PublicKey.cpp +++ b/src/libxrpl/protocol/PublicKey.cpp @@ -109,16 +109,11 @@ sliceToHex(Slice const& slice) std::optional ecdsaCanonicality(Slice const& sig) { - using uint264 = - boost::multiprecision::number>; + using uint264 = boost::multiprecision::number< + boost::multiprecision:: + cpp_int_backend<264, 264, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void>>; - static uint264 const G( - "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); + static uint264 const G("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); // The format of a signature should be: // <30> [ <02> ] [ <02> ] @@ -155,9 +150,8 @@ ed25519Canonical(Slice const& sig) return false; // Big-endian Order, the Ed25519 subgroup order std::uint8_t const Order[] = { - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, - 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED, }; // Take the second half of signature // and byte-reverse it to big-endian. @@ -216,19 +210,14 @@ publicKeyType(Slice const& slice) } bool -verifyDigest( - PublicKey const& publicKey, - uint256 const& digest, - Slice const& sig, - bool mustBeFullyCanonical) noexcept +verifyDigest(PublicKey const& publicKey, uint256 const& digest, Slice const& sig, bool mustBeFullyCanonical) noexcept { if (publicKeyType(publicKey) != KeyType::secp256k1) LogicError("sign: secp256k1 required for digest signing"); auto const canonicality = ecdsaCanonicality(sig); if (!canonicality) return false; - if (mustBeFullyCanonical && - (*canonicality != ECDSACanonicality::fullyCanonical)) + if (mustBeFullyCanonical && (*canonicality != ECDSACanonicality::fullyCanonical)) return false; secp256k1_pubkey pubkey_imp; @@ -241,28 +230,19 @@ verifyDigest( secp256k1_ecdsa_signature sig_imp; if (secp256k1_ecdsa_signature_parse_der( - secp256k1Context(), - &sig_imp, - reinterpret_cast(sig.data()), - sig.size()) != 1) + secp256k1Context(), &sig_imp, reinterpret_cast(sig.data()), sig.size()) != 1) return false; if (*canonicality != ECDSACanonicality::fullyCanonical) { secp256k1_ecdsa_signature sig_norm; - if (secp256k1_ecdsa_signature_normalize( - secp256k1Context(), &sig_norm, &sig_imp) != 1) + if (secp256k1_ecdsa_signature_normalize(secp256k1Context(), &sig_norm, &sig_imp) != 1) return false; return secp256k1_ecdsa_verify( - secp256k1Context(), - &sig_norm, - reinterpret_cast(digest.data()), - &pubkey_imp) == 1; + secp256k1Context(), &sig_norm, reinterpret_cast(digest.data()), &pubkey_imp) == + 1; } return secp256k1_ecdsa_verify( - secp256k1Context(), - &sig_imp, - reinterpret_cast(digest.data()), - &pubkey_imp) == 1; + secp256k1Context(), &sig_imp, reinterpret_cast(digest.data()), &pubkey_imp) == 1; } bool @@ -283,9 +263,7 @@ verify(PublicKey const& publicKey, Slice const& m, Slice const& sig) noexcept // byte to distinguish them from secp256k1 keys // so when verifying the signature, we need to // first strip that prefix. - return ed25519_sign_open( - m.data(), m.size(), publicKey.data() + 1, sig.data()) == - 0; + return ed25519_sign_open(m.data(), m.size(), publicKey.data() + 1, sig.data()) == 0; } } return false; diff --git a/src/libxrpl/protocol/Quality.cpp b/src/libxrpl/protocol/Quality.cpp index cd56f237fc..fda0ac2e1e 100644 --- a/src/libxrpl/protocol/Quality.cpp +++ b/src/libxrpl/protocol/Quality.cpp @@ -13,8 +13,7 @@ Quality::Quality(std::uint64_t value) : m_value(value) { } -Quality::Quality(Amounts const& amount) - : m_value(getRate(amount.out, amount.in)) +Quality::Quality(Amounts const& amount) : m_value(getRate(amount.out, amount.in)) { } @@ -37,9 +36,7 @@ Quality::operator++(int) Quality& Quality::operator--() { - XRPL_ASSERT( - m_value < std::numeric_limits::max(), - "xrpl::Quality::operator--() : maximum value"); + XRPL_ASSERT(m_value < std::numeric_limits::max(), "xrpl::Quality::operator--() : maximum value"); ++m_value; return *this; } @@ -52,25 +49,17 @@ Quality::operator--(int) return prev; } -template +template static Amounts -ceil_in_impl( - Amounts const& amount, - STAmount const& limit, - bool roundUp, - Quality const& quality) +ceil_in_impl(Amounts const& amount, STAmount const& limit, bool roundUp, Quality const& quality) { if (amount.in > limit) { - Amounts result( - limit, - DivRoundFunc(limit, quality.rate(), amount.out.asset(), roundUp)); + Amounts result(limit, DivRoundFunc(limit, quality.rate(), amount.out.asset(), roundUp)); // Clamp out if (result.out > amount.out) result.out = amount.out; - XRPL_ASSERT( - result.in == limit, "xrpl::ceil_in_impl : result matches limit"); + XRPL_ASSERT(result.in == limit, "xrpl::ceil_in_impl : result matches limit"); return result; } XRPL_ASSERT(amount.in <= limit, "xrpl::ceil_in_impl : result inside limit"); @@ -84,37 +73,25 @@ Quality::ceil_in(Amounts const& amount, STAmount const& limit) const } Amounts -Quality::ceil_in_strict( - Amounts const& amount, - STAmount const& limit, - bool roundUp) const +Quality::ceil_in_strict(Amounts const& amount, STAmount const& limit, bool roundUp) const { return ceil_in_impl(amount, limit, roundUp, *this); } -template +template static Amounts -ceil_out_impl( - Amounts const& amount, - STAmount const& limit, - bool roundUp, - Quality const& quality) +ceil_out_impl(Amounts const& amount, STAmount const& limit, bool roundUp, Quality const& quality) { if (amount.out > limit) { - Amounts result( - MulRoundFunc(limit, quality.rate(), amount.in.asset(), roundUp), - limit); + Amounts result(MulRoundFunc(limit, quality.rate(), amount.in.asset(), roundUp), limit); // Clamp in if (result.in > amount.in) result.in = amount.in; - XRPL_ASSERT( - result.out == limit, "xrpl::ceil_out_impl : result matches limit"); + XRPL_ASSERT(result.out == limit, "xrpl::ceil_out_impl : result matches limit"); return result; } - XRPL_ASSERT( - amount.out <= limit, "xrpl::ceil_out_impl : result inside limit"); + XRPL_ASSERT(amount.out <= limit, "xrpl::ceil_out_impl : result inside limit"); return amount; } @@ -125,10 +102,7 @@ Quality::ceil_out(Amounts const& amount, STAmount const& limit) const } Amounts -Quality::ceil_out_strict( - Amounts const& amount, - STAmount const& limit, - bool roundUp) const +Quality::ceil_out_strict(Amounts const& amount, STAmount const& limit, bool roundUp) const { return ceil_out_impl(amount, limit, roundUp, *this); } @@ -137,22 +111,17 @@ Quality composed_quality(Quality const& lhs, Quality const& rhs) { STAmount const lhs_rate(lhs.rate()); - XRPL_ASSERT( - lhs_rate != beast::zero, "xrpl::composed_quality : nonzero left input"); + XRPL_ASSERT(lhs_rate != beast::zero, "xrpl::composed_quality : nonzero left input"); STAmount const rhs_rate(rhs.rate()); - XRPL_ASSERT( - rhs_rate != beast::zero, - "xrpl::composed_quality : nonzero right input"); + XRPL_ASSERT(rhs_rate != beast::zero, "xrpl::composed_quality : nonzero right input"); STAmount const rate(mulRound(lhs_rate, rhs_rate, lhs_rate.asset(), true)); std::uint64_t const stored_exponent(rate.exponent() + 100); std::uint64_t const stored_mantissa(rate.mantissa()); - XRPL_ASSERT( - (stored_exponent > 0) && (stored_exponent <= 255), - "xrpl::composed_quality : valid exponent"); + XRPL_ASSERT((stored_exponent > 0) && (stored_exponent <= 255), "xrpl::composed_quality : valid exponent"); return Quality((stored_exponent << (64 - 8)) | stored_mantissa); } diff --git a/src/libxrpl/protocol/QualityFunction.cpp b/src/libxrpl/protocol/QualityFunction.cpp index b254e1af86..db004bf478 100644 --- a/src/libxrpl/protocol/QualityFunction.cpp +++ b/src/libxrpl/protocol/QualityFunction.cpp @@ -9,10 +9,7 @@ namespace xrpl { -QualityFunction::QualityFunction( - Quality const& quality, - QualityFunction::CLOBLikeTag) - : m_(0), b_(0), quality_(quality) +QualityFunction::QualityFunction(Quality const& quality, QualityFunction::CLOBLikeTag) : m_(0), b_(0), quality_(quality) { if (quality.rate() <= beast::zero) Throw("QualityFunction quality rate is 0."); diff --git a/src/libxrpl/protocol/Rate2.cpp b/src/libxrpl/protocol/Rate2.cpp index 511b28cc67..490474fdb1 100644 --- a/src/libxrpl/protocol/Rate2.cpp +++ b/src/libxrpl/protocol/Rate2.cpp @@ -53,14 +53,9 @@ multiplyRound(STAmount const& amount, Rate const& rate, bool roundUp) } STAmount -multiplyRound( - STAmount const& amount, - Rate const& rate, - Asset const& asset, - bool roundUp) +multiplyRound(STAmount const& amount, Rate const& rate, Asset const& asset, bool roundUp) { - XRPL_ASSERT( - rate.value, "xrpl::nft::multiplyRound(Issue) : nonzero rate input"); + XRPL_ASSERT(rate.value, "xrpl::nft::multiplyRound(Issue) : nonzero rate input"); if (rate == parityRate) { @@ -93,14 +88,9 @@ divideRound(STAmount const& amount, Rate const& rate, bool roundUp) } STAmount -divideRound( - STAmount const& amount, - Rate const& rate, - Asset const& asset, - bool roundUp) +divideRound(STAmount const& amount, Rate const& rate, Asset const& asset, bool roundUp) { - XRPL_ASSERT( - rate.value, "xrpl::nft::divideRound(Issue) : nonzero rate input"); + XRPL_ASSERT(rate.value, "xrpl::nft::divideRound(Issue) : nonzero rate input"); if (rate == parityRate) return amount; diff --git a/src/libxrpl/protocol/Rules.cpp b/src/libxrpl/protocol/Rules.cpp index 3710322699..e649b15ea2 100644 --- a/src/libxrpl/protocol/Rules.cpp +++ b/src/libxrpl/protocol/Rules.cpp @@ -39,11 +39,8 @@ setCurrentTransactionRules(std::optional r) // Make global changes associated with the rules before the value is moved. // Push the appropriate setting, instead of having the class pull every time // the value is needed. That could get expensive fast. - bool enableLargeNumbers = !r || - (r->enabled(featureSingleAssetVault) || - r->enabled(featureLendingProtocol)); - Number::setMantissaScale( - enableLargeNumbers ? MantissaRange::large : MantissaRange::small); + bool enableLargeNumbers = !r || (r->enabled(featureSingleAssetVault) || r->enabled(featureLendingProtocol)); + Number::setMantissaScale(enableLargeNumbers ? MantissaRange::large : MantissaRange::small); *getCurrentTransactionRulesRef() = std::move(r); } @@ -56,8 +53,7 @@ private: std::unordered_set> const& presets_; public: - explicit Impl(std::unordered_set> const& presets) - : presets_(presets) + explicit Impl(std::unordered_set> const& presets) : presets_(presets) { } @@ -100,8 +96,7 @@ public: } }; -Rules::Rules(std::unordered_set> const& presets) - : impl_(std::make_shared(presets)) +Rules::Rules(std::unordered_set> const& presets) : impl_(std::make_shared(presets)) { } @@ -130,9 +125,7 @@ Rules::enabled(uint256 const& feature) const bool Rules::operator==(Rules const& other) const { - XRPL_ASSERT( - impl_ && other.impl_, - "xrpl::Rules::operator==(Rules) const : both initialized"); + XRPL_ASSERT(impl_ && other.impl_, "xrpl::Rules::operator==(Rules) const : both initialized"); if (impl_.get() == other.impl_.get()) return true; return *impl_ == *other.impl_; diff --git a/src/libxrpl/protocol/SField.cpp b/src/libxrpl/protocol/SField.cpp index 54402ea6e2..c04c82f2bc 100644 --- a/src/libxrpl/protocol/SField.cpp +++ b/src/libxrpl/protocol/SField.cpp @@ -22,8 +22,7 @@ static SField::private_access_tag_t access; template template -TypedField::TypedField(private_access_tag_t pat, Args&&... args) - : SField(pat, std::forward(args)...) +TypedField::TypedField(private_access_tag_t pat, Args&&... args) : SField(pat, std::forward(args)...) { } @@ -37,19 +36,10 @@ TypedField::TypedField(private_access_tag_t pat, Args&&... args) #undef TYPED_SFIELD #define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \ - SField const sfName( \ - access, \ - STI_##stiSuffix, \ - fieldValue, \ - std::string_view(#sfName).substr(2).data(), \ - ##__VA_ARGS__); + SField const sfName(access, STI_##stiSuffix, fieldValue, std::string_view(#sfName).substr(2).data(), ##__VA_ARGS__); #define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \ SF_##stiSuffix const sfName( \ - access, \ - STI_##stiSuffix, \ - fieldValue, \ - std::string_view(#sfName).substr(2).data(), \ - ##__VA_ARGS__); + access, STI_##stiSuffix, fieldValue, std::string_view(#sfName).substr(2).data(), ##__VA_ARGS__); // SFields which, for historical reasons, do not follow naming conventions. SField const sfInvalid(access, -1, ""); @@ -66,13 +56,7 @@ SField const sfIndex(access, STI_UINT256, 258, "index"); #undef UNTYPED_SFIELD #pragma pop_macro("UNTYPED_SFIELD") -SField::SField( - private_access_tag_t, - SerializedTypeID tid, - int fv, - char const* fn, - int meta, - IsSigning signing) +SField::SField(private_access_tag_t, SerializedTypeID tid, int fv, char const* fn, int meta, IsSigning signing) : fieldCode(field_code(tid, fv)) , fieldType(tid) , fieldValue(fv) @@ -83,11 +67,9 @@ SField::SField( , jsonName(fieldName.c_str()) { XRPL_ASSERT( - !knownCodeToField.contains(fieldCode), - "xrpl::SField::SField(tid,fv,fn,meta,signing) : fieldCode is unique"); + !knownCodeToField.contains(fieldCode), "xrpl::SField::SField(tid,fv,fn,meta,signing) : fieldCode is unique"); XRPL_ASSERT( - !knownNameToField.contains(fieldName), - "xrpl::SField::SField(tid,fv,fn,meta,signing) : fieldName is unique"); + !knownNameToField.contains(fieldName), "xrpl::SField::SField(tid,fv,fn,meta,signing) : fieldName is unique"); knownCodeToField[fieldCode] = this; knownNameToField[fieldName] = this; } @@ -102,12 +84,8 @@ SField::SField(private_access_tag_t, int fc, char const* fn) , signingField(IsSigning::yes) , jsonName(fieldName.c_str()) { - XRPL_ASSERT( - !knownCodeToField.contains(fieldCode), - "xrpl::SField::SField(fc,fn) : fieldCode is unique"); - XRPL_ASSERT( - !knownNameToField.contains(fieldName), - "xrpl::SField::SField(fc,fn) : fieldName is unique"); + XRPL_ASSERT(!knownCodeToField.contains(fieldCode), "xrpl::SField::SField(fc,fn) : fieldCode is unique"); + XRPL_ASSERT(!knownNameToField.contains(fieldName), "xrpl::SField::SField(fc,fn) : fieldName is unique"); knownCodeToField[fieldCode] = this; knownNameToField[fieldName] = this; } diff --git a/src/libxrpl/protocol/SOTemplate.cpp b/src/libxrpl/protocol/SOTemplate.cpp index 46edf98710..23d086f493 100644 --- a/src/libxrpl/protocol/SOTemplate.cpp +++ b/src/libxrpl/protocol/SOTemplate.cpp @@ -8,9 +8,7 @@ namespace xrpl { -SOTemplate::SOTemplate( - std::initializer_list uniqueFields, - std::initializer_list commonFields) +SOTemplate::SOTemplate(std::initializer_list uniqueFields, std::initializer_list commonFields) : indices_(SField::getNumFields() + 1, -1) // Unmapped indices == -1 { // Add all SOElements. diff --git a/src/libxrpl/protocol/STAccount.cpp b/src/libxrpl/protocol/STAccount.cpp index 728fb25f6c..b85341daf3 100644 --- a/src/libxrpl/protocol/STAccount.cpp +++ b/src/libxrpl/protocol/STAccount.cpp @@ -20,8 +20,7 @@ STAccount::STAccount() : STBase(), value_(beast::zero), default_(true) { } -STAccount::STAccount(SField const& n) - : STBase(n), value_(beast::zero), default_(true) +STAccount::STAccount(SField const& n) : STBase(n), value_(beast::zero), default_(true) { } @@ -42,13 +41,11 @@ STAccount::STAccount(SField const& n, Buffer&& v) : STAccount(n) memcpy(value_.begin(), v.data(), uint160::bytes); } -STAccount::STAccount(SerialIter& sit, SField const& name) - : STAccount(name, sit.getVLBuffer()) +STAccount::STAccount(SerialIter& sit, SField const& name) : STAccount(name, sit.getVLBuffer()) { } -STAccount::STAccount(SField const& n, AccountID const& v) - : STBase(n), value_(v), default_(false) +STAccount::STAccount(SField const& n, AccountID const& v) : STBase(n), value_(v), default_(false) { } @@ -73,11 +70,8 @@ STAccount::getSType() const void STAccount::add(Serializer& s) const { - XRPL_ASSERT( - getFName().isBinary(), "xrpl::STAccount::add : field is binary"); - XRPL_ASSERT( - getFName().fieldType == STI_ACCOUNT, - "xrpl::STAccount::add : valid field type"); + XRPL_ASSERT(getFName().isBinary(), "xrpl::STAccount::add : field is binary"); + XRPL_ASSERT(getFName().fieldType == STI_ACCOUNT, "xrpl::STAccount::add : valid field type"); // Preserve the serialization behavior of an STBlob: // o If we are default (all zeros) serialize as an empty blob. diff --git a/src/libxrpl/protocol/STAmount.cpp b/src/libxrpl/protocol/STAmount.cpp index 91ad029dda..b7c33bb907 100644 --- a/src/libxrpl/protocol/STAmount.cpp +++ b/src/libxrpl/protocol/STAmount.cpp @@ -61,14 +61,11 @@ getInt64Value(STAmount const& amount, bool valid, char const* error) { if (!valid) Throw(error); - XRPL_ASSERT( - amount.exponent() == 0, "xrpl::getInt64Value : exponent is zero"); + XRPL_ASSERT(amount.exponent() == 0, "xrpl::getInt64Value : exponent is zero"); auto ret = static_cast(amount.mantissa()); - XRPL_ASSERT( - static_cast(ret) == amount.mantissa(), - "xrpl::getInt64Value : mantissa must roundtrip"); + XRPL_ASSERT(static_cast(ret) == amount.mantissa(), "xrpl::getInt64Value : mantissa must roundtrip"); if (amount.negative()) ret = -ret; @@ -85,16 +82,14 @@ getSNValue(STAmount const& amount) static std::int64_t getMPTValue(STAmount const& amount) { - return getInt64Value( - amount, amount.holds(), "amount is not MPT!"); + return getInt64Value(amount, amount.holds(), "amount is not MPT!"); } static bool areComparable(STAmount const& v1, STAmount const& v2) { if (v1.holds() && v2.holds()) - return v1.native() == v2.native() && - v1.get().currency == v2.get().currency; + return v1.native() == v2.native() && v1.get().currency == v2.get().currency; if (v1.holds() && v2.holds()) return v1.get() == v2.get(); return false; @@ -160,8 +155,7 @@ STAmount::STAmount(SerialIter& sit, SField const& name) : STBase(name) bool isNegative = (offset & 256) == 0; offset = (offset & 255) - 97; // center the range - if (value < cMinValue || value > cMaxValue || offset < cMinOffset || - offset > cMaxOffset) + if (value < cMinValue || value > cMaxValue || offset < cMinOffset || offset > cMaxOffset) { Throw("invalid currency value"); } @@ -184,18 +178,13 @@ STAmount::STAmount(SerialIter& sit, SField const& name) : STBase(name) canonicalize(); } -STAmount::STAmount(SField const& name, std::int64_t mantissa) - : STBase(name), mAsset(xrpIssue()), mOffset(0) +STAmount::STAmount(SField const& name, std::int64_t mantissa) : STBase(name), mAsset(xrpIssue()), mOffset(0) { set(mantissa); } STAmount::STAmount(SField const& name, std::uint64_t mantissa, bool negative) - : STBase(name) - , mAsset(xrpIssue()) - , mValue(mantissa) - , mOffset(0) - , mIsNegative(negative) + : STBase(name), mAsset(xrpIssue()), mValue(mantissa), mOffset(0), mIsNegative(negative) { XRPL_ASSERT( mValue <= std::numeric_limits::max(), @@ -204,11 +193,7 @@ STAmount::STAmount(SField const& name, std::uint64_t mantissa, bool negative) } STAmount::STAmount(SField const& name, STAmount const& from) - : STBase(name) - , mAsset(from.mAsset) - , mValue(from.mValue) - , mOffset(from.mOffset) - , mIsNegative(from.mIsNegative) + : STBase(name), mAsset(from.mAsset), mValue(from.mValue), mOffset(from.mOffset), mIsNegative(from.mIsNegative) { XRPL_ASSERT( mValue <= std::numeric_limits::max(), @@ -219,10 +204,7 @@ STAmount::STAmount(SField const& name, STAmount const& from) //------------------------------------------------------------------------------ STAmount::STAmount(std::uint64_t mantissa, bool negative) - : mAsset(xrpIssue()) - , mValue(mantissa) - , mOffset(0) - , mIsNegative(mantissa != 0 && negative) + : mAsset(xrpIssue()), mValue(mantissa), mOffset(0), mIsNegative(mantissa != 0 && negative) { XRPL_ASSERT( mValue <= std::numeric_limits::max(), @@ -230,8 +212,7 @@ STAmount::STAmount(std::uint64_t mantissa, bool negative) "input"); } -STAmount::STAmount(XRPAmount const& amount) - : mAsset(xrpIssue()), mOffset(0), mIsNegative(amount < beast::zero) +STAmount::STAmount(XRPAmount const& amount) : mAsset(xrpIssue()), mOffset(0), mIsNegative(amount < beast::zero) { if (mIsNegative) mValue = unsafe_cast(-amount.drops()); @@ -268,8 +249,7 @@ XRPAmount STAmount::xrp() const { if (!native()) - Throw( - "Cannot return non-native STAmount as XRPAmount"); + Throw("Cannot return non-native STAmount as XRPAmount"); auto drops = static_cast(mValue); XRPL_ASSERT(mOffset == 0, "xrpl::STAmount::xrp : amount is canonical"); @@ -313,9 +293,7 @@ STAmount::mpt() const STAmount& STAmount::operator=(IOUAmount const& iou) { - XRPL_ASSERT( - integral() == false, - "xrpl::STAmount::operator=(IOUAmount) : is not integral"); + XRPL_ASSERT(integral() == false, "xrpl::STAmount::operator=(IOUAmount) : is not integral"); mOffset = iou.exponent(); mIsNegative = iou < beast::zero; if (mIsNegative) @@ -328,8 +306,7 @@ STAmount::operator=(IOUAmount const& iou) STAmount& STAmount::operator=(Number const& number) { - if (!getCurrentTransactionRules() || - isFeatureEnabled(featureSingleAssetVault) || + if (!getCurrentTransactionRules() || isFeatureEnabled(featureSingleAssetVault) || isFeatureEnabled(featureLendingProtocol)) { *this = fromNumber(mAsset, number); @@ -377,12 +354,7 @@ operator+(STAmount const& v1, STAmount const& v2) if (v1 == beast::zero) { // Result must be in terms of v1 currency and issuer. - return { - v1.getFName(), - v1.asset(), - v2.mantissa(), - v2.exponent(), - v2.negative()}; + return {v1.getFName(), v1.asset(), v2.mantissa(), v2.exponent(), v2.negative()}; } if (v1.native()) @@ -428,15 +400,9 @@ operator+(STAmount const& v1, STAmount const& v2) return {v1.getFName(), v1.asset()}; if (fv >= 0) - return STAmount{ - v1.getFName(), - v1.asset(), - static_cast(fv), - ov1, - false}; + return STAmount{v1.getFName(), v1.asset(), static_cast(fv), ov1, false}; - return STAmount{ - v1.getFName(), v1.asset(), static_cast(-fv), ov1, true}; + return STAmount{v1.getFName(), v1.asset(), static_cast(-fv), ov1, true}; } STAmount @@ -474,9 +440,7 @@ getRate(STAmount const& offerOut, STAmount const& offerIn) STAmount r = divide(offerIn, offerOut, noIssue()); if (r == beast::zero) // offer is too good return 0; - XRPL_ASSERT( - (r.exponent() >= -100) && (r.exponent() <= 155), - "xrpl::getRate : exponent inside range"); + XRPL_ASSERT((r.exponent() >= -100) && (r.exponent() <= 155), "xrpl::getRate : exponent inside range"); std::uint64_t ret = r.exponent() + 100; return (ret << (64 - 8)) | r.mantissa(); } @@ -523,12 +487,8 @@ canAdd(STAmount const& a, STAmount const& b) XRPAmount A = a.xrp(); XRPAmount B = b.xrp(); - if ((B > XRPAmount{0} && - A > XRPAmount{std::numeric_limits::max()} - - B) || - (B < XRPAmount{0} && - A < XRPAmount{std::numeric_limits::min()} - - B)) + if ((B > XRPAmount{0} && A > XRPAmount{std::numeric_limits::max()} - B) || + (B < XRPAmount{0} && A < XRPAmount{std::numeric_limits::min()} - B)) { return false; } @@ -542,8 +502,7 @@ canAdd(STAmount const& a, STAmount const& b) static STAmount const maxLoss{IOUAmount{1, -4}, noIssue()}; STAmount lhs = divide((a - b) + b, a, noIssue()) - one; STAmount rhs = divide((b - a) + a, b, noIssue()) - one; - return ((rhs.negative() ? -rhs : rhs) + - (lhs.negative() ? -lhs : lhs)) <= maxLoss; + return ((rhs.negative() ? -rhs : rhs) + (lhs.negative() ? -lhs : lhs)) <= maxLoss; } // MPT (overflow & underflow check) @@ -551,12 +510,8 @@ canAdd(STAmount const& a, STAmount const& b) { MPTAmount A = a.mpt(); MPTAmount B = b.mpt(); - if ((B > MPTAmount{0} && - A > MPTAmount{std::numeric_limits::max()} - - B) || - (B < MPTAmount{0} && - A < MPTAmount{std::numeric_limits::min()} - - B)) + if ((B > MPTAmount{0} && A > MPTAmount{std::numeric_limits::max()} - B) || + (B < MPTAmount{0} && A < MPTAmount{std::numeric_limits::min()} - B)) { return false; } @@ -607,9 +562,7 @@ canSubtract(STAmount const& a, STAmount const& b) return false; // Check for overflow - if (B < XRPAmount{0} && - A > XRPAmount{std::numeric_limits::max()} + - B) + if (B < XRPAmount{0} && A > XRPAmount{std::numeric_limits::max()} + B) return false; return true; @@ -632,9 +585,7 @@ canSubtract(STAmount const& a, STAmount const& b) return false; // Overflow check - if (B < MPTAmount{0} && - A > MPTAmount{std::numeric_limits::max()} + - B) + if (B < MPTAmount{0} && A > MPTAmount{std::numeric_limits::max()} + B) return false; return true; } @@ -697,8 +648,7 @@ STAmount::getText() const if (mIsNegative) ret.append(1, '-'); - bool const scientific( - (mOffset != 0) && ((mOffset < -25) || (mOffset > -5))); + bool const scientific((mOffset != 0) && ((mOffset < -25) || (mOffset > -5))); if (native() || mAsset.holds() || scientific) { @@ -737,8 +687,7 @@ STAmount::getText() const if (std::distance(pre_from, pre_to) > pad_prefix) pre_from += pad_prefix; - XRPL_ASSERT( - post_to >= post_from, "xrpl::STAmount::getText : first distance check"); + XRPL_ASSERT(post_to >= post_from, "xrpl::STAmount::getText : first distance check"); pre_from = std::find_if(pre_from, pre_to, [](char c) { return c != '0'; }); @@ -747,15 +696,11 @@ STAmount::getText() const if (std::distance(post_from, post_to) > pad_suffix) post_to -= pad_suffix; - XRPL_ASSERT( - post_to >= post_from, - "xrpl::STAmount::getText : second distance check"); + XRPL_ASSERT(post_to >= post_from, "xrpl::STAmount::getText : second distance check"); - post_to = std::find_if( - std::make_reverse_iterator(post_to), - std::make_reverse_iterator(post_from), - [](char c) { return c != '0'; }) - .base(); + post_to = std::find_if(std::make_reverse_iterator(post_to), std::make_reverse_iterator(post_from), [](char c) { + return c != '0'; + }).base(); // Assemble the output: if (pre_from == pre_to) @@ -806,14 +751,9 @@ STAmount::add(Serializer& s) const if (*this == beast::zero) s.add64(cIssuedCurrency); else if (mIsNegative) // 512 = not native - s.add64( - mValue | - (static_cast(mOffset + 512 + 97) << (64 - 10))); + s.add64(mValue | (static_cast(mOffset + 512 + 97) << (64 - 10))); else // 256 = positive - s.add64( - mValue | - (static_cast(mOffset + 512 + 256 + 97) - << (64 - 10))); + s.add64(mValue | (static_cast(mOffset + 512 + 256 + 97) << (64 - 10))); s.addBitString(mAsset.get().currency); s.addBitString(mAsset.get().account); } @@ -901,8 +841,7 @@ STAmount::canonicalize() // N.B. do not move the overflow check to after the // multiplication if (native() && mValue > cMaxNativeN) - Throw( - "Native currency amount out of range"); + Throw("Native currency amount out of range"); else if (!native() && mValue > maxMPTokenAmount) Throw("MPT amount out of range"); @@ -964,9 +903,7 @@ STAmount::canonicalize() XRPL_ASSERT( (mValue == 0) || ((mOffset >= cMinOffset) && (mOffset <= cMaxOffset)), "xrpl::STAmount::canonicalize : offset inside range"); - XRPL_ASSERT( - (mValue != 0) || (mOffset != -100), - "xrpl::STAmount::canonicalize : value or offset set"); + XRPL_ASSERT((mValue != 0) || (mOffset != -100), "xrpl::STAmount::canonicalize : value or offset set"); } void @@ -1003,8 +940,7 @@ amountFromString(Asset const& asset, std::string const& amount) { auto const parts = partsFromString(amount); if ((asset.native() || asset.holds()) && parts.exponent < 0) - Throw( - "XRP and MPT must be specified as integral amount."); + Throw("XRP and MPT must be specified as integral amount."); return {asset, parts.mantissa, parts.exponent, parts.negative}; } @@ -1020,8 +956,7 @@ amountFromJson(SField const& name, Json::Value const& v) if (v.isNull()) { - Throw( - "XRP may not be specified with a null Json value"); + Throw("XRP may not be specified with a null Json value"); } else if (v.isObject()) { @@ -1068,8 +1003,7 @@ amountFromJson(SField const& name, Json::Value const& v) value = v; } - bool const native = !currencyOrMPTID.isString() || - currencyOrMPTID.asString().empty() || + bool const native = !currencyOrMPTID.isString() || currencyOrMPTID.asString().empty() || (currencyOrMPTID.asString() == systemCurrencyCode()); if (native) @@ -1093,8 +1027,7 @@ amountFromJson(SField const& name, Json::Value const& v) Issue issue; if (!to_currency(issue.currency, currencyOrMPTID.asString())) Throw("invalid currency"); - if (!issuer.isString() || - !to_issuer(issue.account, issuer.asString())) + if (!issuer.isString() || !to_issuer(issue.account, issuer.asString())) Throw("invalid issuer"); if (issue.native()) Throw("invalid issuer"); @@ -1125,8 +1058,7 @@ amountFromJson(SField const& name, Json::Value const& v) parts = partsFromString(value.asString()); // Can't specify XRP or MPT using fractional representation if ((asset.native() || asset.holds()) && parts.exponent < 0) - Throw( - "XRP and MPT must be specified as integral amount."); + Throw("XRP and MPT must be specified as integral amount."); } else { @@ -1146,8 +1078,7 @@ amountFromJsonNoThrow(STAmount& result, Json::Value const& jvSource) } catch (std::exception const& e) { - JLOG(debugLog().warn()) - << "amountFromJsonNoThrow: caught: " << e.what(); + JLOG(debugLog().warn()) << "amountFromJsonNoThrow: caught: " << e.what(); } return false; } @@ -1161,16 +1092,15 @@ amountFromJsonNoThrow(STAmount& result, Json::Value const& jvSource) bool operator==(STAmount const& lhs, STAmount const& rhs) { - return areComparable(lhs, rhs) && lhs.negative() == rhs.negative() && - lhs.exponent() == rhs.exponent() && lhs.mantissa() == rhs.mantissa(); + return areComparable(lhs, rhs) && lhs.negative() == rhs.negative() && lhs.exponent() == rhs.exponent() && + lhs.mantissa() == rhs.mantissa(); } bool operator<(STAmount const& lhs, STAmount const& rhs) { if (!areComparable(lhs, rhs)) - Throw( - "Can't compare amounts that are't comparable!"); + Throw("Can't compare amounts that are't comparable!"); if (lhs.negative() != rhs.negative()) return lhs.negative(); @@ -1206,12 +1136,7 @@ operator-(STAmount const& value) if (value.mantissa() == 0) return value; return STAmount( - value.getFName(), - value.asset(), - value.mantissa(), - value.exponent(), - !value.negative(), - STAmount::unchecked{}); + value.getFName(), value.asset(), value.mantissa(), value.exponent(), !value.negative(), STAmount::unchecked{}); } //------------------------------------------------------------------------------ @@ -1223,10 +1148,7 @@ operator-(STAmount const& value) // Calculate (a * b) / c when all three values are 64-bit // without loss of precision: static std::uint64_t -muldiv( - std::uint64_t multiplier, - std::uint64_t multiplicand, - std::uint64_t divisor) +muldiv(std::uint64_t multiplier, std::uint64_t multiplicand, std::uint64_t divisor) { boost::multiprecision::uint128_t ret; @@ -1236,19 +1158,15 @@ muldiv( if (ret > std::numeric_limits::max()) { Throw( - "overflow: (" + std::to_string(multiplier) + " * " + - std::to_string(multiplicand) + ") / " + std::to_string(divisor)); + "overflow: (" + std::to_string(multiplier) + " * " + std::to_string(multiplicand) + ") / " + + std::to_string(divisor)); } return static_cast(ret); } static std::uint64_t -muldiv_round( - std::uint64_t multiplier, - std::uint64_t multiplicand, - std::uint64_t divisor, - std::uint64_t rounding) +muldiv_round(std::uint64_t multiplier, std::uint64_t multiplicand, std::uint64_t divisor, std::uint64_t rounding) { boost::multiprecision::uint128_t ret; @@ -1259,9 +1177,8 @@ muldiv_round( if (ret > std::numeric_limits::max()) { Throw( - "overflow: ((" + std::to_string(multiplier) + " * " + - std::to_string(multiplicand) + ") + " + std::to_string(rounding) + - ") / " + std::to_string(divisor)); + "overflow: ((" + std::to_string(multiplier) + " * " + std::to_string(multiplicand) + ") + " + + std::to_string(rounding) + ") / " + std::to_string(divisor)); } return static_cast(ret); @@ -1306,10 +1223,7 @@ divide(STAmount const& num, STAmount const& den, Asset const& asset) // 10^32 to 10^33) followed by a division, so the result // is in the range of 10^16 to 10^15. return STAmount( - asset, - muldiv(numVal, tenTo17, denVal) + 5, - numOffset - denOffset - 17, - num.negative() != den.negative()); + asset, muldiv(numVal, tenTo17, denVal) + 5, numOffset - denOffset - 17, num.negative() != den.negative()); } STAmount @@ -1378,11 +1292,7 @@ multiply(STAmount const& v1, STAmount const& v2, Asset const& asset) // and 10^16), so their product is in the 10^30 to 10^32 // range. Dividing their product by 10^14 maintains the // precision, by scaling the result to 10^16 to 10^18. - return STAmount( - asset, - muldiv(value1, value2, tenTo14) + 7, - offset1 + offset2 + 14, - v1.negative() != v2.negative()); + return STAmount(asset, muldiv(value1, value2, tenTo14) + 7, offset1 + offset2 + 14, v1.negative() != v2.negative()); } // This is the legacy version of canonicalizeRound. It's been in use @@ -1445,11 +1355,7 @@ canonicalizeRound(bool native, std::uint64_t& value, int& offset, bool) // rounding decisions. canonicalizeRoundStrict() tracks all of the bits in // the value being rounded. static void -canonicalizeRoundStrict( - bool native, - std::uint64_t& value, - int& offset, - bool roundUp) +canonicalizeRoundStrict(bool native, std::uint64_t& value, int& offset, bool roundUp) { if (native) { @@ -1467,8 +1373,7 @@ canonicalizeRoundStrict( value = newValue; ++offset; } - value += - (hadRemainder && roundUp) ? 10 : 9; // Add before last divide + value += (hadRemainder && roundUp) ? 10 : 9; // Add before last divide value /= 10; ++offset; } @@ -1487,10 +1392,7 @@ canonicalizeRoundStrict( } STAmount -roundToScale( - STAmount const& value, - std::int32_t scale, - Number::rounding_mode rounding) +roundToScale(STAmount const& value, std::int32_t scale, Number::rounding_mode rounding) { // Nothing to do for integral types. if (value.integral()) @@ -1506,8 +1408,7 @@ roundToScale( if (value.exponent() >= scale) return value; - STAmount const referenceValue{ - value.asset(), STAmount::cMinValue, scale, value.negative()}; + STAmount const referenceValue{value.asset(), STAmount::cMinValue, scale, value.negative()}; NumberRoundModeGuard mg(rounding); // With an IOU, the the result of addition will be truncated to the @@ -1540,15 +1441,9 @@ public: // // We might need to use NumberRoundModeGuard. Allow the caller // to pass either that or a replacement as a template parameter. -template < - void (*CanonicalizeFunc)(bool, std::uint64_t&, int&, bool), - typename MightSaveRound> +template static STAmount -mulRoundImpl( - STAmount const& v1, - STAmount const& v2, - Asset const& asset, - bool roundUp) +mulRoundImpl(STAmount const& v1, STAmount const& v2, Asset const& asset, bool roundUp) { if (v1 == beast::zero || v2 == beast::zero) return {asset}; @@ -1614,8 +1509,7 @@ mulRoundImpl( // If the we're rounding up, we want to round up away // from zero, and if we're rounding down, truncation // is implicit. - std::uint64_t amount = muldiv_round( - value1, value2, tenTo14, (resultNegative != roundUp) ? tenTo14m1 : 0); + std::uint64_t amount = muldiv_round(value1, value2, tenTo14, (resultNegative != roundUp) ? tenTo14m1 : 0); int offset = offset1 + offset2 + 14; if (resultNegative != roundUp) @@ -1649,36 +1543,22 @@ mulRoundImpl( } STAmount -mulRound( - STAmount const& v1, - STAmount const& v2, - Asset const& asset, - bool roundUp) +mulRound(STAmount const& v1, STAmount const& v2, Asset const& asset, bool roundUp) { - return mulRoundImpl( - v1, v2, asset, roundUp); + return mulRoundImpl(v1, v2, asset, roundUp); } STAmount -mulRoundStrict( - STAmount const& v1, - STAmount const& v2, - Asset const& asset, - bool roundUp) +mulRoundStrict(STAmount const& v1, STAmount const& v2, Asset const& asset, bool roundUp) { - return mulRoundImpl( - v1, v2, asset, roundUp); + return mulRoundImpl(v1, v2, asset, roundUp); } // We might need to use NumberRoundModeGuard. Allow the caller // to pass either that or a replacement as a template parameter. template static STAmount -divRoundImpl( - STAmount const& num, - STAmount const& den, - Asset const& asset, - bool roundUp) +divRoundImpl(STAmount const& num, STAmount const& den, Asset const& asset, bool roundUp) { if (den == beast::zero) Throw("division by zero"); @@ -1717,22 +1597,19 @@ divRoundImpl( // // We round away from zero if we're rounding up or // truncate if we're rounding down. - std::uint64_t amount = muldiv_round( - numVal, tenTo17, denVal, (resultNegative != roundUp) ? denVal - 1 : 0); + std::uint64_t amount = muldiv_round(numVal, tenTo17, denVal, (resultNegative != roundUp) ? denVal - 1 : 0); int offset = numOffset - denOffset - 17; if (resultNegative != roundUp) - canonicalizeRound( - asset.native() || asset.holds(), amount, offset, roundUp); + canonicalizeRound(asset.native() || asset.holds(), amount, offset, roundUp); STAmount result = [&]() { // If appropriate, tell Number the rounding mode we are using. // Note that "roundUp == true" actually means "round away from zero". // Otherwise round toward zero. using enum Number::rounding_mode; - MightSaveRound const savedRound( - roundUp ^ resultNegative ? upward : downward); + MightSaveRound const savedRound(roundUp ^ resultNegative ? upward : downward); return STAmount(asset, amount, offset, resultNegative); }(); @@ -1756,21 +1633,13 @@ divRoundImpl( } STAmount -divRound( - STAmount const& num, - STAmount const& den, - Asset const& asset, - bool roundUp) +divRound(STAmount const& num, STAmount const& den, Asset const& asset, bool roundUp) { return divRoundImpl(num, den, asset, roundUp); } STAmount -divRoundStrict( - STAmount const& num, - STAmount const& den, - Asset const& asset, - bool roundUp) +divRoundStrict(STAmount const& num, STAmount const& den, Asset const& asset, bool roundUp) { return divRoundImpl(num, den, asset, roundUp); } diff --git a/src/libxrpl/protocol/STArray.cpp b/src/libxrpl/protocol/STArray.cpp index de1e6905c6..8e7827cccc 100644 --- a/src/libxrpl/protocol/STArray.cpp +++ b/src/libxrpl/protocol/STArray.cpp @@ -14,8 +14,7 @@ namespace xrpl { -STArray::STArray(STArray&& other) - : STBase(other.getFName()), v_(std::move(other.v_)) +STArray::STArray(STArray&& other) : STBase(other.getFName()), v_(std::move(other.v_)) { } @@ -53,8 +52,7 @@ STArray::STArray(SerialIter& sit, SField const& f, int depth) : STBase(f) if ((type == STI_OBJECT) && (field == 1)) { - JLOG(debugLog().error()) - << "Encountered array with end of object marker"; + JLOG(debugLog().error()) << "Encountered array with end of object marker"; Throw("Illegal terminator in array"); } @@ -62,8 +60,7 @@ STArray::STArray(SerialIter& sit, SField const& f, int depth) : STBase(f) if (fn.isInvalid()) { - JLOG(debugLog().error()) - << "Unknown field: " << type << "/" << field; + JLOG(debugLog().error()) << "Unknown field: " << type << "/" << field; Throw("Unknown field"); } diff --git a/src/libxrpl/protocol/STBase.cpp b/src/libxrpl/protocol/STBase.cpp index d3faf090eb..f6b1dcec58 100644 --- a/src/libxrpl/protocol/STBase.cpp +++ b/src/libxrpl/protocol/STBase.cpp @@ -101,9 +101,7 @@ STBase::add(Serializer& s) const bool STBase::isEquivalent(STBase const& t) const { - XRPL_ASSERT( - getSType() == STI_NOTPRESENT, - "xrpl::STBase::isEquivalent : type not present"); + XRPL_ASSERT(getSType() == STI_NOTPRESENT, "xrpl::STBase::isEquivalent : type not present"); return t.getSType() == STI_NOTPRESENT; } @@ -129,8 +127,7 @@ STBase::getFName() const void STBase::addFieldID(Serializer& s) const { - XRPL_ASSERT( - fName->isBinary(), "xrpl::STBase::addFieldID : field is binary"); + XRPL_ASSERT(fName->isBinary(), "xrpl::STBase::addFieldID : field is binary"); s.addFieldID(fName->fieldType, fName->fieldValue); } diff --git a/src/libxrpl/protocol/STBlob.cpp b/src/libxrpl/protocol/STBlob.cpp index 65670a6a9f..1a9dae7771 100644 --- a/src/libxrpl/protocol/STBlob.cpp +++ b/src/libxrpl/protocol/STBlob.cpp @@ -11,8 +11,7 @@ namespace xrpl { -STBlob::STBlob(SerialIter& st, SField const& name) - : STBase(name), value_(st.getVLBuffer()) +STBlob::STBlob(SerialIter& st, SField const& name) : STBase(name), value_(st.getVLBuffer()) { } @@ -45,8 +44,7 @@ STBlob::add(Serializer& s) const { XRPL_ASSERT(getFName().isBinary(), "xrpl::STBlob::add : field is binary"); XRPL_ASSERT( - (getFName().fieldType == STI_VL) || - (getFName().fieldType == STI_ACCOUNT), + (getFName().fieldType == STI_VL) || (getFName().fieldType == STI_ACCOUNT), "xrpl::STBlob::add : valid field type"); s.addVL(value_.data(), value_.size()); } diff --git a/src/libxrpl/protocol/STCurrency.cpp b/src/libxrpl/protocol/STCurrency.cpp index d4c10b48d3..cfbbe509c6 100644 --- a/src/libxrpl/protocol/STCurrency.cpp +++ b/src/libxrpl/protocol/STCurrency.cpp @@ -23,8 +23,7 @@ STCurrency::STCurrency(SerialIter& sit, SField const& name) : STBase{name} currency_ = sit.get160(); } -STCurrency::STCurrency(SField const& name, Currency const& currency) - : STBase{name}, currency_{currency} +STCurrency::STCurrency(SField const& name, Currency const& currency) : STBase{name}, currency_{currency} { } @@ -88,15 +87,13 @@ currencyFromJson(SField const& name, Json::Value const& v) { if (!v.isString()) { - Throw( - "currencyFromJson currency must be a string Json value"); + Throw("currencyFromJson currency must be a string Json value"); } auto const currency = to_currency(v.asString()); if (currency == badCurrency() || currency == noCurrency()) { - Throw( - "currencyFromJson currency must be a valid currency"); + Throw("currencyFromJson currency must be a valid currency"); } return STCurrency{name, currency}; diff --git a/src/libxrpl/protocol/STInteger.cpp b/src/libxrpl/protocol/STInteger.cpp index e701fc4203..ae7b3ff279 100644 --- a/src/libxrpl/protocol/STInteger.cpp +++ b/src/libxrpl/protocol/STInteger.cpp @@ -20,8 +20,7 @@ namespace xrpl { template <> -STInteger::STInteger(SerialIter& sit, SField const& name) - : STInteger(name, sit.get8()) +STInteger::STInteger(SerialIter& sit, SField const& name) : STInteger(name, sit.get8()) { } @@ -44,8 +43,7 @@ STUInt8::getText() const return human; // LCOV_EXCL_START - JLOG(debugLog().error()) - << "Unknown result code in metadata: " << value_; + JLOG(debugLog().error()) << "Unknown result code in metadata: " << value_; // LCOV_EXCL_STOP } @@ -64,8 +62,7 @@ STUInt8::getJson(JsonOptions) const return token; // LCOV_EXCL_START - JLOG(debugLog().error()) - << "Unknown result code in metadata: " << value_; + JLOG(debugLog().error()) << "Unknown result code in metadata: " << value_; // LCOV_EXCL_STOP } @@ -75,8 +72,7 @@ STUInt8::getJson(JsonOptions) const //------------------------------------------------------------------------------ template <> -STInteger::STInteger(SerialIter& sit, SField const& name) - : STInteger(name, sit.get16()) +STInteger::STInteger(SerialIter& sit, SField const& name) : STInteger(name, sit.get16()) { } @@ -93,8 +89,7 @@ STUInt16::getText() const { if (getFName() == sfLedgerEntryType) { - auto item = LedgerFormats::getInstance().findByType( - safe_cast(value_)); + auto item = LedgerFormats::getInstance().findByType(safe_cast(value_)); if (item != nullptr) return item->getName(); @@ -102,8 +97,7 @@ STUInt16::getText() const if (getFName() == sfTransactionType) { - auto item = - TxFormats::getInstance().findByType(safe_cast(value_)); + auto item = TxFormats::getInstance().findByType(safe_cast(value_)); if (item != nullptr) return item->getName(); @@ -118,8 +112,7 @@ STUInt16::getJson(JsonOptions) const { if (getFName() == sfLedgerEntryType) { - auto item = LedgerFormats::getInstance().findByType( - safe_cast(value_)); + auto item = LedgerFormats::getInstance().findByType(safe_cast(value_)); if (item != nullptr) return item->getName(); @@ -127,8 +120,7 @@ STUInt16::getJson(JsonOptions) const if (getFName() == sfTransactionType) { - auto item = - TxFormats::getInstance().findByType(safe_cast(value_)); + auto item = TxFormats::getInstance().findByType(safe_cast(value_)); if (item != nullptr) return item->getName(); @@ -140,8 +132,7 @@ STUInt16::getJson(JsonOptions) const //------------------------------------------------------------------------------ template <> -STInteger::STInteger(SerialIter& sit, SField const& name) - : STInteger(name, sit.get32()) +STInteger::STInteger(SerialIter& sit, SField const& name) : STInteger(name, sit.get32()) { } @@ -158,8 +149,7 @@ STUInt32::getText() const { if (getFName() == sfPermissionValue) { - auto const permissionName = - Permission::getInstance().getPermissionName(value_); + auto const permissionName = Permission::getInstance().getPermissionName(value_); if (permissionName) return *permissionName; } @@ -172,8 +162,7 @@ STUInt32::getJson(JsonOptions) const { if (getFName() == sfPermissionValue) { - auto const permissionName = - Permission::getInstance().getPermissionName(value_); + auto const permissionName = Permission::getInstance().getPermissionName(value_); if (permissionName) return *permissionName; } @@ -184,8 +173,7 @@ STUInt32::getJson(JsonOptions) const //------------------------------------------------------------------------------ template <> -STInteger::STInteger(SerialIter& sit, SField const& name) - : STInteger(name, sit.get64()) +STInteger::STInteger(SerialIter& sit, SField const& name) : STInteger(name, sit.get64()) { } @@ -208,16 +196,10 @@ Json::Value STUInt64::getJson(JsonOptions) const { auto convertToString = [](uint64_t const value, int const base) { - XRPL_ASSERT( - base == 10 || base == 16, - "xrpl::STUInt64::getJson : base 10 or 16"); - std::string str( - base == 10 ? 20 : 16, 0); // Allocate space depending on base - auto ret = - std::to_chars(str.data(), str.data() + str.size(), value, base); - XRPL_ASSERT( - ret.ec == std::errc(), - "xrpl::STUInt64::getJson : to_chars succeeded"); + XRPL_ASSERT(base == 10 || base == 16, "xrpl::STUInt64::getJson : base 10 or 16"); + std::string str(base == 10 ? 20 : 16, 0); // Allocate space depending on base + auto ret = std::to_chars(str.data(), str.data() + str.size(), value, base); + XRPL_ASSERT(ret.ec == std::errc(), "xrpl::STUInt64::getJson : to_chars succeeded"); str.resize(std::distance(str.data(), ret.ptr)); return str; }; @@ -233,8 +215,7 @@ STUInt64::getJson(JsonOptions) const //------------------------------------------------------------------------------ template <> -STInteger::STInteger(SerialIter& sit, SField const& name) - : STInteger(name, sit.get32()) +STInteger::STInteger(SerialIter& sit, SField const& name) : STInteger(name, sit.get32()) { } diff --git a/src/libxrpl/protocol/STIssue.cpp b/src/libxrpl/protocol/STIssue.cpp index 213c8b7962..627c61fc58 100644 --- a/src/libxrpl/protocol/STIssue.cpp +++ b/src/libxrpl/protocol/STIssue.cpp @@ -44,13 +44,9 @@ STIssue::STIssue(SerialIter& sit, SField const& name) : STBase{name} { MPTID mptID; std::uint32_t sequence = sit.get32(); - static_assert( - MPTID::size() == sizeof(sequence) + sizeof(currencyOrAccount)); + static_assert(MPTID::size() == sizeof(sequence) + sizeof(currencyOrAccount)); memcpy(mptID.data(), &sequence, sizeof(sequence)); - memcpy( - mptID.data() + sizeof(sequence), - currencyOrAccount.data(), - sizeof(currencyOrAccount)); + memcpy(mptID.data() + sizeof(sequence), currencyOrAccount.data(), sizeof(currencyOrAccount)); MPTIssue issue{mptID}; asset_ = issue; } @@ -60,8 +56,7 @@ STIssue::STIssue(SerialIter& sit, SField const& name) : STBase{name} issue.currency = currencyOrAccount; issue.account = account; if (!isConsistent(issue)) - Throw( - "invalid issue: currency and account native mismatch"); + Throw("invalid issue: currency and account native mismatch"); asset_ = issue; } } diff --git a/src/libxrpl/protocol/STLedgerEntry.cpp b/src/libxrpl/protocol/STLedgerEntry.cpp index 8ee3669a24..d73da2eb3a 100644 --- a/src/libxrpl/protocol/STLedgerEntry.cpp +++ b/src/libxrpl/protocol/STLedgerEntry.cpp @@ -28,30 +28,26 @@ namespace xrpl { -STLedgerEntry::STLedgerEntry(Keylet const& k) - : STObject(sfLedgerEntry), key_(k.key), type_(k.type) +STLedgerEntry::STLedgerEntry(Keylet const& k) : STObject(sfLedgerEntry), key_(k.key), type_(k.type) { auto const format = LedgerFormats::getInstance().findByType(type_); if (format == nullptr) Throw( - "Attempt to create a SLE of unknown type " + - std::to_string(safe_cast(k.type))); + "Attempt to create a SLE of unknown type " + std::to_string(safe_cast(k.type))); set(format->getSOTemplate()); setFieldU16(sfLedgerEntryType, static_cast(type_)); } -STLedgerEntry::STLedgerEntry(SerialIter& sit, uint256 const& index) - : STObject(sfLedgerEntry), key_(index) +STLedgerEntry::STLedgerEntry(SerialIter& sit, uint256 const& index) : STObject(sfLedgerEntry), key_(index) { set(sit); setSLEType(); } -STLedgerEntry::STLedgerEntry(STObject const& object, uint256 const& index) - : STObject(object), key_(index) +STLedgerEntry::STLedgerEntry(STObject const& object, uint256 const& index) : STObject(object), key_(index) { setSLEType(); } @@ -59,8 +55,7 @@ STLedgerEntry::STLedgerEntry(STObject const& object, uint256 const& index) void STLedgerEntry::setSLEType() { - auto format = LedgerFormats::getInstance().findByType( - safe_cast(getFieldU16(sfLedgerEntryType))); + auto format = LedgerFormats::getInstance().findByType(safe_cast(getFieldU16(sfLedgerEntryType))); if (format == nullptr) Throw("invalid ledger entry type"); @@ -108,8 +103,7 @@ STLedgerEntry::getSType() const std::string STLedgerEntry::getText() const { - return str( - boost::format("{ %s, %s }") % to_string(key_) % STObject::getText()); + return str(boost::format("{ %s, %s }") % to_string(key_) % STObject::getText()); } Json::Value @@ -120,8 +114,7 @@ STLedgerEntry::getJson(JsonOptions options) const ret[jss::index] = to_string(key_); if (getType() == ltMPTOKEN_ISSUANCE) - ret[jss::mpt_issuance_id] = to_string( - makeMptID(getFieldU32(sfSequence), getAccountID(sfIssuer))); + ret[jss::mpt_issuance_id] = to_string(makeMptID(getFieldU32(sfSequence), getAccountID(sfIssuer))); return ret; } @@ -134,19 +127,12 @@ STLedgerEntry::isThreadedType(Rules const& rules) const // Exclude PrevTxnID/PrevTxnLgrSeq if the fixPreviousTxnID amendment is not // enabled and the ledger object type is in the above set bool const excludePrevTxnID = !rules.enabled(fixPreviousTxnID) && - std::count( - newPreviousTxnIDTypes.cbegin(), - newPreviousTxnIDTypes.cend(), - type_); + std::count(newPreviousTxnIDTypes.cbegin(), newPreviousTxnIDTypes.cend(), type_); return !excludePrevTxnID && getFieldIndex(sfPreviousTxnID) != -1; } bool -STLedgerEntry::thread( - uint256 const& txID, - std::uint32_t ledgerSeq, - uint256& prevTxID, - std::uint32_t& prevLedgerID) +STLedgerEntry::thread(uint256 const& txID, std::uint32_t ledgerSeq, uint256& prevTxID, std::uint32_t& prevLedgerID) { uint256 oldPrevTxID = getFieldH256(sfPreviousTxnID); @@ -156,8 +142,7 @@ STLedgerEntry::thread( { // this transaction is already threaded XRPL_ASSERT( - getFieldU32(sfPreviousTxnLgrSeq) == ledgerSeq, - "xrpl::STLedgerEntry::thread : ledger sequence match"); + getFieldU32(sfPreviousTxnLgrSeq) == ledgerSeq, "xrpl::STLedgerEntry::thread : ledger sequence match"); return false; } diff --git a/src/libxrpl/protocol/STNumber.cpp b/src/libxrpl/protocol/STNumber.cpp index 2f2dae7493..a549a0e482 100644 --- a/src/libxrpl/protocol/STNumber.cpp +++ b/src/libxrpl/protocol/STNumber.cpp @@ -20,8 +20,7 @@ namespace xrpl { -STNumber::STNumber(SField const& field, Number const& value) - : STTakesAsset(field), value_(value) +STNumber::STNumber(SField const& field, Number const& value) : STTakesAsset(field), value_(value) { } @@ -51,10 +50,7 @@ STNumber::associateAsset(Asset const& a) { STTakesAsset::associateAsset(a); - XRPL_ASSERT_PARTS( - getFName().shouldMeta(SField::sMD_NeedsAsset), - "STNumber::associateAsset", - "field needs asset"); + XRPL_ASSERT_PARTS(getFName().shouldMeta(SField::sMD_NeedsAsset), "STNumber::associateAsset", "field needs asset"); roundToAsset(a, value_); } @@ -63,9 +59,7 @@ void STNumber::add(Serializer& s) const { XRPL_ASSERT(getFName().isBinary(), "xrpl::STNumber::add : field is binary"); - XRPL_ASSERT( - getFName().fieldType == getSType(), - "xrpl::STNumber::add : field type match"); + XRPL_ASSERT(getFName().fieldType == getSType(), "xrpl::STNumber::add : field type match"); auto value = value_; auto const mantissa = value.mantissa(); @@ -80,10 +74,7 @@ STNumber::add(Serializer& s) const // The number should be rounded to the asset's precision, but round // it here if it has an asset assigned. roundToAsset(*asset_, value); - XRPL_ASSERT_PARTS( - value_ == value, - "xrpl::STNumber::add", - "value is already rounded"); + XRPL_ASSERT_PARTS(value_ == value, "xrpl::STNumber::add", "value is already rounded"); } else { @@ -103,8 +94,7 @@ STNumber::add(Serializer& s) const } XRPL_ASSERT_PARTS( - mantissa <= std::numeric_limits::max() && - mantissa >= std::numeric_limits::min(), + mantissa <= std::numeric_limits::max() && mantissa >= std::numeric_limits::min(), "xrpl::STNumber::add", "mantissa in valid range"); s.add64(mantissa); @@ -138,9 +128,7 @@ STNumber::move(std::size_t n, void* buf) bool STNumber::isEquivalent(STBase const& t) const { - XRPL_ASSERT( - t.getSType() == this->getSType(), - "xrpl::STNumber::isEquivalent : field type match"); + XRPL_ASSERT(t.getSType() == this->getSType(), "xrpl::STNumber::isEquivalent : field type match"); STNumber const& v = dynamic_cast(t); return value_ == v; } @@ -238,29 +226,19 @@ numberFromJson(SField const& field, Json::Value const& value) { parts = partsFromString(value.asString()); - XRPL_ASSERT_PARTS( - !getCurrentTransactionRules(), - "xrpld::numberFromJson", - "Not in a Transactor context"); + XRPL_ASSERT_PARTS(!getCurrentTransactionRules(), "xrpld::numberFromJson", "Not in a Transactor context"); // Number mantissas are much bigger than the allowable parsed values, so // it can't be out of range. static_assert( - std::numeric_limits::max() >= - std::numeric_limits::max()); + std::numeric_limits::max() >= std::numeric_limits::max()); } else { Throw("not a number"); } - return STNumber{ - field, - Number{ - parts.negative, - parts.mantissa, - parts.exponent, - Number::normalized{}}}; + return STNumber{field, Number{parts.negative, parts.mantissa, parts.exponent, Number::normalized{}}}; } } // namespace xrpl diff --git a/src/libxrpl/protocol/STObject.cpp b/src/libxrpl/protocol/STObject.cpp index a45eb4b7c7..ad5b6fe352 100644 --- a/src/libxrpl/protocol/STObject.cpp +++ b/src/libxrpl/protocol/STObject.cpp @@ -41,8 +41,7 @@ namespace xrpl { -STObject::STObject(STObject&& other) - : STBase(other.getFName()), v_(std::move(other.v_)), mType(other.mType) +STObject::STObject(STObject&& other) : STBase(other.getFName()), v_(std::move(other.v_)), mType(other.mType) { } @@ -55,17 +54,14 @@ STObject::STObject(SOTemplate const& type, SField const& name) : STBase(name) set(type); } -STObject::STObject(SOTemplate const& type, SerialIter& sit, SField const& name) - : STBase(name) +STObject::STObject(SOTemplate const& type, SerialIter& sit, SField const& name) : STBase(name) { v_.reserve(type.size()); set(sit); applyTemplate(type); // May throw } -STObject::STObject(SerialIter& sit, SField const& name, int depth) noexcept( - false) - : STBase(name), mType(nullptr) +STObject::STObject(SerialIter& sit, SField const& name, int depth) noexcept(false) : STBase(name), mType(nullptr) { if (depth > 10) Throw("Maximum nesting depth of STObject exceeded"); @@ -87,8 +83,7 @@ STObject::makeInnerObject(SField const& name) if (!rules || (rules->enabled(fixInnerObjTemplate) && isAMMObj) || (rules->enabled(fixInnerObjTemplate2) && !isAMMObj)) { - if (SOTemplate const* elements = - InnerObjectFormats::getInstance().findSOTemplateBySField(name)) + if (SOTemplate const* elements = InnerObjectFormats::getInstance().findSOTemplateBySField(name)) obj.set(*elements); } return obj; @@ -165,17 +160,13 @@ STObject::applyTemplate(SOTemplate const& type) v.reserve(type.size()); for (auto const& e : type) { - auto const iter = - std::find_if(v_.begin(), v_.end(), [&](detail::STVar const& b) { - return b.get().getFName() == e.sField(); - }); + auto const iter = std::find_if( + v_.begin(), v_.end(), [&](detail::STVar const& b) { return b.get().getFName() == e.sField(); }); if (iter != v_.end()) { if ((e.style() == soeDEFAULT) && iter->get().isDefault()) { - throwFieldErr( - e.sField().fieldName, - "may not be explicitly set to default."); + throwFieldErr(e.sField().fieldName, "may not be explicitly set to default."); } v.emplace_back(std::move(*iter)); v_.erase(iter); @@ -194,8 +185,7 @@ STObject::applyTemplate(SOTemplate const& type) // Anything left over in the object must be discardable if (!e->getFName().isDiscardable()) { - throwFieldErr( - e->getFName().getName(), "found in disallowed location."); + throwFieldErr(e->getFName().getName(), "found in disallowed location."); } } // Swap the template matching data in for the old data, @@ -206,8 +196,7 @@ STObject::applyTemplate(SOTemplate const& type) void STObject::applyTemplateFromSField(SField const& sField) { - SOTemplate const* elements = - InnerObjectFormats::getInstance().findSOTemplateBySField(sField); + SOTemplate const* elements = InnerObjectFormats::getInstance().findSOTemplateBySField(sField); if (elements) applyTemplate(*elements); // May throw } @@ -239,8 +228,7 @@ STObject::set(SerialIter& sit, int depth) if (type == STI_ARRAY && field == 1) { - JLOG(debugLog().error()) - << "Encountered object with embedded end-of-array marker"; + JLOG(debugLog().error()) << "Encountered object with embedded end-of-array marker"; Throw("Illegal end-of-array marker in object"); } @@ -248,8 +236,7 @@ STObject::set(SerialIter& sit, int depth) if (fn.isInvalid()) { - JLOG(debugLog().error()) << "Unknown field: field_type=" << type - << ", field_name=" << field; + JLOG(debugLog().error()) << "Unknown field: field_type=" << type << ", field_name=" << field; Throw("Unknown field"); } @@ -265,10 +252,9 @@ STObject::set(SerialIter& sit, int depth) // duplicate fields. This is a key invariant: auto const sf = getSortedFields(*this, withAllFields); - auto const dup = std::adjacent_find( - sf.cbegin(), sf.cend(), [](STBase const* lhs, STBase const* rhs) { - return lhs->getFName() == rhs->getFName(); - }); + auto const dup = std::adjacent_find(sf.cbegin(), sf.cend(), [](STBase const* lhs, STBase const* rhs) { + return lhs->getFName() == rhs->getFName(); + }); if (dup != sf.cend()) Throw("Duplicate field detected"); @@ -347,29 +333,17 @@ STObject::isEquivalent(STBase const& t) const if (mType != nullptr && v->mType == mType) { - return std::equal( - begin(), - end(), - v->begin(), - v->end(), - [](STBase const& st1, STBase const& st2) { - return (st1.getSType() == st2.getSType()) && - st1.isEquivalent(st2); - }); + return std::equal(begin(), end(), v->begin(), v->end(), [](STBase const& st1, STBase const& st2) { + return (st1.getSType() == st2.getSType()) && st1.isEquivalent(st2); + }); } auto const sf1 = getSortedFields(*this, withAllFields); auto const sf2 = getSortedFields(*v, withAllFields); - return std::equal( - sf1.begin(), - sf1.end(), - sf2.begin(), - sf2.end(), - [](STBase const* st1, STBase const* st2) { - return (st1->getSType() == st2->getSType()) && - st1->isEquivalent(*st2); - }); + return std::equal(sf1.begin(), sf1.end(), sf2.begin(), sf2.end(), [](STBase const* st1, STBase const* st2) { + return (st1->getSType() == st2->getSType()) && st1->isEquivalent(*st2); + }); } uint256 @@ -897,8 +871,7 @@ STObject::add(Serializer& s, WhichFields whichFields) const { // Depending on whichFields, signing fields are either serialized or // not. Then fields are added to the Serializer sorted by fieldCode. - std::vector const fields{ - getSortedFields(*this, whichFields)}; + std::vector const fields{getSortedFields(*this, whichFields)}; // insert sorted for (STBase const* const field : fields) @@ -908,8 +881,7 @@ STObject::add(Serializer& s, WhichFields whichFields) const // must be OBJECT, or the object cannot be deserialized SerializedTypeID const sType{field->getSType()}; XRPL_ASSERT( - (sType != STI_OBJECT) || - (field->getFName().fieldType == STI_OBJECT), + (sType != STI_OBJECT) || (field->getFName().fieldType == STI_OBJECT), "xrpl::STObject::add : valid field type"); field->addFieldID(s); field->add(s); @@ -928,8 +900,7 @@ STObject::getSortedFields(STObject const& objToSort, WhichFields whichFields) for (detail::STVar const& elem : objToSort.v_) { STBase const& base = elem.get(); - if ((base.getSType() != STI_NOTPRESENT) && - base.getFName().shouldInclude(whichFields)) + if ((base.getSType() != STI_NOTPRESENT) && base.getFName().shouldInclude(whichFields)) { sf.push_back(&base); } diff --git a/src/libxrpl/protocol/STParsedJSON.cpp b/src/libxrpl/protocol/STParsedJSON.cpp index 34c8b70e45..878f6c3605 100644 --- a/src/libxrpl/protocol/STParsedJSON.cpp +++ b/src/libxrpl/protocol/STParsedJSON.cpp @@ -45,9 +45,8 @@ namespace xrpl { namespace STParsedJSONDetail { template -constexpr std:: - enable_if_t::value && std::is_signed::value, U> - to_unsigned(S value) +constexpr std::enable_if_t::value && std::is_signed::value, U> +to_unsigned(S value) { if (value < 0 || std::numeric_limits::max() < value) Throw("Value out of range"); @@ -55,9 +54,8 @@ constexpr std:: } template -constexpr std:: - enable_if_t::value && std::is_unsigned::value, U1> - to_unsigned(U2 value) +constexpr std::enable_if_t::value && std::is_unsigned::value, U1> +to_unsigned(U2 value) { if (std::numeric_limits::max() < value) Throw("Value out of range"); @@ -77,9 +75,7 @@ make_name(std::string const& object, std::string const& field) static inline Json::Value not_an_object(std::string const& object, std::string const& field) { - return RPC::make_error( - rpcINVALID_PARAMS, - "Field '" + make_name(object, field) + "' is not a JSON object."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' is not a JSON object."); } static inline Json::Value @@ -91,40 +87,31 @@ not_an_object(std::string const& object) static inline Json::Value not_an_array(std::string const& object) { - return RPC::make_error( - rpcINVALID_PARAMS, "Field '" + object + "' is not a JSON array."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + object + "' is not a JSON array."); } static inline Json::Value unknown_field(std::string const& object, std::string const& field) { - return RPC::make_error( - rpcINVALID_PARAMS, - "Field '" + make_name(object, field) + "' is unknown."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' is unknown."); } static inline Json::Value out_of_range(std::string const& object, std::string const& field) { - return RPC::make_error( - rpcINVALID_PARAMS, - "Field '" + make_name(object, field) + "' is out of range."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' is out of range."); } static inline Json::Value bad_type(std::string const& object, std::string const& field) { - return RPC::make_error( - rpcINVALID_PARAMS, - "Field '" + make_name(object, field) + "' has bad type."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' has bad type."); } static inline Json::Value invalid_data(std::string const& object, std::string const& field) { - return RPC::make_error( - rpcINVALID_PARAMS, - "Field '" + make_name(object, field) + "' has invalid data."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' has invalid data."); } static inline Json::Value @@ -136,25 +123,19 @@ invalid_data(std::string const& object) static inline Json::Value array_expected(std::string const& object, std::string const& field) { - return RPC::make_error( - rpcINVALID_PARAMS, - "Field '" + make_name(object, field) + "' must be a JSON array."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' must be a JSON array."); } static inline Json::Value string_expected(std::string const& object, std::string const& field) { - return RPC::make_error( - rpcINVALID_PARAMS, - "Field '" + make_name(object, field) + "' must be a string."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + make_name(object, field) + "' must be a string."); } static inline Json::Value too_deep(std::string const& object) { - return RPC::make_error( - rpcINVALID_PARAMS, - "Field '" + object + "' exceeds nesting depth limit."); + return RPC::make_error(rpcINVALID_PARAMS, "Field '" + object + "' exceeds nesting depth limit."); } static inline Json::Value @@ -162,17 +143,14 @@ singleton_expected(std::string const& object, unsigned int index) { return RPC::make_error( rpcINVALID_PARAMS, - "Field '" + object + "[" + std::to_string(index) + - "]' must be an object with a single key/object value."); + "Field '" + object + "[" + std::to_string(index) + "]' must be an object with a single key/object value."); } static inline Json::Value template_mismatch(SField const& sField) { return RPC::make_error( - rpcINVALID_PARAMS, - "Object '" + sField.getName() + - "' contents did not meet requirements for that type."); + rpcINVALID_PARAMS, "Object '" + sField.getName() + "' contents did not meet requirements for that type."); } static inline Json::Value @@ -202,21 +180,15 @@ parseUnsigned( if (value.isString()) { ret = detail::make_stvar( - field, - safe_cast( - beast::lexicalCastThrow(value.asString()))); + field, safe_cast(beast::lexicalCastThrow(value.asString()))); } else if (value.isInt()) { - ret = detail::make_stvar( - field, - to_unsigned(value.asInt())); + ret = detail::make_stvar(field, to_unsigned(value.asInt())); } else if (value.isUInt()) { - ret = detail::make_stvar( - field, - to_unsigned(value.asUInt())); + ret = detail::make_stvar(field, to_unsigned(value.asUInt())); } else { @@ -251,17 +223,14 @@ parseUint16( { std::string const strValue = value.asString(); - if (!strValue.empty() && - ((strValue[0] < '0') || (strValue[0] > '9'))) + if (!strValue.empty() && ((strValue[0] < '0') || (strValue[0] > '9'))) { if (field == sfTransactionType) { ret = detail::make_stvar( field, safe_cast( - static_cast( - TxFormats::getInstance().findTypeByName( - strValue)))); + static_cast(TxFormats::getInstance().findTypeByName(strValue)))); if (*name == sfGeneric) name = &sfTransaction; @@ -271,9 +240,7 @@ parseUint16( ret = detail::make_stvar( field, safe_cast( - static_cast( - LedgerFormats::getInstance().findTypeByName( - strValue)))); + static_cast(LedgerFormats::getInstance().findTypeByName(strValue)))); if (*name == sfGeneric) name = &sfLedgerEntry; @@ -286,8 +253,7 @@ parseUint16( } } if (!ret) - return parseUnsigned( - field, json_name, fieldName, name, value, error); + return parseUnsigned(field, json_name, fieldName, name, value, error); } catch (std::exception const&) { @@ -317,33 +283,26 @@ parseUint32( if (field == sfPermissionValue) { std::string const strValue = value.asString(); - auto const granularPermission = - Permission::getInstance().getGranularValue(strValue); + auto const granularPermission = Permission::getInstance().getGranularValue(strValue); if (granularPermission) { - ret = detail::make_stvar( - field, *granularPermission); + ret = detail::make_stvar(field, *granularPermission); } else { - auto const& txType = - TxFormats::getInstance().findTypeByName(strValue); - ret = detail::make_stvar( - field, - Permission::getInstance().txToPermissionType(txType)); + auto const& txType = TxFormats::getInstance().findTypeByName(strValue); + ret = detail::make_stvar(field, Permission::getInstance().txToPermissionType(txType)); } } else { ret = detail::make_stvar( field, - safe_cast( - beast::lexicalCastThrow(value.asString()))); + safe_cast(beast::lexicalCastThrow(value.asString()))); } } if (!ret) - return parseUnsigned( - field, json_name, fieldName, name, value, error); + return parseUnsigned(field, json_name, fieldName, name, value, error); } catch (std::exception const&) { @@ -382,31 +341,25 @@ parseLeaf( case STI_UINT8: try { - constexpr auto minValue = - std::numeric_limits::min(); - constexpr auto maxValue = - std::numeric_limits::max(); + constexpr auto minValue = std::numeric_limits::min(); + constexpr auto maxValue = std::numeric_limits::max(); if (value.isString()) { std::string const strValue = value.asString(); - if (!strValue.empty() && - ((strValue[0] < '0') || (strValue[0] > '9'))) + if (!strValue.empty() && ((strValue[0] < '0') || (strValue[0] > '9'))) { if (field == sfTransactionResult) { auto ter = transCode(strValue); - if (!ter || TERtoInt(*ter) < minValue || - TERtoInt(*ter) > maxValue) + if (!ter || TERtoInt(*ter) < minValue || TERtoInt(*ter) > maxValue) { error = out_of_range(json_name, fieldName); return ret; } - ret = detail::make_stvar( - field, - static_cast(TERtoInt(*ter))); + ret = detail::make_stvar(field, static_cast(TERtoInt(*ter))); } else { @@ -416,9 +369,7 @@ parseLeaf( } else { - ret = detail::make_stvar( - field, - beast::lexicalCastThrow(strValue)); + ret = detail::make_stvar(field, beast::lexicalCastThrow(strValue)); } } else if (value.isInt()) @@ -429,8 +380,7 @@ parseLeaf( return ret; } - ret = detail::make_stvar( - field, static_cast(value.asInt())); + ret = detail::make_stvar(field, static_cast(value.asInt())); } else if (value.isUInt()) { @@ -440,8 +390,7 @@ parseLeaf( return ret; } - ret = detail::make_stvar( - field, static_cast(value.asUInt())); + ret = detail::make_stvar(field, static_cast(value.asUInt())); } else { @@ -457,16 +406,14 @@ parseLeaf( break; case STI_UINT16: - ret = parseUint16( - field, json_name, fieldName, name, value, error); + ret = parseUint16(field, json_name, fieldName, name, value, error); if (!ret) return ret; break; case STI_UINT32: - ret = parseUint32( - field, json_name, fieldName, name, value, error); + ret = parseUint32(field, json_name, fieldName, name, value, error); if (!ret) return ret; @@ -481,15 +428,10 @@ parseLeaf( std::uint64_t val; - bool const useBase10 = - field.shouldMeta(SField::sMD_BaseTen); + bool const useBase10 = field.shouldMeta(SField::sMD_BaseTen); // if the field is amount, serialize as base 10 - auto [p, ec] = std::from_chars( - str.data(), - str.data() + str.size(), - val, - useBase10 ? 10 : 16); + auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), val, useBase10 ? 10 : 16); if (ec != std::errc() || (p != str.data() + str.size())) Throw("invalid data"); @@ -498,13 +440,11 @@ parseLeaf( } else if (value.isInt()) { - ret = detail::make_stvar( - field, to_unsigned(value.asInt())); + ret = detail::make_stvar(field, to_unsigned(value.asInt())); } else if (value.isUInt()) { - ret = detail::make_stvar( - field, safe_cast(value.asUInt())); + ret = detail::make_stvar(field, safe_cast(value.asUInt())); } else { @@ -621,32 +561,25 @@ parseLeaf( { if (value.isString()) { - ret = detail::make_stvar( - field, - beast::lexicalCastThrow( - value.asString())); + ret = detail::make_stvar(field, beast::lexicalCastThrow(value.asString())); } else if (value.isInt()) { // future-proofing - a static assert failure if the JSON // library ever supports larger ints // In such case, we will need additional bounds checks here - static_assert( - std::is_same_v); + static_assert(std::is_same_v); ret = detail::make_stvar(field, value.asInt()); } else if (value.isUInt()) { auto const uintValue = value.asUInt(); - if (uintValue > - static_cast( - std::numeric_limits::max())) + if (uintValue > static_cast(std::numeric_limits::max())) { error = out_of_range(json_name, fieldName); return ret; } - ret = detail::make_stvar( - field, static_cast(uintValue)); + ret = detail::make_stvar(field, static_cast(uintValue)); } else { @@ -673,8 +606,7 @@ parseLeaf( { if (auto vBlob = strUnHex(value.asString())) { - ret = detail::make_stvar( - field, vBlob->data(), vBlob->size()); + ret = detail::make_stvar(field, vBlob->data(), vBlob->size()); } else { @@ -692,8 +624,7 @@ parseLeaf( case STI_AMOUNT: try { - ret = - detail::make_stvar(amountFromJson(field, value)); + ret = detail::make_stvar(amountFromJson(field, value)); } catch (std::exception const&) { @@ -706,8 +637,7 @@ parseLeaf( case STI_NUMBER: try { - ret = - detail::make_stvar(numberFromJson(field, value)); + ret = detail::make_stvar(numberFromJson(field, value)); } catch (std::exception const&) { @@ -771,8 +701,7 @@ parseLeaf( { std::stringstream ss; ss << fieldName << "[" << i << "][" << j << "]"; - std::string const element_name( - json_name + "." + ss.str()); + std::string const element_name(json_name + "." + ss.str()); // each element in this path has some combination of // account, currency, or issuer @@ -803,8 +732,7 @@ parseLeaf( // human account id if (!account.isString()) { - error = - string_expected(element_name, "account"); + error = string_expected(element_name, "account"); return ret; } @@ -812,12 +740,10 @@ parseLeaf( // we set it, otherwise, we assume it's an AccountID if (!uAccount.parseHex(account.asString())) { - auto const a = - parseBase58(account.asString()); + auto const a = parseBase58(account.asString()); if (!a) { - error = - invalid_data(element_name, "account"); + error = invalid_data(element_name, "account"); return ret; } uAccount = *a; @@ -829,8 +755,7 @@ parseLeaf( // human currency if (!currency.isString()) { - error = - string_expected(element_name, "currency"); + error = string_expected(element_name, "currency"); return ret; } @@ -838,11 +763,9 @@ parseLeaf( if (!uCurrency.parseHex(currency.asString())) { - if (!to_currency( - uCurrency, currency.asString())) + if (!to_currency(uCurrency, currency.asString())) { - error = - invalid_data(element_name, "currency"); + error = invalid_data(element_name, "currency"); return ret; } } @@ -859,20 +782,17 @@ parseLeaf( if (!uIssuer.parseHex(issuer.asString())) { - auto const a = - parseBase58(issuer.asString()); + auto const a = parseBase58(issuer.asString()); if (!a) { - error = - invalid_data(element_name, "issuer"); + error = invalid_data(element_name, "issuer"); return ret; } uIssuer = *a; } } - p.emplace_back( - uAccount, uCurrency, uIssuer, hasCurrency); + p.emplace_back(uAccount, uCurrency, uIssuer, hasCurrency); } tail.push_back(p); @@ -930,8 +850,7 @@ parseLeaf( case STI_XCHAIN_BRIDGE: try { - ret = detail::make_stvar( - STXChainBridge(field, value)); + ret = detail::make_stvar(STXChainBridge(field, value)); } catch (std::exception const&) { @@ -943,8 +862,7 @@ parseLeaf( case STI_CURRENCY: try { - ret = detail::make_stvar( - currencyFromJson(field, value)); + ret = detail::make_stvar(currencyFromJson(field, value)); } catch (std::exception const&) { @@ -965,20 +883,10 @@ static int const maxDepth = 64; // Forward declaration since parseObject() and parseArray() call each other. static std::optional -parseArray( - std::string const& json_name, - Json::Value const& json, - SField const& inName, - int depth, - Json::Value& error); +parseArray(std::string const& json_name, Json::Value const& json, SField const& inName, int depth, Json::Value& error); static std::optional -parseObject( - std::string const& json_name, - Json::Value const& json, - SField const& inName, - int depth, - Json::Value& error) +parseObject(std::string const& json_name, Json::Value const& json, SField const& inName, int depth, Json::Value& error) { if (!json.isObjectOrNull()) { @@ -1023,12 +931,7 @@ parseObject( try { - auto ret = parseObject( - json_name + "." + fieldName, - value, - field, - depth + 1, - error); + auto ret = parseObject(json_name + "." + fieldName, value, field, depth + 1, error); if (!ret) return std::nullopt; data.emplace_back(std::move(*ret)); @@ -1045,12 +948,7 @@ parseObject( case STI_ARRAY: try { - auto array = parseArray( - json_name + "." + fieldName, - value, - field, - depth + 1, - error); + auto array = parseArray(json_name + "." + fieldName, value, field, depth + 1, error); if (!array.has_value()) return std::nullopt; data.emplace_back(std::move(*array)); @@ -1065,8 +963,7 @@ parseObject( // Everything else (types that don't recurse). default: { - auto leaf = - parseLeaf(json_name, fieldName, &inName, value, error); + auto leaf = parseLeaf(json_name, fieldName, &inName, value, error); if (!leaf) return std::nullopt; @@ -1096,12 +993,7 @@ parseObject( } static std::optional -parseArray( - std::string const& json_name, - Json::Value const& json, - SField const& inName, - int depth, - Json::Value& error) +parseArray(std::string const& json_name, Json::Value const& json, SField const& inName, int depth, Json::Value& error) { if (!json.isArrayOrNull()) { @@ -1149,13 +1041,11 @@ parseArray( std::stringstream ss; ss << json_name << "." << "[" << i << "]." << objectName; - auto ret = parseObject( - ss.str(), objectFields, nameField, depth + 1, error); + auto ret = parseObject(ss.str(), objectFields, nameField, depth + 1, error); if (!ret) { std::string errMsg = error["error_message"].asString(); - error["error_message"] = - "Error at '" + ss.str() + "'. " + errMsg; + error["error_message"] = "Error at '" + ss.str() + "'. " + errMsg; return std::nullopt; } @@ -1182,9 +1072,7 @@ parseArray( //------------------------------------------------------------------------------ -STParsedJSONObject::STParsedJSONObject( - std::string const& name, - Json::Value const& json) +STParsedJSONObject::STParsedJSONObject(std::string const& name, Json::Value const& json) { using namespace STParsedJSONDetail; object = parseObject(name, json, sfGeneric, 0, error); diff --git a/src/libxrpl/protocol/STPathSet.cpp b/src/libxrpl/protocol/STPathSet.cpp index 631fd51d8a..060f5c4d7c 100644 --- a/src/libxrpl/protocol/STPathSet.cpp +++ b/src/libxrpl/protocol/STPathSet.cpp @@ -47,8 +47,7 @@ STPathSet::STPathSet(SerialIter& sit, SField const& name) : STBase(name) { int iType = sit.get8(); - if (iType == STPathElement::typeNone || - iType == STPathElement::typeBoundary) + if (iType == STPathElement::typeNone || iType == STPathElement::typeBoundary) { if (path.empty()) { @@ -64,8 +63,7 @@ STPathSet::STPathSet(SerialIter& sit, SField const& name) : STBase(name) } else if (iType & ~STPathElement::typeAll) { - JLOG(debugLog().error()) - << "Bad path element " << iType << " in pathset"; + JLOG(debugLog().error()) << "Bad path element " << iType << " in pathset"; Throw("bad path element"); } else @@ -139,15 +137,11 @@ STPathSet::isDefault() const } bool -STPath::hasSeen( - AccountID const& account, - Currency const& currency, - AccountID const& issuer) const +STPath::hasSeen(AccountID const& account, Currency const& currency, AccountID const& issuer) const { for (auto& p : mPath) { - if (p.getAccountID() == account && p.getCurrency() == currency && - p.getIssuerID() == issuer) + if (p.getAccountID() == account && p.getCurrency() == currency && p.getIssuerID() == issuer) return true; } @@ -200,11 +194,8 @@ STPathSet::getSType() const void STPathSet::add(Serializer& s) const { - XRPL_ASSERT( - getFName().isBinary(), "xrpl::STPathSet::add : field is binary"); - XRPL_ASSERT( - getFName().fieldType == STI_PATHSET, - "xrpl::STPathSet::add : valid field type"); + XRPL_ASSERT(getFName().isBinary(), "xrpl::STPathSet::add : field is binary"); + XRPL_ASSERT(getFName().fieldType == STI_PATHSET, "xrpl::STPathSet::add : valid field type"); bool first = true; for (auto const& spPath : value) diff --git a/src/libxrpl/protocol/STTakesAsset.cpp b/src/libxrpl/protocol/STTakesAsset.cpp index 9167c6ace0..ba57f4f2a8 100644 --- a/src/libxrpl/protocol/STTakesAsset.cpp +++ b/src/libxrpl/protocol/STTakesAsset.cpp @@ -23,15 +23,9 @@ associateAsset(SLE& sle, Asset const& asset) // SField auto& ta = entry.downcast(); auto const style = sle.getStyle(ta.getFName()); - XRPL_ASSERT_PARTS( - style != soeINVALID, - "xrpl::associateAsset", - "valid template element style"); + XRPL_ASSERT_PARTS(style != soeINVALID, "xrpl::associateAsset", "valid template element style"); - XRPL_ASSERT_PARTS( - style != soeDEFAULT || !ta.isDefault(), - "xrpl::associateAsset", - "non-default value"); + XRPL_ASSERT_PARTS(style != soeDEFAULT || !ta.isDefault(), "xrpl::associateAsset", "non-default value"); ta.associateAsset(asset); // associateAsset in derived classes may change the underlying diff --git a/src/libxrpl/protocol/STTx.cpp b/src/libxrpl/protocol/STTx.cpp index 6640468bd4..5dea8be56d 100644 --- a/src/libxrpl/protocol/STTx.cpp +++ b/src/libxrpl/protocol/STTx.cpp @@ -61,8 +61,7 @@ getTxFormat(TxType type) if (format == nullptr) { Throw( - "Invalid transaction type " + - std::to_string(safe_cast>(type))); + "Invalid transaction type " + std::to_string(safe_cast>(type))); } return format; @@ -91,8 +90,7 @@ STTx::STTx(SerialIter& sit) : STObject(sfTransaction) tid_ = getHash(HashPrefix::transactionID); } -STTx::STTx(TxType type, std::function assembler) - : STObject(sfTransaction) +STTx::STTx(TxType type, std::function assembler) : STObject(sfTransaction) { auto format = getTxFormat(type); @@ -148,9 +146,7 @@ STTx::getMentionedAccounts() const { if (auto sacc = dynamic_cast(&it)) { - XRPL_ASSERT( - !sacc->isDefault(), - "xrpl::STTx::getMentionedAccounts : account is set"); + XRPL_ASSERT(!sacc->isDefault(), "xrpl::STTx::getMentionedAccounts : account is set"); if (!sacc->isDefault()) list.insert(sacc->value()); } @@ -246,8 +242,7 @@ STTx::checkSign(Rules const& rules, STObject const& sigObject) const // multi-signing. Otherwise we're single-signing. Blob const& signingPubKey = sigObject.getFieldVL(sfSigningPubKey); - return signingPubKey.empty() ? checkMultiSign(rules, sigObject) - : checkSingleSign(sigObject); + return signingPubKey.empty() ? checkMultiSign(rules, sigObject) : checkSingleSign(sigObject); } catch (std::exception const&) { @@ -275,9 +270,7 @@ STTx::checkBatchSign(Rules const& rules) const { try { - XRPL_ASSERT( - getTxnType() == ttBATCH, - "STTx::checkBatchSign : not a batch transaction"); + XRPL_ASSERT(getTxnType() == ttBATCH, "STTx::checkBatchSign : not a batch transaction"); if (getTxnType() != ttBATCH) { JLOG(debugLog().fatal()) << "not a batch transaction"; @@ -287,9 +280,8 @@ STTx::checkBatchSign(Rules const& rules) const for (auto const& signer : signers) { Blob const& signingPubKey = signer.getFieldVL(sfSigningPubKey); - auto const result = signingPubKey.empty() - ? checkBatchMultiSign(signer, rules) - : checkBatchSingleSign(signer); + auto const result = + signingPubKey.empty() ? checkBatchMultiSign(signer, rules) : checkBatchSingleSign(signer); if (!result) return result; @@ -298,8 +290,7 @@ STTx::checkBatchSign(Rules const& rules) const } catch (std::exception const& e) { - JLOG(debugLog().error()) - << "Batch signature check failed: " << e.what(); + JLOG(debugLog().error()) << "Batch signature check failed: " << e.what(); } return Unexpected("Internal batch signature check failure."); } @@ -354,8 +345,7 @@ STTx::getMetaSQLInsertReplaceHeader() } std::string -STTx::getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData) - const +STTx::getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData) const { Serializer s; add(s); @@ -364,22 +354,16 @@ STTx::getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData) // VFALCO This could be a free function elsewhere std::string -STTx::getMetaSQL( - Serializer rawTxn, - std::uint32_t inLedger, - char status, - std::string const& escapedMetaData) const +STTx::getMetaSQL(Serializer rawTxn, std::uint32_t inLedger, char status, std::string const& escapedMetaData) const { - static boost::format bfTrans( - "('%s', '%s', '%s', '%d', '%d', '%c', %s, %s)"); + static boost::format bfTrans("('%s', '%s', '%s', '%d', '%d', '%c', %s, %s)"); std::string rTxn = sqlBlobLiteral(rawTxn.peekData()); auto format = TxFormats::getInstance().findByType(tx_type_); XRPL_ASSERT(format, "xrpl::STTx::getMetaSQL : non-null type format"); return str( - boost::format(bfTrans) % to_string(getTransactionID()) % - format->getName() % toBase58(getAccountID(sfAccount)) % + boost::format(bfTrans) % to_string(getTransactionID()) % format->getName() % toBase58(getAccountID(sfAccount)) % getFieldU32(sfSequence) % inLedger % status % rTxn % escapedMetaData); } @@ -399,8 +383,7 @@ singleSignHelper(STObject const& sigObject, Slice const& data) if (publicKeyType(makeSlice(spk))) { Blob const signature = sigObject.getFieldVL(sfTxnSignature); - validSig = - verify(PublicKey(makeSlice(spk)), data, makeSlice(signature)); + validSig = verify(PublicKey(makeSlice(spk)), data, makeSlice(signature)); } } catch (std::exception const&) @@ -449,8 +432,7 @@ multiSignHelper( STArray const& signers{sigObject.getFieldArray(sfSigners)}; // There are well known bounds that the number of signers must be within. - if (signers.size() < STTx::minMultiSigners || - signers.size() > STTx::maxMultiSigners) + if (signers.size() < STTx::minMultiSigners || signers.size() > STTx::maxMultiSigners) return Unexpected("Invalid Signers array size."); // Signers must be in sorted order by AccountID. @@ -486,10 +468,7 @@ multiSignHelper( if (publicKeyType(makeSlice(spk))) { Blob const signature = signer.getFieldVL(sfTxnSignature); - validSig = verify( - PublicKey(makeSlice(spk)), - makeMsg(accountID).slice(), - makeSlice(signature)); + validSig = verify(PublicKey(makeSlice(spk)), makeMsg(accountID).slice(), makeSlice(signature)); } } catch (std::exception const& e) @@ -500,8 +479,7 @@ multiSignHelper( } if (!validSig) return Unexpected( - std::string("Invalid signature on account ") + - toBase58(accountID) + errorWhat.value_or("") + "."); + std::string("Invalid signature on account ") + toBase58(accountID) + errorWhat.value_or("") + "."); } // All signatures verified. return {}; @@ -531,9 +509,7 @@ STTx::checkMultiSign(Rules const& rules, STObject const& sigObject) const { // Used inside the loop in multiSignHelper to enforce that // the account owner may not multisign for themselves. - auto const txnAccountID = &sigObject != this - ? std::nullopt - : std::optional(getAccountID(sfAccount)); + auto const txnAccountID = &sigObject != this ? std::nullopt : std::optional(getAccountID(sfAccount)); // We can ease the computational load inside the loop a bit by // pre-constructing part of the data that we hash. Fill a Serializer @@ -568,12 +544,8 @@ STTx::checkMultiSign(Rules const& rules, STObject const& sigObject) const std::vector const& STTx::getBatchTransactionIDs() const { - XRPL_ASSERT( - getTxnType() == ttBATCH, - "STTx::getBatchTransactionIDs : not a batch transaction"); - XRPL_ASSERT( - getFieldArray(sfRawTransactions).size() != 0, - "STTx::getBatchTransactionIDs : empty raw transactions"); + XRPL_ASSERT(getTxnType() == ttBATCH, "STTx::getBatchTransactionIDs : not a batch transaction"); + XRPL_ASSERT(getFieldArray(sfRawTransactions).size() != 0, "STTx::getBatchTransactionIDs : empty raw transactions"); // The list of inner ids is built once, then reused on subsequent calls. // After the list is built, it must always have the same size as the array @@ -626,8 +598,7 @@ isMemoOkay(STObject const& st, std::string& reason) { auto const& name = memoElement.getFName(); - if (name != sfMemoType && name != sfMemoData && - name != sfMemoFormat) + if (name != sfMemoType && name != sfMemoData && name != sfMemoFormat) { reason = "A memo may contain only MemoType, MemoData or " @@ -703,18 +674,15 @@ invalidMPTAmountInTx(STObject const& tx) auto const txType = tx[~sfTransactionType]; if (!txType) return false; - if (auto const* item = - TxFormats::getInstance().findByType(safe_cast(*txType))) + if (auto const* item = TxFormats::getInstance().findByType(safe_cast(*txType))) { for (auto const& e : item->getSOTemplate()) { if (tx.isFieldPresent(e.sField()) && e.supportMPT() != soeMPTNone) { if (auto const& field = tx.peekAtField(e.sField()); - (field.getSType() == STI_AMOUNT && - static_cast(field).holds()) || - (field.getSType() == STI_ISSUE && - static_cast(field).holds())) + (field.getSType() == STI_AMOUNT && static_cast(field).holds()) || + (field.getSType() == STI_ISSUE && static_cast(field).holds())) { if (e.supportMPT() != soeMPTSupported) return true; @@ -731,8 +699,7 @@ isRawTransactionOkay(STObject const& st, std::string& reason) if (!st.isFieldPresent(sfRawTransactions)) return true; - if (st.isFieldPresent(sfBatchSigners) && - st.getFieldArray(sfBatchSigners).size() > maxBatchTxCount) + if (st.isFieldPresent(sfBatchSigners) && st.getFieldArray(sfBatchSigners).size() > maxBatchTxCount) { reason = "Batch Signers array exceeds max entries."; return false; @@ -748,8 +715,7 @@ isRawTransactionOkay(STObject const& st, std::string& reason) { try { - TxType const tt = - safe_cast(raw.getFieldU16(sfTransactionType)); + TxType const tt = safe_cast(raw.getFieldU16(sfTransactionType)); if (tt == ttBATCH) { reason = "Raw Transactions may not contain batch transactions."; diff --git a/src/libxrpl/protocol/STValidation.cpp b/src/libxrpl/protocol/STValidation.cpp index f6f89d43e9..2bea078809 100644 --- a/src/libxrpl/protocol/STValidation.cpp +++ b/src/libxrpl/protocol/STValidation.cpp @@ -100,14 +100,10 @@ STValidation::isValid() const noexcept if (!valid_) { XRPL_ASSERT( - publicKeyType(getSignerPublic()) == KeyType::secp256k1, - "xrpl::STValidation::isValid : valid key type"); + publicKeyType(getSignerPublic()) == KeyType::secp256k1, "xrpl::STValidation::isValid : valid key type"); valid_ = verifyDigest( - getSignerPublic(), - getSigningHash(), - makeSlice(getFieldVL(sfSignature)), - getFlags() & vfFullyCanonicalSig); + getSignerPublic(), getSigningHash(), makeSlice(getFieldVL(sfSignature)), getFlags() & vfFullyCanonicalSig); } return valid_.value(); diff --git a/src/libxrpl/protocol/STVar.cpp b/src/libxrpl/protocol/STVar.cpp index e0df5d51a9..d77aabc312 100644 --- a/src/libxrpl/protocol/STVar.cpp +++ b/src/libxrpl/protocol/STVar.cpp @@ -93,8 +93,7 @@ STVar::STVar(defaultObject_t, SField const& name) : STVar(name.fieldType, name) { } -STVar::STVar(nonPresentObject_t, SField const& name) - : STVar(STI_NOTPRESENT, name) +STVar::STVar(nonPresentObject_t, SField const& name) : STVar(STI_NOTPRESENT, name) { } @@ -130,22 +129,17 @@ void STVar::constructST(SerializedTypeID id, int depth, Args&&... args) { auto constructWithDepth = [&]() { - if constexpr (std::is_same_v< - std::tuple...>, - std::tuple>) + if constexpr (std::is_same_v...>, std::tuple>) { construct(std::forward(args)...); } - else if constexpr (std::is_same_v< - std::tuple...>, - std::tuple>) + else if constexpr (std::is_same_v...>, std::tuple>) { construct(std::forward(args)..., depth); } else { - constexpr bool alwaysFalse = - !std::is_same_v, std::tuple>; + constexpr bool alwaysFalse = !std::is_same_v, std::tuple>; static_assert(alwaysFalse, "Invalid STVar constructor arguments"); } }; @@ -154,8 +148,7 @@ STVar::constructST(SerializedTypeID id, int depth, Args&&... args) { case STI_NOTPRESENT: { // Last argument is always SField - SField const& field = - std::get(std::forward_as_tuple(args...)); + SField const& field = std::get(std::forward_as_tuple(args...)); construct(field); return; } diff --git a/src/libxrpl/protocol/STVector256.cpp b/src/libxrpl/protocol/STVector256.cpp index 17b4895b62..312184dcc0 100644 --- a/src/libxrpl/protocol/STVector256.cpp +++ b/src/libxrpl/protocol/STVector256.cpp @@ -19,9 +19,7 @@ STVector256::STVector256(SerialIter& sit, SField const& name) : STBase(name) auto const slice = sit.getSlice(sit.getVLDataLength()); if (slice.size() % uint256::size() != 0) - Throw( - "Bad serialization for STVector256: " + - std::to_string(slice.size())); + Throw("Bad serialization for STVector256: " + std::to_string(slice.size())); auto const cnt = slice.size() / uint256::size(); @@ -58,11 +56,8 @@ STVector256::isDefault() const void STVector256::add(Serializer& s) const { - XRPL_ASSERT( - getFName().isBinary(), "xrpl::STVector256::add : field is binary"); - XRPL_ASSERT( - getFName().fieldType == STI_VECTOR256, - "xrpl::STVector256::add : valid field type"); + XRPL_ASSERT(getFName().isBinary(), "xrpl::STVector256::add : field is binary"); + XRPL_ASSERT(getFName().fieldType == STI_VECTOR256, "xrpl::STVector256::add : valid field type"); s.addVL(mValue.begin(), mValue.end(), mValue.size() * (256 / 8)); } diff --git a/src/libxrpl/protocol/STXChainBridge.cpp b/src/libxrpl/protocol/STXChainBridge.cpp index 413094b0cd..ed79c28f29 100644 --- a/src/libxrpl/protocol/STXChainBridge.cpp +++ b/src/libxrpl/protocol/STXChainBridge.cpp @@ -50,30 +50,25 @@ STXChainBridge::STXChainBridge(STObject const& o) { } -STXChainBridge::STXChainBridge(Json::Value const& v) - : STXChainBridge{sfXChainBridge, v} +STXChainBridge::STXChainBridge(Json::Value const& v) : STXChainBridge{sfXChainBridge, v} { } -STXChainBridge::STXChainBridge(SField const& name, Json::Value const& v) - : STBase{name} +STXChainBridge::STXChainBridge(SField const& name, Json::Value const& v) : STBase{name} { if (!v.isObject()) { - Throw( - "STXChainBridge can only be specified with a 'object' Json value"); + Throw("STXChainBridge can only be specified with a 'object' Json value"); } auto checkExtra = [](Json::Value const& v) { - static auto const bridgeJson = - xrpl::STXChainBridge().getJson(xrpl::JsonOptions::none); + static auto const bridgeJson = xrpl::STXChainBridge().getJson(xrpl::JsonOptions::none); for (auto it = v.begin(); it != v.end(); ++it) { std::string const name = it.memberName(); if (!bridgeJson.isMember(name)) { - Throw( - "STXChainBridge extra field detected: " + name); + Throw("STXChainBridge extra field detected: " + name); } } return true; @@ -87,36 +82,28 @@ STXChainBridge::STXChainBridge(SField const& name, Json::Value const& v) if (!lockingChainDoorStr.isString()) { - Throw( - "STXChainBridge LockingChainDoor must be a string Json value"); + Throw("STXChainBridge LockingChainDoor must be a string Json value"); } if (!issuingChainDoorStr.isString()) { - Throw( - "STXChainBridge IssuingChainDoor must be a string Json value"); + Throw("STXChainBridge IssuingChainDoor must be a string Json value"); } - auto const lockingChainDoor = - parseBase58(lockingChainDoorStr.asString()); - auto const issuingChainDoor = - parseBase58(issuingChainDoorStr.asString()); + auto const lockingChainDoor = parseBase58(lockingChainDoorStr.asString()); + auto const issuingChainDoor = parseBase58(issuingChainDoorStr.asString()); if (!lockingChainDoor) { - Throw( - "STXChainBridge LockingChainDoor must be a valid account"); + Throw("STXChainBridge LockingChainDoor must be a valid account"); } if (!issuingChainDoor) { - Throw( - "STXChainBridge IssuingChainDoor must be a valid account"); + Throw("STXChainBridge IssuingChainDoor must be a valid account"); } lockingChainDoor_ = STAccount{sfLockingChainDoor, *lockingChainDoor}; - lockingChainIssue_ = - STIssue{sfLockingChainIssue, issueFromJson(lockingChainIssue)}; + lockingChainIssue_ = STIssue{sfLockingChainIssue, issueFromJson(lockingChainIssue)}; issuingChainDoor_ = STAccount{sfIssuingChainDoor, *issuingChainDoor}; - issuingChainIssue_ = - STIssue{sfIssuingChainIssue, issueFromJson(issuingChainIssue)}; + issuingChainIssue_ = STIssue{sfIssuingChainIssue, issueFromJson(issuingChainIssue)}; } STXChainBridge::STXChainBridge(SerialIter& sit, SField const& name) @@ -152,11 +139,10 @@ std::string STXChainBridge::getText() const { return str( - boost::format("{ %s = %s, %s = %s, %s = %s, %s = %s }") % - sfLockingChainDoor.getName() % lockingChainDoor_.getText() % - sfLockingChainIssue.getName() % lockingChainIssue_.getText() % - sfIssuingChainDoor.getName() % issuingChainDoor_.getText() % - sfIssuingChainIssue.getName() % issuingChainIssue_.getText()); + boost::format("{ %s = %s, %s = %s, %s = %s, %s = %s }") % sfLockingChainDoor.getName() % + lockingChainDoor_.getText() % sfLockingChainIssue.getName() % lockingChainIssue_.getText() % + sfIssuingChainDoor.getName() % issuingChainDoor_.getText() % sfIssuingChainIssue.getName() % + issuingChainIssue_.getText()); } STObject @@ -186,8 +172,8 @@ STXChainBridge::isEquivalent(STBase const& t) const bool STXChainBridge::isDefault() const { - return lockingChainDoor_.isDefault() && lockingChainIssue_.isDefault() && - issuingChainDoor_.isDefault() && issuingChainIssue_.isDefault(); + return lockingChainDoor_.isDefault() && lockingChainIssue_.isDefault() && issuingChainDoor_.isDefault() && + issuingChainIssue_.isDefault(); } std::unique_ptr diff --git a/src/libxrpl/protocol/SecretKey.cpp b/src/libxrpl/protocol/SecretKey.cpp index 2507269407..ee112b9072 100644 --- a/src/libxrpl/protocol/SecretKey.cpp +++ b/src/libxrpl/protocol/SecretKey.cpp @@ -156,22 +156,16 @@ private: } public: - explicit Generator(Seed const& seed) - : root_(deriveDeterministicRootKey(seed)) + explicit Generator(Seed const& seed) : root_(deriveDeterministicRootKey(seed)) { secp256k1_pubkey pubkey; - if (secp256k1_ec_pubkey_create( - secp256k1Context(), &pubkey, root_.data()) != 1) + if (secp256k1_ec_pubkey_create(secp256k1Context(), &pubkey, root_.data()) != 1) LogicError("derivePublicKey: secp256k1_ec_pubkey_create failed"); auto len = generator_.size(); if (secp256k1_ec_pubkey_serialize( - secp256k1Context(), - generator_.data(), - &len, - &pubkey, - SECP256K1_EC_COMPRESSED) != 1) + secp256k1Context(), generator_.data(), &len, &pubkey, SECP256K1_EC_COMPRESSED) != 1) LogicError("derivePublicKey: secp256k1_ec_pubkey_serialize failed"); } @@ -189,8 +183,7 @@ public: auto gsk = [this, tweak = calculateTweak(ordinal)]() { auto rpk = root_; - if (secp256k1_ec_seckey_tweak_add( - secp256k1Context(), rpk.data(), tweak.data()) == 1) + if (secp256k1_ec_seckey_tweak_add(secp256k1Context(), rpk.data(), tweak.data()) == 1) { SecretKey sk{Slice{rpk.data(), rpk.size()}}; secure_erase(rpk.data(), rpk.size()); @@ -225,8 +218,7 @@ signDigest(PublicKey const& pk, SecretKey const& sk, uint256 const& digest) unsigned char sig[72]; size_t len = sizeof(sig); - if (secp256k1_ecdsa_signature_serialize_der( - secp256k1Context(), sig, &len, &sig_imp) != 1) + if (secp256k1_ecdsa_signature_serialize_der(secp256k1Context(), sig, &len, &sig_imp) != 1) LogicError("sign: secp256k1_ecdsa_signature_serialize_der failed"); return Buffer{sig, len}; @@ -242,8 +234,7 @@ sign(PublicKey const& pk, SecretKey const& sk, Slice const& m) { case KeyType::ed25519: { Buffer b(64); - ed25519_sign( - m.data(), m.size(), sk.data(), pk.data() + 1, b.data()); + ed25519_sign(m.data(), m.size(), sk.data(), pk.data() + 1, b.data()); return b; } case KeyType::secp256k1: { @@ -263,10 +254,8 @@ sign(PublicKey const& pk, SecretKey const& sk, Slice const& m) unsigned char sig[72]; size_t len = sizeof(sig); - if (secp256k1_ecdsa_signature_serialize_der( - secp256k1Context(), sig, &len, &sig_imp) != 1) - LogicError( - "sign: secp256k1_ecdsa_signature_serialize_der failed"); + if (secp256k1_ecdsa_signature_serialize_der(secp256k1Context(), sig, &len, &sig_imp) != 1) + LogicError("sign: secp256k1_ecdsa_signature_serialize_der failed"); return Buffer{sig, len}; } @@ -315,22 +304,14 @@ derivePublicKey(KeyType type, SecretKey const& sk) case KeyType::secp256k1: { secp256k1_pubkey pubkey_imp; if (secp256k1_ec_pubkey_create( - secp256k1Context(), - &pubkey_imp, - reinterpret_cast(sk.data())) != 1) - LogicError( - "derivePublicKey: secp256k1_ec_pubkey_create failed"); + secp256k1Context(), &pubkey_imp, reinterpret_cast(sk.data())) != 1) + LogicError("derivePublicKey: secp256k1_ec_pubkey_create failed"); unsigned char pubkey[33]; std::size_t len = sizeof(pubkey); - if (secp256k1_ec_pubkey_serialize( - secp256k1Context(), - pubkey, - &len, - &pubkey_imp, - SECP256K1_EC_COMPRESSED) != 1) - LogicError( - "derivePublicKey: secp256k1_ec_pubkey_serialize failed"); + if (secp256k1_ec_pubkey_serialize(secp256k1Context(), pubkey, &len, &pubkey_imp, SECP256K1_EC_COMPRESSED) != + 1) + LogicError("derivePublicKey: secp256k1_ec_pubkey_serialize failed"); return PublicKey{Slice{pubkey, len}}; } diff --git a/src/libxrpl/protocol/Seed.cpp b/src/libxrpl/protocol/Seed.cpp index 18e89ef6ca..2629d08439 100644 --- a/src/libxrpl/protocol/Seed.cpp +++ b/src/libxrpl/protocol/Seed.cpp @@ -80,10 +80,8 @@ parseGenericSeed(std::string const& str, bool rfc1751) if (str.empty()) return std::nullopt; - if (parseBase58(str) || - parseBase58(TokenType::NodePublic, str) || - parseBase58(TokenType::AccountPublic, str) || - parseBase58(TokenType::NodePrivate, str) || + if (parseBase58(str) || parseBase58(TokenType::NodePublic, str) || + parseBase58(TokenType::AccountPublic, str) || parseBase58(TokenType::NodePrivate, str) || parseBase58(TokenType::AccountSecret, str)) { return std::nullopt; diff --git a/src/libxrpl/protocol/Serializer.cpp b/src/libxrpl/protocol/Serializer.cpp index e6c1e6967f..bb3eb17ae3 100644 --- a/src/libxrpl/protocol/Serializer.cpp +++ b/src/libxrpl/protocol/Serializer.cpp @@ -34,8 +34,7 @@ Serializer::add32(HashPrefix p) { // This should never trigger; the size & type of a hash prefix are // integral parts of the protocol and unlikely to ever change. - static_assert( - std::is_same_v>); + static_assert(std::is_same_v>); return add32(safe_cast(p)); } @@ -108,8 +107,7 @@ Serializer::addFieldID(int type, int name) { int ret = mData.size(); XRPL_ASSERT( - (type > 0) && (type < 256) && (name > 0) && (name < 256), - "xrpl::Serializer::addFieldID : inputs inside range"); + (type > 0) && (type < 256) && (name > 0) && (name < 256), "xrpl::Serializer::addFieldID : inputs inside range"); if (type < 16) { @@ -179,8 +177,7 @@ Serializer::addVL(Blob const& vector) int ret = addEncoded(vector.size()); addRaw(vector); XRPL_ASSERT( - mData.size() == - (ret + vector.size() + encodeLengthLength(vector.size())), + mData.size() == (ret + vector.size() + encodeLengthLength(vector.size())), "xrpl::Serializer::addVL : size matches expected"); return ret; } @@ -369,8 +366,7 @@ SerialIter::get32() p_ += 4; used_ += 4; remain_ -= 4; - return (std::uint64_t(t[0]) << 24) + (std::uint64_t(t[1]) << 16) + - (std::uint64_t(t[2]) << 8) + std::uint64_t(t[3]); + return (std::uint64_t(t[0]) << 24) + (std::uint64_t(t[1]) << 16) + (std::uint64_t(t[2]) << 8) + std::uint64_t(t[3]); } std::uint64_t @@ -382,9 +378,8 @@ SerialIter::get64() p_ += 8; used_ += 8; remain_ -= 8; - return (std::uint64_t(t[0]) << 56) + (std::uint64_t(t[1]) << 48) + - (std::uint64_t(t[2]) << 40) + (std::uint64_t(t[3]) << 32) + - (std::uint64_t(t[4]) << 24) + (std::uint64_t(t[5]) << 16) + + return (std::uint64_t(t[0]) << 56) + (std::uint64_t(t[1]) << 48) + (std::uint64_t(t[2]) << 40) + + (std::uint64_t(t[3]) << 32) + (std::uint64_t(t[4]) << 24) + (std::uint64_t(t[5]) << 16) + (std::uint64_t(t[6]) << 8) + std::uint64_t(t[7]); } @@ -424,8 +419,7 @@ SerialIter::getFieldID(int& type, int& name) // uncommon type type = get8(); if (type < 16) - Throw( - "gFID: uncommon type out of range " + std::to_string(type)); + Throw("gFID: uncommon type out of range " + std::to_string(type)); } if (name == 0) @@ -433,8 +427,7 @@ SerialIter::getFieldID(int& type, int& name) // uncommon name name = get8(); if (name < 16) - Throw( - "gFID: uncommon name out of range " + std::to_string(name)); + Throw("gFID: uncommon name out of range " + std::to_string(name)); } } @@ -443,8 +436,7 @@ template T SerialIter::getRawHelper(int size) { - static_assert( - std::is_same::value || std::is_same::value, ""); + static_assert(std::is_same::value || std::is_same::value, ""); if (remain_ < size) Throw("invalid SerialIter getRaw"); T result(size); @@ -485,8 +477,7 @@ SerialIter::getVLDataLength() } else { - XRPL_ASSERT( - lenLen == 3, "xrpl::SerialIter::getVLDataLength : lenLen is 3"); + XRPL_ASSERT(lenLen == 3, "xrpl::SerialIter::getVLDataLength : lenLen is 3"); int b2 = get8(); int b3 = get8(); datLen = Serializer::decodeVLLength(b1, b2, b3); diff --git a/src/libxrpl/protocol/Sign.cpp b/src/libxrpl/protocol/Sign.cpp index 9edd2bbfa4..fe18941940 100644 --- a/src/libxrpl/protocol/Sign.cpp +++ b/src/libxrpl/protocol/Sign.cpp @@ -12,12 +12,7 @@ namespace xrpl { void -sign( - STObject& st, - HashPrefix const& prefix, - KeyType type, - SecretKey const& sk, - SF_VL const& sigField) +sign(STObject& st, HashPrefix const& prefix, KeyType type, SecretKey const& sk, SF_VL const& sigField) { Serializer ss; ss.add32(prefix); @@ -26,11 +21,7 @@ sign( } bool -verify( - STObject const& st, - HashPrefix const& prefix, - PublicKey const& pk, - SF_VL const& sigField) +verify(STObject const& st, HashPrefix const& prefix, PublicKey const& pk, SF_VL const& sigField) { auto const sig = get(st, sigField); if (!sig) @@ -38,8 +29,7 @@ verify( Serializer ss; ss.add32(prefix); st.addWithoutSigningFields(ss); - return verify( - pk, Slice(ss.data(), ss.size()), Slice(sig->data(), sig->size())); + return verify(pk, Slice(ss.data(), ss.size()), Slice(sig->data(), sig->size())); } // Questions regarding buildMultiSigningData: diff --git a/src/libxrpl/protocol/TER.cpp b/src/libxrpl/protocol/TER.cpp index 6871cf5700..723bbae505 100644 --- a/src/libxrpl/protocol/TER.cpp +++ b/src/libxrpl/protocol/TER.cpp @@ -10,9 +10,7 @@ namespace xrpl { -std::unordered_map< - TERUnderlyingType, - std::pair> const& +std::unordered_map> const& transResults() { // clang-format off @@ -265,11 +263,9 @@ transCode(std::string const& token) static auto const results = [] { auto& byTer = transResults(); auto range = boost::make_iterator_range(byTer.begin(), byTer.end()); - auto tRange = boost::adaptors::transform(range, [](auto const& r) { - return std::make_pair(r.second.first, r.first); - }); - std::unordered_map const byToken( - tRange.begin(), tRange.end()); + auto tRange = + boost::adaptors::transform(range, [](auto const& r) { return std::make_pair(r.second.first, r.first); }); + std::unordered_map const byToken(tRange.begin(), tRange.end()); return byToken; }(); diff --git a/src/libxrpl/protocol/TxFormats.cpp b/src/libxrpl/protocol/TxFormats.cpp index c725c1da69..00a560de1b 100644 --- a/src/libxrpl/protocol/TxFormats.cpp +++ b/src/libxrpl/protocol/TxFormats.cpp @@ -36,8 +36,7 @@ TxFormats::TxFormats() #undef TRANSACTION #define UNWRAP(...) __VA_ARGS__ -#define TRANSACTION( \ - tag, value, name, delegable, amendment, privileges, fields) \ +#define TRANSACTION(tag, value, name, delegable, amendment, privileges, fields) \ add(jss::name, tag, UNWRAP fields, commonFields); #include diff --git a/src/libxrpl/protocol/TxMeta.cpp b/src/libxrpl/protocol/TxMeta.cpp index f0077c7f92..62e62a9b5c 100644 --- a/src/libxrpl/protocol/TxMeta.cpp +++ b/src/libxrpl/protocol/TxMeta.cpp @@ -21,17 +21,13 @@ namespace xrpl { TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj) - : transactionID_(txid) - , ledgerSeq_(ledger) - , nodes_(obj.getFieldArray(sfAffectedNodes)) + : transactionID_(txid), ledgerSeq_(ledger), nodes_(obj.getFieldArray(sfAffectedNodes)) { result_ = obj.getFieldU8(sfTransactionResult); index_ = obj.getFieldU32(sfTransactionIndex); - auto affectedNodes = - dynamic_cast(obj.peekAtPField(sfAffectedNodes)); - XRPL_ASSERT( - affectedNodes, "xrpl::TxMeta::TxMeta(STObject) : type cast succeeded"); + auto affectedNodes = dynamic_cast(obj.peekAtPField(sfAffectedNodes)); + XRPL_ASSERT(affectedNodes, "xrpl::TxMeta::TxMeta(STObject) : type cast succeeded"); if (affectedNodes) nodes_ = *affectedNodes; @@ -62,10 +58,7 @@ TxMeta::TxMeta(uint256 const& transactionID, std::uint32_t ledger) } void -TxMeta::setAffectedNode( - uint256 const& node, - SField const& type, - std::uint16_t nodeType) +TxMeta::setAffectedNode(uint256 const& node, SField const& type, std::uint16_t nodeType) { // make sure the node exists and force its type for (auto& n : nodes_) @@ -81,9 +74,7 @@ TxMeta::setAffectedNode( nodes_.push_back(STObject(type)); STObject& obj = nodes_.back(); - XRPL_ASSERT( - obj.getFName() == type, - "xrpl::TxMeta::setAffectedNode : field type match"); + XRPL_ASSERT(obj.getFName() == type, "xrpl::TxMeta::setAffectedNode : field type match"); obj.setFieldH256(sfLedgerIndex, node); obj.setFieldU16(sfLedgerEntryType, nodeType); } @@ -98,33 +89,25 @@ TxMeta::getAffectedAccounts() const // Meta#getAffectedAccounts for (auto const& node : nodes_) { - int index = node.getFieldIndex( - (node.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields); + int index = node.getFieldIndex((node.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields); if (index != -1) { - auto const* inner = - dynamic_cast(&node.peekAtIndex(index)); - XRPL_ASSERT( - inner, - "xrpl::getAffectedAccounts : STObject type cast succeeded"); + auto const* inner = dynamic_cast(&node.peekAtIndex(index)); + XRPL_ASSERT(inner, "xrpl::getAffectedAccounts : STObject type cast succeeded"); if (inner) { for (auto const& field : *inner) { if (auto sa = dynamic_cast(&field)) { - XRPL_ASSERT( - !sa->isDefault(), - "xrpl::getAffectedAccounts : account is set"); + XRPL_ASSERT(!sa->isDefault(), "xrpl::getAffectedAccounts : account is set"); if (!sa->isDefault()) list.insert(sa->value()); } else if ( - (field.getFName() == sfLowLimit) || - (field.getFName() == sfHighLimit) || - (field.getFName() == sfTakerPays) || - (field.getFName() == sfTakerGets)) + (field.getFName() == sfLowLimit) || (field.getFName() == sfHighLimit) || + (field.getFName() == sfTakerPays) || (field.getFName() == sfTakerGets)) { auto lim = dynamic_cast(&field); XRPL_ASSERT( @@ -142,8 +125,7 @@ TxMeta::getAffectedAccounts() const } else if (field.getFName() == sfMPTokenIssuanceID) { - auto mptID = - dynamic_cast const*>(&field); + auto mptID = dynamic_cast const*>(&field); if (mptID != nullptr) { auto issuer = MPTIssue(mptID->value()).getIssuer(); @@ -172,9 +154,7 @@ TxMeta::getAffectedNode(SLE::ref node, SField const& type) nodes_.push_back(STObject(type)); STObject& obj = nodes_.back(); - XRPL_ASSERT( - obj.getFName() == type, - "xrpl::TxMeta::getAffectedNode(SLE::ref) : field type match"); + XRPL_ASSERT(obj.getFName() == type, "xrpl::TxMeta::getAffectedNode(SLE::ref) : field type match"); obj.setFieldH256(sfLedgerIndex, index); obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType)); @@ -218,9 +198,7 @@ TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index) { result_ = TERtoInt(result); index_ = index; - XRPL_ASSERT( - (result_ == 0) || ((result_ > 100) && (result_ <= 255)), - "xrpl::TxMeta::addRaw : valid TER input"); + XRPL_ASSERT((result_ == 0) || ((result_ > 100) && (result_ <= 255)), "xrpl::TxMeta::addRaw : valid TER input"); nodes_.sort([](STObject const& o1, STObject const& o2) { return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex); diff --git a/src/libxrpl/protocol/UintTypes.cpp b/src/libxrpl/protocol/UintTypes.cpp index 6c799397ee..ca29147989 100644 --- a/src/libxrpl/protocol/UintTypes.cpp +++ b/src/libxrpl/protocol/UintTypes.cpp @@ -40,19 +40,16 @@ to_string(Currency const& currency) if (currency == noCurrency()) return "1"; - static constexpr Currency sIsoBits( - "FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF"); + static constexpr Currency sIsoBits("FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF"); if ((currency & sIsoBits).isZero()) { std::string const iso( - currency.data() + detail::isoCodeOffset, - currency.data() + detail::isoCodeOffset + detail::isoCodeLength); + currency.data() + detail::isoCodeOffset, currency.data() + detail::isoCodeOffset + detail::isoCodeLength); // Specifying the system currency code using ISO-style representation // is not allowed. - if ((iso != systemCurrencyCode()) && - (iso.find_first_not_of(detail::isoCharSet) == std::string::npos)) + if ((iso != systemCurrencyCode()) && (iso.find_first_not_of(detail::isoCharSet) == std::string::npos)) { return iso; } @@ -78,8 +75,7 @@ to_currency(Currency& currency, std::string const& code) currency = beast::zero; - std::copy( - code.begin(), code.end(), currency.begin() + detail::isoCodeOffset); + std::copy(code.begin(), code.end(), currency.begin() + detail::isoCodeOffset); return true; } diff --git a/src/libxrpl/protocol/XChainAttestations.cpp b/src/libxrpl/protocol/XChainAttestations.cpp index 89771b63b0..5f109ea272 100644 --- a/src/libxrpl/protocol/XChainAttestations.cpp +++ b/src/libxrpl/protocol/XChainAttestations.cpp @@ -44,9 +44,7 @@ AttestationBase::AttestationBase( } bool -AttestationBase::equalHelper( - AttestationBase const& lhs, - AttestationBase const& rhs) +AttestationBase::equalHelper(AttestationBase const& lhs, AttestationBase const& rhs) { return std::tie( lhs.attestationSignerAccount, @@ -67,16 +65,10 @@ AttestationBase::equalHelper( } bool -AttestationBase::sameEventHelper( - AttestationBase const& lhs, - AttestationBase const& rhs) +AttestationBase::sameEventHelper(AttestationBase const& lhs, AttestationBase const& rhs) { - return std::tie( - lhs.sendingAccount, - lhs.sendingAmount, - lhs.wasLockingChainSend) == - std::tie( - rhs.sendingAccount, rhs.sendingAmount, rhs.wasLockingChainSend); + return std::tie(lhs.sendingAccount, lhs.sendingAmount, lhs.wasLockingChainSend) == + std::tie(rhs.sendingAccount, rhs.sendingAmount, rhs.wasLockingChainSend); } bool @@ -98,9 +90,7 @@ AttestationBase::AttestationBase(STObject const& o) } AttestationBase::AttestationBase(Json::Value const& v) - : attestationSignerAccount{Json::getOrThrow( - v, - sfAttestationSignerAccount)} + : attestationSignerAccount{Json::getOrThrow(v, sfAttestationSignerAccount)} , publicKey{Json::getOrThrow(v, sfPublicKey)} , signature{Json::getOrThrow(v, sfSignature)} , sendingAccount{Json::getOrThrow(v, sfAccount)} @@ -177,8 +167,7 @@ AttestationClaim::AttestationClaim(STObject const& o) } AttestationClaim::AttestationClaim(Json::Value const& v) - : AttestationBase{v} - , claimID{Json::getOrThrow(v, sfXChainClaimID)} + : AttestationBase{v}, claimID{Json::getOrThrow(v, sfXChainClaimID)} { if (v.isMember(sfDestination.getJsonName())) dst = Json::getOrThrow(v, sfDestination); @@ -187,8 +176,7 @@ AttestationClaim::AttestationClaim(Json::Value const& v) STObject AttestationClaim::toSTObject() const { - STObject o = - STObject::makeInnerObject(sfXChainClaimAttestationCollectionElement); + STObject o = STObject::makeInnerObject(sfXChainClaimAttestationCollectionElement); addHelper(o); o[sfXChainClaimID] = claimID; if (dst) @@ -227,13 +215,7 @@ std::vector AttestationClaim::message(STXChainBridge const& bridge) const { return AttestationClaim::message( - bridge, - sendingAccount, - sendingAmount, - rewardAccount, - wasLockingChainSend, - claimID, - dst); + bridge, sendingAccount, sendingAmount, rewardAccount, wasLockingChainSend, claimID, dst); } bool @@ -245,15 +227,13 @@ AttestationClaim::validAmounts() const bool AttestationClaim::sameEvent(AttestationClaim const& rhs) const { - return AttestationClaim::sameEventHelper(*this, rhs) && - tie(claimID, dst) == tie(rhs.claimID, rhs.dst); + return AttestationClaim::sameEventHelper(*this, rhs) && tie(claimID, dst) == tie(rhs.claimID, rhs.dst); } bool operator==(AttestationClaim const& lhs, AttestationClaim const& rhs) { - return AttestationClaim::equalHelper(lhs, rhs) && - tie(lhs.claimID, lhs.dst) == tie(rhs.claimID, rhs.dst); + return AttestationClaim::equalHelper(lhs, rhs) && tie(lhs.claimID, lhs.dst) == tie(rhs.claimID, rhs.dst); } AttestationCreateAccount::AttestationCreateAccount(STObject const& o) @@ -266,9 +246,7 @@ AttestationCreateAccount::AttestationCreateAccount(STObject const& o) AttestationCreateAccount::AttestationCreateAccount(Json::Value const& v) : AttestationBase{v} - , createCount{Json::getOrThrow( - v, - sfXChainAccountCreateCount)} + , createCount{Json::getOrThrow(v, sfXChainAccountCreateCount)} , toCreate{Json::getOrThrow(v, sfDestination)} , rewardAmount{Json::getOrThrow(v, sfSignatureReward)} { @@ -330,8 +308,7 @@ AttestationCreateAccount::AttestationCreateAccount( STObject AttestationCreateAccount::toSTObject() const { - STObject o = STObject::makeInnerObject( - sfXChainCreateAccountAttestationCollectionElement); + STObject o = STObject::makeInnerObject(sfXChainCreateAccountAttestationCollectionElement); addHelper(o); o[sfXChainAccountCreateCount] = createCount; @@ -373,14 +350,7 @@ std::vector AttestationCreateAccount::message(STXChainBridge const& bridge) const { return AttestationCreateAccount::message( - bridge, - sendingAccount, - sendingAmount, - rewardAmount, - rewardAccount, - wasLockingChainSend, - createCount, - toCreate); + bridge, sendingAccount, sendingAmount, rewardAmount, rewardAccount, wasLockingChainSend, createCount, toCreate); } bool @@ -393,14 +363,11 @@ bool AttestationCreateAccount::sameEvent(AttestationCreateAccount const& rhs) const { return AttestationCreateAccount::sameEventHelper(*this, rhs) && - std::tie(createCount, toCreate, rewardAmount) == - std::tie(rhs.createCount, rhs.toCreate, rhs.rewardAmount); + std::tie(createCount, toCreate, rewardAmount) == std::tie(rhs.createCount, rhs.toCreate, rhs.rewardAmount); } bool -operator==( - AttestationCreateAccount const& lhs, - AttestationCreateAccount const& rhs) +operator==(AttestationCreateAccount const& lhs, AttestationCreateAccount const& rhs) { return AttestationCreateAccount::equalHelper(lhs, rhs) && std::tie(lhs.createCount, lhs.toCreate, lhs.rewardAmount) == @@ -410,8 +377,7 @@ operator==( } // namespace Attestations SField const& XChainClaimAttestation::ArrayFieldName{sfXChainClaimAttestations}; -SField const& XChainCreateAccountAttestation::ArrayFieldName{ - sfXChainCreateAccountAttestations}; +SField const& XChainCreateAccountAttestation::ArrayFieldName{sfXChainCreateAccountAttestations}; XChainClaimAttestation::XChainClaimAttestation( AccountID const& keyAccount_, @@ -468,8 +434,7 @@ XChainClaimAttestation::XChainClaimAttestation(Json::Value const& v) dst = Json::getOrThrow(v, sfDestination); }; -XChainClaimAttestation::XChainClaimAttestation( - XChainClaimAttestation::TSignedAttestation const& claimAtt) +XChainClaimAttestation::XChainClaimAttestation(XChainClaimAttestation::TSignedAttestation const& claimAtt) : XChainClaimAttestation{ claimAtt.attestationSignerAccount, claimAtt.publicKey, @@ -484,12 +449,10 @@ STObject XChainClaimAttestation::toSTObject() const { STObject o = STObject::makeInnerObject(sfXChainClaimProofSig); - o[sfAttestationSignerAccount] = - STAccount{sfAttestationSignerAccount, keyAccount}; + o[sfAttestationSignerAccount] = STAccount{sfAttestationSignerAccount, keyAccount}; o[sfPublicKey] = publicKey; o[sfAmount] = STAmount{sfAmount, amount}; - o[sfAttestationRewardAccount] = - STAccount{sfAttestationRewardAccount, rewardAccount}; + o[sfAttestationRewardAccount] = STAccount{sfAttestationRewardAccount, rewardAccount}; o[sfWasLockingChainSend] = wasLockingChainSend; if (dst) o[sfDestination] = STAccount{sfDestination, *dst}; @@ -499,36 +462,19 @@ XChainClaimAttestation::toSTObject() const bool operator==(XChainClaimAttestation const& lhs, XChainClaimAttestation const& rhs) { - return std::tie( - lhs.keyAccount, - lhs.publicKey, - lhs.amount, - lhs.rewardAccount, - lhs.wasLockingChainSend, - lhs.dst) == - std::tie( - rhs.keyAccount, - rhs.publicKey, - rhs.amount, - rhs.rewardAccount, - rhs.wasLockingChainSend, - rhs.dst); + return std::tie(lhs.keyAccount, lhs.publicKey, lhs.amount, lhs.rewardAccount, lhs.wasLockingChainSend, lhs.dst) == + std::tie(rhs.keyAccount, rhs.publicKey, rhs.amount, rhs.rewardAccount, rhs.wasLockingChainSend, rhs.dst); } -XChainClaimAttestation::MatchFields::MatchFields( - XChainClaimAttestation::TSignedAttestation const& att) - : amount{att.sendingAmount} - , wasLockingChainSend{att.wasLockingChainSend} - , dst{att.dst} +XChainClaimAttestation::MatchFields::MatchFields(XChainClaimAttestation::TSignedAttestation const& att) + : amount{att.sendingAmount}, wasLockingChainSend{att.wasLockingChainSend}, dst{att.dst} { } AttestationMatch -XChainClaimAttestation::match( - XChainClaimAttestation::MatchFields const& rhs) const +XChainClaimAttestation::match(XChainClaimAttestation::MatchFields const& rhs) const { - if (std::tie(amount, wasLockingChainSend) != - std::tie(rhs.amount, rhs.wasLockingChainSend)) + if (std::tie(amount, wasLockingChainSend) != std::tie(rhs.amount, rhs.wasLockingChainSend)) return AttestationMatch::nonDstMismatch; if (dst != rhs.dst) return AttestationMatch::matchExceptDst; @@ -555,8 +501,7 @@ XChainCreateAccountAttestation::XChainCreateAccountAttestation( { } -XChainCreateAccountAttestation::XChainCreateAccountAttestation( - STObject const& o) +XChainCreateAccountAttestation::XChainCreateAccountAttestation(STObject const& o) : XChainCreateAccountAttestation{ o[sfAttestationSignerAccount], PublicKey{o[sfPublicKey]}, @@ -566,8 +511,7 @@ XChainCreateAccountAttestation::XChainCreateAccountAttestation( o[sfWasLockingChainSend] != 0, o[sfDestination]} {}; -XChainCreateAccountAttestation ::XChainCreateAccountAttestation( - Json::Value const& v) +XChainCreateAccountAttestation ::XChainCreateAccountAttestation(Json::Value const& v) : XChainCreateAccountAttestation{ Json::getOrThrow(v, sfAttestationSignerAccount), Json::getOrThrow(v, sfPublicKey), @@ -597,21 +541,18 @@ XChainCreateAccountAttestation::toSTObject() const { STObject o = STObject::makeInnerObject(sfXChainCreateAccountProofSig); - o[sfAttestationSignerAccount] = - STAccount{sfAttestationSignerAccount, keyAccount}; + o[sfAttestationSignerAccount] = STAccount{sfAttestationSignerAccount, keyAccount}; o[sfPublicKey] = publicKey; o[sfAmount] = STAmount{sfAmount, amount}; o[sfSignatureReward] = STAmount{sfSignatureReward, rewardAmount}; - o[sfAttestationRewardAccount] = - STAccount{sfAttestationRewardAccount, rewardAccount}; + o[sfAttestationRewardAccount] = STAccount{sfAttestationRewardAccount, rewardAccount}; o[sfWasLockingChainSend] = wasLockingChainSend; o[sfDestination] = STAccount{sfDestination, dst}; return o; } -XChainCreateAccountAttestation::MatchFields::MatchFields( - XChainCreateAccountAttestation::TSignedAttestation const& att) +XChainCreateAccountAttestation::MatchFields::MatchFields(XChainCreateAccountAttestation::TSignedAttestation const& att) : amount{att.sendingAmount} , rewardAmount(att.rewardAmount) , wasLockingChainSend{att.wasLockingChainSend} @@ -620,8 +561,7 @@ XChainCreateAccountAttestation::MatchFields::MatchFields( } AttestationMatch -XChainCreateAccountAttestation::match( - XChainCreateAccountAttestation::MatchFields const& rhs) const +XChainCreateAccountAttestation::match(XChainCreateAccountAttestation::MatchFields const& rhs) const { if (std::tie(amount, rewardAmount, wasLockingChainSend) != std::tie(rhs.amount, rhs.rewardAmount, rhs.wasLockingChainSend)) @@ -632,9 +572,7 @@ XChainCreateAccountAttestation::match( } bool -operator==( - XChainCreateAccountAttestation const& lhs, - XChainCreateAccountAttestation const& rhs) +operator==(XChainCreateAccountAttestation const& lhs, XChainCreateAccountAttestation const& rhs) { return std::tie( lhs.keyAccount, @@ -657,8 +595,7 @@ operator==( //------------------------------------------------------------------------------ // template -XChainAttestationsBase::XChainAttestationsBase( - XChainAttestationsBase::AttCollection&& atts) +XChainAttestationsBase::XChainAttestationsBase(XChainAttestationsBase::AttCollection&& atts) : attestations_{std::move(atts)} { } @@ -692,8 +629,7 @@ XChainAttestationsBase::end() } template -XChainAttestationsBase::XChainAttestationsBase( - Json::Value const& v) +XChainAttestationsBase::XChainAttestationsBase(Json::Value const& v) { if (!v.isObject()) { @@ -706,8 +642,7 @@ XChainAttestationsBase::XChainAttestationsBase( auto const jAtts = v[jss::attestations]; if (jAtts.size() > maxAttestations) - Throw( - "XChainAttestationsBase exceeded max number of attestations"); + Throw("XChainAttestationsBase exceeded max number of attestations"); std::vector r; r.reserve(jAtts.size()); @@ -721,8 +656,7 @@ template XChainAttestationsBase::XChainAttestationsBase(STArray const& arr) { if (arr.size() > maxAttestations) - Throw( - "XChainAttestationsBase exceeded max number of attestations"); + Throw("XChainAttestationsBase exceeded max number of attestations"); attestations_.reserve(arr.size()); for (auto const& o : arr) diff --git a/src/libxrpl/protocol/digest.cpp b/src/libxrpl/protocol/digest.cpp index dd4ecd7688..aa5600dde0 100644 --- a/src/libxrpl/protocol/digest.cpp +++ b/src/libxrpl/protocol/digest.cpp @@ -9,18 +9,13 @@ namespace xrpl { openssl_ripemd160_hasher::openssl_ripemd160_hasher() { - static_assert( - sizeof(decltype(openssl_ripemd160_hasher::ctx_)) == - sizeof(RIPEMD160_CTX), - ""); + static_assert(sizeof(decltype(openssl_ripemd160_hasher::ctx_)) == sizeof(RIPEMD160_CTX), ""); auto const ctx = reinterpret_cast(ctx_); RIPEMD160_Init(ctx); } void -openssl_ripemd160_hasher::operator()( - void const* data, - std::size_t size) noexcept +openssl_ripemd160_hasher::operator()(void const* data, std::size_t size) noexcept { auto const ctx = reinterpret_cast(ctx_); RIPEMD160_Update(ctx, data, size); @@ -38,9 +33,7 @@ openssl_ripemd160_hasher::operator result_type() noexcept openssl_sha512_hasher::openssl_sha512_hasher() { - static_assert( - sizeof(decltype(openssl_sha512_hasher::ctx_)) == sizeof(SHA512_CTX), - ""); + static_assert(sizeof(decltype(openssl_sha512_hasher::ctx_)) == sizeof(SHA512_CTX), ""); auto const ctx = reinterpret_cast(ctx_); SHA512_Init(ctx); } @@ -64,9 +57,7 @@ openssl_sha512_hasher::operator result_type() noexcept openssl_sha256_hasher::openssl_sha256_hasher() { - static_assert( - sizeof(decltype(openssl_sha256_hasher::ctx_)) == sizeof(SHA256_CTX), - ""); + static_assert(sizeof(decltype(openssl_sha256_hasher::ctx_)) == sizeof(SHA256_CTX), ""); auto const ctx = reinterpret_cast(ctx_); SHA256_Init(ctx); } diff --git a/src/libxrpl/protocol/tokens.cpp b/src/libxrpl/protocol/tokens.cpp index 420eb56df0..1b73b06380 100644 --- a/src/libxrpl/protocol/tokens.cpp +++ b/src/libxrpl/protocol/tokens.cpp @@ -121,8 +121,7 @@ coefficients sizes greatly speeds up the multi-precision computations. namespace xrpl { -static constexpr char const* alphabetForward = - "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"; +static constexpr char const* alphabetForward = "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"; static constexpr std::array const alphabetReverse = []() { std::array map{}; @@ -142,11 +141,7 @@ digest(void const* data, std::size_t size) noexcept return static_cast(h); } -template < - class Hasher, - class T, - std::size_t N, - class = std::enable_if_t> +template > static typename Hasher::result_type digest(std::array const& v) { @@ -202,11 +197,7 @@ namespace b58_ref { namespace detail { std::string -encodeBase58( - void const* message, - std::size_t size, - void* temp, - std::size_t temp_size) +encodeBase58(void const* message, std::size_t size, void* temp, std::size_t temp_size) { auto pbegin = reinterpret_cast(message); auto const pend = pbegin + size; @@ -234,8 +225,7 @@ encodeBase58( iter[-1] = carry % 58; carry /= 58; } - XRPL_ASSERT( - carry == 0, "xrpl::b58_ref::detail::encodeBase58 : zero carry"); + XRPL_ASSERT(carry == 0, "xrpl::b58_ref::detail::encodeBase58 : zero carry"); pbegin++; } @@ -285,14 +275,12 @@ decodeBase58(std::string const& s) *iter = carry % 256; carry /= 256; } - XRPL_ASSERT( - carry == 0, "xrpl::b58_ref::detail::decodeBase58 : zero carry"); + XRPL_ASSERT(carry == 0, "xrpl::b58_ref::detail::decodeBase58 : zero carry"); ++psz; --remain; } // Skip leading zeroes in b256. - auto iter = std::find_if( - b256.begin(), b256.end(), [](unsigned char c) { return c != 0; }); + auto iter = std::find_if(b256.begin(), b256.end(), [](unsigned char c) { return c != 0; }); std::string result; result.reserve(zeroes + (b256.end() - iter)); result.assign(zeroes, 0x00); @@ -323,8 +311,7 @@ encodeBase58Token(TokenType type, void const* token, std::size_t size) std::memcpy(buf.data() + 1, token, size); checksum(buf.data() + 1 + size, buf.data(), 1 + size); - return detail::encodeBase58( - buf.data(), expanded, buf.data() + expanded, bufsize - expanded); + return detail::encodeBase58(buf.data(), expanded, buf.data() + expanded, bufsize - expanded); } std::string @@ -367,8 +354,7 @@ b256_to_b58_be(std::span input, std::span out) return Unexpected(TokenCodecErrc::inputTooLarge); }; - auto count_leading_zeros = - [](std::span const& col) -> std::size_t { + auto count_leading_zeros = [](std::span const& col) -> std::size_t { std::size_t count = 0; for (auto const& c : col) { @@ -387,8 +373,7 @@ b256_to_b58_be(std::span input, std::span out) // Allocate enough base 2^64 coeff for encoding 38 bytes // log(2^(38*8),2^64)) ~= 4.75. So 5 coeff are enough std::array base_2_64_coeff_buf{}; - std::span const base_2_64_coeff = - [&]() -> std::span { + std::span const base_2_64_coeff = [&]() -> std::span { // convert input from big endian to native u64, lowest coeff first std::size_t num_coeff = 0; for (int i = 0; i < base_2_64_coeff_buf.size(); ++i) @@ -400,10 +385,8 @@ b256_to_b58_be(std::span input, std::span out) auto const src_i_end = input.size() - i * 8; if (src_i_end >= 8) { - std::memcpy( - &base_2_64_coeff_buf[num_coeff], &input[src_i_end - 8], 8); - boost::endian::big_to_native_inplace( - base_2_64_coeff_buf[num_coeff]); + std::memcpy(&base_2_64_coeff_buf[num_coeff], &input[src_i_end - 8], 8); + boost::endian::big_to_native_inplace(base_2_64_coeff_buf[num_coeff]); } else { @@ -430,8 +413,7 @@ b256_to_b58_be(std::span input, std::span out) while (cur_2_64_end > 0) { base_58_10_coeff[num_58_10_coeffs] = - xrpl::b58_fast::detail::inplace_bigint_div_rem( - base_2_64_coeff.subspan(0, cur_2_64_end), B_58_10); + xrpl::b58_fast::detail::inplace_bigint_div_rem(base_2_64_coeff.subspan(0, cur_2_64_end), B_58_10); num_58_10_coeffs += 1; if (base_2_64_coeff[cur_2_64_end - 1] == 0) { @@ -441,8 +423,7 @@ b256_to_b58_be(std::span input, std::span out) // Translate the result into the alphabet // Put all the zeros at the beginning, then all the values from the output - std::fill( - out.begin(), out.begin() + input_zeros, ::xrpl::alphabetForward[0]); + std::fill(out.begin(), out.begin() + input_zeros, ::xrpl::alphabetForward[0]); // iterate through the base 58^10 coeff // convert to base 58 big endian then @@ -460,8 +441,7 @@ b256_to_b58_be(std::span input, std::span out) { return Unexpected(TokenCodecErrc::inputTooLarge); } - std::array const b58_be = - xrpl::b58_fast::detail::b58_10_to_b58_be(base_58_10_coeff[i]); + std::array const b58_be = xrpl::b58_fast::detail::b58_10_to_b58_be(base_58_10_coeff[i]); std::size_t to_skip = 0; std::span b58_be_s{b58_be.data(), b58_be.size()}; if (skip_zeros) @@ -519,13 +499,10 @@ b58_to_b256_be(std::string_view input, std::span out) // (33 bytes for nodepublic + 1 byte token + 4 bytes checksum) // log(2^(38*8),58^10)) ~= 5.18. So 6 coeff are enough std::array b_58_10_coeff{}; - auto [num_full_coeffs, partial_coeff_len] = - xrpl::b58_fast::detail::div_rem(input.size(), 10); + auto [num_full_coeffs, partial_coeff_len] = xrpl::b58_fast::detail::div_rem(input.size(), 10); auto const num_partial_coeffs = partial_coeff_len ? 1 : 0; auto const num_b_58_10_coeffs = num_full_coeffs + num_partial_coeffs; - XRPL_ASSERT( - num_b_58_10_coeffs <= b_58_10_coeff.size(), - "xrpl::b58_fast::detail::b58_to_b256_be : maximum coeff"); + XRPL_ASSERT(num_b_58_10_coeffs <= b_58_10_coeff.size(), "xrpl::b58_fast::detail::b58_to_b256_be : maximum coeff"); for (unsigned char c : input.substr(0, partial_coeff_len)) { auto cur_val = ::xrpl::alphabetReverse[c]; @@ -562,16 +539,14 @@ b58_to_b256_be(std::string_view input, std::span out) std::uint64_t const c = b_58_10_coeff[i]; { - auto code = xrpl::b58_fast::detail::inplace_bigint_mul( - std::span(&result[0], cur_result_size + 1), B_58_10); + auto code = xrpl::b58_fast::detail::inplace_bigint_mul(std::span(&result[0], cur_result_size + 1), B_58_10); if (code != TokenCodecErrc::success) { return Unexpected(code); } } { - auto code = xrpl::b58_fast::detail::inplace_bigint_add( - std::span(&result[0], cur_result_size + 1), c); + auto code = xrpl::b58_fast::detail::inplace_bigint_add(std::span(&result[0], cur_result_size + 1), c); if (code != TokenCodecErrc::success) { return Unexpected(code); @@ -623,10 +598,7 @@ b58_to_b256_be(std::string_view input, std::span out) } // namespace detail B58Result> -encodeBase58Token( - TokenType token_type, - std::span input, - std::span out) +encodeBase58Token(TokenType token_type, std::span input, std::span out) { constexpr std::size_t tmpBufSize = 128; std::array buf; @@ -654,14 +626,10 @@ encodeBase58Token( // The decoded base 256 value does not include the token type or checksum. // It is an error if the token type or checksum does not match. B58Result> -decodeBase58Token( - TokenType type, - std::string_view s, - std::span outBuf) +decodeBase58Token(TokenType type, std::string_view s, std::span outBuf) { std::array tmpBuf; - auto const decodeResult = - detail::b58_to_b256_be(s, std::span(tmpBuf.data(), tmpBuf.size())); + auto const decodeResult = detail::b58_to_b256_be(s, std::span(tmpBuf.data(), tmpBuf.size())); if (!decodeResult) return decodeResult; @@ -703,10 +671,8 @@ encodeBase58Token(TokenType type, void const* token, std::size_t size) // over-allocation, this function uses 128 (again, over-allocation assuming // 2 base 58 char per byte) sr.resize(128); - std::span outSp( - reinterpret_cast(sr.data()), sr.size()); - std::span inSp( - reinterpret_cast(token), size); + std::span outSp(reinterpret_cast(sr.data()), sr.size()); + std::span inSp(reinterpret_cast(token), size); auto r = b58_fast::encodeBase58Token(type, inSp, outSp); if (!r) return {}; @@ -721,8 +687,7 @@ decodeBase58Token(std::string const& s, TokenType type) // The largest object encoded as base58 is 33 bytes; 64 is plenty (and // there's no benefit making it smaller) sr.resize(64); - std::span outSp( - reinterpret_cast(sr.data()), sr.size()); + std::span outSp(reinterpret_cast(sr.data()), sr.size()); auto r = b58_fast::decodeBase58Token(type, s, outSp); if (!r) return {}; diff --git a/src/libxrpl/resource/Charge.cpp b/src/libxrpl/resource/Charge.cpp index 1d88526b65..eece5355f0 100644 --- a/src/libxrpl/resource/Charge.cpp +++ b/src/libxrpl/resource/Charge.cpp @@ -8,8 +8,7 @@ namespace xrpl { namespace Resource { -Charge::Charge(value_type cost, std::string const& label) - : m_cost(cost), m_label(label) +Charge::Charge(value_type cost, std::string const& label) : m_cost(cost), m_label(label) { } diff --git a/src/libxrpl/resource/Consumer.cpp b/src/libxrpl/resource/Consumer.cpp index c9d8ea6125..11c23b1044 100644 --- a/src/libxrpl/resource/Consumer.cpp +++ b/src/libxrpl/resource/Consumer.cpp @@ -13,8 +13,7 @@ namespace xrpl { namespace Resource { -Consumer::Consumer(Logic& logic, Entry& entry) - : m_logic(&logic), m_entry(&entry) +Consumer::Consumer(Logic& logic, Entry& entry) : m_logic(&logic), m_entry(&entry) { } @@ -22,8 +21,7 @@ Consumer::Consumer() : m_logic(nullptr), m_entry(nullptr) { } -Consumer::Consumer(Consumer const& other) - : m_logic(other.m_logic), m_entry(nullptr) +Consumer::Consumer(Consumer const& other) : m_logic(other.m_logic), m_entry(nullptr) { if (m_logic && other.m_entry) { @@ -104,8 +102,7 @@ Consumer::warn() bool Consumer::disconnect(beast::Journal const& j) { - XRPL_ASSERT( - m_entry, "xrpl::Resource::Consumer::disconnect : non-null entry"); + XRPL_ASSERT(m_entry, "xrpl::Resource::Consumer::disconnect : non-null entry"); bool const d = m_logic->disconnect(*m_entry); if (d) { diff --git a/src/libxrpl/resource/ResourceManager.cpp b/src/libxrpl/resource/ResourceManager.cpp index 15d31a558e..787ceff768 100644 --- a/src/libxrpl/resource/ResourceManager.cpp +++ b/src/libxrpl/resource/ResourceManager.cpp @@ -36,9 +36,7 @@ private: std::condition_variable cond_; public: - ManagerImp( - beast::insight::Collector::ptr const& collector, - beast::Journal journal) + ManagerImp(beast::insight::Collector::ptr const& collector, beast::Journal journal) : journal_(journal), logic_(collector, stopwatch(), journal) { thread_ = std::thread{&ManagerImp::run, this}; @@ -66,10 +64,7 @@ public: } Consumer - newInboundEndpoint( - beast::IP::Endpoint const& address, - bool const proxy, - std::string_view forwardedFor) override + newInboundEndpoint(beast::IP::Endpoint const& address, bool const proxy, std::string_view forwardedFor) override { if (!proxy) return newInboundEndpoint(address); @@ -78,14 +73,11 @@ public: auto const proxiedIp = boost::asio::ip::make_address(forwardedFor, ec); if (ec) { - journal_.warn() - << "forwarded for (" << forwardedFor << ") from proxy " - << address.to_string() - << " doesn't convert to IP endpoint: " << ec.message(); + journal_.warn() << "forwarded for (" << forwardedFor << ") from proxy " << address.to_string() + << " doesn't convert to IP endpoint: " << ec.message(); return newInboundEndpoint(address); } - return newInboundEndpoint( - beast::IPAddressConversion::from_asio(proxiedIp)); + return newInboundEndpoint(beast::IPAddressConversion::from_asio(proxiedIp)); } Consumer @@ -163,9 +155,7 @@ Manager::~Manager() = default; //------------------------------------------------------------------------------ std::unique_ptr -make_Manager( - beast::insight::Collector::ptr const& collector, - beast::Journal journal) +make_Manager(beast::insight::Collector::ptr const& collector, beast::Journal journal) { return std::make_unique(collector, journal); } diff --git a/src/libxrpl/server/JSONRPCUtil.cpp b/src/libxrpl/server/JSONRPCUtil.cpp index 845781374d..634bb07850 100644 --- a/src/libxrpl/server/JSONRPCUtil.cpp +++ b/src/libxrpl/server/JSONRPCUtil.cpp @@ -27,20 +27,12 @@ getHTTPHeaderTimestamp() #else gmtime_s(&now_gmt, &now); #endif - strftime( - buffer, - sizeof(buffer), - "Date: %a, %d %b %Y %H:%M:%S +0000\r\n", - &now_gmt); + strftime(buffer, sizeof(buffer), "Date: %a, %d %b %Y %H:%M:%S +0000\r\n", &now_gmt); return std::string(buffer); } void -HTTPReply( - int nStatus, - std::string const& content, - Json::Output const& output, - beast::Journal j) +HTTPReply(int nStatus, std::string const& content, Json::Output const& output, beast::Journal j) { JLOG(j.trace()) << "HTTP Reply " << nStatus << " " << content; diff --git a/src/libxrpl/server/Port.cpp b/src/libxrpl/server/Port.cpp index 03a503e940..389714a40f 100644 --- a/src/libxrpl/server/Port.cpp +++ b/src/libxrpl/server/Port.cpp @@ -26,8 +26,8 @@ namespace xrpl { bool Port::secure() const { - return protocol.count("peer") > 0 || protocol.count("https") > 0 || - protocol.count("wss") > 0 || protocol.count("wss2") > 0; + return protocol.count("peer") > 0 || protocol.count("https") > 0 || protocol.count("wss") > 0 || + protocol.count("wss2") > 0; } std::string @@ -111,8 +111,7 @@ populate( { if (is_unspecified(*addr)) { - nets4.push_back( - boost::asio::ip::make_network_v4("0.0.0.0/0")); + nets4.push_back(boost::asio::ip::make_network_v4("0.0.0.0/0")); nets6.push_back(boost::asio::ip::make_network_v6("::/0")); // No reason to allow more IPs--it would be redundant. break; @@ -164,8 +163,7 @@ populate( if (v4Net != v4Net.canonical()) { log << "The configured subnet " << v4Net.to_string() - << " is not the same as the network address, which is " - << v4Net.canonical().to_string(); + << " is not the same as the network address, which is " << v4Net.canonical().to_string(); Throw(); } nets4.push_back(v4Net); @@ -175,8 +173,7 @@ populate( if (v6Net != v6Net.canonical()) { log << "The configured subnet " << v6Net.to_string() - << " is not the same as the network address, which is " - << v6Net.canonical().to_string(); + << " is not the same as the network address, which is " << v6Net.canonical().to_string(); Throw(); } nets6.push_back(v6Net); @@ -184,8 +181,7 @@ populate( } catch (boost::system::system_error const& e) { - log << "Invalid value '" << ip << "' for key '" << field << "' in [" - << section.name() << "]: " << e.what(); + log << "Invalid value '" << ip << "' for key '" << field << "' in [" << section.name() << "]: " << e.what(); Throw(); } } @@ -205,8 +201,7 @@ parse_Port(ParsedPort& port, Section const& section, std::ostream& log) } catch (std::exception const&) { - log << "Invalid value '" << *optResult << "' for key 'ip' in [" - << section.name() << "]"; + log << "Invalid value '" << *optResult << "' for key 'ip' in [" << section.name() << "]"; Rethrow(); } } @@ -237,8 +232,7 @@ parse_Port(ParsedPort& port, Section const& section, std::ostream& log) auto const optResult = section.get("protocol"); if (optResult) { - for (auto const& s : beast::rfc2616::split_commas( - optResult->begin(), optResult->end())) + for (auto const& s : beast::rfc2616::split_commas(optResult->begin(), optResult->end())) port.protocol.insert(s); } } @@ -250,8 +244,7 @@ parse_Port(ParsedPort& port, Section const& section, std::ostream& log) { try { - port.limit = - safe_cast(beast::lexicalCastThrow(lim)); + port.limit = safe_cast(beast::lexicalCastThrow(lim)); } catch (std::exception const&) { @@ -268,8 +261,7 @@ parse_Port(ParsedPort& port, Section const& section, std::ostream& log) { try { - port.ws_queue_limit = - beast::lexicalCastThrow(*optResult); + port.ws_queue_limit = beast::lexicalCastThrow(*optResult); // Queue must be greater than 0 if (port.ws_queue_limit == 0) @@ -290,12 +282,7 @@ parse_Port(ParsedPort& port, Section const& section, std::ostream& log) } populate(section, "admin", log, port.admin_nets_v4, port.admin_nets_v6); - populate( - section, - "secure_gateway", - log, - port.secure_gateway_nets_v4, - port.secure_gateway_nets_v6); + populate(section, "secure_gateway", log, port.secure_gateway_nets_v4, port.secure_gateway_nets_v6); set(port.user, "user", section); set(port.password, "password", section); @@ -306,16 +293,11 @@ parse_Port(ParsedPort& port, Section const& section, std::ostream& log) set(port.ssl_chain, "ssl_chain", section); set(port.ssl_ciphers, "ssl_ciphers", section); - port.pmd_options.server_enable = - section.value_or("permessage_deflate", true); - port.pmd_options.client_max_window_bits = - section.value_or("client_max_window_bits", 15); - port.pmd_options.server_max_window_bits = - section.value_or("server_max_window_bits", 15); - port.pmd_options.client_no_context_takeover = - section.value_or("client_no_context_takeover", false); - port.pmd_options.server_no_context_takeover = - section.value_or("server_no_context_takeover", false); + port.pmd_options.server_enable = section.value_or("permessage_deflate", true); + port.pmd_options.client_max_window_bits = section.value_or("client_max_window_bits", 15); + port.pmd_options.server_max_window_bits = section.value_or("server_max_window_bits", 15); + port.pmd_options.client_no_context_takeover = section.value_or("client_no_context_takeover", false); + port.pmd_options.server_no_context_takeover = section.value_or("server_no_context_takeover", false); port.pmd_options.compLevel = section.value_or("compress_level", 8); port.pmd_options.memLevel = section.value_or("memory_level", 4); } diff --git a/src/libxrpl/shamap/SHAMap.cpp b/src/libxrpl/shamap/SHAMap.cpp index 2a156dc2d4..e84a620b77 100644 --- a/src/libxrpl/shamap/SHAMap.cpp +++ b/src/libxrpl/shamap/SHAMap.cpp @@ -10,30 +10,23 @@ namespace xrpl { [[nodiscard]] intr_ptr::SharedPtr -makeTypedLeaf( - SHAMapNodeType type, - boost::intrusive_ptr item, - std::uint32_t owner) +makeTypedLeaf(SHAMapNodeType type, boost::intrusive_ptr item, std::uint32_t owner) { if (type == SHAMapNodeType::tnTRANSACTION_NM) return intr_ptr::make_shared(std::move(item), owner); if (type == SHAMapNodeType::tnTRANSACTION_MD) - return intr_ptr::make_shared( - std::move(item), owner); + return intr_ptr::make_shared(std::move(item), owner); if (type == SHAMapNodeType::tnACCOUNT_STATE) - return intr_ptr::make_shared( - std::move(item), owner); + return intr_ptr::make_shared(std::move(item), owner); LogicError( "Attempt to create leaf node of unknown type " + - std::to_string( - static_cast>(type))); + std::to_string(static_cast>(type))); } -SHAMap::SHAMap(SHAMapType t, Family& f) - : f_(f), journal_(f.journal()), state_(SHAMapState::Modifying), type_(t) +SHAMap::SHAMap(SHAMapType t, Family& f) : f_(f), journal_(f.journal()), state_(SHAMapState::Modifying), type_(t) { root_ = intr_ptr::make_shared(cowid_); } @@ -59,8 +52,7 @@ SHAMap::SHAMap(SHAMap const& other, bool isMutable) , backed_(other.backed_) { // If either map may change, they cannot share nodes - if ((state_ != SHAMapState::Immutable) || - (other.state_ != SHAMapState::Immutable)) + if ((state_ != SHAMapState::Immutable) || (other.state_ != SHAMapState::Immutable)) { unshare(); } @@ -73,10 +65,7 @@ SHAMap::snapShot(bool isMutable) const } void -SHAMap::dirtyUp( - SharedPtrNodeStack& stack, - uint256 const& target, - intr_ptr::SharedPtr child) +SHAMap::dirtyUp(SharedPtrNodeStack& stack, uint256 const& target, intr_ptr::SharedPtr child) { // walk the tree up from through the inner nodes to the root_ // update hashes and links @@ -84,16 +73,12 @@ SHAMap::dirtyUp( // child can be an inner node or a leaf XRPL_ASSERT( - (state_ != SHAMapState::Synching) && (state_ != SHAMapState::Immutable), - "xrpl::SHAMap::dirtyUp : valid state"); - XRPL_ASSERT( - child && (child->cowid() == cowid_), - "xrpl::SHAMap::dirtyUp : valid child input"); + (state_ != SHAMapState::Synching) && (state_ != SHAMapState::Immutable), "xrpl::SHAMap::dirtyUp : valid state"); + XRPL_ASSERT(child && (child->cowid() == cowid_), "xrpl::SHAMap::dirtyUp : valid child input"); while (!stack.empty()) { - auto node = - intr_ptr::dynamic_pointer_cast(stack.top().first); + auto node = intr_ptr::dynamic_pointer_cast(stack.top().first); SHAMapNodeID nodeID = stack.top().second; stack.pop(); XRPL_ASSERT(node, "xrpl::SHAMap::dirtyUp : non-null node"); @@ -111,9 +96,7 @@ SHAMap::dirtyUp( SHAMapLeafNode* SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const { - XRPL_ASSERT( - stack == nullptr || stack->empty(), - "xrpl::SHAMap::walkTowardsKey : empty stack input"); + XRPL_ASSERT(stack == nullptr || stack->empty(), "xrpl::SHAMap::walkTowardsKey : empty stack input"); auto inNode = root_; SHAMapNodeID nodeID; @@ -122,8 +105,7 @@ SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const if (stack != nullptr) stack->push({inNode, nodeID}); - auto const inner = - intr_ptr::static_pointer_cast(inNode); + auto const inner = intr_ptr::static_pointer_cast(inNode); auto const branch = selectBranch(nodeID, id); if (inner->isEmptyBranch(branch)) return nullptr; @@ -155,9 +137,7 @@ SHAMap::fetchNodeFromDB(SHAMapHash const& hash) const } intr_ptr::SharedPtr -SHAMap::finishFetch( - SHAMapHash const& hash, - std::shared_ptr const& object) const +SHAMap::finishFetch(SHAMapHash const& hash, std::shared_ptr const& object) const { XRPL_ASSERT(backed_, "xrpl::SHAMap::finishFetch : is backed"); @@ -173,8 +153,7 @@ SHAMap::finishFetch( return {}; } - auto node = - SHAMapTreeNode::makeFromPrefix(makeSlice(object->getData()), hash); + auto node = SHAMapTreeNode::makeFromPrefix(makeSlice(object->getData()), hash); if (node) canonicalize(hash, node); return node; @@ -185,8 +164,7 @@ SHAMap::finishFetch( } catch (...) { - JLOG(journal_.warn()) - << "finishFetch exception: unknown exception: " << hash; + JLOG(journal_.warn()) << "finishFetch exception: unknown exception: " << hash; } return {}; @@ -200,16 +178,10 @@ SHAMap::checkFilter(SHAMapHash const& hash, SHAMapSyncFilter* filter) const { try { - auto node = - SHAMapTreeNode::makeFromPrefix(makeSlice(*nodeData), hash); + auto node = SHAMapTreeNode::makeFromPrefix(makeSlice(*nodeData), hash); if (node) { - filter->gotNode( - true, - hash, - ledgerSeq_, - std::move(*nodeData), - node->getType()); + filter->gotNode(true, hash, ledgerSeq_, std::move(*nodeData), node->getType()); if (backed_) canonicalize(hash, node); } @@ -217,8 +189,7 @@ SHAMap::checkFilter(SHAMapHash const& hash, SHAMapSyncFilter* filter) const } catch (std::exception const& x) { - JLOG(f_.journal().warn()) - << "Invalid node/data, hash=" << hash << ": " << x.what(); + JLOG(f_.journal().warn()) << "Invalid node/data, hash=" << hash << ": " << x.what(); } } return {}; @@ -301,8 +272,7 @@ SHAMap::descend(SHAMapInnerNode* parent, int branch) const if (ret || !backed_) return ret; - intr_ptr::SharedPtr node = - fetchNodeNT(parent->getChildHash(branch)); + intr_ptr::SharedPtr node = fetchNodeNT(parent->getChildHash(branch)); if (!node) return nullptr; @@ -337,28 +307,18 @@ SHAMap::descendNoStore(SHAMapInnerNode& parent, int branch) const } std::pair -SHAMap::descend( - SHAMapInnerNode* parent, - SHAMapNodeID const& parentID, - int branch, - SHAMapSyncFilter* filter) const +SHAMap::descend(SHAMapInnerNode* parent, SHAMapNodeID const& parentID, int branch, SHAMapSyncFilter* filter) const { - XRPL_ASSERT( - parent->isInner(), "xrpl::SHAMap::descend : valid parent input"); - XRPL_ASSERT( - (branch >= 0) && (branch < branchFactor), - "xrpl::SHAMap::descend : valid branch input"); - XRPL_ASSERT( - !parent->isEmptyBranch(branch), - "xrpl::SHAMap::descend : parent branch is non-empty"); + XRPL_ASSERT(parent->isInner(), "xrpl::SHAMap::descend : valid parent input"); + XRPL_ASSERT((branch >= 0) && (branch < branchFactor), "xrpl::SHAMap::descend : valid branch input"); + XRPL_ASSERT(!parent->isEmptyBranch(branch), "xrpl::SHAMap::descend : parent branch is non-empty"); SHAMapTreeNode* child = parent->getChildPointer(branch); if (!child) { auto const& childHash = parent->getChildHash(branch); - intr_ptr::SharedPtr childNode = - fetchNodeNT(childHash, filter); + intr_ptr::SharedPtr childNode = fetchNodeNT(childHash, filter); if (childNode) { @@ -397,8 +357,7 @@ SHAMap::descendAsync( f_.db().asyncFetch( hash.as_uint256(), ledgerSeq_, - [this, hash, cb{std::move(callback)}]( - std::shared_ptr const& object) { + [this, hash, cb{std::move(callback)}](std::shared_ptr const& object) { auto node = finishFetch(hash, object); cb(node, hash); }); @@ -418,15 +377,11 @@ intr_ptr::SharedPtr SHAMap::unshareNode(intr_ptr::SharedPtr node, SHAMapNodeID const& nodeID) { // make sure the node is suitable for the intended operation (copy on write) - XRPL_ASSERT( - node->cowid() <= cowid_, - "xrpl::SHAMap::unshareNode : node valid for cowid"); + XRPL_ASSERT(node->cowid() <= cowid_, "xrpl::SHAMap::unshareNode : node valid for cowid"); if (node->cowid() != cowid_) { // have a CoW - XRPL_ASSERT( - state_ != SHAMapState::Immutable, - "xrpl::SHAMap::unshareNode : not immutable"); + XRPL_ASSERT(state_ != SHAMapState::Immutable, "xrpl::SHAMap::unshareNode : not immutable"); node = intr_ptr::static_pointer_cast(node->clone(cowid_)); if (nodeID.isRoot()) root_ = node; @@ -439,8 +394,7 @@ SHAMap::belowHelper( intr_ptr::SharedPtr node, SharedPtrNodeStack& stack, int branch, - std::tuple, std::function> const& - loopParams) const + std::tuple, std::function> const& loopParams) const { auto& [init, cmp, incr] = loopParams; if (node->isLeaf()) @@ -459,8 +413,7 @@ SHAMap::belowHelper( if (!inner->isEmptyBranch(i)) { node.adopt(descendThrow(inner.get(), i)); - XRPL_ASSERT( - !stack.empty(), "xrpl::SHAMap::belowHelper : non-empty stack"); + XRPL_ASSERT(!stack.empty(), "xrpl::SHAMap::belowHelper : non-empty stack"); if (node->isLeaf()) { auto n = intr_ptr::static_pointer_cast(node); @@ -477,10 +430,7 @@ SHAMap::belowHelper( return nullptr; } SHAMapLeafNode* -SHAMap::lastBelow( - intr_ptr::SharedPtr node, - SharedPtrNodeStack& stack, - int branch) const +SHAMap::lastBelow(intr_ptr::SharedPtr node, SharedPtrNodeStack& stack, int branch) const { auto init = branchFactor - 1; auto cmp = [](int i) { return i >= 0; }; @@ -489,10 +439,7 @@ SHAMap::lastBelow( return belowHelper(node, stack, branch, {init, cmp, incr}); } SHAMapLeafNode* -SHAMap::firstBelow( - intr_ptr::SharedPtr node, - SharedPtrNodeStack& stack, - int branch) const +SHAMap::firstBelow(intr_ptr::SharedPtr node, SharedPtrNodeStack& stack, int branch) const { auto init = 0; auto cmp = [](int i) { return i <= branchFactor; }; @@ -536,17 +483,14 @@ SHAMap::onlyBelow(SHAMapTreeNode* node) const // An inner node must have at least one leaf // below it, unless it's the root_ auto const leaf = static_cast(node); - XRPL_ASSERT( - leaf->peekItem() || (leaf == root_.get()), - "xrpl::SHAMap::onlyBelow : valid inner node"); + XRPL_ASSERT(leaf->peekItem() || (leaf == root_.get()), "xrpl::SHAMap::onlyBelow : valid inner node"); return leaf->peekItem(); } SHAMapLeafNode const* SHAMap::peekFirstItem(SharedPtrNodeStack& stack) const { - XRPL_ASSERT( - stack.empty(), "xrpl::SHAMap::peekFirstItem : empty stack input"); + XRPL_ASSERT(stack.empty(), "xrpl::SHAMap::peekFirstItem : empty stack input"); SHAMapLeafNode* node = firstBelow(root_, stack); if (!node) { @@ -560,18 +504,13 @@ SHAMap::peekFirstItem(SharedPtrNodeStack& stack) const SHAMapLeafNode const* SHAMap::peekNextItem(uint256 const& id, SharedPtrNodeStack& stack) const { - XRPL_ASSERT( - !stack.empty(), "xrpl::SHAMap::peekNextItem : non-empty stack input"); - XRPL_ASSERT( - stack.top().first->isLeaf(), - "xrpl::SHAMap::peekNextItem : stack starts with leaf"); + XRPL_ASSERT(!stack.empty(), "xrpl::SHAMap::peekNextItem : non-empty stack input"); + XRPL_ASSERT(stack.top().first->isLeaf(), "xrpl::SHAMap::peekNextItem : stack starts with leaf"); stack.pop(); while (!stack.empty()) { auto [node, nodeID] = stack.top(); - XRPL_ASSERT( - !node->isLeaf(), - "xrpl::SHAMap::peekNextItem : another node is not leaf"); + XRPL_ASSERT(!node->isLeaf(), "xrpl::SHAMap::peekNextItem : another node is not leaf"); auto inner = intr_ptr::static_pointer_cast(node); for (auto i = selectBranch(nodeID, id) + 1; i < branchFactor; ++i) { @@ -581,9 +520,7 @@ SHAMap::peekNextItem(uint256 const& id, SharedPtrNodeStack& stack) const auto leaf = firstBelow(node, stack, i); if (!leaf) Throw(type_, id); - XRPL_ASSERT( - leaf->isLeaf(), - "xrpl::SHAMap::peekNextItem : leaf is valid"); + XRPL_ASSERT(leaf->isLeaf(), "xrpl::SHAMap::peekNextItem : leaf is valid"); return leaf; } } @@ -628,15 +565,12 @@ SHAMap::upper_bound(uint256 const& id) const { auto leaf = static_cast(node.get()); if (leaf->peekItem()->key() > id) - return const_iterator( - this, leaf->peekItem().get(), std::move(stack)); + return const_iterator(this, leaf->peekItem().get(), std::move(stack)); } else { auto inner = intr_ptr::static_pointer_cast(node); - for (auto branch = selectBranch(nodeID, id) + 1; - branch < branchFactor; - ++branch) + for (auto branch = selectBranch(nodeID, id) + 1; branch < branchFactor; ++branch) { if (!inner->isEmptyBranch(branch)) { @@ -644,8 +578,7 @@ SHAMap::upper_bound(uint256 const& id) const auto leaf = firstBelow(node, stack, branch); if (!leaf) Throw(type_, id); - return const_iterator( - this, leaf->peekItem().get(), std::move(stack)); + return const_iterator(this, leaf->peekItem().get(), std::move(stack)); } } } @@ -665,14 +598,12 @@ SHAMap::lower_bound(uint256 const& id) const { auto leaf = static_cast(node.get()); if (leaf->peekItem()->key() < id) - return const_iterator( - this, leaf->peekItem().get(), std::move(stack)); + return const_iterator(this, leaf->peekItem().get(), std::move(stack)); } else { auto inner = intr_ptr::static_pointer_cast(node); - for (int branch = selectBranch(nodeID, id) - 1; branch >= 0; - --branch) + for (int branch = selectBranch(nodeID, id) - 1; branch >= 0; --branch) { if (!inner->isEmptyBranch(branch)) { @@ -680,8 +611,7 @@ SHAMap::lower_bound(uint256 const& id) const auto leaf = lastBelow(node, stack, branch); if (!leaf) Throw(type_, id); - return const_iterator( - this, leaf->peekItem().get(), std::move(stack)); + return const_iterator(this, leaf->peekItem().get(), std::move(stack)); } } } @@ -701,9 +631,7 @@ bool SHAMap::delItem(uint256 const& id) { // delete the item with this ID - XRPL_ASSERT( - state_ != SHAMapState::Immutable, - "xrpl::SHAMap::delItem : not immutable"); + XRPL_ASSERT(state_ != SHAMapState::Immutable, "xrpl::SHAMap::delItem : not immutable"); SharedPtrNodeStack stack; walkTowardsKey(id, &stack); @@ -711,8 +639,7 @@ SHAMap::delItem(uint256 const& id) if (stack.empty()) Throw(type_, id); - auto leaf = - intr_ptr::dynamic_pointer_cast(stack.top().first); + auto leaf = intr_ptr::dynamic_pointer_cast(stack.top().first); stack.pop(); if (!leaf || (leaf->peekItem()->key() != id)) @@ -726,8 +653,7 @@ SHAMap::delItem(uint256 const& id) while (!stack.empty()) { - auto node = - intr_ptr::static_pointer_cast(stack.top().first); + auto node = intr_ptr::static_pointer_cast(stack.top().first); SHAMapNodeID nodeID = stack.top().second; stack.pop(); @@ -755,8 +681,7 @@ SHAMap::delItem(uint256 const& id) { if (!node->isEmptyBranch(i)) { - node->setChild( - i, intr_ptr::SharedPtr{}); + node->setChild(i, intr_ptr::SharedPtr{}); break; } } @@ -780,16 +705,10 @@ SHAMap::delItem(uint256 const& id) } bool -SHAMap::addGiveItem( - SHAMapNodeType type, - boost::intrusive_ptr item) +SHAMap::addGiveItem(SHAMapNodeType type, boost::intrusive_ptr item) { - XRPL_ASSERT( - state_ != SHAMapState::Immutable, - "xrpl::SHAMap::addGiveItem : not immutable"); - XRPL_ASSERT( - type != SHAMapNodeType::tnINNER, - "xrpl::SHAMap::addGiveItem : valid type input"); + XRPL_ASSERT(state_ != SHAMapState::Immutable, "xrpl::SHAMap::addGiveItem : not immutable"); + XRPL_ASSERT(type != SHAMapNodeType::tnINNER, "xrpl::SHAMap::addGiveItem : valid type input"); // add the specified item, does not update uint256 tag = item->key(); @@ -815,9 +734,7 @@ SHAMap::addGiveItem( // easy case, we end on an inner node auto inner = intr_ptr::static_pointer_cast(node); int branch = selectBranch(nodeID, tag); - XRPL_ASSERT( - inner->isEmptyBranch(branch), - "xrpl::SHAMap::addGiveItem : inner branch is empty"); + XRPL_ASSERT(inner->isEmptyBranch(branch), "xrpl::SHAMap::addGiveItem : inner branch is empty"); inner->setChild(branch, makeTypedLeaf(type, std::move(item), cowid_)); } else @@ -826,16 +743,13 @@ SHAMap::addGiveItem( // items auto leaf = intr_ptr::static_pointer_cast(node); auto otherItem = leaf->peekItem(); - XRPL_ASSERT( - otherItem && (tag != otherItem->key()), - "xrpl::SHAMap::addGiveItem : non-null item"); + XRPL_ASSERT(otherItem && (tag != otherItem->key()), "xrpl::SHAMap::addGiveItem : non-null item"); node = intr_ptr::make_shared(node->cowid()); unsigned int b1, b2; - while ((b1 = selectBranch(nodeID, tag)) == - (b2 = selectBranch(nodeID, otherItem->key()))) + while ((b1 = selectBranch(nodeID, tag)) == (b2 = selectBranch(nodeID, otherItem->key()))) { stack.push({node, nodeID}); @@ -846,8 +760,7 @@ SHAMap::addGiveItem( } // we can add the two leaf nodes here - XRPL_ASSERT( - node->isInner(), "xrpl::SHAMap::addGiveItem : node is inner"); + XRPL_ASSERT(node->isInner(), "xrpl::SHAMap::addGiveItem : node is inner"); auto inner = static_cast(node.get()); inner->setChild(b1, makeTypedLeaf(type, std::move(item), cowid_)); @@ -859,9 +772,7 @@ SHAMap::addGiveItem( } bool -SHAMap::addItem( - SHAMapNodeType type, - boost::intrusive_ptr item) +SHAMap::addItem(SHAMapNodeType type, boost::intrusive_ptr item) { return addGiveItem(type, std::move(item)); } @@ -879,16 +790,12 @@ SHAMap::getHash() const } bool -SHAMap::updateGiveItem( - SHAMapNodeType type, - boost::intrusive_ptr item) +SHAMap::updateGiveItem(SHAMapNodeType type, boost::intrusive_ptr item) { // can't change the tag but can change the hash uint256 tag = item->key(); - XRPL_ASSERT( - state_ != SHAMapState::Immutable, - "xrpl::SHAMap::updateGiveItem : not immutable"); + XRPL_ASSERT(state_ != SHAMapState::Immutable, "xrpl::SHAMap::updateGiveItem : not immutable"); SharedPtrNodeStack stack; walkTowardsKey(tag, &stack); @@ -896,8 +803,7 @@ SHAMap::updateGiveItem( if (stack.empty()) Throw(type_, tag); - auto node = - intr_ptr::dynamic_pointer_cast(stack.top().first); + auto node = intr_ptr::dynamic_pointer_cast(stack.top().first); auto nodeID = stack.top().second; stack.pop(); @@ -950,9 +856,7 @@ SHAMap::fetchRoot(SHAMapHash const& hash, SHAMapSyncFilter* filter) if (newRoot) { root_ = newRoot; - XRPL_ASSERT( - root_->getHash() == hash, - "xrpl::SHAMap::fetchRoot : root hash do match"); + XRPL_ASSERT(root_->getHash() == hash, "xrpl::SHAMap::fetchRoot : root hash do match"); return true; } @@ -972,19 +876,16 @@ SHAMap::fetchRoot(SHAMapHash const& hash, SHAMapSyncFilter* filter) first call SHAMapTreeNode::unshare(). */ intr_ptr::SharedPtr -SHAMap::writeNode(NodeObjectType t, intr_ptr::SharedPtr node) - const +SHAMap::writeNode(NodeObjectType t, intr_ptr::SharedPtr node) const { - XRPL_ASSERT( - node->cowid() == 0, "xrpl::SHAMap::writeNode : valid input node"); + XRPL_ASSERT(node->cowid() == 0, "xrpl::SHAMap::writeNode : valid input node"); XRPL_ASSERT(backed_, "xrpl::SHAMap::writeNode : is backed"); canonicalize(node->getHash(), node); Serializer s; node->serializeWithPrefix(s); - f_.db().store( - t, std::move(s.modData()), node->getHash().as_uint256(), ledgerSeq_); + f_.db().store(t, std::move(s.modData()), node->getHash().as_uint256(), ledgerSeq_); return node; } @@ -1091,8 +992,7 @@ SHAMap::walkSubTree(bool doWrite, NodeObjectType t) // The semantics of this changes when we move to c++-20 // Right now no move will occur; With c++-20 child will // be moved from. - node = intr_ptr::static_pointer_cast( - std::move(child)); + node = intr_ptr::static_pointer_cast(std::move(child)); pos = 0; } else @@ -1123,8 +1023,7 @@ SHAMap::walkSubTree(bool doWrite, NodeObjectType t) node->unshare(); if (doWrite) - node = intr_ptr::static_pointer_cast( - writeNode(t, std::move(node))); + node = intr_ptr::static_pointer_cast(writeNode(t, std::move(node))); ++flushed; @@ -1136,9 +1035,7 @@ SHAMap::walkSubTree(bool doWrite, NodeObjectType t) stack.pop(); // Hook this inner node to its parent - XRPL_ASSERT( - parent->cowid() == cowid_, - "xrpl::SHAMap::walkSubTree : parent cowid do match"); + XRPL_ASSERT(parent->cowid() == cowid_, "xrpl::SHAMap::walkSubTree : parent cowid do match"); parent->shareChild(pos, node); // Continue with parent's next child, if any @@ -1183,8 +1080,7 @@ SHAMap::dump(bool hash) const if (child) { XRPL_ASSERT( - child->getHash() == inner->getChildHash(i), - "xrpl::SHAMap::dump : child hash do match"); + child->getHash() == inner->getChildHash(i), "xrpl::SHAMap::dump : child hash do match"); stack.push({child, nodeID.getChildNodeID(i)}); } } @@ -1201,23 +1097,16 @@ intr_ptr::SharedPtr SHAMap::cacheLookup(SHAMapHash const& hash) const { auto ret = f_.getTreeNodeCache()->fetch(hash.as_uint256()); - XRPL_ASSERT( - !ret || !ret->cowid(), - "xrpl::SHAMap::cacheLookup : not found or zero cowid"); + XRPL_ASSERT(!ret || !ret->cowid(), "xrpl::SHAMap::cacheLookup : not found or zero cowid"); return ret; } void -SHAMap::canonicalize( - SHAMapHash const& hash, - intr_ptr::SharedPtr& node) const +SHAMap::canonicalize(SHAMapHash const& hash, intr_ptr::SharedPtr& node) const { XRPL_ASSERT(backed_, "xrpl::SHAMap::canonicalize : is backed"); - XRPL_ASSERT( - node->cowid() == 0, "xrpl::SHAMap::canonicalize : valid node input"); - XRPL_ASSERT( - node->getHash() == hash, - "xrpl::SHAMap::canonicalize : node hash do match"); + XRPL_ASSERT(node->cowid() == 0, "xrpl::SHAMap::canonicalize : valid node input"); + XRPL_ASSERT(node->getHash() == hash, "xrpl::SHAMap::canonicalize : node hash do match"); f_.getTreeNodeCache()->canonicalize_replace_client(hash.as_uint256(), node); } @@ -1228,11 +1117,9 @@ SHAMap::invariants() const (void)getHash(); // update node hashes auto node = root_.get(); XRPL_ASSERT(node, "xrpl::SHAMap::invariants : non-null root node"); - XRPL_ASSERT( - !node->isLeaf(), "xrpl::SHAMap::invariants : root node is not leaf"); + XRPL_ASSERT(!node->isLeaf(), "xrpl::SHAMap::invariants : root node is not leaf"); SharedPtrNodeStack stack; - for (auto leaf = peekFirstItem(stack); leaf != nullptr; - leaf = peekNextItem(leaf->peekItem()->key(), stack)) + for (auto leaf = peekFirstItem(stack); leaf != nullptr; leaf = peekNextItem(leaf->peekItem()->key(), stack)) ; node->invariants(true); } diff --git a/src/libxrpl/shamap/SHAMapDelta.cpp b/src/libxrpl/shamap/SHAMapDelta.cpp index d7234bcbab..d8aabcc67c 100644 --- a/src/libxrpl/shamap/SHAMapDelta.cpp +++ b/src/libxrpl/shamap/SHAMapDelta.cpp @@ -53,11 +53,9 @@ SHAMap::walkBranch( { // unmatched if (isFirstMap) - differences.insert( - std::make_pair(item->key(), DeltaRef(item, nullptr))); + differences.insert(std::make_pair(item->key(), DeltaRef(item, nullptr))); else - differences.insert( - std::make_pair(item->key(), DeltaRef(nullptr, item))); + differences.insert(std::make_pair(item->key(), DeltaRef(nullptr, item))); if (--maxCount <= 0) return false; @@ -66,11 +64,9 @@ SHAMap::walkBranch( { // non-matching items with same tag if (isFirstMap) - differences.insert(std::make_pair( - item->key(), DeltaRef(item, otherMapItem))); + differences.insert(std::make_pair(item->key(), DeltaRef(item, otherMapItem))); else - differences.insert(std::make_pair( - item->key(), DeltaRef(otherMapItem, item))); + differences.insert(std::make_pair(item->key(), DeltaRef(otherMapItem, item))); if (--maxCount <= 0) return false; @@ -89,11 +85,9 @@ SHAMap::walkBranch( { // otherMapItem was unmatched, must add if (isFirstMap) // this is first map, so other item is from second - differences.insert(std::make_pair( - otherMapItem->key(), DeltaRef(nullptr, otherMapItem))); + differences.insert(std::make_pair(otherMapItem->key(), DeltaRef(nullptr, otherMapItem))); else - differences.insert(std::make_pair( - otherMapItem->key(), DeltaRef(otherMapItem, nullptr))); + differences.insert(std::make_pair(otherMapItem->key(), DeltaRef(otherMapItem, nullptr))); if (--maxCount <= 0) return false; @@ -110,16 +104,13 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const // many differences throws on corrupt tables or missing nodes CAUTION: // otherMap is not locked and must be immutable - XRPL_ASSERT( - isValid() && otherMap.isValid(), - "xrpl::SHAMap::compare : valid state and valid input"); + XRPL_ASSERT(isValid() && otherMap.isValid(), "xrpl::SHAMap::compare : valid state and valid input"); if (getHash() == otherMap.getHash()) return true; using StackEntry = std::pair; - std::stack> - nodeStack; // track nodes we've pushed + std::stack> nodeStack; // track nodes we've pushed nodeStack.push({root_.get(), otherMap.root_.get()}); while (!nodeStack.empty()) @@ -144,24 +135,19 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const { if (ours->peekItem()->slice() != other->peekItem()->slice()) { - differences.insert(std::make_pair( - ours->peekItem()->key(), - DeltaRef(ours->peekItem(), other->peekItem()))); + differences.insert( + std::make_pair(ours->peekItem()->key(), DeltaRef(ours->peekItem(), other->peekItem()))); if (--maxCount <= 0) return false; } } else { - differences.insert(std::make_pair( - ours->peekItem()->key(), - DeltaRef(ours->peekItem(), nullptr))); + differences.insert(std::make_pair(ours->peekItem()->key(), DeltaRef(ours->peekItem(), nullptr))); if (--maxCount <= 0) return false; - differences.insert(std::make_pair( - other->peekItem()->key(), - DeltaRef(nullptr, other->peekItem()))); + differences.insert(std::make_pair(other->peekItem()->key(), DeltaRef(nullptr, other->peekItem()))); if (--maxCount <= 0) return false; } @@ -170,16 +156,14 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const { auto ours = static_cast(ourNode); auto other = static_cast(otherNode); - if (!walkBranch( - ours, other->peekItem(), true, differences, maxCount)) + if (!walkBranch(ours, other->peekItem(), true, differences, maxCount)) return false; } else if (ourNode->isLeaf() && otherNode->isInner()) { auto ours = static_cast(ourNode); auto other = static_cast(otherNode); - if (!otherMap.walkBranch( - other, ours->peekItem(), false, differences, maxCount)) + if (!otherMap.walkBranch(other, ours->peekItem(), false, differences, maxCount)) return false; } else if (ourNode->isInner() && otherNode->isInner()) @@ -193,22 +177,18 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const { // We have a branch, the other tree does not SHAMapTreeNode* iNode = descendThrow(ours, i); - if (!walkBranch( - iNode, nullptr, true, differences, maxCount)) + if (!walkBranch(iNode, nullptr, true, differences, maxCount)) return false; } else if (ours->isEmptyBranch(i)) { // The other tree has a branch, we do not SHAMapTreeNode* iNode = otherMap.descendThrow(other, i); - if (!otherMap.walkBranch( - iNode, nullptr, false, differences, maxCount)) + if (!otherMap.walkBranch(iNode, nullptr, false, differences, maxCount)) return false; } else // The two trees have different non-empty branches - nodeStack.push( - {descendThrow(ours, i), - otherMap.descendThrow(other, i)}); + nodeStack.push({descendThrow(ours, i), otherMap.descendThrow(other, i)}); } } else @@ -223,8 +203,7 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const } void -SHAMap::walkMap(std::vector& missingNodes, int maxMissing) - const +SHAMap::walkMap(std::vector& missingNodes, int maxMissing) const { if (!root_->isInner()) // root_ is only node, and we have it return; @@ -243,15 +222,12 @@ SHAMap::walkMap(std::vector& missingNodes, int maxMissing) { if (!node->isEmptyBranch(i)) { - intr_ptr::SharedPtr nextNode = - descendNoStore(*node, i); + intr_ptr::SharedPtr nextNode = descendNoStore(*node, i); if (nextNode) { if (nextNode->isInner()) - nodeStack.push( - intr_ptr::static_pointer_cast( - nextNode)); + nodeStack.push(intr_ptr::static_pointer_cast(nextNode)); } else { @@ -265,9 +241,7 @@ SHAMap::walkMap(std::vector& missingNodes, int maxMissing) } bool -SHAMap::walkMapParallel( - std::vector& missingNodes, - int maxMissing) const +SHAMap::walkMapParallel(std::vector& missingNodes, int maxMissing) const { if (!root_->isInner()) // root_ is only node, and we have it return false; @@ -275,8 +249,7 @@ SHAMap::walkMapParallel( using StackEntry = intr_ptr::SharedPtr; std::array, 16> topChildren; { - auto const& innerRoot = - intr_ptr::static_pointer_cast(root_); + auto const& innerRoot = intr_ptr::static_pointer_cast(root_); for (int i = 0; i < 16; ++i) { if (!innerRoot->isEmptyBranch(i)) @@ -300,8 +273,7 @@ SHAMap::walkMapParallel( if (!child || !child->isInner()) continue; - nodeStacks[rootChildIndex].push( - intr_ptr::static_pointer_cast(child)); + nodeStacks[rootChildIndex].push(intr_ptr::static_pointer_cast(child)); JLOG(journal_.debug()) << "starting worker " << rootChildIndex; workers.push_back(std::thread( @@ -311,32 +283,25 @@ SHAMap::walkMapParallel( { while (!nodeStack.empty()) { - intr_ptr::SharedPtr node = - std::move(nodeStack.top()); - XRPL_ASSERT( - node, - "xrpl::SHAMap::walkMapParallel : non-null node"); + intr_ptr::SharedPtr node = std::move(nodeStack.top()); + XRPL_ASSERT(node, "xrpl::SHAMap::walkMapParallel : non-null node"); nodeStack.pop(); for (int i = 0; i < 16; ++i) { if (node->isEmptyBranch(i)) continue; - intr_ptr::SharedPtr nextNode = - descendNoStore(*node, i); + intr_ptr::SharedPtr nextNode = descendNoStore(*node, i); if (nextNode) { if (nextNode->isInner()) - nodeStack.push( - intr_ptr::static_pointer_cast< - SHAMapInnerNode>(nextNode)); + nodeStack.push(intr_ptr::static_pointer_cast(nextNode)); } else { std::lock_guard l{m}; - missingNodes.emplace_back( - type_, node->getChildHash(i)); + missingNodes.emplace_back(type_, node->getChildHash(i)); if (--maxMissing <= 0) return; } diff --git a/src/libxrpl/shamap/SHAMapInnerNode.cpp b/src/libxrpl/shamap/SHAMapInnerNode.cpp index 5d4a0fd27f..5ccca9c2f4 100644 --- a/src/libxrpl/shamap/SHAMapInnerNode.cpp +++ b/src/libxrpl/shamap/SHAMapInnerNode.cpp @@ -10,9 +10,7 @@ namespace xrpl { -SHAMapInnerNode::SHAMapInnerNode( - std::uint32_t cowid, - std::uint8_t numAllocatedChildren) +SHAMapInnerNode::SHAMapInnerNode(std::uint32_t cowid, std::uint8_t numAllocatedChildren) : SHAMapTreeNode(cowid), hashesAndChildren_(numAllocatedChildren) { } @@ -24,10 +22,8 @@ SHAMapInnerNode::partialDestructor() { intr_ptr::SharedPtr* children; // structured bindings can't be captured in c++ 17; use tie instead - std::tie(std::ignore, std::ignore, children) = - hashesAndChildren_.getHashesAndChildren(); - iterNonEmptyChildIndexes( - [&](auto branchNum, auto indexNum) { children[indexNum].reset(); }); + std::tie(std::ignore, std::ignore, children) = hashesAndChildren_.getHashesAndChildren(); + iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) { children[indexNum].reset(); }); } template @@ -47,8 +43,7 @@ SHAMapInnerNode::iterNonEmptyChildIndexes(F&& f) const void SHAMapInnerNode::resizeChildArrays(std::uint8_t toAllocate) { - hashesAndChildren_ = - TaggedPointer(std::move(hashesAndChildren_), isBranch_, toAllocate); + hashesAndChildren_ = TaggedPointer(std::move(hashesAndChildren_), isBranch_, toAllocate); } std::optional @@ -69,23 +64,18 @@ SHAMapInnerNode::clone(std::uint32_t cowid) const SHAMapHash *cloneHashes, *thisHashes; intr_ptr::SharedPtr*cloneChildren, *thisChildren; // structured bindings can't be captured in c++ 17; use tie instead - std::tie(std::ignore, cloneHashes, cloneChildren) = - p->hashesAndChildren_.getHashesAndChildren(); - std::tie(std::ignore, thisHashes, thisChildren) = - hashesAndChildren_.getHashesAndChildren(); + std::tie(std::ignore, cloneHashes, cloneChildren) = p->hashesAndChildren_.getHashesAndChildren(); + std::tie(std::ignore, thisHashes, thisChildren) = hashesAndChildren_.getHashesAndChildren(); if (thisIsSparse) { int cloneChildIndex = 0; - iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) { - cloneHashes[cloneChildIndex++] = thisHashes[indexNum]; - }); + iterNonEmptyChildIndexes( + [&](auto branchNum, auto indexNum) { cloneHashes[cloneChildIndex++] = thisHashes[indexNum]; }); } else { - iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) { - cloneHashes[branchNum] = thisHashes[indexNum]; - }); + iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) { cloneHashes[branchNum] = thisHashes[indexNum]; }); } spinlock sl(lock_); @@ -94,25 +84,20 @@ SHAMapInnerNode::clone(std::uint32_t cowid) const if (thisIsSparse) { int cloneChildIndex = 0; - iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) { - cloneChildren[cloneChildIndex++] = thisChildren[indexNum]; - }); + iterNonEmptyChildIndexes( + [&](auto branchNum, auto indexNum) { cloneChildren[cloneChildIndex++] = thisChildren[indexNum]; }); } else { - iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) { - cloneChildren[branchNum] = thisChildren[indexNum]; - }); + iterNonEmptyChildIndexes( + [&](auto branchNum, auto indexNum) { cloneChildren[branchNum] = thisChildren[indexNum]; }); } return p; } intr_ptr::SharedPtr -SHAMapInnerNode::makeFullInner( - Slice data, - SHAMapHash const& hash, - bool hashValid) +SHAMapInnerNode::makeFullInner(Slice data, SHAMapHash const& hash, bool hashValid) { // A full inner node is serialized as 16 256-bit hashes, back to back: if (data.size() != branchFactor * uint256::bytes) @@ -149,8 +134,7 @@ SHAMapInnerNode::makeCompressedInner(Slice data) // representing a one byte "position" and a 256-bit hash: constexpr std::size_t chunkSize = uint256::bytes + 1; - if (auto const s = data.size(); - (s % chunkSize != 0) || (s > chunkSize * branchFactor)) + if (auto const s = data.size(); (s % chunkSize != 0) || (s > chunkSize * branchFactor)) Throw("Invalid CI node"); SerialIter si(data); @@ -199,8 +183,7 @@ SHAMapInnerNode::updateHashDeep() SHAMapHash* hashes; intr_ptr::SharedPtr* children; // structured bindings can't be captured in c++ 17; use tie instead - std::tie(std::ignore, hashes, children) = - hashesAndChildren_.getHashesAndChildren(); + std::tie(std::ignore, hashes, children) = hashesAndChildren_.getHashesAndChildren(); iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) { if (auto p = children[indexNum].get()) hashes[indexNum] = p->getHash(); @@ -211,8 +194,7 @@ SHAMapInnerNode::updateHashDeep() void SHAMapInnerNode::serializeForWire(Serializer& s) const { - XRPL_ASSERT( - !isEmpty(), "xrpl::SHAMapInnerNode::serializeForWire : is non-empty"); + XRPL_ASSERT(!isEmpty(), "xrpl::SHAMapInnerNode::serializeForWire : is non-empty"); // If the node is sparse, then only send non-empty branches: if (getBranchCount() < 12) @@ -227,8 +209,7 @@ SHAMapInnerNode::serializeForWire(Serializer& s) const } else { - iterChildren( - [&](SHAMapHash const& hh) { s.addBitString(hh.as_uint256()); }); + iterChildren([&](SHAMapHash const& hh) { s.addBitString(hh.as_uint256()); }); s.add8(wireTypeInner); } } @@ -236,13 +217,10 @@ SHAMapInnerNode::serializeForWire(Serializer& s) const void SHAMapInnerNode::serializeWithPrefix(Serializer& s) const { - XRPL_ASSERT( - !isEmpty(), - "xrpl::SHAMapInnerNode::serializeWithPrefix : is non-empty"); + XRPL_ASSERT(!isEmpty(), "xrpl::SHAMapInnerNode::serializeWithPrefix : is non-empty"); s.add32(HashPrefix::innerNode); - iterChildren( - [&](SHAMapHash const& hh) { s.addBitString(hh.as_uint256()); }); + iterChildren([&](SHAMapHash const& hh) { s.addBitString(hh.as_uint256()); }); } std::string @@ -263,13 +241,9 @@ SHAMapInnerNode::getString(SHAMapNodeID const& id) const void SHAMapInnerNode::setChild(int m, intr_ptr::SharedPtr child) { - XRPL_ASSERT( - (m >= 0) && (m < branchFactor), - "xrpl::SHAMapInnerNode::setChild : valid branch input"); + XRPL_ASSERT((m >= 0) && (m < branchFactor), "xrpl::SHAMapInnerNode::setChild : valid branch input"); XRPL_ASSERT(cowid_, "xrpl::SHAMapInnerNode::setChild : nonzero cowid"); - XRPL_ASSERT( - child.get() != this, - "xrpl::SHAMapInnerNode::setChild : valid child input"); + XRPL_ASSERT(child.get() != this, "xrpl::SHAMapInnerNode::setChild : valid child input"); auto const dstIsBranch = [&] { if (child) @@ -281,8 +255,7 @@ SHAMapInnerNode::setChild(int m, intr_ptr::SharedPtr child) auto const dstToAllocate = popcnt16(dstIsBranch); // change hashesAndChildren to remove the element, or make room for the // added element, if necessary - hashesAndChildren_ = TaggedPointer( - std::move(hashesAndChildren_), isBranch_, dstIsBranch, dstToAllocate); + hashesAndChildren_ = TaggedPointer(std::move(hashesAndChildren_), isBranch_, dstIsBranch, dstToAllocate); isBranch_ = dstIsBranch; @@ -297,41 +270,27 @@ SHAMapInnerNode::setChild(int m, intr_ptr::SharedPtr child) hash_.zero(); XRPL_ASSERT( - getBranchCount() <= hashesAndChildren_.capacity(), - "xrpl::SHAMapInnerNode::setChild : maximum branch count"); + getBranchCount() <= hashesAndChildren_.capacity(), "xrpl::SHAMapInnerNode::setChild : maximum branch count"); } // finished modifying, now make shareable void -SHAMapInnerNode::shareChild( - int m, - intr_ptr::SharedPtr const& child) +SHAMapInnerNode::shareChild(int m, intr_ptr::SharedPtr const& child) { - XRPL_ASSERT( - (m >= 0) && (m < branchFactor), - "xrpl::SHAMapInnerNode::shareChild : valid branch input"); + XRPL_ASSERT((m >= 0) && (m < branchFactor), "xrpl::SHAMapInnerNode::shareChild : valid branch input"); XRPL_ASSERT(cowid_, "xrpl::SHAMapInnerNode::shareChild : nonzero cowid"); - XRPL_ASSERT( - child, "xrpl::SHAMapInnerNode::shareChild : non-null child input"); - XRPL_ASSERT( - child.get() != this, - "xrpl::SHAMapInnerNode::shareChild : valid child input"); + XRPL_ASSERT(child, "xrpl::SHAMapInnerNode::shareChild : non-null child input"); + XRPL_ASSERT(child.get() != this, "xrpl::SHAMapInnerNode::shareChild : valid child input"); - XRPL_ASSERT( - !isEmptyBranch(m), - "xrpl::SHAMapInnerNode::shareChild : non-empty branch input"); + XRPL_ASSERT(!isEmptyBranch(m), "xrpl::SHAMapInnerNode::shareChild : non-empty branch input"); hashesAndChildren_.getChildren()[*getChildIndex(m)] = child; } SHAMapTreeNode* SHAMapInnerNode::getChildPointer(int branch) { - XRPL_ASSERT( - branch >= 0 && branch < branchFactor, - "xrpl::SHAMapInnerNode::getChildPointer : valid branch input"); - XRPL_ASSERT( - !isEmptyBranch(branch), - "xrpl::SHAMapInnerNode::getChildPointer : non-empty branch input"); + XRPL_ASSERT(branch >= 0 && branch < branchFactor, "xrpl::SHAMapInnerNode::getChildPointer : valid branch input"); + XRPL_ASSERT(!isEmptyBranch(branch), "xrpl::SHAMapInnerNode::getChildPointer : non-empty branch input"); auto const index = *getChildIndex(branch); @@ -343,12 +302,8 @@ SHAMapInnerNode::getChildPointer(int branch) intr_ptr::SharedPtr SHAMapInnerNode::getChild(int branch) { - XRPL_ASSERT( - branch >= 0 && branch < branchFactor, - "xrpl::SHAMapInnerNode::getChild : valid branch input"); - XRPL_ASSERT( - !isEmptyBranch(branch), - "xrpl::SHAMapInnerNode::getChild : non-empty branch input"); + XRPL_ASSERT(branch >= 0 && branch < branchFactor, "xrpl::SHAMapInnerNode::getChild : valid branch input"); + XRPL_ASSERT(!isEmptyBranch(branch), "xrpl::SHAMapInnerNode::getChild : non-empty branch input"); auto const index = *getChildIndex(branch); @@ -360,9 +315,7 @@ SHAMapInnerNode::getChild(int branch) SHAMapHash const& SHAMapInnerNode::getChildHash(int m) const { - XRPL_ASSERT( - (m >= 0) && (m < branchFactor), - "xrpl::SHAMapInnerNode::getChildHash : valid branch input"); + XRPL_ASSERT((m >= 0) && (m < branchFactor), "xrpl::SHAMapInnerNode::getChildHash : valid branch input"); if (auto const i = getChildIndex(m)) return hashesAndChildren_.getHashes()[*i]; @@ -370,19 +323,11 @@ SHAMapInnerNode::getChildHash(int m) const } intr_ptr::SharedPtr -SHAMapInnerNode::canonicalizeChild( - int branch, - intr_ptr::SharedPtr node) +SHAMapInnerNode::canonicalizeChild(int branch, intr_ptr::SharedPtr node) { - XRPL_ASSERT( - branch >= 0 && branch < branchFactor, - "xrpl::SHAMapInnerNode::canonicalizeChild : valid branch input"); - XRPL_ASSERT( - node != nullptr, - "xrpl::SHAMapInnerNode::canonicalizeChild : valid node input"); - XRPL_ASSERT( - !isEmptyBranch(branch), - "xrpl::SHAMapInnerNode::canonicalizeChild : non-empty branch input"); + XRPL_ASSERT(branch >= 0 && branch < branchFactor, "xrpl::SHAMapInnerNode::canonicalizeChild : valid branch input"); + XRPL_ASSERT(node != nullptr, "xrpl::SHAMapInnerNode::canonicalizeChild : valid node input"); + XRPL_ASSERT(!isEmptyBranch(branch), "xrpl::SHAMapInnerNode::canonicalizeChild : non-empty branch input"); auto const childIndex = *getChildIndex(branch); auto [_, hashes, children] = hashesAndChildren_.getHashesAndChildren(); XRPL_ASSERT( @@ -410,17 +355,14 @@ void SHAMapInnerNode::invariants(bool is_root) const { [[maybe_unused]] unsigned count = 0; - auto [numAllocated, hashes, children] = - hashesAndChildren_.getHashesAndChildren(); + auto [numAllocated, hashes, children] = hashesAndChildren_.getHashesAndChildren(); if (numAllocated != branchFactor) { auto const branchCount = getBranchCount(); for (int i = 0; i < branchCount; ++i) { - XRPL_ASSERT( - hashes[i].isNonZero(), - "xrpl::SHAMapInnerNode::invariants : nonzero hash in branch"); + XRPL_ASSERT(hashes[i].isNonZero(), "xrpl::SHAMapInnerNode::invariants : nonzero hash in branch"); if (children[i] != nullptr) children[i]->invariants(); ++count; @@ -452,11 +394,8 @@ SHAMapInnerNode::invariants(bool is_root) const if (!is_root) { - XRPL_ASSERT( - hash_.isNonZero(), - "xrpl::SHAMapInnerNode::invariants : nonzero hash"); - XRPL_ASSERT( - count >= 1, "xrpl::SHAMapInnerNode::invariants : minimum count"); + XRPL_ASSERT(hash_.isNonZero(), "xrpl::SHAMapInnerNode::invariants : nonzero hash"); + XRPL_ASSERT(count >= 1, "xrpl::SHAMapInnerNode::invariants : minimum count"); } XRPL_ASSERT( (count == 0) ? hash_.isZero() : hash_.isNonZero(), diff --git a/src/libxrpl/shamap/SHAMapLeafNode.cpp b/src/libxrpl/shamap/SHAMapLeafNode.cpp index 72e57cd737..7f449af3a7 100644 --- a/src/libxrpl/shamap/SHAMapLeafNode.cpp +++ b/src/libxrpl/shamap/SHAMapLeafNode.cpp @@ -2,9 +2,7 @@ namespace xrpl { -SHAMapLeafNode::SHAMapLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid) +SHAMapLeafNode::SHAMapLeafNode(boost::intrusive_ptr item, std::uint32_t cowid) : SHAMapTreeNode(cowid), item_(std::move(item)) { XRPL_ASSERT( @@ -13,10 +11,7 @@ SHAMapLeafNode::SHAMapLeafNode( "SHAMapItem const>, std::uint32_t) : minimum input size"); } -SHAMapLeafNode::SHAMapLeafNode( - boost::intrusive_ptr item, - std::uint32_t cowid, - SHAMapHash const& hash) +SHAMapLeafNode::SHAMapLeafNode(boost::intrusive_ptr item, std::uint32_t cowid, SHAMapHash const& hash) : SHAMapTreeNode(cowid, hash), item_(std::move(item)) { XRPL_ASSERT( @@ -73,8 +68,7 @@ SHAMapLeafNode::getString(SHAMapNodeID const& id) const void SHAMapLeafNode::invariants(bool) const { - XRPL_ASSERT( - hash_.isNonZero(), "xrpl::SHAMapLeafNode::invariants : nonzero hash"); + XRPL_ASSERT(hash_.isNonZero(), "xrpl::SHAMapLeafNode::invariants : nonzero hash"); XRPL_ASSERT(item_, "xrpl::SHAMapLeafNode::invariants : non-null item"); } diff --git a/src/libxrpl/shamap/SHAMapNodeID.cpp b/src/libxrpl/shamap/SHAMapNodeID.cpp index a32ff5c28e..e8840f398d 100644 --- a/src/libxrpl/shamap/SHAMapNodeID.cpp +++ b/src/libxrpl/shamap/SHAMapNodeID.cpp @@ -34,15 +34,10 @@ depthMask(unsigned int depth) } // canonicalize the hash to a node ID for this depth -SHAMapNodeID::SHAMapNodeID(unsigned int depth, uint256 const& hash) - : id_(hash), depth_(depth) +SHAMapNodeID::SHAMapNodeID(unsigned int depth, uint256 const& hash) : id_(hash), depth_(depth) { - XRPL_ASSERT( - depth <= SHAMap::leafDepth, - "xrpl::SHAMapNodeID::SHAMapNodeID : maximum depth input"); - XRPL_ASSERT( - id_ == (id_ & depthMask(depth)), - "xrpl::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match"); + XRPL_ASSERT(depth <= SHAMap::leafDepth, "xrpl::SHAMapNodeID::SHAMapNodeID : maximum depth input"); + XRPL_ASSERT(id_ == (id_ & depthMask(depth)), "xrpl::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match"); } std::string @@ -57,9 +52,7 @@ SHAMapNodeID::getRawString() const SHAMapNodeID SHAMapNodeID::getChildNodeID(unsigned int m) const { - XRPL_ASSERT( - m < SHAMap::branchFactor, - "xrpl::SHAMapNodeID::getChildNodeID : valid branch input"); + XRPL_ASSERT(m < SHAMap::branchFactor, "xrpl::SHAMapNodeID::getChildNodeID : valid branch input"); // A SHAMap has exactly 65 levels, so nodes must not exceed that // depth; if they do, this breaks the invariant of never allowing @@ -69,13 +62,10 @@ SHAMapNodeID::getChildNodeID(unsigned int m) const // We throw (but never assert) if the node is at level 64, since // entries at that depth are leaf nodes and have no children and even // constructing a child node from them would break the above invariant. - XRPL_ASSERT( - depth_ <= SHAMap::leafDepth, - "xrpl::SHAMapNodeID::getChildNodeID : maximum leaf depth"); + XRPL_ASSERT(depth_ <= SHAMap::leafDepth, "xrpl::SHAMapNodeID::getChildNodeID : maximum leaf depth"); if (depth_ >= SHAMap::leafDepth) - Throw( - "Request for child node ID of " + to_string(*this)); + Throw("Request for child node ID of " + to_string(*this)); if (id_ != (id_ & depthMask(depth_))) Throw("Incorrect mask for " + to_string(*this)); @@ -116,17 +106,14 @@ selectBranch(SHAMapNodeID const& id, uint256 const& hash) else branch >>= 4; - XRPL_ASSERT( - branch < SHAMap::branchFactor, "xrpl::selectBranch : maximum result"); + XRPL_ASSERT(branch < SHAMap::branchFactor, "xrpl::selectBranch : maximum result"); return branch; } SHAMapNodeID SHAMapNodeID::createID(int depth, uint256 const& key) { - XRPL_ASSERT( - (depth >= 0) && (depth < 65), - "xrpl::SHAMapNodeID::createID : valid branch input"); + XRPL_ASSERT((depth >= 0) && (depth < 65), "xrpl::SHAMapNodeID::createID : valid branch input"); return SHAMapNodeID(depth, key & depthMask(depth)); } diff --git a/src/libxrpl/shamap/SHAMapSync.cpp b/src/libxrpl/shamap/SHAMapSync.cpp index d9c0846fbf..503505b80c 100644 --- a/src/libxrpl/shamap/SHAMapSync.cpp +++ b/src/libxrpl/shamap/SHAMapSync.cpp @@ -6,9 +6,7 @@ namespace xrpl { void -SHAMap::visitLeaves( - std::function const& - item)> const& leafFunction) const +SHAMap::visitLeaves(std::function const& item)> const& leafFunction) const { visitNodes([&leafFunction](SHAMapTreeNode& node) { if (!node.isInner()) @@ -40,8 +38,7 @@ SHAMap::visitNodes(std::function const& function) const { if (!node->isEmptyBranch(pos)) { - intr_ptr::SharedPtr child = - descendNoStore(*node, pos); + intr_ptr::SharedPtr child = descendNoStore(*node, pos); if (!function(*child)) return; @@ -60,8 +57,7 @@ SHAMap::visitNodes(std::function const& function) const } // descend to the child's first position - node = - intr_ptr::static_pointer_cast(child); + node = intr_ptr::static_pointer_cast(child); pos = 0; } } @@ -80,9 +76,7 @@ SHAMap::visitNodes(std::function const& function) const } void -SHAMap::visitDifferences( - SHAMap const* have, - std::function const& function) const +SHAMap::visitDifferences(SHAMap const* have, std::function const& function) const { // Visit every node in this SHAMap that is not present // in the specified SHAMap @@ -98,8 +92,7 @@ SHAMap::visitDifferences( if (root_->isLeaf()) { auto leaf = intr_ptr::static_pointer_cast(root_); - if (!have || - !have->hasLeafNode(leaf->peekItem()->key(), leaf->getHash())) + if (!have || !have->hasLeafNode(leaf->peekItem()->key(), leaf->getHash())) function(*root_); return; } @@ -130,14 +123,9 @@ SHAMap::visitDifferences( if (next->isInner()) { if (!have || !have->hasInnerNode(childID, childHash)) - stack.push( - {static_cast(next), childID}); + stack.push({static_cast(next), childID}); } - else if ( - !have || - !have->hasLeafNode( - static_cast(next)->peekItem()->key(), - childHash)) + else if (!have || !have->hasLeafNode(static_cast(next)->peekItem()->key(), childHash)) { if (!function(*next)) return; @@ -173,9 +161,7 @@ SHAMap::gmn_ProcessNodes(MissingNodes& mn, MissingNodes::StackEntry& se) // we already know this child node is missing fullBelow = false; } - else if ( - !backed_ || - !f_.getFullBelowCache()->touch_if_exists(childHash.as_uint256())) + else if (!backed_ || !f_.getFullBelowCache()->touch_if_exists(childHash.as_uint256())) { bool pending = false; auto d = descendAsync( @@ -183,13 +169,10 @@ SHAMap::gmn_ProcessNodes(MissingNodes& mn, MissingNodes::StackEntry& se) branch, mn.filter_, pending, - [node, nodeID, branch, &mn]( - intr_ptr::SharedPtr found, - SHAMapHash const&) { + [node, nodeID, branch, &mn](intr_ptr::SharedPtr found, SHAMapHash const&) { // a read completed asynchronously std::unique_lock lock{mn.deferLock_}; - mn.finishedReads_.emplace_back( - node, nodeID, branch, std::move(found)); + mn.finishedReads_.emplace_back(node, nodeID, branch, std::move(found)); mn.deferCondVar_.notify_one(); }); @@ -204,15 +187,12 @@ SHAMap::gmn_ProcessNodes(MissingNodes& mn, MissingNodes::StackEntry& se) fullBelow = false; // for now, not known full below mn.missingHashes_.insert(childHash); - mn.missingNodes_.emplace_back( - nodeID.getChildNodeID(branch), childHash.as_uint256()); + mn.missingNodes_.emplace_back(nodeID.getChildNodeID(branch), childHash.as_uint256()); if (--mn.max_ <= 0) return; } - else if ( - d->isInner() && - !static_cast(d)->isFullBelow(mn.generation_)) + else if (d->isInner() && !static_cast(d)->isFullBelow(mn.generation_)) { mn.stack_.push(se); @@ -250,12 +230,7 @@ SHAMap::gmn_ProcessDeferredReads(MissingNodes& mn) int complete = 0; while (complete != mn.deferred_) { - std::tuple< - SHAMapInnerNode*, - SHAMapNodeID, - int, - intr_ptr::SharedPtr> - deferredNode; + std::tuple> deferredNode; { std::unique_lock lock{mn.deferLock_}; @@ -280,8 +255,7 @@ SHAMap::gmn_ProcessDeferredReads(MissingNodes& mn) } else if ((mn.max_ > 0) && (mn.missingHashes_.insert(nodeHash).second)) { - mn.missingNodes_.emplace_back( - parentID.getChildNodeID(branch), nodeHash.as_uint256()); + mn.missingNodes_.emplace_back(parentID.getChildNodeID(branch), nodeHash.as_uint256()); --mn.max_; } } @@ -298,9 +272,7 @@ SHAMap::gmn_ProcessDeferredReads(MissingNodes& mn) std::vector> SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) { - XRPL_ASSERT( - root_->getHash().isNonZero(), - "xrpl::SHAMap::getMissingNodes : nonzero root hash"); + XRPL_ASSERT(root_->getHash().isNonZero(), "xrpl::SHAMap::getMissingNodes : nonzero root hash"); XRPL_ASSERT(max > 0, "xrpl::SHAMap::getMissingNodes : valid max input"); MissingNodes mn( @@ -309,9 +281,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) 512, // number of async reads per pass f_.getFullBelowCache()->getGeneration()); - if (!root_->isInner() || - intr_ptr::static_pointer_cast(root_)->isFullBelow( - mn.generation_)) + if (!root_->isInner() || intr_ptr::static_pointer_cast(root_)->isFullBelow(mn.generation_)) { clearSynching(); return std::move(mn.missingNodes_); @@ -323,12 +293,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) // (randomly selected) inner node. This increases the likelihood // that the two threads will produce different request sets (which is // more efficient than sending identical requests). - MissingNodes::StackEntry pos{ - static_cast(root_.get()), - SHAMapNodeID(), - rand_int(255), - 0, - true}; + MissingNodes::StackEntry pos{static_cast(root_.get()), SHAMapNodeID(), rand_int(255), 0, true}; auto& node = std::get<0>(pos); auto& nextChild = std::get<3>(pos); auto& fullBelow = std::get<4>(pos); @@ -360,9 +325,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) // This is a node we are continuing to process fullBelow = fullBelow && was; // was and still is } - XRPL_ASSERT( - node, - "xrpl::SHAMap::getMissingNodes : first non-null node"); + XRPL_ASSERT(node, "xrpl::SHAMap::getMissingNodes : first non-null node"); } } @@ -382,8 +345,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) // Recheck nodes we could not finish before for (auto const& [innerNode, nodeId] : mn.resumes_) if (!innerNode->isFullBelow(mn.generation_)) - mn.stack_.push(std::make_tuple( - innerNode, nodeId, rand_int(255), 0, true)); + mn.stack_.push(std::make_tuple(innerNode, nodeId, rand_int(255), 0, true)); mn.resumes_.clear(); } @@ -393,9 +355,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) // Resume at the top of the stack pos = mn.stack_.top(); mn.stack_.pop(); - XRPL_ASSERT( - node, - "xrpl::SHAMap::getMissingNodes : second non-null node"); + XRPL_ASSERT(node, "xrpl::SHAMap::getMissingNodes : second non-null node"); } } @@ -436,9 +396,7 @@ SHAMap::getNodeFat( if (node == nullptr || wanted != nodeID) { - JLOG(journal_.info()) - << "peer requested node that is not in the map: " << wanted - << " but found " << nodeID; + JLOG(journal_.info()) << "peer requested node that is not in the map: " << wanted << " but found " << nodeID; return false; } @@ -484,18 +442,14 @@ SHAMap::getNodeFat( { // If there's more than one child, reduce the depth // If only one child, follow the chain - stack.emplace( - childNode, - childID, - (bc > 1) ? (depth - 1) : depth); + stack.emplace(childNode, childID, (bc > 1) ? (depth - 1) : depth); } else if (childNode->isInner() || fatLeaves) { // Just include this node s.erase(); childNode->serializeForWire(s); - data.emplace_back( - std::make_pair(childID, s.getData())); + data.emplace_back(std::make_pair(childID, s.getData())); } } } @@ -513,18 +467,13 @@ SHAMap::serializeRoot(Serializer& s) const } SHAMapAddNode -SHAMap::addRootNode( - SHAMapHash const& hash, - Slice const& rootNode, - SHAMapSyncFilter* filter) +SHAMap::addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFilter* filter) { // we already have a root_ node if (root_->getHash().isNonZero()) { JLOG(journal_.trace()) << "got root node, already have one"; - XRPL_ASSERT( - root_->getHash() == hash, - "xrpl::SHAMap::addRootNode : valid hash input"); + XRPL_ASSERT(root_->getHash() == hash, "xrpl::SHAMap::addRootNode : valid hash input"); return SHAMapAddNode::duplicate(); } @@ -545,25 +494,16 @@ SHAMap::addRootNode( { Serializer s; root_->serializeWithPrefix(s); - filter->gotNode( - false, - root_->getHash(), - ledgerSeq_, - std::move(s.modData()), - root_->getType()); + filter->gotNode(false, root_->getHash(), ledgerSeq_, std::move(s.modData()), root_->getType()); } return SHAMapAddNode::useful(); } SHAMapAddNode -SHAMap::addKnownNode( - SHAMapNodeID const& node, - Slice const& rawNode, - SHAMapSyncFilter* filter) +SHAMap::addKnownNode(SHAMapNodeID const& node, Slice const& rawNode, SHAMapSyncFilter* filter) { - XRPL_ASSERT( - !node.isRoot(), "xrpl::SHAMap::addKnownNode : valid node input"); + XRPL_ASSERT(!node.isRoot(), "xrpl::SHAMap::addKnownNode : valid node input"); if (!isSynching()) { @@ -575,8 +515,7 @@ SHAMap::addKnownNode( SHAMapNodeID currNodeID; auto currNode = root_.get(); - while (currNode->isInner() && - !static_cast(currNode)->isFullBelow(generation) && + while (currNode->isInner() && !static_cast(currNode)->isFullBelow(generation) && (currNodeID.getDepth() < node.getDepth())) { int const branch = selectBranch(currNodeID, node.getNodeID()); @@ -595,8 +534,7 @@ SHAMap::addKnownNode( } auto prevNode = inner; - std::tie(currNode, currNodeID) = - descend(inner, currNodeID, branch, filter); + std::tie(currNode, currNodeID) = descend(inner, currNodeID, branch, filter); if (currNode != nullptr) continue; @@ -616,20 +554,14 @@ SHAMap::addKnownNode( // propagate further down the line. if (newNode->isLeaf()) { - auto const& actualKey = - static_cast(newNode.get()) - ->peekItem() - ->key(); + auto const& actualKey = static_cast(newNode.get())->peekItem()->key(); // Validate that this leaf belongs at the target position - auto const expectedNodeID = - SHAMapNodeID::createID(node.getDepth(), actualKey); + auto const expectedNodeID = SHAMapNodeID::createID(node.getDepth(), actualKey); if (expectedNodeID.getNodeID() != node.getNodeID()) { - JLOG(journal_.debug()) - << "Leaf node position mismatch: " - << "expected=" << expectedNodeID.getNodeID() - << ", actual=" << node.getNodeID(); + JLOG(journal_.debug()) << "Leaf node position mismatch: " + << "expected=" << expectedNodeID.getNodeID() << ", actual=" << node.getNodeID(); return SHAMapAddNode::invalid(); } } @@ -637,8 +569,7 @@ SHAMap::addKnownNode( // Inner nodes must be at a level strictly less than 64 // but leaf nodes (while notionally at level 64) can be // at any depth up to and including 64: - if ((currNodeID.getDepth() > leafDepth) || - (newNode->isInner() && currNodeID.getDepth() == leafDepth)) + if ((currNodeID.getDepth() > leafDepth) || (newNode->isInner() && currNodeID.getDepth() == leafDepth)) { // Map is provably invalid state_ = SHAMapState::Invalid; @@ -650,8 +581,7 @@ SHAMap::addKnownNode( // Either this node is broken or we didn't request it (yet) JLOG(journal_.warn()) << "unable to hook node " << node; JLOG(journal_.info()) << " stuck at " << currNodeID; - JLOG(journal_.info()) << "got depth=" << node.getDepth() - << ", walked to= " << currNodeID.getDepth(); + JLOG(journal_.info()) << "got depth=" << node.getDepth() << ", walked to= " << currNodeID.getDepth(); return SHAMapAddNode::useful(); } @@ -664,12 +594,7 @@ SHAMap::addKnownNode( { Serializer s; newNode->serializeWithPrefix(s); - filter->gotNode( - false, - childHash, - ledgerSeq_, - std::move(s.modData()), - newNode->getType()); + filter->gotNode(false, childHash, ledgerSeq_, std::move(s.modData()), newNode->getType()); } return SHAMapAddNode::useful(); @@ -708,8 +633,7 @@ SHAMap::deepCompare(SHAMap& other) const if (!otherNode->isLeaf()) return false; auto& nodePeek = static_cast(node)->peekItem(); - auto& otherNodePeek = - static_cast(otherNode)->peekItem(); + auto& otherNodePeek = static_cast(otherNode)->peekItem(); if (nodePeek->key() != otherNodePeek->key()) return false; if (nodePeek->slice() != otherNodePeek->slice()) @@ -752,9 +676,7 @@ SHAMap::deepCompare(SHAMap& other) const /** Does this map have this inner node? */ bool -SHAMap::hasInnerNode( - SHAMapNodeID const& targetNodeID, - SHAMapHash const& targetNodeHash) const +SHAMap::hasInnerNode(SHAMapNodeID const& targetNodeID, SHAMapHash const& targetNodeHash) const { auto node = root_.get(); SHAMapNodeID nodeID; @@ -791,8 +713,7 @@ SHAMap::hasLeafNode(uint256 const& tag, SHAMapHash const& targetNodeHash) const if (inner->isEmptyBranch(branch)) return false; // Dead end, node must not be here - if (inner->getChildHash(branch) == - targetNodeHash) // Matching leaf, no need to retrieve it + if (inner->getChildHash(branch) == targetNodeHash) // Matching leaf, no need to retrieve it return true; node = descendThrow(inner, branch); @@ -815,10 +736,8 @@ SHAMap::getProofPath(uint256 const& key) const return {}; } - if (auto const& node = stack.top().first; !node || node->isInner() || - intr_ptr::static_pointer_cast(node) - ->peekItem() - ->key() != key) + if (auto const& node = stack.top().first; + !node || node->isInner() || intr_ptr::static_pointer_cast(node)->peekItem()->key() != key) { JLOG(journal_.debug()) << "no path to " << key; return {}; @@ -834,16 +753,12 @@ SHAMap::getProofPath(uint256 const& key) const stack.pop(); } - JLOG(journal_.debug()) << "getPath for key " << key << ", path length " - << path.size(); + JLOG(journal_.debug()) << "getPath for key " << key << ", path length " << path.size(); return path; } bool -SHAMap::verifyProofPath( - uint256 const& rootHash, - uint256 const& key, - std::vector const& path) +SHAMap::verifyProofPath(uint256 const& rootHash, uint256 const& key, std::vector const& path) { if (path.empty() || path.size() > 65) return false; @@ -865,8 +780,7 @@ SHAMap::verifyProofPath( if (node->isInner()) { auto nodeId = SHAMapNodeID::createID(depth, key); - hash = static_cast(node.get()) - ->getChildHash(selectBranch(nodeId, key)); + hash = static_cast(node.get())->getChildHash(selectBranch(nodeId, key)); } else { diff --git a/src/libxrpl/shamap/SHAMapTreeNode.cpp b/src/libxrpl/shamap/SHAMapTreeNode.cpp index 854b4c1097..156570a60f 100644 --- a/src/libxrpl/shamap/SHAMapTreeNode.cpp +++ b/src/libxrpl/shamap/SHAMapTreeNode.cpp @@ -13,26 +13,18 @@ namespace xrpl { intr_ptr::SharedPtr -SHAMapTreeNode::makeTransaction( - Slice data, - SHAMapHash const& hash, - bool hashValid) +SHAMapTreeNode::makeTransaction(Slice data, SHAMapHash const& hash, bool hashValid) { - auto item = - make_shamapitem(sha512Half(HashPrefix::transactionID, data), data); + auto item = make_shamapitem(sha512Half(HashPrefix::transactionID, data), data); if (hashValid) - return intr_ptr::make_shared( - std::move(item), 0, hash); + return intr_ptr::make_shared(std::move(item), 0, hash); return intr_ptr::make_shared(std::move(item), 0); } intr_ptr::SharedPtr -SHAMapTreeNode::makeTransactionWithMeta( - Slice data, - SHAMapHash const& hash, - bool hashValid) +SHAMapTreeNode::makeTransactionWithMeta(Slice data, SHAMapHash const& hash, bool hashValid) { Serializer s(data.data(), data.size()); @@ -43,25 +35,20 @@ SHAMapTreeNode::makeTransactionWithMeta( // FIXME: improve this interface so that the above check isn't needed if (!s.getBitString(tag, s.size() - tag.bytes)) - Throw( - "Short TXN+MD node (" + std::to_string(s.size()) + ")"); + Throw("Short TXN+MD node (" + std::to_string(s.size()) + ")"); s.chop(tag.bytes); auto item = make_shamapitem(tag, s.slice()); if (hashValid) - return intr_ptr::make_shared( - std::move(item), 0, hash); + return intr_ptr::make_shared(std::move(item), 0, hash); return intr_ptr::make_shared(std::move(item), 0); } intr_ptr::SharedPtr -SHAMapTreeNode::makeAccountState( - Slice data, - SHAMapHash const& hash, - bool hashValid) +SHAMapTreeNode::makeAccountState(Slice data, SHAMapHash const& hash, bool hashValid) { Serializer s(data.data(), data.size()); @@ -72,8 +59,7 @@ SHAMapTreeNode::makeAccountState( // FIXME: improve this interface so that the above check isn't needed if (!s.getBitString(tag, s.size() - tag.bytes)) - Throw( - "Short AS node (" + std::to_string(s.size()) + ")"); + Throw("Short AS node (" + std::to_string(s.size()) + ")"); s.chop(tag.bytes); @@ -83,11 +69,9 @@ SHAMapTreeNode::makeAccountState( auto item = make_shamapitem(tag, s.slice()); if (hashValid) - return intr_ptr::make_shared( - std::move(item), 0, hash); + return intr_ptr::make_shared(std::move(item), 0, hash); - return intr_ptr::make_shared( - std::move(item), 0); + return intr_ptr::make_shared(std::move(item), 0); } intr_ptr::SharedPtr @@ -118,8 +102,7 @@ SHAMapTreeNode::makeFromWire(Slice rawNode) if (type == wireTypeTransactionWithMeta) return makeTransactionWithMeta(rawNode, hash, hashValid); - Throw( - "wire: Unknown type (" + std::to_string(type) + ")"); + Throw("wire: Unknown type (" + std::to_string(type) + ")"); } intr_ptr::SharedPtr @@ -131,10 +114,8 @@ SHAMapTreeNode::makeFromPrefix(Slice rawNode, SHAMapHash const& hash) // FIXME: Use SerialIter::get32? // Extract the prefix auto const type = safe_cast( - (safe_cast(rawNode[0]) << 24) + - (safe_cast(rawNode[1]) << 16) + - (safe_cast(rawNode[2]) << 8) + - (safe_cast(rawNode[3]))); + (safe_cast(rawNode[0]) << 24) + (safe_cast(rawNode[1]) << 16) + + (safe_cast(rawNode[2]) << 8) + (safe_cast(rawNode[3]))); rawNode.remove_prefix(4); @@ -153,9 +134,7 @@ SHAMapTreeNode::makeFromPrefix(Slice rawNode, SHAMapHash const& hash) return makeTransactionWithMeta(rawNode, hash, hashValid); Throw( - "prefix: unknown type (" + - std::to_string(safe_cast>(type)) + - ")"); + "prefix: unknown type (" + std::to_string(safe_cast>(type)) + ")"); } std::string diff --git a/src/test/app/AMMCalc_test.cpp b/src/test/app/AMMCalc_test.cpp index abfb548b64..7d735c2575 100644 --- a/src/test/app/AMMCalc_test.cpp +++ b/src/test/app/AMMCalc_test.cpp @@ -188,8 +188,7 @@ class AMMCalc_test : public beast::unit_test::suite STAmount limitStepOut{}; auto trate = [&](auto const& amt) { auto const currency = to_string(amt.issue().currency); - return rates.find(currency) != rates.end() ? rates.at(currency) - : QUALITY_ONE; + return rates.find(currency) != rates.end() ? rates.at(currency) : QUALITY_ONE; }; // swap out reverse sin = sout; @@ -235,8 +234,7 @@ class AMMCalc_test : public beast::unit_test::suite sin = sout; resultOut = sout; } - std::cout << "in: " << toString(resultIn) - << " out: " << toString(resultOut) << std::endl; + std::cout << "in: " << toString(resultIn) << " out: " << toString(resultOut) << std::endl; } void @@ -253,18 +251,14 @@ class AMMCalc_test : public beast::unit_test::suite STAmount limitStepIn{}; auto trate = [&](auto const& amt) { auto const currency = to_string(amt.issue().currency); - return rates.find(currency) != rates.end() ? rates.at(currency) - : QUALITY_ONE; + return rates.find(currency) != rates.end() ? rates.at(currency) : QUALITY_ONE; }; // Swap in forward for (auto it = vp.begin(); it != vp.end(); ++it) { auto const [amts, amm] = *it; - sin = mulratio( - sin, - QUALITY_ONE, - trate(sin), - false); // out of the next step + sin = mulratio(sin, QUALITY_ONE, trate(sin), + false); // out of the next step // assume no amm limit if (amm) { @@ -303,8 +297,7 @@ class AMMCalc_test : public beast::unit_test::suite resultIn = sin; } resultOut = mulratio(resultOut, QUALITY_ONE, trate(resultOut), true); - std::cout << "in: " << toString(resultIn) - << " out: " << toString(resultOut) << std::endl; + std::cout << "in: " << toString(resultIn) << " out: " << toString(resultOut) << std::endl; } void @@ -378,11 +371,7 @@ class AMMCalc_test : public beast::unit_test::suite { Account const amm("amm"); auto const LPT = amm["LPT"]; - std::cout - << to_string( - ammLPTokens(pool->first.in, pool->first.out, LPT) - .iou()) - << std::endl; + std::cout << to_string(ammLPTokens(pool->first.in, pool->first.out, LPT).iou()) << std::endl; return true; } } @@ -409,17 +398,11 @@ class AMMCalc_test : public beast::unit_test::suite env.current()->rules(), beast::Journal(beast::Journal::getNullSink())); ammOffer) - std::cout - << "amm offer: " << toString(ammOffer->in) - << " " << toString(ammOffer->out) - << "\nnew pool: " - << toString(pool->first.in + ammOffer->in) - << " " - << toString(pool->first.out - ammOffer->out) - << std::endl; + std::cout << "amm offer: " << toString(ammOffer->in) << " " << toString(ammOffer->out) + << "\nnew pool: " << toString(pool->first.in + ammOffer->in) << " " + << toString(pool->first.out - ammOffer->out) << std::endl; else - std::cout << "can't change the pool's SP quality" - << std::endl; + std::cout << "can't change the pool's SP quality" << std::endl; return true; } } diff --git a/src/test/app/AMMClawback_test.cpp b/src/test/app/AMMClawback_test.cpp index 52f05f9ed5..65cf7f0a60 100644 --- a/src/test/app/AMMClawback_test.cpp +++ b/src/test/app/AMMClawback_test.cpp @@ -36,9 +36,7 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, alice, XRP(100), USD(100)); env.close(); - env(amm::ammClawback( - gw, Account("unknown"), USD, XRP, std::nullopt), - ter(terNO_ACCOUNT)); + env(amm::ammClawback(gw, Account("unknown"), USD, XRP, std::nullopt), ter(terNO_ACCOUNT)); } // Test if asset pair provided does not exist. This should @@ -70,8 +68,7 @@ class AMMClawback_test : public beast::unit_test::suite // The AMM account does not exist at all now. // It should return terNO_AMM error. - env(amm::ammClawback(gw, alice, USD, gw["EUR"], std::nullopt), - ter(terNO_AMM)); + env(amm::ammClawback(gw, alice, USD, gw["EUR"], std::nullopt), ter(terNO_AMM)); } // Test if the issuer field and holder field is the same. This should @@ -97,12 +94,10 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, gw, XRP(100), USD(100), ter(tesSUCCESS)); // Issuer can not clawback from himself. - env(amm::ammClawback(gw, gw, USD, XRP, std::nullopt), - ter(temMALFORMED)); + env(amm::ammClawback(gw, gw, USD, XRP, std::nullopt), ter(temMALFORMED)); // Holder can not clawback from himself. - env(amm::ammClawback(alice, alice, USD, XRP, std::nullopt), - ter(temMALFORMED)); + env(amm::ammClawback(alice, alice, USD, XRP, std::nullopt), ter(temMALFORMED)); } // Test if the Asset field matches the Account field. @@ -128,12 +123,7 @@ class AMMClawback_test : public beast::unit_test::suite // The Asset's issuer field is alice, while the Account field is gw. // This should return temMALFORMED because they do not match. - env(amm::ammClawback( - gw, - alice, - Issue{gw["USD"].currency, alice.id()}, - XRP, - std::nullopt), + env(amm::ammClawback(gw, alice, Issue{gw["USD"].currency, alice.id()}, XRP, std::nullopt), ter(temMALFORMED)); } @@ -161,12 +151,7 @@ class AMMClawback_test : public beast::unit_test::suite // The Asset's issuer subfield is gw account and Amount's issuer // subfield is alice account. Return temBAD_AMOUNT because // they do not match. - env(amm::ammClawback( - gw, - alice, - USD, - XRP, - STAmount{Issue{gw["USD"].currency, alice.id()}, 1}), + env(amm::ammClawback(gw, alice, USD, XRP, STAmount{Issue{gw["USD"].currency, alice.id()}, 1}), ter(temBAD_AMOUNT)); } @@ -192,21 +177,11 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, gw, XRP(100), USD(100), ter(tesSUCCESS)); // Return temBAD_AMOUNT if the Amount value is less than 0. - env(amm::ammClawback( - gw, - alice, - USD, - XRP, - STAmount{Issue{gw["USD"].currency, gw.id()}, -1}), + env(amm::ammClawback(gw, alice, USD, XRP, STAmount{Issue{gw["USD"].currency, gw.id()}, -1}), ter(temBAD_AMOUNT)); // Return temBAD_AMOUNT if the Amount value is 0. - env(amm::ammClawback( - gw, - alice, - USD, - XRP, - STAmount{Issue{gw["USD"].currency, gw.id()}, 0}), + env(amm::ammClawback(gw, alice, USD, XRP, STAmount{Issue{gw["USD"].currency, gw.id()}, 0}), ter(temBAD_AMOUNT)); } @@ -232,8 +207,7 @@ class AMMClawback_test : public beast::unit_test::suite // If asfAllowTrustLineClawback is not set, the issuer is not // allowed to send the AMMClawback transaction. - env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), - ter(tecNO_PERMISSION)); + env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), ter(tecNO_PERMISSION)); } // Test invalid flag. @@ -258,9 +232,7 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, gw, XRP(100), USD(100), ter(tesSUCCESS)); // Return temINVALID_FLAG when providing invalid flag. - env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), - txflags(tfTwoAssetIfEmpty), - ter(temINVALID_FLAG)); + env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), txflags(tfTwoAssetIfEmpty), ter(temINVALID_FLAG)); } // Test if tfClawTwoAssets is set when the two assets in the AMM pool @@ -290,9 +262,7 @@ class AMMClawback_test : public beast::unit_test::suite // but the issuer only issues USD in the pool. The issuer is not // allowed to set tfClawTwoAssets flag if he did not issue both // assets in the pool. - env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), - txflags(tfClawTwoAssets), - ter(temINVALID_FLAG)); + env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), txflags(tfClawTwoAssets), ter(temINVALID_FLAG)); } // Test clawing back XRP is being prohibited. @@ -319,8 +289,7 @@ class AMMClawback_test : public beast::unit_test::suite env.close(); // Clawback XRP is prohibited. - env(amm::ammClawback(gw, alice, XRP, USD, std::nullopt), - ter(temMALFORMED)); + env(amm::ammClawback(gw, alice, XRP, USD, std::nullopt), ter(temMALFORMED)); } } @@ -351,8 +320,7 @@ class AMMClawback_test : public beast::unit_test::suite // When featureAMMClawback is not enabled, AMMClawback is disabled. // Because when featureAMMClawback is disabled, we can not create // amm account, call amm::ammClawback directly for testing purpose. - env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), - ter(temDISABLED)); + env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), ter(temDISABLED)); } } @@ -397,12 +365,10 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, alice, EUR(1000), USD(2000), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT(amm.expectBalances( - USD(2000), EUR(1000), IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectBalances(USD(2000), EUR(1000), IOUAmount{1414213562373095, -12})); // gw clawback 1000 USD from the AMM pool. - env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); // Alice's initial balance for USD is 3000 USD. Alice deposited 2000 @@ -419,17 +385,14 @@ class AMMClawback_test : public beast::unit_test::suite // 1000 USD and 500 EUR was withdrawn from the AMM pool, so the // current balance is 1000 USD and 500 EUR. - BEAST_EXPECT(amm.expectBalances( - USD(1000), EUR(500), IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectBalances(USD(1000), EUR(500), IOUAmount{7071067811865475, -13})); // Alice has half of its initial lptokens Left. - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865475, -13})); // gw clawback another 1000 USD from the AMM pool. The AMM pool will // be empty and get deleted. - env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); // Alice should still has 1000 USD because gw clawed back from the @@ -472,14 +435,12 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, alice, XRP(1000), USD(2000), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT(amm.expectBalances( - USD(2000), XRP(1000), IOUAmount{1414213562373095, -9})); + BEAST_EXPECT(amm.expectBalances(USD(2000), XRP(1000), IOUAmount{1414213562373095, -9})); auto aliceXrpBalance = env.balance(alice, XRP); // gw clawback 1000 USD from the AMM pool. - env(amm::ammClawback(gw, alice, USD, XRP, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, XRP, USD(1000)), ter(tesSUCCESS)); env.close(); // Alice's initial balance for USD is 3000 USD. Alice deposited 2000 @@ -489,23 +450,19 @@ class AMMClawback_test : public beast::unit_test::suite env.require(balance(alice, USD(1000))); // Alice will get 500 XRP back. - BEAST_EXPECT( - expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(500))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(500))); aliceXrpBalance = env.balance(alice, XRP); // 1000 USD and 500 XRP was withdrawn from the AMM pool, so the // current balance is 1000 USD and 500 XRP. - BEAST_EXPECT(amm.expectBalances( - USD(1000), XRP(500), IOUAmount{7071067811865475, -10})); + BEAST_EXPECT(amm.expectBalances(USD(1000), XRP(500), IOUAmount{7071067811865475, -10})); // Alice has half of its initial lptokens Left. - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{7071067811865475, -10})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865475, -10})); // gw clawback another 1000 USD from the AMM pool. The AMM pool will // be empty and get deleted. - env(amm::ammClawback(gw, alice, USD, XRP, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, XRP, USD(1000)), ter(tesSUCCESS)); env.close(); // Alice should still has 1000 USD because gw clawed back from the @@ -514,8 +471,7 @@ class AMMClawback_test : public beast::unit_test::suite env.require(balance(alice, USD(1000))); // Alice will get another 500 XRP back. - BEAST_EXPECT( - expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(500))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(500))); // amm is automatically deleted. BEAST_EXPECT(!amm.ammExists()); @@ -566,15 +522,12 @@ class AMMClawback_test : public beast::unit_test::suite env.close(); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(4000), EUR(5000), IOUAmount{4472135954999580, -12})); + BEAST_EXPECT(amm.expectBalances(USD(4000), EUR(5000), IOUAmount{4472135954999580, -12})); else - BEAST_EXPECT(amm.expectBalances( - USD(4000), EUR(5000), IOUAmount{4472135954999579, -12})); + BEAST_EXPECT(amm.expectBalances(USD(4000), EUR(5000), IOUAmount{4472135954999579, -12})); // gw clawback 1000 USD from the AMM pool - env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); // Alice's initial balance for USD is 6000 USD. Alice deposited 4000 @@ -590,23 +543,18 @@ class AMMClawback_test : public beast::unit_test::suite // 1000 USD and 1250 EUR was withdrawn from the AMM pool, so the // current balance is 3000 USD and 3750 EUR. if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(3000), EUR(3750), IOUAmount{3354101966249685, -12})); + BEAST_EXPECT(amm.expectBalances(USD(3000), EUR(3750), IOUAmount{3354101966249685, -12})); else - BEAST_EXPECT(amm.expectBalances( - USD(3000), EUR(3750), IOUAmount{3354101966249684, -12})); + BEAST_EXPECT(amm.expectBalances(USD(3000), EUR(3750), IOUAmount{3354101966249684, -12})); // Alice has 3/4 of its initial lptokens Left. if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{3354101966249685, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{3354101966249685, -12})); else - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{3354101966249684, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{3354101966249684, -12})); // gw clawback another 500 USD from the AMM pool. - env(amm::ammClawback(gw, alice, USD, EUR, USD(500)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(500)), ter(tesSUCCESS)); env.close(); // Alice should still has 2000 USD because gw clawed back from the @@ -619,13 +567,10 @@ class AMMClawback_test : public beast::unit_test::suite STAmount{EUR, UINT64_C(3125000000000001), -12}, IOUAmount{2795084971874738, -12})); else - BEAST_EXPECT(amm.expectBalances( - USD(2500), EUR(3125), IOUAmount{2795084971874737, -12})); + BEAST_EXPECT(amm.expectBalances(USD(2500), EUR(3125), IOUAmount{2795084971874737, -12})); if (!features[fixAMMv1_3]) - BEAST_EXPECT( - env.balance(alice, EUR) == - STAmount(EUR, UINT64_C(2874999999999999), -12)); + BEAST_EXPECT(env.balance(alice, EUR) == STAmount(EUR, UINT64_C(2874999999999999), -12)); else BEAST_EXPECT(env.balance(alice, EUR) == EUR(2875)); @@ -642,8 +587,7 @@ class AMMClawback_test : public beast::unit_test::suite STAmount{EUR, UINT64_C(3123750000000002), -12}, IOUAmount{2793966937885989, -12})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectBalances( - USD(2499), EUR(3123.75), IOUAmount{2793966937885987, -12})); + BEAST_EXPECT(amm.expectBalances(USD(2499), EUR(3123.75), IOUAmount{2793966937885987, -12})); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) BEAST_EXPECT(amm.expectBalances( STAmount{USD, UINT64_C(2499000000000001), -12}, @@ -651,28 +595,21 @@ class AMMClawback_test : public beast::unit_test::suite IOUAmount{2793966937885988, -12})); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT( - env.balance(alice, EUR) == - STAmount(EUR, UINT64_C(2876'249999999998), -12)); + BEAST_EXPECT(env.balance(alice, EUR) == STAmount(EUR, UINT64_C(2876'249999999998), -12)); else if (!features[fixAMMClawbackRounding]) BEAST_EXPECT(env.balance(alice, EUR) == EUR(2876.25)); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) - BEAST_EXPECT( - env.balance(alice, EUR) == - STAmount(EUR, UINT64_C(2876'249999999999), -12)); + BEAST_EXPECT(env.balance(alice, EUR) == STAmount(EUR, UINT64_C(2876'249999999999), -12)); // gw clawback 4000 USD, exceeding the current balance. We // will clawback all. - env(amm::ammClawback(gw, alice, USD, EUR, USD(4000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(4000)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, USD(2000))); // All alice's EUR in the pool goes back to alice. - BEAST_EXPECT( - env.balance(alice, EUR) == - STAmount(EUR, UINT64_C(6000000000000000), -12)); + BEAST_EXPECT(env.balance(alice, EUR) == STAmount(EUR, UINT64_C(6000000000000000), -12)); // amm is automatically deleted. BEAST_EXPECT(!amm.ammExists()); @@ -720,48 +657,38 @@ class AMMClawback_test : public beast::unit_test::suite // gw creates AMM pool of XRP/USD, alice and bob deposit XRP/USD. AMM amm(env, gw, XRP(2000), USD(1000), ter(tesSUCCESS)); - BEAST_EXPECT(amm.expectBalances( - USD(1000), XRP(2000), IOUAmount{1414213562373095, -9})); + BEAST_EXPECT(amm.expectBalances(USD(1000), XRP(2000), IOUAmount{1414213562373095, -9})); amm.deposit(alice, USD(1000), XRP(2000)); - BEAST_EXPECT(amm.expectBalances( - USD(2000), XRP(4000), IOUAmount{2828427124746190, -9})); + BEAST_EXPECT(amm.expectBalances(USD(2000), XRP(4000), IOUAmount{2828427124746190, -9})); amm.deposit(bob, USD(1000), XRP(2000)); - BEAST_EXPECT(amm.expectBalances( - USD(3000), XRP(6000), IOUAmount{4242640687119285, -9})); + BEAST_EXPECT(amm.expectBalances(USD(3000), XRP(6000), IOUAmount{4242640687119285, -9})); env.close(); // gw2 creates AMM pool of XRP/EUR, alice and bob deposit XRP/EUR. AMM amm2(env, gw2, XRP(3000), EUR(1000), ter(tesSUCCESS)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm2.expectBalances( - EUR(1000), XRP(3000), IOUAmount{1732050807568878, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(1000), XRP(3000), IOUAmount{1732050807568878, -9})); else - BEAST_EXPECT(amm2.expectBalances( - EUR(1000), XRP(3000), IOUAmount{1732050807568877, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(1000), XRP(3000), IOUAmount{1732050807568877, -9})); amm2.deposit(alice, EUR(1000), XRP(3000)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm2.expectBalances( - EUR(2000), XRP(6000), IOUAmount{3464101615137756, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(2000), XRP(6000), IOUAmount{3464101615137756, -9})); else - BEAST_EXPECT(amm2.expectBalances( - EUR(2000), XRP(6000), IOUAmount{3464101615137754, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(2000), XRP(6000), IOUAmount{3464101615137754, -9})); amm2.deposit(bob, EUR(1000), XRP(3000)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm2.expectBalances( - EUR(3000), XRP(9000), IOUAmount{5196152422706634, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(3000), XRP(9000), IOUAmount{5196152422706634, -9})); else - BEAST_EXPECT(amm2.expectBalances( - EUR(3000), XRP(9000), IOUAmount{5196152422706631, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(3000), XRP(9000), IOUAmount{5196152422706631, -9})); env.close(); auto aliceXrpBalance = env.balance(alice, XRP); auto bobXrpBalance = env.balance(bob, XRP); // gw clawback 500 USD from alice in amm - env(amm::ammClawback(gw, alice, USD, XRP, USD(500)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, XRP, USD(500)), ter(tesSUCCESS)); env.close(); // Alice's initial balance for USD is 6000 USD. Alice deposited 1000 @@ -774,37 +701,26 @@ class AMMClawback_test : public beast::unit_test::suite // Alice gets 1000 XRP back. if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(1000) - XRPAmount(1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(1000) - XRPAmount(1))); else - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(1000))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(1000))); aliceXrpBalance = env.balance(alice, XRP); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectBalances( - USD(2500), XRP(5000), IOUAmount{3535533905932738, -9})); + BEAST_EXPECT(amm.expectBalances(USD(2500), XRP(5000), IOUAmount{3535533905932738, -9})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectBalances( - USD(2500), XRP(5000), IOUAmount{3535533905932737, -9})); + BEAST_EXPECT(amm.expectBalances(USD(2500), XRP(5000), IOUAmount{3535533905932737, -9})); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(2500), - XRPAmount(5000000001), - IOUAmount{3'535'533'905932738, -9})); + BEAST_EXPECT(amm.expectBalances(USD(2500), XRPAmount(5000000001), IOUAmount{3'535'533'905932738, -9})); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{7071067811865480, -10})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865480, -10})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{7071067811865474, -10})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865474, -10})); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{707106781186548, -9})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{707106781186548, -9})); - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{1414213562373095, -9})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{1414213562373095, -9})); // gw clawback 10 USD from bob in amm. env(amm::ammClawback(gw, bob, USD, XRP, USD(10)), ter(tesSUCCESS)); @@ -814,18 +730,14 @@ class AMMClawback_test : public beast::unit_test::suite env.require(balance(bob, USD(4000))); // Bob gets 20 XRP back. - BEAST_EXPECT( - expectLedgerEntryRoot(env, bob, bobXrpBalance + XRP(20))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, bobXrpBalance + XRP(20))); bobXrpBalance = env.balance(bob, XRP); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) BEAST_EXPECT(amm.expectBalances( - STAmount{USD, UINT64_C(2490000000000001), -12}, - XRP(4980), - IOUAmount{3521391770309008, -9})); + STAmount{USD, UINT64_C(2490000000000001), -12}, XRP(4980), IOUAmount{3521391770309008, -9})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectBalances( - USD(2'490), XRP(4980), IOUAmount{3521391770309006, -9})); + BEAST_EXPECT(amm.expectBalances(USD(2'490), XRP(4980), IOUAmount{3521391770309006, -9})); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) BEAST_EXPECT(amm.expectBalances( STAmount{USD, UINT64_C(2490000000000001), -12}, @@ -833,74 +745,54 @@ class AMMClawback_test : public beast::unit_test::suite IOUAmount{3521391'770309008, -9})); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{7071067811865480, -10})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865480, -10})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{7071067811865474, -10})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865474, -10})); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{707106781186548, -9})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{707106781186548, -9})); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{1400071426749365, -9})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{1400071426749365, -9})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{1400071426749364, -9})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{1400071426749364, -9})); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{1400071426749365, -9})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{1400071426749365, -9})); // gw2 clawback 200 EUR from amm2. - env(amm::ammClawback(gw2, alice, EUR, XRP, EUR(200)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw2, alice, EUR, XRP, EUR(200)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, EUR(4000))); env.require(balance(bob, EUR(3000))); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(600))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(600))); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(600))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(600))); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(600) - XRPAmount{1})); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(600) - XRPAmount{1})); aliceXrpBalance = env.balance(alice, XRP); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(2800), XRP(8400), IOUAmount{4849742261192859, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(2800), XRP(8400), IOUAmount{4849742261192859, -9})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(2800), XRP(8400), IOUAmount{4849742261192856, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(2800), XRP(8400), IOUAmount{4849742261192856, -9})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(2800), - XRPAmount(8400000001), - IOUAmount{4849742261192856, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(2800), XRPAmount(8400000001), IOUAmount{4849742261192856, -9})); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm2.expectLPTokens( - alice, IOUAmount{1385640646055103, -9})); + BEAST_EXPECT(amm2.expectLPTokens(alice, IOUAmount{1385640646055103, -9})); else - BEAST_EXPECT(amm2.expectLPTokens( - alice, IOUAmount{1385640646055102, -9})); + BEAST_EXPECT(amm2.expectLPTokens(alice, IOUAmount{1385640646055102, -9})); if (!features[fixAMMv1_3]) - BEAST_EXPECT( - amm2.expectLPTokens(bob, IOUAmount{1732050807568878, -9})); + BEAST_EXPECT(amm2.expectLPTokens(bob, IOUAmount{1732050807568878, -9})); else - BEAST_EXPECT( - amm2.expectLPTokens(bob, IOUAmount{1732050807568877, -9})); + BEAST_EXPECT(amm2.expectLPTokens(bob, IOUAmount{1732050807568877, -9})); // gw claw back 1000 USD from alice in amm, which exceeds alice's // balance. This will clawback all the remaining LP tokens of alice // (corresponding 500 USD / 1000 XRP). - env(amm::ammClawback(gw, alice, USD, XRP, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, XRP, USD(1000)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, USD(5000))); @@ -908,37 +800,26 @@ class AMMClawback_test : public beast::unit_test::suite // Alice gets 1000 XRP back. if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(1000))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(1000))); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(1000) - XRPAmount{1})); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(1000) - XRPAmount{1})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(1000))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(1000))); aliceXrpBalance = env.balance(alice, XRP); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(0))); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{1400071426749365, -9})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{1400071426749365, -9})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{1400071426749364, -9})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{1400071426749364, -9})); else if (features[fixAMMClawbackRounding] && features[fixAMMv1_3]) - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{1400071426749365, -9})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{1400071426749365, -9})); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) BEAST_EXPECT(amm.expectBalances( - STAmount{USD, UINT64_C(1990000000000001), -12}, - XRP(3980), - IOUAmount{2814284989122460, -9})); + STAmount{USD, UINT64_C(1990000000000001), -12}, XRP(3980), IOUAmount{2814284989122460, -9})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectBalances( - USD(1'990), - XRPAmount{3'980'000'001}, - IOUAmount{2814284989122459, -9})); + BEAST_EXPECT(amm.expectBalances(USD(1'990), XRPAmount{3'980'000'001}, IOUAmount{2814284989122459, -9})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) BEAST_EXPECT(amm.expectBalances( STAmount{USD, UINT64_C(1990000000000001), -12}, @@ -948,8 +829,7 @@ class AMMClawback_test : public beast::unit_test::suite // gw clawback 1000 USD from bob in amm, which also exceeds bob's // balance in amm. All bob's lptoken in amm will be consumed, which // corresponds to 990 USD / 1980 XRP - env(amm::ammClawback(gw, bob, USD, XRP, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, bob, USD, XRP, USD(1000)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, USD(5000))); @@ -957,8 +837,7 @@ class AMMClawback_test : public beast::unit_test::suite BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance)); - BEAST_EXPECT( - expectLedgerEntryRoot(env, bob, bobXrpBalance + XRP(1980))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, bobXrpBalance + XRP(1980))); bobXrpBalance = env.balance(bob, XRP); // Now neither alice nor bob has any lptoken in amm. @@ -968,8 +847,7 @@ class AMMClawback_test : public beast::unit_test::suite // gw2 claw back 1000 EUR from alice in amm2, which exceeds alice's // balance. All alice's lptokens will be consumed, which corresponds // to 800EUR / 2400 XRP. - env(amm::ammClawback(gw2, alice, EUR, XRP, EUR(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw2, alice, EUR, XRP, EUR(1000)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, EUR(4000))); @@ -977,8 +855,7 @@ class AMMClawback_test : public beast::unit_test::suite // Alice gets another 2400 XRP back, bob's XRP balance remains the // same. - BEAST_EXPECT( - expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(2400))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(2400))); BEAST_EXPECT(expectLedgerEntryRoot(env, bob, bobXrpBalance)); aliceXrpBalance = env.balance(alice, XRP); @@ -987,22 +864,16 @@ class AMMClawback_test : public beast::unit_test::suite BEAST_EXPECT(amm2.expectLPTokens(alice, IOUAmount(0))); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(2000), XRP(6000), IOUAmount{3464101615137756, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(2000), XRP(6000), IOUAmount{3464101615137756, -9})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(2000), XRP(6000), IOUAmount{3464101615137754, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(2000), XRP(6000), IOUAmount{3464101615137754, -9})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(2000), - XRPAmount(6000000001), - IOUAmount{3464101615137754, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(2000), XRPAmount(6000000001), IOUAmount{3464101615137754, -9})); // gw2 claw back 2000 EUR from bob in amm2, which exceeds bob's // balance. All bob's lptokens will be consumed, which corresponds // to 1000EUR / 3000 XRP. - env(amm::ammClawback(gw2, bob, EUR, XRP, EUR(2000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw2, bob, EUR, XRP, EUR(2000)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, EUR(4000))); @@ -1012,8 +883,7 @@ class AMMClawback_test : public beast::unit_test::suite // same. BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance)); - BEAST_EXPECT( - expectLedgerEntryRoot(env, bob, bobXrpBalance + XRP(3000))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, bobXrpBalance + XRP(3000))); bobXrpBalance = env.balance(bob, XRP); // Neither alice nor bob has any lptoken in amm2 @@ -1021,16 +891,11 @@ class AMMClawback_test : public beast::unit_test::suite BEAST_EXPECT(amm2.expectLPTokens(bob, IOUAmount(0))); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(1000), XRP(3000), IOUAmount{1732050807568878, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(1000), XRP(3000), IOUAmount{1732050807568878, -9})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(1000), XRP(3000), IOUAmount{1732050807568877, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(1000), XRP(3000), IOUAmount{1732050807568877, -9})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm2.expectBalances( - EUR(1000), - XRPAmount(3000000001), - IOUAmount{1732050807568877, -9})); + BEAST_EXPECT(amm2.expectBalances(EUR(1000), XRPAmount(3000000001), IOUAmount{1732050807568877, -9})); } } @@ -1089,44 +954,32 @@ class AMMClawback_test : public beast::unit_test::suite env.close(); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(4000), EUR(5000), IOUAmount{4472135954999580, -12})); + BEAST_EXPECT(amm.expectBalances(USD(4000), EUR(5000), IOUAmount{4472135954999580, -12})); else - BEAST_EXPECT(amm.expectBalances( - USD(4000), EUR(5000), IOUAmount{4472135954999579, -12})); + BEAST_EXPECT(amm.expectBalances(USD(4000), EUR(5000), IOUAmount{4472135954999579, -12})); amm.deposit(bob, USD(2000), EUR(2500)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(6000), EUR(7500), IOUAmount{6708203932499370, -12})); + BEAST_EXPECT(amm.expectBalances(USD(6000), EUR(7500), IOUAmount{6708203932499370, -12})); else - BEAST_EXPECT(amm.expectBalances( - USD(6000), EUR(7500), IOUAmount{6708203932499368, -12})); + BEAST_EXPECT(amm.expectBalances(USD(6000), EUR(7500), IOUAmount{6708203932499368, -12})); amm.deposit(carol, USD(1000), EUR(1250)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(7000), EUR(8750), IOUAmount{7826237921249265, -12})); + BEAST_EXPECT(amm.expectBalances(USD(7000), EUR(8750), IOUAmount{7826237921249265, -12})); else - BEAST_EXPECT(amm.expectBalances( - USD(7000), EUR(8750), IOUAmount{7826237921249262, -12})); + BEAST_EXPECT(amm.expectBalances(USD(7000), EUR(8750), IOUAmount{7826237921249262, -12})); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{4472135954999580, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4472135954999580, -12})); else - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{4472135954999579, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4472135954999579, -12})); if (!features[fixAMMv1_3]) - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{2236067977499790, -12})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{2236067977499790, -12})); else - BEAST_EXPECT( - amm.expectLPTokens(bob, IOUAmount{2236067977499789, -12})); + BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{2236067977499789, -12})); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectLPTokens( - carol, IOUAmount{1118033988749895, -12})); + BEAST_EXPECT(amm.expectLPTokens(carol, IOUAmount{1118033988749895, -12})); else - BEAST_EXPECT(amm.expectLPTokens( - carol, IOUAmount{1118033988749894, -12})); + BEAST_EXPECT(amm.expectLPTokens(carol, IOUAmount{1118033988749894, -12})); env.require(balance(alice, USD(2000))); env.require(balance(alice, EUR(1000))); @@ -1136,8 +989,7 @@ class AMMClawback_test : public beast::unit_test::suite env.require(balance(carol, EUR(2750))); // gw clawback all the bob's USD in amm. (2000 USD / 2500 EUR) - env(amm::ammClawback(gw, bob, USD, EUR, std::nullopt), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, bob, USD, EUR, std::nullopt), ter(tesSUCCESS)); env.close(); if (!features[fixAMMv1_3]) @@ -1152,40 +1004,29 @@ class AMMClawback_test : public beast::unit_test::suite IOUAmount{5590169943749473, -12})); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{4472135954999580, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4472135954999580, -12})); else - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{4472135954999579, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4472135954999579, -12})); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(0))); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectLPTokens( - carol, IOUAmount{1118033988749895, -12})); + BEAST_EXPECT(amm.expectLPTokens(carol, IOUAmount{1118033988749895, -12})); else - BEAST_EXPECT(amm.expectLPTokens( - carol, IOUAmount{1118033988749894, -12})); + BEAST_EXPECT(amm.expectLPTokens(carol, IOUAmount{1118033988749894, -12})); // Bob will get 2500 EUR back. env.require(balance(alice, USD(2000))); env.require(balance(alice, EUR(1000))); - BEAST_EXPECT( - env.balance(bob, USD) == - STAmount(USD, UINT64_C(3000000000000000), -12)); + BEAST_EXPECT(env.balance(bob, USD) == STAmount(USD, UINT64_C(3000000000000000), -12)); if (!features[fixAMMv1_3]) - BEAST_EXPECT( - env.balance(bob, EUR) == - STAmount(EUR, UINT64_C(5000000000000001), -12)); + BEAST_EXPECT(env.balance(bob, EUR) == STAmount(EUR, UINT64_C(5000000000000001), -12)); else - BEAST_EXPECT( - env.balance(bob, EUR) == - STAmount(EUR, UINT64_C(4999999999999999), -12)); + BEAST_EXPECT(env.balance(bob, EUR) == STAmount(EUR, UINT64_C(4999999999999999), -12)); env.require(balance(carol, USD(3000))); env.require(balance(carol, EUR(2750))); // gw2 clawback all carol's EUR in amm. (1000 USD / 1250 EUR) - env(amm::ammClawback(gw2, carol, EUR, USD, std::nullopt), - ter(tesSUCCESS)); + env(amm::ammClawback(gw2, carol, EUR, USD, std::nullopt), ter(tesSUCCESS)); env.close(); if (!features[fixAMMv1_3]) BEAST_EXPECT(amm.expectBalances( @@ -1199,17 +1040,14 @@ class AMMClawback_test : public beast::unit_test::suite IOUAmount{4472135954999579, -12})); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{4472135954999580, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4472135954999580, -12})); else - BEAST_EXPECT(amm.expectLPTokens( - alice, IOUAmount{4472135954999579, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4472135954999579, -12})); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(0))); BEAST_EXPECT(amm.expectLPTokens(carol, IOUAmount(0))); // gw2 clawback all alice's EUR in amm. (4000 USD / 5000 EUR) - env(amm::ammClawback(gw2, alice, EUR, USD, std::nullopt), - ter(tesSUCCESS)); + env(amm::ammClawback(gw2, alice, EUR, USD, std::nullopt), ter(tesSUCCESS)); env.close(); env.require(balance(carol, EUR(2750))); @@ -1243,64 +1081,45 @@ class AMMClawback_test : public beast::unit_test::suite // gw creates AMM pool of XRP/USD, alice and bob deposit XRP/USD. AMM amm(env, gw, XRP(2000), USD(10000), ter(tesSUCCESS)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(10000), XRP(2000), IOUAmount{4472135954999580, -9})); + BEAST_EXPECT(amm.expectBalances(USD(10000), XRP(2000), IOUAmount{4472135954999580, -9})); else - BEAST_EXPECT(amm.expectBalances( - USD(10000), XRP(2000), IOUAmount{4472135954999579, -9})); + BEAST_EXPECT(amm.expectBalances(USD(10000), XRP(2000), IOUAmount{4472135954999579, -9})); amm.deposit(alice, USD(1000), XRP(200)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(11000), XRP(2200), IOUAmount{4919349550499538, -9})); + BEAST_EXPECT(amm.expectBalances(USD(11000), XRP(2200), IOUAmount{4919349550499538, -9})); else - BEAST_EXPECT(amm.expectBalances( - USD(11000), XRP(2200), IOUAmount{4919349550499536, -9})); + BEAST_EXPECT(amm.expectBalances(USD(11000), XRP(2200), IOUAmount{4919349550499536, -9})); amm.deposit(bob, USD(2000), XRP(400)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(13000), XRP(2600), IOUAmount{5813776741499453, -9})); + BEAST_EXPECT(amm.expectBalances(USD(13000), XRP(2600), IOUAmount{5813776741499453, -9})); else - BEAST_EXPECT(amm.expectBalances( - USD(13000), XRP(2600), IOUAmount{5813776741499451, -9})); + BEAST_EXPECT(amm.expectBalances(USD(13000), XRP(2600), IOUAmount{5813776741499451, -9})); env.close(); auto aliceXrpBalance = env.balance(alice, XRP); auto bobXrpBalance = env.balance(bob, XRP); // gw clawback all alice's USD in amm. (1000 USD / 200 XRP) - env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), ter(tesSUCCESS)); env.close(); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(12000), XRP(2400), IOUAmount{5366563145999495, -9})); + BEAST_EXPECT(amm.expectBalances(USD(12000), XRP(2400), IOUAmount{5366563145999495, -9})); else - BEAST_EXPECT(amm.expectBalances( - USD(12000), - XRPAmount(2400000001), - IOUAmount{5366563145999494, -9})); + BEAST_EXPECT(amm.expectBalances(USD(12000), XRPAmount(2400000001), IOUAmount{5366563145999494, -9})); if (!features[fixAMMv1_3]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(200))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(200))); else - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(200) - XRPAmount{1})); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(200) - XRPAmount{1})); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(0))); // gw clawback all bob's USD in amm. (2000 USD / 400 XRP) - env(amm::ammClawback(gw, bob, USD, XRP, std::nullopt), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, bob, USD, XRP, std::nullopt), ter(tesSUCCESS)); env.close(); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - USD(10000), XRP(2000), IOUAmount{4472135954999580, -9})); + BEAST_EXPECT(amm.expectBalances(USD(10000), XRP(2000), IOUAmount{4472135954999580, -9})); else - BEAST_EXPECT(amm.expectBalances( - USD(10000), - XRPAmount(2000000001), - IOUAmount{4472135954999579, -9})); - BEAST_EXPECT( - expectLedgerEntryRoot(env, bob, bobXrpBalance + XRP(400))); + BEAST_EXPECT(amm.expectBalances(USD(10000), XRPAmount(2000000001), IOUAmount{4472135954999579, -9})); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, bobXrpBalance + XRP(400))); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(0))); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(0))); } @@ -1352,19 +1171,16 @@ class AMMClawback_test : public beast::unit_test::suite BEAST_EXPECT(amm.expectBalances(USD(8000), EUR(2000), IOUAmount(4000))); amm.deposit(bob, USD(4000), EUR(1000)); - BEAST_EXPECT( - amm.expectBalances(USD(12000), EUR(3000), IOUAmount(6000))); + BEAST_EXPECT(amm.expectBalances(USD(12000), EUR(3000), IOUAmount(6000))); if (!features[fixAMMv1_3]) amm.deposit(carol, USD(2000), EUR(500)); else amm.deposit(carol, USD(2000.25), EUR(500)); - BEAST_EXPECT( - amm.expectBalances(USD(14000), EUR(3500), IOUAmount(7000))); + BEAST_EXPECT(amm.expectBalances(USD(14000), EUR(3500), IOUAmount(7000))); // gw clawback 1000 USD from carol. env(amm::ammClawback(gw, carol, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT( - amm.expectBalances(USD(13000), EUR(3250), IOUAmount(6500))); + BEAST_EXPECT(amm.expectBalances(USD(13000), EUR(3250), IOUAmount(6500))); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(4000))); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(2000))); @@ -1376,21 +1192,16 @@ class AMMClawback_test : public beast::unit_test::suite if (!features[fixAMMv1_3]) BEAST_EXPECT(env.balance(carol, USD) == USD(6000)); else - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(5999'999999999999), -12)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(5999'999999999999), -12)); // 250 EUR goes back to carol. BEAST_EXPECT(env.balance(carol, EUR) == EUR(7750)); // gw clawback 1000 USD from bob with tfClawTwoAssets flag. // then the corresponding EUR will also be clawed back // by gw. - env(amm::ammClawback(gw, bob, USD, EUR, USD(1000)), - txflags(tfClawTwoAssets), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, bob, USD, EUR, USD(1000)), txflags(tfClawTwoAssets), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT( - amm.expectBalances(USD(12000), EUR(3000), IOUAmount(6000))); + BEAST_EXPECT(amm.expectBalances(USD(12000), EUR(3000), IOUAmount(6000))); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(4000))); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(1500))); @@ -1403,15 +1214,11 @@ class AMMClawback_test : public beast::unit_test::suite if (!features[fixAMMv1_3]) BEAST_EXPECT(env.balance(carol, USD) == USD(6000)); else - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(5999'999999999999), -12)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(5999'999999999999), -12)); BEAST_EXPECT(env.balance(carol, EUR) == EUR(7750)); // gw clawback all USD from alice and set tfClawTwoAssets. - env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), - txflags(tfClawTwoAssets), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), txflags(tfClawTwoAssets), ter(tesSUCCESS)); env.close(); BEAST_EXPECT(amm.expectBalances(USD(4000), EUR(1000), IOUAmount(2000))); @@ -1425,9 +1232,7 @@ class AMMClawback_test : public beast::unit_test::suite if (!features[fixAMMv1_3]) BEAST_EXPECT(env.balance(carol, USD) == USD(6000)); else - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(5999'999999999999), -12)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(5999'999999999999), -12)); BEAST_EXPECT(env.balance(carol, EUR) == EUR(7750)); } @@ -1473,64 +1278,37 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, alice, gw["USD"](1000), gw2["USD"](1500), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT(amm.expectBalances( - gw["USD"](1000), - gw2["USD"](1500), - IOUAmount{1224744871391589, -12})); + BEAST_EXPECT(amm.expectBalances(gw["USD"](1000), gw2["USD"](1500), IOUAmount{1224744871391589, -12})); amm.deposit(bob, gw["USD"](2000), gw2["USD"](3000)); - BEAST_EXPECT(amm.expectBalances( - gw["USD"](3000), - gw2["USD"](4500), - IOUAmount{3674234614174767, -12})); + BEAST_EXPECT(amm.expectBalances(gw["USD"](3000), gw2["USD"](4500), IOUAmount{3674234614174767, -12})); // Issuer does not match with asset. - env(amm::ammClawback( - gw, - alice, - gw2["USD"], - gw["USD"], - STAmount{Issue{gw2["USD"].currency, gw2.id()}, 500}), + env(amm::ammClawback(gw, alice, gw2["USD"], gw["USD"], STAmount{Issue{gw2["USD"].currency, gw2.id()}, 500}), ter(temMALFORMED)); // gw2 clawback 500 gw2[USD] from alice. - env(amm::ammClawback( - gw2, - alice, - gw2["USD"], - gw["USD"], - STAmount{Issue{gw2["USD"].currency, gw2.id()}, 500}), + env(amm::ammClawback(gw2, alice, gw2["USD"], gw["USD"], STAmount{Issue{gw2["USD"].currency, gw2.id()}, 500}), ter(tesSUCCESS)); env.close(); BEAST_EXPECT(amm.expectBalances( - STAmount{gw["USD"], UINT64_C(2666666666666667), -12}, - gw2["USD"](4000), - IOUAmount{3265986323710904, -12})); + STAmount{gw["USD"], UINT64_C(2666666666666667), -12}, gw2["USD"](4000), IOUAmount{3265986323710904, -12})); - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{8164965809277260, -13})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{8164965809277260, -13})); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount{2449489742783178, -12})); - BEAST_EXPECT( - env.balance(alice, gw["USD"]) == - STAmount(gw["USD"], UINT64_C(7333333333333333), -12)); + BEAST_EXPECT(env.balance(alice, gw["USD"]) == STAmount(gw["USD"], UINT64_C(7333333333333333), -12)); BEAST_EXPECT(env.balance(alice, gw2["USD"]) == gw2["USD"](4500)); BEAST_EXPECT(env.balance(bob, gw["USD"]) == gw["USD"](5000)); BEAST_EXPECT(env.balance(bob, gw2["USD"]) == gw2["USD"](2000)); // gw clawback all gw["USD"] from bob. - env(amm::ammClawback(gw, bob, gw["USD"], gw2["USD"], std::nullopt), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, bob, gw["USD"], gw2["USD"], std::nullopt), ter(tesSUCCESS)); env.close(); BEAST_EXPECT(amm.expectBalances( - STAmount{gw["USD"], UINT64_C(6666666666666670), -13}, - gw2["USD"](1000), - IOUAmount{8164965809277260, -13})); + STAmount{gw["USD"], UINT64_C(6666666666666670), -13}, gw2["USD"](1000), IOUAmount{8164965809277260, -13})); - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{8164965809277260, -13})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{8164965809277260, -13})); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(0))); - BEAST_EXPECT( - env.balance(alice, gw["USD"]) == - STAmount(gw["USD"], UINT64_C(7333333333333333), -12)); + BEAST_EXPECT(env.balance(alice, gw["USD"]) == STAmount(gw["USD"], UINT64_C(7333333333333333), -12)); BEAST_EXPECT(env.balance(alice, gw2["USD"]) == gw2["USD"](4500)); BEAST_EXPECT(env.balance(bob, gw["USD"]) == gw["USD"](5000)); // Bob gets 3000 gw2["USD"] back and now his balance is 5000. @@ -1577,41 +1355,32 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, gw, USD(1000), EUR(2000), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT(amm.expectBalances( - USD(1000), EUR(2000), IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectBalances(USD(1000), EUR(2000), IOUAmount{1414213562373095, -12})); amm.deposit(gw2, USD(2000), EUR(4000)); - BEAST_EXPECT(amm.expectBalances( - USD(3000), EUR(6000), IOUAmount{4242640687119285, -12})); + BEAST_EXPECT(amm.expectBalances(USD(3000), EUR(6000), IOUAmount{4242640687119285, -12})); amm.deposit(alice, USD(3000), EUR(6000)); - BEAST_EXPECT(amm.expectBalances( - USD(6000), EUR(12000), IOUAmount{8485281374238570, -12})); + BEAST_EXPECT(amm.expectBalances(USD(6000), EUR(12000), IOUAmount{8485281374238570, -12})); BEAST_EXPECT(amm.expectLPTokens(gw, IOUAmount{1414213562373095, -12})); BEAST_EXPECT(amm.expectLPTokens(gw2, IOUAmount{2828427124746190, -12})); - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{4242640687119285, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4242640687119285, -12})); // gw claws back 1000 USD from gw2. env(amm::ammClawback(gw, gw2, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); if (!features[fixAMMv1_3] || !features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectBalances( - USD(5000), EUR(10000), IOUAmount{7071067811865475, -12})); + BEAST_EXPECT(amm.expectBalances(USD(5000), EUR(10000), IOUAmount{7071067811865475, -12})); else - BEAST_EXPECT(amm.expectBalances( - USD(5000), EUR(10000), IOUAmount{7071067811865474, -12})); + BEAST_EXPECT(amm.expectBalances(USD(5000), EUR(10000), IOUAmount{7071067811865474, -12})); BEAST_EXPECT(amm.expectLPTokens(gw, IOUAmount{1414213562373095, -12})); if (!features[fixAMMv1_3] || !features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw2, IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectLPTokens(gw2, IOUAmount{1414213562373095, -12})); else - BEAST_EXPECT( - amm.expectLPTokens(gw2, IOUAmount{1414213562373094, -12})); - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{4242640687119285, -12})); + BEAST_EXPECT(amm.expectLPTokens(gw2, IOUAmount{1414213562373094, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4242640687119285, -12})); BEAST_EXPECT(env.balance(alice, USD) == USD(2000)); BEAST_EXPECT(env.balance(alice, EUR) == EUR(0)); @@ -1623,37 +1392,26 @@ class AMMClawback_test : public beast::unit_test::suite env.close(); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) BEAST_EXPECT(amm.expectBalances( - USD(4500), - STAmount(EUR, UINT64_C(9000000000000001), -12), - IOUAmount{6363961030678928, -12})); + USD(4500), STAmount(EUR, UINT64_C(9000000000000001), -12), IOUAmount{6363961030678928, -12})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectBalances( - USD(4500), EUR(9000), IOUAmount{6363961030678928, -12})); + BEAST_EXPECT(amm.expectBalances(USD(4500), EUR(9000), IOUAmount{6363961030678928, -12})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) BEAST_EXPECT(amm.expectBalances( - USD(4500), - STAmount(EUR, UINT64_C(9000000000000001), -12), - IOUAmount{6363961030678927, -12})); + USD(4500), STAmount(EUR, UINT64_C(9000000000000001), -12), IOUAmount{6363961030678927, -12})); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw, IOUAmount{7071067811865480, -13})); + BEAST_EXPECT(amm.expectLPTokens(gw, IOUAmount{7071067811865480, -13})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw, IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectLPTokens(gw, IOUAmount{7071067811865475, -13})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw, IOUAmount{7071067811865480, -13})); + BEAST_EXPECT(amm.expectLPTokens(gw, IOUAmount{7071067811865480, -13})); if (!features[fixAMMv1_3] || !features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw2, IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectLPTokens(gw2, IOUAmount{1414213562373095, -12})); else - BEAST_EXPECT( - amm.expectLPTokens(gw2, IOUAmount{1414213562373094, -12})); + BEAST_EXPECT(amm.expectLPTokens(gw2, IOUAmount{1414213562373094, -12})); - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{4242640687119285, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{4242640687119285, -12})); BEAST_EXPECT(env.balance(alice, USD) == USD(2000)); BEAST_EXPECT(env.balance(alice, EUR) == EUR(0)); @@ -1665,36 +1423,25 @@ class AMMClawback_test : public beast::unit_test::suite env.close(); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) BEAST_EXPECT(amm.expectBalances( - USD(2500), - STAmount(EUR, UINT64_C(5000000000000001), -12), - IOUAmount{3535533905932738, -12})); + USD(2500), STAmount(EUR, UINT64_C(5000000000000001), -12), IOUAmount{3535533905932738, -12})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT(amm.expectBalances( - USD(2500), EUR(5000), IOUAmount{3535533905932738, -12})); + BEAST_EXPECT(amm.expectBalances(USD(2500), EUR(5000), IOUAmount{3535533905932738, -12})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) BEAST_EXPECT(amm.expectBalances( - USD(2500), - STAmount(EUR, UINT64_C(5000000000000001), -12), - IOUAmount{3535533905932737, -12})); + USD(2500), STAmount(EUR, UINT64_C(5000000000000001), -12), IOUAmount{3535533905932737, -12})); if (!features[fixAMMv1_3] && !features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw, IOUAmount{7071067811865480, -13})); + BEAST_EXPECT(amm.expectLPTokens(gw, IOUAmount{7071067811865480, -13})); else if (!features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw, IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectLPTokens(gw, IOUAmount{7071067811865475, -13})); else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw, IOUAmount{7071067811865480, -13})); + BEAST_EXPECT(amm.expectLPTokens(gw, IOUAmount{7071067811865480, -13})); if (!features[fixAMMv1_3] || !features[fixAMMClawbackRounding]) - BEAST_EXPECT( - amm.expectLPTokens(gw2, IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectLPTokens(gw2, IOUAmount{1414213562373095, -12})); else - BEAST_EXPECT( - amm.expectLPTokens(gw2, IOUAmount{1414213562373094, -12})); - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectLPTokens(gw2, IOUAmount{1414213562373094, -12})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{1414213562373095, -12})); BEAST_EXPECT(env.balance(alice, USD) == USD(4000)); BEAST_EXPECT(env.balance(alice, EUR) == EUR(0)); @@ -1730,8 +1477,7 @@ class AMMClawback_test : public beast::unit_test::suite // Alice did not deposit in the amm pool. So AMMClawback from Alice // will fail. - env(amm::ammClawback(gw, alice, USD, XRP, USD(1000)), - ter(tecAMM_BALANCE)); + env(amm::ammClawback(gw, alice, USD, XRP, USD(1000)), ter(tecAMM_BALANCE)); } void @@ -1772,31 +1518,26 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, alice, EUR(1000), USD(2000), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT(amm.expectBalances( - USD(2000), EUR(1000), IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectBalances(USD(2000), EUR(1000), IOUAmount{1414213562373095, -12})); // freeze trustline env(trust(gw, alice["USD"](0), tfSetFreeze)); env.close(); // gw clawback 1000 USD from the AMM pool. - env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, USD(1000))); env.require(balance(alice, EUR(2500))); - BEAST_EXPECT(amm.expectBalances( - USD(1000), EUR(500), IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectBalances(USD(1000), EUR(500), IOUAmount{7071067811865475, -13})); // Alice has half of its initial lptokens Left. - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865475, -13})); // gw clawback another 1000 USD from the AMM pool. The AMM pool will // be empty and get deleted. - env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); // Alice should still has 1000 USD because gw clawed back from the @@ -1840,8 +1581,7 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, alice, EUR(1000), USD(2000), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT(amm.expectBalances( - USD(2000), EUR(1000), IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectBalances(USD(2000), EUR(1000), IOUAmount{1414213562373095, -12})); // freeze trustlines env(trust(gw, alice["USD"](0), tfSetFreeze)); @@ -1849,16 +1589,13 @@ class AMMClawback_test : public beast::unit_test::suite env.close(); // gw clawback 1000 USD from the AMM pool. - env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, USD(1000))); env.require(balance(alice, EUR(2500))); - BEAST_EXPECT(amm.expectBalances( - USD(1000), EUR(500), IOUAmount{7071067811865475, -13})); - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectBalances(USD(1000), EUR(500), IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865475, -13})); } // test gw global freeze. @@ -1893,24 +1630,20 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, alice, EUR(1000), USD(2000), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT(amm.expectBalances( - USD(2000), EUR(1000), IOUAmount{1414213562373095, -12})); + BEAST_EXPECT(amm.expectBalances(USD(2000), EUR(1000), IOUAmount{1414213562373095, -12})); // global freeze env(fset(gw, asfGlobalFreeze)); env.close(); // gw clawback 1000 USD from the AMM pool. - env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); env.require(balance(alice, USD(1000))); env.require(balance(alice, EUR(2500))); - BEAST_EXPECT(amm.expectBalances( - USD(1000), EUR(500), IOUAmount{7071067811865475, -13})); - BEAST_EXPECT( - amm.expectLPTokens(alice, IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectBalances(USD(1000), EUR(500), IOUAmount{7071067811865475, -13})); + BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{7071067811865475, -13})); } // Test both assets are issued by the same issuer. And issuer sets @@ -1950,28 +1683,23 @@ class AMMClawback_test : public beast::unit_test::suite AMM amm(env, alice, EUR(2000), USD(8000), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT( - amm.expectBalances(USD(8000), EUR(2000), IOUAmount(4000))); + BEAST_EXPECT(amm.expectBalances(USD(8000), EUR(2000), IOUAmount(4000))); amm.deposit(bob, USD(4000), EUR(1000)); - BEAST_EXPECT( - amm.expectBalances(USD(12000), EUR(3000), IOUAmount(6000))); + BEAST_EXPECT(amm.expectBalances(USD(12000), EUR(3000), IOUAmount(6000))); if (!features[fixAMMv1_3]) amm.deposit(carol, USD(2000), EUR(500)); else amm.deposit(carol, USD(2000.25), EUR(500)); - BEAST_EXPECT( - amm.expectBalances(USD(14000), EUR(3500), IOUAmount(7000))); + BEAST_EXPECT(amm.expectBalances(USD(14000), EUR(3500), IOUAmount(7000))); // global freeze env(fset(gw, asfGlobalFreeze)); env.close(); // gw clawback 1000 USD from carol. - env(amm::ammClawback(gw, carol, USD, EUR, USD(1000)), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, carol, USD, EUR, USD(1000)), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT( - amm.expectBalances(USD(13000), EUR(3250), IOUAmount(6500))); + BEAST_EXPECT(amm.expectBalances(USD(13000), EUR(3250), IOUAmount(6500))); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(4000))); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(2000))); @@ -1983,21 +1711,16 @@ class AMMClawback_test : public beast::unit_test::suite if (!features[fixAMMv1_3]) BEAST_EXPECT(env.balance(carol, USD) == USD(6000)); else - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(5999'999999999999), -12)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(5999'999999999999), -12)); // 250 EUR goes back to carol. BEAST_EXPECT(env.balance(carol, EUR) == EUR(7750)); // gw clawback 1000 USD from bob with tfClawTwoAssets flag. // then the corresponding EUR will also be clawed back // by gw. - env(amm::ammClawback(gw, bob, USD, EUR, USD(1000)), - txflags(tfClawTwoAssets), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, bob, USD, EUR, USD(1000)), txflags(tfClawTwoAssets), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT( - amm.expectBalances(USD(12000), EUR(3000), IOUAmount(6000))); + BEAST_EXPECT(amm.expectBalances(USD(12000), EUR(3000), IOUAmount(6000))); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(4000))); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(1500))); @@ -2010,18 +1733,13 @@ class AMMClawback_test : public beast::unit_test::suite if (!features[fixAMMv1_3]) BEAST_EXPECT(env.balance(carol, USD) == USD(6000)); else - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(5999'999999999999), -12)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(5999'999999999999), -12)); BEAST_EXPECT(env.balance(carol, EUR) == EUR(7750)); // gw clawback all USD from alice and set tfClawTwoAssets. - env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), - txflags(tfClawTwoAssets), - ter(tesSUCCESS)); + env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), txflags(tfClawTwoAssets), ter(tesSUCCESS)); env.close(); - BEAST_EXPECT( - amm.expectBalances(USD(4000), EUR(1000), IOUAmount(2000))); + BEAST_EXPECT(amm.expectBalances(USD(4000), EUR(1000), IOUAmount(2000))); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(0))); BEAST_EXPECT(amm.expectLPTokens(bob, IOUAmount(1500))); @@ -2033,9 +1751,7 @@ class AMMClawback_test : public beast::unit_test::suite if (!features[fixAMMv1_3]) BEAST_EXPECT(env.balance(carol, USD) == USD(6000)); else - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(5999'999999999999), -12)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(5999'999999999999), -12)); BEAST_EXPECT(env.balance(carol, EUR) == EUR(7750)); } } @@ -2076,8 +1792,7 @@ class AMMClawback_test : public beast::unit_test::suite amm.deposit(alice, USD(400)); env.close(); - BEAST_EXPECT(amm.expectBalances( - USD(800), XRP(100), IOUAmount{2828427124746190, -10})); + BEAST_EXPECT(amm.expectBalances(USD(800), XRP(100), IOUAmount{2828427124746190, -10})); auto aliceXrpBalance = env.balance(alice, XRP); @@ -2085,22 +1800,16 @@ class AMMClawback_test : public beast::unit_test::suite env.close(); if (!features[fixAMMv1_3]) - BEAST_EXPECT(amm.expectBalances( - STAmount(USD, UINT64_C(5656854249492380), -13), - XRP(70.710678), - IOUAmount(200000))); + BEAST_EXPECT( + amm.expectBalances(STAmount(USD, UINT64_C(5656854249492380), -13), XRP(70.710678), IOUAmount(200000))); else - BEAST_EXPECT(amm.expectBalances( - STAmount(USD, UINT64_C(565'685424949238), -12), - XRP(70.710679), - IOUAmount(200000))); + BEAST_EXPECT( + amm.expectBalances(STAmount(USD, UINT64_C(565'685424949238), -12), XRP(70.710679), IOUAmount(200000))); BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount(0))); if (!features[fixAMMv1_3]) - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(29.289322))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(29.289322))); else - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, aliceXrpBalance + XRP(29.289321))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, aliceXrpBalance + XRP(29.289321))); } void @@ -2112,34 +1821,26 @@ class AMMClawback_test : public beast::unit_test::suite using namespace jtx; std::string logs; - auto setupAccounts = - [&](Env& env, Account& gw, Account& alice, Account& bob) { - env.fund(XRP(100000), gw, alice, bob); - env.close(); - env(fset(gw, asfAllowTrustLineClawback)); - env.close(); + auto setupAccounts = [&](Env& env, Account& gw, Account& alice, Account& bob) { + env.fund(XRP(100000), gw, alice, bob); + env.close(); + env(fset(gw, asfAllowTrustLineClawback)); + env.close(); - auto const USD = gw["USD"]; - env.trust(USD(100000), alice); - env(pay(gw, alice, USD(50000))); - env.trust(USD(100000), bob); - env(pay(gw, bob, USD(40000))); - env.close(); + auto const USD = gw["USD"]; + env.trust(USD(100000), alice); + env(pay(gw, alice, USD(50000))); + env.trust(USD(100000), bob); + env(pay(gw, bob, USD(40000))); + env.close(); - return USD; - }; + return USD; + }; auto getLPTokenBalances = - [&](auto& env, - auto const& amm, - auto const& account) -> std::pair { - auto const lpToken = - getAccountLines( - env, account, amm.lptIssue())[jss::lines][0u][jss::balance] - .asString(); - auto const lpTokenBalance = - amm.ammRpcInfo()[jss::amm][jss::lp_token][jss::value] - .asString(); + [&](auto& env, auto const& amm, auto const& account) -> std::pair { + auto const lpToken = getAccountLines(env, account, amm.lptIssue())[jss::lines][0u][jss::balance].asString(); + auto const lpTokenBalance = amm.ammRpcInfo()[jss::amm][jss::lp_token][jss::value].asString(); return {lpToken, lpTokenBalance}; }; @@ -2155,30 +1856,23 @@ class AMMClawback_test : public beast::unit_test::suite amm.withdraw(alice, IOUAmount{1'876123487565916, -15}); amm.withdrawAll(bob); - auto [lpToken, lpTokenBalance] = - getLPTokenBalances(env, amm, alice); - BEAST_EXPECT( - lpToken == "1414.21356237366" && - lpTokenBalance == "1414.213562374"); + auto [lpToken, lpTokenBalance] = getLPTokenBalances(env, amm, alice); + BEAST_EXPECT(lpToken == "1414.21356237366" && lpTokenBalance == "1414.213562374"); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); BEAST_EXPECT(res && res.value()); if (!features[fixAMMClawbackRounding] || !features[fixAMMv1_3]) { - env(amm::ammClawback(gw, alice, USD, XRP, USD(1)), - ter(tecAMM_BALANCE)); + env(amm::ammClawback(gw, alice, USD, XRP, USD(1)), ter(tecAMM_BALANCE)); BEAST_EXPECT(amm.ammExists()); } else { auto const lpBalance = IOUAmount{989, -12}; env(amm::ammClawback(gw, alice, USD, XRP, USD(1))); - BEAST_EXPECT(amm.expectBalances( - STAmount(USD, UINT64_C(7000000000000000), -28), - XRPAmount(1), - lpBalance)); + BEAST_EXPECT( + amm.expectBalances(STAmount(USD, UINT64_C(7000000000000000), -28), XRPAmount(1), lpBalance)); BEAST_EXPECT(amm.expectLPTokens(alice, lpBalance)); } } @@ -2194,14 +1888,10 @@ class AMMClawback_test : public beast::unit_test::suite amm.deposit(bob, IOUAmount{1'000'000}); amm.withdrawAll(bob); - auto [lpToken, lpTokenBalance] = - getLPTokenBalances(env, amm, alice); - BEAST_EXPECT( - lpToken == "1416.08968586066" && - lpTokenBalance == "1416.089685861"); + auto [lpToken, lpTokenBalance] = getLPTokenBalances(env, amm, alice); + BEAST_EXPECT(lpToken == "1416.08968586066" && lpTokenBalance == "1416.089685861"); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); BEAST_EXPECT(res && res.value()); env(amm::ammClawback(gw, alice, USD, XRP, USD(0.5))); @@ -2223,10 +1913,8 @@ class AMMClawback_test : public beast::unit_test::suite else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) { auto const lpBalance = IOUAmount{708'9829046743238, -13}; - BEAST_EXPECT(amm.expectBalances( - STAmount(USD, UINT64_C(5013266196406999), -16), - XRPAmount(1002655), - lpBalance)); + BEAST_EXPECT( + amm.expectBalances(STAmount(USD, UINT64_C(5013266196406999), -16), XRPAmount(1002655), lpBalance)); BEAST_EXPECT(amm.expectLPTokens(alice, lpBalance)); } } @@ -2243,28 +1931,21 @@ class AMMClawback_test : public beast::unit_test::suite amm.withdraw(alice, IOUAmount{1'876123487565916, -15}); amm.withdrawAll(bob); - auto [lpToken, lpTokenBalance] = - getLPTokenBalances(env, amm, alice); - BEAST_EXPECT( - lpToken == "1414.21356237366" && - lpTokenBalance == "1414.213562374"); + auto [lpToken, lpTokenBalance] = getLPTokenBalances(env, amm, alice); + BEAST_EXPECT(lpToken == "1414.21356237366" && lpTokenBalance == "1414.213562374"); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); BEAST_EXPECT(res && res.value()); if (!features[fixAMMClawbackRounding] && !features[fixAMMv1_3]) { - env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), - ter(tecAMM_BALANCE)); + env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt), ter(tecAMM_BALANCE)); } else if (!features[fixAMMClawbackRounding]) { env(amm::ammClawback(gw, alice, USD, XRP, std::nullopt)); BEAST_EXPECT(amm.expectBalances( - STAmount(USD, UINT64_C(2410000000000000), -28), - XRPAmount(1), - IOUAmount{34, -11})); + STAmount(USD, UINT64_C(2410000000000000), -28), XRPAmount(1), IOUAmount{34, -11})); } else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) { @@ -2295,14 +1976,10 @@ class AMMClawback_test : public beast::unit_test::suite amm.withdraw(alice, IOUAmount{1'576123487565916, -15}); amm.withdrawAll(bob); - auto [lpToken, lpTokenBalance] = - getLPTokenBalances(env, amm, alice); - BEAST_EXPECT( - lpToken == "1.414213562374011" && - lpTokenBalance == "1.414213562374"); + auto [lpToken, lpTokenBalance] = getLPTokenBalances(env, amm, alice); + BEAST_EXPECT(lpToken == "1.414213562374011" && lpTokenBalance == "1.414213562374"); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); BEAST_EXPECT(res && res.value()); if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) @@ -2312,8 +1989,7 @@ class AMMClawback_test : public beast::unit_test::suite } else { - env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), - ter(tecINTERNAL)); + env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), ter(tecINTERNAL)); BEAST_EXPECT(amm.ammExists()); } } @@ -2337,27 +2013,20 @@ class AMMClawback_test : public beast::unit_test::suite amm.withdraw(alice, IOUAmount{1'076123487565916, -15}); amm.withdrawAll(bob); - auto [lpToken, lpTokenBalance] = - getLPTokenBalances(env, amm, alice); - BEAST_EXPECT( - lpToken == "1.414213562374011" && - lpTokenBalance == "1.414213562374"); + auto [lpToken, lpTokenBalance] = getLPTokenBalances(env, amm, alice); + BEAST_EXPECT(lpToken == "1.414213562374011" && lpTokenBalance == "1.414213562374"); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); BEAST_EXPECT(res && res.value()); if (features[fixAMMClawbackRounding]) { - env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), - txflags(tfClawTwoAssets)); + env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), txflags(tfClawTwoAssets)); BEAST_EXPECT(!amm.ammExists()); } else { - env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), - txflags(tfClawTwoAssets), - ter(tecINTERNAL)); + env(amm::ammClawback(gw, alice, USD, EUR, std::nullopt), txflags(tfClawTwoAssets), ter(tecINTERNAL)); BEAST_EXPECT(amm.ammExists()); } } @@ -2381,42 +2050,32 @@ class AMMClawback_test : public beast::unit_test::suite amm.withdraw(alice, IOUAmount{1'076123487565916, -12}); amm.withdrawAll(bob); - auto [lpToken, lpTokenBalance] = - getLPTokenBalances(env, amm, alice); + auto [lpToken, lpTokenBalance] = getLPTokenBalances(env, amm, alice); - BEAST_EXPECT( - lpToken == "1414.213562373101" && - lpTokenBalance == "1414.2135623731"); + BEAST_EXPECT(lpToken == "1414.213562373101" && lpTokenBalance == "1414.2135623731"); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); BEAST_EXPECT(res && res.value()); if (!features[fixAMMClawbackRounding] && !features[fixAMMv1_3]) { env(amm::ammClawback(gw, alice, USD, EUR, USD(1))); BEAST_EXPECT(amm.expectBalances( - STAmount(USD, UINT64_C(4), -15), - STAmount(EUR, UINT64_C(8), -9), - IOUAmount{6, -12})); + STAmount(USD, UINT64_C(4), -15), STAmount(EUR, UINT64_C(8), -9), IOUAmount{6, -12})); } else if (!features[fixAMMClawbackRounding]) { // sqrt(amount * amount2) >= LPTokens and exceeds the allowed // tolerance - env(amm::ammClawback(gw, alice, USD, EUR, USD(1)), - ter(tecINVARIANT_FAILED)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1)), ter(tecINVARIANT_FAILED)); BEAST_EXPECT(amm.ammExists()); } else if (features[fixAMMv1_3] && features[fixAMMClawbackRounding]) { - env(amm::ammClawback(gw, alice, USD, EUR, USD(1)), - txflags(tfClawTwoAssets)); + env(amm::ammClawback(gw, alice, USD, EUR, USD(1)), txflags(tfClawTwoAssets)); auto const lpBalance = IOUAmount{5, -12}; - BEAST_EXPECT(amm.expectBalances( - STAmount(USD, UINT64_C(4), -15), - STAmount(EUR, UINT64_C(8), -9), - lpBalance)); + BEAST_EXPECT( + amm.expectBalances(STAmount(USD, UINT64_C(4), -15), STAmount(EUR, UINT64_C(8), -9), lpBalance)); BEAST_EXPECT(amm.expectLPTokens(alice, lpBalance)); } } @@ -2427,15 +2086,11 @@ class AMMClawback_test : public beast::unit_test::suite { // For now, just disable SAV entirely, which locks in the small Number // mantissas - FeatureBitset const all = jtx::testable_amendments() - - featureSingleAssetVault - featureLendingProtocol; + FeatureBitset const all = jtx::testable_amendments() - featureSingleAssetVault - featureLendingProtocol; testInvalidRequest(); testFeatureDisabled(all - featureAMMClawback); - for (auto const& features : - {all - fixAMMv1_3 - fixAMMClawbackRounding, - all - fixAMMClawbackRounding, - all}) + for (auto const& features : {all - fixAMMv1_3 - fixAMMClawbackRounding, all - fixAMMClawbackRounding, all}) { testAMMClawbackSpecificAmount(features); testAMMClawbackExceedBalance(features); diff --git a/src/test/app/AMMExtended_test.cpp b/src/test/app/AMMExtended_test.cpp index d1816df51b..3cc48787d5 100644 --- a/src/test/app/AMMExtended_test.cpp +++ b/src/test/app/AMMExtended_test.cpp @@ -48,12 +48,7 @@ private: Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - XRP(10'000), - {USD(200'000), BTC(2'000)}); + fund(env, gw, {alice, bob, carol}, XRP(10'000), {USD(200'000), BTC(2'000)}); // Must be two offers at the same quality // "taker gets" must be XRP @@ -71,24 +66,17 @@ private: PathSet paths(Path(XRP, USD), Path(USD)); - env(pay(alice, bob, USD(100)), - json(paths.json()), - sendmax(BTC(1'000)), - txflags(tfPartialPayment)); + env(pay(alice, bob, USD(100)), json(paths.json()), sendmax(BTC(1'000)), txflags(tfPartialPayment)); if (!features[fixAMMv1_1]) { BEAST_EXPECT(ammCarol.expectBalances( - STAmount{BTC, UINT64_C(1'001'000000374812), -12}, - USD(100'000), - ammCarol.tokens())); + STAmount{BTC, UINT64_C(1'001'000000374812), -12}, USD(100'000), ammCarol.tokens())); } else { BEAST_EXPECT(ammCarol.expectBalances( - STAmount{BTC, UINT64_C(1'001'000000374815), -12}, - USD(100'000), - ammCarol.tokens())); + STAmount{BTC, UINT64_C(1'001'000000374815), -12}, USD(100'000), ammCarol.tokens())); } env.require(balance(bob, USD(200'100))); @@ -157,15 +145,10 @@ private: AMM ammDan(env, dan, XRP(10'000), USD1(10'050)); - env(pay(alice, carol, USD2(50)), - path(~USD1, bob), - sendmax(XRP(50)), - txflags(tfNoRippleDirect)); - BEAST_EXPECT(ammDan.expectBalances( - XRP(10'050), USD1(10'000), ammDan.tokens())); + env(pay(alice, carol, USD2(50)), path(~USD1, bob), sendmax(XRP(50)), txflags(tfNoRippleDirect)); + BEAST_EXPECT(ammDan.expectBalances(XRP(10'050), USD1(10'000), ammDan.tokens())); - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, XRP(20'000) - XRP(50) - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, XRP(20'000) - XRP(50) - txfee(env, 1))); BEAST_EXPECT(expectHolding(env, bob, USD1(100))); BEAST_EXPECT(expectHolding(env, bob, USD2(0))); BEAST_EXPECT(expectHolding(env, carol, USD2(50))); @@ -187,26 +170,18 @@ private: [&](AMM& ammAlice, Env& env) { // Order that can't be filled TER const killedCode{TER{tecKILLED}}; - env(offer(carol, USD(100), XRP(100)), - txflags(tfFillOrKill), - ter(killedCode)); + env(offer(carol, USD(100), XRP(100)), txflags(tfFillOrKill), ter(killedCode)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); // fee = AMM - BEAST_EXPECT(expectLedgerEntryRoot( - env, carol, XRP(30'000) - (txfee(env, 1)))); + BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRP(30'000) - (txfee(env, 1)))); BEAST_EXPECT(expectOffers(env, carol, 0)); BEAST_EXPECT(expectHolding(env, carol, USD(30'000))); // Order that can be filled - env(offer(carol, XRP(100), USD(100)), - txflags(tfFillOrKill), - ter(tesSUCCESS)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'100), ammAlice.tokens())); - BEAST_EXPECT(expectLedgerEntryRoot( - env, carol, XRP(30'000) + XRP(100) - txfee(env, 2))); + env(offer(carol, XRP(100), USD(100)), txflags(tfFillOrKill), ter(tesSUCCESS)); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'100), ammAlice.tokens())); + BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRP(30'000) + XRP(100) - txfee(env, 2))); BEAST_EXPECT(expectHolding(env, carol, USD(29'900))); BEAST_EXPECT(expectOffers(env, carol, 0)); }, @@ -219,17 +194,13 @@ private: // and add nothing on the books. testAMM( [&](AMM& ammAlice, Env& env) { - env(offer(carol, XRP(200), USD(200)), - txflags(tfImmediateOrCancel), - ter(tesSUCCESS)); + env(offer(carol, XRP(200), USD(200)), txflags(tfImmediateOrCancel), ter(tesSUCCESS)); // AMM generates a synthetic offer of 100USD/100XRP // to match the CLOB offer quality. - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'100), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'100), ammAlice.tokens())); // +AMM - offer * fee - BEAST_EXPECT(expectLedgerEntryRoot( - env, carol, XRP(30'000) + XRP(100) - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRP(30'000) + XRP(100) - txfee(env, 1))); // AMM BEAST_EXPECT(expectHolding(env, carol, USD(29'900))); BEAST_EXPECT(expectOffers(env, carol, 0)); @@ -246,10 +217,8 @@ private: // Carol's offer should stay in the ledger. env(offer(carol, XRP(100), USD(100), tfPassive)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), STAmount{USD, 10'000}, ammAlice.tokens())); - BEAST_EXPECT(expectOffers( - env, carol, 1, {{{XRP(100), STAmount{USD, 100}}}})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), STAmount{USD, 10'000}, ammAlice.tokens())); + BEAST_EXPECT(expectOffers(env, carol, 1, {{{XRP(100), STAmount{USD, 100}}}})); }, {{XRP(10'100), USD(10'000)}}, 0, @@ -267,9 +236,7 @@ private: env(offer(carol, XRP(100), USD(100), tfPassive)); env.close(); BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'900), - STAmount{USD, UINT64_C(9'082'56880733945), -11}, - ammAlice.tokens())); + XRP(10'900), STAmount{USD, UINT64_C(9'082'56880733945), -11}, ammAlice.tokens())); BEAST_EXPECT(expectOffers(env, carol, 0)); BEAST_EXPECT(expectOffers(env, alice, 1)); }, @@ -298,14 +265,10 @@ private: auto const xrpTransferred = XRPAmount{3'061'224'490}; env(offer(bob, USD(1), XRP(4'000))); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(150'000) + xrpTransferred, - USD(49), - IOUAmount{273'861'278752583, -8})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(150'000) + xrpTransferred, USD(49), IOUAmount{273'861'278752583, -8})); BEAST_EXPECT(expectHolding(env, bob, STAmount{USD, 101})); - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(300'000) - xrpTransferred - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(300'000) - xrpTransferred - txfee(env, 1))); BEAST_EXPECT(expectOffers(env, bob, 0)); } @@ -328,17 +291,14 @@ private: AMM ammAlice(env, alice, XRP(150'000), USD(51)); env(offer(bob, USD(1), XRP(3'000))); - BEAST_EXPECT( - ammAlice.expectBalances(XRP(153'000), USD(50), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(153'000), USD(50), ammAlice.tokens())); auto jrr = ledgerEntryState(env, bob, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-1"); jrr = ledgerEntryRoot(env, bob); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string( - (XRP(200'000) - XRP(3'000) - env.current()->fees().base * 1) - .xrp())); + to_string((XRP(200'000) - XRP(3'000) - env.current()->fees().base * 1).xrp())); } void @@ -364,15 +324,13 @@ private: env(pay(alice, alice, XRP(500)), sendmax(USD(100))); - BEAST_EXPECT( - ammBob.expectBalances(USD(300), XRP(1'000), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(USD(300), XRP(1'000), ammBob.tokens())); BEAST_EXPECT(expectHolding(env, alice, USD(0))); auto jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string((XRP(10'000) + XRP(500) - env.current()->fees().base * 2) - .xrp())); + to_string((XRP(10'000) + XRP(500) - env.current()->fees().base * 2).xrp())); } void @@ -386,26 +344,18 @@ private: [&](AMM& ammAlice, Env& env) { // Alice converts USD to XRP which should fail // due to PartialPayment. - env(pay(alice, alice, XRP(100)), - sendmax(USD(100)), - ter(tecPATH_PARTIAL)); + env(pay(alice, alice, XRP(100)), sendmax(USD(100)), ter(tecPATH_PARTIAL)); // Alice converts USD to XRP, should succeed because // we permit partial payment - env(pay(alice, alice, XRP(100)), - sendmax(USD(100)), - txflags(tfPartialPayment)); + env(pay(alice, alice, XRP(100)), sendmax(USD(100)), txflags(tfPartialPayment)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{9'900'990'100}, USD(10'100), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount{9'900'990'100}, USD(10'100), ammAlice.tokens())); // initial 30,000 - 10,000AMM - 100pay BEAST_EXPECT(expectHolding(env, alice, USD(19'900))); // initial 30,000 - 10,0000AMM + 99.009900pay - fee*3 BEAST_EXPECT(expectLedgerEntryRoot( - env, - alice, - XRP(30'000) - XRP(10'000) + XRPAmount{99'009'900} - - ammCrtFee(env) - txfee(env, 2))); + env, alice, XRP(30'000) - XRP(10'000) + XRPAmount{99'009'900} - ammCrtFee(env) - txfee(env, 2))); }, {{XRP(10'000), USD(10'000)}}, 0, @@ -427,8 +377,7 @@ private: env(trust(bob, USD(100))); env.close(); env(pay(alice, bob, USD(100)), sendmax(XRP(100))); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, bob, USD(100))); }, {{XRP(10'000), USD(10'100)}}, @@ -451,10 +400,8 @@ private: env(trust(bob, USD(100))); env.close(); env(pay(alice, bob, XRP(100)), sendmax(USD(100))); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'100), ammAlice.tokens())); - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(1'000) + XRP(100) - txfee(env, 1))); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'100), ammAlice.tokens())); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(1'000) + XRP(100) - txfee(env, 1))); }, {{XRP(10'100), USD(10'000)}}, 0, @@ -500,14 +447,10 @@ private: Json::Value jtp{Json::arrayValue}; jtp[0u][0u][jss::currency] = "XRP"; - env(pay(alice, bob, EUR1(30)), - json(jss::Paths, jtp), - sendmax(USD1(333))); + env(pay(alice, bob, EUR1(30)), json(jss::Paths, jtp), sendmax(USD1(333))); env.close(); - BEAST_EXPECT(ammCarol.expectBalances( - XRP(49'700), - STAmount{USD1, UINT64_C(5'030'181086519115), -12}, - ammCarol.tokens())); + BEAST_EXPECT( + ammCarol.expectBalances(XRP(49'700), STAmount{USD1, UINT64_C(5'030'181086519115), -12}, ammCarol.tokens())); BEAST_EXPECT(expectOffers(env, dan, 1, {{Amounts{XRP(200), EUR(20)}}})); BEAST_EXPECT(expectHolding(env, bob, STAmount{EUR1, 30})); } @@ -536,9 +479,7 @@ private: // fees: // 1 for each trust limit == 3 (alice < mtgox/amazon/bitstamp) + // 1 for payment == 4 - auto const starting_xrp = XRP(100) + - env.current()->fees().accountReserve(3) + - env.current()->fees().base * 4; + auto const starting_xrp = XRP(100) + env.current()->fees().accountReserve(3) + env.current()->fees().base * 4; env.fund(starting_xrp, gw1, gw2, gw3, alice); env.fund(XRP(2'000), bob); @@ -559,18 +500,13 @@ private: // The pool gets only 100XRP for ~109.09USD, even though // it can exchange more. - BEAST_EXPECT(ammBob.expectBalances( - XRP(1'100), - STAmount{USD1, UINT64_C(1'090'909090909091), -12}, - ammBob.tokens())); + BEAST_EXPECT( + ammBob.expectBalances(XRP(1'100), STAmount{USD1, UINT64_C(1'090'909090909091), -12}, ammBob.tokens())); auto jrr = ledgerEntryState(env, alice, gw1, "USD"); - BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName][jss::value] == - "109.090909090909"); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "109.090909090909"); jrr = ledgerEntryRoot(env, alice); - BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName] == XRP(350).value().getText()); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName] == XRP(350).value().getText()); } void @@ -595,13 +531,11 @@ private: AMM ammAlice(env, alice, USD(150), XRP(150'100)); env(offer(bob, XRP(100), USD(0.1))); - BEAST_EXPECT(ammAlice.expectBalances( - USD(150.1), XRP(150'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(USD(150.1), XRP(150'000), ammAlice.tokens())); auto const jrr = ledgerEntryState(env, bob, gw, "USD"); // Bob pays 0.005 transfer fee. Note 10**-10 round-off. - BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName][jss::value] == "-0.8995000001"); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-0.8995000001"); } void @@ -615,12 +549,10 @@ private: [&](AMM& ammAlice, Env& env) { env(offer(carol, USD(100), XRP(100)), json(jss::Flags, tfSell)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(9'999), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(9'999), ammAlice.tokens())); BEAST_EXPECT(expectOffers(env, carol, 0)); BEAST_EXPECT(expectHolding(env, carol, USD(30'101))); - BEAST_EXPECT(expectLedgerEntryRoot( - env, carol, XRP(30'000) - XRP(100) - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRP(30'000) - XRP(100) - txfee(env, 1))); }, {{XRP(9'900), USD(10'100)}}, 0, @@ -637,8 +569,7 @@ private: Env env{*this, features}; - auto const starting_xrp = - XRP(100) + reserve(env, 1) + env.current()->fees().base * 2; + auto const starting_xrp = XRP(100) + reserve(env, 1) + env.current()->fees().base * 2; env.fund(starting_xrp, gw, alice); env.fund(XRP(2'000), bob); @@ -656,8 +587,7 @@ private: // Selling XRP. // Will sell all 100 XRP and get more USD than asked for. env(offer(alice, USD(100), XRP(200)), json(jss::Flags, tfSell)); - BEAST_EXPECT( - ammBob.expectBalances(XRP(1'100), USD(2'000), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(XRP(1'100), USD(2'000), ammBob.tokens())); BEAST_EXPECT(expectHolding(env, alice, USD(200))); BEAST_EXPECT(expectLedgerEntryRoot(env, alice, XRP(250))); BEAST_EXPECT(expectOffers(env, alice, 0)); @@ -675,15 +605,8 @@ private: auto const XTS = gw["XTS"]; auto const XXX = gw["XXX"]; - auto const starting_xrp = - XRP(100.1) + reserve(env, 1) + env.current()->fees().base * 2; - fund( - env, - gw, - {alice, bob}, - starting_xrp, - {XTS(100), XXX(100)}, - Fund::All); + auto const starting_xrp = XRP(100.1) + reserve(env, 1) + env.current()->fees().base * 2; + fund(env, gw, {alice, bob}, starting_xrp, {XTS(100), XXX(100)}, Fund::All); AMM ammAlice(env, alice, XTS(100), XXX(100)); @@ -692,34 +615,24 @@ private: payment[jss::id] = env.seq(bob); payment[jss::build_path] = true; payment[jss::tx_json] = pay(bob, bob, bob["XXX"](1)); - payment[jss::tx_json][jss::Sequence] = - env.current() - ->read(keylet::account(bob.id())) - ->getFieldU32(sfSequence); + payment[jss::tx_json][jss::Sequence] = env.current()->read(keylet::account(bob.id()))->getFieldU32(sfSequence); payment[jss::tx_json][jss::Fee] = to_string(env.current()->fees().base); - payment[jss::tx_json][jss::SendMax] = - bob["XTS"](1.5).value().getJson(JsonOptions::none); + payment[jss::tx_json][jss::SendMax] = bob["XTS"](1.5).value().getJson(JsonOptions::none); payment[jss::tx_json][jss::Flags] = tfPartialPayment; auto const jrr = env.rpc("json", "submit", to_string(payment)); BEAST_EXPECT(jrr[jss::result][jss::status] == "success"); BEAST_EXPECT(jrr[jss::result][jss::engine_result] == "tesSUCCESS"); if (!features[fixAMMv1_1]) { - BEAST_EXPECT(ammAlice.expectBalances( - STAmount(XTS, UINT64_C(101'010101010101), -12), - XXX(99), - ammAlice.tokens())); - BEAST_EXPECT(expectHolding( - env, bob, STAmount{XTS, UINT64_C(98'989898989899), -12})); + BEAST_EXPECT( + ammAlice.expectBalances(STAmount(XTS, UINT64_C(101'010101010101), -12), XXX(99), ammAlice.tokens())); + BEAST_EXPECT(expectHolding(env, bob, STAmount{XTS, UINT64_C(98'989898989899), -12})); } else { - BEAST_EXPECT(ammAlice.expectBalances( - STAmount(XTS, UINT64_C(101'0101010101011), -13), - XXX(99), - ammAlice.tokens())); - BEAST_EXPECT(expectHolding( - env, bob, STAmount{XTS, UINT64_C(98'9898989898989), -13})); + BEAST_EXPECT( + ammAlice.expectBalances(STAmount(XTS, UINT64_C(101'0101010101011), -13), XXX(99), ammAlice.tokens())); + BEAST_EXPECT(expectHolding(env, bob, STAmount{XTS, UINT64_C(98'9898989898989), -13})); } BEAST_EXPECT(expectHolding(env, bob, XXX(101))); } @@ -734,12 +647,7 @@ private: { Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - {USD(15'000), EUR(15'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(15'000), EUR(15'000)}, Fund::All); // The scenario: // o USD/XRP AMM is created. @@ -755,10 +663,8 @@ private: env(offer(carol, USD(100), EUR(100))); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); - BEAST_EXPECT(ammBob.expectBalances( - XRP(10'000), EUR(10'100), ammBob.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammBob.expectBalances(XRP(10'000), EUR(10'100), ammBob.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(15'100))); BEAST_EXPECT(expectHolding(env, carol, EUR(14'900))); BEAST_EXPECT(expectOffers(env, carol, 0)); @@ -767,12 +673,7 @@ private: { Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - {USD(15'000), EUR(15'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(15'000), EUR(15'000)}, Fund::All); // The scenario: // o USD/XRP AMM is created. @@ -790,8 +691,7 @@ private: env(offer(carol, USD(100), EUR(100))); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(15'100))); BEAST_EXPECT(expectHolding(env, carol, EUR(14'900))); BEAST_EXPECT(expectOffers(env, carol, 0)); @@ -801,12 +701,7 @@ private: { Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - {USD(15'000), EUR(15'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(15'000), EUR(15'000)}, Fund::All); // The scenario: // o USD/XRP offer is created. @@ -824,8 +719,7 @@ private: env(offer(carol, USD(100), EUR(100))); env.close(); - BEAST_EXPECT(ammBob.expectBalances( - XRP(10'000), EUR(10'100), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(XRP(10'000), EUR(10'100), ammBob.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(15'100))); BEAST_EXPECT(expectHolding(env, carol, EUR(14'900))); BEAST_EXPECT(expectOffers(env, carol, 0)); @@ -850,11 +744,9 @@ private: fund(env, gw, {alice, bob}, {USD(20'000)}, Fund::All); AMM ammBob(env, bob, XRP(20'000), USD(200)); // alice submits a tfSell | tfFillOrKill offer that does not cross. - env(offer(alice, USD(2.1), XRP(210), tfSell | tfFillOrKill), - ter(killedCode)); + env(offer(alice, USD(2.1), XRP(210), tfSell | tfFillOrKill), ter(killedCode)); - BEAST_EXPECT( - ammBob.expectBalances(XRP(20'000), USD(200), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(XRP(20'000), USD(200), ammBob.tokens())); BEAST_EXPECT(expectOffers(env, bob, 0)); } { @@ -865,12 +757,9 @@ private: // Even though tfSell is present it doesn't matter this time. env(offer(alice, USD(2), XRP(220), tfSell | tfFillOrKill)); env.close(); - BEAST_EXPECT(ammBob.expectBalances( - XRP(20'220), - STAmount{USD, UINT64_C(197'8239366963403), -13}, - ammBob.tokens())); - BEAST_EXPECT(expectHolding( - env, alice, STAmount{USD, UINT64_C(1'002'17606330366), -11})); + BEAST_EXPECT( + ammBob.expectBalances(XRP(20'220), STAmount{USD, UINT64_C(197'8239366963403), -13}, ammBob.tokens())); + BEAST_EXPECT(expectHolding(env, alice, STAmount{USD, UINT64_C(1'002'17606330366), -11})); BEAST_EXPECT(expectOffers(env, alice, 0)); } { @@ -883,12 +772,9 @@ private: env(offer(alice, USD(10), XRP(1'500), tfSell | tfFillOrKill)); env.close(); - BEAST_EXPECT(ammBob.expectBalances( - XRP(21'500), - STAmount{USD, UINT64_C(186'046511627907), -12}, - ammBob.tokens())); - BEAST_EXPECT(expectHolding( - env, alice, STAmount{USD, UINT64_C(1'013'953488372093), -12})); + BEAST_EXPECT( + ammBob.expectBalances(XRP(21'500), STAmount{USD, UINT64_C(186'046511627907), -12}, ammBob.tokens())); + BEAST_EXPECT(expectHolding(env, alice, STAmount{USD, UINT64_C(1'013'953488372093), -12})); BEAST_EXPECT(expectOffers(env, alice, 0)); } { @@ -901,8 +787,7 @@ private: fund(env, gw, {alice, bob}, {USD(10'000)}, Fund::All); AMM ammBob(env, bob, XRP(5000), USD(10)); - env(offer(alice, USD(1), XRP(501), tfSell | tfFillOrKill), - ter(tecKILLED)); + env(offer(alice, USD(1), XRP(501), tfSell | tfFillOrKill), ter(tecKILLED)); env.close(); BEAST_EXPECT(expectOffers(env, alice, 0)); BEAST_EXPECT(expectOffers(env, bob, 0)); @@ -926,8 +811,7 @@ private: env.close(); // AMM doesn't pay the transfer fee - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(30'100))); BEAST_EXPECT(expectOffers(env, carol, 0)); }, @@ -946,8 +830,7 @@ private: env(offer(carol, XRP(100), USD(100))); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'100), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'100), ammAlice.tokens())); // Carol pays 25% transfer fee BEAST_EXPECT(expectHolding(env, carol, USD(29'875))); BEAST_EXPECT(expectOffers(env, carol, 0)); @@ -960,12 +843,7 @@ private: { // Bridged crossing. Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - {USD(15'000), EUR(15'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(15'000), EUR(15'000)}, Fund::All); env(rate(gw, 1.25)); // The scenario: @@ -984,8 +862,7 @@ private: env.close(); // AMM doesn't pay the transfer fee - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(15'100))); // Carol pays 25% transfer fee. BEAST_EXPECT(expectHolding(env, carol, EUR(14'875))); @@ -997,12 +874,7 @@ private: // Bridged crossing. The transfer fee is paid on the step not // involving AMM as src/dst. Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - {USD(15'000), EUR(15'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(15'000), EUR(15'000)}, Fund::All); env(rate(gw, 1.25)); // The scenario: @@ -1024,14 +896,12 @@ private: // account but not from the remaining offer. // AMM doesn't pay the transfer fee - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'050), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'050), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(15'050))); // Carol pays 25% transfer fee. BEAST_EXPECT(expectHolding(env, carol, EUR(14'937.5))); BEAST_EXPECT(expectOffers(env, carol, 0)); - BEAST_EXPECT( - expectOffers(env, bob, 1, {{Amounts{EUR(50), XRP(50)}}})); + BEAST_EXPECT(expectOffers(env, bob, 1, {{Amounts{EUR(50), XRP(50)}}})); } { @@ -1069,8 +939,7 @@ private: env.close(); // AMM doesn't pay the transfer fee - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(100))); // Carol pays 25% transfer fee: 1250 - 100(offer) - 25(transfer fee) BEAST_EXPECT(expectHolding(env, carol, EUR(1'125))); @@ -1112,8 +981,7 @@ private: env.close(); // AMM pay doesn't transfer fee - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(100))); // Carol pays 25% transfer fee: 1000 - 100(offer) - 25(transfer fee) BEAST_EXPECT(expectHolding(env, carol, EUR(875))); @@ -1142,8 +1010,7 @@ private: env(offer(alice, USD_bob(100), XRP(100))); env.close(); - BEAST_EXPECT(ammBob.expectBalances( - XRP(10'100), USD_bob(10'000), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(XRP(10'100), USD_bob(10'000), ammBob.tokens())); BEAST_EXPECT(expectOffers(env, alice, 0)); BEAST_EXPECT(expectHolding(env, alice, USD_bob(100))); } @@ -1201,14 +1068,10 @@ private: env.close(); // This payment caused the assert. - env(pay(ann, ann, D_BUX(30)), - path(A_BUX, D_BUX), - sendmax(A_BUX(30)), - ter(temBAD_PATH)); + env(pay(ann, ann, D_BUX(30)), path(A_BUX, D_BUX), sendmax(A_BUX(30)), ter(temBAD_PATH)); env.close(); - BEAST_EXPECT( - ammBob.expectBalances(A_BUX(30), D_BUX(30), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(A_BUX(30), D_BUX(30), ammBob.tokens())); BEAST_EXPECT(expectHolding(env, ann, A_BUX(none))); BEAST_EXPECT(expectHolding(env, ann, D_BUX(0))); BEAST_EXPECT(expectHolding(env, cam, A_BUX(none))); @@ -1331,8 +1194,7 @@ private: AMM ammAlice(env, alice, USD(1'000), XRP(1'050)); // Set up authorized trust line for AMM. - env(trust(gw, STAmount{Issue{USD.currency, ammAlice.ammAccount()}, 10}), - txflags(tfSetfAuth)); + env(trust(gw, STAmount{Issue{USD.currency, ammAlice.ammAccount()}, 10}), txflags(tfSetfAuth)); env.close(); env(pay(gw, bob, USD(50))); @@ -1344,8 +1206,7 @@ private: env(offer(bob, XRP(50), USD(50))); env.close(); - BEAST_EXPECT( - ammAlice.expectBalances(USD(1'050), XRP(1'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(USD(1'050), XRP(1'000), ammAlice.tokens())); BEAST_EXPECT(expectOffers(env, bob, 0)); BEAST_EXPECT(expectHolding(env, bob, USD(0))); } @@ -1364,8 +1225,7 @@ private: // Alice doesn't have the funds { - AMM ammAlice( - env, alice, USD(1'000), XRP(1'000), ter(tecUNFUNDED_AMM)); + AMM ammAlice(env, alice, USD(1'000), XRP(1'000), ter(tecUNFUNDED_AMM)); } env(fset(gw, asfRequireAuth)); @@ -1404,16 +1264,14 @@ private: AMM ammAlice(env, alice, USD(1'000), XRP(1'050)); // Set up authorized trust line for AMM. - env(trust(gw, STAmount{Issue{USD.currency, ammAlice.ammAccount()}, 10}), - txflags(tfSetfAuth)); + env(trust(gw, STAmount{Issue{USD.currency, ammAlice.ammAccount()}, 10}), txflags(tfSetfAuth)); env.close(); // Now bob creates his offer again, which crosses with alice's AMM. env(offer(bob, XRP(50), USD(50))); env.close(); - BEAST_EXPECT( - ammAlice.expectBalances(USD(1'050), XRP(1'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(USD(1'050), XRP(1'000), ammAlice.tokens())); BEAST_EXPECT(expectOffers(env, bob, 0)); BEAST_EXPECT(expectHolding(env, bob, USD(0))); } @@ -1424,9 +1282,7 @@ private: using namespace jtx; // For now, just disable SAV entirely, which locks in the small Number // mantissas - FeatureBitset const all{ - testable_amendments() - featureSingleAssetVault - - featureLendingProtocol}; + FeatureBitset const all{testable_amendments() - featureSingleAssetVault - featureLendingProtocol}; testRmFundedOffer(all); testRmFundedOffer(all - fixAMMv1_1 - fixAMMv1_3); @@ -1471,25 +1327,14 @@ private: STPathSet st; STAmount sa; STAmount da; - std::tie(st, sa, da) = find_paths( - env, - alice, - bob, - bob["AUD"](-1), - std::optional(XRP(100'000'000))); + std::tie(st, sa, da) = find_paths(env, alice, bob, bob["AUD"](-1), std::optional(XRP(100'000'000))); BEAST_EXPECT(st.empty()); - std::tie(st, sa, da) = find_paths( - env, - alice, - bob, - bob["USD"](-1), - std::optional(XRP(100'000'000))); + std::tie(st, sa, da) = find_paths(env, alice, bob, bob["USD"](-1), std::optional(XRP(100'000'000))); // Alice sends all requested 100,000,000XRP BEAST_EXPECT(sa == XRP(100'000'000)); // Bob gets ~99.99USD. This is the amount Bob // can get out of AMM for 100,000,000XRP. - BEAST_EXPECT(equal( - da, STAmount{bob["USD"].issue(), UINT64_C(99'9999000001), -10})); + BEAST_EXPECT(equal(da, STAmount{bob["USD"].issue(), UINT64_C(99'9999000001), -10})); } // carol holds gateway AUD, sells gateway AUD for XRP @@ -1513,12 +1358,10 @@ private: env(pay(alice, bob, AUD(10)), sendmax(XRP(100)), paths(XRP)); env.close(); // AMM offer is 51.282052XRP/11AUD, 11AUD/1.1 = 10AUD to bob - BEAST_EXPECT( - ammCarol.expectBalances(XRP(51), AUD(40), ammCarol.tokens())); + BEAST_EXPECT(ammCarol.expectBalances(XRP(51), AUD(40), ammCarol.tokens())); BEAST_EXPECT(expectHolding(env, bob, AUD(10))); - auto const result = - find_paths(env, alice, bob, Account(bob)["USD"](25)); + auto const result = find_paths(env, alice, bob, Account(bob)["USD"](25)); BEAST_EXPECT(std::get<0>(result).empty()); } @@ -1533,16 +1376,14 @@ private: Env env = pathTestEnv(); fund(env, gw, {alice, bob, charlie}, {USD(11)}, Fund::All); AMM ammCharlie(env, charlie, XRP(10), USD(11)); - auto [st, sa, da] = - find_paths(env, alice, bob, USD(-1), XRP(1).value()); + auto [st, sa, da] = find_paths(env, alice, bob, USD(-1), XRP(1).value()); BEAST_EXPECT(sa == XRP(1)); BEAST_EXPECT(equal(da, USD(1))); if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1)) { auto const& pathElem = st[0][0]; BEAST_EXPECT( - pathElem.isOffer() && pathElem.getIssuerID() == gw.id() && - pathElem.getCurrency() == USD.currency); + pathElem.isOffer() && pathElem.getIssuerID() == gw.id() && pathElem.getCurrency() == USD.currency); } } { @@ -1551,16 +1392,14 @@ private: fund(env, gw, {alice, bob, charlie}, {USD(11)}, Fund::All); AMM ammCharlie(env, charlie, XRP(11), USD(10)); env.close(); - auto [st, sa, da] = - find_paths(env, alice, bob, drops(-1), USD(1).value()); + auto [st, sa, da] = find_paths(env, alice, bob, drops(-1), USD(1).value()); BEAST_EXPECT(sa == USD(1)); BEAST_EXPECT(equal(da, XRP(1))); if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1)) { auto const& pathElem = st[0][0]; BEAST_EXPECT( - pathElem.isOffer() && - pathElem.getIssuerID() == xrpAccount() && + pathElem.isOffer() && pathElem.getIssuerID() == xrpAccount() && pathElem.getCurrency() == xrpCurrency()); } } @@ -1611,8 +1450,7 @@ private: { auto const& send_amt = XRP(10); - std::tie(st, sa, da) = - find_paths(env, A1, A2, send_amt, std::nullopt, xrpCurrency()); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, xrpCurrency()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(st.empty()); } @@ -1621,16 +1459,14 @@ private: // no path should exist for this since dest account // does not exist. auto const& send_amt = XRP(200); - std::tie(st, sa, da) = find_paths( - env, A1, Account{"A0"}, send_amt, std::nullopt, xrpCurrency()); + std::tie(st, sa, da) = find_paths(env, A1, Account{"A0"}, send_amt, std::nullopt, xrpCurrency()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(st.empty()); } { auto const& send_amt = G3["ABC"](10); - std::tie(st, sa, da) = - find_paths(env, A2, G3, send_amt, std::nullopt, xrpCurrency()); + std::tie(st, sa, da) = find_paths(env, A2, G3, send_amt, std::nullopt, xrpCurrency()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, XRPAmount{101'010'102})); BEAST_EXPECT(same(st, stpath(IPE(G3["ABC"])))); @@ -1638,8 +1474,7 @@ private: { auto const& send_amt = A2["ABC"](1); - std::tie(st, sa, da) = - find_paths(env, A1, A2, send_amt, std::nullopt, xrpCurrency()); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, xrpCurrency()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, XRPAmount{10'010'011})); BEAST_EXPECT(same(st, stpath(IPE(G3["ABC"]), G3))); @@ -1647,8 +1482,7 @@ private: { auto const& send_amt = A3["ABC"](1); - std::tie(st, sa, da) = - find_paths(env, A1, A3, send_amt, std::nullopt, xrpCurrency()); + std::tie(st, sa, da) = find_paths(env, A1, A3, send_amt, std::nullopt, xrpCurrency()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, XRPAmount{10'010'011})); BEAST_EXPECT(same(st, stpath(IPE(G3["ABC"]), G3, A2))); @@ -1685,8 +1519,7 @@ private: STAmount sa, da; auto const& send_amt = XRP(10); - std::tie(st, sa, da) = - find_paths(env, A1, A2, send_amt, std::nullopt, A2["ABC"].currency); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, A2["ABC"].currency); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["ABC"](1))); BEAST_EXPECT(same(st, stpath(G3, IPE(xrpIssue())))); @@ -1743,8 +1576,7 @@ private: // A) Borrow or repay -- // Source -> Destination (repay source issuer) auto const& send_amt = G1["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, A1, G1, send_amt, std::nullopt, G1["HKD"].currency); + std::tie(st, sa, da) = find_paths(env, A1, G1, send_amt, std::nullopt, G1["HKD"].currency); BEAST_EXPECT(st.empty()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); @@ -1754,8 +1586,7 @@ private: // A2) Borrow or repay -- // Source -> Destination (repay destination issuer) auto const& send_amt = A1["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, A1, G1, send_amt, std::nullopt, G1["HKD"].currency); + std::tie(st, sa, da) = find_paths(env, A1, G1, send_amt, std::nullopt, G1["HKD"].currency); BEAST_EXPECT(st.empty()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); @@ -1765,8 +1596,7 @@ private: // B) Common gateway -- // Source -> AC -> Destination auto const& send_amt = A3["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, A1, A3, send_amt, std::nullopt, G1["HKD"].currency); + std::tie(st, sa, da) = find_paths(env, A1, A3, send_amt, std::nullopt, G1["HKD"].currency); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same(st, stpath(G1))); @@ -1776,24 +1606,18 @@ private: // C) Gateway to gateway -- // Source -> OB -> Destination auto const& send_amt = G2["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, G1, G2, send_amt, std::nullopt, G1["HKD"].currency); + std::tie(st, sa, da) = find_paths(env, G1, G2, send_amt, std::nullopt, G1["HKD"].currency); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, G1["HKD"](10))); - BEAST_EXPECT(same( - st, - stpath(IPE(G2["HKD"])), - stpath(M1), - stpath(M2), - stpath(IPE(xrpIssue()), IPE(G2["HKD"])))); + BEAST_EXPECT( + same(st, stpath(IPE(G2["HKD"])), stpath(M1), stpath(M2), stpath(IPE(xrpIssue()), IPE(G2["HKD"])))); } { // D) User to unlinked gateway via order book -- // Source -> AC -> OB -> Destination auto const& send_amt = G2["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, A1, G2, send_amt, std::nullopt, G1["HKD"].currency); + std::tie(st, sa, da) = find_paths(env, A1, G2, send_amt, std::nullopt, G1["HKD"].currency); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same( @@ -1809,8 +1633,7 @@ private: // Source -> AC -> OB to XRP -> OB from XRP -> AC -> // Destination auto const& send_amt = A2["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, A1, A2, send_amt, std::nullopt, G1["HKD"].currency); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, G1["HKD"].currency); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same( @@ -1859,8 +1682,7 @@ private: auto const& send_amt = A2["HKD"](10); STPathSet st; STAmount sa, da; - std::tie(st, sa, da) = - find_paths(env, G1, A2, send_amt, std::nullopt, G1["HKD"].currency); + std::tie(st, sa, da) = find_paths(env, G1, A2, send_amt, std::nullopt, G1["HKD"].currency); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, G1["HKD"](10))); BEAST_EXPECT(same(st, stpath(M1, G2), stpath(IPE(G2["HKD"]), G2))); @@ -1918,13 +1740,7 @@ private: // simple IOU/IOU offer Env env(*this, features); - fund( - env, - gw, - {alice, bob, carol}, - XRP(10'000), - {BTC(100), USD(150)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, XRP(10'000), {BTC(100), USD(150)}, Fund::All); AMM ammBob(env, bob, BTC(100), USD(150)); @@ -1934,20 +1750,13 @@ private: BEAST_EXPECT(expectHolding(env, bob, BTC(0))); BEAST_EXPECT(expectHolding(env, bob, USD(0))); BEAST_EXPECT(expectHolding(env, carol, USD(200))); - BEAST_EXPECT( - ammBob.expectBalances(BTC(150), USD(100), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(BTC(150), USD(100), ammBob.tokens())); } { // simple IOU/XRP XRP/IOU offer Env env(*this, features); - fund( - env, - gw, - {alice, carol, bob}, - XRP(10'000), - {BTC(100), USD(150)}, - Fund::All); + fund(env, gw, {alice, carol, bob}, XRP(10'000), {BTC(100), USD(150)}, Fund::All); AMM ammBobBTC_XRP(env, bob, BTC(100), XRP(150)); AMM ammBobXRP_USD(env, bob, XRP(100), USD(150)); @@ -1958,59 +1767,40 @@ private: BEAST_EXPECT(expectHolding(env, bob, BTC(0))); BEAST_EXPECT(expectHolding(env, bob, USD(0))); BEAST_EXPECT(expectHolding(env, carol, USD(200))); - BEAST_EXPECT(ammBobBTC_XRP.expectBalances( - BTC(150), XRP(100), ammBobBTC_XRP.tokens())); - BEAST_EXPECT(ammBobXRP_USD.expectBalances( - XRP(150), USD(100), ammBobXRP_USD.tokens())); + BEAST_EXPECT(ammBobBTC_XRP.expectBalances(BTC(150), XRP(100), ammBobBTC_XRP.tokens())); + BEAST_EXPECT(ammBobXRP_USD.expectBalances(XRP(150), USD(100), ammBobXRP_USD.tokens())); } { // simple XRP -> USD through offer and sendmax Env env(*this, features); - fund( - env, - gw, - {alice, carol, bob}, - XRP(10'000), - {USD(150)}, - Fund::All); + fund(env, gw, {alice, carol, bob}, XRP(10'000), {USD(150)}, Fund::All); AMM ammBob(env, bob, XRP(100), USD(150)); env(pay(alice, carol, USD(50)), path(~USD), sendmax(XRP(50))); - BEAST_EXPECT(expectLedgerEntryRoot( - env, alice, xrpMinusFee(env, 10'000 - 50))); - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(10'000) - XRP(100) - ammCrtFee(env))); + BEAST_EXPECT(expectLedgerEntryRoot(env, alice, xrpMinusFee(env, 10'000 - 50))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(10'000) - XRP(100) - ammCrtFee(env))); BEAST_EXPECT(expectHolding(env, bob, USD(0))); BEAST_EXPECT(expectHolding(env, carol, USD(200))); - BEAST_EXPECT( - ammBob.expectBalances(XRP(150), USD(100), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(XRP(150), USD(100), ammBob.tokens())); } { // simple USD -> XRP through offer and sendmax Env env(*this, features); - fund( - env, - gw, - {alice, carol, bob}, - XRP(10'000), - {USD(100)}, - Fund::All); + fund(env, gw, {alice, carol, bob}, XRP(10'000), {USD(100)}, Fund::All); AMM ammBob(env, bob, USD(100), XRP(150)); env(pay(alice, carol, XRP(50)), path(~XRP), sendmax(USD(50))); BEAST_EXPECT(expectHolding(env, alice, USD(50))); - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(10'000) - XRP(150) - ammCrtFee(env))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(10'000) - XRP(150) - ammCrtFee(env))); BEAST_EXPECT(expectHolding(env, bob, USD(0))); BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRP(10'000 + 50))); - BEAST_EXPECT( - ammBob.expectBalances(USD(150), XRP(100), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(USD(150), XRP(100), ammBob.tokens())); } { // test unfunded offers are removed when payment succeeds @@ -2039,10 +1829,7 @@ private: BEAST_EXPECT(isOffer(env, bob, BTC(50), USD(50))); BEAST_EXPECT(isOffer(env, bob, BTC(40), EUR(50))); - env(pay(alice, carol, USD(50)), - path(~USD), - path(~EUR, ~USD), - sendmax(BTC(60))); + env(pay(alice, carol, USD(50)), path(~USD), path(~EUR, ~USD), sendmax(BTC(60))); env.require(balance(alice, BTC(10))); env.require(balance(bob, BTC(50))); @@ -2054,8 +1841,7 @@ private: // found unfunded BEAST_EXPECT(!isOffer(env, bob, BTC(40), EUR(50))); // unchanged - BEAST_EXPECT( - ammBob.expectBalances(EUR(100), USD(150), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(EUR(100), USD(150), ammBob.tokens())); } { // test unfunded offers are removed when the payment fails. @@ -2094,8 +1880,7 @@ private: // unfund offer env(pay(bob, gw, EUR(50))); - BEAST_EXPECT(ammBobBTC_USD.expectBalances( - BTC(50), USD(50), ammBobBTC_USD.tokens())); + BEAST_EXPECT(ammBobBTC_USD.expectBalances(BTC(50), USD(50), ammBobBTC_USD.tokens())); BEAST_EXPECT(isOffer(env, bob, BTC(60), EUR(50))); BEAST_EXPECT(isOffer(env, carol, BTC(1'000), EUR(1))); BEAST_EXPECT(isOffer(env, bob, EUR(50), USD(50))); @@ -2139,21 +1924,19 @@ private: }(); BEAST_EXPECT(flowResult.removableOffers.size() == 1); - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) { - if (flowResult.removableOffers.empty()) - return false; - Sandbox sb(&view, tapNONE); - for (auto const& o : flowResult.removableOffers) - if (auto ok = sb.peek(keylet::offer(o))) - offerDelete(sb, ok, flowJournal); - sb.apply(view); - return true; - }); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { + if (flowResult.removableOffers.empty()) + return false; + Sandbox sb(&view, tapNONE); + for (auto const& o : flowResult.removableOffers) + if (auto ok = sb.peek(keylet::offer(o))) + offerDelete(sb, ok, flowJournal); + sb.apply(view); + return true; + }); // used in payment, but since payment failed should be untouched - BEAST_EXPECT(ammBobBTC_USD.expectBalances( - BTC(50), USD(50), ammBobBTC_USD.tokens())); + BEAST_EXPECT(ammBobBTC_USD.expectBalances(BTC(50), USD(50), ammBobBTC_USD.tokens())); BEAST_EXPECT(isOffer(env, carol, BTC(1'000), EUR(1))); // found unfunded BEAST_EXPECT(!isOffer(env, bob, BTC(60), EUR(50))); @@ -2190,8 +1973,7 @@ private: txflags(tfNoRippleDirect | tfPartialPayment)); BEAST_EXPECT(expectHolding(env, carol, EUR(1))); - BEAST_EXPECT(ammBob.expectBalances( - USD(8.4), XRPAmount{20}, ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(USD(8.4), XRPAmount{20}, ammBob.tokens())); } } @@ -2205,12 +1987,7 @@ private: // payment via AMM Env env(*this, features); - fund( - env, - gw, - {alice, bob, carol}, - XRP(1'000), - {USD(1'000), GBP(1'000)}); + fund(env, gw, {alice, bob, carol}, XRP(1'000), {USD(1'000), GBP(1'000)}); env(rate(gw, 1.25)); env.close(); @@ -2228,22 +2005,17 @@ private: if (!features[fixAMMv1_1]) { // 120GBP is swapped in for 107.1428USD - BEAST_EXPECT(amm.expectBalances( - GBP(1'120), - STAmount{USD, UINT64_C(892'8571428571428), -13}, - amm.tokens())); + BEAST_EXPECT( + amm.expectBalances(GBP(1'120), STAmount{USD, UINT64_C(892'8571428571428), -13}, amm.tokens())); } else { - BEAST_EXPECT(amm.expectBalances( - GBP(1'120), - STAmount{USD, UINT64_C(892'8571428571429), -13}, - amm.tokens())); + BEAST_EXPECT( + amm.expectBalances(GBP(1'120), STAmount{USD, UINT64_C(892'8571428571429), -13}, amm.tokens())); } // 25% of 85.7142USD is paid in tr fee // 85.7142*1.25 = 107.1428USD - BEAST_EXPECT(expectHolding( - env, carol, STAmount(USD, UINT64_C(1'085'714285714286), -12))); + BEAST_EXPECT(expectHolding(env, carol, STAmount(USD, UINT64_C(1'085'714285714286), -12))); } { @@ -2251,12 +2023,7 @@ private: Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(1'000), EUR(1'000), GBP(1'000)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(1'000), EUR(1'000), GBP(1'000)}); env(rate(gw, 1.25)); env.close(); @@ -2278,29 +2045,19 @@ private: // consumed offer is 120GBP/120EUR // ed doesn't pay tr fee BEAST_EXPECT(expectHolding(env, ed, EUR(880), GBP(1'120))); - BEAST_EXPECT( - expectOffers(env, ed, 1, {Amounts{GBP(880), EUR(880)}})); + BEAST_EXPECT(expectOffers(env, ed, 1, {Amounts{GBP(880), EUR(880)}})); // 25% on 96EUR is paid in tr fee 96*1.25 = 120EUR // 96EUR is swapped in for 87.5912USD - BEAST_EXPECT(amm.expectBalances( - EUR(1'096), - STAmount{USD, UINT64_C(912'4087591240876), -13}, - amm.tokens())); + BEAST_EXPECT(amm.expectBalances(EUR(1'096), STAmount{USD, UINT64_C(912'4087591240876), -13}, amm.tokens())); // 25% on 70.0729USD is paid in tr fee 70.0729*1.25 = 87.5912USD - BEAST_EXPECT(expectHolding( - env, carol, STAmount(USD, UINT64_C(1'070'07299270073), -11))); + BEAST_EXPECT(expectHolding(env, carol, STAmount(USD, UINT64_C(1'070'07299270073), -11))); } { // Payment via AMM, AMM Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(1'000), EUR(1'000), GBP(1'000)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(1'000), EUR(1'000), GBP(1'000)}); env(rate(gw, 1.25)); env.close(); @@ -2319,10 +2076,8 @@ private: // alice buys 107.1428EUR with 120GBP and pays 25% tr fee on // 120GBP 1,000 - 120*1.25 = 850GBP 120GBP is swapped in for // 107.1428EUR - BEAST_EXPECT(amm1.expectBalances( - GBP(1'120), - STAmount{EUR, UINT64_C(892'8571428571428), -13}, - amm1.tokens())); + BEAST_EXPECT( + amm1.expectBalances(GBP(1'120), STAmount{EUR, UINT64_C(892'8571428571428), -13}, amm1.tokens())); // 25% on 85.7142EUR is paid in tr fee 85.7142*1.25 = // 107.1428EUR 85.7142EUR is swapped in for 78.9473USD BEAST_EXPECT(amm2.expectBalances( @@ -2335,10 +2090,8 @@ private: // alice buys 107.1428EUR with 120GBP and pays 25% tr fee on // 120GBP 1,000 - 120*1.25 = 850GBP 120GBP is swapped in for // 107.1428EUR - BEAST_EXPECT(amm1.expectBalances( - GBP(1'120), - STAmount{EUR, UINT64_C(892'8571428571429), -13}, - amm1.tokens())); + BEAST_EXPECT( + amm1.expectBalances(GBP(1'120), STAmount{EUR, UINT64_C(892'8571428571429), -13}, amm1.tokens())); // 25% on 85.7142EUR is paid in tr fee 85.7142*1.25 = // 107.1428EUR 85.7142EUR is swapped in for 78.9473USD BEAST_EXPECT(amm2.expectBalances( @@ -2347,8 +2100,7 @@ private: amm2.tokens())); } // 25% on 63.1578USD is paid in tr fee 63.1578*1.25 = 78.9473USD - BEAST_EXPECT(expectHolding( - env, carol, STAmount(USD, UINT64_C(1'063'157894736842), -12))); + BEAST_EXPECT(expectHolding(env, carol, STAmount(USD, UINT64_C(1'063'157894736842), -12))); } { // AMM offer crossing @@ -2363,8 +2115,7 @@ private: env.close(); // 100USD is swapped in for 100EUR - BEAST_EXPECT( - amm.expectBalances(USD(1'100), EUR(1'000), amm.tokens())); + BEAST_EXPECT(amm.expectBalances(USD(1'100), EUR(1'000), amm.tokens())); // alice pays 25% tr fee on 100USD 1100-100*1.25 = 975USD BEAST_EXPECT(expectHolding(env, alice, USD(975), EUR(1'200))); BEAST_EXPECT(expectOffers(env, alice, 0)); @@ -2374,12 +2125,7 @@ private: // Payment via AMM with limit quality Env env(*this, features); - fund( - env, - gw, - {alice, bob, carol}, - XRP(1'000), - {USD(1'000), GBP(1'000)}); + fund(env, gw, {alice, bob, carol}, XRP(1'000), {USD(1'000), GBP(1'000)}); env(rate(gw, 1.25)); env.close(); @@ -2396,13 +2142,9 @@ private: // alice buys 125USD with 142.8571GBP and pays 25% tr fee // on 142.8571GBP // 1,000 - 142.8571*1.25 = 821.4285GBP - BEAST_EXPECT(expectHolding( - env, alice, STAmount(GBP, UINT64_C(821'4285714285712), -13))); + BEAST_EXPECT(expectHolding(env, alice, STAmount(GBP, UINT64_C(821'4285714285712), -13))); // 142.8571GBP is swapped in for 125USD - BEAST_EXPECT(amm.expectBalances( - STAmount{GBP, UINT64_C(1'142'857142857143), -12}, - USD(875), - amm.tokens())); + BEAST_EXPECT(amm.expectBalances(STAmount{GBP, UINT64_C(1'142'857142857143), -12}, USD(875), amm.tokens())); // 25% on 100USD is paid in tr fee // 100*1.25 = 125USD BEAST_EXPECT(expectHolding(env, carol, USD(1'100))); @@ -2412,12 +2154,7 @@ private: // than requested Env env(*this, features); - fund( - env, - gw, - {alice, bob, carol}, - XRP(1'000), - {USD(1'200), GBP(1'200)}); + fund(env, gw, {alice, bob, carol}, XRP(1'000), {USD(1'200), GBP(1'200)}); env(rate(gw, 1.25)); env.close(); @@ -2438,23 +2175,17 @@ private: // 1,200 - 24*1.25 = 1,170GBP BEAST_EXPECT(expectHolding(env, alice, GBP(1'170))); // 24GBP is swapped in for 28.125USD - BEAST_EXPECT(amm.expectBalances( - GBP(1'024), USD(1'171.875), amm.tokens())); + BEAST_EXPECT(amm.expectBalances(GBP(1'024), USD(1'171.875), amm.tokens())); } else { // alice buys 28.125USD with 24GBP and pays 25% tr fee // on 24GBP // 1,200 - 24*1.25 =~ 1,170GBP - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{GBP, UINT64_C(1'169'999999999999), -12})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{GBP, UINT64_C(1'169'999999999999), -12})); // 24GBP is swapped in for 28.125USD - BEAST_EXPECT(amm.expectBalances( - STAmount{GBP, UINT64_C(1'024'000000000001), -12}, - USD(1'171.875), - amm.tokens())); + BEAST_EXPECT( + amm.expectBalances(STAmount{GBP, UINT64_C(1'024'000000000001), -12}, USD(1'171.875), amm.tokens())); } // 25% on 22.5USD is paid in tr fee // 22.5*1.25 = 28.125USD @@ -2466,12 +2197,7 @@ private: Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(1'400), EUR(1'400), GBP(1'400)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(1'400), EUR(1'400), GBP(1'400)}); env(rate(gw, 1.25)); env.close(); @@ -2493,10 +2219,7 @@ private: // alice buys 70.4210EUR with 70.4210GBP via the offer // and pays 25% tr fee on 70.4210GBP // 1,400 - 70.4210*1.25 = 1400 - 88.0262 = 1311.9736GBP - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{GBP, UINT64_C(1'311'973684210527), -12})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{GBP, UINT64_C(1'311'973684210527), -12})); // ed doesn't pay tr fee, the balances reflect consumed offer // 70.4210GBP/70.4210EUR BEAST_EXPECT(expectHolding( @@ -2523,10 +2246,7 @@ private: // alice buys 70.4210EUR with 70.4210GBP via the offer // and pays 25% tr fee on 70.4210GBP // 1,400 - 70.4210*1.25 = 1400 - 88.0262 = 1311.9736GBP - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{GBP, UINT64_C(1'311'973684210525), -12})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{GBP, UINT64_C(1'311'973684210525), -12})); // ed doesn't pay tr fee, the balances reflect consumed offer // 70.4210GBP/70.4210EUR BEAST_EXPECT(expectHolding( @@ -2549,8 +2269,7 @@ private: amm.tokens())); } // 25% on 59.7321USD is paid in tr fee 59.7321*1.25 = 74.6651USD - BEAST_EXPECT(expectHolding( - env, carol, STAmount(USD, UINT64_C(1'459'732142857143), -12))); + BEAST_EXPECT(expectHolding(env, carol, STAmount(USD, UINT64_C(1'459'732142857143), -12))); } { // Payment via AMM and offer with limit quality, deliver less @@ -2558,12 +2277,7 @@ private: Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(1'400), EUR(1'400), GBP(1'400)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(1'400), EUR(1'400), GBP(1'400)}); env(rate(gw, 1.25)); env.close(); @@ -2585,10 +2299,7 @@ private: // alice buys 53.3322EUR with 56.3368GBP via the amm // and pays 25% tr fee on 56.3368GBP // 1,400 - 56.3368*1.25 = 1400 - 70.4210 = 1329.5789GBP - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{GBP, UINT64_C(1'329'578947368421), -12})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{GBP, UINT64_C(1'329'578947368421), -12})); //// 25% on 56.3368EUR is paid in tr fee 56.3368*1.25 ///= 70.4210EUR // 56.3368GBP is swapped in for 53.3322EUR @@ -2602,10 +2313,7 @@ private: // alice buys 53.3322EUR with 56.3368GBP via the amm // and pays 25% tr fee on 56.3368GBP // 1,400 - 56.3368*1.25 = 1400 - 70.4210 = 1329.5789GBP - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{GBP, UINT64_C(1'329'57894736842), -11})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{GBP, UINT64_C(1'329'57894736842), -11})); //// 25% on 56.3368EUR is paid in tr fee 56.3368*1.25 ///= 70.4210EUR // 56.3368GBP is swapped in for 53.3322EUR @@ -2629,8 +2337,7 @@ private: STAmount{EUR, UINT64_C(957'3341836734693), -13}, STAmount{USD, UINT64_C(1'340'267857142857), -12}}})); // 25% on 47.7857USD is paid in tr fee 47.7857*1.25 = 59.7321USD - BEAST_EXPECT(expectHolding( - env, carol, STAmount(USD, UINT64_C(1'447'785714285714), -12))); + BEAST_EXPECT(expectHolding(env, carol, STAmount(USD, UINT64_C(1'447'785714285714), -12))); } { // Payment via AMM, AMM with limit quality, deliver less @@ -2638,12 +2345,7 @@ private: Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(1'400), EUR(1'400), GBP(1'400)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(1'400), EUR(1'400), GBP(1'400)}); env(rate(gw, 1.25)); env.close(); @@ -2663,10 +2365,7 @@ private: // alice buys 53.3322EUR with 107.5308GBP // 25% on 86.0246GBP is paid in tr fee // 1,400 - 86.0246*1.25 = 1400 - 107.5308 = 1229.4691GBP - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{GBP, UINT64_C(1'292'469135802469), -12})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{GBP, UINT64_C(1'292'469135802469), -12})); // 86.0246GBP is swapped in for 79.2106EUR BEAST_EXPECT(amm1.expectBalances( STAmount{GBP, UINT64_C(1'086'024691358025), -12}, @@ -2684,10 +2383,7 @@ private: // alice buys 53.3322EUR with 107.5308GBP // 25% on 86.0246GBP is paid in tr fee // 1,400 - 86.0246*1.25 = 1400 - 107.5308 = 1229.4691GBP - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{GBP, UINT64_C(1'292'469135802466), -12})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{GBP, UINT64_C(1'292'469135802466), -12})); // 86.0246GBP is swapped in for 79.2106EUR BEAST_EXPECT(amm1.expectBalances( STAmount{GBP, UINT64_C(1'086'024691358027), -12}, @@ -2701,20 +2397,14 @@ private: amm2.tokens())); } // 25% on 66.7432USD is paid in tr fee 66.7432*1.25 = 83.4291USD - BEAST_EXPECT(expectHolding( - env, carol, STAmount(USD, UINT64_C(1'466'743295019157), -12))); + BEAST_EXPECT(expectHolding(env, carol, STAmount(USD, UINT64_C(1'466'743295019157), -12))); } { // Payment by the issuer via AMM, AMM with limit quality, // deliver less than requested Env env(*this, features); - fund( - env, - gw, - {alice, bob, carol}, - XRP(1'000), - {USD(1'400), EUR(1'400), GBP(1'400)}); + fund(env, gw, {alice, bob, carol}, XRP(1'000), {USD(1'400), EUR(1'400), GBP(1'400)}); env(rate(gw, 1.25)); env.close(); @@ -2758,8 +2448,7 @@ private: amm2.tokens())); } // 25% on 81.1111USD is paid in tr fee 81.1111*1.25 = 101.3888USD - BEAST_EXPECT(expectHolding( - env, carol, STAmount{USD, UINT64_C(1'481'111111111111), -12})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(1'481'111111111111), -12})); } } @@ -2786,8 +2475,7 @@ private: sendmax(XRP(100)), txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality)); - BEAST_EXPECT( - ammBob.expectBalances(XRP(1'050), USD(1'000), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(XRP(1'050), USD(1'000), ammBob.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(2'050))); BEAST_EXPECT(expectOffers(env, bob, 1, {{{XRP(100), USD(50)}}})); } @@ -2804,13 +2492,7 @@ private: Env env(*this, testable_amendments()); // Note, if alice doesn't have default ripple, then pay // fails with tecPATH_DRY. - fund( - env, - gw, - {alice, bob}, - XRP(10'000), - {USD(200), EUR(200)}, - Fund::All); + fund(env, gw, {alice, bob}, XRP(10'000), {USD(200), EUR(200)}, Fund::All); AMM ammAliceXRP_USD(env, alice, XRP(100), USD(101)); AMM ammAliceXRP_EUR(env, alice, XRP(100), EUR(101)); @@ -2828,13 +2510,7 @@ private: Env env(*this); // Note, if alice doesn't have default ripple, then pay fails // with tecPATH_DRY. - fund( - env, - gw, - {alice, bob}, - XRP(10'000), - {USD(200), EUR(200)}, - Fund::All); + fund(env, gw, {alice, bob}, XRP(10'000), {USD(200), EUR(200)}, Fund::All); AMM ammAliceXRP_USD(env, alice, XRP(100), USD(100)); AMM ammAliceXRP_EUR(env, alice, XRP(100), EUR(100)); @@ -2852,13 +2528,7 @@ private: Env env(*this); // Note, if alice doesn't have default ripple, then pay fails // with tecPATH_DRY. - fund( - env, - gw, - {alice, bob}, - XRP(10'000), - {USD(200), EUR(200), JPY(200)}, - Fund::All); + fund(env, gw, {alice, bob}, XRP(10'000), {USD(200), EUR(200), JPY(200)}, Fund::All); AMM ammAliceXRP_USD(env, alice, XRP(100), USD(100)); AMM ammAliceXRP_EUR(env, alice, XRP(100), EUR(100)); @@ -2897,11 +2567,9 @@ private: // offer, removes 999 more as unfunded, then hits the step limit. env(offer(alice, USD(1'000), XRP(1'000))); if (!features[fixAMMv1_1]) - env.require(balance( - alice, STAmount{USD, UINT64_C(2'050126257867561), -15})); + env.require(balance(alice, STAmount{USD, UINT64_C(2'050126257867561), -15})); else - env.require(balance( - alice, STAmount{USD, UINT64_C(2'050125257867587), -15})); + env.require(balance(alice, STAmount{USD, UINT64_C(2'050125257867587), -15})); env.require(owners(alice, 2)); env.require(balance(bob, USD(0))); env.require(owners(bob, 1'001)); @@ -2930,25 +2598,14 @@ private: Env env(*this, features); fund(env, gw, {alice, bob, carol}, XRP(10'000)); env.trust(USD(100), alice, bob, carol); - env(pay(alice, bob, USD(10)), - deliver_min(USD(10)), - ter(temBAD_AMOUNT)); - env(pay(alice, bob, USD(10)), - deliver_min(USD(-5)), - txflags(tfPartialPayment), - ter(temBAD_AMOUNT)); - env(pay(alice, bob, USD(10)), - deliver_min(XRP(5)), - txflags(tfPartialPayment), - ter(temBAD_AMOUNT)); + env(pay(alice, bob, USD(10)), deliver_min(USD(10)), ter(temBAD_AMOUNT)); + env(pay(alice, bob, USD(10)), deliver_min(USD(-5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); + env(pay(alice, bob, USD(10)), deliver_min(XRP(5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay(alice, bob, USD(10)), deliver_min(Account(carol)["USD"](5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); - env(pay(alice, bob, USD(10)), - deliver_min(USD(15)), - txflags(tfPartialPayment), - ter(temBAD_AMOUNT)); + env(pay(alice, bob, USD(10)), deliver_min(USD(15)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay(gw, carol, USD(50))); AMM ammCarol(env, carol, XRP(10), USD(15)); env(pay(alice, bob, USD(10)), @@ -2957,9 +2614,7 @@ private: txflags(tfPartialPayment), sendmax(XRP(5)), ter(tecPATH_PARTIAL)); - env.require(balance( - alice, - drops(10'000'000'000 - env.current()->fees().base.drops()))); + env.require(balance(alice, drops(10'000'000'000 - env.current()->fees().base.drops()))); env.require(balance(bob, XRP(10'000))); } @@ -2994,8 +2649,7 @@ private: deliver_min(USD(200)), txflags(tfPartialPayment), sendmax(XRP(1'100))); - BEAST_EXPECT( - ammBob.expectBalances(XRP(6'600), USD(1'000), ammBob.tokens())); + BEAST_EXPECT(ammBob.expectBalances(XRP(6'600), USD(1'000), ammBob.tokens())); env.require(balance(carol, USD(200))); } @@ -3019,8 +2673,7 @@ private: sendmax(XRP(200))); env.require(balance(bob, USD(0))); env.require(balance(carol, USD(200))); - BEAST_EXPECT(ammDan.expectBalances( - XRP(1'100), USD(1'000), ammDan.tokens())); + BEAST_EXPECT(ammDan.expectBalances(XRP(1'100), USD(1'000), ammDan.tokens())); } else { @@ -3030,12 +2683,9 @@ private: txflags(tfPartialPayment), sendmax(XRPAmount(200'000'001))); env.require(balance(bob, USD(0))); - env.require(balance( - carol, STAmount{USD, UINT64_C(200'00000090909), -11})); + env.require(balance(carol, STAmount{USD, UINT64_C(200'00000090909), -11})); BEAST_EXPECT(ammDan.expectBalances( - XRPAmount{1'100'000'001}, - STAmount{USD, UINT64_C(999'99999909091), -11}, - ammDan.tokens())); + XRPAmount{1'100'000'001}, STAmount{USD, UINT64_C(999'99999909091), -11}, ammDan.tokens())); } } } @@ -3068,18 +2718,14 @@ private: // Make sure the payment works if PaymentAuth is not involved. env(pay(becky, becky, USD(10)), path(~USD), sendmax(XRP(10))); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(107'692'308), USD(130), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount(107'692'308), USD(130), ammAlice.tokens())); // becky decides to require authorization for deposits. env(fset(becky, asfDepositAuth)); env.close(); // becky pays herself again. - env(pay(becky, becky, USD(10)), - path(~USD), - sendmax(XRP(10)), - ter(tesSUCCESS)); + env(pay(becky, becky, USD(10)), path(~USD), sendmax(XRP(10)), ter(tesSUCCESS)); env.close(); } @@ -3126,9 +2772,7 @@ private: // Note that even though alice is paying bob in XRP, the payment // is still not allowed since the payment passes through an // offer. - env(pay(alice, bob, drops(1)), - sendmax(USD(1)), - ter(tecNO_PERMISSION)); + env(pay(alice, bob, drops(1)), sendmax(USD(1)), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(bobXrpBalance == env.balance(bob, XRP)); @@ -3174,8 +2818,7 @@ private: env(pay(alice, bob, drops(1)), sendmax(USD(1))); env.close(); - BEAST_EXPECT(ammCarol.expectBalances( - USD(101), XRPAmount(100), ammCarol.tokens())); + BEAST_EXPECT(ammCarol.expectBalances(USD(101), XRPAmount(100), ammCarol.tokens())); } void @@ -3240,8 +2883,7 @@ private: // test: can buy more assets on that line env(offer(bob, G1["USD"](5), XRP(25))); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(525), G1["USD"](100), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(525), G1["USD"](100), ammAlice.tokens())); } { @@ -3296,15 +2938,11 @@ private: // Is cleared via a TrustSet with ClearFreeze flag // test: sets LowFreeze | HighFreeze flags env(trust(G1, bob["USD"](0), tfClearFreeze)); - auto affected = env.meta()->getJson( - JsonOptions::none)[sfAffectedNodes.fieldName]; + auto affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, 2u))) return; - auto ff = - affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; - BEAST_EXPECT( - ff[sfLowLimit.fieldName] == - G1["USD"](0).value().getJson(JsonOptions::none)); + auto ff = affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; + BEAST_EXPECT(ff[sfLowLimit.fieldName] == G1["USD"](0).value().getJson(JsonOptions::none)); BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfLowFreeze)); BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfHighFreeze)); env.close(); @@ -3351,10 +2989,7 @@ private: // Account without GlobalFreeze (proving operations normally // work) // test: visible offers where taker_pays is unfrozen issuer - auto offers = env.rpc( - "book_offers", - std::string("USD/") + G1.human(), - "XRP")[jss::result][jss::offers]; + auto offers = env.rpc("book_offers", std::string("USD/") + G1.human(), "XRP")[jss::result][jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 1u))) return; std::set accounts; @@ -3365,10 +3000,7 @@ private: BEAST_EXPECT(accounts.find(A2.human()) != std::end(accounts)); // test: visible offers where taker_gets is unfrozen issuer - offers = env.rpc( - "book_offers", - "XRP", - std::string("USD/") + G1.human())[jss::result][jss::offers]; + offers = env.rpc("book_offers", "XRP", std::string("USD/") + G1.human())[jss::result][jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 1u))) return; accounts.clear(); @@ -3421,17 +3053,11 @@ private: { // test: book_offers shows offers // (should these actually be filtered?) - auto offers = env.rpc( - "book_offers", - "XRP", - std::string("USD/") + G1.human())[jss::result][jss::offers]; + auto offers = env.rpc("book_offers", "XRP", std::string("USD/") + G1.human())[jss::result][jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 1u))) return; - offers = env.rpc( - "book_offers", - std::string("USD/") + G1.human(), - "XRP")[jss::result][jss::offers]; + offers = env.rpc("book_offers", std::string("USD/") + G1.human(), "XRP")[jss::result][jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 1u))) return; } @@ -3482,19 +3108,16 @@ private: env(pay(A2, G1, G1["USD"](1)), paths(G1["USD"]), sendmax(XRP(1))); env.close(); - BEAST_EXPECT( - ammA3.expectBalances(XRP(1'001), G1["USD"](1'000), ammA3.tokens())); + BEAST_EXPECT(ammA3.expectBalances(XRP(1'001), G1["USD"](1'000), ammA3.tokens())); // test: someone else creates an offer providing liquidity env(offer(A4, XRP(999), G1["USD"](999))); env.close(); // The offer consumes AMM offer - BEAST_EXPECT( - ammA3.expectBalances(XRP(1'000), G1["USD"](1'001), ammA3.tokens())); + BEAST_EXPECT(ammA3.expectBalances(XRP(1'000), G1["USD"](1'001), ammA3.tokens())); // test: AMM line is frozen - auto const a3am = - STAmount{Issue{to_currency("USD"), ammA3.ammAccount()}, 0}; + auto const a3am = STAmount{Issue{to_currency("USD"), ammA3.ammAccount()}, 0}; env(trust(G1, a3am, tfSetFreeze)); auto const info = ammA3.ammRpcInfo(); BEAST_EXPECT(info[jss::amm][jss::asset2_frozen].asBool()); @@ -3504,8 +3127,7 @@ private: env(pay(A2, G1, G1["USD"](1)), paths(G1["USD"]), sendmax(XRP(1))); env.close(); // AMM is not consumed - BEAST_EXPECT( - ammA3.expectBalances(XRP(1'000), G1["USD"](1'001), ammA3.tokens())); + BEAST_EXPECT(ammA3.expectBalances(XRP(1'000), G1["USD"](1'001), ammA3.tokens())); // removal buy successful OfferCreate // test: freeze the new offer @@ -3560,16 +3182,13 @@ private: std::nullopt, ms, ter(tesSUCCESS)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), ammAlice.tokens())); ammAlice.deposit(alice, 1'000'000); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); ammAlice.withdraw(alice, 1'000'000); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), ammAlice.tokens())); ammAlice.vote({}, 1'000); BEAST_EXPECT(ammAlice.expectTradingFee(1'000)); @@ -3577,8 +3196,7 @@ private: env(ammAlice.bid({.account = alice, .bidMin = 100}), ms).close(); BEAST_EXPECT(ammAlice.expectAuctionSlot(100, 0, IOUAmount{4'000})); // 4000 tokens burnt - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{9'996'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{9'996'000, 0})); } void @@ -3592,12 +3210,7 @@ private: Env env(*this, features); - fund( - env, - gw, - {alice, bob, carol}, - XRP(10'000), - {USD(2'000), EUR(1'000)}); + fund(env, gw, {alice, bob, carol}, XRP(10'000), {USD(2'000), EUR(1'000)}); AMM bobXRP_USD(env, bob, XRP(1'000), USD(1'000)); AMM bobUSD_EUR(env, bob, USD(1'000), EUR(1'000)); @@ -3624,12 +3237,7 @@ private: env.trust(USD(1'000), alice, bob); env.trust(EUR(1'000), alice, bob); env.close(); - fund( - env, - bob, - {alice, gw}, - {BobUSD(100), BobEUR(100)}, - Fund::IOUOnly); + fund(env, bob, {alice, gw}, {BobUSD(100), BobEUR(100)}, Fund::IOUOnly); env.close(); AMM ammBobXRP_USD(env, bob, XRP(100), BobUSD(100)); @@ -3662,10 +3270,7 @@ private: AMM ammBob(env, bob, XRP(100), USD(100)); // payment path: XRP -> XRP/USD -> USD/XRP - env(pay(alice, carol, XRP(100)), - path(~USD, ~XRP), - txflags(tfNoRippleDirect), - ter(temBAD_SEND_XRP_PATHS)); + env(pay(alice, carol, XRP(100)), path(~USD, ~XRP), txflags(tfNoRippleDirect), ter(temBAD_SEND_XRP_PATHS)); } { @@ -3757,9 +3362,7 @@ private: using namespace jtx; // For now, just disable SAV entirely, which locks in the small Number // mantissas in the transaction engine - FeatureBitset const all{ - testable_amendments() - featureSingleAssetVault - - featureLendingProtocol}; + FeatureBitset const all{testable_amendments() - featureSingleAssetVault - featureLendingProtocol}; testFalseDry(all); testBookStep(all); @@ -3775,9 +3378,7 @@ private: using namespace jtx; // For now, just disable SAV entirely, which locks in the small Number // mantissas in the transaction engine - FeatureBitset const all{ - testable_amendments() - featureSingleAssetVault - - featureLendingProtocol}; + FeatureBitset const all{testable_amendments() - featureSingleAssetVault - featureLendingProtocol}; testStepLimit(all); testStepLimit(all - fixAMMv1_1 - fixAMMv1_3); } @@ -3788,9 +3389,7 @@ private: using namespace jtx; // For now, just disable SAV entirely, which locks in the small Number // mantissas in the transaction engine - FeatureBitset const all{ - testable_amendments() - featureSingleAssetVault - - featureLendingProtocol}; + FeatureBitset const all{testable_amendments() - featureSingleAssetVault - featureLendingProtocol}; test_convert_all_of_an_asset(all); test_convert_all_of_an_asset(all - fixAMMv1_1 - fixAMMv1_3); } @@ -3800,9 +3399,7 @@ private: { // For now, just disable SAV entirely, which locks in the small Number // mantissas in the transaction engine - FeatureBitset const all{ - jtx::testable_amendments() - featureSingleAssetVault - - featureLendingProtocol}; + FeatureBitset const all{jtx::testable_amendments() - featureSingleAssetVault - featureLendingProtocol}; testPayment(all); testPayIOU(); } @@ -3813,9 +3410,7 @@ private: using namespace test::jtx; // For now, just disable SAV entirely, which locks in the small Number // mantissas in the transaction engine - FeatureBitset const sa{ - testable_amendments() - featureSingleAssetVault - - featureLendingProtocol}; + FeatureBitset const sa{testable_amendments() - featureSingleAssetVault - featureLendingProtocol}; testRippleState(sa); testGlobalFreeze(sa); testOffersWhenFrozen(sa); diff --git a/src/test/app/AMM_test.cpp b/src/test/app/AMM_test.cpp index 55bf4aa0a3..14b97f30f1 100644 --- a/src/test/app/AMM_test.cpp +++ b/src/test/app/AMM_test.cpp @@ -39,8 +39,7 @@ private: { // For now, just disable SAV entirely, which locks in the small Number // mantissas - return jtx::testable_amendments() - featureSingleAssetVault - - featureLendingProtocol; + return jtx::testable_amendments() - featureSingleAssetVault - featureLendingProtocol; } void @@ -54,8 +53,7 @@ private: // XRP to IOU, with featureSingleAssetVault testAMM( [&](AMM& ammAlice, Env&) { - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); }, {}, 0, @@ -66,8 +64,7 @@ private: // XRP to IOU, without featureSingleAssetVault testAMM( [&](AMM& ammAlice, Env&) { - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); }, {}, 0, @@ -77,8 +74,7 @@ private: // IOU to IOU testAMM( [&](AMM& ammAlice, Env&) { - BEAST_EXPECT(ammAlice.expectBalances( - USD(20'000), BTC(0.5), IOUAmount{100, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(20'000), BTC(0.5), IOUAmount{100, 0})); }, {{USD(20'000), BTC(0.5)}}); @@ -90,8 +86,7 @@ private: env.close(); // no transfer fee on create AMM ammAlice(env, alice, USD(20'000), BTC(0.5)); - BEAST_EXPECT(ammAlice.expectBalances( - USD(20'000), BTC(0.5), IOUAmount{100, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(20'000), BTC(0.5), IOUAmount{100, 0})); BEAST_EXPECT(expectHolding(env, alice, USD(0))); BEAST_EXPECT(expectHolding(env, alice, BTC(0))); } @@ -121,8 +116,7 @@ private: env.close(); env(fset(gw, asfGlobalFreeze)); env.close(); - AMM ammAliceFail( - env, alice, XRP(10'000), USD(10'000), ter(tecFROZEN)); + AMM ammAliceFail(env, alice, XRP(10'000), USD(10'000), ter(tecFROZEN)); env(fclear(gw, asfGlobalFreeze)); env.close(); AMM ammAlice(env, alice, XRP(10'000), USD(10'000)); @@ -138,12 +132,8 @@ private: 1'000); // Make sure asset comparison works. - BEAST_EXPECT( - STIssue(sfAsset, STAmount(XRP(2'000)).issue()) == - STIssue(sfAsset, STAmount(XRP(2'000)).issue())); - BEAST_EXPECT( - STIssue(sfAsset, STAmount(XRP(2'000)).issue()) != - STIssue(sfAsset, STAmount(USD(2'000)).issue())); + BEAST_EXPECT(STIssue(sfAsset, STAmount(XRP(2'000)).issue()) == STIssue(sfAsset, STAmount(XRP(2'000)).issue())); + BEAST_EXPECT(STIssue(sfAsset, STAmount(XRP(2'000)).issue()) != STIssue(sfAsset, STAmount(USD(2'000)).issue())); } void @@ -157,8 +147,7 @@ private: { Env env{*this}; fund(env, gw, {alice}, {USD(30'000)}, Fund::All); - AMM ammAlice( - env, alice, XRP(10'000), XRP(10'000), ter(temBAD_AMM_TOKENS)); + AMM ammAlice(env, alice, XRP(10'000), XRP(10'000), ter(temBAD_AMM_TOKENS)); BEAST_EXPECT(!ammAlice.ammExists()); } @@ -166,8 +155,7 @@ private: { Env env{*this}; fund(env, gw, {alice}, {USD(30'000)}, Fund::All); - AMM ammAlice( - env, alice, USD(10'000), USD(10'000), ter(temBAD_AMM_TOKENS)); + AMM ammAlice(env, alice, USD(10'000), USD(10'000), ter(temBAD_AMM_TOKENS)); BEAST_EXPECT(!ammAlice.ammExists()); } @@ -179,11 +167,9 @@ private: BEAST_EXPECT(!ammAlice.ammExists()); AMM ammAlice1(env, alice, XRP(10'000), USD(0), ter(temBAD_AMOUNT)); BEAST_EXPECT(!ammAlice1.ammExists()); - AMM ammAlice2( - env, alice, XRP(10'000), USD(-10'000), ter(temBAD_AMOUNT)); + AMM ammAlice2(env, alice, XRP(10'000), USD(-10'000), ter(temBAD_AMOUNT)); BEAST_EXPECT(!ammAlice2.ammExists()); - AMM ammAlice3( - env, alice, XRP(-10'000), USD(10'000), ter(temBAD_AMOUNT)); + AMM ammAlice3(env, alice, XRP(-10'000), USD(10'000), ter(temBAD_AMOUNT)); BEAST_EXPECT(!ammAlice3.ammExists()); } @@ -191,8 +177,7 @@ private: { Env env{*this}; fund(env, gw, {alice}, {USD(30'000)}, Fund::All); - AMM ammAlice( - env, alice, XRP(10'000), BAD(10'000), ter(temBAD_CURRENCY)); + AMM ammAlice(env, alice, XRP(10'000), BAD(10'000), ter(temBAD_CURRENCY)); BEAST_EXPECT(!ammAlice.ammExists()); } @@ -200,8 +185,7 @@ private: { Env env{*this}; fund(env, gw, {alice}, {USD(30'000)}, Fund::All); - AMM ammAlice( - env, alice, XRP(10'000), USD(40'000), ter(tecUNFUNDED_AMM)); + AMM ammAlice(env, alice, XRP(10'000), USD(40'000), ter(tecUNFUNDED_AMM)); BEAST_EXPECT(!ammAlice.ammExists()); } @@ -209,8 +193,7 @@ private: { Env env{*this}; fund(env, gw, {alice}, {USD(30'000)}, Fund::All); - AMM ammAlice( - env, alice, XRP(40'000), USD(10'000), ter(tecUNFUNDED_AMM)); + AMM ammAlice(env, alice, XRP(40'000), USD(10'000), ter(tecUNFUNDED_AMM)); BEAST_EXPECT(!ammAlice.ammExists()); } @@ -234,10 +217,8 @@ private: } // AMM already exists - testAMM([&](AMM& ammAlice, Env& env) { - AMM ammCarol( - env, carol, XRP(10'000), USD(10'000), ter(tecDUPLICATE)); - }); + testAMM( + [&](AMM& ammAlice, Env& env) { AMM ammCarol(env, carol, XRP(10'000), USD(10'000), ter(tecDUPLICATE)); }); // Invalid flags { @@ -320,8 +301,7 @@ private: // Insufficient reserve, XRP/IOU { Env env(*this); - auto const starting_xrp = - XRP(1'000) + reserve(env, 3) + env.current()->fees().base * 4; + auto const starting_xrp = XRP(1'000) + reserve(env, 3) + env.current()->fees().base * 4; env.fund(starting_xrp, gw); env.fund(starting_xrp, alice); env.trust(USD(2'000), alice); @@ -330,15 +310,13 @@ private: env.close(); env(offer(alice, XRP(101), USD(100))); env(offer(alice, XRP(102), USD(100))); - AMM ammAlice( - env, alice, XRP(1'000), USD(1'000), ter(tecUNFUNDED_AMM)); + AMM ammAlice(env, alice, XRP(1'000), USD(1'000), ter(tecUNFUNDED_AMM)); } // Insufficient reserve, IOU/IOU { Env env(*this); - auto const starting_xrp = - reserve(env, 4) + env.current()->fees().base * 5; + auto const starting_xrp = reserve(env, 4) + env.current()->fees().base * 5; env.fund(starting_xrp, gw); env.fund(starting_xrp, alice); env.trust(USD(2'000), alice); @@ -349,8 +327,7 @@ private: env.close(); env(offer(alice, EUR(101), USD(100))); env(offer(alice, EUR(102), USD(100))); - AMM ammAlice( - env, alice, EUR(1'000), USD(1'000), ter(tecINSUF_RESERVE_LINE)); + AMM ammAlice(env, alice, EUR(1'000), USD(1'000), ter(tecINSUF_RESERVE_LINE)); } // Insufficient fee @@ -377,17 +354,9 @@ private: testAMM([&](AMM& ammAlice, Env& env) { fund(env, gw, {alice}, {EUR(10'000)}, Fund::IOUOnly); AMM ammAMMToken( - env, - alice, - EUR(10'000), - STAmount{ammAlice.lptIssue(), 1'000'000}, - ter(tecAMM_INVALID_TOKENS)); + env, alice, EUR(10'000), STAmount{ammAlice.lptIssue(), 1'000'000}, ter(tecAMM_INVALID_TOKENS)); AMM ammAMMToken1( - env, - alice, - STAmount{ammAlice.lptIssue(), 1'000'000}, - EUR(10'000), - ter(tecAMM_INVALID_TOKENS)); + env, alice, STAmount{ammAlice.lptIssue(), 1'000'000}, EUR(10'000), ter(tecAMM_INVALID_TOKENS)); }); // AMM with two LPTokens from other AMMs. @@ -397,11 +366,7 @@ private: auto const token1 = ammAlice.lptIssue(); auto const token2 = ammAlice1.lptIssue(); AMM ammAMMTokens( - env, - alice, - STAmount{token1, 1'000'000}, - STAmount{token2, 1'000'000}, - ter(tecAMM_INVALID_TOKENS)); + env, alice, STAmount{token1, 1'000'000}, STAmount{token2, 1'000'000}, ter(tecAMM_INVALID_TOKENS)); }); // Issuer has DefaultRipple disabled @@ -413,8 +378,7 @@ private: env.fund(XRP(30'000), alice); env.trust(USD(30'000), alice); env(pay(gw, alice, USD(30'000))); - AMM ammAlice( - env, alice, XRP(10'000), USD(10'000), ter(terNO_RIPPLE)); + AMM ammAlice(env, alice, XRP(10'000), USD(10'000), ter(terNO_RIPPLE)); Account const gw1("gw1"); env.fund(XRP(30'000), gw1); env(fclear(gw1, asfDefaultRipple)); @@ -424,8 +388,7 @@ private: AMM ammGwGw1(env, gw, USD(10'000), USD1(10'000), ter(terNO_RIPPLE)); env.trust(USD1(30'000), alice); env(pay(gw1, alice, USD1(30'000))); - AMM ammAlice1( - env, alice, USD(10'000), USD1(10'000), ter(terNO_RIPPLE)); + AMM ammAlice1(env, alice, USD(10'000), USD1(10'000), ter(terNO_RIPPLE)); } } @@ -438,12 +401,7 @@ private: testAMM([&](AMM& ammAlice, Env& env) { // Invalid flags - ammAlice.deposit( - alice, - 1'000'000, - std::nullopt, - tfWithdrawAll, - ter(temINVALID_FLAG)); + ammAlice.deposit(alice, 1'000'000, std::nullopt, tfWithdrawAll, ter(temINVALID_FLAG)); // Invalid options std::vector>> invalidOptions = { // flags, tokens, asset1In, asset2in, EPrice, tfee - {tfLPToken, - 1'000, - std::nullopt, - USD(100), - std::nullopt, - std::nullopt}, - {tfLPToken, - 1'000, - XRP(100), - std::nullopt, - std::nullopt, - std::nullopt}, - {tfLPToken, - 1'000, - std::nullopt, - std::nullopt, - STAmount{USD, 1, -1}, - std::nullopt}, - {tfLPToken, - std::nullopt, - USD(100), - std::nullopt, - STAmount{USD, 1, -1}, - std::nullopt}, - {tfLPToken, - 1'000, - XRP(100), - std::nullopt, - STAmount{USD, 1, -1}, - std::nullopt}, - {tfLPToken, - 1'000, - std::nullopt, - std::nullopt, - std::nullopt, - 1'000}, - {tfSingleAsset, - 1'000, - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt}, - {tfSingleAsset, - std::nullopt, - std::nullopt, - USD(100), - std::nullopt, - std::nullopt}, - {tfSingleAsset, - std::nullopt, - std::nullopt, - std::nullopt, - STAmount{USD, 1, -1}, - std::nullopt}, - {tfSingleAsset, - std::nullopt, - USD(100), - std::nullopt, - std::nullopt, - 1'000}, - {tfTwoAsset, - 1'000, - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt}, - {tfTwoAsset, - std::nullopt, - XRP(100), - USD(100), - STAmount{USD, 1, -1}, - std::nullopt}, - {tfTwoAsset, - std::nullopt, - XRP(100), - std::nullopt, - std::nullopt, - std::nullopt}, - {tfTwoAsset, - std::nullopt, - XRP(100), - USD(100), - std::nullopt, - 1'000}, - {tfTwoAsset, - std::nullopt, - std::nullopt, - USD(100), - STAmount{USD, 1, -1}, - std::nullopt}, - {tfOneAssetLPToken, - 1'000, - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt}, - {tfOneAssetLPToken, - std::nullopt, - XRP(100), - USD(100), - std::nullopt, - std::nullopt}, - {tfOneAssetLPToken, - std::nullopt, - XRP(100), - std::nullopt, - STAmount{USD, 1, -1}, - std::nullopt}, - {tfOneAssetLPToken, - 1'000, - XRP(100), - std::nullopt, - std::nullopt, - 1'000}, - {tfLimitLPToken, - 1'000, - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt}, - {tfLimitLPToken, - 1'000, - USD(100), - std::nullopt, - std::nullopt, - std::nullopt}, - {tfLimitLPToken, - std::nullopt, - USD(100), - XRP(100), - std::nullopt, - std::nullopt}, - {tfLimitLPToken, - std::nullopt, - XRP(100), - std::nullopt, - STAmount{USD, 1, -1}, - 1'000}, - {tfTwoAssetIfEmpty, - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, - 1'000}, - {tfTwoAssetIfEmpty, - 1'000, - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt}, - {tfTwoAssetIfEmpty, - std::nullopt, - XRP(100), - USD(100), - STAmount{USD, 1, -1}, - std::nullopt}, + {tfLPToken, 1'000, std::nullopt, USD(100), std::nullopt, std::nullopt}, + {tfLPToken, 1'000, XRP(100), std::nullopt, std::nullopt, std::nullopt}, + {tfLPToken, 1'000, std::nullopt, std::nullopt, STAmount{USD, 1, -1}, std::nullopt}, + {tfLPToken, std::nullopt, USD(100), std::nullopt, STAmount{USD, 1, -1}, std::nullopt}, + {tfLPToken, 1'000, XRP(100), std::nullopt, STAmount{USD, 1, -1}, std::nullopt}, + {tfLPToken, 1'000, std::nullopt, std::nullopt, std::nullopt, 1'000}, + {tfSingleAsset, 1'000, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + {tfSingleAsset, std::nullopt, std::nullopt, USD(100), std::nullopt, std::nullopt}, + {tfSingleAsset, std::nullopt, std::nullopt, std::nullopt, STAmount{USD, 1, -1}, std::nullopt}, + {tfSingleAsset, std::nullopt, USD(100), std::nullopt, std::nullopt, 1'000}, + {tfTwoAsset, 1'000, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + {tfTwoAsset, std::nullopt, XRP(100), USD(100), STAmount{USD, 1, -1}, std::nullopt}, + {tfTwoAsset, std::nullopt, XRP(100), std::nullopt, std::nullopt, std::nullopt}, + {tfTwoAsset, std::nullopt, XRP(100), USD(100), std::nullopt, 1'000}, + {tfTwoAsset, std::nullopt, std::nullopt, USD(100), STAmount{USD, 1, -1}, std::nullopt}, + {tfOneAssetLPToken, 1'000, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + {tfOneAssetLPToken, std::nullopt, XRP(100), USD(100), std::nullopt, std::nullopt}, + {tfOneAssetLPToken, std::nullopt, XRP(100), std::nullopt, STAmount{USD, 1, -1}, std::nullopt}, + {tfOneAssetLPToken, 1'000, XRP(100), std::nullopt, std::nullopt, 1'000}, + {tfLimitLPToken, 1'000, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + {tfLimitLPToken, 1'000, USD(100), std::nullopt, std::nullopt, std::nullopt}, + {tfLimitLPToken, std::nullopt, USD(100), XRP(100), std::nullopt, std::nullopt}, + {tfLimitLPToken, std::nullopt, XRP(100), std::nullopt, STAmount{USD, 1, -1}, 1'000}, + {tfTwoAssetIfEmpty, std::nullopt, std::nullopt, std::nullopt, std::nullopt, 1'000}, + {tfTwoAssetIfEmpty, 1'000, std::nullopt, std::nullopt, std::nullopt, std::nullopt}, + {tfTwoAssetIfEmpty, std::nullopt, XRP(100), USD(100), STAmount{USD, 1, -1}, std::nullopt}, {tfTwoAssetIfEmpty | tfLPToken, std::nullopt, XRP(100), @@ -637,34 +465,23 @@ private: Json::Value jv = Json::objectValue; jv[jss::Account] = alice.human(); jv[jss::TransactionType] = jss::AMMDeposit; - jv[jss::Asset] = - STIssue(sfAsset, XRP).getJson(JsonOptions::none); - jv[jss::Asset2] = - STIssue(sfAsset, USD).getJson(JsonOptions::none); + jv[jss::Asset] = STIssue(sfAsset, XRP).getJson(JsonOptions::none); + jv[jss::Asset2] = STIssue(sfAsset, USD).getJson(JsonOptions::none); jv[jss::Fee] = "-1"; env(jv, ter(temBAD_FEE)); } // Invalid tokens - ammAlice.deposit( - alice, 0, std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); - ammAlice.deposit( - alice, - IOUAmount{-1}, - std::nullopt, - std::nullopt, - ter(temBAD_AMM_TOKENS)); + ammAlice.deposit(alice, 0, std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); + ammAlice.deposit(alice, IOUAmount{-1}, std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); { Json::Value jv = Json::objectValue; jv[jss::Account] = alice.human(); jv[jss::TransactionType] = jss::AMMDeposit; - jv[jss::Asset] = - STIssue(sfAsset, XRP).getJson(JsonOptions::none); - jv[jss::Asset2] = - STIssue(sfAsset, USD).getJson(JsonOptions::none); - jv[jss::LPTokenOut] = - USD(100).value().getJson(JsonOptions::none); + jv[jss::Asset] = STIssue(sfAsset, XRP).getJson(JsonOptions::none); + jv[jss::Asset2] = STIssue(sfAsset, USD).getJson(JsonOptions::none); + jv[jss::LPTokenOut] = USD(100).value().getJson(JsonOptions::none); jv[jss::Flags] = tfLPToken; env(jv, ter(temBAD_AMM_TOKENS)); } @@ -700,63 +517,21 @@ private: } // Depositing mismatched token, invalid Asset1In.issue - ammAlice.deposit( - alice, - GBP(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(temBAD_AMM_TOKENS)); + ammAlice.deposit(alice, GBP(100), std::nullopt, std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); // Depositing mismatched token, invalid Asset2In.issue - ammAlice.deposit( - alice, - USD(100), - GBP(100), - std::nullopt, - std::nullopt, - ter(temBAD_AMM_TOKENS)); + ammAlice.deposit(alice, USD(100), GBP(100), std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); // Depositing mismatched token, Asset1In.issue == Asset2In.issue - ammAlice.deposit( - alice, - USD(100), - USD(100), - std::nullopt, - std::nullopt, - ter(temBAD_AMM_TOKENS)); + ammAlice.deposit(alice, USD(100), USD(100), std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); // Invalid amount value - ammAlice.deposit( - alice, - USD(0), - std::nullopt, - std::nullopt, - std::nullopt, - ter(temBAD_AMOUNT)); - ammAlice.deposit( - alice, - USD(-1'000), - std::nullopt, - std::nullopt, - std::nullopt, - ter(temBAD_AMOUNT)); - ammAlice.deposit( - alice, - USD(10), - std::nullopt, - USD(-1), - std::nullopt, - ter(temBAD_AMOUNT)); + ammAlice.deposit(alice, USD(0), std::nullopt, std::nullopt, std::nullopt, ter(temBAD_AMOUNT)); + ammAlice.deposit(alice, USD(-1'000), std::nullopt, std::nullopt, std::nullopt, ter(temBAD_AMOUNT)); + ammAlice.deposit(alice, USD(10), std::nullopt, USD(-1), std::nullopt, ter(temBAD_AMOUNT)); // Bad currency - ammAlice.deposit( - alice, - BAD(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(temBAD_CURRENCY)); + ammAlice.deposit(alice, BAD(100), std::nullopt, std::nullopt, std::nullopt, ter(temBAD_CURRENCY)); // Invalid Account Account bad("bad"); @@ -816,54 +591,28 @@ private: // Deposit amount is invalid // Calculated amount to deposit is 98,000,000 - ammAlice.deposit( - alice, - USD(0), - std::nullopt, - STAmount{USD, 1, -1}, - std::nullopt, - ter(tecUNFUNDED_AMM)); + ammAlice.deposit(alice, USD(0), std::nullopt, STAmount{USD, 1, -1}, std::nullopt, ter(tecUNFUNDED_AMM)); // Calculated amount is 0 - ammAlice.deposit( - alice, - USD(0), - std::nullopt, - STAmount{USD, 2'000, -6}, - std::nullopt, - ter(tecAMM_FAILED)); + ammAlice.deposit(alice, USD(0), std::nullopt, STAmount{USD, 2'000, -6}, std::nullopt, ter(tecAMM_FAILED)); // Deposit non-empty AMM - ammAlice.deposit( - carol, - XRP(100), - USD(100), - std::nullopt, - tfTwoAssetIfEmpty, - ter(tecAMM_NOT_EMPTY)); + ammAlice.deposit(carol, XRP(100), USD(100), std::nullopt, tfTwoAssetIfEmpty, ter(tecAMM_NOT_EMPTY)); }); // Tiny deposit testAMM( [&](AMM& ammAlice, Env& env) { - auto const enabledV1_3 = - env.current()->rules().enabled(fixAMMv1_3); - auto const err = - !enabledV1_3 ? ter(temBAD_AMOUNT) : ter(tesSUCCESS); + auto const enabledV1_3 = env.current()->rules().enabled(fixAMMv1_3); + auto const err = !enabledV1_3 ? ter(temBAD_AMOUNT) : ter(tesSUCCESS); // Pre-amendment XRP deposit side is rounded to 0 // and deposit fails. // Post-amendment XRP deposit side is rounded to 1 // and deposit succeeds. - ammAlice.deposit( - carol, IOUAmount{1, -4}, std::nullopt, std::nullopt, err); + ammAlice.deposit(carol, IOUAmount{1, -4}, std::nullopt, std::nullopt, err); // Pre/post-amendment LPTokens is rounded to 0 and deposit // fails with tecAMM_INVALID_TOKENS. ammAlice.deposit( - carol, - STAmount{USD, 1, -12}, - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); + carol, STAmount{USD, 1, -12}, std::nullopt, std::nullopt, std::nullopt, ter(tecAMM_INVALID_TOKENS)); }, std::nullopt, 0, @@ -873,8 +622,7 @@ private: // Invalid AMM testAMM([&](AMM& ammAlice, Env& env) { ammAlice.withdrawAll(alice); - ammAlice.deposit( - alice, 10'000, std::nullopt, std::nullopt, ter(terNO_AMM)); + ammAlice.deposit(alice, 10'000, std::nullopt, std::nullopt, ter(terNO_AMM)); }); // Globally frozen asset @@ -890,33 +638,10 @@ private: // If the issuer set global freeze, the holder cannot // deposit the other non-frozen token when AMMClawback is // enabled. - ammAlice.deposit( - carol, - XRP(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); - ammAlice.deposit( - carol, - USD(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); - ammAlice.deposit( - carol, - 1'000'000, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); - ammAlice.deposit( - carol, - XRP(100), - USD(100), - std::nullopt, - std::nullopt, - ter(tecFROZEN)); + ammAlice.deposit(carol, XRP(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.deposit(carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.deposit(carol, 1'000'000, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.deposit(carol, XRP(100), USD(100), std::nullopt, std::nullopt, ter(tecFROZEN)); }, std::nullopt, 0, @@ -935,50 +660,18 @@ private: else // Cannot deposit non-frozen token if the other token is // frozen when AMMClawback is enabled - ammAlice.deposit( - carol, - XRP(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); + ammAlice.deposit(carol, XRP(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN)); - ammAlice.deposit( - carol, - 1'000'000, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); - ammAlice.deposit( - carol, - USD(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); + ammAlice.deposit(carol, 1'000'000, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.deposit(carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN)); env(trust(gw, carol["USD"](0), tfClearFreeze)); // Individually frozen AMM - env(trust( - gw, - STAmount{ - Issue{gw["USD"].currency, ammAlice.ammAccount()}, 0}, - tfSetFreeze)); + env(trust(gw, STAmount{Issue{gw["USD"].currency, ammAlice.ammAccount()}, 0}, tfSetFreeze)); env.close(); // Can deposit non-frozen token ammAlice.deposit(carol, XRP(100)); - ammAlice.deposit( - carol, - 1'000'000, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); - ammAlice.deposit( - carol, - USD(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); + ammAlice.deposit(carol, 1'000'000, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.deposit(carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN)); }, std::nullopt, 0, @@ -991,41 +684,15 @@ private: env(trust(gw, carol["USD"](0), tfSetFreeze)); env(trust(gw, carol["BTC"](0), tfSetFreeze)); env.close(); - ammAlice.deposit( - carol, - 1'000'000, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); - ammAlice.deposit( - carol, - USD(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); + ammAlice.deposit(carol, 1'000'000, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.deposit(carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecFROZEN)); env(trust(gw, carol["USD"](0), tfClearFreeze)); // Individually frozen AMM - env(trust( - gw, - STAmount{ - Issue{gw["USD"].currency, ammAlice.ammAccount()}, 0}, - tfSetFreeze)); + env(trust(gw, STAmount{Issue{gw["USD"].currency, ammAlice.ammAccount()}, 0}, tfSetFreeze)); env.close(); // Cannot deposit non-frozen token - ammAlice.deposit( - carol, - 1'000'000, - std::nullopt, - std::nullopt, - ter(tecFROZEN)); - ammAlice.deposit( - carol, - USD(100), - BTC(0.01), - std::nullopt, - std::nullopt, - ter(tecFROZEN)); + ammAlice.deposit(carol, 1'000'000, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.deposit(carol, USD(100), BTC(0.01), std::nullopt, std::nullopt, ter(tecFROZEN)); }, {{USD(20'000), BTC(0.5)}}); @@ -1050,21 +717,9 @@ private: // if featureAMMClawback is enabled, bob can not deposit XRP // because he's not authorized to hold the paired token // gw["USD"]. - amm.deposit( - bob, - XRP(10), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecNO_AUTH)); + amm.deposit(bob, XRP(10), std::nullopt, std::nullopt, std::nullopt, ter(tecNO_AUTH)); else - amm.deposit( - bob, - XRP(10), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tesSUCCESS)); + amm.deposit(bob, XRP(10), std::nullopt, std::nullopt, std::nullopt, ter(tesSUCCESS)); } // Insufficient XRP balance @@ -1073,26 +728,14 @@ private: env.close(); // Adds LPT trustline ammAlice.deposit(bob, XRP(10)); - ammAlice.deposit( - bob, - XRP(1'000), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecUNFUNDED_AMM)); + ammAlice.deposit(bob, XRP(1'000), std::nullopt, std::nullopt, std::nullopt, ter(tecUNFUNDED_AMM)); }); // Insufficient USD balance testAMM([&](AMM& ammAlice, Env& env) { fund(env, gw, {bob}, {USD(1'000)}, Fund::Acct); env.close(); - ammAlice.deposit( - bob, - USD(1'001), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecUNFUNDED_AMM)); + ammAlice.deposit(bob, USD(1'001), std::nullopt, std::nullopt, std::nullopt, ter(tecUNFUNDED_AMM)); }); // Insufficient USD balance by tokens @@ -1135,8 +778,7 @@ private: // Insufficient reserve, XRP/IOU { Env env(*this); - auto const starting_xrp = - reserve(env, 4) + env.current()->fees().base * 4; + auto const starting_xrp = reserve(env, 4) + env.current()->fees().base * 4; env.fund(XRP(10'000), gw); env.fund(XRP(10'000), alice); env.fund(starting_xrp, carol); @@ -1149,29 +791,16 @@ private: env(offer(carol, XRP(100), USD(101))); env(offer(carol, XRP(100), USD(102))); AMM ammAlice(env, alice, XRP(1'000), USD(1'000)); - ammAlice.deposit( - carol, - XRP(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecINSUF_RESERVE_LINE)); + ammAlice.deposit(carol, XRP(100), std::nullopt, std::nullopt, std::nullopt, ter(tecINSUF_RESERVE_LINE)); env(offer(carol, XRP(100), USD(103))); - ammAlice.deposit( - carol, - USD(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecINSUF_RESERVE_LINE)); + ammAlice.deposit(carol, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecINSUF_RESERVE_LINE)); } // Insufficient reserve, IOU/IOU { Env env(*this); - auto const starting_xrp = - reserve(env, 4) + env.current()->fees().base * 4; + auto const starting_xrp = reserve(env, 4) + env.current()->fees().base * 4; env.fund(XRP(10'000), gw); env.fund(XRP(10'000), alice); env.fund(starting_xrp, carol); @@ -1188,22 +817,14 @@ private: env(offer(carol, XRP(100), USD(101))); env(offer(carol, XRP(100), USD(102))); AMM ammAlice(env, alice, XRP(1'000), USD(1'000)); - ammAlice.deposit( - carol, - XRP(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecINSUF_RESERVE_LINE)); + ammAlice.deposit(carol, XRP(100), std::nullopt, std::nullopt, std::nullopt, ter(tecINSUF_RESERVE_LINE)); } // Invalid min testAMM([&](AMM& ammAlice, Env& env) { // min tokens can't be <= zero - ammAlice.deposit( - carol, 0, XRP(100), tfSingleAsset, ter(temBAD_AMM_TOKENS)); - ammAlice.deposit( - carol, -1, XRP(100), tfSingleAsset, ter(temBAD_AMM_TOKENS)); + ammAlice.deposit(carol, 0, XRP(100), tfSingleAsset, ter(temBAD_AMM_TOKENS)); + ammAlice.deposit(carol, -1, XRP(100), tfSingleAsset, ter(temBAD_AMM_TOKENS)); ammAlice.deposit( carol, 0, @@ -1328,49 +949,36 @@ private: // Equal deposit, tokens rounded to 0 testAMM([&](AMM& amm, Env& env) { - amm.deposit(DepositArg{ - .tokens = IOUAmount{1, -12}, - .err = ter(tecAMM_INVALID_TOKENS)}); + amm.deposit(DepositArg{.tokens = IOUAmount{1, -12}, .err = ter(tecAMM_INVALID_TOKENS)}); }); // Equal deposit limit, tokens rounded to 0 testAMM( [&](AMM& amm, Env& env) { amm.deposit(DepositArg{ - .asset1In = STAmount{USD, 1, -15}, - .asset2In = XRPAmount{1}, - .err = ter(tecAMM_INVALID_TOKENS)}); + .asset1In = STAmount{USD, 1, -15}, .asset2In = XRPAmount{1}, .err = ter(tecAMM_INVALID_TOKENS)}); }, - {.pool = {{USD(1'000'000), XRP(1'000'000)}}, - .features = {features - fixAMMv1_3}}); + {.pool = {{USD(1'000'000), XRP(1'000'000)}}, .features = {features - fixAMMv1_3}}); testAMM([&](AMM& amm, Env& env) { amm.deposit(DepositArg{ - .asset1In = STAmount{USD, 1, -15}, - .asset2In = XRPAmount{1}, - .err = ter(tecAMM_INVALID_TOKENS)}); + .asset1In = STAmount{USD, 1, -15}, .asset2In = XRPAmount{1}, .err = ter(tecAMM_INVALID_TOKENS)}); }); // Single deposit by asset, tokens rounded to 0 testAMM([&](AMM& amm, Env& env) { - amm.deposit(DepositArg{ - .asset1In = STAmount{USD, 1, -15}, - .err = ter(tecAMM_INVALID_TOKENS)}); + amm.deposit(DepositArg{.asset1In = STAmount{USD, 1, -15}, .err = ter(tecAMM_INVALID_TOKENS)}); }); // Single deposit by tokens, tokens rounded to 0 testAMM([&](AMM& amm, Env& env) { amm.deposit(DepositArg{ - .tokens = IOUAmount{1, -10}, - .asset1In = STAmount{USD, 1, -15}, - .err = ter(tecAMM_INVALID_TOKENS)}); + .tokens = IOUAmount{1, -10}, .asset1In = STAmount{USD, 1, -15}, .err = ter(tecAMM_INVALID_TOKENS)}); }); // Single deposit with eprice, tokens rounded to 0 testAMM([&](AMM& amm, Env& env) { amm.deposit(DepositArg{ - .asset1In = STAmount{USD, 1, -15}, - .maxEP = STAmount{USD, 1, -1}, - .err = ter(tecAMM_INVALID_TOKENS)}); + .asset1In = STAmount{USD, 1, -15}, .maxEP = STAmount{USD, 1, -1}, .err = ter(tecAMM_INVALID_TOKENS)}); }); } @@ -1386,21 +994,18 @@ private: testAMM([&](AMM& ammAlice, Env& env) { auto const baseFee = env.current()->fees().base; ammAlice.deposit(carol, 1'000'000); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); // 30,000 less deposited 1,000 BEAST_EXPECT(expectHolding(env, carol, USD(29'000))); // 30,000 less deposited 1,000 and 10 drops tx fee - BEAST_EXPECT(expectLedgerEntryRoot( - env, carol, XRPAmount{29'000'000'000 - baseFee})); + BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRPAmount{29'000'000'000 - baseFee})); }); // equal asset deposit: unit test to exercise the rounding-down of // LPTokens in the AMMHelpers.cpp: adjustLPTokens calculations // The LPTokens need to have 16 significant digits and a fractional part for (Number const& deltaLPTokens : - {Number{UINT64_C(100000'0000000009), -10}, - Number{UINT64_C(100000'0000000001), -10}}) + {Number{UINT64_C(100000'0000000009), -10}, Number{UINT64_C(100000'0000000001), -10}}) { testAMM([&](AMM& ammAlice, Env& env) { // initial LPToken balance @@ -1408,8 +1013,7 @@ private: IOUAmount const newLPTokens{deltaLPTokens}; // carol performs a two-asset deposit - ammAlice.deposit( - DepositArg{.account = carol, .tokens = newLPTokens}); + ammAlice.deposit(DepositArg{.account = carol, .tokens = newLPTokens}); IOUAmount const finalLPToken = ammAlice.getLPTokensBalance(); @@ -1436,16 +1040,12 @@ private: // initial LPTokens (1e7) + newLPTokens BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000) + depositXRP, - USD(10'000) + depositUSD, - IOUAmount{1, 7} + newLPTokens)); + XRP(10'000) + depositXRP, USD(10'000) + depositUSD, IOUAmount{1, 7} + newLPTokens)); // 30,000 less deposited depositUSD - BEAST_EXPECT( - expectHolding(env, carol, USD(30'000) - depositUSD)); + BEAST_EXPECT(expectHolding(env, carol, USD(30'000) - depositUSD)); // 30,000 less deposited depositXRP and 10 drops tx fee - BEAST_EXPECT(expectLedgerEntryRoot( - env, carol, XRP(30'000) - depositXRP - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRP(30'000) - depositXRP - txfee(env, 1))); }); } @@ -1456,85 +1056,66 @@ private: // Deposit 100USD/100XRP testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, USD(100), XRP(100)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'100), IOUAmount{10'100'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'100), IOUAmount{10'100'000, 0})); }); // Equal limit deposit. // Try to deposit 200USD/100XRP. Is truncated to 100USD/100XRP. testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, USD(200), XRP(100)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'100), IOUAmount{10'100'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'100), IOUAmount{10'100'000, 0})); }); // Try to deposit 100USD/200XRP. Is truncated to 100USD/100XRP. testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, USD(100), XRP(200)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'100), IOUAmount{10'100'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'100), IOUAmount{10'100'000, 0})); }); // Single deposit: 1000 USD testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, USD(1'000)); BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, UINT64_C(10'999'99999999999), -11}, - IOUAmount{10'488'088'48170151, -8})); + XRP(10'000), STAmount{USD, UINT64_C(10'999'99999999999), -11}, IOUAmount{10'488'088'48170151, -8})); }); // Single deposit: 1000 XRP testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, XRP(1'000)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(10'000), IOUAmount{10'488'088'48170151, -8})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(10'000), IOUAmount{10'488'088'48170151, -8})); }); // Single deposit: 100000 tokens worth of USD testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, 100000, USD(205)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'201), IOUAmount{10'100'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'201), IOUAmount{10'100'000, 0})); }); // Single deposit: 100000 tokens worth of XRP testAMM([&](AMM& ammAlice, Env& env) { ammAlice.deposit(carol, 100'000, XRP(205)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'201), USD(10'000), IOUAmount{10'100'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'201), USD(10'000), IOUAmount{10'100'000, 0})); }); // Single deposit with EP not exceeding specified: // 100USD with EP not to exceed 0.1 (AssetIn/TokensOut) testAMM([&](AMM& ammAlice, Env&) { - ammAlice.deposit( - carol, USD(1'000), std::nullopt, STAmount{USD, 1, -1}); + ammAlice.deposit(carol, USD(1'000), std::nullopt, STAmount{USD, 1, -1}); BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, UINT64_C(10'999'99999999999), -11}, - IOUAmount{10'488'088'48170151, -8})); + XRP(10'000), STAmount{USD, UINT64_C(10'999'99999999999), -11}, IOUAmount{10'488'088'48170151, -8})); }); // Single deposit with EP not exceeding specified: // 100USD with EP not to exceed 0.002004 (AssetIn/TokensOut) testAMM([&](AMM& ammAlice, Env&) { - ammAlice.deposit( - carol, USD(100), std::nullopt, STAmount{USD, 2004, -6}); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, 10'080'16, -2}, - IOUAmount{10'040'000, 0})); + ammAlice.deposit(carol, USD(100), std::nullopt, STAmount{USD, 2004, -6}); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), STAmount{USD, 10'080'16, -2}, IOUAmount{10'040'000, 0})); }); // Single deposit with EP not exceeding specified: // 0USD with EP not to exceed 0.002004 (AssetIn/TokensOut) testAMM([&](AMM& ammAlice, Env&) { - ammAlice.deposit( - carol, USD(0), std::nullopt, STAmount{USD, 2004, -6}); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, 10'080'16, -2}, - IOUAmount{10'040'000, 0})); + ammAlice.deposit(carol, USD(0), std::nullopt, STAmount{USD, 2004, -6}); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), STAmount{USD, 10'080'16, -2}, IOUAmount{10'040'000, 0})); }); // IOU to IOU + transfer fee @@ -1544,15 +1125,13 @@ private: env(rate(gw, 1.25)); env.close(); AMM ammAlice(env, alice, USD(20'000), BTC(0.5)); - BEAST_EXPECT(ammAlice.expectBalances( - USD(20'000), BTC(0.5), IOUAmount{100, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(20'000), BTC(0.5), IOUAmount{100, 0})); BEAST_EXPECT(expectHolding(env, alice, USD(0))); BEAST_EXPECT(expectHolding(env, alice, BTC(0))); fund(env, gw, {carol}, {USD(2'000), BTC(0.05)}, Fund::Acct); // no transfer fee on deposit ammAlice.deposit(carol, 10); - BEAST_EXPECT(ammAlice.expectBalances( - USD(22'000), BTC(0.55), IOUAmount{110, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(22'000), BTC(0.55), IOUAmount{110, 0})); BEAST_EXPECT(expectHolding(env, carol, USD(0))); BEAST_EXPECT(expectHolding(env, carol, BTC(0))); } @@ -1561,25 +1140,19 @@ private: testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, IOUAmount{1, -3}); BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{10'000'000'001}, - STAmount{USD, UINT64_C(10'000'000001), -6}, - IOUAmount{10'000'000'001, -3})); + XRPAmount{10'000'000'001}, STAmount{USD, UINT64_C(10'000'000001), -6}, IOUAmount{10'000'000'001, -3})); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{1, -3})); }); testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, XRPAmount{1}); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{10'000'000'001}, - USD(10'000), - IOUAmount{1'000'000'000049999, -8})); + BEAST_EXPECT( + ammAlice.expectBalances(XRPAmount{10'000'000'001}, USD(10'000), IOUAmount{1'000'000'000049999, -8})); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{49999, -8})); }); testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, STAmount{USD, 1, -10}); BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, UINT64_C(10'000'00000000008), -11}, - IOUAmount{10'000'000'00000004, -8})); + XRP(10'000), STAmount{USD, UINT64_C(10'000'00000000008), -11}, IOUAmount{10'000'000'00000004, -8})); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{4, -8})); }); @@ -1589,88 +1162,48 @@ private: Env env(*this, feat); env.fund(XRP(30000), gw); AMM ammGw(env, gw, XRP(10'000), USD(10'000)); - BEAST_EXPECT( - ammGw.expectBalances(XRP(10'000), USD(10'000), ammGw.tokens())); + BEAST_EXPECT(ammGw.expectBalances(XRP(10'000), USD(10'000), ammGw.tokens())); ammGw.deposit(gw, 1'000'000); - BEAST_EXPECT(ammGw.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000})); + BEAST_EXPECT(ammGw.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000})); ammGw.deposit(gw, USD(1'000)); BEAST_EXPECT(ammGw.expectBalances( - XRP(11'000), - STAmount{USD, UINT64_C(11'999'99999999998), -11}, - IOUAmount{11'489'125'29307605, -8})); + XRP(11'000), STAmount{USD, UINT64_C(11'999'99999999998), -11}, IOUAmount{11'489'125'29307605, -8})); } // Issuer deposit testAMM([&](AMM& ammAlice, Env& env) { ammAlice.deposit(gw, 1'000'000); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000})); ammAlice.deposit(gw, USD(1'000)); BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), - STAmount{USD, UINT64_C(11'999'99999999998), -11}, - IOUAmount{11'489'125'29307605, -8})); + XRP(11'000), STAmount{USD, UINT64_C(11'999'99999999998), -11}, IOUAmount{11'489'125'29307605, -8})); }); // Min deposit testAMM([&](AMM& ammAlice, Env& env) { // Equal deposit by tokens ammAlice.deposit( - carol, - 1'000'000, - XRP(1'000), - USD(1'000), - std::nullopt, - tfLPToken, - std::nullopt, - std::nullopt); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); + carol, 1'000'000, XRP(1'000), USD(1'000), std::nullopt, tfLPToken, std::nullopt, std::nullopt); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); }); testAMM([&](AMM& ammAlice, Env& env) { // Equal deposit by asset ammAlice.deposit( - carol, - 1'000'000, - XRP(1'000), - USD(1'000), - std::nullopt, - tfTwoAsset, - std::nullopt, - std::nullopt); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); + carol, 1'000'000, XRP(1'000), USD(1'000), std::nullopt, tfTwoAsset, std::nullopt, std::nullopt); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); }); testAMM([&](AMM& ammAlice, Env& env) { // Single deposit by asset ammAlice.deposit( - carol, - 488'088, - XRP(1'000), - std::nullopt, - std::nullopt, - tfSingleAsset, - std::nullopt, - std::nullopt); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(10'000), IOUAmount{10'488'088'48170151, -8})); + carol, 488'088, XRP(1'000), std::nullopt, std::nullopt, tfSingleAsset, std::nullopt, std::nullopt); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(10'000), IOUAmount{10'488'088'48170151, -8})); }); testAMM([&](AMM& ammAlice, Env& env) { // Single deposit by asset ammAlice.deposit( - carol, - 488'088, - USD(1'000), - std::nullopt, - std::nullopt, - tfSingleAsset, - std::nullopt, - std::nullopt); + carol, 488'088, USD(1'000), std::nullopt, std::nullopt, tfSingleAsset, std::nullopt, std::nullopt); BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, UINT64_C(10'999'99999999999), -11}, - IOUAmount{10'488'088'48170151, -8})); + XRP(10'000), STAmount{USD, UINT64_C(10'999'99999999999), -11}, IOUAmount{10'488'088'48170151, -8})); }); } @@ -1758,96 +1291,26 @@ private: NotTEC>> invalidOptions = { // tokens, asset1Out, asset2Out, EPrice, flags, ter - {std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, - temMALFORMED}, - {std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, - tfSingleAsset | tfTwoAsset, - temMALFORMED}, - {1'000, - std::nullopt, - std::nullopt, - std::nullopt, - tfWithdrawAll, - temMALFORMED}, - {std::nullopt, - USD(0), - XRP(100), - std::nullopt, - tfWithdrawAll | tfLPToken, - temMALFORMED}, - {std::nullopt, - std::nullopt, - USD(100), - std::nullopt, - tfWithdrawAll, - temMALFORMED}, + {std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, temMALFORMED}, + {std::nullopt, std::nullopt, std::nullopt, std::nullopt, tfSingleAsset | tfTwoAsset, temMALFORMED}, + {1'000, std::nullopt, std::nullopt, std::nullopt, tfWithdrawAll, temMALFORMED}, + {std::nullopt, USD(0), XRP(100), std::nullopt, tfWithdrawAll | tfLPToken, temMALFORMED}, + {std::nullopt, std::nullopt, USD(100), std::nullopt, tfWithdrawAll, temMALFORMED}, {std::nullopt, std::nullopt, std::nullopt, std::nullopt, tfWithdrawAll | tfOneAssetWithdrawAll, temMALFORMED}, - {std::nullopt, - USD(100), - std::nullopt, - std::nullopt, - tfWithdrawAll, - temMALFORMED}, - {std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, - tfOneAssetWithdrawAll, - temMALFORMED}, - {1'000, - std::nullopt, - USD(100), - std::nullopt, - std::nullopt, - temMALFORMED}, - {std::nullopt, - std::nullopt, - std::nullopt, - IOUAmount{250, 0}, - tfWithdrawAll, - temMALFORMED}, - {1'000, - std::nullopt, - std::nullopt, - IOUAmount{250, 0}, - std::nullopt, - temMALFORMED}, - {std::nullopt, - std::nullopt, - USD(100), - IOUAmount{250, 0}, - std::nullopt, - temMALFORMED}, - {std::nullopt, - XRP(100), - USD(100), - IOUAmount{250, 0}, - std::nullopt, - temMALFORMED}, - {1'000, - XRP(100), - USD(100), - std::nullopt, - std::nullopt, - temMALFORMED}, - {std::nullopt, - XRP(100), - USD(100), - std::nullopt, - tfWithdrawAll, - temMALFORMED}}; + {std::nullopt, USD(100), std::nullopt, std::nullopt, tfWithdrawAll, temMALFORMED}, + {std::nullopt, std::nullopt, std::nullopt, std::nullopt, tfOneAssetWithdrawAll, temMALFORMED}, + {1'000, std::nullopt, USD(100), std::nullopt, std::nullopt, temMALFORMED}, + {std::nullopt, std::nullopt, std::nullopt, IOUAmount{250, 0}, tfWithdrawAll, temMALFORMED}, + {1'000, std::nullopt, std::nullopt, IOUAmount{250, 0}, std::nullopt, temMALFORMED}, + {std::nullopt, std::nullopt, USD(100), IOUAmount{250, 0}, std::nullopt, temMALFORMED}, + {std::nullopt, XRP(100), USD(100), IOUAmount{250, 0}, std::nullopt, temMALFORMED}, + {1'000, XRP(100), USD(100), std::nullopt, std::nullopt, temMALFORMED}, + {std::nullopt, XRP(100), USD(100), std::nullopt, tfWithdrawAll, temMALFORMED}}; for (auto const& it : invalidOptions) { ammAlice.withdraw( @@ -1863,69 +1326,27 @@ private: } // Invalid tokens - ammAlice.withdraw( - alice, 0, std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); - ammAlice.withdraw( - alice, - IOUAmount{-1}, - std::nullopt, - std::nullopt, - ter(temBAD_AMM_TOKENS)); + ammAlice.withdraw(alice, 0, std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); + ammAlice.withdraw(alice, IOUAmount{-1}, std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); // Mismatched token, invalid Asset1Out issue - ammAlice.withdraw( - alice, - GBP(100), - std::nullopt, - std::nullopt, - ter(temBAD_AMM_TOKENS)); + ammAlice.withdraw(alice, GBP(100), std::nullopt, std::nullopt, ter(temBAD_AMM_TOKENS)); // Mismatched token, invalid Asset2Out issue - ammAlice.withdraw( - alice, - USD(100), - GBP(100), - std::nullopt, - ter(temBAD_AMM_TOKENS)); + ammAlice.withdraw(alice, USD(100), GBP(100), std::nullopt, ter(temBAD_AMM_TOKENS)); // Mismatched token, Asset1Out.issue == Asset2Out.issue - ammAlice.withdraw( - alice, - USD(100), - USD(100), - std::nullopt, - ter(temBAD_AMM_TOKENS)); + ammAlice.withdraw(alice, USD(100), USD(100), std::nullopt, ter(temBAD_AMM_TOKENS)); // Invalid amount value - ammAlice.withdraw( - alice, USD(0), std::nullopt, std::nullopt, ter(temBAD_AMOUNT)); - ammAlice.withdraw( - alice, - USD(-100), - std::nullopt, - std::nullopt, - ter(temBAD_AMOUNT)); - ammAlice.withdraw( - alice, - USD(10), - std::nullopt, - IOUAmount{-1}, - ter(temBAD_AMOUNT)); + ammAlice.withdraw(alice, USD(0), std::nullopt, std::nullopt, ter(temBAD_AMOUNT)); + ammAlice.withdraw(alice, USD(-100), std::nullopt, std::nullopt, ter(temBAD_AMOUNT)); + ammAlice.withdraw(alice, USD(10), std::nullopt, IOUAmount{-1}, ter(temBAD_AMOUNT)); // Invalid amount/token value, withdraw all tokens from one side // of the pool. - ammAlice.withdraw( - alice, - USD(10'000), - std::nullopt, - std::nullopt, - ter(tecAMM_BALANCE)); - ammAlice.withdraw( - alice, - XRP(10'000), - std::nullopt, - std::nullopt, - ter(tecAMM_BALANCE)); + ammAlice.withdraw(alice, USD(10'000), std::nullopt, std::nullopt, ter(tecAMM_BALANCE)); + ammAlice.withdraw(alice, XRP(10'000), std::nullopt, std::nullopt, ter(tecAMM_BALANCE)); ammAlice.withdraw( alice, std::nullopt, @@ -1938,12 +1359,7 @@ private: ter(tecAMM_BALANCE)); // Bad currency - ammAlice.withdraw( - alice, - BAD(100), - std::nullopt, - std::nullopt, - ter(temBAD_CURRENCY)); + ammAlice.withdraw(alice, BAD(100), std::nullopt, std::nullopt, ter(temBAD_CURRENCY)); // Invalid Account Account bad("bad"); @@ -1972,31 +1388,15 @@ private: ter(terNO_AMM)); // Carol is not a Liquidity Provider - ammAlice.withdraw( - carol, 10'000, std::nullopt, std::nullopt, ter(tecAMM_BALANCE)); + ammAlice.withdraw(carol, 10'000, std::nullopt, std::nullopt, ter(tecAMM_BALANCE)); // Withdrawing from one side. // XRP by tokens - ammAlice.withdraw( - alice, - IOUAmount(9'999'999'9999, -4), - XRP(0), - std::nullopt, - ter(tecAMM_BALANCE)); + ammAlice.withdraw(alice, IOUAmount(9'999'999'9999, -4), XRP(0), std::nullopt, ter(tecAMM_BALANCE)); // USD by tokens - ammAlice.withdraw( - alice, - IOUAmount(9'999'999'9, -1), - USD(0), - std::nullopt, - ter(tecAMM_BALANCE)); + ammAlice.withdraw(alice, IOUAmount(9'999'999'9, -1), USD(0), std::nullopt, ter(tecAMM_BALANCE)); // XRP - ammAlice.withdraw( - alice, - XRP(10'000), - std::nullopt, - std::nullopt, - ter(tecAMM_BALANCE)); + ammAlice.withdraw(alice, XRP(10'000), std::nullopt, std::nullopt, ter(tecAMM_BALANCE)); // USD ammAlice.withdraw( alice, @@ -2015,17 +1415,10 @@ private: // while leaving a tiny amount in USD pool. // Post-amendment: // Most of the pool is withdrawn with remaining tiny amounts - auto err = env.enabled(fixAMMv1_3) ? ter(tesSUCCESS) - : ter(tecAMM_BALANCE); - ammAlice.withdraw( - alice, - IOUAmount{9'999'999'9999, -4}, - std::nullopt, - std::nullopt, - err); + auto err = env.enabled(fixAMMv1_3) ? ter(tesSUCCESS) : ter(tecAMM_BALANCE); + ammAlice.withdraw(alice, IOUAmount{9'999'999'9999, -4}, std::nullopt, std::nullopt, err); if (env.enabled(fixAMMv1_3)) - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(1), STAmount{USD, 1, -7}, IOUAmount{1, -4})); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount(1), STAmount{USD, 1, -7}, IOUAmount{1, -4})); }, std::nullopt, 0, @@ -2040,17 +1433,10 @@ private: // Equal withdraw but due to XRP precision limit, // this results in full withdraw of XRP pool only, // while leaving a tiny amount in USD pool. - auto err = env.enabled(fixAMMv1_3) ? ter(tesSUCCESS) - : ter(tecAMM_BALANCE); - ammAlice.withdraw( - alice, - IOUAmount{9'999'999'999999999, -9}, - std::nullopt, - std::nullopt, - err); + auto err = env.enabled(fixAMMv1_3) ? ter(tesSUCCESS) : ter(tecAMM_BALANCE); + ammAlice.withdraw(alice, IOUAmount{9'999'999'999999999, -9}, std::nullopt, std::nullopt, err); if (env.enabled(fixAMMv1_3)) - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(1), STAmount{USD, 1, -11}, IOUAmount{1, -8})); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount(1), STAmount{USD, 1, -11}, IOUAmount{1, -8})); }, std::nullopt, 0, @@ -2060,8 +1446,7 @@ private: // Invalid AMM testAMM([&](AMM& ammAlice, Env& env) { ammAlice.withdrawAll(alice); - ammAlice.withdraw( - alice, 10'000, std::nullopt, std::nullopt, ter(terNO_AMM)); + ammAlice.withdraw(alice, 10'000, std::nullopt, std::nullopt, ter(terNO_AMM)); }); // Globally frozen asset @@ -2070,10 +1455,8 @@ private: env.close(); // Can withdraw non-frozen token ammAlice.withdraw(alice, XRP(100)); - ammAlice.withdraw( - alice, USD(100), std::nullopt, std::nullopt, ter(tecFROZEN)); - ammAlice.withdraw( - alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.withdraw(alice, USD(100), std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN)); }); // Individually frozen (AMM) account @@ -2082,22 +1465,15 @@ private: env.close(); // Can withdraw non-frozen token ammAlice.withdraw(alice, XRP(100)); - ammAlice.withdraw( - alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN)); - ammAlice.withdraw( - alice, USD(100), std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.withdraw(alice, USD(100), std::nullopt, std::nullopt, ter(tecFROZEN)); env(trust(gw, alice["USD"](0), tfClearFreeze)); // Individually frozen AMM - env(trust( - gw, - STAmount{Issue{gw["USD"].currency, ammAlice.ammAccount()}, 0}, - tfSetFreeze)); + env(trust(gw, STAmount{Issue{gw["USD"].currency, ammAlice.ammAccount()}, 0}, tfSetFreeze)); // Can withdraw non-frozen token ammAlice.withdraw(alice, XRP(100)); - ammAlice.withdraw( - alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN)); - ammAlice.withdraw( - alice, USD(100), std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.withdraw(alice, 1'000, std::nullopt, std::nullopt, ter(tecFROZEN)); + ammAlice.withdraw(alice, USD(100), std::nullopt, std::nullopt, ter(tecFROZEN)); }); // Carol withdraws more than she owns @@ -2105,17 +1481,10 @@ private: // Single deposit of 100000 worth of tokens, // which is 10% of the pool. Carol is LP now. ammAlice.deposit(carol, 1'000'000); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); - ammAlice.withdraw( - carol, - 2'000'000, - std::nullopt, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); + ammAlice.withdraw(carol, 2'000'000, std::nullopt, std::nullopt, ter(tecAMM_INVALID_TOKENS)); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); }); // Withdraw with EPrice limit. Fails to withdraw, calculated tokens @@ -2123,11 +1492,8 @@ private: testAMM( [&](AMM& ammAlice, Env& env) { ammAlice.deposit(carol, 1'000'000); - auto const err = env.enabled(fixAMMv1_3) - ? ter(tecAMM_INVALID_TOKENS) - : ter(tecAMM_FAILED); - ammAlice.withdraw( - carol, USD(100), std::nullopt, IOUAmount{500, 0}, err); + auto const err = env.enabled(fixAMMv1_3) ? ter(tecAMM_INVALID_TOKENS) : ter(tecAMM_FAILED); + ammAlice.withdraw(carol, USD(100), std::nullopt, IOUAmount{500, 0}, err); }, std::nullopt, 0, @@ -2138,48 +1504,28 @@ private: // to withdraw are greater than the LP shares. testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, 1'000'000); - ammAlice.withdraw( - carol, - USD(100), - std::nullopt, - IOUAmount{600, 0}, - ter(tecAMM_INVALID_TOKENS)); + ammAlice.withdraw(carol, USD(100), std::nullopt, IOUAmount{600, 0}, ter(tecAMM_INVALID_TOKENS)); }); // Withdraw with EPrice limit. Fails to withdraw, amount1 // to withdraw is less than 1700USD. testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, 1'000'000); - ammAlice.withdraw( - carol, - USD(1'700), - std::nullopt, - IOUAmount{520, 0}, - ter(tecAMM_FAILED)); + ammAlice.withdraw(carol, USD(1'700), std::nullopt, IOUAmount{520, 0}, ter(tecAMM_FAILED)); }); // Deposit/Withdraw the same amount with the trading fee testAMM( [&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, USD(1'000)); - ammAlice.withdraw( - carol, - USD(1'000), - std::nullopt, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); + ammAlice.withdraw(carol, USD(1'000), std::nullopt, std::nullopt, ter(tecAMM_INVALID_TOKENS)); }, std::nullopt, 1'000); testAMM( [&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, XRP(1'000)); - ammAlice.withdraw( - carol, - XRP(1'000), - std::nullopt, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); + ammAlice.withdraw(carol, XRP(1'000), std::nullopt, std::nullopt, ter(tecAMM_INVALID_TOKENS)); }, std::nullopt, 1'000); @@ -2187,70 +1533,33 @@ private: // Deposit/Withdraw the same amount fails due to the tokens adjustment testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, STAmount{USD, 1, -6}); - ammAlice.withdraw( - carol, - STAmount{USD, 1, -6}, - std::nullopt, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); + ammAlice.withdraw(carol, STAmount{USD, 1, -6}, std::nullopt, std::nullopt, ter(tecAMM_INVALID_TOKENS)); }); // Withdraw close to one side of the pool. Account's LP tokens // are rounded to all LP tokens. testAMM( [&](AMM& ammAlice, Env& env) { - auto const err = env.enabled(fixAMMv1_3) - ? ter(tecINVARIANT_FAILED) - : ter(tecAMM_BALANCE); + auto const err = env.enabled(fixAMMv1_3) ? ter(tecINVARIANT_FAILED) : ter(tecAMM_BALANCE); ammAlice.withdraw( - alice, - STAmount{USD, UINT64_C(9'999'999999999999), -12}, - std::nullopt, - std::nullopt, - err); + alice, STAmount{USD, UINT64_C(9'999'999999999999), -12}, std::nullopt, std::nullopt, err); }, {.features = {all, all - fixAMMv1_3}, .noLog = true}); // Tiny withdraw testAMM([&](AMM& ammAlice, Env&) { // XRP amount to withdraw is 0 - ammAlice.withdraw( - alice, - IOUAmount{1, -5}, - std::nullopt, - std::nullopt, - ter(tecAMM_FAILED)); + ammAlice.withdraw(alice, IOUAmount{1, -5}, std::nullopt, std::nullopt, ter(tecAMM_FAILED)); // Calculated tokens to withdraw are 0 - ammAlice.withdraw( - alice, - std::nullopt, - STAmount{USD, 1, -11}, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); + ammAlice.withdraw(alice, std::nullopt, STAmount{USD, 1, -11}, std::nullopt, ter(tecAMM_INVALID_TOKENS)); ammAlice.deposit(carol, STAmount{USD, 1, -10}); - ammAlice.withdraw( - carol, - std::nullopt, - STAmount{USD, 1, -9}, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); - ammAlice.withdraw( - carol, - std::nullopt, - XRPAmount{1}, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); + ammAlice.withdraw(carol, std::nullopt, STAmount{USD, 1, -9}, std::nullopt, ter(tecAMM_INVALID_TOKENS)); + ammAlice.withdraw(carol, std::nullopt, XRPAmount{1}, std::nullopt, ter(tecAMM_INVALID_TOKENS)); + ammAlice.withdraw(WithdrawArg{.tokens = IOUAmount{1, -10}, .err = ter(tecAMM_INVALID_TOKENS)}); ammAlice.withdraw(WithdrawArg{ - .tokens = IOUAmount{1, -10}, - .err = ter(tecAMM_INVALID_TOKENS)}); + .asset1Out = STAmount{USD, 1, -15}, .asset2Out = XRPAmount{1}, .err = ter(tecAMM_INVALID_TOKENS)}); ammAlice.withdraw(WithdrawArg{ - .asset1Out = STAmount{USD, 1, -15}, - .asset2Out = XRPAmount{1}, - .err = ter(tecAMM_INVALID_TOKENS)}); - ammAlice.withdraw(WithdrawArg{ - .tokens = IOUAmount{1, -10}, - .asset1Out = STAmount{USD, 1, -15}, - .err = ter(tecAMM_INVALID_TOKENS)}); + .tokens = IOUAmount{1, -10}, .asset1Out = STAmount{USD, 1, -15}, .err = ter(tecAMM_INVALID_TOKENS)}); }); } @@ -2269,31 +1578,25 @@ private: // Single deposit of 100000 worth of tokens, // which is 10% of the pool. Carol is LP now. ammAlice.deposit(carol, 1'000'000); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); - BEAST_EXPECT( - ammAlice.expectLPTokens(carol, IOUAmount{1'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{11'000'000, 0})); + BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{1'000'000, 0})); // 30,000 less deposited 1,000 BEAST_EXPECT(expectHolding(env, carol, USD(29'000))); // 30,000 less deposited 1,000 and 10 drops tx fee - BEAST_EXPECT(expectLedgerEntryRoot( - env, carol, XRPAmount{29'000'000'000 - baseFee})); + BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRPAmount{29'000'000'000 - baseFee})); // Carol withdraws all tokens ammAlice.withdraw(carol, 1'000'000); - BEAST_EXPECT( - ammAlice.expectLPTokens(carol, IOUAmount(beast::Zero()))); + BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount(beast::Zero()))); BEAST_EXPECT(expectHolding(env, carol, USD(30'000))); - BEAST_EXPECT(expectLedgerEntryRoot( - env, carol, XRPAmount{30'000'000'000 - 2 * baseFee})); + BEAST_EXPECT(expectLedgerEntryRoot(env, carol, XRPAmount{30'000'000'000 - 2 * baseFee})); }); // Equal withdrawal by tokens 1000000, 10% // of the current pool testAMM([&](AMM& ammAlice, Env&) { ammAlice.withdraw(alice, 1'000'000); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(9'000), USD(9'000), IOUAmount{9'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(9'000), USD(9'000), IOUAmount{9'000'000, 0})); }); // Equal withdrawal with a limit. Withdraw XRP200. @@ -2303,15 +1606,13 @@ private: // in this case - XRP100/USD100. testAMM([&](AMM& ammAlice, Env&) { ammAlice.withdraw(alice, XRP(200), USD(100)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(9'900), USD(9'900), IOUAmount{9'900'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(9'900), USD(9'900), IOUAmount{9'900'000, 0})); }); // Equal withdrawal with a limit. XRP100/USD100. testAMM([&](AMM& ammAlice, Env&) { ammAlice.withdraw(alice, XRP(100), USD(200)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(9'900), USD(9'900), IOUAmount{9'900'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(9'900), USD(9'900), IOUAmount{9'900'000, 0})); }); // Single withdrawal by amount XRP1000 @@ -2319,15 +1620,10 @@ private: [&](AMM& ammAlice, Env& env) { ammAlice.withdraw(alice, XRP(1'000)); if (!env.enabled(fixAMMv1_3)) - BEAST_EXPECT(ammAlice.expectBalances( - XRP(9'000), - USD(10'000), - IOUAmount{9'486'832'98050514, -8})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(9'000), USD(10'000), IOUAmount{9'486'832'98050514, -8})); else BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{9'000'000'001}, - USD(10'000), - IOUAmount{9'486'832'98050514, -8})); + XRPAmount{9'000'000'001}, USD(10'000), IOUAmount{9'486'832'98050514, -8})); }, std::nullopt, 0, @@ -2337,19 +1633,14 @@ private: // Single withdrawal by tokens 10000. testAMM([&](AMM& ammAlice, Env&) { ammAlice.withdraw(alice, 10'000, USD(0)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(9980.01), IOUAmount{9'990'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(9980.01), IOUAmount{9'990'000, 0})); }); // Withdraw all tokens. testAMM([&](AMM& ammAlice, Env& env) { env(trust(carol, STAmount{ammAlice.lptIssue(), 10'000})); // Can SetTrust only for AMM LP tokens - env(trust( - carol, - STAmount{ - Issue{EUR.currency, ammAlice.ammAccount()}, 10'000}), - ter(tecNO_PERMISSION)); + env(trust(carol, STAmount{Issue{EUR.currency, ammAlice.ammAccount()}, 10'000}), ter(tecNO_PERMISSION)); env.close(); ammAlice.withdrawAll(alice); BEAST_EXPECT(!ammAlice.ammExists()); @@ -2358,18 +1649,15 @@ private: // Can create AMM for the XRP/USD pair AMM ammCarol(env, carol, XRP(10'000), USD(10'000)); - BEAST_EXPECT(ammCarol.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); + BEAST_EXPECT(ammCarol.expectBalances(XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); }); // Single deposit 1000USD, withdraw all tokens in USD testAMM([&](AMM& ammAlice, Env& env) { ammAlice.deposit(carol, USD(1'000)); ammAlice.withdrawAll(carol, USD(0)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); - BEAST_EXPECT( - ammAlice.expectLPTokens(carol, IOUAmount(beast::Zero()))); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); + BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount(beast::Zero()))); }); // Single deposit 1000USD, withdraw all tokens in XRP @@ -2377,9 +1665,7 @@ private: ammAlice.deposit(carol, USD(1'000)); ammAlice.withdrawAll(carol, XRP(0)); BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(9'090'909'091), - STAmount{USD, UINT64_C(10'999'99999999999), -11}, - IOUAmount{10'000'000, 0})); + XRPAmount(9'090'909'091), STAmount{USD, UINT64_C(10'999'99999999999), -11}, IOUAmount{10'000'000, 0})); }); // Single deposit/withdraw by the same account @@ -2395,13 +1681,9 @@ private: lpTokens = ammAlice.deposit(carol, XRPAmount(1)); ammAlice.withdraw(carol, lpTokens, XRPAmount(0)); if (!env.enabled(fixAMMv1_3)) - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), ammAlice.tokens())); else - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(10'000'000'001), - USD(10'000), - ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount(10'000'000'001), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{0})); }, std::nullopt, @@ -2416,8 +1698,7 @@ private: auto const aliceTokens = ammAlice.deposit(alice, USD(1'000)); ammAlice.withdraw(alice, aliceTokens, USD(0)); ammAlice.withdraw(carol, carolTokens, USD(0)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), ammAlice.tokens())); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{0})); BEAST_EXPECT(ammAlice.expectLPTokens(alice, ammAlice.tokens())); }); @@ -2426,8 +1707,7 @@ private: testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, 1'000'000); ammAlice.withdrawAll(carol); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0})); }); // Equal deposit 10%, withdraw all tokens in USD @@ -2435,29 +1715,22 @@ private: ammAlice.deposit(carol, 1'000'000); ammAlice.withdrawAll(carol, USD(0)); BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), - STAmount{USD, UINT64_C(9'090'909090909092), -12}, - IOUAmount{10'000'000, 0})); + XRP(11'000), STAmount{USD, UINT64_C(9'090'909090909092), -12}, IOUAmount{10'000'000, 0})); }); // Equal deposit 10%, withdraw all tokens in XRP testAMM([&](AMM& ammAlice, Env&) { ammAlice.deposit(carol, 1'000'000); ammAlice.withdrawAll(carol, XRP(0)); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(9'090'909'091), - USD(11'000), - IOUAmount{10'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount(9'090'909'091), USD(11'000), IOUAmount{10'000'000, 0})); }); // Withdraw with EPrice limit. testAMM( [&](AMM& ammAlice, Env& env) { ammAlice.deposit(carol, 1'000'000); - ammAlice.withdraw( - carol, USD(100), std::nullopt, IOUAmount{520, 0}); - BEAST_EXPECT(ammAlice.expectLPTokens( - carol, IOUAmount{153'846'15384616, -8})); + ammAlice.withdraw(carol, USD(100), std::nullopt, IOUAmount{520, 0}); + BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{153'846'15384616, -8})); if (!env.enabled(fixAMMv1_1) && !env.enabled(fixAMMv1_3)) BEAST_EXPECT(ammAlice.expectBalances( XRPAmount(11'000'000'000), @@ -2476,17 +1749,14 @@ private: ammAlice.withdrawAll(carol); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{0})); }, - {.features = {all, all - fixAMMv1_3, all - fixAMMv1_1 - fixAMMv1_3}, - .noLog = true}); + {.features = {all, all - fixAMMv1_3, all - fixAMMv1_1 - fixAMMv1_3}, .noLog = true}); // Withdraw with EPrice limit. AssetOut is 0. testAMM( [&](AMM& ammAlice, Env& env) { ammAlice.deposit(carol, 1'000'000); - ammAlice.withdraw( - carol, USD(0), std::nullopt, IOUAmount{520, 0}); - BEAST_EXPECT(ammAlice.expectLPTokens( - carol, IOUAmount{153'846'15384616, -8})); + ammAlice.withdraw(carol, USD(0), std::nullopt, IOUAmount{520, 0}); + BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{153'846'15384616, -8})); if (!env.enabled(fixAMMv1_1) && !env.enabled(fixAMMv1_3)) BEAST_EXPECT(ammAlice.expectBalances( XRP(11'000), @@ -2516,21 +1786,18 @@ private: env.close(); // no transfer fee on create AMM ammAlice(env, alice, USD(20'000), BTC(0.5)); - BEAST_EXPECT(ammAlice.expectBalances( - USD(20'000), BTC(0.5), IOUAmount{100, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(20'000), BTC(0.5), IOUAmount{100, 0})); BEAST_EXPECT(expectHolding(env, alice, USD(0))); BEAST_EXPECT(expectHolding(env, alice, BTC(0))); fund(env, gw, {carol}, {USD(2'000), BTC(0.05)}, Fund::Acct); // no transfer fee on deposit ammAlice.deposit(carol, 10); - BEAST_EXPECT(ammAlice.expectBalances( - USD(22'000), BTC(0.55), IOUAmount{110, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(22'000), BTC(0.55), IOUAmount{110, 0})); BEAST_EXPECT(expectHolding(env, carol, USD(0))); BEAST_EXPECT(expectHolding(env, carol, BTC(0))); // no transfer fee on withdraw ammAlice.withdraw(carol, 10); - BEAST_EXPECT(ammAlice.expectBalances( - USD(20'000), BTC(0.5), IOUAmount{100, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(20'000), BTC(0.5), IOUAmount{100, 0})); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{0, 0})); BEAST_EXPECT(expectHolding(env, carol, USD(2'000))); BEAST_EXPECT(expectHolding(env, carol, BTC(0.05))); @@ -2541,24 +1808,17 @@ private: // By tokens ammAlice.withdraw(alice, IOUAmount{1, -3}); BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{9'999'999'999}, - STAmount{USD, UINT64_C(9'999'999999), -6}, - IOUAmount{9'999'999'999, -3})); + XRPAmount{9'999'999'999}, STAmount{USD, UINT64_C(9'999'999999), -6}, IOUAmount{9'999'999'999, -3})); }); testAMM( [&](AMM& ammAlice, Env& env) { // Single XRP pool ammAlice.withdraw(alice, std::nullopt, XRPAmount{1}); if (!env.enabled(fixAMMv1_3)) - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{9'999'999'999}, - USD(10'000), - IOUAmount{9'999'999'9995, -4})); + BEAST_EXPECT( + ammAlice.expectBalances(XRPAmount{9'999'999'999}, USD(10'000), IOUAmount{9'999'999'9995, -4})); else - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - USD(10'000), - IOUAmount{9'999'999'9995, -4})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{9'999'999'9995, -4})); }, std::nullopt, 0, @@ -2568,42 +1828,34 @@ private: // Single USD pool ammAlice.withdraw(alice, std::nullopt, STAmount{USD, 1, -10}); BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, UINT64_C(9'999'9999999999), -10}, - IOUAmount{9'999'999'99999995, -8})); + XRP(10'000), STAmount{USD, UINT64_C(9'999'9999999999), -10}, IOUAmount{9'999'999'99999995, -8})); }); // Withdraw close to entire pool // Equal by tokens testAMM([&](AMM& ammAlice, Env&) { ammAlice.withdraw(alice, IOUAmount{9'999'999'999, -3}); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{1}, STAmount{USD, 1, -6}, IOUAmount{1, -3})); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount{1}, STAmount{USD, 1, -6}, IOUAmount{1, -3})); }); // USD by tokens testAMM([&](AMM& ammAlice, Env&) { ammAlice.withdraw(alice, IOUAmount{9'999'999}, USD(0)); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), STAmount{USD, 1, -10}, IOUAmount{1})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), STAmount{USD, 1, -10}, IOUAmount{1})); }); // XRP by tokens testAMM([&](AMM& ammAlice, Env&) { ammAlice.withdraw(alice, IOUAmount{9'999'900}, XRP(0)); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{1}, USD(10'000), IOUAmount{100})); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount{1}, USD(10'000), IOUAmount{100})); }); // USD testAMM([&](AMM& ammAlice, Env&) { - ammAlice.withdraw( - alice, STAmount{USD, UINT64_C(9'999'99999999999), -11}); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10000), STAmount{USD, 1, -11}, IOUAmount{316227765, -9})); + ammAlice.withdraw(alice, STAmount{USD, UINT64_C(9'999'99999999999), -11}); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10000), STAmount{USD, 1, -11}, IOUAmount{316227765, -9})); }); // XRP testAMM([&](AMM& ammAlice, Env&) { ammAlice.withdraw(alice, XRPAmount{9'999'999'999}); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{1}, USD(10'000), IOUAmount{100})); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount{1}, USD(10'000), IOUAmount{100})); }); } @@ -2615,64 +1867,28 @@ private: testAMM([&](AMM& ammAlice, Env& env) { // Invalid flags - ammAlice.vote( - std::nullopt, - 1'000, - tfWithdrawAll, - std::nullopt, - std::nullopt, - ter(temINVALID_FLAG)); + ammAlice.vote(std::nullopt, 1'000, tfWithdrawAll, std::nullopt, std::nullopt, ter(temINVALID_FLAG)); // Invalid fee. - ammAlice.vote( - std::nullopt, - 1'001, - std::nullopt, - std::nullopt, - std::nullopt, - ter(temBAD_FEE)); + ammAlice.vote(std::nullopt, 1'001, std::nullopt, std::nullopt, std::nullopt, ter(temBAD_FEE)); BEAST_EXPECT(ammAlice.expectTradingFee(0)); // Invalid Account Account bad("bad"); env.memoize(bad); - ammAlice.vote( - bad, - 1'000, - std::nullopt, - seq(1), - std::nullopt, - ter(terNO_ACCOUNT)); + ammAlice.vote(bad, 1'000, std::nullopt, seq(1), std::nullopt, ter(terNO_ACCOUNT)); // Invalid AMM - ammAlice.vote( - alice, - 1'000, - std::nullopt, - std::nullopt, - {{USD, GBP}}, - ter(terNO_AMM)); + ammAlice.vote(alice, 1'000, std::nullopt, std::nullopt, {{USD, GBP}}, ter(terNO_AMM)); // Account is not LP - ammAlice.vote( - carol, - 1'000, - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecAMM_INVALID_TOKENS)); + ammAlice.vote(carol, 1'000, std::nullopt, std::nullopt, std::nullopt, ter(tecAMM_INVALID_TOKENS)); }); // Invalid AMM testAMM([&](AMM& ammAlice, Env& env) { ammAlice.withdrawAll(alice); - ammAlice.vote( - alice, - 1'000, - std::nullopt, - std::nullopt, - std::nullopt, - ter(terNO_AMM)); + ammAlice.vote(alice, 1'000, std::nullopt, std::nullopt, std::nullopt, ter(terNO_AMM)); }); } @@ -2842,8 +2058,7 @@ private: BEAST_EXPECT(amm.expectAuctionSlot(100, 0, IOUAmount{999'999})); // 999'999 tokens are burned, only 1 LPToken is owned by gw - BEAST_EXPECT( - amm.expectBalances(XRP(1'000), USD(1'000), IOUAmount{1})); + BEAST_EXPECT(amm.expectBalances(XRP(1'000), USD(1'000), IOUAmount{1})); // gw owns only 1 LPToken in its balance BEAST_EXPECT(Number{amm.getLPTokensBalance(gw)} == 1); @@ -3038,8 +2253,7 @@ private: env(ammAlice.bid({.account = carol, .bidMin = 110})); BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{110})); // 110 tokens are burned. - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{10'999'890, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{10'999'890, 0})); }, std::nullopt, 0, @@ -3051,17 +2265,13 @@ private: [&](AMM& ammAlice, Env& env) { ammAlice.deposit(carol, 1'000'000); // Bid exactly 110. Pay 110 because the pay price is < 110. - env(ammAlice.bid( - {.account = carol, .bidMin = 110, .bidMax = 110})); + env(ammAlice.bid({.account = carol, .bidMin = 110, .bidMax = 110})); BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{110})); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{10'999'890})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{10'999'890})); // Bid exactly 180-200. Pay 180 because the pay price is < 180. - env(ammAlice.bid( - {.account = alice, .bidMin = 180, .bidMax = 200})); + env(ammAlice.bid({.account = alice, .bidMin = 180, .bidMax = 200})); BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{180})); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(11'000), USD(11'000), IOUAmount{10'999'814'5, -1})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(11'000), USD(11'000), IOUAmount{10'999'814'5, -1})); }, std::nullopt, 0, @@ -3080,8 +2290,7 @@ private: ammAlice.deposit(bob, 1'000'000); // Bid, pay the computed price. env(ammAlice.bid({.account = bob})); - BEAST_EXPECT( - ammAlice.expectAuctionSlot(0, 0, IOUAmount(1155, -1))); + BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount(1155, -1))); // Bid bidMax fails because the computed price is higher. env(ammAlice.bid({ @@ -3091,8 +2300,7 @@ private: ter(tecAMM_FAILED)); // Bid MaxSlotPrice succeeds - pay computed price env(ammAlice.bid({.account = carol, .bidMax = 600})); - BEAST_EXPECT( - ammAlice.expectAuctionSlot(0, 0, IOUAmount{121'275, -3})); + BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{121'275, -3})); // Bid Min/MaxSlotPrice fails because the computed price is not // in range @@ -3103,10 +2311,8 @@ private: }), ter(tecAMM_FAILED)); // Bid Min/MaxSlotPrice succeeds - pay computed price - env(ammAlice.bid( - {.account = carol, .bidMin = 100, .bidMax = 600})); - BEAST_EXPECT( - ammAlice.expectAuctionSlot(0, 0, IOUAmount{127'33875, -5})); + env(ammAlice.bid({.account = carol, .bidMin = 100, .bidMax = 600})); + BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{127'33875, -5})); }, std::nullopt, 0, @@ -3121,13 +2327,10 @@ private: fund(env, gw, {bob}, {USD(10'000)}, Fund::Acct); ammAlice.deposit(bob, 1'000'000); if (!features[fixAMMv1_3]) - BEAST_EXPECT(ammAlice.expectBalances( - XRP(12'000), USD(12'000), IOUAmount{12'000'000, 0})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(12'000), USD(12'000), IOUAmount{12'000'000, 0})); else - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{12'000'000'001}, - USD(12'000), - IOUAmount{12'000'000, 0})); + BEAST_EXPECT( + ammAlice.expectBalances(XRPAmount{12'000'000'001}, USD(12'000), IOUAmount{12'000'000, 0})); // Initial state. Pay bidMin. env(ammAlice.bid({.account = carol, .bidMin = 110})).close(); @@ -3136,39 +2339,27 @@ private: // 1st Interval after close, price for 0th interval. env(ammAlice.bid({.account = bob})); env.close(seconds(AUCTION_SLOT_INTERVAL_DURATION + 1)); - BEAST_EXPECT( - ammAlice.expectAuctionSlot(0, 1, IOUAmount{1'155, -1})); + BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 1, IOUAmount{1'155, -1})); // 10th Interval after close, price for 1st interval. env(ammAlice.bid({.account = carol})); env.close(seconds(10 * AUCTION_SLOT_INTERVAL_DURATION + 1)); - BEAST_EXPECT( - ammAlice.expectAuctionSlot(0, 10, IOUAmount{121'275, -3})); + BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 10, IOUAmount{121'275, -3})); // 20th Interval (expired) after close, price for 10th interval. env(ammAlice.bid({.account = bob})); - env.close(seconds( - AUCTION_SLOT_TIME_INTERVALS * - AUCTION_SLOT_INTERVAL_DURATION + - 1)); - BEAST_EXPECT(ammAlice.expectAuctionSlot( - 0, std::nullopt, IOUAmount{127'33875, -5})); + env.close(seconds(AUCTION_SLOT_TIME_INTERVALS * AUCTION_SLOT_INTERVAL_DURATION + 1)); + BEAST_EXPECT(ammAlice.expectAuctionSlot(0, std::nullopt, IOUAmount{127'33875, -5})); // 0 Interval. env(ammAlice.bid({.account = carol, .bidMin = 110})).close(); - BEAST_EXPECT(ammAlice.expectAuctionSlot( - 0, std::nullopt, IOUAmount{110})); + BEAST_EXPECT(ammAlice.expectAuctionSlot(0, std::nullopt, IOUAmount{110})); // ~321.09 tokens burnt on bidding fees. if (!features[fixAMMv1_3]) - BEAST_EXPECT(ammAlice.expectBalances( - XRP(12'000), - USD(12'000), - IOUAmount{11'999'678'91, -2})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(12'000), USD(12'000), IOUAmount{11'999'678'91, -2})); else - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{12'000'000'001}, - USD(12'000), - IOUAmount{11'999'678'91, -2})); + BEAST_EXPECT( + ammAlice.expectBalances(XRPAmount{12'000'000'001}, USD(12'000), IOUAmount{11'999'678'91, -2})); }, std::nullopt, 0, @@ -3198,11 +2389,9 @@ private: ammTokens -= slotPrice; BEAST_EXPECT(ammAlice.expectAuctionSlot(100, 0, slotPrice)); if (!features[fixAMMv1_3]) - BEAST_EXPECT(ammAlice.expectBalances( - XRP(13'000), USD(13'000), ammTokens)); + BEAST_EXPECT(ammAlice.expectBalances(XRP(13'000), USD(13'000), ammTokens)); else - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'003}, USD(13'000), ammTokens)); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount{13'000'000'003}, USD(13'000), ammTokens)); // Discounted trade for (int i = 0; i < 10; ++i) { @@ -3216,43 +2405,25 @@ private: // carol, bob, and ed pay ~0.99USD in fees. if (!features[fixAMMv1_1]) { - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(29'499'00572620545), -11)); - BEAST_EXPECT( - env.balance(bob, USD) == - STAmount(USD, UINT64_C(18'999'00572616195), -11)); - BEAST_EXPECT( - env.balance(ed, USD) == - STAmount(USD, UINT64_C(18'999'00572611841), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(29'499'00572620545), -11)); + BEAST_EXPECT(env.balance(bob, USD) == STAmount(USD, UINT64_C(18'999'00572616195), -11)); + BEAST_EXPECT(env.balance(ed, USD) == STAmount(USD, UINT64_C(18'999'00572611841), -11)); // USD pool is slightly higher because of the fees. BEAST_EXPECT(ammAlice.expectBalances( - XRP(13'000), - STAmount(USD, UINT64_C(13'002'98282151419), -11), - ammTokens)); + XRP(13'000), STAmount(USD, UINT64_C(13'002'98282151419), -11), ammTokens)); } else { - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(29'499'00572620544), -11)); - BEAST_EXPECT( - env.balance(bob, USD) == - STAmount(USD, UINT64_C(18'999'00572616194), -11)); - BEAST_EXPECT( - env.balance(ed, USD) == - STAmount(USD, UINT64_C(18'999'0057261184), -10)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(29'499'00572620544), -11)); + BEAST_EXPECT(env.balance(bob, USD) == STAmount(USD, UINT64_C(18'999'00572616194), -11)); + BEAST_EXPECT(env.balance(ed, USD) == STAmount(USD, UINT64_C(18'999'0057261184), -10)); // USD pool is slightly higher because of the fees. if (!features[fixAMMv1_3]) BEAST_EXPECT(ammAlice.expectBalances( - XRP(13'000), - STAmount(USD, UINT64_C(13'002'98282151422), -11), - ammTokens)); + XRP(13'000), STAmount(USD, UINT64_C(13'002'98282151422), -11), ammTokens)); else BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'003}, - STAmount(USD, UINT64_C(13'002'98282151422), -11), - ammTokens)); + XRPAmount{13'000'000'003}, STAmount(USD, UINT64_C(13'002'98282151422), -11), ammTokens)); } ammTokens = ammAlice.getLPTokensBalance(); // Trade with the fee @@ -3266,82 +2437,54 @@ private: // than the trading fee. if (!features[fixAMMv1_1]) { - BEAST_EXPECT( - env.balance(dan, USD) == - STAmount(USD, UINT64_C(19'490'056722744), -9)); + BEAST_EXPECT(env.balance(dan, USD) == STAmount(USD, UINT64_C(19'490'056722744), -9)); // USD pool gains more in dan's fees. BEAST_EXPECT(ammAlice.expectBalances( - XRP(13'000), - STAmount{USD, UINT64_C(13'012'92609877019), -11}, - ammTokens)); + XRP(13'000), STAmount{USD, UINT64_C(13'012'92609877019), -11}, ammTokens)); // Discounted fee payment ammAlice.deposit(carol, USD(100)); ammTokens = ammAlice.getLPTokensBalance(); BEAST_EXPECT(ammAlice.expectBalances( - XRP(13'000), - STAmount{USD, UINT64_C(13'112'92609877019), -11}, - ammTokens)); - env(pay(carol, bob, USD(100)), - path(~USD), - sendmax(XRP(110))); + XRP(13'000), STAmount{USD, UINT64_C(13'112'92609877019), -11}, ammTokens)); + env(pay(carol, bob, USD(100)), path(~USD), sendmax(XRP(110))); env.close(); // carol pays 100000 drops in fees // 99900668XRP swapped in for 100USD BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'100'000'668}, - STAmount{USD, UINT64_C(13'012'92609877019), -11}, - ammTokens)); + XRPAmount{13'100'000'668}, STAmount{USD, UINT64_C(13'012'92609877019), -11}, ammTokens)); } else { if (!features[fixAMMv1_3]) - BEAST_EXPECT( - env.balance(dan, USD) == - STAmount(USD, UINT64_C(19'490'05672274399), -11)); + BEAST_EXPECT(env.balance(dan, USD) == STAmount(USD, UINT64_C(19'490'05672274399), -11)); else - BEAST_EXPECT( - env.balance(dan, USD) == - STAmount(USD, UINT64_C(19'490'05672274398), -11)); + BEAST_EXPECT(env.balance(dan, USD) == STAmount(USD, UINT64_C(19'490'05672274398), -11)); // USD pool gains more in dan's fees. if (!features[fixAMMv1_3]) BEAST_EXPECT(ammAlice.expectBalances( - XRP(13'000), - STAmount{USD, UINT64_C(13'012'92609877023), -11}, - ammTokens)); + XRP(13'000), STAmount{USD, UINT64_C(13'012'92609877023), -11}, ammTokens)); else BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'003}, - STAmount{USD, UINT64_C(13'012'92609877024), -11}, - ammTokens)); + XRPAmount{13'000'000'003}, STAmount{USD, UINT64_C(13'012'92609877024), -11}, ammTokens)); // Discounted fee payment ammAlice.deposit(carol, USD(100)); ammTokens = ammAlice.getLPTokensBalance(); if (!features[fixAMMv1_3]) BEAST_EXPECT(ammAlice.expectBalances( - XRP(13'000), - STAmount{USD, UINT64_C(13'112'92609877023), -11}, - ammTokens)); + XRP(13'000), STAmount{USD, UINT64_C(13'112'92609877023), -11}, ammTokens)); else BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'003}, - STAmount{USD, UINT64_C(13'112'92609877024), -11}, - ammTokens)); - env(pay(carol, bob, USD(100)), - path(~USD), - sendmax(XRP(110))); + XRPAmount{13'000'000'003}, STAmount{USD, UINT64_C(13'112'92609877024), -11}, ammTokens)); + env(pay(carol, bob, USD(100)), path(~USD), sendmax(XRP(110))); env.close(); // carol pays 100000 drops in fees // 99900668XRP swapped in for 100USD if (!features[fixAMMv1_3]) BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'100'000'668}, - STAmount{USD, UINT64_C(13'012'92609877023), -11}, - ammTokens)); + XRPAmount{13'100'000'668}, STAmount{USD, UINT64_C(13'012'92609877023), -11}, ammTokens)); else BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'100'000'671}, - STAmount{USD, UINT64_C(13'012'92609877024), -11}, - ammTokens)); + XRPAmount{13'100'000'671}, STAmount{USD, UINT64_C(13'012'92609877024), -11}, ammTokens)); } // Payment with the trading fee env(pay(alice, carol, XRP(100)), path(~XRP), sendmax(USD(110))); @@ -3352,36 +2495,26 @@ private: if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) { BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'668}, - STAmount{USD, UINT64_C(13'114'03663047264), -11}, - ammTokens)); + XRPAmount{13'000'000'668}, STAmount{USD, UINT64_C(13'114'03663047264), -11}, ammTokens)); } else if (features[fixAMMv1_1] && !features[fixAMMv1_3]) { BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'668}, - STAmount{USD, UINT64_C(13'114'03663047269), -11}, - ammTokens)); + XRPAmount{13'000'000'668}, STAmount{USD, UINT64_C(13'114'03663047269), -11}, ammTokens)); } else { BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'671}, - STAmount{USD, UINT64_C(13'114'03663044937), -11}, - ammTokens)); + XRPAmount{13'000'000'671}, STAmount{USD, UINT64_C(13'114'03663044937), -11}, ammTokens)); } // Auction slot expired, no discounted fee env.close(seconds(TOTAL_TIME_SLOT_SECS + 1)); // clock is parent's based env.close(); if (!features[fixAMMv1_1]) - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(29'399'00572620545), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(29'399'00572620545), -11)); else if (!features[fixAMMv1_3]) - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(29'399'00572620544), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(29'399'00572620544), -11)); ammTokens = ammAlice.getLPTokensBalance(); for (int i = 0; i < 10; ++i) { @@ -3392,33 +2525,21 @@ private: // trading fees vs discounted fee. if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) { - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(29'389'06197177128), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(29'389'06197177128), -11)); BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'668}, - STAmount{USD, UINT64_C(13'123'98038490681), -11}, - ammTokens)); + XRPAmount{13'000'000'668}, STAmount{USD, UINT64_C(13'123'98038490681), -11}, ammTokens)); } else if (features[fixAMMv1_1] && !features[fixAMMv1_3]) { - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(29'389'06197177124), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(29'389'06197177124), -11)); BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'668}, - STAmount{USD, UINT64_C(13'123'98038490689), -11}, - ammTokens)); + XRPAmount{13'000'000'668}, STAmount{USD, UINT64_C(13'123'98038490689), -11}, ammTokens)); } else { - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(29'389'06197177129), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(29'389'06197177129), -11)); BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{13'000'000'671}, - STAmount{USD, UINT64_C(13'123'98038488352), -11}, - ammTokens)); + XRPAmount{13'000'000'671}, STAmount{USD, UINT64_C(13'123'98038488352), -11}, ammTokens)); } env(pay(carol, bob, USD(100)), path(~USD), sendmax(XRP(110))); env.close(); @@ -3428,23 +2549,17 @@ private: if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) { BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(13'100'824'790), - STAmount{USD, UINT64_C(13'023'98038490681), -11}, - ammTokens)); + XRPAmount(13'100'824'790), STAmount{USD, UINT64_C(13'023'98038490681), -11}, ammTokens)); } else if (features[fixAMMv1_1] && !features[fixAMMv1_3]) { BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(13'100'824'790), - STAmount{USD, UINT64_C(13'023'98038490689), -11}, - ammTokens)); + XRPAmount(13'100'824'790), STAmount{USD, UINT64_C(13'023'98038490689), -11}, ammTokens)); } else { BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(13'100'824'793), - STAmount{USD, UINT64_C(13'023'98038488352), -11}, - ammTokens)); + XRPAmount(13'100'824'793), STAmount{USD, UINT64_C(13'023'98038488352), -11}, ammTokens)); } }, std::nullopt, @@ -3456,29 +2571,23 @@ private: testAMM( [&](AMM& ammAlice, Env& env) { // Bid a tiny amount - auto const tiny = - Number{STAmount::cMinValue, STAmount::cMinOffset}; - env(ammAlice.bid( - {.account = alice, .bidMin = IOUAmount{tiny}})); + auto const tiny = Number{STAmount::cMinValue, STAmount::cMinOffset}; + env(ammAlice.bid({.account = alice, .bidMin = IOUAmount{tiny}})); // Auction slot purchase price is equal to the tiny amount // since the minSlotPrice is 0 with no trading fee. BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{tiny})); // The purchase price is too small to affect the total tokens - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), ammAlice.tokens())); // Bid the tiny amount env(ammAlice.bid({ .account = alice, - .bidMin = - IOUAmount{STAmount::cMinValue, STAmount::cMinOffset}, + .bidMin = IOUAmount{STAmount::cMinValue, STAmount::cMinOffset}, })); // Pay slightly higher price - BEAST_EXPECT(ammAlice.expectAuctionSlot( - 0, 0, IOUAmount{tiny * Number{105, -2}})); + BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{tiny * Number{105, -2}})); // The purchase price is still too small to affect the total // tokens - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), ammAlice.tokens())); }, std::nullopt, 0, @@ -3528,10 +2637,7 @@ private: // But trades with the discounted fee since she still owns the slot. // Alice pays 10011 drops in fees env(pay(alice, bob, USD(10)), path(~USD), sendmax(XRP(11))); - BEAST_EXPECT(amm.expectBalances( - XRPAmount{1'010'010'011}, - USD(1'000), - IOUAmount{1'004'487'562112089, -9})); + BEAST_EXPECT(amm.expectBalances(XRPAmount{1'010'010'011}, USD(1'000), IOUAmount{1'004'487'562112089, -9})); // Bob pays the full fee ~0.1USD env(pay(bob, alice, XRP(10)), path(~XRP), sendmax(USD(11))); if (!features[fixAMMv1_1]) @@ -3562,12 +2668,7 @@ private: { auto jtx = env.jt(tx, seq(1), fee(baseFee)); env.app().config().features.erase(featureAMM); - PreflightContext pfCtx( - env.app(), - *jtx.stx, - env.current()->rules(), - tapNONE, - env.journal); + PreflightContext pfCtx(env.app(), *jtx.stx, env.current()->rules(), tapNONE, env.journal); auto pf = Transactor::invokePreflight(pfCtx); BEAST_EXPECT(pf == temDISABLED); env.app().config().features.insert(featureAMM); @@ -3577,12 +2678,7 @@ private: auto jtx = env.jt(tx, seq(1), fee(baseFee)); jtx.jv["TxnSignature"] = "deadbeef"; jtx.stx = env.ust(jtx); - PreflightContext pfCtx( - env.app(), - *jtx.stx, - env.current()->rules(), - tapNONE, - env.journal); + PreflightContext pfCtx(env.app(), *jtx.stx, env.current()->rules(), tapNONE, env.journal); auto pf = Transactor::invokePreflight(pfCtx); BEAST_EXPECT(pf != tesSUCCESS); } @@ -3592,12 +2688,7 @@ private: jtx.jv["Asset2"]["currency"] = "XRP"; jtx.jv["Asset2"].removeMember("issuer"); jtx.stx = env.ust(jtx); - PreflightContext pfCtx( - env.app(), - *jtx.stx, - env.current()->rules(), - tapNONE, - env.journal); + PreflightContext pfCtx(env.app(), *jtx.stx, env.current()->rules(), tapNONE, env.journal); auto pf = Transactor::invokePreflight(pfCtx); BEAST_EXPECT(pf == temBAD_AMM_TOKENS); } @@ -3622,14 +2713,11 @@ private: // XRP balance is below reserve AMM ammAlice(env, acct, XRP(10), USD(10)); // Pay below reserve - env(pay(carol, ammAlice.ammAccount(), XRP(10)), - ter(tecNO_PERMISSION)); + env(pay(carol, ammAlice.ammAccount(), XRP(10)), ter(tecNO_PERMISSION)); // Pay above reserve - env(pay(carol, ammAlice.ammAccount(), XRP(300)), - ter(tecNO_PERMISSION)); + env(pay(carol, ammAlice.ammAccount(), XRP(300)), ter(tecNO_PERMISSION)); // Pay IOU - env(pay(carol, ammAlice.ammAccount(), USD(10)), - ter(tecNO_PERMISSION)); + env(pay(carol, ammAlice.ammAccount(), USD(10)), ter(tecNO_PERMISSION)); } { Env env(*this); @@ -3637,11 +2725,9 @@ private: // XRP balance is above reserve AMM ammAlice(env, acct, XRP(1'000'000), USD(100)); // Pay below reserve - env(pay(carol, ammAlice.ammAccount(), XRP(10)), - ter(tecNO_PERMISSION)); + env(pay(carol, ammAlice.ammAccount(), XRP(10)), ter(tecNO_PERMISSION)); // Pay above reserve - env(pay(carol, ammAlice.ammAccount(), XRP(1'000'000)), - ter(tecNO_PERMISSION)); + env(pay(carol, ammAlice.ammAccount(), XRP(1'000'000)), ter(tecNO_PERMISSION)); } } @@ -3660,46 +2746,28 @@ private: testAMM([&](AMM& ammAlice, Env& env) { auto const pk = carol.pk(); auto const settleDelay = 100s; - NetClock::time_point const cancelAfter = - env.current()->header().parentCloseTime + 200s; - env(paychan::create( - carol, - ammAlice.ammAccount(), - XRP(1'000), - settleDelay, - pk, - cancelAfter), + NetClock::time_point const cancelAfter = env.current()->header().parentCloseTime + 200s; + env(paychan::create(carol, ammAlice.ammAccount(), XRP(1'000), settleDelay, pk, cancelAfter), ter(tecNO_PERMISSION)); }); // Can't pay into AMM with checks. testAMM([&](AMM& ammAlice, Env& env) { - env(check::create(env.master.id(), ammAlice.ammAccount(), XRP(100)), - ter(tecNO_PERMISSION)); + env(check::create(env.master.id(), ammAlice.ammAccount(), XRP(100)), ter(tecNO_PERMISSION)); }); // Pay amounts close to one side of the pool testAMM( [&](AMM& ammAlice, Env& env) { // Can't consume whole pool - env(pay(alice, carol, USD(100)), - path(~USD), - sendmax(XRP(1'000'000'000)), - ter(tecPATH_PARTIAL)); - env(pay(alice, carol, XRP(100)), - path(~XRP), - sendmax(USD(1'000'000'000)), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, USD(100)), path(~USD), sendmax(XRP(1'000'000'000)), ter(tecPATH_PARTIAL)); + env(pay(alice, carol, XRP(100)), path(~XRP), sendmax(USD(1'000'000'000)), ter(tecPATH_PARTIAL)); // Overflow - env(pay(alice, - carol, - STAmount{USD, UINT64_C(99'999999999), -9}), + env(pay(alice, carol, STAmount{USD, UINT64_C(99'999999999), -9}), path(~USD), sendmax(XRP(1'000'000'000)), ter(tecPATH_PARTIAL)); - env(pay(alice, - carol, - STAmount{USD, UINT64_C(999'99999999), -8}), + env(pay(alice, carol, STAmount{USD, UINT64_C(999'99999999), -8}), path(~USD), sendmax(XRP(1'000'000'000)), ter(tecPATH_PARTIAL)); @@ -3708,10 +2776,7 @@ private: sendmax(USD(1'000'000'000)), ter(tecPATH_PARTIAL)); // Sender doesn't have enough funds - env(pay(alice, carol, USD(99.99)), - path(~USD), - sendmax(XRP(1'000'000'000)), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, USD(99.99)), path(~USD), sendmax(XRP(1'000'000'000)), ter(tecPATH_PARTIAL)); env(pay(alice, carol, STAmount{xrpIssue(), 99'990'000}), path(~XRP), sendmax(USD(1'000'000'000)), @@ -3737,10 +2802,7 @@ private: // Individually frozen AMM testAMM([&](AMM& ammAlice, Env& env) { - env(trust( - gw, - STAmount{Issue{gw["USD"].currency, ammAlice.ammAccount()}, 0}, - tfSetFreeze)); + env(trust(gw, STAmount{Issue{gw["USD"].currency, ammAlice.ammAccount()}, 0}, tfSetFreeze)); env.close(); env(pay(alice, carol, USD(1)), path(~USD), @@ -3775,8 +2837,7 @@ private: // For now, just disable SAV entirely, which locks in the small Number // mantissas - features = features - featureSingleAssetVault - featureLendingProtocol - - featureLendingProtocol; + features = features - featureSingleAssetVault - featureLendingProtocol - featureLendingProtocol; // Payment 100USD for 100XRP. // Force one path with tfNoRippleDirect. @@ -3784,18 +2845,13 @@ private: [&](AMM& ammAlice, Env& env) { env.fund(jtx::XRP(30'000), bob); env.close(); - env(pay(bob, carol, USD(100)), - path(~USD), - sendmax(XRP(100)), - txflags(tfNoRippleDirect)); + env(pay(bob, carol, USD(100)), path(~USD), sendmax(XRP(100)), txflags(tfNoRippleDirect)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); // Initial balance 30,000 + 100 BEAST_EXPECT(expectHolding(env, carol, USD(30'100))); // Initial balance 30,000 - 100(sendmax) - 10(tx fee) - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(30'000) - XRP(100) - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(30'000) - XRP(100) - txfee(env, 1))); }, {{XRP(10'000), USD(10'100)}}, 0, @@ -3809,13 +2865,11 @@ private: env.close(); env(pay(bob, carol, USD(100)), sendmax(XRP(100))); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); // Initial balance 30,000 + 100 BEAST_EXPECT(expectHolding(env, carol, USD(30'100))); // Initial balance 30,000 - 100(sendmax) - 10(tx fee) - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(30'000) - XRP(100) - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(30'000) - XRP(100) - txfee(env, 1))); }, {{XRP(10'000), USD(10'100)}}, 0, @@ -3830,13 +2884,11 @@ private: env.close(); env(pay(bob, carol, USD(100)), path(~USD), sendmax(XRP(100))); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); // Initial balance 30,000 + 100 BEAST_EXPECT(expectHolding(env, carol, USD(30'100))); // Initial balance 30,000 - 100(sendmax) - 10(tx fee) - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(30'000) - XRP(100) - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(30'000) - XRP(100) - txfee(env, 1))); }, {{XRP(10'000), USD(10'100)}}, 0, @@ -3853,25 +2905,21 @@ private: env(pay(bob, carol, USD(100)), path(~USD), sendmax(XRP(100)), - txflags( - tfNoRippleDirect | tfPartialPayment | tfLimitQuality)); + txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'010), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'010), USD(10'000), ammAlice.tokens())); // Initial balance 30,000 + 10(limited by limitQuality) BEAST_EXPECT(expectHolding(env, carol, USD(30'010))); // Initial balance 30,000 - 10(limited by limitQuality) - 10(tx // fee) - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(30'000) - XRP(10) - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(30'000) - XRP(10) - txfee(env, 1))); // Fails because of limitQuality. Would have sent // ~98.91USD/110XRP has it not been for limitQuality. env(pay(bob, carol, USD(100)), path(~USD), sendmax(XRP(100)), - txflags( - tfNoRippleDirect | tfPartialPayment | tfLimitQuality), + txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality), ter(tecPATH_DRY)); env.close(); }, @@ -3893,18 +2941,12 @@ private: env(pay(bob, carol, USD(100)), path(~USD), sendmax(XRP(110)), - txflags( - tfNoRippleDirect | tfPartialPayment | tfLimitQuality)); + txflags(tfNoRippleDirect | tfPartialPayment | tfLimitQuality)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'010), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'010), USD(10'000), ammAlice.tokens())); // 10USD - 10% transfer fee - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(30'009'09090909091), -11})); - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(30'000) - XRP(10) - txfee(env, 1))); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(30'009'09090909091), -11})); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(30'000) - XRP(10) - txfee(env, 1))); }, {{XRP(10'000), USD(10'010)}}, 0, @@ -3933,8 +2975,7 @@ private: // is taken from the offer. { Env env(*this, features); - fund( - env, gw, {alice, carol}, {USD(30'000), EUR(30'000)}, Fund::All); + fund(env, gw, {alice, carol}, {USD(30'000), EUR(30'000)}, Fund::All); env.close(); env.fund(XRP(1'000), bob); env.close(); @@ -3942,15 +2983,10 @@ private: auto ammUSD_EUR = AMM(env, alice, EUR(10'000), USD(10'000)); env(offer(alice, XRP(101), USD(100)), txflags(tfPassive)); env.close(); - env(pay(bob, carol, USD(100)), - path(~EUR, ~USD), - sendmax(XRP(102)), - txflags(tfPartialPayment)); + env(pay(bob, carol, USD(100)), path(~EUR, ~USD), sendmax(XRP(102)), txflags(tfPartialPayment)); env.close(); BEAST_EXPECT(ammEUR_XRP.expectBalances( - XRPAmount(10'030'082'730), - STAmount(EUR, UINT64_C(9'970'007498125468), -12), - ammEUR_XRP.tokens())); + XRPAmount(10'030'082'730), STAmount(EUR, UINT64_C(9'970'007498125468), -12), ammEUR_XRP.tokens())); if (!features[fixAMMv1_1]) { BEAST_EXPECT(ammUSD_EUR.expectBalances( @@ -3959,12 +2995,9 @@ private: ammUSD_EUR.tokens())); // fixReducedOffersV2 changes the expected results slightly. - Amounts const expectedAmounts = - env.closed()->rules().enabled(fixReducedOffersV2) + Amounts const expectedAmounts = env.closed()->rules().enabled(fixReducedOffersV2) ? Amounts{XRPAmount(30'201'749), STAmount(USD, UINT64_C(29'90272233787816), -14)} - : Amounts{ - XRPAmount(30'201'749), - STAmount(USD, UINT64_C(29'90272233787818), -14)}; + : Amounts{XRPAmount(30'201'749), STAmount(USD, UINT64_C(29'90272233787818), -14)}; BEAST_EXPECT(expectOffers(env, alice, 1, {{expectedAmounts}})); } @@ -3976,12 +3009,9 @@ private: ammUSD_EUR.tokens())); // fixReducedOffersV2 changes the expected results slightly. - Amounts const expectedAmounts = - env.closed()->rules().enabled(fixReducedOffersV2) + Amounts const expectedAmounts = env.closed()->rules().enabled(fixReducedOffersV2) ? Amounts{XRPAmount(30'201'749), STAmount(USD, UINT64_C(29'90272233782839), -14)} - : Amounts{ - XRPAmount(30'201'749), - STAmount(USD, UINT64_C(29'90272233782840), -14)}; + : Amounts{XRPAmount(30'201'749), STAmount(USD, UINT64_C(29'90272233782840), -14)}; BEAST_EXPECT(expectOffers(env, alice, 1, {{expectedAmounts}})); } @@ -3989,10 +3019,7 @@ private: BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, 30'100})); // Initial 1,000 - 30082730(AMM pool) - 70798251(offer) - 10(tx fee) BEAST_EXPECT(expectLedgerEntryRoot( - env, - bob, - XRP(1'000) - XRPAmount{30'082'730} - XRPAmount{70'798'251} - - txfee(env, 1))); + env, bob, XRP(1'000) - XRPAmount{30'082'730} - XRPAmount{70'798'251} - txfee(env, 1))); } // Default path (with AMM) has a better quality than a non-default path. @@ -4009,37 +3036,24 @@ private: env.close(); env(offer(alice, EUR(100), USD(100)), txflags(tfPassive)); env.close(); - env(pay(bob, carol, USD(100)), - path(~EUR, ~USD), - sendmax(XRP(102)), - txflags(tfPartialPayment)); + env(pay(bob, carol, USD(100)), path(~EUR, ~USD), sendmax(XRP(102)), txflags(tfPartialPayment)); env.close(); BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(10'050'238'637), - STAmount(USD, UINT64_C(9'950'01249687578), -11), - ammAlice.tokens())); + XRPAmount(10'050'238'637), STAmount(USD, UINT64_C(9'950'01249687578), -11), ammAlice.tokens())); BEAST_EXPECT(expectOffers( env, alice, 2, - {{Amounts{ - XRPAmount(50'487'378), - STAmount(EUR, UINT64_C(49'98750312422), -11)}, + {{Amounts{XRPAmount(50'487'378), STAmount(EUR, UINT64_C(49'98750312422), -11)}, Amounts{ STAmount(EUR, UINT64_C(49'98750312422), -11), STAmount(USD, UINT64_C(49'98750312422), -11)}}})); // Initial 30,000 + 99.99999999999 - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(30'099'99999999999), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(30'099'99999999999), -11})); // Initial 1,000 - 50238637(AMM pool) - 50512622(offer) - 10(tx // fee) BEAST_EXPECT(expectLedgerEntryRoot( - env, - bob, - XRP(1'000) - XRPAmount{50'238'637} - XRPAmount{50'512'622} - - txfee(env, 1))); + env, bob, XRP(1'000) - XRPAmount{50'238'637} - XRPAmount{50'512'622} - txfee(env, 1))); }, std::nullopt, 0, @@ -4054,35 +3068,24 @@ private: env.close(); env(offer(bob, XRP(100), USD(100)), txflags(tfPassive)); env.close(); - env(pay(alice, carol, USD(200)), - sendmax(XRP(200)), - txflags(tfPartialPayment)); + env(pay(alice, carol, USD(200)), sendmax(XRP(200)), txflags(tfPartialPayment)); env.close(); if (!features[fixAMMv1_1]) { - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); // Initial 30,000 + 200 BEAST_EXPECT(expectHolding(env, carol, USD(30'200))); } else { BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), - STAmount(USD, UINT64_C(10'000'00000000001), -11), - ammAlice.tokens())); - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount(USD, UINT64_C(30'199'99999999999), -11))); + XRP(10'100), STAmount(USD, UINT64_C(10'000'00000000001), -11), ammAlice.tokens())); + BEAST_EXPECT(expectHolding(env, carol, STAmount(USD, UINT64_C(30'199'99999999999), -11))); } // Initial 30,000 - 10000(AMM pool LP) - 100(AMM offer) - // - 100(offer) - 10(tx fee) - one reserve BEAST_EXPECT(expectLedgerEntryRoot( - env, - alice, - XRP(30'000) - XRP(10'000) - XRP(100) - XRP(100) - - ammCrtFee(env) - txfee(env, 1))); + env, alice, XRP(30'000) - XRP(10'000) - XRP(100) - XRP(100) - ammCrtFee(env) - txfee(env, 1))); BEAST_EXPECT(expectOffers(env, bob, 0)); }, {{XRP(10'000), USD(10'100)}}, @@ -4100,12 +3103,9 @@ private: env(offer(bob, XRP(50), USD(150)), txflags(tfPassive)); env.close(); AMM ammAlice(env, alice, XRP(1'000), USD(1'050)); - env(pay(alice, carol, USD(200)), - sendmax(XRP(200)), - txflags(tfPartialPayment)); + env(pay(alice, carol, USD(200)), sendmax(XRP(200)), txflags(tfPartialPayment)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(1'050), USD(1'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(1'050), USD(1'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(2'200))); BEAST_EXPECT(expectOffers(env, bob, 0)); } @@ -4117,13 +3117,11 @@ private: env.close(); env(offer(bob, USD(100), XRP(100))); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'100), USD(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'100), USD(10'000), ammAlice.tokens())); // Initial 1,000 + 100 BEAST_EXPECT(expectHolding(env, bob, USD(1'100))); // Initial 30,000 - 100(offer) - 10(tx fee) - BEAST_EXPECT(expectLedgerEntryRoot( - env, bob, XRP(30'000) - XRP(100) - txfee(env, 1))); + BEAST_EXPECT(expectLedgerEntryRoot(env, bob, XRP(30'000) - XRP(100) - txfee(env, 1))); BEAST_EXPECT(expectOffers(env, bob, 0)); }, {{XRP(10'000), USD(10'100)}}, @@ -4144,8 +3142,7 @@ private: env(offer(carol, EUR(100), GBP(100))); env.close(); // No transfer fee - BEAST_EXPECT(ammAlice.expectBalances( - GBP(1'100), EUR(1'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(GBP(1'100), EUR(1'000), ammAlice.tokens())); // Initial 30,000 - 100(offer) - 25% transfer fee BEAST_EXPECT(expectHolding(env, carol, GBP(29'875))); // Initial 30,000 + 100(offer) @@ -4172,10 +3169,8 @@ private: // on higher limit out, which generates a larger offer // with lower quality. Consequently, the offer fails // to cross. - BEAST_EXPECT( - amm.expectBalances(XRP(1'000), USD(500), amm.tokens())); - BEAST_EXPECT(expectOffers( - env, carol, 1, {{Amounts{XRP(100), USD(55)}}})); + BEAST_EXPECT(amm.expectBalances(XRP(1'000), USD(500), amm.tokens())); + BEAST_EXPECT(expectOffers(env, carol, 1, {{Amounts{XRP(100), USD(55)}}})); } else { @@ -4187,21 +3182,12 @@ private: // quality. // AMM offer ~50USD/91XRP BEAST_EXPECT(amm.expectBalances( - XRPAmount(909'090'909), - STAmount{USD, UINT64_C(550'000000055), -9}, - amm.tokens())); + XRPAmount(909'090'909), STAmount{USD, UINT64_C(550'000000055), -9}, amm.tokens())); // Offer ~91XRP/49.99USD - BEAST_EXPECT(expectOffers( - env, - carol, - 1, - {{Amounts{ - XRPAmount{9'090'909}, - STAmount{USD, 4'99999995, -8}}}})); - // Carol pays 0.1% fee on ~50USD =~ 0.05USD BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(29'949'94999999494), -11)); + expectOffers(env, carol, 1, {{Amounts{XRPAmount{9'090'909}, STAmount{USD, 4'99999995, -8}}}})); + // Carol pays 0.1% fee on ~50USD =~ 0.05USD + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(29'949'94999999494), -11)); } }, {{XRP(1'000), USD(500)}}, @@ -4216,18 +3202,14 @@ private: env.close(); if (!features[fixAMMv1_1]) { - BEAST_EXPECT(amm.expectBalances( - XRP(990), - STAmount{USD, UINT64_C(505'050505050505), -12}, - amm.tokens())); + BEAST_EXPECT( + amm.expectBalances(XRP(990), STAmount{USD, UINT64_C(505'050505050505), -12}, amm.tokens())); BEAST_EXPECT(expectOffers(env, carol, 0)); } else { - BEAST_EXPECT(amm.expectBalances( - XRP(990), - STAmount{USD, UINT64_C(505'0505050505051), -13}, - amm.tokens())); + BEAST_EXPECT( + amm.expectBalances(XRP(990), STAmount{USD, UINT64_C(505'0505050505051), -13}, amm.tokens())); BEAST_EXPECT(expectOffers(env, carol, 0)); } }, @@ -4239,13 +3221,7 @@ private: testAMM( [&](AMM& ammAlice, Env& env) { Account const ed("ed"); - fund( - env, - gw, - {bob, ed}, - XRP(30'000), - {GBP(2'000), EUR(2'000)}, - Fund::Acct); + fund(env, gw, {bob, ed}, XRP(30'000), {GBP(2'000), EUR(2'000)}, Fund::Acct); env(rate(gw, 1.25)); env.close(); // The auto-bridge is worse quality than AMM, is not consumed @@ -4287,15 +3263,9 @@ private: // = 58.825 = ~29941.17 // carol bought ~72.93EUR at the cost of ~70.68GBP // the offer is partially consumed - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{GBP, UINT64_C(29'941'16770347333), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{GBP, UINT64_C(29'941'16770347333), -11})); // Initial 30,000 + ~49.3(offers = 39.3(AMM) + 10(LOB)) - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{EUR, UINT64_C(30'049'31517120716), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{EUR, UINT64_C(30'049'31517120716), -11})); } else { @@ -4326,15 +3296,9 @@ private: // = 88.35 = ~29911.64 // carol bought ~72.93EUR at the cost of ~70.68GBP // the offer is partially consumed - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{GBP, UINT64_C(29'911'64396400896), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{GBP, UINT64_C(29'911'64396400896), -11})); // Initial 30,000 + ~72.93(offers = 62.93(AMM) + 10(LOB)) - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{EUR, UINT64_C(30'072'93416277865), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{EUR, UINT64_C(30'072'93416277865), -11})); } // Initial 2000 + 10 = 2010 BEAST_EXPECT(expectHolding(env, bob, GBP(2'010))); @@ -4358,13 +3322,9 @@ private: fund(env, gw, {bob}, {GBP(200), EUR(200)}, Fund::Acct); env(rate(gw, 1.25)); env.close(); - env(pay(bob, carol, EUR(100)), - path(~EUR), - sendmax(GBP(125)), - txflags(tfPartialPayment)); + env(pay(bob, carol, EUR(100)), path(~EUR), sendmax(GBP(125)), txflags(tfPartialPayment)); env.close(); - BEAST_EXPECT(ammAlice.expectBalances( - GBP(1'100), EUR(1'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(GBP(1'100), EUR(1'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, bob, GBP(75))); BEAST_EXPECT(expectHolding(env, carol, EUR(30'080))); }, @@ -4405,8 +3365,7 @@ private: env.close(); BEAST_EXPECT(expectHolding(env, bob, CAN(0))); BEAST_EXPECT(expectHolding(env, dan, CAN(356.25), GBP(43.75))); - BEAST_EXPECT(ammAlice.expectBalances( - GBP(10'125), EUR(10'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(GBP(10'125), EUR(10'000), ammAlice.tokens())); BEAST_EXPECT(expectHolding(env, ed, EUR(300), USD(100))); BEAST_EXPECT(expectHolding(env, carol, USD(80))); }, @@ -4448,12 +3407,7 @@ private: { Env env(*this, features); auto const ETH = gw["ETH"]; - fund( - env, - gw, - {alice}, - XRP(100'000), - {EUR(50'000), BTC(50'000), ETH(50'000), USD(50'000)}); + fund(env, gw, {alice}, XRP(100'000), {EUR(50'000), BTC(50'000), ETH(50'000), USD(50'000)}); fund(env, gw, {carol, bob}, XRP(1'000), {USD(200)}, Fund::Acct); AMM xrp_eur(env, alice, XRP(10'100), EUR(10'000)); AMM eur_btc(env, alice, EUR(10'000), BTC(10'200)); @@ -4472,9 +3426,7 @@ private: // XRP-ETH-EUR-USD // This path provides ~26.06USD/26.2XRP BEAST_EXPECT(xrp_eth.expectBalances( - XRPAmount(10'026'208'900), - STAmount{ETH, UINT64_C(10'073'65779244494), -11}, - xrp_eth.tokens())); + XRPAmount(10'026'208'900), STAmount{ETH, UINT64_C(10'073'65779244494), -11}, xrp_eth.tokens())); BEAST_EXPECT(eth_eur.expectBalances( STAmount{ETH, UINT64_C(10'926'34220755506), -11}, STAmount{EUR, UINT64_C(10'973'54232078752), -11}, @@ -4486,16 +3438,12 @@ private: // XRP-USD path // This path provides ~73.9USD/74.1XRP BEAST_EXPECT(xrp_usd.expectBalances( - XRPAmount(10'224'106'246), - STAmount{USD, UINT64_C(10'126'06848287914), -11}, - xrp_usd.tokens())); + XRPAmount(10'224'106'246), STAmount{USD, UINT64_C(10'126'06848287914), -11}, xrp_usd.tokens())); } else { BEAST_EXPECT(xrp_eth.expectBalances( - XRPAmount(10'026'208'900), - STAmount{ETH, UINT64_C(10'073'65779244461), -11}, - xrp_eth.tokens())); + XRPAmount(10'026'208'900), STAmount{ETH, UINT64_C(10'073'65779244461), -11}, xrp_eth.tokens())); BEAST_EXPECT(eth_eur.expectBalances( STAmount{ETH, UINT64_C(10'926'34220755539), -11}, STAmount{EUR, UINT64_C(10'973'5423207872), -10}, @@ -4507,9 +3455,7 @@ private: // XRP-USD path // This path provides ~73.9USD/74.1XRP BEAST_EXPECT(xrp_usd.expectBalances( - XRPAmount(10'224'106'246), - STAmount{USD, UINT64_C(10'126'06848287943), -11}, - xrp_usd.tokens())); + XRPAmount(10'224'106'246), STAmount{USD, UINT64_C(10'126'06848287943), -11}, xrp_usd.tokens())); } // XRP-EUR-BTC-USD @@ -4518,12 +3464,9 @@ private: // shows a different distribution: // XRP-EUR-BTC-USD 11.6USD/11.64XRP, XRP-USD 60.7USD/60.8XRP, // XRP-ETH-EUR-USD 27.6USD/27.6XRP - BEAST_EXPECT(xrp_eur.expectBalances( - XRP(10'100), EUR(10'000), xrp_eur.tokens())); - BEAST_EXPECT(eur_btc.expectBalances( - EUR(10'000), BTC(10'200), eur_btc.tokens())); - BEAST_EXPECT(btc_usd.expectBalances( - BTC(10'100), USD(10'000), btc_usd.tokens())); + BEAST_EXPECT(xrp_eur.expectBalances(XRP(10'100), EUR(10'000), xrp_eur.tokens())); + BEAST_EXPECT(eur_btc.expectBalances(EUR(10'000), BTC(10'200), eur_btc.tokens())); + BEAST_EXPECT(btc_usd.expectBalances(BTC(10'100), USD(10'000), btc_usd.tokens())); BEAST_EXPECT(expectHolding(env, carol, USD(300))); } @@ -4532,42 +3475,28 @@ private: { Env env(*this, features); auto const ETH = gw["ETH"]; - fund( - env, - gw, - {alice}, - XRP(40'000), - {EUR(50'000), BTC(50'000), ETH(50'000), USD(50'000)}); + fund(env, gw, {alice}, XRP(40'000), {EUR(50'000), BTC(50'000), ETH(50'000), USD(50'000)}); fund(env, gw, {carol, bob}, XRP(1000), {USD(200)}, Fund::Acct); AMM xrp_eur(env, alice, XRP(10'100), EUR(10'000)); AMM eur_btc(env, alice, EUR(10'000), BTC(10'200)); AMM btc_usd(env, alice, BTC(10'100), USD(10'000)); AMM xrp_eth(env, alice, XRP(10'000), ETH(10'100)); AMM eth_eur(env, alice, ETH(10'900), EUR(11'000)); - env(pay(bob, carol, USD(100)), - path(~EUR, ~BTC, ~USD), - path(~ETH, ~EUR, ~BTC, ~USD), - sendmax(XRP(200))); + env(pay(bob, carol, USD(100)), path(~EUR, ~BTC, ~USD), path(~ETH, ~EUR, ~BTC, ~USD), sendmax(XRP(200))); if (!features[fixAMMv1_1]) { // XRP-EUR-BTC-USD path provides ~17.8USD/~18.7XRP // XRP-ETH-EUR-BTC-USD path provides ~82.2USD/82.4XRP BEAST_EXPECT(xrp_eur.expectBalances( - XRPAmount(10'118'738'472), - STAmount{EUR, UINT64_C(9'981'544436337968), -12}, - xrp_eur.tokens())); + XRPAmount(10'118'738'472), STAmount{EUR, UINT64_C(9'981'544436337968), -12}, xrp_eur.tokens())); BEAST_EXPECT(eur_btc.expectBalances( STAmount{EUR, UINT64_C(10'101'16096785173), -11}, STAmount{BTC, UINT64_C(10'097'91426968066), -11}, eur_btc.tokens())); BEAST_EXPECT(btc_usd.expectBalances( - STAmount{BTC, UINT64_C(10'202'08573031934), -11}, - USD(9'900), - btc_usd.tokens())); + STAmount{BTC, UINT64_C(10'202'08573031934), -11}, USD(9'900), btc_usd.tokens())); BEAST_EXPECT(xrp_eth.expectBalances( - XRPAmount(10'082'446'397), - STAmount{ETH, UINT64_C(10'017'41072778012), -11}, - xrp_eth.tokens())); + XRPAmount(10'082'446'397), STAmount{ETH, UINT64_C(10'017'41072778012), -11}, xrp_eth.tokens())); BEAST_EXPECT(eth_eur.expectBalances( STAmount{ETH, UINT64_C(10'982'58927221988), -11}, STAmount{EUR, UINT64_C(10'917'2945958103), -10}, @@ -4576,21 +3505,15 @@ private: else { BEAST_EXPECT(xrp_eur.expectBalances( - XRPAmount(10'118'738'472), - STAmount{EUR, UINT64_C(9'981'544436337923), -12}, - xrp_eur.tokens())); + XRPAmount(10'118'738'472), STAmount{EUR, UINT64_C(9'981'544436337923), -12}, xrp_eur.tokens())); BEAST_EXPECT(eur_btc.expectBalances( STAmount{EUR, UINT64_C(10'101'16096785188), -11}, STAmount{BTC, UINT64_C(10'097'91426968059), -11}, eur_btc.tokens())); BEAST_EXPECT(btc_usd.expectBalances( - STAmount{BTC, UINT64_C(10'202'08573031941), -11}, - USD(9'900), - btc_usd.tokens())); + STAmount{BTC, UINT64_C(10'202'08573031941), -11}, USD(9'900), btc_usd.tokens())); BEAST_EXPECT(xrp_eth.expectBalances( - XRPAmount(10'082'446'397), - STAmount{ETH, UINT64_C(10'017'41072777996), -11}, - xrp_eth.tokens())); + XRPAmount(10'082'446'397), STAmount{ETH, UINT64_C(10'017'41072777996), -11}, xrp_eth.tokens())); BEAST_EXPECT(eth_eur.expectBalances( STAmount{ETH, UINT64_C(10'982'58927222004), -11}, STAmount{EUR, UINT64_C(10'917'2945958102), -10}, @@ -4619,27 +3542,16 @@ private: { // Carol gets ~29.91USD because of the AMM offers limit BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'030), - STAmount{USD, UINT64_C(9'970'089730807577), -12}, - ammAlice.tokens())); - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(30'029'91026919241), -11})); + XRP(10'030), STAmount{USD, UINT64_C(9'970'089730807577), -12}, ammAlice.tokens())); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(30'029'91026919241), -11})); } else { BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'030), - STAmount{USD, UINT64_C(9'970'089730807827), -12}, - ammAlice.tokens())); - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(30'029'91026919217), -11})); + XRP(10'030), STAmount{USD, UINT64_C(9'970'089730807827), -12}, ammAlice.tokens())); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(30'029'91026919217), -11})); } - BEAST_EXPECT( - expectOffers(env, alice, 1, {{{EUR(140), XRP(100)}}})); + BEAST_EXPECT(expectOffers(env, alice, 1, {{{EUR(140), XRP(100)}}})); }, std::nullopt, 0, @@ -4660,26 +3572,18 @@ private: path(~XRP, ~USD), sendmax(EUR(400)), txflags(tfPartialPayment | tfNoRippleDirect)); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{10'101'010'102}, USD(9'900), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(XRPAmount{10'101'010'102}, USD(9'900), ammAlice.tokens())); if (!features[fixAMMv1_1]) { // Carol gets ~100USD - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(30'099'99999999999), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(30'099'99999999999), -11})); } else { BEAST_EXPECT(expectHolding(env, carol, USD(30'100))); } - BEAST_EXPECT(expectOffers( - env, - alice, - 1, - {{{STAmount{EUR, UINT64_C(39'1858572), -7}, - XRPAmount{27'989'898}}}})); + BEAST_EXPECT( + expectOffers(env, alice, 1, {{{STAmount{EUR, UINT64_C(39'1858572), -7}, XRPAmount{27'989'898}}}})); }, std::nullopt, 0, @@ -4697,28 +3601,16 @@ private: if (!features[fixAMMv1_1]) { BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{10'049'825'373}, - STAmount{USD, UINT64_C(10'049'92586949302), -11}, - ammAlice.tokens())); + XRPAmount{10'049'825'373}, STAmount{USD, UINT64_C(10'049'92586949302), -11}, ammAlice.tokens())); BEAST_EXPECT(expectOffers( - env, - bob, - 1, - {{{XRPAmount{50'074'629}, - STAmount{USD, UINT64_C(50'07513050698), -11}}}})); + env, bob, 1, {{{XRPAmount{50'074'629}, STAmount{USD, UINT64_C(50'07513050698), -11}}}})); } else { BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{10'049'825'372}, - STAmount{USD, UINT64_C(10'049'92587049303), -11}, - ammAlice.tokens())); + XRPAmount{10'049'825'372}, STAmount{USD, UINT64_C(10'049'92587049303), -11}, ammAlice.tokens())); BEAST_EXPECT(expectOffers( - env, - bob, - 1, - {{{XRPAmount{50'074'628}, - STAmount{USD, UINT64_C(50'07512950697), -11}}}})); + env, bob, 1, {{{XRPAmount{50'074'628}, STAmount{USD, UINT64_C(50'07512950697), -11}}}})); BEAST_EXPECT(expectHolding(env, carol, USD(30'100))); } } @@ -4752,17 +3644,13 @@ private: auto const baseFee = env.current()->fees().base.drops(); auto const token1 = ammAlice.lptIssue(); auto priceXRP = ammAssetOut( - STAmount{XRPAmount{10'000'000'000}}, - STAmount{token1, 10'000'000}, - STAmount{token1, 5'000'000}, - 0); + STAmount{XRPAmount{10'000'000'000}}, STAmount{token1, 10'000'000}, STAmount{token1, 5'000'000}, 0); // Carol places an order to buy LPTokens env(offer(carol, STAmount{token1, 5'000'000}, priceXRP)); // Alice places an order to sell LPTokens env(offer(alice, priceXRP, STAmount{token1, 5'000'000})); // Pool's LPTokens balance doesn't change - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{10'000'000})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{10'000'000})); // Carol is Liquidity Provider BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{5'000'000})); BEAST_EXPECT(ammAlice.expectLPTokens(alice, IOUAmount{5'000'000})); @@ -4775,23 +3663,14 @@ private: env(ammAlice.bid({.account = carol, .bidMin = 100})); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{4'999'900})); BEAST_EXPECT(ammAlice.expectAuctionSlot(0, 0, IOUAmount{100})); - BEAST_EXPECT( - accountBalance(env, carol) == - std::to_string(22500000000 - 4 * baseFee)); + BEAST_EXPECT(accountBalance(env, carol) == std::to_string(22500000000 - 4 * baseFee)); priceXRP = ammAssetOut( - STAmount{XRPAmount{10'000'000'000}}, - STAmount{token1, 9'999'900}, - STAmount{token1, 4'999'900}, - 0); + STAmount{XRPAmount{10'000'000'000}}, STAmount{token1, 9'999'900}, STAmount{token1, 4'999'900}, 0); // Carol withdraws ammAlice.withdrawAll(carol, XRP(0)); + BEAST_EXPECT(accountBalance(env, carol) == std::to_string(29999949999 - 5 * baseFee)); BEAST_EXPECT( - accountBalance(env, carol) == - std::to_string(29999949999 - 5 * baseFee)); - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount{10'000'000'000} - priceXRP, - USD(10'000), - IOUAmount{5'000'000})); + ammAlice.expectBalances(XRPAmount{10'000'000'000} - priceXRP, USD(10'000), IOUAmount{5'000'000})); BEAST_EXPECT(ammAlice.expectLPTokens(alice, IOUAmount{5'000'000})); BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{0})); }); @@ -4804,8 +3683,7 @@ private: ammAlice1.deposit(carol, 1'000'000); auto const token1 = ammAlice.lptIssue(); auto const token2 = ammAlice1.lptIssue(); - env(offer(alice, STAmount{token1, 100}, STAmount{token2, 100}), - txflags(tfPassive)); + env(offer(alice, STAmount{token1, 100}, STAmount{token2, 100}), txflags(tfPassive)); env.close(); BEAST_EXPECT(expectOffers(env, alice, 1)); env(offer(carol, STAmount{token2, 100}, STAmount{token1, 100})); @@ -4816,8 +3694,7 @@ private: BEAST_EXPECT( expectHolding(env, carol, STAmount{token2, 1'000'100}) && expectHolding(env, carol, STAmount{token1, 999'900})); - BEAST_EXPECT( - expectOffers(env, alice, 0) && expectOffers(env, carol, 0)); + BEAST_EXPECT(expectOffers(env, alice, 0) && expectOffers(env, carol, 0)); }); // LPs pay LPTokens directly. Must trust set because the trust line @@ -4859,8 +3736,7 @@ private: FeatureBitset const all{testable_amendments()}; FeatureBitset const noAMM{all - featureAMM}; FeatureBitset const noNumber{all - fixUniversalNumber}; - FeatureBitset const noAMMAndNumber{ - all - featureAMM - fixUniversalNumber}; + FeatureBitset const noAMMAndNumber{all - featureAMM - fixUniversalNumber}; using namespace jtx; for (auto const& feature : {noAMM, noNumber, noAMMAndNumber}) @@ -4874,8 +3750,7 @@ private: amm.vote(VoteArg{.tfee = 100, .err = ter(temDISABLED)}); amm.withdraw(WithdrawArg{.tokens = 100, .err = ter(temMALFORMED)}); amm.withdraw(WithdrawArg{.err = ter(temDISABLED)}); - amm.deposit( - DepositArg{.asset1In = USD(100), .err = ter(temDISABLED)}); + amm.deposit(DepositArg{.asset1In = USD(100), .err = ter(temDISABLED)}); amm.ammDelete(alice, ter(temDISABLED)); } } @@ -4888,16 +3763,9 @@ private: testAMM([&](AMM& ammAlice, Env& env) { auto const info = env.rpc( - "json", - "account_info", - std::string( - "{\"account\": \"" + to_string(ammAlice.ammAccount()) + - "\"}")); - auto const flags = - info[jss::result][jss::account_data][jss::Flags].asUInt(); - BEAST_EXPECT( - flags == - (lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth)); + "json", "account_info", std::string("{\"account\": \"" + to_string(ammAlice.ammAccount()) + "\"}")); + auto const flags = info[jss::result][jss::account_data][jss::Flags].asUInt(); + BEAST_EXPECT(flags == (lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth)); }); } @@ -4987,9 +3855,7 @@ private: prep( [&](Env& env) { AMM amm(env, LP1, TST(25), XRP(250)); }, [&](Env& env) { - lp2TSTBalance = - getAccountLines(env, LP2, TST)["lines"][0u]["balance"] - .asString(); + lp2TSTBalance = getAccountLines(env, LP2, TST)["lines"][0u]["balance"].asString(); auto const offer = getAccountOffers(env, LP2)["offers"][0u]; lp2TakerGets = offer["taker_gets"].asString(); lp2TakerPays = offer["taker_pays"]["value"].asString(); @@ -4998,27 +3864,17 @@ private: prep( [&](Env& env) { if (!features[fixAMMv1_1]) - env(offer( - LP1, - XRPAmount{18'095'133}, - STAmount{TST, UINT64_C(1'68737984885388), -14}), + env(offer(LP1, XRPAmount{18'095'133}, STAmount{TST, UINT64_C(1'68737984885388), -14}), txflags(tfPassive)); else - env(offer( - LP1, - XRPAmount{18'095'132}, - STAmount{TST, UINT64_C(1'68737976189735), -14}), + env(offer(LP1, XRPAmount{18'095'132}, STAmount{TST, UINT64_C(1'68737976189735), -14}), txflags(tfPassive)); }, [&](Env& env) { - BEAST_EXPECT( - lp2TSTBalance == - getAccountLines(env, LP2, TST)["lines"][0u]["balance"] - .asString()); + BEAST_EXPECT(lp2TSTBalance == getAccountLines(env, LP2, TST)["lines"][0u]["balance"].asString()); auto const offer = getAccountOffers(env, LP2)["offers"][0u]; BEAST_EXPECT(lp2TakerGets == offer["taker_gets"].asString()); - BEAST_EXPECT( - lp2TakerPays == offer["taker_pays"]["value"].asString()); + BEAST_EXPECT(lp2TakerPays == offer["taker_pays"]["value"].asString()); }); } @@ -5043,17 +3899,13 @@ private: // Carol gets fewer LPToken ~994, because of the single deposit // fee ammAlice.deposit(carol, USD(3'000)); - BEAST_EXPECT(ammAlice.expectLPTokens( - carol, IOUAmount{994'981155689671, -12})); + BEAST_EXPECT(ammAlice.expectLPTokens(carol, IOUAmount{994'981155689671, -12})); BEAST_EXPECT(expectHolding(env, carol, USD(27'000))); // Set fee to 0 ammAlice.vote(alice, 0); ammAlice.withdrawAll(carol, USD(0)); // Carol gets back less than the original deposit - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(29'994'96220068281), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(29'994'96220068281), -11})); }, {{USD(1'000), EUR(1'000)}}, 0, @@ -5065,8 +3917,7 @@ private: testAMM( [&](AMM& ammAlice, Env& env) { auto const balance = env.balance(carol, USD); - auto tokensFee = ammAlice.deposit( - carol, USD(1'000), std::nullopt, STAmount{USD, 1, -1}); + auto tokensFee = ammAlice.deposit(carol, USD(1'000), std::nullopt, STAmount{USD, 1, -1}); auto const deposit = balance - env.balance(carol, USD); ammAlice.withdrawAll(carol, USD(0)); ammAlice.vote(alice, 0); @@ -5087,8 +3938,7 @@ private: testAMM( [&](AMM& ammAlice, Env& env) { auto const balance = env.balance(carol, USD); - auto const tokensFee = ammAlice.deposit( - carol, USD(200), std::nullopt, STAmount{USD, 2020, -6}); + auto const tokensFee = ammAlice.deposit(carol, USD(200), std::nullopt, STAmount{USD, 2020, -6}); auto const deposit = balance - env.balance(carol, USD); ammAlice.withdrawAll(carol, USD(0)); ammAlice.vote(alice, 0); @@ -5117,10 +3967,7 @@ private: BEAST_EXPECT(ammAlice.expectTradingFee(1'000)); // Single withdrawal. Carol gets ~5USD less than deposited. ammAlice.withdrawAll(carol, USD(0)); - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(29'994'97487437186), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(29'994'97487437186), -11})); }, {{USD(1'000), EUR(1'000)}}, 0, @@ -5131,8 +3978,7 @@ private: testAMM( [&](AMM& ammAlice, Env& env) { ammAlice.deposit(carol, 1'000'000); - auto const tokensFee = ammAlice.withdraw( - carol, USD(100), std::nullopt, IOUAmount{520, 0}); + auto const tokensFee = ammAlice.withdraw(carol, USD(100), std::nullopt, IOUAmount{520, 0}); // carol withdraws ~1,443.44USD auto const balanceAfterWithdraw = [&]() { if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) @@ -5151,28 +3997,19 @@ private: BEAST_EXPECT(ammAlice.expectTradingFee(0)); auto const tokensNoFee = ammAlice.withdraw(carol, deposit); if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(30'443'43891402717), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(30'443'43891402717), -11)); else if (features[fixAMMv1_1] && !features[fixAMMv1_3]) - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(30'443'43891402716), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(30'443'43891402716), -11)); else - BEAST_EXPECT( - env.balance(carol, USD) == - STAmount(USD, UINT64_C(30'443'43891402713), -11)); + BEAST_EXPECT(env.balance(carol, USD) == STAmount(USD, UINT64_C(30'443'43891402713), -11)); // carol pays ~4008 LPTokens in fees or ~0.5% of the no-fee // LPTokens if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) - BEAST_EXPECT( - tokensNoFee == IOUAmount(746'579'80779913, -8)); + BEAST_EXPECT(tokensNoFee == IOUAmount(746'579'80779913, -8)); else if (features[fixAMMv1_1] && !features[fixAMMv1_3]) - BEAST_EXPECT( - tokensNoFee == IOUAmount(746'579'80779912, -8)); + BEAST_EXPECT(tokensNoFee == IOUAmount(746'579'80779912, -8)); else - BEAST_EXPECT( - tokensNoFee == IOUAmount(746'579'80779911, -8)); + BEAST_EXPECT(tokensNoFee == IOUAmount(746'579'80779911, -8)); BEAST_EXPECT(tokensFee == IOUAmount(750'588'23529411, -8)); }, std::nullopt, @@ -5183,22 +4020,13 @@ private: // Payment, 1% fee testAMM( [&](AMM& ammAlice, Env& env) { - fund( - env, - gw, - {bob}, - XRP(1'000), - {USD(1'000), EUR(1'000)}, - Fund::Acct); + fund(env, gw, {bob}, XRP(1'000), {USD(1'000), EUR(1'000)}, Fund::Acct); // Alice contributed 1010EUR and 1000USD to the pool BEAST_EXPECT(expectHolding(env, alice, EUR(28'990))); BEAST_EXPECT(expectHolding(env, alice, USD(29'000))); BEAST_EXPECT(expectHolding(env, carol, USD(30'000))); // Carol pays to Alice with no fee - env(pay(carol, alice, EUR(10)), - path(~EUR), - sendmax(USD(10)), - txflags(tfNoRippleDirect)); + env(pay(carol, alice, EUR(10)), path(~EUR), sendmax(USD(10)), txflags(tfNoRippleDirect)); env.close(); // Alice has 10EUR more and Carol has 10USD less BEAST_EXPECT(expectHolding(env, alice, EUR(29'000))); @@ -5209,20 +4037,14 @@ private: ammAlice.vote(alice, 1'000); BEAST_EXPECT(ammAlice.expectTradingFee(1'000)); // Bob pays to Carol with 1% fee - env(pay(bob, carol, USD(10)), - path(~USD), - sendmax(EUR(15)), - txflags(tfNoRippleDirect)); + env(pay(bob, carol, USD(10)), path(~USD), sendmax(EUR(15)), txflags(tfNoRippleDirect)); env.close(); // Bob sends 10.1~EUR to pay 10USD - BEAST_EXPECT(expectHolding( - env, bob, STAmount{EUR, UINT64_C(989'8989898989899), -13})); + BEAST_EXPECT(expectHolding(env, bob, STAmount{EUR, UINT64_C(989'8989898989899), -13})); // Carol got 10USD BEAST_EXPECT(expectHolding(env, carol, USD(30'000))); BEAST_EXPECT(ammAlice.expectBalances( - USD(1'000), - STAmount{EUR, UINT64_C(1'010'10101010101), -11}, - ammAlice.tokens())); + USD(1'000), STAmount{EUR, UINT64_C(1'010'10101010101), -11}, ammAlice.tokens())); }, {{USD(1'000), EUR(1'010)}}, 0, @@ -5247,14 +4069,8 @@ private: env.close(); // Alice gets fewer ~4.97EUR for ~5.02USD, the difference goes // to the pool - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(29'995'02512562814), -11})); - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{EUR, UINT64_C(30'004'97487437186), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(29'995'02512562814), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{EUR, UINT64_C(30'004'97487437186), -11})); BEAST_EXPECT(expectOffers( env, carol, @@ -5289,33 +4105,21 @@ private: { Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(2'000), EUR(2'000)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(2'000), EUR(2'000)}); env(offer(carol, EUR(5), USD(5))); AMM ammAlice(env, alice, USD(1'005), EUR(1'000)); - env(pay(bob, ed, USD(10)), - path(~USD), - sendmax(EUR(15)), - txflags(tfNoRippleDirect)); + env(pay(bob, ed, USD(10)), path(~USD), sendmax(EUR(15)), txflags(tfNoRippleDirect)); BEAST_EXPECT(expectHolding(env, ed, USD(2'010))); if (!features[fixAMMv1_1]) { BEAST_EXPECT(expectHolding(env, bob, EUR(1'990))); - BEAST_EXPECT(ammAlice.expectBalances( - USD(1'000), EUR(1'005), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(USD(1'000), EUR(1'005), ammAlice.tokens())); } else { - BEAST_EXPECT(expectHolding( - env, bob, STAmount(EUR, UINT64_C(1989'999999999999), -12))); + BEAST_EXPECT(expectHolding(env, bob, STAmount(EUR, UINT64_C(1989'999999999999), -12))); BEAST_EXPECT(ammAlice.expectBalances( - USD(1'000), - STAmount(EUR, UINT64_C(1005'000000000001), -12), - ammAlice.tokens())); + USD(1'000), STAmount(EUR, UINT64_C(1005'000000000001), -12), ammAlice.tokens())); } BEAST_EXPECT(expectOffers(env, carol, 0)); } @@ -5325,41 +4129,23 @@ private: { Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(2'000), EUR(2'000)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(2'000), EUR(2'000)}); env(offer(carol, EUR(5), USD(5))); // Set 0.25% fee AMM ammAlice(env, alice, USD(1'005), EUR(1'000), false, 250); - env(pay(bob, ed, USD(10)), - path(~USD), - sendmax(EUR(15)), - txflags(tfNoRippleDirect)); + env(pay(bob, ed, USD(10)), path(~USD), sendmax(EUR(15)), txflags(tfNoRippleDirect)); BEAST_EXPECT(expectHolding(env, ed, USD(2'010))); if (!features[fixAMMv1_1]) { - BEAST_EXPECT(expectHolding( - env, - bob, - STAmount{EUR, UINT64_C(1'989'987453007618), -12})); + BEAST_EXPECT(expectHolding(env, bob, STAmount{EUR, UINT64_C(1'989'987453007618), -12})); BEAST_EXPECT(ammAlice.expectBalances( - USD(1'000), - STAmount{EUR, UINT64_C(1'005'012546992382), -12}, - ammAlice.tokens())); + USD(1'000), STAmount{EUR, UINT64_C(1'005'012546992382), -12}, ammAlice.tokens())); } else { - BEAST_EXPECT(expectHolding( - env, - bob, - STAmount{EUR, UINT64_C(1'989'987453007628), -12})); + BEAST_EXPECT(expectHolding(env, bob, STAmount{EUR, UINT64_C(1'989'987453007628), -12})); BEAST_EXPECT(ammAlice.expectBalances( - USD(1'000), - STAmount{EUR, UINT64_C(1'005'012546992372), -12}, - ammAlice.tokens())); + USD(1'000), STAmount{EUR, UINT64_C(1'005'012546992372), -12}, ammAlice.tokens())); } BEAST_EXPECT(expectOffers(env, carol, 0)); } @@ -5370,23 +4156,14 @@ private: { Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(2'000), EUR(2'000)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(2'000), EUR(2'000)}); env(offer(carol, EUR(10), USD(10))); // Set 1% fee AMM ammAlice(env, alice, USD(1'005), EUR(1'000), false, 1'000); - env(pay(bob, ed, USD(10)), - path(~USD), - sendmax(EUR(15)), - txflags(tfNoRippleDirect)); + env(pay(bob, ed, USD(10)), path(~USD), sendmax(EUR(15)), txflags(tfNoRippleDirect)); BEAST_EXPECT(expectHolding(env, ed, USD(2'010))); BEAST_EXPECT(expectHolding(env, bob, EUR(1'990))); - BEAST_EXPECT(ammAlice.expectBalances( - USD(1'005), EUR(1'000), ammAlice.tokens())); + BEAST_EXPECT(ammAlice.expectBalances(USD(1'005), EUR(1'000), ammAlice.tokens())); BEAST_EXPECT(expectOffers(env, carol, 0)); } @@ -5397,26 +4174,15 @@ private: { Env env(*this, features); Account const ed("ed"); - fund( - env, - gw, - {alice, bob, carol, ed}, - XRP(1'000), - {USD(2'000), EUR(2'000)}); + fund(env, gw, {alice, bob, carol, ed}, XRP(1'000), {USD(2'000), EUR(2'000)}); env(offer(carol, EUR(9), USD(9))); // Set 1% fee AMM ammAlice(env, alice, USD(1'005), EUR(1'000), false, 1'000); - env(pay(bob, ed, USD(10)), - path(~USD), - sendmax(EUR(15)), - txflags(tfNoRippleDirect)); + env(pay(bob, ed, USD(10)), path(~USD), sendmax(EUR(15)), txflags(tfNoRippleDirect)); BEAST_EXPECT(expectHolding(env, ed, USD(2'010))); - BEAST_EXPECT(expectHolding( - env, bob, STAmount{EUR, UINT64_C(1'989'993923296712), -12})); + BEAST_EXPECT(expectHolding(env, bob, STAmount{EUR, UINT64_C(1'989'993923296712), -12})); BEAST_EXPECT(ammAlice.expectBalances( - USD(1'004), - STAmount{EUR, UINT64_C(1'001'006076703288), -12}, - ammAlice.tokens())); + USD(1'004), STAmount{EUR, UINT64_C(1'001'006076703288), -12}, ammAlice.tokens())); BEAST_EXPECT(expectOffers(env, carol, 0)); } } @@ -5439,12 +4205,7 @@ private: Account const simon("simon"); Account const ben("ben"); Account const nataly("nataly"); - fund( - env, - gw, - {bob, ed, paul, dan, chris, simon, ben, nataly}, - {USD(1'500'000)}, - Fund::Acct); + fund(env, gw, {bob, ed, paul, dan, chris, simon, ben, nataly}, {USD(1'500'000)}, Fund::Acct); for (int i = 0; i < 10; ++i) { ammAlice.deposit(ben, STAmount{USD, 1, -10}); @@ -5471,26 +4232,18 @@ private: // gets everything in the pool. if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, UINT64_C(10'000'0000000013), -10}, - IOUAmount{10'000'000})); + XRP(10'000), STAmount{USD, UINT64_C(10'000'0000000013), -10}, IOUAmount{10'000'000})); else if (features[fixAMMv1_3]) BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), - STAmount{USD, UINT64_C(10'000'0000000003), -10}, - IOUAmount{10'000'000})); + XRP(10'000), STAmount{USD, UINT64_C(10'000'0000000003), -10}, IOUAmount{10'000'000})); else - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{10'000'000})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{10'000'000})); BEAST_EXPECT(expectHolding(env, ben, USD(1'500'000))); BEAST_EXPECT(expectHolding(env, simon, USD(1'500'000))); BEAST_EXPECT(expectHolding(env, chris, USD(1'500'000))); BEAST_EXPECT(expectHolding(env, dan, USD(1'500'000))); if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) - BEAST_EXPECT(expectHolding( - env, - carol, - STAmount{USD, UINT64_C(30'000'00000000001), -11})); + BEAST_EXPECT(expectHolding(env, carol, STAmount{USD, UINT64_C(30'000'00000000001), -11})); else if (features[fixAMMv1_1] && !features[fixAMMv1_3]) BEAST_EXPECT(expectHolding(env, carol, USD(30'000))); else @@ -5498,37 +4251,23 @@ private: BEAST_EXPECT(expectHolding(env, ed, USD(1'500'000))); BEAST_EXPECT(expectHolding(env, paul, USD(1'500'000))); if (!features[fixAMMv1_1] && !features[fixAMMv1_3]) - BEAST_EXPECT(expectHolding( - env, - nataly, - STAmount{USD, UINT64_C(1'500'000'000000002), -9})); + BEAST_EXPECT(expectHolding(env, nataly, STAmount{USD, UINT64_C(1'500'000'000000002), -9})); else if (features[fixAMMv1_1] && !features[fixAMMv1_3]) - BEAST_EXPECT(expectHolding( - env, - nataly, - STAmount{USD, UINT64_C(1'500'000'000000005), -9})); + BEAST_EXPECT(expectHolding(env, nataly, STAmount{USD, UINT64_C(1'500'000'000000005), -9})); else BEAST_EXPECT(expectHolding(env, nataly, USD(1'500'000))); ammAlice.withdrawAll(alice); BEAST_EXPECT(!ammAlice.ammExists()); if (!features[fixAMMv1_1]) - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{USD, UINT64_C(30'000'0000000013), -10})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{USD, UINT64_C(30'000'0000000013), -10})); else if (features[fixAMMv1_3]) - BEAST_EXPECT(expectHolding( - env, - alice, - STAmount{USD, UINT64_C(30'000'0000000003), -10})); + BEAST_EXPECT(expectHolding(env, alice, STAmount{USD, UINT64_C(30'000'0000000003), -10})); else BEAST_EXPECT(expectHolding(env, alice, USD(30'000))); // alice XRP balance is 30,000initial - 50 ammcreate fee - // 10drops fee BEAST_EXPECT( - accountBalance(env, alice) == - std::to_string( - 29950000000 - env.current()->fees().base.drops())); + accountBalance(env, alice) == std::to_string(29950000000 - env.current()->fees().base.drops())); }, std::nullopt, 0, @@ -5546,13 +4285,7 @@ private: Account const simon("simon"); Account const ben("ben"); Account const nataly("nataly"); - fund( - env, - gw, - {bob, ed, paul, dan, chris, simon, ben, nataly}, - XRP(2'000'000), - {}, - Fund::Acct); + fund(env, gw, {bob, ed, paul, dan, chris, simon, ben, nataly}, XRP(2'000'000), {}, Fund::Acct); for (int i = 0; i < 10; ++i) { ammAlice.deposit(ben, XRPAmount{1}); @@ -5578,62 +4311,43 @@ private: if (!features[fixAMMv1_3]) { // No round off with XRP in this test - BEAST_EXPECT(ammAlice.expectBalances( - XRP(10'000), USD(10'000), IOUAmount{10'000'000})); + BEAST_EXPECT(ammAlice.expectBalances(XRP(10'000), USD(10'000), IOUAmount{10'000'000})); ammAlice.withdrawAll(alice); BEAST_EXPECT(!ammAlice.ammExists()); // 20,000 initial - (deposit+withdraw) * 10 - auto const xrpBalance = - (XRP(2'000'000) - txfee(env, 20)).getText(); + auto const xrpBalance = (XRP(2'000'000) - txfee(env, 20)).getText(); BEAST_EXPECT(accountBalance(env, ben) == xrpBalance); BEAST_EXPECT(accountBalance(env, simon) == xrpBalance); BEAST_EXPECT(accountBalance(env, chris) == xrpBalance); BEAST_EXPECT(accountBalance(env, dan) == xrpBalance); // 30,000 initial - (deposit+withdraw) * 10 - BEAST_EXPECT( - accountBalance(env, carol) == - std::to_string(30'000'000'000 - 20 * baseFee)); + BEAST_EXPECT(accountBalance(env, carol) == std::to_string(30'000'000'000 - 20 * baseFee)); BEAST_EXPECT(accountBalance(env, ed) == xrpBalance); BEAST_EXPECT(accountBalance(env, paul) == xrpBalance); BEAST_EXPECT(accountBalance(env, nataly) == xrpBalance); // 30,000 initial - 50 ammcreate fee - 10drops withdraw fee - BEAST_EXPECT( - accountBalance(env, alice) == - std::to_string(29'950'000'000 - baseFee)); + BEAST_EXPECT(accountBalance(env, alice) == std::to_string(29'950'000'000 - baseFee)); } else { // post-amendment the rounding takes place to ensure // AMM invariant - BEAST_EXPECT(ammAlice.expectBalances( - XRPAmount(10'000'000'080), - USD(10'000), - IOUAmount{10'000'000})); + BEAST_EXPECT( + ammAlice.expectBalances(XRPAmount(10'000'000'080), USD(10'000), IOUAmount{10'000'000})); ammAlice.withdrawAll(alice); BEAST_EXPECT(!ammAlice.ammExists()); - auto const xrpBalance = - XRP(2'000'000) - txfee(env, 20) - drops(10); + auto const xrpBalance = XRP(2'000'000) - txfee(env, 20) - drops(10); auto const xrpBalanceText = xrpBalance.getText(); BEAST_EXPECT(accountBalance(env, ben) == xrpBalanceText); BEAST_EXPECT(accountBalance(env, simon) == xrpBalanceText); BEAST_EXPECT(accountBalance(env, chris) == xrpBalanceText); BEAST_EXPECT(accountBalance(env, dan) == xrpBalanceText); - BEAST_EXPECT( - accountBalance(env, carol) == - std::to_string(30'000'000'000 - 20 * baseFee - 10)); - BEAST_EXPECT( - accountBalance(env, ed) == - (xrpBalance + drops(2)).getText()); - BEAST_EXPECT( - accountBalance(env, paul) == - (xrpBalance + drops(3)).getText()); - BEAST_EXPECT( - accountBalance(env, nataly) == - (xrpBalance + drops(5)).getText()); - BEAST_EXPECT( - accountBalance(env, alice) == - std::to_string(29'950'000'000 - baseFee + 80)); + BEAST_EXPECT(accountBalance(env, carol) == std::to_string(30'000'000'000 - 20 * baseFee - 10)); + BEAST_EXPECT(accountBalance(env, ed) == (xrpBalance + drops(2)).getText()); + BEAST_EXPECT(accountBalance(env, paul) == (xrpBalance + drops(3)).getText()); + BEAST_EXPECT(accountBalance(env, nataly) == (xrpBalance + drops(5)).getText()); + BEAST_EXPECT(accountBalance(env, alice) == std::to_string(29'950'000'000 - baseFee + 80)); } }, std::nullopt, @@ -5679,24 +4393,10 @@ private: .bidMin = 1000, }), ter(tecAMM_EMPTY)); - amm.vote( - std::nullopt, - 100, - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecAMM_EMPTY)); - amm.withdraw( - alice, 100, std::nullopt, std::nullopt, ter(tecAMM_EMPTY)); - amm.deposit( - alice, - USD(100), - std::nullopt, - std::nullopt, - std::nullopt, - ter(tecAMM_EMPTY)); - env(trust(alice, STAmount{amm.lptIssue(), 10'000}), - ter(tecAMM_EMPTY)); + amm.vote(std::nullopt, 100, std::nullopt, std::nullopt, std::nullopt, ter(tecAMM_EMPTY)); + amm.withdraw(alice, 100, std::nullopt, std::nullopt, ter(tecAMM_EMPTY)); + amm.deposit(alice, USD(100), std::nullopt, std::nullopt, std::nullopt, ter(tecAMM_EMPTY)); + env(trust(alice, STAmount{amm.lptIssue(), 10'000}), ter(tecAMM_EMPTY)); // Can deposit with tfTwoAssetIfEmpty option amm.deposit( @@ -5709,8 +4409,7 @@ private: std::nullopt, std::nullopt, 1'000); - BEAST_EXPECT( - amm.expectBalances(XRP(10'000), USD(10'000), amm.tokens())); + BEAST_EXPECT(amm.expectBalances(XRP(10'000), USD(10'000), amm.tokens())); BEAST_EXPECT(amm.expectTradingFee(1'000)); BEAST_EXPECT(amm.expectAuctionSlot(100, 0, IOUAmount{0})); @@ -5774,40 +4473,30 @@ private: using namespace jtx; testAMM([&](AMM& amm, Env& env) { amm.setClose(false); - auto const info = env.rpc( - "json", - "account_info", - std::string( - "{\"account\": \"" + to_string(amm.ammAccount()) + "\"}")); + auto const info = + env.rpc("json", "account_info", std::string("{\"account\": \"" + to_string(amm.ammAccount()) + "\"}")); try { - BEAST_EXPECT( - info[jss::result][jss::account_data][jss::AMMID] - .asString() == to_string(amm.ammID())); + BEAST_EXPECT(info[jss::result][jss::account_data][jss::AMMID].asString() == to_string(amm.ammID())); } catch (...) { fail(); } amm.deposit(carol, 1'000); - auto affected = env.meta()->getJson( - JsonOptions::none)[sfAffectedNodes.fieldName]; + auto affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; try { bool found = false; for (auto const& node : affected) { if (node.isMember(sfModifiedNode.fieldName) && - node[sfModifiedNode.fieldName] - [sfLedgerEntryType.fieldName] - .asString() == "AccountRoot" && - node[sfModifiedNode.fieldName][sfFinalFields.fieldName] - [jss::Account] - .asString() == to_string(amm.ammAccount())) + node[sfModifiedNode.fieldName][sfLedgerEntryType.fieldName].asString() == "AccountRoot" && + node[sfModifiedNode.fieldName][sfFinalFields.fieldName][jss::Account].asString() == + to_string(amm.ammAccount())) { - found = node[sfModifiedNode.fieldName] - [sfFinalFields.fieldName][jss::AMMID] - .asString() == to_string(amm.ammID()); + found = node[sfModifiedNode.fieldName][sfFinalFields.fieldName][jss::AMMID].asString() == + to_string(amm.ammID()); break; } } @@ -5837,19 +4526,13 @@ private: auto prep = [&](Env& env, auto gwRate, auto gw1Rate) { fund(env, gw, {alice, carol, bob, ed}, XRP(2'000), {USD(2'000)}); env.fund(XRP(2'000), gw1); - fund( - env, - gw1, - {alice, carol, bob, ed}, - {ETH(2'000), CAN(2'000)}, - Fund::IOUOnly); + fund(env, gw1, {alice, carol, bob, ed}, {ETH(2'000), CAN(2'000)}, Fund::IOUOnly); env(rate(gw, gwRate)); env(rate(gw1, gw1Rate)); env.close(); }; - for (auto const& rates : - {std::make_pair(1.5, 1.9), std::make_pair(1.9, 1.5)}) + for (auto const& rates : {std::make_pair(1.5, 1.9), std::make_pair(1.9, 1.5)}) { // Offer Selection @@ -5875,20 +4558,15 @@ private: } if (i > 0) amm.emplace(env, ed, USD(1'000), ETH(1'000)); - env(pay(carol, bob, USD(100)), - path(~USD), - sendmax(ETH(500))); + env(pay(carol, bob, USD(100)), path(~USD), sendmax(ETH(500))); env.close(); // CLOB and AMM, AMM is not selected if (i == 2) { - BEAST_EXPECT(amm->expectBalances( - USD(1'000), ETH(1'000), amm->tokens())); + BEAST_EXPECT(amm->expectBalances(USD(1'000), ETH(1'000), amm->tokens())); } BEAST_EXPECT(expectHolding(env, bob, USD(2'100))); - q[i] = Quality(Amounts{ - ETH(2'000) - env.balance(carol, ETH), - env.balance(bob, USD) - USD(2'000)}); + q[i] = Quality(Amounts{ETH(2'000) - env.balance(carol, ETH), env.balance(bob, USD) - USD(2'000)}); } // CLOB is better quality than AMM BEAST_EXPECT(q[0] > q[1]); @@ -5917,8 +4595,7 @@ private: // AMM is not selected if (i > 0) { - BEAST_EXPECT(amm->expectBalances( - USD(1'000), ETH(1'000), amm->tokens())); + BEAST_EXPECT(amm->expectBalances(USD(1'000), ETH(1'000), amm->tokens())); } if (i == 0 || i == 2) { @@ -5928,8 +4605,7 @@ private: // Fails to cross because AMM is not selected else { - BEAST_EXPECT(expectOffers( - env, alice, 1, {Amounts{USD(400), ETH(400)}})); + BEAST_EXPECT(expectOffers(env, alice, 1, {Amounts{USD(400), ETH(400)}})); } BEAST_EXPECT(expectOffers(env, ed, 0)); } @@ -5952,15 +4628,12 @@ private: } if (i > 0) amm.emplace(env, ed, USD(1'000), ETH(1'000)); - env(pay(carol, bob, USD(100)), - path(~USD), - sendmax(ETH(500))); + env(pay(carol, bob, USD(100)), path(~USD), sendmax(ETH(500))); env.close(); // AMM and CLOB are selected if (i > 0) { - BEAST_EXPECT(!amm->expectBalances( - USD(1'000), ETH(1'000), amm->tokens())); + BEAST_EXPECT(!amm->expectBalances(USD(1'000), ETH(1'000), amm->tokens())); } if (i == 2 && !features[fixAMMv1_1]) { @@ -5972,28 +4645,16 @@ private: ed, 1, {{Amounts{ - STAmount{ - ETH, - UINT64_C(378'6327949540823), - -13}, - STAmount{ - USD, - UINT64_C(283'9745962155617), - -13}}}})); + STAmount{ETH, UINT64_C(378'6327949540823), -13}, + STAmount{USD, UINT64_C(283'9745962155617), -13}}}})); else BEAST_EXPECT(expectOffers( env, ed, 1, {{Amounts{ - STAmount{ - ETH, - UINT64_C(378'6327949540813), - -13}, - STAmount{ - USD, - UINT64_C(283'974596215561), - -12}}}})); + STAmount{ETH, UINT64_C(378'6327949540813), -13}, + STAmount{USD, UINT64_C(283'974596215561), -12}}}})); } else { @@ -6003,28 +4664,16 @@ private: ed, 1, {{Amounts{ - STAmount{ - ETH, - UINT64_C(325'299461620749), - -12}, - STAmount{ - USD, - UINT64_C(243'9745962155617), - -13}}}})); + STAmount{ETH, UINT64_C(325'299461620749), -12}, + STAmount{USD, UINT64_C(243'9745962155617), -13}}}})); else BEAST_EXPECT(expectOffers( env, ed, 1, {{Amounts{ - STAmount{ - ETH, - UINT64_C(325'299461620748), - -12}, - STAmount{ - USD, - UINT64_C(243'974596215561), - -12}}}})); + STAmount{ETH, UINT64_C(325'299461620748), -12}, + STAmount{USD, UINT64_C(243'974596215561), -12}}}})); } } else if (i == 2) @@ -6036,12 +4685,8 @@ private: ed, 1, {{Amounts{ - STAmount{ - ETH, UINT64_C(378'6327949540812), -13}, - STAmount{ - USD, - UINT64_C(283'9745962155609), - -13}}}})); + STAmount{ETH, UINT64_C(378'6327949540812), -13}, + STAmount{USD, UINT64_C(283'9745962155609), -13}}}})); } else { @@ -6050,18 +4695,12 @@ private: ed, 1, {{Amounts{ - STAmount{ - ETH, UINT64_C(325'2994616207479), -13}, - STAmount{ - USD, - UINT64_C(243'9745962155609), - -13}}}})); + STAmount{ETH, UINT64_C(325'2994616207479), -13}, + STAmount{USD, UINT64_C(243'9745962155609), -13}}}})); } } BEAST_EXPECT(expectHolding(env, bob, USD(2'100))); - q[i] = Quality(Amounts{ - ETH(2'000) - env.balance(carol, ETH), - env.balance(bob, USD) - USD(2'000)}); + q[i] = Quality(Amounts{ETH(2'000) - env.balance(carol, ETH), env.balance(bob, USD) - USD(2'000)}); } // AMM is better quality BEAST_EXPECT(q[1] > q[0]); @@ -6087,8 +4726,7 @@ private: // AMM is selected in both cases if (i > 0) { - BEAST_EXPECT(!amm->expectBalances( - USD(1'000), ETH(1'000), amm->tokens())); + BEAST_EXPECT(!amm->expectBalances(USD(1'000), ETH(1'000), amm->tokens())); } // Partially crosses, AMM is selected, CLOB fails // limitQuality @@ -6098,17 +4736,14 @@ private: { if (!features[fixAMMv1_1]) { - BEAST_EXPECT(expectOffers( - env, ed, 1, {{Amounts{ETH(400), USD(250)}}})); + BEAST_EXPECT(expectOffers(env, ed, 1, {{Amounts{ETH(400), USD(250)}}})); BEAST_EXPECT(expectOffers( env, alice, 1, {{Amounts{ - STAmount{ - USD, UINT64_C(40'5694150420947), -13}, - STAmount{ - ETH, UINT64_C(64'91106406735152), -14}, + STAmount{USD, UINT64_C(40'5694150420947), -13}, + STAmount{ETH, UINT64_C(64'91106406735152), -14}, }}})); } else @@ -6121,10 +4756,8 @@ private: ed, 1, {{Amounts{ - STAmount{ - ETH, UINT64_C(335'0889359326475), -13}, - STAmount{ - USD, UINT64_C(209'4305849579047), -13}, + STAmount{ETH, UINT64_C(335'0889359326475), -13}, + STAmount{USD, UINT64_C(209'4305849579047), -13}, }}})); BEAST_EXPECT(expectOffers(env, alice, 0)); } @@ -6139,10 +4772,8 @@ private: ed, 1, {{Amounts{ - STAmount{ - ETH, UINT64_C(335'0889359326485), -13}, - STAmount{ - USD, UINT64_C(209'4305849579053), -13}, + STAmount{ETH, UINT64_C(335'0889359326485), -13}, + STAmount{USD, UINT64_C(209'4305849579053), -13}, }}})); BEAST_EXPECT(expectOffers(env, alice, 0)); } @@ -6154,10 +4785,8 @@ private: ed, 1, {{Amounts{ - STAmount{ - ETH, UINT64_C(335'0889359326475), -13}, - STAmount{ - USD, UINT64_C(209'4305849579047), -13}, + STAmount{ETH, UINT64_C(335'0889359326475), -13}, + STAmount{USD, UINT64_C(209'4305849579047), -13}, }}})); BEAST_EXPECT(expectOffers(env, alice, 0)); } @@ -6199,10 +4828,7 @@ private: if (i > 0) amm.emplace(env, ed, ETH(1'000), USD(1'000)); - env(pay(carol, bob, USD(100)), - path(~USD), - path(~CAN, ~USD), - sendmax(ETH(600))); + env(pay(carol, bob, USD(100)), path(~USD), path(~CAN, ~USD), sendmax(ETH(600))); env.close(); BEAST_EXPECT(expectHolding(env, bob, USD(2'100))); @@ -6213,15 +4839,12 @@ private: { // Liquidity is consumed from AMM strand only BEAST_EXPECT(amm->expectBalances( - STAmount{ETH, UINT64_C(1'176'66038955758), -11}, - USD(850), - amm->tokens())); + STAmount{ETH, UINT64_C(1'176'66038955758), -11}, USD(850), amm->tokens())); } else { BEAST_EXPECT(amm->expectBalances( - STAmount{ - ETH, UINT64_C(1'179'540094339627), -12}, + STAmount{ETH, UINT64_C(1'179'540094339627), -12}, STAmount{USD, UINT64_C(847'7880529867501), -13}, amm->tokens())); BEAST_EXPECT(expectOffers( @@ -6229,24 +4852,12 @@ private: ed, 2, {{Amounts{ - STAmount{ - ETH, - UINT64_C(343'3179205198749), - -13}, - STAmount{ - CAN, - UINT64_C(343'3179205198749), - -13}, + STAmount{ETH, UINT64_C(343'3179205198749), -13}, + STAmount{CAN, UINT64_C(343'3179205198749), -13}, }, Amounts{ - STAmount{ - CAN, - UINT64_C(362'2119470132499), - -13}, - STAmount{ - USD, - UINT64_C(362'2119470132499), - -13}, + STAmount{CAN, UINT64_C(362'2119470132499), -13}, + STAmount{USD, UINT64_C(362'2119470132499), -13}, }}})); } } @@ -6256,10 +4867,7 @@ private: { // Liquidity is consumed from AMM strand only BEAST_EXPECT(amm->expectBalances( - STAmount{ - ETH, UINT64_C(1'176'660389557593), -12}, - USD(850), - amm->tokens())); + STAmount{ETH, UINT64_C(1'176'660389557593), -12}, USD(850), amm->tokens())); } else { @@ -6272,30 +4880,16 @@ private: ed, 2, {{Amounts{ - STAmount{ - ETH, - UINT64_C(343'3179205198749), - -13}, - STAmount{ - CAN, - UINT64_C(343'3179205198749), - -13}, + STAmount{ETH, UINT64_C(343'3179205198749), -13}, + STAmount{CAN, UINT64_C(343'3179205198749), -13}, }, Amounts{ - STAmount{ - CAN, - UINT64_C(362'2119470132499), - -13}, - STAmount{ - USD, - UINT64_C(362'2119470132499), - -13}, + STAmount{CAN, UINT64_C(362'2119470132499), -13}, + STAmount{USD, UINT64_C(362'2119470132499), -13}, }}})); } } - q[i] = Quality(Amounts{ - ETH(2'000) - env.balance(carol, ETH), - env.balance(bob, USD) - USD(2'000)}); + q[i] = Quality(Amounts{ETH(2'000) - env.balance(carol, ETH), env.balance(bob, USD) - USD(2'000)}); } BEAST_EXPECT(q[1] > q[0]); BEAST_EXPECT(q[2] > q[0] && q[2] < q[1]); @@ -6320,37 +4914,23 @@ private: std::optional extra = std::nullopt) { Env env(*this, features); fund(env, gw, {alice}, XRP(1'000), {USD(10)}); - AMM amm( - env, - gw, - XRP(10), - USD(10), - {.tfee = tfee, .close = closeLedger}); + AMM amm(env, gw, XRP(10), USD(10), {.tfee = tfee, .close = closeLedger}); amm.deposit(alice, USD(10), XRP(10)); amm.vote(VoteArg{.account = alice, .tfee = tfee, .err = ter(err1)}); - amm.withdraw(WithdrawArg{ - .account = gw, .asset1Out = USD(1), .err = ter(err2)}); + amm.withdraw(WithdrawArg{.account = gw, .asset1Out = USD(1), .err = ter(err2)}); // with the amendment disabled and ledger not closed, // second vote succeeds if the first vote sets the trading fee // to non-zero; if the first vote sets the trading fee to >0 && // <9 then the second withdraw succeeds if the second vote sets // the trading fee so that the discounted fee is non-zero amm.vote(VoteArg{.account = alice, .tfee = 20, .err = ter(err3)}); - amm.withdraw(WithdrawArg{ - .account = gw, .asset1Out = USD(2), .err = ter(err4)}); + amm.withdraw(WithdrawArg{.account = gw, .asset1Out = USD(2), .err = ter(err4)}); }; // ledger is closed after each transaction, vote/withdraw don't fail // regardless whether the amendment is enabled or not test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 0, true); - test( - all - fixInnerObjTemplate, - tesSUCCESS, - tesSUCCESS, - tesSUCCESS, - tesSUCCESS, - 0, - true); + test(all - fixInnerObjTemplate, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 0, true); // ledger is not closed after each transaction // vote/withdraw don't fail if the amendment is enabled test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 0, false); @@ -6358,49 +4938,21 @@ private: // second vote/withdraw still fail: second vote fails because // the initial trading fee is 0, consequently second withdraw fails // because the second vote fails - test( - all - fixInnerObjTemplate, - tefEXCEPTION, - tefEXCEPTION, - tefEXCEPTION, - tefEXCEPTION, - 0, - false); + test(all - fixInnerObjTemplate, tefEXCEPTION, tefEXCEPTION, tefEXCEPTION, tefEXCEPTION, 0, false); // if non-zero trading/discounted fee then vote/withdraw // don't fail whether the ledger is closed or not and // the amendment is enabled or not test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 10, true); - test( - all - fixInnerObjTemplate, - tesSUCCESS, - tesSUCCESS, - tesSUCCESS, - tesSUCCESS, - 10, - true); + test(all - fixInnerObjTemplate, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 10, true); test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 10, false); - test( - all - fixInnerObjTemplate, - tesSUCCESS, - tesSUCCESS, - tesSUCCESS, - tesSUCCESS, - 10, - false); + test(all - fixInnerObjTemplate, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 10, false); // non-zero trading fee but discounted fee is 0, vote doesn't fail // but withdraw fails test(all, tesSUCCESS, tesSUCCESS, tesSUCCESS, tesSUCCESS, 9, false); // second vote sets the trading fee to non-zero, consequently // second withdraw doesn't fail even if the amendment is not // enabled and the ledger is not closed - test( - all - fixInnerObjTemplate, - tesSUCCESS, - tefEXCEPTION, - tesSUCCESS, - tesSUCCESS, - 9, - false); + test(all - fixInnerObjTemplate, tesSUCCESS, tefEXCEPTION, tesSUCCESS, tesSUCCESS, 9, false); } void @@ -6420,14 +4972,12 @@ private: // side is generated first SucceedShouldFail, // Succeed in pre-fix, fail after fix // due to small quality difference - Fail, // Both fail because the quality can't be matched - Succeed // Both succeed + Fail, // Both fail because the quality can't be matched + Succeed // Both succeed }; using enum Status; - auto const xrpIouAmounts10_100 = - TAmounts{XRPAmount{10}, IOUAmount{100}}; - auto const iouXrpAmounts10_100 = - TAmounts{IOUAmount{10}, XRPAmount{100}}; + auto const xrpIouAmounts10_100 = TAmounts{XRPAmount{10}, IOUAmount{100}}; + auto const iouXrpAmounts10_100 = TAmounts{IOUAmount{10}, XRPAmount{100}}; // clang-format off std::vector> tests = { //Pool In , Pool Out, Quality , Fee, Status @@ -6508,21 +5058,15 @@ private: auto const& quality = std::get(t); auto const tfee = std::get(t); auto const status = std::get(t); - auto const poolInIsXRP = - boost::regex_search(std::get<0>(t), match, rx); - auto const poolOutIsXRP = - boost::regex_search(std::get<1>(t), match, rx); + auto const poolInIsXRP = boost::regex_search(std::get<0>(t), match, rx); + auto const poolOutIsXRP = boost::regex_search(std::get<1>(t), match, rx); assert(!(poolInIsXRP && poolOutIsXRP)); auto const poolIn = getPool(std::get<0>(t), poolInIsXRP); auto const poolOut = getPool(std::get<1>(t), poolOutIsXRP); try { auto const amounts = changeSpotPriceQuality( - Amounts{poolIn, poolOut}, - quality, - tfee, - env.current()->rules(), - env.journal); + Amounts{poolIn, poolOut}, quality, tfee, env.current()->rules(), env.journal); if (amounts) { if (status == SucceedShouldSucceedResize) @@ -6537,24 +5081,19 @@ private: if (!features[fixAMMv1_1]) BEAST_EXPECT( Quality{*amounts} >= quality || - withinRelativeDistance( - Quality{*amounts}, quality, Number{1, -7})); + withinRelativeDistance(Quality{*amounts}, quality, Number{1, -7})); else BEAST_EXPECT(Quality{*amounts} >= quality); } else if (status == FailShouldSucceed) { - BEAST_EXPECT( - features[fixAMMv1_1] && - Quality{*amounts} >= quality); + BEAST_EXPECT(features[fixAMMv1_1] && Quality{*amounts} >= quality); } else if (status == SucceedShouldFail) { BEAST_EXPECT( - !features[fixAMMv1_1] && - Quality{*amounts} < quality && - withinRelativeDistance( - Quality{*amounts}, quality, Number{1, -7})); + !features[fixAMMv1_1] && Quality{*amounts} < quality && + withinRelativeDistance(Quality{*amounts}, quality, Number{1, -7})); } } else @@ -6569,29 +5108,15 @@ private: if (isXRP(poolIn)) { auto const takerPays = STAmount{xrpIssue(), 1}; - return Amounts{ - takerPays, - swapAssetIn( - Amounts{poolIn, poolOut}, - takerPays, - tfee)}; + return Amounts{takerPays, swapAssetIn(Amounts{poolIn, poolOut}, takerPays, tfee)}; } else if (isXRP(poolOut)) { auto const takerGets = STAmount{xrpIssue(), 1}; - return Amounts{ - swapAssetOut( - Amounts{poolIn, poolOut}, - takerGets, - tfee), - takerGets}; + return Amounts{swapAssetOut(Amounts{poolIn, poolOut}, takerGets, tfee), takerGets}; } - auto const takerPays = toAmount( - getIssue(poolIn), Number{1, -10} * poolIn); - return Amounts{ - takerPays, - swapAssetIn( - Amounts{poolIn, poolOut}, takerPays, tfee)}; + auto const takerPays = toAmount(getIssue(poolIn), Number{1, -10} * poolIn); + return Amounts{takerPays, swapAssetIn(Amounts{poolIn, poolOut}, takerPays, tfee)}; }(); BEAST_EXPECT(Quality(tinyOffer) < quality); } @@ -6607,18 +5132,15 @@ private: } catch (std::runtime_error const& e) { - BEAST_EXPECT( - !strcmp(e.what(), "changeSpotPriceQuality failed")); - BEAST_EXPECT( - !features[fixAMMv1_1] && status == FailShouldSucceed); + BEAST_EXPECT(!strcmp(e.what(), "changeSpotPriceQuality failed")); + BEAST_EXPECT(!features[fixAMMv1_1] && status == FailShouldSucceed); } } // Test negative discriminant { // b**2 - 4 * a * c -> 1 * 1 - 4 * 1 * 1 = -3 - auto const res = - solveQuadraticEqSmallest(Number{1}, Number{1}, Number{1}); + auto const res = solveQuadraticEqSmallest(Number{1}, Number{1}, Number{1}); BEAST_EXPECT(!res.has_value()); } } @@ -6918,8 +5440,7 @@ private: }) { testcase(input.testCase); - for (auto const& features : - {all - fixAMMOverflowOffer - fixAMMv1_1 - fixAMMv1_3, all}) + for (auto const& features : {all - fixAMMOverflowOffer - fixAMMv1_1 - fixAMMv1_3, all}) { Env env(*this, features, std::make_unique(&logs)); @@ -6941,21 +5462,13 @@ private: env(pay(bitstamp, trader, usdBIT(100'000))); env.close(); - AMM amm{ - env, - trader, - usdGH(input.poolUsdGH), - usdBIT(input.poolUsdBIT)}; + AMM amm{env, trader, usdGH(input.poolUsdGH), usdBIT(input.poolUsdBIT)}; env.close(); - IOUAmount const preSwapLPTokenBalance = - amm.getLPTokensBalance(); + IOUAmount const preSwapLPTokenBalance = amm.getLPTokensBalance(); env(offer(trader, usdBIT(1), btcGH(input.offer1BtcGH))); - env(offer( - trader, - btcGH(input.offer2BtcGH), - usdGH(input.offer2UsdGH))); + env(offer(trader, btcGH(input.offer2BtcGH), usdGH(input.offer2UsdGH))); env.close(); env(pay(trader, trader, input.sendUsdGH), @@ -6965,37 +5478,28 @@ private: txflags(tfPartialPayment)); env.close(); - auto const failUsdGH = - features[fixAMMv1_1] ? input.failUsdGHr : input.failUsdGH; - auto const failUsdBIT = - features[fixAMMv1_1] ? input.failUsdBITr : input.failUsdBIT; - auto const goodUsdGH = - features[fixAMMv1_1] ? input.goodUsdGHr : input.goodUsdGH; - auto const goodUsdBIT = - features[fixAMMv1_1] ? input.goodUsdBITr : input.goodUsdBIT; - auto const lpTokenBalance = - env.enabled(fixAMMv1_3) && input.lpTokenBalanceAlt + auto const failUsdGH = features[fixAMMv1_1] ? input.failUsdGHr : input.failUsdGH; + auto const failUsdBIT = features[fixAMMv1_1] ? input.failUsdBITr : input.failUsdBIT; + auto const goodUsdGH = features[fixAMMv1_1] ? input.goodUsdGHr : input.goodUsdGH; + auto const goodUsdBIT = features[fixAMMv1_1] ? input.goodUsdBITr : input.goodUsdBIT; + auto const lpTokenBalance = env.enabled(fixAMMv1_3) && input.lpTokenBalanceAlt ? *input.lpTokenBalanceAlt : input.lpTokenBalance; if (!features[fixAMMOverflowOffer]) { - BEAST_EXPECT(amm.expectBalances( - failUsdGH, failUsdBIT, lpTokenBalance)); + BEAST_EXPECT(amm.expectBalances(failUsdGH, failUsdBIT, lpTokenBalance)); } else { - BEAST_EXPECT(amm.expectBalances( - goodUsdGH, goodUsdBIT, lpTokenBalance)); + BEAST_EXPECT(amm.expectBalances(goodUsdGH, goodUsdBIT, lpTokenBalance)); // Invariant: LPToken balance must not change in a // payment or a swap transaction - BEAST_EXPECT( - amm.getLPTokensBalance() == preSwapLPTokenBalance); + BEAST_EXPECT(amm.getLPTokensBalance() == preSwapLPTokenBalance); // Invariant: The square root of (product of the pool // balances) must be at least the LPTokenBalance - Number const sqrtPoolProduct = - root2(goodUsdGH * goodUsdBIT); + Number const sqrtPoolProduct = root2(goodUsdGH * goodUsdBIT); // Include a tiny tolerance for the test cases using // .goodUsdGH{usdGH, uint64_t(35'44113971506987), @@ -7005,9 +5509,7 @@ private: // to 99.99999999999994227040383754105 which gets // internally rounded to 100, due to representation // error. - BEAST_EXPECT( - (sqrtPoolProduct + Number{1, -14} >= - input.lpTokenBalance)); + BEAST_EXPECT((sqrtPoolProduct + Number{1, -14} >= input.lpTokenBalance)); } } } @@ -7023,8 +5525,7 @@ private: STAmount const iouPool{USD, UINT64_C(803040'9987141784), -10}; STAmount const xrpBob{XRP, UINT64_C(1092'878933)}; - STAmount const iouBob{ - USD, UINT64_C(3'988035892323031), -28}; // 3.9...e-13 + STAmount const iouBob{USD, UINT64_C(3'988035892323031), -28}; // 3.9...e-13 testAMM( [&](AMM& amm, Env& env) { @@ -7041,8 +5542,7 @@ private: env.close(); // Assert that AMM is unchanged. - BEAST_EXPECT( - amm.expectBalances(xrpBegin, iouBegin, amm.tokens())); + BEAST_EXPECT(amm.expectBalances(xrpBegin, iouBegin, amm.tokens())); }, {{xrpPool, iouPool}}, 889, @@ -7076,20 +5576,15 @@ private: if (!features[fixAMMv1_1]) { - BEAST_EXPECT(amm.expectBalances( - XRP(200'000), USD(100'000), amm.tokens())); - BEAST_EXPECT(expectOffers( - env, alice, 1, {{Amounts{XRP(1), USD(0.01)}}})); + BEAST_EXPECT(amm.expectBalances(XRP(200'000), USD(100'000), amm.tokens())); + BEAST_EXPECT(expectOffers(env, alice, 1, {{Amounts{XRP(1), USD(0.01)}}})); // Carol's offer is blocked by alice's offer - BEAST_EXPECT(expectOffers( - env, carol, 1, {{Amounts{USD(0.49), XRP(1)}}})); + BEAST_EXPECT(expectOffers(env, carol, 1, {{Amounts{USD(0.49), XRP(1)}}})); } else { - BEAST_EXPECT(amm.expectBalances( - XRPAmount(200'000'980'005), USD(99'999.51), amm.tokens())); - BEAST_EXPECT(expectOffers( - env, alice, 1, {{Amounts{XRP(1), USD(0.01)}}})); + BEAST_EXPECT(amm.expectBalances(XRPAmount(200'000'980'005), USD(99'999.51), amm.tokens())); + BEAST_EXPECT(expectOffers(env, alice, 1, {{Amounts{XRP(1), USD(0.01)}}})); // Carol's offer crosses AMM BEAST_EXPECT(expectOffers(env, carol, 0)); } @@ -7111,8 +5606,7 @@ private: env.close(); // The same result as with the blocking offer - BEAST_EXPECT(amm.expectBalances( - XRPAmount(200'000'980'005), USD(99'999.51), amm.tokens())); + BEAST_EXPECT(amm.expectBalances(XRPAmount(200'000'980'005), USD(99'999.51), amm.tokens())); // Carol's offer crosses AMM BEAST_EXPECT(expectOffers(env, carol, 0)); } @@ -7131,28 +5625,17 @@ private: env.close(); if (!features[fixAMMv1_1]) { - BEAST_EXPECT( - amm.expectBalances(XRP(1'000), USD(500), amm.tokens())); - BEAST_EXPECT(expectOffers( - env, bob, 1, {{Amounts{USD(1), XRPAmount(500)}}})); - BEAST_EXPECT(expectOffers( - env, carol, 1, {{Amounts{XRP(100), USD(55)}}})); + BEAST_EXPECT(amm.expectBalances(XRP(1'000), USD(500), amm.tokens())); + BEAST_EXPECT(expectOffers(env, bob, 1, {{Amounts{USD(1), XRPAmount(500)}}})); + BEAST_EXPECT(expectOffers(env, carol, 1, {{Amounts{XRP(100), USD(55)}}})); } else { BEAST_EXPECT(amm.expectBalances( - XRPAmount(909'090'909), - STAmount{USD, UINT64_C(550'000000055), -9}, - amm.tokens())); - BEAST_EXPECT(expectOffers( - env, - carol, - 1, - {{Amounts{ - XRPAmount{9'090'909}, - STAmount{USD, 4'99999995, -8}}}})); - BEAST_EXPECT(expectOffers( - env, bob, 1, {{Amounts{USD(1), XRPAmount(500)}}})); + XRPAmount(909'090'909), STAmount{USD, UINT64_C(550'000000055), -9}, amm.tokens())); + BEAST_EXPECT( + expectOffers(env, carol, 1, {{Amounts{XRPAmount{9'090'909}, STAmount{USD, 4'99999995, -8}}}})); + BEAST_EXPECT(expectOffers(env, bob, 1, {{Amounts{USD(1), XRPAmount(500)}}})); } } @@ -7165,16 +5648,9 @@ private: AMM amm(env, alice, XRP(1'000), USD(500)); env(offer(carol, XRP(100), USD(55))); env.close(); - BEAST_EXPECT(amm.expectBalances( - XRPAmount(909'090'909), - STAmount{USD, UINT64_C(550'000000055), -9}, - amm.tokens())); - BEAST_EXPECT(expectOffers( - env, - carol, - 1, - {{Amounts{ - XRPAmount{9'090'909}, STAmount{USD, 4'99999995, -8}}}})); + BEAST_EXPECT( + amm.expectBalances(XRPAmount(909'090'909), STAmount{USD, UINT64_C(550'000000055), -9}, amm.tokens())); + BEAST_EXPECT(expectOffers(env, carol, 1, {{Amounts{XRPAmount{9'090'909}, STAmount{USD, 4'99999995, -8}}}})); } } @@ -7188,12 +5664,7 @@ private: { std::string logs; Env env(*this, features, std::make_unique(&logs)); - fund( - env, - gw, - {alice, carol}, - XRP(1'000'000'000), - {USD(1'000'000'000)}); + fund(env, gw, {alice, carol}, XRP(1'000'000'000), {USD(1'000'000'000)}); AMM amm(env, gw, XRP(2), USD(1)); amm.deposit(alice, IOUAmount{1'876123487565916, -15}); amm.deposit(carol, IOUAmount{1'000'000}); @@ -7201,13 +5672,9 @@ private: BEAST_EXPECT(amm.expectLPTokens(alice, IOUAmount{0})); amm.withdrawAll(carol); BEAST_EXPECT(amm.expectLPTokens(carol, IOUAmount{0})); - auto const lpToken = getAccountLines( - env, gw, amm.lptIssue())[jss::lines][0u][jss::balance]; - auto const lpTokenBalance = - amm.ammRpcInfo()[jss::amm][jss::lp_token][jss::value]; - BEAST_EXPECT( - lpToken == "1414.213562373095" && - lpTokenBalance == "1414.213562373"); + auto const lpToken = getAccountLines(env, gw, amm.lptIssue())[jss::lines][0u][jss::balance]; + auto const lpTokenBalance = amm.ammRpcInfo()[jss::amm][jss::lp_token][jss::value]; + BEAST_EXPECT(lpToken == "1414.213562373095" && lpTokenBalance == "1414.213562373"); if (!features[fixAMMv1_1]) { amm.withdrawAll(gw, std::nullopt, ter(tecAMM_BALANCE)); @@ -7226,24 +5693,15 @@ private: { Env env(*this, features); auto const ABC = gw["ABC"]; - fund( - env, - gw, - {alice, carol, bob}, - XRP(1'000), - {USD(1'000'000'000), ABC(1'000'000'000'000)}); + fund(env, gw, {alice, carol, bob}, XRP(1'000), {USD(1'000'000'000), ABC(1'000'000'000'000)}); AMM amm(env, lp, ABC(2'000'000), USD(1)); amm.deposit(alice, IOUAmount{1'876123487565916, -15}); amm.deposit(carol, IOUAmount{1'000'000}); amm.withdrawAll(alice); amm.withdrawAll(carol); - auto const lpToken = getAccountLines( - env, lp, amm.lptIssue())[jss::lines][0u][jss::balance]; - auto const lpTokenBalance = - amm.ammRpcInfo()[jss::amm][jss::lp_token][jss::value]; - BEAST_EXPECT( - lpToken == "1414.213562373095" && - lpTokenBalance == "1414.213562373"); + auto const lpToken = getAccountLines(env, lp, amm.lptIssue())[jss::lines][0u][jss::balance]; + auto const lpTokenBalance = amm.ammRpcInfo()[jss::amm][jss::lp_token][jss::value]; + BEAST_EXPECT(lpToken == "1414.213562373095" && lpTokenBalance == "1414.213562373"); if (!features[fixAMMv1_1]) { amm.withdrawAll(lp, std::nullopt, ter(tecAMM_BALANCE)); @@ -7263,11 +5721,9 @@ private: fund(env, gw, {alice}, XRP(1'000), {USD(1'000)}); AMM amm(env, gw, XRP(10), USD(10)); amm.deposit(alice, 1'000); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), gw); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), gw); BEAST_EXPECT(res && !res.value()); - res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); + res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); BEAST_EXPECT(res && !res.value()); } // IOU/IOU, issuer of both IOU @@ -7276,11 +5732,9 @@ private: fund(env, gw, {alice}, XRP(1'000), {USD(1'000), EUR(1'000)}); AMM amm(env, gw, EUR(10), USD(10)); amm.deposit(alice, 1'000); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), gw); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), gw); BEAST_EXPECT(res && !res.value()); - res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); + res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), alice); BEAST_EXPECT(res && !res.value()); } // IOU/IOU, issuer of one IOU @@ -7292,8 +5746,7 @@ private: fund(env, gw1, {gw}, XRP(1'000), {YAN(1'000)}, Fund::IOUOnly); AMM amm(env, gw1, YAN(10), USD(10)); amm.deposit(gw, 1'000); - auto res = - isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), gw); + auto res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), gw); BEAST_EXPECT(res && !res.value()); res = isOnlyLiquidityProvider(*env.current(), amm.lptIssue(), gw1); BEAST_EXPECT(res && !res.value()); @@ -7342,9 +5795,7 @@ private: // allowed for clawing back from an AMM account. Please notice the // `issuer` subfield represents the account being clawed back, which // is confusing. - auto const error = features[featureSingleAssetVault] - ? ter{tecPSEUDO_ACCOUNT} - : ter{tecAMM_ACCOUNT}; + auto const error = features[featureSingleAssetVault] ? ter{tecPSEUDO_ACCOUNT} : ter{tecAMM_ACCOUNT}; Issue usd(USD.issue().currency, amm.ammAccount()); auto amount = amountFromString(usd, "10"); env(claw(gw, amount), error); @@ -7374,13 +5825,7 @@ private: { Env env(*this, features); testAMMDeposit(env, [&](AMM& amm) { - amm.deposit( - alice, - USD(100), - XRP(100), - std::nullopt, - tfTwoAsset, - ter(tecFROZEN)); + amm.deposit(alice, USD(100), XRP(100), std::nullopt, tfTwoAsset, ter(tecFROZEN)); }); } @@ -7389,13 +5834,7 @@ private: { Env env(*this, features); testAMMDeposit(env, [&](AMM& amm) { - amm.deposit( - alice, - USD(100), - std::nullopt, - std::nullopt, - tfSingleAsset, - ter(tecFROZEN)); + amm.deposit(alice, USD(100), std::nullopt, std::nullopt, tfSingleAsset, ter(tecFROZEN)); }); } @@ -7406,13 +5845,7 @@ private: // when feature AMMClawback is enabled. Env env(*this, features); testAMMDeposit(env, [&](AMM& amm) { - amm.deposit( - alice, - XRP(100), - std::nullopt, - std::nullopt, - tfSingleAsset, - ter(tecFROZEN)); + amm.deposit(alice, XRP(100), std::nullopt, std::nullopt, tfSingleAsset, ter(tecFROZEN)); }); } else @@ -7422,13 +5855,7 @@ private: // when feature AMMClawback is not enabled. Env env(*this, features); testAMMDeposit(env, [&](AMM& amm) { - amm.deposit( - alice, - XRP(100), - std::nullopt, - std::nullopt, - tfSingleAsset, - ter(tesSUCCESS)); + amm.deposit(alice, XRP(100), std::nullopt, std::nullopt, tfSingleAsset, ter(tesSUCCESS)); }); } } @@ -7439,13 +5866,11 @@ private: testcase("Fix Reserve Check On Withdrawal"); using namespace jtx; - auto const err = features[fixAMMv1_2] ? ter(tecINSUFFICIENT_RESERVE) - : ter(tesSUCCESS); + auto const err = features[fixAMMv1_2] ? ter(tecINSUFFICIENT_RESERVE) : ter(tesSUCCESS); auto test = [&](auto&& cb) { Env env(*this, features); - auto const starting_xrp = - reserve(env, 2) + env.current()->fees().base * 5; + auto const starting_xrp = reserve(env, 2) + env.current()->fees().base * 5; env.fund(starting_xrp, gw); env.fund(starting_xrp, alice); env.trust(USD(2'000), alice); @@ -7462,22 +5887,13 @@ private: // Equal withdraw with a limit test([&](AMM& amm) { - amm.withdraw(WithdrawArg{ - .account = alice, - .asset1Out = EUR(0.1), - .asset2Out = USD(0.1), - .err = err}); - amm.withdraw(WithdrawArg{ - .account = alice, - .asset1Out = USD(0.1), - .asset2Out = EUR(0.1), - .err = err}); + amm.withdraw(WithdrawArg{.account = alice, .asset1Out = EUR(0.1), .asset2Out = USD(0.1), .err = err}); + amm.withdraw(WithdrawArg{.account = alice, .asset1Out = USD(0.1), .asset2Out = EUR(0.1), .err = err}); }); // Single withdraw test([&](AMM& amm) { - amm.withdraw(WithdrawArg{ - .account = alice, .asset1Out = EUR(0.1), .err = err}); + amm.withdraw(WithdrawArg{.account = alice, .asset1Out = EUR(0.1), .err = err}); amm.withdraw(WithdrawArg{.account = alice, .asset1Out = USD(0.1)}); }); } @@ -7502,13 +5918,9 @@ private: auto const keylet = keylet::amm(amount.issue(), amount2.issue()); for (int i = 0; i < 256; ++i) { - AccountID const accountId = - xrpl::pseudoAccountAddress(*env.current(), keylet.key); + AccountID const accountId = xrpl::pseudoAccountAddress(*env.current(), keylet.key); - env(pay(env.master.id(), accountId, XRP(1000)), - seq(autofill), - fee(autofill), - sig(autofill)); + env(pay(env.master.id(), accountId, XRP(1000)), seq(autofill), fee(autofill), sig(autofill)); } AMM ammAlice( @@ -7516,15 +5928,11 @@ private: alice, amount, amount2, - features[featureSingleAssetVault] ? ter{terADDRESS_COLLISION} - : ter{tecDUPLICATE}); + features[featureSingleAssetVault] ? ter{terADDRESS_COLLISION} : ter{tecDUPLICATE}); }; - testCase( - "tecDUPLICATE", testable_amendments() - featureSingleAssetVault); - testCase( - "terADDRESS_COLLISION", - testable_amendments() | featureSingleAssetVault); + testCase("tecDUPLICATE", testable_amendments() - featureSingleAssetVault); + testCase("terADDRESS_COLLISION", testable_amendments() | featureSingleAssetVault); } void @@ -7548,20 +5956,16 @@ private: AMM amm(env, gw, xrpBalance, xpmBalance, CreateArg{.tfee = tfee_}); // AMM LPToken balance required to replicate single deposit failure - STAmount lptAMMBalance{ - amm.lptIssue(), UINT64_C(3'234'987'266'485968), -6}; - auto const burn = - IOUAmount{amm.getLPTokensBalance() - lptAMMBalance}; + STAmount lptAMMBalance{amm.lptIssue(), UINT64_C(3'234'987'266'485968), -6}; + auto const burn = IOUAmount{amm.getLPTokensBalance() - lptAMMBalance}; // burn tokens to get to the required AMM state env(amm.bid(BidArg{.account = gw, .bidMin = burn, .bidMax = burn})); cb(amm, env); }; test( [&](AMM& amm, Env& env) { - auto const err = env.enabled(fixAMMv1_3) ? ter(tesSUCCESS) - : ter(tecUNFUNDED_AMM); - amm.deposit(DepositArg{ - .account = alice, .asset1In = amount, .err = err}); + auto const err = env.enabled(fixAMMv1_3) ? ter(tesSUCCESS) : ter(tecUNFUNDED_AMM); + amm.deposit(DepositArg{.account = alice, .asset1In = amount, .err = err}); }, tfee); test( @@ -7569,8 +5973,7 @@ private: auto const [amount, amount2, lptAMM] = amm.balances(XRP, XPM); auto const withdraw = STAmount{XPM, 1, -5}; amm.withdraw(WithdrawArg{.asset1Out = STAmount{XPM, 1, -5}}); - auto const [amount_, amount2_, lptAMM_] = - amm.balances(XRP, XPM); + auto const [amount_, amount2_, lptAMM_] = amm.balances(XRP, XPM); if (!env.enabled(fixAMMv1_3)) BEAST_EXPECT((amount2 - amount2_) > withdraw); else @@ -7580,17 +5983,12 @@ private: } void - invariant( - jtx::AMM& amm, - jtx::Env& env, - std::string const& msg, - bool shouldFail) + invariant(jtx::AMM& amm, jtx::Env& env, std::string const& msg, bool shouldFail) { auto const [amount, amount2, lptBalance] = amm.balances(GBP, EUR); NumberMantissaScaleGuard sg(MantissaRange::small); - NumberRoundModeGuard g( - env.enabled(fixAMMv1_3) ? Number::upward : Number::getround()); + NumberRoundModeGuard g(env.enabled(fixAMMv1_3) ? Number::upward : Number::getround()); auto const res = root2(amount * amount2); if (shouldFail) @@ -7616,23 +6014,11 @@ private: { testAMM( [&](AMM& ammAlice, Env& env) { - fund( - env, - gw, - {bob}, - XRP(10'000'000), - {GBP(100'000), EUR(100'000)}, - Fund::Acct); + fund(env, gw, {bob}, XRP(10'000'000), {GBP(100'000), EUR(100'000)}, Fund::Acct); env.close(); - ammAlice.deposit( - DepositArg{.account = bob, .asset1In = deposit}); - invariant( - ammAlice, - env, - "dep1", - deposit == STAmount{EUR, 1, -3} && - !env.enabled(fixAMMv1_3)); + ammAlice.deposit(DepositArg{.account = bob, .asset1In = deposit}); + invariant(ammAlice, env, "dep1", deposit == STAmount{EUR, 1, -3} && !env.enabled(fixAMMv1_3)); }, {{GBP(30'000), EUR(30'000)}}, 0, @@ -7643,24 +6029,13 @@ private: // Two-asset proportional deposit (1:1 pool ratio) testAMM( [&](AMM& ammAlice, Env& env) { - fund( - env, - gw, - {bob}, - XRP(10'000'000), - {GBP(100'000), EUR(100'000)}, - Fund::Acct); + fund(env, gw, {bob}, XRP(10'000'000), {GBP(100'000), EUR(100'000)}, Fund::Acct); env.close(); - STAmount const depositEuro{ - EUR, UINT64_C(10'1234567890123456), -16}; - STAmount const depositGBP{ - GBP, UINT64_C(10'1234567890123456), -16}; + STAmount const depositEuro{EUR, UINT64_C(10'1234567890123456), -16}; + STAmount const depositGBP{GBP, UINT64_C(10'1234567890123456), -16}; - ammAlice.deposit(DepositArg{ - .account = bob, - .asset1In = depositEuro, - .asset2In = depositGBP}); + ammAlice.deposit(DepositArg{.account = bob, .asset1In = depositEuro, .asset2In = depositGBP}); invariant(ammAlice, env, "dep2", false); }, {{GBP(30'000), EUR(30'000)}}, @@ -7673,27 +6048,14 @@ private: { testAMM( [&](AMM& ammAlice, Env& env) { - fund( - env, - gw, - {bob}, - XRP(10'000'000), - {GBP(100'000), EUR(100'000)}, - Fund::Acct); + fund(env, gw, {bob}, XRP(10'000'000), {GBP(100'000), EUR(100'000)}, Fund::Acct); env.close(); STAmount const depositEuro{EUR, 1, exponent}; STAmount const depositGBP{GBP, 1, exponent}; - ammAlice.deposit(DepositArg{ - .account = bob, - .asset1In = depositEuro, - .asset2In = depositGBP}); - invariant( - ammAlice, - env, - "dep3", - exponent != -3 && !env.enabled(fixAMMv1_3)); + ammAlice.deposit(DepositArg{.account = bob, .asset1In = depositEuro, .asset2In = depositGBP}); + invariant(ammAlice, env, "dep3", exponent != -3 && !env.enabled(fixAMMv1_3)); }, {{GBP(10'000), EUR(30'000)}}, 0, @@ -7704,18 +6066,10 @@ private: // tfLPToken deposit testAMM( [&](AMM& ammAlice, Env& env) { - fund( - env, - gw, - {bob}, - XRP(10'000'000), - {GBP(100'000), EUR(100'000)}, - Fund::Acct); + fund(env, gw, {bob}, XRP(10'000'000), {GBP(100'000), EUR(100'000)}, Fund::Acct); env.close(); - ammAlice.deposit(DepositArg{ - .account = bob, - .tokens = IOUAmount{10'1234567890123456, -16}}); + ammAlice.deposit(DepositArg{.account = bob, .tokens = IOUAmount{10'1234567890123456, -16}}); invariant(ammAlice, env, "dep4", false); }, {{GBP(7'000), EUR(30'000)}}, @@ -7736,19 +6090,10 @@ private: { testAMM( [&](AMM& ammAlice, Env& env) { - fund( - env, - gw, - {bob}, - XRP(10'000'000), - {GBP(100'000), EUR(1'000'000)}, - Fund::Acct); + fund(env, gw, {bob}, XRP(10'000'000), {GBP(100'000), EUR(1'000'000)}, Fund::Acct); env.close(); - ammAlice.deposit(DepositArg{ - .account = bob, - .tokens = tokens, - .asset1In = STAmount{EUR, 1, 6}}); + ammAlice.deposit(DepositArg{.account = bob, .tokens = tokens, .asset1In = STAmount{EUR, 1, 6}}); invariant(ammAlice, env, "dep5", false); }, {{GBP(7'000), EUR(30'000)}}, @@ -7761,17 +6106,10 @@ private: // 1'000 GBP with EP not to exceed 5 (GBP/TokensOut) testAMM( [&](AMM& ammAlice, Env& env) { - fund( - env, - gw, - {bob}, - XRP(10'000'000), - {GBP(100'000), EUR(100'000)}, - Fund::Acct); + fund(env, gw, {bob}, XRP(10'000'000), {GBP(100'000), EUR(100'000)}, Fund::Acct); env.close(); - ammAlice.deposit( - bob, GBP(1'000), std::nullopt, STAmount{GBP, 5}); + ammAlice.deposit(bob, GBP(1'000), std::nullopt, STAmount{GBP, 5}); invariant(ammAlice, env, "dep6", false); }, {{GBP(30'000), EUR(30'000)}}, @@ -7801,8 +6139,7 @@ private: // tfWithdrawAll mode testAMM( [&](AMM& ammAlice, Env& env) { - ammAlice.withdraw( - WithdrawArg{.account = alice, .flags = tfWithdrawAll}); + ammAlice.withdraw(WithdrawArg{.account = alice, .flags = tfWithdrawAll}); invariant(ammAlice, env, "with2", false); }, {{GBP(7'000), EUR(30'000)}}, @@ -7832,10 +6169,8 @@ private: // errors testAMM( [&](AMM& ammAlice, Env& env) { - ammAlice.withdraw(WithdrawArg{ - .account = alice, - .asset1Out = STAmount{GBP, 1'234}, - .flags = tfSingleAsset}); + ammAlice.withdraw( + WithdrawArg{.account = alice, .asset1Out = STAmount{GBP, 1'234}, .flags = tfSingleAsset}); invariant(ammAlice, env, "with4", false); }, {{GBP(7'000), EUR(30'000)}}, @@ -7846,22 +6181,13 @@ private: // tfOneAssetWithdrawAll mode testAMM( [&](AMM& ammAlice, Env& env) { - fund( - env, - gw, - {bob}, - XRP(10'000'000), - {GBP(100'000), EUR(100'000)}, - Fund::Acct); + fund(env, gw, {bob}, XRP(10'000'000), {GBP(100'000), EUR(100'000)}, Fund::Acct); env.close(); - ammAlice.deposit(DepositArg{ - .account = bob, .asset1In = STAmount{GBP, 3'456}}); + ammAlice.deposit(DepositArg{.account = bob, .asset1In = STAmount{GBP, 3'456}}); - ammAlice.withdraw(WithdrawArg{ - .account = bob, - .asset1Out = STAmount{GBP, 1'000}, - .flags = tfOneAssetWithdrawAll}); + ammAlice.withdraw( + WithdrawArg{.account = bob, .asset1Out = STAmount{GBP, 1'000}, .flags = tfOneAssetWithdrawAll}); invariant(ammAlice, env, "with5", false); }, {{GBP(7'000), EUR(30'000)}}, @@ -7873,10 +6199,7 @@ private: testAMM( [&](AMM& ammAlice, Env& env) { ammAlice.withdraw(WithdrawArg{ - .account = alice, - .tokens = 1'000, - .asset1Out = STAmount{GBP, 100}, - .flags = tfOneAssetLPToken}); + .account = alice, .tokens = 1'000, .asset1Out = STAmount{GBP, 100}, .flags = tfOneAssetLPToken}); invariant(ammAlice, env, "with6", false); }, {{GBP(7'000), EUR(30'000)}}, @@ -7888,10 +6211,7 @@ private: testAMM( [&](AMM& ammAlice, Env& env) { ammAlice.withdraw(WithdrawArg{ - .account = alice, - .asset1Out = STAmount{GBP, 100}, - .maxEP = IOUAmount{2}, - .flags = tfLimitLPToken}); + .account = alice, .asset1Out = STAmount{GBP, 100}, .maxEP = IOUAmount{2}, .flags = tfLimitLPToken}); invariant(ammAlice, env, "with7", true); }, {{GBP(7'000), EUR(30'000)}}, @@ -7921,8 +6241,7 @@ private: testBasicPaymentEngine(all); testBasicPaymentEngine(all - fixAMMv1_1 - fixAMMv1_3); testBasicPaymentEngine(all - fixReducedOffersV2); - testBasicPaymentEngine( - all - fixAMMv1_1 - fixAMMv1_3 - fixReducedOffersV2); + testBasicPaymentEngine(all - fixAMMv1_1 - fixAMMv1_3 - fixReducedOffersV2); testAMMTokens(); testAmendment(); testFlags(); @@ -7961,8 +6280,7 @@ private: testAMMDepositWithFrozenAssets(all); testAMMDepositWithFrozenAssets(all - featureAMMClawback); testAMMDepositWithFrozenAssets(all - fixAMMv1_1 - featureAMMClawback); - testAMMDepositWithFrozenAssets( - all - fixAMMv1_1 - fixAMMv1_3 - featureAMMClawback); + testAMMDepositWithFrozenAssets(all - fixAMMv1_1 - fixAMMv1_3 - featureAMMClawback); testFixReserveCheckOnWithdrawal(all); testFixReserveCheckOnWithdrawal(all - fixAMMv1_2); testDepositAndWithdrawRounding(all); diff --git a/src/test/app/AccountDelete_test.cpp b/src/test/app/AccountDelete_test.cpp index 44d484ac7a..7c9a593cae 100644 --- a/src/test/app/AccountDelete_test.cpp +++ b/src/test/app/AccountDelete_test.cpp @@ -17,8 +17,7 @@ private: verifyDeliveredAmount(jtx::Env& env, STAmount const& amount) { // Get the hash for the most recent transaction. - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; // Verify DeliveredAmount and delivered_amount metadata are correct. // We can't use env.meta() here, because meta() doesn't include @@ -82,9 +81,7 @@ public: env(acctdelete(alice, becky), fee(drops(-1)), ter(temBAD_FEE)); // Invalid flags. - env(acctdelete(alice, becky), - txflags(tfImmediateOrCancel), - ter(temINVALID_FLAG)); + env(acctdelete(alice, becky), txflags(tfImmediateOrCancel), ter(temINVALID_FLAG)); // Account deletion has a high fee. Make sure the fee requirement // behaves as we expect. @@ -92,9 +89,7 @@ public: env(acctdelete(alice, becky), ter(telINSUF_FEE_P)); // Try a fee one drop less than the required amount. - env(acctdelete(alice, becky), - fee(acctDelFee - drops(1)), - ter(telINSUF_FEE_P)); + env(acctdelete(alice, becky), fee(acctDelFee - drops(1)), ter(telINSUF_FEE_P)); // alice's account is created too recently to be deleted. env(acctdelete(alice, becky), fee(acctDelFee), ter(tecTOO_SOON)); @@ -145,9 +140,7 @@ public: BEAST_EXPECT(!env.closed()->exists(keylet::ownerDir(alice.id()))); // Verify that alice's XRP, minus the fee, was transferred to becky. - BEAST_EXPECT( - env.balance(becky) == - aliceOldBalance + beckyOldBalance - acctDelFee); + BEAST_EXPECT(env.balance(becky) == aliceOldBalance + beckyOldBalance - acctDelFee); } // Attempt to delete becky's account but get stopped by the trust line. @@ -179,12 +172,9 @@ public: // pre-authorization, offer, ticket, and signer list exist. BEAST_EXPECT(env.closed()->exists(keylet::account(carol.id()))); BEAST_EXPECT(env.closed()->exists(keylet::ownerDir(carol.id()))); - BEAST_EXPECT(env.closed()->exists( - keylet::depositPreauth(carol.id(), becky.id()))); - BEAST_EXPECT( - env.closed()->exists(keylet::offer(carol.id(), carolOfferSeq))); - BEAST_EXPECT(env.closed()->exists( - keylet::ticket(carol.id(), carolTicketSeq))); + BEAST_EXPECT(env.closed()->exists(keylet::depositPreauth(carol.id(), becky.id()))); + BEAST_EXPECT(env.closed()->exists(keylet::offer(carol.id(), carolOfferSeq))); + BEAST_EXPECT(env.closed()->exists(keylet::ticket(carol.id(), carolTicketSeq))); BEAST_EXPECT(env.closed()->exists(keylet::signers(carol.id()))); // Delete carol's account even with stuff in her directory. Show @@ -196,18 +186,13 @@ public: // Verify that Carol's account, directory, and other stuff are gone. BEAST_EXPECT(!env.closed()->exists(keylet::account(carol.id()))); BEAST_EXPECT(!env.closed()->exists(keylet::ownerDir(carol.id()))); - BEAST_EXPECT(!env.closed()->exists( - keylet::depositPreauth(carol.id(), becky.id()))); - BEAST_EXPECT(!env.closed()->exists( - keylet::offer(carol.id(), carolOfferSeq))); - BEAST_EXPECT(!env.closed()->exists( - keylet::ticket(carol.id(), carolTicketSeq))); + BEAST_EXPECT(!env.closed()->exists(keylet::depositPreauth(carol.id(), becky.id()))); + BEAST_EXPECT(!env.closed()->exists(keylet::offer(carol.id(), carolOfferSeq))); + BEAST_EXPECT(!env.closed()->exists(keylet::ticket(carol.id(), carolTicketSeq))); BEAST_EXPECT(!env.closed()->exists(keylet::signers(carol.id()))); // Verify that Carol's XRP, minus the fee, was transferred to becky. - BEAST_EXPECT( - env.balance(becky) == - carolOldBalance + beckyOldBalance - acctDelFee); + BEAST_EXPECT(env.balance(becky) == carolOldBalance + beckyOldBalance - acctDelFee); // Since becky received an influx of XRP, her lsfPasswordSpent bit // is cleared and she can change her regular key for free again. @@ -328,8 +313,7 @@ public: // Now cancel the escrow, but create a payment channel between // alice and becky. - bool const withTokenEscrow = - env.current()->rules().enabled(featureTokenEscrow); + bool const withTokenEscrow = env.current()->rules().enabled(featureTokenEscrow); if (withTokenEscrow) { Account const gw1("gw1"); @@ -351,9 +335,7 @@ public: incLgrSeqForAccDel(env, gw1); - env(acctdelete(gw1, becky), - fee(acctDelFee), - ter(tecHAS_OBLIGATIONS)); + env(acctdelete(gw1, becky), fee(acctDelFee), ter(tecHAS_OBLIGATIONS)); env.close(); env(escrow::cancel(becky, carol, escrowSeq)); @@ -363,11 +345,9 @@ public: env(escrow::cancel(becky, alice, escrowSeq)); env.close(); - Keylet const alicePayChanKey{ - keylet::payChan(alice, becky, env.seq(alice))}; + Keylet const alicePayChanKey{keylet::payChan(alice, becky, env.seq(alice))}; - env(payChanCreate( - alice, becky, XRP(57), 4s, env.now() + 2s, alice.pk())); + env(payChanCreate(alice, becky, XRP(57), 4s, env.now() + 2s, alice.pk())); env.close(); // With the PayChannel in place becky and alice should not be @@ -381,9 +361,7 @@ public: // in her directory. // Lambda to close a PayChannel. - auto payChanClose = [](jtx::Account const& account, - Keylet const& payChanKeylet, - PublicKey const& pk) { + auto payChanClose = [](jtx::Account const& account, Keylet const& payChanKeylet, PublicKey const& pk) { Json::Value jv; jv[jss::TransactionType] = jss::PaymentChannelClaim; jv[jss::Flags] = tfClose; @@ -483,8 +461,7 @@ public: // alice's offers. for (std::uint32_t i{0}; i < offerCount; ++i) - BEAST_EXPECT( - closed->exists(keylet::offer(alice.id(), offerSeq0 + i))); + BEAST_EXPECT(closed->exists(keylet::offer(alice.id(), offerSeq0 + i))); } // Delete alice's account. Should fail because she has too many @@ -514,13 +491,11 @@ public: // alice's former directory nodes. for (std::uint32_t i{0}; i < ((offerCount / 32) + 1); ++i) - BEAST_EXPECT( - !closed->exists(keylet::page(aliceOwnerDirKey, i))); + BEAST_EXPECT(!closed->exists(keylet::page(aliceOwnerDirKey, i))); // alice's former offers. for (std::uint32_t i{0}; i < offerCount; ++i) - BEAST_EXPECT( - !closed->exists(keylet::offer(alice.id(), offerSeq0 + i))); + BEAST_EXPECT(!closed->exists(keylet::offer(alice.id(), offerSeq0 + i))); } } @@ -600,9 +575,7 @@ public: // // The balance of env.master should not change. auto const masterBalance{env.balance(env.master)}; - env(acctdelete(alice, env.master), - fee(acctDelFee), - ter(terINSUF_FEE_B)); + env(acctdelete(alice, env.master), fee(acctDelFee), ter(terINSUF_FEE_B)); env.close(); { std::shared_ptr const closed{env.closed()}; @@ -647,8 +620,7 @@ public: BEAST_EXPECT(closed->exists(keylet::account(bob.id()))); for (std::uint32_t i = 0; i < 250; ++i) { - BEAST_EXPECT( - closed->exists(keylet::ticket(bob.id(), ticketSeq + i))); + BEAST_EXPECT(closed->exists(keylet::ticket(bob.id(), ticketSeq + i))); } } @@ -667,8 +639,7 @@ public: BEAST_EXPECT(!closed->exists(keylet::account(bob.id()))); for (std::uint32_t i = 0; i < 250; ++i) { - BEAST_EXPECT( - !closed->exists(keylet::ticket(bob.id(), ticketSeq + i))); + BEAST_EXPECT(!closed->exists(keylet::ticket(bob.id(), ticketSeq + i))); } } } @@ -732,8 +703,7 @@ public: testDestinationDepositAuthCredentials() { { - testcase( - "Destination Constraints with DepositPreauth and Credentials"); + testcase("Destination Constraints with DepositPreauth and Credentials"); using namespace test::jtx; @@ -753,8 +723,7 @@ public: env.close(); // get credentials index - auto const jv = - credentials::ledgerEntry(env, becky, carol, credType); + auto const jv = credentials::ledgerEntry(env, becky, carol, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); // Close enough ledgers to be able to delete becky's account. @@ -763,10 +732,7 @@ public: auto const acctDelFee{drops(env.current()->fees().increment)}; // becky use credentials but they aren't accepted - env(acctdelete(becky, alice), - credentials::ids({credIdx}), - fee(acctDelFee), - ter(tecBAD_CREDENTIALS)); + env(acctdelete(becky, alice), credentials::ids({credIdx}), fee(acctDelFee), ter(tecBAD_CREDENTIALS)); env.close(); { @@ -778,10 +744,7 @@ public: } // Fail, credentials still not accepted - env(acctdelete(becky, alice), - credentials::ids({credIdx}), - fee(acctDelFee), - ter(tecBAD_CREDENTIALS)); + env(acctdelete(becky, alice), credentials::ids({credIdx}), fee(acctDelFee), ter(tecBAD_CREDENTIALS)); env.close(); // becky accept the credentials @@ -789,16 +752,10 @@ public: env.close(); // Fail, credentials doesn’t belong to carol - env(acctdelete(carol, alice), - credentials::ids({credIdx}), - fee(acctDelFee), - ter(tecBAD_CREDENTIALS)); + env(acctdelete(carol, alice), credentials::ids({credIdx}), fee(acctDelFee), ter(tecBAD_CREDENTIALS)); // Fail, no depositPreauth for provided credentials - env(acctdelete(becky, alice), - credentials::ids({credIdx}), - fee(acctDelFee), - ter(tecNO_PERMISSION)); + env(acctdelete(becky, alice), credentials::ids({credIdx}), fee(acctDelFee), ter(tecNO_PERMISSION)); env.close(); // alice create DepositPreauth Object @@ -807,38 +764,28 @@ public: // becky attempts to delete her account, but alice won't take her // XRP, so the delete is blocked. - env(acctdelete(becky, alice), - fee(acctDelFee), - ter(tecNO_PERMISSION)); + env(acctdelete(becky, alice), fee(acctDelFee), ter(tecNO_PERMISSION)); // becky use empty credentials and can't delete account - env(acctdelete(becky, alice), - fee(acctDelFee), - credentials::ids({}), - ter(temMALFORMED)); + env(acctdelete(becky, alice), fee(acctDelFee), credentials::ids({}), ter(temMALFORMED)); // becky use bad credentials and can't delete account env(acctdelete(becky, alice), - credentials::ids( - {"48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6E" - "A288BE4"}), + credentials::ids({"48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6E" + "A288BE4"}), fee(acctDelFee), ter(tecBAD_CREDENTIALS)); env.close(); // becky use credentials and can delete account - env(acctdelete(becky, alice), - credentials::ids({credIdx}), - fee(acctDelFee)); + env(acctdelete(becky, alice), credentials::ids({credIdx}), fee(acctDelFee)); env.close(); { // check that credential object deleted too - auto const jNoCred = - credentials::ledgerEntry(env, becky, carol, credType); + auto const jNoCred = credentials::ledgerEntry(env, becky, carol, credType); BEAST_EXPECT( - jNoCred.isObject() && jNoCred.isMember(jss::result) && - jNoCred[jss::result].isMember(jss::error) && + jNoCred.isObject() && jNoCred.isMember(jss::result) && jNoCred[jss::result].isMember(jss::error) && jNoCred[jss::result][jss::error] == "entryNotFound"); } @@ -849,24 +796,18 @@ public: env(credentials::accept(daria, carol, credType)); env.close(); std::string const credDaria = - credentials::ledgerEntry( - env, daria, carol, credType)[jss::result][jss::index] - .asString(); + credentials::ledgerEntry(env, daria, carol, credType)[jss::result][jss::index].asString(); // daria use valid credentials, which aren't required and can // delete her account - env(acctdelete(daria, carol), - credentials::ids({credDaria}), - fee(acctDelFee)); + env(acctdelete(daria, carol), credentials::ids({credDaria}), fee(acctDelFee)); env.close(); // check that credential object deleted too - auto const jNoCred = - credentials::ledgerEntry(env, daria, carol, credType); + auto const jNoCred = credentials::ledgerEntry(env, daria, carol, credType); BEAST_EXPECT( - jNoCred.isObject() && jNoCred.isMember(jss::result) && - jNoCred[jss::result].isMember(jss::error) && + jNoCred.isObject() && jNoCred.isMember(jss::result) && jNoCred[jss::result].isMember(jss::error) && jNoCred[jss::result][jss::error] == "entryNotFound"); } @@ -882,9 +823,7 @@ public: env(credentials::accept(eaton, carol, credType)); env.close(); std::string const credEaton = - credentials::ledgerEntry( - env, eaton, carol, credType)[jss::result][jss::index] - .asString(); + credentials::ledgerEntry(env, eaton, carol, credType)[jss::result][jss::index].asString(); // fred make pre-authorization through authorized account env(fset(fred, asfDepositAuth)); @@ -898,18 +837,14 @@ public: // eaton use valid credentials, but he already authorized // through "Authorized" field. - env(acctdelete(eaton, fred), - credentials::ids({credEaton}), - fee(acctDelFee)); + env(acctdelete(eaton, fred), credentials::ids({credEaton}), fee(acctDelFee)); env.close(); // check that credential object deleted too - auto const jNoCred = - credentials::ledgerEntry(env, eaton, carol, credType); + auto const jNoCred = credentials::ledgerEntry(env, eaton, carol, credType); BEAST_EXPECT( - jNoCred.isObject() && jNoCred.isMember(jss::result) && - jNoCred[jss::result].isMember(jss::error) && + jNoCred.isObject() && jNoCred.isMember(jss::result) && jNoCred[jss::result].isMember(jss::error) && jNoCred[jss::result][jss::error] == "entryNotFound"); } @@ -921,37 +856,27 @@ public: env.close(); auto jv = credentials::create(john, carol, credType); - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() + - 20; + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count() + 20; jv[sfExpiration.jsonName] = t; env(jv); env.close(); env(credentials::accept(john, carol, credType)); env.close(); jv = credentials::ledgerEntry(env, john, carol, credType); - std::string const credIdx = - jv[jss::result][jss::index].asString(); + std::string const credIdx = jv[jss::result][jss::index].asString(); incLgrSeqForAccDel(env, john); // credentials are expired // john use credentials but can't delete account - env(acctdelete(john, alice), - credentials::ids({credIdx}), - fee(acctDelFee), - ter(tecEXPIRED)); + env(acctdelete(john, alice), credentials::ids({credIdx}), fee(acctDelFee), ter(tecEXPIRED)); env.close(); { // check that expired credential object deleted - auto jv = - credentials::ledgerEntry(env, john, carol, credType); + auto jv = credentials::ledgerEntry(env, john, carol, credType); BEAST_EXPECT( - jv.isObject() && jv.isMember(jss::result) && - jv[jss::result].isMember(jss::error) && + jv.isObject() && jv.isMember(jss::result) && jv[jss::result].isMember(jss::error) && jv[jss::result][jss::error] == "entryNotFound"); } } @@ -988,10 +913,7 @@ public: env(deposit::auth(alice, becky)); env.close(); - env(acctdelete(becky, alice), - credentials::ids({credIdx}), - fee(acctDelFee), - ter(temDISABLED)); + env(acctdelete(becky, alice), credentials::ids({credIdx}), fee(acctDelFee), ter(temDISABLED)); env.close(); } } @@ -1021,8 +943,7 @@ public: env.close(); // get credentials index - auto const jv = - credentials::ledgerEntry(env, becky, carol, credType); + auto const jv = credentials::ledgerEntry(env, becky, carol, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); // Close enough ledgers to be able to delete carol's account. @@ -1034,11 +955,9 @@ public: { // check that credential object deleted too BEAST_EXPECT(!env.le(credIdx)); - auto const jv = - credentials::ledgerEntry(env, becky, carol, credType); + auto const jv = credentials::ledgerEntry(env, becky, carol, credType); BEAST_EXPECT( - jv.isObject() && jv.isMember(jss::result) && - jv[jss::result].isMember(jss::error) && + jv.isObject() && jv.isMember(jss::result) && jv[jss::result].isMember(jss::error) && jv[jss::result][jss::error] == "entryNotFound"); } } @@ -1065,8 +984,7 @@ public: env.close(); // get credentials index - auto const jv = - credentials::ledgerEntry(env, becky, carol, credType); + auto const jv = credentials::ledgerEntry(env, becky, carol, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); // Close enough ledgers to be able to delete carol's account. @@ -1078,11 +996,9 @@ public: { // check that credential object deleted too BEAST_EXPECT(!env.le(credIdx)); - auto const jv = - credentials::ledgerEntry(env, becky, carol, credType); + auto const jv = credentials::ledgerEntry(env, becky, carol, credType); BEAST_EXPECT( - jv.isObject() && jv.isMember(jss::result) && - jv[jss::result].isMember(jss::error) && + jv.isObject() && jv.isMember(jss::result) && jv[jss::result].isMember(jss::error) && jv[jss::result][jss::error] == "entryNotFound"); } } diff --git a/src/test/app/AccountTxPaging_test.cpp b/src/test/app/AccountTxPaging_test.cpp index 5efe307812..27078f0578 100644 --- a/src/test/app/AccountTxPaging_test.cpp +++ b/src/test/app/AccountTxPaging_test.cpp @@ -13,9 +13,7 @@ class AccountTxPaging_test : public beast::unit_test::suite bool checkTransaction(Json::Value const& tx, int sequence, int ledger) { - return ( - tx[jss::tx][jss::Sequence].asInt() == sequence && - tx[jss::tx][jss::ledger_index].asInt() == ledger); + return (tx[jss::tx][jss::Sequence].asInt() == sequence && tx[jss::tx][jss::ledger_index].asInt() == ledger); } auto diff --git a/src/test/app/AmendmentTable_test.cpp b/src/test/app/AmendmentTable_test.cpp index a320bccfe8..1e4b096927 100644 --- a/src/test/app/AmendmentTable_test.cpp +++ b/src/test/app/AmendmentTable_test.cpp @@ -34,9 +34,7 @@ private: } static Section - makeSection( - std::string const& name, - std::vector const& amendments) + makeSection(std::string const& name, std::vector const& amendments) { Section section(name); for (auto const& a : amendments) @@ -62,17 +60,13 @@ private: makeConfig() { auto cfg = test::jtx::envconfig(); - cfg->section(SECTION_AMENDMENTS) = - makeSection(SECTION_AMENDMENTS, enabled_); - cfg->section(SECTION_VETO_AMENDMENTS) = - makeSection(SECTION_VETO_AMENDMENTS, vetoed_); + cfg->section(SECTION_AMENDMENTS) = makeSection(SECTION_AMENDMENTS, enabled_); + cfg->section(SECTION_VETO_AMENDMENTS) = makeSection(SECTION_VETO_AMENDMENTS, vetoed_); return cfg; } static std::vector - makeFeatureInfo( - std::vector const& amendments, - VoteBehavior voteBehavior) + makeFeatureInfo(std::vector const& amendments, VoteBehavior voteBehavior) { std::vector result; result.reserve(amendments.size()); @@ -92,8 +86,7 @@ private: static std::vector makeDefaultYes(uint256 const amendment) { - std::vector result{ - {to_string(amendment), amendment, VoteBehavior::DefaultYes}}; + std::vector result{{to_string(amendment), amendment, VoteBehavior::DefaultYes}}; return result; } @@ -120,10 +113,7 @@ private: template static void - combine_arg( - std::vector& dest, - std::vector const& src, - Args const&... args) + combine_arg(std::vector& dest, std::vector const& src, Args const&... args) { assert(dest.capacity() >= dest.size() + src.size()); std::copy(src.begin(), src.end(), std::back_inserter(dest)); @@ -151,14 +141,11 @@ private: // Enabled amendments are typically a subset of supported amendments. // Vetoed amendments should be supported but not enabled. // Unsupported amendments may be added to the AmendmentTable. - std::vector const - yes_{"g", "i", "k", "m", "o", "q", "r", "s", "t", "u"}; - std::vector const - enabled_{"b", "d", "f", "h", "j", "l", "n", "p"}; + std::vector const yes_{"g", "i", "k", "m", "o", "q", "r", "s", "t", "u"}; + std::vector const enabled_{"b", "d", "f", "h", "j", "l", "n", "p"}; std::vector const vetoed_{"a", "c", "e"}; std::vector const obsolete_{"0", "1", "2"}; - std::vector const allSupported_{ - combine(yes_, enabled_, vetoed_, obsolete_)}; + std::vector const allSupported_{combine(yes_, enabled_, vetoed_, obsolete_)}; std::vector const unsupported_{"v", "w", "x"}; std::vector const unsupportedMajority_{"y", "z"}; @@ -180,8 +167,7 @@ public: Section const& enabled, Section const& vetoed) { - return make_AmendmentTable( - app, majorityTime, supported, enabled, vetoed, journal_); + return make_AmendmentTable(app, majorityTime, supported, enabled, vetoed, journal_); } std::unique_ptr @@ -198,22 +184,16 @@ public: std::unique_ptr makeTable(test::jtx::Env& env, std::chrono::seconds majorityTime) { - static std::vector const supported = - combine( - makeDefaultYes(yes_), - // Use non-intuitive default votes for "enabled_" and "vetoed_" - // so that when the tests later explicitly enable or veto them, - // we can be certain that they are not simply going by their - // default vote setting. - makeDefaultNo(enabled_), - makeDefaultYes(vetoed_), - makeObsolete(obsolete_)); - return makeTable( - env.app(), - majorityTime, - supported, - makeSection(enabled_), - makeSection(vetoed_)); + static std::vector const supported = combine( + makeDefaultYes(yes_), + // Use non-intuitive default votes for "enabled_" and "vetoed_" + // so that when the tests later explicitly enable or veto them, + // we can be certain that they are not simply going by their + // default vote setting. + makeDefaultNo(enabled_), + makeDefaultYes(vetoed_), + makeObsolete(obsolete_)); + return makeTable(env.app(), majorityTime, supported, makeSection(enabled_), makeSection(vetoed_)); } void @@ -270,16 +250,14 @@ public: // Verify that unsupportedID is not in table. uint256 const unsupportedID = amendmentId(unsupported_[0]); { - Json::Value const unsupp = - table->getJson(unsupportedID, true)[to_string(unsupportedID)]; + Json::Value const unsupp = table->getJson(unsupportedID, true)[to_string(unsupportedID)]; BEAST_EXPECT(unsupp.size() == 0); } // After vetoing unsupportedID verify that it is in table. table->veto(unsupportedID); { - Json::Value const unsupp = - table->getJson(unsupportedID, true)[to_string(unsupportedID)]; + Json::Value const unsupp = table->getJson(unsupportedID, true)[to_string(unsupportedID)]; BEAST_EXPECT(unsupp[jss::vetoed].asBool()); } } @@ -305,8 +283,7 @@ public: } catch (std::exception const& e) { - BEAST_EXPECT( - e.what() == "Invalid entry '" + id + "' in [Test]"); + BEAST_EXPECT(e.what() == "Invalid entry '" + id + "' in [Test]"); } } @@ -322,9 +299,7 @@ public: } catch (std::exception const& e) { - BEAST_EXPECT( - e.what() == - "Invalid entry '" + id + " Test Name' in [Test]"); + BEAST_EXPECT(e.what() == "Invalid entry '" + id + " Test Name' in [Test]"); } } @@ -343,8 +318,7 @@ public: } catch (std::exception const& e) { - BEAST_EXPECT( - e.what() == "Invalid entry '" + sid + " Name' in [Test]"); + BEAST_EXPECT(e.what() == "Invalid entry '" + sid + " Name' in [Test]"); } } @@ -363,8 +337,7 @@ public: } catch (std::exception const& e) { - BEAST_EXPECT( - e.what() == "Invalid entry '" + sid + " Name' in [Test]"); + BEAST_EXPECT(e.what() == "Invalid entry '" + sid + " Name' in [Test]"); } } @@ -384,8 +357,7 @@ public: } catch (std::exception const& e) { - BEAST_EXPECT( - e.what() == "Invalid entry '" + sid + " Name' in [Test]"); + BEAST_EXPECT(e.what() == "Invalid entry '" + sid + " Name' in [Test]"); } } } @@ -416,9 +388,7 @@ public: bool const enabled = table->isEnabled(supportedID); bool const found = allEnabled.find(supportedID) != allEnabled.end(); BEAST_EXPECTS( - enabled == found, - a + (enabled ? " enabled " : " disabled ") + - (found ? " found" : " not found")); + enabled == found, a + (enabled ? " enabled " : " disabled ") + (found ? " found" : " not found")); } // All supported and unVetoed amendments should be returned as desired. @@ -444,9 +414,7 @@ public: BEAST_EXPECT(table->unVeto(unvetoedID)); std::vector const desired = table->getDesired(); - BEAST_EXPECT( - std::find(desired.begin(), desired.end(), unvetoedID) != - desired.end()); + BEAST_EXPECT(std::find(desired.begin(), desired.end(), unvetoedID) != desired.end()); } // Veto all supported amendments. Now desired should be empty. @@ -475,8 +443,7 @@ public: trustedValidators.reserve(num); for (int i = 0; i < num; ++i) { - auto const& back = - ret.emplace_back(randomKeyPair(KeyType::secp256k1)); + auto const& back = ret.emplace_back(randomKeyPair(KeyType::secp256k1)); trustedValidators.insert(back.first); } table->trustChanged(trustedValidators); @@ -534,14 +501,9 @@ public: } auto v = std::make_shared( - xrpl::NetClock::time_point{}, - pub, - sec, - calcNodeID(pub), - [&field](STValidation& v) { + xrpl::NetClock::time_point{}, pub, sec, calcNodeID(pub), [&field](STValidation& v) { if (!field.empty()) - v.setFieldV256( - sfAmendments, STVector256(sfAmendments, field)); + v.setFieldV256(sfAmendments, STVector256(sfAmendments, field)); v.setFieldU32(sfLedgerSequence, 6180339); }); @@ -550,8 +512,7 @@ public: ourVotes = table.doValidation(enabled); - auto actions = - table.doVoting(rules, roundTime, enabled, majority, validations); + auto actions = table.doVoting(rules, roundTime, enabled, majority, validations); for (auto const& [hash, action] : actions) { // This code assumes other validators do as we do @@ -570,15 +531,13 @@ public: case tfGotMajority: if (majority.find(hash) != majority.end()) - Throw( - "got majority while having majority"); + Throw("got majority while having majority"); majority[hash] = roundTime; break; case tfLostMajority: if (majority.find(hash) == majority.end()) - Throw( - "lost majority without majority"); + Throw("lost majority without majority"); majority.erase(hash); break; @@ -597,8 +556,7 @@ public: auto const testAmendment = amendmentId("TestAmendment"); test::jtx::Env env{*this, feat}; - auto table = - makeTable(env, weeks(2), emptyYes_, emptySection_, emptySection_); + auto table = makeTable(env, weeks(2), emptyYes_, emptySection_, emptySection_); auto const validators = makeValidators(10, table); @@ -607,30 +565,20 @@ public: std::set enabled; majorityAmendments_t majority; - doRound( - env.current()->rules(), - *table, - weeks{1}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{1}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(ourVotes.empty()); BEAST_EXPECT(enabled.empty()); BEAST_EXPECT(majority.empty()); uint256 const unsupportedID = amendmentId(unsupported_[0]); { - Json::Value const unsupp = - table->getJson(unsupportedID, false)[to_string(unsupportedID)]; + Json::Value const unsupp = table->getJson(unsupportedID, false)[to_string(unsupportedID)]; BEAST_EXPECT(unsupp.size() == 0); } table->veto(unsupportedID); { - Json::Value const unsupp = - table->getJson(unsupportedID, false)[to_string(unsupportedID)]; + Json::Value const unsupp = table->getJson(unsupportedID, false)[to_string(unsupportedID)]; BEAST_EXPECT(!unsupp[jss::vetoed].asBool()); } @@ -638,15 +586,7 @@ public: votes.emplace_back(testAmendment, validators.size()); - doRound( - env.current()->rules(), - *table, - weeks{2}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{2}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(ourVotes.empty()); BEAST_EXPECT(enabled.empty()); @@ -654,15 +594,7 @@ public: // Note that the simulation code assumes others behave as we do, // so the amendment won't get enabled - doRound( - env.current()->rules(), - *table, - weeks{5}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{5}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(ourVotes.empty()); BEAST_EXPECT(enabled.empty()); } @@ -676,12 +608,7 @@ public: auto const testAmendment = amendmentId("vetoedAmendment"); test::jtx::Env env{*this, feat}; - auto table = makeTable( - env, - weeks(2), - emptyYes_, - emptySection_, - makeSection(testAmendment)); + auto table = makeTable(env, weeks(2), emptyYes_, emptySection_, makeSection(testAmendment)); auto const validators = makeValidators(10, table); @@ -690,44 +617,20 @@ public: std::set enabled; majorityAmendments_t majority; - doRound( - env.current()->rules(), - *table, - weeks{1}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{1}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(ourVotes.empty()); BEAST_EXPECT(enabled.empty()); BEAST_EXPECT(majority.empty()); votes.emplace_back(testAmendment, validators.size()); - doRound( - env.current()->rules(), - *table, - weeks{2}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{2}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(ourVotes.empty()); BEAST_EXPECT(enabled.empty()); majority[testAmendment] = hourTime(weeks{1}); - doRound( - env.current()->rules(), - *table, - weeks{5}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{5}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(ourVotes.empty()); BEAST_EXPECT(enabled.empty()); } @@ -739,8 +642,7 @@ public: testcase("voteEnable"); test::jtx::Env env{*this, feat}; - auto table = makeTable( - env, weeks(2), makeDefaultYes(yes_), emptySection_, emptySection_); + auto table = makeTable(env, weeks(2), makeDefaultYes(yes_), emptySection_, emptySection_); auto const validators = makeValidators(10, table); @@ -750,15 +652,7 @@ public: majorityAmendments_t majority; // Week 1: We should vote for all known amendments not enabled - doRound( - env.current()->rules(), - *table, - weeks{1}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{1}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(ourVotes.size() == yes_.size()); BEAST_EXPECT(enabled.empty()); for (auto const& i : yes_) @@ -769,15 +663,7 @@ public: votes.emplace_back(amendmentId(i), validators.size()); // Week 2: We should recognize a majority - doRound( - env.current()->rules(), - *table, - weeks{2}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{2}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(ourVotes.size() == yes_.size()); BEAST_EXPECT(enabled.empty()); @@ -785,27 +671,11 @@ public: BEAST_EXPECT(majority[amendmentId(i)] == hourTime(weeks{2})); // Week 5: We should enable the amendment - doRound( - env.current()->rules(), - *table, - weeks{5}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{5}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(enabled.size() == yes_.size()); // Week 6: We should remove it from our votes and from having a majority - doRound( - env.current()->rules(), - *table, - weeks{6}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{6}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(enabled.size() == yes_.size()); BEAST_EXPECT(ourVotes.empty()); for (auto const& i : yes_) @@ -820,12 +690,7 @@ public: auto const testAmendment = amendmentId("detectMajority"); test::jtx::Env env{*this, feat}; - auto table = makeTable( - env, - weeks(2), - makeDefaultYes(testAmendment), - emptySection_, - emptySection_); + auto table = makeTable(env, weeks(2), makeDefaultYes(testAmendment), emptySection_, emptySection_); auto const validators = makeValidators(16, table); @@ -840,15 +705,7 @@ public: if ((i > 0) && (i < 17)) votes.emplace_back(testAmendment, i); - doRound( - env.current()->rules(), - *table, - weeks{i}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{i}, validators, votes, ourVotes, enabled, majority); if (i < 13) // 13 => 13/16 = 0.8125 => > 80% { @@ -890,12 +747,7 @@ public: auto const testAmendment = amendmentId("lostMajority"); test::jtx::Env env{*this, feat}; - auto table = makeTable( - env, - weeks(8), - makeDefaultYes(testAmendment), - emptySection_, - emptySection_); + auto table = makeTable(env, weeks(8), makeDefaultYes(testAmendment), emptySection_, emptySection_); auto const validators = makeValidators(16, table); @@ -909,15 +761,7 @@ public: votes.emplace_back(testAmendment, validators.size()); - doRound( - env.current()->rules(), - *table, - weeks{1}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{1}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(enabled.empty()); BEAST_EXPECT(!majority.empty()); @@ -931,15 +775,7 @@ public: // Gradually reduce support votes.emplace_back(testAmendment, validators.size() - i); - doRound( - env.current()->rules(), - *table, - weeks{i + 1}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{i + 1}, validators, votes, ourVotes, enabled, majority); if (i < 4) // 16 - 3 = 13 => 13/16 = 0.8125 => > 80% { // 16 - 4 = 12 => 12/16 = 0.75 => < 80% @@ -966,15 +802,9 @@ public: auto const testAmendment = amendmentId("changedUNL"); test::jtx::Env env{*this, feat}; - auto table = makeTable( - env, - weeks(8), - makeDefaultYes(testAmendment), - emptySection_, - emptySection_); + auto table = makeTable(env, weeks(8), makeDefaultYes(testAmendment), emptySection_, emptySection_); - std::vector> validators = - makeValidators(10, table); + std::vector> validators = makeValidators(10, table); std::set enabled; majorityAmendments_t majority; @@ -986,15 +816,7 @@ public: votes.emplace_back(testAmendment, validators.size() - 2); - doRound( - env.current()->rules(), - *table, - weeks{1}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{1}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(enabled.empty()); BEAST_EXPECT(majority.empty()); @@ -1005,22 +827,18 @@ public: // A lambda that updates the AmendmentTable with the latest // trusted validators. - auto callTrustChanged = - [](std::vector> const& validators, - std::unique_ptr const& table) { - // We need a hash_set to pass to trustChanged. - hash_set trustedValidators; - trustedValidators.reserve(validators.size()); - std::for_each( - validators.begin(), - validators.end(), - [&trustedValidators](auto const& val) { - trustedValidators.insert(val.first); - }); + auto callTrustChanged = [](std::vector> const& validators, + std::unique_ptr const& table) { + // We need a hash_set to pass to trustChanged. + hash_set trustedValidators; + trustedValidators.reserve(validators.size()); + std::for_each(validators.begin(), validators.end(), [&trustedValidators](auto const& val) { + trustedValidators.insert(val.first); + }); - // Tell the AmendmentTable that the UNL changed. - table->trustChanged(trustedValidators); - }; + // Tell the AmendmentTable that the UNL changed. + table->trustChanged(trustedValidators); + }; // Tell the table that there's been a change in trusted validators. callTrustChanged(validators, table); @@ -1032,15 +850,7 @@ public: votes.emplace_back(testAmendment, validators.size() - 2); - doRound( - env.current()->rules(), - *table, - weeks{2}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{2}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(enabled.empty()); BEAST_EXPECT(!majority.empty()); @@ -1048,8 +858,7 @@ public: { // One of the validators goes flaky and doesn't send validations // (without the UNL changing) so the amendment loses majority. - std::pair const savedValidator = - validators.front(); + std::pair const savedValidator = validators.front(); validators.erase(validators.begin()); std::vector> votes; @@ -1057,15 +866,7 @@ public: votes.emplace_back(testAmendment, validators.size() - 2); - doRound( - env.current()->rules(), - *table, - weeks{3}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{3}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(enabled.empty()); BEAST_EXPECT(majority.empty()); @@ -1076,15 +877,7 @@ public: votes.front().second = validators.size() - 2; - doRound( - env.current()->rules(), - *table, - weeks{4}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{4}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(enabled.empty()); BEAST_EXPECT(!majority.empty()); @@ -1098,15 +891,7 @@ public: votes.front().second = validators.size() - 2; - doRound( - env.current()->rules(), - *table, - weeks{5}, - validators, - votes, - ourVotes, - enabled, - majority); + doRound(env.current()->rules(), *table, weeks{5}, validators, votes, ourVotes, enabled, majority); BEAST_EXPECT(enabled.empty()); BEAST_EXPECT(majority.empty()); @@ -1131,18 +916,12 @@ public: { test::jtx::Env env{*this, feat}; auto const testAmendment = amendmentId("validatorFlapping"); - auto table = makeTable( - env, - weeks(1), - makeDefaultYes(testAmendment), - emptySection_, - emptySection_); + auto table = makeTable(env, weeks(1), makeDefaultYes(testAmendment), emptySection_, emptySection_); // Make two lists of validators, one with a missing validator, to // make it easy to simulate validator flapping. auto const allValidators = makeValidators(11, table); - decltype(allValidators) const mostValidators( - allValidators.begin() + 1, allValidators.end()); + decltype(allValidators) const mostValidators(allValidators.begin() + 1, allValidators.end()); BEAST_EXPECT(allValidators.size() == mostValidators.size() + 1); std::set enabled; @@ -1184,9 +963,7 @@ public: // no flapping. Otherwise we should only have majority // if allValidators vote -- which means there are no // missing validators. - bool const expectMajority = (delay <= 24) - ? true - : &thisHoursValidators == &allValidators; + bool const expectMajority = (delay <= 24) ? true : &thisHoursValidators == &allValidators; BEAST_EXPECT(majority.empty() != expectMajority); } else @@ -1217,9 +994,7 @@ public: std::set enabled; std::for_each( - unsupported_.begin(), - unsupported_.end(), - [&enabled](auto const& s) { enabled.insert(amendmentId(s)); }); + unsupported_.begin(), unsupported_.end(), [&enabled](auto const& s) { enabled.insert(amendmentId(s)); }); majorityAmendments_t majority; table->doValidatedLedger(1, enabled, majority); @@ -1227,18 +1002,14 @@ public: BEAST_EXPECT(!table->firstUnsupportedExpected()); NetClock::duration t{1000s}; - std::for_each( - unsupportedMajority_.begin(), - unsupportedMajority_.end(), - [&majority, &t](auto const& s) { - majority[amendmentId(s)] = NetClock::time_point{--t}; - }); + std::for_each(unsupportedMajority_.begin(), unsupportedMajority_.end(), [&majority, &t](auto const& s) { + majority[amendmentId(s)] = NetClock::time_point{--t}; + }); table->doValidatedLedger(1, enabled, majority); BEAST_EXPECT(table->hasUnsupportedEnabled()); BEAST_EXPECT( - table->firstUnsupportedExpected() && - *table->firstUnsupportedExpected() == NetClock::time_point{t} + w); + table->firstUnsupportedExpected() && *table->firstUnsupportedExpected() == NetClock::time_point{t} + w); // Make sure the table knows when it needs an update. BEAST_EXPECT(!table->needValidatedLedger(256)); diff --git a/src/test/app/Batch_test.cpp b/src/test/app/Batch_test.cpp index 67b0933ae2..035a1f8a6f 100644 --- a/src/test/app/Batch_test.cpp +++ b/src/test/app/Batch_test.cpp @@ -57,27 +57,19 @@ class Batch_test : public beast::unit_test::suite } void - validateInnerTxn( - jtx::Env& env, - std::string const& batchID, - TestLedgerData const& ledgerResult) + validateInnerTxn(jtx::Env& env, std::string const& batchID, TestLedgerData const& ledgerResult) { Json::Value const jrr = env.rpc("tx", ledgerResult.txHash)[jss::result]; BEAST_EXPECT(jrr[sfTransactionType.jsonName] == ledgerResult.txType); - BEAST_EXPECT( - jrr[jss::meta][sfTransactionResult.jsonName] == - ledgerResult.result); + BEAST_EXPECT(jrr[jss::meta][sfTransactionResult.jsonName] == ledgerResult.result); BEAST_EXPECT(jrr[jss::meta][sfParentBatchID.jsonName] == batchID); } void - validateClosedLedger( - jtx::Env& env, - std::vector const& ledgerResults) + validateClosedLedger(jtx::Env& env, std::vector const& ledgerResults) { auto const jrr = getLastLedger(env); - auto const transactions = - jrr[jss::result][jss::ledger][jss::transactions]; + auto const transactions = jrr[jss::result][jss::ledger][jss::transactions]; BEAST_EXPECT(transactions.size() == ledgerResults.size()); for (TestLedgerData const& ledgerResult : ledgerResults) { @@ -85,10 +77,8 @@ class Batch_test : public beast::unit_test::suite BEAST_EXPECT(txn[jss::hash].asString() == ledgerResult.txHash); BEAST_EXPECT(txn.isMember(jss::metaData)); Json::Value const meta = txn[jss::metaData]; - BEAST_EXPECT( - txn[sfTransactionType.jsonName] == ledgerResult.txType); - BEAST_EXPECT( - meta[sfTransactionResult.jsonName] == ledgerResult.result); + BEAST_EXPECT(txn[sfTransactionType.jsonName] == ledgerResult.txType); + BEAST_EXPECT(meta[sfTransactionResult.jsonName] == ledgerResult.result); if (ledgerResult.batchID) validateInnerTxn(env, *ledgerResult.batchID, ledgerResult); } @@ -155,10 +145,8 @@ class Batch_test : public beast::unit_test::suite for (bool const withBatch : {true, false}) { - testcase << "enabled: Batch " - << (withBatch ? "enabled" : "disabled") - << ", Inner Sig Fix: " - << (withInnerSigFix ? "enabled" : "disabled"); + testcase << "enabled: Batch " << (withBatch ? "enabled" : "disabled") + << ", Inner Sig Fix: " << (withInnerSigFix ? "enabled" : "disabled"); auto const amend = withBatch ? features : features - featureBatch; @@ -174,8 +162,7 @@ class Batch_test : public beast::unit_test::suite { auto const seq = env.seq(alice); auto const batchFee = batch::calcBatchFee(env, 0, 2); - auto const txResult = - withBatch ? ter(tesSUCCESS) : ter(temDISABLED); + auto const txResult = withBatch ? ter(tesSUCCESS) : ter(temDISABLED); env(batch::outer(alice, seq, batchFee, tfAllOrNothing), batch::inner(pay(alice, bob, XRP(1)), seq + 1), batch::inner(pay(alice, bob, XRP(1)), seq + 2), @@ -188,11 +175,8 @@ class Batch_test : public beast::unit_test::suite // temINVALID_FLAG. If the feature is enabled, the transaction fails // early in checkValidity() { - auto const txResult = - withBatch ? ter(telENV_RPC_FAILED) : ter(temINVALID_FLAG); - env(pay(alice, bob, XRP(1)), - txflags(tfInnerBatchTxn), - txResult); + auto const txResult = withBatch ? ter(telENV_RPC_FAILED) : ter(temINVALID_FLAG); + env(pay(alice, bob, XRP(1)), txflags(tfInnerBatchTxn), txResult); env.close(); } @@ -221,8 +205,7 @@ class Batch_test : public beast::unit_test::suite // temBAD_FEE: preflight1 { - env(batch::outer(alice, env.seq(alice), XRP(-1), tfAllOrNothing), - ter(temBAD_FEE)); + env(batch::outer(alice, env.seq(alice), XRP(-1), tfAllOrNothing), ter(temBAD_FEE)); env.close(); } @@ -231,8 +214,7 @@ class Batch_test : public beast::unit_test::suite { auto const seq = env.seq(alice); auto const batchFee = batch::calcBatchFee(env, 0, 0); - env(batch::outer(alice, seq, batchFee, tfInnerBatchTxn), - ter(telENV_RPC_FAILED)); + env(batch::outer(alice, seq, batchFee, tfInnerBatchTxn), ter(telENV_RPC_FAILED)); env.close(); } @@ -240,8 +222,7 @@ class Batch_test : public beast::unit_test::suite { auto const seq = env.seq(alice); auto const batchFee = batch::calcBatchFee(env, 0, 0); - env(batch::outer(alice, seq, batchFee, tfDisallowXRP), - ter(temINVALID_FLAG)); + env(batch::outer(alice, seq, batchFee, tfDisallowXRP), ter(temINVALID_FLAG)); env.close(); } @@ -259,8 +240,7 @@ class Batch_test : public beast::unit_test::suite { auto const seq = env.seq(alice); auto const batchFee = batch::calcBatchFee(env, 0, 0); - env(batch::outer(alice, seq, batchFee, tfAllOrNothing), - ter(temARRAY_EMPTY)); + env(batch::outer(alice, seq, batchFee, tfAllOrNothing), ter(temARRAY_EMPTY)); env.close(); } @@ -312,8 +292,7 @@ class Batch_test : public beast::unit_test::suite auto const seq = env.seq(alice); auto const batchFee = batch::calcBatchFee(env, 0, 2); env(batch::outer(alice, seq, batchFee, tfAllOrNothing), - batch::inner( - batch::outer(alice, seq, batchFee, tfAllOrNothing), seq), + batch::inner(batch::outer(alice, seq, batchFee, tfAllOrNothing), seq), batch::inner(pay(alice, bob, XRP(1)), seq + 2), ter(telENV_RPC_FAILED)); env.close(); @@ -354,12 +333,9 @@ class Batch_test : public beast::unit_test::suite auto tx1 = pay(alice, bob, XRP(1)); tx1[sfSigners.jsonName] = Json::arrayValue; tx1[sfSigners.jsonName][0U][sfSigner.jsonName] = Json::objectValue; - tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] = - alice.human(); - tx1[sfSigners.jsonName][0U][sfSigner.jsonName] - [sfSigningPubKey.jsonName] = strHex(alice.pk()); - tx1[sfSigners.jsonName][0U][sfSigner.jsonName] - [sfTxnSignature.jsonName] = "DEADBEEF"; + tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfAccount.jsonName] = alice.human(); + tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfSigningPubKey.jsonName] = strHex(alice.pk()); + tx1[sfSigners.jsonName][0U][sfSigner.jsonName][sfTxnSignature.jsonName] = "DEADBEEF"; env(batch::outer(alice, seq, batchFee, tfAllOrNothing), batch::inner(tx1, seq + 1), batch::inner(pay(alice, bob, XRP(1)), seq + 2), @@ -510,17 +486,7 @@ class Batch_test : public beast::unit_test::suite env(batch::outer(alice, seq, batchFee, tfAllOrNothing), batch::inner(pay(alice, bob, XRP(10)), seq + 1), batch::inner(pay(alice, bob, XRP(5)), seq + 2), - batch::sig( - bob, - carol, - alice, - bob, - carol, - alice, - bob, - carol, - alice, - alice), + batch::sig(bob, carol, alice, bob, carol, alice, bob, carol, alice, alice), ter(telENV_RPC_FAILED)); env.close(); } @@ -585,15 +551,11 @@ class Batch_test : public beast::unit_test::suite batch::inner(pay(bob, alice, XRP(5)), bobSeq)); Serializer msg; - serializeBatch( - msg, tfAllOrNothing, jt.stx->getBatchTransactionIDs()); + serializeBatch(msg, tfAllOrNothing, jt.stx->getBatchTransactionIDs()); auto const sig = xrpl::sign(bob.pk(), bob.sk(), msg.slice()); - jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName] - [sfAccount.jsonName] = bob.human(); - jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName] - [sfSigningPubKey.jsonName] = strHex(alice.pk()); - jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName] - [sfTxnSignature.jsonName] = + jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfAccount.jsonName] = bob.human(); + jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfSigningPubKey.jsonName] = strHex(alice.pk()); + jt.jv[sfBatchSigners.jsonName][0u][sfBatchSigner.jsonName][sfTxnSignature.jsonName] = strHex(Slice{sig.data(), sig.size()}); env(jt.jv, ter(temBAD_SIGNATURE)); @@ -1338,16 +1300,15 @@ class Batch_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob, gw); env.close(); - auto const ammCreate = - [&alice](STAmount const& amount, STAmount const& amount2) { - Json::Value jv; - jv[jss::Account] = alice.human(); - jv[jss::Amount] = amount.getJson(JsonOptions::none); - jv[jss::Amount2] = amount2.getJson(JsonOptions::none); - jv[jss::TradingFee] = 0; - jv[jss::TransactionType] = jss::AMMCreate; - return jv; - }; + auto const ammCreate = [&alice](STAmount const& amount, STAmount const& amount2) { + Json::Value jv; + jv[jss::Account] = alice.human(); + jv[jss::Amount] = amount.getJson(JsonOptions::none); + jv[jss::Amount2] = amount2.getJson(JsonOptions::none); + jv[jss::TradingFee] = 0; + jv[jss::TransactionType] = jss::AMMCreate; + return jv; + }; auto const batchFee = batch::calcBatchFee(env, 0, 2); auto const seq = env.seq(alice); @@ -1415,14 +1376,11 @@ class Batch_test : public beast::unit_test::suite batch::inner(pay(alice, bob, XRP(1)), aliceSeq), batch::inner(pay(alice, bob, XRP(1)), aliceSeq)); - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) { - auto const result = - xrpl::apply(env.app(), view, *jt.stx, tapNONE, j); - BEAST_EXPECT( - !result.applied && result.ter == temARRAY_TOO_LARGE); - return result.applied; - }); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { + auto const result = xrpl::apply(env.app(), view, *jt.stx, tapNONE, j); + BEAST_EXPECT(!result.applied && result.ter == temARRAY_TOO_LARGE); + return result.applied; + }); } // telENV_RPC_FAILED: Batch: signers array exceeds 8 entries. @@ -1461,14 +1419,11 @@ class Batch_test : public beast::unit_test::suite batch::inner(pay(alice, bob, XRP(5)), aliceSeq + 2), batch::sig(bob, bob, bob, bob, bob, bob, bob, bob, bob, bob)); - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) { - auto const result = - xrpl::apply(env.app(), view, *jt.stx, tapNONE, j); - BEAST_EXPECT( - !result.applied && result.ter == temARRAY_TOO_LARGE); - return result.applied; - }); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { + auto const result = xrpl::apply(env.app(), view, *jt.stx, tapNONE, j); + BEAST_EXPECT(!result.applied && result.ter == temARRAY_TOO_LARGE); + return result.applied; + }); } } @@ -1799,27 +1754,9 @@ class Batch_test : public beast::unit_test::suite env, tesSUCCESS, batch::outer(alice, seq, batchFee, tfOnlyOne), - batch::inner( - offer( - alice, - alice["USD"](100), - XRP(100), - tfImmediateOrCancel), - seq + 1), - batch::inner( - offer( - alice, - alice["USD"](100), - XRP(100), - tfImmediateOrCancel), - seq + 2), - batch::inner( - offer( - alice, - alice["USD"](100), - XRP(100), - tfImmediateOrCancel), - seq + 3), + batch::inner(offer(alice, alice["USD"](100), XRP(100), tfImmediateOrCancel), seq + 1), + batch::inner(offer(alice, alice["USD"](100), XRP(100), tfImmediateOrCancel), seq + 2), + batch::inner(offer(alice, alice["USD"](100), XRP(100), tfImmediateOrCancel), seq + 3), batch::inner(pay(alice, bob, XRP(100)), seq + 4), batch::inner(pay(alice, carol, XRP(100)), seq + 5), batch::inner(pay(alice, dave, XRP(100)), seq + 6)); @@ -2038,13 +1975,7 @@ class Batch_test : public beast::unit_test::suite batch::outer(alice, seq, batchFee, tfUntilFailure), batch::inner(pay(alice, bob, XRP(100)), seq + 1), batch::inner(pay(alice, carol, XRP(100)), seq + 2), - batch::inner( - offer( - alice, - alice["USD"](100), - XRP(100), - tfImmediateOrCancel), - seq + 3), + batch::inner(offer(alice, alice["USD"](100), XRP(100), tfImmediateOrCancel), seq + 3), batch::inner(pay(alice, dave, XRP(100)), seq + 4)); env.close(); @@ -2232,13 +2163,7 @@ class Batch_test : public beast::unit_test::suite batch::outer(alice, seq, batchFee, tfIndependent), batch::inner(pay(alice, bob, XRP(100)), seq + 1), batch::inner(pay(alice, carol, XRP(100)), seq + 2), - batch::inner( - offer( - alice, - alice["USD"](100), - XRP(100), - tfImmediateOrCancel), - seq + 3)); + batch::inner(offer(alice, alice["USD"](100), XRP(100), tfImmediateOrCancel), seq + 3)); env.close(); std::vector testCases = { @@ -2262,9 +2187,8 @@ class Batch_test : public beast::unit_test::suite std::string const testName = [&]() { std::stringstream ss; - ss << "inner submit rpc: batch " - << (withBatch ? "enabled" : "disabled") << ", inner sig fix: " - << (withInnerSigFix ? "enabled" : "disabled") << ": "; + ss << "inner submit rpc: batch " << (withBatch ? "enabled" : "disabled") + << ", inner sig fix: " << (withInnerSigFix ? "enabled" : "disabled") << ": "; return ss.str(); }(); @@ -2283,45 +2207,37 @@ class Batch_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob); env.close(); - auto submitAndValidate = - [&](std::string caseName, - Slice const& slice, - int line, - std::optional expectedEnabled = std::nullopt, - std::optional expectedDisabled = std::nullopt, - bool expectInvalidFlag = false) { - testcase << testName << caseName - << (expectInvalidFlag - ? " - Expected to reach tx engine!" - : ""); - auto const jrr = env.rpc("submit", strHex(slice))[jss::result]; - auto const expected = withBatch - ? expectedEnabled.value_or( - "fails local checks: Malformed: Invalid inner batch " - "transaction.") - : expectedDisabled.value_or( - "fails local checks: Empty SigningPubKey."); - if (expectInvalidFlag) - { - expect( - jrr[jss::status] == "success" && - jrr[jss::engine_result] == "temINVALID_FLAG", - pretty(jrr), - __FILE__, - line); - } - else - { - expect( - jrr[jss::status] == "error" && - jrr[jss::error] == "invalidTransaction" && - jrr[jss::error_exception] == expected, - pretty(jrr), - __FILE__, - line); - } - env.close(); - }; + auto submitAndValidate = [&](std::string caseName, + Slice const& slice, + int line, + std::optional expectedEnabled = std::nullopt, + std::optional expectedDisabled = std::nullopt, + bool expectInvalidFlag = false) { + testcase << testName << caseName << (expectInvalidFlag ? " - Expected to reach tx engine!" : ""); + auto const jrr = env.rpc("submit", strHex(slice))[jss::result]; + auto const expected = withBatch ? expectedEnabled.value_or( + "fails local checks: Malformed: Invalid inner batch " + "transaction.") + : expectedDisabled.value_or("fails local checks: Empty SigningPubKey."); + if (expectInvalidFlag) + { + expect( + jrr[jss::status] == "success" && jrr[jss::engine_result] == "temINVALID_FLAG", + pretty(jrr), + __FILE__, + line); + } + else + { + expect( + jrr[jss::status] == "error" && jrr[jss::error] == "invalidTransaction" && + jrr[jss::error_exception] == expected, + pretty(jrr), + __FILE__, + line); + } + env.close(); + }; // Invalid RPC Submission: TxnSignature // + has `TxnSignature` field @@ -2349,11 +2265,7 @@ class Batch_test : public beast::unit_test::suite Serializer s; parsed.object->add(s); submitAndValidate( - "SigningPubKey set", - s.slice(), - __LINE__, - std::nullopt, - "fails local checks: Invalid signature."); + "SigningPubKey set", s.slice(), __LINE__, std::nullopt, "fails local checks: Invalid signature."); } // Invalid RPC Submission: Signers @@ -2368,29 +2280,18 @@ class Batch_test : public beast::unit_test::suite Serializer s; parsed.object->add(s); submitAndValidate( - "Signers set", - s.slice(), - __LINE__, - std::nullopt, - "fails local checks: Invalid Signers array size."); + "Signers set", s.slice(), __LINE__, std::nullopt, "fails local checks: Invalid Signers array size."); } { // Fully signed inner batch transaction - auto const txn = - batch::inner(pay(alice, bob, XRP(1)), env.seq(alice)); + auto const txn = batch::inner(pay(alice, bob, XRP(1)), env.seq(alice)); auto const jt = env.jt(txn.getTxn()); STParsedJSONObject parsed("test", jt.jv); Serializer s; parsed.object->add(s); - submitAndValidate( - "Fully signed", - s.slice(), - __LINE__, - std::nullopt, - std::nullopt, - !withBatch); + submitAndValidate("Fully signed", s.slice(), __LINE__, std::nullopt, std::nullopt, !withBatch); } // Invalid RPC Submission: tfInnerBatchTxn @@ -2418,15 +2319,13 @@ class Batch_test : public beast::unit_test::suite // - has no `Signers` field // + has `tfInnerBatchTxn` flag { - STTx amendTx( - ttAMENDMENT, [seq = env.closed()->header().seq + 1](auto& obj) { - obj.setAccountID(sfAccount, AccountID()); - obj.setFieldH256(sfAmendment, fixBatchInnerSigs); - obj.setFieldU32(sfLedgerSequence, seq); - obj.setFieldU32(sfFlags, tfInnerBatchTxn); - }); - auto txn = batch::inner( - amendTx.getJson(JsonOptions::none), env.seq(alice)); + STTx amendTx(ttAMENDMENT, [seq = env.closed()->header().seq + 1](auto& obj) { + obj.setAccountID(sfAccount, AccountID()); + obj.setFieldH256(sfAmendment, fixBatchInnerSigs); + obj.setFieldU32(sfLedgerSequence, seq); + obj.setFieldU32(sfFlags, tfInnerBatchTxn); + }); + auto txn = batch::inner(amendTx.getJson(JsonOptions::none), env.seq(alice)); STParsedJSONObject parsed("test", txn.getTxn()); Serializer s; parsed.object->add(s); @@ -2434,9 +2333,8 @@ class Batch_test : public beast::unit_test::suite "Pseudo-transaction", s.slice(), __LINE__, - withInnerSigFix - ? "fails local checks: Empty SigningPubKey." - : "fails local checks: Cannot submit pseudo transactions.", + withInnerSigFix ? "fails local checks: Empty SigningPubKey." + : "fails local checks: Cannot submit pseudo transactions.", "fails local checks: Empty SigningPubKey."); } } @@ -2537,8 +2435,7 @@ class Batch_test : public beast::unit_test::suite auto const sle = env.le(keylet::account(alice)); BEAST_EXPECT(sle); - BEAST_EXPECT( - sle->getFieldVL(sfDomain) == Blob(domain.begin(), domain.end())); + BEAST_EXPECT(sle->getFieldVL(sfDomain) == Blob(domain.begin(), domain.end())); // Alice consumes sequences (# of txns) BEAST_EXPECT(env.seq(alice) == seq + 3); @@ -2573,8 +2470,7 @@ class Batch_test : public beast::unit_test::suite auto const preBob = env.balance(bob); auto const seq = env.seq(alice); - auto const batchFee = batch::calcBatchFee(env, 0, 2) + - env.current()->fees().increment; + auto const batchFee = batch::calcBatchFee(env, 0, 2) + env.current()->fees().increment; auto const [txIDs, batchID] = submitBatch( env, tesSUCCESS, @@ -2617,8 +2513,7 @@ class Batch_test : public beast::unit_test::suite env.close(); auto const seq = env.seq(alice); - auto const batchFee = batch::calcBatchFee(env, 0, 2) + - env.current()->fees().increment; + auto const batchFee = batch::calcBatchFee(env, 0, 2) + env.current()->fees().increment; auto const [txIDs, batchID] = submitBatch( env, tesSUCCESS, @@ -2659,8 +2554,7 @@ class Batch_test : public beast::unit_test::suite auto const preBob = env.balance(bob); auto const seq = env.seq(alice); - auto const batchFee = batch::calcBatchFee(env, 0, 2) + - env.current()->fees().increment; + auto const batchFee = batch::calcBatchFee(env, 0, 2) + env.current()->fees().increment; auto const [txIDs, batchID] = submitBatch( env, tesSUCCESS, @@ -2687,17 +2581,14 @@ class Batch_test : public beast::unit_test::suite { testcase("loan"); - bool const lendingBatchEnabled = !std::any_of( - Batch::disabledTxTypes.begin(), - Batch::disabledTxTypes.end(), - [](auto const& disabled) { return disabled == ttLOAN_BROKER_SET; }); + bool const lendingBatchEnabled = + !std::any_of(Batch::disabledTxTypes.begin(), Batch::disabledTxTypes.end(), [](auto const& disabled) { + return disabled == ttLOAN_BROKER_SET; + }); using namespace test::jtx; - test::jtx::Env env{ - *this, - features | featureSingleAssetVault | featureLendingProtocol | - featureMPTokensV1}; + test::jtx::Env env{*this, features | featureSingleAssetVault | featureLendingProtocol | featureMPTokensV1}; Account const issuer{"issuer"}; // For simplicity, lender will be the sole actor for the vault & @@ -2720,18 +2611,15 @@ class Batch_test : public beast::unit_test::suite auto const debtMaximumValue = asset(25'000).value(); auto const coverDepositValue = asset(1000).value(); - auto [tx, vaultKeylet] = - vault.create({.owner = lender, .asset = asset}); + auto [tx, vaultKeylet] = vault.create({.owner = lender, .asset = asset}); env(tx); env.close(); BEAST_EXPECT(env.le(vaultKeylet)); - env(vault.deposit( - {.depositor = lender, .id = vaultKeylet.key, .amount = deposit})); + env(vault.deposit({.depositor = lender, .id = vaultKeylet.key, .amount = deposit})); env.close(); - auto const brokerKeylet = - keylet::loanbroker(lender.id(), env.seq(lender)); + auto const brokerKeylet = keylet::loanbroker(lender.id(), env.seq(lender)); { using namespace loanBroker; @@ -2757,8 +2645,7 @@ class Batch_test : public beast::unit_test::suite { auto const [txIDs, batchID] = submitBatch( env, - lendingBatchEnabled ? temBAD_SIGNATURE - : temINVALID_INNER_BATCH, + lendingBatchEnabled ? temBAD_SIGNATURE : temINVALID_INNER_BATCH, batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), batch::inner( env.json( @@ -2769,11 +2656,7 @@ class Batch_test : public beast::unit_test::suite fee(none), seq(none)), lenderSeq + 1), - batch::inner( - pay(lender, - loanKeylet.key, - STAmount{asset, asset(500).value()}), - lenderSeq + 2)); + batch::inner(pay(lender, loanKeylet.key, STAmount{asset, asset(500).value()}), lenderSeq + 2)); } { auto const [txIDs, batchID] = submitBatch( @@ -2788,17 +2671,12 @@ class Batch_test : public beast::unit_test::suite fee(none), seq(none)), lenderSeq + 1), - batch::inner( - pay(lender, - loanKeylet.key, - STAmount{asset, asset(500).value()}), - lenderSeq + 2)); + batch::inner(pay(lender, loanKeylet.key, STAmount{asset, asset(500).value()}), lenderSeq + 2)); } { auto const [txIDs, batchID] = submitBatch( env, - lendingBatchEnabled ? temBAD_SIGNER - : temINVALID_INNER_BATCH, + lendingBatchEnabled ? temBAD_SIGNER : temINVALID_INNER_BATCH, batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), batch::inner( env.json( @@ -2809,11 +2687,7 @@ class Batch_test : public beast::unit_test::suite fee(none), seq(none)), lenderSeq + 1), - batch::inner( - pay(lender, - loanKeylet.key, - STAmount{asset, asset(500).value()}), - lenderSeq + 2)); + batch::inner(pay(lender, loanKeylet.key, STAmount{asset, asset(500).value()}), lenderSeq + 2)); } { // LoanSet normally charges at least 2x base fee, but since the @@ -2822,8 +2696,7 @@ class Batch_test : public beast::unit_test::suite auto const batchFee = batch::calcBatchFee(env, 1, 2); auto const [txIDs, batchID] = submitBatch( env, - lendingBatchEnabled ? TER(tesSUCCESS) - : TER(temINVALID_INNER_BATCH), + lendingBatchEnabled ? TER(tesSUCCESS) : TER(temINVALID_INNER_BATCH), batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), batch::inner( env.json( @@ -2855,8 +2728,7 @@ class Batch_test : public beast::unit_test::suite auto const batchFee = batch::calcBatchFee(env, 1, 2); auto const [txIDs, batchID] = submitBatch( env, - lendingBatchEnabled ? TER(tesSUCCESS) - : TER(temINVALID_INNER_BATCH), + lendingBatchEnabled ? TER(tesSUCCESS) : TER(temINVALID_INNER_BATCH), batch::outer(lender, lenderSeq, batchFee, tfAllOrNothing), batch::inner( env.json( @@ -2866,16 +2738,13 @@ class Batch_test : public beast::unit_test::suite fee(none), seq(none)), lenderSeq + 1), - batch::inner( - manage(lender, loanKeylet.key, tfLoanImpair), - lenderSeq + 2), + batch::inner(manage(lender, loanKeylet.key, tfLoanImpair), lenderSeq + 2), batch::sig(borrower)); } env.close(); BEAST_EXPECT(env.le(brokerKeylet)); - if (auto const sleLoan = env.le(loanKeylet); lendingBatchEnabled - ? BEAST_EXPECT(sleLoan) - : !BEAST_EXPECT(!sleLoan)) + if (auto const sleLoan = env.le(loanKeylet); + lendingBatchEnabled ? BEAST_EXPECT(sleLoan) : !BEAST_EXPECT(!sleLoan)) { BEAST_EXPECT(sleLoan->isFlag(lsfLoanImpaired)); } @@ -2943,8 +2812,7 @@ class Batch_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(bob) == preBob); // Alice pays USD & Bob receives USD - BEAST_EXPECT( - env.balance(alice, USD.issue()) == preAliceUSD + USD(10)); + BEAST_EXPECT(env.balance(alice, USD.issue()) == preAliceUSD + USD(10)); BEAST_EXPECT(env.balance(bob, USD.issue()) == preBobUSD - USD(10)); } @@ -3478,8 +3346,7 @@ class Batch_test : public beast::unit_test::suite auto const aliceSeq = env.seq(alice); // AccountSet Txn - auto const noopTxn = - env.jt(noop(alice), ticket::use(aliceTicketSeq + 1)); + auto const noopTxn = env.jt(noop(alice), ticket::use(aliceTicketSeq + 1)); auto const noopTxnID = to_string(noopTxn.stx->getTransactionID()); env(noopTxn, ter(tesSUCCESS)); @@ -3537,8 +3404,7 @@ class Batch_test : public beast::unit_test::suite ticket::use(aliceTicketSeq)); // AccountSet Txn - auto const noopTxn = - env.jt(noop(alice), ticket::use(aliceTicketSeq + 1)); + auto const noopTxn = env.jt(noop(alice), ticket::use(aliceTicketSeq + 1)); env(noopTxn); env.close(); @@ -3820,8 +3686,7 @@ class Batch_test : public beast::unit_test::suite BEAST_EXPECT(env.seq(bob) == bobSeq + 2); // Alice pays XRP & Fee; Bob receives XRP & pays Fee - BEAST_EXPECT( - env.balance(alice) == preAlice - XRP(10) - batchFee - baseFee); + BEAST_EXPECT(env.balance(alice) == preAlice - XRP(10) - batchFee - baseFee); BEAST_EXPECT(env.balance(bob) == preBob + XRP(10) - baseFee); } @@ -3837,8 +3702,7 @@ class Batch_test : public beast::unit_test::suite { test::jtx::Env env{ *this, - makeSmallQueueConfig( - {{"minimum_txn_in_ledger_standalone", "2"}}), + makeSmallQueueConfig({{"minimum_txn_in_ledger_standalone", "2"}}), features, nullptr, beast::severities::kError}; @@ -3879,11 +3743,7 @@ class Batch_test : public beast::unit_test::suite // Replace Queued Batch { - env(batch::outer( - alice, - aliceSeq, - openLedgerFee(env, batchFee), - tfAllOrNothing), + env(batch::outer(alice, aliceSeq, openLedgerFee(env, batchFee), tfAllOrNothing), batch::inner(pay(alice, bob, XRP(10)), aliceSeq + 1), batch::inner(pay(bob, alice, XRP(5)), bobSeq), batch::sig(bob), @@ -3898,8 +3758,7 @@ class Batch_test : public beast::unit_test::suite { test::jtx::Env env{ *this, - makeSmallQueueConfig( - {{"minimum_txn_in_ledger_standalone", "2"}}), + makeSmallQueueConfig({{"minimum_txn_in_ledger_standalone", "2"}}), features, nullptr, beast::severities::kError}; @@ -3947,12 +3806,7 @@ class Batch_test : public beast::unit_test::suite using namespace test::jtx; using namespace std::literals; - Env env( - *this, - envconfig(), - features, - nullptr, - beast::severities::kDisabled); + Env env(*this, envconfig(), features, nullptr, beast::severities::kDisabled); auto alice = Account("alice"); auto bob = Account("bob"); @@ -3972,10 +3826,8 @@ class Batch_test : public beast::unit_test::suite Serializer s; jt.stx->add(s); std::string reason; - auto transaction = - std::make_shared(jt.stx, reason, env.app()); - env.app().getOPs().processTransaction( - transaction, false, true, NetworkOPs::FailHard::yes); + auto transaction = std::make_shared(jt.stx, reason, env.app()); + env.app().getOPs().processTransaction(transaction, false, true, NetworkOPs::FailHard::yes); return transaction->getID(); }; @@ -3983,18 +3835,14 @@ class Batch_test : public beast::unit_test::suite { // Submit a tx with tfInnerBatchTxn uint256 const txBad = submitTx(tfInnerBatchTxn); - BEAST_EXPECT( - env.app().getHashRouter().getFlags(txBad) == - HashRouterFlags::UNDEFINED); + BEAST_EXPECT(env.app().getHashRouter().getFlags(txBad) == HashRouterFlags::UNDEFINED); } // Validate: NetworkOPs::processTransaction() { uint256 const txid = processTxn(tfInnerBatchTxn); // HashRouter::getFlags() should return LedgerFlags::BAD - BEAST_EXPECT( - env.app().getHashRouter().getFlags(txid) == - HashRouterFlags::BAD); + BEAST_EXPECT(env.app().getHashRouter().getFlags(txid) == HashRouterFlags::BAD); } } @@ -4167,8 +4015,7 @@ class Batch_test : public beast::unit_test::suite env.close(); // alice gives granular permission to bob of MPTokenIssuanceLock - env(delegate::set( - alice, bob, {"MPTokenIssuanceLock", "MPTokenIssuanceUnlock"})); + env(delegate::set(alice, bob, {"MPTokenIssuanceLock", "MPTokenIssuanceUnlock"})); env.close(); auto const seq = env.seq(alice); @@ -4220,8 +4067,7 @@ class Batch_test : public beast::unit_test::suite env(trust(alice, gw["USD"](50))); env.close(); - env(delegate::set( - gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"})); + env(delegate::set(gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"})); env.close(); auto const seq = env.seq(gw); @@ -4260,8 +4106,7 @@ class Batch_test : public beast::unit_test::suite env(trust(alice, gw["USD"](50))); env.close(); - env(delegate::set( - gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"})); + env(delegate::set(gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"})); env.close(); auto const seq = env.seq(gw); @@ -4316,11 +4161,9 @@ class Batch_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(jr.isMember(jss::account_sequence_available)); - BEAST_EXPECT( - jr[jss::account_sequence_available].asUInt() == aliceSeq + 1); + BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq + 1); BEAST_EXPECT(jr.isMember(jss::account_sequence_next)); - BEAST_EXPECT( - jr[jss::account_sequence_next].asUInt() == aliceSeq + 1); + BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq + 1); BEAST_EXPECT(jr.isMember(jss::open_ledger_cost)); BEAST_EXPECT(jr[jss::open_ledger_cost] == to_string(baseFee)); BEAST_EXPECT(jr.isMember(jss::validated_ledger_index)); @@ -4339,11 +4182,9 @@ class Batch_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(jr.isMember(jss::account_sequence_available)); - BEAST_EXPECT( - jr[jss::account_sequence_available].asUInt() == aliceSeq + 1); + BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq + 1); BEAST_EXPECT(jr.isMember(jss::account_sequence_next)); - BEAST_EXPECT( - jr[jss::account_sequence_next].asUInt() == aliceSeq + 1); + BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq + 1); BEAST_EXPECT(jr.isMember(jss::open_ledger_cost)); BEAST_EXPECT(jr[jss::open_ledger_cost] == to_string(baseFee)); BEAST_EXPECT(jr.isMember(jss::validated_ledger_index)); @@ -4361,8 +4202,7 @@ class Batch_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(jr.isMember(jss::account_sequence_available)); - BEAST_EXPECT( - jr[jss::account_sequence_available].asUInt() == aliceSeq); + BEAST_EXPECT(jr[jss::account_sequence_available].asUInt() == aliceSeq); BEAST_EXPECT(jr.isMember(jss::account_sequence_next)); BEAST_EXPECT(jr[jss::account_sequence_next].asUInt() == aliceSeq); BEAST_EXPECT(jr.isMember(jss::open_ledger_cost)); @@ -4394,8 +4234,7 @@ class Batch_test : public beast::unit_test::suite XRPAmount const batchFee = batch::calcBatchFee(env, 0, 2); auto jtx = env.jt( batch::outer(alice, seq, batchFee, tfAllOrNothing), - batch::inner( - batch::outer(alice, seq, batchFee, tfAllOrNothing), seq), + batch::inner(batch::outer(alice, seq, batchFee, tfAllOrNothing), seq), batch::inner(pay(alice, bob, XRP(1)), seq + 2)); XRPAmount const txBaseFee = getBaseFee(jtx); BEAST_EXPECT(txBaseFee == XRPAmount(INITIAL_XRP)); @@ -4431,17 +4270,7 @@ class Batch_test : public beast::unit_test::suite batch::outer(alice, seq, batchFee, tfAllOrNothing), batch::inner(pay(alice, bob, XRP(10)), seq + 1), batch::inner(pay(alice, bob, XRP(5)), seq + 2), - batch::sig( - bob, - carol, - alice, - bob, - carol, - alice, - bob, - carol, - alice, - alice)); + batch::sig(bob, carol, alice, bob, carol, alice, bob, carol, alice, alice)); XRPAmount const txBaseFee = getBaseFee(jtx); BEAST_EXPECT(txBaseFee == XRPAmount(INITIAL_XRP)); } diff --git a/src/test/app/Check_test.cpp b/src/test/app/Check_test.cpp index 8eccdc4824..42c600c22b 100644 --- a/src/test/app/Check_test.cpp +++ b/src/test/app/Check_test.cpp @@ -14,8 +14,7 @@ private: std::uint32_t const expiry_; public: - explicit expiration(NetClock::time_point const& expiry) - : expiry_{expiry.time_since_epoch().count()} + explicit expiration(NetClock::time_point const& expiry) : expiry_{expiry.time_since_epoch().count()} { } @@ -78,13 +77,10 @@ class Check_test : public beast::unit_test::suite checksOnAccount(test::jtx::Env& env, test::jtx::Account account) { std::vector> result; - forEachItem( - *env.current(), - account, - [&result](std::shared_ptr const& sle) { - if (sle && sle->getType() == ltCHECK) - result.push_back(sle); - }); + forEachItem(*env.current(), account, [&result](std::shared_ptr const& sle) { + if (sle && sle->getType() == ltCHECK) + result.push_back(sle); + }); return result; } @@ -96,8 +92,7 @@ class Check_test : public beast::unit_test::suite verifyDeliveredAmount(test::jtx::Env& env, STAmount const& amount) { // Get the hash for the most recent transaction. - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; // Verify DeliveredAmount and delivered_amount metadata are correct. env.close(); @@ -109,11 +104,8 @@ class Check_test : public beast::unit_test::suite // DeliveredAmount and delivered_amount should both be present and // equal amount. - BEAST_EXPECT( - meta[sfDeliveredAmount.jsonName] == - amount.getJson(JsonOptions::none)); - BEAST_EXPECT( - meta[jss::delivered_amount] == amount.getJson(JsonOptions::none)); + BEAST_EXPECT(meta[sfDeliveredAmount.jsonName] == amount.getJson(JsonOptions::none)); + BEAST_EXPECT(meta[jss::delivered_amount] == amount.getJson(JsonOptions::none)); } void @@ -131,16 +123,14 @@ class Check_test : public beast::unit_test::suite env.fund(XRP(1000), alice); env.close(); - uint256 const checkId1{ - getCheckIndex(env.master, env.seq(env.master))}; + uint256 const checkId1{getCheckIndex(env.master, env.seq(env.master))}; env(check::create(env.master, alice, XRP(100))); env.close(); env(check::cash(alice, checkId1, XRP(100))); env.close(); - uint256 const checkId2{ - getCheckIndex(env.master, env.seq(env.master))}; + uint256 const checkId2{getCheckIndex(env.master, env.seq(env.master))}; env(check::create(env.master, alice, XRP(100))); env.close(); @@ -171,8 +161,7 @@ class Check_test : public beast::unit_test::suite // Note that no trust line has been set up for alice, but alice can // still write a check for USD. You don't have to have the funds // necessary to cover a check in order to write a check. - auto writeTwoChecks = [&env, &USD, this]( - Account const& from, Account const& to) { + auto writeTwoChecks = [&env, &USD, this](Account const& from, Account const& to) { std::uint32_t const fromOwnerCount{ownerCount(env, from)}; std::uint32_t const toOwnerCount{ownerCount(env, to)}; @@ -189,8 +178,7 @@ class Check_test : public beast::unit_test::suite BEAST_EXPECT(checksOnAccount(env, to).size() == toCkCount + 2); env.require(owners(from, fromOwnerCount + 2)); - env.require( - owners(to, to == from ? fromOwnerCount + 2 : toOwnerCount)); + env.require(owners(to, to == from ? fromOwnerCount + 2 : toOwnerCount)); }; // from to writeTwoChecks(alice, bob); @@ -241,9 +229,7 @@ class Check_test : public beast::unit_test::suite // alice uses multisigning to create a check. XRPAmount const baseFeeDrops{env.current()->fees().base}; - env(check::create(alice, bob, USD(50)), - msig(bogie, demon), - fee(3 * baseFeeDrops)); + env(check::create(alice, bob, USD(50)), msig(bogie, demon), fee(3 * baseFeeDrops)); env.close(); BEAST_EXPECT(checksOnAccount(env, alice).size() == aliceCount + 7); BEAST_EXPECT(checksOnAccount(env, bob).size() == bobCount + 7); @@ -271,10 +257,7 @@ class Check_test : public beast::unit_test::suite * Attempt to create two checks from `from` to `to` and * require they both result in error/success code `expected` */ - auto writeTwoChecksDI = [&env, &USD, this]( - Account const& from, - Account const& to, - TER expected) { + auto writeTwoChecksDI = [&env, &USD, this](Account const& from, Account const& to, TER expected) { std::uint32_t const fromOwnerCount{ownerCount(env, from)}; std::uint32_t const toOwnerCount{ownerCount(env, to)}; @@ -289,13 +272,11 @@ class Check_test : public beast::unit_test::suite if (expected == tesSUCCESS) { - BEAST_EXPECT( - checksOnAccount(env, from).size() == fromCkCount + 2); + BEAST_EXPECT(checksOnAccount(env, from).size() == fromCkCount + 2); BEAST_EXPECT(checksOnAccount(env, to).size() == toCkCount + 2); env.require(owners(from, fromOwnerCount + 2)); - env.require( - owners(to, to == from ? fromOwnerCount + 2 : toOwnerCount)); + env.require(owners(to, to == from ? fromOwnerCount + 2 : toOwnerCount)); return; } @@ -353,15 +334,11 @@ class Check_test : public beast::unit_test::suite env.close(); // Bad fee. - env(check::create(alice, bob, USD(50)), - fee(drops(-10)), - ter(temBAD_FEE)); + env(check::create(alice, bob, USD(50)), fee(drops(-10)), ter(temBAD_FEE)); env.close(); // Bad flags. - env(check::create(alice, bob, USD(50)), - txflags(tfImmediateOrCancel), - ter(temINVALID_FLAG)); + env(check::create(alice, bob, USD(50)), txflags(tfImmediateOrCancel), ter(temINVALID_FLAG)); env.close(); // Check to self. @@ -393,9 +370,7 @@ class Check_test : public beast::unit_test::suite } // Bad expiration. - env(check::create(alice, bob, USD(50)), - expiration(NetClock::time_point{}), - ter(temBAD_EXPIRATION)); + env(check::create(alice, bob, USD(50)), expiration(NetClock::time_point{}), ter(temBAD_EXPIRATION)); env.close(); // Destination does not exist. @@ -492,9 +467,7 @@ class Check_test : public beast::unit_test::suite } // Expired expiration. - env(check::create(alice, bob, USD(50)), - expiration(env.now()), - ter(tecEXPIRED)); + env(check::create(alice, bob, USD(50)), expiration(env.now()), ter(tecEXPIRED)); env.close(); using namespace std::chrono_literals; @@ -506,9 +479,7 @@ class Check_test : public beast::unit_test::suite env.fund(env.current()->fees().accountReserve(1) - drops(1), cheri); env.close(); - env(check::create(cheri, bob, USD(50)), - fee(drops(env.current()->fees().base)), - ter(tecINSUFFICIENT_RESERVE)); + env(check::create(cheri, bob, USD(50)), fee(drops(env.current()->fees().base)), ter(tecINSUFFICIENT_RESERVE)); env.close(); env(pay(bob, cheri, drops(env.current()->fees().base + 1))); @@ -549,10 +520,8 @@ class Check_test : public beast::unit_test::suite env(check::cash(bob, chkId, XRP(10))); env.close(); - env.require( - balance(alice, startBalance - XRP(10) - drops(baseFeeDrops))); - env.require( - balance(bob, startBalance + XRP(10) - drops(baseFeeDrops))); + env.require(balance(alice, startBalance - XRP(10) - drops(baseFeeDrops))); + env.require(balance(bob, startBalance + XRP(10) - drops(baseFeeDrops))); BEAST_EXPECT(checksOnAccount(env, alice).size() == 0); BEAST_EXPECT(checksOnAccount(env, bob).size() == 0); BEAST_EXPECT(ownerCount(env, alice) == 0); @@ -568,19 +537,15 @@ class Check_test : public beast::unit_test::suite { // Write a check that chews into alice's reserve. STAmount const reserve{env.current()->fees().reserve}; - STAmount const checkAmount{ - startBalance - reserve - drops(baseFeeDrops)}; + STAmount const checkAmount{startBalance - reserve - drops(baseFeeDrops)}; uint256 const chkId{getCheckIndex(alice, env.seq(alice))}; env(check::create(alice, bob, checkAmount)); env.close(); // bob tries to cash for more than the check amount. - env(check::cash(bob, chkId, checkAmount + drops(1)), - ter(tecPATH_PARTIAL)); + env(check::cash(bob, chkId, checkAmount + drops(1)), ter(tecPATH_PARTIAL)); env.close(); - env(check::cash( - bob, chkId, check::DeliverMin(checkAmount + drops(1))), - ter(tecPATH_PARTIAL)); + env(check::cash(bob, chkId, check::DeliverMin(checkAmount + drops(1))), ter(tecPATH_PARTIAL)); env.close(); // bob cashes exactly the check amount. This is successful @@ -589,8 +554,7 @@ class Check_test : public beast::unit_test::suite env(check::cash(bob, chkId, check::DeliverMin(checkAmount))); verifyDeliveredAmount(env, drops(checkAmount.mantissa())); env.require(balance(alice, reserve)); - env.require(balance( - bob, startBalance + checkAmount - drops(baseFeeDrops * 3))); + env.require(balance(bob, startBalance + checkAmount - drops(baseFeeDrops * 3))); BEAST_EXPECT(checksOnAccount(env, alice).size() == 0); BEAST_EXPECT(checksOnAccount(env, bob).size() == 0); BEAST_EXPECT(ownerCount(env, alice) == 0); @@ -606,8 +570,7 @@ class Check_test : public beast::unit_test::suite { // Write a check that goes one drop past what alice can pay. STAmount const reserve{env.current()->fees().reserve}; - STAmount const checkAmount{ - startBalance - reserve - drops(baseFeeDrops - 1)}; + STAmount const checkAmount{startBalance - reserve - drops(baseFeeDrops - 1)}; uint256 const chkId{getCheckIndex(alice, env.seq(alice))}; env(check::create(alice, bob, checkAmount)); env.close(); @@ -621,8 +584,7 @@ class Check_test : public beast::unit_test::suite env(check::cash(bob, chkId, check::DeliverMin(drops(1)))); verifyDeliveredAmount(env, drops(checkAmount.mantissa() - 1)); env.require(balance(alice, reserve)); - env.require(balance( - bob, startBalance + checkAmount - drops(baseFeeDrops * 2 + 1))); + env.require(balance(bob, startBalance + checkAmount - drops(baseFeeDrops * 2 + 1))); BEAST_EXPECT(checksOnAccount(env, alice).size() == 0); BEAST_EXPECT(checksOnAccount(env, bob).size() == 0); BEAST_EXPECT(ownerCount(env, alice) == 0); @@ -630,8 +592,7 @@ class Check_test : public beast::unit_test::suite // Make alice's and bob's balances easy to think about. env(pay(env.master, alice, checkAmount + drops(baseFeeDrops - 1))); - env(pay( - bob, env.master, checkAmount - drops(baseFeeDrops * 3 + 1))); + env(pay(bob, env.master, checkAmount - drops(baseFeeDrops * 3 + 1))); env.close(); env.require(balance(alice, startBalance)); env.require(balance(bob, startBalance)); @@ -821,8 +782,7 @@ class Check_test : public beast::unit_test::suite // bob attempts to cash a check for the amount on the check. // Should fail, since alice doesn't have the funds. - env(check::cash(bob, chkId9, check::DeliverMin(USD(9))), - ter(tecPATH_PARTIAL)); + env(check::cash(bob, chkId9, check::DeliverMin(USD(9))), ter(tecPATH_PARTIAL)); env.close(); // bob sets a DeliverMin of 7 and gets all that alice has. @@ -974,9 +934,7 @@ class Check_test : public beast::unit_test::suite // bob uses multisigning to cash a check. XRPAmount const baseFeeDrops{env.current()->fees().base}; - env(check::cash(bob, chkId2, (USD(2))), - msig(bogie, demon), - fee(3 * baseFeeDrops)); + env(check::cash(bob, chkId2, (USD(2))), msig(bogie, demon), fee(3 * baseFeeDrops)); env.close(); env.require(balance(alice, USD(5))); env.require(balance(bob, USD(3))); @@ -1031,8 +989,7 @@ class Check_test : public beast::unit_test::suite // bob attempts to cash the check for face value. Should fail. env(check::cash(bob, chkId125, USD(125)), ter(tecPATH_PARTIAL)); env.close(); - env(check::cash(bob, chkId125, check::DeliverMin(USD(101))), - ter(tecPATH_PARTIAL)); + env(check::cash(bob, chkId125, check::DeliverMin(USD(101))), ter(tecPATH_PARTIAL)); env.close(); // bob decides that he'll accept anything USD(75) or up. @@ -1092,59 +1049,53 @@ class Check_test : public beast::unit_test::suite // There are two test lambdas: one for a Payment and one for a Check. // This shows whether a Payment and a Check behave the same. - auto testNonIssuerQPay = [&env, &alice, &bob, &USD]( - Account const& truster, - IOU const& iou, - auto const& inOrOut, - double pct, - double amount) { - // Capture bob's and alice's balances so we can test at the end. - STAmount const aliceStart{env.balance(alice, USD.issue()).value()}; - STAmount const bobStart{env.balance(bob, USD.issue()).value()}; + auto testNonIssuerQPay = + [&env, &alice, &bob, &USD]( + Account const& truster, IOU const& iou, auto const& inOrOut, double pct, double amount) { + // Capture bob's and alice's balances so we can test at the end. + STAmount const aliceStart{env.balance(alice, USD.issue()).value()}; + STAmount const bobStart{env.balance(bob, USD.issue()).value()}; - // Set the modified quality. - env(trust(truster, iou(1000)), inOrOut(pct)); - env.close(); + // Set the modified quality. + env(trust(truster, iou(1000)), inOrOut(pct)); + env.close(); - env(pay(alice, bob, USD(amount)), sendmax(USD(10))); - env.close(); - env.require(balance(alice, aliceStart - USD(10))); - env.require(balance(bob, bobStart + USD(10))); + env(pay(alice, bob, USD(amount)), sendmax(USD(10))); + env.close(); + env.require(balance(alice, aliceStart - USD(10))); + env.require(balance(bob, bobStart + USD(10))); - // Return the quality to the unmodified state so it doesn't - // interfere with upcoming tests. - env(trust(truster, iou(1000)), inOrOut(0)); - env.close(); - }; + // Return the quality to the unmodified state so it doesn't + // interfere with upcoming tests. + env(trust(truster, iou(1000)), inOrOut(0)); + env.close(); + }; - auto testNonIssuerQCheck = [&env, &alice, &bob, &USD]( - Account const& truster, - IOU const& iou, - auto const& inOrOut, - double pct, - double amount) { - // Capture bob's and alice's balances so we can test at the end. - STAmount const aliceStart{env.balance(alice, USD.issue()).value()}; - STAmount const bobStart{env.balance(bob, USD.issue()).value()}; + auto testNonIssuerQCheck = + [&env, &alice, &bob, &USD]( + Account const& truster, IOU const& iou, auto const& inOrOut, double pct, double amount) { + // Capture bob's and alice's balances so we can test at the end. + STAmount const aliceStart{env.balance(alice, USD.issue()).value()}; + STAmount const bobStart{env.balance(bob, USD.issue()).value()}; - // Set the modified quality. - env(trust(truster, iou(1000)), inOrOut(pct)); - env.close(); + // Set the modified quality. + env(trust(truster, iou(1000)), inOrOut(pct)); + env.close(); - uint256 const chkId = getCheckIndex(alice, env.seq(alice)); - env(check::create(alice, bob, USD(10))); - env.close(); + uint256 const chkId = getCheckIndex(alice, env.seq(alice)); + env(check::create(alice, bob, USD(10))); + env.close(); - env(check::cash(bob, chkId, USD(amount))); - env.close(); - env.require(balance(alice, aliceStart - USD(10))); - env.require(balance(bob, bobStart + USD(10))); + env(check::cash(bob, chkId, USD(amount))); + env.close(); + env.require(balance(alice, aliceStart - USD(10))); + env.require(balance(bob, bobStart + USD(10))); - // Return the quality to the unmodified state so it doesn't - // interfere with upcoming tests. - env(trust(truster, iou(1000)), inOrOut(0)); - env.close(); - }; + // Return the quality to the unmodified state so it doesn't + // interfere with upcoming tests. + env(trust(truster, iou(1000)), inOrOut(0)); + env.close(); + }; // pct amount testNonIssuerQPay(alice, gw["USD"], qIn, 50, 10); @@ -1341,18 +1292,13 @@ class Check_test : public beast::unit_test::suite env.close(); // Same set of failing cases for both IOU and XRP check cashing. - auto failingCases = [&env, &gw, &alice, &bob]( - uint256 const& chkId, STAmount const& amount) { + auto failingCases = [&env, &gw, &alice, &bob](uint256 const& chkId, STAmount const& amount) { // Bad fee. - env(check::cash(bob, chkId, amount), - fee(drops(-10)), - ter(temBAD_FEE)); + env(check::cash(bob, chkId, amount), fee(drops(-10)), ter(temBAD_FEE)); env.close(); // Bad flags. - env(check::cash(bob, chkId, amount), - txflags(tfImmediateOrCancel), - ter(temINVALID_FLAG)); + env(check::cash(bob, chkId, amount), txflags(tfImmediateOrCancel), ter(temINVALID_FLAG)); env.close(); // Missing both Amount and DeliverMin. @@ -1376,8 +1322,7 @@ class Check_test : public beast::unit_test::suite neg.negate(); env(check::cash(bob, chkId, neg), ter(temBAD_AMOUNT)); env.close(); - env(check::cash(bob, chkId, amount.zeroed()), - ter(temBAD_AMOUNT)); + env(check::cash(bob, chkId, amount.zeroed()), ter(temBAD_AMOUNT)); env.close(); } @@ -1420,8 +1365,7 @@ class Check_test : public beast::unit_test::suite env.close(); // DeliverMin bigger than SendMax. - env(check::cash(bob, chkId, check::DeliverMin(amount + amount)), - ter(tecPATH_PARTIAL)); + env(check::cash(bob, chkId, check::DeliverMin(amount + amount)), ter(tecPATH_PARTIAL)); env.close(); }; @@ -1455,8 +1399,7 @@ class Check_test : public beast::unit_test::suite env(check::cash(bob, chkIdFroz1, USD(1)), ter(tecPATH_PARTIAL)); env.close(); - env(check::cash(bob, chkIdFroz1, check::DeliverMin(USD(0.5))), - ter(tecPATH_PARTIAL)); + env(check::cash(bob, chkIdFroz1, check::DeliverMin(USD(0.5))), ter(tecPATH_PARTIAL)); env.close(); env(fclear(gw, asfGlobalFreeze)); @@ -1473,8 +1416,7 @@ class Check_test : public beast::unit_test::suite env.close(); env(check::cash(bob, chkIdFroz2, USD(2)), ter(tecPATH_PARTIAL)); env.close(); - env(check::cash(bob, chkIdFroz2, check::DeliverMin(USD(1))), - ter(tecPATH_PARTIAL)); + env(check::cash(bob, chkIdFroz2, check::DeliverMin(USD(1))), ter(tecPATH_PARTIAL)); env.close(); // Clear that freeze. Now check cashing works. @@ -1490,8 +1432,7 @@ class Check_test : public beast::unit_test::suite env.close(); env(check::cash(bob, chkIdFroz3, USD(3)), ter(tecFROZEN)); env.close(); - env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))), - ter(tecFROZEN)); + env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))), ter(tecFROZEN)); env.close(); // Clear that freeze. Now check cashing works again. @@ -1508,8 +1449,7 @@ class Check_test : public beast::unit_test::suite env.close(); env(check::cash(bob, chkIdFroz4, USD(4)), ter(terNO_LINE)); env.close(); - env(check::cash(bob, chkIdFroz4, check::DeliverMin(USD(1))), - ter(terNO_LINE)); + env(check::cash(bob, chkIdFroz4, check::DeliverMin(USD(1))), ter(terNO_LINE)); env.close(); // Clear bob's freeze bit and the check should be cashable. @@ -1527,8 +1467,7 @@ class Check_test : public beast::unit_test::suite env.close(); env(check::cash(bob, chkIdNoDest1, USD(1)), ter(tecDST_TAG_NEEDED)); env.close(); - env(check::cash(bob, chkIdNoDest1, check::DeliverMin(USD(0.5))), - ter(tecDST_TAG_NEEDED)); + env(check::cash(bob, chkIdNoDest1, check::DeliverMin(USD(0.5))), ter(tecDST_TAG_NEEDED)); env.close(); // bob can cash a check with a destination tag. @@ -1585,18 +1524,15 @@ class Check_test : public beast::unit_test::suite // Three checks that expire in 10 minutes. using namespace std::chrono_literals; uint256 const chkIdNotExp1{getCheckIndex(alice, env.seq(alice))}; - env(check::create(alice, bob, XRP(10)), - expiration(env.now() + 600s)); + env(check::create(alice, bob, XRP(10)), expiration(env.now() + 600s)); env.close(); uint256 const chkIdNotExp2{getCheckIndex(alice, env.seq(alice))}; - env(check::create(alice, bob, USD(10)), - expiration(env.now() + 600s)); + env(check::create(alice, bob, USD(10)), expiration(env.now() + 600s)); env.close(); uint256 const chkIdNotExp3{getCheckIndex(alice, env.seq(alice))}; - env(check::create(alice, bob, XRP(10)), - expiration(env.now() + 600s)); + env(check::create(alice, bob, XRP(10)), expiration(env.now() + 600s)); env.close(); // Three checks that expire in one second. @@ -1689,9 +1625,7 @@ class Check_test : public beast::unit_test::suite // alice uses multisigning to cancel a check. XRPAmount const baseFeeDrops{env.current()->fees().base}; - env(check::cancel(alice, chkIdMSig), - msig(bogie, demon), - fee(3 * baseFeeDrops)); + env(check::cancel(alice, chkIdMSig), msig(bogie, demon), fee(3 * baseFeeDrops)); env.close(); BEAST_EXPECT(checksOnAccount(env, alice).size() == 2); BEAST_EXPECT(ownerCount(env, alice) == 3); @@ -1726,9 +1660,7 @@ class Check_test : public beast::unit_test::suite env.close(); // Bad fee. - env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))), - fee(drops(-10)), - ter(temBAD_FEE)); + env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))), fee(drops(-10)), ter(temBAD_FEE)); env.close(); // Bad flags. @@ -1738,8 +1670,7 @@ class Check_test : public beast::unit_test::suite env.close(); // Non-existent check. - env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))), - ter(tecNO_ENTRY)); + env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))), ter(tecNO_ENTRY)); env.close(); } @@ -1764,8 +1695,7 @@ class Check_test : public beast::unit_test::suite env(check::cash(bob, chkId, check::DeliverMin(XRP(100)))); // Get the hash for the most recent transaction. - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; env.close(); Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta]; @@ -1898,11 +1828,7 @@ class Check_test : public beast::unit_test::suite void verifyOwners(std::uint32_t line) const { - suite.expect( - ownerCount(env, acct) == owners, - "Owner count mismatch", - __FILE__, - line); + suite.expect(ownerCount(env, acct) == owners, "Owner count mismatch", __FILE__, line); } // Operators to make using the class more convenient. @@ -1956,8 +1882,7 @@ class Check_test : public beast::unit_test::suite env(check::create(gw1, yui, CK8(99))); env.close(); - env(check::cash(yui, chkId, CK8(99)), - ter(tecNO_LINE_INSUF_RESERVE)); + env(check::cash(yui, chkId, CK8(99)), ter(tecNO_LINE_INSUF_RESERVE)); env.close(); alice.verifyOwners(__LINE__); @@ -1988,14 +1913,9 @@ class Check_test : public beast::unit_test::suite // between the same two accounts but with two different currencies. // The lambda expects the two trust lines to be largely similar. auto cmpTrustLines = [this, &env]( - Account const& acct1, - Account const& acct2, - IOU const& offerIou, - IOU const& checkIou) { - auto const offerLine = - env.le(keylet::line(acct1, acct2, offerIou.currency)); - auto const checkLine = - env.le(keylet::line(acct1, acct2, checkIou.currency)); + Account const& acct1, Account const& acct2, IOU const& offerIou, IOU const& checkIou) { + auto const offerLine = env.le(keylet::line(acct1, acct2, offerIou.currency)); + auto const checkLine = env.le(keylet::line(acct1, acct2, checkIou.currency)); if (offerLine == nullptr || checkLine == nullptr) { BEAST_EXPECT(offerLine == nullptr && checkLine == nullptr); @@ -2008,50 +1928,39 @@ class Check_test : public beast::unit_test::suite // Lambda that compares the contents of required STAmounts // without comparing the currency. - auto cmpReqAmount = - [this, offerLine, checkLine](SF_AMOUNT const& sfield) { - STAmount const offerAmount = offerLine->at(sfield); - STAmount const checkAmount = checkLine->at(sfield); + auto cmpReqAmount = [this, offerLine, checkLine](SF_AMOUNT const& sfield) { + STAmount const offerAmount = offerLine->at(sfield); + STAmount const checkAmount = checkLine->at(sfield); - // Neither STAmount should be native. - if (!BEAST_EXPECT( - !offerAmount.native() && !checkAmount.native())) - return; + // Neither STAmount should be native. + if (!BEAST_EXPECT(!offerAmount.native() && !checkAmount.native())) + return; - BEAST_EXPECT( - offerAmount.issue().account == - checkAmount.issue().account); - BEAST_EXPECT( - offerAmount.negative() == checkAmount.negative()); - BEAST_EXPECT( - offerAmount.mantissa() == checkAmount.mantissa()); - BEAST_EXPECT( - offerAmount.exponent() == checkAmount.exponent()); - }; + BEAST_EXPECT(offerAmount.issue().account == checkAmount.issue().account); + BEAST_EXPECT(offerAmount.negative() == checkAmount.negative()); + BEAST_EXPECT(offerAmount.mantissa() == checkAmount.mantissa()); + BEAST_EXPECT(offerAmount.exponent() == checkAmount.exponent()); + }; cmpReqAmount(sfBalance); cmpReqAmount(sfLowLimit); cmpReqAmount(sfHighLimit); } { // Lambda that compares the contents of optional fields. - auto cmpOptField = - [this, offerLine, checkLine](auto const& sfield) { - // Expect both fields to either be present or absent. - if (!BEAST_EXPECT( - offerLine->isFieldPresent(sfield) == - checkLine->isFieldPresent(sfield))) - return; + auto cmpOptField = [this, offerLine, checkLine](auto const& sfield) { + // Expect both fields to either be present or absent. + if (!BEAST_EXPECT(offerLine->isFieldPresent(sfield) == checkLine->isFieldPresent(sfield))) + return; - // If both fields are absent then there's nothing - // further to check. - if (!offerLine->isFieldPresent(sfield)) - return; + // If both fields are absent then there's nothing + // further to check. + if (!offerLine->isFieldPresent(sfield)) + return; - // Both optional fields are present so we can compare - // them. - BEAST_EXPECT( - offerLine->at(sfield) == checkLine->at(sfield)); - }; + // Both optional fields are present so we can compare + // them. + BEAST_EXPECT(offerLine->at(sfield) == checkLine->at(sfield)); + }; cmpOptField(sfLowNode); cmpOptField(sfLowQualityIn); cmpOptField(sfLowQualityOut); @@ -2076,8 +1985,7 @@ class Check_test : public beast::unit_test::suite IOU const OF1 = gw1["OF1"]; env(offer(gw1, XRP(98), OF1(98))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, OF1.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, OF1.currency)) == nullptr); env(offer(alice, OF1(98), XRP(98))); ++alice.owners; env.close(); @@ -2095,8 +2003,7 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))}; env(check::create(gw1, alice, CK1(98))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, CK1.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, CK1.currency)) == nullptr); env(check::cash(alice, chkId, CK1(98))); ++alice.owners; verifyDeliveredAmount(env, CK1(98)); @@ -2125,8 +2032,7 @@ class Check_test : public beast::unit_test::suite IOU const OF1 = gw1["OF1"]; env(offer(alice, XRP(97), OF1(97))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, OF1.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, OF1.currency)) == nullptr); env(offer(bob, OF1(97), XRP(97))); ++bob.owners; env.close(); @@ -2150,15 +2056,12 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(alice, env.seq(alice))}; env(check::create(alice, bob, CK1(97))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, CK1.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, CK1.currency)) == nullptr); env(check::cash(bob, chkId, CK1(97)), ter(terNO_RIPPLE)); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, bob, OF1.currency)) != nullptr); - BEAST_EXPECT( - env.le(keylet::line(gw1, bob, CK1.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, bob, OF1.currency)) != nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, bob, CK1.currency)) == nullptr); // Delete alice's check since it is no longer needed. env(check::cancel(alice, chkId)); @@ -2182,8 +2085,7 @@ class Check_test : public beast::unit_test::suite IOU const OF2 = gw1["OF2"]; env(offer(gw1, XRP(96), OF2(96))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, OF2.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, OF2.currency)) == nullptr); env(offer(alice, OF2(96), XRP(96))); ++alice.owners; env.close(); @@ -2201,8 +2103,7 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))}; env(check::create(gw1, alice, CK2(96))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, CK2.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, CK2.currency)) == nullptr); env(check::cash(alice, chkId, CK2(96))); ++alice.owners; verifyDeliveredAmount(env, CK2(96)); @@ -2228,8 +2129,7 @@ class Check_test : public beast::unit_test::suite IOU const OF2 = gw1["OF2"]; env(offer(alice, XRP(95), OF2(95))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, OF2.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, OF2.currency)) == nullptr); env(offer(bob, OF2(95), XRP(95))); ++bob.owners; env.close(); @@ -2244,8 +2144,7 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(alice, env.seq(alice))}; env(check::create(alice, bob, CK2(95))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, CK2.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, CK2.currency)) == nullptr); env(check::cash(bob, chkId, CK2(95))); ++bob.owners; verifyDeliveredAmount(env, CK2(95)); @@ -2277,8 +2176,7 @@ class Check_test : public beast::unit_test::suite IOU const OF3 = gw1["OF3"]; env(offer(gw1, XRP(94), OF3(94))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, OF3.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, OF3.currency)) == nullptr); env(offer(alice, OF3(94), XRP(94))); ++alice.owners; env.close(); @@ -2296,8 +2194,7 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))}; env(check::create(gw1, alice, CK3(94))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, CK3.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, CK3.currency)) == nullptr); env(check::cash(alice, chkId, CK3(94))); ++alice.owners; verifyDeliveredAmount(env, CK3(94)); @@ -2323,8 +2220,7 @@ class Check_test : public beast::unit_test::suite IOU const OF3 = gw1["OF3"]; env(offer(alice, XRP(93), OF3(93))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, OF3.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, OF3.currency)) == nullptr); env(offer(bob, OF3(93), XRP(93))); ++bob.owners; env.close(); @@ -2339,8 +2235,7 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(alice, env.seq(alice))}; env(check::create(alice, bob, CK3(93))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, CK3.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, CK3.currency)) == nullptr); env(check::cash(bob, chkId, CK3(93))); ++bob.owners; verifyDeliveredAmount(env, CK3(93)); @@ -2366,8 +2261,7 @@ class Check_test : public beast::unit_test::suite IOU const OF4 = gw1["OF4"]; env(offer(gw1, XRP(92), OF4(92)), ter(tecFROZEN)); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr); env(offer(alice, OF4(92), XRP(92)), ter(tecFROZEN)); env.close(); @@ -2381,8 +2275,7 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(gw1, env.seq(gw1))}; env(check::create(gw1, alice, CK4(92)), ter(tecFROZEN)); env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr); env(check::cash(alice, chkId, CK4(92)), ter(tecNO_ENTRY)); env.close(); @@ -2393,10 +2286,8 @@ class Check_test : public beast::unit_test::suite // Because gw1 has set lsfGlobalFreeze, neither trust line // is created. - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr); - BEAST_EXPECT( - env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, OF4.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, alice, CK4.currency)) == nullptr); } //------------ lsfGlobalFreeze, check written by non-issuer ------------ { @@ -2408,8 +2299,7 @@ class Check_test : public beast::unit_test::suite IOU const OF4 = gw1["OF4"]; env(offer(alice, XRP(91), OF4(91)), ter(tecFROZEN)); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, OF4.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, OF4.currency)) == nullptr); env(offer(bob, OF4(91), XRP(91)), ter(tecFROZEN)); env.close(); @@ -2423,8 +2313,7 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(alice, env.seq(alice))}; env(check::create(alice, bob, CK4(91)), ter(tecFROZEN)); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, CK4.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, CK4.currency)) == nullptr); env(check::cash(bob, chkId, CK4(91)), ter(tecNO_ENTRY)); env.close(); @@ -2435,10 +2324,8 @@ class Check_test : public beast::unit_test::suite // Because gw1 has set lsfGlobalFreeze, neither trust line // is created. - BEAST_EXPECT( - env.le(keylet::line(gw1, bob, OF4.currency)) == nullptr); - BEAST_EXPECT( - env.le(keylet::line(gw1, bob, CK4.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, bob, OF4.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw1, bob, CK4.currency)) == nullptr); } //-------------- lsfRequireAuth, check written by issuer --------------- @@ -2462,8 +2349,7 @@ class Check_test : public beast::unit_test::suite env(offer(gw2, XRP(92), OF5(92))); ++gw2.owners; env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr); env(offer(alice, OF5(92), XRP(92)), ter(tecNO_LINE)); env.close(); @@ -2485,8 +2371,7 @@ class Check_test : public beast::unit_test::suite env(check::create(gw2, alice, CK5(92))); ++gw2.owners; env.close(); - BEAST_EXPECT( - env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr); env(check::cash(alice, chkId, CK5(92)), ter(tecNO_AUTH)); env.close(); @@ -2498,10 +2383,8 @@ class Check_test : public beast::unit_test::suite // Because gw2 has set lsfRequireAuth, neither trust line // is created. - BEAST_EXPECT( - env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr); - BEAST_EXPECT( - env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw2, alice, OF5.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw2, alice, CK5.currency)) == nullptr); // Since we don't need it any more, remove gw2's check. env(check::cancel(gw2, chkId)); @@ -2520,8 +2403,7 @@ class Check_test : public beast::unit_test::suite env(offer(alice, XRP(91), OF5(91)), ter(tecUNFUNDED_OFFER)); env.close(); env(offer(bob, OF5(91), XRP(91)), ter(tecNO_LINE)); - BEAST_EXPECT( - env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr); env.close(); gw2.verifyOwners(__LINE__); @@ -2533,8 +2415,7 @@ class Check_test : public beast::unit_test::suite uint256 const chkId{getCheckIndex(alice, env.seq(alice))}; env(check::create(alice, bob, CK5(91))); env.close(); - BEAST_EXPECT( - env.le(keylet::line(alice, bob, CK5.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(alice, bob, CK5.currency)) == nullptr); env(check::cash(bob, chkId, CK5(91)), ter(tecPATH_PARTIAL)); env.close(); @@ -2549,10 +2430,8 @@ class Check_test : public beast::unit_test::suite // Because gw2 has set lsfRequireAuth, neither trust line // is created. - BEAST_EXPECT( - env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr); - BEAST_EXPECT( - env.le(keylet::line(gw2, bob, CK5.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw2, bob, OF5.currency)) == nullptr); + BEAST_EXPECT(env.le(keylet::line(gw2, bob, CK5.currency)) == nullptr); } } diff --git a/src/test/app/Clawback_test.cpp b/src/test/app/Clawback_test.cpp index c8c4aea757..d169e9e165 100644 --- a/src/test/app/Clawback_test.cpp +++ b/src/test/app/Clawback_test.cpp @@ -250,9 +250,7 @@ class Clawback_test : public beast::unit_test::suite env.require(balance(alice, bob["USD"](-10))); // fails due to invalid flag - env(claw(alice, bob["USD"](5)), - txflags(0x00008000), - ter(temINVALID_FLAG)); + env(claw(alice, bob["USD"](5)), txflags(0x00008000), ter(temINVALID_FLAG)); env.close(); // fails due to negative amount diff --git a/src/test/app/Credentials_test.cpp b/src/test/app/Credentials_test.cpp index 7de34e05a1..31c867c24d 100644 --- a/src/test/app/Credentials_test.cpp +++ b/src/test/app/Credentials_test.cpp @@ -39,8 +39,7 @@ struct Credentials_test : public beast::unit_test::suite env.close(); // Test Create credentials - env(credentials::create(subject, issuer, credType), - credentials::uri(uri)); + env(credentials::create(subject, issuer, credType), credentials::uri(uri)); env.close(); { auto const sleCred = env.le(credKey); @@ -55,21 +54,14 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(!ownerCount(env, subject)); BEAST_EXPECT(checkVL(sleCred, sfCredentialType, credType)); BEAST_EXPECT(checkVL(sleCred, sfURI, uri)); - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember("LedgerEntryType") && - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Credential && - jle[jss::result][jss::node][jss::Issuer] == - issuer.human() && - jle[jss::result][jss::node][jss::Subject] == - subject.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType))); + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && + jle[jss::result].isMember(jss::node) && jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && + jle[jss::result][jss::node][jss::Issuer] == issuer.human() && + jle[jss::result][jss::node][jss::Subject] == subject.human() && + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType))); } env(credentials::accept(subject, issuer, credType)); @@ -99,11 +91,9 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(!ownerCount(env, subject)); // check no credential exists anymore - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } } @@ -113,8 +103,7 @@ struct Credentials_test : public beast::unit_test::suite auto const credKey = credentials::keylet(issuer, issuer, credType); - env(credentials::create(issuer, issuer, credType), - credentials::uri(uri)); + env(credentials::create(issuer, issuer, credType), credentials::uri(uri)); env.close(); { auto const sleCred = env.le(credKey); @@ -125,27 +114,18 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(sleCred->getAccountID(sfSubject) == issuer.id()); BEAST_EXPECT(sleCred->getAccountID(sfIssuer) == issuer.id()); BEAST_EXPECT((sleCred->getFieldU32(sfFlags) & lsfAccepted)); - BEAST_EXPECT( - sleCred->getFieldU64(sfIssuerNode) == - sleCred->getFieldU64(sfSubjectNode)); + BEAST_EXPECT(sleCred->getFieldU64(sfIssuerNode) == sleCred->getFieldU64(sfSubjectNode)); BEAST_EXPECT(ownerCount(env, issuer) == 1); BEAST_EXPECT(checkVL(sleCred, sfCredentialType, credType)); BEAST_EXPECT(checkVL(sleCred, sfURI, uri)); - auto const jle = - credentials::ledgerEntry(env, issuer, issuer, credType); + auto const jle = credentials::ledgerEntry(env, issuer, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember("LedgerEntryType") && - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Credential && - jle[jss::result][jss::node][jss::Issuer] == - issuer.human() && - jle[jss::result][jss::node][jss::Subject] == - issuer.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType))); + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && + jle[jss::result].isMember(jss::node) && jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && + jle[jss::result][jss::node][jss::Issuer] == issuer.human() && + jle[jss::result][jss::node][jss::Subject] == issuer.human() && + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType))); } env(credentials::deleteCred(issuer, issuer, issuer, credType)); @@ -155,11 +135,9 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(!ownerCount(env, issuer)); // check no credential exists anymore - auto const jle = - credentials::ledgerEntry(env, issuer, issuer, credType); + auto const jle = credentials::ledgerEntry(env, issuer, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } } @@ -205,11 +183,9 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(!ownerCount(env, subject)); // check no credential exists anymore - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } @@ -243,11 +219,9 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(!ownerCount(env, subject)); // check no credential exists anymore - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } @@ -279,11 +253,9 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(!ownerCount(env, issuer)); // check no credential exists anymore - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } @@ -317,11 +289,9 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(!ownerCount(env, issuer)); // check no credential exists anymore - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } @@ -335,10 +305,7 @@ struct Credentials_test : public beast::unit_test::suite auto const credKey = credentials::keylet(subject, issuer, credType); auto jv = credentials::create(subject, issuer, credType); - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count(); + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count(); jv[sfExpiration.jsonName] = t + 20; env(jv); @@ -358,11 +325,9 @@ struct Credentials_test : public beast::unit_test::suite BEAST_EXPECT(!ownerCount(env, subject)); // check no credential exists anymore - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } } @@ -377,16 +342,13 @@ struct Credentials_test : public beast::unit_test::suite env(credentials::deleteCred(subject, subject, issuer, credType)); env.close(); { - auto const credKey = - credentials::keylet(subject, issuer, credType); + auto const credKey = credentials::keylet(subject, issuer, credType); BEAST_EXPECT(!env.le(credKey)); BEAST_EXPECT(!ownerCount(env, subject)); BEAST_EXPECT(!ownerCount(env, issuer)); - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } } @@ -399,16 +361,13 @@ struct Credentials_test : public beast::unit_test::suite env(credentials::deleteCred(issuer, subject, issuer, credType)); env.close(); { - auto const credKey = - credentials::keylet(subject, issuer, credType); + auto const credKey = credentials::keylet(subject, issuer, credType); BEAST_EXPECT(!env.le(credKey)); BEAST_EXPECT(!ownerCount(env, subject)); BEAST_EXPECT(!ownerCount(env, issuer)); - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && jle[jss::result].isMember(jss::error) && jle[jss::result][jss::error] == "entryNotFound"); } } @@ -481,27 +440,19 @@ struct Credentials_test : public beast::unit_test::suite "WULE" "fv28o37gfwEFB3872TFO8GSDSDVD"; static_assert(longURI.size() > maxCredentialURILength); - env(credentials::create(subject, issuer, credType), - credentials::uri(longURI), - ter(temMALFORMED)); + env(credentials::create(subject, issuer, credType), credentials::uri(longURI), ter(temMALFORMED)); } { testcase("Credentials fail, URI empty."); - env(credentials::create(subject, issuer, credType), - credentials::uri(""), - ter(temMALFORMED)); + env(credentials::create(subject, issuer, credType), credentials::uri(""), ter(temMALFORMED)); } { testcase("Credentials fail, expiration in the past."); auto jv = credentials::create(subject, issuer, credType); // current time in ripple epoch - 1s - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() - - 1; + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count() - 1; jv[sfExpiration.jsonName] = t; env(jv, ter(tecEXPIRED)); } @@ -523,21 +474,14 @@ struct Credentials_test : public beast::unit_test::suite env.close(); // check credential still present - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember("LedgerEntryType") && - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Credential && - jle[jss::result][jss::node][jss::Issuer] == - issuer.human() && - jle[jss::result][jss::node][jss::Subject] == - subject.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType))); + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && + jle[jss::result].isMember(jss::node) && jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && + jle[jss::result][jss::node][jss::Issuer] == issuer.human() && + jle[jss::result][jss::node][jss::Subject] == subject.human() && + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType))); } { @@ -548,10 +492,7 @@ struct Credentials_test : public beast::unit_test::suite // Everything below can only be tested on open ledger. auto const res1 = directory::bumpLastPage( - env, - directory::maximumPageIndex(env), - keylet::ownerDir(issuer.id()), - directory::adjustOwnerNode); + env, directory::maximumPageIndex(env), keylet::ownerDir(issuer.id()), directory::adjustOwnerNode); BEAST_EXPECT(res1); auto const jv = credentials::create(issuer, subject, credType); @@ -562,10 +503,7 @@ struct Credentials_test : public beast::unit_test::suite // Fill subject directory env(ticket::create(subject, 63)); auto const res2 = directory::bumpLastPage( - env, - directory::maximumPageIndex(env), - keylet::ownerDir(subject.id()), - directory::adjustOwnerNode); + env, directory::maximumPageIndex(env), keylet::ownerDir(subject.id()), directory::adjustOwnerNode); BEAST_EXPECT(res2); env(jv, ter(tecDIR_FULL)); @@ -622,8 +560,7 @@ struct Credentials_test : public beast::unit_test::suite { testcase("CredentialsAccept fail, Credential doesn't exist."); - env(credentials::accept(subject, issuer, credType), - ter(tecNO_ENTRY)); + env(credentials::accept(subject, issuer, credType), ter(tecNO_ENTRY)); env.close(); } @@ -636,8 +573,7 @@ struct Credentials_test : public beast::unit_test::suite } { - testcase( - "CredentialsAccept fail, invalid credentialType param."); + testcase("CredentialsAccept fail, invalid credentialType param."); auto jv = credentials::accept(subject, issuer, ""); env(jv, ter(temMALFORMED)); } @@ -655,26 +591,18 @@ struct Credentials_test : public beast::unit_test::suite env(credentials::create(subject, issuer, credType)); env.close(); - env(credentials::accept(subject, issuer, credType), - ter(tecINSUFFICIENT_RESERVE)); + env(credentials::accept(subject, issuer, credType), ter(tecINSUFFICIENT_RESERVE)); env.close(); // check credential still present - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember("LedgerEntryType") && - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Credential && - jle[jss::result][jss::node][jss::Issuer] == - issuer.human() && - jle[jss::result][jss::node][jss::Subject] == - subject.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType))); + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && + jle[jss::result].isMember(jss::node) && jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && + jle[jss::result][jss::node][jss::Issuer] == issuer.human() && + jle[jss::result][jss::node][jss::Subject] == subject.human() && + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType))); } } @@ -697,26 +625,18 @@ struct Credentials_test : public beast::unit_test::suite testcase("CredentialsAccept fail, lsfAccepted already set."); env(credentials::accept(subject, issuer, credType)); env.close(); - env(credentials::accept(subject, issuer, credType), - ter(tecDUPLICATE)); + env(credentials::accept(subject, issuer, credType), ter(tecDUPLICATE)); env.close(); // check credential still present - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember("LedgerEntryType") && - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Credential && - jle[jss::result][jss::node][jss::Issuer] == - issuer.human() && - jle[jss::result][jss::node][jss::Subject] == - subject.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType))); + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && + jle[jss::result].isMember(jss::node) && jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && + jle[jss::result][jss::node][jss::Issuer] == issuer.human() && + jle[jss::result][jss::node][jss::Subject] == subject.human() && + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType))); } { @@ -724,26 +644,20 @@ struct Credentials_test : public beast::unit_test::suite testcase("CredentialsAccept fail, expired credentials."); auto jv = credentials::create(subject, issuer, credType2); - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count(); + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count(); jv[sfExpiration.jsonName] = t; env(jv); env.close(); // credentials are expired now - env(credentials::accept(subject, issuer, credType2), - ter(tecEXPIRED)); + env(credentials::accept(subject, issuer, credType2), ter(tecEXPIRED)); env.close(); // check that expired credentials were deleted - auto const jDelCred = - credentials::ledgerEntry(env, subject, issuer, credType2); + auto const jDelCred = credentials::ledgerEntry(env, subject, issuer, credType2); BEAST_EXPECT( jDelCred.isObject() && jDelCred.isMember(jss::result) && - jDelCred[jss::result].isMember(jss::error) && - jDelCred[jss::result][jss::error] == "entryNotFound"); + jDelCred[jss::result].isMember(jss::error) && jDelCred[jss::result][jss::error] == "entryNotFound"); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, subject) == 1); @@ -776,12 +690,10 @@ struct Credentials_test : public beast::unit_test::suite env.close(); // check that expired credentials were deleted - auto const jDelCred = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jDelCred = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( jDelCred.isObject() && jDelCred.isMember(jss::result) && - jDelCred[jss::result].isMember(jss::error) && - jDelCred[jss::result][jss::error] == "entryNotFound"); + jDelCred[jss::result].isMember(jss::error) && jDelCred[jss::result][jss::error] == "entryNotFound"); } } } @@ -805,15 +717,13 @@ struct Credentials_test : public beast::unit_test::suite { testcase("CredentialsDelete fail, no Credentials."); - env(credentials::deleteCred(subject, subject, issuer, credType), - ter(tecNO_ENTRY)); + env(credentials::deleteCred(subject, subject, issuer, credType), ter(tecNO_ENTRY)); env.close(); } { testcase("CredentialsDelete fail, invalid Subject account."); - auto jv = - credentials::deleteCred(subject, subject, issuer, credType); + auto jv = credentials::deleteCred(subject, subject, issuer, credType); jv[jss::Subject] = to_string(xrpAccount()); env(jv, ter(temINVALID_ACCOUNT_ID)); env.close(); @@ -821,16 +731,14 @@ struct Credentials_test : public beast::unit_test::suite { testcase("CredentialsDelete fail, invalid Issuer account."); - auto jv = - credentials::deleteCred(subject, subject, issuer, credType); + auto jv = credentials::deleteCred(subject, subject, issuer, credType); jv[jss::Issuer] = to_string(xrpAccount()); env(jv, ter(temINVALID_ACCOUNT_ID)); env.close(); } { - testcase( - "CredentialsDelete fail, invalid credentialType param."); + testcase("CredentialsDelete fail, invalid credentialType param."); auto jv = credentials::deleteCred(subject, subject, issuer, ""); env(jv, ter(temMALFORMED)); } @@ -842,26 +750,18 @@ struct Credentials_test : public beast::unit_test::suite env.close(); // Other account can't delete credentials without expiration - env(credentials::deleteCred(other, subject, issuer, credType2), - ter(tecNO_PERMISSION)); + env(credentials::deleteCred(other, subject, issuer, credType2), ter(tecNO_PERMISSION)); env.close(); // check credential still present - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType2); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType2); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember("LedgerEntryType") && - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Credential && - jle[jss::result][jss::node][jss::Issuer] == - issuer.human() && - jle[jss::result][jss::node][jss::Subject] == - subject.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType2))); + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && + jle[jss::result].isMember(jss::node) && jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && + jle[jss::result][jss::node][jss::Issuer] == issuer.human() && + jle[jss::result][jss::node][jss::Subject] == subject.human() && + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType2))); } { @@ -869,43 +769,30 @@ struct Credentials_test : public beast::unit_test::suite auto jv = credentials::create(subject, issuer, credType); // current time in ripple epoch + 1000s - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() + - 1000; + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count() + 1000; jv[sfExpiration.jsonName] = t; env(jv); env.close(); // Other account can't delete credentials that not expired - env(credentials::deleteCred(other, subject, issuer, credType), - ter(tecNO_PERMISSION)); + env(credentials::deleteCred(other, subject, issuer, credType), ter(tecNO_PERMISSION)); env.close(); // check credential still present - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember("LedgerEntryType") && - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Credential && - jle[jss::result][jss::node][jss::Issuer] == - issuer.human() && - jle[jss::result][jss::node][jss::Subject] == - subject.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType))); + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && + jle[jss::result].isMember(jss::node) && jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && + jle[jss::result][jss::node][jss::Issuer] == issuer.human() && + jle[jss::result][jss::node][jss::Subject] == subject.human() && + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType))); } { testcase("CredentialsDelete fail, no Issuer and Subject."); - auto jv = - credentials::deleteCred(subject, subject, issuer, credType); + auto jv = credentials::deleteCred(subject, subject, issuer, credType); jv.removeMember(jss::Subject); jv.removeMember(jss::Issuer); env(jv, ter(temMALFORMED)); @@ -915,8 +802,7 @@ struct Credentials_test : public beast::unit_test::suite { testcase("CredentialsDelete fail, invalid fee."); - auto jv = - credentials::deleteCred(subject, subject, issuer, credType); + auto jv = credentials::deleteCred(subject, subject, issuer, credType); jv[jss::Fee] = -1; env(jv, ter(temBAD_FEE)); env.close(); @@ -924,8 +810,7 @@ struct Credentials_test : public beast::unit_test::suite { testcase("deleteSLE fail, bad SLE."); - auto view = std::make_shared( - env.current().get(), ApplyFlags::tapNONE); + auto view = std::make_shared(env.current().get(), ApplyFlags::tapNONE); auto ter = xrpl::credentials::deleteSLE(*view, {}, env.journal); BEAST_EXPECT(ter == tecNO_ENTRY); } @@ -950,12 +835,9 @@ struct Credentials_test : public beast::unit_test::suite { testcase("Credentials fail, Feature is not enabled."); - env(credentials::create(subject, issuer, credType), - ter(temDISABLED)); - env(credentials::accept(subject, issuer, credType), - ter(temDISABLED)); - env(credentials::deleteCred(subject, subject, issuer, credType), - ter(temDISABLED)); + env(credentials::create(subject, issuer, credType), ter(temDISABLED)); + env(credentials::accept(subject, issuer, credType), ter(temDISABLED)); + env(credentials::deleteCred(subject, subject, issuer, credType), ter(temDISABLED)); } } } @@ -988,16 +870,13 @@ struct Credentials_test : public beast::unit_test::suite { Json::Value params; params[jss::account] = subject.human(); - auto const jv = env.rpc( - "json", "account_tx", to_string(params))[jss::result]; + auto const jv = env.rpc("json", "account_tx", to_string(params))[jss::result]; BEAST_EXPECT(jv[jss::transactions].size() == 4); auto const& tx0(jv[jss::transactions][0u][jss::tx]); - BEAST_EXPECT( - tx0[jss::TransactionType] == jss::CredentialAccept); + BEAST_EXPECT(tx0[jss::TransactionType] == jss::CredentialAccept); auto const& tx1(jv[jss::transactions][1u][jss::tx]); - BEAST_EXPECT( - tx1[jss::TransactionType] == jss::CredentialCreate); + BEAST_EXPECT(tx1[jss::TransactionType] == jss::CredentialCreate); txHash0 = tx0[jss::hash].asString(); txHash1 = tx1[jss::hash].asString(); } @@ -1005,16 +884,13 @@ struct Credentials_test : public beast::unit_test::suite { Json::Value params; params[jss::account] = issuer.human(); - auto const jv = env.rpc( - "json", "account_tx", to_string(params))[jss::result]; + auto const jv = env.rpc("json", "account_tx", to_string(params))[jss::result]; BEAST_EXPECT(jv[jss::transactions].size() == 4); auto const& tx0(jv[jss::transactions][0u][jss::tx]); - BEAST_EXPECT( - tx0[jss::TransactionType] == jss::CredentialAccept); + BEAST_EXPECT(tx0[jss::TransactionType] == jss::CredentialAccept); auto const& tx1(jv[jss::transactions][1u][jss::tx]); - BEAST_EXPECT( - tx1[jss::TransactionType] == jss::CredentialCreate); + BEAST_EXPECT(tx1[jss::TransactionType] == jss::CredentialCreate); BEAST_EXPECT(txHash0 == tx0[jss::hash].asString()); BEAST_EXPECT(txHash1 == tx1[jss::hash].asString()); @@ -1025,28 +901,24 @@ struct Credentials_test : public beast::unit_test::suite { Json::Value params; params[jss::account] = subject.human(); - auto jv = env.rpc( - "json", "account_objects", to_string(params))[jss::result]; + auto jv = env.rpc("json", "account_objects", to_string(params))[jss::result]; BEAST_EXPECT(jv[jss::account_objects].size() == 1); auto const& object(jv[jss::account_objects][0u]); - BEAST_EXPECT( - object["LedgerEntryType"].asString() == jss::Credential); + BEAST_EXPECT(object["LedgerEntryType"].asString() == jss::Credential); objectIdx = object[jss::index].asString(); } { Json::Value params; params[jss::account] = issuer.human(); - auto jv = env.rpc( - "json", "account_objects", to_string(params))[jss::result]; + auto jv = env.rpc("json", "account_objects", to_string(params))[jss::result]; BEAST_EXPECT(jv[jss::account_objects].size() == 1); auto const& object(jv[jss::account_objects][0u]); - BEAST_EXPECT( - object["LedgerEntryType"].asString() == jss::Credential); + BEAST_EXPECT(object["LedgerEntryType"].asString() == jss::Credential); BEAST_EXPECT(objectIdx == object[jss::index].asString()); } } @@ -1058,9 +930,7 @@ struct Credentials_test : public beast::unit_test::suite using namespace test::jtx; bool const enabled = features[fixInvalidTxFlags]; - testcase( - std::string("Test flag, fix ") + - (enabled ? "enabled" : "disabled")); + testcase(std::string("Test flag, fix ") + (enabled ? "enabled" : "disabled")); char const credType[] = "abcde"; Account const issuer{"issuer"}; @@ -1074,17 +944,10 @@ struct Credentials_test : public beast::unit_test::suite env.close(); { - ter const expected( - enabled ? TER(temINVALID_FLAG) : TER(tesSUCCESS)); - env(credentials::create(subject, issuer, credType), - txflags(tfTransferable), - expected); - env(credentials::accept(subject, issuer, credType), - txflags(tfSellNFToken), - expected); - env(credentials::deleteCred(subject, subject, issuer, credType), - txflags(tfPassive), - expected); + ter const expected(enabled ? TER(temINVALID_FLAG) : TER(tesSUCCESS)); + env(credentials::create(subject, issuer, credType), txflags(tfTransferable), expected); + env(credentials::accept(subject, issuer, credType), txflags(tfSellNFToken), expected); + env(credentials::deleteCred(subject, subject, issuer, credType), txflags(tfPassive), expected); } } } diff --git a/src/test/app/CrossingLimits_test.cpp b/src/test/app/CrossingLimits_test.cpp index 8c11dd6737..e1974adee1 100644 --- a/src/test/app/CrossingLimits_test.cpp +++ b/src/test/app/CrossingLimits_test.cpp @@ -283,8 +283,7 @@ public: // best quality n_offers(env, 2000, alice, EUR(2), XRP(1)); n_offers(env, 100, alice, XRP(1), USD(4)); - n_offers( - env, 801, carol, XRP(1), USD(3)); // only one offer is funded + n_offers(env, 801, carol, XRP(1), USD(3)); // only one offer is funded n_offers(env, 1000, alice, XRP(1), USD(3)); n_offers(env, 1, alice, EUR(500), USD(500)); @@ -341,8 +340,7 @@ public: env.require(balance(alice, USD(2503))); env.require(balance(alice, EUR(1100))); - auto const numAOffers = - 2000 + 100 + 1000 + 1 - (2 * 100 + 2 * 199 + 1 + 1); + auto const numAOffers = 2000 + 100 + 1000 + 1 - (2 * 100 + 2 * 199 + 1 + 1); env.require(offers(alice, numAOffers)); env.require(owners(alice, numAOffers + 2)); @@ -363,8 +361,7 @@ public: n_offers(env, 1, alice, EUR(1), USD(10)); n_offers(env, 2000, alice, EUR(2), XRP(1)); n_offers(env, 100, alice, XRP(1), USD(4)); - n_offers( - env, 801, carol, XRP(1), USD(3)); // only one offer is funded + n_offers(env, 801, carol, XRP(1), USD(3)); // only one offer is funded n_offers(env, 1000, alice, XRP(1), USD(3)); n_offers(env, 1, alice, EUR(499), USD(499)); @@ -414,8 +411,7 @@ public: env.require(balance(alice, USD(2494))); env.require(balance(alice, EUR(1100))); - auto const numAOffers = - 1 + 2000 + 100 + 1000 + 1 - (1 + 2 * 100 + 2 * 199 + 1 + 1); + auto const numAOffers = 1 + 2000 + 100 + 1000 + 1 - (1 + 2 * 100 + 2 * 199 + 1 + 1); env.require(offers(alice, numAOffers)); env.require(owners(alice, numAOffers + 2)); diff --git a/src/test/app/DID_test.cpp b/src/test/app/DID_test.cpp index e7adfee178..f83571deab 100644 --- a/src/test/app/DID_test.cpp +++ b/src/test/app/DID_test.cpp @@ -60,9 +60,7 @@ struct DID_test : public beast::unit_test::suite // Pay alice almost enough to make the reserve for a DID. env(pay(env.master, alice, drops(incReserve + 2 * baseFee - 1))); - BEAST_EXPECT( - env.balance(alice) == - acctReserve + incReserve + drops(baseFee - 1)); + BEAST_EXPECT(env.balance(alice) == acctReserve + incReserve + drops(baseFee - 1)); env.close(); // alice still does not have enough XRP for the reserve of a DID. @@ -113,11 +111,7 @@ struct DID_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, alice) == 0); // all empty fields - env(did::set(alice), - did::uri(""), - did::document(""), - did::data(""), - ter(temEMPTY_DID)); + env(did::set(alice), did::uri(""), did::document(""), did::data(""), ter(temEMPTY_DID)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); @@ -133,19 +127,14 @@ struct DID_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, alice) == 0); // attestation is too long - env(did::set(alice), - did::document("data"), - did::data(longString), - ter(temMALFORMED)); + env(did::set(alice), did::document("data"), did::data(longString), ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); // some empty fields, some optional fields // pre-fix amendment auto const fixEnabled = env.current()->rules().enabled(fixEmptyDID); - env(did::set(alice), - did::uri(""), - fixEnabled ? ter(tecEMPTY_DID) : ter(tesSUCCESS)); + env(did::set(alice), did::uri(""), fixEnabled ? ter(tecEMPTY_DID) : ter(tesSUCCESS)); env.close(); auto const expectedOwnerReserve = fixEnabled ? 0 : 1; BEAST_EXPECT(ownerCount(env, alice) == expectedOwnerReserve); @@ -231,10 +220,7 @@ struct DID_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, francis) == 1); // URI + DIDDocument + Data - env(did::set(george), - did::uri("uri"), - did::document("data"), - did::data("attest")); + env(did::set(george), did::uri("uri"), did::document("data"), did::data("attest")); BEAST_EXPECT(ownerCount(env, george) == 1); } diff --git a/src/test/app/DNS_test.cpp b/src/test/app/DNS_test.cpp index fc6917e15c..0d41c0f419 100644 --- a/src/test/app/DNS_test.cpp +++ b/src/test/app/DNS_test.cpp @@ -31,14 +31,13 @@ public: void makeRequest(endpoint_type const& lastEndpoint, bool lastStatus) { - auto onFetch = [&](error_code const& errorCode, - endpoint_type const& endpoint, - xrpl::detail::response_type&& resp) { - BEAST_EXPECT(!errorCode); - lastEndpoint_ = endpoint; - resolved_[endpoint.address().to_string()]++; - cv_.notify_all(); - }; + auto onFetch = + [&](error_code const& errorCode, endpoint_type const& endpoint, xrpl::detail::response_type&& resp) { + BEAST_EXPECT(!errorCode); + lastEndpoint_ = endpoint; + resolved_[endpoint.address().to_string()]++; + cv_.notify_all(); + }; auto sp = std::make_shared( pUrl_.domain, @@ -92,8 +91,7 @@ public: for (int i = 1; i <= 4; ++i) { makeRequest(lastEndpoint_, true); - BEAST_EXPECT( - resolved_.size() == 1 && resolved_.begin()->second == i); + BEAST_EXPECT(resolved_.size() == 1 && resolved_.begin()->second == i); } if (!isMultipleEndpoints()) return; diff --git a/src/test/app/Delegate_test.cpp b/src/test/app/Delegate_test.cpp index 4039f60ef0..2207c83148 100644 --- a/src/test/app/Delegate_test.cpp +++ b/src/test/app/Delegate_test.cpp @@ -22,8 +22,7 @@ class Delegate_test : public beast::unit_test::suite env.fund(XRP(1000000), gw, alice, bob); env.close(); - auto res = features[featurePermissionDelegationV1_1] ? ter(tesSUCCESS) - : ter(temDISABLED); + auto res = features[featurePermissionDelegationV1_1] ? ter(tesSUCCESS) : ter(temDISABLED); // can not set Delegate when feature disabled env(delegate::set(gw, alice, {"Payment"}), res); @@ -52,61 +51,42 @@ class Delegate_test : public beast::unit_test::suite auto const entry = delegate::entry(env, gw, alice); BEAST_EXPECT(entry[jss::result][jss::error] == "entryNotFound"); - auto const permissions = std::vector{ - "Payment", - "EscrowCreate", - "EscrowFinish", - "TrustlineAuthorize", - "CheckCreate"}; + auto const permissions = + std::vector{"Payment", "EscrowCreate", "EscrowFinish", "TrustlineAuthorize", "CheckCreate"}; env(delegate::set(gw, alice, permissions)); env.close(); // this lambda function is used to compare the json value of ledger // entry response with the given vector of permissions. - auto comparePermissions = - [&](Json::Value const& jle, - std::vector const& permissions, - Account const& account, - Account const& authorize) { - BEAST_EXPECT( - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node)); - BEAST_EXPECT( - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Delegate); - BEAST_EXPECT( - jle[jss::result][jss::node][jss::Account] == - account.human()); - BEAST_EXPECT( - jle[jss::result][jss::node][sfAuthorize.jsonName] == - authorize.human()); + auto comparePermissions = [&](Json::Value const& jle, + std::vector const& permissions, + Account const& account, + Account const& authorize) { + BEAST_EXPECT(!jle[jss::result].isMember(jss::error) && jle[jss::result].isMember(jss::node)); + BEAST_EXPECT(jle[jss::result][jss::node]["LedgerEntryType"] == jss::Delegate); + BEAST_EXPECT(jle[jss::result][jss::node][jss::Account] == account.human()); + BEAST_EXPECT(jle[jss::result][jss::node][sfAuthorize.jsonName] == authorize.human()); - auto const& jPermissions = - jle[jss::result][jss::node][sfPermissions.jsonName]; - unsigned i = 0; - for (auto const& permission : permissions) - { - BEAST_EXPECT( - jPermissions[i][sfPermission.jsonName] - [sfPermissionValue.jsonName] == permission); - i++; - } - }; + auto const& jPermissions = jle[jss::result][jss::node][sfPermissions.jsonName]; + unsigned i = 0; + for (auto const& permission : permissions) + { + BEAST_EXPECT(jPermissions[i][sfPermission.jsonName][sfPermissionValue.jsonName] == permission); + i++; + } + }; // get ledger entry with valid parameter - comparePermissions( - delegate::entry(env, gw, alice), permissions, gw, alice); + comparePermissions(delegate::entry(env, gw, alice), permissions, gw, alice); // gw updates permission - auto const newPermissions = std::vector{ - "Payment", "AMMCreate", "AMMDeposit", "AMMWithdraw"}; + auto const newPermissions = std::vector{"Payment", "AMMCreate", "AMMDeposit", "AMMWithdraw"}; env(delegate::set(gw, alice, newPermissions)); env.close(); // get ledger entry again, permissions should be updated to // newPermissions - comparePermissions( - delegate::entry(env, gw, alice), newPermissions, gw, alice); + comparePermissions(delegate::entry(env, gw, alice), newPermissions, gw, alice); // gw deletes all permissions delegated to alice, this will delete // the @@ -119,8 +99,7 @@ class Delegate_test : public beast::unit_test::suite // alice can delegate permissions to gw as well env(delegate::set(alice, gw, permissions)); env.close(); - comparePermissions( - delegate::entry(env, alice, gw), permissions, alice, gw); + comparePermissions(delegate::entry(env, alice, gw), permissions, alice, gw); auto const response = delegate::entry(env, gw, alice); // alice has not been granted any permissions by gw BEAST_EXPECT(response[jss::result][jss::error] == "entryNotFound"); @@ -199,8 +178,7 @@ class Delegate_test : public beast::unit_test::suite // when authorizing account which does not exist, should return // tecNO_TARGET { - env(delegate::set(gw, Account("unknown"), {"Payment"}), - ter(tecNO_TARGET)); + env(delegate::set(gw, Account("unknown"), {"Payment"}), ter(tecNO_TARGET)); } // non-delegable transaction @@ -209,8 +187,7 @@ class Delegate_test : public beast::unit_test::suite env(delegate::set(gw, alice, {"AccountSet"}), ter(temMALFORMED)); env(delegate::set(gw, alice, {"SignerListSet"}), ter(temMALFORMED)); env(delegate::set(gw, alice, {"DelegateSet"}), ter(temMALFORMED)); - env(delegate::set(gw, alice, {"EnableAmendment"}), - ter(temMALFORMED)); + env(delegate::set(gw, alice, {"EnableAmendment"}), ter(temMALFORMED)); env(delegate::set(gw, alice, {"UNLModify"}), ter(temMALFORMED)); env(delegate::set(gw, alice, {"SetFee"}), ter(temMALFORMED)); env(delegate::set(gw, alice, {"Batch"}), ter(temMALFORMED)); @@ -231,13 +208,11 @@ class Delegate_test : public beast::unit_test::suite Account carol{"carol"}; env.fund(drops(env.current()->fees().accountReserve(0)), alice); - env.fund( - drops(env.current()->fees().accountReserve(1)), bob, carol); + env.fund(drops(env.current()->fees().accountReserve(1)), bob, carol); env.close(); // alice does not have enough reserve to create Delegate - env(delegate::set(alice, bob, {"Payment"}), - ter(tecINSUFFICIENT_RESERVE)); + env(delegate::set(alice, bob, {"Payment"}), ter(tecINSUFFICIENT_RESERVE)); // bob has enough reserve env(delegate::set(bob, alice, {"Payment"})); @@ -245,8 +220,7 @@ class Delegate_test : public beast::unit_test::suite // now bob create another Delegate, he does not have // enough reserve - env(delegate::set(bob, carol, {"Payment"}), - ter(tecINSUFFICIENT_RESERVE)); + env(delegate::set(bob, carol, {"Payment"}), ter(tecINSUFFICIENT_RESERVE)); } // test reserve when sending transaction on behalf of other account @@ -265,10 +239,7 @@ class Delegate_test : public beast::unit_test::suite // bob set DID on behalf of alice, but alice does not have enough // reserve - env(did::set(alice), - did::uri("uri"), - delegate::as(bob), - ter(tecINSUFFICIENT_RESERVE)); + env(did::set(alice), did::uri("uri"), delegate::as(bob), ter(tecINSUFFICIENT_RESERVE)); // bob can set DID for himself because he has enough reserve env(did::set(bob), did::uri("uri")); @@ -295,10 +266,7 @@ class Delegate_test : public beast::unit_test::suite auto bobBalance = env.balance(bob); auto carolBalance = env.balance(carol); - env(pay(alice, carol, XRP(100)), - fee(XRP(2000)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(pay(alice, carol, XRP(100)), fee(XRP(2000)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); BEAST_EXPECT(env.balance(alice) == aliceBalance); BEAST_EXPECT(env.balance(bob) == bobBalance); @@ -329,10 +297,7 @@ class Delegate_test : public beast::unit_test::suite auto bobBalance = env.balance(bob); auto carolBalance = env.balance(carol); - env(pay(alice, carol, XRP(100)), - fee(XRP(2000)), - delegate::as(bob), - ter(terINSUF_FEE_B)); + env(pay(alice, carol, XRP(100)), fee(XRP(2000)), delegate::as(bob), ter(terINSUF_FEE_B)); env.close(); BEAST_EXPECT(env.balance(alice) == aliceBalance); BEAST_EXPECT(env.balance(bob) == bobBalance); @@ -347,10 +312,7 @@ class Delegate_test : public beast::unit_test::suite auto carolBalance = env.balance(carol); auto const feeAmt = XRP(10); - env(pay(alice, carol, XRP(20000)), - fee(feeAmt), - delegate::as(bob), - ter(tecUNFUNDED_PAYMENT)); + env(pay(alice, carol, XRP(20000)), fee(feeAmt), delegate::as(bob), ter(tecUNFUNDED_PAYMENT)); env.close(); BEAST_EXPECT(env.balance(alice) == aliceBalance); BEAST_EXPECT(env.balance(bob) == bobBalance - feeAmt); @@ -425,8 +387,7 @@ class Delegate_test : public beast::unit_test::suite env(delegate::set(alice, bob, {"Payment"})); env.close(); - BEAST_EXPECT( - env.closed()->exists(keylet::delegate(alice.id(), bob.id()))); + BEAST_EXPECT(env.closed()->exists(keylet::delegate(alice.id(), bob.id()))); for (std::uint32_t i = 0; i < 256; ++i) env.close(); @@ -443,8 +404,7 @@ class Delegate_test : public beast::unit_test::suite BEAST_EXPECT(!env.closed()->exists(keylet::ownerDir(alice.id()))); BEAST_EXPECT(env.balance(bob) == bobBalance + aliceBalance - deleteFee); - BEAST_EXPECT( - !env.closed()->exists(keylet::delegate(alice.id(), bob.id()))); + BEAST_EXPECT(!env.closed()->exists(keylet::delegate(alice.id(), bob.id()))); } void @@ -503,14 +463,10 @@ class Delegate_test : public beast::unit_test::suite env.close(); // bob does not have permission to create check - env(check::create(alice, bob, XRP(10)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(check::create(alice, bob, XRP(10)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // carol does not have permission to create check - env(check::create(alice, bob, XRP(10)), - delegate::as(carol), - ter(terNO_DELEGATE_PERMISSION)); + env(check::create(alice, bob, XRP(10)), delegate::as(carol), ter(terNO_DELEGATE_PERMISSION)); } void @@ -543,9 +499,7 @@ class Delegate_test : public beast::unit_test::suite auto gw2Balance = env.balance(gw2, XRP); // delegate ledger object is not created yet - env(pay(gw, alice, USD(50)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(pay(gw, alice, USD(50)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.require(balance(bob, bobBalance)); // gw gives bob burn permission @@ -555,9 +509,7 @@ class Delegate_test : public beast::unit_test::suite gwBalance = env.balance(gw, XRP); // bob sends a payment transaction on behalf of gw - env(pay(gw, alice, USD(50)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(pay(gw, alice, USD(50)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); env.require(balance(bob, bobBalance)); @@ -571,9 +523,7 @@ class Delegate_test : public beast::unit_test::suite gwBalance = env.balance(gw, XRP); // can not send XRP - env(pay(gw, alice, XRP(50)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(pay(gw, alice, XRP(50)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); env.require(balance(bob, bobBalance)); @@ -658,9 +608,7 @@ class Delegate_test : public beast::unit_test::suite // bob can not mint on behalf of gw because he only has burn // permission - env(pay(gw, alice, USD(50)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(pay(gw, alice, USD(50)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); env.require(balance(bob, bobBalance)); @@ -767,8 +715,7 @@ class Delegate_test : public beast::unit_test::suite Account const gw{"gateway"}; MPTTester mpt(env, gw, {.holders = {alice, bob}}); - mpt.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); + mpt.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); mpt.authorize({.account = alice}); mpt.authorize({.account = bob}); @@ -804,8 +751,7 @@ class Delegate_test : public beast::unit_test::suite // Grant both granular permissions and tx level permission. { - env(delegate::set( - alice, bob, {"PaymentBurn", "PaymentMint", "Payment"})); + env(delegate::set(alice, bob, {"PaymentBurn", "PaymentMint", "Payment"})); env.close(); env(pay(alice, gw, MPT(50)), delegate::as(bob)); BEAST_EXPECT(env.balance(alice, MPT) == aliceMPT - MPT(50)); @@ -838,9 +784,7 @@ class Delegate_test : public beast::unit_test::suite env.close(); // bob can not create trustline on behalf of alice because he only // has unfreeze permission - env(trust(alice, gw["USD"](50)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(trust(alice, gw["USD"](50)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); // alice creates trustline by herself @@ -852,70 +796,45 @@ class Delegate_test : public beast::unit_test::suite env.close(); // unsupported flags - env(trust(alice, gw["USD"](50), tfSetNoRipple), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); - env(trust(alice, gw["USD"](50), tfClearNoRipple), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); - env(trust(gw, gw["USD"](0), alice, tfSetDeepFreeze), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); - env(trust(gw, gw["USD"](0), alice, tfClearDeepFreeze), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(trust(alice, gw["USD"](50), tfSetNoRipple), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); + env(trust(alice, gw["USD"](50), tfClearNoRipple), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); + env(trust(gw, gw["USD"](0), alice, tfSetDeepFreeze), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); + env(trust(gw, gw["USD"](0), alice, tfClearDeepFreeze), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); // supported flags with wrong permission - env(trust(gw, gw["USD"](0), alice, tfSetfAuth), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); - env(trust(gw, gw["USD"](0), alice, tfSetFreeze), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(trust(gw, gw["USD"](0), alice, tfSetfAuth), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); + env(trust(gw, gw["USD"](0), alice, tfSetFreeze), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); env(delegate::set(gw, bob, {"TrustlineAuthorize"})); env.close(); - env(trust(gw, gw["USD"](0), alice, tfClearFreeze), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(trust(gw, gw["USD"](0), alice, tfClearFreeze), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); // although trustline authorize is granted, bob can not change the // limit number - env(trust(gw, gw["USD"](50), alice, tfSetfAuth), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(trust(gw, gw["USD"](50), alice, tfSetfAuth), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env.close(); // supported flags with correct permission env(trust(gw, gw["USD"](0), alice, tfSetfAuth), delegate::as(bob)); env.close(); - env(delegate::set( - gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"})); + env(delegate::set(gw, bob, {"TrustlineAuthorize", "TrustlineFreeze"})); env.close(); env(trust(gw, gw["USD"](0), alice, tfSetFreeze), delegate::as(bob)); env.close(); - env(delegate::set( - gw, bob, {"TrustlineAuthorize", "TrustlineUnfreeze"})); + env(delegate::set(gw, bob, {"TrustlineAuthorize", "TrustlineUnfreeze"})); env.close(); - env(trust(gw, gw["USD"](0), alice, tfClearFreeze), - delegate::as(bob)); + env(trust(gw, gw["USD"](0), alice, tfClearFreeze), delegate::as(bob)); env.close(); // but bob can not freeze trustline because he no longer has freeze // permission - env(trust(gw, gw["USD"](0), alice, tfSetFreeze), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(trust(gw, gw["USD"](0), alice, tfSetFreeze), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // cannot update LimitAmount with granular permission, both high and // low account - env(trust(alice, gw["USD"](100)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); - env(trust(gw, alice["USD"](100)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(trust(alice, gw["USD"](100)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); + env(trust(gw, alice["USD"](100)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // can not set QualityIn or QualityOut auto tx = trust(alice, gw["USD"](50)); @@ -956,53 +875,34 @@ class Delegate_test : public beast::unit_test::suite env.close(); // bob does not have permission - env(trust(alice, gw["USD"](50)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); - env(delegate::set( - alice, bob, {"TrustlineUnfreeze", "NFTokenCreateOffer"})); + env(trust(alice, gw["USD"](50)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); + env(delegate::set(alice, bob, {"TrustlineUnfreeze", "NFTokenCreateOffer"})); env.close(); // bob still does not have permission - env(trust(alice, gw["USD"](50)), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(trust(alice, gw["USD"](50)), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // add TrustSet permission and some unrelated permission env(delegate::set( - alice, - bob, - {"TrustlineUnfreeze", - "NFTokenCreateOffer", - "TrustSet", - "AccountTransferRateSet"})); + alice, bob, {"TrustlineUnfreeze", "NFTokenCreateOffer", "TrustSet", "AccountTransferRateSet"})); env.close(); env(trust(alice, gw["USD"](50)), delegate::as(bob)); env.close(); env(delegate::set( - gw, - bob, - {"TrustlineUnfreeze", - "NFTokenCreateOffer", - "TrustSet", - "AccountTransferRateSet"})); + gw, bob, {"TrustlineUnfreeze", "NFTokenCreateOffer", "TrustSet", "AccountTransferRateSet"})); env.close(); // since bob has TrustSet permission, he does not need // TrustlineFreeze granular permission to freeze the trustline env(trust(gw, gw["USD"](0), alice, tfSetFreeze), delegate::as(bob)); - env(trust(gw, gw["USD"](0), alice, tfClearFreeze), - delegate::as(bob)); + env(trust(gw, gw["USD"](0), alice, tfClearFreeze), delegate::as(bob)); // bob can perform all the operations regarding TrustSet env(trust(gw, gw["USD"](0), alice, tfSetFreeze), delegate::as(bob)); - env(trust(gw, gw["USD"](0), alice, tfSetDeepFreeze), - delegate::as(bob)); - env(trust(gw, gw["USD"](0), alice, tfClearDeepFreeze), - delegate::as(bob)); + env(trust(gw, gw["USD"](0), alice, tfSetDeepFreeze), delegate::as(bob)); + env(trust(gw, gw["USD"](0), alice, tfClearDeepFreeze), delegate::as(bob)); env(trust(gw, gw["USD"](0), alice, tfSetfAuth), delegate::as(bob)); env(trust(alice, gw["USD"](50), tfSetNoRipple), delegate::as(bob)); - env(trust(alice, gw["USD"](50), tfClearNoRipple), - delegate::as(bob)); + env(trust(alice, gw["USD"](50), tfClearNoRipple), delegate::as(bob)); } // tfFullyCanonicalSig won't block delegated transaction @@ -1019,9 +919,7 @@ class Delegate_test : public beast::unit_test::suite env(delegate::set(gw, bob, {"TrustlineAuthorize"})); env.close(); - env(trust( - gw, gw["USD"](0), alice, tfSetfAuth | tfFullyCanonicalSig), - delegate::as(bob)); + env(trust(gw, gw["USD"](0), alice, tfSetfAuth | tfFullyCanonicalSig), delegate::as(bob)); } } @@ -1055,8 +953,7 @@ class Delegate_test : public beast::unit_test::suite // add granular permission related to AccountSet but is not the // correct permission for domain set - env(delegate::set( - alice, bob, {"TrustlineUnfreeze", "AccountEmailHashSet"})); + env(delegate::set(alice, bob, {"TrustlineUnfreeze", "AccountEmailHashSet"})); env.close(); env(jt, ter(terNO_DELEGATE_PERMISSION)); @@ -1089,8 +986,7 @@ class Delegate_test : public beast::unit_test::suite env(jt, ter(terNO_DELEGATE_PERMISSION)); // alice give granular permission of AccountEmailHashSet to bob - env(delegate::set( - alice, bob, {"AccountDomainSet", "AccountEmailHashSet"})); + env(delegate::set(alice, bob, {"AccountDomainSet", "AccountEmailHashSet"})); env.close(); env(jt); BEAST_EXPECT(to_string((*env.le(alice))[sfEmailHash]) == mh); @@ -1102,36 +998,24 @@ class Delegate_test : public beast::unit_test::suite env(jt, ter(terNO_DELEGATE_PERMISSION)); // alice give granular permission of AccountMessageKeySet to bob - env(delegate::set( - alice, - bob, - {"AccountDomainSet", - "AccountEmailHashSet", - "AccountMessageKeySet"})); + env(delegate::set(alice, bob, {"AccountDomainSet", "AccountEmailHashSet", "AccountMessageKeySet"})); env.close(); // bob can set message key for alice env(jt); - BEAST_EXPECT( - strHex((*env.le(alice))[sfMessageKey]) == - strHex(rkp.first.slice())); + BEAST_EXPECT(strHex((*env.le(alice))[sfMessageKey]) == strHex(rkp.first.slice())); jt[sfMessageKey] = ""; env(jt); BEAST_EXPECT(!env.le(alice)->isFieldPresent(sfMessageKey)); // bob does not have permission to set transfer rate for alice - env(rate(alice, 2.0), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(rate(alice, 2.0), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // alice give granular permission of AccountTransferRateSet to bob env(delegate::set( alice, bob, - {"AccountDomainSet", - "AccountEmailHashSet", - "AccountMessageKeySet", - "AccountTransferRateSet"})); + {"AccountDomainSet", "AccountEmailHashSet", "AccountMessageKeySet", "AccountTransferRateSet"})); env.close(); auto jtRate = rate(alice, 2.0); jtRate[sfDelegate] = bob.human(); @@ -1156,18 +1040,14 @@ class Delegate_test : public beast::unit_test::suite BEAST_EXPECT((*env.le(alice))[sfTickSize] == 8); // can not set asfRequireAuth flag for alice - env(fset(alice, asfRequireAuth), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fset(alice, asfRequireAuth), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // reset Delegate will delete the Delegate // object env(delegate::set(alice, bob, {})); // bib still does not have permission to set asfRequireAuth for // alice - env(fset(alice, asfRequireAuth), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fset(alice, asfRequireAuth), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // alice can set for herself env(fset(alice, asfRequireAuth)); env.require(flags(alice, asfRequireAuth)); @@ -1177,12 +1057,7 @@ class Delegate_test : public beast::unit_test::suite jt[sfTickSize] = 7; env(jt, ter(terNO_DELEGATE_PERMISSION)); - env(delegate::set( - alice, - bob, - {"AccountDomainSet", - "AccountEmailHashSet", - "AccountMessageKeySet"})); + env(delegate::set(alice, bob, {"AccountDomainSet", "AccountEmailHashSet", "AccountMessageKeySet"})); env.close(); // bob does not have permission to set wallet locater for alice @@ -1206,17 +1081,13 @@ class Delegate_test : public beast::unit_test::suite auto testSetClearFlag = [&](std::uint32_t flag) { // bob can not set flag on behalf of alice - env(fset(alice, flag), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fset(alice, flag), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // alice set by herself env(fset(alice, flag)); env.close(); env.require(flags(alice, flag)); // bob can not clear on behalf of alice - env(fclear(alice, flag), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fclear(alice, flag), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); }; // testSetClearFlag(asfNoFreeze); @@ -1224,12 +1095,7 @@ class Delegate_test : public beast::unit_test::suite testSetClearFlag(asfAllowTrustLineClawback); // alice gives some granular permissions to bob - env(delegate::set( - alice, - bob, - {"AccountDomainSet", - "AccountEmailHashSet", - "AccountMessageKeySet"})); + env(delegate::set(alice, bob, {"AccountDomainSet", "AccountEmailHashSet", "AccountMessageKeySet"})); env.close(); testSetClearFlag(asfDefaultRipple); @@ -1243,15 +1109,11 @@ class Delegate_test : public beast::unit_test::suite testSetClearFlag(asfGlobalFreeze); // bob can not set asfAccountTxnID on behalf of alice - env(fset(alice, asfAccountTxnID), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fset(alice, asfAccountTxnID), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env(fset(alice, asfAccountTxnID)); env.close(); BEAST_EXPECT(env.le(alice)->isFieldPresent(sfAccountTxnID)); - env(fclear(alice, asfAccountTxnID), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fclear(alice, asfAccountTxnID), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // bob can not set asfAuthorizedNFTokenMinter on behalf of alice Json::Value jt = fset(alice, asfAuthorizedNFTokenMinter); @@ -1260,36 +1122,24 @@ class Delegate_test : public beast::unit_test::suite env(jt, ter(terNO_DELEGATE_PERMISSION)); // bob gives alice some permissions - env(delegate::set( - bob, - alice, - {"AccountDomainSet", - "AccountEmailHashSet", - "AccountMessageKeySet"})); + env(delegate::set(bob, alice, {"AccountDomainSet", "AccountEmailHashSet", "AccountMessageKeySet"})); env.close(); // since we can not set asfNoFreeze if asfAllowTrustLineClawback is // set, which can not be clear either. Test alice set asfNoFreeze on // behalf of bob. - env(fset(alice, asfNoFreeze), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fset(alice, asfNoFreeze), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); env(fset(bob, asfNoFreeze)); env.close(); env.require(flags(bob, asfNoFreeze)); // alice can not clear on behalf of bob - env(fclear(alice, asfNoFreeze), - delegate::as(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fclear(alice, asfNoFreeze), delegate::as(bob), ter(terNO_DELEGATE_PERMISSION)); // bob can not set asfDisableMaster on behalf of alice Account const bobKey{"bobKey", KeyType::secp256k1}; env(regkey(bob, bobKey)); env.close(); - env(fset(alice, asfDisableMaster), - delegate::as(bob), - sig(bob), - ter(terNO_DELEGATE_PERMISSION)); + env(fset(alice, asfDisableMaster), delegate::as(bob), sig(bob), ter(terNO_DELEGATE_PERMISSION)); } // tfFullyCanonicalSig won't block delegated transaction @@ -1300,8 +1150,7 @@ class Delegate_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob); env.close(); - env(delegate::set( - alice, bob, {"AccountDomainSet", "AccountEmailHashSet"})); + env(delegate::set(alice, bob, {"AccountDomainSet", "AccountEmailHashSet"})); env.close(); std::string const domain = "example.com"; @@ -1335,34 +1184,21 @@ class Delegate_test : public beast::unit_test::suite env.close(); // delegate ledger object is not created yet - mpt.set( - {.account = alice, - .flags = tfMPTLock, - .delegate = bob, - .err = terNO_DELEGATE_PERMISSION}); + mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob, .err = terNO_DELEGATE_PERMISSION}); // alice gives granular permission to bob of MPTokenIssuanceUnlock env(delegate::set(alice, bob, {"MPTokenIssuanceUnlock"})); env.close(); // bob does not have lock permission - mpt.set( - {.account = alice, - .flags = tfMPTLock, - .delegate = bob, - .err = terNO_DELEGATE_PERMISSION}); + mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob, .err = terNO_DELEGATE_PERMISSION}); // bob now has lock permission, but does not have unlock permission env(delegate::set(alice, bob, {"MPTokenIssuanceLock"})); env.close(); mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob}); - mpt.set( - {.account = alice, - .flags = tfMPTUnlock, - .delegate = bob, - .err = terNO_DELEGATE_PERMISSION}); + mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob, .err = terNO_DELEGATE_PERMISSION}); // now bob can lock and unlock - env(delegate::set( - alice, bob, {"MPTokenIssuanceLock", "MPTokenIssuanceUnlock"})); + env(delegate::set(alice, bob, {"MPTokenIssuanceLock", "MPTokenIssuanceUnlock"})); env.close(); mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob}); mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob}); @@ -1387,34 +1223,17 @@ class Delegate_test : public beast::unit_test::suite env.close(); mpt.set({.account = alice, .flags = tfMPTLock, .delegate = bob}); // bob does not have unlock permission - mpt.set( - {.account = alice, - .flags = tfMPTUnlock, - .delegate = bob, - .err = terNO_DELEGATE_PERMISSION}); + mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob, .err = terNO_DELEGATE_PERMISSION}); // alice gives bob some unrelated permission with // MPTokenIssuanceLock - env(delegate::set( - alice, - bob, - {"NFTokenMint", "MPTokenIssuanceLock", "NFTokenBurn"})); + env(delegate::set(alice, bob, {"NFTokenMint", "MPTokenIssuanceLock", "NFTokenBurn"})); env.close(); // bob can not unlock - mpt.set( - {.account = alice, - .flags = tfMPTUnlock, - .delegate = bob, - .err = terNO_DELEGATE_PERMISSION}); + mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob, .err = terNO_DELEGATE_PERMISSION}); // alice add MPTokenIssuanceSet to permissions - env(delegate::set( - alice, - bob, - {"NFTokenMint", - "MPTokenIssuanceLock", - "NFTokenBurn", - "MPTokenIssuanceSet"})); + env(delegate::set(alice, bob, {"NFTokenMint", "MPTokenIssuanceLock", "NFTokenBurn", "MPTokenIssuanceSet"})); mpt.set({.account = alice, .flags = tfMPTUnlock, .delegate = bob}); // alice can lock by herself mpt.set({.account = alice, .flags = tfMPTLock}); @@ -1438,10 +1257,7 @@ class Delegate_test : public beast::unit_test::suite // alice gives granular permission to bob of MPTokenIssuanceLock env(delegate::set(alice, bob, {"MPTokenIssuanceLock"})); env.close(); - mpt.set( - {.account = alice, - .flags = tfMPTLock | tfFullyCanonicalSig, - .delegate = bob}); + mpt.set({.account = alice, .flags = tfMPTLock | tfFullyCanonicalSig, .delegate = bob}); } } @@ -1465,10 +1281,7 @@ class Delegate_test : public beast::unit_test::suite auto bobBalance = env.balance(bob); auto carolBalance = env.balance(carol); - env(pay(alice, carol, XRP(100)), - fee(XRP(10)), - delegate::as(bob), - sig(bob)); + env(pay(alice, carol, XRP(100)), fee(XRP(10)), delegate::as(bob), sig(bob)); env.close(); BEAST_EXPECT(env.balance(alice) == aliceBalance - XRP(100)); BEAST_EXPECT(env.balance(bob) == bobBalance - XRP(10)); @@ -1496,11 +1309,7 @@ class Delegate_test : public beast::unit_test::suite auto bobBalance = env.balance(bob); auto carolBalance = env.balance(carol); - env(pay(alice, carol, XRP(100)), - fee(XRP(10)), - delegate::as(bob), - sig(alice), - ter(tefBAD_AUTH)); + env(pay(alice, carol, XRP(100)), fee(XRP(10)), delegate::as(bob), sig(alice), ter(tefBAD_AUTH)); env.close(); BEAST_EXPECT(env.balance(alice) == aliceBalance); BEAST_EXPECT(env.balance(bob) == bobBalance); @@ -1600,10 +1409,7 @@ class Delegate_test : public beast::unit_test::suite auto dariaBalance = env.balance(daria); auto edwardBalance = env.balance(edward); - env(pay(alice, carol, XRP(100)), - fee(XRP(10)), - delegate::as(bob), - msig(daria, edward)); + env(pay(alice, carol, XRP(100)), fee(XRP(10)), delegate::as(bob), msig(daria, edward)); env.close(); BEAST_EXPECT(env.balance(alice) == aliceBalance - XRP(100)); BEAST_EXPECT(env.balance(bob) == bobBalance - XRP(10)); @@ -1640,11 +1446,7 @@ class Delegate_test : public beast::unit_test::suite auto dariaBalance = env.balance(daria); auto edwardBalance = env.balance(edward); - env(pay(alice, carol, XRP(100)), - fee(XRP(10)), - delegate::as(bob), - msig(daria, edward), - ter(tefBAD_QUORUM)); + env(pay(alice, carol, XRP(100)), fee(XRP(10)), delegate::as(bob), msig(daria, edward), ter(tefBAD_QUORUM)); env.close(); BEAST_EXPECT(env.balance(alice) == aliceBalance); BEAST_EXPECT(env.balance(bob) == bobBalance); @@ -1743,8 +1545,7 @@ class Delegate_test : public beast::unit_test::suite // Can not delegate tx if any required feature disabled. { - auto txAmendmentDisabled = [&](FeatureBitset features, - std::string const& tx) { + auto txAmendmentDisabled = [&](FeatureBitset features, std::string const& tx) { BEAST_EXPECT(txRequiredFeatures.contains(tx)); Env env(*this, features - txRequiredFeatures[tx]); diff --git a/src/test/app/DeliverMin_test.cpp b/src/test/app/DeliverMin_test.cpp index c49f83b518..711b29cfa8 100644 --- a/src/test/app/DeliverMin_test.cpp +++ b/src/test/app/DeliverMin_test.cpp @@ -24,25 +24,14 @@ public: env.close(); env.trust(USD(100), "alice", "bob", "carol"); env.close(); - env(pay("alice", "bob", USD(10)), - deliver_min(USD(10)), - ter(temBAD_AMOUNT)); - env(pay("alice", "bob", USD(10)), - deliver_min(USD(-5)), - txflags(tfPartialPayment), - ter(temBAD_AMOUNT)); - env(pay("alice", "bob", USD(10)), - deliver_min(XRP(5)), - txflags(tfPartialPayment), - ter(temBAD_AMOUNT)); + env(pay("alice", "bob", USD(10)), deliver_min(USD(10)), ter(temBAD_AMOUNT)); + env(pay("alice", "bob", USD(10)), deliver_min(USD(-5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); + env(pay("alice", "bob", USD(10)), deliver_min(XRP(5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay("alice", "bob", USD(10)), deliver_min(Account("carol")["USD"](5)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); - env(pay("alice", "bob", USD(10)), - deliver_min(USD(15)), - txflags(tfPartialPayment), - ter(temBAD_AMOUNT)); + env(pay("alice", "bob", USD(10)), deliver_min(USD(15)), txflags(tfPartialPayment), ter(temBAD_AMOUNT)); env(pay(gw, "carol", USD(50))); env(offer("carol", XRP(5), USD(5))); env(pay("alice", "bob", USD(10)), @@ -51,8 +40,7 @@ public: txflags(tfPartialPayment), sendmax(XRP(5)), ter(tecPATH_PARTIAL)); - env.require(balance( - "alice", XRP(10000) - drops(env.current()->fees().base))); + env.require(balance("alice", XRP(10000) - drops(env.current()->fees().base))); env.require(balance("bob", XRP(10000))); } diff --git a/src/test/app/DepositAuth_test.cpp b/src/test/app/DepositAuth_test.cpp index 775d7b1e81..535abc6af8 100644 --- a/src/test/app/DepositAuth_test.cpp +++ b/src/test/app/DepositAuth_test.cpp @@ -92,9 +92,7 @@ struct DepositAuth_test : public beast::unit_test::suite // Note that even though alice is paying bob in XRP, the payment // is still not allowed since the payment passes through an offer. - env(pay(alice, bob, drops(1)), - sendmax(USD(1)), - ter(tecNO_PERMISSION)); + env(pay(alice, bob, drops(1)), sendmax(USD(1)), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(bobXrpBalance == env.balance(bob, XRP)); @@ -205,14 +203,12 @@ struct DepositAuth_test : public beast::unit_test::suite // We should be able to pay bob the base reserve one more time. env(pay(alice, bob, reserve(env, 0) + drops(0))); env.close(); - BEAST_EXPECT( - env.balance(bob, XRP) == (reserve(env, 0) + reserve(env, 0))); + BEAST_EXPECT(env.balance(bob, XRP) == (reserve(env, 0) + reserve(env, 0))); // bob's above the threshold again. Any payment should fail. env(pay(alice, bob, drops(1)), ter(tecNO_PERMISSION)); env.close(); - BEAST_EXPECT( - env.balance(bob, XRP) == (reserve(env, 0) + reserve(env, 0))); + BEAST_EXPECT(env.balance(bob, XRP) == (reserve(env, 0) + reserve(env, 0))); // Take bob back down to a zero XRP balance. env(noop(bob), fee(env.balance(bob, XRP))); @@ -262,50 +258,41 @@ struct DepositAuth_test : public beast::unit_test::suite IOU const USD1(gw1["USD"]); IOU const USD2(gw2["USD"]); - auto testIssuer = [&](FeatureBitset const& features, - bool noRipplePrev, - bool noRippleNext, - bool withDepositAuth) { - Env env(*this, features); + auto testIssuer = + [&](FeatureBitset const& features, bool noRipplePrev, bool noRippleNext, bool withDepositAuth) { + Env env(*this, features); - env.fund(XRP(10000), gw1, alice, bob); - env.close(); - env(trust(gw1, alice["USD"](10), noRipplePrev ? tfSetNoRipple : 0)); - env(trust(gw1, bob["USD"](10), noRippleNext ? tfSetNoRipple : 0)); - env.trust(USD1(10), alice, bob); + env.fund(XRP(10000), gw1, alice, bob); + env.close(); + env(trust(gw1, alice["USD"](10), noRipplePrev ? tfSetNoRipple : 0)); + env(trust(gw1, bob["USD"](10), noRippleNext ? tfSetNoRipple : 0)); + env.trust(USD1(10), alice, bob); - env(pay(gw1, alice, USD1(10))); + env(pay(gw1, alice, USD1(10))); - if (withDepositAuth) - env(fset(gw1, asfDepositAuth)); + if (withDepositAuth) + env(fset(gw1, asfDepositAuth)); - TER const result = (noRippleNext && noRipplePrev) ? TER{tecPATH_DRY} - : TER{tesSUCCESS}; - env(pay(alice, bob, USD1(10)), path(gw1), ter(result)); - }; + TER const result = (noRippleNext && noRipplePrev) ? TER{tecPATH_DRY} : TER{tesSUCCESS}; + env(pay(alice, bob, USD1(10)), path(gw1), ter(result)); + }; - auto testNonIssuer = [&](FeatureBitset const& features, - bool noRipplePrev, - bool noRippleNext, - bool withDepositAuth) { - Env env(*this, features); + auto testNonIssuer = + [&](FeatureBitset const& features, bool noRipplePrev, bool noRippleNext, bool withDepositAuth) { + Env env(*this, features); - env.fund(XRP(10000), gw1, gw2, alice); - env.close(); - env(trust(alice, USD1(10), noRipplePrev ? tfSetNoRipple : 0)); - env(trust(alice, USD2(10), noRippleNext ? tfSetNoRipple : 0)); - env(pay(gw2, alice, USD2(10))); + env.fund(XRP(10000), gw1, gw2, alice); + env.close(); + env(trust(alice, USD1(10), noRipplePrev ? tfSetNoRipple : 0)); + env(trust(alice, USD2(10), noRippleNext ? tfSetNoRipple : 0)); + env(pay(gw2, alice, USD2(10))); - if (withDepositAuth) - env(fset(alice, asfDepositAuth)); + if (withDepositAuth) + env(fset(alice, asfDepositAuth)); - TER const result = (noRippleNext && noRipplePrev) ? TER{tecPATH_DRY} - : TER{tesSUCCESS}; - env(pay(gw1, gw2, USD2(10)), - path(alice), - sendmax(USD1(10)), - ter(result)); - }; + TER const result = (noRippleNext && noRipplePrev) ? TER{tecPATH_DRY} : TER{tesSUCCESS}; + env(pay(gw1, gw2, USD2(10)), path(alice), sendmax(USD1(10)), ter(result)); + }; // Test every combo of noRipplePrev, noRippleNext, and withDepositAuth for (int i = 0; i < 8; ++i) @@ -313,17 +300,9 @@ struct DepositAuth_test : public beast::unit_test::suite auto const noRipplePrev = i & 0x1; auto const noRippleNext = i & 0x2; auto const withDepositAuth = i & 0x4; - testIssuer( - testable_amendments(), - noRipplePrev, - noRippleNext, - withDepositAuth); + testIssuer(testable_amendments(), noRipplePrev, noRippleNext, withDepositAuth); - testNonIssuer( - testable_amendments(), - noRipplePrev, - noRippleNext, - withDepositAuth); + testNonIssuer(testable_amendments(), noRipplePrev, noRippleNext, withDepositAuth); } } @@ -346,8 +325,7 @@ ledgerEntryDepositPreauth( Json::Value jvParams; jvParams[jss::ledger_index] = jss::validated; jvParams[jss::deposit_preauth][jss::owner] = acc.human(); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - Json::arrayValue; + jvParams[jss::deposit_preauth][jss::authorized_credentials] = Json::arrayValue; auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]); for (auto const& o : auth) { @@ -564,8 +542,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env(pay(gw, alice, USD(500))); env.close(); - env(offer(alice, XRP(100), USD(100), tfPassive), - require(offers(alice, 1))); + env(offer(alice, XRP(100), USD(100), tfPassive), require(offers(alice, 1))); env.close(); // becky pays herself USD (10) by consuming part of alice's offer. @@ -578,10 +555,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env.close(); // becky pays herself again. - env(pay(becky, becky, USD(10)), - path(~USD), - sendmax(XRP(10)), - ter(tesSUCCESS)); + env(pay(becky, becky, USD(10)), path(~USD), sendmax(XRP(10)), ter(tesSUCCESS)); env.close(); { @@ -593,11 +567,9 @@ struct DepositPreauth_test : public beast::unit_test::suite bool const supportsCredentials = features[featureCredentials]; - TER const expectTer( - !supportsCredentials ? TER(temDISABLED) : TER(tesSUCCESS)); + TER const expectTer(!supportsCredentials ? TER(temDISABLED) : TER(tesSUCCESS)); - env(deposit::authCredentials(becky, {{carol, credType}}), - ter(expectTer)); + env(deposit::authCredentials(becky, {{carol, credType}}), ter(expectTer)); env.close(); // gw accept credentials @@ -612,9 +584,7 @@ struct DepositPreauth_test : public beast::unit_test::suite : "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6" "EA288BE4"; - env(pay(gw, becky, USD(100)), - credentials::ids({credIdx}), - ter(expectTer)); + env(pay(gw, becky, USD(100)), credentials::ids({credIdx}), ter(expectTer)); env.close(); } } @@ -729,8 +699,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env.close(); // Setup DepositPreauth object failed - amendent is not supported - env(deposit::authCredentials(bob, {{issuer, credType}}), - ter(temDISABLED)); + env(deposit::authCredentials(bob, {{issuer, credType}}), ter(temDISABLED)); env.close(); // But can create old DepositPreauth @@ -742,9 +711,7 @@ struct DepositPreauth_test : public beast::unit_test::suite std::string const invalidIdx = "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E" "01E034"; - env(pay(alice, bob, XRP(10)), - credentials::ids({invalidIdx}), - ter(temDISABLED)); + env(pay(alice, bob, XRP(10)), credentials::ids({invalidIdx}), ter(temDISABLED)); env.close(); } @@ -761,8 +728,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env.close(); // Get the index of the credentials - auto const jv = - credentials::ledgerEntry(env, alice, issuer, credType); + auto const jv = credentials::ledgerEntry(env, alice, issuer, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); // Bob require pre-authorization @@ -774,15 +740,11 @@ struct DepositPreauth_test : public beast::unit_test::suite env(deposit::authCredentials(bob, {{issuer, credType}})); env.close(); - auto const jDP = - ledgerEntryDepositPreauth(env, bob, {{issuer, credType}}); + auto const jDP = ledgerEntryDepositPreauth(env, bob, {{issuer, credType}}); BEAST_EXPECT( - jDP.isObject() && jDP.isMember(jss::result) && - !jDP[jss::result].isMember(jss::error) && - jDP[jss::result].isMember(jss::node) && - jDP[jss::result][jss::node].isMember("LedgerEntryType") && - jDP[jss::result][jss::node]["LedgerEntryType"] == - jss::DepositPreauth); + jDP.isObject() && jDP.isMember(jss::result) && !jDP[jss::result].isMember(jss::error) && + jDP[jss::result].isMember(jss::node) && jDP[jss::result][jss::node].isMember("LedgerEntryType") && + jDP[jss::result][jss::node]["LedgerEntryType"] == jss::DepositPreauth); // Alice can't pay - empty credentials array { @@ -793,9 +755,7 @@ struct DepositPreauth_test : public beast::unit_test::suite } // Alice can't pay - not accepted credentials - env(pay(alice, bob, XRP(100)), - credentials::ids({credIdx}), - ter(tecBAD_CREDENTIALS)); + env(pay(alice, bob, XRP(100)), credentials::ids({credIdx}), ter(tecBAD_CREDENTIALS)); env.close(); // Alice accept the credentials @@ -833,8 +793,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env(credentials::accept(alice, issuer, credType)); env.close(); // Get the index of the credentials - auto const jv = - credentials::ledgerEntry(env, alice, issuer, credType); + auto const jv = credentials::ledgerEntry(env, alice, issuer, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); { @@ -849,15 +808,11 @@ struct DepositPreauth_test : public beast::unit_test::suite { // Fail as destination didn't setup DepositPreauth object - env(pay(alice, bob, XRP(100)), - credentials::ids({credIdx}), - ter(tecNO_PERMISSION)); + env(pay(alice, bob, XRP(100)), credentials::ids({credIdx}), ter(tecNO_PERMISSION)); } // Bob setup DepositPreauth object, duplicates is not allowed - env(deposit::authCredentials( - bob, {{issuer, credType}, {issuer, credType}}), - ter(temMALFORMED)); + env(deposit::authCredentials(bob, {{issuer, credType}, {issuer, credType}}), ter(temMALFORMED)); // Bob setup DepositPreauth object env(deposit::authCredentials(bob, {{issuer, credType}})); @@ -868,16 +823,12 @@ struct DepositPreauth_test : public beast::unit_test::suite "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E" "01E034"; // Alice can't pay with non-existing credentials - env(pay(alice, bob, XRP(100)), - credentials::ids({invalidIdx}), - ter(tecBAD_CREDENTIALS)); + env(pay(alice, bob, XRP(100)), credentials::ids({invalidIdx}), ter(tecBAD_CREDENTIALS)); } { // maria can't pay using valid credentials but issued for // different account - env(pay(maria, bob, XRP(100)), - credentials::ids({credIdx}), - ter(tecBAD_CREDENTIALS)); + env(pay(maria, bob, XRP(100)), credentials::ids({credIdx}), ter(tecBAD_CREDENTIALS)); } { @@ -887,21 +838,15 @@ struct DepositPreauth_test : public beast::unit_test::suite env.close(); env(credentials::accept(alice, issuer, credType2)); env.close(); - auto const jv = - credentials::ledgerEntry(env, alice, issuer, credType2); - std::string const credIdx2 = - jv[jss::result][jss::index].asString(); + auto const jv = credentials::ledgerEntry(env, alice, issuer, credType2); + std::string const credIdx2 = jv[jss::result][jss::index].asString(); // Alice can't pay with invalid set of valid credentials - env(pay(alice, bob, XRP(100)), - credentials::ids({credIdx, credIdx2}), - ter(tecNO_PERMISSION)); + env(pay(alice, bob, XRP(100)), credentials::ids({credIdx, credIdx2}), ter(tecNO_PERMISSION)); } // Error, duplicate credentials - env(pay(alice, bob, XRP(100)), - credentials::ids({credIdx, credIdx}), - ter(temMALFORMED)); + env(pay(alice, bob, XRP(100)), credentials::ids({credIdx, credIdx}), ter(temMALFORMED)); // Alice can pay env(pay(alice, bob, XRP(100)), credentials::ids({credIdx})); @@ -975,8 +920,7 @@ struct DepositPreauth_test : public beast::unit_test::suite auto& arr(jv[sfAuthorizeCredentials.jsonName]); Json::Value cred = Json::objectValue; cred[jss::Issuer] = to_string(xrpAccount()); - cred[sfCredentialType.jsonName] = - strHex(std::string_view(credType)); + cred[sfCredentialType.jsonName] = strHex(std::string_view(credType)); Json::Value credParent; credParent[jss::Credential] = cred; arr.append(std::move(credParent)); @@ -992,20 +936,10 @@ struct DepositPreauth_test : public beast::unit_test::suite { // AuthorizeCredentials is larger than 8 elements - Account const a("a"), b("b"), c("c"), d("d"), e("e"), f("f"), - g("g"), h("h"), i("i"); + Account const a("a"), b("b"), c("c"), d("d"), e("e"), f("f"), g("g"), h("h"), i("i"); auto const& z = credType; auto jv = deposit::authCredentials( - bob, - {{a, z}, - {b, z}, - {c, z}, - {d, z}, - {e, z}, - {f, z}, - {g, z}, - {h, z}, - {i, z}}); + bob, {{a, z}, {b, z}, {c, z}, {d, z}, {e, z}, {f, z}, {g, z}, {h, z}, {i, z}}); env(jv, ter(temARRAY_TOO_LARGE)); } @@ -1028,8 +962,7 @@ struct DepositPreauth_test : public beast::unit_test::suite { // NO deposit object exists - env(deposit::unauthCredentials(bob, {{issuer, credType}}), - ter(tecNO_ENTRY)); + env(deposit::unauthCredentials(bob, {{issuer, credType}}), ter(tecNO_ENTRY)); } // Create DepositPreauth object @@ -1037,45 +970,34 @@ struct DepositPreauth_test : public beast::unit_test::suite env(deposit::authCredentials(bob, {{issuer, credType}})); env.close(); - auto const jDP = - ledgerEntryDepositPreauth(env, bob, {{issuer, credType}}); + auto const jDP = ledgerEntryDepositPreauth(env, bob, {{issuer, credType}}); BEAST_EXPECT( - jDP.isObject() && jDP.isMember(jss::result) && - !jDP[jss::result].isMember(jss::error) && - jDP[jss::result].isMember(jss::node) && - jDP[jss::result][jss::node].isMember("LedgerEntryType") && - jDP[jss::result][jss::node]["LedgerEntryType"] == - jss::DepositPreauth); + jDP.isObject() && jDP.isMember(jss::result) && !jDP[jss::result].isMember(jss::error) && + jDP[jss::result].isMember(jss::node) && jDP[jss::result][jss::node].isMember("LedgerEntryType") && + jDP[jss::result][jss::node]["LedgerEntryType"] == jss::DepositPreauth); // Check object fields - BEAST_EXPECT( - jDP[jss::result][jss::node][jss::Account] == bob.human()); - auto const& credentials( - jDP[jss::result][jss::node]["AuthorizeCredentials"]); + BEAST_EXPECT(jDP[jss::result][jss::node][jss::Account] == bob.human()); + auto const& credentials(jDP[jss::result][jss::node]["AuthorizeCredentials"]); BEAST_EXPECT(credentials.isArray() && credentials.size() == 1); for (auto const& o : credentials) { auto const& c(o[jss::Credential]); BEAST_EXPECT(c[jss::Issuer].asString() == issuer.human()); - BEAST_EXPECT( - c["CredentialType"].asString() == - strHex(std::string_view(credType))); + BEAST_EXPECT(c["CredentialType"].asString() == strHex(std::string_view(credType))); } // can't create duplicate - env(deposit::authCredentials(bob, {{issuer, credType}}), - ter(tecDUPLICATE)); + env(deposit::authCredentials(bob, {{issuer, credType}}), ter(tecDUPLICATE)); } // Delete DepositPreauth object { env(deposit::unauthCredentials(bob, {{issuer, credType}})); env.close(); - auto const jDP = - ledgerEntryDepositPreauth(env, bob, {{issuer, credType}}); + auto const jDP = ledgerEntryDepositPreauth(env, bob, {{issuer, credType}}); BEAST_EXPECT( - jDP.isObject() && jDP.isMember(jss::result) && - jDP[jss::result].isMember(jss::error) && + jDP.isObject() && jDP.isMember(jss::result) && jDP[jss::result].isMember(jss::error) && jDP[jss::result][jss::error] == "entryNotFound"); } } @@ -1106,11 +1028,7 @@ struct DepositPreauth_test : public beast::unit_test::suite auto jv = credentials::create(alice, issuer, credType); // Current time in ripple epoch. // Every time ledger close, unittest timer increase by 10s - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() + - 60; + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count() + 60; jv[sfExpiration.jsonName] = t; env(jv); env.close(); @@ -1121,11 +1039,7 @@ struct DepositPreauth_test : public beast::unit_test::suite // Create credential which not expired jv = credentials::create(alice, issuer, credType2); - uint32_t const t2 = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() + - 1000; + uint32_t const t2 = env.current()->header().parentCloseTime.time_since_epoch().count() + 1000; jv[sfExpiration.jsonName] = t2; env(jv); env.close(); @@ -1145,27 +1059,22 @@ struct DepositPreauth_test : public beast::unit_test::suite env(fset(bob, asfDepositAuth)); env.close(); // Bob setup DepositPreauth object - env(deposit::authCredentials( - bob, {{issuer, credType}, {issuer, credType2}})); + env(deposit::authCredentials(bob, {{issuer, credType}, {issuer, credType2}})); env.close(); { // Alice can pay - env(pay(alice, bob, XRP(100)), - credentials::ids({credIdx, credIdx2})); + env(pay(alice, bob, XRP(100)), credentials::ids({credIdx, credIdx2})); env.close(); env.close(); // Ledger closed, time increased, alice can't pay anymore - env(pay(alice, bob, XRP(100)), - credentials::ids({credIdx, credIdx2}), - ter(tecEXPIRED)); + env(pay(alice, bob, XRP(100)), credentials::ids({credIdx, credIdx2}), ter(tecEXPIRED)); env.close(); { // check that expired credentials were deleted - auto const jDelCred = - credentials::ledgerEntry(env, alice, issuer, credType); + auto const jDelCred = credentials::ledgerEntry(env, alice, issuer, credType); BEAST_EXPECT( jDelCred.isObject() && jDelCred.isMember(jss::result) && jDelCred[jss::result].isMember(jss::error) && @@ -1174,22 +1083,15 @@ struct DepositPreauth_test : public beast::unit_test::suite { // check that non-expired credential still present - auto const jle = - credentials::ledgerEntry(env, alice, issuer, credType2); + auto const jle = credentials::ledgerEntry(env, alice, issuer, credType2); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember( - "LedgerEntryType") && - jle[jss::result][jss::node]["LedgerEntryType"] == - jss::Credential && - jle[jss::result][jss::node][jss::Issuer] == - issuer.human() && - jle[jss::result][jss::node][jss::Subject] == - alice.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType2))); + jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && + jle[jss::result][jss::node][jss::Issuer] == issuer.human() && + jle[jss::result][jss::node][jss::Subject] == alice.human() && + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType2))); } BEAST_EXPECT(ownerCount(env, issuer) == 0); @@ -1198,11 +1100,7 @@ struct DepositPreauth_test : public beast::unit_test::suite { auto jv = credentials::create(gw, issuer, credType); - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() + - 40; + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count() + 40; jv[sfExpiration.jsonName] = t; env(jv); env.close(); @@ -1210,8 +1108,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env.close(); jv = credentials::ledgerEntry(env, gw, issuer, credType); - std::string const credIdx = - jv[jss::result][jss::index].asString(); + std::string const credIdx = jv[jss::result][jss::index].asString(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, gw) == 1); @@ -1221,18 +1118,14 @@ struct DepositPreauth_test : public beast::unit_test::suite env.close(); // credentials are expired - env(pay(gw, bob, USD(150)), - credentials::ids({credIdx}), - ter(tecEXPIRED)); + env(pay(gw, bob, USD(150)), credentials::ids({credIdx}), ter(tecEXPIRED)); env.close(); // check that expired credentials were deleted - auto const jDelCred = - credentials::ledgerEntry(env, gw, issuer, credType); + auto const jDelCred = credentials::ledgerEntry(env, gw, issuer, credType); BEAST_EXPECT( jDelCred.isObject() && jDelCred.isMember(jss::result) && - jDelCred[jss::result].isMember(jss::error) && - jDelCred[jss::result][jss::error] == "entryNotFound"); + jDelCred[jss::result].isMember(jss::error) && jDelCred[jss::result][jss::error] == "entryNotFound"); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, gw) == 0); @@ -1251,11 +1144,7 @@ struct DepositPreauth_test : public beast::unit_test::suite // Create credentials auto jv = credentials::create(zelda, issuer, credType); - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() + - 50; + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count() + 50; jv[sfExpiration.jsonName] = t; env(jv); env.close(); @@ -1276,15 +1165,12 @@ struct DepositPreauth_test : public beast::unit_test::suite env.close(); auto const seq = env.seq(alice); - env(escrow::create(alice, bob, XRP(1000)), - escrow::finish_time(env.now() + 1s)); + env(escrow::create(alice, bob, XRP(1000)), escrow::finish_time(env.now() + 1s)); env.close(); // zelda can't finish escrow with invalid credentials { - env(escrow::finish(zelda, alice, seq), - credentials::ids({}), - ter(temMALFORMED)); + env(escrow::finish(zelda, alice, seq), credentials::ids({}), ter(temMALFORMED)); env.close(); } @@ -1294,26 +1180,19 @@ struct DepositPreauth_test : public beast::unit_test::suite "0E0B04ED60588A758B67E21FBBE95AC5A63598BA951761DC0EC9C08D7E" "01E034"; - env(escrow::finish(zelda, alice, seq), - credentials::ids({invalidIdx}), - ter(tecBAD_CREDENTIALS)); + env(escrow::finish(zelda, alice, seq), credentials::ids({invalidIdx}), ter(tecBAD_CREDENTIALS)); env.close(); } { // Ledger closed, time increased, zelda can't finish escrow - env(escrow::finish(zelda, alice, seq), - credentials::ids({credIdx}), - fee(1500), - ter(tecEXPIRED)); + env(escrow::finish(zelda, alice, seq), credentials::ids({credIdx}), fee(1500), ter(tecEXPIRED)); env.close(); } // check that expired credentials were deleted - auto const jDelCred = - credentials::ledgerEntry(env, zelda, issuer, credType); + auto const jDelCred = credentials::ledgerEntry(env, zelda, issuer, credType); BEAST_EXPECT( - jDelCred.isObject() && jDelCred.isMember(jss::result) && - jDelCred[jss::result].isMember(jss::error) && + jDelCred.isObject() && jDelCred.isMember(jss::result) && jDelCred[jss::result].isMember(jss::error) && jDelCred[jss::result][jss::error] == "entryNotFound"); } } @@ -1334,14 +1213,7 @@ struct DepositPreauth_test : public beast::unit_test::suite env.fund(XRP(5000), stock, alice, bob); std::vector credentials = { - {"a", "a"}, - {"b", "b"}, - {"c", "c"}, - {"d", "d"}, - {"e", "e"}, - {"f", "f"}, - {"g", "g"}, - {"h", "h"}}; + {"a", "a"}, {"b", "b"}, {"c", "c"}, {"d", "d"}, {"e", "e"}, {"f", "f"}, {"g", "g"}, {"h", "h"}}; for (auto const& c : credentials) env.fund(XRP(5000), c.issuer); @@ -1362,13 +1234,9 @@ struct DepositPreauth_test : public beast::unit_test::suite env(deposit::authCredentials(stock, credentials)); env.close(); - auto const dp = - ledgerEntryDepositPreauth(env, stock, credentials); - auto const& authCred( - dp[jss::result][jss::node]["AuthorizeCredentials"]); - BEAST_EXPECT( - authCred.isArray() && - authCred.size() == credentials.size()); + auto const dp = ledgerEntryDepositPreauth(env, stock, credentials); + auto const& authCred(dp[jss::result][jss::node]["AuthorizeCredentials"]); + BEAST_EXPECT(authCred.isArray() && authCred.size() == credentials.size()); std::vector> readedCreds; for (auto const& o : authCred) { @@ -1376,9 +1244,7 @@ struct DepositPreauth_test : public beast::unit_test::suite auto issuer = c[jss::Issuer].asString(); if (BEAST_EXPECT(pubKey2Acc.contains(issuer))) - readedCreds.emplace_back( - pubKey2Acc.at(issuer), - c["CredentialType"].asString()); + readedCreds.emplace_back(pubKey2Acc.at(issuer), c["CredentialType"].asString()); } BEAST_EXPECT(std::ranges::is_sorted(readedCreds)); @@ -1397,24 +1263,21 @@ struct DepositPreauth_test : public beast::unit_test::suite for (int i = 0; i < 10; ++i) { std::ranges::shuffle(credentials, gen); - env(deposit::authCredentials(stock, credentials), - ter(tecDUPLICATE)); + env(deposit::authCredentials(stock, credentials), ter(tecDUPLICATE)); } } testcase("Check duplicate credentials."); { // check duplicates in depositPreauth params - std::vector copyCredentials( - credentials.begin(), credentials.end() - 1); + std::vector copyCredentials(credentials.begin(), credentials.end() - 1); std::ranges::shuffle(copyCredentials, gen); for (auto const& c : copyCredentials) { auto credentials2 = copyCredentials; credentials2.push_back(c); - env(deposit::authCredentials(stock, credentials2), - ter(temMALFORMED)); + env(deposit::authCredentials(stock, credentials2), ter(temMALFORMED)); } // create batch of credentials and save their hashes @@ -1426,12 +1289,8 @@ struct DepositPreauth_test : public beast::unit_test::suite env(credentials::accept(alice, c.issuer, c.credType)); env.close(); - credentialIDs.push_back(credentials::ledgerEntry( - env, - alice, - c.issuer, - c.credType)[jss::result][jss::index] - .asString()); + credentialIDs.push_back( + credentials::ledgerEntry(env, alice, c.issuer, c.credType)[jss::result][jss::index].asString()); } // check duplicates in payment params @@ -1440,9 +1299,7 @@ struct DepositPreauth_test : public beast::unit_test::suite auto credentialIDs2 = credentialIDs; credentialIDs2.push_back(h); - env(pay(alice, bob, XRP(100)), - credentials::ids(credentialIDs2), - ter(temMALFORMED)); + env(pay(alice, bob, XRP(100)), credentials::ids(credentialIDs2), ter(temMALFORMED)); } } } diff --git a/src/test/app/Discrepancy_test.cpp b/src/test/app/Discrepancy_test.cpp index 0e96f3aa1a..b56cb5b7c6 100644 --- a/src/test/app/Discrepancy_test.cpp +++ b/src/test/app/Discrepancy_test.cpp @@ -69,20 +69,14 @@ class Discrepancy_test : public beast::unit_test::suite env.close(); test::PathSet payPaths{ - test::Path{A2["JPY"], A2}, - test::Path{XRP, A2["JPY"], A2}, - test::Path{A6, XRP, A2["JPY"], A2}}; + test::Path{A2["JPY"], A2}, test::Path{XRP, A2["JPY"], A2}, test::Path{A6, XRP, A2["JPY"], A2}}; - env(pay(A1, A1, A2["JPY"](1000)), - json(payPaths.json()), - txflags(tfPartialPayment), - sendmax(A3["CNY"](56))); + env(pay(A1, A1, A2["JPY"](1000)), json(payPaths.json()), txflags(tfPartialPayment), sendmax(A3["CNY"](56))); env.close(); Json::Value jrq2; jrq2[jss::binary] = false; - jrq2[jss::transaction] = - env.tx()->getJson(JsonOptions::none)[jss::hash]; + jrq2[jss::transaction] = env.tx()->getJson(JsonOptions::none)[jss::hash]; jrq2[jss::id] = 3; auto jrr = env.rpc("json", "tx", to_string(jrq2))[jss::result]; uint64_t fee{jrr[jss::Fee].asUInt()}; @@ -102,19 +96,14 @@ class Discrepancy_test : public beast::unit_test::suite if (node && node[sfLedgerEntryType.fieldName] == jss::AccountRoot) { - Json::Value prevFields = - node.isMember(sfPreviousFields.fieldName) - ? node[sfPreviousFields.fieldName] - : node[sfNewFields.fieldName]; - Json::Value finalFields = node.isMember(sfFinalFields.fieldName) - ? node[sfFinalFields.fieldName] - : node[sfNewFields.fieldName]; + Json::Value prevFields = node.isMember(sfPreviousFields.fieldName) ? node[sfPreviousFields.fieldName] + : node[sfNewFields.fieldName]; + Json::Value finalFields = node.isMember(sfFinalFields.fieldName) ? node[sfFinalFields.fieldName] + : node[sfNewFields.fieldName]; if (prevFields) - sumPrev += beast::lexicalCastThrow( - prevFields[sfBalance.fieldName].asString()); + sumPrev += beast::lexicalCastThrow(prevFields[sfBalance.fieldName].asString()); if (finalFields) - sumFinal += beast::lexicalCastThrow( - finalFields[sfBalance.fieldName].asString()); + sumFinal += beast::lexicalCastThrow(finalFields[sfBalance.fieldName].asString()); } } // the difference in balances (final and prev) should be the diff --git a/src/test/app/EscrowToken_test.cpp b/src/test/app/EscrowToken_test.cpp index 589a8b474e..b5088f247a 100644 --- a/src/test/app/EscrowToken_test.cpp +++ b/src/test/app/EscrowToken_test.cpp @@ -19,10 +19,7 @@ namespace test { struct EscrowToken_test : public beast::unit_test::suite { static uint64_t - mptEscrowed( - jtx::Env const& env, - jtx::Account const& account, - jtx::MPT const& mpt) + mptEscrowed(jtx::Env const& env, jtx::Account const& account, jtx::MPT const& mpt) { auto const sle = env.le(keylet::mptoken(mpt.mpt(), account)); if (sle && sle->isFieldPresent(sfLockedAmount)) @@ -40,17 +37,13 @@ struct EscrowToken_test : public beast::unit_test::suite } jtx::PrettyAmount - issuerBalance( - jtx::Env& env, - jtx::Account const& account, - Issue const& issue) + issuerBalance(jtx::Env& env, jtx::Account const& account, Issue const& issue) { Json::Value params; params[jss::account] = account.human(); auto jrr = env.rpc("json", "gateway_balances", to_string(params)); auto const result = jrr[jss::result]; - auto const obligations = - result[jss::obligations][to_string(issue.currency)]; + auto const obligations = result[jss::obligations][to_string(issue.currency)]; if (obligations.isNull()) return {STAmount(issue, 0), account.name()}; STAmount const amount = amountFromString(issue, obligations.asString()); @@ -58,10 +51,7 @@ struct EscrowToken_test : public beast::unit_test::suite } jtx::PrettyAmount - issuerEscrowed( - jtx::Env& env, - jtx::Account const& account, - Issue const& issue) + issuerEscrowed(jtx::Env& env, jtx::Account const& account, Issue const& issue) { Json::Value params; params[jss::account] = account.human(); @@ -84,8 +74,7 @@ struct EscrowToken_test : public beast::unit_test::suite for (bool const withTokenEscrow : {false, true}) { - auto const amend = - withTokenEscrow ? features : features - featureTokenEscrow; + auto const amend = withTokenEscrow ? features : features - featureTokenEscrow; Env env{*this, amend}; auto const baseFee = env.current()->fees().base; auto const alice = Account("alice"); @@ -101,10 +90,8 @@ struct EscrowToken_test : public beast::unit_test::suite env(pay(gw, bob, USD(5000))); env.close(); - auto const createResult = - withTokenEscrow ? ter(tesSUCCESS) : ter(temBAD_AMOUNT); - auto const finishResult = - withTokenEscrow ? ter(tesSUCCESS) : ter(tecNO_TARGET); + auto const createResult = withTokenEscrow ? ter(tesSUCCESS) : ter(temBAD_AMOUNT); + auto const finishResult = withTokenEscrow ? ter(tesSUCCESS) : ter(tecNO_TARGET); auto const seq1 = env.seq(alice); env(escrow::create(alice, bob, USD(1'000)), @@ -134,8 +121,7 @@ struct EscrowToken_test : public beast::unit_test::suite for (bool const withTokenEscrow : {false, true}) { - auto const amend = - withTokenEscrow ? features : features - featureTokenEscrow; + auto const amend = withTokenEscrow ? features : features - featureTokenEscrow; Env env{*this, amend}; auto const baseFee = env.current()->fees().base; auto const alice = Account("alice"); @@ -246,10 +232,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const USD = gw["USD"]; env.fund(XRP(5000), alice, bob, gw); - env(escrow::create(alice, bob, USD(1)), - escrow::finish_time(env.now() + 1s), - fee(XRP(-1)), - ter(temBAD_FEE)); + env(escrow::create(alice, bob, USD(1)), escrow::finish_time(env.now() + 1s), fee(XRP(-1)), ter(temBAD_FEE)); env.close(); } @@ -559,8 +542,7 @@ struct EscrowToken_test : public beast::unit_test::suite env(pay(gw, bob, USD(1))); env.close(); - bool const largeMantissa = features[featureSingleAssetVault] || - features[featureLendingProtocol]; + bool const largeMantissa = features[featureSingleAssetVault] || features[featureLendingProtocol]; // alice cannot create escrow for 1/10 iou - precision loss env(escrow::create(alice, bob, USD(1)), @@ -868,9 +850,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); // alice cannot cancel because she is not authorized - env(escrow::cancel(bob, alice, seq1), - fee(baseFee), - ter(tecNO_AUTH)); + env(escrow::cancel(bob, alice, seq1), fee(baseFee), ter(tecNO_AUTH)); env.close(); } } @@ -914,8 +894,7 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(alice, USD) == preAliceUSD - USD(1'000)); BEAST_EXPECT(env.balance(bob, USD) == preBobUSD); - BEAST_EXPECT( - issuerBalance(env, gw, USD) == outstandingUSD - USD(1'000)); + BEAST_EXPECT(issuerBalance(env, gw, USD) == outstandingUSD - USD(1'000)); BEAST_EXPECT(issuerEscrowed(env, gw, USD) == USD(1'000)); } { @@ -949,8 +928,7 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(alice, USD) == preAliceUSD - USD(1'000)); BEAST_EXPECT(env.balance(bob, USD) == preBobUSD); - BEAST_EXPECT( - issuerBalance(env, gw, USD) == outstandingUSD - USD(1'000)); + BEAST_EXPECT(issuerBalance(env, gw, USD) == outstandingUSD - USD(1'000)); BEAST_EXPECT(issuerEscrowed(env, gw, USD) == USD(1'000)); } { @@ -996,32 +974,26 @@ struct EscrowToken_test : public beast::unit_test::suite env(escrow::create(alice, alice, USD(1'000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 500s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const aa = env.le(keylet::escrow(alice.id(), aseq)); BEAST_EXPECT(aa); { xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), aa) != aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), aa) != aod.end()); } { xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 4); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), aa) != iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), aa) != iod.end()); } env(escrow::create(bob, bob, USD(1'000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 2s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const bb = env.le(keylet::escrow(bob.id(), bseq)); BEAST_EXPECT(bb); @@ -1029,58 +1001,47 @@ struct EscrowToken_test : public beast::unit_test::suite { xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) != bod.end()); } { xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 5); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), bb) != iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), bb) != iod.end()); } env.close(5s); env(escrow::finish(alice, alice, aseq)); { BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), aa) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), aa) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) != bod.end()); xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 4); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), bb) != iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), bb) != iod.end()); } env.close(5s); env(escrow::cancel(bob, bob, bseq)); { BEAST_EXPECT(!env.le(keylet::escrow(bob.id(), bseq))); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) == bod.end()); xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 3); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), bb) == iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), bb) == iod.end()); } } { @@ -1099,18 +1060,13 @@ struct EscrowToken_test : public beast::unit_test::suite auto const aseq = env.seq(alice); auto const bseq = env.seq(bob); - env(escrow::create(alice, bob, USD(1'000)), - escrow::finish_time(env.now() + 1s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + env(escrow::create(alice, bob, USD(1'000)), escrow::finish_time(env.now() + 1s)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); env(escrow::create(bob, carol, USD(1'000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 2s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const ab = env.le(keylet::escrow(alice.id(), aseq)); @@ -1122,27 +1078,21 @@ struct EscrowToken_test : public beast::unit_test::suite { xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) != aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) != aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 3); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) != bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) != bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 2); - BEAST_EXPECT( - std::find(cod.begin(), cod.end(), bc) != cod.end()); + BEAST_EXPECT(std::find(cod.begin(), cod.end(), bc) != cod.end()); xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 5); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), ab) != iod.end()); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), bc) != iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), ab) != iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), bc) != iod.end()); } env.close(5s); @@ -1153,25 +1103,20 @@ struct EscrowToken_test : public beast::unit_test::suite xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) == bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) != bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 2); xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 4); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), ab) == iod.end()); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), bc) != iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), ab) == iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), bc) != iod.end()); } env.close(5s); @@ -1182,25 +1127,20 @@ struct EscrowToken_test : public beast::unit_test::suite xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) == bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) == bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 3); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), ab) == iod.end()); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), bc) == iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), ab) == iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), bc) == iod.end()); } } @@ -1218,12 +1158,9 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); auto const aseq = env.seq(alice); - env(escrow::create(alice, gw, USD(1'000)), - escrow::finish_time(env.now() + 1s)); + env(escrow::create(alice, gw, USD(1'000)), escrow::finish_time(env.now() + 1s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); env(escrow::create(gw, carol, USD(1'000)), escrow::finish_time(env.now() + 1s), @@ -1237,16 +1174,14 @@ struct EscrowToken_test : public beast::unit_test::suite { xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ag) != aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ag) != aod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 3); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), ag) != iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), ag) != iod.end()); } env.close(5s); @@ -1256,16 +1191,14 @@ struct EscrowToken_test : public beast::unit_test::suite xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ag) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ag) == aod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 2); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), ag) == iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), ag) == iod.end()); } } } @@ -1495,8 +1428,7 @@ struct EscrowToken_test : public beast::unit_test::suite fee(baseFee * 150)); env.close(); auto const transferRate = escrow::rate(env, alice, seq1); - BEAST_EXPECT( - transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); + BEAST_EXPECT(transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); // bob can finish escrow env(escrow::finish(bob, alice, seq1), @@ -1533,8 +1465,7 @@ struct EscrowToken_test : public beast::unit_test::suite fee(baseFee * 150)); env.close(); auto transferRate = escrow::rate(env, alice, seq1); - BEAST_EXPECT( - transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); + BEAST_EXPECT(transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); // issuer changes rate higher env(rate(gw, 1.26)); @@ -1576,8 +1507,7 @@ struct EscrowToken_test : public beast::unit_test::suite fee(baseFee * 150)); env.close(); auto transferRate = escrow::rate(env, alice, seq1); - BEAST_EXPECT( - transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); + BEAST_EXPECT(transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); // issuer changes rate lower env(rate(gw, 1.00)); @@ -1619,8 +1549,7 @@ struct EscrowToken_test : public beast::unit_test::suite fee(baseFee)); env.close(); auto transferRate = escrow::rate(env, alice, seq1); - BEAST_EXPECT( - transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); + BEAST_EXPECT(transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); // issuer changes rate lower env(rate(gw, 1.00)); @@ -1937,8 +1866,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); // clear freeze on alice trustline - env(trust( - gw, USD(10'000), alice, tfClearFreeze | tfClearDeepFreeze)); + env(trust(gw, USD(10'000), alice, tfClearFreeze | tfClearDeepFreeze)); env.close(); // create escrow success @@ -1962,8 +1890,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); // reset freeze on alice and bob trustline - env(trust( - gw, USD(10'000), alice, tfClearFreeze | tfClearDeepFreeze)); + env(trust(gw, USD(10'000), alice, tfClearFreeze | tfClearDeepFreeze)); env(trust(gw, USD(10'000), bob, tfClearFreeze | tfClearDeepFreeze)); env.close(); @@ -1980,9 +1907,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); // bob cancel escrow fails because of deep frozen assets - env(escrow::cancel(bob, alice, seq1), - fee(baseFee), - ter(tesSUCCESS)); + env(escrow::cancel(bob, alice, seq1), fee(baseFee), ter(tesSUCCESS)); env.close(); } } @@ -2079,8 +2004,7 @@ struct EscrowToken_test : public beast::unit_test::suite env(pay(gw, bob, USD(1))); env.close(); - bool const largeMantissa = features[featureSingleAssetVault] || - features[featureLendingProtocol]; + bool const largeMantissa = features[featureSingleAssetVault] || features[featureLendingProtocol]; // alice cannot create escrow for 1/10 iou - precision loss env(escrow::create(alice, bob, USD(1)), @@ -2117,8 +2041,7 @@ struct EscrowToken_test : public beast::unit_test::suite for (bool const withTokenEscrow : {false, true}) { - auto const amend = - withTokenEscrow ? features : features - featureTokenEscrow; + auto const amend = withTokenEscrow ? features : features - featureTokenEscrow; Env env{*this, amend}; auto const baseFee = env.current()->fees().base; auto const alice = Account("alice"); @@ -2127,19 +2050,14 @@ struct EscrowToken_test : public beast::unit_test::suite env.fund(XRP(5000), bob); MPTTester mptGw(env, gw, {.holders = {alice}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); auto const MPT = mptGw["MPT"]; env(pay(gw, alice, MPT(10'000))); env.close(); - auto const createResult = - withTokenEscrow ? ter(tesSUCCESS) : ter(temBAD_AMOUNT); - auto const finishResult = - withTokenEscrow ? ter(tesSUCCESS) : ter(tecNO_TARGET); + auto const createResult = withTokenEscrow ? ter(tesSUCCESS) : ter(temBAD_AMOUNT); + auto const finishResult = withTokenEscrow ? ter(tesSUCCESS) : ter(tecNO_TARGET); auto const seq1 = env.seq(alice); env(escrow::create(alice, bob, MPT(1'000)), @@ -2176,8 +2094,7 @@ struct EscrowToken_test : public beast::unit_test::suite for (bool const withMPT : {true, false}) { - auto const amend = - withMPT ? features : features - featureMPTokensV1; + auto const amend = withMPT ? features : features - featureMPTokensV1; Env env{*this, amend}; auto const baseFee = env.current()->fees().base; auto const alice = Account("alice"); @@ -2187,16 +2104,11 @@ struct EscrowToken_test : public beast::unit_test::suite Json::Value jv = escrow::create(alice, bob, XRP(1)); jv.removeMember(jss::Amount); - jv[jss::Amount][jss::mpt_issuance_id] = - "00000004A407AF5856CCF3C42619DAA925813FC955C72983"; + jv[jss::Amount][jss::mpt_issuance_id] = "00000004A407AF5856CCF3C42619DAA925813FC955C72983"; jv[jss::Amount][jss::value] = "-1"; auto const result = withMPT ? ter(temBAD_AMOUNT) : ter(temDISABLED); - env(jv, - escrow::condition(escrow::cb1), - escrow::finish_time(env.now() + 1s), - fee(baseFee * 150), - result); + env(jv, escrow::condition(escrow::cb1), escrow::finish_time(env.now() + 1s), fee(baseFee * 150), result); env.close(); } @@ -2209,10 +2121,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -2244,10 +2153,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); auto const MPT = mptGw["MPT"]; env(pay(gw, alice, MPT(10'000))); @@ -2271,11 +2177,9 @@ struct EscrowToken_test : public beast::unit_test::suite env.fund(XRP(10'000), alice, bob, gw); env.close(); - auto const mpt = xrpl::test::jtx::MPT( - alice.name(), makeMptID(env.seq(alice), alice)); + auto const mpt = xrpl::test::jtx::MPT(alice.name(), makeMptID(env.seq(alice), alice)); Json::Value jv = escrow::create(alice, bob, mpt(2)); - jv[jss::Amount][jss::mpt_issuance_id] = - "00000004A407AF5856CCF3C42619DAA925813FC955C72983"; + jv[jss::Amount][jss::mpt_issuance_id] = "00000004A407AF5856CCF3C42619DAA925813FC955C72983"; env(jv, escrow::condition(escrow::cb1), escrow::finish_time(env.now() + 1s), @@ -2293,8 +2197,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -2319,10 +2222,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); auto const MPT = mptGw["MPT"]; env(escrow::create(alice, bob, MPT(4)), @@ -2343,10 +2243,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = - tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = gw, .holder = alice}); auto const MPT = mptGw["MPT"]; @@ -2354,8 +2251,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); // unauthorize account - mptGw.authorize( - {.account = gw, .holder = alice, .flags = tfMPTUnauthorize}); + mptGw.authorize({.account = gw, .holder = alice, .flags = tfMPTUnauthorize}); env(escrow::create(alice, bob, MPT(5)), escrow::condition(escrow::cb1), @@ -2375,10 +2271,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = - tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = gw, .holder = alice}); mptGw.authorize({.account = bob}); @@ -2389,8 +2282,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); // unauthorize dest - mptGw.authorize( - {.account = gw, .holder = bob, .flags = tfMPTUnauthorize}); + mptGw.authorize({.account = gw, .holder = bob, .flags = tfMPTUnauthorize}); env(escrow::create(alice, bob, MPT(6)), escrow::condition(escrow::cb1), @@ -2410,9 +2302,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -2441,9 +2331,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -2471,8 +2359,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -2497,10 +2384,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -2524,10 +2408,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -2561,10 +2442,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = - tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = gw, .holder = alice}); mptGw.authorize({.account = bob}); @@ -2583,8 +2461,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); // unauthorize dest - mptGw.authorize( - {.account = gw, .holder = bob, .flags = tfMPTUnauthorize}); + mptGw.authorize({.account = gw, .holder = bob, .flags = tfMPTUnauthorize}); env(escrow::finish(bob, alice, seq1), escrow::condition(escrow::cb1), @@ -2604,20 +2481,17 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); auto const seq1 = env.seq(alice); - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) { - Sandbox sb(&view, tapNONE); - auto sleNew = - std::make_shared(keylet::escrow(alice, seq1)); - MPTIssue const mpt{ - MPTIssue{makeMptID(1, AccountID(0x4985601))}}; - STAmount amt(mpt, 10); - sleNew->setAccountID(sfDestination, bob); - sleNew->setFieldAmount(sfAmount, amt); - sb.insert(sleNew); - sb.apply(view); - return true; - }); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { + Sandbox sb(&view, tapNONE); + auto sleNew = std::make_shared(keylet::escrow(alice, seq1)); + MPTIssue const mpt{MPTIssue{makeMptID(1, AccountID(0x4985601))}}; + STAmount amt(mpt, 10); + sleNew->setAccountID(sfDestination, bob); + sleNew->setFieldAmount(sfAmount, amt); + sb.insert(sleNew); + sb.apply(view); + return true; + }); env(escrow::finish(bob, alice, seq1), escrow::condition(escrow::cb1), @@ -2637,9 +2511,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -2688,10 +2560,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); MPTTester mptGw(env, gw, {.holders = {alice}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); auto const MPT = mptGw["MPT"]; env(pay(gw, alice, MPT(10'000))); @@ -2724,10 +2593,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); MPTTester mptGw(env, gw, {.holders = {alice}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); auto const MPT = mptGw["MPT"]; env(pay(gw, alice, MPT(10'000))); @@ -2761,10 +2627,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); MPTTester mptGw(env, gw, {.holders = {alice}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); auto const MPT = mptGw["MPT"]; env(pay(gw, alice, MPT(10'000))); @@ -2804,10 +2667,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = - tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = gw, .holder = alice}); mptGw.authorize({.account = bob}); @@ -2826,8 +2686,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); // unauthorize account - mptGw.authorize( - {.account = gw, .holder = alice, .flags = tfMPTUnauthorize}); + mptGw.authorize({.account = gw, .holder = alice, .flags = tfMPTUnauthorize}); env(escrow::cancel(bob, alice, seq1), ter(tecNO_AUTH)); env.close(); @@ -2842,24 +2701,19 @@ struct EscrowToken_test : public beast::unit_test::suite env.fund(XRP(10'000), alice, bob); auto const seq1 = env.seq(alice); - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) { - Sandbox sb(&view, tapNONE); - auto sleNew = - std::make_shared(keylet::escrow(alice, seq1)); - MPTIssue const mpt{ - MPTIssue{makeMptID(1, AccountID(0x4985601))}}; - STAmount amt(mpt, 10); - sleNew->setAccountID(sfDestination, bob); - sleNew->setFieldAmount(sfAmount, amt); - sb.insert(sleNew); - sb.apply(view); - return true; - }); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { + Sandbox sb(&view, tapNONE); + auto sleNew = std::make_shared(keylet::escrow(alice, seq1)); + MPTIssue const mpt{MPTIssue{makeMptID(1, AccountID(0x4985601))}}; + STAmount amt(mpt, 10); + sleNew->setAccountID(sfDestination, bob); + sleNew->setFieldAmount(sfAmount, amt); + sb.insert(sleNew); + sb.apply(view); + return true; + }); - env(escrow::cancel(bob, alice, seq1), - fee(baseFee), - ter(tecOBJECT_NOT_FOUND)); + env(escrow::cancel(bob, alice, seq1), fee(baseFee), ter(tecOBJECT_NOT_FOUND)); env.close(); } } @@ -2881,10 +2735,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.fund(XRP(5000), bob); MPTTester mptGw(env, gw, {.holders = {alice, carol}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = carol}); auto const MPT = mptGw["MPT"]; @@ -3058,10 +2909,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3095,14 +2943,12 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(alice, MPT) == preAliceMPT - MPT(1)); BEAST_EXPECT(mptEscrowed(env, alice, MPT) == 0); - BEAST_EXPECT(!env.le(keylet::mptoken(MPT.mpt(), alice)) - ->isFieldPresent(sfLockedAmount)); + BEAST_EXPECT(!env.le(keylet::mptoken(MPT.mpt(), alice))->isFieldPresent(sfLockedAmount)); BEAST_EXPECT(env.balance(bob, MPT) == preBobMPT + MPT(1)); BEAST_EXPECT(mptEscrowed(env, bob, MPT) == 0); BEAST_EXPECT(env.balance(gw, MPT) == outstandingMPT); BEAST_EXPECT(issuerMPTEscrowed(env, MPT) == 0); - BEAST_EXPECT(!env.le(keylet::mptIssuance(MPT.mpt())) - ->isFieldPresent(sfLockedAmount)); + BEAST_EXPECT(!env.le(keylet::mptIssuance(MPT.mpt()))->isFieldPresent(sfLockedAmount)); } // Max MPT Amount Issued (Escrow Max MPT) @@ -3114,10 +2960,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3144,8 +2987,7 @@ struct EscrowToken_test : public beast::unit_test::suite fee(baseFee * 150)); env.close(); - BEAST_EXPECT( - env.balance(alice, MPT) == preAliceMPT - MPT(maxMPTokenAmount)); + BEAST_EXPECT(env.balance(alice, MPT) == preAliceMPT - MPT(maxMPTokenAmount)); BEAST_EXPECT(mptEscrowed(env, alice, MPT) == maxMPTokenAmount); BEAST_EXPECT(env.balance(bob, MPT) == preBobMPT); BEAST_EXPECT(mptEscrowed(env, bob, MPT) == 0); @@ -3166,11 +3008,9 @@ struct EscrowToken_test : public beast::unit_test::suite ter(tesSUCCESS)); env.close(); - BEAST_EXPECT( - env.balance(alice, MPT) == preAliceMPT - MPT(maxMPTokenAmount)); + BEAST_EXPECT(env.balance(alice, MPT) == preAliceMPT - MPT(maxMPTokenAmount)); BEAST_EXPECT(mptEscrowed(env, alice, MPT) == 0); - BEAST_EXPECT( - env.balance(bob, MPT) == preBobMPT + MPT(maxMPTokenAmount)); + BEAST_EXPECT(env.balance(bob, MPT) == preBobMPT + MPT(maxMPTokenAmount)); BEAST_EXPECT(mptEscrowed(env, bob, MPT) == 0); BEAST_EXPECT(env.balance(gw, MPT) == outstandingMPT); BEAST_EXPECT(issuerMPTEscrowed(env, MPT) == 0); @@ -3192,10 +3032,7 @@ struct EscrowToken_test : public beast::unit_test::suite Env env{*this, features}; MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3208,32 +3045,26 @@ struct EscrowToken_test : public beast::unit_test::suite env(escrow::create(alice, alice, MPT(1'000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 500s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const aa = env.le(keylet::escrow(alice.id(), aseq)); BEAST_EXPECT(aa); { xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), aa) != aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), aa) != aod.end()); } { xrpl::Dir iod(*env.current(), keylet::ownerDir(gw.id())); BEAST_EXPECT(std::distance(iod.begin(), iod.end()) == 1); - BEAST_EXPECT( - std::find(iod.begin(), iod.end(), aa) == iod.end()); + BEAST_EXPECT(std::find(iod.begin(), iod.end(), aa) == iod.end()); } env(escrow::create(bob, bob, MPT(1'000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 2s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const bb = env.le(keylet::escrow(bob.id(), bseq)); BEAST_EXPECT(bb); @@ -3241,41 +3072,33 @@ struct EscrowToken_test : public beast::unit_test::suite { xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) != bod.end()); } env.close(5s); env(escrow::finish(alice, alice, aseq)); { BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), aa) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), aa) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) != bod.end()); } env.close(5s); env(escrow::cancel(bob, bob, bseq)); { BEAST_EXPECT(!env.le(keylet::escrow(bob.id(), bseq))); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) == bod.end()); } } @@ -3284,10 +3107,7 @@ struct EscrowToken_test : public beast::unit_test::suite Env env{*this, features}; MPTTester mptGw(env, gw, {.holders = {alice, bob, carol}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); mptGw.authorize({.account = carol}); @@ -3299,18 +3119,13 @@ struct EscrowToken_test : public beast::unit_test::suite auto const aseq = env.seq(alice); auto const bseq = env.seq(bob); - env(escrow::create(alice, bob, MPT(1'000)), - escrow::finish_time(env.now() + 1s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + env(escrow::create(alice, bob, MPT(1'000)), escrow::finish_time(env.now() + 1s)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); env(escrow::create(bob, carol, MPT(1'000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 2s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const ab = env.le(keylet::escrow(alice.id(), aseq)); @@ -3322,20 +3137,16 @@ struct EscrowToken_test : public beast::unit_test::suite { xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 2); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) != aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) != aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 3); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) != bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) != bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 2); - BEAST_EXPECT( - std::find(cod.begin(), cod.end(), bc) != cod.end()); + BEAST_EXPECT(std::find(cod.begin(), cod.end(), bc) != cod.end()); } env.close(5s); @@ -3346,15 +3157,12 @@ struct EscrowToken_test : public beast::unit_test::suite xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) == bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) != bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 2); @@ -3368,15 +3176,12 @@ struct EscrowToken_test : public beast::unit_test::suite xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bob.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) == bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) == bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); @@ -3399,10 +3204,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); auto const MPT = mptGw["MPT"]; env(pay(gw, alice, MPT(10'000))); @@ -3464,10 +3266,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.transferFee = 25000, - .ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + {.transferFee = 25000, .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3485,8 +3284,7 @@ struct EscrowToken_test : public beast::unit_test::suite fee(baseFee * 150)); env.close(); auto const transferRate = escrow::rate(env, alice, seq1); - BEAST_EXPECT( - transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); + BEAST_EXPECT(transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); BEAST_EXPECT(mptEscrowed(env, alice, MPT) == 125); BEAST_EXPECT(issuerMPTEscrowed(env, MPT) == 125); @@ -3502,11 +3300,9 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(alice, MPT) == preAlice - delta); BEAST_EXPECT(env.balance(bob, MPT) == MPT(10'100)); - auto const escrowedWithFix = - env.current()->rules().enabled(fixTokenEscrowV1) ? 0 : 25; + auto const escrowedWithFix = env.current()->rules().enabled(fixTokenEscrowV1) ? 0 : 25; auto const outstandingWithFix = - env.current()->rules().enabled(fixTokenEscrowV1) ? MPT(19'975) - : MPT(20'000); + env.current()->rules().enabled(fixTokenEscrowV1) ? MPT(19'975) : MPT(20'000); BEAST_EXPECT(mptEscrowed(env, alice, MPT) == escrowedWithFix); BEAST_EXPECT(issuerMPTEscrowed(env, MPT) == escrowedWithFix); BEAST_EXPECT(env.balance(gw, MPT) == -outstandingWithFix); @@ -3522,10 +3318,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.transferFee = 25000, - .ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + {.transferFee = 25000, .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3545,8 +3338,7 @@ struct EscrowToken_test : public beast::unit_test::suite fee(baseFee * 150)); env.close(); auto const transferRate = escrow::rate(env, alice, seq1); - BEAST_EXPECT( - transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); + BEAST_EXPECT(transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); // alice can cancel escrow env(escrow::cancel(alice, alice, seq1), fee(baseFee)); @@ -3569,10 +3361,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.transferFee = 25000, - .ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + {.transferFee = 25000, .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3590,8 +3379,7 @@ struct EscrowToken_test : public beast::unit_test::suite fee(baseFee * 150)); env.close(); auto const transferRate = escrow::rate(env, alice, seq1); - BEAST_EXPECT( - transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); + BEAST_EXPECT(transferRate.value == std::uint32_t(1'000'000'000 * 1.25)); BEAST_EXPECT(mptEscrowed(env, alice, MPT) == 125); BEAST_EXPECT(issuerMPTEscrowed(env, MPT) == 125); @@ -3626,9 +3414,7 @@ struct EscrowToken_test : public beast::unit_test::suite MPTTester mptGw(env, gw, {.holders = {alice, bob}}); mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTRequireAuth}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = gw, .holder = alice}); mptGw.authorize({.account = bob}); @@ -3668,10 +3454,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer | tfMPTCanLock}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3719,8 +3502,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3788,10 +3570,7 @@ struct EscrowToken_test : public beast::unit_test::suite auto const gw = Account("gw"); MPTTester mptGw(env, gw, {.holders = {alice, bob}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); mptGw.authorize({.account = bob}); auto const MPT = mptGw["MPT"]; @@ -3815,10 +3594,7 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(mptEscrowed(env, bob, MPT) == 0); BEAST_EXPECT(env.balance(gw, MPT) == MPT(-10)); mptGw.authorize({.account = bob, .flags = tfMPTUnauthorize}); - mptGw.destroy( - {.id = mptGw.issuanceID(), - .ownerCount = 1, - .err = tecHAS_OBLIGATIONS}); + mptGw.destroy({.id = mptGw.issuanceID(), .ownerCount = 1, .err = tecHAS_OBLIGATIONS}); env(escrow::finish(bob, alice, seq1), escrow::condition(escrow::cb1), @@ -3842,10 +3618,7 @@ struct EscrowToken_test : public beast::unit_test::suite env.close(); MPTTester mptGw(env, gw, {.holders = {alice}}); - mptGw.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanEscrow | tfMPTCanTransfer}); + mptGw.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanEscrow | tfMPTCanTransfer}); mptGw.authorize({.account = alice}); auto const MPT = mptGw["MPT"]; env(pay(gw, alice, MPT(10'000))); @@ -3864,10 +3637,7 @@ struct EscrowToken_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(alice, MPT) == MPT(0)); BEAST_EXPECT(mptEscrowed(env, alice, MPT) == 10); - mptGw.authorize( - {.account = alice, - .flags = tfMPTUnauthorize, - .err = tecHAS_OBLIGATIONS}); + mptGw.authorize({.account = alice, .flags = tfMPTUnauthorize, .err = tecHAS_OBLIGATIONS}); env(escrow::finish(bob, alice, seq1), escrow::condition(escrow::cb1), @@ -3930,8 +3700,7 @@ public: { using namespace test::jtx; FeatureBitset const all{testable_amendments()}; - for (FeatureBitset const& feats : - {all - featureSingleAssetVault - featureLendingProtocol, all}) + for (FeatureBitset const& feats : {all - featureSingleAssetVault - featureLendingProtocol, all}) { testIOUWithFeats(feats); testMPTWithFeats(feats); diff --git a/src/test/app/Escrow_test.cpp b/src/test/app/Escrow_test.cpp index 2b7297009a..652049270f 100644 --- a/src/test/app/Escrow_test.cpp +++ b/src/test/app/Escrow_test.cpp @@ -27,8 +27,7 @@ struct Escrow_test : public beast::unit_test::suite Env env(*this, features); auto const baseFee = env.current()->fees().base; env.fund(XRP(5000), "alice", "bob"); - env(escrow::create("alice", "bob", XRP(1000)), - escrow::finish_time(env.now() + 1s)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::finish_time(env.now() + 1s)); env.close(); auto const seq1 = env.seq("alice"); @@ -71,15 +70,12 @@ struct Escrow_test : public beast::unit_test::suite auto const ts = env.now() + 97s; auto const seq = env.seq("alice"); - env(escrow::create("alice", "bob", XRP(1000)), - escrow::finish_time(ts)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::finish_time(ts)); // Advance the ledger, verifying that the finish won't complete // prematurely. for (; env.now() < ts; env.close()) - env(escrow::finish("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); + env(escrow::finish("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); env(escrow::finish("bob", "alice", seq), fee(baseFee * 150)); } @@ -95,16 +91,12 @@ struct Escrow_test : public beast::unit_test::suite auto const ts = env.now() + 117s; auto const seq = env.seq("alice"); - env(escrow::create("alice", "bob", XRP(1000)), - escrow::condition(escrow::cb1), - escrow::cancel_time(ts)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::condition(escrow::cb1), escrow::cancel_time(ts)); // Advance the ledger, verifying that the cancel won't complete // prematurely. for (; env.now() < ts; env.close()) - env(escrow::cancel("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); + env(escrow::cancel("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); // Verify that a finish won't work anymore. env(escrow::finish("bob", "alice", seq), @@ -129,26 +121,18 @@ struct Escrow_test : public beast::unit_test::suite auto const cts = env.now() + 192s; auto const seq = env.seq("alice"); - env(escrow::create("alice", "bob", XRP(1000)), - escrow::finish_time(fts), - escrow::cancel_time(cts)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::finish_time(fts), escrow::cancel_time(cts)); // Advance the ledger, verifying that the finish and cancel won't // complete prematurely. for (; env.now() < fts; env.close()) { - env(escrow::finish("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); - env(escrow::cancel("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); + env(escrow::finish("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); + env(escrow::cancel("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); } // Verify that a cancel still won't work - env(escrow::cancel("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); + env(escrow::cancel("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); // And verify that a finish will env(escrow::finish("bob", "alice", seq), fee(baseFee * 150)); @@ -166,34 +150,24 @@ struct Escrow_test : public beast::unit_test::suite auto const cts = env.now() + 184s; auto const seq = env.seq("alice"); - env(escrow::create("alice", "bob", XRP(1000)), - escrow::finish_time(fts), - escrow::cancel_time(cts)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::finish_time(fts), escrow::cancel_time(cts)); // Advance the ledger, verifying that the finish and cancel won't // complete prematurely. for (; env.now() < fts; env.close()) { - env(escrow::finish("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); - env(escrow::cancel("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); + env(escrow::finish("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); + env(escrow::cancel("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); } // Continue advancing, verifying that the cancel won't complete // prematurely. At this point a finish would succeed. for (; env.now() < cts; env.close()) - env(escrow::cancel("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); + env(escrow::cancel("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); // Verify that finish will no longer work, since we are past the // cancel activation time. - env(escrow::finish("bob", "alice", seq), - fee(baseFee * 150), - ter(tecNO_PERMISSION)); + env(escrow::finish("bob", "alice", seq), fee(baseFee * 150), ter(tecNO_PERMISSION)); // And verify that a cancel will succeed. env(escrow::cancel("bob", "alice", seq), fee(baseFee * 150)); @@ -218,17 +192,12 @@ struct Escrow_test : public beast::unit_test::suite // Check to make sure that we correctly detect if tags are really // required: env(fset(bob, asfRequireDest)); - env(escrow::create(alice, bob, XRP(1000)), - escrow::finish_time(env.now() + 1s), - ter(tecDST_TAG_NEEDED)); + env(escrow::create(alice, bob, XRP(1000)), escrow::finish_time(env.now() + 1s), ter(tecDST_TAG_NEEDED)); // set source and dest tags auto const seq = env.seq(alice); - env(escrow::create(alice, bob, XRP(1000)), - escrow::finish_time(env.now() + 1s), - stag(1), - dtag(2)); + env(escrow::create(alice, bob, XRP(1000)), escrow::finish_time(env.now() + 1s), stag(1), dtag(2)); auto const sle = env.le(keylet::escrow(alice.id(), seq)); BEAST_EXPECT(sle); @@ -259,8 +228,7 @@ struct Escrow_test : public beast::unit_test::suite env.fund(XRP(5000), "bob", "george"); env(fset("george", asfDisallowXRP)); - env(escrow::create("bob", "george", XRP(10)), - escrow::finish_time(env.now() + 1s)); + env(escrow::create("bob", "george", XRP(10)), escrow::finish_time(env.now() + 1s)); } } @@ -307,9 +275,7 @@ struct Escrow_test : public beast::unit_test::suite fee(baseFee * 150)); env.close(); env(escrow::finish("carol", "alice", seqFt), fee(150 * baseFee)); - BEAST_EXPECT( - env.balance("bob") == - XRP(5200)); // 5100 (from last transaction) + 100 + BEAST_EXPECT(env.balance("bob") == XRP(5200)); // 5100 (from last transaction) + 100 } void @@ -332,9 +298,7 @@ struct Escrow_test : public beast::unit_test::suite ter(temINVALID_FLAG)); // Finish time is in the past - env(escrow::create("alice", "bob", XRP(1000)), - escrow::finish_time(env.now() - 5s), - ter(tecNO_PERMISSION)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::finish_time(env.now() - 5s), ter(tecNO_PERMISSION)); // Cancel time is in the past env(escrow::create("alice", "bob", XRP(1000)), @@ -343,45 +307,33 @@ struct Escrow_test : public beast::unit_test::suite ter(tecNO_PERMISSION)); // no destination account - env(escrow::create("alice", "carol", XRP(1000)), - escrow::finish_time(env.now() + 1s), - ter(tecNO_DST)); + env(escrow::create("alice", "carol", XRP(1000)), escrow::finish_time(env.now() + 1s), ter(tecNO_DST)); env.fund(XRP(5000), "carol"); // Using non-XRP: - bool const withTokenEscrow = - env.current()->rules().enabled(featureTokenEscrow); + bool const withTokenEscrow = env.current()->rules().enabled(featureTokenEscrow); { // tecNO_PERMISSION: token escrow is enabled but the issuer did not // set the asfAllowTrustLineLocking flag - auto const txResult = - withTokenEscrow ? ter(tecNO_PERMISSION) : ter(temBAD_AMOUNT); + auto const txResult = withTokenEscrow ? ter(tecNO_PERMISSION) : ter(temBAD_AMOUNT); env(escrow::create("alice", "carol", Account("alice")["USD"](500)), escrow::finish_time(env.now() + 5s), txResult); } // Sending zero or no XRP: - env(escrow::create("alice", "carol", XRP(0)), - escrow::finish_time(env.now() + 1s), - ter(temBAD_AMOUNT)); - env(escrow::create("alice", "carol", XRP(-1000)), - escrow::finish_time(env.now() + 1s), - ter(temBAD_AMOUNT)); + env(escrow::create("alice", "carol", XRP(0)), escrow::finish_time(env.now() + 1s), ter(temBAD_AMOUNT)); + env(escrow::create("alice", "carol", XRP(-1000)), escrow::finish_time(env.now() + 1s), ter(temBAD_AMOUNT)); // Fail if neither CancelAfter nor FinishAfter are specified: env(escrow::create("alice", "carol", XRP(1)), ter(temBAD_EXPIRATION)); // Fail if neither a FinishTime nor a condition are attached: - env(escrow::create("alice", "carol", XRP(1)), - escrow::cancel_time(env.now() + 1s), - ter(temMALFORMED)); + env(escrow::create("alice", "carol", XRP(1)), escrow::cancel_time(env.now() + 1s), ter(temMALFORMED)); // Fail if FinishAfter has already passed: - env(escrow::create("alice", "carol", XRP(1)), - escrow::finish_time(env.now() - 1s), - ter(tecNO_PERMISSION)); + env(escrow::create("alice", "carol", XRP(1)), escrow::finish_time(env.now() - 1s), ter(tecNO_PERMISSION)); // If both CancelAfter and FinishAfter are set, then CancelAfter must // be strictly later than FinishAfter. @@ -414,18 +366,13 @@ struct Escrow_test : public beast::unit_test::suite { // Fail if the sender wants to send more than he has: auto const accountReserve = drops(env.current()->fees().reserve); - auto const accountIncrement = - drops(env.current()->fees().increment); + auto const accountIncrement = drops(env.current()->fees().increment); env.fund(accountReserve + accountIncrement + XRP(50), "daniel"); - env(escrow::create("daniel", "bob", XRP(51)), - escrow::finish_time(env.now() + 1s), - ter(tecUNFUNDED)); + env(escrow::create("daniel", "bob", XRP(51)), escrow::finish_time(env.now() + 1s), ter(tecUNFUNDED)); env.fund(accountReserve + accountIncrement + XRP(50), "evan"); - env(escrow::create("evan", "bob", XRP(50)), - escrow::finish_time(env.now() + 1s), - ter(tecUNFUNDED)); + env(escrow::create("evan", "bob", XRP(50)), escrow::finish_time(env.now() + 1s), ter(tecUNFUNDED)); env.fund(accountReserve, "frank"); env(escrow::create("frank", "bob", XRP(1)), @@ -436,21 +383,16 @@ struct Escrow_test : public beast::unit_test::suite { // Specify incorrect sequence number env.fund(XRP(5000), "hannah"); auto const seq = env.seq("hannah"); - env(escrow::create("hannah", "hannah", XRP(10)), - escrow::finish_time(env.now() + 1s), - fee(150 * baseFee)); + env(escrow::create("hannah", "hannah", XRP(10)), escrow::finish_time(env.now() + 1s), fee(150 * baseFee)); env.close(); - env(escrow::finish("hannah", "hannah", seq + 7), - fee(150 * baseFee), - ter(tecNO_TARGET)); + env(escrow::finish("hannah", "hannah", seq + 7), fee(150 * baseFee), ter(tecNO_TARGET)); } { // Try to specify a condition for a non-conditional payment env.fund(XRP(5000), "ivan"); auto const seq = env.seq("ivan"); - env(escrow::create("ivan", "ivan", XRP(10)), - escrow::finish_time(env.now() + 1s)); + env(escrow::create("ivan", "ivan", XRP(10)), escrow::finish_time(env.now() + 1s)); env.close(); env(escrow::finish("ivan", "ivan", seq), escrow::condition(escrow::cb1), @@ -474,8 +416,7 @@ struct Escrow_test : public beast::unit_test::suite auto const baseFee = env.current()->fees().base; env.fund(XRP(5000), "alice", "bob"); auto const seq = env.seq("alice"); - env(escrow::create("alice", "alice", XRP(1000)), - escrow::finish_time(env.now() + 5s)); + env(escrow::create("alice", "alice", XRP(1000)), escrow::finish_time(env.now() + 5s)); env.require(balance("alice", XRP(4000) - drops(baseFee))); // Not enough time has elapsed for a finish and canceling isn't @@ -499,8 +440,7 @@ struct Escrow_test : public beast::unit_test::suite auto const baseFee = env.current()->fees().base; env.fund(XRP(5000), "alice", "bob", "zelda"); auto const seq = env.seq("alice"); - env(escrow::create("alice", "bob", XRP(1000)), - escrow::finish_time(env.now() + 5s)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::finish_time(env.now() + 5s)); env.require(balance("alice", XRP(4000) - drops(baseFee))); // Not enough time has elapsed for a finish and canceling isn't @@ -530,8 +470,7 @@ struct Escrow_test : public beast::unit_test::suite env.close(); auto const seq = env.seq("alice"); - env(escrow::create("alice", "bob", XRP(1000)), - escrow::finish_time(env.now() + 5s)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::finish_time(env.now() + 5s)); env.require(balance("alice", XRP(4000) - drops(baseFee))); // Not enough time has elapsed for a finish and canceling isn't @@ -571,8 +510,7 @@ struct Escrow_test : public beast::unit_test::suite env.close(); auto const seq = env.seq("alice"); - env(escrow::create("alice", "bob", XRP(1000)), - escrow::finish_time(env.now() + 5s)); + env(escrow::create("alice", "bob", XRP(1000)), escrow::finish_time(env.now() + 5s)); env.require(balance("alice", XRP(4000) - drops(baseFee))); env.close(); @@ -620,10 +558,8 @@ struct Escrow_test : public beast::unit_test::suite // requires the fulfillment associated with the escrow. env(escrow::cancel("alice", "alice", seq), ter(tecNO_PERMISSION)); env(escrow::cancel("bob", "alice", seq), ter(tecNO_PERMISSION)); - env(escrow::finish("bob", "alice", seq), - ter(tecCRYPTOCONDITION_ERROR)); - env(escrow::finish("alice", "alice", seq), - ter(tecCRYPTOCONDITION_ERROR)); + env(escrow::finish("bob", "alice", seq), ter(tecCRYPTOCONDITION_ERROR)); + env(escrow::finish("alice", "alice", seq), ter(tecCRYPTOCONDITION_ERROR)); env.close(); env(escrow::finish("bob", "alice", seq), @@ -645,10 +581,8 @@ struct Escrow_test : public beast::unit_test::suite env.close(); // Finish is now possible but requires the cryptocondition. - env(escrow::finish("bob", "alice", seq), - ter(tecCRYPTOCONDITION_ERROR)); - env(escrow::finish("alice", "alice", seq), - ter(tecCRYPTOCONDITION_ERROR)); + env(escrow::finish("bob", "alice", seq), ter(tecCRYPTOCONDITION_ERROR)); + env(escrow::finish("alice", "alice", seq), ter(tecCRYPTOCONDITION_ERROR)); // Enable deposit authorization. After this only Alice can finish // the escrow. @@ -689,12 +623,9 @@ struct Escrow_test : public beast::unit_test::suite env.close(); // Finish is now possible but requires the cryptocondition. - env(escrow::finish("alice", "alice", seq), - ter(tecCRYPTOCONDITION_ERROR)); - env(escrow::finish("bob", "alice", seq), - ter(tecCRYPTOCONDITION_ERROR)); - env(escrow::finish("zelda", "alice", seq), - ter(tecCRYPTOCONDITION_ERROR)); + env(escrow::finish("alice", "alice", seq), ter(tecCRYPTOCONDITION_ERROR)); + env(escrow::finish("bob", "alice", seq), ter(tecCRYPTOCONDITION_ERROR)); + env(escrow::finish("zelda", "alice", seq), ter(tecCRYPTOCONDITION_ERROR)); // Alice enables deposit authorization. After this only Alice or // Zelda (because Zelda is preauthorized) can finish the escrow. @@ -742,8 +673,7 @@ struct Escrow_test : public beast::unit_test::suite BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1); // Attempt to finish without a fulfillment - env(escrow::finish("bob", "alice", seq), - ter(tecCRYPTOCONDITION_ERROR)); + env(escrow::finish("bob", "alice", seq), ter(tecCRYPTOCONDITION_ERROR)); BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1); // Attempt to finish with a condition instead of a fulfillment @@ -1079,12 +1009,8 @@ struct Escrow_test : public beast::unit_test::suite // Assemble finish that is missing the Condition or the Fulfillment // since either both must be present, or neither can: - env(escrow::finish("bob", "alice", seq), - escrow::condition(escrow::cb3), - ter(temMALFORMED)); - env(escrow::finish("bob", "alice", seq), - escrow::fulfillment(escrow::fb3), - ter(temMALFORMED)); + env(escrow::finish("bob", "alice", seq), escrow::condition(escrow::cb3), ter(temMALFORMED)); + env(escrow::finish("bob", "alice", seq), escrow::fulfillment(escrow::fb3), ter(temMALFORMED)); // Now finish it. env(escrow::finish("bob", "alice", seq), @@ -1099,12 +1025,10 @@ struct Escrow_test : public beast::unit_test::suite Env env(*this, features); env.fund(XRP(5000), "alice", "bob"); - std::array cb = { - {0xA2, 0x2B, 0x80, 0x20, 0x42, 0x4A, 0x70, 0x49, 0x49, - 0x52, 0x92, 0x67, 0xB6, 0x21, 0xB3, 0xD7, 0x91, 0x19, - 0xD7, 0x29, 0xB2, 0x38, 0x2C, 0xED, 0x8B, 0x29, 0x6C, - 0x3C, 0x02, 0x8F, 0xA9, 0x7D, 0x35, 0x0F, 0x6D, 0x07, - 0x81, 0x03, 0x06, 0x34, 0xD2, 0x82, 0x02, 0x03, 0xC8}}; + std::array cb = {{0xA2, 0x2B, 0x80, 0x20, 0x42, 0x4A, 0x70, 0x49, 0x49, 0x52, 0x92, 0x67, + 0xB6, 0x21, 0xB3, 0xD7, 0x91, 0x19, 0xD7, 0x29, 0xB2, 0x38, 0x2C, 0xED, + 0x8B, 0x29, 0x6C, 0x3C, 0x02, 0x8F, 0xA9, 0x7D, 0x35, 0x0F, 0x6D, 0x07, + 0x81, 0x03, 0x06, 0x34, 0xD2, 0x82, 0x02, 0x03, 0xC8}}; // FIXME: this transaction should, eventually, return temDISABLED // instead of temMALFORMED. @@ -1136,9 +1060,7 @@ struct Escrow_test : public beast::unit_test::suite env(escrow::create(alice, alice, XRP(1000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 500s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const aa = env.le(keylet::escrow(alice.id(), aseq)); BEAST_EXPECT(aa); @@ -1146,16 +1068,13 @@ struct Escrow_test : public beast::unit_test::suite { xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), aa) != aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), aa) != aod.end()); } env(escrow::create(bruce, bruce, XRP(1000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 2s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const bb = env.le(keylet::escrow(bruce.id(), bseq)); BEAST_EXPECT(bb); @@ -1163,41 +1082,33 @@ struct Escrow_test : public beast::unit_test::suite { xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) != bod.end()); } env.close(5s); env(escrow::finish(alice, alice, aseq)); { BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq))); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), aa) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), aa) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) != bod.end()); } env.close(5s); env(escrow::cancel(bruce, bruce, bseq)); { BEAST_EXPECT(!env.le(keylet::escrow(bruce.id(), bseq))); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 0); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bb) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) == bod.end()); } } { @@ -1208,18 +1119,13 @@ struct Escrow_test : public beast::unit_test::suite auto const aseq = env.seq(alice); auto const bseq = env.seq(bruce); - env(escrow::create(alice, bruce, XRP(1000)), - escrow::finish_time(env.now() + 1s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + env(escrow::create(alice, bruce, XRP(1000)), escrow::finish_time(env.now() + 1s)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); env(escrow::create(bruce, carol, XRP(1000)), escrow::finish_time(env.now() + 1s), escrow::cancel_time(env.now() + 2s)); - BEAST_EXPECT( - (*env.meta())[sfTransactionResult] == - static_cast(tesSUCCESS)); + BEAST_EXPECT((*env.meta())[sfTransactionResult] == static_cast(tesSUCCESS)); env.close(5s); auto const ab = env.le(keylet::escrow(alice.id(), aseq)); @@ -1231,20 +1137,16 @@ struct Escrow_test : public beast::unit_test::suite { xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) != aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) != aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) != bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) != bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); - BEAST_EXPECT( - std::find(cod.begin(), cod.end(), bc) != cod.end()); + BEAST_EXPECT(std::find(cod.begin(), cod.end(), bc) != cod.end()); } env.close(5s); @@ -1255,15 +1157,12 @@ struct Escrow_test : public beast::unit_test::suite xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) == bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) != bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) != bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1); @@ -1277,15 +1176,12 @@ struct Escrow_test : public beast::unit_test::suite xrpl::Dir aod(*env.current(), keylet::ownerDir(alice.id())); BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0); - BEAST_EXPECT( - std::find(aod.begin(), aod.end(), ab) == aod.end()); + BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) == aod.end()); xrpl::Dir bod(*env.current(), keylet::ownerDir(bruce.id())); BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 0); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), ab) == bod.end()); - BEAST_EXPECT( - std::find(bod.begin(), bod.end(), bc) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) == bod.end()); + BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) == bod.end()); xrpl::Dir cod(*env.current(), keylet::ownerDir(carol.id())); BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 0); @@ -1309,16 +1205,8 @@ struct Escrow_test : public beast::unit_test::suite { auto const jtx = env.jt( - escrow::create("alice", "carol", XRP(1000)), - escrow::finish_time(env.now() + 1s), - seq(1), - fee(baseFee)); - auto const pf = preflight( - env.app(), - env.current()->rules(), - *jtx.stx, - tapNONE, - env.journal); + escrow::create("alice", "carol", XRP(1000)), escrow::finish_time(env.now() + 1s), seq(1), fee(baseFee)); + auto const pf = preflight(env.app(), env.current()->rules(), *jtx.stx, tapNONE, env.journal); BEAST_EXPECT(pf.ter == tesSUCCESS); BEAST_EXPECT(!pf.consequences.isBlocker()); BEAST_EXPECT(pf.consequences.fee() == drops(baseFee)); @@ -1326,14 +1214,8 @@ struct Escrow_test : public beast::unit_test::suite } { - auto const jtx = - env.jt(escrow::cancel("bob", "alice", 3), seq(1), fee(baseFee)); - auto const pf = preflight( - env.app(), - env.current()->rules(), - *jtx.stx, - tapNONE, - env.journal); + auto const jtx = env.jt(escrow::cancel("bob", "alice", 3), seq(1), fee(baseFee)); + auto const pf = preflight(env.app(), env.current()->rules(), *jtx.stx, tapNONE, env.journal); BEAST_EXPECT(pf.ter == tesSUCCESS); BEAST_EXPECT(!pf.consequences.isBlocker()); BEAST_EXPECT(pf.consequences.fee() == drops(baseFee)); @@ -1341,14 +1223,8 @@ struct Escrow_test : public beast::unit_test::suite } { - auto const jtx = - env.jt(escrow::finish("bob", "alice", 3), seq(1), fee(baseFee)); - auto const pf = preflight( - env.app(), - env.current()->rules(), - *jtx.stx, - tapNONE, - env.journal); + auto const jtx = env.jt(escrow::finish("bob", "alice", 3), seq(1), fee(baseFee)); + auto const pf = preflight(env.app(), env.current()->rules(), *jtx.stx, tapNONE, env.journal); BEAST_EXPECT(pf.ter == tesSUCCESS); BEAST_EXPECT(!pf.consequences.isBlocker()); BEAST_EXPECT(pf.consequences.fee() == drops(baseFee)); @@ -1396,9 +1272,7 @@ struct Escrow_test : public beast::unit_test::suite auto const ts = env.now() + 97s; std::uint32_t const escrowSeq = aliceTicket; - env(escrow::create(alice, bob, XRP(1000)), - escrow::finish_time(ts), - ticket::use(aliceTicket)); + env(escrow::create(alice, bob, XRP(1000)), escrow::finish_time(ts), ticket::use(aliceTicket)); BEAST_EXPECT(env.seq(alice) == aliceRootSeq); env.require(tickets(alice, 0)); env.require(tickets(bob, bobTicketCount)); @@ -1415,15 +1289,10 @@ struct Escrow_test : public beast::unit_test::suite } // bob tries to re-use a ticket, which is rejected. - env(escrow::finish(bob, alice, escrowSeq), - fee(150 * baseFee), - ticket::use(bobTicket), - ter(tefNO_TICKET)); + env(escrow::finish(bob, alice, escrowSeq), fee(150 * baseFee), ticket::use(bobTicket), ter(tefNO_TICKET)); // bob uses one of his remaining tickets. Success! - env(escrow::finish(bob, alice, escrowSeq), - fee(150 * baseFee), - ticket::use(--bobTicket)); + env(escrow::finish(bob, alice, escrowSeq), fee(150 * baseFee), ticket::use(--bobTicket)); env.close(); BEAST_EXPECT(env.seq(bob) == bobRootSeq); } @@ -1485,9 +1354,7 @@ struct Escrow_test : public beast::unit_test::suite BEAST_EXPECT(env.seq(bob) == bobRootSeq); // Verify that the cancel succeeds. - env(escrow::cancel(bob, alice, escrowSeq), - fee(150 * baseFee), - ticket::use(bobTicket++)); + env(escrow::cancel(bob, alice, escrowSeq), fee(150 * baseFee), ticket::use(bobTicket++)); env.close(); BEAST_EXPECT(env.seq(bob) == bobRootSeq); @@ -1519,8 +1386,7 @@ struct Escrow_test : public beast::unit_test::suite env.close(); auto const seq = env.seq(alice); - env(escrow::create(alice, bob, XRP(1000)), - escrow::finish_time(env.now() + 1s)); + env(escrow::create(alice, bob, XRP(1000)), escrow::finish_time(env.now() + 1s)); env.close(); env(fset(bob, asfDepositAuth)); @@ -1531,9 +1397,7 @@ struct Escrow_test : public beast::unit_test::suite std::string const credIdx = "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B" "E4"; - env(escrow::finish(bob, alice, seq), - credentials::ids({credIdx}), - ter(temDISABLED)); + env(escrow::finish(bob, alice, seq), credentials::ids({credIdx}), ter(temDISABLED)); } { @@ -1544,13 +1408,11 @@ struct Escrow_test : public beast::unit_test::suite env(credentials::create(carol, zelda, credType)); env.close(); - auto const jv = - credentials::ledgerEntry(env, carol, zelda, credType); + auto const jv = credentials::ledgerEntry(env, carol, zelda, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); auto const seq = env.seq(alice); - env(escrow::create(alice, bob, XRP(1000)), - escrow::finish_time(env.now() + 50s)); + env(escrow::create(alice, bob, XRP(1000)), escrow::finish_time(env.now() + 50s)); env.close(); // Bob require pre-authorization @@ -1558,9 +1420,7 @@ struct Escrow_test : public beast::unit_test::suite env.close(); // Fail, credentials not accepted - env(escrow::finish(carol, alice, seq), - credentials::ids({credIdx}), - ter(tecBAD_CREDENTIALS)); + env(escrow::finish(carol, alice, seq), credentials::ids({credIdx}), ter(tecBAD_CREDENTIALS)); env.close(); @@ -1568,14 +1428,10 @@ struct Escrow_test : public beast::unit_test::suite env.close(); // Fail, credentials doesn’t belong to root account - env(escrow::finish(dillon, alice, seq), - credentials::ids({credIdx}), - ter(tecBAD_CREDENTIALS)); + env(escrow::finish(dillon, alice, seq), credentials::ids({credIdx}), ter(tecBAD_CREDENTIALS)); // Fail, no depositPreauth - env(escrow::finish(carol, alice, seq), - credentials::ids({credIdx}), - ter(tecNO_PERMISSION)); + env(escrow::finish(carol, alice, seq), credentials::ids({credIdx}), ter(tecNO_PERMISSION)); env(deposit::authCredentials(bob, {{zelda, credType}})); env.close(); @@ -1599,13 +1455,11 @@ struct Escrow_test : public beast::unit_test::suite env.close(); env(credentials::accept(carol, zelda, credType)); env.close(); - auto const jv = - credentials::ledgerEntry(env, carol, zelda, credType); + auto const jv = credentials::ledgerEntry(env, carol, zelda, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); auto const seq = env.seq(alice); - env(escrow::create(alice, bob, XRP(1000)), - escrow::finish_time(env.now() + 50s)); + env(escrow::create(alice, bob, XRP(1000)), escrow::finish_time(env.now() + 50s)); // time advance env.close(); env.close(); @@ -1626,13 +1480,10 @@ struct Escrow_test : public beast::unit_test::suite env(credentials::accept(bob, zelda, credType2)); env.close(); auto const credIdxBob = - credentials::ledgerEntry( - env, bob, zelda, credType2)[jss::result][jss::index] - .asString(); + credentials::ledgerEntry(env, bob, zelda, credType2)[jss::result][jss::index].asString(); auto const seq = env.seq(alice); - env(escrow::create(alice, bob, XRP(1000)), - escrow::finish_time(env.now() + 1s)); + env(escrow::create(alice, bob, XRP(1000)), escrow::finish_time(env.now() + 1s)); env.close(); // Bob require pre-authorization @@ -1642,8 +1493,7 @@ struct Escrow_test : public beast::unit_test::suite env.close(); // Use any valid credentials if account == dst - env(escrow::finish(bob, alice, seq), - credentials::ids({credIdxBob})); + env(escrow::finish(bob, alice, seq), credentials::ids({credIdxBob})); env.close(); } } diff --git a/src/test/app/FeeVote_test.cpp b/src/test/app/FeeVote_test.cpp index c7f33544f9..15dd385d65 100644 --- a/src/test/app/FeeVote_test.cpp +++ b/src/test/app/FeeVote_test.cpp @@ -27,10 +27,7 @@ struct FeeSettingsFields }; STTx -createFeeTx( - Rules const& rules, - std::uint32_t seq, - FeeSettingsFields const& fields) +createFeeTx(Rules const& rules, std::uint32_t seq, FeeSettingsFields const& fields) { auto fill = [&](auto& obj) { obj.setAccountID(sfAccount, AccountID()); @@ -39,30 +36,18 @@ createFeeTx( if (rules.enabled(featureXRPFees)) { // New XRPFees format - all three fields are REQUIRED + obj.setFieldAmount(sfBaseFeeDrops, fields.baseFeeDrops ? *fields.baseFeeDrops : XRPAmount{0}); + obj.setFieldAmount(sfReserveBaseDrops, fields.reserveBaseDrops ? *fields.reserveBaseDrops : XRPAmount{0}); obj.setFieldAmount( - sfBaseFeeDrops, - fields.baseFeeDrops ? *fields.baseFeeDrops : XRPAmount{0}); - obj.setFieldAmount( - sfReserveBaseDrops, - fields.reserveBaseDrops ? *fields.reserveBaseDrops - : XRPAmount{0}); - obj.setFieldAmount( - sfReserveIncrementDrops, - fields.reserveIncrementDrops ? *fields.reserveIncrementDrops - : XRPAmount{0}); + sfReserveIncrementDrops, fields.reserveIncrementDrops ? *fields.reserveIncrementDrops : XRPAmount{0}); } else { // Legacy format - all four fields are REQUIRED obj.setFieldU64(sfBaseFee, fields.baseFee ? *fields.baseFee : 0); - obj.setFieldU32( - sfReserveBase, fields.reserveBase ? *fields.reserveBase : 0); - obj.setFieldU32( - sfReserveIncrement, - fields.reserveIncrement ? *fields.reserveIncrement : 0); - obj.setFieldU32( - sfReferenceFeeUnits, - fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0); + obj.setFieldU32(sfReserveBase, fields.reserveBase ? *fields.reserveBase : 0); + obj.setFieldU32(sfReserveIncrement, fields.reserveIncrement ? *fields.reserveIncrement : 0); + obj.setFieldU32(sfReferenceFeeUnits, fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0); } }; return STTx(ttFEE, fill); @@ -122,16 +107,12 @@ createInvalidFeeTx( bool applyFeeAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx) { - auto const res = - apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal); + auto const res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal); return res.ter == tesSUCCESS; } bool -verifyFeeObject( - std::shared_ptr const& ledger, - Rules const& rules, - FeeSettingsFields const& expected) +verifyFeeObject(std::shared_ptr const& ledger, Rules const& rules, FeeSettingsFields const& expected) { auto const feeObject = ledger->read(keylet::fees()); if (!feeObject) @@ -145,28 +126,20 @@ verifyFeeObject( if (rules.enabled(featureXRPFees)) { - if (feeObject->isFieldPresent(sfBaseFee) || - feeObject->isFieldPresent(sfReserveBase) || - feeObject->isFieldPresent(sfReserveIncrement) || - feeObject->isFieldPresent(sfReferenceFeeUnits)) + if (feeObject->isFieldPresent(sfBaseFee) || feeObject->isFieldPresent(sfReserveBase) || + feeObject->isFieldPresent(sfReserveIncrement) || feeObject->isFieldPresent(sfReferenceFeeUnits)) return false; - if (!checkEquality( - sfBaseFeeDrops, expected.baseFeeDrops.value_or(XRPAmount{0}))) + if (!checkEquality(sfBaseFeeDrops, expected.baseFeeDrops.value_or(XRPAmount{0}))) return false; - if (!checkEquality( - sfReserveBaseDrops, - expected.reserveBaseDrops.value_or(XRPAmount{0}))) + if (!checkEquality(sfReserveBaseDrops, expected.reserveBaseDrops.value_or(XRPAmount{0}))) return false; - if (!checkEquality( - sfReserveIncrementDrops, - expected.reserveIncrementDrops.value_or(XRPAmount{0}))) + if (!checkEquality(sfReserveIncrementDrops, expected.reserveIncrementDrops.value_or(XRPAmount{0}))) return false; } else { - if (feeObject->isFieldPresent(sfBaseFeeDrops) || - feeObject->isFieldPresent(sfReserveBaseDrops) || + if (feeObject->isFieldPresent(sfBaseFeeDrops) || feeObject->isFieldPresent(sfReserveBaseDrops) || feeObject->isFieldPresent(sfReserveIncrementDrops)) return false; @@ -213,10 +186,7 @@ class FeeVote_test : public beast::unit_test::suite } { Section config; - config.append( - {"reference_fee = 50", - "account_reserve = 1234567", - "owner_reserve = 1234"}); + config.append({"reference_fee = 50", "account_reserve = 1234567", "owner_reserve = 1234"}); auto setup = setup_FeeVote(config); BEAST_EXPECT(setup.reference_fee == 50); BEAST_EXPECT(setup.account_reserve == 1234567); @@ -224,10 +194,7 @@ class FeeVote_test : public beast::unit_test::suite } { Section config; - config.append( - {"reference_fee = blah", - "account_reserve = yada", - "owner_reserve = foo"}); + config.append({"reference_fee = blah", "account_reserve = yada", "owner_reserve = foo"}); // Illegal values are ignored, and the defaults left unchanged auto setup = setup_FeeVote(config); BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee); @@ -236,28 +203,18 @@ class FeeVote_test : public beast::unit_test::suite } { Section config; - config.append( - {"reference_fee = -50", - "account_reserve = -1234567", - "owner_reserve = -1234"}); + config.append({"reference_fee = -50", "account_reserve = -1234567", "owner_reserve = -1234"}); // Illegal values are ignored, and the defaults left unchanged auto setup = setup_FeeVote(config); BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee); - BEAST_EXPECT( - setup.account_reserve == static_cast(-1234567)); - BEAST_EXPECT( - setup.owner_reserve == static_cast(-1234)); + BEAST_EXPECT(setup.account_reserve == static_cast(-1234567)); + BEAST_EXPECT(setup.owner_reserve == static_cast(-1234)); } { - auto const big64 = std::to_string( - static_cast( - std::numeric_limits::max()) + - 1); + auto const big64 = + std::to_string(static_cast(std::numeric_limits::max()) + 1); Section config; - config.append( - {"reference_fee = " + big64, - "account_reserve = " + big64, - "owner_reserve = " + big64}); + config.append({"reference_fee = " + big64, "account_reserve = " + big64, "owner_reserve = " + big64}); // Illegal values are ignored, and the defaults left unchanged auto setup = setup_FeeVote(config); BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee); @@ -275,22 +232,15 @@ class FeeVote_test : public beast::unit_test::suite { jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); // Create the next ledger to apply transaction to - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); // Test successful fee transaction with legacy fields FeeSettingsFields fields{ - .baseFee = 10, - .reserveBase = 200000, - .reserveIncrement = 50000, - .referenceFeeUnits = 10}; + .baseFee = 10, .reserveBase = 200000, .reserveIncrement = 50000, .referenceFeeUnits = 10}; auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields); OpenView accum(ledger.get()); @@ -305,14 +255,10 @@ class FeeVote_test : public beast::unit_test::suite { jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); // Create the next ledger to apply transaction to - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); FeeSettingsFields fields{ .baseFeeDrops = XRPAmount{10}, @@ -338,48 +284,36 @@ class FeeVote_test : public beast::unit_test::suite { jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); // Create the next ledger to apply transaction to - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); // Test transaction with missing required legacy fields - auto invalidTx = createInvalidFeeTx( - ledger->rules(), ledger->seq(), true, false, 1); + auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 1); OpenView accum(ledger.get()); BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx)); // Test transaction with new format fields when XRPFees is disabled - auto disallowedTx = createInvalidFeeTx( - ledger->rules(), ledger->seq(), false, true, 2); + auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 2); BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx)); } { jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); // Create the next ledger to apply transaction to - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); // Test transaction with missing required new fields - auto invalidTx = createInvalidFeeTx( - ledger->rules(), ledger->seq(), true, false, 3); + auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 3); OpenView accum(ledger.get()); BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx)); // Test transaction with legacy fields when XRPFees is enabled - auto disallowedTx = createInvalidFeeTx( - ledger->rules(), ledger->seq(), false, true, 4); + auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 4); BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx)); } } @@ -391,14 +325,10 @@ class FeeVote_test : public beast::unit_test::suite jtx::Env env(*this, jtx::testable_amendments()); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); // Create the next ledger to apply transaction to - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); auto feeTx = createFeeTx( ledger->rules(), @@ -430,13 +360,9 @@ class FeeVote_test : public beast::unit_test::suite jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); FeeSettingsFields fields1{ .baseFeeDrops = XRPAmount{10}, @@ -453,8 +379,7 @@ class FeeVote_test : public beast::unit_test::suite BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields1)); // Apply second fee transaction with different values - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); FeeSettingsFields fields2{ .baseFeeDrops = XRPAmount{20}, @@ -479,13 +404,9 @@ class FeeVote_test : public beast::unit_test::suite jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); // Test transaction with wrong ledger sequence auto feeTx = createFeeTx( @@ -510,13 +431,9 @@ class FeeVote_test : public beast::unit_test::suite jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); FeeSettingsFields fields1{ .baseFeeDrops = XRPAmount{10}, @@ -532,13 +449,10 @@ class FeeVote_test : public beast::unit_test::suite BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields1)); - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); // Apply partial update (only some fields) - FeeSettingsFields fields2{ - .baseFeeDrops = XRPAmount{20}, - .reserveBaseDrops = XRPAmount{200000}}; + FeeSettingsFields fields2{.baseFeeDrops = XRPAmount{20}, .reserveBaseDrops = XRPAmount{200000}}; auto feeTx2 = createFeeTx(ledger->rules(), ledger->seq(), fields2); { @@ -558,20 +472,15 @@ class FeeVote_test : public beast::unit_test::suite jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); // Test invalid transaction with non-zero account - this should fail // validation auto invalidTx = STTx(ttFEE, [&](auto& obj) { - obj.setAccountID( - sfAccount, - AccountID(1)); // Should be zero (this makes it invalid) + obj.setAccountID(sfAccount, + AccountID(1)); // Should be zero (this makes it invalid) obj.setFieldU32(sfLedgerSequence, ledger->seq()); obj.setFieldAmount(sfBaseFeeDrops, XRPAmount{10}); obj.setFieldAmount(sfReserveBaseDrops, XRPAmount{200000}); @@ -600,20 +509,13 @@ class FeeVote_test : public beast::unit_test::suite auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote")); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); auto sec = randomSecretKey(); auto pub = derivePublicKey(KeyType::secp256k1, sec); auto val = std::make_shared( - env.app().timeKeeper().now(), - pub, - sec, - calcNodeID(pub), - [](STValidation& v) { + env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [](STValidation& v) { v.setFieldU32(sfLedgerSequence, 12345); }); @@ -624,9 +526,7 @@ class FeeVote_test : public beast::unit_test::suite feeVote->doValidation(currentFees, ledger->rules(), *val); BEAST_EXPECT(val->isFieldPresent(sfBaseFeeDrops)); - BEAST_EXPECT( - val->getFieldAmount(sfBaseFeeDrops) == - XRPAmount(setup.reference_fee)); + BEAST_EXPECT(val->getFieldAmount(sfBaseFeeDrops) == XRPAmount(setup.reference_fee)); } // Test with XRPFees disabled (legacy format) @@ -635,20 +535,13 @@ class FeeVote_test : public beast::unit_test::suite auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote")); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); auto sec = randomSecretKey(); auto pub = derivePublicKey(KeyType::secp256k1, sec); auto val = std::make_shared( - env.app().timeKeeper().now(), - pub, - sec, - calcNodeID(pub), - [](STValidation& v) { + env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [](STValidation& v) { v.setFieldU32(sfLedgerSequence, 12345); }); @@ -677,24 +570,19 @@ class FeeVote_test : public beast::unit_test::suite Env env(*this, testable_amendments() | featureXRPFees); // establish what the current fees are - BEAST_EXPECT( - env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE}); + BEAST_EXPECT(env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE}); BEAST_EXPECT(env.current()->fees().reserve == XRPAmount{200'000'000}); BEAST_EXPECT(env.current()->fees().increment == XRPAmount{50'000'000}); auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote")); auto ledger = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); // doVoting requires a flag ledger (every 256th ledger) // We need to create a ledger at sequence 256 to make it a flag ledger for (int i = 0; i < 256 - 1; ++i) { - ledger = std::make_shared( - *ledger, env.app().timeKeeper().closeTime()); + ledger = std::make_shared(*ledger, env.app().timeKeeper().closeTime()); } BEAST_EXPECT(ledger->isFlagLedger()); @@ -707,28 +595,19 @@ class FeeVote_test : public beast::unit_test::suite auto pub = derivePublicKey(KeyType::secp256k1, sec); auto val = std::make_shared( - env.app().timeKeeper().now(), - pub, - sec, - calcNodeID(pub), - [&](STValidation& v) { + env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [&](STValidation& v) { v.setFieldU32(sfLedgerSequence, ledger->seq()); // Vote for different fees than current - v.setFieldAmount( - sfBaseFeeDrops, XRPAmount{setup.reference_fee}); - v.setFieldAmount( - sfReserveBaseDrops, XRPAmount{setup.account_reserve}); - v.setFieldAmount( - sfReserveIncrementDrops, - XRPAmount{setup.owner_reserve}); + v.setFieldAmount(sfBaseFeeDrops, XRPAmount{setup.reference_fee}); + v.setFieldAmount(sfReserveBaseDrops, XRPAmount{setup.account_reserve}); + v.setFieldAmount(sfReserveIncrementDrops, XRPAmount{setup.owner_reserve}); }); if (i % 2) val->setTrusted(); validations.push_back(val); } - auto txSet = std::make_shared( - SHAMapType::TRANSACTION, env.app().getNodeFamily()); + auto txSet = std::make_shared(SHAMapType::TRANSACTION, env.app().getNodeFamily()); // This should not throw since we have a flag ledger feeVote->doVoting(ledger, validations, txSet); @@ -753,15 +632,9 @@ class FeeVote_test : public beast::unit_test::suite BEAST_EXPECT(!feeTx.isFieldPresent(sfReferenceFeeUnits)); // Check the values - BEAST_EXPECT( - feeTx.getFieldAmount(sfBaseFeeDrops) == - XRPAmount{setup.reference_fee}); - BEAST_EXPECT( - feeTx.getFieldAmount(sfReserveBaseDrops) == - XRPAmount{setup.account_reserve}); - BEAST_EXPECT( - feeTx.getFieldAmount(sfReserveIncrementDrops) == - XRPAmount{setup.owner_reserve}); + BEAST_EXPECT(feeTx.getFieldAmount(sfBaseFeeDrops) == XRPAmount{setup.reference_fee}); + BEAST_EXPECT(feeTx.getFieldAmount(sfReserveBaseDrops) == XRPAmount{setup.account_reserve}); + BEAST_EXPECT(feeTx.getFieldAmount(sfReserveIncrementDrops) == XRPAmount{setup.owner_reserve}); } void diff --git a/src/test/app/FixNFTokenPageLinks_test.cpp b/src/test/app/FixNFTokenPageLinks_test.cpp index ad457cc58b..8a3b51bbf1 100644 --- a/src/test/app/FixNFTokenPageLinks_test.cpp +++ b/src/test/app/FixNFTokenPageLinks_test.cpp @@ -40,9 +40,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // creation of NFT pages that are completely full. This lambda // tells us the taxon value we should pass in in order for the // internal representation to match the passed in value. - auto internalTaxon = [this, &env]( - Account const& acct, - std::uint32_t taxon) -> std::uint32_t { + auto internalTaxon = [this, &env](Account const& acct, std::uint32_t taxon) -> std::uint32_t { std::uint32_t tokenSeq = [this, &env, &acct]() { auto const le = env.le(acct); if (BEAST_EXPECT(le)) @@ -51,9 +49,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite }(); // We must add FirstNFTokenSequence. - tokenSeq += env.le(acct) - ->at(~sfFirstNFTokenSequence) - .value_or(env.seq(acct)); + tokenSeq += env.le(acct)->at(~sfFirstNFTokenSequence).value_or(env.seq(acct)); return toUInt32(nft::cipheredTaxon(tokenSeq, nft::toTaxon(taxon))); }; @@ -68,8 +64,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // populated. std::uint32_t const intTaxon = (i / 16) + (i & 0b10000 ? 2 : 0); uint32_t const extTaxon = internalTaxon(owner, intTaxon); - nfts.push_back( - token::getNextID(env, owner, extTaxon, tfTransferable)); + nfts.push_back(token::getNextID(env, owner, extTaxon, tfTransferable)); env(token::mint(owner, extTaxon), txflags(tfTransferable)); env.close(); } @@ -85,15 +80,13 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite params[jss::account] = owner.human(); auto resp = env.rpc("json", "account_objects", to_string(params)); - Json::Value const& acctObjs = - resp[jss::result][jss::account_objects]; + Json::Value const& acctObjs = resp[jss::result][jss::account_objects]; int pageCount = 0; for (Json::UInt i = 0; i < acctObjs.size(); ++i) { if (BEAST_EXPECT( - acctObjs[i].isMember(sfNFTokens.jsonName) && - acctObjs[i][sfNFTokens.jsonName].isArray())) + acctObjs[i].isMember(sfNFTokens.jsonName) && acctObjs[i][sfNFTokens.jsonName].isArray())) { BEAST_EXPECT(acctObjs[i][sfNFTokens.jsonName].size() == 32); ++pageCount; @@ -122,9 +115,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite env.fund(XRP(1000), alice); auto const linkFixFee = drops(env.current()->fees().increment); - env(ledgerStateFix::nftPageLinks(alice, alice), - fee(linkFixFee), - ter(temDISABLED)); + env(ledgerStateFix::nftPageLinks(alice, alice), fee(linkFixFee), ter(temDISABLED)); } Env env{*this, testable_amendments()}; @@ -147,10 +138,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // Invalid flags. auto const linkFixFee = drops(env.current()->fees().increment); - env(ledgerStateFix::nftPageLinks(alice, alice), - fee(linkFixFee), - txflags(tfPassive), - ter(temINVALID_FLAG)); + env(ledgerStateFix::nftPageLinks(alice, alice), fee(linkFixFee), txflags(tfPassive), ter(temINVALID_FLAG)); { // ledgerStateFix::nftPageLinks requires an Owner field. @@ -171,9 +159,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // Preclaim Account const carol("carol"); env.memoize(carol); - env(ledgerStateFix::nftPageLinks(alice, carol), - fee(linkFixFee), - ter(tecOBJECT_NOT_FOUND)); + env(ledgerStateFix::nftPageLinks(alice, carol), fee(linkFixFee), ter(tecOBJECT_NOT_FOUND)); } void @@ -194,17 +180,13 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // Owner has no pages to fix. auto const linkFixFee = drops(env.current()->fees().increment); - env(ledgerStateFix::nftPageLinks(alice, alice), - fee(linkFixFee), - ter(tecFAILED_PROCESSING)); + env(ledgerStateFix::nftPageLinks(alice, alice), fee(linkFixFee), ter(tecFAILED_PROCESSING)); // Alice has only one page. env(token::mint(alice), txflags(tfTransferable)); env.close(); - env(ledgerStateFix::nftPageLinks(alice, alice), - fee(linkFixFee), - ter(tecFAILED_PROCESSING)); + env(ledgerStateFix::nftPageLinks(alice, alice), fee(linkFixFee), ter(tecFAILED_PROCESSING)); // Alice has at least three pages. for (std::uint32_t i = 0; i < 64; ++i) @@ -213,9 +195,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite env.close(); } - env(ledgerStateFix::nftPageLinks(alice, alice), - fee(linkFixFee), - ter(tecFAILED_PROCESSING)); + env(ledgerStateFix::nftPageLinks(alice, alice), fee(linkFixFee), ter(tecFAILED_PROCESSING)); } void @@ -280,15 +260,13 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // alice's "middle" page is still present, but has no links. { - auto aliceMiddleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), aliceMiddleNFTokenPageIndex)); + auto aliceMiddleNFTokenPage = + env.le(keylet::nftpage(keylet::nftpage_min(alice), aliceMiddleNFTokenPageIndex)); if (!BEAST_EXPECT(aliceMiddleNFTokenPage)) return; - BEAST_EXPECT( - !aliceMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); - BEAST_EXPECT( - !aliceMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); + BEAST_EXPECT(!aliceMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!aliceMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); } //********************************************************************** @@ -325,13 +303,11 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // bob's "middle" page is still present, but has lost the // NextPageMin field. { - auto bobMiddleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(bob), bobMiddleNFTokenPageIndex)); + auto bobMiddleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(bob), bobMiddleNFTokenPageIndex)); if (!BEAST_EXPECT(bobMiddleNFTokenPage)) return; - BEAST_EXPECT( - bobMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(bobMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!bobMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); } @@ -356,10 +332,8 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite dariaNFTs.reserve(32); for (int i = 0; i < 32; ++i) { - uint256 const offerIndex = - keylet::nftoffer(carol, env.seq(carol)).key; - env(token::createOffer(carol, carolNFTs.back(), XRP(0)), - txflags(tfSellNFToken)); + uint256 const offerIndex = keylet::nftoffer(carol, env.seq(carol)).key; + env(token::createOffer(carol, carolNFTs.back(), XRP(0)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(daria, offerIndex)); @@ -378,8 +352,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // carol's "middle" page is still present, but has lost the // NextPageMin field. - auto carolMiddleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(carol), carolMiddleNFTokenPageIndex)); + auto carolMiddleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(carol), carolMiddleNFTokenPageIndex)); if (!BEAST_EXPECT(carolMiddleNFTokenPage)) return; @@ -392,8 +365,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // back from daria. for (uint256 const& nft : dariaNFTs) { - uint256 const offerIndex = - keylet::nftoffer(carol, env.seq(carol)).key; + uint256 const offerIndex = keylet::nftoffer(carol, env.seq(carol)).key; env(token::createOffer(carol, nft, drops(1)), token::owner(daria)); env.close(); @@ -410,22 +382,19 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // carol's "middle" page is present and still has no NextPageMin field. { - auto carolMiddleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(carol), carolMiddleNFTokenPageIndex)); + auto carolMiddleNFTokenPage = + env.le(keylet::nftpage(keylet::nftpage_min(carol), carolMiddleNFTokenPageIndex)); if (!BEAST_EXPECT(carolMiddleNFTokenPage)) return; - BEAST_EXPECT( - carolMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); - BEAST_EXPECT( - !carolMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); + BEAST_EXPECT(carolMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!carolMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); } // carol has a "last" page again, but it has no PreviousPageMin field. { auto carolLastNFTokenPage = env.le(keylet::nftpage_max(carol)); - BEAST_EXPECT( - !carolLastNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!carolLastNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!carolLastNFTokenPage->isFieldPresent(sfNextPageMin)); } @@ -434,9 +403,7 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite //********************************************************************** // Verify that the LedgerStateFix transaction is not enabled. auto const linkFixFee = drops(env.current()->fees().increment); - env(ledgerStateFix::nftPageLinks(daria, alice), - fee(linkFixFee), - ter(temDISABLED)); + env(ledgerStateFix::nftPageLinks(daria, alice), fee(linkFixFee), ter(temDISABLED)); // Wait 15 ledgers so the LedgerStateFix transaction is no longer // retried. @@ -457,15 +424,13 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // alice's "middle" page is still present and has no links. { - auto aliceMiddleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), aliceMiddleNFTokenPageIndex)); + auto aliceMiddleNFTokenPage = + env.le(keylet::nftpage(keylet::nftpage_min(alice), aliceMiddleNFTokenPageIndex)); if (!BEAST_EXPECT(aliceMiddleNFTokenPage)) return; - BEAST_EXPECT( - !aliceMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); - BEAST_EXPECT( - !aliceMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); + BEAST_EXPECT(!aliceMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!aliceMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); } // The server "remembers" daria's failed nftPageLinks transaction @@ -483,14 +448,12 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite if (!BEAST_EXPECT(aliceLastNFTokenPage)) return; - BEAST_EXPECT( - !aliceLastNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!aliceLastNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!aliceLastNFTokenPage->isFieldPresent(sfNextPageMin)); } // alice's middle page should be gone. - BEAST_EXPECT(!env.le(keylet::nftpage( - keylet::nftpage_min(alice), aliceMiddleNFTokenPageIndex))); + BEAST_EXPECT(!env.le(keylet::nftpage(keylet::nftpage_min(alice), aliceMiddleNFTokenPageIndex))); BEAST_EXPECT(nftCount(env, alice) == 32); BEAST_EXPECT(ownerCount(env, alice) == 1); @@ -506,13 +469,11 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // bob's "middle" page is still present and missing NextPageMin. { - auto bobMiddleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(bob), bobMiddleNFTokenPageIndex)); + auto bobMiddleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(bob), bobMiddleNFTokenPageIndex)); if (!BEAST_EXPECT(bobMiddleNFTokenPage)) return; - BEAST_EXPECT( - bobMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(bobMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!bobMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); } @@ -529,28 +490,22 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite return; BEAST_EXPECT(bobLastNFTokenPage->isFieldPresent(sfPreviousPageMin)); - BEAST_EXPECT( - bobLastNFTokenPage->at(sfPreviousPageMin) != - bobMiddleNFTokenPageIndex); + BEAST_EXPECT(bobLastNFTokenPage->at(sfPreviousPageMin) != bobMiddleNFTokenPageIndex); BEAST_EXPECT(!bobLastNFTokenPage->isFieldPresent(sfNextPageMin)); - auto const bobNewFirstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(bob), - bobLastNFTokenPage->at(sfPreviousPageMin))); + auto const bobNewFirstNFTokenPage = + env.le(keylet::nftpage(keylet::nftpage_min(bob), bobLastNFTokenPage->at(sfPreviousPageMin))); if (!BEAST_EXPECT(bobNewFirstNFTokenPage)) return; BEAST_EXPECT( bobNewFirstNFTokenPage->isFieldPresent(sfNextPageMin) && - bobNewFirstNFTokenPage->at(sfNextPageMin) == - lastPageKeylet.key); - BEAST_EXPECT( - !bobNewFirstNFTokenPage->isFieldPresent(sfPreviousPageMin)); + bobNewFirstNFTokenPage->at(sfNextPageMin) == lastPageKeylet.key); + BEAST_EXPECT(!bobNewFirstNFTokenPage->isFieldPresent(sfPreviousPageMin)); } // bob's middle page should be gone. - BEAST_EXPECT(!env.le(keylet::nftpage( - keylet::nftpage_min(bob), bobMiddleNFTokenPageIndex))); + BEAST_EXPECT(!env.le(keylet::nftpage(keylet::nftpage_min(bob), bobMiddleNFTokenPageIndex))); BEAST_EXPECT(nftCount(env, bob) == 64); BEAST_EXPECT(ownerCount(env, bob) == 2); @@ -563,22 +518,19 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite // carol's "middle" page is present and has no NextPageMin field. { - auto carolMiddleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(carol), carolMiddleNFTokenPageIndex)); + auto carolMiddleNFTokenPage = + env.le(keylet::nftpage(keylet::nftpage_min(carol), carolMiddleNFTokenPageIndex)); if (!BEAST_EXPECT(carolMiddleNFTokenPage)) return; - BEAST_EXPECT( - carolMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); - BEAST_EXPECT( - !carolMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); + BEAST_EXPECT(carolMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!carolMiddleNFTokenPage->isFieldPresent(sfNextPageMin)); } // carol has a "last" page, but it has no PreviousPageMin field. { auto carolLastNFTokenPage = env.le(keylet::nftpage_max(carol)); - BEAST_EXPECT( - !carolLastNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!carolLastNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!carolLastNFTokenPage->isFieldPresent(sfNextPageMin)); } @@ -589,17 +541,15 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite { // carol's "middle" page is present and now has a NextPageMin field. auto const lastPageKeylet = keylet::nftpage_max(carol); - auto carolMiddleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(carol), carolMiddleNFTokenPageIndex)); + auto carolMiddleNFTokenPage = + env.le(keylet::nftpage(keylet::nftpage_min(carol), carolMiddleNFTokenPageIndex)); if (!BEAST_EXPECT(carolMiddleNFTokenPage)) return; - BEAST_EXPECT( - carolMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(carolMiddleNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT( carolMiddleNFTokenPage->isFieldPresent(sfNextPageMin) && - carolMiddleNFTokenPage->at(sfNextPageMin) == - lastPageKeylet.key); + carolMiddleNFTokenPage->at(sfNextPageMin) == lastPageKeylet.key); // carol has a "last" page that includes a PreviousPageMin field. auto carolLastNFTokenPage = env.le(lastPageKeylet); @@ -608,23 +558,19 @@ class FixNFTokenPageLinks_test : public beast::unit_test::suite BEAST_EXPECT( carolLastNFTokenPage->isFieldPresent(sfPreviousPageMin) && - carolLastNFTokenPage->at(sfPreviousPageMin) == - carolMiddleNFTokenPageIndex); + carolLastNFTokenPage->at(sfPreviousPageMin) == carolMiddleNFTokenPageIndex); BEAST_EXPECT(!carolLastNFTokenPage->isFieldPresent(sfNextPageMin)); // carol also has a "first" page that includes a NextPageMin field. - auto carolFirstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(carol), - carolMiddleNFTokenPage->at(sfPreviousPageMin))); + auto carolFirstNFTokenPage = + env.le(keylet::nftpage(keylet::nftpage_min(carol), carolMiddleNFTokenPage->at(sfPreviousPageMin))); if (!BEAST_EXPECT(carolFirstNFTokenPage)) return; BEAST_EXPECT( carolFirstNFTokenPage->isFieldPresent(sfNextPageMin) && - carolFirstNFTokenPage->at(sfNextPageMin) == - carolMiddleNFTokenPageIndex); - BEAST_EXPECT( - !carolFirstNFTokenPage->isFieldPresent(sfPreviousPageMin)); + carolFirstNFTokenPage->at(sfNextPageMin) == carolMiddleNFTokenPageIndex); + BEAST_EXPECT(!carolFirstNFTokenPage->isFieldPresent(sfPreviousPageMin)); } // With the link repair, the server knows that carol has 96 NFTs. diff --git a/src/test/app/Flow_test.cpp b/src/test/app/Flow_test.cpp index 8c5a9615fa..551bd117d8 100644 --- a/src/test/app/Flow_test.cpp +++ b/src/test/app/Flow_test.cpp @@ -14,16 +14,11 @@ namespace xrpl { namespace test { bool -getNoRippleFlag( - jtx::Env const& env, - jtx::Account const& src, - jtx::Account const& dst, - Currency const& cur) +getNoRippleFlag(jtx::Env const& env, jtx::Account const& src, jtx::Account const& dst, Currency const& cur) { if (auto sle = env.le(keylet::line(src, dst, cur))) { - auto const flag = - (src.id() > dst.id()) ? lsfHighNoRipple : lsfLowNoRipple; + auto const flag = (src.id() > dst.id()) ? lsfHighNoRipple : lsfLowNoRipple; return sle->isFlag(flag); } Throw("No line in getTrustFlag"); @@ -80,9 +75,7 @@ struct Flow_test : public beast::unit_test::suite env(pay(gw, alice, USD(100))); env(pay(alice, bob, USD(110)), paths(USD), ter(tecPATH_PARTIAL)); env.require(balance(bob, USD(0))); - env(pay(alice, bob, USD(110)), - paths(USD), - txflags(tfPartialPayment)); + env(pay(alice, bob, USD(110)), paths(USD), txflags(tfPartialPayment)); env.require(balance(bob, USD(100))); } { @@ -95,10 +88,7 @@ struct Flow_test : public beast::unit_test::suite env.trust(USDB(10), carol); env.trust(USDC(10), dan); env(pay(alice, dan, USDC(10)), paths(USDA)); - env.require( - balance(bob, USDA(10)), - balance(carol, USDB(10)), - balance(dan, USDC(10))); + env.require(balance(bob, USDA(10)), balance(carol, USDB(10)), balance(dan, USDC(10))); } { // Pay by rippling through accounts, specify path @@ -114,10 +104,7 @@ struct Flow_test : public beast::unit_test::suite // alice will redeem to bob; a transfer fee will be charged env(pay(bob, alice, USDB(6))); - env(pay(alice, dan, USDC(5)), - path(bob, carol), - sendmax(USDA(6)), - txflags(tfNoRippleDirect)); + env(pay(alice, dan, USDC(5)), path(bob, carol), sendmax(USDA(6)), txflags(tfNoRippleDirect)); env.require(balance(dan, USDC(5))); env.require(balance(alice, USDB(0.5))); } @@ -133,10 +120,7 @@ struct Flow_test : public beast::unit_test::suite env.trust(USDC(10), dan); env(rate(bob, 1.1)); - env(pay(alice, dan, USDC(5)), - path(bob, carol), - sendmax(USDA(6)), - txflags(tfNoRippleDirect)); + env(pay(alice, dan, USDC(5)), path(bob, carol), sendmax(USDA(6)), txflags(tfNoRippleDirect)); env.require(balance(dan, USDC(5))); env.require(balance(bob, USDA(5))); } @@ -156,10 +140,7 @@ struct Flow_test : public beast::unit_test::suite // Pay alice so she redeems to carol and a transfer fee is charged env(pay(carol, alice, USDC(10))); - env(pay(alice, erin, USDD(5)), - path(carol, dan), - path(bob, dan), - txflags(tfNoRippleDirect)); + env(pay(alice, erin, USDD(5)), path(carol, dan), path(bob, dan), txflags(tfNoRippleDirect)); env.require(balance(erin, USDD(5))); env.require(balance(dan, USDB(5))); @@ -180,9 +161,7 @@ struct Flow_test : public beast::unit_test::suite ter(tecPATH_DRY)); env.require(balance(carol, USDB(0))); - env(pay(alice, carol, USDB(5)), - sendmax(USDA(4)), - txflags(tfPartialPayment)); + env(pay(alice, carol, USDB(5)), sendmax(USDA(4)), txflags(tfPartialPayment)); env.require(balance(carol, USDB(4))); } } @@ -215,15 +194,10 @@ struct Flow_test : public beast::unit_test::suite env(pay(alice, bob, USDA(100))); env.require(balance(bob, USDA(100))); - env(pay(dan, carol, USDA(10)), - path(bob), - sendmax(USDD(100)), - txflags(tfNoRippleDirect)); + env(pay(dan, carol, USDA(10)), path(bob), sendmax(USDD(100)), txflags(tfNoRippleDirect)); env.require(balance(bob, USDA(90))); if (bobAliceQOut > bobDanQIn) - env.require(balance( - bob, - USDD(10.0 * double(bobAliceQOut) / double(bobDanQIn)))); + env.require(balance(bob, USDD(10.0 * double(bobAliceQOut) / double(bobDanQIn)))); else env.require(balance(bob, USDD(10))); env.require(balance(carol, USDA(10))); @@ -242,8 +216,7 @@ struct Flow_test : public beast::unit_test::suite env(pay(alice, bob, USDA(10))); env.require(balance(bob, USDA(10))); env(pay(bob, carol, USDA(5)), sendmax(USDA(10))); - auto const effectiveQ = - carolAliceQIn > 100 ? 1.0 : carolAliceQIn / 100.0; + auto const effectiveQ = carolAliceQIn > 100 ? 1.0 : carolAliceQIn / 100.0; env.require(balance(bob, USDA(10.0 - 5.0 / effectiveQ))); } @@ -391,10 +364,7 @@ struct Flow_test : public beast::unit_test::suite BEAST_EXPECT(isOffer(env, bob, BTC(40), EUR(50))); BEAST_EXPECT(isOffer(env, bob, EUR(50), USD(50))); - env(pay(alice, carol, USD(50)), - path(~USD), - path(~EUR, ~USD), - sendmax(BTC(60))); + env(pay(alice, carol, USD(50)), path(~USD), path(~EUR, ~USD), sendmax(BTC(60))); env.require(balance(alice, BTC(10))); env.require(balance(bob, BTC(50))); @@ -480,17 +450,16 @@ struct Flow_test : public beast::unit_test::suite }(); BEAST_EXPECT(flowResult.removableOffers.size() == 1); - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) { - if (flowResult.removableOffers.empty()) - return false; - Sandbox sb(&view, tapNONE); - for (auto const& o : flowResult.removableOffers) - if (auto ok = sb.peek(keylet::offer(o))) - offerDelete(sb, ok, flowJournal); - sb.apply(view); - return true; - }); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { + if (flowResult.removableOffers.empty()) + return false; + Sandbox sb(&view, tapNONE); + for (auto const& o : flowResult.removableOffers) + if (auto ok = sb.peek(keylet::offer(o))) + offerDelete(sb, ok, flowJournal); + sb.apply(view); + return true; + }); // used in payment, but since payment failed should be untouched BEAST_EXPECT(isOffer(env, bob, BTC(50), USD(50))); @@ -526,8 +495,7 @@ struct Flow_test : public beast::unit_test::suite // USD(0.5) of bob's USD offer. If we provide 1 drop for less // than USD(0.5), then the remaining fractional offer would // block the order book. - TER const expectedTER = - reducedOffersV2 ? TER(tecPATH_DRY) : TER(tesSUCCESS); + TER const expectedTER = reducedOffersV2 ? TER(tecPATH_DRY) : TER(tesSUCCESS); env(pay(alice, carol, EUR(1)), path(~XRP, ~EUR), sendmax(USD(0.4)), @@ -547,13 +515,11 @@ struct Flow_test : public beast::unit_test::suite std::uint64_t const bookRate = [&usdOffer]() { // Extract the least significant 64 bits from the // book page. That's where the quality is stored. - std::string bookDirStr = - to_string(usdOffer->at(sfBookDirectory)); + std::string bookDirStr = to_string(usdOffer->at(sfBookDirectory)); bookDirStr.erase(0, 48); return std::stoull(bookDirStr, nullptr, 16); }(); - std::uint64_t const actualRate = getRate( - usdOffer->at(sfTakerGets), usdOffer->at(sfTakerPays)); + std::uint64_t const actualRate = getRate(usdOffer->at(sfTakerGets), usdOffer->at(sfTakerPays)); // We expect the actual rate of the offer to be worse // (larger) than the rate of the book page holding the @@ -589,9 +555,7 @@ struct Flow_test : public beast::unit_test::suite env.trust(USD(1000), alice, bob); env(offer(gw, XRP(125), USD(125))); env(pay(alice, bob, USD(100)), sendmax(XRP(200))); - env.require( - balance(alice, xrpMinusFee(env, 10000 - 125)), - balance(bob, USD(100))); + env.require(balance(alice, xrpMinusFee(env, 10000 - 125)), balance(bob, USD(100))); } void @@ -687,13 +651,10 @@ struct Flow_test : public beast::unit_test::suite offersOnAccount(jtx::Env& env, jtx::Account account) { std::vector> result; - forEachItem( - *env.current(), - account, - [&result](std::shared_ptr const& sle) { - if (sle->getType() == ltOFFER) - result.push_back(sle); - }); + forEachItem(*env.current(), account, [&result](std::shared_ptr const& sle) { + if (sle->getType() == ltOFFER) + result.push_back(sle); + }); return result; } @@ -751,9 +712,7 @@ struct Flow_test : public beast::unit_test::suite BEAST_EXPECT(offer[sfTakerPays] == USD(500)); } - env(pay(alice, alice, EUR(600)), - sendmax(USD(500)), - txflags(tfPartialPayment)); + env(pay(alice, alice, EUR(600)), sendmax(USD(500)), txflags(tfPartialPayment)); env.close(); env.require(owners(alice, 3)); @@ -822,9 +781,7 @@ struct Flow_test : public beast::unit_test::suite BEAST_EXPECT(offer[sfTakerPays] == USD(500)); } - env(pay(alice, alice, EUR(60)), - sendmax(USD(50)), - txflags(tfPartialPayment)); + env(pay(alice, alice, EUR(60)), sendmax(USD(50)), txflags(tfPartialPayment)); env.close(); env.require(owners(alice, 3)); @@ -867,10 +824,7 @@ struct Flow_test : public beast::unit_test::suite // Consuming the offer changes the owner count, which could also cause // liquidity to decrease in the forward pass auto const toSend = consumeOffer ? USD(10) : USD(9); - env(pay(alice, alice, toSend), - path(~USD), - sendmax(XRP(20000)), - txflags(tfPartialPayment | tfNoRippleDirect)); + env(pay(alice, alice, toSend), path(~USD), sendmax(XRP(20000)), txflags(tfPartialPayment | tfNoRippleDirect)); } void @@ -892,24 +846,11 @@ struct Flow_test : public beast::unit_test::suite env.close(); env(trust(bob, USD(20))); - STAmount tinyAmt1{ - USD.issue(), - 9000000000000000ll, - -17, - false, - STAmount::unchecked{}}; - STAmount tinyAmt3{ - USD.issue(), - 9000000000000003ll, - -17, - false, - STAmount::unchecked{}}; + STAmount tinyAmt1{USD.issue(), 9000000000000000ll, -17, false, STAmount::unchecked{}}; + STAmount tinyAmt3{USD.issue(), 9000000000000003ll, -17, false, STAmount::unchecked{}}; env(offer(gw, drops(9000000000), tinyAmt3)); - env(pay(alice, bob, tinyAmt1), - path(~USD), - sendmax(drops(9000000000)), - txflags(tfNoRippleDirect)); + env(pay(alice, bob, tinyAmt1), path(~USD), sendmax(drops(9000000000)), txflags(tfNoRippleDirect)); BEAST_EXPECT(!isOffer(env, gw, XRP(0), USD(0))); } @@ -926,26 +867,13 @@ struct Flow_test : public beast::unit_test::suite env.close(); env(trust(alice, USD(20))); - STAmount tinyAmt1{ - USD.issue(), - 9000000000000000ll, - -17, - false, - STAmount::unchecked{}}; - STAmount tinyAmt3{ - USD.issue(), - 9000000000000003ll, - -17, - false, - STAmount::unchecked{}}; + STAmount tinyAmt1{USD.issue(), 9000000000000000ll, -17, false, STAmount::unchecked{}}; + STAmount tinyAmt3{USD.issue(), 9000000000000003ll, -17, false, STAmount::unchecked{}}; env(pay(gw, alice, tinyAmt1)); env(offer(gw, tinyAmt3, drops(9000000000))); - env(pay(alice, bob, drops(9000000000)), - path(~XRP), - sendmax(USD(1)), - txflags(tfNoRippleDirect)); + env(pay(alice, bob, drops(9000000000)), path(~XRP), sendmax(USD(1)), txflags(tfNoRippleDirect)); BEAST_EXPECT(!isOffer(env, gw, USD(0), XRP(0))); } @@ -972,45 +900,37 @@ struct Flow_test : public beast::unit_test::suite BEAST_EXPECT(!getNoRippleFlag(env, gw, alice, usdC)); - env(pay( - gw, - alice, - // 12.55.... - STAmount{ - USD.issue(), std::uint64_t(1255555555555555ull), -14, false})); + env( + pay(gw, + alice, + // 12.55.... + STAmount{USD.issue(), std::uint64_t(1255555555555555ull), -14, false})); env(offer( gw, // 5.0... - STAmount{ - USD.issue(), std::uint64_t(5000000000000000ull), -15, false}, + STAmount{USD.issue(), std::uint64_t(5000000000000000ull), -15, false}, XRP(1000))); env(offer( gw, // .555... - STAmount{ - USD.issue(), std::uint64_t(5555555555555555ull), -16, false}, + STAmount{USD.issue(), std::uint64_t(5555555555555555ull), -16, false}, XRP(10))); env(offer( gw, // 4.44.... - STAmount{ - USD.issue(), std::uint64_t(4444444444444444ull), -15, false}, + STAmount{USD.issue(), std::uint64_t(4444444444444444ull), -15, false}, XRP(.1))); env(offer( alice, // 17 - STAmount{ - USD.issue(), std::uint64_t(1700000000000000ull), -14, false}, + STAmount{USD.issue(), std::uint64_t(1700000000000000ull), -14, false}, XRP(.001))); - env(pay(alice, bob, XRP(10000)), - path(~XRP), - sendmax(USD(100)), - txflags(tfPartialPayment | tfNoRippleDirect)); + env(pay(alice, bob, XRP(10000)), path(~XRP), sendmax(USD(100)), txflags(tfPartialPayment | tfNoRippleDirect)); } void @@ -1136,9 +1056,7 @@ struct Flow_test : public beast::unit_test::suite env.close(); // This payment caused the assert. - env(pay(ann, ann, CTB(0.687)), - sendmax(drops(20000000000)), - txflags(tfPartialPayment)); + env(pay(ann, ann, CTB(0.687)), sendmax(drops(20000000000)), txflags(tfPartialPayment)); } void @@ -1154,9 +1072,7 @@ struct Flow_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.close(); - env(pay(alice, alice, alice["USD"](100)), - path(~alice["USD"]), - ter(temBAD_PATH)); + env(pay(alice, alice, alice["USD"](100)), path(~alice["USD"]), ter(temBAD_PATH)); } void @@ -1270,8 +1186,7 @@ struct Flow_test : public beast::unit_test::suite env(pay(alice, bob, XRP(1000)), ticket::use(ticketSeq)); env.close(); env.require(balance(bob, XRP(1000))); - env.require( - balance(alice, XRP(9000) - (env.current()->fees().base * 2))); + env.require(balance(alice, XRP(9000) - (env.current()->fees().base * 2))); } void diff --git a/src/test/app/Freeze_test.cpp b/src/test/app/Freeze_test.cpp index 85c2b5a924..9d7db52e56 100644 --- a/src/test/app/Freeze_test.cpp +++ b/src/test/app/Freeze_test.cpp @@ -69,15 +69,11 @@ class Freeze_test : public beast::unit_test::suite // Is created via a TrustSet with SetFreeze flag // test: sets LowFreeze | HighFreeze flags env(trust(G1, bob["USD"](0), tfSetFreeze)); - auto affected = env.meta()->getJson( - JsonOptions::none)[sfAffectedNodes.fieldName]; + auto affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, 2u))) return; - auto ff = - affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; - BEAST_EXPECT( - ff[sfLowLimit.fieldName] == - G1["USD"](0).value().getJson(JsonOptions::none)); + auto ff = affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; + BEAST_EXPECT(ff[sfLowLimit.fieldName] == G1["USD"](0).value().getJson(JsonOptions::none)); BEAST_EXPECT(ff[jss::Flags].asUInt() & lsfLowFreeze); BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfHighFreeze)); env.close(); @@ -87,18 +83,12 @@ class Freeze_test : public beast::unit_test::suite // Account with line frozen by issuer // test: can buy more assets on that line env(offer(bob, G1["USD"](5), XRP(25))); - auto affected = env.meta()->getJson( - JsonOptions::none)[sfAffectedNodes.fieldName]; + auto affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, 5u))) return; - auto ff = - affected[3u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; - BEAST_EXPECT( - ff[sfHighLimit.fieldName] == - bob["USD"](100).value().getJson(JsonOptions::none)); - auto amt = STAmount{Issue{to_currency("USD"), noAccount()}, -15} - .value() - .getJson(JsonOptions::none); + auto ff = affected[3u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; + BEAST_EXPECT(ff[sfHighLimit.fieldName] == bob["USD"](100).value().getJson(JsonOptions::none)); + auto amt = STAmount{Issue{to_currency("USD"), noAccount()}, -15}.value().getJson(JsonOptions::none); BEAST_EXPECT(ff[sfBalance.fieldName] == amt); env.close(); } @@ -155,15 +145,11 @@ class Freeze_test : public beast::unit_test::suite // Is cleared via a TrustSet with ClearFreeze flag // test: sets LowFreeze | HighFreeze flags env(trust(G1, bob["USD"](0), tfClearFreeze)); - auto affected = env.meta()->getJson( - JsonOptions::none)[sfAffectedNodes.fieldName]; + auto affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, 2u))) return; - auto ff = - affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; - BEAST_EXPECT( - ff[sfLowLimit.fieldName] == - G1["USD"](0).value().getJson(JsonOptions::none)); + auto ff = affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; + BEAST_EXPECT(ff[sfLowLimit.fieldName] == G1["USD"](0).value().getJson(JsonOptions::none)); BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfLowFreeze)); BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfHighFreeze)); env.close(); @@ -211,8 +197,7 @@ class Freeze_test : public beast::unit_test::suite } // test: Issuer deep freezing not already frozen line must fail - env(trust(G1, A1["USD"](0), tfSetDeepFreeze), - ter(tecNO_PERMISSION)); + env(trust(G1, A1["USD"](0), tfSetDeepFreeze), ter(tecNO_PERMISSION)); env(trust(G1, A1["USD"](0), tfSetFreeze)); env.close(); @@ -258,8 +243,7 @@ class Freeze_test : public beast::unit_test::suite env(trust(G1, A1["USD"](0), tfSetDeepFreeze), ter(temINVALID_FLAG)); // test: clearing deep freeze before amendment fails - env(trust(G1, A1["USD"](0), tfClearDeepFreeze), - ter(temINVALID_FLAG)); + env(trust(G1, A1["USD"](0), tfClearDeepFreeze), ter(temINVALID_FLAG)); } } @@ -295,8 +279,7 @@ class Freeze_test : public beast::unit_test::suite // test: cannot create deep frozen trustline without normal freeze if (features[featureDeepFreeze]) { - env(trust(G1, A1["USD"](1000), tfSetDeepFreeze), - ter(tecNO_PERMISSION)); + env(trust(G1, A1["USD"](1000), tfSetDeepFreeze), ter(tecNO_PERMISSION)); env.close(); env.require(lines(A1, 0)); } @@ -334,14 +317,10 @@ class Freeze_test : public beast::unit_test::suite { // test: can't have both set and clear flag families in the same // transaction - env(trust(G1, A1["USD"](0), tfSetFreeze | tfClearFreeze), - ter(tecNO_PERMISSION)); - env(trust(G1, A1["USD"](0), tfSetFreeze | tfClearDeepFreeze), - ter(tecNO_PERMISSION)); - env(trust(G1, A1["USD"](0), tfSetDeepFreeze | tfClearFreeze), - ter(tecNO_PERMISSION)); - env(trust(G1, A1["USD"](0), tfSetDeepFreeze | tfClearDeepFreeze), - ter(tecNO_PERMISSION)); + env(trust(G1, A1["USD"](0), tfSetFreeze | tfClearFreeze), ter(tecNO_PERMISSION)); + env(trust(G1, A1["USD"](0), tfSetFreeze | tfClearDeepFreeze), ter(tecNO_PERMISSION)); + env(trust(G1, A1["USD"](0), tfSetDeepFreeze | tfClearFreeze), ter(tecNO_PERMISSION)); + env(trust(G1, A1["USD"](0), tfSetDeepFreeze | tfClearDeepFreeze), ter(tecNO_PERMISSION)); } else { @@ -349,10 +328,8 @@ class Freeze_test : public beast::unit_test::suite // trust line env(trust(G1, A1["USD"](0), tfSetFreeze | tfClearFreeze)); { - auto affected = env.meta()->getJson( - JsonOptions::none)[sfAffectedNodes.fieldName]; - BEAST_EXPECT(checkArraySize( - affected, 1u)); // means no trustline changes + auto affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; + BEAST_EXPECT(checkArraySize(affected, 1u)); // means no trustline changes } } } @@ -411,10 +388,7 @@ class Freeze_test : public beast::unit_test::suite { // Account without GlobalFreeze (proving operations normally work) // test: visible offers where taker_pays is unfrozen issuer - auto offers = env.rpc( - "book_offers", - std::string("USD/") + G1.human(), - "XRP")[jss::result][jss::offers]; + auto offers = env.rpc("book_offers", std::string("USD/") + G1.human(), "XRP")[jss::result][jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 2u))) return; std::set accounts; @@ -426,10 +400,7 @@ class Freeze_test : public beast::unit_test::suite BEAST_EXPECT(accounts.find(G1.human()) != std::end(accounts)); // test: visible offers where taker_gets is unfrozen issuer - offers = env.rpc( - "book_offers", - "XRP", - std::string("USD/") + G1.human())[jss::result][jss::offers]; + offers = env.rpc("book_offers", "XRP", std::string("USD/") + G1.human())[jss::result][jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 2u))) return; accounts.clear(); @@ -487,17 +458,11 @@ class Freeze_test : public beast::unit_test::suite // test: book_offers shows offers // (should these actually be filtered?) - offers = env.rpc( - "book_offers", - "XRP", - std::string("USD/") + G1.human())[jss::result][jss::offers]; + offers = env.rpc("book_offers", "XRP", std::string("USD/") + G1.human())[jss::result][jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 2u))) return; - offers = env.rpc( - "book_offers", - std::string("USD/") + G1.human(), - "XRP")[jss::result][jss::offers]; + offers = env.rpc("book_offers", std::string("USD/") + G1.human(), "XRP")[jss::result][jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 2u))) return; } @@ -553,8 +518,7 @@ class Freeze_test : public beast::unit_test::suite } if (features[featureDeepFreeze]) { - env(trust( - G1, deepFrozenAcc["USD"](0), tfSetFreeze | tfSetDeepFreeze)); + env(trust(G1, deepFrozenAcc["USD"](0), tfSetFreeze | tfSetDeepFreeze)); { auto const flags = getTrustlineFlags(env, 2u, 1u); BEAST_EXPECT(!(flags & (lsfLowFreeze | lsfLowDeepFreeze))); @@ -593,21 +557,18 @@ class Freeze_test : public beast::unit_test::suite // test: cannot deep freeze already frozen line when no freeze // enacted - env(trust(G1, frozenAcc["USD"](0), tfSetDeepFreeze), - ter(tecNO_PERMISSION)); + env(trust(G1, frozenAcc["USD"](0), tfSetDeepFreeze), ter(tecNO_PERMISSION)); } else { // test: previous functionality, checking there's no changes to a // trust line env(trust(G1, A1["USD"](0), tfSetFreeze)); - auto affected = env.meta()->getJson( - JsonOptions::none)[sfAffectedNodes.fieldName]; + auto affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, 1u))) return; - auto let = affected[0u][sfModifiedNode.fieldName] - [sfLedgerEntryType.fieldName]; + auto let = affected[0u][sfModifiedNode.fieldName][sfLedgerEntryType.fieldName]; BEAST_EXPECT(let == jss::AccountRoot); } @@ -668,9 +629,7 @@ class Freeze_test : public beast::unit_test::suite auto offers = getAccountOffers(env, A3)[jss::offers]; if (!BEAST_EXPECT(checkArraySize(offers, 1u))) return; - BEAST_EXPECT( - offers[0u][jss::taker_gets] == - G1["USD"](999).value().getJson(JsonOptions::none)); + BEAST_EXPECT(offers[0u][jss::taker_gets] == G1["USD"](999).value().getJson(JsonOptions::none)); // test: someone else creates an offer providing liquidity env(offer(A4, XRP(999), G1["USD"](999))); @@ -678,15 +637,11 @@ class Freeze_test : public beast::unit_test::suite // test: owner of partially consumed offers line is frozen env(trust(G1, A3["USD"](0), tfSetFreeze)); - auto affected = - env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; + auto affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, 2u))) return; - auto ff = - affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; - BEAST_EXPECT( - ff[sfHighLimit.fieldName] == - G1["USD"](0).value().getJson(JsonOptions::none)); + auto ff = affected[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; + BEAST_EXPECT(ff[sfHighLimit.fieldName] == G1["USD"](0).value().getJson(JsonOptions::none)); BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfLowFreeze)); BEAST_EXPECT(ff[jss::Flags].asUInt() & lsfHighFreeze); env.close(); @@ -708,27 +663,22 @@ class Freeze_test : public beast::unit_test::suite // removal buy successful OfferCreate // test: freeze the new offer env(trust(G1, A4["USD"](0), tfSetFreeze)); - affected = - env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; + affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, 2u))) return; ff = affected[0u][sfModifiedNode.fieldName][sfFinalFields.fieldName]; - BEAST_EXPECT( - ff[sfLowLimit.fieldName] == - G1["USD"](0).value().getJson(JsonOptions::none)); + BEAST_EXPECT(ff[sfLowLimit.fieldName] == G1["USD"](0).value().getJson(JsonOptions::none)); BEAST_EXPECT(ff[jss::Flags].asUInt() & lsfLowFreeze); BEAST_EXPECT(!(ff[jss::Flags].asUInt() & lsfHighFreeze)); env.close(); // test: can no longer create a crossing offer env(offer(A2, G1["USD"](999), XRP(999))); - affected = - env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; + affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, 8u))) return; auto created = affected[0u][sfCreatedNode.fieldName]; - BEAST_EXPECT( - created[sfNewFields.fieldName][jss::Account] == A2.human()); + BEAST_EXPECT(created[sfNewFields.fieldName][jss::Account] == A2.human()); env.close(); // test: offer was removed by offer_create @@ -800,20 +750,15 @@ class Freeze_test : public beast::unit_test::suite // test: can still buy from A2 env(offer(A1, USD(1), XRP(2)), txflags(tfFillOrKill)); env.close(); - env.require( - balance(A1, USD(1001)), balance(A2, USD(998)), offers(A1, 0)); + env.require(balance(A1, USD(1001)), balance(A2, USD(998)), offers(A1, 0)); // test: cannot create passive sell offer - env(offer(A1, XRP(2), USD(1)), - txflags(tfPassive), - ter(tecUNFUNDED_OFFER)); + env(offer(A1, XRP(2), USD(1)), txflags(tfPassive), ter(tecUNFUNDED_OFFER)); env.close(); env.require(balance(A1, USD(1001)), offers(A1, 0)); // test: cannot sell to A3 - env(offer(A1, XRP(1), USD(1)), - txflags(tfFillOrKill), - ter(tecUNFUNDED_OFFER)); + env(offer(A1, XRP(1), USD(1)), txflags(tfFillOrKill), ter(tecUNFUNDED_OFFER)); env.close(); env.require(balance(A1, USD(1001)), offers(A1, 0)); @@ -829,27 +774,19 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: cannot create passive buy offer - env(offer(A1, USD(1), XRP(0.5)), - txflags(tfPassive), - ter(tecFROZEN)); + env(offer(A1, USD(1), XRP(0.5)), txflags(tfPassive), ter(tecFROZEN)); env.close(); // test: cannot buy from A2 - env(offer(A1, USD(1), XRP(2)), - txflags(tfFillOrKill), - ter(tecFROZEN)); + env(offer(A1, USD(1), XRP(2)), txflags(tfFillOrKill), ter(tecFROZEN)); env.close(); // test: cannot create passive sell offer - env(offer(A1, XRP(2), USD(1)), - txflags(tfPassive), - ter(tecUNFUNDED_OFFER)); + env(offer(A1, XRP(2), USD(1)), txflags(tfPassive), ter(tecUNFUNDED_OFFER)); env.close(); // test: cannot sell to A3 - env(offer(A1, XRP(1), USD(1)), - txflags(tfFillOrKill), - ter(tecUNFUNDED_OFFER)); + env(offer(A1, XRP(1), USD(1)), txflags(tfFillOrKill), ter(tecUNFUNDED_OFFER)); env.close(); env(trust(G1, A1["USD"](0), tfClearFreeze | tfClearDeepFreeze)); @@ -873,18 +810,13 @@ class Freeze_test : public beast::unit_test::suite env.require(balance(A1, USD(1001)), balance(A2, USD(998))); env(offer(A2, XRP(1.1), USD(1)), txflags(tfFillOrKill)); env.close(); - env.require( - balance(A1, USD(1002)), balance(A2, USD(997)), offers(A1, 1)); + env.require(balance(A1, USD(1002)), balance(A2, USD(997)), offers(A1, 1)); // test: A3 wants to buy from A1, must fail - env.require( - balance(A1, USD(1002)), balance(A3, USD(1)), offers(A1, 1)); - env(offer(A3, USD(1), XRP(1.9)), - txflags(tfFillOrKill), - ter(tecKILLED)); + env.require(balance(A1, USD(1002)), balance(A3, USD(1)), offers(A1, 1)); + env(offer(A3, USD(1), XRP(1.9)), txflags(tfFillOrKill), ter(tecKILLED)); env.close(); - env.require( - balance(A1, USD(1002)), balance(A3, USD(1)), offers(A1, 0)); + env.require(balance(A1, USD(1002)), balance(A3, USD(1)), offers(A1, 0)); env(trust(G1, A1["USD"](0), tfClearFreeze)); env.close(); @@ -905,22 +837,15 @@ class Freeze_test : public beast::unit_test::suite // test: A2 wants to sell to A1, must fail env.require(balance(A1, USD(1002)), balance(A2, USD(997))); - env(offer(A2, XRP(1.1), USD(1)), - txflags(tfFillOrKill), - ter(tecKILLED)); + env(offer(A2, XRP(1.1), USD(1)), txflags(tfFillOrKill), ter(tecKILLED)); env.close(); - env.require( - balance(A1, USD(1002)), balance(A2, USD(997)), offers(A1, 1)); + env.require(balance(A1, USD(1002)), balance(A2, USD(997)), offers(A1, 1)); // test: A3 wants to buy from A1, must fail - env.require( - balance(A1, USD(1002)), balance(A3, USD(1)), offers(A1, 1)); - env(offer(A3, USD(1), XRP(1.9)), - txflags(tfFillOrKill), - ter(tecKILLED)); + env.require(balance(A1, USD(1002)), balance(A3, USD(1)), offers(A1, 1)); + env(offer(A3, USD(1), XRP(1.9)), txflags(tfFillOrKill), ter(tecKILLED)); env.close(); - env.require( - balance(A1, USD(1002)), balance(A3, USD(1)), offers(A1, 0)); + env.require(balance(A1, USD(1002)), balance(A3, USD(1)), offers(A1, 0)); env(trust(G1, A1["USD"](0), tfClearFreeze | tfClearDeepFreeze)); env.close(); @@ -942,12 +867,9 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 wants to buy, must fail - env(offer(A1, USD(1), XRP(2)), - txflags(tfFillOrKill), - ter(tecKILLED)); + env(offer(A1, USD(1), XRP(2)), txflags(tfFillOrKill), ter(tecKILLED)); env.close(); - env.require( - balance(A1, USD(1002)), balance(A2, USD(997)), offers(A1, 0)); + env.require(balance(A1, USD(1002)), balance(A2, USD(997)), offers(A1, 0)); // test: A1 can create passive sell offer env(offer(A1, XRP(2), USD(1)), txflags(tfPassive)); @@ -975,27 +897,19 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 cannot create passive buy offer - env(offer(A1, USD(1), XRP(0.5)), - txflags(tfPassive), - ter(tecFROZEN)); + env(offer(A1, USD(1), XRP(0.5)), txflags(tfPassive), ter(tecFROZEN)); env.close(); // test: A1 cannot buy, must fail - env(offer(A1, USD(1), XRP(2)), - txflags(tfFillOrKill), - ter(tecFROZEN)); + env(offer(A1, USD(1), XRP(2)), txflags(tfFillOrKill), ter(tecFROZEN)); env.close(); // test: A1 cannot create passive sell offer - env(offer(A1, XRP(2), USD(1)), - txflags(tfPassive), - ter(tecUNFUNDED_OFFER)); + env(offer(A1, XRP(2), USD(1)), txflags(tfPassive), ter(tecUNFUNDED_OFFER)); env.close(); // test: A1 cannot sell to A3 - env(offer(A1, XRP(1), USD(1)), - txflags(tfFillOrKill), - ter(tecUNFUNDED_OFFER)); + env(offer(A1, XRP(1), USD(1)), txflags(tfFillOrKill), ter(tecUNFUNDED_OFFER)); env.close(); env(trust(A1, limit, tfClearFreeze | tfClearDeepFreeze)); @@ -1036,19 +950,11 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 cannot send USD using XRP through A2 offer - env(pay(A1, G1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(A1, G1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); // test: G1 cannot send USD using XRP through A2 offer - env(pay(G1, A1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(G1, A1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); env(trust(G1, A2["USD"](0), tfClearFreeze)); @@ -1062,19 +968,11 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 cannot send USD using XRP through A2 offer - env(pay(A1, G1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(A1, G1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); // test: G1 cannot send USD using XRP through A2 offer - env(pay(G1, A1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(G1, A1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); env(trust(G1, A2["USD"](0), tfClearFreeze | tfClearDeepFreeze)); @@ -1088,17 +986,11 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 can send USD using XRP through A2 offer - env(pay(A1, G1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect)); + env(pay(A1, G1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect)); env.close(); // test: G1 can send USD using XRP through A2 offer - env(pay(G1, A1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect)); + env(pay(G1, A1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect)); env.close(); env(trust(A2, limit, tfClearFreeze)); @@ -1113,19 +1005,11 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 cannot send USD using XRP through A2 offer - env(pay(A1, G1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(A1, G1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); // test: G1 cannot send USD using XRP through A2 offer - env(pay(G1, A1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(G1, A1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); env(trust(A2, limit, tfClearFreeze | tfClearDeepFreeze)); @@ -1146,17 +1030,11 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 can send XRP using USD through A2 offer - env(pay(A1, G1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect)); + env(pay(A1, G1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect)); env.close(); // test: G1 can send XRP using USD through A2 offer - env(pay(G1, A1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect)); + env(pay(G1, A1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect)); env.close(); env(trust(G1, A2["USD"](0), tfClearFreeze)); @@ -1171,19 +1049,11 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 cannot send XRP using USD through A2 offer - env(pay(A1, G1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(A1, G1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); // test: G1 cannot send XRP using USD through A2 offer - env(pay(G1, A1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(G1, A1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); env(trust(G1, A2["USD"](0), tfClearFreeze | tfClearDeepFreeze)); @@ -1197,17 +1067,11 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 can send XRP using USD through A2 offer - env(pay(A1, G1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect)); + env(pay(A1, G1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect)); env.close(); // test: G1 can send XRP using USD through A2 offer - env(pay(G1, A1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect)); + env(pay(G1, A1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect)); env.close(); env(trust(A2, limit, tfClearFreeze)); @@ -1222,19 +1086,11 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A1 cannot send XRP using USD through A2 offer - env(pay(A1, G1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(A1, G1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); // test: G1 cannot send XRP using USD through A2 offer - env(pay(G1, A1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_PARTIAL)); + env(pay(G1, A1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect), ter(tecPATH_PARTIAL)); env.close(); env(trust(A2, limit, tfClearFreeze | tfClearDeepFreeze)); @@ -1696,32 +1552,19 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: can still use XRP to make payment - env(pay(A1, A2, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect)); + env(pay(A1, A2, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect)); env.close(); // test: cannot use USD to make payment - env(pay(A1, A2, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_DRY)); + env(pay(A1, A2, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect), ter(tecPATH_DRY)); env.close(); // test: can still receive USD payments. - env(pay(A2, A1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect)); + env(pay(A2, A1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect)); env.close(); // test: can still receive XRP payments. - env(pay(A2, A1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect)); + env(pay(A2, A1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect)); env.close(); env(trust(G1, A1["USD"](0), tfClearFreeze)); @@ -1736,33 +1579,19 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: can still use XRP to make payment - env(pay(A1, A2, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect)); + env(pay(A1, A2, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect)); env.close(); // test: cannot use USD to make payment - env(pay(A1, A2, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_DRY)); + env(pay(A1, A2, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect), ter(tecPATH_DRY)); env.close(); // test: cannot receive USD payments. - env(pay(A2, A1, USD(10)), - path(~USD), - sendmax(XRP(11)), - txflags(tfNoRippleDirect), - ter(tecPATH_DRY)); + env(pay(A2, A1, USD(10)), path(~USD), sendmax(XRP(11)), txflags(tfNoRippleDirect), ter(tecPATH_DRY)); env.close(); // test: can still receive XRP payments. - env(pay(A2, A1, XRP(10)), - path(~XRP), - sendmax(USD(11)), - txflags(tfNoRippleDirect)); + env(pay(A2, A1, XRP(10)), path(~XRP), sendmax(USD(11)), txflags(tfNoRippleDirect)); env.close(); env(trust(G1, A1["USD"](0), tfClearFreeze | tfClearDeepFreeze)); @@ -1830,8 +1659,7 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A2 cannot send USD for NFT - env(token::acceptSellOffer(A2, sellOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::acceptSellOffer(A2, sellOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); env(trust(G1, A2["USD"](0), tfClearFreeze)); @@ -1846,8 +1674,7 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A2 cannot send USD for NFT - env(token::acceptSellOffer(A2, sellOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::acceptSellOffer(A2, sellOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); env(trust(G1, A2["USD"](0), tfClearFreeze | tfClearDeepFreeze)); @@ -1855,8 +1682,7 @@ class Freeze_test : public beast::unit_test::suite } // Testing A1 nft buy offer when A2 deep frozen by issuer - if (features[featureDeepFreeze] && - features[fixEnforceNFTokenTrustlineV2]) + if (features[featureDeepFreeze] && features[fixEnforceNFTokenTrustlineV2]) { env(trust(G1, A2["USD"](0), tfSetFreeze | tfSetDeepFreeze)); env.close(); @@ -1931,8 +1757,7 @@ class Freeze_test : public beast::unit_test::suite env.close(); // test: A2 cannot send USD for NFT - env(token::acceptSellOffer(A2, sellOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::acceptSellOffer(A2, sellOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); env(trust(A2, limit, tfClearFreeze | tfClearDeepFreeze)); @@ -1940,8 +1765,7 @@ class Freeze_test : public beast::unit_test::suite } // Testing brokered offer acceptance - if (features[featureDeepFreeze] && - features[fixEnforceNFTokenTrustlineV2]) + if (features[featureDeepFreeze] && features[fixEnforceNFTokenTrustlineV2]) { Account broker{"broker"}; env.fund(XRP(10000), broker); @@ -1960,15 +1784,12 @@ class Freeze_test : public beast::unit_test::suite env(token::createOffer(A1, nftID, USD(11)), token::owner(A2)); env.close(); - env(token::brokerOffers(broker, buyIdx, sellIdx), - token::brokerFee(USD(1)), - ter(tecFROZEN)); + env(token::brokerOffers(broker, buyIdx, sellIdx), token::brokerFee(USD(1)), ter(tecFROZEN)); env.close(); } // Testing transfer fee - if (features[featureDeepFreeze] && - features[fixEnforceNFTokenTrustlineV2]) + if (features[featureDeepFreeze] && features[fixEnforceNFTokenTrustlineV2]) { Account minter{"minter"}; env.fund(XRP(10000), minter); @@ -1976,24 +1797,18 @@ class Freeze_test : public beast::unit_test::suite env(trust(G1, minter["USD"](1000))); env.close(); - uint256 const nftID{ - token::getNextID(env, minter, 0u, tfTransferable, 1u)}; - env(token::mint(minter, 0), - token::xferFee(1u), - txflags(tfTransferable)); + uint256 const nftID{token::getNextID(env, minter, 0u, tfTransferable, 1u)}; + env(token::mint(minter, 0), token::xferFee(1u), txflags(tfTransferable)); env.close(); - uint256 const minterSellIdx = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, drops(1)), - txflags(tfSellNFToken)); + uint256 const minterSellIdx = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, drops(1)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(A2, minterSellIdx)); env.close(); uint256 const sellIdx = keylet::nftoffer(A2, env.seq(A2)).key; - env(token::createOffer(A2, nftID, USD(100)), - txflags(tfSellNFToken)); + env(token::createOffer(A2, nftID, USD(100)), txflags(tfSellNFToken)); env.close(); env(trust(G1, minter["USD"](1000), tfSetFreeze | tfSetDeepFreeze)); env.close(); @@ -2004,28 +1819,19 @@ class Freeze_test : public beast::unit_test::suite // Helper function to extract trustline flags from open ledger uint32_t - getTrustlineFlags( - test::jtx::Env& env, - size_t expectedArraySize, - size_t expectedArrayIndex, - bool modified = true) + getTrustlineFlags(test::jtx::Env& env, size_t expectedArraySize, size_t expectedArrayIndex, bool modified = true) { using namespace test::jtx; - auto const affected = - env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; + auto const affected = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; if (!BEAST_EXPECT(checkArraySize(affected, expectedArraySize))) return 0; if (modified) { - return affected[expectedArrayIndex][sfModifiedNode.fieldName] - [sfFinalFields.fieldName][jss::Flags] - .asUInt(); + return affected[expectedArrayIndex][sfModifiedNode.fieldName][sfFinalFields.fieldName][jss::Flags].asUInt(); } - return affected[expectedArrayIndex][sfCreatedNode.fieldName] - [sfNewFields.fieldName][jss::Flags] - .asUInt(); + return affected[expectedArrayIndex][sfCreatedNode.fieldName][sfNewFields.fieldName][jss::Flags].asUInt(); } // Helper function that returns the index of the next check on account @@ -2036,20 +1842,15 @@ class Freeze_test : public beast::unit_test::suite } uint256 - createNFTSellOffer( - test::jtx::Env& env, - test::jtx::Account const& account, - test::jtx::PrettyAmount const& currency) + createNFTSellOffer(test::jtx::Env& env, test::jtx::Account const& account, test::jtx::PrettyAmount const& currency) { using namespace test::jtx; uint256 const nftID{token::getNextID(env, account, 0u, tfTransferable)}; env(token::mint(account, 0), txflags(tfTransferable)); env.close(); - uint256 const sellOfferIndex = - keylet::nftoffer(account, env.seq(account)).key; - env(token::createOffer(account, nftID, currency), - txflags(tfSellNFToken)); + uint256 const sellOfferIndex = keylet::nftoffer(account, env.seq(account)).key; + env(token::createOffer(account, nftID, currency), txflags(tfSellNFToken)); env.close(); return sellOfferIndex; @@ -2076,9 +1877,7 @@ public: }; using namespace test::jtx; auto const sa = testable_amendments(); - testAll( - sa - featureDeepFreeze - featurePermissionedDEX - - fixEnforceNFTokenTrustlineV2); + testAll(sa - featureDeepFreeze - featurePermissionedDEX - fixEnforceNFTokenTrustlineV2); testAll(sa - featurePermissionedDEX - fixEnforceNFTokenTrustlineV2); testAll(sa - featureDeepFreeze - featurePermissionedDEX); testAll(sa - featurePermissionedDEX); diff --git a/src/test/app/HashRouter_test.cpp b/src/test/app/HashRouter_test.cpp index 2d1d37c3e3..03bb28e35a 100644 --- a/src/test/app/HashRouter_test.cpp +++ b/src/test/app/HashRouter_test.cpp @@ -368,9 +368,7 @@ class HashRouter_test : public beast::unit_test::suite HF f2 = HF::SAVED; HF combined = f1 | f2; - BEAST_EXPECT( - static_cast(combined) == - (static_cast(f1) | static_cast(f2))); + BEAST_EXPECT(static_cast(combined) == (static_cast(f1) | static_cast(f2))); HF temp = f1; temp |= f2; diff --git a/src/test/app/Invariants_test.cpp b/src/test/app/Invariants_test.cpp index 9f70538778..b3fa027753 100644 --- a/src/test/app/Invariants_test.cpp +++ b/src/test/app/Invariants_test.cpp @@ -29,18 +29,12 @@ class Invariants_test : public beast::unit_test::suite // on the ledger after creating two accounts, but before closing it, and // before the Precheck function. These should only be valid functions, and // not direct manipulations. Preclose is not commonly used. - using Preclose = std::function; + using Preclose = std::function; // this is common setup/method for running a failing invariant check. The // precheck function is used to manipulate the ApplyContext with view // changes that will cause the check to fail. - using Precheck = std::function; + using Precheck = std::function; /** Run a specific test case to put the ledger into a state that will be * detected by an invariant. Simulates the actions of a transaction that @@ -65,14 +59,12 @@ class Invariants_test : public beast::unit_test::suite Precheck const& precheck, XRPAmount fee = XRPAmount{}, STTx tx = STTx{ttACCOUNT_SET, [](STObject&) {}}, - std::initializer_list ters = - {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, + std::initializer_list ters = {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, Preclose const& preclose = {}, TxAccount setTxAccount = TxAccount::None) { using namespace test::jtx; - FeatureBitset amendments = testable_amendments() | - featureInvariantsV1_1 | featureSingleAssetVault; + FeatureBitset amendments = testable_amendments() | featureInvariantsV1_1 | featureSingleAssetVault; Env env{*this, amendments}; Account const A1{"A1"}; @@ -86,16 +78,8 @@ class Invariants_test : public beast::unit_test::suite test::StreamSink sink{beast::severities::kWarning}; beast::Journal jlog{sink}; if (setTxAccount != TxAccount::None) - tx.setAccountID( - sfAccount, setTxAccount == TxAccount::A1 ? A1.id() : A2.id()); - ApplyContext ac{ - env.app(), - ov, - tx, - tesSUCCESS, - env.current()->fees().base, - tapNONE, - jlog}; + tx.setAccountID(sfAccount, setTxAccount == TxAccount::A1 ? A1.id() : A2.id()); + ApplyContext ac{env.app(), ov, tx, tesSUCCESS, env.current()->fees().base, tapNONE, jlog}; BEAST_EXPECT(precheck(A1, A2, ac)); @@ -110,8 +94,7 @@ class Invariants_test : public beast::unit_test::suite BEAST_EXPECT(terExpect == terActual); auto const messages = sink.messages().str(); BEAST_EXPECT( - messages.starts_with("Invariant failed:") || - messages.starts_with("Transaction caused an exception")); + messages.starts_with("Invariant failed:") || messages.starts_with("Transaction caused an exception")); // std::cerr << messages << '\n'; for (auto const& m : expect_logs) { @@ -131,8 +114,7 @@ class Invariants_test : public beast::unit_test::suite using namespace test::jtx; testcase << "XRP created"; doInvariantCheck( - {{"XRP net change was positive: 500"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"XRP net change was positive: 500"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // put a single account in the view and "manufacture" some XRP auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) @@ -151,20 +133,18 @@ class Invariants_test : public beast::unit_test::suite testcase << "account root removed"; // An account was deleted, but not by an AccountDelete transaction. - doInvariantCheck( - {{"an account root was deleted"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { - // remove an account from the view - auto sle = ac.view().peek(keylet::account(A1.id())); - if (!sle) - return false; - // Clear the balance so the "account deletion left behind a - // non-zero balance" check doesn't trip earlier than the desired - // check. - sle->at(sfBalance) = beast::zero; - ac.view().erase(sle); - return true; - }); + doInvariantCheck({{"an account root was deleted"}}, [](Account const& A1, Account const&, ApplyContext& ac) { + // remove an account from the view + auto sle = ac.view().peek(keylet::account(A1.id())); + if (!sle) + return false; + // Clear the balance so the "account deletion left behind a + // non-zero balance" check doesn't trip earlier than the desired + // check. + sle->at(sfBalance) = beast::zero; + ac.view().erase(sle); + return true; + }); // Successful AccountDelete transaction that didn't delete an account. // @@ -173,9 +153,7 @@ class Invariants_test : public beast::unit_test::suite // After a discussion with the team, we believe that's okay. doInvariantCheck( {{"account deletion succeeded without deleting an account"}}, - [](Account const&, Account const&, ApplyContext& ac) { - return true; - }, + [](Account const&, Account const&, ApplyContext& ac) { return true; }, XRPAmount{}, STTx{ttACCOUNT_DELETE, [](STObject& tx) {}}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}); @@ -262,8 +240,7 @@ class Invariants_test : public beast::unit_test::suite using namespace std::string_literals; doInvariantCheck( - {{"account deletion left behind a "s + type.c_str() + - " object"}}, + {{"account deletion left behind a "s + type.c_str() + " object"}}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { // Add an object to the ledger for account A1, then delete // A1 @@ -364,9 +341,7 @@ class Invariants_test : public beast::unit_test::suite BEAST_EXPECT(sle->at(~sfAMMID)); BEAST_EXPECT(sle->at(~sfAMMID) == ammKey); - for (auto const& trustKeylet : - {keylet::line(ammAcctID, A1["USD"]), - keylet::line(A1, ammIssue)}) + for (auto const& trustKeylet : {keylet::line(ammAcctID, A1["USD"]), keylet::line(A1, ammIssue)}) { if (auto const line = ac.view().peek(trustKeylet); !line) { @@ -377,12 +352,8 @@ class Invariants_test : public beast::unit_test::suite STAmount const lowLimit = line->at(sfLowLimit); STAmount const highLimit = line->at(sfHighLimit); BEAST_EXPECT( - trustDelete( - ac.view(), - line, - lowLimit.getIssuer(), - highLimit.getIssuer(), - ac.journal) == tesSUCCESS); + trustDelete(ac.view(), line, lowLimit.getIssuer(), highLimit.getIssuer(), ac.journal) == + tesSUCCESS); } } @@ -391,11 +362,8 @@ class Invariants_test : public beast::unit_test::suite return false; auto const ownerDirKeylet = keylet::ownerDir(ammAcctID); - BEAST_EXPECT(ac.view().dirRemove( - ownerDirKeylet, ammSle->at(sfOwnerNode), ammKey, false)); - BEAST_EXPECT( - !ac.view().exists(ownerDirKeylet) || - ac.view().emptyDirDelete(ownerDirKeylet)); + BEAST_EXPECT(ac.view().dirRemove(ownerDirKeylet, ammSle->at(sfOwnerNode), ammKey, false)); + BEAST_EXPECT(!ac.view().exists(ownerDirKeylet) || ac.view().emptyDirDelete(ownerDirKeylet)); // Clear the balance so the "account deletion left behind a // non-zero balance" check doesn't trip earlier than the desired @@ -426,8 +394,7 @@ class Invariants_test : public beast::unit_test::suite using namespace test::jtx; testcase << "ledger entry types don't match"; doInvariantCheck( - {{"ledger entry type mismatch"}, - {"XRP net change of -1000000000 doesn't match fee 0"}}, + {{"ledger entry type mismatch"}, {"XRP net change of -1000000000 doesn't match fee 0"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // replace an entry in the table with an SLE of a different type auto const sle = ac.view().peek(keylet::account(A1.id())); @@ -439,8 +406,7 @@ class Invariants_test : public beast::unit_test::suite }); doInvariantCheck( - {{"invalid ledger entry type added"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"invalid ledger entry type added"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // add an entry in the table with an SLE of an invalid type auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) @@ -449,8 +415,7 @@ class Invariants_test : public beast::unit_test::suite // make a dummy escrow ledger entry, then change the type to an // unsupported value so that the valid type invariant check // will fail. - auto const sleNew = std::make_shared( - keylet::escrow(A1, (*sle)[sfSequence] + 2)); + auto const sleNew = std::make_shared(keylet::escrow(A1, (*sle)[sfSequence] + 2)); // We don't use ltNICKNAME directly since it's marked deprecated // to prevent accidental use elsewhere. @@ -466,11 +431,9 @@ class Invariants_test : public beast::unit_test::suite using namespace test::jtx; testcase << "trust lines with XRP not allowed"; doInvariantCheck( - {{"an XRP trust line was created"}}, - [](Account const& A1, Account const& A2, ApplyContext& ac) { + {{"an XRP trust line was created"}}, [](Account const& A1, Account const& A2, ApplyContext& ac) { // create simple trust SLE with xrp currency - auto const sleNew = std::make_shared( - keylet::line(A1, A2, xrpIssue().currency)); + auto const sleNew = std::make_shared(keylet::line(A1, A2, xrpIssue().currency)); ac.view().insert(sleNew); return true; }); @@ -486,8 +449,7 @@ class Invariants_test : public beast::unit_test::suite {{"a trust line with deep freeze flag without normal freeze was " "created"}}, [](Account const& A1, Account const& A2, ApplyContext& ac) { - auto const sleNew = std::make_shared( - keylet::line(A1, A2, A1["USD"].currency)); + auto const sleNew = std::make_shared(keylet::line(A1, A2, A1["USD"].currency)); sleNew->setFieldAmount(sfLowLimit, A1["USD"](0)); sleNew->setFieldAmount(sfHighLimit, A1["USD"](0)); @@ -502,8 +464,7 @@ class Invariants_test : public beast::unit_test::suite {{"a trust line with deep freeze flag without normal freeze was " "created"}}, [](Account const& A1, Account const& A2, ApplyContext& ac) { - auto const sleNew = std::make_shared( - keylet::line(A1, A2, A1["USD"].currency)); + auto const sleNew = std::make_shared(keylet::line(A1, A2, A1["USD"].currency)); sleNew->setFieldAmount(sfLowLimit, A1["USD"](0)); sleNew->setFieldAmount(sfHighLimit, A1["USD"](0)); std::uint32_t uFlags = 0u; @@ -517,8 +478,7 @@ class Invariants_test : public beast::unit_test::suite {{"a trust line with deep freeze flag without normal freeze was " "created"}}, [](Account const& A1, Account const& A2, ApplyContext& ac) { - auto const sleNew = std::make_shared( - keylet::line(A1, A2, A1["USD"].currency)); + auto const sleNew = std::make_shared(keylet::line(A1, A2, A1["USD"].currency)); sleNew->setFieldAmount(sfLowLimit, A1["USD"](0)); sleNew->setFieldAmount(sfHighLimit, A1["USD"](0)); std::uint32_t uFlags = 0u; @@ -532,8 +492,7 @@ class Invariants_test : public beast::unit_test::suite {{"a trust line with deep freeze flag without normal freeze was " "created"}}, [](Account const& A1, Account const& A2, ApplyContext& ac) { - auto const sleNew = std::make_shared( - keylet::line(A1, A2, A1["USD"].currency)); + auto const sleNew = std::make_shared(keylet::line(A1, A2, A1["USD"].currency)); sleNew->setFieldAmount(sfLowLimit, A1["USD"](0)); sleNew->setFieldAmount(sfHighLimit, A1["USD"](0)); std::uint32_t uFlags = 0u; @@ -547,8 +506,7 @@ class Invariants_test : public beast::unit_test::suite {{"a trust line with deep freeze flag without normal freeze was " "created"}}, [](Account const& A1, Account const& A2, ApplyContext& ac) { - auto const sleNew = std::make_shared( - keylet::line(A1, A2, A1["USD"].currency)); + auto const sleNew = std::make_shared(keylet::line(A1, A2, A1["USD"].currency)); sleNew->setFieldAmount(sfLowLimit, A1["USD"](0)); sleNew->setFieldAmount(sfHighLimit, A1["USD"](0)); std::uint32_t uFlags = 0u; @@ -567,55 +525,49 @@ class Invariants_test : public beast::unit_test::suite Account G1{"G1"}; // Helper function to establish the trustlines - auto const createTrustlines = - [&](Account const& A1, Account const& A2, Env& env) { - // Preclose callback to establish trust lines with gateway - env.fund(XRP(1000), G1); + auto const createTrustlines = [&](Account const& A1, Account const& A2, Env& env) { + // Preclose callback to establish trust lines with gateway + env.fund(XRP(1000), G1); - env.trust(G1["USD"](10000), A1); - env.trust(G1["USD"](10000), A2); - env.close(); + env.trust(G1["USD"](10000), A1); + env.trust(G1["USD"](10000), A2); + env.close(); - env(pay(G1, A1, G1["USD"](1000))); - env(pay(G1, A2, G1["USD"](1000))); - env.close(); + env(pay(G1, A1, G1["USD"](1000))); + env(pay(G1, A2, G1["USD"](1000))); + env.close(); - return true; - }; - - auto const A1FrozenByIssuer = - [&](Account const& A1, Account const& A2, Env& env) { - createTrustlines(A1, A2, env); - env(trust(G1, A1["USD"](10000), tfSetFreeze)); - env.close(); - - return true; - }; - - auto const A1DeepFrozenByIssuer = - [&](Account const& A1, Account const& A2, Env& env) { - A1FrozenByIssuer(A1, A2, env); - env(trust(G1, A1["USD"](10000), tfSetDeepFreeze)); - env.close(); - - return true; - }; - - auto const changeBalances = [&](Account const& A1, - Account const& A2, - ApplyContext& ac, - int A1Balance, - int A2Balance) { - auto const sleA1 = ac.view().peek(keylet::line(A1, G1["USD"])); - auto const sleA2 = ac.view().peek(keylet::line(A2, G1["USD"])); - - sleA1->setFieldAmount(sfBalance, G1["USD"](A1Balance)); - sleA2->setFieldAmount(sfBalance, G1["USD"](A2Balance)); - - ac.view().update(sleA1); - ac.view().update(sleA2); + return true; }; + auto const A1FrozenByIssuer = [&](Account const& A1, Account const& A2, Env& env) { + createTrustlines(A1, A2, env); + env(trust(G1, A1["USD"](10000), tfSetFreeze)); + env.close(); + + return true; + }; + + auto const A1DeepFrozenByIssuer = [&](Account const& A1, Account const& A2, Env& env) { + A1FrozenByIssuer(A1, A2, env); + env(trust(G1, A1["USD"](10000), tfSetDeepFreeze)); + env.close(); + + return true; + }; + + auto const changeBalances = + [&](Account const& A1, Account const& A2, ApplyContext& ac, int A1Balance, int A2Balance) { + auto const sleA1 = ac.view().peek(keylet::line(A1, G1["USD"])); + auto const sleA2 = ac.view().peek(keylet::line(A2, G1["USD"])); + + sleA1->setFieldAmount(sfBalance, G1["USD"](A1Balance)); + sleA2->setFieldAmount(sfBalance, G1["USD"](A2Balance)); + + ac.view().update(sleA1); + ac.view().update(sleA2); + }; + // test: imitating frozen A1 making a payment to A2. doInvariantCheck( {{"Attempting to move frozen funds"}}, @@ -673,8 +625,7 @@ class Invariants_test : public beast::unit_test::suite }); doInvariantCheck( - {{"incorrect account XRP balance"}, - {"XRP net change was positive: 99999999000000001"}}, + {{"incorrect account XRP balance"}, {"XRP net change was positive: 99999999000000001"}}, [this](Account const& A1, Account const&, ApplyContext& ac) { // balance exceeds genesis amount auto const sle = ac.view().peek(keylet::account(A1.id())); @@ -689,8 +640,7 @@ class Invariants_test : public beast::unit_test::suite }); doInvariantCheck( - {{"incorrect account XRP balance"}, - {"XRP net change of -1000000001 doesn't match fee 0"}}, + {{"incorrect account XRP balance"}, {"XRP net change of -1000000001 doesn't match fee 0"}}, [this](Account const& A1, Account const&, ApplyContext& ac) { // balance is negative auto const sle = ac.view().peek(keylet::account(A1.id())); @@ -711,26 +661,21 @@ class Invariants_test : public beast::unit_test::suite testcase << "Transaction fee checks"; doInvariantCheck( - {{"fee paid was negative: -1"}, - {"XRP net change of 0 doesn't match fee -1"}}, + {{"fee paid was negative: -1"}, {"XRP net change of 0 doesn't match fee -1"}}, [](Account const&, Account const&, ApplyContext&) { return true; }, XRPAmount{-1}); doInvariantCheck( {{"fee paid exceeds system limit: "s + to_string(INITIAL_XRP)}, - {"XRP net change of 0 doesn't match fee "s + - to_string(INITIAL_XRP)}}, + {"XRP net change of 0 doesn't match fee "s + to_string(INITIAL_XRP)}}, [](Account const&, Account const&, ApplyContext&) { return true; }, XRPAmount{INITIAL_XRP}); doInvariantCheck( - {{"fee paid is 20 exceeds fee specified in transaction."}, - {"XRP net change of 0 doesn't match fee 20"}}, + {{"fee paid is 20 exceeds fee specified in transaction."}, {"XRP net change of 0 doesn't match fee 20"}}, [](Account const&, Account const&, ApplyContext&) { return true; }, XRPAmount{20}, - STTx{ttACCOUNT_SET, [](STObject& tx) { - tx.setFieldAmount(sfFee, XRPAmount{10}); - }}); + STTx{ttACCOUNT_SET, [](STObject& tx) { tx.setFieldAmount(sfFee, XRPAmount{10}); }}); } void @@ -739,55 +684,46 @@ class Invariants_test : public beast::unit_test::suite using namespace test::jtx; testcase << "no bad offers"; - doInvariantCheck( - {{"offer with a bad amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { - // offer with negative takerpays - auto const sle = ac.view().peek(keylet::account(A1.id())); - if (!sle) - return false; - auto sleNew = std::make_shared( - keylet::offer(A1.id(), (*sle)[sfSequence])); - sleNew->setAccountID(sfAccount, A1.id()); - sleNew->setFieldU32(sfSequence, (*sle)[sfSequence]); - sleNew->setFieldAmount(sfTakerPays, XRP(-1)); - ac.view().insert(sleNew); - return true; - }); + doInvariantCheck({{"offer with a bad amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { + // offer with negative takerpays + auto const sle = ac.view().peek(keylet::account(A1.id())); + if (!sle) + return false; + auto sleNew = std::make_shared(keylet::offer(A1.id(), (*sle)[sfSequence])); + sleNew->setAccountID(sfAccount, A1.id()); + sleNew->setFieldU32(sfSequence, (*sle)[sfSequence]); + sleNew->setFieldAmount(sfTakerPays, XRP(-1)); + ac.view().insert(sleNew); + return true; + }); - doInvariantCheck( - {{"offer with a bad amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { - // offer with negative takergets - auto const sle = ac.view().peek(keylet::account(A1.id())); - if (!sle) - return false; - auto sleNew = std::make_shared( - keylet::offer(A1.id(), (*sle)[sfSequence])); - sleNew->setAccountID(sfAccount, A1.id()); - sleNew->setFieldU32(sfSequence, (*sle)[sfSequence]); - sleNew->setFieldAmount(sfTakerPays, A1["USD"](10)); - sleNew->setFieldAmount(sfTakerGets, XRP(-1)); - ac.view().insert(sleNew); - return true; - }); + doInvariantCheck({{"offer with a bad amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { + // offer with negative takergets + auto const sle = ac.view().peek(keylet::account(A1.id())); + if (!sle) + return false; + auto sleNew = std::make_shared(keylet::offer(A1.id(), (*sle)[sfSequence])); + sleNew->setAccountID(sfAccount, A1.id()); + sleNew->setFieldU32(sfSequence, (*sle)[sfSequence]); + sleNew->setFieldAmount(sfTakerPays, A1["USD"](10)); + sleNew->setFieldAmount(sfTakerGets, XRP(-1)); + ac.view().insert(sleNew); + return true; + }); - doInvariantCheck( - {{"offer with a bad amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { - // offer XRP to XRP - auto const sle = ac.view().peek(keylet::account(A1.id())); - if (!sle) - return false; - auto sleNew = std::make_shared( - keylet::offer(A1.id(), (*sle)[sfSequence])); - sleNew->setAccountID(sfAccount, A1.id()); - sleNew->setFieldU32(sfSequence, (*sle)[sfSequence]); - sleNew->setFieldAmount(sfTakerPays, XRP(10)); - sleNew->setFieldAmount(sfTakerGets, XRP(11)); - ac.view().insert(sleNew); - return true; - }); + doInvariantCheck({{"offer with a bad amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { + // offer XRP to XRP + auto const sle = ac.view().peek(keylet::account(A1.id())); + if (!sle) + return false; + auto sleNew = std::make_shared(keylet::offer(A1.id(), (*sle)[sfSequence])); + sleNew->setAccountID(sfAccount, A1.id()); + sleNew->setFieldU32(sfSequence, (*sle)[sfSequence]); + sleNew->setFieldAmount(sfTakerPays, XRP(10)); + sleNew->setFieldAmount(sfTakerGets, XRP(11)); + ac.view().insert(sleNew); + return true; + }); } void @@ -797,30 +733,26 @@ class Invariants_test : public beast::unit_test::suite testcase << "no zero escrow"; doInvariantCheck( - {{"XRP net change of -1000000 doesn't match fee 0"}, - {"escrow specifies invalid amount"}}, + {{"XRP net change of -1000000 doesn't match fee 0"}, {"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // escrow with negative amount auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - auto sleNew = std::make_shared( - keylet::escrow(A1, (*sle)[sfSequence] + 2)); + auto sleNew = std::make_shared(keylet::escrow(A1, (*sle)[sfSequence] + 2)); sleNew->setFieldAmount(sfAmount, XRP(-1)); ac.view().insert(sleNew); return true; }); doInvariantCheck( - {{"XRP net change was positive: 100000000000000001"}, - {"escrow specifies invalid amount"}}, + {{"XRP net change was positive: 100000000000000001"}, {"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // escrow with too-large amount auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - auto sleNew = std::make_shared( - keylet::escrow(A1, (*sle)[sfSequence] + 2)); + auto sleNew = std::make_shared(keylet::escrow(A1, (*sle)[sfSequence] + 2)); // Use `drops(1)` to bypass a call to STAmount::canonicalize // with an invalid value sleNew->setFieldAmount(sfAmount, INITIAL_XRP + drops(1)); @@ -830,17 +762,14 @@ class Invariants_test : public beast::unit_test::suite // IOU < 0 doInvariantCheck( - {{"escrow specifies invalid amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // escrow with too-little iou auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - auto sleNew = std::make_shared( - keylet::escrow(A1, (*sle)[sfSequence] + 2)); + auto sleNew = std::make_shared(keylet::escrow(A1, (*sle)[sfSequence] + 2)); - Issue const usd{ - Currency(0x5553440000000000), AccountID(0x4985601)}; + Issue const usd{Currency(0x5553440000000000), AccountID(0x4985601)}; STAmount amt(usd, -1); sleNew->setFieldAmount(sfAmount, amt); ac.view().insert(sleNew); @@ -849,14 +778,12 @@ class Invariants_test : public beast::unit_test::suite // IOU bad currency doInvariantCheck( - {{"escrow specifies invalid amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // escrow with bad iou currency auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - auto sleNew = std::make_shared( - keylet::escrow(A1, (*sle)[sfSequence] + 2)); + auto sleNew = std::make_shared(keylet::escrow(A1, (*sle)[sfSequence] + 2)); Issue const bad{badCurrency(), AccountID(0x4985601)}; STAmount amt(bad, 1); @@ -867,17 +794,14 @@ class Invariants_test : public beast::unit_test::suite // MPT < 0 doInvariantCheck( - {{"escrow specifies invalid amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // escrow with too-little mpt auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - auto sleNew = std::make_shared( - keylet::escrow(A1, (*sle)[sfSequence] + 2)); + auto sleNew = std::make_shared(keylet::escrow(A1, (*sle)[sfSequence] + 2)); - MPTIssue const mpt{ - MPTIssue{makeMptID(1, AccountID(0x4985601))}}; + MPTIssue const mpt{MPTIssue{makeMptID(1, AccountID(0x4985601))}}; STAmount amt(mpt, -1); sleNew->setFieldAmount(sfAmount, amt); ac.view().insert(sleNew); @@ -886,17 +810,14 @@ class Invariants_test : public beast::unit_test::suite // MPT OutstandingAmount < 0 doInvariantCheck( - {{"escrow specifies invalid amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // mptissuance outstanding is negative auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - MPTIssue const mpt{ - MPTIssue{makeMptID(1, AccountID(0x4985601))}}; - auto sleNew = - std::make_shared(keylet::mptIssuance(mpt.getMptID())); + MPTIssue const mpt{MPTIssue{makeMptID(1, AccountID(0x4985601))}}; + auto sleNew = std::make_shared(keylet::mptIssuance(mpt.getMptID())); sleNew->setFieldU64(sfOutstandingAmount, -1); ac.view().insert(sleNew); return true; @@ -904,17 +825,14 @@ class Invariants_test : public beast::unit_test::suite // MPT LockedAmount < 0 doInvariantCheck( - {{"escrow specifies invalid amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // mptissuance locked is less than locked auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - MPTIssue const mpt{ - MPTIssue{makeMptID(1, AccountID(0x4985601))}}; - auto sleNew = - std::make_shared(keylet::mptIssuance(mpt.getMptID())); + MPTIssue const mpt{MPTIssue{makeMptID(1, AccountID(0x4985601))}}; + auto sleNew = std::make_shared(keylet::mptIssuance(mpt.getMptID())); sleNew->setFieldU64(sfLockedAmount, -1); ac.view().insert(sleNew); return true; @@ -922,17 +840,14 @@ class Invariants_test : public beast::unit_test::suite // MPT OutstandingAmount < LockedAmount doInvariantCheck( - {{"escrow specifies invalid amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // mptissuance outstanding is less than locked auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - MPTIssue const mpt{ - MPTIssue{makeMptID(1, AccountID(0x4985601))}}; - auto sleNew = - std::make_shared(keylet::mptIssuance(mpt.getMptID())); + MPTIssue const mpt{MPTIssue{makeMptID(1, AccountID(0x4985601))}}; + auto sleNew = std::make_shared(keylet::mptIssuance(mpt.getMptID())); sleNew->setFieldU64(sfOutstandingAmount, 1); sleNew->setFieldU64(sfLockedAmount, 10); ac.view().insert(sleNew); @@ -941,17 +856,14 @@ class Invariants_test : public beast::unit_test::suite // MPT MPTAmount < 0 doInvariantCheck( - {{"escrow specifies invalid amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // mptoken amount is negative auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - MPTIssue const mpt{ - MPTIssue{makeMptID(1, AccountID(0x4985601))}}; - auto sleNew = - std::make_shared(keylet::mptoken(mpt.getMptID(), A1)); + MPTIssue const mpt{MPTIssue{makeMptID(1, AccountID(0x4985601))}}; + auto sleNew = std::make_shared(keylet::mptoken(mpt.getMptID(), A1)); sleNew->setFieldU64(sfMPTAmount, -1); ac.view().insert(sleNew); return true; @@ -959,17 +871,14 @@ class Invariants_test : public beast::unit_test::suite // MPT LockedAmount < 0 doInvariantCheck( - {{"escrow specifies invalid amount"}}, - [](Account const& A1, Account const&, ApplyContext& ac) { + {{"escrow specifies invalid amount"}}, [](Account const& A1, Account const&, ApplyContext& ac) { // mptoken locked amount is negative auto const sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; - MPTIssue const mpt{ - MPTIssue{makeMptID(1, AccountID(0x4985601))}}; - auto sleNew = - std::make_shared(keylet::mptoken(mpt.getMptID(), A1)); + MPTIssue const mpt{MPTIssue{makeMptID(1, AccountID(0x4985601))}}; + auto sleNew = std::make_shared(keylet::mptoken(mpt.getMptID(), A1)); sleNew->setFieldU64(sfLockedAmount, -1); ac.view().insert(sleNew); return true; @@ -982,17 +891,15 @@ class Invariants_test : public beast::unit_test::suite using namespace test::jtx; testcase << "valid new account root"; - doInvariantCheck( - {{"account root created illegally"}}, - [](Account const&, Account const&, ApplyContext& ac) { - // Insert a new account root created by a non-payment into - // the view. - Account const A3{"A3"}; - Keylet const acctKeylet = keylet::account(A3); - auto const sleNew = std::make_shared(acctKeylet); - ac.view().insert(sleNew); - return true; - }); + doInvariantCheck({{"account root created illegally"}}, [](Account const&, Account const&, ApplyContext& ac) { + // Insert a new account root created by a non-payment into + // the view. + Account const A3{"A3"}; + Keylet const acctKeylet = keylet::account(A3); + auto const sleNew = std::make_shared(acctKeylet); + ac.view().insert(sleNew); + return true; + }); doInvariantCheck( {{"multiple accounts created in a single transaction"}}, @@ -1035,9 +942,7 @@ class Invariants_test : public beast::unit_test::suite auto const sleNew = std::make_shared(acctKeylet); sleNew->setFieldU32(sfSequence, 0); sleNew->setFieldH256(sfAMMID, uint256(1)); - sleNew->setFieldU32( - sfFlags, - lsfDisableMaster | lsfDefaultRipple | lsfDefaultRipple); + sleNew->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDefaultRipple); ac.view().insert(sleNew); return true; }, @@ -1052,9 +957,7 @@ class Invariants_test : public beast::unit_test::suite auto const sleNew = std::make_shared(acctKeylet); sleNew->setFieldU32(sfSequence, ac.view().seq()); sleNew->setFieldH256(sfAMMID, uint256(1)); - sleNew->setFieldU32( - sfFlags, - lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth); + sleNew->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth); ac.view().insert(sleNew); return true; }, @@ -1069,8 +972,7 @@ class Invariants_test : public beast::unit_test::suite auto const sleNew = std::make_shared(acctKeylet); sleNew->setFieldU32(sfSequence, 0); sleNew->setFieldH256(sfAMMID, uint256(1)); - sleNew->setFieldU32( - sfFlags, lsfDisableMaster | lsfDefaultRipple); + sleNew->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple); ac.view().insert(sleNew); return true; }, @@ -1085,10 +987,7 @@ class Invariants_test : public beast::unit_test::suite auto const sleNew = std::make_shared(acctKeylet); sleNew->setFieldU32(sfSequence, 0); sleNew->setFieldH256(sfAMMID, uint256(1)); - sleNew->setFieldU32( - sfFlags, - lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth | - lsfRequireDestTag); + sleNew->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth | lsfRequireDestTag); ac.view().insert(sleNew); return true; }, @@ -1103,21 +1002,17 @@ class Invariants_test : public beast::unit_test::suite testcase << "NFTokenPage"; // lambda that returns an STArray of NFTokenIDs. - uint256 const firstNFTID( - "0000000000000000000000000000000000000001FFFFFFFFFFFFFFFF00000000"); + uint256 const firstNFTID("0000000000000000000000000000000000000001FFFFFFFFFFFFFFFF00000000"); auto makeNFTokenIDs = [&firstNFTID](unsigned int nftCount) { - SOTemplate const* nfTokenTemplate = - InnerObjectFormats::getInstance().findSOTemplateBySField( - sfNFToken); + SOTemplate const* nfTokenTemplate = InnerObjectFormats::getInstance().findSOTemplateBySField(sfNFToken); uint256 nftID(firstNFTID); STArray ret; for (int i = 0; i < nftCount; ++i) { - STObject newNFToken( - *nfTokenTemplate, sfNFToken, [&nftID](STObject& object) { - object.setFieldH256(sfNFTokenID, nftID); - }); + STObject newNFToken(*nfTokenTemplate, sfNFToken, [&nftID](STObject& object) { + object.setFieldH256(sfNFTokenID, nftID); + }); ret.push_back(std::move(newNFToken)); ++nftID; } @@ -1125,9 +1020,7 @@ class Invariants_test : public beast::unit_test::suite }; doInvariantCheck( - {{"NFT page has invalid size"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const&, ApplyContext& ac) { + {{"NFT page has invalid size"}}, [&makeNFTokenIDs](Account const& A1, Account const&, ApplyContext& ac) { auto nftPage = std::make_shared(keylet::nftpage_max(A1)); nftPage->setFieldArray(sfNFTokens, makeNFTokenIDs(0)); @@ -1136,9 +1029,7 @@ class Invariants_test : public beast::unit_test::suite }); doInvariantCheck( - {{"NFT page has invalid size"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const&, ApplyContext& ac) { + {{"NFT page has invalid size"}}, [&makeNFTokenIDs](Account const& A1, Account const&, ApplyContext& ac) { auto nftPage = std::make_shared(keylet::nftpage_max(A1)); nftPage->setFieldArray(sfNFTokens, makeNFTokenIDs(33)); @@ -1147,9 +1038,7 @@ class Invariants_test : public beast::unit_test::suite }); doInvariantCheck( - {{"NFTs on page are not sorted"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const&, ApplyContext& ac) { + {{"NFTs on page are not sorted"}}, [&makeNFTokenIDs](Account const& A1, Account const&, ApplyContext& ac) { STArray nfTokens = makeNFTokenIDs(2); std::iter_swap(nfTokens.begin(), nfTokens.begin() + 1); @@ -1161,9 +1050,7 @@ class Invariants_test : public beast::unit_test::suite }); doInvariantCheck( - {{"NFT contains empty URI"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const&, ApplyContext& ac) { + {{"NFT contains empty URI"}}, [&makeNFTokenIDs](Account const& A1, Account const&, ApplyContext& ac) { STArray nfTokens = makeNFTokenIDs(1); nfTokens[0].setFieldVL(sfURI, Blob{}); @@ -1176,12 +1063,10 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"NFT page is improperly linked"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const&, ApplyContext& ac) { + [&makeNFTokenIDs](Account const& A1, Account const&, ApplyContext& ac) { auto nftPage = std::make_shared(keylet::nftpage_max(A1)); nftPage->setFieldArray(sfNFTokens, makeNFTokenIDs(1)); - nftPage->setFieldH256( - sfPreviousPageMin, keylet::nftpage_max(A1).key); + nftPage->setFieldH256(sfPreviousPageMin, keylet::nftpage_max(A1).key); ac.view().insert(nftPage); return true; @@ -1189,12 +1074,10 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"NFT page is improperly linked"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const& A2, ApplyContext& ac) { + [&makeNFTokenIDs](Account const& A1, Account const& A2, ApplyContext& ac) { auto nftPage = std::make_shared(keylet::nftpage_max(A1)); nftPage->setFieldArray(sfNFTokens, makeNFTokenIDs(1)); - nftPage->setFieldH256( - sfPreviousPageMin, keylet::nftpage_min(A2).key); + nftPage->setFieldH256(sfPreviousPageMin, keylet::nftpage_min(A2).key); ac.view().insert(nftPage); return true; @@ -1202,8 +1085,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"NFT page is improperly linked"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const&, ApplyContext& ac) { + [&makeNFTokenIDs](Account const& A1, Account const&, ApplyContext& ac) { auto nftPage = std::make_shared(keylet::nftpage_max(A1)); nftPage->setFieldArray(sfNFTokens, makeNFTokenIDs(1)); nftPage->setFieldH256(sfNextPageMin, nftPage->key()); @@ -1214,28 +1096,22 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"NFT page is improperly linked"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const& A2, ApplyContext& ac) { + [&makeNFTokenIDs](Account const& A1, Account const& A2, ApplyContext& ac) { STArray nfTokens = makeNFTokenIDs(1); - auto nftPage = std::make_shared(keylet::nftpage( - keylet::nftpage_max(A1), - ++(nfTokens[0].getFieldH256(sfNFTokenID)))); + auto nftPage = std::make_shared( + keylet::nftpage(keylet::nftpage_max(A1), ++(nfTokens[0].getFieldH256(sfNFTokenID)))); nftPage->setFieldArray(sfNFTokens, std::move(nfTokens)); - nftPage->setFieldH256( - sfNextPageMin, keylet::nftpage_max(A2).key); + nftPage->setFieldH256(sfNextPageMin, keylet::nftpage_max(A2).key); ac.view().insert(nftPage); return true; }); doInvariantCheck( - {{"NFT found in incorrect page"}}, - [&makeNFTokenIDs]( - Account const& A1, Account const&, ApplyContext& ac) { + {{"NFT found in incorrect page"}}, [&makeNFTokenIDs](Account const& A1, Account const&, ApplyContext& ac) { STArray nfTokens = makeNFTokenIDs(2); - auto nftPage = std::make_shared(keylet::nftpage( - keylet::nftpage_max(A1), - (nfTokens[1].getFieldH256(sfNFTokenID)))); + auto nftPage = std::make_shared( + keylet::nftpage(keylet::nftpage_max(A1), (nfTokens[1].getFieldH256(sfNFTokenID)))); nftPage->setFieldArray(sfNFTokens, std::move(nfTokens)); ac.view().insert(nftPage); @@ -1259,8 +1135,7 @@ class Invariants_test : public beast::unit_test::suite auto cred = STObject::makeInnerObject(sfCredential); cred.setAccountID(sfIssuer, A2); auto credType = "cred_type" + std::to_string(n); - cred.setFieldVL( - sfCredentialType, Slice(credType.c_str(), credType.size())); + cred.setFieldVL(sfCredentialType, Slice(credType.c_str(), credType.size())); credentials.push_back(std::move(cred)); } sle->setFieldArray(sfAcceptedCredentials, credentials); @@ -1292,8 +1167,7 @@ class Invariants_test : public beast::unit_test::suite auto constexpr tooBig = maxPermissionedDomainCredentialsArraySize + 1; doInvariantCheck( - {{"permissioned domain bad credentials size " + - std::to_string(tooBig)}}, + {{"permissioned domain bad credentials size " + std::to_string(tooBig)}}, [](Account const& A1, Account const& A2, ApplyContext& ac) { Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10); auto slePd = std::make_shared(pdKeylet); @@ -1305,11 +1179,8 @@ class Invariants_test : public beast::unit_test::suite { auto cred = STObject::makeInnerObject(sfCredential); cred.setAccountID(sfIssuer, A2); - auto credType = - std::string("cred_type") + std::to_string(n); - cred.setFieldVL( - sfCredentialType, - Slice(credType.c_str(), credType.size())); + auto credType = std::string("cred_type") + std::to_string(n); + cred.setFieldVL(sfCredentialType, Slice(credType.c_str(), credType.size())); credentials.push_back(std::move(cred)); } slePd->setFieldArray(sfAcceptedCredentials, credentials); @@ -1334,11 +1205,8 @@ class Invariants_test : public beast::unit_test::suite { auto cred = STObject::makeInnerObject(sfCredential); cred.setAccountID(sfIssuer, A2); - auto credType = - std::string("cred_type") + std::to_string(9 - n); - cred.setFieldVL( - sfCredentialType, - Slice(credType.c_str(), credType.size())); + auto credType = std::string("cred_type") + std::to_string(9 - n); + cred.setFieldVL(sfCredentialType, Slice(credType.c_str(), credType.size())); credentials.push_back(std::move(cred)); } slePd->setFieldArray(sfAcceptedCredentials, credentials); @@ -1399,8 +1267,7 @@ class Invariants_test : public beast::unit_test::suite testcase << "PermissionedDomain Set 2"; doInvariantCheck( - {{"permissioned domain bad credentials size " + - std::to_string(tooBig)}}, + {{"permissioned domain bad credentials size " + std::to_string(tooBig)}}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { Keylet const pdKeylet = keylet::permissionedDomain(A1.id(), 10); auto slePd = std::make_shared(pdKeylet); @@ -1417,9 +1284,7 @@ class Invariants_test : public beast::unit_test::suite auto cred = STObject::makeInnerObject(sfCredential); cred.setAccountID(sfIssuer, A2); auto credType = "cred_type2" + std::to_string(n); - cred.setFieldVL( - sfCredentialType, - Slice(credType.c_str(), credType.size())); + cred.setFieldVL(sfCredentialType, Slice(credType.c_str(), credType.size())); credentials.push_back(std::move(cred)); } @@ -1450,11 +1315,8 @@ class Invariants_test : public beast::unit_test::suite { auto cred = STObject::makeInnerObject(sfCredential); cred.setAccountID(sfIssuer, A2); - auto credType = - std::string("cred_type2") + std::to_string(9 - n); - cred.setFieldVL( - sfCredentialType, - Slice(credType.c_str(), credType.size())); + auto credType = std::string("cred_type2") + std::to_string(9 - n); + cred.setFieldVL(sfCredentialType, Slice(credType.c_str(), credType.size())); credentials.push_back(std::move(cred)); } @@ -1485,8 +1347,7 @@ class Invariants_test : public beast::unit_test::suite { auto cred = STObject::makeInnerObject(sfCredential); cred.setAccountID(sfIssuer, A2); - cred.setFieldVL( - sfCredentialType, Slice("cred_type", 9)); + cred.setFieldVL(sfCredentialType, Slice("cred_type", 9)); credentials.push_back(std::move(cred)); } slePd->setFieldArray(sfAcceptedCredentials, credentials); @@ -1508,23 +1369,21 @@ class Invariants_test : public beast::unit_test::suite using namespace jtx; AccountID pseudoAccountID; - Preclose createPseudo = - [&, this](Account const& a, Account const& b, Env& env) { - PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + Preclose createPseudo = [&, this](Account const& a, Account const& b, Env& env) { + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; - // Create vault - Vault vault{env}; - auto [tx, vKeylet] = - vault.create({.owner = a, .asset = xrpAsset}); - env(tx); - env.close(); - if (auto const vSle = env.le(vKeylet); BEAST_EXPECT(vSle)) - { - pseudoAccountID = vSle->at(sfAccount); - } + // Create vault + Vault vault{env}; + auto [tx, vKeylet] = vault.create({.owner = a, .asset = xrpAsset}); + env(tx); + env.close(); + if (auto const vSle = env.le(vKeylet); BEAST_EXPECT(vSle)) + { + pseudoAccountID = vSle->at(sfAccount); + } - return BEAST_EXPECT(env.le(keylet::account(pseudoAccountID))); - }; + return BEAST_EXPECT(env.le(keylet::account(pseudoAccountID))); + }; /* Cases to check "pseudo-account has 0 pseudo-account fields set" @@ -1556,9 +1415,7 @@ class Invariants_test : public beast::unit_test::suite }, { "pseudo-account has a regular key", - [](SLE::pointer& sle) { - sle->at(sfRegularKey) = Account("regular").id(); - }, + [](SLE::pointer& sle) { sle->at(sfRegularKey) = Account("regular").id(); }, }, }); @@ -1644,9 +1501,8 @@ class Invariants_test : public beast::unit_test::suite [](STObject& tx) { tx.setFieldH256( sfDomainID, - uint256{ - "F10D0CC9A0F9A3CBF585B80BE09A186483668FDBDD39AA7E33" - "70F3649CE134E5"}); + uint256{"F10D0CC9A0F9A3CBF585B80BE09A186483668FDBDD39AA7E33" + "70F3649CE134E5"}); Account const A1{"A1"}; tx.setFieldAmount(sfTakerPays, A1["USD"](10)); tx.setFieldAmount(sfTakerGets, XRP(1)); @@ -1734,8 +1590,7 @@ class Invariants_test : public beast::unit_test::suite auto slePd = std::make_shared(pdKeylet); createPermissionedDomain(ac, slePd, A1, A2); - Keylet const badDomainKeylet = - keylet::permissionedDomain(A1.id(), 20); + Keylet const badDomainKeylet = keylet::permissionedDomain(A1.id(), 20); auto sleBadPd = std::make_shared(badDomainKeylet); createPermissionedDomain(ac, sleBadPd, A1, A2); @@ -1753,8 +1608,7 @@ class Invariants_test : public beast::unit_test::suite ttOFFER_CREATE, [&](STObject& tx) { Account const A1{"A1"}; - Keylet const badDomainKey = - keylet::permissionedDomain(A1.id(), 20); + Keylet const badDomainKey = keylet::permissionedDomain(A1.id(), 20); tx.setFieldH256(sfDomainID, badDomainKey.key); tx.setFieldAmount(sfTakerPays, A1["USD"](10)); tx.setFieldAmount(sfTakerGets, XRP(1)); @@ -1781,8 +1635,7 @@ class Invariants_test : public beast::unit_test::suite ttOFFER_CREATE, [&](STObject& tx) { Account const A1{"A1"}; - Keylet const domainKey = - keylet::permissionedDomain(A1.id(), 10); + Keylet const domainKey = keylet::permissionedDomain(A1.id(), 10); tx.setFieldH256(sfDomainID, domainKey.key); tx.setFieldAmount(sfTakerPays, A1["USD"](10)); tx.setFieldAmount(sfTakerGets, XRP(1)); @@ -1791,10 +1644,7 @@ class Invariants_test : public beast::unit_test::suite } Keylet - createLoanBroker( - jtx::Account const& a, - jtx::Env& env, - jtx::PrettyAsset const& asset) + createLoanBroker(jtx::Account const& a, jtx::Env& env, jtx::PrettyAsset const& asset) { using namespace jtx; @@ -1825,39 +1675,27 @@ class Invariants_test : public beast::unit_test::suite // Initialize with a placeholder value because there's no default ctor Keylet loanBrokerKeylet = keylet::amendments(); - Preclose createLoanBroker = - [&, this](Account const& a, Account const& b, Env& env) { - PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; + Preclose createLoanBroker = [&, this](Account const& a, Account const& b, Env& env) { + PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; - loanBrokerKeylet = this->createLoanBroker(a, env, xrpAsset); - return BEAST_EXPECT(env.le(loanBrokerKeylet)); - }; + loanBrokerKeylet = this->createLoanBroker(a, env, xrpAsset); + return BEAST_EXPECT(env.le(loanBrokerKeylet)); + }; { - auto const mods = - std::to_array>({ - [](SLE::pointer& sle) { sle->at(sfSequence) += 1; }, - [](SLE::pointer& sle) { sle->at(sfOwnerNode) += 1; }, - [](SLE::pointer& sle) { sle->at(sfVaultNode) += 1; }, - [](SLE::pointer& sle) { sle->at(sfVaultID) = uint256(1u); }, - [](SLE::pointer& sle) { - sle->at(sfAccount) = sle->at(sfOwner); - }, - [](SLE::pointer& sle) { - sle->at(sfOwner) = sle->at(sfAccount); - }, - [](SLE::pointer& sle) { - sle->at(sfManagementFeeRate) += 1; - }, - [](SLE::pointer& sle) { sle->at(sfCoverRateMinimum) += 1; }, - [](SLE::pointer& sle) { - sle->at(sfCoverRateLiquidation) += 1; - }, - [](SLE::pointer& sle) { sle->at(sfLedgerEntryType) += 1; }, - [](SLE::pointer& sle) { - sle->at(sfLedgerIndex) = sle->at(sfVaultID).value(); - }, - }); + auto const mods = std::to_array>({ + [](SLE::pointer& sle) { sle->at(sfSequence) += 1; }, + [](SLE::pointer& sle) { sle->at(sfOwnerNode) += 1; }, + [](SLE::pointer& sle) { sle->at(sfVaultNode) += 1; }, + [](SLE::pointer& sle) { sle->at(sfVaultID) = uint256(1u); }, + [](SLE::pointer& sle) { sle->at(sfAccount) = sle->at(sfOwner); }, + [](SLE::pointer& sle) { sle->at(sfOwner) = sle->at(sfAccount); }, + [](SLE::pointer& sle) { sle->at(sfManagementFeeRate) += 1; }, + [](SLE::pointer& sle) { sle->at(sfCoverRateMinimum) += 1; }, + [](SLE::pointer& sle) { sle->at(sfCoverRateLiquidation) += 1; }, + [](SLE::pointer& sle) { sle->at(sfLedgerEntryType) += 1; }, + [](SLE::pointer& sle) { sle->at(sfLedgerIndex) = sle->at(sfVaultID).value(); }, + }); for (auto const& mod : mods) { @@ -1881,19 +1719,15 @@ class Invariants_test : public beast::unit_test::suite // TODO: Loan Object { - auto const mods = - std::to_array>({ - [](SLE::pointer& sle) { sle->at(sfLedgerEntryType) += 1; }, - [](SLE::pointer& sle) { - sle->at(sfLedgerIndex) = uint256(1u); - }, - }); + auto const mods = std::to_array>({ + [](SLE::pointer& sle) { sle->at(sfLedgerEntryType) += 1; }, + [](SLE::pointer& sle) { sle->at(sfLedgerIndex) = uint256(1u); }, + }); for (auto const& mod : mods) { doInvariantCheck( - {{"changed an unchangeable field"}}, - [&](Account const& A1, Account const&, ApplyContext& ac) { + {{"changed an unchangeable field"}}, [&](Account const& A1, Account const&, ApplyContext& ac) { auto sle = ac.view().peek(keylet::account(A1.id())); if (!sle) return false; @@ -1913,18 +1747,14 @@ class Invariants_test : public beast::unit_test::suite using namespace jtx; enum class Asset { XRP, IOU, MPT }; - auto const assetTypes = - std::to_array({Asset::XRP, Asset::IOU, Asset::MPT}); + auto const assetTypes = std::to_array({Asset::XRP, Asset::IOU, Asset::MPT}); for (auto const assetType : assetTypes) { // Initialize with a placeholder value because there's no default // ctor Keylet loanBrokerKeylet = keylet::amendments(); - Preclose createLoanBroker = [&, this]( - Account const& alice, - Account const& issuer, - Env& env) { + Preclose createLoanBroker = [&, this](Account const& alice, Account const& issuer, Env& env) { PrettyAsset const asset = [&]() { switch (assetType) { @@ -1938,9 +1768,7 @@ class Invariants_test : public beast::unit_test::suite case Asset::MPT: { MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | - tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); PrettyAsset const mptAsset = mptt.issuanceID(); mptt.authorize({.account = alice}); env(pay(issuer, alice, mptAsset(1000))); @@ -1960,8 +1788,7 @@ class Invariants_test : public beast::unit_test::suite // Ensure the test scenarios are set up completely. The test cases // will need to recompute any of these values it needs for itself // rather than trying to return a bunch of items - auto setupTest = - [&, this](Account const& A1, Account const&, ApplyContext& ac) + auto setupTest = [&, this](Account const& A1, Account const&, ApplyContext& ac) -> std::optional> { if (loanBrokerKeylet.type != ltLOAN_BROKER) return {}; @@ -1976,8 +1803,7 @@ class Invariants_test : public beast::unit_test::suite // The pseudo-account holds the directory, so get it auto const pseudoAccountID = sleBroker->at(sfAccount); - auto const pseudoAccountKeylet = - keylet::account(pseudoAccountID); + auto const pseudoAccountKeylet = keylet::account(pseudoAccountID); // Strictly speaking, we don't need to load the // ACCOUNT_ROOT, but check anyway auto slePseudo = ac.view().peek(pseudoAccountKeylet); @@ -1991,11 +1817,7 @@ class Invariants_test : public beast::unit_test::suite { // Create the directory BEAST_EXPECT( - ::xrpl::directory::createRoot( - ac.view(), - dirKeylet, - loanBrokerKeylet.key, - describe) == 0); + ::xrpl::directory::createRoot(ac.view(), dirKeylet, loanBrokerKeylet.key, describe) == 0); sleDir = ac.view().peek(dirKeylet); } @@ -2006,16 +1828,14 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"Loan Broker with zero OwnerCount has multiple directory " "pages"}}, - [&setupTest, this]( - Account const& A1, Account const& A2, ApplyContext& ac) { + [&setupTest, this](Account const& A1, Account const& A2, ApplyContext& ac) { auto test = setupTest(A1, A2, ac); if (!test || !test->first || !test->second) return false; auto slePseudo = test->first; auto sleDir = test->second; - auto const describe = - describeOwnerDir(slePseudo->at(sfAccount)); + auto const describe = describeOwnerDir(slePseudo->at(sfAccount)); BEAST_EXPECT( ::xrpl::directory::insertPage( @@ -2038,8 +1858,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"Loan Broker with zero OwnerCount has multiple indexes in " "the Directory root"}}, - [&setupTest]( - Account const& A1, Account const& A2, ApplyContext& ac) { + [&setupTest](Account const& A1, Account const& A2, ApplyContext& ac) { auto test = setupTest(A1, A2, ac); if (!test || !test->first || !test->second) return false; @@ -2051,8 +1870,7 @@ class Invariants_test : public beast::unit_test::suite // Put some extra garbage into the directory for (auto const& key : {slePseudo->key(), sleDir->key()}) { - ::xrpl::directory::insertKey( - ac.view(), sleDir, 0, false, indexes, key); + ::xrpl::directory::insertKey(ac.view(), sleDir, 0, false, indexes, key); } return true; @@ -2064,26 +1882,22 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"Loan Broker directory corrupt"}}, - [&setupTest]( - Account const& A1, Account const& A2, ApplyContext& ac) { + [&setupTest](Account const& A1, Account const& A2, ApplyContext& ac) { auto test = setupTest(A1, A2, ac); if (!test || !test->first || !test->second) return false; auto slePseudo = test->first; auto sleDir = test->second; - auto const describe = - describeOwnerDir(slePseudo->at(sfAccount)); + auto const describe = describeOwnerDir(slePseudo->at(sfAccount)); // Empty vector will overwrite the existing entry for the // holding, if any, avoiding the "has multiple indexes" // failure. STVector256 indexes; // Put one meaningless key into the directory - auto const key = - keylet::account(Account("random").id()).key; - ::xrpl::directory::insertKey( - ac.view(), sleDir, 0, false, indexes, key); + auto const key = keylet::account(Account("random").id()).key; + ::xrpl::directory::insertKey(ac.view(), sleDir, 0, false, indexes, key); return true; }, @@ -2095,8 +1909,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {{"Loan Broker with zero OwnerCount has an unexpected entry in " "the directory"}}, - [&setupTest]( - Account const& A1, Account const& A2, ApplyContext& ac) { + [&setupTest](Account const& A1, Account const& A2, ApplyContext& ac) { auto test = setupTest(A1, A2, ac); if (!test || !test->first || !test->second) return false; @@ -2108,8 +1921,7 @@ class Invariants_test : public beast::unit_test::suite // failure. STVector256 indexes; - ::xrpl::directory::insertKey( - ac.view(), sleDir, 0, false, indexes, slePseudo->key()); + ::xrpl::directory::insertKey(ac.view(), sleDir, 0, false, indexes, slePseudo->key()); return true; }, @@ -2164,9 +1976,7 @@ class Invariants_test : public beast::unit_test::suite std::optional accountAssets = {}; std::optional accountShares = {}; }; - auto constexpr adjust = [&](ApplyView& ac, - xrpl::Keylet keylet, - Adjustments args) { + auto constexpr adjust = [&](ApplyView& ac, xrpl::Keylet keylet, Adjustments args) { auto sleVault = ac.peek(keylet); if (!sleVault) return false; @@ -2184,17 +1994,14 @@ class Invariants_test : public beast::unit_test::suite // Remaining fields are adjusted in terms of difference if (args.assetsTotal) - (*sleVault)[sfAssetsTotal] = - *(*sleVault)[sfAssetsTotal] + *args.assetsTotal; + (*sleVault)[sfAssetsTotal] = *(*sleVault)[sfAssetsTotal] + *args.assetsTotal; if (args.assetsAvailable) - (*sleVault)[sfAssetsAvailable] = - *(*sleVault)[sfAssetsAvailable] + *args.assetsAvailable; + (*sleVault)[sfAssetsAvailable] = *(*sleVault)[sfAssetsAvailable] + *args.assetsAvailable; ac.update(sleVault); if (args.sharesTotal) { - (*sleShares)[sfOutstandingAmount] = - *(*sleShares)[sfOutstandingAmount] + *args.sharesTotal; + (*sleShares)[sfOutstandingAmount] = *(*sleShares)[sfOutstandingAmount] + *args.sharesTotal; ac.update(sleShares); } @@ -2207,8 +2014,7 @@ class Invariants_test : public beast::unit_test::suite auto slePseudoAccount = ac.peek(keylet::account(pseudoId)); if (!slePseudoAccount) return false; - (*slePseudoAccount)[sfBalance] = - *(*slePseudoAccount)[sfBalance] + *args.vaultAssets; + (*slePseudoAccount)[sfBalance] = *(*slePseudoAccount)[sfBalance] + *args.vaultAssets; ac.update(slePseudoAccount); } else if (assets.holds()) @@ -2217,8 +2023,7 @@ class Invariants_test : public beast::unit_test::suite auto sleMPToken = ac.peek(keylet::mptoken(mptId, pseudoId)); if (!sleMPToken) return false; - (*sleMPToken)[sfMPTAmount] = - *(*sleMPToken)[sfMPTAmount] + *args.vaultAssets; + (*sleMPToken)[sfMPTAmount] = *(*sleMPToken)[sfMPTAmount] + *args.vaultAssets; ac.update(sleMPToken); } else @@ -2233,19 +2038,16 @@ class Invariants_test : public beast::unit_test::suite auto sleAccount = ac.peek(keylet::account(pair.account)); if (!sleAccount) return false; - (*sleAccount)[sfBalance] = - *(*sleAccount)[sfBalance] + pair.amount; + (*sleAccount)[sfBalance] = *(*sleAccount)[sfBalance] + pair.amount; ac.update(sleAccount); } else if (assets.holds()) { auto const mptID = assets.get().getMptID(); - auto sleMPToken = - ac.peek(keylet::mptoken(mptID, pair.account)); + auto sleMPToken = ac.peek(keylet::mptoken(mptID, pair.account)); if (!sleMPToken) return false; - (*sleMPToken)[sfMPTAmount] = - *(*sleMPToken)[sfMPTAmount] + pair.amount; + (*sleMPToken)[sfMPTAmount] = *(*sleMPToken)[sfMPTAmount] + pair.amount; ac.update(sleMPToken); } else @@ -2255,19 +2057,16 @@ class Invariants_test : public beast::unit_test::suite if (args.accountShares) { auto const& pair = *args.accountShares; - auto sleMPToken = - ac.peek(keylet::mptoken(mptIssuanceID, pair.account)); + auto sleMPToken = ac.peek(keylet::mptoken(mptIssuanceID, pair.account)); if (!sleMPToken) return false; - (*sleMPToken)[sfMPTAmount] = - *(*sleMPToken)[sfMPTAmount] + pair.amount; + (*sleMPToken)[sfMPTAmount] = *(*sleMPToken)[sfMPTAmount] + pair.amount; ac.update(sleMPToken); } return true; }; - constexpr auto args = - [](AccountID id, int adjustment, auto fn) -> Adjustments { + constexpr auto args = [](AccountID id, int adjustment, auto fn) -> Adjustments { Adjustments sample = { .assetsTotal = adjustment, .assetsAvailable = adjustment, @@ -2284,19 +2083,14 @@ class Invariants_test : public beast::unit_test::suite Account A3{"A3"}; Account A4{"A4"}; - auto const precloseXrp = - [&](Account const& A1, Account const& A2, Env& env) -> bool { + auto const precloseXrp = [&](Account const& A1, Account const& A2, Env& env) -> bool { env.fund(XRP(1000), A3, A4); Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); - env(vault.deposit( - {.depositor = A1, .id = keylet.key, .amount = XRP(10)})); - env(vault.deposit( - {.depositor = A2, .id = keylet.key, .amount = XRP(10)})); - env(vault.deposit( - {.depositor = A3, .id = keylet.key, .amount = XRP(10)})); + env(vault.deposit({.depositor = A1, .id = keylet.key, .amount = XRP(10)})); + env(vault.deposit({.depositor = A2, .id = keylet.key, .amount = XRP(10)})); + env(vault.deposit({.depositor = A3, .id = keylet.key, .amount = XRP(10)})); return true; }; @@ -2367,10 +2161,8 @@ class Invariants_test : public beast::unit_test::suite auto const sequence = ac.view().seq(); auto const vaultKeylet = keylet::vault(A1.id(), sequence); auto sleVault = std::make_shared(vaultKeylet); - auto const vaultPage = ac.view().dirInsert( - keylet::ownerDir(A1.id()), - sleVault->key(), - describeOwnerDir(A1.id())); + auto const vaultPage = + ac.view().dirInsert(keylet::ownerDir(A1.id()), sleVault->key(), describeOwnerDir(A1.id())); sleVault->setFieldU64(sfOwnerNode, *vaultPage); ac.view().insert(sleVault); return true; @@ -2424,13 +2216,11 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; { - auto [tx, _] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, _] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); } { - auto [tx, _] = - vault.create({.owner = A2, .asset = xrpIssue()}); + auto [tx, _] = vault.create({.owner = A2, .asset = xrpIssue()}); env(tx); } return true; @@ -2443,10 +2233,8 @@ class Invariants_test : public beast::unit_test::suite auto const insertVault = [&](Account const A) { auto const vaultKeylet = keylet::vault(A.id(), sequence); auto sleVault = std::make_shared(vaultKeylet); - auto const vaultPage = ac.view().dirInsert( - keylet::ownerDir(A.id()), - sleVault->key(), - describeOwnerDir(A.id())); + auto const vaultPage = + ac.view().dirInsert(keylet::ownerDir(A.id()), sleVault->key(), describeOwnerDir(A.id())); sleVault->setFieldU64(sfOwnerNode, *vaultPage); ac.view().insert(sleVault); }; @@ -2487,8 +2275,7 @@ class Invariants_test : public beast::unit_test::suite auto sleVault = ac.view().peek(keylet); if (!sleVault) return false; - auto sleShares = ac.view().peek( - keylet::mptIssuance((*sleVault)[sfShareMPTID])); + auto sleShares = ac.view().peek(keylet::mptIssuance((*sleVault)[sfShareMPTID])); if (!sleShares) return false; ac.view().erase(sleVault); @@ -2500,11 +2287,9 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tefINVARIANT_FAILED}, [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); - env(vault.deposit( - {.depositor = A1, .id = keylet.key, .amount = XRP(10)})); + env(vault.deposit({.depositor = A1, .id = keylet.key, .amount = XRP(10)})); return true; }); @@ -2515,8 +2300,7 @@ class Invariants_test : public beast::unit_test::suite auto sleVault = ac.view().peek(keylet); if (!sleVault) return false; - auto sleShares = ac.view().peek( - keylet::mptIssuance((*sleVault)[sfShareMPTID])); + auto sleShares = ac.view().peek(keylet::mptIssuance((*sleVault)[sfShareMPTID])); if (!sleShares) return false; // Note, such an "orphaned" update of MPT issuance attached to a @@ -2533,9 +2317,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {"vault operation succeeded without modifying a vault"}, - [&](Account const& A1, Account const& A2, ApplyContext& ac) { - return true; - }, + [&](Account const& A1, Account const& A2, ApplyContext& ac) { return true; }, XRPAmount{}, STTx{ttVAULT_CREATE, [](STObject&) {}}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, @@ -2548,9 +2330,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {"vault operation succeeded without modifying a vault"}, - [&](Account const& A1, Account const& A2, ApplyContext& ac) { - return true; - }, + [&](Account const& A1, Account const& A2, ApplyContext& ac) { return true; }, XRPAmount{}, STTx{ttVAULT_DEPOSIT, [](STObject&) {}}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, @@ -2563,9 +2343,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {"vault operation succeeded without modifying a vault"}, - [&](Account const& A1, Account const& A2, ApplyContext& ac) { - return true; - }, + [&](Account const& A1, Account const& A2, ApplyContext& ac) { return true; }, XRPAmount{}, STTx{ttVAULT_WITHDRAW, [](STObject&) {}}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, @@ -2578,9 +2356,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {"vault operation succeeded without modifying a vault"}, - [&](Account const& A1, Account const& A2, ApplyContext& ac) { - return true; - }, + [&](Account const& A1, Account const& A2, ApplyContext& ac) { return true; }, XRPAmount{}, STTx{ttVAULT_CLAWBACK, [](STObject&) {}}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, @@ -2593,9 +2369,7 @@ class Invariants_test : public beast::unit_test::suite doInvariantCheck( {"vault operation succeeded without modifying a vault"}, - [&](Account const& A1, Account const& A2, ApplyContext& ac) { - return true; - }, + [&](Account const& A1, Account const& A2, ApplyContext& ac) { return true; }, XRPAmount{}, STTx{ttVAULT_DELETE, [](STObject&) {}}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, @@ -2616,8 +2390,7 @@ class Invariants_test : public beast::unit_test::suite (*sleVault)[sfAssetsMaximum] = 200; ac.view().update(sleVault); - auto sleShares = ac.view().peek( - keylet::mptIssuance((*sleVault)[sfShareMPTID])); + auto sleShares = ac.view().peek(keylet::mptIssuance((*sleVault)[sfShareMPTID])); if (!sleShares) return false; ac.view().erase(sleShares); @@ -2650,11 +2423,9 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); - env(vault.deposit( - {.depositor = A1, .id = keylet.key, .amount = XRP(10)})); + env(vault.deposit({.depositor = A1, .id = keylet.key, .amount = XRP(10)})); return true; }); @@ -2671,12 +2442,10 @@ class Invariants_test : public beast::unit_test::suite auto sleVault = ac.view().peek(keylet); if (!sleVault) return false; - auto slePseudoAccount = - ac.view().peek(keylet::account(*(*sleVault)[sfAccount])); + auto slePseudoAccount = ac.view().peek(keylet::account(*(*sleVault)[sfAccount])); if (!slePseudoAccount) return false; - (*slePseudoAccount)[sfBalance] = - *(*slePseudoAccount)[sfBalance] - 10; + (*slePseudoAccount)[sfBalance] = *(*slePseudoAccount)[sfBalance] - 10; ac.view().update(slePseudoAccount); // Move 10 drops to A4 to enforce total XRP balance @@ -2686,14 +2455,11 @@ class Invariants_test : public beast::unit_test::suite (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10; ac.view().update(sleA4); - return adjust( - ac.view(), - keylet, - args(A2.id(), 0, [&](Adjustments& sample) { - sample.assetsAvailable = (DROPS_PER_XRP * -100).value(); - sample.assetsTotal = (DROPS_PER_XRP * -200).value(); - sample.sharesTotal = -1; - })); + return adjust(ac.view(), keylet, args(A2.id(), 0, [&](Adjustments& sample) { + sample.assetsAvailable = (DROPS_PER_XRP * -100).value(); + sample.assetsTotal = (DROPS_PER_XRP * -200).value(); + sample.sharesTotal = -1; + })); }, XRPAmount{}, STTx{ttVAULT_SET, [](STObject& tx) {}}, @@ -2708,8 +2474,7 @@ class Invariants_test : public beast::unit_test::suite auto sleVault = ac.view().peek(keylet); if (!sleVault) return false; - sleVault->setFieldIssue( - sfAsset, STIssue{sfAsset, MPTIssue(MPTID(42))}); + sleVault->setFieldIssue(sfAsset, STIssue{sfAsset, MPTIssue(MPTID(42))}); ac.view().update(sleVault); return true; }, @@ -2751,17 +2516,13 @@ class Invariants_test : public beast::unit_test::suite precloseXrp); doInvariantCheck( - {"vault transaction must not change loss unrealized", - "set must not change assets outstanding"}, + {"vault transaction must not change loss unrealized", "set must not change assets outstanding"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); - return adjust( - ac.view(), - keylet, - args(A2.id(), 0, [&](Adjustments& sample) { - sample.lossUnrealized = 13; - sample.assetsTotal = 20; - })); + return adjust(ac.view(), keylet, args(A2.id(), 0, [&](Adjustments& sample) { + sample.lossUnrealized = 13; + sample.assetsTotal = 20; + })); }, XRPAmount{}, STTx{ttVAULT_SET, [](STObject& tx) {}}, @@ -2776,18 +2537,10 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 100, [&](Adjustments& sample) { - sample.lossUnrealized = 13; - })); + ac.view(), keylet, args(A2.id(), 100, [&](Adjustments& sample) { sample.lossUnrealized = 13; })); }, XRPAmount{}, - STTx{ - ttVAULT_DEPOSIT, - [](STObject& tx) { - tx.setFieldAmount(sfAmount, XRPAmount(200)); - }}, + STTx{ttVAULT_DEPOSIT, [](STObject& tx) { tx.setFieldAmount(sfAmount, XRPAmount(200)); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -2797,11 +2550,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 0, [&](Adjustments& sample) { - sample.assetsMaximum = 1; - })); + ac.view(), keylet, args(A2.id(), 0, [&](Adjustments& sample) { sample.assetsMaximum = 1; })); }, XRPAmount{}, STTx{ttVAULT_SET, [](STObject& tx) {}}, @@ -2814,11 +2563,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 0, [&](Adjustments& sample) { - sample.assetsMaximum = -1; - })); + ac.view(), keylet, args(A2.id(), 0, [&](Adjustments& sample) { sample.assetsMaximum = -1; })); }, XRPAmount{}, STTx{ttVAULT_SET, [](STObject& tx) {}}, @@ -2836,8 +2581,7 @@ class Invariants_test : public beast::unit_test::suite if (!sleVault) return false; ac.view().update(sleVault); - auto sleShares = ac.view().peek( - keylet::mptIssuance((*sleVault)[sfShareMPTID])); + auto sleShares = ac.view().peek(keylet::mptIssuance((*sleVault)[sfShareMPTID])); if (!sleShares) return false; (*sleShares)[sfOutstandingAmount] = 0; @@ -2857,15 +2601,13 @@ class Invariants_test : public beast::unit_test::suite auto sleVault = ac.view().peek(keylet); if (!sleVault) return false; - auto sleShares = ac.view().peek( - keylet::mptIssuance((*sleVault)[sfShareMPTID])); + auto sleShares = ac.view().peek(keylet::mptIssuance((*sleVault)[sfShareMPTID])); if (!sleShares) return false; (*sleShares)[sfMaximumAmount] = 10; ac.view().update(sleShares); - return adjust( - ac.view(), keylet, args(A2.id(), 10, [](Adjustments&) {})); + return adjust(ac.view(), keylet, args(A2.id(), 10, [](Adjustments&) {})); }, XRPAmount{}, STTx{ttVAULT_DEPOSIT, [](STObject&) {}}, @@ -2877,14 +2619,12 @@ class Invariants_test : public beast::unit_test::suite {"updated shares must not exceed maximum"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); - adjust( - ac.view(), keylet, args(A2.id(), 10, [](Adjustments&) {})); + adjust(ac.view(), keylet, args(A2.id(), 10, [](Adjustments&) {})); auto sleVault = ac.view().peek(keylet); if (!sleVault) return false; - auto sleShares = ac.view().peek( - keylet::mptIssuance((*sleVault)[sfShareMPTID])); + auto sleShares = ac.view().peek(keylet::mptIssuance((*sleVault)[sfShareMPTID])); if (!sleShares) return false; (*sleShares)[sfOutstandingAmount] = maxMPTokenAmount + 1; @@ -2918,8 +2658,7 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); return true; }); @@ -2945,8 +2684,7 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); return true; }); @@ -2973,8 +2711,7 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); return true; }); @@ -2989,8 +2726,7 @@ class Invariants_test : public beast::unit_test::suite auto sleVault = ac.view().peek(keylet); if (!sleVault) return false; - auto sleShares = ac.view().peek( - keylet::mptIssuance((*sleVault)[sfShareMPTID])); + auto sleShares = ac.view().peek(keylet::mptIssuance((*sleVault)[sfShareMPTID])); if (!sleShares) return false; ac.view().update(sleVault); @@ -3003,8 +2739,7 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); return true; }); @@ -3028,8 +2763,7 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); return true; }); @@ -3044,8 +2778,7 @@ class Invariants_test : public beast::unit_test::suite auto sleVault = ac.view().peek(keylet); if (!sleVault) return false; - auto sleShares = ac.view().peek( - keylet::mptIssuance((*sleVault)[sfShareMPTID])); + auto sleShares = ac.view().peek(keylet::mptIssuance((*sleVault)[sfShareMPTID])); if (!sleShares) return false; ac.view().update(sleVault); @@ -3058,15 +2791,13 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, [&](Account const& A1, Account const& A2, Env& env) { Vault vault{env}; - auto [tx, keylet] = - vault.create({.owner = A1, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = A1, .asset = xrpIssue()}); env(tx); return true; }); doInvariantCheck( - {"vault created by a wrong transaction type", - "account root created illegally"}, + {"vault created by a wrong transaction type", "account root created illegally"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { // The code below will create a valid vault with (almost) all // the invariants holding. Except one: it is created by the @@ -3074,17 +2805,13 @@ class Invariants_test : public beast::unit_test::suite auto const sequence = ac.view().seq(); auto const vaultKeylet = keylet::vault(A1.id(), sequence); auto sleVault = std::make_shared(vaultKeylet); - auto const vaultPage = ac.view().dirInsert( - keylet::ownerDir(A1.id()), - sleVault->key(), - describeOwnerDir(A1.id())); + auto const vaultPage = + ac.view().dirInsert(keylet::ownerDir(A1.id()), sleVault->key(), describeOwnerDir(A1.id())); sleVault->setFieldU64(sfOwnerNode, *vaultPage); - auto pseudoId = - pseudoAccountAddress(ac.view(), vaultKeylet.key); + auto pseudoId = pseudoAccountAddress(ac.view(), vaultKeylet.key); // Create pseudo-account. - auto sleAccount = - std::make_shared(keylet::account(pseudoId)); + auto sleAccount = std::make_shared(keylet::account(pseudoId)); sleAccount->setAccountID(sfAccount, pseudoId); sleAccount->setFieldAmount(sfBalance, STAmount{}); std::uint32_t const seqno = // @@ -3092,19 +2819,15 @@ class Invariants_test : public beast::unit_test::suite ? 0 // : sequence; sleAccount->setFieldU32(sfSequence, seqno); - sleAccount->setFieldU32( - sfFlags, - lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth); + sleAccount->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth); sleAccount->setFieldH256(sfVaultID, vaultKeylet.key); ac.view().insert(sleAccount); auto const sharesMptId = makeMptID(sequence, pseudoId); auto const sharesKeylet = keylet::mptIssuance(sharesMptId); auto sleShares = std::make_shared(sharesKeylet); - auto const sharesPage = ac.view().dirInsert( - keylet::ownerDir(pseudoId), - sharesKeylet, - describeOwnerDir(pseudoId)); + auto const sharesPage = + ac.view().dirInsert(keylet::ownerDir(pseudoId), sharesKeylet, describeOwnerDir(pseudoId)); sleShares->setFieldU64(sfOwnerNode, *sharesPage); sleShares->at(sfFlags) = 0; @@ -3120,8 +2843,7 @@ class Invariants_test : public beast::unit_test::suite sleVault->at(sfAssetsAvailable) = Number(0); sleVault->at(sfLossUnrealized) = Number(0); sleVault->at(sfShareMPTID) = sharesMptId; - sleVault->at(sfWithdrawalPolicy) = - vaultStrategyFirstComeFirstServe; + sleVault->at(sfWithdrawalPolicy) = vaultStrategyFirstComeFirstServe; ac.view().insert(sleVault); ac.view().insert(sleShares); @@ -3138,17 +2860,13 @@ class Invariants_test : public beast::unit_test::suite auto const sequence = ac.view().seq(); auto const vaultKeylet = keylet::vault(A1.id(), sequence); auto sleVault = std::make_shared(vaultKeylet); - auto const vaultPage = ac.view().dirInsert( - keylet::ownerDir(A1.id()), - sleVault->key(), - describeOwnerDir(A1.id())); + auto const vaultPage = + ac.view().dirInsert(keylet::ownerDir(A1.id()), sleVault->key(), describeOwnerDir(A1.id())); sleVault->setFieldU64(sfOwnerNode, *vaultPage); - auto pseudoId = - pseudoAccountAddress(ac.view(), vaultKeylet.key); + auto pseudoId = pseudoAccountAddress(ac.view(), vaultKeylet.key); // Create pseudo-account. - auto sleAccount = - std::make_shared(keylet::account(pseudoId)); + auto sleAccount = std::make_shared(keylet::account(pseudoId)); sleAccount->setAccountID(sfAccount, pseudoId); sleAccount->setFieldAmount(sfBalance, STAmount{}); std::uint32_t const seqno = // @@ -3156,9 +2874,7 @@ class Invariants_test : public beast::unit_test::suite ? 0 // : sequence; sleAccount->setFieldU32(sfSequence, seqno); - sleAccount->setFieldU32( - sfFlags, - lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth); + sleAccount->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth); // sleAccount->setFieldH256(sfVaultID, vaultKeylet.key); // Setting wrong vault key sleAccount->setFieldH256(sfVaultID, uint256(42)); @@ -3167,10 +2883,8 @@ class Invariants_test : public beast::unit_test::suite auto const sharesMptId = makeMptID(sequence, pseudoId); auto const sharesKeylet = keylet::mptIssuance(sharesMptId); auto sleShares = std::make_shared(sharesKeylet); - auto const sharesPage = ac.view().dirInsert( - keylet::ownerDir(pseudoId), - sharesKeylet, - describeOwnerDir(pseudoId)); + auto const sharesPage = + ac.view().dirInsert(keylet::ownerDir(pseudoId), sharesKeylet, describeOwnerDir(pseudoId)); sleShares->setFieldU64(sfOwnerNode, *sharesPage); sleShares->at(sfFlags) = 0; @@ -3188,8 +2902,7 @@ class Invariants_test : public beast::unit_test::suite sleVault->at(sfAssetsAvailable) = Number(0); sleVault->at(sfLossUnrealized) = Number(0); sleVault->at(sfShareMPTID) = sharesMptId; - sleVault->at(sfWithdrawalPolicy) = - vaultStrategyFirstComeFirstServe; + sleVault->at(sfWithdrawalPolicy) = vaultStrategyFirstComeFirstServe; ac.view().insert(sleVault); ac.view().insert(sleShares); @@ -3200,25 +2913,20 @@ class Invariants_test : public beast::unit_test::suite {tecINVARIANT_FAILED, tefINVARIANT_FAILED}); doInvariantCheck( - {"shares issuer and vault pseudo-account must be the same", - "shares issuer must exist"}, + {"shares issuer and vault pseudo-account must be the same", "shares issuer must exist"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const sequence = ac.view().seq(); auto const vaultKeylet = keylet::vault(A1.id(), sequence); auto sleVault = std::make_shared(vaultKeylet); - auto const vaultPage = ac.view().dirInsert( - keylet::ownerDir(A1.id()), - sleVault->key(), - describeOwnerDir(A1.id())); + auto const vaultPage = + ac.view().dirInsert(keylet::ownerDir(A1.id()), sleVault->key(), describeOwnerDir(A1.id())); sleVault->setFieldU64(sfOwnerNode, *vaultPage); auto const sharesMptId = makeMptID(sequence, A2.id()); auto const sharesKeylet = keylet::mptIssuance(sharesMptId); auto sleShares = std::make_shared(sharesKeylet); - auto const sharesPage = ac.view().dirInsert( - keylet::ownerDir(A2.id()), - sharesKeylet, - describeOwnerDir(A2.id())); + auto const sharesPage = + ac.view().dirInsert(keylet::ownerDir(A2.id()), sharesKeylet, describeOwnerDir(A2.id())); sleShares->setFieldU64(sfOwnerNode, *sharesPage); sleShares->at(sfFlags) = 0; @@ -3235,8 +2943,7 @@ class Invariants_test : public beast::unit_test::suite sleVault->at(sfAssetsAvailable) = Number(0); sleVault->at(sfLossUnrealized) = Number(0); sleVault->at(sfShareMPTID) = sharesMptId; - sleVault->at(sfWithdrawalPolicy) = - vaultStrategyFirstComeFirstServe; + sleVault->at(sfWithdrawalPolicy) = vaultStrategyFirstComeFirstServe; ac.view().insert(sleVault); ac.view().insert(sleShares); @@ -3252,11 +2959,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 0, [](Adjustments& sample) { - sample.vaultAssets.reset(); - })); + ac.view(), keylet, args(A2.id(), 0, [](Adjustments& sample) { sample.vaultAssets.reset(); })); }, XRPAmount{}, STTx{ttVAULT_DEPOSIT, [](STObject&) {}}, @@ -3268,18 +2971,10 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 200, [&](Adjustments& sample) { - sample.assetsMaximum = 1; - })); + ac.view(), keylet, args(A2.id(), 200, [&](Adjustments& sample) { sample.assetsMaximum = 1; })); }, XRPAmount{}, - STTx{ - ttVAULT_DEPOSIT, - [](STObject& tx) { - tx.setFieldAmount(sfAmount, XRPAmount(200)); - }}, + STTx{ttVAULT_DEPOSIT, [](STObject& tx) { tx.setFieldAmount(sfAmount, XRPAmount(200)); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -3289,8 +2984,7 @@ class Invariants_test : public beast::unit_test::suite // The operation makes no sense, but the defensive check in // ValidVault::finalize is otherwise impossible to trigger. doInvariantCheck( - {"deposit must increase vault balance", - "deposit must change depositor balance"}, + {"deposit must increase vault balance", "deposit must change depositor balance"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); @@ -3301,12 +2995,9 @@ class Invariants_test : public beast::unit_test::suite (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10; ac.view().update(sleA4); - return adjust( - ac.view(), - keylet, - args(A3.id(), -10, [&](Adjustments& sample) { - sample.accountAssets->amount = -100; - })); + return adjust(ac.view(), keylet, args(A3.id(), -10, [&](Adjustments& sample) { + sample.accountAssets->amount = -100; + })); }, XRPAmount{100}, STTx{ @@ -3334,18 +3025,13 @@ class Invariants_test : public beast::unit_test::suite (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] + 10; ac.view().update(sleA3); - return adjust( - ac.view(), - keylet, - args(A2.id(), 10, [&](Adjustments& sample) { - sample.vaultAssets = -20; - sample.accountAssets->amount = 10; - })); + return adjust(ac.view(), keylet, args(A2.id(), 10, [&](Adjustments& sample) { + sample.vaultAssets = -20; + sample.accountAssets->amount = 10; + })); }, XRPAmount{}, - STTx{ - ttVAULT_DEPOSIT, - [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, + STTx{ttVAULT_DEPOSIT, [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -3362,17 +3048,12 @@ class Invariants_test : public beast::unit_test::suite (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] - 10; ac.view().update(sleA3); - return adjust( - ac.view(), - keylet, - args(A2.id(), 10, [&](Adjustments& sample) { - sample.accountAssets->amount = 0; - })); + return adjust(ac.view(), keylet, args(A2.id(), 10, [&](Adjustments& sample) { + sample.accountAssets->amount = 0; + })); }, XRPAmount{}, - STTx{ - ttVAULT_DEPOSIT, - [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, + STTx{ttVAULT_DEPOSIT, [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -3382,16 +3063,10 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 10, [&](Adjustments& sample) { - sample.accountShares.reset(); - })); + ac.view(), keylet, args(A2.id(), 10, [&](Adjustments& sample) { sample.accountShares.reset(); })); }, XRPAmount{}, - STTx{ - ttVAULT_DEPOSIT, - [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, + STTx{ttVAULT_DEPOSIT, [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -3402,16 +3077,10 @@ class Invariants_test : public beast::unit_test::suite auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 10, [](Adjustments& sample) { - sample.sharesTotal = 0; - })); + ac.view(), keylet, args(A2.id(), 10, [](Adjustments& sample) { sample.sharesTotal = 0; })); }, XRPAmount{}, - STTx{ - ttVAULT_DEPOSIT, - [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, + STTx{ttVAULT_DEPOSIT, [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -3423,18 +3092,13 @@ class Invariants_test : public beast::unit_test::suite "amount"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); - return adjust( - ac.view(), - keylet, - args(A2.id(), 10, [&](Adjustments& sample) { - sample.accountShares->amount = -5; - sample.sharesTotal = -10; - })); + return adjust(ac.view(), keylet, args(A2.id(), 10, [&](Adjustments& sample) { + sample.accountShares->amount = -5; + sample.sharesTotal = -10; + })); }, XRPAmount{}, - STTx{ - ttVAULT_DEPOSIT, - [](STObject& tx) { tx[sfAmount] = XRPAmount(5); }}, + STTx{ttVAULT_DEPOSIT, [](STObject& tx) { tx[sfAmount] = XRPAmount(5); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -3448,11 +3112,7 @@ class Invariants_test : public beast::unit_test::suite auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 10, [&](Adjustments& sample) { - sample.assetsTotal = 11; - })); + ac.view(), keylet, args(A2.id(), 10, [&](Adjustments& sample) { sample.assetsTotal = 11; })); }, XRPAmount{2000}, STTx{ @@ -3467,22 +3127,16 @@ class Invariants_test : public beast::unit_test::suite TxAccount::A2); doInvariantCheck( - {"deposit and assets outstanding must add up", - "deposit and assets available must add up"}, + {"deposit and assets outstanding must add up", "deposit and assets available must add up"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); - return adjust( - ac.view(), - keylet, - args(A2.id(), 10, [&](Adjustments& sample) { - sample.assetsTotal = 7; - sample.assetsAvailable = 7; - })); + return adjust(ac.view(), keylet, args(A2.id(), 10, [&](Adjustments& sample) { + sample.assetsTotal = 7; + sample.assetsAvailable = 7; + })); }, XRPAmount{}, - STTx{ - ttVAULT_DEPOSIT, - [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, + STTx{ttVAULT_DEPOSIT, [](STObject& tx) { tx[sfAmount] = XRPAmount(10); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -3493,11 +3147,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), 0, [](Adjustments& sample) { - sample.vaultAssets.reset(); - })); + ac.view(), keylet, args(A2.id(), 0, [](Adjustments& sample) { sample.vaultAssets.reset(); })); }, XRPAmount{}, STTx{ttVAULT_WITHDRAW, [](STObject&) {}}, @@ -3520,12 +3170,9 @@ class Invariants_test : public beast::unit_test::suite (*sleA4)[sfBalance] = *(*sleA4)[sfBalance] + 10; ac.view().update(sleA4); - return adjust( - ac.view(), - keylet, - args(A3.id(), -10, [&](Adjustments& sample) { - sample.accountAssets->amount = -100; - })); + return adjust(ac.view(), keylet, args(A3.id(), -10, [&](Adjustments& sample) { + sample.accountAssets->amount = -100; + })); }, XRPAmount{100}, STTx{ @@ -3556,13 +3203,10 @@ class Invariants_test : public beast::unit_test::suite (*sleA3)[sfBalance] = *(*sleA3)[sfBalance] + 10; ac.view().update(sleA3); - return adjust( - ac.view(), - keylet, - args(A2.id(), -10, [&](Adjustments& sample) { - sample.vaultAssets = 10; - sample.accountAssets->amount = -20; - })); + return adjust(ac.view(), keylet, args(A2.id(), -10, [&](Adjustments& sample) { + sample.vaultAssets = 10; + sample.accountAssets->amount = -20; + })); }, XRPAmount{}, STTx{ttVAULT_WITHDRAW, [](STObject&) {}}, @@ -3575,11 +3219,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); if (!adjust( - ac.view(), - keylet, - args(A2.id(), -10, [&](Adjustments& sample) { - *sample.vaultAssets -= 5; - }))) + ac.view(), keylet, args(A2.id(), -10, [&](Adjustments& sample) { *sample.vaultAssets -= 5; }))) return false; auto sleA3 = ac.view().peek(keylet::account(A3.id())); if (!sleA3) @@ -3589,9 +3229,7 @@ class Invariants_test : public beast::unit_test::suite return true; }, XRPAmount{}, - STTx{ - ttVAULT_WITHDRAW, - [&](STObject& tx) { tx.setAccountID(sfDestination, A3.id()); }}, + STTx{ttVAULT_WITHDRAW, [&](STObject& tx) { tx.setAccountID(sfDestination, A3.id()); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseXrp, TxAccount::A2); @@ -3601,11 +3239,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), -10, [&](Adjustments& sample) { - sample.accountShares.reset(); - })); + ac.view(), keylet, args(A2.id(), -10, [&](Adjustments& sample) { sample.accountShares.reset(); })); }, XRPAmount{}, STTx{ttVAULT_WITHDRAW, [](STObject&) {}}, @@ -3618,11 +3252,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), -10, [](Adjustments& sample) { - sample.sharesTotal = 0; - })); + ac.view(), keylet, args(A2.id(), -10, [](Adjustments& sample) { sample.sharesTotal = 0; })); }, XRPAmount{}, STTx{ttVAULT_WITHDRAW, [](STObject&) {}}, @@ -3636,13 +3266,10 @@ class Invariants_test : public beast::unit_test::suite "amount"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); - return adjust( - ac.view(), - keylet, - args(A2.id(), -10, [&](Adjustments& sample) { - sample.accountShares->amount = 5; - sample.sharesTotal = 10; - })); + return adjust(ac.view(), keylet, args(A2.id(), -10, [&](Adjustments& sample) { + sample.accountShares->amount = 5; + sample.sharesTotal = 10; + })); }, XRPAmount{}, STTx{ttVAULT_WITHDRAW, [](STObject&) {}}, @@ -3651,17 +3278,13 @@ class Invariants_test : public beast::unit_test::suite TxAccount::A2); doInvariantCheck( - {"withdrawal and assets outstanding must add up", - "withdrawal and assets available must add up"}, + {"withdrawal and assets outstanding must add up", "withdrawal and assets available must add up"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); - return adjust( - ac.view(), - keylet, - args(A2.id(), -10, [&](Adjustments& sample) { - sample.assetsTotal = -15; - sample.assetsAvailable = -15; - })); + return adjust(ac.view(), keylet, args(A2.id(), -10, [&](Adjustments& sample) { + sample.assetsTotal = -15; + sample.assetsAvailable = -15; + })); }, XRPAmount{}, STTx{ttVAULT_WITHDRAW, [](STObject&) {}}, @@ -3678,11 +3301,7 @@ class Invariants_test : public beast::unit_test::suite auto const keylet = keylet::vault(A1.id(), ac.view().seq()); return adjust( - ac.view(), - keylet, - args(A2.id(), -10, [&](Adjustments& sample) { - sample.assetsTotal = -7; - })); + ac.view(), keylet, args(A2.id(), -10, [&](Adjustments& sample) { sample.assetsTotal = -7; })); }, XRPAmount{2000}, STTx{ @@ -3696,8 +3315,7 @@ class Invariants_test : public beast::unit_test::suite precloseXrp, TxAccount::A2); - auto const precloseMpt = - [&](Account const& A1, Account const& A2, Env& env) -> bool { + auto const precloseMpt = [&](Account const& A1, Account const& A2, Env& env) -> bool { env.fund(XRP(1000), A3, A4); // Create MPT asset @@ -3737,12 +3355,9 @@ class Invariants_test : public beast::unit_test::suite Vault vault{env}; auto [tx, keylet] = vault.create({.owner = A1, .asset = asset}); env(tx); - env(vault.deposit( - {.depositor = A1, .id = keylet.key, .amount = asset(10)})); - env(vault.deposit( - {.depositor = A2, .id = keylet.key, .amount = asset(10)})); - env(vault.deposit( - {.depositor = A4, .id = keylet.key, .amount = asset(10)})); + env(vault.deposit({.depositor = A1, .id = keylet.key, .amount = asset(10)})); + env(vault.deposit({.depositor = A2, .id = keylet.key, .amount = asset(10)})); + env(vault.deposit({.depositor = A4, .id = keylet.key, .amount = asset(10)})); return true; }; @@ -3752,17 +3367,12 @@ class Invariants_test : public beast::unit_test::suite "amount"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq() - 2); - return adjust( - ac.view(), - keylet, - args(A2.id(), -10, [&](Adjustments& sample) { - sample.accountShares->amount = 5; - })); + return adjust(ac.view(), keylet, args(A2.id(), -10, [&](Adjustments& sample) { + sample.accountShares->amount = 5; + })); }, XRPAmount{}, - STTx{ - ttVAULT_WITHDRAW, - [&](STObject& tx) { tx[sfAccount] = A3.id(); }}, + STTx{ttVAULT_WITHDRAW, [&](STObject& tx) { tx[sfAccount] = A3.id(); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseMpt, TxAccount::A2); @@ -3773,16 +3383,10 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq() - 2); return adjust( - ac.view(), - keylet, - args(A2.id(), -1, [&](Adjustments& sample) { - sample.vaultAssets.reset(); - })); + ac.view(), keylet, args(A2.id(), -1, [&](Adjustments& sample) { sample.vaultAssets.reset(); })); }, XRPAmount{}, - STTx{ - ttVAULT_CLAWBACK, - [&](STObject& tx) { tx[sfAccount] = A3.id(); }}, + STTx{ttVAULT_CLAWBACK, [&](STObject& tx) { tx[sfAccount] = A3.id(); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseMpt); @@ -3791,10 +3395,7 @@ class Invariants_test : public beast::unit_test::suite {"clawback may only be performed by the asset issuer"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq()); - return adjust( - ac.view(), - keylet, - args(A2.id(), 0, [&](Adjustments& sample) {})); + return adjust(ac.view(), keylet, args(A2.id(), 0, [&](Adjustments& sample) {})); }, XRPAmount{}, STTx{ttVAULT_CLAWBACK, [](STObject&) {}}, @@ -3806,15 +3407,10 @@ class Invariants_test : public beast::unit_test::suite {"clawback may only be performed by the asset issuer"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq() - 2); - return adjust( - ac.view(), - keylet, - args(A2.id(), 0, [&](Adjustments& sample) {})); + return adjust(ac.view(), keylet, args(A2.id(), 0, [&](Adjustments& sample) {})); }, XRPAmount{}, - STTx{ - ttVAULT_CLAWBACK, - [&](STObject& tx) { tx[sfAccount] = A4.id(); }}, + STTx{ttVAULT_CLAWBACK, [&](STObject& tx) { tx[sfAccount] = A4.id(); }}, {tecINVARIANT_FAILED, tecINVARIANT_FAILED}, precloseMpt); @@ -3825,11 +3421,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq() - 2); return adjust( - ac.view(), - keylet, - args(A4.id(), 10, [&](Adjustments& sample) { - sample.sharesTotal = 0; - })); + ac.view(), keylet, args(A4.id(), 10, [&](Adjustments& sample) { sample.sharesTotal = 0; })); }, XRPAmount{}, STTx{ @@ -3846,11 +3438,7 @@ class Invariants_test : public beast::unit_test::suite [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq() - 2); return adjust( - ac.view(), - keylet, - args(A4.id(), -10, [&](Adjustments& sample) { - sample.accountShares.reset(); - })); + ac.view(), keylet, args(A4.id(), -10, [&](Adjustments& sample) { sample.accountShares.reset(); })); }, XRPAmount{}, STTx{ @@ -3868,14 +3456,11 @@ class Invariants_test : public beast::unit_test::suite "clawback and assets available must add up"}, [&](Account const& A1, Account const& A2, ApplyContext& ac) { auto const keylet = keylet::vault(A1.id(), ac.view().seq() - 2); - return adjust( - ac.view(), - keylet, - args(A4.id(), -10, [&](Adjustments& sample) { - sample.accountShares->amount = -8; - sample.assetsTotal = -7; - sample.assetsAvailable = -7; - })); + return adjust(ac.view(), keylet, args(A4.id(), -10, [&](Adjustments& sample) { + sample.accountShares->amount = -8; + sample.assetsTotal = -7; + sample.assetsAvailable = -7; + })); }, XRPAmount{}, STTx{ diff --git a/src/test/app/LPTokenTransfer_test.cpp b/src/test/app/LPTokenTransfer_test.cpp index b2a6f39ddf..f9cfc4d5ce 100644 --- a/src/test/app/LPTokenTransfer_test.cpp +++ b/src/test/app/LPTokenTransfer_test.cpp @@ -18,18 +18,15 @@ class LPTokenTransfer_test : public jtx::AMMTest env.close(); AMM ammAlice(env, alice, USD(20'000), BTC(0.5)); - BEAST_EXPECT( - ammAlice.expectBalances(USD(20'000), BTC(0.5), IOUAmount{100, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(20'000), BTC(0.5), IOUAmount{100, 0})); fund(env, gw, {carol}, {USD(4'000), BTC(1)}, Fund::Acct); ammAlice.deposit(carol, 10); - BEAST_EXPECT( - ammAlice.expectBalances(USD(22'000), BTC(0.55), IOUAmount{110, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(22'000), BTC(0.55), IOUAmount{110, 0})); fund(env, gw, {bob}, {USD(4'000), BTC(1)}, Fund::Acct); ammAlice.deposit(bob, 10); - BEAST_EXPECT( - ammAlice.expectBalances(USD(24'000), BTC(0.60), IOUAmount{120, 0})); + BEAST_EXPECT(ammAlice.expectBalances(USD(24'000), BTC(0.60), IOUAmount{120, 0})); auto const lpIssue = ammAlice.lptIssue(); env.trust(STAmount{lpIssue, 500}, alice); @@ -49,8 +46,7 @@ class LPTokenTransfer_test : public jtx::AMMTest env.close(); // cannot transfer to an amm account - env(pay(carol, lpIssue.getIssuer(), STAmount{lpIssue, 5}), - ter(tecNO_PERMISSION)); + env(pay(carol, lpIssue.getIssuer(), STAmount{lpIssue, 5}), ter(tecNO_PERMISSION)); env.close(); if (features[fixFrozenLPTokenTransfer]) @@ -73,12 +69,7 @@ class LPTokenTransfer_test : public jtx::AMMTest using namespace jtx; Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - {USD(10'000), EUR(10'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(10'000), EUR(10'000)}, Fund::All); AMM ammAlice(env, alice, USD(10'000), EUR(10'000)); ammAlice.deposit(carol, 1'000); ammAlice.deposit(bob, 1'000); @@ -106,10 +97,7 @@ class LPTokenTransfer_test : public jtx::AMMTest { // with fixFrozenLPTokenTransfer, alice fails to consume carol's // offer since carol's USD is frozen - env(pay(alice, bob, STAmount{lpIssue, 10}), - txflags(tfPartialPayment), - sendmax(XRP(10)), - ter(tecPATH_DRY)); + env(pay(alice, bob, STAmount{lpIssue, 10}), txflags(tfPartialPayment), sendmax(XRP(10)), ter(tecPATH_DRY)); env.close(); BEAST_EXPECT(expectOffers(env, carol, 1)); @@ -118,9 +106,7 @@ class LPTokenTransfer_test : public jtx::AMMTest env.close(); // alice successfully consumes carol's offer - env(pay(alice, bob, STAmount{lpIssue, 10}), - txflags(tfPartialPayment), - sendmax(XRP(10))); + env(pay(alice, bob, STAmount{lpIssue, 10}), txflags(tfPartialPayment), sendmax(XRP(10))); env.close(); BEAST_EXPECT(expectOffers(env, carol, 0)); } @@ -128,9 +114,7 @@ class LPTokenTransfer_test : public jtx::AMMTest { // without fixFrozenLPTokenTransfer, alice can consume carol's offer // even when carol's USD is frozen - env(pay(alice, bob, STAmount{lpIssue, 10}), - txflags(tfPartialPayment), - sendmax(XRP(10))); + env(pay(alice, bob, STAmount{lpIssue, 10}), txflags(tfPartialPayment), sendmax(XRP(10))); env.close(); BEAST_EXPECT(expectOffers(env, carol, 0)); } @@ -143,8 +127,7 @@ class LPTokenTransfer_test : public jtx::AMMTest // even when carol's USD is frozen { // carol creates an offer to buy lptoken - env(offer(carol, STAmount{lpIssue, 10}, XRP(10)), - txflags(tfPassive)); + env(offer(carol, STAmount{lpIssue, 10}, XRP(10)), txflags(tfPassive)); env.close(); BEAST_EXPECT(expectOffers(env, carol, 1)); @@ -153,9 +136,7 @@ class LPTokenTransfer_test : public jtx::AMMTest env.close(); // alice successfully consumes carol's offer - env(pay(alice, bob, XRP(10)), - txflags(tfPartialPayment), - sendmax(STAmount{lpIssue, 10})); + env(pay(alice, bob, XRP(10)), txflags(tfPartialPayment), sendmax(STAmount{lpIssue, 10})); env.close(); BEAST_EXPECT(expectOffers(env, carol, 0)); } @@ -169,12 +150,7 @@ class LPTokenTransfer_test : public jtx::AMMTest using namespace jtx; Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - {USD(10'000), EUR(10'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(10'000), EUR(10'000)}, Fund::All); AMM ammAlice(env, alice, USD(10'000), EUR(10'000)); ammAlice.deposit(carol, 1'000); ammAlice.deposit(bob, 1'000); @@ -193,9 +169,7 @@ class LPTokenTransfer_test : public jtx::AMMTest // sell lptoken when one of the assets is frozen // carol can't create an offer to sell lptoken - env(offer(carol, XRP(10), STAmount{lpIssue, 10}), - txflags(tfPassive), - ter(tecUNFUNDED_OFFER)); + env(offer(carol, XRP(10), STAmount{lpIssue, 10}), txflags(tfPassive), ter(tecUNFUNDED_OFFER)); env.close(); BEAST_EXPECT(expectOffers(env, carol, 0)); @@ -204,16 +178,14 @@ class LPTokenTransfer_test : public jtx::AMMTest env.close(); // carol can create an offer to sell lptoken after USD is unfrozen - env(offer(carol, XRP(10), STAmount{lpIssue, 10}), - txflags(tfPassive)); + env(offer(carol, XRP(10), STAmount{lpIssue, 10}), txflags(tfPassive)); env.close(); BEAST_EXPECT(expectOffers(env, carol, 1)); } else { // without fixFrozenLPTokenTransfer, carol can create an offer - env(offer(carol, XRP(10), STAmount{lpIssue, 10}), - txflags(tfPassive)); + env(offer(carol, XRP(10), STAmount{lpIssue, 10}), txflags(tfPassive)); env.close(); BEAST_EXPECT(expectOffers(env, carol, 1)); } @@ -273,8 +245,7 @@ class LPTokenTransfer_test : public jtx::AMMTest BEAST_EXPECT( expectHolding(env, carol, STAmount{token2, 10'000'000}) && expectHolding(env, carol, STAmount{token1, 10'000'000})); - BEAST_EXPECT( - expectOffers(env, alice, 1) && expectOffers(env, carol, 0)); + BEAST_EXPECT(expectOffers(env, alice, 1) && expectOffers(env, carol, 0)); } else { @@ -286,8 +257,7 @@ class LPTokenTransfer_test : public jtx::AMMTest BEAST_EXPECT( expectHolding(env, carol, STAmount{token2, 10'000'100}) && expectHolding(env, carol, STAmount{token1, 9'999'900})); - BEAST_EXPECT( - expectOffers(env, alice, 0) && expectOffers(env, carol, 0)); + BEAST_EXPECT(expectOffers(env, alice, 0) && expectOffers(env, carol, 0)); } } @@ -299,12 +269,7 @@ class LPTokenTransfer_test : public jtx::AMMTest using namespace jtx; Env env{*this, features}; - fund( - env, - gw, - {alice, bob, carol}, - {USD(10'000), EUR(10'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(10'000), EUR(10'000)}, Fund::All); AMM ammAlice(env, alice, USD(10'000), EUR(10'000)); ammAlice.deposit(carol, 1'000); ammAlice.deposit(bob, 1'000); @@ -323,8 +288,7 @@ class LPTokenTransfer_test : public jtx::AMMTest // with fixFrozenLPTokenTransfer enabled, bob fails to cash the check if (features[fixFrozenLPTokenTransfer]) - env(check::cash(bob, carolChkId, STAmount{lpIssue, 10}), - ter(tecPATH_PARTIAL)); + env(check::cash(bob, carolChkId, STAmount{lpIssue, 10}), ter(tecPATH_PARTIAL)); else env(check::cash(bob, carolChkId, STAmount{lpIssue, 10})); @@ -350,12 +314,7 @@ class LPTokenTransfer_test : public jtx::AMMTest Env env{*this, features}; // Setup AMM - fund( - env, - gw, - {alice, bob, carol}, - {USD(10'000), EUR(10'000)}, - Fund::All); + fund(env, gw, {alice, bob, carol}, {USD(10'000), EUR(10'000)}, Fund::All); AMM ammAlice(env, alice, USD(10'000), EUR(10'000)); ammAlice.deposit(carol, 1'000); ammAlice.deposit(bob, 1'000); @@ -369,8 +328,7 @@ class LPTokenTransfer_test : public jtx::AMMTest // bob creates a sell offer for lptoken uint256 const sellOfferIndex = keylet::nftoffer(bob, env.seq(bob)).key; - env(token::createOffer(bob, nftID, STAmount{lpIssue, 10}), - txflags(tfSellNFToken)); + env(token::createOffer(bob, nftID, STAmount{lpIssue, 10}), txflags(tfSellNFToken)); env.close(); // gateway freezes carol's USD @@ -386,8 +344,7 @@ class LPTokenTransfer_test : public jtx::AMMTest // carol fails to accept bob's offer with lptoken because carol's // USD is frozen - env(token::acceptSellOffer(carol, sellOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::acceptSellOffer(carol, sellOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); // gateway unfreezes carol's USD @@ -404,9 +361,7 @@ class LPTokenTransfer_test : public jtx::AMMTest // bob fails to create a buy offer with lptoken for carol's nft // since bob's USD is frozen - env(token::createOffer(bob, nftID, STAmount{lpIssue, 10}), - token::owner(carol), - ter(tecUNFUNDED_OFFER)); + env(token::createOffer(bob, nftID, STAmount{lpIssue, 10}), token::owner(carol), ter(tecUNFUNDED_OFFER)); env.close(); // gateway unfreezes bob's USD @@ -414,8 +369,7 @@ class LPTokenTransfer_test : public jtx::AMMTest env.close(); // bob can now create a buy offer - env(token::createOffer(bob, nftID, STAmount{lpIssue, 10}), - token::owner(carol)); + env(token::createOffer(bob, nftID, STAmount{lpIssue, 10}), token::owner(carol)); env.close(); } else @@ -432,10 +386,8 @@ class LPTokenTransfer_test : public jtx::AMMTest env.close(); // bob creates a buy offer with lptoken despite bob's USD is frozen - uint256 const buyOfferIndex = - keylet::nftoffer(bob, env.seq(bob)).key; - env(token::createOffer(bob, nftID, STAmount{lpIssue, 10}), - token::owner(carol)); + uint256 const buyOfferIndex = keylet::nftoffer(bob, env.seq(bob)).key; + env(token::createOffer(bob, nftID, STAmount{lpIssue, 10}), token::owner(carol)); env.close(); // carol accepts bob's offer diff --git a/src/test/app/LedgerHistory_test.cpp b/src/test/app/LedgerHistory_test.cpp index b69203f1e0..eeca551f35 100644 --- a/src/test/app/LedgerHistory_test.cpp +++ b/src/test/app/LedgerHistory_test.cpp @@ -37,19 +37,14 @@ public: { assert(!stx); return std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); } - auto res = std::make_shared( - *prev, prev->header().closeTime + closeOffset); + auto res = std::make_shared(*prev, prev->header().closeTime + closeOffset); if (stx) { OpenView accum(&*res); - applyTransaction( - env.app(), accum, *stx, false, tapNONE, env.journal); + applyTransaction(env.app(), accum, *stx, false, tapNONE, env.journal); accum.apply(*res); } res->updateSkipList(); @@ -61,10 +56,7 @@ public: res->unshare(); // Accept ledger - res->setAccepted( - res->header().closeTime, - res->header().closeTimeResolution, - true /* close time correct*/); + res->setAccepted(res->header().closeTime, res->header().closeTimeResolution, true /* close time correct*/); lh.insert(res, false); return res; } @@ -79,10 +71,7 @@ public: // No mismatch { bool found = false; - Env env{ - *this, - envconfig(), - std::make_unique("MISMATCH ", &found)}; + Env env{*this, envconfig(), std::make_unique("MISMATCH ", &found)}; LedgerHistory lh{beast::insight::NullCollector::New(), env.app()}; auto const genesis = makeLedger({}, env, lh, 0s); uint256 const dummyTxHash{1}; @@ -95,11 +84,7 @@ public: // Close time mismatch { bool found = false; - Env env{ - *this, - envconfig(), - std::make_unique( - "MISMATCH on close time", &found)}; + Env env{*this, envconfig(), std::make_unique("MISMATCH on close time", &found)}; LedgerHistory lh{beast::insight::NullCollector::New(), env.app()}; auto const genesis = makeLedger({}, env, lh, 0s); auto const ledgerA = makeLedger(genesis, env, lh, 4s); @@ -115,11 +100,7 @@ public: // Prior ledger mismatch { bool found = false; - Env env{ - *this, - envconfig(), - std::make_unique( - "MISMATCH on prior ledger", &found)}; + Env env{*this, envconfig(), std::make_unique("MISMATCH on prior ledger", &found)}; LedgerHistory lh{beast::insight::NullCollector::New(), env.app()}; auto const genesis = makeLedger({}, env, lh, 0s); auto const ledgerA = makeLedger(genesis, env, lh, 4s); @@ -138,14 +119,10 @@ public: // somehow generate different ledgers for (bool const txBug : {true, false}) { - std::string const msg = txBug - ? "MISMATCH with same consensus transaction set" - : "MISMATCH on consensus transaction set"; + std::string const msg = + txBug ? "MISMATCH with same consensus transaction set" : "MISMATCH on consensus transaction set"; bool found = false; - Env env{ - *this, - envconfig(), - std::make_unique(msg, &found)}; + Env env{*this, envconfig(), std::make_unique(msg, &found)}; LedgerHistory lh{beast::insight::NullCollector::New(), env.app()}; Account alice{"A1"}; @@ -153,12 +130,10 @@ public: env.fund(XRP(1000), alice, bob); env.close(); - auto const ledgerBase = - env.app().getLedgerMaster().getClosedLedger(); + auto const ledgerBase = env.app().getLedgerMaster().getClosedLedger(); JTx txAlice = env.jt(noop(alice)); - auto const ledgerA = - makeLedger(ledgerBase, env, lh, 4s, txAlice.stx); + auto const ledgerA = makeLedger(ledgerBase, env, lh, 4s, txAlice.stx); JTx txBob = env.jt(noop(bob)); auto const ledgerB = makeLedger(ledgerBase, env, lh, 4s, txBob.stx); @@ -166,10 +141,7 @@ public: lh.builtLedger(ledgerA, txAlice.stx->getTransactionID(), {}); // Simulate the bug by claiming ledgerB had the same consensus hash // as ledgerA, but somehow generated different ledgers - lh.validatedLedger( - ledgerB, - txBug ? txAlice.stx->getTransactionID() - : txBob.stx->getTransactionID()); + lh.validatedLedger(ledgerB, txBug ? txAlice.stx->getTransactionID() : txBob.stx->getTransactionID()); BEAST_EXPECT(found); } diff --git a/src/test/app/LedgerLoad_test.cpp b/src/test/app/LedgerLoad_test.cpp index d5c37d0404..f27edadd58 100644 --- a/src/test/app/LedgerLoad_test.cpp +++ b/src/test/app/LedgerLoad_test.cpp @@ -69,8 +69,7 @@ class LedgerLoad_test : public beast::unit_test::suite } retval.ledger = env.rpc("ledger", "current", "full")[jss::result]; - BEAST_EXPECT( - retval.ledger[jss::ledger][jss::accountState].size() == 102); + BEAST_EXPECT(retval.ledger[jss::ledger][jss::accountState].size() == 102); retval.hashes = [&] { for (auto const& it : retval.ledger[jss::ledger][jss::accountState]) @@ -83,10 +82,7 @@ class LedgerLoad_test : public beast::unit_test::suite BEAST_EXPECT(retval.hashes.size() == 41); retval.trapTxHash = [&]() { - auto const txs = env.rpc( - "ledger", - std::to_string(41), - "tx")[jss::result][jss::ledger][jss::transactions]; + auto const txs = env.rpc("ledger", std::to_string(41), "tx")[jss::result][jss::ledger][jss::transactions]; BEAST_EXPECT(txs.isArray() && txs.size() > 0); uint256 tmp; BEAST_EXPECT(tmp.parseHex(txs[0u][jss::hash].asString())); @@ -109,18 +105,11 @@ class LedgerLoad_test : public beast::unit_test::suite // create a new env with the ledger file specified for startup Env env( *this, - envconfig( - ledgerConfig, - sd.dbPath, - sd.ledgerFile, - Config::LOAD_FILE, - std::nullopt), + envconfig(ledgerConfig, sd.dbPath, sd.ledgerFile, Config::LOAD_FILE, std::nullopt), nullptr, beast::severities::kDisabled); auto jrb = env.rpc("ledger", "current", "full")[jss::result]; - BEAST_EXPECT( - sd.ledger[jss::ledger][jss::accountState].size() == - jrb[jss::ledger][jss::accountState].size()); + BEAST_EXPECT(sd.ledger[jss::ledger][jss::accountState].size() == jrb[jss::ledger][jss::accountState].size()); } void @@ -134,12 +123,7 @@ class LedgerLoad_test : public beast::unit_test::suite except([&] { Env env( *this, - envconfig( - ledgerConfig, - sd.dbPath, - "", - Config::LOAD_FILE, - std::nullopt), + envconfig(ledgerConfig, sd.dbPath, "", Config::LOAD_FILE, std::nullopt), nullptr, beast::severities::kDisabled); }); @@ -148,25 +132,15 @@ class LedgerLoad_test : public beast::unit_test::suite except([&] { Env env( *this, - envconfig( - ledgerConfig, - sd.dbPath, - "badfile.json", - Config::LOAD_FILE, - std::nullopt), + envconfig(ledgerConfig, sd.dbPath, "badfile.json", Config::LOAD_FILE, std::nullopt), nullptr, beast::severities::kDisabled); }); // make a corrupted version of the ledger file (last 10 bytes removed). boost::system::error_code ec; - auto ledgerFileCorrupt = - boost::filesystem::path{sd.dbPath} / "ledgerdata_bad.json"; - copy_file( - sd.ledgerFile, - ledgerFileCorrupt, - copy_options::overwrite_existing, - ec); + auto ledgerFileCorrupt = boost::filesystem::path{sd.dbPath} / "ledgerdata_bad.json"; + copy_file(sd.ledgerFile, ledgerFileCorrupt, copy_options::overwrite_existing, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; auto filesize = file_size(ledgerFileCorrupt, ec); @@ -179,12 +153,7 @@ class LedgerLoad_test : public beast::unit_test::suite except([&] { Env env( *this, - envconfig( - ledgerConfig, - sd.dbPath, - ledgerFileCorrupt.string(), - Config::LOAD_FILE, - std::nullopt), + envconfig(ledgerConfig, sd.dbPath, ledgerFileCorrupt.string(), Config::LOAD_FILE, std::nullopt), nullptr, beast::severities::kDisabled); }); @@ -201,19 +170,12 @@ class LedgerLoad_test : public beast::unit_test::suite boost::erase_all(ledgerHash, "\""); Env env( *this, - envconfig( - ledgerConfig, - sd.dbPath, - ledgerHash, - Config::LOAD, - std::nullopt), + envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::LOAD, std::nullopt), nullptr, beast::severities::kDisabled); auto jrb = env.rpc("ledger", "current", "full")[jss::result]; BEAST_EXPECT(jrb[jss::ledger][jss::accountState].size() == 98); - BEAST_EXPECT( - jrb[jss::ledger][jss::accountState].size() <= - sd.ledger[jss::ledger][jss::accountState].size()); + BEAST_EXPECT(jrb[jss::ledger][jss::accountState].size() <= sd.ledger[jss::ledger][jss::accountState].size()); } void @@ -227,12 +189,7 @@ class LedgerLoad_test : public beast::unit_test::suite boost::erase_all(ledgerHash, "\""); Env env( *this, - envconfig( - ledgerConfig, - sd.dbPath, - ledgerHash, - Config::REPLAY, - std::nullopt), + envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, std::nullopt), nullptr, beast::severities::kDisabled); auto const jrb = env.rpc("ledger", "current", "full")[jss::result]; @@ -242,9 +199,7 @@ class LedgerLoad_test : public beast::unit_test::suite env.close(); auto const closed = env.rpc("ledger", "current", "full")[jss::result]; BEAST_EXPECT(closed[jss::ledger][jss::accountState].size() == 98); - BEAST_EXPECT( - closed[jss::ledger][jss::accountState].size() <= - sd.ledger[jss::ledger][jss::accountState].size()); + BEAST_EXPECT(closed[jss::ledger][jss::accountState].size() <= sd.ledger[jss::ledger][jss::accountState].size()); } void @@ -258,12 +213,7 @@ class LedgerLoad_test : public beast::unit_test::suite boost::erase_all(ledgerHash, "\""); Env env( *this, - envconfig( - ledgerConfig, - sd.dbPath, - ledgerHash, - Config::REPLAY, - sd.trapTxHash), + envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, sd.trapTxHash), nullptr, beast::severities::kDisabled); auto const jrb = env.rpc("ledger", "current", "full")[jss::result]; @@ -273,9 +223,7 @@ class LedgerLoad_test : public beast::unit_test::suite env.close(); auto const closed = env.rpc("ledger", "current", "full")[jss::result]; BEAST_EXPECT(closed[jss::ledger][jss::accountState].size() == 98); - BEAST_EXPECT( - closed[jss::ledger][jss::accountState].size() <= - sd.ledger[jss::ledger][jss::accountState].size()); + BEAST_EXPECT(closed[jss::ledger][jss::accountState].size() <= sd.ledger[jss::ledger][jss::accountState].size()); } void @@ -293,12 +241,7 @@ class LedgerLoad_test : public beast::unit_test::suite // replay when trapTxHash is set to an invalid transaction Env env( *this, - envconfig( - ledgerConfig, - sd.dbPath, - ledgerHash, - Config::REPLAY, - ~sd.trapTxHash), + envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, ~sd.trapTxHash), nullptr, beast::severities::kDisabled); BEAST_EXPECT(false); @@ -322,14 +265,11 @@ class LedgerLoad_test : public beast::unit_test::suite // create a new env with the ledger "latest" specified for startup Env env( *this, - envconfig( - ledgerConfig, sd.dbPath, "latest", Config::LOAD, std::nullopt), + envconfig(ledgerConfig, sd.dbPath, "latest", Config::LOAD, std::nullopt), nullptr, beast::severities::kDisabled); auto jrb = env.rpc("ledger", "current", "full")[jss::result]; - BEAST_EXPECT( - sd.ledger[jss::ledger][jss::accountState].size() == - jrb[jss::ledger][jss::accountState].size()); + BEAST_EXPECT(sd.ledger[jss::ledger][jss::accountState].size() == jrb[jss::ledger][jss::accountState].size()); } void @@ -341,14 +281,11 @@ class LedgerLoad_test : public beast::unit_test::suite // create a new env with specific ledger index at startup Env env( *this, - envconfig( - ledgerConfig, sd.dbPath, "43", Config::LOAD, std::nullopt), + envconfig(ledgerConfig, sd.dbPath, "43", Config::LOAD, std::nullopt), nullptr, beast::severities::kDisabled); auto jrb = env.rpc("ledger", "current", "full")[jss::result]; - BEAST_EXPECT( - sd.ledger[jss::ledger][jss::accountState].size() == - jrb[jss::ledger][jss::accountState].size()); + BEAST_EXPECT(sd.ledger[jss::ledger][jss::accountState].size() == jrb[jss::ledger][jss::accountState].size()); } public: diff --git a/src/test/app/LedgerMaster_test.cpp b/src/test/app/LedgerMaster_test.cpp index 59e02cbabb..eb346288c2 100644 --- a/src/test/app/LedgerMaster_test.cpp +++ b/src/test/app/LedgerMaster_test.cpp @@ -43,8 +43,7 @@ class LedgerMaster_test : public beast::unit_test::suite env(noop(alice)); txns.emplace_back(env.tx()); env.close(); - metas.emplace_back( - env.closed()->txRead(env.tx()->getTransactionID()).second); + metas.emplace_back(env.closed()->txRead(env.tx()->getTransactionID()).second); } // add last (empty) ledger env.close(); @@ -54,35 +53,30 @@ class LedgerMaster_test : public beast::unit_test::suite { std::uint32_t ledgerSeq = -1; std::uint32_t txnIndex = 0; - auto result = - env.app().getLedgerMaster().txnIdFromIndex(ledgerSeq, txnIndex); + auto result = env.app().getLedgerMaster().txnIdFromIndex(ledgerSeq, txnIndex); BEAST_EXPECT(!result); } // test not in ledger { uint32_t txnIndex = metas[0]->getFieldU32(sfTransactionIndex); - auto result = - env.app().getLedgerMaster().txnIdFromIndex(0, txnIndex); + auto result = env.app().getLedgerMaster().txnIdFromIndex(0, txnIndex); BEAST_EXPECT(!result); } // test empty ledger { - auto result = - env.app().getLedgerMaster().txnIdFromIndex(endLegSeq, 0); + auto result = env.app().getLedgerMaster().txnIdFromIndex(endLegSeq, 0); BEAST_EXPECT(!result); } // ended without result { uint32_t txnIndex = metas[0]->getFieldU32(sfTransactionIndex); - auto result = env.app().getLedgerMaster().txnIdFromIndex( - endLegSeq + 1, txnIndex); + auto result = env.app().getLedgerMaster().txnIdFromIndex(endLegSeq + 1, txnIndex); BEAST_EXPECT(!result); } // success (first tx) { uint32_t txnIndex = metas[0]->getFieldU32(sfTransactionIndex); - auto result = env.app().getLedgerMaster().txnIdFromIndex( - startLegSeq, txnIndex); + auto result = env.app().getLedgerMaster().txnIdFromIndex(startLegSeq, txnIndex); BEAST_EXPECT( *result == uint256("277F4FD89C20B92457FEF05FF63F6405563AD0563C73D967A29727" @@ -91,8 +85,7 @@ class LedgerMaster_test : public beast::unit_test::suite // success (second tx) { uint32_t txnIndex = metas[1]->getFieldU32(sfTransactionIndex); - auto result = env.app().getLedgerMaster().txnIdFromIndex( - startLegSeq + 1, txnIndex); + auto result = env.app().getLedgerMaster().txnIdFromIndex(startLegSeq + 1, txnIndex); BEAST_EXPECT( *result == uint256("293DF7335EBBAF4420D52E70ABF470EB4C5792CAEA2F91F76193C2" diff --git a/src/test/app/LedgerReplay_test.cpp b/src/test/app/LedgerReplay_test.cpp index beb27817a1..8bf1a8f668 100644 --- a/src/test/app/LedgerReplay_test.cpp +++ b/src/test/app/LedgerReplay_test.cpp @@ -39,14 +39,9 @@ struct LedgerReplay_test : public beast::unit_test::suite LedgerMaster& ledgerMaster = env.app().getLedgerMaster(); auto const lastClosed = ledgerMaster.getClosedLedger(); - auto const lastClosedParent = - ledgerMaster.getLedgerByHash(lastClosed->header().parentHash); + auto const lastClosedParent = ledgerMaster.getLedgerByHash(lastClosed->header().parentHash); - auto const replayed = buildLedger( - LedgerReplay(lastClosedParent, lastClosed), - tapNONE, - env.app(), - env.journal); + auto const replayed = buildLedger(LedgerReplay(lastClosedParent, lastClosed), tapNONE, env.app(), env.journal); BEAST_EXPECT(replayed->header().hash == lastClosed->header().hash); } @@ -65,18 +60,14 @@ enum class InboundLedgersBehavior { class MagicInboundLedgers : public InboundLedgers { public: - MagicInboundLedgers( - LedgerMaster& ledgerSource, - LedgerMaster& ledgerSink, - InboundLedgersBehavior bhvr) + MagicInboundLedgers(LedgerMaster& ledgerSource, LedgerMaster& ledgerSink, InboundLedgersBehavior bhvr) : ledgerSource(ledgerSource), ledgerSink(ledgerSink), bhvr(bhvr) { } virtual ~MagicInboundLedgers() = default; virtual std::shared_ptr - acquire(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason) - override + acquire(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason) override { if (bhvr == InboundLedgersBehavior::DropAll) return {}; @@ -90,10 +81,7 @@ public: } virtual void - acquireAsync( - uint256 const& hash, - std::uint32_t seq, - InboundLedger::Reason reason) override + acquireAsync(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason reason) override { } @@ -104,10 +92,7 @@ public: } virtual bool - gotLedgerData( - LedgerHash const& ledgerHash, - std::shared_ptr, - std::shared_ptr) override + gotLedgerData(LedgerHash const& ledgerHash, std::shared_ptr, std::shared_ptr) override { return false; } @@ -189,8 +174,7 @@ class TestPeer : public Peer { public: TestPeer(bool enableLedgerReplay) - : ledgerReplayEnabled_(enableLedgerReplay) - , nodePublicKey_(derivePublicKey(KeyType::ed25519, randomSecretKey())) + : ledgerReplayEnabled_(enableLedgerReplay), nodePublicKey_(derivePublicKey(KeyType::ed25519, randomSecretKey())) { } @@ -204,8 +188,7 @@ public: return {}; } void - charge(Resource::Charge const& fee, std::string const& context = {}) - override + charge(Resource::Charge const& fee, std::string const& context = {}) override { } id_t @@ -339,10 +322,7 @@ struct TestPeerSet : public PeerSet LedgerReplayMsgHandler& other, PeerSetBehavior bhvr, bool enableLedgerReplay) - : local(me) - , remote(other) - , dummyPeer(std::make_shared(enableLedgerReplay)) - , behavior(bhvr) + : local(me), remote(other), dummyPeer(std::make_shared(enableLedgerReplay)), behavior(bhvr) { } @@ -357,10 +337,8 @@ struct TestPeerSet : public PeerSet } void - sendRequest( - ::google::protobuf::Message const& msg, - protocol::MessageType type, - std::shared_ptr const& peer) override + sendRequest(::google::protobuf::Message const& msg, protocol::MessageType type, std::shared_ptr const& peer) + override { int dropRate = 0; if (behavior == PeerSetBehavior::Drop50) @@ -378,8 +356,7 @@ struct TestPeerSet : public PeerSet return; auto request = std::make_shared( dynamic_cast(msg)); - auto reply = std::make_shared( - remote.processProofPathRequest(request)); + auto reply = std::make_shared(remote.processProofPathRequest(request)); local.processProofPathResponse(reply); if (behavior == PeerSetBehavior::Repeat) local.processProofPathResponse(reply); @@ -390,8 +367,8 @@ struct TestPeerSet : public PeerSet return; auto request = std::make_shared( dynamic_cast(msg)); - auto reply = std::make_shared( - remote.processReplayDeltaRequest(request)); + auto reply = + std::make_shared(remote.processReplayDeltaRequest(request)); local.processReplayDeltaResponse(reply); if (behavior == PeerSetBehavior::Repeat) local.processReplayDeltaResponse(reply); @@ -426,18 +403,14 @@ public: LedgerReplayMsgHandler& other, PeerSetBehavior bhvr, PeerFeature peerFeature) - : local(me) - , remote(other) - , behavior(bhvr) - , enableLedgerReplay(peerFeature == PeerFeature::LedgerReplayEnabled) + : local(me), remote(other), behavior(bhvr), enableLedgerReplay(peerFeature == PeerFeature::LedgerReplayEnabled) { } std::unique_ptr build() override { - return std::make_unique( - local, remote, behavior, enableLedgerReplay); + return std::make_unique(local, remote, behavior, enableLedgerReplay); } private: @@ -484,8 +457,7 @@ struct LedgerServer auto fundedAccounts = accounts.size(); for (int i = 0; i < newAccounts; ++i) { - accounts.emplace_back( - "alice_" + std::to_string(fundedAccounts + i)); + accounts.emplace_back("alice_" + std::to_string(fundedAccounts + i)); env.fund(jtx::XRP(param.initAmount), accounts.back()); } env.close(); @@ -522,8 +494,7 @@ struct LedgerServer env.apply( pay(accounts[fromIdx], accounts[toIdx], - jtx::drops(ledgerMaster.getClosedLedger()->fees().base) + - jtx::XRP(param.txAmount)), + jtx::drops(ledgerMaster.getClosedLedger()->fees().base) + jtx::XRP(param.txAmount)), jtx::seq(jtx::autofill), jtx::fee(jtx::autofill), jtx::sig(jtx::autofill)); @@ -577,20 +548,13 @@ public: : env(suite, jtx::envconfig(), nullptr, beast::severities::kDisabled) , app(env.app()) , ledgerMaster(env.app().getLedgerMaster()) - , inboundLedgers( - server.app.getLedgerMaster(), - ledgerMaster, - inboundBhvr) + , inboundLedgers(server.app.getLedgerMaster(), ledgerMaster, inboundBhvr) , serverMsgHandler(server.app, server.app.getLedgerReplayer()) , clientMsgHandler(env.app(), replayer) , replayer( env.app(), inboundLedgers, - std::make_unique( - clientMsgHandler, - serverMsgHandler, - behavior, - peerFeature)) + std::make_unique(clientMsgHandler, serverMsgHandler, behavior, peerFeature)) { } @@ -666,11 +630,9 @@ public: findTask(uint256 const& hash, int totalReplay) { std::unique_lock lock(replayer.mtx_); - auto i = std::find_if( - replayer.tasks_.begin(), replayer.tasks_.end(), [&](auto const& t) { - return t->parameter_.finishHash_ == hash && - t->parameter_.totalLedgers_ == totalReplay; - }); + auto i = std::find_if(replayer.tasks_.begin(), replayer.tasks_.end(), [&](auto const& t) { + return t->parameter_.finishHash_ == hash && t->parameter_.totalLedgers_ == totalReplay; + }); if (i == replayer.tasks_.end()) return {}; return *i; @@ -691,14 +653,10 @@ public: } bool - countsAsExpected( - std::size_t tasks, - std::size_t skipLists, - std::size_t deltas) + countsAsExpected(std::size_t tasks, std::size_t skipLists, std::size_t deltas) { std::unique_lock lock(replayer.mtx_); - return replayer.tasks_.size() == tasks && - replayer.skipLists_.size() == skipLists && + return replayer.tasks_.size() == tasks && replayer.skipLists_.size() == skipLists && replayer.deltas_.size() == deltas; } @@ -807,8 +765,7 @@ public: if (!waitForDone()) return false; - return checkStatus( - hash, totalReplay, taskExpect, skiplistExpect, deltaExpects); + return checkStatus(hash, totalReplay, taskExpect, skiplistExpect, deltaExpects); } jtx::Env env; @@ -822,10 +779,7 @@ public: using namespace beast::severities; void -logAll( - LedgerServer& server, - LedgerReplayClient& client, - beast::severities::Severity level = Severity::kTrace) +logAll(LedgerServer& server, LedgerReplayClient& client, beast::severities::Severity level = Severity::kTrace) { server.app.logs().threshold(level); client.app.logs().threshold(level); @@ -843,8 +797,7 @@ struct NetworkOfTwo PeerSetBehavior behavior = PeerSetBehavior::Good, InboundLedgersBehavior inboundBhvr = InboundLedgersBehavior::Good, PeerFeature peerFeature = PeerFeature::LedgerReplayEnabled) - : server(suite, param) - , client(suite, server, behavior, inboundBhvr, peerFeature) + : server(suite, param), client(suite, server, behavior, inboundBhvr, peerFeature) { // logAll(server, client); } @@ -889,11 +842,10 @@ struct LedgerReplayer_test : public beast::unit_test::suite { // request, missing key auto request = std::make_shared(); - request->set_ledgerhash( - l->header().hash.data(), l->header().hash.size()); + request->set_ledgerhash(l->header().hash.data(), l->header().hash.size()); request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE); - auto reply = std::make_shared( - server.msgHandler.processProofPathRequest(request)); + auto reply = + std::make_shared(server.msgHandler.processProofPathRequest(request)); BEAST_EXPECT(reply->has_error()); BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply)); } @@ -901,26 +853,23 @@ struct LedgerReplayer_test : public beast::unit_test::suite // request, wrong hash auto request = std::make_shared(); request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE); - request->set_key( - keylet::skip().key.data(), keylet::skip().key.size()); + request->set_key(keylet::skip().key.data(), keylet::skip().key.size()); uint256 hash(1234567); request->set_ledgerhash(hash.data(), hash.size()); - auto reply = std::make_shared( - server.msgHandler.processProofPathRequest(request)); + auto reply = + std::make_shared(server.msgHandler.processProofPathRequest(request)); BEAST_EXPECT(reply->has_error()); } { // good request auto request = std::make_shared(); - request->set_ledgerhash( - l->header().hash.data(), l->header().hash.size()); + request->set_ledgerhash(l->header().hash.data(), l->header().hash.size()); request->set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE); - request->set_key( - keylet::skip().key.data(), keylet::skip().key.size()); + request->set_key(keylet::skip().key.data(), keylet::skip().key.size()); // generate response - auto reply = std::make_shared( - server.msgHandler.processProofPathRequest(request)); + auto reply = + std::make_shared(server.msgHandler.processProofPathRequest(request)); BEAST_EXPECT(!reply->has_error()); BEAST_EXPECT(server.msgHandler.processProofPathResponse(reply)); @@ -930,15 +879,13 @@ struct LedgerReplayer_test : public beast::unit_test::suite std::string r(reply->ledgerheader()); r.back()--; reply->set_ledgerheader(r); - BEAST_EXPECT( - !server.msgHandler.processProofPathResponse(reply)); + BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply)); r.back()++; reply->set_ledgerheader(r); BEAST_EXPECT(server.msgHandler.processProofPathResponse(reply)); // bad proof path reply->mutable_path()->RemoveLast(); - BEAST_EXPECT( - !server.msgHandler.processProofPathResponse(reply)); + BEAST_EXPECT(!server.msgHandler.processProofPathResponse(reply)); } } } @@ -953,15 +900,15 @@ struct LedgerReplayer_test : public beast::unit_test::suite { // request, missing hash auto request = std::make_shared(); - auto reply = std::make_shared( - server.msgHandler.processReplayDeltaRequest(request)); + auto reply = + std::make_shared(server.msgHandler.processReplayDeltaRequest(request)); BEAST_EXPECT(reply->has_error()); BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply)); // request, wrong hash uint256 hash(1234567); request->set_ledgerhash(hash.data(), hash.size()); - reply = std::make_shared( - server.msgHandler.processReplayDeltaRequest(request)); + reply = + std::make_shared(server.msgHandler.processReplayDeltaRequest(request)); BEAST_EXPECT(reply->has_error()); BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply)); } @@ -969,10 +916,9 @@ struct LedgerReplayer_test : public beast::unit_test::suite { // good request auto request = std::make_shared(); - request->set_ledgerhash( - l->header().hash.data(), l->header().hash.size()); - auto reply = std::make_shared( - server.msgHandler.processReplayDeltaRequest(request)); + request->set_ledgerhash(l->header().hash.data(), l->header().hash.size()); + auto reply = + std::make_shared(server.msgHandler.processReplayDeltaRequest(request)); BEAST_EXPECT(!reply->has_error()); BEAST_EXPECT(server.msgHandler.processReplayDeltaResponse(reply)); @@ -982,16 +928,13 @@ struct LedgerReplayer_test : public beast::unit_test::suite std::string r(reply->ledgerheader()); r.back()--; reply->set_ledgerheader(r); - BEAST_EXPECT( - !server.msgHandler.processReplayDeltaResponse(reply)); + BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply)); r.back()++; reply->set_ledgerheader(r); - BEAST_EXPECT( - server.msgHandler.processReplayDeltaResponse(reply)); + BEAST_EXPECT(server.msgHandler.processReplayDeltaResponse(reply)); // bad txns reply->mutable_transaction()->RemoveLast(); - BEAST_EXPECT( - !server.msgHandler.processReplayDeltaResponse(reply)); + BEAST_EXPECT(!server.msgHandler.processReplayDeltaResponse(reply)); } } } @@ -1008,8 +951,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite return sList; }; - LedgerReplayTask::TaskParameter tp10( - InboundLedger::Reason::GENERIC, uint256(10), 10); + LedgerReplayTask::TaskParameter tp10(InboundLedger::Reason::GENERIC, uint256(10), 10); BEAST_EXPECT(!tp10.update(uint256(777), 5, makeSkipList(10))); BEAST_EXPECT(!tp10.update(uint256(10), 5, makeSkipList(8))); BEAST_EXPECT(tp10.update(uint256(10), 10, makeSkipList(10))); @@ -1018,8 +960,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite BEAST_EXPECT(tp10.canMergeInto(tp10)); // smaller task - LedgerReplayTask::TaskParameter tp9( - InboundLedger::Reason::GENERIC, uint256(9), 9); + LedgerReplayTask::TaskParameter tp9(InboundLedger::Reason::GENERIC, uint256(9), 9); BEAST_EXPECT(tp9.canMergeInto(tp10)); BEAST_EXPECT(!tp10.canMergeInto(tp9)); @@ -1040,8 +981,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite BEAST_EXPECT(tp9.canMergeInto(tp10)); // larger task - LedgerReplayTask::TaskParameter tp20( - InboundLedger::Reason::GENERIC, uint256(20), 20); + LedgerReplayTask::TaskParameter tp20(InboundLedger::Reason::GENERIC, uint256(20), 20); BEAST_EXPECT(tp20.update(uint256(20), 20, makeSkipList(20))); BEAST_EXPECT(tp10.canMergeInto(tp20)); BEAST_EXPECT(tp9.canMergeInto(tp20)); @@ -1088,26 +1028,15 @@ struct LedgerReplayer_test : public beast::unit_test::suite http_request_type http_request; http_request.version(request.version()); http_request.base() = request.base(); - bool serverResult = - peerFeatureEnabled(http_request, FEATURE_LEDGER_REPLAY, server); + bool serverResult = peerFeatureEnabled(http_request, FEATURE_LEDGER_REPLAY, server); if (serverResult != expecting) return false; - beast::IP::Address addr = - boost::asio::ip::make_address("172.1.1.100"); + beast::IP::Address addr = boost::asio::ip::make_address("172.1.1.100"); jtx::Env serverEnv(*this); serverEnv.app().config().LEDGER_REPLAY = server; - auto http_resp = xrpl::makeResponse( - true, - http_request, - addr, - addr, - uint256{1}, - 1, - {1, 0}, - serverEnv.app()); - auto const clientResult = - peerFeatureEnabled(http_resp, FEATURE_LEDGER_REPLAY, client); + auto http_resp = xrpl::makeResponse(true, http_request, addr, addr, uint256{1}, 1, {1, 0}, serverEnv.app()); + auto const clientResult = peerFeatureEnabled(http_resp, FEATURE_LEDGER_REPLAY, client); if (clientResult != expecting) return false; @@ -1138,24 +1067,17 @@ struct LedgerReplayer_test : public beast::unit_test::suite if (l) { net.client.ledgerMaster.storeLedger(l); - l = net.server.ledgerMaster.getLedgerByHash( - l->header().parentHash); + l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash); } else break; } - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); - std::vector deltaStatuses( - totalReplay - 1, TaskStatus::Completed); + std::vector deltaStatuses(totalReplay - 1, TaskStatus::Completed); BEAST_EXPECT(net.client.waitAndCheckStatus( - finalHash, - totalReplay, - TaskStatus::Completed, - TaskStatus::Completed, - deltaStatuses)); + finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses)); // sweep net.client.replayer.sweep(); @@ -1167,25 +1089,15 @@ struct LedgerReplayer_test : public beast::unit_test::suite { testcase("all the ledgers from InboundLedgers"); NetworkOfTwo net( - *this, - {totalReplay + 1}, - PeerSetBehavior::DropAll, - InboundLedgersBehavior::Good, - PeerFeature::None); + *this, {totalReplay + 1}, PeerSetBehavior::DropAll, InboundLedgersBehavior::Good, PeerFeature::None); auto l = net.server.ledgerMaster.getClosedLedger(); uint256 finalHash = l->header().hash; - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); - std::vector deltaStatuses( - totalReplay - 1, TaskStatus::Completed); + std::vector deltaStatuses(totalReplay - 1, TaskStatus::Completed); BEAST_EXPECT(net.client.waitAndCheckStatus( - finalHash, - totalReplay, - TaskStatus::Completed, - TaskStatus::Completed, - deltaStatuses)); + finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses)); // sweep net.client.replayer.sweep(); @@ -1226,17 +1138,11 @@ struct LedgerReplayer_test : public beast::unit_test::suite } net.client.ledgerMaster.storeLedger(l); - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); - std::vector deltaStatuses( - totalReplay - 1, TaskStatus::Completed); + std::vector deltaStatuses(totalReplay - 1, TaskStatus::Completed); BEAST_EXPECT(net.client.waitAndCheckStatus( - finalHash, - totalReplay, - TaskStatus::Completed, - TaskStatus::Completed, - deltaStatuses)); + finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses)); BEAST_EXPECT(net.client.waitForLedgers(finalHash, totalReplay)); // sweep @@ -1258,16 +1164,11 @@ struct LedgerReplayer_test : public beast::unit_test::suite auto l = net.server.ledgerMaster.getClosedLedger(); uint256 finalHash = l->header().hash; - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); std::vector deltaStatuses; - BEAST_EXPECT(net.client.checkStatus( - finalHash, - totalReplay, - TaskStatus::NotDone, - TaskStatus::NotDone, - deltaStatuses)); + BEAST_EXPECT( + net.client.checkStatus(finalHash, totalReplay, TaskStatus::NotDone, TaskStatus::NotDone, deltaStatuses)); BEAST_EXPECT(net.client.countsAsExpected(1, 1, 0)); net.client.replayer.stop(); @@ -1288,34 +1189,22 @@ struct LedgerReplayer_test : public beast::unit_test::suite auto l = net.server.ledgerMaster.getClosedLedger(); uint256 finalHash = l->header().hash; - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); auto skipList = net.client.findSkipListAcquire(finalHash); - std::uint8_t payload[55] = { - 0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08, 0xB2}; - auto item = - make_shamapitem(uint256(12345), Slice(payload, sizeof(payload))); + std::uint8_t payload[55] = {0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08, 0xB2}; + auto item = make_shamapitem(uint256(12345), Slice(payload, sizeof(payload))); skipList->processData(l->seq(), item); std::vector deltaStatuses; BEAST_EXPECT(net.client.waitAndCheckStatus( - finalHash, - totalReplay, - TaskStatus::Failed, - TaskStatus::Failed, - deltaStatuses)); + finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses)); // add another task - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay + 1); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay + 1); BEAST_EXPECT(net.client.waitAndCheckStatus( - finalHash, - totalReplay, - TaskStatus::Failed, - TaskStatus::Failed, - deltaStatuses)); + finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses)); BEAST_EXPECT(net.client.countsAsExpected(2, 1, 0)); } @@ -1334,24 +1223,18 @@ struct LedgerReplayer_test : public beast::unit_test::suite auto l = net.server.ledgerMaster.getClosedLedger(); uint256 finalHash = l->header().hash; net.client.ledgerMaster.storeLedger(l); - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); auto delta = net.client.findLedgerDeltaAcquire(l->header().parentHash); delta->processData( l->header(), // wrong ledger info std::map>()); BEAST_EXPECT(net.client.taskStatus(delta) == TaskStatus::Failed); - BEAST_EXPECT( - net.client.taskStatus(net.client.findTask( - finalHash, totalReplay)) == TaskStatus::Failed); + BEAST_EXPECT(net.client.taskStatus(net.client.findTask(finalHash, totalReplay)) == TaskStatus::Failed); // add another task - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay + 1); - BEAST_EXPECT( - net.client.taskStatus(net.client.findTask( - finalHash, totalReplay + 1)) == TaskStatus::Failed); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay + 1); + BEAST_EXPECT(net.client.taskStatus(net.client.findTask(finalHash, totalReplay + 1)) == TaskStatus::Failed); } void @@ -1367,25 +1250,17 @@ struct LedgerReplayer_test : public beast::unit_test::suite PeerFeature::LedgerReplayEnabled); auto l = net.server.ledgerMaster.getClosedLedger(); uint256 finalHash = l->header().hash; - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); - std::vector deltaStatuses( - totalReplay - 1, TaskStatus::Completed); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); + std::vector deltaStatuses(totalReplay - 1, TaskStatus::Completed); BEAST_EXPECT(net.client.waitAndCheckStatus( - finalHash, - totalReplay, - TaskStatus::Completed, - TaskStatus::Completed, - deltaStatuses)); + finalHash, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses)); BEAST_EXPECT(net.client.waitForLedgers(finalHash, totalReplay)); // same range, same reason - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); BEAST_EXPECT(net.client.countsAsExpected(1, 1, totalReplay - 1)); // same range, different reason - net.client.replayer.replay( - InboundLedger::Reason::CONSENSUS, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::CONSENSUS, finalHash, totalReplay); BEAST_EXPECT(net.client.countsAsExpected(2, 1, totalReplay - 1)); // no overlap @@ -1394,8 +1269,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash); } auto finalHash_early = l->header().hash; - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash_early, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash_early, totalReplay); BEAST_EXPECT(net.client.waitAndCheckStatus( finalHash_early, totalReplay, @@ -1408,24 +1282,19 @@ struct LedgerReplayer_test : public beast::unit_test::suite // partial overlap l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash); auto finalHash_moreEarly = l->header().parentHash; - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash_moreEarly, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash_moreEarly, totalReplay); BEAST_EXPECT(net.client.waitAndCheckStatus( finalHash_moreEarly, totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses)); // deltaStatuses no change - BEAST_EXPECT( - net.client.waitForLedgers(finalHash_moreEarly, totalReplay)); - BEAST_EXPECT( - net.client.countsAsExpected(4, 3, 2 * (totalReplay - 1) + 2)); + BEAST_EXPECT(net.client.waitForLedgers(finalHash_moreEarly, totalReplay)); + BEAST_EXPECT(net.client.countsAsExpected(4, 3, 2 * (totalReplay - 1) + 2)); // cover - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay * 3); - deltaStatuses = - std::vector(totalReplay * 3 - 1, TaskStatus::Completed); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay * 3); + deltaStatuses = std::vector(totalReplay * 3 - 1, TaskStatus::Completed); BEAST_EXPECT(net.client.waitAndCheckStatus( finalHash, totalReplay * 3, @@ -1479,16 +1348,11 @@ struct LedgerReplayerTimeout_test : public beast::unit_test::suite auto l = net.server.ledgerMaster.getClosedLedger(); uint256 finalHash = l->header().hash; - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); std::vector deltaStatuses; BEAST_EXPECT(net.client.waitAndCheckStatus( - finalHash, - totalReplay, - TaskStatus::Failed, - TaskStatus::Failed, - deltaStatuses)); + finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Failed, deltaStatuses)); // sweep BEAST_EXPECT(net.client.countsAsExpected(1, 1, 0)); @@ -1511,18 +1375,12 @@ struct LedgerReplayerTimeout_test : public beast::unit_test::suite auto l = net.server.ledgerMaster.getClosedLedger(); uint256 finalHash = l->header().hash; net.client.ledgerMaster.storeLedger(l); - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finalHash, totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finalHash, totalReplay); - std::vector deltaStatuses( - totalReplay - 1, TaskStatus::Failed); + std::vector deltaStatuses(totalReplay - 1, TaskStatus::Failed); deltaStatuses.back() = TaskStatus::Completed; // in client ledgerMaster BEAST_EXPECT(net.client.waitAndCheckStatus( - finalHash, - totalReplay, - TaskStatus::Failed, - TaskStatus::Completed, - deltaStatuses)); + finalHash, totalReplay, TaskStatus::Failed, TaskStatus::Completed, deltaStatuses)); // sweep BEAST_EXPECT(net.client.countsAsExpected(1, 1, totalReplay - 1)); @@ -1560,34 +1418,25 @@ struct LedgerReplayerLong_test : public beast::unit_test::suite finishHashes.push_back(l->header().hash); for (int j = 0; j < totalReplay; ++j) { - l = net.server.ledgerMaster.getLedgerByHash( - l->header().parentHash); + l = net.server.ledgerMaster.getLedgerByHash(l->header().parentHash); } } BEAST_EXPECT(finishHashes.size() == rounds); for (int i = 0; i < rounds; ++i) { - net.client.replayer.replay( - InboundLedger::Reason::GENERIC, finishHashes[i], totalReplay); + net.client.replayer.replay(InboundLedger::Reason::GENERIC, finishHashes[i], totalReplay); } - std::vector deltaStatuses( - totalReplay - 1, TaskStatus::Completed); + std::vector deltaStatuses(totalReplay - 1, TaskStatus::Completed); for (int i = 0; i < rounds; ++i) { BEAST_EXPECT(net.client.waitAndCheckStatus( - finishHashes[i], - totalReplay, - TaskStatus::Completed, - TaskStatus::Completed, - deltaStatuses)); + finishHashes[i], totalReplay, TaskStatus::Completed, TaskStatus::Completed, deltaStatuses)); } - BEAST_EXPECT( - net.client.waitForLedgers(finishHashes[0], totalReplay * rounds)); - BEAST_EXPECT(net.client.countsAsExpected( - rounds, rounds, rounds * (totalReplay - 1))); + BEAST_EXPECT(net.client.waitForLedgers(finishHashes[0], totalReplay * rounds)); + BEAST_EXPECT(net.client.countsAsExpected(rounds, rounds, rounds * (totalReplay - 1))); // sweep net.client.replayer.sweep(); diff --git a/src/test/app/LendingHelpers_test.cpp b/src/test/app/LendingHelpers_test.cpp index 55fffad6b0..ee829550e1 100644 --- a/src/test/app/LendingHelpers_test.cpp +++ b/src/test/app/LendingHelpers_test.cpp @@ -64,12 +64,10 @@ class LendingHelpers_test : public beast::unit_test::suite { testcase("computeRaisedRate: " + tc.name); - auto const computedRaisedRate = - computeRaisedRate(tc.periodicRate, tc.paymentsRemaining); + auto const computedRaisedRate = computeRaisedRate(tc.periodicRate, tc.paymentsRemaining); BEAST_EXPECTS( computedRaisedRate == tc.expectedRaisedRate, - "Raised rate mismatch: expected " + - to_string(tc.expectedRaisedRate) + ", got " + + "Raised rate mismatch: expected " + to_string(tc.expectedRaisedRate) + ", got " + to_string(computedRaisedRate)); } } @@ -118,12 +116,10 @@ class LendingHelpers_test : public beast::unit_test::suite { testcase("computePaymentFactor: " + tc.name); - auto const computedPaymentFactor = - computePaymentFactor(tc.periodicRate, tc.paymentsRemaining); + auto const computedPaymentFactor = computePaymentFactor(tc.periodicRate, tc.paymentsRemaining); BEAST_EXPECTS( computedPaymentFactor == tc.expectedPaymentFactor, - "Payment factor mismatch: expected " + - to_string(tc.expectedPaymentFactor) + ", got " + + "Payment factor mismatch: expected " + to_string(tc.expectedPaymentFactor) + ", got " + to_string(computedPaymentFactor)); } } @@ -168,11 +164,9 @@ class LendingHelpers_test : public beast::unit_test::suite { .name = "Standard case", .principalOutstanding = Number{1'000}, - .periodicRate = - loanPeriodicRate(TenthBips32(100'000), 30 * 24 * 60 * 60), + .periodicRate = loanPeriodicRate(TenthBips32(100'000), 30 * 24 * 60 * 60), .paymentsRemaining = 3, - .expectedPeriodicPayment = - Number{389569066396123265, -15}, // from calc + .expectedPeriodicPayment = Number{389569066396123265, -15}, // from calc }, }; @@ -180,12 +174,11 @@ class LendingHelpers_test : public beast::unit_test::suite { testcase("loanPeriodicPayment: " + tc.name); - auto const computedPeriodicPayment = loanPeriodicPayment( - tc.principalOutstanding, tc.periodicRate, tc.paymentsRemaining); + auto const computedPeriodicPayment = + loanPeriodicPayment(tc.principalOutstanding, tc.periodicRate, tc.paymentsRemaining); BEAST_EXPECTS( computedPeriodicPayment == tc.expectedPeriodicPayment, - "Periodic payment mismatch: expected " + - to_string(tc.expectedPeriodicPayment) + ", got " + + "Periodic payment mismatch: expected " + to_string(tc.expectedPeriodicPayment) + ", got " + to_string(computedPeriodicPayment)); } } @@ -229,10 +222,8 @@ class LendingHelpers_test : public beast::unit_test::suite }, { .name = "Standard case", - .periodicPayment = - Number{389569066396123265, -15}, // from calc - .periodicRate = - loanPeriodicRate(TenthBips32(100'000), 30 * 24 * 60 * 60), + .periodicPayment = Number{389569066396123265, -15}, // from calc + .periodicRate = loanPeriodicRate(TenthBips32(100'000), 30 * 24 * 60 * 60), .paymentsRemaining = 3, .expectedPrincipalOutstanding = Number{1'000}, }, @@ -243,12 +234,10 @@ class LendingHelpers_test : public beast::unit_test::suite testcase("loanPrincipalFromPeriodicPayment: " + tc.name); auto const computedPrincipalOutstanding = - loanPrincipalFromPeriodicPayment( - tc.periodicPayment, tc.periodicRate, tc.paymentsRemaining); + loanPrincipalFromPeriodicPayment(tc.periodicPayment, tc.periodicRate, tc.paymentsRemaining); BEAST_EXPECTS( computedPrincipalOutstanding == tc.expectedPrincipalOutstanding, - "Principal outstanding mismatch: expected " + - to_string(tc.expectedPrincipalOutstanding) + ", got " + + "Principal outstanding mismatch: expected " + to_string(tc.expectedPrincipalOutstanding) + ", got " + to_string(computedPrincipalOutstanding)); } } @@ -268,45 +257,28 @@ class LendingHelpers_test : public beast::unit_test::suite auto const overpaymentFeeRate = TenthBips32{50'000}; // 50% auto const managementFeeRate = TenthBips16{10'000}; // 10% - auto const expectedOverpaymentFee = Number{500}; // 50% of 1,000 - auto const expectedOverpaymentInterestGross = - Number{100}; // 10% of 1,000 - auto const expectedOverpaymentInterestNet = - Number{90}; // 100 - 10% of 100 - auto const expectedOverpaymentManagementFee = Number{10}; // 10% of 100 - auto const expectedPrincipalPortion = Number{400}; // 1,000 - 100 - 500 + auto const expectedOverpaymentFee = Number{500}; // 50% of 1,000 + auto const expectedOverpaymentInterestGross = Number{100}; // 10% of 1,000 + auto const expectedOverpaymentInterestNet = Number{90}; // 100 - 10% of 100 + auto const expectedOverpaymentManagementFee = Number{10}; // 10% of 100 + auto const expectedPrincipalPortion = Number{400}; // 1,000 - 100 - 500 auto const components = detail::computeOverpaymentComponents( - IOU, - loanScale, - overpayment, - overpaymentInterestRate, - overpaymentFeeRate, - managementFeeRate); + IOU, loanScale, overpayment, overpaymentInterestRate, overpaymentFeeRate, managementFeeRate); + + BEAST_EXPECT(components.untrackedManagementFee == expectedOverpaymentFee); + + BEAST_EXPECT(components.untrackedInterest == expectedOverpaymentInterestNet); + + BEAST_EXPECT(components.trackedInterestPart() == expectedOverpaymentInterestNet); + + BEAST_EXPECT(components.trackedManagementFeeDelta == expectedOverpaymentManagementFee); + BEAST_EXPECT(components.trackedPrincipalDelta == expectedPrincipalPortion); + BEAST_EXPECT( + components.trackedManagementFeeDelta + components.untrackedInterest == expectedOverpaymentInterestGross); BEAST_EXPECT( - components.untrackedManagementFee == expectedOverpaymentFee); - - BEAST_EXPECT( - components.untrackedInterest == expectedOverpaymentInterestNet); - - BEAST_EXPECT( - components.trackedInterestPart() == expectedOverpaymentInterestNet); - - BEAST_EXPECT( - components.trackedManagementFeeDelta == - expectedOverpaymentManagementFee); - BEAST_EXPECT( - components.trackedPrincipalDelta == expectedPrincipalPortion); - BEAST_EXPECT( - components.trackedManagementFeeDelta + - components.untrackedInterest == - expectedOverpaymentInterestGross); - - BEAST_EXPECT( - components.trackedManagementFeeDelta + - components.untrackedInterest + - components.trackedPrincipalDelta + + components.trackedManagementFeeDelta + components.untrackedInterest + components.trackedPrincipalDelta + components.untrackedManagementFee == overpayment); } @@ -353,17 +325,14 @@ class LendingHelpers_test : public beast::unit_test::suite testcase("computeInterestAndFeeParts: " + tc.name); auto const [computedInterestPart, computedFeePart] = - computeInterestAndFeeParts( - IOU, tc.interest, tc.managementFeeRate, loanScale); + computeInterestAndFeeParts(IOU, tc.interest, tc.managementFeeRate, loanScale); BEAST_EXPECTS( computedInterestPart == tc.expectedInterestPart, - "Interest part mismatch: expected " + - to_string(tc.expectedInterestPart) + ", got " + + "Interest part mismatch: expected " + to_string(tc.expectedInterestPart) + ", got " + to_string(computedInterestPart)); BEAST_EXPECTS( computedFeePart == tc.expectedFeePart, - "Fee part mismatch: expected " + to_string(tc.expectedFeePart) + - ", got " + to_string(computedFeePart)); + "Fee part mismatch: expected " + to_string(tc.expectedFeePart) + ", got " + to_string(computedFeePart)); } } @@ -387,8 +356,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "On-time payment", .principalOutstanding = Number{1'000}, .lateInterestRate = TenthBips32{10'000}, // 10% - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .nextPaymentDueDate = 3'000, .expectedLateInterest = Number{0}, }, @@ -396,8 +364,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Early payment", .principalOutstanding = Number{1'000}, .lateInterestRate = TenthBips32{10'000}, // 10% - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .nextPaymentDueDate = 4'000, .expectedLateInterest = Number{0}, }, @@ -405,8 +372,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "No principal outstanding", .principalOutstanding = Number{0}, .lateInterestRate = TenthBips32{10'000}, // 10% - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .nextPaymentDueDate = 2'000, .expectedLateInterest = Number{0}, }, @@ -414,8 +380,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "No late interest rate", .principalOutstanding = Number{1'000}, .lateInterestRate = TenthBips32{0}, // 0% - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .nextPaymentDueDate = 2'000, .expectedLateInterest = Number{0}, }, @@ -423,11 +388,9 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Late payment", .principalOutstanding = Number{1'000}, .lateInterestRate = TenthBips32{100'000}, // 100% - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .nextPaymentDueDate = 2'000, - .expectedLateInterest = - Number{317097919837645865, -19}, // from calc + .expectedLateInterest = Number{317097919837645865, -19}, // from calc }, }; @@ -436,14 +399,10 @@ class LendingHelpers_test : public beast::unit_test::suite testcase("loanLatePaymentInterest: " + tc.name); auto const computedLateInterest = loanLatePaymentInterest( - tc.principalOutstanding, - tc.lateInterestRate, - tc.parentCloseTime, - tc.nextPaymentDueDate); + tc.principalOutstanding, tc.lateInterestRate, tc.parentCloseTime, tc.nextPaymentDueDate); BEAST_EXPECTS( computedLateInterest == tc.expectedLateInterest, - "Late interest mismatch: expected " + - to_string(tc.expectedLateInterest) + ", got " + + "Late interest mismatch: expected " + to_string(tc.expectedLateInterest) + ", got " + to_string(computedLateInterest)); } } @@ -470,8 +429,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Zero principal outstanding", .principalOutstanding = Number{0}, .periodicRate = Number{5, -2}, - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .startDate = 2'000, .prevPaymentDate = 2'500, .paymentInterval = 30 * 24 * 60 * 60, @@ -481,8 +439,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Before start date", .principalOutstanding = Number{1'000}, .periodicRate = Number{5, -2}, - .parentCloseTime = - NetClock::time_point{NetClock::duration{1'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{1'000}}, .startDate = 2'000, .prevPaymentDate = 1'500, .paymentInterval = 30 * 24 * 60 * 60, @@ -492,8 +449,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Zero periodic rate", .principalOutstanding = Number{1'000}, .periodicRate = Number{0}, - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .startDate = 2'000, .prevPaymentDate = 2'500, .paymentInterval = 30 * 24 * 60 * 60, @@ -503,8 +459,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Zero payment interval", .principalOutstanding = Number{1'000}, .periodicRate = Number{5, -2}, - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .startDate = 2'000, .prevPaymentDate = 2'500, .paymentInterval = 0, @@ -514,13 +469,11 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Standard case", .principalOutstanding = Number{1'000}, .periodicRate = Number{5, -2}, - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .startDate = 1'000, .prevPaymentDate = 2'000, .paymentInterval = 30 * 24 * 60 * 60, - .expectedAccruedInterest = - Number{1929012345679012346, -20}, // from calc + .expectedAccruedInterest = Number{1929012345679012346, -20}, // from calc }, }; @@ -537,8 +490,7 @@ class LendingHelpers_test : public beast::unit_test::suite tc.paymentInterval); BEAST_EXPECTS( computedAccruedInterest == tc.expectedAccruedInterest, - "Accrued interest mismatch: expected " + - to_string(tc.expectedAccruedInterest) + ", got " + + "Accrued interest mismatch: expected " + to_string(tc.expectedAccruedInterest) + ", got " + to_string(computedAccruedInterest)); } } @@ -569,8 +521,7 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Zero principal outstanding", .rawPrincipalOutstanding = Number{0}, .periodicRate = Number{5, -2}, - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .paymentInterval = 30 * 24 * 60 * 60, .prevPaymentDate = 2'000, .startDate = 1'000, @@ -581,27 +532,23 @@ class LendingHelpers_test : public beast::unit_test::suite .name = "Zero close interest rate", .rawPrincipalOutstanding = Number{1'000}, .periodicRate = Number{5, -2}, - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .paymentInterval = 30 * 24 * 60 * 60, .prevPaymentDate = 2'000, .startDate = 1'000, .closeInterestRate = TenthBips32{0}, - .expectedFullPaymentInterest = - Number{1929012345679012346, -20}, // from calc + .expectedFullPaymentInterest = Number{1929012345679012346, -20}, // from calc }, { .name = "Standard case", .rawPrincipalOutstanding = Number{1'000}, .periodicRate = Number{5, -2}, - .parentCloseTime = - NetClock::time_point{NetClock::duration{3'000}}, + .parentCloseTime = NetClock::time_point{NetClock::duration{3'000}}, .paymentInterval = 30 * 24 * 60 * 60, .prevPaymentDate = 2'000, .startDate = 1'000, .closeInterestRate = TenthBips32{10'000}, - .expectedFullPaymentInterest = - Number{1000192901234567901, -16}, // from calc + .expectedFullPaymentInterest = Number{1000192901234567901, -16}, // from calc }, }; @@ -619,8 +566,7 @@ class LendingHelpers_test : public beast::unit_test::suite tc.closeInterestRate); BEAST_EXPECTS( computedFullPaymentInterest == tc.expectedFullPaymentInterest, - "Full payment interest mismatch: expected " + - to_string(tc.expectedFullPaymentInterest) + ", got " + + "Full payment interest mismatch: expected " + to_string(tc.expectedFullPaymentInterest) + ", got " + to_string(computedFullPaymentInterest)); } } @@ -643,27 +589,14 @@ class LendingHelpers_test : public beast::unit_test::suite Number const loanPrincipal{1'000}; std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; std::uint32_t const paymentsRemaining = 10; - auto const periodicRate = - loanPeriodicRate(loanInterestRate, paymentInterval); + auto const periodicRate = loanPeriodicRate(loanInterestRate, paymentInterval); Number const overpaymentAmount{50}; - ExtendedPaymentComponents const overpaymentComponents = - computeOverpaymentComponents( - asset, - loanScale, - overpaymentAmount, - TenthBips32(0), - TenthBips32(0), - managementFeeRate); + ExtendedPaymentComponents const overpaymentComponents = computeOverpaymentComponents( + asset, loanScale, overpaymentAmount, TenthBips32(0), TenthBips32(0), managementFeeRate); auto const loanProperites = computeLoanProperties( - asset, - loanPrincipal, - loanInterestRate, - paymentInterval, - paymentsRemaining, - managementFeeRate, - loanScale); + asset, loanPrincipal, loanInterestRate, paymentInterval, paymentsRemaining, managementFeeRate, loanScale); Number const periodicPayment = loanProperites.periodicPayment; @@ -686,51 +619,38 @@ class LendingHelpers_test : public beast::unit_test::suite // =========== VALIDATE PAYMENT PARTS =========== BEAST_EXPECTS( actualPaymentParts.valueChange == 0, - " valueChange mismatch: expected 0, got " + - to_string(actualPaymentParts.valueChange)); + " valueChange mismatch: expected 0, got " + to_string(actualPaymentParts.valueChange)); BEAST_EXPECTS( actualPaymentParts.feePaid == 0, - " feePaid mismatch: expected 0, got " + - to_string(actualPaymentParts.feePaid)); + " feePaid mismatch: expected 0, got " + to_string(actualPaymentParts.feePaid)); BEAST_EXPECTS( actualPaymentParts.interestPaid == 0, - " interestPaid mismatch: expected 0, got " + - to_string(actualPaymentParts.interestPaid)); + " interestPaid mismatch: expected 0, got " + to_string(actualPaymentParts.interestPaid)); BEAST_EXPECTS( actualPaymentParts.principalPaid == overpaymentAmount, - " principalPaid mismatch: expected " + - to_string(overpaymentAmount) + ", got " + + " principalPaid mismatch: expected " + to_string(overpaymentAmount) + ", got " + to_string(actualPaymentParts.principalPaid)); // =========== VALIDATE STATE CHANGES =========== BEAST_EXPECTS( loanProperites.loanState.interestDue - newState.interestDue == 0, " interest change mismatch: expected 0, got " + - to_string( - loanProperites.loanState.interestDue - - newState.interestDue)); + to_string(loanProperites.loanState.interestDue - newState.interestDue)); BEAST_EXPECTS( - loanProperites.loanState.managementFeeDue - - newState.managementFeeDue == - 0, + loanProperites.loanState.managementFeeDue - newState.managementFeeDue == 0, " management fee change mismatch: expected 0, got " + - to_string( - loanProperites.loanState.managementFeeDue - - newState.managementFeeDue)); + to_string(loanProperites.loanState.managementFeeDue - newState.managementFeeDue)); BEAST_EXPECTS( actualPaymentParts.principalPaid == - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding, + loanProperites.loanState.principalOutstanding - newState.principalOutstanding, " principalPaid mismatch: expected " + - to_string( - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding) + - ", got " + to_string(actualPaymentParts.principalPaid)); + to_string(loanProperites.loanState.principalOutstanding - newState.principalOutstanding) + ", got " + + to_string(actualPaymentParts.principalPaid)); } void @@ -750,26 +670,18 @@ class LendingHelpers_test : public beast::unit_test::suite Number const loanPrincipal{1'000}; std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; std::uint32_t const paymentsRemaining = 10; - auto const periodicRate = - loanPeriodicRate(loanInterestRate, paymentInterval); + auto const periodicRate = loanPeriodicRate(loanInterestRate, paymentInterval); - ExtendedPaymentComponents const overpaymentComponents = - computeOverpaymentComponents( - asset, - loanScale, - Number{50, 0}, - TenthBips32(0), - TenthBips32(10'000), // 10% overpayment fee - managementFeeRate); + ExtendedPaymentComponents const overpaymentComponents = computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(0), + TenthBips32(10'000), // 10% overpayment fee + managementFeeRate); auto const loanProperites = computeLoanProperties( - asset, - loanPrincipal, - loanInterestRate, - paymentInterval, - paymentsRemaining, - managementFeeRate, - loanScale); + asset, loanPrincipal, loanInterestRate, paymentInterval, paymentsRemaining, managementFeeRate, loanScale); Number const periodicPayment = loanProperites.periodicPayment; @@ -792,52 +704,39 @@ class LendingHelpers_test : public beast::unit_test::suite // =========== VALIDATE PAYMENT PARTS =========== BEAST_EXPECTS( actualPaymentParts.valueChange == 0, - " valueChange mismatch: expected 0, got " + - to_string(actualPaymentParts.valueChange)); + " valueChange mismatch: expected 0, got " + to_string(actualPaymentParts.valueChange)); BEAST_EXPECTS( actualPaymentParts.feePaid == 5, - " feePaid mismatch: expected 5, got " + - to_string(actualPaymentParts.feePaid)); + " feePaid mismatch: expected 5, got " + to_string(actualPaymentParts.feePaid)); BEAST_EXPECTS( actualPaymentParts.principalPaid == 45, - " principalPaid mismatch: expected 45, got `" + - to_string(actualPaymentParts.principalPaid)); + " principalPaid mismatch: expected 45, got `" + to_string(actualPaymentParts.principalPaid)); BEAST_EXPECTS( actualPaymentParts.interestPaid == 0, - " interestPaid mismatch: expected 0, got " + - to_string(actualPaymentParts.interestPaid)); + " interestPaid mismatch: expected 0, got " + to_string(actualPaymentParts.interestPaid)); // =========== VALIDATE STATE CHANGES =========== // With no Loan interest, interest outstanding should not change BEAST_EXPECTS( loanProperites.loanState.interestDue - newState.interestDue == 0, " interest change mismatch: expected 0, got " + - to_string( - loanProperites.loanState.interestDue - - newState.interestDue)); + to_string(loanProperites.loanState.interestDue - newState.interestDue)); // With no Loan management fee, management fee due should not change BEAST_EXPECTS( - loanProperites.loanState.managementFeeDue - - newState.managementFeeDue == - 0, + loanProperites.loanState.managementFeeDue - newState.managementFeeDue == 0, " management fee change mismatch: expected 0, got " + - to_string( - loanProperites.loanState.managementFeeDue - - newState.managementFeeDue)); + to_string(loanProperites.loanState.managementFeeDue - newState.managementFeeDue)); BEAST_EXPECTS( actualPaymentParts.principalPaid == - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding, + loanProperites.loanState.principalOutstanding - newState.principalOutstanding, " principalPaid mismatch: expected " + - to_string( - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding) + - ", got " + to_string(actualPaymentParts.principalPaid)); + to_string(loanProperites.loanState.principalOutstanding - newState.principalOutstanding) + ", got " + + to_string(actualPaymentParts.principalPaid)); } void @@ -857,26 +756,18 @@ class LendingHelpers_test : public beast::unit_test::suite Number const loanPrincipal{1'000}; std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; std::uint32_t const paymentsRemaining = 10; - auto const periodicRate = - loanPeriodicRate(loanInterestRate, paymentInterval); + auto const periodicRate = loanPeriodicRate(loanInterestRate, paymentInterval); - ExtendedPaymentComponents const overpaymentComponents = - computeOverpaymentComponents( - asset, - loanScale, - Number{50, 0}, - TenthBips32(0), // no overpayment interest - TenthBips32(0), // 0% overpayment fee - managementFeeRate); + ExtendedPaymentComponents const overpaymentComponents = computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(0), // no overpayment interest + TenthBips32(0), // 0% overpayment fee + managementFeeRate); auto const loanProperites = computeLoanProperties( - asset, - loanPrincipal, - loanInterestRate, - paymentInterval, - paymentsRemaining, - managementFeeRate, - loanScale); + asset, loanPrincipal, loanInterestRate, paymentInterval, paymentsRemaining, managementFeeRate, loanScale); Number const periodicPayment = loanProperites.periodicPayment; @@ -901,63 +792,48 @@ class LendingHelpers_test : public beast::unit_test::suite // interest decrease BEAST_EXPECTS( (actualPaymentParts.valueChange == Number{-228802, -5}), - " valueChange mismatch: expected " + - to_string(Number{-228802, -5}) + ", got " + + " valueChange mismatch: expected " + to_string(Number{-228802, -5}) + ", got " + to_string(actualPaymentParts.valueChange)); // with no fee portion, fee paid should be zero BEAST_EXPECTS( actualPaymentParts.feePaid == 0, - " feePaid mismatch: expected 0, got " + - to_string(actualPaymentParts.feePaid)); + " feePaid mismatch: expected 0, got " + to_string(actualPaymentParts.feePaid)); BEAST_EXPECTS( actualPaymentParts.principalPaid == 50, - " principalPaid mismatch: expected 50, got `" + - to_string(actualPaymentParts.principalPaid)); + " principalPaid mismatch: expected 50, got `" + to_string(actualPaymentParts.principalPaid)); // with no interest portion, interest paid should be zero BEAST_EXPECTS( actualPaymentParts.interestPaid == 0, - " interestPaid mismatch: expected 0, got " + - to_string(actualPaymentParts.interestPaid)); + " interestPaid mismatch: expected 0, got " + to_string(actualPaymentParts.interestPaid)); // =========== VALIDATE STATE CHANGES =========== BEAST_EXPECTS( actualPaymentParts.principalPaid == - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding, + loanProperites.loanState.principalOutstanding - newState.principalOutstanding, " principalPaid mismatch: expected " + - to_string( - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding) + - ", got " + to_string(actualPaymentParts.principalPaid)); + to_string(loanProperites.loanState.principalOutstanding - newState.principalOutstanding) + ", got " + + to_string(actualPaymentParts.principalPaid)); BEAST_EXPECTS( - actualPaymentParts.valueChange == - newState.interestDue - loanProperites.loanState.interestDue, + actualPaymentParts.valueChange == newState.interestDue - loanProperites.loanState.interestDue, " valueChange mismatch: expected " + - to_string( - newState.interestDue - - loanProperites.loanState.interestDue) + - ", got " + to_string(actualPaymentParts.valueChange)); + to_string(newState.interestDue - loanProperites.loanState.interestDue) + ", got " + + to_string(actualPaymentParts.valueChange)); // With no Loan management fee, management fee due should not change BEAST_EXPECTS( - loanProperites.loanState.managementFeeDue - - newState.managementFeeDue == - 0, + loanProperites.loanState.managementFeeDue - newState.managementFeeDue == 0, " management fee change mismatch: expected 0, got " + - to_string( - loanProperites.loanState.managementFeeDue - - newState.managementFeeDue)); + to_string(loanProperites.loanState.managementFeeDue - newState.managementFeeDue)); } void testTryOverpaymentLoanInterestOverpaymentInterest() { - testcase( - "tryOverpayment - Loan Interest, Overpayment Interest, No Fee"); + testcase("tryOverpayment - Loan Interest, Overpayment Interest, No Fee"); using namespace jtx; using namespace xrpl::detail; @@ -971,26 +847,18 @@ class LendingHelpers_test : public beast::unit_test::suite Number const loanPrincipal{1'000}; std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; std::uint32_t const paymentsRemaining = 10; - auto const periodicRate = - loanPeriodicRate(loanInterestRate, paymentInterval); + auto const periodicRate = loanPeriodicRate(loanInterestRate, paymentInterval); - ExtendedPaymentComponents const overpaymentComponents = - computeOverpaymentComponents( - asset, - loanScale, - Number{50, 0}, - TenthBips32(10'000), // 10% overpayment interest - TenthBips32(0), // 0% overpayment fee - managementFeeRate); + ExtendedPaymentComponents const overpaymentComponents = computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(10'000), // 10% overpayment interest + TenthBips32(0), // 0% overpayment fee + managementFeeRate); auto const loanProperites = computeLoanProperties( - asset, - loanPrincipal, - loanInterestRate, - paymentInterval, - paymentsRemaining, - managementFeeRate, - loanScale); + asset, loanPrincipal, loanInterestRate, paymentInterval, paymentsRemaining, managementFeeRate, loanScale); Number const periodicPayment = loanProperites.periodicPayment; @@ -1014,41 +882,32 @@ class LendingHelpers_test : public beast::unit_test::suite // with overpayment interest portion, interest paid should be 5 BEAST_EXPECTS( actualPaymentParts.interestPaid == 5, - " interestPaid mismatch: expected 5, got " + - to_string(actualPaymentParts.interestPaid)); + " interestPaid mismatch: expected 5, got " + to_string(actualPaymentParts.interestPaid)); // With overpayment interest portion, value change should equal the // interest decrease plus overpayment interest portion BEAST_EXPECTS( - (actualPaymentParts.valueChange == - Number{-205922, -5} + actualPaymentParts.interestPaid), + (actualPaymentParts.valueChange == Number{-205922, -5} + actualPaymentParts.interestPaid), " valueChange mismatch: expected " + - to_string( - actualPaymentParts.valueChange - - actualPaymentParts.interestPaid) + - ", got " + to_string(actualPaymentParts.valueChange)); + to_string(actualPaymentParts.valueChange - actualPaymentParts.interestPaid) + ", got " + + to_string(actualPaymentParts.valueChange)); // with no fee portion, fee paid should be zero BEAST_EXPECTS( actualPaymentParts.feePaid == 0, - " feePaid mismatch: expected 0, got " + - to_string(actualPaymentParts.feePaid)); + " feePaid mismatch: expected 0, got " + to_string(actualPaymentParts.feePaid)); BEAST_EXPECTS( actualPaymentParts.principalPaid == 45, - " principalPaid mismatch: expected 45, got `" + - to_string(actualPaymentParts.principalPaid)); + " principalPaid mismatch: expected 45, got `" + to_string(actualPaymentParts.principalPaid)); // =========== VALIDATE STATE CHANGES =========== BEAST_EXPECTS( actualPaymentParts.principalPaid == - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding, + loanProperites.loanState.principalOutstanding - newState.principalOutstanding, " principalPaid mismatch: expected " + - to_string( - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding) + - ", got " + to_string(actualPaymentParts.principalPaid)); + to_string(loanProperites.loanState.principalOutstanding - newState.principalOutstanding) + ", got " + + to_string(actualPaymentParts.principalPaid)); // The change in interest is equal to the value change sans the // overpayment interest @@ -1057,20 +916,14 @@ class LendingHelpers_test : public beast::unit_test::suite newState.interestDue - loanProperites.loanState.interestDue, " valueChange mismatch: expected " + to_string( - newState.interestDue - - loanProperites.loanState.interestDue + - actualPaymentParts.interestPaid) + + newState.interestDue - loanProperites.loanState.interestDue + actualPaymentParts.interestPaid) + ", got " + to_string(actualPaymentParts.valueChange)); // With no Loan management fee, management fee due should not change BEAST_EXPECTS( - loanProperites.loanState.managementFeeDue - - newState.managementFeeDue == - 0, + loanProperites.loanState.managementFeeDue - newState.managementFeeDue == 0, " management fee change mismatch: expected 0, got " + - to_string( - loanProperites.loanState.managementFeeDue - - newState.managementFeeDue)); + to_string(loanProperites.loanState.managementFeeDue - newState.managementFeeDue)); } void @@ -1092,26 +945,18 @@ class LendingHelpers_test : public beast::unit_test::suite Number const loanPrincipal{1'000}; std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; std::uint32_t const paymentsRemaining = 10; - auto const periodicRate = - loanPeriodicRate(loanInterestRate, paymentInterval); + auto const periodicRate = loanPeriodicRate(loanInterestRate, paymentInterval); - ExtendedPaymentComponents const overpaymentComponents = - computeOverpaymentComponents( - asset, - loanScale, - Number{50, 0}, - TenthBips32(10'000), // 10% overpayment interest - TenthBips32(0), // 0% overpayment fee - managementFeeRate); + ExtendedPaymentComponents const overpaymentComponents = computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(10'000), // 10% overpayment interest + TenthBips32(0), // 0% overpayment fee + managementFeeRate); auto const loanProperites = computeLoanProperties( - asset, - loanPrincipal, - loanInterestRate, - paymentInterval, - paymentsRemaining, - managementFeeRate, - loanScale); + asset, loanPrincipal, loanInterestRate, paymentInterval, paymentsRemaining, managementFeeRate, loanScale); Number const periodicPayment = loanProperites.periodicPayment; @@ -1137,72 +982,52 @@ class LendingHelpers_test : public beast::unit_test::suite // overpayment interest portion first, so interest paid remains 4.5 BEAST_EXPECTS( (actualPaymentParts.interestPaid == Number{45, -1}), - " interestPaid mismatch: expected 4.5, got " + - to_string(actualPaymentParts.interestPaid)); + " interestPaid mismatch: expected 4.5, got " + to_string(actualPaymentParts.interestPaid)); // With overpayment interest portion, value change should equal the // interest decrease plus overpayment interest portion BEAST_EXPECTS( - (actualPaymentParts.valueChange == - Number{-18533, -4} + actualPaymentParts.interestPaid), - " valueChange mismatch: expected " + - to_string( - Number{-18533, -4} + actualPaymentParts.interestPaid) + + (actualPaymentParts.valueChange == Number{-18533, -4} + actualPaymentParts.interestPaid), + " valueChange mismatch: expected " + to_string(Number{-18533, -4} + actualPaymentParts.interestPaid) + ", got " + to_string(actualPaymentParts.valueChange)); // While there is no overpayment fee, fee paid should equal the // management fee charged against the overpayment interest portion BEAST_EXPECTS( (actualPaymentParts.feePaid == Number{5, -1}), - " feePaid mismatch: expected 0.5, got " + - to_string(actualPaymentParts.feePaid)); + " feePaid mismatch: expected 0.5, got " + to_string(actualPaymentParts.feePaid)); BEAST_EXPECTS( actualPaymentParts.principalPaid == 45, - " principalPaid mismatch: expected 45, got `" + - to_string(actualPaymentParts.principalPaid)); + " principalPaid mismatch: expected 45, got `" + to_string(actualPaymentParts.principalPaid)); // =========== VALIDATE STATE CHANGES =========== BEAST_EXPECTS( actualPaymentParts.principalPaid == - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding, + loanProperites.loanState.principalOutstanding - newState.principalOutstanding, " principalPaid mismatch: expected " + - to_string( - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding) + - ", got " + to_string(actualPaymentParts.principalPaid)); + to_string(loanProperites.loanState.principalOutstanding - newState.principalOutstanding) + ", got " + + to_string(actualPaymentParts.principalPaid)); // Note that the management fee value change is not captured, as this // value is not needed to correctly update the Vault state. BEAST_EXPECTS( - (newState.managementFeeDue - - loanProperites.loanState.managementFeeDue == - Number{-20592, -5}), - " management fee change mismatch: expected " + - to_string(Number{-20592, -5}) + ", got " + - to_string( - newState.managementFeeDue - - loanProperites.loanState.managementFeeDue)); + (newState.managementFeeDue - loanProperites.loanState.managementFeeDue == Number{-20592, -5}), + " management fee change mismatch: expected " + to_string(Number{-20592, -5}) + ", got " + + to_string(newState.managementFeeDue - loanProperites.loanState.managementFeeDue)); BEAST_EXPECTS( actualPaymentParts.valueChange - actualPaymentParts.interestPaid == newState.interestDue - loanProperites.loanState.interestDue, " valueChange mismatch: expected " + - to_string( - newState.interestDue - - loanProperites.loanState.interestDue) + - ", got " + - to_string( - actualPaymentParts.valueChange - - actualPaymentParts.interestPaid)); + to_string(newState.interestDue - loanProperites.loanState.interestDue) + ", got " + + to_string(actualPaymentParts.valueChange - actualPaymentParts.interestPaid)); } void testTryOverpaymentLoanInterestFeeOverpaymentInterestFee() { - testcase( - "tryOverpayment - Loan Interest, Fee, Overpayment Interest, Fee"); + testcase("tryOverpayment - Loan Interest, Fee, Overpayment Interest, Fee"); using namespace jtx; using namespace xrpl::detail; @@ -1216,26 +1041,18 @@ class LendingHelpers_test : public beast::unit_test::suite Number const loanPrincipal{1'000}; std::uint32_t const paymentInterval = 30 * 24 * 60 * 60; std::uint32_t const paymentsRemaining = 10; - auto const periodicRate = - loanPeriodicRate(loanInterestRate, paymentInterval); + auto const periodicRate = loanPeriodicRate(loanInterestRate, paymentInterval); - ExtendedPaymentComponents const overpaymentComponents = - computeOverpaymentComponents( - asset, - loanScale, - Number{50, 0}, - TenthBips32(10'000), // 10% overpayment interest - TenthBips32(10'000), // 10% overpayment fee - managementFeeRate); + ExtendedPaymentComponents const overpaymentComponents = computeOverpaymentComponents( + asset, + loanScale, + Number{50, 0}, + TenthBips32(10'000), // 10% overpayment interest + TenthBips32(10'000), // 10% overpayment fee + managementFeeRate); auto const loanProperites = computeLoanProperties( - asset, - loanPrincipal, - loanInterestRate, - paymentInterval, - paymentsRemaining, - managementFeeRate, - loanScale); + asset, loanPrincipal, loanInterestRate, paymentInterval, paymentsRemaining, managementFeeRate, loanScale); Number const periodicPayment = loanProperites.periodicPayment; @@ -1261,66 +1078,47 @@ class LendingHelpers_test : public beast::unit_test::suite // overpayment interest portion first, so interest paid remains 4.5 BEAST_EXPECTS( (actualPaymentParts.interestPaid == Number{45, -1}), - " interestPaid mismatch: expected 4.5, got " + - to_string(actualPaymentParts.interestPaid)); + " interestPaid mismatch: expected 4.5, got " + to_string(actualPaymentParts.interestPaid)); // With overpayment interest portion, value change should equal the // interest decrease plus overpayment interest portion BEAST_EXPECTS( - (actualPaymentParts.valueChange == - Number{-164737, -5} + actualPaymentParts.interestPaid), - " valueChange mismatch: expected " + - to_string( - Number{-164737, -5} + actualPaymentParts.interestPaid) + + (actualPaymentParts.valueChange == Number{-164737, -5} + actualPaymentParts.interestPaid), + " valueChange mismatch: expected " + to_string(Number{-164737, -5} + actualPaymentParts.interestPaid) + ", got " + to_string(actualPaymentParts.valueChange)); // While there is no overpayment fee, fee paid should equal the // management fee charged against the overpayment interest portion BEAST_EXPECTS( (actualPaymentParts.feePaid == Number{55, -1}), - " feePaid mismatch: expected 5.5, got " + - to_string(actualPaymentParts.feePaid)); + " feePaid mismatch: expected 5.5, got " + to_string(actualPaymentParts.feePaid)); BEAST_EXPECTS( actualPaymentParts.principalPaid == 40, - " principalPaid mismatch: expected 40, got `" + - to_string(actualPaymentParts.principalPaid)); + " principalPaid mismatch: expected 40, got `" + to_string(actualPaymentParts.principalPaid)); // =========== VALIDATE STATE CHANGES =========== BEAST_EXPECTS( actualPaymentParts.principalPaid == - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding, + loanProperites.loanState.principalOutstanding - newState.principalOutstanding, " principalPaid mismatch: expected " + - to_string( - loanProperites.loanState.principalOutstanding - - newState.principalOutstanding) + - ", got " + to_string(actualPaymentParts.principalPaid)); + to_string(loanProperites.loanState.principalOutstanding - newState.principalOutstanding) + ", got " + + to_string(actualPaymentParts.principalPaid)); // Note that the management fee value change is not captured, as this // value is not needed to correctly update the Vault state. BEAST_EXPECTS( - (newState.managementFeeDue - - loanProperites.loanState.managementFeeDue == - Number{-18304, -5}), - " management fee change mismatch: expected " + - to_string(Number{-18304, -5}) + ", got " + - to_string( - newState.managementFeeDue - - loanProperites.loanState.managementFeeDue)); + (newState.managementFeeDue - loanProperites.loanState.managementFeeDue == Number{-18304, -5}), + " management fee change mismatch: expected " + to_string(Number{-18304, -5}) + ", got " + + to_string(newState.managementFeeDue - loanProperites.loanState.managementFeeDue)); BEAST_EXPECTS( actualPaymentParts.valueChange - actualPaymentParts.interestPaid == newState.interestDue - loanProperites.loanState.interestDue, " valueChange mismatch: expected " + - to_string( - newState.interestDue - - loanProperites.loanState.interestDue) + - ", got " + - to_string( - actualPaymentParts.valueChange - - actualPaymentParts.interestPaid)); + to_string(newState.interestDue - loanProperites.loanState.interestDue) + ", got " + + to_string(actualPaymentParts.valueChange - actualPaymentParts.interestPaid)); } public: diff --git a/src/test/app/LoadFeeTrack_test.cpp b/src/test/app/LoadFeeTrack_test.cpp index e0638b64bc..61174fc9e9 100644 --- a/src/test/app/LoadFeeTrack_test.cpp +++ b/src/test/app/LoadFeeTrack_test.cpp @@ -23,13 +23,9 @@ public: return f; }(); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{0}, l, fees, false) == XRPAmount{0}); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{10000}, l, fees, false) == - XRPAmount{10000}); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{1}, l, fees, false) == XRPAmount{1}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{0}, l, fees, false) == XRPAmount{0}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{10000}, l, fees, false) == XRPAmount{10000}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{1}, l, fees, false) == XRPAmount{1}); } { Fees const fees = [&]() { @@ -40,13 +36,9 @@ public: return f; }(); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{0}, l, fees, false) == XRPAmount{0}); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{10000}, l, fees, false) == - XRPAmount{10000}); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{1}, l, fees, false) == XRPAmount{1}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{0}, l, fees, false) == XRPAmount{0}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{10000}, l, fees, false) == XRPAmount{10000}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{1}, l, fees, false) == XRPAmount{1}); } { Fees const fees = [&]() { @@ -57,13 +49,9 @@ public: return f; }(); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{0}, l, fees, false) == XRPAmount{0}); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{10000}, l, fees, false) == - XRPAmount{10000}); - BEAST_EXPECT( - scaleFeeLoad(XRPAmount{1}, l, fees, false) == XRPAmount{1}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{0}, l, fees, false) == XRPAmount{0}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{10000}, l, fees, false) == XRPAmount{10000}); + BEAST_EXPECT(scaleFeeLoad(XRPAmount{1}, l, fees, false) == XRPAmount{1}); } } }; diff --git a/src/test/app/LoanBroker_test.cpp b/src/test/app/LoanBroker_test.cpp index 769ed40321..139350a881 100644 --- a/src/test/app/LoanBroker_test.cpp +++ b/src/test/app/LoanBroker_test.cpp @@ -12,8 +12,7 @@ class LoanBroker_test : public beast::unit_test::suite // Ensure that all the features needed for Lending Protocol are included, // even if they are set to unsupported. FeatureBitset const all{ - jtx::testable_amendments() | featureMPTokensV1 | - featureSingleAssetVault | featureLendingProtocol}; + jtx::testable_amendments() | featureMPTokensV1 | featureSingleAssetVault | featureLendingProtocol}; void testDisabled() @@ -33,8 +32,7 @@ class LoanBroker_test : public beast::unit_test::suite // Try to create a vault PrettyAsset const asset{xrpIssue(), 1'000'000}; Vault vault{env}; - auto const [tx, keylet] = - vault.create({.owner = alice, .asset = asset}); + auto const [tx, keylet] = vault.create({.owner = alice, .asset = asset}); env(tx, ter(goodVault ? ter(tesSUCCESS) : ter(temDISABLED))); env.close(); BEAST_EXPECT(static_cast(env.le(keylet)) == goodVault); @@ -42,25 +40,17 @@ class LoanBroker_test : public beast::unit_test::suite using namespace loanBroker; // Can't create a loan broker regardless of whether the vault exists env(set(alice, keylet.key), ter(temDISABLED)); - auto const brokerKeylet = - keylet::loanbroker(alice.id(), env.seq(alice)); + auto const brokerKeylet = keylet::loanbroker(alice.id(), env.seq(alice)); // Other LoanBroker transactions are disabled, too. // 1. LoanBrokerCoverDeposit - env(coverDeposit(alice, brokerKeylet.key, asset(1000)), - ter(temDISABLED)); + env(coverDeposit(alice, brokerKeylet.key, asset(1000)), ter(temDISABLED)); // 2. LoanBrokerCoverWithdraw - env(coverWithdraw(alice, brokerKeylet.key, asset(1000)), - ter(temDISABLED)); + env(coverWithdraw(alice, brokerKeylet.key, asset(1000)), ter(temDISABLED)); // 3. LoanBrokerCoverClawback env(coverClawback(alice), ter(temDISABLED)); - env(coverClawback(alice), - loanBrokerID(brokerKeylet.key), - ter(temDISABLED)); + env(coverClawback(alice), loanBrokerID(brokerKeylet.key), ter(temDISABLED)); env(coverClawback(alice), amount(asset(0)), ter(temDISABLED)); - env(coverClawback(alice), - loanBrokerID(brokerKeylet.key), - amount(asset(1000)), - ter(temDISABLED)); + env(coverClawback(alice), loanBrokerID(brokerKeylet.key), amount(asset(1000)), ter(temDISABLED)); // 4. LoanBrokerDelete env(del(alice, brokerKeylet.key), ter(temDISABLED)); }; @@ -75,10 +65,7 @@ class LoanBroker_test : public beast::unit_test::suite jtx::PrettyAsset asset; uint256 vaultID; jtx::Account pseudoAccount; - VaultInfo( - jtx::PrettyAsset const& asset_, - uint256 const& vaultID_, - AccountID const& pseudo) + VaultInfo(jtx::PrettyAsset const& asset_, uint256 const& vaultID_, AccountID const& pseudo) : asset(asset_), vaultID(vaultID_), pseudoAccount("vault", pseudo) { } @@ -115,8 +102,7 @@ class LoanBroker_test : public beast::unit_test::suite // Bogus assets to use in test cases static PrettyAsset const badMptAsset = [&]() { MPTTester badMptt{env, evan, mptInitNoFund}; - badMptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + badMptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); env.close(); return badMptt["BAD"]; }(); @@ -172,8 +158,7 @@ class LoanBroker_test : public beast::unit_test::suite // std::endl; // } // Load the pseudo-account - Account const pseudoAccount{ - "Broker pseudo-account", broker->at(sfAccount)}; + Account const pseudoAccount{"Broker pseudo-account", broker->at(sfAccount)}; auto const pseudoKeylet = keylet::account(pseudoAccount); if (auto const pseudo = env.le(pseudoKeylet); BEAST_EXPECT(pseudo)) @@ -181,14 +166,10 @@ class LoanBroker_test : public beast::unit_test::suite // log << "Pseudo-account after create: " // << to_string(pseudo->getJson()) << std::endl // << std::endl; - BEAST_EXPECT( - pseudo->at(sfFlags) == - (lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth)); + BEAST_EXPECT(pseudo->at(sfFlags) == (lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth)); BEAST_EXPECT(pseudo->at(sfSequence) == 0); BEAST_EXPECT(pseudo->at(sfBalance) == beast::zero); - BEAST_EXPECT( - pseudo->at(sfOwnerCount) == - (vault.asset.raw().native() ? 0 : 1)); + BEAST_EXPECT(pseudo->at(sfOwnerCount) == (vault.asset.raw().native() ? 0 : 1)); BEAST_EXPECT(!pseudo->isFieldPresent(sfAccountTxnID)); BEAST_EXPECT(!pseudo->isFieldPresent(sfRegularKey)); BEAST_EXPECT(!pseudo->isFieldPresent(sfEmailHash)); @@ -214,17 +195,13 @@ class LoanBroker_test : public beast::unit_test::suite auto const accountInfo = env.rpc("account_info", pseudoStr); if (BEAST_EXPECT(accountInfo.isObject())) { - auto const& accountData = - accountInfo[jss::result][jss::account_data]; + auto const& accountData = accountInfo[jss::result][jss::account_data]; if (BEAST_EXPECT(accountData.isObject())) { BEAST_EXPECT(accountData[jss::Account] == pseudoStr); - BEAST_EXPECT( - accountData[sfLoanBrokerID] == - to_string(keylet.key)); + BEAST_EXPECT(accountData[sfLoanBrokerID] == to_string(keylet.key)); } - auto const& pseudoInfo = - accountInfo[jss::result][jss::pseudo_account]; + auto const& pseudoInfo = accountInfo[jss::result][jss::pseudo_account]; if (BEAST_EXPECT(pseudoInfo.isObject())) { BEAST_EXPECT(pseudoInfo[jss::type] == "LoanBroker"); @@ -232,58 +209,41 @@ class LoanBroker_test : public beast::unit_test::suite } } - auto verifyCoverAmount = - [&env, &vault, &pseudoAccount, &broker, &keylet, this](auto n) { - using namespace jtx; + auto verifyCoverAmount = [&env, &vault, &pseudoAccount, &broker, &keylet, this](auto n) { + using namespace jtx; - if (BEAST_EXPECT(broker = env.le(keylet))) - { - auto const amount = vault.asset(n); - BEAST_EXPECT( - broker->at(sfCoverAvailable) == amount.number()); - env.require(balance(pseudoAccount, amount)); - } - }; + if (BEAST_EXPECT(broker = env.le(keylet))) + { + auto const amount = vault.asset(n); + BEAST_EXPECT(broker->at(sfCoverAvailable) == amount.number()); + env.require(balance(pseudoAccount, amount)); + } + }; // Test Cover funding before allowing alterations - env(coverDeposit(alice, uint256(0), vault.asset(10)), - ter(temINVALID)); - env(coverDeposit(evan, keylet.key, vault.asset(10)), - ter(tecNO_PERMISSION)); - env(coverDeposit(evan, keylet.key, vault.asset(0)), - ter(temBAD_AMOUNT)); - env(coverDeposit(evan, keylet.key, vault.asset(-10)), - ter(temBAD_AMOUNT)); - env(coverDeposit(alice, vault.vaultID, vault.asset(10)), - ter(tecNO_ENTRY)); + env(coverDeposit(alice, uint256(0), vault.asset(10)), ter(temINVALID)); + env(coverDeposit(evan, keylet.key, vault.asset(10)), ter(tecNO_PERMISSION)); + env(coverDeposit(evan, keylet.key, vault.asset(0)), ter(temBAD_AMOUNT)); + env(coverDeposit(evan, keylet.key, vault.asset(-10)), ter(temBAD_AMOUNT)); + env(coverDeposit(alice, vault.vaultID, vault.asset(10)), ter(tecNO_ENTRY)); verifyCoverAmount(0); // Test cover clawback failure cases BEFORE depositing any cover // Need one of brokerID or amount env(coverClawback(alice), ter(temINVALID)); - env(coverClawback(alice), - loanBrokerID(uint256(0)), - ter(temINVALID)); + env(coverClawback(alice), loanBrokerID(uint256(0)), ter(temINVALID)); env(coverClawback(alice), amount(XRP(1000)), ter(temBAD_AMOUNT)); - env(coverClawback(alice), - amount(vault.asset(-10)), - ter(temBAD_AMOUNT)); + env(coverClawback(alice), amount(vault.asset(-10)), ter(temBAD_AMOUNT)); // Clawbacks with an MPT need to specify the broker ID env(coverClawback(alice), amount(badMptAsset(1)), ter(temINVALID)); - env(coverClawback(evan), - loanBrokerID(vault.vaultID), - ter(tecNO_ENTRY)); + env(coverClawback(evan), loanBrokerID(vault.vaultID), ter(tecNO_ENTRY)); // Only the issuer can clawback - env(coverClawback(alice), - loanBrokerID(keylet.key), - ter(tecNO_PERMISSION)); + env(coverClawback(alice), loanBrokerID(keylet.key), ter(tecNO_PERMISSION)); if (vault.asset.raw().native()) { // Can not clawback XRP under any circumstances - env(coverClawback(issuer), - loanBrokerID(keylet.key), - ter(tecNO_PERMISSION)); + env(coverClawback(issuer), loanBrokerID(keylet.key), ter(tecNO_PERMISSION)); } else { @@ -291,24 +251,17 @@ class LoanBroker_test : public beast::unit_test::suite { // Clawbacks without a loanBrokerID need to specify an IOU // with the broker's pseudo-account as the issuer - env(coverClawback(alice), - amount(ghostIouAsset(1)), - ter(tecNO_ENTRY)); - env(coverClawback(alice), - amount(badIouAsset(1)), - ter(tecOBJECT_NOT_FOUND)); + env(coverClawback(alice), amount(ghostIouAsset(1)), ter(tecNO_ENTRY)); + env(coverClawback(alice), amount(badIouAsset(1)), ter(tecOBJECT_NOT_FOUND)); // Pseudo-account is not for a broker - env(coverClawback(alice), - amount(vaultPseudoIouAsset(1)), - ter(tecOBJECT_NOT_FOUND)); + env(coverClawback(alice), amount(vaultPseudoIouAsset(1)), ter(tecOBJECT_NOT_FOUND)); // If we specify a pseudo-account as the IOU amount, it // needs to match the loan broker env(coverClawback(issuer), loanBrokerID(keylet.key), amount(badBrokerPseudoIouAsset(10)), ter(tecWRONG_ASSET)); - PrettyAsset const brokerWrongCurrencyAsset = - pseudoAccount["WAT"]; + PrettyAsset const brokerWrongCurrencyAsset = pseudoAccount["WAT"]; env(coverClawback(issuer), loanBrokerID(keylet.key), amount(brokerWrongCurrencyAsset(10)), @@ -319,9 +272,7 @@ class LoanBroker_test : public beast::unit_test::suite // Clawbacks with an MPT need to specify the broker ID, even // if the asset is valid BEAST_EXPECT(vault.asset.raw().holds()); - env(coverClawback(alice), - amount(vault.asset(10)), - ter(temINVALID)); + env(coverClawback(alice), amount(vault.asset(10)), ter(temINVALID)); } // Since no cover has been deposited, there's nothing to claw // back @@ -338,34 +289,22 @@ class LoanBroker_test : public beast::unit_test::suite verifyCoverAmount(10); // Test withdrawal failure cases - env(coverWithdraw(alice, uint256(0), vault.asset(10)), - ter(temINVALID)); - env(coverWithdraw(evan, keylet.key, vault.asset(10)), - ter(tecNO_PERMISSION)); - env(coverWithdraw(evan, keylet.key, vault.asset(0)), - ter(temBAD_AMOUNT)); - env(coverWithdraw(evan, keylet.key, vault.asset(-10)), - ter(temBAD_AMOUNT)); - env(coverWithdraw(alice, vault.vaultID, vault.asset(10)), - ter(tecNO_ENTRY)); - env(coverWithdraw(alice, keylet.key, vault.asset(900)), - ter(tecINSUFFICIENT_FUNDS)); + env(coverWithdraw(alice, uint256(0), vault.asset(10)), ter(temINVALID)); + env(coverWithdraw(evan, keylet.key, vault.asset(10)), ter(tecNO_PERMISSION)); + env(coverWithdraw(evan, keylet.key, vault.asset(0)), ter(temBAD_AMOUNT)); + env(coverWithdraw(evan, keylet.key, vault.asset(-10)), ter(temBAD_AMOUNT)); + env(coverWithdraw(alice, vault.vaultID, vault.asset(10)), ter(tecNO_ENTRY)); + env(coverWithdraw(alice, keylet.key, vault.asset(900)), ter(tecINSUFFICIENT_FUNDS)); // Skip this test for XRP, because that can always be sent if (!vault.asset.raw().native()) { - TER const expected = vault.asset.raw().holds() - ? tecNO_AUTH - : tecNO_LINE; - env(coverWithdraw(alice, keylet.key, vault.asset(1)), - destination(bystander), - ter(expected)); + TER const expected = vault.asset.raw().holds() ? tecNO_AUTH : tecNO_LINE; + env(coverWithdraw(alice, keylet.key, vault.asset(1)), destination(bystander), ter(expected)); } // Can not withdraw to the zero address - env(coverWithdraw(alice, keylet.key, vault.asset(1)), - destination(AccountID{}), - ter(temMALFORMED)); + env(coverWithdraw(alice, keylet.key, vault.asset(1)), destination(AccountID{}), ter(temMALFORMED)); // Withdraw some of the cover amount env(coverWithdraw(alice, keylet.key, vault.asset(7))); @@ -379,25 +318,20 @@ class LoanBroker_test : public beast::unit_test::suite // Withdraw some more. Send it to Evan. Very generous, considering // how much trouble he's been. - env(coverWithdraw(alice, keylet.key, vault.asset(1)), - destination(evan)); + env(coverWithdraw(alice, keylet.key, vault.asset(1)), destination(evan)); env.close(); verifyCoverAmount(7); // Withdraw some more. Send it to Evan. Very generous, considering // how much trouble he's been. - env(coverWithdraw(alice, keylet.key, vault.asset(1)), - destination(evan), - dtag(3)); + env(coverWithdraw(alice, keylet.key, vault.asset(1)), destination(evan), dtag(3)); env.close(); verifyCoverAmount(6); if (!vault.asset.raw().native()) { // Issuer claws back some of the cover - env(coverClawback(issuer), - loanBrokerID(keylet.key), - amount(vault.asset(2))); + env(coverClawback(issuer), loanBrokerID(keylet.key), amount(vault.asset(2))); env.close(); verifyCoverAmount(4); @@ -409,12 +343,7 @@ class LoanBroker_test : public beast::unit_test::suite // Issuer claws it all back in various different ways for (auto const& tx : { // defer autofills until submission time - env.json( - coverClawback(issuer), - loanBrokerID(keylet.key), - fee(none), - seq(none), - sig(none)), + env.json(coverClawback(issuer), loanBrokerID(keylet.key), fee(none), seq(none), sig(none)), env.json( coverClawback(issuer), loanBrokerID(keylet.key), @@ -468,10 +397,7 @@ class LoanBroker_test : public beast::unit_test::suite // Verify that fields get removed when set to default values // Debt maximum: explicit 0 // Data: explicit empty - env(set(alice, vault.vaultID), - loanBrokerID(broker->key()), - debtMaximum(Number(0)), - data("")); + env(set(alice, vault.vaultID), loanBrokerID(broker->key()), debtMaximum(Number(0)), data("")); env.close(); // Check the updated fields @@ -519,9 +445,7 @@ class LoanBroker_test : public beast::unit_test::suite BEAST_EXPECT(!pseudo); } auto const expectedBalance = aliceBalance + coverFunds - - (aliceBalance.value().native() - ? STAmount(env.current()->fees().base.value()) - : vault.asset(0)); + (aliceBalance.value().native() ? STAmount(env.current()->fees().base.value()) : vault.asset(0)); env.require(balance(alice, expectedBalance)); env.require(balance(pseudoAccount, vault.asset(none))); } @@ -566,8 +490,7 @@ class LoanBroker_test : public beast::unit_test::suite env.close(); MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); env.close(); PrettyAsset const mptAsset = mptt["MPT"]; mptt.authorize({.account = alice}); @@ -591,13 +514,11 @@ class LoanBroker_test : public beast::unit_test::suite vaults.emplace_back(asset, keylet.key, le->at(sfAccount)); } - env(vault.deposit( - {.depositor = alice, .id = keylet.key, .amount = asset(50)})); + env(vault.deposit({.depositor = alice, .id = keylet.key, .amount = asset(50)})); env.close(); } VaultInfo const badVault = [&]() -> VaultInfo { - auto [tx, keylet] = - vault.create({.owner = alice, .asset = iouAsset}); + auto [tx, keylet] = vault.create({.owner = alice, .asset = iouAsset}); env(tx); env.close(); if (auto const le = env.le(keylet); BEAST_EXPECT(env.le(keylet))) @@ -615,21 +536,17 @@ class LoanBroker_test : public beast::unit_test::suite { { // Get the AccountInfo RPC result for the vault pseudo-account - std::string const pseudoStr = - to_string(vault.pseudoAccount.id()); + std::string const pseudoStr = to_string(vault.pseudoAccount.id()); auto const accountInfo = env.rpc("account_info", pseudoStr); if (BEAST_EXPECT(accountInfo.isObject())) { - auto const& accountData = - accountInfo[jss::result][jss::account_data]; + auto const& accountData = accountInfo[jss::result][jss::account_data]; if (BEAST_EXPECT(accountData.isObject())) { BEAST_EXPECT(accountData[jss::Account] == pseudoStr); - BEAST_EXPECT( - accountData[sfVaultID] == to_string(vault.vaultID)); + BEAST_EXPECT(accountData[sfVaultID] == to_string(vault.vaultID)); } - auto const& pseudoInfo = - accountInfo[jss::result][jss::pseudo_account]; + auto const& pseudoInfo = accountInfo[jss::result][jss::pseudo_account]; if (BEAST_EXPECT(pseudoInfo.isObject())) { BEAST_EXPECT(pseudoInfo[jss::type] == "Vault"); @@ -652,21 +569,13 @@ class LoanBroker_test : public beast::unit_test::suite env(set(evan, vault.vaultID, ~tfUniversal), ter(temINVALID_FLAG)); // field length validation // sfData: good length, bad account - env(set(evan, vault.vaultID), - data(std::string(maxDataPayloadLength, 'X')), - ter(tecNO_PERMISSION)); + env(set(evan, vault.vaultID), data(std::string(maxDataPayloadLength, 'X')), ter(tecNO_PERMISSION)); // sfData: too long - env(set(evan, vault.vaultID), - data(std::string(maxDataPayloadLength + 1, 'Y')), - ter(temINVALID)); + env(set(evan, vault.vaultID), data(std::string(maxDataPayloadLength + 1, 'Y')), ter(temINVALID)); // sfManagementFeeRate: good value, bad account - env(set(evan, vault.vaultID), - managementFeeRate(maxManagementFeeRate), - ter(tecNO_PERMISSION)); + env(set(evan, vault.vaultID), managementFeeRate(maxManagementFeeRate), ter(tecNO_PERMISSION)); // sfManagementFeeRate: too big - env(set(evan, vault.vaultID), - managementFeeRate(maxManagementFeeRate + TenthBips16(10)), - ter(temINVALID)); + env(set(evan, vault.vaultID), managementFeeRate(maxManagementFeeRate + TenthBips16(10)), ter(temINVALID)); // sfCoverRateMinimum and sfCoverRateLiquidation are linked // Cover: good value, bad account env(set(evan, vault.vaultID), @@ -685,34 +594,24 @@ class LoanBroker_test : public beast::unit_test::suite ter(temINVALID)); // Cover: zero min, non-zero liquidation - implicit and // explicit zero values. - env(set(evan, vault.vaultID), - coverRateLiquidation(maxCoverRate), - ter(temINVALID)); + env(set(evan, vault.vaultID), coverRateLiquidation(maxCoverRate), ter(temINVALID)); env(set(evan, vault.vaultID), coverRateMinimum(tenthBipsZero), coverRateLiquidation(maxCoverRate), ter(temINVALID)); // Cover: non-zero min, zero liquidation - implicit and // explicit zero values. - env(set(evan, vault.vaultID), - coverRateMinimum(maxCoverRate), - ter(temINVALID)); + env(set(evan, vault.vaultID), coverRateMinimum(maxCoverRate), ter(temINVALID)); env(set(evan, vault.vaultID), coverRateMinimum(maxCoverRate), coverRateLiquidation(tenthBipsZero), ter(temINVALID)); // sfDebtMaximum: good value, bad account - env(set(evan, vault.vaultID), - debtMaximum(Number(0)), - ter(tecNO_PERMISSION)); + env(set(evan, vault.vaultID), debtMaximum(Number(0)), ter(tecNO_PERMISSION)); // sfDebtMaximum: overflow - env(set(evan, vault.vaultID), - debtMaximum(Number(1, 100)), - ter(temINVALID)); + env(set(evan, vault.vaultID), debtMaximum(Number(1, 100)), ter(temINVALID)); // sfDebtMaximum: negative - env(set(evan, vault.vaultID), - debtMaximum(Number(-1)), - ter(temINVALID)); + env(set(evan, vault.vaultID), debtMaximum(Number(-1)), ter(temINVALID)); std::string testData; lifecycle( @@ -730,40 +629,28 @@ class LoanBroker_test : public beast::unit_test::suite // Extra checks BEAST_EXPECT(!broker->isFieldPresent(sfManagementFeeRate)); BEAST_EXPECT(!broker->isFieldPresent(sfCoverRateMinimum)); - BEAST_EXPECT( - !broker->isFieldPresent(sfCoverRateLiquidation)); + BEAST_EXPECT(!broker->isFieldPresent(sfCoverRateLiquidation)); BEAST_EXPECT(!broker->isFieldPresent(sfData)); BEAST_EXPECT(!broker->isFieldPresent(sfDebtMaximum)); BEAST_EXPECT(broker->at(sfDebtMaximum) == 0); BEAST_EXPECT(broker->at(sfCoverRateMinimum) == 0); BEAST_EXPECT(broker->at(sfCoverRateLiquidation) == 0); - BEAST_EXPECT( - env.ownerCount(alice) == aliceOriginalCount + 4); + BEAST_EXPECT(env.ownerCount(alice) == aliceOriginalCount + 4); }, [&](SLE::const_ref broker) { // Modifications // Update the fields - auto const nextKeylet = - keylet::loanbroker(alice.id(), env.seq(alice)); + auto const nextKeylet = keylet::loanbroker(alice.id(), env.seq(alice)); // fields that can't be changed // LoanBrokerID - env(set(alice, vault.vaultID), - loanBrokerID(nextKeylet.key), - ter(tecNO_ENTRY), - THISLINE); + env(set(alice, vault.vaultID), loanBrokerID(nextKeylet.key), ter(tecNO_ENTRY), THISLINE); // VaultID - env(set(alice, nextKeylet.key), - loanBrokerID(broker->key()), - ter(tecNO_ENTRY), - THISLINE); + env(set(alice, nextKeylet.key), loanBrokerID(broker->key()), ter(tecNO_ENTRY), THISLINE); // Owner - env(set(evan, vault.vaultID), - loanBrokerID(broker->key()), - ter(tecNO_PERMISSION), - THISLINE); + env(set(evan, vault.vaultID), loanBrokerID(broker->key()), ter(tecNO_PERMISSION), THISLINE); // ManagementFeeRate env(set(alice, vault.vaultID), loanBrokerID(broker->key()), @@ -819,13 +706,10 @@ class LoanBroker_test : public beast::unit_test::suite [&](SLE::const_ref broker) { // Check the updated fields BEAST_EXPECT(checkVL(broker->at(sfData), testData)); - Number const expected = - STAmount{vault.asset, Number(175, -1)}; + Number const expected = STAmount{vault.asset, Number(175, -1)}; auto const actual = broker->at(sfDebtMaximum); BEAST_EXPECTS( - actual == expected, - "Expected: " + to_string(expected) + - ", Actual: " + to_string(actual)); + actual == expected, "Expected: " + to_string(expected) + ", Actual: " + to_string(actual)); }); lifecycle( @@ -859,10 +743,7 @@ class LoanBroker_test : public beast::unit_test::suite }, [&](SLE::const_ref broker) { // Reset Data & Debt maximum to default values - env(set(alice, vault.vaultID), - loanBrokerID(broker->key()), - data(""), - debtMaximum(Number(0))); + env(set(alice, vault.vaultID), loanBrokerID(broker->key()), data(""), debtMaximum(Number(0))); }, [&](SLE::const_ref broker) { // Check the updated fields @@ -874,20 +755,11 @@ class LoanBroker_test : public beast::unit_test::suite BEAST_EXPECT(env.ownerCount(alice) == aliceOriginalCount); } - enum LoanBrokerTest { - CoverClawback, - CoverDeposit, - CoverWithdraw, - Delete, - Set - }; + enum LoanBrokerTest { CoverClawback, CoverDeposit, CoverWithdraw, Delete, Set }; void testLoanBroker( - std::function getAsset, + std::function getAsset, LoanBrokerTest brokerTest) { using namespace jtx; @@ -923,15 +795,10 @@ class LoanBroker_test : public beast::unit_test::suite if (vaultInfo.vaultID == uint256{}) return; - env(vault.deposit( - {.depositor = alice, - .id = vaultKeylet.key, - .amount = asset(50)}), - THISLINE); + env(vault.deposit({.depositor = alice, .id = vaultKeylet.key, .amount = asset(50)}), THISLINE); env.close(); - auto const brokerKeylet = - keylet::loanbroker(alice.id(), env.seq(alice)); + auto const brokerKeylet = keylet::loanbroker(alice.id(), env.seq(alice)); env(set(alice, vaultInfo.vaultID), THISLINE); env.close(); @@ -965,91 +832,62 @@ class LoanBroker_test : public beast::unit_test::suite if (brokerTest == CoverDeposit) { // preflight: temINVALID (empty/zero broker id) - testZeroBrokerID([&]() { - return coverDeposit(alice, brokerKeylet.key, asset(10)); - }); + testZeroBrokerID([&]() { return coverDeposit(alice, brokerKeylet.key, asset(10)); }); // preclaim: tecWRONG_ASSET - env(coverDeposit(alice, brokerKeylet.key, issuer["BAD"](10)), - ter(tecWRONG_ASSET), - THISLINE); + env(coverDeposit(alice, brokerKeylet.key, issuer["BAD"](10)), ter(tecWRONG_ASSET), THISLINE); // preclaim: tecINSUFFICIENT_FUNDS env(pay(alice, issuer, asset(100'000 - 50)), THISLINE); env.close(); - env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), - ter(tecINSUFFICIENT_FUNDS)); + env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), ter(tecINSUFFICIENT_FUNDS)); // preclaim: tecFROZEN env(fset(issuer, asfGlobalFreeze), THISLINE); env.close(); - env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), - ter(tecFROZEN), - THISLINE); + env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), ter(tecFROZEN), THISLINE); } else // Fund the cover deposit - env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), - THISLINE); + env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), THISLINE); env.close(); if (brokerTest == CoverWithdraw) { // preflight: temINVALID (empty/zero broker id) - testZeroBrokerID([&]() { - return coverWithdraw(alice, brokerKeylet.key, asset(10)); - }); + testZeroBrokerID([&]() { return coverWithdraw(alice, brokerKeylet.key, asset(10)); }); // preclaim: tecWRONG_ASSET - env(coverWithdraw(alice, brokerKeylet.key, issuer["BAD"](10)), - ter(tecWRONG_ASSET), - THISLINE); + env(coverWithdraw(alice, brokerKeylet.key, issuer["BAD"](10)), ter(tecWRONG_ASSET), THISLINE); // preclaim: tecNO_DST Account const bogus{"bogus"}; - env(coverWithdraw(alice, brokerKeylet.key, asset(10)), - destination(bogus), - ter(tecNO_DST), - THISLINE); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), destination(bogus), ter(tecNO_DST), THISLINE); // preclaim: tecDST_TAG_NEEDED Account const dest{"dest"}; env.fund(XRP(1'000), dest); env(fset(dest, asfRequireDest), THISLINE); env.close(); - env(coverWithdraw(alice, brokerKeylet.key, asset(10)), - destination(dest), - ter(tecDST_TAG_NEEDED), - THISLINE); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), destination(dest), ter(tecDST_TAG_NEEDED), THISLINE); // preclaim: tecNO_PERMISSION env(fclear(dest, asfRequireDest), THISLINE); env(fset(dest, asfDepositAuth), THISLINE); env.close(); - env(coverWithdraw(alice, brokerKeylet.key, asset(10)), - destination(dest), - ter(tecNO_PERMISSION), - THISLINE); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), destination(dest), ter(tecNO_PERMISSION), THISLINE); // preclaim: tecFROZEN env(trust(dest, asset(1'000)), THISLINE); env(fclear(dest, asfDepositAuth), THISLINE); env(fset(issuer, asfGlobalFreeze), THISLINE); env.close(); - env(coverWithdraw(alice, brokerKeylet.key, asset(10)), - destination(dest), - ter(tecFROZEN), - THISLINE); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), destination(dest), ter(tecFROZEN), THISLINE); // preclaim:: tecFROZEN (deep frozen) env(fclear(issuer, asfGlobalFreeze), THISLINE); - env(trust( - issuer, asset(1'000), dest, tfSetFreeze | tfSetDeepFreeze), - THISLINE); - env(coverWithdraw(alice, brokerKeylet.key, asset(10)), - destination(dest), - ter(tecFROZEN), - THISLINE); + env(trust(issuer, asset(1'000), dest, tfSetFreeze | tfSetDeepFreeze), THISLINE); + env(coverWithdraw(alice, brokerKeylet.key, asset(10)), destination(dest), ter(tecFROZEN), THISLINE); // preclaim: tecPSEUDO_ACCOUNT env(coverWithdraw(alice, brokerKeylet.key, asset(10)), @@ -1062,10 +900,7 @@ class LoanBroker_test : public beast::unit_test::suite { // preflight: temINVALID (empty/zero broker id) testZeroBrokerID([&]() { - return env.json( - coverClawback(alice), - loanBrokerID(brokerKeylet.key), - amount(vaultInfo.asset(2))); + return env.json(coverClawback(alice), loanBrokerID(brokerKeylet.key), amount(vaultInfo.asset(2))); }); if (asset.holds()) @@ -1078,8 +913,7 @@ class LoanBroker_test : public beast::unit_test::suite THISLINE); // preclaim: NoFreeze is set - env(fset(issuer, asfAllowTrustLineClawback | asfNoFreeze), - THISLINE); + env(fset(issuer, asfAllowTrustLineClawback | asfNoFreeze), THISLINE); env.close(); env(coverClawback(issuer), loanBrokerID(brokerKeylet.key), @@ -1112,23 +946,17 @@ class LoanBroker_test : public beast::unit_test::suite testZeroBrokerID([&]() { return del(alice, brokerKeylet.key); }); // preclaim: tecHAS_OBLIGATIONS - env(del(alice, brokerKeylet.key), - ter(tecHAS_OBLIGATIONS), - THISLINE); + env(del(alice, brokerKeylet.key), ter(tecHAS_OBLIGATIONS), THISLINE); // Repay and delete the loan auto const loanKeylet = keylet::loan(brokerKeylet.key, 1); - env(loan::pay(borrower, loanKeylet.key, asset(50).value()), - THISLINE); + env(loan::pay(borrower, loanKeylet.key, asset(50).value()), THISLINE); env(loan::del(alice, loanKeylet.key), THISLINE); - env(trust(issuer, asset(0), alice, tfSetFreeze | tfSetDeepFreeze), - THISLINE); + env(trust(issuer, asset(0), alice, tfSetFreeze | tfSetDeepFreeze), THISLINE); // preclaim: tecFROZEN (deep frozen) env(del(alice, brokerKeylet.key), ter(tecFROZEN), THISLINE); - env(trust( - issuer, asset(0), alice, tfClearFreeze | tfClearDeepFreeze), - THISLINE); + env(trust(issuer, asset(0), alice, tfClearFreeze | tfClearDeepFreeze), THISLINE); // successful delete the loan broker object env(del(alice, brokerKeylet.key), ter(tesSUCCESS), THISLINE); @@ -1139,17 +967,9 @@ class LoanBroker_test : public beast::unit_test::suite if (brokerTest == Set) { // preflight: temINVALID (empty/zero broker id) - testZeroBrokerID([&]() { - return env.json( - set(alice, vaultInfo.vaultID), - loanBrokerID(brokerKeylet.key)); - }); + testZeroBrokerID([&]() { return env.json(set(alice, vaultInfo.vaultID), loanBrokerID(brokerKeylet.key)); }); // preflight: temINVALID (empty/zero vault id) - testZeroVaultID([&]() { - return env.json( - set(alice, vaultInfo.vaultID), - loanBrokerID(brokerKeylet.key)); - }); + testZeroVaultID([&]() { return env.json(set(alice, vaultInfo.vaultID), loanBrokerID(brokerKeylet.key)); }); if (asset.holds()) { @@ -1162,14 +982,11 @@ class LoanBroker_test : public beast::unit_test::suite env.close(); } - auto const amt = env.balance(alice) - - env.current()->fees().accountReserve(env.ownerCount(alice)); + auto const amt = env.balance(alice) - env.current()->fees().accountReserve(env.ownerCount(alice)); env(pay(alice, issuer, amt), THISLINE); // preclaim:: tecINSUFFICIENT_RESERVE - env(set(alice, vaultInfo.vaultID), - ter(tecINSUFFICIENT_RESERVE), - THISLINE); + env(set(alice, vaultInfo.vaultID), ter(tecINSUFFICIENT_RESERVE), THISLINE); } } @@ -1216,8 +1033,7 @@ class LoanBroker_test : public beast::unit_test::suite // MPTCanClawback is not set testLoanBroker( [&](Env& env, Account const& issuer, Account const& alice) -> MPT { - MPTTester mpt( - {.env = env, .issuer = issuer, .holders = {alice}}); + MPTTester mpt({.env = env, .issuer = issuer, .holders = {alice}}); return mpt; }, CoverClawback); @@ -1298,14 +1114,12 @@ class LoanBroker_test : public beast::unit_test::suite // Create a Vault owned by alice with an XRP asset PrettyAsset const asset{xrpIssue(), 1}; Vault vault{env}; - auto const [createTx, vaultKeylet] = - vault.create({.owner = alice, .asset = asset}); + auto const [createTx, vaultKeylet] = vault.create({.owner = alice, .asset = asset}); env(createTx); env.close(); // Predict LoanBroker key using alice's current sequence BEFORE submit - auto const brokerKeylet = - keylet::loanbroker(alice.id(), env.seq(alice)); + auto const brokerKeylet = keylet::loanbroker(alice.id(), env.seq(alice)); // Create LoanBroker pointing to the vault env(loanBroker::set(alice, vaultKeylet.key)); @@ -1322,17 +1136,9 @@ class LoanBroker_test : public beast::unit_test::suite OpenView ov{*env.current()}; test::StreamSink sink{beast::severities::kWarning}; beast::Journal jlog{sink}; - ApplyContext ac{ - env.app(), - ov, - tx, - tesSUCCESS, - env.current()->fees().base, - tapNONE, - jlog}; + ApplyContext ac{env.app(), ov, tx, tesSUCCESS, env.current()->fees().base, tapNONE, jlog}; - if (auto sleBroker = - ac.view().peek(keylet::loanbroker(brokerKeylet.key))) + if (auto sleBroker = ac.view().peek(keylet::loanbroker(brokerKeylet.key))) { auto const vaultID = (*sleBroker)[sfVaultID]; if (auto sleVault = ac.view().peek(keylet::vault(vaultID))) @@ -1343,8 +1149,7 @@ class LoanBroker_test : public beast::unit_test::suite // Invoke preclaim against the mutated (ApplyView) view; triggers // nullptr deref - PreclaimContext pctx{ - env.app(), ac.view(), tesSUCCESS, tx, tapNONE, jlog}; + PreclaimContext pctx{env.app(), ac.view(), tesSUCCESS, tx, tapNONE, jlog}; (void)LoanBrokerCoverDeposit::preclaim(pctx); } @@ -1367,8 +1172,7 @@ class LoanBroker_test : public beast::unit_test::suite .env = env, .issuer = issuer, .holders = {alice}, - .flags = MPTDEXFlags | tfMPTRequireAuth | tfMPTCanClawback | - tfMPTCanLock, + .flags = MPTDEXFlags | tfMPTRequireAuth | tfMPTCanClawback | tfMPTCanLock, .authHolder = true, }); @@ -1376,8 +1180,7 @@ class LoanBroker_test : public beast::unit_test::suite env.close(); // Alice is not authorized, can still create the vault - asset.authorize( - {.account = issuer, .holder = alice, .flags = tfMPTUnauthorize}); + asset.authorize({.account = issuer, .holder = alice, .flags = tfMPTUnauthorize}); auto [tx, vaultKeylet] = vault.create({.owner = alice, .asset = asset}); env(tx); env.close(); @@ -1393,16 +1196,12 @@ class LoanBroker_test : public beast::unit_test::suite // Can't unauthorize Vault pseudo-account asset.authorize( - {.account = issuer, - .holder = vaultInfo.pseudoAccount, - .flags = tfMPTUnauthorize, - .err = tecNO_PERMISSION}); + {.account = issuer, .holder = vaultInfo.pseudoAccount, .flags = tfMPTUnauthorize, .err = tecNO_PERMISSION}); auto forUnauthAuth = [&](auto&& doTx) { for (auto const flag : {tfMPTUnauthorize, 0u}) { - asset.authorize( - {.account = issuer, .holder = alice, .flags = flag}); + asset.authorize({.account = issuer, .holder = alice, .flags = flag}); env.close(); doTx(flag == 0); env.close(); @@ -1412,25 +1211,16 @@ class LoanBroker_test : public beast::unit_test::suite // Can't deposit into Vault if the vault owner is not authorized forUnauthAuth([&](bool authorized) { auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); - env(vault.deposit( - {.depositor = alice, - .id = vaultKeylet.key, - .amount = asset(51)}), - err); + env(vault.deposit({.depositor = alice, .id = vaultKeylet.key, .amount = asset(51)}), err); }); // Can't withdraw from Vault if the vault owner is not authorized forUnauthAuth([&](bool authorized) { auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); - env(vault.withdraw( - {.depositor = alice, - .id = vaultKeylet.key, - .amount = asset(1)}), - err); + env(vault.withdraw({.depositor = alice, .id = vaultKeylet.key, .amount = asset(1)}), err); }); - auto const brokerKeylet = - keylet::loanbroker(alice.id(), env.seq(alice)); + auto const brokerKeylet = keylet::loanbroker(alice.id(), env.seq(alice)); // Can create LoanBroker if the vault owner is not authorized forUnauthAuth([&](auto) { env(set(alice, vaultInfo.vaultID)); }); @@ -1441,31 +1231,23 @@ class LoanBroker_test : public beast::unit_test::suite // Can't unauthorize LoanBroker pseudo-account asset.authorize( - {.account = issuer, - .holder = brokerPseudo, - .flags = tfMPTUnauthorize, - .err = tecNO_PERMISSION}); + {.account = issuer, .holder = brokerPseudo, .flags = tfMPTUnauthorize, .err = tecNO_PERMISSION}); // Can't cover deposit into Vault if the vault owner is not authorized forUnauthAuth([&](bool authorized) { auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); - env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), - err); + env(coverDeposit(alice, brokerKeylet.key, vaultInfo.asset(10)), err); }); // Can't cover withdraw from Vault if the vault owner is not authorized forUnauthAuth([&](bool authorized) { auto const err = !authorized ? ter(tecNO_AUTH) : ter(tesSUCCESS); - env(coverWithdraw(alice, brokerKeylet.key, vaultInfo.asset(5)), - err); + env(coverWithdraw(alice, brokerKeylet.key, vaultInfo.asset(5)), err); }); // Issuer can always cover clawback. The holder authorization is n/a. - forUnauthAuth([&](bool) { - env(coverClawback(issuer), - loanBrokerID(brokerKeylet.key), - amount(vaultInfo.asset(1))); - }); + forUnauthAuth( + [&](bool) { env(coverClawback(issuer), loanBrokerID(brokerKeylet.key), amount(vaultInfo.asset(1))); }); } void @@ -1484,8 +1266,7 @@ class LoanBroker_test : public beast::unit_test::suite PrettyAsset const asset = [&]() { MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); env.close(); PrettyAsset const mptAsset = mptt["MPT"]; mptt.authorize({.account = alice}); @@ -1508,15 +1289,10 @@ class LoanBroker_test : public beast::unit_test::suite if (vaultInfo.vaultID == uint256{}) return; - env(vault.deposit( - {.depositor = alice, - .id = vaultKeylet.key, - .amount = asset(50)}), - THISLINE); + env(vault.deposit({.depositor = alice, .id = vaultKeylet.key, .amount = asset(50)}), THISLINE); env.close(); - auto const brokerKeylet = - keylet::loanbroker(alice.id(), env.seq(alice)); + auto const brokerKeylet = keylet::loanbroker(alice.id(), env.seq(alice)); env(set(alice, vaultInfo.vaultID), THISLINE); env.close(); @@ -1597,24 +1373,19 @@ class LoanBroker_test : public beast::unit_test::suite auto const [token, deposit, err] = getToken(env); Vault vault(env); - auto const [tx, keylet] = - vault.create({.owner = broker, .asset = token.asset()}); + auto const [tx, keylet] = vault.create({.owner = broker, .asset = token.asset()}); env(tx); env.close(); - env(vault.deposit( - {.depositor = broker, .id = keylet.key, .amount = deposit}), - ter(err)); + env(vault.deposit({.depositor = broker, .id = keylet.key, .amount = deposit}), ter(err)); env.close(); - auto const brokerKeylet = - keylet::loanbroker(broker, env.seq(broker)); + auto const brokerKeylet = keylet::loanbroker(broker, env.seq(broker)); env(loanBroker::set(broker, keylet.key)); env.close(); - env(loanBroker::coverDeposit(broker, brokerKeylet.key, deposit), - ter(err)); + env(loanBroker::coverDeposit(broker, brokerKeylet.key, deposit), ter(err)); env.close(); }; @@ -1672,8 +1443,7 @@ class LoanBroker_test : public beast::unit_test::suite auto const IOU = issuer["IOU"]; Vault vault{env}; - auto [tx, vaultKeylet] = - vault.create({.owner = lender, .asset = IOU.asset()}); + auto [tx, vaultKeylet] = vault.create({.owner = lender, .asset = IOU.asset()}); env(tx); env.close(); @@ -1706,8 +1476,7 @@ class LoanBroker_test : public beast::unit_test::suite auto test = [&](TrustState trustState) { Env env(*this); - testcase << "RIPD-4274 IOU with state: " - << static_cast(trustState); + testcase << "RIPD-4274 IOU with state: " << static_cast(trustState); auto setTrustLine = [&](Account const& acct, TrustState state) { switch (state) @@ -1762,41 +1531,29 @@ class LoanBroker_test : public beast::unit_test::suite env.close(); Vault vault(env); - auto const [tx, keylet] = - vault.create({.owner = broker, .asset = token.asset()}); + auto const [tx, keylet] = vault.create({.owner = broker, .asset = token.asset()}); env(tx); env.close(); // Test Vault withdraw - env(vault.deposit( - {.depositor = broker, - .id = keylet.key, - .amount = token(1'000)})); + env(vault.deposit({.depositor = broker, .id = keylet.key, .amount = token(1'000)})); env.close(); - env(vault.withdraw( - {.depositor = broker, - .id = keylet.key, - .amount = token(1'000)}), + env(vault.withdraw({.depositor = broker, .id = keylet.key, .amount = token(1'000)}), loanBroker::destination(dest), ter(std::ignore)); BEAST_EXPECT(env.ter() == tecNO_LINE); env.close(); - env(vault.withdraw( - {.depositor = broker, - .id = keylet.key, - .amount = token(1'000)})); + env(vault.withdraw({.depositor = broker, .id = keylet.key, .amount = token(1'000)})); // Test LoanBroker withdraw - auto const brokerKeylet = - keylet::loanbroker(broker, env.seq(broker)); + auto const brokerKeylet = keylet::loanbroker(broker, env.seq(broker)); env(loanBroker::set(broker, keylet.key)); env.close(); - env(loanBroker::coverDeposit( - broker, brokerKeylet.key, token(1'000))); + env(loanBroker::coverDeposit(broker, brokerKeylet.key, token(1'000))); env.close(); env(loanBroker::coverWithdraw(broker, brokerKeylet.key, token(100)), @@ -1811,8 +1568,7 @@ class LoanBroker_test : public beast::unit_test::suite env(fclear(issuer, asfRequireAuth)); env.close(); - env(loanBroker::coverWithdraw( - broker, brokerKeylet.key, token(100)), + env(loanBroker::coverWithdraw(broker, brokerKeylet.key, token(100)), loanBroker::destination(dest), ter(std::ignore)); BEAST_EXPECT(env.ter() == tecNO_LINE); @@ -1844,8 +1600,7 @@ class LoanBroker_test : public beast::unit_test::suite auto test = [&](MPTState MPTState) { Env env(*this); - testcase << "RIPD-4274 MPT with state: " - << static_cast(MPTState); + testcase << "RIPD-4274 MPT with state: " << static_cast(MPTState); env.fund(XRP(1'000), issuer, broker, dest); env.close(); @@ -1863,10 +1618,7 @@ class LoanBroker_test : public beast::unit_test::suite .authHolder = true, .maxAmt = 5'000}); // unauthorize dest - tester.authorize( - {.account = issuer, - .holder = dest, - .flags = tfMPTUnauthorize}); + tester.authorize({.account = issuer, .holder = dest, .flags = tfMPTUnauthorize}); return tester; } case ReachedMAX: { @@ -1877,8 +1629,7 @@ class LoanBroker_test : public beast::unit_test::suite .pay = 2'000, .flags = MPTDEXFlags, .maxAmt = 4'000}); - BEAST_EXPECT( - env.balance(issuer, tester) == tester(-4'000)); + BEAST_EXPECT(env.balance(issuer, tester) == tester(-4'000)); return tester; } case NoMPT: { @@ -1900,48 +1651,35 @@ class LoanBroker_test : public beast::unit_test::suite auto const& token = *maybeToken; Vault vault(env); - auto const [tx, keylet] = - vault.create({.owner = broker, .asset = token.asset()}); + auto const [tx, keylet] = vault.create({.owner = broker, .asset = token.asset()}); env(tx); env.close(); // Test Vault withdraw - env(vault.deposit( - {.depositor = broker, - .id = keylet.key, - .amount = token(1'000)})); + env(vault.deposit({.depositor = broker, .id = keylet.key, .amount = token(1'000)})); env.close(); - env(vault.withdraw( - {.depositor = broker, - .id = keylet.key, - .amount = token(1'000)}), + env(vault.withdraw({.depositor = broker, .id = keylet.key, .amount = token(1'000)}), loanBroker::destination(dest), ter(std::ignore)); // Shouldn't fail if at MaximumAmount since no new tokens are issued - TER const err = - MPTState == ReachedMAX ? TER(tesSUCCESS) : tecNO_AUTH; + TER const err = MPTState == ReachedMAX ? TER(tesSUCCESS) : tecNO_AUTH; BEAST_EXPECT(env.ter() == err); env.close(); if (err != tesSUCCESS) { - env(vault.withdraw( - {.depositor = broker, - .id = keylet.key, - .amount = token(1'000)})); + env(vault.withdraw({.depositor = broker, .id = keylet.key, .amount = token(1'000)})); } // Test LoanBroker withdraw - auto const brokerKeylet = - keylet::loanbroker(broker, env.seq(broker)); + auto const brokerKeylet = keylet::loanbroker(broker, env.seq(broker)); env(loanBroker::set(broker, keylet.key)); env.close(); - env(loanBroker::coverDeposit( - broker, brokerKeylet.key, token(1'000))); + env(loanBroker::coverDeposit(broker, brokerKeylet.key, token(1'000))); env.close(); env(loanBroker::coverWithdraw(broker, brokerKeylet.key, token(100)), diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index e9780211de..f02ceddb69 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -22,8 +22,7 @@ protected: // Ensure that all the features needed for Lending Protocol are included, // even if they are set to unsupported. FeatureBitset const all{ - jtx::testable_amendments() | featureMPTokensV1 | - featureSingleAssetVault | featureLendingProtocol}; + jtx::testable_amendments() | featureMPTokensV1 | featureSingleAssetVault | featureLendingProtocol}; std::string const iouCurrency{"IOU"}; @@ -50,14 +49,12 @@ protected: // counter party signature is optional on LoanSet. Confirm that by // sending transaction without one. - auto setTx = - env.jt(set(alice, keylet.key, Number(10000)), ter(temDISABLED)); + auto setTx = env.jt(set(alice, keylet.key, Number(10000)), ter(temDISABLED)); env(setTx); // All loan transactions are disabled. // 1. LoanSet - setTx = env.jt( - setTx, sig(sfCounterpartySignature, bob), ter(temDISABLED)); + setTx = env.jt(setTx, sig(sfCounterpartySignature, bob), ter(temDISABLED)); env(setTx); // Actual sequence will be based off the loan broker, but we // obviously don't have one of those if the amendment is disabled @@ -91,8 +88,7 @@ protected: maxCoveredLoanValue(Number const& currentDebt) const { NumberRoundModeGuard mg(Number::downward); - auto debtLimit = - coverDeposit * tenthBipsPerUnity.value() / coverRateMin.value(); + auto debtLimit = coverDeposit * tenthBipsPerUnity.value() / coverRateMin.value(); return debtLimit - currentDebt; } @@ -119,10 +115,7 @@ protected: Keylet const& brokerKeylet_, Keylet const& vaultKeylet_, BrokerParameters const& p) - : asset(asset_) - , brokerID(brokerKeylet_.key) - , vaultID(vaultKeylet_.key) - , params(p) + : asset(asset_), brokerID(brokerKeylet_.key), vaultID(vaultKeylet_.key), params(p) { } @@ -174,17 +167,12 @@ protected: template jtx::JTx - operator()(jtx::Env& env, BrokerInfo const& broker, FN const&... fN) - const + operator()(jtx::Env& env, BrokerInfo const& broker, FN const&... fN) const { using namespace jtx; using namespace jtx::loan; - JTx jt{loan::set( - account, - broker.brokerID, - broker.asset(principalRequest).number(), - flags.value_or(0))}; + JTx jt{loan::set(account, broker.brokerID, broker.asset(principalRequest).number(), flags.value_or(0))}; sig(sfCounterpartySignature, counter)(env, jt); @@ -193,8 +181,7 @@ protected: if (counterpartyExplicit) counterparty(counter)(env, jt); if (originationFee) - loanOriginationFee(broker.asset(*originationFee).number())( - env, jt); + loanOriginationFee(broker.asset(*originationFee).number())(env, jt); if (serviceFee) loanServiceFee(broker.asset(*serviceFee).number())(env, jt); if (lateFee) @@ -270,10 +257,7 @@ protected: BrokerInfo const& broker_, jtx::Account const& pseudo_, Keylet const& keylet_) - : env(env_) - , broker(broker_) - , pseudoAccount(pseudo_) - , loanKeylet(keylet_) + : env(env_), broker(broker_), pseudoAccount(pseudo_), loanKeylet(keylet_) { } @@ -289,29 +273,21 @@ protected: std::uint32_t ownerCount) const { using namespace jtx; - if (auto brokerSle = env.le(keylet::loanbroker(broker.brokerID)); - env.test.BEAST_EXPECT(brokerSle)) + if (auto brokerSle = env.le(keylet::loanbroker(broker.brokerID)); env.test.BEAST_EXPECT(brokerSle)) { - TenthBips16 const managementFeeRate{ - brokerSle->at(sfManagementFeeRate)}; + TenthBips16 const managementFeeRate{brokerSle->at(sfManagementFeeRate)}; auto const brokerDebt = brokerSle->at(sfDebtTotal); auto const expectedDebt = principalOutstanding + interestOwed; env.test.BEAST_EXPECT(brokerDebt == expectedDebt); env.test.BEAST_EXPECT( - env.balance(pseudoAccount, broker.asset).number() == - brokerSle->at(sfCoverAvailable)); - env.test.BEAST_EXPECT( - brokerSle->at(sfOwnerCount) == ownerCount); + env.balance(pseudoAccount, broker.asset).number() == brokerSle->at(sfCoverAvailable)); + env.test.BEAST_EXPECT(brokerSle->at(sfOwnerCount) == ownerCount); - if (auto vaultSle = - env.le(keylet::vault(brokerSle->at(sfVaultID))); - env.test.BEAST_EXPECT(vaultSle)) + if (auto vaultSle = env.le(keylet::vault(brokerSle->at(sfVaultID))); env.test.BEAST_EXPECT(vaultSle)) { - Account const vaultPseudo{ - "vaultPseudoAccount", vaultSle->at(sfAccount)}; + Account const vaultPseudo{"vaultPseudoAccount", vaultSle->at(sfAccount)}; env.test.BEAST_EXPECT( - vaultSle->at(sfAssetsAvailable) == - env.balance(vaultPseudo, broker.asset).number()); + vaultSle->at(sfAssetsAvailable) == env.balance(vaultPseudo, broker.asset).number()); if (ownerCount == 0) { // Allow some slop for rounding IOUs @@ -323,10 +299,8 @@ protected: env.test.BEAST_EXPECT( total == available || (!broker.asset.integral() && available != 0 && - ((total - available) / available < - Number(1, -6)))); - env.test.BEAST_EXPECT( - vaultSle->at(sfLossUnrealized) == 0); + ((total - available) / available < Number(1, -6)))); + env.test.BEAST_EXPECT(vaultSle->at(sfLossUnrealized) == 0); } } } @@ -340,24 +314,18 @@ protected: STAmount const& expectedPayment, jtx::PrettyAmount const& adjustment) const { - auto const borrowerScale = - std::max(loanScale, balanceBefore.number().exponent()); + auto const borrowerScale = std::max(loanScale, balanceBefore.number().exponent()); STAmount const balanceChangeAmount{ - broker.asset, - roundToAsset( - broker.asset, expectedPayment + adjustment, borrowerScale)}; + broker.asset, roundToAsset(broker.asset, expectedPayment + adjustment, borrowerScale)}; { auto const difference = roundToScale( - env.balance(account, broker.asset) - - (balanceBefore - balanceChangeAmount), - borrowerScale); + env.balance(account, broker.asset) - (balanceBefore - balanceChangeAmount), borrowerScale); env.test.expect( roundToScale(difference, loanScale) >= beast::zero, "Balance before: " + to_string(balanceBefore.value()) + ", expected change: " + to_string(balanceChangeAmount) + - ", difference (balance after - expected): " + - to_string(difference), + ", difference (balance after - expected): " + to_string(difference), __FILE__, __LINE__); } @@ -379,55 +347,35 @@ protected: using namespace jtx; if (auto loan = env.le(loanKeylet); env.test.BEAST_EXPECT(loan)) { - env.test.BEAST_EXPECT( - loan->at(sfPreviousPaymentDueDate) == previousPaymentDate); - env.test.BEAST_EXPECT( - loan->at(sfPaymentRemaining) == paymentRemaining); - env.test.BEAST_EXPECT( - loan->at(sfNextPaymentDueDate) == nextPaymentDate); + env.test.BEAST_EXPECT(loan->at(sfPreviousPaymentDueDate) == previousPaymentDate); + env.test.BEAST_EXPECT(loan->at(sfPaymentRemaining) == paymentRemaining); + env.test.BEAST_EXPECT(loan->at(sfNextPaymentDueDate) == nextPaymentDate); env.test.BEAST_EXPECT(loan->at(sfLoanScale) == loanScale); - env.test.BEAST_EXPECT( - loan->at(sfTotalValueOutstanding) == totalValue); - env.test.BEAST_EXPECT( - loan->at(sfPrincipalOutstanding) == principalOutstanding); - env.test.BEAST_EXPECT( - loan->at(sfManagementFeeOutstanding) == - managementFeeOutstanding); - env.test.BEAST_EXPECT( - loan->at(sfPeriodicPayment) == periodicPayment); + env.test.BEAST_EXPECT(loan->at(sfTotalValueOutstanding) == totalValue); + env.test.BEAST_EXPECT(loan->at(sfPrincipalOutstanding) == principalOutstanding); + env.test.BEAST_EXPECT(loan->at(sfManagementFeeOutstanding) == managementFeeOutstanding); + env.test.BEAST_EXPECT(loan->at(sfPeriodicPayment) == periodicPayment); env.test.BEAST_EXPECT(loan->at(sfFlags) == flags); auto const ls = constructRoundedLoanState(loan); auto const interestRate = TenthBips32{loan->at(sfInterestRate)}; auto const paymentInterval = loan->at(sfPaymentInterval); - checkBroker( - principalOutstanding, - ls.interestDue, - interestRate, - paymentInterval, - paymentRemaining, - 1); + checkBroker(principalOutstanding, ls.interestDue, interestRate, paymentInterval, paymentRemaining, 1); - if (auto brokerSle = - env.le(keylet::loanbroker(broker.brokerID)); - env.test.BEAST_EXPECT(brokerSle)) + if (auto brokerSle = env.le(keylet::loanbroker(broker.brokerID)); env.test.BEAST_EXPECT(brokerSle)) { - if (auto vaultSle = - env.le(keylet::vault(brokerSle->at(sfVaultID))); + if (auto vaultSle = env.le(keylet::vault(brokerSle->at(sfVaultID))); env.test.BEAST_EXPECT(vaultSle)) { - if ((flags & lsfLoanImpaired) && - !(flags & lsfLoanDefault)) + if ((flags & lsfLoanImpaired) && !(flags & lsfLoanDefault)) { env.test.BEAST_EXPECT( - vaultSle->at(sfLossUnrealized) == - totalValue - managementFeeOutstanding); + vaultSle->at(sfLossUnrealized) == totalValue - managementFeeOutstanding); } else { - env.test.BEAST_EXPECT( - vaultSle->at(sfLossUnrealized) == 0); + env.test.BEAST_EXPECT(vaultSle->at(sfLossUnrealized) == 0); } } } @@ -468,17 +416,14 @@ protected: auto const coverRateMinValue = params.coverRateMin; - auto [tx, vaultKeylet] = - vault.create({.owner = lender, .asset = asset}); + auto [tx, vaultKeylet] = vault.create({.owner = lender, .asset = asset}); env(tx); env.close(); BEAST_EXPECT(env.le(vaultKeylet)); - env(vault.deposit( - {.depositor = lender, .id = vaultKeylet.key, .amount = deposit})); + env(vault.deposit({.depositor = lender, .id = vaultKeylet.key, .amount = deposit})); env.close(); - if (auto const vault = env.le(keylet::vault(vaultKeylet.key)); - BEAST_EXPECT(vault)) + if (auto const vault = env.le(keylet::vault(vaultKeylet.key)); BEAST_EXPECT(vault)) { BEAST_EXPECT(vault->at(sfAssetsAvailable) == deposit.value()); } @@ -503,10 +448,7 @@ protected: /// Get the state without checking anything LoanState - getCurrentState( - jtx::Env const& env, - BrokerInfo const& broker, - Keylet const& loanKeylet) + getCurrentState(jtx::Env const& env, BrokerInfo const& broker, Keylet const& loanKeylet) { using d = NetClock::duration; using tp = NetClock::time_point; @@ -522,8 +464,7 @@ protected: .loanScale = loan->at(sfLoanScale), .totalValue = loan->at(sfTotalValueOutstanding), .principalOutstanding = loan->at(sfPrincipalOutstanding), - .managementFeeOutstanding = - loan->at(sfManagementFeeOutstanding), + .managementFeeOutstanding = loan->at(sfManagementFeeOutstanding), .periodicPayment = loan->at(sfPeriodicPayment), .flags = loan->at(sfFlags), .paymentInterval = loan->at(sfPaymentInterval), @@ -553,20 +494,13 @@ protected: BEAST_EXPECT(state.principalOutstanding == broker.asset(1000).value()); BEAST_EXPECT( state.loanScale >= - (broker.asset.integral() - ? 0 - : std::max( - broker.vaultScale(env), - state.principalOutstanding.exponent()))); + (broker.asset.integral() ? 0 : std::max(broker.vaultScale(env), state.principalOutstanding.exponent()))); BEAST_EXPECT(state.paymentInterval == 600); { NumberRoundModeGuard mg(Number::upward); BEAST_EXPECT( state.totalValue == - roundToAsset( - broker.asset, - state.periodicPayment * state.paymentRemaining, - state.loanScale)); + roundToAsset(broker.asset, state.periodicPayment * state.paymentRemaining, state.loanScale)); } BEAST_EXPECT( state.managementFeeOutstanding == @@ -582,23 +516,16 @@ protected: } bool - canImpairLoan( - jtx::Env const& env, - BrokerInfo const& broker, - LoanState const& state) + canImpairLoan(jtx::Env const& env, BrokerInfo const& broker, LoanState const& state) { - if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); BEAST_EXPECT(brokerSle)) { - if (auto const vaultSle = - env.le(keylet::vault(brokerSle->at(sfVaultID))); - BEAST_EXPECT(vaultSle)) + if (auto const vaultSle = env.le(keylet::vault(brokerSle->at(sfVaultID))); BEAST_EXPECT(vaultSle)) { // log << vaultSle->getJson() << std::endl; - auto const assetsUnavailable = vaultSle->at(sfAssetsTotal) - - vaultSle->at(sfAssetsAvailable); - auto const unrealizedLoss = vaultSle->at(sfLossUnrealized) + - state.totalValue - state.managementFeeOutstanding; + auto const assetsUnavailable = vaultSle->at(sfAssetsTotal) - vaultSle->at(sfAssetsAvailable); + auto const unrealizedLoss = + vaultSle->at(sfLossUnrealized) + state.totalValue - state.managementFeeOutstanding; if (!BEAST_EXPECT(unrealizedLoss <= assetsUnavailable)) { @@ -632,9 +559,7 @@ protected: case AssetType::IOU: { PrettyAsset const asset{issuer[iouCurrency]}; - auto const limit = asset( - 100 * - (brokerParams.vaultDeposit + brokerParams.coverDeposit)); + auto const limit = asset(100 * (brokerParams.vaultDeposit + brokerParams.coverDeposit)); if (lender != issuer) env(trust(lender, limit)); if (borrower != issuer) @@ -646,21 +571,14 @@ protected: case AssetType::MPT: { // Enough to cover initial fees if (!env.le(keylet::account(issuer))) - env.fund( - env.current()->fees().accountReserve(10) * 10, issuer); + env.fund(env.current()->fees().accountReserve(10) * 10, issuer); if (!env.le(keylet::account(lender))) - env.fund( - env.current()->fees().accountReserve(10) * 10, - noripple(lender)); + env.fund(env.current()->fees().accountReserve(10) * 10, noripple(lender)); if (!env.le(keylet::account(borrower))) - env.fund( - env.current()->fees().accountReserve(10) * 10, - noripple(borrower)); + env.fund(env.current()->fees().accountReserve(10) * 10, noripple(borrower)); MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = - tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); // Scale the MPT asset so interest is interesting PrettyAsset const asset{mptt.issuanceID(), 10'000}; // Need to do the authorization here because mptt isn't @@ -692,23 +610,14 @@ protected: { using namespace jtx; - auto const asset = - createAsset(env, assetType, brokerParams, issuer, lender, borrower); + auto const asset = createAsset(env, assetType, brokerParams, issuer, lender, borrower); auto const principal = asset(loanParams.principalRequest).number(); auto const interest = loanParams.interest.value_or(TenthBips32{}); - auto const interval = - loanParams.payInterval.value_or(LoanSet::defaultPaymentInterval); - auto const total = - loanParams.payTotal.value_or(LoanSet::defaultPaymentTotal); + auto const interval = loanParams.payInterval.value_or(LoanSet::defaultPaymentInterval); + auto const total = loanParams.payTotal.value_or(LoanSet::defaultPaymentTotal); auto const feeRate = brokerParams.managementFeeRate; auto const props = computeLoanProperties( - asset, - principal, - interest, - interval, - total, - feeRate, - asset(brokerParams.vaultDeposit).number().exponent()); + asset, principal, interest, interval, total, feeRate, asset(brokerParams.vaultDeposit).number().exponent()); log << "Loan properties:\n" << "\tPrincipal: " << principal << std::endl << "\tInterest rate: " << interest << std::endl @@ -716,13 +625,10 @@ protected: << "\tManagement Fee Rate: " << feeRate << std::endl << "\tTotal Payments: " << total << std::endl << "\tPeriodic Payment: " << props.periodicPayment << std::endl - << "\tTotal Value: " << props.loanState.valueOutstanding - << std::endl - << "\tManagement Fee: " << props.loanState.managementFeeDue - << std::endl + << "\tTotal Value: " << props.loanState.valueOutstanding << std::endl + << "\tManagement Fee: " << props.loanState.managementFeeDue << std::endl << "\tLoan Scale: " << props.loanScale << std::endl - << "\tFirst payment principal: " << props.firstPaymentPrincipal - << std::endl; + << "\tFirst payment principal: " << props.firstPaymentPrincipal << std::endl; // checkGuards returns a TER, so success is 0 BEAST_EXPECT(!checkLoanGuards( @@ -749,32 +655,25 @@ protected: // Enough to cover initial fees env.fund(env.current()->fees().accountReserve(10) * 10, issuer); if (lender != issuer) - env.fund( - env.current()->fees().accountReserve(10) * 10, - noripple(lender)); + env.fund(env.current()->fees().accountReserve(10) * 10, noripple(lender)); if (borrower != issuer && borrower != lender) - env.fund( - env.current()->fees().accountReserve(10) * 10, - noripple(borrower)); + env.fund(env.current()->fees().accountReserve(10) * 10, noripple(borrower)); - describeLoan( - env, brokerParams, loanParams, assetType, issuer, lender, borrower); + describeLoan(env, brokerParams, loanParams, assetType, issuer, lender, borrower); // Make the asset - auto const asset = - createAsset(env, assetType, brokerParams, issuer, lender, borrower); + auto const asset = createAsset(env, assetType, brokerParams, issuer, lender, borrower); env.close(); if (asset.native() || lender != issuer) - env(pay( - (asset.native() ? env.master : issuer), - lender, - asset(brokerParams.vaultDeposit + brokerParams.coverDeposit))); + env( + pay((asset.native() ? env.master : issuer), + lender, + asset(brokerParams.vaultDeposit + brokerParams.coverDeposit))); // Fund the borrower later once we know the total loan // size - BrokerInfo const broker = - createVaultAndBroker(env, asset, lender, brokerParams); + BrokerInfo const broker = createVaultAndBroker(env, asset, lender, brokerParams); auto const pseudoAcctOpt = [&]() -> std::optional { auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); @@ -832,22 +731,16 @@ protected: // Add extra for transaction fees and reserves, if appropriate, or a // tiny amount for the extra paid in each transaction - auto const totalNeeded = state.totalValue + - (serviceFee * state.paymentRemaining) + + auto const totalNeeded = state.totalValue + (serviceFee * state.paymentRemaining) + (broker.asset.native() ? Number( baseFee * state.paymentRemaining + - env.current()->fees().accountReserve( - env.ownerCount(borrower))) + env.current()->fees().accountReserve(env.ownerCount(borrower))) : broker.asset(15).number()); auto const shortage = totalNeeded - borrowerBalance.number(); - if (shortage > beast::zero && - (broker.asset.native() || issuer != borrower)) - env( - pay((broker.asset.native() ? env.master : issuer), - borrower, - STAmount{broker.asset, shortage})); + if (shortage > beast::zero && (broker.asset.native() || issuer != borrower)) + env(pay((broker.asset.native() ? env.master : issuer), borrower, STAmount{broker.asset, shortage})); } void @@ -879,11 +772,9 @@ protected: verifyLoanStatus(state); - STAmount const serviceFee = - broker.asset(loanParams.serviceFee.value_or(0)); + STAmount const serviceFee = broker.asset(loanParams.serviceFee.value_or(0)); - topUpBorrower( - env, broker, issuer, borrower, state, loanParams.serviceFee); + topUpBorrower(env, broker, issuer, borrower, state, loanParams.serviceFee); // Periodic payment amount will consist of // 1. principal outstanding (1000) @@ -893,12 +784,9 @@ protected: // Calculate these values without the helper functions // to verify they're working correctly The numbers in // the below BEAST_EXPECTs may not hold across assets. - auto const periodicRate = - loanPeriodicRate(state.interestRate, state.paymentInterval); + auto const periodicRate = loanPeriodicRate(state.interestRate, state.paymentInterval); STAmount const roundedPeriodicPayment{ - broker.asset, - roundPeriodicPayment( - broker.asset, state.periodicPayment, state.loanScale)}; + broker.asset, roundPeriodicPayment(broker.asset, state.periodicPayment, state.loanScale)}; if (!showStepBalances) log << currencyLabel << " Payment components: " @@ -910,43 +798,29 @@ protected: << std::endl; // Include the service fee - STAmount const totalDue = roundToScale( - roundedPeriodicPayment + serviceFee, - state.loanScale, - Number::upward); + STAmount const totalDue = roundToScale(roundedPeriodicPayment + serviceFee, state.loanScale, Number::upward); - auto currentRoundedState = constructLoanState( - state.totalValue, - state.principalOutstanding, - state.managementFeeOutstanding); + auto currentRoundedState = + constructLoanState(state.totalValue, state.principalOutstanding, state.managementFeeOutstanding); { auto const raw = computeTheoreticalLoanState( - state.periodicPayment, - periodicRate, - state.paymentRemaining, - broker.params.managementFeeRate); + state.periodicPayment, periodicRate, state.paymentRemaining, broker.params.managementFeeRate); if (showStepBalances) { log << currencyLabel << " Starting loan balances: " - << "\n\tTotal value: " - << currentRoundedState.valueOutstanding << "\n\tPrincipal: " - << currentRoundedState.principalOutstanding + << "\n\tTotal value: " << currentRoundedState.valueOutstanding + << "\n\tPrincipal: " << currentRoundedState.principalOutstanding << "\n\tInterest: " << currentRoundedState.interestDue - << "\n\tMgmt fee: " << currentRoundedState.managementFeeDue - << "\n\tPayments remaining " << state.paymentRemaining - << std::endl; + << "\n\tMgmt fee: " << currentRoundedState.managementFeeDue << "\n\tPayments remaining " + << state.paymentRemaining << std::endl; } else { - log << currencyLabel - << " Loan starting state: " << state.paymentRemaining - << ", " << raw.interestDue << ", " - << raw.principalOutstanding << ", " << raw.managementFeeDue - << ", " << currentRoundedState.valueOutstanding << ", " - << currentRoundedState.principalOutstanding << ", " - << currentRoundedState.interestDue << ", " - << currentRoundedState.managementFeeDue << std::endl; + log << currencyLabel << " Loan starting state: " << state.paymentRemaining << ", " << raw.interestDue + << ", " << raw.principalOutstanding << ", " << raw.managementFeeDue << ", " + << currentRoundedState.valueOutstanding << ", " << currentRoundedState.principalOutstanding << ", " + << currentRoundedState.interestDue << ", " << currentRoundedState.managementFeeDue << std::endl; } } @@ -954,47 +828,33 @@ protected: // taken auto const extraAmount = paymentParams.overpaymentExtra ? broker.asset(*paymentParams.overpaymentExtra).value() - : std::min( - broker.asset(10).value(), - STAmount{broker.asset, totalDue / 20}); + : std::min(broker.asset(10).value(), STAmount{broker.asset, totalDue / 20}); STAmount const transactionAmount = - STAmount{broker.asset, totalDue * paymentParams.overpaymentFactor} + - extraAmount; + STAmount{broker.asset, totalDue * paymentParams.overpaymentFactor} + extraAmount; - auto const borrowerInitialBalance = - env.balance(borrower, broker.asset).number(); + auto const borrowerInitialBalance = env.balance(borrower, broker.asset).number(); auto const initialState = state; detail::PaymentComponents totalPaid{ - .trackedValueDelta = 0, - .trackedPrincipalDelta = 0, - .trackedManagementFeeDelta = 0}; + .trackedValueDelta = 0, .trackedPrincipalDelta = 0, .trackedManagementFeeDelta = 0}; Number totalInterestPaid = 0; Number totalFeesPaid = 0; std::size_t totalPaymentsMade = 0; xrpl::LoanState currentTrueState = computeTheoreticalLoanState( - state.periodicPayment, - periodicRate, - state.paymentRemaining, - broker.params.managementFeeRate); + state.periodicPayment, periodicRate, state.paymentRemaining, broker.params.managementFeeRate); auto validateBorrowerBalance = [&]() { if (borrower == issuer || !paymentParams.validateBalances) return; auto const totalSpent = (totalPaid.trackedValueDelta + totalFeesPaid + - (broker.asset.native() ? Number(baseFee) * totalPaymentsMade - : numZero)); - BEAST_EXPECT( - env.balance(borrower, broker.asset).number() == - borrowerInitialBalance - totalSpent); + (broker.asset.native() ? Number(baseFee) * totalPaymentsMade : numZero)); + BEAST_EXPECT(env.balance(borrower, broker.asset).number() == borrowerInitialBalance - totalSpent); }; auto const defaultRound = broker.asset.integral() ? 3 : 0; - auto truncate = [defaultRound]( - Number const& n, - std::optional places = std::nullopt) { + auto truncate = [defaultRound](Number const& n, std::optional places = std::nullopt) { auto const p = places.value_or(defaultRound); if (p == 0) return n; @@ -1018,54 +878,35 @@ protected: BEAST_EXPECT( paymentComponents.trackedValueDelta <= roundedPeriodicPayment || - (paymentComponents.specialCase == - detail::PaymentSpecialCase::final && - paymentComponents.trackedValueDelta >= - roundedPeriodicPayment)); + (paymentComponents.specialCase == detail::PaymentSpecialCase::final && + paymentComponents.trackedValueDelta >= roundedPeriodicPayment)); BEAST_EXPECT( paymentComponents.trackedValueDelta == - paymentComponents.trackedPrincipalDelta + - paymentComponents.trackedInterestPart() + + paymentComponents.trackedPrincipalDelta + paymentComponents.trackedInterestPart() + paymentComponents.trackedManagementFeeDelta); xrpl::LoanState const nextTrueState = computeTheoreticalLoanState( - state.periodicPayment, - periodicRate, - state.paymentRemaining - 1, - broker.params.managementFeeRate); - detail::LoanStateDeltas const deltas = - currentTrueState - nextTrueState; + state.periodicPayment, periodicRate, state.paymentRemaining - 1, broker.params.managementFeeRate); + detail::LoanStateDeltas const deltas = currentTrueState - nextTrueState; + BEAST_EXPECT(deltas.total() == deltas.principal + deltas.interest + deltas.managementFee); BEAST_EXPECT( - deltas.total() == - deltas.principal + deltas.interest + deltas.managementFee); - BEAST_EXPECT( - paymentComponents.specialCase == - detail::PaymentSpecialCase::final || + paymentComponents.specialCase == detail::PaymentSpecialCase::final || deltas.total() == state.periodicPayment || - (state.loanScale - - (deltas.total() - state.periodicPayment).exponent()) > 14); + (state.loanScale - (deltas.total() - state.periodicPayment).exponent()) > 14); if (!showStepBalances) - log << currencyLabel - << " Payment components: " << state.paymentRemaining << ", " + log << currencyLabel << " Payment components: " << state.paymentRemaining << ", " - << deltas.interest << ", " << deltas.principal << ", " - << deltas.managementFee << ", " - << paymentComponents.trackedValueDelta << ", " - << paymentComponents.trackedPrincipalDelta << ", " - << paymentComponents.trackedInterestPart() << ", " - << paymentComponents.trackedManagementFeeDelta << ", " - << (paymentComponents.specialCase == - detail::PaymentSpecialCase::final - ? "final" - : paymentComponents.specialCase == - detail::PaymentSpecialCase::extra - ? "extra" - : "none") + << deltas.interest << ", " << deltas.principal << ", " << deltas.managementFee << ", " + << paymentComponents.trackedValueDelta << ", " << paymentComponents.trackedPrincipalDelta << ", " + << paymentComponents.trackedInterestPart() << ", " << paymentComponents.trackedManagementFeeDelta + << ", " + << (paymentComponents.specialCase == detail::PaymentSpecialCase::final ? "final" + : paymentComponents.specialCase == detail::PaymentSpecialCase::extra ? "extra" + : "none") << std::endl; - auto const totalDueAmount = STAmount{ - broker.asset, paymentComponents.trackedValueDelta + serviceFee}; + auto const totalDueAmount = STAmount{broker.asset, paymentComponents.trackedValueDelta + serviceFee}; if (paymentParams.validateBalances) { @@ -1077,34 +918,23 @@ protected: // IOUs, the difference should be dust. Number const diff = totalDue - totalDueAmount; BEAST_EXPECT( - paymentComponents.specialCase == - detail::PaymentSpecialCase::final || - diff == beast::zero || + paymentComponents.specialCase == detail::PaymentSpecialCase::final || diff == beast::zero || (diff > beast::zero && - ((broker.asset.integral() && - (static_cast(diff) < 3)) || + ((broker.asset.integral() && (static_cast(diff) < 3)) || (state.loanScale - diff.exponent() > 13)))); BEAST_EXPECT( paymentComponents.trackedPrincipalDelta >= beast::zero && - paymentComponents.trackedPrincipalDelta <= - state.principalOutstanding); + paymentComponents.trackedPrincipalDelta <= state.principalOutstanding); BEAST_EXPECT( - paymentComponents.specialCase != - detail::PaymentSpecialCase::final || - paymentComponents.trackedPrincipalDelta == - state.principalOutstanding); + paymentComponents.specialCase != detail::PaymentSpecialCase::final || + paymentComponents.trackedPrincipalDelta == state.principalOutstanding); } - auto const borrowerBalanceBeforePayment = - env.balance(borrower, broker.asset); + auto const borrowerBalanceBeforePayment = env.balance(borrower, broker.asset); // Make the payment - env( - pay(borrower, - loanKeylet.key, - transactionAmount, - paymentParams.flags)); + env(pay(borrower, loanKeylet.key, transactionAmount, paymentParams.flags)); env.close(d{state.paymentInterval / 2}); @@ -1119,11 +949,7 @@ protected: // Check the result verifyLoanStatus.checkPayment( - state.loanScale, - borrower, - borrowerBalanceBeforePayment, - totalDueAmount, - adjustment); + state.loanScale, borrower, borrowerBalanceBeforePayment, totalDueAmount, adjustment); } if (showStepBalances) @@ -1135,22 +961,16 @@ protected: auto const current = constructRoundedLoanState(loanSle); auto const errors = nextTrueState - current; log << currencyLabel << " Loan balances: " - << "\n\tAmount taken: " - << paymentComponents.trackedValueDelta + << "\n\tAmount taken: " << paymentComponents.trackedValueDelta << "\n\tTotal value: " << current.valueOutstanding - << " (true: " << truncate(nextTrueState.valueOutstanding) - << ", error: " << truncate(errors.total()) + << " (true: " << truncate(nextTrueState.valueOutstanding) << ", error: " << truncate(errors.total()) << ")\n\tPrincipal: " << current.principalOutstanding - << " (true: " - << truncate(nextTrueState.principalOutstanding) - << ", error: " << truncate(errors.principal) - << ")\n\tInterest: " << current.interestDue - << " (true: " << truncate(nextTrueState.interestDue) - << ", error: " << truncate(errors.interest) + << " (true: " << truncate(nextTrueState.principalOutstanding) + << ", error: " << truncate(errors.principal) << ")\n\tInterest: " << current.interestDue + << " (true: " << truncate(nextTrueState.interestDue) << ", error: " << truncate(errors.interest) << ")\n\tMgmt fee: " << current.managementFeeDue << " (true: " << truncate(nextTrueState.managementFeeDue) - << ", error: " << truncate(errors.managementFee) - << ")\n\tPayments remaining " + << ", error: " << truncate(errors.managementFee) << ")\n\tPayments remaining " << loanSle->at(sfPaymentRemaining) << std::endl; currentRoundedState = current; @@ -1158,8 +978,7 @@ protected: --state.paymentRemaining; state.previousPaymentDate = state.nextPaymentDate; - if (paymentComponents.specialCase == - detail::PaymentSpecialCase::final) + if (paymentComponents.specialCase == detail::PaymentSpecialCase::final) { state.paymentRemaining = 0; state.nextPaymentDate = 0; @@ -1168,20 +987,16 @@ protected: { state.nextPaymentDate += state.paymentInterval; } - state.principalOutstanding -= - paymentComponents.trackedPrincipalDelta; - state.managementFeeOutstanding -= - paymentComponents.trackedManagementFeeDelta; + state.principalOutstanding -= paymentComponents.trackedPrincipalDelta; + state.managementFeeOutstanding -= paymentComponents.trackedManagementFeeDelta; state.totalValue -= paymentComponents.trackedValueDelta; if (paymentParams.validateBalances) verifyLoanStatus(state); totalPaid.trackedValueDelta += paymentComponents.trackedValueDelta; - totalPaid.trackedPrincipalDelta += - paymentComponents.trackedPrincipalDelta; - totalPaid.trackedManagementFeeDelta += - paymentComponents.trackedManagementFeeDelta; + totalPaid.trackedPrincipalDelta += paymentComponents.trackedPrincipalDelta; + totalPaid.trackedManagementFeeDelta += paymentComponents.trackedManagementFeeDelta; totalInterestPaid += paymentComponents.trackedInterestPart(); totalFeesPaid += serviceFee; ++totalPaymentsMade; @@ -1194,20 +1009,14 @@ protected: BEAST_EXPECT(state.paymentRemaining == 0); BEAST_EXPECT(state.principalOutstanding == 0); - auto const initialInterestDue = initialState.totalValue - - (initialState.principalOutstanding + - initialState.managementFeeOutstanding); + auto const initialInterestDue = + initialState.totalValue - (initialState.principalOutstanding + initialState.managementFeeOutstanding); if (paymentParams.validateBalances) { // Make sure all the payments add up - BEAST_EXPECT( - totalPaid.trackedValueDelta == initialState.totalValue); - BEAST_EXPECT( - totalPaid.trackedPrincipalDelta == - initialState.principalOutstanding); - BEAST_EXPECT( - totalPaid.trackedManagementFeeDelta == - initialState.managementFeeOutstanding); + BEAST_EXPECT(totalPaid.trackedValueDelta == initialState.totalValue); + BEAST_EXPECT(totalPaid.trackedPrincipalDelta == initialState.principalOutstanding); + BEAST_EXPECT(totalPaid.trackedManagementFeeDelta == initialState.managementFeeOutstanding); // This is almost a tautology given the previous checks, but // check it anyway for completeness. BEAST_EXPECT(totalInterestPaid == initialInterestDue); @@ -1223,35 +1032,21 @@ protected: log << currencyLabel << " Total amounts paid: " << "\n\tTotal value: " << totalPaid.trackedValueDelta << " (initial: " << truncate(initialState.totalValue) - << ", error: " - << truncate( - initialState.totalValue - totalPaid.trackedValueDelta) + << ", error: " << truncate(initialState.totalValue - totalPaid.trackedValueDelta) << ")\n\tPrincipal: " << totalPaid.trackedPrincipalDelta << " (initial: " << truncate(initialState.principalOutstanding) - << ", error: " - << truncate( - initialState.principalOutstanding - - totalPaid.trackedPrincipalDelta) - << ")\n\tInterest: " << totalInterestPaid - << " (initial: " << truncate(initialInterestDue) << ", error: " - << truncate(initialInterestDue - totalInterestPaid) + << ", error: " << truncate(initialState.principalOutstanding - totalPaid.trackedPrincipalDelta) + << ")\n\tInterest: " << totalInterestPaid << " (initial: " << truncate(initialInterestDue) + << ", error: " << truncate(initialInterestDue - totalInterestPaid) << ")\n\tMgmt fee: " << totalPaid.trackedManagementFeeDelta - << " (initial: " - << truncate(initialState.managementFeeOutstanding) - << ", error: " - << truncate( - initialState.managementFeeOutstanding - - totalPaid.trackedManagementFeeDelta) - << ")\n\tTotal payments made: " << totalPaymentsMade - << std::endl; + << " (initial: " << truncate(initialState.managementFeeOutstanding) + << ", error: " << truncate(initialState.managementFeeOutstanding - totalPaid.trackedManagementFeeDelta) + << ")\n\tTotal payments made: " << totalPaymentsMade << std::endl; } } void - runLoan( - AssetType assetType, - BrokerParameters const& brokerParams, - LoanParameters const& loanParams) + runLoan(AssetType assetType, BrokerParameters const& brokerParams, LoanParameters const& loanParams) { using namespace jtx; @@ -1261,8 +1056,7 @@ protected: Env env(*this, all); - auto loanResult = createLoan( - env, assetType, brokerParams, loanParams, issuer, lender, borrower); + auto loanResult = createLoan(env, assetType, brokerParams, loanParams, issuer, lender, borrower); if (!BEAST_EXPECT(loanResult)) return; @@ -1309,16 +1103,13 @@ protected: std::uint32_t flags, // The end of life callback is expected to take the loan to 0 payments // remaining, one way or another - std::function toEndOfLife) + std::function toEndOfLife) { auto const [keylet, loanSequence] = [&]() { auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); if (!BEAST_EXPECT(brokerSle)) // will be invalid - return std::make_pair( - keylet::loan(broker.brokerID), std::uint32_t(0)); + return std::make_pair(keylet::loan(broker.brokerID), std::uint32_t(0)); // Broker has no loans BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 0); @@ -1326,12 +1117,10 @@ protected: // The loan keylet is based on the LoanSequence of the _LOAN_BROKER_ // object. auto const loanSequence = brokerSle->at(sfLoanSequence); - return std::make_pair( - keylet::loan(broker.brokerID, loanSequence), loanSequence); + return std::make_pair(keylet::loan(broker.brokerID, loanSequence), loanSequence); }(); - VerifyLoanStatus const verifyLoanStatus( - env, broker, pseudoAcct, keylet); + VerifyLoanStatus const verifyLoanStatus(env, broker, pseudoAcct, keylet); // No loans yet verifyLoanStatus.checkBroker(0, 0, TenthBips32{0}, 1, 0, 0); @@ -1345,8 +1134,7 @@ protected: using namespace loan; using namespace std::chrono_literals; - auto applyExponent = [interestExponent, - this](TenthBips32 value) mutable { + auto applyExponent = [interestExponent, this](TenthBips32 value) mutable { BEAST_EXPECT(value > TenthBips32(0)); while (interestExponent > 0) { @@ -1383,19 +1171,15 @@ protected: // 2.4% .lateInterest = applyExponent(percentageToTenthBips(24) / 10), .closeInterest = applyExponent(percentageToTenthBips(36) / 10), - .overpaymentInterest = - applyExponent(percentageToTenthBips(48) / 10), + .overpaymentInterest = applyExponent(percentageToTenthBips(48) / 10), .payTotal = 12, .payInterval = 600, .gracePd = 60, .flags = flags, }; - Number const principalRequestAmount = - broker.asset(loanParams.principalRequest).value(); - auto const originationFeeAmount = - broker.asset(*loanParams.originationFee).value(); - auto const serviceFeeAmount = - broker.asset(*loanParams.serviceFee).value(); + Number const principalRequestAmount = broker.asset(loanParams.principalRequest).value(); + auto const originationFeeAmount = broker.asset(*loanParams.originationFee).value(); + auto const serviceFeeAmount = broker.asset(*loanParams.serviceFee).value(); auto const lateFeeAmount = broker.asset(*loanParams.lateFee).value(); auto const closeFeeAmount = broker.asset(*loanParams.closeFee).value(); @@ -1407,11 +1191,9 @@ protected: env.close(); - auto const startDate = - env.current()->header().parentCloseTime.time_since_epoch().count(); + auto const startDate = env.current()->header().parentCloseTime.time_since_epoch().count(); - if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); BEAST_EXPECT(brokerSle)) { BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 1); } @@ -1426,56 +1208,38 @@ protected: BEAST_EXPECT( env.balance(borrower, broker.asset).value() == - borrowerStartbalance.value() + principalRequestAmount - - originationFeeAmount - adjustment.value()); + borrowerStartbalance.value() + principalRequestAmount - originationFeeAmount - adjustment.value()); } - auto const loanFlags = createJtx.stx->isFlag(tfLoanOverpayment) - ? lsfLoanOverpayment - : LedgerSpecificFlags(0); + auto const loanFlags = createJtx.stx->isFlag(tfLoanOverpayment) ? lsfLoanOverpayment : LedgerSpecificFlags(0); if (auto loan = env.le(keylet); BEAST_EXPECT(loan)) { // log << "loan after create: " << to_string(loan->getJson()) // << std::endl; - BEAST_EXPECT( - loan->isFlag(lsfLoanOverpayment) == - createJtx.stx->isFlag(tfLoanOverpayment)); + BEAST_EXPECT(loan->isFlag(lsfLoanOverpayment) == createJtx.stx->isFlag(tfLoanOverpayment)); BEAST_EXPECT(loan->at(sfLoanSequence) == loanSequence); BEAST_EXPECT(loan->at(sfBorrower) == borrower.id()); BEAST_EXPECT(loan->at(sfLoanBrokerID) == broker.brokerID); - BEAST_EXPECT( - loan->at(sfLoanOriginationFee) == originationFeeAmount); + BEAST_EXPECT(loan->at(sfLoanOriginationFee) == originationFeeAmount); BEAST_EXPECT(loan->at(sfLoanServiceFee) == serviceFeeAmount); BEAST_EXPECT(loan->at(sfLatePaymentFee) == lateFeeAmount); BEAST_EXPECT(loan->at(sfClosePaymentFee) == closeFeeAmount); BEAST_EXPECT(loan->at(sfOverpaymentFee) == *loanParams.overFee); BEAST_EXPECT(loan->at(sfInterestRate) == *loanParams.interest); - BEAST_EXPECT( - loan->at(sfLateInterestRate) == *loanParams.lateInterest); - BEAST_EXPECT( - loan->at(sfCloseInterestRate) == *loanParams.closeInterest); - BEAST_EXPECT( - loan->at(sfOverpaymentInterestRate) == - *loanParams.overpaymentInterest); + BEAST_EXPECT(loan->at(sfLateInterestRate) == *loanParams.lateInterest); + BEAST_EXPECT(loan->at(sfCloseInterestRate) == *loanParams.closeInterest); + BEAST_EXPECT(loan->at(sfOverpaymentInterestRate) == *loanParams.overpaymentInterest); BEAST_EXPECT(loan->at(sfStartDate) == startDate); - BEAST_EXPECT( - loan->at(sfPaymentInterval) == *loanParams.payInterval); + BEAST_EXPECT(loan->at(sfPaymentInterval) == *loanParams.payInterval); BEAST_EXPECT(loan->at(sfGracePeriod) == *loanParams.gracePd); BEAST_EXPECT(loan->at(sfPreviousPaymentDueDate) == 0); - BEAST_EXPECT( - loan->at(sfNextPaymentDueDate) == - startDate + *loanParams.payInterval); + BEAST_EXPECT(loan->at(sfNextPaymentDueDate) == startDate + *loanParams.payInterval); BEAST_EXPECT(loan->at(sfPaymentRemaining) == *loanParams.payTotal); BEAST_EXPECT( loan->at(sfLoanScale) >= - (broker.asset.integral() - ? 0 - : std::max( - broker.vaultScale(env), - principalRequestAmount.exponent()))); - BEAST_EXPECT( - loan->at(sfPrincipalOutstanding) == principalRequestAmount); + (broker.asset.integral() ? 0 : std::max(broker.vaultScale(env), principalRequestAmount.exponent()))); + BEAST_EXPECT(loan->at(sfPrincipalOutstanding) == principalRequestAmount); } auto state = getCurrentState(env, broker, keylet, verifyLoanStatus); @@ -1514,17 +1278,10 @@ protected: // unknown flags env(manage(lender, keylet.key, tfLoanManageMask), ter(temINVALID_FLAG)); // combinations of flags are not allowed - env(manage(lender, keylet.key, tfLoanUnimpair | tfLoanImpair), - ter(temINVALID_FLAG)); - env(manage(lender, keylet.key, tfLoanImpair | tfLoanDefault), - ter(temINVALID_FLAG)); - env(manage(lender, keylet.key, tfLoanUnimpair | tfLoanDefault), - ter(temINVALID_FLAG)); - env(manage( - lender, - keylet.key, - tfLoanUnimpair | tfLoanImpair | tfLoanDefault), - ter(temINVALID_FLAG)); + env(manage(lender, keylet.key, tfLoanUnimpair | tfLoanImpair), ter(temINVALID_FLAG)); + env(manage(lender, keylet.key, tfLoanImpair | tfLoanDefault), ter(temINVALID_FLAG)); + env(manage(lender, keylet.key, tfLoanUnimpair | tfLoanDefault), ter(temINVALID_FLAG)); + env(manage(lender, keylet.key, tfLoanUnimpair | tfLoanImpair | tfLoanDefault), ter(temINVALID_FLAG)); // invalid loan ID env(manage(lender, broker.brokerID, tfLoanImpair), ter(tecNO_ENTRY)); // Loan is unimpaired, can't unimpair it again @@ -1536,11 +1293,9 @@ protected: // Check the vault bool const canImpair = canImpairLoan(env, broker, state); // Impair the loan, if possible - env(manage(lender, keylet.key, tfLoanImpair), - canImpair ? ter(tesSUCCESS) : ter(tecLIMIT_EXCEEDED)); + env(manage(lender, keylet.key, tfLoanImpair), canImpair ? ter(tesSUCCESS) : ter(tecLIMIT_EXCEEDED)); // Unimpair the loan - env(manage(lender, keylet.key, tfLoanUnimpair), - canImpair ? ter(tesSUCCESS) : ter(tecNO_PERMISSION)); + env(manage(lender, keylet.key, tfLoanUnimpair), canImpair ? ter(tesSUCCESS) : ter(tecNO_PERMISSION)); auto const nextDueDate = startDate + *loanParams.payInterval; @@ -1570,8 +1325,7 @@ protected: BEAST_EXPECT(loan->at(sfPaymentRemaining) == 0); BEAST_EXPECT(loan->at(sfPrincipalOutstanding) == 0); } - auto const borrowerStartingBalance = - env.balance(borrower, broker.asset); + auto const borrowerStartingBalance = env.balance(borrower, broker.asset); // Try to delete the loan broker with an active loan env(loanBroker::del(lender, broker.brokerID), ter(tecHAS_OBLIGATIONS)); @@ -1605,13 +1359,10 @@ protected: // No loans left verifyLoanStatus.checkBroker(0, 0, *loanParams.interest, 1, 0, 0); - BEAST_EXPECT( - env.balance(borrower, broker.asset).value() == - borrowerStartingBalance.value() - adjustment); + BEAST_EXPECT(env.balance(borrower, broker.asset).value() == borrowerStartingBalance.value() - adjustment); BEAST_EXPECT(env.ownerCount(borrower) == borrowerOwnerCount); - if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); BEAST_EXPECT(brokerSle)) { BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 0); } @@ -1620,11 +1371,7 @@ protected: std::string getCurrencyLabel(Asset const& asset) { - return ( - asset.native() ? "XRP" - : asset.holds() ? "IOU" - : asset.holds() ? "MPT" - : "Unknown"); + return (asset.native() ? "XRP" : asset.holds() ? "IOU" : asset.holds() ? "MPT" : "Unknown"); } /** Wrapper to run a series of lifecycle tests for a given asset and loan @@ -1652,8 +1399,8 @@ protected: auto const currencyLabel = getCurrencyLabel(asset); auto const caseLabel = [&]() { std::stringstream ss; - ss << "Lifecycle: " << loanAmount << " " << currencyLabel - << " Scale interest to: " << interestExponent << " "; + ss << "Lifecycle: " << loanAmount << " " << currencyLabel << " Scale interest to: " << interestExponent + << " "; return ss.str(); }(); testcase << caseLabel; @@ -1677,12 +1424,9 @@ protected: Number const principalRequest = broker.asset(loanAmount).value(); Number const maxCoveredLoanValue = broker.params.maxCoveredLoanValue(0); BEAST_EXPECT(maxCoveredLoanValue == 1000 * 100 / 10); - Number const maxCoveredLoanRequest = - broker.asset(maxCoveredLoanValue).value(); - Number const totalVaultRequest = - broker.asset(broker.params.vaultDeposit).value(); - Number const debtMaximumRequest = - broker.asset(broker.params.debtMax).value(); + Number const maxCoveredLoanRequest = broker.asset(maxCoveredLoanValue).value(); + Number const totalVaultRequest = broker.asset(broker.params.vaultDeposit).value(); + Number const debtMaximumRequest = broker.asset(broker.params.debtMax).value(); auto const loanSetFee = fee(env.current()->fees().base * 2); @@ -1955,13 +1699,11 @@ protected: return; auto const vaultPseudo = [&]() { - auto const vaultSle = - env.le(keylet::vault(brokerSle->at(sfVaultID))); + auto const vaultSle = env.le(keylet::vault(brokerSle->at(sfVaultID))); if (!BEAST_EXPECT(vaultSle)) // This will be wrong, but the test has failed anyway. return lender; - auto const vaultPseudo = - Account("Vault pseudo-account", vaultSle->at(sfAccount)); + auto const vaultPseudo = Account("Vault pseudo-account", vaultSle->at(sfAccount)); return vaultPseudo; }(); @@ -1984,33 +1726,20 @@ protected: env(trust(issuer, holder[iouCurrency](0), tfSetFreeze)); }; auto deepfreeze = [&](Account const& holder) { - env(trust( - issuer, - holder[iouCurrency](0), - tfSetFreeze | tfSetDeepFreeze)); + env(trust(issuer, holder[iouCurrency](0), tfSetFreeze | tfSetDeepFreeze)); }; auto unfreeze = [&](Account const& holder) { - env(trust( - issuer, - holder[iouCurrency](0), - tfClearFreeze | tfClearDeepFreeze)); + env(trust(issuer, holder[iouCurrency](0), tfClearFreeze | tfClearDeepFreeze)); }; - return std::make_tuple( - freeze, deepfreeze, unfreeze, tecFROZEN); + return std::make_tuple(freeze, deepfreeze, unfreeze, tecFROZEN); } else { auto freeze = [&](Account const& holder) { - mptt.set( - {.account = issuer, - .holder = holder, - .flags = tfMPTLock}); + mptt.set({.account = issuer, .holder = holder, .flags = tfMPTLock}); }; auto unfreeze = [&](Account const& holder) { - mptt.set( - {.account = issuer, - .holder = holder, - .flags = tfMPTUnlock}); + mptt.set({.account = issuer, .holder = holder, .flags = tfMPTUnlock}); }; return std::make_tuple(freeze, empty, unfreeze, tecLOCKED); } @@ -2054,13 +1783,12 @@ protected: // automatically.) env(trust(evan, issuer[iouCurrency](100'000))); - for (auto const& account : - {// these accounts can't be frozen, which deep freeze - // implies - vaultPseudo, - evan, - // these accounts can't be deep frozen - lender}) + for (auto const& account : {// these accounts can't be frozen, which deep freeze + // implies + vaultPseudo, + evan, + // these accounts can't be deep frozen + lender}) { // Freeze evan deepfreeze(account); @@ -2089,39 +1817,28 @@ protected: // Finally! Create a loan std::string testData; - auto coverAvailable = - [&env, this](uint256 const& brokerID, Number const& expected) { - if (auto const brokerSle = env.le(keylet::loanbroker(brokerID)); - BEAST_EXPECT(brokerSle)) - { - auto const available = brokerSle->at(sfCoverAvailable); - BEAST_EXPECT(available == expected); - return available; - } - return Number{}; - }; - auto getDefaultInfo = [&env, this]( - LoanState const& state, - BrokerInfo const& broker) { - if (auto const brokerSle = - env.le(keylet::loanbroker(broker.brokerID)); - BEAST_EXPECT(brokerSle)) + auto coverAvailable = [&env, this](uint256 const& brokerID, Number const& expected) { + if (auto const brokerSle = env.le(keylet::loanbroker(brokerID)); BEAST_EXPECT(brokerSle)) + { + auto const available = brokerSle->at(sfCoverAvailable); + BEAST_EXPECT(available == expected); + return available; + } + return Number{}; + }; + auto getDefaultInfo = [&env, this](LoanState const& state, BrokerInfo const& broker) { + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); BEAST_EXPECT(brokerSle)) { BEAST_EXPECT( - state.loanScale >= - (broker.asset.integral() - ? 0 - : std::max( - broker.vaultScale(env), - state.principalOutstanding.exponent()))); + state.loanScale >= (broker.asset.integral() + ? 0 + : std::max(broker.vaultScale(env), state.principalOutstanding.exponent()))); NumberRoundModeGuard mg(Number::upward); auto const defaultAmount = roundToAsset( broker.asset, std::min( tenthBipsOfValue( - tenthBipsOfValue( - brokerSle->at(sfDebtTotal), - broker.params.coverRateMin), + tenthBipsOfValue(brokerSle->at(sfDebtTotal), broker.params.coverRateMin), broker.params.coverRateLiquidation), state.totalValue - state.managementFeeOutstanding), state.loanScale); @@ -2134,34 +1851,25 @@ protected: AccountID const& brokerAcct, Number const& startingCoverAvailable, Number const& amountToBeCovered) { - coverAvailable( - broker.brokerID, startingCoverAvailable - amountToBeCovered); - env(loanBroker::coverDeposit( - brokerAcct, - broker.brokerID, - STAmount{broker.asset, amountToBeCovered})); + coverAvailable(broker.brokerID, startingCoverAvailable - amountToBeCovered); + env(loanBroker::coverDeposit(brokerAcct, broker.brokerID, STAmount{broker.asset, amountToBeCovered})); coverAvailable(broker.brokerID, startingCoverAvailable); env.close(); }; - auto defaultImmediately = [&](std::uint32_t baseFlag, - bool impair = true) { - return [&, impair, baseFlag]( - Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { + auto defaultImmediately = [&](std::uint32_t baseFlag, bool impair = true) { + return [&, impair, baseFlag](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { // toEndOfLife // // Default the loan // Initialize values with the current state - auto state = - getCurrentState(env, broker, loanKeylet, verifyLoanStatus); + auto state = getCurrentState(env, broker, loanKeylet, verifyLoanStatus); BEAST_EXPECT(state.flags == baseFlag); auto const& broker = verifyLoanStatus.broker; - auto const startingCoverAvailable = coverAvailable( - broker.brokerID, - broker.asset(broker.params.coverDeposit).number()); + auto const startingCoverAvailable = + coverAvailable(broker.brokerID, broker.asset(broker.params.coverDeposit).number()); if (impair) { @@ -2174,12 +1882,10 @@ protected: if (canImpair) { state.flags |= tfLoanImpair; - state.nextPaymentDate = - env.now().time_since_epoch().count(); + state.nextPaymentDate = env.now().time_since_epoch().count(); // Once the loan is impaired, it can't be impaired again - env(manage(lender, loanKeylet.key, tfLoanImpair), - ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanImpair), ter(tecNO_PERMISSION)); } verifyLoanStatus(state); } @@ -2188,15 +1894,13 @@ protected: // Can't default the loan yet. The grace period hasn't // expired - env(manage(lender, loanKeylet.key, tfLoanDefault), - ter(tecTOO_SOON)); + env(manage(lender, loanKeylet.key, tfLoanDefault), ter(tecTOO_SOON)); // Let some time pass so that the loan can be // defaulted env.close(nextDueDate + 60s); - auto const [amountToBeCovered, brokerAcct] = - getDefaultInfo(state, broker); + auto const [amountToBeCovered, brokerAcct] = getDefaultInfo(state, broker); // Default the loan env(manage(lender, loanKeylet.key, tfLoanDefault)); @@ -2204,11 +1908,7 @@ protected: // The LoanBroker just lost some of it's first-loss capital. // Replenish it. - replenishCover( - broker, - brokerAcct, - startingCoverAvailable, - amountToBeCovered); + replenishCover(broker, brokerAcct, startingCoverAvailable, amountToBeCovered); state.flags |= tfLoanDefault; state.paymentRemaining = 0; @@ -2219,13 +1919,10 @@ protected: verifyLoanStatus(state); // Once a loan is defaulted, it can't be managed - env(manage(lender, loanKeylet.key, tfLoanUnimpair), - ter(tecNO_PERMISSION)); - env(manage(lender, loanKeylet.key, tfLoanImpair), - ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanUnimpair), ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanImpair), ter(tecNO_PERMISSION)); // Can't make a payment on it either - env(pay(borrower, loanKeylet.key, broker.asset(300)), - ter(tecKILLED)); + env(pay(borrower, loanKeylet.key, broker.asset(300)), ter(tecKILLED)); }; }; @@ -2241,19 +1938,12 @@ protected: verifyLoanStatus(state); // Send some bogus pay transactions - env(pay(borrower, - keylet::loan(uint256(0)).key, - broker.asset(10), - txFlags), - ter(temINVALID)); + env(pay(borrower, keylet::loan(uint256(0)).key, broker.asset(10), txFlags), ter(temINVALID)); // broker.asset(80) is less than a single payment, but all these // checks fail before that matters - env(pay(borrower, loanKeylet.key, broker.asset(-80), txFlags), - ter(temBAD_AMOUNT)); - env(pay(borrower, broker.brokerID, broker.asset(80), txFlags), - ter(tecNO_ENTRY)); - env(pay(evan, loanKeylet.key, broker.asset(80), txFlags), - ter(tecNO_PERMISSION)); + env(pay(borrower, loanKeylet.key, broker.asset(-80), txFlags), ter(temBAD_AMOUNT)); + env(pay(borrower, broker.brokerID, broker.asset(80), txFlags), ter(tecNO_ENTRY)); + env(pay(evan, loanKeylet.key, broker.asset(80), txFlags), ter(tecNO_PERMISSION)); // TODO: Write a general "isFlag" function? See STObject::isFlag. // Maybe add a static overloaded member? @@ -2264,13 +1954,9 @@ protected: // don't end up duplicating the next test transaction. env(pay(borrower, loanKeylet.key, - STAmount{ - broker.asset, - state.periodicPayment * Number{15, -1}}, + STAmount{broker.asset, state.periodicPayment * Number{15, -1}}, tfLoanOverpayment), - fee(XRPAmount{ - baseFee * - (Number{15, -1} / loanPaymentsPerFeeIncrement + 1)}), + fee(XRPAmount{baseFee * (Number{15, -1} / loanPaymentsPerFeeIncrement + 1)}), ter(temINVALID_FLAG)); } // Try to send a payment marked as multiple mutually exclusive @@ -2298,24 +1984,16 @@ protected: ter(temINVALID_FLAG)); { - auto const otherAsset = broker.asset.raw() == assets[0].raw() - ? assets[1] - : assets[0]; - env(pay(borrower, loanKeylet.key, otherAsset(100), txFlags), - ter(tecWRONG_ASSET)); + auto const otherAsset = broker.asset.raw() == assets[0].raw() ? assets[1] : assets[0]; + env(pay(borrower, loanKeylet.key, otherAsset(100), txFlags), ter(tecWRONG_ASSET)); } // Amount doesn't cover a single payment - env(pay(borrower, - loanKeylet.key, - STAmount{broker.asset, 1}, - txFlags), - ter(tecINSUFFICIENT_PAYMENT)); + env(pay(borrower, loanKeylet.key, STAmount{broker.asset, 1}, txFlags), ter(tecINSUFFICIENT_PAYMENT)); // Get the balance after these failed transactions take // fees - auto const borrowerBalanceBeforePayment = - env.balance(borrower, broker.asset); + auto const borrowerBalanceBeforePayment = env.balance(borrower, broker.asset); BEAST_EXPECT(payoffAmount > state.principalOutstanding); // Try to pay a little extra to show that it's _not_ @@ -2326,22 +2004,16 @@ protected: // balance XRPAmount const badFee{ baseFee * - (borrowerBalanceBeforePayment.number() * 2 / - state.periodicPayment / loanPaymentsPerFeeIncrement + - 1)}; + (borrowerBalanceBeforePayment.number() * 2 / state.periodicPayment / loanPaymentsPerFeeIncrement + 1)}; env(pay(borrower, loanKeylet.key, - STAmount{ - broker.asset, - borrowerBalanceBeforePayment.number() * 2}, + STAmount{broker.asset, borrowerBalanceBeforePayment.number() * 2}, txFlags), fee(badFee), ter(tecINSUFFICIENT_FUNDS)); - XRPAmount const goodFee{ - baseFee * (numPayments / loanPaymentsPerFeeIncrement + 1)}; - env(pay(borrower, loanKeylet.key, transactionAmount, txFlags), - fee(goodFee)); + XRPAmount const goodFee{baseFee * (numPayments / loanPaymentsPerFeeIncrement + 1)}; + env(pay(borrower, loanKeylet.key, transactionAmount, txFlags), fee(goodFee)); env.close(); @@ -2358,33 +2030,23 @@ protected: state.principalOutstanding = 0; state.totalValue = 0; state.managementFeeOutstanding = 0; - state.previousPaymentDate = state.nextPaymentDate + - state.paymentInterval * (numPayments - 1); + state.previousPaymentDate = state.nextPaymentDate + state.paymentInterval * (numPayments - 1); state.nextPaymentDate = 0; verifyLoanStatus(state); verifyLoanStatus.checkPayment( - state.loanScale, - borrower, - borrowerBalanceBeforePayment, - payoffAmount, - adjustment); + state.loanScale, borrower, borrowerBalanceBeforePayment, payoffAmount, adjustment); // Can't impair or default a paid off loan - env(manage(lender, loanKeylet.key, tfLoanImpair), - ter(tecNO_PERMISSION)); - env(manage(lender, loanKeylet.key, tfLoanDefault), - ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanImpair), ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanDefault), ter(tecNO_PERMISSION)); }; auto fullPayment = [&](std::uint32_t baseFlag) { - return [&, baseFlag]( - Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { + return [&, baseFlag](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { // toEndOfLife // - auto state = - getCurrentState(env, broker, loanKeylet, verifyLoanStatus); + auto state = getCurrentState(env, broker, loanKeylet, verifyLoanStatus); env.close(state.startDate + 20s); auto const loanAge = (env.now() - state.startDate).count(); BEAST_EXPECT(loanAge == 30); @@ -2398,79 +2060,48 @@ protected: // to verify they're working correctly The numbers in // the below BEAST_EXPECTs may not hold across assets. Number const interval = state.paymentInterval; - auto const periodicRate = - interval * Number(12, -2) / secondsInYear; - BEAST_EXPECT( - periodicRate == - Number(2283105022831050228ULL, -24, Number::normalized{})); - STAmount const principalOutstanding{ - broker.asset, state.principalOutstanding}; + auto const periodicRate = interval * Number(12, -2) / secondsInYear; + BEAST_EXPECT(periodicRate == Number(2283105022831050228ULL, -24, Number::normalized{})); + STAmount const principalOutstanding{broker.asset, state.principalOutstanding}; STAmount const accruedInterest{ - broker.asset, - state.principalOutstanding * periodicRate * loanAge / - interval}; - BEAST_EXPECT( - accruedInterest == - broker.asset(Number(1141552511415525, -19))); - STAmount const prepaymentPenalty{ - broker.asset, state.principalOutstanding * Number(36, -3)}; + broker.asset, state.principalOutstanding * periodicRate * loanAge / interval}; + BEAST_EXPECT(accruedInterest == broker.asset(Number(1141552511415525, -19))); + STAmount const prepaymentPenalty{broker.asset, state.principalOutstanding * Number(36, -3)}; BEAST_EXPECT(prepaymentPenalty == broker.asset(36)); STAmount const closePaymentFee = broker.asset(4); auto const payoffAmount = roundToScale( - principalOutstanding + accruedInterest + prepaymentPenalty + - closePaymentFee, - state.loanScale); + principalOutstanding + accruedInterest + prepaymentPenalty + closePaymentFee, state.loanScale); BEAST_EXPECT( payoffAmount == - roundToAsset( - broker.asset, - broker.asset(Number(1040000114155251, -12)).number(), - state.loanScale)); + roundToAsset(broker.asset, broker.asset(Number(1040000114155251, -12)).number(), state.loanScale)); // The terms of this loan actually make the early payoff // more expensive than just making payments - BEAST_EXPECT( - payoffAmount > state.paymentRemaining * - (state.periodicPayment + broker.asset(2).value())); + BEAST_EXPECT(payoffAmount > state.paymentRemaining * (state.periodicPayment + broker.asset(2).value())); - singlePayment( - loanKeylet, - verifyLoanStatus, - state, - payoffAmount, - 1, - baseFlag, - tfLoanFullPayment); + singlePayment(loanKeylet, verifyLoanStatus, state, payoffAmount, 1, baseFlag, tfLoanFullPayment); }; }; auto combineAllPayments = [&](std::uint32_t baseFlag) { - return [&, baseFlag]( - Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { + return [&, baseFlag](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { // toEndOfLife // - auto state = - getCurrentState(env, broker, loanKeylet, verifyLoanStatus); + auto state = getCurrentState(env, broker, loanKeylet, verifyLoanStatus); env.close(); BEAST_EXPECT( - STAmount(broker.asset, state.periodicPayment) == - broker.asset(Number(8333457002039338267, -17))); + STAmount(broker.asset, state.periodicPayment) == broker.asset(Number(8333457002039338267, -17))); // Make all the payments in one transaction // service fee is 2 auto const startingPayments = state.paymentRemaining; STAmount const payoffAmount = [&]() { NumberRoundModeGuard mg(Number::upward); - auto const rawPayoff = startingPayments * - (state.periodicPayment + broker.asset(2).value()); + auto const rawPayoff = startingPayments * (state.periodicPayment + broker.asset(2).value()); STAmount payoffAmount{broker.asset, rawPayoff}; - BEAST_EXPECTS( - payoffAmount == - broker.asset(Number(1024014840244721, -12)), - to_string(payoffAmount)); + BEAST_EXPECTS(payoffAmount == broker.asset(Number(1024014840244721, -12)), to_string(payoffAmount)); BEAST_EXPECT(payoffAmount > state.principalOutstanding); payoffAmount = roundToScale(payoffAmount, state.loanScale); @@ -2478,24 +2109,14 @@ protected: return payoffAmount; }(); - auto const totalPayoffValue = state.totalValue + - startingPayments * broker.asset(2).value(); - STAmount const totalPayoffAmount{ - broker.asset, totalPayoffValue}; + auto const totalPayoffValue = state.totalValue + startingPayments * broker.asset(2).value(); + STAmount const totalPayoffAmount{broker.asset, totalPayoffValue}; BEAST_EXPECTS( totalPayoffAmount == payoffAmount, - "Payoff amount: " + to_string(payoffAmount) + - ". Total Value: " + to_string(totalPayoffAmount)); + "Payoff amount: " + to_string(payoffAmount) + ". Total Value: " + to_string(totalPayoffAmount)); - singlePayment( - loanKeylet, - verifyLoanStatus, - state, - payoffAmount, - state.paymentRemaining, - baseFlag, - 0); + singlePayment(loanKeylet, verifyLoanStatus, state, payoffAmount, state.paymentRemaining, baseFlag, 0); }; }; @@ -2627,13 +2248,11 @@ protected: broker, pseudoAcct, 0, - [&](Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { + [&](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { // toEndOfLife // // Draw and make multiple payments - auto state = - getCurrentState(env, broker, loanKeylet, verifyLoanStatus); + auto state = getCurrentState(env, broker, loanKeylet, verifyLoanStatus); BEAST_EXPECT(state.flags == 0); env.close(); @@ -2652,152 +2271,105 @@ protected: // to verify they're working correctly The numbers in // the below BEAST_EXPECTs may not hold across assets. Number const interval = state.paymentInterval; - auto const periodicRate = - interval * Number(12, -2) / secondsInYear; - BEAST_EXPECT( - periodicRate == - Number(2283105022831050228, -24, Number::normalized{})); + auto const periodicRate = interval * Number(12, -2) / secondsInYear; + BEAST_EXPECT(periodicRate == Number(2283105022831050228, -24, Number::normalized{})); STAmount const roundedPeriodicPayment{ - broker.asset, - roundPeriodicPayment( - broker.asset, state.periodicPayment, state.loanScale)}; + broker.asset, roundPeriodicPayment(broker.asset, state.periodicPayment, state.loanScale)}; - testcase - << currencyLabel << " Payment components: " - << "Payments remaining, rawInterest, rawPrincipal, " - "rawMFee, trackedValueDelta, trackedPrincipalDelta, " - "trackedInterestDelta, trackedMgmtFeeDelta, special"; + testcase << currencyLabel << " Payment components: " + << "Payments remaining, rawInterest, rawPrincipal, " + "rawMFee, trackedValueDelta, trackedPrincipalDelta, " + "trackedInterestDelta, trackedMgmtFeeDelta, special"; auto const serviceFee = broker.asset(2); BEAST_EXPECT( roundedPeriodicPayment == roundToScale( - broker.asset( - Number(8333457002039338267, -17), Number::upward), + broker.asset(Number(8333457002039338267, -17), Number::upward), state.loanScale, Number::upward)); // 83334570.01162141 // Include the service fee - STAmount const totalDue = roundToScale( - roundedPeriodicPayment + serviceFee, - state.loanScale, - Number::upward); + STAmount const totalDue = + roundToScale(roundedPeriodicPayment + serviceFee, state.loanScale, Number::upward); // Only check the first payment since the rounding // may drift as payments are made BEAST_EXPECT( totalDue == roundToScale( - broker.asset( - Number(8533457002039338267, -17), Number::upward), + broker.asset(Number(8533457002039338267, -17), Number::upward), state.loanScale, Number::upward)); { auto const raw = computeTheoreticalLoanState( - state.periodicPayment, - periodicRate, - state.paymentRemaining, - broker.params.managementFeeRate); + state.periodicPayment, periodicRate, state.paymentRemaining, broker.params.managementFeeRate); auto const rounded = constructLoanState( - state.totalValue, - state.principalOutstanding, - state.managementFeeOutstanding); - testcase - << currencyLabel - << " Loan starting state: " << state.paymentRemaining - << ", " << raw.interestDue << ", " - << raw.principalOutstanding << ", " - << raw.managementFeeDue << ", " - << rounded.valueOutstanding << ", " - << rounded.principalOutstanding << ", " - << rounded.interestDue << ", " - << rounded.managementFeeDue; + state.totalValue, state.principalOutstanding, state.managementFeeOutstanding); + testcase << currencyLabel << " Loan starting state: " << state.paymentRemaining << ", " + << raw.interestDue << ", " << raw.principalOutstanding << ", " << raw.managementFeeDue + << ", " << rounded.valueOutstanding << ", " << rounded.principalOutstanding << ", " + << rounded.interestDue << ", " << rounded.managementFeeDue; } // Try to pay a little extra to show that it's _not_ // taken - STAmount const transactionAmount = - STAmount{broker.asset, totalDue} + broker.asset(10); + STAmount const transactionAmount = STAmount{broker.asset, totalDue} + broker.asset(10); // Only check the first payment since the rounding // may drift as payments are made BEAST_EXPECT( transactionAmount == roundToScale( - broker.asset( - Number(9533457002039400, -14), Number::upward), - state.loanScale, - Number::upward)); + broker.asset(Number(9533457002039400, -14), Number::upward), state.loanScale, Number::upward)); auto const initialState = state; detail::PaymentComponents totalPaid{ - .trackedValueDelta = 0, - .trackedPrincipalDelta = 0, - .trackedManagementFeeDelta = 0}; + .trackedValueDelta = 0, .trackedPrincipalDelta = 0, .trackedManagementFeeDelta = 0}; Number totalInterestPaid = 0; std::size_t totalPaymentsMade = 0; xrpl::LoanState currentTrueState = computeTheoreticalLoanState( - state.periodicPayment, - periodicRate, - state.paymentRemaining, - broker.params.managementFeeRate); + state.periodicPayment, periodicRate, state.paymentRemaining, broker.params.managementFeeRate); while (state.paymentRemaining > 0) { // Compute the expected principal amount - auto const paymentComponents = - detail::computePaymentComponents( - broker.asset.raw(), - state.loanScale, - state.totalValue, - state.principalOutstanding, - state.managementFeeOutstanding, - state.periodicPayment, - periodicRate, - state.paymentRemaining, - broker.params.managementFeeRate); + auto const paymentComponents = detail::computePaymentComponents( + broker.asset.raw(), + state.loanScale, + state.totalValue, + state.principalOutstanding, + state.managementFeeOutstanding, + state.periodicPayment, + periodicRate, + state.paymentRemaining, + broker.params.managementFeeRate); BEAST_EXPECTS( - paymentComponents.specialCase == - detail::PaymentSpecialCase::final || - paymentComponents.trackedValueDelta <= - roundedPeriodicPayment, - "Delta: " + - to_string(paymentComponents.trackedValueDelta) + - ", periodic payment: " + - to_string(roundedPeriodicPayment)); + paymentComponents.specialCase == detail::PaymentSpecialCase::final || + paymentComponents.trackedValueDelta <= roundedPeriodicPayment, + "Delta: " + to_string(paymentComponents.trackedValueDelta) + + ", periodic payment: " + to_string(roundedPeriodicPayment)); - xrpl::LoanState const nextTrueState = - computeTheoreticalLoanState( - state.periodicPayment, - periodicRate, - state.paymentRemaining - 1, - broker.params.managementFeeRate); - detail::LoanStateDeltas const deltas = - currentTrueState - nextTrueState; + xrpl::LoanState const nextTrueState = computeTheoreticalLoanState( + state.periodicPayment, + periodicRate, + state.paymentRemaining - 1, + broker.params.managementFeeRate); + detail::LoanStateDeltas const deltas = currentTrueState - nextTrueState; - testcase - << currencyLabel - << " Payment components: " << state.paymentRemaining - << ", " << deltas.interest << ", " << deltas.principal - << ", " << deltas.managementFee << ", " - << paymentComponents.trackedValueDelta << ", " - << paymentComponents.trackedPrincipalDelta << ", " - << paymentComponents.trackedInterestPart() << ", " - << paymentComponents.trackedManagementFeeDelta << ", " - << (paymentComponents.specialCase == - detail::PaymentSpecialCase::final - ? "final" - : paymentComponents.specialCase == - detail::PaymentSpecialCase::extra - ? "extra" - : "none"); + testcase << currencyLabel << " Payment components: " << state.paymentRemaining << ", " + << deltas.interest << ", " << deltas.principal << ", " << deltas.managementFee << ", " + << paymentComponents.trackedValueDelta << ", " << paymentComponents.trackedPrincipalDelta + << ", " << paymentComponents.trackedInterestPart() << ", " + << paymentComponents.trackedManagementFeeDelta << ", " + << (paymentComponents.specialCase == detail::PaymentSpecialCase::final ? "final" + : paymentComponents.specialCase == detail::PaymentSpecialCase::extra ? "extra" + : "none"); - auto const totalDueAmount = STAmount{ - broker.asset, - paymentComponents.trackedValueDelta + - serviceFee.number()}; + auto const totalDueAmount = + STAmount{broker.asset, paymentComponents.trackedValueDelta + serviceFee.number()}; // Due to the rounding algorithms to keep the interest and // principal in sync with "true" values, the computed amount @@ -2807,58 +2379,39 @@ protected: // IOUs, the difference should be after the 8th digit. Number const diff = totalDue - totalDueAmount; BEAST_EXPECT( - paymentComponents.specialCase == - detail::PaymentSpecialCase::final || - diff == beast::zero || + paymentComponents.specialCase == detail::PaymentSpecialCase::final || diff == beast::zero || (diff > beast::zero && - ((broker.asset.integral() && - (static_cast(diff) < 3)) || + ((broker.asset.integral() && (static_cast(diff) < 3)) || (state.loanScale - diff.exponent() > 13)))); BEAST_EXPECT( paymentComponents.trackedValueDelta == - paymentComponents.trackedPrincipalDelta + - paymentComponents.trackedInterestPart() + + paymentComponents.trackedPrincipalDelta + paymentComponents.trackedInterestPart() + paymentComponents.trackedManagementFeeDelta); BEAST_EXPECT( - paymentComponents.specialCase == - detail::PaymentSpecialCase::final || - paymentComponents.trackedValueDelta <= - roundedPeriodicPayment); + paymentComponents.specialCase == detail::PaymentSpecialCase::final || + paymentComponents.trackedValueDelta <= roundedPeriodicPayment); BEAST_EXPECT( state.paymentRemaining < 12 || - roundToAsset( - broker.asset, - deltas.principal, - state.loanScale, - Number::upward) == + roundToAsset(broker.asset, deltas.principal, state.loanScale, Number::upward) == roundToScale( - broker.asset( - Number(8333228691531218890, -17), - Number::upward), + broker.asset(Number(8333228691531218890, -17), Number::upward), state.loanScale, Number::upward)); BEAST_EXPECT( - paymentComponents.trackedPrincipalDelta >= - beast::zero && - paymentComponents.trackedPrincipalDelta <= - state.principalOutstanding); + paymentComponents.trackedPrincipalDelta >= beast::zero && + paymentComponents.trackedPrincipalDelta <= state.principalOutstanding); BEAST_EXPECT( - paymentComponents.specialCase != - detail::PaymentSpecialCase::final || - paymentComponents.trackedPrincipalDelta == - state.principalOutstanding); + paymentComponents.specialCase != detail::PaymentSpecialCase::final || + paymentComponents.trackedPrincipalDelta == state.principalOutstanding); BEAST_EXPECT( - paymentComponents.specialCase == - detail::PaymentSpecialCase::final || + paymentComponents.specialCase == detail::PaymentSpecialCase::final || (state.periodicPayment.exponent() - - (deltas.principal + deltas.interest + - deltas.managementFee - state.periodicPayment) + (deltas.principal + deltas.interest + deltas.managementFee - state.periodicPayment) .exponent()) > 14); - auto const borrowerBalanceBeforePayment = - env.balance(borrower, broker.asset); + auto const borrowerBalanceBeforePayment = env.balance(borrower, broker.asset); if (canImpairLoan(env, broker, state)) // Making a payment will unimpair the loan @@ -2880,16 +2433,11 @@ protected: // Check the result verifyLoanStatus.checkPayment( - state.loanScale, - borrower, - borrowerBalanceBeforePayment, - totalDueAmount, - adjustment); + state.loanScale, borrower, borrowerBalanceBeforePayment, totalDueAmount, adjustment); --state.paymentRemaining; state.previousPaymentDate = state.nextPaymentDate; - if (paymentComponents.specialCase == - detail::PaymentSpecialCase::final) + if (paymentComponents.specialCase == detail::PaymentSpecialCase::final) { state.paymentRemaining = 0; state.nextPaymentDate = 0; @@ -2898,22 +2446,16 @@ protected: { state.nextPaymentDate += state.paymentInterval; } - state.principalOutstanding -= - paymentComponents.trackedPrincipalDelta; - state.managementFeeOutstanding -= - paymentComponents.trackedManagementFeeDelta; + state.principalOutstanding -= paymentComponents.trackedPrincipalDelta; + state.managementFeeOutstanding -= paymentComponents.trackedManagementFeeDelta; state.totalValue -= paymentComponents.trackedValueDelta; verifyLoanStatus(state); - totalPaid.trackedValueDelta += - paymentComponents.trackedValueDelta; - totalPaid.trackedPrincipalDelta += - paymentComponents.trackedPrincipalDelta; - totalPaid.trackedManagementFeeDelta += - paymentComponents.trackedManagementFeeDelta; - totalInterestPaid += - paymentComponents.trackedInterestPart(); + totalPaid.trackedValueDelta += paymentComponents.trackedValueDelta; + totalPaid.trackedPrincipalDelta += paymentComponents.trackedPrincipalDelta; + totalPaid.trackedManagementFeeDelta += paymentComponents.trackedManagementFeeDelta; + totalInterestPaid += paymentComponents.trackedInterestPart(); ++totalPaymentsMade; currentTrueState = nextTrueState; @@ -2924,29 +2466,20 @@ protected: BEAST_EXPECT(state.principalOutstanding == 0); // Make sure all the payments add up - BEAST_EXPECT( - totalPaid.trackedValueDelta == initialState.totalValue); - BEAST_EXPECT( - totalPaid.trackedPrincipalDelta == - initialState.principalOutstanding); - BEAST_EXPECT( - totalPaid.trackedManagementFeeDelta == - initialState.managementFeeOutstanding); + BEAST_EXPECT(totalPaid.trackedValueDelta == initialState.totalValue); + BEAST_EXPECT(totalPaid.trackedPrincipalDelta == initialState.principalOutstanding); + BEAST_EXPECT(totalPaid.trackedManagementFeeDelta == initialState.managementFeeOutstanding); // This is almost a tautology given the previous checks, but // check it anyway for completeness. BEAST_EXPECT( totalInterestPaid == initialState.totalValue - - (initialState.principalOutstanding + - initialState.managementFeeOutstanding)); - BEAST_EXPECT( - totalPaymentsMade == initialState.paymentRemaining); + (initialState.principalOutstanding + initialState.managementFeeOutstanding)); + BEAST_EXPECT(totalPaymentsMade == initialState.paymentRemaining); // Can't impair or default a paid off loan - env(manage(lender, loanKeylet.key, tfLoanImpair), - ter(tecNO_PERMISSION)); - env(manage(lender, loanKeylet.key, tfLoanDefault), - ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanImpair), ter(tecNO_PERMISSION)); + env(manage(lender, loanKeylet.key, tfLoanDefault), ter(tecNO_PERMISSION)); }); #if LOANTODO @@ -2969,8 +2502,7 @@ protected: auto const start = clock_type::now(); timed(); - auto const duration = std::chrono::duration_cast( - clock_type::now() - start); + auto const duration = std::chrono::duration_cast(clock_type::now() - start); log << label << " took " << duration.count() << "ms" << std::endl; @@ -2989,45 +2521,32 @@ protected: broker, pseudoAcct, tfLoanOverpayment, - [&](Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { + [&](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { // Estimate optimal values for loanPaymentsPerFeeIncrement and // loanMaximumPaymentsPerTransaction. using namespace loan; - auto const state = - getCurrentState(env, broker, verifyLoanStatus.keylet); + auto const state = getCurrentState(env, broker, verifyLoanStatus.keylet); auto const serviceFee = broker.asset(2).value(); STAmount const totalDue{ broker.asset, - roundPeriodicPayment( - broker.asset, - state.periodicPayment + serviceFee, - state.loanScale)}; + roundPeriodicPayment(broker.asset, state.periodicPayment + serviceFee, state.loanScale)}; // Make a single payment - time("single payment", [&]() { - env(pay(borrower, loanKeylet.key, totalDue)); - }); + time("single payment", [&]() { env(pay(borrower, loanKeylet.key, totalDue)); }); env.close(); // Make all but the final payment auto const numPayments = (state.paymentRemaining - 2); STAmount const bigPayment{broker.asset, totalDue * numPayments}; - XRPAmount const bigFee{ - baseFee * (numPayments / loanPaymentsPerFeeIncrement + 1)}; - time("ten payments", [&]() { - env(pay(borrower, loanKeylet.key, bigPayment), fee(bigFee)); - }); + XRPAmount const bigFee{baseFee * (numPayments / loanPaymentsPerFeeIncrement + 1)}; + time("ten payments", [&]() { env(pay(borrower, loanKeylet.key, bigPayment), fee(bigFee)); }); env.close(); time("final payment", [&]() { // Make the final payment - env( - pay(borrower, - loanKeylet.key, - totalDue + STAmount{broker.asset, 1})); + env(pay(borrower, loanKeylet.key, totalDue + STAmount{broker.asset, 1})); }); env.close(); }); @@ -3044,8 +2563,7 @@ protected: broker, pseudoAcct, tfLoanOverpayment, - [&](Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); + [&](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); lifecycle( caseLabel, @@ -3059,8 +2577,7 @@ protected: broker, pseudoAcct, tfLoanOverpayment, - [&](Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); + [&](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); lifecycle( caseLabel, @@ -3074,8 +2591,7 @@ protected: broker, pseudoAcct, tfLoanOverpayment, - [&](Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); + [&](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); lifecycle( caseLabel, @@ -3089,8 +2605,7 @@ protected: broker, pseudoAcct, tfLoanOverpayment, - [&](Keylet const& loanKeylet, - VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); + [&](Keylet const& loanKeylet, VerifyLoanStatus const& verifyLoanStatus) { throw 0; }); #endif } @@ -3111,81 +2626,76 @@ protected: int initialXRP = 1'000'000; }; - auto const testCase = - [&, this]( - std::function - mptTest, - std::function iouTest, - CaseArgs args = {}) { - Env env(*this, all); - env.fund(XRP(args.initialXRP), issuer, lender, borrower); + auto const testCase = [&, this]( + std::function mptTest, + std::function iouTest, + CaseArgs args = {}) { + Env env(*this, all); + env.fund(XRP(args.initialXRP), issuer, lender, borrower); + env.close(); + if (args.requireAuth) + { + env(fset(issuer, asfRequireAuth)); env.close(); - if (args.requireAuth) - { - env(fset(issuer, asfRequireAuth)); - env.close(); - } + } - // We need two different asset types, MPT and IOU. Prepare MPT - // first - MPTTester mptt{env, issuer, mptInitNoFund}; + // We need two different asset types, MPT and IOU. Prepare MPT + // first + MPTTester mptt{env, issuer, mptInitNoFund}; - auto const none = LedgerSpecificFlags(0); - mptt.create( - {.flags = tfMPTCanTransfer | tfMPTCanLock | - (args.requireAuth ? tfMPTRequireAuth : none)}); + auto const none = LedgerSpecificFlags(0); + mptt.create({.flags = tfMPTCanTransfer | tfMPTCanLock | (args.requireAuth ? tfMPTRequireAuth : none)}); + env.close(); + PrettyAsset mptAsset = mptt.issuanceID(); + mptt.authorize({.account = lender}); + mptt.authorize({.account = borrower}); + env.close(); + if (args.requireAuth) + { + mptt.authorize({.account = issuer, .holder = lender}); + if (args.authorizeBorrower) + mptt.authorize({.account = issuer, .holder = borrower}); env.close(); - PrettyAsset mptAsset = mptt.issuanceID(); - mptt.authorize({.account = lender}); - mptt.authorize({.account = borrower}); - env.close(); - if (args.requireAuth) - { - mptt.authorize({.account = issuer, .holder = lender}); - if (args.authorizeBorrower) - mptt.authorize({.account = issuer, .holder = borrower}); - env.close(); - } + } - env(pay(issuer, lender, mptAsset(10'000'000))); - env.close(); + env(pay(issuer, lender, mptAsset(10'000'000))); + env.close(); - // Prepare IOU - PrettyAsset const iouAsset = issuer[iouCurrency]; - env(trust(lender, iouAsset(10'000'000))); - env(trust(borrower, iouAsset(10'000'000))); - env.close(); - if (args.requireAuth) + // Prepare IOU + PrettyAsset const iouAsset = issuer[iouCurrency]; + env(trust(lender, iouAsset(10'000'000))); + env(trust(borrower, iouAsset(10'000'000))); + env.close(); + if (args.requireAuth) + { + env(trust(issuer, iouAsset(0), lender, tfSetfAuth)); + env(pay(issuer, lender, iouAsset(10'000'000))); + if (args.authorizeBorrower) { - env(trust(issuer, iouAsset(0), lender, tfSetfAuth)); - env(pay(issuer, lender, iouAsset(10'000'000))); - if (args.authorizeBorrower) - { - env(trust(issuer, iouAsset(0), borrower, tfSetfAuth)); - env(pay(issuer, borrower, iouAsset(10'000))); - } - } - else - { - env(pay(issuer, lender, iouAsset(10'000'000))); + env(trust(issuer, iouAsset(0), borrower, tfSetfAuth)); env(pay(issuer, borrower, iouAsset(10'000))); } - env.close(); + } + else + { + env(pay(issuer, lender, iouAsset(10'000'000))); + env(pay(issuer, borrower, iouAsset(10'000))); + } + env.close(); - // Create vaults and loan brokers - std::array const assets{mptAsset, iouAsset}; - std::vector brokers; - for (auto const& asset : assets) - { - brokers.emplace_back( - createVaultAndBroker(env, asset, lender)); - } + // Create vaults and loan brokers + std::array const assets{mptAsset, iouAsset}; + std::vector brokers; + for (auto const& asset : assets) + { + brokers.emplace_back(createVaultAndBroker(env, asset, lender)); + } - if (mptTest) - (mptTest)(env, brokers[0], mptt); - if (iouTest) - (iouTest)(env, brokers[1]); - }; + if (mptTest) + (mptTest)(env, brokers[0], mptt); + if (iouTest) + (iouTest)(env, brokers[1]); + }; testCase( [&, this](Env& env, BrokerInfo const& broker, auto&) { @@ -3264,10 +2774,8 @@ protected: auto const [acctReserve, incReserve] = [this]() -> std::pair { Env env{*this, testable_amendments()}; return { - env.current()->fees().accountReserve(0).drops() / - DROPS_PER_XRP.drops(), - env.current()->fees().increment.drops() / - DROPS_PER_XRP.drops()}; + env.current()->fees().accountReserve(0).drops() / DROPS_PER_XRP.drops(), + env.current()->fees().increment.drops() / DROPS_PER_XRP.drops()}; }(); testCase( @@ -3278,12 +2786,10 @@ protected: testcase( "MPT authorized borrower, borrower submits, borrower has " "no reserve"); - mptt.authorize( - {.account = borrower, .flags = tfMPTUnauthorize}); + mptt.authorize({.account = borrower, .flags = tfMPTUnauthorize}); env.close(); - auto const mptoken = - keylet::mptoken(mptt.issuanceID(), borrower); + auto const mptoken = keylet::mptoken(mptt.issuanceID(), borrower); auto const sleMPT1 = env.le(mptoken); BEAST_EXPECT(sleMPT1 == nullptr); @@ -3329,8 +2835,7 @@ protected: env(pay(borrower, issuer, broker.asset(10'000))); env.close(); - auto const trustline = - keylet::line(borrower, broker.asset.raw().get()); + auto const trustline = keylet::line(borrower, broker.asset.raw().get()); auto const sleLine1 = env.le(trustline); BEAST_EXPECT(sleLine1 == nullptr); @@ -3372,8 +2877,7 @@ protected: auto const sleMPT1 = env.le(mptoken); BEAST_EXPECT(sleMPT1 != nullptr); - env(pay( - lender, issuer, broker.asset(sleMPT1->at(sfMPTAmount)))); + env(pay(lender, issuer, broker.asset(sleMPT1->at(sfMPTAmount)))); env.close(); mptt.authorize({.account = lender, .flags = tfMPTUnauthorize}); @@ -3424,15 +2928,11 @@ protected: env.trust(broker.asset(0), lender); env.close(); - auto const trustline = - keylet::line(lender, broker.asset.raw().get()); + auto const trustline = keylet::line(lender, broker.asset.raw().get()); auto const sleLine1 = env.le(trustline); BEAST_EXPECT(sleLine1 != nullptr); - env( - pay(lender, - issuer, - broker.asset(abs(sleLine1->at(sfBalance).value())))); + env(pay(lender, issuer, broker.asset(abs(sleLine1->at(sfBalance).value())))); env.close(); auto const sleLine2 = env.le(trustline); BEAST_EXPECT(sleLine2 == nullptr); @@ -3475,8 +2975,7 @@ protected: auto const sleMPT1 = env.le(mptoken); BEAST_EXPECT(sleMPT1 != nullptr); - env(pay( - lender, issuer, broker.asset(sleMPT1->at(sfMPTAmount)))); + env(pay(lender, issuer, broker.asset(sleMPT1->at(sfMPTAmount)))); env.close(); mptt.authorize({.account = lender, .flags = tfMPTUnauthorize}); @@ -3648,9 +3147,7 @@ protected: Number const principalRequest = broker.asset(1'000).value(); Vault vault{env}; auto tx = vault.set({.owner = lender, .id = broker.vaultID}); - tx[sfAssetsMaximum] = - BrokerParameters::defaults().vaultDeposit + - broker.asset(1).number(); + tx[sfAssetsMaximum] = BrokerParameters::defaults().vaultDeposit + broker.asset(1).number(); env(tx); env.close(); @@ -3707,8 +3204,7 @@ protected: env.close(); MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); // Scale the MPT asset a little bit so we can get some interest PrettyAsset const mptAsset{mptt.issuanceID(), 100}; mptt.authorize({.account = lender}); @@ -3726,11 +3222,8 @@ protected: std::vector brokers; for (auto const& asset : assets) { - brokers.emplace_back(createVaultAndBroker( - env, - asset, - lender, - BrokerParameters{.data = "spam spam spam spam"})); + brokers.emplace_back( + createVaultAndBroker(env, asset, lender, BrokerParameters{.data = "spam spam spam spam"})); } // Create and update Loans @@ -3739,30 +3232,19 @@ protected: for (int amountExponent = 3; amountExponent >= 3; --amountExponent) { Number const loanAmount{1, amountExponent}; - for (int interestExponent = 0; interestExponent >= 0; - --interestExponent) + for (int interestExponent = 0; interestExponent >= 0; --interestExponent) { - testCaseWrapper( - env, - mptt, - assets, - broker, - loanAmount, - interestExponent); + testCaseWrapper(env, mptt, assets, broker, loanAmount, interestExponent); } } - if (auto brokerSle = env.le(keylet::loanbroker(broker.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto brokerSle = env.le(keylet::loanbroker(broker.brokerID)); BEAST_EXPECT(brokerSle)) { BEAST_EXPECT(brokerSle->at(sfOwnerCount) == 0); BEAST_EXPECT(brokerSle->at(sfDebtTotal) == 0); auto const coverAvailable = brokerSle->at(sfCoverAvailable); - env(loanBroker::coverWithdraw( - lender, - broker.brokerID, - STAmount(broker.asset, coverAvailable))); + env(loanBroker::coverWithdraw(lender, broker.brokerID, STAmount(broker.asset, coverAvailable))); env.close(); brokerSle = env.le(keylet::loanbroker(broker.brokerID)); @@ -3808,17 +3290,13 @@ protected: // The LoanSet json can be created without a counterparty signature, // but it will not pass preflight - auto createJson = env.json( - set(lender, - broker.brokerID, - broker.asset(principalRequest).value()), - fee(loanSetFee)); + auto createJson = + env.json(set(lender, broker.brokerID, broker.asset(principalRequest).value()), fee(loanSetFee)); env(createJson, ter(temBAD_SIGNER)); // Adding an empty counterparty signature object also fails, but // at the RPC level. - createJson = env.json( - createJson, json(sfCounterpartySignature, Json::objectValue)); + createJson = env.json(createJson, json(sfCounterpartySignature, Json::objectValue)); env(createJson, ter(telENV_RPC_FAILED)); if (auto const jt = env.jt(createJson); BEAST_EXPECT(jt.stx)) @@ -3830,9 +3308,7 @@ protected: BEAST_EXPECT(jr.isMember(jss::result)); auto const jResult = jr[jss::result]; BEAST_EXPECT(jResult[jss::error] == "invalidTransaction"); - BEAST_EXPECT( - jResult[jss::error_exception] == - "fails local checks: Transaction has bad signature."); + BEAST_EXPECT(jResult[jss::error_exception] == "fails local checks: Transaction has bad signature."); } // Copy the transaction signature into the counterparty signature. @@ -3843,8 +3319,7 @@ protected: counterpartyJson[sfSigners] = createJson[sfSigners]; // The duplicated signature works - createJson = env.json( - createJson, json(sfCounterpartySignature, counterpartyJson)); + createJson = env.json(createJson, json(sfCounterpartySignature, counterpartyJson)); env(createJson); env.close(); @@ -3863,8 +3338,7 @@ protected: ++types[object[sfLedgerEntryType].asString()]; } BEAST_EXPECT(types.size() == 4); - for (std::string const type : - {"MPToken", "Vault", "LoanBroker", "Loan"}) + for (std::string const type : {"MPToken", "Vault", "LoanBroker", "Loan"}) { BEAST_EXPECT(types[type] == 1); } @@ -3873,8 +3347,7 @@ protected: Json::Value params(Json::objectValue); params[jss::account] = lender.human(); params[jss::type] = "Loan"; - auto const res = - env.rpc("json", "account_objects", to_string(params)); + auto const res = env.rpc("json", "account_objects", to_string(params)); auto const objects = res[jss::result][jss::account_objects]; BEAST_EXPECT(objects.size() == 1); @@ -3894,8 +3367,7 @@ protected: BEAST_EXPECT(!loan.isMember(sfLoanOriginationFee)); BEAST_EXPECT(loan[sfLoanSequence] == 1); BEAST_EXPECT(!loan.isMember(sfLoanServiceFee)); - BEAST_EXPECT( - loan[sfNextPaymentDueDate] == loan[sfStartDate].asUInt() + 60); + BEAST_EXPECT(loan[sfNextPaymentDueDate] == loan[sfStartDate].asUInt() + 60); BEAST_EXPECT(!loan.isMember(sfOverpaymentFee)); BEAST_EXPECT(!loan.isMember(sfOverpaymentInterestRate)); BEAST_EXPECT(loan[sfPaymentInterval] == 60); @@ -3905,9 +3377,7 @@ protected: BEAST_EXPECT(loan[sfPrincipalOutstanding] == "1000000000"); BEAST_EXPECT(loan[sfTotalValueOutstanding] == "1000000000"); BEAST_EXPECT(!loan.isMember(sfLoanScale)); - BEAST_EXPECT( - loan[sfStartDate].asUInt() == - startDate.time_since_epoch().count()); + BEAST_EXPECT(loan[sfStartDate].asUInt() == startDate.time_since_epoch().count()); return loan["index"].asString(); }(); @@ -3925,10 +3395,10 @@ protected: // From FIND-001 testcase << "Batch Bypass Counterparty"; - bool const lendingBatchEnabled = !std::any_of( - Batch::disabledTxTypes.begin(), - Batch::disabledTxTypes.end(), - [](auto const& disabled) { return disabled == ttLOAN_BROKER_SET; }); + bool const lendingBatchEnabled = + !std::any_of(Batch::disabledTxTypes.begin(), Batch::disabledTxTypes.end(), [](auto const& disabled) { + return disabled == ttLOAN_BROKER_SET; + }); using namespace jtx; using namespace std::chrono_literals; @@ -3943,16 +3413,14 @@ protected: PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; - BrokerInfo broker{ - createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; + BrokerInfo broker{createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; using namespace loan; auto const loanSetFee = fee(env.current()->fees().base * 2); Number const principalRequest{1, 3}; - auto forgedLoanSet = - set(borrower, broker.brokerID, principalRequest, 0); + auto forgedLoanSet = set(borrower, broker.brokerID, principalRequest, 0); Json::Value randomData{Json::objectValue}; randomData[jss::SigningPubKey] = Json::StaticString{"2600"}; @@ -3975,8 +3443,7 @@ protected: env(batch::outer(borrower, seq, batchFee, tfAllOrNothing), batch::inner(forgedLoanSet, seq + 1), batch::inner(pay(borrower, lender, XRP(1)), seq + 2), - ter(lendingBatchEnabled ? temBAD_SIGNATURE - : temINVALID_INNER_BATCH)); + ter(lendingBatchEnabled ? temBAD_SIGNATURE : temINVALID_INNER_BATCH)); env.close(); // ? Check that the loan was NOT created @@ -3984,8 +3451,7 @@ protected: Json::Value params(Json::objectValue); params[jss::account] = borrower.human(); params[jss::type] = "Loan"; - auto const res = - env.rpc("json", "account_objects", to_string(params)); + auto const res = env.rpc("json", "account_objects", to_string(params)); auto const objects = res[jss::result][jss::account_objects]; BEAST_EXPECT(objects.size() == 0); } @@ -4005,17 +3471,14 @@ protected: Account const lender{"lender"}; BrokerParameters brokerParams{.debtMax = 0}; - env.fund( - XRP(brokerParams.vaultDeposit * 100), issuer, noripple(lender)); + env.fund(XRP(brokerParams.vaultDeposit * 100), issuer, noripple(lender)); env.close(); PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; - BrokerInfo broker{ - createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; + BrokerInfo broker{createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; - if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); BEAST_EXPECT(brokerSle)) { BEAST_EXPECT(brokerSle->at(sfDebtMaximum) == 0); } @@ -4025,8 +3488,7 @@ protected: auto const loanSetFee = fee(env.current()->fees().base * 2); Number const principalRequest{1, 3}; - auto createJson = env.json( - set(lender, broker.brokerID, principalRequest), fee(loanSetFee)); + auto createJson = env.json(set(lender, broker.brokerID, principalRequest), fee(loanSetFee)); Json::Value counterpartyJson{Json::objectValue}; counterpartyJson[sfTxnSignature] = createJson[sfTxnSignature]; @@ -4034,8 +3496,7 @@ protected: if (!BEAST_EXPECT(!createJson.isMember(jss::Signers))) counterpartyJson[sfSigners] = createJson[sfSigners]; - createJson = env.json( - createJson, json(sfCounterpartySignature, counterpartyJson)); + createJson = env.json(createJson, json(sfCounterpartySignature, counterpartyJson)); env(createJson); env.close(); @@ -4057,13 +3518,11 @@ protected: Account const borrower{"borrower"}; BrokerParameters brokerParams; - env.fund( - XRP(brokerParams.vaultDeposit * 100), issuer, lender, borrower); + env.fund(XRP(brokerParams.vaultDeposit * 100), issuer, lender, borrower); env.close(); PrettyAsset const xrpAsset{xrpIssue(), 1'000'000}; - BrokerInfo broker{ - createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; + BrokerInfo broker{createVaultAndBroker(env, xrpAsset, lender, brokerParams)}; using namespace loan; @@ -4088,8 +3547,7 @@ protected: createJson["OverpaymentInterestRate"] = 1360; createJson["PaymentInterval"] = 727; - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); auto const loanSequence = brokerStateBefore->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); @@ -4162,9 +3620,7 @@ protected: return signParams; }(); auto const jSign = env.rpc("json", "sign", to_string(signParams)); - BEAST_EXPECT( - jSign.isMember(jss::result) && - jSign[jss::result].isMember(jss::tx_json)); + BEAST_EXPECT(jSign.isMember(jss::result) && jSign[jss::result].isMember(jss::tx_json)); auto txSignResult = jSign[jss::result][jss::tx_json]; auto txSignBlob = jSign[jss::result][jss::tx_blob].asString(); txSignResult.removeMember(jss::hash); @@ -4175,10 +3631,8 @@ protected: lowerFee(); auto const jSubmit = env.rpc("submit", txSignBlob); BEAST_EXPECT( - jSubmit.isMember(jss::result) && - jSubmit[jss::result].isMember(jss::engine_result) && - jSubmit[jss::result][jss::engine_result].asString() == - "tesSUCCESS"); + jSubmit.isMember(jss::result) && jSubmit[jss::result].isMember(jss::engine_result) && + jSubmit[jss::result][jss::engine_result].asString() == "tesSUCCESS"); lowerFee(); env(jtx.jv, sig(none), seq(none), fee(none), ter(tefPAST_SEQ)); @@ -4199,15 +3653,12 @@ protected: params[jss::tx_json] = txJson; return params; }(); - auto const jSignBorrower = - env.rpc("json", "sign", to_string(borrowerSignParams)); + auto const jSignBorrower = env.rpc("json", "sign", to_string(borrowerSignParams)); BEAST_EXPECT( - jSignBorrower.isMember(jss::result) && - jSignBorrower[jss::result].isMember(jss::error) && + jSignBorrower.isMember(jss::result) && jSignBorrower[jss::result].isMember(jss::error) && jSignBorrower[jss::result][jss::error] == "invalidParams" && jSignBorrower[jss::result].isMember(jss::error_message) && - jSignBorrower[jss::result][jss::error_message] == - "Destination"); + jSignBorrower[jss::result][jss::error_message] == "Destination"); } { testcase("RPC LoanSet - sign and submit borrower initiated"); @@ -4235,16 +3686,12 @@ protected: params[jss::tx_json] = txJson; return params; }(); - auto const jSignBorrower = - env.rpc("json", "sign", to_string(borrowerSignParams)); + auto const jSignBorrower = env.rpc("json", "sign", to_string(borrowerSignParams)); BEAST_EXPECTS( - jSignBorrower.isMember(jss::result) && - jSignBorrower[jss::result].isMember(jss::tx_json), + jSignBorrower.isMember(jss::result) && jSignBorrower[jss::result].isMember(jss::tx_json), to_string(jSignBorrower)); - auto const txBorrowerSignResult = - jSignBorrower[jss::result][jss::tx_json]; - auto const txBorrowerSignBlob = - jSignBorrower[jss::result][jss::tx_blob].asString(); + auto const txBorrowerSignResult = jSignBorrower[jss::result][jss::tx_json]; + auto const txBorrowerSignBlob = jSignBorrower[jss::result][jss::tx_blob].asString(); // 2a. Borrower attempts to submit the transaction. It doesn't // work @@ -4258,8 +3705,7 @@ protected: // missing BEAST_EXPECT( jSubmitBlobResult.isMember(jss::engine_result) && - jSubmitBlobResult[jss::engine_result].asString() == - "temBAD_SIGNER"); + jSubmitBlobResult[jss::engine_result].asString() == "temBAD_SIGNER"); } // 3. Borrower sends the signed transaction to the lender @@ -4272,15 +3718,10 @@ protected: params[jss::tx_json] = txBorrowerSignResult; return params; }(); - auto const jSignLender = - env.rpc("json", "sign", to_string(lenderSignParams)); - BEAST_EXPECT( - jSignLender.isMember(jss::result) && - jSignLender[jss::result].isMember(jss::tx_json)); - auto const txLenderSignResult = - jSignLender[jss::result][jss::tx_json]; - auto const txLenderSignBlob = - jSignLender[jss::result][jss::tx_blob].asString(); + auto const jSignLender = env.rpc("json", "sign", to_string(lenderSignParams)); + BEAST_EXPECT(jSignLender.isMember(jss::result) && jSignLender[jss::result].isMember(jss::tx_json)); + auto const txLenderSignResult = jSignLender[jss::result][jss::tx_json]; + auto const txLenderSignBlob = jSignLender[jss::result][jss::tx_blob].asString(); // 5. Lender submits the signed transaction blob lowerFee(); @@ -4294,21 +3735,17 @@ protected: // succeed because no Vault or Broker were created. BEAST_EXPECTS( jSubmitBlobResult.isMember(jss::engine_result) && - jSubmitBlobResult[jss::engine_result].asString() == - "tecNO_ENTRY", + jSubmitBlobResult[jss::engine_result].asString() == "tecNO_ENTRY", to_string(jSubmitBlobResult)); - BEAST_EXPECT( - !jSubmitBlob.isMember(jss::error) && - !jSubmitBlobResult.isMember(jss::error)); + BEAST_EXPECT(!jSubmitBlob.isMember(jss::error) && !jSubmitBlobResult.isMember(jss::error)); // 4-alt. Lender submits the transaction json originally // received from the Borrower. It gets signed, but is now a // duplicate, so fails. Borrower could done this instead of // steps 4 and 5. lowerFee(); - auto const jSubmitJson = - env.rpc("json", "submit", to_string(lenderSignParams)); + auto const jSubmitJson = env.rpc("json", "submit", to_string(lenderSignParams)); BEAST_EXPECT(jSubmitJson.isMember(jss::result)); auto const jSubmitJsonResult = jSubmitJson[jss::result]; BEAST_EXPECT(jSubmitJsonResult.isMember(jss::tx_json)); @@ -4317,13 +3754,10 @@ protected: // going anywhere BEAST_EXPECTS( jSubmitJsonResult.isMember(jss::engine_result) && - jSubmitJsonResult[jss::engine_result].asString() == - "tefPAST_SEQ", + jSubmitJsonResult[jss::engine_result].asString() == "tefPAST_SEQ", to_string(jSubmitJsonResult)); - BEAST_EXPECT( - !jSubmitJson.isMember(jss::error) && - !jSubmitJsonResult.isMember(jss::error)); + BEAST_EXPECT(!jSubmitJson.isMember(jss::error) && !jSubmitJsonResult.isMember(jss::error)); BEAST_EXPECT(jSubmitBlobTx == jSubmitJsonTx); } @@ -4354,15 +3788,10 @@ protected: params[jss::tx_json] = txJson; return params; }(); - auto const jSignLender = - env.rpc("json", "sign", to_string(lenderSignParams)); - BEAST_EXPECT( - jSignLender.isMember(jss::result) && - jSignLender[jss::result].isMember(jss::tx_json)); - auto const txLenderSignResult = - jSignLender[jss::result][jss::tx_json]; - auto const txLenderSignBlob = - jSignLender[jss::result][jss::tx_blob].asString(); + auto const jSignLender = env.rpc("json", "sign", to_string(lenderSignParams)); + BEAST_EXPECT(jSignLender.isMember(jss::result) && jSignLender[jss::result].isMember(jss::tx_json)); + auto const txLenderSignResult = jSignLender[jss::result][jss::tx_json]; + auto const txLenderSignBlob = jSignLender[jss::result][jss::tx_blob].asString(); // 2a. Lender attempts to submit the transaction. It doesn't // work @@ -4376,8 +3805,7 @@ protected: // missing BEAST_EXPECT( jSubmitBlobResult.isMember(jss::engine_result) && - jSubmitBlobResult[jss::engine_result].asString() == - "temBAD_SIGNER"); + jSubmitBlobResult[jss::engine_result].asString() == "temBAD_SIGNER"); } // 3. Lender sends the signed transaction to the Borrower @@ -4390,15 +3818,10 @@ protected: params[jss::tx_json] = txLenderSignResult; return params; }(); - auto const jSignBorrower = - env.rpc("json", "sign", to_string(borrowerSignParams)); - BEAST_EXPECT( - jSignBorrower.isMember(jss::result) && - jSignBorrower[jss::result].isMember(jss::tx_json)); - auto const txBorrowerSignResult = - jSignBorrower[jss::result][jss::tx_json]; - auto const txBorrowerSignBlob = - jSignBorrower[jss::result][jss::tx_blob].asString(); + auto const jSignBorrower = env.rpc("json", "sign", to_string(borrowerSignParams)); + BEAST_EXPECT(jSignBorrower.isMember(jss::result) && jSignBorrower[jss::result].isMember(jss::tx_json)); + auto const txBorrowerSignResult = jSignBorrower[jss::result][jss::tx_json]; + auto const txBorrowerSignBlob = jSignBorrower[jss::result][jss::tx_blob].asString(); // 5. Borrower submits the signed transaction blob lowerFee(); @@ -4412,21 +3835,17 @@ protected: // succeed because no Vault or Broker were created. BEAST_EXPECTS( jSubmitBlobResult.isMember(jss::engine_result) && - jSubmitBlobResult[jss::engine_result].asString() == - "tecNO_ENTRY", + jSubmitBlobResult[jss::engine_result].asString() == "tecNO_ENTRY", to_string(jSubmitBlobResult)); - BEAST_EXPECT( - !jSubmitBlob.isMember(jss::error) && - !jSubmitBlobResult.isMember(jss::error)); + BEAST_EXPECT(!jSubmitBlob.isMember(jss::error) && !jSubmitBlobResult.isMember(jss::error)); // 4-alt. Borrower submits the transaction json originally // received from the Lender. It gets signed, but is now a // duplicate, so fails. Lender could done this instead of steps // 4 and 5. lowerFee(); - auto const jSubmitJson = - env.rpc("json", "submit", to_string(borrowerSignParams)); + auto const jSubmitJson = env.rpc("json", "submit", to_string(borrowerSignParams)); BEAST_EXPECT(jSubmitJson.isMember(jss::result)); auto const jSubmitJsonResult = jSubmitJson[jss::result]; BEAST_EXPECT(jSubmitJsonResult.isMember(jss::tx_json)); @@ -4435,13 +3854,10 @@ protected: // going anywhere BEAST_EXPECTS( jSubmitJsonResult.isMember(jss::engine_result) && - jSubmitJsonResult[jss::engine_result].asString() == - "tefPAST_SEQ", + jSubmitJsonResult[jss::engine_result].asString() == "tefPAST_SEQ", to_string(jSubmitJsonResult)); - BEAST_EXPECT( - !jSubmitJson.isMember(jss::error) && - !jSubmitJsonResult.isMember(jss::error)); + BEAST_EXPECT(!jSubmitJson.isMember(jss::error) && !jSubmitJsonResult.isMember(jss::error)); BEAST_EXPECT(jSubmitBlobTx == jSubmitJsonTx); } @@ -4462,15 +3878,11 @@ protected: { Env env(*this); - auto getCoverBalance = [&](BrokerInfo const& brokerInfo, - auto const& accountField) { - if (auto const le = - env.le(keylet::loanbroker(brokerInfo.brokerID)); - BEAST_EXPECT(le)) + auto getCoverBalance = [&](BrokerInfo const& brokerInfo, auto const& accountField) { + if (auto const le = env.le(keylet::loanbroker(brokerInfo.brokerID)); BEAST_EXPECT(le)) { auto const account = le->at(accountField); - if (auto const sleLine = env.le(keylet::line(account, IOU)); - BEAST_EXPECT(sleLine)) + if (auto const sleLine = env.le(keylet::line(account, IOU)); BEAST_EXPECT(sleLine)) { STAmount balance = sleLine->at(sfBalance); if (account > issuer.id()) @@ -4507,15 +3919,11 @@ protected: env(pay(issuer, borrower, IOU(500))); env.close(); - if (auto const le = env.le(keylet::loan(keylet.key)); - BEAST_EXPECT(le)) + if (auto const le = env.le(keylet::loan(keylet.key)); BEAST_EXPECT(le)) { if (deepFreeze) { - env(trust( - issuer, - broker["IOU"](0), - tfSetFreeze | tfSetDeepFreeze)); + env(trust(issuer, broker["IOU"](0), tfSetFreeze | tfSetDeepFreeze)); env.close(); } @@ -4525,18 +3933,14 @@ protected: if (deepFreeze) { // The fee goes to the broker pseudo-account - BEAST_EXPECT( - getCoverBalance(brokerInfo, sfAccount) == IOU(1'100)); - BEAST_EXPECT( - getCoverBalance(brokerInfo, sfOwner) == IOU(8'999'000)); + BEAST_EXPECT(getCoverBalance(brokerInfo, sfAccount) == IOU(1'100)); + BEAST_EXPECT(getCoverBalance(brokerInfo, sfOwner) == IOU(8'999'000)); } else { // The fee goes to the broker account - BEAST_EXPECT( - getCoverBalance(brokerInfo, sfOwner) == IOU(8'999'100)); - BEAST_EXPECT( - getCoverBalance(brokerInfo, sfAccount) == IOU(1'000)); + BEAST_EXPECT(getCoverBalance(brokerInfo, sfOwner) == IOU(8'999'100)); + BEAST_EXPECT(getCoverBalance(brokerInfo, sfAccount) == IOU(1'000)); } } }; @@ -4557,22 +3961,15 @@ protected: env.fund(XRP(1'000), issuer, lender); std::int64_t constexpr issuerBalance = 10'000'000; - MPTTester asset( - {.env = env, - .issuer = issuer, - .holders = {lender}, - .pay = issuerBalance}); + MPTTester asset({.env = env, .issuer = issuer, .holders = {lender}, .pay = issuerBalance}); BrokerParameters const brokerParams{ .debtMax = 200, }; - auto const broker = - createVaultAndBroker(env, asset, lender, brokerParams); + auto const broker = createVaultAndBroker(env, asset, lender, brokerParams); auto const loanSetFee = fee(env.current()->fees().base * 2); // Create Loan - env(set(borrower, broker.brokerID, 200), - sig(sfCounterpartySignature, lender), - loanSetFee); + env(set(borrower, broker.brokerID, 200), sig(sfCounterpartySignature, lender), loanSetFee); env.close(); // Issuer should not create MPToken BEAST_EXPECT(!env.le(keylet::mptoken(asset.issuanceID(), issuer))); @@ -4655,18 +4052,14 @@ protected: env.close(); // preclaim: tecFROZEN - env(pay(borrower, loanKeylet.key, debtMaximumRequest), - ter(tecFROZEN), - THISLINE); + env(pay(borrower, loanKeylet.key, debtMaximumRequest), ter(tecFROZEN), THISLINE); env.close(); env(fclear(issuer, asfGlobalFreeze), THISLINE); env.close(); auto const pseudoBroker = [&]() -> std::optional { - if (auto brokerSle = - env.le(keylet::loanbroker(brokerInfo.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto brokerSle = env.le(keylet::loanbroker(brokerInfo.brokerID)); BEAST_EXPECT(brokerSle)) { return Account{"pseudo", brokerSle->at(sfAccount)}; } @@ -4679,52 +4072,28 @@ protected: return; // Lender and pseudoaccount must both be frozen - env(trust( - issuer, - lender["IOU"](1'000), - lender, - tfSetFreeze | tfSetDeepFreeze), - THISLINE); - env(trust( - issuer, - (*pseudoBroker)["IOU"](1'000), - *pseudoBroker, - tfSetFreeze | tfSetDeepFreeze), - THISLINE); + env(trust(issuer, lender["IOU"](1'000), lender, tfSetFreeze | tfSetDeepFreeze), THISLINE); + env(trust(issuer, (*pseudoBroker)["IOU"](1'000), *pseudoBroker, tfSetFreeze | tfSetDeepFreeze), THISLINE); env.close(); // preclaim: tecFROZEN due to deep frozen - env(pay(borrower, loanKeylet.key, debtMaximumRequest), - ter(tecFROZEN), - THISLINE); + env(pay(borrower, loanKeylet.key, debtMaximumRequest), ter(tecFROZEN), THISLINE); env.close(); // Only one needs to be unfrozen - env(trust( - issuer, - lender["IOU"](1'000), - tfClearFreeze | tfClearDeepFreeze), - THISLINE); + env(trust(issuer, lender["IOU"](1'000), tfClearFreeze | tfClearDeepFreeze), THISLINE); env.close(); // The payment is late by this point - env(pay(borrower, loanKeylet.key, debtMaximumRequest), - ter(tecEXPIRED), - THISLINE); + env(pay(borrower, loanKeylet.key, debtMaximumRequest), ter(tecEXPIRED), THISLINE); env.close(); - env(pay(borrower, - loanKeylet.key, - debtMaximumRequest, - tfLoanLatePayment), - THISLINE); + env(pay(borrower, loanKeylet.key, debtMaximumRequest, tfLoanLatePayment), THISLINE); env.close(); // preclaim: tecKILLED // note that tecKILLED in loanMakePayment() // doesn't happen because of the preclaim check. - env(pay(borrower, loanKeylet.key, debtMaximumRequest), - ter(tecKILLED), - THISLINE); + env(pay(borrower, loanKeylet.key, debtMaximumRequest), ter(tecKILLED), THISLINE); } void @@ -4743,8 +4112,7 @@ protected: env.fund(XRP(1'000), lender, issuer, borrower); env(trust(lender, IOU(10'000'000))); env(pay(issuer, lender, IOU(5'000'000))); - BrokerInfo brokerInfo{ - createVaultAndBroker(env, issuer["IOU"], lender)}; + BrokerInfo brokerInfo{createVaultAndBroker(env, issuer["IOU"], lender)}; auto const loanSetFee = fee(env.current()->fees().base * 2); Number const debtMaximumRequest = brokerInfo.asset(1'000).value(); @@ -4752,122 +4120,108 @@ protected: }; // preflight: - testWrapper([&](Env& env, - BrokerInfo const& brokerInfo, - jtx::fee const& loanSetFee, - Number const& debtMaximumRequest) { - // first temBAD_SIGNER: TODO - // invalid grace period - { - // zero grace period - env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), - sig(sfCounterpartySignature, lender), - gracePeriod(0), - loanSetFee, - ter(temINVALID)); - - // grace period less than default minimum - env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), - sig(sfCounterpartySignature, lender), - gracePeriod(LoanSet::defaultGracePeriod - 1), - loanSetFee, - ter(temINVALID)); - - // grace period greater than payment interval - env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), - sig(sfCounterpartySignature, lender), - paymentInterval(120), - gracePeriod(121), - loanSetFee, - ter(temINVALID)); - } - // empty/zero broker ID - { - auto jv = set(borrower, uint256{}, debtMaximumRequest); - - auto testZeroBrokerID = [&](std::string const& id, - std::uint32_t flags = 0) { - // empty broker ID - jv[sfLoanBrokerID] = id; - env(jv, + testWrapper( + [&](Env& env, BrokerInfo const& brokerInfo, jtx::fee const& loanSetFee, Number const& debtMaximumRequest) { + // first temBAD_SIGNER: TODO + // invalid grace period + { + // zero grace period + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), sig(sfCounterpartySignature, lender), + gracePeriod(0), loanSetFee, - txflags(flags), ter(temINVALID)); - }; - // empty broker ID - testZeroBrokerID(std::string("")); - // zero broker ID - // needs a flag to distinguish the parsed STTx from the prior - // test - testZeroBrokerID(to_string(uint256{}), tfFullyCanonicalSig); - } - // preflightCheckSigningKey() failure: - // can it happen? the signature is checked before transactor - // executes + // grace period less than default minimum + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + gracePeriod(LoanSet::defaultGracePeriod - 1), + loanSetFee, + ter(temINVALID)); - JTx tx = env.jt( - set(borrower, brokerInfo.brokerID, debtMaximumRequest), - sig(sfCounterpartySignature, lender), - loanSetFee); - STTx local = *(tx.stx); - auto counterpartySig = - local.getFieldObject(sfCounterpartySignature); - auto badPubKey = counterpartySig.getFieldVL(sfSigningPubKey); - badPubKey[20] ^= 0xAA; - counterpartySig.setFieldVL(sfSigningPubKey, badPubKey); - local.setFieldObject(sfCounterpartySignature, counterpartySig); - Json::Value jvResult; - jvResult[jss::tx_blob] = strHex(local.getSerializer().slice()); - auto res = env.rpc("json", "submit", to_string(jvResult))["result"]; - BEAST_EXPECT( - res[jss::error] == "invalidTransaction" && - res[jss::error_exception] == - "fails local checks: Counterparty: Invalid signature."); - }); + // grace period greater than payment interval + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + paymentInterval(120), + gracePeriod(121), + loanSetFee, + ter(temINVALID)); + } + // empty/zero broker ID + { + auto jv = set(borrower, uint256{}, debtMaximumRequest); + + auto testZeroBrokerID = [&](std::string const& id, std::uint32_t flags = 0) { + // empty broker ID + jv[sfLoanBrokerID] = id; + env(jv, sig(sfCounterpartySignature, lender), loanSetFee, txflags(flags), ter(temINVALID)); + }; + // empty broker ID + testZeroBrokerID(std::string("")); + // zero broker ID + // needs a flag to distinguish the parsed STTx from the prior + // test + testZeroBrokerID(to_string(uint256{}), tfFullyCanonicalSig); + } + + // preflightCheckSigningKey() failure: + // can it happen? the signature is checked before transactor + // executes + + JTx tx = env.jt( + set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee); + STTx local = *(tx.stx); + auto counterpartySig = local.getFieldObject(sfCounterpartySignature); + auto badPubKey = counterpartySig.getFieldVL(sfSigningPubKey); + badPubKey[20] ^= 0xAA; + counterpartySig.setFieldVL(sfSigningPubKey, badPubKey); + local.setFieldObject(sfCounterpartySignature, counterpartySig); + Json::Value jvResult; + jvResult[jss::tx_blob] = strHex(local.getSerializer().slice()); + auto res = env.rpc("json", "submit", to_string(jvResult))["result"]; + BEAST_EXPECT( + res[jss::error] == "invalidTransaction" && + res[jss::error_exception] == "fails local checks: Counterparty: Invalid signature."); + }); // preclaim: - testWrapper([&](Env& env, - BrokerInfo const& brokerInfo, - jtx::fee const& loanSetFee, - Number const& debtMaximumRequest) { - // canAddHoldingFailure (IOU only, if MPT doesn't have - // MPTCanTransfer set, then can't create Vault/LoanBroker, - // and LoanSet will fail with different error - env(fclear(issuer, asfDefaultRipple)); - env.close(); - env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), - sig(sfCounterpartySignature, lender), - loanSetFee, - ter(terNO_RIPPLE)); - }); + testWrapper( + [&](Env& env, BrokerInfo const& brokerInfo, jtx::fee const& loanSetFee, Number const& debtMaximumRequest) { + // canAddHoldingFailure (IOU only, if MPT doesn't have + // MPTCanTransfer set, then can't create Vault/LoanBroker, + // and LoanSet will fail with different error + env(fclear(issuer, asfDefaultRipple)); + env.close(); + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(terNO_RIPPLE)); + }); // doApply: - testWrapper([&](Env& env, - BrokerInfo const& brokerInfo, - jtx::fee const& loanSetFee, - Number const& debtMaximumRequest) { - auto const amt = env.balance(borrower) - - env.current()->fees().accountReserve(env.ownerCount(borrower)); - env(pay(borrower, issuer, amt)); + testWrapper( + [&](Env& env, BrokerInfo const& brokerInfo, jtx::fee const& loanSetFee, Number const& debtMaximumRequest) { + auto const amt = env.balance(borrower) - env.current()->fees().accountReserve(env.ownerCount(borrower)); + env(pay(borrower, issuer, amt)); - // tecINSUFFICIENT_RESERVE - env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), - sig(sfCounterpartySignature, lender), - loanSetFee, - ter(tecINSUFFICIENT_RESERVE)); + // tecINSUFFICIENT_RESERVE + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(tecINSUFFICIENT_RESERVE)); - // addEmptyHolding failure - env(pay(issuer, borrower, amt)); - env(fset(issuer, asfGlobalFreeze)); - env.close(); + // addEmptyHolding failure + env(pay(issuer, borrower, amt)); + env(fset(issuer, asfGlobalFreeze)); + env.close(); - env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), - sig(sfCounterpartySignature, lender), - loanSetFee, - ter(tecFROZEN)); - }); + env(set(borrower, brokerInfo.brokerID, debtMaximumRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + ter(tecFROZEN)); + }); } void @@ -4889,8 +4243,7 @@ protected: env.close(); MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); PrettyAsset const mptAsset = mptt.issuanceID(); mptt.authorize({.account = lender}); mptt.authorize({.account = borrower}); @@ -4924,8 +4277,7 @@ protected: createJson["PaymentTotal"] = "2891743748"; createJson["PrincipalRequested"] = "8516.98"; - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); createJson = env.json(createJson, sig(sfCounterpartySignature, lender)); env(createJson, ter(temINVALID)); @@ -4954,8 +4306,7 @@ protected: PrettyAsset const iouAsset = issuer[iouCurrency]; auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); env(trustLenderTx); - auto trustBorrowerTx = - env.json(trust(borrower, iouAsset(1'000'000'000))); + auto trustBorrowerTx = env.json(trust(borrower, iouAsset(1'000'000'000))); env(trustBorrowerTx); auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); env(payLenderTx); @@ -4987,8 +4338,7 @@ protected: createJson["PaymentTotal"] = 5678; createJson["PrincipalRequested"] = "9924.81"; - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); auto const loanSequence = brokerStateBefore->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); @@ -5009,32 +4359,17 @@ protected: verifyLoanStatus(originalState); Number const payment{3'269'349'176'470'588, -12}; - XRPAmount const payFee{ - baseFee * - ((payment / originalState.periodicPayment) / - loanPaymentsPerFeeIncrement + - 1)}; - auto loanPayTx = env.json( - pay(borrower, keylet.key, STAmount{broker.asset, payment}), - fee(payFee)); + XRPAmount const payFee{baseFee * ((payment / originalState.periodicPayment) / loanPaymentsPerFeeIncrement + 1)}; + auto loanPayTx = env.json(pay(borrower, keylet.key, STAmount{broker.asset, payment}), fee(payFee)); BEAST_EXPECT(to_string(payment) == "3269.349176470588"); env(loanPayTx, ter(tesSUCCESS)); env.close(); auto const newState = getCurrentState(env, broker, keylet); - BEAST_EXPECT(isRounded( - broker.asset, - newState.managementFeeOutstanding, - originalState.loanScale)); - BEAST_EXPECT( - newState.managementFeeOutstanding < - originalState.managementFeeOutstanding); - BEAST_EXPECT(isRounded( - broker.asset, newState.totalValue, originalState.loanScale)); - BEAST_EXPECT(isRounded( - broker.asset, - newState.principalOutstanding, - originalState.loanScale)); + BEAST_EXPECT(isRounded(broker.asset, newState.managementFeeOutstanding, originalState.loanScale)); + BEAST_EXPECT(newState.managementFeeOutstanding < originalState.managementFeeOutstanding); + BEAST_EXPECT(isRounded(broker.asset, newState.totalValue, originalState.loanScale)); + BEAST_EXPECT(isRounded(broker.asset, newState.principalOutstanding, originalState.loanScale)); } void @@ -5057,8 +4392,7 @@ protected: PrettyAsset const iouAsset = issuer[iouCurrency]; auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); env(trustLenderTx); - auto trustBorrowerTx = - env.json(trust(borrower, iouAsset(1'000'000'000))); + auto trustBorrowerTx = env.json(trust(borrower, iouAsset(1'000'000'000))); env(trustBorrowerTx); auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); env(payLenderTx); @@ -5089,8 +4423,7 @@ protected: createJson["PaymentTotal"] = 1; createJson["PrincipalRequested"] = "0.000763058"; - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); auto const loanSequence = brokerStateBefore->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); @@ -5098,8 +4431,7 @@ protected: env(createJson, THISLINE); env.close(); - auto loanPayTx = env.json( - pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + auto loanPayTx = env.json(pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); loanPayTx["Amount"]["value"] = "0.000281284125490196"; env(loanPayTx, ter(tecINSUFFICIENT_PAYMENT), THISLINE); env.close(); @@ -5155,8 +4487,7 @@ protected: createJson["PaymentTotal"] = 3239184; createJson["PrincipalRequested"] = "3959.37"; - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); auto const loanSequence = brokerStateBefore->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); @@ -5166,26 +4497,18 @@ protected: auto const stateBefore = getCurrentState(env, broker, keylet); BEAST_EXPECT(stateBefore.paymentRemaining == 3239184); - BEAST_EXPECT( - stateBefore.paymentRemaining > loanMaximumPaymentsPerTransaction); + BEAST_EXPECT(stateBefore.paymentRemaining > loanMaximumPaymentsPerTransaction); - auto loanPayTx = env.json( - pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + auto loanPayTx = env.json(pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); Number const amount{395937, -2}; loanPayTx["Amount"]["value"] = to_string(amount); XRPAmount const payFee{ - baseFee * - std::int64_t( - amount / stateBefore.periodicPayment / - loanPaymentsPerFeeIncrement + - 1)}; + baseFee * std::int64_t(amount / stateBefore.periodicPayment / loanPaymentsPerFeeIncrement + 1)}; env(loanPayTx, ter(tesSUCCESS), fee(payFee)); env.close(); auto const stateAfter = getCurrentState(env, broker, keylet); - BEAST_EXPECT( - stateAfter.paymentRemaining == - stateBefore.paymentRemaining - loanMaximumPaymentsPerTransaction); + BEAST_EXPECT(stateAfter.paymentRemaining == stateBefore.paymentRemaining - loanMaximumPaymentsPerTransaction); } void @@ -5210,8 +4533,7 @@ protected: PrettyAsset const iouAsset = issuer[iouCurrency]; auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); env(trustLenderTx); - auto trustBorrowerTx = - env.json(trust(borrower, iouAsset(1'000'000'000))); + auto trustBorrowerTx = env.json(trust(borrower, iouAsset(1'000'000'000))); env(trustBorrowerTx); auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); env(payLenderTx); @@ -5241,8 +4563,7 @@ protected: createJson["PaymentTotal"] = 5678; createJson["PrincipalRequested"] = "9924.81"; - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); auto const loanSequence = brokerStateBefore->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); @@ -5255,30 +4576,20 @@ protected: auto const stateBefore = getCurrentState(env, broker, keylet); { - auto loanPayTx = env.json( - pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + auto loanPayTx = env.json(pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); Number const amount{3074'745'058'823'529, -12}; BEAST_EXPECT(to_string(amount) == "3074.745058823529"); - XRPAmount const payFee{ - baseFee * - (amount / stateBefore.periodicPayment / - loanPaymentsPerFeeIncrement + - 1)}; + XRPAmount const payFee{baseFee * (amount / stateBefore.periodicPayment / loanPaymentsPerFeeIncrement + 1)}; loanPayTx["Amount"]["value"] = to_string(amount); env(loanPayTx, fee(payFee), ter(tesSUCCESS)); env.close(); } { - auto loanPayTx = env.json( - pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + auto loanPayTx = env.json(pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); Number const amount{6732'118'170'944'051, -12}; BEAST_EXPECT(to_string(amount) == "6732.118170944051"); - XRPAmount const payFee{ - baseFee * - (amount / stateBefore.periodicPayment / - loanPaymentsPerFeeIncrement + - 1)}; + XRPAmount const payFee{baseFee * (amount / stateBefore.periodicPayment / loanPaymentsPerFeeIncrement + 1)}; loanPayTx["Amount"]["value"] = to_string(amount); env(loanPayTx, fee(payFee), ter(tesSUCCESS)); env.close(); @@ -5288,17 +4599,14 @@ protected: // Total interest outstanding is non-negative BEAST_EXPECT(stateAfter.totalValue >= stateAfter.principalOutstanding); // Principal paid is non-negative - BEAST_EXPECT( - stateBefore.principalOutstanding >= - stateAfter.principalOutstanding); + BEAST_EXPECT(stateBefore.principalOutstanding >= stateAfter.principalOutstanding); // Total value change is non-negative BEAST_EXPECT(stateBefore.totalValue >= stateAfter.totalValue); // Value delta is larger or same as principal delta (meaning // non-negative interest paid) BEAST_EXPECT( (stateBefore.totalValue - stateAfter.totalValue) >= - (stateBefore.principalOutstanding - - stateAfter.principalOutstanding)); + (stateBefore.principalOutstanding - stateAfter.principalOutstanding)); } void @@ -5322,8 +4630,7 @@ protected: PrettyAsset const iouAsset = issuer[iouCurrency]; auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); env(trustLenderTx); - auto trustBorrowerTx = - env.json(trust(borrower, iouAsset(1'000'000'000))); + auto trustBorrowerTx = env.json(trust(borrower, iouAsset(1'000'000'000))); env(trustBorrowerTx); auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); env(payLenderTx); @@ -5333,10 +4640,8 @@ protected: BrokerInfo broker{createVaultAndBroker(env, iouAsset, lender)}; { - auto const coverDepositValue = - broker.asset(broker.params.coverDeposit * 10).value(); - env(loanBroker::coverDeposit( - lender, broker.brokerID, coverDepositValue)); + auto const coverDepositValue = broker.asset(broker.params.coverDeposit * 10).value(); + env(loanBroker::coverDeposit(lender, broker.brokerID, coverDepositValue)); env.close(); } @@ -5360,8 +4665,7 @@ protected: createJson["PaymentTotal"] = 5678; createJson["PrincipalRequested"] = "9924.81"; - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); auto const loanSequence = brokerStateBefore->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); @@ -5373,26 +4677,18 @@ protected: auto const stateBefore = getCurrentState(env, broker, keylet); BEAST_EXPECT(stateBefore.paymentRemaining == 5678); - BEAST_EXPECT( - stateBefore.paymentRemaining > loanMaximumPaymentsPerTransaction); + BEAST_EXPECT(stateBefore.paymentRemaining > loanMaximumPaymentsPerTransaction); - auto loanPayTx = env.json( - pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); + auto loanPayTx = env.json(pay(borrower, keylet.key, STAmount{broker.asset, Number{}})); Number const amount{9924'81, -2}; BEAST_EXPECT(to_string(amount) == "9924.81"); - XRPAmount const payFee{ - baseFee * - (amount / stateBefore.periodicPayment / - loanPaymentsPerFeeIncrement + - 1)}; + XRPAmount const payFee{baseFee * (amount / stateBefore.periodicPayment / loanPaymentsPerFeeIncrement + 1)}; loanPayTx["Amount"]["value"] = to_string(amount); env(loanPayTx, fee(payFee), ter(tesSUCCESS)); env.close(); auto const stateAfter = getCurrentState(env, broker, keylet); - BEAST_EXPECT( - stateAfter.paymentRemaining == - stateBefore.paymentRemaining - loanMaximumPaymentsPerTransaction); + BEAST_EXPECT(stateAfter.paymentRemaining == stateBefore.paymentRemaining - loanMaximumPaymentsPerTransaction); } void @@ -5416,8 +4712,7 @@ protected: PrettyAsset const iouAsset = issuer[iouCurrency]; auto trustLenderTx = env.json(trust(lender, iouAsset(1'000'000'000))); env(trustLenderTx); - auto trustBorrowerTx = - env.json(trust(borrower, iouAsset(1'000'000'000))); + auto trustBorrowerTx = env.json(trust(borrower, iouAsset(1'000'000'000))); env(trustBorrowerTx); auto payLenderTx = pay(issuer, lender, iouAsset(100'000'000)); env(payLenderTx); @@ -5425,10 +4720,8 @@ protected: env(payIssuerTx); env.close(); - BrokerParameters const brokerParams{ - .debtMax = Number{0}, .coverRateMin = TenthBips32{1}}; - BrokerInfo broker{ - createVaultAndBroker(env, iouAsset, lender, brokerParams)}; + BrokerParameters const brokerParams{.debtMax = Number{0}, .coverRateMin = TenthBips32{1}}; + BrokerInfo broker{createVaultAndBroker(env, iouAsset, lender, brokerParams)}; using namespace loan; @@ -5458,9 +4751,7 @@ protected: auto const baseFee = env.current()->fees().base; - auto parentCloseTime = [&]() { - return env.current()->parentCloseTime().time_since_epoch().count(); - }; + auto parentCloseTime = [&]() { return env.current()->parentCloseTime().time_since_epoch().count(); }; auto maxLoanTime = [&]() { auto const startDate = parentCloseTime(); @@ -5473,12 +4764,9 @@ protected: // straight-up overflow: interval auto const interval = maxLoanTime() + 1; auto const total = 1; - auto createJson = env.json( - baseJson, paymentInterval(interval), paymentTotal(total)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total)); - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tecKILLED)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tecKILLED)); env.close(); } { @@ -5486,12 +4774,9 @@ protected: // min interval is 60 auto const interval = 60; auto const total = maxLoanTime() + 1; - auto createJson = env.json( - baseJson, paymentInterval(interval), paymentTotal(total)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total)); - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tecKILLED)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tecKILLED)); env.close(); } { @@ -5500,28 +4785,19 @@ protected: auto const interval = maxLoanTime() + 1; auto const total = 1; auto const grace = interval; - auto createJson = env.json( - baseJson, - paymentInterval(interval), - paymentTotal(total), - gracePeriod(grace)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total), gracePeriod(grace)); // The grace period can't be larger than the interval. - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tecKILLED)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tecKILLED)); env.close(); } { // Overflow with multiplication of a few large intervals auto const interval = 1'000'000'000; auto const total = 10; - auto createJson = env.json( - baseJson, paymentInterval(interval), paymentTotal(total)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total)); - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tecKILLED)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tecKILLED)); env.close(); } { @@ -5529,12 +4805,9 @@ protected: // min interval is 60 auto const interval = 60; auto const total = 1'000'000'000; - auto createJson = env.json( - baseJson, paymentInterval(interval), paymentTotal(total)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total)); - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tecKILLED)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tecKILLED)); env.close(); } { @@ -5543,36 +4816,23 @@ protected: auto const total = 60; auto const interval = (maxLoanTime() - total) / total; auto const grace = interval; - auto createJson = env.json( - baseJson, - paymentInterval(interval), - paymentTotal(total), - gracePeriod(grace)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total), gracePeriod(grace)); - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tecKILLED)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tecKILLED)); env.close(); } { // Start date when the ledger is closed will be larger - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); auto const loanSequence = brokerStateBefore->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); auto const grace = 100; auto const interval = maxLoanTime() - grace; auto const total = 1; - auto createJson = env.json( - baseJson, - paymentInterval(interval), - paymentTotal(total), - gracePeriod(grace)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total), gracePeriod(grace)); - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tesSUCCESS)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tesSUCCESS)); env.close(); // The transaction is killed in the closed ledger @@ -5589,8 +4849,7 @@ protected: } { // Start date when the ledger is closed will be larger - auto const brokerStateBefore = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerStateBefore = env.le(keylet::loanbroker(broker.brokerID)); auto const loanSequence = brokerStateBefore->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); @@ -5598,15 +4857,9 @@ protected: auto const grace = 5'000; auto const interval = maxTime - closeStartDate - grace; auto const total = 1; - auto createJson = env.json( - baseJson, - paymentInterval(interval), - paymentTotal(total), - gracePeriod(grace)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total), gracePeriod(grace)); - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tesSUCCESS)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tesSUCCESS)); env.close(); // The transaction succeeds in the closed ledger @@ -5643,28 +4896,20 @@ protected: if (!BEAST_EXPECT(total != 0)) return; - auto const brokerState = - env.le(keylet::loanbroker(broker.brokerID)); + auto const brokerState = env.le(keylet::loanbroker(broker.brokerID)); // Intentionally shadow the outer values auto const loanSequence = brokerState->at(sfLoanSequence); auto const keylet = keylet::loan(broker.brokerID, loanSequence); auto const interval = maxLoanTime / total; - auto createJson = env.json( - baseJson, - paymentInterval(interval), - paymentTotal(total), - gracePeriod(grace)); + auto createJson = env.json(baseJson, paymentInterval(interval), paymentTotal(total), gracePeriod(grace)); - env(createJson, - sig(sfCounterpartySignature, lender), - ter(tesSUCCESS)); + env(createJson, sig(sfCounterpartySignature, lender), ter(tesSUCCESS)); env.close(); // This loan exists auto const beforeState = getCurrentState(env, broker, keylet); - BEAST_EXPECT( - beforeState.nextPaymentDate == closeStartDate + interval); + BEAST_EXPECT(beforeState.nextPaymentDate == closeStartDate + interval); BEAST_EXPECT(beforeState.previousPaymentDate == 0); BEAST_EXPECT(beforeState.paymentRemaining == total); BEAST_EXPECT(beforeState.periodicPayment > 0); @@ -5672,14 +4917,10 @@ protected: // pay all but the last payment { NumberRoundModeGuard mg{Number::upward}; - Number const payment = - beforeState.periodicPayment * (total - 1); - XRPAmount const payFee{ - baseFee * ((total - 1) / loanPaymentsPerFeeIncrement + 1)}; - STAmount const paymentAmount = roundToScale( - STAmount{broker.asset, payment}, beforeState.loanScale); - auto loanPayTx = env.json( - pay(borrower, keylet.key, paymentAmount), fee(payFee)); + Number const payment = beforeState.periodicPayment * (total - 1); + XRPAmount const payFee{baseFee * ((total - 1) / loanPaymentsPerFeeIncrement + 1)}; + STAmount const paymentAmount = roundToScale(STAmount{broker.asset, payment}, beforeState.loanScale); + auto loanPayTx = env.json(pay(borrower, keylet.key, paymentAmount), fee(payFee)); env(loanPayTx, ter(tesSUCCESS)); env.close(); } @@ -5688,8 +4929,7 @@ protected: auto const afterState = getCurrentState(env, broker, keylet); BEAST_EXPECT(afterState.paymentRemaining == 1); BEAST_EXPECT(afterState.nextPaymentDate == maxTime - grace); - BEAST_EXPECT( - afterState.previousPaymentDate == maxTime - grace - interval); + BEAST_EXPECT(afterState.previousPaymentDate == maxTime - grace - interval); } } @@ -5711,8 +4951,7 @@ protected: .env = env, .issuer = issuer, .holders = {lender, borrower}, - .flags = MPTDEXFlags | tfMPTRequireAuth | tfMPTCanClawback | - tfMPTCanLock, + .flags = MPTDEXFlags | tfMPTRequireAuth | tfMPTCanClawback | tfMPTCanLock, .authHolder = true, }); @@ -5725,8 +4964,7 @@ protected: auto forUnauthAuth = [&](auto&& doTx) { for (auto const flag : {tfMPTUnauthorize, 0u}) { - asset.authorize( - {.account = issuer, .holder = borrower, .flags = flag}); + asset.authorize({.account = issuer, .holder = borrower, .flags = flag}); env.close(); doTx(flag == 0); env.close(); @@ -5755,8 +4993,7 @@ protected: void testCoverDepositWithdrawNonTransferableMPT() { - testcase( - "CoverDeposit and CoverWithdraw reject MPT without CanTransfer"); + testcase("CoverDeposit and CoverWithdraw reject MPT without CanTransfer"); using namespace jtx; using namespace loanBroker; @@ -5770,9 +5007,7 @@ protected: MPTTester mpt{env, issuer, mptInitNoFund}; - mpt.create( - {.flags = tfMPTCanTransfer, - .mutableFlags = tmfMPTCanMutateCanTransfer}); + mpt.create({.flags = tfMPTCanTransfer, .mutableFlags = tmfMPTCanMutateCanTransfer}); env.close(); @@ -5785,13 +5020,11 @@ protected: env.close(); Vault vault{env}; - auto const [createTx, vaultKeylet] = - vault.create({.owner = alice, .asset = asset}); + auto const [createTx, vaultKeylet] = vault.create({.owner = alice, .asset = asset}); env(createTx); env.close(); - auto const brokerKeylet = - keylet::loanbroker(alice.id(), env.seq(alice)); + auto const brokerKeylet = keylet::loanbroker(alice.id(), env.seq(alice)); env(set(alice, vaultKeylet.key)); env.close(); @@ -5799,8 +5032,7 @@ protected: if (!BEAST_EXPECT(brokerSle)) return; - Account const pseudoAccount{ - "Loan Broker pseudo-account", brokerSle->at(sfAccount)}; + Account const pseudoAccount{"Loan Broker pseudo-account", brokerSle->at(sfAccount)}; // Remove CanTransfer after the broker is set up. mpt.set({.mutableFlags = tmfMPTClearCanTransfer}); @@ -5812,12 +5044,10 @@ protected: // Cover cannot be transferred to broker account auto const depositAmount = asset(1); - env(coverDeposit(alice, brokerKeylet.key, depositAmount), - ter{tecNO_AUTH}); + env(coverDeposit(alice, brokerKeylet.key, depositAmount), ter{tecNO_AUTH}); env.close(); - if (auto const refreshed = env.le(brokerKeylet); - BEAST_EXPECT(refreshed)) + if (auto const refreshed = env.le(brokerKeylet); BEAST_EXPECT(refreshed)) { BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 0); env.require(balance(pseudoAccount, asset(0))); @@ -5830,8 +5060,7 @@ protected: env(coverDeposit(alice, brokerKeylet.key, depositAmount)); env.close(); - if (auto const refreshed = env.le(brokerKeylet); - BEAST_EXPECT(refreshed)) + if (auto const refreshed = env.le(brokerKeylet); BEAST_EXPECT(refreshed)) { BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 1); env.require(balance(pseudoAccount, depositAmount)); @@ -5842,8 +5071,7 @@ protected: env.close(); // Cover cannot be transferred from broker account - env(coverWithdraw(alice, brokerKeylet.key, depositAmount), - ter{tecNO_AUTH}); + env(coverWithdraw(alice, brokerKeylet.key, depositAmount), ter{tecNO_AUTH}); env.close(); // Set CanTransfer again and withdraw @@ -5853,8 +5081,7 @@ protected: env(coverWithdraw(alice, brokerKeylet.key, depositAmount)); env.close(); - if (auto const refreshed = env.le(brokerKeylet); - BEAST_EXPECT(refreshed)) + if (auto const refreshed = env.le(brokerKeylet); BEAST_EXPECT(refreshed)) { BEAST_EXPECT(refreshed->at(sfCoverAvailable) == 0); env.require(balance(pseudoAccount, asset(0))); @@ -5922,8 +5149,7 @@ protected: using d = NetClock::duration; using tp = NetClock::time_point; - auto const overdueClose = - tp{d{state1.nextPaymentDate + state1.paymentInterval}}; + auto const overdueClose = tp{d{state1.nextPaymentDate + state1.paymentInterval}}; env.close(overdueClose); auto const brokerSle = env.le(keylet::loanbroker(broker.brokerID)); @@ -5935,33 +5161,23 @@ protected: TenthBips16 const managementFeeRate{brokerSle->at(sfManagementFeeRate)}; TenthBips32 const interestRateValue{loanSle->at(sfInterestRate)}; - TenthBips32 const lateInterestRateValue{ - loanSle->at(sfLateInterestRate)}; - TenthBips32 const closeInterestRateValue{ - loanSle->at(sfCloseInterestRate)}; + TenthBips32 const lateInterestRateValue{loanSle->at(sfLateInterestRate)}; + TenthBips32 const closeInterestRateValue{loanSle->at(sfCloseInterestRate)}; - Number const closePaymentFeeRounded = roundToAsset( - broker.asset, loanSle->at(sfClosePaymentFee), state.loanScale); - Number const latePaymentFeeRounded = roundToAsset( - broker.asset, loanSle->at(sfLatePaymentFee), state.loanScale); + Number const closePaymentFeeRounded = + roundToAsset(broker.asset, loanSle->at(sfClosePaymentFee), state.loanScale); + Number const latePaymentFeeRounded = roundToAsset(broker.asset, loanSle->at(sfLatePaymentFee), state.loanScale); - auto const roundedLoanState = constructLoanState( - state.totalValue, - state.principalOutstanding, - state.managementFeeOutstanding); + auto const roundedLoanState = + constructLoanState(state.totalValue, state.principalOutstanding, state.managementFeeOutstanding); Number const totalInterestOutstanding = roundedLoanState.interestDue; - auto const periodicRate = - loanPeriodicRate(interestRateValue, state.paymentInterval); - auto const rawLoanState = computeTheoreticalLoanState( - state.periodicPayment, - periodicRate, - state.paymentRemaining, - managementFeeRate); + auto const periodicRate = loanPeriodicRate(interestRateValue, state.paymentInterval); + auto const rawLoanState = + computeTheoreticalLoanState(state.periodicPayment, periodicRate, state.paymentRemaining, managementFeeRate); auto const parentCloseTime = env.current()->parentCloseTime(); - auto const startDateSeconds = static_cast( - state.startDate.time_since_epoch().count()); + auto const startDateSeconds = static_cast(state.startDate.time_since_epoch().count()); Number const fullPaymentInterest = computeFullPaymentInterest( rawLoanState.principalOutstanding, @@ -5972,46 +5188,30 @@ protected: startDateSeconds, closeInterestRateValue); - Number const roundedFullInterestAmount = - roundToAsset(broker.asset, fullPaymentInterest, state.loanScale); - Number const roundedFullManagementFee = computeManagementFee( - broker.asset, - roundedFullInterestAmount, - managementFeeRate, - state.loanScale); - Number const roundedFullInterest = - roundedFullInterestAmount - roundedFullManagementFee; + Number const roundedFullInterestAmount = roundToAsset(broker.asset, fullPaymentInterest, state.loanScale); + Number const roundedFullManagementFee = + computeManagementFee(broker.asset, roundedFullInterestAmount, managementFeeRate, state.loanScale); + Number const roundedFullInterest = roundedFullInterestAmount - roundedFullManagementFee; - Number const trackedValueDelta = state.principalOutstanding + - totalInterestOutstanding + state.managementFeeOutstanding; - Number const untrackedManagementFee = closePaymentFeeRounded + - roundedFullManagementFee - state.managementFeeOutstanding; - Number const untrackedInterest = - roundedFullInterest - totalInterestOutstanding; + Number const trackedValueDelta = + state.principalOutstanding + totalInterestOutstanding + state.managementFeeOutstanding; + Number const untrackedManagementFee = + closePaymentFeeRounded + roundedFullManagementFee - state.managementFeeOutstanding; + Number const untrackedInterest = roundedFullInterest - totalInterestOutstanding; - Number const baseFullDue = - trackedValueDelta + untrackedInterest + untrackedManagementFee; - BEAST_EXPECT( - baseFullDue == - roundToAsset(broker.asset, baseFullDue, state.loanScale)); + Number const baseFullDue = trackedValueDelta + untrackedInterest + untrackedManagementFee; + BEAST_EXPECT(baseFullDue == roundToAsset(broker.asset, baseFullDue, state.loanScale)); - auto const overdueSeconds = - parentCloseTime.time_since_epoch().count() - state.nextPaymentDate; + auto const overdueSeconds = parentCloseTime.time_since_epoch().count() - state.nextPaymentDate; if (!BEAST_EXPECT(overdueSeconds > 0)) return; - Number const overdueRate = - loanPeriodicRate(lateInterestRateValue, overdueSeconds); + Number const overdueRate = loanPeriodicRate(lateInterestRateValue, overdueSeconds); Number const lateInterestRaw = state.principalOutstanding * overdueRate; - Number const lateInterestRounded = - roundToAsset(broker.asset, lateInterestRaw, state.loanScale); - Number const lateManagementFeeRounded = computeManagementFee( - broker.asset, - lateInterestRounded, - managementFeeRate, - state.loanScale); - Number const penaltyDue = lateInterestRounded + - lateManagementFeeRounded + latePaymentFeeRounded; + Number const lateInterestRounded = roundToAsset(broker.asset, lateInterestRaw, state.loanScale); + Number const lateManagementFeeRounded = + computeManagementFee(broker.asset, lateInterestRounded, managementFeeRate, state.loanScale); + Number const penaltyDue = lateInterestRounded + lateManagementFeeRounded + latePaymentFeeRounded; BEAST_EXPECT(penaltyDue > Number{}); auto const balanceBefore = env.balance(borrower, broker.asset).number(); @@ -6035,88 +5235,79 @@ protected: void testLoanCoverMinimumRoundingExploit() { - auto testLoanCoverMinimumRoundingExploit = - [&, this](Number const& principalRequest) { - testcase << "LoanBrokerCoverClawback drains cover via rounding" - << " principalRequested=" - << to_string(principalRequest); + auto testLoanCoverMinimumRoundingExploit = [&, this](Number const& principalRequest) { + testcase << "LoanBrokerCoverClawback drains cover via rounding" + << " principalRequested=" << to_string(principalRequest); - using namespace jtx; - using namespace loan; - using namespace loanBroker; + using namespace jtx; + using namespace loan; + using namespace loanBroker; - Env env(*this, all); + Env env(*this, all); - Account const issuer{"issuer"}; - Account const lender{"lender"}; - Account const borrower{"borrower"}; + Account const issuer{"issuer"}; + Account const lender{"lender"}; + Account const borrower{"borrower"}; - env.fund(XRP(1'000'000'000), issuer, lender, borrower); - env.close(); + env.fund(XRP(1'000'000'000), issuer, lender, borrower); + env.close(); - env(fset(issuer, asfAllowTrustLineClawback)); - env.close(); + env(fset(issuer, asfAllowTrustLineClawback)); + env.close(); - PrettyAsset const asset = issuer[iouCurrency]; - env(trust(lender, asset(2'000'0000))); - env(trust(borrower, asset(2'000'0000))); - env.close(); + PrettyAsset const asset = issuer[iouCurrency]; + env(trust(lender, asset(2'000'0000))); + env(trust(borrower, asset(2'000'0000))); + env.close(); - env(pay(issuer, lender, asset(2'000'0000))); - env.close(); + env(pay(issuer, lender, asset(2'000'0000))); + env.close(); - BrokerParameters brokerParams{ - .debtMax = 0, .coverRateMin = TenthBips32{10'000}}; - BrokerInfo broker{ - createVaultAndBroker(env, asset, lender, brokerParams)}; + BrokerParameters brokerParams{.debtMax = 0, .coverRateMin = TenthBips32{10'000}}; + BrokerInfo broker{createVaultAndBroker(env, asset, lender, brokerParams)}; - auto const loanSetFee = fee(env.current()->fees().base * 2); - auto createTx = env.jt( - set(borrower, broker.brokerID, principalRequest), - sig(sfCounterpartySignature, lender), - loanSetFee, - paymentInterval(600), - paymentTotal(1), - gracePeriod(60)); - env(createTx); - env.close(); + auto const loanSetFee = fee(env.current()->fees().base * 2); + auto createTx = env.jt( + set(borrower, broker.brokerID, principalRequest), + sig(sfCounterpartySignature, lender), + loanSetFee, + paymentInterval(600), + paymentTotal(1), + gracePeriod(60)); + env(createTx); + env.close(); - auto const brokerBefore = - env.le(keylet::loanbroker(broker.brokerID)); - BEAST_EXPECT(brokerBefore); - if (!brokerBefore) - return; + auto const brokerBefore = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerBefore); + if (!brokerBefore) + return; - Number const debtOutstanding = brokerBefore->at(sfDebtTotal); - Number const coverAvailableBefore = - brokerBefore->at(sfCoverAvailable); + Number const debtOutstanding = brokerBefore->at(sfDebtTotal); + Number const coverAvailableBefore = brokerBefore->at(sfCoverAvailable); - BEAST_EXPECT(debtOutstanding > Number{}); - BEAST_EXPECT(coverAvailableBefore > Number{}); + BEAST_EXPECT(debtOutstanding > Number{}); + BEAST_EXPECT(coverAvailableBefore > Number{}); - log << "debt=" << to_string(debtOutstanding) - << " cover_available=" << to_string(coverAvailableBefore); + log << "debt=" << to_string(debtOutstanding) << " cover_available=" << to_string(coverAvailableBefore); - env(coverClawback(issuer, 0), loanBrokerID(broker.brokerID)); - env.close(); + env(coverClawback(issuer, 0), loanBrokerID(broker.brokerID)); + env.close(); - auto const brokerAfter = - env.le(keylet::loanbroker(broker.brokerID)); - BEAST_EXPECT(brokerAfter); - if (!brokerAfter) - return; + auto const brokerAfter = env.le(keylet::loanbroker(broker.brokerID)); + BEAST_EXPECT(brokerAfter); + if (!brokerAfter) + return; - Number const debtAfter = brokerAfter->at(sfDebtTotal); - // the debt has not changed - BEAST_EXPECT(debtAfter == debtOutstanding); + Number const debtAfter = brokerAfter->at(sfDebtTotal); + // the debt has not changed + BEAST_EXPECT(debtAfter == debtOutstanding); - Number const coverAvailableAfter = - brokerAfter->at(sfCoverAvailable); + Number const coverAvailableAfter = brokerAfter->at(sfCoverAvailable); - // since the cover rate min != 0, the cover available should not - // be zero - BEAST_EXPECT(coverAvailableAfter != Number{}); - }; + // since the cover rate min != 0, the cover available should not + // be zero + BEAST_EXPECT(coverAvailableAfter != Number{}); + }; // Call the lambda with different principal values testLoanCoverMinimumRoundingExploit(Number{1, -30}); // 1e-30 units @@ -6143,8 +5334,7 @@ protected: // and LoanPay applies the inflated valueChange to the vault // (sfAssetsTotal), increasing NAV. // -------------------------------------------------------------------- - testcase( - "PoC: Unsigned-underflow full-pay accrual after early periodic"); + testcase("PoC: Unsigned-underflow full-pay accrual after early periodic"); using namespace jtx; using namespace loan; @@ -6159,8 +5349,7 @@ protected: PrettyAsset const asset{xrpIssue(), 1'000'000}; BrokerParameters brokerParams{}; - auto const broker = - createVaultAndBroker(env, asset, lender, brokerParams); + auto const broker = createVaultAndBroker(env, asset, lender, brokerParams); // Create a 3-payment loan so full-payment path is enabled after 1 // periodic payment. @@ -6206,8 +5395,7 @@ protected: // Compute a regular periodic due and pay it early (before next due). auto state = getCurrentState(env, broker, loanKeylet); - Number const periodicRate = - loanPeriodicRate(state.interestRate, state.paymentInterval); + Number const periodicRate = loanPeriodicRate(state.interestRate, state.paymentInterval); auto const components = detail::computePaymentComponents( asset.raw(), state.loanScale, @@ -6218,8 +5406,7 @@ protected: periodicRate, state.paymentRemaining, brokerParams.managementFeeRate); - STAmount const regularDue{ - asset, components.trackedValueDelta + serviceFeePA.number()}; + STAmount const regularDue{asset, components.trackedValueDelta + serviceFeePA.number()}; // now < nextDue immediately after creation, so this is an early pay. env(pay(borrower, loanKeylet.key, regularDue)); env.close(); @@ -6232,103 +5419,72 @@ protected: auto const brokerSle2 = env.le(keylet::loanbroker(broker.brokerID)); BEAST_EXPECT(brokerSle2); - auto const closePaymentFee = - loanSle ? loanSle->at(sfClosePaymentFee) : Number{}; - auto const closeInterestRate = loanSle - ? TenthBips32{loanSle->at(sfCloseInterestRate)} - : TenthBips32{}; - auto const managementFeeRate = brokerSle2 - ? TenthBips16{brokerSle2->at(sfManagementFeeRate)} - : TenthBips16{}; + auto const closePaymentFee = loanSle ? loanSle->at(sfClosePaymentFee) : Number{}; + auto const closeInterestRate = loanSle ? TenthBips32{loanSle->at(sfCloseInterestRate)} : TenthBips32{}; + auto const managementFeeRate = brokerSle2 ? TenthBips16{brokerSle2->at(sfManagementFeeRate)} : TenthBips16{}; - Number const periodicRate2 = - loanPeriodicRate(after.interestRate, after.paymentInterval); + Number const periodicRate2 = loanPeriodicRate(after.interestRate, after.paymentInterval); // Accrued + prepayment-penalty interest based on current periodic // schedule auto const fullPaymentInterest = computeFullPaymentInterest( - detail::loanPrincipalFromPeriodicPayment( - after.periodicPayment, periodicRate2, after.paymentRemaining), + detail::loanPrincipalFromPeriodicPayment(after.periodicPayment, periodicRate2, after.paymentRemaining), periodicRate2, env.current()->parentCloseTime(), after.paymentInterval, after.previousPaymentDate, - static_cast( - after.startDate.time_since_epoch().count()), + static_cast(after.startDate.time_since_epoch().count()), closeInterestRate); // Round to asset scale and split interest/fee parts - auto const roundedInterest = - roundToAsset(asset.raw(), fullPaymentInterest, after.loanScale); - Number const roundedFullMgmtFee = computeManagementFee( - asset.raw(), roundedInterest, managementFeeRate, after.loanScale); + auto const roundedInterest = roundToAsset(asset.raw(), fullPaymentInterest, after.loanScale); + Number const roundedFullMgmtFee = + computeManagementFee(asset.raw(), roundedInterest, managementFeeRate, after.loanScale); Number const roundedFullInterest = roundedInterest - roundedFullMgmtFee; // Show both signed and unsigned deltas to highlight the underflow. - auto const nowSecs = static_cast( - env.current()->parentCloseTime().time_since_epoch().count()); - auto const startSecs = static_cast( - after.startDate.time_since_epoch().count()); - auto const lastPaymentDate = - std::max(after.previousPaymentDate, startSecs); - auto const signedDelta = static_cast(nowSecs) - - static_cast(lastPaymentDate); - auto const unsignedDelta = - static_cast(nowSecs - lastPaymentDate); - log << "PoC window: prev=" << after.previousPaymentDate - << " start=" << startSecs << " now=" << nowSecs - << " signedDelta=" << signedDelta - << " unsignedDelta=" << unsignedDelta << std::endl; + auto const nowSecs = static_cast(env.current()->parentCloseTime().time_since_epoch().count()); + auto const startSecs = static_cast(after.startDate.time_since_epoch().count()); + auto const lastPaymentDate = std::max(after.previousPaymentDate, startSecs); + auto const signedDelta = static_cast(nowSecs) - static_cast(lastPaymentDate); + auto const unsignedDelta = static_cast(nowSecs - lastPaymentDate); + log << "PoC window: prev=" << after.previousPaymentDate << " start=" << startSecs << " now=" << nowSecs + << " signedDelta=" << signedDelta << " unsignedDelta=" << unsignedDelta << std::endl; // Reference (clamped) computation: emulate a non-negative accrual // window by clamping prevPaymentDate to 'now' for the full-pay path. auto const prevClamped = std::min(after.previousPaymentDate, nowSecs); auto const fullPaymentInterestClamped = computeFullPaymentInterest( - detail::loanPrincipalFromPeriodicPayment( - after.periodicPayment, periodicRate2, after.paymentRemaining), + detail::loanPrincipalFromPeriodicPayment(after.periodicPayment, periodicRate2, after.paymentRemaining), periodicRate2, env.current()->parentCloseTime(), after.paymentInterval, prevClamped, startSecs, closeInterestRate); - auto const roundedInterestClamped = roundToAsset( - asset.raw(), fullPaymentInterestClamped, after.loanScale); - Number const roundedFullMgmtFeeClamped = computeManagementFee( - asset.raw(), - roundedInterestClamped, - managementFeeRate, - after.loanScale); - Number const roundedFullInterestClamped = - roundedInterestClamped - roundedFullMgmtFeeClamped; + auto const roundedInterestClamped = roundToAsset(asset.raw(), fullPaymentInterestClamped, after.loanScale); + Number const roundedFullMgmtFeeClamped = + computeManagementFee(asset.raw(), roundedInterestClamped, managementFeeRate, after.loanScale); + Number const roundedFullInterestClamped = roundedInterestClamped - roundedFullMgmtFeeClamped; STAmount const fullDueClamped{ asset, - after.principalOutstanding + roundedFullInterestClamped + - roundedFullMgmtFeeClamped + closePaymentFee}; + after.principalOutstanding + roundedFullInterestClamped + roundedFullMgmtFeeClamped + closePaymentFee}; // Collect vault NAV before closing payment - auto const vaultId2 = - brokerSle2 ? brokerSle2->at(sfVaultID) : uint256{}; + auto const vaultId2 = brokerSle2 ? brokerSle2->at(sfVaultID) : uint256{}; auto const vaultKey2 = keylet::vault(vaultId2); auto const vaultBefore = env.le(vaultKey2); BEAST_EXPECT(vaultBefore); - Number const assetsTotalBefore = - vaultBefore ? vaultBefore->at(sfAssetsTotal) : Number{}; + Number const assetsTotalBefore = vaultBefore ? vaultBefore->at(sfAssetsTotal) : Number{}; STAmount const fullDue{ - asset, - after.principalOutstanding + roundedFullInterest + - roundedFullMgmtFee + closePaymentFee}; + asset, after.principalOutstanding + roundedFullInterest + roundedFullMgmtFee + closePaymentFee}; log << "PoC payoff: principalOutstanding=" << after.principalOutstanding - << " roundedFullInterest=" << roundedFullInterest - << " roundedFullMgmtFee=" << roundedFullMgmtFee - << " closeFee=" << closePaymentFee - << " fullDue=" << to_string(fullDue.getJson()) << std::endl; - log << "PoC reference (clamped): roundedFullInterestClamped=" - << roundedFullInterestClamped + << " roundedFullInterest=" << roundedFullInterest << " roundedFullMgmtFee=" << roundedFullMgmtFee + << " closeFee=" << closePaymentFee << " fullDue=" << to_string(fullDue.getJson()) << std::endl; + log << "PoC reference (clamped): roundedFullInterestClamped=" << roundedFullInterestClamped << " roundedFullMgmtFeeClamped=" << roundedFullMgmtFeeClamped - << " fullDueClamped=" << to_string(fullDueClamped.getJson()) - << std::endl; + << " fullDueClamped=" << to_string(fullDueClamped.getJson()) << std::endl; env(pay(borrower, loanKeylet.key, fullDue), txflags(tfLoanFullPayment)); env.close(); @@ -6343,10 +5499,8 @@ protected: if (vaultAfter) { auto const assetsTotalAfter = vaultAfter->at(sfAssetsTotal); - log << "PoC NAV: assetsTotalBefore=" << assetsTotalBefore - << " assetsTotalAfter=" << assetsTotalAfter - << " delta=" << (assetsTotalAfter - assetsTotalBefore) - << std::endl; + log << "PoC NAV: assetsTotalBefore=" << assetsTotalBefore << " assetsTotalAfter=" << assetsTotalAfter + << " delta=" << (assetsTotalAfter - assetsTotalBefore) << std::endl; // Value-based proof: underflowed window yields a payoff larger than // the clamped (non-underflow) reference. @@ -6431,9 +5585,7 @@ protected: // before the loan the assets total and available should be equal BEAST_EXPECT(assetsAvail == assetsTotal); - BEAST_EXPECT( - assetsAvail == - broker.asset(brokerParams.vaultDeposit).number()); + BEAST_EXPECT(assetsAvail == broker.asset(brokerParams.vaultDeposit).number()); } Keylet const& loanKeylet = *loanKeyletOpt; @@ -6470,28 +5622,17 @@ protected: auto const state = constructRoundedLoanState(loanSle); log << "Loan state:" << std::endl; - log << " ValueOutstanding: " << state.valueOutstanding - << std::endl; - log << " PrincipalOutstanding: " << state.principalOutstanding - << std::endl; - log << " InterestOutstanding: " << state.interestOutstanding() - << std::endl; + log << " ValueOutstanding: " << state.valueOutstanding << std::endl; + log << " PrincipalOutstanding: " << state.principalOutstanding << std::endl; + log << " InterestOutstanding: " << state.interestOutstanding() << std::endl; log << " InterestDue: " << state.interestDue << std::endl; log << " FeeDue: " << state.managementFeeDue << std::endl; // after loan creation the assets total and available should // reflect the value of the loan BEAST_EXPECT(assetsAvail < assetsTotal); - BEAST_EXPECT( - assetsAvail == - broker - .asset( - brokerParams.vaultDeposit - loanParams.principalRequest) - .number()); - BEAST_EXPECT( - assetsTotal == - broker.asset(brokerParams.vaultDeposit + state.interestDue) - .number()); + BEAST_EXPECT(assetsAvail == broker.asset(brokerParams.vaultDeposit - loanParams.principalRequest).number()); + BEAST_EXPECT(assetsTotal == broker.asset(brokerParams.vaultDeposit + state.interestDue).number()); } // Step 7: Trigger default (dust adjustment will occur) @@ -6507,8 +5648,7 @@ protected: log << "After default:" << std::endl; log << " AssetsTotal: " << assetsTotal2 << std::endl; log << " AssetsAvailable: " << assetsAvail2 << std::endl; - log << " Difference: " << (assetsTotal2 - assetsAvail2) - << std::endl; + log << " Difference: " << (assetsTotal2 - assetsAvail2) << std::endl; // after a default the assets total and available should be equal BEAST_EXPECT(assetsAvail2 == assetsTotal2); @@ -6545,8 +5685,7 @@ protected: Env env(*this, all); - auto loanResult = createLoan( - env, assetType, brokerParams, loanParams, issuer, lender, borrower); + auto loanResult = createLoan(env, assetType, brokerParams, loanParams, issuer, lender, borrower); if (!BEAST_EXPECT(loanResult)) return; @@ -6560,17 +5699,14 @@ protected: auto state = getCurrentState(env, broker, loanKeylet); if (auto loan = env.le(loanKeylet); BEAST_EXPECT(loan)) { - env.close(tp{d{ - loan->at(sfNextPaymentDueDate) + loan->at(sfGracePeriod) + 1}}); + env.close(tp{d{loan->at(sfNextPaymentDueDate) + loan->at(sfGracePeriod) + 1}}); } - topUpBorrower( - env, broker, issuer, borrower, state, loanParams.serviceFee); + topUpBorrower(env, broker, issuer, borrower, state, loanParams.serviceFee); using namespace jtx::loan; - auto jv = - pay(borrower, loanKeylet.key, drops(XRPAmount(state.totalValue))); + auto jv = pay(borrower, loanKeylet.key, drops(XRPAmount(state.totalValue))); { auto const submitParam = to_string(jv); @@ -6619,8 +5755,7 @@ protected: Env env(*this, all); - auto loanResult = createLoan( - env, assetType, brokerParams, loanParams, issuer, lender, borrower); + auto loanResult = createLoan(env, assetType, brokerParams, loanParams, issuer, lender, borrower); if (!BEAST_EXPECT(loanResult)) return; @@ -6631,14 +5766,11 @@ protected: VerifyLoanStatus verifyLoanStatus(env, broker, pseudoAcct, loanKeylet); - if (auto const brokerSle = env.le(broker.brokerKeylet()); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(broker.brokerKeylet()); BEAST_EXPECT(brokerSle)) { if (auto const loanSle = env.le(loanKeylet); BEAST_EXPECT(loanSle)) { - BEAST_EXPECT( - brokerSle->at(sfDebtTotal) == - loanSle->at(sfTotalValueOutstanding)); + BEAST_EXPECT(brokerSle->at(sfDebtTotal) == loanSle->at(sfTotalValueOutstanding)); } } @@ -6653,14 +5785,11 @@ protected: borrower, PaymentParameters{.showStepBalances = true}); - if (auto const brokerSle = env.le(broker.brokerKeylet()); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(broker.brokerKeylet()); BEAST_EXPECT(brokerSle)) { if (auto const loanSle = env.le(loanKeylet); BEAST_EXPECT(loanSle)) { - BEAST_EXPECT( - brokerSle->at(sfDebtTotal) == - loanSle->at(sfTotalValueOutstanding)); + BEAST_EXPECT(brokerSle->at(sfDebtTotal) == loanSle->at(sfTotalValueOutstanding)); BEAST_EXPECT(brokerSle->at(sfDebtTotal) == beast::zero); } } @@ -6684,20 +5813,14 @@ protected: env.fund(XRP(10'000), lender, issuer, borrower, depositor); env.close(); - auto [tx, vaultKeyLet] = - vault.create({.owner = lender, .asset = xrpIssue()}); + auto [tx, vaultKeyLet] = vault.create({.owner = lender, .asset = xrpIssue()}); env(tx, txfee); env.close(); - env(vault.deposit( - {.depositor = depositor, - .id = vaultKeyLet.key, - .amount = XRP(1'000)}), - txfee); + env(vault.deposit({.depositor = depositor, .id = vaultKeyLet.key, .amount = XRP(1'000)}), txfee); env.close(); - auto const brokerKeyLet = - keylet::loanbroker(lender.id(), env.seq(lender)); + auto const brokerKeyLet = keylet::loanbroker(lender.id(), env.seq(lender)); env(loanBroker::set(lender, vaultKeyLet.key), txfee); env.close(); @@ -6720,9 +5843,7 @@ protected: if (auto loan = env.le(loanKeylet); env.test.BEAST_EXPECT(loan)) { - env(loan::pay(borrower, loanKeylet.key, XRPAmount(150'001)), - txflags(tfLoanOverpayment), - txfee); + env(loan::pay(borrower, loanKeylet.key, XRPAmount(150'001)), txflags(tfLoanOverpayment), txfee); env.close(); } } @@ -6745,8 +5866,7 @@ protected: // Vault with XRP asset Vault vault{env}; - auto [vaultCreate, vaultKeylet] = - vault.create({.owner = lender, .asset = xrpIssue()}); + auto [vaultCreate, vaultKeylet] = vault.create({.owner = lender, .asset = xrpIssue()}); env(vaultCreate); env.close(); BEAST_EXPECT(env.le(vaultKeylet)); @@ -6761,8 +5881,7 @@ protected: .coverDeposit = 82, }; - auto const brokerInfo = - createVaultAndBroker(env, xrpAsset, lender, brokerParams); + auto const brokerInfo = createVaultAndBroker(env, xrpAsset, lender, brokerParams); // Create a loan with principal 804 XRP and 0% interest (so // DebtTotal increases by exactly 804) env(loan::set(borrower, brokerInfo.brokerID, xrpAsset(804).value()), @@ -6773,9 +5892,7 @@ protected: env.close(); // Verify DebtTotal is exactly 804 - if (auto const brokerSle = - env.le(keylet::loanbroker(brokerInfo.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(brokerInfo.brokerID)); BEAST_EXPECT(brokerSle)) { log << *brokerSle << std::endl; BEAST_EXPECT(brokerSle->at(sfDebtTotal) == Number(804)); @@ -6783,8 +5900,7 @@ protected: // Attempt to withdraw 2 XRP to self, leaving 80 XRP CoverAvailable. // The minimum is 80.4 XRP, which rounds up to 81 XRP, so this fails. - env(coverWithdraw(lender, brokerInfo.brokerID, xrpAsset(2).value()), - ter(tecINSUFFICIENT_FUNDS)); + env(coverWithdraw(lender, brokerInfo.brokerID, xrpAsset(2).value()), ter(tecINSUFFICIENT_FUNDS)); BEAST_EXPECT(env.ter() == tecINSUFFICIENT_FUNDS); env.close(); @@ -6795,18 +5911,14 @@ protected: env.close(); // Validate CoverAvailable == 80 XRP and DebtTotal remains 804 - if (auto const brokerSle = - env.le(keylet::loanbroker(brokerInfo.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(brokerInfo.brokerID)); BEAST_EXPECT(brokerSle)) { log << *brokerSle << std::endl; - BEAST_EXPECT( - brokerSle->at(sfCoverAvailable) == xrpAsset(81).value()); + BEAST_EXPECT(brokerSle->at(sfCoverAvailable) == xrpAsset(81).value()); BEAST_EXPECT(brokerSle->at(sfDebtTotal) == Number(804)); // Also demonstrate that the true minimum (804 * 10%) exceeds 80 - auto const theoreticalMin = - tenthBipsOfValue(Number(804), TenthBips32(10'000)); + auto const theoreticalMin = tenthBipsOfValue(Number(804), TenthBips32(10'000)); log << "Theoretical min cover: " << theoreticalMin << std::endl; BEAST_EXPECT(Number(804, -1) == theoreticalMin); } @@ -6842,8 +5954,7 @@ protected: Env env(*this, all); - auto loanResult = createLoan( - env, assetType, brokerParams, loanParams, issuer, lender, borrower); + auto loanResult = createLoan(env, assetType, brokerParams, loanParams, issuer, lender, borrower); if (!BEAST_EXPECT(loanResult)) return; @@ -6895,20 +6006,14 @@ protected: auto const& asset = debtMaximumRequest.asset(); auto const initialVault = asset(debtMaximumRequest * 100); - auto [tx, vaultKeylet] = - vault.create({.owner = broker, .asset = asset}); + auto [tx, vaultKeylet] = vault.create({.owner = broker, .asset = asset}); env(tx, txFee); env.close(); - env(vault.deposit( - {.depositor = depositor, - .id = vaultKeylet.key, - .amount = initialVault}), - txFee); + env(vault.deposit({.depositor = depositor, .id = vaultKeylet.key, .amount = initialVault}), txFee); env.close(); - auto const brokerKeylet = - keylet::loanbroker(broker.id(), env.seq(broker)); + auto const brokerKeylet = keylet::loanbroker(broker.id(), env.seq(broker)); env(loanBroker::set(broker, vaultKeylet.key), txFee); env.close(); @@ -6924,21 +6029,17 @@ protected: env.close(); std::uint32_t const loanSequence = 1; - auto const loanKeylet = - keylet::loan(brokerKeylet.key, loanSequence); + auto const loanKeylet = keylet::loan(brokerKeylet.key, loanSequence); auto const brokerBalanceBefore = env.balance(broker, asset); - if (auto const loanSle = env.le(loanKeylet); - env.test.BEAST_EXPECT(loanSle)) + if (auto const loanSle = env.le(loanKeylet); env.test.BEAST_EXPECT(loanSle)) { auto const payment = loanSle->at(sfPeriodicPayment); auto const totalPayment = payment + serviceFee; - env(loan::pay(borrower, loanKeylet.key, asset(totalPayment)), - txFee); + env(loan::pay(borrower, loanKeylet.key, asset(totalPayment)), txFee); env.close(); - if (auto const vaultSle = env.le(vaultKeylet); - BEAST_EXPECT(vaultSle)) + if (auto const vaultSle = env.le(vaultKeylet); BEAST_EXPECT(vaultSle)) { auto const expected = [&]() { // The service fee is transferred to the broker if @@ -6950,13 +6051,10 @@ protected: // the service fee. // If the asset is XRP then the broker pays the txfee. if (asset.native()) - return brokerBalanceBefore.number() - payment - - xrpFee.number(); + return brokerBalanceBefore.number() - payment - xrpFee.number(); return brokerBalanceBefore.number() - payment; }(); - BEAST_EXPECT( - env.balance(broker, asset).value() == - asset(expected).value()); + BEAST_EXPECT(env.balance(broker, asset).value() == asset(expected).value()); } } }; @@ -6964,9 +6062,7 @@ protected: // service fee transfer in both cases. for (auto const& borrowerAcct : {broker, borrower_}) { - testLoanAsset( - [&](Env&) -> STAmount { return STAmount{XRPAmount{200'000}}; }, - borrowerAcct); + testLoanAsset([&](Env&) -> STAmount { return STAmount{XRPAmount{200'000}}; }, borrowerAcct); testLoanAsset( [&](Env& env) -> STAmount { auto const IOU = issuer["USD"]; @@ -6980,11 +6076,7 @@ protected: borrowerAcct); testLoanAsset( [&](Env& env) -> STAmount { - MPTTester mpt( - {.env = env, - .issuer = issuer, - .holders = {broker, depositor}, - .pay = 100'000'000}); + MPTTester mpt({.env = env, .issuer = issuer, .holders = {broker, depositor}, .pay = 100'000'000}); return mpt(200'000); }, borrowerAcct); @@ -7007,17 +6099,13 @@ protected: .coverRateMin = TenthBips32{0}, .managementFeeRate = TenthBips16{0}, .coverRateLiquidation = TenthBips32{0}}; - LoanParameters const loanParams{ - .account = lender, - .counter = issuer, - .principalRequest = Number{10000}}; + LoanParameters const loanParams{.account = lender, .counter = issuer, .principalRequest = Number{10000}}; auto const assetType = AssetType::IOU; Env env(*this, all); - auto loanResult = createLoan( - env, assetType, brokerParams, loanParams, issuer, lender, issuer); + auto loanResult = createLoan(env, assetType, brokerParams, loanParams, issuer, lender, issuer); if (!BEAST_EXPECT(loanResult)) return; @@ -7070,15 +6158,9 @@ protected: auto const assetType = AssetType::XRP; - Env env( - *this, - makeConfig(), - all, - nullptr, - beast::severities::Severity::kWarning); + Env env(*this, makeConfig(), all, nullptr, beast::severities::Severity::kWarning); - auto loanResult = createLoan( - env, assetType, brokerParams, loanParams, issuer, lender, borrower); + auto loanResult = createLoan(env, assetType, brokerParams, loanParams, issuer, lender, borrower); if (!BEAST_EXPECT(loanResult)) return; @@ -7092,10 +6174,7 @@ protected: auto const state = getCurrentState(env, broker, loanKeylet); env(loan::pay( - borrower, - loanKeylet.key, - STAmount{broker.asset, state.periodicPayment * 3 / 2 + 1}, - tfLoanOverpayment)); + borrower, loanKeylet.key, STAmount{broker.asset, state.periodicPayment * 3 / 2 + 1}, tfLoanOverpayment)); env.close(); PaymentParameters paymentParams{ @@ -7104,15 +6183,7 @@ protected: }; makeLoanPayments( - env, - broker, - loanParams, - loanKeylet, - verifyLoanStatus, - issuer, - lender, - borrower, - paymentParams); + env, broker, loanParams, loanKeylet, verifyLoanStatus, issuer, lender, borrower, paymentParams); } void @@ -7143,19 +6214,13 @@ protected: auto const loanSetFee = fee(env.current()->fees().base * 2); - auto const loanKeylet = keylet::loan( - result.brokerKeylet().key, - (env.le(result.brokerKeylet()))->at(sfLoanSequence)); - env(loan::set( - borrower, - result.brokerKeylet().key, - asset(10'000).value(), - tfLoanOverpayment), + auto const loanKeylet = + keylet::loan(result.brokerKeylet().key, (env.le(result.brokerKeylet()))->at(sfLoanSequence)); + env(loan::set(borrower, result.brokerKeylet().key, asset(10'000).value(), tfLoanOverpayment), sig(sfCounterpartySignature, lender), loan::paymentInterval(86400 * 30), loan::paymentTotal(3), - loan::overpaymentInterestRate( - TenthBips32(percentageToTenthBips(20))), + loan::overpaymentInterestRate(TenthBips32(percentageToTenthBips(20))), loanSetFee); // From calculator @@ -7163,19 +6228,13 @@ protected: auto const loanBrokerBalanceBefore = env.balance(lender); auto const loanPayFee = fee(env.current()->fees().base * 2); - env(pay(borrower, - loanKeylet.key, - asset(5'000).value(), - tfLoanOverpayment), - loanPayFee); + env(pay(borrower, loanKeylet.key, asset(5'000).value(), tfLoanOverpayment), loanPayFee); env.close(); BEAST_EXPECTS( - env.balance(lender) - loanBrokerBalanceBefore == - expectedOverpaymentManagementFee, - "overpayment management fee missmatch; expected:" + - to_string(expectedOverpaymentManagementFee) + " got: " + - to_string(env.balance(lender) - loanBrokerBalanceBefore)); + env.balance(lender) - loanBrokerBalanceBefore == expectedOverpaymentManagementFee, + "overpayment management fee missmatch; expected:" + to_string(expectedOverpaymentManagementFee) + + " got: " + to_string(env.balance(lender) - loanBrokerBalanceBefore)); } void @@ -7214,8 +6273,7 @@ protected: // at least 1,000 cover. Default cover is 1,000, so we add more to be // safe. auto const additionalCover = IOU(50'000).value(); - env(loanBroker::coverDeposit( - broker, brokerInfo.brokerID, STAmount{IOU, additionalCover})); + env(loanBroker::coverDeposit(broker, brokerInfo.brokerID, STAmount{IOU, additionalCover})); env.close(); // Verify broker owner has a trustline auto const brokerTrustline = keylet::line(broker, IOU); @@ -7232,22 +6290,17 @@ protected: BEAST_EXPECT(env.le(brokerTrustline) == nullptr); // Now borrower tries to make a payment // We should get a tesSUCCESS instead of a tecNO_LINE. - env(pay(borrower, keylet.key, IOU(10'100)), - fee(XRP(100)), - ter(tesSUCCESS)); + env(pay(borrower, keylet.key, IOU(10'100)), fee(XRP(100)), ter(tesSUCCESS)); env.close(); // Verify trustline is still deleted BEAST_EXPECT(env.le(brokerTrustline) == nullptr); // Verify the service fee went to the broker pseudo-account - if (auto const brokerSle = - env.le(keylet::loanbroker(brokerInfo.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(brokerInfo.brokerID)); BEAST_EXPECT(brokerSle)) { Account const pseudo("pseudo-account", brokerSle->at(sfAccount)); auto const balance = env.balance(pseudo, IOU); // 1,000 default + 50,000 extra + 100 service fee from LoanPay - BEAST_EXPECTS( - balance == IOU(51'100), to_string(Json::Value(balance))); + BEAST_EXPECTS(balance == IOU(51'100), to_string(Json::Value(balance))); } } @@ -7267,8 +6320,7 @@ protected: env.close(); MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); PrettyAsset const MPT{mptt.issuanceID()}; @@ -7300,8 +6352,7 @@ protected: // at least 1,000 cover. Default cover is 1,000, so we add more to be // safe. auto const additionalCover = MPT(50'000).value(); - env(loanBroker::coverDeposit( - broker, brokerInfo.brokerID, STAmount{MPT, additionalCover})); + env(loanBroker::coverDeposit(broker, brokerInfo.brokerID, STAmount{MPT, additionalCover})); env.close(); // Verify broker owner is authorized auto const brokerMpt = keylet::mptoken(mptt.issuanceID(), broker); @@ -7319,30 +6370,24 @@ protected: // Now borrower tries to make a payment // We should get a tesSUCCESS instead of a tecNO_AUTH. auto const borrowerBalance = env.balance(borrower, MPT); - env(pay(borrower, keylet.key, MPT(10'100)), - fee(XRP(100)), - ter(tesSUCCESS)); + env(pay(borrower, keylet.key, MPT(10'100)), fee(XRP(100)), ter(tesSUCCESS)); env.close(); // Verify the MPT is still unauthorized. BEAST_EXPECT(env.le(brokerMpt) == nullptr); // Verify the service fee went to the broker pseudo-account - if (auto const brokerSle = - env.le(keylet::loanbroker(brokerInfo.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(brokerInfo.brokerID)); BEAST_EXPECT(brokerSle)) { Account const pseudo("pseudo-account", brokerSle->at(sfAccount)); auto const balance = env.balance(pseudo, MPT); // 1,000 default + 50,000 extra + 100 service fee from LoanPay - BEAST_EXPECTS( - balance == MPT(51'100), to_string(Json::Value(balance))); + BEAST_EXPECTS(balance == MPT(51'100), to_string(Json::Value(balance))); } } void testLoanPayBrokerOwnerNoPermissionedDomainMPT() { - testcase - << "LoanPay Broker Owner without permissioned domain of the MPT"; + testcase << "LoanPay Broker Owner without permissioned domain of the MPT"; using namespace jtx; using namespace loan; @@ -7372,8 +6417,7 @@ protected: MPTTester mptt{env, issuer, mptInitNoFund}; mptt.create({ - .flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer | - tfMPTCanLock, + .flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer | tfMPTCanLock, .domainID = domainID, }); @@ -7407,8 +6451,7 @@ protected: // at least 1,000 cover. Default cover is 1,000, so we add more to be // safe. auto const additionalCover = MPT(50'000).value(); - env(loanBroker::coverDeposit( - broker, brokerInfo.brokerID, STAmount{MPT, additionalCover})); + env(loanBroker::coverDeposit(broker, brokerInfo.brokerID, STAmount{MPT, additionalCover})); env.close(); // Verify broker owner is authorized auto const brokerMpt = keylet::mptoken(mptt.issuanceID(), broker); @@ -7429,30 +6472,24 @@ protected: // Now borrower tries to make a payment // We should get a tesSUCCESS instead of a tecNO_AUTH. auto const borrowerBalance = env.balance(borrower, MPT); - env(pay(borrower, keylet.key, MPT(10'100)), - fee(XRP(100)), - ter(tesSUCCESS)); + env(pay(borrower, keylet.key, MPT(10'100)), fee(XRP(100)), ter(tesSUCCESS)); env.close(); // Verify broker is still not authorized env(pay(issuer, broker, MPT(1'000)), ter(tecNO_AUTH)); // Verify the service fee went to the broker pseudo-account - if (auto const brokerSle = - env.le(keylet::loanbroker(brokerInfo.brokerID)); - BEAST_EXPECT(brokerSle)) + if (auto const brokerSle = env.le(keylet::loanbroker(brokerInfo.brokerID)); BEAST_EXPECT(brokerSle)) { Account const pseudo("pseudo-account", brokerSle->at(sfAccount)); auto const balance = env.balance(pseudo, MPT); // 1,000 default + 50,000 extra + 100 service fee from LoanPay - BEAST_EXPECTS( - balance == MPT(51'100), to_string(Json::Value(balance))); + BEAST_EXPECTS(balance == MPT(51'100), to_string(Json::Value(balance))); } } void testLoanSetBrokerOwnerNoPermissionedDomainMPT() { - testcase - << "LoanSet Broker Owner without permissioned domain of the MPT"; + testcase << "LoanSet Broker Owner without permissioned domain of the MPT"; using namespace jtx; using namespace loan; @@ -7483,8 +6520,7 @@ protected: MPTTester mptt{env, issuer, mptInitNoFund}; mptt.create({ - .flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer | - tfMPTCanLock, + .flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer | tfMPTCanLock, .domainID = domainID, }); @@ -7542,8 +6578,7 @@ protected: env.close(); PrettyAsset const asset = xrpIssue(); - auto const vaultDepositAmount = - asset(200'000); // Enough for 2 x 50k loans plus interest/fees + auto const vaultDepositAmount = asset(200'000); // Enough for 2 x 50k loans plus interest/fees auto const brokerInfo = createVaultAndBroker( env, @@ -7703,15 +6738,11 @@ protected: beast::xor_shift_engine engine_; std::uniform_int_distribution<> assetDist{0, 2}; - std::uniform_int_distribution principalDist{ - 100'000, - 1'000'000'000}; + std::uniform_int_distribution principalDist{100'000, 1'000'000'000}; std::uniform_int_distribution interestRateDist{0, 10000}; std::uniform_int_distribution<> paymentTotalDist{12, 10000}; std::uniform_int_distribution<> paymentIntervalDist{60, 3600 * 24 * 30}; - std::uniform_int_distribution managementFeeRateDist{ - 0, - 10'000}; + std::uniform_int_distribution managementFeeRateDist{0, 10'000}; std::uniform_int_distribution<> serviceFeeDist{0, 20}; /* # Generate parameters that are more likely to be valid @@ -7795,8 +6826,7 @@ public: for (int i = 0; i < numIterations; ++i) { if (i % updateInterval == 0) - testcase << "Random Loan Test iteration " << (i + 1) << "/" - << numIterations; + testcase << "Random Loan Test iteration " << (i + 1) << "/" << numIterations; testRandomLoan(); } } diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index 65cb753755..f8d736c257 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -42,11 +42,7 @@ class MPToken_test : public beast::unit_test::suite // tries to set a txfee while not enabling in the flag mptAlice.create( - {.maxAmt = 100, - .assetScale = 0, - .transferFee = 1, - .metadata = "test", - .err = temMALFORMED}); + {.maxAmt = 100, .assetScale = 0, .transferFee = 1, .metadata = "test", .err = temMALFORMED}); if (!features[featureSingleAssetVault]) { @@ -74,11 +70,7 @@ class MPToken_test : public beast::unit_test::suite { // tries to set DomainID when RequireAuth is not set mptAlice.create( - {.maxAmt = 100, - .assetScale = 0, - .metadata = "test", - .domainID = uint256(42), - .err = temMALFORMED}); + {.maxAmt = 100, .assetScale = 0, .metadata = "test", .domainID = uint256(42), .err = temMALFORMED}); // tries to set zero DomainID mptAlice.create( @@ -108,20 +100,10 @@ class MPToken_test : public beast::unit_test::suite .err = temMALFORMED}); // empty metadata returns error - mptAlice.create( - {.maxAmt = 100, - .assetScale = 0, - .transferFee = 0, - .metadata = "", - .err = temMALFORMED}); + mptAlice.create({.maxAmt = 100, .assetScale = 0, .transferFee = 0, .metadata = "", .err = temMALFORMED}); // MaximumAmount of 0 returns error - mptAlice.create( - {.maxAmt = 0, - .assetScale = 1, - .transferFee = 1, - .metadata = "test", - .err = temMALFORMED}); + mptAlice.create({.maxAmt = 0, .assetScale = 1, .transferFee = 1, .metadata = "test", .err = temMALFORMED}); // MaximumAmount larger than 63 bit returns error mptAlice.create( @@ -158,16 +140,14 @@ class MPToken_test : public beast::unit_test::suite .transferFee = 10, .metadata = "123", .ownerCount = 1, - .flags = tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | - tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback}); + .flags = tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | + tfMPTCanClawback}); // Get the hash for the most recent transaction. - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; Json::Value const result = env.rpc("tx", txHash)[jss::result]; - BEAST_EXPECT( - result[sfMaximumAmount.getJsonName()] == "9223372036854775807"); + BEAST_EXPECT(result[sfMaximumAmount.getJsonName()] == "9223372036854775807"); } if (features[featureSingleAssetVault]) @@ -176,8 +156,7 @@ class MPToken_test : public beast::unit_test::suite Account const credIssuer1{"credIssuer1"}; std::string const credType = "credential"; - pdomain::Credentials const credentials1{ - {.issuer = credIssuer1, .credType = credType}}; + pdomain::Credentials const credentials1{{.issuer = credIssuer1, .credType = credType}}; { Env env{*this, features}; @@ -196,19 +175,16 @@ class MPToken_test : public beast::unit_test::suite .transferFee = 10, .metadata = "123", .ownerCount = 1, - .flags = tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | - tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback, + .flags = tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | + tfMPTCanClawback, .domainID = domainId1, }); // Get the hash for the most recent transaction. - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; Json::Value const result = env.rpc("tx", txHash)[jss::result]; - BEAST_EXPECT( - result[sfMaximumAmount.getJsonName()] == - "9223372036854775807"); + BEAST_EXPECT(result[sfMaximumAmount.getJsonName()] == "9223372036854775807"); } } } @@ -230,8 +206,7 @@ class MPToken_test : public beast::unit_test::suite env.enableFeature(featureMPTokensV1); - mptAlice.destroy( - {.id = id, .flags = 0x00000001, .err = temINVALID_FLAG}); + mptAlice.destroy({.id = id, .flags = 0x00000001, .err = temINVALID_FLAG}); } // MPTokenIssuanceDestroy (preclaim) @@ -239,10 +214,7 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, features}; MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.destroy( - {.id = makeMptID(env.seq(alice), alice), - .ownerCount = 0, - .err = tecOBJECT_NOT_FOUND}); + mptAlice.destroy({.id = makeMptID(env.seq(alice), alice), .ownerCount = 0, .err = tecOBJECT_NOT_FOUND}); mptAlice.create({.ownerCount = 1}); @@ -295,10 +267,7 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, features - featureMPTokensV1}; MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.authorize( - {.account = bob, - .id = makeMptID(env.seq(alice), alice), - .err = temDISABLED}); + mptAlice.authorize({.account = bob, .id = makeMptID(env.seq(alice), alice), .err = temDISABLED}); } // Validate fields in MPTokenAuthorize (preflight) @@ -310,11 +279,9 @@ class MPToken_test : public beast::unit_test::suite // The only valid MPTokenAuthorize flag is tfMPTUnauthorize, which // has a value of 1 - mptAlice.authorize( - {.account = bob, .flags = 0x00000002, .err = temINVALID_FLAG}); + mptAlice.authorize({.account = bob, .flags = 0x00000002, .err = temINVALID_FLAG}); - mptAlice.authorize( - {.account = bob, .holder = bob, .err = temMALFORMED}); + mptAlice.authorize({.account = bob, .holder = bob, .err = temMALFORMED}); mptAlice.authorize({.holder = alice, .err = temMALFORMED}); } @@ -326,11 +293,9 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); auto const id = makeMptID(env.seq(alice), alice); - mptAlice.authorize( - {.holder = bob, .id = id, .err = tecOBJECT_NOT_FOUND}); + mptAlice.authorize({.holder = bob, .id = id, .err = tecOBJECT_NOT_FOUND}); - mptAlice.authorize( - {.account = bob, .id = id, .err = tecOBJECT_NOT_FOUND}); + mptAlice.authorize({.account = bob, .id = id, .err = tecOBJECT_NOT_FOUND}); } // Test bad scenarios without allowlisting in MPTokenAuthorize @@ -342,8 +307,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.create({.ownerCount = 1}); // bob submits a tx with a holder field - mptAlice.authorize( - {.account = bob, .holder = alice, .err = tecNO_PERMISSION}); + mptAlice.authorize({.account = bob, .holder = alice, .err = tecNO_PERMISSION}); // alice tries to hold onto her own token mptAlice.authorize({.account = alice, .err = tecNO_PERMISSION}); @@ -365,10 +329,7 @@ class MPToken_test : public beast::unit_test::suite // bob tries to delete his MPToken, but fails since he still // holds tokens - mptAlice.authorize( - {.account = bob, - .flags = tfMPTUnauthorize, - .err = tecHAS_OBLIGATIONS}); + mptAlice.authorize({.account = bob, .flags = tfMPTUnauthorize, .err = tecHAS_OBLIGATIONS}); // bob pays back alice 100 tokens mptAlice.pay(bob, alice, 100); @@ -380,10 +341,7 @@ class MPToken_test : public beast::unit_test::suite // bob receives error when he tries to delete his MPToken that has // already been deleted mptAlice.authorize( - {.account = bob, - .holderCount = 0, - .flags = tfMPTUnauthorize, - .err = tecOBJECT_NOT_FOUND}); + {.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize, .err = tecOBJECT_NOT_FOUND}); } // Test bad scenarios with allow-listing in MPTokenAuthorize (preclaim) @@ -421,8 +379,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.authorize({.holder = bob}); // bob deletes his mptoken - mptAlice.authorize( - {.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize}); } // Test mptoken reserve requirement - first two mpts free (doApply) @@ -433,11 +390,7 @@ class MPToken_test : public beast::unit_test::suite // 1 drop BEAST_EXPECT(incReserve > XRPAmount(1)); - MPTTester mptAlice1( - env, - alice, - {.holders = {bob}, - .xrpHolders = acctReserve + (incReserve - 1)}); + MPTTester mptAlice1(env, alice, {.holders = {bob}, .xrpHolders = acctReserve + (incReserve - 1)}); mptAlice1.create(); MPTTester mptAlice2(env, alice, {.fund = false}); @@ -452,11 +405,9 @@ class MPToken_test : public beast::unit_test::suite // second mpt free mptAlice2.authorize({.account = bob, .holderCount = 2}); - mptAlice3.authorize( - {.account = bob, .err = tecINSUFFICIENT_RESERVE}); + mptAlice3.authorize({.account = bob, .err = tecINSUFFICIENT_RESERVE}); - env(pay( - env.master, bob, drops(incReserve + incReserve + incReserve))); + env(pay(env.master, bob, drops(incReserve + incReserve + incReserve))); env.close(); mptAlice3.authorize({.account = bob, .holderCount = 3}); @@ -483,12 +434,10 @@ class MPToken_test : public beast::unit_test::suite // bob creates a mptoken mptAlice.authorize({.account = bob, .holderCount = 1}); - mptAlice.authorize( - {.account = bob, .holderCount = 1, .err = tecDUPLICATE}); + mptAlice.authorize({.account = bob, .holderCount = 1, .err = tecDUPLICATE}); // bob deletes his mptoken - mptAlice.authorize( - {.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize}); } // With allowlisting @@ -507,14 +456,9 @@ class MPToken_test : public beast::unit_test::suite mptAlice.authorize({.account = alice, .holder = bob}); // Unauthorize bob's mptoken - mptAlice.authorize( - {.account = alice, - .holder = bob, - .holderCount = 1, - .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = alice, .holder = bob, .holderCount = 1, .flags = tfMPTUnauthorize}); - mptAlice.authorize( - {.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize}); } // Holder can have dangling MPToken even if issuance has been destroyed. @@ -533,8 +477,7 @@ class MPToken_test : public beast::unit_test::suite // bob can delete his mptoken even though issuance is no longer // existent - mptAlice.authorize( - {.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = bob, .holderCount = 0, .flags = tfMPTUnauthorize}); } } @@ -552,10 +495,7 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, features - featureMPTokensV1}; MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.set( - {.account = bob, - .id = makeMptID(env.seq(alice), alice), - .err = temDISABLED}); + mptAlice.set({.account = bob, .id = makeMptID(env.seq(alice), alice), .err = temDISABLED}); env.enableFeature(featureMPTokensV1); @@ -565,79 +505,43 @@ class MPToken_test : public beast::unit_test::suite // test invalid flag - only valid flags are tfMPTLock (1) and Unlock // (2) - mptAlice.set( - {.account = alice, - .flags = 0x00000008, - .err = temINVALID_FLAG}); + mptAlice.set({.account = alice, .flags = 0x00000008, .err = temINVALID_FLAG}); - if (!features[featureSingleAssetVault] && - !features[featureDynamicMPT]) + if (!features[featureSingleAssetVault] && !features[featureDynamicMPT]) { // test invalid flags - nothing is being changed - mptAlice.set( - {.account = alice, - .flags = 0x00000000, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .flags = 0x00000000, .err = tecNO_PERMISSION}); - mptAlice.set( - {.account = alice, - .holder = bob, - .flags = 0x00000000, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .holder = bob, .flags = 0x00000000, .err = tecNO_PERMISSION}); // cannot set DomainID since SAV is not enabled - mptAlice.set( - {.account = alice, - .domainID = uint256(42), - .err = temDISABLED}); + mptAlice.set({.account = alice, .domainID = uint256(42), .err = temDISABLED}); } else { // test invalid flags - nothing is being changed - mptAlice.set( - {.account = alice, - .flags = 0x00000000, - .err = temMALFORMED}); + mptAlice.set({.account = alice, .flags = 0x00000000, .err = temMALFORMED}); - mptAlice.set( - {.account = alice, - .holder = bob, - .flags = 0x00000000, - .err = temMALFORMED}); + mptAlice.set({.account = alice, .holder = bob, .flags = 0x00000000, .err = temMALFORMED}); - if (!features[featurePermissionedDomains] || - !features[featureSingleAssetVault]) + if (!features[featurePermissionedDomains] || !features[featureSingleAssetVault]) { // cannot set DomainID since PD is not enabled - mptAlice.set( - {.account = alice, - .domainID = uint256(42), - .err = temDISABLED}); + mptAlice.set({.account = alice, .domainID = uint256(42), .err = temDISABLED}); } else if (features[featureSingleAssetVault]) { // cannot set DomainID since Holder is set - mptAlice.set( - {.account = alice, - .holder = bob, - .domainID = uint256(42), - .err = temMALFORMED}); + mptAlice.set({.account = alice, .holder = bob, .domainID = uint256(42), .err = temMALFORMED}); } } // set both lock and unlock flags at the same time will fail - mptAlice.set( - {.account = alice, - .flags = tfMPTLock | tfMPTUnlock, - .err = temINVALID_FLAG}); + mptAlice.set({.account = alice, .flags = tfMPTLock | tfMPTUnlock, .err = temINVALID_FLAG}); // if the holder is the same as the acct that submitted the tx, // tx fails - mptAlice.set( - {.account = alice, - .holder = alice, - .flags = tfMPTLock, - .err = temMALFORMED}); + mptAlice.set({.account = alice, .holder = alice, .flags = tfMPTLock, .err = temMALFORMED}); } // Validate fields in MPTokenIssuanceSet (preclaim) @@ -650,32 +554,18 @@ class MPToken_test : public beast::unit_test::suite mptAlice.create({.ownerCount = 1}); // alice tries to lock a mptissuance that has disabled locking - mptAlice.set( - {.account = alice, - .flags = tfMPTLock, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .flags = tfMPTLock, .err = tecNO_PERMISSION}); // alice tries to unlock mptissuance that has disabled locking - mptAlice.set( - {.account = alice, - .flags = tfMPTUnlock, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .flags = tfMPTUnlock, .err = tecNO_PERMISSION}); // issuer tries to lock a bob's mptoken that has disabled // locking - mptAlice.set( - {.account = alice, - .holder = bob, - .flags = tfMPTLock, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTLock, .err = tecNO_PERMISSION}); // issuer tries to unlock a bob's mptoken that has disabled // locking - mptAlice.set( - {.account = alice, - .holder = bob, - .flags = tfMPTUnlock, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTUnlock, .err = tecNO_PERMISSION}); } // Validate fields in MPTokenIssuanceSet (preclaim) @@ -686,38 +576,28 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); // alice trying to set when the mptissuance doesn't exist yet - mptAlice.set( - {.id = makeMptID(env.seq(alice), alice), - .flags = tfMPTLock, - .err = tecOBJECT_NOT_FOUND}); + mptAlice.set({.id = makeMptID(env.seq(alice), alice), .flags = tfMPTLock, .err = tecOBJECT_NOT_FOUND}); // create a mptokenissuance with locking mptAlice.create({.ownerCount = 1, .flags = tfMPTCanLock}); // a non-issuer acct tries to set the mptissuance - mptAlice.set( - {.account = bob, .flags = tfMPTLock, .err = tecNO_PERMISSION}); + mptAlice.set({.account = bob, .flags = tfMPTLock, .err = tecNO_PERMISSION}); // trying to set a holder who doesn't have a mptoken - mptAlice.set( - {.holder = bob, - .flags = tfMPTLock, - .err = tecOBJECT_NOT_FOUND}); + mptAlice.set({.holder = bob, .flags = tfMPTLock, .err = tecOBJECT_NOT_FOUND}); // trying to set a holder who doesn't exist - mptAlice.set( - {.holder = cindy, .flags = tfMPTLock, .err = tecNO_DST}); + mptAlice.set({.holder = cindy, .flags = tfMPTLock, .err = tecNO_DST}); } - if (features[featureSingleAssetVault] && - features[featurePermissionedDomains]) + if (features[featureSingleAssetVault] && features[featurePermissionedDomains]) { // Add permissioned domain Account const credIssuer1{"credIssuer1"}; std::string const credType = "credential"; - pdomain::Credentials const credentials1{ - {.issuer = credIssuer1, .credType = credType}}; + pdomain::Credentials const credentials1{{.issuer = credIssuer1, .credType = credType}}; { Env env{*this, features}; @@ -726,11 +606,9 @@ class MPToken_test : public beast::unit_test::suite mptAlice.create({}); // Trying to set DomainID on a public MPTokenIssuance - mptAlice.set( - {.domainID = uint256(42), .err = tecNO_PERMISSION}); + mptAlice.set({.domainID = uint256(42), .err = tecNO_PERMISSION}); - mptAlice.set( - {.domainID = beast::zero, .err = tecNO_PERMISSION}); + mptAlice.set({.domainID = beast::zero, .err = tecNO_PERMISSION}); } { @@ -740,19 +618,12 @@ class MPToken_test : public beast::unit_test::suite mptAlice.create({.flags = tfMPTRequireAuth}); // Trying to set non-existing DomainID - mptAlice.set( - {.domainID = uint256(42), .err = tecOBJECT_NOT_FOUND}); + mptAlice.set({.domainID = uint256(42), .err = tecOBJECT_NOT_FOUND}); // Trying to lock but locking is disabled - mptAlice.set( - {.flags = tfMPTUnlock, - .domainID = uint256(42), - .err = tecNO_PERMISSION}); + mptAlice.set({.flags = tfMPTUnlock, .domainID = uint256(42), .err = tecNO_PERMISSION}); - mptAlice.set( - {.flags = tfMPTUnlock, - .domainID = beast::zero, - .err = tecNO_PERMISSION}); + mptAlice.set({.flags = tfMPTUnlock, .domainID = beast::zero, .err = tecNO_PERMISSION}); } } } @@ -773,8 +644,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); // create a mptokenissuance with locking - mptAlice.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanLock}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanLock}); mptAlice.authorize({.account = bob, .holderCount = 1}); @@ -794,8 +664,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTLock}); // alice unlocks bob's mptoken - mptAlice.set( - {.account = alice, .holder = bob, .flags = tfMPTUnlock}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTUnlock}); // locks up bob's mptoken again mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTLock}); @@ -804,33 +673,24 @@ class MPToken_test : public beast::unit_test::suite // Delete bobs' mptoken even though it is locked mptAlice.authorize({.account = bob, .flags = tfMPTUnauthorize}); - mptAlice.set( - {.account = alice, - .holder = bob, - .flags = tfMPTUnlock, - .err = tecOBJECT_NOT_FOUND}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTUnlock, .err = tecOBJECT_NOT_FOUND}); return; } // Cannot delete locked MPToken - mptAlice.authorize( - {.account = bob, - .flags = tfMPTUnauthorize, - .err = tecNO_PERMISSION}); + mptAlice.authorize({.account = bob, .flags = tfMPTUnauthorize, .err = tecNO_PERMISSION}); // alice unlocks mptissuance mptAlice.set({.account = alice, .flags = tfMPTUnlock}); // alice unlocks bob's mptoken - mptAlice.set( - {.account = alice, .holder = bob, .flags = tfMPTUnlock}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTUnlock}); // alice unlocks mptissuance and bob's mptoken again despite that // they are already unlocked. Make sure this will not change the // flags - mptAlice.set( - {.account = alice, .holder = bob, .flags = tfMPTUnlock}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTUnlock}); mptAlice.set({.account = alice, .flags = tfMPTUnlock}); } @@ -846,8 +706,7 @@ class MPToken_test : public beast::unit_test::suite Account const credIssuer1{"credIssuer1"}; env.fund(XRP(1000), credIssuer1); - pdomain::Credentials const credentials1{ - {.issuer = credIssuer1, .credType = credType}}; + pdomain::Credentials const credentials1{{.issuer = credIssuer1, .credType = credType}}; env(pdomain::setTx(credIssuer1, credentials1)); return [&]() { @@ -860,8 +719,7 @@ class MPToken_test : public beast::unit_test::suite Account const credIssuer2{"credIssuer2"}; env.fund(XRP(1000), credIssuer2); - pdomain::Credentials const credentials2{ - {.issuer = credIssuer2, .credType = credType}}; + pdomain::Credentials const credentials2{{.issuer = credIssuer2, .credType = credType}}; env(pdomain::setTx(credIssuer2, credentials2)); return [&]() { @@ -873,8 +731,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); // create a mptokenissuance with auth. - mptAlice.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTRequireAuth}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTRequireAuth}); BEAST_EXPECT(mptAlice.checkDomainID(std::nullopt)); // reset "domain not set" to "domain not set", i.e. no change @@ -951,9 +808,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.authorize({.account = bob}); for (auto flags : {tfNoRippleDirect, tfLimitQuality}) - env(pay(alice, bob, MPT(10)), - txflags(flags), - ter(temINVALID_FLAG)); + env(pay(alice, bob, MPT(10)), txflags(flags), ter(temINVALID_FLAG)); } // Invalid combination of send, sendMax, deliverMin, paths @@ -971,32 +826,17 @@ class MPToken_test : public beast::unit_test::suite // sendMax and DeliverMin are valid XRP amount, // but is invalid combination with MPT amount auto const MPT = mptAlice["MPT"]; - env(pay(alice, carol, MPT(100)), - sendmax(XRP(100)), - ter(temMALFORMED)); - env(pay(alice, carol, MPT(100)), - deliver_min(XRP(100)), - ter(temBAD_AMOUNT)); + env(pay(alice, carol, MPT(100)), sendmax(XRP(100)), ter(temMALFORMED)); + env(pay(alice, carol, MPT(100)), deliver_min(XRP(100)), ter(temBAD_AMOUNT)); // sendMax MPT is invalid with IOU or XRP auto const USD = alice["USD"]; - env(pay(alice, carol, USD(100)), - sendmax(MPT(100)), - ter(temMALFORMED)); - env(pay(alice, carol, XRP(100)), - sendmax(MPT(100)), - ter(temMALFORMED)); - env(pay(alice, carol, USD(100)), - deliver_min(MPT(100)), - ter(temBAD_AMOUNT)); - env(pay(alice, carol, XRP(100)), - deliver_min(MPT(100)), - ter(temBAD_AMOUNT)); + env(pay(alice, carol, USD(100)), sendmax(MPT(100)), ter(temMALFORMED)); + env(pay(alice, carol, XRP(100)), sendmax(MPT(100)), ter(temMALFORMED)); + env(pay(alice, carol, USD(100)), deliver_min(MPT(100)), ter(temBAD_AMOUNT)); + env(pay(alice, carol, XRP(100)), deliver_min(MPT(100)), ter(temBAD_AMOUNT)); // sendmax and amount are different MPT issue - test::jtx::MPT const MPT1( - "MPT", makeMptID(env.seq(alice) + 10, alice)); - env(pay(alice, carol, MPT1(100)), - sendmax(MPT(100)), - ter(temMALFORMED)); + test::jtx::MPT const MPT1("MPT", makeMptID(env.seq(alice) + 10, alice)); + env(pay(alice, carol, MPT1(100)), sendmax(MPT(100)), ter(temMALFORMED)); // paths is invalid env(pay(alice, carol, MPT(100)), path(~USD), ter(temMALFORMED)); } @@ -1021,9 +861,7 @@ class MPToken_test : public beast::unit_test::suite payment[jss::build_path] = true; auto jrr = env.rpc("json", "submit", to_string(payment)); BEAST_EXPECT(jrr[jss::result][jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::result][jss::error_message] == - "Field 'build_path' not allowed in this context."); + BEAST_EXPECT(jrr[jss::result][jss::error_message] == "Field 'build_path' not allowed in this context."); } // Can't pay negative amount @@ -1087,10 +925,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTRequireAuth | tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTRequireAuth | tfMPTCanTransfer}); mptAlice.authorize({.account = bob}); @@ -1104,10 +939,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTRequireAuth | tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTRequireAuth | tfMPTCanTransfer}); // bob creates an empty MPToken mptAlice.authorize({.account = bob}); @@ -1119,16 +951,14 @@ class MPToken_test : public beast::unit_test::suite mptAlice.pay(alice, bob, 100); // alice UNAUTHORIZES bob - mptAlice.authorize( - {.account = alice, .holder = bob, .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = alice, .holder = bob, .flags = tfMPTUnauthorize}); // bob fails to send back to alice because he is no longer // authorize to move his funds! mptAlice.pay(bob, alice, 100, tecNO_AUTH); } - if (features[featureSingleAssetVault] && - features[featurePermissionedDomains]) + if (features[featureSingleAssetVault] && features[featurePermissionedDomains]) { // If RequireAuth is enabled and domain is a match, payment succeeds { @@ -1138,8 +968,7 @@ class MPToken_test : public beast::unit_test::suite env.fund(XRP(1000), credIssuer1, bob); auto const domainId1 = [&]() { - pdomain::Credentials const credentials1{ - {.issuer = credIssuer1, .credType = credType}}; + pdomain::Credentials const credentials1{{.issuer = credIssuer1, .credType = credType}}; env(pdomain::setTx(credIssuer1, credentials1)); return [&]() { @@ -1180,8 +1009,7 @@ class MPToken_test : public beast::unit_test::suite env.fund(XRP(1000), credIssuer1, bob); auto const domainId1 = [&]() { - pdomain::Credentials const credentials1{ - {.issuer = credIssuer1, .credType = credType}}; + pdomain::Credentials const credentials1{{.issuer = credIssuer1, .credType = credType}}; env(pdomain::setTx(credIssuer1, credentials1)); return [&]() { @@ -1214,10 +1042,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.pay(alice, bob, 100); // alice UNAUTHORIZES bob - mptAlice.authorize( - {.account = alice, - .holder = bob, - .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = alice, .holder = bob, .flags = tfMPTUnauthorize}); // bob is still authorized, via domain mptAlice.pay(bob, alice, 10); @@ -1240,8 +1065,7 @@ class MPToken_test : public beast::unit_test::suite env.fund(XRP(1000), credIssuer1, credIssuer2, bob, carol); auto const domainId1 = [&]() { - pdomain::Credentials const credentials{ - {.issuer = credIssuer1, .credType = credType}}; + pdomain::Credentials const credentials{{.issuer = credIssuer1, .credType = credType}}; env(pdomain::setTx(credIssuer1, credentials)); return [&]() { @@ -1252,8 +1076,7 @@ class MPToken_test : public beast::unit_test::suite auto const domainId2 = [&]() { pdomain::Credentials const credentials{ - {.issuer = credIssuer1, .credType = credType}, - {.issuer = credIssuer2, .credType = credType}}; + {.issuer = credIssuer1, .credType = credType}, {.issuer = credIssuer2, .credType = credType}}; env(pdomain::setTx(credIssuer2, credentials)); return [&]() { @@ -1312,8 +1135,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); // bob loses his authorization and can no longer send MPT - env(credentials::deleteCred( - credIssuer1, bob, credIssuer1, credType)); + env(credentials::deleteCred(credIssuer1, bob, credIssuer1, credType)); env.close(); mptAlice.pay(bob, carol, 10, tecNO_AUTH); @@ -1356,8 +1178,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); - mptAlice.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); // issuer to holder mptAlice.pay(alice, bob, 100, tecNO_AUTH); @@ -1395,8 +1216,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); - mptAlice.create( - {.ownerCount = 1, .flags = tfMPTCanLock | tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .flags = tfMPTCanLock | tfMPTCanTransfer}); mptAlice.authorize({.account = bob}); mptAlice.authorize({.account = carol}); @@ -1434,11 +1254,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); // Transfer fee is 10% - mptAlice.create( - {.transferFee = 10'000, - .ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanTransfer}); + mptAlice.create({.transferFee = 10'000, .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); // Holders create MPToken mptAlice.authorize({.account = bob}); @@ -1461,9 +1277,7 @@ class MPToken_test : public beast::unit_test::suite auto const MPT = mptAlice["MPT"]; // SendMax doesn't cover the fee - env(pay(bob, carol, MPT(100)), - sendmax(MPT(109)), - ter(tecPATH_PARTIAL)); + env(pay(bob, carol, MPT(100)), sendmax(MPT(109)), ter(tecPATH_PARTIAL)); // Payment succeeds if sufficient SendMax is included. // 100 to carol, 10 to issuer @@ -1474,9 +1288,7 @@ class MPToken_test : public beast::unit_test::suite BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 200)); // Payment succeeds if partial payment even if // SendMax is less than deliver amount - env(pay(bob, carol, MPT(100)), - sendmax(MPT(90)), - txflags(tfPartialPayment)); + env(pay(bob, carol, MPT(100)), sendmax(MPT(90)), txflags(tfPartialPayment)); // 82 to carol, 8 to issuer (90 / 1.1 ~ 81.81 (rounded to nearest) = // 82) BEAST_EXPECT(mptAlice.checkMPTokenAmount(bob, 690)); @@ -1489,8 +1301,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); - mptAlice.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); // Holders create MPToken mptAlice.authorize({.account = bob}); @@ -1499,20 +1310,14 @@ class MPToken_test : public beast::unit_test::suite auto const MPT = mptAlice["MPT"]; // SendMax is less than the amount - env(pay(bob, carol, MPT(100)), - sendmax(MPT(99)), - ter(tecPATH_PARTIAL)); - env(pay(bob, alice, MPT(100)), - sendmax(MPT(99)), - ter(tecPATH_PARTIAL)); + env(pay(bob, carol, MPT(100)), sendmax(MPT(99)), ter(tecPATH_PARTIAL)); + env(pay(bob, alice, MPT(100)), sendmax(MPT(99)), ter(tecPATH_PARTIAL)); // Payment succeeds if sufficient SendMax is included. env(pay(bob, carol, MPT(100)), sendmax(MPT(100))); BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 100)); // Payment succeeds if partial payment - env(pay(bob, carol, MPT(100)), - sendmax(MPT(99)), - txflags(tfPartialPayment)); + env(pay(bob, carol, MPT(100)), sendmax(MPT(99)), txflags(tfPartialPayment)); BEAST_EXPECT(mptAlice.checkMPTokenAmount(carol, 199)); } @@ -1522,8 +1327,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); - mptAlice.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); // Holders create MPToken mptAlice.authorize({.account = bob}); @@ -1539,10 +1343,7 @@ class MPToken_test : public beast::unit_test::suite txflags(tfPartialPayment), ter(tecPATH_PARTIAL)); // Payment succeeds if deliver amount >= deliverMin - env(pay(bob, alice, MPT(100)), - sendmax(MPT(99)), - deliver_min(MPT(99)), - txflags(tfPartialPayment)); + env(pay(bob, alice, MPT(100)), sendmax(MPT(99)), deliver_min(MPT(99)), txflags(tfPartialPayment)); } // Issuer fails trying to send more than the maximum amount allowed @@ -1551,11 +1352,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.maxAmt = 100, - .ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanTransfer}); + mptAlice.create({.maxAmt = 100, .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); mptAlice.authorize({.account = bob}); @@ -1593,8 +1390,7 @@ class MPToken_test : public beast::unit_test::suite Json::Value jv; jv[jss::secret] = alice.name(); jv[jss::tx_json] = pay(alice, bob, mpt); - jv[jss::tx_json][jss::Amount][jss::value] = - std::to_string(maxMPTokenAmount + 1); + jv[jss::tx_json][jss::Amount][jss::value] = std::to_string(maxMPTokenAmount + 1); auto const jrr = env.rpc("json", "submit", to_string(jv)); BEAST_EXPECT(jrr[jss::result][jss::error] == "invalidParams"); } @@ -1607,11 +1403,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); mptAlice.create( - {.maxAmt = 10'000, - .transferFee = 100, - .ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanTransfer}); + {.maxAmt = 10'000, .transferFee = 100, .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); auto const MPT = mptAlice["MPT"]; mptAlice.authorize({.account = bob}); @@ -1621,33 +1413,22 @@ class MPToken_test : public beast::unit_test::suite mptAlice.pay(alice, bob, 10'000); // payment between the holders - env(pay(bob, carol, MPT(10'000)), - sendmax(MPT(10'000)), - txflags(tfPartialPayment)); + env(pay(bob, carol, MPT(10'000)), sendmax(MPT(10'000)), txflags(tfPartialPayment)); // Verify the metadata - auto const meta = env.meta()->getJson( - JsonOptions::none)[sfAffectedNodes.fieldName]; + auto const meta = env.meta()->getJson(JsonOptions::none)[sfAffectedNodes.fieldName]; // Issuer got 10 in the transfer fees BEAST_EXPECT( - meta[0u][sfModifiedNode.fieldName][sfFinalFields.fieldName] - [sfOutstandingAmount.fieldName] == "9990"); + meta[0u][sfModifiedNode.fieldName][sfFinalFields.fieldName][sfOutstandingAmount.fieldName] == "9990"); // Destination account got 9'990 - BEAST_EXPECT( - meta[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName] - [sfMPTAmount.fieldName] == "9990"); + BEAST_EXPECT(meta[1u][sfModifiedNode.fieldName][sfFinalFields.fieldName][sfMPTAmount.fieldName] == "9990"); // Source account spent 10'000 BEAST_EXPECT( - meta[2u][sfModifiedNode.fieldName][sfPreviousFields.fieldName] - [sfMPTAmount.fieldName] == "10000"); - BEAST_EXPECT( - !meta[2u][sfModifiedNode.fieldName][sfFinalFields.fieldName] - .isMember(sfMPTAmount.fieldName)); + meta[2u][sfModifiedNode.fieldName][sfPreviousFields.fieldName][sfMPTAmount.fieldName] == "10000"); + BEAST_EXPECT(!meta[2u][sfModifiedNode.fieldName][sfFinalFields.fieldName].isMember(sfMPTAmount.fieldName)); // payment between the holders fails without // partial payment - env(pay(bob, carol, MPT(10'000)), - sendmax(MPT(10'000)), - ter(tecPATH_PARTIAL)); + env(pay(bob, carol, MPT(10'000)), sendmax(MPT(10'000)), ter(tecPATH_PARTIAL)); } // Pay maximum allowed amount @@ -1656,11 +1437,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); - mptAlice.create( - {.maxAmt = maxMPTokenAmount, - .ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanTransfer}); + mptAlice.create({.maxAmt = maxMPTokenAmount, .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); auto const MPT = mptAlice["MPT"]; mptAlice.authorize({.account = bob}); @@ -1668,13 +1445,11 @@ class MPToken_test : public beast::unit_test::suite // issuer sends holder the max amount allowed mptAlice.pay(alice, bob, maxMPTokenAmount); - BEAST_EXPECT( - mptAlice.checkMPTokenOutstandingAmount(maxMPTokenAmount)); + BEAST_EXPECT(mptAlice.checkMPTokenOutstandingAmount(maxMPTokenAmount)); // payment between the holders mptAlice.pay(bob, carol, maxMPTokenAmount); - BEAST_EXPECT( - mptAlice.checkMPTokenOutstandingAmount(maxMPTokenAmount)); + BEAST_EXPECT(mptAlice.checkMPTokenOutstandingAmount(maxMPTokenAmount)); // holder pays back to the issuer mptAlice.pay(carol, alice, maxMPTokenAmount); BEAST_EXPECT(mptAlice.checkMPTokenOutstandingAmount(0)); @@ -1735,8 +1510,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); - mptAlice.create( - {.maxAmt = 100, .ownerCount = 1, .flags = tfMPTCanTransfer}); + mptAlice.create({.maxAmt = 100, .ownerCount = 1, .flags = tfMPTCanTransfer}); mptAlice.authorize({.account = bob}); mptAlice.authorize({.account = carol}); @@ -1753,8 +1527,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); - mptAlice.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); mptAlice.authorize({.account = bob}); mptAlice.authorize({.account = carol}); @@ -1792,10 +1565,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTRequireAuth | tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTRequireAuth | tfMPTCanTransfer}); env(pay(diana, bob, XRP(500))); env.close(); @@ -1826,8 +1596,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); env(credentials::accept(alice, dpIssuer, credType)); env.close(); - auto const jv = - credentials::ledgerEntry(env, alice, dpIssuer, credType); + auto const jv = credentials::ledgerEntry(env, alice, dpIssuer, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); // alice sends 100 MPT to bob with credentials which aren't required @@ -1871,10 +1640,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTRequireAuth | tfMPTCanTransfer}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTRequireAuth | tfMPTCanTransfer}); env(pay(diana, bob, XRP(500))); env.close(); @@ -1941,12 +1707,10 @@ class MPToken_test : public beast::unit_test::suite // Transaction has amount/issue fields. // Exclude pseudo-transaction SetFee. Don't consider // the Fee field since it's included in every transaction. - if (e.supportMPT() == soeMPTNotSupported && - e.sField().getName() != jss::Fee && + if (e.supportMPT() == soeMPTNotSupported && e.sField().getName() != jss::Fee && format.getName() != jss::SetFee) { - txWithAmounts.insert( - format.getName() + e.sField().fieldName); + txWithAmounts.insert(format.getName() + e.sField().fieldName); break; } } @@ -1963,18 +1727,15 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, feature}; env.fund(XRP(1'000), alice); env.fund(XRP(1'000), carol); - auto test = [&](Json::Value const& jv, - std::string const& mptField) { - txWithAmounts.erase( - jv[jss::TransactionType].asString() + mptField); + auto test = [&](Json::Value const& jv, std::string const& mptField) { + txWithAmounts.erase(jv[jss::TransactionType].asString() + mptField); // tx is signed auto jtx = env.jt(jv); Serializer s; jtx.stx->add(s); auto jrr = env.rpc("submit", strHex(s.slice())); - BEAST_EXPECT( - jrr[jss::result][jss::error] == "invalidTransaction"); + BEAST_EXPECT(jrr[jss::result][jss::error] == "invalidTransaction"); // tx is unsigned Json::Value jv1; @@ -1986,17 +1747,12 @@ class MPToken_test : public beast::unit_test::suite jrr = env.rpc("json", "sign", to_string(jv1)); BEAST_EXPECT(jrr[jss::result][jss::error] == "invalidParams"); }; - auto toSFieldRef = [](SField const& field) { - return std::ref(field); - }; - auto setMPTFields = [&](SField const& field, - Json::Value& jv, - bool withAmount = true) { + auto toSFieldRef = [](SField const& field) { return std::ref(field); }; + auto setMPTFields = [&](SField const& field, Json::Value& jv, bool withAmount = true) { jv[jss::Asset] = to_json(xrpIssue()); jv[jss::Asset2] = to_json(USD.issue()); if (withAmount) - jv[field.fieldName] = - USD(10).value().getJson(JsonOptions::none); + jv[field.fieldName] = USD(10).value().getJson(JsonOptions::none); if (field == sfAsset) jv[jss::Asset] = to_json(mpt.get()); else if (field == sfAsset2) @@ -2013,12 +1769,10 @@ class MPToken_test : public beast::unit_test::suite Json::Value jv; jv[jss::TransactionType] = jss::AMMCreate; jv[jss::Account] = alice.human(); - jv[jss::Amount] = (field.fieldName == sfAmount.fieldName) - ? mpt.getJson(JsonOptions::none) - : "100000000"; - jv[jss::Amount2] = (field.fieldName == sfAmount2.fieldName) - ? mpt.getJson(JsonOptions::none) - : "100000000"; + jv[jss::Amount] = + (field.fieldName == sfAmount.fieldName) ? mpt.getJson(JsonOptions::none) : "100000000"; + jv[jss::Amount2] = + (field.fieldName == sfAmount2.fieldName) ? mpt.getJson(JsonOptions::none) : "100000000"; jv[jss::TradingFee] = 0; test(jv, field.fieldName); }; @@ -2067,10 +1821,7 @@ class MPToken_test : public beast::unit_test::suite test(jv, field.fieldName); }; for (SField const& field : - {toSFieldRef(sfBidMin), - toSFieldRef(sfBidMax), - toSFieldRef(sfAsset), - toSFieldRef(sfAsset2)}) + {toSFieldRef(sfBidMin), toSFieldRef(sfBidMax), toSFieldRef(sfAsset), toSFieldRef(sfAsset2)}) ammBid(field); // AMMClawback auto ammClawback = [&](SField const& field) { @@ -2081,10 +1832,7 @@ class MPToken_test : public beast::unit_test::suite setMPTFields(field, jv); test(jv, field.fieldName); }; - for (SField const& field : - {toSFieldRef(sfAmount), - toSFieldRef(sfAsset), - toSFieldRef(sfAsset2)}) + for (SField const& field : {toSFieldRef(sfAmount), toSFieldRef(sfAsset), toSFieldRef(sfAsset2)}) ammClawback(field); // AMMDelete auto ammDelete = [&](SField const& field) { @@ -2177,8 +1925,7 @@ class MPToken_test : public beast::unit_test::suite Json::Value jv; jv[jss::TransactionType] = jss::NFTokenAcceptOffer; jv[jss::Account] = alice.human(); - jv[sfNFTokenBrokerFee.fieldName] = - mpt.getJson(JsonOptions::none); + jv[sfNFTokenBrokerFee.fieldName] = mpt.getJson(JsonOptions::none); test(jv, sfNFTokenBrokerFee.fieldName); } // NFTokenMint @@ -2213,39 +1960,19 @@ class MPToken_test : public beast::unit_test::suite } // XChainCreateClaimID { - Json::Value const jv = - xchain_create_claim_id(alice, jvb, mpt, alice); + Json::Value const jv = xchain_create_claim_id(alice, jvb, mpt, alice); test(jv, sfSignatureReward.fieldName); } // XChainAddClaimAttestation { - Json::Value const jv = claim_attestation( - alice, - jvb, - alice, - mpt, - alice, - true, - 1, - alice, - signer(alice)); + Json::Value const jv = claim_attestation(alice, jvb, alice, mpt, alice, true, 1, alice, signer(alice)); test(jv, jss::Amount.c_str()); } // XChainAddAccountCreateAttestation { - Json::Value jv = create_account_attestation( - alice, - jvb, - alice, - mpt, - XRP(10), - alice, - false, - 1, - alice, - signer(alice)); - for (auto const& field : - {sfAmount.fieldName, sfSignatureReward.fieldName}) + Json::Value jv = + create_account_attestation(alice, jvb, alice, mpt, XRP(10), alice, false, 1, alice, signer(alice)); + for (auto const& field : {sfAmount.fieldName, sfSignatureReward.fieldName}) { jv[field] = mpt.getJson(JsonOptions::none); test(jv, field); @@ -2253,10 +1980,8 @@ class MPToken_test : public beast::unit_test::suite } // XChainAccountCreateCommit { - Json::Value jv = sidechain_xchain_account_create( - alice, jvb, alice, mpt, XRP(10)); - for (auto const& field : - {sfAmount.fieldName, sfSignatureReward.fieldName}) + Json::Value jv = sidechain_xchain_account_create(alice, jvb, alice, mpt, XRP(10)); + for (auto const& field : {sfAmount.fieldName, sfSignatureReward.fieldName}) { jv[field] = mpt.getJson(JsonOptions::none); test(jv, field); @@ -2271,28 +1996,16 @@ class MPToken_test : public beast::unit_test::suite jv[jss::TransactionType] = tt; jv[jss::Account] = alice.human(); jv[sfXChainBridge.fieldName] = jvb; - jv[sfSignatureReward.fieldName] = - rewardAmount.getJson(JsonOptions::none); - jv[sfMinAccountCreateAmount.fieldName] = - minAccountAmount.getJson(JsonOptions::none); + jv[sfSignatureReward.fieldName] = rewardAmount.getJson(JsonOptions::none); + jv[sfMinAccountCreateAmount.fieldName] = minAccountAmount.getJson(JsonOptions::none); test(jv, field); }; auto reward = STAmount{sfSignatureReward, mpt}; auto minAmount = STAmount{sfMinAccountCreateAmount, USD(10)}; - for (SField const& field : - {std::ref(sfSignatureReward), - std::ref(sfMinAccountCreateAmount)}) + for (SField const& field : {std::ref(sfSignatureReward), std::ref(sfMinAccountCreateAmount)}) { - bridgeTx( - jss::XChainCreateBridge, - reward, - minAmount, - field.fieldName); - bridgeTx( - jss::XChainModifyBridge, - reward, - minAmount, - field.fieldName); + bridgeTx(jss::XChainCreateBridge, reward, minAmount, field.fieldName); + bridgeTx(jss::XChainModifyBridge, reward, minAmount, field.fieldName); reward = STAmount{sfSignatureReward, USD(10)}; minAmount = STAmount{sfMinAccountCreateAmount, mpt}; } @@ -2317,8 +2030,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.create(); - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; BEAST_EXPECTS( txHash == "E11F0E0CA14219922B7881F060B9CEE67CFBC87E4049A441ED2AE348FF8FAC" @@ -2329,8 +2041,7 @@ class MPToken_test : public beast::unit_test::suite // Expect mpt_issuance_id field BEAST_EXPECT(meta.isMember(jss::mpt_issuance_id)); BEAST_EXPECT(id == to_string(mptAlice.issuanceID())); - BEAST_EXPECTS( - id == "00000004AE123A8556F3CF91154711376AFB0F894F832B3D", id); + BEAST_EXPECTS(id == "00000004AE123A8556F3CF91154711376AFB0F894F832B3D", id); } void @@ -2349,8 +2060,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); auto const USD = alice["USD"]; - auto const mpt = xrpl::test::jtx::MPT( - alice.name(), makeMptID(env.seq(alice), alice)); + auto const mpt = xrpl::test::jtx::MPT(alice.name(), makeMptID(env.seq(alice), alice)); env(claw(alice, bob["USD"](5), bob), ter(temMALFORMED)); env.close(); @@ -2372,8 +2082,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); auto const USD = alice["USD"]; - auto const mpt = xrpl::test::jtx::MPT( - alice.name(), makeMptID(env.seq(alice), alice)); + auto const mpt = xrpl::test::jtx::MPT(alice.name(), makeMptID(env.seq(alice), alice)); // clawing back IOU from a MPT holder fails env(claw(alice, bob["USD"](5), bob), ter(temMALFORMED)); @@ -2431,16 +2140,14 @@ class MPToken_test : public beast::unit_test::suite env.close(); MPTTester mptAlice(env, alice, {.holders = {bob}}); - auto const fakeMpt = xrpl::test::jtx::MPT( - alice.name(), makeMptID(env.seq(alice), alice)); + auto const fakeMpt = xrpl::test::jtx::MPT(alice.name(), makeMptID(env.seq(alice), alice)); // issuer tries to clawback MPT where issuance doesn't exist env(claw(alice, fakeMpt(5), bob), ter(tecOBJECT_NOT_FOUND)); env.close(); // alice creates issuance - mptAlice.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanClawback}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanClawback}); // alice tries to clawback from someone who doesn't have MPToken mptAlice.claw(alice, bob, 1, tecOBJECT_NOT_FOUND); @@ -2470,8 +2177,7 @@ class MPToken_test : public beast::unit_test::suite env.fund(XRP(1000), alice, bob); env.close(); - auto const mpt = xrpl::test::jtx::MPT( - alice.name(), makeMptID(env.seq(alice), alice)); + auto const mpt = xrpl::test::jtx::MPT(alice.name(), makeMptID(env.seq(alice), alice)); Json::Value jv = claw(alice, mpt(1), bob); jv[jss::Amount][jss::value] = std::to_string(maxMPTokenAmount + 1); @@ -2497,8 +2203,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); // alice creates issuance - mptAlice.create( - {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanClawback}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanClawback}); // bob creates a MPToken mptAlice.authorize({.account = bob}); @@ -2523,10 +2228,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); // alice creates issuance - mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanLock | tfMPTCanClawback}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanLock | tfMPTCanClawback}); // bob creates a MPToken mptAlice.authorize({.account = bob}); @@ -2548,10 +2250,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); // alice creates issuance - mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanLock | tfMPTCanClawback}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanLock | tfMPTCanClawback}); // bob creates a MPToken mptAlice.authorize({.account = bob}); @@ -2573,10 +2272,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); // alice creates issuance - mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanClawback | tfMPTRequireAuth}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanClawback | tfMPTRequireAuth}); // bob creates a MPToken mptAlice.authorize({.account = bob}); @@ -2588,8 +2284,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.pay(alice, bob, 100); // alice unauthorizes bob - mptAlice.authorize( - {.account = alice, .holder = bob, .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = alice, .holder = bob, .flags = tfMPTUnauthorize}); mptAlice.claw(alice, bob, 100); } @@ -2703,16 +2398,14 @@ class MPToken_test : public beast::unit_test::suite testcase("Test MPTIssue from/to Json"); MPTIssue const issue1{asset1.get()}; Json::Value const jv = to_json(issue1); - BEAST_EXPECT( - jv[jss::mpt_issuance_id] == to_string(asset1.get())); + BEAST_EXPECT(jv[jss::mpt_issuance_id] == to_string(asset1.get())); BEAST_EXPECT(issue1 == mptIssueFromJson(jv)); } { testcase("Test Asset from/to Json"); Json::Value const jv = to_json(asset1); - BEAST_EXPECT( - jv[jss::mpt_issuance_id] == to_string(asset1.get())); + BEAST_EXPECT(jv[jss::mpt_issuance_id] == to_string(asset1.get())); BEAST_EXPECT( to_string(jv) == "{\"mpt_issuance_id\":" @@ -2733,10 +2426,8 @@ class MPToken_test : public beast::unit_test::suite { Env env{*this, features - featureDynamicMPT}; MPTTester mptAlice(env, alice); - mptAlice.create( - {.ownerCount = 0, .mutableFlags = 2, .err = temDISABLED}); - mptAlice.create( - {.ownerCount = 0, .mutableFlags = 0, .err = temDISABLED}); + mptAlice.create({.ownerCount = 0, .mutableFlags = 2, .err = temDISABLED}); + mptAlice.create({.ownerCount = 0, .mutableFlags = 0, .err = temDISABLED}); } // MutableFlags contains invalid values @@ -2745,18 +2436,12 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice); // Value 1 is reserved for MPT lock. - mptAlice.create( - {.ownerCount = 0, .mutableFlags = 1, .err = temINVALID_FLAG}); - mptAlice.create( - {.ownerCount = 0, .mutableFlags = 17, .err = temINVALID_FLAG}); - mptAlice.create( - {.ownerCount = 0, - .mutableFlags = 65535, - .err = temINVALID_FLAG}); + mptAlice.create({.ownerCount = 0, .mutableFlags = 1, .err = temINVALID_FLAG}); + mptAlice.create({.ownerCount = 0, .mutableFlags = 17, .err = temINVALID_FLAG}); + mptAlice.create({.ownerCount = 0, .mutableFlags = 65535, .err = temINVALID_FLAG}); // MutableFlags can not be 0 - mptAlice.create( - {.ownerCount = 0, .mutableFlags = 0, .err = temINVALID_FLAG}); + mptAlice.create({.ownerCount = 0, .mutableFlags = 0, .err = temINVALID_FLAG}); } } @@ -2777,40 +2462,16 @@ class MPToken_test : public beast::unit_test::suite auto const mptID = makeMptID(env.seq(alice), alice); // MutableFlags is not allowed when DynamicMPT is not enabled - mptAlice.set( - {.account = alice, - .id = mptID, - .mutableFlags = 2, - .err = temDISABLED}); - mptAlice.set( - {.account = alice, - .id = mptID, - .mutableFlags = 0, - .err = temDISABLED}); + mptAlice.set({.account = alice, .id = mptID, .mutableFlags = 2, .err = temDISABLED}); + mptAlice.set({.account = alice, .id = mptID, .mutableFlags = 0, .err = temDISABLED}); // MPTokenMetadata is not allowed when DynamicMPT is not enabled - mptAlice.set( - {.account = alice, - .id = mptID, - .metadata = "test", - .err = temDISABLED}); - mptAlice.set( - {.account = alice, - .id = mptID, - .metadata = "", - .err = temDISABLED}); + mptAlice.set({.account = alice, .id = mptID, .metadata = "test", .err = temDISABLED}); + mptAlice.set({.account = alice, .id = mptID, .metadata = "", .err = temDISABLED}); // TransferFee is not allowed when DynamicMPT is not enabled - mptAlice.set( - {.account = alice, - .id = mptID, - .transferFee = 100, - .err = temDISABLED}); - mptAlice.set( - {.account = alice, - .id = mptID, - .transferFee = 0, - .err = temDISABLED}); + mptAlice.set({.account = alice, .id = mptID, .transferFee = 100, .err = temDISABLED}); + mptAlice.set({.account = alice, .id = mptID, .transferFee = 0, .err = temDISABLED}); } // Can not provide holder when MutableFlags, MPTokenMetadata or @@ -2821,28 +2482,13 @@ class MPToken_test : public beast::unit_test::suite auto const mptID = makeMptID(env.seq(alice), alice); // Holder is not allowed when MutableFlags is present - mptAlice.set( - {.account = alice, - .holder = bob, - .id = mptID, - .mutableFlags = 2, - .err = temMALFORMED}); + mptAlice.set({.account = alice, .holder = bob, .id = mptID, .mutableFlags = 2, .err = temMALFORMED}); // Holder is not allowed when MPTokenMetadata is present - mptAlice.set( - {.account = alice, - .holder = bob, - .id = mptID, - .metadata = "test", - .err = temMALFORMED}); + mptAlice.set({.account = alice, .holder = bob, .id = mptID, .metadata = "test", .err = temMALFORMED}); // Holder is not allowed when TransferFee is present - mptAlice.set( - {.account = alice, - .holder = bob, - .id = mptID, - .transferFee = 100, - .err = temMALFORMED}); + mptAlice.set({.account = alice, .holder = bob, .id = mptID, .transferFee = 100, .err = temMALFORMED}); } // Can not set Flags when MutableFlags, MPTokenMetadata or @@ -2852,29 +2498,16 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); mptAlice.create( {.ownerCount = 1, - .mutableFlags = tmfMPTCanMutateMetadata | - tmfMPTCanMutateCanLock | tmfMPTCanMutateTransferFee}); + .mutableFlags = tmfMPTCanMutateMetadata | tmfMPTCanMutateCanLock | tmfMPTCanMutateTransferFee}); // Setting flags is not allowed when MutableFlags is present - mptAlice.set( - {.account = alice, - .flags = tfMPTCanLock, - .mutableFlags = 2, - .err = temMALFORMED}); + mptAlice.set({.account = alice, .flags = tfMPTCanLock, .mutableFlags = 2, .err = temMALFORMED}); // Setting flags is not allowed when MPTokenMetadata is present - mptAlice.set( - {.account = alice, - .flags = tfMPTCanLock, - .metadata = "test", - .err = temMALFORMED}); + mptAlice.set({.account = alice, .flags = tfMPTCanLock, .metadata = "test", .err = temMALFORMED}); // setting flags is not allowed when TransferFee is present - mptAlice.set( - {.account = alice, - .flags = tfMPTCanLock, - .transferFee = 100, - .err = temMALFORMED}); + mptAlice.set({.account = alice, .flags = tfMPTCanLock, .transferFee = 100, .err = temMALFORMED}); } // Flags being 0 or tfFullyCanonicalSig is fine @@ -2886,19 +2519,10 @@ class MPToken_test : public beast::unit_test::suite {.transferFee = 10, .ownerCount = 1, .flags = tfMPTCanTransfer, - .mutableFlags = - tmfMPTCanMutateTransferFee | tmfMPTCanMutateMetadata}); + .mutableFlags = tmfMPTCanMutateTransferFee | tmfMPTCanMutateMetadata}); - mptAlice.set( - {.account = alice, - .flags = 0, - .transferFee = 100, - .metadata = "test"}); - mptAlice.set( - {.account = alice, - .flags = tfFullyCanonicalSig, - .transferFee = 200, - .metadata = "test2"}); + mptAlice.set({.account = alice, .flags = 0, .transferFee = 100, .metadata = "test"}); + mptAlice.set({.account = alice, .flags = tfFullyCanonicalSig, .transferFee = 200, .metadata = "test2"}); } // Invalid MutableFlags @@ -2909,11 +2533,7 @@ class MPToken_test : public beast::unit_test::suite for (auto const flags : {10000, 0, 5000}) { - mptAlice.set( - {.account = alice, - .id = mptID, - .mutableFlags = flags, - .err = temINVALID_FLAG}); + mptAlice.set({.account = alice, .id = mptID, .mutableFlags = flags, .err = temINVALID_FLAG}); } } @@ -2931,16 +2551,11 @@ class MPToken_test : public beast::unit_test::suite tmfMPTSetCanTransfer | tmfMPTClearCanTransfer, tmfMPTSetCanClawback | tmfMPTClearCanClawback, tmfMPTSetCanLock | tmfMPTClearCanLock | tmfMPTClearCanTrade, - tmfMPTSetCanTransfer | tmfMPTClearCanTransfer | - tmfMPTSetCanEscrow | tmfMPTClearCanClawback}; + tmfMPTSetCanTransfer | tmfMPTClearCanTransfer | tmfMPTSetCanEscrow | tmfMPTClearCanClawback}; for (auto const& mutableFlags : flagCombinations) { - mptAlice.set( - {.account = alice, - .id = mptID, - .mutableFlags = mutableFlags, - .err = temINVALID_FLAG}); + mptAlice.set({.account = alice, .id = mptID, .mutableFlags = mutableFlags, .err = temINVALID_FLAG}); } } @@ -2967,10 +2582,7 @@ class MPToken_test : public beast::unit_test::suite for (auto const& mutableFlag : mutableFlags) { - mptAlice.set( - {.account = alice, - .mutableFlags = mutableFlag, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .mutableFlags = mutableFlag, .err = tecNO_PERMISSION}); } } @@ -2979,12 +2591,10 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, features}; MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.ownerCount = 1, .mutableFlags = tmfMPTCanMutateMetadata}); + mptAlice.create({.ownerCount = 1, .mutableFlags = tmfMPTCanMutateMetadata}); std::string metadata(maxMPTokenMetadataLength + 1, 'a'); - mptAlice.set( - {.account = alice, .metadata = metadata, .err = temMALFORMED}); + mptAlice.set({.account = alice, .metadata = metadata, .err = temMALFORMED}); } // Can not mutate metadata when it is not mutable @@ -2993,10 +2603,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); mptAlice.create({.ownerCount = 1}); - mptAlice.set( - {.account = alice, - .metadata = "test", - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .metadata = "test", .err = tecNO_PERMISSION}); } // Transfer fee exceeding the max value @@ -3005,14 +2612,10 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); auto const mptID = makeMptID(env.seq(alice), alice); - mptAlice.create( - {.ownerCount = 1, .mutableFlags = tmfMPTCanMutateTransferFee}); + mptAlice.create({.ownerCount = 1, .mutableFlags = tmfMPTCanMutateTransferFee}); mptAlice.set( - {.account = alice, - .id = mptID, - .transferFee = maxTransferFee + 1, - .err = temBAD_TRANSFER_FEE}); + {.account = alice, .id = mptID, .transferFee = maxTransferFee + 1, .err = temBAD_TRANSFER_FEE}); } // Test setting non-zero transfer fee and clearing MPTCanTransfer at the @@ -3025,24 +2628,17 @@ class MPToken_test : public beast::unit_test::suite {.transferFee = 100, .ownerCount = 1, .flags = tfMPTCanTransfer, - .mutableFlags = - tmfMPTCanMutateTransferFee | tmfMPTCanMutateCanTransfer}); + .mutableFlags = tmfMPTCanMutateTransferFee | tmfMPTCanMutateCanTransfer}); // Can not set non-zero transfer fee and clear MPTCanTransfer at the // same time mptAlice.set( - {.account = alice, - .mutableFlags = tmfMPTClearCanTransfer, - .transferFee = 1, - .err = temMALFORMED}); + {.account = alice, .mutableFlags = tmfMPTClearCanTransfer, .transferFee = 1, .err = temMALFORMED}); // Can set transfer fee to zero and clear MPTCanTransfer at the same // time. tfMPTCanTransfer will be cleared and TransferFee field will // be removed. - mptAlice.set( - {.account = alice, - .mutableFlags = tmfMPTClearCanTransfer, - .transferFee = 0}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanTransfer, .transferFee = 0}); BEAST_EXPECT(!mptAlice.isTransferFeePresent()); } @@ -3051,24 +2647,15 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, features}; MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.ownerCount = 1, - .mutableFlags = - tmfMPTCanMutateTransferFee | tmfMPTCanMutateCanTransfer}); + mptAlice.create({.ownerCount = 1, .mutableFlags = tmfMPTCanMutateTransferFee | tmfMPTCanMutateCanTransfer}); - mptAlice.set( - {.account = alice, - .transferFee = 100, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .transferFee = 100, .err = tecNO_PERMISSION}); // Can not set transfer fee even when trying to set MPTCanTransfer // at the same time. MPTCanTransfer must be set first, then transfer // fee can be set in a separate transaction. mptAlice.set( - {.account = alice, - .mutableFlags = tmfMPTSetCanTransfer, - .transferFee = 100, - .err = tecNO_PERMISSION}); + {.account = alice, .mutableFlags = tmfMPTSetCanTransfer, .transferFee = 100, .err = tecNO_PERMISSION}); } // Can not mutate transfer fee when it is not mutable @@ -3076,18 +2663,11 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, features}; MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.transferFee = 10, - .ownerCount = 1, - .flags = tfMPTCanTransfer}); + mptAlice.create({.transferFee = 10, .ownerCount = 1, .flags = tfMPTCanTransfer}); - mptAlice.set( - {.account = alice, - .transferFee = 100, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .transferFee = 100, .err = tecNO_PERMISSION}); - mptAlice.set( - {.account = alice, .transferFee = 0, .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .transferFee = 0, .err = tecNO_PERMISSION}); } // Set some flags mutable. Can not mutate the others @@ -3097,14 +2677,10 @@ class MPToken_test : public beast::unit_test::suite mptAlice.create( {.ownerCount = 1, - .mutableFlags = tmfMPTCanMutateCanTrade | - tmfMPTCanMutateCanTransfer | tmfMPTCanMutateMetadata}); + .mutableFlags = tmfMPTCanMutateCanTrade | tmfMPTCanMutateCanTransfer | tmfMPTCanMutateMetadata}); // Can not mutate transfer fee - mptAlice.set( - {.account = alice, - .transferFee = 100, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .transferFee = 100, .err = tecNO_PERMISSION}); auto const invalidFlags = { tmfMPTSetCanLock, @@ -3119,22 +2695,16 @@ class MPToken_test : public beast::unit_test::suite // Can not mutate flags which are not mutable for (auto const& mutableFlag : invalidFlags) { - mptAlice.set( - {.account = alice, - .mutableFlags = mutableFlag, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .mutableFlags = mutableFlag, .err = tecNO_PERMISSION}); } // Can mutate MPTCanTrade mptAlice.set({.account = alice, .mutableFlags = tmfMPTSetCanTrade}); - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanTrade}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanTrade}); // Can mutate MPTCanTransfer - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTSetCanTransfer}); - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanTransfer}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTSetCanTransfer}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanTransfer}); // Can mutate metadata mptAlice.set({.account = alice, .metadata = "test"}); @@ -3154,10 +2724,7 @@ class MPToken_test : public beast::unit_test::suite { Env env{*this, features}; MPTTester mptAlice(env, alice); - mptAlice.create( - {.metadata = "test", - .ownerCount = 1, - .mutableFlags = tmfMPTCanMutateMetadata}); + mptAlice.create({.metadata = "test", .ownerCount = 1, .mutableFlags = tmfMPTCanMutateMetadata}); std::vector metadatas = { "mutate metadata", @@ -3189,8 +2756,8 @@ class MPToken_test : public beast::unit_test::suite .flags = tfMPTCanTransfer, .mutableFlags = tmfMPTCanMutateTransferFee}); - for (std::uint16_t const fee : std::initializer_list{ - 1, 10, 100, 200, 500, 1000, maxTransferFee}) + for (std::uint16_t const fee : + std::initializer_list{1, 10, 100, 200, 500, 1000, maxTransferFee}) { mptAlice.set({.account = alice, .transferFee = fee}); BEAST_EXPECT(mptAlice.checkTransferFee(fee)); @@ -3207,17 +2774,12 @@ class MPToken_test : public beast::unit_test::suite // Test flag toggling { - auto testFlagToggle = [&](std::uint32_t createFlags, - std::uint32_t setFlags, - std::uint32_t clearFlags) { + auto testFlagToggle = [&](std::uint32_t createFlags, std::uint32_t setFlags, std::uint32_t clearFlags) { Env env{*this, features}; MPTTester mptAlice(env, alice); // Create the MPT object with the specified initial flags - mptAlice.create( - {.metadata = "test", - .ownerCount = 1, - .mutableFlags = createFlags}); + mptAlice.create({.metadata = "test", .ownerCount = 1, .mutableFlags = createFlags}); // Set and clear the flag multiple times mptAlice.set({.account = alice, .mutableFlags = setFlags}); @@ -3230,28 +2792,12 @@ class MPToken_test : public beast::unit_test::suite mptAlice.set({.account = alice, .mutableFlags = clearFlags}); }; - testFlagToggle( - tmfMPTCanMutateCanLock, tfMPTCanLock, tmfMPTClearCanLock); - testFlagToggle( - tmfMPTCanMutateRequireAuth, - tmfMPTSetRequireAuth, - tmfMPTClearRequireAuth); - testFlagToggle( - tmfMPTCanMutateCanEscrow, - tmfMPTSetCanEscrow, - tmfMPTClearCanEscrow); - testFlagToggle( - tmfMPTCanMutateCanTrade, - tmfMPTSetCanTrade, - tmfMPTClearCanTrade); - testFlagToggle( - tmfMPTCanMutateCanTransfer, - tmfMPTSetCanTransfer, - tmfMPTClearCanTransfer); - testFlagToggle( - tmfMPTCanMutateCanClawback, - tmfMPTSetCanClawback, - tmfMPTClearCanClawback); + testFlagToggle(tmfMPTCanMutateCanLock, tfMPTCanLock, tmfMPTClearCanLock); + testFlagToggle(tmfMPTCanMutateRequireAuth, tmfMPTSetRequireAuth, tmfMPTClearRequireAuth); + testFlagToggle(tmfMPTCanMutateCanEscrow, tmfMPTSetCanEscrow, tmfMPTClearCanEscrow); + testFlagToggle(tmfMPTCanMutateCanTrade, tmfMPTSetCanTrade, tmfMPTClearCanTrade); + testFlagToggle(tmfMPTCanMutateCanTransfer, tmfMPTSetCanTransfer, tmfMPTClearCanTransfer); + testFlagToggle(tmfMPTCanMutateCanClawback, tmfMPTSetCanClawback, tmfMPTClearCanClawback); } } @@ -3272,22 +2818,18 @@ class MPToken_test : public beast::unit_test::suite {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanLock | tfMPTCanTransfer, - .mutableFlags = tmfMPTCanMutateCanLock | - tmfMPTCanMutateCanTrade | tmfMPTCanMutateTransferFee}); + .mutableFlags = tmfMPTCanMutateCanLock | tmfMPTCanMutateCanTrade | tmfMPTCanMutateTransferFee}); mptAlice.authorize({.account = bob, .holderCount = 1}); // Lock bob's mptoken mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTLock}); // Can mutate the mutable flags and fields - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanLock}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanLock}); mptAlice.set({.account = alice, .mutableFlags = tmfMPTSetCanLock}); - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanLock}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanLock}); mptAlice.set({.account = alice, .mutableFlags = tmfMPTSetCanTrade}); - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanTrade}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanTrade}); mptAlice.set({.account = alice, .transferFee = 200}); } @@ -3299,23 +2841,18 @@ class MPToken_test : public beast::unit_test::suite {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanLock, - .mutableFlags = tmfMPTCanMutateCanLock | - tmfMPTCanMutateCanClawback | tmfMPTCanMutateMetadata}); + .mutableFlags = tmfMPTCanMutateCanLock | tmfMPTCanMutateCanClawback | tmfMPTCanMutateMetadata}); mptAlice.authorize({.account = bob, .holderCount = 1}); // Lock issuance mptAlice.set({.account = alice, .flags = tfMPTLock}); // Can mutate the mutable flags and fields - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanLock}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanLock}); mptAlice.set({.account = alice, .mutableFlags = tmfMPTSetCanLock}); - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanLock}); - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTSetCanClawback}); - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanClawback}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanLock}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTSetCanClawback}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanClawback}); mptAlice.set({.account = alice, .metadata = "mutate"}); } @@ -3327,40 +2864,23 @@ class MPToken_test : public beast::unit_test::suite {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanLock, - .mutableFlags = tmfMPTCanMutateCanLock | - tmfMPTCanMutateCanClawback | tmfMPTCanMutateMetadata}); + .mutableFlags = tmfMPTCanMutateCanLock | tmfMPTCanMutateCanClawback | tmfMPTCanMutateMetadata}); mptAlice.authorize({.account = bob, .holderCount = 1}); // Can lock and unlock mptAlice.set({.account = alice, .flags = tfMPTLock}); mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTLock}); mptAlice.set({.account = alice, .flags = tfMPTUnlock}); - mptAlice.set( - {.account = alice, .holder = bob, .flags = tfMPTUnlock}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTUnlock}); // Clear lsfMPTCanLock - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanLock}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanLock}); // Can not lock or unlock - mptAlice.set( - {.account = alice, - .flags = tfMPTLock, - .err = tecNO_PERMISSION}); - mptAlice.set( - {.account = alice, - .flags = tfMPTUnlock, - .err = tecNO_PERMISSION}); - mptAlice.set( - {.account = alice, - .holder = bob, - .flags = tfMPTLock, - .err = tecNO_PERMISSION}); - mptAlice.set( - {.account = alice, - .holder = bob, - .flags = tfMPTUnlock, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .flags = tfMPTLock, .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .flags = tfMPTUnlock, .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTLock, .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTUnlock, .err = tecNO_PERMISSION}); // Set MPTCanLock again mptAlice.set({.account = alice, .mutableFlags = tmfMPTSetCanLock}); @@ -3369,8 +2889,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.set({.account = alice, .flags = tfMPTLock}); mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTLock}); mptAlice.set({.account = alice, .flags = tfMPTUnlock}); - mptAlice.set( - {.account = alice, .holder = bob, .flags = tfMPTUnlock}); + mptAlice.set({.account = alice, .holder = bob, .flags = tfMPTUnlock}); } } @@ -3385,10 +2904,7 @@ class MPToken_test : public beast::unit_test::suite Account const bob("bob"); MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.ownerCount = 1, - .flags = tfMPTRequireAuth, - .mutableFlags = tmfMPTCanMutateRequireAuth}); + mptAlice.create({.ownerCount = 1, .flags = tfMPTRequireAuth, .mutableFlags = tmfMPTCanMutateRequireAuth}); mptAlice.authorize({.account = bob}); mptAlice.authorize({.account = alice, .holder = bob}); @@ -3397,15 +2913,13 @@ class MPToken_test : public beast::unit_test::suite mptAlice.pay(alice, bob, 1000); // Unauthorize bob - mptAlice.authorize( - {.account = alice, .holder = bob, .flags = tfMPTUnauthorize}); + mptAlice.authorize({.account = alice, .holder = bob, .flags = tfMPTUnauthorize}); // Can not pay to bob mptAlice.pay(bob, alice, 100, tecNO_AUTH); // Clear RequireAuth - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearRequireAuth}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearRequireAuth}); // Can pay to bob mptAlice.pay(alice, bob, 1000); @@ -3438,10 +2952,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {carol, bob}}); mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanTransfer, - .mutableFlags = tmfMPTCanMutateCanEscrow}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer, .mutableFlags = tmfMPTCanMutateCanEscrow}); mptAlice.authorize({.account = carol}); mptAlice.authorize({.account = bob}); @@ -3487,10 +2998,7 @@ class MPToken_test : public beast::unit_test::suite Env env{*this, features}; MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); - mptAlice.create( - {.ownerCount = 1, - .mutableFlags = - tmfMPTCanMutateCanTransfer | tmfMPTCanMutateTransferFee}); + mptAlice.create({.ownerCount = 1, .mutableFlags = tmfMPTCanMutateCanTransfer | tmfMPTCanMutateTransferFee}); mptAlice.authorize({.account = bob}); mptAlice.authorize({.account = carol}); @@ -3502,22 +3010,15 @@ class MPToken_test : public beast::unit_test::suite mptAlice.pay(bob, carol, 50, tecNO_AUTH); // Can not set non-zero transfer fee when MPTCanTransfer is not set - mptAlice.set( - {.account = alice, - .transferFee = 100, - .err = tecNO_PERMISSION}); + mptAlice.set({.account = alice, .transferFee = 100, .err = tecNO_PERMISSION}); // Can not set non-zero transfer fee even when trying to set // MPTCanTransfer at the same time mptAlice.set( - {.account = alice, - .mutableFlags = tmfMPTSetCanTransfer, - .transferFee = 100, - .err = tecNO_PERMISSION}); + {.account = alice, .mutableFlags = tmfMPTSetCanTransfer, .transferFee = 100, .err = tecNO_PERMISSION}); // Alice sets MPTCanTransfer - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTSetCanTransfer}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTSetCanTransfer}); // Can set transfer fee now BEAST_EXPECT(!mptAlice.isTransferFeePresent()); @@ -3528,8 +3029,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.pay(bob, carol, 50); // Alice clears MPTCanTransfer - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanTransfer}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanTransfer}); // TransferFee field is removed when MPTCanTransfer is cleared BEAST_EXPECT(!mptAlice.isTransferFeePresent()); @@ -3548,14 +3048,12 @@ class MPToken_test : public beast::unit_test::suite {.transferFee = 100, .ownerCount = 1, .flags = tfMPTCanTransfer, - .mutableFlags = - tmfMPTCanMutateTransferFee | tmfMPTCanMutateCanTransfer}); + .mutableFlags = tmfMPTCanMutateTransferFee | tmfMPTCanMutateCanTransfer}); BEAST_EXPECT(mptAlice.checkTransferFee(100)); // Clear MPTCanTransfer and transfer fee is removed - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanTransfer}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanTransfer}); BEAST_EXPECT(!mptAlice.isTransferFeePresent()); // Can still set transfer fee to zero, although it is already zero @@ -3578,10 +3076,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob}}); - mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .mutableFlags = tmfMPTCanMutateCanClawback}); + mptAlice.create({.ownerCount = 1, .holderCount = 0, .mutableFlags = tmfMPTCanMutateCanClawback}); // Bob creates an MPToken mptAlice.authorize({.account = bob}); @@ -3599,8 +3094,7 @@ class MPToken_test : public beast::unit_test::suite mptAlice.claw(alice, bob, 1); // Clear MPTCanClawback - mptAlice.set( - {.account = alice, .mutableFlags = tmfMPTClearCanClawback}); + mptAlice.set({.account = alice, .mutableFlags = tmfMPTClearCanClawback}); // Can not clawback mptAlice.claw(alice, bob, 1, tecNO_PERMISSION); diff --git a/src/test/app/Manifest_test.cpp b/src/test/app/Manifest_test.cpp index 09054658c9..f5004a3200 100644 --- a/src/test/app/Manifest_test.cpp +++ b/src/test/app/Manifest_test.cpp @@ -55,8 +55,7 @@ private: if (!is_directory(dbPath)) { // someone created a file where we want to put our directory - Throw( - "Cannot create directory: " + dbPath.string()); + Throw("Cannot create directory: " + dbPath.string()); } } static boost::filesystem::path @@ -88,12 +87,7 @@ public: } std::string - makeManifestString( - PublicKey const& pk, - SecretKey const& sk, - PublicKey const& spk, - SecretKey const& ssk, - int seq) + makeManifestString(PublicKey const& pk, SecretKey const& sk, PublicKey const& spk, SecretKey const& ssk, int seq) { STObject st(sfGeneric); st[sfSequence] = seq; @@ -101,25 +95,16 @@ public: st[sfSigningPubKey] = spk; sign(st, HashPrefix::manifest, *publicKeyType(spk), ssk); - sign( - st, - HashPrefix::manifest, - *publicKeyType(pk), - sk, - sfMasterSignature); + sign(st, HashPrefix::manifest, *publicKeyType(pk), sk, sfMasterSignature); Serializer s; st.add(s); - return base64_encode( - std::string(static_cast(s.data()), s.size())); + return base64_encode(std::string(static_cast(s.data()), s.size())); } std::string - makeRevocationString( - SecretKey const& sk, - KeyType type, - bool invalidSig = false) + makeRevocationString(SecretKey const& sk, KeyType type, bool invalidSig = false) { auto const pk = derivePublicKey(type, sk); @@ -127,21 +112,13 @@ public: st[sfSequence] = std::numeric_limits::max(); st[sfPublicKey] = pk; - sign( - st, - HashPrefix::manifest, - type, - invalidSig ? randomSecretKey() : sk, - sfMasterSignature); - BEAST_EXPECT( - invalidSig ^ - verify(st, HashPrefix::manifest, pk, sfMasterSignature)); + sign(st, HashPrefix::manifest, type, invalidSig ? randomSecretKey() : sk, sfMasterSignature); + BEAST_EXPECT(invalidSig ^ verify(st, HashPrefix::manifest, pk, sfMasterSignature)); Serializer s; st.add(s); - return base64_encode( - std::string(static_cast(s.data()), s.size())); + return base64_encode(std::string(static_cast(s.data()), s.size())); } Manifest @@ -153,15 +130,8 @@ public: st[sfSequence] = std::numeric_limits::max(); st[sfPublicKey] = pk; - sign( - st, - HashPrefix::manifest, - type, - invalidSig ? randomSecretKey() : sk, - sfMasterSignature); - BEAST_EXPECT( - invalidSig ^ - verify(st, HashPrefix::manifest, pk, sfMasterSignature)); + sign(st, HashPrefix::manifest, type, invalidSig ? randomSecretKey() : sk, sfMasterSignature); + BEAST_EXPECT(invalidSig ^ verify(st, HashPrefix::manifest, pk, sfMasterSignature)); Serializer s; st.add(s); @@ -171,8 +141,7 @@ public: if (auto r = deserializeManifest(std::move(m))) return std::move(*r); Throw("Could not create a revocation manifest"); - return *deserializeManifest( - std::string{}); // Silence compiler warning. + return *deserializeManifest(std::string{}); // Silence compiler warning. } Manifest @@ -195,34 +164,24 @@ public: sign(st, HashPrefix::manifest, stype, ssk); BEAST_EXPECT(verify(st, HashPrefix::manifest, spk)); - sign( - st, - HashPrefix::manifest, - type, - invalidSig ? randomSecretKey() : sk, - sfMasterSignature); - BEAST_EXPECT( - invalidSig ^ - verify(st, HashPrefix::manifest, pk, sfMasterSignature)); + sign(st, HashPrefix::manifest, type, invalidSig ? randomSecretKey() : sk, sfMasterSignature); + BEAST_EXPECT(invalidSig ^ verify(st, HashPrefix::manifest, pk, sfMasterSignature)); Serializer s; st.add(s); - std::string m( - static_cast(s.data()), - s.size()); // non-const so can be moved + std::string m(static_cast(s.data()), + s.size()); // non-const so can be moved if (auto r = deserializeManifest(std::move(m))) return std::move(*r); Throw("Could not create a manifest"); - return *deserializeManifest( - std::string{}); // Silence compiler warning. + return *deserializeManifest(std::string{}); // Silence compiler warning. } Manifest clone(Manifest const& m) { - Manifest m2( - m.serialized, m.masterKey, m.signingKey, m.sequence, m.domain); + Manifest m2(m.serialized, m.masterKey, m.signingKey, m.sequence, m.domain); return m2; } @@ -240,52 +199,35 @@ public: auto dbCon = makeTestWalletDB(setup, dbName, env.journal); - auto getPopulatedManifests = - [](ManifestCache const& cache) -> std::vector { + auto getPopulatedManifests = [](ManifestCache const& cache) -> std::vector { std::vector result; result.reserve(32); - cache.for_each_manifest( - [&result](Manifest const& man) { result.push_back(&man); }); + cache.for_each_manifest([&result](Manifest const& man) { result.push_back(&man); }); return result; }; - auto sort = [](std::vector mv) - -> std::vector { - std::sort( - mv.begin(), - mv.end(), - [](Manifest const* lhs, Manifest const* rhs) { - return lhs->serialized < rhs->serialized; - }); + auto sort = [](std::vector mv) -> std::vector { + std::sort(mv.begin(), mv.end(), [](Manifest const* lhs, Manifest const* rhs) { + return lhs->serialized < rhs->serialized; + }); return mv; }; - std::vector const inManifests( - sort(getPopulatedManifests(m))); + std::vector const inManifests(sort(getPopulatedManifests(m))); auto& app = env.app(); auto unl = std::make_unique( - m, - m, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + m, m, env.timeKeeper(), app.config().legacy("database_path"), env.journal); { // save should not store untrusted master keys to db // except for revocations - m.save( - *dbCon, - "ValidatorManifests", - [&unl](PublicKey const& pubKey) { - return unl->listed(pubKey); - }); + m.save(*dbCon, "ValidatorManifests", [&unl](PublicKey const& pubKey) { return unl->listed(pubKey); }); ManifestCache loaded; loaded.load(*dbCon, "ValidatorManifests"); // check that all loaded manifests are revocations - std::vector const loadedManifests( - sort(getPopulatedManifests(loaded))); + std::vector const loadedManifests(sort(getPopulatedManifests(loaded))); for (auto const& man : loadedManifests) BEAST_EXPECT(man->revoked()); @@ -296,22 +238,15 @@ public: std::vector keys; std::string cfgManifest; for (auto const& man : inManifests) - s1.push_back( - toBase58(TokenType::NodePublic, man->masterKey)); + s1.push_back(toBase58(TokenType::NodePublic, man->masterKey)); unl->load({}, s1, keys); - m.save( - *dbCon, - "ValidatorManifests", - [&unl](PublicKey const& pubKey) { - return unl->listed(pubKey); - }); + m.save(*dbCon, "ValidatorManifests", [&unl](PublicKey const& pubKey) { return unl->listed(pubKey); }); ManifestCache loaded; loaded.load(*dbCon, "ValidatorManifests"); // check that the manifest caches are the same - std::vector const loadedManifests( - sort(getPopulatedManifests(loaded))); + std::vector const loadedManifests(sort(getPopulatedManifests(loaded))); if (inManifests.size() == loadedManifests.size()) { @@ -319,9 +254,7 @@ public: inManifests.begin(), inManifests.end(), loadedManifests.begin(), - [](Manifest const* lhs, Manifest const* rhs) { - return *lhs == *rhs; - })); + [](Manifest const* lhs, Manifest const* rhs) { return *lhs == *rhs; })); } else { @@ -334,74 +267,44 @@ public: std::vector const emptyRevocation; std::string const badManifest = "bad manifest"; - BEAST_EXPECT(!loaded.load( - *dbCon, - "ValidatorManifests", - badManifest, - emptyRevocation)); + BEAST_EXPECT(!loaded.load(*dbCon, "ValidatorManifests", badManifest, emptyRevocation)); auto const sk = randomSecretKey(); auto const pk = derivePublicKey(KeyType::ed25519, sk); auto const kp = randomKeyPair(KeyType::secp256k1); - std::string const cfgManifest = - makeManifestString(pk, sk, kp.first, kp.second, 0); + std::string const cfgManifest = makeManifestString(pk, sk, kp.first, kp.second, 0); - BEAST_EXPECT(loaded.load( - *dbCon, - "ValidatorManifests", - cfgManifest, - emptyRevocation)); + BEAST_EXPECT(loaded.load(*dbCon, "ValidatorManifests", cfgManifest, emptyRevocation)); } { // load config revocation ManifestCache loaded; std::string const emptyManifest; - std::vector const badRevocation = { - "bad revocation"}; - BEAST_EXPECT(!loaded.load( - *dbCon, - "ValidatorManifests", - emptyManifest, - badRevocation)); + std::vector const badRevocation = {"bad revocation"}; + BEAST_EXPECT(!loaded.load(*dbCon, "ValidatorManifests", emptyManifest, badRevocation)); auto const sk = randomSecretKey(); auto const keyType = KeyType::ed25519; auto const pk = derivePublicKey(keyType, sk); auto const kp = randomKeyPair(KeyType::secp256k1); - std::vector const nonRevocation = { - makeManifestString(pk, sk, kp.first, kp.second, 0)}; + std::vector const nonRevocation = {makeManifestString(pk, sk, kp.first, kp.second, 0)}; - BEAST_EXPECT(!loaded.load( - *dbCon, - "ValidatorManifests", - emptyManifest, - nonRevocation)); + BEAST_EXPECT(!loaded.load(*dbCon, "ValidatorManifests", emptyManifest, nonRevocation)); BEAST_EXPECT(!loaded.revoked(pk)); - std::vector const badSigRevocation = { - makeRevocationString(sk, keyType, true)}; - BEAST_EXPECT(!loaded.load( - *dbCon, - "ValidatorManifests", - emptyManifest, - badSigRevocation)); + std::vector const badSigRevocation = {makeRevocationString(sk, keyType, true)}; + BEAST_EXPECT(!loaded.load(*dbCon, "ValidatorManifests", emptyManifest, badSigRevocation)); BEAST_EXPECT(!loaded.revoked(pk)); - std::vector const cfgRevocation = { - makeRevocationString(sk, keyType)}; - BEAST_EXPECT(loaded.load( - *dbCon, - "ValidatorManifests", - emptyManifest, - cfgRevocation)); + std::vector const cfgRevocation = {makeRevocationString(sk, keyType)}; + BEAST_EXPECT(loaded.load(*dbCon, "ValidatorManifests", emptyManifest, cfgRevocation)); BEAST_EXPECT(loaded.revoked(pk)); } } - boost::filesystem::remove( - getDatabasePath() / boost::filesystem::path(dbName)); + boost::filesystem::remove(getDatabasePath() / boost::filesystem::path(dbName)); } void @@ -411,8 +314,7 @@ public: auto const sk = randomSecretKey(); auto const pk = derivePublicKey(KeyType::ed25519, sk); auto const kp = randomKeyPair(KeyType::secp256k1); - auto const m = makeManifest( - sk, KeyType::ed25519, kp.second, KeyType::secp256k1, 0); + auto const m = makeManifest(sk, KeyType::ed25519, kp.second, KeyType::secp256k1, 0); STObject st(sfGeneric); st[sfSequence] = 0; @@ -447,8 +349,7 @@ public: auto const kp0 = randomKeyPair(KeyType::secp256k1); BEAST_EXPECT( ManifestDisposition::accepted == - cache.applyManifest(makeManifest( - sk, KeyType::ed25519, kp0.second, KeyType::secp256k1, 0))); + cache.applyManifest(makeManifest(sk, KeyType::ed25519, kp0.second, KeyType::secp256k1, 0))); BEAST_EXPECT(cache.getSigningKey(pk) == kp0.first); BEAST_EXPECT(cache.getMasterKey(kp0.first) == pk); @@ -459,8 +360,7 @@ public: auto const kp1 = randomKeyPair(KeyType::secp256k1); BEAST_EXPECT( ManifestDisposition::accepted == - cache.applyManifest(makeManifest( - sk, KeyType::ed25519, kp1.second, KeyType::secp256k1, 1))); + cache.applyManifest(makeManifest(sk, KeyType::ed25519, kp1.second, KeyType::secp256k1, 1))); BEAST_EXPECT(cache.getSigningKey(pk) == kp1.first); BEAST_EXPECT(cache.getMasterKey(kp1.first) == pk); BEAST_EXPECT(cache.getMasterKey(kp0.first) == kp0.first); @@ -469,8 +369,7 @@ public: // applied with the same signing key but a higher sequence BEAST_EXPECT( ManifestDisposition::badEphemeralKey == - cache.applyManifest(makeManifest( - sk, KeyType::ed25519, kp1.second, KeyType::secp256k1, 2))); + cache.applyManifest(makeManifest(sk, KeyType::ed25519, kp1.second, KeyType::secp256k1, 2))); BEAST_EXPECT(cache.getSigningKey(pk) == kp1.first); BEAST_EXPECT(cache.getMasterKey(kp1.first) == pk); BEAST_EXPECT(cache.getMasterKey(kp0.first) == kp0.first); @@ -478,9 +377,7 @@ public: // getSigningKey should return std::nullopt for a revoked master public // key getMasterKey should return std::nullopt for an ephemeral public // key from a revoked master public key - BEAST_EXPECT( - ManifestDisposition::accepted == - cache.applyManifest(makeRevocation(sk, KeyType::ed25519))); + BEAST_EXPECT(ManifestDisposition::accepted == cache.applyManifest(makeRevocation(sk, KeyType::ed25519))); BEAST_EXPECT(cache.revoked(pk)); BEAST_EXPECT(cache.getSigningKey(pk) == pk); BEAST_EXPECT(cache.getMasterKey(kp0.first) == kp0.first); @@ -493,9 +390,8 @@ public: testcase("validator token"); { - auto const valSecret = parseBase58( - TokenType::NodePrivate, - "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi"); + auto const valSecret = + parseBase58(TokenType::NodePrivate, "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi"); // Format token string to test trim() std::vector const tokenBlob = { @@ -560,12 +456,7 @@ public: if (version != 0) st[sfVersion] = version; - sign( - st, - HashPrefix::manifest, - KeyType::ed25519, - sk, - sfMasterSignature); + sign(st, HashPrefix::manifest, KeyType::ed25519, sk, sfMasterSignature); sign(st, HashPrefix::manifest, KeyType::secp256k1, ssk); Serializer s; @@ -585,35 +476,18 @@ public: void testManifestDeserialization() { - std::array const keyTypes{ - {KeyType::ed25519, KeyType::secp256k1}}; + std::array const keyTypes{{KeyType::ed25519, KeyType::secp256k1}}; std::uint32_t sequence = 0; // public key with invalid type - std::array const badKey{ - 0x99, 0x30, 0xE7, 0xFC, 0x9D, 0x56, 0xBB, 0x25, 0xD6, 0x89, 0x3B, - 0xA3, 0xF3, 0x17, 0xAE, 0x5B, 0xCF, 0x33, 0xB3, 0x29, 0x1B, 0xD6, - 0x3D, 0xB3, 0x26, 0x54, 0xA3, 0x13, 0x22, 0x2F, 0x7F, 0xD0, 0x20}; + std::array const badKey{0x99, 0x30, 0xE7, 0xFC, 0x9D, 0x56, 0xBB, 0x25, 0xD6, 0x89, 0x3B, + 0xA3, 0xF3, 0x17, 0xAE, 0x5B, 0xCF, 0x33, 0xB3, 0x29, 0x1B, 0xD6, + 0x3D, 0xB3, 0x26, 0x54, 0xA3, 0x13, 0x22, 0x2F, 0x7F, 0xD0, 0x20}; // Short public key: std::array const shortKey{ - 0x03, - 0x30, - 0xE7, - 0xFC, - 0x9D, - 0x56, - 0xBB, - 0x25, - 0xD6, - 0x89, - 0x3B, - 0xA3, - 0xF3, - 0x17, - 0xAE, - 0x5B}; + 0x03, 0x30, 0xE7, 0xFC, 0x9D, 0x56, 0xBB, 0x25, 0xD6, 0x89, 0x3B, 0xA3, 0xF3, 0x17, 0xAE, 0x5B}; auto toString = [](STObject const& st) { Serializer s; @@ -632,42 +506,34 @@ public: auto const ssk = generateSecretKey(sKeyType, randomSeed()); auto const spk = derivePublicKey(sKeyType, ssk); - auto buildManifestObject = - [&](std::uint32_t seq, - std::optional domain, - bool noSigningPublic = false, - bool noSignature = false) { - STObject st(sfGeneric); - st[sfSequence] = seq; - st[sfPublicKey] = pk; + auto buildManifestObject = [&](std::uint32_t seq, + std::optional domain, + bool noSigningPublic = false, + bool noSignature = false) { + STObject st(sfGeneric); + st[sfSequence] = seq; + st[sfPublicKey] = pk; - if (domain) - st[sfDomain] = makeSlice(*domain); + if (domain) + st[sfDomain] = makeSlice(*domain); - if (!noSigningPublic) - st[sfSigningPubKey] = spk; + if (!noSigningPublic) + st[sfSigningPubKey] = spk; - sign( - st, - HashPrefix::manifest, - keyType, - sk, - sfMasterSignature); + sign(st, HashPrefix::manifest, keyType, sk, sfMasterSignature); - if (!noSignature) - sign(st, HashPrefix::manifest, sKeyType, ssk); + if (!noSignature) + sign(st, HashPrefix::manifest, sKeyType, ssk); - return st; - }; + return st; + }; { - testcase << "deserializeManifest: normal manifest (" - << to_string(keyType) << " + " + testcase << "deserializeManifest: normal manifest (" << to_string(keyType) << " + " << to_string(sKeyType) << ")"; { // valid manifest without domain - auto const st = - buildManifestObject(++sequence, std::nullopt); + auto const st = buildManifestObject(++sequence, std::nullopt); auto const m = toString(st); auto const manifest = deserializeManifest(m); @@ -682,32 +548,27 @@ public: } { // invalid manifest (empty domain) - auto const st = - buildManifestObject(++sequence, std::string{}); + auto const st = buildManifestObject(++sequence, std::string{}); BEAST_EXPECT(!deserializeManifest(toString(st))); } { // invalid manifest (domain too short) - auto const st = - buildManifestObject(++sequence, std::string{"a.b"}); + auto const st = buildManifestObject(++sequence, std::string{"a.b"}); BEAST_EXPECT(!deserializeManifest(toString(st))); } { // invalid manifest (domain too long) std::string s(254, 'a'); - auto const st = - buildManifestObject(++sequence, s + ".example.com"); + auto const st = buildManifestObject(++sequence, s + ".example.com"); BEAST_EXPECT(!deserializeManifest(toString(st))); } { // invalid manifest (domain component too long) std::string s(72, 'a'); - auto const st = - buildManifestObject(++sequence, s + ".example.com"); + auto const st = buildManifestObject(++sequence, s + ".example.com"); BEAST_EXPECT(!deserializeManifest(toString(st))); } - auto const st = buildManifestObject( - ++sequence, std::string{"example.com"}); + auto const st = buildManifestObject(++sequence, std::string{"example.com"}); { // valid manifest with domain @@ -799,12 +660,7 @@ public: st[sfPublicKey] = pk; st[sfSigningPubKey] = pk; - sign( - st, - HashPrefix::manifest, - keyType, - sk, - sfMasterSignature); + sign(st, HashPrefix::manifest, keyType, sk, sfMasterSignature); sign(st, HashPrefix::manifest, sKeyType, sk); @@ -813,17 +669,13 @@ public: } { - testcase << "deserializeManifest: revocation manifest (" - << to_string(keyType) << " + " + testcase << "deserializeManifest: revocation manifest (" << to_string(keyType) << " + " << to_string(sKeyType) << ")"; // valid revocation { - auto const st = buildManifestObject( - std::numeric_limits::max(), - std::nullopt, - true, - true); + auto const st = + buildManifestObject(std::numeric_limits::max(), std::nullopt, true, true); auto const m = toString(st); auto const manifest = deserializeManifest(m); @@ -841,29 +693,20 @@ public: } { // can't specify an ephemeral signing key - auto const st = buildManifestObject( - std::numeric_limits::max(), - std::nullopt, - true, - false); + auto const st = + buildManifestObject(std::numeric_limits::max(), std::nullopt, true, false); BEAST_EXPECT(!deserializeManifest(toString(st))); } { // can't specify an ephemeral signature - auto const st = buildManifestObject( - std::numeric_limits::max(), - std::nullopt, - false, - true); + auto const st = + buildManifestObject(std::numeric_limits::max(), std::nullopt, false, true); BEAST_EXPECT(!deserializeManifest(toString(st))); } { // can't specify an ephemeral key & signature - auto const st = buildManifestObject( - std::numeric_limits::max(), - std::nullopt, - false, - false); + auto const st = + buildManifestObject(std::numeric_limits::max(), std::nullopt, false, false); BEAST_EXPECT(!deserializeManifest(toString(st))); } @@ -890,19 +733,13 @@ public: st[sfDomain] = makeSlice(domain); st[sfSigningPubKey] = pk2; - sign( - st, - HashPrefix::manifest, - KeyType::secp256k1, - sk1, - sfMasterSignature); + sign(st, HashPrefix::manifest, KeyType::secp256k1, sk1, sfMasterSignature); sign(st, HashPrefix::manifest, KeyType::secp256k1, sk2); Serializer s; st.add(s); - return deserializeManifest( - std::string(static_cast(s.data()), s.size())); + return deserializeManifest(std::string(static_cast(s.data()), s.size())); }; BEAST_EXPECT(test("example.com")); @@ -953,9 +790,7 @@ public: BEAST_EXPECT(!test(std::string(64, 'a') + "." + std::string(64, 'b'))); // Overall too long: - BEAST_EXPECT(!test( - std::string(63, 'a') + "." + std::string(63, 'b') + - ".example.com")); + BEAST_EXPECT(!test(std::string(63, 'a') + "." + std::string(63, 'b') + ".example.com")); } void @@ -969,20 +804,16 @@ public: auto const pk_a = derivePublicKey(KeyType::ed25519, sk_a); auto const kp_a0 = randomKeyPair(KeyType::secp256k1); auto const kp_a1 = randomKeyPair(KeyType::secp256k1); - auto const s_a0 = makeManifest( - sk_a, KeyType::ed25519, kp_a0.second, KeyType::secp256k1, 0); - auto const s_a1 = makeManifest( - sk_a, KeyType::ed25519, kp_a1.second, KeyType::secp256k1, 1); - auto const s_a2 = makeManifest( - sk_a, KeyType::ed25519, kp_a1.second, KeyType::secp256k1, 2); + auto const s_a0 = makeManifest(sk_a, KeyType::ed25519, kp_a0.second, KeyType::secp256k1, 0); + auto const s_a1 = makeManifest(sk_a, KeyType::ed25519, kp_a1.second, KeyType::secp256k1, 1); + auto const s_a2 = makeManifest(sk_a, KeyType::ed25519, kp_a1.second, KeyType::secp256k1, 2); auto const s_aMax = makeRevocation(sk_a, KeyType::ed25519); auto const sk_b = randomSecretKey(); auto const kp_b0 = randomKeyPair(KeyType::secp256k1); auto const kp_b1 = randomKeyPair(KeyType::secp256k1); auto const kp_b2 = randomKeyPair(KeyType::secp256k1); - auto const s_b0 = makeManifest( - sk_b, KeyType::ed25519, kp_b0.second, KeyType::secp256k1, 0); + auto const s_b0 = makeManifest(sk_b, KeyType::ed25519, kp_b0.second, KeyType::secp256k1, 0); auto const s_b1 = makeManifest( sk_b, KeyType::ed25519, @@ -990,70 +821,40 @@ public: KeyType::secp256k1, 1, true); // invalidSig - auto const s_b2 = makeManifest( - sk_b, KeyType::ed25519, kp_b2.second, KeyType::ed25519, 2); + auto const s_b2 = makeManifest(sk_b, KeyType::ed25519, kp_b2.second, KeyType::ed25519, 2); auto const fake = s_b2.serialized + '\0'; // applyManifest should accept new manifests with // higher sequence numbers - BEAST_EXPECT( - cache.applyManifest(clone(s_a0)) == - ManifestDisposition::accepted); - BEAST_EXPECT( - cache.applyManifest(clone(s_a0)) == ManifestDisposition::stale); + BEAST_EXPECT(cache.applyManifest(clone(s_a0)) == ManifestDisposition::accepted); + BEAST_EXPECT(cache.applyManifest(clone(s_a0)) == ManifestDisposition::stale); - BEAST_EXPECT( - cache.applyManifest(clone(s_a1)) == - ManifestDisposition::accepted); - BEAST_EXPECT( - cache.applyManifest(clone(s_a1)) == ManifestDisposition::stale); - BEAST_EXPECT( - cache.applyManifest(clone(s_a0)) == ManifestDisposition::stale); + BEAST_EXPECT(cache.applyManifest(clone(s_a1)) == ManifestDisposition::accepted); + BEAST_EXPECT(cache.applyManifest(clone(s_a1)) == ManifestDisposition::stale); + BEAST_EXPECT(cache.applyManifest(clone(s_a0)) == ManifestDisposition::stale); - BEAST_EXPECT( - cache.applyManifest(clone(s_a2)) == - ManifestDisposition::badEphemeralKey); + BEAST_EXPECT(cache.applyManifest(clone(s_a2)) == ManifestDisposition::badEphemeralKey); // applyManifest should accept manifests with max sequence numbers // that revoke the master public key BEAST_EXPECT(!cache.revoked(pk_a)); BEAST_EXPECT(s_aMax.revoked()); - BEAST_EXPECT( - cache.applyManifest(clone(s_aMax)) == - ManifestDisposition::accepted); - BEAST_EXPECT( - cache.applyManifest(clone(s_aMax)) == - ManifestDisposition::stale); - BEAST_EXPECT( - cache.applyManifest(clone(s_a1)) == ManifestDisposition::stale); - BEAST_EXPECT( - cache.applyManifest(clone(s_a0)) == ManifestDisposition::stale); + BEAST_EXPECT(cache.applyManifest(clone(s_aMax)) == ManifestDisposition::accepted); + BEAST_EXPECT(cache.applyManifest(clone(s_aMax)) == ManifestDisposition::stale); + BEAST_EXPECT(cache.applyManifest(clone(s_a1)) == ManifestDisposition::stale); + BEAST_EXPECT(cache.applyManifest(clone(s_a0)) == ManifestDisposition::stale); BEAST_EXPECT(cache.revoked(pk_a)); // applyManifest should reject manifests with invalid signatures - BEAST_EXPECT( - cache.applyManifest(clone(s_b0)) == - ManifestDisposition::accepted); - BEAST_EXPECT( - cache.applyManifest(clone(s_b0)) == ManifestDisposition::stale); + BEAST_EXPECT(cache.applyManifest(clone(s_b0)) == ManifestDisposition::accepted); + BEAST_EXPECT(cache.applyManifest(clone(s_b0)) == ManifestDisposition::stale); BEAST_EXPECT(!deserializeManifest(fake)); - BEAST_EXPECT( - cache.applyManifest(clone(s_b1)) == - ManifestDisposition::invalid); - BEAST_EXPECT( - cache.applyManifest(clone(s_b2)) == - ManifestDisposition::accepted); + BEAST_EXPECT(cache.applyManifest(clone(s_b1)) == ManifestDisposition::invalid); + BEAST_EXPECT(cache.applyManifest(clone(s_b2)) == ManifestDisposition::accepted); - auto const s_c0 = makeManifest( - kp_b2.second, - KeyType::ed25519, - randomSecretKey(), - KeyType::ed25519, - 47); - BEAST_EXPECT( - cache.applyManifest(clone(s_c0)) == - ManifestDisposition::badMasterKey); + auto const s_c0 = makeManifest(kp_b2.second, KeyType::ed25519, randomSecretKey(), KeyType::ed25519, 47); + BEAST_EXPECT(cache.applyManifest(clone(s_c0)) == ManifestDisposition::badMasterKey); } testLoadStore(cache); diff --git a/src/test/app/MultiSign_test.cpp b/src/test/app/MultiSign_test.cpp index 5c5404c17e..3d732ee2e0 100644 --- a/src/test/app/MultiSign_test.cpp +++ b/src/test/app/MultiSign_test.cpp @@ -84,14 +84,7 @@ public: Json::Value bigSigners = signers( alice, 1, - {{bogie, 1}, - {demon, 1}, - {ghost, 1}, - {haunt, 1}, - {jinni, 1}, - {phase, 1}, - {shade, 1}, - {spook, 1}}); + {{bogie, 1}, {demon, 1}, {ghost, 1}, {haunt, 1}, {jinni, 1}, {phase, 1}, {shade, 1}, {spook, 1}}); env(bigSigners, ter(tecINSUFFICIENT_RESERVE)); env.close(); env.require(owners(alice, 1)); @@ -136,14 +129,7 @@ public: env(signers( alice, 1, - {{bogie, 1}, - {demon, 1}, - {ghost, 1}, - {haunt, 1}, - {jinni, 1}, - {phase, 1}, - {demon, 1}, - {spook, 1}}), + {{bogie, 1}, {demon, 1}, {ghost, 1}, {haunt, 1}, {jinni, 1}, {phase, 1}, {demon, 1}, {spook, 1}}), ter(temBAD_SIGNER)); // Set a quorum of zero. Should fail. @@ -153,14 +139,7 @@ public: env(signers( alice, 9, - {{bogie, 1}, - {demon, 1}, - {ghost, 1}, - {haunt, 1}, - {jinni, 1}, - {phase, 1}, - {shade, 1}, - {spook, 1}}), + {{bogie, 1}, {demon, 1}, {ghost, 1}, {haunt, 1}, {jinni, 1}, {phase, 1}, {shade, 1}, {spook, 1}}), ter(temBAD_QUORUM)); // clang-format off @@ -225,17 +204,13 @@ public: env(noop(alice), msig(demon, demon), fee(3 * baseFee), - rpc("invalidTransaction", - "fails local checks: Duplicate Signers not allowed.")); + rpc("invalidTransaction", "fails local checks: Duplicate Signers not allowed.")); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); // A non-signer should fail. aliceSeq = env.seq(alice); - env(noop(alice), - msig(bogie, spook), - fee(3 * baseFee), - ter(tefBAD_SIGNATURE)); + env(noop(alice), msig(bogie, spook), fee(3 * baseFee), ter(tefBAD_SIGNATURE)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); @@ -268,14 +243,7 @@ public: env(signers( alice, 1, - {{bogie, 1}, - {demon, 1}, - {ghost, 1}, - {haunt, 1}, - {jinni, 1}, - {phase, 1}, - {shade, 1}, - {spook, 1}})); + {{bogie, 1}, {demon, 1}, {ghost, 1}, {haunt, 1}, {jinni, 1}, {phase, 1}, {shade, 1}, {spook, 1}})); env.close(); env.require(owners(alice, 1)); @@ -289,19 +257,14 @@ public: // This should fail because the fee is too small. aliceSeq = env.seq(alice); - env(noop(alice), - msig(bogie), - fee((2 * baseFee) - 1), - ter(telINSUF_FEE_P)); + env(noop(alice), msig(bogie), fee((2 * baseFee) - 1), ter(telINSUF_FEE_P)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); // This should work. aliceSeq = env.seq(alice); - env(noop(alice), - msig(bogie, demon, ghost, haunt, jinni, phase, shade, spook), - fee(9 * baseFee)); + env(noop(alice), msig(bogie, demon, ghost, haunt, jinni, phase, shade, spook), fee(9 * baseFee)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); @@ -337,10 +300,7 @@ public: msig phantoms{bogie, demon}; std::reverse(phantoms.signers.begin(), phantoms.signers.end()); std::uint32_t const aliceSeq = env.seq(alice); - env(noop(alice), - phantoms, - rpc("invalidTransaction", - "fails local checks: Unsorted Signers array.")); + env(noop(alice), phantoms, rpc("invalidTransaction", "fails local checks: Unsorted Signers array.")); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); } @@ -438,10 +398,7 @@ public: // cheri should not be able to multisign using her master key. aliceSeq = env.seq(alice); - env(noop(alice), - msig(cheri), - fee(2 * baseFee), - ter(tefMASTER_DISABLED)); + env(noop(alice), msig(cheri), fee(2 * baseFee), ter(tefMASTER_DISABLED)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); @@ -458,9 +415,7 @@ public: // Both becky and cheri should be able to sign using regular keys. aliceSeq = env.seq(alice); - env(noop(alice), - fee(3 * baseFee), - msig(Reg{becky, beck}, Reg{cheri, cher})); + env(noop(alice), fee(3 * baseFee), msig(Reg{becky, beck}, Reg{cheri, cher})); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); } @@ -527,8 +482,7 @@ public: aliceSeq = env.seq(alice); Json::Value jv_one = setup_tx(); cheri_sign(jv_one); - auto jrr = - env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; + auto jrr = env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); // for the second sign_for, use the returned tx_json with @@ -541,10 +495,7 @@ public: Json::Value jv_submit; jv_submit[jss::tx_json] = jrr[jss::tx_json]; - jrr = env.rpc( - "json", - "submit_multisigned", - to_string(jv_submit))[jss::result]; + jrr = env.rpc("json", "submit_multisigned", to_string(jv_submit))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); @@ -554,16 +505,12 @@ public: // failure case -- SigningPubKey not empty aliceSeq = env.seq(alice); Json::Value jv_one = setup_tx(); - jv_one[jss::tx_json][jss::SigningPubKey] = - strHex(alice.pk().slice()); + jv_one[jss::tx_json][jss::SigningPubKey] = strHex(alice.pk().slice()); cheri_sign(jv_one); - auto jrr = - env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; + auto jrr = env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "When multi-signing 'tx_json.SigningPubKey' must be empty."); + BEAST_EXPECT(jrr[jss::error_message] == "When multi-signing 'tx_json.SigningPubKey' must be empty."); } { @@ -572,8 +519,7 @@ public: Json::Value jv_one = setup_tx(); jv_one[jss::tx_json][jss::Fee] = -1; cheri_sign(jv_one); - auto jrr = - env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; + auto jrr = env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); // for the second sign_for, use the returned tx_json with @@ -586,26 +532,19 @@ public: Json::Value jv_submit; jv_submit[jss::tx_json] = jrr[jss::tx_json]; - jrr = env.rpc( - "json", - "submit_multisigned", - to_string(jv_submit))[jss::result]; + jrr = env.rpc("json", "submit_multisigned", to_string(jv_submit))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid Fee field. Fees must be greater than zero."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid Fee field. Fees must be greater than zero."); } { // failure case - bad fee v2 aliceSeq = env.seq(alice); Json::Value jv_one = setup_tx(); - jv_one[jss::tx_json][jss::Fee] = - alice["USD"](10).value().getFullText(); + jv_one[jss::tx_json][jss::Fee] = alice["USD"](10).value().getFullText(); cheri_sign(jv_one); - auto jrr = - env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; + auto jrr = env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); // for the second sign_for, use the returned tx_json with @@ -618,10 +557,7 @@ public: Json::Value jv_submit; jv_submit[jss::tx_json] = jrr[jss::tx_json]; - jrr = env.rpc( - "json", - "submit_multisigned", - to_string(jv_submit))[jss::result]; + jrr = env.rpc("json", "submit_multisigned", to_string(jv_submit))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error] == "internal"); BEAST_EXPECT(jrr[jss::error_message] == "Internal error."); @@ -646,8 +582,7 @@ public: aliceSeq = env.seq(alice); Json::Value jv_one = setup_tx(); cheri_sign(jv_one); - auto jrr = - env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; + auto jrr = env.rpc("json", "sign_for", to_string(jv_one))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); // for the second sign_for, use the returned tx_json with @@ -662,10 +597,7 @@ public: Json::Value jv_submit; jv_submit[jss::tx_json] = jrr[jss::tx_json]; - jrr = env.rpc( - "json", - "submit_multisigned", - to_string(jv_submit))[jss::result]; + jrr = env.rpc("json", "submit_multisigned", to_string(jv_submit))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); @@ -690,16 +622,12 @@ public: { aliceSeq = env.seq(alice); Json::Value jv = setup_tx(); - jv[jss::tx_json][sfSigners.fieldName] = - Json::Value{Json::arrayValue}; + jv[jss::tx_json][sfSigners.fieldName] = Json::Value{Json::arrayValue}; becky_sign(jv); - auto jrr = env.rpc( - "json", "submit_multisigned", to_string(jv))[jss::result]; + auto jrr = env.rpc("json", "submit_multisigned", to_string(jv))[jss::result]; BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "tx_json.Signers array may not be empty."); + BEAST_EXPECT(jrr[jss::error_message] == "tx_json.Signers array may not be empty."); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); } @@ -737,8 +665,7 @@ public: env.close(); // Attach signers to alice. - env(signers(alice, 1, {{becky, 1}, {cheri, 1}, {daria, 1}, {jinni, 1}}), - sig(alie)); + env(signers(alice, 1, {{becky, 1}, {cheri, 1}, {daria, 1}, {jinni, 1}}), sig(alie)); env.close(); env.require(owners(alice, 1)); @@ -771,36 +698,23 @@ public: // Should also work if all signers sign. aliceSeq = env.seq(alice); - env(noop(alice), - fee(5 * baseFee), - msig(becky, Reg{cheri, cher}, Reg{daria, dari}, jinni)); + env(noop(alice), fee(5 * baseFee), msig(becky, Reg{cheri, cher}, Reg{daria, dari}, jinni)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); // Require all signers to sign. - env(signers( - alice, - 0x3FFFC, - {{becky, 0xFFFF}, - {cheri, 0xFFFF}, - {daria, 0xFFFF}, - {jinni, 0xFFFF}}), - sig(alie)); + env(signers(alice, 0x3FFFC, {{becky, 0xFFFF}, {cheri, 0xFFFF}, {daria, 0xFFFF}, {jinni, 0xFFFF}}), sig(alie)); env.close(); env.require(owners(alice, 1)); aliceSeq = env.seq(alice); - env(noop(alice), - fee(9 * baseFee), - msig(becky, Reg{cheri, cher}, Reg{daria, dari}, jinni)); + env(noop(alice), fee(9 * baseFee), msig(becky, Reg{cheri, cher}, Reg{daria, dari}, jinni)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); // Try cheri with both key types. aliceSeq = env.seq(alice); - env(noop(alice), - fee(5 * baseFee), - msig(becky, cheri, Reg{daria, dari}, jinni)); + env(noop(alice), fee(5 * baseFee), msig(becky, cheri, Reg{daria, dari}, jinni)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); @@ -823,24 +737,13 @@ public: aliceSeq = env.seq(alice); env(noop(alice), fee(9 * baseFee), - msig( - becky, - Reg{cheri, cher}, - Reg{daria, dari}, - haunt, - jinni, - phase, - shade, - spook)); + msig(becky, Reg{cheri, cher}, Reg{daria, dari}, haunt, jinni, phase, shade, spook)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); // One signer short should fail. aliceSeq = env.seq(alice); - env(noop(alice), - msig(becky, cheri, haunt, jinni, phase, shade, spook), - fee(8 * baseFee), - ter(tefBAD_QUORUM)); + env(noop(alice), msig(becky, cheri, haunt, jinni, phase, shade, spook), fee(8 * baseFee), ter(tefBAD_QUORUM)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); @@ -880,9 +783,7 @@ public: // Master key tests. // M0: A lone master key cannot be disabled. - env(fset(alice, asfDisableMaster), - sig(alice), - ter(tecNO_ALTERNATIVE_KEY)); + env(fset(alice, asfDisableMaster), sig(alice), ter(tecNO_ALTERNATIVE_KEY)); // Add a regular key. Account const alie{"alie", KeyType::ed25519}; @@ -902,10 +803,7 @@ public: // L0: A lone signer list cannot be removed. auto const baseFee = env.current()->fees().base; - env(signers(alice, jtx::none), - msig(bogie), - fee(2 * baseFee), - ter(tecNO_ALTERNATIVE_KEY)); + env(signers(alice, jtx::none), msig(bogie), fee(2 * baseFee), ter(tecNO_ALTERNATIVE_KEY)); // Enable the master key. env(fclear(alice, asfDisableMaster), msig(bogie), fee(2 * baseFee)); @@ -999,9 +897,7 @@ public: // Multisign a ttPAYMENT. auto const baseFee = env.current()->fees().base; std::uint32_t aliceSeq = env.seq(alice); - env(pay(alice, env.master, XRP(1)), - msig(becky, bogie), - fee(3 * baseFee)); + env(pay(alice, env.master, XRP(1)), msig(becky, bogie), fee(3 * baseFee)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); @@ -1019,10 +915,7 @@ public: BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); // Multisign a ttTRUST_SET - env(trust("alice", USD(100)), - msig(becky, bogie), - fee(3 * baseFee), - require(lines("alice", 1))); + env(trust("alice", USD(100)), msig(becky, bogie), fee(3 * baseFee), require(lines("alice", 1))); env.close(); env.require(owners(alice, 2)); @@ -1033,28 +926,21 @@ public: env.require(balance(gw, alice["USD"](-50))); std::uint32_t const offerSeq = env.seq(alice); - env(offer(alice, XRP(50), USD(50)), - msig(becky, bogie), - fee(3 * baseFee)); + env(offer(alice, XRP(50), USD(50)), msig(becky, bogie), fee(3 * baseFee)); env.close(); env.require(owners(alice, 3)); // Now multisign a ttOFFER_CANCEL canceling the offer we just created. { aliceSeq = env.seq(alice); - env(offer_cancel(alice, offerSeq), - seq(aliceSeq), - msig(becky, bogie), - fee(3 * baseFee)); + env(offer_cancel(alice, offerSeq), seq(aliceSeq), msig(becky, bogie), fee(3 * baseFee)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); env.require(owners(alice, 2)); } // Multisign a ttSIGNER_LIST_SET. - env(signers(alice, 3, {{becky, 1}, {bogie, 1}, {demon, 1}}), - msig(becky, bogie), - fee(3 * baseFee)); + env(signers(alice, 3, {{becky, 1}, {bogie, 1}, {demon, 1}}), msig(becky, bogie), fee(3 * baseFee)); env.close(); env.require(owners(alice, 2)); } @@ -1088,9 +974,7 @@ public: STTx local = *(tx.stx); local.setFieldVL(sfSigningPubKey, Blob()); // Empty SigningPubKey auto const info = submitSTTx(local); - BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Empty SigningPubKey."); + BEAST_EXPECT(info[jss::result][jss::error_exception] == "fails local checks: Empty SigningPubKey."); } { // Single-sign, but invalidate the signature. @@ -1102,9 +986,7 @@ public: local.setFieldVL(sfTxnSignature, badSig); // Signature should fail. auto const info = submitSTTx(local); - BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Invalid signature."); + BEAST_EXPECT(info[jss::result][jss::error_exception] == "fails local checks: Invalid signature."); } { // Single-sign, but invalidate the sequence number. @@ -1115,9 +997,7 @@ public: local.setFieldU32(sfSequence, seq + 1); // Signature should fail. auto const info = submitSTTx(local); - BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Invalid signature."); + BEAST_EXPECT(info[jss::result][jss::error_exception] == "fails local checks: Invalid signature."); } { // Multisign, but leave a nonempty sfSigningPubKey. @@ -1126,8 +1006,7 @@ public: local[sfSigningPubKey] = alice.pk(); // Insert sfSigningPubKey auto const info = submitSTTx(local); BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Cannot both single- and multi-sign."); + info[jss::result][jss::error_exception] == "fails local checks: Cannot both single- and multi-sign."); } { // Both multi- and single-sign with an empty SigningPubKey. @@ -1137,8 +1016,7 @@ public: local.setFieldVL(sfSigningPubKey, Blob()); // Empty SigningPubKey auto const info = submitSTTx(local); BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Cannot both single- and multi-sign."); + info[jss::result][jss::error_exception] == "fails local checks: Cannot both single- and multi-sign."); } { // Multisign but invalidate one of the signatures. @@ -1152,8 +1030,8 @@ public: // Signature should fail. auto const info = submitSTTx(local); BEAST_EXPECT( - info[jss::result][jss::error_exception].asString().find( - "Invalid signature on account r") != std::string::npos); + info[jss::result][jss::error_exception].asString().find("Invalid signature on account r") != + std::string::npos); } { // Multisign with an empty signers array should fail. @@ -1161,9 +1039,7 @@ public: STTx local = *(tx.stx); local.peekFieldArray(sfSigners).clear(); // Empty Signers array. auto const info = submitSTTx(local); - BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Invalid Signers array size."); + BEAST_EXPECT(info[jss::result][jss::error_exception] == "fails local checks: Invalid Signers array size."); } { JTx tx = env.jt( @@ -1206,18 +1082,14 @@ public: bogie)); STTx local = *(tx.stx); auto const info = submitSTTx(local); - BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Invalid Signers array size."); + BEAST_EXPECT(info[jss::result][jss::error_exception] == "fails local checks: Invalid Signers array size."); } { // The account owner may not multisign for themselves. JTx tx = env.jt(noop(alice), fee(2 * baseFee), msig(alice)); STTx local = *(tx.stx); auto const info = submitSTTx(local); - BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Invalid multisigner."); + BEAST_EXPECT(info[jss::result][jss::error_exception] == "fails local checks: Invalid multisigner."); } { // No duplicate multisignatures allowed. @@ -1225,8 +1097,7 @@ public: STTx local = *(tx.stx); auto const info = submitSTTx(local); BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Duplicate Signers not allowed."); + info[jss::result][jss::error_exception] == "fails local checks: Duplicate Signers not allowed."); } { // Multisignatures must be submitted in sorted order. @@ -1237,9 +1108,7 @@ public: std::reverse(signers.begin(), signers.end()); // Signature should fail. auto const info = submitSTTx(local); - BEAST_EXPECT( - info[jss::result][jss::error_exception] == - "fails local checks: Unsorted Signers array."); + BEAST_EXPECT(info[jss::result][jss::error_exception] == "fails local checks: Unsorted Signers array."); } } @@ -1256,10 +1125,7 @@ public: env.close(); auto const baseFee = env.current()->fees().base; - env(noop(alice), - msig(becky, demon), - fee(3 * baseFee), - ter(tefNOT_MULTI_SIGNING)); + env(noop(alice), msig(becky, demon), fee(3 * baseFee), ter(tefNOT_MULTI_SIGNING)); } void @@ -1299,27 +1165,18 @@ public: // Since becky's master key is disabled she can no longer // multisign for alice. - env(noop(alice), - msig(becky), - fee(2 * baseFee), - ter(tefMASTER_DISABLED)); + env(noop(alice), msig(becky), fee(2 * baseFee), ter(tefMASTER_DISABLED)); env.close(); // Becky cannot 2-level multisign for alice. 2-level multisigning // is not supported. - env(noop(alice), - msig(Reg{becky, bogie}), - fee(2 * baseFee), - ter(tefBAD_SIGNATURE)); + env(noop(alice), msig(Reg{becky, bogie}), fee(2 * baseFee), ter(tefBAD_SIGNATURE)); env.close(); // Verify that becky cannot sign with a regular key that she has // not yet enabled. Account const beck{"beck", KeyType::ed25519}; - env(noop(alice), - msig(Reg{becky, beck}), - fee(2 * baseFee), - ter(tefBAD_SIGNATURE)); + env(noop(alice), msig(Reg{becky, beck}), fee(2 * baseFee), ter(tefBAD_SIGNATURE)); env.close(); // Once becky gives herself the regular key, she can sign for alice @@ -1332,10 +1189,7 @@ public: // The presence of becky's regular key does not influence whether she // can 2-level multisign; it still won't work. - env(noop(alice), - msig(Reg{becky, demon}), - fee(2 * baseFee), - ter(tefBAD_SIGNATURE)); + env(noop(alice), msig(Reg{becky, demon}), fee(2 * baseFee), ter(tefBAD_SIGNATURE)); env.close(); } @@ -1381,35 +1235,26 @@ public: BEAST_EXPECT(jvSig2[jss::result][jss::status].asString() == "success"); // Save the hash with one signature for use later. - std::string const hash1 = - jvSig2[jss::result][jss::tx_json][jss::hash].asString(); + std::string const hash1 = jvSig2[jss::result][jss::tx_json][jss::hash].asString(); // Add the next signature and sign again. jvSig2[jss::result][jss::account] = ghost.human(); jvSig2[jss::result][jss::secret] = ghost.name(); - Json::Value jvSubmit = - env.rpc("json", "sign_for", to_string(jvSig2[jss::result])); - BEAST_EXPECT( - jvSubmit[jss::result][jss::status].asString() == "success"); + Json::Value jvSubmit = env.rpc("json", "sign_for", to_string(jvSig2[jss::result])); + BEAST_EXPECT(jvSubmit[jss::result][jss::status].asString() == "success"); // Save the hash with two signatures for use later. - std::string const hash2 = - jvSubmit[jss::result][jss::tx_json][jss::hash].asString(); + std::string const hash2 = jvSubmit[jss::result][jss::tx_json][jss::hash].asString(); BEAST_EXPECT(hash1 != hash2); // Submit the result of the two signatures. - Json::Value jvResult = env.rpc( - "json", "submit_multisigned", to_string(jvSubmit[jss::result])); - BEAST_EXPECT( - jvResult[jss::result][jss::status].asString() == "success"); - BEAST_EXPECT( - jvResult[jss::result][jss::engine_result].asString() == - "tesSUCCESS"); + Json::Value jvResult = env.rpc("json", "submit_multisigned", to_string(jvSubmit[jss::result])); + BEAST_EXPECT(jvResult[jss::result][jss::status].asString() == "success"); + BEAST_EXPECT(jvResult[jss::result][jss::engine_result].asString() == "tesSUCCESS"); // The hash from the submit should be the same as the hash from the // second signing. - BEAST_EXPECT( - hash2 == jvResult[jss::result][jss::tx_json][jss::hash].asString()); + BEAST_EXPECT(hash2 == jvResult[jss::result][jss::tx_json][jss::hash].asString()); env.close(); // The transaction we just submitted should now be available and @@ -1417,9 +1262,7 @@ public: Json::Value jvTx = env.rpc("tx", hash2); BEAST_EXPECT(jvTx[jss::result][jss::status].asString() == "success"); BEAST_EXPECT(jvTx[jss::result][jss::validated].asString() == "true"); - BEAST_EXPECT( - jvTx[jss::result][jss::meta][sfTransactionResult.jsonName] - .asString() == "tesSUCCESS"); + BEAST_EXPECT(jvTx[jss::result][jss::meta][sfTransactionResult.jsonName].asString() == "tesSUCCESS"); } void @@ -1440,18 +1283,14 @@ public: std::uint32_t const aliceSeq = env.seq(alice); // Attach phantom signers to alice using a ticket. - env(signers(alice, 1, {{bogie, 1}, {demon, 1}}), - ticket::use(aliceTicketSeq++)); + env(signers(alice, 1, {{bogie, 1}, {demon, 1}}), ticket::use(aliceTicketSeq++)); env.close(); env.require(tickets(alice, env.seq(alice) - aliceTicketSeq)); BEAST_EXPECT(env.seq(alice) == aliceSeq); // This should work. auto const baseFee = env.current()->fees().base; - env(noop(alice), - msig(bogie, demon), - fee(3 * baseFee), - ticket::use(aliceTicketSeq++)); + env(noop(alice), msig(bogie, demon), fee(3 * baseFee), ticket::use(aliceTicketSeq++)); env.close(); env.require(tickets(alice, env.seq(alice) - aliceTicketSeq)); BEAST_EXPECT(env.seq(alice) == aliceSeq); @@ -1473,13 +1312,11 @@ public: Account const alice{"alice", KeyType::ed25519}; env.fund(XRP(1000), alice); env.close(); - uint8_t tag1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; + uint8_t tag1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; - uint8_t tag2[] = - "hello world some ascii 32b long"; // including 1 byte for NUL + uint8_t tag2[] = "hello world some ascii 32b long"; // including 1 byte for NUL uint256 bogie_tag = xrpl::base_uint<256>::fromVoid(tag1); uint256 demon_tag = xrpl::base_uint<256>::fromVoid(tag2); @@ -1512,17 +1349,13 @@ public: env(noop(alice), msig(demon, demon), fee(3 * baseFee), - rpc("invalidTransaction", - "fails local checks: Duplicate Signers not allowed.")); + rpc("invalidTransaction", "fails local checks: Duplicate Signers not allowed.")); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); // A non-signer should fail. aliceSeq = env.seq(alice); - env(noop(alice), - msig(bogie, spook), - fee(3 * baseFee), - ter(tefBAD_SIGNATURE)); + env(noop(alice), msig(bogie, spook), fee(3 * baseFee), ter(tefBAD_SIGNATURE)); env.close(); BEAST_EXPECT(env.seq(alice) == aliceSeq); @@ -1552,14 +1385,10 @@ public: env.close(); bool const enabled = features[fixInvalidTxFlags]; - testcase( - std::string("SignerListSet flag, fix ") + - (enabled ? "enabled" : "disabled")); + testcase(std::string("SignerListSet flag, fix ") + (enabled ? "enabled" : "disabled")); ter const expected(enabled ? TER(temINVALID_FLAG) : TER(tesSUCCESS)); - env(signers(alice, 2, {{bogie, 1}, {ghost, 1}}), - expected, - txflags(tfPassive)); + env(signers(alice, 2, {{bogie, 1}, {ghost, 1}}), expected, txflags(tfPassive)); env.close(); } diff --git a/src/test/app/NFTokenAuth_test.cpp b/src/test/app/NFTokenAuth_test.cpp index dce8da0042..1e7afc9bb0 100644 --- a/src/test/app/NFTokenAuth_test.cpp +++ b/src/test/app/NFTokenAuth_test.cpp @@ -14,16 +14,12 @@ class NFTokenAuth_test : public beast::unit_test::suite uint32_t xfee = 0u) { using namespace test::jtx; - auto const nftID{ - token::getNextID(env, account, 0u, tfTransferable, xfee)}; - env(token::mint(account, 0), - token::xferFee(xfee), - txflags(tfTransferable)); + auto const nftID{token::getNextID(env, account, 0u, tfTransferable, xfee)}; + env(token::mint(account, 0), token::xferFee(xfee), txflags(tfTransferable)); env.close(); auto const sellIdx = keylet::nftoffer(account, env.seq(account)).key; - env(token::createOffer(account, nftID, currency), - txflags(tfSellNFToken)); + env(token::createOffer(account, nftID, currency), txflags(tfSellNFToken)); env.close(); return std::make_tuple(nftID, sellIdx); @@ -102,18 +98,14 @@ public: auto const [nftID, _] = mintAndOfferNFT(env, A2, drops(1)); // test: check that buyer can't make an offer if they're not authorized. - env(token::createOffer(A1, nftID, USD(10)), - token::owner(A2), - ter(tecUNFUNDED_OFFER)); + env(token::createOffer(A1, nftID, USD(10)), token::owner(A2), ter(tecUNFUNDED_OFFER)); env.close(); // Artificially create an unauthorized trustline with balance. Don't // close ledger before running the actual tests against this trustline. // After ledger is closed, the trustline will not exist. - auto const unauthTrustline = [&](OpenView& view, - beast::Journal) -> bool { - auto const sleA1 = - std::make_shared(keylet::line(A1, G1, G1["USD"].currency)); + auto const unauthTrustline = [&](OpenView& view, beast::Journal) -> bool { + auto const sleA1 = std::make_shared(keylet::line(A1, G1, G1["USD"].currency)); sleA1->setFieldAmount(sfBalance, A1["USD"](-1000)); view.rawInsert(sleA1); return true; @@ -123,9 +115,7 @@ public: if (features[fixEnforceNFTokenTrustlineV2]) { // test: check that buyer can't make an offer even with balance - env(token::createOffer(A1, nftID, USD(10)), - token::owner(A2), - ter(tecNO_AUTH)); + env(token::createOffer(A1, nftID, USD(10)), token::owner(A2), ter(tecNO_AUTH)); } else { @@ -177,10 +167,8 @@ public: // trustline with balance. Don't close ledger before running the actual // tests against this trustline. After ledger is closed, the trustline // will not exist. - auto const unauthTrustline = [&](OpenView& view, - beast::Journal) -> bool { - auto const sleA1 = - std::make_shared(keylet::line(A1, G1, G1["USD"].currency)); + auto const unauthTrustline = [&](OpenView& view, beast::Journal) -> bool { + auto const sleA1 = std::make_shared(keylet::line(A1, G1, G1["USD"].currency)); sleA1->setFieldAmount(sfBalance, A1["USD"](-1000)); view.rawInsert(sleA1); return true; @@ -222,15 +210,11 @@ public: { // test: can't create sell offer if there is no trustline but auth // required - env(token::createOffer(A2, nftID, USD(10)), - txflags(tfSellNFToken), - ter(tecNO_LINE)); + env(token::createOffer(A2, nftID, USD(10)), txflags(tfSellNFToken), ter(tecNO_LINE)); env(trust(A2, limit)); // test: can't create sell offer if not authorized to hold token - env(token::createOffer(A2, nftID, USD(10)), - txflags(tfSellNFToken), - ter(tecNO_AUTH)); + env(token::createOffer(A2, nftID, USD(10)), txflags(tfSellNFToken), ter(tecNO_AUTH)); // Authorizing trustline to make an offer creation possible env(trust(G1, USD(0), A2, tfSetfAuth)); @@ -303,10 +287,8 @@ public: env.close(); // Creating an artificial unauth trustline - auto const unauthTrustline = [&](OpenView& view, - beast::Journal) -> bool { - auto const sleA1 = - std::make_shared(keylet::line(A1, G1, G1["USD"].currency)); + auto const unauthTrustline = [&](OpenView& view, beast::Journal) -> bool { + auto const sleA1 = std::make_shared(keylet::line(A1, G1, G1["USD"].currency)); sleA1->setFieldAmount(sfBalance, A1["USD"](-1000)); view.rawInsert(sleA1); return true; @@ -353,9 +335,7 @@ public: if (features[fixEnforceNFTokenTrustlineV2]) { // test: G1 requires authorization of broker, no trust line exists - env(token::brokerOffers(broker, buyIdx, sellIdx), - token::brokerFee(USD(1)), - ter(tecNO_LINE)); + env(token::brokerOffers(broker, buyIdx, sellIdx), token::brokerFee(USD(1)), ter(tecNO_LINE)); env.close(); // trust line created, but not authorized @@ -363,9 +343,7 @@ public: env.close(); // test: G1 requires authorization of broker - env(token::brokerOffers(broker, buyIdx, sellIdx), - token::brokerFee(USD(1)), - ter(tecNO_AUTH)); + env(token::brokerOffers(broker, buyIdx, sellIdx), token::brokerFee(USD(1)), ter(tecNO_AUTH)); env.close(); // test: can still be brokered without broker fee. @@ -375,8 +353,7 @@ public: else { // Old behavior: broker can receive IOUs without the authorization - env(token::brokerOffers(broker, buyIdx, sellIdx), - token::brokerFee(USD(1))); + env(token::brokerOffers(broker, buyIdx, sellIdx), token::brokerFee(USD(1))); env.close(); BEAST_EXPECT(env.balance(broker, USD) == USD(1)); @@ -425,10 +402,8 @@ public: env(trust(A1, USD(0))); env.close(); - auto const unauthTrustline = [&](OpenView& view, - beast::Journal) -> bool { - auto const sleA1 = - std::make_shared(keylet::line(A1, G1, G1["USD"].currency)); + auto const unauthTrustline = [&](OpenView& view, beast::Journal) -> bool { + auto const sleA1 = std::make_shared(keylet::line(A1, G1, G1["USD"].currency)); sleA1->setFieldAmount(sfBalance, A1["USD"](-1000)); view.rawInsert(sleA1); return true; @@ -438,9 +413,7 @@ public: if (features[fixEnforceNFTokenTrustlineV2]) { // test: G1 requires authorization of A2 - env(token::brokerOffers(broker, buyIdx, sellIdx), - token::brokerFee(USD(1)), - ter(tecNO_AUTH)); + env(token::brokerOffers(broker, buyIdx, sellIdx), token::brokerFee(USD(1)), ter(tecNO_AUTH)); env.close(); } } @@ -491,9 +464,7 @@ public: if (features[fixEnforceNFTokenTrustlineV2]) { // test: G1 requires authorization of broker, no trust line exists - env(token::brokerOffers(broker, buyIdx, sellIdx), - token::brokerFee(USD(1)), - ter(tecNO_LINE)); + env(token::brokerOffers(broker, buyIdx, sellIdx), token::brokerFee(USD(1)), ter(tecNO_LINE)); env.close(); // trust line created, but not authorized @@ -501,9 +472,7 @@ public: env.close(); // test: G1 requires authorization of A2 - env(token::brokerOffers(broker, buyIdx, sellIdx), - token::brokerFee(USD(1)), - ter(tecNO_AUTH)); + env(token::brokerOffers(broker, buyIdx, sellIdx), token::brokerFee(USD(1)), ter(tecNO_AUTH)); env.close(); // test: cannot be brokered even without broker fee. @@ -513,8 +482,7 @@ public: else { // Old behavior: broker can receive IOUs without the authorization - env(token::brokerOffers(broker, buyIdx, sellIdx), - token::brokerFee(USD(1))); + env(token::brokerOffers(broker, buyIdx, sellIdx), token::brokerFee(USD(1))); env.close(); BEAST_EXPECT(env.balance(A2, USD) == USD(10)); @@ -553,8 +521,7 @@ public: // We authorized A1 and A2, but not the minter. // Now mint NFT - auto const [nftID, minterSellIdx] = - mintAndOfferNFT(env, minter, drops(1), 1); + auto const [nftID, minterSellIdx] = mintAndOfferNFT(env, minter, drops(1), 1); env(token::acceptSellOffer(A1, minterSellIdx)); uint256 const sellIdx = keylet::nftoffer(A1, env.seq(A1)).key; @@ -582,8 +549,7 @@ public: using namespace test::jtx; static FeatureBitset const all{testable_amendments()}; - static std::array const features = { - all - fixEnforceNFTokenTrustlineV2, all}; + static std::array const features = {all - fixEnforceNFTokenTrustlineV2, all}; for (auto const feature : features) { diff --git a/src/test/app/NFTokenBurn_test.cpp b/src/test/app/NFTokenBurn_test.cpp index a1c6ffb6de..915bb6ec79 100644 --- a/src/test/app/NFTokenBurn_test.cpp +++ b/src/test/app/NFTokenBurn_test.cpp @@ -32,11 +32,8 @@ class NFTokenBurn_test : public beast::unit_test::suite size_t const tokenCancelCount) { using namespace test::jtx; - uint256 const nftokenID = - token::getNextID(env, owner, 0, tfTransferable); - env(token::mint(owner, 0), - token::uri(std::string(maxTokenURILength, 'u')), - txflags(tfTransferable)); + uint256 const nftokenID = token::getNextID(env, owner, 0, tfTransferable); + env(token::mint(owner, 0), token::uri(std::string(maxTokenURILength, 'u')), txflags(tfTransferable)); env.close(); offerIndexes.reserve(tokenCancelCount); @@ -45,8 +42,7 @@ class NFTokenBurn_test : public beast::unit_test::suite { // Create sell offer offerIndexes.push_back(keylet::nftoffer(owner, env.seq(owner)).key); - env(token::createOffer(owner, nftokenID, drops(1)), - txflags(tfSellNFToken)); + env(token::createOffer(owner, nftokenID, drops(1)), txflags(tfSellNFToken)); env.close(); } @@ -69,12 +65,10 @@ class NFTokenBurn_test : public beast::unit_test::suite jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; { - Json::Value jrr = - env.rpc("json", "ledger_data", to_string(jvParams)); + Json::Value jrr = env.rpc("json", "ledger_data", to_string(jvParams)); // Iterate the state and print all NFTokenPages. - if (!jrr.isMember(jss::result) || - !jrr[jss::result].isMember(jss::state)) + if (!jrr.isMember(jss::result) || !jrr[jss::result].isMember(jss::state)) { std::cout << "No ledger state found!" << std::endl; return; @@ -87,13 +81,10 @@ class NFTokenBurn_test : public beast::unit_test::suite } for (Json::UInt i = 0; i < state.size(); ++i) { - if (state[i].isMember(sfNFTokens.jsonName) && - state[i][sfNFTokens.jsonName].isArray()) + if (state[i].isMember(sfNFTokens.jsonName) && state[i][sfNFTokens.jsonName].isArray()) { - std::uint32_t tokenCount = - state[i][sfNFTokens.jsonName].size(); - std::cout << tokenCount << " NFtokens in page " - << state[i][jss::index].asString() << std::endl; + std::uint32_t tokenCount = state[i][sfNFTokens.jsonName].size(); + std::cout << tokenCount << " NFtokens in page " << state[i][jss::index].asString() << std::endl; if (vol == noisy) { @@ -102,16 +93,10 @@ class NFTokenBurn_test : public beast::unit_test::suite else { if (tokenCount > 0) - std::cout << "first: " - << state[i][sfNFTokens.jsonName][0u] - .toStyledString() - << std::endl; + std::cout << "first: " << state[i][sfNFTokens.jsonName][0u].toStyledString() << std::endl; if (tokenCount > 1) - std::cout - << "last: " - << state[i][sfNFTokens.jsonName][tokenCount - 1] - .toStyledString() - << std::endl; + std::cout << "last: " << state[i][sfNFTokens.jsonName][tokenCount - 1].toStyledString() + << std::endl; } } } @@ -169,18 +154,14 @@ class NFTokenBurn_test : public beast::unit_test::suite // effect of random numbers, but we want the test to run the same // way each time. std::mt19937 engine; - std::uniform_int_distribution feeDist( - decltype(maxTransferFee){}, maxTransferFee); + std::uniform_int_distribution feeDist(decltype(maxTransferFee){}, maxTransferFee); alice.nfts.reserve(105); while (alice.nfts.size() < 105) { std::uint16_t const xferFee = feeDist(engine); - alice.nfts.push_back(token::getNextID( - env, alice, 0u, tfTransferable | tfBurnable, xferFee)); - env(token::mint(alice), - txflags(tfTransferable | tfBurnable), - token::xferFee(xferFee)); + alice.nfts.push_back(token::getNextID(env, alice, 0u, tfTransferable | tfBurnable, xferFee)); + env(token::mint(alice), txflags(tfTransferable | tfBurnable), token::xferFee(xferFee)); env.close(); } @@ -188,8 +169,7 @@ class NFTokenBurn_test : public beast::unit_test::suite while (minter.nfts.size() < 105) { std::uint16_t const xferFee = feeDist(engine); - minter.nfts.push_back(token::getNextID( - env, alice, 0u, tfTransferable | tfBurnable, xferFee)); + minter.nfts.push_back(token::getNextID(env, alice, 0u, tfTransferable | tfBurnable, xferFee)); env(token::mint(minter), txflags(tfTransferable | tfBurnable), token::xferFee(xferFee), @@ -207,10 +187,8 @@ class NFTokenBurn_test : public beast::unit_test::suite { // We do the same work on alice and minter, so make a lambda. auto xferNFT = [&env, &becky](AcctStat& acct, auto& iter) { - uint256 offerIndex = - keylet::nftoffer(acct.acct, env.seq(acct.acct)).key; - env(token::createOffer(acct, *iter, XRP(0)), - txflags(tfSellNFToken)); + uint256 offerIndex = keylet::nftoffer(acct.acct, env.seq(acct.acct)).key; + env(token::createOffer(acct, *iter, XRP(0)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(becky, offerIndex)); env.close(); @@ -232,33 +210,24 @@ class NFTokenBurn_test : public beast::unit_test::suite // Next we'll create offers for all of those NFTs. This calls for // another lambda. - auto addOffers = - [&env](AcctStat& owner, AcctStat& other1, AcctStat& other2) { - for (uint256 nft : owner.nfts) - { - // Create sell offers for owner. - env(token::createOffer(owner, nft, drops(1)), - txflags(tfSellNFToken), - token::destination(other1)); - env(token::createOffer(owner, nft, drops(1)), - txflags(tfSellNFToken), - token::destination(other2)); - env.close(); + auto addOffers = [&env](AcctStat& owner, AcctStat& other1, AcctStat& other2) { + for (uint256 nft : owner.nfts) + { + // Create sell offers for owner. + env(token::createOffer(owner, nft, drops(1)), txflags(tfSellNFToken), token::destination(other1)); + env(token::createOffer(owner, nft, drops(1)), txflags(tfSellNFToken), token::destination(other2)); + env.close(); - // Create buy offers for other1 and other2. - env(token::createOffer(other1, nft, drops(1)), - token::owner(owner)); - env(token::createOffer(other2, nft, drops(1)), - token::owner(owner)); - env.close(); + // Create buy offers for other1 and other2. + env(token::createOffer(other1, nft, drops(1)), token::owner(owner)); + env(token::createOffer(other2, nft, drops(1)), token::owner(owner)); + env.close(); - env(token::createOffer(other2, nft, drops(2)), - token::owner(owner)); - env(token::createOffer(other1, nft, drops(2)), - token::owner(owner)); - env.close(); - } - }; + env(token::createOffer(other2, nft, drops(2)), token::owner(owner)); + env(token::createOffer(other1, nft, drops(2)), token::owner(owner)); + env.close(); + } + }; addOffers(alice, becky, minter); addOffers(becky, minter, alice); addOffers(minter, alice, becky); @@ -273,8 +242,7 @@ class NFTokenBurn_test : public beast::unit_test::suite std::uniform_int_distribution acctDist(0, 2); std::uniform_int_distribution mintDist(0, 1); - while (stats[0]->nfts.size() > 0 || stats[1]->nfts.size() > 0 || - stats[2]->nfts.size() > 0) + while (stats[0]->nfts.size() > 0 || stats[1]->nfts.size() > 0 || stats[2]->nfts.size() > 0) { // Pick an account to burn an nft. If there are no nfts left // pick again. @@ -283,8 +251,7 @@ class NFTokenBurn_test : public beast::unit_test::suite continue; // Pick one of the nfts. - std::uniform_int_distribution nftDist( - 0lu, owner.nfts.size() - 1); + std::uniform_int_distribution nftDist(0lu, owner.nfts.size() - 1); auto nftIter = owner.nfts.begin() + nftDist(engine); uint256 const nft = *nftIter; owner.nfts.erase(nftIter); @@ -292,10 +259,9 @@ class NFTokenBurn_test : public beast::unit_test::suite // Decide which of the accounts should burn the nft. If the // owner is becky then any of the three accounts can burn. // Otherwise either alice or minter can burn. - AcctStat& burner = owner.acct == becky.acct - ? *(stats[acctDist(engine)]) - : mintDist(engine) ? alice - : minter; + AcctStat& burner = owner.acct == becky.acct ? *(stats[acctDist(engine)]) + : mintDist(engine) ? alice + : minter; if (owner.acct == burner.acct) env(token::burn(burner, nft)); @@ -350,19 +316,13 @@ class NFTokenBurn_test : public beast::unit_test::suite // creation of NFT pages that are completely full. This lambda // tells us the taxon value we should pass in in order for the // internal representation to match the passed in value. - auto internalTaxon = [&env]( - Account const& acct, - std::uint32_t taxon) -> std::uint32_t { - std::uint32_t tokenSeq = - env.le(acct)->at(~sfMintedNFTokens).value_or(0); + auto internalTaxon = [&env](Account const& acct, std::uint32_t taxon) -> std::uint32_t { + std::uint32_t tokenSeq = env.le(acct)->at(~sfMintedNFTokens).value_or(0); // We must add FirstNFTokenSequence. - tokenSeq += env.le(acct) - ->at(~sfFirstNFTokenSequence) - .value_or(env.seq(acct)); + tokenSeq += env.le(acct)->at(~sfFirstNFTokenSequence).value_or(env.seq(acct)); - return toUInt32( - nft::cipheredTaxon(tokenSeq, nft::toTaxon(taxon))); + return toUInt32(nft::cipheredTaxon(tokenSeq, nft::toTaxon(taxon))); }; for (std::uint32_t i = 0; i < 96; ++i) @@ -390,19 +350,16 @@ class NFTokenBurn_test : public beast::unit_test::suite jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; { - Json::Value jrr = - env.rpc("json", "ledger_data", to_string(jvParams)); + Json::Value jrr = env.rpc("json", "ledger_data", to_string(jvParams)); Json::Value& state = jrr[jss::result][jss::state]; int pageCount = 0; for (Json::UInt i = 0; i < state.size(); ++i) { - if (state[i].isMember(sfNFTokens.jsonName) && - state[i][sfNFTokens.jsonName].isArray()) + if (state[i].isMember(sfNFTokens.jsonName) && state[i][sfNFTokens.jsonName].isArray()) { - BEAST_EXPECT( - state[i][sfNFTokens.jsonName].size() == 32); + BEAST_EXPECT(state[i][sfNFTokens.jsonName].size() == 32); ++pageCount; } } @@ -435,8 +392,7 @@ class NFTokenBurn_test : public beast::unit_test::suite jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; { - Json::Value jrr = - env.rpc("json", "ledger_data", to_string(jvParams)); + Json::Value jrr = env.rpc("json", "ledger_data", to_string(jvParams)); Json::Value& state = jrr[jss::result][jss::state]; @@ -461,17 +417,13 @@ class NFTokenBurn_test : public beast::unit_test::suite if (!BEAST_EXPECT(lastNFTokenPage)) return; - uint256 const middleNFTokenPageIndex = - lastNFTokenPage->at(sfPreviousPageMin); - auto middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + uint256 const middleNFTokenPageIndex = lastNFTokenPage->at(sfPreviousPageMin); + auto middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); if (!BEAST_EXPECT(middleNFTokenPage)) return; - uint256 const firstNFTokenPageIndex = - middleNFTokenPage->at(sfPreviousPageMin); - auto firstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), firstNFTokenPageIndex)); + uint256 const firstNFTokenPageIndex = middleNFTokenPage->at(sfPreviousPageMin); + auto firstNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); if (!BEAST_EXPECT(firstNFTokenPage)) return; @@ -489,8 +441,7 @@ class NFTokenBurn_test : public beast::unit_test::suite if (!BEAST_EXPECT(lastNFTokenPage)) return; - BEAST_EXPECT( - lastNFTokenPage->getFieldArray(sfNFTokens).size() == 1); + BEAST_EXPECT(lastNFTokenPage->getFieldArray(sfNFTokens).size() == 1); BEAST_EXPECT(lastNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!lastNFTokenPage->isFieldPresent(sfNextPageMin)); @@ -507,30 +458,21 @@ class NFTokenBurn_test : public beast::unit_test::suite // are moved into the last page. lastNFTokenPage = env.le(keylet::nftpage_max(alice)); BEAST_EXPECT(lastNFTokenPage); - BEAST_EXPECT( - lastNFTokenPage->at(~sfPreviousPageMin) == - firstNFTokenPageIndex); + BEAST_EXPECT(lastNFTokenPage->at(~sfPreviousPageMin) == firstNFTokenPageIndex); BEAST_EXPECT(!lastNFTokenPage->isFieldPresent(sfNextPageMin)); - BEAST_EXPECT( - lastNFTokenPage->getFieldArray(sfNFTokens).size() == 32); + BEAST_EXPECT(lastNFTokenPage->getFieldArray(sfNFTokens).size() == 32); // The "middle" page should be gone. - middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); BEAST_EXPECT(!middleNFTokenPage); // The "first" page should still be present and linked to // the last page. - firstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), firstNFTokenPageIndex)); + firstNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); BEAST_EXPECT(firstNFTokenPage); - BEAST_EXPECT( - !firstNFTokenPage->isFieldPresent(sfPreviousPageMin)); - BEAST_EXPECT( - firstNFTokenPage->at(~sfNextPageMin) == - lastNFTokenPage->key()); - BEAST_EXPECT( - lastNFTokenPage->getFieldArray(sfNFTokens).size() == 32); + BEAST_EXPECT(!firstNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(firstNFTokenPage->at(~sfNextPageMin) == lastNFTokenPage->key()); + BEAST_EXPECT(lastNFTokenPage->getFieldArray(sfNFTokens).size() == 32); } else { @@ -542,12 +484,10 @@ class NFTokenBurn_test : public beast::unit_test::suite // The "middle" page is still present, but has lost the // NextPageMin field. - middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); if (!BEAST_EXPECT(middleNFTokenPage)) return; - BEAST_EXPECT( - middleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(middleNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!middleNFTokenPage->isFieldPresent(sfNextPageMin)); } @@ -576,17 +516,13 @@ class NFTokenBurn_test : public beast::unit_test::suite if (!BEAST_EXPECT(lastNFTokenPage)) return; - uint256 const middleNFTokenPageIndex = - lastNFTokenPage->at(sfPreviousPageMin); - auto middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + uint256 const middleNFTokenPageIndex = lastNFTokenPage->at(sfPreviousPageMin); + auto middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); if (!BEAST_EXPECT(middleNFTokenPage)) return; - uint256 const firstNFTokenPageIndex = - middleNFTokenPage->at(sfPreviousPageMin); - auto firstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), firstNFTokenPageIndex)); + uint256 const firstNFTokenPageIndex = middleNFTokenPage->at(sfPreviousPageMin); + auto firstNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); if (!BEAST_EXPECT(firstNFTokenPage)) return; @@ -601,21 +537,15 @@ class NFTokenBurn_test : public beast::unit_test::suite // Verify that middle page is gone and the links in the two // remaining pages are correct. - middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); BEAST_EXPECT(!middleNFTokenPage); lastNFTokenPage = env.le(keylet::nftpage_max(alice)); BEAST_EXPECT(!lastNFTokenPage->isFieldPresent(sfNextPageMin)); - BEAST_EXPECT( - lastNFTokenPage->getFieldH256(sfPreviousPageMin) == - firstNFTokenPageIndex); + BEAST_EXPECT(lastNFTokenPage->getFieldH256(sfPreviousPageMin) == firstNFTokenPageIndex); - firstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), firstNFTokenPageIndex)); - BEAST_EXPECT( - firstNFTokenPage->getFieldH256(sfNextPageMin) == - keylet::nftpage_max(alice).key); + firstNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); + BEAST_EXPECT(firstNFTokenPage->getFieldH256(sfNextPageMin) == keylet::nftpage_max(alice).key); BEAST_EXPECT(!firstNFTokenPage->isFieldPresent(sfPreviousPageMin)); // Burn the remaining nfts. @@ -642,17 +572,13 @@ class NFTokenBurn_test : public beast::unit_test::suite if (!BEAST_EXPECT(lastNFTokenPage)) return; - uint256 const middleNFTokenPageIndex = - lastNFTokenPage->at(sfPreviousPageMin); - auto middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + uint256 const middleNFTokenPageIndex = lastNFTokenPage->at(sfPreviousPageMin); + auto middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); if (!BEAST_EXPECT(middleNFTokenPage)) return; - uint256 const firstNFTokenPageIndex = - middleNFTokenPage->at(sfPreviousPageMin); - auto firstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), firstNFTokenPageIndex)); + uint256 const firstNFTokenPageIndex = middleNFTokenPage->at(sfPreviousPageMin); + auto firstNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); if (!BEAST_EXPECT(firstNFTokenPage)) return; @@ -666,13 +592,11 @@ class NFTokenBurn_test : public beast::unit_test::suite } // Verify the first page is gone. - firstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), firstNFTokenPageIndex)); + firstNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); BEAST_EXPECT(!firstNFTokenPage); // Check the links in the other two pages. - middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); if (!BEAST_EXPECT(middleNFTokenPage)) return; BEAST_EXPECT(!middleNFTokenPage->isFieldPresent(sfPreviousPageMin)); @@ -701,20 +625,16 @@ class NFTokenBurn_test : public beast::unit_test::suite // are moved into the last page. lastNFTokenPage = env.le(keylet::nftpage_max(alice)); BEAST_EXPECT(lastNFTokenPage); - BEAST_EXPECT( - !lastNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!lastNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!lastNFTokenPage->isFieldPresent(sfNextPageMin)); - BEAST_EXPECT( - lastNFTokenPage->getFieldArray(sfNFTokens).size() == 32); + BEAST_EXPECT(lastNFTokenPage->getFieldArray(sfNFTokens).size() == 32); // The "middle" page should be gone. - middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); BEAST_EXPECT(!middleNFTokenPage); // The "first" page should still be gone. - firstNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), firstNFTokenPageIndex)); + firstNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); BEAST_EXPECT(!firstNFTokenPage); } else @@ -727,12 +647,10 @@ class NFTokenBurn_test : public beast::unit_test::suite // The "middle" page is still present, but has lost the // NextPageMin field. - middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); if (!BEAST_EXPECT(middleNFTokenPage)) return; - BEAST_EXPECT( - !middleNFTokenPage->isFieldPresent(sfPreviousPageMin)); + BEAST_EXPECT(!middleNFTokenPage->isFieldPresent(sfPreviousPageMin)); BEAST_EXPECT(!middleNFTokenPage->isFieldPresent(sfNextPageMin)); } @@ -779,40 +697,28 @@ class NFTokenBurn_test : public beast::unit_test::suite STTx tx{ttACCOUNT_SET, [](STObject&) {}}; test::StreamSink sink{beast::severities::kWarning}; beast::Journal jlog{sink}; - ApplyContext ac{ - env.app(), - ov, - tx, - tesSUCCESS, - env.current()->fees().base, - tapNONE, - jlog}; + ApplyContext ac{env.app(), ov, tx, tesSUCCESS, env.current()->fees().base, tapNONE, jlog}; // Verify that the last page is present and contains one NFT. - auto lastNFTokenPage = - ac.view().peek(keylet::nftpage_max(alice)); + auto lastNFTokenPage = ac.view().peek(keylet::nftpage_max(alice)); if (!BEAST_EXPECT(lastNFTokenPage)) return; - BEAST_EXPECT( - lastNFTokenPage->getFieldArray(sfNFTokens).size() == 1); + BEAST_EXPECT(lastNFTokenPage->getFieldArray(sfNFTokens).size() == 1); // Erase that last page. ac.view().erase(lastNFTokenPage); // Exercise the invariant. TER terActual = tesSUCCESS; - for (TER const& terExpect : - {TER(tecINVARIANT_FAILED), TER(tefINVARIANT_FAILED)}) + for (TER const& terExpect : {TER(tecINVARIANT_FAILED), TER(tefINVARIANT_FAILED)}) { terActual = ac.checkInvariants(terActual, XRPAmount{}); BEAST_EXPECT(terExpect == terActual); - BEAST_EXPECT( - sink.messages().str().starts_with("Invariant failed:")); + BEAST_EXPECT(sink.messages().str().starts_with("Invariant failed:")); // uncomment to log the invariant failure message // log << " --> " << sink.messages().str() << std::endl; BEAST_EXPECT( - sink.messages().str().find( - "Last NFT page deleted with non-empty directory") != + sink.messages().str().find("Last NFT page deleted with non-empty directory") != std::string::npos); } } @@ -823,21 +729,12 @@ class NFTokenBurn_test : public beast::unit_test::suite STTx tx{ttACCOUNT_SET, [](STObject&) {}}; test::StreamSink sink{beast::severities::kWarning}; beast::Journal jlog{sink}; - ApplyContext ac{ - env.app(), - ov, - tx, - tesSUCCESS, - env.current()->fees().base, - tapNONE, - jlog}; + ApplyContext ac{env.app(), ov, tx, tesSUCCESS, env.current()->fees().base, tapNONE, jlog}; // Verify that the middle page is present. - auto lastNFTokenPage = - ac.view().peek(keylet::nftpage_max(alice)); - auto middleNFTokenPage = ac.view().peek(keylet::nftpage( - keylet::nftpage_min(alice), - lastNFTokenPage->getFieldH256(sfPreviousPageMin))); + auto lastNFTokenPage = ac.view().peek(keylet::nftpage_max(alice)); + auto middleNFTokenPage = ac.view().peek( + keylet::nftpage(keylet::nftpage_min(alice), lastNFTokenPage->getFieldH256(sfPreviousPageMin))); BEAST_EXPECT(middleNFTokenPage); // Remove the NextMinPage link from the middle page to fire @@ -847,18 +744,14 @@ class NFTokenBurn_test : public beast::unit_test::suite // Exercise the invariant. TER terActual = tesSUCCESS; - for (TER const& terExpect : - {TER(tecINVARIANT_FAILED), TER(tefINVARIANT_FAILED)}) + for (TER const& terExpect : {TER(tecINVARIANT_FAILED), TER(tefINVARIANT_FAILED)}) { terActual = ac.checkInvariants(terActual, XRPAmount{}); BEAST_EXPECT(terExpect == terActual); - BEAST_EXPECT( - sink.messages().str().starts_with("Invariant failed:")); + BEAST_EXPECT(sink.messages().str().starts_with("Invariant failed:")); // uncomment to log the invariant failure message // log << " --> " << sink.messages().str() << std::endl; - BEAST_EXPECT( - sink.messages().str().find("Lost NextMinPage link") != - std::string::npos); + BEAST_EXPECT(sink.messages().str().find("Lost NextMinPage link") != std::string::npos); } } } @@ -887,8 +780,7 @@ class NFTokenBurn_test : public beast::unit_test::suite // When the token is burned, 498 sell offers and 1 buy offer are // removed. In total, 499 offers are removed std::vector offerIndexes; - auto const nftokenID = createNftAndOffers( - env, alice, offerIndexes, maxDeletableTokenOfferEntries - 2); + auto const nftokenID = createNftAndOffers(env, alice, offerIndexes, maxDeletableTokenOfferEntries - 2); // Verify all sell offers are present in the ledger. for (uint256 const& offerIndex : offerIndexes) @@ -897,10 +789,8 @@ class NFTokenBurn_test : public beast::unit_test::suite } // Becky creates a buy offer - uint256 const beckyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftokenID, drops(1)), - token::owner(alice)); + uint256 const beckyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftokenID, drops(1)), token::owner(alice)); env.close(); // Burn the token @@ -936,8 +826,7 @@ class NFTokenBurn_test : public beast::unit_test::suite // After we burn the token, 500 of the sell offers should be // removed, and one is left over std::vector offerIndexes; - auto const nftokenID = createNftAndOffers( - env, alice, offerIndexes, maxDeletableTokenOfferEntries + 1); + auto const nftokenID = createNftAndOffers(env, alice, offerIndexes, maxDeletableTokenOfferEntries + 1); // Verify all sell offers are present in the ledger. for (uint256 const& offerIndex : offerIndexes) @@ -980,8 +869,7 @@ class NFTokenBurn_test : public beast::unit_test::suite // are removed. // In total, 500 offers are removed std::vector offerIndexes; - auto const nftokenID = createNftAndOffers( - env, alice, offerIndexes, maxDeletableTokenOfferEntries - 1); + auto const nftokenID = createNftAndOffers(env, alice, offerIndexes, maxDeletableTokenOfferEntries - 1); // Verify all sell offers are present in the ledger. for (uint256 const& offerIndex : offerIndexes) @@ -990,11 +878,9 @@ class NFTokenBurn_test : public beast::unit_test::suite } // becky creates 2 buy offers - env(token::createOffer(becky, nftokenID, drops(1)), - token::owner(alice)); + env(token::createOffer(becky, nftokenID, drops(1)), token::owner(alice)); env.close(); - env(token::createOffer(becky, nftokenID, drops(1)), - token::owner(alice)); + env(token::createOffer(becky, nftokenID, drops(1)), token::owner(alice)); env.close(); // Burn the token @@ -1052,19 +938,13 @@ class NFTokenBurn_test : public beast::unit_test::suite // creation of NFT pages that are completely full. This lambda // tells us the taxon value we should pass in in order for the // internal representation to match the passed in value. - auto internalTaxon = [&env]( - Account const& acct, - std::uint32_t taxon) -> std::uint32_t { - std::uint32_t tokenSeq = - env.le(acct)->at(~sfMintedNFTokens).value_or(0); + auto internalTaxon = [&env](Account const& acct, std::uint32_t taxon) -> std::uint32_t { + std::uint32_t tokenSeq = env.le(acct)->at(~sfMintedNFTokens).value_or(0); // We must add FirstNFTokenSequence. - tokenSeq += env.le(acct) - ->at(~sfFirstNFTokenSequence) - .value_or(env.seq(acct)); + tokenSeq += env.le(acct)->at(~sfFirstNFTokenSequence).value_or(env.seq(acct)); - return toUInt32( - nft::cipheredTaxon(tokenSeq, nft::toTaxon(taxon))); + return toUInt32(nft::cipheredTaxon(tokenSeq, nft::toTaxon(taxon))); }; for (std::uint32_t i = 0; i < 96; ++i) @@ -1077,16 +957,13 @@ class NFTokenBurn_test : public beast::unit_test::suite // populated. std::uint32_t const intTaxon = (i / 16) + (i & 0b10000 ? 2 : 0); uint32_t const extTaxon = internalTaxon(minter, intTaxon); - nfts.push_back( - token::getNextID(env, minter, extTaxon, tfTransferable)); + nfts.push_back(token::getNextID(env, minter, extTaxon, tfTransferable)); env(token::mint(minter, extTaxon), txflags(tfTransferable)); env.close(); // Minter creates an offer for the NFToken. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nfts.back(), XRP(0)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nfts.back(), XRP(0)), txflags(tfSellNFToken)); env.close(); // alice accepts the offer. @@ -1104,19 +981,16 @@ class NFTokenBurn_test : public beast::unit_test::suite jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; { - Json::Value jrr = - env.rpc("json", "ledger_data", to_string(jvParams)); + Json::Value jrr = env.rpc("json", "ledger_data", to_string(jvParams)); Json::Value& state = jrr[jss::result][jss::state]; int pageCount = 0; for (Json::UInt i = 0; i < state.size(); ++i) { - if (state[i].isMember(sfNFTokens.jsonName) && - state[i][sfNFTokens.jsonName].isArray()) + if (state[i].isMember(sfNFTokens.jsonName) && state[i][sfNFTokens.jsonName].isArray()) { - BEAST_EXPECT( - state[i][sfNFTokens.jsonName].size() == 32); + BEAST_EXPECT(state[i][sfNFTokens.jsonName].size() == 32); ++pageCount; } } @@ -1138,17 +1012,13 @@ class NFTokenBurn_test : public beast::unit_test::suite if (!BEAST_EXPECT(lastNFTokenPage)) return; - uint256 const middleNFTokenPageIndex = - lastNFTokenPage->at(sfPreviousPageMin); - auto middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + uint256 const middleNFTokenPageIndex = lastNFTokenPage->at(sfPreviousPageMin); + auto middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); if (!BEAST_EXPECT(middleNFTokenPage)) return; - uint256 const firstNFTokenPageIndex = - middleNFTokenPage->at(sfPreviousPageMin); - auto firstNFTokenPage = env.le( - keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); + uint256 const firstNFTokenPageIndex = middleNFTokenPage->at(sfPreviousPageMin); + auto firstNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), firstNFTokenPageIndex)); if (!BEAST_EXPECT(firstNFTokenPage)) return; @@ -1160,10 +1030,8 @@ class NFTokenBurn_test : public beast::unit_test::suite nfts.pop_back(); // alice creates an offer for the NFToken. - uint256 const aliceOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, last32NFTs.back(), XRP(0)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, last32NFTs.back(), XRP(0)), txflags(tfSellNFToken)); env.close(); // minter accepts the offer. @@ -1180,8 +1048,7 @@ class NFTokenBurn_test : public beast::unit_test::suite // The "middle" page is still present, but has lost the // NextPageMin field. - middleNFTokenPage = env.le(keylet::nftpage( - keylet::nftpage_min(alice), middleNFTokenPageIndex)); + middleNFTokenPage = env.le(keylet::nftpage(keylet::nftpage_min(alice), middleNFTokenPageIndex)); if (!BEAST_EXPECT(middleNFTokenPage)) return; BEAST_EXPECT(middleNFTokenPage->isFieldPresent(sfPreviousPageMin)); @@ -1189,19 +1056,15 @@ class NFTokenBurn_test : public beast::unit_test::suite // Attempt to delete alice's account, but fail because she owns NFTs. auto const acctDelFee{drops(env.current()->fees().increment)}; - env(acctdelete(alice, minter), - fee(acctDelFee), - ter(tecHAS_OBLIGATIONS)); + env(acctdelete(alice, minter), fee(acctDelFee), ter(tecHAS_OBLIGATIONS)); env.close(); // minter sells the last 32 NFTs back to alice. for (uint256 nftID : last32NFTs) { // minter creates an offer for the NFToken. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, XRP(0)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, XRP(0)), txflags(tfSellNFToken)); env.close(); // alice accepts the offer. @@ -1220,8 +1083,7 @@ class NFTokenBurn_test : public beast::unit_test::suite return env.rpc("json", "account_objects", to_string(params)); }(); BEAST_EXPECT(!acctObjs.isMember(jss::marker)); - BEAST_EXPECT( - acctObjs[jss::result][jss::account_objects].size() == 2); + BEAST_EXPECT(acctObjs[jss::result][jss::account_objects].size() == 2); } { // Try the account_nfts RPC command. It only returns 64 NFTs @@ -1233,8 +1095,7 @@ class NFTokenBurn_test : public beast::unit_test::suite return env.rpc("json", "account_nfts", to_string(params)); }(); BEAST_EXPECT(!aliceNFTs.isMember(jss::marker)); - BEAST_EXPECT( - aliceNFTs[jss::result][jss::account_nfts].size() == 64); + BEAST_EXPECT(aliceNFTs[jss::result][jss::account_nfts].size() == 64); } } diff --git a/src/test/app/NFTokenDir_test.cpp b/src/test/app/NFTokenDir_test.cpp index 9718a5d073..65bd97ec32 100644 --- a/src/test/app/NFTokenDir_test.cpp +++ b/src/test/app/NFTokenDir_test.cpp @@ -28,12 +28,10 @@ class NFTokenDir_test : public beast::unit_test::suite jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; { - Json::Value jrr = - env.rpc("json", "ledger_data", to_string(jvParams)); + Json::Value jrr = env.rpc("json", "ledger_data", to_string(jvParams)); // Iterate the state and print all NFTokenPages. - if (!jrr.isMember(jss::result) || - !jrr[jss::result].isMember(jss::state)) + if (!jrr.isMember(jss::result) || !jrr[jss::result].isMember(jss::state)) { std::cout << "No ledger state found!" << std::endl; return; @@ -46,13 +44,10 @@ class NFTokenDir_test : public beast::unit_test::suite } for (Json::UInt i = 0; i < state.size(); ++i) { - if (state[i].isMember(sfNFTokens.jsonName) && - state[i][sfNFTokens.jsonName].isArray()) + if (state[i].isMember(sfNFTokens.jsonName) && state[i][sfNFTokens.jsonName].isArray()) { - std::uint32_t tokenCount = - state[i][sfNFTokens.jsonName].size(); - std::cout << tokenCount << " NFtokens in page " - << state[i][jss::index].asString() << std::endl; + std::uint32_t tokenCount = state[i][sfNFTokens.jsonName].size(); + std::cout << tokenCount << " NFtokens in page " << state[i][jss::index].asString() << std::endl; if (vol == noisy) { @@ -61,16 +56,10 @@ class NFTokenDir_test : public beast::unit_test::suite else { if (tokenCount > 0) - std::cout << "first: " - << state[i][sfNFTokens.jsonName][0u] - .toStyledString() - << std::endl; + std::cout << "first: " << state[i][sfNFTokens.jsonName][0u].toStyledString() << std::endl; if (tokenCount > 1) - std::cout - << "last: " - << state[i][sfNFTokens.jsonName][tokenCount - 1] - .toStyledString() - << std::endl; + std::cout << "last: " << state[i][sfNFTokens.jsonName][tokenCount - 1].toStyledString() + << std::endl; } } } @@ -106,10 +95,8 @@ class NFTokenDir_test : public beast::unit_test::suite nftIDs.reserve(nftCount); for (int i = 0; i < nftCount; ++i) { - std::uint32_t taxon = - toUInt32(nft::cipheredTaxon(i, nft::toTaxon(0))); - nftIDs.emplace_back( - token::getNextID(env, issuer, taxon, tfTransferable)); + std::uint32_t taxon = toUInt32(nft::cipheredTaxon(i, nft::toTaxon(0))); + nftIDs.emplace_back(token::getNextID(env, issuer, taxon, tfTransferable)); env(token::mint(issuer, taxon), txflags(tfTransferable)); env.close(); } @@ -120,8 +107,7 @@ class NFTokenDir_test : public beast::unit_test::suite for (uint256 const& nftID : nftIDs) { offers.emplace_back(keylet::nftoffer(issuer, env.seq(issuer)).key); - env(token::createOffer(issuer, nftID, XRP(0)), - txflags((tfSellNFToken))); + env(token::createOffer(issuer, nftID, XRP(0)), txflags((tfSellNFToken))); env.close(); } @@ -153,203 +139,187 @@ class NFTokenDir_test : public beast::unit_test::suite // with identical 96-low-bits are all kept on the same page. // Lambda that exercises the lopsided splits. - auto exerciseLopsided = - [this, - &features](std::initializer_list seeds) { - Env env{*this, features}; + auto exerciseLopsided = [this, &features](std::initializer_list seeds) { + Env env{*this, features}; - // Eventually all of the NFTokens will be owned by buyer. - Account const buyer{"buyer"}; - env.fund(XRP(10000), buyer); + // Eventually all of the NFTokens will be owned by buyer. + Account const buyer{"buyer"}; + env.fund(XRP(10000), buyer); + env.close(); + + // Create accounts for all of the seeds and fund those accounts. + std::vector accounts; + accounts.reserve(seeds.size()); + for (std::string_view seed : seeds) + { + Account const& account = accounts.emplace_back(Account::base58Seed, std::string(seed)); + env.fund(XRP(10000), account); + + // Do not close the ledger inside the loop. If accounts are + // initialized at different ledgers, they will have + // different account sequences. That would cause the + // accounts to have different NFTokenID sequence numbers. + } + env.close(); + + // All of the accounts create one NFT and and offer that NFT to + // buyer. + std::vector nftIDs; + std::vector offers; + offers.reserve(accounts.size()); + for (Account const& account : accounts) + { + // Mint the NFT. + uint256 const& nftID = nftIDs.emplace_back(token::getNextID(env, account, 0, tfTransferable)); + env(token::mint(account, 0), txflags(tfTransferable)); env.close(); - // Create accounts for all of the seeds and fund those accounts. - std::vector accounts; - accounts.reserve(seeds.size()); - for (std::string_view seed : seeds) - { - Account const& account = accounts.emplace_back( - Account::base58Seed, std::string(seed)); - env.fund(XRP(10000), account); + // Create an offer to give the NFT to buyer for free. + offers.emplace_back(keylet::nftoffer(account, env.seq(account)).key); + env(token::createOffer(account, nftID, XRP(0)), token::destination(buyer), txflags((tfSellNFToken))); + } + env.close(); - // Do not close the ledger inside the loop. If accounts are - // initialized at different ledgers, they will have - // different account sequences. That would cause the - // accounts to have different NFTokenID sequence numbers. - } + // buyer accepts all of the offers. + for (uint256 const& offer : offers) + { + env(token::acceptSellOffer(buyer, offer)); + env.close(); + } + + // This can be a good time to look at the NFT pages. + // printNFTPages(env, noisy); + + // Verify that all NFTs are owned by buyer and findable in the + // ledger by having buyer create sell offers for all of their + // NFTs. Attempting to sell an offer that the ledger can't find + // generates a non-tesSUCCESS error code. + for (uint256 const& nftID : nftIDs) + { + uint256 const offerID = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, XRP(100)), txflags(tfSellNFToken)); env.close(); - // All of the accounts create one NFT and and offer that NFT to - // buyer. - std::vector nftIDs; - std::vector offers; - offers.reserve(accounts.size()); - for (Account const& account : accounts) - { - // Mint the NFT. - uint256 const& nftID = nftIDs.emplace_back( - token::getNextID(env, account, 0, tfTransferable)); - env(token::mint(account, 0), txflags(tfTransferable)); - env.close(); + env(token::cancelOffer(buyer, {offerID})); + } - // Create an offer to give the NFT to buyer for free. - offers.emplace_back( - keylet::nftoffer(account, env.seq(account)).key); - env(token::createOffer(account, nftID, XRP(0)), - token::destination(buyer), - txflags((tfSellNFToken))); - } - env.close(); + // Verify that all the NFTs are owned by buyer. + Json::Value buyerNFTs = [&env, &buyer]() { + Json::Value params; + params[jss::account] = buyer.human(); + params[jss::type] = "state"; + return env.rpc("json", "account_nfts", to_string(params)); + }(); - // buyer accepts all of the offers. - for (uint256 const& offer : offers) - { - env(token::acceptSellOffer(buyer, offer)); - env.close(); - } + BEAST_EXPECT(buyerNFTs[jss::result][jss::account_nfts].size() == nftIDs.size()); + for (Json::Value const& ownedNFT : buyerNFTs[jss::result][jss::account_nfts]) + { + uint256 ownedID; + BEAST_EXPECT(ownedID.parseHex(ownedNFT[sfNFTokenID.jsonName].asString())); + auto const foundIter = std::find(nftIDs.begin(), nftIDs.end(), ownedID); - // This can be a good time to look at the NFT pages. - // printNFTPages(env, noisy); + // Assuming we find the NFT, erase it so we know it's been + // found and can't be found again. + if (BEAST_EXPECT(foundIter != nftIDs.end())) + nftIDs.erase(foundIter); + } - // Verify that all NFTs are owned by buyer and findable in the - // ledger by having buyer create sell offers for all of their - // NFTs. Attempting to sell an offer that the ledger can't find - // generates a non-tesSUCCESS error code. - for (uint256 const& nftID : nftIDs) - { - uint256 const offerID = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, XRP(100)), - txflags(tfSellNFToken)); - env.close(); - - env(token::cancelOffer(buyer, {offerID})); - } - - // Verify that all the NFTs are owned by buyer. - Json::Value buyerNFTs = [&env, &buyer]() { - Json::Value params; - params[jss::account] = buyer.human(); - params[jss::type] = "state"; - return env.rpc("json", "account_nfts", to_string(params)); - }(); - - BEAST_EXPECT( - buyerNFTs[jss::result][jss::account_nfts].size() == - nftIDs.size()); - for (Json::Value const& ownedNFT : - buyerNFTs[jss::result][jss::account_nfts]) - { - uint256 ownedID; - BEAST_EXPECT(ownedID.parseHex( - ownedNFT[sfNFTokenID.jsonName].asString())); - auto const foundIter = - std::find(nftIDs.begin(), nftIDs.end(), ownedID); - - // Assuming we find the NFT, erase it so we know it's been - // found and can't be found again. - if (BEAST_EXPECT(foundIter != nftIDs.end())) - nftIDs.erase(foundIter); - } - - // All NFTs should now be accounted for, so nftIDs should be - // empty. - BEAST_EXPECT(nftIDs.empty()); - }; + // All NFTs should now be accounted for, so nftIDs should be + // empty. + BEAST_EXPECT(nftIDs.empty()); + }; // These seeds cause a lopsided split where the new NFT is added // to the upper page. - static std::initializer_list const - splitAndAddToHi{ - "sp6JS7f14BuwFY8Mw5p3b8jjQBBTK", // 0. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6F7X3EiGKazu", // 1. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6FxjntJJfKXq", // 2. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6eSF1ydEozJg", // 3. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6koPB91um2ej", // 4. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6m6D64iwquSe", // 5. 0x1d2932ea + static std::initializer_list const splitAndAddToHi{ + "sp6JS7f14BuwFY8Mw5p3b8jjQBBTK", // 0. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6F7X3EiGKazu", // 1. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6FxjntJJfKXq", // 2. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6eSF1ydEozJg", // 3. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6koPB91um2ej", // 4. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6m6D64iwquSe", // 5. 0x1d2932ea - "sp6JS7f14BuwFY8Mw5rC43sN4adC2", // 6. 0x208dbc24 - "sp6JS7f14BuwFY8Mw65L9DDQqgebz", // 7. 0x208dbc24 - "sp6JS7f14BuwFY8Mw65nKvU8pPQNn", // 8. 0x208dbc24 - "sp6JS7f14BuwFY8Mw6bxZLyTrdipw", // 9. 0x208dbc24 - "sp6JS7f14BuwFY8Mw6d5abucntSoX", // 10. 0x208dbc24 - "sp6JS7f14BuwFY8Mw6qXK5awrRRP8", // 11. 0x208dbc24 + "sp6JS7f14BuwFY8Mw5rC43sN4adC2", // 6. 0x208dbc24 + "sp6JS7f14BuwFY8Mw65L9DDQqgebz", // 7. 0x208dbc24 + "sp6JS7f14BuwFY8Mw65nKvU8pPQNn", // 8. 0x208dbc24 + "sp6JS7f14BuwFY8Mw6bxZLyTrdipw", // 9. 0x208dbc24 + "sp6JS7f14BuwFY8Mw6d5abucntSoX", // 10. 0x208dbc24 + "sp6JS7f14BuwFY8Mw6qXK5awrRRP8", // 11. 0x208dbc24 - // These eight need to be kept together by the implementation. - "sp6JS7f14BuwFY8Mw66EBtMxoMcCa", // 12. 0x309b67ed - "sp6JS7f14BuwFY8Mw66dGfE9jVfGv", // 13. 0x309b67ed - "sp6JS7f14BuwFY8Mw6APdZa7PH566", // 14. 0x309b67ed - "sp6JS7f14BuwFY8Mw6C3QX5CZyET5", // 15. 0x309b67ed - "sp6JS7f14BuwFY8Mw6CSysFf8GvaR", // 16. 0x309b67ed - "sp6JS7f14BuwFY8Mw6c7QSDmoAeRV", // 17. 0x309b67ed - "sp6JS7f14BuwFY8Mw6mvonveaZhW7", // 18. 0x309b67ed - "sp6JS7f14BuwFY8Mw6vtHHG7dYcXi", // 19. 0x309b67ed + // These eight need to be kept together by the implementation. + "sp6JS7f14BuwFY8Mw66EBtMxoMcCa", // 12. 0x309b67ed + "sp6JS7f14BuwFY8Mw66dGfE9jVfGv", // 13. 0x309b67ed + "sp6JS7f14BuwFY8Mw6APdZa7PH566", // 14. 0x309b67ed + "sp6JS7f14BuwFY8Mw6C3QX5CZyET5", // 15. 0x309b67ed + "sp6JS7f14BuwFY8Mw6CSysFf8GvaR", // 16. 0x309b67ed + "sp6JS7f14BuwFY8Mw6c7QSDmoAeRV", // 17. 0x309b67ed + "sp6JS7f14BuwFY8Mw6mvonveaZhW7", // 18. 0x309b67ed + "sp6JS7f14BuwFY8Mw6vtHHG7dYcXi", // 19. 0x309b67ed - "sp6JS7f14BuwFY8Mw66yppUNxESaw", // 20. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6ATYQvobXiDT", // 21. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6bis8D1Wa9Uy", // 22. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6cTiGCWA8Wfa", // 23. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6eAy2fpXmyYf", // 24. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6icn58TRs8YG", // 25. 0x40d4b96f + "sp6JS7f14BuwFY8Mw66yppUNxESaw", // 20. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6ATYQvobXiDT", // 21. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6bis8D1Wa9Uy", // 22. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6cTiGCWA8Wfa", // 23. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6eAy2fpXmyYf", // 24. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6icn58TRs8YG", // 25. 0x40d4b96f - "sp6JS7f14BuwFY8Mw68tj2eQEWoJt", // 26. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6AjnAinNnMHT", // 27. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6CKDUwB4LrhL", // 28. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6d2yPszEFA6J", // 29. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6jcBQBH3PfnB", // 30. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6qxx19KSnN1w", // 31. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw68tj2eQEWoJt", // 26. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6AjnAinNnMHT", // 27. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6CKDUwB4LrhL", // 28. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6d2yPszEFA6J", // 29. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6jcBQBH3PfnB", // 30. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6qxx19KSnN1w", // 31. 0x503b6ba9 - // Adding this NFT splits the page. It is added to the upper - // page. - "sp6JS7f14BuwFY8Mw6ut1hFrqWoY5", // 32. 0x503b6ba9 - }; + // Adding this NFT splits the page. It is added to the upper + // page. + "sp6JS7f14BuwFY8Mw6ut1hFrqWoY5", // 32. 0x503b6ba9 + }; // These seeds cause a lopsided split where the new NFT is added // to the lower page. - static std::initializer_list const - splitAndAddToLo{ - "sp6JS7f14BuwFY8Mw5p3b8jjQBBTK", // 0. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6F7X3EiGKazu", // 1. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6FxjntJJfKXq", // 2. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6eSF1ydEozJg", // 3. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6koPB91um2ej", // 4. 0x1d2932ea - "sp6JS7f14BuwFY8Mw6m6D64iwquSe", // 5. 0x1d2932ea + static std::initializer_list const splitAndAddToLo{ + "sp6JS7f14BuwFY8Mw5p3b8jjQBBTK", // 0. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6F7X3EiGKazu", // 1. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6FxjntJJfKXq", // 2. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6eSF1ydEozJg", // 3. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6koPB91um2ej", // 4. 0x1d2932ea + "sp6JS7f14BuwFY8Mw6m6D64iwquSe", // 5. 0x1d2932ea - "sp6JS7f14BuwFY8Mw5rC43sN4adC2", // 6. 0x208dbc24 - "sp6JS7f14BuwFY8Mw65L9DDQqgebz", // 7. 0x208dbc24 - "sp6JS7f14BuwFY8Mw65nKvU8pPQNn", // 8. 0x208dbc24 - "sp6JS7f14BuwFY8Mw6bxZLyTrdipw", // 9. 0x208dbc24 - "sp6JS7f14BuwFY8Mw6d5abucntSoX", // 10. 0x208dbc24 - "sp6JS7f14BuwFY8Mw6qXK5awrRRP8", // 11. 0x208dbc24 + "sp6JS7f14BuwFY8Mw5rC43sN4adC2", // 6. 0x208dbc24 + "sp6JS7f14BuwFY8Mw65L9DDQqgebz", // 7. 0x208dbc24 + "sp6JS7f14BuwFY8Mw65nKvU8pPQNn", // 8. 0x208dbc24 + "sp6JS7f14BuwFY8Mw6bxZLyTrdipw", // 9. 0x208dbc24 + "sp6JS7f14BuwFY8Mw6d5abucntSoX", // 10. 0x208dbc24 + "sp6JS7f14BuwFY8Mw6qXK5awrRRP8", // 11. 0x208dbc24 - // These eight need to be kept together by the implementation. - "sp6JS7f14BuwFY8Mw66EBtMxoMcCa", // 12. 0x309b67ed - "sp6JS7f14BuwFY8Mw66dGfE9jVfGv", // 13. 0x309b67ed - "sp6JS7f14BuwFY8Mw6APdZa7PH566", // 14. 0x309b67ed - "sp6JS7f14BuwFY8Mw6C3QX5CZyET5", // 15. 0x309b67ed - "sp6JS7f14BuwFY8Mw6CSysFf8GvaR", // 16. 0x309b67ed - "sp6JS7f14BuwFY8Mw6c7QSDmoAeRV", // 17. 0x309b67ed - "sp6JS7f14BuwFY8Mw6mvonveaZhW7", // 18. 0x309b67ed - "sp6JS7f14BuwFY8Mw6vtHHG7dYcXi", // 19. 0x309b67ed + // These eight need to be kept together by the implementation. + "sp6JS7f14BuwFY8Mw66EBtMxoMcCa", // 12. 0x309b67ed + "sp6JS7f14BuwFY8Mw66dGfE9jVfGv", // 13. 0x309b67ed + "sp6JS7f14BuwFY8Mw6APdZa7PH566", // 14. 0x309b67ed + "sp6JS7f14BuwFY8Mw6C3QX5CZyET5", // 15. 0x309b67ed + "sp6JS7f14BuwFY8Mw6CSysFf8GvaR", // 16. 0x309b67ed + "sp6JS7f14BuwFY8Mw6c7QSDmoAeRV", // 17. 0x309b67ed + "sp6JS7f14BuwFY8Mw6mvonveaZhW7", // 18. 0x309b67ed + "sp6JS7f14BuwFY8Mw6vtHHG7dYcXi", // 19. 0x309b67ed - "sp6JS7f14BuwFY8Mw66yppUNxESaw", // 20. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6ATYQvobXiDT", // 21. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6bis8D1Wa9Uy", // 22. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6cTiGCWA8Wfa", // 23. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6eAy2fpXmyYf", // 24. 0x40d4b96f - "sp6JS7f14BuwFY8Mw6icn58TRs8YG", // 25. 0x40d4b96f + "sp6JS7f14BuwFY8Mw66yppUNxESaw", // 20. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6ATYQvobXiDT", // 21. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6bis8D1Wa9Uy", // 22. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6cTiGCWA8Wfa", // 23. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6eAy2fpXmyYf", // 24. 0x40d4b96f + "sp6JS7f14BuwFY8Mw6icn58TRs8YG", // 25. 0x40d4b96f - "sp6JS7f14BuwFY8Mw68tj2eQEWoJt", // 26. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6AjnAinNnMHT", // 27. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6CKDUwB4LrhL", // 28. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6d2yPszEFA6J", // 29. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6jcBQBH3PfnB", // 30. 0x503b6ba9 - "sp6JS7f14BuwFY8Mw6qxx19KSnN1w", // 31. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw68tj2eQEWoJt", // 26. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6AjnAinNnMHT", // 27. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6CKDUwB4LrhL", // 28. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6d2yPszEFA6J", // 29. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6jcBQBH3PfnB", // 30. 0x503b6ba9 + "sp6JS7f14BuwFY8Mw6qxx19KSnN1w", // 31. 0x503b6ba9 - // Adding this NFT splits the page. It is added to the lower - // page. - "sp6JS7f14BuwFY8Mw6xCigaMwC6Dp", // 32. 0x309b67ed - }; + // Adding this NFT splits the page. It is added to the lower + // page. + "sp6JS7f14BuwFY8Mw6xCigaMwC6Dp", // 32. 0x309b67ed + }; // Run the test cases. exerciseLopsided(splitAndAddToHi); @@ -369,118 +339,99 @@ class NFTokenDir_test : public beast::unit_test::suite // the index for the new page. This test recreates the problem. // Lambda that exercises the split. - auto exercise = - [this, - &features](std::initializer_list seeds) { - Env env{ - *this, - envconfig(), - features, - nullptr, - beast::severities::kDisabled}; + auto exercise = [this, &features](std::initializer_list seeds) { + Env env{*this, envconfig(), features, nullptr, beast::severities::kDisabled}; - // Eventually all of the NFTokens will be owned by buyer. - Account const buyer{"buyer"}; - env.fund(XRP(10000), buyer); + // Eventually all of the NFTokens will be owned by buyer. + Account const buyer{"buyer"}; + env.fund(XRP(10000), buyer); + env.close(); + + // Create accounts for all of the seeds and fund those accounts. + std::vector accounts; + accounts.reserve(seeds.size()); + for (std::string_view seed : seeds) + { + Account const& account = accounts.emplace_back(Account::base58Seed, std::string(seed)); + env.fund(XRP(10000), account); + + // Do not close the ledger inside the loop. If accounts are + // initialized at different ledgers, they will have + // different account sequences. That would cause the + // accounts to have different NFTokenID sequence numbers. + } + env.close(); + + // All of the accounts create one NFT and and offer that NFT to + // buyer. + std::vector nftIDs; + std::vector offers; + offers.reserve(accounts.size()); + for (Account const& account : accounts) + { + // Mint the NFT. + uint256 const& nftID = nftIDs.emplace_back(token::getNextID(env, account, 0, tfTransferable)); + env(token::mint(account, 0), txflags(tfTransferable)); env.close(); - // Create accounts for all of the seeds and fund those accounts. - std::vector accounts; - accounts.reserve(seeds.size()); - for (std::string_view seed : seeds) - { - Account const& account = accounts.emplace_back( - Account::base58Seed, std::string(seed)); - env.fund(XRP(10000), account); + // Create an offer to give the NFT to buyer for free. + offers.emplace_back(keylet::nftoffer(account, env.seq(account)).key); + env(token::createOffer(account, nftID, XRP(0)), token::destination(buyer), txflags((tfSellNFToken))); + } + env.close(); - // Do not close the ledger inside the loop. If accounts are - // initialized at different ledgers, they will have - // different account sequences. That would cause the - // accounts to have different NFTokenID sequence numbers. - } + // buyer accepts all of the but the last. The last offer + // causes the page to split. + for (std::size_t i = 0; i < offers.size() - 1; ++i) + { + env(token::acceptSellOffer(buyer, offers[i])); + env.close(); + } + + env(token::acceptSellOffer(buyer, offers.back())); + env.close(); + + // This can be a good time to look at the NFT pages. + // printNFTPages(env, noisy); + + // Verify that all NFTs are owned by buyer and findable in the + // ledger by having buyer create sell offers for all of their + // NFTs. Attempting to sell an offer that the ledger can't find + // generates a non-tesSUCCESS error code. + for (uint256 const& nftID : nftIDs) + { + uint256 const offerID = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, XRP(100)), txflags(tfSellNFToken)); env.close(); - // All of the accounts create one NFT and and offer that NFT to - // buyer. - std::vector nftIDs; - std::vector offers; - offers.reserve(accounts.size()); - for (Account const& account : accounts) - { - // Mint the NFT. - uint256 const& nftID = nftIDs.emplace_back( - token::getNextID(env, account, 0, tfTransferable)); - env(token::mint(account, 0), txflags(tfTransferable)); - env.close(); + env(token::cancelOffer(buyer, {offerID})); + } - // Create an offer to give the NFT to buyer for free. - offers.emplace_back( - keylet::nftoffer(account, env.seq(account)).key); - env(token::createOffer(account, nftID, XRP(0)), - token::destination(buyer), - txflags((tfSellNFToken))); - } - env.close(); + // Verify that all the NFTs are owned by buyer. + Json::Value buyerNFTs = [&env, &buyer]() { + Json::Value params; + params[jss::account] = buyer.human(); + params[jss::type] = "state"; + return env.rpc("json", "account_nfts", to_string(params)); + }(); - // buyer accepts all of the but the last. The last offer - // causes the page to split. - for (std::size_t i = 0; i < offers.size() - 1; ++i) - { - env(token::acceptSellOffer(buyer, offers[i])); - env.close(); - } + BEAST_EXPECT(buyerNFTs[jss::result][jss::account_nfts].size() == nftIDs.size()); + for (Json::Value const& ownedNFT : buyerNFTs[jss::result][jss::account_nfts]) + { + uint256 ownedID; + BEAST_EXPECT(ownedID.parseHex(ownedNFT[sfNFTokenID.jsonName].asString())); + auto const foundIter = std::find(nftIDs.begin(), nftIDs.end(), ownedID); - env(token::acceptSellOffer(buyer, offers.back())); - env.close(); + // Assuming we find the NFT, erase it so we know it's been + // found and can't be found again. + if (BEAST_EXPECT(foundIter != nftIDs.end())) + nftIDs.erase(foundIter); + } - // This can be a good time to look at the NFT pages. - // printNFTPages(env, noisy); - - // Verify that all NFTs are owned by buyer and findable in the - // ledger by having buyer create sell offers for all of their - // NFTs. Attempting to sell an offer that the ledger can't find - // generates a non-tesSUCCESS error code. - for (uint256 const& nftID : nftIDs) - { - uint256 const offerID = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, XRP(100)), - txflags(tfSellNFToken)); - env.close(); - - env(token::cancelOffer(buyer, {offerID})); - } - - // Verify that all the NFTs are owned by buyer. - Json::Value buyerNFTs = [&env, &buyer]() { - Json::Value params; - params[jss::account] = buyer.human(); - params[jss::type] = "state"; - return env.rpc("json", "account_nfts", to_string(params)); - }(); - - BEAST_EXPECT( - buyerNFTs[jss::result][jss::account_nfts].size() == - nftIDs.size()); - for (Json::Value const& ownedNFT : - buyerNFTs[jss::result][jss::account_nfts]) - { - uint256 ownedID; - BEAST_EXPECT(ownedID.parseHex( - ownedNFT[sfNFTokenID.jsonName].asString())); - auto const foundIter = - std::find(nftIDs.begin(), nftIDs.end(), ownedID); - - // Assuming we find the NFT, erase it so we know it's been - // found and can't be found again. - if (BEAST_EXPECT(foundIter != nftIDs.end())) - nftIDs.erase(foundIter); - } - - // All NFTs should now be accounted for, so nftIDs should be - // empty. - BEAST_EXPECT(nftIDs.empty()); - }; + // All NFTs should now be accounted for, so nftIDs should be + // empty. + BEAST_EXPECT(nftIDs.empty()); + }; // These seeds fill the last 17 entries of the initial page with // equivalent NFTs. The split should keep these together. @@ -628,8 +579,7 @@ class NFTokenDir_test : public beast::unit_test::suite accounts.reserve(seeds.size()); for (std::string_view seed : seeds) { - Account const& account = - accounts.emplace_back(Account::base58Seed, std::string(seed)); + Account const& account = accounts.emplace_back(Account::base58Seed, std::string(seed)); env.fund(XRP(10000), account); // Do not close the ledger inside the loop. If accounts are @@ -646,17 +596,13 @@ class NFTokenDir_test : public beast::unit_test::suite for (Account const& account : accounts) { // Mint the NFT. - uint256 const& nftID = nftIDs.emplace_back( - token::getNextID(env, account, 0, tfTransferable)); + uint256 const& nftID = nftIDs.emplace_back(token::getNextID(env, account, 0, tfTransferable)); env(token::mint(account, 0), txflags(tfTransferable)); env.close(); // Create an offer to give the NFT to buyer for free. - offers.emplace_back( - keylet::nftoffer(account, env.seq(account)).key); - env(token::createOffer(account, nftID, XRP(0)), - token::destination(buyer), - txflags((tfSellNFToken))); + offers.emplace_back(keylet::nftoffer(account, env.seq(account)).key); + env(token::createOffer(account, nftID, XRP(0)), token::destination(buyer), txflags((tfSellNFToken))); } env.close(); @@ -681,8 +627,7 @@ class NFTokenDir_test : public beast::unit_test::suite } // buyer accepts the last offer which causes a page overflow. - env(token::acceptSellOffer(buyer, offerForPageOverflow), - ter(tecNO_SUITABLE_NFTOKEN_PAGE)); + env(token::acceptSellOffer(buyer, offerForPageOverflow), ter(tecNO_SUITABLE_NFTOKEN_PAGE)); // Verify that all expected NFTs are owned by buyer and findable in // the ledger by having buyer create sell offers for all of their NFTs. @@ -691,8 +636,7 @@ class NFTokenDir_test : public beast::unit_test::suite for (uint256 const& nftID : nftIDs) { uint256 const offerID = keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, XRP(100)), - txflags(tfSellNFToken)); + env(token::createOffer(buyer, nftID, XRP(100)), txflags(tfSellNFToken)); env.close(); env(token::cancelOffer(buyer, {offerID})); @@ -706,16 +650,12 @@ class NFTokenDir_test : public beast::unit_test::suite return env.rpc("json", "account_nfts", to_string(params)); }(); - BEAST_EXPECT( - buyerNFTs[jss::result][jss::account_nfts].size() == nftIDs.size()); - for (Json::Value const& ownedNFT : - buyerNFTs[jss::result][jss::account_nfts]) + BEAST_EXPECT(buyerNFTs[jss::result][jss::account_nfts].size() == nftIDs.size()); + for (Json::Value const& ownedNFT : buyerNFTs[jss::result][jss::account_nfts]) { uint256 ownedID; - BEAST_EXPECT( - ownedID.parseHex(ownedNFT[sfNFTokenID.jsonName].asString())); - auto const foundIter = - std::find(nftIDs.begin(), nftIDs.end(), ownedID); + BEAST_EXPECT(ownedID.parseHex(ownedNFT[sfNFTokenID.jsonName].asString())); + auto const foundIter = std::find(nftIDs.begin(), nftIDs.end(), ownedID); // Assuming we find the NFT, erase it so we know it's been found // and can't be found again. @@ -799,8 +739,7 @@ class NFTokenDir_test : public beast::unit_test::suite accounts.reserve(seeds.size()); for (std::string_view seed : seeds) { - Account const& account = - accounts.emplace_back(Account::base58Seed, std::string(seed)); + Account const& account = accounts.emplace_back(Account::base58Seed, std::string(seed)); env.fund(XRP(10000), account); // Do not close the ledger inside the loop. If accounts are @@ -823,20 +762,16 @@ class NFTokenDir_test : public beast::unit_test::suite for (Account const& account : accounts) { // Mint the NFT. Tweak the taxon so zero is always stored. - std::uint32_t taxon = - toUInt32(nft::cipheredTaxon(i, nft::toTaxon(0))); + std::uint32_t taxon = toUInt32(nft::cipheredTaxon(i, nft::toTaxon(0))); - uint256 const& nftID = nftIDsByPage[i].emplace_back( - token::getNextID(env, account, taxon, tfTransferable)); + uint256 const& nftID = + nftIDsByPage[i].emplace_back(token::getNextID(env, account, taxon, tfTransferable)); env(token::mint(account, taxon), txflags(tfTransferable)); env.close(); // Create an offer to give the NFT to buyer for free. - offers[i].emplace_back( - keylet::nftoffer(account, env.seq(account)).key); - env(token::createOffer(account, nftID, XRP(0)), - token::destination(buyer), - txflags((tfSellNFToken))); + offers[i].emplace_back(keylet::nftoffer(account, env.seq(account)).key); + env(token::createOffer(account, nftID, XRP(0)), token::destination(buyer), txflags((tfSellNFToken))); } } env.close(); @@ -886,8 +821,7 @@ class NFTokenDir_test : public beast::unit_test::suite // the transaction succeeded. for (uint256 const& offer : overflowOffers) { - env(token::acceptSellOffer(buyer, offer), - ter(tecNO_SUITABLE_NFTOKEN_PAGE)); + env(token::acceptSellOffer(buyer, offer), ter(tecNO_SUITABLE_NFTOKEN_PAGE)); env.close(); } @@ -899,8 +833,7 @@ class NFTokenDir_test : public beast::unit_test::suite { for (uint256 const& nftID : vec) { - env(token::createOffer(buyer, nftID, XRP(100)), - txflags(tfSellNFToken)); + env(token::createOffer(buyer, nftID, XRP(100)), txflags(tfSellNFToken)); env.close(); } } @@ -918,8 +851,7 @@ class NFTokenDir_test : public beast::unit_test::suite if (!marker.empty()) params[jss::marker] = marker; - return env.rpc( - "json", "account_objects", to_string(params)); + return env.rpc("json", "account_objects", to_string(params)); }(); marker.clear(); @@ -974,8 +906,7 @@ class NFTokenDir_test : public beast::unit_test::suite return env.rpc("json", "account_objects", to_string(params)); }(); BEAST_EXPECT( - remainingOffers.isMember(jss::result) && - remainingOffers[jss::result].isMember(jss::account_objects) && + remainingOffers.isMember(jss::result) && remainingOffers[jss::result].isMember(jss::account_objects) && remainingOffers[jss::result][jss::account_objects].size() == 0); } @@ -1024,8 +955,7 @@ class NFTokenDir_test : public beast::unit_test::suite if (ownedNFT.isMember(sfNFTokenID.jsonName)) { uint256 ownedID; - BEAST_EXPECT(ownedID.parseHex( - ownedNFT[sfNFTokenID.jsonName].asString())); + BEAST_EXPECT(ownedID.parseHex(ownedNFT[sfNFTokenID.jsonName].asString())); auto const foundIter = allNftIDs.find(ownedID); // Assuming we find the NFT, erase it so we know it's been found diff --git a/src/test/app/NFToken_test.cpp b/src/test/app/NFToken_test.cpp index 59995a4078..51590903e3 100644 --- a/src/test/app/NFToken_test.cpp +++ b/src/test/app/NFToken_test.cpp @@ -57,10 +57,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite std::uint32_t lastClose(test::jtx::Env& env) { - return env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count(); + return env.current()->header().parentCloseTime.time_since_epoch().count(); } void @@ -92,8 +89,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(mintedCount(env, master) == 1); BEAST_EXPECT(burnedCount(env, master) == 1); - uint256 const nftId1{ - token::getNextID(env, env.master, 0u, tfTransferable)}; + uint256 const nftId1{token::getNextID(env, env.master, 0u, tfTransferable)}; env(token::mint(env.master, 0u), txflags(tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, master) == 1); @@ -103,10 +99,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite Account const alice{"alice"}; env.fund(XRP(10000), alice); env.close(); - uint256 const aliceOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId1, XRP(1000)), - token::owner(master)); + uint256 const aliceOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId1, XRP(1000)), token::owner(master)); env.close(); BEAST_EXPECT(ownerCount(env, master) == 1); @@ -171,28 +165,22 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // A lambda that checks alice's ownerCount, mintedCount, and // burnedCount all in one fell swoop. - auto checkAliceOwnerMintedBurned = [&env, this, &alice]( - std::uint32_t owners, - std::uint32_t minted, - std::uint32_t burned, - int line) { - auto oneCheck = - [line, this]( - char const* type, std::uint32_t found, std::uint32_t exp) { + auto checkAliceOwnerMintedBurned = + [&env, this, &alice](std::uint32_t owners, std::uint32_t minted, std::uint32_t burned, int line) { + auto oneCheck = [line, this](char const* type, std::uint32_t found, std::uint32_t exp) { if (found == exp) pass(); else { std::stringstream ss; - ss << "Wrong " << type << " count. Found: " << found - << "; Expected: " << exp; + ss << "Wrong " << type << " count. Found: " << found << "; Expected: " << exp; fail(ss.str(), __FILE__, line); } }; - oneCheck("owner", ownerCount(env, alice), owners); - oneCheck("minted", mintedCount(env, alice), minted); - oneCheck("burned", burnedCount(env, alice), burned); - }; + oneCheck("owner", ownerCount(env, alice), owners); + oneCheck("minted", mintedCount(env, alice), minted); + oneCheck("burned", burnedCount(env, alice), burned); + }; // alice still does not have enough XRP for the reserve of an NFT // page. @@ -255,8 +243,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } // alice burns a non-existent NFT. - env(token::burn(alice, token::getID(env, alice, 197, 5)), - ter(tecNO_ENTRY)); + env(token::burn(alice, token::getID(env, alice, 197, 5)), ter(tecNO_ENTRY)); env.close(); checkAliceOwnerMintedBurned(0, 33, 33, __LINE__); @@ -265,8 +252,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // minter. env(token::setMinter(alice, minter)); env.close(); - BEAST_EXPECT( - env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id()); + BEAST_EXPECT(env.le(alice)->getAccountID(sfNFTokenMinter) == minter.id()); // A lambda that checks minter's and alice's ownerCount, // mintedCount, and burnedCount all in one fell swoop. @@ -278,32 +264,22 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite std::uint32_t minterMinted, std::uint32_t minterBurned, int line) { - auto oneCheck = [this]( - char const* type, - std::uint32_t found, - std::uint32_t exp, - int line) { + auto oneCheck = [this](char const* type, std::uint32_t found, std::uint32_t exp, int line) { if (found == exp) pass(); else { std::stringstream ss; - ss << "Wrong " << type << " count. Found: " << found - << "; Expected: " << exp; + ss << "Wrong " << type << " count. Found: " << found << "; Expected: " << exp; fail(ss.str(), __FILE__, line); } }; oneCheck("alice owner", ownerCount(env, alice), aliceOwners, line); - oneCheck( - "alice minted", mintedCount(env, alice), aliceMinted, line); - oneCheck( - "alice burned", burnedCount(env, alice), aliceBurned, line); - oneCheck( - "minter owner", ownerCount(env, minter), minterOwners, line); - oneCheck( - "minter minted", mintedCount(env, minter), minterMinted, line); - oneCheck( - "minter burned", burnedCount(env, minter), minterBurned, line); + oneCheck("alice minted", mintedCount(env, alice), aliceMinted, line); + oneCheck("alice burned", burnedCount(env, alice), aliceBurned, line); + oneCheck("minter owner", ownerCount(env, minter), minterOwners, line); + oneCheck("minter minted", mintedCount(env, minter), minterMinted, line); + oneCheck("minter burned", burnedCount(env, minter), minterBurned, line); }; std::uint32_t nftSeq = 33; @@ -316,10 +292,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // minter still does not have enough XRP for the reserve of an NFT // page. Just for grins (and code coverage), minter mints NFTs that // include a URI. - env(token::mint(minter), - token::issuer(alice), - token::uri("uri"), - ter(tecINSUFFICIENT_RESERVE)); + env(token::mint(minter), token::issuer(alice), token::uri("uri"), ter(tecINSUFFICIENT_RESERVE)); env.close(); checkMintersOwnerMintedBurned(0, 33, nftSeq, 0, 0, 0, __LINE__); @@ -347,10 +320,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // That NFT page is full. Creating an additional NFT page requires // additional reserve. - env(token::mint(minter), - token::issuer(alice), - token::uri("uri"), - ter(tecINSUFFICIENT_RESERVE)); + env(token::mint(minter), token::issuer(alice), token::uri("uri"), ter(tecINSUFFICIENT_RESERVE)); env.close(); checkMintersOwnerMintedBurned(0, 65, nftSeq, 1, 0, 0, __LINE__); @@ -368,8 +338,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { env(token::burn(minter, token::getID(env, alice, 0, nftSeq++))); env.close(); - checkMintersOwnerMintedBurned( - 0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__); + checkMintersOwnerMintedBurned(0, 66, nftSeq, (65 - seq) ? 1 : 0, 0, 0, __LINE__); } // minter has one more NFT to burn. Should take her owner count to @@ -379,8 +348,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__); // minter burns a non-existent NFT. - env(token::burn(minter, token::getID(env, alice, 2009, 3)), - ter(tecNO_ENTRY)); + env(token::burn(minter, token::getID(env, alice, 2009, 3)), ter(tecNO_ENTRY)); env.close(); checkMintersOwnerMintedBurned(0, 66, nftSeq, 0, 0, 0, __LINE__); } @@ -416,29 +384,28 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Note that we're bypassing almost all of the ledger's safety // checks with this modify() call. If you call close() between // here and the end of the test all the effort will be lost. - env.app().openLedger().modify( - [&alice](OpenView& view, beast::Journal j) { - // Get the account root we want to hijack. - auto const sle = view.read(keylet::account(alice.id())); - if (!sle) - return false; // This would be really surprising! + env.app().openLedger().modify([&alice](OpenView& view, beast::Journal j) { + // Get the account root we want to hijack. + auto const sle = view.read(keylet::account(alice.id())); + if (!sle) + return false; // This would be really surprising! - // Just for sanity's sake we'll check that the current value - // of sfMintedNFTokens matches what we expect. - auto replacement = std::make_shared(*sle, sle->key()); - if (replacement->getFieldU32(sfMintedNFTokens) != 1) - return false; // Unexpected test conditions. + // Just for sanity's sake we'll check that the current value + // of sfMintedNFTokens matches what we expect. + auto replacement = std::make_shared(*sle, sle->key()); + if (replacement->getFieldU32(sfMintedNFTokens) != 1) + return false; // Unexpected test conditions. - // Sequence number is generated by sfFirstNFTokenSequence + - // sfMintedNFTokens. We can replace the two fields with any - // numbers as long as they add up to the largest valid number. - // In our case, sfFirstNFTokenSequence is set to the largest - // valid number, and sfMintedNFTokens is set to zero. - (*replacement)[sfFirstNFTokenSequence] = 0xFFFF'FFFE; - (*replacement)[sfMintedNFTokens] = 0x0000'0000; - view.rawReplace(replacement); - return true; - }); + // Sequence number is generated by sfFirstNFTokenSequence + + // sfMintedNFTokens. We can replace the two fields with any + // numbers as long as they add up to the largest valid number. + // In our case, sfFirstNFTokenSequence is set to the largest + // valid number, and sfMintedNFTokens is set to zero. + (*replacement)[sfFirstNFTokenSequence] = 0xFFFF'FFFE; + (*replacement)[sfMintedNFTokens] = 0x0000'0000; + view.rawReplace(replacement); + return true; + }); // See whether alice is at the boundary that causes an error. env(token::mint(alice, 0u), ter(tesSUCCESS)); @@ -474,18 +441,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // preflight // Set a negative fee. - env(token::mint(alice, 0u), - fee(STAmount(10ull, true)), - ter(temBAD_FEE)); + env(token::mint(alice, 0u), fee(STAmount(10ull, true)), ter(temBAD_FEE)); // Set an invalid flag. env(token::mint(alice, 0u), txflags(0x00008000), ter(temINVALID_FLAG)); // Can't set a transfer fee if the NFT does not have the tfTRANSFERABLE // flag set. - env(token::mint(alice, 0u), - token::xferFee(maxTransferFee), - ter(temMALFORMED)); + env(token::mint(alice, 0u), token::xferFee(maxTransferFee), ter(temMALFORMED)); // Set a bad transfer fee. env(token::mint(alice, 0u), @@ -500,25 +463,19 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(token::mint(alice, 0u), token::uri(""), ter(temMALFORMED)); // Invalid URI: too long. - env(token::mint(alice, 0u), - token::uri(std::string(maxTokenURILength + 1, 'q')), - ter(temMALFORMED)); + env(token::mint(alice, 0u), token::uri(std::string(maxTokenURILength + 1, 'q')), ter(temMALFORMED)); //---------------------------------------------------------------------- // preclaim // Non-existent issuer. - env(token::mint(alice, 0u), - token::issuer(Account("demon")), - ter(tecNO_ISSUER)); + env(token::mint(alice, 0u), token::issuer(Account("demon")), ter(tecNO_ISSUER)); //---------------------------------------------------------------------- // doApply // Existent issuer, but not given minting permission - env(token::mint(minter, 0u), - token::issuer(alice), - ter(tecNO_PERMISSION)); + env(token::mint(minter, 0u), token::issuer(alice), ter(tecNO_PERMISSION)); } void @@ -543,8 +500,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); - uint256 const nftAlice0ID = - token::getNextID(env, alice, 0, tfTransferable); + uint256 const nftAlice0ID = token::getNextID(env, alice, 0, tfTransferable); env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); @@ -553,16 +509,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // preflight // Set a negative fee. - env(token::burn(alice, nftAlice0ID), - fee(STAmount(10ull, true)), - ter(temBAD_FEE)); + env(token::burn(alice, nftAlice0ID), fee(STAmount(10ull, true)), ter(temBAD_FEE)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); // Set an invalid flag. - env(token::burn(alice, nftAlice0ID), - txflags(0x00008000), - ter(temINVALID_FLAG)); + env(token::burn(alice, nftAlice0ID), txflags(0x00008000), ter(temINVALID_FLAG)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -570,8 +522,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // preclaim // Try to burn a token that doesn't exist. - env(token::burn(alice, token::getID(env, alice, 0, 1)), - ter(tecNO_ENTRY)); + env(token::burn(alice, token::getID(env, alice, 0, 1)), ter(tecNO_ENTRY)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -602,16 +553,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); - uint256 const nftAlice0ID = - token::getNextID(env, alice, 0, tfTransferable, 10); - env(token::mint(alice, 0u), - txflags(tfTransferable), - token::xferFee(10)); + uint256 const nftAlice0ID = token::getNextID(env, alice, 0, tfTransferable, 10); + env(token::mint(alice, 0u), txflags(tfTransferable), token::xferFee(10)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); - uint256 const nftXrpOnlyID = - token::getNextID(env, alice, 0, tfOnlyXRP | tfTransferable); + uint256 const nftXrpOnlyID = token::getNextID(env, alice, 0, tfOnlyXRP | tfTransferable); env(token::mint(alice, 0), txflags(tfOnlyXRP | tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); @@ -630,47 +577,35 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // buyer tries to create an NFTokenOffer, but doesn't have the reserve. - env(token::createOffer(buyer, nftAlice0ID, XRP(1000)), - token::owner(alice), - ter(tecINSUFFICIENT_RESERVE)); + env(token::createOffer(buyer, nftAlice0ID, XRP(1000)), token::owner(alice), ter(tecINSUFFICIENT_RESERVE)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // Set a negative fee. - env(token::createOffer(buyer, nftAlice0ID, XRP(1000)), - fee(STAmount(10ull, true)), - ter(temBAD_FEE)); + env(token::createOffer(buyer, nftAlice0ID, XRP(1000)), fee(STAmount(10ull, true)), ter(temBAD_FEE)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // Set an invalid flag. - env(token::createOffer(buyer, nftAlice0ID, XRP(1000)), - txflags(0x00008000), - ter(temINVALID_FLAG)); + env(token::createOffer(buyer, nftAlice0ID, XRP(1000)), txflags(0x00008000), ter(temINVALID_FLAG)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // Set an invalid amount. - env(token::createOffer(buyer, nftXrpOnlyID, buyer["USD"](1)), - ter(temBAD_AMOUNT)); - env(token::createOffer(buyer, nftAlice0ID, buyer["USD"](0)), - ter(temBAD_AMOUNT)); - env(token::createOffer(buyer, nftXrpOnlyID, drops(0)), - ter(temBAD_AMOUNT)); + env(token::createOffer(buyer, nftXrpOnlyID, buyer["USD"](1)), ter(temBAD_AMOUNT)); + env(token::createOffer(buyer, nftAlice0ID, buyer["USD"](0)), ter(temBAD_AMOUNT)); + env(token::createOffer(buyer, nftXrpOnlyID, drops(0)), ter(temBAD_AMOUNT)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // Set a bad expiration. - env(token::createOffer(buyer, nftAlice0ID, buyer["USD"](1)), - token::expiration(0), - ter(temBAD_EXPIRATION)); + env(token::createOffer(buyer, nftAlice0ID, buyer["USD"](1)), token::expiration(0), ter(temBAD_EXPIRATION)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // Invalid Owner field and tfSellToken flag relationships. // A buy offer must specify the owner. - env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)), - ter(temMALFORMED)); + env(token::createOffer(buyer, nftXrpOnlyID, XRP(1000)), ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -683,9 +618,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, alice) == 1); // An owner may not offer to buy their own token. - env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)), - token::owner(alice), - ter(temMALFORMED)); + env(token::createOffer(alice, nftXrpOnlyID, XRP(1000)), token::owner(alice), ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); @@ -717,25 +650,21 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, buyer) == 0); // The nftID must be present in the ledger. - env(token::createOffer( - buyer, token::getID(env, alice, 0, 1), XRP(1000)), + env(token::createOffer(buyer, token::getID(env, alice, 0, 1), XRP(1000)), token::owner(alice), ter(tecNO_ENTRY)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // The nftID must be present in the ledger of a sell offer too. - env(token::createOffer( - alice, token::getID(env, alice, 0, 1), XRP(1000)), + env(token::createOffer(alice, token::getID(env, alice, 0, 1), XRP(1000)), txflags(tfSellNFToken), ter(tecNO_ENTRY)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // buyer must have the funds to pay for their offer. - env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), - token::owner(alice), - ter(tecNO_LINE)); + env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(tecNO_LINE)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -745,9 +674,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // Issuer (alice) must have a trust line for the offered funds. - env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), - token::owner(alice), - ter(tecNO_LINE)); + env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(tecNO_LINE)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -757,9 +684,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Issuer (alice) must have a trust line for the offered funds and // the trust line may not be frozen. - env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), - token::owner(alice), - ter(tecFROZEN)); + env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(tecFROZEN)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -778,9 +703,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(trust(gw, buyer["AUD"](999), tfSetFreeze)); env.close(); - env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), - token::owner(alice), - ter(tecFROZEN)); + env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(tecFROZEN)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -790,9 +713,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(trust(buyer, gwAUD(1000))); env.close(); - env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), - token::owner(alice), - ter(tecUNFUNDED_OFFER)); + env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(tecUNFUNDED_OFFER)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); // the trust line. @@ -805,9 +726,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // However buyer doesn't have enough XRP to cover the reserve for // an NFT offer. - env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), - token::owner(alice), - ter(tecINSUFFICIENT_RESERVE)); + env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(tecINSUFFICIENT_RESERVE)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -816,9 +735,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(pay(env.master, buyer, XRP(50) + drops(baseFee * 12 - 1))); env.close(); - env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), - token::owner(alice), - ter(tecINSUFFICIENT_RESERVE)); + env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(tecINSUFFICIENT_RESERVE)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -828,9 +745,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // We don't care whether the offer is fully funded until the offer is // accepted. Success at last! - env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), - token::owner(alice), - ter(tesSUCCESS)); + env(token::createOffer(buyer, nftAlice0ID, gwAUD(1000)), token::owner(alice), ter(tesSUCCESS)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); } @@ -852,18 +767,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); - uint256 const nftAlice0ID = - token::getNextID(env, alice, 0, tfTransferable); + uint256 const nftAlice0ID = token::getNextID(env, alice, 0, tfTransferable); env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); // This is the offer we'll try to cancel. - uint256 const buyerOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftAlice0ID, XRP(1)), - token::owner(alice), - ter(tesSUCCESS)); + uint256 const buyerOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftAlice0ID, XRP(1)), token::owner(alice), ter(tesSUCCESS)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -871,16 +782,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // preflight // Set a negative fee. - env(token::cancelOffer(buyer, {buyerOfferIndex}), - fee(STAmount(10ull, true)), - ter(temBAD_FEE)); + env(token::cancelOffer(buyer, {buyerOfferIndex}), fee(STAmount(10ull, true)), ter(temBAD_FEE)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); // Set an invalid flag. - env(token::cancelOffer(buyer, {buyerOfferIndex}), - txflags(0x00008000), - ter(temINVALID_FLAG)); + env(token::cancelOffer(buyer, {buyerOfferIndex}), txflags(0x00008000), ter(temINVALID_FLAG)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -895,8 +802,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // List of tokens to delete is too long. { - std::vector offers( - maxTokenOfferCancelCount + 1, buyerOfferIndex); + std::vector offers(maxTokenOfferCancelCount + 1, buyerOfferIndex); env(token::cancelOffer(buyer, offers), ter(temMALFORMED)); env.close(); @@ -904,8 +810,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } // Duplicate entries are not allowed in the list of offers to cancel. - env(token::cancelOffer(buyer, {buyerOfferIndex, buyerOfferIndex}), - ter(temMALFORMED)); + env(token::cancelOffer(buyer, {buyerOfferIndex, buyerOfferIndex}), ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -972,14 +877,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); - uint256 const nftAlice0ID = - token::getNextID(env, alice, 0, tfTransferable); + uint256 const nftAlice0ID = token::getNextID(env, alice, 0, tfTransferable); env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); - uint256 const nftXrpOnlyID = - token::getNextID(env, alice, 0, tfOnlyXRP | tfTransferable); + uint256 const nftXrpOnlyID = token::getNextID(env, alice, 0, tfOnlyXRP | tfTransferable); env(token::mint(alice, 0), txflags(tfOnlyXRP | tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); @@ -990,37 +893,28 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, alice) == 1); // alice creates sell offers for her nfts. - uint256 const plainOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftAlice0ID, XRP(10)), - txflags(tfSellNFToken)); + uint256 const plainOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftAlice0ID, XRP(10)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); - uint256 const audOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftAlice0ID, gwAUD(30)), - txflags(tfSellNFToken)); + uint256 const audOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftAlice0ID, gwAUD(30)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 3); - uint256 const xrpOnlyOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftXrpOnlyID, XRP(20)), - txflags(tfSellNFToken)); + uint256 const xrpOnlyOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftXrpOnlyID, XRP(20)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 4); - uint256 const noXferOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftNoXferID, XRP(30)), - txflags(tfSellNFToken)); + uint256 const noXferOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftNoXferID, XRP(30)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 5); // alice creates a sell offer that will expire soon. - uint256 const aliceExpOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; + uint256 const aliceExpOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; env(token::createOffer(alice, nftNoXferID, XRP(40)), txflags(tfSellNFToken), token::expiration(lastClose(env) + 5)); @@ -1031,16 +925,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // preflight // Set a negative fee. - env(token::acceptSellOffer(buyer, noXferOfferIndex), - fee(STAmount(10ull, true)), - ter(temBAD_FEE)); + env(token::acceptSellOffer(buyer, noXferOfferIndex), fee(STAmount(10ull, true)), ter(temBAD_FEE)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // Set an invalid flag. - env(token::acceptSellOffer(buyer, noXferOfferIndex), - txflags(0x00008000), - ter(temINVALID_FLAG)); + env(token::acceptSellOffer(buyer, noXferOfferIndex), txflags(0x00008000), ter(temINVALID_FLAG)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -1056,8 +946,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // A buy offer may not contain a sfNFTokenBrokerFee field. { Json::Value jv = token::acceptBuyOffer(buyer, noXferOfferIndex); - jv[sfNFTokenBrokerFee.jsonName] = - STAmount(500000).getJson(JsonOptions::none); + jv[sfNFTokenBrokerFee.jsonName] = STAmount(500000).getJson(JsonOptions::none); env(jv, ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -1066,8 +955,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // A sell offer may not contain a sfNFTokenBrokerFee field. { Json::Value jv = token::acceptSellOffer(buyer, noXferOfferIndex); - jv[sfNFTokenBrokerFee.jsonName] = - STAmount(500000).getJson(JsonOptions::none); + jv[sfNFTokenBrokerFee.jsonName] = STAmount(500000).getJson(JsonOptions::none); env(jv, ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -1084,15 +972,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // preclaim // The buy offer must be non-zero. - env(token::acceptBuyOffer(buyer, beast::zero), - ter(tecOBJECT_NOT_FOUND)); + env(token::acceptBuyOffer(buyer, beast::zero), ter(tecOBJECT_NOT_FOUND)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // The buy offer must be present in the ledger. uint256 const missingOfferIndex = keylet::nftoffer(alice, 1).key; - env(token::acceptBuyOffer(buyer, missingOfferIndex), - ter(tecOBJECT_NOT_FOUND)); + env(token::acceptBuyOffer(buyer, missingOfferIndex), ter(tecOBJECT_NOT_FOUND)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -1102,14 +988,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, buyer) == 0); // The sell offer must be non-zero. - env(token::acceptSellOffer(buyer, beast::zero), - ter(tecOBJECT_NOT_FOUND)); + env(token::acceptSellOffer(buyer, beast::zero), ter(tecOBJECT_NOT_FOUND)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); // The sell offer must be present in the ledger. - env(token::acceptSellOffer(buyer, missingOfferIndex), - ter(tecOBJECT_NOT_FOUND)); + env(token::acceptSellOffer(buyer, missingOfferIndex), ter(tecOBJECT_NOT_FOUND)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); @@ -1135,29 +1019,24 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // corresponding buy and sell offers. { // buyer creates a buy offer for one of alice's nfts. - uint256 const buyerOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)), - token::owner(alice)); + uint256 const buyerOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftAlice0ID, gwAUD(29)), token::owner(alice)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); // gw attempts to broker offers that are not for the same token. - env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex), - ter(tecNFTOKEN_BUY_SELL_MISMATCH)); + env(token::brokerOffers(gw, buyerOfferIndex, xrpOnlyOfferIndex), ter(tecNFTOKEN_BUY_SELL_MISMATCH)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); // gw attempts to broker offers that are not for the same currency. - env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex), - ter(tecNFTOKEN_BUY_SELL_MISMATCH)); + env(token::brokerOffers(gw, buyerOfferIndex, plainOfferIndex), ter(tecNFTOKEN_BUY_SELL_MISMATCH)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); // In a brokered offer, the buyer must offer greater than or // equal to the selling price. - env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex), - ter(tecINSUFFICIENT_PAYMENT)); + env(token::brokerOffers(gw, buyerOfferIndex, audOfferIndex), ter(tecINSUFFICIENT_PAYMENT)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); @@ -1168,10 +1047,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } { // buyer creates a buy offer for one of alice's nfts. - uint256 const buyerOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)), - token::owner(alice)); + uint256 const buyerOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftAlice0ID, gwAUD(31)), token::owner(alice)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); @@ -1207,22 +1084,18 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // preclaim buy { // buyer creates a buy offer for one of alice's nfts. - uint256 const buyerOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)), - token::owner(alice)); + uint256 const buyerOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftAlice0ID, gwAUD(30)), token::owner(alice)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); // Don't accept a buy offer if the sell flag is set. - env(token::acceptBuyOffer(buyer, plainOfferIndex), - ter(tecNFTOKEN_OFFER_TYPE_MISMATCH)); + env(token::acceptBuyOffer(buyer, plainOfferIndex), ter(tecNFTOKEN_OFFER_TYPE_MISMATCH)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 7); // An account can't accept its own offer. - env(token::acceptBuyOffer(buyer, buyerOfferIndex), - ter(tecCANT_ACCEPT_OWN_NFTOKEN_OFFER)); + env(token::acceptBuyOffer(buyer, buyerOfferIndex), ter(tecCANT_ACCEPT_OWN_NFTOKEN_OFFER)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); @@ -1230,17 +1103,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(pay(buyer, gw, gwAUD(30))); env.close(); BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0)); - env(token::acceptBuyOffer(alice, buyerOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::acceptBuyOffer(alice, buyerOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); // alice gives her NFT to gw, so alice no longer owns nftAlice0. { - uint256 const offerIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftAlice0ID, XRP(0)), - txflags(tfSellNFToken)); + uint256 const offerIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftAlice0ID, XRP(0)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(gw, offerIndex)); env.close(); @@ -1250,8 +1120,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // alice can't accept a buy offer for an NFT she no longer owns. - env(token::acceptBuyOffer(alice, buyerOfferIndex), - ter(tecNO_PERMISSION)); + env(token::acceptBuyOffer(alice, buyerOfferIndex), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); @@ -1264,29 +1133,24 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // preclaim sell { // buyer creates a buy offer for one of alice's nfts. - uint256 const buyerOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)), - token::owner(alice)); + uint256 const buyerOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftXrpOnlyID, XRP(30)), token::owner(alice)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); // Don't accept a sell offer without the sell flag set. - env(token::acceptSellOffer(alice, buyerOfferIndex), - ter(tecNFTOKEN_OFFER_TYPE_MISMATCH)); + env(token::acceptSellOffer(alice, buyerOfferIndex), ter(tecNFTOKEN_OFFER_TYPE_MISMATCH)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 7); // An account can't accept its own offer. - env(token::acceptSellOffer(alice, plainOfferIndex), - ter(tecCANT_ACCEPT_OWN_NFTOKEN_OFFER)); + env(token::acceptSellOffer(alice, plainOfferIndex), ter(tecCANT_ACCEPT_OWN_NFTOKEN_OFFER)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); // The seller must currently be in possession of the token they // are selling. alice gave nftAlice0ID to gw. - env(token::acceptSellOffer(buyer, plainOfferIndex), - ter(tecNO_PERMISSION)); + env(token::acceptSellOffer(buyer, plainOfferIndex), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); @@ -1294,10 +1158,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // buyer attempting to accept one of alice's offers with // insufficient funds. { - uint256 const offerIndex = - keylet::nftoffer(gw, env.seq(gw)).key; - env(token::createOffer(gw, nftAlice0ID, XRP(0)), - txflags(tfSellNFToken)); + uint256 const offerIndex = keylet::nftoffer(gw, env.seq(gw)).key; + env(token::createOffer(gw, nftAlice0ID, XRP(0)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(alice, offerIndex)); env.close(); @@ -1306,8 +1168,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(pay(buyer, gw, gwAUD(30))); env.close(); BEAST_EXPECT(env.balance(buyer, gwAUD) == gwAUD(0)); - env(token::acceptSellOffer(buyer, audOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::acceptSellOffer(buyer, audOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); } @@ -1345,16 +1206,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // 1. creates an alice nft // 2. minted by minter and // 3. transfers that nft to buyer. - auto nftToBuyer = [&env, &alice, &minter1, &buyer]( - std::uint32_t flags) { + auto nftToBuyer = [&env, &alice, &minter1, &buyer](std::uint32_t flags) { uint256 const nftID{token::getNextID(env, alice, 0u, flags)}; env(token::mint(minter1, 0u), token::issuer(alice), txflags(flags)); env.close(); - uint256 const offerIndex = - keylet::nftoffer(minter1, env.seq(minter1)).key; - env(token::createOffer(minter1, nftID, XRP(0)), - txflags(tfSellNFToken)); + uint256 const offerIndex = keylet::nftoffer(minter1, env.seq(minter1)).key; + env(token::createOffer(minter1, nftID, XRP(0)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(buyer, offerIndex)); @@ -1366,17 +1224,11 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // An NFT without flagBurnable can only be burned by its owner. { uint256 const noBurnID = nftToBuyer(0); - env(token::burn(alice, noBurnID), - token::owner(buyer), - ter(tecNO_PERMISSION)); + env(token::burn(alice, noBurnID), token::owner(buyer), ter(tecNO_PERMISSION)); env.close(); - env(token::burn(minter1, noBurnID), - token::owner(buyer), - ter(tecNO_PERMISSION)); + env(token::burn(minter1, noBurnID), token::owner(buyer), ter(tecNO_PERMISSION)); env.close(); - env(token::burn(minter2, noBurnID), - token::owner(buyer), - ter(tecNO_PERMISSION)); + env(token::burn(minter2, noBurnID), token::owner(buyer), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -1387,9 +1239,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // An NFT with flagBurnable can be burned by the issuer. { uint256 const burnableID = nftToBuyer(tfBurnable); - env(token::burn(minter2, burnableID), - token::owner(buyer), - ter(tecNO_PERMISSION)); + env(token::burn(minter2, burnableID), token::owner(buyer), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -1424,9 +1274,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // minter1 is no longer alice's minter, so no longer has // permission to burn alice's nfts. - env(token::burn(minter1, burnableID), - token::owner(buyer), - ter(tecNO_PERMISSION)); + env(token::burn(minter1, burnableID), token::owner(buyer), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); @@ -1461,24 +1309,19 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Don't set flagOnlyXRP and offers can be made with IOUs. { - uint256 const nftIOUsOkayID{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftIOUsOkayID{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); - uint256 const aliceOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftIOUsOkayID, gwAUD(50)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftIOUsOkayID, gwAUD(50)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 3); BEAST_EXPECT(ownerCount(env, buyer) == 1); - uint256 const buyerOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftIOUsOkayID, gwAUD(50)), - token::owner(alice)); + uint256 const buyerOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftIOUsOkayID, gwAUD(50)), token::owner(alice)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); @@ -1497,35 +1340,28 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Set flagOnlyXRP and offers using IOUs are rejected. { - uint256 const nftOnlyXRPID{ - token::getNextID(env, alice, 0u, tfOnlyXRP | tfTransferable)}; + uint256 const nftOnlyXRPID{token::getNextID(env, alice, 0u, tfOnlyXRP | tfTransferable)}; env(token::mint(alice, 0u), txflags(tfOnlyXRP | tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); - env(token::createOffer(alice, nftOnlyXRPID, gwAUD(50)), - txflags(tfSellNFToken), - ter(temBAD_AMOUNT)); + env(token::createOffer(alice, nftOnlyXRPID, gwAUD(50)), txflags(tfSellNFToken), ter(temBAD_AMOUNT)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); BEAST_EXPECT(ownerCount(env, buyer) == 1); - env(token::createOffer(buyer, nftOnlyXRPID, gwAUD(50)), - token::owner(alice), - ter(temBAD_AMOUNT)); + env(token::createOffer(buyer, nftOnlyXRPID, gwAUD(50)), token::owner(alice), ter(temBAD_AMOUNT)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 1); // However offers for XRP are okay. BEAST_EXPECT(ownerCount(env, alice) == 2); - env(token::createOffer(alice, nftOnlyXRPID, XRP(60)), - txflags(tfSellNFToken)); + env(token::createOffer(alice, nftOnlyXRPID, XRP(60)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 3); BEAST_EXPECT(ownerCount(env, buyer) == 1); - env(token::createOffer(buyer, nftOnlyXRPID, XRP(60)), - token::owner(alice)); + env(token::createOffer(buyer, nftOnlyXRPID, XRP(60)), token::owner(alice)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 2); } @@ -1551,8 +1387,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // presence (or absence) of the fixRemoveNFTokenAutoTrustLine // amendment. So we test both cases here. for (auto const& tweakedFeatures : - {features - fixRemoveNFTokenAutoTrustLine, - features | fixRemoveNFTokenAutoTrustLine}) + {features - fixRemoveNFTokenAutoTrustLine, features | fixRemoveNFTokenAutoTrustLine}) { Env env{*this, tweakedFeatures}; env.fund(XRP(1000), alice, becky, cheri, gw); @@ -1577,38 +1412,28 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // fee will not allow creating offers that use IOUs for payment. for (std::uint32_t xferFee : {0, 1}) { - uint256 const nftNoAutoTrustID{ - token::getNextID(env, alice, 0u, tfTransferable, xferFee)}; - env(token::mint(alice, 0u), - token::xferFee(xferFee), - txflags(tfTransferable)); + uint256 const nftNoAutoTrustID{token::getNextID(env, alice, 0u, tfTransferable, xferFee)}; + env(token::mint(alice, 0u), token::xferFee(xferFee), txflags(tfTransferable)); env.close(); // becky buys the nft for 1 drop. - uint256 const beckyBuyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), - token::owner(alice)); + uint256 const beckyBuyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), token::owner(alice)); env.close(); env(token::acceptBuyOffer(alice, beckyBuyOfferIndex)); env.close(); // becky attempts to sell the nft for AUD. - TER const createOfferTER = - xferFee ? TER(tecNO_LINE) : TER(tesSUCCESS); - uint256 const beckyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; + TER const createOfferTER = xferFee ? TER(tecNO_LINE) : TER(tesSUCCESS); + uint256 const beckyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)), txflags(tfSellNFToken), ter(createOfferTER)); env.close(); // cheri offers to buy the nft for CAD. - uint256 const cheriOfferIndex = - keylet::nftoffer(cheri, env.seq(cheri)).key; - env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)), - token::owner(becky), - ter(createOfferTER)); + uint256 const cheriOfferIndex = keylet::nftoffer(cheri, env.seq(cheri)).key; + env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)), token::owner(becky), ter(createOfferTER)); env.close(); // To keep things tidy, cancel the offers. @@ -1621,14 +1446,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { std::uint16_t transferFee = 10000; // 10% - uint256 const nftAutoTrustID{token::getNextID( - env, alice, 0u, tfTransferable | tfTrustLine, transferFee)}; + uint256 const nftAutoTrustID{ + token::getNextID(env, alice, 0u, tfTransferable | tfTrustLine, transferFee)}; // If the fixRemoveNFTokenAutoTrustLine amendment is active // then this transaction fails. { - TER const mintTER = - tweakedFeatures[fixRemoveNFTokenAutoTrustLine] + TER const mintTER = tweakedFeatures[fixRemoveNFTokenAutoTrustLine] ? static_cast(temINVALID_FLAG) : static_cast(tesSUCCESS); @@ -1644,19 +1468,15 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite break; } // becky buys the nft for 1 drop. - uint256 const beckyBuyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAutoTrustID, drops(1)), - token::owner(alice)); + uint256 const beckyBuyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAutoTrustID, drops(1)), token::owner(alice)); env.close(); env(token::acceptBuyOffer(alice, beckyBuyOfferIndex)); env.close(); // becky sells the nft for AUD. - uint256 const beckySellOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)), - txflags(tfSellNFToken)); + uint256 const beckySellOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(cheri, beckySellOfferIndex)); env.close(); @@ -1665,10 +1485,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(10)); // becky buys the nft back for CAD. - uint256 const beckyBuyBackOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)), - token::owner(cheri)); + uint256 const beckyBuyBackOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAutoTrustID, gwCAD(50)), token::owner(cheri)); env.close(); env(token::acceptBuyOffer(cheri, beckyBuyBackOfferIndex)); env.close(); @@ -1681,18 +1499,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // flagCreateTrustLines will work for preestablished trust lines. { std::uint16_t transferFee = 5000; // 5% - uint256 const nftNoAutoTrustID{token::getNextID( - env, alice, 0u, tfTransferable, transferFee)}; - env(token::mint(alice, 0u), - token::xferFee(transferFee), - txflags(tfTransferable)); + uint256 const nftNoAutoTrustID{token::getNextID(env, alice, 0u, tfTransferable, transferFee)}; + env(token::mint(alice, 0u), token::xferFee(transferFee), txflags(tfTransferable)); env.close(); // alice sells the nft using AUD. - uint256 const aliceSellOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)), - txflags(tfSellNFToken)); + uint256 const aliceSellOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftNoAutoTrustID, gwAUD(200)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(cheri, aliceSellOfferIndex)); env.close(); @@ -1703,14 +1516,10 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(alice, gwAUD) == gwAUD(210)); // cheri can't sell the NFT for EUR, but can for CAD. - env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)), - txflags(tfSellNFToken), - ter(tecNO_LINE)); + env(token::createOffer(cheri, nftNoAutoTrustID, gwEUR(50)), txflags(tfSellNFToken), ter(tecNO_LINE)); env.close(); - uint256 const cheriSellOfferIndex = - keylet::nftoffer(cheri, env.seq(cheri)).key; - env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)), - txflags(tfSellNFToken)); + uint256 const cheriSellOfferIndex = keylet::nftoffer(cheri, env.seq(cheri)).key; + env(token::createOffer(cheri, nftNoAutoTrustID, gwCAD(100)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(becky, cheriSellOfferIndex)); env.close(); @@ -1743,8 +1552,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // First try an nft made by alice without flagTransferable set. { BEAST_EXPECT(ownerCount(env, alice) == 0); - uint256 const nftAliceNoTransferID{ - token::getNextID(env, alice, 0u)}; + uint256 const nftAliceNoTransferID{token::getNextID(env, alice, 0u)}; env(token::mint(alice, 0u), token::xferFee(0)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); @@ -1756,10 +1564,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite ter(tefNFTOKEN_IS_NOT_TRANSFERABLE)); // alice offers to sell the nft and becky accepts the offer. - uint256 const aliceSellOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)), - txflags(tfSellNFToken)); + uint256 const aliceSellOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftAliceNoTransferID, XRP(20)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(becky, aliceSellOfferIndex)); env.close(); @@ -1786,10 +1592,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice offers to buy the nft back from becky. becky accepts // the offer. - uint256 const aliceBuyOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)), - token::owner(becky)); + uint256 const aliceBuyOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftAliceNoTransferID, XRP(22)), token::owner(becky)); env.close(); env(token::acceptBuyOffer(becky, aliceBuyOfferIndex)); env.close(); @@ -1808,8 +1612,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(ownerCount(env, minter) == 0); - uint256 const nftMinterNoTransferID{ - token::getNextID(env, alice, 0u)}; + uint256 const nftMinterNoTransferID{token::getNextID(env, alice, 0u)}; env(token::mint(minter), token::issuer(alice)); env.close(); BEAST_EXPECT(ownerCount(env, minter) == 1); @@ -1845,10 +1648,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // minter successfully offers their nft for sale. BEAST_EXPECT(ownerCount(env, minter) == 1); - uint256 const minterSellOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)), - txflags(tfSellNFToken)); + uint256 const minterSellOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftMinterNoTransferID, XRP(22)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, minter) == 2); @@ -1882,10 +1683,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice can create an offer to buy the nft. BEAST_EXPECT(ownerCount(env, alice) == 0); - uint256 const aliceBuyOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)), - token::owner(becky)); + uint256 const aliceBuyOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftMinterNoTransferID, XRP(25)), token::owner(becky)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); @@ -1899,10 +1698,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Now minter can create an offer to buy the nft. BEAST_EXPECT(ownerCount(env, minter) == 0); - uint256 const minterBuyOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)), - token::owner(becky)); + uint256 const minterBuyOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftMinterNoTransferID, XRP(26)), token::owner(becky)); env.close(); BEAST_EXPECT(ownerCount(env, minter) == 1); @@ -1934,24 +1731,19 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // by anybody. { BEAST_EXPECT(ownerCount(env, alice) == 0); - uint256 const nftAliceID{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftAliceID{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 1); // Both alice and becky can make offers for alice's nft. - uint256 const aliceSellOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftAliceID, XRP(20)), - txflags(tfSellNFToken)); + uint256 const aliceSellOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftAliceID, XRP(20)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); - uint256 const beckyBuyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAliceID, XRP(21)), - token::owner(alice)); + uint256 const beckyBuyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAliceID, XRP(21)), token::owner(alice)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); @@ -1962,10 +1754,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, becky) == 2); // becky offers to sell the nft. - uint256 const beckySellOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAliceID, XRP(22)), - txflags(tfSellNFToken)); + uint256 const beckySellOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAliceID, XRP(22)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); BEAST_EXPECT(ownerCount(env, becky) == 3); @@ -1979,10 +1769,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, minter) == 1); // minter offers to sell the nft. - uint256 const minterSellOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftAliceID, XRP(23)), - txflags(tfSellNFToken)); + uint256 const minterSellOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftAliceID, XRP(23)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); BEAST_EXPECT(ownerCount(env, becky) == 1); @@ -2058,16 +1846,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, carol) == 1); BEAST_EXPECT(ownerCount(env, minter) == 1); - uint256 const nftID = - token::getNextID(env, alice, 0u, tfTransferable); + uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable); env(token::mint(alice), txflags(tfTransferable)); env.close(); // Becky buys the nft for XAU(10). Check balances. - uint256 const beckyBuyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftID, gwXAU(10)), - token::owner(alice)); + uint256 const beckyBuyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftID, gwXAU(10)), token::owner(alice)); env.close(); BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000)); BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000)); @@ -2078,10 +1863,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990)); // becky sells nft to carol. alice's balance should not change. - uint256 const beckySellOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftID, gwXAU(10)), - txflags(tfSellNFToken)); + uint256 const beckySellOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftID, gwXAU(10)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(carol, beckySellOfferIndex)); env.close(); @@ -2090,10 +1873,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990)); // minter buys nft from carol. alice's balance should not change. - uint256 const minterBuyOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, gwXAU(10)), - token::owner(carol)); + uint256 const minterBuyOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, gwXAU(10)), token::owner(carol)); env.close(); env(token::acceptBuyOffer(carol, minterBuyOfferIndex)); env.close(); @@ -2104,10 +1885,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // minter sells the nft to alice. gwXAU balances should finish // where they started. - uint256 const minterSellOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, gwXAU(10)), - txflags(tfSellNFToken)); + uint256 const minterSellOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, gwXAU(10)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(alice, minterSellOfferIndex)); env.close(); @@ -2128,16 +1907,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Set the smallest possible transfer fee. { // An nft with a transfer fee of 1 basis point. - uint256 const nftID = - token::getNextID(env, alice, 0u, tfTransferable, 1); + uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1); env(token::mint(alice), txflags(tfTransferable), token::xferFee(1)); env.close(); // Becky buys the nft for XAU(10). Check balances. - uint256 const beckyBuyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftID, gwXAU(10)), - token::owner(alice)); + uint256 const beckyBuyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftID, gwXAU(10)), token::owner(alice)); env.close(); BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000)); BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000)); @@ -2148,10 +1924,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990)); // becky sells nft to carol. alice's balance goes up. - uint256 const beckySellOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftID, gwXAU(10)), - txflags(tfSellNFToken)); + uint256 const beckySellOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftID, gwXAU(10)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(carol, beckySellOfferIndex)); env.close(); @@ -2161,10 +1935,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(carol, gwXAU) == gwXAU(990)); // minter buys nft from carol. alice's balance goes up. - uint256 const minterBuyOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, gwXAU(10)), - token::owner(carol)); + uint256 const minterBuyOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, gwXAU(10)), token::owner(carol)); env.close(); env(token::acceptBuyOffer(carol, minterBuyOfferIndex)); env.close(); @@ -2176,10 +1948,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // minter sells the nft to alice. Because alice is part of the // transaction no transfer fee is removed. - uint256 const minterSellOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, gwXAU(10)), - txflags(tfSellNFToken)); + uint256 const minterSellOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, gwXAU(10)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(alice, minterSellOfferIndex)); env.close(); @@ -2218,18 +1988,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // Make an nft with a transfer fee of 50%. - uint256 const nftID = token::getNextID( - env, alice, 0u, tfTransferable, maxTransferFee); - env(token::mint(alice), - txflags(tfTransferable), - token::xferFee(maxTransferFee)); + uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, maxTransferFee); + env(token::mint(alice), txflags(tfTransferable), token::xferFee(maxTransferFee)); env.close(); // Becky buys the nft for XAU(10). Check balances. - uint256 const beckyBuyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftID, gwXAU(10)), - token::owner(alice)); + uint256 const beckyBuyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftID, gwXAU(10)), token::owner(alice)); env.close(); BEAST_EXPECT(env.balance(alice, gwXAU) == gwXAU(1000)); BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(1000)); @@ -2240,10 +2005,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(becky, gwXAU) == gwXAU(990)); // becky sells nft to minter. alice's balance goes up. - uint256 const beckySellOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftID, gwXAU(100)), - txflags(tfSellNFToken)); + uint256 const beckySellOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftID, gwXAU(100)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(minter, beckySellOfferIndex)); env.close(); @@ -2253,10 +2016,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(900)); // carol buys nft from minter. alice's balance goes up. - uint256 const carolBuyOfferIndex = - keylet::nftoffer(carol, env.seq(carol)).key; - env(token::createOffer(carol, nftID, gwXAU(10)), - token::owner(minter)); + uint256 const carolBuyOfferIndex = keylet::nftoffer(carol, env.seq(carol)).key; + env(token::createOffer(carol, nftID, gwXAU(10)), token::owner(minter)); env.close(); env(token::acceptBuyOffer(minter, carolBuyOfferIndex)); env.close(); @@ -2268,10 +2029,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // carol sells the nft to alice. Because alice is part of the // transaction no transfer fee is removed. - uint256 const carolSellOfferIndex = - keylet::nftoffer(carol, env.seq(carol)).key; - env(token::createOffer(carol, nftID, gwXAU(10)), - txflags(tfSellNFToken)); + uint256 const carolSellOfferIndex = keylet::nftoffer(carol, env.seq(carol)).key; + env(token::createOffer(carol, nftID, gwXAU(10)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(alice, carolSellOfferIndex)); env.close(); @@ -2309,8 +2068,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.disableFeature(fixUniversalNumber); // An nft with a transfer fee of 1 basis point. - uint256 const nftID = - token::getNextID(env, alice, 0u, tfTransferable, 1); + uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1); env(token::mint(alice), txflags(tfTransferable), token::xferFee(1)); env.close(); @@ -2318,8 +2076,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice there should be no transfer fee. STAmount aliceBalance = env.balance(alice); STAmount minterBalance = env.balance(minter); - uint256 const minterBuyOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const minterBuyOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftID, XRP(1)), token::owner(alice)); env.close(); env(token::acceptBuyOffer(alice, minterBuyOfferIndex)); @@ -2333,8 +2090,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice does not get any transfer fee. auto pmt = NumberSwitchOver ? drops(50000) : drops(99999); STAmount carolBalance = env.balance(carol); - uint256 const minterSellOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const minterSellOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftID, pmt), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(carol, minterSellOfferIndex)); @@ -2348,8 +2104,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // carol sells to becky. This is the smallest amount to pay for a // transfer that enables a transfer fee of 1 basis point. STAmount beckyBalance = env.balance(becky); - uint256 const beckyBuyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; + uint256 const beckyBuyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; pmt = NumberSwitchOver ? drops(50001) : drops(100000); env(token::createOffer(becky, nftID, pmt), token::owner(carol)); env.close(); @@ -2369,8 +2124,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // of an IOU. { // An nft with a transfer fee of 1 basis point. - uint256 const nftID = - token::getNextID(env, alice, 0u, tfTransferable, 1); + uint256 const nftID = token::getNextID(env, alice, 0u, tfTransferable, 1); env(token::mint(alice), txflags(tfTransferable), token::xferFee(1)); env.close(); @@ -2382,25 +2136,21 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(pay(becky, gw, env.balance(becky, gwXAU))); env.close(); - STAmount const startXAUBalance( - gwXAU.issue(), STAmount::cMinValue, STAmount::cMinOffset + 5); + STAmount const startXAUBalance(gwXAU.issue(), STAmount::cMinValue, STAmount::cMinOffset + 5); env(pay(gw, alice, startXAUBalance)); env(pay(gw, minter, startXAUBalance)); env(pay(gw, becky, startXAUBalance)); env.close(); // Here is the smallest expressible gwXAU amount. - STAmount tinyXAU( - gwXAU.issue(), STAmount::cMinValue, STAmount::cMinOffset); + STAmount tinyXAU(gwXAU.issue(), STAmount::cMinValue, STAmount::cMinOffset); // minter buys the nft for tinyXAU. Since the transfer involves // alice there should be no transfer fee. STAmount aliceBalance = env.balance(alice, gwXAU); STAmount minterBalance = env.balance(minter, gwXAU); - uint256 const minterBuyOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, tinyXAU), - token::owner(alice)); + uint256 const minterBuyOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, tinyXAU), token::owner(alice)); env.close(); env(token::acceptBuyOffer(alice, minterBuyOfferIndex)); env.close(); @@ -2411,10 +2161,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // minter sells to carol. STAmount carolBalance = env.balance(carol, gwXAU); - uint256 const minterSellOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, tinyXAU), - txflags(tfSellNFToken)); + uint256 const minterSellOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, tinyXAU), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(carol, minterSellOfferIndex)); env.close(); @@ -2428,14 +2176,11 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // carol sells to becky. This is the smallest gwXAU amount // to pay for a transfer that enables a transfer fee of 1. - STAmount const cheapNFT( - gwXAU.issue(), STAmount::cMinValue, STAmount::cMinOffset + 5); + STAmount const cheapNFT(gwXAU.issue(), STAmount::cMinValue, STAmount::cMinOffset + 5); STAmount beckyBalance = env.balance(becky, gwXAU); - uint256 const beckyBuyOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftID, cheapNFT), - token::owner(carol)); + uint256 const beckyBuyOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftID, cheapNFT), token::owner(carol)); env.close(); env(token::acceptBuyOffer(carol, beckyBuyOfferIndex)); env.close(); @@ -2497,29 +2242,18 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite else { std::stringstream ss; - ss << "Taxon recovery failed from nftID " - << to_string(nftID) << ". Expected: " << taxon + ss << "Taxon recovery failed from nftID " << to_string(nftID) << ". Expected: " << taxon << "; got: " << gotTaxon; fail(ss.str()); } }; uint256 const nftAliceID = token::getID( - env, - alice, - taxon, - rand_int(), - rand_int(), - rand_int()); + env, alice, taxon, rand_int(), rand_int(), rand_int()); check(taxon, nftAliceID); uint256 const nftBeckyID = token::getID( - env, - becky, - taxon, - rand_int(), - rand_int(), - rand_int()); + env, becky, taxon, rand_int(), rand_int(), rand_int()); check(taxon, nftBeckyID); } } @@ -2568,8 +2302,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite std::string uri; std::uint32_t taxon; - Entry(std::string uri_, std::uint32_t taxon_) - : uri(std::move(uri_)), taxon(taxon_) + Entry(std::string uri_, std::uint32_t taxon_) : uri(std::move(uri_)), taxon(taxon_) { } }; @@ -2612,12 +2345,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite sortedNFTs.reserve(nfts.size()); for (std::size_t i = 0; i < nfts.size(); ++i) sortedNFTs.push_back(nfts[i]); - std::sort( - sortedNFTs.begin(), - sortedNFTs.end(), - [](Json::Value const& lhs, Json::Value const& rhs) { - return lhs[jss::nft_serial] < rhs[jss::nft_serial]; - }); + std::sort(sortedNFTs.begin(), sortedNFTs.end(), [](Json::Value const& lhs, Json::Value const& rhs) { + return lhs[jss::nft_serial] < rhs[jss::nft_serial]; + }); for (std::size_t i = 0; i < entries.size(); ++i) { @@ -2657,39 +2387,24 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(token::setMinter(issuer, minter)); env.close(); - uint256 const nftokenID = - token::getNextID(env, issuer, 0, tfTransferable); - env(token::mint(minter, 0), - token::issuer(issuer), - txflags(tfTransferable)); + uint256 const nftokenID = token::getNextID(env, issuer, 0, tfTransferable); + env(token::mint(minter, 0), token::issuer(issuer), txflags(tfTransferable)); env.close(); // Test how adding a Destination field to an offer affects permissions // for canceling offers. { - uint256 const offerMinterToIssuer = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::destination(issuer), - txflags(tfSellNFToken)); + uint256 const offerMinterToIssuer = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID, drops(1)), token::destination(issuer), txflags(tfSellNFToken)); - uint256 const offerMinterToBuyer = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::destination(buyer), - txflags(tfSellNFToken)); + uint256 const offerMinterToBuyer = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID, drops(1)), token::destination(buyer), txflags(tfSellNFToken)); - uint256 const offerIssuerToMinter = - keylet::nftoffer(issuer, env.seq(issuer)).key; - env(token::createOffer(issuer, nftokenID, drops(1)), - token::owner(minter), - token::destination(minter)); + uint256 const offerIssuerToMinter = keylet::nftoffer(issuer, env.seq(issuer)).key; + env(token::createOffer(issuer, nftokenID, drops(1)), token::owner(minter), token::destination(minter)); - uint256 const offerIssuerToBuyer = - keylet::nftoffer(issuer, env.seq(issuer)).key; - env(token::createOffer(issuer, nftokenID, drops(1)), - token::owner(minter), - token::destination(buyer)); + uint256 const offerIssuerToBuyer = keylet::nftoffer(issuer, env.seq(issuer)).key; + env(token::createOffer(issuer, nftokenID, drops(1)), token::owner(minter), token::destination(buyer)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 2); @@ -2703,14 +2418,10 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Note that issuer does not have any special permissions regarding // offer cancellation. issuer cannot cancel an offer for an // NFToken they issued. - env(token::cancelOffer(issuer, {offerMinterToBuyer}), - ter(tecNO_PERMISSION)); - env(token::cancelOffer(buyer, {offerMinterToIssuer}), - ter(tecNO_PERMISSION)); - env(token::cancelOffer(buyer, {offerIssuerToMinter}), - ter(tecNO_PERMISSION)); - env(token::cancelOffer(minter, {offerIssuerToBuyer}), - ter(tecNO_PERMISSION)); + env(token::cancelOffer(issuer, {offerMinterToBuyer}), ter(tecNO_PERMISSION)); + env(token::cancelOffer(buyer, {offerMinterToIssuer}), ter(tecNO_PERMISSION)); + env(token::cancelOffer(buyer, {offerIssuerToMinter}), ter(tecNO_PERMISSION)); + env(token::cancelOffer(minter, {offerIssuerToBuyer}), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 2); BEAST_EXPECT(ownerCount(env, minter) == 3); @@ -2731,11 +2442,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Test how adding a Destination field to a sell offer affects // accepting that offer. { - uint256 const offerMinterSellsToBuyer = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::destination(buyer), - txflags(tfSellNFToken)); + uint256 const offerMinterSellsToBuyer = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID, drops(1)), token::destination(buyer), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 2); @@ -2743,8 +2451,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // issuer cannot accept a sell offer where they are not the // destination. - env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer), - ter(tecNO_PERMISSION)); + env(token::acceptSellOffer(issuer, offerMinterSellsToBuyer), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 2); @@ -2761,11 +2468,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Test how adding a Destination field to a buy offer affects // accepting that offer. { - uint256 const offerMinterBuysFromBuyer = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::owner(buyer), - token::destination(buyer)); + uint256 const offerMinterBuysFromBuyer = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID, drops(1)), token::owner(buyer), token::destination(buyer)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 1); @@ -2773,8 +2477,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // issuer cannot accept a buy offer where they are the // destination. - env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer), - ter(tecNO_PERMISSION)); + env(token::acceptBuyOffer(issuer, offerMinterBuysFromBuyer), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 1); @@ -2790,18 +2493,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // If a destination other than the NFToken owner is set, that // destination must act as a broker. The NFToken owner may not // simply accept the offer. - uint256 const offerBuyerBuysFromMinter = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID, drops(1)), - token::owner(minter), - token::destination(broker)); + uint256 const offerBuyerBuysFromMinter = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID, drops(1)), token::owner(minter), token::destination(broker)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 1); BEAST_EXPECT(ownerCount(env, buyer) == 1); - env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter), - ter(tecNO_PERMISSION)); + env(token::acceptBuyOffer(minter, offerBuyerBuysFromMinter), ter(tecNO_PERMISSION)); env.close(); // Clean up the unused offer. @@ -2815,16 +2514,11 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Show that a sell offer's Destination can broker that sell offer // to another account. { - uint256 const offerMinterToBroker = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::destination(broker), - txflags(tfSellNFToken)); + uint256 const offerMinterToBroker = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID, drops(1)), token::destination(broker), txflags(tfSellNFToken)); - uint256 const offerBuyerToMinter = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID, drops(1)), - token::owner(minter)); + uint256 const offerBuyerToMinter = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID, drops(1)), token::owner(minter)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); @@ -2834,9 +2528,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // issuer cannot broker the offers, because they are not the // Destination. - env(token::brokerOffers( - issuer, offerBuyerToMinter, offerMinterToBroker), - ter(tecNO_PERMISSION)); + env(token::brokerOffers(issuer, offerBuyerToMinter, offerMinterToBroker), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 2); @@ -2845,8 +2537,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Since broker is the sell offer's destination, they can broker // the two offers. - env(token::brokerOffers( - broker, offerBuyerToMinter, offerMinterToBroker)); + env(token::brokerOffers(broker, offerBuyerToMinter, offerMinterToBroker)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 0); @@ -2857,21 +2548,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Destination doesn't match, but can complete if the Destination // does match. { - uint256 const offerBuyerToMinter = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID, drops(1)), - token::destination(minter), - txflags(tfSellNFToken)); + uint256 const offerBuyerToMinter = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID, drops(1)), token::destination(minter), txflags(tfSellNFToken)); - uint256 const offerMinterToBuyer = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::owner(buyer)); + uint256 const offerMinterToBuyer = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID, drops(1)), token::owner(buyer)); - uint256 const offerIssuerToBuyer = - keylet::nftoffer(issuer, env.seq(issuer)).key; - env(token::createOffer(issuer, nftokenID, drops(1)), - token::owner(buyer)); + uint256 const offerIssuerToBuyer = keylet::nftoffer(issuer, env.seq(issuer)).key; + env(token::createOffer(issuer, nftokenID, drops(1)), token::owner(buyer)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 1); @@ -2881,18 +2565,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // Cannot broker offers when the sell destination is not the // buyer. - env(token::brokerOffers( - broker, offerIssuerToBuyer, offerBuyerToMinter), - ter(tecNO_PERMISSION)); + env(token::brokerOffers(broker, offerIssuerToBuyer, offerBuyerToMinter), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 1); BEAST_EXPECT(ownerCount(env, minter) == 1); BEAST_EXPECT(ownerCount(env, buyer) == 2); - env(token::brokerOffers( - broker, offerMinterToBuyer, offerBuyerToMinter), - ter(tecNO_PERMISSION)); + env(token::brokerOffers(broker, offerMinterToBuyer, offerBuyerToMinter), ter(tecNO_PERMISSION)); env.close(); // Buyer is successful with acceptOffer. @@ -2920,24 +2600,16 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Show that if a buy and a sell offer both have the same destination, // then that destination can broker the offers. { - uint256 const offerMinterToBroker = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::destination(broker), - txflags(tfSellNFToken)); + uint256 const offerMinterToBroker = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID, drops(1)), token::destination(broker), txflags(tfSellNFToken)); - uint256 const offerBuyerToBroker = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID, drops(1)), - token::owner(minter), - token::destination(broker)); + uint256 const offerBuyerToBroker = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID, drops(1)), token::owner(minter), token::destination(broker)); { // Cannot broker offers when the sell destination is not the // buyer or the broker. - env(token::brokerOffers( - issuer, offerBuyerToBroker, offerMinterToBroker), - ter(tecNO_PERMISSION)); + env(token::brokerOffers(issuer, offerBuyerToBroker, offerMinterToBroker), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 2); @@ -2945,8 +2617,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } // Broker is successful if they are the destination of both offers. - env(token::brokerOffers( - broker, offerBuyerToBroker, offerMinterToBroker)); + env(token::brokerOffers(broker, offerBuyerToBroker, offerMinterToBroker)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, minter) == 0); @@ -2973,11 +2644,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(token::setMinter(issuer, minter)); env.close(); - uint256 const nftokenID = - token::getNextID(env, issuer, 0, tfTransferable); - env(token::mint(minter, 0), - token::issuer(issuer), - txflags(tfTransferable)); + uint256 const nftokenID = token::getNextID(env, issuer, 0, tfTransferable); + env(token::mint(minter, 0), token::issuer(issuer), txflags(tfTransferable)); env.close(); // enable flag @@ -3002,12 +2670,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // create offer (allowed now) then cancel { - uint256 const offerIndex = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const offerIndex = keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::destination(buyer), - txflags(tfSellNFToken)); + env(token::createOffer(minter, nftokenID, drops(1)), token::destination(buyer), txflags(tfSellNFToken)); env.close(); env(token::cancelOffer(minter, {offerIndex})); @@ -3016,12 +2681,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // create offer, enable flag, then cancel { - uint256 const offerIndex = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const offerIndex = keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::destination(buyer), - txflags(tfSellNFToken)); + env(token::createOffer(minter, nftokenID, drops(1)), token::destination(buyer), txflags(tfSellNFToken)); env.close(); env(fset(buyer, asfDisallowIncomingNFTokenOffer)); @@ -3036,12 +2698,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // create offer then transfer { - uint256 const offerIndex = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const offerIndex = keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID, drops(1)), - token::destination(buyer), - txflags(tfSellNFToken)); + env(token::createOffer(minter, nftokenID, drops(1)), token::destination(buyer), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(buyer, offerIndex)); @@ -3056,17 +2715,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // a random offer to buy the token { - env(token::createOffer(alice, nftokenID, drops(1)), - token::owner(buyer), - ter(tecNO_PERMISSION)); + env(token::createOffer(alice, nftokenID, drops(1)), token::owner(buyer), ter(tecNO_PERMISSION)); env.close(); } // minter offer to buy the token { - env(token::createOffer(minter, nftokenID, drops(1)), - token::owner(buyer), - ter(tecNO_PERMISSION)); + env(token::createOffer(minter, nftokenID, drops(1)), token::owner(buyer), ter(tecNO_PERMISSION)); env.close(); } @@ -3076,17 +2731,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // enable flag env(fset(buyer, asfDisallowIncomingNFTokenOffer)); // a sell offer from the minter to the buyer should be rejected - env(token::mint(minter), - token::amount(drops(1)), - token::destination(buyer), - ter(tecNO_PERMISSION)); + env(token::mint(minter), token::amount(drops(1)), token::destination(buyer), ter(tecNO_PERMISSION)); env.close(); // disable flag env(fclear(buyer, asfDisallowIncomingNFTokenOffer)); - env(token::mint(minter), - token::amount(drops(1)), - token::destination(buyer)); + env(token::mint(minter), token::amount(drops(1)), token::destination(buyer)); env.close(); } } @@ -3112,18 +2762,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(token::setMinter(issuer, minter)); env.close(); - uint256 const nftokenID0 = - token::getNextID(env, issuer, 0, tfTransferable); - env(token::mint(minter, 0), - token::issuer(issuer), - txflags(tfTransferable)); + uint256 const nftokenID0 = token::getNextID(env, issuer, 0, tfTransferable); + env(token::mint(minter, 0), token::issuer(issuer), txflags(tfTransferable)); env.close(); - uint256 const nftokenID1 = - token::getNextID(env, issuer, 0, tfTransferable); - env(token::mint(minter, 0), - token::issuer(issuer), - txflags(tfTransferable)); + uint256 const nftokenID1 = token::getNextID(env, issuer, 0, tfTransferable); + env(token::mint(minter, 0), token::issuer(issuer), txflags(tfTransferable)); env.close(); // Test how adding an Expiration field to an offer affects permissions @@ -3131,30 +2775,22 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { std::uint32_t const expiration = lastClose(env) + 25; - uint256 const offerMinterToIssuer = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const offerMinterToIssuer = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftokenID0, drops(1)), token::destination(issuer), token::expiration(expiration), txflags(tfSellNFToken)); - uint256 const offerMinterToAnyone = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const offerMinterToAnyone = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftokenID0, drops(1)), token::expiration(expiration), txflags(tfSellNFToken)); - uint256 const offerIssuerToMinter = - keylet::nftoffer(issuer, env.seq(issuer)).key; - env(token::createOffer(issuer, nftokenID0, drops(1)), - token::owner(minter), - token::expiration(expiration)); + uint256 const offerIssuerToMinter = keylet::nftoffer(issuer, env.seq(issuer)).key; + env(token::createOffer(issuer, nftokenID0, drops(1)), token::owner(minter), token::expiration(expiration)); - uint256 const offerBuyerToMinter = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, drops(1)), - token::owner(minter), - token::expiration(expiration)); + uint256 const offerBuyerToMinter = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, drops(1)), token::owner(minter), token::expiration(expiration)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 1); BEAST_EXPECT(ownerCount(env, minter) == 3); @@ -3166,10 +2802,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // // Note that these are tec responses, so these transactions will // not be retried by the ledger. - env(token::cancelOffer(issuer, {offerMinterToAnyone}), - ter(tecNO_PERMISSION)); - env(token::cancelOffer(buyer, {offerIssuerToMinter}), - ter(tecNO_PERMISSION)); + env(token::cancelOffer(issuer, {offerMinterToAnyone}), ter(tecNO_PERMISSION)); + env(token::cancelOffer(buyer, {offerIssuerToMinter}), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(lastClose(env) < expiration); BEAST_EXPECT(ownerCount(env, issuer) == 1); @@ -3206,14 +2840,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { std::uint32_t const expiration = lastClose(env) + 25; - uint256 const offer0 = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const offer0 = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftokenID0, drops(1)), token::expiration(expiration), txflags(tfSellNFToken)); - uint256 const offer1 = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const offer1 = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftokenID1, drops(1)), token::expiration(expiration), txflags(tfSellNFToken)); @@ -3253,11 +2885,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Transfer nftokenID0 back to minter so we start the next test in // a simple place. - uint256 const offerSellBack = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, XRP(0)), - txflags(tfSellNFToken), - token::destination(minter)); + uint256 const offerSellBack = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(tfSellNFToken), token::destination(minter)); env.close(); env(token::acceptSellOffer(minter, offerSellBack)); env.close(); @@ -3273,14 +2902,10 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite std::uint32_t const expiration = lastClose(env) + 25; uint256 const offer0 = keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, drops(1)), - token::owner(minter), - token::expiration(expiration)); + env(token::createOffer(buyer, nftokenID0, drops(1)), token::owner(minter), token::expiration(expiration)); uint256 const offer1 = keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID1, drops(1)), - token::owner(minter), - token::expiration(expiration)); + env(token::createOffer(buyer, nftokenID1, drops(1)), token::owner(minter), token::expiration(expiration)); env.close(); BEAST_EXPECT(lastClose(env) < expiration); BEAST_EXPECT(ownerCount(env, issuer) == 0); @@ -3317,11 +2942,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Transfer nftokenID0 back to minter so we start the next test in // a simple place. - uint256 const offerSellBack = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, XRP(0)), - txflags(tfSellNFToken), - token::destination(minter)); + uint256 const offerSellBack = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(tfSellNFToken), token::destination(minter)); env.close(); env(token::acceptSellOffer(minter, offerSellBack)); env.close(); @@ -3336,27 +2958,21 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { std::uint32_t const expiration = lastClose(env) + 25; - uint256 const sellOffer0 = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const sellOffer0 = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftokenID0, drops(1)), token::expiration(expiration), txflags(tfSellNFToken)); - uint256 const sellOffer1 = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const sellOffer1 = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftokenID1, drops(1)), token::expiration(expiration), txflags(tfSellNFToken)); - uint256 const buyOffer0 = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, drops(1)), - token::owner(minter)); + uint256 const buyOffer0 = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, drops(1)), token::owner(minter)); - uint256 const buyOffer1 = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID1, drops(1)), - token::owner(minter)); + uint256 const buyOffer1 = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID1, drops(1)), token::owner(minter)); env.close(); BEAST_EXPECT(lastClose(env) < expiration); @@ -3376,8 +2992,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, buyer) == 2); // If the sell offer is expired it cannot be brokered. - env(token::brokerOffers(issuer, buyOffer1, sellOffer1), - ter(tecEXPIRED)); + env(token::brokerOffers(issuer, buyOffer1, sellOffer1), ter(tecEXPIRED)); env.close(); // The expired sell offer is still in the ledger. @@ -3394,11 +3009,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Transfer nftokenID0 back to minter so we start the next test in // a simple place. - uint256 const offerSellBack = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, XRP(0)), - txflags(tfSellNFToken), - token::destination(minter)); + uint256 const offerSellBack = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(tfSellNFToken), token::destination(minter)); env.close(); env(token::acceptSellOffer(minter, offerSellBack)); env.close(); @@ -3413,27 +3025,17 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { std::uint32_t const expiration = lastClose(env) + 25; - uint256 const sellOffer0 = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID0, drops(1)), - txflags(tfSellNFToken)); + uint256 const sellOffer0 = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID0, drops(1)), txflags(tfSellNFToken)); - uint256 const sellOffer1 = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftokenID1, drops(1)), - txflags(tfSellNFToken)); + uint256 const sellOffer1 = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftokenID1, drops(1)), txflags(tfSellNFToken)); - uint256 const buyOffer0 = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, drops(1)), - token::expiration(expiration), - token::owner(minter)); + uint256 const buyOffer0 = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, drops(1)), token::expiration(expiration), token::owner(minter)); - uint256 const buyOffer1 = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID1, drops(1)), - token::expiration(expiration), - token::owner(minter)); + uint256 const buyOffer1 = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID1, drops(1)), token::expiration(expiration), token::owner(minter)); env.close(); BEAST_EXPECT(lastClose(env) < expiration); @@ -3453,8 +3055,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, buyer) == 2); // If the buy offer is expired it cannot be brokered. - env(token::brokerOffers(issuer, buyOffer1, sellOffer1), - ter(tecEXPIRED)); + env(token::brokerOffers(issuer, buyOffer1, sellOffer1), ter(tecEXPIRED)); env.close(); // The expired buy offer is still in the ledger. @@ -3471,11 +3072,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Transfer nftokenID0 back to minter so we start the next test in // a simple place. - uint256 const offerSellBack = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, XRP(0)), - txflags(tfSellNFToken), - token::destination(minter)); + uint256 const offerSellBack = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(tfSellNFToken), token::destination(minter)); env.close(); env(token::acceptSellOffer(minter, offerSellBack)); env.close(); @@ -3491,29 +3089,21 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { std::uint32_t const expiration = lastClose(env) + 25; - uint256 const sellOffer0 = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const sellOffer0 = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftokenID0, drops(1)), token::expiration(expiration), txflags(tfSellNFToken)); - uint256 const sellOffer1 = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const sellOffer1 = keylet::nftoffer(minter, env.seq(minter)).key; env(token::createOffer(minter, nftokenID1, drops(1)), token::expiration(expiration), txflags(tfSellNFToken)); - uint256 const buyOffer0 = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, drops(1)), - token::expiration(expiration), - token::owner(minter)); + uint256 const buyOffer0 = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, drops(1)), token::expiration(expiration), token::owner(minter)); - uint256 const buyOffer1 = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID1, drops(1)), - token::expiration(expiration), - token::owner(minter)); + uint256 const buyOffer1 = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID1, drops(1)), token::expiration(expiration), token::owner(minter)); env.close(); BEAST_EXPECT(lastClose(env) < expiration); @@ -3533,8 +3123,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, buyer) == 2); // If the offers are expired they cannot be brokered. - env(token::brokerOffers(issuer, buyOffer1, sellOffer1), - ter(tecEXPIRED)); + env(token::brokerOffers(issuer, buyOffer1, sellOffer1), ter(tecEXPIRED)); env.close(); // The expired offers are still in the ledger. @@ -3551,11 +3140,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Transfer nftokenID0 back to minter so we start the next test in // a simple place. - uint256 const offerSellBack = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftokenID0, XRP(0)), - txflags(tfSellNFToken), - token::destination(minter)); + uint256 const offerSellBack = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftokenID0, XRP(0)), txflags(tfSellNFToken), token::destination(minter)); env.close(); env(token::acceptSellOffer(minter, offerSellBack)); env.close(); @@ -3585,14 +3171,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(token::setMinter(alice, minter)); env.close(); - uint256 const nftokenID = - token::getNextID(env, alice, 0, tfTransferable); + uint256 const nftokenID = token::getNextID(env, alice, 0, tfTransferable); env(token::mint(alice, 0), txflags(tfTransferable)); env.close(); // Anyone can cancel an expired offer. - uint256 const expiredOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; + uint256 const expiredOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; env(token::createOffer(alice, nftokenID, XRP(1000)), txflags(tfSellNFToken), @@ -3601,8 +3185,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // The offer has not expired yet, so becky can't cancel it now. BEAST_EXPECT(ownerCount(env, alice) == 2); - env(token::cancelOffer(becky, {expiredOfferIndex}), - ter(tecNO_PERMISSION)); + env(token::cancelOffer(becky, {expiredOfferIndex}), ter(tecNO_PERMISSION)); env.close(); // Close a couple of ledgers and advance the time. Then becky @@ -3615,18 +3198,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Create a couple of offers with a destination. Those offers // should be cancellable by the creator and the destination. - uint256 const dest1OfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; + uint256 const dest1OfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftokenID, XRP(1000)), - token::destination(becky), - txflags(tfSellNFToken)); + env(token::createOffer(alice, nftokenID, XRP(1000)), token::destination(becky), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); // Minter can't cancel that offer, but becky (the destination) can. - env(token::cancelOffer(minter, {dest1OfferIndex}), - ter(tecNO_PERMISSION)); + env(token::cancelOffer(minter, {dest1OfferIndex}), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); @@ -3635,12 +3214,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, alice) == 1); // alice can cancel her own offer, even if becky is the destination. - uint256 const dest2OfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; + uint256 const dest2OfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftokenID, XRP(1000)), - token::destination(becky), - txflags(tfSellNFToken)); + env(token::createOffer(alice, nftokenID, XRP(1000)), token::destination(becky), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 2); @@ -3651,26 +3227,19 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // The issuer has no special permissions regarding offer cancellation. // Minter creates a token with alice as issuer. alice cannot cancel // minter's offer. - uint256 const mintersNFTokenID = - token::getNextID(env, alice, 0, tfTransferable); - env(token::mint(minter, 0), - token::issuer(alice), - txflags(tfTransferable)); + uint256 const mintersNFTokenID = token::getNextID(env, alice, 0, tfTransferable); + env(token::mint(minter, 0), token::issuer(alice), txflags(tfTransferable)); env.close(); - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, mintersNFTokenID, XRP(1000)), - txflags(tfSellNFToken)); + env(token::createOffer(minter, mintersNFTokenID, XRP(1000)), txflags(tfSellNFToken)); env.close(); BEAST_EXPECT(ownerCount(env, minter) == 2); // Nobody other than minter should be able to cancel minter's offer. - env(token::cancelOffer(alice, {minterOfferIndex}), - ter(tecNO_PERMISSION)); - env(token::cancelOffer(becky, {minterOfferIndex}), - ter(tecNO_PERMISSION)); + env(token::cancelOffer(alice, {minterOfferIndex}), ter(tecNO_PERMISSION)); + env(token::cancelOffer(becky, {minterOfferIndex}), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, minter) == 2); @@ -3712,20 +3281,15 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite for (uint32_t i = 0; i < maxTokenOfferCancelCount + 1; ++i) { Account const nftAcct(std::string("nftAcct") + std::to_string(i)); - Account const offerAcct( - std::string("offerAcct") + std::to_string(i)); + Account const offerAcct(std::string("offerAcct") + std::to_string(i)); env.fund(XRP(1000), nftAcct, offerAcct); env.close(); - uint256 const nftokenID = - token::getNextID(env, nftAcct, 0, tfTransferable); - env(token::mint(nftAcct, 0), - token::uri(uri), - txflags(tfTransferable)); + uint256 const nftokenID = token::getNextID(env, nftAcct, 0, tfTransferable); + env(token::mint(nftAcct, 0), token::uri(uri), txflags(tfTransferable)); env.close(); - offerIndexes.push_back( - keylet::nftoffer(offerAcct, env.seq(offerAcct)).key); + offerIndexes.push_back(keylet::nftoffer(offerAcct, env.seq(offerAcct)).key); env(token::createOffer(offerAcct, nftokenID, drops(1)), token::owner(nftAcct), token::expiration(lastClose(env) + 5)); @@ -3756,16 +3320,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // But alice adds a sell offer to the list... { - uint256 const nftokenID = - token::getNextID(env, alice, 0, tfTransferable); - env(token::mint(alice, 0), - token::uri(uri), - txflags(tfTransferable)); + uint256 const nftokenID = token::getNextID(env, alice, 0, tfTransferable); + env(token::mint(alice, 0), token::uri(uri), txflags(tfTransferable)); env.close(); offerIndexes.push_back(keylet::nftoffer(alice, env.seq(alice)).key); - env(token::createOffer(alice, nftokenID, drops(1)), - txflags(tfSellNFToken)); + env(token::createOffer(alice, nftokenID, drops(1)), txflags(tfSellNFToken)); env.close(); // alice's owner count should now to 2 for the nft and the offer. @@ -3837,20 +3397,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Lambda to check owner count of all accounts is one. auto checkOwnerCountIsOne = - [this, &env]( - std::initializer_list> - accounts, - int line) { + [this, &env](std::initializer_list> accounts, int line) { for (Account const& acct : accounts) { - if (std::uint32_t ownerCount = - test::jtx::ownerCount(env, acct); - ownerCount != 1) + if (std::uint32_t ownerCount = test::jtx::ownerCount(env, acct); ownerCount != 1) { std::stringstream ss; - ss << "Account " << acct.human() - << " expected ownerCount == 1. Got " - << ownerCount; + ss << "Account " << acct.human() << " expected ownerCount == 1. Got " << ownerCount; fail(ss.str(), __FILE__, line); } } @@ -3858,12 +3411,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Lambda that mints an NFT and returns the nftID. auto mintNFT = [&env, &issuer, &minter](std::uint16_t xferFee = 0) { - uint256 const nftID = - token::getNextID(env, issuer, 0, tfTransferable, xferFee); - env(token::mint(minter, 0), - token::issuer(issuer), - token::xferFee(xferFee), - txflags(tfTransferable)); + uint256 const nftID = token::getNextID(env, issuer, 0, tfTransferable, xferFee); + env(token::mint(minter, 0), token::issuer(issuer), token::xferFee(xferFee), txflags(tfTransferable)); env.close(); return nftID; }; @@ -3879,18 +3428,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite uint256 const nftID = mintNFT(); // minter creates their offer. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, XRP(0)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, XRP(0)), txflags(tfSellNFToken)); env.close(); // buyer creates their offer. Note: a buy offer can never // offer zero. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, XRP(1)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, XRP(1)), token::owner(minter)); env.close(); auto const minterBalance = env.balance(minter); @@ -3899,8 +3444,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite auto const issuerBalance = env.balance(issuer); // Broker charges no brokerFee. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex)); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex)); env.close(); // Note that minter's XRP balance goes up even though they @@ -3926,23 +3470,18 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite uint256 const nftID = mintNFT(); // minter creates their offer. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, XRP(0)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, XRP(0)), txflags(tfSellNFToken)); env.close(); // buyer creates their offer. Note: a buy offer can never // offer zero. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, XRP(1)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, XRP(1)), token::owner(minter)); env.close(); // Broker attempts to charge a 1.1 XRP brokerFee and fails. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(XRP(1.1)), ter(tecINSUFFICIENT_PAYMENT)); env.close(); @@ -3953,17 +3492,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite auto const issuerBalance = env.balance(issuer); // Broker charges a 0.5 XRP brokerFee. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - token::brokerFee(XRP(0.5))); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(XRP(0.5))); env.close(); // Note that minter's XRP balance goes up even though they // requested XRP(0). BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.5)); BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1)); - BEAST_EXPECT( - env.balance(broker) == brokerBalance + XRP(0.5) - baseFee); + BEAST_EXPECT(env.balance(broker) == brokerBalance + XRP(0.5) - baseFee); BEAST_EXPECT(env.balance(issuer) == issuerBalance); // Burn the NFT so the next test starts with a clean state. @@ -3982,18 +3518,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite uint256 const nftID = mintNFT(maxTransferFee); // minter creates their offer. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, XRP(0)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, XRP(0)), txflags(tfSellNFToken)); env.close(); // buyer creates their offer. Note: a buy offer can never // offer zero. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, XRP(1)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, XRP(1)), token::owner(minter)); env.close(); auto const minterBalance = env.balance(minter); @@ -4002,8 +3534,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite auto const issuerBalance = env.balance(issuer); // Broker charges no brokerFee. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex)); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex)); env.close(); // Note that minter's XRP balance goes up even though they @@ -4029,18 +3560,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite uint256 const nftID = mintNFT(maxTransferFee); // minter creates their offer. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, XRP(0)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, XRP(0)), txflags(tfSellNFToken)); env.close(); // buyer creates their offer. Note: a buy offer can never // offer zero. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, XRP(1)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, XRP(1)), token::owner(minter)); env.close(); auto const minterBalance = env.balance(minter); @@ -4049,9 +3576,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite auto const issuerBalance = env.balance(issuer); // Broker charges a 0.75 XRP brokerFee. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - token::brokerFee(XRP(0.75))); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(XRP(0.75))); env.close(); // Note that, with a 50% transfer fee, issuer gets 1/2 of what's @@ -4059,8 +3584,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // remainder after both broker and minter take their cuts BEAST_EXPECT(env.balance(minter) == minterBalance + XRP(0.125)); BEAST_EXPECT(env.balance(buyer) == buyerBalance - XRP(1)); - BEAST_EXPECT( - env.balance(broker) == brokerBalance + XRP(0.75) - baseFee); + BEAST_EXPECT(env.balance(broker) == brokerBalance + XRP(0.75) - baseFee); BEAST_EXPECT(env.balance(issuer) == issuerBalance + XRP(0.125)); // Burn the NFT so the next test starts with a clean state. @@ -4072,10 +3596,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // gwXAU(amount). auto setXAUBalance = [this, &gw, &gwXAU, &env]( - std::initializer_list> - accounts, - int amount, - int line) { + std::initializer_list> accounts, int amount, int line) { for (Account const& acct : accounts) { auto const xauAmt = gwXAU(amount); @@ -4093,8 +3614,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite if (env.balance(acct, gwXAU) != xauAmt) { std::stringstream ss; - ss << "Unable to set " << acct.human() - << " account balance to gwXAU(" << amount << ")"; + ss << "Unable to set " << acct.human() << " account balance to gwXAU(" << amount << ")"; this->fail(ss.str(), __FILE__, line); } } @@ -4109,25 +3629,19 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite uint256 const nftID = mintNFT(); // minter creates their offer. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, gwXAU(1000)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, gwXAU(1000)), txflags(tfSellNFToken)); env.close(); { // buyer creates an offer for more XAU than they currently // own. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, gwXAU(1001)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, gwXAU(1001)), token::owner(minter)); env.close(); // broker attempts to broker the offers but cannot. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); // Cancel buyer's bad offer so the next test starts in a @@ -4138,16 +3652,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // buyer creates an offer for less that what minter is // asking. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, gwXAU(999)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, gwXAU(999)), token::owner(minter)); env.close(); // broker attempts to broker the offers but cannot. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - ter(tecINSUFFICIENT_PAYMENT)); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), ter(tecINSUFFICIENT_PAYMENT)); env.close(); // Cancel buyer's bad offer so the next test starts in a @@ -4157,22 +3667,18 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } // buyer creates a large enough offer. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, gwXAU(1000)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, gwXAU(1000)), token::owner(minter)); env.close(); // Broker attempts to charge a brokerFee but cannot. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(gwXAU(0.1)), ter(tecINSUFFICIENT_PAYMENT)); env.close(); // broker charges no brokerFee and succeeds. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex)); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 1); @@ -4198,24 +3704,18 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite uint256 const nftID = mintNFT(maxTransferFee); // minter creates their offer. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, gwXAU(900)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, gwXAU(900)), txflags(tfSellNFToken)); env.close(); { // buyer creates an offer for more XAU than they currently // own. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, gwXAU(1001)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, gwXAU(1001)), token::owner(minter)); env.close(); // broker attempts to broker the offers but cannot. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); // Cancel buyer's bad offer so the next test starts in a @@ -4226,16 +3726,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // buyer creates an offer for less that what minter is // asking. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, gwXAU(899)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, gwXAU(899)), token::owner(minter)); env.close(); // broker attempts to broker the offers but cannot. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - ter(tecINSUFFICIENT_PAYMENT)); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), ter(tecINSUFFICIENT_PAYMENT)); env.close(); // Cancel buyer's bad offer so the next test starts in a @@ -4244,25 +3740,20 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); } // buyer creates a large enough offer. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, gwXAU(1000)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, gwXAU(1000)), token::owner(minter)); env.close(); // Broker attempts to charge a brokerFee larger than the // difference between the two offers but cannot. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(gwXAU(101)), ter(tecINSUFFICIENT_PAYMENT)); env.close(); // broker charges the full difference between the two offers and // succeeds. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - token::brokerFee(gwXAU(100))); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(gwXAU(100))); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 1); @@ -4288,25 +3779,19 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite uint256 const nftID = mintNFT(maxTransferFee / 2); // 25% // minter creates their offer. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, gwXAU(900)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, gwXAU(900)), txflags(tfSellNFToken)); env.close(); // buyer creates a large enough offer. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, gwXAU(1000)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, gwXAU(1000)), token::owner(minter)); env.close(); // broker charges half difference between the two offers and // succeeds. 25% of the remaining difference goes to issuer. // The rest goes to minter. - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - token::brokerFee(gwXAU(50))); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(gwXAU(50))); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 1); @@ -4330,22 +3815,16 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite uint256 const nftID = mintNFT(maxTransferFee / 2); // 25% // minter creates their offer. - uint256 const minterOfferIndex = - keylet::nftoffer(minter, env.seq(minter)).key; - env(token::createOffer(minter, nftID, gwXAU(900)), - txflags(tfSellNFToken)); + uint256 const minterOfferIndex = keylet::nftoffer(minter, env.seq(minter)).key; + env(token::createOffer(minter, nftID, gwXAU(900)), txflags(tfSellNFToken)); env.close(); // buyer creates a large enough offer. - uint256 const buyOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID, gwXAU(1000)), - token::owner(minter)); + uint256 const buyOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID, gwXAU(1000)), token::owner(minter)); env.close(); - env(token::brokerOffers( - broker, buyOfferIndex, minterOfferIndex), - token::brokerFee(gwXAU(50))); + env(token::brokerOffers(broker, buyOfferIndex, minterOfferIndex), token::brokerFee(gwXAU(50))); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 1); BEAST_EXPECT(ownerCount(env, minter) == 1); @@ -4390,11 +3869,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(nftCount(env, buyer2) == 0); // Both buyer1 and buyer2 create buy offers for nftId. - uint256 const buyer1OfferIndex = - keylet::nftoffer(buyer1, env.seq(buyer1)).key; + uint256 const buyer1OfferIndex = keylet::nftoffer(buyer1, env.seq(buyer1)).key; env(token::createOffer(buyer1, nftId, XRP(100)), token::owner(issuer)); - uint256 const buyer2OfferIndex = - keylet::nftoffer(buyer2, env.seq(buyer2)).key; + uint256 const buyer2OfferIndex = keylet::nftoffer(buyer2, env.seq(buyer2)).key; env(token::createOffer(buyer2, nftId, XRP(100)), token::owner(issuer)); env.close(); @@ -4404,11 +3881,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // returned, so we skip the marker stuff. Json::Value params; params[jss::nft_id] = to_string(nftId); - Json::Value buyOffers = - env.rpc("json", "nft_buy_offers", to_string(params)); + Json::Value buyOffers = env.rpc("json", "nft_buy_offers", to_string(params)); - if (buyOffers.isMember(jss::result) && - buyOffers[jss::result].isMember(jss::offers)) + if (buyOffers.isMember(jss::result) && buyOffers[jss::result].isMember(jss::offers)) return buyOffers[jss::result][jss::offers].size(); return 0; @@ -4477,9 +3952,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // NFTokenMint BEAST_EXPECT(ownerCount(env, issuer) == 10); uint256 const nftId{token::getNextID(env, issuer, 0u, tfTransferable)}; - env(token::mint(issuer, 0u), - txflags(tfTransferable), - ticket::use(issuerTicketSeq++)); + env(token::mint(issuer, 0u), txflags(tfTransferable), ticket::use(issuerTicketSeq++)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 10); BEAST_EXPECT(ticketCount(env, issuer) == 9); @@ -4487,32 +3960,26 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // NFTokenCreateOffer BEAST_EXPECT(ownerCount(env, buyer) == 10); uint256 const offerIndex0 = keylet::nftoffer(buyer, buyerTicketSeq).key; - env(token::createOffer(buyer, nftId, XRP(1)), - token::owner(issuer), - ticket::use(buyerTicketSeq++)); + env(token::createOffer(buyer, nftId, XRP(1)), token::owner(issuer), ticket::use(buyerTicketSeq++)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 10); BEAST_EXPECT(ticketCount(env, buyer) == 9); // NFTokenCancelOffer - env(token::cancelOffer(buyer, {offerIndex0}), - ticket::use(buyerTicketSeq++)); + env(token::cancelOffer(buyer, {offerIndex0}), ticket::use(buyerTicketSeq++)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 8); BEAST_EXPECT(ticketCount(env, buyer) == 8); // NFTokenCreateOffer. buyer tries again. uint256 const offerIndex1 = keylet::nftoffer(buyer, buyerTicketSeq).key; - env(token::createOffer(buyer, nftId, XRP(2)), - token::owner(issuer), - ticket::use(buyerTicketSeq++)); + env(token::createOffer(buyer, nftId, XRP(2)), token::owner(issuer), ticket::use(buyerTicketSeq++)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 8); BEAST_EXPECT(ticketCount(env, buyer) == 7); // NFTokenAcceptOffer. issuer accepts buyer's offer. - env(token::acceptBuyOffer(issuer, offerIndex1), - ticket::use(issuerTicketSeq++)); + env(token::acceptBuyOffer(issuer, offerIndex1), ticket::use(issuerTicketSeq++)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 8); BEAST_EXPECT(ownerCount(env, buyer) == 8); @@ -4561,9 +4028,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); uint256 const nftId{token::getNextID(env, issuer, 0u, tfTransferable)}; - env(token::mint(minter, 0u), - token::issuer(issuer), - txflags(tfTransferable)); + env(token::mint(minter, 0u), token::issuer(issuer), txflags(tfTransferable)); env.close(); // At the moment issuer and minter cannot delete themselves. @@ -4582,8 +4047,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(token::createOffer(becky, nftId, XRP(2)), token::owner(minter)); env.close(); - uint256 const carlaOfferIndex = - keylet::nftoffer(carla, env.seq(carla)).key; + uint256 const carlaOfferIndex = keylet::nftoffer(carla, env.seq(carla)).key; env(token::createOffer(carla, nftId, XRP(3)), token::owner(minter)); env.close(); @@ -4652,11 +4116,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // A lambda that validates nft_XXX_offers query responses. - auto checkOffers = [this, &env, &nftID]( - char const* request, - int expectCount, - int expectMarkerCount, - int line) { + auto checkOffers = [this, &env, &nftID](char const* request, int expectCount, int expectMarkerCount, int line) { int markerCount = 0; Json::Value allOffers(Json::arrayValue); std::string marker; @@ -4676,21 +4136,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // If there are no offers for the NFT we get an error if (expectCount == 0) { - if (expect( - nftOffers.isMember(jss::result), - "expected \"result\"", - __FILE__, - line)) + if (expect(nftOffers.isMember(jss::result), "expected \"result\"", __FILE__, line)) { - if (expect( - nftOffers[jss::result].isMember(jss::error), - "expected \"error\"", - __FILE__, - line)) + if (expect(nftOffers[jss::result].isMember(jss::error), "expected \"error\"", __FILE__, line)) { expect( - nftOffers[jss::result][jss::error].asString() == - "objectNotFound", + nftOffers[jss::result][jss::error].asString() == "objectNotFound", "expected \"objectNotFound\"", __FILE__, line); @@ -4700,11 +4151,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } marker.clear(); - if (expect( - nftOffers.isMember(jss::result), - "expected \"result\"", - __FILE__, - line)) + if (expect(nftOffers.isMember(jss::result), "expected \"result\"", __FILE__, line)) { Json::Value& result = nftOffers[jss::result]; @@ -4714,11 +4161,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite marker = result[jss::marker].asString(); } - if (expect( - result.isMember(jss::offers), - "expected \"offers\"", - __FILE__, - line)) + if (expect(result.isMember(jss::offers), "expected \"offers\"", __FILE__, line)) { Json::Value& someOffers = result[jss::offers]; for (std::size_t i = 0; i < someOffers.size(); ++i) @@ -4728,16 +4171,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } while (!marker.empty()); // Verify the contents of allOffers makes sense. - expect( - allOffers.size() == expectCount, - "Unexpected returned offer count", - __FILE__, - line); - expect( - markerCount == expectMarkerCount, - "Unexpected marker count", - __FILE__, - line); + expect(allOffers.size() == expectCount, "Unexpected returned offer count", __FILE__, line); + expect(markerCount == expectMarkerCount, "Unexpected marker count", __FILE__, line); std::optional globalFlags; std::set offerIndexes; std::set amounts; @@ -4747,11 +4182,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite if (!globalFlags) globalFlags = offer[jss::flags].asInt(); - expect( - *globalFlags == offer[jss::flags].asInt(), - "Inconsistent flags returned", - __FILE__, - line); + expect(*globalFlags == offer[jss::flags].asInt(), "Inconsistent flags returned", __FILE__, line); // The test conditions should produce unique indexes and // amounts for all offers. @@ -4759,16 +4190,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite amounts.insert(offer[jss::amount].asString()); } - expect( - offerIndexes.size() == expectCount, - "Duplicate indexes returned?", - __FILE__, - line); - expect( - amounts.size() == expectCount, - "Duplicate amounts returned?", - __FILE__, - line); + expect(offerIndexes.size() == expectCount, "Duplicate indexes returned?", __FILE__, line); + expect(amounts.size() == expectCount, "Duplicate amounts returned?", __FILE__, line); }; // There are no sell offers. @@ -4776,20 +4199,18 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // A lambda that generates sell offers. STAmount sellPrice = XRP(0); - auto makeSellOffers = - [&env, &issuer, &nftID, &sellPrice](STAmount const& limit) { - // Save a little test time by not closing too often. - int offerCount = 0; - while (sellPrice < limit) - { - sellPrice += XRP(1); - env(token::createOffer(issuer, nftID, sellPrice), - txflags(tfSellNFToken)); - if (++offerCount % 10 == 0) - env.close(); - } - env.close(); - }; + auto makeSellOffers = [&env, &issuer, &nftID, &sellPrice](STAmount const& limit) { + // Save a little test time by not closing too often. + int offerCount = 0; + while (sellPrice < limit) + { + sellPrice += XRP(1); + env(token::createOffer(issuer, nftID, sellPrice), txflags(tfSellNFToken)); + if (++offerCount % 10 == 0) + env.close(); + } + env.close(); + }; // There is one sell offer. makeSellOffers(XRP(1)); @@ -4816,20 +4237,18 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // A lambda that generates buy offers. STAmount buyPrice = XRP(0); - auto makeBuyOffers = - [&env, &buyer, &issuer, &nftID, &buyPrice](STAmount const& limit) { - // Save a little test time by not closing too often. - int offerCount = 0; - while (buyPrice < limit) - { - buyPrice += XRP(1); - env(token::createOffer(buyer, nftID, buyPrice), - token::owner(issuer)); - if (++offerCount % 10 == 0) - env.close(); - } - env.close(); - }; + auto makeBuyOffers = [&env, &buyer, &issuer, &nftID, &buyPrice](STAmount const& limit) { + // Save a little test time by not closing too often. + int offerCount = 0; + while (buyPrice < limit) + { + buyPrice += XRP(1); + env(token::createOffer(buyer, nftID, buyPrice), token::owner(issuer)); + if (++offerCount % 10 == 0) + env.close(); + } + env.close(); + }; // There is one buy offer; makeBuyOffers(XRP(1)); @@ -4879,46 +4298,32 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // Create an NFT that we'll make XRP offers for. - uint256 const nftID0{ - token::getNextID(env, issuer, 0u, tfTransferable)}; + uint256 const nftID0{token::getNextID(env, issuer, 0u, tfTransferable)}; env(token::mint(issuer, 0), txflags(tfTransferable)); env.close(); // Create an NFT that we'll make IOU offers for. - uint256 const nftID1{ - token::getNextID(env, issuer, 1u, tfTransferable)}; + uint256 const nftID1{token::getNextID(env, issuer, 1u, tfTransferable)}; env(token::mint(issuer, 1), txflags(tfTransferable)); env.close(); TER const offerCreateTER = temBAD_AMOUNT; // Make offers with negative amounts for the NFTs - uint256 const sellNegXrpOfferIndex = - keylet::nftoffer(issuer, env.seq(issuer)).key; - env(token::createOffer(issuer, nftID0, XRP(-2)), - txflags(tfSellNFToken), - ter(offerCreateTER)); + uint256 const sellNegXrpOfferIndex = keylet::nftoffer(issuer, env.seq(issuer)).key; + env(token::createOffer(issuer, nftID0, XRP(-2)), txflags(tfSellNFToken), ter(offerCreateTER)); env.close(); - uint256 const sellNegIouOfferIndex = - keylet::nftoffer(issuer, env.seq(issuer)).key; - env(token::createOffer(issuer, nftID1, gwXAU(-2)), - txflags(tfSellNFToken), - ter(offerCreateTER)); + uint256 const sellNegIouOfferIndex = keylet::nftoffer(issuer, env.seq(issuer)).key; + env(token::createOffer(issuer, nftID1, gwXAU(-2)), txflags(tfSellNFToken), ter(offerCreateTER)); env.close(); - uint256 const buyNegXrpOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID0, XRP(-1)), - token::owner(issuer), - ter(offerCreateTER)); + uint256 const buyNegXrpOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID0, XRP(-1)), token::owner(issuer), ter(offerCreateTER)); env.close(); - uint256 const buyNegIouOfferIndex = - keylet::nftoffer(buyer, env.seq(buyer)).key; - env(token::createOffer(buyer, nftID1, gwXAU(-1)), - token::owner(issuer), - ter(offerCreateTER)); + uint256 const buyNegIouOfferIndex = keylet::nftoffer(buyer, env.seq(buyer)).key; + env(token::createOffer(buyer, nftID1, gwXAU(-1)), token::owner(issuer), ter(offerCreateTER)); env.close(); { @@ -4926,32 +4331,24 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite TER const offerAcceptTER = tecOBJECT_NOT_FOUND; // Sell offers. - env(token::acceptSellOffer(buyer, sellNegXrpOfferIndex), - ter(offerAcceptTER)); + env(token::acceptSellOffer(buyer, sellNegXrpOfferIndex), ter(offerAcceptTER)); env.close(); - env(token::acceptSellOffer(buyer, sellNegIouOfferIndex), - ter(offerAcceptTER)); + env(token::acceptSellOffer(buyer, sellNegIouOfferIndex), ter(offerAcceptTER)); env.close(); // Buy offers. - env(token::acceptBuyOffer(issuer, buyNegXrpOfferIndex), - ter(offerAcceptTER)); + env(token::acceptBuyOffer(issuer, buyNegXrpOfferIndex), ter(offerAcceptTER)); env.close(); - env(token::acceptBuyOffer(issuer, buyNegIouOfferIndex), - ter(offerAcceptTER)); + env(token::acceptBuyOffer(issuer, buyNegIouOfferIndex), ter(offerAcceptTER)); env.close(); } { TER const offerAcceptTER = tecOBJECT_NOT_FOUND; // Brokered offers. - env(token::brokerOffers( - gw, buyNegXrpOfferIndex, sellNegXrpOfferIndex), - ter(offerAcceptTER)); + env(token::brokerOffers(gw, buyNegXrpOfferIndex, sellNegXrpOfferIndex), ter(offerAcceptTER)); env.close(); - env(token::brokerOffers( - gw, buyNegIouOfferIndex, sellNegIouOfferIndex), - ter(offerAcceptTER)); + env(token::brokerOffers(gw, buyNegIouOfferIndex, sellNegIouOfferIndex), ter(offerAcceptTER)); env.close(); } } @@ -4963,8 +4360,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.fund(XRP(1000000), issuer, buyer); // Create an NFT that we'll make offers for. - uint256 const nftID{ - token::getNextID(env, issuer, 0u, tfTransferable)}; + uint256 const nftID{token::getNextID(env, issuer, 0u, tfTransferable)}; env(token::mint(issuer, 0), txflags(tfTransferable)); env.close(); @@ -5010,15 +4406,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env(rate(gw, 1.02)); env.close(); - auto expectInitialState = [this, - &env, - &buyer, - &minter, - &secondarySeller, - &broker, - &gw, - &gwXAU, - &gwXPB]() { + auto expectInitialState = [this, &env, &buyer, &minter, &secondarySeller, &broker, &gw, &gwXAU, &gwXPB]() { // Buyer should have XAU 1000, XPB 0 // Minter should have XAU 0, XPB 0 // Secondary seller should have XAU 0, XPB 0 @@ -5035,107 +4423,80 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(gw, buyer["XPB"]) == gwXPB(0)); BEAST_EXPECT(env.balance(gw, minter["XAU"]) == gwXAU(0)); BEAST_EXPECT(env.balance(gw, minter["XPB"]) == gwXPB(0)); - BEAST_EXPECT( - env.balance(gw, secondarySeller["XAU"]) == gwXAU(0)); - BEAST_EXPECT( - env.balance(gw, secondarySeller["XPB"]) == gwXPB(0)); + BEAST_EXPECT(env.balance(gw, secondarySeller["XAU"]) == gwXAU(0)); + BEAST_EXPECT(env.balance(gw, secondarySeller["XPB"]) == gwXPB(0)); BEAST_EXPECT(env.balance(gw, broker["XAU"]) == gwXAU(-5000)); BEAST_EXPECT(env.balance(gw, broker["XPB"]) == gwXPB(0)); }; - auto reinitializeTrustLineBalances = [&expectInitialState, - &env, - &buyer, - &minter, - &secondarySeller, - &broker, - &gw, - &gwXAU, - &gwXPB]() { - if (auto const difference = - gwXAU(1000) - env.balance(buyer, gwXAU); - difference > gwXAU(0)) - env(pay(gw, buyer, difference)); - if (env.balance(buyer, gwXPB) > gwXPB(0)) - env(pay(buyer, gw, env.balance(buyer, gwXPB))); - if (env.balance(minter, gwXAU) > gwXAU(0)) - env(pay(minter, gw, env.balance(minter, gwXAU))); - if (env.balance(minter, gwXPB) > gwXPB(0)) - env(pay(minter, gw, env.balance(minter, gwXPB))); - if (env.balance(secondarySeller, gwXAU) > gwXAU(0)) - env( - pay(secondarySeller, - gw, - env.balance(secondarySeller, gwXAU))); - if (env.balance(secondarySeller, gwXPB) > gwXPB(0)) - env( - pay(secondarySeller, - gw, - env.balance(secondarySeller, gwXPB))); - auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU); - if (brokerDiff > gwXAU(0)) - env(pay(gw, broker, brokerDiff)); - else if (brokerDiff < gwXAU(0)) - { - brokerDiff.negate(); - env(pay(broker, gw, brokerDiff)); - } - if (env.balance(broker, gwXPB) > gwXPB(0)) - env(pay(broker, gw, env.balance(broker, gwXPB))); - env.close(); - expectInitialState(); - }; + auto reinitializeTrustLineBalances = + [&expectInitialState, &env, &buyer, &minter, &secondarySeller, &broker, &gw, &gwXAU, &gwXPB]() { + if (auto const difference = gwXAU(1000) - env.balance(buyer, gwXAU); difference > gwXAU(0)) + env(pay(gw, buyer, difference)); + if (env.balance(buyer, gwXPB) > gwXPB(0)) + env(pay(buyer, gw, env.balance(buyer, gwXPB))); + if (env.balance(minter, gwXAU) > gwXAU(0)) + env(pay(minter, gw, env.balance(minter, gwXAU))); + if (env.balance(minter, gwXPB) > gwXPB(0)) + env(pay(minter, gw, env.balance(minter, gwXPB))); + if (env.balance(secondarySeller, gwXAU) > gwXAU(0)) + env(pay(secondarySeller, gw, env.balance(secondarySeller, gwXAU))); + if (env.balance(secondarySeller, gwXPB) > gwXPB(0)) + env(pay(secondarySeller, gw, env.balance(secondarySeller, gwXPB))); + auto brokerDiff = gwXAU(5000) - env.balance(broker, gwXAU); + if (brokerDiff > gwXAU(0)) + env(pay(gw, broker, brokerDiff)); + else if (brokerDiff < gwXAU(0)) + { + brokerDiff.negate(); + env(pay(broker, gw, brokerDiff)); + } + if (env.balance(broker, gwXPB) > gwXPB(0)) + env(pay(broker, gw, env.balance(broker, gwXPB))); + env.close(); + expectInitialState(); + }; auto mintNFT = [&env](Account const& minter, int transferFee = 0) { - uint256 const nftID = token::getNextID( - env, minter, 0, tfTransferable, transferFee); - env(token::mint(minter), - token::xferFee(transferFee), - txflags(tfTransferable)); + uint256 const nftID = token::getNextID(env, minter, 0, tfTransferable, transferFee); + env(token::mint(minter), token::xferFee(transferFee), txflags(tfTransferable)); env.close(); return nftID; }; - auto createBuyOffer = - [&env]( - Account const& offerer, - Account const& owner, - uint256 const& nftID, - STAmount const& amount, - std::optional const terCode = {}) { - uint256 const offerID = - keylet::nftoffer(offerer, env.seq(offerer)).key; - env(token::createOffer(offerer, nftID, amount), - token::owner(owner), - terCode ? ter(*terCode) - : ter(static_cast(tesSUCCESS))); - env.close(); - return offerID; - }; + auto createBuyOffer = [&env]( + Account const& offerer, + Account const& owner, + uint256 const& nftID, + STAmount const& amount, + std::optional const terCode = {}) { + uint256 const offerID = keylet::nftoffer(offerer, env.seq(offerer)).key; + env(token::createOffer(offerer, nftID, amount), + token::owner(owner), + terCode ? ter(*terCode) : ter(static_cast(tesSUCCESS))); + env.close(); + return offerID; + }; - auto createSellOffer = - [&env]( - Account const& offerer, - uint256 const& nftID, - STAmount const& amount, - std::optional const terCode = {}) { - uint256 const offerID = - keylet::nftoffer(offerer, env.seq(offerer)).key; - env(token::createOffer(offerer, nftID, amount), - txflags(tfSellNFToken), - terCode ? ter(*terCode) - : ter(static_cast(tesSUCCESS))); - env.close(); - return offerID; - }; + auto createSellOffer = [&env]( + Account const& offerer, + uint256 const& nftID, + STAmount const& amount, + std::optional const terCode = {}) { + uint256 const offerID = keylet::nftoffer(offerer, env.seq(offerer)).key; + env(token::createOffer(offerer, nftID, amount), + txflags(tfSellNFToken), + terCode ? ter(*terCode) : ter(static_cast(tesSUCCESS))); + env.close(); + return offerID; + }; { // Buyer attempts to send 100% of their balance of an IOU // (sellside) reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); - auto const offerID = - createSellOffer(minter, nftID, gwXAU(1000)); + auto const offerID = createSellOffer(minter, nftID, gwXAU(1000)); TER const sellTER = tecINSUFFICIENT_FUNDS; env(token::acceptSellOffer(buyer, offerID), ter(sellTER)); env.close(); @@ -5147,8 +4508,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // (buyside) reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); - auto const offerID = - createBuyOffer(buyer, minter, nftID, gwXAU(1000)); + auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(1000)); TER const sellTER = tecINSUFFICIENT_FUNDS; env(token::acceptBuyOffer(minter, offerID), ter(sellTER)); env.close(); @@ -5174,8 +4534,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // fee would be greater than the buyer's balance (buyside) reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); - auto const offerID = - createBuyOffer(buyer, minter, nftID, gwXAU(995)); + auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(995)); TER const sellTER = tecINSUFFICIENT_FUNDS; env(token::acceptBuyOffer(minter, offerID), ter(sellTER)); env.close(); @@ -5205,8 +4564,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // (buyside) reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); - auto const offerID = - createBuyOffer(buyer, minter, nftID, gwXAU(900)); + auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(900)); env(token::acceptBuyOffer(minter, offerID)); env.close(); @@ -5227,8 +4585,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); auto const nftID = mintNFT(minter); - auto const offerID = - createSellOffer(minter, nftID, gwXAU(1000)); + auto const offerID = createSellOffer(minter, nftID, gwXAU(1000)); env(token::acceptSellOffer(buyer, offerID)); env.close(); @@ -5249,8 +4606,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); auto const nftID = mintNFT(minter); - auto const offerID = - createBuyOffer(buyer, minter, nftID, gwXAU(1000)); + auto const offerID = createBuyOffer(buyer, minter, nftID, gwXAU(1000)); env(token::acceptBuyOffer(minter, offerID)); env.close(); @@ -5265,8 +4621,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); - auto const offerID = - createSellOffer(minter, nftID, gwXAU(1000)); + auto const offerID = createSellOffer(minter, nftID, gwXAU(1000)); TER const sellTER = tesSUCCESS; env(token::acceptSellOffer(gw, offerID), ter(sellTER)); env.close(); @@ -5281,8 +4636,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite auto const nftID = mintNFT(minter); TER const offerTER = tesSUCCESS; - auto const offerID = - createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER}); + auto const offerID = createBuyOffer(gw, minter, nftID, gwXAU(1000), {offerTER}); TER const sellTER = tesSUCCESS; env(token::acceptBuyOffer(minter, offerID), ter(sellTER)); env.close(); @@ -5295,8 +4649,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // than minter trusts (sellside) reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); - auto const offerID = - createSellOffer(minter, nftID, gwXAU(5000)); + auto const offerID = createSellOffer(minter, nftID, gwXAU(5000)); TER const sellTER = tesSUCCESS; env(token::acceptSellOffer(gw, offerID), ter(sellTER)); env.close(); @@ -5311,8 +4664,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite auto const nftID = mintNFT(minter); TER const offerTER = tesSUCCESS; - auto const offerID = - createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER}); + auto const offerID = createBuyOffer(gw, minter, nftID, gwXAU(5000), {offerTER}); TER const sellTER = tesSUCCESS; env(token::acceptBuyOffer(minter, offerID), ter(sellTER)); env.close(); @@ -5340,8 +4692,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite reinitializeTrustLineBalances(); auto const nftID = mintNFT(gw); - auto const offerID = - createBuyOffer(buyer, gw, nftID, gwXAU(1000)); + auto const offerID = createBuyOffer(buyer, gw, nftID, gwXAU(1000)); env(token::acceptBuyOffer(gw, offerID)); env.close(); @@ -5355,8 +4706,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite reinitializeTrustLineBalances(); auto const nftID = mintNFT(gw); auto const offerID = createSellOffer(gw, nftID, gwXAU(2000)); - env(token::acceptSellOffer(buyer, offerID), - ter(static_cast(tecINSUFFICIENT_FUNDS))); + env(token::acceptSellOffer(buyer, offerID), ter(static_cast(tecINSUFFICIENT_FUNDS))); env.close(); expectInitialState(); } @@ -5366,10 +4716,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // (buyside) reinitializeTrustLineBalances(); auto const nftID = mintNFT(gw); - auto const offerID = - createBuyOffer(buyer, gw, nftID, gwXAU(2000)); - env(token::acceptBuyOffer(gw, offerID), - ter(static_cast(tecINSUFFICIENT_FUNDS))); + auto const offerID = createBuyOffer(buyer, gw, nftID, gwXAU(2000)); + env(token::acceptBuyOffer(gw, offerID), ter(static_cast(tecINSUFFICIENT_FUNDS))); env.close(); expectInitialState(); } @@ -5379,8 +4727,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); auto const offerID = createSellOffer(minter, nftID, gwXPB(10)); - env(token::acceptSellOffer(buyer, offerID), - ter(static_cast(tecINSUFFICIENT_FUNDS))); + env(token::acceptSellOffer(buyer, offerID), ter(static_cast(tecINSUFFICIENT_FUNDS))); env.close(); expectInitialState(); } @@ -5389,14 +4736,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // have no trust line for and buyer has none of (buyside). reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); - auto const offerID = createBuyOffer( - buyer, - minter, - nftID, - gwXPB(10), - {static_cast(tecUNFUNDED_OFFER)}); - env(token::acceptBuyOffer(minter, offerID), - ter(static_cast(tecOBJECT_NOT_FOUND))); + auto const offerID = + createBuyOffer(buyer, minter, nftID, gwXPB(10), {static_cast(tecUNFUNDED_OFFER)}); + env(token::acceptBuyOffer(minter, offerID), ter(static_cast(tecOBJECT_NOT_FOUND))); env.close(); expectInitialState(); } @@ -5427,8 +4769,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); auto const nftID = mintNFT(minter); - auto const offerID = - createBuyOffer(buyer, minter, nftID, gwXPB(10)); + auto const offerID = createBuyOffer(buyer, minter, nftID, gwXPB(10)); env(token::acceptBuyOffer(minter, offerID)); env.close(); @@ -5445,14 +4786,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // secondarySeller has to sell it because transfer fees only // happen on secondary sales auto const nftID = mintNFT(minter, 3000); // 3% - auto const primaryOfferID = - createSellOffer(minter, nftID, XRP(0)); + auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0)); env(token::acceptSellOffer(secondarySeller, primaryOfferID)); env.close(); // now we can do a secondary sale - auto const offerID = - createSellOffer(secondarySeller, nftID, gwXAU(1000)); + auto const offerID = createSellOffer(secondarySeller, nftID, gwXAU(1000)); TER const sellTER = tecINSUFFICIENT_FUNDS; env(token::acceptSellOffer(buyer, offerID), ter(sellTER)); env.close(); @@ -5467,17 +4806,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // secondarySeller has to sell it because transfer fees only // happen on secondary sales auto const nftID = mintNFT(minter, 3000); // 3% - auto const primaryOfferID = - createSellOffer(minter, nftID, XRP(0)); + auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0)); env(token::acceptSellOffer(secondarySeller, primaryOfferID)); env.close(); // now we can do a secondary sale - auto const offerID = - createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000)); + auto const offerID = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(1000)); TER const sellTER = tecINSUFFICIENT_FUNDS; - env(token::acceptBuyOffer(secondarySeller, offerID), - ter(sellTER)); + env(token::acceptBuyOffer(secondarySeller, offerID), ter(sellTER)); env.close(); expectInitialState(); @@ -5490,14 +4826,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // secondarySeller has to sell it because transfer fees only // happen on secondary sales auto const nftID = mintNFT(minter, 3000); // 3% - auto const primaryOfferID = - createSellOffer(minter, nftID, XRP(0)); + auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0)); env(token::acceptSellOffer(secondarySeller, primaryOfferID)); env.close(); // now we can do a secondary sale - auto const offerID = - createSellOffer(secondarySeller, nftID, gwXAU(900)); + auto const offerID = createSellOffer(secondarySeller, nftID, gwXAU(900)); env(token::acceptSellOffer(buyer, offerID)); env.close(); @@ -5505,8 +4839,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(secondarySeller, gwXAU) == gwXAU(873)); BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82)); BEAST_EXPECT(env.balance(gw, minter["XAU"]) == gwXAU(-27)); - BEAST_EXPECT( - env.balance(gw, secondarySeller["XAU"]) == gwXAU(-873)); + BEAST_EXPECT(env.balance(gw, secondarySeller["XAU"]) == gwXAU(-873)); BEAST_EXPECT(env.balance(gw, buyer["XAU"]) == gwXAU(-82)); } { @@ -5517,14 +4850,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // secondarySeller has to sell it because transfer fees only // happen on secondary sales auto const nftID = mintNFT(minter, 3000); // 3% - auto const primaryOfferID = - createSellOffer(minter, nftID, XRP(0)); + auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0)); env(token::acceptSellOffer(secondarySeller, primaryOfferID)); env.close(); // now we can do a secondary sale - auto const offerID = - createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900)); + auto const offerID = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(900)); env(token::acceptBuyOffer(secondarySeller, offerID)); env.close(); @@ -5535,8 +4866,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // pays 900 plus 2% transfer fee on XAU - 918 BEAST_EXPECT(env.balance(buyer, gwXAU) == gwXAU(82)); BEAST_EXPECT(env.balance(gw, minter["XAU"]) == gwXAU(-27)); - BEAST_EXPECT( - env.balance(gw, secondarySeller["XAU"]) == gwXAU(-873)); + BEAST_EXPECT(env.balance(gw, secondarySeller["XAU"]) == gwXAU(-873)); BEAST_EXPECT(env.balance(gw, buyer["XAU"]) == gwXAU(-82)); } { @@ -5558,12 +4888,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite reinitializeTrustLineBalances(); auto const nftID = mintNFT(minter); - auto const sellOffer = - createSellOffer(minter, nftID, gwXAU(300)); - auto const buyOffer = - createBuyOffer(buyer, minter, nftID, gwXAU(500)); - env(token::brokerOffers(broker, buyOffer, sellOffer), - token::brokerFee(gwXAU(100))); + auto const sellOffer = createSellOffer(minter, nftID, gwXAU(300)); + auto const buyOffer = createBuyOffer(buyer, minter, nftID, gwXAU(500)); + env(token::brokerOffers(broker, buyOffer, sellOffer), token::brokerFee(gwXAU(100))); env.close(); BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(400)); @@ -5594,18 +4921,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // secondarySeller has to sell it because transfer fees only // happen on secondary sales auto const nftID = mintNFT(minter, 3000); // 3% - auto const primaryOfferID = - createSellOffer(minter, nftID, XRP(0)); + auto const primaryOfferID = createSellOffer(minter, nftID, XRP(0)); env(token::acceptSellOffer(secondarySeller, primaryOfferID)); env.close(); // now we can do a secondary sale - auto const sellOffer = - createSellOffer(secondarySeller, nftID, gwXAU(300)); - auto const buyOffer = - createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500)); - env(token::brokerOffers(broker, buyOffer, sellOffer), - token::brokerFee(gwXAU(100))); + auto const sellOffer = createSellOffer(secondarySeller, nftID, gwXAU(300)); + auto const buyOffer = createBuyOffer(buyer, secondarySeller, nftID, gwXAU(500)); + env(token::brokerOffers(broker, buyOffer, sellOffer), token::brokerFee(gwXAU(100))); env.close(); BEAST_EXPECT(env.balance(minter, gwXAU) == gwXAU(12)); @@ -5614,8 +4937,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.balance(broker, gwXAU) == gwXAU(5100)); BEAST_EXPECT(env.balance(gw, minter["XAU"]) == gwXAU(-12)); BEAST_EXPECT(env.balance(gw, buyer["XAU"]) == gwXAU(-490)); - BEAST_EXPECT( - env.balance(gw, secondarySeller["XAU"]) == gwXAU(-388)); + BEAST_EXPECT(env.balance(gw, secondarySeller["XAU"]) == gwXAU(-388)); BEAST_EXPECT(env.balance(gw, broker["XAU"]) == gwXAU(-5100)); } } @@ -5670,15 +4992,11 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Bob creates a buy offer for 5 XRP. Alice creates a sell offer // for 0 XRP. - uint256 const bobBuyOfferIndex = - keylet::nftoffer(bob, env.seq(bob)).key; + uint256 const bobBuyOfferIndex = keylet::nftoffer(bob, env.seq(bob)).key; env(token::createOffer(bob, nftId, XRP(5)), token::owner(alice)); - uint256 const aliceSellOfferIndex = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId, XRP(0)), - token::destination(bob), - txflags(tfSellNFToken)); + uint256 const aliceSellOfferIndex = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId, XRP(0)), token::destination(bob), txflags(tfSellNFToken)); env.close(); // bob accepts alice's offer but forgets to remove the old buy offer. @@ -5689,8 +5007,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(env.le(keylet::nftoffer(bobBuyOfferIndex))); // Bob creates a sell offer for the gift NFT from alice. - uint256 const bobSellOfferIndex = - keylet::nftoffer(bob, env.seq(bob)).key; + uint256 const bobSellOfferIndex = keylet::nftoffer(bob, env.seq(bob)).key; env(token::createOffer(bob, nftId, XRP(4)), txflags(tfSellNFToken)); env.close(); @@ -5740,8 +5057,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite auto incLgrSeqForFixNftRemint = [&](Env& env, Account const& acct) { int delta = 0; auto const deletableLgrSeq = - (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) + - (*env.le(acct))[sfMintedNFTokens] + 255; + (*env.le(acct))[~sfFirstNFTokenSequence].value_or(0) + (*env.le(acct))[sfMintedNFTokens] + 255; if (deletableLgrSeq > openLedgerSeq(env)) delta = deletableLgrSeq - openLedgerSeq(env); @@ -5898,9 +5214,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // The new NFT minted will not have the same ID // as any of the NFTs authorized minter minted - BEAST_EXPECT( - std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) == - nftIDs.end()); + BEAST_EXPECT(std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) == nftIDs.end()); } // When an account mints and burns a batch of NFTokens using tickets, @@ -5936,8 +5250,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice burns 50 NFTs using tickets for (auto const nftokenID : nftIDs) { - env(token::burn(alice, nftokenID), - ticket::use(aliceTicketSeq++)); + env(token::burn(alice, nftokenID), ticket::use(aliceTicketSeq++)); } env.close(); @@ -6000,9 +5313,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // The new NFT minted will not have the same ID // as any of the NFTs authorized minter minted using tickets - BEAST_EXPECT( - std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) == - nftIDs.end()); + BEAST_EXPECT(std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) == nftIDs.end()); } // When an authorized minter mints and burns a batch of NFTokens using // tickets, issuer's account needs to wait a longer time before it can @@ -6036,9 +5347,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { uint256 const nftokenID = token::getNextID(env, alice, 0u); nftIDs.push_back(nftokenID); - env(token::mint(minter), - token::issuer(alice), - ticket::use(minterTicketSeq++)); + env(token::mint(minter), token::issuer(alice), ticket::use(minterTicketSeq++)); } env.close(); @@ -6107,9 +5416,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // The new NFT minted will not have the same ID // as one of NFTs authorized minter minted using tickets - BEAST_EXPECT( - std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) == - nftIDs.end()); + BEAST_EXPECT(std::find(nftIDs.begin(), nftIDs.end(), remintNFTokenID) == nftIDs.end()); } void @@ -6128,19 +5435,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.fund(XRP(10000), alice, buyer); env.close(); - env(token::mint(alice), - token::amount(XRP(10000)), - ter(temDISABLED)); + env(token::mint(alice), token::amount(XRP(10000)), ter(temDISABLED)); env.close(); - env(token::mint(alice), - token::destination("buyer"), - ter(temDISABLED)); + env(token::mint(alice), token::destination("buyer"), ter(temDISABLED)); env.close(); - env(token::mint(alice), - token::expiration(lastClose(env) + 25), - ter(temDISABLED)); + env(token::mint(alice), token::expiration(lastClose(env) + 25), ter(temDISABLED)); env.close(); return; @@ -6163,16 +5464,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // Destination field specified but Amount field not specified - env(token::mint(alice), - token::destination(buyer), - ter(temMALFORMED)); + env(token::mint(alice), token::destination(buyer), ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); // Expiration field specified but Amount field not specified - env(token::mint(alice), - token::expiration(lastClose(env) + 25), - ter(temMALFORMED)); + env(token::mint(alice), token::expiration(lastClose(env) + 25), ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, buyer) == 0); } @@ -6180,50 +5477,33 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // The destination may not be the account submitting the // transaction. - env(token::mint(alice), - token::amount(XRP(1000)), - token::destination(alice), - ter(temMALFORMED)); + env(token::mint(alice), token::amount(XRP(1000)), token::destination(alice), ter(temMALFORMED)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); // The destination must be an account already established in the // ledger. - env(token::mint(alice), - token::amount(XRP(1000)), - token::destination(Account("demon")), - ter(tecNO_DST)); + env(token::mint(alice), token::amount(XRP(1000)), token::destination(Account("demon")), ter(tecNO_DST)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); } { // Set a bad expiration. - env(token::mint(alice), - token::amount(XRP(1000)), - token::expiration(0), - ter(temBAD_EXPIRATION)); + env(token::mint(alice), token::amount(XRP(1000)), token::expiration(0), ter(temBAD_EXPIRATION)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); // The new NFTokenOffer may not have passed its expiration time. - env(token::mint(alice), - token::amount(XRP(1000)), - token::expiration(lastClose(env)), - ter(tecEXPIRED)); + env(token::mint(alice), token::amount(XRP(1000)), token::expiration(lastClose(env)), ter(tecEXPIRED)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); } { // Set an invalid amount. - env(token::mint(alice), - token::amount(buyer["USD"](1)), - txflags(tfOnlyXRP), - ter(temBAD_AMOUNT)); - env(token::mint(alice), - token::amount(buyer["USD"](0)), - ter(temBAD_AMOUNT)); + env(token::mint(alice), token::amount(buyer["USD"](1)), txflags(tfOnlyXRP), ter(temBAD_AMOUNT)); + env(token::mint(alice), token::amount(buyer["USD"](0)), ter(temBAD_AMOUNT)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); @@ -6239,10 +5519,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // If the IOU issuer and the NFToken issuer are the same, // then that issuer does not need a trust line to accept their // fee. - env(token::mint(gw), - token::amount(gwAUD(1000)), - txflags(tfTransferable), - token::xferFee(10)); + env(token::mint(gw), token::amount(gwAUD(1000)), txflags(tfTransferable), token::xferFee(10)); env.close(); // Give alice the needed trust line, but freeze it. @@ -6260,9 +5537,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite BEAST_EXPECT(ownerCount(env, alice) == 0); // Seller (alice) must have a trust line may not be frozen. - env(token::mint(alice), - token::amount(gwAUD(1000)), - ter(tecFROZEN)); + env(token::mint(alice), token::amount(gwAUD(1000)), ter(tecFROZEN)); env.close(); BEAST_EXPECT(ownerCount(env, alice) == 0); @@ -6280,9 +5555,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // doesn't have reserve for 2 objects (NFTokenPage, Offer) - env(token::mint(bob), - token::amount(XRP(0)), - ter(tecINSUFFICIENT_RESERVE)); + env(token::mint(bob), token::amount(XRP(0)), ter(tecINSUFFICIENT_RESERVE)); env.close(); // have reserve for NFTokenPage, Offer @@ -6294,9 +5567,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // doesn't have reserve for Offer env(pay(env.master, bob, drops(baseFee))); env.close(); - env(token::mint(bob), - token::amount(XRP(0)), - ter(tecINSUFFICIENT_RESERVE)); + env(token::mint(bob), token::amount(XRP(0)), ter(tecINSUFFICIENT_RESERVE)); env.close(); // have reserve for Offer @@ -6335,8 +5606,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite token::amount(XRP(10)), token::destination(buyer), token::expiration(lastClose(env) + 25)); - uint256 const offerAliceSellsToBuyer = - keylet::nftoffer(alice, env.seq(alice)).key; + uint256 const offerAliceSellsToBuyer = keylet::nftoffer(alice, env.seq(alice)).key; env(token::cancelOffer(alice, {offerAliceSellsToBuyer})); env.close(); @@ -6345,8 +5615,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite token::amount(XRP(10)), token::destination(alice), token::expiration(lastClose(env) + 25)); - uint256 const offerBuyerSellsToAlice = - keylet::nftoffer(buyer, env.seq(buyer)).key; + uint256 const offerBuyerSellsToAlice = keylet::nftoffer(buyer, env.seq(buyer)).key; env(token::cancelOffer(alice, {offerBuyerSellsToAlice})); env.close(); @@ -6356,9 +5625,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Minter will have offer not issuer BEAST_EXPECT(ownerCount(env, minter) == 0); BEAST_EXPECT(ownerCount(env, issuer) == 0); - env(token::mint(minter), - token::issuer(issuer), - token::amount(drops(1))); + env(token::mint(minter), token::issuer(issuer), token::amount(drops(1))); env.close(); BEAST_EXPECT(ownerCount(env, minter) == 2); BEAST_EXPECT(ownerCount(env, issuer) == 0); @@ -6407,12 +5674,10 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // transaction auto verifyNFTokenID = [&](uint256 const& actualNftID) { // Get the hash for the most recent transaction. - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; env.close(); - Json::Value const meta = - env.rpc("tx", txHash)[jss::result][jss::meta]; + Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta]; // Expect nftokens_id field if (!BEAST_EXPECT(meta.isMember(jss::nftoken_id))) @@ -6427,55 +5692,50 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Verify `nftoken_ids` value equals to the NFTokenIDs that were // changed in the most recent NFTokenCancelOffer transaction - auto verifyNFTokenIDsInCancelOffer = - [&](std::vector actualNftIDs) { - // Get the hash for the most recent transaction. - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + auto verifyNFTokenIDsInCancelOffer = [&](std::vector actualNftIDs) { + // Get the hash for the most recent transaction. + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; - env.close(); - Json::Value const meta = - env.rpc("tx", txHash)[jss::result][jss::meta]; + env.close(); + Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta]; - // Expect nftokens_ids field and verify the values - if (!BEAST_EXPECT(meta.isMember(jss::nftoken_ids))) - return; + // Expect nftokens_ids field and verify the values + if (!BEAST_EXPECT(meta.isMember(jss::nftoken_ids))) + return; - // Convert NFT IDs from Json::Value to uint256 - std::vector metaIDs; - std::transform( - meta[jss::nftoken_ids].begin(), - meta[jss::nftoken_ids].end(), - std::back_inserter(metaIDs), - [this](Json::Value id) { - uint256 nftID; - BEAST_EXPECT(nftID.parseHex(id.asString())); - return nftID; - }); + // Convert NFT IDs from Json::Value to uint256 + std::vector metaIDs; + std::transform( + meta[jss::nftoken_ids].begin(), + meta[jss::nftoken_ids].end(), + std::back_inserter(metaIDs), + [this](Json::Value id) { + uint256 nftID; + BEAST_EXPECT(nftID.parseHex(id.asString())); + return nftID; + }); - // Sort both array to prepare for comparison - std::sort(metaIDs.begin(), metaIDs.end()); - std::sort(actualNftIDs.begin(), actualNftIDs.end()); + // Sort both array to prepare for comparison + std::sort(metaIDs.begin(), metaIDs.end()); + std::sort(actualNftIDs.begin(), actualNftIDs.end()); - // Make sure the expect number of NFTs is correct - BEAST_EXPECT(metaIDs.size() == actualNftIDs.size()); + // Make sure the expect number of NFTs is correct + BEAST_EXPECT(metaIDs.size() == actualNftIDs.size()); - // Check the value of NFT ID in the meta with the - // actual values - for (size_t i = 0; i < metaIDs.size(); ++i) - BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]); - }; + // Check the value of NFT ID in the meta with the + // actual values + for (size_t i = 0; i < metaIDs.size(); ++i) + BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]); + }; // Verify `offer_id` value equals to the offerID that was // changed in the most recent NFTokenCreateOffer tx auto verifyNFTokenOfferID = [&](uint256 const& offerID) { // Get the hash for the most recent transaction. - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; env.close(); - Json::Value const meta = - env.rpc("tx", txHash)[jss::result][jss::meta]; + Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta]; // Expect offer_id field and verify the value if (!BEAST_EXPECT(meta.isMember(jss::offer_id))) @@ -6490,14 +5750,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // Alice mints 2 NFTs // Verify the NFTokenIDs are correct in the NFTokenMint tx meta - uint256 const nftId1{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId1{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); verifyNFTokenID(nftId1); - uint256 const nftId2{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId2{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); verifyNFTokenID(nftId2); @@ -6505,32 +5763,26 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Alice creates one sell offer for each NFT // Verify the offer indexes are correct in the NFTokenCreateOffer tx // meta - uint256 const aliceOfferIndex1 = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId1, drops(1)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex1 = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId1, drops(1)), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(aliceOfferIndex1); - uint256 const aliceOfferIndex2 = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId2, drops(1)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex2 = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId2, drops(1)), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(aliceOfferIndex2); // Alice cancels two offers she created // Verify the NFTokenIDs are correct in the NFTokenCancelOffer tx // meta - env(token::cancelOffer( - alice, {aliceOfferIndex1, aliceOfferIndex2})); + env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2})); env.close(); verifyNFTokenIDsInCancelOffer({nftId1, nftId2}); // Bobs creates a buy offer for nftId1 // Verify the offer id is correct in the NFTokenCreateOffer tx meta - auto const bobBuyOfferIndex = - keylet::nftoffer(bob, env.seq(bob)).key; + auto const bobBuyOfferIndex = keylet::nftoffer(bob, env.seq(bob)).key; env(token::createOffer(bob, nftId1, drops(1)), token::owner(alice)); env.close(); verifyNFTokenOfferID(bobBuyOfferIndex); @@ -6545,31 +5797,25 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Check `nftoken_ids` in brokered mode { // Alice mints a NFT - uint256 const nftId{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); verifyNFTokenID(nftId); // Alice creates sell offer and set broker as destination - uint256 const offerAliceToBroker = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId, drops(1)), - token::destination(broker), - txflags(tfSellNFToken)); + uint256 const offerAliceToBroker = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId, drops(1)), token::destination(broker), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(offerAliceToBroker); // Bob creates buy offer - uint256 const offerBobToBroker = - keylet::nftoffer(bob, env.seq(bob)).key; + uint256 const offerBobToBroker = keylet::nftoffer(bob, env.seq(bob)).key; env(token::createOffer(bob, nftId, drops(1)), token::owner(alice)); env.close(); verifyNFTokenOfferID(offerBobToBroker); // Check NFTokenID meta for NFTokenAcceptOffer in brokered mode - env(token::brokerOffers( - broker, offerBobToBroker, offerAliceToBroker)); + env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker)); env.close(); verifyNFTokenID(nftId); } @@ -6578,39 +5824,32 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // multiple offers are cancelled for the same NFT { // Alice mints a NFT - uint256 const nftId{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); verifyNFTokenID(nftId); // Alice creates 2 sell offers for the same NFT - uint256 const aliceOfferIndex1 = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId, drops(1)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex1 = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId, drops(1)), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(aliceOfferIndex1); - uint256 const aliceOfferIndex2 = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId, drops(1)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex2 = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId, drops(1)), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(aliceOfferIndex2); // Make sure the metadata only has 1 nft id, since both offers are // for the same nft - env(token::cancelOffer( - alice, {aliceOfferIndex1, aliceOfferIndex2})); + env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2})); env.close(); verifyNFTokenIDsInCancelOffer({nftId}); } if (features[featureNFTokenMintOffer]) { - uint256 const aliceMintWithOfferIndex1 = - keylet::nftoffer(alice, env.seq(alice)).key; + uint256 const aliceMintWithOfferIndex1 = keylet::nftoffer(alice, env.seq(alice)).key; env(token::mint(alice), token::amount(XRP(0))); env.close(); verifyNFTokenOfferID(aliceMintWithOfferIndex1); @@ -6625,18 +5864,15 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite using namespace test::jtx; // Lambda that mints an NFT and then creates a sell offer - auto mintAndCreateSellOffer = [](test::jtx::Env& env, - test::jtx::Account const& acct, - STAmount const amt) -> uint256 { + auto mintAndCreateSellOffer = + [](test::jtx::Env& env, test::jtx::Account const& acct, STAmount const amt) -> uint256 { // acct mints a NFT - uint256 const nftId{ - token::getNextID(env, acct, 0u, tfTransferable)}; + uint256 const nftId{token::getNextID(env, acct, 0u, tfTransferable)}; env(token::mint(acct, 0u), txflags(tfTransferable)); env.close(); // acct makes an sell offer - uint256 const sellOfferIndex = - keylet::nftoffer(acct, env.seq(acct)).key; + uint256 const sellOfferIndex = keylet::nftoffer(acct, env.seq(acct)).key; env(token::createOffer(acct, nftId, amt), txflags(tfSellNFToken)); env.close(); @@ -6663,8 +5899,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // alice mints an NFT and create a sell offer for 0 XRP - auto const sellOfferIndex = - mintAndCreateSellOffer(env, alice, XRP(0)); + auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0)); // Bob owns no object BEAST_EXPECT(ownerCount(env, bob) == 0); @@ -6693,8 +5928,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // Bob is not able to accept the offer with only the account // reserve (200,000,000 drops) - env(token::acceptSellOffer(bob, sellOfferIndex), - ter(tecINSUFFICIENT_RESERVE)); + env(token::acceptSellOffer(bob, sellOfferIndex), ter(tecINSUFFICIENT_RESERVE)); env.close(); // after prev transaction, Bob owns `200M - base fee` drops due @@ -6710,8 +5944,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // However, this transaction will still fail because the reserve // requirement is `base fee` drops higher - env(token::acceptSellOffer(bob, sellOfferIndex), - ter(tecINSUFFICIENT_RESERVE)); + env(token::acceptSellOffer(bob, sellOfferIndex), ter(tecINSUFFICIENT_RESERVE)); env.close(); // Send bob `base fee * 2` drops @@ -6749,8 +5982,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite for (size_t i = 0; i < 200; i++) { // alice mints an NFT and creates a sell offer for 0 XRP - auto const sellOfferIndex = - mintAndCreateSellOffer(env, alice, XRP(0)); + auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0)); // Bob is able to accept the offer env(token::acceptSellOffer(bob, sellOfferIndex)); @@ -6760,13 +5992,11 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite else { // alice mints the first NFT and creates a sell offer for 0 XRP - auto const sellOfferIndex1 = - mintAndCreateSellOffer(env, alice, XRP(0)); + auto const sellOfferIndex1 = mintAndCreateSellOffer(env, alice, XRP(0)); // Bob cannot accept this offer because he doesn't have the // reserve for the NFT - env(token::acceptSellOffer(bob, sellOfferIndex1), - ter(tecINSUFFICIENT_RESERVE)); + env(token::acceptSellOffer(bob, sellOfferIndex1), ter(tecINSUFFICIENT_RESERVE)); env.close(); // Give bob enough reserve @@ -6786,8 +6016,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite for (size_t i = 0; i < 31; i++) { // alice mints an NFT and creates a sell offer for 0 XRP - auto const sellOfferIndex = - mintAndCreateSellOffer(env, alice, XRP(0)); + auto const sellOfferIndex = mintAndCreateSellOffer(env, alice, XRP(0)); // Bob can accept the offer because the new NFT is stored in // an existing NFTokenPage so no new reserve is required @@ -6799,13 +6028,11 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // alice now mints the 33rd NFT and creates an sell offer for 0 // XRP - auto const sellOfferIndex33 = - mintAndCreateSellOffer(env, alice, XRP(0)); + auto const sellOfferIndex33 = mintAndCreateSellOffer(env, alice, XRP(0)); // Bob fails to accept this NFT because he does not have enough // reserve for a new NFTokenPage - env(token::acceptSellOffer(bob, sellOfferIndex33), - ter(tecINSUFFICIENT_RESERVE)); + env(token::acceptSellOffer(bob, sellOfferIndex33), ter(tecINSUFFICIENT_RESERVE)); env.close(); // Send bob incremental reserve @@ -6845,8 +6072,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // Alice mints a NFT - uint256 const nftId{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); @@ -6858,8 +6084,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // accepting the buy offer fails because bob's balance is `base fee` // drops lower than the required amount, since the previous tx burnt // drops for tx fee. - env(token::acceptBuyOffer(alice, buyOfferIndex), - ter(tecINSUFFICIENT_FUNDS)); + env(token::acceptBuyOffer(alice, buyOfferIndex), ter(tecINSUFFICIENT_FUNDS)); env.close(); // send Bob `base fee` drops @@ -6895,22 +6120,17 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // Alice mints a NFT - uint256 const nftId{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); // Alice creates sell offer and set broker as destination - uint256 const offerAliceToBroker = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId, XRP(1)), - token::destination(broker), - txflags(tfSellNFToken)); + uint256 const offerAliceToBroker = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId, XRP(1)), token::destination(broker), txflags(tfSellNFToken)); env.close(); // Bob creates buy offer - uint256 const offerBobToBroker = - keylet::nftoffer(bob, env.seq(bob)).key; + uint256 const offerBobToBroker = keylet::nftoffer(bob, env.seq(bob)).key; env(token::createOffer(bob, nftId, XRP(1)), token::owner(alice)); env.close(); @@ -6918,9 +6138,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Returns insufficient funds, because bob burnt tx fee when he // created his buy offer, which makes his spendable balance to be // less than the required amount. - env(token::brokerOffers( - broker, offerBobToBroker, offerAliceToBroker), - ter(tecINSUFFICIENT_FUNDS)); + env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker), ter(tecINSUFFICIENT_FUNDS)); env.close(); // send Bob `base fee` drops @@ -6928,8 +6146,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // broker offers. - env(token::brokerOffers( - broker, offerBobToBroker, offerAliceToBroker)); + env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker)); env.close(); } } @@ -6974,11 +6191,9 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // // In both cases we remove the fixRemoveNFTokenAutoTrustLine amendment. // Otherwise we can't create NFTokens with tfTrustLine enabled. - FeatureBitset const localFeatures = - features - fixRemoveNFTokenAutoTrustLine; + FeatureBitset const localFeatures = features - fixRemoveNFTokenAutoTrustLine; for (FeatureBitset feats : - {localFeatures - fixEnforceNFTokenTrustline, - localFeatures | fixEnforceNFTokenTrustline}) + {localFeatures - fixEnforceNFTokenTrustline, localFeatures | fixEnforceNFTokenTrustline}) { Env env{*this, feats}; env.fund(XRP(1000), issuer, becky, cheri, gw); @@ -6993,31 +6208,21 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // issuer creates two NFTs: one with and one without AutoTrustLine. std::uint16_t xferFee = 5000; // 5% - uint256 const nftAutoTrustID{token::getNextID( - env, issuer, 0u, tfTransferable | tfTrustLine, xferFee)}; - env(token::mint(issuer, 0u), - token::xferFee(xferFee), - txflags(tfTransferable | tfTrustLine)); + uint256 const nftAutoTrustID{token::getNextID(env, issuer, 0u, tfTransferable | tfTrustLine, xferFee)}; + env(token::mint(issuer, 0u), token::xferFee(xferFee), txflags(tfTransferable | tfTrustLine)); env.close(); - uint256 const nftNoAutoTrustID{ - token::getNextID(env, issuer, 0u, tfTransferable, xferFee)}; - env(token::mint(issuer, 0u), - token::xferFee(xferFee), - txflags(tfTransferable)); + uint256 const nftNoAutoTrustID{token::getNextID(env, issuer, 0u, tfTransferable, xferFee)}; + env(token::mint(issuer, 0u), token::xferFee(xferFee), txflags(tfTransferable)); env.close(); // becky buys the nfts for 1 drop each. { - uint256 const beckyBuyOfferIndex1 = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAutoTrustID, drops(1)), - token::owner(issuer)); + uint256 const beckyBuyOfferIndex1 = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAutoTrustID, drops(1)), token::owner(issuer)); - uint256 const beckyBuyOfferIndex2 = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), - token::owner(issuer)); + uint256 const beckyBuyOfferIndex2 = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), token::owner(issuer)); env.close(); env(token::acceptBuyOffer(issuer, beckyBuyOfferIndex1)); @@ -7026,17 +6231,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } // becky creates offers to sell the nfts for AUD. - uint256 const beckyAutoTrustOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)), - txflags(tfSellNFToken)); + uint256 const beckyAutoTrustOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAutoTrustID, gwAUD(100)), txflags(tfSellNFToken)); env.close(); // Creating an offer for the NFToken without tfTrustLine fails // because issuer does not have a trust line for AUD. - env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)), - txflags(tfSellNFToken), - ter(tecNO_LINE)); + env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)), txflags(tfSellNFToken), ter(tecNO_LINE)); env.close(); // issuer creates a trust line. Now the offer create for the @@ -7046,10 +6247,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 1); - uint256 const beckyNoAutoTrustOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)), - txflags(tfSellNFToken)); + uint256 const beckyNoAutoTrustOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftNoAutoTrustID, gwAUD(100)), txflags(tfSellNFToken)); env.close(); // Now that the offers are in place, issuer removes the trustline. @@ -7079,8 +6278,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // With fixEnforceNFTokenTrustline cheri can't accept the // offer because issuer could not get their transfer fee // without the appropriate trustline. - env(token::acceptSellOffer(cheri, beckyNoAutoTrustOfferIndex), - ter(tecNO_LINE)); + env(token::acceptSellOffer(cheri, beckyNoAutoTrustOfferIndex), ter(tecNO_LINE)); env.close(); // But if issuer re-establishes the trustline then the offer @@ -7145,8 +6343,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // // We remove the fixRemoveNFTokenAutoTrustLine amendment. Otherwise // we can't create NFTokens with tfTrustLine enabled. - FeatureBitset const localFeatures = - features - fixRemoveNFTokenAutoTrustLine; + FeatureBitset const localFeatures = features - fixRemoveNFTokenAutoTrustLine; Env env{*this, localFeatures}; env.fund(XRP(1000), issuer, becky, cheri); @@ -7161,31 +6358,21 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // issuer creates two NFTs: one with and one without AutoTrustLine. std::uint16_t xferFee = 5000; // 5% - uint256 const nftAutoTrustID{token::getNextID( - env, issuer, 0u, tfTransferable | tfTrustLine, xferFee)}; - env(token::mint(issuer, 0u), - token::xferFee(xferFee), - txflags(tfTransferable | tfTrustLine)); + uint256 const nftAutoTrustID{token::getNextID(env, issuer, 0u, tfTransferable | tfTrustLine, xferFee)}; + env(token::mint(issuer, 0u), token::xferFee(xferFee), txflags(tfTransferable | tfTrustLine)); env.close(); - uint256 const nftNoAutoTrustID{ - token::getNextID(env, issuer, 0u, tfTransferable, xferFee)}; - env(token::mint(issuer, 0u), - token::xferFee(xferFee), - txflags(tfTransferable)); + uint256 const nftNoAutoTrustID{token::getNextID(env, issuer, 0u, tfTransferable, xferFee)}; + env(token::mint(issuer, 0u), token::xferFee(xferFee), txflags(tfTransferable)); env.close(); // becky buys the nfts for 1 drop each. { - uint256 const beckyBuyOfferIndex1 = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAutoTrustID, drops(1)), - token::owner(issuer)); + uint256 const beckyBuyOfferIndex1 = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAutoTrustID, drops(1)), token::owner(issuer)); - uint256 const beckyBuyOfferIndex2 = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), - token::owner(issuer)); + uint256 const beckyBuyOfferIndex2 = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftNoAutoTrustID, drops(1)), token::owner(issuer)); env.close(); env(token::acceptBuyOffer(issuer, beckyBuyOfferIndex1)); @@ -7200,9 +6387,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // Without featureNFTokenMintOffer becky simply can't // create an offer for a non-tfTrustLine NFToken that would // pay the transfer fee in issuer's own IOU. - env(token::createOffer(becky, nftNoAutoTrustID, isISU(100)), - txflags(tfSellNFToken), - ter(tecNO_LINE)); + env(token::createOffer(becky, nftNoAutoTrustID, isISU(100)), txflags(tfSellNFToken), ter(tecNO_LINE)); env.close(); // And issuer can't create a trust line to themselves. @@ -7211,10 +6396,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite // However if the NFToken has the tfTrustLine flag set, // then becky can create the offer. - uint256 const beckyAutoTrustOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAutoTrustID, isISU(100)), - txflags(tfSellNFToken)); + uint256 const beckyAutoTrustOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAutoTrustID, isISU(100)), txflags(tfSellNFToken)); env.close(); // And cheri can accept the offer. @@ -7230,15 +6413,11 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // With featureNFTokenMintOffer things go better. // becky creates offers to sell the nfts for ISU. - uint256 const beckyNoAutoTrustOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftNoAutoTrustID, isISU(100)), - txflags(tfSellNFToken)); + uint256 const beckyNoAutoTrustOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftNoAutoTrustID, isISU(100)), txflags(tfSellNFToken)); env.close(); - uint256 const beckyAutoTrustOfferIndex = - keylet::nftoffer(becky, env.seq(becky)).key; - env(token::createOffer(becky, nftAutoTrustID, isISU(100)), - txflags(tfSellNFToken)); + uint256 const beckyAutoTrustOfferIndex = keylet::nftoffer(becky, env.seq(becky)).key; + env(token::createOffer(becky, nftAutoTrustID, isISU(100)), txflags(tfSellNFToken)); env.close(); // cheri accepts becky's offers. Behavior is uniform: @@ -7281,8 +6460,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.fund(XRP(10000), issuer); env.close(); - auto const expectedTer = - modifyEnabled ? TER{tesSUCCESS} : TER{temINVALID_FLAG}; + auto const expectedTer = modifyEnabled ? TER{tesSUCCESS} : TER{temINVALID_FLAG}; env(token::mint(issuer, 0u), txflags(tfMutable), ter(expectedTer)); env.close(); } @@ -7322,32 +6500,22 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); // Set a negative fee. Exercises invalid preflight1. - env(token::modify(issuer, nftId), - fee(STAmount(10ull, true)), - ter(temBAD_FEE)); + env(token::modify(issuer, nftId), fee(STAmount(10ull, true)), ter(temBAD_FEE)); env.close(); // Invalid Flags - env(token::modify(issuer, nftId), - txflags(0x00000001), - ter(temINVALID_FLAG)); + env(token::modify(issuer, nftId), txflags(0x00000001), ter(temINVALID_FLAG)); // Invalid Owner - env(token::modify(issuer, nftId), - token::owner(issuer), - ter(temMALFORMED)); + env(token::modify(issuer, nftId), token::owner(issuer), ter(temMALFORMED)); env.close(); // Invalid URI length = 0 - env(token::modify(issuer, nftId), - token::uri(""), - ter(temMALFORMED)); + env(token::modify(issuer, nftId), token::uri(""), ter(temMALFORMED)); env.close(); // Invalid URI length > 256 - env(token::modify(issuer, nftId), - token::uri(std::string(maxTokenURILength + 1, 'q')), - ter(temMALFORMED)); + env(token::modify(issuer, nftId), token::uri(std::string(maxTokenURILength + 1, 'q')), ter(temMALFORMED)); env.close(); } { @@ -7357,8 +6525,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite { // NFToken not exists - uint256 const nftIDNotExists{ - token::getNextID(env, issuer, 0u, tfMutable)}; + uint256 const nftIDNotExists{token::getNextID(env, issuer, 0u, tfMutable)}; env.close(); env(token::modify(issuer, nftIDNotExists), ter(tecNO_ENTRY)); @@ -7366,33 +6533,26 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite } { // Invalid NFToken flag - uint256 const nftIDNotModifiable{ - token::getNextID(env, issuer, 0u)}; + uint256 const nftIDNotModifiable{token::getNextID(env, issuer, 0u)}; env(token::mint(issuer, 0u)); env.close(); - env(token::modify(issuer, nftIDNotModifiable), - ter(tecNO_PERMISSION)); + env(token::modify(issuer, nftIDNotModifiable), ter(tecNO_PERMISSION)); env.close(); } { // Unauthorized account - uint256 const nftId{ - token::getNextID(env, issuer, 0u, tfMutable)}; + uint256 const nftId{token::getNextID(env, issuer, 0u, tfMutable)}; env(token::mint(issuer, 0u), txflags(tfMutable)); env.close(); - env(token::modify(bob, nftId), - token::owner(issuer), - ter(tecNO_PERMISSION)); + env(token::modify(bob, nftId), token::owner(issuer), ter(tecNO_PERMISSION)); env.close(); env(token::setMinter(issuer, alice)); env.close(); - env(token::modify(bob, nftId), - token::owner(issuer), - ter(tecNO_PERMISSION)); + env(token::modify(bob, nftId), token::owner(issuer), ter(tecNO_PERMISSION)); env.close(); } } @@ -7419,16 +6579,12 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite Json::Value params; params[jss::account] = acct.human(); params[jss::type] = "state"; - auto response = - env.rpc("json", "account_nfts", to_string(params)); + auto response = env.rpc("json", "account_nfts", to_string(params)); return response[jss::result][jss::account_nfts]; }; // lambda that checks for the expected URI value of an NFToken - auto checkURI = [&accountNFTs, this]( - Account const& acct, - char const* uri, - int line) { + auto checkURI = [&accountNFTs, this](Account const& acct, char const* uri, int line) { auto const nfts = accountNFTs(acct); if (nfts.size() == 1) pass(); @@ -7447,8 +6603,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite else { std::ostringstream text; - text << "checkURI: unexpected URI present on line " - << line; + text << "checkURI: unexpected URI present on line " << line; fail(text.str(), __FILE__, line); } return; @@ -7459,8 +6614,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite else { std::ostringstream text; - text << "checkURI: unexpected URI contents on line " - << line; + text << "checkURI: unexpected URI contents on line " << line; fail(text.str(), __FILE__, line); } }; @@ -7488,10 +6642,8 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite checkURI(issuer, "uri", __LINE__); // Account != Owner - uint256 const offerID = - keylet::nftoffer(issuer, env.seq(issuer)).key; - env(token::createOffer(issuer, nftId, XRP(0)), - txflags(tfSellNFToken)); + uint256 const offerID = keylet::nftoffer(issuer, env.seq(issuer)).key; + env(token::createOffer(issuer, nftId, XRP(0)), txflags(tfSellNFToken)); env.close(); env(token::acceptSellOffer(alice, offerID)); env.close(); @@ -7500,17 +6652,13 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite checkURI(alice, "uri", __LINE__); // Modify by owner fails. - env(token::modify(alice, nftId), - token::uri("new_uri"), - ter(tecNO_PERMISSION)); + env(token::modify(alice, nftId), token::uri("new_uri"), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, alice) == 1); checkURI(alice, "uri", __LINE__); - env(token::modify(issuer, nftId), - token::owner(alice), - token::uri("new_uri")); + env(token::modify(issuer, nftId), token::owner(alice), token::uri("new_uri")); env.close(); BEAST_EXPECT(ownerCount(env, issuer) == 0); BEAST_EXPECT(ownerCount(env, alice) == 1); @@ -7520,18 +6668,14 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); checkURI(alice, nullptr, __LINE__); - env(token::modify(issuer, nftId), - token::owner(alice), - token::uri("uri")); + env(token::modify(issuer, nftId), token::owner(alice), token::uri("uri")); env.close(); checkURI(alice, "uri", __LINE__); // Modify by authorized minter env(token::setMinter(issuer, bob)); env.close(); - env(token::modify(bob, nftId), - token::owner(alice), - token::uri("new_uri")); + env(token::modify(bob, nftId), token::owner(alice), token::uri("new_uri")); env.close(); checkURI(alice, "new_uri", __LINE__); @@ -7539,9 +6683,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite env.close(); checkURI(alice, nullptr, __LINE__); - env(token::modify(bob, nftId), - token::owner(alice), - token::uri("uri")); + env(token::modify(bob, nftId), token::owner(alice), token::uri("uri")); env.close(); checkURI(alice, "uri", __LINE__); } @@ -7594,9 +6736,7 @@ public: void run() override { - testWithFeats( - allFeatures - fixNFTokenReserve - featureNFTokenMintOffer - - featureDynamicNFT); + testWithFeats(allFeatures - fixNFTokenReserve - featureNFTokenMintOffer - featureDynamicNFT); } }; @@ -7605,9 +6745,7 @@ class NFTokenDisallowIncoming_test : public NFTokenBaseUtil_test void run() override { - testWithFeats( - allFeatures - fixNFTokenReserve - featureNFTokenMintOffer - - featureDynamicNFT); + testWithFeats(allFeatures - fixNFTokenReserve - featureNFTokenMintOffer - featureDynamicNFT); } }; @@ -7616,8 +6754,7 @@ class NFTokenWOMintOffer_test : public NFTokenBaseUtil_test void run() override { - testWithFeats( - allFeatures - featureNFTokenMintOffer - featureDynamicNFT); + testWithFeats(allFeatures - featureNFTokenMintOffer - featureDynamicNFT); } }; diff --git a/src/test/app/NetworkID_test.cpp b/src/test/app/NetworkID_test.cpp index d924710cb3..5fddc8f641 100644 --- a/src/test/app/NetworkID_test.cpp +++ b/src/test/app/NetworkID_test.cpp @@ -37,9 +37,7 @@ public: auto const alice = Account{"alice"}; - auto const runTx = [&](test::jtx::Env& env, - Json::Value const& jv, - TER expectedOutcome) { + auto const runTx = [&](test::jtx::Env& env, Json::Value const& jv, TER expectedOutcome) { env.memoize(env.master); env.memoize(alice); @@ -117,10 +115,7 @@ public: Serializer s; jt.stx->add(s); BEAST_EXPECT( - env.rpc( - "submit", - strHex(s.slice()))[jss::result][jss::engine_result] == - "telREQUIRES_NETWORK_ID"); + env.rpc("submit", strHex(s.slice()))[jss::result][jss::engine_result] == "telREQUIRES_NETWORK_ID"); env.close(); } diff --git a/src/test/app/NetworkOPs_test.cpp b/src/test/app/NetworkOPs_test.cpp index 582f9a8084..ffca1ed79d 100644 --- a/src/test/app/NetworkOPs_test.cpp +++ b/src/test/app/NetworkOPs_test.cpp @@ -28,30 +28,23 @@ public: { using namespace jtx; auto const alice = Account{"alice"}; - Env env{ - *this, - envconfig(), - std::make_unique(&logs), - beast::severities::kAll}; + Env env{*this, envconfig(), std::make_unique(&logs), beast::severities::kAll}; env.memoize(env.master); env.memoize(alice); auto const jtx = env.jt(ticket::create(alice, 1), seq(1), fee(10)); auto transactionId = jtx.stx->getTransactionID(); - env.app().getHashRouter().setFlags( - transactionId, HashRouterFlags::HELD); + env.app().getHashRouter().setFlags(transactionId, HashRouterFlags::HELD); env(jtx, json(jss::Sequence, 1), ter(terNO_ACCOUNT)); - env.app().getHashRouter().setFlags( - transactionId, HashRouterFlags::BAD); + env.app().getHashRouter().setFlags(transactionId, HashRouterFlags::BAD); env.close(); } - BEAST_EXPECT( - logs.find("No transaction to process!") != std::string::npos); + BEAST_EXPECT(logs.find("No transaction to process!") != std::string::npos); } }; diff --git a/src/test/app/Offer_test.cpp b/src/test/app/Offer_test.cpp index f1d68ece1e..09d7e41141 100644 --- a/src/test/app/Offer_test.cpp +++ b/src/test/app/Offer_test.cpp @@ -20,30 +20,20 @@ class OfferBaseUtil_test : public beast::unit_test::suite std::uint32_t lastClose(jtx::Env& env) { - return env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count(); + return env.current()->header().parentCloseTime.time_since_epoch().count(); } static auto - ledgerEntryOffer( - jtx::Env& env, - jtx::Account const& acct, - std::uint32_t offer_seq) + ledgerEntryOffer(jtx::Env& env, jtx::Account const& acct, std::uint32_t offer_seq) { Json::Value jvParams; jvParams[jss::offer][jss::account] = acct.human(); jvParams[jss::offer][jss::seq] = offer_seq; - return env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; } static auto - getBookOffers( - jtx::Env& env, - Issue const& taker_pays, - Issue const& taker_gets) + getBookOffers(jtx::Env& env, Issue const& taker_pays, Issue const& taker_gets) { Json::Value jvbp; jvbp[jss::ledger_index] = "current"; @@ -105,15 +95,10 @@ public: PathSet paths(Path(XRP, USD), Path(USD)); - env(pay(alice, bob, USD(100)), - json(paths.json()), - sendmax(BTC(1000)), - txflags(tfPartialPayment)); + env(pay(alice, bob, USD(100)), json(paths.json()), sendmax(BTC(1000)), txflags(tfPartialPayment)); env.require(balance(bob, USD(100))); - BEAST_EXPECT( - !isOffer(env, carol, BTC(1), USD(100)) && - isOffer(env, carol, BTC(49), XRP(49))); + BEAST_EXPECT(!isOffer(env, carol, BTC(1), USD(100)) && isOffer(env, carol, BTC(49), XRP(49))); } void @@ -146,26 +131,18 @@ public: // cancel the offer above and replace it with a new offer auto const offer2Seq = env.seq(alice); - env(offer(alice, XRP(300), USD(100)), - json(jss::OfferSequence, offer1Seq), - require(offers(alice, 1))); + env(offer(alice, XRP(300), USD(100)), json(jss::OfferSequence, offer1Seq), require(offers(alice, 1))); env.close(); - BEAST_EXPECT( - isOffer(env, alice, XRP(300), USD(100)) && - !isOffer(env, alice, XRP(500), USD(100))); + BEAST_EXPECT(isOffer(env, alice, XRP(300), USD(100)) && !isOffer(env, alice, XRP(500), USD(100))); // Test canceling non-existent offer. // auto const offer3Seq = env.seq (alice); - env(offer(alice, XRP(400), USD(200)), - json(jss::OfferSequence, offer1Seq), - require(offers(alice, 2))); + env(offer(alice, XRP(400), USD(200)), json(jss::OfferSequence, offer1Seq), require(offers(alice, 2))); env.close(); - BEAST_EXPECT( - isOffer(env, alice, XRP(300), USD(100)) && - isOffer(env, alice, XRP(400), USD(200))); + BEAST_EXPECT(isOffer(env, alice, XRP(300), USD(100)) && isOffer(env, alice, XRP(400), USD(200))); // Test cancellation now with OfferCancel tx auto const offer4Seq = env.seq(alice); @@ -289,10 +266,7 @@ public: // stAmountCalcSwitchover2 was inactive.) env(offer(erin, drops(2), USD(1))); - env(pay(alice, bob, USD(1)), - path(~USD), - sendmax(XRP(102)), - txflags(tfNoRippleDirect | tfPartialPayment)); + env(pay(alice, bob, USD(1)), path(~USD), sendmax(XRP(102)), txflags(tfNoRippleDirect | tfPartialPayment)); env.require(offers(carol, 0), offers(dan, 1)); @@ -347,22 +321,15 @@ public: env(offer(alice, USD(1), aliceTakerGets)); env.close(); - env.require( - offers(carol, 0), - balance( - carol, - initialCarolUSD)); // offer is removed but not taken + env.require(offers(carol, 0), balance(carol, + initialCarolUSD)); // offer is removed but not taken if (crossBothOffers) { - env.require( - offers(alice, 0), - balance(alice, USD(1))); // alice's offer is crossed + env.require(offers(alice, 0), balance(alice, USD(1))); // alice's offer is crossed } else { - env.require( - offers(alice, 1), - balance(alice, USD(0))); // alice's offer is not crossed + env.require(offers(alice, 1), balance(alice, USD(0))); // alice's offer is not crossed } } @@ -386,26 +353,18 @@ public: env.close(); env.require(offers(bob, 1), offers(carol, 1)); - std::uint32_t const flags = partialPayment - ? (tfNoRippleDirect | tfPartialPayment) - : tfNoRippleDirect; + std::uint32_t const flags = partialPayment ? (tfNoRippleDirect | tfPartialPayment) : tfNoRippleDirect; - TER const expectedTer = - partialPayment ? TER{tesSUCCESS} : TER{tecPATH_PARTIAL}; + TER const expectedTer = partialPayment ? TER{tesSUCCESS} : TER{tecPATH_PARTIAL}; - env(pay(alice, bob, USD(5)), - path(~USD), - sendmax(XRP(1)), - txflags(flags), - ter(expectedTer)); + env(pay(alice, bob, USD(5)), path(~USD), sendmax(XRP(1)), txflags(flags), ter(expectedTer)); env.close(); if (expectedTer == tesSUCCESS) { env.require(offers(carol, 0)); - env.require(balance( - carol, - initialCarolUSD)); // offer is removed but not taken + env.require(balance(carol, + initialCarolUSD)); // offer is removed but not taken } else { @@ -475,22 +434,15 @@ public: env(offer(alice, USD(1), aliceTakerGets)); env.close(); - env.require( - offers(carol, 0), - balance( - carol, - initialCarolUSD)); // offer is removed but not taken + env.require(offers(carol, 0), balance(carol, + initialCarolUSD)); // offer is removed but not taken if (crossBothOffers) { - env.require( - offers(alice, 0), - balance(alice, USD(1))); // alice's offer is crossed + env.require(offers(alice, 0), balance(alice, USD(1))); // alice's offer is crossed } else { - env.require( - offers(alice, 1), - balance(alice, USD(0))); // alice's offer is not crossed + env.require(offers(alice, 1), balance(alice, USD(0))); // alice's offer is not crossed } } @@ -517,26 +469,18 @@ public: env.close(); env.require(offers(bob, 1), offers(carol, 1)); - std::uint32_t const flags = partialPayment - ? (tfNoRippleDirect | tfPartialPayment) - : tfNoRippleDirect; + std::uint32_t const flags = partialPayment ? (tfNoRippleDirect | tfPartialPayment) : tfNoRippleDirect; - TER const expectedTer = - partialPayment ? TER{tesSUCCESS} : TER{tecPATH_PARTIAL}; + TER const expectedTer = partialPayment ? TER{tesSUCCESS} : TER{tecPATH_PARTIAL}; - env(pay(alice, bob, USD(5)), - path(~USD), - sendmax(EUR(10)), - txflags(flags), - ter(expectedTer)); + env(pay(alice, bob, USD(5)), path(~USD), sendmax(EUR(10)), txflags(flags), ter(expectedTer)); env.close(); if (expectedTer == tesSUCCESS) { env.require(offers(carol, 0)); - env.require(balance( - carol, - initialCarolUSD)); // offer is removed but not taken + env.require(balance(carol, + initialCarolUSD)); // offer is removed but not taken } else { @@ -612,10 +556,7 @@ public: env(offer(dan, XRP(50), USD1(50))); - env(pay(alice, carol, USD2(50)), - path(~USD1, bob), - sendmax(XRP(50)), - txflags(tfNoRippleDirect)); + env(pay(alice, carol, USD2(50)), path(~USD1, bob), sendmax(XRP(50)), txflags(tfNoRippleDirect)); env.require(balance(alice, xrpMinusFee(env, 10000 - 50))); env.require(balance(bob, USD1(100))); @@ -737,13 +678,10 @@ public: offersOnAccount(jtx::Env& env, jtx::Account account) { std::vector> result; - forEachItem( - *env.current(), - account, - [&result](std::shared_ptr const& sle) { - if (sle->getType() == ltOFFER) - result.push_back(sle); - }); + forEachItem(*env.current(), account, [&result](std::shared_ptr const& sle) { + if (sle->getType() == ltOFFER) + result.push_back(sle); + }); return result; } @@ -772,9 +710,7 @@ public: env.close(); // bob creates an offer that expires before the next ledger close. - env(offer(bob, USD(500), XRP(500)), - json(sfExpiration.fieldName, lastClose(env) + 1), - ter(tesSUCCESS)); + env(offer(bob, USD(500), XRP(500)), json(sfExpiration.fieldName, lastClose(env) + 1), ter(tesSUCCESS)); // The offer expires (it's not removed yet). env.close(); @@ -791,9 +727,7 @@ public: // Order that can't be filled but will remove bob's expired offer: { TER const killedCode{TER{tecKILLED}}; - env(offer(alice, XRP(1000), USD(1000)), - txflags(tfFillOrKill), - ter(killedCode)); + env(offer(alice, XRP(1000), USD(1000)), txflags(tfFillOrKill), ter(killedCode)); } env.require( balance(alice, startBalance - (f * 2)), @@ -806,9 +740,7 @@ public: offers(bob, 1)); // Order that can be filled - env(offer(alice, XRP(500), USD(500)), - txflags(tfFillOrKill), - ter(tesSUCCESS)); + env(offer(alice, XRP(500), USD(500)), txflags(tfFillOrKill), ter(tesSUCCESS)); env.require( balance(alice, startBalance - (f * 3) + XRP(500)), @@ -837,22 +769,15 @@ public: // No cross: { TER const expectedCode = tecKILLED; - env(offer(alice, XRP(1000), USD(1000)), - txflags(tfImmediateOrCancel), - ter(expectedCode)); + env(offer(alice, XRP(1000), USD(1000)), txflags(tfImmediateOrCancel), ter(expectedCode)); } env.require( - balance(alice, startBalance - f - f), - balance(alice, USD(1000)), - owners(alice, 1), - offers(alice, 0)); + balance(alice, startBalance - f - f), balance(alice, USD(1000)), owners(alice, 1), offers(alice, 0)); // Partially cross: env(offer(bob, USD(50), XRP(50)), ter(tesSUCCESS)); - env(offer(alice, XRP(1000), USD(1000)), - txflags(tfImmediateOrCancel), - ter(tesSUCCESS)); + env(offer(alice, XRP(1000), USD(1000)), txflags(tfImmediateOrCancel), ter(tesSUCCESS)); env.require( balance(alice, startBalance - f - f - f + XRP(50)), @@ -866,9 +791,7 @@ public: // Fully cross: env(offer(bob, USD(50), XRP(50)), ter(tesSUCCESS)); - env(offer(alice, XRP(50), USD(50)), - txflags(tfImmediateOrCancel), - ter(tesSUCCESS)); + env(offer(alice, XRP(50), USD(50)), txflags(tfImmediateOrCancel), ter(tesSUCCESS)); env.require( balance(alice, startBalance - f - f - f - f + XRP(100)), @@ -990,18 +913,12 @@ public: env.close(); // Order that has invalid flags - env(offer(alice, USD(1000), XRP(1000)), - txflags(tfImmediateOrCancel + 1), - ter(temINVALID_FLAG)); - env.require( - balance(alice, startBalance), owners(alice, 0), offers(alice, 0)); + env(offer(alice, USD(1000), XRP(1000)), txflags(tfImmediateOrCancel + 1), ter(temINVALID_FLAG)); + env.require(balance(alice, startBalance), owners(alice, 0), offers(alice, 0)); // Order with incompatible flags - env(offer(alice, USD(1000), XRP(1000)), - txflags(tfImmediateOrCancel | tfFillOrKill), - ter(temINVALID_FLAG)); - env.require( - balance(alice, startBalance), owners(alice, 0), offers(alice, 0)); + env(offer(alice, USD(1000), XRP(1000)), txflags(tfImmediateOrCancel | tfFillOrKill), ter(temINVALID_FLAG)); + env.require(balance(alice, startBalance), owners(alice, 0), offers(alice, 0)); // Sell and buy the same asset { @@ -1035,9 +952,7 @@ public: // Offer with a bad offer sequence { - env(offer(alice, USD(1000), XRP(1000)), - json(jss::OfferSequence, std::uint32_t(0)), - ter(temBAD_SEQUENCE)); + env(offer(alice, USD(1000), XRP(1000)), json(jss::OfferSequence, std::uint32_t(0)), ter(temBAD_SEQUENCE)); env.require(owners(alice, 1), offers(alice, 0)); } @@ -1076,40 +991,22 @@ public: env(trust(alice, usdOffer), ter(tesSUCCESS)); env(pay(gw, alice, usdOffer), ter(tesSUCCESS)); env.close(); - env.require( - balance(alice, startBalance - f), - balance(alice, usdOffer), - offers(alice, 0), - owners(alice, 1)); + env.require(balance(alice, startBalance - f), balance(alice, usdOffer), offers(alice, 0), owners(alice, 1)); - env(offer(alice, xrpOffer, usdOffer), - json(sfExpiration.fieldName, lastClose(env)), - ter(tecEXPIRED)); + env(offer(alice, xrpOffer, usdOffer), json(sfExpiration.fieldName, lastClose(env)), ter(tecEXPIRED)); - env.require( - balance(alice, startBalance - f - f), - balance(alice, usdOffer), - offers(alice, 0), - owners(alice, 1)); + env.require(balance(alice, startBalance - f - f), balance(alice, usdOffer), offers(alice, 0), owners(alice, 1)); env.close(); // Add an offer that expires before the next ledger close - env(offer(alice, xrpOffer, usdOffer), - json(sfExpiration.fieldName, lastClose(env) + 1), - ter(tesSUCCESS)); + env(offer(alice, xrpOffer, usdOffer), json(sfExpiration.fieldName, lastClose(env) + 1), ter(tesSUCCESS)); env.require( - balance(alice, startBalance - f - f - f), - balance(alice, usdOffer), - offers(alice, 1), - owners(alice, 2)); + balance(alice, startBalance - f - f - f), balance(alice, usdOffer), offers(alice, 1), owners(alice, 2)); // The offer expires (it's not removed yet) env.close(); env.require( - balance(alice, startBalance - f - f - f), - balance(alice, usdOffer), - offers(alice, 1), - owners(alice, 2)); + balance(alice, startBalance - f - f - f), balance(alice, usdOffer), offers(alice, 1), owners(alice, 2)); // Add offer - the expired offer is removed env(offer(bob, usdOffer, xrpOffer), ter(tesSUCCESS)); @@ -1165,8 +1062,7 @@ public: env.fund(reserve(env, 0) + f + XRP(1), "carol"); env.close(); env(offer("carol", usdOffer, xrpOffer), ter(tecINSUF_RESERVE_OFFER)); - env.require( - balance("carol", reserve(env, 0) + XRP(1)), owners("carol", 0)); + env.require(balance("carol", reserve(env, 0) + XRP(1)), owners("carol", 0)); // Account has enough for the reserve plus one // offer, and the fee. @@ -1180,16 +1076,13 @@ public: env.fund(reserve(env, 1) + f + xrpOffer, "eve"); env.close(); env(offer("eve", usdOffer, xrpOffer), ter(tesSUCCESS)); - env.require( - balance("eve", reserve(env, 1) + xrpOffer), owners("eve", 1)); + env.require(balance("eve", reserve(env, 1) + xrpOffer), owners("eve", 1)); } void testSelfCross(bool use_partner, FeatureBitset features) { - testcase( - std::string("Self-crossing") + - (use_partner ? ", with partner account" : "")); + testcase(std::string("Self-crossing") + (use_partner ? ", with partner account" : "")); using namespace jtx; @@ -1305,8 +1198,7 @@ public: // This is one of the few tests where fixReducedOffersV2 changes the // results. So test both with and without fixReducedOffersV2. - for (FeatureBitset localFeatures : - {features - fixReducedOffersV2, features | fixReducedOffersV2}) + for (FeatureBitset localFeatures : {features - fixReducedOffersV2, features | fixReducedOffersV2}) { Env env{*this, localFeatures}; @@ -1321,8 +1213,7 @@ public: auto const gw_initial_balance = drops(1149999730); auto const alice_initial_balance = drops(499946999680); auto const bob_initial_balance = drops(10199999920); - auto const small_amount = - STAmount{bob["USD"].issue(), UINT64_C(2710505431213761), -33}; + auto const small_amount = STAmount{bob["USD"].issue(), UINT64_C(2710505431213761), -33}; env.fund(gw_initial_balance, gw); env.fund(alice_initial_balance, alice); @@ -1348,13 +1239,10 @@ public: // verify balances auto jrr = ledgerEntryState(env, alice, gw, "USD"); - BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName][jss::value] == "50"); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "50"); jrr = ledgerEntryState(env, bob, gw, "USD"); - BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName][jss::value] == - "-2710505431213761e-33"); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-2710505431213761e-33"); // create crossing offer std::uint32_t const bobOfferSeq = env.seq(bob); @@ -1366,12 +1254,9 @@ public: // offer does not cross alice's offer and goes straight into // the ledger. jrr = ledgerEntryState(env, bob, gw, "USD"); - BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName][jss::value] == - "-2710505431213761e-33"); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-2710505431213761e-33"); - Json::Value const bobOffer = - ledgerEntryOffer(env, bob, bobOfferSeq)[jss::node]; + Json::Value const bobOffer = ledgerEntryOffer(env, bob, bobOfferSeq)[jss::node]; BEAST_EXPECT(bobOffer[sfTakerGets.jsonName][jss::value] == "1"); BEAST_EXPECT(bobOffer[sfTakerPays.jsonName] == "2000000000"); return; @@ -1387,29 +1272,22 @@ public: auto const crossingDelta = drops(1); jrr = ledgerEntryState(env, alice, gw, "USD"); - BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName][jss::value] == "50"); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "50"); BEAST_EXPECT( env.balance(alice, xrpIssue()) == - alice_initial_balance - env.current()->fees().base * 3 - - crossingDelta); + alice_initial_balance - env.current()->fees().base * 3 - crossingDelta); jrr = ledgerEntryState(env, bob, gw, "USD"); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "0"); BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName][jss::value] == "0"); - BEAST_EXPECT( - env.balance(bob, xrpIssue()) == - bob_initial_balance - env.current()->fees().base * 2 + - crossingDelta); + env.balance(bob, xrpIssue()) == bob_initial_balance - env.current()->fees().base * 2 + crossingDelta); } } void testOfferCrossWithXRP(bool reverse_order, FeatureBitset features) { - testcase( - std::string("Offer Crossing with XRP, ") + - (reverse_order ? "Reverse" : "Normal") + " order"); + testcase(std::string("Offer Crossing with XRP, ") + (reverse_order ? "Reverse" : "Normal") + " order"); using namespace jtx; @@ -1445,18 +1323,14 @@ public: jrr = ledgerEntryRoot(env, bob); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string((XRP(10000) - XRP(reverse_order ? 4000 : 3000) - - env.current()->fees().base * 2) - .xrp())); + to_string((XRP(10000) - XRP(reverse_order ? 4000 : 3000) - env.current()->fees().base * 2).xrp())); jrr = ledgerEntryState(env, alice, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-499"); jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string((XRP(10000) + XRP(reverse_order ? 4000 : 3000) - - env.current()->fees().base * 2) - .xrp())); + to_string((XRP(10000) + XRP(reverse_order ? 4000 : 3000) - env.current()->fees().base * 2).xrp())); } void @@ -1488,16 +1362,14 @@ public: jrr = ledgerEntryRoot(env, bob); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string((XRP(100000) - XRP(3000) - env.current()->fees().base * 1) - .xrp())); + to_string((XRP(100000) - XRP(3000) - env.current()->fees().base * 1).xrp())); jrr = ledgerEntryState(env, alice, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-499"); jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string((XRP(100000) + XRP(3000) - env.current()->fees().base * 2) - .xrp())); + to_string((XRP(100000) + XRP(3000) - env.current()->fees().base * 2).xrp())); } void @@ -1541,11 +1413,9 @@ public: env(offer_cancel(env.master, nextOfferSeq)); - env(offer_cancel(env.master, env.seq(env.master)), - ter(temBAD_SEQUENCE)); + env(offer_cancel(env.master, env.seq(env.master)), ter(temBAD_SEQUENCE)); - env(offer_cancel(env.master, env.seq(env.master) + 1), - ter(temBAD_SEQUENCE)); + env(offer_cancel(env.master, env.seq(env.master) + 1), ter(temBAD_SEQUENCE)); env.close(); } @@ -1579,11 +1449,8 @@ public: env.require(owners(alice, 1), owners(bob, 2)); auto jro = ledgerEntryOffer(env, bob, bobOfferSeq); - BEAST_EXPECT( - jro[jss::node][jss::TakerGets] == XRP(500).value().getText()); - BEAST_EXPECT( - jro[jss::node][jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jro[jss::node][jss::TakerGets] == XRP(500).value().getText()); + BEAST_EXPECT(jro[jss::node][jss::TakerPays] == USD(100).value().getJson(JsonOptions::none)); env(pay(alice, alice, XRP(500)), sendmax(USD(100))); @@ -1592,8 +1459,7 @@ public: jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string((XRP(10000) + XRP(500) - env.current()->fees().base * 2) - .xrp())); + to_string((XRP(10000) + XRP(500) - env.current()->fees().base * 2).xrp())); jrr = ledgerEntryState(env, bob, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-100"); @@ -1625,8 +1491,7 @@ public: env(trust(carol, bob["EUR"](1000))); auto const bobOfferSeq = env.seq(bob); - env(offer(bob, alice["USD"](50), carol["EUR"](200)), - ter(tecUNFUNDED_OFFER)); + env(offer(bob, alice["USD"](50), carol["EUR"](200)), ter(tecUNFUNDED_OFFER)); env(offer(alice, carol["EUR"](200), alice["USD"](50))); @@ -1663,11 +1528,8 @@ public: // The previous payment reduced the remaining offer amount by 200 XRP auto jro = ledgerEntryOffer(env, bob, bobOfferSeq); - BEAST_EXPECT( - jro[jss::node][jss::TakerGets] == XRP(300).value().getText()); - BEAST_EXPECT( - jro[jss::node][jss::TakerPays] == - USD(60).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jro[jss::node][jss::TakerGets] == XRP(300).value().getText()); + BEAST_EXPECT(jro[jss::node][jss::TakerPays] == USD(60).value().getJson(JsonOptions::none)); // the balance between alice and gw is 160 USD..200 less the 40 taken // by the offer @@ -1677,8 +1539,7 @@ public: jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string((XRP(10000) + XRP(200) - env.current()->fees().base * 2) - .xrp())); + to_string((XRP(10000) + XRP(200) - env.current()->fees().base * 2).xrp())); // bob got 40 USD from partial consumption of the offer jrr = ledgerEntryState(env, bob, gw, "USD"); @@ -1686,15 +1547,11 @@ public: // Alice converts USD to XRP which should fail // due to PartialPayment. - env(pay(alice, alice, XRP(600)), - sendmax(USD(100)), - ter(tecPATH_PARTIAL)); + env(pay(alice, alice, XRP(600)), sendmax(USD(100)), ter(tecPATH_PARTIAL)); // Alice converts USD to XRP, should succeed because // we permit partial payment - env(pay(alice, alice, XRP(600)), - sendmax(USD(100)), - txflags(tfPartialPayment)); + env(pay(alice, alice, XRP(600)), sendmax(USD(100)), txflags(tfPartialPayment)); // Verify the offer was consumed jro = ledgerEntryOffer(env, bob, bobOfferSeq); @@ -1710,9 +1567,7 @@ public: jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - to_string((XRP(10000) + XRP(200) + XRP(300) - - env.current()->fees().base * 4) - .xrp())); + to_string((XRP(10000) + XRP(200) + XRP(300) - env.current()->fees().base * 4).xrp())); // bob now has 100 USD - 40 from the first payment and 60 from the // second (partial) payment @@ -1755,11 +1610,8 @@ public: BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-475"); auto jro = ledgerEntryOffer(env, carol, carolOfferSeq); - BEAST_EXPECT( - jro[jss::node][jss::TakerGets] == - USD(25).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jro[jss::node][jss::TakerPays] == XRP(250).value().getText()); + BEAST_EXPECT(jro[jss::node][jss::TakerGets] == USD(25).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jro[jss::node][jss::TakerPays] == XRP(250).value().getText()); } void @@ -1799,15 +1651,11 @@ public: jrr = ledgerEntryRoot(env, bob); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - std::to_string( - XRP(10000).value().mantissa() + XRP(250).value().mantissa())); + std::to_string(XRP(10000).value().mantissa() + XRP(250).value().mantissa())); auto jro = ledgerEntryOffer(env, carol, carolOfferSeq); - BEAST_EXPECT( - jro[jss::node][jss::TakerGets] == XRP(250).value().getText()); - BEAST_EXPECT( - jro[jss::node][jss::TakerPays] == - USD(25).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jro[jss::node][jss::TakerGets] == XRP(250).value().getText()); + BEAST_EXPECT(jro[jss::node][jss::TakerPays] == USD(25).value().getJson(JsonOptions::none)); } void @@ -1862,18 +1710,12 @@ public: BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-370"); auto jro = ledgerEntryOffer(env, carol, carolOfferSeq); - BEAST_EXPECT( - jro[jss::node][jss::TakerGets] == XRP(200).value().getText()); - BEAST_EXPECT( - jro[jss::node][jss::TakerPays] == - USD(20).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jro[jss::node][jss::TakerGets] == XRP(200).value().getText()); + BEAST_EXPECT(jro[jss::node][jss::TakerPays] == USD(20).value().getJson(JsonOptions::none)); jro = ledgerEntryOffer(env, dan, danOfferSeq); - BEAST_EXPECT( - jro[jss::node][jss::TakerGets] == - gw2["EUR"](20).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jro[jss::node][jss::TakerPays] == XRP(200).value().getText()); + BEAST_EXPECT(jro[jss::node][jss::TakerGets] == gw2["EUR"](20).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jro[jss::node][jss::TakerPays] == XRP(200).value().getText()); } void @@ -1967,9 +1809,7 @@ public: // fees: // 1 for each trust limit == 3 (alice < mtgox/amazon/bitstamp) + // 1 for payment == 4 - auto const starting_xrp = XRP(100) + - env.current()->fees().accountReserve(3) + - env.current()->fees().base * 4; + auto const starting_xrp = XRP(100) + env.current()->fees().accountReserve(3) + env.current()->fees().base * 4; env.fund(starting_xrp, gw1, gw2, gw3, alice, bob); env.close(); @@ -1991,8 +1831,7 @@ public: BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "100"); jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName] == - STAmount(env.current()->fees().accountReserve(3)).getText()); + jrr[jss::node][sfBalance.fieldName] == STAmount(env.current()->fees().accountReserve(3)).getText()); jrr = ledgerEntryState(env, bob, gw1, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-400"); @@ -2036,13 +1875,10 @@ public: env(offer(bob, XRP(100), USD(0.1))); auto jrr = ledgerEntryState(env, alice, gw, "USD"); - BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName][jss::value] == - "49.96666666666667"); + BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "49.96666666666667"); jrr = ledgerEntryState(env, bob, gw, "USD"); - Json::Value const bobsUSD = - jrr[jss::node][sfBalance.fieldName][jss::value]; + Json::Value const bobsUSD = jrr[jss::node][sfBalance.fieldName][jss::value]; if (!NumberSwitchOver) { BEAST_EXPECT(bobsUSD == "-0.966500000033334"); @@ -2068,9 +1904,7 @@ public: auto const bob = Account{"bob"}; auto const USD = gw["USD"]; - auto const starting_xrp = XRP(100) + - env.current()->fees().accountReserve(1) + - env.current()->fees().base * 2; + auto const starting_xrp = XRP(100) + env.current()->fees().accountReserve(1) + env.current()->fees().base * 2; env.fund(starting_xrp, gw, alice, bob); env.close(); @@ -2090,8 +1924,7 @@ public: BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-100"); jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName] == - STAmount(env.current()->fees().accountReserve(1)).getText()); + jrr[jss::node][sfBalance.fieldName] == STAmount(env.current()->fees().accountReserve(1)).getText()); jrr = ledgerEntryState(env, bob, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-400"); @@ -2111,9 +1944,7 @@ public: auto const bob = Account{"bob"}; auto const USD = gw["USD"]; - auto const starting_xrp = XRP(100) + - env.current()->fees().accountReserve(1) + - env.current()->fees().base * 2; + auto const starting_xrp = XRP(100) + env.current()->fees().accountReserve(1) + env.current()->fees().base * 2; env.fund(starting_xrp, gw, alice, bob); env.close(); @@ -2135,8 +1966,7 @@ public: BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-200"); jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( - jrr[jss::node][sfBalance.fieldName] == - STAmount(env.current()->fees().accountReserve(1)).getText()); + jrr[jss::node][sfBalance.fieldName] == STAmount(env.current()->fees().accountReserve(1)).getText()); jrr = ledgerEntryState(env, bob, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-300"); @@ -2157,9 +1987,7 @@ public: auto const XTS = gw["XTS"]; auto const XXX = gw["XXX"]; - auto const starting_xrp = XRP(100.1) + - env.current()->fees().accountReserve(1) + - env.current()->fees().base * 2; + auto const starting_xrp = XRP(100.1) + env.current()->fees().accountReserve(1) + env.current()->fees().base * 2; env.fund(starting_xrp, gw, alice, bob); env.close(); @@ -2184,22 +2012,16 @@ public: payment[jss::id] = env.seq(bob); payment[jss::build_path] = true; payment[jss::tx_json] = pay(bob, bob, bob["XXX"](1)); - payment[jss::tx_json][jss::Sequence] = - env.current() - ->read(keylet::account(bob.id())) - ->getFieldU32(sfSequence); + payment[jss::tx_json][jss::Sequence] = env.current()->read(keylet::account(bob.id()))->getFieldU32(sfSequence); payment[jss::tx_json][jss::Fee] = to_string(env.current()->fees().base); - payment[jss::tx_json][jss::SendMax] = - bob["XTS"](1.5).value().getJson(JsonOptions::none); + payment[jss::tx_json][jss::SendMax] = bob["XTS"](1.5).value().getJson(JsonOptions::none); auto jrr = wsc->invoke("submit", payment); BEAST_EXPECT(jrr[jss::status] == "success"); BEAST_EXPECT(jrr[jss::result][jss::engine_result] == "tesSUCCESS"); if (wsc->version() == 2) { - BEAST_EXPECT( - jrr.isMember(jss::jsonrpc) && jrr[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - jrr.isMember(jss::ripplerpc) && jrr[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(jrr.isMember(jss::jsonrpc) && jrr[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(jrr.isMember(jss::ripplerpc) && jrr[jss::ripplerpc] == "2.0"); BEAST_EXPECT(jrr.isMember(jss::id) && jrr[jss::id] == 5); } @@ -2221,13 +2043,9 @@ public: // a trust line defined). If the trustline is not defaulted then the tests // will not pass. void - verifyDefaultTrustline( - jtx::Env& env, - jtx::Account const& account, - jtx::PrettyAmount const& expectBalance) + verifyDefaultTrustline(jtx::Env& env, jtx::Account const& account, jtx::PrettyAmount const& expectBalance) { - auto const sleTrust = - env.le(keylet::line(account.id(), expectBalance.value().issue())); + auto const sleTrust = env.le(keylet::line(account.id(), expectBalance.value().issue())); BEAST_EXPECT(sleTrust); if (sleTrust) { @@ -2370,8 +2188,7 @@ public: std::uint32_t const acctOfferSeq = env.seq(acct) - 1; BEAST_EXPECT(env.balance(acct, USD.issue()) == t.balanceUsd); - BEAST_EXPECT( - env.balance(acct, xrpIssue()) == t.fundXrp - t.spentXrp); + BEAST_EXPECT(env.balance(acct, xrpIssue()) == t.fundXrp - t.spentXrp); env.require(offers(acct, t.offers)); env.require(owners(acct, t.owners)); @@ -2396,8 +2213,7 @@ public: else { // Verify that no trustline was created. - auto const sleTrust = - env.le(keylet::line(acct, USD.issue())); + auto const sleTrust = env.le(keylet::line(acct, USD.issue())); BEAST_EXPECT(!sleTrust); } } @@ -2534,11 +2350,7 @@ public: env(offer(bob, usdOffer, eurOffer)); env.close(); - env.require( - balance(alice, eurOffer), - balance(bob, usdOffer), - offers(alice, 0), - offers(bob, 0)); + env.require(balance(alice, eurOffer), balance(bob, usdOffer), offers(alice, 0), offers(bob, 0)); // Alice's offer crossing created a default EUR trustline and // Bob's offer crossing created a default USD trustline: @@ -2865,8 +2677,7 @@ public: // Check results BEAST_EXPECT(env.balance(acct, USD.issue()) == t.finalUsd); - BEAST_EXPECT( - env.balance(acct, xrpIssue()) == t.fundXrp - t.spentXrp); + BEAST_EXPECT(env.balance(acct, xrpIssue()) == t.fundXrp - t.spentXrp); env.require(offers(acct, t.offers)); env.require(owners(acct, t.owners)); @@ -2923,8 +2734,7 @@ public: env.close(); { // alice submits a tfSell | tfFillOrKill offer that does not cross. - env(offer(alice, USD(21), XRP(2100), tfSell | tfFillOrKill), - ter(killedCode)); + env(offer(alice, USD(21), XRP(2100), tfSell | tfFillOrKill), ter(killedCode)); env.close(); env.require(balance(alice, USD(none))); env.require(offers(alice, 0)); @@ -2957,8 +2767,7 @@ public: // all of the offer is consumed. // We're using bob's left-over offer for XRP(500), USD(5) - env(offer(alice, USD(1), XRP(501), tfSell | tfFillOrKill), - ter(killedCode)); + env(offer(alice, USD(1), XRP(501), tfSell | tfFillOrKill), ter(killedCode)); env.close(); env.require(balance(alice, USD(35))); env.require(offers(alice, 0)); @@ -4026,12 +3835,9 @@ public: auto actorOffers = offersOnAccount(env, actor.acct); auto const offerCount = std::distance( actorOffers.begin(), - std::remove_if( - actorOffers.begin(), - actorOffers.end(), - [](std::shared_ptr& offer) { - return (*offer)[sfTakerGets].signum() == 0; - })); + std::remove_if(actorOffers.begin(), actorOffers.end(), [](std::shared_ptr& offer) { + return (*offer)[sfTakerGets].signum() == 0; + })); BEAST_EXPECT(offerCount == actor.offers); env.require(balance(actor.acct, actor.xrp)); @@ -4175,12 +3981,9 @@ public: auto actorOffers = offersOnAccount(env, actor.acct); auto const offerCount = std::distance( actorOffers.begin(), - std::remove_if( - actorOffers.begin(), - actorOffers.end(), - [](std::shared_ptr& offer) { - return (*offer)[sfTakerGets].signum() == 0; - })); + std::remove_if(actorOffers.begin(), actorOffers.end(), [](std::shared_ptr& offer) { + return (*offer)[sfTakerGets].signum() == 0; + })); BEAST_EXPECT(offerCount == actor.offers); env.require(balance(actor.acct, actor.xrp)); @@ -4430,12 +4233,10 @@ public: // MM places offers float const rate = 0.9f; // 0.9 USD = 1 EUR - env(offer(mm, EUR(4000000 * rate), USD(4000000)), - json(jss::Flags, tfSell)); + env(offer(mm, EUR(4000000 * rate), USD(4000000)), json(jss::Flags, tfSell)); float const reverseRate = 1.0f / rate * 1.00101f; - env(offer(mm, USD(4000000 * reverseRate), EUR(4000000)), - json(jss::Flags, tfSell)); + env(offer(mm, USD(4000000 * reverseRate), EUR(4000000)), json(jss::Flags, tfSell)); env.close(); // There should be a path available from hot US to cold EUR @@ -4447,13 +4248,10 @@ public: jvParams[jss::destination_amount][jss::value] = 10; jvParams[jss::source_account] = hotUS.human(); - Json::Value const jrr{env.rpc( - "json", "ripple_path_find", to_string(jvParams))[jss::result]}; + Json::Value const jrr{env.rpc("json", "ripple_path_find", to_string(jvParams))[jss::result]}; BEAST_EXPECT(jrr[jss::status] == "success"); - BEAST_EXPECT( - jrr[jss::alternatives].isArray() && - jrr[jss::alternatives].size() > 0); + BEAST_EXPECT(jrr[jss::alternatives].isArray() && jrr[jss::alternatives].size() > 0); } // Send the payment using the found path. env(pay(hotUS, coldEU, EUR(10)), sendmax(USD(11.1223326))); @@ -4531,10 +4329,8 @@ public: testcase("Deleted offer issuer"); - auto trustLineExists = [](jtx::Env const& env, - jtx::Account const& src, - jtx::Account const& dst, - Currency const& cur) -> bool { + auto trustLineExists = + [](jtx::Env const& env, jtx::Account const& src, jtx::Account const& dst, Currency const& cur) -> bool { return bool(env.le(keylet::line(src, dst, cur))); }; @@ -4574,8 +4370,7 @@ public: { // The ledger sequence needs to far enough ahead of the account // sequence before the account can be deleted. - int const delta = - [&env, &gw, openLedgerSeq = env.current()->seq()]() -> int { + int const delta = [&env, &gw, openLedgerSeq = env.current()->seq()]() -> int { std::uint32_t const gwSeq{env.seq(gw)}; if (gwSeq + 255 > openLedgerSeq) return gwSeq - openLedgerSeq + 255; @@ -4586,8 +4381,7 @@ public: env.close(); // Account deletion has a high fee. Account for that. - env(acctdelete(gw, alice), - fee(drops(env.current()->fees().increment))); + env(acctdelete(gw, alice), fee(drops(env.current()->fees().increment))); env.close(); // Verify that gw's account root is gone from the ledger. @@ -4700,40 +4494,31 @@ public: env(offer(alice, XTS(30), XXX(10)), json(jss::Flags, tfSell)); std::map> offers; - forEachItem( - *env.current(), alice, [&](std::shared_ptr const& sle) { - if (sle->getType() == ltOFFER) - offers.emplace( - (*sle)[sfSequence], - std::make_pair( - (*sle)[sfTakerPays], (*sle)[sfTakerGets])); - }); + forEachItem(*env.current(), alice, [&](std::shared_ptr const& sle) { + if (sle->getType() == ltOFFER) + offers.emplace((*sle)[sfSequence], std::make_pair((*sle)[sfTakerPays], (*sle)[sfTakerGets])); + }); // first offer auto it = offers.begin(); BEAST_EXPECT(it != offers.end()); - BEAST_EXPECT( - it->second.first == XTS(10) && it->second.second < XXX(30) && - it->second.second > XXX(29.9994)); + BEAST_EXPECT(it->second.first == XTS(10) && it->second.second < XXX(30) && it->second.second > XXX(29.9994)); // second offer ++it; BEAST_EXPECT(it != offers.end()); - BEAST_EXPECT( - it->second.first == XTS(30) && it->second.second == XXX(10)); + BEAST_EXPECT(it->second.first == XTS(30) && it->second.second == XXX(10)); // third offer ++it; BEAST_EXPECT(it != offers.end()); - BEAST_EXPECT( - it->second.first == XTS(10.0002) && it->second.second == XXX(30)); + BEAST_EXPECT(it->second.first == XTS(10.0002) && it->second.second == XXX(30)); // fourth offer // exact TakerPays is XTS(1/.033333) ++it; BEAST_EXPECT(it != offers.end()); - BEAST_EXPECT( - it->second.first == XTS(30) && it->second.second == XXX(10)); + BEAST_EXPECT(it->second.first == XTS(30) && it->second.second == XXX(10)); BEAST_EXPECT(++it == offers.end()); } @@ -4742,13 +4527,11 @@ public: static std::vector> sortedOffersOnAccount(jtx::Env& env, jtx::Account const& acct) { - std::vector> offers{ - offersOnAccount(env, acct)}; + std::vector> offers{offersOnAccount(env, acct)}; std::sort( offers.begin(), offers.end(), - [](std::shared_ptr const& rhs, - std::shared_ptr const& lhs) { + [](std::shared_ptr const& rhs, std::shared_ptr const& lhs) { return (*rhs)[sfSequence] < (*lhs)[sfSequence]; }); return offers; @@ -5038,15 +4821,12 @@ public: // tfFillOrKill, TakerPays must be filled { - TER const err = - features[fixFillOrKill] ? TER(tesSUCCESS) : tecKILLED; + TER const err = features[fixFillOrKill] ? TER(tesSUCCESS) : tecKILLED; env(offer(maker, XRP(100), USD(100))); env.close(); - env(offer(taker, USD(100), XRP(101)), - txflags(tfFillOrKill), - ter(err)); + env(offer(taker, USD(100), XRP(101)), txflags(tfFillOrKill), ter(err)); env.close(); makerXRPBalance -= txfee(env, 1); @@ -5063,9 +4843,7 @@ public: env(offer(maker, USD(100), XRP(100))); env.close(); - env(offer(taker, XRP(100), USD(101)), - txflags(tfFillOrKill), - ter(err)); + env(offer(taker, XRP(100), USD(101)), txflags(tfFillOrKill), ter(err)); env.close(); makerXRPBalance -= txfee(env, 1); @@ -5082,9 +4860,7 @@ public: env(offer(maker, USD(100), EUR(100))); env.close(); - env(offer(taker, EUR(100), USD(101)), - txflags(tfFillOrKill), - ter(err)); + env(offer(taker, EUR(100), USD(101)), txflags(tfFillOrKill), ter(err)); env.close(); makerXRPBalance -= txfee(env, 1); @@ -5104,8 +4880,7 @@ public: env(offer(maker, XRP(101), USD(101))); env.close(); - env(offer(taker, USD(100), XRP(101)), - txflags(tfFillOrKill | tfSell)); + env(offer(taker, USD(100), XRP(101)), txflags(tfFillOrKill | tfSell)); env.close(); makerUSDBalance -= USD(101); @@ -5117,8 +4892,7 @@ public: env(offer(maker, USD(101), XRP(101))); env.close(); - env(offer(taker, XRP(100), USD(101)), - txflags(tfFillOrKill | tfSell)); + env(offer(taker, XRP(100), USD(101)), txflags(tfFillOrKill | tfSell)); env.close(); makerUSDBalance += USD(101); @@ -5130,8 +4904,7 @@ public: env(offer(maker, USD(101), EUR(101))); env.close(); - env(offer(taker, EUR(100), USD(101)), - txflags(tfFillOrKill | tfSell)); + env(offer(taker, EUR(100), USD(101)), txflags(tfFillOrKill | tfSell)); env.close(); makerUSDBalance += USD(101); @@ -5149,9 +4922,7 @@ public: env(offer(maker, XRP(100), USD(100))); env.close(); - env(offer(taker, USD(100), XRP(99)), - txflags(flags), - ter(tecKILLED)); + env(offer(taker, USD(100), XRP(99)), txflags(flags), ter(tecKILLED)); env.close(); makerXRPBalance -= txfee(env, 1); @@ -5161,9 +4932,7 @@ public: env(offer(maker, USD(100), XRP(100))); env.close(); - env(offer(taker, XRP(100), USD(99)), - txflags(flags), - ter(tecKILLED)); + env(offer(taker, XRP(100), USD(99)), txflags(flags), ter(tecKILLED)); env.close(); makerXRPBalance -= txfee(env, 1); @@ -5173,9 +4942,7 @@ public: env(offer(maker, USD(100), EUR(100))); env.close(); - env(offer(taker, EUR(100), USD(99)), - txflags(flags), - ter(tecKILLED)); + env(offer(taker, EUR(100), USD(99)), txflags(flags), ter(tecKILLED)); env.close(); makerXRPBalance -= txfee(env, 1); @@ -5184,12 +4951,9 @@ public: } BEAST_EXPECT( - env.balance(maker, USD) == makerUSDBalance && - env.balance(taker, USD) == takerUSDBalance && - env.balance(maker, EUR) == makerEURBalance && - env.balance(taker, EUR) == takerEURBalance && - env.balance(maker, XRP) == makerXRPBalance && - env.balance(taker, XRP) == takerXRPBalance); + env.balance(maker, USD) == makerUSDBalance && env.balance(taker, USD) == takerUSDBalance && + env.balance(maker, EUR) == makerEURBalance && env.balance(taker, EUR) == takerEURBalance && + env.balance(maker, XRP) == makerXRPBalance && env.balance(taker, XRP) == takerXRPBalance); } void diff --git a/src/test/app/Oracle_test.cpp b/src/test/app/Oracle_test.cpp index 6708f56275..66a8969164 100644 --- a/src/test/app/Oracle_test.cpp +++ b/src/test/app/Oracle_test.cpp @@ -44,14 +44,8 @@ private: // Insufficient reserve if the data series extends to greater than 5 { Env env(*this); - env.fund( - env.current()->fees().accountReserve(1) + - env.current()->fees().base * 2, - owner); - Oracle oracle( - env, - {.owner = owner, - .fee = static_cast(env.current()->fees().base.drops())}); + env.fund(env.current()->fees().accountReserve(1) + env.current()->fees().base * 2, owner); + Oracle oracle(env, {.owner = owner, .fee = static_cast(env.current()->fees().base.drops())}); BEAST_EXPECT(oracle.exists()); oracle.set(UpdateArg{ .series = @@ -68,40 +62,31 @@ private: { Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}, false); // Invalid flag - oracle.set(CreateArg{ - .flags = tfSellNFToken, - .fee = baseFee, - .err = ter(temINVALID_FLAG)}); + oracle.set(CreateArg{.flags = tfSellNFToken, .fee = baseFee, .err = ter(temINVALID_FLAG)}); // Duplicate token pair oracle.set(CreateArg{ - .series = {{"XRP", "USD", 740, 1}, {"XRP", "USD", 750, 1}}, - .fee = baseFee, - .err = ter(temMALFORMED)}); + .series = {{"XRP", "USD", 740, 1}, {"XRP", "USD", 750, 1}}, .fee = baseFee, .err = ter(temMALFORMED)}); // Price is not included oracle.set(CreateArg{ - .series = - {{"XRP", "USD", 740, 1}, {"XRP", "EUR", std::nullopt, 1}}, + .series = {{"XRP", "USD", 740, 1}, {"XRP", "EUR", std::nullopt, 1}}, .fee = baseFee, .err = ter(temMALFORMED)}); // Token pair is in update and delete oracle.set(CreateArg{ - .series = - {{"XRP", "USD", 740, 1}, {"XRP", "USD", std::nullopt, 1}}, + .series = {{"XRP", "USD", 740, 1}, {"XRP", "USD", std::nullopt, 1}}, .fee = baseFee, .err = ter(temMALFORMED)}); // Token pair is in add and delete oracle.set(CreateArg{ - .series = - {{"XRP", "EUR", 740, 1}, {"XRP", "EUR", std::nullopt, 1}}, + .series = {{"XRP", "EUR", 740, 1}, {"XRP", "EUR", std::nullopt, 1}}, .fee = baseFee, .err = ter(temMALFORMED)}); @@ -121,23 +106,16 @@ private: {"XRP", "U11", 740, 1}}, .fee = baseFee, .err = ter(temARRAY_TOO_LARGE)}); - oracle.set(CreateArg{ - .series = {}, .fee = baseFee, .err = ter(temARRAY_EMPTY)}); + oracle.set(CreateArg{.series = {}, .fee = baseFee, .err = ter(temARRAY_EMPTY)}); } // Array of token pair exceeds 10 after update { Env env{*this}; - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); - Oracle oracle( - env, - CreateArg{ - .owner = owner, - .series = {{{"XRP", "USD", 740, 1}}}, - .fee = baseFee}); + Oracle oracle(env, CreateArg{.owner = owner, .series = {{{"XRP", "USD", 740, 1}}}, .fee = baseFee}); oracle.set(UpdateArg{ .series = { @@ -158,17 +136,13 @@ private: { Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}, false); // Asset class or provider not included on create oracle.set(CreateArg{ - .assetClass = std::nullopt, - .provider = "provider", - .fee = baseFee, - .err = ter(temMALFORMED)}); + .assetClass = std::nullopt, .provider = "provider", .fee = baseFee, .err = ter(temMALFORMED)}); oracle.set(CreateArg{ .assetClass = "currency", .provider = std::nullopt, @@ -178,14 +152,10 @@ private: // Asset class or provider are included on update // and don't match the current values - oracle.set(CreateArg{ - .fee = static_cast(env.current()->fees().base.drops())}); + oracle.set(CreateArg{.fee = static_cast(env.current()->fees().base.drops())}); BEAST_EXPECT(oracle.exists()); oracle.set(UpdateArg{ - .series = {{"XRP", "USD", 740, 1}}, - .provider = "provider1", - .fee = baseFee, - .err = ter(temMALFORMED)}); + .series = {{"XRP", "USD", 740, 1}}, .provider = "provider1", .fee = baseFee, .err = ter(temMALFORMED)}); oracle.set(UpdateArg{ .series = {{"XRP", "USD", 740, 1}}, .assetClass = "currency1", @@ -195,68 +165,49 @@ private: { Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}, false); // Fields too long // Asset class std::string assetClass(17, '0'); - oracle.set(CreateArg{ - .assetClass = assetClass, - .fee = baseFee, - .err = ter(temMALFORMED)}); + oracle.set(CreateArg{.assetClass = assetClass, .fee = baseFee, .err = ter(temMALFORMED)}); // provider std::string const large(257, '0'); - oracle.set(CreateArg{ - .provider = large, .fee = baseFee, .err = ter(temMALFORMED)}); + oracle.set(CreateArg{.provider = large, .fee = baseFee, .err = ter(temMALFORMED)}); // URI - oracle.set(CreateArg{ - .uri = large, .fee = baseFee, .err = ter(temMALFORMED)}); + oracle.set(CreateArg{.uri = large, .fee = baseFee, .err = ter(temMALFORMED)}); // Empty field // Asset class - oracle.set(CreateArg{ - .assetClass = "", .fee = baseFee, .err = ter(temMALFORMED)}); + oracle.set(CreateArg{.assetClass = "", .fee = baseFee, .err = ter(temMALFORMED)}); // provider - oracle.set(CreateArg{ - .provider = "", .fee = baseFee, .err = ter(temMALFORMED)}); + oracle.set(CreateArg{.provider = "", .fee = baseFee, .err = ter(temMALFORMED)}); // URI - oracle.set( - CreateArg{.uri = "", .fee = baseFee, .err = ter(temMALFORMED)}); + oracle.set(CreateArg{.uri = "", .fee = baseFee, .err = ter(temMALFORMED)}); } { // Different owner creates a new object and fails because // of missing fields currency/provider Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); Account const some("some"); env.fund(XRP(1'000), owner); env.fund(XRP(1'000), some); Oracle oracle(env, {.owner = owner, .fee = baseFee}); BEAST_EXPECT(oracle.exists()); - oracle.set(UpdateArg{ - .owner = some, - .series = {{"XRP", "USD", 740, 1}}, - .fee = baseFee, - .err = ter(temMALFORMED)}); + oracle.set( + UpdateArg{.owner = some, .series = {{"XRP", "USD", 740, 1}}, .fee = baseFee, .err = ter(temMALFORMED)}); } { // Invalid update time using namespace std::chrono; Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); auto closeTime = [&]() { - return duration_cast( - env.current() - ->header() - .closeTime.time_since_epoch() - - 10'000s) - .count(); + return duration_cast(env.current()->header().closeTime.time_since_epoch() - 10'000s).count(); }; env.fund(XRP(1'000), owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}); @@ -274,10 +225,8 @@ private: .lastUpdateTime = static_cast(closeTime() + 311), .fee = baseFee, .err = ter(tecINVALID_UPDATE_TIME)}); - oracle.set( - UpdateArg{.series = {{"XRP", "USD", 740, 1}}, .fee = baseFee}); - BEAST_EXPECT(oracle.expectLastUpdateTime( - static_cast(testStartTime.count() + 450))); + oracle.set(UpdateArg{.series = {{"XRP", "USD", 740, 1}}, .fee = baseFee}); + BEAST_EXPECT(oracle.expectLastUpdateTime(static_cast(testStartTime.count() + 450))); // Less than the previous lastUpdateTime oracle.set(UpdateArg{ .series = {{"XRP", "USD", 740, 1}}, @@ -295,8 +244,7 @@ private: { // delete token pair that doesn't exist Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}); BEAST_EXPECT(oracle.exists()); @@ -306,30 +254,22 @@ private: .err = ter(tecTOKEN_PAIR_NOT_FOUND)}); // delete all token pairs oracle.set(UpdateArg{ - .series = {{"XRP", "USD", std::nullopt, std::nullopt}}, - .fee = baseFee, - .err = ter(tecARRAY_EMPTY)}); + .series = {{"XRP", "USD", std::nullopt, std::nullopt}}, .fee = baseFee, .err = ter(tecARRAY_EMPTY)}); } { // same BaseAsset and QuoteAsset Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); Oracle oracle( - env, - {.owner = owner, - .series = {{"USD", "USD", 740, 1}}, - .fee = baseFee, - .err = ter(temMALFORMED)}); + env, {.owner = owner, .series = {{"USD", "USD", 740, 1}}, .fee = baseFee, .err = ter(temMALFORMED)}); } { // Scale is greater than maxPriceScale Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); Oracle oracle( env, @@ -342,14 +282,11 @@ private: { // Updating token pair to add and delete Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}); oracle.set(UpdateArg{ - .series = - {{"XRP", "EUR", std::nullopt, std::nullopt}, - {"XRP", "EUR", 740, 1}}, + .series = {{"XRP", "EUR", std::nullopt, std::nullopt}, {"XRP", "EUR", 740, 1}}, .fee = baseFee, .err = ter(temMALFORMED)}); // Delete token pair that doesn't exist in this oracle @@ -369,14 +306,9 @@ private: // Bad fee Env env(*this); env.fund(XRP(1'000), owner); - Oracle oracle( - env, {.owner = owner, .fee = -1, .err = ter(temBAD_FEE)}); - Oracle oracle1( - env, - {.owner = owner, - .fee = static_cast(env.current()->fees().base.drops())}); - oracle.set( - UpdateArg{.owner = owner, .fee = -1, .err = ter(temBAD_FEE)}); + Oracle oracle(env, {.owner = owner, .fee = -1, .err = ter(temBAD_FEE)}); + Oracle oracle1(env, {.owner = owner, .fee = static_cast(env.current()->fees().base.drops())}); + oracle.set(UpdateArg{.owner = owner, .fee = -1, .err = ter(temBAD_FEE)}); } } @@ -388,21 +320,17 @@ private: Account const owner("owner"); auto test = [&](Env& env, DataSeries const& series, std::uint16_t adj) { - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); auto const count = ownerCount(env, owner); - Oracle oracle( - env, {.owner = owner, .series = series, .fee = baseFee}); + Oracle oracle(env, {.owner = owner, .series = series, .fee = baseFee}); BEAST_EXPECT(oracle.exists()); BEAST_EXPECT(ownerCount(env, owner) == (count + adj)); auto const entry = oracle.ledgerEntry(); BEAST_EXPECT(entry[jss::node][jss::Owner] == owner.human()); if (features[fixIncludeKeyletFields]) { - BEAST_EXPECT( - entry[jss::node][jss::OracleDocumentID] == - oracle.documentID()); + BEAST_EXPECT(entry[jss::node][jss::OracleDocumentID] == oracle.documentID()); } else { @@ -434,17 +362,13 @@ private: { // Different owner creates a new object Env env(*this, features); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); Account const some("some"); env.fund(XRP(1'000), owner); env.fund(XRP(1'000), some); Oracle oracle(env, {.owner = owner, .fee = baseFee}); BEAST_EXPECT(oracle.exists()); - oracle.set(CreateArg{ - .owner = some, - .series = {{"912810RR9", "USD", 740, 1}}, - .fee = baseFee}); + oracle.set(CreateArg{.owner = some, .series = {{"912810RR9", "USD", 740, 1}}, .fee = baseFee}); BEAST_EXPECT(Oracle::exists(env, some, oracle.documentID())); } } @@ -456,8 +380,7 @@ private: using namespace jtx; Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); Account const owner("owner"); env.fund(XRP(1'000), owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}); @@ -467,28 +390,19 @@ private: // Invalid account Account const bad("bad"); env.memoize(bad); - oracle.remove( - {.owner = bad, - .seq = seq(1), - .fee = baseFee, - .err = ter(terNO_ACCOUNT)}); + oracle.remove({.owner = bad, .seq = seq(1), .fee = baseFee, .err = ter(terNO_ACCOUNT)}); } // Invalid DocumentID - oracle.remove( - {.documentID = 2, .fee = baseFee, .err = ter(tecNO_ENTRY)}); + oracle.remove({.documentID = 2, .fee = baseFee, .err = ter(tecNO_ENTRY)}); // Invalid owner Account const invalid("invalid"); env.fund(XRP(1'000), invalid); - oracle.remove( - {.owner = invalid, .fee = baseFee, .err = ter(tecNO_ENTRY)}); + oracle.remove({.owner = invalid, .fee = baseFee, .err = ter(tecNO_ENTRY)}); // Invalid flags - oracle.remove( - {.flags = tfSellNFToken, - .fee = baseFee, - .err = ter(temINVALID_FLAG)}); + oracle.remove({.flags = tfSellNFToken, .fee = baseFee, .err = ter(temINVALID_FLAG)}); // Bad fee oracle.remove({.fee = -1, .err = ter(temBAD_FEE)}); @@ -502,11 +416,9 @@ private: Account const owner("owner"); auto test = [&](Env& env, DataSeries const& series, std::uint16_t adj) { - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); - Oracle oracle( - env, {.owner = owner, .series = series, .fee = baseFee}); + Oracle oracle(env, {.owner = owner, .series = series, .fee = baseFee}); auto const count = ownerCount(env, owner); BEAST_EXPECT(oracle.exists()); oracle.remove({.fee = baseFee}); @@ -539,24 +451,14 @@ private: { // deleting the account deletes the oracles Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); auto const alice = Account("alice"); auto const acctDelFee{drops(env.current()->fees().increment)}; env.fund(XRP(1'000), owner); env.fund(XRP(1'000), alice); - Oracle oracle( - env, - {.owner = owner, - .series = {{"XRP", "USD", 740, 1}}, - .fee = baseFee}); - Oracle oracle1( - env, - {.owner = owner, - .documentID = 2, - .series = {{"XRP", "EUR", 740, 1}}, - .fee = baseFee}); + Oracle oracle(env, {.owner = owner, .series = {{"XRP", "USD", 740, 1}}, .fee = baseFee}); + Oracle oracle1(env, {.owner = owner, .documentID = 2, .series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); BEAST_EXPECT(ownerCount(env, owner) == 2); BEAST_EXPECT(oracle.exists()); BEAST_EXPECT(oracle1.exists()); @@ -575,8 +477,7 @@ private: jvParams[field] = value; jvParams[jss::binary] = false; jvParams[jss::type] = jss::oracle; - Json::Value jrr = - env.rpc("json", "ledger_data", to_string(jvParams)); + Json::Value jrr = env.rpc("json", "ledger_data", to_string(jvParams)); BEAST_EXPECT(jrr[jss::result][jss::state].size() == 2); }; verifyLedgerData(jss::ledger_index, index); @@ -593,16 +494,14 @@ private: { Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); auto count = ownerCount(env, owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}); BEAST_EXPECT(oracle.exists()); // update existing pair - oracle.set( - UpdateArg{.series = {{"XRP", "USD", 740, 2}}, .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "USD", 740, 2}}, .fee = baseFee}); BEAST_EXPECT(oracle.expectPrice({{"XRP", "USD", 740, 2}})); // owner count is increased by 1 since the oracle object is added // with one token pair @@ -610,19 +509,14 @@ private: BEAST_EXPECT(ownerCount(env, owner) == count); // add new pairs, not-included pair is reset - oracle.set( - UpdateArg{.series = {{"XRP", "EUR", 700, 2}}, .fee = baseFee}); - BEAST_EXPECT(oracle.expectPrice( - {{"XRP", "USD", 0, 0}, {"XRP", "EUR", 700, 2}})); + oracle.set(UpdateArg{.series = {{"XRP", "EUR", 700, 2}}, .fee = baseFee}); + BEAST_EXPECT(oracle.expectPrice({{"XRP", "USD", 0, 0}, {"XRP", "EUR", 700, 2}})); // owner count is not changed since the number of pairs is 2 BEAST_EXPECT(ownerCount(env, owner) == count); // update both pairs - oracle.set(UpdateArg{ - .series = {{"XRP", "USD", 741, 2}, {"XRP", "EUR", 710, 2}}, - .fee = baseFee}); - BEAST_EXPECT(oracle.expectPrice( - {{"XRP", "USD", 741, 2}, {"XRP", "EUR", 710, 2}})); + oracle.set(UpdateArg{.series = {{"XRP", "USD", 741, 2}, {"XRP", "EUR", 710, 2}}, .fee = baseFee}); + BEAST_EXPECT(oracle.expectPrice({{"XRP", "USD", 741, 2}, {"XRP", "EUR", 710, 2}})); // owner count is not changed since the number of pairs is 2 BEAST_EXPECT(ownerCount(env, owner) == count); @@ -640,9 +534,7 @@ private: BEAST_EXPECT(ownerCount(env, owner) == count); // update two pairs and delete four - oracle.set(UpdateArg{ - .series = {{"BTC", "USD", std::nullopt, std::nullopt}}, - .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"BTC", "USD", std::nullopt, std::nullopt}}, .fee = baseFee}); oracle.set(UpdateArg{ .series = {{"XRP", "USD", 742, 2}, @@ -651,8 +543,7 @@ private: {"YAN", "EUR", std::nullopt, std::nullopt}, {"CAN", "EUR", std::nullopt, std::nullopt}}, .fee = baseFee}); - BEAST_EXPECT(oracle.expectPrice( - {{"XRP", "USD", 742, 2}, {"XRP", "EUR", 711, 2}})); + BEAST_EXPECT(oracle.expectPrice({{"XRP", "USD", 742, 2}, {"XRP", "EUR", 711, 2}})); // owner count is decreased by 1 since the number of pairs is 2 count -= 1; BEAST_EXPECT(ownerCount(env, owner) == count); @@ -661,57 +552,37 @@ private: // Min reserve to create and update { Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); - env.fund( - env.current()->fees().accountReserve(1) + - env.current()->fees().base * 2, - owner); + auto const baseFee = static_cast(env.current()->fees().base.drops()); + env.fund(env.current()->fees().accountReserve(1) + env.current()->fees().base * 2, owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}); - oracle.set( - UpdateArg{.series = {{"XRP", "USD", 742, 2}}, .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "USD", 742, 2}}, .fee = baseFee}); } for (bool const withFixOrder : {false, true}) { // Should be same order as creation - Env env( - *this, - withFixOrder ? testable_amendments() - : testable_amendments() - fixPriceOracleOrder); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + Env env(*this, withFixOrder ? testable_amendments() : testable_amendments() - fixPriceOracleOrder); + auto const baseFee = static_cast(env.current()->fees().base.drops()); auto test = [&](Env& env, DataSeries const& series) { env.fund(XRP(1'000), owner); - Oracle oracle( - env, {.owner = owner, .series = series, .fee = baseFee}); + Oracle oracle(env, {.owner = owner, .series = series, .fee = baseFee}); BEAST_EXPECT(oracle.exists()); auto sle = env.le(keylet::oracle(owner, oracle.documentID())); - BEAST_EXPECT( - sle->getFieldArray(sfPriceDataSeries).size() == - series.size()); + BEAST_EXPECT(sle->getFieldArray(sfPriceDataSeries).size() == series.size()); auto const beforeQuoteAssetName1 = - sle->getFieldArray(sfPriceDataSeries)[0] - .getFieldCurrency(sfQuoteAsset) - .getText(); + sle->getFieldArray(sfPriceDataSeries)[0].getFieldCurrency(sfQuoteAsset).getText(); auto const beforeQuoteAssetName2 = - sle->getFieldArray(sfPriceDataSeries)[1] - .getFieldCurrency(sfQuoteAsset) - .getText(); + sle->getFieldArray(sfPriceDataSeries)[1].getFieldCurrency(sfQuoteAsset).getText(); oracle.set(UpdateArg{.series = series, .fee = baseFee}); sle = env.le(keylet::oracle(owner, oracle.documentID())); auto const afterQuoteAssetName1 = - sle->getFieldArray(sfPriceDataSeries)[0] - .getFieldCurrency(sfQuoteAsset) - .getText(); + sle->getFieldArray(sfPriceDataSeries)[0].getFieldCurrency(sfQuoteAsset).getText(); auto const afterQuoteAssetName2 = - sle->getFieldArray(sfPriceDataSeries)[1] - .getFieldCurrency(sfQuoteAsset) - .getText(); + sle->getFieldArray(sfPriceDataSeries)[1].getFieldCurrency(sfQuoteAsset).getText(); if (env.current()->rules().enabled(fixPriceOracleOrder)) { @@ -736,8 +607,7 @@ private: Oracle::setFee(100'000); Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); Account const alice{"alice", KeyType::secp256k1}; Account const bogie{"bogie", KeyType::secp256k1}; @@ -761,32 +631,18 @@ private: // Create // Force close (true) and time advancement because the close time // is no longer 0. - Oracle oracle( - env, - CreateArg{.owner = alice, .fee = baseFee, .close = true}, - false); - oracle.set(CreateArg{ - .msig = msig(becky), .fee = baseFee, .err = ter(tefBAD_QUORUM)}); - oracle.set(CreateArg{ - .msig = msig(zelda), .fee = baseFee, .err = ter(tefBAD_SIGNATURE)}); + Oracle oracle(env, CreateArg{.owner = alice, .fee = baseFee, .close = true}, false); + oracle.set(CreateArg{.msig = msig(becky), .fee = baseFee, .err = ter(tefBAD_QUORUM)}); + oracle.set(CreateArg{.msig = msig(zelda), .fee = baseFee, .err = ter(tefBAD_SIGNATURE)}); oracle.set(CreateArg{.msig = msig(becky, bogie), .fee = baseFee}); BEAST_EXPECT(oracle.exists()); // Update oracle.set(UpdateArg{ - .series = {{"XRP", "USD", 740, 1}}, - .msig = msig(becky), - .fee = baseFee, - .err = ter(tefBAD_QUORUM)}); + .series = {{"XRP", "USD", 740, 1}}, .msig = msig(becky), .fee = baseFee, .err = ter(tefBAD_QUORUM)}); oracle.set(UpdateArg{ - .series = {{"XRP", "USD", 740, 1}}, - .msig = msig(zelda), - .fee = baseFee, - .err = ter(tefBAD_SIGNATURE)}); - oracle.set(UpdateArg{ - .series = {{"XRP", "USD", 741, 1}}, - .msig = msig(becky, bogie), - .fee = baseFee}); + .series = {{"XRP", "USD", 740, 1}}, .msig = msig(zelda), .fee = baseFee, .err = ter(tefBAD_SIGNATURE)}); + oracle.set(UpdateArg{.series = {{"XRP", "USD", 741, 1}}, .msig = msig(becky, bogie), .fee = baseFee}); BEAST_EXPECT(oracle.expectPrice({{"XRP", "USD", 741, 1}})); // remove the signer list env(signers(alice, jtx::none), sig(alie)); @@ -802,24 +658,14 @@ private: .fee = baseFee, .err = ter(tefBAD_SIGNATURE)}); // updated list succeeds - oracle.set(UpdateArg{ - .series = {{"XRP", "USD", 7412, 2}}, - .msig = msig(zelda, bob), - .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "USD", 7412, 2}}, .msig = msig(zelda, bob), .fee = baseFee}); BEAST_EXPECT(oracle.expectPrice({{"XRP", "USD", 7412, 2}})); - oracle.set(UpdateArg{ - .series = {{"XRP", "USD", 74245, 3}}, - .msig = msig(ed), - .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "USD", 74245, 3}}, .msig = msig(ed), .fee = baseFee}); BEAST_EXPECT(oracle.expectPrice({{"XRP", "USD", 74245, 3}})); // Remove - oracle.remove( - {.msig = msig(bob), .fee = baseFee, .err = ter(tefBAD_QUORUM)}); - oracle.remove( - {.msig = msig(becky), - .fee = baseFee, - .err = ter(tefBAD_SIGNATURE)}); + oracle.remove({.msig = msig(bob), .fee = baseFee, .err = ter(tefBAD_QUORUM)}); + oracle.remove({.msig = msig(becky), .fee = baseFee, .err = ter(tefBAD_SIGNATURE)}); oracle.remove({.msig = msig(ed), .fee = baseFee}); BEAST_EXPECT(!oracle.exists()); } @@ -833,13 +679,11 @@ private: auto const features = testable_amendments() - featurePriceOracle; Account const owner("owner"); Env env(*this, features); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); env.fund(XRP(1'000), owner); { - Oracle oracle( - env, {.owner = owner, .fee = baseFee, .err = ter(temDISABLED)}); + Oracle oracle(env, {.owner = owner, .fee = baseFee, .err = ter(temDISABLED)}); } { diff --git a/src/test/app/OversizeMeta_test.cpp b/src/test/app/OversizeMeta_test.cpp index 2eb300b095..d5e2948f5b 100644 --- a/src/test/app/OversizeMeta_test.cpp +++ b/src/test/app/OversizeMeta_test.cpp @@ -160,8 +160,7 @@ public: void run() override { - auto const result = - bfind(100, 9000, [&](std::size_t n) { return oversize(n); }); + auto const result = bfind(100, 9000, [&](std::size_t n) { return oversize(n); }); log << "Min oversize offers = " << result << '\n'; } }; diff --git a/src/test/app/Path_test.cpp b/src/test/app/Path_test.cpp index 8a80ecd6d8..c019c2b8a3 100644 --- a/src/test/app/Path_test.cpp +++ b/src/test/app/Path_test.cpp @@ -140,8 +140,7 @@ public: params[jss::command] = "ripple_path_find"; params[jss::source_account] = toBase58(src); params[jss::destination_account] = toBase58(dst); - params[jss::destination_amount] = - saDstAmount.getJson(JsonOptions::none); + params[jss::destination_amount] = saDstAmount.getJson(JsonOptions::none); if (saSendMax) params[jss::send_max] = saSendMax->getJson(JsonOptions::none); if (saSrcCurrency) @@ -156,13 +155,12 @@ public: Json::Value result; gate g; - app.getJobQueue().postCoro( - jtCLIENT, "RPC-Client", [&](auto const& coro) { - context.params = std::move(params); - context.coro = coro; - RPC::doCommand(context, result); - g.signal(); - }); + app.getJobQueue().postCoro(jtCLIENT, "RPC-Client", [&](auto const& coro) { + context.params = std::move(params); + context.coro = coro; + RPC::doCommand(context, result); + g.signal(); + }); using namespace std::chrono_literals; BEAST_EXPECT(g.wait_for(5s)); @@ -180,8 +178,7 @@ public: std::optional const& saSrcCurrency = std::nullopt, std::optional const& domain = std::nullopt) { - Json::Value result = find_paths_request( - env, src, dst, saDstAmount, saSendMax, saSrcCurrency, domain); + Json::Value result = find_paths_request(env, src, dst, saDstAmount, saSendMax, saSrcCurrency, domain); BEAST_EXPECT(!result.isMember(jss::error)); STAmount da; @@ -201,8 +198,7 @@ public: sa = amountFromJson(sfGeneric, path[jss::source_amount]); if (path.isMember(jss::destination_amount)) - da = amountFromJson( - sfGeneric, path[jss::destination_amount]); + da = amountFromJson(sfGeneric, path[jss::destination_amount]); if (path.isMember(jss::paths_computed)) { @@ -250,53 +246,45 @@ public: Json::Value result; gate g; // Test RPC::Tuning::max_src_cur source currencies. - app.getJobQueue().postCoro( - jtCLIENT, "RPC-Client", [&](auto const& coro) { - context.params = rpf( - Account("alice"), Account("bob"), RPC::Tuning::max_src_cur); - context.coro = coro; - RPC::doCommand(context, result); - g.signal(); - }); + app.getJobQueue().postCoro(jtCLIENT, "RPC-Client", [&](auto const& coro) { + context.params = rpf(Account("alice"), Account("bob"), RPC::Tuning::max_src_cur); + context.coro = coro; + RPC::doCommand(context, result); + g.signal(); + }); BEAST_EXPECT(g.wait_for(5s)); BEAST_EXPECT(!result.isMember(jss::error)); // Test more than RPC::Tuning::max_src_cur source currencies. - app.getJobQueue().postCoro( - jtCLIENT, "RPC-Client", [&](auto const& coro) { - context.params = - rpf(Account("alice"), - Account("bob"), - RPC::Tuning::max_src_cur + 1); - context.coro = coro; - RPC::doCommand(context, result); - g.signal(); - }); + app.getJobQueue().postCoro(jtCLIENT, "RPC-Client", [&](auto const& coro) { + context.params = rpf(Account("alice"), Account("bob"), RPC::Tuning::max_src_cur + 1); + context.coro = coro; + RPC::doCommand(context, result); + g.signal(); + }); BEAST_EXPECT(g.wait_for(5s)); BEAST_EXPECT(result.isMember(jss::error)); // Test RPC::Tuning::max_auto_src_cur source currencies. for (auto i = 0; i < (RPC::Tuning::max_auto_src_cur - 1); ++i) env.trust(Account("alice")[std::to_string(i + 100)](100), "bob"); - app.getJobQueue().postCoro( - jtCLIENT, "RPC-Client", [&](auto const& coro) { - context.params = rpf(Account("alice"), Account("bob"), 0); - context.coro = coro; - RPC::doCommand(context, result); - g.signal(); - }); + app.getJobQueue().postCoro(jtCLIENT, "RPC-Client", [&](auto const& coro) { + context.params = rpf(Account("alice"), Account("bob"), 0); + context.coro = coro; + RPC::doCommand(context, result); + g.signal(); + }); BEAST_EXPECT(g.wait_for(5s)); BEAST_EXPECT(!result.isMember(jss::error)); // Test more than RPC::Tuning::max_auto_src_cur source currencies. env.trust(Account("alice")["AUD"](100), "bob"); - app.getJobQueue().postCoro( - jtCLIENT, "RPC-Client", [&](auto const& coro) { - context.params = rpf(Account("alice"), Account("bob"), 0); - context.coro = coro; - RPC::doCommand(context, result); - g.signal(); - }); + app.getJobQueue().postCoro(jtCLIENT, "RPC-Client", [&](auto const& coro) { + context.params = rpf(Account("alice"), Account("bob"), 0); + context.coro = coro; + RPC::doCommand(context, result); + g.signal(); + }); BEAST_EXPECT(g.wait_for(5s)); BEAST_EXPECT(result.isMember(jss::error)); } @@ -310,8 +298,7 @@ public: env.fund(XRP(10000), "alice", "bob"); env.close(); - auto const result = - find_paths(env, "alice", "bob", Account("bob")["USD"](5)); + auto const result = find_paths(env, "alice", "bob", Account("bob")["USD"](5)); BEAST_EXPECT(std::get<0>(result).empty()); } @@ -327,8 +314,7 @@ public: STPathSet st; STAmount sa; - std::tie(st, sa, std::ignore) = - find_paths(env, "alice", "bob", Account("bob")["USD"](5)); + std::tie(st, sa, std::ignore) = find_paths(env, "alice", "bob", Account("bob")["USD"](5)); BEAST_EXPECT(st.empty()); BEAST_EXPECT(equal(sa, Account("alice")["USD"](5))); } @@ -356,9 +342,7 @@ public: void path_find(bool const domainEnabled) { - testcase( - std::string("path find") + (domainEnabled ? " w/ " : " w/o ") + - "domain"); + testcase(std::string("path find") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); auto const gw = Account("gateway"); @@ -376,14 +360,8 @@ public: STPathSet st; STAmount sa; - std::tie(st, sa, std::ignore) = find_paths( - env, - "alice", - "bob", - Account("bob")["USD"](5), - std::nullopt, - std::nullopt, - domainID); + std::tie(st, sa, std::ignore) = + find_paths(env, "alice", "bob", Account("bob")["USD"](5), std::nullopt, std::nullopt, domainID); BEAST_EXPECT(same(st, stpath("gateway"))); BEAST_EXPECT(equal(sa, Account("alice")["USD"](5))); } @@ -392,9 +370,7 @@ public: xrp_to_xrp(bool const domainEnabled) { using namespace jtx; - testcase( - std::string("XRP to XRP") + (domainEnabled ? " w/ " : " w/o ") + - "domain"); + testcase(std::string("XRP to XRP") + (domainEnabled ? " w/ " : " w/o ") + "domain"); Env env = pathTestEnv(); env.fund(XRP(10000), "alice", "bob"); env.close(); @@ -403,17 +379,14 @@ public: if (domainEnabled) domainID = setupDomain(env, {"alice", "bob"}); - auto const result = find_paths( - env, "alice", "bob", XRP(5), std::nullopt, std::nullopt, domainID); + auto const result = find_paths(env, "alice", "bob", XRP(5), std::nullopt, std::nullopt, domainID); BEAST_EXPECT(std::get<0>(result).empty()); } void path_find_consume_all(bool const domainEnabled) { - testcase( - std::string("path find consume all") + - (domainEnabled ? " w/ " : " w/o ") + "domain"); + testcase(std::string("path find consume all") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; { @@ -428,20 +401,13 @@ public: std::optional domainID; if (domainEnabled) - domainID = setupDomain( - env, {"alice", "bob", "carol", "dan", "edward"}); + domainID = setupDomain(env, {"alice", "bob", "carol", "dan", "edward"}); STPathSet st; STAmount sa; STAmount da; - std::tie(st, sa, da) = find_paths( - env, - "alice", - "edward", - Account("edward")["USD"](-1), - std::nullopt, - std::nullopt, - domainID); + std::tie(st, sa, da) = + find_paths(env, "alice", "edward", Account("edward")["USD"](-1), std::nullopt, std::nullopt, domainID); BEAST_EXPECT(same(st, stpath("dan"), stpath("bob", "carol"))); BEAST_EXPECT(equal(sa, Account("alice")["USD"](110))); BEAST_EXPECT(equal(da, Account("edward")["USD"](110))); @@ -461,8 +427,7 @@ public: std::optional domainID; if (domainEnabled) { - domainID = - setupDomain(env, {"alice", "bob", "carol", "gateway"}); + domainID = setupDomain(env, {"alice", "bob", "carol", "gateway"}); env(offer("carol", XRP(100), USD(100)), domain(*domainID)); } else @@ -514,9 +479,7 @@ public: void alternative_path_consume_both(bool const domainEnabled) { - testcase( - std::string("alternative path consume both") + - (domainEnabled ? " w/ " : " w/o ") + "domain"); + testcase(std::string("alternative path consume both") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); auto const gw = Account("gateway"); @@ -533,20 +496,16 @@ public: std::optional domainID; if (domainEnabled) { - domainID = - setupDomain(env, {"alice", "bob", "gateway", "gateway2"}); + domainID = setupDomain(env, {"alice", "bob", "gateway", "gateway2"}); env(pay(gw, "alice", USD(70)), domain(*domainID)); env(pay(gw2, "alice", gw2_USD(70)), domain(*domainID)); - env(pay("alice", "bob", Account("bob")["USD"](140)), - paths(Account("alice")["USD"]), - domain(*domainID)); + env(pay("alice", "bob", Account("bob")["USD"](140)), paths(Account("alice")["USD"]), domain(*domainID)); } else { env(pay(gw, "alice", USD(70))); env(pay(gw2, "alice", gw2_USD(70))); - env(pay("alice", "bob", Account("bob")["USD"](140)), - paths(Account("alice")["USD"])); + env(pay("alice", "bob", Account("bob")["USD"](140)), paths(Account("alice")["USD"])); } env.require(balance("alice", USD(0))); @@ -563,8 +522,7 @@ public: alternative_paths_consume_best_transfer(bool const domainEnabled) { testcase( - std::string("alternative paths consume best transfer") + - (domainEnabled ? " w/ " : " w/o ") + "domain"); + std::string("alternative paths consume best transfer") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); auto const gw = Account("gateway"); @@ -582,8 +540,7 @@ public: std::optional domainID; if (domainEnabled) { - domainID = - setupDomain(env, {"alice", "bob", "gateway", "gateway2"}); + domainID = setupDomain(env, {"alice", "bob", "gateway", "gateway2"}); env(pay(gw, "alice", USD(70)), domain(*domainID)); env(pay(gw2, "alice", gw2_USD(70)), domain(*domainID)); env(pay("alice", "bob", USD(70)), domain(*domainID)); @@ -637,12 +594,10 @@ public: } void - alternative_paths_limit_returned_paths_to_best_quality( - bool const domainEnabled) + alternative_paths_limit_returned_paths_to_best_quality(bool const domainEnabled) { testcase( - std::string( - "alternative paths - limit returned paths to best quality") + + std::string("alternative paths - limit returned paths to best quality") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); @@ -670,35 +625,21 @@ public: std::optional domainID; if (domainEnabled) { - domainID = - setupDomain(env, {"alice", "bob", "carol", "dan", gw, gw2}); + domainID = setupDomain(env, {"alice", "bob", "carol", "dan", gw, gw2}); } STPathSet st; STAmount sa; - std::tie(st, sa, std::ignore) = find_paths( - env, - "alice", - "bob", - Account("bob")["USD"](5), - std::nullopt, - std::nullopt, - domainID); - BEAST_EXPECT(same( - st, - stpath("gateway"), - stpath("gateway2"), - stpath("dan"), - stpath("carol"))); + std::tie(st, sa, std::ignore) = + find_paths(env, "alice", "bob", Account("bob")["USD"](5), std::nullopt, std::nullopt, domainID); + BEAST_EXPECT(same(st, stpath("gateway"), stpath("gateway2"), stpath("dan"), stpath("carol"))); BEAST_EXPECT(equal(sa, Account("alice")["USD"](5))); } void issues_path_negative_issue(bool const domainEnabled) { - testcase( - std::string("path negative: Issue #5") + - (domainEnabled ? " w/ " : " w/o ") + "domain"); + testcase(std::string("path negative: Issue #5") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); env.fund(XRP(10000), "alice", "bob", "carol", "dan"); @@ -717,27 +658,13 @@ public: domainID = setupDomain(env, {"alice", "bob", "carol", "dan"}); } - auto result = find_paths( - env, - "alice", - "bob", - Account("bob")["USD"](25), - std::nullopt, - std::nullopt, - domainID); + auto result = find_paths(env, "alice", "bob", Account("bob")["USD"](25), std::nullopt, std::nullopt, domainID); BEAST_EXPECT(std::get<0>(result).empty()); env(pay("alice", "bob", Account("alice")["USD"](25)), ter(tecPATH_DRY)); env.close(); - result = find_paths( - env, - "alice", - "bob", - Account("alice")["USD"](25), - std::nullopt, - std::nullopt, - domainID); + result = find_paths(env, "alice", "bob", Account("alice")["USD"](25), std::nullopt, std::nullopt, domainID); BEAST_EXPECT(std::get<0>(result).empty()); env.require(balance("alice", Account("bob")["USD"](0))); @@ -767,8 +694,7 @@ public: env.trust(Account("dan")["USD"](20), "bob"); env.trust(Account("alice")["USD"](20), "carol"); env.trust(Account("carol")["USD"](20), "dan"); - env(pay("alice", "bob", Account("bob")["USD"](55)), - paths(Account("alice")["USD"])); + env(pay("alice", "bob", Account("bob")["USD"](55)), paths(Account("alice")["USD"])); env.require(balance("bob", Account("alice")["USD"](40))); env.require(balance("bob", Account("dan")["USD"](15))); } @@ -788,8 +714,7 @@ public: env.trust(Account("dan")["USD"](100), "bob"); env.trust(Account("alice")["USD"](25), "carol"); env.trust(Account("carol")["USD"](75), "dan"); - env(pay("alice", "bob", Account("bob")["USD"](50)), - paths(Account("alice")["USD"])); + env(pay("alice", "bob", Account("bob")["USD"](50)), paths(Account("alice")["USD"])); env.require(balance("alice", Account("edward")["USD"](-25))); env.require(balance("alice", Account("carol")["USD"](-25))); env.require(balance("bob", Account("edward")["USD"](25))); @@ -806,9 +731,7 @@ public: void via_offers_via_gateway(bool const domainEnabled) { - testcase( - std::string("via gateway") + (domainEnabled ? " w/ " : " w/o ") + - "domain"); + testcase(std::string("via gateway") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); auto const gw = Account("gateway"); @@ -828,10 +751,7 @@ public: domainID = setupDomain(env, {"alice", "bob", "carol", gw}); env(offer("carol", XRP(50), AUD(50)), domain(*domainID)); env.close(); - env(pay("alice", "bob", AUD(10)), - sendmax(XRP(100)), - paths(XRP), - domain(*domainID)); + env(pay("alice", "bob", AUD(10)), sendmax(XRP(100)), paths(XRP), domain(*domainID)); env.close(); } else @@ -845,14 +765,8 @@ public: env.require(balance("bob", AUD(10))); env.require(balance("carol", AUD(39))); - auto const result = find_paths( - env, - "alice", - "bob", - Account("bob")["USD"](25), - std::nullopt, - std::nullopt, - domainID); + auto const result = + find_paths(env, "alice", "bob", Account("bob")["USD"](25), std::nullopt, std::nullopt, domainID); BEAST_EXPECT(std::get<0>(result).empty()); } @@ -869,8 +783,7 @@ public: STPathSet st; STAmount sa; - std::tie(st, sa, std::ignore) = - find_paths(env, "alice", "carol", Account("carol")["USD"](5)); + std::tie(st, sa, std::ignore) = find_paths(env, "alice", "carol", Account("carol")["USD"](5)); BEAST_EXPECT(same(st, stpath("bob"))); BEAST_EXPECT(equal(sa, Account("alice")["USD"](5))); } @@ -915,9 +828,7 @@ public: jv); auto const jv_l = - env.le(keylet::line( - Account("bob").id(), Account("alice")["USD"].issue())) - ->getJson(JsonOptions::none); + env.le(keylet::line(Account("bob").id(), Account("alice")["USD"].issue()))->getJson(JsonOptions::none); for (auto it = jv.begin(); it != jv.end(); ++it) BEAST_EXPECT(*it == jv_l[it.memberName()]); } @@ -959,18 +870,13 @@ public: jv); auto const jv_l = - env.le(keylet::line( - Account("bob").id(), Account("alice")["USD"].issue())) - ->getJson(JsonOptions::none); + env.le(keylet::line(Account("bob").id(), Account("alice")["USD"].issue()))->getJson(JsonOptions::none); for (auto it = jv.begin(); it != jv.end(); ++it) BEAST_EXPECT(*it == jv_l[it.memberName()]); env.trust(Account("bob")["USD"](0), "alice"); env.trust(Account("alice")["USD"](0), "bob"); - BEAST_EXPECT( - env.le(keylet::line( - Account("bob").id(), Account("alice")["USD"].issue())) == - nullptr); + BEAST_EXPECT(env.le(keylet::line(Account("bob").id(), Account("alice")["USD"].issue())) == nullptr); } void @@ -1014,25 +920,18 @@ public: jv); auto const jv_l = - env.le(keylet::line( - Account("alice").id(), Account("bob")["USD"].issue())) - ->getJson(JsonOptions::none); + env.le(keylet::line(Account("alice").id(), Account("bob")["USD"].issue()))->getJson(JsonOptions::none); for (auto it = jv.begin(); it != jv.end(); ++it) BEAST_EXPECT(*it == jv_l[it.memberName()]); env(pay("alice", "bob", Account("alice")["USD"](50))); - BEAST_EXPECT( - env.le(keylet::line( - Account("alice").id(), Account("bob")["USD"].issue())) == - nullptr); + BEAST_EXPECT(env.le(keylet::line(Account("alice").id(), Account("bob")["USD"].issue())) == nullptr); } void path_find_01(bool const domainEnabled) { - testcase( - std::string("Path Find: XRP -> XRP and XRP -> IOU") + - (domainEnabled ? " w/ " : " w/o ") + "domain"); + testcase(std::string("Path Find: XRP -> XRP and XRP -> IOU") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); Account A1{"A1"}; @@ -1084,8 +983,7 @@ public: { auto const& send_amt = XRP(10); - std::tie(st, sa, da) = find_paths( - env, A1, A2, send_amt, std::nullopt, xrpCurrency(), domainID); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, xrpCurrency(), domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(st.empty()); } @@ -1094,22 +992,14 @@ public: // no path should exist for this since dest account // does not exist. auto const& send_amt = XRP(200); - std::tie(st, sa, da) = find_paths( - env, - A1, - Account{"A0"}, - send_amt, - std::nullopt, - xrpCurrency(), - domainID); + std::tie(st, sa, da) = find_paths(env, A1, Account{"A0"}, send_amt, std::nullopt, xrpCurrency(), domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(st.empty()); } { auto const& send_amt = G3["ABC"](10); - std::tie(st, sa, da) = find_paths( - env, A2, G3, send_amt, std::nullopt, xrpCurrency(), domainID); + std::tie(st, sa, da) = find_paths(env, A2, G3, send_amt, std::nullopt, xrpCurrency(), domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, XRP(100))); BEAST_EXPECT(same(st, stpath(IPE(G3["ABC"])))); @@ -1117,8 +1007,7 @@ public: { auto const& send_amt = A2["ABC"](1); - std::tie(st, sa, da) = find_paths( - env, A1, A2, send_amt, std::nullopt, xrpCurrency(), domainID); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, xrpCurrency(), domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, XRP(10))); BEAST_EXPECT(same(st, stpath(IPE(G3["ABC"]), G3))); @@ -1126,8 +1015,7 @@ public: { auto const& send_amt = A3["ABC"](1); - std::tie(st, sa, da) = find_paths( - env, A1, A3, send_amt, std::nullopt, xrpCurrency(), domainID); + std::tie(st, sa, da) = find_paths(env, A1, A3, send_amt, std::nullopt, xrpCurrency(), domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, XRP(10))); BEAST_EXPECT(same(st, stpath(IPE(G3["ABC"]), G3, A2))); @@ -1137,9 +1025,7 @@ public: void path_find_02(bool const domainEnabled) { - testcase( - std::string("Path Find: non-XRP -> XRP") + - (domainEnabled ? " w/ " : " w/o ") + "domain"); + testcase(std::string("Path Find: non-XRP -> XRP") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); Account A1{"A1"}; @@ -1176,14 +1062,7 @@ public: auto const& send_amt = XRP(10); { - std::tie(st, sa, da) = find_paths( - env, - A1, - A2, - send_amt, - std::nullopt, - A2["ABC"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, A2["ABC"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["ABC"](1))); BEAST_EXPECT(same(st, stpath(G3, IPE(xrpIssue())))); @@ -1193,8 +1072,7 @@ public: // paths if (domainEnabled) { - std::tie(st, sa, da) = find_paths( - env, A1, A2, send_amt, std::nullopt, A2["ABC"].currency); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, A2["ABC"].currency); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(st.empty()); } @@ -1204,8 +1082,7 @@ public: path_find_04(bool const domainEnabled) { testcase( - std::string( - "Path Find: Bitstamp and SnapSwap, liquidity with no offers") + + std::string("Path Find: Bitstamp and SnapSwap, liquidity with no offers") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; Env env = pathTestEnv(); @@ -1243,14 +1120,7 @@ public: { auto const& send_amt = A2["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - A1, - A2, - send_amt, - std::nullopt, - A2["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, A2["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same(st, stpath(G1BS, M1, G2SW))); @@ -1258,14 +1128,7 @@ public: { auto const& send_amt = A1["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - A2, - A1, - send_amt, - std::nullopt, - A1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, A2, A1, send_amt, std::nullopt, A1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A2["HKD"](10))); BEAST_EXPECT(same(st, stpath(G2SW, M1, G1BS))); @@ -1273,14 +1136,7 @@ public: { auto const& send_amt = A2["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - G1BS, - A2, - send_amt, - std::nullopt, - A1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, G1BS, A2, send_amt, std::nullopt, A1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, G1BS["HKD"](10))); BEAST_EXPECT(same(st, stpath(M1, G2SW))); @@ -1288,14 +1144,7 @@ public: { auto const& send_amt = M1["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - M1, - G1BS, - send_amt, - std::nullopt, - A1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, M1, G1BS, send_amt, std::nullopt, A1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, M1["HKD"](10))); BEAST_EXPECT(st.empty()); @@ -1303,14 +1152,7 @@ public: { auto const& send_amt = A1["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - G2SW, - A1, - send_amt, - std::nullopt, - A1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, G2SW, A1, send_amt, std::nullopt, A1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, G2SW["HKD"](10))); BEAST_EXPECT(same(st, stpath(M1, G1BS))); @@ -1321,8 +1163,8 @@ public: path_find_05(bool const domainEnabled) { testcase( - std::string("Path Find: non-XRP -> non-XRP, same currency") + - (domainEnabled ? " w/ " : " w/o ") + "domain"); + std::string("Path Find: non-XRP -> non-XRP, same currency") + (domainEnabled ? " w/ " : " w/o ") + + "domain"); using namespace jtx; Env env = pathTestEnv(); Account A1{"A1"}; @@ -1362,8 +1204,7 @@ public: std::optional domainID; if (domainEnabled) { - domainID = - setupDomain(env, {A1, A2, A3, A4, G1, G2, G3, G4, M1, M2}); + domainID = setupDomain(env, {A1, A2, A3, A4, G1, G2, G3, G4, M1, M2}); env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), domain(*domainID)); env(offer(M2, XRP(10000), G2["HKD"](1000)), domain(*domainID)); env(offer(M2, G1["HKD"](1000), XRP(10000)), domain(*domainID)); @@ -1382,14 +1223,7 @@ public: // A) Borrow or repay -- // Source -> Destination (repay source issuer) auto const& send_amt = G1["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - A1, - G1, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, A1, G1, send_amt, std::nullopt, G1["HKD"].currency, domainID); BEAST_EXPECT(st.empty()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); @@ -1399,14 +1233,7 @@ public: // A2) Borrow or repay -- // Source -> Destination (repay destination issuer) auto const& send_amt = A1["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - A1, - G1, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, A1, G1, send_amt, std::nullopt, G1["HKD"].currency, domainID); BEAST_EXPECT(st.empty()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); @@ -1416,14 +1243,7 @@ public: // B) Common gateway -- // Source -> AC -> Destination auto const& send_amt = A3["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - A1, - A3, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, A1, A3, send_amt, std::nullopt, G1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same(st, stpath(G1))); @@ -1433,36 +1253,18 @@ public: // C) Gateway to gateway -- // Source -> OB -> Destination auto const& send_amt = G2["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - G1, - G2, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, G1, G2, send_amt, std::nullopt, G1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, G1["HKD"](10))); - BEAST_EXPECT(same( - st, - stpath(IPE(G2["HKD"])), - stpath(M1), - stpath(M2), - stpath(IPE(xrpIssue()), IPE(G2["HKD"])))); + BEAST_EXPECT( + same(st, stpath(IPE(G2["HKD"])), stpath(M1), stpath(M2), stpath(IPE(xrpIssue()), IPE(G2["HKD"])))); } { // D) User to unlinked gateway via order book -- // Source -> AC -> OB -> Destination auto const& send_amt = G2["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - A1, - G2, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, A1, G2, send_amt, std::nullopt, G1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same( @@ -1478,14 +1280,7 @@ public: // Source -> AC -> OB to XRP -> OB from XRP -> AC -> // Destination auto const& send_amt = A2["HKD"](10); - std::tie(st, sa, da) = find_paths( - env, - A1, - A2, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainID); + std::tie(st, sa, da) = find_paths(env, A1, A2, send_amt, std::nullopt, G1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same( @@ -1501,8 +1296,8 @@ public: path_find_06(bool const domainEnabled) { testcase( - std::string("Path Find: non-XRP -> non-XRP, same currency)") + - (domainEnabled ? " w/ " : " w/o ") + "domain"); + std::string("Path Find: non-XRP -> non-XRP, same currency)") + (domainEnabled ? " w/ " : " w/o ") + + "domain"); using namespace jtx; Env env = pathTestEnv(); Account A1{"A1"}; @@ -1545,8 +1340,7 @@ public: auto const& send_amt = A2["HKD"](10); STPathSet st; STAmount sa, da; - std::tie(st, sa, da) = find_paths( - env, G1, A2, send_amt, std::nullopt, G1["HKD"].currency, domainID); + std::tie(st, sa, da) = find_paths(env, G1, A2, send_amt, std::nullopt, G1["HKD"].currency, domainID); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, G1["HKD"](10))); BEAST_EXPECT(same(st, stpath(M1, G2), stpath(IPE(G2["HKD"]), G2))); @@ -1555,9 +1349,7 @@ public: void receive_max(bool const domainEnabled) { - testcase( - std::string("Receive max") + (domainEnabled ? " w/ " : " w/o ") + - "domain"); + testcase(std::string("Receive max") + (domainEnabled ? " w/ " : " w/o ") + "domain"); using namespace jtx; auto const alice = Account("alice"); @@ -1588,22 +1380,14 @@ public: env.close(); } - auto [st, sa, da] = find_paths( - env, - alice, - bob, - USD(-1), - XRP(100).value(), - std::nullopt, - domainID); + auto [st, sa, da] = find_paths(env, alice, bob, USD(-1), XRP(100).value(), std::nullopt, domainID); BEAST_EXPECT(sa == XRP(10)); BEAST_EXPECT(equal(da, USD(10))); if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1)) { auto const& pathElem = st[0][0]; BEAST_EXPECT( - pathElem.isOffer() && pathElem.getIssuerID() == gw.id() && - pathElem.getCurrency() == USD.currency); + pathElem.isOffer() && pathElem.getIssuerID() == gw.id() && pathElem.getCurrency() == USD.currency); } } { @@ -1629,22 +1413,14 @@ public: env.close(); } - auto [st, sa, da] = find_paths( - env, - alice, - bob, - drops(-1), - USD(100).value(), - std::nullopt, - domainID); + auto [st, sa, da] = find_paths(env, alice, bob, drops(-1), USD(100).value(), std::nullopt, domainID); BEAST_EXPECT(sa == USD(10)); BEAST_EXPECT(equal(da, XRP(10))); if (BEAST_EXPECT(st.size() == 1 && st[0].size() == 1)) { auto const& pathElem = st[0][0]; BEAST_EXPECT( - pathElem.isOffer() && - pathElem.getIssuerID() == xrpAccount() && + pathElem.isOffer() && pathElem.getIssuerID() == xrpAccount() && pathElem.getCurrency() == xrpCurrency()); } } @@ -1662,10 +1438,7 @@ public: auto const bob = Account("bob"); auto const george = Account("george"); auto const USD = george["USD"]; - auto test = [&](std::string casename, - bool aliceRipple, - bool bobRipple, - bool expectPath) { + auto test = [&](std::string casename, bool aliceRipple, bool bobRipple, bool expectPath) { testcase(casename); Env env = pathTestEnv(); @@ -1673,26 +1446,15 @@ public: env.close(); // Set the same flags at both ends of the trustline, even though // only george's matter. - env(trust( - alice, - USD(100), - aliceRipple ? tfClearNoRipple : tfSetNoRipple)); - env(trust( - george, - alice["USD"](100), - aliceRipple ? tfClearNoRipple : tfSetNoRipple)); - env(trust( - bob, USD(100), bobRipple ? tfClearNoRipple : tfSetNoRipple)); - env(trust( - george, - bob["USD"](100), - bobRipple ? tfClearNoRipple : tfSetNoRipple)); + env(trust(alice, USD(100), aliceRipple ? tfClearNoRipple : tfSetNoRipple)); + env(trust(george, alice["USD"](100), aliceRipple ? tfClearNoRipple : tfSetNoRipple)); + env(trust(bob, USD(100), bobRipple ? tfClearNoRipple : tfSetNoRipple)); + env(trust(george, bob["USD"](100), bobRipple ? tfClearNoRipple : tfSetNoRipple)); env.close(); env(pay(george, alice, USD(70))); env.close(); - auto [st, sa, da] = - find_paths(env, "alice", "bob", Account("bob")["USD"](5)); + auto [st, sa, da] = find_paths(env, "alice", "bob", Account("bob")["USD"](5)); BEAST_EXPECT(equal(da, bob["USD"](5))); if (expectPath) @@ -1758,8 +1520,7 @@ public: env(pay(G2, M2, G2["HKD"](5000))); env.close(); - std::optional domainID = - setupDomain(env, {A1, A2, A3, A4, G1, G2, G3, G4, M1, M2}); + std::optional domainID = setupDomain(env, {A1, A2, A3, A4, G1, G2, G3, G4, M1, M2}); BEAST_EXPECT(domainID); func(env, M1, M2, G1, G2, *domainID); @@ -1772,13 +1533,7 @@ public: // Source -> Destination (repay source issuer) auto const& send_amt = G1["HKD"](10); std::tie(st, sa, da) = find_paths( - env, - A1, - G1, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainEnabled ? domainID : std::nullopt); + env, A1, G1, send_amt, std::nullopt, G1["HKD"].currency, domainEnabled ? domainID : std::nullopt); BEAST_EXPECT(st.empty()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); @@ -1789,13 +1544,7 @@ public: // Source -> Destination (repay destination issuer) auto const& send_amt = A1["HKD"](10); std::tie(st, sa, da) = find_paths( - env, - A1, - G1, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainEnabled ? domainID : std::nullopt); + env, A1, G1, send_amt, std::nullopt, G1["HKD"].currency, domainEnabled ? domainID : std::nullopt); BEAST_EXPECT(st.empty()); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); @@ -1806,13 +1555,7 @@ public: // Source -> AC -> Destination auto const& send_amt = A3["HKD"](10); std::tie(st, sa, da) = find_paths( - env, - A1, - A3, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainEnabled ? domainID : std::nullopt); + env, A1, A3, send_amt, std::nullopt, G1["HKD"].currency, domainEnabled ? domainID : std::nullopt); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same(st, stpath(G1))); @@ -1823,21 +1566,11 @@ public: // Source -> OB -> Destination auto const& send_amt = G2["HKD"](10); std::tie(st, sa, da) = find_paths( - env, - G1, - G2, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainEnabled ? domainID : std::nullopt); + env, G1, G2, send_amt, std::nullopt, G1["HKD"].currency, domainEnabled ? domainID : std::nullopt); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, G1["HKD"](10))); - BEAST_EXPECT(same( - st, - stpath(IPE(G2["HKD"])), - stpath(M1), - stpath(M2), - stpath(IPE(xrpIssue()), IPE(G2["HKD"])))); + BEAST_EXPECT( + same(st, stpath(IPE(G2["HKD"])), stpath(M1), stpath(M2), stpath(IPE(xrpIssue()), IPE(G2["HKD"])))); } { @@ -1845,13 +1578,7 @@ public: // Source -> AC -> OB -> Destination auto const& send_amt = G2["HKD"](10); std::tie(st, sa, da) = find_paths( - env, - A1, - G2, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainEnabled ? domainID : std::nullopt); + env, A1, G2, send_amt, std::nullopt, G1["HKD"].currency, domainEnabled ? domainID : std::nullopt); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same( @@ -1868,13 +1595,7 @@ public: // Destination auto const& send_amt = A2["HKD"](10); std::tie(st, sa, da) = find_paths( - env, - A1, - A2, - send_amt, - std::nullopt, - G1["HKD"].currency, - domainEnabled ? domainID : std::nullopt); + env, A1, A2, send_amt, std::nullopt, G1["HKD"].currency, domainEnabled ? domainID : std::nullopt); BEAST_EXPECT(equal(da, send_amt)); BEAST_EXPECT(equal(sa, A1["HKD"](10))); BEAST_EXPECT(same( @@ -1890,77 +1611,34 @@ public: // offers to make sure that hybrid offers work in pathfinding for open // order book { - testPathfind([](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { - env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); + testPathfind([](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { + env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); env(offer(M2, XRP(10000), G2["HKD"](1000))); env(offer(M2, G1["HKD"](1000), XRP(10000))); }); - testPathfind([](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { - env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); - env(offer(M2, XRP(10000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); + testPathfind([](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { + env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); + env(offer(M2, XRP(10000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); env(offer(M2, G1["HKD"](1000), XRP(10000))); }); - testPathfind([](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { - env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); - env(offer(M2, XRP(10000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); - env(offer(M2, G1["HKD"](1000), XRP(10000)), - domain(domainID), - txflags(tfHybrid)); + testPathfind([](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { + env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); + env(offer(M2, XRP(10000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); + env(offer(M2, G1["HKD"](1000), XRP(10000)), domain(domainID), txflags(tfHybrid)); }); - testPathfind([](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { + testPathfind([](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { env(offer(M1, G1["HKD"](1000), G2["HKD"](1000))); env(offer(M2, XRP(10000), G2["HKD"](1000))); - env(offer(M2, G1["HKD"](1000), XRP(10000)), - domain(domainID), - txflags(tfHybrid)); + env(offer(M2, G1["HKD"](1000), XRP(10000)), domain(domainID), txflags(tfHybrid)); }); - testPathfind([](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { + testPathfind([](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { env(offer(M1, G1["HKD"](1000), G2["HKD"](1000))); - env(offer(M2, XRP(10000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); - env(offer(M2, G1["HKD"](1000), XRP(10000)), - domain(domainID), - txflags(tfHybrid)); + env(offer(M2, XRP(10000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); + env(offer(M2, G1["HKD"](1000), XRP(10000)), domain(domainID), txflags(tfHybrid)); }); } @@ -1969,72 +1647,34 @@ public: // order book { testPathfind( - [](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { - env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); - env(offer(M2, XRP(10000), G2["HKD"](1000)), - domain(domainID)); - env(offer(M2, G1["HKD"](1000), XRP(10000)), - domain(domainID)); + [](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { + env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); + env(offer(M2, XRP(10000), G2["HKD"](1000)), domain(domainID)); + env(offer(M2, G1["HKD"](1000), XRP(10000)), domain(domainID)); }, true); testPathfind( - [](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { - env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); - env(offer(M2, XRP(10000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); - env(offer(M2, G1["HKD"](1000), XRP(10000)), - domain(domainID)); + [](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { + env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); + env(offer(M2, XRP(10000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); + env(offer(M2, G1["HKD"](1000), XRP(10000)), domain(domainID)); }, true); testPathfind( - [](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { - env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), - domain(domainID)); - env(offer(M2, XRP(10000), G2["HKD"](1000)), - domain(domainID)); - env(offer(M2, G1["HKD"](1000), XRP(10000)), - domain(domainID), - txflags(tfHybrid)); + [](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { + env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), domain(domainID)); + env(offer(M2, XRP(10000), G2["HKD"](1000)), domain(domainID)); + env(offer(M2, G1["HKD"](1000), XRP(10000)), domain(domainID), txflags(tfHybrid)); }, true); testPathfind( - [](Env& env, - Account M1, - Account M2, - Account G1, - Account G2, - uint256 domainID) { - env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), - domain(domainID)); - env(offer(M2, XRP(10000), G2["HKD"](1000)), - domain(domainID), - txflags(tfHybrid)); - env(offer(M2, G1["HKD"](1000), XRP(10000)), - domain(domainID), - txflags(tfHybrid)); + [](Env& env, Account M1, Account M2, Account G1, Account G2, uint256 domainID) { + env(offer(M1, G1["HKD"](1000), G2["HKD"](1000)), domain(domainID)); + env(offer(M2, XRP(10000), G2["HKD"](1000)), domain(domainID), txflags(tfHybrid)); + env(offer(M2, G1["HKD"](1000), XRP(10000)), domain(domainID), txflags(tfHybrid)); }, true); } @@ -2047,8 +1687,7 @@ public: using namespace jtx; Env env = pathTestEnv(); PermissionedDEX permDex(env); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - permDex; + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = permDex; AMM amm(env, alice, XRP(10), USD(50)); STPathSet st; @@ -2057,13 +1696,11 @@ public: auto const& send_amt = XRP(1); // doing pathfind with domain won't include amm - std::tie(st, sa, da) = find_paths( - env, bob, carol, send_amt, std::nullopt, USD.currency, domainID); + std::tie(st, sa, da) = find_paths(env, bob, carol, send_amt, std::nullopt, USD.currency, domainID); BEAST_EXPECT(st.empty()); // a non-domain pathfind returns amm in the path - std::tie(st, sa, da) = - find_paths(env, bob, carol, send_amt, std::nullopt, USD.currency); + std::tie(st, sa, da) = find_paths(env, bob, carol, send_amt, std::nullopt, USD.currency); BEAST_EXPECT(same(st, stpath(gw, IPE(xrpIssue())))); } @@ -2089,8 +1726,7 @@ public: path_find_consume_all(domainEnabled); alternative_path_consume_both(domainEnabled); alternative_paths_consume_best_transfer(domainEnabled); - alternative_paths_limit_returned_paths_to_best_quality( - domainEnabled); + alternative_paths_limit_returned_paths_to_best_quality(domainEnabled); issues_path_negative_issue(domainEnabled); via_offers_via_gateway(domainEnabled); xrp_to_xrp(domainEnabled); diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index ed8c3c507e..019dd42ca1 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -15,10 +15,7 @@ using namespace jtx::paychan; struct PayChan_test : public beast::unit_test::suite { static std::pair> - channelKeyAndSle( - ReadView const& view, - jtx::Account const& account, - jtx::Account const& dst) + channelKeyAndSle(ReadView const& view, jtx::Account const& account, jtx::Account const& dst) { auto const sle = view.read(keylet::account(account)); if (!sle) @@ -28,11 +25,7 @@ struct PayChan_test : public beast::unit_test::suite } static Buffer - signClaimAuth( - PublicKey const& pk, - SecretKey const& sk, - uint256 const& channel, - STAmount const& authAmt) + signClaimAuth(PublicKey const& pk, SecretKey const& sk, uint256 const& channel, STAmount const& authAmt) { Serializer msg; serializePayChanAuthorization(msg, channel, authAmt.xrp()); @@ -91,27 +84,19 @@ struct PayChan_test : public beast::unit_test::suite { // bad amounts (non-xrp, negative amounts) - env(create(alice, bob, USDA(1000), settleDelay, pk), - ter(temBAD_AMOUNT)); + env(create(alice, bob, USDA(1000), settleDelay, pk), ter(temBAD_AMOUNT)); env(fund(alice, chan, USDA(1000)), ter(temBAD_AMOUNT)); - env(create(alice, bob, XRP(-1000), settleDelay, pk), - ter(temBAD_AMOUNT)); + env(create(alice, bob, XRP(-1000), settleDelay, pk), ter(temBAD_AMOUNT)); env(fund(alice, chan, XRP(-1000)), ter(temBAD_AMOUNT)); } // invalid account - env(create(alice, "noAccount", XRP(1000), settleDelay, pk), - ter(tecNO_DST)); + env(create(alice, "noAccount", XRP(1000), settleDelay, pk), ter(tecNO_DST)); // can't create channel to the same account - env(create(alice, alice, XRP(1000), settleDelay, pk), - ter(temDST_IS_SRC)); + env(create(alice, alice, XRP(1000), settleDelay, pk), ter(temDST_IS_SRC)); // invalid channel - env(fund( - alice, - channel(alice, "noAccount", env.seq(alice) - 1), - XRP(1000)), - ter(tecNO_ENTRY)); + env(fund(alice, channel(alice, "noAccount", env.seq(alice) - 1), XRP(1000)), ter(tecNO_ENTRY)); // not enough funds env(create(alice, bob, XRP(10000), settleDelay, pk), ter(tecUNFUNDED)); @@ -155,8 +140,7 @@ struct PayChan_test : public beast::unit_test::suite auto const reqBal = chanBal + delta; auto const authAmt = reqBal + XRP(100); assert(reqBal <= chanAmt); - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk())); BEAST_EXPECT(channelBalance(*env.current(), chan) == reqBal); BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); @@ -166,8 +150,7 @@ struct PayChan_test : public beast::unit_test::suite // claim again preBob = env.balance(bob); - env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()), - ter(tecUNFUNDED_PAYMENT)); + env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()), ter(tecUNFUNDED_PAYMENT)); BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); BEAST_EXPECT(env.balance(bob) == preBob - feeDrops); @@ -178,10 +161,8 @@ struct PayChan_test : public beast::unit_test::suite STAmount const authAmt = chanBal + XRP(500); STAmount const reqAmt = authAmt + STAmount{1}; assert(reqAmt <= chanAmt); - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); - env(claim(bob, chan, reqAmt, authAmt, Slice(sig), alice.pk()), - ter(temBAD_AMOUNT)); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); + env(claim(bob, chan, reqAmt, authAmt, Slice(sig), alice.pk()), ter(temBAD_AMOUNT)); BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); BEAST_EXPECT(env.balance(bob) == preBob); @@ -195,28 +176,14 @@ struct PayChan_test : public beast::unit_test::suite { // Wrong signing key auto const sig = signClaimAuth(bob.pk(), bob.sk(), chan, XRP(1500)); - env(claim( - bob, - chan, - XRP(1500).value(), - XRP(1500).value(), - Slice(sig), - bob.pk()), - ter(temBAD_SIGNER)); + env(claim(bob, chan, XRP(1500).value(), XRP(1500).value(), Slice(sig), bob.pk()), ter(temBAD_SIGNER)); BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); } { // Bad signature auto const sig = signClaimAuth(bob.pk(), bob.sk(), chan, XRP(1500)); - env(claim( - bob, - chan, - XRP(1500).value(), - XRP(1500).value(), - Slice(sig), - alice.pk()), - ter(temBAD_SIGNATURE)); + env(claim(bob, chan, XRP(1500).value(), XRP(1500).value(), Slice(sig), alice.pk()), ter(temBAD_SIGNATURE)); BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal); BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); } @@ -256,8 +223,7 @@ struct PayChan_test : public beast::unit_test::suite // channel creation from alice to bob is disallowed { auto const chan = channel(alice, bob, env.seq(alice)); - env(create(alice, bob, XRP(1000), settleDelay, pk), - ter(tecNO_PERMISSION)); + env(create(alice, bob, XRP(1000), settleDelay, pk), ter(tecNO_PERMISSION)); BEAST_EXPECT(!channelExists(*env.current(), chan)); } @@ -268,8 +234,7 @@ struct PayChan_test : public beast::unit_test::suite // channel creation from bob to alice is now disallowed { auto const chan = channel(bob, alice, env.seq(bob)); - env(create(bob, alice, XRP(1000), settleDelay, pk), - ter(tecNO_PERMISSION)); + env(create(bob, alice, XRP(1000), settleDelay, pk), ter(tecNO_PERMISSION)); BEAST_EXPECT(!channelExists(*env.current(), chan)); } @@ -280,16 +245,14 @@ struct PayChan_test : public beast::unit_test::suite // now the channel between alice and bob can exist { auto const chan = channel(alice, bob, env.seq(alice)); - env(create(alice, bob, XRP(1000), settleDelay, pk), - ter(tesSUCCESS)); + env(create(alice, bob, XRP(1000), settleDelay, pk), ter(tesSUCCESS)); BEAST_EXPECT(channelExists(*env.current(), chan)); } // a channel from cho to alice isn't allowed { auto const chan = channel(cho, alice, env.seq(cho)); - env(create(cho, alice, XRP(1000), settleDelay, pk), - ter(tecNO_PERMISSION)); + env(create(cho, alice, XRP(1000), settleDelay, pk), ter(tecNO_PERMISSION)); BEAST_EXPECT(!channelExists(*env.current(), chan)); } @@ -300,8 +263,7 @@ struct PayChan_test : public beast::unit_test::suite // now a channel from cho to alice is allowed { auto const chan = channel(cho, alice, env.seq(cho)); - env(create(cho, alice, XRP(1000), settleDelay, pk), - ter(tesSUCCESS)); + env(create(cho, alice, XRP(1000), settleDelay, pk), ter(tesSUCCESS)); BEAST_EXPECT(channelExists(*env.current(), chan)); } } @@ -321,8 +283,7 @@ struct PayChan_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob); auto const pk = alice.pk(); auto const settleDelay = 100s; - NetClock::time_point const cancelAfter = - env.current()->header().parentCloseTime + 3600s; + NetClock::time_point const cancelAfter = env.current()->header().parentCloseTime + 3600s; auto const channelFunds = XRP(1000); auto const chan = channel(alice, bob, env.seq(alice)); env(create(alice, bob, channelFunds, settleDelay, pk, cancelAfter)); @@ -338,8 +299,7 @@ struct PayChan_test : public beast::unit_test::suite auto const reqBal = chanBal + delta; auto const authAmt = reqBal + XRP(100); assert(reqBal <= chanAmt); - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk())); auto const feeDrops = env.current()->fees().base; BEAST_EXPECT(!channelExists(*env.current(), chan)); @@ -353,8 +313,7 @@ struct PayChan_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob, carol); auto const pk = alice.pk(); auto const settleDelay = 100s; - NetClock::time_point const cancelAfter = - env.current()->header().parentCloseTime + 3600s; + NetClock::time_point const cancelAfter = env.current()->header().parentCloseTime + 3600s; auto const channelFunds = XRP(1000); auto const chan = channel(alice, bob, env.seq(alice)); env(create(alice, bob, channelFunds, settleDelay, pk, cancelAfter)); @@ -374,9 +333,7 @@ struct PayChan_test : public beast::unit_test::suite { for (bool const withFixPayChan : {true, false}) { - auto const amend = withFixPayChan - ? features - : features - fixPayChanCancelAfter; + auto const amend = withFixPayChan ? features : features - fixPayChanCancelAfter; Env env{*this, amend}; env.fund(XRP(10000), alice, bob); env.close(); @@ -384,13 +341,9 @@ struct PayChan_test : public beast::unit_test::suite auto const pk = alice.pk(); auto const settleDelay = 100s; auto const channelFunds = XRP(1000); - NetClock::time_point const cancelAfter = - env.current()->header().parentCloseTime - 1s; - auto const txResult = - withFixPayChan ? ter(tecEXPIRED) : ter(tesSUCCESS); - env(create( - alice, bob, channelFunds, settleDelay, pk, cancelAfter), - txResult); + NetClock::time_point const cancelAfter = env.current()->header().parentCloseTime - 1s; + auto const txResult = withFixPayChan ? ter(tecEXPIRED) : ter(tesSUCCESS); + env(create(alice, bob, channelFunds, settleDelay, pk, cancelAfter), txResult); } } // fixPayChanCancelAfter @@ -398,9 +351,7 @@ struct PayChan_test : public beast::unit_test::suite { for (bool const withFixPayChan : {true, false}) { - auto const amend = withFixPayChan - ? features - : features - fixPayChanCancelAfter; + auto const amend = withFixPayChan ? features : features - fixPayChanCancelAfter; Env env{*this, amend}; env.fund(XRP(10000), alice, bob); env.close(); @@ -408,11 +359,8 @@ struct PayChan_test : public beast::unit_test::suite auto const pk = alice.pk(); auto const settleDelay = 100s; auto const channelFunds = XRP(1000); - NetClock::time_point const cancelAfter = - env.current()->header().parentCloseTime; - env(create( - alice, bob, channelFunds, settleDelay, pk, cancelAfter), - ter(tesSUCCESS)); + NetClock::time_point const cancelAfter = env.current()->header().parentCloseTime; + env(create(alice, bob, channelFunds, settleDelay, pk, cancelAfter), ter(tesSUCCESS)); } } } @@ -440,46 +388,28 @@ struct PayChan_test : public beast::unit_test::suite BEAST_EXPECT(!channelExpiration(*env.current(), chan)); // Owner closes, will close after settleDelay env(claim(alice, chan), txflags(tfClose)); - auto counts = [](auto const& t) { - return t.time_since_epoch().count(); - }; - BEAST_EXPECT( - *channelExpiration(*env.current(), chan) == counts(minExpiration)); + auto counts = [](auto const& t) { return t.time_since_epoch().count(); }; + BEAST_EXPECT(*channelExpiration(*env.current(), chan) == counts(minExpiration)); // increase the expiration time - env(fund( - alice, chan, XRP(1), NetClock::time_point{minExpiration + 100s})); - BEAST_EXPECT( - *channelExpiration(*env.current(), chan) == - counts(minExpiration) + 100); + env(fund(alice, chan, XRP(1), NetClock::time_point{minExpiration + 100s})); + BEAST_EXPECT(*channelExpiration(*env.current(), chan) == counts(minExpiration) + 100); // decrease the expiration, but still above minExpiration - env(fund( - alice, chan, XRP(1), NetClock::time_point{minExpiration + 50s})); - BEAST_EXPECT( - *channelExpiration(*env.current(), chan) == - counts(minExpiration) + 50); + env(fund(alice, chan, XRP(1), NetClock::time_point{minExpiration + 50s})); + BEAST_EXPECT(*channelExpiration(*env.current(), chan) == counts(minExpiration) + 50); // decrease the expiration below minExpiration - env(fund( - alice, chan, XRP(1), NetClock::time_point{minExpiration - 50s}), - ter(temBAD_EXPIRATION)); - BEAST_EXPECT( - *channelExpiration(*env.current(), chan) == - counts(minExpiration) + 50); + env(fund(alice, chan, XRP(1), NetClock::time_point{minExpiration - 50s}), ter(temBAD_EXPIRATION)); + BEAST_EXPECT(*channelExpiration(*env.current(), chan) == counts(minExpiration) + 50); env(claim(bob, chan), txflags(tfRenew), ter(tecNO_PERMISSION)); - BEAST_EXPECT( - *channelExpiration(*env.current(), chan) == - counts(minExpiration) + 50); + BEAST_EXPECT(*channelExpiration(*env.current(), chan) == counts(minExpiration) + 50); env(claim(alice, chan), txflags(tfRenew)); BEAST_EXPECT(!channelExpiration(*env.current(), chan)); // decrease the expiration below minExpiration - env(fund( - alice, chan, XRP(1), NetClock::time_point{minExpiration - 50s}), - ter(temBAD_EXPIRATION)); + env(fund(alice, chan, XRP(1), NetClock::time_point{minExpiration - 50s}), ter(temBAD_EXPIRATION)); BEAST_EXPECT(!channelExpiration(*env.current(), chan)); env(fund(alice, chan, XRP(1), NetClock::time_point{minExpiration})); env.close(minExpiration); // Try to extend the expiration after the expiration has already passed - env(fund( - alice, chan, XRP(1), NetClock::time_point{minExpiration + 1000s})); + env(fund(alice, chan, XRP(1), NetClock::time_point{minExpiration + 1000s})); BEAST_EXPECT(!channelExists(*env.current(), chan)); } @@ -495,8 +425,7 @@ struct PayChan_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob); auto const pk = alice.pk(); auto const settleDelay = 3600s; - NetClock::time_point const settleTimepoint = - env.current()->header().parentCloseTime + settleDelay; + NetClock::time_point const settleTimepoint = env.current()->header().parentCloseTime + settleDelay; auto const channelFunds = XRP(1000); auto const chan = channel(alice, bob, env.seq(alice)); env(create(alice, bob, channelFunds, settleDelay, pk)); @@ -514,8 +443,7 @@ struct PayChan_test : public beast::unit_test::suite auto const reqBal = chanBal + delta; auto const authAmt = reqBal + XRP(100); assert(reqBal <= chanAmt); - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk())); BEAST_EXPECT(channelBalance(*env.current(), chan) == reqBal); BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt); @@ -533,8 +461,7 @@ struct PayChan_test : public beast::unit_test::suite auto const reqBal = chanBal + delta; auto const authAmt = reqBal + XRP(100); assert(reqBal <= chanAmt); - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk())); BEAST_EXPECT(!channelExists(*env.current(), chan)); auto const feeDrops = env.current()->fees().base; @@ -605,8 +532,7 @@ struct PayChan_test : public beast::unit_test::suite auto const delta = XRP(500); auto const reqBal = chanBal + delta; assert(reqBal <= chanAmt); - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, reqBal); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, reqBal); env(claim(bob, chan, reqBal, std::nullopt, Slice(sig), alice.pk())); BEAST_EXPECT(channelBalance(*env.current(), chan) == reqBal); auto const feeDrops = env.current()->fees().base; @@ -622,8 +548,7 @@ struct PayChan_test : public beast::unit_test::suite auto const delta = XRP(500); auto const reqBal = chanBal + delta; assert(reqBal <= chanAmt); - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, reqBal); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, reqBal); env(claim(bob, chan, reqBal, std::nullopt, Slice(sig), alice.pk())); BEAST_EXPECT(channelBalance(*env.current(), chan) == reqBal); auto const feeDrops = env.current()->fees().base; @@ -687,14 +612,12 @@ struct PayChan_test : public beast::unit_test::suite auto const channelFunds = XRP(1000); { auto const chan = channel(alice, bob, env.seq(alice)); - env(create(alice, bob, channelFunds, settleDelay, pk), - ter(tecDST_TAG_NEEDED)); + env(create(alice, bob, channelFunds, settleDelay, pk), ter(tecDST_TAG_NEEDED)); BEAST_EXPECT(!channelExists(*env.current(), chan)); } { auto const chan = channel(alice, bob, env.seq(alice)); - env(create( - alice, bob, channelFunds, settleDelay, pk, std::nullopt, 1)); + env(create(alice, bob, channelFunds, settleDelay, pk, std::nullopt, 1)); BEAST_EXPECT(channelExists(*env.current(), chan)); } } @@ -732,8 +655,7 @@ struct PayChan_test : public beast::unit_test::suite env.close(); // alice claims. Fails because bob's lsfDepositAuth flag is set. - env(claim(alice, chan, XRP(500).value(), XRP(500).value()), - ter(tecNO_PERMISSION)); + env(claim(alice, chan, XRP(500).value(), XRP(500).value()), ter(tecNO_PERMISSION)); env.close(); // Claim with signature @@ -745,8 +667,7 @@ struct PayChan_test : public beast::unit_test::suite // alice claims with signature. Fails since bob has // lsfDepositAuth flag set. - env(claim(alice, chan, delta, delta, Slice(sig), pk), - ter(tecNO_PERMISSION)); + env(claim(alice, chan, delta, delta, Slice(sig), pk), ter(tecNO_PERMISSION)); env.close(); BEAST_EXPECT(env.balance(bob) == preBob); @@ -769,8 +690,7 @@ struct PayChan_test : public beast::unit_test::suite // carol claims and fails. Only channel participants (bob or // alice) may claim. - env(claim(carol, chan, delta, delta, Slice(sig), pk), - ter(tecNO_PERMISSION)); + env(claim(carol, chan, delta, delta, Slice(sig), pk), ter(tecNO_PERMISSION)); env.close(); // bob preauthorizes carol for deposit. But after that carol @@ -778,13 +698,11 @@ struct PayChan_test : public beast::unit_test::suite env(deposit::auth(bob, carol)); env.close(); - env(claim(carol, chan, delta, delta, Slice(sig), pk), - ter(tecNO_PERMISSION)); + env(claim(carol, chan, delta, delta, Slice(sig), pk), ter(tecNO_PERMISSION)); // Since alice is not preauthorized she also may not claim // for bob. - env(claim(alice, chan, delta, delta, Slice(sig), pk), - ter(tecNO_PERMISSION)); + env(claim(alice, chan, delta, delta, Slice(sig), pk), ter(tecNO_PERMISSION)); env.close(); // However if bob preauthorizes alice for deposit then she can @@ -795,8 +713,7 @@ struct PayChan_test : public beast::unit_test::suite env(claim(alice, chan, delta, delta, Slice(sig), pk)); env.close(); - BEAST_EXPECT( - env.balance(bob) == preBob + delta - (3 * baseFee)); + BEAST_EXPECT(env.balance(bob) == preBob + delta - (3 * baseFee)); } { // bob removes pre-authorization of alice. Once again she @@ -817,8 +734,7 @@ struct PayChan_test : public beast::unit_test::suite // alice claims successfully. env(claim(alice, chan, delta, delta)); env.close(); - BEAST_EXPECT( - env.balance(bob) == preBob + XRP(800) - (5 * baseFee)); + BEAST_EXPECT(env.balance(bob) == preBob + XRP(800) - (5 * baseFee)); } } } @@ -860,18 +776,13 @@ struct PayChan_test : public beast::unit_test::suite { // create credentials auto jv = credentials::create(alice, carol, credType); - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() + - 100; + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count() + 100; jv[sfExpiration.jsonName] = t; env(jv); env.close(); } - auto const jv = - credentials::ledgerEntry(env, alice, carol, credType); + auto const jv = credentials::ledgerEntry(env, alice, carol, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); // Bob require pre-authorization @@ -879,18 +790,14 @@ struct PayChan_test : public beast::unit_test::suite env.close(); // Fail, credentials not accepted - env(claim(alice, chan, delta, delta), - credentials::ids({credIdx}), - ter(tecBAD_CREDENTIALS)); + env(claim(alice, chan, delta, delta), credentials::ids({credIdx}), ter(tecBAD_CREDENTIALS)); env.close(); env(credentials::accept(alice, carol, credType)); env.close(); // Fail, no depositPreauth object - env(claim(alice, chan, delta, delta), - credentials::ids({credIdx}), - ter(tecNO_PERMISSION)); + env(claim(alice, chan, delta, delta), credentials::ids({credIdx}), ter(tecNO_PERMISSION)); env.close(); // Setup deposit authorization @@ -898,22 +805,16 @@ struct PayChan_test : public beast::unit_test::suite env.close(); // Fail, credentials doesn’t belong to root account - env(claim(dillon, chan, delta, delta), - credentials::ids({credIdx}), - ter(tecBAD_CREDENTIALS)); + env(claim(dillon, chan, delta, delta), credentials::ids({credIdx}), ter(tecBAD_CREDENTIALS)); // Fails because bob's lsfDepositAuth flag is set. env(claim(alice, chan, delta, delta), ter(tecNO_PERMISSION)); // Fail, bad credentials index. - env(claim(alice, chan, delta, delta), - credentials::ids({credBadIdx}), - ter(tecBAD_CREDENTIALS)); + env(claim(alice, chan, delta, delta), credentials::ids({credBadIdx}), ter(tecBAD_CREDENTIALS)); // Fail, empty credentials - env(claim(alice, chan, delta, delta), - credentials::ids({}), - ter(temMALFORMED)); + env(claim(alice, chan, delta, delta), credentials::ids({}), ter(temMALFORMED)); { // claim fails cause of expired credentials @@ -922,9 +823,7 @@ struct PayChan_test : public beast::unit_test::suite for (int i = 0; i < 10; ++i) env.close(); - env(claim(alice, chan, delta, delta), - credentials::ids({credIdx}), - ter(tecEXPIRED)); + env(claim(alice, chan, delta, delta), credentials::ids({credIdx}), ter(tecEXPIRED)); env.close(); } @@ -934,14 +833,11 @@ struct PayChan_test : public beast::unit_test::suite env(credentials::accept(alice, carol, credType)); env.close(); - auto const jv = - credentials::ledgerEntry(env, alice, carol, credType); - std::string const credIdx = - jv[jss::result][jss::index].asString(); + auto const jv = credentials::ledgerEntry(env, alice, carol, credType); + std::string const credIdx = jv[jss::result][jss::index].asString(); // Success - env(claim(alice, chan, delta, delta), - credentials::ids({credIdx})); + env(claim(alice, chan, delta, delta), credentials::ids({credIdx})); } } @@ -968,8 +864,7 @@ struct PayChan_test : public beast::unit_test::suite env.close(); } - auto const jv = - credentials::ledgerEntry(env, alice, carol, credType); + auto const jv = credentials::ledgerEntry(env, alice, carol, credType); std::string const credIdx = jv[jss::result][jss::index].asString(); // Succeed, lsfDepositAuth is not set @@ -1001,9 +896,7 @@ struct PayChan_test : public beast::unit_test::suite env(deposit::auth(bob, alice)); env.close(); - env(claim(alice, chan, XRP(500).value(), XRP(500).value()), - credentials::ids({credIdx}), - ter(temDISABLED)); + env(claim(alice, chan, XRP(500).value(), XRP(500).value()), credentials::ids({credIdx}), ter(temDISABLED)); } } @@ -1053,11 +946,9 @@ struct PayChan_test : public beast::unit_test::suite auto testInvalidAccountParam = [&](auto const& param) { Json::Value params; params[jss::account] = param; - auto jrr = env.rpc( - "json", "account_channels", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_channels", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -1068,23 +959,19 @@ struct PayChan_test : public beast::unit_test::suite testInvalidAccountParam(Json::Value(Json::arrayValue)); } { - auto const r = - env.rpc("account_channels", alice.human(), bob.human()); + auto const r = env.rpc("account_channels", alice.human(), bob.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 1); - BEAST_EXPECT( - r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); + BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); BEAST_EXPECT(r[jss::result][jss::validated]); } { auto const r = env.rpc("account_channels", alice.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 1); - BEAST_EXPECT( - r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); + BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); BEAST_EXPECT(r[jss::result][jss::validated]); } { - auto const r = - env.rpc("account_channels", bob.human(), alice.human()); + auto const r = env.rpc("account_channels", bob.human(), alice.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 0); BEAST_EXPECT(r[jss::result][jss::validated]); } @@ -1092,8 +979,7 @@ struct PayChan_test : public beast::unit_test::suite env(create(alice, bob, channelFunds, settleDelay, pk)); env.close(); { - auto const r = - env.rpc("account_channels", alice.human(), bob.human()); + auto const r = env.rpc("account_channels", alice.human(), bob.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 2); BEAST_EXPECT(r[jss::result][jss::validated]); BEAST_EXPECT(chan1Str != chan2Str); @@ -1146,8 +1032,7 @@ struct PayChan_test : public beast::unit_test::suite test::jtx::Account const& src, std::optional limit = std::nullopt, Json::Value const& marker = Json::nullValue, - std::optional const& dst = - std::nullopt) { + std::optional const& dst = std::nullopt) { Json::Value jvc; jvc[jss::account] = src.human(); if (dst) @@ -1157,8 +1042,7 @@ struct PayChan_test : public beast::unit_test::suite if (marker) jvc[jss::marker] = marker; - return env.rpc( - "json", "account_channels", to_string(jvc))[jss::result]; + return env.rpc("json", "account_channels", to_string(jvc))[jss::result]; }; { @@ -1193,8 +1077,7 @@ struct PayChan_test : public beast::unit_test::suite auto const s = r[jss::channels].size(); for (int j = 0; j < s; ++j) { - auto const dstAcc = - c[j][jss::destination_account].asString(); + auto const dstAcc = c[j][jss::destination_account].asString(); BEAST_EXPECT(leftToFind.count(dstAcc)); leftToFind.erase(dstAcc); } @@ -1247,14 +1130,11 @@ struct PayChan_test : public beast::unit_test::suite Json::Value jvc; jvc[jss::account] = alice.human(); - return env.rpc( - "json", "account_channels", to_string(jvc))[jss::result]; + return env.rpc("json", "account_channels", to_string(jvc))[jss::result]; }(); BEAST_EXPECT(r.isMember(jss::channels)); BEAST_EXPECT(r[jss::channels].size() == 1); - BEAST_EXPECT( - r[jss::channels][0u][jss::destination_account].asString() == - bob.human()); + BEAST_EXPECT(r[jss::channels][0u][jss::destination_account].asString() == bob.human()); } void @@ -1283,13 +1163,9 @@ struct PayChan_test : public beast::unit_test::suite // test for all api versions forAllApiVersions([&, this](unsigned apiVersion) { - testcase( - "PayChan Channel_Auth RPC Api " + std::to_string(apiVersion)); + testcase("PayChan Channel_Auth RPC Api " + std::to_string(apiVersion)); args[jss::api_version] = apiVersion; - auto const rs = env.rpc( - "json", - "channel_authorize", - args.toStyledString())[jss::result]; + auto const rs = env.rpc("json", "channel_authorize", args.toStyledString())[jss::result]; auto const error = apiVersion < 2u ? "invalidParams" : "badKeyType"; BEAST_EXPECT(rs[jss::error] == error); }); @@ -1314,27 +1190,21 @@ struct PayChan_test : public beast::unit_test::suite env.close(); std::string chan1PkStr; { - auto const r = - env.rpc("account_channels", alice.human(), bob.human()); + auto const r = env.rpc("account_channels", alice.human(), bob.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 1); - BEAST_EXPECT( - r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); + BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); BEAST_EXPECT(r[jss::result][jss::validated]); - chan1PkStr = - r[jss::result][jss::channels][0u][jss::public_key].asString(); + chan1PkStr = r[jss::result][jss::channels][0u][jss::public_key].asString(); } { auto const r = env.rpc("account_channels", alice.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 1); - BEAST_EXPECT( - r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); + BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan1Str); BEAST_EXPECT(r[jss::result][jss::validated]); - chan1PkStr = - r[jss::result][jss::channels][0u][jss::public_key].asString(); + chan1PkStr = r[jss::result][jss::channels][0u][jss::public_key].asString(); } { - auto const r = - env.rpc("account_channels", bob.human(), alice.human()); + auto const r = env.rpc("account_channels", bob.human(), alice.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 0); BEAST_EXPECT(r[jss::result][jss::validated]); } @@ -1342,8 +1212,7 @@ struct PayChan_test : public beast::unit_test::suite env(create(alice, bob, channelFunds, settleDelay, pk)); env.close(); { - auto const r = - env.rpc("account_channels", alice.human(), bob.human()); + auto const r = env.rpc("account_channels", alice.human(), bob.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 2); BEAST_EXPECT(r[jss::result][jss::validated]); BEAST_EXPECT(chan1Str != chan2Str); @@ -1366,28 +1235,24 @@ struct PayChan_test : public beast::unit_test::suite { // Verify chan1 auth - auto const rs = - env.rpc("channel_authorize", "alice", chan1Str, "1000"); + auto const rs = env.rpc("channel_authorize", "alice", chan1Str, "1000"); auto const sig = rs[jss::result][jss::signature].asString(); BEAST_EXPECT(!sig.empty()); { - auto const rv = env.rpc( - "channel_verify", chan1PkStr, chan1Str, "1000", sig); + auto const rv = env.rpc("channel_verify", chan1PkStr, chan1Str, "1000", sig); BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool()); } { // use pk hex to verify auto const pkAsHex = sliceToHex(pk.slice()); - auto const rv = - env.rpc("channel_verify", pkAsHex, chan1Str, "1000", sig); + auto const rv = env.rpc("channel_verify", pkAsHex, chan1Str, "1000", sig); BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool()); } { // malformed amount auto const pkAsHex = sliceToHex(pk.slice()); - auto rv = - env.rpc("channel_verify", pkAsHex, chan1Str, "1000x", sig); + auto rv = env.rpc("channel_verify", pkAsHex, chan1Str, "1000x", sig); BEAST_EXPECT(rv[jss::error] == "channelAmtMalformed"); rv = env.rpc("channel_verify", pkAsHex, chan1Str, "1000 ", sig); BEAST_EXPECT(rv[jss::error] == "channelAmtMalformed"); @@ -1397,8 +1262,7 @@ struct PayChan_test : public beast::unit_test::suite BEAST_EXPECT(rv[jss::error] == "channelAmtMalformed"); rv = env.rpc("channel_verify", pkAsHex, chan1Str, " ", sig); BEAST_EXPECT(rv[jss::error] == "channelAmtMalformed"); - rv = env.rpc( - "channel_verify", pkAsHex, chan1Str, "1000 1000", sig); + rv = env.rpc("channel_verify", pkAsHex, chan1Str, "1000 1000", sig); BEAST_EXPECT(rv[jss::error] == "channelAmtMalformed"); rv = env.rpc("channel_verify", pkAsHex, chan1Str, "1,000", sig); BEAST_EXPECT(rv[jss::error] == "channelAmtMalformed"); @@ -1412,24 +1276,21 @@ struct PayChan_test : public beast::unit_test::suite auto const pkAsHex = sliceToHex(pk.slice()); auto chan1StrBad = chan1Str; chan1StrBad.pop_back(); - auto rv = env.rpc( - "channel_verify", pkAsHex, chan1StrBad, "1000", sig); + auto rv = env.rpc("channel_verify", pkAsHex, chan1StrBad, "1000", sig); BEAST_EXPECT(rv[jss::error] == "channelMalformed"); rv = env.rpc("channel_authorize", "alice", chan1StrBad, "1000"); BEAST_EXPECT(rv[jss::error] == "channelMalformed"); chan1StrBad = chan1Str; chan1StrBad.push_back('0'); - rv = env.rpc( - "channel_verify", pkAsHex, chan1StrBad, "1000", sig); + rv = env.rpc("channel_verify", pkAsHex, chan1StrBad, "1000", sig); BEAST_EXPECT(rv[jss::error] == "channelMalformed"); rv = env.rpc("channel_authorize", "alice", chan1StrBad, "1000"); BEAST_EXPECT(rv[jss::error] == "channelMalformed"); chan1StrBad = chan1Str; chan1StrBad.back() = 'x'; - rv = env.rpc( - "channel_verify", pkAsHex, chan1StrBad, "1000", sig); + rv = env.rpc("channel_verify", pkAsHex, chan1StrBad, "1000", sig); BEAST_EXPECT(rv[jss::error] == "channelMalformed"); rv = env.rpc("channel_authorize", "alice", chan1StrBad, "1000"); BEAST_EXPECT(rv[jss::error] == "channelMalformed"); @@ -1437,100 +1298,77 @@ struct PayChan_test : public beast::unit_test::suite { // give an ill formed base 58 public key auto illFormedPk = chan1PkStr.substr(0, chan1PkStr.size() - 1); - auto const rv = env.rpc( - "channel_verify", illFormedPk, chan1Str, "1000", sig); - BEAST_EXPECT( - !rv[jss::result][jss::signature_verified].asBool()); + auto const rv = env.rpc("channel_verify", illFormedPk, chan1Str, "1000", sig); + BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool()); } { // give an ill formed hex public key auto const pkAsHex = sliceToHex(pk.slice()); auto illFormedPk = pkAsHex.substr(0, chan1PkStr.size() - 1); - auto const rv = env.rpc( - "channel_verify", illFormedPk, chan1Str, "1000", sig); - BEAST_EXPECT( - !rv[jss::result][jss::signature_verified].asBool()); + auto const rv = env.rpc("channel_verify", illFormedPk, chan1Str, "1000", sig); + BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool()); } } { // Try to verify chan2 auth with chan1 key - auto const rs = - env.rpc("channel_authorize", "alice", chan2Str, "1000"); + auto const rs = env.rpc("channel_authorize", "alice", chan2Str, "1000"); auto const sig = rs[jss::result][jss::signature].asString(); BEAST_EXPECT(!sig.empty()); { - auto const rv = env.rpc( - "channel_verify", chan1PkStr, chan1Str, "1000", sig); - BEAST_EXPECT( - !rv[jss::result][jss::signature_verified].asBool()); + auto const rv = env.rpc("channel_verify", chan1PkStr, chan1Str, "1000", sig); + BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool()); } { // use pk hex to verify auto const pkAsHex = sliceToHex(pk.slice()); - auto const rv = - env.rpc("channel_verify", pkAsHex, chan1Str, "1000", sig); - BEAST_EXPECT( - !rv[jss::result][jss::signature_verified].asBool()); + auto const rv = env.rpc("channel_verify", pkAsHex, chan1Str, "1000", sig); + BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool()); } } { // Try to explicitly specify secp256k1 and Ed25519 keys: - auto const chan = - to_string(channel(charlie, alice, env.seq(charlie))); - env(create( - charlie, alice, channelFunds, settleDelay, charlie.pk())); + auto const chan = to_string(channel(charlie, alice, env.seq(charlie))); + env(create(charlie, alice, channelFunds, settleDelay, charlie.pk())); env.close(); std::string cpk; { - auto const r = - env.rpc("account_channels", charlie.human(), alice.human()); + auto const r = env.rpc("account_channels", charlie.human(), alice.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 1); - BEAST_EXPECT( - r[jss::result][jss::channels][0u][jss::channel_id] == chan); + BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan); BEAST_EXPECT(r[jss::result][jss::validated]); - cpk = r[jss::result][jss::channels][0u][jss::public_key] - .asString(); + cpk = r[jss::result][jss::channels][0u][jss::public_key].asString(); } // Try to authorize without specifying a key type, expect an error: - auto const rs = - env.rpc("channel_authorize", "charlie", chan, "1000"); + auto const rs = env.rpc("channel_authorize", "charlie", chan, "1000"); auto const sig = rs[jss::result][jss::signature].asString(); BEAST_EXPECT(!sig.empty()); { - auto const rv = - env.rpc("channel_verify", cpk, chan, "1000", sig); - BEAST_EXPECT( - !rv[jss::result][jss::signature_verified].asBool()); + auto const rv = env.rpc("channel_verify", cpk, chan, "1000", sig); + BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool()); } // Try to authorize using an unknown key type, except an error: - auto const rs1 = - env.rpc("channel_authorize", "charlie", "nyx", chan, "1000"); + auto const rs1 = env.rpc("channel_authorize", "charlie", "nyx", chan, "1000"); BEAST_EXPECT(rs1[jss::error] == "badKeyType"); // Try to authorize using secp256k1; the authorization _should_ // succeed but the verification should fail: - auto const rs2 = env.rpc( - "channel_authorize", "charlie", "secp256k1", chan, "1000"); + auto const rs2 = env.rpc("channel_authorize", "charlie", "secp256k1", chan, "1000"); auto const sig2 = rs2[jss::result][jss::signature].asString(); BEAST_EXPECT(!sig2.empty()); { - auto const rv = - env.rpc("channel_verify", cpk, chan, "1000", sig2); - BEAST_EXPECT( - !rv[jss::result][jss::signature_verified].asBool()); + auto const rv = env.rpc("channel_verify", cpk, chan, "1000", sig2); + BEAST_EXPECT(!rv[jss::result][jss::signature_verified].asBool()); } // Try to authorize using Ed25519; expect success: - auto const rs3 = env.rpc( - "channel_authorize", "charlie", "ed25519", chan, "1000"); + auto const rs3 = env.rpc("channel_authorize", "charlie", "ed25519", chan, "1000"); auto const sig3 = rs3[jss::result][jss::signature].asString(); BEAST_EXPECT(!sig3.empty()); { - auto const rv = - env.rpc("channel_verify", cpk, chan, "1000", sig3); + auto const rv = env.rpc("channel_verify", cpk, chan, "1000", sig3); BEAST_EXPECT(rv[jss::result][jss::signature_verified].asBool()); } } @@ -1549,10 +1387,7 @@ struct PayChan_test : public beast::unit_test::suite args[jss::amount] = "2000"; args[jss::key_type] = "secp256k1"; args[jss::passphrase] = "passphrase_can_be_anything"; - rs = env.rpc( - "json", - "channel_authorize", - args.toStyledString())[jss::result]; + rs = env.rpc("json", "channel_authorize", args.toStyledString())[jss::result]; BEAST_EXPECT(rs[jss::error] == "invalidParams"); } { @@ -1561,10 +1396,7 @@ struct PayChan_test : public beast::unit_test::suite args[jss::channel_id] = chan1Str; args[jss::key_type] = "secp256k1"; args[jss::passphrase] = "passphrase_can_be_anything"; - rs = env.rpc( - "json", - "channel_authorize", - args.toStyledString())[jss::result]; + rs = env.rpc("json", "channel_authorize", args.toStyledString())[jss::result]; BEAST_EXPECT(rs[jss::error] == "invalidParams"); } { @@ -1573,10 +1405,7 @@ struct PayChan_test : public beast::unit_test::suite args[jss::amount] = "2000"; args[jss::channel_id] = chan1Str; args[jss::passphrase] = "passphrase_can_be_anything"; - rs = env.rpc( - "json", - "channel_authorize", - args.toStyledString())[jss::result]; + rs = env.rpc("json", "channel_authorize", args.toStyledString())[jss::result]; BEAST_EXPECT(rs[jss::error] == "invalidParams"); } { @@ -1587,10 +1416,7 @@ struct PayChan_test : public beast::unit_test::suite args[jss::key_type] = "secp256k1"; args[jss::passphrase] = "passphrase_can_be_anything"; args[jss::seed] = "seed can be anything"; - rs = env.rpc( - "json", - "channel_authorize", - args.toStyledString())[jss::result]; + rs = env.rpc("json", "channel_authorize", args.toStyledString())[jss::result]; BEAST_EXPECT(rs[jss::error] == "invalidParams"); } { @@ -1600,10 +1426,7 @@ struct PayChan_test : public beast::unit_test::suite args[jss::channel_id] = chan1Str + "1"; args[jss::key_type] = "secp256k1"; args[jss::passphrase] = "passphrase_can_be_anything"; - rs = env.rpc( - "json", - "channel_authorize", - args.toStyledString())[jss::result]; + rs = env.rpc("json", "channel_authorize", args.toStyledString())[jss::result]; BEAST_EXPECT(rs[jss::error] == "channelMalformed"); } { @@ -1613,10 +1436,7 @@ struct PayChan_test : public beast::unit_test::suite args[jss::channel_id] = chan1Str; args[jss::key_type] = "secp256k1"; args[jss::passphrase] = "passphrase_can_be_anything"; - rs = env.rpc( - "json", - "channel_authorize", - args.toStyledString())[jss::result]; + rs = env.rpc("json", "channel_authorize", args.toStyledString())[jss::result]; BEAST_EXPECT(rs[jss::error] == "channelAmtMalformed"); } { @@ -1626,10 +1446,7 @@ struct PayChan_test : public beast::unit_test::suite args[jss::channel_id] = chan1Str; args[jss::key_type] = "secp256k1"; args[jss::passphrase] = "passphrase_can_be_anything"; - rs = env.rpc( - "json", - "channel_authorize", - args.toStyledString())[jss::result]; + rs = env.rpc("json", "channel_authorize", args.toStyledString())[jss::result]; BEAST_EXPECT(rs[jss::error] == "channelAmtMalformed"); } } @@ -1656,33 +1473,19 @@ struct PayChan_test : public beast::unit_test::suite { auto const chan = to_string(channel(alice, bob, env.seq(alice))); env(create(alice, bob, channelFunds, settleDelay, pk)); - auto const r = - env.rpc("account_channels", alice.human(), bob.human()); + auto const r = env.rpc("account_channels", alice.human(), bob.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 1); - BEAST_EXPECT( - r[jss::result][jss::channels][0u][jss::channel_id] == chan); - BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember( - jss::destination_tag)); + BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan); + BEAST_EXPECT(!r[jss::result][jss::channels][0u].isMember(jss::destination_tag)); } { std::uint32_t dstTag = 42; auto const chan = to_string(channel(alice, carol, env.seq(alice))); - env(create( - alice, - carol, - channelFunds, - settleDelay, - pk, - cancelAfter, - dstTag)); - auto const r = - env.rpc("account_channels", alice.human(), carol.human()); + env(create(alice, carol, channelFunds, settleDelay, pk, cancelAfter, dstTag)); + auto const r = env.rpc("account_channels", alice.human(), carol.human()); BEAST_EXPECT(r[jss::result][jss::channels].size() == 1); - BEAST_EXPECT( - r[jss::result][jss::channels][0u][jss::channel_id] == chan); - BEAST_EXPECT( - r[jss::result][jss::channels][0u][jss::destination_tag] == - dstTag); + BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::channel_id] == chan); + BEAST_EXPECT(r[jss::result][jss::channels][0u][jss::destination_tag] == dstTag); } } @@ -1718,13 +1521,7 @@ struct PayChan_test : public beast::unit_test::suite auto const authAmt = XRP(100); auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); - jv = claim( - bob, - chan, - authAmt.value(), - authAmt.value(), - Slice(sig), - alice.pk()); + jv = claim(bob, chan, authAmt.value(), authAmt.value(), Slice(sig), alice.pk()); jv["PublicKey"] = pkHex.substr(2, pkHex.size() - 2); env(jv, ter(temMALFORMED)); jv["PublicKey"] = pkHex.substr(0, pkHex.size() - 2); @@ -1769,16 +1566,12 @@ struct PayChan_test : public beast::unit_test::suite auto const settleDelay = 100s; auto const pk = alice.pk(); - auto inOwnerDir = [](ReadView const& view, - Account const& acc, - std::shared_ptr const& chan) -> bool { + auto inOwnerDir = [](ReadView const& view, Account const& acc, std::shared_ptr const& chan) -> bool { xrpl::Dir const ownerDir(view, keylet::ownerDir(acc.id())); - return std::find(ownerDir.begin(), ownerDir.end(), chan) != - ownerDir.end(); + return std::find(ownerDir.begin(), ownerDir.end(), chan) != ownerDir.end(); }; - auto ownerDirCount = [](ReadView const& view, - Account const& acc) -> std::size_t { + auto ownerDirCount = [](ReadView const& view, Account const& acc) -> std::size_t { xrpl::Dir const ownerDir(view, keylet::ownerDir(acc.id())); return std::distance(ownerDir.begin(), ownerDir.end()); }; @@ -1789,8 +1582,7 @@ struct PayChan_test : public beast::unit_test::suite env.fund(XRP(10000), alice, bob); env(create(alice, bob, XRP(1000), settleDelay, pk)); env.close(); - auto const [chan, chanSle] = - channelKeyAndSle(*env.current(), alice, bob); + auto const [chan, chanSle] = channelKeyAndSle(*env.current(), alice, bob); BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle)); BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1); BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle)); @@ -1812,8 +1604,7 @@ struct PayChan_test : public beast::unit_test::suite // create the channel before the amendment activates env(create(alice, bob, XRP(1000), settleDelay, pk)); env.close(); - auto const [chan, chanSle] = - channelKeyAndSle(*env.current(), alice, bob); + auto const [chan, chanSle] = channelKeyAndSle(*env.current(), alice, bob); BEAST_EXPECT(inOwnerDir(*env.current(), alice, chanSle)); BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1); BEAST_EXPECT(inOwnerDir(*env.current(), bob, chanSle)); @@ -1834,26 +1625,16 @@ struct PayChan_test : public beast::unit_test::suite testcase("Account Delete"); using namespace test::jtx; using namespace std::literals::chrono_literals; - auto rmAccount = [this]( - Env& env, - Account const& toRm, - Account const& dst, - TER expectedTer = tesSUCCESS) { + auto rmAccount = [this](Env& env, Account const& toRm, Account const& dst, TER expectedTer = tesSUCCESS) { // only allow an account to be deleted if the account's sequence // number is at least 256 less than the current ledger sequence - for (auto minRmSeq = env.seq(toRm) + 257; - env.current()->seq() < minRmSeq; - env.close()) + for (auto minRmSeq = env.seq(toRm) + 257; env.current()->seq() < minRmSeq; env.close()) { } - env(acctdelete(toRm, dst), - fee(drops(env.current()->fees().increment)), - ter(expectedTer)); + env(acctdelete(toRm, dst), fee(drops(env.current()->fees().increment)), ter(expectedTer)); env.close(); - this->BEAST_EXPECT( - isTesSuccess(expectedTer) == - !env.closed()->exists(keylet::account(toRm.id()))); + this->BEAST_EXPECT(isTesSuccess(expectedTer) == !env.closed()->exists(keylet::account(toRm.id()))); }; auto const alice = Account("alice"); @@ -1900,8 +1681,7 @@ struct PayChan_test : public beast::unit_test::suite env(fund(alice, chan, XRP(1000))); env.close(); BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1000) - feeDrops); - BEAST_EXPECT( - channelAmount(*env.current(), chan) == chanAmt + XRP(1000)); + BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt + XRP(1000)); chanAmt = chanAmt + XRP(1000); { @@ -1946,8 +1726,7 @@ struct PayChan_test : public beast::unit_test::suite auto const settleDelay = 100s; auto const chan = channel(alice, bob, aliceTicketSeq); - env(create(alice, bob, XRP(1000), settleDelay, pk), - ticket::use(aliceTicketSeq++)); + env(create(alice, bob, XRP(1000), settleDelay, pk), ticket::use(aliceTicketSeq++)); env.require(tickets(alice, env.seq(alice) - aliceTicketSeq)); BEAST_EXPECT(env.seq(alice) == aliceSeq); @@ -1978,8 +1757,7 @@ struct PayChan_test : public beast::unit_test::suite auto const reqBal = chanBal + delta; auto const authAmt = reqBal + XRP(100); assert(reqBal <= chanAmt); - env(claim(alice, chan, reqBal, authAmt), - ticket::use(aliceTicketSeq++)); + env(claim(alice, chan, reqBal, authAmt), ticket::use(aliceTicketSeq++)); env.require(tickets(alice, env.seq(alice) - aliceTicketSeq)); BEAST_EXPECT(env.seq(alice) == aliceSeq); @@ -1996,10 +1774,8 @@ struct PayChan_test : public beast::unit_test::suite auto const reqBal = chanBal + delta; auto const authAmt = reqBal + XRP(100); assert(reqBal <= chanAmt); - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); - env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()), - ticket::use(bobTicketSeq++)); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); + env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()), ticket::use(bobTicketSeq++)); env.require(tickets(bob, env.seq(bob) - bobTicketSeq)); BEAST_EXPECT(env.seq(bob) == bobSeq); @@ -2032,8 +1808,7 @@ struct PayChan_test : public beast::unit_test::suite assert(reqAmt <= chanAmt); // Note that since claim() returns a tem (neither tec nor tes), // the ticket is not consumed. So we don't increment bobTicket. - auto const sig = - signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); + auto const sig = signClaimAuth(alice.pk(), alice.sk(), chan, authAmt); env(claim(bob, chan, reqAmt, authAmt, Slice(sig), alice.pk()), ticket::use(bobTicketSeq), ter(temBAD_AMOUNT)); @@ -2047,9 +1822,7 @@ struct PayChan_test : public beast::unit_test::suite } // Dst tries to fund the channel - env(fund(bob, chan, XRP(1000)), - ticket::use(bobTicketSeq++), - ter(tecNO_PERMISSION)); + env(fund(bob, chan, XRP(1000)), ticket::use(bobTicketSeq++), ter(tecNO_PERMISSION)); env.require(tickets(bob, env.seq(bob) - bobTicketSeq)); BEAST_EXPECT(env.seq(bob) == bobSeq); @@ -2061,9 +1834,7 @@ struct PayChan_test : public beast::unit_test::suite // Dst closes channel auto const preAlice = env.balance(alice); auto const preBob = env.balance(bob); - env(claim(bob, chan), - txflags(tfClose), - ticket::use(bobTicketSeq++)); + env(claim(bob, chan), txflags(tfClose), ticket::use(bobTicketSeq++)); env.require(tickets(bob, env.seq(bob) - bobTicketSeq)); BEAST_EXPECT(env.seq(bob) == bobSeq); diff --git a/src/test/app/PayStrand_test.cpp b/src/test/app/PayStrand_test.cpp index 8e0ff337b4..2f3b36eae5 100644 --- a/src/test/app/PayStrand_test.cpp +++ b/src/test/app/PayStrand_test.cpp @@ -53,12 +53,7 @@ trustFlag(TrustFlag f, bool useHigh) } bool -getTrustFlag( - jtx::Env const& env, - jtx::Account const& src, - jtx::Account const& dst, - Currency const& cur, - TrustFlag flag) +getTrustFlag(jtx::Env const& env, jtx::Account const& src, jtx::Account const& dst, Currency const& cur, TrustFlag flag) { if (auto sle = env.le(keylet::line(src, dst, cur))) { @@ -124,8 +119,7 @@ equal(Strand const& strand, Args&&... args) STPathElement ape(AccountID const& a) { - return STPathElement( - STPathElement::typeAccount, a, xrpCurrency(), xrpAccount()); + return STPathElement(STPathElement::typeAccount, a, xrpCurrency(), xrpAccount()); }; // Issue path element @@ -133,18 +127,14 @@ STPathElement ipe(Issue const& iss) { return STPathElement( - STPathElement::typeCurrency | STPathElement::typeIssuer, - xrpAccount(), - iss.currency, - iss.account); + STPathElement::typeCurrency | STPathElement::typeIssuer, xrpAccount(), iss.currency, iss.account); }; // Issuer path element STPathElement iape(AccountID const& account) { - return STPathElement( - STPathElement::typeIssuer, xrpAccount(), xrpCurrency(), account); + return STPathElement(STPathElement::typeIssuer, xrpAccount(), xrpCurrency(), account); }; class ElementComboIter @@ -169,9 +159,7 @@ class ElementComboIter }; std::uint16_t state_ = 0; - static_assert( - safe_cast(SB::last) <= sizeof(decltype(state_)) * 8, - ""); + static_assert(safe_cast(SB::last) <= sizeof(decltype(state_)) * 8, ""); STPathElement const* prev_ = nullptr; // disallow iss and cur to be specified with acc is specified (simplifies // some tests) @@ -211,17 +199,11 @@ public: bool valid() const { - return (allowCompound_ || - !(has(SB::acc) && hasAny({SB::cur, SB::iss}))) && + return (allowCompound_ || !(has(SB::acc) && hasAny({SB::cur, SB::iss}))) && (!hasAny({SB::prevAcc, SB::prevCur, SB::prevIss}) || prev_) && - (!hasAny( - {SB::rootAcc, SB::sameAccIss, SB::existingAcc, SB::prevAcc}) || - has(SB::acc)) && - (!hasAny( - {SB::rootIss, SB::sameAccIss, SB::existingIss, SB::prevIss}) || - has(SB::iss)) && - (!hasAny({SB::xrp, SB::existingCur, SB::prevCur}) || - has(SB::cur)) && + (!hasAny({SB::rootAcc, SB::sameAccIss, SB::existingAcc, SB::prevAcc}) || has(SB::acc)) && + (!hasAny({SB::rootIss, SB::sameAccIss, SB::existingIss, SB::prevIss}) || has(SB::iss)) && + (!hasAny({SB::xrp, SB::existingCur, SB::prevCur}) || has(SB::cur)) && // These will be duplicates (count({SB::xrp, SB::existingCur, SB::prevCur}) <= 1) && (count({SB::rootAcc, SB::existingAcc, SB::prevAcc}) <= 1) && @@ -240,11 +222,7 @@ public: return !has(SB::last); } - template < - class Col, - class AccFactory, - class IssFactory, - class CurrencyFactory> + template void emplace_into( Col& col, @@ -340,8 +318,7 @@ struct ExistingElementPool ExistingElementPool& p_; ResetState state_; - explicit StateGuard(ExistingElementPool& p) - : p_{p}, state_{p.getResetState()} + explicit StateGuard(ExistingElementPool& p) : p_{p}, state_{p.getResetState()} { } ~StateGuard() @@ -356,11 +333,7 @@ struct ExistingElementPool // currency/account; the offer owner is either the specified // account or the issuer of the "taker gets" account void - setupEnv( - jtx::Env& env, - size_t numAct, - size_t numCur, - std::optional const& offererIndex) + setupEnv(jtx::Env& env, size_t numAct, size_t numCur, std::optional const& offererIndex) { using namespace jtx; @@ -398,8 +371,7 @@ struct ExistingElementPool env.fund(XRP(100000), a); // Every account trusts every other account with every currency - for (auto ai1 = accounts.begin(), aie = accounts.end(); ai1 != aie; - ++ai1) + for (auto ai1 = accounts.begin(), aie = accounts.end(); ai1 != aie; ++ai1) { for (auto ai2 = accounts.begin(); ai2 != aie; ++ai2) { @@ -429,20 +401,17 @@ struct ExistingElementPool ious.emplace_back(a[cn]); // create offers from every currency to every other currency - for (auto takerPays = ious.begin(), ie = ious.end(); takerPays != ie; - ++takerPays) + for (auto takerPays = ious.begin(), ie = ious.end(); takerPays != ie; ++takerPays) { for (auto takerGets = ious.begin(); takerGets != ie; ++takerGets) { if (takerPays == takerGets) continue; - auto const owner = - offererIndex ? accounts[*offererIndex] : takerGets->account; + auto const owner = offererIndex ? accounts[*offererIndex] : takerGets->account; if (owner.id() != takerGets->account.id()) env(pay(takerGets->account, owner, (*takerGets)(1000))); - env(offer(owner, (*takerPays)(1000), (*takerGets)(1000)), - txflags(tfPassive)); + env(offer(owner, (*takerPays)(1000), (*takerGets)(1000)), txflags(tfPassive)); } env.close(); } @@ -450,8 +419,7 @@ struct ExistingElementPool // create offers to/from xrp to every other ious for (auto const& iou : ious) { - auto const owner = - offererIndex ? accounts[*offererIndex] : iou.account; + auto const owner = offererIndex ? accounts[*offererIndex] : iou.account; env(offer(owner, iou(1000), XRP(1000)), txflags(tfPassive)); env(offer(owner, XRP(1000), iou(1000)), txflags(tfPassive)); env.close(); @@ -497,8 +465,7 @@ struct ExistingElementPool return (*sle)[sfBalance]; }; std::uint64_t totalXRP[2]{}; - for (auto ai1 = accounts.begin(), aie = accounts.end(); ai1 != aie; - ++ai1) + for (auto ai1 = accounts.begin(), aie = accounts.end(); ai1 != aie; ++ai1) { { // XRP balance @@ -556,8 +523,7 @@ struct ExistingElementPool auto issF = [&] { return this->getAvailAccount(); }; auto currencyF = [&] { return this->getAvailCurrency(); }; - STPathElement const* prevOuter = - prefix.empty() ? nullptr : &prefix.back(); + STPathElement const* prevOuter = prefix.empty() ? nullptr : &prefix.back(); ElementComboIter outer(prevOuter); std::vector outerResult; @@ -569,28 +535,14 @@ struct ExistingElementPool { StateGuard og{*this}; outerResult = prefix; - outer.emplace_into( - outerResult, - accF, - issF, - currencyF, - existingAcc, - existingCur, - existingIss); + outer.emplace_into(outerResult, accF, issF, currencyF, existingAcc, existingCur, existingIss); STPathElement const* prevInner = &outerResult.back(); ElementComboIter inner(prevInner); while (inner.next()) { StateGuard ig{*this}; result = outerResult; - inner.emplace_into( - result, - accF, - issF, - currencyF, - existingAcc, - existingCur, - existingIss); + inner.emplace_into(result, accF, issF, currencyF, existingAcc, existingCur, existingIss); result.insert(result.end(), suffix.begin(), suffix.end()); f(sendMax, deliver, result); } @@ -646,8 +598,7 @@ struct PayStrand_test : public beast::unit_test::suite env.app().logs().journal("Flow")); BEAST_EXPECT(ter == expTer); if (sizeof...(expSteps) != 0) - BEAST_EXPECT(equal( - strand, std::forward(expSteps)...)); + BEAST_EXPECT(equal(strand, std::forward(expSteps)...)); }; { @@ -658,8 +609,7 @@ struct PayStrand_test : public beast::unit_test::suite env(pay(gw, alice, EUR(100))); { - STPath const path = - STPath({ipe(bob["USD"]), cpe(EUR.currency)}); + STPath const path = STPath({ipe(bob["USD"]), cpe(EUR.currency)}); auto [ter, _] = toStrand( *env.current(), alice, @@ -709,14 +659,7 @@ struct PayStrand_test : public beast::unit_test::suite env(pay(gw, carol, USD(100))); // Insert implied account - test( - env, - USD, - std::nullopt, - STPath(), - tesSUCCESS, - D{alice, gw, usdC}, - D{gw, bob, usdC}); + test(env, USD, std::nullopt, STPath(), tesSUCCESS, D{alice, gw, usdC}, D{gw, bob, usdC}); env.trust(EUR(1000), alice, bob); // Insert implied offer @@ -769,11 +712,7 @@ struct PayStrand_test : public beast::unit_test::suite env, xrpIssue(), USD.issue(), - STPath({STPathElement{ - STPathElement::typeCurrency, - xrpAccount(), - xrpCurrency(), - xrpAccount()}}), + STPath({STPathElement{STPathElement::typeCurrency, xrpAccount(), xrpCurrency(), xrpAccount()}}), tesSUCCESS, D{alice, gw, usdC}, B{USD, XRP, std::nullopt}, @@ -851,39 +790,23 @@ struct PayStrand_test : public beast::unit_test::suite } // Create an offer with the same in/out issue - test( - env, - EUR, - USD.issue(), - STPath({ipe(USD), ipe(EUR)}), - temBAD_PATH); + test(env, EUR, USD.issue(), STPath({ipe(USD), ipe(EUR)}), temBAD_PATH); // Path element with type zero test( env, USD, std::nullopt, - STPath({STPathElement( - 0, xrpAccount(), xrpCurrency(), xrpAccount())}), + STPath({STPathElement(0, xrpAccount(), xrpCurrency(), xrpAccount())}), temBAD_PATH); // The same account can't appear more than once on a path // `gw` will be used from alice->carol and implied between carol // and bob - test( - env, - USD, - std::nullopt, - STPath({ape(gw), ape(carol)}), - temBAD_PATH_LOOP); + test(env, USD, std::nullopt, STPath({ape(gw), ape(carol)}), temBAD_PATH_LOOP); // The same offer can't appear more than once on a path - test( - env, - EUR, - USD.issue(), - STPath({ipe(EUR), ipe(USD), ipe(EUR)}), - temBAD_PATH_LOOP); + test(env, EUR, USD.issue(), STPath({ipe(EUR), ipe(USD), ipe(EUR)}), temBAD_PATH_LOOP); } { @@ -1013,11 +936,7 @@ struct PayStrand_test : public beast::unit_test::suite std::nullopt, env.app().logs().journal("Flow")); BEAST_EXPECT(ter == tesSUCCESS); - BEAST_EXPECT(equal( - strand, - D{alice, gw, usdC}, - B{USD.issue(), xrpIssue(), std::nullopt}, - XRPS{bob})); + BEAST_EXPECT(equal(strand, D{alice, gw, usdC}, B{USD.issue(), xrpIssue(), std::nullopt}, XRPS{bob})); } } @@ -1046,8 +965,7 @@ struct PayStrand_test : public beast::unit_test::suite env(offer(bob, XRP(100), bob["USD"](100)), txflags(tfPassive)); env(offer(gw, XRP(100), USD(100)), txflags(tfPassive)); - env(offer(bob, bob["USD"](100), bob["EUR"](100)), - txflags(tfPassive)); + env(offer(bob, bob["USD"](100), bob["EUR"](100)), txflags(tfPassive)); env(offer(gw, USD(100), EUR(100)), txflags(tfPassive)); Path const p = [&] { @@ -1078,10 +996,7 @@ struct PayStrand_test : public beast::unit_test::suite env(offer(bob, USD(100), XRP(100)), txflags(tfPassive)); // payment path: XRP -> XRP/USD -> USD/XRP - env(pay(alice, carol, XRP(100)), - path(~USD, ~XRP), - txflags(tfNoRippleDirect), - ter(temBAD_SEND_XRP_PATHS)); + env(pay(alice, carol, XRP(100)), path(~USD, ~XRP), txflags(tfNoRippleDirect), ter(temBAD_SEND_XRP_PATHS)); } { @@ -1189,54 +1104,22 @@ struct PayStrand_test : public beast::unit_test::suite PaymentSandbox sb{env.current().get(), tapNONE}; { auto const r = ::xrpl::path::RippleCalc::rippleCalculate( - sb, - sendMax, - deliver, - dstAcc, - noAccount(), - pathSet, - std::nullopt, - env.app().logs(), - &inputs); + sb, sendMax, deliver, dstAcc, noAccount(), pathSet, std::nullopt, env.app().logs(), &inputs); BEAST_EXPECT(r.result() == temBAD_PATH); } { auto const r = ::xrpl::path::RippleCalc::rippleCalculate( - sb, - sendMax, - deliver, - noAccount(), - srcAcc, - pathSet, - std::nullopt, - env.app().logs(), - &inputs); + sb, sendMax, deliver, noAccount(), srcAcc, pathSet, std::nullopt, env.app().logs(), &inputs); BEAST_EXPECT(r.result() == temBAD_PATH); } { auto const r = ::xrpl::path::RippleCalc::rippleCalculate( - sb, - noAccountAmount, - deliver, - dstAcc, - srcAcc, - pathSet, - std::nullopt, - env.app().logs(), - &inputs); + sb, noAccountAmount, deliver, dstAcc, srcAcc, pathSet, std::nullopt, env.app().logs(), &inputs); BEAST_EXPECT(r.result() == temBAD_PATH); } { auto const r = ::xrpl::path::RippleCalc::rippleCalculate( - sb, - sendMax, - noAccountAmount, - dstAcc, - srcAcc, - pathSet, - std::nullopt, - env.app().logs(), - &inputs); + sb, sendMax, noAccountAmount, dstAcc, srcAcc, pathSet, std::nullopt, env.app().logs(), &inputs); BEAST_EXPECT(r.result() == temBAD_PATH); } } diff --git a/src/test/app/PermissionedDEX_test.cpp b/src/test/app/PermissionedDEX_test.cpp index c29b5344e2..7a55866780 100644 --- a/src/test/app/PermissionedDEX_test.cpp +++ b/src/test/app/PermissionedDEX_test.cpp @@ -53,8 +53,7 @@ class PermissionedDEX_test : public beast::unit_test::suite { auto offerInDir = [&](uint256 const& directory, uint64_t const pageIndex, - std::optional domain = - std::nullopt) -> bool { + std::optional domain = std::nullopt) -> bool { auto const page = env.le(keylet::page(directory, pageIndex)); if (!page) return false; @@ -85,10 +84,7 @@ class PermissionedDEX_test : public beast::unit_test::suite return false; if (!domainOffer && sle->isFieldPresent(sfDomainID)) return false; - if (!offerInDir( - sle->getFieldH256(sfBookDirectory), - sle->getFieldU64(sfBookNode), - (*sle)[~sfDomainID])) + if (!offerInDir(sle->getFieldH256(sfBookDirectory), sle->getFieldU64(sfBookNode), (*sle)[~sfDomainID])) return false; if (sle->isFlag(lsfHybrid)) @@ -100,8 +96,7 @@ class PermissionedDEX_test : public beast::unit_test::suite if (sle->getFieldArray(sfAdditionalBooks).size() != 1) return false; - auto const& additionalBookDirs = - sle->getFieldArray(sfAdditionalBooks); + auto const& additionalBookDirs = sle->getFieldArray(sfAdditionalBooks); for (auto const& bookDir : additionalBookDirs) { @@ -124,21 +119,13 @@ class PermissionedDEX_test : public beast::unit_test::suite } uint256 - getBookDirKey( - Book const& book, - STAmount const& takerPays, - STAmount const& takerGets) + getBookDirKey(Book const& book, STAmount const& takerPays, STAmount const& takerGets) { - return keylet::quality( - keylet::book(book), getRate(takerGets, takerPays)) - .key; + return keylet::quality(keylet::book(book), getRate(takerGets, takerPays)).key; } std::optional - getDefaultOfferDirKey( - Env const& env, - Account const& account, - std::uint32_t offerSeq) + getDefaultOfferDirKey(Env const& env, Account const& account, std::uint32_t offerSeq) { if (auto const sle = env.le(keylet::offer(account.id(), offerSeq))) return Keylet(ltDIR_NODE, (*sle)[sfBookDirectory]).key; @@ -174,12 +161,9 @@ class PermissionedDEX_test : public beast::unit_test::suite // test preflight { Env env(*this, features - featurePermissionedDEX); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); - env(offer(bob, XRP(10), USD(10)), - domain(domainID), - ter(temDISABLED)); + env(offer(bob, XRP(10), USD(10)), domain(domainID), ter(temDISABLED)); env.close(); env.enableFeature(featurePermissionedDEX); @@ -191,8 +175,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // preclaim - someone outside of the domain cannot create domain offer { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); // create devin account who is not part of the domain Account devin("devin"); @@ -203,9 +186,7 @@ class PermissionedDEX_test : public beast::unit_test::suite env(pay(gw, devin, USD(100))); env.close(); - env(offer(devin, XRP(10), USD(10)), - domain(domainID), - ter(tecNO_PERMISSION)); + env(offer(devin, XRP(10), USD(10)), domain(domainID), ter(tecNO_PERMISSION)); env.close(); // domain owner also issues a credential for devin @@ -213,9 +194,7 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); // devin still cannot create offer since he didn't accept credential - env(offer(devin, XRP(10), USD(10)), - domain(domainID), - ter(tecNO_PERMISSION)); + env(offer(devin, XRP(10), USD(10)), domain(domainID), ter(tecNO_PERMISSION)); env.close(); env(credentials::accept(devin, domainOwner, credType)); @@ -228,8 +207,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // preclaim - someone with expired cred cannot create domain offer { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); // create devin account who is not part of the domain Account devin("devin"); @@ -241,10 +219,7 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); auto jv = credentials::create(devin, domainOwner, credType); - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count(); + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count(); jv[sfExpiration.jsonName] = t + 20; env(jv); @@ -259,24 +234,19 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(std::chrono::seconds(20)); // devin cannot create offer with expired cred - env(offer(devin, XRP(10), USD(10)), - domain(domainID), - ter(tecNO_PERMISSION)); + env(offer(devin, XRP(10), USD(10)), domain(domainID), ter(tecNO_PERMISSION)); env.close(); } // preclaim - cannot create an offer in a non existent domain { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); uint256 const badDomain{ "F10D0CC9A0F9A3CBF585B80BE09A186483668FDBDD39AA7E3370F3649CE134" "E5"}; - env(offer(bob, XRP(10), USD(10)), - domain(badDomain), - ter(tecNO_PERMISSION)); + env(offer(bob, XRP(10), USD(10)), domain(badDomain), ter(tecNO_PERMISSION)); env.close(); } @@ -284,60 +254,51 @@ class PermissionedDEX_test : public beast::unit_test::suite // domain { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); - env(credentials::deleteCred( - domainOwner, gw, domainOwner, credType)); + env(credentials::deleteCred(domainOwner, gw, domainOwner, credType)); env.close(); auto const bobOfferSeq{env.seq(bob)}; env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); } // apply - offer can be created even if takerpays issuer is not in // domain { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); - env(credentials::deleteCred( - domainOwner, gw, domainOwner, credType)); + env(credentials::deleteCred(domainOwner, gw, domainOwner, credType)); env.close(); auto const bobOfferSeq{env.seq(bob)}; env(offer(bob, USD(10), XRP(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, USD(10), XRP(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, USD(10), XRP(10), 0, true)); } // apply - two domain offers cross with each other { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const bobOfferSeq{env.seq(bob)}; env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); BEAST_EXPECT(ownerCount(env, bob) == 3); // a non domain offer cannot cross with domain offer env(offer(carol, USD(10), XRP(10))); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); auto const aliceOfferSeq{env.seq(alice)}; env(offer(alice, USD(10), XRP(10)), domain(domainID)); @@ -351,8 +312,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // apply - create lots of domain offers { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); std::vector offerSeqs; offerSeqs.reserve(100); @@ -364,8 +324,7 @@ class PermissionedDEX_test : public beast::unit_test::suite env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); } for (auto const offerSeq : offerSeqs) @@ -385,14 +344,9 @@ class PermissionedDEX_test : public beast::unit_test::suite // test preflight - without enabling featurePermissionedDEX amendment { Env env(*this, features - featurePermissionedDEX); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); - env(pay(bob, alice, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID), - ter(temDISABLED)); + env(pay(bob, alice, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID), ter(temDISABLED)); env.close(); env.enableFeature(featurePermissionedDEX); @@ -401,35 +355,26 @@ class PermissionedDEX_test : public beast::unit_test::suite env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - env(pay(bob, alice, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(bob, alice, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); } // preclaim - cannot send payment with non existent domain { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); uint256 const badDomain{ "F10D0CC9A0F9A3CBF585B80BE09A186483668FDBDD39AA7E3370F3649CE134" "E5"}; - env(pay(bob, alice, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(badDomain), - ter(tecNO_PERMISSION)); + env(pay(bob, alice, USD(10)), path(~USD), sendmax(XRP(10)), domain(badDomain), ter(tecNO_PERMISSION)); env.close(); } // preclaim - payment with non-domain destination fails { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); @@ -444,11 +389,7 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); // devin is not part of domain - env(pay(alice, devin, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID), - ter(tecNO_PERMISSION)); + env(pay(alice, devin, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID), ter(tecNO_PERMISSION)); env.close(); // domain owner also issues a credential for devin @@ -456,29 +397,21 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); // devin has not yet accepted cred - env(pay(alice, devin, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID), - ter(tecNO_PERMISSION)); + env(pay(alice, devin, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID), ter(tecNO_PERMISSION)); env.close(); env(credentials::accept(devin, domainOwner, credType)); env.close(); // devin can now receive payment after he is in domain - env(pay(alice, devin, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(alice, devin, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); } // preclaim - non-domain sender cannot send payment { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); @@ -493,11 +426,7 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); // devin tries to send domain payment - env(pay(devin, alice, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID), - ter(tecNO_PERMISSION)); + env(pay(devin, alice, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID), ter(tecNO_PERMISSION)); env.close(); // domain owner also issues a credential for devin @@ -505,48 +434,34 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); // devin has not yet accepted cred - env(pay(devin, alice, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID), - ter(tecNO_PERMISSION)); + env(pay(devin, alice, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID), ter(tecNO_PERMISSION)); env.close(); env(credentials::accept(devin, domainOwner, credType)); env.close(); // devin can now send payment after he is in domain - env(pay(devin, alice, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(devin, alice, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); } // apply - domain owner can always send and receive domain payment { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); // domain owner can always be destination - env(pay(alice, domainOwner, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(alice, domainOwner, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); // domain owner can send - env(pay(domainOwner, alice, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(domainOwner, alice, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); } } @@ -559,27 +474,20 @@ class PermissionedDEX_test : public beast::unit_test::suite // test domain cross currency payment consuming one offer { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); // create a regular offer without domain auto const regularOfferSeq{env.seq(bob)}; env(offer(bob, XRP(10), USD(10))); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, regularOfferSeq, XRP(10), USD(10))); + BEAST_EXPECT(checkOffer(env, bob, regularOfferSeq, XRP(10), USD(10))); - auto const regularDirKey = - getDefaultOfferDirKey(env, bob, regularOfferSeq); + auto const regularDirKey = getDefaultOfferDirKey(env, bob, regularOfferSeq); BEAST_EXPECT(regularDirKey); BEAST_EXPECT(checkDirectorySize(env, *regularDirKey, 1)); // a domain payment cannot consume regular offers - env(pay(alice, carol, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); // create a domain offer @@ -587,24 +495,18 @@ class PermissionedDEX_test : public beast::unit_test::suite env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, domainOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, domainOfferSeq, XRP(10), USD(10), 0, true)); - auto const domainDirKey = - getDefaultOfferDirKey(env, bob, domainOfferSeq); + auto const domainDirKey = getDefaultOfferDirKey(env, bob, domainOfferSeq); BEAST_EXPECT(domainDirKey); BEAST_EXPECT(checkDirectorySize(env, *domainDirKey, 1)); // cross-currency permissioned payment consumed // domain offer instead of regular offer - env(pay(alice, carol, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(alice, carol, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); BEAST_EXPECT(!offerExists(env, bob, domainOfferSeq)); - BEAST_EXPECT( - checkOffer(env, bob, regularOfferSeq, XRP(10), USD(10))); + BEAST_EXPECT(checkOffer(env, bob, regularOfferSeq, XRP(10), USD(10))); // domain directory is empty BEAST_EXPECT(checkDirectorySize(env, *domainDirKey, 0)); @@ -614,8 +516,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // test domain payment consuming two offers in the path { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const EUR = gw["EUR"]; env.trust(EUR(1000), alice); @@ -632,75 +533,53 @@ class PermissionedDEX_test : public beast::unit_test::suite env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, true)); // payment fail because there isn't eur offer - env(pay(alice, carol, EUR(10)), - path(~USD, ~EUR), - sendmax(XRP(10)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, EUR(10)), path(~USD, ~EUR), sendmax(XRP(10)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, true)); // bob creates a regular USD/EUR offer auto const regularOfferSeq{env.seq(bob)}; env(offer(bob, USD(10), EUR(10))); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, regularOfferSeq, USD(10), EUR(10))); + BEAST_EXPECT(checkOffer(env, bob, regularOfferSeq, USD(10), EUR(10))); // alice tries to pay again, but still fails because the regular // offer cannot be consumed - env(pay(alice, carol, EUR(10)), - path(~USD, ~EUR), - sendmax(XRP(10)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, EUR(10)), path(~USD, ~EUR), sendmax(XRP(10)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); // bob creates a domain USD/EUR offer auto const eurOfferSeq{env.seq(bob)}; env(offer(bob, USD(10), EUR(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, eurOfferSeq, USD(10), EUR(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, eurOfferSeq, USD(10), EUR(10), 0, true)); // alice successfully consume two domain offers: xrp/usd and usd/eur - env(pay(alice, carol, EUR(5)), - sendmax(XRP(5)), - domain(domainID), - path(~USD, ~EUR)); + env(pay(alice, carol, EUR(5)), sendmax(XRP(5)), domain(domainID), path(~USD, ~EUR)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, usdOfferSeq, XRP(5), USD(5), 0, true)); - BEAST_EXPECT( - checkOffer(env, bob, eurOfferSeq, USD(5), EUR(5), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, usdOfferSeq, XRP(5), USD(5), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, eurOfferSeq, USD(5), EUR(5), 0, true)); // alice successfully consume two domain offers and deletes them // we compute path this time using `paths` - env(pay(alice, carol, EUR(5)), - sendmax(XRP(5)), - domain(domainID), - paths(XRP)); + env(pay(alice, carol, EUR(5)), sendmax(XRP(5)), domain(domainID), paths(XRP)); env.close(); BEAST_EXPECT(!offerExists(env, bob, usdOfferSeq)); BEAST_EXPECT(!offerExists(env, bob, eurOfferSeq)); // regular offer is not consumed - BEAST_EXPECT( - checkOffer(env, bob, regularOfferSeq, USD(10), EUR(10))); + BEAST_EXPECT(checkOffer(env, bob, regularOfferSeq, USD(10), EUR(10))); } // domain payment cannot consume offer from another domain { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); // Fund devin and create USD trustline Account badDomainOwner("badDomainOwner"); @@ -728,25 +607,17 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); // domain payment can't consume an offer from another domain - env(pay(alice, carol, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); // bob creates an offer under the right domain auto const bobOfferSeq{env.seq(bob)}; env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); // domain payment now consumes from the right domain - env(pay(alice, carol, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(alice, carol, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); BEAST_EXPECT(!offerExists(env, bob, bobOfferSeq)); @@ -757,8 +628,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // offer { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); @@ -783,8 +653,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // offer becomes unfunded when offer owner's cred expires { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); // create devin account who is not part of the domain Account devin("devin"); @@ -796,10 +665,7 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); auto jv = credentials::create(devin, domainOwner, credType); - uint32_t const t = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count(); + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count(); jv[sfExpiration.jsonName] = t + 20; env(jv); @@ -812,61 +678,41 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); // devin's offer can still be consumed while his cred isn't expired - env(pay(alice, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID)); + env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, devin, offerSeq, XRP(5), USD(5), 0, true)); + BEAST_EXPECT(checkOffer(env, devin, offerSeq, XRP(5), USD(5), 0, true)); // advance time env.close(std::chrono::seconds(20)); // devin's offer is unfunded now due to expired cred - env(pay(alice, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); - BEAST_EXPECT( - checkOffer(env, devin, offerSeq, XRP(5), USD(5), 0, true)); + BEAST_EXPECT(checkOffer(env, devin, offerSeq, XRP(5), USD(5), 0, true)); } // offer becomes unfunded when offer owner's cred is removed { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const offerSeq{env.seq(bob)}; env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); // bob's offer can still be consumed while his cred exists - env(pay(alice, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID)); + env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, offerSeq, XRP(5), USD(5), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, offerSeq, XRP(5), USD(5), 0, true)); // remove bob's cred - env(credentials::deleteCred( - domainOwner, bob, domainOwner, credType)); + env(credentials::deleteCred(domainOwner, bob, domainOwner, credType)); env.close(); // bob's offer is unfunded now due to expired cred - env(pay(alice, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, offerSeq, XRP(5), USD(5), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, offerSeq, XRP(5), USD(5), 0, true)); } } @@ -879,8 +725,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // payment. If the domain wishes to control who is allowed to ripple // through, they should set the rippling individually Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const EURA = alice["EUR"]; auto const EURB = bob["EUR"]; @@ -904,10 +749,7 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); // payment no longer works because carol has no ripple on bob - env(pay(alice, carol, EURB(5)), - paths(EURA), - domain(domainID), - ter(tecPATH_DRY)); + env(pay(alice, carol, EURB(5)), paths(EURA), domain(domainID), ter(tecPATH_DRY)); env.close(); env.require(balance(bob, EURA(10)), balance(carol, EURB(10))); } @@ -920,8 +762,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // whether the issuer is in the domain should NOT affect whether an // offer can be consumed in domain payment Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); // create an xrp/usd offer with usd as takergets auto const bobOffer1Seq{env.seq(bob)}; @@ -933,10 +774,8 @@ class PermissionedDEX_test : public beast::unit_test::suite env(offer(bob, USD(10), XRP(10)), domain(domainID), txflags(tfPassive)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOffer1Seq, XRP(10), USD(10), 0, true)); - BEAST_EXPECT(checkOffer( - env, bob, bobOffer2Seq, USD(10), XRP(10), lsfPassive, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOffer1Seq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOffer2Seq, USD(10), XRP(10), lsfPassive, true)); // remove gateway from domain env(credentials::deleteCred(domainOwner, gw, domainOwner, credType)); @@ -944,19 +783,13 @@ class PermissionedDEX_test : public beast::unit_test::suite // payment succeeds even if issuer is not in domain // xrp/usd offer is consumed - env(pay(alice, carol, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(alice, carol, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); BEAST_EXPECT(!offerExists(env, bob, bobOffer1Seq)); // payment succeeds even if issuer is not in domain // usd/xrp offer is consumed - env(pay(alice, carol, XRP(10)), - path(~XRP), - sendmax(USD(10)), - domain(domainID)); + env(pay(alice, carol, XRP(10)), path(~XRP), sendmax(USD(10)), domain(domainID)); env.close(); BEAST_EXPECT(!offerExists(env, bob, bobOffer2Seq)); } @@ -969,8 +802,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // checking that an unfunded offer will be implicitly removed by a // successful payment tx Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const aliceOfferSeq{env.seq(alice)}; env(offer(alice, XRP(100), USD(100)), domain(domainID)); @@ -980,10 +812,8 @@ class PermissionedDEX_test : public beast::unit_test::suite env(offer(bob, XRP(20), USD(20)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(20), USD(20), 0, true)); - BEAST_EXPECT( - checkOffer(env, alice, aliceOfferSeq, XRP(100), USD(100), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(20), USD(20), 0, true)); + BEAST_EXPECT(checkOffer(env, alice, aliceOfferSeq, XRP(100), USD(100), 0, true)); auto const domainDirKey = getDefaultOfferDirKey(env, bob, bobOfferSeq); BEAST_EXPECT(domainDirKey); @@ -993,14 +823,10 @@ class PermissionedDEX_test : public beast::unit_test::suite env(credentials::deleteCred(domainOwner, alice, domainOwner, credType)); env.close(); - env(pay(gw, carol, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(gw, carol, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); // alice's unfunded offer is removed implicitly BEAST_EXPECT(!offerExists(env, alice, aliceOfferSeq)); @@ -1013,16 +839,11 @@ class PermissionedDEX_test : public beast::unit_test::suite testcase("AMM not used"); Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); AMM amm(env, alice, XRP(10), USD(50)); // a domain payment isn't able to consume AMM - env(pay(bob, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(bob, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); // a non domain payment can use AMM @@ -1042,53 +863,38 @@ class PermissionedDEX_test : public beast::unit_test::suite // test preflight - invalid hybrid flag { Env env(*this, features - featurePermissionedDEX); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); - env(offer(bob, XRP(10), USD(10)), - domain(domainID), - txflags(tfHybrid), - ter(temDISABLED)); + env(offer(bob, XRP(10), USD(10)), domain(domainID), txflags(tfHybrid), ter(temDISABLED)); env.close(); - env(offer(bob, XRP(10), USD(10)), - txflags(tfHybrid), - ter(temINVALID_FLAG)); + env(offer(bob, XRP(10), USD(10)), txflags(tfHybrid), ter(temINVALID_FLAG)); env.close(); env.enableFeature(featurePermissionedDEX); env.close(); // hybrid offer must have domainID - env(offer(bob, XRP(10), USD(10)), - txflags(tfHybrid), - ter(temINVALID_FLAG)); + env(offer(bob, XRP(10), USD(10)), txflags(tfHybrid), ter(temINVALID_FLAG)); env.close(); // hybrid offer must have domainID auto const offerSeq{env.seq(bob)}; - env(offer(bob, XRP(10), USD(10)), - txflags(tfHybrid), - domain(domainID)); + env(offer(bob, XRP(10), USD(10)), txflags(tfHybrid), domain(domainID)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, offerSeq, XRP(10), USD(10), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, offerSeq, XRP(10), USD(10), lsfHybrid, true)); } // apply - domain offer can cross with hybrid { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const bobOfferSeq{env.seq(bob)}; - env(offer(bob, XRP(10), USD(10)), - txflags(tfHybrid), - domain(domainID)); + env(offer(bob, XRP(10), USD(10)), txflags(tfHybrid), domain(domainID)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, bobOfferSeq, XRP(10), USD(10), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), lsfHybrid, true)); BEAST_EXPECT(offerExists(env, bob, bobOfferSeq)); BEAST_EXPECT(ownerCount(env, bob) == 3); @@ -1104,19 +910,15 @@ class PermissionedDEX_test : public beast::unit_test::suite // apply - open offer can cross with hybrid { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const bobOfferSeq{env.seq(bob)}; - env(offer(bob, XRP(10), USD(10)), - txflags(tfHybrid), - domain(domainID)); + env(offer(bob, XRP(10), USD(10)), txflags(tfHybrid), domain(domainID)); env.close(); BEAST_EXPECT(offerExists(env, bob, bobOfferSeq)); BEAST_EXPECT(ownerCount(env, bob) == 3); - BEAST_EXPECT(checkOffer( - env, bob, bobOfferSeq, XRP(10), USD(10), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), lsfHybrid, true)); auto const aliceOfferSeq{env.seq(alice)}; env(offer(alice, USD(10), XRP(10))); @@ -1131,22 +933,18 @@ class PermissionedDEX_test : public beast::unit_test::suite // domain book { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const bobOfferSeq{env.seq(bob)}; env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, true)); BEAST_EXPECT(ownerCount(env, bob) == 3); // hybrid offer auto crosses with domain offer auto const aliceOfferSeq{env.seq(alice)}; - env(offer(alice, USD(10), XRP(10)), - domain(domainID), - txflags(tfHybrid)); + env(offer(alice, USD(10), XRP(10)), domain(domainID), txflags(tfHybrid)); env.close(); BEAST_EXPECT(!offerExists(env, alice, aliceOfferSeq)); @@ -1158,30 +956,24 @@ class PermissionedDEX_test : public beast::unit_test::suite // because by default, it only tries to cross domain offers { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const bobOfferSeq{env.seq(bob)}; env(offer(bob, XRP(10), USD(10))); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, false)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, false)); BEAST_EXPECT(ownerCount(env, bob) == 3); // hybrid offer auto crosses with domain offer auto const aliceOfferSeq{env.seq(alice)}; - env(offer(alice, USD(10), XRP(10)), - domain(domainID), - txflags(tfHybrid)); + env(offer(alice, USD(10), XRP(10)), domain(domainID), txflags(tfHybrid)); env.close(); BEAST_EXPECT(offerExists(env, alice, aliceOfferSeq)); BEAST_EXPECT(offerExists(env, bob, bobOfferSeq)); - BEAST_EXPECT( - checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, false)); - BEAST_EXPECT(checkOffer( - env, alice, aliceOfferSeq, USD(10), XRP(10), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), 0, false)); + BEAST_EXPECT(checkOffer(env, alice, aliceOfferSeq, USD(10), XRP(10), lsfHybrid, true)); BEAST_EXPECT(ownerCount(env, alice) == 3); } } @@ -1195,8 +987,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // in this case, the hybrid offer will be considered as unfunded even in // a regular payment Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const hybridOfferSeq{env.seq(bob)}; env(offer(bob, XRP(50), USD(50)), txflags(tfHybrid), domain(domainID)); @@ -1208,24 +999,15 @@ class PermissionedDEX_test : public beast::unit_test::suite // bob's hybrid offer is unfunded and can not be consumed in a domain // payment - env(pay(alice, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, hybridOfferSeq, XRP(50), USD(50), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, hybridOfferSeq, XRP(50), USD(50), lsfHybrid, true)); // bob's unfunded hybrid offer can't be consumed even with a regular // payment - env(pay(alice, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5)), ter(tecPATH_PARTIAL)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, hybridOfferSeq, XRP(50), USD(50), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, hybridOfferSeq, XRP(50), USD(50), lsfHybrid, true)); // create a regular offer auto const regularOfferSeq{env.seq(bob)}; @@ -1234,12 +1016,9 @@ class PermissionedDEX_test : public beast::unit_test::suite BEAST_EXPECT(offerExists(env, bob, regularOfferSeq)); BEAST_EXPECT(checkOffer(env, bob, regularOfferSeq, XRP(10), USD(10))); - auto const sleHybridOffer = - env.le(keylet::offer(bob.id(), hybridOfferSeq)); + auto const sleHybridOffer = env.le(keylet::offer(bob.id(), hybridOfferSeq)); BEAST_EXPECT(sleHybridOffer); - auto const openDir = - sleHybridOffer->getFieldArray(sfAdditionalBooks)[0].getFieldH256( - sfBookDirectory); + auto const openDir = sleHybridOffer->getFieldArray(sfAdditionalBooks)[0].getFieldH256(sfBookDirectory); BEAST_EXPECT(checkDirectorySize(env, openDir, 2)); // this normal payment should consume the regular offer and remove the @@ -1260,22 +1039,15 @@ class PermissionedDEX_test : public beast::unit_test::suite // both non domain and domain payments can consume hybrid offer { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const hybridOfferSeq{env.seq(bob)}; - env(offer(bob, XRP(10), USD(10)), - txflags(tfHybrid), - domain(domainID)); + env(offer(bob, XRP(10), USD(10)), txflags(tfHybrid), domain(domainID)); env.close(); - env(pay(alice, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID)); + env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, hybridOfferSeq, XRP(5), USD(5), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, hybridOfferSeq, XRP(5), USD(5), lsfHybrid, true)); // hybrid offer can't be consumed since bob is not in domain anymore env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5))); @@ -1288,8 +1060,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // wrong domainID { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); // Fund accounts Account badDomainOwner("badDomainOwner"); @@ -1310,28 +1081,17 @@ class PermissionedDEX_test : public beast::unit_test::suite env.close(); auto const hybridOfferSeq{env.seq(bob)}; - env(offer(bob, XRP(10), USD(10)), - txflags(tfHybrid), - domain(domainID)); + env(offer(bob, XRP(10), USD(10)), txflags(tfHybrid), domain(domainID)); env.close(); // other domains can't consume the offer - env(pay(devin, badDomainOwner, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(badDomainID), - ter(tecPATH_DRY)); + env(pay(devin, badDomainOwner, USD(5)), path(~USD), sendmax(XRP(5)), domain(badDomainID), ter(tecPATH_DRY)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, hybridOfferSeq, XRP(10), USD(10), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, hybridOfferSeq, XRP(10), USD(10), lsfHybrid, true)); - env(pay(alice, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID)); + env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, hybridOfferSeq, XRP(5), USD(5), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, hybridOfferSeq, XRP(5), USD(5), lsfHybrid, true)); // hybrid offer can't be consumed since bob is not in domain anymore env(pay(alice, carol, USD(5)), path(~USD), sendmax(XRP(5))); @@ -1343,8 +1103,7 @@ class PermissionedDEX_test : public beast::unit_test::suite // test domain payment consuming two offers w/ hybrid offer { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const EUR = gw["EUR"]; env.trust(EUR(1000), alice); @@ -1360,46 +1119,31 @@ class PermissionedDEX_test : public beast::unit_test::suite env(offer(bob, XRP(10), USD(10)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, true)); // payment fail because there isn't eur offer - env(pay(alice, carol, EUR(5)), - path(~USD, ~EUR), - sendmax(XRP(5)), - domain(domainID), - ter(tecPATH_PARTIAL)); + env(pay(alice, carol, EUR(5)), path(~USD, ~EUR), sendmax(XRP(5)), domain(domainID), ter(tecPATH_PARTIAL)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, true)); // bob creates a hybrid eur offer auto const eurOfferSeq{env.seq(bob)}; - env(offer(bob, USD(10), EUR(10)), - domain(domainID), - txflags(tfHybrid)); + env(offer(bob, USD(10), EUR(10)), domain(domainID), txflags(tfHybrid)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, eurOfferSeq, USD(10), EUR(10), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, eurOfferSeq, USD(10), EUR(10), lsfHybrid, true)); // alice successfully consume two domain offers: xrp/usd and usd/eur - env(pay(alice, carol, EUR(5)), - path(~USD, ~EUR), - sendmax(XRP(5)), - domain(domainID)); + env(pay(alice, carol, EUR(5)), path(~USD, ~EUR), sendmax(XRP(5)), domain(domainID)); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, usdOfferSeq, XRP(5), USD(5), 0, true)); - BEAST_EXPECT(checkOffer( - env, bob, eurOfferSeq, USD(5), EUR(5), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, usdOfferSeq, XRP(5), USD(5), 0, true)); + BEAST_EXPECT(checkOffer(env, bob, eurOfferSeq, USD(5), EUR(5), lsfHybrid, true)); } // test regular payment using a regular offer and a hybrid offer { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const EUR = gw["EUR"]; env.trust(EUR(1000), alice); @@ -1416,26 +1160,20 @@ class PermissionedDEX_test : public beast::unit_test::suite env(offer(bob, XRP(10), USD(10))); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, false)); + BEAST_EXPECT(checkOffer(env, bob, usdOfferSeq, XRP(10), USD(10), 0, false)); // bob creates a hybrid eur offer auto const eurOfferSeq{env.seq(bob)}; - env(offer(bob, USD(10), EUR(10)), - domain(domainID), - txflags(tfHybrid)); + env(offer(bob, USD(10), EUR(10)), domain(domainID), txflags(tfHybrid)); env.close(); - BEAST_EXPECT(checkOffer( - env, bob, eurOfferSeq, USD(10), EUR(10), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, eurOfferSeq, USD(10), EUR(10), lsfHybrid, true)); // alice successfully consume two offers: xrp/usd and usd/eur env(pay(alice, carol, EUR(5)), path(~USD, ~EUR), sendmax(XRP(5))); env.close(); - BEAST_EXPECT( - checkOffer(env, bob, usdOfferSeq, XRP(5), USD(5), 0, false)); - BEAST_EXPECT(checkOffer( - env, bob, eurOfferSeq, USD(5), EUR(5), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, usdOfferSeq, XRP(5), USD(5), 0, false)); + BEAST_EXPECT(checkOffer(env, bob, eurOfferSeq, USD(5), EUR(5), lsfHybrid, true)); } } @@ -1443,8 +1181,7 @@ class PermissionedDEX_test : public beast::unit_test::suite testHybridOfferDirectories(FeatureBitset features) { Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); std::vector offerSeqs; offerSeqs.reserve(100); @@ -1461,22 +1198,16 @@ class PermissionedDEX_test : public beast::unit_test::suite { auto const bobOfferSeq{env.seq(bob)}; offerSeqs.emplace_back(bobOfferSeq); - env(offer(bob, XRP(10), USD(10)), - txflags(tfHybrid), - domain(domainID)); + env(offer(bob, XRP(10), USD(10)), txflags(tfHybrid), domain(domainID)); env.close(); auto const sleOffer = env.le(keylet::offer(bob.id(), bobOfferSeq)); BEAST_EXPECT(sleOffer); BEAST_EXPECT(sleOffer->getFieldH256(sfBookDirectory) == domainDir); - BEAST_EXPECT( - sleOffer->getFieldArray(sfAdditionalBooks).size() == 1); - BEAST_EXPECT( - sleOffer->getFieldArray(sfAdditionalBooks)[0].getFieldH256( - sfBookDirectory) == openDir); + BEAST_EXPECT(sleOffer->getFieldArray(sfAdditionalBooks).size() == 1); + BEAST_EXPECT(sleOffer->getFieldArray(sfAdditionalBooks)[0].getFieldH256(sfBookDirectory) == openDir); - BEAST_EXPECT(checkOffer( - env, bob, bobOfferSeq, XRP(10), USD(10), lsfHybrid, true)); + BEAST_EXPECT(checkOffer(env, bob, bobOfferSeq, XRP(10), USD(10), lsfHybrid, true)); BEAST_EXPECT(checkDirectorySize(env, domainDir, i)); BEAST_EXPECT(checkDirectorySize(env, openDir, i)); } @@ -1498,8 +1229,7 @@ class PermissionedDEX_test : public beast::unit_test::suite testcase("Auto bridge"); Env env(*this, features); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - PermissionedDEX(env); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = PermissionedDEX(env); auto const EUR = gw["EUR"]; for (auto const& account : {alice, bob, carol}) diff --git a/src/test/app/PermissionedDomains_test.cpp b/src/test/app/PermissionedDomains_test.cpp index a7dff84cff..1a1fe9a9eb 100644 --- a/src/test/app/PermissionedDomains_test.cpp +++ b/src/test/app/PermissionedDomains_test.cpp @@ -33,8 +33,7 @@ exceptionExpected(Env& env, Json::Value const& jv) class PermissionedDomains_test : public beast::unit_test::suite { - FeatureBitset withoutFeature_{ - testable_amendments() - featurePermissionedDomains}; + FeatureBitset withoutFeature_{testable_amendments() - featurePermissionedDomains}; FeatureBitset withFeature_{ testable_amendments() // | featurePermissionedDomains | featureCredentials}; @@ -89,10 +88,7 @@ class PermissionedDomains_test : public beast::unit_test::suite // Verify that bad inputs fail for each of create new and update // behaviors of PermissionedDomainSet void - testBadData( - Account const& account, - Env& env, - std::optional domain = std::nullopt) + testBadData(Account const& account, Env& env, std::optional domain = std::nullopt) { Account const alice2("alice2"); Account const alice3("alice3"); @@ -108,8 +104,7 @@ class PermissionedDomains_test : public beast::unit_test::suite auto const setFee(drops(env.current()->fees().increment)); // Test empty credentials. - env(pdomain::setTx(account, pdomain::Credentials(), domain), - ter(temARRAY_EMPTY)); + env(pdomain::setTx(account, pdomain::Credentials(), domain), ter(temARRAY_EMPTY)); // Test 11 credentials. pdomain::Credentials const credentials11{ @@ -124,11 +119,8 @@ class PermissionedDomains_test : public beast::unit_test::suite {alice10, "credential9"}, {alice11, "credential10"}, {alice12, "credential11"}}; - BEAST_EXPECT( - credentials11.size() == - maxPermissionedDomainCredentialsArraySize + 1); - env(pdomain::setTx(account, credentials11, domain), - ter(temARRAY_TOO_LARGE)); + BEAST_EXPECT(credentials11.size() == maxPermissionedDomainCredentialsArraySize + 1); + env(pdomain::setTx(account, credentials11, domain), ter(temARRAY_TOO_LARGE)); // Test credentials including non-existent issuer. Account const nobody("nobody"); @@ -143,9 +135,7 @@ class PermissionedDomains_test : public beast::unit_test::suite env(pdomain::setTx(account, credentialsNon, domain), ter(tecNO_ISSUER)); // Test bad fee - env(pdomain::setTx(account, credentials11, domain), - fee(1, true), - ter(temBAD_FEE)); + env(pdomain::setTx(account, credentials11, domain), fee(1, true), ter(temBAD_FEE)); pdomain::Credentials const credentials4{ {alice2, "credential1"}, @@ -157,15 +147,12 @@ class PermissionedDomains_test : public beast::unit_test::suite auto const credentialOrig = txJsonMutable["AcceptedCredentials"][2u]; // Remove Issuer from a credential and apply. - txJsonMutable["AcceptedCredentials"][2u][jss::Credential].removeMember( - jss::Issuer); - BEAST_EXPECT( - exceptionExpected(env, txJsonMutable).starts_with("invalidParams")); + txJsonMutable["AcceptedCredentials"][2u][jss::Credential].removeMember(jss::Issuer); + BEAST_EXPECT(exceptionExpected(env, txJsonMutable).starts_with("invalidParams")); // Make an empty CredentialType. txJsonMutable["AcceptedCredentials"][2u] = credentialOrig; - txJsonMutable["AcceptedCredentials"][2u][jss::Credential] - ["CredentialType"] = ""; + txJsonMutable["AcceptedCredentials"][2u][jss::Credential]["CredentialType"] = ""; env(txJsonMutable, ter(temMALFORMED)); // Make too long CredentialType. @@ -173,22 +160,16 @@ class PermissionedDomains_test : public beast::unit_test::suite "Cred0123456789012345678901234567890123456789012345678901234567890"; static_assert(longCredentialType.size() == maxCredentialTypeLength + 1); txJsonMutable["AcceptedCredentials"][2u] = credentialOrig; - txJsonMutable["AcceptedCredentials"][2u][jss::Credential] - ["CredentialType"] = std::string(longCredentialType); - BEAST_EXPECT( - exceptionExpected(env, txJsonMutable).starts_with("invalidParams")); + txJsonMutable["AcceptedCredentials"][2u][jss::Credential]["CredentialType"] = std::string(longCredentialType); + BEAST_EXPECT(exceptionExpected(env, txJsonMutable).starts_with("invalidParams")); // Remove Credentialtype from a credential and apply. - txJsonMutable["AcceptedCredentials"][2u][jss::Credential].removeMember( - "CredentialType"); - BEAST_EXPECT( - exceptionExpected(env, txJsonMutable).starts_with("invalidParams")); + txJsonMutable["AcceptedCredentials"][2u][jss::Credential].removeMember("CredentialType"); + BEAST_EXPECT(exceptionExpected(env, txJsonMutable).starts_with("invalidParams")); // Remove both - txJsonMutable["AcceptedCredentials"][2u][jss::Credential].removeMember( - jss::Issuer); - BEAST_EXPECT( - exceptionExpected(env, txJsonMutable).starts_with("invalidParams")); + txJsonMutable["AcceptedCredentials"][2u][jss::Credential].removeMember(jss::Issuer); + BEAST_EXPECT(exceptionExpected(env, txJsonMutable).starts_with("invalidParams")); // Make 2 identical credentials. Duplicates are not supported by // permissioned domains, so transactions should return errors @@ -207,8 +188,7 @@ class PermissionedDomains_test : public beast::unit_test::suite auto const sorted = pdomain::sortCredentials(credentialsDup); BEAST_EXPECT(sorted.size() == 4); - env(pdomain::setTx(account, credentialsDup, domain), - ter(temMALFORMED)); + env(pdomain::setTx(account, credentialsDup, domain), ter(temMALFORMED)); env.close(); env(pdomain::setTx(account, sorted, domain)); @@ -220,8 +200,7 @@ class PermissionedDomains_test : public beast::unit_test::suite d = pdomain::getNewDomain(env.meta()); env.close(); auto objects = pdomain::getObjects(account, env); - auto const fromObject = - pdomain::credentialsFromJson(objects[d], human2Acc); + auto const fromObject = pdomain::credentialsFromJson(objects[d], human2Acc); auto const sortedCreds = pdomain::sortCredentials(credentialsDup); BEAST_EXPECT(fromObject == sortedCreds); } @@ -240,8 +219,7 @@ class PermissionedDomains_test : public beast::unit_test::suite for (auto const& c : credentialsSame) human2Acc.emplace(c.issuer.human(), c.issuer); - BEAST_EXPECT( - credentialsSame != pdomain::sortCredentials(credentialsSame)); + BEAST_EXPECT(credentialsSame != pdomain::sortCredentials(credentialsSame)); env(pdomain::setTx(account, credentialsSame, domain)); uint256 d; @@ -251,8 +229,7 @@ class PermissionedDomains_test : public beast::unit_test::suite d = pdomain::getNewDomain(env.meta()); env.close(); auto objects = pdomain::getObjects(account, env); - auto const fromObject = - pdomain::credentialsFromJson(objects[d], human2Acc); + auto const fromObject = pdomain::credentialsFromJson(objects[d], human2Acc); auto const sortedCreds = pdomain::sortCredentials(credentialsSame); BEAST_EXPECT(fromObject == sortedCreds); } @@ -302,9 +279,7 @@ class PermissionedDomains_test : public beast::unit_test::suite BEAST_EXPECT(object["LedgerEntryType"] == "PermissionedDomain"); BEAST_EXPECT(object["Owner"] == alice[0].human()); BEAST_EXPECT(object["Sequence"] == tx["Sequence"]); - BEAST_EXPECT( - pdomain::credentialsFromJson(object, human2Acc) == - credentials1); + BEAST_EXPECT(pdomain::credentialsFromJson(object, human2Acc) == credentials1); } // Make longest possible CredentialType. @@ -313,8 +288,7 @@ class PermissionedDomains_test : public beast::unit_test::suite "Cred0123456789012345678901234567890123456789012345678901234567" "89"; static_assert(longCredentialType.size() == maxCredentialTypeLength); - pdomain::Credentials const longCredentials{ - {alice[1], std::string(longCredentialType)}}; + pdomain::Credentials const longCredentials{{alice[1], std::string(longCredentialType)}}; env(pdomain::setTx(alice[0], longCredentials)); @@ -326,19 +300,15 @@ class PermissionedDomains_test : public beast::unit_test::suite BEAST_EXPECT(tx["Account"] == alice[0].human()); bool findSeq = false; - for (auto const& [domain, object] : - pdomain::getObjects(alice[0], env)) + for (auto const& [domain, object] : pdomain::getObjects(alice[0], env)) { findSeq = object["Sequence"] == tx["Sequence"]; if (findSeq) { BEAST_EXPECT(domain.isNonZero()); - BEAST_EXPECT( - object["LedgerEntryType"] == "PermissionedDomain"); + BEAST_EXPECT(object["LedgerEntryType"] == "PermissionedDomain"); BEAST_EXPECT(object["Owner"] == alice[0].human()); - BEAST_EXPECT( - pdomain::credentialsFromJson(object, human2Acc) == - longCredentials); + BEAST_EXPECT(pdomain::credentialsFromJson(object, human2Acc) == longCredentials); break; } } @@ -361,52 +331,39 @@ class PermissionedDomains_test : public beast::unit_test::suite }; uint256 domain2; { - BEAST_EXPECT( - credentials10.size() == - maxPermissionedDomainCredentialsArraySize); - BEAST_EXPECT( - credentials10 != pdomain::sortCredentials(credentials10)); + BEAST_EXPECT(credentials10.size() == maxPermissionedDomainCredentialsArraySize); + BEAST_EXPECT(credentials10 != pdomain::sortCredentials(credentials10)); env(pdomain::setTx(alice[0], credentials10)); auto tx = env.tx()->getJson(JsonOptions::none); domain2 = pdomain::getNewDomain(env.meta()); auto objects = pdomain::getObjects(alice[0], env); auto object = objects[domain2]; - BEAST_EXPECT( - pdomain::credentialsFromJson(object, human2Acc) == - pdomain::sortCredentials(credentials10)); + BEAST_EXPECT(pdomain::credentialsFromJson(object, human2Acc) == pdomain::sortCredentials(credentials10)); } // Update with 1 credential. env(pdomain::setTx(alice[0], credentials1, domain2)); BEAST_EXPECT( - pdomain::credentialsFromJson( - pdomain::getObjects(alice[0], env)[domain2], human2Acc) == - credentials1); + pdomain::credentialsFromJson(pdomain::getObjects(alice[0], env)[domain2], human2Acc) == credentials1); // Update with 10 credentials. env(pdomain::setTx(alice[0], credentials10, domain2)); env.close(); BEAST_EXPECT( - pdomain::credentialsFromJson( - pdomain::getObjects(alice[0], env)[domain2], human2Acc) == + pdomain::credentialsFromJson(pdomain::getObjects(alice[0], env)[domain2], human2Acc) == pdomain::sortCredentials(credentials10)); // Update from the wrong owner. - env(pdomain::setTx(alice[2], credentials1, domain2), - ter(tecNO_PERMISSION)); + env(pdomain::setTx(alice[2], credentials1, domain2), ter(tecNO_PERMISSION)); // Update a uint256(0) domain - env(pdomain::setTx(alice[0], credentials1, uint256(0)), - ter(temMALFORMED)); + env(pdomain::setTx(alice[0], credentials1, uint256(0)), ter(temMALFORMED)); // Update non-existent domain - env(pdomain::setTx(alice[0], credentials1, uint256(75)), - ter(tecNO_ENTRY)); + env(pdomain::setTx(alice[0], credentials1, uint256(75)), ter(tecNO_ENTRY)); // Wrong flag - env(pdomain::setTx(alice[0], credentials1), - txflags(tfClawTwoAssets), - ter(temINVALID_FLAG)); + env(pdomain::setTx(alice[0], credentials1), txflags(tfClawTwoAssets), ter(temINVALID_FLAG)); // Test bad data when creating a domain. testBadData(alice[0], env); @@ -421,9 +378,7 @@ class PermissionedDomains_test : public beast::unit_test::suite std::size_t ownerSeq = env.seq(alice[0]); while (deleteDelta + ownerSeq > env.current()->seq()) env.close(); - env(acctdelete(alice[0], alice[2]), - fee(acctDelFee), - ter(tecHAS_OBLIGATIONS)); + env(acctdelete(alice[0], alice[2]), fee(acctDelFee), ter(tecHAS_OBLIGATIONS)); } { @@ -466,14 +421,10 @@ class PermissionedDomains_test : public beast::unit_test::suite env(pdomain::deleteTx(alice, uint256(75)), ter(tecNO_ENTRY)); // Test bad fee - env(pdomain::deleteTx(alice, uint256(75)), - ter(temBAD_FEE), - fee(1, true)); + env(pdomain::deleteTx(alice, uint256(75)), ter(temBAD_FEE), fee(1, true)); // Wrong flag - env(pdomain::deleteTx(alice, domain), - ter(temINVALID_FLAG), - txflags(tfClawTwoAssets)); + env(pdomain::deleteTx(alice, domain), ter(temINVALID_FLAG), txflags(tfClawTwoAssets)); // Delete a zero domain. env(pdomain::deleteTx(alice, uint256(0)), ter(temMALFORMED)); @@ -527,9 +478,7 @@ class PermissionedDomains_test : public beast::unit_test::suite // Pay alice almost enough to make the reserve. env(pay(env.master, alice, incReserve + drops(2 * baseFee) - drops(1))); - BEAST_EXPECT( - env.balance(alice) == - acctReserve + incReserve + drops(baseFee) - drops(1)); + BEAST_EXPECT(env.balance(alice) == acctReserve + incReserve + drops(baseFee) - drops(1)); env.close(); // alice still does not have enough XRP for the reserve. diff --git a/src/test/app/PseudoTx_test.cpp b/src/test/app/PseudoTx_test.cpp index f01ba616c8..29e13888c3 100644 --- a/src/test/app/PseudoTx_test.cpp +++ b/src/test/app/PseudoTx_test.cpp @@ -49,8 +49,7 @@ struct PseudoTx_test : public beast::unit_test::suite { std::vector res; - res.emplace_back(STTx( - ttACCOUNT_SET, [&](auto& obj) { obj[sfAccount] = AccountID(1); })); + res.emplace_back(STTx(ttACCOUNT_SET, [&](auto& obj) { obj[sfAccount] = AccountID(1); })); res.emplace_back(STTx(ttPAYMENT, [&](auto& obj) { obj.setAccountID(sfAccount, AccountID(2)); @@ -66,20 +65,17 @@ struct PseudoTx_test : public beast::unit_test::suite using namespace jtx; Env env(*this, features); - for (auto const& stx : - getPseudoTxs(env.closed()->rules(), env.closed()->seq() + 1)) + for (auto const& stx : getPseudoTxs(env.closed()->rules(), env.closed()->seq() + 1)) { std::string reason; BEAST_EXPECT(isPseudoTx(stx)); BEAST_EXPECT(!passesLocalChecks(stx, reason)); BEAST_EXPECT(reason == "Cannot submit pseudo transactions."); - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) { - auto const result = - xrpl::apply(env.app(), view, stx, tapNONE, j); - BEAST_EXPECT(!result.applied && result.ter == temINVALID); - return result.applied; - }); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { + auto const result = xrpl::apply(env.app(), view, stx, tapNONE, j); + BEAST_EXPECT(!result.applied && result.ter == temINVALID); + return result.applied; + }); } } diff --git a/src/test/app/RCLValidations_test.cpp b/src/test/app/RCLValidations_test.cpp index 729f373738..495176104b 100644 --- a/src/test/app/RCLValidations_test.cpp +++ b/src/test/app/RCLValidations_test.cpp @@ -17,11 +17,9 @@ class RCLValidations_test : public beast::unit_test::suite testcase("Change validation trusted status"); auto keys = randomKeyPair(KeyType::secp256k1); auto v = std::make_shared( - xrpl::NetClock::time_point{}, - keys.first, - keys.second, - calcNodeID(keys.first), - [&](STValidation& v) { v.setFieldU32(sfLedgerSequence, 123456); }); + xrpl::NetClock::time_point{}, keys.first, keys.second, calcNodeID(keys.first), [&](STValidation& v) { + v.setFieldU32(sfLedgerSequence, 123456); + }); BEAST_EXPECT(v->isTrusted()); v->setUntrusted(); @@ -56,16 +54,12 @@ class RCLValidations_test : public beast::unit_test::suite jtx::Env env(*this); Config config; - auto prev = std::make_shared( - create_genesis, - config, - std::vector{}, - env.app().getNodeFamily()); + auto prev = + std::make_shared(create_genesis, config, std::vector{}, env.app().getNodeFamily()); history.push_back(prev); for (auto i = 0; i < (2 * maxAncestors + 1); ++i) { - auto next = std::make_shared( - *prev, env.app().timeKeeper().closeTime()); + auto next = std::make_shared(*prev, env.app().timeKeeper().closeTime()); next->updateSkipList(); history.push_back(next); prev = next; @@ -73,8 +67,7 @@ class RCLValidations_test : public beast::unit_test::suite // altHistory agrees with first half of regular history Seq const diverge = history.size() / 2; - std::vector> altHistory( - history.begin(), history.begin() + diverge); + std::vector> altHistory(history.begin(), history.begin() + diverge); // advance clock to get new ledgers using namespace std::chrono_literals; env.timeKeeper().set(env.timeKeeper().now() + 1200s); @@ -82,8 +75,7 @@ class RCLValidations_test : public beast::unit_test::suite bool forceHash = true; while (altHistory.size() < history.size()) { - auto next = std::make_shared( - *prev, env.app().timeKeeper().closeTime()); + auto next = std::make_shared(*prev, env.app().timeKeeper().closeTime()); // Force a different hash on the first iteration next->updateSkipList(); BEAST_EXPECT(next->read(keylet::fees())); @@ -219,16 +211,12 @@ class RCLValidations_test : public beast::unit_test::suite jtx::Env env(*this); auto& j = env.journal; Config config; - auto prev = std::make_shared( - create_genesis, - config, - std::vector{}, - env.app().getNodeFamily()); + auto prev = + std::make_shared(create_genesis, config, std::vector{}, env.app().getNodeFamily()); history.push_back(prev); for (auto i = 0; i < (maxAncestors + 10); ++i) { - auto next = std::make_shared( - *prev, env.app().timeKeeper().closeTime()); + auto next = std::make_shared(*prev, env.app().timeKeeper().closeTime()); next->updateSkipList(); history.push_back(next); prev = next; @@ -279,8 +267,7 @@ class RCLValidations_test : public beast::unit_test::suite // quirk of RCLValidation and prevents deleting the old support // for ledger 257 - BEAST_EXPECT( - trie.remove(RCLValidatedLedger{history[257], env.journal}, 1)); + BEAST_EXPECT(trie.remove(RCLValidatedLedger{history[257], env.journal}, 1)); trie.insert(RCLValidatedLedger{history[258], env.journal}, 1); trie.getPreferred(1); // trie.dump(std::cout); diff --git a/src/test/app/ReducedOffer_test.cpp b/src/test/app/ReducedOffer_test.cpp index 8a395913b2..aa1473d2ee 100644 --- a/src/test/app/ReducedOffer_test.cpp +++ b/src/test/app/ReducedOffer_test.cpp @@ -12,36 +12,24 @@ namespace test { class ReducedOffer_test : public beast::unit_test::suite { static auto - ledgerEntryOffer( - jtx::Env& env, - jtx::Account const& acct, - std::uint32_t offer_seq) + ledgerEntryOffer(jtx::Env& env, jtx::Account const& acct, std::uint32_t offer_seq) { Json::Value jvParams; jvParams[jss::offer][jss::account] = acct.human(); jvParams[jss::offer][jss::seq] = offer_seq; - return env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + return env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; } static bool - offerInLedger( - jtx::Env& env, - jtx::Account const& acct, - std::uint32_t offerSeq) + offerInLedger(jtx::Env& env, jtx::Account const& acct, std::uint32_t offerSeq) { Json::Value ledgerOffer = ledgerEntryOffer(env, acct, offerSeq); - return !( - ledgerOffer.isMember(jss::error) && - ledgerOffer[jss::error].asString() == "entryNotFound"); + return !(ledgerOffer.isMember(jss::error) && ledgerOffer[jss::error].asString() == "entryNotFound"); } // Common code to clean up unneeded offers. static void - cleanupOldOffers( - jtx::Env& env, - std::initializer_list> - list) + cleanupOldOffers(jtx::Env& env, std::initializer_list> list) { for (auto [acct, offerSeq] : list) env(offer_cancel(acct, offerSeq)); @@ -80,10 +68,8 @@ public: // 2. Collects the results, and // 3. Cleans up for the next offer pair. // Returns 1 if the crossed offer has a bad rate for the book. - auto exerciseOfferPair = - [this, &env, &alice, &bob]( - Amounts const& inLedger, - Amounts const& newOffer) -> unsigned int { + auto exerciseOfferPair = [this, &env, &alice, &bob]( + Amounts const& inLedger, Amounts const& newOffer) -> unsigned int { // Put inLedger offer in the ledger so newOffer can cross it. std::uint32_t const aliceOfferSeq = env.seq(alice); env(offer(alice, inLedger.in, inLedger.out)); @@ -94,8 +80,7 @@ public: std::uint32_t const bobOfferSeq = env.seq(bob); STAmount const bobInitialBalance = env.balance(bob); STAmount const bobsFee = env.current()->fees().base; - env(offer(bob, newOffer.in, newOffer.out, tfSell), - fee(bobsFee)); + env(offer(bob, newOffer.in, newOffer.out, tfSell), fee(bobsFee)); env.close(); STAmount const bobFinalBalance = env.balance(bob); @@ -109,20 +94,16 @@ public: // bob's offer should be in the ledger, but reduced in size. unsigned int badRate = 1; { - Json::Value bobOffer = - ledgerEntryOffer(env, bob, bobOfferSeq); + Json::Value bobOffer = ledgerEntryOffer(env, bob, bobOfferSeq); - STAmount const reducedTakerGets = amountFromJson( - sfTakerGets, bobOffer[jss::node][sfTakerGets.jsonName]); - STAmount const reducedTakerPays = amountFromJson( - sfTakerPays, bobOffer[jss::node][sfTakerPays.jsonName]); - STAmount const bobGot = - env.balance(bob) + bobsFee - bobInitialBalance; + STAmount const reducedTakerGets = + amountFromJson(sfTakerGets, bobOffer[jss::node][sfTakerGets.jsonName]); + STAmount const reducedTakerPays = + amountFromJson(sfTakerPays, bobOffer[jss::node][sfTakerPays.jsonName]); + STAmount const bobGot = env.balance(bob) + bobsFee - bobInitialBalance; BEAST_EXPECT(reducedTakerPays < newOffer.in); BEAST_EXPECT(reducedTakerGets < newOffer.out); - STAmount const inLedgerRate = - Quality(Amounts{reducedTakerPays, reducedTakerGets}) - .rate(); + STAmount const inLedgerRate = Quality(Amounts{reducedTakerPays, reducedTakerGets}).rate(); badRate = inLedgerRate > initialRate ? 1 : 0; @@ -133,11 +114,8 @@ public: // was computed. if (badRate == 0) { - STAmount const tweakedTakerPays = - reducedTakerPays + drops(1); - STAmount const tweakedRate = - Quality(Amounts{tweakedTakerPays, reducedTakerGets}) - .rate(); + STAmount const tweakedTakerPays = reducedTakerPays + drops(1); + STAmount const tweakedRate = Quality(Amounts{tweakedTakerPays, reducedTakerGets}).rate(); BEAST_EXPECT(tweakedRate > initialRate); } #if 0 @@ -158,29 +136,23 @@ public: // In preparation for the next iteration make sure the two // offers are gone from the ledger. - cleanupOldOffers( - env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); + cleanupOldOffers(env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); return badRate; }; // bob's offer (the new offer) is the same every time: - Amounts const bobsOffer{ - STAmount(XRP(1)), STAmount(USD.issue(), 1, 0)}; + Amounts const bobsOffer{STAmount(XRP(1)), STAmount(USD.issue(), 1, 0)}; // alice's offer has a slightly smaller TakerPays with each // iteration. This should mean that the size of the offer bob // places in the ledger should increase with each iteration. unsigned int blockedCount = 0; - for (std::uint64_t mantissaReduce = 1'000'000'000ull; - mantissaReduce <= 5'000'000'000ull; + for (std::uint64_t mantissaReduce = 1'000'000'000ull; mantissaReduce <= 5'000'000'000ull; mantissaReduce += 20'000'000ull) { STAmount aliceUSD{ - bobsOffer.out.issue(), - bobsOffer.out.mantissa() - mantissaReduce, - bobsOffer.out.exponent()}; - STAmount aliceXRP{ - bobsOffer.in.issue(), bobsOffer.in.mantissa() - 1}; + bobsOffer.out.issue(), bobsOffer.out.mantissa() - mantissaReduce, bobsOffer.out.exponent()}; + STAmount aliceXRP{bobsOffer.in.issue(), bobsOffer.in.mantissa() - 1}; Amounts alicesOffer{aliceUSD, aliceXRP}; blockedCount += exerciseOfferPair(alicesOffer, bobsOffer); } @@ -220,10 +192,8 @@ public: // 1. Exercises one offer pair, // 2. Collects the results, and // 3. Cleans up for the next offer pair. - auto exerciseOfferPair = - [this, &env, &alice, &bob]( - Amounts const& inLedger, - Amounts const& newOffer) -> unsigned int { + auto exerciseOfferPair = [this, &env, &alice, &bob]( + Amounts const& inLedger, Amounts const& newOffer) -> unsigned int { // Get the inLedger offer into the ledger so newOffer can cross // it. STAmount const initialRate = Quality(inLedger).rate(); @@ -243,30 +213,23 @@ public: { // If the in-ledger offer was not consumed then further // results are meaningless. - cleanupOldOffers( - env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); + cleanupOldOffers(env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); return 1; } // alice's offer should still be in the ledger, but reduced in // size. unsigned int badRate = 1; { - Json::Value aliceOffer = - ledgerEntryOffer(env, alice, aliceOfferSeq); + Json::Value aliceOffer = ledgerEntryOffer(env, alice, aliceOfferSeq); - STAmount const reducedTakerGets = amountFromJson( - sfTakerGets, - aliceOffer[jss::node][sfTakerGets.jsonName]); - STAmount const reducedTakerPays = amountFromJson( - sfTakerPays, - aliceOffer[jss::node][sfTakerPays.jsonName]); - STAmount const aliceGot = - env.balance(alice) - aliceInitialBalance; + STAmount const reducedTakerGets = + amountFromJson(sfTakerGets, aliceOffer[jss::node][sfTakerGets.jsonName]); + STAmount const reducedTakerPays = + amountFromJson(sfTakerPays, aliceOffer[jss::node][sfTakerPays.jsonName]); + STAmount const aliceGot = env.balance(alice) - aliceInitialBalance; BEAST_EXPECT(reducedTakerPays < inLedger.in); BEAST_EXPECT(reducedTakerGets < inLedger.out); - STAmount const inLedgerRate = - Quality(Amounts{reducedTakerPays, reducedTakerGets}) - .rate(); + STAmount const inLedgerRate = Quality(Amounts{reducedTakerPays, reducedTakerGets}).rate(); badRate = inLedgerRate > initialRate ? 1 : 0; // If the inLedgerRate is less than initial rate, then @@ -276,11 +239,8 @@ public: // was computed. if (badRate == 0) { - STAmount const tweakedTakerPays = - reducedTakerPays + drops(1); - STAmount const tweakedRate = - Quality(Amounts{tweakedTakerPays, reducedTakerGets}) - .rate(); + STAmount const tweakedTakerPays = reducedTakerPays + drops(1); + STAmount const tweakedRate = Quality(Amounts{tweakedTakerPays, reducedTakerGets}).rate(); BEAST_EXPECT(tweakedRate > initialRate); } #if 0 @@ -302,29 +262,23 @@ public: // In preparation for the next iteration make sure the two // offers are gone from the ledger. - cleanupOldOffers( - env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); + cleanupOldOffers(env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); return badRate; }; // alice's offer (the old offer) is the same every time: - Amounts const aliceOffer{ - STAmount(XRP(1)), STAmount(USD.issue(), 1, 0)}; + Amounts const aliceOffer{STAmount(XRP(1)), STAmount(USD.issue(), 1, 0)}; // bob's offer has a slightly smaller TakerPays with each iteration. // This should mean that the size of the offer alice leaves in the // ledger should increase with each iteration. unsigned int blockedCount = 0; - for (std::uint64_t mantissaReduce = 1'000'000'000ull; - mantissaReduce <= 4'000'000'000ull; + for (std::uint64_t mantissaReduce = 1'000'000'000ull; mantissaReduce <= 4'000'000'000ull; mantissaReduce += 20'000'000ull) { STAmount bobUSD{ - aliceOffer.out.issue(), - aliceOffer.out.mantissa() - mantissaReduce, - aliceOffer.out.exponent()}; - STAmount bobXRP{ - aliceOffer.in.issue(), aliceOffer.in.mantissa() - 1}; + aliceOffer.out.issue(), aliceOffer.out.mantissa() - mantissaReduce, aliceOffer.out.exponent()}; + STAmount bobXRP{aliceOffer.in.issue(), aliceOffer.in.mantissa() - 1}; Amounts bobsOffer{bobUSD, bobXRP}; blockedCount += exerciseOfferPair(aliceOffer, bobsOffer); @@ -357,8 +311,7 @@ public: env.trust(USD(1000), alice, bob); int blockedOrderBookCount = 0; - for (STAmount initialBobUSD = USD(0.45); initialBobUSD <= USD(1); - initialBobUSD += USD(0.025)) + for (STAmount initialBobUSD = USD(0.45); initialBobUSD <= USD(1); initialBobUSD += USD(0.025)) { // underfund bob's offer env(pay(gw, bob, initialBobUSD)); @@ -380,8 +333,7 @@ public: // then we use that as evidence that bob's offer blocked the // order book. { - bool const bobsOfferGone = - !offerInLedger(env, bob, bobOfferSeq); + bool const bobsOfferGone = !offerInLedger(env, bob, bobOfferSeq); STAmount const aliceBalanceUSD = env.balance(alice, USD); // Sanity check the ledger if alice got USD. @@ -400,16 +352,13 @@ public: // In preparation for the next iteration clean up any // leftover offers. - cleanupOldOffers( - env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); + cleanupOldOffers(env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); // Zero out alice's and bob's USD balances. - if (STAmount const aliceBalance = env.balance(alice, USD); - aliceBalance.signum() > 0) + if (STAmount const aliceBalance = env.balance(alice, USD); aliceBalance.signum() > 0) env(pay(alice, gw, aliceBalance)); - if (STAmount const bobBalance = env.balance(bob, USD); - bobBalance.signum() > 0) + if (STAmount const bobBalance = env.balance(bob, USD); bobBalance.signum() > 0) env(pay(bob, gw, bobBalance)); env.close(); @@ -448,17 +397,13 @@ public: env.trust(USD(1000), alice, bob); env.trust(EUR(1000), alice, bob); - STAmount const eurOffer( - EUR.issue(), /*mantissa*/ 2957, /*exponent*/ -76); - STAmount const usdOffer( - USD.issue(), /*mantissa*/ 7109, /*exponent*/ -76); + STAmount const eurOffer(EUR.issue(), /*mantissa*/ 2957, /*exponent*/ -76); + STAmount const usdOffer(USD.issue(), /*mantissa*/ 7109, /*exponent*/ -76); - STAmount const endLoop( - USD.issue(), /*mantissa*/ 50, /*exponent*/ -81); + STAmount const endLoop(USD.issue(), /*mantissa*/ 50, /*exponent*/ -81); int blockedOrderBookCount = 0; - for (STAmount initialBobUSD = tinyUSD; initialBobUSD <= endLoop; - initialBobUSD += tinyUSD) + for (STAmount initialBobUSD = tinyUSD; initialBobUSD <= endLoop; initialBobUSD += tinyUSD) { // underfund bob's offer env(pay(gw, bob, initialBobUSD)); @@ -478,8 +423,7 @@ public: // Examine the aftermath of alice's offer. { - bool const bobsOfferGone = - !offerInLedger(env, bob, bobOfferSeq); + bool const bobsOfferGone = !offerInLedger(env, bob, bobOfferSeq); STAmount aliceBalanceUSD = env.balance(alice, USD); #if 0 std::cout @@ -505,14 +449,11 @@ public: // In preparation for the next iteration clean up any // leftover offers. - cleanupOldOffers( - env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); + cleanupOldOffers(env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}}); // Zero out alice's and bob's IOU balances. - auto zeroBalance = [&env, &gw]( - Account const& acct, IOU const& iou) { - if (STAmount const balance = env.balance(acct, iou); - balance.signum() > 0) + auto zeroBalance = [&env, &gw](Account const& acct, IOU const& iou) { + if (STAmount const balance = env.balance(acct, iou); balance.signum() > 0) env(pay(acct, gw, balance)); }; @@ -532,10 +473,8 @@ public: Amounts jsonOfferToAmounts(Json::Value const& json) { - STAmount const in = - amountFromJson(sfTakerPays, json[sfTakerPays.jsonName]); - STAmount const out = - amountFromJson(sfTakerGets, json[sfTakerGets.jsonName]); + STAmount const in = amountFromJson(sfTakerPays, json[sfTakerPays.jsonName]); + STAmount const out = amountFromJson(sfTakerGets, json[sfTakerGets.jsonName]); return {in, out}; } @@ -558,8 +497,7 @@ public: // Make one test run without fixReducedOffersV2 and one with. for (FeatureBitset features : - {testable_amendments() - fixReducedOffersV2, - testable_amendments() | fixReducedOffersV2}) + {testable_amendments() - fixReducedOffersV2, testable_amendments() | fixReducedOffersV2}) { // Make sure none of the offers we generate are under funded. Env env{*this, features}; @@ -581,17 +519,14 @@ public: // 2. Collects the results, and // 3. Cleans up for the next offer trio. auto exerciseOfferTrio = - [this, &env, &alice, &bob, &carol, &USD]( - Amounts const& carolOffer) -> unsigned int { + [this, &env, &alice, &bob, &carol, &USD](Amounts const& carolOffer) -> unsigned int { // alice submits an offer that may become a blocker. std::uint32_t const aliceOfferSeq = env.seq(alice); static Amounts const aliceInitialOffer(USD(2), drops(3382562)); env(offer(alice, aliceInitialOffer.in, aliceInitialOffer.out)); env.close(); STAmount const initialRate = - Quality(jsonOfferToAmounts(ledgerEntryOffer( - env, alice, aliceOfferSeq)[jss::node])) - .rate(); + Quality(jsonOfferToAmounts(ledgerEntryOffer(env, alice, aliceOfferSeq)[jss::node])).rate(); // bob submits an offer that is more desirable than alice's std::uint32_t const bobOfferSeq = env.seq(bob); @@ -601,39 +536,29 @@ public: // Now carol's offer consumes bob's and partially crosses // alice's. The tfSell flag is important. std::uint32_t const carolOfferSeq = env.seq(carol); - env(offer(carol, carolOffer.in, carolOffer.out), - txflags(tfSell)); + env(offer(carol, carolOffer.in, carolOffer.out), txflags(tfSell)); env.close(); // carol's offer should not have made it into the ledger and // bob's offer should be fully consumed. - if (!BEAST_EXPECT( - !offerInLedger(env, carol, carolOfferSeq) && - !offerInLedger(env, bob, bobOfferSeq))) + if (!BEAST_EXPECT(!offerInLedger(env, carol, carolOfferSeq) && !offerInLedger(env, bob, bobOfferSeq))) { // If carol's or bob's offers are still in the ledger then // further results are meaningless. - cleanupOldOffers( - env, - {{alice, aliceOfferSeq}, - {bob, bobOfferSeq}, - {carol, carolOfferSeq}}); + cleanupOldOffers(env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}, {carol, carolOfferSeq}}); return 1; } // alice's offer should still be in the ledger, but reduced in // size. unsigned int badRate = 1; { - Json::Value aliceOffer = - ledgerEntryOffer(env, alice, aliceOfferSeq); + Json::Value aliceOffer = ledgerEntryOffer(env, alice, aliceOfferSeq); - Amounts aliceReducedOffer = - jsonOfferToAmounts(aliceOffer[jss::node]); + Amounts aliceReducedOffer = jsonOfferToAmounts(aliceOffer[jss::node]); BEAST_EXPECT(aliceReducedOffer.in < aliceInitialOffer.in); BEAST_EXPECT(aliceReducedOffer.out < aliceInitialOffer.out); - STAmount const inLedgerRate = - Quality(aliceReducedOffer).rate(); + STAmount const inLedgerRate = Quality(aliceReducedOffer).rate(); badRate = inLedgerRate > initialRate ? 1 : 0; // If the inLedgerRate is less than initial rate, then @@ -648,10 +573,7 @@ public: aliceReducedOffer.in.mantissa() + 1, aliceReducedOffer.in.exponent(), aliceReducedOffer.in.negative()); - STAmount const tweakedRate = - Quality( - Amounts{aliceReducedOffer.in, tweakedTakerGets}) - .rate(); + STAmount const tweakedRate = Quality(Amounts{aliceReducedOffer.in, tweakedTakerGets}).rate(); BEAST_EXPECT(tweakedRate > initialRate); } #if 0 @@ -671,11 +593,7 @@ public: // In preparation for the next iteration make sure all three // offers are gone from the ledger. - cleanupOldOffers( - env, - {{alice, aliceOfferSeq}, - {bob, bobOfferSeq}, - {carol, carolOfferSeq}}); + cleanupOldOffers(env, {{alice, aliceOfferSeq}, {bob, bobOfferSeq}, {carol, carolOfferSeq}}); return badRate; }; @@ -686,8 +604,7 @@ public: STAmount const step(increaseGets.issue(), 1, -8); for (unsigned int i = 0; i < loopCount; ++i) { - blockedCount += exerciseOfferTrio( - Amounts(drops(1642020), USD(1) + increaseGets)); + blockedCount += exerciseOfferTrio(Amounts(drops(1642020), USD(1) + increaseGets)); increaseGets += step; } } diff --git a/src/test/app/Regression_test.cpp b/src/test/app/Regression_test.cpp index 56f0de9e07..052b334ef5 100644 --- a/src/test/app/Regression_test.cpp +++ b/src/test/app/Regression_test.cpp @@ -45,25 +45,20 @@ struct Regression_test : public beast::unit_test::suite // be reproduced against an open ledger. Make a local // closed ledger and work with it directly. auto closed = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); auto expectedDrops = INITIAL_XRP; BEAST_EXPECT(closed->header().drops == expectedDrops); auto const aliceXRP = 400; auto const aliceAmount = XRP(aliceXRP); - auto next = std::make_shared( - *closed, env.app().timeKeeper().closeTime()); + auto next = std::make_shared(*closed, env.app().timeKeeper().closeTime()); { // Fund alice auto const jt = env.jt(pay(env.master, "alice", aliceAmount)); OpenView accum(&*next); - auto const result = - xrpl::apply(env.app(), accum, *jt.stx, tapNONE, env.journal); + auto const result = xrpl::apply(env.app(), accum, *jt.stx, tapNONE, env.journal); BEAST_EXPECT(result.ter == tesSUCCESS); BEAST_EXPECT(result.applied); @@ -86,8 +81,7 @@ struct Regression_test : public beast::unit_test::suite OpenView accum(&*next); - auto const result = - xrpl::apply(env.app(), accum, *jt.stx, tapNONE, env.journal); + auto const result = xrpl::apply(env.app(), accum, *jt.stx, tapNONE, env.journal); BEAST_EXPECT(result.ter == tecINSUFF_FEE); BEAST_EXPECT(result.applied); @@ -115,8 +109,7 @@ struct Regression_test : public beast::unit_test::suite auto test256r1key = [&env](Account const& acct) { auto const baseFee = env.current()->fees().base; std::uint32_t const acctSeq = env.seq(acct); - Json::Value jsonNoop = - env.json(noop(acct), fee(baseFee), seq(acctSeq), sig(acct)); + Json::Value jsonNoop = env.json(noop(acct), fee(baseFee), seq(acctSeq), sig(acct)); JTx jt = env.jt(jsonNoop); jt.fill_sig = false; @@ -137,9 +130,7 @@ struct Regression_test : public beast::unit_test::suite secp256r1Sig->setFieldVL(sfSigningPubKey, *pubKeyBlob); jt.stx.reset(secp256r1Sig.release()); - env(jt, - rpc("invalidTransaction", - "fails local checks: Invalid signature.")); + env(jt, rpc("invalidTransaction", "fails local checks: Invalid signature.")); }; Account const alice{"alice", KeyType::secp256k1}; @@ -157,8 +148,7 @@ struct Regression_test : public beast::unit_test::suite testcase("Autofilled fee should use the escalated fee"); using namespace jtx; Env env(*this, envconfig([](std::unique_ptr cfg) { - cfg->section("transaction_queue") - .set("minimum_txn_in_ledger_standalone", "3"); + cfg->section("transaction_queue").set("minimum_txn_in_ledger_standalone", "3"); cfg->FEES.reference_fee = 10; return cfg; })); @@ -230,10 +220,8 @@ struct Regression_test : public beast::unit_test::suite std::vector buffers; buffers.emplace_back(buffer(request, 1024)); - buffers.emplace_back( - buffer(request.data() + 1024, request.length() - 1024)); - BEAST_EXPECT( - jrReader.parse(jvRequest, buffers) && jvRequest.isObject()); + buffers.emplace_back(buffer(request.data() + 1024, request.length() - 1024)); + BEAST_EXPECT(jrReader.parse(jvRequest, buffers) && jvRequest.isObject()); } void @@ -254,9 +242,7 @@ struct Regression_test : public beast::unit_test::suite auto const alice_index = keylet::account(alice).key; if (BEAST_EXPECT(alice_index.isNonZero())) { - env(check::cash( - alice, alice_index, check::DeliverMin(XRP(100))), - ter(tecNO_ENTRY)); + env(check::cash(alice, alice_index, check::DeliverMin(XRP(100))), ter(tecNO_ENTRY)); } } @@ -264,8 +250,7 @@ struct Regression_test : public beast::unit_test::suite auto const bob_index = keylet::account(bob).key; auto const digest = [&]() -> std::optional { - auto const& state = - env.app().getLedgerMaster().getClosedLedger()->stateMap(); + auto const& state = env.app().getLedgerMaster().getClosedLedger()->stateMap(); SHAMapHash digest; if (!state.peekItem(bob_index, digest)) return std::nullopt; @@ -282,30 +267,21 @@ struct Regression_test : public beast::unit_test::suite return result; }; - if (BEAST_EXPECT(bob_index.isNonZero()) && - BEAST_EXPECT(digest.has_value())) + if (BEAST_EXPECT(bob_index.isNonZero()) && BEAST_EXPECT(digest.has_value())) { auto& cache = env.app().cachedSLEs(); cache.del(*digest, false); - auto const beforeCounts = - mapCounts(CountedObjects::getInstance().getCounts(0)); + auto const beforeCounts = mapCounts(CountedObjects::getInstance().getCounts(0)); - env(check::cash(alice, bob_index, check::DeliverMin(XRP(100))), - ter(tecNO_ENTRY)); + env(check::cash(alice, bob_index, check::DeliverMin(XRP(100))), ter(tecNO_ENTRY)); - auto const afterCounts = - mapCounts(CountedObjects::getInstance().getCounts(0)); + auto const afterCounts = mapCounts(CountedObjects::getInstance().getCounts(0)); using namespace std::string_literals; + BEAST_EXPECT(beforeCounts.at("CachedView::hit"s) == afterCounts.at("CachedView::hit"s)); BEAST_EXPECT( - beforeCounts.at("CachedView::hit"s) == - afterCounts.at("CachedView::hit"s)); - BEAST_EXPECT( - beforeCounts.at("CachedView::hitExpired"s) + 1 == - afterCounts.at("CachedView::hitExpired"s)); - BEAST_EXPECT( - beforeCounts.at("CachedView::miss"s) == - afterCounts.at("CachedView::miss"s)); + beforeCounts.at("CachedView::hitExpired"s) + 1 == afterCounts.at("CachedView::hitExpired"s)); + BEAST_EXPECT(beforeCounts.at("CachedView::miss"s) == afterCounts.at("CachedView::miss"s)); } } } diff --git a/src/test/app/SHAMapStore_test.cpp b/src/test/app/SHAMapStore_test.cpp index d9689dc977..91845709c5 100644 --- a/src/test/app/SHAMapStore_test.cpp +++ b/src/test/app/SHAMapStore_test.cpp @@ -35,22 +35,16 @@ class SHAMapStore_test : public beast::unit_test::suite } bool - goodLedger( - jtx::Env& env, - Json::Value const& json, - std::string ledgerID, - bool checkDB = false) + goodLedger(jtx::Env& env, Json::Value const& json, std::string ledgerID, bool checkDB = false) { - auto good = json.isMember(jss::result) && - !RPC::contains_error(json[jss::result]) && + auto good = json.isMember(jss::result) && !RPC::contains_error(json[jss::result]) && json[jss::result][jss::ledger][jss::ledger_index] == ledgerID; if (!good || !checkDB) return good; auto const seq = json[jss::result][jss::ledger_index].asUInt(); - std::optional oinfo = - env.app().getRelationalDatabase().getLedgerInfoByIndex(seq); + std::optional oinfo = env.app().getRelationalDatabase().getLedgerInfoByIndex(seq); if (!oinfo) return false; LedgerHeader const& info = oinfo.value(); @@ -59,25 +53,19 @@ class SHAMapStore_test : public beast::unit_test::suite LedgerIndex const outSeq = info.seq; std::string const outParentHash = to_string(info.parentHash); std::string const outDrops = to_string(info.drops); - std::uint64_t const outCloseTime = - info.closeTime.time_since_epoch().count(); - std::uint64_t const outParentCloseTime = - info.parentCloseTime.time_since_epoch().count(); - std::uint64_t const outCloseTimeResolution = - info.closeTimeResolution.count(); + std::uint64_t const outCloseTime = info.closeTime.time_since_epoch().count(); + std::uint64_t const outParentCloseTime = info.parentCloseTime.time_since_epoch().count(); + std::uint64_t const outCloseTimeResolution = info.closeTimeResolution.count(); std::uint64_t const outCloseFlags = info.closeFlags; std::string const outAccountHash = to_string(info.accountHash); std::string const outTxHash = to_string(info.txHash); auto const& ledger = json[jss::result][jss::ledger]; - return outHash == ledger[jss::ledger_hash].asString() && - outSeq == seq && - outParentHash == ledger[jss::parent_hash].asString() && - outDrops == ledger[jss::total_coins].asString() && + return outHash == ledger[jss::ledger_hash].asString() && outSeq == seq && + outParentHash == ledger[jss::parent_hash].asString() && outDrops == ledger[jss::total_coins].asString() && outCloseTime == ledger[jss::close_time].asUInt() && outParentCloseTime == ledger[jss::parent_close_time].asUInt() && - outCloseTimeResolution == - ledger[jss::close_time_resolution].asUInt() && + outCloseTimeResolution == ledger[jss::close_time_resolution].asUInt() && outCloseFlags == ledger[jss::close_flags].asUInt() && outAccountHash == ledger[jss::account_hash].asString() && outTxHash == ledger[jss::transaction_hash].asString(); @@ -86,8 +74,7 @@ class SHAMapStore_test : public beast::unit_test::suite bool bad(Json::Value const& json, error_code_i error = rpcLGR_NOT_FOUND) { - return json.isMember(jss::result) && - RPC::contains_error(json[jss::result]) && + return json.isMember(jss::result) && RPC::contains_error(json[jss::result]) && json[jss::result][jss::error_code] == error; } @@ -95,8 +82,7 @@ class SHAMapStore_test : public beast::unit_test::suite getHash(Json::Value const& json) { BEAST_EXPECT( - json.isMember(jss::result) && - json[jss::result].isMember(jss::ledger) && + json.isMember(jss::result) && json[jss::result].isMember(jss::ledger) && json[jss::result][jss::ledger].isMember(jss::ledger_hash) && json[jss::result][jss::ledger][jss::ledger_hash].isString()); return json[jss::result][jss::ledger][jss::ledger_hash].asString(); @@ -106,8 +92,7 @@ class SHAMapStore_test : public beast::unit_test::suite ledgerCheck(jtx::Env& env, int const rows, int const first) { auto const [actualRows, actualFirst, actualLast] = - dynamic_cast(&env.app().getRelationalDatabase()) - ->getLedgerCountMinMax(); + dynamic_cast(&env.app().getRelationalDatabase())->getLedgerCountMinMax(); BEAST_EXPECT(actualRows == rows); BEAST_EXPECT(actualFirst == first); @@ -117,17 +102,14 @@ class SHAMapStore_test : public beast::unit_test::suite void transactionCheck(jtx::Env& env, int const rows) { - BEAST_EXPECT( - dynamic_cast(&env.app().getRelationalDatabase()) - ->getTransactionCount() == rows); + BEAST_EXPECT(dynamic_cast(&env.app().getRelationalDatabase())->getTransactionCount() == rows); } void accountTransactionCheck(jtx::Env& env, int const rows) { BEAST_EXPECT( - dynamic_cast(&env.app().getRelationalDatabase()) - ->getAccountTransactionCount() == rows); + dynamic_cast(&env.app().getRelationalDatabase())->getAccountTransactionCount() == rows); } int @@ -204,11 +186,8 @@ public: for (auto i = 3; i < deleteInterval + lastRotated; ++i) { - ledgers.emplace( - std::make_pair(i, env.rpc("ledger", std::to_string(i)))); - BEAST_EXPECT( - goodLedger(env, ledgers[i], std::to_string(i), true) && - getHash(ledgers[i]).length()); + ledgers.emplace(std::make_pair(i, env.rpc("ledger", std::to_string(i)))); + BEAST_EXPECT(goodLedger(env, ledgers[i], std::to_string(i), true) && getHash(ledgers[i]).length()); } ledgerCheck(env, deleteInterval + 1, 2); @@ -220,8 +199,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "current"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(deleteInterval + 4))); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(deleteInterval + 4))); } store.rendezvous(); @@ -236,22 +214,16 @@ public: accountTransactionCheck(env, 2 * deleteInterval); // The last iteration of this loop should trigger a rotate - for (auto i = lastRotated - 1; i < lastRotated + deleteInterval - 1; - ++i) + for (auto i = lastRotated - 1; i < lastRotated + deleteInterval - 1; ++i) { env.close(); ledgerTmp = env.rpc("ledger", "current"); BEAST_EXPECT(goodLedger(env, ledgerTmp, std::to_string(i + 3))); - ledgers.emplace( - std::make_pair(i, env.rpc("ledger", std::to_string(i)))); - BEAST_EXPECT( - store.getLastRotated() == lastRotated || - i == lastRotated + deleteInterval - 2); - BEAST_EXPECT( - goodLedger(env, ledgers[i], std::to_string(i), true) && - getHash(ledgers[i]).length()); + ledgers.emplace(std::make_pair(i, env.rpc("ledger", std::to_string(i)))); + BEAST_EXPECT(store.getLastRotated() == lastRotated || i == lastRotated + deleteInterval - 2); + BEAST_EXPECT(goodLedger(env, ledgers[i], std::to_string(i), true) && getHash(ledgers[i]).length()); } store.rendezvous(); @@ -289,8 +261,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq), true)); } store.rendezvous(); @@ -305,8 +276,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); } store.rendezvous(); @@ -322,8 +292,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq), true)); } store.rendezvous(); @@ -362,8 +331,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq), true)); } store.rendezvous(); @@ -372,12 +340,9 @@ public: BEAST_EXPECT(lastRotated == store.getLastRotated()); // This does not kick off a cleanup - canDelete = env.rpc( - "can_delete", std::to_string(ledgerSeq + deleteInterval / 2)); + canDelete = env.rpc("can_delete", std::to_string(ledgerSeq + deleteInterval / 2)); BEAST_EXPECT(!RPC::contains_error(canDelete[jss::result])); - BEAST_EXPECT( - canDelete[jss::result][jss::can_delete] == - ledgerSeq + deleteInterval / 2); + BEAST_EXPECT(canDelete[jss::result][jss::can_delete] == ledgerSeq + deleteInterval / 2); store.rendezvous(); @@ -389,8 +354,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); } store.rendezvous(); @@ -406,8 +370,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq), true)); } store.rendezvous(); @@ -419,8 +382,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); } store.rendezvous(); @@ -433,9 +395,7 @@ public: // This does not kick off a cleanup canDelete = env.rpc("can_delete", "always"); BEAST_EXPECT(!RPC::contains_error(canDelete[jss::result])); - BEAST_EXPECT( - canDelete[jss::result][jss::can_delete] == - std::numeric_limits::max()); + BEAST_EXPECT(canDelete[jss::result][jss::can_delete] == std::numeric_limits::max()); for (; ledgerSeq < lastRotated + deleteInterval; ++ledgerSeq) { @@ -443,8 +403,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq), true)); } store.rendezvous(); @@ -456,8 +415,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); } store.rendezvous(); @@ -478,8 +436,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq), true)); } store.rendezvous(); @@ -491,8 +448,7 @@ public: env.close(); auto ledger = env.rpc("ledger", "validated"); - BEAST_EXPECT( - goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); + BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq++), true)); } store.rendezvous(); @@ -504,13 +460,9 @@ public: } std::unique_ptr - makeBackendRotating( - jtx::Env& env, - NodeStoreScheduler& scheduler, - std::string path) + makeBackendRotating(jtx::Env& env, NodeStoreScheduler& scheduler, std::string path) { - Section section{ - env.app().config().section(ConfigSection::nodeDatabase())}; + Section section{env.app().config().section(ConfigSection::nodeDatabase())}; boost::filesystem::path newPath; if (!BEAST_EXPECT(path.size())) @@ -520,8 +472,7 @@ public: auto backend{NodeStore::Manager::instance().make_Backend( section, - megabytes(env.app().config().getValueFor( - SizedItem::burstSize, std::nullopt)), + megabytes(env.app().config().getValueFor(SizedItem::burstSize, std::nullopt)), scheduler, env.app().logs().journal("NodeStoreTest"))}; backend->open(); @@ -546,15 +497,11 @@ public: // Provide default values: if (!nscfg.exists("cache_size")) nscfg.set( - "cache_size", - std::to_string(env.app().config().getValueFor( - SizedItem::treeCacheSize, std::nullopt))); + "cache_size", std::to_string(env.app().config().getValueFor(SizedItem::treeCacheSize, std::nullopt))); if (!nscfg.exists("cache_age")) nscfg.set( - "cache_age", - std::to_string(env.app().config().getValueFor( - SizedItem::treeCacheAge, std::nullopt))); + "cache_age", std::to_string(env.app().config().getValueFor(SizedItem::treeCacheAge, std::nullopt))); NodeStoreScheduler scheduler(env.app().getJobQueue()); @@ -580,11 +527,9 @@ public: std::atomic threadNum = 0; { - auto newBackend = makeBackendRotating( - env, scheduler, std::to_string(++threadNum)); + auto newBackend = makeBackendRotating(env, scheduler, std::to_string(++threadNum)); - auto const cb = [&](std::string const& writableName, - std::string const& archiveName) { + auto const cb = [&](std::string const& writableName, std::string const& archiveName) { BEAST_EXPECT(writableName == "1"); BEAST_EXPECT(archiveName == "write"); // Ensure that dbr functions can be called from within the @@ -600,25 +545,21 @@ public: ///////////////////////////////////////////////////////////// // Do something stupid. Try to re-enter rotate from inside the callback. { - auto const cb = [&](std::string const& writableName, - std::string const& archiveName) { + auto const cb = [&](std::string const& writableName, std::string const& archiveName) { BEAST_EXPECT(writableName == "3"); BEAST_EXPECT(archiveName == "2"); // Ensure that dbr functions can be called from within the // callback BEAST_EXPECT(dbr->getName() == "3"); }; - auto const cbReentrant = [&](std::string const& writableName, - std::string const& archiveName) { + auto const cbReentrant = [&](std::string const& writableName, std::string const& archiveName) { BEAST_EXPECT(writableName == "2"); BEAST_EXPECT(archiveName == "1"); - auto newBackend = makeBackendRotating( - env, scheduler, std::to_string(++threadNum)); + auto newBackend = makeBackendRotating(env, scheduler, std::to_string(++threadNum)); // Reminder: doing this is stupid and should never happen dbr->rotate(std::move(newBackend), cb); }; - auto newBackend = makeBackendRotating( - env, scheduler, std::to_string(++threadNum)); + auto newBackend = makeBackendRotating(env, scheduler, std::to_string(++threadNum)); dbr->rotate(std::move(newBackend), cbReentrant); } diff --git a/src/test/app/SetAuth_test.cpp b/src/test/app/SetAuth_test.cpp index 29f1e46ca4..400e2b0e29 100644 --- a/src/test/app/SetAuth_test.cpp +++ b/src/test/app/SetAuth_test.cpp @@ -12,16 +12,12 @@ struct SetAuth_test : public beast::unit_test::suite // If the trust line does not exist, then it should // be created under the new rules. static Json::Value - auth( - jtx::Account const& account, - jtx::Account const& dest, - std::string const& currency) + auth(jtx::Account const& account, jtx::Account const& dest, std::string const& currency) { using namespace jtx; Json::Value jv; jv[jss::Account] = account.human(); - jv[jss::LimitAmount] = STAmount(Issue{to_currency(currency), dest}) - .getJson(JsonOptions::none); + jv[jss::LimitAmount] = STAmount(Issue{to_currency(currency), dest}).getJson(JsonOptions::none); jv[jss::TransactionType] = jss::TrustSet; jv[jss::Flags] = tfSetfAuth; return jv; @@ -40,8 +36,7 @@ struct SetAuth_test : public beast::unit_test::suite env(fset(gw, asfRequireAuth)); env.close(); env(auth(gw, "alice", "USD")); - BEAST_EXPECT( - env.le(keylet::line(Account("alice").id(), gw.id(), USD.currency))); + BEAST_EXPECT(env.le(keylet::line(Account("alice").id(), gw.id(), USD.currency))); env(trust("alice", USD(1000))); env(trust("bob", USD(1000))); env(pay(gw, "alice", USD(100))); diff --git a/src/test/app/SetRegularKey_test.cpp b/src/test/app/SetRegularKey_test.cpp index 308e5527f7..aec8dddc7a 100644 --- a/src/test/app/SetRegularKey_test.cpp +++ b/src/test/app/SetRegularKey_test.cpp @@ -28,9 +28,7 @@ public: env(noop(alice), sig(alice), ter(tefMASTER_DISABLED)); testcase("Re-enable master key"); - env(fclear(alice, asfDisableMaster), - sig(alice), - ter(tefMASTER_DISABLED)); + env(fclear(alice, asfDisableMaster), sig(alice), ter(tefMASTER_DISABLED)); env(fclear(alice, asfDisableMaster), sig(bob)); env(noop(alice), sig(bob)); @@ -67,17 +65,13 @@ public: env.fund(XRP(10000), alice, bob); auto ar = env.le(alice); - BEAST_EXPECT( - ar->isFieldPresent(sfFlags) && - ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == 0)); + BEAST_EXPECT(ar->isFieldPresent(sfFlags) && ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == 0)); env(regkey(alice, bob), sig(alice), fee(0)); ar = env.le(alice); BEAST_EXPECT( - ar->isFieldPresent(sfFlags) && - ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == - lsfPasswordSpent)); + ar->isFieldPresent(sfFlags) && ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == lsfPasswordSpent)); // The second SetRegularKey transaction with Fee=0 should fail. env(regkey(alice, bob), sig(alice), fee(0), ter(telINSUF_FEE_P)); @@ -85,9 +79,7 @@ public: env.trust(bob["USD"](1), alice); env(pay(bob, alice, bob["USD"](1))); ar = env.le(alice); - BEAST_EXPECT( - ar->isFieldPresent(sfFlags) && - ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == 0)); + BEAST_EXPECT(ar->isFieldPresent(sfFlags) && ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == 0)); } void @@ -128,9 +120,7 @@ public: env.close(); // Disable alice's master key using a ticket. - env(fset(alice, asfDisableMaster), - sig(alice), - ticket::use(--ticketSeq)); + env(fset(alice, asfDisableMaster), sig(alice), ticket::use(--ticketSeq)); env.close(); // alice should be able to sign using the regular key but not the @@ -142,9 +132,7 @@ public: BEAST_EXPECT(env.seq(alice) == aliceSeq + 1); // Re-enable the master key using a ticket. - env(fclear(alice, asfDisableMaster), - sig(alie), - ticket::use(--ticketSeq)); + env(fclear(alice, asfDisableMaster), sig(alie), ticket::use(--ticketSeq)); env.close(); // Disable the regular key using a ticket. diff --git a/src/test/app/SetTrust_test.cpp b/src/test/app/SetTrust_test.cpp index f8309c4271..4704365550 100644 --- a/src/test/app/SetTrust_test.cpp +++ b/src/test/app/SetTrust_test.cpp @@ -13,8 +13,7 @@ public: void testTrustLineDelete() { - testcase( - "Test deletion of trust lines: revert trust line limit to zero"); + testcase("Test deletion of trust lines: revert trust line limit to zero"); using namespace jtx; Env env(*this); @@ -149,10 +148,7 @@ public: } void - testFreeTrustlines( - FeatureBitset features, - bool thirdLineCreatesLE, - bool createOnHighAcct) + testFreeTrustlines(FeatureBitset features, bool thirdLineCreatesLE, bool createOnHighAcct) { if (thirdLineCreatesLE) testcase("Allow two free trustlines"); @@ -188,20 +184,16 @@ public: if (thirdLineCreatesLE) { // creator does not have enough for the third trust line - env(trust(creator, assistor["USD"](100)), - ter(tecNO_LINE_INSUF_RESERVE), - require(lines(creator, 2))); + env(trust(creator, assistor["USD"](100)), ter(tecNO_LINE_INSUF_RESERVE), require(lines(creator, 2))); } else { // First establish opposite trust direction from assistor - env(trust(assistor, creator["USD"](100)), - require(lines(creator, 3))); + env(trust(assistor, creator["USD"](100)), require(lines(creator, 3))); // creator does not have enough to create the other direction on // the existing trust line ledger entry - env(trust(creator, assistor["USD"](100)), - ter(tecINSUF_RESERVE_LINE)); + env(trust(creator, assistor["USD"](100)), ter(tecINSUF_RESERVE_LINE)); } // Fund creator additional amount to cover @@ -209,13 +201,11 @@ public: if (thirdLineCreatesLE) { - env(trust(creator, assistor["USD"](100)), - require(lines(creator, 3))); + env(trust(creator, assistor["USD"](100)), require(lines(creator, 3))); } else { - env(trust(creator, assistor["USD"](100)), - require(lines(creator, 3))); + env(trust(creator, assistor["USD"](100)), require(lines(creator, 3))); Json::Value jv; jv["account"] = creator.human(); @@ -288,32 +278,23 @@ public: env.fund(XRP(10000), gw, alice); // Require valid tf flags - for (std::uint64_t badFlag = 1u; - badFlag <= std::numeric_limits::max(); - badFlag *= 2) + for (std::uint64_t badFlag = 1u; badFlag <= std::numeric_limits::max(); badFlag *= 2) { if (badFlag & tfTrustSetMask) - env(trust( - alice, - gw["USD"](100), - static_cast(badFlag)), - ter(temINVALID_FLAG)); + env(trust(alice, gw["USD"](100), static_cast(badFlag)), ter(temINVALID_FLAG)); } // trust amount can't be XRP env(trust_explicit_amt(alice, drops(10000)), ter(temBAD_LIMIT)); // trust amount can't be badCurrency IOU - env(trust_explicit_amt(alice, gw[to_string(badCurrency())](100)), - ter(temBAD_CURRENCY)); + env(trust_explicit_amt(alice, gw[to_string(badCurrency())](100)), ter(temBAD_CURRENCY)); // trust amount can't be negative env(trust(alice, gw["USD"](-1000)), ter(temBAD_LIMIT)); // trust amount can't be from invalid issuer - env(trust_explicit_amt( - alice, STAmount{Issue{to_currency("USD"), noAccount()}, 100}), - ter(temDST_NEEDED)); + env(trust_explicit_amt(alice, STAmount{Issue{to_currency("USD"), noAccount()}, 100}), ter(temDST_NEEDED)); // trust cannot be to self env(trust(alice, alice["USD"](100)), ter(temDST_IS_SRC)); @@ -417,13 +398,9 @@ public: } void - testModifyQualityOfTrustline( - FeatureBitset features, - bool createQuality, - bool createOnHighAcct) + testModifyQualityOfTrustline(FeatureBitset features, bool createQuality, bool createOnHighAcct) { - testcase << "SetTrust " << (createQuality ? "creates" : "removes") - << " quality of trustline for " + testcase << "SetTrust " << (createQuality ? "creates" : "removes") << " quality of trustline for " << (createOnHighAcct ? "high" : "low") << " account"; using namespace jtx; @@ -455,11 +432,8 @@ public: auto quality = exists ? 1000 : 0; BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); BEAST_EXPECT(lines[jss::result][jss::lines].size() == 1); - BEAST_EXPECT( - lines[jss::result][jss::lines][0u][jss::quality_in] == quality); - BEAST_EXPECT( - lines[jss::result][jss::lines][0u][jss::quality_out] == - quality); + BEAST_EXPECT(lines[jss::result][jss::lines][0u][jss::quality_in] == quality); + BEAST_EXPECT(lines[jss::result][jss::lines][0u][jss::quality_out] == quality); }; env(tx1, require(lines(toAcct, 1)), require(lines(fromAcct, 1))); @@ -480,8 +454,7 @@ public: { for (bool const withFix : {true, false}) { - auto const amend = - withFix ? features : features - fixDisallowIncomingV1; + auto const amend = withFix ? features : features - fixDisallowIncomingV1; Env env{*this, amend}; auto const dist = Account("dist"); @@ -503,15 +476,11 @@ public: // withFix: can set trustline // withOutFix: cannot set trustline - auto const trustResult = - withFix ? ter(tesSUCCESS) : ter(tecNO_PERMISSION); - env(trust(gw, distUSD(10000)), - txflags(tfSetfAuth), - trustResult); + auto const trustResult = withFix ? ter(tesSUCCESS) : ter(tecNO_PERMISSION); + env(trust(gw, distUSD(10000)), txflags(tfSetfAuth), trustResult); env.close(); - auto const txResult = - withFix ? ter(tesSUCCESS) : ter(tecPATH_DRY); + auto const txResult = withFix ? ter(tesSUCCESS) : ter(tecPATH_DRY); env(pay(gw, dist, USD(1000)), txResult); env.close(); } diff --git a/src/test/app/TheoreticalQuality_test.cpp b/src/test/app/TheoreticalQuality_test.cpp index ed4a62c4b0..1f626ad477 100644 --- a/src/test/app/TheoreticalQuality_test.cpp +++ b/src/test/app/TheoreticalQuality_test.cpp @@ -44,27 +44,18 @@ struct RippleCalcTestParams { if (pe.isMember(jss::account)) { - assert( - !pe.isMember(jss::currency) && - !pe.isMember(jss::issuer)); + assert(!pe.isMember(jss::currency) && !pe.isMember(jss::issuer)); p.emplace_back( - *parseBase58( - pe[jss::account].asString()), - std::nullopt, - std::nullopt); + *parseBase58(pe[jss::account].asString()), std::nullopt, std::nullopt); } - else if ( - pe.isMember(jss::currency) && pe.isMember(jss::issuer)) + else if (pe.isMember(jss::currency) && pe.isMember(jss::issuer)) { - auto const currency = - to_currency(pe[jss::currency].asString()); + auto const currency = to_currency(pe[jss::currency].asString()); std::optional issuer; if (!isXRP(currency)) - issuer = *parseBase58( - pe[jss::issuer].asString()); + issuer = *parseBase58(pe[jss::issuer].asString()); else - assert(isXRP(*parseBase58( - pe[jss::issuer].asString()))); + assert(isXRP(*parseBase58(pe[jss::issuer].asString()))); p.emplace_back(std::nullopt, currency, issuer); } else @@ -112,20 +103,14 @@ class RandomAccountParams return; auto const percent = qualityPercentDist_(engine_); - auto const& field = - qDir == QualityDirection::in ? sfQualityIn : sfQualityOut; - auto const value = - static_cast((percent / 100) * QUALITY_ONE); + auto const& field = qDir == QualityDirection::in ? sfQualityIn : sfQualityOut; + auto const value = static_cast((percent / 100) * QUALITY_ONE); jv[field.jsonName] = value; }; // Setup the trust amounts and in/out qualities (but not the balances) void - setupTrustLine( - jtx::Env& env, - jtx::Account const& acc, - jtx::Account const& peer, - Currency const& currency) + setupTrustLine(jtx::Env& env, jtx::Account const& acc, jtx::Account const& peer, Currency const& currency) { using namespace jtx; IOU const iou{peer, currency}; @@ -137,13 +122,9 @@ class RandomAccountParams }; public: - explicit RandomAccountParams( - std::uint32_t trustAmount = 100, - std::uint32_t initialBalance = 50) + explicit RandomAccountParams(std::uint32_t trustAmount = 100, std::uint32_t initialBalance = 50) // Use a deterministic seed so the unit tests run in a reproducible way - : engine_{1977u} - , trustAmount_{trustAmount} - , initialBalance_{initialBalance} {}; + : engine_{1977u}, trustAmount_{trustAmount}, initialBalance_{initialBalance} {}; void maybeSetTransferRate(jtx::Env& env, jtx::Account const& acc) @@ -154,29 +135,19 @@ public: // Set the initial balance, taking into account the qualities void - setInitialBalance( - jtx::Env& env, - jtx::Account const& acc, - jtx::Account const& peer, - Currency const& currency) + setInitialBalance(jtx::Env& env, jtx::Account const& acc, jtx::Account const& peer, Currency const& currency) { using namespace jtx; IOU const iou{acc, currency}; // This payment sets the acc's balance to `initialBalance`. // Since input qualities complicate this payment, use `sendMax` with // `initialBalance` to make sure the balance is set correctly. - env(pay(peer, acc, iou(trustAmount_)), - sendmax(iou(initialBalance_)), - txflags(tfPartialPayment)); + env(pay(peer, acc, iou(trustAmount_)), sendmax(iou(initialBalance_)), txflags(tfPartialPayment)); env.close(); } void - maybeSetInitialBalance( - jtx::Env& env, - jtx::Account const& acc, - jtx::Account const& peer, - Currency const& currency) + maybeSetInitialBalance(jtx::Env& env, jtx::Account const& acc, jtx::Account const& peer, Currency const& currency) { using namespace jtx; if (zeroOneDist_(engine_) > probRedeem_) @@ -187,11 +158,7 @@ public: // Setup the trust amounts and in/out qualities (but not the balances) on // both sides of the trust line void - setupTrustLines( - jtx::Env& env, - jtx::Account const& acc1, - jtx::Account const& acc2, - Currency const& currency) + setupTrustLines(jtx::Env& env, jtx::Account const& acc1, jtx::Account const& acc2, Currency const& currency) { setupTrustLine(env, acc1, acc2, currency); setupTrustLine(env, acc2, acc1, currency); @@ -270,8 +237,7 @@ class TheoreticalQuality_test : public beast::unit_test::suite for (auto const& strand : sr.second) { Quality const theoreticalQ = *qualityUpperBound(sb, strand); - auto const f = flow( - sb, strand, IOUAmount(10, 0), IOUAmount(5, 0), dummyJ); + auto const f = flow(sb, strand, IOUAmount(10, 0), IOUAmount(5, 0), dummyJ); BEAST_EXPECT(f.success); Quality const actualQ(f.out, f.in); if (actualQ != theoreticalQ && !compareClose(actualQ, theoreticalQ)) @@ -282,8 +248,7 @@ class TheoreticalQuality_test : public beast::unit_test::suite log << "AQ: " << prettyQuality(actualQ) << "\n"; logStrand(log, strand); } - if (expectedQ && expectedQ != theoreticalQ && - !compareClose(*expectedQ, theoreticalQ)) + if (expectedQ && expectedQ != theoreticalQ && !compareClose(*expectedQ, theoreticalQ)) { BEAST_EXPECT(expectedQ == theoreticalQ); // get the failure log << "\nExpected != Theoretical\n"; @@ -351,8 +316,7 @@ public: auto const carol = Account("carol" + iterAsStr); auto const dan = Account("dan" + iterAsStr); std::array accounts{{alice, bob, carol, dan}}; - static_assert( - numAccounts == 4, "Path is only correct for four accounts"); + static_assert(numAccounts == 4, "Path is only correct for four accounts"); path const accountsPath(accounts[1], accounts[2]); env.fund(XRP(10000), alice, bob, carol, dan); env.close(); @@ -370,18 +334,14 @@ public: if (j == numAccounts) continue; - rndAccParams.setupTrustLines( - env, accounts[ii], accounts[j], currency); - rndAccParams.maybeSetInitialBalance( - env, accounts[ii], accounts[j], currency); + rndAccParams.setupTrustLines(env, accounts[ii], accounts[j], currency); + rndAccParams.maybeSetInitialBalance(env, accounts[ii], accounts[j], currency); } // Accounts are set up, make the payment IOU const iou{accounts.back(), currency}; RippleCalcTestParams rcp{env.json( - pay(accounts.front(), accounts.back(), iou(paymentAmount)), - accountsPath, - txflags(tfNoRippleDirect))}; + pay(accounts.front(), accounts.back(), iou(paymentAmount)), accountsPath, txflags(tfNoRippleDirect))}; testCase(rcp, env.closed()); } @@ -427,8 +387,7 @@ public: auto const USDB = bob["USD"]; auto const EURC = carol["EUR"]; constexpr std::size_t const numAccounts = 5; - std::array accounts{ - {alice, bob, carol, dan, oscar}}; + std::array accounts{{alice, bob, carol, dan, oscar}}; // sendmax should be in USDB and delivered amount should be in EURC // normalized path should be: @@ -443,14 +402,10 @@ public: for (auto const& currency : {usdCurrency, eurCurrency}) { - rndAccParams.setupTrustLines( - env, alice, bob, currency); // first step in payment - rndAccParams.setupTrustLines( - env, carol, dan, currency); // last step in payment - rndAccParams.setupTrustLines( - env, oscar, bob, currency); // offer owner - rndAccParams.setupTrustLines( - env, oscar, carol, currency); // offer owner + rndAccParams.setupTrustLines(env, alice, bob, currency); // first step in payment + rndAccParams.setupTrustLines(env, carol, dan, currency); // last step in payment + rndAccParams.setupTrustLines(env, oscar, bob, currency); // offer owner + rndAccParams.setupTrustLines(env, oscar, carol, currency); // offer owner } rndAccParams.maybeSetInitialBalance(env, alice, bob, usdCurrency); @@ -479,8 +434,7 @@ public: { testcase("Relative quality distance"); - auto toQuality = [](std::uint64_t mantissa, - int exponent = 0) -> Quality { + auto toQuality = [](std::uint64_t mantissa, int exponent = 0) -> Quality { // The only way to construct a Quality from an STAmount is to take // their ratio. Set the denominator STAmount to `one` to easily // create a quality from a single amount @@ -492,18 +446,14 @@ public: BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100)) == 0); BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100, 1)) == 9); BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(110)) == .1); - BEAST_EXPECT( - relativeDistance(toQuality(100, 90), toQuality(110, 90)) == .1); - BEAST_EXPECT( - relativeDistance(toQuality(100, 90), toQuality(110, 91)) == 10); - BEAST_EXPECT( - relativeDistance(toQuality(100, 0), toQuality(100, 90)) == 1e90); + BEAST_EXPECT(relativeDistance(toQuality(100, 90), toQuality(110, 90)) == .1); + BEAST_EXPECT(relativeDistance(toQuality(100, 90), toQuality(110, 91)) == 10); + BEAST_EXPECT(relativeDistance(toQuality(100, 0), toQuality(100, 90)) == 1e90); // Make the mantissa in the smaller value bigger than the mantissa in // the larger value. Instead of checking the exact result, we check that // it's large. If the values did not compare correctly in // `relativeDistance`, then the returned value would be negative. - BEAST_EXPECT( - relativeDistance(toQuality(102, 0), toQuality(101, 90)) >= 1e89); + BEAST_EXPECT(relativeDistance(toQuality(102, 0), toQuality(101, 90)) >= 1e89); } void diff --git a/src/test/app/Ticket_test.cpp b/src/test/app/Ticket_test.cpp index 3136699103..0835c02289 100644 --- a/src/test/app/Ticket_test.cpp +++ b/src/test/app/Ticket_test.cpp @@ -19,19 +19,14 @@ class Ticket_test : public beast::unit_test::suite Json::Value const& tx{env.tx()->getJson(JsonOptions::none)}; { - std::string const txType = - tx[sfTransactionType.jsonName].asString(); + std::string const txType = tx[sfTransactionType.jsonName].asString(); - if (!BEAST_EXPECTS( - txType == jss::TicketCreate, - "Unexpected TransactionType: "s + txType)) + if (!BEAST_EXPECTS(txType == jss::TicketCreate, "Unexpected TransactionType: "s + txType)) return; } std::uint32_t const count = {tx[sfTicketCount.jsonName].asUInt()}; - if (!BEAST_EXPECTS( - count >= 1, - "Unexpected ticket count: "s + std::to_string(count))) + if (!BEAST_EXPECTS(count >= 1, "Unexpected ticket count: "s + std::to_string(count))) return; std::uint32_t const txSeq = {tx[sfSequence.jsonName].asUInt()}; @@ -40,8 +35,7 @@ class Ticket_test : public beast::unit_test::suite Json::Value const& metadata = env.meta()->getJson(JsonOptions::none); if (!BEAST_EXPECTS( metadata.isMember(sfTransactionResult.jsonName) && - metadata[sfTransactionResult.jsonName].asString() == - "tesSUCCESS", + metadata[sfTransactionResult.jsonName].asString() == "tesSUCCESS", "Not metadata for successful TicketCreate.")) return; @@ -57,20 +51,16 @@ class Ticket_test : public beast::unit_test::suite if (node.isMember(sfModifiedNode.jsonName)) { Json::Value const& modified = node[sfModifiedNode.jsonName]; - std::string const entryType = - modified[sfLedgerEntryType.jsonName].asString(); + std::string const entryType = modified[sfLedgerEntryType.jsonName].asString(); if (entryType == jss::AccountRoot) { - auto const& previousFields = - modified[sfPreviousFields.jsonName]; + auto const& previousFields = modified[sfPreviousFields.jsonName]; auto const& finalFields = modified[sfFinalFields.jsonName]; { // Verify the account root Sequence did the right thing. - std::uint32_t const prevSeq = - previousFields[sfSequence.jsonName].asUInt(); + std::uint32_t const prevSeq = previousFields[sfSequence.jsonName].asUInt(); - acctRootFinalSeq = - finalFields[sfSequence.jsonName].asUInt(); + acctRootFinalSeq = finalFields[sfSequence.jsonName].asUInt(); if (txSeq == 0) { @@ -81,13 +71,11 @@ class Ticket_test : public beast::unit_test::suite { // Transaction used a (plain) Sequence. BEAST_EXPECT(prevSeq == txSeq); - BEAST_EXPECT( - acctRootFinalSeq == prevSeq + count + 1); + BEAST_EXPECT(acctRootFinalSeq == prevSeq + count + 1); } } - std::uint32_t const consumedTickets = { - txSeq == 0u ? 1u : 0u}; + std::uint32_t const consumedTickets = {txSeq == 0u ? 1u : 0u}; // If... // 1. The TicketCount is 1 and @@ -96,28 +84,23 @@ class Ticket_test : public beast::unit_test::suite // previous TicketCount is not reported. // But, since the count did not change, we know it equals // the final Ticket count. - bool const unreportedPrevTicketCount = { - count == 1 && txSeq == 0}; + bool const unreportedPrevTicketCount = {count == 1 && txSeq == 0}; // Verify the OwnerCount did the right thing if (unreportedPrevTicketCount) { // The number of Tickets should not have changed, so // the previous OwnerCount should not be reported. - BEAST_EXPECT( - !previousFields.isMember(sfOwnerCount.jsonName)); + BEAST_EXPECT(!previousFields.isMember(sfOwnerCount.jsonName)); } else { // Verify the OwnerCount did the right thing. - std::uint32_t const prevCount = { - previousFields[sfOwnerCount.jsonName].asUInt()}; + std::uint32_t const prevCount = {previousFields[sfOwnerCount.jsonName].asUInt()}; - std::uint32_t const finalCount = { - finalFields[sfOwnerCount.jsonName].asUInt()}; + std::uint32_t const finalCount = {finalFields[sfOwnerCount.jsonName].asUInt()}; - BEAST_EXPECT( - prevCount + count - consumedTickets == finalCount); + BEAST_EXPECT(prevCount + count - consumedTickets == finalCount); } // Verify TicketCount metadata. @@ -127,8 +110,7 @@ class Ticket_test : public beast::unit_test::suite { // The number of Tickets should not have changed, so // the previous TicketCount should not be reported. - BEAST_EXPECT( - !previousFields.isMember(sfTicketCount.jsonName)); + BEAST_EXPECT(!previousFields.isMember(sfTicketCount.jsonName)); } else { @@ -136,17 +118,12 @@ class Ticket_test : public beast::unit_test::suite // should have been greater than zero. std::uint32_t const startCount = { previousFields.isMember(sfTicketCount.jsonName) - ? previousFields[sfTicketCount.jsonName] - .asUInt() + ? previousFields[sfTicketCount.jsonName].asUInt() : 0u}; - BEAST_EXPECT( - (startCount == 0u) ^ - previousFields.isMember(sfTicketCount.jsonName)); + BEAST_EXPECT((startCount == 0u) ^ previousFields.isMember(sfTicketCount.jsonName)); - BEAST_EXPECT( - startCount + count - consumedTickets == - finalFields[sfTicketCount.jsonName]); + BEAST_EXPECT(startCount + count - consumedTickets == finalFields[sfTicketCount.jsonName]); } } else if (entryType == jss::DirectoryNode) @@ -155,25 +132,19 @@ class Ticket_test : public beast::unit_test::suite } else { - fail( - "Unexpected modified node: "s + entryType, - __FILE__, - __LINE__); + fail("Unexpected modified node: "s + entryType, __FILE__, __LINE__); } } else if (node.isMember(sfCreatedNode.jsonName)) { Json::Value const& created = node[sfCreatedNode.jsonName]; - std::string const entryType = - created[sfLedgerEntryType.jsonName].asString(); + std::string const entryType = created[sfLedgerEntryType.jsonName].asString(); if (entryType == jss::Ticket) { auto const& newFields = created[sfNewFields.jsonName]; - BEAST_EXPECT( - newFields[sfAccount.jsonName].asString() == account); - ticketSeqs.push_back( - newFields[sfTicketSequence.jsonName].asUInt()); + BEAST_EXPECT(newFields[sfAccount.jsonName].asString() == account); + ticketSeqs.push_back(newFields[sfTicketSequence.jsonName].asUInt()); } else if (entryType == jss::DirectoryNode) { @@ -181,17 +152,13 @@ class Ticket_test : public beast::unit_test::suite } else { - fail( - "Unexpected created node: "s + entryType, - __FILE__, - __LINE__); + fail("Unexpected created node: "s + entryType, __FILE__, __LINE__); } } else if (node.isMember(sfDeletedNode.jsonName)) { Json::Value const& deleted = node[sfDeletedNode.jsonName]; - std::string const entryType = - deleted[sfLedgerEntryType.jsonName].asString(); + std::string const entryType = deleted[sfLedgerEntryType.jsonName].asString(); if (entryType == jss::Ticket) { @@ -200,21 +167,16 @@ class Ticket_test : public beast::unit_test::suite // Verify the account of the deleted ticket. auto const& finalFields = deleted[sfFinalFields.jsonName]; - BEAST_EXPECT( - finalFields[sfAccount.jsonName].asString() == account); + BEAST_EXPECT(finalFields[sfAccount.jsonName].asString() == account); // Verify the deleted ticket has the right TicketSequence. BEAST_EXPECT( - finalFields[sfTicketSequence.jsonName].asUInt() == - tx[sfTicketSequence.jsonName].asUInt()); + finalFields[sfTicketSequence.jsonName].asUInt() == tx[sfTicketSequence.jsonName].asUInt()); } } else { - fail( - "Unexpected node type in TicketCreate metadata.", - __FILE__, - __LINE__); + fail("Unexpected node type in TicketCreate metadata.", __FILE__, __LINE__); } } BEAST_EXPECT(directoryChanged); @@ -222,9 +184,7 @@ class Ticket_test : public beast::unit_test::suite // Verify that all the expected Tickets were created. BEAST_EXPECT(ticketSeqs.size() == count); std::sort(ticketSeqs.begin(), ticketSeqs.end()); - BEAST_EXPECT( - std::adjacent_find(ticketSeqs.begin(), ticketSeqs.end()) == - ticketSeqs.end()); + BEAST_EXPECT(std::adjacent_find(ticketSeqs.begin(), ticketSeqs.end()) == ticketSeqs.end()); BEAST_EXPECT(*ticketSeqs.rbegin() == acctRootFinalSeq - 1); } @@ -262,25 +222,19 @@ class Ticket_test : public beast::unit_test::suite // was deleted. BEAST_EXPECT(tx[sfSequence.jsonName].asUInt() == 0); std::string const account{tx[sfAccount.jsonName].asString()}; - if (!BEAST_EXPECTS( - tx.isMember(sfTicketSequence.jsonName), - "Not metadata for a ticket consuming transaction.")) + if (!BEAST_EXPECTS(tx.isMember(sfTicketSequence.jsonName), "Not metadata for a ticket consuming transaction.")) return; std::uint32_t const ticketSeq{tx[sfTicketSequence.jsonName].asUInt()}; Json::Value const& metadata{env.meta()->getJson(JsonOptions::none)}; - if (!BEAST_EXPECTS( - metadata.isMember(sfTransactionResult.jsonName), - "Metadata is missing TransactionResult.")) + if (!BEAST_EXPECTS(metadata.isMember(sfTransactionResult.jsonName), "Metadata is missing TransactionResult.")) return; { - std::string const transactionResult{ - metadata[sfTransactionResult.jsonName].asString()}; + std::string const transactionResult{metadata[sfTransactionResult.jsonName].asString()}; if (!BEAST_EXPECTS( - transactionResult == "tesSUCCESS" || - transactionResult.compare(0, 3, "tec") == 0, + transactionResult == "tesSUCCESS" || transactionResult.compare(0, 3, "tec") == 0, transactionResult + " neither tesSUCCESS nor tec")) return; } @@ -296,16 +250,13 @@ class Ticket_test : public beast::unit_test::suite if (node.isMember(sfModifiedNode.jsonName)) { Json::Value const& modified{node[sfModifiedNode.jsonName]}; - std::string const entryType = - modified[sfLedgerEntryType.jsonName].asString(); + std::string const entryType = modified[sfLedgerEntryType.jsonName].asString(); if (entryType == "AccountRoot" && - modified[sfFinalFields.jsonName][sfAccount.jsonName] - .asString() == account) + modified[sfFinalFields.jsonName][sfAccount.jsonName].asString() == account) { acctRootFound = true; - auto const& previousFields = - modified[sfPreviousFields.jsonName]; + auto const& previousFields = modified[sfPreviousFields.jsonName]; auto const& finalFields = modified[sfFinalFields.jsonName]; acctRootSeq = finalFields[sfSequence.jsonName].asUInt(); @@ -318,38 +269,29 @@ class Ticket_test : public beast::unit_test::suite "AccountRoot previous is missing TicketCount")) return; - std::uint32_t const prevTicketCount = - previousFields[sfTicketCount.jsonName].asUInt(); + std::uint32_t const prevTicketCount = previousFields[sfTicketCount.jsonName].asUInt(); BEAST_EXPECT(prevTicketCount > 0); if (prevTicketCount == 1) - BEAST_EXPECT( - !finalFields.isMember(sfTicketCount.jsonName)); + BEAST_EXPECT(!finalFields.isMember(sfTicketCount.jsonName)); else BEAST_EXPECT( finalFields.isMember(sfTicketCount.jsonName) && - finalFields[sfTicketCount.jsonName].asUInt() == - prevTicketCount - 1); + finalFields[sfTicketCount.jsonName].asUInt() == prevTicketCount - 1); } } else if (node.isMember(sfDeletedNode.jsonName)) { Json::Value const& deleted{node[sfDeletedNode.jsonName]}; - std::string const entryType{ - deleted[sfLedgerEntryType.jsonName].asString()}; + std::string const entryType{deleted[sfLedgerEntryType.jsonName].asString()}; if (entryType == jss::Ticket) { // Verify the account of the deleted ticket. - BEAST_EXPECT( - deleted[sfFinalFields.jsonName][sfAccount.jsonName] - .asString() == account); + BEAST_EXPECT(deleted[sfFinalFields.jsonName][sfAccount.jsonName].asString() == account); // Verify the deleted ticket has the right TicketSequence. - BEAST_EXPECT( - deleted[sfFinalFields.jsonName] - [sfTicketSequence.jsonName] - .asUInt() == ticketSeq); + BEAST_EXPECT(deleted[sfFinalFields.jsonName][sfTicketSequence.jsonName].asUInt() == ticketSeq); ++ticketsRemoved; } @@ -419,9 +361,7 @@ class Ticket_test : public beast::unit_test::suite Account alice{"alice"}; env.memoize(alice); - env(ticket::create(alice, 1), - json(jss::Sequence, 1), - ter(terNO_ACCOUNT)); + env(ticket::create(alice, 1), json(jss::Sequence, 1), ter(terNO_ACCOUNT)); } { // Exceed the threshold where tickets can no longer be @@ -445,9 +385,7 @@ class Ticket_test : public beast::unit_test::suite env.require(owners(alice, 250), tickets(alice, 250)); // Adding one more ticket will exceed the threshold. - env(ticket::create(alice, 2), - ticket::use(ticketSeq + 1), - ter(tecDIR_FULL)); + env(ticket::create(alice, 2), ticket::use(ticketSeq + 1), ter(tecDIR_FULL)); env.close(); env.require(owners(alice, 249), tickets(alice, 249)); @@ -479,9 +417,7 @@ class Ticket_test : public beast::unit_test::suite // Adding 250 tickets (while consuming one) will exceed the // threshold. - env(ticket::create(alice, 250), - ticket::use(ticketSeq_AB + 0), - ter(tecDIR_FULL)); + env(ticket::create(alice, 250), ticket::use(ticketSeq_AB + 0), ter(tecDIR_FULL)); env.close(); env.require(owners(alice, 1), tickets(alice, 1)); @@ -517,10 +453,7 @@ class Ticket_test : public beast::unit_test::suite env.require(owners(alice, 0), tickets(alice, 0)); // Give alice enough to exactly meet the reserve for one Ticket. - env( - pay(env.master, - alice, - env.current()->fees().accountReserve(1) - env.balance(alice))); + env(pay(env.master, alice, env.current()->fees().accountReserve(1) - env.balance(alice))); env.close(); env(ticket::create(alice, 1)); @@ -530,11 +463,7 @@ class Ticket_test : public beast::unit_test::suite // Give alice not quite enough to make the reserve for a total of // 250 Tickets. - env( - pay(env.master, - alice, - env.current()->fees().accountReserve(250) - drops(1) - - env.balance(alice))); + env(pay(env.master, alice, env.current()->fees().accountReserve(250) - drops(1) - env.balance(alice))); env.close(); // alice doesn't quite have the reserve for a total of 250 @@ -545,10 +474,7 @@ class Ticket_test : public beast::unit_test::suite // Give alice enough so she can make the reserve for all 250 // Tickets. - env(pay( - env.master, - alice, - env.current()->fees().accountReserve(250) - env.balance(alice))); + env(pay(env.master, alice, env.current()->fees().accountReserve(250) - env.balance(alice))); env.close(); std::uint32_t const ticketSeq{env.seq(alice) + 1}; @@ -637,10 +563,7 @@ class Ticket_test : public beast::unit_test::suite checkTicketCreateMeta(env); env.close(); - env(noop(alice), - ticket::use(ticketSeq_G), - json(R"({"AccountTxnID": "0"})"), - ter(temINVALID)); + env(noop(alice), ticket::use(ticketSeq_G), json(R"({"AccountTxnID": "0"})"), ter(temINVALID)); env.close(); env.require(owners(alice, 2), tickets(alice, 1)); } @@ -733,10 +656,8 @@ class Ticket_test : public beast::unit_test::suite TxType txType) { error_code_i txErrCode{rpcSUCCESS}; - using TxPair = std:: - pair, std::shared_ptr>; - std::variant maybeTx = - Transaction::load(txID, env.app(), txErrCode); + using TxPair = std::pair, std::shared_ptr>; + std::variant maybeTx = Transaction::load(txID, env.app(), txErrCode); BEAST_EXPECT(txErrCode == rpcSUCCESS); if (auto txPtr = std::get_if(&maybeTx)) @@ -810,11 +731,9 @@ class Ticket_test : public beast::unit_test::suite Json::Value jr = env.rpc("json", "sign", to_string(tx)); // Verify that "sign" inserted a "Sequence": 0 field. - if (BEAST_EXPECT(jr[jss::result][jss::tx_json].isMember( - sfSequence.jsonName))) + if (BEAST_EXPECT(jr[jss::result][jss::tx_json].isMember(sfSequence.jsonName))) { - BEAST_EXPECT( - jr[jss::result][jss::tx_json][sfSequence.jsonName] == 0); + BEAST_EXPECT(jr[jss::result][jss::tx_json][sfSequence.jsonName] == 0); } // "sign" should not have consumed any of alice's tickets. @@ -845,11 +764,9 @@ class Ticket_test : public beast::unit_test::suite Json::Value jr = env.rpc("json", "submit", to_string(tx)); // Verify that "submit" inserted a "Sequence": 0 field. - if (BEAST_EXPECT(jr[jss::result][jss::tx_json].isMember( - sfSequence.jsonName))) + if (BEAST_EXPECT(jr[jss::result][jss::tx_json].isMember(sfSequence.jsonName))) { - BEAST_EXPECT( - jr[jss::result][jss::tx_json][sfSequence.jsonName] == 0); + BEAST_EXPECT(jr[jss::result][jss::tx_json][sfSequence.jsonName] == 0); } // "submit" should have consumed the last of alice's tickets. @@ -882,10 +799,7 @@ class Ticket_test : public beast::unit_test::suite // Create a transaction that includes both a ticket and a non-zero // sequence number. The transaction fails with temSEQ_AND_TICKET. - env(noop(alice), - ticket::use(ticketSeq), - seq(env.seq(alice)), - ter(temSEQ_AND_TICKET)); + env(noop(alice), ticket::use(ticketSeq), seq(env.seq(alice)), ter(temSEQ_AND_TICKET)); env.close(); // Verify that the transaction failed by looking at alice's diff --git a/src/test/app/Transaction_ordering_test.cpp b/src/test/app/Transaction_ordering_test.cpp index 81c9ae196c..f7d431fc90 100644 --- a/src/test/app/Transaction_ordering_test.cpp +++ b/src/test/app/Transaction_ordering_test.cpp @@ -20,8 +20,7 @@ struct Transaction_ordering_test : public beast::unit_test::suite auto const aliceSequence = env.seq(alice); auto const tx1 = env.jt(noop(alice), seq(aliceSequence)); - auto const tx2 = - env.jt(noop(alice), seq(aliceSequence + 1), last_ledger_seq(7)); + auto const tx2 = env.jt(noop(alice), seq(aliceSequence + 1), last_ledger_seq(7)); env(tx1); env.close(); @@ -33,16 +32,12 @@ struct Transaction_ordering_test : public beast::unit_test::suite env.close(); { - auto const result = - env.rpc("tx", to_string(tx1.stx->getTransactionID())); - BEAST_EXPECT( - result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); + auto const result = env.rpc("tx", to_string(tx1.stx->getTransactionID())); + BEAST_EXPECT(result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); } { - auto const result = - env.rpc("tx", to_string(tx2.stx->getTransactionID())); - BEAST_EXPECT( - result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); + auto const result = env.rpc("tx", to_string(tx2.stx->getTransactionID())); + BEAST_EXPECT(result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); } } @@ -64,8 +59,7 @@ struct Transaction_ordering_test : public beast::unit_test::suite auto const aliceSequence = env.seq(alice); auto const tx1 = env.jt(noop(alice), seq(aliceSequence)); - auto const tx2 = - env.jt(noop(alice), seq(aliceSequence + 1), last_ledger_seq(7)); + auto const tx2 = env.jt(noop(alice), seq(aliceSequence + 1), last_ledger_seq(7)); env(tx2, ter(terPRE_SEQ)); BEAST_EXPECT(env.seq(alice) == aliceSequence); @@ -76,16 +70,12 @@ struct Transaction_ordering_test : public beast::unit_test::suite env.close(); { - auto const result = - env.rpc("tx", to_string(tx1.stx->getTransactionID())); - BEAST_EXPECT( - result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); + auto const result = env.rpc("tx", to_string(tx1.stx->getTransactionID())); + BEAST_EXPECT(result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); } { - auto const result = - env.rpc("tx", to_string(tx2.stx->getTransactionID())); - BEAST_EXPECT( - result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); + auto const result = env.rpc("tx", to_string(tx2.stx->getTransactionID())); + BEAST_EXPECT(result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); } } @@ -109,8 +99,7 @@ struct Transaction_ordering_test : public beast::unit_test::suite std::vector tx; for (auto i = 0; i < 5; ++i) { - tx.emplace_back(env.jt( - noop(alice), seq(aliceSequence + i), last_ledger_seq(7))); + tx.emplace_back(env.jt(noop(alice), seq(aliceSequence + i), last_ledger_seq(7))); } for (auto i = 1; i < 5; ++i) @@ -127,10 +116,8 @@ struct Transaction_ordering_test : public beast::unit_test::suite for (auto i = 0; i < 5; ++i) { - auto const result = - env.rpc("tx", to_string(tx[i].stx->getTransactionID())); - BEAST_EXPECT( - result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); + auto const result = env.rpc("tx", to_string(tx[i].stx->getTransactionID())); + BEAST_EXPECT(result["result"]["meta"]["TransactionResult"] == "tesSUCCESS"); } } diff --git a/src/test/app/TrustAndBalance_test.cpp b/src/test/app/TrustAndBalance_test.cpp index 25c22b823b..b695430c7f 100644 --- a/src/test/app/TrustAndBalance_test.cpp +++ b/src/test/app/TrustAndBalance_test.cpp @@ -57,36 +57,24 @@ class TrustAndBalance_test : public beast::unit_test::suite jrr = ledgerEntryState(env, gw, alice, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "0"); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::value] == "800"); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::issuer] == - alice.human()); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::currency] == "USD"); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::value] == "800"); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::issuer] == alice.human()); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::currency] == "USD"); BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::value] == "0"); - BEAST_EXPECT( - jrr[jss::node][sfLowLimit.fieldName][jss::issuer] == gw.human()); - BEAST_EXPECT( - jrr[jss::node][sfLowLimit.fieldName][jss::currency] == "USD"); + BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::issuer] == gw.human()); + BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::currency] == "USD"); // modify the credit limit env(trust(alice, gw["USD"](700))); jrr = ledgerEntryState(env, gw, alice, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "0"); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::value] == "700"); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::issuer] == - alice.human()); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::currency] == "USD"); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::value] == "700"); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::issuer] == alice.human()); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::currency] == "USD"); BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::value] == "0"); - BEAST_EXPECT( - jrr[jss::node][sfLowLimit.fieldName][jss::issuer] == gw.human()); - BEAST_EXPECT( - jrr[jss::node][sfLowLimit.fieldName][jss::currency] == "USD"); + BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::issuer] == gw.human()); + BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::currency] == "USD"); // set negative limit - expect failure env(trust(alice, gw["USD"](-1)), ter(temBAD_LIMIT)); @@ -109,17 +97,12 @@ class TrustAndBalance_test : public beast::unit_test::suite // check the ledger state for the trust line jrr = ledgerEntryState(env, alice, bob, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "0"); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::value] == "500"); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::issuer] == bob.human()); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.fieldName][jss::currency] == "USD"); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::value] == "500"); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::issuer] == bob.human()); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.fieldName][jss::currency] == "USD"); BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::value] == "600"); - BEAST_EXPECT( - jrr[jss::node][sfLowLimit.fieldName][jss::issuer] == alice.human()); - BEAST_EXPECT( - jrr[jss::node][sfLowLimit.fieldName][jss::currency] == "USD"); + BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::issuer] == alice.human()); + BEAST_EXPECT(jrr[jss::node][sfLowLimit.fieldName][jss::currency] == "USD"); } void @@ -167,8 +150,7 @@ class TrustAndBalance_test : public beast::unit_test::suite testWithTransferFee(bool subscribe, bool with_rate, FeatureBitset features) { testcase( - std::string("Direct Payment: ") + - (with_rate ? "With " : "Without ") + " Xfer Fee, " + + std::string("Direct Payment: ") + (with_rate ? "With " : "Without ") + " Xfer Fee, " + (subscribe ? "With " : "Without ") + " Subscribe"); using namespace test::jtx; @@ -233,12 +215,9 @@ class TrustAndBalance_test : public beast::unit_test::suite auto const& t = jval[jss::transaction]; return t[jss::TransactionType] == jss::Payment; })); - BEAST_EXPECT(wsc->findMsg(5s, [](auto const& jval) { - return jval[jss::type] == "ledgerClosed"; - })); + BEAST_EXPECT(wsc->findMsg(5s, [](auto const& jval) { return jval[jss::type] == "ledgerClosed"; })); - BEAST_EXPECT( - wsc->invoke("unsubscribe", jv)[jss::status] == "success"); + BEAST_EXPECT(wsc->invoke("unsubscribe", jv)[jss::status] == "success"); } } @@ -283,9 +262,7 @@ class TrustAndBalance_test : public beast::unit_test::suite // alice sends bob issues to bob with a max spend in alice issues. // expect fail since gw is not involved - env(pay(alice, bob, bob["AUD"](1)), - sendmax(alice["AUD"](1.1)), - ter(tecPATH_DRY)); + env(pay(alice, bob, bob["AUD"](1)), sendmax(alice["AUD"](1.1)), ter(tecPATH_DRY)); env.require(balance(alice, gw["AUD"](1.1))); env.require(balance(bob, gw["AUD"](3))); @@ -335,9 +312,7 @@ class TrustAndBalance_test : public beast::unit_test::suite void testIndirectMultiPath(bool with_rate, FeatureBitset features) { - testcase( - std::string("Indirect Payment, Multi Path, ") + - (with_rate ? "With " : "Without ") + " Xfer Fee, "); + testcase(std::string("Indirect Payment, Multi Path, ") + (with_rate ? "With " : "Without ") + " Xfer Fee, "); using namespace test::jtx; Env env{*this, features}; @@ -370,20 +345,12 @@ class TrustAndBalance_test : public beast::unit_test::suite test::jtx::path(bob), test::jtx::path(carol)); else - env(pay(alice, amazon, gw["USD"](150)), - test::jtx::path(bob), - test::jtx::path(carol)); + env(pay(alice, amazon, gw["USD"](150)), test::jtx::path(bob), test::jtx::path(carol)); if (with_rate) { - env.require(balance( - alice, - STAmount( - carol["USD"].issue(), - 6500000000000000ull, - -14, - true, - STAmount::unchecked{}))); + env.require( + balance(alice, STAmount(carol["USD"].issue(), 6500000000000000ull, -14, true, STAmount::unchecked{}))); env.require(balance(carol, gw["USD"](35))); } else @@ -416,13 +383,10 @@ class TrustAndBalance_test : public beast::unit_test::suite jvs[jss::streams].append("transactions"); BEAST_EXPECT(wsc->invoke("subscribe", jvs)[jss::status] == "success"); - char const* invoiceid = - "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"; + char const* invoiceid = "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"; Json::Value jv; - auto tx = env.jt( - pay(env.master, alice, XRP(10000)), - json(sfInvoiceID.fieldName, invoiceid)); + auto tx = env.jt(pay(env.master, alice, XRP(10000)), json(sfInvoiceID.fieldName, invoiceid)); jv[jss::tx_blob] = strHex(tx.stx->getSerializer().slice()); auto jrr = wsc->invoke("submit", jv)[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); @@ -432,8 +396,7 @@ class TrustAndBalance_test : public beast::unit_test::suite using namespace std::chrono_literals; BEAST_EXPECT(wsc->findMsg(2s, [invoiceid](auto const& jval) { auto const& t = jval[jss::transaction]; - return t[jss::TransactionType] == jss::Payment && - t[sfInvoiceID.fieldName] == invoiceid; + return t[jss::TransactionType] == jss::Payment && t[sfInvoiceID.fieldName] == invoiceid; })); BEAST_EXPECT(wsc->invoke("unsubscribe", jv)[jss::status] == "success"); diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index 9489bb7f04..13feceb74e 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -68,8 +68,7 @@ class TxQPosNegFlows_test : public beast::unit_test::suite auto calcMedFeeLevel(FeeLevel64 const feeLevel1, FeeLevel64 const feeLevel2) { - FeeLevel64 const expectedMedFeeLevel = - (feeLevel1 + feeLevel2 + FeeLevel64{1}) / 2; + FeeLevel64 const expectedMedFeeLevel = (feeLevel1 + feeLevel2 + FeeLevel64{1}) / 2; return std::max(expectedMedFeeLevel, minEscalationFeeLevel).fee(); } @@ -331,13 +330,7 @@ public: env(noop(env.master), fee(baseFee * 2), queued); ++metrics.txCount; - checkMetrics( - *this, - env, - metrics.txCount, - metrics.txQMaxSize, - metrics.txPerLedger + 1, - metrics.txPerLedger); + checkMetrics(*this, env, metrics.txCount, metrics.txQMaxSize, metrics.txPerLedger + 1, metrics.txPerLedger); } void @@ -400,10 +393,7 @@ public: env(noop(alice), ticket::use(tkt1 + 10), fee(baseFee * 2.0), queued); env(noop(alice), ticket::use(tkt1 + 11), fee(baseFee * 2.1), queued); env(noop(alice), ticket::use(tkt1 + 12), fee(baseFee * 2.2), queued); - env(noop(alice), - ticket::use(tkt1 + 13), - fee(baseFee * 2.3), - ter(telCAN_NOT_QUEUE_FULL)); + env(noop(alice), ticket::use(tkt1 + 13), fee(baseFee * 2.3), ter(telCAN_NOT_QUEUE_FULL)); checkMetrics(*this, env, 8, 8, 5, 4, expectedMinFeeLevel); // Check which of the queued transactions got into the ledger by @@ -509,22 +499,10 @@ public: env(noop(alice), ticket::use(tkt1 + 15), fee(baseFee * 2.7), queued); env(noop(alice), ticket::use(tkt250 - 2), fee(baseFee * 2.6), queued); env(noop(alice), ticket::use(tkt1 + 16), fee(baseFee * 2.5), queued); - env(noop(alice), - ticket::use(tkt250 - 3), - fee(baseFee * 2.4), - ter(telCAN_NOT_QUEUE_FULL)); - env(noop(alice), - ticket::use(tkt1 + 17), - fee(baseFee * 2.3), - ter(telCAN_NOT_QUEUE_FULL)); - env(noop(alice), - ticket::use(tkt250 - 4), - fee(baseFee * 2.2), - ter(telCAN_NOT_QUEUE_FULL)); - env(noop(alice), - ticket::use(tkt1 + 18), - fee(baseFee * 2.1), - ter(telCAN_NOT_QUEUE_FULL)); + env(noop(alice), ticket::use(tkt250 - 3), fee(baseFee * 2.4), ter(telCAN_NOT_QUEUE_FULL)); + env(noop(alice), ticket::use(tkt1 + 17), fee(baseFee * 2.3), ter(telCAN_NOT_QUEUE_FULL)); + env(noop(alice), ticket::use(tkt250 - 4), fee(baseFee * 2.2), ter(telCAN_NOT_QUEUE_FULL)); + env(noop(alice), ticket::use(tkt1 + 18), fee(baseFee * 2.1), ter(telCAN_NOT_QUEUE_FULL)); checkMetrics(*this, env, 10, 12, 7, 6); @@ -565,24 +543,12 @@ public: // let's try replacing them. // The lowest fee ticket is baseFee * 2.1, trying to replace it - env(noop(alice), - ticket::use(tkt1 + 18), - fee(baseFee * 2.1 * 1.25 - 1), - ter(telCAN_NOT_QUEUE_FEE)); - env(noop(alice), - ticket::use(tkt1 + 18), - fee(baseFee * 2.1 * 1.25 + 1), - queued); + env(noop(alice), ticket::use(tkt1 + 18), fee(baseFee * 2.1 * 1.25 - 1), ter(telCAN_NOT_QUEUE_FEE)); + env(noop(alice), ticket::use(tkt1 + 18), fee(baseFee * 2.1 * 1.25 + 1), queued); // New lowest fee ticket is baseFee * 2.2 - env(noop(alice), - ticket::use(tkt250 - 4), - fee(baseFee * 2.2 * 1.25 - 1), - ter(telCAN_NOT_QUEUE_FEE)); - env(noop(alice), - ticket::use(tkt250 - 4), - fee(baseFee * 2.2 * 1.25 + 1), - queued); + env(noop(alice), ticket::use(tkt250 - 4), fee(baseFee * 2.2 * 1.25 - 1), ter(telCAN_NOT_QUEUE_FEE)); + env(noop(alice), ticket::use(tkt250 - 4), fee(baseFee * 2.2 * 1.25 + 1), queued); env.close(); env.require(owners(alice, 227), tickets(alice, 227)); @@ -658,10 +624,7 @@ public: checkMetrics(*this, env, 0, std::nullopt, 3, 2); // Future transaction for Alice - fails - env(noop(alice), - fee(openLedgerCost(env)), - seq(env.seq(alice) + 1), - ter(terPRE_SEQ)); + env(noop(alice), fee(openLedgerCost(env)), seq(env.seq(alice) + 1), ter(terPRE_SEQ)); checkMetrics(*this, env, 0, std::nullopt, 3, 2); // Current transaction for Alice: held @@ -747,16 +710,12 @@ public: auto aliceStat = txQ.getAccountTxs(alice.id()); BEAST_EXPECT(aliceStat.size() == 1); BEAST_EXPECT(aliceStat.begin()->feeLevel == baseFeeLevel); - BEAST_EXPECT( - aliceStat.begin()->lastValid && - *aliceStat.begin()->lastValid == 8); + BEAST_EXPECT(aliceStat.begin()->lastValid && *aliceStat.begin()->lastValid == 8); BEAST_EXPECT(!aliceStat.begin()->consequences.isBlocker()); auto bobStat = txQ.getAccountTxs(bob.id()); BEAST_EXPECT(bobStat.size() == 1); - BEAST_EXPECT( - bobStat.begin()->feeLevel == - FeeLevel64{baseFeeLevel.fee() * largeFeeMultiplier}); + BEAST_EXPECT(bobStat.begin()->feeLevel == FeeLevel64{baseFeeLevel.fee() * largeFeeMultiplier}); BEAST_EXPECT(!bobStat.begin()->lastValid); BEAST_EXPECT(!bobStat.begin()->consequences.isBlocker()); @@ -977,10 +936,8 @@ public: Env::ParsedResult parsed; - env.app().openLedger().modify([&](OpenView& view, - beast::Journal j) { - auto const result = - xrpl::apply(env.app(), view, *jt.stx, tapNONE, env.journal); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { + auto const result = xrpl::apply(env.app(), view, *jt.stx, tapNONE, env.journal); parsed.ter = result.ter; return result.applied; }); @@ -1003,8 +960,7 @@ public: Env env( *this, makeConfig( - {{"minimum_txn_in_ledger_standalone", "3"}}, - {{"account_reserve", "200"}, {"owner_reserve", "50"}})); + {{"minimum_txn_in_ledger_standalone", "3"}}, {{"account_reserve", "200"}, {"owner_reserve", "50"}})); auto alice = Account("alice"); auto bob = Account("bob"); @@ -1078,11 +1034,7 @@ public: auto lastLedgerSeq = env.current()->header().seq + 2; for (auto i = 0; i < 7; i++) { - env(noop(alice), - seq(aliceSeq), - json(jss::LastLedgerSequence, lastLedgerSeq + i), - fee(--aliceFee), - queued); + env(noop(alice), seq(aliceSeq), json(jss::LastLedgerSequence, lastLedgerSeq + i), fee(--aliceFee), queued); ++aliceSeq; } checkMetrics(*this, env, 8, 8, 5, 4, 513); @@ -1096,12 +1048,10 @@ public: for (auto const& tx : aliceStat) { BEAST_EXPECT(tx.seqProxy.isSeq() && tx.seqProxy.value() == seq); - BEAST_EXPECT( - tx.feeLevel == toFeeLevel(XRPAmount(--aliceFee), baseFee)); + BEAST_EXPECT(tx.feeLevel == toFeeLevel(XRPAmount(--aliceFee), baseFee)); BEAST_EXPECT(tx.lastValid); BEAST_EXPECT( - (tx.consequences.fee() == drops(aliceFee) && - tx.consequences.potentialSpend() == drops(0) && + (tx.consequences.fee() == drops(aliceFee) && tx.consequences.potentialSpend() == drops(0) && !tx.consequences.isBlocker()) || tx.seqProxy.value() == env.seq(alice) + 6); ++seq; @@ -1138,20 +1088,14 @@ public: // Alice wants this tx more than the dropped tx, // so resubmits with higher fee, but the queue // is full, and her account is the cheapest. - env(noop(alice), - seq(aliceSeq - 1), - fee(aliceFee), - ter(telCAN_NOT_QUEUE_FULL)); + env(noop(alice), seq(aliceSeq - 1), fee(aliceFee), ter(telCAN_NOT_QUEUE_FULL)); checkMetrics(*this, env, 8, 8, 5, 4, 538); // Try to replace a middle item in the queue // without enough fee. aliceSeq = env.seq(alice) + 2; aliceFee = 29; - env(noop(alice), - seq(aliceSeq), - fee(aliceFee), - ter(telCAN_NOT_QUEUE_FEE)); + env(noop(alice), seq(aliceSeq), fee(aliceFee), ter(telCAN_NOT_QUEUE_FEE)); checkMetrics(*this, env, 8, 8, 5, 4, 538); // Replace a middle item from the queue successfully @@ -1171,12 +1115,8 @@ public: // bankrupt Alice. Fails, because an account can't have // more than the minimum reserve in flight before the // last queued transaction - aliceFee = - env.le(alice)->getFieldAmount(sfBalance).xrp().drops() - (62); - env(noop(alice), - seq(aliceSeq), - fee(aliceFee), - ter(telCAN_NOT_QUEUE_BALANCE)); + aliceFee = env.le(alice)->getFieldAmount(sfBalance).xrp().drops() - (62); + env(noop(alice), seq(aliceSeq), fee(aliceFee), ter(telCAN_NOT_QUEUE_BALANCE)); checkMetrics(*this, env, 4, 10, 6, 5); // Try to spend more than Alice can afford with all the other txs. @@ -1195,10 +1135,7 @@ public: // the fee is checked against the balance aliceFee /= 5; ++aliceSeq; - env(noop(alice), - seq(aliceSeq), - fee(aliceFee), - ter(telCAN_NOT_QUEUE_BALANCE)); + env(noop(alice), seq(aliceSeq), fee(aliceFee), ter(telCAN_NOT_QUEUE_BALANCE)); checkMetrics(*this, env, 4, 10, 6, 5); env.close(); @@ -1231,12 +1168,8 @@ public: // Try to replace a middle item in the queue // with enough fee to bankrupt bob and make the // later transactions unable to pay their fees - std::int64_t bobFee = - env.le(bob)->getFieldAmount(sfBalance).xrp().drops() - (9 * 10 - 1); - env(noop(bob), - seq(bobSeq + 5), - fee(bobFee), - ter(telCAN_NOT_QUEUE_BALANCE)); + std::int64_t bobFee = env.le(bob)->getFieldAmount(sfBalance).xrp().drops() - (9 * 10 - 1); + env(noop(bob), seq(bobSeq + 5), fee(bobFee), ter(telCAN_NOT_QUEUE_BALANCE)); checkMetrics(*this, env, 10, 12, 7, 6); // Attempt to replace a middle item in the queue with enough fee @@ -1245,12 +1178,8 @@ public: // // The attempt fails because the sum of bob's fees now exceeds the // (artificially lowered to 200 drops) account reserve. - bobFee = - env.le(bob)->getFieldAmount(sfBalance).xrp().drops() - (9 * 10); - env(noop(bob), - seq(bobSeq + 5), - fee(bobFee), - ter(telCAN_NOT_QUEUE_BALANCE)); + bobFee = env.le(bob)->getFieldAmount(sfBalance).xrp().drops() - (9 * 10); + env(noop(bob), seq(bobSeq + 5), fee(bobFee), ter(telCAN_NOT_QUEUE_BALANCE)); checkMetrics(*this, env, 10, 12, 7, 6); // Close the ledger and verify that the queued transactions succeed @@ -1361,44 +1290,29 @@ public: // This next test should remain unchanged regardless of // transaction ordering BEAST_EXPECT( - aliceSeq + bobSeq + charlieSeq + dariaSeq + elmoSeq + fredSeq + - gwenSeq + hankSeq + 6 == - env.seq(alice) + env.seq(bob) + env.seq(charlie) + env.seq(daria) + - env.seq(elmo) + env.seq(fred) + env.seq(gwen) + env.seq(hank)); + aliceSeq + bobSeq + charlieSeq + dariaSeq + elmoSeq + fredSeq + gwenSeq + hankSeq + 6 == + env.seq(alice) + env.seq(bob) + env.seq(charlie) + env.seq(daria) + env.seq(elmo) + env.seq(fred) + + env.seq(gwen) + env.seq(hank)); // These tests may change if TxQ ordering is changed using namespace std::string_literals; BEAST_EXPECTS( - aliceSeq == env.seq(alice), - "alice: "s + std::to_string(aliceSeq) + ", " + - std::to_string(env.seq(alice))); + aliceSeq == env.seq(alice), "alice: "s + std::to_string(aliceSeq) + ", " + std::to_string(env.seq(alice))); BEAST_EXPECTS( - bobSeq + 1 == env.seq(bob), - "bob: "s + std::to_string(bobSeq) + ", " + - std::to_string(env.seq(bob))); + bobSeq + 1 == env.seq(bob), "bob: "s + std::to_string(bobSeq) + ", " + std::to_string(env.seq(bob))); BEAST_EXPECTS( charlieSeq + 2 == env.seq(charlie), - "charlie: "s + std::to_string(charlieSeq) + ", " + - std::to_string(env.seq(charlie))); + "charlie: "s + std::to_string(charlieSeq) + ", " + std::to_string(env.seq(charlie))); BEAST_EXPECTS( dariaSeq + 1 == env.seq(daria), - "daria: "s + std::to_string(dariaSeq) + ", " + - std::to_string(env.seq(daria))); + "daria: "s + std::to_string(dariaSeq) + ", " + std::to_string(env.seq(daria))); BEAST_EXPECTS( - elmoSeq + 1 == env.seq(elmo), - "elmo: "s + std::to_string(elmoSeq) + ", " + - std::to_string(env.seq(elmo))); + elmoSeq + 1 == env.seq(elmo), "elmo: "s + std::to_string(elmoSeq) + ", " + std::to_string(env.seq(elmo))); BEAST_EXPECTS( - fredSeq == env.seq(fred), - "fred: "s + std::to_string(fredSeq) + ", " + - std::to_string(env.seq(fred))); + fredSeq == env.seq(fred), "fred: "s + std::to_string(fredSeq) + ", " + std::to_string(env.seq(fred))); BEAST_EXPECTS( - gwenSeq == env.seq(gwen), - "gwen: "s + std::to_string(gwenSeq) + ", " + - std::to_string(env.seq(gwen))); + gwenSeq == env.seq(gwen), "gwen: "s + std::to_string(gwenSeq) + ", " + std::to_string(env.seq(gwen))); BEAST_EXPECTS( - hankSeq + 1 == env.seq(hank), - "hank: "s + std::to_string(hankSeq) + ", " + - std::to_string(env.seq(hank))); + hankSeq + 1 == env.seq(hank), "hank: "s + std::to_string(hankSeq) + ", " + std::to_string(env.seq(hank))); // Which sequences get incremented may change if TxQ ordering is // changed @@ -1424,19 +1338,10 @@ public: BEAST_EXPECT(qTxCount1.size() <= 3); // Fill up the queue again - env(noop(alice), - seq(aliceSeq + qTxCount1[alice.id()]++), - fee(15), - queued); + env(noop(alice), seq(aliceSeq + qTxCount1[alice.id()]++), fee(15), queued); env(noop(bob), seq(bobSeq + qTxCount1[bob.id()]++), fee(15), queued); - env(noop(charlie), - seq(charlieSeq + qTxCount1[charlie.id()]++), - fee(15), - queued); - env(noop(daria), - seq(dariaSeq + qTxCount1[daria.id()]++), - fee(15), - queued); + env(noop(charlie), seq(charlieSeq + qTxCount1[charlie.id()]++), fee(15), queued); + env(noop(daria), seq(dariaSeq + qTxCount1[daria.id()]++), fee(15), queued); env(noop(elmo), seq(elmoSeq + qTxCount1[elmo.id()]++), fee(15), queued); env(noop(fred), seq(fredSeq + qTxCount1[fred.id()]++), fee(15), queued); env(noop(gwen), seq(gwenSeq + qTxCount1[gwen.id()]++), fee(15), queued); @@ -1447,10 +1352,7 @@ public: // Add another transaction, with a higher fee, // Not high enough to get into the ledger, but high // enough to get into the queue (and kick somebody out) - env(noop(alice), - fee(100), - seq(aliceSeq + qTxCount1[alice.id()]++), - queued); + env(noop(alice), fee(100), seq(aliceSeq + qTxCount1[alice.id()]++), queued); checkMetrics(*this, env, 10, 10, 6, 5, minFeeLevel); @@ -1467,50 +1369,34 @@ public: // This next test should remain unchanged regardless of // transaction ordering BEAST_EXPECT( - aliceSeq + bobSeq + charlieSeq + dariaSeq + elmoSeq + fredSeq + - gwenSeq + hankSeq + 7 == - env.seq(alice) + env.seq(bob) + env.seq(charlie) + env.seq(daria) + - env.seq(elmo) + env.seq(fred) + env.seq(gwen) + env.seq(hank)); + aliceSeq + bobSeq + charlieSeq + dariaSeq + elmoSeq + fredSeq + gwenSeq + hankSeq + 7 == + env.seq(alice) + env.seq(bob) + env.seq(charlie) + env.seq(daria) + env.seq(elmo) + env.seq(fred) + + env.seq(gwen) + env.seq(hank)); // These tests may change if TxQ ordering is changed BEAST_EXPECTS( - aliceSeq + qTxCount1[alice.id()] - qTxCount2[alice.id()] == - env.seq(alice), - "alice: "s + std::to_string(aliceSeq) + ", " + - std::to_string(env.seq(alice))); + aliceSeq + qTxCount1[alice.id()] - qTxCount2[alice.id()] == env.seq(alice), + "alice: "s + std::to_string(aliceSeq) + ", " + std::to_string(env.seq(alice))); BEAST_EXPECTS( bobSeq + qTxCount1[bob.id()] - qTxCount2[bob.id()] == env.seq(bob), - "bob: "s + std::to_string(bobSeq) + ", " + - std::to_string(env.seq(bob))); + "bob: "s + std::to_string(bobSeq) + ", " + std::to_string(env.seq(bob))); BEAST_EXPECTS( - charlieSeq + qTxCount1[charlie.id()] - qTxCount2[charlie.id()] == - env.seq(charlie), - "charlie: "s + std::to_string(charlieSeq) + ", " + - std::to_string(env.seq(charlie))); + charlieSeq + qTxCount1[charlie.id()] - qTxCount2[charlie.id()] == env.seq(charlie), + "charlie: "s + std::to_string(charlieSeq) + ", " + std::to_string(env.seq(charlie))); BEAST_EXPECTS( - dariaSeq + qTxCount1[daria.id()] - qTxCount2[daria.id()] == - env.seq(daria), - "daria: "s + std::to_string(dariaSeq) + ", " + - std::to_string(env.seq(daria))); + dariaSeq + qTxCount1[daria.id()] - qTxCount2[daria.id()] == env.seq(daria), + "daria: "s + std::to_string(dariaSeq) + ", " + std::to_string(env.seq(daria))); BEAST_EXPECTS( - elmoSeq + qTxCount1[elmo.id()] - qTxCount2[elmo.id()] == - env.seq(elmo), - "elmo: "s + std::to_string(elmoSeq) + ", " + - std::to_string(env.seq(elmo))); + elmoSeq + qTxCount1[elmo.id()] - qTxCount2[elmo.id()] == env.seq(elmo), + "elmo: "s + std::to_string(elmoSeq) + ", " + std::to_string(env.seq(elmo))); BEAST_EXPECTS( - fredSeq + qTxCount1[fred.id()] - qTxCount2[fred.id()] == - env.seq(fred), - "fred: "s + std::to_string(fredSeq) + ", " + - std::to_string(env.seq(fred))); + fredSeq + qTxCount1[fred.id()] - qTxCount2[fred.id()] == env.seq(fred), + "fred: "s + std::to_string(fredSeq) + ", " + std::to_string(env.seq(fred))); BEAST_EXPECTS( - gwenSeq + qTxCount1[gwen.id()] - qTxCount2[gwen.id()] == - env.seq(gwen), - "gwen: "s + std::to_string(gwenSeq) + ", " + - std::to_string(env.seq(gwen))); + gwenSeq + qTxCount1[gwen.id()] - qTxCount2[gwen.id()] == env.seq(gwen), + "gwen: "s + std::to_string(gwenSeq) + ", " + std::to_string(env.seq(gwen))); BEAST_EXPECTS( - hankSeq + qTxCount1[hank.id()] - qTxCount2[hank.id()] == - env.seq(hank), - "hank: "s + std::to_string(hankSeq) + ", " + - std::to_string(env.seq(hank))); + hankSeq + qTxCount1[hank.id()] - qTxCount2[hank.id()] == env.seq(hank), + "hank: "s + std::to_string(hankSeq) + ", " + std::to_string(env.seq(hank))); } void @@ -1534,9 +1420,7 @@ public: // Immediately after the fset, the sfAccountTxnID field // is still uninitialized, so preflight succeeds here, // and this txn fails because it can't be stored in the queue. - env(noop(alice), - json(R"({"AccountTxnID": "0"})"), - ter(telCAN_NOT_QUEUE)); + env(noop(alice), json(R"({"AccountTxnID": "0"})"), ter(telCAN_NOT_QUEUE)); checkMetrics(*this, env, 0, std::nullopt, 2, 1); env.close(); @@ -1583,10 +1467,8 @@ public: // calculate median fee level. if (i == 4) { - double const feeMultiplier = - static_cast(cost.drops()) / baseFee; - medFeeLevel = FeeLevel64{static_cast( - feeMultiplier * baseFeeLevel.fee())}; + double const feeMultiplier = static_cast(cost.drops()) / baseFee; + medFeeLevel = FeeLevel64{static_cast(feeMultiplier * baseFeeLevel.fee())}; } env(noop(alice), fee(cost)); @@ -1675,8 +1557,7 @@ public: Env env( *this, makeConfig( - {{"minimum_txn_in_ledger_standalone", "3"}}, - {{"account_reserve", "200"}, {"owner_reserve", "50"}})); + {{"minimum_txn_in_ledger_standalone", "3"}}, {{"account_reserve", "200"}, {"owner_reserve", "50"}})); auto alice = Account("alice"); auto bob = Account("bob"); @@ -1716,16 +1597,12 @@ public: // up to Alice's reserve. env(offer(bob, drops(5000), USD(5000)), fee(openLedgerCost(env)), - require( - balance(alice, drops(250)), owners(alice, 1), lines(alice, 1))); + require(balance(alice, drops(250)), owners(alice, 1), lines(alice, 1))); checkMetrics(*this, env, 4, 6, 5, 3); // Try adding a new transaction. // Too many fees in flight. - env(noop(alice), - fee(drops(200)), - seq(aliceSeq + 1), - ter(telCAN_NOT_QUEUE_BALANCE)); + env(noop(alice), fee(drops(200)), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BALANCE)); checkMetrics(*this, env, 4, 6, 5, 3); // Close the ledger. All of Alice's transactions @@ -1736,10 +1613,7 @@ public: // Still can't add a new transaction for Alice, // no matter the fee. - env(noop(alice), - fee(drops(200)), - seq(aliceSeq + 1), - ter(telCAN_NOT_QUEUE_BALANCE)); + env(noop(alice), fee(drops(200)), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BALANCE)); checkMetrics(*this, env, 1, 10, 3, 5); /* At this point, Alice's transaction is indefinitely @@ -1798,15 +1672,9 @@ public: env(noop(alice), seq(aliceSeq + 1), queued); // Can't replace either queued transaction with a blocker - env(fset(alice, asfAccountTxnID), - seq(aliceSeq + 0), - fee(baseFee * 2), - ter(telCAN_NOT_QUEUE_BLOCKS)); + env(fset(alice, asfAccountTxnID), seq(aliceSeq + 0), fee(baseFee * 2), ter(telCAN_NOT_QUEUE_BLOCKS)); - env(regkey(alice, bob), - seq(aliceSeq + 1), - fee(baseFee * 2), - ter(telCAN_NOT_QUEUE_BLOCKS)); + env(regkey(alice, bob), seq(aliceSeq + 1), fee(baseFee * 2), ter(telCAN_NOT_QUEUE_BLOCKS)); // Can't append a blocker to the queue. env(signers(alice, 2, {{bob}, {charlie}, {daria}}), @@ -1833,10 +1701,7 @@ public: // Since there's only one entry in the queue we can replace // that entry with a blocker. - env(regkey(alice, bob), - seq(aliceSeq + 0), - fee(baseFee * 2), - queued); + env(regkey(alice, bob), seq(aliceSeq + 0), fee(baseFee * 2), queued); // Now that there's a blocker in the queue we can't append to // the queue. @@ -1846,10 +1711,7 @@ public: env(noop(bob), queued); // We can replace the blocker with a different blocker. - env(signers(alice, 2, {{bob}, {charlie}, {daria}}), - seq(aliceSeq + 0), - fee(baseFee * 2.6), - queued); + env(signers(alice, 2, {{bob}, {charlie}, {daria}}), seq(aliceSeq + 0), fee(baseFee * 2.6), queued); // Prove that the queue is still blocked. env(noop(alice), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BLOCKED)); @@ -1933,20 +1795,12 @@ public: env(noop(alice), ticket::use(tkt + 1), queued); // Can't replace either queued transaction with a blocker - env(fset(alice, asfAccountTxnID), - ticket::use(tkt + 1), - fee(baseFee * 2), - ter(telCAN_NOT_QUEUE_BLOCKS)); + env(fset(alice, asfAccountTxnID), ticket::use(tkt + 1), fee(baseFee * 2), ter(telCAN_NOT_QUEUE_BLOCKS)); - env(regkey(alice, bob), - ticket::use(tkt + 2), - fee(baseFee * 2), - ter(telCAN_NOT_QUEUE_BLOCKS)); + env(regkey(alice, bob), ticket::use(tkt + 2), fee(baseFee * 2), ter(telCAN_NOT_QUEUE_BLOCKS)); // Can't append a blocker to the queue. - env(signers(alice, 2, {{bob}, {charlie}, {daria}}), - fee(baseFee * 2), - ter(telCAN_NOT_QUEUE_BLOCKS)); + env(signers(alice, 2, {{bob}, {charlie}, {daria}}), fee(baseFee * 2), ter(telCAN_NOT_QUEUE_BLOCKS)); env(signers(alice, 2, {{bob}, {charlie}, {daria}}), ticket::use(tkt + 0), @@ -1977,41 +1831,26 @@ public: // Since there's an entry in the queue we cannot append a // blocker to the account's queue. - env(regkey(alice, bob), - fee(baseFee * 2), - ter(telCAN_NOT_QUEUE_BLOCKS)); - env(regkey(alice, bob), - ticket::use(tkt + 1), - fee(baseFee * 2), - ter(telCAN_NOT_QUEUE_BLOCKS)); + env(regkey(alice, bob), fee(baseFee * 2), ter(telCAN_NOT_QUEUE_BLOCKS)); + env(regkey(alice, bob), ticket::use(tkt + 1), fee(baseFee * 2), ter(telCAN_NOT_QUEUE_BLOCKS)); // However we can _replace_ that lone entry with a blocker. - env(regkey(alice, bob), - ticket::use(tkt + 0), - fee(baseFee * 2), - queued); + env(regkey(alice, bob), ticket::use(tkt + 0), fee(baseFee * 2), queued); // Now that there's a blocker in the queue we can't append to // the queue. env(noop(alice), ter(telCAN_NOT_QUEUE_BLOCKED)); - env(noop(alice), - ticket::use(tkt + 1), - ter(telCAN_NOT_QUEUE_BLOCKED)); + env(noop(alice), ticket::use(tkt + 1), ter(telCAN_NOT_QUEUE_BLOCKED)); // Other accounts are unaffected. env(noop(bob), queued); // We can replace the blocker with a different blocker. - env(signers(alice, 2, {{bob}, {charlie}, {daria}}), - ticket::use(tkt + 0), - fee(baseFee * 2.6), - queued); + env(signers(alice, 2, {{bob}, {charlie}, {daria}}), ticket::use(tkt + 0), fee(baseFee * 2.6), queued); // Prove that the queue is still blocked. env(noop(alice), ter(telCAN_NOT_QUEUE_BLOCKED)); - env(noop(alice), - ticket::use(tkt + 1), - ter(telCAN_NOT_QUEUE_BLOCKED)); + env(noop(alice), ticket::use(tkt + 1), ter(telCAN_NOT_QUEUE_BLOCKED)); // We can replace the blocker with a non-blocker. Then we can // successfully append to the queue. @@ -2041,9 +1880,7 @@ public: // Since there's a blocker in the queue we can't append to // the queue. - env(noop(alice), - ticket::use(tkt + 1), - ter(telCAN_NOT_QUEUE_BLOCKED)); + env(noop(alice), ticket::use(tkt + 1), ter(telCAN_NOT_QUEUE_BLOCKED)); // Other accounts are unaffected. env(noop(bob), queued); @@ -2068,8 +1905,7 @@ public: Env env( *this, makeConfig( - {{"minimum_txn_in_ledger_standalone", "3"}}, - {{"account_reserve", "200"}, {"owner_reserve", "50"}})); + {{"minimum_txn_in_ledger_standalone", "3"}}, {{"account_reserve", "200"}, {"owner_reserve", "50"}})); auto alice = Account("alice"); auto charlie = Account("charlie"); @@ -2143,10 +1979,7 @@ public: // So even a noop will look like alice // doesn't have the balance to pay the fee - env(noop(alice), - fee(drops(51)), - seq(aliceSeq + 2), - ter(terINSUF_FEE_B)); + env(noop(alice), fee(drops(51)), seq(aliceSeq + 2), ter(terINSUF_FEE_B)); checkMetrics(*this, env, 2, limit * 2, limit + 1, limit); env.close(); @@ -2176,10 +2009,7 @@ public: // So even a noop will look like alice // doesn't have the balance to pay the fee - env(noop(alice), - fee(drops(51)), - seq(aliceSeq + 1), - ter(telCAN_NOT_QUEUE_BALANCE)); + env(noop(alice), fee(drops(51)), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BALANCE)); checkMetrics(*this, env, 1, limit * 2, limit + 1, limit); env.close(); @@ -2267,8 +2097,7 @@ public: checkMetrics(*this, env, 0, limit * 2, 2, limit); // The payment succeeds - env.require( - balance(alice, aliceBal - XRP(500) - drops(20)), owners(alice, 0)); + env.require(balance(alice, aliceBal - XRP(500) - drops(20)), owners(alice, 0)); ////////////////////////////////////////// // Large IOU payment allows later txs @@ -2427,12 +2256,7 @@ public: env.memoize("carol"); { auto const jtx = env.jt(offer_cancel(alice, 3), seq(5), fee(10)); - auto const pf = preflight( - env.app(), - env.current()->rules(), - *jtx.stx, - tapNONE, - env.journal); + auto const pf = preflight(env.app(), env.current()->rules(), *jtx.stx, tapNONE, env.journal); BEAST_EXPECT(pf.ter == tesSUCCESS); BEAST_EXPECT(!pf.consequences.isBlocker()); BEAST_EXPECT(pf.consequences.fee() == drops(10)); @@ -2442,14 +2266,8 @@ public: { auto USD = alice["USD"]; - auto const jtx = - env.jt(trust("carol", USD(50000000)), seq(1), fee(10)); - auto const pf = preflight( - env.app(), - env.current()->rules(), - *jtx.stx, - tapNONE, - env.journal); + auto const jtx = env.jt(trust("carol", USD(50000000)), seq(1), fee(10)); + auto const pf = preflight(env.app(), env.current()->rules(), *jtx.stx, tapNONE, env.journal); BEAST_EXPECT(pf.ter == tesSUCCESS); BEAST_EXPECT(!pf.consequences.isBlocker()); BEAST_EXPECT(pf.consequences.fee() == drops(10)); @@ -2458,12 +2276,7 @@ public: { auto const jtx = env.jt(ticket::create(alice, 1), seq(1), fee(10)); - auto const pf = preflight( - env.app(), - env.current()->rules(), - *jtx.stx, - tapNONE, - env.journal); + auto const pf = preflight(env.app(), env.current()->rules(), *jtx.stx, tapNONE, env.journal); BEAST_EXPECT(pf.ter == tesSUCCESS); BEAST_EXPECT(!pf.consequences.isBlocker()); BEAST_EXPECT(pf.consequences.fee() == drops(10)); @@ -2571,18 +2384,9 @@ public: // Charlie is paying a high enough fee to go straight into the // ledger in order to get into the vicinity of an assert which // should no longer fire :-). - env(noop(charlie), - fee(baseFee * 800), - seq(charlieSeq - 1), - ter(tefPAST_SEQ)); - env(noop(charlie), - fee(baseFee * 800), - seq(charlieSeq + 1), - ter(terPRE_SEQ)); - env(noop(charlie), - fee(baseFee * 800), - seq(charlieSeq), - ter(tesSUCCESS)); + env(noop(charlie), fee(baseFee * 800), seq(charlieSeq - 1), ter(tefPAST_SEQ)); + env(noop(charlie), fee(baseFee * 800), seq(charlieSeq + 1), ter(terPRE_SEQ)); + env(noop(charlie), fee(baseFee * 800), seq(charlieSeq), ter(tesSUCCESS)); } void @@ -2595,13 +2399,10 @@ public: auto fee = env.rpc("fee"); - if (BEAST_EXPECT(fee.isMember(jss::result)) && - BEAST_EXPECT(!RPC::contains_error(fee[jss::result]))) + if (BEAST_EXPECT(fee.isMember(jss::result)) && BEAST_EXPECT(!RPC::contains_error(fee[jss::result]))) { auto const& result = fee[jss::result]; - BEAST_EXPECT( - result.isMember(jss::ledger_current_index) && - result[jss::ledger_current_index] == 3); + BEAST_EXPECT(result.isMember(jss::ledger_current_index) && result[jss::ledger_current_index] == 3); BEAST_EXPECT(result.isMember(jss::current_ledger_size)); BEAST_EXPECT(result.isMember(jss::current_queue_size)); BEAST_EXPECT(result.isMember(jss::expected_ledger_size)); @@ -2624,13 +2425,10 @@ public: fee = env.rpc("fee"); - if (BEAST_EXPECT(fee.isMember(jss::result)) && - BEAST_EXPECT(!RPC::contains_error(fee[jss::result]))) + if (BEAST_EXPECT(fee.isMember(jss::result)) && BEAST_EXPECT(!RPC::contains_error(fee[jss::result]))) { auto const& result = fee[jss::result]; - BEAST_EXPECT( - result.isMember(jss::ledger_current_index) && - result[jss::ledger_current_index] == 4); + BEAST_EXPECT(result.isMember(jss::ledger_current_index) && result[jss::ledger_current_index] == 4); BEAST_EXPECT(result.isMember(jss::current_ledger_size)); BEAST_EXPECT(result.isMember(jss::current_queue_size)); BEAST_EXPECT(result.isMember(jss::expected_ledger_size)); @@ -2686,14 +2484,8 @@ public: BEAST_EXPECT(env.current()->header().seq == 3); env(noop(alice), seq(aliceSeq), last_ledger_seq(5), ter(terQUEUED)); env(noop(alice), seq(aliceSeq + 1), last_ledger_seq(5), ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 2), - last_ledger_seq(10), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 3), - last_ledger_seq(11), - ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 2), last_ledger_seq(10), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 3), last_ledger_seq(11), ter(terQUEUED)); checkMetrics(*this, env, 4, std::nullopt, 2, 1); auto const bobSeq = env.seq(bob); // Ledger 4 gets 3, @@ -2719,9 +2511,7 @@ public: env(noop(alice), seq(aliceSeq + 1), ter(terPRE_SEQ)); // Cannot fill the gap with a blocker since Alice's queue is not empty. - env(fset(alice, asfAccountTxnID), - seq(aliceSeq), - ter(telCAN_NOT_QUEUE_BLOCKS)); + env(fset(alice, asfAccountTxnID), seq(aliceSeq), ter(telCAN_NOT_QUEUE_BLOCKS)); checkMetrics(*this, env, 2, 40, 5, 4); // However we can fill the gap with a non-blocker. @@ -2729,9 +2519,7 @@ public: checkMetrics(*this, env, 3, 40, 5, 4); // Attempt to queue up a new aliceSeq + 1 tx that's a blocker. - env(fset(alice, asfAccountTxnID), - seq(aliceSeq + 1), - ter(telCAN_NOT_QUEUE_BLOCKS)); + env(fset(alice, asfAccountTxnID), seq(aliceSeq + 1), ter(telCAN_NOT_QUEUE_BLOCKS)); checkMetrics(*this, env, 3, 40, 5, 4); // Queue up a non-blocker replacement for aliceSeq + 1. @@ -2761,9 +2549,7 @@ public: testcase("full queue gap handling"); auto cfg = makeConfig( - {{"minimum_txn_in_ledger_standalone", "1"}, - {"ledgers_in_queue", "10"}, - {"maximum_txn_per_account", "11"}}); + {{"minimum_txn_in_ledger_standalone", "1"}, {"ledgers_in_queue", "10"}, {"maximum_txn_per_account", "11"}}); cfg->FEES.reference_fee = 10; Env env(*this, std::move(cfg)); @@ -2783,46 +2569,16 @@ public: // Start by procuring tickets for alice to use to keep her queue full // without affecting the sequence gap that will appear later. - env(ticket::create(alice, 11), - seq(aliceSeq + 0), - fee(baseFee * 20 + 1), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 11), - last_ledger_seq(11), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 12), - last_ledger_seq(11), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 13), - last_ledger_seq(11), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 14), - last_ledger_seq(11), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 15), - last_ledger_seq(11), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 16), - last_ledger_seq(5), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 17), - last_ledger_seq(5), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 18), - last_ledger_seq(5), - ter(terQUEUED)); - env(noop(alice), - seq(aliceSeq + 19), - last_ledger_seq(11), - ter(terQUEUED)); + env(ticket::create(alice, 11), seq(aliceSeq + 0), fee(baseFee * 20 + 1), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 11), last_ledger_seq(11), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 12), last_ledger_seq(11), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 13), last_ledger_seq(11), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 14), last_ledger_seq(11), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 15), last_ledger_seq(11), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 16), last_ledger_seq(5), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 17), last_ledger_seq(5), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 18), last_ledger_seq(5), ter(terQUEUED)); + env(noop(alice), seq(aliceSeq + 19), last_ledger_seq(11), ter(terQUEUED)); checkMetrics(*this, env, 10, std::nullopt, 2, 1); auto const bobSeq = env.seq(bob); @@ -2945,9 +2701,7 @@ public: json(jss::LastLedgerSequence, lastLedgerSeq), ter(terQUEUED))(submitParams); else - envs( - noop(alice), fee(baseFee * 100), seq(none), ter(terQUEUED))( - submitParams); + envs(noop(alice), fee(baseFee * 100), seq(none), ter(terQUEUED))(submitParams); } checkMetrics(*this, env, 5, std::nullopt, 7, 6); { @@ -2957,12 +2711,10 @@ public: for (auto const& tx : aliceStat) { BEAST_EXPECT(tx.seqProxy == seq); - BEAST_EXPECT( - tx.feeLevel == FeeLevel64{baseFeeLevel.fee() * 100}); + BEAST_EXPECT(tx.feeLevel == FeeLevel64{baseFeeLevel.fee() * 100}); if (seq.value() == aliceSeq + 2) { - BEAST_EXPECT( - tx.lastValid && *tx.lastValid == lastLedgerSeq); + BEAST_EXPECT(tx.lastValid && *tx.lastValid == lastLedgerSeq); } else { @@ -3012,15 +2764,13 @@ public: ++seq; BEAST_EXPECT(tx.seqProxy.isSeq() && tx.seqProxy.value() == seq); - BEAST_EXPECT( - tx.feeLevel == FeeLevel64{baseFeeLevel.fee() * 100}); + BEAST_EXPECT(tx.feeLevel == FeeLevel64{baseFeeLevel.fee() * 100}); BEAST_EXPECT(!tx.lastValid); ++seq; } } // Now, fill the gap. - envs(noop(alice), fee(baseFee * 100), seq(none), ter(terQUEUED))( - submitParams); + envs(noop(alice), fee(baseFee * 100), seq(none), ter(terQUEUED))(submitParams); checkMetrics(*this, env, 5, 18, 10, 9); { auto aliceStat = txQ.getAccountTxs(alice.id()); @@ -3077,20 +2827,14 @@ public: { // account_info without the "queue" argument. - auto const info = - env.rpc("json", "account_info", to_string(withoutQueue)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withoutQueue)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); BEAST_EXPECT(!info[jss::result].isMember(jss::queue_data)); } { // account_info with the "queue" argument. - auto const info = - env.rpc("json", "account_info", to_string(withQueue)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withQueue)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& result = info[jss::result]; BEAST_EXPECT(result.isMember(jss::queue_data)); auto const& queue_data = result[jss::queue_data]; @@ -3109,11 +2853,8 @@ public: checkMetrics(*this, env, 0, 6, 4, 3); { - auto const info = - env.rpc("json", "account_info", to_string(withQueue)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withQueue)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& result = info[jss::result]; BEAST_EXPECT(result.isMember(jss::queue_data)); auto const& queue_data = result[jss::queue_data]; @@ -3128,22 +2869,15 @@ public: } auto submitParams = Json::Value(Json::objectValue); - envs(noop(alice), fee(baseFee * 10), seq(none), ter(terQUEUED))( - submitParams); - envs(noop(alice), fee(baseFee * 10), seq(none), ter(terQUEUED))( - submitParams); - envs(noop(alice), fee(baseFee * 10), seq(none), ter(terQUEUED))( - submitParams); - envs(noop(alice), fee(baseFee * 10), seq(none), ter(terQUEUED))( - submitParams); + envs(noop(alice), fee(baseFee * 10), seq(none), ter(terQUEUED))(submitParams); + envs(noop(alice), fee(baseFee * 10), seq(none), ter(terQUEUED))(submitParams); + envs(noop(alice), fee(baseFee * 10), seq(none), ter(terQUEUED))(submitParams); + envs(noop(alice), fee(baseFee * 10), seq(none), ter(terQUEUED))(submitParams); checkMetrics(*this, env, 4, 6, 4, 3); { - auto const info = - env.rpc("json", "account_info", to_string(withQueue)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withQueue)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& result = info[jss::result]; auto const& data = result[jss::account_data]; BEAST_EXPECT(result.isMember(jss::queue_data)); @@ -3152,19 +2886,15 @@ public: BEAST_EXPECT(queue_data.isMember(jss::txn_count)); BEAST_EXPECT(queue_data[jss::txn_count] == 4); BEAST_EXPECT(queue_data.isMember(jss::lowest_sequence)); - BEAST_EXPECT( - queue_data[jss::lowest_sequence] == data[jss::Sequence]); + BEAST_EXPECT(queue_data[jss::lowest_sequence] == data[jss::Sequence]); BEAST_EXPECT(queue_data.isMember(jss::highest_sequence)); BEAST_EXPECT( queue_data[jss::highest_sequence] == - data[jss::Sequence].asUInt() + - queue_data[jss::txn_count].asUInt() - 1); + data[jss::Sequence].asUInt() + queue_data[jss::txn_count].asUInt() - 1); BEAST_EXPECT(queue_data.isMember(jss::auth_change_queued)); BEAST_EXPECT(queue_data[jss::auth_change_queued] == false); BEAST_EXPECT(queue_data.isMember(jss::max_spend_drops_total)); - BEAST_EXPECT( - queue_data[jss::max_spend_drops_total] == - std::to_string(baseFee * 40)); + BEAST_EXPECT(queue_data[jss::max_spend_drops_total] == std::to_string(baseFee * 40)); BEAST_EXPECT(queue_data.isMember(jss::transactions)); auto const& queued = queue_data[jss::transactions]; BEAST_EXPECT(queued.size() == queue_data[jss::txn_count]); @@ -3172,16 +2902,13 @@ public: { auto const& item = queued[i]; BEAST_EXPECT(item[jss::seq] == data[jss::Sequence].asInt() + i); - BEAST_EXPECT( - item[jss::fee_level] == - std::to_string(baseFeeLevel.fee() * 10)); + BEAST_EXPECT(item[jss::fee_level] == std::to_string(baseFeeLevel.fee() * 10)); BEAST_EXPECT(!item.isMember(jss::LastLedgerSequence)); BEAST_EXPECT(item.isMember(jss::fee)); BEAST_EXPECT(item[jss::fee] == std::to_string(baseFee * 10)); BEAST_EXPECT(item.isMember(jss::max_spend_drops)); - BEAST_EXPECT( - item[jss::max_spend_drops] == std::to_string(baseFee * 10)); + BEAST_EXPECT(item[jss::max_spend_drops] == std::to_string(baseFee * 10)); BEAST_EXPECT(item.isMember(jss::auth_change)); BEAST_EXPECT(item[jss::auth_change].asBool() == false); } @@ -3203,11 +2930,8 @@ public: checkMetrics(*this, env, 1, 8, 5, 4); { - auto const info = - env.rpc("json", "account_info", to_string(withQueue)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withQueue)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& result = info[jss::result]; auto const& data = result[jss::account_data]; BEAST_EXPECT(result.isMember(jss::queue_data)); @@ -3216,19 +2940,15 @@ public: BEAST_EXPECT(queue_data.isMember(jss::txn_count)); BEAST_EXPECT(queue_data[jss::txn_count] == 1); BEAST_EXPECT(queue_data.isMember(jss::lowest_sequence)); - BEAST_EXPECT( - queue_data[jss::lowest_sequence] == data[jss::Sequence]); + BEAST_EXPECT(queue_data[jss::lowest_sequence] == data[jss::Sequence]); BEAST_EXPECT(queue_data.isMember(jss::highest_sequence)); BEAST_EXPECT( queue_data[jss::highest_sequence] == - data[jss::Sequence].asUInt() + - queue_data[jss::txn_count].asUInt() - 1); + data[jss::Sequence].asUInt() + queue_data[jss::txn_count].asUInt() - 1); BEAST_EXPECT(queue_data.isMember(jss::auth_change_queued)); BEAST_EXPECT(queue_data[jss::auth_change_queued] == true); BEAST_EXPECT(queue_data.isMember(jss::max_spend_drops_total)); - BEAST_EXPECT( - queue_data[jss::max_spend_drops_total] == - std::to_string(baseFee * 10)); + BEAST_EXPECT(queue_data[jss::max_spend_drops_total] == std::to_string(baseFee * 10)); BEAST_EXPECT(queue_data.isMember(jss::transactions)); auto const& queued = queue_data[jss::transactions]; BEAST_EXPECT(queued.size() == queue_data[jss::txn_count]); @@ -3236,14 +2956,11 @@ public: { auto const& item = queued[i]; BEAST_EXPECT(item[jss::seq] == data[jss::Sequence].asInt() + i); - BEAST_EXPECT( - item[jss::fee_level] == - std::to_string(baseFeeLevel.fee() * 10)); + BEAST_EXPECT(item[jss::fee_level] == std::to_string(baseFeeLevel.fee() * 10)); BEAST_EXPECT(item.isMember(jss::fee)); BEAST_EXPECT(item[jss::fee] == std::to_string(baseFee * 10)); BEAST_EXPECT(item.isMember(jss::max_spend_drops)); - BEAST_EXPECT( - item[jss::max_spend_drops] == std::to_string(baseFee * 10)); + BEAST_EXPECT(item[jss::max_spend_drops] == std::to_string(baseFee * 10)); BEAST_EXPECT(item.isMember(jss::auth_change)); if (i == queued.size() - 1) @@ -3260,19 +2977,12 @@ public: } } - envs( - noop(alice), - fee(baseFee * 10), - seq(none), - ter(telCAN_NOT_QUEUE_BLOCKED))(submitParams); + envs(noop(alice), fee(baseFee * 10), seq(none), ter(telCAN_NOT_QUEUE_BLOCKED))(submitParams); checkMetrics(*this, env, 1, 8, 5, 4); { - auto const info = - env.rpc("json", "account_info", to_string(withQueue)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withQueue)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& result = info[jss::result]; auto const& data = result[jss::account_data]; BEAST_EXPECT(result.isMember(jss::queue_data)); @@ -3281,19 +2991,15 @@ public: BEAST_EXPECT(queue_data.isMember(jss::txn_count)); BEAST_EXPECT(queue_data[jss::txn_count] == 1); BEAST_EXPECT(queue_data.isMember(jss::lowest_sequence)); - BEAST_EXPECT( - queue_data[jss::lowest_sequence] == data[jss::Sequence]); + BEAST_EXPECT(queue_data[jss::lowest_sequence] == data[jss::Sequence]); BEAST_EXPECT(queue_data.isMember(jss::highest_sequence)); BEAST_EXPECT( queue_data[jss::highest_sequence] == - data[jss::Sequence].asUInt() + - queue_data[jss::txn_count].asUInt() - 1); + data[jss::Sequence].asUInt() + queue_data[jss::txn_count].asUInt() - 1); BEAST_EXPECT(queue_data.isMember(jss::auth_change_queued)); BEAST_EXPECT(queue_data[jss::auth_change_queued].asBool()); BEAST_EXPECT(queue_data.isMember(jss::max_spend_drops_total)); - BEAST_EXPECT( - queue_data[jss::max_spend_drops_total] == - std::to_string(baseFee * 10)); + BEAST_EXPECT(queue_data[jss::max_spend_drops_total] == std::to_string(baseFee * 10)); BEAST_EXPECT(queue_data.isMember(jss::transactions)); auto const& queued = queue_data[jss::transactions]; BEAST_EXPECT(queued.size() == queue_data[jss::txn_count]); @@ -3301,19 +3007,14 @@ public: { auto const& item = queued[i]; BEAST_EXPECT(item[jss::seq] == data[jss::Sequence].asInt() + i); - BEAST_EXPECT( - item[jss::fee_level] == - std::to_string(baseFeeLevel.fee() * 10)); + BEAST_EXPECT(item[jss::fee_level] == std::to_string(baseFeeLevel.fee() * 10)); if (i == queued.size() - 1) { BEAST_EXPECT(item.isMember(jss::fee)); - BEAST_EXPECT( - item[jss::fee] == std::to_string(baseFee * 10)); + BEAST_EXPECT(item[jss::fee] == std::to_string(baseFee * 10)); BEAST_EXPECT(item.isMember(jss::max_spend_drops)); - BEAST_EXPECT( - item[jss::max_spend_drops] == - std::to_string(baseFee * 10)); + BEAST_EXPECT(item[jss::max_spend_drops] == std::to_string(baseFee * 10)); BEAST_EXPECT(item.isMember(jss::auth_change)); BEAST_EXPECT(item[jss::auth_change].asBool()); BEAST_EXPECT(item.isMember(jss::LastLedgerSequence)); @@ -3322,12 +3023,9 @@ public: else { BEAST_EXPECT(item.isMember(jss::fee)); - BEAST_EXPECT( - item[jss::fee] == std::to_string(baseFee * 10)); + BEAST_EXPECT(item[jss::fee] == std::to_string(baseFee * 10)); BEAST_EXPECT(item.isMember(jss::max_spend_drops)); - BEAST_EXPECT( - item[jss::max_spend_drops] == - std::to_string(baseFee * 10)); + BEAST_EXPECT(item[jss::max_spend_drops] == std::to_string(baseFee * 10)); BEAST_EXPECT(item.isMember(jss::auth_change)); BEAST_EXPECT(!item[jss::auth_change].asBool()); BEAST_EXPECT(!item.isMember(jss::LastLedgerSequence)); @@ -3336,11 +3034,8 @@ public: } { - auto const info = - env.rpc("json", "account_info", to_string(prevLedgerWithQueue)); - BEAST_EXPECT( - info.isMember(jss::result) && - RPC::contains_error(info[jss::result])); + auto const info = env.rpc("json", "account_info", to_string(prevLedgerWithQueue)); + BEAST_EXPECT(info.isMember(jss::result) && RPC::contains_error(info[jss::result])); } env.close(); @@ -3349,11 +3044,8 @@ public: checkMetrics(*this, env, 0, 10, 0, 5); { - auto const info = - env.rpc("json", "account_info", to_string(withQueue)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withQueue)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& result = info[jss::result]; BEAST_EXPECT(result.isMember(jss::queue_data)); auto const& queue_data = result[jss::queue_data]; @@ -3384,12 +3076,9 @@ public: { auto const server_info = env.rpc("server_info"); - BEAST_EXPECT( - server_info.isMember(jss::result) && - server_info[jss::result].isMember(jss::info)); + BEAST_EXPECT(server_info.isMember(jss::result) && server_info[jss::result].isMember(jss::info)); auto const& info = server_info[jss::result][jss::info]; - BEAST_EXPECT( - info.isMember(jss::load_factor) && info[jss::load_factor] == 1); + BEAST_EXPECT(info.isMember(jss::load_factor) && info[jss::load_factor] == 1); BEAST_EXPECT(!info.isMember(jss::load_factor_server)); BEAST_EXPECT(!info.isMember(jss::load_factor_local)); BEAST_EXPECT(!info.isMember(jss::load_factor_net)); @@ -3398,23 +3087,14 @@ public: { auto const server_state = env.rpc("server_state"); auto const& state = server_state[jss::result][jss::state]; + BEAST_EXPECT(state.isMember(jss::load_factor) && state[jss::load_factor] == 256); + BEAST_EXPECT(state.isMember(jss::load_base) && state[jss::load_base] == 256); + BEAST_EXPECT(state.isMember(jss::load_factor_server) && state[jss::load_factor_server] == 256); BEAST_EXPECT( - state.isMember(jss::load_factor) && - state[jss::load_factor] == 256); + state.isMember(jss::load_factor_fee_escalation) && state[jss::load_factor_fee_escalation] == 256); + BEAST_EXPECT(state.isMember(jss::load_factor_fee_queue) && state[jss::load_factor_fee_queue] == 256); BEAST_EXPECT( - state.isMember(jss::load_base) && state[jss::load_base] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_server) && - state[jss::load_factor_server] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_escalation) && - state[jss::load_factor_fee_escalation] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_queue) && - state[jss::load_factor_fee_queue] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_reference) && - state[jss::load_factor_fee_reference] == 256); + state.isMember(jss::load_factor_fee_reference) && state[jss::load_factor_fee_reference] == 256); } checkMetrics(*this, env, 0, 6, 0, 3); @@ -3425,98 +3105,62 @@ public: auto aliceSeq = env.seq(alice); auto submitParams = Json::Value(Json::objectValue); for (auto i = 0; i < 4; ++i) - envs( - noop(alice), - fee(baseFee * 10), - seq(aliceSeq + i), - ter(terQUEUED))(submitParams); + envs(noop(alice), fee(baseFee * 10), seq(aliceSeq + i), ter(terQUEUED))(submitParams); checkMetrics(*this, env, 4, 6, 4, 3); { auto const server_info = env.rpc("server_info"); - BEAST_EXPECT( - server_info.isMember(jss::result) && - server_info[jss::result].isMember(jss::info)); + BEAST_EXPECT(server_info.isMember(jss::result) && server_info[jss::result].isMember(jss::info)); auto const& info = server_info[jss::result][jss::info]; // Avoid double rounding issues by comparing to a range. BEAST_EXPECT( - info.isMember(jss::load_factor) && - info[jss::load_factor] > 888.88 && - info[jss::load_factor] < 888.89); - BEAST_EXPECT( - info.isMember(jss::load_factor_server) && - info[jss::load_factor_server] == 1); + info.isMember(jss::load_factor) && info[jss::load_factor] > 888.88 && info[jss::load_factor] < 888.89); + BEAST_EXPECT(info.isMember(jss::load_factor_server) && info[jss::load_factor_server] == 1); BEAST_EXPECT(!info.isMember(jss::load_factor_local)); BEAST_EXPECT(!info.isMember(jss::load_factor_net)); BEAST_EXPECT( - info.isMember(jss::load_factor_fee_escalation) && - info[jss::load_factor_fee_escalation] > 888.88 && + info.isMember(jss::load_factor_fee_escalation) && info[jss::load_factor_fee_escalation] > 888.88 && info[jss::load_factor_fee_escalation] < 888.89); } { auto const server_state = env.rpc("server_state"); auto const& state = server_state[jss::result][jss::state]; + BEAST_EXPECT(state.isMember(jss::load_factor) && state[jss::load_factor] == 227555); + BEAST_EXPECT(state.isMember(jss::load_base) && state[jss::load_base] == 256); + BEAST_EXPECT(state.isMember(jss::load_factor_server) && state[jss::load_factor_server] == 256); BEAST_EXPECT( - state.isMember(jss::load_factor) && - state[jss::load_factor] == 227555); + state.isMember(jss::load_factor_fee_escalation) && state[jss::load_factor_fee_escalation] == 227555); + BEAST_EXPECT(state.isMember(jss::load_factor_fee_queue) && state[jss::load_factor_fee_queue] == 256); BEAST_EXPECT( - state.isMember(jss::load_base) && state[jss::load_base] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_server) && - state[jss::load_factor_server] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_escalation) && - state[jss::load_factor_fee_escalation] == 227555); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_queue) && - state[jss::load_factor_fee_queue] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_reference) && - state[jss::load_factor_fee_reference] == 256); + state.isMember(jss::load_factor_fee_reference) && state[jss::load_factor_fee_reference] == 256); } env.app().getFeeTrack().setRemoteFee(256000); { auto const server_info = env.rpc("server_info"); - BEAST_EXPECT( - server_info.isMember(jss::result) && - server_info[jss::result].isMember(jss::info)); + BEAST_EXPECT(server_info.isMember(jss::result) && server_info[jss::result].isMember(jss::info)); auto const& info = server_info[jss::result][jss::info]; // Avoid double rounding issues by comparing to a range. - BEAST_EXPECT( - info.isMember(jss::load_factor) && - info[jss::load_factor] == 1000); + BEAST_EXPECT(info.isMember(jss::load_factor) && info[jss::load_factor] == 1000); BEAST_EXPECT(!info.isMember(jss::load_factor_server)); BEAST_EXPECT(!info.isMember(jss::load_factor_local)); + BEAST_EXPECT(info.isMember(jss::load_factor_net) && info[jss::load_factor_net] == 1000); BEAST_EXPECT( - info.isMember(jss::load_factor_net) && - info[jss::load_factor_net] == 1000); - BEAST_EXPECT( - info.isMember(jss::load_factor_fee_escalation) && - info[jss::load_factor_fee_escalation] > 888.88 && + info.isMember(jss::load_factor_fee_escalation) && info[jss::load_factor_fee_escalation] > 888.88 && info[jss::load_factor_fee_escalation] < 888.89); } { auto const server_state = env.rpc("server_state"); auto const& state = server_state[jss::result][jss::state]; + BEAST_EXPECT(state.isMember(jss::load_factor) && state[jss::load_factor] == 256000); + BEAST_EXPECT(state.isMember(jss::load_base) && state[jss::load_base] == 256); + BEAST_EXPECT(state.isMember(jss::load_factor_server) && state[jss::load_factor_server] == 256000); BEAST_EXPECT( - state.isMember(jss::load_factor) && - state[jss::load_factor] == 256000); + state.isMember(jss::load_factor_fee_escalation) && state[jss::load_factor_fee_escalation] == 227555); + BEAST_EXPECT(state.isMember(jss::load_factor_fee_queue) && state[jss::load_factor_fee_queue] == 256); BEAST_EXPECT( - state.isMember(jss::load_base) && state[jss::load_base] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_server) && - state[jss::load_factor_server] == 256000); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_escalation) && - state[jss::load_factor_fee_escalation] == 227555); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_queue) && - state[jss::load_factor_fee_queue] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_reference) && - state[jss::load_factor_fee_reference] == 256); + state.isMember(jss::load_factor_fee_reference) && state[jss::load_factor_fee_reference] == 256); } env.app().getFeeTrack().setRemoteFee(256); @@ -3528,65 +3172,48 @@ public: { auto const server_info = env.rpc("server_info"); - BEAST_EXPECT( - server_info.isMember(jss::result) && - server_info[jss::result].isMember(jss::info)); + BEAST_EXPECT(server_info.isMember(jss::result) && server_info[jss::result].isMember(jss::info)); auto const& info = server_info[jss::result][jss::info]; // Avoid double rounding issues by comparing to a range. BEAST_EXPECT( - info.isMember(jss::load_factor) && - info[jss::load_factor] > 888.88 && - info[jss::load_factor] < 888.89); + info.isMember(jss::load_factor) && info[jss::load_factor] > 888.88 && info[jss::load_factor] < 888.89); // There can be a race between LoadManager lowering the fee, // and the call to server_info, so check a wide range. // The important thing is that it's not 1. BEAST_EXPECT( - info.isMember(jss::load_factor_server) && - info[jss::load_factor_server] > 1.245 && + info.isMember(jss::load_factor_server) && info[jss::load_factor_server] > 1.245 && info[jss::load_factor_server] < 2.4415); BEAST_EXPECT( - info.isMember(jss::load_factor_local) && - info[jss::load_factor_local] > 1.245 && + info.isMember(jss::load_factor_local) && info[jss::load_factor_local] > 1.245 && info[jss::load_factor_local] < 2.4415); BEAST_EXPECT(!info.isMember(jss::load_factor_net)); BEAST_EXPECT( - info.isMember(jss::load_factor_fee_escalation) && - info[jss::load_factor_fee_escalation] > 888.88 && + info.isMember(jss::load_factor_fee_escalation) && info[jss::load_factor_fee_escalation] > 888.88 && info[jss::load_factor_fee_escalation] < 888.89); } { auto const server_state = env.rpc("server_state"); auto const& state = server_state[jss::result][jss::state]; - BEAST_EXPECT( - state.isMember(jss::load_factor) && - state[jss::load_factor] == 227555); - BEAST_EXPECT( - state.isMember(jss::load_base) && state[jss::load_base] == 256); + BEAST_EXPECT(state.isMember(jss::load_factor) && state[jss::load_factor] == 227555); + BEAST_EXPECT(state.isMember(jss::load_base) && state[jss::load_base] == 256); // There can be a race between LoadManager lowering the fee, // and the call to server_info, so check a wide range. // The important thing is that it's not 256. BEAST_EXPECT( - state.isMember(jss::load_factor_server) && - state[jss::load_factor_server] >= 320 && + state.isMember(jss::load_factor_server) && state[jss::load_factor_server] >= 320 && state[jss::load_factor_server] <= 625); BEAST_EXPECT( - state.isMember(jss::load_factor_fee_escalation) && - state[jss::load_factor_fee_escalation] == 227555); + state.isMember(jss::load_factor_fee_escalation) && state[jss::load_factor_fee_escalation] == 227555); + BEAST_EXPECT(state.isMember(jss::load_factor_fee_queue) && state[jss::load_factor_fee_queue] == 256); BEAST_EXPECT( - state.isMember(jss::load_factor_fee_queue) && - state[jss::load_factor_fee_queue] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_reference) && - state[jss::load_factor_fee_reference] == 256); + state.isMember(jss::load_factor_fee_reference) && state[jss::load_factor_fee_reference] == 256); } env.close(); { auto const server_info = env.rpc("server_info"); - BEAST_EXPECT( - server_info.isMember(jss::result) && - server_info[jss::result].isMember(jss::info)); + BEAST_EXPECT(server_info.isMember(jss::result) && server_info[jss::result].isMember(jss::info)); auto const& info = server_info[jss::result][jss::info]; // Avoid double rounding issues by comparing to a range. @@ -3594,13 +3221,10 @@ public: // and the call to server_info, so check a wide range. // The important thing is that it's not 1. BEAST_EXPECT( - info.isMember(jss::load_factor) && - info[jss::load_factor] > 1.245 && - info[jss::load_factor] < 2.4415); + info.isMember(jss::load_factor) && info[jss::load_factor] > 1.245 && info[jss::load_factor] < 2.4415); BEAST_EXPECT(!info.isMember(jss::load_factor_server)); BEAST_EXPECT( - info.isMember(jss::load_factor_local) && - info[jss::load_factor_local] > 1.245 && + info.isMember(jss::load_factor_local) && info[jss::load_factor_local] > 1.245 && info[jss::load_factor_local] < 2.4415); BEAST_EXPECT(!info.isMember(jss::load_factor_net)); BEAST_EXPECT(!info.isMember(jss::load_factor_fee_escalation)); @@ -3609,27 +3233,19 @@ public: auto const server_state = env.rpc("server_state"); auto const& state = server_state[jss::result][jss::state]; BEAST_EXPECT( - state.isMember(jss::load_factor) && - state[jss::load_factor] >= 320 && - state[jss::load_factor] <= 625); - BEAST_EXPECT( - state.isMember(jss::load_base) && state[jss::load_base] == 256); + state.isMember(jss::load_factor) && state[jss::load_factor] >= 320 && state[jss::load_factor] <= 625); + BEAST_EXPECT(state.isMember(jss::load_base) && state[jss::load_base] == 256); // There can be a race between LoadManager lowering the fee, // and the call to server_info, so check a wide range. // The important thing is that it's not 256. BEAST_EXPECT( - state.isMember(jss::load_factor_server) && - state[jss::load_factor_server] >= 320 && + state.isMember(jss::load_factor_server) && state[jss::load_factor_server] >= 320 && state[jss::load_factor_server] <= 625); BEAST_EXPECT( - state.isMember(jss::load_factor_fee_escalation) && - state[jss::load_factor_fee_escalation] == 256); + state.isMember(jss::load_factor_fee_escalation) && state[jss::load_factor_fee_escalation] == 256); + BEAST_EXPECT(state.isMember(jss::load_factor_fee_queue) && state[jss::load_factor_fee_queue] == 256); BEAST_EXPECT( - state.isMember(jss::load_factor_fee_queue) && - state[jss::load_factor_fee_queue] == 256); - BEAST_EXPECT( - state.isMember(jss::load_factor_fee_reference) && - state[jss::load_factor_fee_reference] == 256); + state.isMember(jss::load_factor_fee_reference) && state[jss::load_factor_fee_reference] == 256); } } @@ -3651,8 +3267,7 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); } - Account a{"a"}, b{"b"}, c{"c"}, d{"d"}, e{"e"}, f{"f"}, g{"g"}, h{"h"}, - i{"i"}; + Account a{"a"}, b{"b"}, c{"c"}, d{"d"}, e{"e"}, f{"f"}, g{"g"}, h{"h"}, i{"i"}; // Fund the first few accounts at non escalated fee env.fund(XRP(50000), noripple(a, b, c, d)); @@ -3661,31 +3276,20 @@ public: // First transaction establishes the messaging using namespace std::chrono_literals; BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::type] == "serverStatus" && - jv.isMember(jss::load_factor) && jv[jss::load_factor] == 256 && - jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && - jv.isMember(jss::load_factor_server) && - jv[jss::load_factor_server] == 256 && - jv.isMember(jss::load_factor_fee_escalation) && - jv[jss::load_factor_fee_escalation] == 256 && - jv.isMember(jss::load_factor_fee_queue) && - jv[jss::load_factor_fee_queue] == 256 && - jv.isMember(jss::load_factor_fee_reference) && + return jv[jss::type] == "serverStatus" && jv.isMember(jss::load_factor) && jv[jss::load_factor] == 256 && + jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && jv.isMember(jss::load_factor_server) && + jv[jss::load_factor_server] == 256 && jv.isMember(jss::load_factor_fee_escalation) && + jv[jss::load_factor_fee_escalation] == 256 && jv.isMember(jss::load_factor_fee_queue) && + jv[jss::load_factor_fee_queue] == 256 && jv.isMember(jss::load_factor_fee_reference) && jv[jss::load_factor_fee_reference] == 256; })); // Last transaction escalates the fee BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::type] == "serverStatus" && - jv.isMember(jss::load_factor) && - jv[jss::load_factor] == 227555 && jv.isMember(jss::load_base) && - jv[jss::load_base] == 256 && - jv.isMember(jss::load_factor_server) && - jv[jss::load_factor_server] == 256 && - jv.isMember(jss::load_factor_fee_escalation) && - jv[jss::load_factor_fee_escalation] == 227555 && - jv.isMember(jss::load_factor_fee_queue) && - jv[jss::load_factor_fee_queue] == 256 && - jv.isMember(jss::load_factor_fee_reference) && + return jv[jss::type] == "serverStatus" && jv.isMember(jss::load_factor) && jv[jss::load_factor] == 227555 && + jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && jv.isMember(jss::load_factor_server) && + jv[jss::load_factor_server] == 256 && jv.isMember(jss::load_factor_fee_escalation) && + jv[jss::load_factor_fee_escalation] == 227555 && jv.isMember(jss::load_factor_fee_queue) && + jv[jss::load_factor_fee_queue] == 256 && jv.isMember(jss::load_factor_fee_reference) && jv[jss::load_factor_fee_reference] == 256; })); @@ -3693,16 +3297,11 @@ public: // Closing ledger should publish a status update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::type] == "serverStatus" && - jv.isMember(jss::load_factor) && jv[jss::load_factor] == 256 && - jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && - jv.isMember(jss::load_factor_server) && - jv[jss::load_factor_server] == 256 && - jv.isMember(jss::load_factor_fee_escalation) && - jv[jss::load_factor_fee_escalation] == 256 && - jv.isMember(jss::load_factor_fee_queue) && - jv[jss::load_factor_fee_queue] == 256 && - jv.isMember(jss::load_factor_fee_reference) && + return jv[jss::type] == "serverStatus" && jv.isMember(jss::load_factor) && jv[jss::load_factor] == 256 && + jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && jv.isMember(jss::load_factor_server) && + jv[jss::load_factor_server] == 256 && jv.isMember(jss::load_factor_fee_escalation) && + jv[jss::load_factor_fee_escalation] == 256 && jv.isMember(jss::load_factor_fee_queue) && + jv[jss::load_factor_fee_queue] == 256 && jv.isMember(jss::load_factor_fee_reference) && jv[jss::load_factor_fee_reference] == 256; })); @@ -3724,56 +3323,37 @@ public: // Last transaction escalates the fee BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::type] == "serverStatus" && - jv.isMember(jss::load_factor) && - jv[jss::load_factor] == 200000 && jv.isMember(jss::load_base) && - jv[jss::load_base] == 256 && - jv.isMember(jss::load_factor_server) && - jv[jss::load_factor_server] == 256 && - jv.isMember(jss::load_factor_fee_escalation) && - jv[jss::load_factor_fee_escalation] == 200000 && - jv.isMember(jss::load_factor_fee_queue) && - jv[jss::load_factor_fee_queue] == 256 && - jv.isMember(jss::load_factor_fee_reference) && + return jv[jss::type] == "serverStatus" && jv.isMember(jss::load_factor) && jv[jss::load_factor] == 200000 && + jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && jv.isMember(jss::load_factor_server) && + jv[jss::load_factor_server] == 256 && jv.isMember(jss::load_factor_fee_escalation) && + jv[jss::load_factor_fee_escalation] == 200000 && jv.isMember(jss::load_factor_fee_queue) && + jv[jss::load_factor_fee_queue] == 256 && jv.isMember(jss::load_factor_fee_reference) && jv[jss::load_factor_fee_reference] == 256; })); env.close(); // Ledger close publishes with escalated fees for queued transactions BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::type] == "serverStatus" && - jv.isMember(jss::load_factor) && - jv[jss::load_factor] == 184320 && jv.isMember(jss::load_base) && - jv[jss::load_base] == 256 && - jv.isMember(jss::load_factor_server) && - jv[jss::load_factor_server] == 256 && - jv.isMember(jss::load_factor_fee_escalation) && - jv[jss::load_factor_fee_escalation] == 184320 && - jv.isMember(jss::load_factor_fee_queue) && - jv[jss::load_factor_fee_queue] == 256 && - jv.isMember(jss::load_factor_fee_reference) && + return jv[jss::type] == "serverStatus" && jv.isMember(jss::load_factor) && jv[jss::load_factor] == 184320 && + jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && jv.isMember(jss::load_factor_server) && + jv[jss::load_factor_server] == 256 && jv.isMember(jss::load_factor_fee_escalation) && + jv[jss::load_factor_fee_escalation] == 184320 && jv.isMember(jss::load_factor_fee_queue) && + jv[jss::load_factor_fee_queue] == 256 && jv.isMember(jss::load_factor_fee_reference) && jv[jss::load_factor_fee_reference] == 256; })); env.close(); // ledger close clears queue so fee is back to normal BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::type] == "serverStatus" && - jv.isMember(jss::load_factor) && jv[jss::load_factor] == 256 && - jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && - jv.isMember(jss::load_factor_server) && - jv[jss::load_factor_server] == 256 && - jv.isMember(jss::load_factor_fee_escalation) && - jv[jss::load_factor_fee_escalation] == 256 && - jv.isMember(jss::load_factor_fee_queue) && - jv[jss::load_factor_fee_queue] == 256 && - jv.isMember(jss::load_factor_fee_reference) && + return jv[jss::type] == "serverStatus" && jv.isMember(jss::load_factor) && jv[jss::load_factor] == 256 && + jv.isMember(jss::load_base) && jv[jss::load_base] == 256 && jv.isMember(jss::load_factor_server) && + jv[jss::load_factor_server] == 256 && jv.isMember(jss::load_factor_fee_escalation) && + jv[jss::load_factor_fee_escalation] == 256 && jv.isMember(jss::load_factor_fee_queue) && + jv[jss::load_factor_fee_queue] == 256 && jv.isMember(jss::load_factor_fee_reference) && jv[jss::load_factor_fee_reference] == 256; })); - BEAST_EXPECT(!wsc->findMsg(1s, [&](auto const& jv) { - return jv[jss::type] == "serverStatus"; - })); + BEAST_EXPECT(!wsc->findMsg(1s, [&](auto const& jv) { return jv[jss::type] == "serverStatus"; })); auto jv = wsc->invoke("unsubscribe", stream); BEAST_EXPECT(jv[jss::status] == "success"); @@ -3796,8 +3376,7 @@ public: fillQueue(env, alice); auto calcTotalFee = [&](std::int64_t alreadyPaid, - std::optional numToClear = - std::nullopt) -> std::uint64_t { + std::optional numToClear = std::nullopt) -> std::uint64_t { auto totalFactor = 0; auto const metrics = env.app().getTxQ().getMetrics(*env.current()); if (!numToClear) @@ -3809,8 +3388,7 @@ public: } auto const den = (metrics.txPerLedger * metrics.txPerLedger); - FeeLevel64 feeLevel = - (metrics.medFeeLevel * totalFactor + FeeLevel64{den - 1}) / den; + FeeLevel64 feeLevel = (metrics.medFeeLevel * totalFactor + FeeLevel64{den - 1}) / den; auto result = toDrops(feeLevel, env.current()->fees().base).drops(); @@ -3828,10 +3406,7 @@ public: std::uint64_t totalPaid = 0; for (int i = 0; i < 2; ++i) { - env(noop(alice), - fee(baseFee * 10), - seq(aliceSeq++), - ter(terQUEUED)); + env(noop(alice), fee(baseFee * 10), seq(aliceSeq++), ter(terQUEUED)); totalPaid += baseFee * 10; } @@ -3839,10 +3414,7 @@ public: // This will be the first tx to call the operative function, // but it won't succeed. totalPaid += openLedgerCost(env).drops(); - env(noop(alice), - fee(openLedgerCost(env)), - seq(aliceSeq++), - ter(terQUEUED)); + env(noop(alice), fee(openLedgerCost(env)), seq(aliceSeq++), ter(terQUEUED)); checkMetrics(*this, env, 3, std::nullopt, 4, 3); @@ -3876,28 +3448,21 @@ public: uint64_t totalPaid = 0; for (int i = 0; i < 2; ++i) { - env(noop(alice), - fee(baseFee * 10), - seq(aliceSeq++), - ter(terQUEUED)); + env(noop(alice), fee(baseFee * 10), seq(aliceSeq++), ter(terQUEUED)); totalPaid += baseFee * 10; } // Queue up a transaction paying the open ledger fee // This will be the first tx to call the operative function, // but it won't succeed. - env(noop(alice), - fee(openLedgerCost(env)), - seq(aliceSeq++), - ter(terQUEUED)); + env(noop(alice), fee(openLedgerCost(env)), seq(aliceSeq++), ter(terQUEUED)); checkMetrics(*this, env, 3, std::nullopt, 9, 3); // Figure out how much it would cost to cover all the // queued txs + itself auto const metrics = env.app().getTxQ().getMetrics(*env.current()); - std::uint64_t const totalFee = - calcTotalFee(totalPaid, metrics.txCount); + std::uint64_t const totalFee = calcTotalFee(totalPaid, metrics.txCount); // Replacing the last tx with the large fee succeeds. --aliceSeq; env(noop(alice), fee(totalFee), seq(aliceSeq++)); @@ -3916,10 +3481,7 @@ public: auto aliceSeq = env.seq(alice); for (int i = 0; i < 5; ++i) { - env(noop(alice), - fee(baseFee * 10), - seq(aliceSeq++), - ter(terQUEUED)); + env(noop(alice), fee(baseFee * 10), seq(aliceSeq++), ter(terQUEUED)); } checkMetrics(*this, env, 5, 24, 13, 12); @@ -3931,15 +3493,13 @@ public: env(noop(alice), fee(totalFee), seq(aliceSeq++)); checkMetrics(*this, env, 2, 24, 16, 12); - auto const aliceQueue = - env.app().getTxQ().getAccountTxs(alice.id()); + auto const aliceQueue = env.app().getTxQ().getAccountTxs(alice.id()); BEAST_EXPECT(aliceQueue.size() == 2); SeqProxy seq = SeqProxy::sequence(aliceSeq); for (auto const& tx : aliceQueue) { BEAST_EXPECT(tx.seqProxy == seq); - BEAST_EXPECT( - tx.feeLevel == FeeLevel64{baseFeeLevel.fee() * 10}); + BEAST_EXPECT(tx.feeLevel == FeeLevel64{baseFeeLevel.fee() * 10}); seq.advanceBy(1); } @@ -3956,18 +3516,12 @@ public: uint64_t totalPaid = 0; for (int i = 0; i < 2; ++i) { - env(noop(alice), - fee(baseFee * 20), - seq(aliceSeq++), - ter(terQUEUED)); + env(noop(alice), fee(baseFee * 20), seq(aliceSeq++), ter(terQUEUED)); totalPaid += baseFee * 20; } for (int i = 0; i < 2; ++i) { - env(noop(alice), - fee(baseFee * 2.2), - seq(aliceSeq++), - ter(terQUEUED)); + env(noop(alice), fee(baseFee * 2.2), seq(aliceSeq++), ter(terQUEUED)); totalPaid += baseFee * 2.2; } @@ -4188,10 +3742,8 @@ public: // which won't work if unit tests are separated to only // be callable via RPC.) env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { - auto const tx = - env.jt(noop(alice), seq(aliceSeq), fee(openLedgerCost(env))); - auto const result = - xrpl::apply(env.app(), view, *tx.stx, tapUNLIMITED, j); + auto const tx = env.jt(noop(alice), seq(aliceSeq), fee(openLedgerCost(env))); + auto const result = xrpl::apply(env.app(), view, *tx.stx, tapUNLIMITED, j); BEAST_EXPECT(result.ter == tesSUCCESS && result.applied); return result.applied; }); @@ -4258,12 +3810,8 @@ public: // which won't work if unit tests are separated to only // be callable via RPC.) env.app().openLedger().modify([&](OpenView& view, beast::Journal j) { - auto const tx = env.jt( - noop(alice), - ticket::use(tktSeq0 + 1), - fee(openLedgerCost(env))); - auto const result = - xrpl::apply(env.app(), view, *tx.stx, tapUNLIMITED, j); + auto const tx = env.jt(noop(alice), ticket::use(tktSeq0 + 1), fee(openLedgerCost(env))); + auto const result = xrpl::apply(env.app(), view, *tx.stx, tapUNLIMITED, j); BEAST_EXPECT(result.ter == tesSUCCESS && result.applied); return result.applied; }); @@ -4338,12 +3886,9 @@ public: {{"account_reserve", "1000"}, {"owner_reserve", "50"}}); auto& votingSection = cfg->section("voting"); - votingSection.set( - "account_reserve", - std::to_string(cfg->FEES.reference_fee.drops() * 100)); + votingSection.set("account_reserve", std::to_string(cfg->FEES.reference_fee.drops() * 100)); - votingSection.set( - "reference_fee", std::to_string(cfg->FEES.reference_fee.drops())); + votingSection.set("reference_fee", std::to_string(cfg->FEES.reference_fee.drops())); Env env(*this, std::move(cfg)); @@ -4372,13 +3917,7 @@ public: break; } auto expectedPerLedger = xrpl::detail::numUpVotedAmendments() + 1; - checkMetrics( - *this, - env, - 0, - ledgersInQueue * expectedPerLedger, - 0, - expectedPerLedger); + checkMetrics(*this, env, 0, ledgersInQueue * expectedPerLedger, 0, expectedPerLedger); // Now wait 2 weeks modulo 256 ledgers for the amendments to be // enabled. Speed the process by closing ledgers every 80 minutes, @@ -4393,13 +3932,7 @@ public: auto const baseFee = env.current()->fees().base.drops(); // We're very close to the flag ledger. Fill the ledger. fillQueue(env, alice); - checkMetrics( - *this, - env, - 0, - ledgersInQueue * expectedPerLedger, - expectedPerLedger + 1, - expectedPerLedger); + checkMetrics(*this, env, 0, ledgersInQueue * expectedPerLedger, expectedPerLedger + 1, expectedPerLedger); // Fill everyone's queues. auto seqAlice = env.seq(alice); @@ -4411,46 +3944,21 @@ public: // Use fees to guarantee order int txFee{static_cast(baseFee * 9)}; - auto prepareFee = [&](uint64_t multiplier) { - return fee(txFee - multiplier * baseFee / 10); - }; + auto prepareFee = [&](uint64_t multiplier) { return fee(txFee - multiplier * baseFee / 10); }; uint64_t multiplier = 0; for (int i = 0; i < 10; ++i) { - env(noop(alice), - seq(seqAlice++), - prepareFee(++multiplier), - ter(terQUEUED)); - env(noop(bob), - seq(seqBob++), - prepareFee(++multiplier), - ter(terQUEUED)); - env(noop(carol), - seq(seqCarol++), - prepareFee(++multiplier), - ter(terQUEUED)); - env(noop(daria), - seq(seqDaria++), - prepareFee(++multiplier), - ter(terQUEUED)); - env(noop(ellie), - seq(seqEllie++), - prepareFee(++multiplier), - ter(terQUEUED)); - env(noop(fiona), - seq(seqFiona++), - prepareFee(++multiplier), - ter(terQUEUED)); + env(noop(alice), seq(seqAlice++), prepareFee(++multiplier), ter(terQUEUED)); + env(noop(bob), seq(seqBob++), prepareFee(++multiplier), ter(terQUEUED)); + env(noop(carol), seq(seqCarol++), prepareFee(++multiplier), ter(terQUEUED)); + env(noop(daria), seq(seqDaria++), prepareFee(++multiplier), ter(terQUEUED)); + env(noop(ellie), seq(seqEllie++), prepareFee(++multiplier), ter(terQUEUED)); + env(noop(fiona), seq(seqFiona++), prepareFee(++multiplier), ter(terQUEUED)); } std::size_t expectedInQueue = multiplier; checkMetrics( - *this, - env, - expectedInQueue, - ledgersInQueue * expectedPerLedger, - expectedPerLedger + 1, - expectedPerLedger); + *this, env, expectedInQueue, ledgersInQueue * expectedPerLedger, expectedPerLedger + 1, expectedPerLedger); // The next close should cause the in-ledger amendments to change. // Alice's queued transactions have a cached PreflightResult @@ -4465,43 +3973,20 @@ public: { env.close(closeDuration); auto expectedInLedger = expectedInQueue; - expectedInQueue = - (expectedInQueue > expectedPerLedger + 2 - ? expectedInQueue - (expectedPerLedger + 2) - : 0); + expectedInQueue = (expectedInQueue > expectedPerLedger + 2 ? expectedInQueue - (expectedPerLedger + 2) : 0); expectedInLedger -= expectedInQueue; ++expectedPerLedger; checkMetrics( - *this, - env, - expectedInQueue, - ledgersInQueue * expectedPerLedger, - expectedInLedger, - expectedPerLedger); + *this, env, expectedInQueue, ledgersInQueue * expectedPerLedger, expectedInLedger, expectedPerLedger); { auto const expectedPerAccount = expectedInQueue / 6; auto const expectedRemainder = expectedInQueue % 6; BEAST_EXPECT(env.seq(alice) == seqAlice - expectedPerAccount); - BEAST_EXPECT( - env.seq(bob) == - seqBob - expectedPerAccount - - (expectedRemainder > 4 ? 1 : 0)); - BEAST_EXPECT( - env.seq(carol) == - seqCarol - expectedPerAccount - - (expectedRemainder > 3 ? 1 : 0)); - BEAST_EXPECT( - env.seq(daria) == - seqDaria - expectedPerAccount - - (expectedRemainder > 2 ? 1 : 0)); - BEAST_EXPECT( - env.seq(ellie) == - seqEllie - expectedPerAccount - - (expectedRemainder > 1 ? 1 : 0)); - BEAST_EXPECT( - env.seq(fiona) == - seqFiona - expectedPerAccount - - (expectedRemainder > 0 ? 1 : 0)); + BEAST_EXPECT(env.seq(bob) == seqBob - expectedPerAccount - (expectedRemainder > 4 ? 1 : 0)); + BEAST_EXPECT(env.seq(carol) == seqCarol - expectedPerAccount - (expectedRemainder > 3 ? 1 : 0)); + BEAST_EXPECT(env.seq(daria) == seqDaria - expectedPerAccount - (expectedRemainder > 2 ? 1 : 0)); + BEAST_EXPECT(env.seq(ellie) == seqEllie - expectedPerAccount - (expectedRemainder > 1 ? 1 : 0)); + BEAST_EXPECT(env.seq(fiona) == seqFiona - expectedPerAccount - (expectedRemainder > 0 ? 1 : 0)); } } while (expectedInQueue > 0); } @@ -4566,29 +4051,16 @@ public: auto seqAlice = env.seq(alice); auto const seqSaveAlice = seqAlice; int feeDrops = baseFee * 4; - env(noop(alice), - seq(seqAlice++), - fee(--feeDrops), - last_ledger_seq(7), - ter(terQUEUED)); + env(noop(alice), seq(seqAlice++), fee(--feeDrops), last_ledger_seq(7), ter(terQUEUED)); env(noop(alice), seq(seqAlice++), fee(--feeDrops), ter(terQUEUED)); env(noop(alice), seq(seqAlice++), fee(--feeDrops), ter(terQUEUED)); BEAST_EXPECT(env.seq(alice) == seqSaveAlice); // Similarly for bob, but bob uses tickets in his transactions. // The drop penalty works a little differently with tickets. - env(noop(bob), - ticket::use(bobTicketSeq + 0), - last_ledger_seq(7), - ter(terQUEUED)); - env(noop(bob), - ticket::use(bobTicketSeq + 1), - fee(--feeDrops), - ter(terQUEUED)); - env(noop(bob), - ticket::use(bobTicketSeq + 2), - fee(--feeDrops), - ter(terQUEUED)); + env(noop(bob), ticket::use(bobTicketSeq + 0), last_ledger_seq(7), ter(terQUEUED)); + env(noop(bob), ticket::use(bobTicketSeq + 1), fee(--feeDrops), ter(terQUEUED)); + env(noop(bob), ticket::use(bobTicketSeq + 2), fee(--feeDrops), ter(terQUEUED)); // Fill the queue with higher fee transactions so alice's and // bob's transactions are stuck in the queue. @@ -4731,23 +4203,15 @@ public: // Verify that bob's first transaction was removed from the queue // by queueing another low fee transaction into that spot. - env(noop(bob), - ticket::use(bobTicketSeq + 0), - fee(baseFee * 1.2), - ter(terQUEUED)); + env(noop(bob), ticket::use(bobTicketSeq + 0), fee(baseFee * 1.2), ter(terQUEUED)); // Verify that bob's second transaction was removed from the queue // by queueing another low fee transaction into that spot. - env(noop(bob), - ticket::use(bobTicketSeq + 1), - fee(baseFee * 1.1), - ter(terQUEUED)); + env(noop(bob), ticket::use(bobTicketSeq + 1), fee(baseFee * 1.1), ter(terQUEUED)); // Verify that the last entry in bob's queue is still there // by trying to replace it and having that fail. - env(noop(bob), - ticket::use(bobTicketSeq + 2), - ter(telCAN_NOT_QUEUE_FEE)); + env(noop(bob), ticket::use(bobTicketSeq + 2), ter(telCAN_NOT_QUEUE_FEE)); } void @@ -4781,9 +4245,7 @@ public: auto const aliceSeq = env.seq(alice); env(offer(alice, USD(1000), XRP(1000)), ter(terQUEUED)); - env(offer(alice, USD(1000), XRP(1001)), - seq(aliceSeq + 1), - ter(terQUEUED)); + env(offer(alice, USD(1000), XRP(1001)), seq(aliceSeq + 1), ter(terQUEUED)); // Alice creates transactions that cancel the first set of // offers, one through another offer, and one cancel @@ -4792,9 +4254,7 @@ public: json(jss::OfferSequence, aliceSeq), ter(terQUEUED)); - env(offer_cancel(alice, aliceSeq + 1), - seq(aliceSeq + 3), - ter(terQUEUED)); + env(offer_cancel(alice, aliceSeq + 1), seq(aliceSeq + 3), ter(terQUEUED)); env.close(); @@ -4814,13 +4274,9 @@ public: // Alice creates a couple offers using tickets, consuming the // tickets in reverse order auto const aliceSeq = env.seq(alice); - env(offer(alice, USD(1000), XRP(1000)), - ticket::use(aliceTkt + 4), - ter(terQUEUED)); + env(offer(alice, USD(1000), XRP(1000)), ticket::use(aliceTkt + 4), ter(terQUEUED)); - env(offer(alice, USD(1000), XRP(1001)), - ticket::use(aliceTkt + 3), - ter(terQUEUED)); + env(offer(alice, USD(1000), XRP(1001)), ticket::use(aliceTkt + 3), ter(terQUEUED)); // Alice creates a couple more transactions that cancel the first // set of offers, also in reverse order. This allows Alice to submit @@ -4833,16 +4289,12 @@ public: json(jss::OfferSequence, aliceTkt + 4), ter(terQUEUED)); - env(offer_cancel(alice, aliceTkt + 3), - ticket::use(aliceTkt + 1), - ter(terQUEUED)); + env(offer_cancel(alice, aliceTkt + 3), ticket::use(aliceTkt + 1), ter(terQUEUED)); // Create a couple more offers using sequences env(offer(alice, USD(1000), XRP(1000)), ter(terQUEUED)); - env(offer(alice, USD(1000), XRP(1001)), - seq(aliceSeq + 1), - ter(terQUEUED)); + env(offer(alice, USD(1000), XRP(1001)), seq(aliceSeq + 1), ter(terQUEUED)); // And try to cancel those using tickets env(offer(alice, USD(1000), XRP(1002)), @@ -4850,9 +4302,7 @@ public: json(jss::OfferSequence, aliceSeq), ter(terQUEUED)); - env(offer_cancel(alice, aliceSeq + 1), - ticket::use(aliceTkt + 6), - ter(terQUEUED)); + env(offer_cancel(alice, aliceSeq + 1), ticket::use(aliceTkt + 6), ter(terQUEUED)); env.close(); @@ -4876,9 +4326,7 @@ public: *this, makeConfig( {{"minimum_txn_in_ledger_standalone", "3"}}, - {{"reference_fee", "0"}, - {"account_reserve", "0"}, - {"owner_reserve", "0"}})); + {{"reference_fee", "0"}, {"account_reserve", "0"}, {"owner_reserve", "0"}})); checkMetrics(*this, env, 0, std::nullopt, 0, 3); @@ -4890,39 +4338,22 @@ public: { auto const fee = env.rpc("fee"); - if (BEAST_EXPECT(fee.isMember(jss::result)) && - BEAST_EXPECT(!RPC::contains_error(fee[jss::result]))) + if (BEAST_EXPECT(fee.isMember(jss::result)) && BEAST_EXPECT(!RPC::contains_error(fee[jss::result]))) { auto const& result = fee[jss::result]; BEAST_EXPECT(result.isMember(jss::levels)); auto const& levels = result[jss::levels]; - BEAST_EXPECT( - levels.isMember(jss::median_level) && - levels[jss::median_level] == "128000"); - BEAST_EXPECT( - levels.isMember(jss::minimum_level) && - levels[jss::minimum_level] == "256"); - BEAST_EXPECT( - levels.isMember(jss::open_ledger_level) && - levels[jss::open_ledger_level] == "256"); - BEAST_EXPECT( - levels.isMember(jss::reference_level) && - levels[jss::reference_level] == "256"); + BEAST_EXPECT(levels.isMember(jss::median_level) && levels[jss::median_level] == "128000"); + BEAST_EXPECT(levels.isMember(jss::minimum_level) && levels[jss::minimum_level] == "256"); + BEAST_EXPECT(levels.isMember(jss::open_ledger_level) && levels[jss::open_ledger_level] == "256"); + BEAST_EXPECT(levels.isMember(jss::reference_level) && levels[jss::reference_level] == "256"); auto const& drops = result[jss::drops]; - BEAST_EXPECT( - drops.isMember(jss::base_fee) && - drops[jss::base_fee] == "0"); - BEAST_EXPECT( - drops.isMember(jss::median_fee) && - drops[jss::median_fee] == "0"); - BEAST_EXPECT( - drops.isMember(jss::minimum_fee) && - drops[jss::minimum_fee] == "0"); - BEAST_EXPECT( - drops.isMember(jss::open_ledger_fee) && - drops[jss::open_ledger_fee] == "0"); + BEAST_EXPECT(drops.isMember(jss::base_fee) && drops[jss::base_fee] == "0"); + BEAST_EXPECT(drops.isMember(jss::median_fee) && drops[jss::median_fee] == "0"); + BEAST_EXPECT(drops.isMember(jss::minimum_fee) && drops[jss::minimum_fee] == "0"); + BEAST_EXPECT(drops.isMember(jss::open_ledger_fee) && drops[jss::open_ledger_fee] == "0"); } } @@ -4958,39 +4389,22 @@ public: { auto const fee = env.rpc("fee"); - if (BEAST_EXPECT(fee.isMember(jss::result)) && - BEAST_EXPECT(!RPC::contains_error(fee[jss::result]))) + if (BEAST_EXPECT(fee.isMember(jss::result)) && BEAST_EXPECT(!RPC::contains_error(fee[jss::result]))) { auto const& result = fee[jss::result]; BEAST_EXPECT(result.isMember(jss::levels)); auto const& levels = result[jss::levels]; - BEAST_EXPECT( - levels.isMember(jss::median_level) && - levels[jss::median_level] == "128000"); - BEAST_EXPECT( - levels.isMember(jss::minimum_level) && - levels[jss::minimum_level] == "256"); - BEAST_EXPECT( - levels.isMember(jss::open_ledger_level) && - levels[jss::open_ledger_level] == "355555"); - BEAST_EXPECT( - levels.isMember(jss::reference_level) && - levels[jss::reference_level] == "256"); + BEAST_EXPECT(levels.isMember(jss::median_level) && levels[jss::median_level] == "128000"); + BEAST_EXPECT(levels.isMember(jss::minimum_level) && levels[jss::minimum_level] == "256"); + BEAST_EXPECT(levels.isMember(jss::open_ledger_level) && levels[jss::open_ledger_level] == "355555"); + BEAST_EXPECT(levels.isMember(jss::reference_level) && levels[jss::reference_level] == "256"); auto const& drops = result[jss::drops]; - BEAST_EXPECT( - drops.isMember(jss::base_fee) && - drops[jss::base_fee] == "0"); - BEAST_EXPECT( - drops.isMember(jss::median_fee) && - drops[jss::median_fee] == "0"); - BEAST_EXPECT( - drops.isMember(jss::minimum_fee) && - drops[jss::minimum_fee] == "0"); - BEAST_EXPECT( - drops.isMember(jss::open_ledger_fee) && - drops[jss::open_ledger_fee] == "1389"); + BEAST_EXPECT(drops.isMember(jss::base_fee) && drops[jss::base_fee] == "0"); + BEAST_EXPECT(drops.isMember(jss::median_fee) && drops[jss::median_fee] == "0"); + BEAST_EXPECT(drops.isMember(jss::minimum_fee) && drops[jss::minimum_fee] == "0"); + BEAST_EXPECT(drops.isMember(jss::open_ledger_fee) && drops[jss::open_ledger_fee] == "1389"); } } diff --git a/src/test/app/ValidatorKeys_test.cpp b/src/test/app/ValidatorKeys_test.cpp index 943bf5231f..fac8a4bb7e 100644 --- a/src/test/app/ValidatorKeys_test.cpp +++ b/src/test/app/ValidatorKeys_test.cpp @@ -19,8 +19,7 @@ class ValidatorKeys_test : public beast::unit_test::suite std::string const seed = "shUwVw52ofnCUX5m7kPTKzJdr4HEH"; // Used with [validation_token] - std::string const tokenSecretStr = - "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi"; + std::string const tokenSecretStr = "paQmjZ37pKKPMrgadBLsuf9ab7Y7EUNzh27LQrZqoexpAs31nJi"; std::vector const tokenBlob = { " " @@ -61,26 +60,18 @@ public: { // We're only using Env for its Journal. That Journal gives better // coverage in unit tests. - test::jtx::Env env{ - *this, - test::jtx::envconfig(), - nullptr, - beast::severities::kDisabled}; + test::jtx::Env env{*this, test::jtx::envconfig(), nullptr, beast::severities::kDisabled}; beast::Journal journal{env.app().journal("ValidatorKeys_test")}; // Keys/ID when using [validation_seed] - SecretKey const seedSecretKey = - generateSecretKey(KeyType::secp256k1, *parseBase58(seed)); - PublicKey const seedPublicKey = - derivePublicKey(KeyType::secp256k1, seedSecretKey); + SecretKey const seedSecretKey = generateSecretKey(KeyType::secp256k1, *parseBase58(seed)); + PublicKey const seedPublicKey = derivePublicKey(KeyType::secp256k1, seedSecretKey); NodeID const seedNodeID = calcNodeID(seedPublicKey); // Keys when using [validation_token] - auto const tokenSecretKey = - *parseBase58(TokenType::NodePrivate, tokenSecretStr); + auto const tokenSecretKey = *parseBase58(TokenType::NodePrivate, tokenSecretStr); - auto const tokenPublicKey = - derivePublicKey(KeyType::secp256k1, tokenSecretKey); + auto const tokenPublicKey = derivePublicKey(KeyType::secp256k1, tokenSecretKey); auto const m = deserializeManifest(base64_decode(tokenManifest)); BEAST_EXPECT(m); diff --git a/src/test/app/ValidatorList_test.cpp b/src/test/app/ValidatorList_test.cpp index fa3c836cca..4955686966 100644 --- a/src/test/app/ValidatorList_test.cpp +++ b/src/test/app/ValidatorList_test.cpp @@ -42,12 +42,7 @@ private: } static std::string - makeManifestString( - PublicKey const& pk, - SecretKey const& sk, - PublicKey const& spk, - SecretKey const& ssk, - int seq) + makeManifestString(PublicKey const& pk, SecretKey const& sk, PublicKey const& spk, SecretKey const& ssk, int seq) { STObject st(sfGeneric); st[sfSequence] = seq; @@ -59,12 +54,7 @@ private: sign(st, HashPrefix::manifest, *publicKeyType(spk), ssk); } - sign( - st, - HashPrefix::manifest, - *publicKeyType(pk), - sk, - sfMasterSignature); + sign(st, HashPrefix::manifest, *publicKeyType(pk), sk, sfMasterSignature); Serializer s; st.add(s); @@ -79,12 +69,7 @@ private: st[sfSequence] = std::numeric_limits::max(); st[sfPublicKey] = pk; - sign( - st, - HashPrefix::manifest, - *publicKeyType(pk), - sk, - sfMasterSignature); + sign(st, HashPrefix::manifest, *publicKeyType(pk), sk, sfMasterSignature); Serializer s; st.add(s); @@ -101,12 +86,7 @@ private: return { masterPublic, signingKeys.first, - base64_encode(makeManifestString( - masterPublic, - secret, - signingKeys.first, - signingKeys.second, - 1))}; + base64_encode(makeManifestString(masterPublic, secret, signingKeys.first, signingKeys.second, 1))}; } std::string @@ -116,16 +96,16 @@ private: std::size_t validUntil, std::optional validFrom = {}) { - std::string data = "{\"sequence\":" + std::to_string(sequence) + - ",\"expiration\":" + std::to_string(validUntil); + std::string data = + "{\"sequence\":" + std::to_string(sequence) + ",\"expiration\":" + std::to_string(validUntil); if (validFrom) data += ",\"effective\":" + std::to_string(*validFrom); data += ",\"validators\":["; for (auto const& val : validators) { - data += "{\"validation_public_key\":\"" + strHex(val.masterPublic) + - "\",\"manifest\":\"" + val.manifest + "\"},"; + data += "{\"validation_public_key\":\"" + strHex(val.masterPublic) + "\",\"manifest\":\"" + val.manifest + + "\"},"; } data.pop_back(); @@ -134,9 +114,7 @@ private: } std::string - signList( - std::string const& blob, - std::pair const& keys) + signList(std::string const& blob, std::pair const& keys) { auto const data = base64_decode(blob); return strHex(sign(keys.first, keys.second, makeSlice(data))); @@ -176,22 +154,13 @@ private: auto& app = env.app(); { auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); BEAST_EXPECT(trustedKeys->quorum() == 1); } { std::size_t minQuorum = 0; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal, - minQuorum); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal, minQuorum); BEAST_EXPECT(trustedKeys->quorum() == minQuorum); } } @@ -201,8 +170,7 @@ private: { testcase("Config Load"); - jtx::Env env( - *this, jtx::envconfig(), nullptr, beast::severities::kDisabled); + jtx::Env env(*this, jtx::envconfig(), nullptr, beast::severities::kDisabled); auto& app = env.app(); std::vector const emptyCfgKeys; std::vector const emptyCfgPublishers; @@ -211,18 +179,12 @@ private: auto const localSigningPublicOuter = localSigningKeys.first; auto const localSigningSecret = localSigningKeys.second; auto const localMasterSecret = randomSecretKey(); - auto const localMasterPublic = - derivePublicKey(KeyType::ed25519, localMasterSecret); + auto const localMasterPublic = derivePublicKey(KeyType::ed25519, localMasterSecret); - std::string const cfgManifest(makeManifestString( - localMasterPublic, - localMasterSecret, - localSigningPublicOuter, - localSigningSecret, - 1)); + std::string const cfgManifest( + makeManifestString(localMasterPublic, localMasterSecret, localSigningPublicOuter, localSigningSecret, 1)); - auto format = [](PublicKey const& publicKey, - char const* comment = nullptr) { + auto format = [](PublicKey const& publicKey, char const* comment = nullptr) { auto ret = toBase58(TokenType::NodePublic, publicKey); if (comment) @@ -245,32 +207,23 @@ private: format(configList[3], " Leading Whitespace"), format(configList[4], " Trailing Whitespace "), format(configList[5], " Leading & Trailing Whitespace "), - format( - configList[6], - " Leading, Trailing & Internal Whitespace "), + format(configList[6], " Leading, Trailing & Internal Whitespace "), format(configList[7], " ")}); { ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); // Correct (empty) configuration - BEAST_EXPECT( - trustedKeys->load({}, emptyCfgKeys, emptyCfgPublishers)); + BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, emptyCfgPublishers)); // load local validator key with or without manifest - BEAST_EXPECT(trustedKeys->load( - localSigningPublicOuter, emptyCfgKeys, emptyCfgPublishers)); + BEAST_EXPECT(trustedKeys->load(localSigningPublicOuter, emptyCfgKeys, emptyCfgPublishers)); BEAST_EXPECT(trustedKeys->listed(localSigningPublicOuter)); manifests.applyManifest(*deserializeManifest(cfgManifest)); - BEAST_EXPECT(trustedKeys->load( - localSigningPublicOuter, emptyCfgKeys, emptyCfgPublishers)); + BEAST_EXPECT(trustedKeys->load(localSigningPublicOuter, emptyCfgKeys, emptyCfgPublishers)); BEAST_EXPECT(trustedKeys->listed(localMasterPublic)); BEAST_EXPECT(trustedKeys->listed(localSigningPublicOuter)); @@ -279,11 +232,7 @@ private: // load should add validator keys from config ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); BEAST_EXPECT(trustedKeys->load({}, cfgKeys, emptyCfgPublishers)); @@ -294,42 +243,29 @@ private: auto const masterNode1 = randomMasterKey(); auto const masterNode2 = randomMasterKey(); - std::vector cfgMasterKeys( - {format(masterNode1), format(masterNode2, " Comment")}); - BEAST_EXPECT( - trustedKeys->load({}, cfgMasterKeys, emptyCfgPublishers)); + std::vector cfgMasterKeys({format(masterNode1), format(masterNode2, " Comment")}); + BEAST_EXPECT(trustedKeys->load({}, cfgMasterKeys, emptyCfgPublishers)); BEAST_EXPECT(trustedKeys->listed(masterNode1)); BEAST_EXPECT(trustedKeys->listed(masterNode2)); // load should reject invalid config keys - BEAST_EXPECT( - !trustedKeys->load({}, {"NotAPublicKey"}, emptyCfgPublishers)); - BEAST_EXPECT(!trustedKeys->load( - {}, {format(randomNode(), "!")}, emptyCfgPublishers)); + BEAST_EXPECT(!trustedKeys->load({}, {"NotAPublicKey"}, emptyCfgPublishers)); + BEAST_EXPECT(!trustedKeys->load({}, {format(randomNode(), "!")}, emptyCfgPublishers)); // load terminates when encountering an invalid entry auto const goodKey = randomNode(); - BEAST_EXPECT(!trustedKeys->load( - {}, - {format(randomNode(), "!"), format(goodKey)}, - emptyCfgPublishers)); + BEAST_EXPECT(!trustedKeys->load({}, {format(randomNode(), "!"), format(goodKey)}, emptyCfgPublishers)); BEAST_EXPECT(!trustedKeys->listed(goodKey)); } { // local validator key on config list ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); - auto const localSigningPublic = - parseBase58(TokenType::NodePublic, cfgKeys.front()); + auto const localSigningPublic = parseBase58(TokenType::NodePublic, cfgKeys.front()); - BEAST_EXPECT(trustedKeys->load( - *localSigningPublic, cfgKeys, emptyCfgPublishers)); + BEAST_EXPECT(trustedKeys->load(*localSigningPublic, cfgKeys, emptyCfgPublishers)); BEAST_EXPECT(trustedKeys->localPublicKey() == localSigningPublic); BEAST_EXPECT(trustedKeys->listed(*localSigningPublic)); @@ -340,15 +276,10 @@ private: // local validator key not on config list ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); auto const localSigningPublic = randomNode(); - BEAST_EXPECT(trustedKeys->load( - localSigningPublic, cfgKeys, emptyCfgPublishers)); + BEAST_EXPECT(trustedKeys->load(localSigningPublic, cfgKeys, emptyCfgPublishers)); BEAST_EXPECT(trustedKeys->localPublicKey() == localSigningPublic); BEAST_EXPECT(trustedKeys->listed(localSigningPublic)); @@ -359,16 +290,11 @@ private: // local validator key (with manifest) not on config list ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); manifests.applyManifest(*deserializeManifest(cfgManifest)); - BEAST_EXPECT(trustedKeys->load( - localSigningPublicOuter, cfgKeys, emptyCfgPublishers)); + BEAST_EXPECT(trustedKeys->load(localSigningPublicOuter, cfgKeys, emptyCfgPublishers)); BEAST_EXPECT(trustedKeys->localPublicKey() == localMasterPublic); BEAST_EXPECT(trustedKeys->listed(localSigningPublicOuter)); @@ -379,11 +305,7 @@ private: { ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); // load should reject invalid validator list signing keys std::vector badPublishers({"NotASigningKey"}); @@ -391,8 +313,7 @@ private: // load should reject validator list signing keys with invalid // encoding - std::vector keys( - {randomMasterKey(), randomMasterKey(), randomMasterKey()}); + std::vector keys({randomMasterKey(), randomMasterKey(), randomMasterKey()}); badPublishers.clear(); for (auto const& key : keys) badPublishers.push_back(toBase58(TokenType::NodePublic, key)); @@ -409,30 +330,20 @@ private: BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers)); for (auto const& key : keys) BEAST_EXPECT(trustedKeys->trustedPublisher(key)); - BEAST_EXPECT( - trustedKeys->getListThreshold() == keys.size() / 2 + 1); + BEAST_EXPECT(trustedKeys->getListThreshold() == keys.size() / 2 + 1); } { ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); - std::vector keys( - {randomMasterKey(), - randomMasterKey(), - randomMasterKey(), - randomMasterKey()}); + std::vector keys({randomMasterKey(), randomMasterKey(), randomMasterKey(), randomMasterKey()}); std::vector cfgPublishers; for (auto const& key : keys) cfgPublishers.push_back(strHex(key)); // explicitly set the list threshold - BEAST_EXPECT(trustedKeys->load( - {}, emptyCfgKeys, cfgPublishers, std::size_t(2))); + BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers, std::size_t(2))); for (auto const& key : keys) BEAST_EXPECT(trustedKeys->trustedPublisher(key)); BEAST_EXPECT(trustedKeys->getListThreshold() == 2); @@ -443,15 +354,10 @@ private: ManifestCache valManifests; ManifestCache pubManifests; auto trustedKeys = std::make_unique( - valManifests, - pubManifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + valManifests, pubManifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); auto const pubRevokedSecret = randomSecretKey(); - auto const pubRevokedPublic = - derivePublicKey(KeyType::ed25519, pubRevokedSecret); + auto const pubRevokedPublic = derivePublicKey(KeyType::ed25519, pubRevokedSecret); auto const pubRevokedSigning = randomKeyPair(KeyType::secp256k1); // make this manifest revoked (seq num = max) // -- thus should not be loaded @@ -466,8 +372,7 @@ private: auto legitKey1 = randomMasterKey(); auto legitKey2 = randomMasterKey(); - std::vector cfgPublishers = { - strHex(pubRevokedPublic), strHex(legitKey1), strHex(legitKey2)}; + std::vector cfgPublishers = {strHex(pubRevokedPublic), strHex(legitKey1), strHex(legitKey2)}; BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers)); BEAST_EXPECT(!trustedKeys->trustedPublisher(pubRevokedPublic)); @@ -482,15 +387,10 @@ private: ManifestCache valManifests; ManifestCache pubManifests; auto trustedKeys = std::make_unique( - valManifests, - pubManifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + valManifests, pubManifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); auto const pubRevokedSecret = randomSecretKey(); - auto const pubRevokedPublic = - derivePublicKey(KeyType::ed25519, pubRevokedSecret); + auto const pubRevokedPublic = derivePublicKey(KeyType::ed25519, pubRevokedSecret); auto const pubRevokedSigning = randomKeyPair(KeyType::secp256k1); // make this manifest revoked (seq num = max) // -- thus should not be loaded @@ -504,10 +404,8 @@ private: // this one is not revoked (and not in the manifest cache at all.) auto legitKey = randomMasterKey(); - std::vector cfgPublishers = { - strHex(pubRevokedPublic), strHex(legitKey)}; - BEAST_EXPECT(trustedKeys->load( - {}, emptyCfgKeys, cfgPublishers, std::size_t(2))); + std::vector cfgPublishers = {strHex(pubRevokedPublic), strHex(legitKey)}; + BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers, std::size_t(2))); BEAST_EXPECT(!trustedKeys->trustedPublisher(pubRevokedPublic)); BEAST_EXPECT(trustedKeys->trustedPublisher(legitKey)); @@ -524,93 +422,74 @@ private: std::string const siteUri = "testApplyList.test"; - auto checkAvailable = - [this]( - auto const& trustedKeys, - auto const& hexPublic, - auto const& manifest, - auto const version, - std::vector> const& - expected) { - auto const available = trustedKeys->getAvailable(hexPublic); + auto checkAvailable = [this]( + auto const& trustedKeys, + auto const& hexPublic, + auto const& manifest, + auto const version, + std::vector> const& expected) { + auto const available = trustedKeys->getAvailable(hexPublic); - BEAST_EXPECT(!version || available); - if (available) + BEAST_EXPECT(!version || available); + if (available) + { + auto const& a = *available; + BEAST_EXPECT(a[jss::public_key] == hexPublic); + BEAST_EXPECT(a[jss::manifest] == manifest); + // Because multiple lists were processed, the version was + // overridden + BEAST_EXPECT(a[jss::version] == version); + if (version == 1) { - auto const& a = *available; - BEAST_EXPECT(a[jss::public_key] == hexPublic); - BEAST_EXPECT(a[jss::manifest] == manifest); - // Because multiple lists were processed, the version was - // overridden - BEAST_EXPECT(a[jss::version] == version); - if (version == 1) - { - BEAST_EXPECT(expected.size() == 1); - BEAST_EXPECT(a[jss::blob] == expected[0].first); - BEAST_EXPECT(a[jss::signature] == expected[0].second); - BEAST_EXPECT(!a.isMember(jss::blobs_v2)); - } - else if (BEAST_EXPECT(a.isMember(jss::blobs_v2))) - { - BEAST_EXPECT(!a.isMember(jss::blob)); - BEAST_EXPECT(!a.isMember(jss::signature)); - auto const& blobs_v2 = a[jss::blobs_v2]; - BEAST_EXPECT( - blobs_v2.isArray() && - blobs_v2.size() == expected.size()); + BEAST_EXPECT(expected.size() == 1); + BEAST_EXPECT(a[jss::blob] == expected[0].first); + BEAST_EXPECT(a[jss::signature] == expected[0].second); + BEAST_EXPECT(!a.isMember(jss::blobs_v2)); + } + else if (BEAST_EXPECT(a.isMember(jss::blobs_v2))) + { + BEAST_EXPECT(!a.isMember(jss::blob)); + BEAST_EXPECT(!a.isMember(jss::signature)); + auto const& blobs_v2 = a[jss::blobs_v2]; + BEAST_EXPECT(blobs_v2.isArray() && blobs_v2.size() == expected.size()); - for (unsigned int i = 0; i < expected.size(); ++i) - { - BEAST_EXPECT( - blobs_v2[i][jss::blob] == expected[i].first); - BEAST_EXPECT( - blobs_v2[i][jss::signature] == - expected[i].second); - } + for (unsigned int i = 0; i < expected.size(); ++i) + { + BEAST_EXPECT(blobs_v2[i][jss::blob] == expected[i].first); + BEAST_EXPECT(blobs_v2[i][jss::signature] == expected[i].second); } } - }; + } + }; ManifestCache manifests; jtx::Env env(*this); auto& app = env.app(); auto trustedKeys = std::make_unique( - manifests, - manifests, - env.app().timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.app().timeKeeper(), app.config().legacy("database_path"), env.journal); - auto expectTrusted = - [this, &trustedKeys](std::vector const& list) { - for (auto const& val : list) - { - BEAST_EXPECT(trustedKeys->listed(val.masterPublic)); - BEAST_EXPECT(trustedKeys->listed(val.signingPublic)); - } - }; + auto expectTrusted = [this, &trustedKeys](std::vector const& list) { + for (auto const& val : list) + { + BEAST_EXPECT(trustedKeys->listed(val.masterPublic)); + BEAST_EXPECT(trustedKeys->listed(val.signingPublic)); + } + }; - auto expectUntrusted = - [this, &trustedKeys](std::vector const& list) { - for (auto const& val : list) - { - BEAST_EXPECT(!trustedKeys->listed(val.masterPublic)); - BEAST_EXPECT(!trustedKeys->listed(val.signingPublic)); - } - }; + auto expectUntrusted = [this, &trustedKeys](std::vector const& list) { + for (auto const& val : list) + { + BEAST_EXPECT(!trustedKeys->listed(val.masterPublic)); + BEAST_EXPECT(!trustedKeys->listed(val.signingPublic)); + } + }; auto const publisherSecret = randomSecretKey(); - auto const publisherPublic = - derivePublicKey(KeyType::ed25519, publisherSecret); - auto const hexPublic = - strHex(publisherPublic.begin(), publisherPublic.end()); + auto const publisherPublic = derivePublicKey(KeyType::ed25519, publisherSecret); + auto const hexPublic = strHex(publisherPublic.begin(), publisherPublic.end()); auto const pubSigningKeys1 = randomKeyPair(KeyType::secp256k1); - auto const manifest1 = base64_encode(makeManifestString( - publisherPublic, - publisherSecret, - pubSigningKeys1.first, - pubSigningKeys1.second, - 1)); + auto const manifest1 = base64_encode( + makeManifestString(publisherPublic, publisherSecret, pubSigningKeys1.first, pubSigningKeys1.second, 1)); std::vector cfgKeys1({strHex(publisherPublic)}); std::vector emptyCfgKeys; @@ -636,32 +515,23 @@ private: env.timeKeeper().set(env.timeKeeper().now() + 1s); auto const version = 1; auto const sequence1 = 1; - auto const expiredblob = makeList( - lists.at(1), - sequence1, - env.timeKeeper().now().time_since_epoch().count()); + auto const expiredblob = makeList(lists.at(1), sequence1, env.timeKeeper().now().time_since_epoch().count()); auto const expiredSig = signList(expiredblob, pubSigningKeys1); NetClock::time_point const validUntil = env.timeKeeper().now() + 3600s; auto const sequence2 = 2; - auto const blob2 = makeList( - lists.at(2), sequence2, validUntil.time_since_epoch().count()); + auto const blob2 = makeList(lists.at(2), sequence2, validUntil.time_since_epoch().count()); auto const sig2 = signList(blob2, pubSigningKeys1); checkResult( - trustedKeys->applyLists( - manifest1, - version, - {{expiredblob, expiredSig, {}}, {blob2, sig2, {}}}, - siteUri), + trustedKeys->applyLists(manifest1, version, {{expiredblob, expiredSig, {}}, {blob2, sig2, {}}}, siteUri), publisherPublic, ListDisposition::expired, ListDisposition::accepted); expectTrusted(lists.at(2)); - checkAvailable( - trustedKeys, hexPublic, manifest1, version, {{blob2, sig2}}); + checkAvailable(trustedKeys, hexPublic, manifest1, version, {{blob2, sig2}}); // Do not apply future lists, but process them auto const version2 = 2; @@ -669,28 +539,18 @@ private: auto const effective7 = validUntil - 60s; auto const expiration7 = effective7 + 3600s; auto const blob7 = makeList( - lists.at(7), - sequence7, - expiration7.time_since_epoch().count(), - effective7.time_since_epoch().count()); + lists.at(7), sequence7, expiration7.time_since_epoch().count(), effective7.time_since_epoch().count()); auto const sig7 = signList(blob7, pubSigningKeys1); auto const sequence8 = 8; auto const effective8 = expiration7 - 60s; auto const expiration8 = effective8 + 3600s; auto const blob8 = makeList( - lists.at(8), - sequence8, - expiration8.time_since_epoch().count(), - effective8.time_since_epoch().count()); + lists.at(8), sequence8, expiration8.time_since_epoch().count(), effective8.time_since_epoch().count()); auto const sig8 = signList(blob8, pubSigningKeys1); checkResult( - trustedKeys->applyLists( - manifest1, - version2, - {{blob7, sig7, {}}, {blob8, sig8, {}}}, - siteUri), + trustedKeys->applyLists(manifest1, version2, {{blob7, sig7, {}}, {blob8, sig8, {}}}, siteUri), publisherPublic, ListDisposition::pending, ListDisposition::pending); @@ -703,10 +563,7 @@ private: auto const effective6 = effective7 - 60s; auto const expiration6 = effective6 + 3600s; auto const blob6 = makeList( - lists.at(6), - sequence6, - expiration6.time_since_epoch().count(), - effective6.time_since_epoch().count()); + lists.at(6), sequence6, expiration6.time_since_epoch().count(), effective6.time_since_epoch().count()); auto const sig6 = signList(blob6, pubSigningKeys1); // Process future list that is overridden by a later list @@ -714,18 +571,11 @@ private: auto const effective6a = effective6 + 60s; auto const expiration6a = effective6a + 3600s; auto const blob6a = makeList( - lists.at(5), - sequence6a, - expiration6a.time_since_epoch().count(), - effective6a.time_since_epoch().count()); + lists.at(5), sequence6a, expiration6a.time_since_epoch().count(), effective6a.time_since_epoch().count()); auto const sig6a = signList(blob6a, pubSigningKeys1); checkResult( - trustedKeys->applyLists( - manifest1, - version, - {{blob6a, sig6a, {}}, {blob6, sig6, {}}}, - siteUri), + trustedKeys->applyLists(manifest1, version, {{blob6a, sig6a, {}}, {blob6, sig6, {}}}, siteUri), publisherPublic, ListDisposition::pending, ListDisposition::pending); @@ -736,11 +586,7 @@ private: // Do not apply re-process lists known future sequence numbers checkResult( - trustedKeys->applyLists( - manifest1, - version, - {{blob7, sig7, {}}, {blob6, sig6, {}}}, - siteUri), + trustedKeys->applyLists(manifest1, version, {{blob7, sig7, {}}, {blob6, sig6, {}}}, siteUri), publisherPublic, ListDisposition::known_sequence, ListDisposition::known_sequence); @@ -751,33 +597,24 @@ private: // try empty or mangled manifest checkResult( - trustedKeys->applyLists( - "", version, {{blob7, sig7, {}}, {blob6, sig6, {}}}, siteUri), + trustedKeys->applyLists("", version, {{blob7, sig7, {}}, {blob6, sig6, {}}}, siteUri), publisherPublic, ListDisposition::invalid, ListDisposition::invalid); checkResult( trustedKeys->applyLists( - base64_encode("not a manifest"), - version, - {{blob7, sig7, {}}, {blob6, sig6, {}}}, - siteUri), + base64_encode("not a manifest"), version, {{blob7, sig7, {}}, {blob6, sig6, {}}}, siteUri), publisherPublic, ListDisposition::invalid, ListDisposition::invalid); // do not use list from untrusted publisher - auto const untrustedManifest = base64_encode(makeManifestString( - randomMasterKey(), - publisherSecret, - pubSigningKeys1.first, - pubSigningKeys1.second, - 1)); + auto const untrustedManifest = base64_encode( + makeManifestString(randomMasterKey(), publisherSecret, pubSigningKeys1.first, pubSigningKeys1.second, 1)); checkResult( - trustedKeys->applyLists( - untrustedManifest, version, {{blob2, sig2, {}}}, siteUri), + trustedKeys->applyLists(untrustedManifest, version, {{blob2, sig2, {}}}, siteUri), publisherPublic, ListDisposition::untrusted, ListDisposition::untrusted); @@ -785,21 +622,18 @@ private: // do not use list with unhandled version auto const badVersion = 666; checkResult( - trustedKeys->applyLists( - manifest1, badVersion, {{blob2, sig2, {}}}, siteUri), + trustedKeys->applyLists(manifest1, badVersion, {{blob2, sig2, {}}}, siteUri), publisherPublic, ListDisposition::unsupported_version, ListDisposition::unsupported_version); // apply list with highest sequence number auto const sequence3 = 3; - auto const blob3 = makeList( - lists.at(3), sequence3, validUntil.time_since_epoch().count()); + auto const blob3 = makeList(lists.at(3), sequence3, validUntil.time_since_epoch().count()); auto const sig3 = signList(blob3, pubSigningKeys1); checkResult( - trustedKeys->applyLists( - manifest1, version, {{blob3, sig3, {}}}, siteUri), + trustedKeys->applyLists(manifest1, version, {{blob3, sig3, {}}}, siteUri), publisherPublic, ListDisposition::accepted, ListDisposition::accepted); @@ -811,19 +645,11 @@ private: // Note that blob6a is not present, because it was dropped during // processing checkAvailable( - trustedKeys, - hexPublic, - manifest1, - 2, - {{blob3, sig3}, {blob6, sig6}, {blob7, sig7}, {blob8, sig8}}); + trustedKeys, hexPublic, manifest1, 2, {{blob3, sig3}, {blob6, sig6}, {blob7, sig7}, {blob8, sig8}}); // do not re-apply lists with past or current sequence numbers checkResult( - trustedKeys->applyLists( - manifest1, - version, - {{blob2, sig2, {}}, {blob3, sig3, {}}}, - siteUri), + trustedKeys->applyLists(manifest1, version, {{blob2, sig2, {}}, {blob3, sig3, {}}}, siteUri), publisherPublic, ListDisposition::stale, ListDisposition::same_sequence); @@ -831,26 +657,16 @@ private: // apply list with new publisher key updated by manifest. Also send some // old lists along with the old manifest auto const pubSigningKeys2 = randomKeyPair(KeyType::secp256k1); - auto manifest2 = base64_encode(makeManifestString( - publisherPublic, - publisherSecret, - pubSigningKeys2.first, - pubSigningKeys2.second, - 2)); + auto manifest2 = base64_encode( + makeManifestString(publisherPublic, publisherSecret, pubSigningKeys2.first, pubSigningKeys2.second, 2)); auto const sequence4 = 4; - auto const blob4 = makeList( - lists.at(4), sequence4, validUntil.time_since_epoch().count()); + auto const blob4 = makeList(lists.at(4), sequence4, validUntil.time_since_epoch().count()); auto const sig4 = signList(blob4, pubSigningKeys2); checkResult( trustedKeys->applyLists( - manifest2, - version, - {{blob2, sig2, manifest1}, - {blob3, sig3, manifest1}, - {blob4, sig4, {}}}, - siteUri), + manifest2, version, {{blob2, sig2, manifest1}, {blob3, sig3, manifest1}, {blob4, sig4, {}}}, siteUri), publisherPublic, ListDisposition::stale, ListDisposition::accepted); @@ -860,19 +676,13 @@ private: expectTrusted(lists.at(4)); checkAvailable( - trustedKeys, - hexPublic, - manifest2, - 2, - {{blob4, sig4}, {blob6, sig6}, {blob7, sig7}, {blob8, sig8}}); + trustedKeys, hexPublic, manifest2, 2, {{blob4, sig4}, {blob6, sig6}, {blob7, sig7}, {blob8, sig8}}); auto const sequence5 = 5; - auto const blob5 = makeList( - lists.at(5), sequence5, validUntil.time_since_epoch().count()); + auto const blob5 = makeList(lists.at(5), sequence5, validUntil.time_since_epoch().count()); auto const badSig = signList(blob5, pubSigningKeys1); checkResult( - trustedKeys->applyLists( - manifest1, version, {{blob5, badSig, {}}}, siteUri), + trustedKeys->applyLists(manifest1, version, {{blob5, badSig, {}}}, siteUri), publisherPublic, ListDisposition::invalid, ListDisposition::invalid); @@ -884,11 +694,7 @@ private: // Reprocess the pending list, but the signature is no longer valid checkResult( - trustedKeys->applyLists( - manifest1, - version, - {{blob7, sig7, {}}, {blob8, sig8, {}}}, - siteUri), + trustedKeys->applyLists(manifest1, version, {{blob7, sig7, {}}, {blob8, sig8, {}}}, siteUri), publisherPublic, ListDisposition::invalid, ListDisposition::invalid); @@ -901,21 +707,12 @@ private: // updateTrusted. Note that the timekeeper is NOT moved, so the close // time will be ahead of the test's wall clock trustedKeys->updateTrusted( - {}, - effective6 + 1s, - env.app().getOPs(), - env.app().overlay(), - env.app().getHashRouter()); + {}, effective6 + 1s, env.app().getOPs(), env.app().overlay(), env.app().getHashRouter()); expectUntrusted(lists.at(3)); expectTrusted(lists.at(6)); - checkAvailable( - trustedKeys, - hexPublic, - manifest2, - 2, - {{blob6, sig6}, {blob7, sig7}, {blob8, sig8}}); + checkAvailable(trustedKeys, hexPublic, manifest2, 2, {{blob6, sig6}, {blob7, sig7}, {blob8, sig8}}); // Automatically rotate the LAST pending list using updateTrusted, // bypassing blob7. Note that the timekeeper IS moved, so the provided @@ -923,11 +720,7 @@ private: // clock is used. env.timeKeeper().set(effective8); trustedKeys->updateTrusted( - {}, - effective8 + 1s, - env.app().getOPs(), - env.app().overlay(), - env.app().getHashRouter()); + {}, effective8 + 1s, env.app().getOPs(), env.app().overlay(), env.app().getHashRouter()); expectUntrusted(lists.at(6)); expectUntrusted(lists.at(7)); @@ -942,11 +735,7 @@ private: auto const sig8_2 = signList(blob8, pubSigningKeys2); checkResult( - trustedKeys->applyLists( - manifest2, - version, - {{blob8, sig8, manifest1}, {blob8, sig8_2, {}}}, - siteUri), + trustedKeys->applyLists(manifest2, version, {{blob8, sig8, manifest1}, {blob8, sig8_2, {}}}, siteUri), publisherPublic, ListDisposition::invalid, ListDisposition::same_sequence); @@ -958,17 +747,14 @@ private: // do not apply list with revoked publisher key // applied list is removed due to revoked publisher key auto const signingKeysMax = randomKeyPair(KeyType::secp256k1); - auto maxManifest = base64_encode( - makeRevocationString(publisherPublic, publisherSecret)); + auto maxManifest = base64_encode(makeRevocationString(publisherPublic, publisherSecret)); auto const sequence9 = 9; - auto const blob9 = makeList( - lists.at(9), sequence9, validUntil.time_since_epoch().count()); + auto const blob9 = makeList(lists.at(9), sequence9, validUntil.time_since_epoch().count()); auto const sig9 = signList(blob9, signingKeysMax); checkResult( - trustedKeys->applyLists( - maxManifest, version, {{blob9, sig9, {}}}, siteUri), + trustedKeys->applyLists(maxManifest, version, {{blob9, sig9, {}}}, siteUri), publisherPublic, ListDisposition::untrusted, ListDisposition::untrusted); @@ -995,24 +781,14 @@ private: jtx::Env env(*this); auto& app = env.app(); auto trustedKeys = std::make_unique( - manifests, - manifests, - env.app().timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.app().timeKeeper(), app.config().legacy("database_path"), env.journal); auto const publisherSecret = randomSecretKey(); - auto const publisherPublic = - derivePublicKey(KeyType::ed25519, publisherSecret); - auto const hexPublic = - strHex(publisherPublic.begin(), publisherPublic.end()); + auto const publisherPublic = derivePublicKey(KeyType::ed25519, publisherSecret); + auto const hexPublic = strHex(publisherPublic.begin(), publisherPublic.end()); auto const pubSigningKeys1 = randomKeyPair(KeyType::secp256k1); - auto const manifest = base64_encode(makeManifestString( - publisherPublic, - publisherSecret, - pubSigningKeys1.first, - pubSigningKeys1.second, - 1)); + auto const manifest = base64_encode( + makeManifestString(publisherPublic, publisherSecret, pubSigningKeys1.first, pubSigningKeys1.second, 1)); std::vector cfgKeys1({strHex(publisherPublic)}); std::vector emptyCfgKeys; @@ -1031,8 +807,7 @@ private: // Process a list env.timeKeeper().set(env.timeKeeper().now() + 1s); NetClock::time_point const validUntil = env.timeKeeper().now() + 3600s; - auto const blob = - makeList(list, 1, validUntil.time_since_epoch().count()); + auto const blob = makeList(list, 1, validUntil.time_since_epoch().count()); auto const sig = signList(blob, pubSigningKeys1); { @@ -1042,13 +817,12 @@ private: } BEAST_EXPECT( - trustedKeys->applyLists(manifest, 1, {{blob, sig, {}}}, siteUri) - .bestDisposition() == ListDisposition::accepted); + trustedKeys->applyLists(manifest, 1, {{blob, sig, {}}}, siteUri).bestDisposition() == + ListDisposition::accepted); { // invalid public key - auto const available = - trustedKeys->getAvailable(hexPublic + "invalid", 1); + auto const available = trustedKeys->getAvailable(hexPublic + "invalid", 1); BEAST_EXPECT(!available); } @@ -1130,11 +904,7 @@ private: jtx::Env env(*this); auto& app = env.app(); auto trustedKeysOuter = std::make_unique( - manifestsOuter, - manifestsOuter, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifestsOuter, manifestsOuter, env.timeKeeper(), app.config().legacy("database_path"), env.journal); std::vector cfgPublishersOuter; hash_set activeValidatorsOuter; @@ -1155,8 +925,7 @@ private: unseenValidators.emplace(calcNodeID(valKey)); } - BEAST_EXPECT( - trustedKeysOuter->load({}, cfgKeys, cfgPublishersOuter)); + BEAST_EXPECT(trustedKeysOuter->load({}, cfgKeys, cfgPublishersOuter)); // updateTrusted should make all configured validators trusted // even if they are not active/seen @@ -1172,12 +941,10 @@ private: BEAST_EXPECT(changes.added == activeValidatorsOuter); BEAST_EXPECT(changes.removed.empty()); - BEAST_EXPECT( - trustedKeysOuter->quorum() == std::ceil(cfgKeys.size() * 0.8f)); + BEAST_EXPECT(trustedKeysOuter->quorum() == std::ceil(cfgKeys.size() * 0.8f)); for (auto const& val : cfgKeys) { - if (auto const valKey = - parseBase58(TokenType::NodePublic, val)) + if (auto const valKey = parseBase58(TokenType::NodePublic, val)) { BEAST_EXPECT(trustedKeysOuter->listed(*valKey)); BEAST_EXPECT(trustedKeysOuter->trusted(*valKey)); @@ -1194,20 +961,16 @@ private: env.app().getHashRouter()); BEAST_EXPECT(changes.added.empty()); BEAST_EXPECT(changes.removed.empty()); - BEAST_EXPECT( - trustedKeysOuter->quorum() == std::ceil(cfgKeys.size() * 0.8f)); + BEAST_EXPECT(trustedKeysOuter->quorum() == std::ceil(cfgKeys.size() * 0.8f)); } { // update with manifests auto const masterPrivate = randomSecretKey(); - auto const masterPublic = - derivePublicKey(KeyType::ed25519, masterPrivate); + auto const masterPublic = derivePublicKey(KeyType::ed25519, masterPrivate); - std::vector cfgKeys( - {toBase58(TokenType::NodePublic, masterPublic)}); + std::vector cfgKeys({toBase58(TokenType::NodePublic, masterPublic)}); - BEAST_EXPECT( - trustedKeysOuter->load({}, cfgKeys, cfgPublishersOuter)); + BEAST_EXPECT(trustedKeysOuter->load({}, cfgKeys, cfgPublishersOuter)); auto const signingKeys1 = randomKeyPair(KeyType::secp256k1); auto const signingPublic1 = signingKeys1.first; @@ -1222,24 +985,17 @@ private: env.app().getHashRouter()); BEAST_EXPECT(changes.added == asNodeIDs({masterPublic})); BEAST_EXPECT(changes.removed.empty()); - BEAST_EXPECT( - trustedKeysOuter->quorum() == std::ceil((maxKeys + 1) * 0.8f)); + BEAST_EXPECT(trustedKeysOuter->quorum() == std::ceil((maxKeys + 1) * 0.8f)); BEAST_EXPECT(trustedKeysOuter->listed(masterPublic)); BEAST_EXPECT(trustedKeysOuter->trusted(masterPublic)); BEAST_EXPECT(!trustedKeysOuter->listed(signingPublic1)); BEAST_EXPECT(!trustedKeysOuter->trusted(signingPublic1)); // Should trust the ephemeral signing key from the applied manifest - auto m1 = deserializeManifest(makeManifestString( - masterPublic, - masterPrivate, - signingPublic1, - signingKeys1.second, - 1)); + auto m1 = deserializeManifest( + makeManifestString(masterPublic, masterPrivate, signingPublic1, signingKeys1.second, 1)); - BEAST_EXPECT( - manifestsOuter.applyManifest(std::move(*m1)) == - ManifestDisposition::accepted); + BEAST_EXPECT(manifestsOuter.applyManifest(std::move(*m1)) == ManifestDisposition::accepted); BEAST_EXPECT(trustedKeysOuter->listed(masterPublic)); BEAST_EXPECT(trustedKeysOuter->trusted(masterPublic)); BEAST_EXPECT(trustedKeysOuter->listed(signingPublic1)); @@ -1249,15 +1005,9 @@ private: // from the newest applied manifest auto const signingKeys2 = randomKeyPair(KeyType::secp256k1); auto const signingPublic2 = signingKeys2.first; - auto m2 = deserializeManifest(makeManifestString( - masterPublic, - masterPrivate, - signingPublic2, - signingKeys2.second, - 2)); - BEAST_EXPECT( - manifestsOuter.applyManifest(std::move(*m2)) == - ManifestDisposition::accepted); + auto m2 = deserializeManifest( + makeManifestString(masterPublic, masterPrivate, signingPublic2, signingKeys2.second, 2)); + BEAST_EXPECT(manifestsOuter.applyManifest(std::move(*m2)) == ManifestDisposition::accepted); BEAST_EXPECT(trustedKeysOuter->listed(masterPublic)); BEAST_EXPECT(trustedKeysOuter->trusted(masterPublic)); BEAST_EXPECT(trustedKeysOuter->listed(signingPublic2)); @@ -1269,15 +1019,11 @@ private: auto const signingKeysMax = randomKeyPair(KeyType::secp256k1); auto const signingPublicMax = signingKeysMax.first; activeValidatorsOuter.emplace(calcNodeID(signingPublicMax)); - auto mMax = deserializeManifest( - makeRevocationString(masterPublic, masterPrivate)); + auto mMax = deserializeManifest(makeRevocationString(masterPublic, masterPrivate)); BEAST_EXPECT(mMax->revoked()); - BEAST_EXPECT( - manifestsOuter.applyManifest(std::move(*mMax)) == - ManifestDisposition::accepted); - BEAST_EXPECT( - manifestsOuter.getSigningKey(masterPublic) == masterPublic); + BEAST_EXPECT(manifestsOuter.applyManifest(std::move(*mMax)) == ManifestDisposition::accepted); + BEAST_EXPECT(manifestsOuter.getSigningKey(masterPublic) == masterPublic); BEAST_EXPECT(manifestsOuter.revoked(masterPublic)); // Revoked key remains trusted until list is updated @@ -1292,8 +1038,7 @@ private: env.app().getHashRouter()); BEAST_EXPECT(changes.removed == asNodeIDs({masterPublic})); BEAST_EXPECT(changes.added.empty()); - BEAST_EXPECT( - trustedKeysOuter->quorum() == std::ceil(maxKeys * 0.8f)); + BEAST_EXPECT(trustedKeysOuter->quorum() == std::ceil(maxKeys * 0.8f)); BEAST_EXPECT(trustedKeysOuter->listed(masterPublic)); BEAST_EXPECT(!trustedKeysOuter->trusted(masterPublic)); BEAST_EXPECT(!trustedKeysOuter->listed(signingPublicMax)); @@ -1307,14 +1052,9 @@ private: // Make quorum unattainable if lists from any publishers are // unavailable auto trustedKeys = std::make_unique( - manifestsOuter, - manifestsOuter, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifestsOuter, manifestsOuter, env.timeKeeper(), app.config().legacy("database_path"), env.journal); auto const publisherSecret = randomSecretKey(); - auto const publisherPublic = - derivePublicKey(KeyType::ed25519, publisherSecret); + auto const publisherPublic = derivePublicKey(KeyType::ed25519, publisherSecret); std::vector cfgPublishers({strHex(publisherPublic)}); std::vector emptyCfgKeys; @@ -1329,36 +1069,24 @@ private: env.app().getHashRouter()); BEAST_EXPECT(changes.removed.empty()); BEAST_EXPECT(changes.added.empty()); - BEAST_EXPECT( - trustedKeys->quorum() == - std::numeric_limits::max()); + BEAST_EXPECT(trustedKeys->quorum() == std::numeric_limits::max()); } { // Trust explicitly listed validators also when list threshold is // higher than 1 auto trustedKeys = std::make_unique( - manifestsOuter, - manifestsOuter, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifestsOuter, manifestsOuter, env.timeKeeper(), app.config().legacy("database_path"), env.journal); auto const masterPrivate = randomSecretKey(); - auto const masterPublic = - derivePublicKey(KeyType::ed25519, masterPrivate); - std::vector cfgKeys( - {toBase58(TokenType::NodePublic, masterPublic)}); + auto const masterPublic = derivePublicKey(KeyType::ed25519, masterPrivate); + std::vector cfgKeys({toBase58(TokenType::NodePublic, masterPublic)}); auto const publisher1Secret = randomSecretKey(); - auto const publisher1Public = - derivePublicKey(KeyType::ed25519, publisher1Secret); + auto const publisher1Public = derivePublicKey(KeyType::ed25519, publisher1Secret); auto const publisher2Secret = randomSecretKey(); - auto const publisher2Public = - derivePublicKey(KeyType::ed25519, publisher2Secret); - std::vector cfgPublishers( - {strHex(publisher1Public), strHex(publisher2Public)}); + auto const publisher2Public = derivePublicKey(KeyType::ed25519, publisher2Secret); + std::vector cfgPublishers({strHex(publisher1Public), strHex(publisher2Public)}); - BEAST_EXPECT( - trustedKeys->load({}, cfgKeys, cfgPublishers, std::size_t(2))); + BEAST_EXPECT(trustedKeys->load({}, cfgKeys, cfgPublishers, std::size_t(2))); TrustChanges changes = trustedKeys->updateTrusted( activeValidatorsOuter, @@ -1376,12 +1104,7 @@ private: std::size_t const minQuorum = 1; ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal, - minQuorum); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal, minQuorum); std::size_t n = 10; std::vector cfgKeys; @@ -1438,35 +1161,26 @@ private: auto const publisherKeys = randomKeyPair(KeyType::secp256k1); auto const pubSigningKeys = randomKeyPair(KeyType::secp256k1); auto const manifest = base64_encode(makeManifestString( - publisherKeys.first, - publisherKeys.second, - pubSigningKeys.first, - pubSigningKeys.second, - 1)); + publisherKeys.first, publisherKeys.second, pubSigningKeys.first, pubSigningKeys.second, 1)); std::vector cfgKeys({strHex(publisherKeys.first)}); BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgKeys)); std::vector list({randomValidator(), randomValidator()}); - hash_set activeValidators( - asNodeIDs({list[0].masterPublic, list[1].masterPublic})); + hash_set activeValidators(asNodeIDs({list[0].masterPublic, list[1].masterPublic})); // do not apply expired list auto const version = 1; auto const sequence = 1; using namespace std::chrono_literals; - NetClock::time_point const validUntil = - env.timeKeeper().now() + 60s; - auto const blob = - makeList(list, sequence, validUntil.time_since_epoch().count()); + NetClock::time_point const validUntil = env.timeKeeper().now() + 60s; + auto const blob = makeList(list, sequence, validUntil.time_since_epoch().count()); auto const sig = signList(blob, pubSigningKeys); BEAST_EXPECT( ListDisposition::accepted == - trustedKeys - ->applyLists(manifest, version, {{blob, sig, {}}}, siteUri) - .bestDisposition()); + trustedKeys->applyLists(manifest, version, {{blob, sig, {}}}, siteUri).bestDisposition()); TrustChanges changes = trustedKeys->updateTrusted( activeValidators, @@ -1494,26 +1208,19 @@ private: BEAST_EXPECT(changes.added.empty()); BEAST_EXPECT(!trustedKeys->trusted(list[0].masterPublic)); BEAST_EXPECT(!trustedKeys->trusted(list[1].masterPublic)); - BEAST_EXPECT( - trustedKeys->quorum() == - std::numeric_limits::max()); + BEAST_EXPECT(trustedKeys->quorum() == std::numeric_limits::max()); // (Re)trust validators from new valid list std::vector list2({list[0], randomValidator()}); activeValidators.insert(calcNodeID(list2[1].masterPublic)); auto const sequence2 = 2; - NetClock::time_point const expiration2 = - env.timeKeeper().now() + 60s; - auto const blob2 = makeList( - list2, sequence2, expiration2.time_since_epoch().count()); + NetClock::time_point const expiration2 = env.timeKeeper().now() + 60s; + auto const blob2 = makeList(list2, sequence2, expiration2.time_since_epoch().count()); auto const sig2 = signList(blob2, pubSigningKeys); BEAST_EXPECT( ListDisposition::accepted == - trustedKeys - ->applyLists( - manifest, version, {{blob2, sig2, {}}}, siteUri) - .bestDisposition()); + trustedKeys->applyLists(manifest, version, {{blob2, sig2, {}}}, siteUri).bestDisposition()); changes = trustedKeys->updateTrusted( activeValidators, @@ -1522,9 +1229,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(changes.removed.empty()); - BEAST_EXPECT( - changes.added == - asNodeIDs({list2[0].masterPublic, list2[1].masterPublic})); + BEAST_EXPECT(changes.added == asNodeIDs({list2[0].masterPublic, list2[1].masterPublic})); for (Validator const& val : list2) { BEAST_EXPECT(trustedKeys->trusted(val.masterPublic)); @@ -1537,11 +1242,7 @@ private: { // Test 1-9 configured validators auto trustedKeys = std::make_unique( - manifestsOuter, - manifestsOuter, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifestsOuter, manifestsOuter, env.timeKeeper(), app.config().legacy("database_path"), env.journal); std::vector cfgPublishers; hash_set activeValidators; @@ -1565,8 +1266,7 @@ private: env.app().getHashRouter()); BEAST_EXPECT(changes.removed.empty()); BEAST_EXPECT(changes.added == asNodeIDs({valKey})); - BEAST_EXPECT( - trustedKeys->quorum() == std::ceil(cfgKeys.size() * 0.8f)); + BEAST_EXPECT(trustedKeys->quorum() == std::ceil(cfgKeys.size() * 0.8f)); for (auto const& key : activeKeys) BEAST_EXPECT(trustedKeys->trusted(key)); } @@ -1574,18 +1274,13 @@ private: { // Test 2-9 configured validators as validator auto trustedKeys = std::make_unique( - manifestsOuter, - manifestsOuter, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifestsOuter, manifestsOuter, env.timeKeeper(), app.config().legacy("database_path"), env.journal); auto const localKey = randomNode(); std::vector cfgPublishers; hash_set activeValidators; hash_set activeKeys; - std::vector cfgKeys{ - toBase58(TokenType::NodePublic, localKey)}; + std::vector cfgKeys{toBase58(TokenType::NodePublic, localKey)}; cfgKeys.reserve(9); while (cfgKeys.size() < cfgKeys.capacity()) @@ -1595,8 +1290,7 @@ private: activeValidators.emplace(calcNodeID(valKey)); activeKeys.emplace(valKey); - BEAST_EXPECT( - trustedKeys->load(localKey, cfgKeys, cfgPublishers)); + BEAST_EXPECT(trustedKeys->load(localKey, cfgKeys, cfgPublishers)); TrustChanges changes = trustedKeys->updateTrusted( activeValidators, env.timeKeeper().now(), @@ -1607,11 +1301,9 @@ private: if (cfgKeys.size() > 2) BEAST_EXPECT(changes.added == asNodeIDs({valKey})); else - BEAST_EXPECT( - changes.added == asNodeIDs({localKey, valKey})); + BEAST_EXPECT(changes.added == asNodeIDs({localKey, valKey})); - BEAST_EXPECT( - trustedKeys->quorum() == std::ceil(cfgKeys.size() * 0.8f)); + BEAST_EXPECT(trustedKeys->quorum() == std::ceil(cfgKeys.size() * 0.8f)); for (auto const& key : activeKeys) BEAST_EXPECT(trustedKeys->trusted(key)); @@ -1621,11 +1313,7 @@ private: // Trusted set should include all validators from multiple lists ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); hash_set activeValidators; std::vector valKeys; @@ -1634,19 +1322,14 @@ private: while (valKeys.size() != maxKeys) { valKeys.push_back(randomValidator()); - activeValidators.emplace( - calcNodeID(valKeys.back().masterPublic)); + activeValidators.emplace(calcNodeID(valKeys.back().masterPublic)); } // locals[0]: from 0 to maxKeys - 4 // locals[1]: from 1 to maxKeys - 2 // locals[2]: from 2 to maxKeys constexpr static int publishers = 3; - std::array< - std::pair< - decltype(valKeys)::const_iterator, - decltype(valKeys)::const_iterator>, - publishers> + std::array, publishers> locals = { std::make_pair(valKeys.cbegin(), valKeys.cend() - 4), std::make_pair(valKeys.cbegin() + 1, valKeys.cend() - 2), @@ -1655,41 +1338,28 @@ private: auto addPublishedList = [&, this](int i) { auto const publisherSecret = randomSecretKey(); - auto const publisherPublic = - derivePublicKey(KeyType::ed25519, publisherSecret); + auto const publisherPublic = derivePublicKey(KeyType::ed25519, publisherSecret); auto const pubSigningKeys = randomKeyPair(KeyType::secp256k1); auto const manifest = base64_encode(makeManifestString( - publisherPublic, - publisherSecret, - pubSigningKeys.first, - pubSigningKeys.second, - 1)); + publisherPublic, publisherSecret, pubSigningKeys.first, pubSigningKeys.second, 1)); - std::vector cfgPublishers( - {strHex(publisherPublic)}); + std::vector cfgPublishers({strHex(publisherPublic)}); std::vector emptyCfgKeys; // Threshold of 1 will result in a union of all the lists - BEAST_EXPECT(trustedKeys->load( - {}, emptyCfgKeys, cfgPublishers, std::size_t(1))); + BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers, std::size_t(1))); auto const version = 1; auto const sequence = 1; using namespace std::chrono_literals; - NetClock::time_point const validUntil = - env.timeKeeper().now() + 3600s; - std::vector localKeys{ - locals[i].first, locals[i].second}; - auto const blob = makeList( - localKeys, sequence, validUntil.time_since_epoch().count()); + NetClock::time_point const validUntil = env.timeKeeper().now() + 3600s; + std::vector localKeys{locals[i].first, locals[i].second}; + auto const blob = makeList(localKeys, sequence, validUntil.time_since_epoch().count()); auto const sig = signList(blob, pubSigningKeys); BEAST_EXPECT( ListDisposition::accepted == - trustedKeys - ->applyLists( - manifest, version, {{blob, sig, {}}}, siteUri) - .bestDisposition()); + trustedKeys->applyLists(manifest, version, {{blob, sig, {}}}, siteUri).bestDisposition()); }; // Apply multiple published lists @@ -1704,8 +1374,7 @@ private: env.app().overlay(), env.app().getHashRouter()); - BEAST_EXPECT( - trustedKeys->quorum() == std::ceil(valKeys.size() * 0.8f)); + BEAST_EXPECT(trustedKeys->quorum() == std::ceil(valKeys.size() * 0.8f)); hash_set added; for (auto const& val : valKeys) @@ -1720,11 +1389,7 @@ private: // Trusted set should include validators from intersection of lists ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); hash_set activeValidators; std::vector valKeys; @@ -1733,8 +1398,7 @@ private: while (valKeys.size() != maxKeys) { valKeys.push_back(randomValidator()); - activeValidators.emplace( - calcNodeID(valKeys.back().masterPublic)); + activeValidators.emplace(calcNodeID(valKeys.back().masterPublic)); } // locals[0]: from 0 to maxKeys - 4 @@ -1743,11 +1407,7 @@ private: // intersection of at least 2: same as locals[1] // intersection when 1 is dropped: from 2 to maxKeys - 4 constexpr static int publishers = 3; - std::array< - std::pair< - decltype(valKeys)::const_iterator, - decltype(valKeys)::const_iterator>, - publishers> + std::array, publishers> locals = { std::make_pair(valKeys.cbegin(), valKeys.cend() - 4), std::make_pair(valKeys.cbegin() + 1, valKeys.cend() - 2), @@ -1755,51 +1415,34 @@ private: }; auto addPublishedList = [&, this]( - int i, - NetClock::time_point& validUntil1, - NetClock::time_point& validUntil2) { + int i, NetClock::time_point& validUntil1, NetClock::time_point& validUntil2) { auto const publisherSecret = randomSecretKey(); - auto const publisherPublic = - derivePublicKey(KeyType::ed25519, publisherSecret); + auto const publisherPublic = derivePublicKey(KeyType::ed25519, publisherSecret); auto const pubSigningKeys = randomKeyPair(KeyType::secp256k1); auto const manifest = base64_encode(makeManifestString( - publisherPublic, - publisherSecret, - pubSigningKeys.first, - pubSigningKeys.second, - 1)); + publisherPublic, publisherSecret, pubSigningKeys.first, pubSigningKeys.second, 1)); - std::vector cfgPublishers( - {strHex(publisherPublic)}); + std::vector cfgPublishers({strHex(publisherPublic)}); std::vector emptyCfgKeys; - BEAST_EXPECT( - trustedKeys->load({}, emptyCfgKeys, cfgPublishers)); + BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers)); auto const version = 1; auto const sequence = 1; using namespace std::chrono_literals; // Want to drop 1 sooner - NetClock::time_point const validUntil = env.timeKeeper().now() + - (i == 2 ? 120s - : i == 1 ? 60s - : 3600s); + NetClock::time_point const validUntil = env.timeKeeper().now() + (i == 2 ? 120s : i == 1 ? 60s : 3600s); if (i == 1) validUntil1 = validUntil; else if (i == 2) validUntil2 = validUntil; - std::vector localKeys{ - locals[i].first, locals[i].second}; - auto const blob = makeList( - localKeys, sequence, validUntil.time_since_epoch().count()); + std::vector localKeys{locals[i].first, locals[i].second}; + auto const blob = makeList(localKeys, sequence, validUntil.time_since_epoch().count()); auto const sig = signList(blob, pubSigningKeys); BEAST_EXPECT( ListDisposition::accepted == - trustedKeys - ->applyLists( - manifest, version, {{blob, sig, {}}}, siteUri) - .bestDisposition()); + trustedKeys->applyLists(manifest, version, {{blob, sig, {}}}, siteUri).bestDisposition()); }; // Apply multiple published lists @@ -1816,9 +1459,7 @@ private: env.app().overlay(), env.app().getHashRouter()); - BEAST_EXPECT( - trustedKeys->quorum() == - std::ceil((valKeys.size() - 3) * 0.8f)); + BEAST_EXPECT(trustedKeys->quorum() == std::ceil((valKeys.size() - 3) * 0.8f)); for (auto const& val : valKeys) BEAST_EXPECT(trustedKeys->listed(val.masterPublic)); @@ -1847,9 +1488,7 @@ private: env.app().overlay(), env.app().getHashRouter()); - BEAST_EXPECT( - trustedKeys->quorum() == - std::ceil((valKeys.size() - 6) * 0.8f)); + BEAST_EXPECT(trustedKeys->quorum() == std::ceil((valKeys.size() - 6) * 0.8f)); for (auto const& val : valKeys) BEAST_EXPECT(trustedKeys->listed(val.masterPublic)); @@ -1880,9 +1519,7 @@ private: env.app().overlay(), env.app().getHashRouter()); - BEAST_EXPECT( - trustedKeys->quorum() == - std::numeric_limits::max()); + BEAST_EXPECT(trustedKeys->quorum() == std::numeric_limits::max()); removed.clear(); for (std::size_t i = 0; i < maxKeys; ++i) @@ -1913,19 +1550,13 @@ private: jtx::Env env(*this); auto& app = env.app(); - auto toStr = [](PublicKey const& publicKey) { - return toBase58(TokenType::NodePublic, publicKey); - }; + auto toStr = [](PublicKey const& publicKey) { return toBase58(TokenType::NodePublic, publicKey); }; // Config listed keys { ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); // Empty list has no expiration BEAST_EXPECT(trustedKeys->expires() == std::nullopt); @@ -1933,9 +1564,7 @@ private: // Config listed keys have maximum expiry PublicKey localCfgListed = randomNode(); trustedKeys->load({}, {toStr(localCfgListed)}, {}); - BEAST_EXPECT( - trustedKeys->expires() && - trustedKeys->expires().value() == NetClock::time_point::max()); + BEAST_EXPECT(trustedKeys->expires() && trustedKeys->expires().value() == NetClock::time_point::max()); BEAST_EXPECT(trustedKeys->listed(localCfgListed)); } @@ -1943,11 +1572,7 @@ private: { ManifestCache manifests; auto trustedKeys = std::make_unique( - manifests, - manifests, - env.app().timeKeeper(), - app.config().legacy("database_path"), - env.journal); + manifests, manifests, env.app().timeKeeper(), app.config().legacy("database_path"), env.journal); std::vector validators = {randomValidator()}; hash_set activeValidators; @@ -1966,31 +1591,20 @@ private: using namespace std::chrono_literals; auto addPublishedList = [this, &env, &trustedKeys, &validators]() { auto const publisherSecret = randomSecretKey(); - auto const publisherPublic = - derivePublicKey(KeyType::ed25519, publisherSecret); + auto const publisherPublic = derivePublicKey(KeyType::ed25519, publisherSecret); auto const pubSigningKeys = randomKeyPair(KeyType::secp256k1); auto const manifest = base64_encode(makeManifestString( - publisherPublic, - publisherSecret, - pubSigningKeys.first, - pubSigningKeys.second, - 1)); + publisherPublic, publisherSecret, pubSigningKeys.first, pubSigningKeys.second, 1)); - std::vector cfgPublishers( - {strHex(publisherPublic)}); + std::vector cfgPublishers({strHex(publisherPublic)}); std::vector emptyCfgKeys; - BEAST_EXPECT( - trustedKeys->load({}, emptyCfgKeys, cfgPublishers)); + BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers)); auto const version = 2; auto const sequence1 = 1; - NetClock::time_point const expiration1 = - env.timeKeeper().now() + 1800s; - auto const blob1 = makeList( - validators, - sequence1, - expiration1.time_since_epoch().count()); + NetClock::time_point const expiration1 = env.timeKeeper().now() + 1800s; + auto const blob1 = makeList(validators, sequence1, expiration1.time_since_epoch().count()); auto const sig1 = signList(blob1, pubSigningKeys); NetClock::time_point const effective2 = expiration1 - 300s; @@ -2021,8 +1635,7 @@ private: // Apply first list checkResult( - trustedKeys->applyLists( - prep1.manifest, prep1.version, prep1.blobs, siteUri), + trustedKeys->applyLists(prep1.manifest, prep1.version, prep1.blobs, siteUri), prep1.publisherPublic, ListDisposition::pending, ListDisposition::accepted); @@ -2033,15 +1646,12 @@ private: // Apply second list checkResult( - trustedKeys->applyLists( - prep2.manifest, prep2.version, prep2.blobs, siteUri), + trustedKeys->applyLists(prep2.manifest, prep2.version, prep2.blobs, siteUri), prep2.publisherPublic, ListDisposition::pending, ListDisposition::accepted); // We now have loaded both lists, so expiration is known - BEAST_EXPECT( - trustedKeys->expires() && - trustedKeys->expires().value() == prep1.expirations.back()); + BEAST_EXPECT(trustedKeys->expires() && trustedKeys->expires().value() == prep1.expirations.back()); // Advance past the first list's LAST validFrom date. It remains // the earliest validUntil, while rotating in the second list @@ -2053,9 +1663,7 @@ private: env.app().getOPs(), env.app().overlay(), env.app().getHashRouter()); - BEAST_EXPECT( - trustedKeys->expires() && - trustedKeys->expires().value() == prep1.expirations.back()); + BEAST_EXPECT(trustedKeys->expires() && trustedKeys->expires().value() == prep1.expirations.back()); BEAST_EXPECT(!changes.added.empty()); BEAST_EXPECT(changes.removed.empty()); } @@ -2070,9 +1678,7 @@ private: env.app().getOPs(), env.app().overlay(), env.app().getHashRouter()); - BEAST_EXPECT( - trustedKeys->expires() && - trustedKeys->expires().value() == prep1.expirations.back()); + BEAST_EXPECT(trustedKeys->expires() && trustedKeys->expires().value() == prep1.expirations.back()); BEAST_EXPECT(changes.added.empty()); BEAST_EXPECT(changes.removed.empty()); } @@ -2087,9 +1693,7 @@ private: ManifestCache manifests; auto createValidatorList = - [&](std::uint32_t vlSize, - std::optional minimumQuorum = {}) - -> std::shared_ptr { + [&](std::uint32_t vlSize, std::optional minimumQuorum = {}) -> std::shared_ptr { auto trustedKeys = std::make_shared( manifests, manifests, @@ -2116,8 +1720,7 @@ private: env.app().getOPs(), env.app().overlay(), env.app().getHashRouter()); - if (minimumQuorum == trustedKeys->quorum() || - trustedKeys->quorum() == std::ceil(cfgKeys.size() * 0.8f)) + if (minimumQuorum == trustedKeys->quorum() || trustedKeys->quorum() == std::ceil(cfgKeys.size() * 0.8f)) return trustedKeys; } return nullptr; @@ -2168,8 +1771,7 @@ private: env.app().getHashRouter()); BEAST_EXPECT( validators->quorum() == - static_cast(std::ceil( - std::max((us - nUnlSize) * 0.8f, us * 0.6f)))); + static_cast(std::ceil(std::max((us - nUnlSize) * 0.8f, us * 0.6f)))); } } } @@ -2187,8 +1789,7 @@ private: { //-- set == get, //-- check quorum, with nUNL size: 0, 30, 18, 12 - auto nUnlChange = [&](std::uint32_t nUnlSize, - std::uint32_t quorum) -> bool { + auto nUnlChange = [&](std::uint32_t nUnlSize, std::uint32_t quorum) -> bool { hash_set nUnl; auto it = unl.begin(); for (std::uint32_t i = 0; i < nUnlSize; ++i) @@ -2311,8 +1912,7 @@ private: BEAST_EXPECT(global != sha512Half(signature, blobVector, version)); { - std::map blobMap{ - {99, blobVector[0]}}; + std::map blobMap{{99, blobVector[0]}}; BEAST_EXPECT(global == sha512Half(manifest, blobMap, version)); BEAST_EXPECT(global != sha512Half(blob, blobMap, version)); } @@ -2348,8 +1948,7 @@ private: std::uint32_t const manifestCutoff = 7; auto extractHeader = [this](Message& message) { - auto const& buffer = - message.getBuffer(compression::Compressed::Off); + auto const& buffer = message.getBuffer(compression::Compressed::Off); boost::beast::multi_buffer buffers; @@ -2357,163 +1956,117 @@ private: auto start = buffer.begin(); auto end = buffer.end(); std::vector slice(start, end); - buffers.commit(boost::asio::buffer_copy( - buffers.prepare(slice.size()), boost::asio::buffer(slice))); + buffers.commit(boost::asio::buffer_copy(buffers.prepare(slice.size()), boost::asio::buffer(slice))); boost::system::error_code ec; - auto header = - detail::parseMessageHeader(ec, buffers.data(), buffers.size()); + auto header = detail::parseMessageHeader(ec, buffers.data(), buffers.size()); BEAST_EXPECT(!ec); return std::make_pair(header, buffers); }; - auto extractProtocolMessage1 = [this, - &extractHeader](Message& message) { + auto extractProtocolMessage1 = [this, &extractHeader](Message& message) { auto [header, buffers] = extractHeader(message); - if (BEAST_EXPECT(header) && - BEAST_EXPECT( - header->message_type == protocol::mtVALIDATOR_LIST)) + if (BEAST_EXPECT(header) && BEAST_EXPECT(header->message_type == protocol::mtVALIDATOR_LIST)) { - auto const msg = - detail::parseMessageContent( - *header, buffers.data()); + auto const msg = detail::parseMessageContent(*header, buffers.data()); BEAST_EXPECT(msg); return msg; } return std::shared_ptr(); }; - auto extractProtocolMessage2 = [this, - &extractHeader](Message& message) { + auto extractProtocolMessage2 = [this, &extractHeader](Message& message) { auto [header, buffers] = extractHeader(message); - if (BEAST_EXPECT(header) && - BEAST_EXPECT( - header->message_type == - protocol::mtVALIDATOR_LIST_COLLECTION)) + if (BEAST_EXPECT(header) && BEAST_EXPECT(header->message_type == protocol::mtVALIDATOR_LIST_COLLECTION)) { - auto const msg = detail::parseMessageContent< - protocol::TMValidatorListCollection>( - *header, buffers.data()); + auto const msg = + detail::parseMessageContent(*header, buffers.data()); BEAST_EXPECT(msg); return msg; } return std::shared_ptr(); }; - auto verifyMessage = - [this, - manifestCutoff, - &extractProtocolMessage1, - &extractProtocolMessage2]( - auto const version, - auto const& manifest, - auto const& blobInfos, - auto const& messages, - std::vector>> - expectedInfo) { - BEAST_EXPECT(messages.size() == expectedInfo.size()); - auto msgIter = expectedInfo.begin(); - for (auto const& messageWithHash : messages) + auto verifyMessage = [this, manifestCutoff, &extractProtocolMessage1, &extractProtocolMessage2]( + auto const version, + auto const& manifest, + auto const& blobInfos, + auto const& messages, + std::vector>> expectedInfo) { + BEAST_EXPECT(messages.size() == expectedInfo.size()); + auto msgIter = expectedInfo.begin(); + for (auto const& messageWithHash : messages) + { + if (!BEAST_EXPECT(msgIter != expectedInfo.end())) + break; + if (!BEAST_EXPECT(messageWithHash.message)) + continue; + auto const& expectedSeqs = msgIter->second; + auto seqIter = expectedSeqs.begin(); + auto const size = messageWithHash.message->getBuffer(compression::Compressed::Off).size(); + // This size is arbitrary, but shouldn't change + BEAST_EXPECT(size == msgIter->first); + if (expectedSeqs.size() == 1) { - if (!BEAST_EXPECT(msgIter != expectedInfo.end())) - break; - if (!BEAST_EXPECT(messageWithHash.message)) - continue; - auto const& expectedSeqs = msgIter->second; - auto seqIter = expectedSeqs.begin(); - auto const size = - messageWithHash.message - ->getBuffer(compression::Compressed::Off) - .size(); - // This size is arbitrary, but shouldn't change - BEAST_EXPECT(size == msgIter->first); - if (expectedSeqs.size() == 1) + auto const msg = extractProtocolMessage1(*messageWithHash.message); + auto const expectedVersion = 1; + if (BEAST_EXPECT(msg)) { - auto const msg = - extractProtocolMessage1(*messageWithHash.message); - auto const expectedVersion = 1; - if (BEAST_EXPECT(msg)) - { - BEAST_EXPECT(msg->version() == expectedVersion); - if (!BEAST_EXPECT(seqIter != expectedSeqs.end())) - continue; - auto const& expectedBlob = blobInfos.at(*seqIter); - BEAST_EXPECT( - (*seqIter < manifestCutoff) == - !!expectedBlob.manifest); - auto const expectedManifest = - *seqIter < manifestCutoff && - expectedBlob.manifest - ? *expectedBlob.manifest - : manifest; - BEAST_EXPECT(msg->manifest() == expectedManifest); - BEAST_EXPECT(msg->blob() == expectedBlob.blob); - BEAST_EXPECT( - msg->signature() == expectedBlob.signature); - ++seqIter; - BEAST_EXPECT(seqIter == expectedSeqs.end()); + BEAST_EXPECT(msg->version() == expectedVersion); + if (!BEAST_EXPECT(seqIter != expectedSeqs.end())) + continue; + auto const& expectedBlob = blobInfos.at(*seqIter); + BEAST_EXPECT((*seqIter < manifestCutoff) == !!expectedBlob.manifest); + auto const expectedManifest = + *seqIter < manifestCutoff && expectedBlob.manifest ? *expectedBlob.manifest : manifest; + BEAST_EXPECT(msg->manifest() == expectedManifest); + BEAST_EXPECT(msg->blob() == expectedBlob.blob); + BEAST_EXPECT(msg->signature() == expectedBlob.signature); + ++seqIter; + BEAST_EXPECT(seqIter == expectedSeqs.end()); - BEAST_EXPECT( - messageWithHash.hash == - sha512Half( - expectedManifest, - expectedBlob.blob, - expectedBlob.signature, - expectedVersion)); - } - } - else - { - std::vector hashingBlobs; - hashingBlobs.reserve(msgIter->second.size()); - - auto const msg = - extractProtocolMessage2(*messageWithHash.message); - if (BEAST_EXPECT(msg)) - { - BEAST_EXPECT(msg->version() == version); - BEAST_EXPECT(msg->manifest() == manifest); - for (auto const& blobInfo : msg->blobs()) - { - if (!BEAST_EXPECT( - seqIter != expectedSeqs.end())) - break; - auto const& expectedBlob = - blobInfos.at(*seqIter); - hashingBlobs.push_back(expectedBlob); - BEAST_EXPECT( - blobInfo.has_manifest() == - !!expectedBlob.manifest); - BEAST_EXPECT( - blobInfo.has_manifest() == - (*seqIter < manifestCutoff)); - - if (*seqIter < manifestCutoff) - BEAST_EXPECT( - blobInfo.manifest() == - *expectedBlob.manifest); - BEAST_EXPECT( - blobInfo.blob() == expectedBlob.blob); - BEAST_EXPECT( - blobInfo.signature() == - expectedBlob.signature); - ++seqIter; - } - BEAST_EXPECT(seqIter == expectedSeqs.end()); - } BEAST_EXPECT( messageWithHash.hash == - sha512Half(manifest, hashingBlobs, version)); + sha512Half(expectedManifest, expectedBlob.blob, expectedBlob.signature, expectedVersion)); } - ++msgIter; } - BEAST_EXPECT(msgIter == expectedInfo.end()); - }; - auto verifyBuildMessages = - [this]( - std::pair const& result, - std::size_t expectedSequence, - std::size_t expectedSize) { - BEAST_EXPECT(result.first == expectedSequence); - BEAST_EXPECT(result.second == expectedSize); - }; + else + { + std::vector hashingBlobs; + hashingBlobs.reserve(msgIter->second.size()); + + auto const msg = extractProtocolMessage2(*messageWithHash.message); + if (BEAST_EXPECT(msg)) + { + BEAST_EXPECT(msg->version() == version); + BEAST_EXPECT(msg->manifest() == manifest); + for (auto const& blobInfo : msg->blobs()) + { + if (!BEAST_EXPECT(seqIter != expectedSeqs.end())) + break; + auto const& expectedBlob = blobInfos.at(*seqIter); + hashingBlobs.push_back(expectedBlob); + BEAST_EXPECT(blobInfo.has_manifest() == !!expectedBlob.manifest); + BEAST_EXPECT(blobInfo.has_manifest() == (*seqIter < manifestCutoff)); + + if (*seqIter < manifestCutoff) + BEAST_EXPECT(blobInfo.manifest() == *expectedBlob.manifest); + BEAST_EXPECT(blobInfo.blob() == expectedBlob.blob); + BEAST_EXPECT(blobInfo.signature() == expectedBlob.signature); + ++seqIter; + } + BEAST_EXPECT(seqIter == expectedSeqs.end()); + } + BEAST_EXPECT(messageWithHash.hash == sha512Half(manifest, hashingBlobs, version)); + } + ++msgIter; + } + BEAST_EXPECT(msgIter == expectedInfo.end()); + }; + auto verifyBuildMessages = [this]( + std::pair const& result, + std::size_t expectedSequence, + std::size_t expectedSize) { + BEAST_EXPECT(result.first == expectedSequence); + BEAST_EXPECT(result.second == expectedSize); + }; std::string const manifest = "This is not a manifest"; std::uint32_t const version = 2; @@ -2549,10 +2102,7 @@ private: // This peer has a VL ahead of our "current" verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 1, 8, maxSequence, version, manifest, blobInfos, messages), - 0, - 0); + ValidatorList::buildValidatorListMessages(1, 8, maxSequence, version, manifest, blobInfos, messages), 0, 0); BEAST_EXPECT(messages.size() == 0); // Don't repeat the work if messages is populated, even though the @@ -2561,27 +2111,18 @@ private: // real code. messages.emplace_back(); verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 1, 3, maxSequence, version, manifest, blobInfos, messages), - 5, - 0); + ValidatorList::buildValidatorListMessages(1, 3, maxSequence, version, manifest, blobInfos, messages), 5, 0); BEAST_EXPECT(messages.size() == 1 && !messages.front().message); // Generate a version 1 message messages.clear(); verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 1, 3, maxSequence, version, manifest, blobInfos, messages), - 5, - 1); - if (BEAST_EXPECT(messages.size() == 1) && - BEAST_EXPECT(messages.front().message)) + ValidatorList::buildValidatorListMessages(1, 3, maxSequence, version, manifest, blobInfos, messages), 5, 1); + if (BEAST_EXPECT(messages.size() == 1) && BEAST_EXPECT(messages.front().message)) { auto const& messageWithHash = messages.front(); auto const msg = extractProtocolMessage1(*messageWithHash.message); - auto const size = - messageWithHash.message->getBuffer(compression::Compressed::Off) - .size(); + auto const size = messageWithHash.message->getBuffer(compression::Compressed::Off).size(); // This size is arbitrary, but shouldn't change BEAST_EXPECT(size == 108); auto const& expected = blobInfos.at(5); @@ -2592,10 +2133,7 @@ private: BEAST_EXPECT(msg->blob() == expected.blob); BEAST_EXPECT(msg->signature() == expected.signature); } - BEAST_EXPECT( - messageWithHash.hash == - sha512Half( - *expected.manifest, expected.blob, expected.signature, 1)); + BEAST_EXPECT(messageWithHash.hash == sha512Half(*expected.manifest, expected.blob, expected.signature, 1)); } // Version 2 @@ -2605,13 +2143,7 @@ private: // This peer has a VL ahead of us. verifyBuildMessages( ValidatorList::buildValidatorListMessages( - 2, - maxSequence * 2, - maxSequence, - version, - manifest, - blobInfos, - messages), + 2, maxSequence * 2, maxSequence, version, manifest, blobInfos, messages), 0, 0); BEAST_EXPECT(messages.size() == 0); @@ -2622,8 +2154,7 @@ private: // real code. messages.emplace_back(); verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 2, 3, maxSequence, version, manifest, blobInfos, messages), + ValidatorList::buildValidatorListMessages(2, 3, maxSequence, version, manifest, blobInfos, messages), maxSequence, 0); BEAST_EXPECT(messages.size() == 1 && !messages.front().message); @@ -2631,72 +2162,46 @@ private: // Generate a version 2 message. Don't send the current messages.clear(); verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 2, 5, maxSequence, version, manifest, blobInfos, messages), + ValidatorList::buildValidatorListMessages(2, 5, maxSequence, version, manifest, blobInfos, messages), maxSequence, 4); - verifyMessage( - version, manifest, blobInfos, messages, {{372, {6, 7, 10, 12}}}); + verifyMessage(version, manifest, blobInfos, messages, {{372, {6, 7, 10, 12}}}); // Test message splitting on size limits. // Set a limit that should give two messages messages.clear(); verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 2, 5, maxSequence, version, manifest, blobInfos, messages, 300), + ValidatorList::buildValidatorListMessages(2, 5, maxSequence, version, manifest, blobInfos, messages, 300), maxSequence, 4); - verifyMessage( - version, - manifest, - blobInfos, - messages, - {{212, {6, 7}}, {192, {10, 12}}}); + verifyMessage(version, manifest, blobInfos, messages, {{212, {6, 7}}, {192, {10, 12}}}); // Set a limit between the size of the two earlier messages so one // will split and the other won't messages.clear(); verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 2, 5, maxSequence, version, manifest, blobInfos, messages, 200), + ValidatorList::buildValidatorListMessages(2, 5, maxSequence, version, manifest, blobInfos, messages, 200), maxSequence, 4); - verifyMessage( - version, - manifest, - blobInfos, - messages, - {{108, {6}}, {108, {7}}, {192, {10, 12}}}); + verifyMessage(version, manifest, blobInfos, messages, {{108, {6}}, {108, {7}}, {192, {10, 12}}}); // Set a limit so that all the VLs are sent individually messages.clear(); verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 2, 5, maxSequence, version, manifest, blobInfos, messages, 150), + ValidatorList::buildValidatorListMessages(2, 5, maxSequence, version, manifest, blobInfos, messages, 150), maxSequence, 4); - verifyMessage( - version, - manifest, - blobInfos, - messages, - {{108, {6}}, {108, {7}}, {110, {10}}, {110, {12}}}); + verifyMessage(version, manifest, blobInfos, messages, {{108, {6}}, {108, {7}}, {110, {10}}, {110, {12}}}); // Set a limit smaller than some of the messages. Because single // messages send regardless, they will all still be sent messages.clear(); verifyBuildMessages( - ValidatorList::buildValidatorListMessages( - 2, 5, maxSequence, version, manifest, blobInfos, messages, 108), + ValidatorList::buildValidatorListMessages(2, 5, maxSequence, version, manifest, blobInfos, messages, 108), maxSequence, 4); - verifyMessage( - version, - manifest, - blobInfos, - messages, - {{108, {6}}, {108, {7}}, {110, {10}}, {110, {12}}}); + verifyMessage(version, manifest, blobInfos, messages, {{108, {6}}, {108, {7}}, {110, {10}}, {110, {12}}}); } void @@ -2738,76 +2243,48 @@ private: std::vector& publishers // out ) -> std::unique_ptr { auto result = std::make_unique( - valManifests, - pubManifests, - env.timeKeeper(), - app.config().legacy("database_path"), - env.journal); + valManifests, pubManifests, env.timeKeeper(), app.config().legacy("database_path"), env.journal); std::vector cfgPublishers; for (std::size_t i = 0; i < countTotal; ++i) { auto const publisherSecret = randomSecretKey(); - auto const publisherPublic = - derivePublicKey(KeyType::ed25519, publisherSecret); + auto const publisherPublic = derivePublicKey(KeyType::ed25519, publisherSecret); auto const pubSigningKeys = randomKeyPair(KeyType::secp256k1); cfgPublishers.push_back(strHex(publisherPublic)); - constexpr auto revoked = - std::numeric_limits::max(); + constexpr auto revoked = std::numeric_limits::max(); auto const manifest = base64_encode(makeManifestString( publisherPublic, publisherSecret, pubSigningKeys.first, pubSigningKeys.second, i < countRevoked ? revoked : 1)); - publishers.push_back(Publisher{ - i < countRevoked, - publisherPublic, - pubSigningKeys, - manifest}); + publishers.push_back(Publisher{i < countRevoked, publisherPublic, pubSigningKeys, manifest}); } std::vector const emptyCfgKeys; - auto threshold = - listThreshold > 0 ? std::optional(listThreshold) : std::nullopt; + auto threshold = listThreshold > 0 ? std::optional(listThreshold) : std::nullopt; if (self) { - valManifests.applyManifest( - *deserializeManifest(base64_decode(self->manifest))); - BEAST_EXPECT(result->load( - self->signingPublic, - emptyCfgKeys, - cfgPublishers, - threshold)); + valManifests.applyManifest(*deserializeManifest(base64_decode(self->manifest))); + BEAST_EXPECT(result->load(self->signingPublic, emptyCfgKeys, cfgPublishers, threshold)); } else { - BEAST_EXPECT( - result->load({}, emptyCfgKeys, cfgPublishers, threshold)); + BEAST_EXPECT(result->load({}, emptyCfgKeys, cfgPublishers, threshold)); } for (std::size_t i = 0; i < countTotal; ++i) { using namespace std::chrono_literals; - publishers[i].expiry = env.timeKeeper().now() + - (i == countTotal - 1 ? 60s : 3600s); - auto const blob = makeList( - valKeys, - 1, - publishers[i].expiry.time_since_epoch().count()); + publishers[i].expiry = env.timeKeeper().now() + (i == countTotal - 1 ? 60s : 3600s); + auto const blob = makeList(valKeys, 1, publishers[i].expiry.time_since_epoch().count()); auto const sig = signList(blob, publishers[i].signingKeys); BEAST_EXPECT( - result - ->applyLists( - publishers[i].manifest, - 1, - {{blob, sig, {}}}, - siteUri) - .bestDisposition() == - (publishers[i].revoked ? ListDisposition::untrusted - : ListDisposition::accepted)); + result->applyLists(publishers[i].manifest, 1, {{blob, sig, {}}}, siteUri).bestDisposition() == + (publishers[i].revoked ? ListDisposition::untrusted : ListDisposition::accepted)); } return result; @@ -2842,8 +2319,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -2902,8 +2378,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -2968,8 +2443,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3038,8 +2512,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -3106,8 +2579,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3174,8 +2646,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3240,8 +2711,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -3262,8 +2732,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == quorumDisabled); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); BEAST_EXPECT(trustedKeys->trusted(self.masterPublic)); for (auto const& val : valKeys) @@ -3301,8 +2770,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -3323,8 +2791,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == quorumDisabled); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); BEAST_EXPECT(trustedKeys->trusted(self.masterPublic)); for (auto const& val : valKeys) @@ -3362,8 +2829,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3383,8 +2849,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == quorumDisabled); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); BEAST_EXPECT(trustedKeys->trusted(self.masterPublic)); for (auto const& val : valKeys) @@ -3420,8 +2885,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3441,8 +2905,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == quorumDisabled); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); for (auto const& val : valKeys) { @@ -3487,8 +2950,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == quorumDisabled); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -3555,8 +3017,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == quorumDisabled); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3623,8 +3084,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == quorumDisabled); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3683,8 +3143,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -3745,8 +3204,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -3808,8 +3266,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3870,8 +3327,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -3934,8 +3390,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -3973,8 +3428,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) @@ -4020,8 +3474,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; added.insert(calcNodeID(self.masterPublic)); @@ -4090,8 +3543,7 @@ private: env.app().overlay(), env.app().getHashRouter()); BEAST_EXPECT(trustedKeys->quorum() == std::ceil(keysTotal * 0.8f)); - BEAST_EXPECT( - trustedKeys->getTrustedMasterKeys().size() == keysTotal); + BEAST_EXPECT(trustedKeys->getTrustedMasterKeys().size() == keysTotal); hash_set added; for (auto const& val : valKeys) diff --git a/src/test/app/ValidatorSite_test.cpp b/src/test/app/ValidatorSite_test.cpp index 1118818d7a..3b616ad5c9 100644 --- a/src/test/app/ValidatorSite_test.cpp +++ b/src/test/app/ValidatorSite_test.cpp @@ -50,8 +50,7 @@ private: using namespace jtx; Env env(*this, envconfig(), nullptr, beast::severities::kDisabled); - auto trustedSites = - std::make_unique(env.app(), env.journal); + auto trustedSites = std::make_unique(env.app(), env.journal); // load should accept empty sites list std::vector emptyCfgSites; @@ -118,25 +117,18 @@ private: bool failApply = false; int serverVersion = 1; std::chrono::seconds expiresFromNow = detail::default_expires; - std::chrono::seconds effectiveOverlap = - detail::default_effective_overlap; + std::chrono::seconds effectiveOverlap = detail::default_effective_overlap; int expectedRefreshMin = 0; }; void - testFetchList( - detail::DirGuard const& good, - std::vector const& paths) + testFetchList(detail::DirGuard const& good, std::vector const& paths) { testcase << "Fetch list - " << boost::algorithm::join( - paths | - boost::adaptors::transformed( - [](FetchListConfig const& cfg) { - return cfg.path + - (cfg.ssl ? " [https] v" : " [http] v") + - std::to_string(cfg.serverVersion) + - " " + cfg.msg; - }), + paths | boost::adaptors::transformed([](FetchListConfig const& cfg) { + return cfg.path + (cfg.ssl ? " [https] v" : " [http] v") + + std::to_string(cfg.serverVersion) + " " + cfg.msg; + }), ", "); using namespace jtx; @@ -179,19 +171,11 @@ private: while (item.list.size() < listSize) item.list.push_back(TrustedPublisherServer::randomValidator()); - NetClock::time_point const expires = - env.timeKeeper().now() + cfg.expiresFromNow; - NetClock::time_point const effective2 = - expires - cfg.effectiveOverlap; - NetClock::time_point const expires2 = - effective2 + cfg.expiresFromNow; + NetClock::time_point const expires = env.timeKeeper().now() + cfg.expiresFromNow; + NetClock::time_point const effective2 = expires - cfg.effectiveOverlap; + NetClock::time_point const expires2 = effective2 + cfg.expiresFromNow; item.server = make_TrustedPublisherServer( - env.app().getIOContext(), - item.list, - expires, - {{effective2, expires2}}, - cfg.ssl, - cfg.serverVersion); + env.app().getIOContext(), item.list, expires, {{effective2, expires2}}, cfg.ssl, cfg.serverVersion); std::string pubHex = strHex(item.server->publisherPublic()); cfgPublishers.push_back(pubHex); @@ -204,8 +188,7 @@ private: } std::stringstream uri; - uri << (cfg.ssl ? "https://" : "http://") - << item.server->local_endpoint() << cfg.path; + uri << (cfg.ssl ? "https://" : "http://") << item.server->local_endpoint() << cfg.path; item.uri = uri.str(); } @@ -231,10 +214,8 @@ private: { for (auto const& val : u.list) { - BEAST_EXPECT( - trustedKeys.listed(val.masterPublic) != u.cfg.failApply); - BEAST_EXPECT( - trustedKeys.listed(val.signingPublic) != u.cfg.failApply); + BEAST_EXPECT(trustedKeys.listed(val.masterPublic) != u.cfg.failApply); + BEAST_EXPECT(trustedKeys.listed(val.signingPublic) != u.cfg.failApply); } Json::Value myStatus; @@ -242,30 +223,24 @@ private: if (vs[jss::uri].asString().find(u.uri) != std::string::npos) myStatus = vs; BEAST_EXPECTS( - myStatus[jss::last_refresh_message].asString().empty() != - u.cfg.failFetch, + myStatus[jss::last_refresh_message].asString().empty() != u.cfg.failFetch, to_string(myStatus) + "\n" + sink.messages().str()); if (!u.cfg.msg.empty()) { - BEAST_EXPECTS( - sink.messages().str().find(u.cfg.msg) != std::string::npos, - sink.messages().str()); + BEAST_EXPECTS(sink.messages().str().find(u.cfg.msg) != std::string::npos, sink.messages().str()); } if (u.cfg.expectedRefreshMin) { BEAST_EXPECTS( - myStatus[jss::refresh_interval_min].asInt() == - u.cfg.expectedRefreshMin, - to_string(myStatus)); + myStatus[jss::refresh_interval_min].asInt() == u.cfg.expectedRefreshMin, to_string(myStatus)); } if (u.cfg.failFetch) { using namespace std::chrono; - std::stringstream nextRefreshStr{ - myStatus[jss::next_refresh_time].asString()}; + std::stringstream nextRefreshStr{myStatus[jss::next_refresh_time].asString()}; system_clock::time_point nextRefresh; date::from_stream(nextRefreshStr, "%Y-%b-%d %T", nextRefresh); BEAST_EXPECT(!nextRefreshStr.fail()); @@ -280,8 +255,7 @@ private: void testFileList(std::vector> const& paths) { - testcase << "File list - " << paths[0].first - << (paths.size() > 1 ? ", " + paths[1].first : ""); + testcase << "File list - " << paths[0].first << (paths.size() > 1 ? ", " + paths[1].first : ""); using namespace jtx; @@ -326,16 +300,10 @@ private: for (auto const& vs : jv[jss::validator_sites]) if (vs[jss::uri].asString().find(u.uri) != std::string::npos) myStatus = vs; - BEAST_EXPECTS( - myStatus[jss::last_refresh_message].asString().empty() != - u.shouldFail, - to_string(myStatus)); + BEAST_EXPECTS(myStatus[jss::last_refresh_message].asString().empty() != u.shouldFail, to_string(myStatus)); if (u.shouldFail) { - BEAST_EXPECTS( - sink.messages().str().find(u.expectMsg) != - std::string::npos, - sink.messages().str()); + BEAST_EXPECTS(sink.messages().str().find(u.expectMsg) != std::string::npos, sink.messages().str()); } } } @@ -351,27 +319,19 @@ private: }; { // Create a file with a real validator list - detail::FileDirGuard good( - *this, "test_val", "vl.txt", detail::realValidatorContents()); + detail::FileDirGuard good(*this, "test_val", "vl.txt", detail::realValidatorContents()); // Create a file with arbitrary content - detail::FileDirGuard hello( - *this, "test_val", "helloworld.txt", "Hello, world!"); + detail::FileDirGuard hello(*this, "test_val", "helloworld.txt", "Hello, world!"); // Create a file with malformed Json - detail::FileDirGuard json( - *this, - "test_val", - "json.txt", - R"json({ "version": 2, "extra" : "value" })json"); + detail::FileDirGuard json(*this, "test_val", "json.txt", R"json({ "version": 2, "extra" : "value" })json"); auto const goodPath = fullPath(good); auto const helloPath = fullPath(hello); auto const jsonPath = fullPath(json); auto const missingPath = jsonPath + ".bad"; testFileList({ {goodPath, ""}, - {helloPath, - "Unable to parse JSON response from file://" + helloPath}, - {jsonPath, - "Missing fields in JSON response from file://" + jsonPath}, + {helloPath, "Unable to parse JSON response from file://" + helloPath}, + {jsonPath, "Missing fields in JSON response from file://" + jsonPath}, {missingPath, "Problem retrieving from file://" + missingPath}, }); } @@ -390,179 +350,68 @@ public: testFetchList(good, {{"/validators", "", ssl}}); testFetchList(good, {{"/validators2", "", ssl}}); // fetch multiple sites - testFetchList( - good, {{"/validators", "", ssl}, {"/validators", "", ssl}}); - testFetchList( - good, {{"/validators", "", ssl}, {"/validators2", "", ssl}}); - testFetchList( - good, {{"/validators2", "", ssl}, {"/validators", "", ssl}}); - testFetchList( - good, {{"/validators2", "", ssl}, {"/validators2", "", ssl}}); + testFetchList(good, {{"/validators", "", ssl}, {"/validators", "", ssl}}); + testFetchList(good, {{"/validators", "", ssl}, {"/validators2", "", ssl}}); + testFetchList(good, {{"/validators2", "", ssl}, {"/validators", "", ssl}}); + testFetchList(good, {{"/validators2", "", ssl}, {"/validators2", "", ssl}}); // fetch single site with single redirects testFetchList(good, {{"/redirect_once/301", "", ssl}}); testFetchList(good, {{"/redirect_once/302", "", ssl}}); testFetchList(good, {{"/redirect_once/307", "", ssl}}); testFetchList(good, {{"/redirect_once/308", "", ssl}}); // one redirect, one not - testFetchList( - good, - {{"/validators", "", ssl}, {"/redirect_once/302", "", ssl}}); - testFetchList( - good, - {{"/validators2", "", ssl}, {"/redirect_once/302", "", ssl}}); + testFetchList(good, {{"/validators", "", ssl}, {"/redirect_once/302", "", ssl}}); + testFetchList(good, {{"/validators2", "", ssl}, {"/redirect_once/302", "", ssl}}); // UNLs with a "gap" between validUntil of one and validFrom of the // next testFetchList( - good, - {{"/validators2", - "", - ssl, - false, - false, - 1, - detail::default_expires, - std::chrono::seconds{-90}}}); + good, {{"/validators2", "", ssl, false, false, 1, detail::default_expires, std::chrono::seconds{-90}}}); // fetch single site with unending redirect (fails to load) - testFetchList( - good, - {{"/redirect_forever/301", - "Exceeded max redirects", - ssl, - true, - true}}); + testFetchList(good, {{"/redirect_forever/301", "Exceeded max redirects", ssl, true, true}}); // two that redirect forever testFetchList( good, - {{"/redirect_forever/307", - "Exceeded max redirects", - ssl, - true, - true}, - {"/redirect_forever/308", - "Exceeded max redirects", - ssl, - true, - true}}); + {{"/redirect_forever/307", "Exceeded max redirects", ssl, true, true}, + {"/redirect_forever/308", "Exceeded max redirects", ssl, true, true}}); + // one unending redirect, one not + testFetchList( + good, {{"/validators", "", ssl}, {"/redirect_forever/302", "Exceeded max redirects", ssl, true, true}}); // one unending redirect, one not testFetchList( good, - {{"/validators", "", ssl}, - {"/redirect_forever/302", - "Exceeded max redirects", - ssl, - true, - true}}); - // one unending redirect, one not - testFetchList( - good, - {{"/validators2", "", ssl}, - {"/redirect_forever/302", - "Exceeded max redirects", - ssl, - true, - true}}); + {{"/validators2", "", ssl}, {"/redirect_forever/302", "Exceeded max redirects", ssl, true, true}}); // invalid redir Location + testFetchList(good, {{"/redirect_to/ftp://invalid-url/302", "Invalid redirect location", ssl, true, true}}); testFetchList( - good, - {{"/redirect_to/ftp://invalid-url/302", - "Invalid redirect location", - ssl, - true, - true}}); - testFetchList( - good, - {{"/redirect_to/file://invalid-url/302", - "Invalid redirect location", - ssl, - true, - true}}); + good, {{"/redirect_to/file://invalid-url/302", "Invalid redirect location", ssl, true, true}}); // invalid json - testFetchList( - good, - {{"/validators/bad", - "Unable to parse JSON response", - ssl, - true, - true}}); - testFetchList( - good, - {{"/validators2/bad", - "Unable to parse JSON response", - ssl, - true, - true}}); + testFetchList(good, {{"/validators/bad", "Unable to parse JSON response", ssl, true, true}}); + testFetchList(good, {{"/validators2/bad", "Unable to parse JSON response", ssl, true, true}}); // error status returned - testFetchList( - good, - {{"/bad-resource", "returned bad status", ssl, true, true}}); + testFetchList(good, {{"/bad-resource", "returned bad status", ssl, true, true}}); // location field missing - testFetchList( - good, - {{"/redirect_nolo/308", - "returned a redirect with no Location", - ssl, - true, - true}}); + testFetchList(good, {{"/redirect_nolo/308", "returned a redirect with no Location", ssl, true, true}}); // json fields missing - testFetchList( - good, - {{"/validators/missing", - "Missing fields in JSON response", - ssl, - true, - true}}); - testFetchList( - good, - {{"/validators2/missing", - "Missing fields in JSON response", - ssl, - true, - true}}); + testFetchList(good, {{"/validators/missing", "Missing fields in JSON response", ssl, true, true}}); + testFetchList(good, {{"/validators2/missing", "Missing fields in JSON response", ssl, true, true}}); // timeout - testFetchList( - good, {{"/sleep/13", "took too long", ssl, true, true}}); + testFetchList(good, {{"/sleep/13", "took too long", ssl, true, true}}); // bad manifest format using known versions // * Retrieves a v1 formatted list claiming version 2 - testFetchList( - good, {{"/validators", "Missing fields", ssl, true, true, 2}}); + testFetchList(good, {{"/validators", "Missing fields", ssl, true, true, 2}}); // * Retrieves a v2 formatted list claiming version 1 - testFetchList( - good, {{"/validators2", "Missing fields", ssl, true, true, 0}}); + testFetchList(good, {{"/validators2", "Missing fields", ssl, true, true, 0}}); // bad manifest version // Because versions other than 1 are treated as v2, the v1 // list won't have the blobs_v2 fields, and thus will claim to have // missing fields - testFetchList( - good, {{"/validators", "Missing fields", ssl, true, true, 4}}); - testFetchList( - good, - {{"/validators2", - "1 unsupported version", - ssl, - false, - true, - 4}}); + testFetchList(good, {{"/validators", "Missing fields", ssl, true, true, 4}}); + testFetchList(good, {{"/validators2", "1 unsupported version", ssl, false, true, 4}}); using namespace std::chrono_literals; // get expired validator list + testFetchList(good, {{"/validators", "Applied 1 expired validator list(s)", ssl, false, false, 1, 0s}}); testFetchList( - good, - {{"/validators", - "Applied 1 expired validator list(s)", - ssl, - false, - false, - 1, - 0s}}); - testFetchList( - good, - {{"/validators2", - "Applied 1 expired validator list(s)", - ssl, - false, - false, - 1, - 0s, - -1s}}); + good, {{"/validators2", "Applied 1 expired validator list(s)", ssl, false, false, 1, 0s, -1s}}); // force an out-of-range validUntil value testFetchList( good, @@ -578,27 +427,13 @@ public: // returns the "best" result, so this looks like a success. testFetchList( good, - {{"/validators2", - "", - ssl, - false, - false, - 1, - std::chrono::seconds{Json::Value::maxInt - 300}, - 299s}}); + {{"/validators2", "", ssl, false, false, 1, std::chrono::seconds{Json::Value::maxInt - 300}, 299s}}); // force an out-of-range validFrom value // The first list is accepted. The second fails. The parser // returns the "best" result, so this looks like a success. testFetchList( good, - {{"/validators2", - "", - ssl, - false, - false, - 1, - std::chrono::seconds{Json::Value::maxInt - 300}, - 301s}}); + {{"/validators2", "", ssl, false, false, 1, std::chrono::seconds{Json::Value::maxInt - 300}, 301s}}); // force an out-of-range validUntil value on _both_ lists testFetchList( good, diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index d8bfa71d46..e39f665711 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -35,8 +35,7 @@ class Vault_test : public beast::unit_test::suite using PrettyAsset = xrpl::test::jtx::PrettyAsset; using PrettyAmount = xrpl::test::jtx::PrettyAmount; - static auto constexpr negativeAmount = - [](PrettyAsset const& asset) -> PrettyAmount { + static auto constexpr negativeAmount = [](PrettyAsset const& asset) -> PrettyAmount { return {STAmount{asset.raw(), 1ul, 0, true, STAmount::unchecked{}}, ""}; }; @@ -51,10 +50,7 @@ class Vault_test : public beast::unit_test::suite Account dave{"dave"}; auto const testSequence = [&, this]( - std::string const& prefix, - Env& env, - Vault& vault, - PrettyAsset const& asset) { + std::string const& prefix, Env& env, Vault& vault, PrettyAsset const& asset) { auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); tx[sfData] = "AFEED00E"; tx[sfAssetsMaximum] = asset(100).number(); @@ -64,26 +60,20 @@ class Vault_test : public beast::unit_test::suite std::uint64_t const scale = asset.raw().holds() ? 1 : 1e6; auto const [share, vaultAccount] = - [&env, - keylet = keylet, - asset, - this]() -> std::tuple { + [&env, keylet = keylet, asset, this]() -> std::tuple { auto const vault = env.le(keylet); BEAST_EXPECT(vault != nullptr); if (!asset.integral()) BEAST_EXPECT(vault->at(sfScale) == 6); else BEAST_EXPECT(vault->at(sfScale) == 0); - auto const shares = - env.le(keylet::mptIssuance(vault->at(sfShareMPTID))); + auto const shares = env.le(keylet::mptIssuance(vault->at(sfShareMPTID))); BEAST_EXPECT(shares != nullptr); if (!asset.integral()) BEAST_EXPECT(shares->at(sfAssetScale) == 6); else BEAST_EXPECT(shares->at(sfAssetScale) == 0); - return { - MPTIssue(vault->at(sfShareMPTID)), - Account("vault", vault->at(sfAccount))}; + return {MPTIssue(vault->at(sfShareMPTID)), Account("vault", vault->at(sfAccount))}; }(); auto const shares = share.raw().get(); env.memoize(vaultAccount); @@ -97,36 +87,25 @@ class Vault_test : public beast::unit_test::suite { testcase(prefix + " fail to deposit more than assets held"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(10000)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(10000)}); env(tx, ter(tecINSUFFICIENT_FUNDS)); env.close(); } { testcase(prefix + " deposit non-zero amount"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(depositor, shares) == share(50 * scale)); + BEAST_EXPECT(env.balance(depositor, shares) == share(50 * scale)); } { testcase(prefix + " deposit non-zero amount again"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(depositor, shares) == share(100 * scale)); + BEAST_EXPECT(env.balance(depositor, shares) == share(100 * scale)); } { @@ -145,8 +124,7 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - prefix + " fail to set maximum lower than current amount"); + testcase(prefix + " fail to set maximum lower than current amount"); auto tx = vault.set({.owner = owner, .id = keylet.key}); tx[sfAssetsMaximum] = asset(50).number(); env(tx, ter(tecLIMIT_EXCEEDED)); @@ -187,10 +165,7 @@ class Vault_test : public beast::unit_test::suite { testcase(prefix + " fail to deposit more than maximum"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter(tecLIMIT_EXCEEDED)); env.close(); } @@ -205,50 +180,36 @@ class Vault_test : public beast::unit_test::suite { testcase(prefix + " fail to withdraw more than assets held"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1000)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(1000)}); env(tx, ter(tecINSUFFICIENT_FUNDS)); env.close(); } { testcase(prefix + " deposit some more"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(depositor, shares) == share(200 * scale)); + BEAST_EXPECT(env.balance(depositor, shares) == share(200 * scale)); } { testcase(prefix + " clawback some"); - auto code = - asset.raw().native() ? ter(temMALFORMED) : ter(tesSUCCESS); - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(10)}); + auto code = asset.raw().native() ? ter(temMALFORMED) : ter(tesSUCCESS); + auto tx = + vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(10)}); env(tx, code); env.close(); if (!asset.raw().native()) { - BEAST_EXPECT( - env.balance(depositor, shares) == share(190 * scale)); + BEAST_EXPECT(env.balance(depositor, shares) == share(190 * scale)); } } { testcase(prefix + " clawback all"); - auto code = asset.raw().native() ? ter(tecNO_PERMISSION) - : ter(tesSUCCESS); - auto tx = vault.clawback( - {.issuer = issuer, .id = keylet.key, .holder = depositor}); + auto code = asset.raw().native() ? ter(tecNO_PERMISSION) : ter(tesSUCCESS); + auto tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor}); env(tx, code); env.close(); if (!asset.raw().native()) @@ -257,19 +218,13 @@ class Vault_test : public beast::unit_test::suite { auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(10)}); + {.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(10)}); env(tx, ter{tecPRECISION_LOSS}); env.close(); } { - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(10)}); env(tx, ter{tecPRECISION_LOSS}); env.close(); } @@ -279,72 +234,46 @@ class Vault_test : public beast::unit_test::suite if (!asset.raw().native()) { testcase(prefix + " deposit again"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(200)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(200)}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(depositor, shares) == share(200 * scale)); + BEAST_EXPECT(env.balance(depositor, shares) == share(200 * scale)); } else { testcase(prefix + " deposit/withdrawal same or less than fee"); auto const amount = env.current()->fees().base; - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = amount}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = amount}); env(tx); env.close(); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = amount}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = amount}); env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = amount}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = amount}); env(tx); env.close(); // Withdraw to 3rd party - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = amount}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = amount}); tx[sfDestination] = charlie.human(); env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = amount - 1}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = amount - 1}); env(tx); env.close(); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = amount - 1}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = amount - 1}); env(tx); env.close(); } { - testcase( - prefix + " fail to withdraw to 3rd party lsfDepositAuth"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + testcase(prefix + " fail to withdraw to 3rd party lsfDepositAuth"); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); tx[sfDestination] = alice.human(); env(tx, ter{tecNO_PERMISSION}); env.close(); @@ -352,10 +281,7 @@ class Vault_test : public beast::unit_test::suite { testcase(prefix + " fail to withdraw to zero destination"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1000)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(1000)}); tx[sfDestination] = "0"; env(tx, ter(temMALFORMED)); env.close(); @@ -363,26 +289,16 @@ class Vault_test : public beast::unit_test::suite if (!asset.raw().native()) { - testcase( - prefix + " fail to withdraw to 3rd party no authorization"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + testcase(prefix + " fail to withdraw to 3rd party no authorization"); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); tx[sfDestination] = erin.human(); - env(tx, - ter{asset.raw().holds() ? tecNO_LINE : tecNO_AUTH}); + env(tx, ter{asset.raw().holds() ? tecNO_LINE : tecNO_AUTH}); env.close(); } { - testcase( - prefix + - " fail to withdraw to 3rd party lsfRequireDestTag"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + testcase(prefix + " fail to withdraw to 3rd party lsfRequireDestTag"); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); tx[sfDestination] = dave.human(); env(tx, ter{tecDST_TAG_NEEDED}); env.close(); @@ -390,10 +306,7 @@ class Vault_test : public beast::unit_test::suite { testcase(prefix + " withdraw to 3rd party lsfRequireDestTag"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); tx[sfDestination] = dave.human(); tx[sfDestinationTag] = "0"; env(tx); @@ -402,24 +315,21 @@ class Vault_test : public beast::unit_test::suite { testcase(prefix + " deposit again"); - auto tx = vault.deposit( - {.depositor = dave, .id = keylet.key, .amount = asset(50)}); + auto tx = vault.deposit({.depositor = dave, .id = keylet.key, .amount = asset(50)}); env(tx); env.close(); } { testcase(prefix + " fail to withdraw lsfRequireDestTag"); - auto tx = vault.withdraw( - {.depositor = dave, .id = keylet.key, .amount = asset(50)}); + auto tx = vault.withdraw({.depositor = dave, .id = keylet.key, .amount = asset(50)}); env(tx, ter{tecDST_TAG_NEEDED}); env.close(); } { testcase(prefix + " withdraw with tag"); - auto tx = vault.withdraw( - {.depositor = dave, .id = keylet.key, .amount = asset(50)}); + auto tx = vault.withdraw({.depositor = dave, .id = keylet.key, .amount = asset(50)}); tx[sfDestinationTag] = "0"; env(tx); env.close(); @@ -427,46 +337,32 @@ class Vault_test : public beast::unit_test::suite { testcase(prefix + " withdraw to authorized 3rd party"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); tx[sfDestination] = charlie.human(); env(tx); env.close(); - BEAST_EXPECT( - env.balance(depositor, shares) == share(100 * scale)); + BEAST_EXPECT(env.balance(depositor, shares) == share(100 * scale)); } { testcase(prefix + " withdraw to issuer"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); tx[sfDestination] = issuer.human(); env(tx); env.close(); - BEAST_EXPECT( - env.balance(depositor, shares) == share(50 * scale)); + BEAST_EXPECT(env.balance(depositor, shares) == share(50 * scale)); } if (!asset.raw().native()) { testcase(prefix + " issuer deposits"); - auto tx = vault.deposit( - {.depositor = issuer, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.deposit({.depositor = issuer, .id = keylet.key, .amount = asset(10)}); env(tx); env.close(); BEAST_EXPECT(env.balance(issuer, shares) == share(10 * scale)); testcase(prefix + " issuer withdraws"); - tx = vault.withdraw( - {.depositor = issuer, - .id = keylet.key, - .amount = share(10 * scale)}); + tx = vault.withdraw({.depositor = issuer, .id = keylet.key, .amount = share(10 * scale)}); env(tx); env.close(); BEAST_EXPECT(env.balance(issuer, shares) == share(0 * scale)); @@ -474,30 +370,21 @@ class Vault_test : public beast::unit_test::suite { testcase(prefix + " withdraw remaining assets"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx); env.close(); BEAST_EXPECT(env.balance(depositor, shares) == share(0)); if (!asset.raw().native()) { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(0)}); + auto tx = + vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(0)}); env(tx, ter{tecPRECISION_LOSS}); env.close(); } { - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = share(10)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = share(10)}); env(tx, ter{tecINSUFFICIENT_FUNDS}); env.close(); } @@ -511,8 +398,7 @@ class Vault_test : public beast::unit_test::suite env(pay(issuer, erin, asset(10))); // Erin deposits all in vault, then sends shares to depositor - auto tx = vault.deposit( - {.depositor = erin, .id = keylet.key, .amount = asset(10)}); + auto tx = vault.deposit({.depositor = erin, .id = keylet.key, .amount = asset(10)}); env(tx); env.close(); { @@ -523,10 +409,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // depositor will gain MPToken for shares again - env(vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1)})); + env(vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1)})); env.close(); env(tx); @@ -535,10 +418,7 @@ class Vault_test : public beast::unit_test::suite testcase(prefix + " withdraw to authorized 3rd party"); // Depositor withdraws assets, destined to Erin - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(10)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(10)}); tx[sfDestination] = erin.human(); env(tx); env.close(); @@ -556,10 +436,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // Depositor withdraws remaining single asset - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(1)}); env(tx); env.close(); } @@ -580,9 +457,7 @@ class Vault_test : public beast::unit_test::suite } }; - auto testCases = [&, this]( - std::string prefix, - std::function setup) { + auto testCases = [&, this](std::string prefix, std::function setup) { Env env{*this, testable_amendments() | featureSingleAssetVault}; Vault vault{env}; @@ -599,9 +474,7 @@ class Vault_test : public beast::unit_test::suite testSequence(prefix, env, vault, asset); }; - testCases("XRP", [&](Env& env) -> PrettyAsset { - return {xrpIssue(), 1'000'000}; - }); + testCases("XRP", [&](Env& env) -> PrettyAsset { return {xrpIssue(), 1'000'000}; }); testCases("IOU", [&](Env& env) -> Asset { PrettyAsset asset = issuer["IOU"]; @@ -620,8 +493,7 @@ class Vault_test : public beast::unit_test::suite testCases("MPT", [&](Env& env) -> Asset { MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); PrettyAsset asset = mptt.issuanceID(); mptt.authorize({.account = depositor}); mptt.authorize({.account = charlie}); @@ -639,49 +511,40 @@ class Vault_test : public beast::unit_test::suite struct CaseArgs { - FeatureBitset features = - testable_amendments() | featureSingleAssetVault; + FeatureBitset features = testable_amendments() | featureSingleAssetVault; }; - auto testCase = [&, this]( - std::function test, - CaseArgs args = {}) { - Env env{*this, args.features}; - Account issuer{"issuer"}; - Account owner{"owner"}; - Vault vault{env}; - env.fund(XRP(1000), issuer, owner); - env.close(); + auto testCase = + [&, this]( + std::function test, + CaseArgs args = {}) { + Env env{*this, args.features}; + Account issuer{"issuer"}; + Account owner{"owner"}; + Vault vault{env}; + env.fund(XRP(1000), issuer, owner); + env.close(); - env(fset(issuer, asfAllowTrustLineClawback)); - env(fset(issuer, asfRequireAuth)); - env.close(); + env(fset(issuer, asfAllowTrustLineClawback)); + env(fset(issuer, asfRequireAuth)); + env.close(); - PrettyAsset asset = issuer["IOU"]; - env(trust(owner, asset(1000))); - env(trust(issuer, asset(0), owner, tfSetfAuth)); - env(pay(issuer, owner, asset(1000))); - env.close(); + PrettyAsset asset = issuer["IOU"]; + env(trust(owner, asset(1000))); + env(trust(issuer, asset(0), owner, tfSetfAuth)); + env(pay(issuer, owner, asset(1000))); + env.close(); - test(env, issuer, owner, asset, vault); - }; + test(env, issuer, owner, asset, vault); + }; auto testDisabled = [&](TER resultAfterCreate = temDISABLED) { return [&, resultAfterCreate]( - Env& env, - Account const& issuer, - Account const& owner, - Asset const& asset, - Vault& vault) { + Env& env, Account const& issuer, Account const& owner, Asset const& asset, Vault& vault) { testcase("disabled single asset vault"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx, ter{temDISABLED}); { @@ -690,27 +553,18 @@ class Vault_test : public beast::unit_test::suite } { - auto tx = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(10)}); env(tx, ter{resultAfterCreate}); } { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); env(tx, ter{resultAfterCreate}); } { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(10)}); + auto tx = + vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(10)}); env(tx, ter{resultAfterCreate}); } @@ -721,24 +575,15 @@ class Vault_test : public beast::unit_test::suite }; }; - testCase( - testDisabled(), - {.features = testable_amendments() - featureSingleAssetVault}); + testCase(testDisabled(), {.features = testable_amendments() - featureSingleAssetVault}); + + testCase(testDisabled(tecNO_ENTRY), {.features = testable_amendments() - featureMPTokensV1}); testCase( - testDisabled(tecNO_ENTRY), - {.features = testable_amendments() - featureMPTokensV1}); - - testCase( - [&](Env& env, - Account const& issuer, - Account const& owner, - Asset const& asset, - Vault& vault) { + [&](Env& env, Account const& issuer, Account const& owner, Asset const& asset, Vault& vault) { testcase("disabled permissioned domains"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); tx[sfFlags] = tx[sfFlags].asUInt() | tfVaultPrivate; @@ -755,11 +600,7 @@ class Vault_test : public beast::unit_test::suite }, {.features = testable_amendments() - featurePermissionedDomains}); - testCase([&](Env& env, - Account const& issuer, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const& issuer, Account const& owner, Asset const& asset, Vault& vault) { testcase("invalid flags"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -773,29 +614,19 @@ class Vault_test : public beast::unit_test::suite } { - auto tx = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(10)}); tx[sfFlags] = tfClearDeepFreeze; env(tx, ter{temINVALID_FLAG}); } { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); tx[sfFlags] = tfClearDeepFreeze; env(tx, ter{temINVALID_FLAG}); } { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(10)}); + auto tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(10)}); tx[sfFlags] = tfClearDeepFreeze; env(tx, ter{temINVALID_FLAG}); } @@ -807,11 +638,7 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const& issuer, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const& issuer, Account const& owner, Asset const& asset, Vault& vault) { testcase("invalid fee"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -825,29 +652,19 @@ class Vault_test : public beast::unit_test::suite } { - auto tx = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(10)}); tx[jss::Fee] = "-1"; env(tx, ter{temBAD_FEE}); } { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); tx[jss::Fee] = "-1"; env(tx, ter{temBAD_FEE}); } { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(10)}); + auto tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(10)}); tx[jss::Fee] = "-1"; env(tx, ter{temBAD_FEE}); } @@ -860,15 +677,10 @@ class Vault_test : public beast::unit_test::suite }); testCase( - [&](Env& env, - Account const&, - Account const& owner, - Asset const&, - Vault& vault) { + [&](Env& env, Account const&, Account const& owner, Asset const&, Vault& vault) { testcase("disabled permissioned domain"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = xrpIssue()}); tx[sfDomainID] = to_string(base_uint<256>(42ul)); env(tx, ter{temDISABLED}); @@ -884,18 +696,12 @@ class Vault_test : public beast::unit_test::suite env(tx, ter{temDISABLED}); } }, - {.features = (testable_amendments() | featureSingleAssetVault) - - featurePermissionedDomains}); + {.features = (testable_amendments() | featureSingleAssetVault) - featurePermissionedDomains}); - testCase([&](Env& env, - Account const& issuer, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const& issuer, Account const& owner, Asset const& asset, Vault& vault) { testcase("use zero vault"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = xrpIssue()}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = xrpIssue()}); { auto tx = vault.set({ @@ -906,27 +712,17 @@ class Vault_test : public beast::unit_test::suite } { - auto tx = vault.deposit( - {.depositor = owner, - .id = beast::zero, - .amount = asset(10)}); + auto tx = vault.deposit({.depositor = owner, .id = beast::zero, .amount = asset(10)}); env(tx, ter(temMALFORMED)); } { - auto tx = vault.withdraw( - {.depositor = owner, - .id = beast::zero, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = beast::zero, .amount = asset(10)}); env(tx, ter{temMALFORMED}); } { - auto tx = vault.clawback( - {.issuer = issuer, - .id = beast::zero, - .holder = owner, - .amount = asset(10)}); + auto tx = vault.clawback({.issuer = issuer, .id = beast::zero, .holder = owner, .amount = asset(10)}); env(tx, ter{temMALFORMED}); } @@ -939,50 +735,36 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("withdraw to bad destination"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); tx[jss::Destination] = "0"; env(tx, ter{temMALFORMED}); } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("create with Scale"); { - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); tx[sfScale] = 255; env(tx, ter(temMALFORMED)); } { - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); tx[sfScale] = 19; env(tx, ter(temMALFORMED)); } // accepted range from 0 to 18 { - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); tx[sfScale] = 18; env(tx); env.close(); @@ -992,8 +774,7 @@ class Vault_test : public beast::unit_test::suite } { - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); tx[sfScale] = 0; env(tx); env.close(); @@ -1003,8 +784,7 @@ class Vault_test : public beast::unit_test::suite } { - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); auto const sleVault = env.le(keylet); @@ -1013,11 +793,7 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("create or set invalid data"); auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -1049,11 +825,7 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("set nothing updated"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -1064,11 +836,7 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("create with invalid metadata"); auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -1088,11 +856,7 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("set negative maximum"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -1104,35 +868,23 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("invalid deposit amount"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); { - auto tx = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = negativeAmount(asset)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = negativeAmount(asset)}); env(tx, ter(temBAD_AMOUNT)); } { - auto tx = vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(0)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(0)}); env(tx, ter(temBAD_AMOUNT)); } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("invalid set immutable flag"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -1144,35 +896,23 @@ class Vault_test : public beast::unit_test::suite } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("invalid withdraw amount"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = negativeAmount(asset)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = negativeAmount(asset)}); env(tx, ter(temBAD_AMOUNT)); } { - auto tx = vault.withdraw( - {.depositor = owner, .id = keylet.key, .amount = asset(0)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(0)}); env(tx, ter(temBAD_AMOUNT)); } }); - testCase([&](Env& env, - Account const& issuer, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const& issuer, Account const& owner, Asset const& asset, Vault& vault) { testcase("invalid clawback"); auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -1180,29 +920,18 @@ class Vault_test : public beast::unit_test::suite // Preclaim only checks for native assets. if (asset.native()) { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(50)}); + auto tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(50)}); env(tx, ter(temMALFORMED)); } { auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = negativeAmount(asset)}); + {.issuer = issuer, .id = keylet.key, .holder = owner, .amount = negativeAmount(asset)}); env(tx, ter(temBAD_AMOUNT)); } }); - testCase([&](Env& env, - Account const&, - Account const& owner, - Asset const& asset, - Vault& vault) { + testCase([&](Env& env, Account const&, Account const& owner, Asset const& asset, Vault& vault) { testcase("invalid create"); auto [tx1, keylet] = vault.create({.owner = owner, .asset = asset}); @@ -1280,10 +1009,7 @@ class Vault_test : public beast::unit_test::suite PrettyAsset const& asset, Vault& vault) { testcase("nothing to deposit to"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet::skip().key, - .amount = asset(10)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet::skip().key, .amount = asset(10)}); env(tx, ter(tecNO_ENTRY)); }); @@ -1295,10 +1021,7 @@ class Vault_test : public beast::unit_test::suite PrettyAsset const& asset, Vault& vault) { testcase("nothing to withdraw from"); - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet::skip().key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet::skip().key, .amount = asset(10)}); env(tx, ter(tecNO_ENTRY)); }); @@ -1415,10 +1138,7 @@ class Vault_test : public beast::unit_test::suite { { testcase("IOU fail because MPT is disabled"); - Env env{ - *this, - (testable_amendments() - featureMPTokensV1) | - featureSingleAssetVault}; + Env env{*this, (testable_amendments() - featureMPTokensV1) | featureSingleAssetVault}; Account issuer{"issuer"}; Account owner{"owner"}; env.fund(XRP(1000), issuer, owner); @@ -1426,8 +1146,7 @@ class Vault_test : public beast::unit_test::suite Vault vault{env}; Asset asset = issuer["IOU"].asset(); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx, ter(temDISABLED)); env.close(); @@ -1445,8 +1164,7 @@ class Vault_test : public beast::unit_test::suite Vault vault{env}; Asset asset = issuer["IOU"].asset(); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx, ter(tecFROZEN)); env.close(); @@ -1464,8 +1182,7 @@ class Vault_test : public beast::unit_test::suite Vault vault{env}; Asset asset = issuer["IOU"].asset(); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx, ter(terNO_RIPPLE)); env.close(); } @@ -1481,8 +1198,7 @@ class Vault_test : public beast::unit_test::suite Vault vault{env}; Asset asset = issuer["IOU"].asset(); { - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx, ter(terNO_ACCOUNT)); env.close(); } @@ -1497,8 +1213,7 @@ class Vault_test : public beast::unit_test::suite Account const carol("carol"); IOU const USD = gw["USD"]; - auto const [asset1, asset2] = - std::pair(XRP(10000), USD(10000)); + auto const [asset1, asset2] = std::pair(XRP(10000), USD(10000)); auto toFund = [&](STAmount const& a) -> STAmount { if (a.native()) { @@ -1523,15 +1238,13 @@ class Vault_test : public beast::unit_test::suite else if (asset2.native()) fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All); - AMM ammAlice( - env, alice, asset1, asset2, CreateArg{.log = false, .tfee = 0}); + AMM ammAlice(env, alice, asset1, asset2, CreateArg{.log = false, .tfee = 0}); Account const owner{"owner"}; env.fund(XRP(1000000), owner); Vault vault{env}; - auto [tx, k] = - vault.create({.owner = owner, .asset = ammAlice.lptIssue()}); + auto [tx, k] = vault.create({.owner = owner, .asset = ammAlice.lptIssue()}); env(tx, ter{tecWRONG_ASSET}); env.close(); } @@ -1630,14 +1343,10 @@ class Vault_test : public beast::unit_test::suite { testcase("nontransferable deposits"); - auto tx1 = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(40)}); + auto tx1 = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(40)}); env(tx1); - auto tx2 = vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(60)}); + auto tx2 = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(60)}); env(tx2); env.close(); } @@ -1646,17 +1355,11 @@ class Vault_test : public beast::unit_test::suite [&env, key = keylet.key, this]() -> AccountID { auto jvVault = env.rpc("vault_info", strHex(key)); - BEAST_EXPECT( - jvVault[jss::result][jss::vault][sfAssetsTotal] == "100"); - BEAST_EXPECT( - jvVault[jss::result][jss::vault][jss::shares] - [sfOutstandingAmount] == "100000000"); + BEAST_EXPECT(jvVault[jss::result][jss::vault][sfAssetsTotal] == "100"); + BEAST_EXPECT(jvVault[jss::result][jss::vault][jss::shares][sfOutstandingAmount] == "100000000"); // Vault pseudo-account - return parseBase58( - jvVault[jss::result][jss::vault][jss::Account] - .asString()) - .value(); + return parseBase58(jvVault[jss::result][jss::vault][jss::Account].asString()).value(); }(); auto const MptID = makeMptID(1, vaultAccount); @@ -1670,14 +1373,10 @@ class Vault_test : public beast::unit_test::suite { testcase("nontransferable shares can be used to withdraw"); - auto tx1 = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(20)}); + auto tx1 = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(20)}); env(tx1); - auto tx2 = vault.withdraw( - {.depositor = owner, .id = keylet.key, .amount = asset(30)}); + auto tx2 = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(30)}); env(tx2); env.close(); } @@ -1685,23 +1384,16 @@ class Vault_test : public beast::unit_test::suite { testcase("nontransferable shares balance check"); auto jvVault = env.rpc("vault_info", strHex(keylet.key)); - BEAST_EXPECT( - jvVault[jss::result][jss::vault][sfAssetsTotal] == "50"); - BEAST_EXPECT( - jvVault[jss::result][jss::vault][jss::shares] - [sfOutstandingAmount] == "50000000"); + BEAST_EXPECT(jvVault[jss::result][jss::vault][sfAssetsTotal] == "50"); + BEAST_EXPECT(jvVault[jss::result][jss::vault][jss::shares][sfOutstandingAmount] == "50000000"); } { testcase("nontransferable shares withdraw rest"); - auto tx1 = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(20)}); + auto tx1 = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(20)}); env(tx1); - auto tx2 = vault.withdraw( - {.depositor = owner, .id = keylet.key, .amount = asset(30)}); + auto tx2 = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(30)}); env(tx2); env.close(); } @@ -1747,8 +1439,7 @@ class Vault_test : public beast::unit_test::suite MPTTester mptt{env, issuer, mptInitNoFund}; auto const none = LedgerSpecificFlags(0); mptt.create( - {.flags = tfMPTCanTransfer | tfMPTCanLock | - (args.enableClawback ? tfMPTCanClawback : none) | + {.flags = tfMPTCanTransfer | tfMPTCanLock | (args.enableClawback ? tfMPTCanClawback : none) | (args.requireAuth ? tfMPTRequireAuth : none), .mutableFlags = tmfMPTCanMutateCanTransfer}); PrettyAsset asset = mptt.issuanceID(); @@ -1775,11 +1466,8 @@ class Vault_test : public beast::unit_test::suite Vault& vault, MPTTester& mptt) { testcase("MPT nothing to clawback from"); - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet::skip().key, - .holder = depositor, - .amount = asset(10)}); + auto tx = + vault.clawback({.issuer = issuer, .id = keylet::skip().key, .holder = depositor, .amount = asset(10)}); env(tx, ter(tecNO_ENTRY)); }); @@ -1813,10 +1501,7 @@ class Vault_test : public beast::unit_test::suite mptt.set({.account = issuer, .flags = tfMPTLock}); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter{tecLOCKED}); env.close(); @@ -1837,10 +1522,7 @@ class Vault_test : public beast::unit_test::suite auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx); env.close(); @@ -1857,21 +1539,14 @@ class Vault_test : public beast::unit_test::suite mptt.set({.account = issuer, .flags = tfMPTLock}); env.close(); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter(tecLOCKED)); tx[sfDestination] = issuer.human(); env(tx, ter(tecLOCKED)); // Clawback is still permitted, even with global lock - tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(0)}); + tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(0)}); env(tx); env.close(); @@ -1898,10 +1573,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx); env.close(); @@ -1935,33 +1607,24 @@ class Vault_test : public beast::unit_test::suite MPTTester& mptt) { testcase("MPT depositor without MPToken, auth required"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1000)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1000)}); env(tx); env.close(); { // Remove depositor MPToken and it will not be re-created - mptt.authorize( - {.account = depositor, .flags = tfMPTUnauthorize}); + mptt.authorize({.account = depositor, .flags = tfMPTUnauthorize}); env.close(); - auto const mptoken = - keylet::mptoken(mptt.issuanceID(), depositor); + auto const mptoken = keylet::mptoken(mptt.issuanceID(), depositor); auto const sleMPT1 = env.le(mptoken); BEAST_EXPECT(sleMPT1 == nullptr); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter{tecNO_AUTH}); env.close(); @@ -1975,10 +1638,7 @@ class Vault_test : public beast::unit_test::suite env.fund(XRP(1000), charlie); env.close(); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); tx[sfDestination] = charlie.human(); env(tx, ter(tecNO_AUTH)); } @@ -1996,35 +1656,27 @@ class Vault_test : public beast::unit_test::suite MPTTester& mptt) { testcase("MPT depositor without MPToken, no auth required"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); auto v = env.le(keylet); BEAST_EXPECT(v); tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1000)}); // all assets held by depositor + {.depositor = depositor, .id = keylet.key, .amount = asset(1000)}); // all assets held by depositor env(tx); env.close(); { // Remove depositor's MPToken and it will be re-created - mptt.authorize( - {.account = depositor, .flags = tfMPTUnauthorize}); + mptt.authorize({.account = depositor, .flags = tfMPTUnauthorize}); env.close(); - auto const mptoken = - keylet::mptoken(mptt.issuanceID(), depositor); + auto const mptoken = keylet::mptoken(mptt.issuanceID(), depositor); auto const sleMPT1 = env.le(mptoken); BEAST_EXPECT(sleMPT1 == nullptr); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx); env.close(); @@ -2035,19 +1687,14 @@ class Vault_test : public beast::unit_test::suite { // Remove 3rd party MPToken and it will not be re-created - mptt.authorize( - {.account = owner, .flags = tfMPTUnauthorize}); + mptt.authorize({.account = owner, .flags = tfMPTUnauthorize}); env.close(); - auto const mptoken = - keylet::mptoken(mptt.issuanceID(), owner); + auto const mptoken = keylet::mptoken(mptt.issuanceID(), owner); auto const sleMPT1 = env.le(mptoken); BEAST_EXPECT(sleMPT1 == nullptr); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); tx[sfDestination] = owner.human(); env(tx, ter(tecNO_AUTH)); env.close(); @@ -2061,10 +1708,8 @@ class Vault_test : public beast::unit_test::suite auto const [acctReserve, incReserve] = [this]() -> std::pair { Env env{*this, testable_amendments()}; return { - env.current()->fees().accountReserve(0).drops() / - DROPS_PER_XRP.drops(), - env.current()->fees().increment.drops() / - DROPS_PER_XRP.drops()}; + env.current()->fees().accountReserve(0).drops() / DROPS_PER_XRP.drops(), + env.current()->fees().increment.drops() / DROPS_PER_XRP.drops()}; }(); testCase( @@ -2078,8 +1723,7 @@ class Vault_test : public beast::unit_test::suite MPTTester& mptt) { testcase("MPT fail reserve to re-create MPToken"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); auto v = env.le(keylet); @@ -2089,20 +1733,16 @@ class Vault_test : public beast::unit_test::suite env.close(); tx = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(1000)}); // all assets held by owner + {.depositor = owner, .id = keylet.key, .amount = asset(1000)}); // all assets held by owner env(tx); env.close(); { // Remove owners's MPToken and it will not be re-created - mptt.authorize( - {.account = owner, .flags = tfMPTUnauthorize}); + mptt.authorize({.account = owner, .flags = tfMPTUnauthorize}); env.close(); - auto const mptoken = - keylet::mptoken(mptt.issuanceID(), owner); + auto const mptoken = keylet::mptoken(mptt.issuanceID(), owner); auto const sleMPT = env.le(mptoken); BEAST_EXPECT(sleMPT == nullptr); @@ -2111,10 +1751,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // No reserve to create MPToken for asset in VaultWithdraw - tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(100)}); env(tx, ter{tecINSUFFICIENT_RESERVE}); env.close(); @@ -2126,8 +1763,7 @@ class Vault_test : public beast::unit_test::suite env.close(); } }, - {.requireAuth = false, - .initialXRP = acctReserve + incReserve * 4 + 1}); + {.requireAuth = false, .initialXRP = acctReserve + incReserve * 4 + 1}); testCase([this]( Env& env, @@ -2143,19 +1779,12 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1000)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1000)}); env(tx); env.close(); { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(0)}); + auto tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(0)}); env(tx); } @@ -2163,33 +1792,22 @@ class Vault_test : public beast::unit_test::suite env.close(); { - auto [tx, keylet] = - vault.create({.owner = depositor, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = depositor, .asset = asset}); env(tx, ter{tecOBJECT_NOT_FOUND}); } { - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(10)}); env(tx, ter{tecOBJECT_NOT_FOUND}); } { - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(10)}); env(tx, ter{tecOBJECT_NOT_FOUND}); } { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(0)}); + auto tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(0)}); env(tx, ter{tecOBJECT_NOT_FOUND}); } @@ -2210,10 +1828,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1000)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1000)}); env(tx); env.close(); @@ -2228,10 +1843,7 @@ class Vault_test : public beast::unit_test::suite env(pay(depositor, owner, shares(1))); env.close(); - tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = shares(1)}); + tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = shares(1)}); env(tx); env.close(); @@ -2239,11 +1851,7 @@ class Vault_test : public beast::unit_test::suite env(pay(depositor, owner, shares(1))); env.close(); - tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(0)}); + tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(0)}); env(tx); env.close(); @@ -2272,11 +1880,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // destroy all remaining shares, so we can delete vault - tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(0)}); + tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(0)}); env(tx); env.close(); @@ -2297,24 +1901,17 @@ class Vault_test : public beast::unit_test::suite MPTTester& mptt) { testcase("MPT clawback disabled"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1000)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1000)}); env(tx); env.close(); { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(0)}); + auto tx = + vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(0)}); env(tx, ter{tecNO_PERMISSION}); } }, @@ -2332,24 +1929,15 @@ class Vault_test : public beast::unit_test::suite auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1000)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1000)}); env(tx); env.close(); - mptt.authorize( - {.account = issuer, - .holder = depositor, - .flags = tfMPTUnauthorize}); + mptt.authorize({.account = issuer, .holder = depositor, .flags = tfMPTUnauthorize}); env.close(); { - auto tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + auto tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter(tecNO_AUTH)); // Withdrawal to other (authorized) accounts works @@ -2364,28 +1952,17 @@ class Vault_test : public beast::unit_test::suite { // Cannot deposit some more - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter(tecNO_AUTH)); } { // Cannot clawback if issuer is the holder - tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = issuer, - .amount = asset(800)}); + tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = issuer, .amount = asset(800)}); env(tx, ter(tecNO_PERMISSION)); } // Clawback works - tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(800)}); + tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(800)}); env(tx); env.close(); @@ -2405,25 +1982,20 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - auto const vaultAccount = - [&env, keylet = keylet, this]() -> AccountID { + auto const vaultAccount = [&env, keylet = keylet, this]() -> AccountID { auto const vault = env.le(keylet); BEAST_EXPECT(vault != nullptr); return vault->at(sfAccount); }(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx); env.close(); tx = [&]() { Json::Value jv; jv[jss::Account] = issuer.human(); - jv[sfMPTokenIssuanceID] = - to_string(asset.get().getMptID()); + jv[sfMPTokenIssuanceID] = to_string(asset.get().getMptID()); jv[jss::Holder] = toBase58(vaultAccount); jv[jss::TransactionType] = jss::MPTokenIssuanceSet; jv[jss::Flags] = tfMPTLock; @@ -2432,24 +2004,14 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter(tecLOCKED)); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter(tecLOCKED)); // Clawback works, even when locked - tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(100)}); + tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(100)}); env(tx); // Can delete an empty vault even when asset is locked. @@ -2468,9 +2030,7 @@ class Vault_test : public beast::unit_test::suite Vault vault{env}; MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanTransfer | tfMPTCanLock | lsfMPTCanClawback | - tfMPTRequireAuth}); + mptt.create({.flags = tfMPTCanTransfer | tfMPTCanLock | lsfMPTCanClawback | tfMPTRequireAuth}); mptt.authorize({.account = owner}); mptt.authorize({.account = issuer, .holder = owner}); PrettyAsset asset = mptt.issuanceID(); @@ -2504,10 +2064,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx); env.close(); @@ -2518,10 +2075,7 @@ class Vault_test : public beast::unit_test::suite env(tx, ter{tecNO_AUTH}); env.close(); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(100)}); env(tx, ter{tecNO_AUTH}); env.close(); @@ -2551,65 +2105,53 @@ class Vault_test : public beast::unit_test::suite bool charlieRipple = true; }; - auto testCase = - [&, this]( - std::function vaultAccount, - Vault& vault, - PrettyAsset const& asset, - std::function issuanceId)> test, - CaseArgs args = {}) { - Env env{*this, testable_amendments() | featureSingleAssetVault}; - Account const owner{"owner"}; - Account const issuer{"issuer"}; - Account const charlie{"charlie"}; - Vault vault{env}; - env.fund(XRP(args.initialXRP), issuer, owner, charlie); - env(fset(issuer, asfAllowTrustLineClawback)); - env.close(); + auto testCase = [&, this]( + std::function vaultAccount, + Vault& vault, + PrettyAsset const& asset, + std::function issuanceId)> test, + CaseArgs args = {}) { + Env env{*this, testable_amendments() | featureSingleAssetVault}; + Account const owner{"owner"}; + Account const issuer{"issuer"}; + Account const charlie{"charlie"}; + Vault vault{env}; + env.fund(XRP(args.initialXRP), issuer, owner, charlie); + env(fset(issuer, asfAllowTrustLineClawback)); + env.close(); - PrettyAsset const asset = issuer["IOU"]; - env.trust(asset(1000), owner); - env(pay(issuer, owner, asset(args.initialIOU))); + PrettyAsset const asset = issuer["IOU"]; + env.trust(asset(1000), owner); + env(pay(issuer, owner, asset(args.initialIOU))); + env.close(); + if (!args.charlieRipple) + { + env(fset(issuer, 0, asfDefaultRipple)); env.close(); - if (!args.charlieRipple) - { - env(fset(issuer, 0, asfDefaultRipple)); - env.close(); - env.trust(asset(1000), charlie); - env.close(); - env(pay(issuer, charlie, asset(args.initialIOU))); - env.close(); - env(fset(issuer, asfDefaultRipple)); - } - else - env.trust(asset(1000), charlie); + env.trust(asset(1000), charlie); env.close(); - env(rate(issuer, args.transferRate)); + env(pay(issuer, charlie, asset(args.initialIOU))); env.close(); + env(fset(issuer, asfDefaultRipple)); + } + else + env.trust(asset(1000), charlie); + env.close(); + env(rate(issuer, args.transferRate)); + env.close(); - auto const vaultAccount = - [&env](xrpl::Keylet keylet) -> Account { - return Account("vault", env.le(keylet)->at(sfAccount)); - }; - auto const issuanceId = [&env](xrpl::Keylet keylet) -> MPTID { - return env.le(keylet)->at(sfShareMPTID); - }; - - test( - env, - owner, - issuer, - charlie, - vaultAccount, - vault, - asset, - issuanceId); + auto const vaultAccount = [&env](xrpl::Keylet keylet) -> Account { + return Account("vault", env.le(keylet)->at(sfAccount)); }; + auto const issuanceId = [&env](xrpl::Keylet keylet) -> MPTID { return env.le(keylet)->at(sfShareMPTID); }; + + test(env, owner, issuer, charlie, vaultAccount, vault, asset, issuanceId); + }; testCase([&, this]( Env& env, @@ -2633,8 +2175,7 @@ class Vault_test : public beast::unit_test::suite Json::Value jv; jv[jss::Account] = issuer.human(); { - auto& ja = jv[jss::LimitAmount] = - foo(0).value().getJson(JsonOptions::none); + auto& ja = jv[jss::LimitAmount] = foo(0).value().getJson(JsonOptions::none); ja[jss::issuer] = toBase58(account); } jv[jss::TransactionType] = jss::TrustSet; @@ -2646,15 +2187,13 @@ class Vault_test : public beast::unit_test::suite } { - auto tx = vault.deposit( - {.depositor = issuer, .id = keylet.key, .amount = foo(20)}); + auto tx = vault.deposit({.depositor = issuer, .id = keylet.key, .amount = foo(20)}); env(tx, ter{tecWRONG_ASSET}); env.close(); } { - auto tx = vault.withdraw( - {.depositor = issuer, .id = keylet.key, .amount = foo(20)}); + auto tx = vault.withdraw({.depositor = issuer, .id = keylet.key, .amount = foo(20)}); env(tx, ter{tecWRONG_ASSET}); env.close(); } @@ -2678,8 +2217,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - env(vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(100)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)})); env.close(); Asset const share = Asset(issuanceId(keylet)); @@ -2689,8 +2227,7 @@ class Vault_test : public beast::unit_test::suite Json::Value jv; jv[jss::Account] = issuer.human(); { - auto& ja = jv[jss::LimitAmount] = - asset(0).value().getJson(JsonOptions::none); + auto& ja = jv[jss::LimitAmount] = asset(0).value().getJson(JsonOptions::none); ja[jss::issuer] = toBase58(account); } jv[jss::TransactionType] = jss::TrustSet; @@ -2705,18 +2242,12 @@ class Vault_test : public beast::unit_test::suite // is reported as "locked" state of the vault shares, because // this state is attached to shares by means of the transitive // isFrozen. - auto tx = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(80)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(80)}); env(tx, ter{tecLOCKED}); } { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(100)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(100)}); env(tx, ter{tecLOCKED}); // also when trying to withdraw to a 3rd party @@ -2727,11 +2258,7 @@ class Vault_test : public beast::unit_test::suite { // Clawback works, even when locked - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(50)}); + auto tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(50)}); env(tx); env.close(); } @@ -2741,10 +2268,7 @@ class Vault_test : public beast::unit_test::suite env(trustSet); env.close(); - env(vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = share(50'000'000)})); + env(vault.withdraw({.depositor = owner, .id = keylet.key, .amount = share(50'000'000)})); env(vault.del({.owner = owner, .id = keylet.key})); env.close(); @@ -2762,15 +2286,11 @@ class Vault_test : public beast::unit_test::suite auto issuanceId) { testcase("IOU transfer fees not applied"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); - env(vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(100)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)})); env.close(); auto const issue = asset.raw().get(); @@ -2778,39 +2298,27 @@ class Vault_test : public beast::unit_test::suite // transfer fees ignored on deposit BEAST_EXPECT(env.balance(owner, issue) == asset(100)); - BEAST_EXPECT( - env.balance(vaultAccount(keylet), issue) == asset(100)); + BEAST_EXPECT(env.balance(vaultAccount(keylet), issue) == asset(100)); { - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(50)}); + auto tx = + vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(50)}); env(tx); env.close(); } // transfer fees ignored on clawback BEAST_EXPECT(env.balance(owner, issue) == asset(100)); - BEAST_EXPECT( - env.balance(vaultAccount(keylet), issue) == asset(50)); + BEAST_EXPECT(env.balance(vaultAccount(keylet), issue) == asset(50)); - env(vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = share(20'000'000)})); + env(vault.withdraw({.depositor = owner, .id = keylet.key, .amount = share(20'000'000)})); // transfer fees ignored on withdraw BEAST_EXPECT(env.balance(owner, issue) == asset(120)); - BEAST_EXPECT( - env.balance(vaultAccount(keylet), issue) == asset(30)); + BEAST_EXPECT(env.balance(vaultAccount(keylet), issue) == asset(30)); { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = share(30'000'000)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = share(30'000'000)}); tx[sfDestination] = charlie.human(); env(tx); } @@ -2818,8 +2326,7 @@ class Vault_test : public beast::unit_test::suite // transfer fees ignored on withdraw to 3rd party BEAST_EXPECT(env.balance(owner, issue) == asset(120)); BEAST_EXPECT(env.balance(charlie, issue) == asset(30)); - BEAST_EXPECT( - env.balance(vaultAccount(keylet), issue) == asset(0)); + BEAST_EXPECT(env.balance(vaultAccount(keylet), issue) == asset(0)); env(vault.del({.owner = owner, .id = keylet.key})); env.close(); @@ -2841,16 +2348,12 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - env(vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(100)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)})); env.close(); // Withdraw to 3rd party works auto const withdrawToCharlie = [&](xrpl::Keylet keylet) { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); tx[sfDestination] = charlie.human(); return tx; }(keylet); @@ -2861,8 +2364,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // Cannot withdraw - auto const withdraw = vault.withdraw( - {.depositor = owner, .id = keylet.key, .amount = asset(10)}); + auto const withdraw = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); env(withdraw, ter{tecFROZEN}); // Cannot withdraw to 3rd party @@ -2871,20 +2373,13 @@ class Vault_test : public beast::unit_test::suite { // Cannot deposit some more - auto tx = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(10)}); env(tx, ter{tecFROZEN}); } { // Clawback still works - auto tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(0)}); + auto tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(0)}); env(tx); env.close(); } @@ -2908,8 +2403,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - env(vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(100)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)})); env.close(); Account const erin{"erin"}; @@ -2918,10 +2412,7 @@ class Vault_test : public beast::unit_test::suite // Withdraw to 3rd party without trust line auto const tx1 = [&](xrpl::Keylet keylet) { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); tx[sfDestination] = erin.human(); return tx; }(keylet); @@ -2947,20 +2438,15 @@ class Vault_test : public beast::unit_test::suite env.trust(asset(0), owner); env.close(); - env(vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(200)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(200)})); env.close(); - auto trustline = - env.le(keylet::line(owner, asset.raw().get())); + auto trustline = env.le(keylet::line(owner, asset.raw().get())); BEAST_EXPECT(trustline == nullptr); // Withdraw without trust line, will succeed auto const tx1 = [&](xrpl::Keylet keylet) { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); return tx; }(keylet); env(tx1); @@ -2978,41 +2464,30 @@ class Vault_test : public beast::unit_test::suite std::function issuanceId) { testcase("IOU non-transferable"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); tx[sfScale] = 0; env(tx); env.close(); // Turn on noripple on the pseudo account's trust line. // Charlie's is already set. - env(trust(issuer, vaultAccount(keylet)["IOU"], tfSetNoRipple), - THISLINE); + env(trust(issuer, vaultAccount(keylet)["IOU"], tfSetNoRipple), THISLINE); { // Charlie cannot deposit - auto tx = vault.deposit( - {.depositor = charlie, - .id = keylet.key, - .amount = asset(100)}); + auto tx = vault.deposit({.depositor = charlie, .id = keylet.key, .amount = asset(100)}); env(tx, ter{terNO_RIPPLE}, THISLINE); env.close(); } { PrettyAsset shares = issuanceId(keylet); - auto tx1 = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(100)}); + auto tx1 = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)}); env(tx1, THISLINE); env.close(); // Charlie cannot receive funds - auto tx2 = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = shares(100)}); + auto tx2 = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = shares(100)}); tx2[sfDestination] = charlie.human(); env(tx2, ter{terNO_RIPPLE}, THISLINE); env.close(); @@ -3021,8 +2496,7 @@ class Vault_test : public beast::unit_test::suite // Create MPToken for shares held by Charlie Json::Value tx{Json::objectValue}; tx[sfAccount] = charlie.human(); - tx[sfMPTokenIssuanceID] = - to_string(shares.raw().get().getMptID()); + tx[sfMPTokenIssuanceID] = to_string(shares.raw().get().getMptID()); tx[sfTransactionType] = jss::MPTokenAuthorize; env(tx); env.close(); @@ -3031,10 +2505,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // Charlie cannot withdraw - auto tx3 = vault.withdraw( - {.depositor = charlie, - .id = keylet.key, - .amount = shares(100)}); + auto tx3 = vault.withdraw({.depositor = charlie, .id = keylet.key, .amount = shares(100)}); env(tx3, ter{terNO_RIPPLE}); env.close(); @@ -3042,10 +2513,7 @@ class Vault_test : public beast::unit_test::suite env.close(); } - tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(100)}); env(tx, THISLINE); env.close(); @@ -3066,30 +2534,22 @@ class Vault_test : public beast::unit_test::suite auto&&...) { testcase("IOU calculation rounding"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); tx[sfScale] = 1; env(tx); env.close(); auto const startingOwnerBalance = env.balance(owner, asset); - BEAST_EXPECT( - (startingOwnerBalance.value() == - STAmount{asset, 11875, -2})); + BEAST_EXPECT((startingOwnerBalance.value() == STAmount{asset, 11875, -2})); // This operation (first deposit 100, then 3.75 x 5) is known to // have triggered calculation rounding errors in Number // (addition and division), causing the last deposit to be // blocked by Vault invariants. - env(vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(100)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)})); - auto const tx1 = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(Number(375, -2))}); + auto const tx1 = + vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(Number(375, -2))}); for (auto i = 0; i < 5; ++i) { env(tx1); @@ -3098,11 +2558,8 @@ class Vault_test : public beast::unit_test::suite { STAmount const xfer{asset, 1185, -1}; - BEAST_EXPECT( - env.balance(owner, asset) == - startingOwnerBalance.value() - xfer); - BEAST_EXPECT( - env.balance(vaultAccount(keylet), asset) == xfer); + BEAST_EXPECT(env.balance(owner, asset) == startingOwnerBalance.value() - xfer); + BEAST_EXPECT(env.balance(vaultAccount(keylet), asset) == xfer); auto const vault = env.le(keylet); BEAST_EXPECT(vault->at(sfAssetsAvailable) == xfer); @@ -3112,18 +2569,11 @@ class Vault_test : public beast::unit_test::suite // Total vault balance should be 118.5 IOU. Withdraw and delete // the vault to verify this exact amount was deposited and the // owner has matching shares - env(vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(Number(1000 + 37 * 5, -1))})); + env(vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(Number(1000 + 37 * 5, -1))})); { - BEAST_EXPECT( - env.balance(owner, asset) == - startingOwnerBalance.value()); - BEAST_EXPECT( - env.balance(vaultAccount(keylet), asset) == - beast::zero); + BEAST_EXPECT(env.balance(owner, asset) == startingOwnerBalance.value()); + BEAST_EXPECT(env.balance(vaultAccount(keylet), asset) == beast::zero); auto const vault = env.le(keylet); BEAST_EXPECT(vault->at(sfAssetsAvailable) == beast::zero); BEAST_EXPECT(vault->at(sfAssetsTotal) == beast::zero); @@ -3137,10 +2587,8 @@ class Vault_test : public beast::unit_test::suite auto const [acctReserve, incReserve] = [this]() -> std::pair { Env env{*this, testable_amendments()}; return { - env.current()->fees().accountReserve(0).drops() / - DROPS_PER_XRP.drops(), - env.current()->fees().increment.drops() / - DROPS_PER_XRP.drops()}; + env.current()->fees().accountReserve(0).drops() / DROPS_PER_XRP.drops(), + env.current()->fees().increment.drops() / DROPS_PER_XRP.drops()}; }(); testCase( @@ -3154,8 +2602,7 @@ class Vault_test : public beast::unit_test::suite PrettyAsset const& asset, auto&&...) { testcase("IOU no trust line to depositor no reserve"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); @@ -3164,24 +2611,17 @@ class Vault_test : public beast::unit_test::suite env.trust(asset(0), owner); env.close(); - env(vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(200)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(200)})); env.close(); - auto trustline = - env.le(keylet::line(owner, asset.raw().get())); + auto trustline = env.le(keylet::line(owner, asset.raw().get())); BEAST_EXPECT(trustline == nullptr); env(ticket::create(owner, 1)); env.close(); // Fail because not enough reserve to create trust line - tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); env(tx, ter{tecNO_LINE_INSUF_RESERVE}); env.close(); @@ -3205,8 +2645,7 @@ class Vault_test : public beast::unit_test::suite PrettyAsset const& asset, auto&&...) { testcase("IOU no reserve for share MPToken"); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = asset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); env(tx); env.close(); @@ -3217,10 +2656,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // Fail because not enough reserve to create MPToken for shares - tx = vault.deposit( - {.depositor = charlie, - .id = keylet.key, - .amount = asset(100)}); + tx = vault.deposit({.depositor = charlie, .id = keylet.key, .amount = asset(100)}); env(tx, ter{tecINSUFFICIENT_RESERVE}); env.close(); @@ -3248,16 +2684,12 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - env(vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(100)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)})); env.close(); // Withdraw to 3rd party works auto const withdrawToCharlie = [&](xrpl::Keylet keylet) { - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); tx[sfDestination] = charlie.human(); return tx; }(keylet); @@ -3268,8 +2700,7 @@ class Vault_test : public beast::unit_test::suite env.close(); // Can withdraw - auto const withdraw = vault.withdraw( - {.depositor = owner, .id = keylet.key, .amount = asset(10)}); + auto const withdraw = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); env(withdraw); env.close(); @@ -3277,11 +2708,7 @@ class Vault_test : public beast::unit_test::suite env(withdrawToCharlie, ter{tecFROZEN}); env.close(); - env(vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(0)})); + env(vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(0)})); env.close(); env(vault.del({.owner = owner, .id = keylet.key})); @@ -3303,8 +2730,7 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - env(vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(100)})); + env(vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(100)})); env.close(); env(fset(issuer, asfGlobalFreeze)); @@ -3312,10 +2738,7 @@ class Vault_test : public beast::unit_test::suite { // Cannot withdraw - auto tx = vault.withdraw( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + auto tx = vault.withdraw({.depositor = owner, .id = keylet.key, .amount = asset(10)}); env(tx, ter{tecFROZEN}); // Cannot withdraw to 3rd party @@ -3324,20 +2747,13 @@ class Vault_test : public beast::unit_test::suite env.close(); // Cannot deposit some more - tx = vault.deposit( - {.depositor = owner, - .id = keylet.key, - .amount = asset(10)}); + tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(10)}); env(tx, ter{tecFROZEN}); } // Clawback is permitted - env(vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(0)})); + env(vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(0)})); env.close(); env(vault.del({.owner = owner, .id = keylet.key})); @@ -3362,15 +2778,7 @@ class Vault_test : public beast::unit_test::suite Account credIssuer2{"credIssuer2"}; std::string const credType = "credential"; Vault vault{env}; - env.fund( - XRP(1000), - issuer, - owner, - depositor, - charlie, - pdOwner, - credIssuer1, - credIssuer2); + env.fund(XRP(1000), issuer, owner, depositor, charlie, pdOwner, credIssuer1, credIssuer2); env.close(); env(fset(issuer, asfAllowTrustLineClawback)); env.close(); @@ -3385,25 +2793,20 @@ class Vault_test : public beast::unit_test::suite env(pay(issuer, charlie, asset(5))); env.close(); - auto [tx, keylet] = vault.create( - {.owner = owner, .asset = asset, .flags = tfVaultPrivate}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset, .flags = tfVaultPrivate}); env(tx); env.close(); BEAST_EXPECT(env.le(keylet)); { testcase("private vault owner can deposit"); - auto tx = vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(50)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(50)}); env(tx); } { testcase("private vault depositor not authorized yet"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx, ter{tecNO_AUTH}); } @@ -3418,8 +2821,7 @@ class Vault_test : public beast::unit_test::suite testcase("private vault set domainId"); { - pdomain::Credentials const credentials1{ - {.issuer = credIssuer1, .credType = credType}}; + pdomain::Credentials const credentials1{{.issuer = credIssuer1, .credType = credType}}; env(pdomain::setTx(pdOwner, credentials1)); auto const domainId1 = [&]() { @@ -3439,8 +2841,7 @@ class Vault_test : public beast::unit_test::suite { pdomain::Credentials const credentials{ - {.issuer = credIssuer1, .credType = credType}, - {.issuer = credIssuer2, .credType = credType}}; + {.issuer = credIssuer1, .credType = credType}, {.issuer = credIssuer2, .credType = credType}}; env(pdomain::setTx(pdOwner, credentials)); auto const domainId = [&]() { @@ -3463,16 +2864,12 @@ class Vault_test : public beast::unit_test::suite { testcase("private vault depositor still not authorized"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx, ter{tecNO_AUTH}); env.close(); } - auto const credKeylet = - credentials::keylet(depositor, credIssuer1, credType); + auto const credKeylet = credentials::keylet(depositor, credIssuer1, credType); { testcase("private vault depositor now authorized"); env(credentials::create(depositor, credIssuer1, credType)); @@ -3483,33 +2880,24 @@ class Vault_test : public beast::unit_test::suite auto credSle = env.le(credKeylet); BEAST_EXPECT(credSle != nullptr); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx); env.close(); - tx = vault.deposit( - {.depositor = charlie, .id = keylet.key, .amount = asset(50)}); + tx = vault.deposit({.depositor = charlie, .id = keylet.key, .amount = asset(50)}); env(tx, ter{tecNO_AUTH}); env.close(); } { testcase("private vault depositor lost authorization"); - env(credentials::deleteCred( - credIssuer1, depositor, credIssuer1, credType)); - env(credentials::deleteCred( - credIssuer1, charlie, credIssuer1, credType)); + env(credentials::deleteCred(credIssuer1, depositor, credIssuer1, credType)); + env(credentials::deleteCred(credIssuer1, charlie, credIssuer1, credType)); env.close(); auto credSle = env.le(credKeylet); BEAST_EXPECT(credSle == nullptr); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx, ter{tecNO_AUTH}); env.close(); } @@ -3522,13 +2910,9 @@ class Vault_test : public beast::unit_test::suite { testcase("private vault expired authorization"); - uint32_t const closeTime = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count(); + uint32_t const closeTime = env.current()->header().parentCloseTime.time_since_epoch().count(); { - auto tx0 = - credentials::create(depositor, credIssuer2, credType); + auto tx0 = credentials::create(depositor, credIssuer2, credType); tx0[sfExpiration] = closeTime + 20; env(tx0); tx0 = credentials::create(charlie, credIssuer2, credType); @@ -3542,15 +2926,11 @@ class Vault_test : public beast::unit_test::suite } { - auto tx1 = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx1 = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx1); env.close(); - auto const tokenKeylet = keylet::mptoken( - shares.get().getMptID(), depositor.id()); + auto const tokenKeylet = keylet::mptoken(shares.get().getMptID(), depositor.id()); BEAST_EXPECT(env.le(tokenKeylet) != nullptr); } @@ -3560,14 +2940,10 @@ class Vault_test : public beast::unit_test::suite env.close(); env.close(); - auto const credsKeylet = - credentials::keylet(depositor, credIssuer2, credType); + auto const credsKeylet = credentials::keylet(depositor, credIssuer2, credType); BEAST_EXPECT(env.le(credsKeylet) != nullptr); - auto tx2 = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(1)}); + auto tx2 = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(1)}); env(tx2, ter{tecEXPIRED}); env.close(); @@ -3575,17 +2951,12 @@ class Vault_test : public beast::unit_test::suite } { - auto const credsKeylet = - credentials::keylet(charlie, credIssuer2, credType); + auto const credsKeylet = credentials::keylet(charlie, credIssuer2, credType); BEAST_EXPECT(env.le(credsKeylet) != nullptr); - auto const tokenKeylet = keylet::mptoken( - shares.get().getMptID(), charlie.id()); + auto const tokenKeylet = keylet::mptoken(shares.get().getMptID(), charlie.id()); BEAST_EXPECT(env.le(tokenKeylet) == nullptr); - auto tx3 = vault.deposit( - {.depositor = charlie, - .id = keylet.key, - .amount = asset(2)}); + auto tx3 = vault.deposit({.depositor = charlie, .id = keylet.key, .amount = asset(2)}); env(tx3, ter{tecEXPIRED}); env.close(); @@ -3601,32 +2972,18 @@ class Vault_test : public beast::unit_test::suite env(tx); env.close(); - tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx, ter{tecNO_AUTH}); env.close(); - tx = vault.withdraw( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + tx = vault.withdraw({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx); env.close(); - tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = depositor, - .amount = asset(0)}); + tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = depositor, .amount = asset(0)}); env(tx); - tx = vault.clawback( - {.issuer = issuer, - .id = keylet.key, - .holder = owner, - .amount = asset(0)}); + tx = vault.clawback({.issuer = issuer, .id = keylet.key, .holder = owner, .amount = asset(0)}); env(tx); env.close(); @@ -3655,13 +3012,11 @@ class Vault_test : public beast::unit_test::suite env.close(); PrettyAsset asset = xrpIssue(); - auto [tx, keylet] = vault.create( - {.owner = owner, .asset = asset, .flags = tfVaultPrivate}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = asset, .flags = tfVaultPrivate}); env(tx); env.close(); - auto const [vaultAccount, issuanceId] = - [&env, keylet = keylet, this]() -> std::tuple { + auto const [vaultAccount, issuanceId] = [&env, keylet = keylet, this]() -> std::tuple { auto const vault = env.le(keylet); BEAST_EXPECT(vault != nullptr); return {vault->at(sfAccount), vault->at(sfShareMPTID)}; @@ -3672,8 +3027,7 @@ class Vault_test : public beast::unit_test::suite { testcase("private XRP vault owner can deposit"); - auto tx = vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(50)}); + auto tx = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(50)}); env(tx); env.close(); } @@ -3685,17 +3039,13 @@ class Vault_test : public beast::unit_test::suite { testcase("private XRP vault depositor not authorized yet"); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx, ter{tecNO_AUTH}); } { testcase("private XRP vault set DomainID"); - pdomain::Credentials const credentials{ - {.issuer = owner, .credType = credType}}; + pdomain::Credentials const credentials{{.issuer = owner, .credType = credType}}; env(pdomain::setTx(owner, credentials)); auto const domainId = [&]() { @@ -3717,10 +3067,7 @@ class Vault_test : public beast::unit_test::suite env.close(); BEAST_EXPECT(env.le(credKeylet)); - auto tx = vault.deposit( - {.depositor = depositor, - .id = keylet.key, - .amount = asset(50)}); + auto tx = vault.deposit({.depositor = depositor, .id = keylet.key, .amount = asset(50)}); env(tx); env.close(); } @@ -3757,17 +3104,12 @@ class Vault_test : public beast::unit_test::suite auto const keylet = keylet::vault(owner.id(), env.seq(owner)); for (int i = 0; i < 256; ++i) { - AccountID const accountId = - xrpl::pseudoAccountAddress(*env.current(), keylet.key); + AccountID const accountId = xrpl::pseudoAccountAddress(*env.current(), keylet.key); - env(pay(env.master.id(), accountId, XRP(1000)), - seq(autofill), - fee(autofill), - sig(autofill)); + env(pay(env.master.id(), accountId, XRP(1000)), seq(autofill), fee(autofill), sig(autofill)); } - auto [tx, keylet1] = - vault.create({.owner = owner, .asset = xrpIssue()}); + auto [tx, keylet1] = vault.create({.owner = owner, .asset = xrpIssue()}); BEAST_EXPECT(keylet.key == keylet1.key); env(tx, ter{terADDRESS_COLLISION}); } @@ -3792,9 +3134,7 @@ class Vault_test : public beast::unit_test::suite std::function)> peek; }; - auto testCase = [&, this]( - std::uint8_t scale, - std::function test) { + auto testCase = [&, this](std::uint8_t scale, std::function test) { Env env{*this, testable_amendments() | featureSingleAssetVault}; Account const owner{"owner"}; Account const issuer{"issuer"}; @@ -3815,37 +3155,31 @@ class Vault_test : public beast::unit_test::suite tx[sfScale] = scale; env(tx); - auto const [vaultAccount, issuanceId] = - [&env](xrpl::Keylet keylet) -> std::tuple { + auto const [vaultAccount, issuanceId] = [&env](xrpl::Keylet keylet) -> std::tuple { auto const vault = env.le(keylet); - return { - Account("vault", vault->at(sfAccount)), - vault->at(sfShareMPTID)}; + return {Account("vault", vault->at(sfAccount)), vault->at(sfShareMPTID)}; }(keylet); MPTIssue shares(issuanceId); env.memoize(vaultAccount); - auto const peek = - [=, &env, this](std::function fn) -> bool { - return env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) -> bool { - Sandbox sb(&view, tapNONE); - auto vault = sb.peek(keylet::vault(keylet.key)); - if (!BEAST_EXPECT(vault != nullptr)) - return false; - auto shares = sb.peek( - keylet::mptIssuance(vault->at(sfShareMPTID))); - if (!BEAST_EXPECT(shares != nullptr)) - return false; - if (fn(*vault, *shares)) - { - sb.update(vault); - sb.update(shares); - sb.apply(view); - return true; - } + auto const peek = [=, &env, this](std::function fn) -> bool { + return env.app().openLedger().modify([&](OpenView& view, beast::Journal j) -> bool { + Sandbox sb(&view, tapNONE); + auto vault = sb.peek(keylet::vault(keylet.key)); + if (!BEAST_EXPECT(vault != nullptr)) return false; - }); + auto shares = sb.peek(keylet::mptIssuance(vault->at(sfShareMPTID))); + if (!BEAST_EXPECT(shares != nullptr)) + return false; + if (fn(*vault, *shares)) + { + sb.update(vault); + sb.update(shares); + sb.apply(view); + return true; + } + return false; + }); }; test( @@ -3865,10 +3199,7 @@ class Vault_test : public beast::unit_test::suite testCase(18, [&, this](Env& env, Data d) { testcase("Scale deposit overflow on first deposit"); - auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = d.asset(10)}); + auto tx = d.vault.deposit({.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(10)}); env(tx, ter{tecPATH_DRY}); env.close(); }); @@ -3877,19 +3208,13 @@ class Vault_test : public beast::unit_test::suite testcase("Scale deposit overflow on second deposit"); { - auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = d.asset(5)}); + auto tx = d.vault.deposit({.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)}); env(tx); env.close(); } { - auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = d.asset(10)}); + auto tx = d.vault.deposit({.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(10)}); env(tx, ter{tecPATH_DRY}); env.close(); } @@ -3899,19 +3224,13 @@ class Vault_test : public beast::unit_test::suite testcase("Scale deposit overflow on total shares"); { - auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = d.asset(5)}); + auto tx = d.vault.deposit({.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)}); env(tx); env.close(); } { - auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = d.asset(5)}); + auto tx = d.vault.deposit({.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)}); env(tx, ter{tecPATH_DRY}); env.close(); } @@ -3921,25 +3240,18 @@ class Vault_test : public beast::unit_test::suite testcase("Scale deposit exact"); auto const start = env.balance(d.depositor, d.assets).number(); - auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = d.asset(1)}); + auto tx = d.vault.deposit({.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(1)}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(10)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - 1)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - 1)); }); testCase(1, [&, this](Env& env, Data d) { testcase("Scale deposit insignificant amount"); auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(9, -2))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(9, -2))}); env(tx, ter{tecPRECISION_LOSS}); }); @@ -3948,15 +3260,11 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(15, -1))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(15, -1))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(15)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(15, -1))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(15, -1))); }); testCase(1, [&, this](Env& env, Data d) { @@ -3967,41 +3275,29 @@ class Vault_test : public beast::unit_test::suite // vault and receive 12 shares in exchange { auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(125, -2))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(125, -2))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(12)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(12, -1))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(12, -1))); } { auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(1201, -3))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(1201, -3))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(24)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(24, -1))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(24, -1))); } { auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(1299, -3))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(1299, -3))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(36)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(36, -1))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(36, -1))); } }); @@ -4011,28 +3307,20 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); // round to 12 auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(1201, -3))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(1201, -3))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(12)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(12, -1))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(12, -1))); { // round to 6 auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(69, -2))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(69, -2))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(18)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(18, -1))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(18, -1))); } }); @@ -4042,28 +3330,20 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); // round to 12 auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(1299, -3))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(1299, -3))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(12)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(12, -1))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(12, -1))); { // round to 6 auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(62, -2))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(62, -2))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(18)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(18, -1))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(18, -1))); } }); @@ -4071,21 +3351,13 @@ class Vault_test : public beast::unit_test::suite // initial setup: deposit 100 IOU, receive 1000 shares auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(100, 0))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(100, 0))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(1000)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(100, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(100, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, Number(-1000, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(100, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(100, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, Number(-1000, 0))); { testcase("Scale redeem exact"); @@ -4095,22 +3367,13 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.share, Number(100, 0))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.share, Number(100, 0))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(900)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start + Number(10, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(90, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, Number(-900, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start + Number(10, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(90, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, Number(-900, 0))); } { @@ -4130,22 +3393,13 @@ class Vault_test : public beast::unit_test::suite // closed (because a modification like above is not persistent), // which is why the checks below are expected to pass. auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.share, Number(25, 0))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.share, Number(25, 0))}); env(tx, ter{tecINSUFFICIENT_FUNDS}); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(900 - 25)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start + Number(25, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(900 - 25, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(900 - 25, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900 - 25)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start + Number(25, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(900 - 25, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(900 - 25, 0))); } { @@ -4157,39 +3411,26 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.share, Number(21, 0))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.share, Number(21, 0))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(875 - 21)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start + Number(21, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(875 - 21, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(875 - 21, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(875 - 21)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start + Number(21, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(875 - 21, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(875 - 21, 0))); } { testcase("Scale redeem rest"); auto const rest = env.balance(d.depositor, d.shares).number(); - tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.share, rest)}); + tx = + d.vault.withdraw({.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.share, rest)}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares).number() == 0); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets).number() == 0); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares).number() == 0); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets).number() == 0); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares).number() == 0); } }); @@ -4197,19 +3438,14 @@ class Vault_test : public beast::unit_test::suite testcase("Scale withdraw overflow"); { - auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = d.asset(5)}); + auto tx = d.vault.deposit({.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)}); env(tx); env.close(); } { auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(10, 0))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(10, 0))}); env(tx, ter{tecPATH_DRY}); env.close(); } @@ -4219,21 +3455,13 @@ class Vault_test : public beast::unit_test::suite // initial setup: deposit 100 IOU, receive 1000 shares auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(100, 0))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(100, 0))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(1000)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(100, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(100, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, Number(-1000, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(100, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(100, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, Number(-1000, 0))); { testcase("Scale withdraw exact"); @@ -4246,30 +3474,19 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(10, 0))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(10, 0))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(900)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start + Number(10, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(90, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, Number(-900, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start + Number(10, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(90, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, Number(-900, 0))); } { testcase("Scale withdraw insignificant amount"); auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(4, -2))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(4, -2))}); env(tx, ter{tecPRECISION_LOSS}); } @@ -4293,22 +3510,13 @@ class Vault_test : public beast::unit_test::suite // closed (because a modification like above is not persistent), // which is why the checks below are expected to pass. auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(25, -1))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(25, -1))}); env(tx, ter{tecINSUFFICIENT_FUNDS}); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(900 - 25)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start + Number(25, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(900 - 25, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(900 - 25, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900 - 25)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start + Number(25, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(900 - 25, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(900 - 25, 0))); } { @@ -4322,22 +3530,13 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(375, -2))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(375, -2))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(875 - 38)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start + Number(38, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(875 - 38, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(875 - 38, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(875 - 38)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start + Number(38, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(875 - 38, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(875 - 38, 0))); } { @@ -4351,22 +3550,13 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(372, -2))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(372, -2))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(837 - 37)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start + Number(37, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(837 - 37, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(837 - 37, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(837 - 37)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start + Number(37, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(837 - 37, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(837 - 37, 0))); } { @@ -4374,40 +3564,26 @@ class Vault_test : public beast::unit_test::suite auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(9, -2))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(9, -2))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(800 - 1)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start + Number(1, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(800 - 1, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(800 - 1, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(800 - 1)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start + Number(1, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(800 - 1, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(800 - 1, 0))); } { testcase("Scale withdraw rest"); - auto const rest = - env.balance(d.vaultAccount, d.assets).number(); + auto const rest = env.balance(d.vaultAccount, d.assets).number(); - tx = d.vault.withdraw( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, rest)}); + tx = + d.vault.withdraw({.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, rest)}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares).number() == 0); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets).number() == 0); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares).number() == 0); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets).number() == 0); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares).number() == 0); } }); @@ -4415,10 +3591,7 @@ class Vault_test : public beast::unit_test::suite testcase("Scale clawback overflow"); { - auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = d.asset(5)}); + auto tx = d.vault.deposit({.depositor = d.depositor, .id = d.keylet.key, .amount = d.asset(5)}); env(tx); env.close(); } @@ -4438,21 +3611,13 @@ class Vault_test : public beast::unit_test::suite // initial setup: deposit 100 IOU, receive 1000 shares auto const start = env.balance(d.depositor, d.assets).number(); auto tx = d.vault.deposit( - {.depositor = d.depositor, - .id = d.keylet.key, - .amount = STAmount(d.asset, Number(100, 0))}); + {.depositor = d.depositor, .id = d.keylet.key, .amount = STAmount(d.asset, Number(100, 0))}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(1000)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start - Number(100, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(100, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(1000, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start - Number(100, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(100, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(1000, 0))); { testcase("Scale clawback exact"); // assetsToSharesWithdraw: @@ -4470,17 +3635,10 @@ class Vault_test : public beast::unit_test::suite .amount = STAmount(d.asset, Number(10, 0))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(900)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start)); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(90, 0))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(900, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start)); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(90, 0))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(900, 0))); } { @@ -4510,17 +3668,10 @@ class Vault_test : public beast::unit_test::suite .amount = STAmount(d.asset, Number(25, -1))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(900 - 25)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start)); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(900 - 25, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(900 - 25, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(900 - 25)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start)); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(900 - 25, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(900 - 25, 0))); } { @@ -4540,17 +3691,10 @@ class Vault_test : public beast::unit_test::suite .amount = STAmount(d.asset, Number(375, -2))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(875 - 38)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start)); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(875 - 38, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(875 - 38, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(875 - 38)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start)); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(875 - 38, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(875 - 38, 0))); } { @@ -4570,17 +3714,10 @@ class Vault_test : public beast::unit_test::suite .amount = STAmount(d.asset, Number(372, -2))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(837 - 37)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start)); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(837 - 37, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(837 - 37, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(837 - 37)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start)); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(837 - 37, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(837 - 37, 0))); } { @@ -4594,23 +3731,15 @@ class Vault_test : public beast::unit_test::suite .amount = STAmount(d.asset, Number(9, -2))}); env(tx); env.close(); - BEAST_EXPECT( - env.balance(d.depositor, d.shares) == d.share(800 - 1)); - BEAST_EXPECT( - env.balance(d.depositor, d.assets) == - STAmount(d.asset, start)); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets) == - STAmount(d.asset, Number(800 - 1, -1))); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares) == - STAmount(d.share, -Number(800 - 1, 0))); + BEAST_EXPECT(env.balance(d.depositor, d.shares) == d.share(800 - 1)); + BEAST_EXPECT(env.balance(d.depositor, d.assets) == STAmount(d.asset, start)); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets) == STAmount(d.asset, Number(800 - 1, -1))); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares) == STAmount(d.share, -Number(800 - 1, 0))); } { testcase("Scale clawback rest"); - auto const rest = - env.balance(d.vaultAccount, d.assets).number(); + auto const rest = env.balance(d.vaultAccount, d.assets).number(); d.peek([](SLE& vault, auto&) -> bool { vault[sfAssetsAvailable] = Number(5); return true; @@ -4621,17 +3750,12 @@ class Vault_test : public beast::unit_test::suite // * when the ledger is closed with unmodified AssetsAvailable // because a modification like above is not persistent. tx = d.vault.clawback( - {.issuer = d.issuer, - .id = d.keylet.key, - .holder = d.depositor, - .amount = STAmount(d.asset, rest)}); + {.issuer = d.issuer, .id = d.keylet.key, .holder = d.depositor, .amount = STAmount(d.asset, rest)}); env(tx); env.close(); BEAST_EXPECT(env.balance(d.depositor, d.shares).number() == 0); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.assets).number() == 0); - BEAST_EXPECT( - env.balance(d.vaultAccount, d.shares).number() == 0); + BEAST_EXPECT(env.balance(d.vaultAccount, d.assets).number() == 0); + BEAST_EXPECT(env.balance(d.vaultAccount, d.shares).number() == 0); } }); } @@ -4661,8 +3785,7 @@ class Vault_test : public beast::unit_test::suite // Set some fields { - auto tx1 = vault.deposit( - {.depositor = owner, .id = keylet.key, .amount = asset(50)}); + auto tx1 = vault.deposit({.depositor = owner, .id = keylet.key, .amount = asset(50)}); env(tx1); auto tx2 = vault.set({.owner = owner, .id = keylet.key}); @@ -4678,29 +3801,19 @@ class Vault_test : public beast::unit_test::suite }(); auto const check = [&, keylet = keylet, sle = sleVault, this]( - Json::Value const& vault, - Json::Value const& issuance = Json::nullValue) { + Json::Value const& vault, Json::Value const& issuance = Json::nullValue) { BEAST_EXPECT(vault.isObject()); - constexpr auto checkString = - [](auto& node, SField const& field, std::string v) -> bool { - return node.isMember(field.fieldName) && - node[field.fieldName].isString() && - node[field.fieldName] == v; + constexpr auto checkString = [](auto& node, SField const& field, std::string v) -> bool { + return node.isMember(field.fieldName) && node[field.fieldName].isString() && node[field.fieldName] == v; }; - constexpr auto checkObject = - [](auto& node, SField const& field, Json::Value v) -> bool { - return node.isMember(field.fieldName) && - node[field.fieldName].isObject() && - node[field.fieldName] == v; + constexpr auto checkObject = [](auto& node, SField const& field, Json::Value v) -> bool { + return node.isMember(field.fieldName) && node[field.fieldName].isObject() && node[field.fieldName] == v; }; - constexpr auto checkInt = - [](auto& node, SField const& field, int v) -> bool { + constexpr auto checkInt = [](auto& node, SField const& field, int v) -> bool { return node.isMember(field.fieldName) && - ((node[field.fieldName].isInt() && - node[field.fieldName] == Json::Int(v)) || - (node[field.fieldName].isUInt() && - node[field.fieldName] == Json::UInt(v))); + ((node[field.fieldName].isInt() && node[field.fieldName] == Json::Int(v)) || + (node[field.fieldName].isUInt() && node[field.fieldName] == Json::UInt(v))); }; BEAST_EXPECT(vault["LedgerEntryType"].asString() == "Vault"); @@ -4708,10 +3821,8 @@ class Vault_test : public beast::unit_test::suite BEAST_EXPECT(checkInt(vault, sfFlags, 0)); // Ignore all other standard fields, this test doesn't care - BEAST_EXPECT( - checkString(vault, sfAccount, toBase58(sle->at(sfAccount)))); - BEAST_EXPECT( - checkObject(vault, sfAsset, to_json(sle->at(sfAsset)))); + BEAST_EXPECT(checkString(vault, sfAccount, toBase58(sle->at(sfAccount)))); + BEAST_EXPECT(checkObject(vault, sfAsset, to_json(sle->at(sfAsset)))); BEAST_EXPECT(checkString(vault, sfAssetsAvailable, "50")); BEAST_EXPECT(checkString(vault, sfAssetsMaximum, "1000")); BEAST_EXPECT(checkString(vault, sfAssetsTotal, "50")); @@ -4721,23 +3832,15 @@ class Vault_test : public beast::unit_test::suite BEAST_EXPECT(checkString(vault, sfShareMPTID, strShareID)); BEAST_EXPECT(checkString(vault, sfOwner, toBase58(owner.id()))); BEAST_EXPECT(checkInt(vault, sfSequence, sequence)); - BEAST_EXPECT(checkInt( - vault, sfWithdrawalPolicy, vaultStrategyFirstComeFirstServe)); + BEAST_EXPECT(checkInt(vault, sfWithdrawalPolicy, vaultStrategyFirstComeFirstServe)); if (issuance.isObject()) { - BEAST_EXPECT( - issuance["LedgerEntryType"].asString() == - "MPTokenIssuance"); - BEAST_EXPECT( - issuance[jss::mpt_issuance_id].asString() == strShareID); + BEAST_EXPECT(issuance["LedgerEntryType"].asString() == "MPTokenIssuance"); + BEAST_EXPECT(issuance[jss::mpt_issuance_id].asString() == strShareID); BEAST_EXPECT(checkInt(issuance, sfSequence, 1)); - BEAST_EXPECT(checkInt( - issuance, - sfFlags, - int(lsfMPTCanEscrow | lsfMPTCanTrade | lsfMPTCanTransfer))); - BEAST_EXPECT( - checkString(issuance, sfOutstandingAmount, "50000000")); + BEAST_EXPECT(checkInt(issuance, sfFlags, int(lsfMPTCanEscrow | lsfMPTCanTrade | lsfMPTCanTransfer))); + BEAST_EXPECT(checkString(issuance, sfOutstandingAmount, "50000000")); } }; @@ -4772,8 +3875,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::vault] = to_string(uint256(42)); auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams)); - BEAST_EXPECT( - jvVault[jss::result][jss::error].asString() == "entryNotFound"); + BEAST_EXPECT(jvVault[jss::result][jss::error].asString() == "entryNotFound"); } { @@ -4783,8 +3885,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::vault][jss::owner] = issuer.human(); jvParams[jss::vault][jss::seq] = 1'000'000; auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams)); - BEAST_EXPECT( - jvVault[jss::result][jss::error].asString() == "entryNotFound"); + BEAST_EXPECT(jvVault[jss::result][jss::error].asString() == "entryNotFound"); } { @@ -4793,9 +3894,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::vault] = 42; auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams)); - BEAST_EXPECT( - jvVault[jss::result][jss::error].asString() == - "malformedRequest"); + BEAST_EXPECT(jvVault[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4805,9 +3904,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::vault][jss::owner] = 42; jvParams[jss::vault][jss::seq] = sequence; auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams)); - BEAST_EXPECT( - jvVault[jss::result][jss::error].asString() == - "malformedOwner"); + BEAST_EXPECT(jvVault[jss::result][jss::error].asString() == "malformedOwner"); } { @@ -4817,9 +3914,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::vault][jss::owner] = issuer.human(); jvParams[jss::vault][jss::seq] = "foo"; auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams)); - BEAST_EXPECT( - jvVault[jss::result][jss::error].asString() == - "malformedRequest"); + BEAST_EXPECT(jvVault[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4829,9 +3924,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::vault][jss::owner] = issuer.human(); jvParams[jss::vault][jss::seq] = -1; auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams)); - BEAST_EXPECT( - jvVault[jss::result][jss::error].asString() == - "malformedRequest"); + BEAST_EXPECT(jvVault[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4841,9 +3934,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::vault][jss::owner] = issuer.human(); jvParams[jss::vault][jss::seq] = 1e20; auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams)); - BEAST_EXPECT( - jvVault[jss::result][jss::error].asString() == - "malformedRequest"); + BEAST_EXPECT(jvVault[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4853,9 +3944,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::vault][jss::owner] = issuer.human(); jvParams[jss::vault][jss::seq] = true; auto jvVault = env.rpc("json", "ledger_entry", to_string(jvParams)); - BEAST_EXPECT( - jvVault[jss::result][jss::error].asString() == - "malformedRequest"); + BEAST_EXPECT(jvVault[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4864,8 +3953,7 @@ class Vault_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::account] = owner.human(); jvParams[jss::type] = jss::vault; - auto jv = env.rpc( - "json", "account_objects", to_string(jvParams))[jss::result]; + auto jv = env.rpc("json", "account_objects", to_string(jvParams))[jss::result]; BEAST_EXPECT(jv[jss::account_objects].size() == 1); check(jv[jss::account_objects][0u]); @@ -4878,22 +3966,18 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::binary] = false; jvParams[jss::type] = jss::vault; - Json::Value jv = - env.rpc("json", "ledger_data", to_string(jvParams)); + Json::Value jv = env.rpc("json", "ledger_data", to_string(jvParams)); BEAST_EXPECT(jv[jss::result][jss::state].size() == 1); check(jv[jss::result][jss::state][0u]); } { testcase("RPC vault_info command line"); - Json::Value jv = - env.rpc("vault_info", strHex(keylet.key), "validated"); + Json::Value jv = env.rpc("vault_info", strHex(keylet.key), "validated"); BEAST_EXPECT(!jv[jss::result].isMember(jss::error)); BEAST_EXPECT(jv[jss::result].isMember(jss::vault)); - check( - jv[jss::result][jss::vault], - jv[jss::result][jss::vault][jss::shares]); + check(jv[jss::result][jss::vault], jv[jss::result][jss::vault][jss::shares]); } { @@ -4905,9 +3989,7 @@ class Vault_test : public beast::unit_test::suite BEAST_EXPECT(!jv[jss::result].isMember(jss::error)); BEAST_EXPECT(jv[jss::result].isMember(jss::vault)); - check( - jv[jss::result][jss::vault], - jv[jss::result][jss::vault][jss::shares]); + check(jv[jss::result][jss::vault], jv[jss::result][jss::vault][jss::shares]); } { @@ -4916,8 +3998,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::vault_id] = "foobar"; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4926,8 +4007,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::vault_id] = 0; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4940,9 +4020,7 @@ class Vault_test : public beast::unit_test::suite BEAST_EXPECT(!jv[jss::result].isMember(jss::error)); BEAST_EXPECT(jv[jss::result].isMember(jss::vault)); - check( - jv[jss::result][jss::vault], - jv[jss::result][jss::vault][jss::shares]); + check(jv[jss::result][jss::vault], jv[jss::result][jss::vault][jss::shares]); } { @@ -4952,8 +4030,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::owner] = owner.human(); jvParams[jss::seq] = "foobar"; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4963,8 +4040,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::owner] = owner.human(); jvParams[jss::seq] = 0; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4974,8 +4050,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::owner] = owner.human(); jvParams[jss::seq] = -1; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4985,8 +4060,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::owner] = owner.human(); jvParams[jss::seq] = 1e20; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -4996,8 +4070,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::owner] = owner.human(); jvParams[jss::seq] = true; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -5007,8 +4080,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::owner] = "foobar"; jvParams[jss::seq] = sequence; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -5017,8 +4089,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::owner] = owner.human(); auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -5027,8 +4098,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::seq] = sequence; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -5038,8 +4108,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::vault_id] = strHex(keylet.key); jvParams[jss::seq] = sequence; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -5049,8 +4118,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::vault_id] = strHex(keylet.key); jvParams[jss::owner] = owner.human(); auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -5063,8 +4131,7 @@ class Vault_test : public beast::unit_test::suite jvParams[jss::seq] = sequence; jvParams[jss::owner] = owner.human(); auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -5072,8 +4139,7 @@ class Vault_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ledger_index] = jss::validated; auto jv = env.rpc("json", "vault_info", to_string(jvParams)); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { @@ -5085,23 +4151,19 @@ class Vault_test : public beast::unit_test::suite { testcase("RPC vault_info command line invalid index"); Json::Value jv = env.rpc("vault_info", "0", "validated"); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "malformedRequest"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "malformedRequest"); } { testcase("RPC vault_info command line invalid index"); - Json::Value jv = - env.rpc("vault_info", strHex(uint256(42)), "validated"); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "entryNotFound"); + Json::Value jv = env.rpc("vault_info", strHex(uint256(42)), "validated"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "entryNotFound"); } { testcase("RPC vault_info command line invalid ledger"); Json::Value jv = env.rpc("vault_info", strHex(keylet.key), "0"); - BEAST_EXPECT( - jv[jss::result][jss::error].asString() == "lgrNotFound"); + BEAST_EXPECT(jv[jss::result][jss::error].asString() == "lgrNotFound"); } } @@ -5120,9 +4182,7 @@ class Vault_test : public beast::unit_test::suite PrettyAsset asset = xrpIssue(); }; - auto const xrpBalance = - [this]( - Env const& env, Account const& account) -> std::optional { + auto const xrpBalance = [this](Env const& env, Account const& account) -> std::optional { auto sle = env.le(keylet::account(account.id())); if (BEAST_EXPECT(sle != nullptr)) return sle->getFieldAmount(sfBalance).xrp().drops(); @@ -5179,24 +4239,17 @@ class Vault_test : public beast::unit_test::suite if (!BEAST_EXPECT(startBalance.has_value())) return; - tx = vault.deposit( - {.depositor = carol, - .id = keylet.key, - .amount = asset(amount)}); + tx = vault.deposit({.depositor = carol, .id = keylet.key, .amount = asset(amount)}); env(tx, delegate::as(alice)); env.close(); BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - amount); - tx = vault.withdraw( - {.depositor = carol, - .id = keylet.key, - .amount = asset(amount - 1)}); + tx = vault.withdraw({.depositor = carol, .id = keylet.key, .amount = asset(amount - 1)}); env(tx, delegate::as(alice)); env.close(); BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - 1); - tx = vault.withdraw( - {.depositor = carol, .id = keylet.key, .amount = asset(1)}); + tx = vault.withdraw({.depositor = carol, .id = keylet.key, .amount = asset(1)}); env(tx); env.close(); BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - baseFee); @@ -5215,27 +4268,17 @@ class Vault_test : public beast::unit_test::suite if (!BEAST_EXPECT(startBalance.has_value())) return; - tx = vault.deposit( - {.depositor = carol, - .id = keylet.key, - .amount = asset(amount)}); + tx = vault.deposit({.depositor = carol, .id = keylet.key, .amount = asset(amount)}); env(tx); env.close(); - BEAST_EXPECT( - xrpBalance(env, carol) == *startBalance - amount - baseFee); + BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - amount - baseFee); - tx = vault.withdraw( - {.depositor = carol, - .id = keylet.key, - .amount = asset(baseFee)}); + tx = vault.withdraw({.depositor = carol, .id = keylet.key, .amount = asset(baseFee)}); env(tx, delegate::as(alice)); env.close(); BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - amount); - tx = vault.withdraw( - {.depositor = carol, - .id = keylet.key, - .amount = asset(amount - baseFee)}); + tx = vault.withdraw({.depositor = carol, .id = keylet.key, .amount = asset(amount - baseFee)}); env(tx, delegate::as(alice)); env.close(); BEAST_EXPECT(xrpBalance(env, carol) == *startBalance - baseFee); @@ -5258,29 +4301,24 @@ class Vault_test : public beast::unit_test::suite auto const sleVault = env.le(vaultKeylet); BEAST_EXPECT(sleVault != nullptr); - return std::make_pair( - sleVault->at(sfAssetsAvailable), sleVault->at(sfAssetsTotal)); + return std::make_pair(sleVault->at(sfAssetsAvailable), sleVault->at(sfAssetsTotal)); }; auto const vaultShareBalance = [&](Keylet const& vaultKeylet) { auto const sleVault = env.le(vaultKeylet); BEAST_EXPECT(sleVault != nullptr); - auto const sleIssuance = - env.le(keylet::mptIssuance(sleVault->at(sfShareMPTID))); + auto const sleIssuance = env.le(keylet::mptIssuance(sleVault->at(sfShareMPTID))); BEAST_EXPECT(sleIssuance != nullptr); return sleIssuance->at(sfOutstandingAmount); }; auto const setupVault = - [&](PrettyAsset const& asset, - Account const& owner, - Account const& depositor) -> std::pair { + [&](PrettyAsset const& asset, Account const& owner, Account const& depositor) -> std::pair { Vault vault{env}; - auto const& [tx, vaultKeylet] = - vault.create({.owner = owner, .asset = asset}); + auto const& [tx, vaultKeylet] = vault.create({.owner = owner, .asset = asset}); env(tx, ter(tesSUCCESS), THISLINE); env.close(); @@ -5289,32 +4327,24 @@ class Vault_test : public beast::unit_test::suite Asset share = vaultSle->at(sfShareMPTID); - env(vault.deposit( - {.depositor = depositor, - .id = vaultKeylet.key, - .amount = asset(100)}), + env(vault.deposit({.depositor = depositor, .id = vaultKeylet.key, .amount = asset(100)}), ter(tesSUCCESS), THISLINE); env.close(); - auto const& [availablePreDefault, totalPreDefault] = - vaultAssetBalance(vaultKeylet); + auto const& [availablePreDefault, totalPreDefault] = vaultAssetBalance(vaultKeylet); BEAST_EXPECT(availablePreDefault == totalPreDefault); BEAST_EXPECT(availablePreDefault == asset(100).value()); // attempt to clawback shares while there are assets fails env(vault.clawback( - {.issuer = owner, - .id = vaultKeylet.key, - .holder = depositor, - .amount = share(0).value()}), + {.issuer = owner, .id = vaultKeylet.key, .holder = depositor, .amount = share(0).value()}), ter(tecNO_PERMISSION), THISLINE); env.close(); auto const& sharesAvailable = vaultShareBalance(vaultKeylet); - auto const& brokerKeylet = - keylet::loanbroker(owner.id(), env.seq(owner)); + auto const& brokerKeylet = keylet::loanbroker(owner.id(), env.seq(owner)); env(set(owner, vaultKeylet.key), THISLINE); env.close(); @@ -5336,22 +4366,16 @@ class Vault_test : public beast::unit_test::suite // attempt to clawback shares while there assetsAvailable == 0 and // assetsTotal > 0 fails env(vault.clawback( - {.issuer = owner, - .id = vaultKeylet.key, - .holder = depositor, - .amount = share(0).value()}), + {.issuer = owner, .id = vaultKeylet.key, .holder = depositor, .amount = share(0).value()}), ter(tecNO_PERMISSION), THISLINE); env.close(); env.close(std::chrono::seconds{120 + 60}); - env(manage(owner, loanKeylet.key, tfLoanDefault), - ter(tesSUCCESS), - THISLINE); + env(manage(owner, loanKeylet.key, tfLoanDefault), ter(tesSUCCESS), THISLINE); - auto const& [availablePostDefault, totalPostDefault] = - vaultAssetBalance(vaultKeylet); + auto const& [availablePostDefault, totalPostDefault] = vaultAssetBalance(vaultKeylet); BEAST_EXPECT(availablePostDefault == totalPostDefault); BEAST_EXPECT(availablePostDefault == asset(0).value()); @@ -5360,141 +4384,124 @@ class Vault_test : public beast::unit_test::suite return std::make_pair(vault, vaultKeylet); }; - auto const testCase = [&](PrettyAsset const& asset, - std::string const& prefix, - Account const& owner, - Account const& depositor) { - { - testcase( - "VaultClawback (share) - " + prefix + - " owner asset clawback fails"); - auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); - env(vault.clawback({ - .issuer = owner, - .id = vaultKeylet.key, - .holder = depositor, - .amount = asset(100).value(), - }), - // when asset is XRP or owner is not issuer clawback fail - // when owner is issuer precision loss occurs as vault is - // empty - asset.native() ? ter(temMALFORMED) - : asset.raw().getIssuer() != owner.id() - ? ter(tecNO_PERMISSION) - : ter(tecPRECISION_LOSS), - THISLINE); - env.close(); - } + auto const testCase = + [&](PrettyAsset const& asset, std::string const& prefix, Account const& owner, Account const& depositor) { + { + testcase("VaultClawback (share) - " + prefix + " owner asset clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = asset(100).value(), + }), + // when asset is XRP or owner is not issuer clawback fail + // when owner is issuer precision loss occurs as vault is + // empty + asset.native() ? ter(temMALFORMED) + : asset.raw().getIssuer() != owner.id() ? ter(tecNO_PERMISSION) + : ter(tecPRECISION_LOSS), + THISLINE); + env.close(); + } - { - testcase( - "VaultClawback (share) - " + prefix + - " owner incomplete share clawback fails"); - auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); - auto const& vaultSle = env.le(vaultKeylet); - BEAST_EXPECT(vaultSle != nullptr); - if (!vaultSle) - return; - Asset share = vaultSle->at(sfShareMPTID); - env(vault.clawback({ - .issuer = owner, - .id = vaultKeylet.key, - .holder = depositor, - .amount = share(1).value(), - }), - ter(tecLIMIT_EXCEEDED), - THISLINE); - env.close(); - } + { + testcase("VaultClawback (share) - " + prefix + " owner incomplete share clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + if (!vaultSle) + return; + Asset share = vaultSle->at(sfShareMPTID); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = share(1).value(), + }), + ter(tecLIMIT_EXCEEDED), + THISLINE); + env.close(); + } - { - testcase( - "VaultClawback (share) - " + prefix + - " owner implicit complete share clawback"); - auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); - env(vault.clawback({ - .issuer = owner, - .id = vaultKeylet.key, - .holder = depositor, - }), - // when owner is issuer implicit clawback fails - asset.native() || asset.raw().getIssuer() != owner.id() - ? ter(tesSUCCESS) - : ter(tecWRONG_ASSET), - THISLINE); - env.close(); - } + { + testcase("VaultClawback (share) - " + prefix + " owner implicit complete share clawback"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + }), + // when owner is issuer implicit clawback fails + asset.native() || asset.raw().getIssuer() != owner.id() ? ter(tesSUCCESS) : ter(tecWRONG_ASSET), + THISLINE); + env.close(); + } - { - testcase( - "VaultClawback (share) - " + prefix + - " owner explicit complete share clawback succeeds"); - auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); - auto const& vaultSle = env.le(vaultKeylet); - BEAST_EXPECT(vaultSle != nullptr); - if (!vaultSle) - return; - Asset share = vaultSle->at(sfShareMPTID); - env(vault.clawback({ - .issuer = owner, - .id = vaultKeylet.key, - .holder = depositor, - .amount = share(vaultShareBalance(vaultKeylet)).value(), - }), - ter(tesSUCCESS), - THISLINE); - env.close(); - } - { - testcase( - "VaultClawback (share) - " + prefix + - " owner can clawback own shares"); - auto [vault, vaultKeylet] = setupVault(asset, owner, owner); - auto const& vaultSle = env.le(vaultKeylet); - BEAST_EXPECT(vaultSle != nullptr); - if (!vaultSle) - return; - Asset share = vaultSle->at(sfShareMPTID); - env(vault.clawback({ - .issuer = owner, - .id = vaultKeylet.key, - .holder = owner, - .amount = share(vaultShareBalance(vaultKeylet)).value(), - }), - ter(tesSUCCESS), - THISLINE); - env.close(); - } + { + testcase("VaultClawback (share) - " + prefix + " owner explicit complete share clawback succeeds"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor); + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + if (!vaultSle) + return; + Asset share = vaultSle->at(sfShareMPTID); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = depositor, + .amount = share(vaultShareBalance(vaultKeylet)).value(), + }), + ter(tesSUCCESS), + THISLINE); + env.close(); + } + { + testcase("VaultClawback (share) - " + prefix + " owner can clawback own shares"); + auto [vault, vaultKeylet] = setupVault(asset, owner, owner); + auto const& vaultSle = env.le(vaultKeylet); + BEAST_EXPECT(vaultSle != nullptr); + if (!vaultSle) + return; + Asset share = vaultSle->at(sfShareMPTID); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = owner, + .amount = share(vaultShareBalance(vaultKeylet)).value(), + }), + ter(tesSUCCESS), + THISLINE); + env.close(); + } - { - testcase( - "VaultClawback (share) - " + prefix + - " empty vault share clawback fails"); - auto [vault, vaultKeylet] = setupVault(asset, owner, owner); - auto const& vaultSle = env.le(vaultKeylet); - if (BEAST_EXPECT(vaultSle != nullptr)) - return; - Asset share = vaultSle->at(sfShareMPTID); - env(vault.clawback({ - .issuer = owner, - .id = vaultKeylet.key, - .holder = owner, - .amount = share(vaultShareBalance(vaultKeylet)).value(), - }), - ter(tesSUCCESS), - THISLINE); + { + testcase("VaultClawback (share) - " + prefix + " empty vault share clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, owner); + auto const& vaultSle = env.le(vaultKeylet); + if (BEAST_EXPECT(vaultSle != nullptr)) + return; + Asset share = vaultSle->at(sfShareMPTID); + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = owner, + .amount = share(vaultShareBalance(vaultKeylet)).value(), + }), + ter(tesSUCCESS), + THISLINE); - // Now the vault is empty, clawback again fails - env(vault.clawback({ - .issuer = owner, - .id = vaultKeylet.key, - .holder = owner, - }), - ter(tecNO_PERMISSION), - THISLINE); - env.close(); - } - }; + // Now the vault is empty, clawback again fails + env(vault.clawback({ + .issuer = owner, + .id = vaultKeylet.key, + .holder = owner, + }), + ter(tecNO_PERMISSION), + THISLINE); + env.close(); + } + }; Account owner{"alice"}; Account depositor{"bob"}; @@ -5523,8 +4530,7 @@ class Vault_test : public beast::unit_test::suite // Test MPT MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); PrettyAsset MPT = mptt.issuanceID(); mptt.authorize({.account = owner}); mptt.authorize({.account = depositor}); @@ -5543,24 +4549,19 @@ class Vault_test : public beast::unit_test::suite using namespace loan; Env env(*this); - auto const setupVault = - [&](PrettyAsset const& asset, - Account const& owner, - Account const& depositor, - Account const& issuer) -> std::pair { + auto const setupVault = [&](PrettyAsset const& asset, + Account const& owner, + Account const& depositor, + Account const& issuer) -> std::pair { Vault vault{env}; - auto const& [tx, vaultKeylet] = - vault.create({.owner = owner, .asset = asset}); + auto const& [tx, vaultKeylet] = vault.create({.owner = owner, .asset = asset}); env(tx, ter(tesSUCCESS), THISLINE); env.close(); auto const& vaultSle = env.le(vaultKeylet); BEAST_EXPECT(vaultSle != nullptr); - env(vault.deposit( - {.depositor = depositor, - .id = vaultKeylet.key, - .amount = asset(100)}), + env(vault.deposit({.depositor = depositor, .id = vaultKeylet.key, .amount = asset(100)}), ter(tesSUCCESS), THISLINE); env.close(); @@ -5575,11 +4576,8 @@ class Vault_test : public beast::unit_test::suite Account const& issuer) { if (asset.native()) { - testcase( - "VaultClawback (asset) - " + prefix + - " issuer XRP clawback fails"); - auto [vault, vaultKeylet] = - setupVault(asset, owner, depositor, issuer); + testcase("VaultClawback (asset) - " + prefix + " issuer XRP clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor, issuer); // If the asset is XRP, clawback with amount fails as malfored // when asset is specified. env(vault.clawback({ @@ -5602,11 +4600,8 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - "VaultClawback (asset) - " + prefix + - " clawback for different asset fails"); - auto [vault, vaultKeylet] = - setupVault(asset, owner, depositor, issuer); + testcase("VaultClawback (asset) - " + prefix + " clawback for different asset fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor, issuer); Account issuer2{"issuer2"}; PrettyAsset asset2 = issuer2["FOO"]; @@ -5621,11 +4616,8 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - "VaultClawback (asset) - " + prefix + - " ambiguous owner/issuer asset clawback fails"); - auto [vault, vaultKeylet] = - setupVault(asset, issuer, depositor, issuer); + testcase("VaultClawback (asset) - " + prefix + " ambiguous owner/issuer asset clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, issuer, depositor, issuer); env(vault.clawback({ .issuer = issuer, .id = vaultKeylet.key, @@ -5636,11 +4628,8 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - "VaultClawback (asset) - " + prefix + - " non-issuer asset clawback fails"); - auto [vault, vaultKeylet] = - setupVault(asset, owner, depositor, issuer); + testcase("VaultClawback (asset) - " + prefix + " non-issuer asset clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor, issuer); env(vault.clawback({ .issuer = owner, @@ -5661,11 +4650,8 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - "VaultClawback (asset) - " + prefix + - " issuer clawback from self fails"); - auto [vault, vaultKeylet] = - setupVault(asset, owner, issuer, issuer); + testcase("VaultClawback (asset) - " + prefix + " issuer clawback from self fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, issuer, issuer); env(vault.clawback({ .issuer = issuer, .id = vaultKeylet.key, @@ -5676,11 +4662,8 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - "VaultClawback (asset) - " + prefix + - " issuer share clawback fails"); - auto [vault, vaultKeylet] = - setupVault(asset, owner, depositor, issuer); + testcase("VaultClawback (asset) - " + prefix + " issuer share clawback fails"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor, issuer); auto const& vaultSle = env.le(vaultKeylet); BEAST_EXPECT(vaultSle != nullptr); if (!vaultSle) @@ -5698,11 +4681,8 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - "VaultClawback (asset) - " + prefix + - " partial issuer asset clawback succeeds"); - auto [vault, vaultKeylet] = - setupVault(asset, owner, depositor, issuer); + testcase("VaultClawback (asset) - " + prefix + " partial issuer asset clawback succeeds"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor, issuer); env(vault.clawback({ .issuer = issuer, @@ -5715,11 +4695,8 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - "VaultClawback (asset) - " + prefix + - " full issuer asset clawback succeeds"); - auto [vault, vaultKeylet] = - setupVault(asset, owner, depositor, issuer); + testcase("VaultClawback (asset) - " + prefix + " full issuer asset clawback succeeds"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor, issuer); env(vault.clawback({ .issuer = issuer, @@ -5732,11 +4709,8 @@ class Vault_test : public beast::unit_test::suite } { - testcase( - "VaultClawback (asset) - " + prefix + - " implicit full issuer asset clawback succeeds"); - auto [vault, vaultKeylet] = - setupVault(asset, owner, depositor, issuer); + testcase("VaultClawback (asset) - " + prefix + " implicit full issuer asset clawback succeeds"); + auto [vault, vaultKeylet] = setupVault(asset, owner, depositor, issuer); env(vault.clawback({ .issuer = issuer, @@ -5772,8 +4746,7 @@ class Vault_test : public beast::unit_test::suite // Test MPT MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); PrettyAsset MPT = mptt.issuanceID(); mptt.authorize({.account = owner}); mptt.authorize({.account = depositor}); @@ -5797,15 +4770,12 @@ class Vault_test : public beast::unit_test::suite env.fund(XRP(1'000'000), issuer, owner); env.close(); - auto const maxInt64 = - std::to_string(std::numeric_limits::max()); + auto const maxInt64 = std::to_string(std::numeric_limits::max()); BEAST_EXPECT(maxInt64 == "9223372036854775807"); // Naming things is hard - auto const maxInt64Plus1 = std::to_string( - static_cast( - std::numeric_limits::max()) + - 1); + auto const maxInt64Plus1 = + std::to_string(static_cast(std::numeric_limits::max()) + 1); BEAST_EXPECT(maxInt64Plus1 == "9223372036854775808"); auto const initialXRP = to_string(INITIAL_XRP); @@ -5819,8 +4789,7 @@ class Vault_test : public beast::unit_test::suite PrettyAsset const xrpAsset = xrpIssue(); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = xrpAsset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = xrpAsset}); tx[sfData] = "4D65746144617461"; tx[sfAssetsMaximum] = maxInt64; @@ -5841,8 +4810,8 @@ class Vault_test : public beast::unit_test::suite // This value will be rounded auto const insertAt = maxInt64Plus1.size() - 3; - auto const decimalTest = maxInt64Plus1.substr(0, insertAt) + "." + - maxInt64Plus1.substr(insertAt); // (max int64+1) / 1000 + auto const decimalTest = + maxInt64Plus1.substr(0, insertAt) + "." + maxInt64Plus1.substr(insertAt); // (max int64+1) / 1000 BEAST_EXPECT(decimalTest == "9223372036854775.808"); tx[sfAssetsMaximum] = decimalTest; auto const newKeylet = keylet::vault(owner.id(), env.seq(owner)); @@ -5861,9 +4830,7 @@ class Vault_test : public beast::unit_test::suite PrettyAsset const mptAsset = [&]() { MPTTester mptt{env, issuer, mptInitNoFund}; - mptt.create( - {.flags = - tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); + mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); env.close(); PrettyAsset const mptAsset = mptt["MPT"]; mptt.authorize({.account = owner}); @@ -5874,8 +4841,7 @@ class Vault_test : public beast::unit_test::suite env(pay(issuer, owner, mptAsset(100'000)), THISLINE); env.close(); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = mptAsset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = mptAsset}); tx[sfData] = "4D65746144617461"; tx[sfAssetsMaximum] = maxInt64; @@ -5896,8 +4862,8 @@ class Vault_test : public beast::unit_test::suite // This value will be rounded auto const insertAt = maxInt64Plus1.size() - 1; - auto const decimalTest = maxInt64Plus1.substr(0, insertAt) + "." + - maxInt64Plus1.substr(insertAt); // (max int64+1) / 10 + auto const decimalTest = + maxInt64Plus1.substr(0, insertAt) + "." + maxInt64Plus1.substr(insertAt); // (max int64+1) / 10 BEAST_EXPECT(decimalTest == "922337203685477580.8"); tx[sfAssetsMaximum] = decimalTest; auto const newKeylet = keylet::vault(owner.id(), env.seq(owner)); @@ -5920,8 +4886,7 @@ class Vault_test : public beast::unit_test::suite env(pay(issuer, owner, iouAsset(200))); env.close(); - auto [tx, keylet] = - vault.create({.owner = owner, .asset = iouAsset}); + auto [tx, keylet] = vault.create({.owner = owner, .asset = iouAsset}); tx[sfData] = "4D65746144617461"; tx[sfAssetsMaximum] = maxInt64; @@ -5949,12 +4914,11 @@ class Vault_test : public beast::unit_test::suite // These values will be rounded to 15 significant digits { auto const insertAt = maxInt64Plus1.size() - 1; - auto const decimalTest = maxInt64Plus1.substr(0, insertAt) + - "." + maxInt64Plus1.substr(insertAt); // (max int64+1) / 10 + auto const decimalTest = + maxInt64Plus1.substr(0, insertAt) + "." + maxInt64Plus1.substr(insertAt); // (max int64+1) / 10 BEAST_EXPECT(decimalTest == "922337203685477580.8"); tx[sfAssetsMaximum] = decimalTest; - auto const newKeylet = - keylet::vault(owner.id(), env.seq(owner)); + auto const newKeylet = keylet::vault(owner.id(), env.seq(owner)); env(tx, THISLINE); env.close(); @@ -5962,15 +4926,11 @@ class Vault_test : public beast::unit_test::suite if (!BEAST_EXPECT(vaultSle)) return; - BEAST_EXPECT( - (vaultSle->at(sfAssetsMaximum) == - Number{9223372036854776, 2, Number::normalized{}})); + BEAST_EXPECT((vaultSle->at(sfAssetsMaximum) == Number{9223372036854776, 2, Number::normalized{}})); } { - tx[sfAssetsMaximum] = - "9223372036854775807e40"; // max int64 * 10^40 - auto const newKeylet = - keylet::vault(owner.id(), env.seq(owner)); + tx[sfAssetsMaximum] = "9223372036854775807e40"; // max int64 * 10^40 + auto const newKeylet = keylet::vault(owner.id(), env.seq(owner)); env(tx, THISLINE); env.close(); @@ -5978,15 +4938,11 @@ class Vault_test : public beast::unit_test::suite if (!BEAST_EXPECT(vaultSle)) return; - BEAST_EXPECT( - (vaultSle->at(sfAssetsMaximum) == - Number{9223372036854776, 43, Number::normalized{}})); + BEAST_EXPECT((vaultSle->at(sfAssetsMaximum) == Number{9223372036854776, 43, Number::normalized{}})); } { - tx[sfAssetsMaximum] = - "9223372036854775807e-40"; // max int64 * 10^-40 - auto const newKeylet = - keylet::vault(owner.id(), env.seq(owner)); + tx[sfAssetsMaximum] = "9223372036854775807e-40"; // max int64 * 10^-40 + auto const newKeylet = keylet::vault(owner.id(), env.seq(owner)); env(tx, THISLINE); env.close(); @@ -5994,15 +4950,11 @@ class Vault_test : public beast::unit_test::suite if (!BEAST_EXPECT(vaultSle)) return; - BEAST_EXPECT( - (vaultSle->at(sfAssetsMaximum) == - Number{9223372036854776, -37, Number::normalized{}})); + BEAST_EXPECT((vaultSle->at(sfAssetsMaximum) == Number{9223372036854776, -37, Number::normalized{}})); } { - tx[sfAssetsMaximum] = - "9223372036854775807e-100"; // max int64 * 10^-100 - auto const newKeylet = - keylet::vault(owner.id(), env.seq(owner)); + tx[sfAssetsMaximum] = "9223372036854775807e-100"; // max int64 * 10^-100 + auto const newKeylet = keylet::vault(owner.id(), env.seq(owner)); env(tx, THISLINE); env.close(); @@ -6023,8 +4975,7 @@ class Vault_test : public beast::unit_test::suite // 2. Mantissa larger than uint64 max try { - tx[sfAssetsMaximum] = - "18446744073709551617e5"; // uint64 max + 1 + tx[sfAssetsMaximum] = "18446744073709551617e5"; // uint64 max + 1 env(tx, THISLINE); BEAST_EXPECT(false); } diff --git a/src/test/app/XChain_test.cpp b/src/test/app/XChain_test.cpp index 3b09845723..e074e03d97 100644 --- a/src/test/app/XChain_test.cpp +++ b/src/test/app/XChain_test.cpp @@ -132,8 +132,7 @@ struct SEnv { STXChainBridge b(jvb); - auto tryGet = - [&](STXChainBridge::ChainType ct) -> std::shared_ptr { + auto tryGet = [&](STXChainBridge::ChainType ct) -> std::shared_ptr { if (auto r = env_.le(keylet::bridge(b, ct))) { if ((*r)[sfXChainBridge] == b) @@ -167,8 +166,7 @@ struct SEnv std::shared_ptr caClaimID(Json::Value const& jvb, std::uint64_t seq) { - return env_.le( - keylet::xChainCreateAccountClaimID(STXChainBridge(jvb), seq)); + return env_.le(keylet::xChainCreateAccountClaimID(STXChainBridge(jvb), seq)); } }; @@ -195,15 +193,7 @@ struct XEnv : public jtx::XChainBridgeObjects, public SEnv } else { - this->fund( - xrp_funds, - scDoor, - scAlice, - scBob, - scCarol, - scGw, - scAttester, - scReward); + this->fund(xrp_funds, scDoor, scAlice, scBob, scCarol, scGw, scAttester, scReward); for (auto& ra : payees) this->fund(xrp_funds, ra); @@ -280,14 +270,7 @@ struct BalanceTransfer jtx::Account const& payer, std::vector const& payees, bool withClaim) - : BalanceTransfer( - env, - from_acct, - to_acct, - payer, - &payees[0], - payees.size(), - withClaim) + : BalanceTransfer(env, from_acct, to_acct, payer, &payees[0], payees.size(), withClaim) { } @@ -295,28 +278,20 @@ struct BalanceTransfer payees_received(STAmount const& reward) const { return std::all_of( - reward_accounts.begin(), - reward_accounts.end(), - [&](balance const& b) { return b.diff() == reward; }); + reward_accounts.begin(), reward_accounts.end(), [&](balance const& b) { return b.diff() == reward; }); } bool check_most_balances(STAmount const& amt, STAmount const& reward) { - return from_.diff() == -amt && to_.diff() == amt && - payees_received(reward); + return from_.diff() == -amt && to_.diff() == amt && payees_received(reward); } bool - has_happened( - STAmount const& amt, - STAmount const& reward, - bool check_payer = true) + has_happened(STAmount const& amt, STAmount const& reward, bool check_payer = true) { - auto reward_cost = - multiply(reward, STAmount(reward_accounts.size()), reward.issue()); - return check_most_balances(amt, reward) && - (!check_payer || payer_.diff() == -(reward_cost + txFees_)); + auto reward_cost = multiply(reward, STAmount(reward_accounts.size()), reward.issue()); + return check_most_balances(amt, reward) && (!check_payer || payer_.diff() == -(reward_cost + txFees_)); } bool @@ -350,18 +325,13 @@ struct BridgeDef return {}; return minAccountCreate; }(); - mcEnv.tx(bridge_create(doorA, jvb, reward, optAccountCreate)) - .tx(jtx::signers(doorA, quorum, signers)) - .close(); + mcEnv.tx(bridge_create(doorA, jvb, reward, optAccountCreate)).tx(jtx::signers(doorA, quorum, signers)).close(); - scEnv.tx(bridge_create(doorB, jvb, reward, optAccountCreate)) - .tx(jtx::signers(doorB, quorum, signers)) - .close(); + scEnv.tx(bridge_create(doorB, jvb, reward, optAccountCreate)).tx(jtx::signers(doorB, quorum, signers)).close(); } }; -struct XChain_test : public beast::unit_test::suite, - public jtx::XChainBridgeObjects +struct XChain_test : public beast::unit_test::suite, public jtx::XChainBridgeObjects { XRPAmount reserve(std::uint32_t count) @@ -418,44 +388,31 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this).tx(create_bridge(mcDoor)).close(); // Bridge not owned by one of the door account. - XEnv(*this).tx( - create_bridge(mcBob), ter(temXCHAIN_BRIDGE_NONDOOR_OWNER)); + XEnv(*this).tx(create_bridge(mcBob), ter(temXCHAIN_BRIDGE_NONDOOR_OWNER)); // Create twice on the same account - XEnv(*this) - .tx(create_bridge(mcDoor)) - .close() - .tx(create_bridge(mcDoor), ter(tecDUPLICATE)); + XEnv(*this).tx(create_bridge(mcDoor)).close().tx(create_bridge(mcDoor), ter(tecDUPLICATE)); // Create USD bridge Alice -> Bob ... should succeed - XEnv(*this).tx( - create_bridge( - mcAlice, bridge(mcAlice, mcGw["USD"], mcBob, mcBob["USD"])), - ter(tesSUCCESS)); + XEnv(*this).tx(create_bridge(mcAlice, bridge(mcAlice, mcGw["USD"], mcBob, mcBob["USD"])), ter(tesSUCCESS)); // Create USD bridge, Alice is both the locking door and locking issue, // ... should fail. XEnv(*this).tx( - create_bridge( - mcAlice, bridge(mcAlice, mcAlice["USD"], mcBob, mcBob["USD"])), + create_bridge(mcAlice, bridge(mcAlice, mcAlice["USD"], mcBob, mcBob["USD"])), ter(temXCHAIN_BRIDGE_BAD_ISSUES)); // Bridge where the two door accounts are equal. XEnv(*this).tx( - create_bridge( - mcBob, bridge(mcBob, mcGw["USD"], mcBob, mcGw["USD"])), - ter(temXCHAIN_EQUAL_DOOR_ACCOUNTS)); + create_bridge(mcBob, bridge(mcBob, mcGw["USD"], mcBob, mcGw["USD"])), ter(temXCHAIN_EQUAL_DOOR_ACCOUNTS)); // Both door accounts are on the same chain. This is not allowed. // Although it doesn't violate any invariants, it's not a useful thing // to do and it complicates the "add claim" transactions. XEnv(*this) - .tx(create_bridge( - mcAlice, bridge(mcAlice, mcGw["USD"], mcBob, mcBob["USD"]))) + .tx(create_bridge(mcAlice, bridge(mcAlice, mcGw["USD"], mcBob, mcBob["USD"]))) .close() - .tx(create_bridge( - mcBob, bridge(mcAlice, mcGw["USD"], mcBob, mcBob["USD"])), - ter(tecDUPLICATE)) + .tx(create_bridge(mcBob, bridge(mcAlice, mcGw["USD"], mcBob, mcBob["USD"])), ter(tecDUPLICATE)) .close(); // Create a bridge on an account with exactly enough balance to @@ -473,36 +430,27 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(mcuDoor, jvub), ter(tecINSUFFICIENT_RESERVE)); // Reward amount is non-xrp - XEnv(*this).tx( - create_bridge(mcDoor, jvb, mcUSD(1)), - ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)); + XEnv(*this).tx(create_bridge(mcDoor, jvb, mcUSD(1)), ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)); // Reward amount is XRP and negative - XEnv(*this).tx( - create_bridge(mcDoor, jvb, XRP(-1)), - ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)); + XEnv(*this).tx(create_bridge(mcDoor, jvb, XRP(-1)), ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)); // Reward amount is 1 xrp => should succeed XEnv(*this).tx(create_bridge(mcDoor, jvb, XRP(1)), ter(tesSUCCESS)); // Min create amount is 1 xrp, mincreate is 1 xrp => should succeed - XEnv(*this).tx( - create_bridge(mcDoor, jvb, XRP(1), XRP(1)), ter(tesSUCCESS)); + XEnv(*this).tx(create_bridge(mcDoor, jvb, XRP(1), XRP(1)), ter(tesSUCCESS)); // Min create amount is non-xrp XEnv(*this).tx( - create_bridge(mcDoor, jvb, XRP(1), mcUSD(100)), - ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); + create_bridge(mcDoor, jvb, XRP(1), mcUSD(100)), ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); // Min create amount is zero (should fail, currently succeeds) - XEnv(*this).tx( - create_bridge(mcDoor, jvb, XRP(1), XRP(0)), - ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); + XEnv(*this).tx(create_bridge(mcDoor, jvb, XRP(1), XRP(0)), ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); // Min create amount is negative XEnv(*this).tx( - create_bridge(mcDoor, jvb, XRP(1), XRP(-1)), - ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); + create_bridge(mcDoor, jvb, XRP(1), XRP(-1)), ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); // coverage test: BridgeCreate::preflight() - create bridge when feature // disabled. @@ -513,20 +461,13 @@ struct XChain_test : public beast::unit_test::suite, // coverage test: BridgeCreate::preclaim() returns tecNO_ISSUER. XEnv(*this).tx( - create_bridge( - mcAlice, bridge(mcAlice, mcuAlice["USD"], mcBob, mcBob["USD"])), - ter(tecNO_ISSUER)); + create_bridge(mcAlice, bridge(mcAlice, mcuAlice["USD"], mcBob, mcBob["USD"])), ter(tecNO_ISSUER)); // coverage test: create_bridge transaction with incorrect flag - XEnv(*this).tx( - create_bridge(mcAlice, jvb), - txflags(tfFillOrKill), - ter(temINVALID_FLAG)); + XEnv(*this).tx(create_bridge(mcAlice, jvb), txflags(tfFillOrKill), ter(temINVALID_FLAG)); // coverage test: create_bridge transaction with xchain feature disabled - XEnv(*this) - .disableFeature(featureXChainBridge) - .tx(create_bridge(mcAlice, jvb), ter(temDISABLED)); + XEnv(*this).disableFeature(featureXChainBridge).tx(create_bridge(mcAlice, jvb), ter(temDISABLED)); } void @@ -611,39 +552,28 @@ struct XChain_test : public beast::unit_test::suite, // Add the exact same bridge to two different accounts (one locking // account and one issuing) env.tx(create_bridge(a3, bridge(a3, GUSD, a4, a4["USD"]))).close(); - env.tx(create_bridge(a4, bridge(a3, GUSD, a4, a4["USD"])), - ter(tecDUPLICATE)) - .close(); + env.tx(create_bridge(a4, bridge(a3, GUSD, a4, a4["USD"])), ter(tecDUPLICATE)).close(); // Add the exact same bridge to two different accounts (one issuing // account and one locking - opposite order from the test above) env.tx(create_bridge(a5, bridge(a6, GUSD, a5, a5["USD"]))).close(); - env.tx(create_bridge(a6, bridge(a6, GUSD, a5, a5["USD"])), - ter(tecDUPLICATE)) - .close(); + env.tx(create_bridge(a6, bridge(a6, GUSD, a5, a5["USD"])), ter(tecDUPLICATE)).close(); // Test case 1 ~ 5, create bridges auto const goodBridge1 = bridge(A, GUSD, B, BUSD); auto const goodBridge2 = bridge(A, BUSD, C, CUSD); env.tx(create_bridge(B, goodBridge1)).close(); // Issuing asset is the same, this is a duplicate - env.tx(create_bridge(B, bridge(A, GEUR, B, BUSD)), ter(tecDUPLICATE)) - .close(); + env.tx(create_bridge(B, bridge(A, GEUR, B, BUSD)), ter(tecDUPLICATE)).close(); env.tx(create_bridge(A, goodBridge2), ter(tesSUCCESS)).close(); // Locking asset is the same - this is a duplicate - env.tx(create_bridge(A, bridge(A, BUSD, B, BEUR)), ter(tecDUPLICATE)) - .close(); + env.tx(create_bridge(A, bridge(A, BUSD, B, BEUR)), ter(tecDUPLICATE)).close(); // Locking asset is USD - this is a duplicate even tho it has a // different issuer - env.tx(create_bridge(A, bridge(A, CUSD, B, BEUR)), ter(tecDUPLICATE)) - .close(); + env.tx(create_bridge(A, bridge(A, CUSD, B, BEUR)), ter(tecDUPLICATE)).close(); // Test case 6 and 7, commits - env.tx(trust(C, BUSD(1000))) - .tx(trust(A, BUSD(1000))) - .close() - .tx(pay(B, C, BUSD(1000))) - .close(); + env.tx(trust(C, BUSD(1000))).tx(trust(A, BUSD(1000))).close().tx(pay(B, C, BUSD(1000))).close(); auto const aBalanceStart = env.balance(A, BUSD); auto const cBalanceStart = env.balance(C, BUSD); env.tx(xchain_commit(C, goodBridge1, 1, BUSD(50))).close(); @@ -853,14 +783,10 @@ struct XChain_test : public beast::unit_test::suite, auto const& expected = expected_result[test_result.size()]; - mcEnv.tx( - create_bridge(a, bridge(a, ia, b, ib)), - ter(TER::fromInt(expected.first))); + mcEnv.tx(create_bridge(a, bridge(a, ia, b, ib)), ter(TER::fromInt(expected.first))); TER mcTER = mcEnv.env_.ter(); - scEnv.tx( - create_bridge(b, bridge(a, ia, b, ib)), - ter(TER::fromInt(expected.second))); + scEnv.tx(create_bridge(b, bridge(a, ia, b, ib)), ter(TER::fromInt(expected.second))); TER scTER = scEnv.env_.ter(); bool pass = mcTER == tesSUCCESS && scTER == tesSUCCESS; @@ -869,8 +795,7 @@ struct XChain_test : public beast::unit_test::suite, }; auto apply_ics = [&](auto const& lc, auto const& ics) { - std::apply( - [&](auto const&... ic) { (testcase(lc, ic), ...); }, ics); + std::apply([&](auto const&... ic) { (testcase(lc, ic), ...); }, ics); }; std::apply([&](auto const&... lc) { (apply_ics(lc, ics), ...); }, lcs); @@ -883,8 +808,7 @@ struct XChain_test : public beast::unit_test::suite, std::cout << "Markdown output for matrix test: " << fname << "\n"; auto print_res = [](auto tup) -> std::string { - std::string status = std::string(transToken(std::get<0>(tup))) + - " / " + transToken(std::get<1>(tup)); + std::string status = std::string(transToken(std::get<0>(tup))) + " / " + transToken(std::get<1>(tup)); if (std::get<2>(tup)) return status; @@ -902,19 +826,11 @@ struct XChain_test : public beast::unit_test::suite, // first two header lines res += "| `issuing ->` | "; - std::apply( - [&](auto const&... ic) { - ((res += ic.first, res += " | "), ...); - }, - ics); + std::apply([&](auto const&... ic) { ((res += ic.first, res += " | "), ...); }, ics); res += "\n"; res += "| :--- | "; - std::apply( - [&](auto const&... ic) { - (((void)ic.first, res += ":---: | "), ...); - }, - ics); + std::apply([&](auto const&... ic) { (((void)ic.first, res += ":---: | "), ...); }, ics); res += "\n"; auto output = [&](auto const& lc, auto const& ic) { @@ -927,13 +843,11 @@ struct XChain_test : public beast::unit_test::suite, res += "| "; res += lc.first; res += " | "; - std::apply( - [&](auto const&... ic) { (output(lc, ic), ...); }, ics); + std::apply([&](auto const&... ic) { (output(lc, ic), ...); }, ics); res += "\n"; }; - std::apply( - [&](auto const&... lc) { (output_ics(lc, ics), ...); }, lcs); + std::apply([&](auto const&... lc) { (output_ics(lc, ics), ...); }, lcs); return res; }; @@ -946,8 +860,8 @@ struct XChain_test : public beast::unit_test::suite, std::ofstream ofs(ter_fname); for (auto& t : test_result) { - ofs << "{ " << std::string(transToken(std::get<0>(t))) << ", " - << std::string(transToken(std::get<1>(t))) << "}\n,"; + ofs << "{ " << std::string(transToken(std::get<0>(t))) << ", " << std::string(transToken(std::get<1>(t))) + << "}\n,"; } #endif } @@ -960,11 +874,7 @@ struct XChain_test : public beast::unit_test::suite, // Changing a non-existent bridge should fail XEnv(*this).tx( - bridge_modify( - mcAlice, - bridge(mcAlice, mcGw["USD"], mcBob, mcBob["USD"]), - XRP(2), - std::nullopt), + bridge_modify(mcAlice, bridge(mcAlice, mcGw["USD"], mcBob, mcBob["USD"]), XRP(2), std::nullopt), ter(tecNO_ENTRY)); // must change something @@ -980,29 +890,21 @@ struct XChain_test : public beast::unit_test::suite, .tx(bridge_modify(mcDoor, jvb, {}, {}), ter(temMALFORMED)); // Reward amount is non-xrp - XEnv(*this).tx( - bridge_modify(mcDoor, jvb, mcUSD(2), XRP(10)), - ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)); + XEnv(*this).tx(bridge_modify(mcDoor, jvb, mcUSD(2), XRP(10)), ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)); // Reward amount is XRP and negative - XEnv(*this).tx( - bridge_modify(mcDoor, jvb, XRP(-2), XRP(10)), - ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)); + XEnv(*this).tx(bridge_modify(mcDoor, jvb, XRP(-2), XRP(10)), ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)); // Min create amount is non-xrp XEnv(*this).tx( - bridge_modify(mcDoor, jvb, XRP(2), mcUSD(10)), - ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); + bridge_modify(mcDoor, jvb, XRP(2), mcUSD(10)), ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); // Min create amount is zero - XEnv(*this).tx( - bridge_modify(mcDoor, jvb, XRP(2), XRP(0)), - ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); + XEnv(*this).tx(bridge_modify(mcDoor, jvb, XRP(2), XRP(0)), ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); // Min create amount is negative XEnv(*this).tx( - bridge_modify(mcDoor, jvb, XRP(2), XRP(-10)), - ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); + bridge_modify(mcDoor, jvb, XRP(2), XRP(-10)), ter(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT)); // First check the regular claim process (without bridge_modify) for (auto withClaim : {false, true}) @@ -1024,25 +926,9 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)) .close(); if (withClaim) @@ -1050,8 +936,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); } BEAST_EXPECT(transfer.has_happened(amt, split_reward_quorum)); @@ -1080,29 +965,12 @@ struct XChain_test : public beast::unit_test::suite, // Now modify the reward on the bridge mcEnv.tx(bridge_modify(mcDoor, jvb, XRP(2), XRP(10))).close(); - scEnv.tx(bridge_modify(Account::master, jvb, XRP(2), XRP(10))) - .close(); + scEnv.tx(bridge_modify(Account::master, jvb, XRP(2), XRP(10))).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)) .close(); if (withClaim) @@ -1110,8 +978,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); } // make sure the reward accounts indeed received the original @@ -1143,40 +1010,21 @@ struct XChain_test : public beast::unit_test::suite, // change signers - claim should not be processed is the batch // is signed by original signers - scEnv.tx(jtx::signers(Account::master, quorum, alt_signers)) - .close(); + scEnv.tx(jtx::signers(Account::master, quorum, alt_signers)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); // submit claim using outdated signers - should fail scEnv .multiTx( - claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers), + claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers), ter(tecNO_PERMISSION)) .close(); if (withClaim) { // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecXCHAIN_CLAIM_NO_QUORUM)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecXCHAIN_CLAIM_NO_QUORUM)).close(); } // make sure transfer has not happened as we sent attestations @@ -1184,40 +1032,26 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // submit claim using current signers - should succeed - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - alt_signers)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, alt_signers)) .close(); if (withClaim) { BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); } // make sure the transfer went through as we sent attestations // using new signers - BEAST_EXPECT( - transfer.has_happened(amt, split_reward_quorum, false)); + BEAST_EXPECT(transfer.has_happened(amt, split_reward_quorum, false)); } // coverage test: bridge_modify transaction with incorrect flag XEnv(*this) .tx(create_bridge(mcDoor, jvb)) .close() - .tx(bridge_modify(mcDoor, jvb, XRP(1), XRP(2)), - txflags(tfFillOrKill), - ter(temINVALID_FLAG)); + .tx(bridge_modify(mcDoor, jvb, XRP(1), XRP(2)), txflags(tfFillOrKill), ter(temINVALID_FLAG)); // coverage test: bridge_modify transaction with xchain feature // disabled @@ -1231,8 +1065,7 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this) .tx(create_bridge(mcDoor, jvb)) .close() - .tx(bridge_modify(mcAlice, jvb, XRP(1), XRP(2)), - ter(temXCHAIN_BRIDGE_NONDOOR_OWNER)); + .tx(bridge_modify(mcAlice, jvb, XRP(1), XRP(2)), ter(temXCHAIN_BRIDGE_NONDOOR_OWNER)); /** * test tfClearAccountCreateAmount flag in BridgeModify tx @@ -1243,18 +1076,13 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this) .tx(create_bridge(mcDoor, jvb, XRP(1), XRP(20))) .close() - .tx(sidechain_xchain_account_create( - mcAlice, jvb, scuAlice, XRP(100), reward)) + .tx(sidechain_xchain_account_create(mcAlice, jvb, scuAlice, XRP(100), reward)) .close() - .tx(bridge_modify(mcDoor, jvb, {}, XRP(2)), - txflags(tfClearAccountCreateAmount), - ter(temMALFORMED)) + .tx(bridge_modify(mcDoor, jvb, {}, XRP(2)), txflags(tfClearAccountCreateAmount), ter(temMALFORMED)) .close() - .tx(bridge_modify(mcDoor, jvb, XRP(3), {}), - txflags(tfClearAccountCreateAmount)) + .tx(bridge_modify(mcDoor, jvb, XRP(3), {}), txflags(tfClearAccountCreateAmount)) .close() - .tx(sidechain_xchain_account_create( - mcAlice, jvb, scuBob, XRP(100), XRP(3)), + .tx(sidechain_xchain_account_create(mcAlice, jvb, scuBob, XRP(100), XRP(3)), ter(tecXCHAIN_CREATE_ACCOUNT_DISABLED)) .close(); } @@ -1292,11 +1120,7 @@ struct XChain_test : public beast::unit_test::suite, // Non-existent bridge XEnv(*this, true) - .tx(xchain_create_claim_id( - scAlice, - bridge(mcAlice, mcAlice["USD"], scBob, scBob["USD"]), - reward, - mcAlice), + .tx(xchain_create_claim_id(scAlice, bridge(mcAlice, mcAlice["USD"], scBob, scBob["USD"]), reward, mcAlice), ter(tecNO_ENTRY)) .close(); @@ -1305,8 +1129,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(Account::master, jvb)) .fund(res1 - xrp_dust, scuAlice) // barely not enough .close() - .tx(xchain_create_claim_id(scuAlice, jvb, reward, mcAlice), - ter(tecINSUFFICIENT_RESERVE)) + .tx(xchain_create_claim_id(scuAlice, jvb, reward, mcAlice), ter(tecINSUFFICIENT_RESERVE)) .close(); // The specified reward doesn't match the reward on the bridge (test @@ -1315,17 +1138,14 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this, true) .tx(create_bridge(Account::master, jvb)) .close() - .tx(xchain_create_claim_id( - scAlice, jvb, split_reward_quorum, mcAlice), - ter(tecXCHAIN_REWARD_MISMATCH)) + .tx(xchain_create_claim_id(scAlice, jvb, split_reward_quorum, mcAlice), ter(tecXCHAIN_REWARD_MISMATCH)) .close(); // A reward amount that isn't XRP XEnv(*this, true) .tx(create_bridge(Account::master, jvb)) .close() - .tx(xchain_create_claim_id(scAlice, jvb, mcUSD(1), mcAlice), - ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)) + .tx(xchain_create_claim_id(scAlice, jvb, mcUSD(1), mcAlice), ter(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT)) .close(); // coverage test: xchain_create_claim_id transaction with incorrect @@ -1333,9 +1153,7 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this, true) .tx(create_bridge(Account::master, jvb)) .close() - .tx(xchain_create_claim_id(scAlice, jvb, reward, mcAlice), - txflags(tfFillOrKill), - ter(temINVALID_FLAG)) + .tx(xchain_create_claim_id(scAlice, jvb, reward, mcAlice), txflags(tfFillOrKill), ter(temINVALID_FLAG)) .close(); // coverage test: xchain_create_claim_id transaction with xchain @@ -1344,8 +1162,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(Account::master, jvb)) .disableFeature(featureXChainBridge) .close() - .tx(xchain_create_claim_id(scAlice, jvb, reward, mcAlice), - ter(temDISABLED)) + .tx(xchain_create_claim_id(scAlice, jvb, reward, mcAlice), ter(temDISABLED)) .close(); } @@ -1359,8 +1176,7 @@ struct XChain_test : public beast::unit_test::suite, testcase("Commit"); // Commit to a non-existent bridge - XEnv(*this).tx( - xchain_commit(mcAlice, jvb, 1, one_xrp, scBob), ter(tecNO_ENTRY)); + XEnv(*this).tx(xchain_commit(mcAlice, jvb, 1, one_xrp, scBob), ter(tecNO_ENTRY)); // check that reward not deducted when doing the commit { @@ -1369,10 +1185,7 @@ struct XChain_test : public beast::unit_test::suite, Balance alice_bal(xenv, mcAlice); auto const amt = XRP(1000); - xenv.tx(create_bridge(mcDoor, jvb)) - .close() - .tx(xchain_commit(mcAlice, jvb, 1, amt, scBob)) - .close(); + xenv.tx(create_bridge(mcDoor, jvb)).close().tx(xchain_commit(mcAlice, jvb, 1, amt, scBob)).close(); STAmount claim_cost = amt; BEAST_EXPECT(alice_bal.diff() == -(claim_cost + tx_fee)); @@ -1382,8 +1195,7 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this) .tx(create_bridge(mcDoor, jvb)) .close() - .tx(xchain_commit(mcAlice, jvb, 1, XRP(-1), scBob), - ter(temBAD_AMOUNT)); + .tx(xchain_commit(mcAlice, jvb, 1, XRP(-1), scBob), ter(temBAD_AMOUNT)); // Commit an amount whose issue that does not match the expected // issue on the bridge (either LockingChainIssue or @@ -1391,8 +1203,7 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this) .tx(create_bridge(mcDoor, jvb)) .close() - .tx(xchain_commit(mcAlice, jvb, 1, mcUSD(100), scBob), - ter(temBAD_ISSUER)); + .tx(xchain_commit(mcAlice, jvb, 1, mcUSD(100), scBob), ter(temBAD_ISSUER)); // Commit an amount that would put the sender below the required // reserve (if XRP) @@ -1400,8 +1211,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(mcDoor, jvb)) .fund(res0 + one_xrp - xrp_dust, mcuAlice) // barely not enough .close() - .tx(xchain_commit(mcuAlice, jvb, 1, one_xrp, scBob), - ter(tecUNFUNDED_PAYMENT)); + .tx(xchain_commit(mcuAlice, jvb, 1, one_xrp, scBob), ter(tecUNFUNDED_PAYMENT)); XEnv(*this) .tx(create_bridge(mcDoor, jvb)) @@ -1417,8 +1227,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(mcDoor, jvb)) .fund(res0, mcuAlice) // barely not enough .close() - .tx(xchain_commit(mcuAlice, jvb, 1, res0 + one_xrp, scBob), - ter(tecUNFUNDED_PAYMENT)); + .tx(xchain_commit(mcuAlice, jvb, 1, res0 + one_xrp, scBob), ter(tecUNFUNDED_PAYMENT)); auto jvb_USD = bridge(mcDoor, mcUSD, scGw, scUSD); @@ -1434,16 +1243,14 @@ struct XChain_test : public beast::unit_test::suite, .tx(trust(mcDoor, mcUSD(10000))) // door needs to have a trustline .tx(create_bridge(mcDoor, jvb_USD)) .close() - .tx(xchain_commit(mcDoor, jvb_USD, 1, mcUSD(1), scBob), - ter(tecXCHAIN_SELF_COMMIT)); + .tx(xchain_commit(mcDoor, jvb_USD, 1, mcUSD(1), scBob), ter(tecXCHAIN_SELF_COMMIT)); // commit sent from mcAlice which has no IOU balance => should fail XEnv(*this) .tx(trust(mcDoor, mcUSD(10000))) // door needs to have a trustline .tx(create_bridge(mcDoor, jvb_USD)) .close() - .tx(xchain_commit(mcAlice, jvb_USD, 1, mcUSD(1), scBob), - ter(terNO_LINE)); + .tx(xchain_commit(mcAlice, jvb_USD, 1, mcUSD(1), scBob), ter(terNO_LINE)); // commit sent from mcAlice which has no IOU balance => should fail // just changed the destination to scGw (which is the door account @@ -1452,8 +1259,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(trust(mcDoor, mcUSD(10000))) // door needs to have a trustline .tx(create_bridge(mcDoor, jvb_USD)) .close() - .tx(xchain_commit(mcAlice, jvb_USD, 1, mcUSD(1), scGw), - ter(terNO_LINE)); + .tx(xchain_commit(mcAlice, jvb_USD, 1, mcUSD(1), scGw), ter(terNO_LINE)); // commit sent from mcAlice which has a IOU balance => should // succeed @@ -1471,9 +1277,7 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this) .tx(create_bridge(mcDoor)) .close() - .tx(xchain_commit(mcAlice, jvb, 1, one_xrp, scBob), - txflags(tfFillOrKill), - ter(temINVALID_FLAG)); + .tx(xchain_commit(mcAlice, jvb, 1, one_xrp, scBob), txflags(tfFillOrKill), ter(temINVALID_FLAG)); // coverage test: xchain_commit transaction with xchain feature // disabled @@ -1481,8 +1285,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(mcDoor)) .disableFeature(featureXChainBridge) .close() - .tx(xchain_commit(mcAlice, jvb, 1, one_xrp, scBob), - ter(temDISABLED)); + .tx(xchain_commit(mcAlice, jvb, 1, one_xrp, scBob), ter(temDISABLED)); } void @@ -1494,9 +1297,7 @@ struct XChain_test : public beast::unit_test::suite, XRPAmount res0 = reserve(0); XRPAmount tx_fee = txFee(); - auto multiTtxFee = [&](std::uint32_t m) -> STAmount { - return multiply(tx_fee, STAmount(m), xrpIssue()); - }; + auto multiTtxFee = [&](std::uint32_t m) -> STAmount { return multiply(tx_fee, STAmount(m), xrpIssue()); }; // Add an attestation to a claim id that has already reached quorum. // This should succeed and share in the reward. @@ -1524,21 +1325,11 @@ struct XChain_test : public beast::unit_test::suite, auto const amt = XRP(1000); mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, Account::master, scBob, scAlice, payees, withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, payees, withClaim); scEnv .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers, - UT_XCHAIN_DEFAULT_QUORUM)) + scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers, UT_XCHAIN_DEFAULT_QUORUM)) .close(); scEnv .tx(claim_attestation( @@ -1558,8 +1349,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); BEAST_EXPECT(!scEnv.claimID(jvb, claimID)); // claim id deleted BEAST_EXPECT(scEnv.claimID(jvb) == claimID); } @@ -1609,27 +1399,9 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - 3, - withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, &payees[0], 3, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers_, - 3)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers_, 3)) .close(); if (withClaim) @@ -1637,14 +1409,12 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); } BEAST_EXPECT(!scEnv.claimID(jvb, 1)); // claim id deleted - BEAST_EXPECT(transfer.has_happened( - amt, divide(reward, STAmount(3), reward.issue()))); + BEAST_EXPECT(transfer.has_happened(amt, divide(reward, STAmount(3), reward.issue()))); } // 4,4 => should succeed @@ -1668,8 +1438,7 @@ struct XChain_test : public beast::unit_test::suite, } return result; }(); - STAmount const split_reward_ = - divide(reward, STAmount(signers_.size()), reward.issue()); + STAmount const split_reward_ = divide(reward, STAmount(signers_.size()), reward.issue()); mcEnv.tx(create_bridge(mcDoor, jvb)).close(); @@ -1686,28 +1455,9 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[2], - 2, - withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, &payees[2], 2, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers_, - 2, - 2)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers_, 2, 2)) .close(); if (withClaim) @@ -1715,14 +1465,12 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); } BEAST_EXPECT(!scEnv.claimID(jvb, claimID)); // claim id deleted - BEAST_EXPECT(transfer.has_happened( - amt, divide(reward, STAmount(2), reward.issue()))); + BEAST_EXPECT(transfer.has_happened(amt, divide(reward, STAmount(2), reward.issue()))); } // 1,2 => should fail @@ -1762,41 +1510,19 @@ struct XChain_test : public beast::unit_test::suite, auto const amt = XRP(1000); mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - 2, - withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, &payees[0], 2, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers_, - 2)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers_, 2)) .close(); if (withClaim) { BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecXCHAIN_CLAIM_NO_QUORUM)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecXCHAIN_CLAIM_NO_QUORUM)).close(); } - BEAST_EXPECT( - !!scEnv.claimID(jvb, claimID)); // claim id still present + BEAST_EXPECT(!!scEnv.claimID(jvb, claimID)); // claim id still present BEAST_EXPECT(transfer.has_not_happened()); } @@ -1838,28 +1564,9 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[1], - 2, - withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, &payees[1], 2, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers_, - 2, - 1)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers_, 2, 1)) .close(); if (withClaim) @@ -1867,14 +1574,10 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecXCHAIN_CLAIM_NO_QUORUM)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecXCHAIN_CLAIM_NO_QUORUM)).close(); } - BEAST_EXPECT( - !!scEnv.claimID(jvb, claimID)); // claim id still present + BEAST_EXPECT(!!scEnv.claimID(jvb, claimID)); // claim id still present BEAST_EXPECT(transfer.has_not_happened()); } @@ -1894,18 +1597,12 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(create_bridge(mcDoor, jvb, reward, XRP(20))) .close() - .tx(sidechain_xchain_account_create( - mcAlice, jvb, scuAlice, amt, reward)) - .tx(sidechain_xchain_account_create( - mcBob, jvb, scuBob, amt, reward)) - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuCarol, amt, reward)) + .tx(sidechain_xchain_account_create(mcAlice, jvb, scuAlice, amt, reward)) + .tx(sidechain_xchain_account_create(mcBob, jvb, scuBob, amt, reward)) + .tx(sidechain_xchain_account_create(mcCarol, jvb, scuCarol, amt, reward)) .close(); - BEAST_EXPECT( - door.diff() == - (multiply(amt_plus_reward, STAmount(3), xrpIssue()) - - tx_fee)); + BEAST_EXPECT(door.diff() == (multiply(amt_plus_reward, STAmount(3), xrpIssue()) - tx_fee)); BEAST_EXPECT(carol.diff() == -(amt + reward + tx_fee)); } @@ -1928,11 +1625,10 @@ struct XChain_test : public beast::unit_test::suite, // att_create_acct_vec return vectors of size 2, so 2*3 txns BEAST_EXPECT(attester.diff() == -multiTtxFee(6)); - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // ca claim id present - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 2)); // ca claim id present - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 3)); // ca claim id present - BEAST_EXPECT( - scEnv.claimCount(jvb) == 0); // claim count still 0 + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // ca claim id present + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 2)); // ca claim id present + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 3)); // ca claim id present + BEAST_EXPECT(scEnv.claimCount(jvb) == 0); // claim count still 0 } { @@ -1941,16 +1637,14 @@ struct XChain_test : public beast::unit_test::suite, Balance attester(scEnv, scAttester); Balance door(scEnv, Account::master); - scEnv.multiTx(att_create_acct_vec(2, amt, scuBob, 3, 2)) - .close(); + scEnv.multiTx(att_create_acct_vec(2, amt, scuBob, 3, 2)).close(); BEAST_EXPECT(door.diff() == STAmount(0)); // att_create_acct_vec return vectors of size 3, so 3 txns BEAST_EXPECT(attester.diff() == -multiTtxFee(3)); - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 2)); // ca claim id present - BEAST_EXPECT( - scEnv.claimCount(jvb) == 0); // claim count still 0 + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 2)); // ca claim id present + BEAST_EXPECT(scEnv.claimCount(jvb) == 0); // claim count still 0 } { @@ -1959,16 +1653,14 @@ struct XChain_test : public beast::unit_test::suite, Balance attester(scEnv, scAttester); Balance door(scEnv, Account::master); - scEnv.multiTx(att_create_acct_vec(3, amt, scuCarol, 3, 2)) - .close(); + scEnv.multiTx(att_create_acct_vec(3, amt, scuCarol, 3, 2)).close(); BEAST_EXPECT(door.diff() == STAmount(0)); // att_create_acct_vec return vectors of size 3, so 3 txns BEAST_EXPECT(attester.diff() == -multiTtxFee(3)); - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 3)); // ca claim id present - BEAST_EXPECT( - scEnv.claimCount(jvb) == 0); // claim count still 0 + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 3)); // ca claim id present + BEAST_EXPECT(scEnv.claimCount(jvb) == 0); // claim count still 0 } { @@ -1977,8 +1669,7 @@ struct XChain_test : public beast::unit_test::suite, Balance attester(scEnv, scAttester); Balance door(scEnv, Account::master); - scEnv.multiTx(att_create_acct_vec(1, amt, scuAlice, 3, 1)) - .close(); + scEnv.multiTx(att_create_acct_vec(1, amt, scuAlice, 3, 1)).close(); BEAST_EXPECT(door.diff() == -amt_plus_reward); // att_create_acct_vec return vectors of size 3, so 3 txns @@ -1997,17 +1688,15 @@ struct XChain_test : public beast::unit_test::suite, Balance attester(scEnv, scAttester); Balance door(scEnv, Account::master); - scEnv.multiTx(att_create_acct_vec(3, amt, scuCarol, 3, 2)) - .close(); + scEnv.multiTx(att_create_acct_vec(3, amt, scuCarol, 3, 2)).close(); BEAST_EXPECT(door.diff() == STAmount(0)); // att_create_acct_vec return vectors of size 3, so 3 txns BEAST_EXPECT(attester.diff() == -multiTtxFee(3)); - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 2)); // claim id 2 present - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 3)); // claim id 3 present - BEAST_EXPECT( - scEnv.claimCount(jvb) == 1); // claim count still 1 + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 2)); // claim id 2 present + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 3)); // claim id 3 present + BEAST_EXPECT(scEnv.claimCount(jvb) == 1); // claim count still 1 } { @@ -2058,10 +1747,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); Balance carol(mcEnv, mcCarol); - mcEnv - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuAlice, amt, reward)) - .close(); + mcEnv.tx(sidechain_xchain_account_create(mcCarol, jvb, scuAlice, amt, reward)).close(); BEAST_EXPECT(door.diff() == amt_plus_reward); BEAST_EXPECT(carol.diff() == -(amt_plus_reward + tx_fee)); @@ -2075,14 +1761,12 @@ struct XChain_test : public beast::unit_test::suite, Balance door(scEnv, Account::master); scEnv.multiTx(att_create_acct_vec(1, amt, scuAlice, 2)).close(); - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // claim id present - BEAST_EXPECT( - scEnv.claimCount(jvb) == 0); // claim count is one less + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // claim id present + BEAST_EXPECT(scEnv.claimCount(jvb) == 0); // claim count is one less scEnv.multiTx(att_create_acct_vec(1, amt, scuAlice, 2, 2)).close(); - BEAST_EXPECT(!scEnv.caClaimID(jvb, 1)); // claim id deleted - BEAST_EXPECT( - scEnv.claimCount(jvb) == 1); // claim count was incremented + BEAST_EXPECT(!scEnv.caClaimID(jvb, 1)); // claim id deleted + BEAST_EXPECT(scEnv.claimCount(jvb) == 1); // claim count was incremented BEAST_EXPECT(attester.diff() == -multiTtxFee(4)); BEAST_EXPECT(door.diff() == -reward); @@ -2104,10 +1788,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); Balance carol(mcEnv, mcCarol); - mcEnv - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scAlice, amt, reward)) - .close(); + mcEnv.tx(sidechain_xchain_account_create(mcCarol, jvb, scAlice, amt, reward)).close(); BEAST_EXPECT(door.diff() == amt_plus_reward); BEAST_EXPECT(carol.diff() == -(amt_plus_reward + tx_fee)); @@ -2122,14 +1803,12 @@ struct XChain_test : public beast::unit_test::suite, Balance alice(scEnv, scAlice); scEnv.multiTx(att_create_acct_vec(1, amt, scAlice, 2)).close(); - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // claim id present - BEAST_EXPECT( - scEnv.claimCount(jvb) == 0); // claim count is one less + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // claim id present + BEAST_EXPECT(scEnv.claimCount(jvb) == 0); // claim count is one less scEnv.multiTx(att_create_acct_vec(1, amt, scAlice, 2, 2)).close(); - BEAST_EXPECT(!scEnv.caClaimID(jvb, 1)); // claim id deleted - BEAST_EXPECT( - scEnv.claimCount(jvb) == 1); // claim count was incremented + BEAST_EXPECT(!scEnv.caClaimID(jvb, 1)); // claim id deleted + BEAST_EXPECT(scEnv.claimCount(jvb) == 1); // claim count was incremented BEAST_EXPECT(door.diff() == -amt_plus_reward); BEAST_EXPECT(attester.diff() == -multiTtxFee(4)); @@ -2151,10 +1830,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); Balance carol(mcEnv, mcCarol); - mcEnv - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scAlice, amt, reward)) - .close(); + mcEnv.tx(sidechain_xchain_account_create(mcCarol, jvb, scAlice, amt, reward)).close(); BEAST_EXPECT(door.diff() == amt_plus_reward); BEAST_EXPECT(carol.diff() == -(amt_plus_reward + tx_fee)); @@ -2170,14 +1846,12 @@ struct XChain_test : public beast::unit_test::suite, Balance alice(scEnv, scAlice); scEnv.multiTx(att_create_acct_vec(1, amt, scAlice, 2)).close(); - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // claim id present - BEAST_EXPECT( - scEnv.claimCount(jvb) == 0); // claim count is one less + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // claim id present + BEAST_EXPECT(scEnv.claimCount(jvb) == 0); // claim count is one less scEnv.multiTx(att_create_acct_vec(1, amt, scAlice, 2, 2)).close(); - BEAST_EXPECT(!scEnv.caClaimID(jvb, 1)); // claim id deleted - BEAST_EXPECT( - scEnv.claimCount(jvb) == 1); // claim count was incremented + BEAST_EXPECT(!scEnv.caClaimID(jvb, 1)); // claim id deleted + BEAST_EXPECT(scEnv.claimCount(jvb) == 1); // claim count was incremented BEAST_EXPECT(door.diff() == -reward); BEAST_EXPECT(attester.diff() == -multiTtxFee(4)); @@ -2201,20 +1875,14 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(create_bridge(mcDoor, jvb, reward, XRP(20))) .close() - .tx(sidechain_xchain_account_create( - mcAlice, jvb, scuAlice, amt, reward)) + .tx(sidechain_xchain_account_create(mcAlice, jvb, scuAlice, amt, reward)) .close() // make sure Alice gets claim #1 - .tx(sidechain_xchain_account_create( - mcBob, jvb, scuBob, amt, reward)) + .tx(sidechain_xchain_account_create(mcBob, jvb, scuBob, amt, reward)) .close() // make sure Bob gets claim #2 - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuCarol, amt, reward)) + .tx(sidechain_xchain_account_create(mcCarol, jvb, scuCarol, amt, reward)) .close(); // and Carol will get claim #3 - BEAST_EXPECT( - door.diff() == - (multiply(amt_plus_reward, STAmount(3), xrpIssue()) - - tx_fee)); + BEAST_EXPECT(door.diff() == (multiply(amt_plus_reward, STAmount(3), xrpIssue()) - tx_fee)); BEAST_EXPECT(carol.diff() == -(amt + reward + tx_fee)); } @@ -2251,58 +1919,42 @@ struct XChain_test : public beast::unit_test::suite, .close(); txCount += 3; - BEAST_EXPECTS( - !!scEnv.caClaimID(jvb, 1), "claim id 1 still there"); - BEAST_EXPECTS( - !!scEnv.caClaimID(jvb, 2), "claim id 2 still there"); - BEAST_EXPECTS( - !!scEnv.caClaimID(jvb, 3), "claim id 3 still there"); - BEAST_EXPECTS( - scEnv.claimCount(jvb) == 0, "No account created yet"); + BEAST_EXPECTS(!!scEnv.caClaimID(jvb, 1), "claim id 1 still there"); + BEAST_EXPECTS(!!scEnv.caClaimID(jvb, 2), "claim id 2 still there"); + BEAST_EXPECTS(!!scEnv.caClaimID(jvb, 3), "claim id 3 still there"); + BEAST_EXPECTS(scEnv.claimCount(jvb) == 0, "No account created yet"); - scEnv.multiTx(att_create_acct_vec(3, amt, scuCarol, 1, 1)) - .close(); + scEnv.multiTx(att_create_acct_vec(3, amt, scuCarol, 1, 1)).close(); txCount += 1; - BEAST_EXPECTS( - !!scEnv.caClaimID(jvb, 3), "claim id 3 still there"); - BEAST_EXPECTS( - scEnv.claimCount(jvb) == 0, "No account created yet"); + BEAST_EXPECTS(!!scEnv.caClaimID(jvb, 3), "claim id 3 still there"); + BEAST_EXPECTS(scEnv.claimCount(jvb) == 0, "No account created yet"); - scEnv.multiTx(att_create_acct_vec(1, amt, scuAlice, 1, 2)) - .close(); + scEnv.multiTx(att_create_acct_vec(1, amt, scuAlice, 1, 2)).close(); txCount += 1; BEAST_EXPECTS(!scEnv.caClaimID(jvb, 1), "claim id 1 deleted"); BEAST_EXPECTS(scEnv.claimCount(jvb) == 1, "scuAlice created"); scEnv.multiTx(att_create_acct_vec(2, amt, scuBob, 1, 3)) - .multiTx( - att_create_acct_vec(1, amt, scuAlice, 1, 3), - ter(tecXCHAIN_ACCOUNT_CREATE_PAST)) + .multiTx(att_create_acct_vec(1, amt, scuAlice, 1, 3), ter(tecXCHAIN_ACCOUNT_CREATE_PAST)) .close(); txCount += 2; BEAST_EXPECTS(!scEnv.caClaimID(jvb, 2), "claim id 2 deleted"); BEAST_EXPECTS(!scEnv.caClaimID(jvb, 1), "claim id 1 not added"); - BEAST_EXPECTS( - scEnv.claimCount(jvb) == 2, "scuAlice & scuBob created"); + BEAST_EXPECTS(scEnv.claimCount(jvb) == 2, "scuAlice & scuBob created"); - scEnv.multiTx(att_create_acct_vec(3, amt, scuCarol, 1, 0)) - .close(); + scEnv.multiTx(att_create_acct_vec(3, amt, scuCarol, 1, 0)).close(); txCount += 1; BEAST_EXPECTS(!scEnv.caClaimID(jvb, 3), "claim id 3 deleted"); - BEAST_EXPECTS( - scEnv.claimCount(jvb) == 3, "All 3 accounts created"); + BEAST_EXPECTS(scEnv.claimCount(jvb) == 3, "All 3 accounts created"); // because of the division of the rewards among attesters, // sometimes a couple drops are left over unspent in the // door account (here 2 drops) - BEAST_EXPECT( - multiply(amt_plus_reward, STAmount(3), xrpIssue()) + - door.diff() < - drops(3)); + BEAST_EXPECT(multiply(amt_plus_reward, STAmount(3), xrpIssue()) + door.diff() < drops(3)); BEAST_EXPECT(attester.diff() == -multiTtxFee(txCount)); BEAST_EXPECT(scEnv.balance(scuAlice) == amt); BEAST_EXPECT(scEnv.balance(scuBob) == amt); @@ -2320,16 +1972,7 @@ struct XChain_test : public beast::unit_test::suite, scEnv.tx(create_bridge(Account::master, jvb)) .tx(jtx::signers(Account::master, quorum, signers)) .close() - .tx(claim_attestation( - scAttester, - jvb, - mcAlice, - XRP(1000), - payees[0], - true, - 1, - {}, - signers[0]), + .tx(claim_attestation(scAttester, jvb, mcAlice, XRP(1000), payees[0], true, 1, {}, signers[0]), txflags(tfFillOrKill), ter(temINVALID_FLAG)) .close(); @@ -2343,16 +1986,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(jtx::signers(Account::master, quorum, signers)) .disableFeature(featureXChainBridge) .close() - .tx(claim_attestation( - scAttester, - jvb, - mcAlice, - XRP(1000), - payees[0], - true, - 1, - {}, - signers[0]), + .tx(claim_attestation(scAttester, jvb, mcAlice, XRP(1000), payees[0], true, 1, {}, signers[0]), ter(temDISABLED)) .close(); } @@ -2388,19 +2022,10 @@ struct XChain_test : public beast::unit_test::suite, for (int i = 0; i < signers.size(); ++i) { - auto const att = claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[i], - true, - claimID, - dst, - signers[i]); + auto const att = + claim_attestation(scAttester, jvb, mcAlice, amt, payees[i], true, claimID, dst, signers[i]); - TER const expectedTER = - i < quorum ? tesSUCCESS : TER{tecXCHAIN_NO_CLAIM_ID}; + TER const expectedTER = i < quorum ? tesSUCCESS : TER{tecXCHAIN_NO_CLAIM_ID}; if (i + 1 == quorum) scEnv.tx(att, ter(expectedTER)).close(); else @@ -2409,8 +2034,7 @@ struct XChain_test : public beast::unit_test::suite, if (i + 1 < quorum) BEAST_EXPECT(dstStartBalance == scEnv.env_.balance(dst)); else - BEAST_EXPECT( - dstStartBalance + amt == scEnv.env_.balance(dst)); + BEAST_EXPECT(dstStartBalance + amt == scEnv.env_.balance(dst)); } BEAST_EXPECT(dstStartBalance + amt == scEnv.env_.balance(dst)); } @@ -2454,47 +2078,25 @@ struct XChain_test : public beast::unit_test::suite, { // G1: master key - auto att = claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[0], - true, - claimID, - dst, - alt_signers[0]); + auto att = + claim_attestation(scAttester, jvb, mcAlice, amt, payees[0], true, claimID, dst, alt_signers[0]); scEnv.tx(att).close(); } { // G2: regular key // alt_signers[0] is the regular key of alt_signers[1] // There should be 2 attestations after the transaction - scEnv - .tx(jtx::regkey( - alt_signers[1].account, alt_signers[0].account)) - .close(); - auto att = claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[1], - true, - claimID, - dst, - alt_signers[0]); - att[sfAttestationSignerAccount.getJsonName()] = - alt_signers[1].account.human(); + scEnv.tx(jtx::regkey(alt_signers[1].account, alt_signers[0].account)).close(); + auto att = + claim_attestation(scAttester, jvb, mcAlice, amt, payees[1], true, claimID, dst, alt_signers[0]); + att[sfAttestationSignerAccount.getJsonName()] = alt_signers[1].account.human(); scEnv.tx(att).close(); } { // B3: public key and non-exist (unfunded) account mismatch // G3: public key and non-exist (unfunded) account match - auto const unfundedSigner1 = - alt_signers[UT_XCHAIN_DEFAULT_NUM_SIGNERS - 1]; - auto const unfundedSigner2 = - alt_signers[UT_XCHAIN_DEFAULT_NUM_SIGNERS - 2]; + auto const unfundedSigner1 = alt_signers[UT_XCHAIN_DEFAULT_NUM_SIGNERS - 1]; + auto const unfundedSigner2 = alt_signers[UT_XCHAIN_DEFAULT_NUM_SIGNERS - 2]; auto att = claim_attestation( scAttester, jvb, @@ -2505,83 +2107,41 @@ struct XChain_test : public beast::unit_test::suite, claimID, dst, unfundedSigner1); - att[sfAttestationSignerAccount.getJsonName()] = - unfundedSigner2.account.human(); - scEnv.tx(att, ter(tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR)) - .close(); - att[sfAttestationSignerAccount.getJsonName()] = - unfundedSigner1.account.human(); + att[sfAttestationSignerAccount.getJsonName()] = unfundedSigner2.account.human(); + scEnv.tx(att, ter(tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR)).close(); + att[sfAttestationSignerAccount.getJsonName()] = unfundedSigner1.account.human(); scEnv.tx(att).close(); } { // B2: single item signer list std::vector tempSignerList = {signers[0]}; - scEnv.tx( - jtx::signers(alt_signers[2].account, 1, tempSignerList)); + scEnv.tx(jtx::signers(alt_signers[2].account, 1, tempSignerList)); auto att = claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[2], - true, - claimID, - dst, - tempSignerList.front()); - att[sfAttestationSignerAccount.getJsonName()] = - alt_signers[2].account.human(); - scEnv.tx(att, ter(tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR)) - .close(); + scAttester, jvb, mcAlice, amt, payees[2], true, claimID, dst, tempSignerList.front()); + att[sfAttestationSignerAccount.getJsonName()] = alt_signers[2].account.human(); + scEnv.tx(att, ter(tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR)).close(); } { // B1: disabled master key - scEnv.tx(fset(alt_signers[2].account, asfDisableMaster, 0)) - .close(); - auto att = claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[2], - true, - claimID, - dst, - alt_signers[2]); - scEnv.tx(att, ter(tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR)) - .close(); + scEnv.tx(fset(alt_signers[2].account, asfDisableMaster, 0)).close(); + auto att = + claim_attestation(scAttester, jvb, mcAlice, amt, payees[2], true, claimID, dst, alt_signers[2]); + scEnv.tx(att, ter(tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR)).close(); } { // --B4: not on signer list - auto att = claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[0], - true, - claimID, - dst, - signers[0]); + auto att = claim_attestation(scAttester, jvb, mcAlice, amt, payees[0], true, claimID, dst, signers[0]); scEnv.tx(att, ter(tecNO_PERMISSION)).close(); } { // --B5: missing sfAttestationSignerAccount field // Then submit the one with the field. Should reach quorum. - auto att = claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[3], - true, - claimID, - dst, - alt_signers[3]); + auto att = + claim_attestation(scAttester, jvb, mcAlice, amt, payees[3], true, claimID, dst, alt_signers[3]); att.removeMember(sfAttestationSignerAccount.getJsonName()); scEnv.tx(att, ter(temMALFORMED)).close(); BEAST_EXPECT(dstStartBalance == scEnv.env_.balance(dst)); - att[sfAttestationSignerAccount.getJsonName()] = - alt_signers[3].account.human(); + att[sfAttestationSignerAccount.getJsonName()] = alt_signers[3].account.human(); scEnv.tx(att).close(); BEAST_EXPECT(dstStartBalance + amt == scEnv.env_.balance(dst)); } @@ -2628,10 +2188,7 @@ struct XChain_test : public beast::unit_test::suite, Balance bal_doorA(mcEnv, doorA); Balance bal_a(mcEnv, a); - mcEnv - .tx(sidechain_xchain_account_create( - a, xrp_b.jvb, ua, amt, xrp_b.reward)) - .close(); + mcEnv.tx(sidechain_xchain_account_create(a, xrp_b.jvb, ua, amt, xrp_b.reward)).close(); BEAST_EXPECT(bal_doorA.diff() == amt_plus_reward); BEAST_EXPECT(bal_a.diff() == -(amt_plus_reward + tx_fee)); @@ -2640,19 +2197,8 @@ struct XChain_test : public beast::unit_test::suite, for (int i = 0; i < signers.size(); ++i) { auto const att = create_account_attestation( - signers[0].account, - xrp_b.jvb, - a, - amt, - xrp_b.reward, - signers[i].account, - true, - 1, - ua, - signers[i]); - TER const expectedTER = i < xrp_b.quorum - ? tesSUCCESS - : TER{tecXCHAIN_ACCOUNT_CREATE_PAST}; + signers[0].account, xrp_b.jvb, a, amt, xrp_b.reward, signers[i].account, true, 1, ua, signers[i]); + TER const expectedTER = i < xrp_b.quorum ? tesSUCCESS : TER{tecXCHAIN_ACCOUNT_CREATE_PAST}; scEnv.tx(att, ter(expectedTER)).close(); if (i + 1 < xrp_b.quorum) @@ -2696,33 +2242,16 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)) .close(); if (withClaim) { BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); } BEAST_EXPECT(transfer.has_happened(amt, split_reward_quorum)); @@ -2750,27 +2279,11 @@ struct XChain_test : public beast::unit_test::suite, std::uint32_t const claimID = 1; mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - 1, - withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, &payees[0], 1, withClaim); jtx::signer master_signer(Account::master); scEnv - .tx(claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[0], - true, - claimID, - dst, - master_signer), + .tx(claim_attestation(scAttester, jvb, mcAlice, amt, payees[0], true, claimID, dst, master_signer), ter(tecXCHAIN_NO_SIGNERS_LIST)) .close(); @@ -2801,27 +2314,11 @@ struct XChain_test : public beast::unit_test::suite, std::uint32_t const claimID = 1; mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - 1, - withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, &payees[0], 1, withClaim); jtx::signer master_signer(payees[0]); scEnv - .tx(claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[0], - true, - claimID, - dst, - master_signer), + .tx(claim_attestation(scAttester, jvb, mcAlice, amt, payees[0], true, claimID, dst, master_signer), ter(tecXCHAIN_NO_SIGNERS_LIST)) .close(); @@ -2837,38 +2334,22 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(create_bridge(mcDoor, jvb)).close(); - auto jvb_unknown = - bridge(mcBob, xrpIssue(), Account::master, xrpIssue()); + auto jvb_unknown = bridge(mcBob, xrpIssue(), Account::master, xrpIssue()); scEnv.tx(create_bridge(Account::master, jvb)) .tx(jtx::signers(Account::master, quorum, signers)) .close() - .tx(xchain_create_claim_id( - scAlice, jvb_unknown, reward, mcAlice), - ter(tecNO_ENTRY)) + .tx(xchain_create_claim_id(scAlice, jvb_unknown, reward, mcAlice), ter(tecNO_ENTRY)) .close(); auto dst(withClaim ? std::nullopt : std::optional{scBob}); auto const amt = XRP(1000); std::uint32_t const claimID = 1; - mcEnv - .tx(xchain_commit(mcAlice, jvb_unknown, claimID, amt, dst), - ter(tecNO_ENTRY)) - .close(); + mcEnv.tx(xchain_commit(mcAlice, jvb_unknown, claimID, amt, dst), ter(tecNO_ENTRY)).close(); - BalanceTransfer transfer( - scEnv, Account::master, scBob, scAlice, payees, withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, payees, withClaim); scEnv - .tx(claim_attestation( - scAttester, - jvb_unknown, - mcAlice, - amt, - payees[0], - true, - claimID, - dst, - signers[0]), + .tx(claim_attestation(scAttester, jvb_unknown, mcAlice, amt, payees[0], true, claimID, dst, signers[0]), ter(tecNO_ENTRY)) .close(); @@ -2877,10 +2358,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb_unknown, claimID, amt, scBob), - ter(tecNO_ENTRY)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb_unknown, claimID, amt, scBob), ter(tecNO_ENTRY)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -2906,21 +2384,11 @@ struct XChain_test : public beast::unit_test::suite, std::uint32_t const claimID = 1; mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, Account::master, scBob, scAlice, payees, withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, payees, withClaim); // attest using non-existent claim id scEnv - .tx(claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[0], - true, - 999, - dst, - signers[0]), + .tx(claim_attestation(scAttester, jvb, mcAlice, amt, payees[0], true, 999, dst, signers[0]), ter(tecXCHAIN_NO_CLAIM_ID)) .close(); if (withClaim) @@ -2928,10 +2396,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // claim using non-existent claim id - scEnv - .tx(xchain_claim(scAlice, jvb, 999, amt, scBob), - ter(tecXCHAIN_NO_CLAIM_ID)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, 999, amt, scBob), ter(tecXCHAIN_NO_CLAIM_ID)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -2958,25 +2423,9 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)) .close(); if (withClaim) { @@ -2984,10 +2433,7 @@ struct XChain_test : public beast::unit_test::suite, // submit a claim transaction with the wrong account (scGw // instead of scAlice) - scEnv - .tx(xchain_claim(scGw, jvb, claimID, amt, scBob), - ter(tecXCHAIN_BAD_CLAIM_ID)) - .close(); + scEnv.tx(xchain_claim(scGw, jvb, claimID, amt, scBob), ter(tecXCHAIN_BAD_CLAIM_ID)).close(); BEAST_EXPECT(transfer.has_not_happened()); } else @@ -3016,8 +2462,7 @@ struct XChain_test : public beast::unit_test::suite, std::uint32_t const claimID = 1; mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, Account::master, scBob, scAlice, payees, withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, payees, withClaim); // don't send any attestations @@ -3026,10 +2471,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecXCHAIN_CLAIM_NO_QUORUM)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecXCHAIN_CLAIM_NO_QUORUM)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -3056,32 +2498,18 @@ struct XChain_test : public beast::unit_test::suite, std::uint32_t const claimID = 1; mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, Account::master, scBob, scAlice, payees, withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, payees, withClaim); auto tooFew = quorum - 1; scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers, - tooFew)) + .multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers, tooFew)) .close(); if (withClaim) { BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecXCHAIN_CLAIM_NO_QUORUM)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecXCHAIN_CLAIM_NO_QUORUM)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -3107,21 +2535,11 @@ struct XChain_test : public beast::unit_test::suite, std::uint32_t const claimID = 1; mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, Account::master, scBob, scAlice, payees, withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scAlice, payees, withClaim); scEnv .multiTx( - claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - 0, - dst, - signers), + claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, 0, dst, signers), ter(tecXCHAIN_NO_CLAIM_ID)) .close(); if (withClaim) @@ -3129,10 +2547,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, 0, amt, scBob), - ter(tecXCHAIN_NO_CLAIM_ID)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, 0, amt, scBob), ter(tecXCHAIN_NO_CLAIM_ID)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -3162,25 +2577,9 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)) .close(); if (withClaim) @@ -3188,10 +2587,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, scUSD(1000), scBob), - ter(temBAD_AMOUNT)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, scUSD(1000), scBob), ter(temBAD_AMOUNT)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -3218,35 +2614,16 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)) .close(); if (withClaim) { BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scuBob), - ter(tecNO_DST)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scuBob), ter(tecNO_DST)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -3276,48 +2653,20 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); if (withClaim) { - scEnv - .multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)) + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)) .close(); BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecUNFUNDED_PAYMENT)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecUNFUNDED_PAYMENT)).close(); } else { - auto txns = claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers); + auto txns = claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers); for (int i = 0; i < UT_XCHAIN_DEFAULT_QUORUM - 1; ++i) { scEnv.tx(txns[i]).close(); @@ -3327,10 +2676,7 @@ struct XChain_test : public beast::unit_test::suite, // The attestation should succeed, because it adds an // attestation, but the claim should fail with insufficient // funds - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecUNFUNDED_PAYMENT)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecUNFUNDED_PAYMENT)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -3352,8 +2698,7 @@ struct XChain_test : public beast::unit_test::suite, res0 + reward, scuAlice) // just not enough because of fees .close() - .tx(xchain_create_claim_id(scuAlice, jvb, reward, mcAlice), - ter(tecINSUFFICIENT_RESERVE)) + .tx(xchain_create_claim_id(scuAlice, jvb, reward, mcAlice), ter(tecINSUFFICIENT_RESERVE)) .close(); auto dst(withClaim ? std::nullopt : std::optional{scBob}); @@ -3361,20 +2706,10 @@ struct XChain_test : public beast::unit_test::suite, std::uint32_t const claimID = 1; mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); - BalanceTransfer transfer( - scEnv, Account::master, scBob, scuAlice, payees, withClaim); + BalanceTransfer transfer(scEnv, Account::master, scBob, scuAlice, payees, withClaim); scEnv - .tx(claim_attestation( - scAttester, - jvb, - mcAlice, - amt, - payees[0], - true, - claimID, - dst, - signers[0]), + .tx(claim_attestation(scAttester, jvb, mcAlice, amt, payees[0], true, claimID, dst, signers[0]), ter(tecXCHAIN_NO_CLAIM_ID)) .close(); if (withClaim) @@ -3382,10 +2717,7 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scuAlice, jvb, claimID, amt, scBob), - ter(tecXCHAIN_NO_CLAIM_ID)) - .close(); + scEnv.tx(xchain_claim(scuAlice, jvb, claimID, amt, scBob), ter(tecXCHAIN_NO_CLAIM_ID)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -3413,23 +2745,8 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); - auto txns = claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); + auto txns = claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers); for (int i = 0; i < UT_XCHAIN_DEFAULT_QUORUM - 1; ++i) { scEnv.tx(txns[i]).close(); @@ -3441,26 +2758,19 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecNO_PERMISSION)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecNO_PERMISSION)).close(); // the transfer failed, but check that we can still use the // claimID with a different account Balance scCarol_bal(scEnv, scCarol); - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scCarol)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scCarol)).close(); BEAST_EXPECT(scCarol_bal.diff() == amt); } else { scEnv.tx(txns.back()).close(); - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecNO_PERMISSION)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecNO_PERMISSION)).close(); // A way would be to remove deposit auth and resubmit the // attestations (even though the witness servers won't do // it) @@ -3496,23 +2806,8 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); - auto txns = claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); + auto txns = claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers); for (int i = 0; i < UT_XCHAIN_DEFAULT_QUORUM - 1; ++i) { scEnv.tx(txns[i]).close(); @@ -3523,26 +2818,19 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecDST_TAG_NEEDED)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecDST_TAG_NEEDED)).close(); // the transfer failed, but check that we can still use the // claimID with a different account Balance scCarol_bal(scEnv, scCarol); - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scCarol)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scCarol)).close(); BEAST_EXPECT(scCarol_bal.diff() == amt); } else { scEnv.tx(txns.back()).close(); - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), - ter(tecDST_TAG_NEEDED)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob), ter(tecDST_TAG_NEEDED)).close(); // A way would be to remove the destination tag requirement // and resubmit the attestations (even though the witness // servers won't do it) @@ -3583,16 +2871,7 @@ struct XChain_test : public beast::unit_test::suite, // should not occur because dest account has deposit auth set Balance scBob_bal(scEnv, scBob); - scEnv.multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)); + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)); BEAST_EXPECT(scBob_bal.diff() == STAmount(0)); // Check that check that we still can use the claimID to transfer @@ -3624,32 +2903,14 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); - scEnv.multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)); if (withClaim) { BEAST_EXPECT(transfer.has_not_happened()); // claim wrong amount - scEnv - .tx(xchain_claim(scAlice, jvb, claimID, one_xrp, scBob), - ter(tecXCHAIN_CLAIM_NO_QUORUM)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, one_xrp, scBob), ter(tecXCHAIN_CLAIM_NO_QUORUM)).close(); } BEAST_EXPECT(transfer.has_not_happened()); @@ -3677,24 +2938,9 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); Balance scAlice_bal(scEnv, scAlice); - scEnv.multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)); + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)); STAmount claim_cost = reward; @@ -3703,14 +2949,12 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); claim_cost += tx_fee; } BEAST_EXPECT(transfer.has_happened(amt, split_reward_quorum)); - BEAST_EXPECT( - scAlice_bal.diff() == -claim_cost); // because reward % 4 == 0 + BEAST_EXPECT(scAlice_bal.diff() == -claim_cost); // because reward % 4 == 0 } // Verify that if a reward is not evenly divisible among the reward @@ -3735,24 +2979,9 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM, - withClaim); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM, withClaim); Balance scAlice_bal(scEnv, scAlice); - scEnv.multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)); + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)); STAmount claim_cost = tiny_reward; if (withClaim) @@ -3760,14 +2989,12 @@ struct XChain_test : public beast::unit_test::suite, BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); claim_cost += tx_fee; } BEAST_EXPECT(transfer.has_happened(amt, tiny_reward_split)); - BEAST_EXPECT( - scAlice_bal.diff() == -(claim_cost - tiny_reward_remainder)); + BEAST_EXPECT(scAlice_bal.diff() == -(claim_cost - tiny_reward_remainder)); } // If a reward distribution fails for one of the reward accounts @@ -3797,31 +3024,15 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.tx(xchain_commit(mcAlice, jvb, claimID, amt, dst)).close(); BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM - 1, - withClaim); - scEnv.multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - alt_payees, - true, - claimID, - dst, - signers)); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM - 1, withClaim); + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, alt_payees, true, claimID, dst, signers)); if (withClaim) { BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); } // this also checks that only 3 * split_reward was deducted from @@ -3856,31 +3067,15 @@ struct XChain_test : public beast::unit_test::suite, // split_reward BalanceTransfer transfer( - scEnv, - Account::master, - scBob, - scAlice, - &payees[0], - UT_XCHAIN_DEFAULT_QUORUM - 1, - withClaim); - scEnv.multiTx(claim_attestations( - scAttester, - jvb, - mcAlice, - amt, - payees, - true, - claimID, - dst, - signers)); + scEnv, Account::master, scBob, scAlice, &payees[0], UT_XCHAIN_DEFAULT_QUORUM - 1, withClaim); + scEnv.multiTx(claim_attestations(scAttester, jvb, mcAlice, amt, payees, true, claimID, dst, signers)); if (withClaim) { BEAST_EXPECT(transfer.has_not_happened()); // need to submit a claim transactions - scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)) - .close(); + scEnv.tx(xchain_claim(scAlice, jvb, claimID, amt, scBob)).close(); } // this also checks that only 3 * split_reward was deducted from @@ -3896,9 +3091,7 @@ struct XChain_test : public beast::unit_test::suite, XEnv(*this, true) .tx(create_bridge(Account::master, jvb)) .close() - .tx(xchain_claim(scAlice, jvb, 1, XRP(1000), scBob), - txflags(tfFillOrKill), - ter(temINVALID_FLAG)) + .tx(xchain_claim(scAlice, jvb, 1, XRP(1000), scBob), txflags(tfFillOrKill), ter(temINVALID_FLAG)) .close(); // coverage test: xchain_claim transaction with xchain feature @@ -3907,16 +3100,14 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(Account::master, jvb)) .disableFeature(featureXChainBridge) .close() - .tx(xchain_claim(scAlice, jvb, 1, XRP(1000), scBob), - ter(temDISABLED)) + .tx(xchain_claim(scAlice, jvb, 1, XRP(1000), scBob), ter(temDISABLED)) .close(); // coverage test: XChainClaim::preclaim - isLockingChain = true; XEnv(*this) .tx(create_bridge(mcDoor, jvb)) .close() - .tx(xchain_claim(mcAlice, jvb, 1, XRP(1000), mcBob), - ter(tecXCHAIN_NO_CLAIM_ID)); + .tx(xchain_claim(mcAlice, jvb, 1, XRP(1000), mcBob), ter(tecXCHAIN_NO_CLAIM_ID)); } void @@ -3934,27 +3125,21 @@ struct XChain_test : public beast::unit_test::suite, auto const amt = XRP(111); auto const amt_plus_reward = amt + reward; - scEnv.tx(create_bridge(Account::master, jvb)) - .tx(jtx::signers(Account::master, quorum, signers)) - .close(); + scEnv.tx(create_bridge(Account::master, jvb)).tx(jtx::signers(Account::master, quorum, signers)).close(); Balance door(scEnv, Account::master); // scEnv.tx(att_create_acct_batch1(1, amt, // Account::master)).close(); - scEnv.multiTx(att_create_acct_vec(1, amt, Account::master, 2)) - .close(); - BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // claim id present - BEAST_EXPECT( - scEnv.claimCount(jvb) == 0); // claim count is one less + scEnv.multiTx(att_create_acct_vec(1, amt, Account::master, 2)).close(); + BEAST_EXPECT(!!scEnv.caClaimID(jvb, 1)); // claim id present + BEAST_EXPECT(scEnv.claimCount(jvb) == 0); // claim count is one less // scEnv.tx(att_create_acct_batch2(1, amt, // Account::master)).close(); - scEnv.multiTx(att_create_acct_vec(1, amt, Account::master, 2, 2)) - .close(); - BEAST_EXPECT(!scEnv.caClaimID(jvb, 1)); // claim id deleted - BEAST_EXPECT( - scEnv.claimCount(jvb) == 1); // claim count was incremented + scEnv.multiTx(att_create_acct_vec(1, amt, Account::master, 2, 2)).close(); + BEAST_EXPECT(!scEnv.caClaimID(jvb, 1)); // claim id deleted + BEAST_EXPECT(scEnv.claimCount(jvb) == 1); // claim count was incremented BEAST_EXPECT(door.diff() == -reward); } @@ -3970,8 +3155,7 @@ struct XChain_test : public beast::unit_test::suite, Balance carol(mcEnv, mcCarol); mcEnv - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuAlice, XRP(19), reward), + .tx(sidechain_xchain_account_create(mcCarol, jvb, scuAlice, XRP(19), reward), ter(tecXCHAIN_INSUFF_CREATE_AMOUNT)) .close(); @@ -3988,8 +3172,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); mcEnv - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuAlice, XRP(20), reward), + .tx(sidechain_xchain_account_create(mcCarol, jvb, scuAlice, XRP(20), reward), txflags(tfFillOrKill), ter(temINVALID_FLAG)) .close(); @@ -4007,9 +3190,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); mcEnv.disableFeature(featureXChainBridge) - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuAlice, XRP(20), reward), - ter(temDISABLED)) + .tx(sidechain_xchain_account_create(mcCarol, jvb, scuAlice, XRP(20), reward), ter(temDISABLED)) .close(); BEAST_EXPECT(door.diff() == STAmount(0)); @@ -4023,10 +3204,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); - mcEnv - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuAlice, XRP(-20), reward), - ter(temBAD_AMOUNT)) + mcEnv.tx(sidechain_xchain_account_create(mcCarol, jvb, scuAlice, XRP(-20), reward), ter(temBAD_AMOUNT)) .close(); BEAST_EXPECT(door.diff() == STAmount(0)); @@ -4040,10 +3218,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); - mcEnv - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuAlice, XRP(20), XRP(-1)), - ter(temBAD_AMOUNT)) + mcEnv.tx(sidechain_xchain_account_create(mcCarol, jvb, scuAlice, XRP(20), XRP(-1)), ter(temBAD_AMOUNT)) .close(); BEAST_EXPECT(door.diff() == STAmount(0)); @@ -4058,9 +3233,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); mcEnv - .tx(sidechain_xchain_account_create( - mcDoor, jvb, scuAlice, XRP(20), XRP(1)), - ter(tecXCHAIN_SELF_COMMIT)) + .tx(sidechain_xchain_account_create(mcDoor, jvb, scuAlice, XRP(20), XRP(1)), ter(tecXCHAIN_SELF_COMMIT)) .close(); BEAST_EXPECT(door.diff() == -tx_fee); @@ -4075,8 +3248,7 @@ struct XChain_test : public beast::unit_test::suite, Balance door(mcEnv, mcDoor); mcEnv - .tx(sidechain_xchain_account_create( - mcCarol, jvb, scuAlice, XRP(20), XRP(2)), + .tx(sidechain_xchain_account_create(mcCarol, jvb, scuAlice, XRP(20), XRP(2)), ter(tecXCHAIN_REWARD_MISMATCH)) .close(); @@ -4098,8 +3270,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(mcDoor, jvb)) .fund(res0 + one_xrp + tx_fee - drops(1), mcuAlice) .close() - .tx(xchain_commit(mcuAlice, jvb, 1, one_xrp, scBob), - ter(tesSUCCESS)); + .tx(xchain_commit(mcuAlice, jvb, 1, one_xrp, scBob), ter(tesSUCCESS)); // commit where the commit amount drips into the reserve, this should // fail @@ -4107,8 +3278,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(mcDoor, jvb)) .fund(res0 + one_xrp - drops(1), mcuAlice) .close() - .tx(xchain_commit(mcuAlice, jvb, 1, one_xrp, scBob), - ter(tecUNFUNDED_PAYMENT)); + .tx(xchain_commit(mcuAlice, jvb, 1, one_xrp, scBob), ter(tecUNFUNDED_PAYMENT)); auto const minAccountCreate = XRP(20); @@ -4116,12 +3286,9 @@ struct XChain_test : public beast::unit_test::suite, // this should succeed XEnv(*this) .tx(create_bridge(mcDoor, jvb, reward, minAccountCreate)) - .fund( - res0 + tx_fee + minAccountCreate + reward - drops(1), mcuAlice) + .fund(res0 + tx_fee + minAccountCreate + reward - drops(1), mcuAlice) .close() - .tx(sidechain_xchain_account_create( - mcuAlice, jvb, scuAlice, minAccountCreate, reward), - ter(tesSUCCESS)); + .tx(sidechain_xchain_account_create(mcuAlice, jvb, scuAlice, minAccountCreate, reward), ter(tesSUCCESS)); // account create commit where the commit dips into the reserve, // this should fail @@ -4129,8 +3296,7 @@ struct XChain_test : public beast::unit_test::suite, .tx(create_bridge(mcDoor, jvb, reward, minAccountCreate)) .fund(res0 + minAccountCreate + reward - drops(1), mcuAlice) .close() - .tx(sidechain_xchain_account_create( - mcuAlice, jvb, scuAlice, minAccountCreate, reward), + .tx(sidechain_xchain_account_create(mcuAlice, jvb, scuAlice, minAccountCreate, reward), ter(tecUNFUNDED_PAYMENT)); } @@ -4141,8 +3307,7 @@ struct XChain_test : public beast::unit_test::suite, testcase("Bridge Delete Door Account"); - auto const acctDelFee{ - drops(XEnv(*this).env_.current()->fees().increment)}; + auto const acctDelFee{drops(XEnv(*this).env_.current()->fees().increment)}; // Deleting an account that owns bridge should fail { @@ -4156,10 +3321,7 @@ struct XChain_test : public beast::unit_test::suite, mcEnv.close(); // try to delete mcDoor, send funds to mcAlice - mcEnv.tx( - acctdelete(mcDoor, mcAlice), - fee(acctDelFee), - ter(tecHAS_OBLIGATIONS)); + mcEnv.tx(acctdelete(mcDoor, mcAlice), fee(acctDelFee), ter(tecHAS_OBLIGATIONS)); } // Deleting an account that owns a claim id should fail @@ -4177,10 +3339,7 @@ struct XChain_test : public beast::unit_test::suite, scEnv.close(); // try to delete scAlice, send funds to scBob - scEnv.tx( - acctdelete(scAlice, scBob), - fee(acctDelFee), - ter(tecHAS_OBLIGATIONS)); + scEnv.tx(acctdelete(scAlice, scBob), fee(acctDelFee), ter(tecHAS_OBLIGATIONS)); } } @@ -4196,11 +3355,8 @@ struct XChain_test : public beast::unit_test::suite, std::uint32_t const claimID = 1; std::optional dst{scBob}; auto const amt = XRP(1000); - scEnv.tx(create_bridge(Account::master, jvb)) - .tx(jtx::signers(Account::master, quorum, signers)) - .close(); - scEnv.tx(xchain_create_claim_id(scAlice, jvb, reward, mcAlice)) - .close(); + scEnv.tx(create_bridge(Account::master, jvb)).tx(jtx::signers(Account::master, quorum, signers)).close(); + scEnv.tx(xchain_create_claim_id(scAlice, jvb, reward, mcAlice)).close(); auto jvAtt = claim_attestation( scAttester, jvb, @@ -4227,9 +3383,7 @@ struct XChain_test : public beast::unit_test::suite, Account dst{scBob}; auto const amt = XRP(1000); auto const rewardAmt = XRP(1); - scEnv.tx(create_bridge(Account::master, jvb)) - .tx(jtx::signers(Account::master, quorum, signers)) - .close(); + scEnv.tx(create_bridge(Account::master, jvb)).tx(jtx::signers(Account::master, quorum, signers)).close(); auto jvAtt = create_account_attestation( scAttester, jvb, @@ -4274,8 +3428,7 @@ struct XChain_test : public beast::unit_test::suite, // ----------------------------------------------------------- // ----------------------------------------------------------- -struct XChainSim_test : public beast::unit_test::suite, - public jtx::XChainBridgeObjects +struct XChainSim_test : public beast::unit_test::suite, public jtx::XChainBridgeObjects { private: static constexpr size_t num_signers = 5; @@ -4338,8 +3491,7 @@ private: using CreateClaimVec = jtx::JValueVec; using CreateClaimMap = std::map; - ChainStateTrack(ENV& env) - : env(env), tx_fee(env.env_.current()->fees().base) + ChainStateTrack(ENV& env) : env(env), tx_fee(env.env_.current()->fees().base) { } @@ -4355,10 +3507,7 @@ private: } uint32_t - sendCreateAttestations( - size_t signer_idx, - BridgeID bridge, - CreateClaimVec& claims) + sendCreateAttestations(size_t signer_idx, BridgeID bridge, CreateClaimVec& claims) { size_t num_successful = 0; for (auto const& c : claims) @@ -4393,13 +3542,11 @@ private: sendAttestations(i, bridge, claims.xfer_claims); auto& c = counters[bridge]; - auto& create_claims = - claims.create_claims[c.claim_count]; + auto& create_claims = claims.create_claims[c.claim_count]; auto num_attns = create_claims.size(); if (num_attns) { - c.num_create_attn_sent += sendCreateAttestations( - i, bridge, create_claims); + c.num_create_attn_sent += sendCreateAttestations(i, bridge, create_claims); } assert(claims.create_claims[c.claim_count].empty()); } @@ -4425,10 +3572,7 @@ private: } void - receive( - jtx::Account const& acct, - STAmount amt, - std::uint64_t divisor = 1) + receive(jtx::Account const& acct, STAmount amt, std::uint64_t divisor = 1) { if (amt.issue() != xrpIssue()) return; @@ -4441,11 +3585,7 @@ private: else { it->second.expectedDiff += - (divisor == 1 ? amt - : divide( - amt, - STAmount(amt.issue(), divisor), - amt.issue())); + (divisor == 1 ? amt : divide(amt, STAmount(amt.issue(), divisor), amt.issue())); } } @@ -4454,12 +3594,7 @@ private: { if (amt.issue() != xrpIssue()) return; - receive( - acct, - times == 1 - ? -amt - : -multiply( - amt, STAmount(amt.issue(), times), amt.issue())); + receive(acct, times == 1 ? -amt : -multiply(amt, STAmount(amt.issue(), times), amt.issue())); } void @@ -4486,14 +3621,12 @@ private: struct BridgeCounters { - using complete_cb = - std::function const& signers)>; + using complete_cb = std::function const& signers)>; uint32_t claim_id{0}; uint32_t create_count{0}; // for account create. First should be 1 - uint32_t claim_count{ - 0}; // for account create. Increments after quorum for - // current create_count (starts at 1) is reached. + uint32_t claim_count{0}; // for account create. Increments after quorum for + // current create_count (starts at 1) is reached. uint32_t num_create_attn_sent{0}; // for current claim_count std::vector signers; @@ -4562,9 +3695,7 @@ private: class SmBase { public: - SmBase( - std::shared_ptr const& chainstate, - BridgeDef const& bridge) + SmBase(std::shared_ptr const& chainstate, BridgeDef const& bridge) : bridge_(bridge), st_(chainstate) { } @@ -4608,9 +3739,7 @@ private: std::shared_ptr const& chainstate, BridgeDef const& bridge, AccountCreate create) - : Base(chainstate, bridge) - , sm_state(st_initial) - , cr(std::move(create)) + : Base(chainstate, bridge), sm_state(st_initial), cr(std::move(create)) { } @@ -4626,9 +3755,7 @@ private: ChainStateTrack& st = srcState(); jtx::Account const& srcdoor = srcDoor(); - st.env - .tx(sidechain_xchain_account_create( - cr.from, bridge_.jvb, cr.to, cr.amt, cr.reward)) + st.env.tx(sidechain_xchain_account_create(cr.from, bridge_.jvb, cr.to, cr.amt, cr.reward)) .close(); // needed for claim_id sequence to be correct' st.spendFee(cr.from); st.transfer(cr.from, srcdoor, cr.amt); @@ -4653,9 +3780,8 @@ private: // enqueue one attestation for this signer cr.attested[signer_idx] = true; - st.signers_attns[signer_idx][&bridge_] - .create_claims[cr.claim_id - 1] - .emplace_back(create_account_attestation( + st.signers_attns[signer_idx][&bridge_].create_claims[cr.claim_id - 1].emplace_back( + create_account_attestation( bridge_.signers[signer_idx].account, bridge_.jvb, cr.from, @@ -4680,9 +3806,7 @@ private: auto complete_cb = [&](std::vector const& signers) { auto num_attestors = signers.size(); st.env.close(); - assert( - num_attestors <= - std::count(cr.attested.begin(), cr.attested.end(), true)); + assert(num_attestors <= std::count(cr.attested.begin(), cr.attested.end(), true)); assert(num_attestors >= bridge_.quorum); assert(cr.claim_id - 1 == counters.claim_count); @@ -4736,13 +3860,8 @@ private: public: using Base = SmBase; - SmTransfer( - std::shared_ptr const& chainstate, - BridgeDef const& bridge, - Transfer xfer) - : Base(chainstate, bridge) - , xfer(std::move(xfer)) - , sm_state(st_initial) + SmTransfer(std::shared_ptr const& chainstate, BridgeDef const& bridge, Transfer xfer) + : Base(chainstate, bridge), xfer(std::move(xfer)), sm_state(st_initial) { } @@ -4757,9 +3876,7 @@ private: { ChainStateTrack& st = destState(); - st.env - .tx(xchain_create_claim_id( - xfer.to, bridge_.jvb, bridge_.reward, xfer.from)) + st.env.tx(xchain_create_claim_id(xfer.to, bridge_.jvb, bridge_.reward, xfer.from)) .close(); // needed for claim_id sequence to be // correct' st.spendFee(xfer.to); @@ -4782,9 +3899,7 @@ private: bridge_.jvb, xfer.claim_id, xfer.amt, - xfer.with_claim == WithClaim::yes - ? std::nullopt - : std::optional(xfer.finaldest))); + xfer.with_claim == WithClaim::yes ? std::nullopt : std::optional(xfer.finaldest))); st.spendFee(xfer.from); st.transfer(xfer.from, srcdoor, xfer.amt); } @@ -4817,27 +3932,22 @@ private: // enqueue one attestation for this signer xfer.attested[signer_idx] = true; - st.signers_attns[signer_idx][&bridge_] - .xfer_claims.emplace_back(claim_attestation( - bridge_.signers[signer_idx].account, - bridge_.jvb, - xfer.from, - xfer.amt, - bridge_.signers[signer_idx].account, - xfer.a2b, - xfer.claim_id, - xfer.with_claim == WithClaim::yes - ? std::nullopt - : std::optional(xfer.finaldest), - bridge_.signers[signer_idx])); + st.signers_attns[signer_idx][&bridge_].xfer_claims.emplace_back(claim_attestation( + bridge_.signers[signer_idx].account, + bridge_.jvb, + xfer.from, + xfer.amt, + bridge_.signers[signer_idx].account, + xfer.a2b, + xfer.claim_id, + xfer.with_claim == WithClaim::yes ? std::nullopt : std::optional(xfer.finaldest), + bridge_.signers[signer_idx])); break; } } // return true if quorum was reached, false otherwise - bool quorum = - std::count(xfer.attested.begin(), xfer.attested.end(), true) >= - bridge_.quorum; + bool quorum = std::count(xfer.attested.begin(), xfer.attested.end(), true) >= bridge_.quorum; if (quorum && xfer.with_claim == WithClaim::no) { distribute_reward(st); @@ -4850,8 +3960,7 @@ private: claim() { ChainStateTrack& st = destState(); - st.env.tx(xchain_claim( - xfer.to, bridge_.jvb, xfer.claim_id, xfer.amt, xfer.finaldest)); + st.env.tx(xchain_claim(xfer.to, bridge_.jvb, xfer.claim_id, xfer.amt, xfer.finaldest)); distribute_reward(st); st.transfer(dstDoor(), xfer.finaldest, xfer.amt); st.spendFee(xfer.to); @@ -4873,10 +3982,8 @@ private: break; case st_attesting: - sm_state = attest(time, rnd) - ? (xfer.with_claim == WithClaim::yes ? st_attested - : st_completed) - : st_attesting; + sm_state = attest(time, rnd) ? (xfer.with_claim == WithClaim::yes ? st_attested : st_completed) + : st_attesting; break; case st_attested: @@ -4911,25 +4018,18 @@ private: BridgeDef const& bridge, Transfer transfer) { - sm_.emplace_back( - time, SmTransfer(chainstate, bridge, std::move(transfer))); + sm_.emplace_back(time, SmTransfer(chainstate, bridge, std::move(transfer))); } void - ac(uint64_t time, - std::shared_ptr const& chainstate, - BridgeDef const& bridge, - AccountCreate ac) + ac(uint64_t time, std::shared_ptr const& chainstate, BridgeDef const& bridge, AccountCreate ac) { - sm_.emplace_back( - time, SmCreateAccount(chainstate, bridge, std::move(ac))); + sm_.emplace_back(time, SmCreateAccount(chainstate, bridge, std::move(ac))); } public: void - runSimulation( - std::shared_ptr const& st, - bool verify_balances = true) + runSimulation(std::shared_ptr const& st, bool verify_balances = true) { using namespace jtx; uint64_t time = 0; @@ -4980,8 +4080,7 @@ public: // create 10 accounts + door funded on both chains, and store // in ChainStateTracker the initial amount of these accounts - Account doorXRPLocking("doorXRPLocking"), - doorUSDLocking("doorUSDLocking"), doorUSDIssuing("doorUSDIssuing"); + Account doorXRPLocking("doorXRPLocking"), doorUSDLocking("doorUSDLocking"), doorUSDIssuing("doorUSDIssuing"); constexpr size_t num_acct = 10; auto a = [&doorXRPLocking, &doorUSDLocking, &doorUSDIssuing]() { @@ -4989,9 +4088,7 @@ public: std::vector result; result.reserve(num_acct); for (int i = 0; i < num_acct; ++i) - result.emplace_back( - "a"s + std::to_string(i), - (i % 2) ? KeyType::ed25519 : KeyType::secp256k1); + result.emplace_back("a"s + std::to_string(i), (i % 2) ? KeyType::ed25519 : KeyType::secp256k1); result.emplace_back("doorXRPLocking"); doorXRPLocking = result.back(); result.emplace_back("doorUSDLocking"); @@ -5040,9 +4137,7 @@ public: std::vector result; result.reserve(num_ua); for (int i = 0; i < num_ua; ++i) - result.emplace_back( - "ua"s + std::to_string(i), - (i % 2) ? KeyType::ed25519 : KeyType::secp256k1); + result.emplace_back("ua"s + std::to_string(i), (i % 2) ? KeyType::ed25519 : KeyType::secp256k1); return result; }(); @@ -5056,30 +4151,14 @@ public: // create XRP -> XRP bridge // ------------------------ BridgeDef xrp_b{ - doorXRPLocking, - xrpIssue(), - Account::master, - xrpIssue(), - XRP(1), - XRP(20), - quorum, - signers, - Json::nullValue}; + doorXRPLocking, xrpIssue(), Account::master, xrpIssue(), XRP(1), XRP(20), quorum, signers, Json::nullValue}; initBridge(xrp_b); // create USD -> USD bridge // ------------------------ BridgeDef usd_b{ - doorUSDLocking, - usdLocking, - doorUSDIssuing, - usdIssuing, - XRP(1), - XRP(20), - quorum, - signers, - Json::nullValue}; + doorUSDLocking, usdLocking, doorUSDIssuing, usdIssuing, XRP(1), XRP(20), quorum, signers, Json::nullValue}; initBridge(usd_b); diff --git a/src/test/app/tx/apply_test.cpp b/src/test/app/tx/apply_test.cpp index 6f9473ce69..fada168112 100644 --- a/src/test/app/tx/apply_test.cpp +++ b/src/test/app/tx/apply_test.cpp @@ -36,8 +36,7 @@ public: STTx const tx = *std::make_shared(std::ref(sitTrans)); { - test::jtx::Env fully_canonical( - *this, test::jtx::testable_amendments()); + test::jtx::Env fully_canonical(*this, test::jtx::testable_amendments()); Validity valid = checkValidity( fully_canonical.app().getHashRouter(), diff --git a/src/test/basics/Buffer_test.cpp b/src/test/basics/Buffer_test.cpp index cb3c48484b..908650982c 100644 --- a/src/test/basics/Buffer_test.cpp +++ b/src/test/basics/Buffer_test.cpp @@ -21,10 +21,9 @@ struct Buffer_test : beast::unit_test::suite void run() override { - std::uint8_t const data[] = { - 0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23, 0x71, 0x6d, 0x2a, - 0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c, - 0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3}; + std::uint8_t const data[] = {0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23, 0x71, 0x6d, 0x2a, + 0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c, + 0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3}; Buffer b0; BEAST_EXPECT(sane(b0)); @@ -100,8 +99,7 @@ struct Buffer_test : beast::unit_test::suite { testcase("Move Construction / Assignment"); - static_assert( - std::is_nothrow_move_constructible::value, ""); + static_assert(std::is_nothrow_move_constructible::value, ""); static_assert(std::is_nothrow_move_assignable::value, ""); { // Move-construct from empty buf diff --git a/src/test/basics/Expected_test.cpp b/src/test/basics/Expected_test.cpp index 010a6fbb8e..186e34d2e0 100644 --- a/src/test/basics/Expected_test.cpp +++ b/src/test/basics/Expected_test.cpp @@ -18,9 +18,7 @@ struct Expected_test : beast::unit_test::suite { // Test non-error const construction. { - auto const expected = []() -> Expected { - return "Valid value"; - }(); + auto const expected = []() -> Expected { return "Valid value"; }(); BEAST_EXPECT(expected); BEAST_EXPECT(expected.has_value()); BEAST_EXPECT(expected.value() == "Valid value"); @@ -42,9 +40,7 @@ struct Expected_test : beast::unit_test::suite } // Test non-error non-const construction. { - auto expected = []() -> Expected { - return "Valid value"; - }(); + auto expected = []() -> Expected { return "Valid value"; }(); BEAST_EXPECT(expected); BEAST_EXPECT(expected.has_value()); BEAST_EXPECT(expected.value() == "Valid value"); @@ -68,9 +64,7 @@ struct Expected_test : beast::unit_test::suite } // Test non-error overlapping type construction. { - auto expected = []() -> Expected { - return 1; - }(); + auto expected = []() -> Expected { return 1; }(); BEAST_EXPECT(expected); BEAST_EXPECT(expected.has_value()); BEAST_EXPECT(expected.value() == 1); @@ -91,9 +85,7 @@ struct Expected_test : beast::unit_test::suite } // Test error construction from rvalue. { - auto const expected = []() -> Expected { - return Unexpected(telLOCAL_ERROR); - }(); + auto const expected = []() -> Expected { return Unexpected(telLOCAL_ERROR); }(); BEAST_EXPECT(!expected); BEAST_EXPECT(!expected.has_value()); BEAST_EXPECT(expected.error() == telLOCAL_ERROR); @@ -114,9 +106,7 @@ struct Expected_test : beast::unit_test::suite // Test error construction from lvalue. { auto const err(telLOCAL_ERROR); - auto expected = [&err]() -> Expected { - return Unexpected(err); - }(); + auto expected = [&err]() -> Expected { return Unexpected(err); }(); BEAST_EXPECT(!expected); BEAST_EXPECT(!expected.has_value()); BEAST_EXPECT(expected.error() == telLOCAL_ERROR); @@ -136,19 +126,14 @@ struct Expected_test : beast::unit_test::suite } // Test error construction from const char*. { - auto const expected = []() -> Expected { - return Unexpected("Not what is expected!"); - }(); + auto const expected = []() -> Expected { return Unexpected("Not what is expected!"); }(); BEAST_EXPECT(!expected); BEAST_EXPECT(!expected.has_value()); - BEAST_EXPECT( - expected.error() == std::string("Not what is expected!")); + BEAST_EXPECT(expected.error() == std::string("Not what is expected!")); } // Test error construction of string from const char*. { - auto expected = []() -> Expected { - return Unexpected("Not what is expected!"); - }(); + auto expected = []() -> Expected { return Unexpected("Not what is expected!"); }(); BEAST_EXPECT(!expected); BEAST_EXPECT(!expected.has_value()); BEAST_EXPECT(expected.error() == "Not what is expected!"); @@ -157,9 +142,7 @@ struct Expected_test : beast::unit_test::suite } // Test non-error const construction of Expected. { - auto const expected = []() -> Expected { - return {}; - }(); + auto const expected = []() -> Expected { return {}; }(); BEAST_EXPECT(expected); bool throwOccurred = false; try @@ -176,9 +159,7 @@ struct Expected_test : beast::unit_test::suite } // Test non-error non-const construction of Expected. { - auto expected = []() -> Expected { - return {}; - }(); + auto expected = []() -> Expected { return {}; }(); BEAST_EXPECT(expected); bool throwOccurred = false; try @@ -195,17 +176,13 @@ struct Expected_test : beast::unit_test::suite } // Test error const construction of Expected. { - auto const expected = []() -> Expected { - return Unexpected("Not what is expected!"); - }(); + auto const expected = []() -> Expected { return Unexpected("Not what is expected!"); }(); BEAST_EXPECT(!expected); BEAST_EXPECT(expected.error() == "Not what is expected!"); } // Test error non-const construction of Expected. { - auto expected = []() -> Expected { - return Unexpected("Not what is expected!"); - }(); + auto expected = []() -> Expected { return Unexpected("Not what is expected!"); }(); BEAST_EXPECT(!expected); BEAST_EXPECT(expected.error() == "Not what is expected!"); std::string const s(std::move(expected.error())); diff --git a/src/test/basics/FileUtilities_test.cpp b/src/test/basics/FileUtilities_test.cpp index c655e4d1bc..d8664448d6 100644 --- a/src/test/basics/FileUtilities_test.cpp +++ b/src/test/basics/FileUtilities_test.cpp @@ -15,14 +15,9 @@ public: using namespace xrpl::detail; using namespace boost::system; - constexpr char const* expectedContents = - "This file is very short. That's all we need."; + constexpr char const* expectedContents = "This file is very short. That's all we need."; - FileDirGuard file( - *this, - "test_file", - "test.txt", - "This is temporary text that should get overwritten"); + FileDirGuard file(*this, "test_file", "test.txt", "This is temporary text that should get overwritten"); error_code ec; auto const path = file.file(); @@ -47,8 +42,7 @@ public: { // Test with small max auto const bad = getFileContents(ec, path, 16); - BEAST_EXPECT( - ec && ec.value() == boost::system::errc::file_too_large); + BEAST_EXPECT(ec && ec.value() == boost::system::errc::file_too_large); BEAST_EXPECT(bad.empty()); } } diff --git a/src/test/basics/IOUAmount_test.cpp b/src/test/basics/IOUAmount_test.cpp index d299f439d4..73ab0343cd 100644 --- a/src/test/basics/IOUAmount_test.cpp +++ b/src/test/basics/IOUAmount_test.cpp @@ -148,8 +148,7 @@ public: BEAST_EXPECTS(result == expected, ss.str()); }; - for (auto const mantissaSize : - {MantissaRange::small, MantissaRange::large}) + for (auto const mantissaSize : {MantissaRange::small, MantissaRange::large}) { NumberMantissaScaleGuard mg(mantissaSize); @@ -203,19 +202,16 @@ public: BEAST_EXPECT(tiny == mulRatio(tiny, maxUInt - 1, maxUInt, true)); // rounding down should be zero BEAST_EXPECT(beast::zero == mulRatio(tiny, 1, maxUInt, false)); - BEAST_EXPECT( - beast::zero == mulRatio(tiny, maxUInt - 1, maxUInt, false)); + BEAST_EXPECT(beast::zero == mulRatio(tiny, maxUInt - 1, maxUInt, false)); // tiny negative numbers IOUAmount tinyNeg(-minMantissa, minExponent); // Round up should give zero BEAST_EXPECT(beast::zero == mulRatio(tinyNeg, 1, maxUInt, true)); - BEAST_EXPECT( - beast::zero == mulRatio(tinyNeg, maxUInt - 1, maxUInt, true)); + BEAST_EXPECT(beast::zero == mulRatio(tinyNeg, maxUInt - 1, maxUInt, true)); // rounding down should be tiny BEAST_EXPECT(tinyNeg == mulRatio(tinyNeg, 1, maxUInt, false)); - BEAST_EXPECT( - tinyNeg == mulRatio(tinyNeg, maxUInt - 1, maxUInt, false)); + BEAST_EXPECT(tinyNeg == mulRatio(tinyNeg, maxUInt - 1, maxUInt, false)); } { // rounding @@ -235,8 +231,7 @@ public: { IOUAmount negOne(-1, 0); auto const rup = mulRatio(negOne, maxUInt - 1, maxUInt, true); - auto const rdown = - mulRatio(negOne, maxUInt - 1, maxUInt, false); + auto const rdown = mulRatio(negOne, maxUInt - 1, maxUInt, false); BEAST_EXPECT(rup.mantissa() - rdown.mantissa() == 1); } } diff --git a/src/test/basics/IntrusiveShared_test.cpp b/src/test/basics/IntrusiveShared_test.cpp index 500b6e7e39..d0aa4c75e9 100644 --- a/src/test/basics/IntrusiveShared_test.cpp +++ b/src/test/basics/IntrusiveShared_test.cpp @@ -96,13 +96,11 @@ public: { for (int i = 0; i < maxStates; ++i) { - state[i].store( - TrackedState::uninitialized, std::memory_order_release); + state[i].store(TrackedState::uninitialized, std::memory_order_release); } nextId.store(0, std::memory_order_release); if (resetCallback) - TIBase::tracingCallback_ = [](TrackedState, - std::optional) {}; + TIBase::tracingCallback_ = [](TrackedState, std::optional) {}; } struct ResetStatesGuard @@ -129,8 +127,7 @@ public: using enum TrackedState; assert(state.size() > id_); - tracingCallback_( - state[id_].load(std::memory_order_relaxed), deletedStarted); + tracingCallback_(state[id_].load(std::memory_order_relaxed), deletedStarted); assert(state.size() > id_); // Use relaxed memory order to try to avoid atomic operations from @@ -152,9 +149,7 @@ public: using enum TrackedState; assert(state.size() > id_); - tracingCallback_( - state[id_].load(std::memory_order_relaxed), - partiallyDeletedStarted); + tracingCallback_(state[id_].load(std::memory_order_relaxed), partiallyDeletedStarted); assert(state.size() > id_); state[id_].store(partiallyDeletedStarted, std::memory_order_relaxed); @@ -167,8 +162,7 @@ public: tracingCallback_(partiallyDeleted, std::nullopt); } - static std::function)> - tracingCallback_; + static std::function)> tracingCallback_; int id_; @@ -183,8 +177,8 @@ private: std::array, TIBase::maxStates> TIBase::state; std::atomic TIBase::nextId{0}; -std::function)> - TIBase::tracingCallback_ = [](TrackedState, std::optional) {}; +std::function)> TIBase::tracingCallback_ = + [](TrackedState, std::optional) {}; } // namespace @@ -387,8 +381,7 @@ public: bool destructorRan = false; bool partialDeleteRan = false; std::latch partialDeleteStartedSyncPoint{2}; - strong->tracingCallback_ = [&](TrackedState cur, - std::optional next) { + strong->tracingCallback_ = [&](TrackedState cur, std::optional next) { using enum TrackedState; if (next == deletedStarted) { @@ -455,8 +448,7 @@ public: bool destructorRan = false; bool partialDeleteRan = false; std::latch weakResetSyncPoint{2}; - strong->tracingCallback_ = [&](TrackedState cur, - std::optional next) { + strong->tracingCallback_ = [&](TrackedState cur, std::optional next) { using enum TrackedState; if (next == partiallyDeleted) { @@ -502,14 +494,9 @@ public: int s = destructionState.load(std::memory_order_relaxed); return {(s & 1) != 0, (s & 2) != 0}; }; - auto setDestructorRan = [&]() -> void { - destructionState.fetch_or(1, std::memory_order_acq_rel); - }; - auto setPartialDeleteRan = [&]() -> void { - destructionState.fetch_or(2, std::memory_order_acq_rel); - }; - auto tracingCallback = [&](TrackedState cur, - std::optional next) { + auto setDestructorRan = [&]() -> void { destructionState.fetch_or(1, std::memory_order_acq_rel); }; + auto setPartialDeleteRan = [&]() -> void { destructionState.fetch_or(2, std::memory_order_acq_rel); }; + auto tracingCallback = [&](TrackedState cur, std::optional next) { using enum TrackedState; auto [destructorRan, partialDeleteRan] = getDestructorState(); if (next == partiallyDeleted) @@ -523,13 +510,9 @@ public: setDestructorRan(); } }; - auto createVecOfPointers = [&](auto const& toClone, - std::default_random_engine& eng) - -> std::vector< - std::variant, WeakIntrusive>> { - std::vector< - std::variant, WeakIntrusive>> - result; + auto createVecOfPointers = [&](auto const& toClone, std::default_random_engine& eng) + -> std::vector, WeakIntrusive>> { + std::vector, WeakIntrusive>> result; std::uniform_int_distribution<> toCreateDist(4, 64); std::uniform_int_distribution<> isStrongDist(0, 1); auto numToCreate = toCreateDist(eng); @@ -581,8 +564,7 @@ public: // clear the temporary variables. rsg.emplace(false); - auto [destructorRan, partialDeleteRan] = - getDestructorState(); + auto [destructorRan, partialDeleteRan] = getDestructorState(); BEAST_EXPECT(!i || destructorRan); destructionState.store(0, std::memory_order_release); @@ -596,8 +578,7 @@ public: // ------ Sync Point ------ postCreateToCloneSyncPoint.arrive_and_wait(); - auto v = - createVecOfPointers(toClone[threadId], engines[threadId]); + auto v = createVecOfPointers(toClone[threadId], engines[threadId]); toClone[threadId].reset(); // ------ Sync Point ------ @@ -642,14 +623,9 @@ public: int s = destructionState.load(std::memory_order_relaxed); return {(s & 1) != 0, (s & 2) != 0}; }; - auto setDestructorRan = [&]() -> void { - destructionState.fetch_or(1, std::memory_order_acq_rel); - }; - auto setPartialDeleteRan = [&]() -> void { - destructionState.fetch_or(2, std::memory_order_acq_rel); - }; - auto tracingCallback = [&](TrackedState cur, - std::optional next) { + auto setDestructorRan = [&]() -> void { destructionState.fetch_or(1, std::memory_order_acq_rel); }; + auto setPartialDeleteRan = [&]() -> void { destructionState.fetch_or(2, std::memory_order_acq_rel); }; + auto tracingCallback = [&](TrackedState cur, std::optional next) { using enum TrackedState; auto [destructorRan, partialDeleteRan] = getDestructorState(); if (next == partiallyDeleted) @@ -664,8 +640,7 @@ public: } }; auto createVecOfPointers = [&](auto const& toClone, - std::default_random_engine& eng) - -> std::vector> { + std::default_random_engine& eng) -> std::vector> { std::vector> result; std::uniform_int_distribution<> toCreateDist(4, 64); auto numToCreate = toCreateDist(eng); @@ -710,8 +685,7 @@ public: // thread will also check that the destructor ran and // clear the temporary variables. rsg.emplace(false); - auto [destructorRan, partialDeleteRan] = - getDestructorState(); + auto [destructorRan, partialDeleteRan] = getDestructorState(); BEAST_EXPECT(!i || destructorRan); destructionState.store(0, std::memory_order_release); @@ -725,8 +699,7 @@ public: // ------ Sync Point ------ postCreateToCloneSyncPoint.arrive_and_wait(); - auto v = - createVecOfPointers(toClone[threadId], engines[threadId]); + auto v = createVecOfPointers(toClone[threadId], engines[threadId]); toClone[threadId].reset(); // ------ Sync Point ------ @@ -785,14 +758,9 @@ public: int s = destructionState.load(std::memory_order_relaxed); return {(s & 1) != 0, (s & 2) != 0}; }; - auto setDestructorRan = [&]() -> void { - destructionState.fetch_or(1, std::memory_order_acq_rel); - }; - auto setPartialDeleteRan = [&]() -> void { - destructionState.fetch_or(2, std::memory_order_acq_rel); - }; - auto tracingCallback = [&](TrackedState cur, - std::optional next) { + auto setDestructorRan = [&]() -> void { destructionState.fetch_or(1, std::memory_order_acq_rel); }; + auto setPartialDeleteRan = [&]() -> void { destructionState.fetch_or(2, std::memory_order_acq_rel); }; + auto tracingCallback = [&](TrackedState cur, std::optional next) { using enum TrackedState; auto [destructorRan, partialDeleteRan] = getDestructorState(); if (next == partiallyDeleted) @@ -833,8 +801,7 @@ public: // thread will also check that the destructor ran and // clear the temporary variables. rsg.emplace(false); - auto [destructorRan, partialDeleteRan] = - getDestructorState(); + auto [destructorRan, partialDeleteRan] = getDestructorState(); BEAST_EXPECT(!i || destructorRan); destructionState.store(0, std::memory_order_release); diff --git a/src/test/basics/Number_test.cpp b/src/test/basics/Number_test.cpp index 1fa5ae6e8f..13b2d72412 100644 --- a/src/test/basics/Number_test.cpp +++ b/src/test/basics/Number_test.cpp @@ -37,8 +37,7 @@ public: auto const minMantissa = Number::minMantissa(); try { - Number x = - Number{false, minMantissa * 10, 32768, Number::normalized{}}; + Number x = Number{false, minMantissa * 10, 32768, Number::normalized{}}; } catch (std::overflow_error const&) { @@ -57,10 +56,7 @@ public: Number{false, minMantissa * 10, 32767, Number::normalized{}}, Number{false, minMantissa, 32768, Number::normalized{}}, __LINE__); - test( - Number{false, minMantissa, -32769, Number::normalized{}}, - Number{}, - __LINE__); + test(Number{false, minMantissa, -32769, Number::normalized{}}, Number{}, __LINE__); test( Number{false, minMantissa, 32000, Number::normalized{}} * 1'000 + Number{false, 1'500, 32000, Number::normalized{}}, @@ -70,29 +66,24 @@ public: test( Number{std::numeric_limits::min()}, - scale == MantissaRange::small - ? Number{-9'223'372'036'854'776, 3} - : Number{true, 9'223'372'036'854'775'808ULL, 0, Number::normalized{}}, + scale == MantissaRange::small ? Number{-9'223'372'036'854'776, 3} + : Number{true, 9'223'372'036'854'775'808ULL, 0, Number::normalized{}}, __LINE__); test( Number{std::numeric_limits::min() + 1}, - scale == MantissaRange::small ? Number{-9'223'372'036'854'776, 3} - : Number{-9'223'372'036'854'775'807}, + scale == MantissaRange::small ? Number{-9'223'372'036'854'776, 3} : Number{-9'223'372'036'854'775'807}, __LINE__); test( Number{std::numeric_limits::max()}, Number{ - scale == MantissaRange::small - ? 9'223'372'036'854'776 - : std::numeric_limits::max(), + scale == MantissaRange::small ? 9'223'372'036'854'776 : std::numeric_limits::max(), 18 - Number::mantissaLog()}, __LINE__); caught = false; try { [[maybe_unused]] - Number q = - Number{false, minMantissa, 32767, Number::normalized{}} * 100; + Number q = Number{false, minMantissa, 32767, Number::normalized{}} * 100; } catch (std::overflow_error const&) { @@ -123,9 +114,7 @@ public: Number{9'999'999'999'999'344, -16}}, {Number{}, Number{5}, Number{5}}, {Number{5}, Number{}, Number{5}}, - {Number{5'555'555'555'555'555, -32768}, - Number{-5'555'555'555'555'554, -32768}, - Number{0}}, + {Number{5'555'555'555'555'555, -32768}, Number{-5'555'555'555'555'554, -32768}, Number{0}}, {Number{-9'999'999'999'999'999, -31}, Number{1'000'000'000'000'000, -15}, Number{9'999'999'999'999'990, -16}}}); @@ -142,23 +131,13 @@ public: Number{-1'000'000'000'000'065'556, -18}}, {Number{-1'000'000'000'000'000, -15}, Number{6'555'555'555'555'555, -29}, - Number{ - true, - 9'999'999'999'999'344'444ULL, - -19, - Number::normalized{}}}, + Number{true, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}}, {Number{-6'555'555'555'555'555, -29}, Number{1'000'000'000'000'000, -15}, - Number{ - false, - 9'999'999'999'999'344'444ULL, - -19, - Number::normalized{}}}, + Number{false, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}}, {Number{}, Number{5}, Number{5}}, {Number{5}, Number{}, Number{5}}, - {Number{5'555'555'555'555'555'000, -32768}, - Number{-5'555'555'555'555'554'000, -32768}, - Number{0}}, + {Number{5'555'555'555'555'555'000, -32768}, Number{-5'555'555'555'555'554'000, -32768}, Number{0}}, {Number{-9'999'999'999'999'999, -31}, Number{1'000'000'000'000'000, -15}, Number{9'999'999'999'999'990, -16}}, @@ -171,53 +150,23 @@ public: Number{-1'000'000'000'000'000'066, -18}}, {Number{-1'000'000'000'000'000'000, -18}, Number{6'555'555'555'555'555'555, -35}, - Number{ - true, - 9'999'999'999'999'999'344ULL, - -19, - Number::normalized{}}}, + Number{true, 9'999'999'999'999'999'344ULL, -19, Number::normalized{}}}, {Number{-6'555'555'555'555'555'555, -35}, Number{1'000'000'000'000'000'000, -18}, - Number{ - false, - 9'999'999'999'999'999'344ULL, - -19, - Number::normalized{}}}, + Number{false, 9'999'999'999'999'999'344ULL, -19, Number::normalized{}}}, {Number{}, Number{5}, Number{5}}, - {Number{5'555'555'555'555'555'555, -32768}, - Number{-5'555'555'555'555'555'554, -32768}, - Number{0}}, - {Number{ - true, - 9'999'999'999'999'999'999ULL, - -37, - Number::normalized{}}, + {Number{5'555'555'555'555'555'555, -32768}, Number{-5'555'555'555'555'555'554, -32768}, Number{0}}, + {Number{true, 9'999'999'999'999'999'999ULL, -37, Number::normalized{}}, Number{1'000'000'000'000'000'000, -18}, - Number{ - false, - 9'999'999'999'999'999'990ULL, - -19, - Number::normalized{}}}, - {Number{Number::maxRep}, - Number{6, -1}, - Number{Number::maxRep / 10, 1}}, - {Number{Number::maxRep - 1}, - Number{1, 0}, - Number{Number::maxRep}}, + Number{false, 9'999'999'999'999'999'990ULL, -19, Number::normalized{}}}, + {Number{Number::maxRep}, Number{6, -1}, Number{Number::maxRep / 10, 1}}, + {Number{Number::maxRep - 1}, Number{1, 0}, Number{Number::maxRep}}, // Test extremes { // Each Number operand rounds up, so the actual mantissa is // minMantissa - Number{ - false, - 9'999'999'999'999'999'999ULL, - 0, - Number::normalized{}}, - Number{ - false, - 9'999'999'999'999'999'999ULL, - 0, - Number::normalized{}}, + Number{false, 9'999'999'999'999'999'999ULL, 0, Number::normalized{}}, + Number{false, 9'999'999'999'999'999'999ULL, 0, Number::normalized{}}, Number{2, 19}, }, { @@ -226,21 +175,9 @@ public: // With addition using uint128_t, there's no problem. After // normalizing, the resulting mantissa ends up less than // maxRep. - Number{ - false, - 9'999'999'999'999'999'990ULL, - 0, - Number::normalized{}}, - Number{ - false, - 9'999'999'999'999'999'990ULL, - 0, - Number::normalized{}}, - Number{ - false, - 1'999'999'999'999'999'998ULL, - 1, - Number::normalized{}}, + Number{false, 9'999'999'999'999'999'990ULL, 0, Number::normalized{}}, + Number{false, 9'999'999'999'999'999'990ULL, 0, Number::normalized{}}, + Number{false, 1'999'999'999'999'999'998ULL, 1, Number::normalized{}}, }, }); auto test = [this](auto const& c) { @@ -260,14 +197,8 @@ public: bool caught = false; try { - Number{ - false, Number::maxMantissa(), 32768, Number::normalized{}} + - Number{ - false, - Number::minMantissa(), - 32767, - Number::normalized{}} * - 5; + Number{false, Number::maxMantissa(), 32768, Number::normalized{}} + + Number{false, Number::minMantissa(), 32767, Number::normalized{}} * 5; } catch (std::overflow_error const&) { @@ -291,9 +222,7 @@ public: {Number{6'555'555'555'555'555, -29}, Number{1'000'000'000'000'000, -15}, Number{-9'999'999'999'999'344, -16}}, - {Number{1'000'000'000'000'000, -15}, - Number{1'000'000'000'000'000, -15}, - Number{0}}, + {Number{1'000'000'000'000'000, -15}, Number{1'000'000'000'000'000, -15}, Number{0}}, {Number{1'000'000'000'000'000, -15}, Number{1'000'000'000'000'001, -15}, Number{-1'000'000'000'000'000, -30}}, @@ -307,21 +236,11 @@ public: { {Number{1'000'000'000'000'000, -15}, Number{6'555'555'555'555'555, -29}, - Number{ - false, - 9'999'999'999'999'344'444ULL, - -19, - Number::normalized{}}}, + Number{false, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}}, {Number{6'555'555'555'555'555, -29}, Number{1'000'000'000'000'000, -15}, - Number{ - true, - 9'999'999'999'999'344'444ULL, - -19, - Number::normalized{}}}, - {Number{1'000'000'000'000'000, -15}, - Number{1'000'000'000'000'000, -15}, - Number{0}}, + Number{true, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}}, + {Number{1'000'000'000'000'000, -15}, Number{1'000'000'000'000'000, -15}, Number{0}}, {Number{1'000'000'000'000'000, -15}, Number{1'000'000'000'000'001, -15}, Number{-1'000'000'000'000'000, -30}}, @@ -331,36 +250,22 @@ public: // Items from cSmall expanded for the larger mantissa {Number{1'000'000'000'000'000'000, -18}, Number{6'555'555'555'555'555'555, -32}, - Number{ - false, - 9'999'999'999'999'344'444ULL, - -19, - Number::normalized{}}}, + Number{false, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}}, {Number{6'555'555'555'555'555'555, -32}, Number{1'000'000'000'000'000'000, -18}, - Number{ - true, - 9'999'999'999'999'344'444ULL, - -19, - Number::normalized{}}}, - {Number{1'000'000'000'000'000'000, -18}, - Number{1'000'000'000'000'000'000, -18}, - Number{0}}, + Number{true, 9'999'999'999'999'344'444ULL, -19, Number::normalized{}}}, + {Number{1'000'000'000'000'000'000, -18}, Number{1'000'000'000'000'000'000, -18}, Number{0}}, {Number{1'000'000'000'000'000'000, -18}, Number{1'000'000'000'000'000'001, -18}, Number{-1'000'000'000'000'000'000, -36}}, {Number{1'000'000'000'000'000'001, -18}, Number{1'000'000'000'000'000'000, -18}, Number{1'000'000'000'000'000'000, -36}}, - {Number{Number::maxRep}, - Number{6, -1}, - Number{Number::maxRep - 1}}, + {Number{Number::maxRep}, Number{6, -1}, Number{Number::maxRep - 1}}, {Number{false, Number::maxRep + 1, 0, Number::normalized{}}, Number{1, 0}, Number{Number::maxRep / 10 + 1, 1}}, - {Number{false, Number::maxRep + 1, 0, Number::normalized{}}, - Number{3, 0}, - Number{Number::maxRep}}, + {Number{false, Number::maxRep + 1, 0, Number::normalized{}}, Number{3, 0}, Number{Number::maxRep}}, {power(2, 63), Number{3, 0}, Number{Number::maxRep}}, }); auto test = [this](auto const& c) { @@ -406,274 +311,157 @@ public: { auto const cSmall = std::to_array({ {Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{2000000000000000, -15}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-2000000000000000, -15}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{2000000000000000, -15}}, - {Number{3214285714285706, -15}, - Number{3111111111111119, -15}, - Number{1000000000000000, -14}}, - {Number{1000000000000000, -32768}, - Number{1000000000000000, -32768}, - Number{0}}, + {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{2000000000000000, -15}}, + {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-2000000000000000, -15}}, + {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{2000000000000000, -15}}, + {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{1000000000000000, -14}}, + {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}, // Maximum mantissa range - {Number{9'999'999'999'999'999, 0}, - Number{9'999'999'999'999'999, 0}, - Number{9'999'999'999'999'998, 16}}, + {Number{9'999'999'999'999'999, 0}, Number{9'999'999'999'999'999, 0}, Number{9'999'999'999'999'998, 16}}, }); auto const cLarge = std::to_array({ // Note that items with extremely large mantissas need to be // calculated, because otherwise they overflow uint64. Items // from C with larger mantissa {Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{1999999999999999862, -18}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-1999999999999999862, -18}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{1999999999999999862, -18}}, + {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999862, -18}}, + {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999862, -18}}, + {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999862, -18}}, {Number{3214285714285706, -15}, Number{3111111111111119, -15}, - Number{ - false, - 9'999'999'999'999'999'579ULL, - -18, - Number::normalized{}}}, - {Number{1000000000000000000, -32768}, - Number{1000000000000000000, -32768}, - Number{0}}, + Number{false, 9'999'999'999'999'999'579ULL, -18, Number::normalized{}}}, + {Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}}, // Items from cSmall expanded for the larger mantissa, // except duplicates. Sadly, it looks like sqrt(2)^2 != 2 // with higher precision - {Number{1414213562373095049, -18}, - Number{1414213562373095049, -18}, - Number{2000000000000000001, -18}}, + {Number{1414213562373095049, -18}, Number{1414213562373095049, -18}, Number{2000000000000000001, -18}}, {Number{-1414213562373095048, -18}, Number{1414213562373095048, -18}, Number{-1999999999999999998, -18}}, {Number{-1414213562373095048, -18}, Number{-1414213562373095049, -18}, Number{1999999999999999999, -18}}, - {Number{3214285714285714278, -18}, - Number{3111111111111111119, -18}, - Number{10, 0}}, + {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}}, // Maximum mantissa range - rounds up to 1e19 {Number{false, maxMantissa, 0, Number::normalized{}}, Number{false, maxMantissa, 0, Number::normalized{}}, Number{1, 38}}, // Maximum int64 range - {Number{Number::maxRep, 0}, - Number{Number::maxRep, 0}, - Number{85'070'591'730'234'615'85, 19}}, + {Number{Number::maxRep, 0}, Number{Number::maxRep, 0}, Number{85'070'591'730'234'615'85, 19}}, }); tests(cSmall, cLarge); } Number::setround(Number::towards_zero); - testcase << "test_mul " << to_string(Number::getMantissaScale()) - << " towards_zero"; + testcase << "test_mul " << to_string(Number::getMantissaScale()) << " towards_zero"; { auto const cSmall = std::to_array( {{Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{1999999999999999, -15}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-1999999999999999, -15}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{1999999999999999, -15}}, - {Number{3214285714285706, -15}, - Number{3111111111111119, -15}, - Number{9999999999999999, -15}}, - {Number{1000000000000000, -32768}, - Number{1000000000000000, -32768}, - Number{0}}}); + {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999, -15}}, + {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999, -15}}, + {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999, -15}}, + {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{9999999999999999, -15}}, + {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}}); auto const cLarge = std::to_array( // Note that items with extremely large mantissas need to be // calculated, because otherwise they overflow uint64. Items // from C with larger mantissa { {Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{1999999999999999861, -18}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-1999999999999999861, -18}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{1999999999999999861, -18}}, + {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999861, -18}}, + {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999861, -18}}, + {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999861, -18}}, {Number{3214285714285706, -15}, Number{3111111111111119, -15}, - Number{ - false, - 9999999999999999579ULL, - -18, - Number::normalized{}}}, - {Number{1000000000000000000, -32768}, - Number{1000000000000000000, -32768}, - Number{0}}, + Number{false, 9999999999999999579ULL, -18, Number::normalized{}}}, + {Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}}, // Items from cSmall expanded for the larger mantissa, // except duplicates. Sadly, it looks like sqrt(2)^2 != 2 // with higher precision - {Number{1414213562373095049, -18}, - Number{1414213562373095049, -18}, - Number{2, 0}}, + {Number{1414213562373095049, -18}, Number{1414213562373095049, -18}, Number{2, 0}}, {Number{-1414213562373095048, -18}, Number{1414213562373095048, -18}, Number{-1999999999999999997, -18}}, {Number{-1414213562373095048, -18}, Number{-1414213562373095049, -18}, Number{1999999999999999999, -18}}, - {Number{3214285714285714278, -18}, - Number{3111111111111111119, -18}, - Number{10, 0}}, + {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}}, // Maximum mantissa range - rounds down to maxMantissa/10e1 // 99'999'999'999'999'999'800'000'000'000'000'000'100 {Number{false, maxMantissa, 0, Number::normalized{}}, Number{false, maxMantissa, 0, Number::normalized{}}, - Number{ - false, - maxMantissa / 10 - 1, - 20, - Number::normalized{}}}, + Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}}}, // Maximum int64 range // 85'070'591'730'234'615'847'396'907'784'232'501'249 - {Number{Number::maxRep, 0}, - Number{Number::maxRep, 0}, - Number{85'070'591'730'234'615'84, 19}}, + {Number{Number::maxRep, 0}, Number{Number::maxRep, 0}, Number{85'070'591'730'234'615'84, 19}}, }); tests(cSmall, cLarge); } Number::setround(Number::downward); - testcase << "test_mul " << to_string(Number::getMantissaScale()) - << " downward"; + testcase << "test_mul " << to_string(Number::getMantissaScale()) << " downward"; { auto const cSmall = std::to_array( {{Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{1999999999999999, -15}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-2000000000000000, -15}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{1999999999999999, -15}}, - {Number{3214285714285706, -15}, - Number{3111111111111119, -15}, - Number{9999999999999999, -15}}, - {Number{1000000000000000, -32768}, - Number{1000000000000000, -32768}, - Number{0}}}); + {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999, -15}}, + {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-2000000000000000, -15}}, + {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999, -15}}, + {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{9999999999999999, -15}}, + {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}}); auto const cLarge = std::to_array( // Note that items with extremely large mantissas need to be // calculated, because otherwise they overflow uint64. Items // from C with larger mantissa { {Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{1999999999999999861, -18}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-1999999999999999862, -18}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{1999999999999999861, -18}}, + {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999861, -18}}, + {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999862, -18}}, + {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999861, -18}}, {Number{3214285714285706, -15}, Number{3111111111111119, -15}, - Number{ - false, - 9'999'999'999'999'999'579ULL, - -18, - Number::normalized{}}}, - {Number{1000000000000000000, -32768}, - Number{1000000000000000000, -32768}, - Number{0}}, + Number{false, 9'999'999'999'999'999'579ULL, -18, Number::normalized{}}}, + {Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}}, // Items from cSmall expanded for the larger mantissa, // except duplicates. Sadly, it looks like sqrt(2)^2 != 2 // with higher precision - {Number{1414213562373095049, -18}, - Number{1414213562373095049, -18}, - Number{2, 0}}, + {Number{1414213562373095049, -18}, Number{1414213562373095049, -18}, Number{2, 0}}, {Number{-1414213562373095048, -18}, Number{1414213562373095048, -18}, Number{-1999999999999999998, -18}}, {Number{-1414213562373095048, -18}, Number{-1414213562373095049, -18}, Number{1999999999999999999, -18}}, - {Number{3214285714285714278, -18}, - Number{3111111111111111119, -18}, - Number{10, 0}}, + {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{10, 0}}, // Maximum mantissa range - rounds down to maxMantissa/10e1 // 99'999'999'999'999'999'800'000'000'000'000'000'100 {Number{false, maxMantissa, 0, Number::normalized{}}, Number{false, maxMantissa, 0, Number::normalized{}}, - Number{ - false, - maxMantissa / 10 - 1, - 20, - Number::normalized{}}}, + Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}}}, // Maximum int64 range // 85'070'591'730'234'615'847'396'907'784'232'501'249 - {Number{Number::maxRep, 0}, - Number{Number::maxRep, 0}, - Number{85'070'591'730'234'615'84, 19}}, + {Number{Number::maxRep, 0}, Number{Number::maxRep, 0}, Number{85'070'591'730'234'615'84, 19}}, }); tests(cSmall, cLarge); } Number::setround(Number::upward); - testcase << "test_mul " << to_string(Number::getMantissaScale()) - << " upward"; + testcase << "test_mul " << to_string(Number::getMantissaScale()) << " upward"; { auto const cSmall = std::to_array( {{Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{2000000000000000, -15}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-1999999999999999, -15}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{2000000000000000, -15}}, - {Number{3214285714285706, -15}, - Number{3111111111111119, -15}, - Number{1000000000000000, -14}}, - {Number{1000000000000000, -32768}, - Number{1000000000000000, -32768}, - Number{0}}}); + {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{2000000000000000, -15}}, + {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999, -15}}, + {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{2000000000000000, -15}}, + {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{1000000000000000, -14}}, + {Number{1000000000000000, -32768}, Number{1000000000000000, -32768}, Number{0}}}); auto const cLarge = std::to_array( // Note that items with extremely large mantissas need to be // calculated, because otherwise they overflow uint64. Items // from C with larger mantissa { {Number{7}, Number{8}, Number{56}}, - {Number{1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{1999999999999999862, -18}}, - {Number{-1414213562373095, -15}, - Number{1414213562373095, -15}, - Number{-1999999999999999861, -18}}, - {Number{-1414213562373095, -15}, - Number{-1414213562373095, -15}, - Number{1999999999999999862, -18}}, - {Number{3214285714285706, -15}, - Number{3111111111111119, -15}, - Number{999999999999999958, -17}}, - {Number{1000000000000000000, -32768}, - Number{1000000000000000000, -32768}, - Number{0}}, + {Number{1414213562373095, -15}, Number{1414213562373095, -15}, Number{1999999999999999862, -18}}, + {Number{-1414213562373095, -15}, Number{1414213562373095, -15}, Number{-1999999999999999861, -18}}, + {Number{-1414213562373095, -15}, Number{-1414213562373095, -15}, Number{1999999999999999862, -18}}, + {Number{3214285714285706, -15}, Number{3111111111111119, -15}, Number{999999999999999958, -17}}, + {Number{1000000000000000000, -32768}, Number{1000000000000000000, -32768}, Number{0}}, // Items from cSmall expanded for the larger mantissa, // except duplicates. Sadly, it looks like sqrt(2)^2 != 2 // with higher precision @@ -683,9 +471,7 @@ public: {Number{-1414213562373095048, -18}, Number{1414213562373095048, -18}, Number{-1999999999999999997, -18}}, - {Number{-1414213562373095048, -18}, - Number{-1414213562373095049, -18}, - Number{2, 0}}, + {Number{-1414213562373095048, -18}, Number{-1414213562373095049, -18}, Number{2, 0}}, {Number{3214285714285714278, -18}, Number{3111111111111111119, -18}, Number{1000000000000000001, -17}}, @@ -696,24 +482,17 @@ public: Number{1, 38}}, // Maximum int64 range // 85'070'591'730'234'615'847'396'907'784'232'501'249 - {Number{Number::maxRep, 0}, - Number{Number::maxRep, 0}, - Number{85'070'591'730'234'615'85, 19}}, + {Number{Number::maxRep, 0}, Number{Number::maxRep, 0}, Number{85'070'591'730'234'615'85, 19}}, }); tests(cSmall, cLarge); } - testcase << "test_mul " << to_string(Number::getMantissaScale()) - << " overflow"; + testcase << "test_mul " << to_string(Number::getMantissaScale()) << " overflow"; { bool caught = false; try { Number{false, maxMantissa, 32768, Number::normalized{}} * - Number{ - false, - Number::minMantissa() * 5, - 32767, - Number::normalized{}}; + Number{false, Number::minMantissa() * 5, 32767, Number::normalized{}}; } catch (std::overflow_error const&) { @@ -753,12 +532,8 @@ public: {Number{1}, Number{10}, Number{1, -1}}, {Number{1}, Number{-10}, Number{-1, -1}}, {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, + {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}}, + {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}}, {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}}, {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}}, {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}}); @@ -770,29 +545,20 @@ public: {Number{1}, Number{10}, Number{1, -1}}, {Number{1}, Number{-10}, Number{-1, -1}}, {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, + {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}}, + {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}}, {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}}, - {Number{-2}, - Number{3}, - Number{-6'666'666'666'666'666'667, -19}}, + {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'667, -19}}, {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}}, // Items from cSmall expanded for the larger mantissa, except // duplicates. - {Number{1414213562373095049, -13}, - Number{1414213562373095049, -13}, - Number{1}}, + {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}}, {Number{false, maxMantissa, 0, Number::normalized{}}, Number{1'000'000'000'000'000'000}, Number{false, maxMantissa, -18, Number::normalized{}}}}); tests(cSmall, cLarge); } - testcase << "test_div " << to_string(Number::getMantissaScale()) - << " towards_zero"; + testcase << "test_div " << to_string(Number::getMantissaScale()) << " towards_zero"; Number::setround(Number::towards_zero); { auto const cSmall = std::to_array( @@ -800,12 +566,8 @@ public: {Number{1}, Number{10}, Number{1, -1}}, {Number{1}, Number{-10}, Number{-1, -1}}, {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, + {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}}, + {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}}, {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}}, {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}}, {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}}); @@ -817,29 +579,20 @@ public: {Number{1}, Number{10}, Number{1, -1}}, {Number{1}, Number{-10}, Number{-1, -1}}, {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, + {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}}, + {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}}, {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}}, - {Number{-2}, - Number{3}, - Number{-6'666'666'666'666'666'666, -19}}, + {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'666, -19}}, {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}}, // Items from cSmall expanded for the larger mantissa, except // duplicates. - {Number{1414213562373095049, -13}, - Number{1414213562373095049, -13}, - Number{1}}, + {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}}, {Number{false, maxMantissa, 0, Number::normalized{}}, Number{1'000'000'000'000'000'000}, Number{false, maxMantissa, -18, Number::normalized{}}}}); tests(cSmall, cLarge); } - testcase << "test_div " << to_string(Number::getMantissaScale()) - << " downward"; + testcase << "test_div " << to_string(Number::getMantissaScale()) << " downward"; Number::setround(Number::downward); { auto const cSmall = std::to_array( @@ -847,12 +600,8 @@ public: {Number{1}, Number{10}, Number{1, -1}}, {Number{1}, Number{-10}, Number{-1, -1}}, {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, + {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}}, + {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}}, {Number{2}, Number{3}, Number{6'666'666'666'666'666, -16}}, {Number{-2}, Number{3}, Number{-6'666'666'666'666'667, -16}}, {Number{1}, Number{7}, Number{1'428'571'428'571'428, -16}}}); @@ -864,29 +613,20 @@ public: {Number{1}, Number{10}, Number{1, -1}}, {Number{1}, Number{-10}, Number{-1, -1}}, {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, + {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}}, + {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}}, {Number{2}, Number{3}, Number{6'666'666'666'666'666'666, -19}}, - {Number{-2}, - Number{3}, - Number{-6'666'666'666'666'666'667, -19}}, + {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'667, -19}}, {Number{1}, Number{7}, Number{1'428'571'428'571'428'571, -19}}, // Items from cSmall expanded for the larger mantissa, except // duplicates. - {Number{1414213562373095049, -13}, - Number{1414213562373095049, -13}, - Number{1}}, + {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}}, {Number{false, maxMantissa, 0, Number::normalized{}}, Number{1'000'000'000'000'000'000}, Number{false, maxMantissa, -18, Number::normalized{}}}}); tests(cSmall, cLarge); } - testcase << "test_div " << to_string(Number::getMantissaScale()) - << " upward"; + testcase << "test_div " << to_string(Number::getMantissaScale()) << " upward"; Number::setround(Number::upward); { auto const cSmall = std::to_array( @@ -894,12 +634,8 @@ public: {Number{1}, Number{10}, Number{1, -1}}, {Number{1}, Number{-10}, Number{-1, -1}}, {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, + {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}}, + {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}}, {Number{2}, Number{3}, Number{6'666'666'666'666'667, -16}}, {Number{-2}, Number{3}, Number{-6'666'666'666'666'666, -16}}, {Number{1}, Number{7}, Number{1'428'571'428'571'429, -16}}}); @@ -911,29 +647,20 @@ public: {Number{1}, Number{10}, Number{1, -1}}, {Number{1}, Number{-10}, Number{-1, -1}}, {Number{0}, Number{100}, Number{0}}, - {Number{1414213562373095, -10}, - Number{1414213562373095, -10}, - Number{1}}, - {Number{9'999'999'999'999'999}, - Number{1'000'000'000'000'000}, - Number{9'999'999'999'999'999, -15}}, + {Number{1414213562373095, -10}, Number{1414213562373095, -10}, Number{1}}, + {Number{9'999'999'999'999'999}, Number{1'000'000'000'000'000}, Number{9'999'999'999'999'999, -15}}, {Number{2}, Number{3}, Number{6'666'666'666'666'666'667, -19}}, - {Number{-2}, - Number{3}, - Number{-6'666'666'666'666'666'666, -19}}, + {Number{-2}, Number{3}, Number{-6'666'666'666'666'666'666, -19}}, {Number{1}, Number{7}, Number{1'428'571'428'571'428'572, -19}}, // Items from cSmall expanded for the larger mantissa, except // duplicates. - {Number{1414213562373095049, -13}, - Number{1414213562373095049, -13}, - Number{1}}, + {Number{1414213562373095049, -13}, Number{1414213562373095049, -13}, Number{1}}, {Number{false, maxMantissa, 0, Number::normalized{}}, Number{1'000'000'000'000'000'000}, Number{false, maxMantissa, -18, Number::normalized{}}}}); tests(cSmall, cLarge); } - testcase << "test_div " << to_string(Number::getMantissaScale()) - << " overflow"; + testcase << "test_div " << to_string(Number::getMantissaScale()) << " overflow"; bool caught = false; try { @@ -958,8 +685,7 @@ public: { auto const result = root(x, y); std::stringstream ss; - ss << "root(" << x << ", " << y << ") = " << result - << ". Expected: " << z; + ss << "root(" << x << ", " << y << ") = " << result << ". Expected: " << z; BEAST_EXPECTS(result == z, ss.str()); } }; @@ -987,14 +713,9 @@ public: Number{false, 999'999'999'999'999'999, -9, Number::normalized{}}}, {Number{false, Number::maxMantissa() - 9, 0, Number::normalized{}}, 2, - Number{ - false, 3'162'277'660'168'379'330, -9, Number::normalized{}}}, - {Number{Number::maxRep}, - 2, - Number{false, 3'037'000'499'976049692, -9, Number::normalized{}}}, - {Number{Number::maxRep}, - 4, - Number{false, 55'108'98747006743627, -14, Number::normalized{}}}, + Number{false, 3'162'277'660'168'379'330, -9, Number::normalized{}}}, + {Number{Number::maxRep}, 2, Number{false, 3'037'000'499'976049692, -9, Number::normalized{}}}, + {Number{Number::maxRep}, 4, Number{false, 55'108'98747006743627, -14, Number::normalized{}}}, }); test(cSmall); if (Number::getMantissaScale() != MantissaRange::small) @@ -1036,8 +757,7 @@ public: auto const expected = root(x, 2); auto const result = root2(x); std::stringstream ss; - ss << "root2(" << x << ") = " << result - << ". Expected: " << expected; + ss << "root2(" << x << ") = " << result << ". Expected: " << expected; BEAST_EXPECTS(result == expected, ss.str()); } }; @@ -1078,12 +798,8 @@ public: {Number{-64}, 2, Number{4096}}, {Number{64}, 3, Number{262144}}, {Number{-64}, 3, Number{-262144}}, - {Number{64}, - 11, - Number{false, 7378697629483820646ULL, 1, Number::normalized{}}}, - {Number{-64}, - 11, - Number{true, 7378697629483820646ULL, 1, Number::normalized{}}}}; + {Number{64}, 11, Number{false, 7378697629483820646ULL, 1, Number::normalized{}}}, + {Number{-64}, 11, Number{true, 7378697629483820646ULL, 1, Number::normalized{}}}}; for (auto const& [x, y, z] : c) BEAST_EXPECT((power(x, y) == z)); } @@ -1384,34 +1100,14 @@ public: auto const maxMantissa = Number::maxMantissa(); BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999); - test( - Number{ - false, - maxMantissa * 1000 + 999, - -3, - Number::normalized()}, - "9999999999999999"); - test( - Number{ - true, - maxMantissa * 1000 + 999, - -3, - Number::normalized()}, - "-9999999999999999"); + test(Number{false, maxMantissa * 1000 + 999, -3, Number::normalized()}, "9999999999999999"); + test(Number{true, maxMantissa * 1000 + 999, -3, Number::normalized()}, "-9999999999999999"); - test( - Number{std::numeric_limits::max(), -3}, - "9223372036854775"); - test( - -(Number{std::numeric_limits::max(), -3}), - "-9223372036854775"); + test(Number{std::numeric_limits::max(), -3}, "9223372036854775"); + test(-(Number{std::numeric_limits::max(), -3}), "-9223372036854775"); - test( - Number{std::numeric_limits::min(), 0}, - "-9223372036854775e3"); - test( - -(Number{std::numeric_limits::min(), 0}), - "9223372036854775e3"); + test(Number{std::numeric_limits::min(), 0}, "-9223372036854775e3"); + test(-(Number{std::numeric_limits::min(), 0}), "9223372036854775e3"); } break; case MantissaRange::large: @@ -1425,37 +1121,21 @@ public: auto const maxMantissa = Number::maxMantissa(); BEAST_EXPECT(maxMantissa == 9'999'999'999'999'999'999ULL); - test( - Number{false, maxMantissa, 0, Number::normalized{}}, - "9999999999999999990"); - test( - Number{true, maxMantissa, 0, Number::normalized{}}, - "-9999999999999999990"); + test(Number{false, maxMantissa, 0, Number::normalized{}}, "9999999999999999990"); + test(Number{true, maxMantissa, 0, Number::normalized{}}, "-9999999999999999990"); - test( - Number{std::numeric_limits::max(), 0}, - "9223372036854775807"); - test( - -(Number{std::numeric_limits::max(), 0}), - "-9223372036854775807"); + test(Number{std::numeric_limits::max(), 0}, "9223372036854775807"); + test(-(Number{std::numeric_limits::max(), 0}), "-9223372036854775807"); // Because the absolute value of min is larger than max, it // will be scaled down to fit under max. Since we're // rounding towards zero, the 8 at the end is dropped. - test( - Number{std::numeric_limits::min(), 0}, - "-9223372036854775800"); - test( - -(Number{std::numeric_limits::min(), 0}), - "9223372036854775800"); + test(Number{std::numeric_limits::min(), 0}, "-9223372036854775800"); + test(-(Number{std::numeric_limits::min(), 0}), "9223372036854775800"); } - test( - Number{std::numeric_limits::max(), 0} + 1, - "9223372036854775810"); - test( - -(Number{std::numeric_limits::max(), 0} + 1), - "-9223372036854775810"); + test(Number{std::numeric_limits::max(), 0} + 1, "9223372036854775810"); + test(-(Number{std::numeric_limits::max(), 0} + 1), "-9223372036854775810"); break; default: BEAST_EXPECT(false); @@ -1465,8 +1145,7 @@ public: void test_relationals() { - testcase << "test_relationals " - << to_string(Number::getMantissaScale()); + testcase << "test_relationals " << to_string(Number::getMantissaScale()); BEAST_EXPECT(!(Number{100} < Number{10})); BEAST_EXPECT(Number{100} > Number{10}); BEAST_EXPECT(Number{100} >= Number{10}); @@ -1554,87 +1233,39 @@ public: std::map const expected{ // Positive numbers {Number{13, -1}, - {{Number::to_nearest, 1}, - {Number::towards_zero, 1}, - {Number::downward, 1}, - {Number::upward, 2}}}, + {{Number::to_nearest, 1}, {Number::towards_zero, 1}, {Number::downward, 1}, {Number::upward, 2}}}, {Number{23, -1}, - {{Number::to_nearest, 2}, - {Number::towards_zero, 2}, - {Number::downward, 2}, - {Number::upward, 3}}}, + {{Number::to_nearest, 2}, {Number::towards_zero, 2}, {Number::downward, 2}, {Number::upward, 3}}}, {Number{15, -1}, - {{Number::to_nearest, 2}, - {Number::towards_zero, 1}, - {Number::downward, 1}, - {Number::upward, 2}}}, + {{Number::to_nearest, 2}, {Number::towards_zero, 1}, {Number::downward, 1}, {Number::upward, 2}}}, {Number{25, -1}, - {{Number::to_nearest, 2}, - {Number::towards_zero, 2}, - {Number::downward, 2}, - {Number::upward, 3}}}, + {{Number::to_nearest, 2}, {Number::towards_zero, 2}, {Number::downward, 2}, {Number::upward, 3}}}, {Number{152, -2}, - {{Number::to_nearest, 2}, - {Number::towards_zero, 1}, - {Number::downward, 1}, - {Number::upward, 2}}}, + {{Number::to_nearest, 2}, {Number::towards_zero, 1}, {Number::downward, 1}, {Number::upward, 2}}}, {Number{252, -2}, - {{Number::to_nearest, 3}, - {Number::towards_zero, 2}, - {Number::downward, 2}, - {Number::upward, 3}}}, + {{Number::to_nearest, 3}, {Number::towards_zero, 2}, {Number::downward, 2}, {Number::upward, 3}}}, {Number{17, -1}, - {{Number::to_nearest, 2}, - {Number::towards_zero, 1}, - {Number::downward, 1}, - {Number::upward, 2}}}, + {{Number::to_nearest, 2}, {Number::towards_zero, 1}, {Number::downward, 1}, {Number::upward, 2}}}, {Number{27, -1}, - {{Number::to_nearest, 3}, - {Number::towards_zero, 2}, - {Number::downward, 2}, - {Number::upward, 3}}}, + {{Number::to_nearest, 3}, {Number::towards_zero, 2}, {Number::downward, 2}, {Number::upward, 3}}}, // Negative numbers {Number{-13, -1}, - {{Number::to_nearest, -1}, - {Number::towards_zero, -1}, - {Number::downward, -2}, - {Number::upward, -1}}}, + {{Number::to_nearest, -1}, {Number::towards_zero, -1}, {Number::downward, -2}, {Number::upward, -1}}}, {Number{-23, -1}, - {{Number::to_nearest, -2}, - {Number::towards_zero, -2}, - {Number::downward, -3}, - {Number::upward, -2}}}, + {{Number::to_nearest, -2}, {Number::towards_zero, -2}, {Number::downward, -3}, {Number::upward, -2}}}, {Number{-15, -1}, - {{Number::to_nearest, -2}, - {Number::towards_zero, -1}, - {Number::downward, -2}, - {Number::upward, -1}}}, + {{Number::to_nearest, -2}, {Number::towards_zero, -1}, {Number::downward, -2}, {Number::upward, -1}}}, {Number{-25, -1}, - {{Number::to_nearest, -2}, - {Number::towards_zero, -2}, - {Number::downward, -3}, - {Number::upward, -2}}}, + {{Number::to_nearest, -2}, {Number::towards_zero, -2}, {Number::downward, -3}, {Number::upward, -2}}}, {Number{-152, -2}, - {{Number::to_nearest, -2}, - {Number::towards_zero, -1}, - {Number::downward, -2}, - {Number::upward, -1}}}, + {{Number::to_nearest, -2}, {Number::towards_zero, -1}, {Number::downward, -2}, {Number::upward, -1}}}, {Number{-252, -2}, - {{Number::to_nearest, -3}, - {Number::towards_zero, -2}, - {Number::downward, -3}, - {Number::upward, -2}}}, + {{Number::to_nearest, -3}, {Number::towards_zero, -2}, {Number::downward, -3}, {Number::upward, -2}}}, {Number{-17, -1}, - {{Number::to_nearest, -2}, - {Number::towards_zero, -1}, - {Number::downward, -2}, - {Number::upward, -1}}}, + {{Number::to_nearest, -2}, {Number::towards_zero, -1}, {Number::downward, -2}, {Number::upward, -1}}}, {Number{-27, -1}, - {{Number::to_nearest, -3}, - {Number::towards_zero, -2}, - {Number::downward, -3}, - {Number::upward, -2}}}, + {{Number::to_nearest, -3}, {Number::towards_zero, -2}, {Number::downward, -3}, {Number::upward, -2}}}, }; for (auto const& [num, roundings] : expected) @@ -1645,9 +1276,8 @@ public: auto const res = static_cast(num); BEAST_EXPECTS( res == val, - to_string(num) + " with mode " + std::to_string(mode) + - " expected " + std::to_string(val) + " got " + - std::to_string(res)); + to_string(num) + " with mode " + std::to_string(mode) + " expected " + std::to_string(val) + + " got " + std::to_string(res)); } } } @@ -1665,8 +1295,7 @@ public: if (scale == MantissaRange::small) { - BEAST_EXPECT( - std::numeric_limits::max() > INITIAL_XRP.drops()); + BEAST_EXPECT(std::numeric_limits::max() > INITIAL_XRP.drops()); BEAST_EXPECT(Number::maxMantissa() < INITIAL_XRP.drops()); Number const initalXrp{INITIAL_XRP}; BEAST_EXPECT(initalXrp.exponent() > 0); @@ -1674,19 +1303,16 @@ public: Number const maxInt64{Number::maxRep}; BEAST_EXPECT(maxInt64.exponent() > 0); // 85'070'591'730'234'615'865'843'651'857'942'052'864 - 38 digits - BEAST_EXPECT( - (power(maxInt64, 2) == Number{85'070'591'730'234'62, 22})); + BEAST_EXPECT((power(maxInt64, 2) == Number{85'070'591'730'234'62, 22})); - Number const max = - Number{false, Number::maxMantissa(), 0, Number::normalized{}}; + Number const max = Number{false, Number::maxMantissa(), 0, Number::normalized{}}; BEAST_EXPECT(max.exponent() <= 0); // 99'999'999'999'999'980'000'000'000'000'001 - 32 digits BEAST_EXPECT((power(max, 2) == Number{99'999'999'999'999'98, 16})); } else { - BEAST_EXPECT( - std::numeric_limits::max() > INITIAL_XRP.drops()); + BEAST_EXPECT(std::numeric_limits::max() > INITIAL_XRP.drops()); BEAST_EXPECT(Number::maxMantissa() > INITIAL_XRP.drops()); Number const initalXrp{INITIAL_XRP}; BEAST_EXPECT(initalXrp.exponent() <= 0); @@ -1694,21 +1320,17 @@ public: Number const maxInt64{Number::maxRep}; BEAST_EXPECT(maxInt64.exponent() <= 0); // 85'070'591'730'234'615'847'396'907'784'232'501'249 - 38 digits - BEAST_EXPECT( - (power(maxInt64, 2) == Number{85'070'591'730'234'615'85, 19})); + BEAST_EXPECT((power(maxInt64, 2) == Number{85'070'591'730'234'615'85, 19})); NumberRoundModeGuard mg(Number::towards_zero); auto const maxMantissa = Number::maxMantissa(); - Number const max = - Number{false, maxMantissa, 0, Number::normalized{}}; + Number const max = Number{false, maxMantissa, 0, Number::normalized{}}; BEAST_EXPECT(max.mantissa() == maxMantissa / 10); BEAST_EXPECT(max.exponent() == 1); // 99'999'999'999'999'999'800'000'000'000'000'000'100 - also 38 // digits - BEAST_EXPECT(( - power(max, 2) == - Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}})); + BEAST_EXPECT((power(max, 2) == Number{false, maxMantissa / 10 - 1, 20, Number::normalized{}})); } } diff --git a/src/test/basics/PerfLog_test.cpp b/src/test/basics/PerfLog_test.cpp index 06944bb5ce..57eed2aed9 100644 --- a/src/test/basics/PerfLog_test.cpp +++ b/src/test/basics/PerfLog_test.cpp @@ -28,11 +28,7 @@ class PerfLog_test : public beast::unit_test::suite // We're only using Env for its Journal. That Journal gives better // coverage in unit tests. - test::jtx::Env env_{ - *this, - test::jtx::envconfig(), - nullptr, - beast::severities::kDisabled}; + test::jtx::Env env_{*this, test::jtx::envconfig(), nullptr, beast::severities::kDisabled}; beast::Journal j_{env_.app().journal("PerfLog_test")}; struct Fixture @@ -89,10 +85,8 @@ class PerfLog_test : public beast::unit_test::suite std::unique_ptr perfLog(WithFile withFile) { - perf::PerfLog::Setup const setup{ - withFile == WithFile::no ? "" : logFile(), logInterval()}; - return perf::make_PerfLog( - setup, app_, j_, [this]() { return signalStop(); }); + perf::PerfLog::Setup const setup{withFile == WithFile::no ? "" : logFile(), logInterval()}; + return perf::make_PerfLog(setup, app_, j_, [this]() { return signalStop(); }); } // Block until the log file has grown in size, indicating that the @@ -156,20 +150,16 @@ class PerfLog_test : public beast::unit_test::suite { currents.emplace_back( jsonToUint64(cur[jss::duration_us]), - cur.isMember(jss::job) ? cur[jss::job].asString() - : cur[jss::method].asString()); + cur.isMember(jss::job) ? cur[jss::job].asString() : cur[jss::method].asString()); } // Note that the longest durations should be at the front of the // vector since they were started first. - std::sort( - currents.begin(), - currents.end(), - [](Cur const& lhs, Cur const& rhs) { - if (lhs.dur != rhs.dur) - return (rhs.dur < lhs.dur); - return (lhs.name < rhs.name); - }); + std::sort(currents.begin(), currents.end(), [](Cur const& lhs, Cur const& rhs) { + if (lhs.dur != rhs.dur) + return (rhs.dur < lhs.dur); + return (lhs.name < rhs.name); + }); return currents; } @@ -200,8 +190,7 @@ public: { // Make a file that prevents PerfLog from creating its file. std::ofstream nastyFile; - nastyFile.open( - fixture.logDir().c_str(), std::ios::out | std::ios::app); + nastyFile.open(fixture.logDir().c_str(), std::ios::out | std::ios::app); if (!BEAST_EXPECT(nastyFile)) return; nastyFile.close(); @@ -239,24 +228,20 @@ public: return; auto fileWriteable = [](boost::filesystem::path const& p) -> bool { - return std::ofstream{p.c_str(), std::ios::out | std::ios::app} - .is_open(); + return std::ofstream{p.c_str(), std::ios::out | std::ios::app}.is_open(); }; if (!BEAST_EXPECT(fileWriteable(fixture.logFile()))) return; boost::filesystem::permissions( - fixture.logFile(), - perms::remove_perms | perms::owner_write | perms::others_write | - perms::group_write); + fixture.logFile(), perms::remove_perms | perms::owner_write | perms::others_write | perms::group_write); // If the test is running as root, then the write protect may have // no effect. Make sure write protect worked before proceeding. if (fileWriteable(fixture.logFile())) { - log << "Unable to write protect file. Test skipped." - << std::endl; + log << "Unable to write protect file. Test skipped." << std::endl; return; } @@ -275,9 +260,7 @@ public: // Fix file permissions so the file can be cleaned up. boost::filesystem::permissions( - fixture.logFile(), - perms::add_perms | perms::owner_write | perms::others_write | - perms::group_write); + fixture.logFile(), perms::add_perms | perms::owner_write | perms::others_write | perms::group_write); } } @@ -292,8 +275,7 @@ public: // Get the all the labels we can use for RPC interfaces without // causing an assert. - std::vector labels = - test::jtx::make_vector(xrpl::RPC::getHandlerNames()); + std::vector labels = test::jtx::make_vector(xrpl::RPC::getHandlerNames()); std::shuffle(labels.begin(), labels.end(), default_prng()); // Get two IDs to associate with each label. Errors tend to happen at @@ -302,15 +284,11 @@ public: std::vector ids; ids.reserve(labels.size() * 2); std::generate_n( - std::back_inserter(ids), - labels.size(), - [i = std::numeric_limits::min()]() mutable { + std::back_inserter(ids), labels.size(), [i = std::numeric_limits::min()]() mutable { return i++; }); std::generate_n( - std::back_inserter(ids), - labels.size(), - [i = std::numeric_limits::max()]() mutable { + std::back_inserter(ids), labels.size(), [i = std::numeric_limits::max()]() mutable { return i--; }); std::shuffle(ids.begin(), ids.end(), default_prng()); @@ -322,8 +300,7 @@ public: for (int idIndex = 0; idIndex < 2; ++idIndex) { std::this_thread::sleep_for(std::chrono::microseconds(10)); - perfLog->rpcStart( - labels[labelIndex], ids[(labelIndex * 2) + idIndex]); + perfLog->rpcStart(labels[labelIndex], ids[(labelIndex * 2) + idIndex]); } } { @@ -350,8 +327,7 @@ public: // Verify that every entry in labels appears twice in currents. // If we sort by duration_us they should be in the order the // rpcStart() call was made. - std::vector const currents{ - getSortedCurrent(perfLog->currentJson()[jss::methods])}; + std::vector const currents{getSortedCurrent(perfLog->currentJson()[jss::methods])}; BEAST_EXPECT(currents.size() == labels.size() * 2); std::uint64_t prevDur = std::numeric_limits::max(); @@ -376,8 +352,7 @@ public: perfLog->rpcFinish(labels[0], ids[0 + 1]); // Note that label[0] id[0] is intentionally left unfinished. - auto validateFinalCounters = [this, &labels]( - Json::Value const& countersJson) { + auto validateFinalCounters = [this, &labels](Json::Value const& countersJson) { { Json::Value const& jobQueue = countersJson[jss::job_queue]; BEAST_EXPECT(jobQueue.isObject()); @@ -404,8 +379,7 @@ public: for (int i = 1; i < labels.size(); ++i) { Json::Value const& counter{rpc[labels[i]]}; - std::uint64_t const dur{ - jsonToUint64(counter[jss::duration_us])}; + std::uint64_t const dur{jsonToUint64(counter[jss::duration_us])}; BEAST_EXPECT(dur != 0 && dur < prevDur); prevDur = dur; BEAST_EXPECT(counter[jss::errored] == "1"); @@ -416,15 +390,12 @@ public: // Check "total" Json::Value const& total{rpc[jss::total]}; BEAST_EXPECT(total[jss::duration_us] != "0"); - BEAST_EXPECT( - jsonToUint64(total[jss::errored]) == labels.size() - 1); + BEAST_EXPECT(jsonToUint64(total[jss::errored]) == labels.size() - 1); BEAST_EXPECT(jsonToUint64(total[jss::finished]) == labels.size()); - BEAST_EXPECT( - jsonToUint64(total[jss::started]) == labels.size() * 2); + BEAST_EXPECT(jsonToUint64(total[jss::started]) == labels.size() * 2); }; - auto validateFinalCurrent = [this, - &labels](Json::Value const& currentJson) { + auto validateFinalCurrent = [this, &labels](Json::Value const& currentJson) { { Json::Value const& job_queue = currentJson[jss::jobs]; BEAST_EXPECT(job_queue.isArray()); @@ -503,8 +474,7 @@ public: JobType type; std::string typeName; - JobName(JobType t, std::string name) - : type(t), typeName(std::move(name)) + JobName(JobType t, std::string name) : type(t), typeName(std::move(name)) { } }; @@ -525,8 +495,7 @@ public: for (int i = 0; i < jobs.size(); ++i) { perfLog->jobQueue(jobs[i].type); - Json::Value const jq_counters{ - perfLog->countersJson()[jss::job_queue]}; + Json::Value const jq_counters{perfLog->countersJson()[jss::job_queue]}; BEAST_EXPECT(jq_counters.size() == i + 2); for (int j = 0; j <= i; ++j) @@ -573,18 +542,15 @@ public: // be half as many queued as started... for (int i = 0; i < jobs.size(); ++i) { - perfLog->jobStart( - jobs[i].type, microseconds{i + 1}, steady_clock::now(), i * 2); + perfLog->jobStart(jobs[i].type, microseconds{i + 1}, steady_clock::now(), i * 2); std::this_thread::sleep_for(microseconds(10)); // Check each jobType counter entry. - Json::Value const jq_counters{ - perfLog->countersJson()[jss::job_queue]}; + Json::Value const jq_counters{perfLog->countersJson()[jss::job_queue]}; for (int j = 0; j < jobs.size(); ++j) { Json::Value const& counter{jq_counters[jobs[j].typeName]}; - std::uint64_t const queued_dur_us{ - jsonToUint64(counter[jss::queued_duration_us])}; + std::uint64_t const queued_dur_us{jsonToUint64(counter[jss::queued_duration_us])}; if (j < i) { BEAST_EXPECT(counter[jss::started] == "2"); @@ -613,24 +579,17 @@ public: BEAST_EXPECT(total[jss::finished] == "0"); // Total queued duration is triangle number of (i + 1). - BEAST_EXPECT( - jsonToUint64(total[jss::queued_duration_us]) == - (((i * i) + 3 * i + 2) / 2)); + BEAST_EXPECT(jsonToUint64(total[jss::queued_duration_us]) == (((i * i) + 3 * i + 2) / 2)); BEAST_EXPECT(total[jss::running_duration_us] == "0"); } - perfLog->jobStart( - jobs[i].type, - microseconds{0}, - steady_clock::now(), - (i * 2) + 1); + perfLog->jobStart(jobs[i].type, microseconds{0}, steady_clock::now(), (i * 2) + 1); std::this_thread::sleep_for(microseconds{10}); // Verify that every entry in jobs appears twice in currents. // If we sort by duration_us they should be in the order the // rpcStart() call was made. - std::vector const currents{ - getSortedCurrent(perfLog->currentJson()[jss::jobs])}; + std::vector const currents{getSortedCurrent(perfLog->currentJson()[jss::jobs])}; BEAST_EXPECT(currents.size() == (i + 1) * 2); std::uint64_t prevDur = std::numeric_limits::max(); @@ -652,17 +611,14 @@ public: // A number of the computations in this loop care about the // number of jobs that have finished. Make that available. int const finished = ((jobs.size() - i) * 2) - 1; - perfLog->jobFinish( - jobs[i].type, microseconds(finished), (i * 2) + 1); + perfLog->jobFinish(jobs[i].type, microseconds(finished), (i * 2) + 1); std::this_thread::sleep_for(microseconds(10)); - Json::Value const jq_counters{ - perfLog->countersJson()[jss::job_queue]}; + Json::Value const jq_counters{perfLog->countersJson()[jss::job_queue]}; for (int j = 0; j < jobs.size(); ++j) { Json::Value const& counter{jq_counters[jobs[j].typeName]}; - std::uint64_t const running_dur_us{ - jsonToUint64(counter[jss::running_duration_us])}; + std::uint64_t const running_dur_us{jsonToUint64(counter[jss::running_duration_us])}; if (j < i) { BEAST_EXPECT(counter[jss::finished] == "0"); @@ -679,8 +635,7 @@ public: BEAST_EXPECT(running_dur_us == ((jobs.size() - j) * 4) - 1); } - std::uint64_t const queued_dur_us{ - jsonToUint64(counter[jss::queued_duration_us])}; + std::uint64_t const queued_dur_us{jsonToUint64(counter[jss::queued_duration_us])}; BEAST_EXPECT(queued_dur_us == j + 1); BEAST_EXPECT(counter[jss::queued] == "1"); BEAST_EXPECT(counter[jss::started] == "2"); @@ -689,31 +644,25 @@ public: // Verify values in jss::total are what we expect. Json::Value const& total{jq_counters[jss::total]}; BEAST_EXPECT(jsonToUint64(total[jss::queued]) == jobs.size()); - BEAST_EXPECT( - jsonToUint64(total[jss::started]) == jobs.size() * 2); + BEAST_EXPECT(jsonToUint64(total[jss::started]) == jobs.size() * 2); BEAST_EXPECT(jsonToUint64(total[jss::finished]) == finished); // Total queued duration should be triangle number of // jobs.size(). int const queuedDur = ((jobs.size() * (jobs.size() + 1)) / 2); - BEAST_EXPECT( - jsonToUint64(total[jss::queued_duration_us]) == queuedDur); + BEAST_EXPECT(jsonToUint64(total[jss::queued_duration_us]) == queuedDur); // Total running duration should be triangle number of finished. int const runningDur = ((finished * (finished + 1)) / 2); - BEAST_EXPECT( - jsonToUint64(total[jss::running_duration_us]) == - runningDur); + BEAST_EXPECT(jsonToUint64(total[jss::running_duration_us]) == runningDur); } - perfLog->jobFinish( - jobs[i].type, microseconds(finished + 1), (i * 2)); + perfLog->jobFinish(jobs[i].type, microseconds(finished + 1), (i * 2)); std::this_thread::sleep_for(microseconds(10)); // Verify that the two jobs we just finished no longer appear in // currents. - std::vector const currents{ - getSortedCurrent(perfLog->currentJson()[jss::jobs])}; + std::vector const currents{getSortedCurrent(perfLog->currentJson()[jss::jobs])}; BEAST_EXPECT(currents.size() == i * 2); std::uint64_t prevDur = std::numeric_limits::max(); @@ -730,8 +679,7 @@ public: } // Validate the final results. - auto validateFinalCounters = [this, - &jobs](Json::Value const& countersJson) { + auto validateFinalCounters = [this, &jobs](Json::Value const& countersJson) { { Json::Value const& rpc = countersJson[jss::rpc]; BEAST_EXPECT(rpc.isObject()); @@ -742,12 +690,10 @@ public: for (int i = jobs.size() - 1; i >= 0; --i) { Json::Value const& counter{jobQueue[jobs[i].typeName]}; - std::uint64_t const running_dur_us{ - jsonToUint64(counter[jss::running_duration_us])}; + std::uint64_t const running_dur_us{jsonToUint64(counter[jss::running_duration_us])}; BEAST_EXPECT(running_dur_us == ((jobs.size() - i) * 4) - 1); - std::uint64_t const queued_dur_us{ - jsonToUint64(counter[jss::queued_duration_us])}; + std::uint64_t const queued_dur_us{jsonToUint64(counter[jss::queued_duration_us])}; BEAST_EXPECT(queued_dur_us == i + 1); BEAST_EXPECT(counter[jss::queued] == "1"); @@ -765,13 +711,11 @@ public: // Total queued duration should be triangle number of // jobs.size(). int const queuedDur = ((jobs.size() * (jobs.size() + 1)) / 2); - BEAST_EXPECT( - jsonToUint64(total[jss::queued_duration_us]) == queuedDur); + BEAST_EXPECT(jsonToUint64(total[jss::queued_duration_us]) == queuedDur); // Total running duration should be triangle number of finished. int const runningDur = ((finished * (finished + 1)) / 2); - BEAST_EXPECT( - jsonToUint64(total[jss::running_duration_us]) == runningDur); + BEAST_EXPECT(jsonToUint64(total[jss::running_duration_us]) == runningDur); }; auto validateFinalCurrent = [this](Json::Value const& currentJson) { @@ -861,37 +805,31 @@ public: perfLog->resizeJobs(1); // Lambda to validate countersJson for this test. - auto verifyCounters = [this, jobTypeName]( - Json::Value const& countersJson, - int started, - int finished, - int queued_us, - int running_us) { - BEAST_EXPECT(countersJson.isObject()); - BEAST_EXPECT(countersJson.size() == 2); + auto verifyCounters = + [this, jobTypeName]( + Json::Value const& countersJson, int started, int finished, int queued_us, int running_us) { + BEAST_EXPECT(countersJson.isObject()); + BEAST_EXPECT(countersJson.size() == 2); - BEAST_EXPECT(countersJson.isMember(jss::rpc)); - BEAST_EXPECT(countersJson[jss::rpc].isObject()); - BEAST_EXPECT(countersJson[jss::rpc].size() == 0); + BEAST_EXPECT(countersJson.isMember(jss::rpc)); + BEAST_EXPECT(countersJson[jss::rpc].isObject()); + BEAST_EXPECT(countersJson[jss::rpc].size() == 0); - BEAST_EXPECT(countersJson.isMember(jss::job_queue)); - BEAST_EXPECT(countersJson[jss::job_queue].isObject()); - BEAST_EXPECT(countersJson[jss::job_queue].size() == 1); - { - Json::Value const& job{ - countersJson[jss::job_queue][jobTypeName]}; + BEAST_EXPECT(countersJson.isMember(jss::job_queue)); + BEAST_EXPECT(countersJson[jss::job_queue].isObject()); + BEAST_EXPECT(countersJson[jss::job_queue].size() == 1); + { + Json::Value const& job{countersJson[jss::job_queue][jobTypeName]}; - BEAST_EXPECT(job.isObject()); - BEAST_EXPECT(jsonToUint64(job[jss::queued]) == 0); - BEAST_EXPECT(jsonToUint64(job[jss::started]) == started); - BEAST_EXPECT(jsonToUint64(job[jss::finished]) == finished); + BEAST_EXPECT(job.isObject()); + BEAST_EXPECT(jsonToUint64(job[jss::queued]) == 0); + BEAST_EXPECT(jsonToUint64(job[jss::started]) == started); + BEAST_EXPECT(jsonToUint64(job[jss::finished]) == finished); - BEAST_EXPECT( - jsonToUint64(job[jss::queued_duration_us]) == queued_us); - BEAST_EXPECT( - jsonToUint64(job[jss::running_duration_us]) == running_us); - } - }; + BEAST_EXPECT(jsonToUint64(job[jss::queued_duration_us]) == queued_us); + BEAST_EXPECT(jsonToUint64(job[jss::running_duration_us]) == running_us); + } + }; // Lambda to validate currentJson (always empty) for this test. auto verifyEmptyCurrent = [this](Json::Value const& currentJson) { diff --git a/src/test/basics/StringUtilities_test.cpp b/src/test/basics/StringUtilities_test.cpp index ec993b20c3..65134da8e5 100644 --- a/src/test/basics/StringUtilities_test.cpp +++ b/src/test/basics/StringUtilities_test.cpp @@ -120,8 +120,7 @@ public: { parsedURL pUrl; - BEAST_EXPECT( - parseUrl(pUrl, "scheme://user:pass@domain:123/abc:321")); + BEAST_EXPECT(parseUrl(pUrl, "scheme://user:pass@domain:123/abc:321")); BEAST_EXPECT(pUrl.scheme == "scheme"); BEAST_EXPECT(pUrl.username == "user"); BEAST_EXPECT(pUrl.password == "pass"); @@ -220,8 +219,7 @@ public: { parsedURL pUrl; - BEAST_EXPECT( - parseUrl(pUrl, "scheme://user:pass@domain/path/with/an@sign")); + BEAST_EXPECT(parseUrl(pUrl, "scheme://user:pass@domain/path/with/an@sign")); BEAST_EXPECT(pUrl.scheme == "scheme"); BEAST_EXPECT(pUrl.username == "user"); BEAST_EXPECT(pUrl.password == "pass"); @@ -270,8 +268,7 @@ public: BEAST_EXPECT(!parseUrl(pUrl, "nonsense")); BEAST_EXPECT(!parseUrl(pUrl, "://")); BEAST_EXPECT(!parseUrl(pUrl, ":///")); - BEAST_EXPECT( - !parseUrl(pUrl, "scheme://user:pass@domain:65536/abc:321")); + BEAST_EXPECT(!parseUrl(pUrl, "scheme://user:pass@domain:65536/abc:321")); BEAST_EXPECT(!parseUrl(pUrl, "UPPER://domain:23498765/")); BEAST_EXPECT(!parseUrl(pUrl, "UPPER://domain:0/")); BEAST_EXPECT(!parseUrl(pUrl, "UPPER://domain:+7/")); diff --git a/src/test/basics/Units_test.cpp b/src/test/basics/Units_test.cpp index d0193320bf..9094730870 100644 --- a/src/test/basics/Units_test.cpp +++ b/src/test/basics/Units_test.cpp @@ -16,17 +16,14 @@ private: { XRPAmount x{100}; BEAST_EXPECT(x.drops() == 100); - BEAST_EXPECT( - (std::is_same_v)); + BEAST_EXPECT((std::is_same_v)); auto y = 4u * x; BEAST_EXPECT(y.value() == 400); - BEAST_EXPECT( - (std::is_same_v)); + BEAST_EXPECT((std::is_same_v)); auto z = 4 * y; BEAST_EXPECT(z.value() == 1600); - BEAST_EXPECT( - (std::is_same_v)); + BEAST_EXPECT((std::is_same_v)); FeeLevel32 f{10}; FeeLevel32 baseFee{100}; @@ -35,23 +32,17 @@ private: BEAST_EXPECT(drops); BEAST_EXPECT(drops.value() == 1000); - BEAST_EXPECT((std::is_same_v< - std::remove_reference_t::unit_type, - unit::dropTag>)); + BEAST_EXPECT((std::is_same_v::unit_type, unit::dropTag>)); - BEAST_EXPECT((std::is_same_v< - std::remove_reference_t, - XRPAmount>)); + BEAST_EXPECT((std::is_same_v, XRPAmount>)); } { XRPAmount x{100}; BEAST_EXPECT(x.value() == 100); - BEAST_EXPECT( - (std::is_same_v)); + BEAST_EXPECT((std::is_same_v)); auto y = 4u * x; BEAST_EXPECT(y.value() == 400); - BEAST_EXPECT( - (std::is_same_v)); + BEAST_EXPECT((std::is_same_v)); FeeLevel64 f{10}; FeeLevel64 baseFee{100}; @@ -60,23 +51,17 @@ private: BEAST_EXPECT(drops); BEAST_EXPECT(drops.value() == 1000); - BEAST_EXPECT((std::is_same_v< - std::remove_reference_t::unit_type, - unit::dropTag>)); - BEAST_EXPECT((std::is_same_v< - std::remove_reference_t, - XRPAmount>)); + BEAST_EXPECT((std::is_same_v::unit_type, unit::dropTag>)); + BEAST_EXPECT((std::is_same_v, XRPAmount>)); } { FeeLevel64 x{1024}; BEAST_EXPECT(x.value() == 1024); - BEAST_EXPECT( - (std::is_same_v)); + BEAST_EXPECT((std::is_same_v)); std::uint64_t m = 4; auto y = m * x; BEAST_EXPECT(y.value() == 4096); - BEAST_EXPECT( - (std::is_same_v)); + BEAST_EXPECT((std::is_same_v)); XRPAmount basefee{10}; FeeLevel64 referencefee{256}; @@ -85,12 +70,8 @@ private: BEAST_EXPECT(drops); BEAST_EXPECT(drops.value() == 40); - BEAST_EXPECT((std::is_same_v< - std::remove_reference_t::unit_type, - unit::dropTag>)); - BEAST_EXPECT((std::is_same_v< - std::remove_reference_t, - XRPAmount>)); + BEAST_EXPECT((std::is_same_v::unit_type, unit::dropTag>)); + BEAST_EXPECT((std::is_same_v, XRPAmount>)); } } @@ -118,8 +99,7 @@ private: FeeLevel64 x{std::numeric_limits::max()}; auto y = x.jsonClipped(); BEAST_EXPECT(y.type() == Json::uintValue); - BEAST_EXPECT( - y == Json::Value{std::numeric_limits::max()}); + BEAST_EXPECT(y == Json::Value{std::numeric_limits::max()}); } { @@ -147,16 +127,14 @@ private: XRPAmount x{std::numeric_limits::max()}; auto y = x.jsonClipped(); BEAST_EXPECT(y.type() == Json::intValue); - BEAST_EXPECT( - y == Json::Value{std::numeric_limits::max()}); + BEAST_EXPECT(y == Json::Value{std::numeric_limits::max()}); } { XRPAmount x{std::numeric_limits::min()}; auto y = x.jsonClipped(); BEAST_EXPECT(y.type() == Json::intValue); - BEAST_EXPECT( - y == Json::Value{std::numeric_limits::min()}); + BEAST_EXPECT(y == Json::Value{std::numeric_limits::min()}); } } @@ -169,9 +147,7 @@ private: { auto make = [&](auto x) -> FeeLevel64 { return x; }; - auto explicitmake = [&](auto x) -> FeeLevel64 { - return FeeLevel64{x}; - }; + auto explicitmake = [&](auto x) -> FeeLevel64 { return FeeLevel64{x}; }; [[maybe_unused]] FeeLevel64 defaulted; @@ -256,9 +232,7 @@ private: } { auto make = [&](auto x) -> FeeLevelDouble { return x; }; - auto explicitmake = [&](auto x) -> FeeLevelDouble { - return FeeLevelDouble{x}; - }; + auto explicitmake = [&](auto x) -> FeeLevelDouble { return FeeLevelDouble{x}; }; [[maybe_unused]] FeeLevelDouble defaulted; diff --git a/src/test/basics/XRPAmount_test.cpp b/src/test/basics/XRPAmount_test.cpp index 3f4e68de6e..391917e678 100644 --- a/src/test/basics/XRPAmount_test.cpp +++ b/src/test/basics/XRPAmount_test.cpp @@ -203,10 +203,8 @@ public: testcase("mulRatio"); constexpr auto maxUInt32 = std::numeric_limits::max(); - constexpr auto maxXRP = - std::numeric_limits::max(); - constexpr auto minXRP = - std::numeric_limits::min(); + constexpr auto maxXRP = std::numeric_limits::max(); + constexpr auto minXRP = std::numeric_limits::min(); { // multiply by a number that would overflow then divide by the same @@ -219,10 +217,8 @@ public: // multiply and divide by values that would overflow if done // naively, and check that it gives the correct answer big -= 0xf; // Subtract a little so it's divisible by 4 - BEAST_EXPECT( - mulRatio(big, 3, 4, false).value() == (big.value() / 4) * 3); - BEAST_EXPECT( - mulRatio(big, 3, 4, true).value() == (big.value() / 4) * 3); + BEAST_EXPECT(mulRatio(big, 3, 4, false).value() == (big.value() / 4) * 3); + BEAST_EXPECT(mulRatio(big, 3, 4, true).value() == (big.value() / 4) * 3); BEAST_EXPECT((big.value() * 3) / 4 != (big.value() / 4) * 3); } @@ -235,10 +231,8 @@ public: // multiply and divide by values that would overflow if done // naively, and check that it gives the correct answer - BEAST_EXPECT( - mulRatio(big, 3, 4, false).value() == (big.value() / 4) * 3); - BEAST_EXPECT( - mulRatio(big, 3, 4, true).value() == (big.value() / 4) * 3); + BEAST_EXPECT(mulRatio(big, 3, 4, false).value() == (big.value() / 4) * 3); + BEAST_EXPECT(mulRatio(big, 3, 4, true).value() == (big.value() / 4) * 3); BEAST_EXPECT((big.value() * 3) / 4 != (big.value() / 4) * 3); } @@ -249,44 +243,36 @@ public: BEAST_EXPECT(tiny == mulRatio(tiny, 1, maxUInt32, true)); // rounding down should be zero BEAST_EXPECT(beast::zero == mulRatio(tiny, 1, maxUInt32, false)); - BEAST_EXPECT( - beast::zero == mulRatio(tiny, maxUInt32 - 1, maxUInt32, false)); + BEAST_EXPECT(beast::zero == mulRatio(tiny, maxUInt32 - 1, maxUInt32, false)); // tiny negative numbers XRPAmount tinyNeg(-1); // Round up should give zero BEAST_EXPECT(beast::zero == mulRatio(tinyNeg, 1, maxUInt32, true)); - BEAST_EXPECT( - beast::zero == - mulRatio(tinyNeg, maxUInt32 - 1, maxUInt32, true)); + BEAST_EXPECT(beast::zero == mulRatio(tinyNeg, maxUInt32 - 1, maxUInt32, true)); // rounding down should be tiny - BEAST_EXPECT( - tinyNeg == mulRatio(tinyNeg, maxUInt32 - 1, maxUInt32, false)); + BEAST_EXPECT(tinyNeg == mulRatio(tinyNeg, maxUInt32 - 1, maxUInt32, false)); } { // rounding { XRPAmount one(1); auto const rup = mulRatio(one, maxUInt32 - 1, maxUInt32, true); - auto const rdown = - mulRatio(one, maxUInt32 - 1, maxUInt32, false); + auto const rdown = mulRatio(one, maxUInt32 - 1, maxUInt32, false); BEAST_EXPECT(rup.drops() - rdown.drops() == 1); } { XRPAmount big(maxXRP); auto const rup = mulRatio(big, maxUInt32 - 1, maxUInt32, true); - auto const rdown = - mulRatio(big, maxUInt32 - 1, maxUInt32, false); + auto const rdown = mulRatio(big, maxUInt32 - 1, maxUInt32, false); BEAST_EXPECT(rup.drops() - rdown.drops() == 1); } { XRPAmount negOne(-1); - auto const rup = - mulRatio(negOne, maxUInt32 - 1, maxUInt32, true); - auto const rdown = - mulRatio(negOne, maxUInt32 - 1, maxUInt32, false); + auto const rup = mulRatio(negOne, maxUInt32 - 1, maxUInt32, true); + auto const rdown = mulRatio(negOne, maxUInt32 - 1, maxUInt32, false); BEAST_EXPECT(rup.drops() - rdown.drops() == 1); } } diff --git a/src/test/basics/base58_test.cpp b/src/test/basics/base58_test.cpp index 16307bdb0f..5da22d533e 100644 --- a/src/test/basics/base58_test.cpp +++ b/src/test/basics/base58_test.cpp @@ -73,8 +73,7 @@ randomTokenTypeAndSize() -> std::tuple // Return the token type and subspan of `d` to use as test data. [[nodiscard]] inline auto -randomB256TestData(std::span d) - -> std::tuple> +randomB256TestData(std::span d) -> std::tuple> { auto& rng = randEngine(); std::uniform_int_distribution dist(0, 255); @@ -165,14 +164,14 @@ class base58_test : public beast::unit_test::suite if (!d) continue; auto bigInt = multiprecision_utils::randomBigInt(); - auto const boostBigInt = multiprecision_utils::toBoostMP( - std::span(bigInt.data(), bigInt.size())); + auto const boostBigInt = + multiprecision_utils::toBoostMP(std::span(bigInt.data(), bigInt.size())); auto const refDiv = boostBigInt / d; auto const refMod = boostBigInt % d; - auto const mod = b58_fast::detail::inplace_bigint_div_rem( - std::span(bigInt.data(), bigInt.size()), d); + auto const mod = + b58_fast::detail::inplace_bigint_div_rem(std::span(bigInt.data(), bigInt.size()), d); auto const foundDiv = multiprecision_utils::toBoostMP(bigInt); BEAST_EXPECT(refMod.convert_to() == mod); BEAST_EXPECT(foundDiv == refDiv); @@ -181,18 +180,17 @@ class base58_test : public beast::unit_test::suite { std::uint64_t const d = dist(eng); auto bigInt = multiprecision_utils::randomBigInt(/*minSize*/ 2); - if (bigInt[bigInt.size() - 1] == - std::numeric_limits::max()) + if (bigInt[bigInt.size() - 1] == std::numeric_limits::max()) { bigInt[bigInt.size() - 1] -= 1; // Prevent overflow } - auto const boostBigInt = multiprecision_utils::toBoostMP( - std::span(bigInt.data(), bigInt.size())); + auto const boostBigInt = + multiprecision_utils::toBoostMP(std::span(bigInt.data(), bigInt.size())); auto const refAdd = boostBigInt + d; - auto const result = b58_fast::detail::inplace_bigint_add( - std::span(bigInt.data(), bigInt.size()), d); + auto const result = + b58_fast::detail::inplace_bigint_add(std::span(bigInt.data(), bigInt.size()), d); BEAST_EXPECT(result == TokenCodecErrc::success); auto const foundAdd = multiprecision_utils::toBoostMP(bigInt); BEAST_EXPECT(refAdd == foundAdd); @@ -201,16 +199,15 @@ class base58_test : public beast::unit_test::suite { std::uint64_t const d = dist1(eng); // Force overflow - std::vector bigInt( - 5, std::numeric_limits::max()); + std::vector bigInt(5, std::numeric_limits::max()); - auto const boostBigInt = multiprecision_utils::toBoostMP( - std::span(bigInt.data(), bigInt.size())); + auto const boostBigInt = + multiprecision_utils::toBoostMP(std::span(bigInt.data(), bigInt.size())); auto const refAdd = boostBigInt + d; - auto const result = b58_fast::detail::inplace_bigint_add( - std::span(bigInt.data(), bigInt.size()), d); + auto const result = + b58_fast::detail::inplace_bigint_add(std::span(bigInt.data(), bigInt.size()), d); BEAST_EXPECT(result == TokenCodecErrc::overflowAdd); auto const foundAdd = multiprecision_utils::toBoostMP(bigInt); BEAST_EXPECT(refAdd != foundAdd); @@ -222,13 +219,13 @@ class base58_test : public beast::unit_test::suite // inplace mul requires the most significant coeff to be zero to // hold the result. bigInt[bigInt.size() - 1] = 0; - auto const boostBigInt = multiprecision_utils::toBoostMP( - std::span(bigInt.data(), bigInt.size())); + auto const boostBigInt = + multiprecision_utils::toBoostMP(std::span(bigInt.data(), bigInt.size())); auto const refMul = boostBigInt * d; - auto const result = b58_fast::detail::inplace_bigint_mul( - std::span(bigInt.data(), bigInt.size()), d); + auto const result = + b58_fast::detail::inplace_bigint_mul(std::span(bigInt.data(), bigInt.size()), d); BEAST_EXPECT(result == TokenCodecErrc::success); auto const foundMul = multiprecision_utils::toBoostMP(bigInt); BEAST_EXPECT(refMul == foundMul); @@ -237,15 +234,14 @@ class base58_test : public beast::unit_test::suite { std::uint64_t const d = dist1(eng); // Force overflow - std::vector bigInt( - 5, std::numeric_limits::max()); - auto const boostBigInt = multiprecision_utils::toBoostMP( - std::span(bigInt.data(), bigInt.size())); + std::vector bigInt(5, std::numeric_limits::max()); + auto const boostBigInt = + multiprecision_utils::toBoostMP(std::span(bigInt.data(), bigInt.size())); auto const refMul = boostBigInt * d; - auto const result = b58_fast::detail::inplace_bigint_mul( - std::span(bigInt.data(), bigInt.size()), d); + auto const result = + b58_fast::detail::inplace_bigint_mul(std::span(bigInt.data(), bigInt.size()), d); BEAST_EXPECT(result == TokenCodecErrc::inputTooLarge); auto const foundMul = multiprecision_utils::toBoostMP(bigInt); BEAST_EXPECT(refMul != foundMul); @@ -267,8 +263,7 @@ class base58_test : public beast::unit_test::suite std::span const outBuf{b58ResultBuf[i]}; if (i == 0) { - auto const r = xrpl::b58_fast::detail::b256_to_b58_be( - b256Data, outBuf); + auto const r = xrpl::b58_fast::detail::b256_to_b58_be(b256Data, outBuf); BEAST_EXPECT(r); b58Result[i] = r.value(); } @@ -276,10 +271,7 @@ class base58_test : public beast::unit_test::suite { std::array tmpBuf; std::string const s = xrpl::b58_ref::detail::encodeBase58( - b256Data.data(), - b256Data.size(), - tmpBuf.data(), - tmpBuf.size()); + b256Data.data(), b256Data.size(), tmpBuf.data(), tmpBuf.size()); BEAST_EXPECT(s.size()); b58Result[i] = outBuf.subspan(0, s.size()); std::copy(s.begin(), s.end(), b58Result[i].begin()); @@ -287,11 +279,7 @@ class base58_test : public beast::unit_test::suite } if (BEAST_EXPECT(b58Result[0].size() == b58Result[1].size())) { - if (!BEAST_EXPECT( - memcmp( - b58Result[0].data(), - b58Result[1].data(), - b58Result[0].size()) == 0)) + if (!BEAST_EXPECT(memcmp(b58Result[0].data(), b58Result[1].data(), b58Result[0].size()) == 0)) { printAsChar(b58Result[0], b58Result[1]); } @@ -299,24 +287,18 @@ class base58_test : public beast::unit_test::suite for (int i = 0; i < 2; ++i) { - std::span const outBuf{ - b256ResultBuf[i].data(), b256ResultBuf[i].size()}; + std::span const outBuf{b256ResultBuf[i].data(), b256ResultBuf[i].size()}; if (i == 0) { - std::string const in( - b58Result[i].data(), - b58Result[i].data() + b58Result[i].size()); - auto const r = - xrpl::b58_fast::detail::b58_to_b256_be(in, outBuf); + std::string const in(b58Result[i].data(), b58Result[i].data() + b58Result[i].size()); + auto const r = xrpl::b58_fast::detail::b58_to_b256_be(in, outBuf); BEAST_EXPECT(r); b256Result[i] = r.value(); } else { - std::string const st( - b58Result[i].begin(), b58Result[i].end()); - std::string const s = - xrpl::b58_ref::detail::decodeBase58(st); + std::string const st(b58Result[i].begin(), b58Result[i].end()); + std::string const s = xrpl::b58_ref::detail::decodeBase58(st); BEAST_EXPECT(s.size()); b256Result[i] = outBuf.subspan(0, s.size()); std::copy(s.begin(), s.end(), b256Result[i].begin()); @@ -325,19 +307,14 @@ class base58_test : public beast::unit_test::suite if (BEAST_EXPECT(b256Result[0].size() == b256Result[1].size())) { - if (!BEAST_EXPECT( - memcmp( - b256Result[0].data(), - b256Result[1].data(), - b256Result[0].size()) == 0)) + if (!BEAST_EXPECT(memcmp(b256Result[0].data(), b256Result[1].data(), b256Result[0].size()) == 0)) { printAsInt(b256Result[0], b256Result[1]); } } }; - auto testTokenEncode = [&](xrpl::TokenType const tokType, - std::span const& b256Data) { + auto testTokenEncode = [&](xrpl::TokenType const tokType, std::span const& b256Data) { std::array b58ResultBuf[2]; std::array, 2> b58Result; @@ -345,19 +322,16 @@ class base58_test : public beast::unit_test::suite std::array, 2> b256Result; for (int i = 0; i < 2; ++i) { - std::span const outBuf{ - b58ResultBuf[i].data(), b58ResultBuf[i].size()}; + std::span const outBuf{b58ResultBuf[i].data(), b58ResultBuf[i].size()}; if (i == 0) { - auto const r = xrpl::b58_fast::encodeBase58Token( - tokType, b256Data, outBuf); + auto const r = xrpl::b58_fast::encodeBase58Token(tokType, b256Data, outBuf); BEAST_EXPECT(r); b58Result[i] = r.value(); } else { - std::string const s = xrpl::b58_ref::encodeBase58Token( - tokType, b256Data.data(), b256Data.size()); + std::string const s = xrpl::b58_ref::encodeBase58Token(tokType, b256Data.data(), b256Data.size()); BEAST_EXPECT(s.size()); b58Result[i] = outBuf.subspan(0, s.size()); std::copy(s.begin(), s.end(), b58Result[i].begin()); @@ -365,11 +339,7 @@ class base58_test : public beast::unit_test::suite } if (BEAST_EXPECT(b58Result[0].size() == b58Result[1].size())) { - if (!BEAST_EXPECT( - memcmp( - b58Result[0].data(), - b58Result[1].data(), - b58Result[0].size()) == 0)) + if (!BEAST_EXPECT(memcmp(b58Result[0].data(), b58Result[1].data(), b58Result[0].size()) == 0)) { printAsChar(b58Result[0], b58Result[1]); } @@ -377,24 +347,18 @@ class base58_test : public beast::unit_test::suite for (int i = 0; i < 2; ++i) { - std::span const outBuf{ - b256ResultBuf[i].data(), b256ResultBuf[i].size()}; + std::span const outBuf{b256ResultBuf[i].data(), b256ResultBuf[i].size()}; if (i == 0) { - std::string const in( - b58Result[i].data(), - b58Result[i].data() + b58Result[i].size()); - auto const r = - xrpl::b58_fast::decodeBase58Token(tokType, in, outBuf); + std::string const in(b58Result[i].data(), b58Result[i].data() + b58Result[i].size()); + auto const r = xrpl::b58_fast::decodeBase58Token(tokType, in, outBuf); BEAST_EXPECT(r); b256Result[i] = r.value(); } else { - std::string const st( - b58Result[i].begin(), b58Result[i].end()); - std::string const s = - xrpl::b58_ref::decodeBase58Token(st, tokType); + std::string const st(b58Result[i].begin(), b58Result[i].end()); + std::string const s = xrpl::b58_ref::decodeBase58Token(st, tokType); BEAST_EXPECT(s.size()); b256Result[i] = outBuf.subspan(0, s.size()); std::copy(s.begin(), s.end(), b256Result[i].begin()); @@ -403,19 +367,14 @@ class base58_test : public beast::unit_test::suite if (BEAST_EXPECT(b256Result[0].size() == b256Result[1].size())) { - if (!BEAST_EXPECT( - memcmp( - b256Result[0].data(), - b256Result[1].data(), - b256Result[0].size()) == 0)) + if (!BEAST_EXPECT(memcmp(b256Result[0].data(), b256Result[1].data(), b256Result[0].size()) == 0)) { printAsInt(b256Result[0], b256Result[1]); } } }; - auto testIt = [&](xrpl::TokenType const tokType, - std::span const& b256Data) { + auto testIt = [&](xrpl::TokenType const tokType, std::span const& b256Data) { testRawEncode(b256Data); testTokenEncode(tokType, b256Data); }; diff --git a/src/test/basics/base_uint_test.cpp b/src/test/basics/base_uint_test.cpp index 8f764fd58b..9fdc2c7f29 100644 --- a/src/test/basics/base_uint_test.cpp +++ b/src/test/basics/base_uint_test.cpp @@ -47,15 +47,13 @@ struct base_uint_test : beast::unit_test::suite testComparisons() { { - static constexpr std:: - array, 6> - test_args{ - {{"0000000000000000", "0000000000000001"}, - {"0000000000000000", "ffffffffffffffff"}, - {"1234567812345678", "2345678923456789"}, - {"8000000000000000", "8000000000000001"}, - {"aaaaaaaaaaaaaaa9", "aaaaaaaaaaaaaaaa"}, - {"fffffffffffffffe", "ffffffffffffffff"}}}; + static constexpr std::array, 6> test_args{ + {{"0000000000000000", "0000000000000001"}, + {"0000000000000000", "ffffffffffffffff"}, + {"1234567812345678", "2345678923456789"}, + {"8000000000000000", "8000000000000001"}, + {"aaaaaaaaaaaaaaa9", "aaaaaaaaaaaaaaaa"}, + {"fffffffffffffffe", "ffffffffffffffff"}}}; for (auto const& arg : test_args) { @@ -78,17 +76,14 @@ struct base_uint_test : beast::unit_test::suite } { - static constexpr std::array< - std::pair, - 6> - test_args{{ - {"000000000000000000000000", "000000000000000000000001"}, - {"000000000000000000000000", "ffffffffffffffffffffffff"}, - {"0123456789ab0123456789ab", "123456789abc123456789abc"}, - {"555555555555555555555555", "55555555555a555555555555"}, - {"aaaaaaaaaaaaaaa9aaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaa"}, - {"fffffffffffffffffffffffe", "ffffffffffffffffffffffff"}, - }}; + static constexpr std::array, 6> test_args{{ + {"000000000000000000000000", "000000000000000000000001"}, + {"000000000000000000000000", "ffffffffffffffffffffffff"}, + {"0123456789ab0123456789ab", "123456789abc123456789abc"}, + {"555555555555555555555555", "55555555555a555555555555"}, + {"aaaaaaaaaaaaaaa9aaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaa"}, + {"fffffffffffffffffffffffe", "ffffffffffffffffffffffff"}, + }}; for (auto const& arg : test_args) { @@ -116,10 +111,8 @@ struct base_uint_test : beast::unit_test::suite { testcase("base_uint: general purpose tests"); - static_assert( - !std::is_constructible>::value); - static_assert( - !std::is_assignable>::value); + static_assert(!std::is_constructible>::value); + static_assert(!std::is_assignable>::value); testComparisons(); @@ -296,9 +289,7 @@ struct base_uint_test : beast::unit_test::suite } catch (std::invalid_argument const& e) { - BEAST_EXPECT( - e.what() == - std::string("invalid length for hex string")); + BEAST_EXPECT(e.what() == std::string("invalid length for hex string")); caught = true; } BEAST_EXPECT(caught); @@ -316,8 +307,7 @@ struct base_uint_test : beast::unit_test::suite } catch (std::range_error const& e) { - BEAST_EXPECT( - e.what() == std::string("invalid hex character")); + BEAST_EXPECT(e.what() == std::string("invalid hex character")); caught = true; } BEAST_EXPECT(caught); diff --git a/src/test/basics/hardened_hash_test.cpp b/src/test/basics/hardened_hash_test.cpp index f7eb78ce31..1a6609ac29 100644 --- a/src/test/basics/hardened_hash_test.cpp +++ b/src/test/basics/hardened_hash_test.cpp @@ -66,12 +66,10 @@ template using test_hardened_unordered_map = std::unordered_map>; template -using test_hardened_unordered_multiset = - std::unordered_multiset>; +using test_hardened_unordered_multiset = std::unordered_multiset>; template -using test_hardened_unordered_multimap = - std::unordered_multimap>; +using test_hardened_unordered_multimap = std::unordered_multimap>; } // namespace detail @@ -83,13 +81,9 @@ private: std::is_integral::value && std::is_unsigned::value, "UInt must be an unsigned integral type"); - static_assert( - Bits % (8 * sizeof(UInt)) == 0, - "Bits must be a multiple of 8*sizeof(UInt)"); + static_assert(Bits % (8 * sizeof(UInt)) == 0, "Bits must be a multiple of 8*sizeof(UInt)"); - static_assert( - Bits >= (8 * sizeof(UInt)), - "Bits must be at least 8*sizeof(UInt)"); + static_assert(Bits >= (8 * sizeof(UInt)), "Bits must be at least 8*sizeof(UInt)"); static std::size_t const size = Bits / (8 * sizeof(UInt)); @@ -136,8 +130,7 @@ public: operator<<(std::ostream& s, unsigned_integer const& v) { for (std::size_t i(0); i < size; ++i) - s << std::hex << std::setfill('0') << std::setw(2 * sizeof(UInt)) - << v.m_vec[i]; + s << std::hex << std::setfill('0') << std::setw(2 * sizeof(UInt)) << v.m_vec[i]; return s; } }; diff --git a/src/test/basics/join_test.cpp b/src/test/basics/join_test.cpp index 5354f2ab60..9739624c63 100644 --- a/src/test/basics/join_test.cpp +++ b/src/test/basics/join_test.cpp @@ -23,13 +23,9 @@ struct join_test : beast::unit_test::suite }; // C++ array - test( - CollectionAndDelimiter(std::array{2, -1, 5, 10}, "/"), - "2/-1/5/10"); + test(CollectionAndDelimiter(std::array{2, -1, 5, 10}, "/"), "2/-1/5/10"); // One item C++ array edge case - test( - CollectionAndDelimiter(std::array{"test"}, " & "), - "test"); + test(CollectionAndDelimiter(std::array{"test"}, " & "), "test"); // Empty C++ array edge case test(CollectionAndDelimiter(std::array{}, ","), ""); { @@ -48,20 +44,13 @@ struct join_test : beast::unit_test::suite test(CollectionAndDelimiter(words, "\n"), "thing"); } // Initializer list - test( - CollectionAndDelimiter(std::initializer_list{19, 25}, "+"), - "19+25"); + test(CollectionAndDelimiter(std::initializer_list{19, 25}, "+"), "19+25"); // vector - test( - CollectionAndDelimiter(std::vector{0, 42}, std::to_string(99)), - "09942"); + test(CollectionAndDelimiter(std::vector{0, 42}, std::to_string(99)), "09942"); { // vector with one item edge case using namespace jtx; - test( - CollectionAndDelimiter( - std::vector{Account::master}, "xxx"), - Account::master.human()); + test(CollectionAndDelimiter(std::vector{Account::master}, "xxx"), Account::master.human()); } // empty vector edge case test(CollectionAndDelimiter(std::vector{}, ","), ""); diff --git a/src/test/beast/IPEndpointCommon.h b/src/test/beast/IPEndpointCommon.h index 73cbe7d95b..3ca023188e 100644 --- a/src/test/beast/IPEndpointCommon.h +++ b/src/test/beast/IPEndpointCommon.h @@ -34,9 +34,7 @@ randomEP(bool v4 = true) static_cast(rand_int(1, UINT8_MAX)), static_cast(rand_int(1, UINT8_MAX))}}; }; - return Endpoint{ - v4 ? Address{AddressV4{dv4()}} : Address{AddressV6{dv6()}}, - rand_int(1, UINT16_MAX)}; + return Endpoint{v4 ? Address{AddressV4{dv4()}} : Address{AddressV6{dv6()}}, rand_int(1, UINT16_MAX)}; } } // namespace IP diff --git a/src/test/beast/IPEndpoint_test.cpp b/src/test/beast/IPEndpoint_test.cpp index 1d451e94a2..67e3f8ed7d 100644 --- a/src/test/beast/IPEndpoint_test.cpp +++ b/src/test/beast/IPEndpoint_test.cpp @@ -20,10 +20,7 @@ class IPEndpoint_test : public unit_test::suite { public: void - shouldParseAddrV4( - std::string const& s, - std::uint32_t value, - std::string const& normal = "") + shouldParseAddrV4(std::string const& s, std::uint32_t value, std::string const& normal = "") { boost::system::error_code ec; Address const result{boost::asio::ip::make_address(s, ec)}; @@ -31,12 +28,9 @@ public: return; if (!BEAST_EXPECTS(result.is_v4(), s + " not v4")) return; - if (!BEAST_EXPECTS( - result.to_v4().to_uint() == value, s + " value mismatch")) + if (!BEAST_EXPECTS(result.to_v4().to_uint() == value, s + " value mismatch")) return; - BEAST_EXPECTS( - result.to_string() == (normal.empty() ? s : normal), - s + " as string"); + BEAST_EXPECTS(result.to_string() == (normal.empty() ? s : normal), s + " as string"); } void @@ -215,14 +209,8 @@ public: shouldParseEPV4("1.2.3.4:5 ", {{1, 2, 3, 4}}, 5, "1.2.3.4:5"); shouldParseEPV4("1.2.3.4 ", {{1, 2, 3, 4}}, 0, "1.2.3.4"); shouldParseEPV4(" 1.2.3.4", {{1, 2, 3, 4}}, 0, "1.2.3.4"); - shouldParseEPV6( - "2001:db8:a0b:12f0::1", - {{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}}, - 0); - shouldParseEPV6( - "[2001:db8:a0b:12f0::1]:8", - {{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}}, - 8); + shouldParseEPV6("2001:db8:a0b:12f0::1", {{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}}, 0); + shouldParseEPV6("[2001:db8:a0b:12f0::1]:8", {{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}}, 8); shouldParseEPV6( "[2001:2002:2003:2004:2005:2006:2007:2008]:65535", {{32, 1, 32, 2, 32, 3, 32, 4, 32, 5, 32, 6, 32, 7, 32, 8}}, @@ -244,10 +232,7 @@ public: BEAST_EXPECT(is_loopback(ep)); BEAST_EXPECT(to_string(ep) == "127.0.0.1:80"); // same address as v4 mapped in ipv6 - ep = Endpoint( - boost::asio::ip::make_address_v6( - boost::asio::ip::v4_mapped, AddressV4{d}), - 80); + ep = Endpoint(boost::asio::ip::make_address_v6(boost::asio::ip::v4_mapped, AddressV4{d}), 80); BEAST_EXPECT(!is_unspecified(ep)); BEAST_EXPECT(!is_public(ep)); BEAST_EXPECT(is_private(ep)); @@ -265,11 +250,8 @@ public: BEAST_EXPECT(!is_loopback(ep)); BEAST_EXPECT(to_string(ep) == "10.0.0.1"); // same address as v4 mapped in ipv6 - ep = Endpoint(boost::asio::ip::make_address_v6( - boost::asio::ip::v4_mapped, AddressV4{d})); - BEAST_EXPECT( - get_class(boost::asio::ip::make_address_v4( - boost::asio::ip::v4_mapped, ep.to_v6())) == 'A'); + ep = Endpoint(boost::asio::ip::make_address_v6(boost::asio::ip::v4_mapped, AddressV4{d})); + BEAST_EXPECT(get_class(boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped, ep.to_v6())) == 'A'); BEAST_EXPECT(!is_unspecified(ep)); BEAST_EXPECT(!is_public(ep)); BEAST_EXPECT(is_private(ep)); @@ -286,8 +268,7 @@ public: BEAST_EXPECT(!is_loopback(ep)); BEAST_EXPECT(to_string(ep) == "166.78.151.147"); // same address as v4 mapped in ipv6 - ep = Endpoint(boost::asio::ip::make_address_v6( - boost::asio::ip::v4_mapped, AddressV4{d})); + ep = Endpoint(boost::asio::ip::make_address_v6(boost::asio::ip::v4_mapped, AddressV4{d})); BEAST_EXPECT(!is_unspecified(ep)); BEAST_EXPECT(is_public(ep)); BEAST_EXPECT(!is_private(ep)); @@ -296,8 +277,7 @@ public: BEAST_EXPECTS(to_string(ep) == "::ffff:166.78.151.147", to_string(ep)); // a private IPv6 - AddressV6::bytes_type d2 = { - {253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}; + AddressV6::bytes_type d2 = {{253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}; ep = Endpoint(AddressV6{d2}); BEAST_EXPECT(!is_unspecified(ep)); BEAST_EXPECT(!is_public(ep)); @@ -405,9 +385,7 @@ public: using namespace std::literals; T t; BEAST_EXPECT(parse(text, t)); - BEAST_EXPECTS( - to_string(t) == (normal.empty() ? text : normal), - "string mismatch for "s + text); + BEAST_EXPECTS(to_string(t) == (normal.empty() ? text : normal), "string mismatch for "s + text); } template diff --git a/src/test/beast/SemanticVersion_test.cpp b/src/test/beast/SemanticVersion_test.cpp index 4620c63670..b3394235d1 100644 --- a/src/test/beast/SemanticVersion_test.cpp +++ b/src/test/beast/SemanticVersion_test.cpp @@ -196,15 +196,9 @@ public: checkValues("1.2.3-rc1.debug.asm", 1, 2, 3, ids("rc1", "debug", "asm")); checkValues("1.2.3+full", 1, 2, 3, ids(), ids("full")); checkValues("1.2.3+full.prod", 1, 2, 3, ids(), ids("full", "prod")); + checkValues("1.2.3+full.prod.x86", 1, 2, 3, ids(), ids("full", "prod", "x86")); checkValues( - "1.2.3+full.prod.x86", 1, 2, 3, ids(), ids("full", "prod", "x86")); - checkValues( - "1.2.3-rc1.debug.asm+full.prod.x86", - 1, - 2, - 3, - ids("rc1", "debug", "asm"), - ids("full", "prod", "x86")); + "1.2.3-rc1.debug.asm+full.prod.x86", 1, 2, 3, ids("rc1", "debug", "asm"), ids("full", "prod", "x86")); } // makes sure the left version is less than the right diff --git a/src/test/beast/aged_associative_container_test.cpp b/src/test/beast/aged_associative_container_test.cpp index e40a24f08c..3af559c1cb 100644 --- a/src/test/beast/aged_associative_container_test.cpp +++ b/src/test/beast/aged_associative_container_test.cpp @@ -292,9 +292,7 @@ public: template struct ContType { - template < - class Compare = std::less, - class Allocator = std::allocator> + template , class Allocator = std::allocator> using Cont = detail::aged_ordered_container< Base::is_multi::value, Base::is_map::value, @@ -334,15 +332,10 @@ public: }; template - struct TestTraitsHelper - : MaybeUnordered< - MaybeMulti, IsMulti>, - IsUnordered> + struct TestTraitsHelper : MaybeUnordered, IsMulti>, IsUnordered> { private: - using Base = MaybeUnordered< - MaybeMulti, IsMulti>, - IsUnordered>; + using Base = MaybeUnordered, IsMulti>, IsUnordered>; public: using typename Base::Key; @@ -357,8 +350,7 @@ public: static std::string name() { - return std::string("aged_") + Base::name_ordered_part() + - Base::name_multi_part() + Base::name_map_part(); + return std::string("aged_") + Base::name_ordered_part() + Base::name_multi_part() + Base::name_map_part(); } }; @@ -372,17 +364,14 @@ public: static std::string name(Cont const&) { - return TestTraits:: - name(); + return TestTraits::name(); } template struct equal_value { bool - operator()( - typename Traits::Value const& lhs, - typename Traits::Value const& rhs) + operator()(typename Traits::Value const& lhs, typename Traits::Value const& rhs) { return Traits::extract(lhs) == Traits::extract(rhs); } @@ -398,26 +387,22 @@ public: //-------------------------------------------------------------------------- template - typename std::enable_if< - Container::is_map::value && !Container::is_multi::value>::type + typename std::enable_if::type checkMapContents(Container& c, Values const& v); template - typename std::enable_if< - !(Container::is_map::value && !Container::is_multi::value)>::type + typename std::enable_if::type checkMapContents(Container, Values const&) { } // unordered template - typename std::enable_if< - std::remove_reference::type::is_unordered::value>::type + typename std::enable_if::type::is_unordered::value>::type checkUnorderedContentsRefRef(C&& c, Values const& v); template - typename std::enable_if< - !std::remove_reference::type::is_unordered::value>::type + typename std::enable_if::type::is_unordered::value>::type checkUnorderedContentsRefRef(C&&, Values const&) { } @@ -614,11 +599,8 @@ public: // Check contents via at() and operator[] // map, unordered_map template -typename std::enable_if< - Container::is_map::value && !Container::is_multi::value>::type -aged_associative_container_test_base::checkMapContents( - Container& c, - Values const& v) +typename std::enable_if::type +aged_associative_container_test_base::checkMapContents(Container& c, Values const& v) { if (v.empty()) { @@ -643,17 +625,11 @@ aged_associative_container_test_base::checkMapContents( // unordered template -typename std::enable_if< - std::remove_reference::type::is_unordered::value>::type -aged_associative_container_test_base::checkUnorderedContentsRefRef( - C&& c, - Values const& v) +typename std::enable_if::type::is_unordered::value>::type +aged_associative_container_test_base::checkUnorderedContentsRefRef(C&& c, Values const& v) { using Cont = typename std::remove_reference::type; - using Traits = TestTraits< - Cont::is_unordered::value, - Cont::is_multi::value, - Cont::is_map::value>; + using Traits = TestTraits; using size_type = typename Cont::size_type; auto const hash(c.hash_function()); auto const key_eq(c.key_eq()); @@ -662,26 +638,19 @@ aged_associative_container_test_base::checkUnorderedContentsRefRef( auto const last(c.end(i)); for (auto iter(c.begin(i)); iter != last; ++iter) { - auto const match(std::find_if( - v.begin(), - v.end(), - [iter](typename Values::value_type const& e) { - return Traits::extract(*iter) == Traits::extract(e); - })); + auto const match(std::find_if(v.begin(), v.end(), [iter](typename Values::value_type const& e) { + return Traits::extract(*iter) == Traits::extract(e); + })); BEAST_EXPECT(match != v.end()); - BEAST_EXPECT( - key_eq(Traits::extract(*iter), Traits::extract(*match))); - BEAST_EXPECT( - hash(Traits::extract(*iter)) == hash(Traits::extract(*match))); + BEAST_EXPECT(key_eq(Traits::extract(*iter), Traits::extract(*match))); + BEAST_EXPECT(hash(Traits::extract(*iter)) == hash(Traits::extract(*match))); } } } template void -aged_associative_container_test_base::checkContentsRefRef( - C&& c, - Values const& v) +aged_associative_container_test_base::checkContentsRefRef(C&& c, Values const& v) { using Cont = typename std::remove_reference::type; using size_type = typename Cont::size_type; @@ -689,18 +658,10 @@ aged_associative_container_test_base::checkContentsRefRef( BEAST_EXPECT(c.size() == v.size()); BEAST_EXPECT(size_type(std::distance(c.begin(), c.end())) == v.size()); BEAST_EXPECT(size_type(std::distance(c.cbegin(), c.cend())) == v.size()); - BEAST_EXPECT( - size_type(std::distance( - c.chronological.begin(), c.chronological.end())) == v.size()); - BEAST_EXPECT( - size_type(std::distance( - c.chronological.cbegin(), c.chronological.cend())) == v.size()); - BEAST_EXPECT( - size_type(std::distance( - c.chronological.rbegin(), c.chronological.rend())) == v.size()); - BEAST_EXPECT( - size_type(std::distance( - c.chronological.crbegin(), c.chronological.crend())) == v.size()); + BEAST_EXPECT(size_type(std::distance(c.chronological.begin(), c.chronological.end())) == v.size()); + BEAST_EXPECT(size_type(std::distance(c.chronological.cbegin(), c.chronological.cend())) == v.size()); + BEAST_EXPECT(size_type(std::distance(c.chronological.rbegin(), c.chronological.rend())) == v.size()); + BEAST_EXPECT(size_type(std::distance(c.chronological.crbegin(), c.chronological.crend())) == v.size()); checkUnorderedContentsRefRef(c, v); } @@ -718,10 +679,7 @@ template void aged_associative_container_test_base::checkContents(Cont& c) { - using Traits = TestTraits< - Cont::is_unordered::value, - Cont::is_multi::value, - Cont::is_map::value>; + using Traits = TestTraits; using Values = typename Traits::Values; checkContents(c, Values()); } @@ -763,8 +721,7 @@ aged_associative_container_test_base::testConstructEmpty() } { - typename Traits::template Cont c( - clock, MyComp(1), MyAlloc(1)); + typename Traits::template Cont c(clock, MyComp(1), MyAlloc(1)); checkContents(c); } } @@ -791,44 +748,37 @@ aged_associative_container_test_base::testConstructEmpty() } { - typename Traits::template Cont c( - clock, MyHash(1)); + typename Traits::template Cont c(clock, MyHash(1)); checkContents(c); } { - typename Traits::template Cont c( - clock, MyEqual(1)); + typename Traits::template Cont c(clock, MyEqual(1)); checkContents(c); } { - typename Traits::template Cont c( - clock, MyAlloc(1)); + typename Traits::template Cont c(clock, MyAlloc(1)); checkContents(c); } { - typename Traits::template Cont c( - clock, MyHash(1), MyEqual(1)); + typename Traits::template Cont c(clock, MyHash(1), MyEqual(1)); checkContents(c); } { - typename Traits::template Cont c( - clock, MyHash(1), MyAlloc(1)); + typename Traits::template Cont c(clock, MyHash(1), MyAlloc(1)); checkContents(c); } { - typename Traits::template Cont c( - clock, MyEqual(1), MyAlloc(1)); + typename Traits::template Cont c(clock, MyEqual(1), MyAlloc(1)); checkContents(c); } { - typename Traits::template Cont c( - clock, MyHash(1), MyEqual(1), MyAlloc(1)); + typename Traits::template Cont c(clock, MyHash(1), MyEqual(1), MyAlloc(1)); checkContents(c); } } @@ -850,34 +800,29 @@ aged_associative_container_test_base::testConstructRange() testcase("range"); { - typename Traits::template Cont c( - v.begin(), v.end(), clock); + typename Traits::template Cont c(v.begin(), v.end(), clock); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyComp(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyComp(1)); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyAlloc(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyAlloc(1)); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyComp(1), MyAlloc(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyComp(1), MyAlloc(1)); checkContents(c, v); } // swap { - typename Traits::template Cont c1( - v.begin(), v.end(), clock); + typename Traits::template Cont c1(v.begin(), v.end(), clock); typename Traits::template Cont c2(clock); std::swap(c1, c2); checkContents(c2, v); @@ -903,44 +848,37 @@ aged_associative_container_test_base::testConstructRange() testcase("range"); { - typename Traits::template Cont c( - v.begin(), v.end(), clock); + typename Traits::template Cont c(v.begin(), v.end(), clock); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyHash(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyHash(1)); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyEqual(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyEqual(1)); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyAlloc(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyAlloc(1)); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyHash(1), MyEqual(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyHash(1), MyEqual(1)); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyHash(1), MyAlloc(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyHash(1), MyAlloc(1)); checkContents(c, v); } { - typename Traits::template Cont c( - v.begin(), v.end(), clock, MyEqual(1), MyAlloc(1)); + typename Traits::template Cont c(v.begin(), v.end(), clock, MyEqual(1), MyAlloc(1)); checkContents(c, v); } @@ -1201,9 +1139,7 @@ aged_associative_container_test_base::testReverseIterator() template void -aged_associative_container_test_base::checkInsertCopy( - Container& c, - Values const& v) +aged_associative_container_test_base::checkInsertCopy(Container& c, Values const& v) { for (auto const& e : v) c.insert(e); @@ -1212,9 +1148,7 @@ aged_associative_container_test_base::checkInsertCopy( template void -aged_associative_container_test_base::checkInsertMove( - Container& c, - Values const& v) +aged_associative_container_test_base::checkInsertMove(Container& c, Values const& v) { Values v2(v); for (auto& e : v2) @@ -1224,9 +1158,7 @@ aged_associative_container_test_base::checkInsertMove( template void -aged_associative_container_test_base::checkInsertHintCopy( - Container& c, - Values const& v) +aged_associative_container_test_base::checkInsertHintCopy(Container& c, Values const& v) { for (auto const& e : v) c.insert(c.cend(), e); @@ -1235,9 +1167,7 @@ aged_associative_container_test_base::checkInsertHintCopy( template void -aged_associative_container_test_base::checkInsertHintMove( - Container& c, - Values const& v) +aged_associative_container_test_base::checkInsertHintMove(Container& c, Values const& v) { Values v2(v); for (auto& e : v2) @@ -1247,9 +1177,7 @@ aged_associative_container_test_base::checkInsertHintMove( template void -aged_associative_container_test_base::checkEmplace( - Container& c, - Values const& v) +aged_associative_container_test_base::checkEmplace(Container& c, Values const& v) { for (auto const& e : v) c.emplace(e); @@ -1258,9 +1186,7 @@ aged_associative_container_test_base::checkEmplace( template void -aged_associative_container_test_base::checkEmplaceHint( - Container& c, - Values const& v) +aged_associative_container_test_base::checkEmplaceHint(Container& c, Values const& v) { for (auto const& e : v) c.emplace_hint(c.cend(), e); @@ -1339,12 +1265,8 @@ aged_associative_container_test_base::testChronological() typename Traits::template Cont<> c(v.begin(), v.end(), clock); - BEAST_EXPECT(std::equal( - c.chronological.cbegin(), - c.chronological.cend(), - v.begin(), - v.end(), - equal_value())); + BEAST_EXPECT( + std::equal(c.chronological.cbegin(), c.chronological.cend(), v.begin(), v.end(), equal_value())); // Test touch() with a non-const iterator. for (auto iter(v.crbegin()); iter != v.crend(); ++iter) @@ -1358,12 +1280,8 @@ aged_associative_container_test_base::testChronological() c.touch(found); } - BEAST_EXPECT(std::equal( - c.chronological.cbegin(), - c.chronological.cend(), - v.crbegin(), - v.crend(), - equal_value())); + BEAST_EXPECT( + std::equal(c.chronological.cbegin(), c.chronological.cend(), v.crbegin(), v.crend(), equal_value())); // Test touch() with a const_iterator for (auto iter(v.cbegin()); iter != v.cend(); ++iter) @@ -1377,12 +1295,8 @@ aged_associative_container_test_base::testChronological() c.touch(found); } - BEAST_EXPECT(std::equal( - c.chronological.cbegin(), - c.chronological.cend(), - v.cbegin(), - v.cend(), - equal_value())); + BEAST_EXPECT( + std::equal(c.chronological.cbegin(), c.chronological.cend(), v.cbegin(), v.cend(), equal_value())); { // Because touch (reverse_iterator pos) is not allowed, the following @@ -1435,9 +1349,7 @@ aged_associative_container_test_base::testArrayCreate() template void -aged_associative_container_test_base::reverseFillAgedContainer( - Container& c, - Values const& values) +aged_associative_container_test_base::reverseFillAgedContainer(Container& c, Values const& values) { // Just in case the passed in container was not empty. c.clear(); @@ -1463,9 +1375,7 @@ aged_associative_container_test_base::reverseFillAgedContainer( // cannot use operator-- with unordered container iterators. template Iter -aged_associative_container_test_base::nextToEndIter( - Iter beginIter, - Iter const endIter) +aged_associative_container_test_base::nextToEndIter(Iter beginIter, Iter const endIter) { if (beginIter == endIter) { @@ -1497,10 +1407,7 @@ aged_associative_container_test_base::nextToEndIter( // the whole test. template bool -aged_associative_container_test_base::doElementErase( - Container& c, - Iter const beginItr, - Iter const endItr) +aged_associative_container_test_base::doElementErase(Container& c, Iter const beginItr, Iter const endItr) { auto it(beginItr); size_t count = c.size(); @@ -1558,8 +1465,7 @@ aged_associative_container_test_base::testElementErase() { // Test standard iterators auto tempContainer(c); - if (!doElementErase( - tempContainer, tempContainer.cbegin(), tempContainer.cend())) + if (!doElementErase(tempContainer, tempContainer.cbegin(), tempContainer.cend())) return; // Test failed BEAST_EXPECT(tempContainer.empty()); @@ -1580,9 +1486,7 @@ aged_associative_container_test_base::testElementErase() auto tempContainer(c); BEAST_EXPECT(tempContainer.size() > 2); if (!doElementErase( - tempContainer, - ++tempContainer.begin(), - nextToEndIter(tempContainer.begin(), tempContainer.end()))) + tempContainer, ++tempContainer.begin(), nextToEndIter(tempContainer.begin(), tempContainer.end()))) return; // Test failed BEAST_EXPECT(tempContainer.size() == 2); @@ -1593,10 +1497,7 @@ aged_associative_container_test_base::testElementErase() auto tempContainer(c); BEAST_EXPECT(tempContainer.size() > 2); auto& chron(tempContainer.chronological); - if (!doElementErase( - tempContainer, - ++chron.begin(), - nextToEndIter(chron.begin(), chron.end()))) + if (!doElementErase(tempContainer, ++chron.begin(), nextToEndIter(chron.begin(), chron.end()))) return; // Test failed BEAST_EXPECT(tempContainer.size() == 2); @@ -1631,9 +1532,7 @@ aged_associative_container_test_base::testElementErase() // template void -aged_associative_container_test_base::doRangeErase( - Container& c, - BeginEndSrc const& beginEndSrc) +aged_associative_container_test_base::doRangeErase(Container& c, BeginEndSrc const& beginEndSrc) { BEAST_EXPECT(c.size() > 2); auto itBeginPlusOne(beginEndSrc.begin()); @@ -1793,51 +1692,35 @@ public: using T = int; static_assert( - std::is_same< - aged_set, - detail::aged_ordered_container>::value, + std::is_same, detail::aged_ordered_container>::value, "bad alias: aged_set"); static_assert( - std::is_same< - aged_multiset, - detail::aged_ordered_container>::value, + std::is_same, detail::aged_ordered_container>::value, "bad alias: aged_multiset"); static_assert( - std::is_same< - aged_map, - detail::aged_ordered_container>::value, + std::is_same, detail::aged_ordered_container>::value, "bad alias: aged_map"); static_assert( - std::is_same< - aged_multimap, - detail::aged_ordered_container>::value, + std::is_same, detail::aged_ordered_container>::value, "bad alias: aged_multimap"); static_assert( - std::is_same< - aged_unordered_set, - detail::aged_unordered_container>::value, + std::is_same, detail::aged_unordered_container>::value, "bad alias: aged_unordered_set"); static_assert( - std::is_same< - aged_unordered_multiset, - detail::aged_unordered_container>::value, + std::is_same, detail::aged_unordered_container>::value, "bad alias: aged_unordered_multiset"); static_assert( - std::is_same< - aged_unordered_map, - detail::aged_unordered_container>::value, + std::is_same, detail::aged_unordered_container>::value, "bad alias: aged_unordered_map"); static_assert( - std::is_same< - aged_unordered_multimap, - detail::aged_unordered_container>::value, + std::is_same, detail::aged_unordered_container>::value, "bad alias: aged_unordered_multimap"); void diff --git a/src/test/beast/beast_CurrentThreadName_test.cpp b/src/test/beast/beast_CurrentThreadName_test.cpp index 918d426979..2a365c6e9c 100644 --- a/src/test/beast/beast_CurrentThreadName_test.cpp +++ b/src/test/beast/beast_CurrentThreadName_test.cpp @@ -12,10 +12,7 @@ class CurrentThreadName_test : public beast::unit_test::suite { private: static void - exerciseName( - std::string myName, - std::atomic* stop, - std::atomic* state) + exerciseName(std::string myName, std::atomic* stop, std::atomic* state) { // Verify that upon creation a thread has no name. auto const initialThreadName = beast::getCurrentThreadName(); @@ -92,11 +89,10 @@ public: // are set correctly (the 16th character is reserved for the null // terminator). { - testName( - "123456789012345", - "123456789012345"); // 15 chars, maximum allowed - testName("", ""); // empty name - testName("short", "short"); // short name + testName("123456789012345", + "123456789012345"); // 15 chars, maximum allowed + testName("", ""); // empty name + testName("short", "short"); // short name } #endif } diff --git a/src/test/beast/beast_PropertyStream_test.cpp b/src/test/beast/beast_PropertyStream_test.cpp index e6c19c8e5a..c2e6ddc22b 100644 --- a/src/test/beast/beast_PropertyStream_test.cpp +++ b/src/test/beast/beast_PropertyStream_test.cpp @@ -9,10 +9,7 @@ public: using Source = PropertyStream::Source; void - test_peel_name( - std::string s, - std::string const& expected, - std::string const& expected_remainder) + test_peel_name(std::string s, std::string const& expected, std::string const& expected_remainder) { try { @@ -28,10 +25,7 @@ public: } void - test_peel_leading_slash( - std::string s, - std::string const& expected, - bool should_be_found) + test_peel_leading_slash(std::string s, std::string const& expected, bool should_be_found) { try { @@ -47,10 +41,7 @@ public: } void - test_peel_trailing_slashstar( - std::string s, - std::string const& expected_remainder, - bool should_be_found) + test_peel_trailing_slashstar(std::string s, std::string const& expected_remainder, bool should_be_found) { try { @@ -111,11 +102,7 @@ public: } void - test_find( - Source& root, - std::string path, - Source* expected, - bool expected_star) + test_find(Source& root, std::string path, Source* expected, bool expected_star) { try { diff --git a/src/test/beast/beast_abstract_clock_test.cpp b/src/test/beast/beast_abstract_clock_test.cpp index 453f3c535f..94b7909820 100644 --- a/src/test/beast/beast_abstract_clock_test.cpp +++ b/src/test/beast/beast_abstract_clock_test.cpp @@ -23,8 +23,7 @@ public: std::this_thread::sleep_for(std::chrono::milliseconds(1500)); auto const t2(c.now()); - log << "t1= " << t1.time_since_epoch().count() - << ", t2= " << t2.time_since_epoch().count() + log << "t1= " << t1.time_since_epoch().count() << ", t2= " << t2.time_since_epoch().count() << ", elapsed= " << (t2 - t1).count() << std::endl; pass(); @@ -46,8 +45,7 @@ public: c.set(clock_type::time_point(std::chrono::seconds(2))); auto c3 = c.now().time_since_epoch(); - log << "[" << c1.count() << "," << c2.count() << "," << c3.count() - << "]" << std::endl; + log << "[" << c1.count() << "," << c2.count() << "," << c3.count() << "]" << std::endl; pass(); } @@ -57,9 +55,7 @@ public: { test("steady_clock", get_abstract_clock()); test("system_clock", get_abstract_clock()); - test( - "high_resolution_clock", - get_abstract_clock()); + test("high_resolution_clock", get_abstract_clock()); test_manual(); } diff --git a/src/test/beast/beast_io_latency_probe_test.cpp b/src/test/beast/beast_io_latency_probe_test.cpp index 1a6b0a9a1e..4a78eb77fe 100644 --- a/src/test/beast/beast_io_latency_probe_test.cpp +++ b/src/test/beast/beast_io_latency_probe_test.cpp @@ -15,11 +15,9 @@ using namespace std::chrono_literals; -class io_latency_probe_test : public beast::unit_test::suite, - public beast::test::enable_yield_to +class io_latency_probe_test : public beast::unit_test::suite, public beast::test::enable_yield_to { - using MyTimer = - boost::asio::basic_waitable_timer; + using MyTimer = boost::asio::basic_waitable_timer; #ifdef XRPL_RUNNING_IN_CI /** @@ -29,9 +27,7 @@ class io_latency_probe_test : public beast::unit_test::suite, * timer inaccuracy impacts the io_probe tests below. * */ - template < - class Clock, - class MeasureClock = std::chrono::high_resolution_clock> + template struct measure_asio_timers { using duration = typename Clock::duration; @@ -43,9 +39,8 @@ class io_latency_probe_test : public beast::unit_test::suite, { using namespace std::chrono; boost::asio::io_context ios; - std::optional> - work{boost::asio::make_work_guard(ios)}; + std::optional> work{ + boost::asio::make_work_guard(ios)}; std::thread worker{[&] { ios.run(); }}; boost::asio::basic_waitable_timer timer{ios}; elapsed_times_.reserve(num_samples); @@ -84,8 +79,7 @@ class io_latency_probe_test : public beast::unit_test::suite, double sum = {0}; for (auto const& v : elapsed_times_) { - sum += static_cast( - std::chrono::duration_cast(v).count()); + sum += static_cast(std::chrono::duration_cast(v).count()); } return sum / elapsed_times_.size(); } @@ -94,9 +88,7 @@ class io_latency_probe_test : public beast::unit_test::suite, auto getMax() { - return std::chrono::duration_cast( - *std::max_element( - elapsed_times_.begin(), elapsed_times_.end())) + return std::chrono::duration_cast(*std::max_element(elapsed_times_.begin(), elapsed_times_.end())) .count(); } @@ -104,9 +96,7 @@ class io_latency_probe_test : public beast::unit_test::suite, auto getMin() { - return std::chrono::duration_cast( - *std::min_element( - elapsed_times_.begin(), elapsed_times_.end())) + return std::chrono::duration_cast(*std::min_element(elapsed_times_.begin(), elapsed_times_.end())) .count(); } }; @@ -117,10 +107,7 @@ class io_latency_probe_test : public beast::unit_test::suite, beast::io_latency_probe probe_; std::vector durations_; - test_sampler( - std::chrono::milliseconds interval, - boost::asio::io_context& ios) - : probe_(interval, ios) + test_sampler(std::chrono::milliseconds interval, boost::asio::io_context& ios) : probe_(interval, ios) { } @@ -173,13 +160,9 @@ class io_latency_probe_test : public beast::unit_test::suite, // adjust min expected based on measurements // if running in CI/VM environment measure_asio_timers tt{interval}; - log << "measured mean for timers: " << tt.getMean() - << "ms\n"; - log << "measured max for timers: " << tt.getMax() - << "ms\n"; - expected_probe_count_min = - static_cast( - duration_cast(probe_duration).count()) / + log << "measured mean for timers: " << tt.getMean() << "ms\n"; + log << "measured max for timers: " << tt.getMax() << "ms\n"; + expected_probe_count_min = static_cast(duration_cast(probe_duration).count()) / static_cast(tt.getMean()); #endif test_sampler io_probe{interval, get_io_context()}; @@ -190,8 +173,7 @@ class io_latency_probe_test : public beast::unit_test::suite, return; auto probes_seen = io_probe.durations_.size(); BEAST_EXPECTS( - probes_seen >= (expected_probe_count_min - 1) && - probes_seen <= (expected_probe_count_max + 1), + probes_seen >= (expected_probe_count_min - 1) && probes_seen <= (expected_probe_count_max + 1), std::string("probe count is ") + std::to_string(probes_seen)); io_probe.probe_.cancel_async(); // wait again in order to flush the remaining diff --git a/src/test/beast/define_print.cpp b/src/test/beast/define_print.cpp index 660f88b24a..07b1422a54 100644 --- a/src/test/beast/define_print.cpp +++ b/src/test/beast/define_print.cpp @@ -23,9 +23,7 @@ public: std::size_t manual = 0; std::size_t total = 0; - auto prefix = [](suite_info const& s) { - return s.manual() ? "|M| " : " "; - }; + auto prefix = [](suite_info const& s) { return s.manual() ? "|M| " : " "; }; for (auto const& s : global_suites()) { @@ -36,8 +34,7 @@ public: ++total; } - log << amount(total, "suite") << " total, " - << amount(manual, "manual suite") << std::endl; + log << amount(total, "suite") << " total, " << amount(manual, "manual suite") << std::endl; pass(); } diff --git a/src/test/beast/xxhasher_test.cpp b/src/test/beast/xxhasher_test.cpp index f740bf0821..868d522384 100644 --- a/src/test/beast/xxhasher_test.cpp +++ b/src/test/beast/xxhasher_test.cpp @@ -16,9 +16,7 @@ public: std::string objectToHash{"Hello, xxHash!"}; hasher(objectToHash.data(), objectToHash.size()); - BEAST_EXPECT( - static_cast(hasher) == - 16042857369214894119ULL); + BEAST_EXPECT(static_cast(hasher) == 16042857369214894119ULL); } void @@ -31,24 +29,19 @@ public: std::string objectToHash{"Hello, xxHash!"}; hasher(objectToHash.data(), objectToHash.size()); - BEAST_EXPECT( - static_cast(hasher) == - 14440132435660934800ULL); + BEAST_EXPECT(static_cast(hasher) == 14440132435660934800ULL); } void testWithTwoSeeds() { testcase("With two seeds"); - xxhasher hasher{ - static_cast(102), static_cast(103)}; + xxhasher hasher{static_cast(102), static_cast(103)}; std::string objectToHash{"Hello, xxHash!"}; hasher(objectToHash.data(), objectToHash.size()); - BEAST_EXPECT( - static_cast(hasher) == - 14440132435660934800ULL); + BEAST_EXPECT(static_cast(hasher) == 14440132435660934800ULL); } void @@ -63,9 +56,7 @@ public: hasher(objectToHash.data(), objectToHash.size()); } - BEAST_EXPECT( - static_cast(hasher) == - 15296278154063476002ULL); + BEAST_EXPECT(static_cast(hasher) == 15296278154063476002ULL); } void @@ -80,9 +71,7 @@ public: hasher(objectToHash.data(), objectToHash.size()); } - BEAST_EXPECT( - static_cast(hasher) == - 17285302196561698791ULL); + BEAST_EXPECT(static_cast(hasher) == 17285302196561698791ULL); } void @@ -101,9 +90,7 @@ public: hasher(bigObject.data(), bigObject.size()); hasher(objectToHash.data(), objectToHash.size()); - BEAST_EXPECT( - static_cast(hasher) == - 1865045178324729219ULL); + BEAST_EXPECT(static_cast(hasher) == 1865045178324729219ULL); } void @@ -122,9 +109,7 @@ public: hasher(bigObject.data(), bigObject.size()); hasher(objectToHash.data(), objectToHash.size()); - BEAST_EXPECT( - static_cast(hasher) == - 16189862915636005281ULL); + BEAST_EXPECT(static_cast(hasher) == 16189862915636005281ULL); } void @@ -140,9 +125,7 @@ public: } hasher(objectToHash.data(), objectToHash.size()); - BEAST_EXPECT( - static_cast(hasher) == - 15296278154063476002ULL); + BEAST_EXPECT(static_cast(hasher) == 15296278154063476002ULL); } void @@ -158,9 +141,7 @@ public: } hasher(objectToHash.data(), objectToHash.size()); - BEAST_EXPECT( - static_cast(hasher) == - 17285302196561698791ULL); + BEAST_EXPECT(static_cast(hasher) == 17285302196561698791ULL); } void diff --git a/src/test/consensus/ByzantineFailureSim_test.cpp b/src/test/consensus/ByzantineFailureSim_test.cpp index 210333e303..62899730c2 100644 --- a/src/test/consensus/ByzantineFailureSim_test.cpp +++ b/src/test/consensus/ByzantineFailureSim_test.cpp @@ -22,8 +22,7 @@ class ByzantineFailureSim_test : public beast::unit_test::suite Sim sim; ConsensusParms const parms{}; - SimDuration const delay = - round(0.2 * parms.ledgerGRANULARITY); + SimDuration const delay = round(0.2 * parms.ledgerGRANULARITY); PeerGroup a = sim.createGroup(1); PeerGroup b = sim.createGroup(1); PeerGroup c = sim.createGroup(1); @@ -46,12 +45,10 @@ class ByzantineFailureSim_test : public beast::unit_test::suite sim.collectors.add(sc); - for (TrustGraph::ForkInfo const& fi : - sim.trustGraph.forkablePairs(0.8)) + for (TrustGraph::ForkInfo const& fi : sim.trustGraph.forkablePairs(0.8)) { std::cout << "Can fork " << PeerGroup{fi.unlA} << " " - << " " << PeerGroup{fi.unlB} << " overlap " << fi.overlap - << " required " << fi.required << "\n"; + << " " << PeerGroup{fi.unlB} << " overlap " << fi.overlap << " required " << fi.required << "\n"; }; // set prior state @@ -66,14 +63,12 @@ class ByzantineFailureSim_test : public beast::unit_test::suite // a non-consensus approved transaction if (byzantineNodes.contains(peer)) { - peer->txInjections.emplace( - peer->lastClosedLedger.seq(), Tx{42}); + peer->txInjections.emplace(peer->lastClosedLedger.seq(), Tx{42}); } } sim.run(4); std::cout << "Branches: " << sim.branches() << "\n"; - std::cout << "Fully synchronized: " << std::boolalpha - << sim.synchronized() << "\n"; + std::cout << "Fully synchronized: " << std::boolalpha << sim.synchronized() << "\n"; // Not tessting anything currently. pass(); } diff --git a/src/test/consensus/Consensus_test.cpp b/src/test/consensus/Consensus_test.cpp index b7bfb302bc..3227ad4d1c 100644 --- a/src/test/consensus/Consensus_test.cpp +++ b/src/test/consensus/Consensus_test.cpp @@ -28,33 +28,24 @@ public: ConsensusParms const p{}; // Bizarre times forcibly close - BEAST_EXPECT(shouldCloseLedger( - true, 10, 10, 10, -10s, 10s, 1s, 1s, p, journal_)); - BEAST_EXPECT(shouldCloseLedger( - true, 10, 10, 10, 100h, 10s, 1s, 1s, p, journal_)); - BEAST_EXPECT(shouldCloseLedger( - true, 10, 10, 10, 10s, 100h, 1s, 1s, p, journal_)); + BEAST_EXPECT(shouldCloseLedger(true, 10, 10, 10, -10s, 10s, 1s, 1s, p, journal_)); + BEAST_EXPECT(shouldCloseLedger(true, 10, 10, 10, 100h, 10s, 1s, 1s, p, journal_)); + BEAST_EXPECT(shouldCloseLedger(true, 10, 10, 10, 10s, 100h, 1s, 1s, p, journal_)); // Rest of network has closed - BEAST_EXPECT( - shouldCloseLedger(true, 10, 3, 5, 10s, 10s, 10s, 10s, p, journal_)); + BEAST_EXPECT(shouldCloseLedger(true, 10, 3, 5, 10s, 10s, 10s, 10s, p, journal_)); // No transactions means wait until end of internval - BEAST_EXPECT( - !shouldCloseLedger(false, 10, 0, 0, 1s, 1s, 1s, 10s, p, journal_)); - BEAST_EXPECT( - shouldCloseLedger(false, 10, 0, 0, 1s, 10s, 1s, 10s, p, journal_)); + BEAST_EXPECT(!shouldCloseLedger(false, 10, 0, 0, 1s, 1s, 1s, 10s, p, journal_)); + BEAST_EXPECT(shouldCloseLedger(false, 10, 0, 0, 1s, 10s, 1s, 10s, p, journal_)); // Enforce minimum ledger open time - BEAST_EXPECT( - !shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 1s, 10s, p, journal_)); + BEAST_EXPECT(!shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 1s, 10s, p, journal_)); // Don't go too much faster than last time - BEAST_EXPECT( - !shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 3s, 10s, p, journal_)); + BEAST_EXPECT(!shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 3s, 10s, p, journal_)); - BEAST_EXPECT( - shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 10s, 10s, p, journal_)); + BEAST_EXPECT(shouldCloseLedger(true, 10, 0, 0, 10s, 10s, 10s, 10s, p, journal_)); } void @@ -70,93 +61,61 @@ public: // Disputes still in doubt // // Not enough time has elapsed - BEAST_EXPECT( - ConsensusState::No == - checkConsensus(10, 2, 2, 0, 3s, 2s, false, p, true, journal_)); + BEAST_EXPECT(ConsensusState::No == checkConsensus(10, 2, 2, 0, 3s, 2s, false, p, true, journal_)); // If not enough peers have proposed, ensure // more time for proposals - BEAST_EXPECT( - ConsensusState::No == - checkConsensus(10, 2, 2, 0, 3s, 4s, false, p, true, journal_)); + BEAST_EXPECT(ConsensusState::No == checkConsensus(10, 2, 2, 0, 3s, 4s, false, p, true, journal_)); // Enough time has elapsed and we all agree - BEAST_EXPECT( - ConsensusState::Yes == - checkConsensus(10, 2, 2, 0, 3s, 10s, false, p, true, journal_)); + BEAST_EXPECT(ConsensusState::Yes == checkConsensus(10, 2, 2, 0, 3s, 10s, false, p, true, journal_)); // Enough time has elapsed and we don't yet agree - BEAST_EXPECT( - ConsensusState::No == - checkConsensus(10, 2, 1, 0, 3s, 10s, false, p, true, journal_)); + BEAST_EXPECT(ConsensusState::No == checkConsensus(10, 2, 1, 0, 3s, 10s, false, p, true, journal_)); // Our peers have moved on // Enough time has elapsed and we all agree - BEAST_EXPECT( - ConsensusState::MovedOn == - checkConsensus(10, 2, 1, 8, 3s, 10s, false, p, true, journal_)); + BEAST_EXPECT(ConsensusState::MovedOn == checkConsensus(10, 2, 1, 8, 3s, 10s, false, p, true, journal_)); // If no peers, don't agree until time has passed. - BEAST_EXPECT( - ConsensusState::No == - checkConsensus(0, 0, 0, 0, 3s, 10s, false, p, true, journal_)); + BEAST_EXPECT(ConsensusState::No == checkConsensus(0, 0, 0, 0, 3s, 10s, false, p, true, journal_)); // Agree if no peers and enough time has passed. - BEAST_EXPECT( - ConsensusState::Yes == - checkConsensus(0, 0, 0, 0, 3s, 16s, false, p, true, journal_)); + BEAST_EXPECT(ConsensusState::Yes == checkConsensus(0, 0, 0, 0, 3s, 16s, false, p, true, journal_)); // Expire if too much time has passed without agreement - BEAST_EXPECT( - ConsensusState::Expired == - checkConsensus(10, 8, 1, 0, 1s, 19s, false, p, true, journal_)); + BEAST_EXPECT(ConsensusState::Expired == checkConsensus(10, 8, 1, 0, 1s, 19s, false, p, true, journal_)); /////////////// // Stalled // // Not enough time has elapsed - BEAST_EXPECT( - ConsensusState::No == - checkConsensus(10, 2, 2, 0, 3s, 2s, true, p, true, journal_)); + BEAST_EXPECT(ConsensusState::No == checkConsensus(10, 2, 2, 0, 3s, 2s, true, p, true, journal_)); // If not enough peers have proposed, ensure // more time for proposals - BEAST_EXPECT( - ConsensusState::No == - checkConsensus(10, 2, 2, 0, 3s, 4s, true, p, true, journal_)); + BEAST_EXPECT(ConsensusState::No == checkConsensus(10, 2, 2, 0, 3s, 4s, true, p, true, journal_)); // Enough time has elapsed and we all agree - BEAST_EXPECT( - ConsensusState::Yes == - checkConsensus(10, 2, 2, 0, 3s, 10s, true, p, true, journal_)); + BEAST_EXPECT(ConsensusState::Yes == checkConsensus(10, 2, 2, 0, 3s, 10s, true, p, true, journal_)); // Enough time has elapsed and we don't yet agree, but there's nothing // left to dispute - BEAST_EXPECT( - ConsensusState::Yes == - checkConsensus(10, 2, 1, 0, 3s, 10s, true, p, true, journal_)); + BEAST_EXPECT(ConsensusState::Yes == checkConsensus(10, 2, 1, 0, 3s, 10s, true, p, true, journal_)); // Our peers have moved on // Enough time has elapsed and we all agree, nothing left to dispute - BEAST_EXPECT( - ConsensusState::Yes == - checkConsensus(10, 2, 1, 8, 3s, 10s, true, p, true, journal_)); + BEAST_EXPECT(ConsensusState::Yes == checkConsensus(10, 2, 1, 8, 3s, 10s, true, p, true, journal_)); // If no peers, don't agree until time has passed. - BEAST_EXPECT( - ConsensusState::No == - checkConsensus(0, 0, 0, 0, 3s, 10s, true, p, true, journal_)); + BEAST_EXPECT(ConsensusState::No == checkConsensus(0, 0, 0, 0, 3s, 10s, true, p, true, journal_)); // Agree if no peers and enough time has passed. - BEAST_EXPECT( - ConsensusState::Yes == - checkConsensus(0, 0, 0, 0, 3s, 16s, true, p, true, journal_)); + BEAST_EXPECT(ConsensusState::Yes == checkConsensus(0, 0, 0, 0, 3s, 16s, true, p, true, journal_)); // We are done if there's nothing left to dispute, no matter how much // time has passed - BEAST_EXPECT( - ConsensusState::Yes == - checkConsensus(10, 8, 1, 0, 1s, 19s, true, p, true, journal_)); + BEAST_EXPECT(ConsensusState::Yes == checkConsensus(10, 8, 1, 0, 1s, 19s, true, p, true, journal_)); } void @@ -196,8 +155,7 @@ public: PeerGroup peers = sim.createGroup(5); // Connected trust and network graphs with single fixed delay - peers.trustAndConnect( - peers, round(0.2 * parms.ledgerGRANULARITY)); + peers.trustAndConnect(peers, round(0.2 * parms.ledgerGRANULARITY)); // everyone submits their own ID as a TX for (Peer* p : peers) @@ -245,11 +203,9 @@ public: network.trust(network); // Fast and slow network connections - fast.connect( - fast, round(0.2 * parms.ledgerGRANULARITY)); + fast.connect(fast, round(0.2 * parms.ledgerGRANULARITY)); - slow.connect( - network, round(1.1 * parms.ledgerGRANULARITY)); + slow.connect(network, round(1.1 * parms.ledgerGRANULARITY)); // All peers submit their own ID as a transaction for (Peer* peer : network) @@ -268,16 +224,14 @@ public: BEAST_EXPECT(lcl.seq() == Ledger::Seq{1}); BEAST_EXPECT(peer->prevProposers == network.size() - 1); - BEAST_EXPECT( - peer->prevRoundTime == network[0]->prevRoundTime); + BEAST_EXPECT(peer->prevRoundTime == network[0]->prevRoundTime); BEAST_EXPECT(lcl.txs().find(Tx{0}) == lcl.txs().end()); for (std::uint32_t i = 2; i < network.size(); ++i) BEAST_EXPECT(lcl.txs().find(Tx{i}) != lcl.txs().end()); // Tx 0 didn't make it - BEAST_EXPECT( - peer->openTxs.find(Tx{0}) != peer->openTxs.end()); + BEAST_EXPECT(peer->openTxs.find(Tx{0}) != peer->openTxs.end()); } } } @@ -301,12 +255,9 @@ public: network.trust(network); // Fast and slow network connections - fast.connect( - fast, round(0.2 * parms.ledgerGRANULARITY)); + fast.connect(fast, round(0.2 * parms.ledgerGRANULARITY)); - slow.connect( - network, - round(1.1 * parms.ledgerGRANULARITY)); + slow.connect(network, round(1.1 * parms.ledgerGRANULARITY)); for (Peer* peer : slow) peer->runAsValidator = isParticipant; @@ -330,22 +281,17 @@ public: BEAST_EXPECT(lcl.seq() == Ledger::Seq{1}); BEAST_EXPECT(lcl.txs().find(Tx{0}) == lcl.txs().end()); BEAST_EXPECT(lcl.txs().find(Tx{1}) == lcl.txs().end()); - for (std::uint32_t i = slow.size(); i < network.size(); - ++i) - BEAST_EXPECT( - lcl.txs().find(Tx{i}) != lcl.txs().end()); + for (std::uint32_t i = slow.size(); i < network.size(); ++i) + BEAST_EXPECT(lcl.txs().find(Tx{i}) != lcl.txs().end()); // Tx 0-1 didn't make it - BEAST_EXPECT( - peer->openTxs.find(Tx{0}) != peer->openTxs.end()); - BEAST_EXPECT( - peer->openTxs.find(Tx{1}) != peer->openTxs.end()); + BEAST_EXPECT(peer->openTxs.find(Tx{0}) != peer->openTxs.end()); + BEAST_EXPECT(peer->openTxs.find(Tx{1}) != peer->openTxs.end()); } Peer const* slowPeer = slow[0]; if (isParticipant) - BEAST_EXPECT( - slowPeer->prevProposers == network.size() - 1); + BEAST_EXPECT(slowPeer->prevProposers == network.size() - 1); else BEAST_EXPECT(slowPeer->prevProposers == fast.size()); @@ -369,18 +315,14 @@ public: if (isParticipant) { - BEAST_EXPECT( - peer->prevProposers == network.size() - 1); - BEAST_EXPECT( - peer->prevRoundTime > slowPeer->prevRoundTime); + BEAST_EXPECT(peer->prevProposers == network.size() - 1); + BEAST_EXPECT(peer->prevRoundTime > slowPeer->prevRoundTime); } else { - BEAST_EXPECT( - peer->prevProposers == fast.size() - 1); + BEAST_EXPECT(peer->prevProposers == fast.size() - 1); // so all peers should have closed together - BEAST_EXPECT( - peer->prevRoundTime == slowPeer->prevRoundTime); + BEAST_EXPECT(peer->prevRoundTime == slowPeer->prevRoundTime); } } } @@ -429,14 +371,12 @@ public: PeerGroup network = groupA + groupB + groupC; network.trust(network); - network.connect( - network, round(0.2 * parms.ledgerGRANULARITY)); + network.connect(network, round(0.2 * parms.ledgerGRANULARITY)); // Run consensus without skew until we have a short close time // resolution Peer* firstPeer = *groupA.begin(); - while (firstPeer->lastClosedLedger.closeTimeResolution() >= - parms.proposeFRESHNESS) + while (firstPeer->lastClosedLedger.closeTimeResolution() >= parms.proposeFRESHNESS) sim.run(1); // Introduce a shift on the time of 2/3 of peers @@ -501,8 +441,7 @@ public: PeerGroup majority = majorityA + majorityB; PeerGroup network = minority + majority; - SimDuration delay = - round(0.2 * parms.ledgerGRANULARITY); + SimDuration delay = round(0.2 * parms.ledgerGRANULARITY); minority.trustAndConnect(minority + majorityA, delay); majority.trustAndConnect(majority, delay); @@ -562,8 +501,7 @@ public: { if (BEAST_EXPECT(peerJumps.closeJumps.size() == 1)) { - JumpCollector::Jump const& jump = - peerJumps.closeJumps.front(); + JumpCollector::Jump const& jump = peerJumps.closeJumps.front(); // Jump is to a different chain BEAST_EXPECT(jump.from.seq() <= jump.to.seq()); BEAST_EXPECT(!jump.to.isAncestor(jump.from)); @@ -571,11 +509,9 @@ public: } // fully validated jump forward in same chain { - if (BEAST_EXPECT( - peerJumps.fullyValidatedJumps.size() == 1)) + if (BEAST_EXPECT(peerJumps.fullyValidatedJumps.size() == 1)) { - JumpCollector::Jump const& jump = - peerJumps.fullyValidatedJumps.front(); + JumpCollector::Jump const& jump = peerJumps.fullyValidatedJumps.front(); // Jump is to a different chain with same seq BEAST_EXPECT(jump.from.seq() < jump.to.seq()); BEAST_EXPECT(jump.to.isAncestor(jump.from)); @@ -606,8 +542,7 @@ public: clique.trust(clique); PeerGroup network = loner + clique; - network.connect( - network, round(0.2 * parms.ledgerGRANULARITY)); + network.connect(network, round(0.2 * parms.ledgerGRANULARITY)); // initial round to set prior state sim.run(1); @@ -655,8 +590,7 @@ public: // Fast and slow network connections fast.connect(fast, round(0.2 * parms.ledgerGRANULARITY)); - slow.connect( - network, round(1.1 * parms.ledgerGRANULARITY)); + slow.connect(network, round(1.1 * parms.ledgerGRANULARITY)); // Run to the ledger *prior* to decreasing the resolution sim.run(increaseLedgerTimeResolutionEvery - 2); @@ -678,8 +612,7 @@ public: NetClock::duration when = network[0]->now().time_since_epoch(); // Check we are before the 30s to 20s transition - NetClock::duration resolution = - network[0]->lastClosedLedger.closeTimeResolution(); + NetClock::duration resolution = network[0]->lastClosedLedger.closeTimeResolution(); BEAST_EXPECT(resolution == NetClock::duration{30s}); while (((when % NetClock::duration{30s}) != NetClock::duration{15s}) || @@ -756,8 +689,7 @@ public: PeerGroup network = a + b; - SimDuration delay = - round(0.2 * parms.ledgerGRANULARITY); + SimDuration delay = round(0.2 * parms.ledgerGRANULARITY); a.trustAndConnect(a, delay); b.trustAndConnect(b, delay); @@ -768,8 +700,7 @@ public: // Nodes have only seen transactions from their neighbors peer->openTxs.insert(Tx{static_cast(peer->id)}); for (Peer* to : sim.trustGraph.trustedPeers(peer)) - peer->openTxs.insert( - Tx{static_cast(to->id)}); + peer->openTxs.insert(Tx{static_cast(to->id)}); } sim.run(1); @@ -832,11 +763,7 @@ public: csf::SimDuration delay; bool reconnected = false; - Disruptor( - csf::PeerGroup& net, - csf::PeerGroup& c, - csf::PeerGroup& split, - csf::SimDuration d) + Disruptor(csf::PeerGroup& net, csf::PeerGroup& c, csf::PeerGroup& split, csf::SimDuration d) : network(net), groupCfast(c), groupCsplit(split), delay(d) { } @@ -854,8 +781,7 @@ public: // As soon as the fastC node fully validates C, disconnect // ALL c nodes from the network. The fast C node needs to disconnect // as well to prevent it from relaying the validations it did see - if (who == groupCfast[0]->id && - e.ledger.seq() == csf::Ledger::Seq{2}) + if (who == groupCfast[0]->id && e.ledger.seq() == csf::Ledger::Seq{2}) { network.disconnect(groupCsplit); network.disconnect(groupCfast); @@ -1079,11 +1005,8 @@ public: // Simulate clients submitting 1 tx every 5 seconds to a random // validator Rate const rate{1, 5s}; - auto peerSelector = makeSelector( - network.begin(), - network.end(), - std::vector(network.size(), 1.), - sim.rng); + auto peerSelector = + makeSelector(network.begin(), network.end(), std::vector(network.size(), 1.), sim.rng); auto txSubmitter = makeSubmitter( ConstantDistribution{rate.inv()}, sim.scheduler.now(), @@ -1129,10 +1052,8 @@ public: { Dispute proposingTrue{txTrue.id(), true, numPeers, journal_}; Dispute proposingFalse{txFalse.id(), false, numPeers, journal_}; - Dispute followingTrue{ - txFollowingTrue.id(), true, numPeers, journal_}; - Dispute followingFalse{ - txFollowingFalse.id(), false, numPeers, journal_}; + Dispute followingTrue{txFollowingTrue.id(), true, numPeers, journal_}; + Dispute followingFalse{txFollowingFalse.id(), false, numPeers, journal_}; BEAST_EXPECT(proposingTrue.ID() == 99); BEAST_EXPECT(proposingFalse.ID() == 98); BEAST_EXPECT(followingTrue.ID() == 97); @@ -1157,14 +1078,10 @@ public: BEAST_EXPECT(proposingFalse.getOurVote() == false); BEAST_EXPECT(followingTrue.getOurVote() == true); BEAST_EXPECT(followingFalse.getOurVote() == false); - BEAST_EXPECT( - !proposingTrue.stalled(p, true, peersUnchanged, j, clog)); - BEAST_EXPECT( - !proposingFalse.stalled(p, true, peersUnchanged, j, clog)); - BEAST_EXPECT( - !followingTrue.stalled(p, false, peersUnchanged, j, clog)); - BEAST_EXPECT( - !followingFalse.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingTrue.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingFalse.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!followingTrue.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(!followingFalse.stalled(p, false, peersUnchanged, j, clog)); BEAST_EXPECT(clog->str() == ""); // I'm in the majority, my vote should not change @@ -1179,14 +1096,10 @@ public: BEAST_EXPECT(!followingFalse.updateVote(10, false, p)); peersUnchanged = 2; - BEAST_EXPECT( - !proposingTrue.stalled(p, true, peersUnchanged, j, clog)); - BEAST_EXPECT( - !proposingFalse.stalled(p, true, peersUnchanged, j, clog)); - BEAST_EXPECT( - !followingTrue.stalled(p, false, peersUnchanged, j, clog)); - BEAST_EXPECT( - !followingFalse.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingTrue.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingFalse.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!followingTrue.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(!followingFalse.stalled(p, false, peersUnchanged, j, clog)); BEAST_EXPECT(clog->str() == ""); // Right now, the vote is 51%. The requirement is about to jump to @@ -1277,14 +1190,10 @@ public: BEAST_EXPECT(followingFalse.getOurVote() == false); peersUnchanged = 3; - BEAST_EXPECT( - !proposingTrue.stalled(p, true, peersUnchanged, j, clog)); - BEAST_EXPECT( - !proposingFalse.stalled(p, true, peersUnchanged, j, clog)); - BEAST_EXPECT( - !followingTrue.stalled(p, false, peersUnchanged, j, clog)); - BEAST_EXPECT( - !followingFalse.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingTrue.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingFalse.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!followingTrue.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(!followingFalse.stalled(p, false, peersUnchanged, j, clog)); BEAST_EXPECT(clog->str() == ""); // Threshold jumps to 95% @@ -1322,67 +1231,33 @@ public: for (peersUnchanged = 0; peersUnchanged < 6; ++peersUnchanged) { - BEAST_EXPECT( - !proposingTrue.stalled(p, true, peersUnchanged, j, clog)); - BEAST_EXPECT( - !proposingFalse.stalled(p, true, peersUnchanged, j, clog)); - BEAST_EXPECT( - !followingTrue.stalled(p, false, peersUnchanged, j, clog)); - BEAST_EXPECT( - !followingFalse.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingTrue.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingFalse.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!followingTrue.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(!followingFalse.stalled(p, false, peersUnchanged, j, clog)); BEAST_EXPECT(clog->str() == ""); } - auto expectStalled = [this, &clog]( - int txid, - bool ourVote, - int ourTime, - int peerTime, - int support, - std::uint32_t line) { - using namespace std::string_literals; + auto expectStalled = + [this, &clog](int txid, bool ourVote, int ourTime, int peerTime, int support, std::uint32_t line) { + using namespace std::string_literals; - auto const s = clog->str(); - expect(s.find("stalled"), s, __FILE__, line); - expect( - s.starts_with("Transaction "s + std::to_string(txid)), - s, - __FILE__, - line); - expect( - s.find("voting "s + (ourVote ? "YES" : "NO")) != s.npos, - s, - __FILE__, - line); - expect( - s.find("for "s + std::to_string(ourTime) + " rounds."s) != - s.npos, - s, - __FILE__, - line); - expect( - s.find( - "votes in "s + std::to_string(peerTime) + " rounds.") != - s.npos, - s, - __FILE__, - line); - expect( - s.ends_with( - "has "s + std::to_string(support) + "% support. "s), - s, - __FILE__, - line); - clog = std::make_unique(); - }; + auto const s = clog->str(); + expect(s.find("stalled"), s, __FILE__, line); + expect(s.starts_with("Transaction "s + std::to_string(txid)), s, __FILE__, line); + expect(s.find("voting "s + (ourVote ? "YES" : "NO")) != s.npos, s, __FILE__, line); + expect(s.find("for "s + std::to_string(ourTime) + " rounds."s) != s.npos, s, __FILE__, line); + expect(s.find("votes in "s + std::to_string(peerTime) + " rounds.") != s.npos, s, __FILE__, line); + expect(s.ends_with("has "s + std::to_string(support) + "% support. "s), s, __FILE__, line); + clog = std::make_unique(); + }; for (int i = 0; i < 1; ++i) { BEAST_EXPECT(!proposingTrue.updateVote(250 + 10 * i, true, p)); BEAST_EXPECT(!proposingFalse.updateVote(250 + 10 * i, true, p)); BEAST_EXPECT(!followingTrue.updateVote(250 + 10 * i, false, p)); - BEAST_EXPECT( - !followingFalse.updateVote(250 + 10 * i, false, p)); + BEAST_EXPECT(!followingFalse.updateVote(250 + 10 * i, false, p)); BEAST_EXPECT(proposingTrue.getOurVote() == true); BEAST_EXPECT(proposingFalse.getOurVote() == false); @@ -1403,20 +1278,16 @@ public: expectStalled(96, false, 11, 0, 3, __LINE__); // true vote has changed recently, so not stalled - BEAST_EXPECT( - !proposingTrue.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(!proposingTrue.stalled(p, true, peersUnchanged, j, clog)); BEAST_EXPECTS(clog->str() == "", clog->str()); // remaining votes have been unchanged in so long that we only // need to hit the second round at 95% to be stalled, regardless // of peers - BEAST_EXPECT( - proposingFalse.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(proposingFalse.stalled(p, true, peersUnchanged, j, clog)); expectStalled(98, false, 11, 6, 2, __LINE__); - BEAST_EXPECT( - followingTrue.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(followingTrue.stalled(p, false, peersUnchanged, j, clog)); expectStalled(97, true, 11, 6, 97, __LINE__); - BEAST_EXPECT( - followingFalse.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(followingFalse.stalled(p, false, peersUnchanged, j, clog)); expectStalled(96, false, 11, 6, 3, __LINE__); } for (int i = 1; i < 3; ++i) @@ -1424,8 +1295,7 @@ public: BEAST_EXPECT(!proposingTrue.updateVote(250 + 10 * i, true, p)); BEAST_EXPECT(!proposingFalse.updateVote(250 + 10 * i, true, p)); BEAST_EXPECT(!followingTrue.updateVote(250 + 10 * i, false, p)); - BEAST_EXPECT( - !followingFalse.updateVote(250 + 10 * i, false, p)); + BEAST_EXPECT(!followingFalse.updateVote(250 + 10 * i, false, p)); BEAST_EXPECT(proposingTrue.getOurVote() == true); BEAST_EXPECT(proposingFalse.getOurVote() == false); @@ -1446,18 +1316,14 @@ public: // true vote changed 2 rounds ago, and peers are NOT changing, // so stalled - BEAST_EXPECT( - proposingTrue.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(proposingTrue.stalled(p, true, peersUnchanged, j, clog)); expectStalled(99, true, 1 + i, 6, 97, __LINE__); // still stalled - BEAST_EXPECT( - proposingFalse.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(proposingFalse.stalled(p, true, peersUnchanged, j, clog)); expectStalled(98, false, 11 + i, 6, 2, __LINE__); - BEAST_EXPECT( - followingTrue.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(followingTrue.stalled(p, false, peersUnchanged, j, clog)); expectStalled(97, true, 11 + i, 6, 97, __LINE__); - BEAST_EXPECT( - followingFalse.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(followingFalse.stalled(p, false, peersUnchanged, j, clog)); expectStalled(96, false, 11 + i, 6, 3, __LINE__); } for (int i = 3; i < 5; ++i) @@ -1465,8 +1331,7 @@ public: BEAST_EXPECT(!proposingTrue.updateVote(250 + 10 * i, true, p)); BEAST_EXPECT(!proposingFalse.updateVote(250 + 10 * i, true, p)); BEAST_EXPECT(!followingTrue.updateVote(250 + 10 * i, false, p)); - BEAST_EXPECT( - !followingFalse.updateVote(250 + 10 * i, false, p)); + BEAST_EXPECT(!followingFalse.updateVote(250 + 10 * i, false, p)); BEAST_EXPECT(proposingTrue.getOurVote() == true); BEAST_EXPECT(proposingFalse.getOurVote() == false); @@ -1482,17 +1347,13 @@ public: BEAST_EXPECT(followingFalse.stalled(p, false, 0, j, clog)); expectStalled(96, false, 11 + i, 0, 3, __LINE__); - BEAST_EXPECT( - proposingTrue.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(proposingTrue.stalled(p, true, peersUnchanged, j, clog)); expectStalled(99, true, 1 + i, 6, 97, __LINE__); - BEAST_EXPECT( - proposingFalse.stalled(p, true, peersUnchanged, j, clog)); + BEAST_EXPECT(proposingFalse.stalled(p, true, peersUnchanged, j, clog)); expectStalled(98, false, 11 + i, 6, 2, __LINE__); - BEAST_EXPECT( - followingTrue.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(followingTrue.stalled(p, false, peersUnchanged, j, clog)); expectStalled(97, true, 11 + i, 6, 97, __LINE__); - BEAST_EXPECT( - followingFalse.stalled(p, false, peersUnchanged, j, clog)); + BEAST_EXPECT(followingFalse.stalled(p, false, peersUnchanged, j, clog)); expectStalled(96, false, 11 + i, 6, 3, __LINE__); } } diff --git a/src/test/consensus/DistributedValidatorsSim_test.cpp b/src/test/consensus/DistributedValidatorsSim_test.cpp index 1a088576ce..49d2c6e7e2 100644 --- a/src/test/consensus/DistributedValidatorsSim_test.cpp +++ b/src/test/consensus/DistributedValidatorsSim_test.cpp @@ -35,8 +35,7 @@ class DistributedValidators_test : public beast::unit_test::suite ledgerLog(prefix + "_ledger.csv", std::ofstream::app); // title - log << prefix << "(" << numPeers << "," << delay.count() << ")" - << std::endl; + log << prefix << "(" << numPeers << "," << delay.count() << ")" << std::endl; // number of peers, UNLs, connections BEAST_EXPECT(numPeers >= 1); @@ -68,11 +67,7 @@ class DistributedValidators_test : public beast::unit_test::suite HeartbeatTimer heart(sim.scheduler); // txs, start/stop/step, target - auto peerSelector = makeSelector( - peers.begin(), - peers.end(), - std::vector(numPeers, 1.), - sim.rng); + auto peerSelector = makeSelector(peers.begin(), peers.end(), std::vector(numPeers, 1.), sim.rng); auto txSubmitter = makeSubmitter( ConstantDistribution{rate.inv()}, sim.scheduler.now() + quiet, @@ -90,11 +85,9 @@ class DistributedValidators_test : public beast::unit_test::suite log << std::right; log << "| Peers: " << std::setw(2) << peers.size(); - log << " | Duration: " << std::setw(6) - << duration_cast(simDuration).count() << " ms"; + log << " | Duration: " << std::setw(6) << duration_cast(simDuration).count() << " ms"; log << " | Branches: " << std::setw(1) << sim.branches(); - log << " | Synchronized: " << std::setw(1) - << (sim.synchronized() ? "Y" : "N"); + log << " | Synchronized: " << std::setw(1) << (sim.synchronized() ? "Y" : "N"); log << " |" << std::endl; txCollector.report(simDuration, log, true); @@ -124,8 +117,7 @@ class DistributedValidators_test : public beast::unit_test::suite ledgerLog(prefix + "_ledger.csv", std::ofstream::app); // title - log << prefix << "(" << numPeers << "," << delay.count() << ")" - << std::endl; + log << prefix << "(" << numPeers << "," << delay.count() << ")" << std::endl; // number of peers, UNLs, connections int const numCNLs = std::max(int(1.00 * numPeers), 1); @@ -133,9 +125,7 @@ class DistributedValidators_test : public beast::unit_test::suite int const maxCNLSize = std::max(int(0.50 * numCNLs), 1); BEAST_EXPECT(numPeers >= 1); BEAST_EXPECT(numCNLs >= 1); - BEAST_EXPECT( - 1 <= minCNLSize && minCNLSize <= maxCNLSize && - maxCNLSize <= numPeers); + BEAST_EXPECT(1 <= minCNLSize && minCNLSize <= maxCNLSize && maxCNLSize <= numPeers); Sim sim; PeerGroup peers = sim.createGroup(numPeers); @@ -144,15 +134,9 @@ class DistributedValidators_test : public beast::unit_test::suite peers.trust(peers); // scale-free connect graph with fixed delay - std::vector const ranks = - sample(peers.size(), PowerLawDistribution{1, 3}, sim.rng); + std::vector const ranks = sample(peers.size(), PowerLawDistribution{1, 3}, sim.rng); randomRankedConnect( - peers, - ranks, - numCNLs, - std::uniform_int_distribution<>{minCNLSize, maxCNLSize}, - sim.rng, - delay); + peers, ranks, numCNLs, std::uniform_int_distribution<>{minCNLSize, maxCNLSize}, sim.rng, delay); // Initialize collectors to track statistics to report TxCollector txCollector; @@ -172,11 +156,7 @@ class DistributedValidators_test : public beast::unit_test::suite HeartbeatTimer heart(sim.scheduler); // txs, start/stop/step, target - auto peerSelector = makeSelector( - peers.begin(), - peers.end(), - std::vector(numPeers, 1.), - sim.rng); + auto peerSelector = makeSelector(peers.begin(), peers.end(), std::vector(numPeers, 1.), sim.rng); auto txSubmitter = makeSubmitter( ConstantDistribution{rate.inv()}, sim.scheduler.now() + quiet, @@ -194,11 +174,9 @@ class DistributedValidators_test : public beast::unit_test::suite log << std::right; log << "| Peers: " << std::setw(2) << peers.size(); - log << " | Duration: " << std::setw(6) - << duration_cast(simDuration).count() << " ms"; + log << " | Duration: " << std::setw(6) << duration_cast(simDuration).count() << " ms"; log << " | Branches: " << std::setw(1) << sim.branches(); - log << " | Synchronized: " << std::setw(1) - << (sim.synchronized() ? "Y" : "N"); + log << " | Synchronized: " << std::setw(1) << (sim.synchronized() ? "Y" : "N"); log << " |" << std::endl; txCollector.report(simDuration, log, true); @@ -225,8 +203,7 @@ class DistributedValidators_test : public beast::unit_test::suite std::chrono::milliseconds const delay(delayCount); - log << "DistributedValidators: 1 to " << maxNumValidators << " Peers" - << std::endl; + log << "DistributedValidators: 1 to " << maxNumValidators << " Peers" << std::endl; /** * Simulate with N = 1 to N diff --git a/src/test/consensus/LedgerTiming_test.cpp b/src/test/consensus/LedgerTiming_test.cpp index 0ec3563c79..ac00cd1f3a 100644 --- a/src/test/consensus/LedgerTiming_test.cpp +++ b/src/test/consensus/LedgerTiming_test.cpp @@ -26,8 +26,7 @@ class LedgerTiming_test : public beast::unit_test::suite std::uint32_t round = 0; do { - nextCloseResolution = getNextLedgerTimeResolution( - closeResolution, previousAgree, ++round); + nextCloseResolution = getNextLedgerTimeResolution(closeResolution, previousAgree, ++round); if (nextCloseResolution < closeResolution) ++res.decrease; else if (nextCloseResolution > closeResolution) diff --git a/src/test/consensus/NegativeUNL_test.cpp b/src/test/consensus/NegativeUNL_test.cpp index 535aec03bf..9e77f158a3 100644 --- a/src/test/consensus/NegativeUNL_test.cpp +++ b/src/test/consensus/NegativeUNL_test.cpp @@ -34,11 +34,7 @@ namespace test { * @return true if meet all three expectation */ bool -negUnlSizeTest( - std::shared_ptr const& l, - size_t size, - bool hasToDisable, - bool hasToReEnable); +negUnlSizeTest(std::shared_ptr const& l, size_t size, bool hasToDisable, bool hasToReEnable); /** * Try to apply a ttUNL_MODIFY Tx, and test the apply result @@ -62,9 +58,7 @@ applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass); * @return true if meet the expectation */ bool -VerifyPubKeyAndSeq( - std::shared_ptr const& l, - hash_map nUnlLedgerSeq); +VerifyPubKeyAndSeq(std::shared_ptr const& l, hash_map nUnlLedgerSeq); /** * Count the number of Tx in a TxSet @@ -211,10 +205,7 @@ class NegativeUNL_test : public beast::unit_test::suite std::vector publicKeys = createPublicKeys(3); // genesis ledger auto l = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); // Record the public keys and ledger sequences of expected negative UNL // validators when we build the ledger history @@ -222,8 +213,7 @@ class NegativeUNL_test : public beast::unit_test::suite { //(1) the ledger after genesis, not a flag ledger - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]); auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]); @@ -240,8 +230,7 @@ class NegativeUNL_test : public beast::unit_test::suite // generate more ledgers for (auto i = 0; i < 256 - 2; ++i) { - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); } BEAST_EXPECT(l->isFlagLedger()); l->updateNegativeUNL(); @@ -276,8 +265,7 @@ class NegativeUNL_test : public beast::unit_test::suite BEAST_EXPECT(good_size); if (good_size) BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]); - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); } BEAST_EXPECT(l->isFlagLedger()); l->updateNegativeUNL(); @@ -329,8 +317,7 @@ class NegativeUNL_test : public beast::unit_test::suite BEAST_EXPECT(l->validatorToDisable() == publicKeys[1]); BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]); } - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); } BEAST_EXPECT(l->isFlagLedger()); l->updateNegativeUNL(); @@ -372,8 +359,7 @@ class NegativeUNL_test : public beast::unit_test::suite BEAST_EXPECT(l->negativeUNL().count(publicKeys[1])); BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]); } - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); } BEAST_EXPECT(l->isFlagLedger()); l->updateNegativeUNL(); @@ -422,8 +408,7 @@ class NegativeUNL_test : public beast::unit_test::suite BEAST_EXPECT(l->negativeUNL().count(publicKeys[1])); BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]); } - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); } BEAST_EXPECT(l->isFlagLedger()); l->updateNegativeUNL(); @@ -465,8 +450,7 @@ class NegativeUNL_test : public beast::unit_test::suite BEAST_EXPECT(l->negativeUNL().count(publicKeys[1])); BEAST_EXPECT(l->validatorToReEnable() == publicKeys[1]); } - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); } BEAST_EXPECT(l->isFlagLedger()); l->updateNegativeUNL(); @@ -480,8 +464,7 @@ class NegativeUNL_test : public beast::unit_test::suite for (auto i = 0; i < 256; ++i) { BEAST_EXPECT(negUnlSizeTest(l, 0, false, false)); - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); } BEAST_EXPECT(l->isFlagLedger()); l->updateNegativeUNL(); @@ -523,9 +506,7 @@ struct NetworkHistory }; NetworkHistory(beast::unit_test::suite& suite, Parameter const& p) - : env(suite, jtx::testable_amendments()) - , param(p) - , validations(env.app().getValidations()) + : env(suite, jtx::testable_amendments()), param(p), validations(env.app().getValidations()) { createNodes(); if (!param.numLedgers) @@ -555,10 +536,7 @@ struct NetworkHistory { static uint256 fake_amendment; // So we have different genesis ledgers auto l = std::make_shared( - create_genesis, - env.app().config(), - std::vector{fake_amendment++}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{fake_amendment++}, env.app().getNodeFamily()); history.push_back(l); // When putting validators into the negative UNL, we start with @@ -566,8 +544,7 @@ struct NetworkHistory int nidx = 0; while (l->seq() <= param.numLedgers) { - l = std::make_shared( - *l, env.app().timeKeeper().closeTime()); + l = std::make_shared(*l, env.app().timeKeeper().closeTime()); history.push_back(l); if (l->isFlagLedger()) @@ -601,8 +578,7 @@ struct NetworkHistory } l->updateSkipList(); } - return negUnlSizeTest( - l, param.negUNLSize, param.hasToDisable, param.hasToReEnable); + return negUnlSizeTest(l, param.negUNLSize, param.hasToDisable, param.hasToReEnable); } /** @@ -616,11 +592,7 @@ struct NetworkHistory { static auto keyPair = randomKeyPair(KeyType::secp256k1); return std::make_shared( - env.app().timeKeeper().now(), - keyPair.first, - keyPair.second, - v, - [&](STValidation& v) { + env.app().timeKeeper().now(), keyPair.first, keyPair.second, v, [&](STValidation& v) { v.setFieldH256(sfLedgerHash, ledger->header().hash); v.setFieldU32(sfLedgerSequence, ledger->seq()); v.setFlag(vfFullValidation); @@ -688,18 +660,12 @@ auto defaultPreVote = [](NegativeUNLVote& vote) {}; */ template bool -voteAndCheck( - NetworkHistory& history, - NodeID const& myId, - std::size_t expect, - PreVote const& pre = defaultPreVote) +voteAndCheck(NetworkHistory& history, NodeID const& myId, std::size_t expect, PreVote const& pre = defaultPreVote) { NegativeUNLVote vote(myId, history.env.journal); pre(vote); - auto txSet = std::make_shared( - SHAMapType::TRANSACTION, history.env.app().getNodeFamily()); - vote.doVoting( - history.lastLedger(), history.UNLKeySet, history.validations, txSet); + auto txSet = std::make_shared(SHAMapType::TRANSACTION, history.env.app().getNodeFamily()); + vote.doVoting(history.lastLedger(), history.UNLKeySet, history.validations, txSet); return countTx(txSet) == expect; } @@ -718,12 +684,9 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite NegativeUNLVote vote(myId, env.journal); // one add, one remove - auto txSet = std::make_shared( - SHAMapType::TRANSACTION, env.app().getNodeFamily()); - PublicKey toDisableKey( - derivePublicKey(KeyType::ed25519, randomSecretKey())); - PublicKey toReEnableKey( - derivePublicKey(KeyType::ed25519, randomSecretKey())); + auto txSet = std::make_shared(SHAMapType::TRANSACTION, env.app().getNodeFamily()); + PublicKey toDisableKey(derivePublicKey(KeyType::ed25519, randomSecretKey())); + PublicKey toReEnableKey(derivePublicKey(KeyType::ed25519, randomSecretKey())); LedgerIndex seq(1234); BEAST_EXPECT(countTx(txSet) == 0); vote.addTx(seq, toDisableKey, NegativeUNLVote::ToDisable, txSet); @@ -777,12 +740,8 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite BEAST_EXPECT(history.goodHistory); if (history.goodHistory) { - NegativeUNLVote vote( - history.UNLNodeIDs[3], history.env.journal); - BEAST_EXPECT(!vote.buildScoreTable( - history.lastLedger(), - history.UNLNodeIDSet, - history.validations)); + NegativeUNLVote vote(history.UNLNodeIDs[3], history.env.journal); + BEAST_EXPECT(!vote.buildScoreTable(history.lastLedger(), history.UNLNodeIDSet, history.validations)); } } @@ -792,12 +751,8 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite BEAST_EXPECT(history.goodHistory); if (history.goodHistory) { - NegativeUNLVote vote( - history.UNLNodeIDs[3], history.env.journal); - BEAST_EXPECT(!vote.buildScoreTable( - history.lastLedger(), - history.UNLNodeIDSet, - history.validations)); + NegativeUNLVote vote(history.UNLNodeIDs[3], history.env.journal); + BEAST_EXPECT(!vote.buildScoreTable(history.lastLedger(), history.UNLNodeIDSet, history.validations)); } } @@ -809,18 +764,12 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite { NodeID myId = history.UNLNodeIDs[3]; history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { + [&](std::shared_ptr const& l, std::size_t idx) -> bool { // skip half my validations. - return !( - history.UNLNodeIDs[idx] == myId && - l->seq() % 2 == 0); + return !(history.UNLNodeIDs[idx] == myId && l->seq() % 2 == 0); }); NegativeUNLVote vote(myId, history.env.journal); - BEAST_EXPECT(!vote.buildScoreTable( - history.lastLedger(), - history.UNLNodeIDSet, - history.validations)); + BEAST_EXPECT(!vote.buildScoreTable(history.lastLedger(), history.UNLNodeIDSet, history.validations)); } } @@ -831,8 +780,7 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite // We need two chains for these tests bool wrongChainSuccess = history.goodHistory; BEAST_EXPECT(wrongChainSuccess); - NetworkHistory::LedgerHistory wrongChain = - std::move(history.history); + NetworkHistory::LedgerHistory wrongChain = std::move(history.history); // Create a new chain and use it as the one that majority of nodes // follow history.createLedgerHistory(); @@ -843,8 +791,7 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite NodeID myId = history.UNLNodeIDs[3]; NodeID badNode = history.UNLNodeIDs[4]; history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { + [&](std::shared_ptr const& l, std::size_t idx) -> bool { // everyone but me return !(history.UNLNodeIDs[idx] == myId); }); @@ -863,10 +810,7 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite // local node still on wrong chain, can build a scoreTable, // but all other nodes' scores are zero - auto scoreTable = vote.buildScoreTable( - wrongChain.back(), - history.UNLNodeIDSet, - history.validations); + auto scoreTable = vote.buildScoreTable(wrongChain.back(), history.UNLNodeIDSet, history.validations); BEAST_EXPECT(scoreTable); if (scoreTable) { @@ -881,10 +825,7 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite // if local node switched to right history, but cannot build // scoreTable because not enough local validations - BEAST_EXPECT(!vote.buildScoreTable( - history.lastLedger(), - history.UNLNodeIDSet, - history.validations)); + BEAST_EXPECT(!vote.buildScoreTable(history.lastLedger(), history.UNLNodeIDSet, history.validations)); } } @@ -895,14 +836,9 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { return true; }); - NegativeUNLVote vote( - history.UNLNodeIDs[3], history.env.journal); - auto scoreTable = vote.buildScoreTable( - history.lastLedger(), - history.UNLNodeIDSet, - history.validations); + [&](std::shared_ptr const& l, std::size_t idx) -> bool { return true; }); + NegativeUNLVote vote(history.UNLNodeIDs[3], history.env.journal); + auto scoreTable = vote.buildScoreTable(history.lastLedger(), history.UNLNodeIDSet, history.validations); BEAST_EXPECT(scoreTable); if (scoreTable) { @@ -937,8 +873,7 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite std::size_t numDisable, std::size_t numReEnable) { - auto [disableCandidates, reEnableCandidates] = - vote.findAllCandidates(unl, negUnl, scoreTable); + auto [disableCandidates, reEnableCandidates] = vote.findAllCandidates(unl, negUnl, scoreTable); bool rightDisable = disableCandidates.size() == numDisable; bool rightReEnable = reEnableCandidates.size() == numReEnable; return rightDisable && rightReEnable; @@ -979,44 +914,36 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite { // all good scores - BEAST_EXPECT(checkCandidateSizes( - vote, history.UNLNodeIDSet, negUnl_012, goodScoreTable, 0, 3)); + BEAST_EXPECT(checkCandidateSizes(vote, history.UNLNodeIDSet, negUnl_012, goodScoreTable, 0, 3)); } { // all bad scores hash_map scoreTable; for (auto& n : history.UNLNodeIDs) scoreTable[n] = NegativeUNLVote::negativeUNLLowWaterMark - 1; - BEAST_EXPECT(checkCandidateSizes( - vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 35 - 3, 0)); + BEAST_EXPECT(checkCandidateSizes(vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 35 - 3, 0)); } { // all between watermarks hash_map scoreTable; for (auto& n : history.UNLNodeIDs) scoreTable[n] = NegativeUNLVote::negativeUNLLowWaterMark + 1; - BEAST_EXPECT(checkCandidateSizes( - vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 0, 0)); + BEAST_EXPECT(checkCandidateSizes(vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 0, 0)); } { // 2 good scorers in negUnl auto scoreTable = goodScoreTable; - scoreTable[*negUnl_012.begin()] = - NegativeUNLVote::negativeUNLLowWaterMark + 1; - BEAST_EXPECT(checkCandidateSizes( - vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 0, 2)); + scoreTable[*negUnl_012.begin()] = NegativeUNLVote::negativeUNLLowWaterMark + 1; + BEAST_EXPECT(checkCandidateSizes(vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 0, 2)); } { // 2 bad scorers not in negUnl auto scoreTable = goodScoreTable; - scoreTable[history.UNLNodeIDs[11]] = - NegativeUNLVote::negativeUNLLowWaterMark - 1; - scoreTable[history.UNLNodeIDs[12]] = - NegativeUNLVote::negativeUNLLowWaterMark - 1; - BEAST_EXPECT(checkCandidateSizes( - vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 2, 3)); + scoreTable[history.UNLNodeIDs[11]] = NegativeUNLVote::negativeUNLLowWaterMark - 1; + scoreTable[history.UNLNodeIDs[12]] = NegativeUNLVote::negativeUNLLowWaterMark - 1; + BEAST_EXPECT(checkCandidateSizes(vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 2, 3)); } { @@ -1025,8 +952,7 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite hash_set UNL_temp = history.UNLNodeIDSet; UNL_temp.erase(history.UNLNodeIDs[0]); UNL_temp.erase(history.UNLNodeIDs[1]); - BEAST_EXPECT(checkCandidateSizes( - vote, UNL_temp, negUnl_012, goodScoreTable, 0, 3)); + BEAST_EXPECT(checkCandidateSizes(vote, UNL_temp, negUnl_012, goodScoreTable, 0, 3)); } { @@ -1034,13 +960,11 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite auto scoreTable = goodScoreTable; scoreTable.erase(history.UNLNodeIDs[0]); scoreTable.erase(history.UNLNodeIDs[1]); - scoreTable[history.UNLNodeIDs[2]] = - NegativeUNLVote::negativeUNLLowWaterMark + 1; + scoreTable[history.UNLNodeIDs[2]] = NegativeUNLVote::negativeUNLLowWaterMark + 1; hash_set UNL_temp = history.UNLNodeIDSet; UNL_temp.erase(history.UNLNodeIDs[0]); UNL_temp.erase(history.UNLNodeIDs[1]); - BEAST_EXPECT(checkCandidateSizes( - vote, UNL_temp, negUnl_012, scoreTable, 0, 2)); + BEAST_EXPECT(checkCandidateSizes(vote, UNL_temp, negUnl_012, scoreTable, 0, 2)); } { @@ -1055,33 +979,27 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite { // 2 new validators have good scores, already in negUnl auto scoreTable = goodScoreTable; - scoreTable[new_1] = - NegativeUNLVote::negativeUNLHighWaterMark + 1; - scoreTable[new_2] = - NegativeUNLVote::negativeUNLHighWaterMark + 1; + scoreTable[new_1] = NegativeUNLVote::negativeUNLHighWaterMark + 1; + scoreTable[new_2] = NegativeUNLVote::negativeUNLHighWaterMark + 1; hash_set negUnl_temp = negUnl_012; negUnl_temp.insert(new_1); negUnl_temp.insert(new_2); - BEAST_EXPECT(checkCandidateSizes( - vote, UNL_temp, negUnl_temp, scoreTable, 0, 3 + 2)); + BEAST_EXPECT(checkCandidateSizes(vote, UNL_temp, negUnl_temp, scoreTable, 0, 3 + 2)); } { // 2 new validators have bad scores, not in negUnl auto scoreTable = goodScoreTable; scoreTable[new_1] = 0; scoreTable[new_2] = 0; - BEAST_EXPECT(checkCandidateSizes( - vote, UNL_temp, negUnl_012, scoreTable, 0, 3)); + BEAST_EXPECT(checkCandidateSizes(vote, UNL_temp, negUnl_012, scoreTable, 0, 3)); } { // expired the new validators have bad scores, not in negUnl - vote.purgeNewValidators( - 256 + NegativeUNLVote::newValidatorDisableSkip + 1); + vote.purgeNewValidators(256 + NegativeUNLVote::newValidatorDisableSkip + 1); auto scoreTable = goodScoreTable; scoreTable[new_1] = 0; scoreTable[new_2] = 0; - BEAST_EXPECT(checkCandidateSizes( - vote, UNL_temp, negUnl_012, scoreTable, 2, 3)); + BEAST_EXPECT(checkCandidateSizes(vote, UNL_temp, negUnl_012, scoreTable, 2, 3)); } } } @@ -1125,24 +1043,23 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite //== combination 1: { - auto fillScoreTable = - [&](std::uint32_t unl_size, - std::uint32_t nUnl_size, - std::uint32_t score, - hash_set& unl, - hash_set& negUnl, - hash_map& scoreTable) { - std::vector nodeIDs; - std::vector keys = createPublicKeys(unl_size); - for (auto const& k : keys) - { - nodeIDs.emplace_back(calcNodeID(k)); - unl.emplace(nodeIDs.back()); - scoreTable[nodeIDs.back()] = score; - } - for (std::uint32_t i = 0; i < nUnl_size; ++i) - negUnl.insert(nodeIDs[i]); - }; + auto fillScoreTable = [&](std::uint32_t unl_size, + std::uint32_t nUnl_size, + std::uint32_t score, + hash_set& unl, + hash_set& negUnl, + hash_map& scoreTable) { + std::vector nodeIDs; + std::vector keys = createPublicKeys(unl_size); + for (auto const& k : keys) + { + nodeIDs.emplace_back(calcNodeID(k)); + unl.emplace(nodeIDs.back()); + scoreTable[nodeIDs.back()] = score; + } + for (std::uint32_t i = 0; i < nUnl_size; ++i) + negUnl.insert(nodeIDs[i]); + }; for (auto us : unlSizes) { @@ -1153,8 +1070,7 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite hash_set unl; hash_set negUnl; hash_map scoreTable; - fillScoreTable( - us, us * np / 100, score, unl, negUnl, scoreTable); + fillScoreTable(us, us * np / 100, score, unl, negUnl, scoreTable); BEAST_EXPECT(unl.size() == us); BEAST_EXPECT(negUnl.size() == us * np / 100); BEAST_EXPECT(scoreTable.size() == us); @@ -1163,77 +1079,67 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite std::size_t toReEnable_expect = 0; if (np == 0) { - if (score < - NegativeUNLVote::negativeUNLLowWaterMark) + if (score < NegativeUNLVote::negativeUNLLowWaterMark) { toDisable_expect = us; } } else if (np == 50) { - if (score > - NegativeUNLVote::negativeUNLHighWaterMark) + if (score > NegativeUNLVote::negativeUNLHighWaterMark) { toReEnable_expect = us * np / 100; } } else { - if (score > - NegativeUNLVote::negativeUNLHighWaterMark) + if (score > NegativeUNLVote::negativeUNLHighWaterMark) { toReEnable_expect = us; } } - BEAST_EXPECT(checkCandidateSizes( - vote, - unl, - negUnl, - scoreTable, - toDisable_expect, - toReEnable_expect)); + BEAST_EXPECT( + checkCandidateSizes(vote, unl, negUnl, scoreTable, toDisable_expect, toReEnable_expect)); } } } //== combination 2: { - auto fillScoreTable = - [&](std::uint32_t unl_size, - std::uint32_t nUnl_percent, - hash_set& unl, - hash_set& negUnl, - hash_map& scoreTable) { - std::vector nodeIDs; - std::vector keys = - createPublicKeys(unl_size); - for (auto const& k : keys) - { - nodeIDs.emplace_back(calcNodeID(k)); - unl.emplace(nodeIDs.back()); - } + auto fillScoreTable = [&](std::uint32_t unl_size, + std::uint32_t nUnl_percent, + hash_set& unl, + hash_set& negUnl, + hash_map& scoreTable) { + std::vector nodeIDs; + std::vector keys = createPublicKeys(unl_size); + for (auto const& k : keys) + { + nodeIDs.emplace_back(calcNodeID(k)); + unl.emplace(nodeIDs.back()); + } - std::uint32_t nIdx = 0; - for (auto score : scores) - { - scoreTable[nodeIDs[nIdx++]] = score; - scoreTable[nodeIDs[nIdx++]] = score; - } - for (; nIdx < unl_size;) - { - scoreTable[nodeIDs[nIdx++]] = scores.back(); - } + std::uint32_t nIdx = 0; + for (auto score : scores) + { + scoreTable[nodeIDs[nIdx++]] = score; + scoreTable[nodeIDs[nIdx++]] = score; + } + for (; nIdx < unl_size;) + { + scoreTable[nodeIDs[nIdx++]] = scores.back(); + } - if (nUnl_percent == 100) - { - negUnl = unl; - } - else if (nUnl_percent == 50) - { - for (std::uint32_t i = 1; i < unl_size; i += 2) - negUnl.insert(nodeIDs[i]); - } - }; + if (nUnl_percent == 100) + { + negUnl = unl; + } + else if (nUnl_percent == 50) + { + for (std::uint32_t i = 1; i < unl_size; i += 2) + negUnl.insert(nodeIDs[i]); + } + }; for (auto us : unlSizes) { @@ -1262,13 +1168,8 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite { toReEnable_expect = negUnl.size() - 12; } - BEAST_EXPECT(checkCandidateSizes( - vote, - unl, - negUnl, - scoreTable, - toDisable_expect, - toReEnable_expect)); + BEAST_EXPECT( + checkCandidateSizes(vote, unl, negUnl, scoreTable, toDisable_expect, toReEnable_expect)); } } } @@ -1310,16 +1211,13 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite BEAST_EXPECT(vote.newValidators_[n2] == 3); } - vote.newValidators( - NegativeUNLVote::newValidatorDisableSkip, {n1, n2, n3}); + vote.newValidators(NegativeUNLVote::newValidatorDisableSkip, {n1, n2, n3}); BEAST_EXPECT(vote.newValidators_.size() == 3); if (vote.newValidators_.size() == 3) { BEAST_EXPECT(vote.newValidators_[n1] == 2); BEAST_EXPECT(vote.newValidators_[n2] == 3); - BEAST_EXPECT( - vote.newValidators_[n3] == - NegativeUNLVote::newValidatorDisableSkip); + BEAST_EXPECT(vote.newValidators_[n3] == NegativeUNLVote::newValidatorDisableSkip); } vote.purgeNewValidators(NegativeUNLVote::newValidatorDisableSkip + 2); @@ -1329,9 +1227,7 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite vote.purgeNewValidators(NegativeUNLVote::newValidatorDisableSkip + 4); BEAST_EXPECT(vote.newValidators_.size() == 1); BEAST_EXPECT(vote.newValidators_.begin()->first == n3); - BEAST_EXPECT( - vote.newValidators_.begin()->second == - NegativeUNLVote::newValidatorDisableSkip); + BEAST_EXPECT(vote.newValidators_.begin()->second == NegativeUNLVote::newValidatorDisableSkip); } void @@ -1371,15 +1267,13 @@ class NegativeUNLVoteScoreTable_test : public beast::unit_test::suite { for (std::uint32_t sp = 0; sp < 4; ++sp) { - NetworkHistory history = { - *this, {unlSize, 0, false, false, 256 + 2}}; + NetworkHistory history = {*this, {unlSize, 0, false, false, 256 + 2}}; BEAST_EXPECT(history.goodHistory); if (history.goodHistory) { NodeID myId = history.UNLNodeIDs[3]; history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { + [&](std::shared_ptr const& l, std::size_t idx) -> bool { std::size_t k; if (idx < 2) k = 0; @@ -1388,24 +1282,20 @@ class NegativeUNLVoteScoreTable_test : public beast::unit_test::suite else k = 2; - bool add_50 = - scorePattern[sp][k] == 50 && l->seq() % 2 == 0; + bool add_50 = scorePattern[sp][k] == 50 && l->seq() % 2 == 0; bool add_100 = scorePattern[sp][k] == 100; bool add_me = history.UNLNodeIDs[idx] == myId; return add_50 || add_100 || add_me; }); NegativeUNLVote vote(myId, history.env.journal); - auto scoreTable = vote.buildScoreTable( - history.lastLedger(), - history.UNLNodeIDSet, - history.validations); + auto scoreTable = + vote.buildScoreTable(history.lastLedger(), history.UNLNodeIDSet, history.validations); BEAST_EXPECT(scoreTable); if (scoreTable) { std::uint32_t i = 0; // looping unl - auto checkScores = [&](std::uint32_t score, - std::uint32_t k) -> bool { + auto checkScores = [&](std::uint32_t score, std::uint32_t k) -> bool { if (history.UNLNodeIDs[i] == myId) return score == 256; if (scorePattern[sp][k] == 0) @@ -1419,18 +1309,15 @@ class NegativeUNLVoteScoreTable_test : public beast::unit_test::suite }; for (; i < 2; ++i) { - BEAST_EXPECT(checkScores( - (*scoreTable)[history.UNLNodeIDs[i]], 0)); + BEAST_EXPECT(checkScores((*scoreTable)[history.UNLNodeIDs[i]], 0)); } for (; i < 4; ++i) { - BEAST_EXPECT(checkScores( - (*scoreTable)[history.UNLNodeIDs[i]], 1)); + BEAST_EXPECT(checkScores((*scoreTable)[history.UNLNodeIDs[i]], 1)); } for (; i < unlSize; ++i) { - BEAST_EXPECT(checkScores( - (*scoreTable)[history.UNLNodeIDs[i]], 2)); + BEAST_EXPECT(checkScores((*scoreTable)[history.UNLNodeIDs[i]], 2)); } } } @@ -1492,8 +1379,7 @@ class NegativeUNLVoteGoodScore_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { return true; }); + [&](std::shared_ptr const& l, std::size_t idx) -> bool { return true; }); BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 0)); } } @@ -1506,8 +1392,7 @@ class NegativeUNLVoteGoodScore_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { return true; }); + [&](std::shared_ptr const& l, std::size_t idx) -> bool { return true; }); BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 1)); } } @@ -1535,13 +1420,11 @@ class NegativeUNLVoteOffline_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { + [&](std::shared_ptr const& l, std::size_t idx) -> bool { // skip node 0 and node 1 return idx > 1; }); - BEAST_EXPECT( - voteAndCheck(history, history.UNLNodeIDs.back(), 1)); + BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs.back(), 1)); } } @@ -1552,19 +1435,14 @@ class NegativeUNLVoteOffline_test : public beast::unit_test::suite BEAST_EXPECT(history.goodHistory); if (history.goodHistory) { - NodeID n1 = - calcNodeID(*history.lastLedger()->negativeUNL().begin()); - NodeID n2 = - calcNodeID(*history.lastLedger()->validatorToDisable()); + NodeID n1 = calcNodeID(*history.lastLedger()->negativeUNL().begin()); + NodeID n2 = calcNodeID(*history.lastLedger()->validatorToDisable()); history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { + [&](std::shared_ptr const& l, std::size_t idx) -> bool { // skip node 0 and node 1 - return history.UNLNodeIDs[idx] != n1 && - history.UNLNodeIDs[idx] != n2; + return history.UNLNodeIDs[idx] != n1 && history.UNLNodeIDs[idx] != n2; }); - BEAST_EXPECT( - voteAndCheck(history, history.UNLNodeIDs.back(), 0)); + BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs.back(), 0)); } } } @@ -1591,13 +1469,11 @@ class NegativeUNLVoteMaxListed_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { + [&](std::shared_ptr const& l, std::size_t idx) -> bool { // skip node 0 ~ 10 return idx > 10; }); - BEAST_EXPECT( - voteAndCheck(history, history.UNLNodeIDs.back(), 0)); + BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs.back(), 0)); } } } @@ -1624,8 +1500,7 @@ class NegativeUNLVoteRetiredValidator_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { return idx > 1; }); + [&](std::shared_ptr const& l, std::size_t idx) -> bool { return idx > 1; }); BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 0)); } } @@ -1638,8 +1513,7 @@ class NegativeUNLVoteRetiredValidator_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { return idx > 1; }); + [&](std::shared_ptr const& l, std::size_t idx) -> bool { return idx > 1; }); BEAST_EXPECT(voteAndCheck(history, NodeID(0xdeadbeef), 0)); } } @@ -1652,16 +1526,11 @@ class NegativeUNLVoteRetiredValidator_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { return idx > 1; }); - BEAST_EXPECT(voteAndCheck( - history, - history.UNLNodeIDs.back(), - 1, - [&](NegativeUNLVote& vote) { - history.UNLKeySet.erase(history.UNLKeys[0]); - history.UNLKeySet.erase(history.UNLKeys[1]); - })); + [&](std::shared_ptr const& l, std::size_t idx) -> bool { return idx > 1; }); + BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs.back(), 1, [&](NegativeUNLVote& vote) { + history.UNLKeySet.erase(history.UNLKeys[0]); + history.UNLKeySet.erase(history.UNLKeys[1]); + })); } } } @@ -1688,60 +1557,39 @@ class NegativeUNLVoteNewValidator_test : public beast::unit_test::suite if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { return true; }); - BEAST_EXPECT(voteAndCheck( - history, - history.UNLNodeIDs[0], - 0, - [&](NegativeUNLVote& vote) { - auto extra_key_1 = - randomKeyPair(KeyType::ed25519).first; - auto extra_key_2 = - randomKeyPair(KeyType::ed25519).first; - history.UNLKeySet.insert(extra_key_1); - history.UNLKeySet.insert(extra_key_2); - hash_set nowTrusted; - nowTrusted.insert(calcNodeID(extra_key_1)); - nowTrusted.insert(calcNodeID(extra_key_2)); - vote.newValidators( - history.lastLedger()->seq(), nowTrusted); - })); + [&](std::shared_ptr const& l, std::size_t idx) -> bool { return true; }); + BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 0, [&](NegativeUNLVote& vote) { + auto extra_key_1 = randomKeyPair(KeyType::ed25519).first; + auto extra_key_2 = randomKeyPair(KeyType::ed25519).first; + history.UNLKeySet.insert(extra_key_1); + history.UNLKeySet.insert(extra_key_2); + hash_set nowTrusted; + nowTrusted.insert(calcNodeID(extra_key_1)); + nowTrusted.insert(calcNodeID(extra_key_2)); + vote.newValidators(history.lastLedger()->seq(), nowTrusted); + })); } } { //== 2 expired new validators have bad scores //-- txSet.size = 1 - NetworkHistory history = { - *this, - {21, - 0, - false, - false, - NegativeUNLVote::newValidatorDisableSkip * 2}}; + NetworkHistory history = {*this, {21, 0, false, false, NegativeUNLVote::newValidatorDisableSkip * 2}}; BEAST_EXPECT(history.goodHistory); if (history.goodHistory) { history.walkHistoryAndAddValidations( - [&](std::shared_ptr const& l, - std::size_t idx) -> bool { return true; }); - BEAST_EXPECT(voteAndCheck( - history, - history.UNLNodeIDs[0], - 1, - [&](NegativeUNLVote& vote) { - auto extra_key_1 = - randomKeyPair(KeyType::ed25519).first; - auto extra_key_2 = - randomKeyPair(KeyType::ed25519).first; - history.UNLKeySet.insert(extra_key_1); - history.UNLKeySet.insert(extra_key_2); - hash_set nowTrusted; - nowTrusted.insert(calcNodeID(extra_key_1)); - nowTrusted.insert(calcNodeID(extra_key_2)); - vote.newValidators(256, nowTrusted); - })); + [&](std::shared_ptr const& l, std::size_t idx) -> bool { return true; }); + BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 1, [&](NegativeUNLVote& vote) { + auto extra_key_1 = randomKeyPair(KeyType::ed25519).first; + auto extra_key_2 = randomKeyPair(KeyType::ed25519).first; + history.UNLKeySet.insert(extra_key_1); + history.UNLKeySet.insert(extra_key_2); + hash_set nowTrusted; + nowTrusted.insert(calcNodeID(extra_key_1)); + nowTrusted.insert(calcNodeID(extra_key_2)); + vote.newValidators(256, nowTrusted); + })); } } } @@ -1761,18 +1609,11 @@ class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite testcase("Filter Validations"); jtx::Env env(*this); auto l = std::make_shared( - create_genesis, - env.app().config(), - std::vector{}, - env.app().getNodeFamily()); + create_genesis, env.app().config(), std::vector{}, env.app().getNodeFamily()); auto createSTVal = [&](std::pair const& keys) { return std::make_shared( - env.app().timeKeeper().now(), - keys.first, - keys.second, - calcNodeID(keys.first), - [&](STValidation& v) { + env.app().timeKeeper().now(), keys.first, keys.second, calcNodeID(keys.first), [&](STValidation& v) { v.setFieldH256(sfLedgerHash, l->header().hash); v.setFieldU32(sfLedgerSequence, l->seq()); v.setFlag(vfFullValidation); @@ -1833,11 +1674,7 @@ BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus, xrpl); BEAST_DEFINE_TESTSUITE_PRIO(NegativeUNLVoteGoodScore, consensus, xrpl, 1); BEAST_DEFINE_TESTSUITE(NegativeUNLVoteOffline, consensus, xrpl); BEAST_DEFINE_TESTSUITE(NegativeUNLVoteMaxListed, consensus, xrpl); -BEAST_DEFINE_TESTSUITE_PRIO( - NegativeUNLVoteRetiredValidator, - consensus, - ripple, - 1); +BEAST_DEFINE_TESTSUITE_PRIO(NegativeUNLVoteRetiredValidator, consensus, xrpl, 1); BEAST_DEFINE_TESTSUITE(NegativeUNLVoteNewValidator, consensus, xrpl); BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus, xrpl); @@ -1845,17 +1682,11 @@ BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus, xrpl); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// bool -negUnlSizeTest( - std::shared_ptr const& l, - size_t size, - bool hasToDisable, - bool hasToReEnable) +negUnlSizeTest(std::shared_ptr const& l, size_t size, bool hasToDisable, bool hasToReEnable) { bool sameSize = l->negativeUNL().size() == size; - bool sameToDisable = - (l->validatorToDisable() != std::nullopt) == hasToDisable; - bool sameToReEnable = - (l->validatorToReEnable() != std::nullopt) == hasToReEnable; + bool sameToDisable = (l->validatorToDisable() != std::nullopt) == hasToDisable; + bool sameToReEnable = (l->validatorToReEnable() != std::nullopt) == hasToReEnable; return sameSize && sameToDisable && sameToReEnable; } @@ -1863,8 +1694,7 @@ negUnlSizeTest( bool applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass) { - auto const res = - apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal); + auto const res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal); if (pass) return res.ter == tesSUCCESS; else @@ -1872,9 +1702,7 @@ applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass) } bool -VerifyPubKeyAndSeq( - std::shared_ptr const& l, - hash_map nUnlLedgerSeq) +VerifyPubKeyAndSeq(std::shared_ptr const& l, hash_map nUnlLedgerSeq) { auto sle = l->read(keylet::negativeUNL()); if (!sle) @@ -1888,8 +1716,7 @@ VerifyPubKeyAndSeq( for (auto const& n : nUnlData) { - if (!n.isFieldPresent(sfFirstLedgerSequence) || - !n.isFieldPresent(sfPublicKey)) + if (!n.isFieldPresent(sfFirstLedgerSequence) || !n.isFieldPresent(sfPublicKey)) return false; auto seq = n.getFieldU32(sfFirstLedgerSequence); diff --git a/src/test/consensus/ScaleFreeSim_test.cpp b/src/test/consensus/ScaleFreeSim_test.cpp index dee4c77268..ae70ee9174 100644 --- a/src/test/consensus/ScaleFreeSim_test.cpp +++ b/src/test/consensus/ScaleFreeSim_test.cpp @@ -29,20 +29,13 @@ class ScaleFreeSim_test : public beast::unit_test::suite PeerGroup network = sim.createGroup(N); // generate trust ranks - std::vector const ranks = - sample(network.size(), PowerLawDistribution{1, 3}, sim.rng); + std::vector const ranks = sample(network.size(), PowerLawDistribution{1, 3}, sim.rng); // generate scale-free trust graph - randomRankedTrust( - network, - ranks, - numUNLs, - std::uniform_int_distribution<>{minUNLSize, maxUNLSize}, - sim.rng); + randomRankedTrust(network, ranks, numUNLs, std::uniform_int_distribution<>{minUNLSize, maxUNLSize}, sim.rng); // nodes with a trust line in either direction are network-connected - network.connectFromTrust( - round(0.2 * parms.ledgerGRANULARITY)); + network.connectFromTrust(round(0.2 * parms.ledgerGRANULARITY)); // Initialize collectors to track statistics to report TxCollector txCollector; @@ -62,8 +55,7 @@ class ScaleFreeSim_test : public beast::unit_test::suite Rate const rate{100, 1000ms}; // txs, start/stop/step, target - auto peerSelector = - makeSelector(network.begin(), network.end(), ranks, sim.rng); + auto peerSelector = makeSelector(network.begin(), network.end(), ranks, sim.rng); auto txSubmitter = makeSubmitter( ConstantDistribution{rate.inv()}, sim.scheduler.now() + quiet, @@ -82,12 +74,9 @@ class ScaleFreeSim_test : public beast::unit_test::suite // TODO: Clean up this formatting mess!! log << "Peers: " << network.size() << std::endl; - log << "Simulated Duration: " - << duration_cast(simDuration).count() << " ms" - << std::endl; + log << "Simulated Duration: " << duration_cast(simDuration).count() << " ms" << std::endl; log << "Branches: " << sim.branches() << std::endl; - log << "Synchronized: " << (sim.synchronized() ? "Y" : "N") - << std::endl; + log << "Synchronized: " << (sim.synchronized() ? "Y" : "N") << std::endl; log << std::endl; txCollector.report(simDuration, log); diff --git a/src/test/consensus/Validations_test.cpp b/src/test/consensus/Validations_test.cpp index 906817add0..34e0c23bad 100644 --- a/src/test/consensus/Validations_test.cpp +++ b/src/test/consensus/Validations_test.cpp @@ -25,8 +25,7 @@ class Validations_test : public beast::unit_test::suite // generated NetClock time to be well past its epoch to ensure // any subtractions are positive using namespace std::chrono; - return NetClock::time_point(duration_cast( - c.now().time_since_epoch() + 86400s)); + return NetClock::time_point(duration_cast(c.now().time_since_epoch() + 86400s)); } // Represents a node that can issue validations @@ -100,50 +99,28 @@ class Validations_test : public beast::unit_test::suite NetClock::duration seenOffset, bool full) const { - Validation v{ - id, - seq, - now() + signOffset, - now() + seenOffset, - currKey(), - nodeID_, - full, - loadFee_}; + Validation v{id, seq, now() + signOffset, now() + seenOffset, currKey(), nodeID_, full, loadFee_}; if (trusted_) v.setTrusted(); return v; } Validation - validate( - Ledger ledger, - NetClock::duration signOffset, - NetClock::duration seenOffset) const + validate(Ledger ledger, NetClock::duration signOffset, NetClock::duration seenOffset) const { - return validate( - ledger.id(), ledger.seq(), signOffset, seenOffset, true); + return validate(ledger.id(), ledger.seq(), signOffset, seenOffset, true); } Validation validate(Ledger ledger) const { - return validate( - ledger.id(), - ledger.seq(), - NetClock::duration{0}, - NetClock::duration{0}, - true); + return validate(ledger.id(), ledger.seq(), NetClock::duration{0}, NetClock::duration{0}, true); } Validation partial(Ledger ledger) const { - return validate( - ledger.id(), - ledger.seq(), - NetClock::duration{0}, - NetClock::duration{0}, - false); + return validate(ledger.id(), ledger.seq(), NetClock::duration{0}, NetClock::duration{0}, false); } }; @@ -267,16 +244,13 @@ class Validations_test : public beast::unit_test::suite harness.clock().advance(1s); - BEAST_EXPECT( - ValStatus::current == harness.add(n.validate(ledgerAB))); + BEAST_EXPECT(ValStatus::current == harness.add(n.validate(ledgerAB))); // Test the node changing signing key // Confirm old ledger on hand, but not new ledger - BEAST_EXPECT( - harness.vals().numTrustedForLedger(ledgerAB.id()) == 1); - BEAST_EXPECT( - harness.vals().numTrustedForLedger(ledgerABC.id()) == 0); + BEAST_EXPECT(harness.vals().numTrustedForLedger(ledgerAB.id()) == 1); + BEAST_EXPECT(harness.vals().numTrustedForLedger(ledgerABC.id()) == 0); // Rotate signing keys n.advanceKey(); @@ -284,20 +258,15 @@ class Validations_test : public beast::unit_test::suite harness.clock().advance(1s); // Cannot re-do the same full validation sequence - BEAST_EXPECT( - ValStatus::conflicting == harness.add(n.validate(ledgerAB))); + BEAST_EXPECT(ValStatus::conflicting == harness.add(n.validate(ledgerAB))); // Cannot send the same partial validation sequence - BEAST_EXPECT( - ValStatus::conflicting == harness.add(n.partial(ledgerAB))); + BEAST_EXPECT(ValStatus::conflicting == harness.add(n.partial(ledgerAB))); // Now trusts the newest ledger too harness.clock().advance(1s); - BEAST_EXPECT( - ValStatus::current == harness.add(n.validate(ledgerABC))); - BEAST_EXPECT( - harness.vals().numTrustedForLedger(ledgerAB.id()) == 1); - BEAST_EXPECT( - harness.vals().numTrustedForLedger(ledgerABC.id()) == 1); + BEAST_EXPECT(ValStatus::current == harness.add(n.validate(ledgerABC))); + BEAST_EXPECT(harness.vals().numTrustedForLedger(ledgerAB.id()) == 1); + BEAST_EXPECT(harness.vals().numTrustedForLedger(ledgerABC.id()) == 1); // Processing validations out of order should ignore the older // validation @@ -319,19 +288,14 @@ class Validations_test : public beast::unit_test::suite Node n = harness.makeNode(); // Establish a new current validation - BEAST_EXPECT( - ValStatus::current == harness.add(n.validate(ledgerA))); + BEAST_EXPECT(ValStatus::current == harness.add(n.validate(ledgerA))); // Process a validation that has "later" seq but early sign time - BEAST_EXPECT( - ValStatus::stale == - harness.add(n.validate(ledgerAB, -1s, -1s))); + BEAST_EXPECT(ValStatus::stale == harness.add(n.validate(ledgerAB, -1s, -1s))); // Process a validation that has a later seq and later sign // time - BEAST_EXPECT( - ValStatus::current == - harness.add(n.validate(ledgerABC, 1s, 1s))); + BEAST_EXPECT(ValStatus::current == harness.add(n.validate(ledgerABC, 1s, 1s))); } { @@ -340,19 +304,13 @@ class Validations_test : public beast::unit_test::suite Node n = harness.makeNode(); BEAST_EXPECT( - ValStatus::stale == - harness.add(n.validate( - ledgerA, -harness.parms().validationCURRENT_EARLY, 0s))); + ValStatus::stale == harness.add(n.validate(ledgerA, -harness.parms().validationCURRENT_EARLY, 0s))); BEAST_EXPECT( - ValStatus::stale == - harness.add(n.validate( - ledgerA, harness.parms().validationCURRENT_WALL, 0s))); + ValStatus::stale == harness.add(n.validate(ledgerA, harness.parms().validationCURRENT_WALL, 0s))); BEAST_EXPECT( - ValStatus::stale == - harness.add(n.validate( - ledgerA, 0s, harness.parms().validationCURRENT_LOCAL))); + ValStatus::stale == harness.add(n.validate(ledgerA, 0s, harness.parms().validationCURRENT_LOCAL))); } { @@ -377,8 +335,7 @@ class Validations_test : public beast::unit_test::suite // If we advance far enough for AB to expire, we can fully // validate or partially validate that sequence number again BEAST_EXPECT(ValStatus::conflicting == process(ledgerAZ)); - harness.clock().advance( - harness.parms().validationSET_EXPIRES + 1ms); + harness.clock().advance(harness.parms().validationSET_EXPIRES + 1ms); BEAST_EXPECT(ValStatus::current == process(ledgerAZ)); } } @@ -401,31 +358,23 @@ class Validations_test : public beast::unit_test::suite [&](TestValidations& vals) { vals.currentTrusted(); }, [&](TestValidations& vals) { vals.getCurrentNodeIDs(); }, [&](TestValidations& vals) { vals.getPreferred(genesisLedger); }, - [&](TestValidations& vals) { - vals.getNodesAfter(ledgerA, ledgerA.id()); - }}; + [&](TestValidations& vals) { vals.getNodesAfter(ledgerA, ledgerA.id()); }}; for (Trigger trigger : triggers) { TestHarness harness(h.oracle); Node n = harness.makeNode(); - BEAST_EXPECT( - ValStatus::current == harness.add(n.validate(ledgerAB))); + BEAST_EXPECT(ValStatus::current == harness.add(n.validate(ledgerAB))); trigger(harness.vals()); - BEAST_EXPECT( - harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 1); - BEAST_EXPECT( - harness.vals().getPreferred(genesisLedger) == - std::make_pair(ledgerAB.seq(), ledgerAB.id())); + BEAST_EXPECT(harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 1); + BEAST_EXPECT(harness.vals().getPreferred(genesisLedger) == std::make_pair(ledgerAB.seq(), ledgerAB.id())); harness.clock().advance(harness.parms().validationCURRENT_LOCAL); // trigger check for stale trigger(harness.vals()); - BEAST_EXPECT( - harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 0); - BEAST_EXPECT( - harness.vals().getPreferred(genesisLedger) == std::nullopt); + BEAST_EXPECT(harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 0); + BEAST_EXPECT(harness.vals().getPreferred(genesisLedger) == std::nullopt); } } @@ -446,8 +395,7 @@ class Validations_test : public beast::unit_test::suite Ledger ledgerAD = h["ad"]; TestHarness harness(h.oracle); - Node a = harness.makeNode(), b = harness.makeNode(), - c = harness.makeNode(), d = harness.makeNode(); + Node a = harness.makeNode(), b = harness.makeNode(), c = harness.makeNode(), d = harness.makeNode(); c.untrust(); // first round a,b,c agree, d has is partial @@ -457,8 +405,7 @@ class Validations_test : public beast::unit_test::suite BEAST_EXPECT(ValStatus::current == harness.add(d.partial(ledgerA))); for (Ledger const& ledger : {ledgerA, ledgerAB, ledgerABC, ledgerAD}) - BEAST_EXPECT( - harness.vals().getNodesAfter(ledger, ledger.id()) == 0); + BEAST_EXPECT(harness.vals().getNodesAfter(ledger, ledger.id()) == 0); harness.clock().advance(5s); @@ -468,18 +415,14 @@ class Validations_test : public beast::unit_test::suite BEAST_EXPECT(ValStatus::current == harness.add(d.partial(ledgerABC))); BEAST_EXPECT(harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 3); - BEAST_EXPECT( - harness.vals().getNodesAfter(ledgerAB, ledgerAB.id()) == 2); - BEAST_EXPECT( - harness.vals().getNodesAfter(ledgerABC, ledgerABC.id()) == 0); - BEAST_EXPECT( - harness.vals().getNodesAfter(ledgerAD, ledgerAD.id()) == 0); + BEAST_EXPECT(harness.vals().getNodesAfter(ledgerAB, ledgerAB.id()) == 2); + BEAST_EXPECT(harness.vals().getNodesAfter(ledgerABC, ledgerABC.id()) == 0); + BEAST_EXPECT(harness.vals().getNodesAfter(ledgerAD, ledgerAD.id()) == 0); // If given a ledger inconsistent with the id, is still able to check // using slower method BEAST_EXPECT(harness.vals().getNodesAfter(ledgerAD, ledgerA.id()) == 1); - BEAST_EXPECT( - harness.vals().getNodesAfter(ledgerAD, ledgerAB.id()) == 2); + BEAST_EXPECT(harness.vals().getNodesAfter(ledgerAD, ledgerAB.id()) == 2); } void @@ -502,22 +445,18 @@ class Validations_test : public beast::unit_test::suite // Only a is trusted BEAST_EXPECT(harness.vals().currentTrusted().size() == 1); - BEAST_EXPECT( - harness.vals().currentTrusted()[0].ledgerID() == ledgerA.id()); + BEAST_EXPECT(harness.vals().currentTrusted()[0].ledgerID() == ledgerA.id()); BEAST_EXPECT(harness.vals().currentTrusted()[0].seq() == ledgerA.seq()); harness.clock().advance(3s); for (auto const& node : {a, b}) - BEAST_EXPECT( - ValStatus::current == harness.add(node.validate(ledgerAC))); + BEAST_EXPECT(ValStatus::current == harness.add(node.validate(ledgerAC))); // New validation for a BEAST_EXPECT(harness.vals().currentTrusted().size() == 1); - BEAST_EXPECT( - harness.vals().currentTrusted()[0].ledgerID() == ledgerAC.id()); - BEAST_EXPECT( - harness.vals().currentTrusted()[0].seq() == ledgerAC.seq()); + BEAST_EXPECT(harness.vals().currentTrusted()[0].ledgerID() == ledgerAC.id()); + BEAST_EXPECT(harness.vals().currentTrusted()[0].seq() == ledgerAC.seq()); // Pass enough time for it to go stale harness.clock().advance(harness.parms().validationCURRENT_LOCAL); @@ -539,8 +478,7 @@ class Validations_test : public beast::unit_test::suite b.untrust(); for (auto const& node : {a, b}) - BEAST_EXPECT( - ValStatus::current == harness.add(node.validate(ledgerA))); + BEAST_EXPECT(ValStatus::current == harness.add(node.validate(ledgerA))); { hash_set const expectedKeys = {a.nodeID(), b.nodeID()}; @@ -554,8 +492,7 @@ class Validations_test : public beast::unit_test::suite b.advanceKey(); for (auto const& node : {a, b}) - BEAST_EXPECT( - ValStatus::current == harness.add(node.partial(ledgerAC))); + BEAST_EXPECT(ValStatus::current == harness.add(node.partial(ledgerAC))); { hash_set const expectedKeys = {a.nodeID(), b.nodeID()}; @@ -583,8 +520,7 @@ class Validations_test : public beast::unit_test::suite LedgerHistoryHelper h; TestHarness harness(h.oracle); - Node a = harness.makeNode(), b = harness.makeNode(), - c = harness.makeNode(), d = harness.makeNode(), + Node a = harness.makeNode(), b = harness.makeNode(), c = harness.makeNode(), d = harness.makeNode(), e = harness.makeNode(); c.untrust(); @@ -594,8 +530,7 @@ class Validations_test : public beast::unit_test::suite c.setLoadFee(12); e.setLoadFee(12); - hash_map, std::vector> - trustedValidations; + hash_map, std::vector> trustedValidations; //---------------------------------------------------------------------- // checkers @@ -610,12 +545,8 @@ class Validations_test : public beast::unit_test::suite auto const& seq = it.first.second; auto const& expectedValidations = it.second; - BEAST_EXPECT( - harness.vals().numTrustedForLedger(id) == - expectedValidations.size()); - BEAST_EXPECT( - sorted(harness.vals().getTrustedForLedger(id, seq)) == - sorted(expectedValidations)); + BEAST_EXPECT(harness.vals().numTrustedForLedger(id) == expectedValidations.size()); + BEAST_EXPECT(sorted(harness.vals().getTrustedForLedger(id, seq)) == sorted(expectedValidations)); std::uint32_t baseFee = 0; std::vector expectedFees; @@ -624,9 +555,7 @@ class Validations_test : public beast::unit_test::suite expectedFees.push_back(val.loadFee().value_or(baseFee)); } - BEAST_EXPECT( - sorted(harness.vals().fees(id, baseFee)) == - sorted(expectedFees)); + BEAST_EXPECT(sorted(harness.vals().fees(id, baseFee)) == sorted(expectedFees)); } }; @@ -644,8 +573,7 @@ class Validations_test : public beast::unit_test::suite auto const val = node.validate(ledgerA); BEAST_EXPECT(ValStatus::current == harness.add(val)); if (val.trusted()) - trustedValidations[{val.ledgerID(), val.seq()}].emplace_back( - val); + trustedValidations[{val.ledgerID(), val.seq()}].emplace_back(val); } // d disagrees { @@ -665,19 +593,16 @@ class Validations_test : public beast::unit_test::suite auto const val = node.validate(ledgerAC); BEAST_EXPECT(ValStatus::current == harness.add(val)); if (val.trusted()) - trustedValidations[{val.ledgerID(), val.seq()}].emplace_back( - val); + trustedValidations[{val.ledgerID(), val.seq()}].emplace_back(val); } // d now thinks ledger 1, but cannot re-issue a previously used seq // and attempting it should generate a conflict. { - BEAST_EXPECT( - ValStatus::conflicting == harness.add(d.partial(ledgerA))); + BEAST_EXPECT(ValStatus::conflicting == harness.add(d.partial(ledgerA))); } // e only issues partials { - BEAST_EXPECT( - ValStatus::current == harness.add(e.partial(ledgerAC))); + BEAST_EXPECT(ValStatus::current == harness.add(e.partial(ledgerAC))); } compare(); @@ -716,9 +641,7 @@ class Validations_test : public beast::unit_test::suite // change toKeep harness.vals().setSeqToKeep(ledgerB.seq() + one, ledgerB.seq() + two); // advance clock slowly - int const loops = harness.parms().validationSET_EXPIRES / - harness.parms().validationFRESHNESS + - 1; + int const loops = harness.parms().validationSET_EXPIRES / harness.parms().validationFRESHNESS + 1; for (int i = 0; i < loops; ++i) { harness.clock().advance(harness.parms().validationFRESHNESS); @@ -745,8 +668,7 @@ class Validations_test : public beast::unit_test::suite LedgerHistoryHelper h; TestHarness harness(h.oracle); - Node a = harness.makeNode(), b = harness.makeNode(), - c = harness.makeNode(); + Node a = harness.makeNode(), b = harness.makeNode(), c = harness.makeNode(); c.untrust(); Ledger ledgerA = h["a"]; @@ -776,8 +698,7 @@ class Validations_test : public beast::unit_test::suite LedgerHistoryHelper h; TestHarness harness(h.oracle); - Node a = harness.makeNode(), b = harness.makeNode(), - c = harness.makeNode(), d = harness.makeNode(); + Node a = harness.makeNode(), b = harness.makeNode(), c = harness.makeNode(), d = harness.makeNode(); c.untrust(); Ledger ledgerA = h["a"]; @@ -787,9 +708,7 @@ class Validations_test : public beast::unit_test::suite using Seq = Ledger::Seq; - auto pref = [](Ledger ledger) { - return std::make_pair(ledger.seq(), ledger.id()); - }; + auto pref = [](Ledger ledger) { return std::make_pair(ledger.seq(), ledger.id()); }; // Empty (no ledgers) BEAST_EXPECT(harness.vals().getPreferred(ledgerA) == std::nullopt); @@ -800,8 +719,7 @@ class Validations_test : public beast::unit_test::suite BEAST_EXPECT(harness.vals().getPreferred(ledgerB) == pref(ledgerB)); // Minimum valid sequence - BEAST_EXPECT( - harness.vals().getPreferred(ledgerA, Seq{10}) == ledgerA.id()); + BEAST_EXPECT(harness.vals().getPreferred(ledgerA, Seq{10}) == ledgerA.id()); // Untrusted doesn't impact preferred ledger // (ledgerB has tie-break over ledgerA) @@ -820,8 +738,7 @@ class Validations_test : public beast::unit_test::suite // Parent of preferred-> stick with ledger for (auto const& node : {a, b, c, d}) - BEAST_EXPECT( - ValStatus::current == harness.add(node.validate(ledgerAC))); + BEAST_EXPECT(ValStatus::current == harness.add(node.validate(ledgerAC))); // Parent of preferred stays put BEAST_EXPECT(harness.vals().getPreferred(ledgerA) == pref(ledgerA)); // Earlier different chain, switch @@ -832,11 +749,9 @@ class Validations_test : public beast::unit_test::suite // Any later grandchild or different chain is preferred harness.clock().advance(5s); for (auto const& node : {a, b, c, d}) - BEAST_EXPECT( - ValStatus::current == harness.add(node.validate(ledgerACD))); + BEAST_EXPECT(ValStatus::current == harness.add(node.validate(ledgerACD))); for (auto const& ledger : {ledgerA, ledgerB, ledgerACD}) - BEAST_EXPECT( - harness.vals().getPreferred(ledger) == pref(ledgerACD)); + BEAST_EXPECT(harness.vals().getPreferred(ledger) == pref(ledgerACD)); } void @@ -859,44 +774,30 @@ class Validations_test : public beast::unit_test::suite hash_map peerCounts; // No trusted validations or counts sticks with current ledger - BEAST_EXPECT( - harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) == - ledgerA.id()); + BEAST_EXPECT(harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) == ledgerA.id()); ++peerCounts[ledgerB.id()]; // No trusted validations, rely on peer counts - BEAST_EXPECT( - harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) == - ledgerB.id()); + BEAST_EXPECT(harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) == ledgerB.id()); ++peerCounts[ledgerC.id()]; // No trusted validations, tied peers goes with larger ID BEAST_EXPECT(ledgerC.id() > ledgerB.id()); - BEAST_EXPECT( - harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) == - ledgerC.id()); + BEAST_EXPECT(harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) == ledgerC.id()); peerCounts[ledgerC.id()] += 1000; // Single trusted always wins over peer counts BEAST_EXPECT(ValStatus::current == harness.add(a.validate(ledgerA))); - BEAST_EXPECT( - harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) == - ledgerA.id()); - BEAST_EXPECT( - harness.vals().getPreferredLCL(ledgerB, Seq{0}, peerCounts) == - ledgerA.id()); - BEAST_EXPECT( - harness.vals().getPreferredLCL(ledgerC, Seq{0}, peerCounts) == - ledgerA.id()); + BEAST_EXPECT(harness.vals().getPreferredLCL(ledgerA, Seq{0}, peerCounts) == ledgerA.id()); + BEAST_EXPECT(harness.vals().getPreferredLCL(ledgerB, Seq{0}, peerCounts) == ledgerA.id()); + BEAST_EXPECT(harness.vals().getPreferredLCL(ledgerC, Seq{0}, peerCounts) == ledgerA.id()); // Stick with current ledger if trusted validation ledger has too old // of a sequence - BEAST_EXPECT( - harness.vals().getPreferredLCL(ledgerB, Seq{2}, peerCounts) == - ledgerB.id()); + BEAST_EXPECT(harness.vals().getPreferredLCL(ledgerB, Seq{2}, peerCounts) == ledgerB.id()); } void @@ -923,18 +824,12 @@ class Validations_test : public beast::unit_test::suite BEAST_EXPECT(harness.vals().getNodesAfter(genesisLedger, ID{0}) == 0); // Initial preferred branch falls back to the ledger we are trying to // acquire - BEAST_EXPECT( - harness.vals().getPreferred(genesisLedger) == - std::make_pair(Seq{2}, ID{2})); + BEAST_EXPECT(harness.vals().getPreferred(genesisLedger) == std::make_pair(Seq{2}, ID{2})); // After adding another unavailable validation, the preferred ledger // breaks ties via higher ID - BEAST_EXPECT( - ValStatus::current == - harness.add(b.validate(ID{3}, Seq{2}, 0s, 0s, true))); - BEAST_EXPECT( - harness.vals().getPreferred(genesisLedger) == - std::make_pair(Seq{2}, ID{3})); + BEAST_EXPECT(ValStatus::current == harness.add(b.validate(ID{3}, Seq{2}, 0s, 0s, true))); + BEAST_EXPECT(harness.vals().getPreferred(genesisLedger) == std::make_pair(Seq{2}, ID{3})); // Create the ledger Ledger ledgerAB = h["ab"]; @@ -946,26 +841,20 @@ class Validations_test : public beast::unit_test::suite Validation val2 = a.validate(ID{4}, Seq{4}, 0s, 0s, true); BEAST_EXPECT(ValStatus::current == harness.add(val2)); BEAST_EXPECT(harness.vals().numTrustedForLedger(ID{4}) == 1); - BEAST_EXPECT( - harness.vals().getPreferred(genesisLedger) == - std::make_pair(ledgerAB.seq(), ledgerAB.id())); + BEAST_EXPECT(harness.vals().getPreferred(genesisLedger) == std::make_pair(ledgerAB.seq(), ledgerAB.id())); // Another node requesting that ledger still doesn't change things Validation val3 = b.validate(ID{4}, Seq{4}, 0s, 0s, true); BEAST_EXPECT(ValStatus::current == harness.add(val3)); BEAST_EXPECT(harness.vals().numTrustedForLedger(ID{4}) == 2); - BEAST_EXPECT( - harness.vals().getPreferred(genesisLedger) == - std::make_pair(ledgerAB.seq(), ledgerAB.id())); + BEAST_EXPECT(harness.vals().getPreferred(genesisLedger) == std::make_pair(ledgerAB.seq(), ledgerAB.id())); // Switch to validation that is available harness.clock().advance(5s); Ledger ledgerABCDE = h["abcde"]; BEAST_EXPECT(ValStatus::current == harness.add(a.partial(ledgerABCDE))); BEAST_EXPECT(ValStatus::current == harness.add(b.partial(ledgerABCDE))); - BEAST_EXPECT( - harness.vals().getPreferred(genesisLedger) == - std::make_pair(ledgerABCDE.seq(), ledgerABCDE.id())); + BEAST_EXPECT(harness.vals().getPreferred(genesisLedger) == std::make_pair(ledgerABCDE.seq(), ledgerABCDE.id())); } void @@ -1013,31 +902,20 @@ class Validations_test : public beast::unit_test::suite testcase("TrustChanged"); using namespace std::chrono; - auto checker = [this]( - TestValidations& vals, - hash_set const& listed, - std::vector const& trustedVals) { - Ledger::ID testID = trustedVals.empty() ? this->genesisLedger.id() - : trustedVals[0].ledgerID(); - Ledger::Seq testSeq = trustedVals.empty() - ? this->genesisLedger.seq() - : trustedVals[0].seq(); - BEAST_EXPECT(vals.currentTrusted() == trustedVals); - BEAST_EXPECT(vals.getCurrentNodeIDs() == listed); - BEAST_EXPECT( - vals.getNodesAfter(this->genesisLedger, genesisLedger.id()) == - trustedVals.size()); - if (trustedVals.empty()) - BEAST_EXPECT( - vals.getPreferred(this->genesisLedger) == std::nullopt); - else - BEAST_EXPECT( - vals.getPreferred(this->genesisLedger)->second == testID); - BEAST_EXPECT( - vals.getTrustedForLedger(testID, testSeq) == trustedVals); - BEAST_EXPECT( - vals.numTrustedForLedger(testID) == trustedVals.size()); - }; + auto checker = + [this](TestValidations& vals, hash_set const& listed, std::vector const& trustedVals) { + Ledger::ID testID = trustedVals.empty() ? this->genesisLedger.id() : trustedVals[0].ledgerID(); + Ledger::Seq testSeq = trustedVals.empty() ? this->genesisLedger.seq() : trustedVals[0].seq(); + BEAST_EXPECT(vals.currentTrusted() == trustedVals); + BEAST_EXPECT(vals.getCurrentNodeIDs() == listed); + BEAST_EXPECT(vals.getNodesAfter(this->genesisLedger, genesisLedger.id()) == trustedVals.size()); + if (trustedVals.empty()) + BEAST_EXPECT(vals.getPreferred(this->genesisLedger) == std::nullopt); + else + BEAST_EXPECT(vals.getPreferred(this->genesisLedger)->second == testID); + BEAST_EXPECT(vals.getTrustedForLedger(testID, testSeq) == trustedVals); + BEAST_EXPECT(vals.numTrustedForLedger(testID) == trustedVals.size()); + }; { // Trusted to untrusted @@ -1081,18 +959,15 @@ class Validations_test : public beast::unit_test::suite LedgerHistoryHelper h; TestHarness harness(h.oracle); Node a = harness.makeNode(); - Validation v = - a.validate(Ledger::ID{2}, Ledger::Seq{2}, 0s, 0s, true); + Validation v = a.validate(Ledger::ID{2}, Ledger::Seq{2}, 0s, 0s, true); BEAST_EXPECT(ValStatus::current == harness.add(v)); hash_set listed({a.nodeID()}); std::vector trustedVals({v}); auto& vals = harness.vals(); BEAST_EXPECT(vals.currentTrusted() == trustedVals); - BEAST_EXPECT( - vals.getPreferred(genesisLedger)->second == v.ledgerID()); - BEAST_EXPECT( - vals.getNodesAfter(genesisLedger, genesisLedger.id()) == 0); + BEAST_EXPECT(vals.getPreferred(genesisLedger)->second == v.ledgerID()); + BEAST_EXPECT(vals.getNodesAfter(genesisLedger, genesisLedger.id()) == 0); trustedVals.clear(); harness.vals().trustChanged({}, {a.nodeID()}); @@ -1100,8 +975,7 @@ class Validations_test : public beast::unit_test::suite h["ab"]; BEAST_EXPECT(vals.currentTrusted() == trustedVals); BEAST_EXPECT(vals.getPreferred(genesisLedger) == std::nullopt); - BEAST_EXPECT( - vals.getNodesAfter(genesisLedger, genesisLedger.id()) == 0); + BEAST_EXPECT(vals.getNodesAfter(genesisLedger, genesisLedger.id()) == 0); } } diff --git a/src/test/core/ClosureCounter_test.cpp b/src/test/core/ClosureCounter_test.cpp index 47f9d9a5d1..f5e9dc7880 100644 --- a/src/test/core/ClosureCounter_test.cpp +++ b/src/test/core/ClosureCounter_test.cpp @@ -16,11 +16,7 @@ class ClosureCounter_test : public beast::unit_test::suite { // We're only using Env for its Journal. That Journal gives better // coverage in unit tests. - test::jtx::Env env_{ - *this, - jtx::envconfig(), - nullptr, - beast::severities::kDisabled}; + test::jtx::Env env_{*this, jtx::envconfig(), nullptr, beast::severities::kDisabled}; beast::Journal j{env_.app().journal("ClosureCounter_test")}; void @@ -110,14 +106,12 @@ class ClosureCounter_test : public beast::unit_test::suite } // Copy constructor - TrackedString(TrackedString const& rhs) - : copies(rhs.copies + 1), moves(rhs.moves), str(rhs.str) + TrackedString(TrackedString const& rhs) : copies(rhs.copies + 1), moves(rhs.moves), str(rhs.str) { } // Move constructor - TrackedString(TrackedString&& rhs) noexcept - : copies(rhs.copies), moves(rhs.moves + 1), str(std::move(rhs.str)) + TrackedString(TrackedString&& rhs) noexcept : copies(rhs.copies), moves(rhs.moves + 1), str(std::move(rhs.str)) { } @@ -152,8 +146,7 @@ class ClosureCounter_test : public beast::unit_test::suite ClosureCounter strCounter; BEAST_EXPECT(strCounter.count() == 0); - auto wrapped = - strCounter.wrap([](TrackedString in) { return in += "!"; }); + auto wrapped = strCounter.wrap([](TrackedString in) { return in += "!"; }); BEAST_EXPECT(strCounter.count() == 1); BEAST_EXPECT(wrapped); @@ -170,8 +163,7 @@ class ClosureCounter_test : public beast::unit_test::suite ClosureCounter strCounter; BEAST_EXPECT(strCounter.count() == 0); - auto wrapped = strCounter.wrap( - [](TrackedString const& in) { return in + "!"; }); + auto wrapped = strCounter.wrap([](TrackedString const& in) { return in + "!"; }); BEAST_EXPECT(strCounter.count() == 1); BEAST_EXPECT(wrapped); @@ -188,8 +180,7 @@ class ClosureCounter_test : public beast::unit_test::suite ClosureCounter strCounter; BEAST_EXPECT(strCounter.count() == 0); - auto wrapped = - strCounter.wrap([](TrackedString& in) { return in += "!"; }); + auto wrapped = strCounter.wrap([](TrackedString& in) { return in += "!"; }); BEAST_EXPECT(strCounter.count() == 1); BEAST_EXPECT(wrapped); diff --git a/src/test/core/Config_test.cpp b/src/test/core/Config_test.cpp index d6ec875982..1035be6fc0 100644 --- a/src/test/core/Config_test.cpp +++ b/src/test/core/Config_test.cpp @@ -100,10 +100,8 @@ r.ripple.com 51235 backend=sqlite )xrpldConfig"); - std::string dbPathSection = - dbPath.empty() ? "" : "[database_path]\n" + dbPath; - std::string valFileSection = - validatorsFile.empty() ? "" : "[validators_file]\n" + validatorsFile; + std::string dbPathSection = dbPath.empty() ? "" : "[database_path]\n" + dbPath; + std::string valFileSection = validatorsFile.empty() ? "" : "[validators_file]\n" + validatorsFile; return boost::str(configContentsTemplate % dbPathSection % valFileSection); } @@ -132,9 +130,7 @@ public: test, std::move(subDir), configFile, - confContents.empty() - ? configContents(dbPath.string(), validatorsFile.string()) - : confContents, + confContents.empty() ? configContents(dbPath.string(), validatorsFile.string()) : confContents, useCounter) , dataDir_(dbPath) { @@ -233,9 +229,7 @@ public: : FileDirGuard( test, std::move(subDir), - path( - validatorsFileName.empty() ? Config::validatorsFileName - : validatorsFileName), + path(validatorsFileName.empty() ? Config::validatorsFileName : validatorsFileName), valFileContents(), useCounter) { @@ -301,8 +295,7 @@ port_wss_admin auto const cwd = current_path(); // Test both config file names. - char const* configFiles[] = { - Config::configFileName, Config::configLegacyName}; + char const* configFiles[] = {Config::configFileName, Config::configLegacyName}; // Config file in current directory. for (auto const& configFile : configFiles) @@ -319,9 +312,7 @@ port_wss_admin Config c; c.setup("", true, false, true); BEAST_EXPECT(c.section(SECTION_DEBUG_LOGFILE).values().size() == 1); - BEAST_EXPECT( - c.section(SECTION_DEBUG_LOGFILE).values()[0] == - "/Users/dummy/xrpld/config/log/debug.log"); + BEAST_EXPECT(c.section(SECTION_DEBUG_LOGFILE).values()[0] == "/Users/dummy/xrpld/config/log/debug.log"); } // Config file in HOME or XDG_CONFIG_HOME directory. @@ -357,16 +348,12 @@ port_wss_admin // Load the config file from the config directory and verify it. Config c; c.setup("", true, false, true); - BEAST_EXPECT( - c.section(SECTION_DEBUG_LOGFILE).values().size() == 1); - BEAST_EXPECT( - c.section(SECTION_DEBUG_LOGFILE).values()[0] == - "/Users/dummy/xrpld/config/log/debug.log"); + BEAST_EXPECT(c.section(SECTION_DEBUG_LOGFILE).values().size() == 1); + BEAST_EXPECT(c.section(SECTION_DEBUG_LOGFILE).values()[0] == "/Users/dummy/xrpld/config/log/debug.log"); // Restore the environment variables. h ? setenv("HOME", h, 1) : unsetenv("HOME"); - x ? setenv("XDG_CONFIG_HOME", x, 1) - : unsetenv("XDG_CONFIG_HOME"); + x ? setenv("XDG_CONFIG_HOME", x, 1) : unsetenv("XDG_CONFIG_HOME"); } // The XDG config directory is not set: the config file must be in a @@ -395,11 +382,8 @@ port_wss_admin // Load the config file from the config directory and verify it. Config c; c.setup("", true, false, true); - BEAST_EXPECT( - c.section(SECTION_DEBUG_LOGFILE).values().size() == 1); - BEAST_EXPECT( - c.section(SECTION_DEBUG_LOGFILE).values()[0] == - "/Users/dummy/xrpld/config/log/debug.log"); + BEAST_EXPECT(c.section(SECTION_DEBUG_LOGFILE).values().size() == 1); + BEAST_EXPECT(c.section(SECTION_DEBUG_LOGFILE).values()[0] == "/Users/dummy/xrpld/config/log/debug.log"); // Restore the environment variables. h ? setenv("HOME", h, 1) : unsetenv("HOME"); @@ -451,13 +435,7 @@ port_wss_admin detail::DirGuard const g0(*this, "test_db"); path const dataDirRel("test_data_dir"); path const dataDirAbs(cwd / g0.subdir() / dataDirRel); - detail::FileCfgGuard const g( - *this, - g0.subdir(), - dataDirAbs, - Config::configFileName, - "", - false); + detail::FileCfgGuard const g(*this, g0.subdir(), dataDirAbs, Config::configFileName, "", false); auto const& c(g.config()); BEAST_EXPECT(g.dataDirExists()); BEAST_EXPECT(g.configFileExists()); @@ -466,8 +444,7 @@ port_wss_admin { // read from file relative path std::string const dbPath("my_db"); - detail::FileCfgGuard const g( - *this, "test_db", dbPath, Config::configFileName, ""); + detail::FileCfgGuard const g(*this, "test_db", dbPath, Config::configFileName, ""); auto const& c(g.config()); std::string const nativeDbPath = absolute(path(dbPath)).string(); BEAST_EXPECT(g.dataDirExists()); @@ -476,11 +453,9 @@ port_wss_admin } { // read from file no path - detail::FileCfgGuard const g( - *this, "test_db", "", Config::configFileName, ""); + detail::FileCfgGuard const g(*this, "test_db", "", Config::configFileName, ""); auto const& c(g.config()); - std::string const nativeDbPath = - absolute(g.subdir() / path(Config::databaseDirName)).string(); + std::string const nativeDbPath = absolute(g.subdir() / path(Config::databaseDirName)).string(); BEAST_EXPECT(g.dataDirExists()); BEAST_EXPECT(g.configFileExists()); BEAST_EXPECT(c.legacy("database_path") == nativeDbPath); @@ -520,8 +495,7 @@ port_wss_admin "and [validator_token] config sections"; try { - c.loadFromString( - boost::str(configTemplate % validationSeed % token)); + c.loadFromString(boost::str(configTemplate % validationSeed % token)); } catch (std::runtime_error& e) { @@ -607,9 +581,7 @@ main boost::format cc("[validators_file]\n%1%\n"); std::string error; std::string const missingPath = "/no/way/this/path/exists"; - auto const expectedError = - "The file specified in [validators_file] does not exist: " + - missingPath; + auto const expectedError = "The file specified in [validators_file] does not exist: " + missingPath; try { Config c; @@ -623,14 +595,11 @@ main } { // load should throw for invalid [validators_file] - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", "validators.cfg"); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg"); path const invalidFile = current_path() / vtg.subdir(); boost::format cc("[validators_file]\n%1%\n"); std::string error; - auto const expectedError = - "Invalid file specified in [validators_file]: " + - invalidFile.string(); + auto const expectedError = "Invalid file specified in [validators_file]: " + invalidFile.string(); try { Config c; @@ -675,25 +644,16 @@ trustthesevalidators.gov 1 )xrpldConfig"); c.loadFromString(toLoad); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values()[0] == - "xrplvalidators.com"); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values()[1] == - "trustthesevalidators.gov"); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values()[0] == "xrplvalidators.com"); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values()[1] == "trustthesevalidators.gov"); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 1); BEAST_EXPECT( c.section(SECTION_VALIDATOR_LIST_KEYS).values()[0] == "021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801" "E566"); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == - 1); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values()[0] == "1"); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values()[0] == "1"); BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == std::size_t(1)); } { @@ -711,25 +671,16 @@ trustthesevalidators.gov 0 )xrpldConfig"); c.loadFromString(toLoad); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values()[0] == - "xrplvalidators.com"); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values()[1] == - "trustthesevalidators.gov"); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values()[0] == "xrplvalidators.com"); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values()[1] == "trustthesevalidators.gov"); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 1); BEAST_EXPECT( c.section(SECTION_VALIDATOR_LIST_KEYS).values()[0] == "021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801" "E566"); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == - 1); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values()[0] == "0"); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values()[0] == "0"); BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == std::nullopt); } { @@ -827,8 +778,7 @@ xrplvalidators.com trustthesevalidators.gov )xrpldConfig"); std::string error; - auto const expectedError = - "[validator_list_keys] config section is missing"; + auto const expectedError = "[validator_list_keys] config section is missing"; try { c.loadFromString(toLoad); @@ -842,124 +792,80 @@ trustthesevalidators.gov } { // load from specified [validators_file] absolute path - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", "validators.cfg"); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg"); BEAST_EXPECT(vtg.validatorsFileExists()); Config c; boost::format cc("[validators_file]\n%1%\n"); c.loadFromString(boost::str(cc % vtg.validatorsFile())); BEAST_EXPECT(c.legacy("validators_file") == vtg.validatorsFile()); BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == - 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == 1); BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2); } { // load from specified [validators_file] file name // in config directory std::string const valFileName = "validators.txt"; - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", valFileName); - detail::FileCfgGuard const rcg( - *this, - vtg.subdir(), - "", - Config::configFileName, - valFileName, - false); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", valFileName); + detail::FileCfgGuard const rcg(*this, vtg.subdir(), "", Config::configFileName, valFileName, false); BEAST_EXPECT(vtg.validatorsFileExists()); BEAST_EXPECT(rcg.configFileExists()); auto const& c(rcg.config()); BEAST_EXPECT(c.legacy("validators_file") == valFileName); BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == - 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == 1); BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2); } { // load from specified [validators_file] relative path // to config directory - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", "validators.txt"); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.txt"); auto const valFilePath = ".." / vtg.subdir() / "validators.txt"; - detail::FileCfgGuard const rcg( - *this, - vtg.subdir(), - "", - Config::configFileName, - valFilePath, - false); + detail::FileCfgGuard const rcg(*this, vtg.subdir(), "", Config::configFileName, valFilePath, false); BEAST_EXPECT(vtg.validatorsFileExists()); BEAST_EXPECT(rcg.configFileExists()); auto const& c(rcg.config()); BEAST_EXPECT(c.legacy("validators_file") == valFilePath); BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == - 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == 1); BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2); } { // load from validators file in default location - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", "validators.txt"); - detail::FileCfgGuard const rcg( - *this, vtg.subdir(), "", Config::configFileName, "", false); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.txt"); + detail::FileCfgGuard const rcg(*this, vtg.subdir(), "", Config::configFileName, "", false); BEAST_EXPECT(vtg.validatorsFileExists()); BEAST_EXPECT(rcg.configFileExists()); auto const& c(rcg.config()); BEAST_EXPECT(c.legacy("validators_file").empty()); BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == - 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == 1); BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2); } { // load from specified [validators_file] instead // of default location - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", "validators.cfg"); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg"); BEAST_EXPECT(vtg.validatorsFileExists()); - detail::ValidatorsTxtGuard const vtgDefault( - *this, vtg.subdir(), "validators.txt", false); + detail::ValidatorsTxtGuard const vtgDefault(*this, vtg.subdir(), "validators.txt", false); BEAST_EXPECT(vtgDefault.validatorsFileExists()); detail::FileCfgGuard const rcg( - *this, - vtg.subdir(), - "", - Config::configFileName, - vtg.validatorsFile(), - false); + *this, vtg.subdir(), "", Config::configFileName, vtg.validatorsFile(), false); BEAST_EXPECT(rcg.configFileExists()); auto const& c(rcg.config()); BEAST_EXPECT(c.legacy("validators_file") == vtg.validatorsFile()); BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == - 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == 1); BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2); } @@ -987,20 +893,15 @@ trustthesevalidators.gov [validator_list_keys] 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566 )xrpldConfig"); - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", "validators.cfg"); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg"); BEAST_EXPECT(vtg.validatorsFileExists()); Config c; c.loadFromString(boost::str(cc % vtg.validatorsFile())); BEAST_EXPECT(c.legacy("validators_file") == vtg.validatorsFile()); BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 15); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 4); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 3); - BEAST_EXPECT( - c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == - 1); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 4); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 3); + BEAST_EXPECT(c.section(SECTION_VALIDATOR_LIST_THRESHOLD).values().size() == 1); BEAST_EXPECT(c.VALIDATOR_LIST_THRESHOLD == 2); } { @@ -1014,8 +915,7 @@ trustthesevalidators.gov 1 )xrpldConfig"); std::string error; - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", "validators.cfg"); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg"); BEAST_EXPECT(vtg.validatorsFileExists()); auto const expectedError = "Config section [validator_list_threshold] should contain " @@ -1039,8 +939,7 @@ trustthesevalidators.gov Config c; boost::format cc("[validators_file]\n%1%\n"); std::string error; - detail::ValidatorsTxtGuard const vtg( - *this, "test_cfg", "validators.cfg"); + detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg"); BEAST_EXPECT(vtg.validatorsFileExists()); auto const expectedError = "The file specified in [validators_file] does not contain a " @@ -1064,12 +963,7 @@ trustthesevalidators.gov void testSetup(bool explicitPath) { - detail::FileCfgGuard const cfg( - *this, - "testSetup", - explicitPath ? "test_db" : "", - Config::configFileName, - ""); + detail::FileCfgGuard const cfg(*this, "testSetup", explicitPath ? "test_db" : "", Config::configFileName, ""); /* FileCfgGuard has a Config object that gets loaded on construction, but Config::setup is not reentrant, so we need a fresh config for every test case, so ignore it. @@ -1137,8 +1031,7 @@ trustthesevalidators.gov BEAST_EXPECT(!config.silent()); BEAST_EXPECT(config.standalone()); BEAST_EXPECT(config.LEDGER_HISTORY == 0); - BEAST_EXPECT( - config.legacy("database_path").empty() == !explicitPath); + BEAST_EXPECT(config.legacy("database_path").empty() == !explicitPath); } { Config config; @@ -1151,8 +1044,7 @@ trustthesevalidators.gov BEAST_EXPECT(!config.silent()); BEAST_EXPECT(config.standalone()); BEAST_EXPECT(config.LEDGER_HISTORY == 0); - BEAST_EXPECT( - config.legacy("database_path").empty() == !explicitPath); + BEAST_EXPECT(config.legacy("database_path").empty() == !explicitPath); } { Config config; @@ -1165,8 +1057,7 @@ trustthesevalidators.gov BEAST_EXPECT(config.silent()); BEAST_EXPECT(config.standalone()); BEAST_EXPECT(config.LEDGER_HISTORY == 0); - BEAST_EXPECT( - config.legacy("database_path").empty() == !explicitPath); + BEAST_EXPECT(config.legacy("database_path").empty() == !explicitPath); } { Config config; @@ -1179,16 +1070,14 @@ trustthesevalidators.gov BEAST_EXPECT(config.silent()); BEAST_EXPECT(config.standalone()); BEAST_EXPECT(config.LEDGER_HISTORY == 0); - BEAST_EXPECT( - config.legacy("database_path").empty() == !explicitPath); + BEAST_EXPECT(config.legacy("database_path").empty() == !explicitPath); } } void testPort() { - detail::FileCfgGuard const cfg( - *this, "testPort", "", Config::configFileName, ""); + detail::FileCfgGuard const cfg(*this, "testPort", "", Config::configFileName, ""); auto const& conf = cfg.config(); if (!BEAST_EXPECT(conf.exists("port_rpc"))) return; @@ -1207,27 +1096,17 @@ trustthesevalidators.gov void testZeroPort() { - auto const contents = std::regex_replace( - detail::configContents("", ""), - std::regex("port\\s*=\\s*\\d+"), - "port = 0"); + auto const contents = + std::regex_replace(detail::configContents("", ""), std::regex("port\\s*=\\s*\\d+"), "port = 0"); try { - detail::FileCfgGuard const cfg( - *this, - "testPort", - "", - Config::configFileName, - "", - true, - contents); + detail::FileCfgGuard const cfg(*this, "testPort", "", Config::configFileName, "", true, contents); BEAST_EXPECT(false); } catch (std::exception const& ex) { - BEAST_EXPECT(std::string_view(ex.what()).starts_with( - "Invalid value '0' for key 'port'")); + BEAST_EXPECT(std::string_view(ex.what()).starts_with("Invalid value '0' for key 'port'")); } } @@ -1264,12 +1143,10 @@ r.ripple.com 51235 cfg.exists("port_rpc") && cfg.section("port_rpc").lines().empty() && cfg.section("port_rpc").values().empty()); BEAST_EXPECT( - cfg.exists(SECTION_IPS) && - cfg.section(SECTION_IPS).lines().size() == 1 && + cfg.exists(SECTION_IPS) && cfg.section(SECTION_IPS).lines().size() == 1 && cfg.section(SECTION_IPS).values().size() == 1); BEAST_EXPECT( - cfg.exists(SECTION_IPS_FIXED) && - cfg.section(SECTION_IPS_FIXED).lines().size() == 2 && + cfg.exists(SECTION_IPS_FIXED) && cfg.section(SECTION_IPS_FIXED).lines().size() == 2 && cfg.section(SECTION_IPS_FIXED).values().size() == 2); } @@ -1320,12 +1197,10 @@ r.ripple.com:51235 cfg.exists("port_rpc") && cfg.section("port_rpc").lines().empty() && cfg.section("port_rpc").values().empty()); BEAST_EXPECT( - cfg.exists(SECTION_IPS) && - cfg.section(SECTION_IPS).lines().size() == 1 && + cfg.exists(SECTION_IPS) && cfg.section(SECTION_IPS).lines().size() == 1 && cfg.section(SECTION_IPS).values().size() == 1); BEAST_EXPECT( - cfg.exists(SECTION_IPS_FIXED) && - cfg.section(SECTION_IPS_FIXED).lines().size() == 15 && + cfg.exists(SECTION_IPS_FIXED) && cfg.section(SECTION_IPS_FIXED).lines().size() == 15 && cfg.section(SECTION_IPS_FIXED).values().size() == 15); BEAST_EXPECT(cfg.IPS[0] == "r.ripple.com 51235"); @@ -1344,11 +1219,8 @@ r.ripple.com:51235 BEAST_EXPECT(cfg.IPS_FIXED[10] == "::1"); BEAST_EXPECT(cfg.IPS_FIXED[11] == "::1:12345"); BEAST_EXPECT(cfg.IPS_FIXED[12] == "[::1]:12345"); - BEAST_EXPECT( - cfg.IPS_FIXED[13] == - "2001:db8:3333:4444:5555:6666:7777:8888:12345"); - BEAST_EXPECT( - cfg.IPS_FIXED[14] == "[2001:db8:3333:4444:5555:6666:7777:8888]:1"); + BEAST_EXPECT(cfg.IPS_FIXED[13] == "2001:db8:3333:4444:5555:6666:7777:8888:12345"); + BEAST_EXPECT(cfg.IPS_FIXED[14] == "[2001:db8:3333:4444:5555:6666:7777:8888]:1"); } void @@ -1542,8 +1414,7 @@ r.ripple.com:51235 { c.loadFromString(toLoad); if (shouldPass) - BEAST_EXPECT( - c.AMENDMENT_MAJORITY_TIME.count() == val * sec); + BEAST_EXPECT(c.AMENDMENT_MAJORITY_TIME.count() == val * sec); else fail(); } @@ -1562,8 +1433,7 @@ r.ripple.com:51235 { testcase("overlay: unknown time"); - auto testUnknown = - [](std::string value) -> std::optional { + auto testUnknown = [](std::string value) -> std::optional { try { Config c; @@ -1597,8 +1467,7 @@ r.ripple.com:51235 testcase("overlay: diverged time"); // In bounds: - auto testDiverged = - [](std::string value) -> std::optional { + auto testDiverged = [](std::string value) -> std::optional { try { Config c; diff --git a/src/test/core/Coroutine_test.cpp b/src/test/core/Coroutine_test.cpp index 761fd46915..73dc3c2f8f 100644 --- a/src/test/core/Coroutine_test.cpp +++ b/src/test/core/Coroutine_test.cpp @@ -55,13 +55,12 @@ public: gate g1, g2; std::shared_ptr c; - env.app().getJobQueue().postCoro( - jtCLIENT, "CoroTest", [&](auto const& cr) { - c = cr; - g1.signal(); - c->yield(); - g2.signal(); - }); + env.app().getJobQueue().postCoro(jtCLIENT, "CoroTest", [&](auto const& cr) { + c = cr; + g1.signal(); + c->yield(); + g2.signal(); + }); BEAST_EXPECT(g1.wait_for(5s)); c->join(); c->post(); @@ -82,12 +81,11 @@ public: })); gate g; - env.app().getJobQueue().postCoro( - jtCLIENT, "CoroTest", [&](auto const& c) { - c->post(); - c->yield(); - g.signal(); - }); + env.app().getJobQueue().postCoro(jtCLIENT, "CoroTest", [&](auto const& c) { + c->post(); + c->yield(); + g.signal(); + }); BEAST_EXPECT(g.wait_for(5s)); } diff --git a/src/test/core/JobQueue_test.cpp b/src/test/core/JobQueue_test.cpp index 641a5fa317..0eee9ce6f2 100644 --- a/src/test/core/JobQueue_test.cpp +++ b/src/test/core/JobQueue_test.cpp @@ -19,9 +19,7 @@ class JobQueue_test : public beast::unit_test::suite { // addJob() should run the Job (and return true). std::atomic jobRan{false}; - BEAST_EXPECT(jQueue.addJob(jtCLIENT, "JobAddTest1", [&jobRan]() { - jobRan = true; - }) == true); + BEAST_EXPECT(jQueue.addJob(jtCLIENT, "JobAddTest1", [&jobRan]() { jobRan = true; }) == true); // Wait for the Job to run. while (jobRan == false) @@ -38,10 +36,7 @@ class JobQueue_test : public beast::unit_test::suite // unprotected variable on the stack should be completely safe. // Not recommended for the faint of heart... bool unprotected; - BEAST_EXPECT( - jQueue.addJob(jtCLIENT, "JobAddTest2", [&unprotected]() { - unprotected = false; - }) == false); + BEAST_EXPECT(jQueue.addJob(jtCLIENT, "JobAddTest2", [&unprotected]() { unprotected = false; }) == false); } } @@ -55,9 +50,7 @@ class JobQueue_test : public beast::unit_test::suite // Test repeated post()s until the Coro completes. std::atomic yieldCount{0}; auto const coro = jQueue.postCoro( - jtCLIENT, - "PostCoroTest1", - [&yieldCount](std::shared_ptr const& coroCopy) { + jtCLIENT, "PostCoroTest1", [&yieldCount](std::shared_ptr const& coroCopy) { while (++yieldCount < 4) coroCopy->yield(); }); @@ -84,9 +77,7 @@ class JobQueue_test : public beast::unit_test::suite // Test repeated resume()s until the Coro completes. int yieldCount{0}; auto const coro = jQueue.postCoro( - jtCLIENT, - "PostCoroTest2", - [&yieldCount](std::shared_ptr const& coroCopy) { + jtCLIENT, "PostCoroTest2", [&yieldCount](std::shared_ptr const& coroCopy) { while (++yieldCount < 4) coroCopy->yield(); }); @@ -121,10 +112,8 @@ class JobQueue_test : public beast::unit_test::suite // unprotected variable on the stack should be completely safe. // Not recommended for the faint of heart... bool unprotected; - auto const coro = jQueue.postCoro( - jtCLIENT, - "PostCoroTest3", - [&unprotected](std::shared_ptr const&) { + auto const coro = + jQueue.postCoro(jtCLIENT, "PostCoroTest3", [&unprotected](std::shared_ptr const&) { unprotected = false; }); BEAST_EXPECT(coro == nullptr); diff --git a/src/test/core/SociDB_test.cpp b/src/test/core/SociDB_test.cpp index fc3c86a994..001022aa95 100644 --- a/src/test/core/SociDB_test.cpp +++ b/src/test/core/SociDB_test.cpp @@ -13,9 +13,7 @@ class SociDB_test final : public TestSuite { private: static void - setupSQLiteConfig( - BasicConfig& config, - boost::filesystem::path const& dbPath) + setupSQLiteConfig(BasicConfig& config, boost::filesystem::path const& dbPath) { config.overwrite("sqdb", "backend", "sqlite"); auto value = dbPath.string(); @@ -45,8 +43,7 @@ private: if (!is_directory(dbPath)) { // someone created a file where we want to put out directory - Throw( - "Cannot create directory: " + dbPath.string()); + Throw("Cannot create directory: " + dbPath.string()); } } static boost::filesystem::path @@ -84,16 +81,12 @@ public: BasicConfig c; setupSQLiteConfig(c, getDatabasePath()); std::vector> const d( - {{"peerfinder", ".sqlite"}, - {"state", ".db"}, - {"random", ".db"}, - {"validators", ".sqlite"}}); + {{"peerfinder", ".sqlite"}, {"state", ".db"}, {"random", ".db"}, {"validators", ".sqlite"}}); for (auto const& i : d) { DBConfig sc(c, i.first); - BEAST_EXPECT( - boost::ends_with(sc.connectionString(), i.first + i.second)); + BEAST_EXPECT(boost::ends_with(sc.connectionString(), i.first + i.second)); } } void @@ -103,27 +96,19 @@ public: BasicConfig c; setupSQLiteConfig(c, getDatabasePath()); DBConfig sc(c, "SociTestDB"); - std::vector const stringData( - {"String1", "String2", "String3"}); + std::vector const stringData({"String1", "String2", "String3"}); std::vector const intData({1, 2, 3}); auto checkValues = [this, &stringData, &intData](soci::session& s) { // Check values in db std::vector stringResult(20 * stringData.size()); std::vector intResult(20 * intData.size()); - s << "SELECT StringData, IntData FROM SociTestTable;", - soci::into(stringResult), soci::into(intResult); - BEAST_EXPECT( - stringResult.size() == stringData.size() && - intResult.size() == intData.size()); + s << "SELECT StringData, IntData FROM SociTestTable;", soci::into(stringResult), soci::into(intResult); + BEAST_EXPECT(stringResult.size() == stringData.size() && intResult.size() == intData.size()); for (int i = 0; i < stringResult.size(); ++i) { - auto si = std::distance( - stringData.begin(), - std::find( - stringData.begin(), stringData.end(), stringResult[i])); - auto ii = std::distance( - intData.begin(), - std::find(intData.begin(), intData.end(), intResult[i])); + auto si = + std::distance(stringData.begin(), std::find(stringData.begin(), stringData.end(), stringResult[i])); + auto ii = std::distance(intData.begin(), std::find(intData.begin(), intData.end(), intResult[i])); BEAST_EXPECT(si == ii && si < stringResult.size()); } }; @@ -164,11 +149,9 @@ public: BasicConfig c; setupSQLiteConfig(c, getDatabasePath()); DBConfig sc(c, "SociTestDB"); - std::vector const ubid( - {(std::uint64_t)std::numeric_limits::max(), 20, 30}); + std::vector const ubid({(std::uint64_t)std::numeric_limits::max(), 20, 30}); std::vector const bid({-10, -20, -30}); - std::vector const uid( - {std::numeric_limits::max(), 2, 3}); + std::vector const uid({std::numeric_limits::max(), 2, 3}); std::vector const id({-1, -2, -3}); { @@ -194,11 +177,9 @@ public: std::uint32_t uig = 0; std::int64_t big = 0; std::uint64_t ubig = 0; - s << "SELECT I, UI, BI, UBI from STT;", soci::into(ig), - soci::into(uig), soci::into(big), soci::into(ubig); - BEAST_EXPECT( - ig == id[0] && uig == uid[0] && big == bid[0] && - ubig == ubid[0]); + s << "SELECT I, UI, BI, UBI from STT;", soci::into(ig), soci::into(uig), soci::into(big), + soci::into(ubig); + BEAST_EXPECT(ig == id[0] && uig == uid[0] && big == bid[0] && ubig == ubid[0]); } catch (std::exception&) { @@ -214,11 +195,9 @@ public: uint32_t uig = 0; boost::optional big; boost::optional ubig; - s << "SELECT I, UI, BI, UBI from STT;", soci::into(ig), - soci::into(uig), soci::into(big), soci::into(ubig); - BEAST_EXPECT( - *ig == id[0] && uig == uid[0] && *big == bid[0] && - *ubig == ubid[0]); + s << "SELECT I, UI, BI, UBI from STT;", soci::into(ig), soci::into(uig), soci::into(big), + soci::into(ubig); + BEAST_EXPECT(*ig == id[0] && uig == uid[0] && *big == bid[0] && *ubig == ubid[0]); } catch (std::exception&) { diff --git a/src/test/core/Workers_test.cpp b/src/test/core/Workers_test.cpp index 0a552e9d61..1f1c16b12b 100644 --- a/src/test/core/Workers_test.cpp +++ b/src/test/core/Workers_test.cpp @@ -49,8 +49,7 @@ class PerfLogTest : public PerfLog } void - jobFinish(JobType const type, std::chrono::microseconds dur, int instance) - override + jobFinish(JobType const type, std::chrono::microseconds dur, int instance) override { } @@ -102,13 +101,10 @@ public: void testThreads(int const tc1, int const tc2, int const tc3) { - testcase( - "threadCounts: " + std::to_string(tc1) + " -> " + - std::to_string(tc2) + " -> " + std::to_string(tc3)); + testcase("threadCounts: " + std::to_string(tc1) + " -> " + std::to_string(tc2) + " -> " + std::to_string(tc3)); TestCallback cb; - std::unique_ptr perfLog = - std::make_unique(); + std::unique_ptr perfLog = std::make_unique(); Workers w(cb, perfLog.get(), "Test", tc1); BEAST_EXPECT(w.getNumberOfThreads() == tc1); @@ -128,8 +124,7 @@ public: // using namespace std::chrono_literals; std::unique_lock lk{cb.mut}; - bool const signaled = - cb.cv.wait_for(lk, 10s, [&cb] { return cb.count == 0; }); + bool const signaled = cb.cv.wait_for(lk, 10s, [&cb] { return cb.count == 0; }); BEAST_EXPECT(signaled); BEAST_EXPECT(cb.count == 0); }; diff --git a/src/test/csf/BasicNetwork.h b/src/test/csf/BasicNetwork.h index cb4e691317..24d762deb0 100644 --- a/src/test/csf/BasicNetwork.h +++ b/src/test/csf/BasicNetwork.h @@ -116,10 +116,7 @@ public: @return `true` if a new connection was established */ bool - connect( - Peer const& from, - Peer const& to, - duration const& delay = std::chrono::seconds{0}); + connect(Peer const& from, Peer const& to, duration const& delay = std::chrono::seconds{0}); /** Break a link. @@ -184,10 +181,7 @@ BasicNetwork::BasicNetwork(Scheduler& s) : scheduler(s) template inline bool -BasicNetwork::connect( - Peer const& from, - Peer const& to, - duration const& delay) +BasicNetwork::connect(Peer const& from, Peer const& to, duration const& delay) { if (to == from) return false; @@ -221,15 +215,14 @@ BasicNetwork::send(Peer const& from, Peer const& to, Function&& f) if (!link) return; time_point const sent = scheduler.now(); - scheduler.in( - link->delay, [from, to, sent, f = std::forward(f), this] { - // only process if still connected and connection was - // not broken since the message was sent - if (auto l = links_.edge(from, to); l && l->established <= sent) - { - f(); - } - }); + scheduler.in(link->delay, [from, to, sent, f = std::forward(f), this] { + // only process if still connected and connection was + // not broken since the message was sent + if (auto l = links_.edge(from, to); l && l->established <= sent) + { + f(); + } + }); } } // namespace csf diff --git a/src/test/csf/BasicNetwork_test.cpp b/src/test/csf/BasicNetwork_test.cpp index 0b29f90ad3..d66f5c9891 100644 --- a/src/test/csf/BasicNetwork_test.cpp +++ b/src/test/csf/BasicNetwork_test.cpp @@ -33,9 +33,7 @@ public: if (id == 0) { for (auto const link : net.links(this)) - net.send(this, link.target, [&, to = link.target] { - to->receive(net, this, 1); - }); + net.send(this, link.target, [&, to = link.target] { to->receive(net, this, 1); }); } else { @@ -52,9 +50,7 @@ public: if (m < 5) { for (auto const link : net.links(this)) - net.send(this, link.target, [&, mm = m, to = link.target] { - to->receive(net, this, mm); - }); + net.send(this, link.target, [&, mm = m, to = link.target] { to->receive(net, this, mm); }); } } }; diff --git a/src/test/csf/Digraph.h b/src/test/csf/Digraph.h index a283f2f7cc..85baecc813 100644 --- a/src/test/csf/Digraph.h +++ b/src/test/csf/Digraph.h @@ -129,9 +129,7 @@ public: auto outVertices() const { - return boost::adaptors::transform( - graph_, - [](typename Graph::value_type const& v) { return v.first; }); + return boost::adaptors::transform(graph_, [](typename Graph::value_type const& v) { return v.first; }); } /** Range over target vertices @@ -142,9 +140,7 @@ public: auto outVertices(Vertex source) const { - auto transform = [](typename Links::value_type const& link) { - return link.first; - }; + auto transform = [](typename Links::value_type const& link) { return link.first; }; auto it = graph_.find(source); if (it != graph_.end()) return boost::adaptors::transform(it->second, transform); diff --git a/src/test/csf/Peer.h b/src/test/csf/Peer.h index b86991ba5f..e0bc7059a2 100644 --- a/src/test/csf/Peer.h +++ b/src/test/csf/Peer.h @@ -405,20 +405,18 @@ struct Peer minDuration = std::min(minDuration, link.data.delay); // Send a message to neighbors to find the ledger - net.send( - this, link.target, [to = link.target, from = this, ledgerID]() { - if (auto it = to->ledgers.find(ledgerID); - it != to->ledgers.end()) - { - // if the ledger is found, send it back to the original - // requesting peer where it is added to the available - // ledgers - to->net.send(to, from, [from, ledger = it->second]() { - from->acquiringLedgers.erase(ledger.id()); - from->ledgers.emplace(ledger.id(), ledger); - }); - } - }); + net.send(this, link.target, [to = link.target, from = this, ledgerID]() { + if (auto it = to->ledgers.find(ledgerID); it != to->ledgers.end()) + { + // if the ledger is found, send it back to the original + // requesting peer where it is added to the available + // ledgers + to->net.send(to, from, [from, ledger = it->second]() { + from->acquiringLedgers.erase(ledger.id()); + from->ledgers.emplace(ledger.id(), ledger); + }); + } + }); } acquiringLedgers[ledgerID] = scheduler.now() + 2 * minDuration; return nullptr; @@ -451,20 +449,18 @@ struct Peer { minDuration = std::min(minDuration, link.data.delay); // Send a message to neighbors to find the tx set - net.send( - this, link.target, [to = link.target, from = this, setId]() { - if (auto it = to->txSets.find(setId); - it != to->txSets.end()) - { - // If the txSet is found, send it back to the original - // requesting peer, where it is handled like a TxSet - // that was broadcast over the network - to->net.send(to, from, [from, txSet = it->second]() { - from->acquiringTxSets.erase(txSet.id()); - from->handle(txSet); - }); - } - }); + net.send(this, link.target, [to = link.target, from = this, setId]() { + if (auto it = to->txSets.find(setId); it != to->txSets.end()) + { + // If the txSet is found, send it back to the original + // requesting peer, where it is handled like a TxSet + // that was broadcast over the network + to->net.send(to, from, [from, txSet = it->second]() { + from->acquiringTxSets.erase(txSet.id()); + from->handle(txSet); + }); + } + }); } acquiringTxSets[setId] = scheduler.now() + 2 * minDuration; return nullptr; @@ -489,22 +485,12 @@ struct Peer } Result - onClose( - Ledger const& prevLedger, - NetClock::time_point closeTime, - ConsensusMode mode) + onClose(Ledger const& prevLedger, NetClock::time_point closeTime, ConsensusMode mode) { issue(CloseLedger{prevLedger, openTxs}); return Result( - TxSet{openTxs}, - Proposal( - prevLedger.id(), - Proposal::seqJoin, - TxSet::calcID(openTxs), - closeTime, - now(), - id)); + TxSet{openTxs}, Proposal(prevLedger.id(), Proposal::seqJoin, TxSet::calcID(openTxs), closeTime, now(), id)); } void @@ -516,14 +502,7 @@ struct Peer ConsensusMode const& mode, Json::Value&& consensusJson) { - onAccept( - result, - prevLedger, - closeResolution, - rawCloseTimes, - mode, - std::move(consensusJson), - validating()); + onAccept(result, prevLedger, closeResolution, rawCloseTimes, mode, std::move(consensusJson), validating()); } void @@ -541,11 +520,8 @@ struct Peer bool const consensusFail = result.state == ConsensusState::MovedOn; TxSet const acceptedTxs = injectTxs(prevLedger, result.txns); - Ledger const newLedger = oracle.accept( - prevLedger, - acceptedTxs.txs(), - closeResolution, - result.position.closeTime()); + Ledger const newLedger = + oracle.accept(prevLedger, acceptedTxs.txs(), closeResolution, result.position.closeTime()); ledgers[newLedger.id()] = newLedger; issue(AcceptLedger{newLedger, lastClosedLedger}); @@ -554,30 +530,19 @@ struct Peer lastClosedLedger = newLedger; auto const it = std::remove_if( - openTxs.begin(), openTxs.end(), [&](Tx const& tx) { - return acceptedTxs.exists(tx.id()); - }); + openTxs.begin(), openTxs.end(), [&](Tx const& tx) { return acceptedTxs.exists(tx.id()); }); openTxs.erase(it, openTxs.end()); // Only send validation if the new ledger is compatible with our // fully validated ledger - bool const isCompatible = - newLedger.isAncestor(fullyValidatedLedger); + bool const isCompatible = newLedger.isAncestor(fullyValidatedLedger); // Can only send one validated ledger per seq - if (runAsValidator && isCompatible && !consensusFail && - validations.canValidateSeq(newLedger.seq())) + if (runAsValidator && isCompatible && !consensusFail && validations.canValidateSeq(newLedger.seq())) { bool isFull = proposing; - Validation v{ - newLedger.id(), - newLedger.seq(), - now(), - now(), - key, - id, - isFull}; + Validation v{newLedger.id(), newLedger.seq(), now(), now(), key, id, isFull}; // share the new validation; it is trusted by the receiver share(v); // we trust ourselves @@ -608,17 +573,13 @@ struct Peer } Ledger::ID - getPrevLedger( - Ledger::ID const& ledgerID, - Ledger const& ledger, - ConsensusMode mode) + getPrevLedger(Ledger::ID const& ledgerID, Ledger const& ledger, ConsensusMode mode) { // only do if we are past the genesis ledger if (ledger.seq() == Ledger::Seq{0}) return ledgerID; - Ledger::ID const netLgr = - validations.getPreferred(ledger, earliestAllowedSeq()); + Ledger::ID const netLgr = validations.getPreferred(ledger, earliestAllowedSeq()); if (netLgr != ledgerID) { @@ -749,12 +710,7 @@ struct Peer if (link.target->router.lastObservedSeq[bm.origin] < bm.seq) { issue(Relay{link.target->id, bm.msg}); - net.send( - this, - link.target, - [to = link.target, bm, id = this->id] { - to->receive(bm, id); - }); + net.send(this, link.target, [to = link.target, bm, id = this->id] { to->receive(bm, id); }); } } } @@ -800,8 +756,7 @@ struct Peer bool handle(TxSet const& txs) { - bool const inserted = - txSets.insert(std::make_pair(txs.id(), txs)).second; + bool const inserted = txSets.insert(std::make_pair(txs.id(), txs)).second; if (inserted) consensus.gotTxSet(now(), txs); // relay only if new @@ -906,8 +861,7 @@ struct Peer // Between rounds, we take the majority ledger // In the future, consider taking peer dominant ledger if no validations // yet - Ledger::ID bestLCL = - validations.getPreferred(lastClosedLedger, earliestAllowedSeq()); + Ledger::ID bestLCL = validations.getPreferred(lastClosedLedger, earliestAllowedSeq()); if (bestLCL == Ledger::ID{0}) bestLCL = lastClosedLedger.id(); @@ -915,8 +869,7 @@ struct Peer // Not yet modeling dynamic UNL. hash_set nowUntrusted; - consensus.startRound( - now(), bestLCL, lastClosedLedger, nowUntrusted, runAsValidator, {}); + consensus.startRound(now(), bestLCL, lastClosedLedger, nowUntrusted, runAsValidator, {}); } // Start the consensus process assuming it is not yet running @@ -939,8 +892,8 @@ struct Peer // code are positive. (e.g. proposeFRESHNESS) using namespace std::chrono; using namespace std::chrono_literals; - return NetClock::time_point(duration_cast( - scheduler.now().time_since_epoch() + 86400s + clockSkew)); + return NetClock::time_point( + duration_cast(scheduler.now().time_since_epoch() + 86400s + clockSkew)); } Ledger::ID diff --git a/src/test/csf/PeerGroup.h b/src/test/csf/PeerGroup.h index 8a215eaf8d..35a4983e4e 100644 --- a/src/test/csf/PeerGroup.h +++ b/src/test/csf/PeerGroup.h @@ -86,9 +86,7 @@ public: bool contains(PeerID id) { - return std::find_if(peers_.begin(), peers_.end(), [id](Peer const* p) { - return p->id == id; - }) != peers_.end(); + return std::find_if(peers_.begin(), peers_.end(), [id](Peer const* p) { return p->id == id; }) != peers_.end(); } std::size_t @@ -217,11 +215,7 @@ public: { PeerGroup res; std::set_union( - a.peers_.begin(), - a.peers_.end(), - b.peers_.begin(), - b.peers_.end(), - std::back_inserter(res.peers_)); + a.peers_.begin(), a.peers_.end(), b.peers_.begin(), b.peers_.end(), std::back_inserter(res.peers_)); return res; } @@ -232,11 +226,7 @@ public: PeerGroup res; std::set_difference( - a.peers_.begin(), - a.peers_.end(), - b.peers_.begin(), - b.peers_.end(), - std::back_inserter(res.peers_)); + a.peers_.begin(), a.peers_.end(), b.peers_.begin(), b.peers_.end(), std::back_inserter(res.peers_)); return res; } @@ -313,8 +303,7 @@ randomRankedTrust( RandomNumberDistribution sizeDist, Generator& g) { - std::vector const groups = - randomRankedGroups(peers, ranks, numGroups, sizeDist, g); + std::vector const groups = randomRankedGroups(peers, ranks, numGroups, sizeDist, g); std::uniform_int_distribution u(0, groups.size() - 1); for (auto& peer : peers) @@ -338,8 +327,7 @@ randomRankedConnect( Generator& g, SimDuration delay) { - std::vector const groups = - randomRankedGroups(peers, ranks, numGroups, sizeDist, g); + std::vector const groups = randomRankedGroups(peers, ranks, numGroups, sizeDist, g); std::uniform_int_distribution u(0, groups.size() - 1); for (auto& peer : peers) diff --git a/src/test/csf/Scheduler.h b/src/test/csf/Scheduler.h index 2c250e6def..e6d53f045b 100644 --- a/src/test/csf/Scheduler.h +++ b/src/test/csf/Scheduler.h @@ -35,8 +35,7 @@ public: using time_point = typename clock_type::time_point; private: - using by_when_hook = boost::intrusive::set_base_hook< - boost::intrusive::link_mode>; + using by_when_hook = boost::intrusive::set_base_hook>; struct event : by_when_hook { @@ -75,8 +74,7 @@ private: operator=(event_impl const&) = delete; template - event_impl(time_point when_, DeducedHandler&& h) - : event(when_), h_(std::forward(h)) + event_impl(time_point when_, DeducedHandler&& h) : event(when_), h_(std::forward(h)) { } @@ -90,9 +88,8 @@ private: class queue_type { private: - using by_when_set = typename boost::intrusive::make_multiset< - event, - boost::intrusive::constant_time_size>::type; + using by_when_set = + typename boost::intrusive::make_multiset>::type; // alloc_ is owned by the scheduler boost::container::pmr::monotonic_buffer_resource* alloc_; by_when_set by_when_; @@ -104,8 +101,7 @@ private: queue_type& operator=(queue_type const&) = delete; - explicit queue_type( - boost::container::pmr::monotonic_buffer_resource* alloc); + explicit queue_type(boost::container::pmr::monotonic_buffer_resource* alloc); ~queue_type(); @@ -256,9 +252,7 @@ public: //------------------------------------------------------------------------------ -inline Scheduler::queue_type::queue_type( - boost::container::pmr::monotonic_buffer_resource* alloc) - : alloc_(alloc) +inline Scheduler::queue_type::queue_type(boost::container::pmr::monotonic_buffer_resource* alloc) : alloc_(alloc) { } @@ -293,8 +287,7 @@ Scheduler::queue_type::end() -> iterator template inline auto -Scheduler::queue_type::emplace(time_point when, Handler&& h) -> - typename by_when_set::iterator +Scheduler::queue_type::emplace(time_point when, Handler&& h) -> typename by_when_set::iterator { using event_type = event_impl>; auto const p = alloc_->allocate(sizeof(event_type)); diff --git a/src/test/csf/Sim.h b/src/test/csf/Sim.h index ad0927e87e..ff99896e99 100644 --- a/src/test/csf/Sim.h +++ b/src/test/csf/Sim.h @@ -24,8 +24,7 @@ class BasicSink : public beast::Journal::Sink Scheduler::clock_type const& clock_; public: - BasicSink(Scheduler::clock_type const& clock) - : Sink(beast::severities::kDisabled, false), clock_{clock} + BasicSink(Scheduler::clock_type const& clock) : Sink(beast::severities::kDisabled, false), clock_{clock} { } @@ -35,16 +34,13 @@ public: if (level < threshold()) return; - std::cout << clock_.now().time_since_epoch().count() << " " << text - << std::endl; + std::cout << clock_.now().time_since_epoch().count() << " " << text << std::endl; } void - writeAlways(beast::severities::Severity level, std::string const& text) - override + writeAlways(beast::severities::Severity level, std::string const& text) override { - std::cout << clock_.now().time_since_epoch().count() << " " << text - << std::endl; + std::cout << clock_.now().time_since_epoch().count() << " " << text << std::endl; } }; @@ -94,13 +90,7 @@ public: for (std::size_t i = 0; i < numPeers; ++i) { peers.emplace_back( - PeerID{static_cast(peers.size())}, - scheduler, - oracle, - net, - trustGraph, - collectors, - j); + PeerID{static_cast(peers.size())}, scheduler, oracle, net, trustGraph, collectors, j); newPeers.emplace_back(&peers.back()); } PeerGroup res{newPeers}; diff --git a/src/test/csf/TrustGraph.h b/src/test/csf/TrustGraph.h index f5b8a9e755..2eb8dac418 100644 --- a/src/test/csf/TrustGraph.h +++ b/src/test/csf/TrustGraph.h @@ -110,8 +110,7 @@ public: std::set unique; for (Peer const peer : graph_.outVertices()) { - unique.emplace( - std::begin(trustedPeers(peer)), std::end(trustedPeers(peer))); + unique.emplace(std::begin(trustedPeers(peer)), std::end(trustedPeers(peer))); } std::vector uniqueUNLs(unique.begin(), unique.end()); @@ -124,18 +123,14 @@ public: { auto const& unlA = uniqueUNLs[i]; auto const& unlB = uniqueUNLs[j]; - double rhs = - 2.0 * (1. - quorum) * std::max(unlA.size(), unlB.size()); + double rhs = 2.0 * (1. - quorum) * std::max(unlA.size(), unlB.size()); int intersectionSize = - std::count_if(unlA.begin(), unlA.end(), [&](Peer p) { - return unlB.find(p) != unlB.end(); - }); + std::count_if(unlA.begin(), unlA.end(), [&](Peer p) { return unlB.find(p) != unlB.end(); }); if (intersectionSize < rhs) { - res.emplace_back( - ForkInfo{unlA, unlB, intersectionSize, rhs}); + res.emplace_back(ForkInfo{unlA, unlB, intersectionSize, rhs}); } } } diff --git a/src/test/csf/Tx.h b/src/test/csf/Tx.h index cf3ee85940..1f355829c8 100644 --- a/src/test/csf/Tx.h +++ b/src/test/csf/Tx.h @@ -145,11 +145,7 @@ public: auto populate_diffs = [&res](auto const& a, auto const& b, bool s) { auto populator = [&](auto const& tx) { res[tx.id()] = s; }; std::set_difference( - a.begin(), - a.end(), - b.begin(), - b.end(), - boost::make_function_output_iterator(std::ref(populator))); + a.begin(), a.end(), b.begin(), b.end(), boost::make_function_output_iterator(std::ref(populator))); }; populate_diffs(txs_, other.txs_, true); diff --git a/src/test/csf/Validation.h b/src/test/csf/Validation.h index 907eca79d0..3ec720e7d2 100644 --- a/src/test/csf/Validation.h +++ b/src/test/csf/Validation.h @@ -140,15 +140,7 @@ public: asTie() const { // trusted is a status set by the receiver, so it is not part of the tie - return std::tie( - ledgerID_, - seq_, - signTime_, - seenTime_, - key_, - nodeID_, - loadFee_, - full_); + return std::tie(ledgerID_, seq_, signTime_, seenTime_, key_, nodeID_, loadFee_, full_); } bool operator==(Validation const& o) const diff --git a/src/test/csf/collectors.h b/src/test/csf/collectors.h index 3b6bc0e0f3..5669b8a380 100644 --- a/src/test/csf/collectors.h +++ b/src/test/csf/collectors.h @@ -46,12 +46,7 @@ class Collectors template static void - apply( - std::tuple& cs, - PeerID who, - SimTime when, - E e, - std::index_sequence) + apply(std::tuple& cs, PeerID who, SimTime when, E e, std::index_sequence) { (..., apply(std::get(cs), who, when, e)); } @@ -235,18 +230,14 @@ struct TxCollector std::size_t orphaned() const { - return std::count_if(txs.begin(), txs.end(), [](auto const& it) { - return !it.second.accepted; - }); + return std::count_if(txs.begin(), txs.end(), [](auto const& it) { return !it.second.accepted; }); } // Returns the number of txs which were never validated std::size_t unvalidated() const { - return std::count_if(txs.begin(), txs.end(), [](auto const& it) { - return !it.second.validated; - }); + return std::count_if(txs.begin(), txs.end(), [](auto const& it) { return !it.second.validated; }); } template @@ -258,86 +249,64 @@ struct TxCollector return double(count) / duration_cast(simDuration).count(); }; - auto fmtS = [](SimDuration dur) { - return duration_cast>(dur).count(); - }; + auto fmtS = [](SimDuration dur) { return duration_cast>(dur).count(); }; if (printBreakline) { - log << std::setw(11) << std::setfill('-') << "-" << "-" - << std::setw(7) << std::setfill('-') << "-" << "-" - << std::setw(7) << std::setfill('-') << "-" << "-" - << std::setw(36) << std::setfill('-') << "-" << std::endl; + log << std::setw(11) << std::setfill('-') << "-" << "-" << std::setw(7) << std::setfill('-') << "-" << "-" + << std::setw(7) << std::setfill('-') << "-" << "-" << std::setw(36) << std::setfill('-') << "-" + << std::endl; log << std::setfill(' '); } - log << std::left << std::setw(11) << "TxStats" << "|" << std::setw(7) - << "Count" << "|" << std::setw(7) << "Per Sec" << "|" - << std::setw(15) << "Latency (sec)" << std::right << std::setw(7) - << "10-ile" << std::setw(7) << "50-ile" << std::setw(7) << "90-ile" - << std::left << std::endl; + log << std::left << std::setw(11) << "TxStats" << "|" << std::setw(7) << "Count" << "|" << std::setw(7) + << "Per Sec" << "|" << std::setw(15) << "Latency (sec)" << std::right << std::setw(7) << "10-ile" + << std::setw(7) << "50-ile" << std::setw(7) << "90-ile" << std::left << std::endl; - log << std::setw(11) << std::setfill('-') << "-" << "|" << std::setw(7) - << std::setfill('-') << "-" << "|" << std::setw(7) - << std::setfill('-') << "-" << "|" << std::setw(36) - << std::setfill('-') << "-" << std::endl; + log << std::setw(11) << std::setfill('-') << "-" << "|" << std::setw(7) << std::setfill('-') << "-" << "|" + << std::setw(7) << std::setfill('-') << "-" << "|" << std::setw(36) << std::setfill('-') << "-" + << std::endl; log << std::setfill(' '); - log << std::left << std::setw(11) << "Submit " << "|" << std::right - << std::setw(7) << submitted << "|" << std::setw(7) - << std::setprecision(2) << perSec(submitted) << "|" << std::setw(36) - << "" << std::endl; + log << std::left << std::setw(11) << "Submit " << "|" << std::right << std::setw(7) << submitted << "|" + << std::setw(7) << std::setprecision(2) << perSec(submitted) << "|" << std::setw(36) << "" << std::endl; - log << std::left << std::setw(11) << "Accept " << "|" << std::right - << std::setw(7) << accepted << "|" << std::setw(7) - << std::setprecision(2) << perSec(accepted) << "|" << std::setw(15) - << std::left << "From Submit" << std::right << std::setw(7) - << std::setprecision(2) << fmtS(submitToAccept.percentile(0.1f)) - << std::setw(7) << std::setprecision(2) - << fmtS(submitToAccept.percentile(0.5f)) << std::setw(7) - << std::setprecision(2) << fmtS(submitToAccept.percentile(0.9f)) + log << std::left << std::setw(11) << "Accept " << "|" << std::right << std::setw(7) << accepted << "|" + << std::setw(7) << std::setprecision(2) << perSec(accepted) << "|" << std::setw(15) << std::left + << "From Submit" << std::right << std::setw(7) << std::setprecision(2) + << fmtS(submitToAccept.percentile(0.1f)) << std::setw(7) << std::setprecision(2) + << fmtS(submitToAccept.percentile(0.5f)) << std::setw(7) << std::setprecision(2) + << fmtS(submitToAccept.percentile(0.9f)) << std::endl; + + log << std::left << std::setw(11) << "Validate " << "|" << std::right << std::setw(7) << validated << "|" + << std::setw(7) << std::setprecision(2) << perSec(validated) << "|" << std::setw(15) << std::left + << "From Submit" << std::right << std::setw(7) << std::setprecision(2) + << fmtS(submitToValidate.percentile(0.1f)) << std::setw(7) << std::setprecision(2) + << fmtS(submitToValidate.percentile(0.5f)) << std::setw(7) << std::setprecision(2) + << fmtS(submitToValidate.percentile(0.9f)) << std::endl; + + log << std::left << std::setw(11) << "Orphan" << "|" << std::right << std::setw(7) << orphaned() << "|" + << std::setw(7) << "" << "|" << std::setw(36) << std::endl; + + log << std::left << std::setw(11) << "Unvalidated" << "|" << std::right << std::setw(7) << unvalidated() << "|" + << std::setw(7) << "" << "|" << std::setw(43) << std::endl; + + log << std::setw(11) << std::setfill('-') << "-" << "-" << std::setw(7) << std::setfill('-') << "-" << "-" + << std::setw(7) << std::setfill('-') << "-" << "-" << std::setw(36) << std::setfill('-') << "-" << std::endl; - - log << std::left << std::setw(11) << "Validate " << "|" << std::right - << std::setw(7) << validated << "|" << std::setw(7) - << std::setprecision(2) << perSec(validated) << "|" << std::setw(15) - << std::left << "From Submit" << std::right << std::setw(7) - << std::setprecision(2) << fmtS(submitToValidate.percentile(0.1f)) - << std::setw(7) << std::setprecision(2) - << fmtS(submitToValidate.percentile(0.5f)) << std::setw(7) - << std::setprecision(2) << fmtS(submitToValidate.percentile(0.9f)) - << std::endl; - - log << std::left << std::setw(11) << "Orphan" << "|" << std::right - << std::setw(7) << orphaned() << "|" << std::setw(7) << "" << "|" - << std::setw(36) << std::endl; - - log << std::left << std::setw(11) << "Unvalidated" << "|" << std::right - << std::setw(7) << unvalidated() << "|" << std::setw(7) << "" << "|" - << std::setw(43) << std::endl; - - log << std::setw(11) << std::setfill('-') << "-" << "-" << std::setw(7) - << std::setfill('-') << "-" << "-" << std::setw(7) - << std::setfill('-') << "-" << "-" << std::setw(36) - << std::setfill('-') << "-" << std::endl; log << std::setfill(' '); } template void - csv(SimDuration simDuration, - T& log, - Tag const& tag, - bool printHeaders = false) + csv(SimDuration simDuration, T& log, Tag const& tag, bool printHeaders = false) { using namespace std::chrono; auto perSec = [&simDuration](std::size_t count) { return double(count) / duration_cast(simDuration).count(); }; - auto fmtS = [](SimDuration dur) { - return duration_cast>(dur).count(); - }; + auto fmtS = [](SimDuration dur) { return duration_cast>(dur).count(); }; if (printHeaders) { @@ -395,8 +364,7 @@ struct TxCollector << std::setprecision(2) << fmtS(submitToValidate.percentile(0.5f)) << "," // txLatencySubmitToValidate90Pctl - << std::setprecision(2) << fmtS(submitToValidate.percentile(0.9f)) - << "," << std::endl; + << std::setprecision(2) << fmtS(submitToValidate.percentile(0.9f)) << "," << std::endl; } }; @@ -476,8 +444,7 @@ struct LedgerCollector auto& parentTracker = parentIt->second; if (parentTracker.fullyValidated) { - fullyValidToFullyValid.insert( - when - *parentTracker.fullyValidated); + fullyValidToFullyValid.insert(when - *parentTracker.fullyValidated); } } } @@ -488,9 +455,7 @@ struct LedgerCollector unvalidated() const { return std::count_if( - ledgers_.begin(), ledgers_.end(), [](auto const& it) { - return !it.second.fullyValidated; - }); + ledgers_.begin(), ledgers_.end(), [](auto const& it) { return !it.second.fullyValidated; }); } template @@ -502,74 +467,56 @@ struct LedgerCollector return double(count) / duration_cast(simDuration).count(); }; - auto fmtS = [](SimDuration dur) { - return duration_cast>(dur).count(); - }; + auto fmtS = [](SimDuration dur) { return duration_cast>(dur).count(); }; if (printBreakline) { - log << std::setw(11) << std::setfill('-') << "-" << "-" - << std::setw(7) << std::setfill('-') << "-" << "-" - << std::setw(7) << std::setfill('-') << "-" << "-" - << std::setw(36) << std::setfill('-') << "-" << std::endl; + log << std::setw(11) << std::setfill('-') << "-" << "-" << std::setw(7) << std::setfill('-') << "-" << "-" + << std::setw(7) << std::setfill('-') << "-" << "-" << std::setw(36) << std::setfill('-') << "-" + << std::endl; log << std::setfill(' '); } - log << std::left << std::setw(11) << "LedgerStats" << "|" - << std::setw(7) << "Count" << "|" << std::setw(7) << "Per Sec" - << "|" << std::setw(15) << "Latency (sec)" << std::right - << std::setw(7) << "10-ile" << std::setw(7) << "50-ile" - << std::setw(7) << "90-ile" << std::left << std::endl; + log << std::left << std::setw(11) << "LedgerStats" << "|" << std::setw(7) << "Count" << "|" << std::setw(7) + << "Per Sec" + << "|" << std::setw(15) << "Latency (sec)" << std::right << std::setw(7) << "10-ile" << std::setw(7) + << "50-ile" << std::setw(7) << "90-ile" << std::left << std::endl; - log << std::setw(11) << std::setfill('-') << "-" << "|" << std::setw(7) - << std::setfill('-') << "-" << "|" << std::setw(7) - << std::setfill('-') << "-" << "|" << std::setw(36) - << std::setfill('-') << "-" << std::endl; + log << std::setw(11) << std::setfill('-') << "-" << "|" << std::setw(7) << std::setfill('-') << "-" << "|" + << std::setw(7) << std::setfill('-') << "-" << "|" << std::setw(36) << std::setfill('-') << "-" + << std::endl; log << std::setfill(' '); - log << std::left << std::setw(11) << "Accept " << "|" << std::right - << std::setw(7) << accepted << "|" << std::setw(7) - << std::setprecision(2) << perSec(accepted) << "|" << std::setw(15) - << std::left << "From Accept" << std::right << std::setw(7) - << std::setprecision(2) << fmtS(acceptToAccept.percentile(0.1f)) - << std::setw(7) << std::setprecision(2) - << fmtS(acceptToAccept.percentile(0.5f)) << std::setw(7) - << std::setprecision(2) << fmtS(acceptToAccept.percentile(0.9f)) - << std::endl; + log << std::left << std::setw(11) << "Accept " << "|" << std::right << std::setw(7) << accepted << "|" + << std::setw(7) << std::setprecision(2) << perSec(accepted) << "|" << std::setw(15) << std::left + << "From Accept" << std::right << std::setw(7) << std::setprecision(2) + << fmtS(acceptToAccept.percentile(0.1f)) << std::setw(7) << std::setprecision(2) + << fmtS(acceptToAccept.percentile(0.5f)) << std::setw(7) << std::setprecision(2) + << fmtS(acceptToAccept.percentile(0.9f)) << std::endl; - log << std::left << std::setw(11) << "Validate " << "|" << std::right - << std::setw(7) << fullyValidated << "|" << std::setw(7) - << std::setprecision(2) << perSec(fullyValidated) << "|" - << std::setw(15) << std::left << "From Validate " << std::right - << std::setw(7) << std::setprecision(2) - << fmtS(fullyValidToFullyValid.percentile(0.1f)) << std::setw(7) - << std::setprecision(2) - << fmtS(fullyValidToFullyValid.percentile(0.5f)) << std::setw(7) - << std::setprecision(2) + log << std::left << std::setw(11) << "Validate " << "|" << std::right << std::setw(7) << fullyValidated << "|" + << std::setw(7) << std::setprecision(2) << perSec(fullyValidated) << "|" << std::setw(15) << std::left + << "From Validate " << std::right << std::setw(7) << std::setprecision(2) + << fmtS(fullyValidToFullyValid.percentile(0.1f)) << std::setw(7) << std::setprecision(2) + << fmtS(fullyValidToFullyValid.percentile(0.5f)) << std::setw(7) << std::setprecision(2) << fmtS(fullyValidToFullyValid.percentile(0.9f)) << std::endl; - log << std::setw(11) << std::setfill('-') << "-" << "-" << std::setw(7) - << std::setfill('-') << "-" << "-" << std::setw(7) - << std::setfill('-') << "-" << "-" << std::setw(36) - << std::setfill('-') << "-" << std::endl; + log << std::setw(11) << std::setfill('-') << "-" << "-" << std::setw(7) << std::setfill('-') << "-" << "-" + << std::setw(7) << std::setfill('-') << "-" << "-" << std::setw(36) << std::setfill('-') << "-" + << std::endl; log << std::setfill(' '); } template void - csv(SimDuration simDuration, - T& log, - Tag const& tag, - bool printHeaders = false) + csv(SimDuration simDuration, T& log, Tag const& tag, bool printHeaders = false) { using namespace std::chrono; auto perSec = [&simDuration](std::size_t count) { return double(count) / duration_cast(simDuration).count(); }; - auto fmtS = [](SimDuration dur) { - return duration_cast>(dur).count(); - }; + auto fmtS = [](SimDuration dur) { return duration_cast>(dur).count(); }; if (printHeaders) { @@ -608,16 +555,13 @@ struct LedgerCollector << std::setprecision(2) << fmtS(acceptToAccept.percentile(0.9f)) << "," // ledgerLatencyFullyValidToFullyValid10Pctl - << std::setprecision(2) - << fmtS(fullyValidToFullyValid.percentile(0.1f)) + << std::setprecision(2) << fmtS(fullyValidToFullyValid.percentile(0.1f)) << "," // ledgerLatencyFullyValidToFullyValid50Pctl - << std::setprecision(2) - << fmtS(fullyValidToFullyValid.percentile(0.5f)) + << std::setprecision(2) << fmtS(fullyValidToFullyValid.percentile(0.5f)) << "," // ledgerLatencyFullyValidToFullyValid90Pctl - << std::setprecision(2) - << fmtS(fullyValidToFullyValid.percentile(0.9f)) << std::endl; + << std::setprecision(2) << fmtS(fullyValidToFullyValid.percentile(0.9f)) << std::endl; } }; @@ -640,16 +584,14 @@ struct StreamCollector void on(PeerID who, SimTime when, AcceptLedger const& e) { - out << when.time_since_epoch().count() << ": Node " << who - << " accepted " << "L" << e.ledger.id() << " " << e.ledger.txs() - << "\n"; + out << when.time_since_epoch().count() << ": Node " << who << " accepted " << "L" << e.ledger.id() << " " + << e.ledger.txs() << "\n"; } void on(PeerID who, SimTime when, FullyValidateLedger const& e) { - out << when.time_since_epoch().count() << ": Node " << who - << " fully-validated " << "L" << e.ledger.id() << " " + out << when.time_since_epoch().count() << ": Node " << who << " fully-validated " << "L" << e.ledger.id() << " " << e.ledger.txs() << "\n"; } }; @@ -692,8 +634,7 @@ struct JumpCollector { // Not a direct child -> parent switch if (e.ledger.parentID() != e.prior.id()) - fullyValidatedJumps.emplace_back( - Jump{who, when, e.prior, e.ledger}); + fullyValidatedJumps.emplace_back(Jump{who, when, e.prior, e.ledger}); } }; diff --git a/src/test/csf/impl/ledgers.cpp b/src/test/csf/impl/ledgers.cpp index 09a098f2d6..12d461a214 100644 --- a/src/test/csf/impl/ledgers.cpp +++ b/src/test/csf/impl/ledgers.cpp @@ -88,8 +88,7 @@ LedgerOracle::accept( next.closeTimeResolution = closeTimeResolution; next.closeTimeAgree = consensusCloseTime != NetClock::time_point{}; if (next.closeTimeAgree) - next.closeTime = effCloseTime( - consensusCloseTime, closeTimeResolution, parent.closeTime()); + next.closeTime = effCloseTime(consensusCloseTime, closeTimeResolution, parent.closeTime()); else next.closeTime = parent.closeTime() + 1s; diff --git a/src/test/csf/ledgers.h b/src/test/csf/ledgers.h index 7614482635..d28abeed4b 100644 --- a/src/test/csf/ledgers.h +++ b/src/test/csf/ledgers.h @@ -94,14 +94,7 @@ private: auto asTie() const { - return std::tie( - seq, - txs, - closeTimeResolution, - closeTime, - closeTimeAgree, - parentID, - parentCloseTime); + return std::tie(seq, txs, closeTimeResolution, closeTime, closeTimeAgree, parentID, parentCloseTime); } friend bool @@ -267,11 +260,7 @@ public: accept(Ledger const& curr, Tx tx) { using namespace std::chrono_literals; - return accept( - curr, - TxSetType{tx}, - curr.closeTimeResolution(), - curr.closeTime() + 1s); + return accept(curr, TxSetType{tx}, curr.closeTimeResolution(), curr.closeTime() + 1s); } /** Determine the number of distinct branches for the set of ledgers. @@ -334,8 +323,7 @@ struct LedgerHistoryHelper assert(seen.emplace(s.back()).second); Ledger const& parent = (*this)[s.substr(0, s.size() - 1)]; - return ledgers.emplace(s, oracle.accept(parent, Tx{++nextTx})) - .first->second; + return ledgers.emplace(s, oracle.accept(parent, Tx{++nextTx})).first->second; } }; diff --git a/src/test/csf/random.h b/src/test/csf/random.h index 8b3ac7e971..12ff03cd64 100644 --- a/src/test/csf/random.h +++ b/src/test/csf/random.h @@ -72,11 +72,7 @@ public: @param w Vector of weights of size list-first @param g the pseudo-random number generator */ - Selector( - RAIter first, - RAIter last, - std::vector const& w, - Generator& g) + Selector(RAIter first, RAIter last, std::vector const& w, Generator& g) : first_{first}, last_{last}, dd_{w.begin(), w.end()}, g_{g} { using tag = typename std::iterator_traits::iterator_category; diff --git a/src/test/csf/submitters.h b/src/test/csf/submitters.h index 0c5d46e075..fce5562014 100644 --- a/src/test/csf/submitters.h +++ b/src/test/csf/submitters.h @@ -80,13 +80,7 @@ class Submitter } public: - Submitter( - Distribution dist, - SimTime start, - SimTime end, - Selector& selector, - Scheduler& s, - Generator& g) + Submitter(Distribution dist, SimTime start, SimTime end, Selector& selector, Scheduler& s, Generator& g) : dist_{dist}, stop_{end}, selector_{selector}, scheduler_{s}, g_{g} { scheduler_.at(start, [&]() { submit(); }); @@ -95,16 +89,9 @@ public: template Submitter -makeSubmitter( - Distribution dist, - SimTime start, - SimTime end, - Selector& sel, - Scheduler& s, - Generator& g) +makeSubmitter(Distribution dist, SimTime start, SimTime end, Selector& sel, Scheduler& s, Generator& g) { - return Submitter( - dist, start, end, sel, s, g); + return Submitter(dist, start, end, sel, s, g); } } // namespace csf diff --git a/src/test/csf/timers.h b/src/test/csf/timers.h index b5902393c7..0823dbe9b9 100644 --- a/src/test/csf/timers.h +++ b/src/test/csf/timers.h @@ -26,10 +26,7 @@ class HeartbeatTimer SimTime startSimTime_; public: - HeartbeatTimer( - Scheduler& sched, - SimDuration interval = std::chrono::seconds{60}, - std::ostream& out = std::cerr) + HeartbeatTimer(Scheduler& sched, SimDuration interval = std::chrono::seconds{60}, std::ostream& out = std::cerr) : scheduler_{sched} , interval_{interval} , out_{out} @@ -53,10 +50,8 @@ public: RealDuration realDuration = realTime - startRealTime_; SimDuration simDuration = simTime - startSimTime_; - out_ << "Heartbeat. Time Elapsed: {sim: " - << duration_cast(simDuration).count() - << "s | real: " << duration_cast(realDuration).count() - << "s}\n" + out_ << "Heartbeat. Time Elapsed: {sim: " << duration_cast(simDuration).count() + << "s | real: " << duration_cast(realDuration).count() << "s}\n" << std::flush; scheduler_.in(interval_, [this]() { beat(scheduler_.now()); }); diff --git a/src/test/jtx/AMM.h b/src/test/jtx/AMM.h index 65c16ec627..54f5e94d03 100644 --- a/src/test/jtx/AMM.h +++ b/src/test/jtx/AMM.h @@ -142,11 +142,7 @@ public: ter const& ter, bool log = false, bool close = true); - AMM(Env& env, - Account const& account, - STAmount const& asset1, - STAmount const& asset2, - CreateArg const& arg); + AMM(Env& env, Account const& account, STAmount const& asset1, STAmount const& asset2, CreateArg const& arg); /** Send amm_info RPC command */ @@ -172,10 +168,7 @@ public: /** Get AMM balances for the token pair. */ std::tuple - balances( - Issue const& issue1, - Issue const& issue2, - std::optional const& account = std::nullopt) const; + balances(Issue const& issue1, Issue const& issue2, std::optional const& account = std::nullopt) const; std::tuple balances(std::optional const& account = std::nullopt) const @@ -192,10 +185,7 @@ public: * @param expectedPrice expected slot price */ [[nodiscard]] bool - expectAuctionSlot( - std::uint32_t fee, - std::optional timeSlot, - IOUAmount expectedPrice) const; + expectAuctionSlot(std::uint32_t fee, std::optional timeSlot, IOUAmount expectedPrice) const; [[nodiscard]] bool expectAuctionSlot(std::vector const& authAccount) const; @@ -263,11 +253,7 @@ public: std::optional const& ter = std::nullopt) { return withdraw( - account, - std::nullopt, - asset1OutDetails, - asset1OutDetails ? tfOneAssetWithdrawAll : tfWithdrawAll, - ter); + account, std::nullopt, asset1OutDetails, asset1OutDetails ? tfOneAssetWithdrawAll : tfWithdrawAll, ter); } IOUAmount @@ -327,8 +313,7 @@ public: } IOUAmount - getLPTokensBalance( - std::optional const& account = std::nullopt) const; + getLPTokensBalance(std::optional const& account = std::nullopt) const; friend std::ostream& operator<<(std::ostream& s, AMM const& amm) @@ -351,9 +336,7 @@ public: } void - ammDelete( - AccountID const& deleter, - std::optional const& ter = std::nullopt); + ammDelete(AccountID const& deleter, std::optional const& ter = std::nullopt); void setClose(bool close) @@ -368,9 +351,7 @@ public: } void - setTokens( - Json::Value& jv, - std::optional> const& assets = std::nullopt); + setTokens(Json::Value& jv, std::optional> const& assets = std::nullopt); private: AccountID @@ -403,17 +384,11 @@ private: } [[nodiscard]] bool - expectAmmInfo( - STAmount const& asset1, - STAmount const& asset2, - IOUAmount const& balance, - Json::Value const& jv) const; + expectAmmInfo(STAmount const& asset1, STAmount const& asset2, IOUAmount const& balance, Json::Value const& jv) + const; void - submit( - Json::Value const& jv, - std::optional const& seq, - std::optional const& ter); + submit(Json::Value const& jv, std::optional const& seq, std::optional const& ter); [[nodiscard]] bool expectAuctionSlot(auto&& cb) const; @@ -424,10 +399,7 @@ private: namespace amm { Json::Value -trust( - AccountID const& account, - STAmount const& amount, - std::uint32_t flags = 0); +trust(AccountID const& account, STAmount const& amount, std::uint32_t flags = 0); Json::Value pay(Account const& account, AccountID const& to, STAmount const& amount); diff --git a/src/test/jtx/AMMTest.h b/src/test/jtx/AMMTest.h index 208e3c4e5f..f468b0ebad 100644 --- a/src/test/jtx/AMMTest.h +++ b/src/test/jtx/AMMTest.h @@ -24,8 +24,7 @@ struct TestAMMArg std::vector features = { // For now, just disable SAV entirely, which locks in the small Number // mantissas - jtx::testable_amendments() - featureSingleAssetVault - - featureLendingProtocol}; + jtx::testable_amendments() - featureSingleAssetVault - featureLendingProtocol}; bool noLog = false; }; @@ -76,8 +75,7 @@ public: { // For now, just disable SAV entirely, which locks in the small Number // mantissas - return jtx::testable_amendments() - featureSingleAssetVault - - featureLendingProtocol; + return jtx::testable_amendments() - featureSingleAssetVault - featureLendingProtocol; } protected: @@ -93,9 +91,7 @@ protected: std::vector const& features = {testable_amendments()}); void - testAMM( - std::function&& cb, - TestAMMArg const& arg); + testAMM(std::function&& cb, TestAMMArg const& arg); }; class AMMTest : public jtx::AMMTestBase diff --git a/src/test/jtx/Account.h b/src/test/jtx/Account.h index af8870f22a..2f35d71a5c 100644 --- a/src/test/jtx/Account.h +++ b/src/test/jtx/Account.h @@ -40,18 +40,14 @@ public: /** @{ */ Account(std::string name, KeyType type = KeyType::secp256k1); - Account(char const* name, KeyType type = KeyType::secp256k1) - : Account(std::string(name), type) + Account(char const* name, KeyType type = KeyType::secp256k1) : Account(std::string(name), type) { } // This constructor needs to be public so `std::pair` can use it when // emplacing into the cache. However, it is logically `private`. This is // enforced with the `privateTag` parameter. - Account( - std::string name, - std::pair const& keys, - Account::privateCtorTag); + Account(std::string name, std::pair const& keys, Account::privateCtorTag); /** @} */ @@ -116,9 +112,7 @@ public: operator[](std::string const& s) const; private: - static std:: - unordered_map, Account, beast::uhash<>> - cache_; + static std::unordered_map, Account, beast::uhash<>> cache_; // Return the account from the cache & add it to the cache if needed static Account diff --git a/src/test/jtx/CaptureLogs.h b/src/test/jtx/CaptureLogs.h index 0ac855e402..89f207a2fc 100644 --- a/src/test/jtx/CaptureLogs.h +++ b/src/test/jtx/CaptureLogs.h @@ -27,27 +27,20 @@ class CaptureLogs : public Logs std::stringstream& strm_; public: - CaptureSink( - beast::severities::Severity threshold, - std::mutex& mutex, - std::stringstream& strm) - : beast::Journal::Sink(threshold, false) - , strmMutex_(mutex) - , strm_(strm) + CaptureSink(beast::severities::Severity threshold, std::mutex& mutex, std::stringstream& strm) + : beast::Journal::Sink(threshold, false), strmMutex_(mutex), strm_(strm) { } void - write(beast::severities::Severity level, std::string const& text) - override + write(beast::severities::Severity level, std::string const& text) override { std::lock_guard lock(strmMutex_); strm_ << text; } void - writeAlways(beast::severities::Severity level, std::string const& text) - override + writeAlways(beast::severities::Severity level, std::string const& text) override { std::lock_guard lock(strmMutex_); strm_ << text; @@ -55,8 +48,7 @@ class CaptureLogs : public Logs }; public: - explicit CaptureLogs(std::string* pResult) - : Logs(beast::severities::kInfo), pResult_(pResult) + explicit CaptureLogs(std::string* pResult) : Logs(beast::severities::kInfo), pResult_(pResult) { } @@ -66,9 +58,7 @@ public: } std::unique_ptr - makeSink( - std::string const& partition, - beast::severities::Severity threshold) override + makeSink(std::string const& partition, beast::severities::Severity threshold) override { return std::make_unique(threshold, strmMutex_, strm_); } diff --git a/src/test/jtx/CheckMessageLogs.h b/src/test/jtx/CheckMessageLogs.h index b0e5f4c82e..83aa73a337 100644 --- a/src/test/jtx/CheckMessageLogs.h +++ b/src/test/jtx/CheckMessageLogs.h @@ -18,24 +18,20 @@ class CheckMessageLogs : public Logs CheckMessageLogs& owner_; public: - CheckMessageSink( - beast::severities::Severity threshold, - CheckMessageLogs& owner) + CheckMessageSink(beast::severities::Severity threshold, CheckMessageLogs& owner) : beast::Journal::Sink(threshold, false), owner_(owner) { } void - write(beast::severities::Severity level, std::string const& text) - override + write(beast::severities::Severity level, std::string const& text) override { if (text.find(owner_.msg_) != std::string::npos) *owner_.pFound_ = true; } void - writeAlways(beast::severities::Severity level, std::string const& text) - override + writeAlways(beast::severities::Severity level, std::string const& text) override { write(level, text); } @@ -54,9 +50,7 @@ public: } std::unique_ptr - makeSink( - std::string const& partition, - beast::severities::Severity threshold) override + makeSink(std::string const& partition, beast::severities::Severity threshold) override { return std::make_unique(threshold, *this); } diff --git a/src/test/jtx/Env.h b/src/test/jtx/Env.h index 26a664efbd..1c07ac2d00 100644 --- a/src/test/jtx/Env.h +++ b/src/test/jtx/Env.h @@ -64,8 +64,7 @@ testable_amendments() if (auto const f = getRegisteredFeature(s)) feats.push_back(*f); else - Throw( - "Unknown feature: " + s + " in allAmendments."); + Throw("Unknown feature: " + s + " in allAmendments."); } return FeatureBitset(feats); }(); @@ -79,17 +78,14 @@ class SuiteLogs : public Logs beast::unit_test::suite& suite_; public: - explicit SuiteLogs(beast::unit_test::suite& suite) - : Logs(beast::severities::kError), suite_(suite) + explicit SuiteLogs(beast::unit_test::suite& suite) : Logs(beast::severities::kError), suite_(suite) { } ~SuiteLogs() override = default; std::unique_ptr - makeSink( - std::string const& partition, - beast::severities::Severity threshold) override + makeSink(std::string const& partition, beast::severities::Severity threshold) override { return std::make_unique(partition, threshold, suite_); } @@ -173,10 +169,7 @@ public: { memoize(Account::master); Pathfinder::initPathTable(); - foreachFeature( - features, [&appFeats = app().config().features](uint256 const& f) { - appFeats.insert(f); - }); + foreachFeature(features, [&appFeats = app().config().features](uint256 const& f) { appFeats.insert(f); }); } /** @@ -192,9 +185,7 @@ public: * @param args collection of features * */ - Env(beast::unit_test::suite& suite_, - FeatureBitset features, - std::unique_ptr logs = nullptr) + Env(beast::unit_test::suite& suite_, FeatureBitset features, std::unique_ptr logs = nullptr) : Env(suite_, envconfig(), features, std::move(logs)) { } @@ -215,11 +206,7 @@ public: std::unique_ptr config, std::unique_ptr logs = nullptr, beast::severities::Severity thresh = beast::severities::kError) - : Env(suite_, - std::move(config), - testable_amendments(), - std::move(logs), - thresh) + : Env(suite_, std::move(config), testable_amendments(), std::move(logs), thresh) { } @@ -232,8 +219,7 @@ public: * * @param suite_ the current unit_test::suite */ - Env(beast::unit_test::suite& suite_, - beast::severities::Severity thresh = beast::severities::kError) + Env(beast::unit_test::suite& suite_, beast::severities::Severity thresh = beast::severities::kError) : Env(suite_, envconfig(), nullptr, thresh) { } @@ -294,9 +280,7 @@ public: template Json::Value - rpc(std::unordered_map const& headers, - std::string const& cmd, - Args&&... args); + rpc(std::unordered_map const& headers, std::string const& cmd, Args&&... args); template Json::Value @@ -346,9 +330,7 @@ public: @return true if no error, false if error */ bool - close( - NetClock::time_point closeTime, - std::optional consensusDelay = std::nullopt); + close(NetClock::time_point closeTime, std::optional consensusDelay = std::nullopt); /** Close and advance the ledger. @@ -553,10 +535,7 @@ public: of JTx submission. */ void - postconditions( - JTx const& jt, - ParsedResult const& parsed, - Json::Value const& jr = Json::Value()); + postconditions(JTx const& jt, ParsedResult const& parsed, Json::Value const& jr = Json::Value()); /** Apply funclets and submit. */ /** @{ */ @@ -700,11 +679,7 @@ public: template void - trust( - STAmount const& amount, - Account const& to0, - Account const& to1, - Accounts const&... toN) + trust(STAmount const& amount, Account const& to0, Account const& to1, Accounts const&... toN) { trust(amount, to0); trust(amount, to1, toN...); @@ -777,44 +752,28 @@ Env::rpc( std::string const& cmd, Args&&... args) { - return do_rpc( - apiVersion, - std::vector{cmd, std::forward(args)...}, - headers); + return do_rpc(apiVersion, std::vector{cmd, std::forward(args)...}, headers); } template Json::Value Env::rpc(unsigned apiVersion, std::string const& cmd, Args&&... args) { - return rpc( - apiVersion, - std::unordered_map(), - cmd, - std::forward(args)...); + return rpc(apiVersion, std::unordered_map(), cmd, std::forward(args)...); } template Json::Value -Env::rpc( - std::unordered_map const& headers, - std::string const& cmd, - Args&&... args) +Env::rpc(std::unordered_map const& headers, std::string const& cmd, Args&&... args) { - return do_rpc( - RPC::apiCommandLineVersion, - std::vector{cmd, std::forward(args)...}, - headers); + return do_rpc(RPC::apiCommandLineVersion, std::vector{cmd, std::forward(args)...}, headers); } template Json::Value Env::rpc(std::string const& cmd, Args&&... args) { - return rpc( - std::unordered_map(), - cmd, - std::forward(args)...); + return rpc(std::unordered_map(), cmd, std::forward(args)...); } } // namespace jtx diff --git a/src/test/jtx/Env_test.cpp b/src/test/jtx/Env_test.cpp index fbe51c2a8d..0f43691b86 100644 --- a/src/test/jtx/Env_test.cpp +++ b/src/test/jtx/Env_test.cpp @@ -61,18 +61,10 @@ public: PrettyAmount(0u); PrettyAmount(1u); PrettyAmount(-1); - static_assert( - !std::is_trivially_constructible::value, ""); - static_assert( - !std::is_trivially_constructible:: - value, - ""); - static_assert( - !std::is_trivially_constructible::value, ""); - static_assert( - !std::is_trivially_constructible:: - value, - ""); + static_assert(!std::is_trivially_constructible::value, ""); + static_assert(!std::is_trivially_constructible::value, ""); + static_assert(!std::is_trivially_constructible::value, ""); + static_assert(!std::is_trivially_constructible::value, ""); try { @@ -139,11 +131,7 @@ public: // unfunded { Env env(*this); - env(pay("alice", "bob", XRP(1000)), - seq(1), - fee(10), - sig("alice"), - ter(terNO_ACCOUNT)); + env(pay("alice", "bob", XRP(1000)), seq(1), fee(10), sig("alice"), ter(terNO_ACCOUNT)); } // fund @@ -187,8 +175,7 @@ public: env.trust(USD(1000), alice); env(pay(gw, alice, USD(10))); BEAST_EXPECT(to_string(env.balance("alice", USD)) == "10/USD(gw)"); - BEAST_EXPECT( - to_string(env.balance(gw, alice["USD"])) == "-10/USD(alice)"); + BEAST_EXPECT(to_string(env.balance(gw, alice["USD"])) == "-10/USD(alice)"); } // seq @@ -234,10 +221,8 @@ public: env(pay(gw, "alice", USD(10)), require(balance("alice", USD(10)))); env.require(nflags("alice", asfRequireDest)); - env(fset("alice", asfRequireDest), - require(flags("alice", asfRequireDest))); - env(fclear("alice", asfRequireDest), - require(nflags("alice", asfRequireDest))); + env(fset("alice", asfRequireDest), require(flags("alice", asfRequireDest))); + env(fclear("alice", asfRequireDest), require(nflags("alice", asfRequireDest))); } // Signing with secp256k1 and ed25519 keys @@ -256,9 +241,7 @@ public: env(noop(alice)); env(noop(bob)); env(noop(alice), sig("alice"), ter(tefBAD_AUTH)); - env(noop(alice), - sig(Account("alice", KeyType::secp256k1)), - ter(tefBAD_AUTH)); + env(noop(alice), sig(Account("alice", KeyType::secp256k1)), ter(tefBAD_AUTH)); env(noop(bob), sig(Account("bob", KeyType::ed25519)), ter(tefBAD_AUTH)); env(noop(alice), sig(carol), ter(tefBAD_AUTH)); @@ -273,9 +256,7 @@ public: env(noop(alice)); env(noop(alice), sig(bob)); env(noop(alice), sig(alice), ter(tefMASTER_DISABLED)); - env(fclear(alice, asfDisableMaster), - sig(alice), - ter(tefMASTER_DISABLED)); + env(fclear(alice, asfDisableMaster), sig(alice), ter(tefMASTER_DISABLED)); env(fclear(alice, asfDisableMaster), sig(bob)); env(noop(alice), sig(alice)); } @@ -314,10 +295,7 @@ public: env(offer("carol", XRP(50), USD(50)), require(owners("carol", 2))); env(pay("alice", "bob", any(USD(10))), ter(tecPATH_DRY)); - env(pay("alice", "bob", any(USD(10))), - paths(XRP), - sendmax(XRP(10)), - ter(tecPATH_PARTIAL)); + env(pay("alice", "bob", any(USD(10))), paths(XRP), sendmax(XRP(10)), ter(tecPATH_PARTIAL)); env(pay("alice", "bob", any(USD(10))), paths(XRP), sendmax(XRP(20))); env.require(balance("bob", USD(10))); env.require(balance("carol", USD(39.5))); @@ -329,9 +307,7 @@ public: env(noop("alice"), sig("eric")); env(noop("alice"), sig("bob"), ter(tefBAD_AUTH)); env(fset("alice", asfDisableMaster), ter(tecNEED_MASTER_KEY)); - env(fset("alice", asfDisableMaster), - sig("eric"), - ter(tecNEED_MASTER_KEY)); + env(fset("alice", asfDisableMaster), sig("eric"), ter(tecNEED_MASTER_KEY)); env.require(nflags("alice", asfDisableMaster)); env(fset("alice", asfDisableMaster), sig("alice")); env.require(flags("alice", asfDisableMaster)); @@ -341,9 +317,7 @@ public: env(noop("alice"), sig("eric")); env(noop("alice"), sig("bob"), ter(tefBAD_AUTH)); env(fclear("alice", asfDisableMaster), sig("bob"), ter(tefBAD_AUTH)); - env(fclear("alice", asfDisableMaster), - sig("alice"), - ter(tefMASTER_DISABLED)); + env(fclear("alice", asfDisableMaster), sig("alice"), ter(tefMASTER_DISABLED)); env(fclear("alice", asfDisableMaster)); env.require(nflags("alice", asfDisableMaster)); env(regkey("alice", disabled)); @@ -366,8 +340,7 @@ public: env.fund(XRP(10000), alice); auto const localTxCnt = env.app().getOPs().getLocalTxCount(); - auto const queueTxCount = - env.app().getTxQ().getMetrics(*env.current()).txCount; + auto const queueTxCount = env.app().getTxQ().getMetrics(*env.current()).txCount; auto const openTxCount = env.current()->txCount(); BEAST_EXPECT(localTxCnt == 2 && queueTxCount == 0 && openTxCount == 2); @@ -387,46 +360,35 @@ public: auto jr = applyTxn(noop(alice), fee(1)); BEAST_EXPECT(jr[jss::result][jss::engine_result] == "telINSUF_FEE_P"); - BEAST_EXPECT( - env.app().getTxQ().getMetrics(*env.current()).txCount == - queueTxCount); + BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount); BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt); BEAST_EXPECT(env.current()->txCount() == openTxCount); jr = applyTxn(noop(alice), sig("bob")); BEAST_EXPECT(jr[jss::result][jss::engine_result] == "tefBAD_AUTH"); - BEAST_EXPECT( - env.app().getTxQ().getMetrics(*env.current()).txCount == - queueTxCount); + BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount); BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt); BEAST_EXPECT(env.current()->txCount() == openTxCount); jr = applyTxn(noop(alice), seq(20)); BEAST_EXPECT(jr[jss::result][jss::engine_result] == "terPRE_SEQ"); - BEAST_EXPECT( - env.app().getTxQ().getMetrics(*env.current()).txCount == - queueTxCount); + BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount); BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt); BEAST_EXPECT(env.current()->txCount() == openTxCount); jr = applyTxn(offer(alice, XRP(1000), USD(1000))); - BEAST_EXPECT( - jr[jss::result][jss::engine_result] == "tecUNFUNDED_OFFER"); - BEAST_EXPECT( - env.app().getTxQ().getMetrics(*env.current()).txCount == - queueTxCount); + BEAST_EXPECT(jr[jss::result][jss::engine_result] == "tecUNFUNDED_OFFER"); + BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount); BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt); BEAST_EXPECT(env.current()->txCount() == openTxCount); jr = applyTxn(noop(alice), fee(drops(-10))); BEAST_EXPECT(jr[jss::result][jss::engine_result] == "temBAD_FEE"); - BEAST_EXPECT( - env.app().getTxQ().getMetrics(*env.current()).txCount == - queueTxCount); + BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount); BEAST_EXPECT(env.app().getOPs().getLocalTxCount() == localTxCnt); BEAST_EXPECT(env.current()->txCount() == openTxCount); @@ -445,8 +407,7 @@ public: Env env(*this); env.fund(XRP(10000), "alice"); - env(signers("alice", 1, {{"alice", 1}, {"bob", 2}}), - ter(temBAD_SIGNER)); + env(signers("alice", 1, {{"alice", 1}, {"bob", 2}}), ter(temBAD_SIGNER)); env(signers("alice", 1, {{"bob", 1}, {"carol", 2}})); env(noop("alice")); @@ -454,10 +415,7 @@ public: env(noop("alice"), msig("bob"), fee(2 * baseFee)); env(noop("alice"), msig("carol"), fee(2 * baseFee)); env(noop("alice"), msig("bob", "carol"), fee(3 * baseFee)); - env(noop("alice"), - msig("bob", "carol", "dilbert"), - fee(4 * baseFee), - ter(tefBAD_SIGNATURE)); + env(noop("alice"), msig("bob", "carol", "dilbert"), fee(4 * baseFee), ter(tefBAD_SIGNATURE)); env(signers("alice", none)); } @@ -472,10 +430,8 @@ public: { Env env(*this); env.fund(XRP(10000), "alice"); - env(noop("alice"), - require(owners("alice", 0), tickets("alice", 0))); - env(ticket::create("alice", 1), - require(owners("alice", 1), tickets("alice", 1))); + env(noop("alice"), require(owners("alice", 0), tickets("alice", 0))); + env(ticket::create("alice", 1), require(owners("alice", 1), tickets("alice", 1))); } } @@ -531,10 +487,7 @@ public: auto jt2 = env.jt(noop("alice"), prop(-1)); BEAST_EXPECT(jt2.get()); BEAST_EXPECT(*jt2.get() == 65535); - auto jt3 = env.jt( - noop("alice"), - prop("Hello, world!"), - prop(false)); + auto jt3 = env.jt(noop("alice"), prop("Hello, world!"), prop(false)); BEAST_EXPECT(jt3.get()); BEAST_EXPECT(*jt3.get() == "Hello, world!"); BEAST_EXPECT(jt3.get()); @@ -600,9 +553,7 @@ public: env(noop("alice"), memo_format("format")); env(noop("alice"), memo_type("type")); env(noop("alice"), memo("data", "format", "type")); - env(noop("alice"), - memo("data1", "format1", "type1"), - memo("data2", "format2", "type2")); + env(noop("alice"), memo("data1", "format1", "type1"), memo("data2", "format2", "type2")); } void @@ -614,12 +565,9 @@ public: memo("data", "format", "type")(env, jt); auto const& memo = jt.jv["Memos"][0u]["Memo"]; - BEAST_EXPECT( - memo["MemoData"].asString() == strHex(std::string("data"))); - BEAST_EXPECT( - memo["MemoFormat"].asString() == strHex(std::string("format"))); - BEAST_EXPECT( - memo["MemoType"].asString() == strHex(std::string("type"))); + BEAST_EXPECT(memo["MemoData"].asString() == strHex(std::string("data"))); + BEAST_EXPECT(memo["MemoFormat"].asString() == strHex(std::string("format"))); + BEAST_EXPECT(memo["MemoType"].asString() == strHex(std::string("type"))); } void @@ -684,8 +632,7 @@ public: std::uint32_t const aliceSeq = env.seq("alice"); // Sign jsonNoop. - Json::Value jsonNoop = - env.json(noop("alice"), fee(baseFee), seq(aliceSeq), sig("alice")); + Json::Value jsonNoop = env.json(noop("alice"), fee(baseFee), seq(aliceSeq), sig("alice")); // Re-sign jsonNoop. JTx jt = env.jt(jsonNoop); env(jt); @@ -734,15 +681,9 @@ public: params[jss::fee_mult_max] = 1; params[jss::fee_div_max] = 2; - auto const expectedErrorString = "Fee of " + - std::to_string(baseFee.drops()) + - " exceeds the requested tx limit of " + - std::to_string(baseFee.drops() / 2); - envs( - noop(alice), - fee(none), - seq(none), - rpc(rpcHIGH_FEE, expectedErrorString))(params); + auto const expectedErrorString = "Fee of " + std::to_string(baseFee.drops()) + + " exceeds the requested tx limit of " + std::to_string(baseFee.drops() / 2); + envs(noop(alice), fee(none), seq(none), rpc(rpcHIGH_FEE, expectedErrorString))(params); auto tx = env.tx(); BEAST_EXPECT(!tx); @@ -771,51 +712,40 @@ public: if (!neverSupportedFeat) { - log << "No unsupported features found - skipping test." - << std::endl; + log << "No unsupported features found - skipping test." << std::endl; pass(); return; } auto hasFeature = [](Env& env, uint256 const& f) { - return ( - env.app().config().features.find(f) != - env.app().config().features.end()); + return (env.app().config().features.find(f) != env.app().config().features.end()); }; { // default Env has all supported features Env env{*this}; - BEAST_EXPECT( - supported.count() == env.app().config().features.size()); - foreachFeature(supported, [&](uint256 const& f) { - this->BEAST_EXPECT(hasFeature(env, f)); - }); + BEAST_EXPECT(supported.count() == env.app().config().features.size()); + foreachFeature(supported, [&](uint256 const& f) { this->BEAST_EXPECT(hasFeature(env, f)); }); } { // a Env FeatureBitset has *only* those features - Env env{ - *this, FeatureBitset{featureDynamicMPT | featureTokenEscrow}}; + Env env{*this, FeatureBitset{featureDynamicMPT | featureTokenEscrow}}; BEAST_EXPECT(env.app().config().features.size() == 2); foreachFeature(supported, [&](uint256 const& f) { - bool const has = - (f == featureDynamicMPT || f == featureTokenEscrow); + bool const has = (f == featureDynamicMPT || f == featureTokenEscrow); this->BEAST_EXPECT(has == hasFeature(env, f)); }); } - auto const missingSomeFeatures = - testable_amendments() - featureDynamicMPT - featureTokenEscrow; + auto const missingSomeFeatures = testable_amendments() - featureDynamicMPT - featureTokenEscrow; BEAST_EXPECT(missingSomeFeatures.count() == (supported.count() - 2)); { // a Env supported_features_except is missing *only* those features Env env{*this, missingSomeFeatures}; - BEAST_EXPECT( - env.app().config().features.size() == (supported.count() - 2)); + BEAST_EXPECT(env.app().config().features.size() == (supported.count() - 2)); foreachFeature(supported, [&](uint256 const& f) { - bool hasnot = - (f == featureDynamicMPT || f == featureTokenEscrow); + bool hasnot = (f == featureDynamicMPT || f == featureTokenEscrow); this->BEAST_EXPECT(hasnot != hasFeature(env, f)); }); } @@ -825,12 +755,7 @@ public: // along with a list of explicit amendments // the unsupported feature should be enabled along with // the two supported ones - Env env{ - *this, - FeatureBitset{ - featureDynamicMPT, - featureTokenEscrow, - *neverSupportedFeat}}; + Env env{*this, FeatureBitset{featureDynamicMPT, featureTokenEscrow, *neverSupportedFeat}}; // this app will have just 2 supported amendments and // one additional never supported feature flag @@ -847,19 +772,14 @@ public: // add a feature that is NOT in the supported amendments list // and omit a few standard amendments // the unsupported features should be enabled - Env env{ - *this, - missingSomeFeatures | FeatureBitset{*neverSupportedFeat}}; + Env env{*this, missingSomeFeatures | FeatureBitset{*neverSupportedFeat}}; // this app will have all supported amendments minus 2 and then the // one additional never supported feature flag - BEAST_EXPECT( - env.app().config().features.size() == - (supported.count() - 2 + 1)); + BEAST_EXPECT(env.app().config().features.size() == (supported.count() - 2 + 1)); BEAST_EXPECT(hasFeature(env, *neverSupportedFeat)); foreachFeature(supported, [&](uint256 const& f) { - bool hasnot = - (f == featureDynamicMPT || f == featureTokenEscrow); + bool hasnot = (f == featureDynamicMPT || f == featureTokenEscrow); this->BEAST_EXPECT(hasnot != hasFeature(env, f)); }); } @@ -872,12 +792,9 @@ public: // this app will have all supported amendments and then the // one additional never supported feature flag - BEAST_EXPECT( - env.app().config().features.size() == (supported.count() + 1)); + BEAST_EXPECT(env.app().config().features.size() == (supported.count() + 1)); BEAST_EXPECT(hasFeature(env, *neverSupportedFeat)); - foreachFeature(supported, [&](uint256 const& f) { - this->BEAST_EXPECT(hasFeature(env, f)); - }); + foreachFeature(supported, [&](uint256 const& f) { this->BEAST_EXPECT(hasFeature(env, f)); }); } } diff --git a/src/test/jtx/JTx.h b/src/test/jtx/JTx.h index aa87ce333d..1568df5f18 100644 --- a/src/test/jtx/JTx.h +++ b/src/test/jtx/JTx.h @@ -28,8 +28,7 @@ struct JTx requires_t require; std::optional ter = TER{tesSUCCESS}; std::optional> rpcCode = std::nullopt; - std::optional>> - rpcException = std::nullopt; + std::optional>> rpcException = std::nullopt; bool fill_fee = true; bool fill_seq = true; bool fill_sig = true; diff --git a/src/test/jtx/Oracle.h b/src/test/jtx/Oracle.h index 17d72384f6..6d993c436e 100644 --- a/src/test/jtx/Oracle.h +++ b/src/test/jtx/Oracle.h @@ -11,8 +11,7 @@ namespace jtx { namespace oracle { using AnyValue = std::variant; -using OraclesData = - std::vector, std::optional>>; +using OraclesData = std::vector, std::optional>>; // Special string value, which is converted to unquoted string in the string // passed to rpc. @@ -33,11 +32,8 @@ void toJsonHex(Json::Value& jv, AnyValue const& v); // base asset, quote asset, price, scale -using DataSeries = std::vector, - std::optional>>; +using DataSeries = + std::vector, std::optional>>; // Typical defaults for Create struct CreateArg @@ -90,8 +86,7 @@ struct RemoveArg // The value doesn't matter much, it has to be greater // than maxLastUpdateTimeDelta in order to pass LastUpdateTime // validation {close-maxLastUpdateTimeDelta,close+maxLastUpdateTimeDelta}. -constexpr static std::chrono::seconds testStartTime = - epoch_offset + std::chrono::seconds(10'000); +constexpr static std::chrono::seconds testStartTime = epoch_offset + std::chrono::seconds(10'000); /** Oracle class facilitates unit-testing of the Price Oracle feature. * It defines functions to create, update, and delete the Oracle object, diff --git a/src/test/jtx/PathSet.h b/src/test/jtx/PathSet.h index 0c54b6fb77..fe96a9884a 100644 --- a/src/test/jtx/PathSet.h +++ b/src/test/jtx/PathSet.h @@ -12,49 +12,33 @@ namespace test { /** Count offer */ inline std::size_t -countOffers( - jtx::Env& env, - jtx::Account const& account, - Issue const& takerPays, - Issue const& takerGets) +countOffers(jtx::Env& env, jtx::Account const& account, Issue const& takerPays, Issue const& takerGets) { size_t count = 0; - forEachItem( - *env.current(), account, [&](std::shared_ptr const& sle) { - if (sle->getType() == ltOFFER && - sle->getFieldAmount(sfTakerPays).issue() == takerPays && - sle->getFieldAmount(sfTakerGets).issue() == takerGets) - ++count; - }); + forEachItem(*env.current(), account, [&](std::shared_ptr const& sle) { + if (sle->getType() == ltOFFER && sle->getFieldAmount(sfTakerPays).issue() == takerPays && + sle->getFieldAmount(sfTakerGets).issue() == takerGets) + ++count; + }); return count; } inline std::size_t -countOffers( - jtx::Env& env, - jtx::Account const& account, - STAmount const& takerPays, - STAmount const& takerGets) +countOffers(jtx::Env& env, jtx::Account const& account, STAmount const& takerPays, STAmount const& takerGets) { size_t count = 0; - forEachItem( - *env.current(), account, [&](std::shared_ptr const& sle) { - if (sle->getType() == ltOFFER && - sle->getFieldAmount(sfTakerPays) == takerPays && - sle->getFieldAmount(sfTakerGets) == takerGets) - ++count; - }); + forEachItem(*env.current(), account, [&](std::shared_ptr const& sle) { + if (sle->getType() == ltOFFER && sle->getFieldAmount(sfTakerPays) == takerPays && + sle->getFieldAmount(sfTakerGets) == takerGets) + ++count; + }); return count; } /** An offer exists */ inline bool -isOffer( - jtx::Env& env, - jtx::Account const& account, - STAmount const& takerPays, - STAmount const& takerGets) +isOffer(jtx::Env& env, jtx::Account const& account, STAmount const& takerPays, STAmount const& takerGets) { return countOffers(env, account, takerPays, takerGets) > 0; } @@ -62,11 +46,7 @@ isOffer( /** An offer exists */ inline bool -isOffer( - jtx::Env& env, - jtx::Account const& account, - Issue const& takerPays, - Issue const& takerGets) +isOffer(jtx::Env& env, jtx::Account const& account, Issue const& takerPays, Issue const& takerGets) { return countOffers(env, account, takerPays, takerGets) > 0; } @@ -114,11 +94,7 @@ Path::push_back(STPathElement const& pe) inline Path& Path::push_back(Issue const& iss) { - path.emplace_back( - STPathElement::typeCurrency | STPathElement::typeIssuer, - beast::zero, - iss.currency, - iss.account); + path.emplace_back(STPathElement::typeCurrency | STPathElement::typeIssuer, beast::zero, iss.currency, iss.account); return *this; } diff --git a/src/test/jtx/SignerUtils.h b/src/test/jtx/SignerUtils.h index 272909c887..4c0218f6b4 100644 --- a/src/test/jtx/SignerUtils.h +++ b/src/test/jtx/SignerUtils.h @@ -18,8 +18,7 @@ struct Reg { } - Reg(Account const& acct_, Account const& regularSig) - : acct(acct_), sig(regularSig) + Reg(Account const& acct_, Account const& regularSig) : acct(acct_), sig(regularSig) { } @@ -27,8 +26,7 @@ struct Reg { } - Reg(char const* acct_, char const* regularSig) - : acct(acct_), sig(regularSig) + Reg(char const* acct_, char const* regularSig) : acct(acct_), sig(regularSig) { } @@ -43,10 +41,7 @@ struct Reg inline void sortSigners(std::vector& signers) { - std::sort( - signers.begin(), signers.end(), [](Reg const& lhs, Reg const& rhs) { - return lhs.acct < rhs.acct; - }); + std::sort(signers.begin(), signers.end(), [](Reg const& lhs, Reg const& rhs) { return lhs.acct < rhs.acct; }); } } // namespace jtx diff --git a/src/test/jtx/TestHelpers.h b/src/test/jtx/TestHelpers.h index 8149c2d464..ccf270867c 100644 --- a/src/test/jtx/TestHelpers.h +++ b/src/test/jtx/TestHelpers.h @@ -27,10 +27,7 @@ namespace jtx { Not every helper will be able to use this because of conversions and other issues, but for classes where it's straightforward, this can simplify things. */ -template < - class SField, - class StoredValue = typename SField::type::value_type, - class OutputValue = StoredValue> +template struct JTxField { using SF = SField; @@ -42,8 +39,7 @@ protected: SV value_; public: - explicit JTxField(SF const& sfield, SV const& value) - : sfield_(sfield), value_(value) + explicit JTxField(SF const& sfield, SV const& value) : sfield_(sfield), value_(value) { } @@ -71,8 +67,7 @@ protected: SV value_; public: - explicit JTxField(SF const& sfield, SV const& value) - : sfield_(sfield), value_(value) + explicit JTxField(SF const& sfield, SV const& value) : sfield_(sfield), value_(value) { } @@ -83,8 +78,7 @@ public: } }; -struct timePointField - : public JTxField +struct timePointField : public JTxField { using SF = SF_UINT32; using SV = NetClock::time_point; @@ -95,8 +89,7 @@ protected: using base::value_; public: - explicit timePointField(SF const& sfield, SV const& value) - : JTxField(sfield, value) + explicit timePointField(SF const& sfield, SV const& value) : JTxField(sfield, value) { } @@ -118,8 +111,7 @@ protected: using base::value_; public: - explicit uint256Field(SF const& sfield, SV const& value) - : JTxField(sfield, value) + explicit uint256Field(SF const& sfield, SV const& value) : JTxField(sfield, value) { } @@ -141,8 +133,7 @@ protected: using base::value_; public: - explicit accountIDField(SF const& sfield, SV const& value) - : JTxField(sfield, value) + explicit accountIDField(SF const& sfield, SV const& value) : JTxField(sfield, value) { } @@ -164,8 +155,7 @@ protected: using base::value_; public: - explicit stAmountField(SF const& sfield, SV const& value) - : JTxField(sfield, value) + explicit stAmountField(SF const& sfield, SV const& value) : JTxField(sfield, value) { } @@ -184,21 +174,18 @@ struct blobField : public JTxField using JTxField::JTxField; - explicit blobField(SF const& sfield, Slice const& cond) - : JTxField(sfield, strHex(cond)) + explicit blobField(SF const& sfield, Slice const& cond) : JTxField(sfield, strHex(cond)) { } template - explicit blobField(SF const& sfield, std::array const& c) - : blobField(sfield, makeSlice(c)) + explicit blobField(SF const& sfield, std::array const& c) : blobField(sfield, makeSlice(c)) { } }; template -struct valueUnitField - : public JTxField, ValueType> +struct valueUnitField : public JTxField, ValueType> { using SF = SField; using SV = unit::ValueUnit; @@ -277,12 +264,8 @@ public: } }; -template < - class SField, - class UnitTag, - class ValueType = typename SField::type::value_type> -using valueUnitWrapper = - JTxFieldWrapper>; +template +using valueUnitWrapper = JTxFieldWrapper>; template using simpleField = JTxFieldWrapper>; @@ -371,10 +354,7 @@ checkVL(Slice const& result, std::string const& expected) [[nodiscard]] inline bool -checkVL( - std::shared_ptr const& sle, - SField const& field, - std::string const& expected) +checkVL(std::shared_ptr const& sle, SField const& field, std::string const& expected) { return strHex(expected) == strHex(sle->getFieldVL(field)); } @@ -454,52 +434,32 @@ PrettyAmount xrpMinusFee(Env const& env, std::int64_t xrpAmount); bool -expectHolding( - Env& env, - AccountID const& account, - STAmount const& value, - bool defaultLimits = false); +expectHolding(Env& env, AccountID const& account, STAmount const& value, bool defaultLimits = false); template bool -expectHolding( - Env& env, - AccountID const& account, - STAmount const& value, - Amts const&... amts) +expectHolding(Env& env, AccountID const& account, STAmount const& value, Amts const&... amts) { - return expectHolding(env, account, value, false) && - expectHolding(env, account, amts...); + return expectHolding(env, account, value, false) && expectHolding(env, account, amts...); } bool expectHolding(Env& env, AccountID const& account, None const& value); bool -expectOffers( - Env& env, - AccountID const& account, - std::uint16_t size, - std::vector const& toMatch = {}); +expectOffers(Env& env, AccountID const& account, std::uint16_t size, std::vector const& toMatch = {}); Json::Value ledgerEntryRoot(Env& env, Account const& acct); Json::Value -ledgerEntryState( - Env& env, - Account const& acct_a, - Account const& acct_b, - std::string const& currency); +ledgerEntryState(Env& env, Account const& acct_a, Account const& acct_b, std::string const& currency); Json::Value accountBalance(Env& env, Account const& acct); [[nodiscard]] bool -expectLedgerEntryRoot( - Env& env, - Account const& acct, - STAmount const& expectedValue); +expectLedgerEntryRoot(Env& env, Account const& acct, STAmount const& expectedValue); /* Payment Channel */ /******************************************************************************/ @@ -525,8 +485,7 @@ create( std::optional const& cancelAfter = std::nullopt, std::optional const& dstTag = std::nullopt) { - return create( - account.id(), to.id(), amount, settleDelay, pk, cancelAfter, dstTag); + return create(account.id(), to.id(), amount, settleDelay, pk, cancelAfter, dstTag); } Json::Value @@ -546,10 +505,7 @@ claim( std::optional const& pk = std::nullopt); uint256 -channel( - AccountID const& account, - AccountID const& dst, - std::uint32_t seqProxyValue); +channel(AccountID const& account, AccountID const& dst, std::uint32_t seqProxyValue); inline uint256 channel(Account const& account, Account const& dst, std::uint32_t seqProxyValue) @@ -569,12 +525,7 @@ channelExists(ReadView const& view, uint256 const& chan); /******************************************************************************/ void -n_offers( - Env& env, - std::size_t n, - Account const& account, - STAmount const& in, - STAmount const& out); +n_offers(Env& env, std::size_t n, Account const& account, STAmount const& in, STAmount const& out); /* Pay Strand */ /***************************************************************/ @@ -609,10 +560,7 @@ create(A const& account, A const& dest, STAmount const& sendMax) // clang-format on inline Json::Value -create( - jtx::Account const& account, - jtx::Account const& dest, - STAmount const& sendMax) +create(jtx::Account const& account, jtx::Account const& dest, STAmount const& sendMax) { return create(account.id(), dest.id(), sendMax); } @@ -642,74 +590,61 @@ checkMetrics( auto const metrics = env.app().getTxQ().getMetrics(*env.current()); using namespace std::string_literals; - metrics.referenceFeeLevel == baseFeeLevel - ? test.pass() - : test.fail( - "reference: "s + - std::to_string(metrics.referenceFeeLevel.value()) + "/" + - std::to_string(baseFeeLevel.value()), - file, - line); + metrics.referenceFeeLevel == baseFeeLevel ? test.pass() + : test.fail( + "reference: "s + std::to_string(metrics.referenceFeeLevel.value()) + + "/" + std::to_string(baseFeeLevel.value()), + file, + line); metrics.txCount == expectedCount ? test.pass() - : test.fail( - "txCount: "s + std::to_string(metrics.txCount) + "/" + - std::to_string(expectedCount), - file, - line); + : test.fail("txCount: "s + std::to_string(metrics.txCount) + "/" + std::to_string(expectedCount), file, line); - metrics.txQMaxSize == expectedMaxCount - ? test.pass() - : test.fail( - "txQMaxSize: "s + std::to_string(metrics.txQMaxSize.value_or(0)) + - "/" + std::to_string(expectedMaxCount.value_or(0)), - file, - line); + metrics.txQMaxSize == expectedMaxCount ? test.pass() + : test.fail( + "txQMaxSize: "s + std::to_string(metrics.txQMaxSize.value_or(0)) + + "/" + std::to_string(expectedMaxCount.value_or(0)), + file, + line); metrics.txInLedger == expectedInLedger ? test.pass() : test.fail( - "txInLedger: "s + std::to_string(metrics.txInLedger) + "/" + - std::to_string(expectedInLedger), + "txInLedger: "s + std::to_string(metrics.txInLedger) + "/" + std::to_string(expectedInLedger), file, line); metrics.txPerLedger == expectedPerLedger ? test.pass() : test.fail( - "txPerLedger: "s + std::to_string(metrics.txPerLedger) + "/" + - std::to_string(expectedPerLedger), + "txPerLedger: "s + std::to_string(metrics.txPerLedger) + "/" + std::to_string(expectedPerLedger), file, line); metrics.minProcessingFeeLevel == expectedMin ? test.pass() : test.fail( - "minProcessingFeeLevel: "s + - std::to_string(metrics.minProcessingFeeLevel.value()) + "/" + + "minProcessingFeeLevel: "s + std::to_string(metrics.minProcessingFeeLevel.value()) + "/" + std::to_string(expectedMin.value()), file, line); - metrics.medFeeLevel == expectedMed - ? test.pass() - : test.fail( - "medFeeLevel: "s + std::to_string(metrics.medFeeLevel.value()) + - "/" + std::to_string(expectedMed.value()), - file, - line); + metrics.medFeeLevel == expectedMed ? test.pass() + : test.fail( + "medFeeLevel: "s + std::to_string(metrics.medFeeLevel.value()) + "/" + + std::to_string(expectedMed.value()), + file, + line); auto const expectedCurFeeLevel = expectedInLedger > expectedPerLedger - ? expectedMed * expectedInLedger * expectedInLedger / - (expectedPerLedger * expectedPerLedger) + ? expectedMed * expectedInLedger * expectedInLedger / (expectedPerLedger * expectedPerLedger) : metrics.referenceFeeLevel; metrics.openLedgerFeeLevel == expectedCurFeeLevel ? test.pass() : test.fail( - "openLedgerFeeLevel: "s + - std::to_string(metrics.openLedgerFeeLevel.value()) + "/" + + "openLedgerFeeLevel: "s + std::to_string(metrics.openLedgerFeeLevel.value()) + "/" + std::to_string(expectedCurFeeLevel.value()), file, line); @@ -728,18 +663,10 @@ Json::Value del(AccountID const& account, uint256 const& brokerID, std::uint32_t flags = 0); Json::Value -coverDeposit( - AccountID const& account, - uint256 const& brokerID, - STAmount const& amount, - std::uint32_t flags = 0); +coverDeposit(AccountID const& account, uint256 const& brokerID, STAmount const& amount, std::uint32_t flags = 0); Json::Value -coverWithdraw( - AccountID const& account, - uint256 const& brokerID, - STAmount const& amount, - std::uint32_t flags = 0); +coverWithdraw(AccountID const& account, uint256 const& brokerID, STAmount const& amount, std::uint32_t flags = 0); // Must specify at least one of loanBrokerID or amount. Json::Value @@ -747,16 +674,13 @@ coverClawback(AccountID const& account, std::uint32_t flags = 0); auto const loanBrokerID = JTxFieldWrapper(sfLoanBrokerID); -auto const managementFeeRate = - valueUnitWrapper(sfManagementFeeRate); +auto const managementFeeRate = valueUnitWrapper(sfManagementFeeRate); auto const debtMaximum = simpleField(sfDebtMaximum); -auto const coverRateMinimum = - valueUnitWrapper(sfCoverRateMinimum); +auto const coverRateMinimum = valueUnitWrapper(sfCoverRateMinimum); -auto const coverRateLiquidation = - valueUnitWrapper(sfCoverRateLiquidation); +auto const coverRateLiquidation = valueUnitWrapper(sfCoverRateLiquidation); auto const destination = JTxFieldWrapper(sfDestination); @@ -767,10 +691,7 @@ auto const destination = JTxFieldWrapper(sfDestination); namespace loan { Json::Value -set(AccountID const& account, - uint256 const& loanBrokerID, - Number principalRequested, - std::uint32_t flags = 0); +set(AccountID const& account, uint256 const& loanBrokerID, Number principalRequested, std::uint32_t flags = 0); auto const counterparty = JTxFieldWrapper(sfCounterparty); @@ -784,20 +705,15 @@ auto const latePaymentFee = simpleField(sfLatePaymentFee); auto const closePaymentFee = simpleField(sfClosePaymentFee); -auto const overpaymentFee = - valueUnitWrapper(sfOverpaymentFee); +auto const overpaymentFee = valueUnitWrapper(sfOverpaymentFee); -auto const interestRate = - valueUnitWrapper(sfInterestRate); +auto const interestRate = valueUnitWrapper(sfInterestRate); -auto const lateInterestRate = - valueUnitWrapper(sfLateInterestRate); +auto const lateInterestRate = valueUnitWrapper(sfLateInterestRate); -auto const closeInterestRate = - valueUnitWrapper(sfCloseInterestRate); +auto const closeInterestRate = valueUnitWrapper(sfCloseInterestRate); -auto const overpaymentInterestRate = - valueUnitWrapper(sfOverpaymentInterestRate); +auto const overpaymentInterestRate = valueUnitWrapper(sfOverpaymentInterestRate); auto const paymentTotal = simpleField(sfPaymentTotal); @@ -812,10 +728,7 @@ Json::Value del(AccountID const& account, uint256 const& loanID, std::uint32_t flags = 0); Json::Value -pay(AccountID const& account, - uint256 const& loanID, - STAmount const& amount, - std::uint32_t flags = 0); +pay(AccountID const& account, uint256 const& loanID, STAmount const& amount, std::uint32_t flags = 0); } // namespace loan diff --git a/src/test/jtx/TestSuite.h b/src/test/jtx/TestSuite.h index 69cbd2a210..e54bc7d131 100644 --- a/src/test/jtx/TestSuite.h +++ b/src/test/jtx/TestSuite.h @@ -48,14 +48,10 @@ public: template bool - expectCollectionEquals( - Collection const& actual, - Collection const& expected, - std::string const& message = "") + expectCollectionEquals(Collection const& actual, Collection const& expected, std::string const& message = "") { auto msg = addPrefix(message); - bool success = expectEquals( - actual.size(), expected.size(), msg + "Sizes are different"); + bool success = expectEquals(actual.size(), expected.size(), msg + "Sizes are different"); using std::begin; using std::end; @@ -65,11 +61,7 @@ public: for (; i != end(actual) && j != end(expected); ++i, ++j, ++k) { - if (!expectEquals( - *i, - *j, - msg + "Elements at " + std::to_string(k) + - " are different.")) + if (!expectEquals(*i, *j, msg + "Elements at " + std::to_string(k) + " are different.")) return false; } diff --git a/src/test/jtx/TrustedPublisherServer.h b/src/test/jtx/TrustedPublisherServer.h index e7ddef7ac9..2d5b98417b 100644 --- a/src/test/jtx/TrustedPublisherServer.h +++ b/src/test/jtx/TrustedPublisherServer.h @@ -26,17 +26,14 @@ namespace xrpl { namespace test { -class TrustedPublisherServer - : public std::enable_shared_from_this +class TrustedPublisherServer : public std::enable_shared_from_this { using endpoint_type = boost::asio::ip::tcp::endpoint; using address_type = boost::asio::ip::address; using socket_type = boost::asio::ip::tcp::socket; - using req_type = - boost::beast::http::request; - using resp_type = - boost::beast::http::response; + using req_type = boost::beast::http::request; + using resp_type = boost::beast::http::response; using error_code = boost::system::error_code; socket_type sock_; @@ -62,21 +59,16 @@ class TrustedPublisherServer load_server_certificate() { sslCtx_.set_password_callback( - [](std::size_t, boost::asio::ssl::context_base::password_purpose) { - return "test"; - }); + [](std::size_t, boost::asio::ssl::context_base::password_purpose) { return "test"; }); sslCtx_.set_options( - boost::asio::ssl::context::default_workarounds | - boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use); - sslCtx_.use_certificate_chain( - boost::asio::buffer(cert().data(), cert().size())); + sslCtx_.use_certificate_chain(boost::asio::buffer(cert().data(), cert().size())); sslCtx_.use_private_key( - boost::asio::buffer(key().data(), key().size()), - boost::asio::ssl::context::file_format::pem); + boost::asio::buffer(key().data(), key().size()), boost::asio::ssl::context::file_format::pem); sslCtx_.use_tmp_dh(boost::asio::buffer(dh().data(), dh().size())); } @@ -102,12 +94,7 @@ public: }; static std::string - makeManifestString( - PublicKey const& pk, - SecretKey const& sk, - PublicKey const& spk, - SecretKey const& ssk, - int seq) + makeManifestString(PublicKey const& pk, SecretKey const& sk, PublicKey const& spk, SecretKey const& ssk, int seq) { STObject st(sfGeneric); st[sfSequence] = seq; @@ -115,18 +102,12 @@ public: st[sfSigningPubKey] = spk; sign(st, HashPrefix::manifest, *publicKeyType(spk), ssk); - sign( - st, - HashPrefix::manifest, - *publicKeyType(pk), - sk, - sfMasterSignature); + sign(st, HashPrefix::manifest, *publicKeyType(pk), sk, sfMasterSignature); Serializer s; st.add(s); - return base64_encode( - std::string(static_cast(s.data()), s.size())); + return base64_encode(std::string(static_cast(s.data()), s.size())); } static Validator @@ -138,12 +119,7 @@ public: return { masterPublic, signingKeys.first, - makeManifestString( - masterPublic, - secret, - signingKeys.first, - signingKeys.second, - 1)}; + makeManifestString(masterPublic, secret, signingKeys.first, signingKeys.second, 1)}; } // TrustedPublisherServer must be accessed through a shared_ptr. @@ -156,9 +132,7 @@ public: boost::asio::io_context& ioc, std::vector const& validators, NetClock::time_point validUntil, - std::vector< - std::pair> const& - futures, + std::vector> const& futures, bool useSSL = false, int version = 1, bool immediateStart = true, @@ -173,22 +147,18 @@ public: , publisherPublic_{derivePublicKey(KeyType::ed25519, publisherSecret_)} { auto const keys = randomKeyPair(KeyType::secp256k1); - auto const manifest = makeManifestString( - publisherPublic_, publisherSecret_, keys.first, keys.second, 1); + auto const manifest = makeManifestString(publisherPublic_, publisherSecret_, keys.first, keys.second, 1); std::vector blobInfo; blobInfo.reserve(futures.size() + 1); auto const [data, blob] = [&]() -> std::pair { // Builds the validator list, then encodes it into a blob. std::string data = "{\"sequence\":" + std::to_string(sequence) + - ",\"expiration\":" + - std::to_string(validUntil.time_since_epoch().count()) + - ",\"validators\":["; + ",\"expiration\":" + std::to_string(validUntil.time_since_epoch().count()) + ",\"validators\":["; for (auto const& val : validators) { - data += "{\"validation_public_key\":\"" + - strHex(val.masterPublic) + "\",\"manifest\":\"" + + data += "{\"validation_public_key\":\"" + strHex(val.masterPublic) + "\",\"manifest\":\"" + val.manifest + "\"},"; } data.pop_back(); @@ -201,33 +171,27 @@ public: getList_ = [blob = blob, sig, manifest, version](int interval) { // Build the contents of a version 1 format UNL file std::stringstream l; - l << "{\"blob\":\"" << blob << "\"" << ",\"signature\":\"" << sig - << "\"" << ",\"manifest\":\"" << manifest << "\"" - << ",\"refresh_interval\": " << interval - << ",\"version\":" << version << '}'; + l << "{\"blob\":\"" << blob << "\"" << ",\"signature\":\"" << sig << "\"" << ",\"manifest\":\"" << manifest + << "\"" + << ",\"refresh_interval\": " << interval << ",\"version\":" << version << '}'; return l.str(); }; for (auto const& future : futures) { std::string data = "{\"sequence\":" + std::to_string(++sequence) + - ",\"effective\":" + - std::to_string(future.first.time_since_epoch().count()) + - ",\"expiration\":" + - std::to_string(future.second.time_since_epoch().count()) + - ",\"validators\":["; + ",\"effective\":" + std::to_string(future.first.time_since_epoch().count()) + + ",\"expiration\":" + std::to_string(future.second.time_since_epoch().count()) + ",\"validators\":["; // Use the same set of validators for simplicity for (auto const& val : validators) { - data += "{\"validation_public_key\":\"" + - strHex(val.masterPublic) + "\",\"manifest\":\"" + + data += "{\"validation_public_key\":\"" + strHex(val.masterPublic) + "\",\"manifest\":\"" + val.manifest + "\"},"; } data.pop_back(); data += "]}"; std::string blob = base64_encode(data); - auto const sig = - strHex(sign(keys.first, keys.second, makeSlice(data))); + auto const sig = strHex(sign(keys.first, keys.second, makeSlice(data))); blobInfo.emplace_back(blob, sig); } getList2_ = [blobInfo, manifest, version](int interval) { @@ -237,15 +201,13 @@ public: std::stringstream l; for (auto const& info : blobInfo) { - l << "{\"blob\":\"" << info.blob << "\"" << ",\"signature\":\"" - << info.signature << "\"},"; + l << "{\"blob\":\"" << info.blob << "\"" << ",\"signature\":\"" << info.signature << "\"},"; } std::string blobs = l.str(); blobs.pop_back(); l.str(std::string()); - l << "{\"blobs_v2\": [ " << blobs << "],\"manifest\":\"" << manifest - << "\"" << ",\"refresh_interval\": " << interval - << ",\"version\":" << (version + 1) << '}'; + l << "{\"blobs_v2\": [ " << blobs << "],\"manifest\":\"" << manifest << "\"" + << ",\"refresh_interval\": " << interval << ",\"version\":" << (version + 1) << '}'; return l.str(); }; @@ -261,19 +223,15 @@ public: { error_code ec; acceptor_.open(ep_.protocol()); - acceptor_.set_option( - boost::asio::ip::tcp::acceptor::reuse_address(true), ec); + acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), ec); acceptor_.bind(ep_); acceptor_.listen(boost::asio::socket_base::max_listen_connections); - acceptor_.async_accept( - sock_, - [wp = std::weak_ptr{shared_from_this()}]( - error_code ec) { - if (auto p = wp.lock()) - { - p->on_accept(ec); - } - }); + acceptor_.async_accept(sock_, [wp = std::weak_ptr{shared_from_this()}](error_code ec) { + if (auto p = wp.lock()) + { + p->on_accept(ec); + } + }); } void @@ -483,16 +441,8 @@ private: boost::asio::executor_work_guard work; bool ssl; - lambda( - int id_, - TrustedPublisherServer& self_, - socket_type&& sock_, - bool ssl_) - : id(id_) - , self(self_) - , sock(std::move(sock_)) - , work(sock_.get_executor()) - , ssl(ssl_) + lambda(int id_, TrustedPublisherServer& self_, socket_type&& sock_, bool ssl_) + : id(id_), self(self_), sock(std::move(sock_)), work(sock_.get_executor()), ssl(ssl_) { } @@ -511,15 +461,12 @@ private: static int id_ = 0; std::thread{lambda{++id_, *this, std::move(sock_), useSSL_}}.detach(); - acceptor_.async_accept( - sock_, - [wp = std::weak_ptr{shared_from_this()}]( - error_code ec) { - if (auto p = wp.lock()) - { - p->on_accept(ec); - } - }); + acceptor_.async_accept(sock_, [wp = std::weak_ptr{shared_from_this()}](error_code ec) { + if (auto p = wp.lock()) + { + p->on_accept(ec); + } + }); } void @@ -573,11 +520,9 @@ private: else { int refresh = 5; - constexpr char const* refreshPrefix = - "/validators2/refresh/"; + constexpr char const* refreshPrefix = "/validators2/refresh/"; if (boost::starts_with(path, refreshPrefix)) - refresh = boost::lexical_cast( - path.substr(strlen(refreshPrefix))); + refresh = boost::lexical_cast(path.substr(strlen(refreshPrefix))); res.body() = getList2_(refresh); } } @@ -592,11 +537,9 @@ private: else { int refresh = 5; - constexpr char const* refreshPrefix = - "/validators/refresh/"; + constexpr char const* refreshPrefix = "/validators/refresh/"; if (boost::starts_with(path, refreshPrefix)) - refresh = boost::lexical_cast( - path.substr(strlen(refreshPrefix))); + refresh = boost::lexical_cast(path.substr(strlen(refreshPrefix))); res.body() = getList_(refresh); } } @@ -607,24 +550,19 @@ private: res.insert("Content-Type", "text/example"); // if huge was requested, lie about content length std::uint64_t cl = - boost::starts_with(path, "/textfile/huge") - ? std::numeric_limits::max() - : 1024; + boost::starts_with(path, "/textfile/huge") ? std::numeric_limits::max() : 1024; res.content_length(cl); if (req.method() == http::verb::get) { std::stringstream body; for (auto i = 0; i < 1024; ++i) - body << static_cast(rand_int(32, 126)), - res.body() = body.str(); + body << static_cast(rand_int(32, 126)), res.body() = body.str(); } } else if (boost::starts_with(path, "/sleep/")) { - auto const sleep_sec = - boost::lexical_cast(path.substr(7)); - std::this_thread::sleep_for( - std::chrono::seconds(sleep_sec)); + auto const sleep_sec = boost::lexical_cast(path.substr(7)); + std::this_thread::sleep_for(std::chrono::seconds(sleep_sec)); } else if (boost::starts_with(path, "/redirect")) { @@ -644,12 +582,8 @@ private: } else if (!boost::starts_with(path, "/redirect_nolo")) { - location - << (ssl ? "https://" : "http://") - << local_endpoint() - << (boost::starts_with(path, "/redirect_forever/") - ? path - : "/validators"); + location << (ssl ? "https://" : "http://") << local_endpoint() + << (boost::starts_with(path, "/redirect_forever/") ? path : "/validators"); } if (!location.str().empty()) res.insert("Location", location.str()); @@ -674,8 +608,7 @@ private: res.version(req.version()); res.insert("Server", "TrustedPublisherServer"); res.insert("Content-Type", "text/html"); - res.body() = - std::string{"An internal error occurred"} + e.what(); + res.body() = std::string{"An internal error occurred"} + e.what(); res.prepare_payload(); } @@ -699,15 +632,14 @@ make_TrustedPublisherServer( boost::asio::io_context& ioc, std::vector const& validators, NetClock::time_point validUntil, - std::vector> const& - futures, + std::vector> const& futures, bool useSSL = false, int version = 1, bool immediateStart = true, int sequence = 1) { - auto const r = std::make_shared( - ioc, validators, validUntil, futures, useSSL, version, sequence); + auto const r = + std::make_shared(ioc, validators, validUntil, futures, useSSL, version, sequence); if (immediateStart) r->start(); return r; diff --git a/src/test/jtx/WSClient.h b/src/test/jtx/WSClient.h index 2365e8ce40..9e9fb60bfc 100644 --- a/src/test/jtx/WSClient.h +++ b/src/test/jtx/WSClient.h @@ -17,15 +17,11 @@ class WSClient : public AbstractClient public: /** Retrieve a message. */ virtual std::optional - getMsg( - std::chrono::milliseconds const& timeout = std::chrono::milliseconds{ - 0}) = 0; + getMsg(std::chrono::milliseconds const& timeout = std::chrono::milliseconds{0}) = 0; /** Retrieve a message that meets the predicate criteria. */ virtual std::optional - findMsg( - std::chrono::milliseconds const& timeout, - std::function pred) = 0; + findMsg(std::chrono::milliseconds const& timeout, std::function pred) = 0; }; /** Returns a client operating through WebSockets/S. */ diff --git a/src/test/jtx/acctdelete.h b/src/test/jtx/acctdelete.h index 71b8597db9..f5d1f7d869 100644 --- a/src/test/jtx/acctdelete.h +++ b/src/test/jtx/acctdelete.h @@ -18,10 +18,7 @@ acctdelete(Account const& account, Account const& dest); // the account. If margin is specified, close the ledger so `margin` // more closes are needed void -incLgrSeqForAccDel( - jtx::Env& env, - jtx::Account const& acc, - std::uint32_t margin = 0); +incLgrSeqForAccDel(jtx::Env& env, jtx::Account const& acc, std::uint32_t margin = 0); } // namespace jtx diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index 147307f7b7..958160224d 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -74,8 +74,7 @@ public: PrettyAmount& operator=(PrettyAmount const&) = default; - PrettyAmount(STAmount const& amount, std::string const& name) - : amount_(amount), name_(name) + PrettyAmount(STAmount const& amount, std::string const& name) : amount_(amount), name_(name) { } @@ -83,20 +82,14 @@ public: template PrettyAmount( T v, - std::enable_if_t< - sizeof(T) >= sizeof(int) && std::is_integral_v && - std::is_signed_v>* = nullptr) + std::enable_if_t= sizeof(int) && std::is_integral_v && std::is_signed_v>* = nullptr) : amount_((v > 0) ? v : -v, v < 0) { } /** drops */ template - PrettyAmount( - T v, - std::enable_if_t= sizeof(int) && std::is_unsigned_v>* = - nullptr) - : amount_(v) + PrettyAmount(T v, std::enable_if_t= sizeof(int) && std::is_unsigned_v>* = nullptr) : amount_(v) { } @@ -166,13 +159,11 @@ private: public: template requires std::convertible_to - PrettyAsset(A const& asset, std::uint32_t scale = 1) - : PrettyAsset{Asset{asset}, scale} + PrettyAsset(A const& asset, std::uint32_t scale = 1) : PrettyAsset{Asset{asset}, scale} { } - PrettyAsset(Asset const& asset, std::uint32_t scale = 1) - : asset_(asset), scale_(scale) + PrettyAsset(Asset const& asset, std::uint32_t scale = 1) : asset_(asset), scale_(scale) { } @@ -200,8 +191,7 @@ public: } PrettyAmount - operator()(Number v, Number::rounding_mode rounding = Number::getround()) - const + operator()(Number v, Number::rounding_mode rounding = Number::getround()) const { NumberRoundModeGuard mg(rounding); STAmount amount{asset_, v * scale_}; @@ -241,8 +231,7 @@ struct BookSpec AccountID account; xrpl::Currency currency; - BookSpec(AccountID const& account_, xrpl::Currency const& currency_) - : account(account_), currency(currency_) + BookSpec(AccountID const& account_, xrpl::Currency const& currency_) : account(account_), currency(currency_) { } }; @@ -277,8 +266,7 @@ struct XRP_t PrettyAmount operator()(T v) const { - using TOut = std:: - conditional_t, std::int64_t, std::uint64_t>; + using TOut = std::conditional_t, std::int64_t, std::uint64_t>; return {TOut{v} * dropsPerXRP}; } @@ -391,8 +379,7 @@ public: Account account; xrpl::Currency currency; - IOU(Account const& account_, xrpl::Currency const& currency_) - : account(account_), currency(currency_) + IOU(Account const& account_, xrpl::Currency const& currency_) : account(account_), currency(currency_) { } @@ -426,10 +413,7 @@ public: return asset(); } - template < - class T, - class = std::enable_if_t< - sizeof(T) >= sizeof(int) && std::is_arithmetic::value>> + template = sizeof(int) && std::is_arithmetic::value>> PrettyAmount operator()(T v) const { @@ -478,8 +462,7 @@ public: std::string name; xrpl::MPTID issuanceID; - MPT(std::string const& n, xrpl::MPTID const& issuanceID_) - : name(n), issuanceID(issuanceID_) + MPT(std::string const& n, xrpl::MPTID const& issuanceID_) : name(n), issuanceID(issuanceID_) { } @@ -577,8 +560,7 @@ struct AnyAmount { } - AnyAmount(STAmount const& amount, any_t const*) - : is_any(true), value(amount) + AnyAmount(STAmount const& amount, any_t const*) : is_any(true), value(amount) { } diff --git a/src/test/jtx/balance.h b/src/test/jtx/balance.h index 999f6b7b0c..741bbcb195 100644 --- a/src/test/jtx/balance.h +++ b/src/test/jtx/balance.h @@ -24,18 +24,15 @@ private: STAmount const value_; public: - balance(Account const& account, none_t) - : none_(true), account_(account), value_(XRP) + balance(Account const& account, none_t) : none_(true), account_(account), value_(XRP) { } - balance(Account const& account, None const& value) - : none_(true), account_(account), value_(value.asset) + balance(Account const& account, None const& value) : none_(true), account_(account), value_(value.asset) { } - balance(Account const& account, STAmount const& value) - : none_(false), account_(account), value_(value) + balance(Account const& account, STAmount const& value) : none_(false), account_(account), value_(value) { } diff --git a/src/test/jtx/batch.h b/src/test/jtx/batch.h index dc9d30a420..51ded4ee1b 100644 --- a/src/test/jtx/batch.h +++ b/src/test/jtx/batch.h @@ -24,18 +24,11 @@ namespace batch { /** Calculate Batch Fee. */ XRPAmount -calcBatchFee( - jtx::Env const& env, - uint32_t const& numSigners, - uint32_t const& txns = 0); +calcBatchFee(jtx::Env const& env, uint32_t const& numSigners, uint32_t const& txns = 0); /** Batch. */ Json::Value -outer( - jtx::Account const& account, - uint32_t seq, - STAmount const& fee, - std::uint32_t flags); +outer(jtx::Account const& account, uint32_t seq, STAmount const& fee, std::uint32_t flags); /** Adds a new Batch Txn on a JTx and autofills. */ class inner @@ -117,20 +110,15 @@ public: Account master; std::vector signers; - msig(Account const& masterAccount, std::vector signers_) - : master(masterAccount), signers(std::move(signers_)) + msig(Account const& masterAccount, std::vector signers_) : master(masterAccount), signers(std::move(signers_)) { sortSigners(signers); } template requires std::convertible_to - explicit msig( - Account const& masterAccount, - AccountType&& a0, - Accounts&&... aN) - : master(masterAccount) - , signers{std::forward(a0), std::forward(aN)...} + explicit msig(Account const& masterAccount, AccountType&& a0, Accounts&&... aN) + : master(masterAccount), signers{std::forward(a0), std::forward(aN)...} { sortSigners(signers); } diff --git a/src/test/jtx/check.h b/src/test/jtx/check.h index 6152195f1f..61ae5033e4 100644 --- a/src/test/jtx/check.h +++ b/src/test/jtx/check.h @@ -27,10 +27,7 @@ struct DeliverMin /** Cash a check requiring that at least a minimum amount be delivered. */ Json::Value -cash( - jtx::Account const& dest, - uint256 const& checkId, - DeliverMin const& atLeast); +cash(jtx::Account const& dest, uint256 const& checkId, DeliverMin const& atLeast); /** Cancel a check. */ Json::Value diff --git a/src/test/jtx/credentials.h b/src/test/jtx/credentials.h index 2b41b5e7ef..96b3fcf103 100644 --- a/src/test/jtx/credentials.h +++ b/src/test/jtx/credentials.h @@ -12,13 +12,9 @@ namespace jtx { namespace credentials { inline Keylet -keylet( - test::jtx::Account const& subject, - test::jtx::Account const& issuer, - std::string_view credType) +keylet(test::jtx::Account const& subject, test::jtx::Account const& issuer, std::string_view credType) { - return keylet::credential( - subject.id(), issuer.id(), Slice(credType.data(), credType.size())); + return keylet::credential(subject.id(), issuer.id(), Slice(credType.data(), credType.size())); } // Sets the optional URI. @@ -60,30 +56,16 @@ public: }; Json::Value -create( - jtx::Account const& subject, - jtx::Account const& issuer, - std::string_view credType); +create(jtx::Account const& subject, jtx::Account const& issuer, std::string_view credType); Json::Value -accept( - jtx::Account const& subject, - jtx::Account const& issuer, - std::string_view credType); +accept(jtx::Account const& subject, jtx::Account const& issuer, std::string_view credType); Json::Value -deleteCred( - jtx::Account const& acc, - jtx::Account const& subject, - jtx::Account const& issuer, - std::string_view credType); +deleteCred(jtx::Account const& acc, jtx::Account const& subject, jtx::Account const& issuer, std::string_view credType); Json::Value -ledgerEntry( - jtx::Env& env, - jtx::Account const& subject, - jtx::Account const& issuer, - std::string_view credType); +ledgerEntry(jtx::Env& env, jtx::Account const& subject, jtx::Account const& issuer, std::string_view credType); Json::Value ledgerEntry(jtx::Env& env, std::string const& credIdx); diff --git a/src/test/jtx/delegate.h b/src/test/jtx/delegate.h index 19707584ad..d965ab580a 100644 --- a/src/test/jtx/delegate.h +++ b/src/test/jtx/delegate.h @@ -10,15 +10,10 @@ namespace jtx { namespace delegate { Json::Value -set(jtx::Account const& account, - jtx::Account const& authorize, - std::vector const& permissions); +set(jtx::Account const& account, jtx::Account const& authorize, std::vector const& permissions); Json::Value -entry( - jtx::Env& env, - jtx::Account const& account, - jtx::Account const& authorize); +entry(jtx::Env& env, jtx::Account const& account, jtx::Account const& authorize); struct as { diff --git a/src/test/jtx/deposit.h b/src/test/jtx/deposit.h index e378366563..579a7bafb9 100644 --- a/src/test/jtx/deposit.h +++ b/src/test/jtx/deposit.h @@ -48,14 +48,10 @@ struct AuthorizeCredentials }; Json::Value -authCredentials( - jtx::Account const& account, - std::vector const& auth); +authCredentials(jtx::Account const& account, std::vector const& auth); Json::Value -unauthCredentials( - jtx::Account const& account, - std::vector const& auth); +unauthCredentials(jtx::Account const& account, std::vector const& auth); } // namespace deposit diff --git a/src/test/jtx/directory.h b/src/test/jtx/directory.h index 6129b79d1c..25ec202cec 100644 --- a/src/test/jtx/directory.h +++ b/src/test/jtx/directory.h @@ -37,8 +37,7 @@ bumpLastPage( Env& env, std::uint64_t newLastPage, Keylet directory, - std::function adjust) - -> Expected; + std::function adjust) -> Expected; /// Implementation of adjust for the most common ledger entry, i.e. one where /// page index is stored in sfOwnerNode (and only there). Pass this function diff --git a/src/test/jtx/envconfig.h b/src/test/jtx/envconfig.h index d6276f2fba..9cf5cff146 100644 --- a/src/test/jtx/envconfig.h +++ b/src/test/jtx/envconfig.h @@ -104,14 +104,10 @@ std::unique_ptr addGrpcConfig(std::unique_ptr); /// /// @param cfg config instance to be modified std::unique_ptr -addGrpcConfigWithSecureGateway( - std::unique_ptr, - std::string const& secureGateway); +addGrpcConfigWithSecureGateway(std::unique_ptr, std::string const& secureGateway); std::unique_ptr -makeConfig( - std::map extraTxQ = {}, - std::map extraVoting = {}); +makeConfig(std::map extraTxQ = {}, std::map extraVoting = {}); } // namespace jtx } // namespace test diff --git a/src/test/jtx/escrow.h b/src/test/jtx/escrow.h index b8490d9534..1bfe170802 100644 --- a/src/test/jtx/escrow.h +++ b/src/test/jtx/escrow.h @@ -49,31 +49,26 @@ rate(Env& env, Account const& account, std::uint32_t const& seq); // A PreimageSha256 fulfillments and its associated condition. std::array const fb1 = {{0xA0, 0x02, 0x80, 0x00}}; -std::array const cb1 = { - {0xA0, 0x25, 0x80, 0x20, 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, - 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, - 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, - 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55, 0x81, 0x01, 0x00}}; +std::array const cb1 = {{0xA0, 0x25, 0x80, 0x20, 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, + 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, + 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, + 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55, 0x81, 0x01, 0x00}}; // Another PreimageSha256 fulfillments and its associated condition. -std::array const fb2 = { - {0xA0, 0x05, 0x80, 0x03, 0x61, 0x61, 0x61}}; +std::array const fb2 = {{0xA0, 0x05, 0x80, 0x03, 0x61, 0x61, 0x61}}; -std::array const cb2 = { - {0xA0, 0x25, 0x80, 0x20, 0x98, 0x34, 0x87, 0x6D, 0xCF, 0xB0, - 0x5C, 0xB1, 0x67, 0xA5, 0xC2, 0x49, 0x53, 0xEB, 0xA5, 0x8C, - 0x4A, 0xC8, 0x9B, 0x1A, 0xDF, 0x57, 0xF2, 0x8F, 0x2F, 0x9D, - 0x09, 0xAF, 0x10, 0x7E, 0xE8, 0xF0, 0x81, 0x01, 0x03}}; +std::array const cb2 = {{0xA0, 0x25, 0x80, 0x20, 0x98, 0x34, 0x87, 0x6D, 0xCF, 0xB0, + 0x5C, 0xB1, 0x67, 0xA5, 0xC2, 0x49, 0x53, 0xEB, 0xA5, 0x8C, + 0x4A, 0xC8, 0x9B, 0x1A, 0xDF, 0x57, 0xF2, 0x8F, 0x2F, 0x9D, + 0x09, 0xAF, 0x10, 0x7E, 0xE8, 0xF0, 0x81, 0x01, 0x03}}; // Another PreimageSha256 fulfillment and its associated condition. -std::array const fb3 = { - {0xA0, 0x06, 0x80, 0x04, 0x6E, 0x69, 0x6B, 0x62}}; +std::array const fb3 = {{0xA0, 0x06, 0x80, 0x04, 0x6E, 0x69, 0x6B, 0x62}}; -std::array const cb3 = { - {0xA0, 0x25, 0x80, 0x20, 0x6E, 0x4C, 0x71, 0x45, 0x30, 0xC0, - 0xA4, 0x26, 0x8B, 0x3F, 0xA6, 0x3B, 0x1B, 0x60, 0x6F, 0x2D, - 0x26, 0x4A, 0x2D, 0x85, 0x7B, 0xE8, 0xA0, 0x9C, 0x1D, 0xFD, - 0x57, 0x0D, 0x15, 0x85, 0x8B, 0xD4, 0x81, 0x01, 0x04}}; +std::array const cb3 = {{0xA0, 0x25, 0x80, 0x20, 0x6E, 0x4C, 0x71, 0x45, 0x30, 0xC0, + 0xA4, 0x26, 0x8B, 0x3F, 0xA6, 0x3B, 0x1B, 0x60, 0x6F, 0x2D, + 0x26, 0x4A, 0x2D, 0x85, 0x7B, 0xE8, 0xA0, 0x9C, 0x1D, 0xFD, + 0x57, 0x0D, 0x15, 0x85, 0x8B, 0xD4, 0x81, 0x01, 0x04}}; /** Set the "FinishAfter" time tag on a JTx */ auto const finish_time = JTxFieldWrapper(sfFinishAfter); diff --git a/src/test/jtx/fee.h b/src/test/jtx/fee.h index 1b3a6ac49c..3ede9680f8 100644 --- a/src/test/jtx/fee.h +++ b/src/test/jtx/fee.h @@ -40,8 +40,7 @@ public: Throw("fee: not XRP"); } - explicit fee(std::uint64_t amount, bool negative = false) - : fee{STAmount{amount, negative}} + explicit fee(std::uint64_t amount, bool negative = false) : fee{STAmount{amount, negative}} { } diff --git a/src/test/jtx/flags.h b/src/test/jtx/flags.h index 6b8c230a79..3f1f8f71a3 100644 --- a/src/test/jtx/flags.h +++ b/src/test/jtx/flags.h @@ -112,8 +112,7 @@ private: public: template - flags(Account const& account, Args... args) - : flags_helper(args...), account_(account) + flags(Account const& account, Args... args) : flags_helper(args...), account_(account) { } @@ -129,8 +128,7 @@ private: public: template - nflags(Account const& account, Args... args) - : flags_helper(args...), account_(account) + nflags(Account const& account, Args... args) : flags_helper(args...), account_(account) { } diff --git a/src/test/jtx/impl/AMM.cpp b/src/test/jtx/impl/AMM.cpp index b620126b0f..4d27ddf740 100644 --- a/src/test/jtx/impl/AMM.cpp +++ b/src/test/jtx/impl/AMM.cpp @@ -27,8 +27,7 @@ AMM::initialTokens() if (!env_.enabled(fixAMMv1_3)) { auto const product = number(asset1_) * number(asset2_); - return (IOUAmount)(product.mantissa() >= 0 ? root2(product) - : root2(-product)); + return (IOUAmount)(product.mantissa() >= 0 ? root2(product) : root2(-product)); } return getLPTokensBalance(); } @@ -59,10 +58,7 @@ AMM::AMM( , msig_(ms) , fee_(fee) , ammAccount_(create(tfee, flags, seq, ter)) - , lptIssue_(xrpl::ammLPTIssue( - asset1_.issue().currency, - asset2_.issue().currency, - ammAccount_)) + , lptIssue_(xrpl::ammLPTIssue(asset1_.issue().currency, asset2_.issue().currency, ammAccount_)) , initialLPTokens_(initialTokens()) { } @@ -75,39 +71,12 @@ AMM::AMM( ter const& ter, bool log, bool close) - : AMM(env, - account, - asset1, - asset2, - log, - 0, - 0, - std::nullopt, - std::nullopt, - std::nullopt, - ter, - close) + : AMM(env, account, asset1, asset2, log, 0, 0, std::nullopt, std::nullopt, std::nullopt, ter, close) { } -AMM::AMM( - Env& env, - Account const& account, - STAmount const& asset1, - STAmount const& asset2, - CreateArg const& arg) - : AMM(env, - account, - asset1, - asset2, - arg.log, - arg.tfee, - arg.fee, - arg.flags, - arg.seq, - arg.ms, - arg.err, - arg.close) +AMM::AMM(Env& env, Account const& account, STAmount const& asset1, STAmount const& asset2, CreateArg const& arg) + : AMM(env, account, asset1, asset2, arg.log, arg.tfee, arg.fee, arg.flags, arg.seq, arg.ms, arg.err, arg.close) { } @@ -134,8 +103,7 @@ AMM::create( if (!ter || env_.ter() == tesSUCCESS) { - if (auto const amm = env_.current()->read( - keylet::amm(asset1_.issue(), asset2_.issue()))) + if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) { return amm->getAccountID(sfAccount); } @@ -163,52 +131,36 @@ AMM::ammRpcInfo( if (issue1 || issue2) { if (issue1) - jv[jss::asset] = - STIssue(sfAsset, *issue1).getJson(JsonOptions::none); + jv[jss::asset] = STIssue(sfAsset, *issue1).getJson(JsonOptions::none); if (issue2) - jv[jss::asset2] = - STIssue(sfAsset2, *issue2).getJson(JsonOptions::none); + jv[jss::asset2] = STIssue(sfAsset2, *issue2).getJson(JsonOptions::none); } else if (!ammAccount) { - jv[jss::asset] = - STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none); - jv[jss::asset2] = - STIssue(sfAsset2, asset2_.issue()).getJson(JsonOptions::none); + jv[jss::asset] = STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none); + jv[jss::asset2] = STIssue(sfAsset2, asset2_.issue()).getJson(JsonOptions::none); } if (ammAccount) jv[jss::amm_account] = to_string(*ammAccount); } auto jr = - (apiVersion == RPC::apiInvalidVersion - ? env_.rpc("json", "amm_info", to_string(jv)) - : env_.rpc(apiVersion, "json", "amm_info", to_string(jv))); - if (jr.isObject() && jr.isMember(jss::result) && - jr[jss::result].isMember(jss::status)) + (apiVersion == RPC::apiInvalidVersion ? env_.rpc("json", "amm_info", to_string(jv)) + : env_.rpc(apiVersion, "json", "amm_info", to_string(jv))); + if (jr.isObject() && jr.isMember(jss::result) && jr[jss::result].isMember(jss::status)) return jr[jss::result]; return Json::nullValue; } std::tuple -AMM::balances( - Issue const& issue1, - Issue const& issue2, - std::optional const& account) const +AMM::balances(Issue const& issue1, Issue const& issue2, std::optional const& account) const { - if (auto const amm = - env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) + if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) { auto const ammAccountID = amm->getAccountID(sfAccount); - auto const [asset1Balance, asset2Balance] = ammPoolHolds( - *env_.current(), - ammAccountID, - issue1, - issue2, - FreezeHandling::fhIGNORE_FREEZE, - env_.journal); - auto const lptAMMBalance = account - ? ammLPHolds(*env_.current(), *amm, *account, env_.journal) - : amm->getFieldAmount(sfLPTokenBalance); + auto const [asset1Balance, asset2Balance] = + ammPoolHolds(*env_.current(), ammAccountID, issue1, issue2, FreezeHandling::fhIGNORE_FREEZE, env_.journal); + auto const lptAMMBalance = + account ? ammLPHolds(*env_.current(), *amm, *account, env_.journal) : amm->getFieldAmount(sfLPTokenBalance); return {asset1Balance, asset2Balance, lptAMMBalance}; } return {STAmount{}, STAmount{}, STAmount{}}; @@ -221,25 +173,16 @@ AMM::expectBalances( IOUAmount const& lpt, std::optional const& account) const { - auto const [asset1Balance, asset2Balance, lptAMMBalance] = - balances(asset1.issue(), asset2.issue(), account); - return asset1 == asset1Balance && asset2 == asset2Balance && - lptAMMBalance == STAmount{lpt, lptIssue_}; + auto const [asset1Balance, asset2Balance, lptAMMBalance] = balances(asset1.issue(), asset2.issue(), account); + return asset1 == asset1Balance && asset2 == asset2Balance && lptAMMBalance == STAmount{lpt, lptIssue_}; } IOUAmount AMM::getLPTokensBalance(std::optional const& account) const { if (account) - return accountHolds( - *env_.current(), - *account, - lptIssue_, - FreezeHandling::fhZERO_IF_FROZEN, - env_.journal) - .iou(); - if (auto const amm = - env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) + return accountHolds(*env_.current(), *account, lptIssue_, FreezeHandling::fhZERO_IF_FROZEN, env_.journal).iou(); + if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) return amm->getFieldAmount(sfLPTokenBalance).iou(); return IOUAmount{0}; } @@ -247,58 +190,45 @@ AMM::getLPTokensBalance(std::optional const& account) const bool AMM::expectLPTokens(AccountID const& account, IOUAmount const& expTokens) const { - if (auto const amm = - env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) + if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) { - auto const lptAMMBalance = - ammLPHolds(*env_.current(), *amm, account, env_.journal); + auto const lptAMMBalance = ammLPHolds(*env_.current(), *amm, account, env_.journal); return lptAMMBalance == STAmount{expTokens, lptIssue_}; } return false; } bool -AMM::expectAuctionSlot( - std::uint32_t fee, - std::optional timeSlot, - IOUAmount expectedPrice) const +AMM::expectAuctionSlot(std::uint32_t fee, std::optional timeSlot, IOUAmount expectedPrice) const { - return expectAuctionSlot([&](std::uint32_t slotFee, - std::optional slotInterval, - IOUAmount const& slotPrice, - auto const&) { - return slotFee == fee && - // Auction slot might be expired, in which case slotInterval is - // 0 - ((!timeSlot && slotInterval == 0) || slotInterval == timeSlot) && - slotPrice == expectedPrice; - }); + return expectAuctionSlot( + [&](std::uint32_t slotFee, std::optional slotInterval, IOUAmount const& slotPrice, auto const&) { + return slotFee == fee && + // Auction slot might be expired, in which case slotInterval is + // 0 + ((!timeSlot && slotInterval == 0) || slotInterval == timeSlot) && slotPrice == expectedPrice; + }); } bool AMM::expectAuctionSlot(std::vector const& authAccounts) const { - return expectAuctionSlot([&](std::uint32_t, - std::optional, - IOUAmount const&, - STArray const& accounts) { - for (auto const& account : accounts) - { - if (std::find( - authAccounts.cbegin(), - authAccounts.cend(), - account.getAccountID(sfAccount)) == authAccounts.end()) - return false; - } - return true; - }); + return expectAuctionSlot( + [&](std::uint32_t, std::optional, IOUAmount const&, STArray const& accounts) { + for (auto const& account : accounts) + { + if (std::find(authAccounts.cbegin(), authAccounts.cend(), account.getAccountID(sfAccount)) == + authAccounts.end()) + return false; + } + return true; + }); } bool AMM::expectTradingFee(std::uint16_t fee) const { - auto const amm = - env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())); + auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())); return amm && (*amm)[sfTradingFee] == fee; } @@ -306,8 +236,7 @@ bool AMM::ammExists() const { return env_.current()->read(keylet::account(ammAccount_)) != nullptr && - env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())) != - nullptr; + env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue())) != nullptr; } bool @@ -319,23 +248,18 @@ AMM::expectAmmRpcInfo( std::optional const& ledger_index, std::optional const& ammAccount) const { - auto const jv = ammRpcInfo( - account, ledger_index, std::nullopt, std::nullopt, ammAccount); + auto const jv = ammRpcInfo(account, ledger_index, std::nullopt, std::nullopt, ammAccount); return expectAmmInfo(asset1, asset2, balance, jv); } bool -AMM::expectAmmInfo( - STAmount const& asset1, - STAmount const& asset2, - IOUAmount const& balance, - Json::Value const& jvres) const +AMM::expectAmmInfo(STAmount const& asset1, STAmount const& asset2, IOUAmount const& balance, Json::Value const& jvres) + const { if (!jvres.isMember(jss::amm)) return false; auto const& jv = jvres[jss::amm]; - if (!jv.isMember(jss::amount) || !jv.isMember(jss::amount2) || - !jv.isMember(jss::lp_token)) + if (!jv.isMember(jss::amount) || !jv.isMember(jss::amount2) || !jv.isMember(jss::lp_token)) return false; STAmount asset1Info; if (!amountFromJsonNoThrow(asset1Info, jv[jss::amount])) @@ -349,28 +273,21 @@ AMM::expectAmmInfo( // ammRpcInfo returns unordered assets if (asset1Info.issue() != asset1.issue()) std::swap(asset1Info, asset2Info); - return asset1 == asset1Info && asset2 == asset2Info && - lptBalance == STAmount{balance, lptIssue_}; + return asset1 == asset1Info && asset2 == asset2Info && lptBalance == STAmount{balance, lptIssue_}; } void -AMM::setTokens( - Json::Value& jv, - std::optional> const& assets) +AMM::setTokens(Json::Value& jv, std::optional> const& assets) { if (assets) { - jv[jss::Asset] = - STIssue(sfAsset, assets->first).getJson(JsonOptions::none); - jv[jss::Asset2] = - STIssue(sfAsset, assets->second).getJson(JsonOptions::none); + jv[jss::Asset] = STIssue(sfAsset, assets->first).getJson(JsonOptions::none); + jv[jss::Asset2] = STIssue(sfAsset, assets->second).getJson(JsonOptions::none); } else { - jv[jss::Asset] = - STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none); - jv[jss::Asset2] = - STIssue(sfAsset, asset2_.issue()).getJson(JsonOptions::none); + jv[jss::Asset] = STIssue(sfAsset, asset1_.issue()).getJson(JsonOptions::none); + jv[jss::Asset2] = STIssue(sfAsset, asset2_.issue()).getJson(JsonOptions::none); } } @@ -402,16 +319,7 @@ AMM::deposit( std::optional const& ter) { return deposit( - account, - tokens, - asset1In, - std::nullopt, - std::nullopt, - flags, - std::nullopt, - std::nullopt, - std::nullopt, - ter); + account, tokens, asset1In, std::nullopt, std::nullopt, flags, std::nullopt, std::nullopt, std::nullopt, ter); } IOUAmount @@ -425,16 +333,7 @@ AMM::deposit( { assert(!(asset2In && maxEP)); return deposit( - account, - std::nullopt, - asset1In, - asset2In, - maxEP, - flags, - std::nullopt, - std::nullopt, - std::nullopt, - ter); + account, std::nullopt, asset1In, asset2In, maxEP, flags, std::nullopt, std::nullopt, std::nullopt, ter); } IOUAmount @@ -527,16 +426,7 @@ AMM::withdraw( std::optional const& flags, std::optional const& ter) { - return withdraw( - account, - tokens, - asset1Out, - std::nullopt, - std::nullopt, - flags, - std::nullopt, - std::nullopt, - ter); + return withdraw(account, tokens, asset1Out, std::nullopt, std::nullopt, flags, std::nullopt, std::nullopt, ter); } IOUAmount @@ -548,16 +438,7 @@ AMM::withdraw( std::optional const& ter) { assert(!(asset2Out && maxEP)); - return withdraw( - account, - std::nullopt, - asset1Out, - asset2Out, - maxEP, - std::nullopt, - std::nullopt, - std::nullopt, - ter); + return withdraw(account, std::nullopt, asset1Out, asset2Out, maxEP, std::nullopt, std::nullopt, std::nullopt, ter); } IOUAmount @@ -608,15 +489,7 @@ IOUAmount AMM::withdraw(WithdrawArg const& arg) { return withdraw( - arg.account, - arg.tokens, - arg.asset1Out, - arg.asset2Out, - arg.maxEP, - arg.flags, - arg.assets, - arg.seq, - arg.err); + arg.account, arg.tokens, arg.asset1Out, arg.asset2Out, arg.maxEP, arg.flags, arg.assets, arg.seq, arg.err); } void @@ -649,16 +522,12 @@ AMM::vote(VoteArg const& arg) Json::Value AMM::bid(BidArg const& arg) { - if (auto const amm = - env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) + if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) { - assert( - !env_.current()->rules().enabled(fixInnerObjTemplate) || - amm->isFieldPresent(sfAuctionSlot)); + assert(!env_.current()->rules().enabled(fixInnerObjTemplate) || amm->isFieldPresent(sfAuctionSlot)); if (amm->isFieldPresent(sfAuctionSlot)) { - auto const& auctionSlot = - static_cast(amm->peekAtField(sfAuctionSlot)); + auto const& auctionSlot = static_cast(amm->peekAtField(sfAuctionSlot)); lastPurchasePrice_ = auctionSlot[sfPrice].iou(); } } @@ -666,8 +535,7 @@ AMM::bid(BidArg const& arg) bidMax_ = std::nullopt; Json::Value jv; - jv[jss::Account] = - arg.account ? arg.account->human() : creatorAccount_.human(); + jv[jss::Account] = arg.account ? arg.account->human() : creatorAccount_.human(); setTokens(jv, arg.assets); auto getBid = [&](auto const& bid) { if (std::holds_alternative(bid)) @@ -711,10 +579,7 @@ AMM::bid(BidArg const& arg) } void -AMM::submit( - Json::Value const& jv, - std::optional const& seq, - std::optional const& ter) +AMM::submit(Json::Value const& jv, std::optional const& seq, std::optional const& ter) { if (log_) std::cout << jv.toStyledString(); @@ -744,16 +609,12 @@ AMM::submit( bool AMM::expectAuctionSlot(auto&& cb) const { - if (auto const amm = - env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) + if (auto const amm = env_.current()->read(keylet::amm(asset1_.issue(), asset2_.issue()))) { - assert( - !env_.current()->rules().enabled(fixInnerObjTemplate) || - amm->isFieldPresent(sfAuctionSlot)); + assert(!env_.current()->rules().enabled(fixInnerObjTemplate) || amm->isFieldPresent(sfAuctionSlot)); if (amm->isFieldPresent(sfAuctionSlot)) { - auto const& auctionSlot = - static_cast(amm->peekAtField(sfAuctionSlot)); + auto const& auctionSlot = static_cast(amm->peekAtField(sfAuctionSlot)); if (auctionSlot.isFieldPresent(sfAccount)) { // This could fail in pre-fixInnerObjTemplate tests @@ -761,12 +622,10 @@ AMM::expectAuctionSlot(auto&& cb) const // the failure scenarios. Access as optional // to avoid the failure. auto const slotFee = auctionSlot[~sfDiscountedFee].value_or(0); - auto const slotInterval = ammAuctionTimeSlot( - env_.app().timeKeeper().now().time_since_epoch().count(), - auctionSlot); + auto const slotInterval = + ammAuctionTimeSlot(env_.app().timeKeeper().now().time_since_epoch().count(), auctionSlot); auto const slotPrice = auctionSlot[sfPrice].iou(); - auto const authAccounts = - auctionSlot.getFieldArray(sfAuthAccounts); + auto const authAccounts = auctionSlot.getFieldArray(sfAuthAccounts); return cb(slotFee, slotInterval, slotPrice, authAccounts); } } diff --git a/src/test/jtx/impl/AMMTest.cpp b/src/test/jtx/impl/AMMTest.cpp index 139b9113b9..18359ad201 100644 --- a/src/test/jtx/impl/AMMTest.cpp +++ b/src/test/jtx/impl/AMMTest.cpp @@ -88,16 +88,11 @@ AMMTestBase::testAMM( std::optional const& ter, std::vector const& vfeatures) { - testAMM( - std::move(cb), - TestAMMArg{ - .pool = pool, .tfee = tfee, .ter = ter, .features = vfeatures}); + testAMM(std::move(cb), TestAMMArg{.pool = pool, .tfee = tfee, .ter = ter, .features = vfeatures}); } void -AMMTestBase::testAMM( - std::function&& cb, - TestAMMArg const& arg) +AMMTestBase::testAMM(std::function&& cb, TestAMMArg const& arg) { using namespace jtx; @@ -115,8 +110,7 @@ AMMTestBase::testAMM( features - featureSingleAssetVault - featureLendingProtocol, arg.noLog ? std::make_unique(&logs) : nullptr}; - auto const [asset1, asset2] = - arg.pool ? *arg.pool : std::make_pair(XRP(10000), USD(10000)); + auto const [asset1, asset2] = arg.pool ? *arg.pool : std::make_pair(XRP(10000), USD(10000)); auto toFund = [&](STAmount const& a) -> STAmount { if (a.native()) { @@ -141,14 +135,8 @@ AMMTestBase::testAMM( else if (asset2.native()) fund(env, gw, {alice, carol}, toFund2, {toFund1}, Fund::All); - AMM ammAlice( - env, - alice, - asset1, - asset2, - CreateArg{.log = false, .tfee = arg.tfee, .err = arg.ter}); - if (BEAST_EXPECT( - ammAlice.expectBalances(asset1, asset2, ammAlice.tokens()))) + AMM ammAlice(env, alice, asset1, asset2, CreateArg{.log = false, .tfee = arg.tfee, .err = arg.ter}); + if (BEAST_EXPECT(ammAlice.expectBalances(asset1, asset2, ammAlice.tokens()))) cb(ammAlice, env); } } @@ -247,8 +235,7 @@ AMMTest::find_paths( std::optional const& saSendMax, std::optional const& saSrcCurrency) { - Json::Value result = find_paths_request( - env, src, dst, saDstAmount, saSendMax, saSrcCurrency); + Json::Value result = find_paths_request(env, src, dst, saDstAmount, saSendMax, saSrcCurrency); BEAST_EXPECT(!result.isMember(jss::error)); STAmount da; diff --git a/src/test/jtx/impl/Account.cpp b/src/test/jtx/impl/Account.cpp index 232c9d4e6c..31798abdc7 100644 --- a/src/test/jtx/impl/Account.cpp +++ b/src/test/jtx/impl/Account.cpp @@ -7,23 +7,15 @@ namespace xrpl { namespace test { namespace jtx { -std::unordered_map, Account, beast::uhash<>> - Account::cache_; +std::unordered_map, Account, beast::uhash<>> Account::cache_; Account const Account::master( "master", generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")), Account::privateCtorTag{}); -Account::Account( - std::string name, - std::pair const& keys, - Account::privateCtorTag) - : name_(std::move(name)) - , pk_(keys.first) - , sk_(keys.second) - , id_(calcAccountID(pk_)) - , human_(toBase58(id_)) +Account::Account(std::string name, std::pair const& keys, Account::privateCtorTag) + : name_(std::move(name)), pk_(keys.first), sk_(keys.second), id_(calcAccountID(pk_)), human_(toBase58(id_)) { } @@ -54,16 +46,12 @@ Account::fromCache(AcctStringType stringType, std::string name, KeyType type) return r.first->second; } -Account::Account(std::string name, KeyType type) - : Account(fromCache(Account::other, std::move(name), type)) +Account::Account(std::string name, KeyType type) : Account(fromCache(Account::other, std::move(name), type)) { } Account::Account(AcctStringType stringType, std::string base58SeedStr) - : Account(fromCache( - Account::base58Seed, - std::move(base58SeedStr), - KeyType::secp256k1)) + : Account(fromCache(Account::base58Seed, std::move(base58SeedStr), KeyType::secp256k1)) { } diff --git a/src/test/jtx/impl/Env.cpp b/src/test/jtx/impl/Env.cpp index ccef0f0398..9971da05c4 100644 --- a/src/test/jtx/impl/Env.cpp +++ b/src/test/jtx/impl/Env.cpp @@ -50,25 +50,18 @@ Env::AppBundle::AppBundle( { logs = std::make_unique(suite); // Use kFatal threshold to reduce noise from STObject. - setDebugLogSink( - std::make_unique("Debug", kFatal, suite)); + setDebugLogSink(std::make_unique("Debug", kFatal, suite)); } auto timeKeeper_ = std::make_unique(); timeKeeper = timeKeeper_.get(); // Hack so we don't have to call Config::setup - HTTPClient::initializeSSLContext( - config->SSL_VERIFY_DIR, - config->SSL_VERIFY_FILE, - config->SSL_VERIFY, - debugLog()); - owned = make_Application( - std::move(config), std::move(logs), std::move(timeKeeper_)); + HTTPClient::initializeSSLContext(config->SSL_VERIFY_DIR, config->SSL_VERIFY_FILE, config->SSL_VERIFY, debugLog()); + owned = make_Application(std::move(config), std::move(logs), std::move(timeKeeper_)); app = owned.get(); app->logs().threshold(thresh); if (!app->setup({})) Throw("Env::AppBundle: setup failed"); - timeKeeper->set( - app->getLedgerMaster().getClosedLedger()->header().closeTime); + timeKeeper->set(app->getLedgerMaster().getClosedLedger()->header().closeTime); app->start(false /*don't start timers*/); thread = std::thread([&]() { app->run(); }); @@ -101,9 +94,7 @@ Env::closed() } bool -Env::close( - NetClock::time_point closeTime, - std::optional consensusDelay) +Env::close(NetClock::time_point closeTime, std::optional consensusDelay) { // Round up to next distinguishable value using namespace std::chrono_literals; @@ -202,8 +193,7 @@ Env::balance(Account const& account, MPTIssue const& mptIssue) const return {STAmount(mptIssue, 0), account.name()}; // Make it negative - STAmount const amount{ - mptIssue, sle->getFieldU64(sfOutstandingAmount), 0, true}; + STAmount const amount{mptIssue, sle->getFieldU64(sfOutstandingAmount), 0, true}; return {amount, lookup(issuer).name()}; } else @@ -221,9 +211,7 @@ Env::balance(Account const& account, MPTIssue const& mptIssue) const PrettyAmount Env::balance(Account const& account, Asset const& asset) const { - return std::visit( - [&](auto const& issue) { return balance(account, issue); }, - asset.value()); + return std::visit([&](auto const& issue) { return balance(account, issue); }, asset.value()); } PrettyAmount @@ -280,20 +268,12 @@ Env::fund(bool setDefaultRipple, STAmount const& amount, Account const& account) jtx::seq(jtx::autofill), fee(jtx::autofill), sig(jtx::autofill)); - apply( - fset(account, asfDefaultRipple), - jtx::seq(jtx::autofill), - fee(jtx::autofill), - sig(jtx::autofill)); + apply(fset(account, asfDefaultRipple), jtx::seq(jtx::autofill), fee(jtx::autofill), sig(jtx::autofill)); require(flags(account, asfDefaultRipple)); } else { - apply( - pay(master, account, amount), - jtx::seq(jtx::autofill), - fee(jtx::autofill), - sig(jtx::autofill)); + apply(pay(master, account, amount), jtx::seq(jtx::autofill), fee(jtx::autofill), sig(jtx::autofill)); require(nflags(account, asfDefaultRipple)); } require(jtx::balance(account, amount)); @@ -303,11 +283,7 @@ void Env::trust(STAmount const& amount, Account const& account) { auto const start = balance(account); - apply( - jtx::trust(account, amount), - jtx::seq(jtx::autofill), - fee(jtx::autofill), - sig(jtx::autofill)); + apply(jtx::trust(account, amount), jtx::seq(jtx::autofill), fee(jtx::autofill), sig(jtx::autofill)); apply( pay(master, account, drops(current()->fees().base)), jtx::seq(jtx::autofill), @@ -327,8 +303,7 @@ Env::parseResult(Json::Value const& jr) if (!object.isObject()) return; if (object.isMember(jss::error_code)) - parsed.rpcCode = - safe_cast(object[jss::error_code].asInt()); + parsed.rpcCode = safe_cast(object[jss::error_code].asInt()); if (object.isMember(jss::error_message)) parsed.rpcMessage = object[jss::error_message].asString(); if (object.isMember(jss::error)) @@ -402,9 +377,8 @@ Env::sign_and_submit(JTx const& jt, Json::Value params) // Use the provided parameters, and go straight // to the (RPC) client. assert(params.isObject()); - if (!params.isMember(jss::secret) && !params.isMember(jss::key_type) && - !params.isMember(jss::seed) && !params.isMember(jss::seed_hex) && - !params.isMember(jss::passphrase)) + if (!params.isMember(jss::secret) && !params.isMember(jss::key_type) && !params.isMember(jss::seed) && + !params.isMember(jss::seed_hex) && !params.isMember(jss::passphrase)) { params[jss::secret] = passphrase; } @@ -423,10 +397,7 @@ Env::sign_and_submit(JTx const& jt, Json::Value params) } void -Env::postconditions( - JTx const& jt, - ParsedResult const& parsed, - Json::Value const& jr) +Env::postconditions(JTx const& jt, ParsedResult const& parsed, Json::Value const& jr) { auto const line = jt.testLine ? " (" + to_string(*jt.testLine) + ")" : ""; bool bad = !test.expect(parsed.ter, "apply: No ter result!" + line); @@ -434,21 +405,15 @@ Env::postconditions( (jt.ter && parsed.ter && !test.expect( *parsed.ter == *jt.ter, - "apply: Got " + transToken(*parsed.ter) + " (" + - transHuman(*parsed.ter) + "); Expected " + - transToken(*jt.ter) + " (" + transHuman(*jt.ter) + ")" + - line)); + "apply: Got " + transToken(*parsed.ter) + " (" + transHuman(*parsed.ter) + "); Expected " + + transToken(*jt.ter) + " (" + transHuman(*jt.ter) + ")" + line)); using namespace std::string_literals; bad = (jt.rpcCode && !test.expect( - parsed.rpcCode == jt.rpcCode->first && - parsed.rpcMessage == jt.rpcCode->second, + parsed.rpcCode == jt.rpcCode->first && parsed.rpcMessage == jt.rpcCode->second, "apply: Got RPC result "s + - (parsed.rpcCode - ? RPC::get_error_info(*parsed.rpcCode).token.c_str() - : "NO RESULT") + - " (" + parsed.rpcMessage + "); Expected " + - RPC::get_error_info(jt.rpcCode->first).token.c_str() + " (" + + (parsed.rpcCode ? RPC::get_error_info(*parsed.rpcCode).token.c_str() : "NO RESULT") + " (" + + parsed.rpcMessage + "); Expected " + RPC::get_error_info(jt.rpcCode->first).token.c_str() + " (" + jt.rpcCode->second + ")" + line)) || bad; // If we have an rpcCode (just checked), then the rpcException check is @@ -458,12 +423,9 @@ Env::postconditions( !test.expect( (jt.rpcCode && parsed.rpcError.empty()) || (parsed.rpcError == jt.rpcException->first && - (!jt.rpcException->second || - parsed.rpcException == *jt.rpcException->second)), - "apply: Got RPC result "s + parsed.rpcError + " (" + - parsed.rpcException + "); Expected " + - jt.rpcException->first + " (" + - jt.rpcException->second.value_or("n/a") + ")" + line)) || + (!jt.rpcException->second || parsed.rpcException == *jt.rpcException->second)), + "apply: Got RPC result "s + parsed.rpcError + " (" + parsed.rpcException + "); Expected " + + jt.rpcException->first + " (" + jt.rpcException->second.value_or("n/a") + ")" + line)) || bad; if (bad) { @@ -534,9 +496,8 @@ Env::autofill_sig(JTx& jt) // If the sig is still needed, get it here. if (!jt.fill_sig) return; - auto const account = jv.isMember(sfDelegate.jsonName) - ? lookup(jv[sfDelegate.jsonName].asString()) - : lookup(jv[jss::Account].asString()); + auto const account = jv.isMember(sfDelegate.jsonName) ? lookup(jv[sfDelegate.jsonName].asString()) + : lookup(jv[jss::Account].asString()); if (!app().checkSigs()) { jv[jss::SigningPubKey] = strHex(account.pk().slice()); @@ -638,18 +599,14 @@ Env::do_rpc( std::vector const& args, std::unordered_map const& headers) { - auto response = - rpcClient(args, app().config(), app().logs(), apiVersion, headers); + auto response = rpcClient(args, app().config(), app().logs(), apiVersion, headers); - for (unsigned ctr = 0; (ctr < retries_) and (response.first == rpcINTERNAL); - ++ctr) + for (unsigned ctr = 0; (ctr < retries_) and (response.first == rpcINTERNAL); ++ctr) { - JLOG(journal.error()) - << "Env::do_rpc error, retrying, attempt #" << ctr + 1 << " ..."; + JLOG(journal.error()) << "Env::do_rpc error, retrying, attempt #" << ctr + 1 << " ..."; std::this_thread::sleep_for(std::chrono::milliseconds(500)); - response = - rpcClient(args, app().config(), app().logs(), apiVersion, headers); + response = rpcClient(args, app().config(), app().logs(), apiVersion, headers); } return response.second; diff --git a/src/test/jtx/impl/JSONRPCClient.cpp b/src/test/jtx/impl/JSONRPCClient.cpp index df41ed39be..34d0ea2f68 100644 --- a/src/test/jtx/impl/JSONRPCClient.cpp +++ b/src/test/jtx/impl/JSONRPCClient.cpp @@ -35,8 +35,7 @@ class JSONRPCClient : public AbstractClient continue; using namespace boost::asio::ip; if (pp.ip && pp.ip->is_unspecified()) - *pp.ip = pp.ip->is_v6() ? address{address_v6::loopback()} - : address{address_v4::loopback()}; + *pp.ip = pp.ip->is_v6() ? address{address_v6::loopback()} : address{address_v4::loopback()}; if (!pp.port) Throw("Use fixConfigPorts with auto ports"); diff --git a/src/test/jtx/impl/Oracle.cpp b/src/test/jtx/impl/Oracle.cpp index 03271cc9ad..c696011da5 100644 --- a/src/test/jtx/impl/Oracle.cpp +++ b/src/test/jtx/impl/Oracle.cpp @@ -12,8 +12,7 @@ namespace test { namespace jtx { namespace oracle { -Oracle::Oracle(Env& env, CreateArg const& arg, bool submit) - : env_(env), owner_{}, documentID_{} +Oracle::Oracle(Env& env, CreateArg const& arg, bool submit) : env_(env), owner_{}, documentID_{} { // LastUpdateTime is checked to be in range // {close-maxLastUpdateTimeDelta, close+maxLastUpdateTimeDelta}. @@ -95,20 +94,14 @@ Oracle::expectPrice(DataSeries const& series) const return false; for (auto const& data : series) { - if (std::find_if( - leSeries.begin(), - leSeries.end(), - [&](STObject const& o) -> bool { - auto const& baseAsset = o.getFieldCurrency(sfBaseAsset); - auto const& quoteAsset = - o.getFieldCurrency(sfQuoteAsset); - auto const& price = o.getFieldU64(sfAssetPrice); - auto const& scale = o.getFieldU8(sfScale); - return baseAsset.getText() == std::get<0>(data) && - quoteAsset.getText() == std::get<1>(data) && - price == std::get<2>(data) && - scale == std::get<3>(data); - }) == leSeries.end()) + if (std::find_if(leSeries.begin(), leSeries.end(), [&](STObject const& o) -> bool { + auto const& baseAsset = o.getFieldCurrency(sfBaseAsset); + auto const& quoteAsset = o.getFieldCurrency(sfQuoteAsset); + auto const& price = o.getFieldU64(sfAssetPrice); + auto const& scale = o.getFieldU8(sfScale); + return baseAsset.getText() == std::get<0>(data) && quoteAsset.getText() == std::get<1>(data) && + price == std::get<2>(data) && scale == std::get<3>(data); + }) == leSeries.end()) return false; } return true; @@ -177,8 +170,7 @@ Oracle::set(UpdateArg const& arg) Json::Value jv; if (arg.owner) owner_ = *arg.owner; - if (arg.documentID && - std::holds_alternative(*arg.documentID)) + if (arg.documentID && std::holds_alternative(*arg.documentID)) { documentID_ = std::get(*arg.documentID); jv[jss::OracleDocumentID] = documentID_; @@ -207,17 +199,13 @@ Oracle::set(UpdateArg const& arg) if (arg.lastUpdateTime) { if (std::holds_alternative(*arg.lastUpdateTime)) - jv[jss::LastUpdateTime] = to_string( - testStartTime.count() + - std::get(*arg.lastUpdateTime)); + jv[jss::LastUpdateTime] = to_string(testStartTime.count() + std::get(*arg.lastUpdateTime)); else toJson(jv[jss::LastUpdateTime], *arg.lastUpdateTime); } else jv[jss::LastUpdateTime] = to_string( - duration_cast( - env_.current()->header().closeTime.time_since_epoch()) - .count() + + duration_cast(env_.current()->header().closeTime.time_since_epoch()).count() + epoch_offset.count()); Json::Value dataSeries(Json::arrayValue); auto assetToStr = [](std::string const& s) { @@ -275,11 +263,9 @@ Oracle::ledgerEntry( if (account) { if (std::holds_alternative(*account)) - jvParams[jss::oracle][jss::account] = - to_string(std::get(*account)); + jvParams[jss::oracle][jss::account] = to_string(std::get(*account)); else - jvParams[jss::oracle][jss::account] = - std::get(*account); + jvParams[jss::oracle][jss::account] = std::get(*account); } if (documentID) toJson(jvParams[jss::oracle][jss::oracle_document_id], *documentID); diff --git a/src/test/jtx/impl/TestHelpers.cpp b/src/test/jtx/impl/TestHelpers.cpp index 4a9d425f01..7155c8fd0a 100644 --- a/src/test/jtx/impl/TestHelpers.cpp +++ b/src/test/jtx/impl/TestHelpers.cpp @@ -62,10 +62,7 @@ STPathElement IPE(Issue const& iss) { return STPathElement( - STPathElement::typeCurrency | STPathElement::typeIssuer, - xrpAccount(), - iss.currency, - iss.account); + STPathElement::typeCurrency | STPathElement::typeIssuer, xrpAccount(), iss.currency, iss.account); } /******************************************************************************/ @@ -84,11 +81,7 @@ xrpMinusFee(Env const& env, std::int64_t xrpAmount) }; [[nodiscard]] bool -expectHolding( - Env& env, - AccountID const& account, - STAmount const& value, - bool defaultLimits) +expectHolding(Env& env, AccountID const& account, STAmount const& value, bool defaultLimits) { if (auto const sle = env.le(keylet::line(account, value.issue()))) { @@ -104,8 +97,7 @@ expectHolding( low.setIssuer(accountLow ? account : issue.account); high.setIssuer(accountLow ? issue.account : account); - expectDefaultTrustLine = sle->getFieldAmount(sfLowLimit) == low && - sle->getFieldAmount(sfHighLimit) == high; + expectDefaultTrustLine = sle->getFieldAmount(sfLowLimit) == low && sle->getFieldAmount(sfHighLimit) == high; } auto amount = sle->getFieldAmount(sfBalance); @@ -118,21 +110,13 @@ expectHolding( } [[nodiscard]] bool -expectHolding( - Env& env, - AccountID const& account, - None const&, - Issue const& issue) +expectHolding(Env& env, AccountID const& account, None const&, Issue const& issue) { return !env.le(keylet::line(account, issue)); } [[nodiscard]] bool -expectHolding( - Env& env, - AccountID const& account, - None const&, - MPTIssue const& mptIssue) +expectHolding(Env& env, AccountID const& account, None const&, MPTIssue const& mptIssue) { return !env.le(keylet::mptoken(mptIssue.getMptID(), account)); } @@ -141,37 +125,27 @@ expectHolding( expectHolding(Env& env, AccountID const& account, None const& value) { return std::visit( - [&](auto const& issue) { - return expectHolding(env, account, value, issue); - }, - value.asset.value()); + [&](auto const& issue) { return expectHolding(env, account, value, issue); }, value.asset.value()); } [[nodiscard]] bool -expectOffers( - Env& env, - AccountID const& account, - std::uint16_t size, - std::vector const& toMatch) +expectOffers(Env& env, AccountID const& account, std::uint16_t size, std::vector const& toMatch) { std::uint16_t cnt = 0; std::uint16_t matched = 0; - forEachItem( - *env.current(), account, [&](std::shared_ptr const& sle) { - if (!sle) - return false; - if (sle->getType() == ltOFFER) - { - ++cnt; - if (std::find_if( - toMatch.begin(), toMatch.end(), [&](auto const& a) { - return a.in == sle->getFieldAmount(sfTakerPays) && - a.out == sle->getFieldAmount(sfTakerGets); - }) != toMatch.end()) - ++matched; - } - return true; - }); + forEachItem(*env.current(), account, [&](std::shared_ptr const& sle) { + if (!sle) + return false; + if (sle->getType() == ltOFFER) + { + ++cnt; + if (std::find_if(toMatch.begin(), toMatch.end(), [&](auto const& a) { + return a.in == sle->getFieldAmount(sfTakerPays) && a.out == sle->getFieldAmount(sfTakerGets); + }) != toMatch.end()) + ++matched; + } + return true; + }); return size == cnt && matched == toMatch.size(); } @@ -185,11 +159,7 @@ ledgerEntryRoot(Env& env, Account const& acct) } Json::Value -ledgerEntryState( - Env& env, - Account const& acct_a, - Account const& acct_b, - std::string const& currency) +ledgerEntryState(Env& env, Account const& acct_a, Account const& acct_b, std::string const& currency) { Json::Value jvParams; jvParams[jss::ledger_index] = "current"; @@ -208,10 +178,7 @@ accountBalance(Env& env, Account const& acct) } [[nodiscard]] bool -expectLedgerEntryRoot( - Env& env, - Account const& acct, - STAmount const& expectedValue) +expectLedgerEntryRoot(Env& env, Account const& acct, STAmount const& expectedValue) { return accountBalance(env, acct) == to_string(expectedValue.xrp()); } @@ -286,10 +253,7 @@ claim( } uint256 -channel( - AccountID const& account, - AccountID const& dst, - std::uint32_t seqProxyValue) +channel(AccountID const& account, AccountID const& dst, std::uint32_t seqProxyValue) { auto const k = keylet::payChan(account, dst, seqProxyValue); return k.key; @@ -317,12 +281,7 @@ channelExists(ReadView const& view, uint256 const& chan) /******************************************************************************/ void -n_offers( - Env& env, - std::size_t n, - Account const& account, - STAmount const& in, - STAmount const& out) +n_offers(Env& env, std::size_t n, Account const& account, STAmount const& in, STAmount const& out) { auto const ownerCount = env.le(account)->getFieldU32(sfOwnerCount); for (std::size_t i = 0; i < n; i++) @@ -340,8 +299,7 @@ n_offers( STPathElement cpe(Currency const& c) { - return STPathElement( - STPathElement::typeCurrency, xrpAccount(), c, xrpAccount()); + return STPathElement(STPathElement::typeCurrency, xrpAccount(), c, xrpAccount()); }; // All path element @@ -349,8 +307,7 @@ STPathElement allpe(AccountID const& a, Issue const& iss) { return STPathElement( - STPathElement::typeAccount | STPathElement::typeCurrency | - STPathElement::typeIssuer, + STPathElement::typeAccount | STPathElement::typeCurrency | STPathElement::typeIssuer, a, iss.currency, iss.account); @@ -384,11 +341,7 @@ del(AccountID const& account, uint256 const& brokerID, uint32_t flags) } Json::Value -coverDeposit( - AccountID const& account, - uint256 const& brokerID, - STAmount const& amount, - uint32_t flags) +coverDeposit(AccountID const& account, uint256 const& brokerID, STAmount const& amount, uint32_t flags) { Json::Value jv; jv[sfTransactionType] = jss::LoanBrokerCoverDeposit; @@ -400,11 +353,7 @@ coverDeposit( } Json::Value -coverWithdraw( - AccountID const& account, - uint256 const& brokerID, - STAmount const& amount, - uint32_t flags) +coverWithdraw(AccountID const& account, uint256 const& brokerID, STAmount const& amount, uint32_t flags) { Json::Value jv; jv[sfTransactionType] = jss::LoanBrokerCoverWithdraw; @@ -432,10 +381,7 @@ coverClawback(AccountID const& account, std::uint32_t flags) namespace loan { Json::Value -set(AccountID const& account, - uint256 const& loanBrokerID, - Number principalRequested, - std::uint32_t flags) +set(AccountID const& account, uint256 const& loanBrokerID, Number principalRequested, std::uint32_t flags) { Json::Value jv; jv[sfTransactionType] = jss::LoanSet; @@ -469,10 +415,7 @@ del(AccountID const& account, uint256 const& loanID, std::uint32_t flags) } Json::Value -pay(AccountID const& account, - uint256 const& loanID, - STAmount const& amount, - std::uint32_t flags) +pay(AccountID const& account, uint256 const& loanID, STAmount const& amount, std::uint32_t flags) { Json::Value jv; jv[sfTransactionType] = jss::LoanPay; diff --git a/src/test/jtx/impl/WSClient.cpp b/src/test/jtx/impl/WSClient.cpp index 878846b41d..c1012b57a4 100644 --- a/src/test/jtx/impl/WSClient.cpp +++ b/src/test/jtx/impl/WSClient.cpp @@ -49,8 +49,7 @@ class WSClientImpl : public WSClient continue; using namespace boost::asio::ip; if (pp.ip && pp.ip->is_unspecified()) - *pp.ip = pp.ip->is_v6() ? address{address_v6::loopback()} - : address{address_v4::loopback()}; + *pp.ip = pp.ip->is_v6() ? address{address_v6::loopback()} : address{address_v4::loopback()}; if (!pp.port) Throw("Use fixConfigPorts with auto ports"); @@ -74,9 +73,7 @@ class WSClientImpl : public WSClient } boost::asio::io_context ios_; - std::optional> - work_; + std::optional> work_; boost::asio::strand strand_; std::thread thread_; boost::asio::ip::tcp::socket stream_; @@ -100,24 +97,21 @@ class WSClientImpl : public WSClient void cleanup() { - boost::asio::post( - ios_, boost::asio::bind_executor(strand_, [this] { - if (!peerClosed_) - { - ws_.async_close( - {}, - boost::asio::bind_executor(strand_, [&](error_code) { - try - { - stream_.cancel(); - } - catch (boost::system::system_error const&) - { - // ignored - } - })); - } - })); + boost::asio::post(ios_, boost::asio::bind_executor(strand_, [this] { + if (!peerClosed_) + { + ws_.async_close({}, boost::asio::bind_executor(strand_, [&](error_code) { + try + { + stream_.cancel(); + } + catch (boost::system::system_error const&) + { + // ignored + } + })); + } + })); work_ = std::nullopt; thread_.join(); } @@ -139,22 +133,16 @@ public: { auto const ep = getEndpoint(cfg, v2); stream_.connect(ep); - ws_.set_option(boost::beast::websocket::stream_base::decorator( - [&](boost::beast::websocket::request_type& req) { + ws_.set_option( + boost::beast::websocket::stream_base::decorator([&](boost::beast::websocket::request_type& req) { for (auto const& h : headers) req.set(h.first, h.second); })); - ws_.handshake( - ep.address().to_string() + ":" + std::to_string(ep.port()), - "/"); + ws_.handshake(ep.address().to_string() + ":" + std::to_string(ep.port()), "/"); ws_.async_read( rb_, boost::asio::bind_executor( - strand_, - std::bind( - &WSClientImpl::on_read_msg, - this, - std::placeholders::_1))); + strand_, std::bind(&WSClientImpl::on_read_msg, this, std::placeholders::_1))); } catch (std::exception&) { @@ -191,9 +179,7 @@ public: ws_.write_some(true, buffer(s)); } - auto jv = findMsg(5s, [&](Json::Value const& jval) { - return jval[jss::type] == jss::response; - }); + auto jv = findMsg(5s, [&](Json::Value const& jval) { return jval[jss::type] == jss::response; }); if (jv) { // Normalize JSON output @@ -229,9 +215,7 @@ public: } std::optional - findMsg( - std::chrono::milliseconds const& timeout, - std::function pred) override + findMsg(std::chrono::milliseconds const& timeout, std::function pred) override { std::shared_ptr m; { @@ -284,10 +268,7 @@ private: } ws_.async_read( rb_, - boost::asio::bind_executor( - strand_, - std::bind( - &WSClientImpl::on_read_msg, this, std::placeholders::_1))); + boost::asio::bind_executor(strand_, std::bind(&WSClientImpl::on_read_msg, this, std::placeholders::_1))); } // Called when the read op terminates diff --git a/src/test/jtx/impl/acctdelete.cpp b/src/test/jtx/impl/acctdelete.cpp index 47ee1c39a6..0b87d501dd 100644 --- a/src/test/jtx/impl/acctdelete.cpp +++ b/src/test/jtx/impl/acctdelete.cpp @@ -25,9 +25,7 @@ void incLgrSeqForAccDel(jtx::Env& env, jtx::Account const& acc, std::uint32_t margin) { using namespace jtx; - auto openLedgerSeq = [](jtx::Env& env) -> std::uint32_t { - return env.current()->seq(); - }; + auto openLedgerSeq = [](jtx::Env& env) -> std::uint32_t { return env.current()->seq(); }; int const delta = [&]() -> int { if (env.seq(acc) + 255 > openLedgerSeq(env)) diff --git a/src/test/jtx/impl/amount.cpp b/src/test/jtx/impl/amount.cpp index 2548a4423b..73dad7f48e 100644 --- a/src/test/jtx/impl/amount.cpp +++ b/src/test/jtx/impl/amount.cpp @@ -74,15 +74,13 @@ operator<<(std::ostream& os, PrettyAmount const& amount) } else if (amount.value().holds()) { - os << amount.value().getText() << "/" - << to_string(amount.value().issue().currency) << "(" << amount.name() + os << amount.value().getText() << "/" << to_string(amount.value().issue().currency) << "(" << amount.name() << ")"; } else { auto const& mptIssue = amount.value().asset().get(); - os << amount.value().getText() << "/" << to_string(mptIssue) << "(" - << amount.name() << ")"; + os << amount.value().getText() << "/" << to_string(mptIssue) << "(" << amount.name() << ")"; } return os; } @@ -100,8 +98,7 @@ IOU::operator()(epsilon_t) const PrettyAmount IOU::operator()(detail::epsilon_multiple m) const { - return { - STAmount(issue(), safe_cast(m.n), -81), account.name()}; + return {STAmount(issue(), safe_cast(m.n), -81), account.name()}; } std::ostream& diff --git a/src/test/jtx/impl/attester.cpp b/src/test/jtx/impl/attester.cpp index 1d00767f0c..04b2a037c6 100644 --- a/src/test/jtx/impl/attester.cpp +++ b/src/test/jtx/impl/attester.cpp @@ -22,13 +22,7 @@ sign_claim_attestation( std::optional const& dst) { auto const toSign = Attestations::AttestationClaim::message( - bridge, - sendingAccount, - sendingAmount, - rewardAccount, - wasLockingChainSend, - claimID, - dst); + bridge, sendingAccount, sendingAmount, rewardAccount, wasLockingChainSend, claimID, dst); return sign(pk, sk, makeSlice(toSign)); } @@ -46,14 +40,7 @@ sign_create_account_attestation( AccountID const& dst) { auto const toSign = Attestations::AttestationCreateAccount::message( - bridge, - sendingAccount, - sendingAmount, - rewardAmount, - rewardAccount, - wasLockingChainSend, - createCount, - dst); + bridge, sendingAccount, sendingAmount, rewardAmount, rewardAccount, wasLockingChainSend, createCount, dst); return sign(pk, sk, makeSlice(toSign)); } diff --git a/src/test/jtx/impl/balance.cpp b/src/test/jtx/impl/balance.cpp index 4449be223c..9d6f5c6124 100644 --- a/src/test/jtx/impl/balance.cpp +++ b/src/test/jtx/impl/balance.cpp @@ -5,12 +5,7 @@ namespace test { namespace jtx { void -doBalance( - Env& env, - AccountID const& account, - bool none, - STAmount const& value, - Issue const& issue) +doBalance(Env& env, AccountID const& account, bool none, STAmount const& value, Issue const& issue) { if (isXRP(issue)) { @@ -43,12 +38,7 @@ doBalance( } void -doBalance( - Env& env, - AccountID const& account, - bool none, - STAmount const& value, - MPTIssue const& mptIssue) +doBalance(Env& env, AccountID const& account, bool none, STAmount const& value, MPTIssue const& mptIssue) { auto const sle = env.le(keylet::mptoken(mptIssue.getMptID(), account)); if (none) @@ -66,10 +56,7 @@ void balance::operator()(Env& env) const { return std::visit( - [&](auto const& issue) { - doBalance(env, account_.id(), none_, value_, issue); - }, - value_.asset().value()); + [&](auto const& issue) { doBalance(env, account_.id(), none_, value_, issue); }, value_.asset().value()); } } // namespace jtx diff --git a/src/test/jtx/impl/batch.cpp b/src/test/jtx/impl/batch.cpp index e0a52d0218..3f993ddea1 100644 --- a/src/test/jtx/impl/batch.cpp +++ b/src/test/jtx/impl/batch.cpp @@ -16,10 +16,7 @@ namespace jtx { namespace batch { XRPAmount -calcBatchFee( - test::jtx::Env const& env, - uint32_t const& numSigners, - uint32_t const& txns) +calcBatchFee(test::jtx::Env const& env, uint32_t const& numSigners, uint32_t const& txns) { XRPAmount const feeDrops = env.current()->fees().base; return ((numSigners + 2) * feeDrops) + feeDrops * txns; @@ -27,11 +24,7 @@ calcBatchFee( // Batch. Json::Value -outer( - jtx::Account const& account, - uint32_t seq, - STAmount const& fee, - std::uint32_t flags) +outer(jtx::Account const& account, uint32_t seq, STAmount const& fee, std::uint32_t flags) { Json::Value jv; jv[jss::TransactionType] = jss::Batch; @@ -81,10 +74,8 @@ sig::operator()(Env& env, JTx& jt) const Serializer msg; serializeBatch(msg, stx.getFlags(), stx.getBatchTransactionIDs()); - auto const sig = xrpl::sign( - *publicKeyType(e.sig.pk().slice()), e.sig.sk(), msg.slice()); - jo[sfTxnSignature.getJsonName()] = - strHex(Slice{sig.data(), sig.size()}); + auto const sig = xrpl::sign(*publicKeyType(e.sig.pk().slice()), e.sig.sk(), msg.slice()); + jo[sfTxnSignature.getJsonName()] = strHex(Slice{sig.data(), sig.size()}); } } @@ -121,10 +112,8 @@ msig::operator()(Env& env, JTx& jt) const Serializer msg; serializeBatch(msg, stx.getFlags(), stx.getBatchTransactionIDs()); finishMultiSigningData(e.acct.id(), msg); - auto const sig = xrpl::sign( - *publicKeyType(e.sig.pk().slice()), e.sig.sk(), msg.slice()); - iso[sfTxnSignature.getJsonName()] = - strHex(Slice{sig.data(), sig.size()}); + auto const sig = xrpl::sign(*publicKeyType(e.sig.pk().slice()), e.sig.sk(), msg.slice()); + iso[sfTxnSignature.getJsonName()] = strHex(Slice{sig.data(), sig.size()}); } } diff --git a/src/test/jtx/impl/check.cpp b/src/test/jtx/impl/check.cpp index 769771861d..22f348aa3f 100644 --- a/src/test/jtx/impl/check.cpp +++ b/src/test/jtx/impl/check.cpp @@ -23,10 +23,7 @@ cash(jtx::Account const& dest, uint256 const& checkId, STAmount const& amount) // Cash a check requiring that at least a minimum amount be delivered. Json::Value -cash( - jtx::Account const& dest, - uint256 const& checkId, - DeliverMin const& atLeast) +cash(jtx::Account const& dest, uint256 const& checkId, DeliverMin const& atLeast) { Json::Value jv; jv[sfAccount.jsonName] = dest.human(); diff --git a/src/test/jtx/impl/creds.cpp b/src/test/jtx/impl/creds.cpp index f93d951e48..5a9ecfec59 100644 --- a/src/test/jtx/impl/creds.cpp +++ b/src/test/jtx/impl/creds.cpp @@ -10,10 +10,7 @@ namespace jtx { namespace credentials { Json::Value -create( - jtx::Account const& subject, - jtx::Account const& issuer, - std::string_view credType) +create(jtx::Account const& subject, jtx::Account const& issuer, std::string_view credType) { Json::Value jv; jv[jss::TransactionType] = jss::CredentialCreate; @@ -26,10 +23,7 @@ create( } Json::Value -accept( - jtx::Account const& subject, - jtx::Account const& issuer, - std::string_view credType) +accept(jtx::Account const& subject, jtx::Account const& issuer, std::string_view credType) { Json::Value jv; jv[jss::TransactionType] = jss::CredentialAccept; @@ -40,11 +34,7 @@ accept( } Json::Value -deleteCred( - jtx::Account const& acc, - jtx::Account const& subject, - jtx::Account const& issuer, - std::string_view credType) +deleteCred(jtx::Account const& acc, jtx::Account const& subject, jtx::Account const& issuer, std::string_view credType) { Json::Value jv; jv[jss::TransactionType] = jss::CredentialDelete; @@ -56,11 +46,7 @@ deleteCred( } Json::Value -ledgerEntry( - jtx::Env& env, - jtx::Account const& subject, - jtx::Account const& issuer, - std::string_view credType) +ledgerEntry(jtx::Env& env, jtx::Account const& subject, jtx::Account const& issuer, std::string_view credType) { Json::Value jvParams; jvParams[jss::ledger_index] = jss::validated; diff --git a/src/test/jtx/impl/delegate.cpp b/src/test/jtx/impl/delegate.cpp index 7cca9aa738..312a3f2403 100644 --- a/src/test/jtx/impl/delegate.cpp +++ b/src/test/jtx/impl/delegate.cpp @@ -9,9 +9,7 @@ namespace jtx { namespace delegate { Json::Value -set(jtx::Account const& account, - jtx::Account const& authorize, - std::vector const& permissions) +set(jtx::Account const& account, jtx::Account const& authorize, std::vector const& permissions) { Json::Value jv; jv[jss::TransactionType] = jss::DelegateSet; diff --git a/src/test/jtx/impl/deposit.cpp b/src/test/jtx/impl/deposit.cpp index 7a49bee06a..4a2ecf0139 100644 --- a/src/test/jtx/impl/deposit.cpp +++ b/src/test/jtx/impl/deposit.cpp @@ -32,9 +32,7 @@ unauth(jtx::Account const& account, jtx::Account const& unauth) // Add DepositPreauth. Json::Value -authCredentials( - jtx::Account const& account, - std::vector const& auth) +authCredentials(jtx::Account const& account, std::vector const& auth) { Json::Value jv; jv[sfAccount.jsonName] = account.human(); @@ -52,9 +50,7 @@ authCredentials( // Remove DepositPreauth. Json::Value -unauthCredentials( - jtx::Account const& account, - std::vector const& auth) +unauthCredentials(jtx::Account const& account, std::vector const& auth) { Json::Value jv; jv[sfAccount.jsonName] = account.human(); diff --git a/src/test/jtx/impl/directory.cpp b/src/test/jtx/impl/directory.cpp index bb44b8d782..7231389d1e 100644 --- a/src/test/jtx/impl/directory.cpp +++ b/src/test/jtx/impl/directory.cpp @@ -12,97 +12,94 @@ bumpLastPage( Env& env, std::uint64_t newLastPage, Keylet directory, - std::function adjust) - -> Expected + std::function adjust) -> Expected { Expected res{}; - env.app().openLedger().modify( - [&](OpenView& view, beast::Journal j) -> bool { - Sandbox sb(&view, tapNONE); + env.app().openLedger().modify([&](OpenView& view, beast::Journal j) -> bool { + Sandbox sb(&view, tapNONE); - // Find the root page - auto sleRoot = sb.peek(directory); - if (!sleRoot) - { - res = Unexpected(DirectoryRootNotFound); - return false; - } + // Find the root page + auto sleRoot = sb.peek(directory); + if (!sleRoot) + { + res = Unexpected(DirectoryRootNotFound); + return false; + } - // Find last page - auto const lastIndex = sleRoot->getFieldU64(sfIndexPrevious); - if (lastIndex == 0) - { - res = Unexpected(DirectoryTooSmall); - return false; - } + // Find last page + auto const lastIndex = sleRoot->getFieldU64(sfIndexPrevious); + if (lastIndex == 0) + { + res = Unexpected(DirectoryTooSmall); + return false; + } - if (sb.exists(keylet::page(directory, newLastPage))) - { - res = Unexpected(DirectoryPageDuplicate); - return false; - } + if (sb.exists(keylet::page(directory, newLastPage))) + { + res = Unexpected(DirectoryPageDuplicate); + return false; + } - if (lastIndex >= newLastPage) - { - res = Unexpected(InvalidLastPage); - return false; - } + if (lastIndex >= newLastPage) + { + res = Unexpected(InvalidLastPage); + return false; + } - auto slePage = sb.peek(keylet::page(directory, lastIndex)); - if (!slePage) + auto slePage = sb.peek(keylet::page(directory, lastIndex)); + if (!slePage) + { + res = Unexpected(DirectoryPageNotFound); + return false; + } + + // Copy its data and delete the page + auto indexes = slePage->getFieldV256(sfIndexes); + auto prevIndex = slePage->at(~sfIndexPrevious); + auto owner = slePage->at(~sfOwner); + sb.erase(slePage); + + // Create new page to replace slePage + auto sleNew = std::make_shared(keylet::page(directory, newLastPage)); + sleNew->setFieldH256(sfRootIndex, directory.key); + sleNew->setFieldV256(sfIndexes, indexes); + if (owner) + sleNew->setAccountID(sfOwner, *owner); + if (prevIndex) + sleNew->setFieldU64(sfIndexPrevious, *prevIndex); + sb.insert(sleNew); + + // Adjust root previous and previous node's next + sleRoot->setFieldU64(sfIndexPrevious, newLastPage); + if (prevIndex.value_or(0) == 0) + sleRoot->setFieldU64(sfIndexNext, newLastPage); + else + { + auto slePrev = sb.peek(keylet::page(directory, *prevIndex)); + if (!slePrev) { res = Unexpected(DirectoryPageNotFound); return false; } + slePrev->setFieldU64(sfIndexNext, newLastPage); + sb.update(slePrev); + } + sb.update(sleRoot); - // Copy its data and delete the page - auto indexes = slePage->getFieldV256(sfIndexes); - auto prevIndex = slePage->at(~sfIndexPrevious); - auto owner = slePage->at(~sfOwner); - sb.erase(slePage); - - // Create new page to replace slePage - auto sleNew = - std::make_shared(keylet::page(directory, newLastPage)); - sleNew->setFieldH256(sfRootIndex, directory.key); - sleNew->setFieldV256(sfIndexes, indexes); - if (owner) - sleNew->setAccountID(sfOwner, *owner); - if (prevIndex) - sleNew->setFieldU64(sfIndexPrevious, *prevIndex); - sb.insert(sleNew); - - // Adjust root previous and previous node's next - sleRoot->setFieldU64(sfIndexPrevious, newLastPage); - if (prevIndex.value_or(0) == 0) - sleRoot->setFieldU64(sfIndexNext, newLastPage); - else + // Fixup page numbers in the objects referred by indexes + if (adjust) + for (auto const key : indexes) { - auto slePrev = sb.peek(keylet::page(directory, *prevIndex)); - if (!slePrev) + if (!adjust(sb, key, newLastPage)) { - res = Unexpected(DirectoryPageNotFound); + res = Unexpected(AdjustmentError); return false; } - slePrev->setFieldU64(sfIndexNext, newLastPage); - sb.update(slePrev); } - sb.update(sleRoot); - // Fixup page numbers in the objects referred by indexes - if (adjust) - for (auto const key : indexes) - { - if (!adjust(sb, key, newLastPage)) - { - res = Unexpected(AdjustmentError); - return false; - } - } - - sb.apply(view); - return true; - }); + sb.apply(view); + return true; + }); return res; } diff --git a/src/test/jtx/impl/envconfig.cpp b/src/test/jtx/impl/envconfig.cpp index 67bbe3b457..1def778c69 100644 --- a/src/test/jtx/impl/envconfig.cpp +++ b/src/test/jtx/impl/envconfig.cpp @@ -94,8 +94,7 @@ std::unique_ptr validator(std::unique_ptr cfg, std::string const& seed) { // If the config has valid validation keys then we run as a validator. - cfg->section(SECTION_VALIDATION_SEED) - .append(std::vector{seed.empty() ? defaultseed : seed}); + cfg->section(SECTION_VALIDATION_SEED).append(std::vector{seed.empty() ? defaultseed : seed}); return cfg; } @@ -108,9 +107,7 @@ addGrpcConfig(std::unique_ptr cfg) } std::unique_ptr -addGrpcConfigWithSecureGateway( - std::unique_ptr cfg, - std::string const& secureGateway) +addGrpcConfigWithSecureGateway(std::unique_ptr cfg, std::string const& secureGateway) { (*cfg)[SECTION_PORT_GRPC].set("ip", getEnvLocalhostAddr()); @@ -122,9 +119,7 @@ addGrpcConfigWithSecureGateway( } std::unique_ptr -makeConfig( - std::map extraTxQ, - std::map extraVoting) +makeConfig(std::map extraTxQ, std::map extraVoting) { auto p = test::jtx::envconfig(); auto& section = p->section("transaction_queue"); diff --git a/src/test/jtx/impl/mpt.cpp b/src/test/jtx/impl/mpt.cpp index ceb60eb319..90378fae90 100644 --- a/src/test/jtx/impl/mpt.cpp +++ b/src/test/jtx/impl/mpt.cpp @@ -39,10 +39,7 @@ MPTTester::makeHolders(std::vector const& holders) } MPTTester::MPTTester(Env& env, Account const& issuer, MPTInit const& arg) - : env_(env) - , issuer_(issuer) - , holders_(makeHolders(arg.holders)) - , close_(arg.close) + : env_(env), issuer_(issuer), holders_(makeHolders(arg.holders)), close_(arg.close) { if (arg.fund) { @@ -66,17 +63,8 @@ MPTTester::MPTTester(Env& env, Account const& issuer, MPTInit const& arg) create(*arg.create); } -MPTTester::MPTTester( - Env& env, - Account const& issuer, - MPTID const& id, - std::vector const& holders, - bool close) - : env_(env) - , issuer_(issuer) - , holders_(makeHolders(holders)) - , id_(id) - , close_(close) +MPTTester::MPTTester(Env& env, Account const& issuer, MPTID const& id, std::vector const& holders, bool close) + : env_(env), issuer_(issuer), holders_(makeHolders(holders)), id_(id), close_(close) { } @@ -99,13 +87,7 @@ makeMPTCreate(MPTInitDef const& arg) } MPTTester::MPTTester(MPTInitDef const& arg) - : MPTTester{ - arg.env, - arg.issuer, - MPTInit{ - .fund = arg.fund, - .close = arg.close, - .create = makeMPTCreate(arg)}} + : MPTTester{arg.env, arg.issuer, MPTInit{.fund = arg.fund, .close = arg.close, .create = makeMPTCreate(arg)}} { } @@ -157,9 +139,7 @@ MPTTester::create(MPTCreate const& arg) if (submit(arg, jv) != tesSUCCESS) { // Verify issuance doesn't exist - env_.require(requireAny([&]() -> bool { - return env_.le(keylet::mptIssuance(*id_)) == nullptr; - })); + env_.require(requireAny([&]() -> bool { return env_.le(keylet::mptIssuance(*id_)) == nullptr; })); id_.reset(); } @@ -170,8 +150,7 @@ MPTTester::create(MPTCreate const& arg) for (auto const& it : accts) { authorize({.account = getAcct(it)}); - if ((arg.flags.value_or(0) & tfMPTRequireAuth) && - arg.authHolder) + if ((arg.flags.value_or(0) & tfMPTRequireAuth) && arg.authHolder) authorize({.account = issuer_, .holder = getAcct(it)}); if (arg.pay && arg.pay->first.empty()) pay(issuer_, getAcct(it), arg.pay->second); @@ -217,9 +196,7 @@ MPTTester::destroy(MPTDestroy const& arg) { if (!arg.id && !id_) Throw("MPT has not been created"); - Json::Value jv = destroyjv( - {.issuer = arg.issuer ? arg.issuer : issuer_, - .id = arg.id ? arg.id : id_}); + Json::Value jv = destroyjv({.issuer = arg.issuer ? arg.issuer : issuer_, .id = arg.id ? arg.id : id_}); submit(arg, jv); } @@ -237,8 +214,7 @@ MPTTester::authorizejv(MPTAuthorize const& arg) { Json::Value jv; if (!arg.account || !arg.id) - Throw( - "MPTTester::authorizejv: issuer/id is not set"); + Throw("MPTTester::authorizejv: issuer/id is not set"); jv[sfAccount] = arg.account->human(); jv[sfMPTokenIssuanceID] = to_string(*arg.id); if (arg.holder) @@ -269,8 +245,7 @@ MPTTester::authorize(MPTAuthorize const& arg) env_.require(mptflags(*this, flags, arg.holder)); // issuer authorizes the holder else - env_.require( - mptflags(*this, flags | lsfMPTAuthorized, arg.holder)); + env_.require(mptflags(*this, flags | lsfMPTAuthorized, arg.holder)); } // Holder authorizes else if (arg.flags.value_or(0) != tfMPTUnauthorize) @@ -283,31 +258,23 @@ MPTTester::authorize(MPTAuthorize const& arg) else { // Verify that the MPToken doesn't exist. - forObject( - [&](SLEP const& sle) { return env_.test.BEAST_EXPECT(!sle); }, - arg.account); + forObject([&](SLEP const& sle) { return env_.test.BEAST_EXPECT(!sle); }, arg.account); } } - else if ( - arg.account && *arg.account != issuer_ && - arg.flags.value_or(0) != tfMPTUnauthorize && id_) + else if (arg.account && *arg.account != issuer_ && arg.flags.value_or(0) != tfMPTUnauthorize && id_) { if (result == tecDUPLICATE) { // Verify that MPToken already exists - env_.require(requireAny([&]() -> bool { - return env_.le(keylet::mptoken(*id_, arg.account->id())) != - nullptr; - })); + env_.require( + requireAny([&]() -> bool { return env_.le(keylet::mptoken(*id_, arg.account->id())) != nullptr; })); } else { // Verify MPToken doesn't exist if holder failed authorizing(unless // it already exists) - env_.require(requireAny([&]() -> bool { - return env_.le(keylet::mptoken(*id_, arg.account->id())) == - nullptr; - })); + env_.require( + requireAny([&]() -> bool { return env_.le(keylet::mptoken(*id_, arg.account->id())) == nullptr; })); } } } @@ -370,11 +337,9 @@ MPTTester::set(MPTSet const& arg) .metadata = arg.metadata, .delegate = arg.delegate, .domainID = arg.domainID}); - if (submit(arg, jv) == tesSUCCESS && - (arg.flags.value_or(0) || arg.mutableFlags)) + if (submit(arg, jv) == tesSUCCESS && (arg.flags.value_or(0) || arg.mutableFlags)) { - auto require = [&](std::optional const& holder, - bool unchanged) { + auto require = [&](std::optional const& holder, bool unchanged) { auto flags = getFlags(holder); if (!unchanged) { @@ -423,21 +388,17 @@ MPTTester::set(MPTSet const& arg) }; if (arg.account) require(std::nullopt, arg.holder.has_value()); - if (auto const account = - (arg.holder ? std::get_if(&(*arg.holder)) : nullptr)) + if (auto const account = (arg.holder ? std::get_if(&(*arg.holder)) : nullptr)) require(*account, false); } } bool -MPTTester::forObject( - std::function const& cb, - std::optional const& holder_) const +MPTTester::forObject(std::function const& cb, std::optional const& holder_) const { if (!id_) Throw("MPT has not been created"); - auto const key = holder_ ? keylet::mptoken(*id_, holder_->id()) - : keylet::mptIssuance(*id_); + auto const key = holder_ ? keylet::mptoken(*id_, holder_->id()) : keylet::mptIssuance(*id_); if (auto const sle = env_.le(key)) return cb(sle); return false; @@ -454,27 +415,19 @@ MPTTester::checkDomainID(std::optional expected) const } [[nodiscard]] bool -MPTTester::checkMPTokenAmount( - Account const& holder_, - std::int64_t expectedAmount) const +MPTTester::checkMPTokenAmount(Account const& holder_, std::int64_t expectedAmount) const { - return forObject( - [&](SLEP const& sle) { return expectedAmount == (*sle)[sfMPTAmount]; }, - holder_); + return forObject([&](SLEP const& sle) { return expectedAmount == (*sle)[sfMPTAmount]; }, holder_); } [[nodiscard]] bool MPTTester::checkMPTokenOutstandingAmount(std::int64_t expectedAmount) const { - return forObject([&](SLEP const& sle) { - return expectedAmount == (*sle)[sfOutstandingAmount]; - }); + return forObject([&](SLEP const& sle) { return expectedAmount == (*sle)[sfOutstandingAmount]; }); } [[nodiscard]] bool -MPTTester::checkFlags( - uint32_t const expectedFlags, - std::optional const& holder) const +MPTTester::checkFlags(uint32_t const expectedFlags, std::optional const& holder) const { return expectedFlags == getFlags(holder); } @@ -484,8 +437,7 @@ MPTTester::checkMetadata(std::string const& metadata) const { return forObject([&](SLEP const& sle) -> bool { if (sle->isFieldPresent(sfMPTokenMetadata)) - return strHex(sle->getFieldVL(sfMPTokenMetadata)) == - strHex(metadata); + return strHex(sle->getFieldVL(sfMPTokenMetadata)) == strHex(metadata); return false; }); } @@ -493,9 +445,7 @@ MPTTester::checkMetadata(std::string const& metadata) const [[nodiscard]] bool MPTTester::isMetadataPresent() const { - return forObject([&](SLEP const& sle) -> bool { - return sle->isFieldPresent(sfMPTokenMetadata); - }); + return forObject([&](SLEP const& sle) -> bool { return sle->isFieldPresent(sfMPTokenMetadata); }); } [[nodiscard]] bool @@ -511,9 +461,7 @@ MPTTester::checkTransferFee(std::uint16_t transferFee) const [[nodiscard]] bool MPTTester::isTransferFeePresent() const { - return forObject([&](SLEP const& sle) -> bool { - return sle->isFieldPresent(sfTransferFee); - }); + return forObject([&](SLEP const& sle) -> bool { return sle->isFieldPresent(sfTransferFee); }); } void @@ -531,10 +479,7 @@ MPTTester::pay( auto const outstnAmt = getBalance(issuer_); if (credentials) - env_( - jtx::pay(src, dest, mpt(amount)), - ter(err.value_or(tesSUCCESS)), - credentials::ids(*credentials)); + env_(jtx::pay(src, dest, mpt(amount)), ter(err.value_or(tesSUCCESS)), credentials::ids(*credentials)); else env_(jtx::pay(src, dest, mpt(amount)), ter(err.value_or(tesSUCCESS))); @@ -555,10 +500,7 @@ MPTTester::pay( else { STAmount const saAmount = {*id_, amount}; - auto const actual = - multiply(saAmount, transferRate(*env_.current(), *id_)) - .mpt() - .value(); + auto const actual = multiply(saAmount, transferRate(*env_.current(), *id_)).mpt().value(); // Sender pays the transfer fee if any env_.require(mptbalance(*this, src, srcAmt - actual)); env_.require(mptbalance(*this, dest, destAmt + amount)); @@ -568,11 +510,7 @@ MPTTester::pay( } void -MPTTester::claw( - Account const& issuer, - Account const& holder, - std::int64_t amount, - std::optional err) +MPTTester::claw(Account const& issuer, Account const& holder, std::int64_t amount, std::optional err) { if (!id_) Throw("MPT has not been created"); @@ -584,10 +522,8 @@ MPTTester::claw( if (close_) env_.close(); - env_.require( - mptbalance(*this, issuer, issuerAmt - std::min(holderAmt, amount))); - env_.require( - mptbalance(*this, holder, holderAmt - std::min(holderAmt, amount))); + env_.require(mptbalance(*this, issuer, issuerAmt - std::min(holderAmt, amount))); + env_.require(mptbalance(*this, holder, holderAmt - std::min(holderAmt, amount))); } PrettyAmount diff --git a/src/test/jtx/impl/multisign.cpp b/src/test/jtx/impl/multisign.cpp index 61af11fb3a..54bde3ebb9 100644 --- a/src/test/jtx/impl/multisign.cpp +++ b/src/test/jtx/impl/multisign.cpp @@ -12,10 +12,7 @@ namespace test { namespace jtx { Json::Value -signers( - Account const& account, - std::uint32_t quorum, - std::vector const& v) +signers(Account const& account, std::uint32_t quorum, std::vector const& v) { Json::Value jv; jv[jss::Account] = account.human(); @@ -78,10 +75,8 @@ msig::operator()(Env& env, JTx& jt) const jo[jss::SigningPubKey] = strHex(e.sig.pk().slice()); Serializer ss{buildMultiSigningData(*st, e.acct.id())}; - auto const sig = xrpl::sign( - *publicKeyType(e.sig.pk().slice()), e.sig.sk(), ss.slice()); - jo[sfTxnSignature.getJsonName()] = - strHex(Slice{sig.data(), sig.size()}); + auto const sig = xrpl::sign(*publicKeyType(e.sig.pk().slice()), e.sig.sk(), ss.slice()); + jo[sfTxnSignature.getJsonName()] = strHex(Slice{sig.data(), sig.size()}); } }; if (!subField) diff --git a/src/test/jtx/impl/offer.cpp b/src/test/jtx/impl/offer.cpp index 251b659f3b..bbcfbf07c1 100644 --- a/src/test/jtx/impl/offer.cpp +++ b/src/test/jtx/impl/offer.cpp @@ -7,11 +7,7 @@ namespace test { namespace jtx { Json::Value -offer( - Account const& account, - STAmount const& takerPays, - STAmount const& takerGets, - std::uint32_t flags) +offer(Account const& account, STAmount const& takerPays, STAmount const& takerGets, std::uint32_t flags) { Json::Value jv; jv[jss::Account] = account.human(); diff --git a/src/test/jtx/impl/owners.cpp b/src/test/jtx/impl/owners.cpp index ad449dab93..ee6efc171c 100644 --- a/src/test/jtx/impl/owners.cpp +++ b/src/test/jtx/impl/owners.cpp @@ -7,20 +7,15 @@ std::uint32_t owned_count_of(ReadView const& view, AccountID const& id, LedgerEntryType type) { std::uint32_t count = 0; - forEachItem( - view, id, [&count, type](std::shared_ptr const& sle) { - if (sle->getType() == type) - ++count; - }); + forEachItem(view, id, [&count, type](std::shared_ptr const& sle) { + if (sle->getType() == type) + ++count; + }); return count; } void -owned_count_helper( - test::jtx::Env& env, - AccountID const& id, - LedgerEntryType type, - std::uint32_t value) +owned_count_helper(test::jtx::Env& env, AccountID const& id, LedgerEntryType type, std::uint32_t value) { env.test.expect(owned_count_of(*env.current(), id, type) == value); } diff --git a/src/test/jtx/impl/paths.cpp b/src/test/jtx/impl/paths.cpp index fd93ebd841..e26f214fe4 100644 --- a/src/test/jtx/impl/paths.cpp +++ b/src/test/jtx/impl/paths.cpp @@ -30,8 +30,7 @@ paths::operator()(Env& env, JTx& jt) const } Pathfinder pf( - std::make_shared( - env.current(), env.app().journal("RippleLineCache")), + std::make_shared(env.current(), env.app().journal("RippleLineCache")), from, to, in_.currency, diff --git a/src/test/jtx/impl/permissioned_domains.cpp b/src/test/jtx/impl/permissioned_domains.cpp index aac9dcc05f..fb802cf084 100644 --- a/src/test/jtx/impl/permissioned_domains.cpp +++ b/src/test/jtx/impl/permissioned_domains.cpp @@ -8,10 +8,7 @@ namespace pdomain { // helpers // Make json for PermissionedDomainSet transaction Json::Value -setTx( - AccountID const& account, - Credentials const& credentials, - std::optional domain) +setTx(AccountID const& account, Credentials const& credentials, std::optional domain) { Json::Value jv; jv[sfTransactionType] = jss::PermissionedDomainSet; @@ -62,8 +59,7 @@ getObjects(Account const& account, Env& env, bool withType) if (withType) { // impossible to get there Throw( - "Invalid object type: " + - object["LedgerEntryType"].asString()); // LCOV_EXCL_LINE + "Invalid object type: " + object["LedgerEntryType"].asString()); // LCOV_EXCL_LINE } continue; } @@ -83,8 +79,7 @@ objectExists(uint256 const& objID, Env& env) Json::Value params; params[jss::index] = to_string(objID); - auto const result = - env.rpc("json", "ledger_entry", to_string(params))["result"]; + auto const result = env.rpc("json", "ledger_entry", to_string(params))["result"]; if ((result["status"] == "error") && (result["error"] == "entryNotFound")) return false; @@ -100,9 +95,7 @@ objectExists(uint256 const& objID, Env& env) // Extract credentials from account_object object Credentials -credentialsFromJson( - Json::Value const& object, - std::unordered_map const& human2Acc) +credentialsFromJson(Json::Value const& object, std::unordered_map const& human2Acc) { Credentials ret; Json::Value credentials(Json::arrayValue); @@ -114,9 +107,7 @@ credentialsFromJson( auto const& issuer = obj[jss::Issuer]; auto const& credentialType = obj["CredentialType"]; auto blob = strUnHex(credentialType.asString()).value(); - ret.push_back( - {human2Acc.at(issuer.asString()), - std::string(blob.begin(), blob.end())}); + ret.push_back({human2Acc.at(issuer.asString()), std::string(blob.begin(), blob.end())}); } return ret; } @@ -142,13 +133,11 @@ getNewDomain(std::shared_ptr const& meta) for (auto const& node : a) { - if (!node.isMember("CreatedNode") || - node["CreatedNode"]["LedgerEntryType"] != "PermissionedDomain") + if (!node.isMember("CreatedNode") || node["CreatedNode"]["LedgerEntryType"] != "PermissionedDomain") { continue; } - std::ignore = - ret.parseHex(node["CreatedNode"]["LedgerIndex"].asString()); + std::ignore = ret.parseHex(node["CreatedNode"]["LedgerIndex"].asString()); break; } diff --git a/src/test/jtx/impl/quality2.cpp b/src/test/jtx/impl/quality2.cpp index c202592b9d..bbd0cff319 100644 --- a/src/test/jtx/impl/quality2.cpp +++ b/src/test/jtx/impl/quality2.cpp @@ -7,14 +7,12 @@ namespace xrpl { namespace test { namespace jtx { -qualityInPercent::qualityInPercent(double percent) - : qIn_(static_cast((percent / 100) * QUALITY_ONE)) +qualityInPercent::qualityInPercent(double percent) : qIn_(static_cast((percent / 100) * QUALITY_ONE)) { assert(percent <= 400 && percent >= 0); } -qualityOutPercent::qualityOutPercent(double percent) - : qOut_(static_cast((percent / 100) * QUALITY_ONE)) +qualityOutPercent::qualityOutPercent(double percent) : qOut_(static_cast((percent / 100) * QUALITY_ONE)) { assert(percent <= 400 && percent >= 0); } diff --git a/src/test/jtx/impl/token.cpp b/src/test/jtx/impl/token.cpp index f74b66f9ae..172bd75bc7 100644 --- a/src/test/jtx/impl/token.cpp +++ b/src/test/jtx/impl/token.cpp @@ -54,8 +54,7 @@ getNextID( std::uint16_t xferFee) { // Get the nftSeq from the account root of the issuer. - std::uint32_t const nftSeq = { - env.le(issuer)->at(~sfMintedNFTokens).value_or(0)}; + std::uint32_t const nftSeq = {env.le(issuer)->at(~sfMintedNFTokens).value_or(0)}; return token::getID(env, issuer, nfTokenTaxon, nftSeq, flags, xferFee); } @@ -70,10 +69,8 @@ getID( { // We must add issuer's FirstNFTokenSequence to offset the starting NFT // sequence number. - nftSeq += - env.le(issuer)->at(~sfFirstNFTokenSequence).value_or(env.seq(issuer)); - return xrpl::NFTokenMint::createNFTokenID( - flags, xferFee, issuer, nft::toTaxon(nfTokenTaxon), nftSeq); + nftSeq += env.le(issuer)->at(~sfFirstNFTokenSequence).value_or(env.seq(issuer)); + return xrpl::NFTokenMint::createNFTokenID(flags, xferFee, issuer, nft::toTaxon(nfTokenTaxon), nftSeq); } Json::Value @@ -87,10 +84,7 @@ burn(jtx::Account const& account, uint256 const& nftokenID) } Json::Value -createOffer( - jtx::Account const& account, - uint256 const& nftokenID, - STAmount const& amount) +createOffer(jtx::Account const& account, uint256 const& nftokenID, STAmount const& amount) { Json::Value jv; jv[sfAccount.jsonName] = account.human(); @@ -135,17 +129,13 @@ cancelOfferImpl(jtx::Account const& account, T const& nftokenOffers) } Json::Value -cancelOffer( - jtx::Account const& account, - std::initializer_list const& nftokenOffers) +cancelOffer(jtx::Account const& account, std::initializer_list const& nftokenOffers) { return cancelOfferImpl(account, nftokenOffers); } Json::Value -cancelOffer( - jtx::Account const& account, - std::vector const& nftokenOffers) +cancelOffer(jtx::Account const& account, std::vector const& nftokenOffers) { return cancelOfferImpl(account, nftokenOffers); } @@ -177,10 +167,7 @@ acceptSellOffer(jtx::Account const& account, uint256 const& offerIndex) } Json::Value -brokerOffers( - jtx::Account const& account, - uint256 const& buyOfferIndex, - uint256 const& sellOfferIndex) +brokerOffers(jtx::Account const& account, uint256 const& buyOfferIndex, uint256 const& sellOfferIndex) { Json::Value jv; jv[sfAccount.jsonName] = account.human(); diff --git a/src/test/jtx/impl/trust.cpp b/src/test/jtx/impl/trust.cpp index a553efa7f2..08cd4ef94c 100644 --- a/src/test/jtx/impl/trust.cpp +++ b/src/test/jtx/impl/trust.cpp @@ -27,11 +27,7 @@ trust(Account const& account, STAmount const& amount, std::uint32_t flags) // authorises peer (third function parameter) to hold a certain currency // (amount, the second function parameter) Json::Value -trust( - Account const& account, - STAmount const& amount, - Account const& peer, - std::uint32_t flags) +trust(Account const& account, STAmount const& amount, Account const& peer, std::uint32_t flags) { if (isXRP(amount)) Throw("trust() requires IOU"); @@ -47,10 +43,7 @@ trust( } Json::Value -claw( - Account const& account, - STAmount const& amount, - std::optional const& mptHolder) +claw(Account const& account, STAmount const& amount, std::optional const& mptHolder) { Json::Value jv; jv[jss::Account] = account.human(); diff --git a/src/test/jtx/impl/utility.cpp b/src/test/jtx/impl/utility.cpp index 920e715c16..7332358031 100644 --- a/src/test/jtx/impl/utility.cpp +++ b/src/test/jtx/impl/utility.cpp @@ -63,10 +63,7 @@ fill_seq(Json::Value& jv, ReadView const& view) } Json::Value -cmdToJSONRPC( - std::vector const& args, - beast::Journal j, - unsigned int apiVersion) +cmdToJSONRPC(std::vector const& args, beast::Journal j, unsigned int apiVersion) { Json::Value jv = Json::Value(Json::objectValue); auto const paramsObj = rpcCmdToJson(args, jv, apiVersion, j); @@ -75,9 +72,7 @@ cmdToJSONRPC( jv.clear(); // Allow parser to rewrite method. - jv[jss::method] = paramsObj.isMember(jss::method) - ? paramsObj[jss::method].asString() - : args[0]; + jv[jss::method] = paramsObj.isMember(jss::method) ? paramsObj[jss::method].asString() : args[0]; // If paramsObj is not empty, put it in a [params] array. if (paramsObj.begin() != paramsObj.end()) diff --git a/src/test/jtx/impl/xchain_bridge.cpp b/src/test/jtx/impl/xchain_bridge.cpp index cc6be6c737..0f78ed3029 100644 --- a/src/test/jtx/impl/xchain_bridge.cpp +++ b/src/test/jtx/impl/xchain_bridge.cpp @@ -61,8 +61,7 @@ bridge_create( jv[sfXChainBridge.getJsonName()] = bridge; jv[sfSignatureReward.getJsonName()] = reward.getJson(JsonOptions::none); if (minAccountCreate) - jv[sfMinAccountCreateAmount.getJsonName()] = - minAccountCreate->getJson(JsonOptions::none); + jv[sfMinAccountCreateAmount.getJsonName()] = minAccountCreate->getJson(JsonOptions::none); jv[jss::TransactionType] = jss::XChainCreateBridge; return jv; @@ -80,11 +79,9 @@ bridge_modify( jv[jss::Account] = acc.human(); jv[sfXChainBridge.getJsonName()] = bridge; if (reward) - jv[sfSignatureReward.getJsonName()] = - reward->getJson(JsonOptions::none); + jv[sfSignatureReward.getJsonName()] = reward->getJson(JsonOptions::none); if (minAccountCreate) - jv[sfMinAccountCreateAmount.getJsonName()] = - minAccountCreate->getJson(JsonOptions::none); + jv[sfMinAccountCreateAmount.getJsonName()] = minAccountCreate->getJson(JsonOptions::none); jv[jss::TransactionType] = jss::XChainModifyBridge; return jv; @@ -163,8 +160,7 @@ sidechain_xchain_account_create( jv[sfXChainBridge.getJsonName()] = bridge; jv[sfDestination.getJsonName()] = dst.human(); jv[sfAmount.getJsonName()] = amt.value.getJson(JsonOptions::none); - jv[sfSignatureReward.getJsonName()] = - reward.value.getJson(JsonOptions::none); + jv[sfSignatureReward.getJsonName()] = reward.value.getJson(JsonOptions::none); jv[jss::TransactionType] = jss::XChainAccountCreateCommit; return jv; @@ -187,15 +183,7 @@ claim_attestation( auto const& pk = signer.account.pk(); auto const& sk = signer.account.sk(); auto const sig = sign_claim_attestation( - pk, - sk, - stBridge, - sendingAccount, - sendingAmount.value, - rewardAccount, - wasLockingChainSend, - claimID, - dst); + pk, sk, stBridge, sendingAccount, sendingAmount.value, rewardAccount, wasLockingChainSend, claimID, dst); Json::Value result; @@ -206,13 +194,11 @@ claim_attestation( result[sfPublicKey.getJsonName()] = strHex(pk.slice()); result[sfSignature.getJsonName()] = strHex(sig); result[sfOtherChainSource.getJsonName()] = toBase58(sendingAccount); - result[sfAmount.getJsonName()] = - sendingAmount.value.getJson(JsonOptions::none); + result[sfAmount.getJsonName()] = sendingAmount.value.getJson(JsonOptions::none); result[sfAttestationRewardAccount.getJsonName()] = toBase58(rewardAccount); result[sfWasLockingChainSend.getJsonName()] = wasLockingChainSend ? 1 : 0; - result[sfXChainClaimID.getJsonName()] = - STUInt64{claimID}.getJson(JsonOptions::none); + result[sfXChainClaimID.getJsonName()] = STUInt64{claimID}.getJson(JsonOptions::none); if (dst) result[sfDestination.getJsonName()] = toBase58(*dst); @@ -259,16 +245,13 @@ create_account_attestation( result[sfPublicKey.getJsonName()] = strHex(pk.slice()); result[sfSignature.getJsonName()] = strHex(sig); result[sfOtherChainSource.getJsonName()] = toBase58(sendingAccount); - result[sfAmount.getJsonName()] = - sendingAmount.value.getJson(JsonOptions::none); + result[sfAmount.getJsonName()] = sendingAmount.value.getJson(JsonOptions::none); result[sfAttestationRewardAccount.getJsonName()] = toBase58(rewardAccount); result[sfWasLockingChainSend.getJsonName()] = wasLockingChainSend ? 1 : 0; - result[sfXChainAccountCreateCount.getJsonName()] = - STUInt64{createCount}.getJson(JsonOptions::none); + result[sfXChainAccountCreateCount.getJsonName()] = STUInt64{createCount}.getJson(JsonOptions::none); result[sfDestination.getJsonName()] = toBase58(dst); - result[sfSignatureReward.getJsonName()] = - rewardAmount.value.getJson(JsonOptions::none); + result[sfSignatureReward.getJsonName()] = rewardAmount.value.getJson(JsonOptions::none); result[jss::TransactionType] = jss::XChainAddAccountCreateAttestation; @@ -366,8 +349,7 @@ XChainBridgeObjects::XChainBridgeObjects() , scuGw("scuGw") , mcUSD(mcGw["USD"]) , scUSD(scGw["USD"]) - , jvXRPBridgeRPC( - bridge_rpc(mcDoor, xrpIssue(), Account::master, xrpIssue())) + , jvXRPBridgeRPC(bridge_rpc(mcDoor, xrpIssue(), Account::master, xrpIssue())) , jvb(bridge(mcDoor, xrpIssue(), Account::master, xrpIssue())) , jvub(bridge(mcuDoor, xrpIssue(), Account::master, xrpIssue())) , features(testable_amendments() | FeatureBitset{featureXChainBridge}) @@ -378,9 +360,7 @@ XChainBridgeObjects::XChainBridgeObjects() for (int i = 0; i < numSigners; ++i) { using namespace std::literals; - auto const a = Account( - "signer_"s + std::to_string(i), - (i % 2) ? KeyType::ed25519 : KeyType::secp256k1); + auto const a = Account("signer_"s + std::to_string(i), (i % 2) ? KeyType::ed25519 : KeyType::secp256k1); result.emplace_back(a); } return result; @@ -392,9 +372,7 @@ XChainBridgeObjects::XChainBridgeObjects() for (int i = 0; i < numSigners; ++i) { using namespace std::literals; - auto const a = Account( - "alt_signer_"s + std::to_string(i), - (i % 2) ? KeyType::ed25519 : KeyType::secp256k1); + auto const a = Account("alt_signer_"s + std::to_string(i), (i % 2) ? KeyType::ed25519 : KeyType::secp256k1); result.emplace_back(a); } return result; @@ -421,23 +399,12 @@ XChainBridgeObjects::XChainBridgeObjects() }()) , quorum(UT_XCHAIN_DEFAULT_QUORUM) , reward(XRP(1)) - , split_reward_quorum( - divide(reward, STAmount(UT_XCHAIN_DEFAULT_QUORUM), reward.issue())) - , split_reward_everyone(divide( - reward, - STAmount(UT_XCHAIN_DEFAULT_NUM_SIGNERS), - reward.issue())) + , split_reward_quorum(divide(reward, STAmount(UT_XCHAIN_DEFAULT_QUORUM), reward.issue())) + , split_reward_everyone(divide(reward, STAmount(UT_XCHAIN_DEFAULT_NUM_SIGNERS), reward.issue())) , tiny_reward(drops(37)) - , tiny_reward_split((divide( - tiny_reward, - STAmount(UT_XCHAIN_DEFAULT_QUORUM), - tiny_reward.issue()))) + , tiny_reward_split((divide(tiny_reward, STAmount(UT_XCHAIN_DEFAULT_QUORUM), tiny_reward.issue()))) , tiny_reward_remainder( - tiny_reward - - multiply( - tiny_reward_split, - STAmount(UT_XCHAIN_DEFAULT_QUORUM), - tiny_reward.issue())) + tiny_reward - multiply(tiny_reward_split, STAmount(UT_XCHAIN_DEFAULT_QUORUM), tiny_reward.issue())) , one_xrp(XRP(1)) , xrp_dust(divide(one_xrp, STAmount(10000), one_xrp.issue())) { @@ -464,8 +431,7 @@ void XChainBridgeObjects::createScBridgeObjects(Env& scEnv) { STAmount xrp_funds{XRP(10000)}; - scEnv.fund( - xrp_funds, scDoor, scAlice, scBob, scCarol, scGw, scAttester, scReward); + scEnv.fund(xrp_funds, scDoor, scAlice, scBob, scCarol, scGw, scAttester, scReward); // Signer's list must match the attestation signers scEnv(jtx::signers(Account::master, signers.size(), signers)); diff --git a/src/test/jtx/memo.h b/src/test/jtx/memo.h index 2506f063fc..c0f8ae5f27 100644 --- a/src/test/jtx/memo.h +++ b/src/test/jtx/memo.h @@ -20,10 +20,7 @@ private: std::string type_; public: - memo( - std::string const& data, - std::string const& format, - std::string const& type) + memo(std::string const& data, std::string const& format, std::string const& type) : data_(data), format_(format), type_(type) { } diff --git a/src/test/jtx/mpt.h b/src/test/jtx/mpt.h index 3eea362b58..fc66b50a1e 100644 --- a/src/test/jtx/mpt.h +++ b/src/test/jtx/mpt.h @@ -25,10 +25,7 @@ private: std::optional holder_; public: - mptflags( - MPTTester& tester, - std::uint32_t flags, - std::optional const& holder = std::nullopt) + mptflags(MPTTester& tester, std::uint32_t flags, std::optional const& holder = std::nullopt) : tester_(tester), flags_(flags), holder_(holder) { } @@ -86,8 +83,7 @@ struct MPTCreate std::optional> authorize = std::nullopt; // pay if seated. if authorize is not seated then authorize. // if empty vector then pay to either authorize or all holders. - std::optional, std::uint64_t>> pay = - std::nullopt; + std::optional, std::uint64_t>> pay = std::nullopt; std::optional flags = {0}; std::optional mutableFlags = std::nullopt; bool authHolder = false; @@ -209,16 +205,13 @@ public: checkDomainID(std::optional expected) const; [[nodiscard]] bool - checkMPTokenAmount(Account const& holder, std::int64_t expectedAmount) - const; + checkMPTokenAmount(Account const& holder, std::int64_t expectedAmount) const; [[nodiscard]] bool checkMPTokenOutstandingAmount(std::int64_t expectedAmount) const; [[nodiscard]] bool - checkFlags( - uint32_t const expectedFlags, - std::optional const& holder = std::nullopt) const; + checkFlags(uint32_t const expectedFlags, std::optional const& holder = std::nullopt) const; [[nodiscard]] bool checkMetadata(std::string const& metadata) const; @@ -248,11 +241,7 @@ public: std::optional> credentials = std::nullopt); void - claw( - Account const& issuer, - Account const& holder, - std::int64_t amount, - std::optional err = std::nullopt); + claw(Account const& issuer, Account const& holder, std::int64_t amount, std::optional err = std::nullopt); PrettyAmount mpt(std::int64_t amount) const; @@ -279,18 +268,14 @@ public: private: using SLEP = SLE::const_pointer; bool - forObject( - std::function const& cb, - std::optional const& holder = std::nullopt) const; + forObject(std::function const& cb, std::optional const& holder = std::nullopt) + const; template TER submit(A const& arg, Json::Value const& jv) { - env_( - jv, - txflags(arg.flags.value_or(0)), - ter(arg.err.value_or(tesSUCCESS))); + env_(jv, txflags(arg.flags.value_or(0)), ter(arg.err.value_or(tesSUCCESS))); auto const err = env_.ter(); if (close_) env_.close(); diff --git a/src/test/jtx/multisign.h b/src/test/jtx/multisign.h index 8582b27a77..f1a50728b9 100644 --- a/src/test/jtx/multisign.h +++ b/src/test/jtx/multisign.h @@ -22,20 +22,14 @@ struct signer Account account; std::optional tag; - signer( - Account account_, - std::uint32_t weight_ = 1, - std::optional tag_ = std::nullopt) + signer(Account account_, std::uint32_t weight_ = 1, std::optional tag_ = std::nullopt) : weight(weight_), account(std::move(account_)), tag(std::move(tag_)) { } }; Json::Value -signers( - Account const& account, - std::uint32_t quorum, - std::vector const& v); +signers(Account const& account, std::uint32_t quorum, std::vector const& v); /** Remove a signer list. */ Json::Value @@ -57,14 +51,12 @@ public: /// a subfield. static constexpr SField* const topLevel = nullptr; - msig(SField const* subField_, std::vector signers_) - : signers(std::move(signers_)), subField(subField_) + msig(SField const* subField_, std::vector signers_) : signers(std::move(signers_)), subField(subField_) { sortSigners(signers); } - msig(SField const& subField_, std::vector signers_) - : msig{&subField_, signers_} + msig(SField const& subField_, std::vector signers_) : msig{&subField_, signers_} { } @@ -75,35 +67,21 @@ public: template requires std::convertible_to explicit msig(SField const* subField_, AccountType&& a0, Accounts&&... aN) - : msig{ - subField_, - std::vector{ - std::forward(a0), - std::forward(aN)...}} + : msig{subField_, std::vector{std::forward(a0), std::forward(aN)...}} { } template requires std::convertible_to explicit msig(SField const& subField_, AccountType&& a0, Accounts&&... aN) - : msig{ - &subField_, - std::vector{ - std::forward(a0), - std::forward(aN)...}} + : msig{&subField_, std::vector{std::forward(a0), std::forward(aN)...}} { } template - requires( - std::convertible_to && - !std::is_same_v) + requires(std::convertible_to && !std::is_same_v) explicit msig(AccountType&& a0, Accounts&&... aN) - : msig{ - topLevel, - std::vector{ - std::forward(a0), - std::forward(aN)...}} + : msig{topLevel, std::vector{std::forward(a0), std::forward(aN)...}} { } diff --git a/src/test/jtx/offer.h b/src/test/jtx/offer.h index 8b01a9381b..22bc14a09d 100644 --- a/src/test/jtx/offer.h +++ b/src/test/jtx/offer.h @@ -12,11 +12,7 @@ namespace jtx { /** Create an offer. */ Json::Value -offer( - Account const& account, - STAmount const& takerPays, - STAmount const& takerGets, - std::uint32_t flags = 0); +offer(Account const& account, STAmount const& takerPays, STAmount const& takerGets, std::uint32_t flags = 0); /** Cancel an offer. */ Json::Value diff --git a/src/test/jtx/owners.h b/src/test/jtx/owners.h index fabaa148e4..73a244185f 100644 --- a/src/test/jtx/owners.h +++ b/src/test/jtx/owners.h @@ -17,11 +17,7 @@ std::uint32_t owned_count_of(ReadView const& view, AccountID const& id, LedgerEntryType type); void -owned_count_helper( - test::jtx::Env& env, - AccountID const& id, - LedgerEntryType type, - std::uint32_t value); +owned_count_helper(test::jtx::Env& env, AccountID const& id, LedgerEntryType type, std::uint32_t value); } // namespace detail @@ -37,8 +33,7 @@ private: std::uint32_t value_; public: - owner_count(Account const& account, std::uint32_t value) - : account_(account), value_(value) + owner_count(Account const& account, std::uint32_t value) : account_(account), value_(value) { } @@ -57,8 +52,7 @@ private: std::uint32_t value_; public: - owners(Account const& account, std::uint32_t value) - : account_(account), value_(value) + owners(Account const& account, std::uint32_t value) : account_(account), value_(value) { } diff --git a/src/test/jtx/paths.h b/src/test/jtx/paths.h index b603db3f7b..a1e5ee0294 100644 --- a/src/test/jtx/paths.h +++ b/src/test/jtx/paths.h @@ -20,8 +20,7 @@ private: unsigned int limit_; public: - paths(Issue const& in, int depth = 7, unsigned int limit = 4) - : in_(in), depth_(depth), limit_(limit) + paths(Issue const& in, int depth = 7, unsigned int limit = 4) : in_(in), depth_(depth), limit_(limit) { } diff --git a/src/test/jtx/permissioned_domains.h b/src/test/jtx/permissioned_domains.h index c0adacd0c5..de015775ce 100644 --- a/src/test/jtx/permissioned_domains.h +++ b/src/test/jtx/permissioned_domains.h @@ -17,10 +17,7 @@ using Credentials = std::vector; // helpers // Make json for PermissionedDomainSet transaction Json::Value -setTx( - AccountID const& account, - Credentials const& credentials, - std::optional domain = std::nullopt); +setTx(AccountID const& account, Credentials const& credentials, std::optional domain = std::nullopt); // Make json for PermissionedDomainDelete transaction Json::Value @@ -36,9 +33,7 @@ objectExists(uint256 const& objID, Env& env); // Extract credentials from account_object object Credentials -credentialsFromJson( - Json::Value const& object, - std::unordered_map const& human2Acc); +credentialsFromJson(Json::Value const& object, std::unordered_map const& human2Acc); // Sort credentials the same way as PermissionedDomainSet Credentials diff --git a/src/test/jtx/prop.h b/src/test/jtx/prop.h index 3478e23d9b..5c4687f88b 100644 --- a/src/test/jtx/prop.h +++ b/src/test/jtx/prop.h @@ -16,8 +16,7 @@ struct prop std::unique_ptr p_; template - prop(Args&&... args) - : p_(std::make_unique>(std::forward(args)...)) + prop(Args&&... args) : p_(std::make_unique>(std::forward(args)...)) { } diff --git a/src/test/jtx/rpc.h b/src/test/jtx/rpc.h index ba3c71074d..30b4f4b1fd 100644 --- a/src/test/jtx/rpc.h +++ b/src/test/jtx/rpc.h @@ -22,15 +22,12 @@ private: public: /// If there's an error code, we expect an error message - explicit rpc(error_code_i code, std::optional m = {}) - : code_(code), errorMessage_(m) + explicit rpc(error_code_i code, std::optional m = {}) : code_(code), errorMessage_(m) { } /// If there is not a code, we expect an exception message - explicit rpc( - std::string error, - std::optional exceptionMessage = {}) + explicit rpc(std::string error, std::optional exceptionMessage = {}) : error_(error), errorException_(exceptionMessage) { } @@ -51,9 +48,7 @@ public: // Take advantage of that fact to populate jt.rpcException. The // check will be aware of whether the rpcException can be safely // ignored. - jt.rpcCode = { - *code_, - errorMessage_ ? *errorMessage_ : errorInfo.message.c_str()}; + jt.rpcCode = {*code_, errorMessage_ ? *errorMessage_ : errorInfo.message.c_str()}; jt.rpcException = {errorInfo.token.c_str(), std::nullopt}; } if (error_) diff --git a/src/test/jtx/sig.h b/src/test/jtx/sig.h index 27d18b322e..1397e5fc71 100644 --- a/src/test/jtx/sig.h +++ b/src/test/jtx/sig.h @@ -40,13 +40,11 @@ public: { } - explicit sig(SField const* subField, Account const& account) - : subField_(subField), account_(account) + explicit sig(SField const* subField, Account const& account) : subField_(subField), account_(account) { } - explicit sig(SField const& subField, Account const& account) - : sig(&subField, account) + explicit sig(SField const& subField, Account const& account) : sig(&subField, account) { } diff --git a/src/test/jtx/token.h b/src/test/jtx/token.h index 5280799582..2c9ecc8393 100644 --- a/src/test/jtx/token.h +++ b/src/test/jtx/token.h @@ -104,10 +104,7 @@ burn(jtx::Account const& account, uint256 const& nftokenID); /** Create an NFTokenOffer. */ Json::Value -createOffer( - jtx::Account const& account, - uint256 const& nftokenID, - STAmount const& amount); +createOffer(jtx::Account const& account, uint256 const& nftokenID, STAmount const& amount); /** Sets the optional Owner on an NFTokenOffer. */ class owner @@ -156,14 +153,10 @@ public: /** Cancel NFTokenOffers. */ Json::Value -cancelOffer( - jtx::Account const& account, - std::initializer_list const& nftokenOffers = {}); +cancelOffer(jtx::Account const& account, std::initializer_list const& nftokenOffers = {}); Json::Value -cancelOffer( - jtx::Account const& account, - std::vector const& nftokenOffers); +cancelOffer(jtx::Account const& account, std::vector const& nftokenOffers); /** Sets the optional RootIndex field when canceling NFTokenOffers. */ class rootIndex @@ -190,10 +183,7 @@ acceptSellOffer(jtx::Account const& account, uint256 const& offerIndex); /** Broker two NFToken offers. */ Json::Value -brokerOffers( - jtx::Account const& account, - uint256 const& buyOfferIndex, - uint256 const& sellOfferIndex); +brokerOffers(jtx::Account const& account, uint256 const& buyOfferIndex, uint256 const& sellOfferIndex); /** Sets the optional NFTokenBrokerFee field in a brokerOffer transaction. */ class brokerFee diff --git a/src/test/jtx/trust.h b/src/test/jtx/trust.h index 69a3e7ba53..34eba0a63b 100644 --- a/src/test/jtx/trust.h +++ b/src/test/jtx/trust.h @@ -16,17 +16,10 @@ trust(Account const& account, STAmount const& amount, std::uint32_t flags = 0); /** Change flags on a trust line. */ Json::Value -trust( - Account const& account, - STAmount const& amount, - Account const& peer, - std::uint32_t flags); +trust(Account const& account, STAmount const& amount, Account const& peer, std::uint32_t flags); Json::Value -claw( - Account const& account, - STAmount const& amount, - std::optional const& mptHolder = std::nullopt); +claw(Account const& account, STAmount const& amount, std::optional const& mptHolder = std::nullopt); } // namespace jtx } // namespace test diff --git a/src/test/jtx/utility.h b/src/test/jtx/utility.h index a824f86c1a..b28868af65 100644 --- a/src/test/jtx/utility.h +++ b/src/test/jtx/utility.h @@ -53,10 +53,7 @@ fill_seq(Json::Value& jv, ReadView const& view); /** Given a rippled unit test rpc command, return the corresponding JSON. */ Json::Value -cmdToJSONRPC( - std::vector const& args, - beast::Journal j, - unsigned int apiVersion); +cmdToJSONRPC(std::vector const& args, beast::Journal j, unsigned int apiVersion); } // namespace jtx } // namespace test diff --git a/src/test/jtx/xchain_bridge.h b/src/test/jtx/xchain_bridge.h index dfd6073ca4..f7c1f019c9 100644 --- a/src/test/jtx/xchain_bridge.h +++ b/src/test/jtx/xchain_bridge.h @@ -71,11 +71,7 @@ sidechain_xchain_account_create( AnyAmount const& xChainFee); Json::Value -sidechain_xchain_account_claim( - Account const& acc, - Json::Value const& bridge, - Account const& dst, - AnyAmount const& amt); +sidechain_xchain_account_claim(Account const& acc, Json::Value const& bridge, Account const& dst, AnyAmount const& amt); Json::Value claim_attestation( @@ -206,18 +202,7 @@ struct XChainBridgeObjects std::size_t const fromIdx = 0) { return create_account_attestations( - scAttester, - jvb, - mcCarol, - amt, - reward, - payees, - true, - createCount, - dst, - signers, - numAtts, - fromIdx); + scAttester, jvb, mcCarol, amt, reward, payees, true, createCount, dst, signers, numAtts, fromIdx); } Json::Value @@ -227,11 +212,7 @@ struct XChainBridgeObjects STAmount const& _reward = XRP(1), std::optional const& minAccountCreate = std::nullopt) { - return bridge_create( - acc, - bridge == Json::nullValue ? jvb : bridge, - _reward, - minAccountCreate); + return bridge_create(acc, bridge == Json::nullValue ? jvb : bridge, _reward, minAccountCreate); } }; diff --git a/src/test/ledger/BookDirs_test.cpp b/src/test/ledger/BookDirs_test.cpp index 4f5cf5cca2..45e585d68d 100644 --- a/src/test/ledger/BookDirs_test.cpp +++ b/src/test/ledger/BookDirs_test.cpp @@ -33,18 +33,13 @@ struct BookDirs_test : public beast::unit_test::suite { env(offer("alice", Account("alice")["USD"](50), XRP(10))); - auto d = BookDirs( - *env.current(), - Book( - Account("alice")["USD"].issue(), xrpIssue(), std::nullopt)); + auto d = BookDirs(*env.current(), Book(Account("alice")["USD"].issue(), xrpIssue(), std::nullopt)); BEAST_EXPECT(std::distance(d.begin(), d.end()) == 1); } { env(offer("alice", gw["CNY"](50), XRP(10))); - auto d = BookDirs( - *env.current(), - Book(gw["CNY"].issue(), xrpIssue(), std::nullopt)); + auto d = BookDirs(*env.current(), Book(gw["CNY"].issue(), xrpIssue(), std::nullopt)); BEAST_EXPECT(std::distance(d.begin(), d.end()) == 1); } @@ -52,9 +47,7 @@ struct BookDirs_test : public beast::unit_test::suite env.trust(Account("bob")["CNY"](10), "alice"); env(pay("bob", "alice", Account("bob")["CNY"](10))); env(offer("alice", USD(50), Account("bob")["CNY"](10))); - auto d = BookDirs( - *env.current(), - Book(USD.issue(), Account("bob")["CNY"].issue(), std::nullopt)); + auto d = BookDirs(*env.current(), Book(USD.issue(), Account("bob")["CNY"].issue(), std::nullopt)); BEAST_EXPECT(std::distance(d.begin(), d.end()) == 1); } @@ -64,8 +57,7 @@ struct BookDirs_test : public beast::unit_test::suite for (auto k = 0; k < 80; ++k) env(offer("alice", AUD(i), XRP(j))); - auto d = BookDirs( - *env.current(), Book(AUD.issue(), xrpIssue(), std::nullopt)); + auto d = BookDirs(*env.current(), Book(AUD.issue(), xrpIssue(), std::nullopt)); BEAST_EXPECT(std::distance(d.begin(), d.end()) == 240); auto i = 1, j = 3, k = 0; for (auto const& e : d) diff --git a/src/test/ledger/Directory_test.cpp b/src/test/ledger/Directory_test.cpp index 721b919238..16d319671c 100644 --- a/src/test/ledger/Directory_test.cpp +++ b/src/test/ledger/Directory_test.cpp @@ -89,8 +89,7 @@ struct Directory_test : public beast::unit_test::suite do { - auto p = - view->read(keylet::page(keylet::ownerDir(alice), page)); + auto p = view->read(keylet::page(keylet::ownerDir(alice), page)); // Ensure that the entries in the page are sorted auto const& v = p->getFieldV256(sfIndexes); @@ -98,8 +97,7 @@ struct Directory_test : public beast::unit_test::suite // Ensure that the page contains the correct orders by // calculating which sequence numbers belong here. - std::uint32_t const minSeq = - firstOfferSeq + (page * dirNodeMaxEntries); + std::uint32_t const minSeq = firstOfferSeq + (page * dirNodeMaxEntries); std::uint32_t const maxSeq = minSeq + dirNodeMaxEntries; for (auto const& e : v) @@ -116,8 +114,7 @@ struct Directory_test : public beast::unit_test::suite // Now check the orderbook: it should be in the order we placed // the offers. - auto book = BookDirs( - *env.current(), Book({xrpIssue(), USD.issue(), std::nullopt})); + auto book = BookDirs(*env.current(), Book({xrpIssue(), USD.issue(), std::nullopt})); int count = 1; for (auto const& offer : book) @@ -266,8 +263,7 @@ struct Directory_test : public beast::unit_test::suite { for (int i = 0; i < dirNodeMaxEntries; ++i) { - env(offer_cancel( - alice, firstOfferSeq + page * dirNodeMaxEntries + i)); + env(offer_cancel(alice, firstOfferSeq + page * dirNodeMaxEntries + i)); env.close(); } } @@ -276,8 +272,7 @@ struct Directory_test : public beast::unit_test::suite // should have no entries and be empty: { Sandbox sb(env.closed().get(), tapNONE); - uint256 const bookBase = - getBookBase({xrpIssue(), USD.issue(), std::nullopt}); + uint256 const bookBase = getBookBase({xrpIssue(), USD.issue(), std::nullopt}); BEAST_EXPECT(dirIsEmpty(sb, keylet::page(bookBase))); BEAST_EXPECT(!sb.succ(bookBase, getQualityNext(bookBase))); @@ -309,11 +304,9 @@ struct Directory_test : public beast::unit_test::suite env.fund(XRP(10000), alice); env.close(); - constexpr uint256 base( - "fb71c9aa3310141da4b01d6c744a98286af2d72ab5448d5adc0910ca0c910880"); + constexpr uint256 base("fb71c9aa3310141da4b01d6c744a98286af2d72ab5448d5adc0910ca0c910880"); - constexpr uint256 item( - "bad0f021aa3b2f6754a8fe82a5779730aa0bbbab82f17201ef24900efc2c7312"); + constexpr uint256 item("bad0f021aa3b2f6754a8fe82a5779730aa0bbbab82f17201ef24900efc2c7312"); { // Create a chain of three pages: @@ -333,8 +326,7 @@ struct Directory_test : public beast::unit_test::suite // Now, try to delete the item from the middle // page. This should cause all pages to be deleted: - BEAST_EXPECT(sb.dirRemove( - keylet::page(base, 0), 1, keylet::unchecked(item), false)); + BEAST_EXPECT(sb.dirRemove(keylet::page(base, 0), 1, keylet::unchecked(item), false)); BEAST_EXPECT(!sb.peek(keylet::page(base, 2))); BEAST_EXPECT(!sb.peek(keylet::page(base, 1))); BEAST_EXPECT(!sb.peek(keylet::page(base, 0))); @@ -367,8 +359,7 @@ struct Directory_test : public beast::unit_test::suite // Now, try to delete the item from page 2. // This should cause pages 2 and 3 to be // deleted: - BEAST_EXPECT(sb.dirRemove( - keylet::page(base, 0), 2, keylet::unchecked(item), false)); + BEAST_EXPECT(sb.dirRemove(keylet::page(base, 0), 2, keylet::unchecked(item), false)); BEAST_EXPECT(!sb.peek(keylet::page(base, 3))); BEAST_EXPECT(!sb.peek(keylet::page(base, 2))); @@ -398,8 +389,7 @@ struct Directory_test : public beast::unit_test::suite Json::Value params; params[jss::type] = jss::directory; params[jss::ledger_index] = "validated"; - auto const result = - env.rpc("json", "ledger_data", to_string(params))[jss::result]; + auto const result = env.rpc("json", "ledger_data", to_string(params))[jss::result]; BEAST_EXPECT(!result.isMember(jss::marker)); return result; }; @@ -418,9 +408,7 @@ struct Directory_test : public beast::unit_test::suite BEAST_EXPECTS(checkArraySize(jstate, 2), jrr.toStyledString()); for (auto const& directory : jstate) { - BEAST_EXPECT( - directory["LedgerEntryType"] == - jss::DirectoryNode); // sanity check + BEAST_EXPECT(directory["LedgerEntryType"] == jss::DirectoryNode); // sanity check // The PreviousTxnID and PreviousTxnLgrSeq fields should not be // on the DirectoryNode object when the amendment is disabled BEAST_EXPECT(!directory.isMember("PreviousTxnID")); @@ -448,9 +436,7 @@ struct Directory_test : public beast::unit_test::suite BEAST_EXPECTS(checkArraySize(jstate, 3), jrr.toStyledString()); for (auto const& directory : jstate) { - BEAST_EXPECT( - directory["LedgerEntryType"] == - jss::DirectoryNode); // sanity check + BEAST_EXPECT(directory["LedgerEntryType"] == jss::DirectoryNode); // sanity check if (directory[jss::Owner] == gw.human()) { // gw's directory did not get touched, so it @@ -463,9 +449,7 @@ struct Directory_test : public beast::unit_test::suite // All of the other directories, including the order // book, did get touched, so they should have those // fields - BEAST_EXPECT( - directory.isMember("PreviousTxnID") && - directory["PreviousTxnID"].asString() == txID); + BEAST_EXPECT(directory.isMember("PreviousTxnID") && directory["PreviousTxnID"].asString() == txID); BEAST_EXPECT( directory.isMember("PreviousTxnLgrSeq") && directory["PreviousTxnLgrSeq"].asUInt() == ledgerSeq); @@ -502,8 +486,7 @@ struct Directory_test : public beast::unit_test::suite env, lastPage, keylet::ownerDir(alice.id()), - [lastPage, this]( - ApplyView& view, uint256 key, std::uint64_t page) { + [lastPage, this](ApplyView& view, uint256 key, std::uint64_t page) { auto sle = view.peek({ltCREDENTIAL, key}); if (!BEAST_EXPECT(sle)) return false; @@ -525,8 +508,7 @@ struct Directory_test : public beast::unit_test::suite // Destroy all objects in directory for (int i = 0; i < 64; ++i) - env(credentials::deleteCred( - alice, alice, alice, std::to_string(i))); + env(credentials::deleteCred(alice, alice, alice, std::to_string(i))); if (!full) env(credentials::deleteCred(alice, alice, alice, "foo")); @@ -539,12 +521,10 @@ struct Directory_test : public beast::unit_test::suite env.close(); }; - testCase( - testable_amendments() - fixDirectoryLimit, - [this](Env&) -> std::tuple { - testcase("directory full without fixDirectoryLimit"); - return {dirNodeMaxPages - 1, true}; - }); + testCase(testable_amendments() - fixDirectoryLimit, [this](Env&) -> std::tuple { + testcase("directory full without fixDirectoryLimit"); + return {dirNodeMaxPages - 1, true}; + }); testCase( testable_amendments(), // [this](Env&) -> std::tuple { diff --git a/src/test/ledger/PaymentSandbox_test.cpp b/src/test/ledger/PaymentSandbox_test.cpp index b5acb38156..cd5b1d1c19 100644 --- a/src/test/ledger/PaymentSandbox_test.cpp +++ b/src/test/ledger/PaymentSandbox_test.cpp @@ -66,9 +66,7 @@ class PaymentSandbox_test : public beast::unit_test::suite PathSet paths(Path(gw1, USD_gw2, gw2), Path(gw2, USD_gw1, gw1)); - env(pay(snd, rcv, any(USD_gw1(4))), - json(paths.json()), - txflags(tfNoRippleDirect | tfPartialPayment)); + env(pay(snd, rcv, any(USD_gw1(4))), json(paths.json()), txflags(tfNoRippleDirect | tfPartialPayment)); env.require(balance("rcv", USD_gw1(0))); env.require(balance("rcv", USD_gw2(2))); @@ -105,23 +103,19 @@ class PaymentSandbox_test : public beast::unit_test::suite ApplyViewImpl av(&*env.current(), tapNONE); auto const iss = USD_gw1.issue(); - auto const startingAmount = accountHolds( - av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); + auto const startingAmount = accountHolds(av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); { auto r = accountSend(av, gw1, alice, toCredit, j); BEAST_EXPECT(r == tesSUCCESS); } BEAST_EXPECT( - accountHolds( - av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount + toCredit); + accountHolds(av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount + toCredit); { auto r = accountSend(av, alice, gw1, toDebit, j); BEAST_EXPECT(r == tesSUCCESS); } BEAST_EXPECT( - accountHolds( - av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == + accountHolds(av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount + toCredit - toDebit); } @@ -130,19 +124,15 @@ class PaymentSandbox_test : public beast::unit_test::suite ApplyViewImpl av(&*env.current(), tapNONE); auto const iss = USD_gw1.issue(); - auto const startingAmount = accountHolds( - av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); + auto const startingAmount = accountHolds(av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); rippleCredit(av, gw1, alice, toCredit, true, j); BEAST_EXPECT( - accountHolds( - av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount + toCredit); + accountHolds(av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount + toCredit); rippleCredit(av, alice, gw1, toDebit, true, j); BEAST_EXPECT( - accountHolds( - av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == + accountHolds(av, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount + toCredit - toDebit); } @@ -152,26 +142,20 @@ class PaymentSandbox_test : public beast::unit_test::suite PaymentSandbox pv(&av); auto const iss = USD_gw1.issue(); - auto const startingAmount = accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); + auto const startingAmount = accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); { auto r = accountSend(pv, gw1, alice, toCredit, j); BEAST_EXPECT(r == tesSUCCESS); } - BEAST_EXPECT( - accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount); + BEAST_EXPECT(accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount); { auto r = accountSend(pv, alice, gw1, toDebit, j); BEAST_EXPECT(r == tesSUCCESS); } BEAST_EXPECT( - accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount - toDebit); + accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount - toDebit); } { @@ -180,14 +164,10 @@ class PaymentSandbox_test : public beast::unit_test::suite PaymentSandbox pv(&av); auto const iss = USD_gw1.issue(); - auto const startingAmount = accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); + auto const startingAmount = accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); rippleCredit(pv, gw1, alice, toCredit, true, j); - BEAST_EXPECT( - accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount); + BEAST_EXPECT(accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount); } { @@ -196,14 +176,11 @@ class PaymentSandbox_test : public beast::unit_test::suite PaymentSandbox pv(&av); auto const iss = USD_gw1.issue(); - auto const startingAmount = accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); + auto const startingAmount = accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); BEAST_EXPECT(redeemIOU(pv, alice, toDebit, iss, j) == tesSUCCESS); BEAST_EXPECT( - accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount - toDebit); + accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount - toDebit); } { @@ -212,14 +189,10 @@ class PaymentSandbox_test : public beast::unit_test::suite PaymentSandbox pv(&av); auto const iss = USD_gw1.issue(); - auto const startingAmount = accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); + auto const startingAmount = accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); BEAST_EXPECT(issueIOU(pv, alice, toCredit, iss, j) == tesSUCCESS); - BEAST_EXPECT( - accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount); + BEAST_EXPECT(accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount); } { @@ -228,40 +201,22 @@ class PaymentSandbox_test : public beast::unit_test::suite PaymentSandbox pv(&av); auto const iss = USD_gw1.issue(); - auto const startingAmount = accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); + auto const startingAmount = accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j); { auto r = accountSend(pv, gw1, alice, toCredit, j); BEAST_EXPECT(r == tesSUCCESS); } - BEAST_EXPECT( - accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount); + BEAST_EXPECT(accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount); { PaymentSandbox pv2(&pv); - BEAST_EXPECT( - accountHolds( - pv2, - alice, - iss.currency, - iss.account, - fhIGNORE_FREEZE, - j) == startingAmount); + BEAST_EXPECT(accountHolds(pv2, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount); { auto r = accountSend(pv2, gw1, alice, toCredit, j); BEAST_EXPECT(r == tesSUCCESS); } - BEAST_EXPECT( - accountHolds( - pv2, - alice, - iss.currency, - iss.account, - fhIGNORE_FREEZE, - j) == startingAmount); + BEAST_EXPECT(accountHolds(pv2, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount); } { @@ -269,9 +224,7 @@ class PaymentSandbox_test : public beast::unit_test::suite BEAST_EXPECT(r == tesSUCCESS); } BEAST_EXPECT( - accountHolds( - pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == - startingAmount - toDebit); + accountHolds(pv, alice, iss.currency, iss.account, fhIGNORE_FREEZE, j) == startingAmount - toDebit); } } @@ -293,18 +246,8 @@ class PaymentSandbox_test : public beast::unit_test::suite auto const USD = gw["USD"]; auto const issue = USD.issue(); - STAmount tinyAmt( - issue, - STAmount::cMinValue, - STAmount::cMinOffset + 1, - false, - STAmount::unchecked{}); - STAmount hugeAmt( - issue, - STAmount::cMaxValue, - STAmount::cMaxOffset - 1, - false, - STAmount::unchecked{}); + STAmount tinyAmt(issue, STAmount::cMinValue, STAmount::cMinOffset + 1, false, STAmount::unchecked{}); + STAmount hugeAmt(issue, STAmount::cMaxValue, STAmount::cMaxOffset - 1, false, STAmount::unchecked{}); ApplyViewImpl av(&*env.current(), tapNONE); PaymentSandbox pv(&av); @@ -318,11 +261,8 @@ class PaymentSandbox_test : public beast::unit_test::suite testcase("Reserve"); using namespace jtx; - auto accountFundsXRP = [](ReadView const& view, - AccountID const& id, - beast::Journal j) -> XRPAmount { - return toAmount(accountHolds( - view, id, xrpCurrency(), xrpAccount(), fhZERO_IF_FROZEN, j)); + auto accountFundsXRP = [](ReadView const& view, AccountID const& id, beast::Journal j) -> XRPAmount { + return toAmount(accountHolds(view, id, xrpCurrency(), xrpAccount(), fhZERO_IF_FROZEN, j)); }; auto reserve = [](jtx::Env& env, std::uint32_t count) -> XRPAmount { @@ -343,17 +283,14 @@ class PaymentSandbox_test : public beast::unit_test::suite // zero (there was a bug that caused her funds to become negative). { - auto r = - accountSend(sb, xrpAccount(), alice, XRP(100), env.journal); + auto r = accountSend(sb, xrpAccount(), alice, XRP(100), env.journal); BEAST_EXPECT(r == tesSUCCESS); } { - auto r = - accountSend(sb, alice, xrpAccount(), XRP(100), env.journal); + auto r = accountSend(sb, alice, xrpAccount(), XRP(100), env.journal); BEAST_EXPECT(r == tesSUCCESS); } - BEAST_EXPECT( - accountFundsXRP(sb, alice, env.journal) == beast::zero); + BEAST_EXPECT(accountFundsXRP(sb, alice, env.journal) == beast::zero); } } @@ -383,8 +320,7 @@ class PaymentSandbox_test : public beast::unit_test::suite sb.creditHook(gw.id(), alice.id(), {USD, 100}, {tlIssue, 600}); // Expect that the STAmount issuer returned by balanceHook() is correct. - STAmount const balance = - sb.balanceHook(gw.id(), alice.id(), {USD, 600}); + STAmount const balance = sb.balanceHook(gw.id(), alice.id(), {USD, 600}); BEAST_EXPECT(balance.getIssuer() == USD.issue().account); } diff --git a/src/test/ledger/SkipList_test.cpp b/src/test/ledger/SkipList_test.cpp index 12fedea5c1..2f4a231c14 100644 --- a/src/test/ledger/SkipList_test.cpp +++ b/src/test/ledger/SkipList_test.cpp @@ -17,16 +17,12 @@ class SkipList_test : public beast::unit_test::suite std::vector> history; { Config config; - auto prev = std::make_shared( - create_genesis, - config, - std::vector{}, - env.app().getNodeFamily()); + auto prev = + std::make_shared(create_genesis, config, std::vector{}, env.app().getNodeFamily()); history.push_back(prev); for (auto i = 0; i < 1023; ++i) { - auto next = std::make_shared( - *prev, env.app().timeKeeper().closeTime()); + auto next = std::make_shared(*prev, env.app().timeKeeper().closeTime()); next->updateSkipList(); history.push_back(next); prev = next; @@ -35,47 +31,31 @@ class SkipList_test : public beast::unit_test::suite { auto l = *(std::next(std::begin(history))); - BEAST_EXPECT( - (*std::begin(history))->header().seq < l->header().seq); - BEAST_EXPECT( - !hashOfSeq(*l, l->header().seq + 1, env.journal).has_value()); - BEAST_EXPECT( - hashOfSeq(*l, l->header().seq, env.journal) == - l->header().hash); - BEAST_EXPECT( - hashOfSeq(*l, l->header().seq - 1, env.journal) == - l->header().parentHash); - BEAST_EXPECT( - !hashOfSeq(*history.back(), l->header().seq, env.journal) - .has_value()); + BEAST_EXPECT((*std::begin(history))->header().seq < l->header().seq); + BEAST_EXPECT(!hashOfSeq(*l, l->header().seq + 1, env.journal).has_value()); + BEAST_EXPECT(hashOfSeq(*l, l->header().seq, env.journal) == l->header().hash); + BEAST_EXPECT(hashOfSeq(*l, l->header().seq - 1, env.journal) == l->header().parentHash); + BEAST_EXPECT(!hashOfSeq(*history.back(), l->header().seq, env.journal).has_value()); } // ledger skip lists store up to the previous 256 hashes for (auto i = history.crbegin(); i != history.crend(); i += 256) { - for (auto n = i; - n != std::next(i, (*i)->header().seq - 256 > 1 ? 257 : 256); - ++n) + for (auto n = i; n != std::next(i, (*i)->header().seq - 256 > 1 ? 257 : 256); ++n) { - BEAST_EXPECT( - hashOfSeq(**i, (*n)->header().seq, env.journal) == - (*n)->header().hash); + BEAST_EXPECT(hashOfSeq(**i, (*n)->header().seq, env.journal) == (*n)->header().hash); } // edge case accessing beyond 256 - BEAST_EXPECT(!hashOfSeq(**i, (*i)->header().seq - 258, env.journal) - .has_value()); + BEAST_EXPECT(!hashOfSeq(**i, (*i)->header().seq - 258, env.journal).has_value()); } // every 256th hash beyond the first 256 is stored - for (auto i = history.crbegin(); i != std::next(history.crend(), -512); - i += 256) + for (auto i = history.crbegin(); i != std::next(history.crend(), -512); i += 256) { for (auto n = std::next(i, 512); n != history.crend(); n += 256) { - BEAST_EXPECT( - hashOfSeq(**i, (*n)->header().seq, env.journal) == - (*n)->header().hash); + BEAST_EXPECT(hashOfSeq(**i, (*n)->header().seq, env.journal) == (*n)->header().hash); } } } diff --git a/src/test/ledger/View_test.cpp b/src/test/ledger/View_test.cpp index a486792209..b2cc8d7057 100644 --- a/src/test/ledger/View_test.cpp +++ b/src/test/ledger/View_test.cpp @@ -60,8 +60,7 @@ class View_test : public beast::unit_test::suite next = view.succ(*next); if (!next) break; - view.rawErase(std::make_shared( - *view.read(keylet::unchecked(*next)))); + view.rawErase(std::make_shared(*view.read(keylet::unchecked(*next)))); } return true; }); @@ -78,17 +77,13 @@ class View_test : public beast::unit_test::suite next = ledger.succ(*next); if (!next) break; - ledger.rawErase( - std::make_shared(*ledger.read(keylet::unchecked(*next)))); + ledger.rawErase(std::make_shared(*ledger.read(keylet::unchecked(*next)))); } } // Test succ correctness void - succ( - ReadView const& v, - std::uint32_t id, - std::optional answer) + succ(ReadView const& v, std::uint32_t id, std::optional answer) { auto const next = v.succ(k(id).key); if (answer) @@ -118,13 +113,9 @@ class View_test : public beast::unit_test::suite using namespace jtx; Env env(*this); Config config; - std::shared_ptr const genesis = std::make_shared( - create_genesis, - config, - std::vector{}, - env.app().getNodeFamily()); - auto const ledger = std::make_shared( - *genesis, env.app().timeKeeper().closeTime()); + std::shared_ptr const genesis = + std::make_shared(create_genesis, config, std::vector{}, env.app().getNodeFamily()); + auto const ledger = std::make_shared(*genesis, env.app().timeKeeper().closeTime()); wipe(*ledger); ReadView& v = *ledger; succ(v, 0, std::nullopt); @@ -385,13 +376,9 @@ class View_test : public beast::unit_test::suite using namespace jtx; Env env(*this); Config config; - std::shared_ptr const genesis = std::make_shared( - create_genesis, - config, - std::vector{}, - env.app().getNodeFamily()); - auto const ledger = std::make_shared( - *genesis, env.app().timeKeeper().closeTime()); + std::shared_ptr const genesis = + std::make_shared(create_genesis, config, std::vector{}, env.app().getNodeFamily()); + auto const ledger = std::make_shared(*genesis, env.app().timeKeeper().closeTime()); auto setup = [&ledger](std::vector const& vec) { wipe(*ledger); @@ -500,9 +487,8 @@ class View_test : public beast::unit_test::suite } { // some full trees, some empty trees, etc - setup({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 20, 25, 30, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 66, 100}); + setup({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 25, 30, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 66, 100}); BEAST_EXPECT( sles(*ledger) == list( @@ -549,98 +535,38 @@ class View_test : public beast::unit_test::suite auto e = ledger->stateMap().end(); BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(0)) == e); BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(1)) == b); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(5))->key() == - uint256(4)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(15))->key() == - uint256(14)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(16))->key() == - uint256(15)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(19))->key() == - uint256(16)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(20))->key() == - uint256(16)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(24))->key() == - uint256(20)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(31))->key() == - uint256(30)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(32))->key() == - uint256(30)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(40))->key() == - uint256(39)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(47))->key() == - uint256(46)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(48))->key() == - uint256(47)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(64))->key() == - uint256(48)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(5))->key() == uint256(4)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(15))->key() == uint256(14)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(16))->key() == uint256(15)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(19))->key() == uint256(16)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(20))->key() == uint256(16)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(24))->key() == uint256(20)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(31))->key() == uint256(30)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(32))->key() == uint256(30)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(40))->key() == uint256(39)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(47))->key() == uint256(46)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(48))->key() == uint256(47)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(64))->key() == uint256(48)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(90))->key() == - uint256(66)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(96))->key() == - uint256(66)); - BEAST_EXPECT( - ledger->stateMap().lower_bound(uint256(100))->key() == - uint256(66)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(90))->key() == uint256(66)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(96))->key() == uint256(66)); + BEAST_EXPECT(ledger->stateMap().lower_bound(uint256(100))->key() == uint256(66)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(0))->key() == - uint256(1)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(5))->key() == - uint256(6)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(15))->key() == - uint256(16)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(16))->key() == - uint256(20)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(18))->key() == - uint256(20)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(20))->key() == - uint256(25)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(31))->key() == - uint256(32)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(32))->key() == - uint256(33)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(47))->key() == - uint256(48)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(48))->key() == - uint256(66)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(53))->key() == - uint256(66)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(66))->key() == - uint256(100)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(70))->key() == - uint256(100)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(85))->key() == - uint256(100)); - BEAST_EXPECT( - ledger->stateMap().upper_bound(uint256(98))->key() == - uint256(100)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(0))->key() == uint256(1)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(5))->key() == uint256(6)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(15))->key() == uint256(16)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(16))->key() == uint256(20)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(18))->key() == uint256(20)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(20))->key() == uint256(25)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(31))->key() == uint256(32)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(32))->key() == uint256(33)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(47))->key() == uint256(48)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(48))->key() == uint256(66)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(53))->key() == uint256(66)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(66))->key() == uint256(100)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(70))->key() == uint256(100)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(85))->key() == uint256(100)); + BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(98))->key() == uint256(100)); BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(100)) == e); BEAST_EXPECT(ledger->stateMap().upper_bound(uint256(155)) == e); } @@ -654,13 +580,9 @@ class View_test : public beast::unit_test::suite using namespace jtx; Env env(*this); Config config; - std::shared_ptr const genesis = std::make_shared( - create_genesis, - config, - std::vector{}, - env.app().getNodeFamily()); - auto const ledger = std::make_shared( - *genesis, env.app().timeKeeper().closeTime()); + std::shared_ptr const genesis = + std::make_shared(create_genesis, config, std::vector{}, env.app().getNodeFamily()); + auto const ledger = std::make_shared(*genesis, env.app().timeKeeper().closeTime()); auto setup123 = [&ledger, this]() { // erase middle element wipe(*ledger); @@ -810,15 +732,7 @@ class View_test : public beast::unit_test::suite env.close(); // Alice's USD balance should be zero if frozen. - BEAST_EXPECT( - USD(0) == - accountHolds( - *env.closed(), - alice, - USD.currency, - gw, - fhZERO_IF_FROZEN, - env.journal)); + BEAST_EXPECT(USD(0) == accountHolds(*env.closed(), alice, USD.currency, gw, fhZERO_IF_FROZEN, env.journal)); // Thaw gw and try again. env(fclear(gw, asfGlobalFreeze)); @@ -835,28 +749,12 @@ class View_test : public beast::unit_test::suite env.close(); // Bob's balance should be zero if frozen. - BEAST_EXPECT( - USD(0) == - accountHolds( - *env.closed(), - bob, - USD.currency, - gw, - fhZERO_IF_FROZEN, - env.journal)); + BEAST_EXPECT(USD(0) == accountHolds(*env.closed(), bob, USD.currency, gw, fhZERO_IF_FROZEN, env.journal)); // gw thaws bob's trust line. bob gets his money back. env(trust(gw, USD(100), bob, tfClearFreeze)); env.close(); - BEAST_EXPECT( - USD(50) == - accountHolds( - *env.closed(), - bob, - USD.currency, - gw, - fhZERO_IF_FROZEN, - env.journal)); + BEAST_EXPECT(USD(50) == accountHolds(*env.closed(), bob, USD.currency, gw, fhZERO_IF_FROZEN, env.journal)); } { // accountHolds(). @@ -864,35 +762,15 @@ class View_test : public beast::unit_test::suite env.close(); // carol has no EUR. - BEAST_EXPECT( - EUR(0) == - accountHolds( - *env.closed(), - carol, - EUR.currency, - gw, - fhZERO_IF_FROZEN, - env.journal)); + BEAST_EXPECT(EUR(0) == accountHolds(*env.closed(), carol, EUR.currency, gw, fhZERO_IF_FROZEN, env.journal)); // But carol does have USD. BEAST_EXPECT( - USD(50) == - accountHolds( - *env.closed(), - carol, - USD.currency, - gw, - fhZERO_IF_FROZEN, - env.journal)); + USD(50) == accountHolds(*env.closed(), carol, USD.currency, gw, fhZERO_IF_FROZEN, env.journal)); // carol's XRP balance should be her holdings minus her reserve. - auto const carolsXRP = accountHolds( - *env.closed(), - carol, - xrpCurrency(), - xrpAccount(), - fhZERO_IF_FROZEN, - env.journal); + auto const carolsXRP = + accountHolds(*env.closed(), carol, xrpCurrency(), xrpAccount(), fhZERO_IF_FROZEN, env.journal); // carol's XRP balance: 10000 // base reserve: -200 // 1 trust line times its reserve: 1 * -50 @@ -907,37 +785,26 @@ class View_test : public beast::unit_test::suite // carol's XRP balance should now show as zero. BEAST_EXPECT( - XRP(0) == - accountHolds( - *env.closed(), - carol, - xrpCurrency(), - gw, - fhZERO_IF_FROZEN, - env.journal)); + XRP(0) == accountHolds(*env.closed(), carol, xrpCurrency(), gw, fhZERO_IF_FROZEN, env.journal)); } { // accountFunds(). // Gateways have whatever funds they claim to have. - auto const gwUSD = accountFunds( - *env.closed(), gw, USD(314159), fhZERO_IF_FROZEN, env.journal); + auto const gwUSD = accountFunds(*env.closed(), gw, USD(314159), fhZERO_IF_FROZEN, env.journal); BEAST_EXPECT(gwUSD == USD(314159)); // carol has funds from the gateway. - auto carolsUSD = accountFunds( - *env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal); + auto carolsUSD = accountFunds(*env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal); BEAST_EXPECT(carolsUSD == USD(50)); // If carol's funds are frozen she has no funds... env(fset(gw, asfGlobalFreeze)); env.close(); - carolsUSD = accountFunds( - *env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal); + carolsUSD = accountFunds(*env.closed(), carol, USD(0), fhZERO_IF_FROZEN, env.journal); BEAST_EXPECT(carolsUSD == USD(0)); // ... unless the query ignores the FROZEN state. - carolsUSD = accountFunds( - *env.closed(), carol, USD(0), fhIGNORE_FREEZE, env.journal); + carolsUSD = accountFunds(*env.closed(), carol, USD(0), fhIGNORE_FREEZE, env.journal); BEAST_EXPECT(carolsUSD == USD(50)); // Just to be tidy, thaw gw. @@ -1044,13 +911,8 @@ class View_test : public beast::unit_test::suite Env env(*this); Config config; std::shared_ptr const genesis = - std::make_shared( - create_genesis, - config, - std::vector{}, - env.app().getNodeFamily()); - auto const ledger = std::make_shared( - *genesis, env.app().timeKeeper().closeTime()); + std::make_shared(create_genesis, config, std::vector{}, env.app().getNodeFamily()); + auto const ledger = std::make_shared(*genesis, env.app().timeKeeper().closeTime()); wipe(*ledger); ledger->rawInsert(sle(1)); ReadView& v0 = *ledger; diff --git a/src/test/nodestore/Backend_test.cpp b/src/test/nodestore/Backend_test.cpp index 07b35ed9fc..19f3bc43e5 100644 --- a/src/test/nodestore/Backend_test.cpp +++ b/src/test/nodestore/Backend_test.cpp @@ -19,10 +19,7 @@ class Backend_test : public TestBase { public: void - testBackend( - std::string const& type, - std::uint64_t const seedValue, - int numObjsToTest = 2000) + testBackend(std::string const& type, std::uint64_t const seedValue, int numObjsToTest = 2000) { DummyScheduler scheduler; @@ -43,8 +40,8 @@ public: { // Open the backend - std::unique_ptr backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + std::unique_ptr backend = + Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); backend->open(); // Write the batch @@ -68,8 +65,8 @@ public: { // Re-open the backend - std::unique_ptr backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + std::unique_ptr backend = + Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); backend->open(); // Read it back in diff --git a/src/test/nodestore/Basics_test.cpp b/src/test/nodestore/Basics_test.cpp index 3a7c6a1fdd..e37544f58e 100644 --- a/src/test/nodestore/Basics_test.cpp +++ b/src/test/nodestore/Basics_test.cpp @@ -40,15 +40,13 @@ public: { EncodedBlob encoded(batch[i]); - DecodedBlob decoded( - encoded.getKey(), encoded.getData(), encoded.getSize()); + DecodedBlob decoded(encoded.getKey(), encoded.getData(), encoded.getSize()); BEAST_EXPECT(decoded.wasOk()); if (decoded.wasOk()) { - std::shared_ptr const object( - decoded.createObject()); + std::shared_ptr const object(decoded.createObject()); BEAST_EXPECT(isSame(batch[i], object)); } diff --git a/src/test/nodestore/Database_test.cpp b/src/test/nodestore/Database_test.cpp index e5446374ec..03f0c11990 100644 --- a/src/test/nodestore/Database_test.cpp +++ b/src/test/nodestore/Database_test.cpp @@ -44,12 +44,9 @@ public: if (BEAST_EXPECT(s.globalPragma->size() == 3)) { - BEAST_EXPECT( - s.globalPragma->at(0) == "PRAGMA journal_mode=wal;"); - BEAST_EXPECT( - s.globalPragma->at(1) == "PRAGMA synchronous=normal;"); - BEAST_EXPECT( - s.globalPragma->at(2) == "PRAGMA temp_store=file;"); + BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=wal;"); + BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=normal;"); + BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=file;"); } } { @@ -68,8 +65,7 @@ public: return Env( *this, std::move(p), - std::make_unique( - integrityWarning, &found), + std::make_unique(integrityWarning, &found), beast::severities::kWarning); }(); @@ -77,12 +73,9 @@ public: auto const s = setup_DatabaseCon(env.app().config()); if (BEAST_EXPECT(s.globalPragma->size() == 3)) { - BEAST_EXPECT( - s.globalPragma->at(0) == "PRAGMA journal_mode=wal;"); - BEAST_EXPECT( - s.globalPragma->at(1) == "PRAGMA synchronous=normal;"); - BEAST_EXPECT( - s.globalPragma->at(2) == "PRAGMA temp_store=file;"); + BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=wal;"); + BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=normal;"); + BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=file;"); } } { @@ -101,8 +94,7 @@ public: return Env( *this, std::move(p), - std::make_unique( - integrityWarning, &found), + std::make_unique(integrityWarning, &found), beast::severities::kWarning); }(); @@ -110,12 +102,9 @@ public: auto const s = setup_DatabaseCon(env.app().config()); if (BEAST_EXPECT(s.globalPragma->size() == 3)) { - BEAST_EXPECT( - s.globalPragma->at(0) == "PRAGMA journal_mode=memory;"); - BEAST_EXPECT( - s.globalPragma->at(1) == "PRAGMA synchronous=off;"); - BEAST_EXPECT( - s.globalPragma->at(2) == "PRAGMA temp_store=memory;"); + BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=memory;"); + BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=off;"); + BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=memory;"); } } { @@ -135,8 +124,7 @@ public: return Env( *this, std::move(p), - std::make_unique( - integrityWarning, &found), + std::make_unique(integrityWarning, &found), beast::severities::kWarning); }(); @@ -146,12 +134,9 @@ public: auto const s = setup_DatabaseCon(env.app().config()); if (BEAST_EXPECT(s.globalPragma->size() == 3)) { - BEAST_EXPECT( - s.globalPragma->at(0) == "PRAGMA journal_mode=off;"); - BEAST_EXPECT( - s.globalPragma->at(1) == "PRAGMA synchronous=extra;"); - BEAST_EXPECT( - s.globalPragma->at(2) == "PRAGMA temp_store=default;"); + BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=off;"); + BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=extra;"); + BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=default;"); } } { @@ -172,8 +157,7 @@ public: return Env( *this, std::move(p), - std::make_unique( - integrityWarning, &found), + std::make_unique(integrityWarning, &found), beast::severities::kWarning); }(); @@ -183,12 +167,9 @@ public: auto const s = setup_DatabaseCon(env.app().config()); if (BEAST_EXPECT(s.globalPragma->size() == 3)) { - BEAST_EXPECT( - s.globalPragma->at(0) == "PRAGMA journal_mode=off;"); - BEAST_EXPECT( - s.globalPragma->at(1) == "PRAGMA synchronous=extra;"); - BEAST_EXPECT( - s.globalPragma->at(2) == "PRAGMA temp_store=default;"); + BEAST_EXPECT(s.globalPragma->at(0) == "PRAGMA journal_mode=off;"); + BEAST_EXPECT(s.globalPragma->at(1) == "PRAGMA synchronous=extra;"); + BEAST_EXPECT(s.globalPragma->at(2) == "PRAGMA temp_store=default;"); } } { @@ -429,12 +410,9 @@ public: if (BEAST_EXPECT(s.txPragma.size() == 4)) { BEAST_EXPECT(s.txPragma.at(0) == "PRAGMA page_size=4096;"); - BEAST_EXPECT( - s.txPragma.at(1) == "PRAGMA journal_size_limit=1582080;"); - BEAST_EXPECT( - s.txPragma.at(2) == "PRAGMA max_page_count=4294967294;"); - BEAST_EXPECT( - s.txPragma.at(3) == "PRAGMA mmap_size=17179869184;"); + BEAST_EXPECT(s.txPragma.at(1) == "PRAGMA journal_size_limit=1582080;"); + BEAST_EXPECT(s.txPragma.at(2) == "PRAGMA max_page_count=4294967294;"); + BEAST_EXPECT(s.txPragma.at(3) == "PRAGMA mmap_size=17179869184;"); } } { @@ -452,18 +430,14 @@ public: if (BEAST_EXPECT(s.txPragma.size() == 4)) { BEAST_EXPECT(s.txPragma.at(0) == "PRAGMA page_size=512;"); - BEAST_EXPECT( - s.txPragma.at(1) == "PRAGMA journal_size_limit=2582080;"); - BEAST_EXPECT( - s.txPragma.at(2) == "PRAGMA max_page_count=4294967294;"); - BEAST_EXPECT( - s.txPragma.at(3) == "PRAGMA mmap_size=17179869184;"); + BEAST_EXPECT(s.txPragma.at(1) == "PRAGMA journal_size_limit=2582080;"); + BEAST_EXPECT(s.txPragma.at(2) == "PRAGMA max_page_count=4294967294;"); + BEAST_EXPECT(s.txPragma.at(3) == "PRAGMA mmap_size=17179869184;"); } } { // Error: Invalid values - auto const expected = - "Invalid page_size. Must be between 512 and 65536."; + auto const expected = "Invalid page_size. Must be between 512 and 65536."; bool found = false; auto p = test::jtx::envconfig(); { @@ -486,8 +460,7 @@ public: } { // Error: Invalid values - auto const expected = - "Invalid page_size. Must be between 512 and 65536."; + auto const expected = "Invalid page_size. Must be between 512 and 65536."; bool found = false; auto p = test::jtx::envconfig(); { @@ -536,10 +509,7 @@ public: //-------------------------------------------------------------------------- void - testImport( - std::string const& destBackendType, - std::string const& srcBackendType, - std::int64_t seedValue) + testImport(std::string const& destBackendType, std::string const& srcBackendType, std::int64_t seedValue) { DummyScheduler scheduler; @@ -553,8 +523,8 @@ public: // Write to source db { - std::unique_ptr src = Manager::instance().make_Database( - megabytes(4), scheduler, 2, srcParams, journal_); + std::unique_ptr src = + Manager::instance().make_Database(megabytes(4), scheduler, 2, srcParams, journal_); storeBatch(*src, batch); } @@ -562,8 +532,8 @@ public: { // Re-open the db - std::unique_ptr src = Manager::instance().make_Database( - megabytes(4), scheduler, 2, srcParams, journal_); + std::unique_ptr src = + Manager::instance().make_Database(megabytes(4), scheduler, 2, srcParams, journal_); // Set up the destination database beast::temp_dir dest_db; @@ -571,12 +541,10 @@ public: destParams.set("type", destBackendType); destParams.set("path", dest_db.path()); - std::unique_ptr dest = Manager::instance().make_Database( - megabytes(4), scheduler, 2, destParams, journal_); + std::unique_ptr dest = + Manager::instance().make_Database(megabytes(4), scheduler, 2, destParams, journal_); - testcase( - "import into '" + destBackendType + "' from '" + - srcBackendType + "'"); + testcase("import into '" + destBackendType + "' from '" + srcBackendType + "'"); // Do the import dest->importDatabase(*src); @@ -618,8 +586,8 @@ public: { // Open the database - std::unique_ptr db = Manager::instance().make_Database( - megabytes(4), scheduler, 2, nodeParams, journal_); + std::unique_ptr db = + Manager::instance().make_Database(megabytes(4), scheduler, 2, nodeParams, journal_); // Write the batch storeBatch(*db, batch); @@ -643,8 +611,8 @@ public: if (testPersistence) { // Re-open the database without the ephemeral DB - std::unique_ptr db = Manager::instance().make_Database( - megabytes(4), scheduler, 2, nodeParams, journal_); + std::unique_ptr db = + Manager::instance().make_Database(megabytes(4), scheduler, 2, nodeParams, journal_); // Read it back in Batch copy; @@ -661,10 +629,8 @@ public: // Verify default earliest ledger sequence { std::unique_ptr db = - Manager::instance().make_Database( - megabytes(4), scheduler, 2, nodeParams, journal_); - BEAST_EXPECT( - db->earliestLedgerSeq() == XRP_LEDGER_EARLIEST_SEQ); + Manager::instance().make_Database(megabytes(4), scheduler, 2, nodeParams, journal_); + BEAST_EXPECT(db->earliestLedgerSeq() == XRP_LEDGER_EARLIEST_SEQ); } // Set an invalid earliest ledger sequence @@ -672,21 +638,18 @@ public: { nodeParams.set("earliest_seq", "0"); std::unique_ptr db = - Manager::instance().make_Database( - megabytes(4), scheduler, 2, nodeParams, journal_); + Manager::instance().make_Database(megabytes(4), scheduler, 2, nodeParams, journal_); } catch (std::runtime_error const& e) { - BEAST_EXPECT( - std::strcmp(e.what(), "Invalid earliest_seq") == 0); + BEAST_EXPECT(std::strcmp(e.what(), "Invalid earliest_seq") == 0); } { // Set a valid earliest ledger sequence nodeParams.set("earliest_seq", "1"); std::unique_ptr db = - Manager::instance().make_Database( - megabytes(4), scheduler, 2, nodeParams, journal_); + Manager::instance().make_Database(megabytes(4), scheduler, 2, nodeParams, journal_); // Verify database uses the earliest ledger sequence setting BEAST_EXPECT(db->earliestLedgerSeq() == 1); @@ -696,17 +659,13 @@ public: try { // Set to default earliest ledger sequence - nodeParams.set( - "earliest_seq", std::to_string(XRP_LEDGER_EARLIEST_SEQ)); + nodeParams.set("earliest_seq", std::to_string(XRP_LEDGER_EARLIEST_SEQ)); std::unique_ptr db2 = - Manager::instance().make_Database( - megabytes(4), scheduler, 2, nodeParams, journal_); + Manager::instance().make_Database(megabytes(4), scheduler, 2, nodeParams, journal_); } catch (std::runtime_error const& e) { - BEAST_EXPECT( - std::strcmp(e.what(), "earliest_seq set more than once") == - 0); + BEAST_EXPECT(std::strcmp(e.what(), "earliest_seq set more than once") == 0); } } } diff --git a/src/test/nodestore/NuDBFactory_test.cpp b/src/test/nodestore/NuDBFactory_test.cpp index b91425259c..7d8f1df45d 100644 --- a/src/test/nodestore/NuDBFactory_test.cpp +++ b/src/test/nodestore/NuDBFactory_test.cpp @@ -30,17 +30,14 @@ private: // Helper function to create a backend and test basic functionality bool - testBackendFunctionality( - Section const& params, - std::size_t expectedBlocksize) + testBackendFunctionality(Section const& params, std::size_t expectedBlocksize) { try { DummyScheduler scheduler; test::SuiteJournal journal("NuDBFactory_test", *this); - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); if (!BEAST_EXPECT(backend)) return false; @@ -72,17 +69,13 @@ private: // Helper function to test log messages void - testLogMessage( - Section const& params, - beast::severities::Severity level, - std::string const& expectedMessage) + testLogMessage(Section const& params, beast::severities::Severity level, std::string const& expectedMessage) { test::StreamSink sink(level); beast::Journal journal(sink); DummyScheduler scheduler; - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); std::string logOutput = sink.messages().str(); BEAST_EXPECT(logOutput.find(expectedMessage) != std::string::npos); @@ -99,12 +92,10 @@ private: beast::Journal journal(sink); DummyScheduler scheduler; - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); std::string logOutput = sink.messages().str(); - bool hasWarning = - logOutput.find("Invalid nudb_block_size") != std::string::npos; + bool hasWarning = logOutput.find("Invalid nudb_block_size") != std::string::npos; BEAST_EXPECT(hasWarning == !shouldWork); } @@ -199,10 +190,7 @@ public: beast::temp_dir tempDir; auto params = createSection(tempDir.path(), "8192"); - testLogMessage( - params, - beast::severities::kInfo, - "Using custom NuDB block size: 8192"); + testLogMessage(params, beast::severities::kInfo, "Using custom NuDB block size: 8192"); } // Test invalid block size failure @@ -216,20 +204,14 @@ public: DummyScheduler scheduler; try { - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); fail(); } catch (std::exception const& e) { std::string logOutput{e.what()}; - BEAST_EXPECT( - logOutput.find("Invalid nudb_block_size: 5000") != - std::string::npos); - BEAST_EXPECT( - logOutput.find( - "Must be power of 2 between 4096 and 32768") != - std::string::npos); + BEAST_EXPECT(logOutput.find("Invalid nudb_block_size: 5000") != std::string::npos); + BEAST_EXPECT(logOutput.find("Must be power of 2 between 4096 and 32768") != std::string::npos); } } @@ -244,17 +226,14 @@ public: DummyScheduler scheduler; try { - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); fail(); } catch (std::exception const& e) { std::string logOutput{e.what()}; - BEAST_EXPECT( - logOutput.find("Invalid nudb_block_size value: invalid") != - std::string::npos); + BEAST_EXPECT(logOutput.find("Invalid nudb_block_size value: invalid") != std::string::npos); } } } @@ -290,16 +269,13 @@ public: DummyScheduler scheduler; try { - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); BEAST_EXPECT(shouldWork); } catch (std::exception const& e) { std::string logOutput{e.what()}; - BEAST_EXPECT( - logOutput.find("Invalid nudb_block_size") != - std::string::npos); + BEAST_EXPECT(logOutput.find("Invalid nudb_block_size") != std::string::npos); } } } @@ -317,8 +293,7 @@ public: // Test first constructor (without nudb::context) { - auto backend1 = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend1 = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); BEAST_EXPECT(backend1 != nullptr); BEAST_EXPECT(testBackendFunctionality(params, 16384)); } @@ -358,14 +333,11 @@ public: beast::Journal journal(sink); DummyScheduler scheduler; - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); // Should log success message for valid values std::string logOutput = sink.messages().str(); - bool hasSuccessMessage = - logOutput.find("Using custom NuDB block size") != - std::string::npos; + bool hasSuccessMessage = logOutput.find("Using custom NuDB block size") != std::string::npos; BEAST_EXPECT(hasSuccessMessage); } @@ -383,8 +355,7 @@ public: DummyScheduler scheduler; try { - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); fail(); } catch (...) @@ -400,8 +371,7 @@ public: { testcase("Data persistence with different block sizes"); - std::vector blockSizes = { - "4096", "8192", "16384", "32768"}; + std::vector blockSizes = {"4096", "8192", "16384", "32768"}; for (auto const& size : blockSizes) { @@ -416,8 +386,7 @@ public: // Store data { - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); backend->open(); storeBatch(*backend, batch); backend->close(); @@ -425,8 +394,7 @@ public: // Retrieve data in new backend instance { - auto backend = Manager::instance().make_Backend( - params, megabytes(4), scheduler, journal); + auto backend = Manager::instance().make_Backend(params, megabytes(4), scheduler, journal); backend->open(); Batch copy; diff --git a/src/test/nodestore/TestBase.h b/src/test/nodestore/TestBase.h index 83db83b1df..c08559de36 100644 --- a/src/test/nodestore/TestBase.h +++ b/src/test/nodestore/TestBase.h @@ -27,9 +27,7 @@ namespace NodeStore { struct LessThan { bool - operator()( - std::shared_ptr const& lhs, - std::shared_ptr const& rhs) const noexcept + operator()(std::shared_ptr const& lhs, std::shared_ptr const& rhs) const noexcept { return lhs->getHash() < rhs->getHash(); } @@ -37,12 +35,9 @@ struct LessThan /** Returns `true` if objects are identical. */ inline bool -isSame( - std::shared_ptr const& lhs, - std::shared_ptr const& rhs) +isSame(std::shared_ptr const& lhs, std::shared_ptr const& rhs) { - return (lhs->getType() == rhs->getType()) && - (lhs->getHash() == rhs->getHash()) && + return (lhs->getType() == rhs->getType()) && (lhs->getHash() == rhs->getHash()) && (lhs->getData() == rhs->getData()); } @@ -91,8 +86,7 @@ public: Blob blob(rand_int(rng, minPayloadBytes, maxPayloadBytes)); beast::rngfill(blob.data(), blob.size(), rng); - batch.push_back( - NodeObject::createObject(type, std::move(blob), hash)); + batch.push_back(NodeObject::createObject(type, std::move(blob), hash)); } return batch; @@ -144,8 +138,7 @@ public: { std::shared_ptr object; - Status const status = - backend.fetch(batch[i]->getHash().cbegin(), &object); + Status const status = backend.fetch(batch[i]->getHash().cbegin(), &object); BEAST_EXPECT(status == ok); @@ -165,8 +158,7 @@ public: { std::shared_ptr object; - Status const status = - backend.fetch(batch[i]->getHash().cbegin(), &object); + Status const status = backend.fetch(batch[i]->getHash().cbegin(), &object); BEAST_EXPECT(status == notFound); } @@ -182,11 +174,7 @@ public: Blob data(object->getData()); - db.store( - object->getType(), - std::move(data), - object->getHash(), - db.earliestLedgerSeq()); + db.store(object->getType(), std::move(data), object->getHash(), db.earliestLedgerSeq()); } } @@ -199,8 +187,7 @@ public: for (int i = 0; i < batch.size(); ++i) { - std::shared_ptr object = - db.fetchNodeObject(batch[i]->getHash(), 0); + std::shared_ptr object = db.fetchNodeObject(batch[i]->getHash(), 0); if (object != nullptr) pCopy->push_back(object); diff --git a/src/test/nodestore/Timing_test.cpp b/src/test/nodestore/Timing_test.cpp index 9c91311416..09e39028e8 100644 --- a/src/test/nodestore/Timing_test.cpp +++ b/src/test/nodestore/Timing_test.cpp @@ -31,13 +31,9 @@ namespace xrpl { namespace NodeStore { std::unique_ptr -make_Backend( - Section const& config, - Scheduler& scheduler, - beast::Journal journal) +make_Backend(Section const& config, Scheduler& scheduler, beast::Journal journal) { - return Manager::instance().make_Backend( - config, megabytes(4), scheduler, journal); + return Manager::instance().make_Backend(config, megabytes(4), scheduler, journal); } // Fill memory with random bits @@ -104,8 +100,7 @@ public: rngcpy(data + 1, key.size() - 1, gen_); Blob value(d_size_(gen_)); rngcpy(&value[0], value.size(), gen_); - return NodeObject::createObject( - safe_cast(d_type_(gen_)), std::move(value), key); + return NodeObject::createObject(safe_cast(d_type_(gen_)), std::move(value), key); } // returns a batch of NodeObjects starting at n @@ -150,8 +145,7 @@ public: { std::string s; for (auto iter = config.begin(); iter != config.end(); ++iter) - s += (iter != config.begin() ? "," : "") + iter->first + "=" + - iter->second; + s += (iter != config.begin() ? "," : "") + iter->first + "=" + iter->second; return s; } @@ -185,8 +179,7 @@ public: std::atomic& c_; public: - parallel_for_lambda(std::size_t n, std::atomic& c) - : n_(n), c_(c) + parallel_for_lambda(std::size_t n, std::atomic& c) : n_(n), c_(c) { } @@ -213,10 +206,7 @@ public: */ template void - parallel_for( - std::size_t const n, - std::size_t number_of_threads, - Args const&... args) + parallel_for(std::size_t const n, std::size_t number_of_threads, Args const&... args) { std::atomic c(0); std::vector t; @@ -229,10 +219,7 @@ public: template void - parallel_for_id( - std::size_t const n, - std::size_t number_of_threads, - Args const&... args) + parallel_for_id(std::size_t const n, std::size_t number_of_threads, Args const&... args) { std::atomic c(0); std::vector t; @@ -247,10 +234,7 @@ public: // Insert only void - do_insert( - Section const& config, - Params const& params, - beast::Journal journal) + do_insert(Section const& config, Params const& params, beast::Journal journal) { DummyScheduler scheduler; auto backend = make_Backend(config, scheduler, journal); @@ -265,8 +249,7 @@ public: Sequence seq_; public: - explicit Body(suite& s, Backend& backend) - : suite_(s), backend_(backend), seq_(1) + explicit Body(suite& s, Backend& backend) : suite_(s), backend_(backend), seq_(1) { } @@ -286,11 +269,7 @@ public: try { - parallel_for( - params.items, - params.threads, - std::ref(*this), - std::ref(*backend)); + parallel_for(params.items, params.threads, std::ref(*this), std::ref(*backend)); } catch (std::exception const&) { @@ -304,10 +283,7 @@ public: // Fetch existing keys void - do_fetch( - Section const& config, - Params const& params, - beast::Journal journal) + do_fetch(Section const& config, Params const& params, beast::Journal journal) { DummyScheduler scheduler; auto backend = make_Backend(config, scheduler, journal); @@ -324,16 +300,8 @@ public: std::uniform_int_distribution dist_; public: - Body( - std::size_t id, - suite& s, - Params const& params, - Backend& backend) - : suite_(s) - , backend_(backend) - , seq1_(1) - , gen_(id + 1) - , dist_(0, params.items - 1) + Body(std::size_t id, suite& s, Params const& params, Backend& backend) + : suite_(s), backend_(backend), seq1_(1), gen_(id + 1), dist_(0, params.items - 1) { } @@ -356,12 +324,7 @@ public: }; try { - parallel_for_id( - params.items, - params.threads, - std::ref(*this), - std::ref(params), - std::ref(*backend)); + parallel_for_id(params.items, params.threads, std::ref(*this), std::ref(params), std::ref(*backend)); } catch (std::exception const&) { @@ -375,10 +338,7 @@ public: // Perform lookups of non-existent keys void - do_missing( - Section const& config, - Params const& params, - beast::Journal journal) + do_missing(Section const& config, Params const& params, beast::Journal journal) { DummyScheduler scheduler; auto backend = make_Backend(config, scheduler, journal); @@ -396,11 +356,7 @@ public: std::uniform_int_distribution dist_; public: - Body( - std::size_t id, - suite& s, - Params const& params, - Backend& backend) + Body(std::size_t id, suite& s, Params const& params, Backend& backend) : suite_(s) //, params_ (params) , backend_(backend) @@ -429,12 +385,7 @@ public: try { - parallel_for_id( - params.items, - params.threads, - std::ref(*this), - std::ref(params), - std::ref(*backend)); + parallel_for_id(params.items, params.threads, std::ref(*this), std::ref(params), std::ref(*backend)); } catch (std::exception const&) { @@ -448,10 +399,7 @@ public: // Fetch with present and missing keys void - do_mixed( - Section const& config, - Params const& params, - beast::Journal journal) + do_mixed(Section const& config, Params const& params, beast::Journal journal) { DummyScheduler scheduler; auto backend = make_Backend(config, scheduler, journal); @@ -471,11 +419,7 @@ public: std::uniform_int_distribution dist_; public: - Body( - std::size_t id, - suite& s, - Params const& params, - Backend& backend) + Body(std::size_t id, suite& s, Params const& params, Backend& backend) : suite_(s) //, params_ (params) , backend_(backend) @@ -517,12 +461,7 @@ public: try { - parallel_for_id( - params.items, - params.threads, - std::ref(*this), - std::ref(params), - std::ref(*backend)); + parallel_for_id(params.items, params.threads, std::ref(*this), std::ref(params), std::ref(*backend)); } catch (std::exception const&) { @@ -561,11 +500,7 @@ public: std::uniform_int_distribution older_; public: - Body( - std::size_t id, - suite& s, - Params const& params, - Backend& backend) + Body(std::size_t id, suite& s, Params const& params, Backend& backend) : suite_(s) , params_(params) , backend_(backend) @@ -631,12 +566,7 @@ public: try { - parallel_for_id( - params.items, - params.threads, - std::ref(*this), - std::ref(params), - std::ref(*backend)); + parallel_for_id(params.items, params.threads, std::ref(*this), std::ref(params), std::ref(*backend)); } catch (std::exception const&) { @@ -650,36 +580,26 @@ public: //-------------------------------------------------------------------------- - using test_func = - void (Timing_test::*)(Section const&, Params const&, beast::Journal); + using test_func = void (Timing_test::*)(Section const&, Params const&, beast::Journal); using test_list = std::vector>; duration_type - do_test( - test_func f, - Section const& config, - Params const& params, - beast::Journal journal) + do_test(test_func f, Section const& config, Params const& params, beast::Journal journal) { auto const start = clock_type::now(); (this->*f)(config, params, journal); - return std::chrono::duration_cast( - clock_type::now() - start); + return std::chrono::duration_cast(clock_type::now() - start); } void - do_tests( - std::size_t threads, - test_list const& tests, - std::vector const& config_strings) + do_tests(std::size_t threads, test_list const& tests, std::vector const& config_strings) { using std::setw; int w = 8; for (auto const& test : tests) if (w < test.first.size()) w = test.first.size(); - log << threads << " Thread" << (threads > 1 ? "s" : "") << ", " - << default_items << " Objects" << std::endl; + log << threads << " Thread" << (threads > 1 ? "s" : "") << ", " << default_items << " Objects" << std::endl; { std::stringstream ss; ss << std::left << setw(10) << "Backend" << std::right; @@ -702,12 +622,9 @@ public: Section config = parse(config_string); config.set("path", tempDir.path()); std::stringstream ss; - ss << std::left << setw(10) - << get(config, "type", std::string()) << std::right; + ss << std::left << setw(10) << get(config, "type", std::string()) << std::right; for (auto const& test : tests) - ss << " " << setw(w) - << to_string( - do_test(test.second, config, params, journal)); + ss << " " << setw(w) << to_string(do_test(test.second, config, params, journal)); ss << " " << to_string(config); log << ss.str() << std::endl; } diff --git a/src/test/nodestore/import_test.cpp b/src/test/nodestore/import_test.cpp index 9a786801cb..896f9558da 100644 --- a/src/test/nodestore/import_test.cpp +++ b/src/test/nodestore/import_test.cpp @@ -62,10 +62,7 @@ public: save_stream_state& operator=(save_stream_state const&) = delete; explicit save_stream_state(std::ostream& os) - : os_(os) - , precision_(os.precision()) - , flags_(os.flags()) - , fill_(os.fill()) + : os_(os), precision_(os.precision()), flags_(os.flags()), fill_(os.fill()) { } }; @@ -212,11 +209,9 @@ public: return; } auto const rate = elapsed.count() / double(work); - clock_type::duration const remain( - static_cast((work_ - work) * rate)); - log << "Remaining: " << detail::fmtdur(remain) << " (" << work << " of " - << work_ << " in " << detail::fmtdur(elapsed) << ", " - << (work - prev_) << " in " << detail::fmtdur(now - report_) << ")"; + clock_type::duration const remain(static_cast((work_ - work) * rate)); + log << "Remaining: " << detail::fmtdur(remain) << " (" << work << " of " << work_ << " in " + << detail::fmtdur(elapsed) << ", " << (work - prev_) << " in " << detail::fmtdur(now - report_) << ")"; report_ = now; prev_ = work; } @@ -335,11 +330,9 @@ public: options.create_if_missing = false; options.max_open_files = 2000; // 5000? rocksdb::DB* pdb = nullptr; - rocksdb::Status status = - rocksdb::DB::OpenForReadOnly(options, from_path, &pdb); + rocksdb::Status status = rocksdb::DB::OpenForReadOnly(options, from_path, &pdb); if (!status.ok() || !pdb) - Throw( - "Can't open '" + from_path + "': " + status.ToString()); + Throw("Can't open '" + from_path + "': " + status.ToString()); db.reset(pdb); } // Create data file with values @@ -372,9 +365,7 @@ public: for (it->SeekToFirst(); it->Valid(); it->Next()) { if (it->key().size() != 32) - Throw( - "Unexpected key size " + - std::to_string(it->key().size())); + Throw("Unexpected key size " + std::to_string(it->key().size())); void const* const key = it->key().data(); void const* const data = it->value().data(); auto const size = it->value().size(); @@ -385,11 +376,9 @@ public: // Verify codec correctness { buffer buf2; - auto const check = - nodeobject_decompress(out.first, out.second, buf2); + auto const check = nodeobject_decompress(out.first, out.second, buf2); BEAST_EXPECT(check.second == size); - BEAST_EXPECT( - std::memcmp(check.first, clean.get(), size) == 0); + BEAST_EXPECT(std::memcmp(check.first, clean.get(), size) == 0); } // Data Record auto os = dw.prepare( @@ -409,8 +398,7 @@ public: Throw(ec); } db.reset(); - log << "Import data: " - << detail::fmtdur(std::chrono::steady_clock::now() - start); + log << "Import data: " << detail::fmtdur(std::chrono::steady_clock::now() - start); auto const df_size = df.size(ec); if (ec) Throw(ec); @@ -424,8 +412,7 @@ public: kh.pepper = pepper(kh.salt); kh.block_size = block_size(kp); kh.load_factor = std::min(65536.0 * load_factor, 65535); - kh.buckets = - std::ceil(nitems / (bucket_capacity(kh.block_size) * load_factor)); + kh.buckets = std::ceil(nitems / (bucket_capacity(kh.block_size) * load_factor)); kh.modulus = ceil_pow2(kh.buckets); native_file kf; kf.create(file_mode::append, kp, ec); @@ -443,8 +430,7 @@ public: // Build contiguous sequential sections of the // key file using multiple passes over the data. // - auto const buckets = - std::max(1, buffer_size / kh.block_size); + auto const buckets = std::max(1, buffer_size / kh.block_size); buf.reserve(buckets * kh.block_size); auto const passes = (kh.buckets + buckets - 1) / buckets; log << "items: " << nitems @@ -471,8 +457,7 @@ public: } // Insert all keys into buckets // Iterate Data File - bulk_reader r( - df, dat_file_header::size, df_size, bulk_size); + bulk_reader r(df, dat_file_header::size, df_size, bulk_size); while (!r.eof()) { auto const offset = r.offset(); @@ -497,8 +482,7 @@ public: p(log, npass * df_size + r.offset()); if (n < b0 || n >= b1) continue; - bucket b( - kh.block_size, buf.get() + (n - b0) * kh.block_size); + bucket b(kh.block_size, buf.get() + (n - b0) * kh.block_size); maybe_spill(b, dw, ec); if (ec) Throw(ec); @@ -517,8 +501,7 @@ public: Throw(ec); } } - kf.write( - (b0 + 1) * kh.block_size, buf.get(), bn * kh.block_size, ec); + kf.write((b0 + 1) * kh.block_size, buf.get(), bn * kh.block_size, ec); if (ec) Throw(ec); ++npass; diff --git a/src/test/overlay/ProtocolVersion_test.cpp b/src/test/overlay/ProtocolVersion_test.cpp index 507a42eca0..02cbaba909 100644 --- a/src/test/overlay/ProtocolVersion_test.cpp +++ b/src/test/overlay/ProtocolVersion_test.cpp @@ -62,18 +62,10 @@ public: testcase("Protocol version negotiation"); BEAST_EXPECT(negotiateProtocolVersion("RTXP/1.2") == std::nullopt); - BEAST_EXPECT( - negotiateProtocolVersion("RTXP/1.2, XRPL/2.0, XRPL/2.1") == - make_protocol(2, 1)); - BEAST_EXPECT( - negotiateProtocolVersion("XRPL/2.2") == make_protocol(2, 2)); - BEAST_EXPECT( - negotiateProtocolVersion( - "RTXP/1.2, XRPL/2.2, XRPL/2.3, XRPL/999.999") == - make_protocol(2, 2)); - BEAST_EXPECT( - negotiateProtocolVersion("XRPL/999.999, WebSocket/1.0") == - std::nullopt); + BEAST_EXPECT(negotiateProtocolVersion("RTXP/1.2, XRPL/2.0, XRPL/2.1") == make_protocol(2, 1)); + BEAST_EXPECT(negotiateProtocolVersion("XRPL/2.2") == make_protocol(2, 2)); + BEAST_EXPECT(negotiateProtocolVersion("RTXP/1.2, XRPL/2.2, XRPL/2.3, XRPL/999.999") == make_protocol(2, 2)); + BEAST_EXPECT(negotiateProtocolVersion("XRPL/999.999, WebSocket/1.0") == std::nullopt); BEAST_EXPECT(negotiateProtocolVersion("") == std::nullopt); } } diff --git a/src/test/overlay/TMGetObjectByHash_test.cpp b/src/test/overlay/TMGetObjectByHash_test.cpp index 71a485416d..c4e70ba305 100644 --- a/src/test/overlay/TMGetObjectByHash_test.cpp +++ b/src/test/overlay/TMGetObjectByHash_test.cpp @@ -97,27 +97,17 @@ class TMGetObjectByHash_test : public beast::unit_test::suite { auto& overlay = dynamic_cast(env.app().overlay()); boost::beast::http::request request; - auto stream_ptr = std::make_unique( - socket_type(env.app().getIOContext()), *context_); + auto stream_ptr = std::make_unique(socket_type(env.app().getIOContext()), *context_); - beast::IP::Endpoint local( - boost::asio::ip::make_address("172.1.1.1"), 51235); - beast::IP::Endpoint remote( - boost::asio::ip::make_address("172.1.1.2"), 51235); + beast::IP::Endpoint local(boost::asio::ip::make_address("172.1.1.1"), 51235); + beast::IP::Endpoint remote(boost::asio::ip::make_address("172.1.1.2"), 51235); PublicKey key(std::get<0>(randomKeyPair(KeyType::ed25519))); auto consumer = overlay.resourceManager().newInboundEndpoint(remote); auto [slot, _] = overlay.peerFinder().new_inbound_slot(local, remote); auto peer = std::make_shared( - env.app(), - slot, - std::move(request), - key, - protocolVersion_, - consumer, - std::move(stream_ptr), - overlay); + env.app(), slot, std::move(request), key, protocolVersion_, consumer, std::move(stream_ptr), overlay); overlay.add_active(peer); return peer; @@ -138,11 +128,7 @@ class TMGetObjectByHash_test : public beast::unit_test::suite hashes.push_back(hash); Blob data(100, static_cast(i % 256)); - nodeStore.store( - hotLEDGER, - std::move(data), - hash, - nodeStore.earliestLedgerSeq()); + nodeStore.store(hotLEDGER, std::move(data), hash, nodeStore.earliestLedgerSeq()); } // Create a request with more objects than hardMaxReplyNodes @@ -182,14 +168,12 @@ class TMGetObjectByHash_test : public beast::unit_test::suite BEAST_EXPECT(sentMessage != nullptr); // Parse the reply message - auto const& buffer = - sentMessage->getBuffer(compression::Compressed::Off); + auto const& buffer = sentMessage->getBuffer(compression::Compressed::Off); BEAST_EXPECT(buffer.size() > 6); // Skip the message header (6 bytes: 4 for size, 2 for type) protocol::TMGetObjectByHash reply; - BEAST_EXPECT( - reply.ParseFromArray(buffer.data() + 6, buffer.size() - 6) == true); + BEAST_EXPECT(reply.ParseFromArray(buffer.data() + 6, buffer.size() - 6) == true); // Verify the reply is limited to expectedReplySize BEAST_EXPECT(reply.objects_size() == expectedReplySize); diff --git a/src/test/overlay/cluster_test.cpp b/src/test/overlay/cluster_test.cpp index 4638434233..60fd5d62b3 100644 --- a/src/test/overlay/cluster_test.cpp +++ b/src/test/overlay/cluster_test.cpp @@ -69,8 +69,7 @@ public: { testcase("Membership: Non-empty cluster and some present"); - std::vector cluster( - network.begin(), network.begin() + 16); + std::vector cluster(network.begin(), network.begin() + 16); while (cluster.size() != 32) cluster.push_back(randomNode()); @@ -83,17 +82,14 @@ public: for (auto const& n : network) { auto found = std::find(cluster.begin(), cluster.end(), n); - BEAST_EXPECT( - static_cast(c->member(n)) == - (found != cluster.end())); + BEAST_EXPECT(static_cast(c->member(n)) == (found != cluster.end())); } } { testcase("Membership: Non-empty cluster and all present"); - std::vector cluster( - network.begin(), network.begin() + 32); + std::vector cluster(network.begin(), network.begin() + 32); auto c = create(cluster); @@ -103,9 +99,7 @@ public: for (auto const& n : network) { auto found = std::find(cluster.begin(), cluster.end(), n); - BEAST_EXPECT( - static_cast(c->member(n)) == - (found != cluster.end())); + BEAST_EXPECT(static_cast(c->member(n)) == (found != cluster.end())); } } } @@ -181,8 +175,7 @@ public: while (network.size() != 8) network.push_back(randomNode()); - auto format = [](PublicKey const& publicKey, - char const* comment = nullptr) { + auto format = [](PublicKey const& publicKey, char const* comment = nullptr) { auto ret = toBase58(TokenType::NodePublic, publicKey); if (comment) @@ -205,8 +198,7 @@ public: s1.append(format(network[4], " Leading Whitespace")); s1.append(format(network[5], " Trailing Whitespace ")); s1.append(format(network[6], " Leading & Trailing Whitespace ")); - s1.append(format( - network[7], " Leading, Trailing & Internal Whitespace ")); + s1.append(format(network[7], " Leading, Trailing & Internal Whitespace ")); BEAST_EXPECT(c->load(s1)); diff --git a/src/test/overlay/compression_test.cpp b/src/test/overlay/compression_test.cpp index f2fe07cb33..6dffe4e5c9 100644 --- a/src/test/overlay/compression_test.cpp +++ b/src/test/overlay/compression_test.cpp @@ -65,11 +65,7 @@ public: template void - doTest( - std::shared_ptr proto, - protocol::MessageType mt, - uint16_t nbuffers, - std::string msg) + doTest(std::shared_ptr proto, protocol::MessageType mt, uint16_t nbuffers, std::string msg) { testcase("Compress/Decompress: " + msg); @@ -84,16 +80,13 @@ public: for (int i = 0; i < nbuffers; i++) { auto start = buffer.begin() + sz * i; - auto end = i < nbuffers - 1 ? (buffer.begin() + sz * (i + 1)) - : buffer.end(); + auto end = i < nbuffers - 1 ? (buffer.begin() + sz * (i + 1)) : buffer.end(); std::vector slice(start, end); - buffers.commit(boost::asio::buffer_copy( - buffers.prepare(slice.size()), boost::asio::buffer(slice))); + buffers.commit(boost::asio::buffer_copy(buffers.prepare(slice.size()), boost::asio::buffer(slice))); } boost::system::error_code ec; - auto header = - xrpl::detail::parseMessageHeader(ec, buffers.data(), buffer.size()); + auto header = xrpl::detail::parseMessageHeader(ec, buffers.data(), buffer.size()); BEAST_EXPECT(header); @@ -103,27 +96,20 @@ public: std::vector decompressed; decompressed.resize(header->uncompressed_size); - BEAST_EXPECT( - header->payload_wire_size == buffer.size() - header->header_size); + BEAST_EXPECT(header->payload_wire_size == buffer.size() - header->header_size); ZeroCopyInputStream stream(buffers.data()); stream.Skip(header->header_size); auto decompressedSize = xrpl::compression::decompress( - stream, - header->payload_wire_size, - decompressed.data(), - header->uncompressed_size); + stream, header->payload_wire_size, decompressed.data(), header->uncompressed_size); BEAST_EXPECT(decompressedSize == header->uncompressed_size); auto const proto1 = std::make_shared(); - BEAST_EXPECT( - proto1->ParseFromArray(decompressed.data(), decompressedSize)); + BEAST_EXPECT(proto1->ParseFromArray(decompressed.data(), decompressedSize)); auto uncompressed = m.getBuffer(Compressed::Off); BEAST_EXPECT(std::equal( - uncompressed.begin() + xrpl::compression::headerBytes, - uncompressed.end(), - decompressed.begin())); + uncompressed.begin() + xrpl::compression::headerBytes, uncompressed.end(), decompressed.begin())); } std::shared_ptr @@ -139,20 +125,9 @@ public: st[sfSequence] = i; st[sfPublicKey] = std::get<0>(master); st[sfSigningPubKey] = std::get<0>(signing); - st[sfDomain] = makeSlice( - std::string("example") + std::to_string(i) + - std::string(".com")); - sign( - st, - HashPrefix::manifest, - KeyType::ed25519, - std::get<1>(master), - sfMasterSignature); - sign( - st, - HashPrefix::manifest, - KeyType::ed25519, - std::get<1>(signing)); + st[sfDomain] = makeSlice(std::string("example") + std::to_string(i) + std::string(".com")); + sign(st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(master), sfMasterSignature); + sign(st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); Serializer s; st.add(s); auto* manifest = manifests->add_list(); @@ -191,8 +166,7 @@ public: auto toBinary = [this](std::string const& text) { auto blob = strUnHex(text); BEAST_EXPECT(blob); - return std::string{ - reinterpret_cast(blob->data()), blob->size()}; + return std::string{reinterpret_cast(blob->data()), blob->size()}; }; std::string usdTxBlob = ""; @@ -200,12 +174,10 @@ public: { Json::Value jrequestUsd; jrequestUsd[jss::secret] = toBase58(generateSeed("bob")); - jrequestUsd[jss::tx_json] = - pay("bob", "alice", bob["USD"](fund / 2)); + jrequestUsd[jss::tx_json] = pay("bob", "alice", bob["USD"](fund / 2)); Json::Value jreply_usd = wsc->invoke("sign", jrequestUsd); - usdTxBlob = - toBinary(jreply_usd[jss::result][jss::tx_blob].asString()); + usdTxBlob = toBinary(jreply_usd[jss::result][jss::tx_blob].asString()); } auto transaction = std::make_shared(); @@ -266,8 +238,7 @@ public: parentHash = ledgerHash(info); Serializer nData; xrpl::addRaw(info, nData); - ledgerData->add_nodes()->set_nodedata( - nData.getDataPtr(), nData.getLength()); + ledgerData->add_nodes()->set_nodedata(nData.getDataPtr(), nData.getLength()); } return ledgerData; @@ -278,8 +249,7 @@ public: { auto getObject = std::make_shared(); - getObject->set_type(protocol::TMGetObjectByHash_ObjectType:: - TMGetObjectByHash_ObjectType_otTRANSACTION); + getObject->set_type(protocol::TMGetObjectByHash_ObjectType::TMGetObjectByHash_ObjectType_otTRANSACTION); getObject->set_query(true); getObject->set_seq(123456789); uint256 hash(xrpl::sha512Half(123456789)); @@ -311,20 +281,14 @@ public: st[sfPublicKey] = std::get<0>(master); st[sfSigningPubKey] = std::get<0>(signing); st[sfDomain] = makeSlice(std::string("example.com")); - sign( - st, - HashPrefix::manifest, - KeyType::ed25519, - std::get<1>(master), - sfMasterSignature); + sign(st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(master), sfMasterSignature); sign(st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); Serializer s; st.add(s); list->set_manifest(s.data(), s.size()); list->set_version(3); STObject signature(sfSignature); - xrpl::sign( - st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); + xrpl::sign(st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); Serializer s1; st.add(s1); list->set_signature(s1.data(), s1.size()); @@ -344,20 +308,14 @@ public: st[sfPublicKey] = std::get<0>(master); st[sfSigningPubKey] = std::get<0>(signing); st[sfDomain] = makeSlice(std::string("example.com")); - sign( - st, - HashPrefix::manifest, - KeyType::ed25519, - std::get<1>(master), - sfMasterSignature); + sign(st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(master), sfMasterSignature); sign(st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); Serializer s; st.add(s); list->set_manifest(s.data(), s.size()); list->set_version(4); STObject signature(sfSignature); - xrpl::sign( - st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); + xrpl::sign(st, HashPrefix::manifest, KeyType::ed25519, std::get<1>(signing)); Serializer s1; st.add(s1); auto& blob = *list->add_blobs(); @@ -390,60 +348,24 @@ public: // 1.3KB doTest(buildEndpoints(100), protocol::mtENDPOINTS, 4, "TMEndpoints100"); // 242B - doTest( - buildTransaction(*logs), - protocol::mtTRANSACTION, - 1, - "TMTransaction"); + doTest(buildTransaction(*logs), protocol::mtTRANSACTION, 1, "TMTransaction"); // 87B doTest(buildGetLedger(), protocol::mtGET_LEDGER, 1, "TMGetLedger"); // 61KB - doTest( - buildLedgerData(500, *logs), - protocol::mtLEDGER_DATA, - 10, - "TMLedgerData500"); + doTest(buildLedgerData(500, *logs), protocol::mtLEDGER_DATA, 10, "TMLedgerData500"); // 122 KB - doTest( - buildLedgerData(1000, *logs), - protocol::mtLEDGER_DATA, - 20, - "TMLedgerData1000"); + doTest(buildLedgerData(1000, *logs), protocol::mtLEDGER_DATA, 20, "TMLedgerData1000"); // 1.2MB - doTest( - buildLedgerData(10000, *logs), - protocol::mtLEDGER_DATA, - 50, - "TMLedgerData10000"); + doTest(buildLedgerData(10000, *logs), protocol::mtLEDGER_DATA, 50, "TMLedgerData10000"); // 12MB - doTest( - buildLedgerData(100000, *logs), - protocol::mtLEDGER_DATA, - 100, - "TMLedgerData100000"); + doTest(buildLedgerData(100000, *logs), protocol::mtLEDGER_DATA, 100, "TMLedgerData100000"); // 61MB - doTest( - buildLedgerData(500000, *logs), - protocol::mtLEDGER_DATA, - 100, - "TMLedgerData500000"); + doTest(buildLedgerData(500000, *logs), protocol::mtLEDGER_DATA, 100, "TMLedgerData500000"); // 7.7KB - doTest( - buildGetObjectByHash(), - protocol::mtGET_OBJECTS, - 4, - "TMGetObjectByHash"); + doTest(buildGetObjectByHash(), protocol::mtGET_OBJECTS, 4, "TMGetObjectByHash"); // 895B - doTest( - buildValidatorList(), - protocol::mtVALIDATOR_LIST, - 4, - "TMValidatorList"); - doTest( - buildValidatorListCollection(), - protocol::mtVALIDATOR_LIST_COLLECTION, - 4, - "TMValidatorListCollection"); + doTest(buildValidatorList(), protocol::mtVALIDATOR_LIST, 4, "TMValidatorList"); + doTest(buildValidatorListCollection(), protocol::mtVALIDATOR_LIST_COLLECTION, 4, "TMValidatorListCollection"); } void @@ -460,13 +382,11 @@ public: c.loadFromString(str.str()); auto env = std::make_shared(*this); env->app().config().COMPRESSION = c.COMPRESSION; - env->app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = - c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE; + env->app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE; return env; }; auto handshake = [&](int outboundEnable, int inboundEnable) { - beast::IP::Address addr = - boost::asio::ip::make_address("172.1.1.100"); + beast::IP::Address addr = boost::asio::ip::make_address("172.1.1.100"); auto env = getEnv(outboundEnable); auto request = xrpl::makeRequest( @@ -483,25 +403,15 @@ public: auto const peerEnabled = inboundEnable && outboundEnable; // inbound is enabled if the request's header has the feature // enabled and the peer's configuration is enabled - auto const inboundEnabled = peerFeatureEnabled( - http_request, FEATURE_COMPR, "lz4", inboundEnable); + auto const inboundEnabled = peerFeatureEnabled(http_request, FEATURE_COMPR, "lz4", inboundEnable); BEAST_EXPECT(!(peerEnabled ^ inboundEnabled)); env.reset(); env = getEnv(inboundEnable); - auto http_resp = xrpl::makeResponse( - true, - http_request, - addr, - addr, - uint256{1}, - 1, - {1, 0}, - env->app()); + auto http_resp = xrpl::makeResponse(true, http_request, addr, addr, uint256{1}, 1, {1, 0}, env->app()); // outbound is enabled if the response's header has the feature // enabled and the peer's configuration is enabled - auto const outboundEnabled = peerFeatureEnabled( - http_resp, FEATURE_COMPR, "lz4", outboundEnable); + auto const outboundEnabled = peerFeatureEnabled(http_resp, FEATURE_COMPR, "lz4", outboundEnable); BEAST_EXPECT(!(peerEnabled ^ outboundEnabled)); }; handshake(1, 1); diff --git a/src/test/overlay/reduce_relay_test.cpp b/src/test/overlay/reduce_relay_test.cpp index 6af27ea8f1..9d9aef7a36 100644 --- a/src/test/overlay/reduce_relay_test.cpp +++ b/src/test/overlay/reduce_relay_test.cpp @@ -31,8 +31,7 @@ using MessageSPtr = std::shared_ptr; using LinkSPtr = std::shared_ptr; using PeerSPtr = std::shared_ptr; using PeerWPtr = std::weak_ptr; -using SquelchCB = - std::function; +using SquelchCB = std::function; using UnsquelchCB = std::function; using LinkIterCB = std::function; @@ -46,8 +45,7 @@ static constexpr std::uint32_t MAX_MESSAGES = 200000; class PeerPartial : public Peer { public: - PeerPartial() - : nodePublicKey_(derivePublicKey(KeyType::ed25519, randomSecretKey())) + PeerPartial() : nodePublicKey_(derivePublicKey(KeyType::ed25519, randomSecretKey())) { } @@ -76,8 +74,7 @@ public: return {}; } void - charge(Resource::Charge const& fee, std::string const& context = {}) - override + charge(Resource::Charge const& fee, std::string const& context = {}) override { } bool @@ -248,10 +245,7 @@ class Link using Latency = std::pair; public: - Link( - Validator& validator, - PeerSPtr peer, - Latency const& latency = {milliseconds(5), milliseconds(15)}) + Link(Validator& validator, PeerSPtr peer, Latency const& latency = {milliseconds(5), milliseconds(15)}) : validator_(validator), peer_(peer), latency_(latency), up_(true) { auto sp = peer_.lock(); @@ -350,8 +344,7 @@ public: void addPeer(PeerSPtr peer) { - links_.emplace( - std::make_pair(peer->id(), std::make_shared(*this, peer))); + links_.emplace(std::make_pair(peer->id(), std::make_shared(*this, peer))); } void @@ -374,10 +367,7 @@ public: for_links(LinkIterCB f, bool simulateSlow = false) { std::vector v; - std::transform( - links_.begin(), links_.end(), std::back_inserter(v), [](auto& kv) { - return kv.second; - }); + std::transform(links_.begin(), links_.end(), std::back_inserter(v), [](auto& kv) { return kv.second; }); std::random_device d; std::mt19937 g(d()); std::shuffle(v.begin(), v.end(), g); @@ -442,8 +432,7 @@ class PeerSim : public PeerPartial, public std::enable_shared_from_this { public: using id_t = Peer::id_t; - PeerSim(Overlay& overlay, beast::Journal journal) - : overlay_(overlay), squelch_(journal) + PeerSim(Overlay& overlay, beast::Journal journal) : overlay_(overlay), squelch_(journal) { id_ = sid_++; } @@ -487,8 +476,7 @@ public: auto validator = squelch.validatorpubkey(); PublicKey key(Slice(validator.data(), validator.size())); if (squelch.squelch()) - squelch_.addSquelch( - key, std::chrono::seconds{squelch.squelchduration()}); + squelch_.addSquelch(key, std::chrono::seconds{squelch.squelchduration()}); else squelch_.removeSquelch(key); } @@ -508,8 +496,7 @@ class OverlaySim : public Overlay, public reduce_relay::SquelchHandler public: using id_t = Peer::id_t; using clock_type = ManualClock; - OverlaySim(Application& app) - : slots_(app.logs(), *this, app.config()), logs_(app.logs()) + OverlaySim(Application& app) : slots_(app.logs(), *this, app.config()), logs_(app.logs()) { } @@ -644,13 +631,7 @@ public: return *selected.begin(); } - std::unordered_map< - id_t, - std::tuple< - reduce_relay::PeerState, - std::uint16_t, - std::uint32_t, - std::uint32_t>> + std::unordered_map> getPeers(PublicKey const& validator) { return slots_.getPeers(validator); @@ -664,10 +645,7 @@ public: private: void - squelch( - PublicKey const& validator, - Peer::id_t id, - std::uint32_t squelchDuration) const override + squelch(PublicKey const& validator, Peer::id_t id, std::uint32_t squelchDuration) const override { if (auto it = peers_.find(id); it != peers_.end()) squelch_(validator, it->second, squelchDuration); @@ -762,10 +740,7 @@ public: void enableLink(std::uint16_t validatorId, Peer::id_t peer, bool enable) { - auto it = - std::find_if(validators_.begin(), validators_.end(), [&](auto& v) { - return v.id() == validatorId; - }); + auto it = std::find_if(validators_.begin(), validators_.end(), [&](auto& v) { return v.id() == validatorId; }); assert(it != validators_.end()); if (enable) it->linkUp(peer); @@ -787,17 +762,13 @@ public: PublicKey key = v; squelch.clear_validatorpubkey(); squelch.set_validatorpubkey(key.data(), key.size()); - v.for_links({peer}, [&](Link& l, MessageSPtr) { - std::dynamic_pointer_cast(l.getPeer())->send(squelch); - }); + v.for_links( + {peer}, [&](Link& l, MessageSPtr) { std::dynamic_pointer_cast(l.getPeer())->send(squelch); }); } } void - for_rand( - std::uint32_t min, - std::uint32_t max, - std::function f) + for_rand(std::uint32_t min, std::uint32_t max, std::function f) { auto size = max - min; std::vector s(size); @@ -829,9 +800,7 @@ public: for (int m = 0; m < nMessages; ++m) { ManualClock::randAdvance(milliseconds(1800), milliseconds(2200)); - for_rand(0, nValidators, [&](std::uint32_t v) { - validators_[v].for_links(link); - }); + for_rand(0, nValidators, [&](std::uint32_t v) { validators_[v].for_links(link); }); } } @@ -862,8 +831,7 @@ public: for (auto& [_, v] : peers) { (void)_; - if (std::get(v) == - reduce_relay::PeerState::Squelched) + if (std::get(v) == reduce_relay::PeerState::Squelched) return false; } } @@ -886,20 +854,15 @@ protected: { auto peers = network_.overlay().getPeers(network_.validator(validator)); std::cout << msg << " " - << "num peers " << (int)network_.overlay().getNumPeers() - << std::endl; + << "num peers " << (int)network_.overlay().getNumPeers() << std::endl; for (auto& [k, v] : peers) - std::cout << k << ":" << (int)std::get(v) - << " "; + std::cout << k << ":" << (int)std::get(v) << " "; std::cout << std::endl; } /** Send squelch (if duration is set) or unsquelch (if duration not set) */ Peer::id_t - sendSquelch( - PublicKey const& validator, - PeerWPtr const& peerPtr, - std::optional duration) + sendSquelch(PublicKey const& validator, PeerWPtr const& peerPtr, std::optional duration) { protocol::TMSquelch squelch; bool res = duration ? true : false; @@ -938,8 +901,7 @@ protected: void random(bool log) { - std::unordered_map events{ - {LinkDown, {}}, {PeerDisconnected, {}}}; + std::unordered_map events{{LinkDown, {}}, {PeerDisconnected, {}}}; time_point lastCheck = ManualClock::now(); network_.reset(); @@ -950,16 +912,12 @@ protected: bool squelched = false; std::stringstream str; - link.send( - m, - [&](PublicKey const& key, - PeerWPtr const& peerPtr, - std::uint32_t duration) { - assert(key == validator); - auto p = sendSquelch(key, peerPtr, duration); - squelched = true; - str << p << " "; - }); + link.send(m, [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) { + assert(key == validator); + auto p = sendSquelch(key, peerPtr, duration); + squelched = true; + str << p << " "; + }); if (squelched) { @@ -968,20 +926,13 @@ protected: for (auto s : selected) str << s << " "; if (log) - std::cout - << (double)reduce_relay::epoch(now) - .count() / - 1000. - << " random, squelched, validator: " << validator.id() - << " peers: " << str.str() << std::endl; - auto countingState = - network_.overlay().isCountingState(validator); + std::cout << (double)reduce_relay::epoch(now).count() / 1000. + << " random, squelched, validator: " << validator.id() << " peers: " << str.str() + << std::endl; + auto countingState = network_.overlay().isCountingState(validator); BEAST_EXPECT( countingState == false && - selected.size() == - env_.app() - .config() - .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); + selected.size() == env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); } // Trigger Link Down or Peer Disconnect event @@ -997,19 +948,14 @@ protected: events[event].time_ = now; if (event == EventType::LinkDown) { - network_.enableLink( - validator.id(), link.peerId(), false); - events[event].isSelected_ = - network_.overlay().isSelected( - validator, link.peerId()); + network_.enableLink(validator.id(), link.peerId(), false); + events[event].isSelected_ = network_.overlay().isSelected(validator, link.peerId()); } else - events[event].isSelected_ = - network_.isSelected(link.peerId()); + events[event].isSelected_ = network_.isSelected(link.peerId()); }; auto r = rand_int(0, 1000); - if (r == (int)EventType::LinkDown || - r == (int)EventType::PeerDisconnected) + if (r == (int)EventType::LinkDown || r == (int)EventType::PeerDisconnected) { update(static_cast(r)); } @@ -1019,22 +965,18 @@ protected: { auto& event = events[EventType::PeerDisconnected]; bool allCounting = network_.allCounting(event.peer_); - network_.overlay().deletePeer( - event.peer_, - [&](PublicKey const& v, PeerWPtr const& peerPtr) { - if (event.isSelected_) - sendSquelch(v, peerPtr, {}); - event.handled_ = true; - }); + network_.overlay().deletePeer(event.peer_, [&](PublicKey const& v, PeerWPtr const& peerPtr) { + if (event.isSelected_) + sendSquelch(v, peerPtr, {}); + event.handled_ = true; + }); // Should only be unsquelched if the peer is in Selected state // If in Selected state it's possible unsquelching didn't // take place because there is no peers in Squelched state in // any of the slots where the peer is in Selected state // (allCounting is true) - bool handled = - (event.isSelected_ == false && !event.handled_) || - (event.isSelected_ == true && - (event.handled_ || allCounting)); + bool handled = (event.isSelected_ == false && !event.handled_) || + (event.isSelected_ == true && (event.handled_ || allCounting)); BEAST_EXPECT(handled); event.state_ = State::Off; event.isSelected_ = false; @@ -1058,38 +1000,28 @@ protected: bool mustHandle = false; if (event.state_ == State::On && BEAST_EXPECT(event.key_)) { - event.isSelected_ = - network_.overlay().isSelected(*event.key_, event.peer_); + event.isSelected_ = network_.overlay().isSelected(*event.key_, event.peer_); auto peers = network_.overlay().getPeers(*event.key_); - auto d = reduce_relay::epoch(now).count() - - std::get<3>(peers[event.peer_]); - mustHandle = event.isSelected_ && - d > milliseconds(reduce_relay::IDLED).count() && - network_.overlay().inState( - *event.key_, reduce_relay::PeerState::Squelched) > - 0 && + auto d = reduce_relay::epoch(now).count() - std::get<3>(peers[event.peer_]); + mustHandle = event.isSelected_ && d > milliseconds(reduce_relay::IDLED).count() && + network_.overlay().inState(*event.key_, reduce_relay::PeerState::Squelched) > 0 && peers.find(event.peer_) != peers.end(); } - network_.overlay().deleteIdlePeers( - [&](PublicKey const& v, PeerWPtr const& ptr) { - event.handled_ = true; - if (mustHandle && v == event.key_) - { - event.state_ = State::WaitReset; - sendSquelch(validator, ptr, {}); - } - }); - bool handled = - (event.handled_ && event.state_ == State::WaitReset) || - (!event.handled_ && !mustHandle); + network_.overlay().deleteIdlePeers([&](PublicKey const& v, PeerWPtr const& ptr) { + event.handled_ = true; + if (mustHandle && v == event.key_) + { + event.state_ = State::WaitReset; + sendSquelch(validator, ptr, {}); + } + }); + bool handled = (event.handled_ && event.state_ == State::WaitReset) || (!event.handled_ && !mustHandle); BEAST_EXPECT(handled); } if (event.state_ == State::WaitReset || - (event.state_ == State::On && - (now - event.time_ > (reduce_relay::IDLED + seconds(2))))) + (event.state_ == State::On && (now - event.time_ > (reduce_relay::IDLED + seconds(2))))) { - bool handled = - event.state_ == State::WaitReset || !event.handled_; + bool handled = event.state_ == State::WaitReset || !event.handled_; BEAST_EXPECT(handled); event.state_ = State::Off; event.isSelected_ = false; @@ -1106,10 +1038,8 @@ protected: // All Peer Disconnect events must be handled BEAST_EXPECT(disconnected.cnt_ == disconnected.handledCnt_); if (log) - std::cout << "link down count: " << down.cnt_ << "/" - << down.handledCnt_ - << " peer disconnect count: " << disconnected.cnt_ << "/" - << disconnected.handledCnt_; + std::cout << "link down count: " << down.cnt_ << "/" << down.handledCnt_ + << " peer disconnect count: " << disconnected.cnt_ << "/" << disconnected.handledCnt_; } bool @@ -1135,9 +1065,7 @@ protected: void testInitialRound(bool log) { - doTest("Initial Round", log, [this](bool log) { - BEAST_EXPECT(propagateAndSquelch(log)); - }); + doTest("Initial Round", log, [this](bool log) { BEAST_EXPECT(propagateAndSquelch(log)); }); } /** Receiving message from squelched peer too soon should not change the @@ -1158,9 +1086,8 @@ protected: testPeerUnsquelched(bool log) { ManualClock::advance(seconds(601)); - doTest("Peer Unsquelched", log, [this](bool log) { - BEAST_EXPECT(propagateNoSquelch(log, 2, true, true, false)); - }); + doTest( + "Peer Unsquelched", log, [this](bool log) { BEAST_EXPECT(propagateNoSquelch(log, 2, true, true, false)); }); } /** Propagate enough messages to generate one squelch event */ @@ -1171,22 +1098,14 @@ protected: network_.propagate( [&](Link& link, MessageSPtr message) { std::uint16_t squelched = 0; - link.send( - message, - [&](PublicKey const& key, - PeerWPtr const& peerPtr, - std::uint32_t duration) { - squelched++; - sendSquelch(key, peerPtr, duration); - }); + link.send(message, [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) { + squelched++; + sendSquelch(key, peerPtr, duration); + }); if (squelched) { BEAST_EXPECT( - squelched == - MAX_PEERS - - env_.app() - .config() - .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); + squelched == MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); n++; } }, @@ -1195,9 +1114,7 @@ protected: purge, resetClock); auto selected = network_.overlay().getSelected(network_.validator(0)); - BEAST_EXPECT( - selected.size() == - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); + BEAST_EXPECT(selected.size() == env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); BEAST_EXPECT(n == 1); // only one selection round auto res = checkCounting(network_.validator(0), false); BEAST_EXPECT(res); @@ -1206,24 +1123,15 @@ protected: /** Send fewer message so that squelch event is not generated */ bool - propagateNoSquelch( - bool log, - std::uint16_t nMessages, - bool countingState, - bool purge = true, - bool resetClock = true) + propagateNoSquelch(bool log, std::uint16_t nMessages, bool countingState, bool purge = true, bool resetClock = true) { bool squelched = false; network_.propagate( [&](Link& link, MessageSPtr message) { - link.send( - message, - [&](PublicKey const& key, - PeerWPtr const& peerPtr, - std::uint32_t duration) { - squelched = true; - BEAST_EXPECT(false); - }); + link.send(message, [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) { + squelched = true; + BEAST_EXPECT(false); + }); }, 1, nMessages, @@ -1256,16 +1164,8 @@ protected: BEAST_EXPECT(propagateAndSquelch(log, true, false)); auto id = network_.overlay().getSelectedPeer(network_.validator(0)); std::uint16_t unsquelched = 0; - network_.overlay().deletePeer( - id, [&](PublicKey const& key, PeerWPtr const& peer) { - unsquelched++; - }); - BEAST_EXPECT( - unsquelched == - MAX_PEERS - - env_.app() - .config() - .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); + network_.overlay().deletePeer(id, [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; }); + BEAST_EXPECT(unsquelched == MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); BEAST_EXPECT(checkCounting(network_.validator(0), true)); }); } @@ -1280,17 +1180,9 @@ protected: BEAST_EXPECT(propagateAndSquelch(log, true, false)); ManualClock::advance(reduce_relay::IDLED + seconds(1)); std::uint16_t unsquelched = 0; - network_.overlay().deleteIdlePeers( - [&](PublicKey const& key, PeerWPtr const& peer) { - unsquelched++; - }); + network_.overlay().deleteIdlePeers([&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; }); auto peers = network_.overlay().getPeers(network_.validator(0)); - BEAST_EXPECT( - unsquelched == - MAX_PEERS - - env_.app() - .config() - .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); + BEAST_EXPECT(unsquelched == MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS); BEAST_EXPECT(checkCounting(network_.validator(0), true)); }); } @@ -1305,15 +1197,12 @@ protected: BEAST_EXPECT(propagateAndSquelch(log, true, false)); auto peers = network_.overlay().getPeers(network_.validator(0)); auto it = std::find_if(peers.begin(), peers.end(), [&](auto it) { - return std::get(it.second) == - reduce_relay::PeerState::Squelched; + return std::get(it.second) == reduce_relay::PeerState::Squelched; }); assert(it != peers.end()); std::uint16_t unsquelched = 0; network_.overlay().deletePeer( - it->first, [&](PublicKey const& key, PeerWPtr const& peer) { - unsquelched++; - }); + it->first, [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; }); BEAST_EXPECT(unsquelched == 0); BEAST_EXPECT(checkCounting(network_.validator(0), false)); }); @@ -1458,12 +1347,9 @@ vp_base_squelch_max_selected_peers=2 { doTest("BaseSquelchReady", log, [&](bool log) { ManualClock::reset(); - auto createSlots = [&](bool baseSquelchEnabled) - -> reduce_relay::Slots { - env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = - baseSquelchEnabled; - return reduce_relay::Slots( - env_.app().logs(), network_.overlay(), env_.app().config()); + auto createSlots = [&](bool baseSquelchEnabled) -> reduce_relay::Slots { + env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = baseSquelchEnabled; + return reduce_relay::Slots(env_.app().logs(), network_.overlay(), env_.app().config()); }; // base squelching must not be ready if squelching is disabled BEAST_EXPECT(!createSlots(false).baseSquelchReady()); @@ -1494,10 +1380,7 @@ vp_base_squelch_max_selected_peers=2 { uint256 key(i); network_.overlay().updateSlotAndSquelch( - key, - network_.validator(0), - 0, - [&](PublicKey const&, PeerWPtr, std::uint32_t) {}); + key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {}); } auto peers = network_.overlay().getPeers(network_.validator(0)); // first message changes Slot state to Counting and is not counted, @@ -1506,20 +1389,14 @@ vp_base_squelch_max_selected_peers=2 // add duplicate uint256 key(nMessages - 1); network_.overlay().updateSlotAndSquelch( - key, - network_.validator(0), - 0, - [&](PublicKey const&, PeerWPtr, std::uint32_t) {}); + key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {}); // confirm the same number of messages peers = network_.overlay().getPeers(network_.validator(0)); BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1)); // advance the clock ManualClock::advance(reduce_relay::IDLED + seconds(1)); network_.overlay().updateSlotAndSquelch( - key, - network_.validator(0), - 0, - [&](PublicKey const&, PeerWPtr, std::uint32_t) {}); + key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {}); peers = network_.overlay().getPeers(network_.validator(0)); // confirm message number increased BEAST_EXPECT(std::get<1>(peers[0]) == nMessages); @@ -1532,8 +1409,7 @@ vp_base_squelch_max_selected_peers=2 { } void - squelch(PublicKey const&, Peer::id_t, std::uint32_t duration) - const override + squelch(PublicKey const&, Peer::id_t, std::uint32_t duration) const override { if (duration > maxDuration_) maxDuration_ = duration; @@ -1554,14 +1430,12 @@ vp_base_squelch_max_selected_peers=2 auto run = [&](int npeers) { handler.maxDuration_ = 0; - reduce_relay::Slots slots( - env_.app().logs(), handler, env_.app().config()); + reduce_relay::Slots slots(env_.app().logs(), handler, env_.app().config()); // 1st message from a new peer switches the slot // to counting state and resets the counts of all peers + // MAX_MESSAGE_THRESHOLD + 1 messages to reach the threshold // and switch the slot's state to peer selection. - for (int m = 1; m <= reduce_relay::MAX_MESSAGE_THRESHOLD + 2; - m++) + for (int m = 1; m <= reduce_relay::MAX_MESSAGE_THRESHOLD + 2; m++) { for (int peer = 0; peer < npeers; peer++) { @@ -1569,11 +1443,7 @@ vp_base_squelch_max_selected_peers=2 // slot's internal hash router accept the message std::uint64_t mid = m * 1000 + peer; uint256 const message{mid}; - slots.updateSlotAndSquelch( - message, - validator, - peer, - protocol::MessageType::mtVALIDATION); + slots.updateSlotAndSquelch(message, validator, peer, protocol::MessageType::mtVALIDATION); } } // make Slot's internal hash router expire all messages @@ -1603,24 +1473,14 @@ vp_base_squelch_max_selected_peers=2 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count()); using namespace beast::unit_test::detail; if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count()) - log << make_reason( - "warning: squelch duration is low", - __FILE__, - __LINE__) - << std::endl - << std::flush; + log << make_reason("warning: squelch duration is low", __FILE__, __LINE__) << std::endl << std::flush; // more than 400 is still less than MAX_UNSQUELCH_EXPIRE_PEERS run(400); BEAST_EXPECT( handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() && handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count()); if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count()) - log << make_reason( - "warning: squelch duration is low", - __FILE__, - __LINE__) - << std::endl - << std::flush; + log << make_reason("warning: squelch duration is low", __FILE__, __LINE__) << std::endl << std::flush; }); } @@ -1636,14 +1496,12 @@ vp_base_squelch_max_selected_peers=2 << "[compression]\n" << "1\n"; c.loadFromString(str.str()); - env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = - c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE; + env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE; env_.app().config().COMPRESSION = c.COMPRESSION; }; auto handshake = [&](int outboundEnable, int inboundEnable) { - beast::IP::Address addr = - boost::asio::ip::make_address("172.1.1.100"); + beast::IP::Address addr = boost::asio::ip::make_address("172.1.1.100"); setEnv(outboundEnable); auto request = xrpl::makeRequest( @@ -1660,24 +1518,14 @@ vp_base_squelch_max_selected_peers=2 auto const peerEnabled = inboundEnable && outboundEnable; // inbound is enabled if the request's header has the feature // enabled and the peer's configuration is enabled - auto const inboundEnabled = peerFeatureEnabled( - http_request, FEATURE_VPRR, inboundEnable); + auto const inboundEnabled = peerFeatureEnabled(http_request, FEATURE_VPRR, inboundEnable); BEAST_EXPECT(!(peerEnabled ^ inboundEnabled)); setEnv(inboundEnable); - auto http_resp = xrpl::makeResponse( - true, - http_request, - addr, - addr, - uint256{1}, - 1, - {1, 0}, - env_.app()); + auto http_resp = xrpl::makeResponse(true, http_request, addr, addr, uint256{1}, 1, {1, 0}, env_.app()); // outbound is enabled if the response's header has the feature // enabled and the peer's configuration is enabled - auto const outboundEnabled = - peerFeatureEnabled(http_resp, FEATURE_VPRR, outboundEnable); + auto const outboundEnabled = peerFeatureEnabled(http_resp, FEATURE_VPRR, outboundEnable); BEAST_EXPECT(!(peerEnabled ^ outboundEnabled)); }; handshake(1, 1); diff --git a/src/test/overlay/short_read_test.cpp b/src/test/overlay/short_read_test.cpp index 2db35dd93e..498ecb6a27 100644 --- a/src/test/overlay/short_read_test.cpp +++ b/src/test/overlay/short_read_test.cpp @@ -36,8 +36,7 @@ class short_read_test : public beast::unit_test::suite private: using io_context_type = boost::asio::io_context; using strand_type = boost::asio::strand; - using timer_type = - boost::asio::basic_waitable_timer; + using timer_type = boost::asio::basic_waitable_timer; using acceptor_type = boost::asio::ip::tcp::acceptor; using socket_type = boost::asio::ip::tcp::socket; using stream_type = boost::asio::ssl::stream; @@ -46,9 +45,7 @@ private: using address_type = boost::asio::ip::address; io_context_type io_context_; - boost::optional> - work_; + boost::optional> work_; std::thread thread_; std::shared_ptr context_; @@ -171,10 +168,7 @@ private: , test_(server_.test_) , acceptor_( test_.io_context_, - endpoint_type( - boost::asio::ip::make_address( - test::getEnvLocalhostAddr()), - 0)) + endpoint_type(boost::asio::ip::make_address(test::getEnvLocalhostAddr()), 0)) , socket_(test_.io_context_) , strand_(boost::asio::make_strand(test_.io_context_)) { @@ -186,9 +180,7 @@ private: close() override { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind(&Acceptor::close, shared_from_this())); + return post(strand_, std::bind(&Acceptor::close, shared_from_this())); acceptor_.close(); } @@ -197,12 +189,7 @@ private: { acceptor_.async_accept( socket_, - bind_executor( - strand_, - std::bind( - &Acceptor::on_accept, - shared_from_this(), - std::placeholders::_1))); + bind_executor(strand_, std::bind(&Acceptor::on_accept, shared_from_this(), std::placeholders::_1))); } void @@ -221,18 +208,12 @@ private: { if (ec) return fail("accept", ec); - auto const p = - std::make_shared(server_, std::move(socket_)); + auto const p = std::make_shared(server_, std::move(socket_)); server_.add(p); p->run(); acceptor_.async_accept( socket_, - bind_executor( - strand_, - std::bind( - &Acceptor::on_accept, - shared_from_this(), - std::placeholders::_1))); + bind_executor(strand_, std::bind(&Acceptor::on_accept, shared_from_this(), std::placeholders::_1))); } }; @@ -261,9 +242,7 @@ private: close() override { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind(&Connection::close, shared_from_this())); + return post(strand_, std::bind(&Connection::close, shared_from_this())); if (socket_.is_open()) { socket_.close(); @@ -276,19 +255,11 @@ private: { timer_.expires_after(std::chrono::seconds(3)); timer_.async_wait(bind_executor( - strand_, - std::bind( - &Connection::on_timer, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_timer, shared_from_this(), std::placeholders::_1))); stream_.async_handshake( stream_type::server, bind_executor( - strand_, - std::bind( - &Connection::on_handshake, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_handshake, shared_from_this(), std::placeholders::_1))); } void @@ -297,8 +268,7 @@ private: if (socket_.is_open()) { if (ec != boost::asio::error::operation_aborted) - test_.log << "[server] " << what << ": " << ec.message() - << std::endl; + test_.log << "[server] " << what << ": " << ec.message() << std::endl; socket_.close(); timer_.cancel(); } @@ -328,10 +298,7 @@ private: bind_executor( strand_, std::bind( - &Connection::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + &Connection::on_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2))); #else close(); #endif @@ -344,11 +311,7 @@ private: { server_.test_.log << "[server] read: EOF" << std::endl; return stream_.async_shutdown(bind_executor( - strand_, - std::bind( - &Connection::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_shutdown, shared_from_this(), std::placeholders::_1))); } if (ec) return fail("read", ec); @@ -362,10 +325,7 @@ private: bind_executor( strand_, std::bind( - &Connection::on_write, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + &Connection::on_write, shared_from_this(), std::placeholders::_1, std::placeholders::_2))); } void @@ -375,11 +335,7 @@ private: if (ec) return fail("write", ec); stream_.async_shutdown(bind_executor( - strand_, - std::bind( - &Connection::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_shutdown, shared_from_this(), std::placeholders::_1))); } void @@ -447,9 +403,7 @@ private: close() override { if (!strand_.running_in_this_thread()) - return post( - strand_, - std::bind(&Connection::close, shared_from_this())); + return post(strand_, std::bind(&Connection::close, shared_from_this())); if (socket_.is_open()) { socket_.close(); @@ -462,19 +416,11 @@ private: { timer_.expires_after(std::chrono::seconds(3)); timer_.async_wait(bind_executor( - strand_, - std::bind( - &Connection::on_timer, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_timer, shared_from_this(), std::placeholders::_1))); socket_.async_connect( ep, bind_executor( - strand_, - std::bind( - &Connection::on_connect, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_connect, shared_from_this(), std::placeholders::_1))); } void @@ -483,8 +429,7 @@ private: if (socket_.is_open()) { if (ec != boost::asio::error::operation_aborted) - test_.log << "[client] " << what << ": " << ec.message() - << std::endl; + test_.log << "[client] " << what << ": " << ec.message() << std::endl; socket_.close(); timer_.cancel(); } @@ -509,11 +454,7 @@ private: stream_.async_handshake( stream_type::client, bind_executor( - strand_, - std::bind( - &Connection::on_handshake, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_handshake, shared_from_this(), std::placeholders::_1))); } void @@ -530,17 +471,10 @@ private: bind_executor( strand_, std::bind( - &Connection::on_write, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + &Connection::on_write, shared_from_this(), std::placeholders::_1, std::placeholders::_2))); #else stream_.async_shutdown(bind_executor( - strand_, - std::bind( - &Connection::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_shutdown, shared_from_this(), std::placeholders::_1))); #endif } @@ -558,17 +492,10 @@ private: bind_executor( strand_, std::bind( - &Connection::on_read, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + &Connection::on_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2))); #else stream_.async_shutdown(bind_executor( - strand_, - std::bind( - &Connection::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_shutdown, shared_from_this(), std::placeholders::_1))); #endif } @@ -579,11 +506,7 @@ private: return fail("read", ec); buf_.commit(bytes_transferred); stream_.async_shutdown(bind_executor( - strand_, - std::bind( - &Connection::on_shutdown, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&Connection::on_shutdown, shared_from_this(), std::placeholders::_1))); } void diff --git a/src/test/overlay/traffic_count_test.cpp b/src/test/overlay/traffic_count_test.cpp index a8948879d9..6516fe3843 100644 --- a/src/test/overlay/traffic_count_test.cpp +++ b/src/test/overlay/traffic_count_test.cpp @@ -21,13 +21,11 @@ public: message.set_type(protocol::TMPing::ptPING); // a known message is categorized to a proper category - auto const known = - TrafficCount::categorize(message, protocol::mtPING, false); + auto const known = TrafficCount::categorize(message, protocol::mtPING, false); BEAST_EXPECT(known == TrafficCount::category::base); // an unknown message type is categorized as unknown - auto const unknown = TrafficCount::categorize( - message, static_cast(99), false); + auto const unknown = TrafficCount::categorize(message, static_cast(99), false); BEAST_EXPECT(unknown == TrafficCount::category::unknown); } @@ -57,18 +55,12 @@ public: }); auto const counts_new = m_traffic.getCounts(); - std::for_each( - counts_new.begin(), counts_new.end(), [&](auto const& pair) { - BEAST_EXPECT( - pair.second.bytesIn.load() == tc.expectedBytesIn); - BEAST_EXPECT( - pair.second.bytesOut.load() == tc.expectedBytesOut); - BEAST_EXPECT( - pair.second.messagesIn.load() == tc.expectedMessagesIn); - BEAST_EXPECT( - pair.second.messagesOut.load() == - tc.expectedMessagesOut); - }); + std::for_each(counts_new.begin(), counts_new.end(), [&](auto const& pair) { + BEAST_EXPECT(pair.second.bytesIn.load() == tc.expectedBytesIn); + BEAST_EXPECT(pair.second.bytesOut.load() == tc.expectedBytesOut); + BEAST_EXPECT(pair.second.messagesIn.load() == tc.expectedMessagesIn); + BEAST_EXPECT(pair.second.messagesOut.load() == tc.expectedMessagesOut); + }); }; auto const testcases = { @@ -114,13 +106,10 @@ public: testcase("category-to-string"); // known category returns known string value - BEAST_EXPECT( - TrafficCount::to_string(TrafficCount::category::total) == "total"); + BEAST_EXPECT(TrafficCount::to_string(TrafficCount::category::total) == "total"); // return "unknown" for unknown categories - BEAST_EXPECT( - TrafficCount::to_string( - static_cast(1000)) == "unknown"); + BEAST_EXPECT(TrafficCount::to_string(static_cast(1000)) == "unknown"); } void diff --git a/src/test/overlay/tx_reduce_relay_test.cpp b/src/test/overlay/tx_reduce_relay_test.cpp index 7286b3fd90..b8e3300c03 100644 --- a/src/test/overlay/tx_reduce_relay_test.cpp +++ b/src/test/overlay/tx_reduce_relay_test.cpp @@ -32,11 +32,7 @@ private: testConfig(bool log) { doTest("Config Test", log, [&](bool log) { - auto test = [&](bool enable, - bool metrics, - std::uint16_t min, - std::uint16_t pct, - bool success = true) { + auto test = [&](bool enable, bool metrics, std::uint16_t min, std::uint16_t pct, bool success = true) { std::stringstream str("[reduce_relay]"); str << "[reduce_relay]\n" << "tx_enable=" << static_cast(enable) << "\n" @@ -135,47 +131,28 @@ private: boost::beast::multi_buffer read_buf_; public: - tx_reduce_relay_test() - : context_(make_SSLContext("")), protocolVersion_{1, 7} + tx_reduce_relay_test() : context_(make_SSLContext("")), protocolVersion_{1, 7} { } private: void - addPeer( - jtx::Env& env, - std::vector>& peers, - std::uint16_t& nDisabled) + addPeer(jtx::Env& env, std::vector>& peers, std::uint16_t& nDisabled) { auto& overlay = dynamic_cast(env.app().overlay()); boost::beast::http::request request; - (nDisabled == 0) - ? (void)request.insert( - "X-Protocol-Ctl", - makeFeaturesRequestHeader(false, false, true, false)) - : (void)nDisabled--; + (nDisabled == 0) ? (void)request.insert("X-Protocol-Ctl", makeFeaturesRequestHeader(false, false, true, false)) + : (void)nDisabled--; auto stream_ptr = std::make_unique( - socket_type(std::forward( - env.app().getIOContext())), - *context_); - beast::IP::Endpoint local( - boost::asio::ip::make_address("172.1.1." + std::to_string(lid_))); - beast::IP::Endpoint remote( - boost::asio::ip::make_address("172.1.1." + std::to_string(rid_))); + socket_type(std::forward(env.app().getIOContext())), *context_); + beast::IP::Endpoint local(boost::asio::ip::make_address("172.1.1." + std::to_string(lid_))); + beast::IP::Endpoint remote(boost::asio::ip::make_address("172.1.1." + std::to_string(rid_))); PublicKey key(std::get<0>(randomKeyPair(KeyType::ed25519))); auto consumer = overlay.resourceManager().newInboundEndpoint(remote); auto [slot, _] = overlay.peerFinder().new_inbound_slot(local, remote); auto const peer = std::make_shared( - env.app(), - slot, - std::move(request), - key, - protocolVersion_, - consumer, - std::move(stream_ptr), - overlay); - BEAST_EXPECT( - overlay.findPeerByPublicKey(key) == std::shared_ptr{}); + env.app(), slot, std::move(request), key, protocolVersion_, consumer, std::move(stream_ptr), overlay); + BEAST_EXPECT(overlay.findPeerByPublicKey(key) == std::shared_ptr{}); overlay.add_active(peer); BEAST_EXPECT(overlay.findPeerByPublicKey(key) == peer); peers.emplace_back(peer); // overlay stores week ptr to PeerImp @@ -218,9 +195,7 @@ private: m.set_deferred(false); m.set_status(protocol::TransactionStatus::tsNEW); env.app().overlay().relay(uint256{0}, m, toSkip); - BEAST_EXPECT( - PeerTest::sendTx_ == expectRelay && - PeerTest::queueTx_ == expectQueue); + BEAST_EXPECT(PeerTest::sendTx_ == expectRelay && PeerTest::queueTx_ == expectQueue); } } diff --git a/src/test/peerfinder/Livecache_test.cpp b/src/test/peerfinder/Livecache_test.cpp index b9487d8ce7..2c2ac01111 100644 --- a/src/test/peerfinder/Livecache_test.cpp +++ b/src/test/peerfinder/Livecache_test.cpp @@ -142,57 +142,32 @@ public: testcase("Shuffle"); Livecache<> c(clock_, journal_); for (auto i = 0; i < 100; ++i) - add(beast::IP::randomEP(true), - c, - xrpl::rand_int(Tuning::maxHops + 1)); + add(beast::IP::randomEP(true), c, xrpl::rand_int(Tuning::maxHops + 1)); using at_hop = std::vector; using all_hops = std::array; auto cmp_EP = [](Endpoint const& a, Endpoint const& b) { - return ( - b.hops < a.hops || (b.hops == a.hops && b.address < a.address)); + return (b.hops < a.hops || (b.hops == a.hops && b.address < a.address)); }; all_hops before; all_hops before_sorted; - for (auto i = std::make_pair(0, c.hops.begin()); - i.second != c.hops.end(); - ++i.first, ++i.second) + for (auto i = std::make_pair(0, c.hops.begin()); i.second != c.hops.end(); ++i.first, ++i.second) { - std::copy( - (*i.second).begin(), - (*i.second).end(), - std::back_inserter(before[i.first])); - std::copy( - (*i.second).begin(), - (*i.second).end(), - std::back_inserter(before_sorted[i.first])); - std::sort( - before_sorted[i.first].begin(), - before_sorted[i.first].end(), - cmp_EP); + std::copy((*i.second).begin(), (*i.second).end(), std::back_inserter(before[i.first])); + std::copy((*i.second).begin(), (*i.second).end(), std::back_inserter(before_sorted[i.first])); + std::sort(before_sorted[i.first].begin(), before_sorted[i.first].end(), cmp_EP); } c.hops.shuffle(); all_hops after; all_hops after_sorted; - for (auto i = std::make_pair(0, c.hops.begin()); - i.second != c.hops.end(); - ++i.first, ++i.second) + for (auto i = std::make_pair(0, c.hops.begin()); i.second != c.hops.end(); ++i.first, ++i.second) { - std::copy( - (*i.second).begin(), - (*i.second).end(), - std::back_inserter(after[i.first])); - std::copy( - (*i.second).begin(), - (*i.second).end(), - std::back_inserter(after_sorted[i.first])); - std::sort( - after_sorted[i.first].begin(), - after_sorted[i.first].end(), - cmp_EP); + std::copy((*i.second).begin(), (*i.second).end(), std::back_inserter(after[i.first])); + std::copy((*i.second).begin(), (*i.second).end(), std::back_inserter(after_sorted[i.first])); + std::sort(after_sorted[i.first].begin(), after_sorted[i.first].end(), cmp_EP); } // each hop bucket should contain the same items diff --git a/src/test/peerfinder/PeerFinder_test.cpp b/src/test/peerfinder/PeerFinder_test.cpp index 7ff1b9de01..49ddc52c9d 100644 --- a/src/test/peerfinder/PeerFinder_test.cpp +++ b/src/test/peerfinder/PeerFinder_test.cpp @@ -65,8 +65,7 @@ public: TestChecker checker; TestStopwatch clock; Logic logic(clock, store, checker, journal_); - logic.addFixedPeer( - "test", beast::IP::Endpoint::from_string("65.0.0.1:5")); + logic.addFixedPeer("test", beast::IP::Endpoint::from_string("65.0.0.1:5")); { Config c; c.autoConnect = false; @@ -81,8 +80,7 @@ public: { BEAST_EXPECT(list.size() == 1); auto const [slot, _] = logic.new_outbound_slot(list.front()); - BEAST_EXPECT(logic.onConnected( - slot, beast::IP::Endpoint::from_string("65.0.0.2:5"))); + BEAST_EXPECT(logic.onConnected(slot, beast::IP::Endpoint::from_string("65.0.0.2:5"))); logic.on_closed(slot); ++n; } @@ -103,8 +101,7 @@ public: TestChecker checker; TestStopwatch clock; Logic logic(clock, store, checker, journal_); - logic.addFixedPeer( - "test", beast::IP::Endpoint::from_string("65.0.0.1:5")); + logic.addFixedPeer("test", beast::IP::Endpoint::from_string("65.0.0.1:5")); { Config c; c.autoConnect = false; @@ -122,13 +119,10 @@ public: { BEAST_EXPECT(list.size() == 1); auto const [slot, _] = logic.new_outbound_slot(list.front()); - if (!BEAST_EXPECT(logic.onConnected( - slot, beast::IP::Endpoint::from_string("65.0.0.2:5")))) + if (!BEAST_EXPECT(logic.onConnected(slot, beast::IP::Endpoint::from_string("65.0.0.2:5")))) return; std::string s = "."; - if (!BEAST_EXPECT( - logic.activate(slot, pk, false) == - PeerFinder::Result::success)) + if (!BEAST_EXPECT(logic.activate(slot, pk, false) == PeerFinder::Result::success)) return; logic.on_closed(slot); ++n; @@ -224,18 +218,15 @@ public: } auto const local = beast::IP::Endpoint::from_string("65.0.0.2:1024"); - auto const [slot, r] = logic.new_inbound_slot( - local, beast::IP::Endpoint::from_string("55.104.0.2:1025")); + auto const [slot, r] = logic.new_inbound_slot(local, beast::IP::Endpoint::from_string("55.104.0.2:1025")); BEAST_EXPECT(slot != nullptr); BEAST_EXPECT(r == Result::success); - auto const [slot1, r1] = logic.new_inbound_slot( - local, beast::IP::Endpoint::from_string("55.104.0.2:1026")); + auto const [slot1, r1] = logic.new_inbound_slot(local, beast::IP::Endpoint::from_string("55.104.0.2:1026")); BEAST_EXPECT(slot1 != nullptr); BEAST_EXPECT(r1 == Result::success); - auto const [slot2, r2] = logic.new_inbound_slot( - local, beast::IP::Endpoint::from_string("55.104.0.2:1027")); + auto const [slot2, r2] = logic.new_inbound_slot(local, beast::IP::Endpoint::from_string("55.104.0.2:1027")); BEAST_EXPECT(r2 == Result::ipLimitExceeded); if (!BEAST_EXPECT(slot2 == nullptr)) @@ -264,13 +255,11 @@ public: PublicKey const pk1(randomKeyPair(KeyType::secp256k1).first); - auto const [slot, rSlot] = logic.new_outbound_slot( - beast::IP::Endpoint::from_string("55.104.0.2:1025")); + auto const [slot, rSlot] = logic.new_outbound_slot(beast::IP::Endpoint::from_string("55.104.0.2:1025")); BEAST_EXPECT(slot != nullptr); BEAST_EXPECT(rSlot == Result::success); - auto const [slot2, r2Slot] = logic.new_outbound_slot( - beast::IP::Endpoint::from_string("55.104.0.2:1026")); + auto const [slot2, r2Slot] = logic.new_outbound_slot(beast::IP::Endpoint::from_string("55.104.0.2:1026")); BEAST_EXPECT(slot2 != nullptr); BEAST_EXPECT(r2Slot == Result::success); @@ -280,8 +269,7 @@ public: BEAST_EXPECT(logic.activate(slot, pk1, false) == Result::success); // activating a different slot with the same node ID (pk) must fail - BEAST_EXPECT( - logic.activate(slot2, pk1, false) == Result::duplicatePeer); + BEAST_EXPECT(logic.activate(slot2, pk1, false) == Result::duplicatePeer); logic.on_closed(slot); @@ -309,13 +297,11 @@ public: PublicKey const pk1(randomKeyPair(KeyType::secp256k1).first); auto const local = beast::IP::Endpoint::from_string("65.0.0.2:1024"); - auto const [slot, rSlot] = logic.new_inbound_slot( - local, beast::IP::Endpoint::from_string("55.104.0.2:1025")); + auto const [slot, rSlot] = logic.new_inbound_slot(local, beast::IP::Endpoint::from_string("55.104.0.2:1025")); BEAST_EXPECT(slot != nullptr); BEAST_EXPECT(rSlot == Result::success); - BEAST_EXPECT( - logic.activate(slot, pk1, false) == Result::inboundDisabled); + BEAST_EXPECT(logic.activate(slot, pk1, false) == Result::inboundDisabled); { Config c; @@ -329,8 +315,7 @@ public: BEAST_EXPECT(logic.activate(slot, pk1, false) == Result::success); // creating a new inbound slot must succeed as IP Limit is not exceeded - auto const [slot2, r2Slot] = logic.new_inbound_slot( - local, beast::IP::Endpoint::from_string("55.104.0.2:1026")); + auto const [slot2, r2Slot] = logic.new_inbound_slot(local, beast::IP::Endpoint::from_string("55.104.0.2:1026")); BEAST_EXPECT(slot2 != nullptr); BEAST_EXPECT(r2Slot == Result::success); @@ -353,8 +338,7 @@ public: Logic logic(clock, store, checker, journal_); try { - logic.addFixedPeer( - "test", beast::IP::Endpoint::from_string("65.0.0.2")); + logic.addFixedPeer("test", beast::IP::Endpoint::from_string("65.0.0.2")); fail("invalid endpoint successfully added"); } catch (std::runtime_error const& e) @@ -404,21 +388,19 @@ public: if (maxPeers) { max = maxPeers.value(); - toLoad += "[peers_max]\n" + std::to_string(max) + "\n" + - "[peers_in_max]\n" + std::to_string(maxIn.value_or(0)) + - "\n" + "[peers_out_max]\n" + + toLoad += "[peers_max]\n" + std::to_string(max) + "\n" + "[peers_in_max]\n" + + std::to_string(maxIn.value_or(0)) + "\n" + "[peers_out_max]\n" + std::to_string(maxOut.value_or(0)) + "\n"; } else if (maxIn && maxOut) { - toLoad += "[peers_in_max]\n" + std::to_string(*maxIn) + "\n" + - "[peers_out_max]\n" + std::to_string(*maxOut) + "\n"; + toLoad += "[peers_in_max]\n" + std::to_string(*maxIn) + "\n" + "[peers_out_max]\n" + + std::to_string(*maxOut) + "\n"; } c.loadFromString(toLoad); BEAST_EXPECT( - (c.PEERS_MAX == max && c.PEERS_IN_MAX == 0 && - c.PEERS_OUT_MAX == 0) || + (c.PEERS_MAX == max && c.PEERS_IN_MAX == 0 && c.PEERS_OUT_MAX == 0) || (c.PEERS_IN_MAX == *maxIn && c.PEERS_OUT_MAX == *maxOut)); Config config = Config::makeConfig(c, port, false, 0); @@ -426,8 +408,7 @@ public: Counts counts; counts.onConfig(config); BEAST_EXPECT( - counts.out_max() == expectOut && counts.in_max() == expectIn && - config.ipLimit == expectIpLimit); + counts.out_max() == expectOut && counts.in_max() == expectIn && config.ipLimit == expectIpLimit); TestStore store; TestChecker checker; diff --git a/src/test/protocol/ApiVersion_test.cpp b/src/test/protocol/ApiVersion_test.cpp index 1dc8ef93f7..0b7babc764 100644 --- a/src/test/protocol/ApiVersion_test.cpp +++ b/src/test/protocol/ApiVersion_test.cpp @@ -19,13 +19,9 @@ struct ApiVersion_test : beast::unit_test::suite { testcase("API versions invariants"); - static_assert( - RPC::apiMinimumSupportedVersion <= - RPC::apiMaximumSupportedVersion); - static_assert( - RPC::apiMinimumSupportedVersion <= RPC::apiMaximumValidVersion); - static_assert( - RPC::apiMaximumSupportedVersion <= RPC::apiMaximumValidVersion); + static_assert(RPC::apiMinimumSupportedVersion <= RPC::apiMaximumSupportedVersion); + static_assert(RPC::apiMinimumSupportedVersion <= RPC::apiMaximumValidVersion); + static_assert(RPC::apiMaximumSupportedVersion <= RPC::apiMaximumValidVersion); static_assert(RPC::apiBetaVersion <= RPC::apiMaximumValidVersion); BEAST_EXPECT(true); diff --git a/src/test/protocol/BuildInfo_test.cpp b/src/test/protocol/BuildInfo_test.cpp index ae06511e85..d9810e93ea 100644 --- a/src/test/protocol/BuildInfo_test.cpp +++ b/src/test/protocol/BuildInfo_test.cpp @@ -14,29 +14,22 @@ public: auto encodedVersion = BuildInfo::encodeSoftwareVersion("1.2.3-b7"); // the first two bytes identify the particular implementation, 0x183B - BEAST_EXPECT( - (encodedVersion & 0xFFFF'0000'0000'0000LLU) == - 0x183B'0000'0000'0000LLU); + BEAST_EXPECT((encodedVersion & 0xFFFF'0000'0000'0000LLU) == 0x183B'0000'0000'0000LLU); // the next three bytes: major version, minor version, patch version, // 0x010203 - BEAST_EXPECT( - (encodedVersion & 0x0000'FFFF'FF00'0000LLU) == - 0x0000'0102'0300'0000LLU); + BEAST_EXPECT((encodedVersion & 0x0000'FFFF'FF00'0000LLU) == 0x0000'0102'0300'0000LLU); // the next two bits: { // 01 if a beta - BEAST_EXPECT( - (encodedVersion & 0x0000'0000'00C0'0000LLU) >> 22 == 0b01); + BEAST_EXPECT((encodedVersion & 0x0000'0000'00C0'0000LLU) >> 22 == 0b01); // 10 if an RC encodedVersion = BuildInfo::encodeSoftwareVersion("1.2.4-rc7"); - BEAST_EXPECT( - (encodedVersion & 0x0000'0000'00C0'0000LLU) >> 22 == 0b10); + BEAST_EXPECT((encodedVersion & 0x0000'0000'00C0'0000LLU) >> 22 == 0b10); // 11 if neither an RC nor a beta encodedVersion = BuildInfo::encodeSoftwareVersion("1.2.5"); - BEAST_EXPECT( - (encodedVersion & 0x0000'0000'00C0'0000LLU) >> 22 == 0b11); + BEAST_EXPECT((encodedVersion & 0x0000'0000'00C0'0000LLU) >> 22 == 0b11); } // the next six bits: rc/beta number (1-63) diff --git a/src/test/protocol/Hooks_test.cpp b/src/test/protocol/Hooks_test.cpp index 27f455f202..f4b33f7e4d 100644 --- a/src/test/protocol/Hooks_test.cpp +++ b/src/test/protocol/Hooks_test.cpp @@ -134,8 +134,7 @@ class Hooks_test : public beast::unit_test::suite } case STI_ACCOUNT: { - AccountID id = *parseBase58( - "rwfSjJNK2YQuN64bSWn7T2eY9FJAyAPYJT"); + AccountID id = *parseBase58("rwfSjJNK2YQuN64bSWn7T2eY9FJAyAPYJT"); dummy.setAccountID(f, id); BEAST_EXPECT(dummy.getAccountID(f) == id); BEAST_EXPECT(dummy.isFieldPresent(f)); diff --git a/src/test/protocol/InnerObjectFormats_test.cpp b/src/test/protocol/InnerObjectFormats_test.cpp index c06524b90e..7d69bb7afb 100644 --- a/src/test/protocol/InnerObjectFormats_test.cpp +++ b/src/test/protocol/InnerObjectFormats_test.cpp @@ -163,8 +163,7 @@ public: Json::Reader().parse(test.txt, req); if (RPC::contains_error(req)) { - Throw( - "Internal InnerObjectFormatsParsedJSON error. Bad JSON."); + Throw("Internal InnerObjectFormatsParsedJSON error. Bad JSON."); } STParsedJSONObject parsed("request", req); bool const noObj = !parsed.object.has_value(); diff --git a/src/test/protocol/Issue_test.cpp b/src/test/protocol/Issue_test.cpp index eec164f5b6..661a8c912b 100644 --- a/src/test/protocol/Issue_test.cpp +++ b/src/test/protocol/Issue_test.cpp @@ -434,12 +434,10 @@ public: // Both Books have the same domain BEAST_EXPECT(Book(a2, a3, domain1) == Book(a2, a3, domain1)); BEAST_EXPECT(Book(a2, a3, domain2) == Book(a2, a3, domain2)); - BEAST_EXPECT( - Book(a2, a3, std::nullopt) == Book(a2, a3, std::nullopt)); + BEAST_EXPECT(Book(a2, a3, std::nullopt) == Book(a2, a3, std::nullopt)); // Both Books have no domain - BEAST_EXPECT( - Book(a2, a3, std::nullopt) == Book(a2, a3, std::nullopt)); + BEAST_EXPECT(Book(a2, a3, std::nullopt) == Book(a2, a3, std::nullopt)); // Testing comparisons with >= and <= @@ -458,10 +456,8 @@ public: BEAST_EXPECT(Book(a2, a3, std::nullopt) < Book(a2, a3, domain2)); // Comparing two Books with no domains - BEAST_EXPECT( - Book(a2, a3, std::nullopt) <= Book(a2, a3, std::nullopt)); - BEAST_EXPECT( - Book(a2, a3, std::nullopt) >= Book(a2, a3, std::nullopt)); + BEAST_EXPECT(Book(a2, a3, std::nullopt) <= Book(a2, a3, std::nullopt)); + BEAST_EXPECT(Book(a2, a3, std::nullopt) >= Book(a2, a3, std::nullopt)); // Test case where domain1 is less than domain2 BEAST_EXPECT(Book(a2, a3, domain1) <= Book(a2, a3, domain2)); @@ -509,99 +505,51 @@ public: // log << std::hex << hash (Book (a3, a4)); // log << std::hex << hash (Book (a3, a4)); - BEAST_EXPECT( - hash(Book(a1, a2, std::nullopt)) == - hash(Book(a1, a2, std::nullopt))); - BEAST_EXPECT( - hash(Book(a1, a3, std::nullopt)) == - hash(Book(a1, a3, std::nullopt))); - BEAST_EXPECT( - hash(Book(a1, a4, std::nullopt)) == - hash(Book(a1, a4, std::nullopt))); - BEAST_EXPECT( - hash(Book(a2, a3, std::nullopt)) == - hash(Book(a2, a3, std::nullopt))); - BEAST_EXPECT( - hash(Book(a2, a4, std::nullopt)) == - hash(Book(a2, a4, std::nullopt))); - BEAST_EXPECT( - hash(Book(a3, a4, std::nullopt)) == - hash(Book(a3, a4, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) == hash(Book(a1, a2, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a3, std::nullopt)) == hash(Book(a1, a3, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a4, std::nullopt)) == hash(Book(a1, a4, std::nullopt))); + BEAST_EXPECT(hash(Book(a2, a3, std::nullopt)) == hash(Book(a2, a3, std::nullopt))); + BEAST_EXPECT(hash(Book(a2, a4, std::nullopt)) == hash(Book(a2, a4, std::nullopt))); + BEAST_EXPECT(hash(Book(a3, a4, std::nullopt)) == hash(Book(a3, a4, std::nullopt))); - BEAST_EXPECT( - hash(Book(a1, a2, std::nullopt)) != - hash(Book(a1, a3, std::nullopt))); - BEAST_EXPECT( - hash(Book(a1, a2, std::nullopt)) != - hash(Book(a1, a4, std::nullopt))); - BEAST_EXPECT( - hash(Book(a1, a2, std::nullopt)) != - hash(Book(a2, a3, std::nullopt))); - BEAST_EXPECT( - hash(Book(a1, a2, std::nullopt)) != - hash(Book(a2, a4, std::nullopt))); - BEAST_EXPECT( - hash(Book(a1, a2, std::nullopt)) != - hash(Book(a3, a4, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a1, a3, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a1, a4, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a2, a3, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a2, a4, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a3, a4, std::nullopt))); // Books with domain - BEAST_EXPECT( - hash(Book(a1, a2, domain1)) == hash(Book(a1, a2, domain1))); - BEAST_EXPECT( - hash(Book(a1, a3, domain1)) == hash(Book(a1, a3, domain1))); - BEAST_EXPECT( - hash(Book(a1, a4, domain1)) == hash(Book(a1, a4, domain1))); - BEAST_EXPECT( - hash(Book(a2, a3, domain1)) == hash(Book(a2, a3, domain1))); - BEAST_EXPECT( - hash(Book(a2, a4, domain1)) == hash(Book(a2, a4, domain1))); - BEAST_EXPECT( - hash(Book(a3, a4, domain1)) == hash(Book(a3, a4, domain1))); - BEAST_EXPECT( - hash(Book(a1, a2, std::nullopt)) == - hash(Book(a1, a2, std::nullopt))); + BEAST_EXPECT(hash(Book(a1, a2, domain1)) == hash(Book(a1, a2, domain1))); + BEAST_EXPECT(hash(Book(a1, a3, domain1)) == hash(Book(a1, a3, domain1))); + BEAST_EXPECT(hash(Book(a1, a4, domain1)) == hash(Book(a1, a4, domain1))); + BEAST_EXPECT(hash(Book(a2, a3, domain1)) == hash(Book(a2, a3, domain1))); + BEAST_EXPECT(hash(Book(a2, a4, domain1)) == hash(Book(a2, a4, domain1))); + BEAST_EXPECT(hash(Book(a3, a4, domain1)) == hash(Book(a3, a4, domain1))); + BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) == hash(Book(a1, a2, std::nullopt))); // Comparing Books with domain1 vs no domain - BEAST_EXPECT( - hash(Book(a1, a2, std::nullopt)) != hash(Book(a1, a2, domain1))); - BEAST_EXPECT( - hash(Book(a1, a3, std::nullopt)) != hash(Book(a1, a3, domain1))); - BEAST_EXPECT( - hash(Book(a1, a4, std::nullopt)) != hash(Book(a1, a4, domain1))); - BEAST_EXPECT( - hash(Book(a2, a3, std::nullopt)) != hash(Book(a2, a3, domain1))); - BEAST_EXPECT( - hash(Book(a2, a4, std::nullopt)) != hash(Book(a2, a4, domain1))); - BEAST_EXPECT( - hash(Book(a3, a4, std::nullopt)) != hash(Book(a3, a4, domain1))); + BEAST_EXPECT(hash(Book(a1, a2, std::nullopt)) != hash(Book(a1, a2, domain1))); + BEAST_EXPECT(hash(Book(a1, a3, std::nullopt)) != hash(Book(a1, a3, domain1))); + BEAST_EXPECT(hash(Book(a1, a4, std::nullopt)) != hash(Book(a1, a4, domain1))); + BEAST_EXPECT(hash(Book(a2, a3, std::nullopt)) != hash(Book(a2, a3, domain1))); + BEAST_EXPECT(hash(Book(a2, a4, std::nullopt)) != hash(Book(a2, a4, domain1))); + BEAST_EXPECT(hash(Book(a3, a4, std::nullopt)) != hash(Book(a3, a4, domain1))); // Books with domain1 but different Issues - BEAST_EXPECT( - hash(Book(a1, a2, domain1)) != hash(Book(a1, a3, domain1))); - BEAST_EXPECT( - hash(Book(a1, a2, domain1)) != hash(Book(a1, a4, domain1))); - BEAST_EXPECT( - hash(Book(a2, a3, domain1)) != hash(Book(a2, a4, domain1))); - BEAST_EXPECT( - hash(Book(a1, a2, domain1)) != hash(Book(a2, a3, domain1))); - BEAST_EXPECT( - hash(Book(a2, a4, domain1)) != hash(Book(a3, a4, domain1))); - BEAST_EXPECT( - hash(Book(a3, a4, domain1)) != hash(Book(a1, a4, domain1))); + BEAST_EXPECT(hash(Book(a1, a2, domain1)) != hash(Book(a1, a3, domain1))); + BEAST_EXPECT(hash(Book(a1, a2, domain1)) != hash(Book(a1, a4, domain1))); + BEAST_EXPECT(hash(Book(a2, a3, domain1)) != hash(Book(a2, a4, domain1))); + BEAST_EXPECT(hash(Book(a1, a2, domain1)) != hash(Book(a2, a3, domain1))); + BEAST_EXPECT(hash(Book(a2, a4, domain1)) != hash(Book(a3, a4, domain1))); + BEAST_EXPECT(hash(Book(a3, a4, domain1)) != hash(Book(a1, a4, domain1))); // Books with domain1 and domain2 - BEAST_EXPECT( - hash(Book(a1, a2, domain1)) != hash(Book(a1, a2, domain2))); - BEAST_EXPECT( - hash(Book(a1, a3, domain1)) != hash(Book(a1, a3, domain2))); - BEAST_EXPECT( - hash(Book(a1, a4, domain1)) != hash(Book(a1, a4, domain2))); - BEAST_EXPECT( - hash(Book(a2, a3, domain1)) != hash(Book(a2, a3, domain2))); - BEAST_EXPECT( - hash(Book(a2, a4, domain1)) != hash(Book(a2, a4, domain2))); - BEAST_EXPECT( - hash(Book(a3, a4, domain1)) != hash(Book(a3, a4, domain2))); + BEAST_EXPECT(hash(Book(a1, a2, domain1)) != hash(Book(a1, a2, domain2))); + BEAST_EXPECT(hash(Book(a1, a3, domain1)) != hash(Book(a1, a3, domain2))); + BEAST_EXPECT(hash(Book(a1, a4, domain1)) != hash(Book(a1, a4, domain2))); + BEAST_EXPECT(hash(Book(a2, a3, domain1)) != hash(Book(a2, a3, domain2))); + BEAST_EXPECT(hash(Book(a2, a4, domain1)) != hash(Book(a2, a4, domain2))); + BEAST_EXPECT(hash(Book(a3, a4, domain1)) != hash(Book(a3, a4, domain2))); } //-------------------------------------------------------------------------- diff --git a/src/test/protocol/Memo_test.cpp b/src/test/protocol/Memo_test.cpp index 706ef79fe2..3c5d3f5a38 100644 --- a/src/test/protocol/Memo_test.cpp +++ b/src/test/protocol/Memo_test.cpp @@ -35,16 +35,14 @@ public: { // Make sure that too big a memo is flagged as invalid. JTx memoSize = makeJtxWithMemo(); - memoSize.jv[sfMemos.jsonName][0u][sfMemo.jsonName] - [sfMemoData.jsonName] = std::string(2020, '0'); + memoSize.jv[sfMemos.jsonName][0u][sfMemo.jsonName][sfMemoData.jsonName] = std::string(2020, '0'); env(memoSize, rpc("invalidTransaction", "fails local checks: The memo exceeds the maximum allowed " "size.")); // This memo is just barely small enough. - memoSize.jv[sfMemos.jsonName][0u][sfMemo.jsonName] - [sfMemoData.jsonName] = std::string(2018, '1'); + memoSize.jv[sfMemos.jsonName][0u][sfMemo.jsonName][sfMemoData.jsonName] = std::string(2018, '1'); env(memoSize); } { @@ -64,9 +62,7 @@ public: { // Put an invalid field in a Memo object. JTx memoExtra = makeJtxWithMemo(); - memoExtra - .jv[sfMemos.jsonName][0u][sfMemo.jsonName][sfFlags.jsonName] = - 13; + memoExtra.jv[sfMemos.jsonName][0u][sfMemo.jsonName][sfFlags.jsonName] = 13; env(memoExtra, rpc("invalidTransaction", "fails local checks: A memo may contain only MemoType, " @@ -75,8 +71,7 @@ public: { // Put a character that is not allowed in a URL in a MemoType field. JTx memoBadChar = makeJtxWithMemo(); - memoBadChar.jv[sfMemos.jsonName][0u][sfMemo.jsonName] - [sfMemoType.jsonName] = + memoBadChar.jv[sfMemos.jsonName][0u][sfMemo.jsonName][sfMemoType.jsonName] = strHex(std::string_view("ONE subject{}; static_assert(sizeof(subject) == sizeof(subject.val)); static_assert(subject.size == subject.val.size()); - static_assert( - std::is_same_v>); + static_assert(std::is_same_v>); BEAST_EXPECT(subject.val.size() == 3); - BEAST_EXPECT( - (subject.val == - std::array{jsonNull, jsonNull, jsonNull})); + BEAST_EXPECT((subject.val == std::array{jsonNull, jsonNull, jsonNull})); subject.val[0] = obj1; subject.val[1] = obj2; @@ -61,21 +58,15 @@ struct MultiApiJson_test : beast::unit_test::suite testcase("forApiVersions, forAllApiVersions"); // Some static data for test inputs - static int const primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, 61, - 67, 71, 73, 79, 83, 89, 97}; + static int const primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, + 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}; static_assert(std::size(primes) > RPC::apiMaximumValidVersion); MultiApiJson<1, 3> s1{}; - static_assert( - s1.size == - RPC::apiMaximumValidVersion + 1 - - RPC::apiMinimumSupportedVersion); + static_assert(s1.size == RPC::apiMaximumValidVersion + 1 - RPC::apiMinimumSupportedVersion); int productAllVersions = 1; - for (unsigned i = RPC::apiMinimumSupportedVersion; - i <= RPC::apiMaximumValidVersion; - ++i) + for (unsigned i = RPC::apiMinimumSupportedVersion; i <= RPC::apiMaximumValidVersion; ++i) { auto const index = i - RPC::apiMinimumSupportedVersion; BEAST_EXPECT(index == s1.index(i)); @@ -85,25 +76,15 @@ struct MultiApiJson_test : beast::unit_test::suite } BEAST_EXPECT(!s1.valid(0)); BEAST_EXPECT(!s1.valid(RPC::apiMaximumValidVersion + 1)); - BEAST_EXPECT( - !s1.valid(std::numeric_limits< - decltype(RPC::apiMaximumValidVersion.value)>::max())); + BEAST_EXPECT(!s1.valid(std::numeric_limits::max())); int result = 1; - static_assert( - RPC::apiMinimumSupportedVersion + 1 <= - RPC::apiMaximumValidVersion); - forApiVersions< - RPC::apiMinimumSupportedVersion, - RPC::apiMinimumSupportedVersion + 1>( + static_assert(RPC::apiMinimumSupportedVersion + 1 <= RPC::apiMaximumValidVersion); + forApiVersions( std::as_const(s1).visit(), - [this]( - Json::Value const& json, - unsigned int version, - int* result) { + [this](Json::Value const& json, unsigned int version, int* result) { BEAST_EXPECT( - version >= RPC::apiMinimumSupportedVersion && - version <= RPC::apiMinimumSupportedVersion + 1); + version >= RPC::apiMinimumSupportedVersion && version <= RPC::apiMinimumSupportedVersion + 1); if (BEAST_EXPECT(json.isMember("value"))) { *result *= json["value"].asInt(); @@ -111,30 +92,22 @@ struct MultiApiJson_test : beast::unit_test::suite }, &result); BEAST_EXPECT( - result == - primes[RPC::apiMinimumSupportedVersion] * - primes[RPC::apiMinimumSupportedVersion + 1]); + result == primes[RPC::apiMinimumSupportedVersion] * primes[RPC::apiMinimumSupportedVersion + 1]); // Check all the values with mutable data - forAllApiVersions( - s1.visit(), [&s1, this](Json::Value& json, auto version) { - BEAST_EXPECT(s1.val[s1.index(version)] == json); - if (BEAST_EXPECT(json.isMember("value"))) - { - BEAST_EXPECT(json["value"].asInt() == primes[version]); - } - }); + forAllApiVersions(s1.visit(), [&s1, this](Json::Value& json, auto version) { + BEAST_EXPECT(s1.val[s1.index(version)] == json); + if (BEAST_EXPECT(json.isMember("value"))) + { + BEAST_EXPECT(json["value"].asInt() == primes[version]); + } + }); result = 1; forAllApiVersions( std::as_const(s1).visit(), - [this]( - Json::Value const& json, - unsigned int version, - int* result) { - BEAST_EXPECT( - version >= RPC::apiMinimumSupportedVersion && - version <= RPC::apiMaximumValidVersion); + [this](Json::Value const& json, unsigned int version, int* result) { + BEAST_EXPECT(version >= RPC::apiMinimumSupportedVersion && version <= RPC::apiMaximumValidVersion); if (BEAST_EXPECT(json.isMember("value"))) { *result *= json["value"].asInt(); @@ -163,7 +136,7 @@ struct MultiApiJson_test : beast::unit_test::suite return !requires { forAllApiVersions( std::forward(v).visit(), // - []() {}); // missing parameters + []() {}); // missing parameters }; }(std::as_const(s1))); static_assert([](auto&& v) { @@ -234,10 +207,7 @@ struct MultiApiJson_test : beast::unit_test::suite forAllApiVersions( std::forward(v).visit(), // []( - Json::Value const&, - std::integral_constant, - int, - char const*) {}, + Json::Value const&, std::integral_constant, int, char const*) {}, 0, ""); }; @@ -308,27 +278,17 @@ struct MultiApiJson_test : beast::unit_test::suite BEAST_EXPECT(x.val[1]["name2"].asString() == "bar"); // Tests of requires clause - these are expected to match - static_assert([](auto&& v) { - return requires { v.set("name", Json::nullValue); }; - }(x)); - static_assert([](auto&& v) { - return requires { v.set("name", "value"); }; - }(x)); - static_assert( - [](auto&& v) { return requires { v.set("name", true); }; }(x)); - static_assert( - [](auto&& v) { return requires { v.set("name", 42); }; }(x)); + static_assert([](auto&& v) { return requires { v.set("name", Json::nullValue); }; }(x)); + static_assert([](auto&& v) { return requires { v.set("name", "value"); }; }(x)); + static_assert([](auto&& v) { return requires { v.set("name", true); }; }(x)); + static_assert([](auto&& v) { return requires { v.set("name", 42); }; }(x)); // Tests of requires clause - these are expected NOT to match struct foo_t final { }; - static_assert([](auto&& v) { - return !requires { v.set("name", foo_t{}); }; - }(x)); - static_assert([](auto&& v) { - return !requires { v.set("name", std::nullopt); }; - }(x)); + static_assert([](auto&& v) { return !requires { v.set("name", foo_t{}); }; }(x)); + static_assert([](auto&& v) { return !requires { v.set("name", std::nullopt); }; }(x)); } { @@ -387,8 +347,7 @@ struct MultiApiJson_test : beast::unit_test::suite v.visitor( v, std::integral_constant{}, - [](Json::Value&, std::integral_constant) { - }); + [](Json::Value&, std::integral_constant) {}); }; }(s1)); BEAST_EXPECT( @@ -396,20 +355,12 @@ struct MultiApiJson_test : beast::unit_test::suite s1, std::integral_constant{}, Overload{ - [](Json::Value& v, - std::integral_constant) { - return v["value"].asInt(); - }, + [](Json::Value& v, std::integral_constant) { return v["value"].asInt(); }, [](Json::Value const&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 2); static_assert([](auto&& v) { - return requires { - v.visitor( - v, - std::integral_constant{}, - [](Json::Value&) {}); - }; + return requires { v.visitor(v, std::integral_constant{}, [](Json::Value&) {}); }; }(s1)); BEAST_EXPECT( s1.visitor( @@ -425,8 +376,7 @@ struct MultiApiJson_test : beast::unit_test::suite v.visitor( v, std::integral_constant{}, - [](Json::Value const&, - std::integral_constant) {}); + [](Json::Value const&, std::integral_constant) {}); }; }(std::as_const(s1))); BEAST_EXPECT( @@ -434,20 +384,12 @@ struct MultiApiJson_test : beast::unit_test::suite std::as_const(s1), std::integral_constant{}, Overload{ - [](Json::Value const& v, - std::integral_constant) { - return v["value"].asInt(); - }, + [](Json::Value const& v, std::integral_constant) { return v["value"].asInt(); }, [](Json::Value&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 3); static_assert([](auto&& v) { - return requires { - v.visitor( - v, - std::integral_constant{}, - [](Json::Value const&) {}); - }; + return requires { v.visitor(v, std::integral_constant{}, [](Json::Value const&) {}); }; }(std::as_const(s1))); BEAST_EXPECT( s1.visitor( @@ -458,25 +400,17 @@ struct MultiApiJson_test : beast::unit_test::suite [](Json::Value&) { return 0; }, [](auto...) { return 0; }}) == 3); - static_assert([](auto&& v) { - return requires { - v.visitor(v, 1, [](Json::Value&, unsigned) {}); - }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](Json::Value&, unsigned) {}); }; }(s1)); BEAST_EXPECT( s1.visitor( s1, // 3u, Overload{ - [](Json::Value& v, unsigned) { - return v["value"].asInt(); - }, + [](Json::Value& v, unsigned) { return v["value"].asInt(); }, [](Json::Value const&, unsigned) { return 0; }, [](auto, auto) { return 0; }}) == 5); - static_assert([](auto&& v) { - return requires { v.visitor(v, 1, [](Json::Value&) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](Json::Value&) {}); }; }(s1)); BEAST_EXPECT( s1.visitor( s1, // @@ -487,24 +421,19 @@ struct MultiApiJson_test : beast::unit_test::suite [](auto...) { return 0; }}) == 5); static_assert([](auto&& v) { - return requires { - v.visitor(v, 1, [](Json::Value const&, unsigned) {}); - }; + return requires { v.visitor(v, 1, [](Json::Value const&, unsigned) {}); }; }(std::as_const(s1))); BEAST_EXPECT( s1.visitor( std::as_const(s1), // 2u, Overload{ - [](Json::Value const& v, unsigned) { - return v["value"].asInt(); - }, + [](Json::Value const& v, unsigned) { return v["value"].asInt(); }, [](Json::Value const&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 3); - static_assert([](auto&& v) { - return requires { v.visitor(v, 1, [](Json::Value const&) {}); }; - }(std::as_const(s1))); + static_assert( + [](auto&& v) { return requires { v.visitor(v, 1, [](Json::Value const&) {}); }; }(std::as_const(s1))); BEAST_EXPECT( s1.visitor( std::as_const(s1), // @@ -519,49 +448,37 @@ struct MultiApiJson_test : beast::unit_test::suite s1.visitor( s1, std::integral_constant{}, // to unsigned - [](Json::Value& v, unsigned) { - return v["value"].asInt(); - }) == 2); + [](Json::Value& v, unsigned) { return v["value"].asInt(); }) == 2); BEAST_EXPECT( s1.visitor( std::as_const(s1), std::integral_constant{}, // to unsigned - [](Json::Value const& v, unsigned) { - return v["value"].asInt(); - }) == 3); + [](Json::Value const& v, unsigned) { return v["value"].asInt(); }) == 3); BEAST_EXPECT( s1.visitor( s1, // to const std::integral_constant{}, - [](Json::Value const& v, auto) { - return v["value"].asInt(); - }) == 5); + [](Json::Value const& v, auto) { return v["value"].asInt(); }) == 5); BEAST_EXPECT( s1.visitor( s1, // to const std::integral_constant{}, - [](Json::Value const& v) { return v["value"].asInt(); }) == - 5); + [](Json::Value const& v) { return v["value"].asInt(); }) == 5); BEAST_EXPECT( s1.visitor( s1, 3, // to long - [](Json::Value& v, long) { return v["value"].asInt(); }) == - 5); + [](Json::Value& v, long) { return v["value"].asInt(); }) == 5); BEAST_EXPECT( s1.visitor( std::as_const(s1), 1, // to long - [](Json::Value const& v, long) { - return v["value"].asInt(); - }) == 2); + [](Json::Value const& v, long) { return v["value"].asInt(); }) == 2); BEAST_EXPECT( s1.visitor( s1, // to const 2, - [](Json::Value const& v, auto) { - return v["value"].asInt(); - }) == 3); + [](Json::Value const& v, auto) { return v["value"].asInt(); }) == 3); BEAST_EXPECT( s1.visitor( s1, // type deduction @@ -571,8 +488,7 @@ struct MultiApiJson_test : beast::unit_test::suite s1.visitor( s1, // to const, type deduction 2, - [](auto const& v, auto) { return v["value"].asInt(); }) == - 3); + [](auto const& v, auto) { return v["value"].asInt(); }) == 3); BEAST_EXPECT( s1.visitor( s1, // type deduction @@ -589,18 +505,14 @@ struct MultiApiJson_test : beast::unit_test::suite s1.visitor( s1, std::integral_constant{}, - [](Json::Value& v, auto ver, auto a1, auto a2) { - return ver * a1 * a2 * v["value"].asInt(); - }, + [](Json::Value& v, auto ver, auto a1, auto a2) { return ver * a1 * a2 * v["value"].asInt(); }, 5, 7) == 2 * 5 * 7 * 3); BEAST_EXPECT( s1.visitor( s1, std::integral_constant{}, - [](Json::Value& v, auto ver, auto... args) { - return ver * (1 * ... * args) * v["value"].asInt(); - }, + [](Json::Value& v, auto ver, auto... args) { return ver * (1 * ... * args) * v["value"].asInt(); }, 5, 7) == 2 * 5 * 7 * 3); @@ -642,55 +554,27 @@ struct MultiApiJson_test : beast::unit_test::suite }(s1)); // Want these to be unambiguous - static_assert([](auto&& v) { - return requires { v.visitor(v, 1, [](auto) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](auto) {}); }; }(s1)); - static_assert([](auto&& v) { - return requires { v.visitor(v, 1, [](Json::Value&) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](Json::Value&) {}); }; }(s1)); - static_assert([](auto&& v) { - return requires { - v.visitor(v, 1, [](Json::Value&, auto...) {}); - }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](Json::Value&, auto...) {}); }; }(s1)); - static_assert([](auto&& v) { - return requires { v.visitor(v, 1, [](Json::Value const&) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](Json::Value const&) {}); }; }(s1)); - static_assert([](auto&& v) { - return requires { - v.visitor(v, 1, [](Json::Value const&, auto...) {}); - }; - }(s1)); + static_assert( + [](auto&& v) { return requires { v.visitor(v, 1, [](Json::Value const&, auto...) {}); }; }(s1)); - static_assert([](auto&& v) { - return requires { v.visitor(v, 1, [](auto...) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](auto...) {}); }; }(s1)); - static_assert([](auto&& v) { - return requires { v.visitor(v, 1, [](auto, auto...) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](auto, auto...) {}); }; }(s1)); - static_assert([](auto&& v) { - return requires { - v.visitor(v, 1, [](auto, auto, auto...) {}); - }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](auto, auto, auto...) {}); }; }(s1)); - static_assert([](auto&& v) { - return requires { - v.visitor(v, 1, [](auto, auto, auto...) {}, ""); - }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visitor(v, 1, [](auto, auto, auto...) {}, ""); }; }(s1)); - static_assert([](auto&& v) { - return requires { - v.visitor(v, 1, [](auto, auto, auto, auto...) {}, ""); - }; - }(s1)); + static_assert( + [](auto&& v) { return requires { v.visitor(v, 1, [](auto, auto, auto, auto...) {}, ""); }; }(s1)); } { @@ -706,45 +590,33 @@ struct MultiApiJson_test : beast::unit_test::suite return requires { v.visit( std::integral_constant{}, - [](Json::Value&, std::integral_constant) { - }); + [](Json::Value&, std::integral_constant) {}); }; }(s1)); BEAST_EXPECT( s1.visit( std::integral_constant{}, Overload{ - [](Json::Value& v, - std::integral_constant) { - return v["value"].asInt(); - }, + [](Json::Value& v, std::integral_constant) { return v["value"].asInt(); }, [](Json::Value const&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 2); static_assert([](auto&& v) { return requires { v.visit()( std::integral_constant{}, - [](Json::Value&, std::integral_constant) { - }); + [](Json::Value&, std::integral_constant) {}); }; }(s1)); BEAST_EXPECT( s1.visit()( std::integral_constant{}, Overload{ - [](Json::Value& v, - std::integral_constant) { - return v["value"].asInt(); - }, + [](Json::Value& v, std::integral_constant) { return v["value"].asInt(); }, [](Json::Value const&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 2); static_assert([](auto&& v) { - return requires { - v.visit( - std::integral_constant{}, - [](Json::Value&) {}); - }; + return requires { v.visit(std::integral_constant{}, [](Json::Value&) {}); }; }(s1)); BEAST_EXPECT( s1.visit( @@ -754,11 +626,7 @@ struct MultiApiJson_test : beast::unit_test::suite [](Json::Value const&) { return 0; }, [](auto...) { return 0; }}) == 2); static_assert([](auto&& v) { - return requires { - v.visit()( - std::integral_constant{}, - [](Json::Value&) {}); - }; + return requires { v.visit()(std::integral_constant{}, [](Json::Value&) {}); }; }(s1)); BEAST_EXPECT( s1.visit()( @@ -772,45 +640,33 @@ struct MultiApiJson_test : beast::unit_test::suite return requires { v.visit( std::integral_constant{}, - [](Json::Value const&, - std::integral_constant) {}); + [](Json::Value const&, std::integral_constant) {}); }; }(std::as_const(s1))); BEAST_EXPECT( std::as_const(s1).visit( std::integral_constant{}, Overload{ - [](Json::Value const& v, - std::integral_constant) { - return v["value"].asInt(); - }, + [](Json::Value const& v, std::integral_constant) { return v["value"].asInt(); }, [](Json::Value&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 3); static_assert([](auto&& v) { return requires { v.visit()( std::integral_constant{}, - [](Json::Value const&, - std::integral_constant) {}); + [](Json::Value const&, std::integral_constant) {}); }; }(std::as_const(s1))); BEAST_EXPECT( std::as_const(s1).visit()( std::integral_constant{}, Overload{ - [](Json::Value const& v, - std::integral_constant) { - return v["value"].asInt(); - }, + [](Json::Value const& v, std::integral_constant) { return v["value"].asInt(); }, [](Json::Value&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 3); static_assert([](auto&& v) { - return requires { - v.visit( - std::integral_constant{}, - [](Json::Value const&) {}); - }; + return requires { v.visit(std::integral_constant{}, [](Json::Value const&) {}); }; }(std::as_const(s1))); BEAST_EXPECT( std::as_const(s1).visit( @@ -820,11 +676,7 @@ struct MultiApiJson_test : beast::unit_test::suite [](Json::Value&) { return 0; }, [](auto...) { return 0; }}) == 3); static_assert([](auto&& v) { - return requires { - v.visit()( - std::integral_constant{}, - [](Json::Value const&) {}); - }; + return requires { v.visit()(std::integral_constant{}, [](Json::Value const&) {}); }; }(std::as_const(s1))); BEAST_EXPECT( std::as_const(s1).visit()( @@ -834,38 +686,26 @@ struct MultiApiJson_test : beast::unit_test::suite [](Json::Value&) { return 0; }, [](auto...) { return 0; }}) == 3); - static_assert([](auto&& v) { - return requires { v.visit(1, [](Json::Value&, unsigned) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visit(1, [](Json::Value&, unsigned) {}); }; }(s1)); BEAST_EXPECT( s1.visit( 3u, Overload{ - [](Json::Value& v, unsigned) { - return v["value"].asInt(); - }, + [](Json::Value& v, unsigned) { return v["value"].asInt(); }, [](Json::Value const&, unsigned) { return 0; }, [](Json::Value&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 5); - static_assert([](auto&& v) { - return requires { - v.visit()(1, [](Json::Value&, unsigned) {}); - }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visit()(1, [](Json::Value&, unsigned) {}); }; }(s1)); BEAST_EXPECT( s1.visit()( 3u, Overload{ - [](Json::Value& v, unsigned) { - return v["value"].asInt(); - }, + [](Json::Value& v, unsigned) { return v["value"].asInt(); }, [](Json::Value const&, unsigned) { return 0; }, [](Json::Value&, auto) { return 0; }, [](auto, auto) { return 0; }}) == 5); - static_assert([](auto&& v) { - return requires { v.visit(1, [](Json::Value&) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visit(1, [](Json::Value&) {}); }; }(s1)); BEAST_EXPECT( s1.visit( 3, @@ -873,9 +713,7 @@ struct MultiApiJson_test : beast::unit_test::suite [](Json::Value& v) { return v["value"].asInt(); }, [](Json::Value const&) { return 0; }, [](auto...) { return 0; }}) == 5); - static_assert([](auto&& v) { - return requires { v.visit()(1, [](Json::Value&) {}); }; - }(s1)); + static_assert([](auto&& v) { return requires { v.visit()(1, [](Json::Value&) {}); }; }(s1)); BEAST_EXPECT( s1.visit()( 3, @@ -885,39 +723,30 @@ struct MultiApiJson_test : beast::unit_test::suite [](auto...) { return 0; }}) == 5); static_assert([](auto&& v) { - return requires { - v.visit(1, [](Json::Value const&, unsigned) {}); - }; + return requires { v.visit(1, [](Json::Value const&, unsigned) {}); }; }(std::as_const(s1))); BEAST_EXPECT( std::as_const(s1).visit( 2u, Overload{ - [](Json::Value const& v, unsigned) { - return v["value"].asInt(); - }, + [](Json::Value const& v, unsigned) { return v["value"].asInt(); }, [](Json::Value const&, auto) { return 0; }, [](Json::Value&, unsigned) { return 0; }, [](auto, auto) { return 0; }}) == 3); static_assert([](auto&& v) { - return requires { - v.visit()(1, [](Json::Value const&, unsigned) {}); - }; + return requires { v.visit()(1, [](Json::Value const&, unsigned) {}); }; }(std::as_const(s1))); BEAST_EXPECT( std::as_const(s1).visit()( 2u, Overload{ - [](Json::Value const& v, unsigned) { - return v["value"].asInt(); - }, + [](Json::Value const& v, unsigned) { return v["value"].asInt(); }, [](Json::Value const&, auto) { return 0; }, [](Json::Value&, unsigned) { return 0; }, [](auto, auto) { return 0; }}) == 3); - static_assert([](auto&& v) { - return requires { v.visit(1, [](Json::Value const&) {}); }; - }(std::as_const(s1))); + static_assert( + [](auto&& v) { return requires { v.visit(1, [](Json::Value const&) {}); }; }(std::as_const(s1))); BEAST_EXPECT( std::as_const(s1).visit( 2, @@ -925,9 +754,8 @@ struct MultiApiJson_test : beast::unit_test::suite [](Json::Value const& v) { return v["value"].asInt(); }, [](Json::Value&) { return 0; }, [](auto...) { return 0; }}) == 3); - static_assert([](auto&& v) { - return requires { v.visit()(1, [](Json::Value const&) {}); }; - }(std::as_const(s1))); + static_assert( + [](auto&& v) { return requires { v.visit()(1, [](Json::Value const&) {}); }; }(std::as_const(s1))); BEAST_EXPECT( std::as_const(s1).visit()( 2, @@ -938,112 +766,60 @@ struct MultiApiJson_test : beast::unit_test::suite // Rvalue MultivarJson visitor only binds to regular reference static_assert([](auto&& v) { - return !requires { - std::forward(v).visit(1, [](Json::Value&&) {}); - }; + return !requires { std::forward(v).visit(1, [](Json::Value&&) {}); }; }(std::move(s1))); static_assert([](auto&& v) { - return !requires { - std::forward(v).visit( - 1, [](Json::Value const&&) {}); - }; + return !requires { std::forward(v).visit(1, [](Json::Value const&&) {}); }; }(std::move(s1))); static_assert([](auto&& v) { - return requires { - std::forward(v).visit(1, [](Json::Value&) {}); - }; + return requires { std::forward(v).visit(1, [](Json::Value&) {}); }; }(std::move(s1))); static_assert([](auto&& v) { - return requires { - std::forward(v).visit( - 1, [](Json::Value const&) {}); - }; + return requires { std::forward(v).visit(1, [](Json::Value const&) {}); }; }(std::move(s1))); static_assert([](auto&& v) { - return !requires { - std::forward(v).visit()( - 1, [](Json::Value&&) {}); - }; + return !requires { std::forward(v).visit()(1, [](Json::Value&&) {}); }; }(std::move(s1))); static_assert([](auto&& v) { - return !requires { - std::forward(v).visit()( - 1, [](Json::Value const&&) {}); - }; + return !requires { std::forward(v).visit()(1, [](Json::Value const&&) {}); }; }(std::move(s1))); static_assert([](auto&& v) { - return requires { - std::forward(v).visit()( - 1, [](Json::Value&) {}); - }; + return requires { std::forward(v).visit()(1, [](Json::Value&) {}); }; }(std::move(s1))); static_assert([](auto&& v) { - return requires { - std::forward(v).visit()( - 1, [](Json::Value const&) {}); - }; + return requires { std::forward(v).visit()(1, [](Json::Value const&) {}); }; }(std::move(s1))); static_assert([](auto&& v) { - return !requires { - std::forward(v).visit( - 1, [](Json::Value const&&) {}); - }; + return !requires { std::forward(v).visit(1, [](Json::Value const&&) {}); }; }(std::move(std::as_const(s1)))); static_assert([](auto&& v) { - return requires { - std::forward(v).visit( - 1, [](Json::Value const&) {}); - }; + return requires { std::forward(v).visit(1, [](Json::Value const&) {}); }; }(std::move(std::as_const(s1)))); static_assert([](auto&& v) { - return !requires { - std::forward(v).visit()( - 1, [](Json::Value const&&) {}); - }; + return !requires { std::forward(v).visit()(1, [](Json::Value const&&) {}); }; }(std::move(std::as_const(s1)))); static_assert([](auto&& v) { - return requires { - std::forward(v).visit()( - 1, [](Json::Value const&) {}); - }; + return requires { std::forward(v).visit()(1, [](Json::Value const&) {}); }; }(std::move(std::as_const(s1)))); // Missing const static_assert([](auto&& v) { - return !requires { - std::forward(v).visit( - 1, [](Json::Value&, auto) {}); - }; + return !requires { std::forward(v).visit(1, [](Json::Value&, auto) {}); }; }(std::as_const(s1))); static_assert([](auto&& v) { - return !requires { - std::forward(v).visit()( - 1, [](Json::Value&, auto) {}); - }; + return !requires { std::forward(v).visit()(1, [](Json::Value&, auto) {}); }; }(std::as_const(s1))); // Missing parameter - static_assert([](auto&& v) { - return !requires { - std::forward(v).visit(1, []() {}); - }; - }(s1)); - static_assert([](auto&& v) { - return !requires { - std::forward(v).visit()(1, []() {}); - }; - }(s1)); + static_assert([](auto&& v) { return !requires { std::forward(v).visit(1, []() {}); }; }(s1)); + static_assert([](auto&& v) { return !requires { std::forward(v).visit()(1, []() {}); }; }(s1)); // Sanity checks static_assert([](auto&& v) { - return requires { - std::forward(v).visit(1, [](auto...) {}); - }; + return requires { std::forward(v).visit(1, [](auto...) {}); }; }(std::as_const(s1))); static_assert([](auto&& v) { - return requires { - std::forward(v).visit()(1, [](auto...) {}); - }; + return requires { std::forward(v).visit()(1, [](auto...) {}); }; }(std::as_const(s1))); } } diff --git a/src/test/protocol/PublicKey_test.cpp b/src/test/protocol/PublicKey_test.cpp index 4af21cd037..cad1e87198 100644 --- a/src/test/protocol/PublicKey_test.cpp +++ b/src/test/protocol/PublicKey_test.cpp @@ -294,11 +294,9 @@ public: // Try converting short, long and malformed data BEAST_EXPECT(!parseBase58(TokenType::NodePublic, "")); BEAST_EXPECT(!parseBase58(TokenType::NodePublic, " ")); - BEAST_EXPECT( - !parseBase58(TokenType::NodePublic, "!ty89234gh45")); + BEAST_EXPECT(!parseBase58(TokenType::NodePublic, "!ty89234gh45")); - auto const good = toBase58( - TokenType::NodePublic, derivePublicKey(keyType, randomSecretKey())); + auto const good = toBase58(TokenType::NodePublic, derivePublicKey(keyType, randomSecretKey())); // Short (non-empty) strings { @@ -368,8 +366,7 @@ public: BEAST_EXPECT((si == sj) == (i == j)); - auto const skj = - parseBase58(TokenType::NodePublic, sj); + auto const skj = parseBase58(TokenType::NodePublic, sj); BEAST_EXPECT(skj && (keys[j] == *skj)); BEAST_EXPECT((*ski == *skj) == (i == j)); @@ -384,13 +381,10 @@ public: { auto const pk1 = derivePublicKey( - KeyType::secp256k1, - generateSecretKey( - KeyType::secp256k1, generateSeed("masterpassphrase"))); + KeyType::secp256k1, generateSecretKey(KeyType::secp256k1, generateSeed("masterpassphrase"))); - auto const pk2 = parseBase58( - TokenType::NodePublic, - "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9"); + auto const pk2 = + parseBase58(TokenType::NodePublic, "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9"); BEAST_EXPECT(pk2); BEAST_EXPECT(pk1 == *pk2); @@ -402,13 +396,10 @@ public: { auto const pk1 = derivePublicKey( - KeyType::ed25519, - generateSecretKey( - KeyType::ed25519, generateSeed("masterpassphrase"))); + KeyType::ed25519, generateSecretKey(KeyType::ed25519, generateSeed("masterpassphrase"))); - auto const pk2 = parseBase58( - TokenType::NodePublic, - "nHUeeJCSY2dM71oxM8Cgjouf5ekTuev2mwDpc374aLMxzDLXNmjf"); + auto const pk2 = + parseBase58(TokenType::NodePublic, "nHUeeJCSY2dM71oxM8Cgjouf5ekTuev2mwDpc374aLMxzDLXNmjf"); BEAST_EXPECT(pk2); BEAST_EXPECT(pk1 == *pk2); @@ -423,18 +414,14 @@ public: testcase("Miscellaneous operations"); auto const pk1 = derivePublicKey( - KeyType::secp256k1, - generateSecretKey( - KeyType::secp256k1, generateSeed("masterpassphrase"))); + KeyType::secp256k1, generateSecretKey(KeyType::secp256k1, generateSeed("masterpassphrase"))); PublicKey pk2(pk1); BEAST_EXPECT(pk1 == pk2); BEAST_EXPECT(pk2 == pk1); PublicKey pk3 = derivePublicKey( - KeyType::secp256k1, - generateSecretKey( - KeyType::secp256k1, generateSeed("arbitraryPassPhrase"))); + KeyType::secp256k1, generateSecretKey(KeyType::secp256k1, generateSeed("arbitraryPassPhrase"))); // Testing the copy assignment operation of PublicKey class pk3 = pk2; BEAST_EXPECT(pk3 == pk2); diff --git a/src/test/protocol/Quality_test.cpp b/src/test/protocol/Quality_test.cpp index 840e903ed5..1dbbbfdf3d 100644 --- a/src/test/protocol/Quality_test.cpp +++ b/src/test/protocol/Quality_test.cpp @@ -16,9 +16,7 @@ public: template static STAmount - amount( - Integer integer, - std::enable_if_t::value>* = 0) + amount(Integer integer, std::enable_if_t::value>* = 0) { static_assert(std::is_integral::value, ""); return STAmount(integer, false); @@ -26,9 +24,7 @@ public: template static STAmount - amount( - Integer integer, - std::enable_if_t::value>* = 0) + amount(Integer integer, std::enable_if_t::value>* = 0) { static_assert(std::is_integral::value, ""); if (integer < 0) @@ -45,13 +41,7 @@ public: template void - ceil_in( - Quality const& q, - In1 in, - Out1 out, - Int limit, - In2 in_expected, - Out2 out_expected) + ceil_in(Quality const& q, In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected) { auto expect_result(amounts(in_expected, out_expected)); auto actual_result(q.ceil_in(amounts(in, out), amount(limit))); @@ -61,13 +51,7 @@ public: template void - ceil_out( - Quality const& q, - In1 in, - Out1 out, - Int limit, - In2 in_expected, - Out2 out_expected) + ceil_out(Quality const& q, In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected) { auto const expect_result(amounts(in_expected, out_expected)); auto const actual_result(q.ceil_out(amounts(in, out), amount(limit))); @@ -269,10 +253,9 @@ public: { Quality q(0x5d048191fb9130daull); // 126836389.7680090 Amounts const value( - amount(349469768), // 349.469768 XRP - raw(2755280000000000ull, -15)); // 2.75528 - STAmount const limit( - raw(4131113916555555, -16)); // .4131113916555555 + amount(349469768), // 349.469768 XRP + raw(2755280000000000ull, -15)); // 2.75528 + STAmount const limit(raw(4131113916555555, -16)); // .4131113916555555 Amounts const result(q.ceil_out(value, limit)); BEAST_EXPECT(result.in != beast::zero); } @@ -366,8 +349,7 @@ public: { testcase("operations"); - Quality const q11( - Amounts(STAmount(noIssue(), 731), STAmount(noIssue(), 731))); + Quality const q11(Amounts(STAmount(noIssue(), 731), STAmount(noIssue(), 731))); Quality qa(q11); Quality qb(q11); diff --git a/src/test/protocol/STAccount_test.cpp b/src/test/protocol/STAccount_test.cpp index d469627d51..76b633df80 100644 --- a/src/test/protocol/STAccount_test.cpp +++ b/src/test/protocol/STAccount_test.cpp @@ -63,8 +63,7 @@ struct STAccount_test : public beast::unit_test::suite Serializer s; zeroAcct.add(s); BEAST_EXPECT(s.size() == 21); - BEAST_EXPECT( - strHex(s) == "140000000000000000000000000000000000000000"); + BEAST_EXPECT(strHex(s) == "140000000000000000000000000000000000000000"); SerialIter sit(s.slice()); STAccount const deserializedZero(sit, sfAccount); BEAST_EXPECT(deserializedZero.isEquivalent(zeroAcct)); @@ -72,8 +71,7 @@ struct STAccount_test : public beast::unit_test::suite { // Construct from a VL that is not exactly 160 bits. Serializer s; - std::uint8_t const bits128[]{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::uint8_t const bits128[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; s.addVL(bits128, sizeof(bits128)); SerialIter sit(s.slice()); try @@ -83,8 +81,7 @@ struct STAccount_test : public beast::unit_test::suite } catch (std::runtime_error const& ex) { - BEAST_EXPECT( - ex.what() == std::string("Invalid STAccount size")); + BEAST_EXPECT(ex.what() == std::string("Invalid STAccount size")); } } @@ -113,8 +110,7 @@ struct STAccount_test : public beast::unit_test::suite } { - auto const s = - "âabcd1rNxp4h8apvRis6mJf9Sh8C6iRxfrDWNâabcdAVâ\xc2\x80\xc2\x8f"; + auto const s = "âabcd1rNxp4h8apvRis6mJf9Sh8C6iRxfrDWNâabcdAVâ\xc2\x80\xc2\x8f"; BEAST_EXPECT(!parseBase58(s)); } } diff --git a/src/test/protocol/STAmount_test.cpp b/src/test/protocol/STAmount_test.cpp index 796ac91de1..10e159dd8d 100644 --- a/src/test/protocol/STAmount_test.cpp +++ b/src/test/protocol/STAmount_test.cpp @@ -35,18 +35,9 @@ public: mantissa--; if (mantissa < STAmount::cMinValue) - return { - amount.issue(), - mantissa, - amount.exponent(), - amount.negative()}; + return {amount.issue(), mantissa, amount.exponent(), amount.negative()}; - return { - amount.issue(), - mantissa, - amount.exponent(), - amount.negative(), - STAmount::unchecked{}}; + return {amount.issue(), mantissa, amount.exponent(), amount.negative(), STAmount::unchecked{}}; } if (valueDigits == 999999999) @@ -54,18 +45,9 @@ public: mantissa++; if (mantissa > STAmount::cMaxValue) - return { - amount.issue(), - mantissa, - amount.exponent(), - amount.negative()}; + return {amount.issue(), mantissa, amount.exponent(), amount.negative()}; - return { - amount.issue(), - mantissa, - amount.exponent(), - amount.negative(), - STAmount::unchecked{}}; + return {amount.issue(), mantissa, amount.exponent(), amount.negative(), STAmount::unchecked{}}; } return amount; @@ -91,9 +73,8 @@ public: if (res != cmp) { - log << "(" << num.getText() << "/" << den.getText() << ") X " - << mul.getText() << " = " << res.getText() << " not " - << cmp.getText(); + log << "(" << num.getText() << "/" << den.getText() << ") X " << mul.getText() << " = " << res.getText() + << " not " << cmp.getText(); fail("Rounding"); return; } @@ -108,14 +89,11 @@ public: BEAST_EXPECT(!prod1.native()); - STAmount prod2( - noIssue(), - static_cast(a) * static_cast(b)); + STAmount prod2(noIssue(), static_cast(a) * static_cast(b)); if (prod1 != prod2) { - log << "nn(" << aa.getFullText() << " * " << bb.getFullText() - << ") = " << prod1.getFullText() << " not " + log << "nn(" << aa.getFullText() << " * " << bb.getFullText() << ") = " << prod1.getFullText() << " not " << prod2.getFullText(); fail("Multiplication result is not exact"); } @@ -124,10 +102,7 @@ public: //-------------------------------------------------------------------------- void - testSetValue( - std::string const& value, - Issue const& issue, - bool success = true) + testSetValue(std::string const& value, Issue const& issue, bool success = true) { try { @@ -215,8 +190,7 @@ public: // VFALCO NOTE Why repeat "STAmount fail" so many times?? unexpected(serializeAndDeserialize(zeroSt) != zeroSt, "STAmount fail"); unexpected(serializeAndDeserialize(one) != one, "STAmount fail"); - unexpected( - serializeAndDeserialize(hundred) != hundred, "STAmount fail"); + unexpected(serializeAndDeserialize(hundred) != hundred, "STAmount fail"); unexpected(!zeroSt.native(), "STAmount fail"); unexpected(!hundred.native(), "STAmount fail"); unexpected(zeroSt != beast::zero, "STAmount fail"); @@ -298,8 +272,7 @@ public: STAmount zeroSt(noIssue()), one(noIssue(), 1), hundred(noIssue(), 100); unexpected(serializeAndDeserialize(zeroSt) != zeroSt, "STAmount fail"); unexpected(serializeAndDeserialize(one) != one, "STAmount fail"); - unexpected( - serializeAndDeserialize(hundred) != hundred, "STAmount fail"); + unexpected(serializeAndDeserialize(hundred) != hundred, "STAmount fail"); unexpected(zeroSt.native(), "STAmount fail"); unexpected(hundred.native(), "STAmount fail"); unexpected(zeroSt != beast::zero, "STAmount fail"); @@ -361,33 +334,19 @@ public: unexpected((hundred != hundred), "STAmount fail"); unexpected(STAmount(noIssue()).getText() != "0", "STAmount fail"); unexpected(STAmount(noIssue(), 31).getText() != "31", "STAmount fail"); + unexpected(STAmount(noIssue(), 31, 1).getText() != "310", "STAmount fail"); + unexpected(STAmount(noIssue(), 31, -1).getText() != "3.1", "STAmount fail"); + unexpected(STAmount(noIssue(), 31, -2).getText() != "0.31", "STAmount fail"); unexpected( - STAmount(noIssue(), 31, 1).getText() != "310", "STAmount fail"); + multiply(STAmount(noIssue(), 20), STAmount(3), noIssue()).getText() != "60", "STAmount multiply fail 1"); unexpected( - STAmount(noIssue(), 31, -1).getText() != "3.1", "STAmount fail"); - unexpected( - STAmount(noIssue(), 31, -2).getText() != "0.31", "STAmount fail"); - unexpected( - multiply(STAmount(noIssue(), 20), STAmount(3), noIssue()) - .getText() != "60", - "STAmount multiply fail 1"); - unexpected( - multiply(STAmount(noIssue(), 20), STAmount(3), xrpIssue()) - .getText() != "60", - "STAmount multiply fail 2"); - unexpected( - multiply(STAmount(20), STAmount(3), noIssue()).getText() != "60", - "STAmount multiply fail 3"); - unexpected( - multiply(STAmount(20), STAmount(3), xrpIssue()).getText() != "60", - "STAmount multiply fail 4"); + multiply(STAmount(noIssue(), 20), STAmount(3), xrpIssue()).getText() != "60", "STAmount multiply fail 2"); + unexpected(multiply(STAmount(20), STAmount(3), noIssue()).getText() != "60", "STAmount multiply fail 3"); + unexpected(multiply(STAmount(20), STAmount(3), xrpIssue()).getText() != "60", "STAmount multiply fail 4"); - if (divide(STAmount(noIssue(), 60), STAmount(3), noIssue()).getText() != - "20") + if (divide(STAmount(noIssue(), 60), STAmount(3), noIssue()).getText() != "20") { - log << "60/3 = " - << divide(STAmount(noIssue(), 60), STAmount(3), noIssue()) - .getText(); + log << "60/3 = " << divide(STAmount(noIssue(), 60), STAmount(3), noIssue()).getText(); fail("STAmount divide fail"); } else @@ -395,30 +354,21 @@ public: pass(); } + unexpected(divide(STAmount(noIssue(), 60), STAmount(3), xrpIssue()).getText() != "20", "STAmount divide fail"); + unexpected( - divide(STAmount(noIssue(), 60), STAmount(3), xrpIssue()) - .getText() != "20", + divide(STAmount(noIssue(), 60), STAmount(noIssue(), 3), noIssue()).getText() != "20", "STAmount divide fail"); unexpected( - divide(STAmount(noIssue(), 60), STAmount(noIssue(), 3), noIssue()) - .getText() != "20", - "STAmount divide fail"); - - unexpected( - divide(STAmount(noIssue(), 60), STAmount(noIssue(), 3), xrpIssue()) - .getText() != "20", + divide(STAmount(noIssue(), 60), STAmount(noIssue(), 3), xrpIssue()).getText() != "20", "STAmount divide fail"); STAmount a1(noIssue(), 60), a2(noIssue(), 10, -1); - unexpected( - divide(a2, a1, noIssue()) != amountFromQuality(getRate(a1, a2)), - "STAmount setRate(getRate) fail"); + unexpected(divide(a2, a1, noIssue()) != amountFromQuality(getRate(a1, a2)), "STAmount setRate(getRate) fail"); - unexpected( - divide(a1, a2, noIssue()) != amountFromQuality(getRate(a2, a1)), - "STAmount setRate(getRate) fail"); + unexpected(divide(a1, a2, noIssue()) != amountFromQuality(getRate(a2, a1)), "STAmount setRate(getRate) fail"); } //-------------------------------------------------------------------------- @@ -433,13 +383,11 @@ public: // and getNeeded unexpected( - getRate(STAmount(1), STAmount(10)) != - (((100ull - 14) << (64 - 8)) | 1000000000000000ull), + getRate(STAmount(1), STAmount(10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull), "STAmount getRate fail 1"); unexpected( - getRate(STAmount(10), STAmount(1)) != - (((100ull - 16) << (64 - 8)) | 1000000000000000ull), + getRate(STAmount(10), STAmount(1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull), "STAmount getRate fail 2"); unexpected( @@ -453,23 +401,19 @@ public: "STAmount getRate fail 4"); unexpected( - getRate(STAmount(noIssue(), 1), STAmount(10)) != - (((100ull - 14) << (64 - 8)) | 1000000000000000ull), + getRate(STAmount(noIssue(), 1), STAmount(10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull), "STAmount getRate fail 5"); unexpected( - getRate(STAmount(noIssue(), 10), STAmount(1)) != - (((100ull - 16) << (64 - 8)) | 1000000000000000ull), + getRate(STAmount(noIssue(), 10), STAmount(1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull), "STAmount getRate fail 6"); unexpected( - getRate(STAmount(1), STAmount(noIssue(), 10)) != - (((100ull - 14) << (64 - 8)) | 1000000000000000ull), + getRate(STAmount(1), STAmount(noIssue(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull), "STAmount getRate fail 7"); unexpected( - getRate(STAmount(10), STAmount(noIssue(), 1)) != - (((100ull - 16) << (64 - 8)) | 1000000000000000ull), + getRate(STAmount(10), STAmount(noIssue(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull), "STAmount getRate fail 8"); roundTest(1, 3, 3); @@ -493,14 +437,8 @@ public: testcase("underflow"); STAmount bigNative(STAmount::cMaxNative / 2); - STAmount bigValue( - noIssue(), - (STAmount::cMinValue + STAmount::cMaxValue) / 2, - STAmount::cMaxOffset - 1); - STAmount smallValue( - noIssue(), - (STAmount::cMinValue + STAmount::cMaxValue) / 2, - STAmount::cMinOffset + 1); + STAmount bigValue(noIssue(), (STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMaxOffset - 1); + STAmount smallValue(noIssue(), (STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMinOffset + 1); STAmount zeroSt(noIssue(), 0); STAmount smallXsmall = multiply(smallValue, smallValue, noIssue()); @@ -600,13 +538,10 @@ public: } { - BEAST_EXPECT( - amountFromJson(sfNumber, Json::Value(42)) == XRPAmount(42)); - BEAST_EXPECT( - amountFromJson(sfNumber, Json::Value(-42)) == XRPAmount(-42)); + BEAST_EXPECT(amountFromJson(sfNumber, Json::Value(42)) == XRPAmount(42)); + BEAST_EXPECT(amountFromJson(sfNumber, Json::Value(-42)) == XRPAmount(-42)); - BEAST_EXPECT( - amountFromJson(sfNumber, Json::UInt(42)) == XRPAmount(42)); + BEAST_EXPECT(amountFromJson(sfNumber, Json::UInt(42)) == XRPAmount(42)); BEAST_EXPECT(amountFromJson(sfNumber, "-123") == XRPAmount(-123)); @@ -614,29 +549,22 @@ public: BEAST_EXPECT(amountFromJson(sfNumber, "-123") == XRPAmount(-123)); BEAST_EXPECT(amountFromJson(sfNumber, "3.14e2") == XRPAmount(314)); - BEAST_EXPECT( - amountFromJson(sfNumber, "-3.14e2") == XRPAmount(-314)); + BEAST_EXPECT(amountFromJson(sfNumber, "-3.14e2") == XRPAmount(-314)); BEAST_EXPECT(amountFromJson(sfNumber, "0") == XRPAmount(0)); BEAST_EXPECT(amountFromJson(sfNumber, "-0") == XRPAmount(0)); constexpr auto imin = std::numeric_limits::min(); BEAST_EXPECT(amountFromJson(sfNumber, imin) == XRPAmount(imin)); - BEAST_EXPECT( - amountFromJson(sfNumber, std::to_string(imin)) == - XRPAmount(imin)); + BEAST_EXPECT(amountFromJson(sfNumber, std::to_string(imin)) == XRPAmount(imin)); constexpr auto imax = std::numeric_limits::max(); BEAST_EXPECT(amountFromJson(sfNumber, imax) == XRPAmount(imax)); - BEAST_EXPECT( - amountFromJson(sfNumber, std::to_string(imax)) == - XRPAmount(imax)); + BEAST_EXPECT(amountFromJson(sfNumber, std::to_string(imax)) == XRPAmount(imax)); constexpr auto umax = std::numeric_limits::max(); BEAST_EXPECT(amountFromJson(sfNumber, umax) == XRPAmount(umax)); - BEAST_EXPECT( - amountFromJson(sfNumber, std::to_string(umax)) == - XRPAmount(umax)); + BEAST_EXPECT(amountFromJson(sfNumber, std::to_string(umax)) == XRPAmount(umax)); // XRP does not handle fractional part try @@ -646,8 +574,7 @@ public: } catch (std::runtime_error const& e) { - std::string const expected = - "XRP and MPT must be specified as integral amount."; + std::string const expected = "XRP and MPT must be specified as integral amount."; BEAST_EXPECT(e.what() == expected); } @@ -659,8 +586,7 @@ public: } catch (std::runtime_error const& e) { - std::string const expected = - "XRP and MPT must be specified as integral amount."; + std::string const expected = "XRP and MPT must be specified as integral amount."; BEAST_EXPECT(e.what() == expected); } @@ -716,8 +642,7 @@ public: } catch (std::runtime_error const& e) { - std::string const expected = - "XRP may not be specified with a null Json value"; + std::string const expected = "XRP may not be specified with a null Json value"; BEAST_EXPECT(e.what() == expected); } @@ -804,8 +729,7 @@ public: Issue const usd{Currency(0x5553440000000000), AccountID(0x4985601)}; Issue const xrp{xrpIssue()}; - for (std::uint64_t drops = 100000000000000000; drops != 1; - drops = drops / 10) + for (std::uint64_t drops = 100000000000000000; drops != 1; drops = drops / 10) { auto const t = amountFromString(xrp, std::to_string(drops)); auto const s = t.xrp(); @@ -837,8 +761,7 @@ public: Issue const usd{Currency(0x5553440000000000), AccountID(0x4985601)}; Issue const xrp{xrpIssue()}; - for (std::uint64_t dollars = 10000000000; dollars != 1; - dollars = dollars / 10) + for (std::uint64_t dollars = 10000000000; dollars != 1; dollars = dollars / 10) { auto const t = amountFromString(usd, std::to_string(dollars)); auto const s = t.iou(); @@ -1021,8 +944,7 @@ public: // Overflow check for max MPT amounts { - STAmount amt1( - mpt, std::numeric_limits::max()); + STAmount amt1(mpt, std::numeric_limits::max()); STAmount amt2(mpt, 1); BEAST_EXPECT(canAdd(amt1, amt2) == false); } @@ -1194,8 +1116,7 @@ public: // Overflow check for max positive MPT amounts (should fail) { - STAmount amt1( - mpt, std::numeric_limits::max()); + STAmount amt1(mpt, std::numeric_limits::max()); STAmount amt2(mpt, -2); BEAST_EXPECT(canSubtract(amt1, amt2) == false); } diff --git a/src/test/protocol/STInteger_test.cpp b/src/test/protocol/STInteger_test.cpp index 73b4ca39ef..74340d53ea 100644 --- a/src/test/protocol/STInteger_test.cpp +++ b/src/test/protocol/STInteger_test.cpp @@ -21,9 +21,7 @@ struct STInteger_test : public beast::unit_test::suite // there is some special handling for sfTransactionResult STUInt8 tr(sfTransactionResult, 0); BEAST_EXPECT(tr.value() == 0); - BEAST_EXPECT( - tr.getText() == - "The transaction was applied. Only final in a validated ledger."); + BEAST_EXPECT(tr.getText() == "The transaction was applied. Only final in a validated ledger."); BEAST_EXPECT(tr.getSType() == STI_UINT8); BEAST_EXPECT(tr.getJson(JsonOptions::none) == "tesSUCCESS"); @@ -101,8 +99,7 @@ struct STInteger_test : public beast::unit_test::suite BEAST_EXPECT(u64_2.value() == 0xFFFFFFFFFFFFFFFFull); BEAST_EXPECT(u64_2.getText() == "18446744073709551615"); BEAST_EXPECT(u64_2.getSType() == STI_UINT64); - BEAST_EXPECT( - u64_2.getJson(JsonOptions::none) == "18446744073709551615"); + BEAST_EXPECT(u64_2.getJson(JsonOptions::none) == "18446744073709551615"); } void diff --git a/src/test/protocol/STIssue_test.cpp b/src/test/protocol/STIssue_test.cpp index d64722712b..cfd047e752 100644 --- a/src/test/protocol/STIssue_test.cpp +++ b/src/test/protocol/STIssue_test.cpp @@ -123,12 +123,8 @@ public: BEAST_EXPECT(STIssue(sfAsset, asset1) != asset3); BEAST_EXPECT(STIssue(sfAsset, asset1) == asset1); BEAST_EXPECT(STIssue(sfAsset, asset1).getText() == "XRP"); - BEAST_EXPECT( - STIssue(sfAsset, asset2).getText() == - "USD/rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn"); - BEAST_EXPECT( - STIssue(sfAsset, asset3).getText() == - "000000000000000000000000000000000000000000000002"); + BEAST_EXPECT(STIssue(sfAsset, asset2).getText() == "USD/rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn"); + BEAST_EXPECT(STIssue(sfAsset, asset3).getText() == "000000000000000000000000000000000000000000000002"); } void diff --git a/src/test/protocol/STNumber_test.cpp b/src/test/protocol/STNumber_test.cpp index 4e7a8388ee..a1a94accaa 100644 --- a/src/test/protocol/STNumber_test.cpp +++ b/src/test/protocol/STNumber_test.cpp @@ -40,16 +40,11 @@ struct STNumber_test : public beast::unit_test::suite } std::initializer_list const mantissas = { - std::numeric_limits::min(), - -1, - 0, - 1, - std::numeric_limits::max()}; + std::numeric_limits::min(), -1, 0, 1, std::numeric_limits::max()}; for (std::int64_t mantissa : mantissas) testCombo(Number{mantissa}); - std::initializer_list const exponents = { - Number::minExponent, -1, 0, 1, Number::maxExponent - 1}; + std::initializer_list const exponents = {Number::minExponent, -1, 0, 1, Number::maxExponent - 1}; for (std::int32_t exponent : exponents) testCombo(Number{123, exponent}); @@ -63,126 +58,71 @@ struct STNumber_test : public beast::unit_test::suite } { - BEAST_EXPECT( - numberFromJson(sfNumber, Json::Value(42)) == - STNumber(sfNumber, 42)); - BEAST_EXPECT( - numberFromJson(sfNumber, Json::Value(-42)) == - STNumber(sfNumber, -42)); + BEAST_EXPECT(numberFromJson(sfNumber, Json::Value(42)) == STNumber(sfNumber, 42)); + BEAST_EXPECT(numberFromJson(sfNumber, Json::Value(-42)) == STNumber(sfNumber, -42)); - BEAST_EXPECT( - numberFromJson(sfNumber, Json::UInt(42)) == - STNumber(sfNumber, 42)); + BEAST_EXPECT(numberFromJson(sfNumber, Json::UInt(42)) == STNumber(sfNumber, 42)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123)); + BEAST_EXPECT(numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123)); - BEAST_EXPECT( - numberFromJson(sfNumber, "123") == STNumber(sfNumber, 123)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123)); + BEAST_EXPECT(numberFromJson(sfNumber, "123") == STNumber(sfNumber, 123)); + BEAST_EXPECT(numberFromJson(sfNumber, "-123") == STNumber(sfNumber, -123)); - BEAST_EXPECT( - numberFromJson(sfNumber, "3.14") == - STNumber(sfNumber, Number(314, -2))); - BEAST_EXPECT( - numberFromJson(sfNumber, "-3.14") == - STNumber(sfNumber, -Number(314, -2))); - BEAST_EXPECT( - numberFromJson(sfNumber, "3.14e2") == STNumber(sfNumber, 314)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-3.14e2") == - STNumber(sfNumber, -314)); + BEAST_EXPECT(numberFromJson(sfNumber, "3.14") == STNumber(sfNumber, Number(314, -2))); + BEAST_EXPECT(numberFromJson(sfNumber, "-3.14") == STNumber(sfNumber, -Number(314, -2))); + BEAST_EXPECT(numberFromJson(sfNumber, "3.14e2") == STNumber(sfNumber, 314)); + BEAST_EXPECT(numberFromJson(sfNumber, "-3.14e2") == STNumber(sfNumber, -314)); - BEAST_EXPECT( - numberFromJson(sfNumber, "1000e-2") == STNumber(sfNumber, 10)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-1000e-2") == - STNumber(sfNumber, -10)); + BEAST_EXPECT(numberFromJson(sfNumber, "1000e-2") == STNumber(sfNumber, 10)); + BEAST_EXPECT(numberFromJson(sfNumber, "-1000e-2") == STNumber(sfNumber, -10)); - BEAST_EXPECT( - numberFromJson(sfNumber, "0") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "0.0") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "0.000") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-0") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-0.0") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-0.000") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "0e6") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "0.0e6") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "0.000e6") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-0e6") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-0.0e6") == STNumber(sfNumber, 0)); - BEAST_EXPECT( - numberFromJson(sfNumber, "-0.000e6") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "0") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "0.0") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "0.000") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "-0") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "-0.0") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "-0.000") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "0e6") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "0.0e6") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "0.000e6") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "-0e6") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "-0.0e6") == STNumber(sfNumber, 0)); + BEAST_EXPECT(numberFromJson(sfNumber, "-0.000e6") == STNumber(sfNumber, 0)); { NumberRoundModeGuard mg(Number::towards_zero); // maxint64 9,223,372,036,854,775,807 - auto const maxInt = - std::to_string(std::numeric_limits::max()); + auto const maxInt = std::to_string(std::numeric_limits::max()); // minint64 -9,223,372,036,854,775,808 - auto const minInt = - std::to_string(std::numeric_limits::min()); + auto const minInt = std::to_string(std::numeric_limits::min()); if (Number::getMantissaScale() == MantissaRange::small) { BEAST_EXPECT( - numberFromJson(sfNumber, maxInt) == - STNumber(sfNumber, Number{9'223'372'036'854'775, 3})); + numberFromJson(sfNumber, maxInt) == STNumber(sfNumber, Number{9'223'372'036'854'775, 3})); BEAST_EXPECT( - numberFromJson(sfNumber, minInt) == - STNumber(sfNumber, Number{-9'223'372'036'854'775, 3})); + numberFromJson(sfNumber, minInt) == STNumber(sfNumber, Number{-9'223'372'036'854'775, 3})); } else { BEAST_EXPECT( - numberFromJson(sfNumber, maxInt) == - STNumber( - sfNumber, Number{9'223'372'036'854'775'807, 0})); + numberFromJson(sfNumber, maxInt) == STNumber(sfNumber, Number{9'223'372'036'854'775'807, 0})); BEAST_EXPECT( numberFromJson(sfNumber, minInt) == - STNumber( - sfNumber, - Number{ - true, - 9'223'372'036'854'775'808ULL, - 0, - Number::normalized{}})); + STNumber(sfNumber, Number{true, 9'223'372'036'854'775'808ULL, 0, Number::normalized{}})); } } constexpr auto imin = std::numeric_limits::min(); - BEAST_EXPECT( - numberFromJson(sfNumber, imin) == - STNumber(sfNumber, Number(imin, 0))); - BEAST_EXPECT( - numberFromJson(sfNumber, std::to_string(imin)) == - STNumber(sfNumber, Number(imin, 0))); + BEAST_EXPECT(numberFromJson(sfNumber, imin) == STNumber(sfNumber, Number(imin, 0))); + BEAST_EXPECT(numberFromJson(sfNumber, std::to_string(imin)) == STNumber(sfNumber, Number(imin, 0))); constexpr auto imax = std::numeric_limits::max(); - BEAST_EXPECT( - numberFromJson(sfNumber, imax) == - STNumber(sfNumber, Number(imax, 0))); - BEAST_EXPECT( - numberFromJson(sfNumber, std::to_string(imax)) == - STNumber(sfNumber, Number(imax, 0))); + BEAST_EXPECT(numberFromJson(sfNumber, imax) == STNumber(sfNumber, Number(imax, 0))); + BEAST_EXPECT(numberFromJson(sfNumber, std::to_string(imax)) == STNumber(sfNumber, Number(imax, 0))); constexpr auto umax = std::numeric_limits::max(); - BEAST_EXPECT( - numberFromJson(sfNumber, umax) == - STNumber(sfNumber, Number(umax, 0))); - BEAST_EXPECT( - numberFromJson(sfNumber, std::to_string(umax)) == - STNumber(sfNumber, Number(umax, 0))); + BEAST_EXPECT(numberFromJson(sfNumber, umax) == STNumber(sfNumber, Number(umax, 0))); + BEAST_EXPECT(numberFromJson(sfNumber, std::to_string(umax)) == STNumber(sfNumber, Number(umax, 0))); // Obvious non-numbers tested here try diff --git a/src/test/protocol/STObject_test.cpp b/src/test/protocol/STObject_test.cpp index c01297b4e1..861a1ab967 100644 --- a/src/test/protocol/STObject_test.cpp +++ b/src/test/protocol/STObject_test.cpp @@ -13,8 +13,7 @@ public: unexpected(sfGeneric.isUseful(), "sfGeneric must not be useful"); { // Try to put sfGeneric in an SOTemplate. - except( - [&]() { SOTemplate elements{{sfGeneric, soeREQUIRED}}; }); + except([&]() { SOTemplate elements{{sfGeneric, soeREQUIRED}}; }); } unexpected(sfInvalid.isUseful(), "sfInvalid must not be useful"); @@ -32,8 +31,7 @@ public: } { // Try to put sfInvalid in an SOTemplate. - except( - [&]() { SOTemplate elements{{sfInvalid, soeREQUIRED}}; }); + except([&]() { SOTemplate elements{{sfInvalid, soeREQUIRED}}; }); } { // Try to put the same SField into an SOTemplate twice. @@ -63,21 +61,15 @@ public: STObject object1(elements, sfTestObject); STObject object2(object1); - unexpected( - object1.getSerializer() != object2.getSerializer(), - "STObject error 1"); + unexpected(object1.getSerializer() != object2.getSerializer(), "STObject error 1"); - unexpected( - object1.isFieldPresent(sfTestH256) || - !object1.isFieldPresent(sfTestVL), - "STObject error"); + unexpected(object1.isFieldPresent(sfTestH256) || !object1.isFieldPresent(sfTestVL), "STObject error"); object1.makeFieldPresent(sfTestH256); unexpected(!object1.isFieldPresent(sfTestH256), "STObject Error 2"); - unexpected( - object1.getFieldH256(sfTestH256) != uint256(), "STObject error 3"); + unexpected(object1.getFieldH256(sfTestH256) != uint256(), "STObject error 3"); if (object1.getSerializer() == object2.getSerializer()) { @@ -96,9 +88,7 @@ public: unexpected(object1.getFlags() != 0, "STObject error 6"); - unexpected( - object1.getSerializer() != object2.getSerializer(), - "STObject error 7"); + unexpected(object1.getSerializer() != object2.getSerializer(), "STObject error 7"); STObject copy(object1); @@ -106,15 +96,11 @@ public: unexpected(copy.isFieldPresent(sfTestH256), "STObject error 9"); - unexpected( - object1.getSerializer() != copy.getSerializer(), - "STObject error 10"); + unexpected(object1.getSerializer() != copy.getSerializer(), "STObject error 10"); copy.setFieldU32(sfTestU32, 1); - unexpected( - object1.getSerializer() == copy.getSerializer(), - "STObject error 11"); + unexpected(object1.getSerializer() == copy.getSerializer(), "STObject error 11"); for (int i = 0; i < 1000; i++) { @@ -339,11 +325,7 @@ public: { STObject st(sfGeneric); auto const v = ~st[~sf1Outer]; - static_assert( - std::is_same< - std::decay_t, - std::optional>::value, - ""); + static_assert(std::is_same, std::optional>::value, ""); } // UDT scalar fields @@ -397,8 +379,7 @@ public: { STObject st(sfGeneric); BEAST_EXPECT(!st[~sf5]); - auto const kp = generateKeyPair( - KeyType::secp256k1, generateSeed("masterpassphrase")); + auto const kp = generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")); st[sf5] = kp.first; st[~sf5] = std::nullopt; } @@ -418,11 +399,7 @@ public: BEAST_EXPECT(cst[~sf]->size() == 2); BEAST_EXPECT(cst[sf][0] == 1); BEAST_EXPECT(cst[sf][1] == 2); - static_assert( - std::is_same< - decltype(cst[sfIndexes]), - std::vector const&>::value, - ""); + static_assert(std::is_same const&>::value, ""); } // Default by reference field @@ -467,8 +444,7 @@ public: try { - std::array const payload{ - {0xe9, 0x12, 0xab, 0xcd, 0x12, 0xfe, 0xdc}}; + std::array const payload{{0xe9, 0x12, 0xab, 0xcd, 0x12, 0xfe, 0xdc}}; SerialIter sit{makeSlice(payload)}; auto obj = std::make_shared(sit, sfMetadata); BEAST_EXPECT(!obj); diff --git a/src/test/protocol/STParsedJSON_test.cpp b/src/test/protocol/STParsedJSON_test.cpp index 9c3a08243b..0ef7878cdc 100644 --- a/src/test/protocol/STParsedJSON_test.cpp +++ b/src/test/protocol/STParsedJSON_test.cpp @@ -260,9 +260,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfIndexNext)); - BEAST_EXPECT( - obj.object->getFieldU64(sfIndexNext) == - 18446744073709551615ull); + BEAST_EXPECT(obj.object->getFieldU64(sfIndexNext) == 18446744073709551615ull); } // Test min value for uint64 @@ -338,24 +336,8 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(obj.object->isFieldPresent(sfEmailHash)); BEAST_EXPECT(obj.object->getFieldH128(sfEmailHash).size() == 16); std::array expected = { - 0x01, - 0x23, - 0x45, - 0x67, - 0x89, - 0xAB, - 0xCD, - 0xEF, - 0x01, - 0x23, - 0x45, - 0x67, - 0x89, - 0xAB, - 0xCD, - 0xEF}; - BEAST_EXPECT( - obj.object->getFieldH128(sfEmailHash) == uint128{expected}); + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; + BEAST_EXPECT(obj.object->getFieldH128(sfEmailHash) == uint128{expected}); } // Valid lowercase hex string for UInt128 @@ -377,8 +359,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(obj.object->isFieldPresent(sfEmailHash)); auto const& h128 = obj.object->getFieldH128(sfEmailHash); BEAST_EXPECT(h128.size() == 16); - bool allZero = std::all_of( - h128.begin(), h128.end(), [](auto b) { return b == 0; }); + bool allZero = std::all_of(h128.begin(), h128.end(), [](auto b) { return b == 0; }); BEAST_EXPECT(allZero); } @@ -441,14 +422,10 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfTakerPaysCurrency)); - BEAST_EXPECT( - obj.object->getFieldH160(sfTakerPaysCurrency).size() == 20); - std::array expected = { - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, - 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67}; - BEAST_EXPECT( - obj.object->getFieldH160(sfTakerPaysCurrency) == - uint160{expected}); + BEAST_EXPECT(obj.object->getFieldH160(sfTakerPaysCurrency).size() == 20); + std::array expected = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67}; + BEAST_EXPECT(obj.object->getFieldH160(sfTakerPaysCurrency) == uint160{expected}); } // Valid lowercase hex string for UInt160 { @@ -457,8 +434,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfTakerPaysCurrency)); - BEAST_EXPECT( - obj.object->getFieldH160(sfTakerPaysCurrency).size() == 20); + BEAST_EXPECT(obj.object->getFieldH160(sfTakerPaysCurrency).size() == 20); } // Empty string for UInt160 (should be valid, all zero) @@ -470,8 +446,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(obj.object->isFieldPresent(sfTakerPaysCurrency)); auto const& h160 = obj.object->getFieldH160(sfTakerPaysCurrency); BEAST_EXPECT(h160.size() == 20); - bool allZero = std::all_of( - h160.begin(), h160.end(), [](auto b) { return b == 0; }); + bool allZero = std::all_of(h160.begin(), h160.end(), [](auto b) { return b == 0; }); BEAST_EXPECT(allZero); } @@ -494,8 +469,7 @@ class STParsedJSON_test : public beast::unit_test::suite // Hex string too long for UInt160 (should fail) { Json::Value j; - j[sfTakerPaysCurrency] = - "0123456789ABCDEF0123456789ABCDEF0123456789"; + j[sfTakerPaysCurrency] = "0123456789ABCDEF0123456789ABCDEF0123456789"; STParsedJSONObject obj("Test", j); BEAST_EXPECT(!obj.object.has_value()); } @@ -523,32 +497,24 @@ class STParsedJSON_test : public beast::unit_test::suite testcase("UInt192"); { Json::Value j; - j[sfMPTokenIssuanceID] = - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; + j[sfMPTokenIssuanceID] = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfMPTokenIssuanceID)); - BEAST_EXPECT( - obj.object->getFieldH192(sfMPTokenIssuanceID).size() == 24); - std::array expected = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - BEAST_EXPECT( - obj.object->getFieldH192(sfMPTokenIssuanceID) == - uint192{expected}); + BEAST_EXPECT(obj.object->getFieldH192(sfMPTokenIssuanceID).size() == 24); + std::array expected = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + BEAST_EXPECT(obj.object->getFieldH192(sfMPTokenIssuanceID) == uint192{expected}); } // Valid lowercase hex string for UInt192 { Json::Value j; - j[sfMPTokenIssuanceID] = - "ffffffffffffffffffffffffffffffffffffffffffffffff"; + j[sfMPTokenIssuanceID] = "ffffffffffffffffffffffffffffffffffffffffffffffff"; STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfMPTokenIssuanceID)); - BEAST_EXPECT( - obj.object->getFieldH192(sfMPTokenIssuanceID).size() == 24); + BEAST_EXPECT(obj.object->getFieldH192(sfMPTokenIssuanceID).size() == 24); } // Empty string for UInt192 (should be valid, all zero) @@ -560,16 +526,14 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(obj.object->isFieldPresent(sfMPTokenIssuanceID)); auto const& h192 = obj.object->getFieldH192(sfMPTokenIssuanceID); BEAST_EXPECT(h192.size() == 24); - bool allZero = std::all_of( - h192.begin(), h192.end(), [](auto b) { return b == 0; }); + bool allZero = std::all_of(h192.begin(), h192.end(), [](auto b) { return b == 0; }); BEAST_EXPECT(allZero); } // Odd-length hex string for UInt192 (should fail) { Json::Value j; - j[sfMPTokenIssuanceID] = - "0123456789ABCDEF0123456789ABCDEF0123456789ABCDE"; + j[sfMPTokenIssuanceID] = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDE"; STParsedJSONObject obj("Test", j); BEAST_EXPECT(!obj.object.has_value()); } @@ -593,8 +557,7 @@ class STParsedJSON_test : public beast::unit_test::suite // Hex string too long for UInt192 (should fail) { Json::Value j; - j[sfMPTokenIssuanceID] = - "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF00"; + j[sfMPTokenIssuanceID] = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF00"; STParsedJSONObject obj("Test", j); BEAST_EXPECT(!obj.object.has_value()); } @@ -630,13 +593,10 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfLedgerHash)); BEAST_EXPECT(obj.object->getFieldH256(sfLedgerHash).size() == 32); - std::array expected = { - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; - BEAST_EXPECT( - obj.object->getFieldH256(sfLedgerHash) == uint256{expected}); + std::array expected = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, + 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, + 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; + BEAST_EXPECT(obj.object->getFieldH256(sfLedgerHash) == uint256{expected}); } // Valid lowercase hex string for UInt256 { @@ -659,8 +619,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(obj.object->isFieldPresent(sfLedgerHash)); auto const& h256 = obj.object->getFieldH256(sfLedgerHash); BEAST_EXPECT(h256.size() == 32); - bool allZero = std::all_of( - h256.begin(), h256.end(), [](auto b) { return b == 0; }); + bool allZero = std::all_of(h256.begin(), h256.end(), [](auto b) { return b == 0; }); BEAST_EXPECT(allZero); } @@ -750,9 +709,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); if (BEAST_EXPECT(obj.object->isFieldPresent(sfLoanScale))) - BEAST_EXPECT( - obj.object->getFieldI32(sfLoanScale) == - static_cast(maxUInt32)); + BEAST_EXPECT(obj.object->getFieldI32(sfLoanScale) == static_cast(maxUInt32)); } // Test with string value @@ -762,8 +719,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); if (BEAST_EXPECT(obj.object->isFieldPresent(sfLoanScale))) - BEAST_EXPECT( - obj.object->getFieldI32(sfLoanScale) == 2147483647u); + BEAST_EXPECT(obj.object->getFieldI32(sfLoanScale) == 2147483647u); } // Test with string negative value @@ -987,8 +943,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(obj.object->isFieldPresent(sfAccount)); auto const& acct = obj.object->getAccountID(sfAccount); BEAST_EXPECT(acct.size() == 20); - BEAST_EXPECT( - toBase58(acct) == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"); + BEAST_EXPECT(toBase58(acct) == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"); } // Valid hex string for AccountID @@ -1172,9 +1127,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfAmount)); - BEAST_EXPECT( - obj.object->getFieldAmount(sfAmount) == - STAmount(100000000000000000ull)); + BEAST_EXPECT(obj.object->getFieldAmount(sfAmount) == STAmount(100000000000000000ull)); } // Test with int value for Amount @@ -1184,8 +1137,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfAmount)); - BEAST_EXPECT( - obj.object->getFieldAmount(sfAmount) == STAmount(4294967295u)); + BEAST_EXPECT(obj.object->getFieldAmount(sfAmount) == STAmount(4294967295u)); } // Test with decimal string for Amount (should fail) @@ -1245,15 +1197,9 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!ps.empty()); BEAST_EXPECT(ps.size() == 1); BEAST_EXPECT(ps[0].size() == 1); - BEAST_EXPECT( - ps[0][0].getAccountID() == - parseBase58( - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")); + BEAST_EXPECT(ps[0][0].getAccountID() == parseBase58("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")); BEAST_EXPECT(to_string(ps[0][0].getCurrency()) == "USD"); - BEAST_EXPECT( - ps[0][0].getIssuerID() == - parseBase58( - "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe")); + BEAST_EXPECT(ps[0][0].getIssuerID() == parseBase58("rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe")); } } @@ -1428,10 +1374,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(issue.currency.size() == 20); BEAST_EXPECT(to_string(issue.currency) == "USD"); BEAST_EXPECT(issue.account.size() == 20); - BEAST_EXPECT( - issue.account == - parseBase58( - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")); + BEAST_EXPECT(issue.account == parseBase58("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")); } } @@ -1457,8 +1400,7 @@ class STParsedJSON_test : public beast::unit_test::suite { Json::Value j; Json::Value issueJson(Json::objectValue); - issueJson["mpt_issuance_id"] = - "0000000000000000000000004D5054494431323334234234"; + issueJson["mpt_issuance_id"] = "0000000000000000000000004D5054494431323334234234"; j[sfAsset] = issueJson; STParsedJSONObject obj("Test", j); if (BEAST_EXPECT(obj.object.has_value())) @@ -1567,10 +1509,8 @@ class STParsedJSON_test : public beast::unit_test::suite { BEAST_EXPECT(obj.object->isFieldPresent(sfXChainBridge)); auto const& bridgeField = (*obj.object)[sfXChainBridge]; - BEAST_EXPECT( - bridgeField->lockingChainIssue().currency.size() == 20); - BEAST_EXPECT( - bridgeField->issuingChainIssue().currency.size() == 20); + BEAST_EXPECT(bridgeField->lockingChainIssue().currency.size() == 20); + BEAST_EXPECT(bridgeField->issuingChainIssue().currency.size() == 20); } } @@ -1579,12 +1519,10 @@ class STParsedJSON_test : public beast::unit_test::suite Json::Value j; Json::Value bridge(Json::objectValue); Json::Value issuingChainIssue(Json::objectValue); - issuingChainIssue["currency"] = - "0123456789ABCDEF01230123456789ABCDEF0123"; + issuingChainIssue["currency"] = "0123456789ABCDEF01230123456789ABCDEF0123"; issuingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; Json::Value lockingChainIssue(Json::objectValue); - lockingChainIssue["currency"] = - "0123456789ABCDEF01230123456789ABCDEF0123"; + lockingChainIssue["currency"] = "0123456789ABCDEF01230123456789ABCDEF0123"; lockingChainIssue["issuer"] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; bridge["LockingChainIssue"] = lockingChainIssue; bridge["IssuingChainIssue"] = issuingChainIssue; @@ -1596,10 +1534,8 @@ class STParsedJSON_test : public beast::unit_test::suite { BEAST_EXPECT(obj.object->isFieldPresent(sfXChainBridge)); auto const& bridgeField = (*obj.object)[sfXChainBridge]; - BEAST_EXPECT( - bridgeField->lockingChainIssue().currency.size() == 20); - BEAST_EXPECT( - bridgeField->issuingChainIssue().currency.size() == 20); + BEAST_EXPECT(bridgeField->lockingChainIssue().currency.size() == 20); + BEAST_EXPECT(bridgeField->issuingChainIssue().currency.size() == 20); } } @@ -1749,9 +1685,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfNumber)); - BEAST_EXPECT( - obj.object->getFieldNumber(sfNumber).value() == - Number(12345, 0)); + BEAST_EXPECT(obj.object->getFieldNumber(sfNumber).value() == Number(12345, 0)); } // Valid uint value for STNumber @@ -1761,9 +1695,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfNumber)); - BEAST_EXPECT( - obj.object->getFieldNumber(sfNumber).value() == - Number(12345, 0)); + BEAST_EXPECT(obj.object->getFieldNumber(sfNumber).value() == Number(12345, 0)); } // Valid string integer value for STNumber @@ -1773,9 +1705,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfNumber)); - BEAST_EXPECT( - obj.object->getFieldNumber(sfNumber).value() == - Number(67890, 0)); + BEAST_EXPECT(obj.object->getFieldNumber(sfNumber).value() == Number(67890, 0)); } // Valid negative integer value for STNumber @@ -1785,8 +1715,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfNumber)); - BEAST_EXPECT( - obj.object->getFieldNumber(sfNumber).value() == Number(-42, 0)); + BEAST_EXPECT(obj.object->getFieldNumber(sfNumber).value() == Number(-42, 0)); } // Valid string negative integer value for STNumber @@ -1796,9 +1725,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfNumber)); - BEAST_EXPECT( - obj.object->getFieldNumber(sfNumber).value() == - Number(-123, 0)); + BEAST_EXPECT(obj.object->getFieldNumber(sfNumber).value() == Number(-123, 0)); } // Valid floating point value for STNumber @@ -1809,9 +1736,7 @@ class STParsedJSON_test : public beast::unit_test::suite if (BEAST_EXPECT(obj.object.has_value())) { BEAST_EXPECT(obj.object->isFieldPresent(sfNumber)); - BEAST_EXPECT( - obj.object->getFieldNumber(sfNumber).value() == - Number(314159, -5)); + BEAST_EXPECT(obj.object->getFieldNumber(sfNumber).value() == Number(314159, -5)); } } @@ -1861,8 +1786,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject obj("Test", j); BEAST_EXPECT(obj.object.has_value()); BEAST_EXPECT(obj.object->isFieldPresent(sfTransactionMetaData)); - auto const& result = - obj.object->peekFieldObject(sfTransactionMetaData); + auto const& result = obj.object->peekFieldObject(sfTransactionMetaData); BEAST_EXPECT(result.getFieldU8(sfTransactionResult) == 1); } @@ -2063,8 +1987,7 @@ class STParsedJSON_test : public beast::unit_test::suite catch (std::runtime_error& e) { std::string what(e.what()); - unexpected( - what.find("First level children of `Template`") != 0); + unexpected(what.find("First level children of `Template`") != 0); } } } @@ -2089,20 +2012,17 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject parsed("test", jv); if (BEAST_EXPECT(parsed.object)) { - std::string const& serialized( - to_string(parsed.object->getJson(JsonOptions::none))); + std::string const& serialized(to_string(parsed.object->getJson(JsonOptions::none))); BEAST_EXPECT(serialized == goodJson); } } } { - std::string const goodJson( - R"({"CloseResolution":19,"Method":"250",)" - R"("TransactionResult":"tecFROZEN"})"); - std::string const expectedJson( - R"({"CloseResolution":19,"Method":250,)" - R"("TransactionResult":"tecFROZEN"})"); + std::string const goodJson(R"({"CloseResolution":19,"Method":"250",)" + R"("TransactionResult":"tecFROZEN"})"); + std::string const expectedJson(R"({"CloseResolution":19,"Method":250,)" + R"("TransactionResult":"tecFROZEN"})"); Json::Value jv; if (BEAST_EXPECT(parseJSONString(goodJson, jv))) @@ -2113,20 +2033,17 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject parsed("test", jv); if (BEAST_EXPECT(parsed.object)) { - std::string const& serialized( - to_string(parsed.object->getJson(JsonOptions::none))); + std::string const& serialized(to_string(parsed.object->getJson(JsonOptions::none))); BEAST_EXPECT(serialized == expectedJson); } } } { - std::string const goodJson( - R"({"CloseResolution":"19","Method":"250",)" - R"("TransactionResult":"tecFROZEN"})"); - std::string const expectedJson( - R"({"CloseResolution":19,"Method":250,)" - R"("TransactionResult":"tecFROZEN"})"); + std::string const goodJson(R"({"CloseResolution":"19","Method":"250",)" + R"("TransactionResult":"tecFROZEN"})"); + std::string const expectedJson(R"({"CloseResolution":19,"Method":250,)" + R"("TransactionResult":"tecFROZEN"})"); Json::Value jv; if (BEAST_EXPECT(parseJSONString(goodJson, jv))) @@ -2137,8 +2054,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject parsed("test", jv); if (BEAST_EXPECT(parsed.object)) { - std::string const& serialized( - to_string(parsed.object->getJson(JsonOptions::none))); + std::string const& serialized(to_string(parsed.object->getJson(JsonOptions::none))); BEAST_EXPECT(serialized == expectedJson); } } @@ -2155,9 +2071,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!parsed.object); BEAST_EXPECT(parsed.error); BEAST_EXPECT(parsed.error[jss::error] == "invalidParams"); - BEAST_EXPECT( - parsed.error[jss::error_message] == - "Field 'test.TransactionResult' is out of range."); + BEAST_EXPECT(parsed.error[jss::error_message] == "Field 'test.TransactionResult' is out of range."); } } @@ -2172,16 +2086,13 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!parsed.object); BEAST_EXPECT(parsed.error); BEAST_EXPECT(parsed.error[jss::error] == "invalidParams"); - BEAST_EXPECT( - parsed.error[jss::error_message] == - "Field 'test.Method' has bad type."); + BEAST_EXPECT(parsed.error[jss::error_message] == "Field 'test.Method' has bad type."); } } { - std::string const json( - R"({"CloseResolution":19,"Method":3294967296,)" - R"("TransactionResult":"tesSUCCESS"})"); + std::string const json(R"({"CloseResolution":19,"Method":3294967296,)" + R"("TransactionResult":"tesSUCCESS"})"); Json::Value jv; if (BEAST_EXPECT(parseJSONString(json, jv))) @@ -2190,9 +2101,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!parsed.object); BEAST_EXPECT(parsed.error); BEAST_EXPECT(parsed.error[jss::error] == "invalidParams"); - BEAST_EXPECT( - parsed.error[jss::error_message] == - "Field 'test.Method' is out of range."); + BEAST_EXPECT(parsed.error[jss::error_message] == "Field 'test.Method' is out of range."); } } @@ -2207,16 +2116,13 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!parsed.object); BEAST_EXPECT(parsed.error); BEAST_EXPECT(parsed.error[jss::error] == "invalidParams"); - BEAST_EXPECT( - parsed.error[jss::error_message] == - "Field 'test.CloseResolution' is out of range."); + BEAST_EXPECT(parsed.error[jss::error_message] == "Field 'test.CloseResolution' is out of range."); } } { - std::string const json( - R"({"CloseResolution":19,"Method":3.141592653,)" - R"("TransactionResult":"tesSUCCESS"})"); + std::string const json(R"({"CloseResolution":19,"Method":3.141592653,)" + R"("TransactionResult":"tesSUCCESS"})"); Json::Value jv; if (BEAST_EXPECT(parseJSONString(json, jv))) @@ -2225,18 +2131,15 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!parsed.object); BEAST_EXPECT(parsed.error); BEAST_EXPECT(parsed.error[jss::error] == "invalidParams"); - BEAST_EXPECT( - parsed.error[jss::error_message] == - "Field 'test.Method' has bad type."); + BEAST_EXPECT(parsed.error[jss::error_message] == "Field 'test.Method' has bad type."); } } { std::string const goodJson(R"({"CloseResolution":19,"Method":250,)" R"("TransferFee":"65535"})"); - std::string const expectedJson( - R"({"CloseResolution":19,"Method":250,)" - R"("TransferFee":65535})"); + std::string const expectedJson(R"({"CloseResolution":19,"Method":250,)" + R"("TransferFee":65535})"); Json::Value jv; if (BEAST_EXPECT(parseJSONString(goodJson, jv))) @@ -2244,8 +2147,7 @@ class STParsedJSON_test : public beast::unit_test::suite STParsedJSONObject parsed("test", jv); if (BEAST_EXPECT(parsed.object)) { - std::string const& serialized( - to_string(parsed.object->getJson(JsonOptions::none))); + std::string const& serialized(to_string(parsed.object->getJson(JsonOptions::none))); BEAST_EXPECT(serialized == expectedJson); } } @@ -2262,9 +2164,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!parsed.object); BEAST_EXPECT(parsed.error); BEAST_EXPECT(parsed.error[jss::error] == "invalidParams"); - BEAST_EXPECT( - parsed.error[jss::error_message] == - "Field 'test.TransferFee' has invalid data."); + BEAST_EXPECT(parsed.error[jss::error_message] == "Field 'test.TransferFee' has invalid data."); } } @@ -2279,9 +2179,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!parsed.object); BEAST_EXPECT(parsed.error); BEAST_EXPECT(parsed.error[jss::error] == "invalidParams"); - BEAST_EXPECT( - parsed.error[jss::error_message] == - "Field 'test.TransferFee' has invalid data."); + BEAST_EXPECT(parsed.error[jss::error_message] == "Field 'test.TransferFee' has invalid data."); } } @@ -2296,9 +2194,7 @@ class STParsedJSON_test : public beast::unit_test::suite BEAST_EXPECT(!parsed.object); BEAST_EXPECT(parsed.error); BEAST_EXPECT(parsed.error[jss::error] == "invalidParams"); - BEAST_EXPECT( - parsed.error[jss::error_message] == - "Field 'test.TransferFee' has bad type."); + BEAST_EXPECT(parsed.error[jss::error_message] == "Field 'test.TransferFee' has bad type."); } } } diff --git a/src/test/protocol/STTx_test.cpp b/src/test/protocol/STTx_test.cpp index 1899b786f9..853ff35635 100644 --- a/src/test/protocol/STTx_test.cpp +++ b/src/test/protocol/STTx_test.cpp @@ -21,8 +21,7 @@ namespace xrpl { inline bool matches(char const* string, char const* regex) { - return std::regex_search( - string, std::basic_regex(regex, std::regex_constants::icase)); + return std::regex_search(string, std::basic_regex(regex, std::regex_constants::icase)); } class STTx_test : public beast::unit_test::suite @@ -48,1323 +47,814 @@ public: { testcase("Malformed serialized form"); - constexpr unsigned char payload1[] = { - 0x0a, 0xff, 0xff, 0xff, 0xff, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, - 0x1b, 0x1b, 0x29, 0x1b, 0x1b, 0x1b, 0x1b, 0xef, 0xef, 0xef, - 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef}; + constexpr unsigned char payload1[] = {0x0a, 0xff, 0xff, 0xff, 0xff, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1b, 0x1b, 0x29, 0x1b, 0x1b, 0x1b, 0x1b, 0xef, 0xef, 0xef, + 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef}; constexpr unsigned char payload2[] = { - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, - 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, - 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, - 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, - 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, - 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, - 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xe7, 0xe7, - 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, - 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, - 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, - 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, - 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, - 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, - 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xe7, 0xe7, 0x29, 0xe7, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, - 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, - 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, - 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, - 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, - 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, - 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, - 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, - 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, - 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, - 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, - 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0x3b, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, - 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, - 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, - 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, - 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, - 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, - 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, - 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, - 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, - 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, - 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, - 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, - 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, - 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, - 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, - 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, - 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xe7, 0x27, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, - 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, - 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, - 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, - 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, - 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, - 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, - 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, - 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, - 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, - 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, - 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, - 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, - 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x14, - 0x14, 0x14, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, - 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, - 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, - 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, - 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, - 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, - 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, - 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, - 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, - 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xe7, 0x27, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, - 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xda, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, - 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, - 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, - 0x3b, 0x3b, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, - 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, - 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, - 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, - 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, - 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, - 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, - 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0x29, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, - 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, - 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xef, 0xff, - 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, - 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, - 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, - 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, - 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, - 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, - 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, - 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, - 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, - 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, - 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0xff, 0xef, - 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0x3b, 0x3b, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x7f, - 0x3b, 0x3b, 0xef, 0xfd, 0xf1, 0xff, 0xf1, 0xff, 0xf1, 0xfb, 0xef, - 0xfd, 0xf1, 0xff, 0xf1, 0xfd, 0xf1, 0xfb, 0xf1, 0xfd, 0xf1, 0xef, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0xff, 0xef, 0xff, 0x01, 0x00, 0xfd, 0xf1, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, - 0xef, 0x3b, 0x3b, 0x43, 0x3b, 0x3b, 0xff, 0x3b, 0x12, 0xf1, 0x12, - 0x12, 0x12, 0xff}; + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, + 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, + 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, + 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, + 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, + 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, + 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, + 0x26, 0xdf, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, + 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, + 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, + 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, + 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, + 0x12, 0x12, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, + 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, + 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, + 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, + 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, + 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, + 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, + 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, + 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, + 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, + 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, + 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, + 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, + 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xe7, 0x27, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, + 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, + 0x12, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, + 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, + 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, + 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, + 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, + 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, + 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, + 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, + 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, + 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, + 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, + 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, + 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, + 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, + 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, + 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, + 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, + 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, + 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x14, 0x14, 0x14, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, + 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, + 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, + 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, + 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, + 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, + 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, + 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, + 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xda, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, + 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, + 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, + 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12, 0x12, + 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0x29, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, + 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, + 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, + 0xe7, 0x12, 0x12, 0x12, 0x12, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, + 0x3b, 0x27, 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0x29, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xef, + 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, + 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xe7, 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, + 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, + 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xf4, 0xef, 0x3b, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3b, 0x3b, + 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, + 0xdf, 0xff, 0x3b, 0x3b, 0x3b, 0x3b, 0x29, 0x2b, 0x3b, 0x18, 0x3b, 0x3b, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xed, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0x3b, 0x3b, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, + 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, + 0xe7, 0xff, 0xe7, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, + 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x26, 0xdf, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xec, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, + 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, + 0xff, 0xef, 0xff, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3b, 0x3b, 0x3b, 0x27, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xef, + 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0xef, 0xff, 0xef, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, + 0xe7, 0x3b, 0x3b, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0xff, + 0xef, 0xef, 0xff, 0xef, 0xef, 0xff, 0xef, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x7f, 0x3b, 0x3b, 0xef, 0xfd, 0xf1, 0xff, 0xf1, 0xff, 0xf1, 0xfb, 0xef, 0xfd, 0xf1, 0xff, 0xf1, 0xfd, + 0xf1, 0xfb, 0xf1, 0xfd, 0xf1, 0xef, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0x01, 0x00, 0xfd, 0xf1, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xff, 0xef, 0xff, 0xef, 0xff, 0xef, 0x3b, 0x3b, 0x43, + 0x3b, 0x3b, 0xff, 0x3b, 0x12, 0xf1, 0x12, 0x12, 0x12, 0xff}; constexpr unsigned char payload3[] = { - 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, - 0x4f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, - 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x1e, 0x00, 0x4f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, - 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x24, 0x59, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x54, 0x72, 0x61, 0x6e, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20, 0xf6, - 0x00, 0x00, 0x03, 0x1f, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, - 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, - 0x10, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe}; + 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x4f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, + 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x4f, 0x00, + 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x24, 0x59, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x54, 0x72, 0x61, 0x6e, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, + 0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20, 0xf6, + 0x00, 0x00, 0x03, 0x1f, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x73, + 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe}; constexpr unsigned char payload4[] = { - 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, - 0x4f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, - 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, - 0x00, 0x20, 0x1e, 0x00, 0x4f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, - 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x24, 0x59, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x54, 0x72, 0x61, 0x6e, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, - 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20, - 0xf6, 0x00, 0x00, 0x03, 0x1f, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00, 0x81, 0x14, - 0x00, 0x10, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe}; + 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x4f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, + 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, 0x00, + 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x4f, + 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x24, 0x59, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x54, 0x72, 0x61, 0x6e, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20, + 0xf6, 0x00, 0x00, 0x03, 0x1f, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, + 0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xfe}; // Construct an STObject with 11 levels of object nesting so the // maximum nesting level exception is thrown. @@ -1379,14 +869,12 @@ public: // Make an STObject that nests objects ten levels deep. There's // a minimum transaction size we must meet, so include a hash256. uint256 const hash{42u}; - auto inner = - std::make_unique(recurse, sfTransactionMetaData); + auto inner = std::make_unique(recurse, sfTransactionMetaData); inner->setFieldH256(sfTransactionHash, hash); for (int i = 1; i < 10; ++i) { - auto outer = - std::make_unique(recurse, sfTransactionMetaData); + auto outer = std::make_unique(recurse, sfTransactionMetaData); outer->set(std::move(inner)); outer->setFieldH256(sfTransactionHash, hash); inner = std::move(outer); @@ -1422,10 +910,7 @@ public: } catch (std::runtime_error const& ex) { - BEAST_EXPECT( - std::strcmp( - ex.what(), "Maximum nesting depth of STVar exceeded") == - 0); + BEAST_EXPECT(std::strcmp(ex.what(), "Maximum nesting depth of STVar exceeded") == 0); } } { @@ -1488,10 +973,7 @@ public: } catch (std::runtime_error const& ex) { - BEAST_EXPECT( - std::strcmp( - ex.what(), "Maximum nesting depth of STVar exceeded") == - 0); + BEAST_EXPECT(std::strcmp(ex.what(), "Maximum nesting depth of STVar exceeded") == 0); } } @@ -1529,8 +1011,7 @@ public: } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp(ex.what(), "Duplicate field detected") == 0); + BEAST_EXPECT(strcmp(ex.what(), "Duplicate field detected") == 0); } } @@ -1580,8 +1061,7 @@ public: } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp(ex.what(), "gFID: uncommon name out of range 0") == 0); + BEAST_EXPECT(strcmp(ex.what(), "gFID: uncommon name out of range 0") == 0); } try @@ -1614,8 +1094,7 @@ public: Rules const defaultRules{presets}; BEAST_EXPECT(!defaultRules.enabled(featureAMM)); - unexpected( - !j.checkSign(defaultRules), "Transaction fails signature test"); + unexpected(!j.checkSign(defaultRules), "Transaction fails signature test"); Serializer rawTxn; j.add(rawTxn); @@ -1640,8 +1119,7 @@ public: if (STObject(j) != parsed.object) { log << "ORIG: " << j.getJson(JsonOptions::none) << '\n' - << "BUILT " << parsed.object->getJson(JsonOptions::none) - << std::endl; + << "BUILT " << parsed.object->getJson(JsonOptions::none) << std::endl; fail("Built a different transaction"); } else @@ -1669,8 +1147,7 @@ public: payment.setFieldAmount(sfAmount, STAmount(10000000000ull)); payment.setFieldAmount(sfFee, STAmount(10ull)); payment.setFieldU32(sfSequence, 1); - payment.setFieldVL( - sfSigningPubKey, Slice(kp1.first.data(), kp1.first.size())); + payment.setFieldVL(sfSigningPubKey, Slice(kp1.first.data(), kp1.first.size())); return payment; }; { @@ -1700,8 +1177,7 @@ public: { got = err.what(); } - BEAST_EXPECT( - got == "Field 'Paths' may not be explicitly set to default."); + BEAST_EXPECT(got == "Field 'Paths' may not be explicitly set to default."); } { // Make a Payment with an extra "SignerWeight" field. @@ -1717,8 +1193,7 @@ public: { got = err.what(); } - BEAST_EXPECT( - got == "Field 'SignerWeight' found in disallowed location."); + BEAST_EXPECT(got == "Field 'SignerWeight' found in disallowed location."); } { // Make a Payment that is missing the required Fee field. @@ -1776,31 +1251,30 @@ public: // the bad ones. // This lambda contains the bulk of the test code. - auto testMalformedSigningAccount = - [this, &txn](STObject const& signer, bool expectPass) { - // Create SigningAccounts array. - STArray signers(sfSigners, 1); - signers.push_back(signer); + auto testMalformedSigningAccount = [this, &txn](STObject const& signer, bool expectPass) { + // Create SigningAccounts array. + STArray signers(sfSigners, 1); + signers.push_back(signer); - // Insert signers into transaction. - STTx tempTxn(txn); - tempTxn.setFieldArray(sfSigners, signers); + // Insert signers into transaction. + STTx tempTxn(txn); + tempTxn.setFieldArray(sfSigners, signers); - Serializer rawTxn; - tempTxn.add(rawTxn); - SerialIter sit(rawTxn.slice()); - bool serialized = false; - try - { - STTx copy(sit); - serialized = true; - } - catch (std::exception const&) - { - ; // If it threw then serialization failed. - } - BEAST_EXPECT(serialized == expectPass); - }; + Serializer rawTxn; + tempTxn.add(rawTxn); + SerialIter sit(rawTxn.slice()); + bool serialized = false; + try + { + STTx copy(sit); + serialized = true; + } + catch (std::exception const&) + { + ; // If it threw then serialization failed. + } + BEAST_EXPECT(serialized == expectPass); + }; { // Test case 1. Make a valid Signer object. diff --git a/src/test/protocol/STValidation_test.cpp b/src/test/protocol/STValidation_test.cpp index 3530d2f34a..0c0951fde2 100644 --- a/src/test/protocol/STValidation_test.cpp +++ b/src/test/protocol/STValidation_test.cpp @@ -14,146 +14,109 @@ class STValidation_test : public beast::unit_test::suite { // No public key: static constexpr std::uint8_t payload1[] = { - 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, - 0x47, 0x31, 0x1A, 0x3A, 0x4E, 0x69, 0x6B, 0x2B, 0x54, 0x69, 0x66, 0x66, - 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, 0xF8, 0x3E, - 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, 0x8C, 0xDE, 0xB8, - 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, - 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, - 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, 0x35, 0x28, 0xEB, - 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x76, 0x47, 0x30, 0x45, 0x02, - 0x21, 0x00, 0xAF, 0x1D, 0x17, 0xA2, 0x12, 0x7B, 0xA4, 0x6B, 0x40, 0xBD, - 0x58, 0x76, 0x39, 0x3F, 0xF4, 0x49, 0x6B, 0x25, 0xA1, 0xAD, 0xB7, 0x36, - 0xFB, 0x64, 0x4C, 0x05, 0x21, 0x0C, 0x43, 0x02, 0xE5, 0xEE, 0x02, 0x20, - 0x26, 0x01, 0x7C, 0x5F, 0x69, 0xDA, 0xD1, 0xC3, 0x28, 0xED, 0x80, 0x05, - 0x36, 0x86, 0x8B, 0x1B, 0x22, 0xE4, 0x8E, 0x09, 0x11, 0x52, 0x28, 0x5A, - 0x48, 0x8F, 0x98, 0x7A, 0x5A, 0x10, 0x74, 0xCC}; + 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, 0x47, 0x31, 0x1A, 0x3A, 0x4E, + 0x69, 0x6B, 0x2B, 0x54, 0x69, 0x66, 0x66, 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, + 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, + 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, + 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, 0x35, 0x28, 0xEB, 0xD9, + 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x76, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xAF, 0x1D, 0x17, 0xA2, + 0x12, 0x7B, 0xA4, 0x6B, 0x40, 0xBD, 0x58, 0x76, 0x39, 0x3F, 0xF4, 0x49, 0x6B, 0x25, 0xA1, 0xAD, 0xB7, + 0x36, 0xFB, 0x64, 0x4C, 0x05, 0x21, 0x0C, 0x43, 0x02, 0xE5, 0xEE, 0x02, 0x20, 0x26, 0x01, 0x7C, 0x5F, + 0x69, 0xDA, 0xD1, 0xC3, 0x28, 0xED, 0x80, 0x05, 0x36, 0x86, 0x8B, 0x1B, 0x22, 0xE4, 0x8E, 0x09, 0x11, + 0x52, 0x28, 0x5A, 0x48, 0x8F, 0x98, 0x7A, 0x5A, 0x10, 0x74, 0xCC}; // Short public key: static constexpr std::uint8_t payload2[] = { - 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, - 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, - 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, - 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, - 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, - 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, - 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x20, - 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, - 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, - 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x76, 0x46, 0x30, 0x44, - 0x02, 0x20, 0x34, 0x89, 0xA3, 0xBF, 0xA9, 0x97, 0x13, 0xBC, 0x87, 0x61, - 0xC5, 0x2B, 0x7F, 0xAA, 0xE9, 0x31, 0x4C, 0xCD, 0x6F, 0x57, 0x68, 0x70, - 0xC8, 0xDC, 0x58, 0x76, 0x91, 0x2F, 0x70, 0x2F, 0xD0, 0x78, 0x02, 0x20, - 0x7E, 0x57, 0x9D, 0xCA, 0x11, 0xF1, 0x3B, 0xA0, 0x39, 0x38, 0x37, 0x40, - 0xC5, 0xC8, 0xFE, 0xC1, 0xFC, 0xE9, 0xE7, 0x84, 0x6C, 0x2D, 0x47, 0x6E, + 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, + 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, + 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, + 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, + 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x20, 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, + 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, + 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x76, 0x46, 0x30, 0x44, 0x02, 0x20, 0x34, 0x89, 0xA3, 0xBF, + 0xA9, 0x97, 0x13, 0xBC, 0x87, 0x61, 0xC5, 0x2B, 0x7F, 0xAA, 0xE9, 0x31, 0x4C, 0xCD, 0x6F, 0x57, 0x68, 0x70, + 0xC8, 0xDC, 0x58, 0x76, 0x91, 0x2F, 0x70, 0x2F, 0xD0, 0x78, 0x02, 0x20, 0x7E, 0x57, 0x9D, 0xCA, 0x11, 0xF1, + 0x3B, 0xA0, 0x39, 0x38, 0x37, 0x40, 0xC5, 0xC8, 0xFE, 0xC1, 0xFC, 0xE9, 0xE7, 0x84, 0x6C, 0x2D, 0x47, 0x6E, 0xD7, 0xFF, 0x83, 0x9D, 0xEF, 0x7D, 0xF7, 0x6A}; // Long public key: static constexpr std::uint8_t payload3[] = { - 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, - 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, - 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, - 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, - 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, - 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, - 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x22, - 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, - 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, - 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x32, 0x78, 0x76, 0x46, - 0x30, 0x44, 0x02, 0x20, 0x3C, 0xAB, 0xEE, 0x36, 0xD8, 0xF3, 0x74, 0x5F, - 0x50, 0x28, 0x66, 0x17, 0x57, 0x26, 0x6A, 0xBD, 0x9A, 0x19, 0x08, 0xAA, - 0x65, 0x94, 0x0B, 0xDF, 0x24, 0x20, 0x44, 0x99, 0x05, 0x8C, 0xB7, 0x3D, - 0x02, 0x20, 0x79, 0x66, 0xE6, 0xCC, 0xA2, 0x5E, 0x15, 0xFE, 0x18, 0x4B, - 0xB2, 0xA8, 0x01, 0x3A, 0xD6, 0x63, 0x54, 0x08, 0x1B, 0xDA, 0xD0, 0x04, + 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, + 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, + 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, + 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, + 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x22, 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, + 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, + 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x32, 0x78, 0x76, 0x46, 0x30, 0x44, 0x02, 0x20, 0x3C, 0xAB, + 0xEE, 0x36, 0xD8, 0xF3, 0x74, 0x5F, 0x50, 0x28, 0x66, 0x17, 0x57, 0x26, 0x6A, 0xBD, 0x9A, 0x19, 0x08, 0xAA, + 0x65, 0x94, 0x0B, 0xDF, 0x24, 0x20, 0x44, 0x99, 0x05, 0x8C, 0xB7, 0x3D, 0x02, 0x20, 0x79, 0x66, 0xE6, 0xCC, + 0xA2, 0x5E, 0x15, 0xFE, 0x18, 0x4B, 0xB2, 0xA8, 0x01, 0x3A, 0xD6, 0x63, 0x54, 0x08, 0x1B, 0xDA, 0xD0, 0x04, 0xEF, 0x4C, 0x73, 0xB3, 0xFF, 0xFE, 0xA9, 0x8E, 0x92, 0xE8}; // Ed25519 public key: static constexpr std::uint8_t payload4[] = { - 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, - 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, - 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, - 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, - 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, - 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, - 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, - 0xED, 0x04, 0x8B, 0x9A, 0x31, 0x5E, 0xC7, 0x33, 0xC0, 0x15, 0x3B, 0x67, - 0x04, 0x73, 0x7A, 0x91, 0x3D, 0xEF, 0x57, 0x1D, 0xAD, 0xEC, 0x57, 0xE5, - 0x91, 0x5D, 0x55, 0xD9, 0x32, 0x9D, 0x45, 0x12, 0x85, 0x76, 0x40, 0x52, - 0x07, 0xF9, 0x0D, 0x18, 0x2B, 0xB7, 0xAF, 0x5D, 0x43, 0xF8, 0xF9, 0xC5, - 0xAD, 0xF9, 0xBA, 0x33, 0x23, 0xC0, 0x2F, 0x95, 0xFF, 0x36, 0x94, 0xD8, - 0x99, 0x99, 0xE0, 0x66, 0xF8, 0xB6, 0x27, 0x22, 0xFD, 0x29, 0x39, 0x30, - 0x39, 0xAB, 0x93, 0xDB, 0x9D, 0x2C, 0xE5, 0xF0, 0x4C, 0xB7, 0x30, 0xFD, - 0xC7, 0xD3, 0x21, 0xC9, 0x4E, 0x0D, 0x8A, 0x1B, 0xB2, 0x89, 0x97, 0x10, - 0x7E, 0x84, 0x09}; + 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, 0x47, 0x31, 0x1A, 0x51, 0x53, + 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, + 0x4B, 0x40, 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, + 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, + 0x2D, 0x18, 0xA6, 0x43, 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, 0xED, + 0x04, 0x8B, 0x9A, 0x31, 0x5E, 0xC7, 0x33, 0xC0, 0x15, 0x3B, 0x67, 0x04, 0x73, 0x7A, 0x91, 0x3D, 0xEF, + 0x57, 0x1D, 0xAD, 0xEC, 0x57, 0xE5, 0x91, 0x5D, 0x55, 0xD9, 0x32, 0x9D, 0x45, 0x12, 0x85, 0x76, 0x40, + 0x52, 0x07, 0xF9, 0x0D, 0x18, 0x2B, 0xB7, 0xAF, 0x5D, 0x43, 0xF8, 0xF9, 0xC5, 0xAD, 0xF9, 0xBA, 0x33, + 0x23, 0xC0, 0x2F, 0x95, 0xFF, 0x36, 0x94, 0xD8, 0x99, 0x99, 0xE0, 0x66, 0xF8, 0xB6, 0x27, 0x22, 0xFD, + 0x29, 0x39, 0x30, 0x39, 0xAB, 0x93, 0xDB, 0x9D, 0x2C, 0xE5, 0xF0, 0x4C, 0xB7, 0x30, 0xFD, 0xC7, 0xD3, + 0x21, 0xC9, 0x4E, 0x0D, 0x8A, 0x1B, 0xB2, 0x89, 0x97, 0x10, 0x7E, 0x84, 0x09}; // No ledger sequence: static constexpr std::uint8_t payload5[] = { - 0x22, 0x80, 0x00, 0x00, 0x01, 0x29, 0x26, 0x47, 0x31, 0x1A, 0x51, 0x53, - 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, - 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, 0x8C, 0xDE, 0xB8, 0x79, 0x39, - 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, 0x0B, 0xAB, - 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, - 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, 0x35, 0x28, 0xEB, 0xD9, 0x06, - 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, 0x02, 0x9D, 0x19, 0xFB, 0x09, - 0x40, 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, 0x71, 0x19, 0x99, 0x94, 0x4A, - 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, 0x92, 0x8C, 0x27, 0x51, 0xFC, - 0x1B, 0x31, 0xEB, 0x32, 0x76, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0x83, - 0xB3, 0x1B, 0xE9, 0x03, 0x8F, 0x4A, 0x92, 0x8B, 0x9B, 0x51, 0xEF, 0x79, - 0xED, 0xA1, 0x4A, 0x58, 0x9B, 0x20, 0xCF, 0x89, 0xC4, 0x75, 0x99, 0x5F, - 0x6D, 0x79, 0x51, 0x79, 0x07, 0xF9, 0x93, 0x02, 0x20, 0x39, 0xA6, 0x0C, - 0x77, 0x68, 0x84, 0x50, 0xDB, 0xDA, 0x64, 0x32, 0x74, 0xEC, 0x63, 0x48, - 0x48, 0x96, 0xB5, 0x94, 0x57, 0x55, 0x8D, 0x7D, 0xD8, 0x25, 0x78, 0xD1, - 0xEA, 0x5F, 0xD9, 0xC7, 0xAA}; + 0x22, 0x80, 0x00, 0x00, 0x01, 0x29, 0x26, 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, + 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, 0x8C, 0xDE, 0xB8, + 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, + 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, 0x35, + 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, + 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, + 0x3E, 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x32, 0x76, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, + 0x83, 0xB3, 0x1B, 0xE9, 0x03, 0x8F, 0x4A, 0x92, 0x8B, 0x9B, 0x51, 0xEF, 0x79, 0xED, 0xA1, 0x4A, 0x58, + 0x9B, 0x20, 0xCF, 0x89, 0xC4, 0x75, 0x99, 0x5F, 0x6D, 0x79, 0x51, 0x79, 0x07, 0xF9, 0x93, 0x02, 0x20, + 0x39, 0xA6, 0x0C, 0x77, 0x68, 0x84, 0x50, 0xDB, 0xDA, 0x64, 0x32, 0x74, 0xEC, 0x63, 0x48, 0x48, 0x96, + 0xB5, 0x94, 0x57, 0x55, 0x8D, 0x7D, 0xD8, 0x25, 0x78, 0xD1, 0xEA, 0x5F, 0xD9, 0xC7, 0xAA}; // No sign time: static constexpr std::uint8_t payload6[] = { - 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x51, 0x53, - 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, - 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, 0x8C, 0xDE, 0xB8, 0x79, 0x39, - 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, 0x0B, 0xAB, - 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, - 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, 0x35, 0x28, 0xEB, 0xD9, 0x06, - 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, 0x02, 0x9D, 0x19, 0xFB, 0x09, - 0x40, 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, 0x71, 0x19, 0x99, 0x94, 0x4A, - 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, 0x92, 0x8C, 0x27, 0x51, 0xFC, - 0x1B, 0x31, 0xEB, 0x32, 0x76, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xDD, - 0xB0, 0x59, 0x9A, 0x02, 0x3E, 0xF2, 0x44, 0xCE, 0x1D, 0xA8, 0x99, 0x06, - 0xF3, 0x8A, 0x4B, 0xEB, 0x95, 0x42, 0x63, 0x6A, 0x6C, 0x04, 0x30, 0x7F, - 0x62, 0x78, 0x3A, 0x89, 0xB0, 0x3F, 0x22, 0x02, 0x20, 0x4E, 0x6A, 0x55, - 0x63, 0x8A, 0x19, 0xED, 0xFE, 0x70, 0x34, 0xD1, 0x30, 0xED, 0x7C, 0xAF, - 0xB2, 0x78, 0xBB, 0x15, 0x6C, 0x42, 0x3E, 0x19, 0x5D, 0xEA, 0xC5, 0x5E, - 0x23, 0xE2, 0x14, 0x80, 0x54}; + 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, + 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, 0x8C, 0xDE, 0xB8, + 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, + 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, 0x35, + 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, + 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, + 0x3E, 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x32, 0x76, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, + 0xDD, 0xB0, 0x59, 0x9A, 0x02, 0x3E, 0xF2, 0x44, 0xCE, 0x1D, 0xA8, 0x99, 0x06, 0xF3, 0x8A, 0x4B, 0xEB, + 0x95, 0x42, 0x63, 0x6A, 0x6C, 0x04, 0x30, 0x7F, 0x62, 0x78, 0x3A, 0x89, 0xB0, 0x3F, 0x22, 0x02, 0x20, + 0x4E, 0x6A, 0x55, 0x63, 0x8A, 0x19, 0xED, 0xFE, 0x70, 0x34, 0xD1, 0x30, 0xED, 0x7C, 0xAF, 0xB2, 0x78, + 0xBB, 0x15, 0x6C, 0x42, 0x3E, 0x19, 0x5D, 0xEA, 0xC5, 0x5E, 0x23, 0xE2, 0x14, 0x80, 0x54}; // No signature field: static constexpr std::uint8_t payload7[] = { - 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, - 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, - 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, - 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, - 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, - 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, - 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, - 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, - 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, - 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x32}; + 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, 0x47, 0x31, 0x1A, 0x51, 0x53, + 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, + 0x4B, 0x40, 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, + 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, + 0x2D, 0x18, 0xA6, 0x43, 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, 0x02, + 0x9D, 0x19, 0xFB, 0x09, 0x40, 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, + 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x32}; // Good: static constexpr std::uint8_t payload8[] = { - 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, - 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, - 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, - 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, - 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, - 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, - 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, - 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, - 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, - 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x32, 0x76, 0x47, 0x30, - 0x45, 0x02, 0x21, 0x00, 0xDD, 0x29, 0xDC, 0xAC, 0x82, 0x5E, 0xF9, 0xE2, - 0x2D, 0x26, 0x03, 0x95, 0xC2, 0x11, 0x3A, 0x2A, 0x83, 0xEE, 0xA0, 0x2B, - 0x9F, 0x2A, 0x51, 0xBD, 0x6B, 0xF7, 0x83, 0xCE, 0x4A, 0x7C, 0x52, 0x29, - 0x02, 0x20, 0x52, 0x45, 0xB9, 0x07, 0x57, 0xEF, 0xB2, 0x6C, 0x69, 0xC5, - 0x47, 0xCA, 0xE2, 0x76, 0x00, 0xFC, 0x35, 0x46, 0x5D, 0x19, 0x64, 0xCE, + 0x22, 0x80, 0x00, 0x00, 0x01, 0x26, 0x03, 0x4B, 0xEA, 0x97, 0x29, 0x26, 0x47, 0x31, 0x1A, 0x51, 0x53, 0x1F, + 0x1A, 0x4E, 0xBB, 0x43, 0x19, 0x69, 0x16, 0xF8, 0x3E, 0xEA, 0x5C, 0x77, 0x94, 0x08, 0x19, 0x0B, 0x4B, 0x40, + 0x8C, 0xDE, 0xB8, 0x79, 0x39, 0xF3, 0x9D, 0x66, 0x7B, 0x12, 0xCA, 0x97, 0x50, 0x17, 0x21, 0x0B, 0xAB, 0xBC, + 0x8C, 0xB7, 0xFB, 0x45, 0x49, 0xED, 0x1E, 0x07, 0xB4, 0xFB, 0xC5, 0xF2, 0xFB, 0x67, 0x2D, 0x18, 0xA6, 0x43, + 0x35, 0x28, 0xEB, 0xD9, 0x06, 0x3E, 0xB3, 0x8B, 0xC2, 0xE0, 0x73, 0x21, 0x02, 0x9D, 0x19, 0xFB, 0x09, 0x40, + 0xE5, 0xC0, 0xD8, 0x58, 0x73, 0xFA, 0x71, 0x19, 0x99, 0x94, 0x4A, 0x68, 0x7D, 0x12, 0x9D, 0xA5, 0xC3, 0x3E, + 0x92, 0x8C, 0x27, 0x51, 0xFC, 0x1B, 0x31, 0xEB, 0x32, 0x76, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xDD, 0x29, + 0xDC, 0xAC, 0x82, 0x5E, 0xF9, 0xE2, 0x2D, 0x26, 0x03, 0x95, 0xC2, 0x11, 0x3A, 0x2A, 0x83, 0xEE, 0xA0, 0x2B, + 0x9F, 0x2A, 0x51, 0xBD, 0x6B, 0xF7, 0x83, 0xCE, 0x4A, 0x7C, 0x52, 0x29, 0x02, 0x20, 0x52, 0x45, 0xB9, 0x07, + 0x57, 0xEF, 0xB2, 0x6C, 0x69, 0xC5, 0x47, 0xCA, 0xE2, 0x76, 0x00, 0xFC, 0x35, 0x46, 0x5D, 0x19, 0x64, 0xCE, 0xCA, 0x88, 0xA1, 0x2A, 0x20, 0xCF, 0x3C, 0xF9, 0xCE, 0xCF}; public: @@ -166,8 +129,7 @@ public: { SerialIter sit{payload8}; - auto val = std::make_shared( - sit, [](PublicKey const& pk) { return calcNodeID(pk); }, true); + auto val = std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, true); BEAST_EXPECT(val); BEAST_EXPECT(val->isFieldPresent(sfLedgerSequence)); @@ -187,55 +149,49 @@ public: try { SerialIter sit{payload1}; - auto val = std::make_shared( - sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); + auto val = + std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("An exception should have been thrown"); } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp( - ex.what(), - "Field 'SigningPubKey' is required but missing.") == 0); + BEAST_EXPECT(strcmp(ex.what(), "Field 'SigningPubKey' is required but missing.") == 0); } try { SerialIter sit{payload2}; - auto val = std::make_shared( - sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); + auto val = + std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("An exception should have been thrown"); } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp(ex.what(), "Invalid public key in validation") == 0); + BEAST_EXPECT(strcmp(ex.what(), "Invalid public key in validation") == 0); } try { SerialIter sit{payload3}; - auto val = std::make_shared( - sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); + auto val = + std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("An exception should have been thrown"); } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp(ex.what(), "Invalid public key in validation") == 0); + BEAST_EXPECT(strcmp(ex.what(), "Invalid public key in validation") == 0); } try { SerialIter sit{payload4}; - auto val = std::make_shared( - sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); + auto val = + std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("An exception should have been thrown"); } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp(ex.what(), "Invalid public key in validation") == 0); + BEAST_EXPECT(strcmp(ex.what(), "Invalid public key in validation") == 0); } testcase("Deserialization: Missing Fields"); @@ -243,48 +199,36 @@ public: try { SerialIter sit{payload5}; - auto val = std::make_shared( - sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); + auto val = std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("Expected exception not thrown from validation"); } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp( - ex.what(), - "Field 'LedgerSequence' is required but missing.") == 0); + BEAST_EXPECT(strcmp(ex.what(), "Field 'LedgerSequence' is required but missing.") == 0); } try { SerialIter sit{payload6}; - auto val = std::make_shared( - sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); + auto val = std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("Expected exception not thrown from validation"); } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp( - ex.what(), - "Field 'SigningTime' is required but missing.") == 0); + BEAST_EXPECT(strcmp(ex.what(), "Field 'SigningTime' is required but missing.") == 0); } try { SerialIter sit{payload7}; - auto val = std::make_shared( - sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); + auto val = std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, false); fail("Expected exception not thrown from validation"); } catch (std::exception const& ex) { - BEAST_EXPECT( - strcmp( - ex.what(), "Field 'Signature' is required but missing.") == - 0); + BEAST_EXPECT(strcmp(ex.what(), "Field 'Signature' is required but missing.") == 0); } testcase("Deserialization: Corrupted Data / Fuzzing"); @@ -307,14 +251,10 @@ public: { SerialIter sit{makeSlice(v2)}; - auto val = std::make_shared( - sit, - [](PublicKey const& pk) { return calcNodeID(pk); }, - true); + auto val = + std::make_shared(sit, [](PublicKey const& pk) { return calcNodeID(pk); }, true); - fail( - "Mutated validation signature checked out: offset=" + - std::to_string(i)); + fail("Mutated validation signature checked out: offset=" + std::to_string(i)); } catch (std::exception const&) { diff --git a/src/test/protocol/SecretKey_test.cpp b/src/test/protocol/SecretKey_test.cpp index e7bdcc1916..60081c8251 100644 --- a/src/test/protocol/SecretKey_test.cpp +++ b/src/test/protocol/SecretKey_test.cpp @@ -31,38 +31,29 @@ public: { testcase("secp256k1: canonicality"); - std::array const digestData{ - 0x34, 0xC1, 0x90, 0x28, 0xC8, 0x0D, 0x21, 0xF3, 0xF4, 0x8C, 0x93, - 0x54, 0x89, 0x5F, 0x8D, 0x5B, 0xF0, 0xD5, 0xEE, 0x7F, 0xF4, 0x57, - 0x64, 0x7C, 0xF6, 0x55, 0xF5, 0x53, 0x0A, 0x30, 0x22, 0xA7}; + std::array const digestData{0x34, 0xC1, 0x90, 0x28, 0xC8, 0x0D, 0x21, 0xF3, 0xF4, 0x8C, 0x93, + 0x54, 0x89, 0x5F, 0x8D, 0x5B, 0xF0, 0xD5, 0xEE, 0x7F, 0xF4, 0x57, + 0x64, 0x7C, 0xF6, 0x55, 0xF5, 0x53, 0x0A, 0x30, 0x22, 0xA7}; - std::array const pkData{ - 0x02, 0x50, 0x96, 0xEB, 0x12, 0xD3, 0xE9, 0x24, 0x23, 0x4E, 0x71, - 0x62, 0x36, 0x9C, 0x11, 0xD8, 0xBF, 0x87, 0x7E, 0xDA, 0x23, 0x87, - 0x78, 0xE7, 0xA3, 0x1F, 0xF0, 0xAA, 0xC5, 0xD0, 0xDB, 0xCF, 0x37}; + std::array const pkData{0x02, 0x50, 0x96, 0xEB, 0x12, 0xD3, 0xE9, 0x24, 0x23, 0x4E, 0x71, + 0x62, 0x36, 0x9C, 0x11, 0xD8, 0xBF, 0x87, 0x7E, 0xDA, 0x23, 0x87, + 0x78, 0xE7, 0xA3, 0x1F, 0xF0, 0xAA, 0xC5, 0xD0, 0xDB, 0xCF, 0x37}; - std::array const skData{ - 0xAA, 0x92, 0x14, 0x17, 0xE7, 0xE5, 0xC2, 0x99, 0xDA, 0x4E, 0xEC, - 0x16, 0xD1, 0xCA, 0xA9, 0x2F, 0x19, 0xB1, 0x9F, 0x2A, 0x68, 0x51, - 0x1F, 0x68, 0xEC, 0x73, 0xBB, 0xB2, 0xF5, 0x23, 0x6F, 0x3D}; + std::array const skData{0xAA, 0x92, 0x14, 0x17, 0xE7, 0xE5, 0xC2, 0x99, 0xDA, 0x4E, 0xEC, + 0x16, 0xD1, 0xCA, 0xA9, 0x2F, 0x19, 0xB1, 0x9F, 0x2A, 0x68, 0x51, + 0x1F, 0x68, 0xEC, 0x73, 0xBB, 0xB2, 0xF5, 0x23, 0x6F, 0x3D}; std::array const sig{ - 0x30, 0x45, 0x02, 0x21, 0x00, 0xB4, 0x9D, 0x07, 0xF0, 0xE9, 0x34, - 0xBA, 0x46, 0x8C, 0x0E, 0xFC, 0x78, 0x11, 0x77, 0x91, 0x40, 0x8D, - 0x1F, 0xB8, 0xB6, 0x3A, 0x64, 0x92, 0xAD, 0x39, 0x5A, 0xC2, 0xF3, - 0x60, 0xF2, 0x46, 0x60, 0x02, 0x20, 0x50, 0x87, 0x39, 0xDB, 0x0A, - 0x2E, 0xF8, 0x16, 0x76, 0xE3, 0x9F, 0x45, 0x9C, 0x8B, 0xBB, 0x07, - 0xA0, 0x9C, 0x3E, 0x9F, 0x9B, 0xEB, 0x69, 0x62, 0x94, 0xD5, 0x24, - 0xD4, 0x79, 0xD6, 0x27, 0x40}; + 0x30, 0x45, 0x02, 0x21, 0x00, 0xB4, 0x9D, 0x07, 0xF0, 0xE9, 0x34, 0xBA, 0x46, 0x8C, 0x0E, 0xFC, 0x78, 0x11, + 0x77, 0x91, 0x40, 0x8D, 0x1F, 0xB8, 0xB6, 0x3A, 0x64, 0x92, 0xAD, 0x39, 0x5A, 0xC2, 0xF3, 0x60, 0xF2, 0x46, + 0x60, 0x02, 0x20, 0x50, 0x87, 0x39, 0xDB, 0x0A, 0x2E, 0xF8, 0x16, 0x76, 0xE3, 0x9F, 0x45, 0x9C, 0x8B, 0xBB, + 0x07, 0xA0, 0x9C, 0x3E, 0x9F, 0x9B, 0xEB, 0x69, 0x62, 0x94, 0xD5, 0x24, 0xD4, 0x79, 0xD6, 0x27, 0x40}; std::array const non{ - 0x30, 0x46, 0x02, 0x21, 0x00, 0xB4, 0x9D, 0x07, 0xF0, 0xE9, 0x34, - 0xBA, 0x46, 0x8C, 0x0E, 0xFC, 0x78, 0x11, 0x77, 0x91, 0x40, 0x8D, - 0x1F, 0xB8, 0xB6, 0x3A, 0x64, 0x92, 0xAD, 0x39, 0x5A, 0xC2, 0xF3, - 0x60, 0xF2, 0x46, 0x60, 0x02, 0x21, 0x00, 0xAF, 0x78, 0xC6, 0x24, - 0xF5, 0xD1, 0x07, 0xE9, 0x89, 0x1C, 0x60, 0xBA, 0x63, 0x74, 0x44, - 0xF7, 0x1A, 0x12, 0x9E, 0x47, 0x13, 0x5D, 0x36, 0xD9, 0x2A, 0xFD, - 0x39, 0xB8, 0x56, 0x60, 0x1A, 0x01}; + 0x30, 0x46, 0x02, 0x21, 0x00, 0xB4, 0x9D, 0x07, 0xF0, 0xE9, 0x34, 0xBA, 0x46, 0x8C, 0x0E, 0xFC, 0x78, 0x11, + 0x77, 0x91, 0x40, 0x8D, 0x1F, 0xB8, 0xB6, 0x3A, 0x64, 0x92, 0xAD, 0x39, 0x5A, 0xC2, 0xF3, 0x60, 0xF2, 0x46, + 0x60, 0x02, 0x21, 0x00, 0xAF, 0x78, 0xC6, 0x24, 0xF5, 0xD1, 0x07, 0xE9, 0x89, 0x1C, 0x60, 0xBA, 0x63, 0x74, + 0x44, 0xF7, 0x1A, 0x12, 0x9E, 0x47, 0x13, 0x5D, 0x36, 0xD9, 0x2A, 0xFD, 0x39, 0xB8, 0x56, 0x60, 0x1A, 0x01}; auto const digest = uint256::fromVoid(digestData.data()); @@ -152,8 +143,7 @@ public: // swaps the smallest and largest elements in buffer std::iter_swap( - std::min_element(badData.begin(), badData.end()), - std::max_element(badData.begin(), badData.end())); + std::min_element(badData.begin(), badData.end()), std::max_element(badData.begin(), badData.end())); // Wrong data: should fail BEAST_EXPECT(!verify(pk, makeSlice(badData), sig)); @@ -178,24 +168,20 @@ public: // Ensure that parsing some well-known secret keys works { - auto const sk1 = generateSecretKey( - KeyType::secp256k1, generateSeed("masterpassphrase")); + auto const sk1 = generateSecretKey(KeyType::secp256k1, generateSeed("masterpassphrase")); - auto const sk2 = parseBase58( - TokenType::NodePrivate, - "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe"); + auto const sk2 = + parseBase58(TokenType::NodePrivate, "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe"); BEAST_EXPECT(sk2); BEAST_EXPECT(sk1 == *sk2); } { - auto const sk1 = generateSecretKey( - KeyType::ed25519, generateSeed("masterpassphrase")); + auto const sk1 = generateSecretKey(KeyType::ed25519, generateSeed("masterpassphrase")); - auto const sk2 = parseBase58( - TokenType::NodePrivate, - "paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36"); + auto const sk2 = + parseBase58(TokenType::NodePrivate, "paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36"); BEAST_EXPECT(sk2); BEAST_EXPECT(sk1 == *sk2); @@ -204,8 +190,7 @@ public: // Try converting short, long and malformed data BEAST_EXPECT(!parseBase58(TokenType::NodePrivate, "")); BEAST_EXPECT(!parseBase58(TokenType::NodePrivate, " ")); - BEAST_EXPECT(!parseBase58( - TokenType::NodePrivate, "!35gty9mhju8nfjl")); + BEAST_EXPECT(!parseBase58(TokenType::NodePrivate, "!35gty9mhju8nfjl")); auto const good = toBase58(TokenType::NodePrivate, randomSecretKey()); @@ -219,8 +204,7 @@ public: while (!s.empty()) { s.erase(r(s) % s.size(), 1); - BEAST_EXPECT( - !parseBase58(TokenType::NodePrivate, s)); + BEAST_EXPECT(!parseBase58(TokenType::NodePrivate, s)); } } @@ -239,8 +223,7 @@ public: { auto s = good; s[i % s.size()] = c; - BEAST_EXPECT( - !parseBase58(TokenType::NodePrivate, s)); + BEAST_EXPECT(!parseBase58(TokenType::NodePrivate, s)); } } @@ -251,8 +234,7 @@ public: for (auto c : std::string("ansrJqtv7")) { s[0] = c; - BEAST_EXPECT( - !parseBase58(TokenType::NodePrivate, s)); + BEAST_EXPECT(!parseBase58(TokenType::NodePrivate, s)); } } @@ -280,8 +262,7 @@ public: BEAST_EXPECT((si == sj) == (i == j)); - auto const skj = - parseBase58(TokenType::NodePrivate, sj); + auto const skj = parseBase58(TokenType::NodePrivate, sj); BEAST_EXPECT(skj && keys[j] == *skj); BEAST_EXPECT((*ski == *skj) == (i == j)); @@ -299,8 +280,7 @@ public: auto const id = parseBase58(test.addr); BEAST_EXPECT(id); - auto kp = - generateKeyPair(KeyType::secp256k1, Seed{makeSlice(test.seed)}); + auto kp = generateKeyPair(KeyType::secp256k1, Seed{makeSlice(test.seed)}); BEAST_EXPECT(kp.first == PublicKey{makeSlice(test.pubkey)}); BEAST_EXPECT(kp.second == SecretKey{makeSlice(test.seckey)}); @@ -318,8 +298,7 @@ public: auto const id = parseBase58(test.addr); BEAST_EXPECT(id); - auto kp = - generateKeyPair(KeyType::ed25519, Seed{makeSlice(test.seed)}); + auto kp = generateKeyPair(KeyType::ed25519, Seed{makeSlice(test.seed)}); BEAST_EXPECT(kp.first == PublicKey{makeSlice(test.pubkey)}); BEAST_EXPECT(kp.second == SecretKey{makeSlice(test.seckey)}); diff --git a/src/test/protocol/Seed_test.cpp b/src/test/protocol/Seed_test.cpp index d33f397921..d6b200cca8 100644 --- a/src/test/protocol/Seed_test.cpp +++ b/src/test/protocol/Seed_test.cpp @@ -14,11 +14,7 @@ class Seed_test : public beast::unit_test::suite static bool equal(Seed const& lhs, Seed const& rhs) { - return std::equal( - lhs.data(), - lhs.data() + lhs.size(), - rhs.data(), - rhs.data() + rhs.size()); + return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size()); } public: @@ -62,15 +58,9 @@ public: testPassphrase() { testcase("generation from passphrase"); - BEAST_EXPECT( - testPassphrase("masterpassphrase") == - "snoPBrXtMeMyMHUVTgbuqAfg1SUTb"); - BEAST_EXPECT( - testPassphrase("Non-Random Passphrase") == - "snMKnVku798EnBwUfxeSD8953sLYA"); - BEAST_EXPECT( - testPassphrase("cookies excitement hand public") == - "sspUXGrmjQhq6mgc24jiRuevZiwKT"); + BEAST_EXPECT(testPassphrase("masterpassphrase") == "snoPBrXtMeMyMHUVTgbuqAfg1SUTb"); + BEAST_EXPECT(testPassphrase("Non-Random Passphrase") == "snMKnVku798EnBwUfxeSD8953sLYA"); + BEAST_EXPECT(testPassphrase("cookies excitement hand public") == "sspUXGrmjQhq6mgc24jiRuevZiwKT"); } void @@ -115,20 +105,14 @@ public: { testcase("Node keypair generation & signing (secp256k1)"); - auto const secretKey = generateSecretKey( - KeyType::secp256k1, generateSeed("masterpassphrase")); - auto const publicKey = - derivePublicKey(KeyType::secp256k1, secretKey); + auto const secretKey = generateSecretKey(KeyType::secp256k1, generateSeed("masterpassphrase")); + auto const publicKey = derivePublicKey(KeyType::secp256k1, secretKey); BEAST_EXPECT( - toBase58(TokenType::NodePublic, publicKey) == - "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9"); + toBase58(TokenType::NodePublic, publicKey) == "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9"); BEAST_EXPECT( - toBase58(TokenType::NodePrivate, secretKey) == - "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe"); - BEAST_EXPECT( - to_string(calcNodeID(publicKey)) == - "7E59C17D50F5959C7B158FEC95C8F815BF653DC8"); + toBase58(TokenType::NodePrivate, secretKey) == "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe"); + BEAST_EXPECT(to_string(calcNodeID(publicKey)) == "7E59C17D50F5959C7B158FEC95C8F815BF653DC8"); auto sig = sign(publicKey, secretKey, makeSlice(message1)); BEAST_EXPECT(sig.size() != 0); @@ -140,9 +124,7 @@ public: // Verify with incorrect public key { auto const otherPublicKey = derivePublicKey( - KeyType::secp256k1, - generateSecretKey( - KeyType::secp256k1, generateSeed("otherpassphrase"))); + KeyType::secp256k1, generateSecretKey(KeyType::secp256k1, generateSeed("otherpassphrase"))); BEAST_EXPECT(!verify(otherPublicKey, makeSlice(message1), sig)); } @@ -160,19 +142,14 @@ public: { testcase("Node keypair generation & signing (ed25519)"); - auto const secretKey = generateSecretKey( - KeyType::ed25519, generateSeed("masterpassphrase")); + auto const secretKey = generateSecretKey(KeyType::ed25519, generateSeed("masterpassphrase")); auto const publicKey = derivePublicKey(KeyType::ed25519, secretKey); BEAST_EXPECT( - toBase58(TokenType::NodePublic, publicKey) == - "nHUeeJCSY2dM71oxM8Cgjouf5ekTuev2mwDpc374aLMxzDLXNmjf"); + toBase58(TokenType::NodePublic, publicKey) == "nHUeeJCSY2dM71oxM8Cgjouf5ekTuev2mwDpc374aLMxzDLXNmjf"); BEAST_EXPECT( - toBase58(TokenType::NodePrivate, secretKey) == - "paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36"); - BEAST_EXPECT( - to_string(calcNodeID(publicKey)) == - "AA066C988C712815CC37AF71472B7CBBBD4E2A0A"); + toBase58(TokenType::NodePrivate, secretKey) == "paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36"); + BEAST_EXPECT(to_string(calcNodeID(publicKey)) == "AA066C988C712815CC37AF71472B7CBBBD4E2A0A"); auto sig = sign(publicKey, secretKey, makeSlice(message1)); BEAST_EXPECT(sig.size() != 0); @@ -184,9 +161,7 @@ public: // Verify with incorrect public key { auto const otherPublicKey = derivePublicKey( - KeyType::ed25519, - generateSecretKey( - KeyType::ed25519, generateSeed("otherpassphrase"))); + KeyType::ed25519, generateSecretKey(KeyType::ed25519, generateSeed("otherpassphrase"))); BEAST_EXPECT(!verify(otherPublicKey, makeSlice(message1), sig)); } @@ -204,18 +179,13 @@ public: { testcase("Account keypair generation & signing (secp256k1)"); - auto const [pk, sk] = generateKeyPair( - KeyType::secp256k1, generateSeed("masterpassphrase")); + auto const [pk, sk] = generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")); + BEAST_EXPECT(toBase58(calcAccountID(pk)) == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"); BEAST_EXPECT( - toBase58(calcAccountID(pk)) == - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"); + toBase58(TokenType::AccountPublic, pk) == "aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw"); BEAST_EXPECT( - toBase58(TokenType::AccountPublic, pk) == - "aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw"); - BEAST_EXPECT( - toBase58(TokenType::AccountSecret, sk) == - "p9JfM6HHi64m6mvB6v5k7G2b1cXzGmYiCNJf6GHPKvFTWdeRVjh"); + toBase58(TokenType::AccountSecret, sk) == "p9JfM6HHi64m6mvB6v5k7G2b1cXzGmYiCNJf6GHPKvFTWdeRVjh"); auto sig = sign(pk, sk, makeSlice(message1)); BEAST_EXPECT(sig.size() != 0); @@ -226,11 +196,9 @@ public: // Verify with incorrect public key { - auto const otherKeyPair = generateKeyPair( - KeyType::secp256k1, generateSeed("otherpassphrase")); + auto const otherKeyPair = generateKeyPair(KeyType::secp256k1, generateSeed("otherpassphrase")); - BEAST_EXPECT( - !verify(otherKeyPair.first, makeSlice(message1), sig)); + BEAST_EXPECT(!verify(otherKeyPair.first, makeSlice(message1), sig)); } // Correct public key but wrong signature @@ -246,18 +214,13 @@ public: { testcase("Account keypair generation & signing (ed25519)"); - auto const [pk, sk] = generateKeyPair( - KeyType::ed25519, generateSeed("masterpassphrase")); + auto const [pk, sk] = generateKeyPair(KeyType::ed25519, generateSeed("masterpassphrase")); + BEAST_EXPECT(to_string(calcAccountID(pk)) == "rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf"); BEAST_EXPECT( - to_string(calcAccountID(pk)) == - "rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf"); + toBase58(TokenType::AccountPublic, pk) == "aKGheSBjmCsKJVuLNKRAKpZXT6wpk2FCuEZAXJupXgdAxX5THCqR"); BEAST_EXPECT( - toBase58(TokenType::AccountPublic, pk) == - "aKGheSBjmCsKJVuLNKRAKpZXT6wpk2FCuEZAXJupXgdAxX5THCqR"); - BEAST_EXPECT( - toBase58(TokenType::AccountSecret, sk) == - "pwDQjwEhbUBmPuEjFpEG75bFhv2obkCB7NxQsfFxM7xGHBMVPu9"); + toBase58(TokenType::AccountSecret, sk) == "pwDQjwEhbUBmPuEjFpEG75bFhv2obkCB7NxQsfFxM7xGHBMVPu9"); auto sig = sign(pk, sk, makeSlice(message1)); BEAST_EXPECT(sig.size() != 0); @@ -268,11 +231,9 @@ public: // Verify with incorrect public key { - auto const otherKeyPair = generateKeyPair( - KeyType::ed25519, generateSeed("otherpassphrase")); + auto const otherKeyPair = generateKeyPair(KeyType::ed25519, generateSeed("otherpassphrase")); - BEAST_EXPECT( - !verify(otherKeyPair.first, makeSlice(message1), sig)); + BEAST_EXPECT(!verify(otherKeyPair.first, makeSlice(message1), sig)); } // Correct public key but wrong signature @@ -296,35 +257,25 @@ public: auto const node1 = randomKeyPair(KeyType::secp256k1); - BEAST_EXPECT( - !parseGenericSeed(toBase58(TokenType::NodePublic, node1.first))); - BEAST_EXPECT( - !parseGenericSeed(toBase58(TokenType::NodePrivate, node1.second))); + BEAST_EXPECT(!parseGenericSeed(toBase58(TokenType::NodePublic, node1.first))); + BEAST_EXPECT(!parseGenericSeed(toBase58(TokenType::NodePrivate, node1.second))); auto const node2 = randomKeyPair(KeyType::ed25519); - BEAST_EXPECT( - !parseGenericSeed(toBase58(TokenType::NodePublic, node2.first))); - BEAST_EXPECT( - !parseGenericSeed(toBase58(TokenType::NodePrivate, node2.second))); + BEAST_EXPECT(!parseGenericSeed(toBase58(TokenType::NodePublic, node2.first))); + BEAST_EXPECT(!parseGenericSeed(toBase58(TokenType::NodePrivate, node2.second))); auto const account1 = generateKeyPair(KeyType::secp256k1, randomSeed()); - BEAST_EXPECT( - !parseGenericSeed(toBase58(calcAccountID(account1.first)))); - BEAST_EXPECT(!parseGenericSeed( - toBase58(TokenType::AccountPublic, account1.first))); - BEAST_EXPECT(!parseGenericSeed( - toBase58(TokenType::AccountSecret, account1.second))); + BEAST_EXPECT(!parseGenericSeed(toBase58(calcAccountID(account1.first)))); + BEAST_EXPECT(!parseGenericSeed(toBase58(TokenType::AccountPublic, account1.first))); + BEAST_EXPECT(!parseGenericSeed(toBase58(TokenType::AccountSecret, account1.second))); auto const account2 = generateKeyPair(KeyType::ed25519, randomSeed()); - BEAST_EXPECT( - !parseGenericSeed(toBase58(calcAccountID(account2.first)))); - BEAST_EXPECT(!parseGenericSeed( - toBase58(TokenType::AccountPublic, account2.first))); - BEAST_EXPECT(!parseGenericSeed( - toBase58(TokenType::AccountSecret, account2.second))); + BEAST_EXPECT(!parseGenericSeed(toBase58(calcAccountID(account2.first)))); + BEAST_EXPECT(!parseGenericSeed(toBase58(TokenType::AccountPublic, account2.first))); + BEAST_EXPECT(!parseGenericSeed(toBase58(TokenType::AccountSecret, account2.second))); } void diff --git a/src/test/protocol/SeqProxy_test.cpp b/src/test/protocol/SeqProxy_test.cpp index d922dd1182..0e91680c8c 100644 --- a/src/test/protocol/SeqProxy_test.cpp +++ b/src/test/protocol/SeqProxy_test.cpp @@ -13,32 +13,28 @@ struct SeqProxy_test : public beast::unit_test::suite expectValues(SeqProxy seqProx, std::uint32_t value, SeqProxy::Type type) { bool const expectSeq{type == SeqProxy::seq}; - return (seqProx.value() == value) && (seqProx.isSeq() == expectSeq) && - (seqProx.isTicket() == !expectSeq); + return (seqProx.value() == value) && (seqProx.isSeq() == expectSeq) && (seqProx.isTicket() == !expectSeq); } // Exercise all SeqProxy comparison operators expecting lhs < rhs. static constexpr bool expectLt(SeqProxy lhs, SeqProxy rhs) { - return (lhs < rhs) && (lhs <= rhs) && (!(lhs == rhs)) && (lhs != rhs) && - (!(lhs >= rhs)) && (!(lhs > rhs)); + return (lhs < rhs) && (lhs <= rhs) && (!(lhs == rhs)) && (lhs != rhs) && (!(lhs >= rhs)) && (!(lhs > rhs)); } // Exercise all SeqProxy comparison operators expecting lhs == rhs. static constexpr bool expectEq(SeqProxy lhs, SeqProxy rhs) { - return (!(lhs < rhs)) && (lhs <= rhs) && (lhs == rhs) && - (!(lhs != rhs)) && (lhs >= rhs) && (!(lhs > rhs)); + return (!(lhs < rhs)) && (lhs <= rhs) && (lhs == rhs) && (!(lhs != rhs)) && (lhs >= rhs) && (!(lhs > rhs)); } // Exercise all SeqProxy comparison operators expecting lhs > rhs. static constexpr bool expectGt(SeqProxy lhs, SeqProxy rhs) { - return (!(lhs < rhs)) && (!(lhs <= rhs)) && (!(lhs == rhs)) && - (lhs != rhs) && (lhs >= rhs) && (lhs > rhs); + return (!(lhs < rhs)) && (!(lhs <= rhs)) && (!(lhs == rhs)) && (lhs != rhs) && (lhs >= rhs) && (lhs > rhs); } // Verify streaming. @@ -52,8 +48,7 @@ struct SeqProxy_test : public beast::unit_test::suite ss << seqProx; std::string str{ss.str()}; - return str.find(type) == 0 && str[type.size()] == ' ' && - str.find(value) == (type.size() + 1); + return str.find(type) == 0 && str[type.size()] == ' ' && str.find(value) == (type.size() + 1); } void @@ -62,8 +57,7 @@ struct SeqProxy_test : public beast::unit_test::suite // While SeqProxy supports values of zero, they are not // expected in the wild. Nevertheless they are tested here. // But so are values of 1, which are expected to occur in the wild. - static constexpr std::uint32_t uintMax{ - std::numeric_limits::max()}; + static constexpr std::uint32_t uintMax{std::numeric_limits::max()}; static constexpr SeqProxy::Type seq{SeqProxy::seq}; static constexpr SeqProxy::Type ticket{SeqProxy::ticket}; diff --git a/src/test/protocol/Serializer_test.cpp b/src/test/protocol/Serializer_test.cpp index c5b56c3029..cd34446fa8 100644 --- a/src/test/protocol/Serializer_test.cpp +++ b/src/test/protocol/Serializer_test.cpp @@ -12,11 +12,7 @@ struct Serializer_test : public beast::unit_test::suite { { std::initializer_list const values = { - std::numeric_limits::min(), - -1, - 0, - 1, - std::numeric_limits::max()}; + std::numeric_limits::min(), -1, 0, 1, std::numeric_limits::max()}; for (std::int32_t value : values) { Serializer s; @@ -28,11 +24,7 @@ struct Serializer_test : public beast::unit_test::suite } { std::initializer_list const values = { - std::numeric_limits::min(), - -1, - 0, - 1, - std::numeric_limits::max()}; + std::numeric_limits::min(), -1, 0, 1, std::numeric_limits::max()}; for (std::int64_t value : values) { Serializer s; diff --git a/src/test/protocol/TER_test.cpp b/src/test/protocol/TER_test.cpp index 56b3b08051..6dce46ed6b 100644 --- a/src/test/protocol/TER_test.cpp +++ b/src/test/protocol/TER_test.cpp @@ -14,8 +14,7 @@ struct TER_test : public beast::unit_test::suite for (auto i = -400; i < 400; ++i) { TER t = TER::fromInt(i); - auto inRange = isTelLocal(t) || isTemMalformed(t) || - isTefFailure(t) || isTerRetry(t) || isTesSuccess(t) || + auto inRange = isTelLocal(t) || isTemMalformed(t) || isTefFailure(t) || isTerRetry(t) || isTesSuccess(t) || isTecClaim(t); std::string token, text; @@ -49,36 +48,21 @@ struct TER_test : public beast::unit_test::suite // unless they are the same types. using To_t = std::decay_t(tup))>; using From_t = std::decay_t(tup))>; + static_assert(std::is_same::value == std::is_convertible::value, "Convert err"); static_assert( - std::is_same::value == - std::is_convertible::value, - "Convert err"); + std::is_same::value == std::is_constructible::value, "Construct err"); static_assert( - std::is_same::value == - std::is_constructible::value, - "Construct err"); - static_assert( - std::is_same::value == - std::is_assignable::value, - "Assign err"); + std::is_same::value == std::is_assignable::value, "Assign err"); // Assignment or conversion from integer to type should never work. - static_assert( - !std::is_convertible::value, "Convert err"); - static_assert( - !std::is_constructible::value, "Construct err"); - static_assert( - !std::is_assignable::value, "Assign err"); + static_assert(!std::is_convertible::value, "Convert err"); + static_assert(!std::is_constructible::value, "Construct err"); + static_assert(!std::is_assignable::value, "Assign err"); } }; // Fast iteration over the tuple. - template < - std::size_t I1, - std::size_t I2, - template - class Func, - typename Tup> + template class Func, typename Tup> std::enable_if_t testIterate(Tup const& tup, beast::unit_test::suite& s) { @@ -88,12 +72,7 @@ struct TER_test : public beast::unit_test::suite } // Slow iteration over the tuple. - template < - std::size_t I1, - std::size_t I2, - template - class Func, - typename Tup> + template class Func, typename Tup> std::enable_if_t testIterate(Tup const& tup, beast::unit_test::suite& s) { @@ -103,12 +82,7 @@ struct TER_test : public beast::unit_test::suite } // Finish iteration over the tuple. - template < - std::size_t I1, - std::size_t I2, - template - class Func, - typename Tup> + template class Func, typename Tup> std::enable_if_t testIterate(Tup const& tup, beast::unit_test::suite& s) { @@ -123,15 +97,9 @@ struct TER_test : public beast::unit_test::suite // are not valid. // Examples of each kind of enum. - static auto const terEnums = std::make_tuple( - telLOCAL_ERROR, - temMALFORMED, - tefFAILURE, - terRETRY, - tesSUCCESS, - tecCLAIM); - static int const hiIndex{ - std::tuple_size::value - 1}; + static auto const terEnums = + std::make_tuple(telLOCAL_ERROR, temMALFORMED, tefFAILURE, terRETRY, tesSUCCESS, tecCLAIM); + static int const hiIndex{std::tuple_size::value - 1}; // Verify that enums cannot be converted to other enum types. testIterate(terEnums, *this); @@ -140,12 +108,9 @@ struct TER_test : public beast::unit_test::suite auto isConvertible = [](auto from, auto to) { using From_t = std::decay_t; using To_t = std::decay_t; - static_assert( - std::is_convertible::value, "Convert err"); - static_assert( - std::is_constructible::value, "Construct err"); - static_assert( - std::is_assignable::value, "Assign err"); + static_assert(std::is_convertible::value, "Convert err"); + static_assert(std::is_constructible::value, "Construct err"); + static_assert(std::is_assignable::value, "Assign err"); }; // Verify the right types convert to NotTEC. @@ -161,12 +126,9 @@ struct TER_test : public beast::unit_test::suite auto notConvertible = [](auto from, auto to) { using To_t = std::decay_t; using From_t = std::decay_t; - static_assert( - !std::is_convertible::value, "Convert err"); - static_assert( - !std::is_constructible::value, "Construct err"); - static_assert( - !std::is_assignable::value, "Assign err"); + static_assert(!std::is_convertible::value, "Convert err"); + static_assert(!std::is_constructible::value, "Construct err"); + static_assert(!std::is_assignable::value, "Assign err"); }; // Verify types that shouldn't convert to NotTEC. @@ -208,29 +170,17 @@ struct TER_test : public beast::unit_test::suite auto const lhs = std::get(tup); auto const rhs = std::get(tup); - static_assert( - std::is_same::value, - "== err"); + static_assert(std::is_same::value, "== err"); - static_assert( - std::is_same::value, - "!= err"); + static_assert(std::is_same::value, "!= err"); - static_assert( - std::is_same::value, - "< err"); + static_assert(std::is_same::value, "< err"); - static_assert( - std::is_same::value, - "<= err"); + static_assert(std::is_same::value, "<= err"); - static_assert( - std::is_same(lhs, rhs)), bool>::value, - "> err"); + static_assert(std::is_same(lhs, rhs)), bool>::value, "> err"); - static_assert( - std::is_same=(lhs, rhs)), bool>::value, - ">= err"); + static_assert(std::is_same=(lhs, rhs)), bool>::value, ">= err"); // Make sure a sampling of TER types exhibit the expected behavior // for all comparison operators. diff --git a/src/test/resource/Logic_test.cpp b/src/test/resource/Logic_test.cpp index 0e520d4983..f3e44e8b32 100644 --- a/src/test/resource/Logic_test.cpp +++ b/src/test/resource/Logic_test.cpp @@ -17,16 +17,14 @@ namespace Resource { class ResourceManager_test : public beast::unit_test::suite { public: - class TestLogic : private boost::base_from_member, - public Logic + class TestLogic : private boost::base_from_member, public Logic { private: using clock_type = boost::base_from_member; public: - explicit TestLogic(beast::Journal journal) - : Logic(beast::insight::NullCollector::New(), member, journal) + explicit TestLogic(beast::Journal journal) : Logic(beast::insight::NullCollector::New(), member, journal) { } @@ -55,8 +53,7 @@ public: { Gossip::Item item; item.balance = 100 + rand_int(499); - beast::IP::AddressV4::bytes_type d = { - {192, 0, 2, static_cast(v + i)}}; + beast::IP::AddressV4::bytes_type d = {{192, 0, 2, static_cast(v + i)}}; item.address = beast::IP::Endpoint{beast::IP::AddressV4{d}}; gossip.items.push_back(item); } @@ -75,16 +72,11 @@ public: TestLogic logic(j); Charge const fee(dropThreshold + 1); - beast::IP::Endpoint const addr( - beast::IP::Endpoint::from_string("192.0.2.2")); + beast::IP::Endpoint const addr(beast::IP::Endpoint::from_string("192.0.2.2")); std::function ep = limited - ? std::bind( - &TestLogic::newInboundEndpoint, &logic, std::placeholders::_1) - : std::bind( - &TestLogic::newUnlimitedEndpoint, - &logic, - std::placeholders::_1); + ? std::bind(&TestLogic::newInboundEndpoint, &logic, std::placeholders::_1) + : std::bind(&TestLogic::newUnlimitedEndpoint, &logic, std::placeholders::_1); { Consumer c(ep(addr)); @@ -222,34 +214,28 @@ public: TestLogic logic(j); { - beast::IP::Endpoint address( - beast::IP::Endpoint::from_string("192.0.2.1")); + beast::IP::Endpoint address(beast::IP::Endpoint::from_string("192.0.2.1")); Consumer c(logic.newInboundEndpoint(address)); Charge fee(1000); - JLOG(j.info()) << "Charging " << c.to_string() << " " << fee - << " per second"; + JLOG(j.info()) << "Charging " << c.to_string() << " " << fee << " per second"; c.charge(fee); for (int i = 0; i < 128; ++i) { - JLOG(j.info()) << "Time= " - << logic.clock().now().time_since_epoch().count() + JLOG(j.info()) << "Time= " << logic.clock().now().time_since_epoch().count() << ", Balance = " << c.balance(); logic.advance(); } } { - beast::IP::Endpoint address( - beast::IP::Endpoint::from_string("192.0.2.2")); + beast::IP::Endpoint address(beast::IP::Endpoint::from_string("192.0.2.2")); Consumer c(logic.newInboundEndpoint(address)); Charge fee(1000); - JLOG(j.info()) << "Charging " << c.to_string() << " " << fee - << " per second"; + JLOG(j.info()) << "Charging " << c.to_string() << " " << fee << " per second"; for (int i = 0; i < 128; ++i) { c.charge(fee); - JLOG(j.info()) << "Time= " - << logic.clock().now().time_since_epoch().count() + JLOG(j.info()) << "Time= " << logic.clock().now().time_since_epoch().count() << ", Balance = " << c.balance(); logic.advance(); } diff --git a/src/test/rpc/AMMInfo_test.cpp b/src/test/rpc/AMMInfo_test.cpp index c76fa15eb7..cf515d7c84 100644 --- a/src/test/rpc/AMMInfo_test.cpp +++ b/src/test/rpc/AMMInfo_test.cpp @@ -21,8 +21,7 @@ public: Account const bogie("bogie"); enum TestAccount { None, Alice, Bogie }; - auto accountId = [&](AMM const& ammAlice, - TestAccount v) -> std::optional { + auto accountId = [&](AMM const& ammAlice, TestAccount v) -> std::optional { if (v == Alice) return ammAlice.ammAccount(); else if (v == Bogie) @@ -35,8 +34,7 @@ public: testAMM([&](AMM& ammAlice, Env&) { Account const gw("gw"); auto const USD = gw["USD"]; - auto const jv = - ammAlice.ammRpcInfo({}, {}, USD.issue(), USD.issue()); + auto const jv = ammAlice.ammRpcInfo({}, {}, USD.issue(), USD.issue()); BEAST_EXPECT(jv[jss::error_message] == "Account not found."); }); @@ -46,11 +44,7 @@ public: BEAST_EXPECT(jv[jss::error_message] == "Account malformed."); }); - std::vector, - std::optional, - TestAccount, - bool>> const invalidParams = { + std::vector, std::optional, TestAccount, bool>> const invalidParams = { {xrpIssue(), std::nullopt, None, false}, {std::nullopt, USD.issue(), None, false}, {xrpIssue(), std::nullopt, Alice, false}, @@ -63,12 +57,7 @@ public: for (auto const& [iss1, iss2, acct, ignoreParams] : invalidParams) { auto const jv = ammAlice.ammRpcInfo( - std::nullopt, - std::nullopt, - iss1, - iss2, - accountId(ammAlice, acct), - ignoreParams); + std::nullopt, std::nullopt, iss1, iss2, accountId(ammAlice, acct), ignoreParams); BEAST_EXPECT(jv[jss::error_message] == "Invalid parameters."); } }); @@ -106,60 +95,38 @@ public: // Invalid AMM account id testAMM([&](AMM& ammAlice, Env&) { - auto const jv = ammAlice.ammRpcInfo( - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, - bogie.id()); + auto const jv = ammAlice.ammRpcInfo(std::nullopt, std::nullopt, std::nullopt, std::nullopt, bogie.id()); BEAST_EXPECT(jv[jss::error_message] == "Account malformed."); }); - std::vector, - std::optional, - TestAccount, - bool>> const invalidParamsBadAccount = { - {xrpIssue(), std::nullopt, None, false}, - {std::nullopt, USD.issue(), None, false}, - {xrpIssue(), std::nullopt, Bogie, false}, - {std::nullopt, USD.issue(), Bogie, false}, - {xrpIssue(), USD.issue(), Bogie, false}, - {std::nullopt, std::nullopt, None, true}}; + std::vector, std::optional, TestAccount, bool>> const + invalidParamsBadAccount = { + {xrpIssue(), std::nullopt, None, false}, + {std::nullopt, USD.issue(), None, false}, + {xrpIssue(), std::nullopt, Bogie, false}, + {std::nullopt, USD.issue(), Bogie, false}, + {xrpIssue(), USD.issue(), Bogie, false}, + {std::nullopt, std::nullopt, None, true}}; // Invalid parameters *and* invalid AMM account, default API version testAMM([&](AMM& ammAlice, Env&) { - for (auto const& [iss1, iss2, acct, ignoreParams] : - invalidParamsBadAccount) + for (auto const& [iss1, iss2, acct, ignoreParams] : invalidParamsBadAccount) { auto const jv = ammAlice.ammRpcInfo( - std::nullopt, - std::nullopt, - iss1, - iss2, - accountId(ammAlice, acct), - ignoreParams); + std::nullopt, std::nullopt, iss1, iss2, accountId(ammAlice, acct), ignoreParams); BEAST_EXPECT(jv[jss::error_message] == "Invalid parameters."); } }); // Invalid parameters *and* invalid AMM account, API version 3 testAMM([&](AMM& ammAlice, Env&) { - for (auto const& [iss1, iss2, acct, ignoreParams] : - invalidParamsBadAccount) + for (auto const& [iss1, iss2, acct, ignoreParams] : invalidParamsBadAccount) { auto const jv = ammAlice.ammRpcInfo( - std::nullopt, - std::nullopt, - iss1, - iss2, - accountId(ammAlice, acct), - ignoreParams, - 3); + std::nullopt, std::nullopt, iss1, iss2, accountId(ammAlice, acct), ignoreParams, 3); BEAST_EXPECT( jv[jss::error_message] == - (acct == Bogie ? std::string("Account malformed.") - : std::string("Invalid parameters."))); + (acct == Bogie ? std::string("Account malformed.") : std::string("Invalid parameters."))); } }); } @@ -171,15 +138,9 @@ public: using namespace jtx; testAMM([&](AMM& ammAlice, Env&) { + BEAST_EXPECT(ammAlice.expectAmmRpcInfo(XRP(10000), USD(10000), IOUAmount{10000000, 0})); BEAST_EXPECT(ammAlice.expectAmmRpcInfo( - XRP(10000), USD(10000), IOUAmount{10000000, 0})); - BEAST_EXPECT(ammAlice.expectAmmRpcInfo( - XRP(10000), - USD(10000), - IOUAmount{10000000, 0}, - std::nullopt, - std::nullopt, - ammAlice.ammAccount())); + XRP(10000), USD(10000), IOUAmount{10000000, 0}, std::nullopt, std::nullopt, ammAlice.ammAccount())); }); } @@ -191,8 +152,7 @@ public: using namespace jtx; testAMM( [&](AMM& ammAlice, Env& env) { - BEAST_EXPECT(ammAlice.expectAmmRpcInfo( - XRP(10000), USD(10000), IOUAmount{10000000, 0})); + BEAST_EXPECT(ammAlice.expectAmmRpcInfo(XRP(10000), USD(10000), IOUAmount{10000000, 0})); std::unordered_map votes; votes.insert({alice.human(), 0}); for (int i = 0; i < 7; ++i) @@ -210,8 +170,7 @@ public: Account ed("ed"); Account bill("bill"); env.fund(XRP(1000), bob, ed, bill); - env(ammAlice.bid( - {.bidMin = 100, .authAccounts = {carol, bob, ed, bill}})); + env(ammAlice.bid({.bidMin = 100, .authAccounts = {carol, bob, ed, bill}})); if (!features[fixAMMv1_3]) BEAST_EXPECT(ammAlice.expectAmmRpcInfo( XRP(80000), @@ -232,13 +191,10 @@ public: { std::unordered_set authAccounts = { carol.human(), bob.human(), ed.human(), bill.human()}; - auto const ammInfo = i ? ammAlice.ammRpcInfo() - : ammAlice.ammRpcInfo( - std::nullopt, - std::nullopt, - std::nullopt, - std::nullopt, - ammAlice.ammAccount()); + auto const ammInfo = i + ? ammAlice.ammRpcInfo() + : ammAlice.ammRpcInfo( + std::nullopt, std::nullopt, std::nullopt, std::nullopt, ammAlice.ammAccount()); auto const& amm = ammInfo[jss::amm]; try { @@ -248,12 +204,9 @@ public: for (std::uint8_t i = 0; i < 8; ++i) { if (!BEAST_EXPECT( - votes[voteSlots[i][jss::account] - .asString()] == - voteSlots[i][jss::trading_fee] - .asUInt() && - voteSlots[i][jss::vote_weight].asUInt() == - 12500)) + votes[voteSlots[i][jss::account].asString()] == + voteSlots[i][jss::trading_fee].asUInt() && + voteSlots[i][jss::vote_weight].asUInt() == 12500)) return; votes.erase(voteSlots[i][jss::account].asString()); } @@ -265,27 +218,20 @@ public: auto const auctionSlot = amm[jss::auction_slot]; for (std::uint8_t i = 0; i < 4; ++i) { - if (!BEAST_EXPECT(authAccounts.contains( - auctionSlot[jss::auth_accounts][i] - [jss::account] - .asString()))) + if (!BEAST_EXPECT( + authAccounts.contains(auctionSlot[jss::auth_accounts][i][jss::account].asString()))) return; - authAccounts.erase( - auctionSlot[jss::auth_accounts][i][jss::account] - .asString()); + authAccounts.erase(auctionSlot[jss::auth_accounts][i][jss::account].asString()); } if (!BEAST_EXPECT(authAccounts.empty())) return; BEAST_EXPECT( - auctionSlot[jss::account].asString() == - alice.human() && + auctionSlot[jss::account].asString() == alice.human() && auctionSlot[jss::discounted_fee].asUInt() == 17 && - auctionSlot[jss::price][jss::value].asString() == - "5600" && + auctionSlot[jss::price][jss::value].asString() == "5600" && auctionSlot[jss::price][jss::currency].asString() == to_string(ammAlice.lptIssue().currency) && - auctionSlot[jss::price][jss::issuer].asString() == - to_string(ammAlice.lptIssue().account)); + auctionSlot[jss::price][jss::issuer].asString() == to_string(ammAlice.lptIssue().account)); } catch (std::exception const& e) { @@ -308,8 +254,7 @@ public: env.close(); auto test = [&](bool freeze) { auto const info = ammAlice.ammRpcInfo(); - BEAST_EXPECT( - info[jss::amm][jss::asset2_frozen].asBool() == freeze); + BEAST_EXPECT(info[jss::amm][jss::asset2_frozen].asBool() == freeze); }; test(true); env(fclear(gw, asfGlobalFreeze)); @@ -325,14 +270,8 @@ public: testcase("Invalid amm field"); testAMM([&](AMM& amm, Env&) { - auto const resp = amm.ammRpcInfo( - std::nullopt, - jss::validated.c_str(), - std::nullopt, - std::nullopt, - gw); - BEAST_EXPECT( - resp.isMember("error") && resp["error"] == "actNotFound"); + auto const resp = amm.ammRpcInfo(std::nullopt, jss::validated.c_str(), std::nullopt, std::nullopt, gw); + BEAST_EXPECT(resp.isMember("error") && resp["error"] == "actNotFound"); }); } diff --git a/src/test/rpc/AccountCurrencies_test.cpp b/src/test/rpc/AccountCurrencies_test.cpp index b1417735be..f467b50adc 100644 --- a/src/test/rpc/AccountCurrencies_test.cpp +++ b/src/test/rpc/AccountCurrencies_test.cpp @@ -23,20 +23,15 @@ class AccountCurrencies_test : public beast::unit_test::suite Json::Value params; params[jss::account] = Account{"bob"}.human(); params[jss::ledger_hash] = 1; - auto const result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; + auto const result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'ledger_hash', not hex string."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'ledger_hash', not hex string."); } { // missing account field - auto const result = - env.rpc("json", "account_currencies", "{}")[jss::result]; + auto const result = env.rpc("json", "account_currencies", "{}")[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT( - result[jss::error_message] == "Missing field 'account'."); + BEAST_EXPECT(result[jss::error_message] == "Missing field 'account'."); } { @@ -44,13 +39,9 @@ class AccountCurrencies_test : public beast::unit_test::suite auto testInvalidAccountParam = [&](auto const& param) { Json::Value params; params[jss::account] = param; - auto jrr = env.rpc( - "json", - "account_currencies", - to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -66,13 +57,9 @@ class AccountCurrencies_test : public beast::unit_test::suite auto testInvalidIdentParam = [&](auto const& param) { Json::Value params; params[jss::ident] = param; - auto jrr = env.rpc( - "json", - "account_currencies", - to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'ident'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'ident'."); }; testInvalidIdentParam(1); @@ -85,10 +72,8 @@ class AccountCurrencies_test : public beast::unit_test::suite { Json::Value params; - params[jss::account] = - "llIIOO"; // these are invalid in bitcoin alphabet - auto const result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; + params[jss::account] = "llIIOO"; // these are invalid in bitcoin alphabet + auto const result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "actMalformed"); BEAST_EXPECT(result[jss::error_message] == "Account malformed."); } @@ -97,8 +82,7 @@ class AccountCurrencies_test : public beast::unit_test::suite // Cannot use a seed as account Json::Value params; params[jss::account] = "Bob"; - auto const result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; + auto const result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "actMalformed"); BEAST_EXPECT(result[jss::error_message] == "Account malformed."); } @@ -106,8 +90,7 @@ class AccountCurrencies_test : public beast::unit_test::suite { // ask for nonexistent account Json::Value params; params[jss::account] = Account{"bob"}.human(); - auto const result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; + auto const result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "actNotFound"); BEAST_EXPECT(result[jss::error_message] == "Account not found."); } @@ -135,20 +118,14 @@ class AccountCurrencies_test : public beast::unit_test::suite Json::Value params; params[jss::account] = alice.human(); - auto result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; + auto result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; - auto arrayCheck = - [&result]( - Json::StaticString const& fld, - std::vector> const& expected) -> bool { - bool stat = result.isMember(fld) && result[fld].isArray() && - result[fld].size() == expected.size(); + auto arrayCheck = [&result]( + Json::StaticString const& fld, std::vector> const& expected) -> bool { + bool stat = result.isMember(fld) && result[fld].isArray() && result[fld].size() == expected.size(); for (size_t i = 0; stat && i < expected.size(); ++i) { - stat &= - (to_string(expected[i].value().currency) == - result[fld][i].asString()); + stat &= (to_string(expected[i].value().currency) == result[fld][i].asString()); } return stat; }; @@ -161,8 +138,7 @@ class AccountCurrencies_test : public beast::unit_test::suite env(pay(gw, alice, c.value()(50))); // send_currencies should be populated now - result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; + result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies)); BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrencies)); @@ -171,10 +147,8 @@ class AccountCurrencies_test : public beast::unit_test::suite env(trust(alice, gw["USD"](100), tfSetFreeze)); result = env.rpc("account_lines", alice.human()); for (auto const& l : result[jss::lines]) - BEAST_EXPECT( - l[jss::freeze].asBool() == (l[jss::currency] == "USD")); - result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; + BEAST_EXPECT(l[jss::freeze].asBool() == (l[jss::currency] == "USD")); + result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies)); BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrencies)); // clear the freeze @@ -183,10 +157,8 @@ class AccountCurrencies_test : public beast::unit_test::suite // make a payment that exhausts the trustline from alice to gw for USA env(pay(gw, alice, gw["USA"](50))); // USA should now be missing from receive_currencies - result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; - decltype(gwCurrencies) gwCurrenciesNoUSA( - gwCurrencies.begin() + 1, gwCurrencies.end()); + result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; + decltype(gwCurrencies) gwCurrenciesNoUSA(gwCurrencies.begin() + 1, gwCurrencies.end()); BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrenciesNoUSA)); BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrencies)); @@ -194,8 +166,7 @@ class AccountCurrencies_test : public beast::unit_test::suite // so that send_currencies for alice will now omit USA env(trust(gw, alice["USA"](100))); env(pay(alice, gw, alice["USA"](200))); - result = env.rpc( - "json", "account_currencies", to_string(params))[jss::result]; + result = env.rpc("json", "account_currencies", to_string(params))[jss::result]; BEAST_EXPECT(arrayCheck(jss::receive_currencies, gwCurrencies)); BEAST_EXPECT(arrayCheck(jss::send_currencies, gwCurrenciesNoUSA)); } diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 6370884124..bdc8e63e3d 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -20,9 +20,7 @@ public: { // account_info with no account. auto const info = env.rpc("json", "account_info", "{ }"); - BEAST_EXPECT( - info[jss::result][jss::error_message] == - "Missing field 'account'."); + BEAST_EXPECT(info[jss::result][jss::error_message] == "Missing field 'account'."); } { // account_info with a malformed account string. @@ -31,31 +29,23 @@ public: "account_info", "{\"account\": " "\"n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV\"}"); - BEAST_EXPECT( - info[jss::result][jss::error_code] == rpcACT_MALFORMED); - BEAST_EXPECT( - info[jss::result][jss::error_message] == "Account malformed."); + BEAST_EXPECT(info[jss::result][jss::error_code] == rpcACT_MALFORMED); + BEAST_EXPECT(info[jss::result][jss::error_message] == "Account malformed."); } { // account_info with an account that's not in the ledger. Account const bogie{"bogie"}; Json::Value params; params[jss::account] = bogie.human(); - auto const info = - env.rpc("json", "account_info", to_string(params)); - BEAST_EXPECT( - info[jss::result][jss::error_code] == rpcACT_NOT_FOUND); - BEAST_EXPECT( - info[jss::result][jss::error_message] == "Account not found."); + auto const info = env.rpc("json", "account_info", to_string(params)); + BEAST_EXPECT(info[jss::result][jss::error_code] == rpcACT_NOT_FOUND); + BEAST_EXPECT(info[jss::result][jss::error_message] == "Account not found."); } { // Cannot use a seed as account - auto const info = - env.rpc("json", "account_info", R"({"account": "foo"})"); - BEAST_EXPECT( - info[jss::result][jss::error_code] == rpcACT_MALFORMED); - BEAST_EXPECT( - info[jss::result][jss::error_message] == "Account malformed."); + auto const info = env.rpc("json", "account_info", R"({"account": "foo"})"); + BEAST_EXPECT(info[jss::result][jss::error_code] == rpcACT_MALFORMED); + BEAST_EXPECT(info[jss::result][jss::error_message] == "Account malformed."); } { // Cannot pass a non-string into the `account` param @@ -63,11 +53,9 @@ public: auto testInvalidAccountParam = [&](auto const& param) { Json::Value params; params[jss::account] = param; - auto jrr = env.rpc( - "json", "account_info", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_info", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -83,11 +71,9 @@ public: auto testInvalidIdentParam = [&](auto const& param) { Json::Value params; params[jss::ident] = param; - auto jrr = env.rpc( - "json", "account_info", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_info", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'ident'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'ident'."); }; testInvalidIdentParam(1); @@ -119,21 +105,14 @@ public: // Alice has no SignerList yet. { // account_info without the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withoutSigners)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); - BEAST_EXPECT(!info[jss::result][jss::account_data].isMember( - jss::signer_lists)); + auto const info = env.rpc("json", "account_info", to_string(withoutSigners)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); + BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(jss::signer_lists)); } { // account_info with the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withSigners)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withSigners)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& data = info[jss::result][jss::account_data]; BEAST_EXPECT(data.isMember(jss::signer_lists)); auto const& signerLists = data[jss::signer_lists]; @@ -148,21 +127,14 @@ public: env(smallSigners); { // account_info without the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withoutSigners)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); - BEAST_EXPECT(!info[jss::result][jss::account_data].isMember( - jss::signer_lists)); + auto const info = env.rpc("json", "account_info", to_string(withoutSigners)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); + BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(jss::signer_lists)); } { // account_info with the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withSigners)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withSigners)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& data = info[jss::result][jss::account_data]; BEAST_EXPECT(data.isMember(jss::signer_lists)); auto const& signerLists = data[jss::signer_lists]; @@ -202,11 +174,8 @@ public: env(bigSigners); { // account_info with the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withSigners)); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + auto const info = env.rpc("json", "account_info", to_string(withSigners)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& data = info[jss::result][jss::account_data]; BEAST_EXPECT(data.isMember(jss::signer_lists)); auto const& signerLists = data[jss::signer_lists]; @@ -246,22 +215,19 @@ public: withSigners[jss::account] = alice.human(); withSigners[jss::signer_lists] = true; - auto const withSignersAsString = std::string("{ ") + - "\"api_version\": 2, \"account\": \"" + alice.human() + "\", " + - "\"signer_lists\": asdfggh }"; + auto const withSignersAsString = std::string("{ ") + "\"api_version\": 2, \"account\": \"" + alice.human() + + "\", " + "\"signer_lists\": asdfggh }"; // Alice has no SignerList yet. { // account_info without the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withoutSigners)); + auto const info = env.rpc("json", "account_info", to_string(withoutSigners)); BEAST_EXPECT(info.isMember(jss::result)); BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists)); } { // account_info with the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withSigners)); + auto const info = env.rpc("json", "account_info", to_string(withSigners)); BEAST_EXPECT(info.isMember(jss::result)); auto const& data = info[jss::result]; BEAST_EXPECT(data.isMember(jss::signer_lists)); @@ -277,15 +243,13 @@ public: env(smallSigners); { // account_info without the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withoutSigners)); + auto const info = env.rpc("json", "account_info", to_string(withoutSigners)); BEAST_EXPECT(info.isMember(jss::result)); BEAST_EXPECT(!info[jss::result].isMember(jss::signer_lists)); } { // account_info with the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withSigners)); + auto const info = env.rpc("json", "account_info", to_string(withSigners)); BEAST_EXPECT(info.isMember(jss::result)); auto const& data = info[jss::result]; BEAST_EXPECT(data.isMember(jss::signer_lists)); @@ -302,8 +266,7 @@ public: } { // account_info with "signer_lists" as not bool should error out - auto const info = - env.rpc("json", "account_info", withSignersAsString); + auto const info = env.rpc("json", "account_info", withSignersAsString); BEAST_EXPECT(info[jss::status] == "error"); BEAST_EXPECT(info[jss::error] == "invalidParams"); } @@ -333,8 +296,7 @@ public: env(bigSigners); { // account_info with the "signer_lists" argument. - auto const info = - env.rpc("json", "account_info", to_string(withSigners)); + auto const info = env.rpc("json", "account_info", to_string(withSigners)); BEAST_EXPECT(info.isMember(jss::result)); auto const& data = info[jss::result]; BEAST_EXPECT(data.isMember(jss::signer_lists)); @@ -387,65 +349,42 @@ public: { // account_info without the "signer_lists" argument. auto const info = env.rpc("json2", withoutSigners); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); - BEAST_EXPECT(!info[jss::result][jss::account_data].isMember( - jss::signer_lists)); - BEAST_EXPECT( - info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); + BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(jss::signer_lists)); + BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5); } { // account_info with the "signer_lists" argument. auto const info = env.rpc("json2", withSigners); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& data = info[jss::result][jss::account_data]; BEAST_EXPECT(data.isMember(jss::signer_lists)); auto const& signerLists = data[jss::signer_lists]; BEAST_EXPECT(signerLists.isArray()); BEAST_EXPECT(signerLists.size() == 0); - BEAST_EXPECT( - info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6); } { // Do both of the above as a batch job - auto const info = env.rpc( - "json2", '[' + withoutSigners + ", " + withSigners + ']'); - BEAST_EXPECT( - info[0u].isMember(jss::result) && - info[0u][jss::result].isMember(jss::account_data)); - BEAST_EXPECT(!info[0u][jss::result][jss::account_data].isMember( - jss::signer_lists)); - BEAST_EXPECT( - info[0u].isMember(jss::jsonrpc) && - info[0u][jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - info[0u].isMember(jss::ripplerpc) && - info[0u][jss::ripplerpc] == "2.0"); + auto const info = env.rpc("json2", '[' + withoutSigners + ", " + withSigners + ']'); + BEAST_EXPECT(info[0u].isMember(jss::result) && info[0u][jss::result].isMember(jss::account_data)); + BEAST_EXPECT(!info[0u][jss::result][jss::account_data].isMember(jss::signer_lists)); + BEAST_EXPECT(info[0u].isMember(jss::jsonrpc) && info[0u][jss::jsonrpc] == "2.0"); + BEAST_EXPECT(info[0u].isMember(jss::ripplerpc) && info[0u][jss::ripplerpc] == "2.0"); BEAST_EXPECT(info[0u].isMember(jss::id) && info[0u][jss::id] == 5); - BEAST_EXPECT( - info[1u].isMember(jss::result) && - info[1u][jss::result].isMember(jss::account_data)); + BEAST_EXPECT(info[1u].isMember(jss::result) && info[1u][jss::result].isMember(jss::account_data)); auto const& data = info[1u][jss::result][jss::account_data]; BEAST_EXPECT(data.isMember(jss::signer_lists)); auto const& signerLists = data[jss::signer_lists]; BEAST_EXPECT(signerLists.isArray()); BEAST_EXPECT(signerLists.size() == 0); - BEAST_EXPECT( - info[1u].isMember(jss::jsonrpc) && - info[1u][jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - info[1u].isMember(jss::ripplerpc) && - info[1u][jss::ripplerpc] == "2.0"); + BEAST_EXPECT(info[1u].isMember(jss::jsonrpc) && info[1u][jss::jsonrpc] == "2.0"); + BEAST_EXPECT(info[1u].isMember(jss::ripplerpc) && info[1u][jss::ripplerpc] == "2.0"); BEAST_EXPECT(info[1u].isMember(jss::id) && info[1u][jss::id] == 6); } @@ -457,23 +396,16 @@ public: { // account_info without the "signer_lists" argument. auto const info = env.rpc("json2", withoutSigners); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); - BEAST_EXPECT(!info[jss::result][jss::account_data].isMember( - jss::signer_lists)); - BEAST_EXPECT( - info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); + BEAST_EXPECT(!info[jss::result][jss::account_data].isMember(jss::signer_lists)); + BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 5); } { // account_info with the "signer_lists" argument. auto const info = env.rpc("json2", withSigners); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& data = info[jss::result][jss::account_data]; BEAST_EXPECT(data.isMember(jss::signer_lists)); auto const& signerLists = data[jss::signer_lists]; @@ -486,10 +418,8 @@ public: BEAST_EXPECT(signerEntries.size() == 1); auto const& entry0 = signerEntries[0u][sfSignerEntry.jsonName]; BEAST_EXPECT(entry0[sfSignerWeight.jsonName] == 3); - BEAST_EXPECT( - info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6); } @@ -519,9 +449,7 @@ public: { // account_info with the "signer_lists" argument. auto const info = env.rpc("json2", withSigners); - BEAST_EXPECT( - info.isMember(jss::result) && - info[jss::result].isMember(jss::account_data)); + BEAST_EXPECT(info.isMember(jss::result) && info[jss::result].isMember(jss::account_data)); auto const& data = info[jss::result][jss::account_data]; BEAST_EXPECT(data.isMember(jss::signer_lists)); auto const& signerLists = data[jss::signer_lists]; @@ -539,10 +467,8 @@ public: BEAST_EXPECT(entry.isMember(sfAccount.jsonName)); BEAST_EXPECT(entry[sfSignerWeight.jsonName] == 1); } - BEAST_EXPECT( - info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::jsonrpc) && info[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(info.isMember(jss::ripplerpc) && info[jss::ripplerpc] == "2.0"); BEAST_EXPECT(info.isMember(jss::id) && info[jss::id] == 6); } } @@ -558,33 +484,27 @@ public: Account const bob{"bob"}; env.fund(XRP(1000), alice, bob); - auto getAccountFlag = [&env]( - std::string_view fName, - Account const& account) { + auto getAccountFlag = [&env](std::string_view fName, Account const& account) { Json::Value params; params[jss::account] = account.human(); - auto const info = - env.rpc("json", "account_info", to_string(params)); + auto const info = env.rpc("json", "account_info", to_string(params)); std::optional res; if (info[jss::result][jss::status] == "success" && info[jss::result][jss::account_flags].isMember(fName.data())) - res.emplace(info[jss::result][jss::account_flags][fName.data()] - .asBool()); + res.emplace(info[jss::result][jss::account_flags][fName.data()].asBool()); return res; }; - static constexpr std:: - array, 7> - asFlags{ - {{"defaultRipple", asfDefaultRipple}, - {"depositAuth", asfDepositAuth}, - {"disallowIncomingXRP", asfDisallowXRP}, - {"globalFreeze", asfGlobalFreeze}, - {"noFreeze", asfNoFreeze}, - {"requireAuthorization", asfRequireAuth}, - {"requireDestinationTag", asfRequireDest}}}; + static constexpr std::array, 7> asFlags{ + {{"defaultRipple", asfDefaultRipple}, + {"depositAuth", asfDepositAuth}, + {"disallowIncomingXRP", asfDisallowXRP}, + {"globalFreeze", asfGlobalFreeze}, + {"noFreeze", asfNoFreeze}, + {"requireAuthorization", asfRequireAuth}, + {"requireDestinationTag", asfRequireDest}}}; for (auto& asf : asFlags) { @@ -605,15 +525,11 @@ public: BEAST_EXPECT(f2.value()); } - static constexpr std:: - array, 4> - disallowIncomingFlags{ - {{"disallowIncomingCheck", asfDisallowIncomingCheck}, - {"disallowIncomingNFTokenOffer", - asfDisallowIncomingNFTokenOffer}, - {"disallowIncomingPayChan", asfDisallowIncomingPayChan}, - {"disallowIncomingTrustline", - asfDisallowIncomingTrustline}}}; + static constexpr std::array, 4> disallowIncomingFlags{ + {{"disallowIncomingCheck", asfDisallowIncomingCheck}, + {"disallowIncomingNFTokenOffer", asfDisallowIncomingNFTokenOffer}, + {"disallowIncomingPayChan", asfDisallowIncomingPayChan}, + {"disallowIncomingTrustline", asfDisallowIncomingTrustline}}}; for (auto& asf : disallowIncomingFlags) { @@ -634,48 +550,41 @@ public: BEAST_EXPECT(f2.value()); } - static constexpr std::pair - allowTrustLineClawbackFlag{ - "allowTrustLineClawback", asfAllowTrustLineClawback}; + static constexpr std::pair allowTrustLineClawbackFlag{ + "allowTrustLineClawback", asfAllowTrustLineClawback}; if (features[featureClawback]) { // must use bob's account because alice has noFreeze set - auto const f1 = - getAccountFlag(allowTrustLineClawbackFlag.first, bob); + auto const f1 = getAccountFlag(allowTrustLineClawbackFlag.first, bob); BEAST_EXPECT(f1.has_value()); BEAST_EXPECT(!f1.value()); // Set allowTrustLineClawback env(fset(bob, allowTrustLineClawbackFlag.second)); env.close(); - auto const f2 = - getAccountFlag(allowTrustLineClawbackFlag.first, bob); + auto const f2 = getAccountFlag(allowTrustLineClawbackFlag.first, bob); BEAST_EXPECT(f2.has_value()); BEAST_EXPECT(f2.value()); } else { - BEAST_EXPECT( - !getAccountFlag(allowTrustLineClawbackFlag.first, bob)); + BEAST_EXPECT(!getAccountFlag(allowTrustLineClawbackFlag.first, bob)); } - static constexpr std::pair - allowTrustLineLockingFlag{ - "allowTrustLineLocking", asfAllowTrustLineLocking}; + static constexpr std::pair allowTrustLineLockingFlag{ + "allowTrustLineLocking", asfAllowTrustLineLocking}; if (features[featureTokenEscrow]) { - auto const f1 = - getAccountFlag(allowTrustLineLockingFlag.first, bob); + auto const f1 = getAccountFlag(allowTrustLineLockingFlag.first, bob); BEAST_EXPECT(f1.has_value()); BEAST_EXPECT(!f1.value()); // Set allowTrustLineLocking env(fset(bob, allowTrustLineLockingFlag.second)); env.close(); - auto const f2 = - getAccountFlag(allowTrustLineLockingFlag.first, bob); + auto const f2 = getAccountFlag(allowTrustLineLockingFlag.first, bob); BEAST_EXPECT(f2.has_value()); BEAST_EXPECT(f2.value()); } diff --git a/src/test/rpc/AccountLines_test.cpp b/src/test/rpc/AccountLines_test.cpp index 6d9b75a44e..337da27ea0 100644 --- a/src/test/rpc/AccountLines_test.cpp +++ b/src/test/rpc/AccountLines_test.cpp @@ -22,30 +22,24 @@ public: // account_lines with no account. auto const lines = env.rpc("json", "account_lines", "{ }"); BEAST_EXPECT( - lines[jss::result][jss::error_message] == - RPC::missing_field_error(jss::account)[jss::error_message]); + lines[jss::result][jss::error_message] == RPC::missing_field_error(jss::account)[jss::error_message]); } { // account_lines with a malformed account. Json::Value params; - params[jss::account] = - "n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"; - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + params[jss::account] = "n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"; + auto const lines = env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT( - lines[jss::result][jss::error_message] == - RPC::make_error(rpcACT_MALFORMED)[jss::error_message]); + lines[jss::result][jss::error_message] == RPC::make_error(rpcACT_MALFORMED)[jss::error_message]); } { // test account non-string auto testInvalidAccountParam = [&](auto const& param) { Json::Value params; params[jss::account] = param; - auto jrr = env.rpc( - "json", "account_lines", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_lines", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -60,11 +54,9 @@ public: // account_lines on an unfunded account. Json::Value params; params[jss::account] = alice.human(); - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + auto const lines = env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT( - lines[jss::result][jss::error_message] == - RPC::make_error(rpcACT_NOT_FOUND)[jss::error_message]); + lines[jss::result][jss::error_message] == RPC::make_error(rpcACT_NOT_FOUND)[jss::error_message]); } env.fund(XRP(10000), alice); env.close(); @@ -75,8 +67,7 @@ public: // alice is funded but has no lines. An empty array is returned. Json::Value params; params[jss::account] = alice.human(); - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + auto const lines = env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0); } @@ -85,21 +76,17 @@ public: Json::Value params; params[jss::account] = alice.human(); params[jss::ledger_index] = "nonsense"; - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + auto const lines = env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT( - lines[jss::result][jss::error_message] == - "Invalid field 'ledger_index', not string or number."); + lines[jss::result][jss::error_message] == "Invalid field 'ledger_index', not string or number."); } { // Specify a different ledger that doesn't exist. Json::Value params; params[jss::account] = alice.human(); params[jss::ledger_index] = 50000; - auto const lines = - env.rpc("json", "account_lines", to_string(params)); - BEAST_EXPECT( - lines[jss::result][jss::error_message] == "ledgerNotFound"); + auto const lines = env.rpc("json", "account_lines", to_string(params)); + BEAST_EXPECT(lines[jss::result][jss::error_message] == "ledgerNotFound"); } // Create trust lines to share with alice. Account const gw1{"gw1"}; @@ -109,8 +96,7 @@ public: for (char c = 0; c <= ('Z' - 'A'); ++c) { // gw1 currencies have names "YAA" -> "YAZ". - gw1Currencies.push_back( - gw1[std::string("YA") + static_cast('A' + c)]); + gw1Currencies.push_back(gw1[std::string("YA") + static_cast('A' + c)]); IOU const& gw1Currency = gw1Currencies.back(); // Establish trust lines. @@ -134,8 +120,7 @@ public: for (char c = 0; c <= ('Z' - 'A'); ++c) { // gw2 currencies have names "ZAA" -> "ZAZ". - gw2Currencies.push_back( - gw2[std::string("ZA") + static_cast('A' + c)]); + gw2Currencies.push_back(gw2[std::string("ZA") + static_cast('A' + c)]); IOU const& gw2Currency = gw2Currencies.back(); // Establish trust lines. @@ -146,27 +131,19 @@ public: env.close(); // Set flags on gw2 trust lines so we can look for them. - env(trust( - alice, - gw2Currency(0), - gw2, - tfSetNoRipple | tfSetFreeze | tfSetDeepFreeze)); + env(trust(alice, gw2Currency(0), gw2, tfSetNoRipple | tfSetFreeze | tfSetDeepFreeze)); } env.close(); LedgerHeader const ledger58Info = env.closed()->header(); BEAST_EXPECT(ledger58Info.seq == 58); // A re-usable test for historic ledgers. - auto testAccountLinesHistory = [this, &env]( - Account const& account, - LedgerHeader const& info, - int count) { + auto testAccountLinesHistory = [this, &env](Account const& account, LedgerHeader const& info, int count) { // Get account_lines by ledger index. Json::Value paramsSeq; paramsSeq[jss::account] = account.human(); paramsSeq[jss::ledger_index] = info.seq; - auto const linesSeq = - env.rpc("json", "account_lines", to_string(paramsSeq)); + auto const linesSeq = env.rpc("json", "account_lines", to_string(paramsSeq)); BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count); @@ -174,8 +151,7 @@ public: Json::Value paramsHash; paramsHash[jss::account] = account.human(); paramsHash[jss::ledger_hash] = to_string(info.hash); - auto const linesHash = - env.rpc("json", "account_lines", to_string(paramsHash)); + auto const linesHash = env.rpc("json", "account_lines", to_string(paramsHash)); BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count); }; @@ -195,8 +171,7 @@ public: params[jss::account] = alice.human(); params[jss::ledger_hash] = to_string(ledger4Info.hash); params[jss::ledger_index] = ledger58Info.seq; - auto const lines = env.rpc( - "json", "account_lines", to_string(params))[jss::result]; + auto const lines = env.rpc("json", "account_lines", to_string(params))[jss::result]; BEAST_EXPECT(lines[jss::error] == "invalidParams"); BEAST_EXPECT( lines[jss::error_message] == @@ -208,19 +183,15 @@ public: Json::Value params; params[jss::account] = alice.human(); params[jss::ledger_index] = Json::objectValue; - auto const lines = env.rpc( - "json", "account_lines", to_string(params))[jss::result]; + auto const lines = env.rpc("json", "account_lines", to_string(params))[jss::result]; BEAST_EXPECT(lines[jss::error] == "invalidParams"); - BEAST_EXPECT( - lines[jss::error_message] == - "Invalid field 'ledger_index', not string or number."); + BEAST_EXPECT(lines[jss::error_message] == "Invalid field 'ledger_index', not string or number."); } { // alice should have 52 trust lines in the current ledger. Json::Value params; params[jss::account] = alice.human(); - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + auto const lines = env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52); } @@ -229,8 +200,7 @@ public: Json::Value params; params[jss::account] = alice.human(); params[jss::peer] = gw1.human(); - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + auto const lines = env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26); @@ -242,32 +212,26 @@ public: // Use a malformed peer. Json::Value params; params[jss::account] = alice.human(); - params[jss::peer] = - "n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"; - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + params[jss::peer] = "n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"; + auto const lines = env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT( - lines[jss::result][jss::error_message] == - RPC::make_error(rpcACT_MALFORMED)[jss::error_message]); + lines[jss::result][jss::error_message] == RPC::make_error(rpcACT_MALFORMED)[jss::error_message]); } { // A negative limit should fail. Json::Value params; params[jss::account] = alice.human(); params[jss::limit] = -1; - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + auto const lines = env.rpc("json", "account_lines", to_string(params)); BEAST_EXPECT( - lines[jss::result][jss::error_message] == - RPC::expected_field_message(jss::limit, "unsigned integer")); + lines[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); } { // Limit the response to 1 trust line. Json::Value paramsA; paramsA[jss::account] = alice.human(); paramsA[jss::limit] = 1; - auto const linesA = - env.rpc("json", "account_lines", to_string(paramsA)); + auto const linesA = env.rpc("json", "account_lines", to_string(paramsA)); BEAST_EXPECT(linesA[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesA[jss::result][jss::lines].size() == 1); @@ -276,8 +240,7 @@ public: Json::Value paramsB; paramsB[jss::account] = alice.human(); paramsB[jss::marker] = marker; - auto const linesB = - env.rpc("json", "account_lines", to_string(paramsB)); + auto const linesB = env.rpc("json", "account_lines", to_string(paramsB)); BEAST_EXPECT(linesB[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 51); @@ -286,8 +249,7 @@ public: paramsC[jss::account] = alice.human(); paramsC[jss::limit] = 3; paramsC[jss::marker] = marker; - auto const linesC = - env.rpc("json", "account_lines", to_string(paramsC)); + auto const linesC = env.rpc("json", "account_lines", to_string(paramsC)); BEAST_EXPECT(linesC[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesC[jss::result][jss::lines].size() == 3); @@ -296,22 +258,17 @@ public: Json::Value paramsD; paramsD[jss::account] = alice.human(); paramsD[jss::marker] = marker; - auto const linesD = - env.rpc("json", "account_lines", to_string(paramsD)); + auto const linesD = env.rpc("json", "account_lines", to_string(paramsD)); BEAST_EXPECT( - linesD[jss::result][jss::error_message] == - RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]); + linesD[jss::result][jss::error_message] == RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]); } { // A non-string marker should also fail. Json::Value params; params[jss::account] = alice.human(); params[jss::marker] = true; - auto const lines = - env.rpc("json", "account_lines", to_string(params)); - BEAST_EXPECT( - lines[jss::result][jss::error_message] == - RPC::expected_field_message(jss::marker, "string")); + auto const lines = env.rpc("json", "account_lines", to_string(params)); + BEAST_EXPECT(lines[jss::result][jss::error_message] == RPC::expected_field_message(jss::marker, "string")); } { // Check that the flags we expect from alice to gw2 are present. @@ -319,8 +276,7 @@ public: params[jss::account] = alice.human(); params[jss::limit] = 10; params[jss::peer] = gw2.human(); - auto const lines = - env.rpc("json", "account_lines", to_string(params)); + auto const lines = env.rpc("json", "account_lines", to_string(params)); auto const& line = lines[jss::result][jss::lines][0u]; BEAST_EXPECT(line[jss::freeze].asBool() == true); BEAST_EXPECT(line[jss::deep_freeze].asBool() == true); @@ -333,8 +289,7 @@ public: paramsA[jss::account] = gw2.human(); paramsA[jss::limit] = 1; paramsA[jss::peer] = alice.human(); - auto const linesA = - env.rpc("json", "account_lines", to_string(paramsA)); + auto const linesA = env.rpc("json", "account_lines", to_string(paramsA)); auto const& lineA = linesA[jss::result][jss::lines][0u]; BEAST_EXPECT(lineA[jss::freeze_peer].asBool() == true); BEAST_EXPECT(lineA[jss::deep_freeze_peer].asBool() == true); @@ -349,8 +304,7 @@ public: paramsB[jss::limit] = 25; paramsB[jss::marker] = marker; paramsB[jss::peer] = alice.human(); - auto const linesB = - env.rpc("json", "account_lines", to_string(paramsB)); + auto const linesB = env.rpc("json", "account_lines", to_string(paramsB)); BEAST_EXPECT(linesB[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 25); BEAST_EXPECT(!linesB[jss::result].isMember(jss::marker)); @@ -393,10 +347,8 @@ public: Json::Value aliceObjectsParams; aliceObjectsParams[jss::account] = alice.human(); aliceObjectsParams[jss::limit] = 10; - Json::Value const aliceObjects = - env.rpc("json", "account_objects", to_string(aliceObjectsParams)); - Json::Value const& aliceSignerList = - aliceObjects[jss::result][jss::account_objects][0u]; + Json::Value const aliceObjects = env.rpc("json", "account_objects", to_string(aliceObjectsParams)); + Json::Value const& aliceSignerList = aliceObjects[jss::result][jss::account_objects][0u]; if (!(aliceSignerList[sfLedgerEntryType.jsonName] == jss::SignerList)) { fail( @@ -412,23 +364,19 @@ public: Json::Value aliceLines1Params; aliceLines1Params[jss::account] = alice.human(); aliceLines1Params[jss::limit] = 1; - auto const aliceLines1 = - env.rpc("json", "account_lines", to_string(aliceLines1Params)); + auto const aliceLines1 = env.rpc("json", "account_lines", to_string(aliceLines1Params)); BEAST_EXPECT(aliceLines1[jss::result].isMember(jss::marker)); // Verify that the marker points at the signer list. - std::string const aliceMarker = - aliceLines1[jss::result][jss::marker].asString(); - std::string const markerIndex = - aliceMarker.substr(0, aliceMarker.find(',')); + std::string const aliceMarker = aliceLines1[jss::result][jss::marker].asString(); + std::string const markerIndex = aliceMarker.substr(0, aliceMarker.find(',')); BEAST_EXPECT(markerIndex == aliceSignerList[jss::index].asString()); // When we fetch Alice's remaining lines we should find one and no more. Json::Value aliceLines2Params; aliceLines2Params[jss::account] = alice.human(); aliceLines2Params[jss::marker] = aliceMarker; - auto const aliceLines2 = - env.rpc("json", "account_lines", to_string(aliceLines2Params)); + auto const aliceLines2 = env.rpc("json", "account_lines", to_string(aliceLines2Params)); BEAST_EXPECT(aliceLines2[jss::result][jss::lines].size() == 1); BEAST_EXPECT(!aliceLines2[jss::result].isMember(jss::marker)); @@ -437,8 +385,7 @@ public: Json::Value beckyLinesParams; beckyLinesParams[jss::account] = becky.human(); beckyLinesParams[jss::marker] = aliceMarker; - auto const beckyLines = - env.rpc("json", "account_lines", to_string(beckyLinesParams)); + auto const beckyLines = env.rpc("json", "account_lines", to_string(beckyLinesParams)); BEAST_EXPECT(beckyLines[jss::result].isMember(jss::error_message)); } @@ -493,10 +440,8 @@ public: Json::Value linesBegParams; linesBegParams[jss::account] = alice.human(); linesBegParams[jss::limit] = 2; - auto const linesBeg = - env.rpc("json", "account_lines", to_string(linesBegParams)); - BEAST_EXPECT( - linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD"); + auto const linesBeg = env.rpc("json", "account_lines", to_string(linesBegParams)); + BEAST_EXPECT(linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD"); BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker)); // alice pays 100 EUR to cheri. @@ -508,11 +453,9 @@ public: Json::Value linesEndParams; linesEndParams[jss::account] = alice.human(); linesEndParams[jss::marker] = linesBeg[jss::result][jss::marker]; - auto const linesEnd = - env.rpc("json", "account_lines", to_string(linesEndParams)); + auto const linesEnd = env.rpc("json", "account_lines", to_string(linesEndParams)); BEAST_EXPECT( - linesEnd[jss::result][jss::error_message] == - RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]); + linesEnd[jss::result][jss::error_message] == RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]); } void @@ -570,48 +513,32 @@ public: env.close(); // Escrow, in each direction - env(escrow::create(alice, becky, XRP(1000)), - escrow::finish_time(env.now() + 1s)); - env(escrow::create(becky, alice, XRP(1000)), - escrow::finish_time(env.now() + 1s)); + env(escrow::create(alice, becky, XRP(1000)), escrow::finish_time(env.now() + 1s)); + env(escrow::create(becky, alice, XRP(1000)), escrow::finish_time(env.now() + 1s)); // Pay channels, in each direction env(payChan(alice, becky, XRP(1000), 100s, alice.pk())); env(payChan(becky, alice, XRP(1000), 100s, becky.pk())); // Mint NFTs, for each account - uint256 const aliceNFtokenID = - token::getNextID(env, alice, 0, tfTransferable); + uint256 const aliceNFtokenID = token::getNextID(env, alice, 0, tfTransferable); env(token::mint(alice, 0), txflags(tfTransferable)); - uint256 const beckyNFtokenID = - token::getNextID(env, becky, 0, tfTransferable); + uint256 const beckyNFtokenID = token::getNextID(env, becky, 0, tfTransferable); env(token::mint(becky, 0), txflags(tfTransferable)); // NFT Offers, for each other's NFTs - env(token::createOffer(alice, beckyNFtokenID, drops(1)), - token::owner(becky)); - env(token::createOffer(becky, aliceNFtokenID, drops(1)), - token::owner(alice)); + env(token::createOffer(alice, beckyNFtokenID, drops(1)), token::owner(becky)); + env(token::createOffer(becky, aliceNFtokenID, drops(1)), token::owner(alice)); - env(token::createOffer(becky, beckyNFtokenID, drops(1)), - txflags(tfSellNFToken), - token::destination(alice)); - env(token::createOffer(alice, aliceNFtokenID, drops(1)), - txflags(tfSellNFToken), - token::destination(becky)); + env(token::createOffer(becky, beckyNFtokenID, drops(1)), txflags(tfSellNFToken), token::destination(alice)); + env(token::createOffer(alice, aliceNFtokenID, drops(1)), txflags(tfSellNFToken), token::destination(becky)); - env(token::createOffer(gw1, beckyNFtokenID, drops(1)), - token::owner(becky), - token::destination(alice)); - env(token::createOffer(gw1, aliceNFtokenID, drops(1)), - token::owner(alice), - token::destination(becky)); + env(token::createOffer(gw1, beckyNFtokenID, drops(1)), token::owner(becky), token::destination(alice)); + env(token::createOffer(gw1, aliceNFtokenID, drops(1)), token::owner(alice), token::destination(becky)); - env(token::createOffer(becky, beckyNFtokenID, drops(1)), - txflags(tfSellNFToken)); - env(token::createOffer(alice, aliceNFtokenID, drops(1)), - txflags(tfSellNFToken)); + env(token::createOffer(becky, beckyNFtokenID, drops(1)), txflags(tfSellNFToken)); + env(token::createOffer(alice, aliceNFtokenID, drops(1)), txflags(tfSellNFToken)); // Checks, in each direction env(check::create(alice, becky, XRP(50))); @@ -640,9 +567,7 @@ public: // Now make repeated calls to `account_lines` with a limit of 1. // That should iterate all of alice's relevant objects, even though // the list will be empty for most calls. - auto getNextLine = [](Env& env, - Account const& alice, - std::optional const marker) { + auto getNextLine = [](Env& env, Account const& alice, std::optional const marker) { Json::Value params(Json::objectValue); params[jss::account] = alice.human(); params[jss::limit] = 1; @@ -658,17 +583,11 @@ public: constexpr std::size_t expectedNFTs = 1; std::size_t foundLines = 0; - auto hasMarker = [](auto const& aliceLines) { - return aliceLines[jss::result].isMember(jss::marker); - }; - auto marker = [](auto const& aliceLines) { - return aliceLines[jss::result][jss::marker].asString(); - }; + auto hasMarker = [](auto const& aliceLines) { return aliceLines[jss::result].isMember(jss::marker); }; + auto marker = [](auto const& aliceLines) { return aliceLines[jss::result][jss::marker].asString(); }; auto checkLines = [](auto const& aliceLines) { - return aliceLines.isMember(jss::result) && - !aliceLines[jss::result].isMember(jss::error_message) && - aliceLines[jss::result].isMember(jss::lines) && - aliceLines[jss::result][jss::lines].isArray() && + return aliceLines.isMember(jss::result) && !aliceLines[jss::result].isMember(jss::error_message) && + aliceLines[jss::result].isMember(jss::lines) && aliceLines[jss::result][jss::lines].isArray() && aliceLines[jss::result][jss::lines].size() <= 1; }; @@ -691,39 +610,28 @@ public: Json::Value aliceObjectsParams2; aliceObjectsParams2[jss::account] = alice.human(); aliceObjectsParams2[jss::limit] = 200; - Json::Value const aliceObjects = env.rpc( - "json", "account_objects", to_string(aliceObjectsParams2)); + Json::Value const aliceObjects = env.rpc("json", "account_objects", to_string(aliceObjectsParams2)); BEAST_EXPECT(aliceObjects.isMember(jss::result)); - BEAST_EXPECT( - !aliceObjects[jss::result].isMember(jss::error_message)); - BEAST_EXPECT( - aliceObjects[jss::result].isMember(jss::account_objects)); - BEAST_EXPECT( - aliceObjects[jss::result][jss::account_objects].isArray()); + BEAST_EXPECT(!aliceObjects[jss::result].isMember(jss::error_message)); + BEAST_EXPECT(aliceObjects[jss::result].isMember(jss::account_objects)); + BEAST_EXPECT(aliceObjects[jss::result][jss::account_objects].isArray()); // account_objects does not currently return NFTPages. If // that ever changes, without also changing account_lines, // this test will need to be updated. - BEAST_EXPECT( - aliceObjects[jss::result][jss::account_objects].size() == - iterations + expectedNFTs); + BEAST_EXPECT(aliceObjects[jss::result][jss::account_objects].size() == iterations + expectedNFTs); // If ledger object association ever changes, for whatever // reason, this test will need to be updated. - BEAST_EXPECTS( - iterations == expectedIterations, std::to_string(iterations)); + BEAST_EXPECTS(iterations == expectedIterations, std::to_string(iterations)); // Get becky's objects just to confirm that they're symmetrical Json::Value beckyObjectsParams; beckyObjectsParams[jss::account] = becky.human(); beckyObjectsParams[jss::limit] = 200; - Json::Value const beckyObjects = env.rpc( - "json", "account_objects", to_string(beckyObjectsParams)); + Json::Value const beckyObjects = env.rpc("json", "account_objects", to_string(beckyObjectsParams)); BEAST_EXPECT(beckyObjects.isMember(jss::result)); - BEAST_EXPECT( - !beckyObjects[jss::result].isMember(jss::error_message)); - BEAST_EXPECT( - beckyObjects[jss::result].isMember(jss::account_objects)); - BEAST_EXPECT( - beckyObjects[jss::result][jss::account_objects].isArray()); + BEAST_EXPECT(!beckyObjects[jss::result].isMember(jss::error_message)); + BEAST_EXPECT(beckyObjects[jss::result].isMember(jss::account_objects)); + BEAST_EXPECT(beckyObjects[jss::result][jss::account_objects].isArray()); // becky should have the same number of objects as alice, except the // 2 tickets that only alice created. BEAST_EXPECT( @@ -747,11 +655,8 @@ public: request[jss::jsonrpc] = "2.0"; request[jss::ripplerpc] = "2.0"; auto const lines = env.rpc("json2", to_string(request)); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); } { // account_lines with no account. @@ -761,21 +666,15 @@ public: request[jss::ripplerpc] = "2.0"; request[jss::id] = 5; auto const lines = env.rpc("json2", to_string(request)); - BEAST_EXPECT( - lines[jss::error][jss::message] == - RPC::missing_field_error(jss::account)[jss::error_message]); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines[jss::error][jss::message] == RPC::missing_field_error(jss::account)[jss::error_message]); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { // account_lines with a malformed account. Json::Value params; - params[jss::account] = - "n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"; + params[jss::account] = "n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"; Json::Value request; request[jss::method] = "account_lines"; request[jss::jsonrpc] = "2.0"; @@ -783,14 +682,9 @@ public: request[jss::id] = 5; request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); - BEAST_EXPECT( - lines[jss::error][jss::message] == - RPC::make_error(rpcACT_MALFORMED)[jss::error_message]); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines[jss::error][jss::message] == RPC::make_error(rpcACT_MALFORMED)[jss::error_message]); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } Account const alice{"alice"}; @@ -805,14 +699,9 @@ public: request[jss::id] = 5; request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); - BEAST_EXPECT( - lines[jss::error][jss::message] == - RPC::make_error(rpcACT_NOT_FOUND)[jss::error_message]); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines[jss::error][jss::message] == RPC::make_error(rpcACT_NOT_FOUND)[jss::error_message]); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } env.fund(XRP(10000), alice); @@ -833,11 +722,8 @@ public: auto const lines = env.rpc("json2", to_string(request)); BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { @@ -852,14 +738,9 @@ public: request[jss::id] = 5; request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); - BEAST_EXPECT( - lines[jss::error][jss::message] == - "Invalid field 'ledger_index', not string or number."); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines[jss::error][jss::message] == "Invalid field 'ledger_index', not string or number."); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { @@ -875,11 +756,8 @@ public: request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); BEAST_EXPECT(lines[jss::error][jss::message] == "ledgerNotFound"); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } // Create trust lines to share with alice. @@ -890,8 +768,7 @@ public: for (char c = 0; c <= ('Z' - 'A'); ++c) { // gw1 currencies have names "YAA" -> "YAZ". - gw1Currencies.push_back( - gw1[std::string("YA") + static_cast('A' + c)]); + gw1Currencies.push_back(gw1[std::string("YA") + static_cast('A' + c)]); IOU const& gw1Currency = gw1Currencies.back(); // Establish trust lines. @@ -915,8 +792,7 @@ public: for (char c = 0; c <= ('Z' - 'A'); ++c) { // gw2 currencies have names "ZAA" -> "ZAZ". - gw2Currencies.push_back( - gw2[std::string("ZA") + static_cast('A' + c)]); + gw2Currencies.push_back(gw2[std::string("ZA") + static_cast('A' + c)]); IOU const& gw2Currency = gw2Currencies.back(); // Establish trust lines. @@ -927,21 +803,14 @@ public: env.close(); // Set flags on gw2 trust lines so we can look for them. - env(trust( - alice, - gw2Currency(0), - gw2, - tfSetNoRipple | tfSetFreeze | tfSetDeepFreeze)); + env(trust(alice, gw2Currency(0), gw2, tfSetNoRipple | tfSetFreeze | tfSetDeepFreeze)); } env.close(); LedgerHeader const ledger58Info = env.closed()->header(); BEAST_EXPECT(ledger58Info.seq == 58); // A re-usable test for historic ledgers. - auto testAccountLinesHistory = [this, &env]( - Account const& account, - LedgerHeader const& info, - int count) { + auto testAccountLinesHistory = [this, &env](Account const& account, LedgerHeader const& info, int count) { // Get account_lines by ledger index. Json::Value paramsSeq; paramsSeq[jss::account] = account.human(); @@ -955,12 +824,8 @@ public: auto const linesSeq = env.rpc("json2", to_string(requestSeq)); BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count); - BEAST_EXPECT( - linesSeq.isMember(jss::jsonrpc) && - linesSeq[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesSeq.isMember(jss::ripplerpc) && - linesSeq[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesSeq.isMember(jss::jsonrpc) && linesSeq[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesSeq.isMember(jss::ripplerpc) && linesSeq[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesSeq.isMember(jss::id) && linesSeq[jss::id] == 5); // Get account_lines by ledger hash. @@ -976,14 +841,9 @@ public: auto const linesHash = env.rpc("json2", to_string(requestHash)); BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count); - BEAST_EXPECT( - linesHash.isMember(jss::jsonrpc) && - linesHash[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesHash.isMember(jss::ripplerpc) && - linesHash[jss::ripplerpc] == "2.0"); - BEAST_EXPECT( - linesHash.isMember(jss::id) && linesHash[jss::id] == 5); + BEAST_EXPECT(linesHash.isMember(jss::jsonrpc) && linesHash[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesHash.isMember(jss::ripplerpc) && linesHash[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesHash.isMember(jss::id) && linesHash[jss::id] == 5); }; // Alice should have no trust lines in ledger 3. @@ -1014,11 +874,8 @@ public: lines[jss::error][jss::message] == "Exactly one of 'ledger_hash' or 'ledger_index' can be " "specified."); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { @@ -1034,11 +891,8 @@ public: auto const lines = env.rpc("json2", to_string(request)); BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { @@ -1055,19 +909,15 @@ public: auto const lines = env.rpc("json2", to_string(request)); BEAST_EXPECT(lines[jss::result][jss::lines].isArray()); BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { // Use a malformed peer. Json::Value params; params[jss::account] = alice.human(); - params[jss::peer] = - "n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"; + params[jss::peer] = "n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"; Json::Value request; request[jss::method] = "account_lines"; request[jss::jsonrpc] = "2.0"; @@ -1075,14 +925,9 @@ public: request[jss::id] = 5; request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); - BEAST_EXPECT( - lines[jss::error][jss::message] == - RPC::make_error(rpcACT_MALFORMED)[jss::error_message]); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines[jss::error][jss::message] == RPC::make_error(rpcACT_MALFORMED)[jss::error_message]); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { @@ -1098,13 +943,9 @@ public: request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); BEAST_EXPECT( - lines[jss::error][jss::message] == - RPC::expected_field_message(jss::limit, "unsigned integer")); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + lines[jss::error][jss::message] == RPC::expected_field_message(jss::limit, "unsigned integer")); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { @@ -1121,11 +962,8 @@ public: auto const linesA = env.rpc("json2", to_string(requestA)); BEAST_EXPECT(linesA[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesA[jss::result][jss::lines].size() == 1); - BEAST_EXPECT( - linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesA.isMember(jss::ripplerpc) && - linesA[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesA.isMember(jss::ripplerpc) && linesA[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesA.isMember(jss::id) && linesA[jss::id] == 5); // Pick up from where the marker left off. We should get 51. @@ -1142,11 +980,8 @@ public: auto const linesB = env.rpc("json2", to_string(requestB)); BEAST_EXPECT(linesB[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 51); - BEAST_EXPECT( - linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesB.isMember(jss::ripplerpc) && - linesB[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesB.isMember(jss::ripplerpc) && linesB[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesB.isMember(jss::id) && linesB[jss::id] == 5); // Go again from where the marker left off, but set a limit of 3. @@ -1163,11 +998,8 @@ public: auto const linesC = env.rpc("json2", to_string(requestC)); BEAST_EXPECT(linesC[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesC[jss::result][jss::lines].size() == 3); - BEAST_EXPECT( - linesC.isMember(jss::jsonrpc) && linesC[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesC.isMember(jss::ripplerpc) && - linesC[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesC.isMember(jss::jsonrpc) && linesC[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesC.isMember(jss::ripplerpc) && linesC[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesC.isMember(jss::id) && linesC[jss::id] == 5); // Mess with the marker so it becomes bad and check for the error. @@ -1182,14 +1014,9 @@ public: requestD[jss::id] = 5; requestD[jss::params] = paramsD; auto const linesD = env.rpc("json2", to_string(requestD)); - BEAST_EXPECT( - linesD[jss::error][jss::message] == - RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]); - BEAST_EXPECT( - linesD.isMember(jss::jsonrpc) && linesD[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesD.isMember(jss::ripplerpc) && - linesD[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesD[jss::error][jss::message] == RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]); + BEAST_EXPECT(linesD.isMember(jss::jsonrpc) && linesD[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesD.isMember(jss::ripplerpc) && linesD[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesD.isMember(jss::id) && linesD[jss::id] == 5); } { @@ -1204,14 +1031,9 @@ public: request[jss::id] = 5; request[jss::params] = params; auto const lines = env.rpc("json2", to_string(request)); - BEAST_EXPECT( - lines[jss::error][jss::message] == - RPC::expected_field_message(jss::marker, "string")); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines[jss::error][jss::message] == RPC::expected_field_message(jss::marker, "string")); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { @@ -1232,11 +1054,8 @@ public: BEAST_EXPECT(line[jss::deep_freeze].asBool() == true); BEAST_EXPECT(line[jss::no_ripple].asBool() == true); BEAST_EXPECT(line[jss::peer_authorized].asBool() == true); - BEAST_EXPECT( - lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - lines.isMember(jss::ripplerpc) && - lines[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(lines.isMember(jss::ripplerpc) && lines[jss::ripplerpc] == "2.0"); BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5); } { @@ -1257,11 +1076,8 @@ public: BEAST_EXPECT(lineA[jss::deep_freeze_peer].asBool() == true); BEAST_EXPECT(lineA[jss::no_ripple_peer].asBool() == true); BEAST_EXPECT(lineA[jss::authorized].asBool() == true); - BEAST_EXPECT( - linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesA.isMember(jss::ripplerpc) && - linesA[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesA.isMember(jss::ripplerpc) && linesA[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesA.isMember(jss::id) && linesA[jss::id] == 5); // Continue from the returned marker to make sure that works. @@ -1282,11 +1098,8 @@ public: BEAST_EXPECT(linesB[jss::result][jss::lines].isArray()); BEAST_EXPECT(linesB[jss::result][jss::lines].size() == 25); BEAST_EXPECT(!linesB[jss::result].isMember(jss::marker)); - BEAST_EXPECT( - linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesB.isMember(jss::ripplerpc) && - linesB[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesB.isMember(jss::ripplerpc) && linesB[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesB.isMember(jss::id) && linesB[jss::id] == 5); } } @@ -1351,14 +1164,10 @@ public: linesBegRequest[jss::id] = 5; linesBegRequest[jss::params] = linesBegParams; auto const linesBeg = env.rpc("json2", to_string(linesBegRequest)); - BEAST_EXPECT( - linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD"); + BEAST_EXPECT(linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD"); BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker)); - BEAST_EXPECT( - linesBeg.isMember(jss::jsonrpc) && linesBeg[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesBeg.isMember(jss::ripplerpc) && - linesBeg[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesBeg.isMember(jss::jsonrpc) && linesBeg[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesBeg.isMember(jss::ripplerpc) && linesBeg[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesBeg.isMember(jss::id) && linesBeg[jss::id] == 5); // alice pays 100 USD to cheri. @@ -1377,14 +1186,9 @@ public: linesEndRequest[jss::id] = 5; linesEndRequest[jss::params] = linesEndParams; auto const linesEnd = env.rpc("json2", to_string(linesEndRequest)); - BEAST_EXPECT( - linesEnd[jss::error][jss::message] == - RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]); - BEAST_EXPECT( - linesEnd.isMember(jss::jsonrpc) && linesEnd[jss::jsonrpc] == "2.0"); - BEAST_EXPECT( - linesEnd.isMember(jss::ripplerpc) && - linesEnd[jss::ripplerpc] == "2.0"); + BEAST_EXPECT(linesEnd[jss::error][jss::message] == RPC::make_error(rpcINVALID_PARAMS)[jss::error_message]); + BEAST_EXPECT(linesEnd.isMember(jss::jsonrpc) && linesEnd[jss::jsonrpc] == "2.0"); + BEAST_EXPECT(linesEnd.isMember(jss::ripplerpc) && linesEnd[jss::ripplerpc] == "2.0"); BEAST_EXPECT(linesEnd.isMember(jss::id) && linesEnd[jss::id] == 5); } diff --git a/src/test/rpc/AccountObjects_test.cpp b/src/test/rpc/AccountObjects_test.cpp index 4f3e1817e1..e9c877b421 100644 --- a/src/test/rpc/AccountObjects_test.cpp +++ b/src/test/rpc/AccountObjects_test.cpp @@ -110,20 +110,16 @@ public: { Json::Value params; auto resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Missing field 'account'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Missing field 'account'."); } // test account non-string { auto testInvalidAccountParam = [&](auto const& param) { Json::Value params; params[jss::account] = param; - auto jrr = env.rpc( - "json", "account_objects", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_objects", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -136,19 +132,16 @@ public: // test error on malformed account string. { Json::Value params; - params[jss::account] = - "n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV"; + params[jss::account] = "n94JNrQYkDrpt62bbSR7nVEhdyAvcJXRAsjEkFYyqRkh9SUTYEqV"; auto resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == "Account malformed."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Account malformed."); } // test error on account that's not in the ledger. { Json::Value params; params[jss::account] = Account{"bogie"}.human(); auto resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == "Account not found."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Account not found."); } Account const bob{"bob"}; // test error on large ledger_index. @@ -157,8 +150,7 @@ public: params[jss::account] = bob.human(); params[jss::ledger_index] = 10; auto resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == "ledgerNotFound"); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "ledgerNotFound"); } env.fund(XRP(1000), bob); @@ -168,9 +160,7 @@ public: params[jss::account] = bob.human(); params[jss::type] = 10; auto resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'type', not string."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'type', not string."); } // test error on type param not a valid type { @@ -178,9 +168,7 @@ public: params[jss::account] = bob.human(); params[jss::type] = "expedited"; auto resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'type'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'type'."); } // test error on limit -ve { @@ -188,9 +176,7 @@ public: params[jss::account] = bob.human(); params[jss::limit] = -1; auto resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'limit', not unsigned integer."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'limit', not unsigned integer."); } // test errors on marker { @@ -210,39 +196,27 @@ public: std::string mark = to_string(resume_marker); params[jss::marker] = 10; resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'marker', not string."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'marker', not string."); params[jss::marker] = "This is a string with no comma"; resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'marker'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'marker'."); params[jss::marker] = "This string has a comma, but is not hex"; resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'marker'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'marker'."); params[jss::marker] = std::string(&mark[1U], 64); resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'marker'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'marker'."); params[jss::marker] = std::string(&mark[1U], 65); resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'marker'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'marker'."); params[jss::marker] = std::string(&mark[1U], 65) + "not hex"; resp = env.rpc("json", "account_objects", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'marker'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'marker'."); // Should this be an error? // A hex digit is absent from the end of marker. @@ -323,8 +297,7 @@ public: params[jss::limit] = 1; for (int i = 0; i < 4; ++i) { - auto resp = - env.rpc("json", "account_objects", to_string(params)); + auto resp = env.rpc("json", "account_objects", to_string(params)); auto& aobjs = resp[jss::result][jss::account_objects]; BEAST_EXPECT(aobjs.size() == 1); auto& aobj = aobjs[0U]; @@ -405,8 +378,7 @@ public: BEAST_EXPECT(!resp.isMember(jss::marker)); Json::Value& aobjs = resp[jss::result][jss::account_objects]; BEAST_EXPECT(aobjs.size() == 1); - BEAST_EXPECT( - aobjs[0u][sfLedgerEntryType.jsonName] == jss::NFTokenPage); + BEAST_EXPECT(aobjs[0u][sfLedgerEntryType.jsonName] == jss::NFTokenPage); BEAST_EXPECT(aobjs[0u][sfNFTokens.jsonName].size() == 1); } // test stepped one-at-a-time with limit=1, resume from prev marker @@ -415,8 +387,7 @@ public: params[jss::account] = bob.human(); params[jss::limit] = 1; - Json::Value resp = - env.rpc("json", "account_objects", to_string(params)); + Json::Value resp = env.rpc("json", "account_objects", to_string(params)); Json::Value& aobjs = resp[jss::result][jss::account_objects]; BEAST_EXPECT(aobjs.size() == 1); auto& aobj = aobjs[0U]; @@ -456,8 +427,7 @@ public: BEAST_EXPECT(!resp.isMember(jss::marker)); Json::Value& aobjs = resp[jss::result][jss::account_objects]; BEAST_EXPECT(aobjs.size() == 1); - BEAST_EXPECT( - aobjs[0u][sfLedgerEntryType.jsonName] == jss::NFTokenPage); + BEAST_EXPECT(aobjs[0u][sfLedgerEntryType.jsonName] == jss::NFTokenPage); BEAST_EXPECT(aobjs[0u][sfNFTokens.jsonName].size() == 1); } // test stepped one-at-a-time with limit=1, resume from prev marker @@ -467,8 +437,7 @@ public: params[jss::limit] = 1; for (int i = 0; i < 5; ++i) { - Json::Value resp = - env.rpc("json", "account_objects", to_string(params)); + Json::Value resp = env.rpc("json", "account_objects", to_string(params)); Json::Value& aobjs = resp[jss::result][jss::account_objects]; BEAST_EXPECT(aobjs.size() == 1); auto& aobj = aobjs[0U]; @@ -522,8 +491,7 @@ public: params[jss::limit] = 1; for (int i = 0; i < 6; ++i) { - Json::Value resp = - env.rpc("json", "account_objects", to_string(params)); + Json::Value resp = env.rpc("json", "account_objects", to_string(params)); Json::Value& aobjs = resp[jss::result][jss::account_objects]; BEAST_EXPECT(aobjs.size() == 1); auto& aobj = aobjs[0U]; @@ -558,8 +526,7 @@ public: Account const gw{"gateway"}; auto const USD = gw["USD"]; - auto const features = testable_amendments() | featureXChainBridge | - featurePermissionedDomains; + auto const features = testable_amendments() | featureXChainBridge | featurePermissionedDomains; Env env(*this, features); // Make a lambda we can use to get "account_objects" easily. @@ -589,8 +556,7 @@ public: // Make a lambda that checks if the response has error for invalid type auto acctObjsTypeIsInvalid = [](Json::Value const& resp) { return resp[jss::result].isMember(jss::error) && - resp[jss::result][jss::error_message] == - "Invalid field \'type\'."; + resp[jss::result][jss::error_message] == "Invalid field \'type\'."; }; env.fund(XRP(10000), gw, alice); @@ -631,8 +597,7 @@ public: auto const& nftPage = resp[jss::result][jss::account_objects][0u]; BEAST_EXPECT(nftPage[sfNFTokens.jsonName].size() == 1); BEAST_EXPECT( - nftPage[sfNFTokens.jsonName][0u][sfNFToken.jsonName] - [sfNFTokenID.jsonName] == to_string(nftID)); + nftPage[sfNFTokens.jsonName][0u][sfNFToken.jsonName][sfNFTokenID.jsonName] == to_string(nftID)); } // Set up a trust line so we can find it. @@ -647,8 +612,7 @@ public: auto const& state = resp[jss::result][jss::account_objects][0u]; BEAST_EXPECT(state[sfBalance.jsonName][jss::value].asInt() == -5); - BEAST_EXPECT( - state[sfHighLimit.jsonName][jss::value].asUInt() == 1000); + BEAST_EXPECT(state[sfHighLimit.jsonName][jss::value].asUInt() == 1000); } // gw writes a check for USD(10) to alice. env(check::create(gw, alice, USD(10))); @@ -682,8 +646,7 @@ public: jvEscrow[jss::Account] = gw.human(); jvEscrow[jss::Destination] = gw.human(); jvEscrow[jss::Amount] = XRP(100).value().getJson(JsonOptions::none); - jvEscrow[sfFinishAfter.jsonName] = - env.now().time_since_epoch().count() + 1; + jvEscrow[sfFinishAfter.jsonName] = env.now().time_since_epoch().count() + 1; env(jvEscrow); env.close(); } @@ -711,30 +674,22 @@ public: Json::Value const resp = acctObjs(gw, jss::permissioned_domain); BEAST_EXPECT(acctObjsIsSize(resp, 1)); - auto const& permissionedDomain = - resp[jss::result][jss::account_objects][0u]; - BEAST_EXPECT( - permissionedDomain.isMember(jss::Owner) && - (permissionedDomain[jss::Owner] == gw.human())); + auto const& permissionedDomain = resp[jss::result][jss::account_objects][0u]; + BEAST_EXPECT(permissionedDomain.isMember(jss::Owner) && (permissionedDomain[jss::Owner] == gw.human())); bool const check1 = BEAST_EXPECT( permissionedDomain.isMember(jss::AcceptedCredentials) && permissionedDomain[jss::AcceptedCredentials].isArray() && (permissionedDomain[jss::AcceptedCredentials].size() == 1) && - (permissionedDomain[jss::AcceptedCredentials][0u].isMember( - jss::Credential))); + (permissionedDomain[jss::AcceptedCredentials][0u].isMember(jss::Credential))); if (check1) { - auto const& credential = - permissionedDomain[jss::AcceptedCredentials][0u] - [jss::Credential]; + auto const& credential = permissionedDomain[jss::AcceptedCredentials][0u][jss::Credential]; BEAST_EXPECT( - credential.isMember(sfIssuer.jsonName) && - (credential[sfIssuer.jsonName] == issuer.human())); + credential.isMember(sfIssuer.jsonName) && (credential[sfIssuer.jsonName] == issuer.human())); BEAST_EXPECT( credential.isMember(sfCredentialType.jsonName) && - (credential[sfCredentialType.jsonName] == - strHex(credentialType1))); + (credential[sfCredentialType.jsonName] == strHex(credentialType1))); } } @@ -752,30 +707,17 @@ public: return scEnv.rpc("json", "account_objects", to_string(params)); }; - Json::Value const resp = - scEnvAcctObjs(Account::master, jss::bridge); + Json::Value const resp = scEnvAcctObjs(Account::master, jss::bridge); BEAST_EXPECT(acctObjsIsSize(resp, 1)); - auto const& acct_bridge = - resp[jss::result][jss::account_objects][0u]; - BEAST_EXPECT( - acct_bridge[sfAccount.jsonName] == Account::master.human()); - BEAST_EXPECT( - acct_bridge[sfLedgerEntryType.getJsonName()] == "Bridge"); - BEAST_EXPECT( - acct_bridge[sfXChainClaimID.getJsonName()].asUInt() == 0); - BEAST_EXPECT( - acct_bridge[sfXChainAccountClaimCount.getJsonName()].asUInt() == - 0); - BEAST_EXPECT( - acct_bridge[sfXChainAccountCreateCount.getJsonName()] - .asUInt() == 0); - BEAST_EXPECT( - acct_bridge[sfMinAccountCreateAmount.getJsonName()].asUInt() == - 20000000); - BEAST_EXPECT( - acct_bridge[sfSignatureReward.getJsonName()].asUInt() == - 1000000); + auto const& acct_bridge = resp[jss::result][jss::account_objects][0u]; + BEAST_EXPECT(acct_bridge[sfAccount.jsonName] == Account::master.human()); + BEAST_EXPECT(acct_bridge[sfLedgerEntryType.getJsonName()] == "Bridge"); + BEAST_EXPECT(acct_bridge[sfXChainClaimID.getJsonName()].asUInt() == 0); + BEAST_EXPECT(acct_bridge[sfXChainAccountClaimCount.getJsonName()].asUInt() == 0); + BEAST_EXPECT(acct_bridge[sfXChainAccountCreateCount.getJsonName()].asUInt() == 0); + BEAST_EXPECT(acct_bridge[sfMinAccountCreateAmount.getJsonName()].asUInt() == 20000000); + BEAST_EXPECT(acct_bridge[sfSignatureReward.getJsonName()].asUInt() == 1000000); BEAST_EXPECT(acct_bridge[sfXChainBridge.getJsonName()] == x.jvb); } { @@ -785,8 +727,7 @@ public: Env scEnv(*this, envconfig(), features); x.createScBridgeObjects(scEnv); - scEnv( - xchain_create_claim_id(x.scAlice, x.jvb, x.reward, x.mcAlice)); + scEnv(xchain_create_claim_id(x.scAlice, x.jvb, x.reward, x.mcAlice)); scEnv.close(); scEnv(xchain_create_claim_id(x.scBob, x.jvb, x.reward, x.mcBob)); scEnv.close(); @@ -801,28 +742,21 @@ public: { // Find the xchain sequence number for Andrea. - Json::Value const resp = - scEnvAcctObjs(x.scAlice, jss::xchain_owned_claim_id); + Json::Value const resp = scEnvAcctObjs(x.scAlice, jss::xchain_owned_claim_id); BEAST_EXPECT(acctObjsIsSize(resp, 1)); - auto const& xchain_seq = - resp[jss::result][jss::account_objects][0u]; - BEAST_EXPECT( - xchain_seq[sfAccount.jsonName] == x.scAlice.human()); - BEAST_EXPECT( - xchain_seq[sfXChainClaimID.getJsonName()].asUInt() == 1); + auto const& xchain_seq = resp[jss::result][jss::account_objects][0u]; + BEAST_EXPECT(xchain_seq[sfAccount.jsonName] == x.scAlice.human()); + BEAST_EXPECT(xchain_seq[sfXChainClaimID.getJsonName()].asUInt() == 1); } { // and the one for Bob - Json::Value const resp = - scEnvAcctObjs(x.scBob, jss::xchain_owned_claim_id); + Json::Value const resp = scEnvAcctObjs(x.scBob, jss::xchain_owned_claim_id); BEAST_EXPECT(acctObjsIsSize(resp, 1)); - auto const& xchain_seq = - resp[jss::result][jss::account_objects][0u]; + auto const& xchain_seq = resp[jss::result][jss::account_objects][0u]; BEAST_EXPECT(xchain_seq[sfAccount.jsonName] == x.scBob.human()); - BEAST_EXPECT( - xchain_seq[sfXChainClaimID.getJsonName()].asUInt() == 2); + BEAST_EXPECT(xchain_seq[sfXChainClaimID.getJsonName()].asUInt() == 2); } } { @@ -836,16 +770,7 @@ public: // account (Account::master) to collect the signatures until a // quorum is reached scEnv(test::jtx::create_account_attestation( - x.scAttester, - x.jvb, - x.mcCarol, - amt, - x.reward, - x.payees[0], - true, - 1, - x.scuAlice, - x.signers[0])); + x.scAttester, x.jvb, x.mcCarol, amt, x.reward, x.payees[0], true, 1, x.scuAlice, x.signers[0])); scEnv.close(); auto scEnvAcctObjs = [&](Account const& acct, char const* type) { @@ -858,19 +783,12 @@ public: { // Find the xchain_create_account_claim_id - Json::Value const resp = scEnvAcctObjs( - Account::master, jss::xchain_owned_create_account_claim_id); + Json::Value const resp = scEnvAcctObjs(Account::master, jss::xchain_owned_create_account_claim_id); BEAST_EXPECT(acctObjsIsSize(resp, 1)); - auto const& xchain_create_account_claim_id = - resp[jss::result][jss::account_objects][0u]; - BEAST_EXPECT( - xchain_create_account_claim_id[sfAccount.jsonName] == - Account::master.human()); - BEAST_EXPECT( - xchain_create_account_claim_id[sfXChainAccountCreateCount - .getJsonName()] - .asUInt() == 1); + auto const& xchain_create_account_claim_id = resp[jss::result][jss::account_objects][0u]; + BEAST_EXPECT(xchain_create_account_claim_id[sfAccount.jsonName] == Account::master.human()); + BEAST_EXPECT(xchain_create_account_claim_id[sfXChainAccountCreateCount.getJsonName()].asUInt() == 1); } } @@ -894,8 +812,7 @@ public: jvPayChan[jss::TransactionType] = jss::PaymentChannelCreate; jvPayChan[jss::Account] = gw.human(); jvPayChan[jss::Destination] = alice.human(); - jvPayChan[jss::Amount] = - XRP(300).value().getJson(JsonOptions::none); + jvPayChan[jss::Amount] = XRP(300).value().getJson(JsonOptions::none); jvPayChan[sfSettleDelay.jsonName] = 24 * 60 * 60; jvPayChan[sfPublicKey.jsonName] = strHex(gw.pk().slice()); env(jvPayChan); @@ -909,8 +826,7 @@ public: auto const& payChan = resp[jss::result][jss::account_objects][0u]; BEAST_EXPECT(payChan[sfAccount.jsonName] == gw.human()); BEAST_EXPECT(payChan[sfAmount.jsonName].asUInt() == 300'000'000); - BEAST_EXPECT( - payChan[sfSettleDelay.jsonName].asUInt() == 24 * 60 * 60); + BEAST_EXPECT(payChan[sfSettleDelay.jsonName].asUInt() == 24 * 60 * 60); } { @@ -939,11 +855,9 @@ public: Json::Value const resp = acctObjs(gw, jss::signer_list); BEAST_EXPECT(acctObjsIsSize(resp, 1)); - auto const& signerList = - resp[jss::result][jss::account_objects][0u]; + auto const& signerList = resp[jss::result][jss::account_objects][0u]; BEAST_EXPECT(signerList[sfSignerQuorum.jsonName] == 6); - auto const& entry = signerList[sfSignerEntries.jsonName][0u] - [sfSignerEntry.jsonName]; + auto const& entry = signerList[sfSignerEntries.jsonName][0u][sfSignerEntry.jsonName]; BEAST_EXPECT(entry[sfAccount.jsonName] == alice.human()); BEAST_EXPECT(entry[sfSignerWeight.jsonName].asUInt() == 7); } @@ -983,8 +897,7 @@ public: return v; }(); - std::uint32_t const expectedAccountObjects{ - static_cast(std::size(expectedLedgerTypes))}; + std::uint32_t const expectedAccountObjects{static_cast(std::size(expectedLedgerTypes))}; if (BEAST_EXPECT(acctObjsIsSize(resp, expectedAccountObjects))) { @@ -993,8 +906,7 @@ public: gotLedgerTypes.reserve(expectedAccountObjects); for (std::uint32_t i = 0; i < expectedAccountObjects; ++i) { - gotLedgerTypes.push_back( - aobjs[i]["LedgerEntryType"].asString()); + gotLedgerTypes.push_back(aobjs[i]["LedgerEntryType"].asString()); } std::sort(gotLedgerTypes.begin(), gotLedgerTypes.end()); BEAST_EXPECT(gotLedgerTypes == expectedLedgerTypes); @@ -1017,19 +929,15 @@ public: } { // Make a lambda to get the types - auto getTypes = [&](Json::Value const& resp, - std::vector& typesOut) { + auto getTypes = [&](Json::Value const& resp, std::vector& typesOut) { auto const objs = resp[jss::result][jss::account_objects]; for (auto const& obj : resp[jss::result][jss::account_objects]) - typesOut.push_back( - obj[sfLedgerEntryType.fieldName].asString()); + typesOut.push_back(obj[sfLedgerEntryType.fieldName].asString()); std::sort(typesOut.begin(), typesOut.end()); }; // Make a lambda we can use to check the number of fetched // account objects and their ledger type - auto expectObjects = - [&](Json::Value const& resp, - std::vector const& types) -> bool { + auto expectObjects = [&](Json::Value const& resp, std::vector const& types) -> bool { if (!acctObjsIsSize(resp, types.size())) return false; std::vector typesOut; @@ -1043,36 +951,24 @@ public: auto const lines = getAccountLines(env, amm.ammAccount()); BEAST_EXPECT(lines[jss::lines].size() == 3); // request AMM only, doesn't depend on the limit - BEAST_EXPECT( - acctObjsIsSize(acctObjs(amm.ammAccount(), jss::amm), 1)); + BEAST_EXPECT(acctObjsIsSize(acctObjs(amm.ammAccount(), jss::amm), 1)); // request first two objects auto resp = acctObjs(amm.ammAccount(), std::nullopt, 2); std::vector typesOut; getTypes(resp, typesOut); // request next two objects - resp = acctObjs( - amm.ammAccount(), - std::nullopt, - 10, - resp[jss::result][jss::marker].asString()); + resp = acctObjs(amm.ammAccount(), std::nullopt, 10, resp[jss::result][jss::marker].asString()); getTypes(resp, typesOut); BEAST_EXPECT( (typesOut == std::vector{ - jss::AMM.c_str(), - jss::RippleState.c_str(), - jss::RippleState.c_str(), - jss::RippleState.c_str()})); + jss::AMM.c_str(), jss::RippleState.c_str(), jss::RippleState.c_str(), jss::RippleState.c_str()})); // filter by state: there are three trustlines resp = acctObjs(amm.ammAccount(), jss::state, 10); - BEAST_EXPECT(expectObjects( - resp, - {jss::RippleState.c_str(), - jss::RippleState.c_str(), - jss::RippleState.c_str()})); - // AMM account doesn't own offers BEAST_EXPECT( - acctObjsIsSize(acctObjs(amm.ammAccount(), jss::offer), 0)); + expectObjects(resp, {jss::RippleState.c_str(), jss::RippleState.c_str(), jss::RippleState.c_str()})); + // AMM account doesn't own offers + BEAST_EXPECT(acctObjsIsSize(acctObjs(amm.ammAccount(), jss::offer), 0)); // gw account doesn't own AMM object BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::amm), 0)); } @@ -1125,8 +1021,7 @@ public: Json::Value params; params[jss::account] = bob.human(); params[jss::ledger_index] = "validated"; - Json::Value const resp = - env.rpc("json", "account_nfts", to_string(params)); + Json::Value const resp = env.rpc("json", "account_nfts", to_string(params)); Json::Value const& nfts = resp[jss::result][jss::account_nfts]; for (Json::Value const& nft : nfts) tokenIDs.push_back(nft["NFTokenID"]); @@ -1135,23 +1030,20 @@ public: // this lambda function is used to check if the account_nfts method // returns the correct token information. lastIndex is used to query the // last marker. - auto compareNFTs = [&tokenIDs, &env, &bob]( - unsigned const limit, unsigned const lastIndex) { + auto compareNFTs = [&tokenIDs, &env, &bob](unsigned const limit, unsigned const lastIndex) { Json::Value params; params[jss::account] = bob.human(); params[jss::limit] = limit; params[jss::marker] = tokenIDs[lastIndex]; params[jss::ledger_index] = "validated"; - Json::Value const resp = - env.rpc("json", "account_nfts", to_string(params)); + Json::Value const resp = env.rpc("json", "account_nfts", to_string(params)); if (resp[jss::result].isMember(jss::error)) return false; Json::Value const& nfts = resp[jss::result][jss::account_nfts]; - unsigned const nftsCount = tokenIDs.size() - lastIndex - 1 < limit - ? tokenIDs.size() - lastIndex - 1 - : limit; + unsigned const nftsCount = + tokenIDs.size() - lastIndex - 1 < limit ? tokenIDs.size() - lastIndex - 1 : limit; if (nfts.size() != nftsCount) return false; @@ -1172,26 +1064,22 @@ public: BEAST_EXPECT(compareNFTs(4, 7)); // lambda that holds common code for invalid cases. - auto testInvalidMarker = [&env, &bob]( - auto marker, char const* errorMessage) { + auto testInvalidMarker = [&env, &bob](auto marker, char const* errorMessage) { Json::Value params; params[jss::account] = bob.human(); params[jss::limit] = 4; params[jss::ledger_index] = jss::validated; params[jss::marker] = marker; - Json::Value const resp = - env.rpc("json", "account_nfts", to_string(params)); + Json::Value const resp = env.rpc("json", "account_nfts", to_string(params)); return resp[jss::result][jss::error_message] == errorMessage; }; // test an invalid marker that is not a string - BEAST_EXPECT( - testInvalidMarker(17, "Invalid field \'marker\', not string.")); + BEAST_EXPECT(testInvalidMarker(17, "Invalid field \'marker\', not string.")); // test an invalid marker that has a non-hex character BEAST_EXPECT(testInvalidMarker( - "00000000F51DFC2A09D62CBBA1DFBDD4691DAC96AD98B900000000000000000G", - "Invalid field \'marker\'.")); + "00000000F51DFC2A09D62CBBA1DFBDD4691DAC96AD98B900000000000000000G", "Invalid field \'marker\'.")); // this lambda function is used to create some fake marker using given // taxon and sequence because we want to test some unassociated markers @@ -1202,20 +1090,17 @@ public: std::uint16_t flags = 0, std::uint16_t fee = 0) { // the marker has the exact same format as an NFTokenID - return to_string(NFTokenMint::createNFTokenID( - flags, fee, issuer, nft::toTaxon(taxon), tokenSeq)); + return to_string(NFTokenMint::createNFTokenID(flags, fee, issuer, nft::toTaxon(taxon), tokenSeq)); }; // test an unassociated marker which does not exist in the NFTokenIDs - BEAST_EXPECT(testInvalidMarker( - createFakeNFTMarker(bob.id(), 0x000000000, 0x00000000), - "Invalid field \'marker\'.")); + BEAST_EXPECT( + testInvalidMarker(createFakeNFTMarker(bob.id(), 0x000000000, 0x00000000), "Invalid field \'marker\'.")); // test an unassociated marker which exceeds the maximum value of the // existing NFTokenID - BEAST_EXPECT(testInvalidMarker( - createFakeNFTMarker(bob.id(), 0xFFFFFFFF, 0xFFFFFFFF), - "Invalid field \'marker\'.")); + BEAST_EXPECT( + testInvalidMarker(createFakeNFTMarker(bob.id(), 0xFFFFFFFF, 0xFFFFFFFF), "Invalid field \'marker\'.")); } void @@ -1231,11 +1116,9 @@ public: auto testInvalidAccountParam = [&](auto const& param) { Json::Value params; params[jss::account] = param; - auto jrr = env.rpc( - "json", "account_nfts", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_nfts", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -1306,10 +1189,8 @@ public: params[jss::limit] = limit; params[jss::ledger_index] = jss::validated; params[jss::marker] = marker; - Json::Value const resp = - env.rpc("json", "account_objects", to_string(params)); - return resp[jss::result][jss::error_message] == - "Invalid field \'marker\'."; + Json::Value const resp = env.rpc("json", "account_objects", to_string(params)); + return resp[jss::result][jss::error_message] == "Invalid field \'marker\'."; }; auto const markerStr = marker.asString(); @@ -1395,8 +1276,7 @@ public: auto resp = env.rpc("json", "account_objects", to_string(params)); auto& accountObjects = resp[jss::result][jss::account_objects]; BEAST_EXPECT(!resp[jss::result].isMember(jss::error)); - BEAST_EXPECT( - accountObjects.size() == accountObjectSize - limit * 2); + BEAST_EXPECT(accountObjects.size() == accountObjectSize - limit * 2); BEAST_EXPECT(!resp[jss::result].isMember(jss::marker)); } diff --git a/src/test/rpc/AccountOffers_test.cpp b/src/test/rpc/AccountOffers_test.cpp index 2c03239bd8..ffa1d70992 100644 --- a/src/test/rpc/AccountOffers_test.cpp +++ b/src/test/rpc/AccountOffers_test.cpp @@ -12,8 +12,7 @@ public: static bool checkMarker(Json::Value const& val) { - return val.isMember(jss::marker) && val[jss::marker].isString() && - val[jss::marker].asString().size() > 0; + return val.isMember(jss::marker) && val[jss::marker].isString() && val[jss::marker].asString().size() > 0; } void @@ -44,8 +43,7 @@ public: } // make non-limited RPC call - auto const jro_nl = - env.rpc("account_offers", bob.human())[jss::result][jss::offers]; + auto const jro_nl = env.rpc("account_offers", bob.human())[jss::result][jss::offers]; BEAST_EXPECT(checkArraySize(jro_nl, offer_count)); // now make a low-limit query, should get "corrected" @@ -54,8 +52,7 @@ public: Json::Value jvParams; jvParams[jss::account] = bob.human(); jvParams[jss::limit] = 1u; - auto const jrr_l = env.rpc( - "json", "account_offers", jvParams.toStyledString())[jss::result]; + auto const jrr_l = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; auto const& jro_l = jrr_l[jss::offers]; BEAST_EXPECT(checkMarker(jrr_l)); // 9u is the expected size, since one account object is a trustline @@ -65,8 +62,7 @@ public: void testSequential(bool asAdmin) { - testcase( - std::string("Sequential - ") + (asAdmin ? "admin" : "non-admin")); + testcase(std::string("Sequential - ") + (asAdmin ? "admin" : "non-admin")); using namespace jtx; Env env{*this, asAdmin ? envconfig() : envconfig(no_admin)}; @@ -88,8 +84,7 @@ public: env(offer(bob, XRP(30), USD_gw(6))); // make the RPC call - auto const jroOuter = - env.rpc("account_offers", bob.human())[jss::result][jss::offers]; + auto const jroOuter = env.rpc("account_offers", bob.human())[jss::result][jss::offers]; if (BEAST_EXPECT(checkArraySize(jroOuter, 3u))) { // Note that the returned offers are sorted by index, not by @@ -98,22 +93,19 @@ public: // if the sequence numbers or the account IDs change. BEAST_EXPECT(jroOuter[0u][jss::quality] == "100000000"); BEAST_EXPECT(jroOuter[0u][jss::taker_gets][jss::currency] == "USD"); - BEAST_EXPECT( - jroOuter[0u][jss::taker_gets][jss::issuer] == gw.human()); + BEAST_EXPECT(jroOuter[0u][jss::taker_gets][jss::issuer] == gw.human()); BEAST_EXPECT(jroOuter[0u][jss::taker_gets][jss::value] == "2"); BEAST_EXPECT(jroOuter[0u][jss::taker_pays] == "200000000"); BEAST_EXPECT(jroOuter[1u][jss::quality] == "100000000"); BEAST_EXPECT(jroOuter[1u][jss::taker_gets][jss::currency] == "USD"); - BEAST_EXPECT( - jroOuter[1u][jss::taker_gets][jss::issuer] == bob.human()); + BEAST_EXPECT(jroOuter[1u][jss::taker_gets][jss::issuer] == bob.human()); BEAST_EXPECT(jroOuter[1u][jss::taker_gets][jss::value] == "1"); BEAST_EXPECT(jroOuter[1u][jss::taker_pays] == "100000000"); BEAST_EXPECT(jroOuter[2u][jss::quality] == "5000000"); BEAST_EXPECT(jroOuter[2u][jss::taker_gets][jss::currency] == "USD"); - BEAST_EXPECT( - jroOuter[2u][jss::taker_gets][jss::issuer] == gw.human()); + BEAST_EXPECT(jroOuter[2u][jss::taker_gets][jss::issuer] == gw.human()); BEAST_EXPECT(jroOuter[2u][jss::taker_gets][jss::value] == "6"); BEAST_EXPECT(jroOuter[2u][jss::taker_pays] == "30000000"); } @@ -123,10 +115,7 @@ public: Json::Value jvParams; jvParams[jss::account] = bob.human(); jvParams[jss::limit] = 1u; - auto const jrr_l_1 = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr_l_1 = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; auto const& jro_l_1 = jrr_l_1[jss::offers]; // there is a difference in the validation of the limit param // between admin and non-admin requests. with admin requests, the @@ -134,19 +123,14 @@ public: // non-admin there are pre-configured limit ranges applied. That's // why we have different BEAST_EXPECT()s here for the two scenarios BEAST_EXPECT(checkArraySize(jro_l_1, asAdmin ? 1u : 3u)); - BEAST_EXPECT( - asAdmin ? checkMarker(jrr_l_1) - : (!jrr_l_1.isMember(jss::marker))); + BEAST_EXPECT(asAdmin ? checkMarker(jrr_l_1) : (!jrr_l_1.isMember(jss::marker))); if (asAdmin) { BEAST_EXPECT(jroOuter[0u] == jro_l_1[0u]); // second item...with previous marker passed jvParams[jss::marker] = jrr_l_1[jss::marker]; - auto const jrr_l_2 = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr_l_2 = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; auto const& jro_l_2 = jrr_l_2[jss::offers]; BEAST_EXPECT(checkMarker(jrr_l_2)); BEAST_EXPECT(checkArraySize(jro_l_2, 1u)); @@ -155,10 +139,7 @@ public: // last item...with previous marker passed jvParams[jss::marker] = jrr_l_2[jss::marker]; jvParams[jss::limit] = 10u; - auto const jrr_l_3 = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr_l_3 = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; auto const& jro_l_3 = jrr_l_3[jss::offers]; BEAST_EXPECT(!jrr_l_3.isMember(jss::marker)); BEAST_EXPECT(checkArraySize(jro_l_3, 1u)); @@ -174,10 +155,7 @@ public: Json::Value jvParams; jvParams[jss::account] = bob.human(); jvParams[jss::limit] = 0u; - auto const jrr = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; BEAST_EXPECT(jrr.isMember(jss::error_message)); } } @@ -210,11 +188,9 @@ public: auto testInvalidAccountParam = [&](auto const& param) { Json::Value params; params[jss::account] = param; - auto jrr = env.rpc( - "json", "account_offers", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_offers", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -229,10 +205,7 @@ public: // empty string account Json::Value jvParams; jvParams[jss::account] = ""; - auto const jrr = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; BEAST_EXPECT(jrr[jss::error] == "actMalformed"); BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error_message] == "Account malformed."); @@ -240,8 +213,7 @@ public: { // bogus account value - auto const jrr = env.rpc( - "account_offers", Account("bogus").human())[jss::result]; + auto const jrr = env.rpc("account_offers", Account("bogus").human())[jss::result]; BEAST_EXPECT(jrr[jss::error] == "actNotFound"); BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error_message] == "Account not found."); @@ -252,15 +224,10 @@ public: Json::Value jvParams; jvParams[jss::account] = bob.human(); jvParams[jss::limit] = "0"; // NOT an integer - auto const jrr = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'limit', not unsigned integer."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'limit', not unsigned integer."); } { @@ -268,15 +235,10 @@ public: Json::Value jvParams; jvParams[jss::account] = bob.human(); jvParams[jss::marker] = "NOT_A_MARKER"; - auto const jrr = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); - BEAST_EXPECTS( - jrr[jss::error_message] == "Invalid field 'marker'.", - jrr.toStyledString()); + BEAST_EXPECTS(jrr[jss::error_message] == "Invalid field 'marker'.", jrr.toStyledString()); } { @@ -284,15 +246,10 @@ public: Json::Value jvParams; jvParams[jss::account] = bob.human(); jvParams[jss::marker] = 1; - auto const jrr = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'marker', not string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not string."); } { @@ -300,10 +257,7 @@ public: Json::Value jvParams; jvParams[jss::account] = bob.human(); jvParams[jss::ledger_index] = 10u; - auto const jrr = env.rpc( - "json", - "account_offers", - jvParams.toStyledString())[jss::result]; + auto const jrr = env.rpc("json", "account_offers", jvParams.toStyledString())[jss::result]; BEAST_EXPECT(jrr[jss::error] == "lgrNotFound"); BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound"); diff --git a/src/test/rpc/AccountSet_test.cpp b/src/test/rpc/AccountSet_test.cpp index 40ef4acba7..2e238773f9 100644 --- a/src/test/rpc/AccountSet_test.cpp +++ b/src/test/rpc/AccountSet_test.cpp @@ -44,12 +44,9 @@ public: env(regkey(alice, alie)); env.close(); - auto testFlags = [this, &alice, &alie, &env]( - std::initializer_list goodFlags) { + auto testFlags = [this, &alice, &alie, &env](std::initializer_list goodFlags) { std::uint32_t const orig_flags = (*env.le(alice))[sfFlags]; - for (std::uint32_t flag{1u}; - flag < std::numeric_limits::digits; - ++flag) + for (std::uint32_t flag{1u}; flag < std::numeric_limits::digits; ++flag) { if (flag == asfNoFreeze) { @@ -66,10 +63,8 @@ public: continue; } - if (flag == asfDisallowIncomingCheck || - flag == asfDisallowIncomingPayChan || - flag == asfDisallowIncomingNFTokenOffer || - flag == asfDisallowIncomingTrustline) + if (flag == asfDisallowIncomingCheck || flag == asfDisallowIncomingPayChan || + flag == asfDisallowIncomingNFTokenOffer || flag == asfDisallowIncomingTrustline) { // These flags are part of the DisallowIncoming amendment // and are tested elsewhere @@ -88,8 +83,7 @@ public: continue; } - if (std::find(goodFlags.begin(), goodFlags.end(), flag) != - goodFlags.end()) + if (std::find(goodFlags.begin(), goodFlags.end(), flag) != goodFlags.end()) { // Good flag env.require(nflags(alice, flag)); @@ -200,8 +194,7 @@ public: std::size_t const maxLength = 256; for (std::size_t len = maxLength - 1; len <= maxLength + 1; ++len) { - std::string domain2 = - std::string(len - domain.length() - 1, 'a') + "." + domain; + std::string domain2 = std::string(len - domain.length() - 1, 'a') + "." + domain; BEAST_EXPECT(domain2.length() == len); @@ -233,9 +226,7 @@ public: auto const rkp = randomKeyPair(KeyType::ed25519); jt[sfMessageKey.fieldName] = strHex(rkp.first.slice()); env(jt); - BEAST_EXPECT( - strHex((*env.le(alice))[sfMessageKey]) == - strHex(rkp.first.slice())); + BEAST_EXPECT(strHex((*env.le(alice))[sfMessageKey]) == strHex(rkp.first.slice())); jt[sfMessageKey.fieldName] = ""; env(jt); @@ -257,8 +248,7 @@ public: env.fund(XRP(10000), alice); auto jt = noop(alice); - std::string const locator = - "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF05"; + std::string const locator = "9633EC8AF54F16B5286DB1D7B519EF49EEFC050C0C8AC4384F1D88ACD1BFDF05"; jt[sfWalletLocator.fieldName] = locator; env(jt); BEAST_EXPECT(to_string((*env.le(alice))[sfWalletLocator]) == locator); @@ -302,9 +292,7 @@ public: testcase("TransferRate"); using namespace test::jtx; - auto doTests = [this]( - FeatureBitset const& features, - std::initializer_list testData) { + auto doTests = [this](FeatureBitset const& features, std::initializer_list testData) { Env env(*this, features); Account const alice("alice"); @@ -319,9 +307,7 @@ public: if (!(*env.le(alice))[~sfTransferRate]) BEAST_EXPECT(r.get == 1.0); else - BEAST_EXPECT( - *(*env.le(alice))[~sfTransferRate] == - r.get * QUALITY_ONE); + BEAST_EXPECT(*(*env.le(alice))[~sfTransferRate] == r.get * QUALITY_ONE); } }; @@ -349,8 +335,7 @@ public: auto const USD = gw["USD"]; // Test gateway with a variety of allowed transfer rates - for (double transferRate = 1.0; transferRate <= 2.0; - transferRate += 0.03125) + for (double transferRate = 1.0; transferRate <= 2.0; transferRate += 0.03125) { Env env(*this); env.fund(XRP(10000), gw, alice, bob); @@ -362,8 +347,7 @@ public: auto const amount = USD(1); Rate const rate(transferRate * QUALITY_ONE); - auto const amountWithRate = - toAmount(multiply(amount.value(), rate)); + auto const amountWithRate = toAmount(multiply(amount.value(), rate)); env(pay(gw, alice, USD(10))); env.close(); @@ -412,25 +396,22 @@ public: // Note that we're bypassing almost all of the ledger's safety // checks with this modify() call. If you call close() between // here and the end of the test all the effort will be lost. - env.app().openLedger().modify( - [&gw, transferRate](OpenView& view, beast::Journal j) { - // Get the account root we want to hijack. - auto const sle = view.read(keylet::account(gw.id())); - if (!sle) - return false; // This would be really surprising! + env.app().openLedger().modify([&gw, transferRate](OpenView& view, beast::Journal j) { + // Get the account root we want to hijack. + auto const sle = view.read(keylet::account(gw.id())); + if (!sle) + return false; // This would be really surprising! - // We'll insert a replacement for the account root - // with the higher (currently invalid) transfer rate. - auto replacement = std::make_shared(*sle, sle->key()); - (*replacement)[sfTransferRate] = - static_cast(transferRate * QUALITY_ONE); - view.rawReplace(replacement); - return true; - }); + // We'll insert a replacement for the account root + // with the higher (currently invalid) transfer rate. + auto replacement = std::make_shared(*sle, sle->key()); + (*replacement)[sfTransferRate] = static_cast(transferRate * QUALITY_ONE); + view.rawReplace(replacement); + return true; + }); auto const amount = USD(1); - auto const amountWithRate = toAmount( - multiply(amount.value(), Rate(transferRate * QUALITY_ONE))); + auto const amountWithRate = toAmount(multiply(amount.value(), Rate(transferRate * QUALITY_ONE))); env(pay(gw, alice, USD(10))); env(pay(alice, bob, amount), sendmax(USD(10))); @@ -478,9 +459,7 @@ public: jt[sfFlags.fieldName] = tfAccountSetMask; env(jt, ter(temINVALID_FLAG)); - env(fset(alice, asfDisableMaster), - sig(alice), - ter(tecNO_ALTERNATIVE_KEY)); + env(fset(alice, asfDisableMaster), sig(alice), ter(tecNO_ALTERNATIVE_KEY)); } void diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp index 36d29236d1..3cc9dbc77c 100644 --- a/src/test/rpc/AccountTx_test.cpp +++ b/src/test/rpc/AccountTx_test.cpp @@ -52,38 +52,26 @@ class AccountTx_test : public beast::unit_test::suite checkSanity(Json::Value const& txNode, NodeSanity const& sane) { BEAST_EXPECT(txNode[jss::validated].asBool() == true); - BEAST_EXPECT( - txNode[jss::tx][sfTransactionType.jsonName].asString() == - sane.txType); + BEAST_EXPECT(txNode[jss::tx][sfTransactionType.jsonName].asString() == sane.txType); // Make sure all of the expected node types are present. boost::container::flat_set createdNodes; boost::container::flat_set deletedNodes; boost::container::flat_set modifiedNodes; - for (Json::Value const& metaNode : - txNode[jss::meta][sfAffectedNodes.jsonName]) + for (Json::Value const& metaNode : txNode[jss::meta][sfAffectedNodes.jsonName]) { if (metaNode.isMember(sfCreatedNode.jsonName)) - createdNodes.insert( - metaNode[sfCreatedNode.jsonName][sfLedgerEntryType.jsonName] - .asString()); + createdNodes.insert(metaNode[sfCreatedNode.jsonName][sfLedgerEntryType.jsonName].asString()); else if (metaNode.isMember(sfDeletedNode.jsonName)) - deletedNodes.insert( - metaNode[sfDeletedNode.jsonName][sfLedgerEntryType.jsonName] - .asString()); + deletedNodes.insert(metaNode[sfDeletedNode.jsonName][sfLedgerEntryType.jsonName].asString()); else if (metaNode.isMember(sfModifiedNode.jsonName)) - modifiedNodes.insert(metaNode[sfModifiedNode.jsonName] - [sfLedgerEntryType.jsonName] - .asString()); + modifiedNodes.insert(metaNode[sfModifiedNode.jsonName][sfLedgerEntryType.jsonName].asString()); else - fail( - "Unexpected or unlabeled node type in metadata.", - __FILE__, - __LINE__); + fail("Unexpected or unlabeled node type in metadata.", __FILE__, __LINE__); } BEAST_EXPECT(createdNodes == sane.created); @@ -112,47 +100,34 @@ class AccountTx_test : public beast::unit_test::suite switch (apiVersion) { case 1: - return j.isMember(jss::result) && - (j[jss::result][jss::status] == "success") && + return j.isMember(jss::result) && (j[jss::result][jss::status] == "success") && (j[jss::result][jss::transactions].size() == 2) && - (j[jss::result][jss::transactions][0u][jss::tx] - [jss::TransactionType] == jss::AccountSet) && - (j[jss::result][jss::transactions][1u][jss::tx] - [jss::TransactionType] == jss::Payment) && - (j[jss::result][jss::transactions][1u][jss::tx] - [jss::DeliverMax] == "10000000010") && - (j[jss::result][jss::transactions][1u][jss::tx] - [jss::Amount] == - j[jss::result][jss::transactions][1u][jss::tx] - [jss::DeliverMax]); + (j[jss::result][jss::transactions][0u][jss::tx][jss::TransactionType] == jss::AccountSet) && + (j[jss::result][jss::transactions][1u][jss::tx][jss::TransactionType] == jss::Payment) && + (j[jss::result][jss::transactions][1u][jss::tx][jss::DeliverMax] == "10000000010") && + (j[jss::result][jss::transactions][1u][jss::tx][jss::Amount] == + j[jss::result][jss::transactions][1u][jss::tx][jss::DeliverMax]); case 2: case 3: - if (j.isMember(jss::result) && - (j[jss::result][jss::status] == "success") && + if (j.isMember(jss::result) && (j[jss::result][jss::status] == "success") && (j[jss::result][jss::transactions].size() == 2) && - (j[jss::result][jss::transactions][0u][jss::tx_json] - [jss::TransactionType] == jss::AccountSet)) + (j[jss::result][jss::transactions][0u][jss::tx_json][jss::TransactionType] == jss::AccountSet)) { - auto const& payment = - j[jss::result][jss::transactions][1u]; + auto const& payment = j[jss::result][jss::transactions][1u]; return (payment.isMember(jss::tx_json)) && - (payment[jss::tx_json][jss::TransactionType] == - jss::Payment) && - (payment[jss::tx_json][jss::DeliverMax] == - "10000000010") && + (payment[jss::tx_json][jss::TransactionType] == jss::Payment) && + (payment[jss::tx_json][jss::DeliverMax] == "10000000010") && (!payment[jss::tx_json].isMember(jss::Amount)) && (!payment[jss::tx_json].isMember(jss::hash)) && (payment[jss::hash] == "9F3085D85F472D1CC29627F260DF68EDE59D42D1D0C33E345" "ECF0D4CE981D0A8") && - (payment[jss::validated] == true) && - (payment[jss::ledger_index] == 3) && + (payment[jss::validated] == true) && (payment[jss::ledger_index] == 3) && (payment[jss::ledger_hash] == "5476DCD816EA04CBBA57D47BBF1FC58A5217CC93A5ADD79CB" "580A5AFDD727E33") && - (payment[jss::close_time_iso] == - "2000-01-01T00:00:10Z"); + (payment[jss::close_time_iso] == "2000-01-01T00:00:10Z"); } else return false; @@ -163,115 +138,89 @@ class AccountTx_test : public beast::unit_test::suite }; auto noTxs = [](Json::Value const& j) { - return j.isMember(jss::result) && - (j[jss::result][jss::status] == "success") && + return j.isMember(jss::result) && (j[jss::result][jss::status] == "success") && (j[jss::result][jss::transactions].size() == 0); }; auto isErr = [](Json::Value const& j, error_code_i code) { - return j.isMember(jss::result) && - j[jss::result].isMember(jss::error) && + return j.isMember(jss::result) && j[jss::result].isMember(jss::error) && j[jss::result][jss::error] == RPC::get_error_info(code).token; }; Json::Value jParams; jParams[jss::api_version] = apiVersion; - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(jParams)), - rpcINVALID_PARAMS)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(jParams)), rpcINVALID_PARAMS)); jParams[jss::account] = "0xDEADBEEF"; - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(jParams)), - rpcACT_MALFORMED)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(jParams)), rpcACT_MALFORMED)); jParams[jss::account] = A1.human(); - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(jParams)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(jParams)))); // Ledger min/max index { Json::Value p{jParams}; p[jss::ledger_index_min] = -1; p[jss::ledger_index_max] = -1; - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); p[jss::ledger_index_min] = 0; p[jss::ledger_index_max] = 100; if (apiVersion < 2u) - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); else - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcLGR_IDX_MALFORMED)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcLGR_IDX_MALFORMED)); p[jss::ledger_index_min] = 1; p[jss::ledger_index_max] = 2; if (apiVersion < 2u) - BEAST_EXPECT( - noTxs(env.rpc("json", "account_tx", to_string(p)))); + BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); else - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcLGR_IDX_MALFORMED)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcLGR_IDX_MALFORMED)); p[jss::ledger_index_min] = 2; p[jss::ledger_index_max] = 1; BEAST_EXPECT(isErr( env.rpc("json", "account_tx", to_string(p)), - (apiVersion == 1 ? rpcLGR_IDXS_INVALID - : rpcINVALID_LGR_RANGE))); + (apiVersion == 1 ? rpcLGR_IDXS_INVALID : rpcINVALID_LGR_RANGE))); } // Ledger index min only { Json::Value p{jParams}; p[jss::ledger_index_min] = -1; - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); p[jss::ledger_index_min] = 1; if (apiVersion < 2u) - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); else - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcLGR_IDX_MALFORMED)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcLGR_IDX_MALFORMED)); p[jss::ledger_index_min] = env.current()->header().seq; BEAST_EXPECT(isErr( env.rpc("json", "account_tx", to_string(p)), - (apiVersion == 1 ? rpcLGR_IDXS_INVALID - : rpcINVALID_LGR_RANGE))); + (apiVersion == 1 ? rpcLGR_IDXS_INVALID : rpcINVALID_LGR_RANGE))); } // Ledger index max only { Json::Value p{jParams}; p[jss::ledger_index_max] = -1; - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); p[jss::ledger_index_max] = env.current()->header().seq; if (apiVersion < 2u) - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); else - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcLGR_IDX_MALFORMED)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcLGR_IDX_MALFORMED)); p[jss::ledger_index_max] = 3; - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); p[jss::ledger_index_max] = env.closed()->header().seq; - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); p[jss::ledger_index_max] = env.closed()->header().seq - 1; BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); @@ -282,20 +231,16 @@ class AccountTx_test : public beast::unit_test::suite Json::Value p{jParams}; p[jss::ledger_index] = env.closed()->header().seq; - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); p[jss::ledger_index] = env.closed()->header().seq - 1; BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); p[jss::ledger_index] = env.current()->header().seq; - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcLGR_NOT_VALIDATED)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcLGR_NOT_VALIDATED)); p[jss::ledger_index] = env.current()->header().seq + 1; - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), rpcLGR_NOT_FOUND)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcLGR_NOT_FOUND)); } // Ledger Hash @@ -303,8 +248,7 @@ class AccountTx_test : public beast::unit_test::suite Json::Value p{jParams}; p[jss::ledger_hash] = to_string(env.closed()->header().hash); - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); p[jss::ledger_hash] = to_string(env.closed()->header().parentHash); BEAST_EXPECT(noTxs(env.rpc("json", "account_tx", to_string(p)))); @@ -322,12 +266,9 @@ class AccountTx_test : public beast::unit_test::suite p[jss::ledger_index] = -1; if (apiVersion < 2u) - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); else - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcINVALID_PARAMS)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcINVALID_PARAMS)); } // Ledger index max only @@ -335,23 +276,18 @@ class AccountTx_test : public beast::unit_test::suite Json::Value p{jParams}; p[jss::ledger_index_max] = env.current()->header().seq; if (apiVersion < 2u) - BEAST_EXPECT(hasTxs( - env.rpc(apiVersion, "json", "account_tx", to_string(p)))); + BEAST_EXPECT(hasTxs(env.rpc(apiVersion, "json", "account_tx", to_string(p)))); else - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcLGR_IDX_MALFORMED)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcLGR_IDX_MALFORMED)); } // test account non-string { auto testInvalidAccountParam = [&](auto const& param) { Json::Value params; params[jss::account] = param; - auto jrr = env.rpc( - "json", "account_tx", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "account_tx", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -371,9 +307,7 @@ class AccountTx_test : public beast::unit_test::suite BEAST_EXPECT(result[jss::result][jss::status] == "success"); } else - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcINVALID_PARAMS)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcINVALID_PARAMS)); p[jss::binary] = true; Json::Value result{env.rpc("json", "account_tx", to_string(p))}; @@ -383,9 +317,7 @@ class AccountTx_test : public beast::unit_test::suite if (apiVersion < 2u) BEAST_EXPECT(result[jss::result][jss::status] == "success"); else - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcINVALID_PARAMS)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcINVALID_PARAMS)); p[jss::forward] = false; result = env.rpc("json", "account_tx", to_string(p)); @@ -397,90 +329,61 @@ class AccountTx_test : public beast::unit_test::suite // Test case: limit = 0 should fail (below minimum) p[jss::limit] = 0; - BEAST_EXPECT(isErr( - env.rpc("json", "account_tx", to_string(p)), - rpcINVALID_PARAMS)); + BEAST_EXPECT(isErr(env.rpc("json", "account_tx", to_string(p)), rpcINVALID_PARAMS)); // Test case: limit = 1.2 should fail (not an integer) p[jss::limit] = 1.2; BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = "10" should fail (string instead of integer) p[jss::limit] = "10"; BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = true should fail (boolean instead of integer) p[jss::limit] = true; BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = false should fail (boolean instead of integer) p[jss::limit] = false; BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = -1 should fail (negative number) p[jss::limit] = -1; BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = [] should fail (array instead of integer) p[jss::limit] = Json::Value(Json::arrayValue); BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = {} should fail (object instead of integer) p[jss::limit] = Json::Value(Json::objectValue); BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = "malformed" should fail (malformed string) p[jss::limit] = "malformed"; BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = ["limit"] should fail (array with string) p[jss::limit] = Json::Value(Json::arrayValue); p[jss::limit].append("limit"); BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = {"limit": 10} should fail (object with @@ -488,19 +391,12 @@ class AccountTx_test : public beast::unit_test::suite p[jss::limit] = Json::Value(Json::objectValue); p[jss::limit][jss::limit] = 10; BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::error_message] == + env.rpc("json", "account_tx", to_string(p))[jss::result][jss::error_message] == RPC::expected_field_message(jss::limit, "unsigned integer")); // Test case: limit = 10 should succeed (valid integer) p[jss::limit] = 10; - BEAST_EXPECT( - env.rpc( - "json", - "account_tx", - to_string(p))[jss::result][jss::status] == "success"); + BEAST_EXPECT(env.rpc("json", "account_tx", to_string(p))[jss::result][jss::status] == "success"); } } @@ -548,9 +444,7 @@ class AccountTx_test : public beast::unit_test::suite // Escrow { // Create an escrow. Requires either a CancelAfter or FinishAfter. - auto escrow = [](Account const& account, - Account const& to, - STAmount const& amount) { + auto escrow = [](Account const& account, Account const& to, STAmount const& amount) { Json::Value escrow; escrow[jss::TransactionType] = jss::EscrowCreate; escrow[jss::Account] = account.human(); @@ -562,17 +456,14 @@ class AccountTx_test : public beast::unit_test::suite NetClock::time_point const nextTime{env.now() + 2s}; Json::Value escrowWithFinish{escrow(alice, alice, XRP(500))}; - escrowWithFinish[sfFinishAfter.jsonName] = - nextTime.time_since_epoch().count(); + escrowWithFinish[sfFinishAfter.jsonName] = nextTime.time_since_epoch().count(); std::uint32_t const escrowFinishSeq{env.seq(alice)}; env(escrowWithFinish, sig(alie)); Json::Value escrowWithCancel{escrow(alice, alice, XRP(500))}; - escrowWithCancel[sfFinishAfter.jsonName] = - nextTime.time_since_epoch().count(); - escrowWithCancel[sfCancelAfter.jsonName] = - nextTime.time_since_epoch().count() + 1; + escrowWithCancel[sfFinishAfter.jsonName] = nextTime.time_since_epoch().count(); + escrowWithCancel[sfCancelAfter.jsonName] = nextTime.time_since_epoch().count() + 1; std::uint32_t const escrowCancelSeq{env.seq(alice)}; env(escrowWithCancel, sig(alie)); @@ -604,24 +495,20 @@ class AccountTx_test : public beast::unit_test::suite payChanCreate[jss::TransactionType] = jss::PaymentChannelCreate; payChanCreate[jss::Account] = alice.human(); payChanCreate[jss::Destination] = gw.human(); - payChanCreate[jss::Amount] = - XRP(500).value().getJson(JsonOptions::none); - payChanCreate[sfSettleDelay.jsonName] = - NetClock::duration{100s}.count(); + payChanCreate[jss::Amount] = XRP(500).value().getJson(JsonOptions::none); + payChanCreate[sfSettleDelay.jsonName] = NetClock::duration{100s}.count(); payChanCreate[sfPublicKey.jsonName] = strHex(alice.pk().slice()); env(payChanCreate, sig(alie)); env.close(); - std::string const payChanIndex{ - strHex(keylet::payChan(alice, gw, payChanSeq).key)}; + std::string const payChanIndex{strHex(keylet::payChan(alice, gw, payChanSeq).key)}; { Json::Value payChanFund; payChanFund[jss::TransactionType] = jss::PaymentChannelFund; payChanFund[jss::Account] = alice.human(); payChanFund[sfChannel.jsonName] = payChanIndex; - payChanFund[jss::Amount] = - XRP(200).value().getJson(JsonOptions::none); + payChanFund[jss::Amount] = XRP(200).value().getJson(JsonOptions::none); env(payChanFund, sig(alie)); env.close(); } @@ -666,8 +553,7 @@ class AccountTx_test : public beast::unit_test::suite params[jss::ledger_index_min] = -1; params[jss::ledger_index_max] = -1; - Json::Value const result{ - env.rpc("json", "account_tx", to_string(params))}; + Json::Value const result{env.rpc("json", "account_tx", to_string(params))}; BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(result[jss::result][jss::transactions].isArray()); @@ -704,8 +590,7 @@ class AccountTx_test : public beast::unit_test::suite }; // clang-format on - BEAST_EXPECT( - std::size(sanity) == result[jss::result][jss::transactions].size()); + BEAST_EXPECT(std::size(sanity) == result[jss::result][jss::transactions].size()); for (unsigned int index{0}; index < std::size(sanity); ++index) { @@ -739,8 +624,7 @@ class AccountTx_test : public beast::unit_test::suite env(noop(becky)); // Close enough ledgers to be able to delete becky's account. - std::uint32_t const ledgerCount{ - env.current()->seq() + 257 - env.seq(becky)}; + std::uint32_t const ledgerCount{env.current()->seq() + 257 - env.seq(becky)}; for (std::uint32_t i = 0; i < ledgerCount; ++i) env.close(); @@ -781,24 +665,18 @@ class AccountTx_test : public beast::unit_test::suite params[jss::ledger_index_min] = -1; params[jss::ledger_index_max] = -1; - Json::Value const result{ - env.rpc("json", "account_tx", to_string(params))}; + Json::Value const result{env.rpc("json", "account_tx", to_string(params))}; BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(result[jss::result][jss::transactions].isArray()); // The first two transactions listed in sanity haven't happened yet. constexpr unsigned int beckyDeletedOffset = 2; - BEAST_EXPECT( - std::size(sanity) == - result[jss::result][jss::transactions].size() + - beckyDeletedOffset); + BEAST_EXPECT(std::size(sanity) == result[jss::result][jss::transactions].size() + beckyDeletedOffset); Json::Value const& txs{result[jss::result][jss::transactions]}; - for (unsigned int index = beckyDeletedOffset; - index < std::size(sanity); - ++index) + for (unsigned int index = beckyDeletedOffset; index < std::size(sanity); ++index) { checkSanity(txs[index - beckyDeletedOffset], sanity[index]); } @@ -806,10 +684,7 @@ class AccountTx_test : public beast::unit_test::suite // All it takes is a large enough XRP payment to resurrect // becky's account. Try too small a payment. - env(pay(alice, - becky, - drops(env.current()->fees().accountReserve(0)) - XRP(1)), - ter(tecNO_DST_INSUF_XRP)); + env(pay(alice, becky, drops(env.current()->fees().accountReserve(0)) - XRP(1)), ter(tecNO_DST_INSUF_XRP)); env.close(); // Actually resurrect becky's account. @@ -831,14 +706,12 @@ class AccountTx_test : public beast::unit_test::suite params[jss::ledger_index_min] = -1; params[jss::ledger_index_max] = -1; - Json::Value const result{ - env.rpc("json", "account_tx", to_string(params))}; + Json::Value const result{env.rpc("json", "account_tx", to_string(params))}; BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(result[jss::result][jss::transactions].isArray()); - BEAST_EXPECT( - std::size(sanity) == result[jss::result][jss::transactions].size()); + BEAST_EXPECT(std::size(sanity) == result[jss::result][jss::transactions].size()); Json::Value const& txs{result[jss::result][jss::transactions]}; @@ -867,28 +740,23 @@ class AccountTx_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {bob, carol}}); // check the latest mpt-related txn is in alice's account history - auto const checkAliceAcctTx = [&](size_t size, - Json::StaticString txType) { + auto const checkAliceAcctTx = [&](size_t size, Json::StaticString txType) { Json::Value params; params[jss::account] = alice.human(); params[jss::limit] = 100; - auto const jv = - env.rpc("json", "account_tx", to_string(params))[jss::result]; + auto const jv = env.rpc("json", "account_tx", to_string(params))[jss::result]; BEAST_EXPECT(jv[jss::transactions].size() == size); auto const& tx0(jv[jss::transactions][0u][jss::tx]); BEAST_EXPECT(tx0[jss::TransactionType] == txType); - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; BEAST_EXPECT(tx0[jss::hash] == txHash); }; // alice creates issuance mptAlice.create( - {.ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer}); + {.ownerCount = 1, .holderCount = 0, .flags = tfMPTCanClawback | tfMPTRequireAuth | tfMPTCanTransfer}); checkAliceAcctTx(3, jss::MPTokenIssuanceCreate); @@ -931,8 +799,7 @@ public: void run() override { - forAllApiVersions( - std::bind_front(&AccountTx_test::testParameters, this)); + forAllApiVersions(std::bind_front(&AccountTx_test::testParameters, this)); testContents(); testAccountDelete(); testMPT(); diff --git a/src/test/rpc/AmendmentBlocked_test.cpp b/src/test/rpc/AmendmentBlocked_test.cpp index 2c3f631ac8..73a8c6d299 100644 --- a/src/test/rpc/AmendmentBlocked_test.cpp +++ b/src/test/rpc/AmendmentBlocked_test.cpp @@ -60,12 +60,10 @@ class AmendmentBlocked_test : public beast::unit_test::suite pf_req[jss::subcommand] = "create"; pf_req[jss::source_account] = alice.human(); pf_req[jss::destination_account] = bob.human(); - pf_req[jss::destination_amount] = - bob["USD"](20).value().getJson(JsonOptions::none); + pf_req[jss::destination_amount] = bob["USD"](20).value().getJson(JsonOptions::none); jr = wsc->invoke("path_find", pf_req)[jss::result]; BEAST_EXPECT( - jr.isMember(jss::alternatives) && jr[jss::alternatives].isArray() && - jr[jss::alternatives].size() == 1); + jr.isMember(jss::alternatives) && jr[jss::alternatives].isArray() && jr[jss::alternatives].size() == 1); BEAST_EXPECT(!jr.isMember(jss::warnings)); // submit @@ -73,9 +71,7 @@ class AmendmentBlocked_test : public beast::unit_test::suite Serializer s; jt.stx->add(s); jr = env.rpc("submit", strHex(s.slice()))[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::engine_result) && - jr[jss::engine_result] == "tesSUCCESS"); + BEAST_EXPECT(jr.isMember(jss::engine_result) && jr[jss::engine_result] == "tesSUCCESS"); BEAST_EXPECT(!jr.isMember(jss::warnings)); // submit_multisigned @@ -100,11 +96,8 @@ class AmendmentBlocked_test : public beast::unit_test::suite Json::Value ms_req; ms_req[jss::tx_json] = jr[jss::tx_json]; - jr = env.rpc( - "json", "submit_multisigned", to_string(ms_req))[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::engine_result) && - jr[jss::engine_result] == "tesSUCCESS"); + jr = env.rpc("json", "submit_multisigned", to_string(ms_req))[jss::result]; + BEAST_EXPECT(jr.isMember(jss::engine_result) && jr[jss::engine_result] == "tesSUCCESS"); BEAST_EXPECT(!jr.isMember(jss::warnings)); // set up an amendment warning. Nothing changes @@ -131,12 +124,10 @@ class AmendmentBlocked_test : public beast::unit_test::suite pf_req[jss::subcommand] = "create"; pf_req[jss::source_account] = alice.human(); pf_req[jss::destination_account] = bob.human(); - pf_req[jss::destination_amount] = - bob["USD"](20).value().getJson(JsonOptions::none); + pf_req[jss::destination_amount] = bob["USD"](20).value().getJson(JsonOptions::none); jr = wsc->invoke("path_find", pf_req)[jss::result]; BEAST_EXPECT( - jr.isMember(jss::alternatives) && jr[jss::alternatives].isArray() && - jr[jss::alternatives].size() == 1); + jr.isMember(jss::alternatives) && jr[jss::alternatives].isArray() && jr[jss::alternatives].size() == 1); BEAST_EXPECT(!jr.isMember(jss::warnings)); // submit @@ -144,9 +135,7 @@ class AmendmentBlocked_test : public beast::unit_test::suite s.erase(); jt.stx->add(s); jr = env.rpc("submit", strHex(s.slice()))[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::engine_result) && - jr[jss::engine_result] == "tesSUCCESS"); + BEAST_EXPECT(jr.isMember(jss::engine_result) && jr[jss::engine_result] == "tesSUCCESS"); BEAST_EXPECT(!jr.isMember(jss::warnings)); // submit_multisigned @@ -168,11 +157,8 @@ class AmendmentBlocked_test : public beast::unit_test::suite BEAST_EXPECT(!jr.isMember(jss::warnings)); ms_req[jss::tx_json] = jr[jss::tx_json]; - jr = env.rpc( - "json", "submit_multisigned", to_string(ms_req))[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::engine_result) && - jr[jss::engine_result] == "tesSUCCESS"); + jr = env.rpc("json", "submit_multisigned", to_string(ms_req))[jss::result]; + BEAST_EXPECT(jr.isMember(jss::engine_result) && jr[jss::engine_result] == "tesSUCCESS"); BEAST_EXPECT(!jr.isMember(jss::warnings)); // make the network amendment blocked...now all the same @@ -182,36 +168,31 @@ class AmendmentBlocked_test : public beast::unit_test::suite // ledger_accept jr = env.rpc("ledger_accept")[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); + BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); BEAST_EXPECT(jr[jss::status] == "error"); BEAST_EXPECT(!jr.isMember(jss::warnings)); // ledger_current jr = env.rpc("ledger_current")[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); + BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); BEAST_EXPECT(jr[jss::status] == "error"); BEAST_EXPECT(!jr.isMember(jss::warnings)); // owner_info jr = env.rpc("owner_info", alice.human())[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); + BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); BEAST_EXPECT(jr[jss::status] == "error"); BEAST_EXPECT(!jr.isMember(jss::warnings)); // path_find jr = wsc->invoke("path_find", pf_req)[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); + BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); BEAST_EXPECT(jr[jss::status] == "error"); BEAST_EXPECT(!jr.isMember(jss::warnings)); // submit jr = env.rpc("submit", strHex(s.slice()))[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); + BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); BEAST_EXPECT(jr[jss::status] == "error"); BEAST_EXPECT(!jr.isMember(jss::warnings)); @@ -221,10 +202,8 @@ class AmendmentBlocked_test : public beast::unit_test::suite jr = env.rpc("json", "sign_for", to_string(sign_for))[jss::result]; BEAST_EXPECT(jr[jss::status] == "success"); ms_req[jss::tx_json] = jr[jss::tx_json]; - jr = env.rpc( - "json", "submit_multisigned", to_string(ms_req))[jss::result]; - BEAST_EXPECT( - jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); + jr = env.rpc("json", "submit_multisigned", to_string(ms_req))[jss::result]; + BEAST_EXPECT(jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked"); BEAST_EXPECT(!jr.isMember(jss::warnings)); } diff --git a/src/test/rpc/BookChanges_test.cpp b/src/test/rpc/BookChanges_test.cpp index 216f4bd895..4ea4b8233b 100644 --- a/src/test/rpc/BookChanges_test.cpp +++ b/src/test/rpc/BookChanges_test.cpp @@ -58,8 +58,7 @@ public: // As per convention in XRPL, ledgers can be specified with strings // "closed", "validated" or "current" - Json::Value const resp = - env.rpc("json", "book_changes", to_string(Json::Value{})); + Json::Value const resp = env.rpc("json", "book_changes", to_string(Json::Value{})); BEAST_EXPECT(!resp[jss::result].isMember(jss::error)); BEAST_EXPECT(resp[jss::result][jss::status] == "success"); @@ -75,27 +74,21 @@ public: using namespace jtx; FeatureBitset const all{ - jtx::testable_amendments() | featurePermissionedDomains | - featureCredentials | featurePermissionedDEX}; + jtx::testable_amendments() | featurePermissionedDomains | featureCredentials | featurePermissionedDEX}; Env env(*this, all); PermissionedDEX permDex(env); - auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = - permDex; + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = permDex; auto wsc = makeWSClient(env.app().config()); env(offer(alice, XRP(10), USD(10)), domain(domainID)); env.close(); - env(pay(bob, carol, USD(10)), - path(~USD), - sendmax(XRP(10)), - domain(domainID)); + env(pay(bob, carol, USD(10)), path(~USD), sendmax(XRP(10)), domain(domainID)); env.close(); - std::string const txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string const txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; Json::Value const txResult = env.rpc("tx", txHash)[jss::result]; auto const ledgerIndex = txResult[jss::ledger_index].asInt(); @@ -107,9 +100,7 @@ public: auto jrr = jv[jss::result]; BEAST_EXPECT(jrr[jss::changes].size() == 1); - BEAST_EXPECT( - jrr[jss::changes][0u][jss::domain].asString() == - to_string(domainID)); + BEAST_EXPECT(jrr[jss::changes][0u][jss::domain].asString() == to_string(domainID)); } void diff --git a/src/test/rpc/Book_test.cpp b/src/test/rpc/Book_test.cpp index ae2aff689d..543e163432 100644 --- a/src/test/rpc/Book_test.cpp +++ b/src/test/rpc/Book_test.cpp @@ -15,11 +15,7 @@ namespace test { class Book_test : public beast::unit_test::suite { std::string - getBookDir( - jtx::Env& env, - Issue const& in, - Issue const& out, - std::optional const& domain = std::nullopt) + getBookDir(jtx::Env& env, Issue const& in, Issue const& out, std::optional const& domain = std::nullopt) { std::string dir; auto uBookBase = getBookBase({in, out, domain}); @@ -31,8 +27,7 @@ class Book_test : public beast::unit_test::suite auto sleOfferDir = view->read(keylet::page(key.value())); uint256 offerIndex; unsigned int bookEntry; - cdirFirst( - *view, sleOfferDir->key(), sleOfferDir, bookEntry, offerIndex); + cdirFirst(*view, sleOfferDir->key(), sleOfferDir, bookEntry, offerIndex); auto sleOffer = view->read(keylet::offer(offerIndex)); dir = to_string(sleOffer->getFieldH256(sfBookDirectory)); } @@ -66,35 +61,28 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - BEAST_EXPECT( - jv[jss::result].isMember(jss::offers) && - jv[jss::result][jss::offers].size() == 0); + BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 0); BEAST_EXPECT(!jv[jss::result].isMember(jss::asks)); BEAST_EXPECT(!jv[jss::result].isMember(jss::bids)); } { // Create an ask: TakerPays 700, TakerGets 100/USD - env(offer("alice", XRP(700), USD(100)), - require(owners("alice", 1))); + env(offer("alice", XRP(700), USD(100)), require(owners("alice", 1))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - XRP(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none); })); } @@ -110,10 +98,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -151,41 +137,32 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; + BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 1); BEAST_EXPECT( - jv[jss::result].isMember(jss::offers) && - jv[jss::result][jss::offers].size() == 1); + jv[jss::result][jss::offers][0u][jss::TakerGets] == XRP(200).value().getJson(JsonOptions::none)); BEAST_EXPECT( - jv[jss::result][jss::offers][0u][jss::TakerGets] == - XRP(200).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::offers][0u][jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none)); + jv[jss::result][jss::offers][0u][jss::TakerPays] == USD(100).value().getJson(JsonOptions::none)); BEAST_EXPECT(!jv[jss::result].isMember(jss::asks)); BEAST_EXPECT(!jv[jss::result].isMember(jss::bids)); } { // Create an ask: TakerPays 700, TakerGets 100/USD - env(offer("alice", XRP(700), USD(100)), - require(owners("alice", 3))); + env(offer("alice", XRP(700), USD(100)), require(owners("alice", 3))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - XRP(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none); })); } @@ -201,10 +178,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -236,37 +211,28 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - BEAST_EXPECT( - jv[jss::result].isMember(jss::asks) && - jv[jss::result][jss::asks].size() == 0); - BEAST_EXPECT( - jv[jss::result].isMember(jss::bids) && - jv[jss::result][jss::bids].size() == 0); + BEAST_EXPECT(jv[jss::result].isMember(jss::asks) && jv[jss::result][jss::asks].size() == 0); + BEAST_EXPECT(jv[jss::result].isMember(jss::bids) && jv[jss::result][jss::bids].size() == 0); BEAST_EXPECT(!jv[jss::result].isMember(jss::offers)); } { // Create an ask: TakerPays 700, TakerGets 100/USD - env(offer("alice", XRP(700), USD(100)), - require(owners("alice", 1))); + env(offer("alice", XRP(700), USD(100)), require(owners("alice", 1))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - XRP(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none); })); } @@ -279,10 +245,8 @@ public: BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - XRP(75).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none); + t[jss::TakerGets] == XRP(75).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == USD(100).value().getJson(JsonOptions::none); })); } @@ -291,10 +255,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -333,49 +295,32 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - BEAST_EXPECT( - jv[jss::result].isMember(jss::asks) && - jv[jss::result][jss::asks].size() == 1); - BEAST_EXPECT( - jv[jss::result].isMember(jss::bids) && - jv[jss::result][jss::bids].size() == 1); - BEAST_EXPECT( - jv[jss::result][jss::asks][0u][jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::asks][0u][jss::TakerPays] == - XRP(500).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::bids][0u][jss::TakerGets] == - XRP(200).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::bids][0u][jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result].isMember(jss::asks) && jv[jss::result][jss::asks].size() == 1); + BEAST_EXPECT(jv[jss::result].isMember(jss::bids) && jv[jss::result][jss::bids].size() == 1); + BEAST_EXPECT(jv[jss::result][jss::asks][0u][jss::TakerGets] == USD(100).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::asks][0u][jss::TakerPays] == XRP(500).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::bids][0u][jss::TakerGets] == XRP(200).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::bids][0u][jss::TakerPays] == USD(100).value().getJson(JsonOptions::none)); BEAST_EXPECT(!jv[jss::result].isMember(jss::offers)); } { // Create an ask: TakerPays 700, TakerGets 100/USD - env(offer("alice", XRP(700), USD(100)), - require(owners("alice", 3))); + env(offer("alice", XRP(700), USD(100)), require(owners("alice", 3))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - XRP(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none); })); } @@ -388,10 +333,8 @@ public: BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - XRP(75).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none); + t[jss::TakerGets] == XRP(75).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == USD(100).value().getJson(JsonOptions::none); })); } @@ -400,10 +343,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -444,35 +385,28 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - BEAST_EXPECT( - jv[jss::result].isMember(jss::offers) && - jv[jss::result][jss::offers].size() == 0); + BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 0); BEAST_EXPECT(!jv[jss::result].isMember(jss::asks)); BEAST_EXPECT(!jv[jss::result].isMember(jss::bids)); } { // Create an ask: TakerPays 700, TakerGets 100/USD - env(offer("alice", XRP(700), USD(100)), - require(owners("alice", 1))); + env(offer("alice", XRP(700), USD(100)), require(owners("alice", 1))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - XRP(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none); })); } @@ -485,18 +419,15 @@ public: { // Create an ask: TakerPays 700/CNY, TakerGets 100/JPY - env(offer("alice", CNY(700), JPY(100)), - require(owners("alice", 3))); + env(offer("alice", CNY(700), JPY(100)), require(owners("alice", 3))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - JPY(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - CNY(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == JPY(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == CNY(700).value().getJson(JsonOptions::none); })); } @@ -512,10 +443,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -569,47 +498,36 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; + BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 2); BEAST_EXPECT( - jv[jss::result].isMember(jss::offers) && - jv[jss::result][jss::offers].size() == 2); + jv[jss::result][jss::offers][0u][jss::TakerGets] == XRP(200).value().getJson(JsonOptions::none)); BEAST_EXPECT( - jv[jss::result][jss::offers][0u][jss::TakerGets] == - XRP(200).value().getJson(JsonOptions::none)); + jv[jss::result][jss::offers][0u][jss::TakerPays] == USD(100).value().getJson(JsonOptions::none)); BEAST_EXPECT( - jv[jss::result][jss::offers][0u][jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none)); + jv[jss::result][jss::offers][1u][jss::TakerGets] == CNY(200).value().getJson(JsonOptions::none)); BEAST_EXPECT( - jv[jss::result][jss::offers][1u][jss::TakerGets] == - CNY(200).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::offers][1u][jss::TakerPays] == - JPY(100).value().getJson(JsonOptions::none)); + jv[jss::result][jss::offers][1u][jss::TakerPays] == JPY(100).value().getJson(JsonOptions::none)); BEAST_EXPECT(!jv[jss::result].isMember(jss::asks)); BEAST_EXPECT(!jv[jss::result].isMember(jss::bids)); } { // Create an ask: TakerPays 700, TakerGets 100/USD - env(offer("alice", XRP(700), USD(100)), - require(owners("alice", 5))); + env(offer("alice", XRP(700), USD(100)), require(owners("alice", 5))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - XRP(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none); })); } @@ -622,18 +540,15 @@ public: { // Create an ask: TakerPays 700/CNY, TakerGets 100/JPY - env(offer("alice", CNY(700), JPY(100)), - require(owners("alice", 7))); + env(offer("alice", CNY(700), JPY(100)), require(owners("alice", 7))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - JPY(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - CNY(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == JPY(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == CNY(700).value().getJson(JsonOptions::none); })); } @@ -649,10 +564,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -695,37 +608,28 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - BEAST_EXPECT( - jv[jss::result].isMember(jss::asks) && - jv[jss::result][jss::asks].size() == 0); - BEAST_EXPECT( - jv[jss::result].isMember(jss::bids) && - jv[jss::result][jss::bids].size() == 0); + BEAST_EXPECT(jv[jss::result].isMember(jss::asks) && jv[jss::result][jss::asks].size() == 0); + BEAST_EXPECT(jv[jss::result].isMember(jss::bids) && jv[jss::result][jss::bids].size() == 0); BEAST_EXPECT(!jv[jss::result].isMember(jss::offers)); } { // Create an ask: TakerPays 700, TakerGets 100/USD - env(offer("alice", XRP(700), USD(100)), - require(owners("alice", 1))); + env(offer("alice", XRP(700), USD(100)), require(owners("alice", 1))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - XRP(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none); })); } @@ -738,27 +642,22 @@ public: BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - XRP(75).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none); + t[jss::TakerGets] == XRP(75).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == USD(100).value().getJson(JsonOptions::none); })); } { // Create an ask: TakerPays 700/CNY, TakerGets 100/JPY - env(offer("alice", CNY(700), JPY(100)), - require(owners("alice", 3))); + env(offer("alice", CNY(700), JPY(100)), require(owners("alice", 3))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - JPY(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - CNY(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == JPY(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == CNY(700).value().getJson(JsonOptions::none); })); } @@ -771,10 +670,8 @@ public: BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - CNY(75).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - JPY(100).value().getJson(JsonOptions::none); + t[jss::TakerGets] == CNY(75).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == JPY(100).value().getJson(JsonOptions::none); })); } @@ -783,10 +680,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -843,61 +738,36 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - BEAST_EXPECT( - jv[jss::result].isMember(jss::asks) && - jv[jss::result][jss::asks].size() == 2); - BEAST_EXPECT( - jv[jss::result].isMember(jss::bids) && - jv[jss::result][jss::bids].size() == 2); - BEAST_EXPECT( - jv[jss::result][jss::asks][0u][jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::asks][0u][jss::TakerPays] == - XRP(500).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::asks][1u][jss::TakerGets] == - JPY(100).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::asks][1u][jss::TakerPays] == - CNY(500).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::bids][0u][jss::TakerGets] == - XRP(200).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::bids][0u][jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::bids][1u][jss::TakerGets] == - CNY(200).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::bids][1u][jss::TakerPays] == - JPY(100).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result].isMember(jss::asks) && jv[jss::result][jss::asks].size() == 2); + BEAST_EXPECT(jv[jss::result].isMember(jss::bids) && jv[jss::result][jss::bids].size() == 2); + BEAST_EXPECT(jv[jss::result][jss::asks][0u][jss::TakerGets] == USD(100).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::asks][0u][jss::TakerPays] == XRP(500).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::asks][1u][jss::TakerGets] == JPY(100).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::asks][1u][jss::TakerPays] == CNY(500).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::bids][0u][jss::TakerGets] == XRP(200).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::bids][0u][jss::TakerPays] == USD(100).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::bids][1u][jss::TakerGets] == CNY(200).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::bids][1u][jss::TakerPays] == JPY(100).value().getJson(JsonOptions::none)); BEAST_EXPECT(!jv[jss::result].isMember(jss::offers)); } { // Create an ask: TakerPays 700, TakerGets 100/USD - env(offer("alice", XRP(700), USD(100)), - require(owners("alice", 5))); + env(offer("alice", XRP(700), USD(100)), require(owners("alice", 5))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - XRP(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == XRP(700).value().getJson(JsonOptions::none); })); } @@ -910,27 +780,22 @@ public: BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - XRP(75).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - USD(100).value().getJson(JsonOptions::none); + t[jss::TakerGets] == XRP(75).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == USD(100).value().getJson(JsonOptions::none); })); } { // Create an ask: TakerPays 700/CNY, TakerGets 100/JPY - env(offer("alice", CNY(700), JPY(100)), - require(owners("alice", 7))); + env(offer("alice", CNY(700), JPY(100)), require(owners("alice", 7))); env.close(); // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - JPY(100).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - CNY(700).value().getJson(JsonOptions::none); + t[jss::TakerGets] == JPY(100).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == CNY(700).value().getJson(JsonOptions::none); })); } @@ -943,10 +808,8 @@ public: BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { auto const& t = jv[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - CNY(75).value().getJson(JsonOptions::none) && - t[jss::TakerPays] == - JPY(100).value().getJson(JsonOptions::none); + t[jss::TakerGets] == CNY(75).value().getJson(JsonOptions::none) && + t[jss::TakerPays] == JPY(100).value().getJson(JsonOptions::none); })); } @@ -955,10 +818,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -991,17 +852,13 @@ public: auto jv = wsc->invoke("subscribe", books); 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::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); } if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - BEAST_EXPECT( - jv[jss::result].isMember(jss::offers) && - jv[jss::result][jss::offers].size() == 0); + BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 0); BEAST_EXPECT(!jv[jss::result].isMember(jss::asks)); BEAST_EXPECT(!jv[jss::result].isMember(jss::bids)); } @@ -1025,10 +882,8 @@ public: auto jv = wsc->invoke("book_offers", jvParams); 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::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); } auto jrr = jv[jss::result]; @@ -1037,20 +892,14 @@ public: BEAST_EXPECT(jrr[jss::offers].size() == 1); auto const jrOffer = jrr[jss::offers][0u]; BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.human()); - BEAST_EXPECT( - jrOffer[sfBookDirectory.fieldName] == - getBookDir(env, XRP, USD.issue())); + BEAST_EXPECT(jrOffer[sfBookDirectory.fieldName] == getBookDir(env, XRP, USD.issue())); BEAST_EXPECT(jrOffer[sfBookNode.fieldName] == "0"); BEAST_EXPECT(jrOffer[jss::Flags] == 0); BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer); BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] == "0"); BEAST_EXPECT(jrOffer[sfSequence.fieldName] == 5); - BEAST_EXPECT( - jrOffer[jss::TakerGets] == - USD(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jrOffer[jss::TakerPays] == - XRP(4000).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jrOffer[jss::TakerGets] == USD(10).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jrOffer[jss::TakerPays] == XRP(4000).value().getJson(JsonOptions::none)); BEAST_EXPECT(jrOffer[jss::owner_funds] == "100"); BEAST_EXPECT(jrOffer[jss::quality] == "400000000"); @@ -1058,11 +907,8 @@ public: BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jval) { auto const& t = jval[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(10).value().getJson(JsonOptions::none) && - t[jss::owner_funds] == "100" && - t[jss::TakerPays] == - XRP(4000).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(10).value().getJson(JsonOptions::none) && t[jss::owner_funds] == "100" && + t[jss::TakerPays] == XRP(4000).value().getJson(JsonOptions::none); })); env(offer(bob, XRP(2000), USD(5))); @@ -1071,20 +917,15 @@ public: BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jval) { auto const& t = jval[jss::transaction]; return t[jss::TransactionType] == jss::OfferCreate && - t[jss::TakerGets] == - USD(5).value().getJson(JsonOptions::none) && - t[jss::owner_funds] == "50" && - t[jss::TakerPays] == - XRP(2000).value().getJson(JsonOptions::none); + t[jss::TakerGets] == USD(5).value().getJson(JsonOptions::none) && t[jss::owner_funds] == "50" && + t[jss::TakerPays] == XRP(2000).value().getJson(JsonOptions::none); })); jv = wsc->invoke("book_offers", jvParams); 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::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); } jrr = jv[jss::result]; @@ -1093,30 +934,22 @@ public: BEAST_EXPECT(jrr[jss::offers].size() == 2); auto const jrNextOffer = jrr[jss::offers][1u]; BEAST_EXPECT(jrNextOffer[sfAccount.fieldName] == bob.human()); - BEAST_EXPECT( - jrNextOffer[sfBookDirectory.fieldName] == - getBookDir(env, XRP, USD.issue())); + BEAST_EXPECT(jrNextOffer[sfBookDirectory.fieldName] == getBookDir(env, XRP, USD.issue())); BEAST_EXPECT(jrNextOffer[sfBookNode.fieldName] == "0"); BEAST_EXPECT(jrNextOffer[jss::Flags] == 0); BEAST_EXPECT(jrNextOffer[sfLedgerEntryType.fieldName] == jss::Offer); BEAST_EXPECT(jrNextOffer[sfOwnerNode.fieldName] == "0"); BEAST_EXPECT(jrNextOffer[sfSequence.fieldName] == 5); - BEAST_EXPECT( - jrNextOffer[jss::TakerGets] == - USD(5).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jrNextOffer[jss::TakerPays] == - XRP(2000).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jrNextOffer[jss::TakerGets] == USD(5).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jrNextOffer[jss::TakerPays] == XRP(2000).value().getJson(JsonOptions::none)); BEAST_EXPECT(jrNextOffer[jss::owner_funds] == "50"); BEAST_EXPECT(jrNextOffer[jss::quality] == "400000000"); jv = wsc->invoke("unsubscribe", books); 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::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"); @@ -1312,8 +1145,7 @@ public: { Json::Value jvParams; jvParams[jss::ledger_index] = 10u; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "lgrNotFound"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound"); } @@ -1321,22 +1153,18 @@ public: { Json::Value jvParams; jvParams[jss::ledger_index] = "validated"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Missing field 'taker_pays'."); + BEAST_EXPECT(jrr[jss::error_message] == "Missing field 'taker_pays'."); } { Json::Value jvParams; jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays] = Json::objectValue; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Missing field 'taker_gets'."); + BEAST_EXPECT(jrr[jss::error_message] == "Missing field 'taker_gets'."); } { @@ -1344,12 +1172,9 @@ public: jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays] = "not an object"; jvParams[jss::taker_gets] = Json::objectValue; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_pays', not object."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_pays', not object."); } { @@ -1357,12 +1182,9 @@ public: jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays] = Json::objectValue; jvParams[jss::taker_gets] = "not an object"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_gets', not object."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_gets', not object."); } { @@ -1370,12 +1192,9 @@ public: jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays] = Json::objectValue; jvParams[jss::taker_gets] = Json::objectValue; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Missing field 'taker_pays.currency'."); + BEAST_EXPECT(jrr[jss::error_message] == "Missing field 'taker_pays.currency'."); } { @@ -1383,12 +1202,9 @@ public: jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays][jss::currency] = 1; jvParams[jss::taker_gets] = Json::objectValue; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_pays.currency', not string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_pays.currency', not string."); } { @@ -1396,12 +1212,9 @@ public: jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets] = Json::objectValue; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Missing field 'taker_gets.currency'."); + BEAST_EXPECT(jrr[jss::error_message] == "Missing field 'taker_gets.currency'."); } { @@ -1409,12 +1222,9 @@ public: jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = 1; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_gets.currency', not string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_gets.currency', not string."); } { @@ -1422,12 +1232,9 @@ public: jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays][jss::currency] = "NOT_VALID"; jvParams[jss::taker_gets][jss::currency] = "XRP"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "srcCurMalformed"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_pays.currency', bad currency."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_pays.currency', bad currency."); } { @@ -1435,12 +1242,9 @@ public: jvParams[jss::ledger_index] = "validated"; jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "NOT_VALID"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "dstAmtMalformed"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_gets.currency', bad currency."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_gets.currency', bad currency."); } { @@ -1449,12 +1253,9 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = 1; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_gets.issuer', not string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_gets.issuer', not string."); } { @@ -1463,12 +1264,9 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_pays][jss::issuer] = 1; jvParams[jss::taker_gets][jss::currency] = "USD"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_pays.issuer', not string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_pays.issuer', not string."); } { @@ -1477,12 +1275,9 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_pays][jss::issuer] = gw.human() + "DEAD"; jvParams[jss::taker_gets][jss::currency] = "USD"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "srcIsrMalformed"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_pays.issuer', bad issuer."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_pays.issuer', bad issuer."); } { @@ -1491,12 +1286,9 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_pays][jss::issuer] = toBase58(noAccount()); jvParams[jss::taker_gets][jss::currency] = "USD"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "srcIsrMalformed"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_pays.issuer', bad issuer account one."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_pays.issuer', bad issuer account one."); } { @@ -1505,12 +1297,9 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human() + "DEAD"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "dstIsrMalformed"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_gets.issuer', bad issuer."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_gets.issuer', bad issuer."); } { @@ -1519,12 +1308,9 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = toBase58(noAccount()); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "dstIsrMalformed"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_gets.issuer', bad issuer account one."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_gets.issuer', bad issuer account one."); } { @@ -1534,8 +1320,7 @@ public: jvParams[jss::taker_pays][jss::issuer] = alice.human(); jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "srcIsrMalformed"); BEAST_EXPECT( jrr[jss::error_message] == @@ -1550,12 +1335,9 @@ public: jvParams[jss::taker_pays][jss::issuer] = toBase58(xrpAccount()); jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "srcIsrMalformed"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker_pays.issuer', expected non-XRP issuer."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker_pays.issuer', expected non-XRP issuer."); } { @@ -1565,12 +1347,9 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'taker', not string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker', not string."); } { @@ -1580,8 +1359,7 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'taker'."); } @@ -1594,8 +1372,7 @@ public: jvParams[jss::taker_pays][jss::issuer] = gw.human(); jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "badMarket"); BEAST_EXPECT(jrr[jss::error_message] == "No such market."); } @@ -1608,12 +1385,9 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'limit', not unsigned integer."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'limit', not unsigned integer."); } { @@ -1624,8 +1398,7 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'limit'."); } @@ -1636,8 +1409,7 @@ public: jvParams[jss::taker_pays][jss::currency] = "USD"; jvParams[jss::taker_pays][jss::issuer] = gw.human(); jvParams[jss::taker_gets][jss::currency] = "USD"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "dstIsrMalformed"); BEAST_EXPECT( jrr[jss::error_message] == @@ -1652,8 +1424,7 @@ public: jvParams[jss::taker_pays][jss::issuer] = gw.human(); jvParams[jss::taker_gets][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "dstIsrMalformed"); BEAST_EXPECT( jrr[jss::error_message] == @@ -1668,8 +1439,7 @@ public: jvParams[jss::taker_gets][jss::currency] = "EUR"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); jvParams[jss::domain] = "badString"; - auto const jrr = env.rpc( - "json", "book_offers", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "domainMalformed"); BEAST_EXPECT(jrr[jss::error_message] == "Unable to parse domain."); } @@ -1701,8 +1471,7 @@ public: jvParams[jss::taker_pays][jss::currency] = "XRP"; jvParams[jss::taker_gets][jss::currency] = "USD"; jvParams[jss::taker_gets][jss::issuer] = gw.human(); - auto jrr = - env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; + auto jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::offers].isArray()); BEAST_EXPECT(jrr[jss::offers].size() == (asAdmin ? 1u : 0u)); // NOTE - a marker field is not returned for this method @@ -1710,16 +1479,12 @@ public: jvParams[jss::limit] = RPC::Tuning::bookOffers.rmax + 1; jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::offers].isArray()); - BEAST_EXPECT( - jrr[jss::offers].size() == - (asAdmin ? RPC::Tuning::bookOffers.rmax + 1 : 0u)); + BEAST_EXPECT(jrr[jss::offers].size() == (asAdmin ? RPC::Tuning::bookOffers.rmax + 1 : 0u)); jvParams[jss::limit] = Json::nullValue; jrr = env.rpc("json", "book_offers", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::offers].isArray()); - BEAST_EXPECT( - jrr[jss::offers].size() == - (asAdmin ? RPC::Tuning::bookOffers.rDefault : 0u)); + BEAST_EXPECT(jrr[jss::offers].size() == (asAdmin ? RPC::Tuning::bookOffers.rDefault : 0u)); } void @@ -1729,8 +1494,7 @@ public: using namespace jtx; FeatureBitset const all{ - jtx::testable_amendments() | featurePermissionedDomains | - featureCredentials | featurePermissionedDEX}; + jtx::testable_amendments() | featurePermissionedDomains | featureCredentials | featurePermissionedDEX}; Env env(*this, all); PermissionedDEX permDex(env); @@ -1751,21 +1515,14 @@ public: BEAST_EXPECT(jrr[jss::offers].size() == 1); auto const jrOffer = jrr[jss::offers][0u]; BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.human()); - BEAST_EXPECT( - jrOffer[sfBookDirectory.fieldName] == - getBookDir(env, XRP, USD.issue(), domainID)); + BEAST_EXPECT(jrOffer[sfBookDirectory.fieldName] == getBookDir(env, XRP, USD.issue(), domainID)); BEAST_EXPECT(jrOffer[sfBookNode.fieldName] == "0"); BEAST_EXPECT(jrOffer[jss::Flags] == 0); BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer); BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] == "0"); - BEAST_EXPECT( - jrOffer[jss::TakerGets] == - USD(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jrOffer[jss::TakerPays] == - XRP(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jrOffer[sfDomainID.jsonName].asString() == to_string(domainID)); + BEAST_EXPECT(jrOffer[jss::TakerGets] == USD(10).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jrOffer[jss::TakerPays] == XRP(10).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jrOffer[sfDomainID.jsonName].asString() == to_string(domainID)); }; // book_offers: open book doesn't return offer @@ -1784,18 +1541,12 @@ public: } auto checkSubBooks = [&](Json::Value const& jv) { + BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 1); BEAST_EXPECT( - jv[jss::result].isMember(jss::offers) && - jv[jss::result][jss::offers].size() == 1); + jv[jss::result][jss::offers][0u][jss::TakerGets] == USD(10).value().getJson(JsonOptions::none)); BEAST_EXPECT( - jv[jss::result][jss::offers][0u][jss::TakerGets] == - USD(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::offers][0u][jss::TakerPays] == - XRP(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::offers][0u][sfDomainID.jsonName] - .asString() == to_string(domainID)); + jv[jss::result][jss::offers][0u][jss::TakerPays] == XRP(10).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::offers][0u][sfDomainID.jsonName].asString() == to_string(domainID)); }; // book_offers: requesting domain book returns hybrid offer @@ -1847,9 +1598,7 @@ public: auto jv = wsc->invoke("subscribe", books); if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - BEAST_EXPECT( - jv[jss::result].isMember(jss::offers) && - jv[jss::result][jss::offers].size() == 0); + BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 0); } } @@ -1860,8 +1609,7 @@ public: using namespace jtx; FeatureBitset const all{ - jtx::testable_amendments() | featurePermissionedDomains | - featureCredentials | featurePermissionedDEX}; + jtx::testable_amendments() | featurePermissionedDomains | featureCredentials | featurePermissionedDEX}; Env env(*this, all); PermissionedDEX permDex(env); @@ -1874,9 +1622,7 @@ public: auto wsc = makeWSClient(env.app().config()); - env(offer(alice, XRP(10), USD(10)), - domain(domainID), - txflags(tfHybrid)); + env(offer(alice, XRP(10), USD(10)), domain(domainID), txflags(tfHybrid)); env.close(); auto checkBookOffers = [&](Json::Value const& jrr) { @@ -1884,21 +1630,14 @@ public: BEAST_EXPECT(jrr[jss::offers].size() == 1); auto const jrOffer = jrr[jss::offers][0u]; BEAST_EXPECT(jrOffer[sfAccount.fieldName] == alice.human()); - BEAST_EXPECT( - jrOffer[sfBookDirectory.fieldName] == - getBookDir(env, XRP, USD.issue(), domainID)); + BEAST_EXPECT(jrOffer[sfBookDirectory.fieldName] == getBookDir(env, XRP, USD.issue(), domainID)); BEAST_EXPECT(jrOffer[sfBookNode.fieldName] == "0"); BEAST_EXPECT(jrOffer[jss::Flags] == lsfHybrid); BEAST_EXPECT(jrOffer[sfLedgerEntryType.fieldName] == jss::Offer); BEAST_EXPECT(jrOffer[sfOwnerNode.fieldName] == "0"); - BEAST_EXPECT( - jrOffer[jss::TakerGets] == - USD(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jrOffer[jss::TakerPays] == - XRP(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jrOffer[sfDomainID.jsonName].asString() == to_string(domainID)); + BEAST_EXPECT(jrOffer[jss::TakerGets] == USD(10).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jrOffer[jss::TakerPays] == XRP(10).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jrOffer[sfDomainID.jsonName].asString() == to_string(domainID)); BEAST_EXPECT(jrOffer[sfAdditionalBooks.jsonName].size() == 1); }; @@ -1917,18 +1656,12 @@ public: } auto checkSubBooks = [&](Json::Value const& jv) { + BEAST_EXPECT(jv[jss::result].isMember(jss::offers) && jv[jss::result][jss::offers].size() == 1); BEAST_EXPECT( - jv[jss::result].isMember(jss::offers) && - jv[jss::result][jss::offers].size() == 1); + jv[jss::result][jss::offers][0u][jss::TakerGets] == USD(10).value().getJson(JsonOptions::none)); BEAST_EXPECT( - jv[jss::result][jss::offers][0u][jss::TakerGets] == - USD(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::offers][0u][jss::TakerPays] == - XRP(10).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - jv[jss::result][jss::offers][0u][sfDomainID.jsonName] - .asString() == to_string(domainID)); + jv[jss::result][jss::offers][0u][jss::TakerPays] == XRP(10).value().getJson(JsonOptions::none)); + BEAST_EXPECT(jv[jss::result][jss::offers][0u][sfDomainID.jsonName].asString() == to_string(domainID)); }; // book_offers: requesting domain book returns hybrid offer diff --git a/src/test/rpc/Connect_test.cpp b/src/test/rpc/Connect_test.cpp index 8d5a2ca33f..c029356bf6 100644 --- a/src/test/rpc/Connect_test.cpp +++ b/src/test/rpc/Connect_test.cpp @@ -22,9 +22,7 @@ class Connect_test : public beast::unit_test::suite BEAST_EXPECT(result[jss::result][jss::status] == "error"); BEAST_EXPECT(result[jss::result].isMember(jss::error)); BEAST_EXPECT(result[jss::result][jss::error] == "notSynced"); - BEAST_EXPECT( - result[jss::result][jss::error_message] == - "Not synced to the network."); + BEAST_EXPECT(result[jss::result][jss::error_message] == "Not synced to the network."); } } diff --git a/src/test/rpc/DeliveredAmount_test.cpp b/src/test/rpc/DeliveredAmount_test.cpp index 3e256aa03b..8d376893ec 100644 --- a/src/test/rpc/DeliveredAmount_test.cpp +++ b/src/test/rpc/DeliveredAmount_test.cpp @@ -46,8 +46,7 @@ class CheckDeliveredAmount } public: - explicit CheckDeliveredAmount(bool afterSwitchTime) - : afterSwitchTime_(afterSwitchTime) + explicit CheckDeliveredAmount(bool afterSwitchTime) : afterSwitchTime_(afterSwitchTime) { } @@ -73,8 +72,7 @@ public: bool checkExpectedCounters() const { - return !numExpectedAvailable_ && !numExpectedNotSet_ && - !numExpectedSetUnavailable_; + return !numExpectedAvailable_ && !numExpectedNotSet_ && !numExpectedSetUnavailable_; } // Check if the transaction has `delivered_amount` in the metaData as @@ -108,8 +106,7 @@ public: { if (metaData.isMember(sfDeliveredAmount.jsonName)) { - if (metaData[jss::delivered_amount] != - metaData[sfDeliveredAmount.jsonName]) + if (metaData[jss::delivered_amount] != metaData[sfDeliveredAmount.jsonName]) return false; } else @@ -220,11 +217,8 @@ class DeliveredAmount_test : public beast::unit_test::suite 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::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::ledger_index] == 3); @@ -234,17 +228,14 @@ class DeliveredAmount_test : public beast::unit_test::suite // Check stream update while (true) { - auto const r = wsc->findMsg(1s, [&](auto const& jv) { - return jv[jss::ledger_index] == 4; - }); + auto const r = wsc->findMsg(1s, [&](auto const& jv) { return jv[jss::ledger_index] == 4; }); if (!r) break; if (!r->isMember(jss::transaction)) continue; - BEAST_EXPECT(checkDeliveredAmount.checkTxn( - (*r)[jss::transaction], (*r)[jss::meta])); + BEAST_EXPECT(checkDeliveredAmount.checkTxn((*r)[jss::transaction], (*r)[jss::meta])); } } BEAST_EXPECT(checkDeliveredAmount.checkExpectedCounters()); @@ -299,14 +290,10 @@ class DeliveredAmount_test : public beast::unit_test::suite jvParams[jss::ledger_index] = 4u; jvParams[jss::transactions] = true; jvParams[jss::expand] = true; - auto const jtxn = env.rpc( - "json", - "ledger", - to_string( - jvParams))[jss::result][jss::ledger][jss::transactions]; + auto const jtxn = + env.rpc("json", "ledger", to_string(jvParams))[jss::result][jss::ledger][jss::transactions]; for (auto const& t : jtxn) - BEAST_EXPECT( - checkDeliveredAmount.checkTxn(t, t[jss::metaData])); + BEAST_EXPECT(checkDeliveredAmount.checkTxn(t, t[jss::metaData])); BEAST_EXPECT(checkDeliveredAmount.checkExpectedCounters()); } } @@ -322,14 +309,9 @@ class DeliveredAmount_test : public beast::unit_test::suite Account const bob("bob"); Env env{*this, features}; - MPTTester mptAlice( - env, alice, {.holders = {bob, carol}, .close = false}); + MPTTester mptAlice(env, alice, {.holders = {bob, carol}, .close = false}); - mptAlice.create( - {.transferFee = 25000, - .ownerCount = 1, - .holderCount = 0, - .flags = tfMPTCanTransfer}); + mptAlice.create({.transferFee = 25000, .ownerCount = 1, .holderCount = 0, .flags = tfMPTCanTransfer}); auto const MPT = mptAlice["MPT"]; mptAlice.authorize({.account = bob}); @@ -343,29 +325,21 @@ class DeliveredAmount_test : public beast::unit_test::suite env.close(); // Get the hash for the most recent transaction. - std::string txHash{ - env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; + std::string txHash{env.tx()->getJson(JsonOptions::none)[jss::hash].asString()}; Json::Value meta = env.rpc("tx", txHash)[jss::result][jss::meta]; if (features[fixMPTDeliveredAmount]) { - BEAST_EXPECT( - meta[sfDeliveredAmount.jsonName] == - STAmount{MPT(800)}.getJson(JsonOptions::none)); - BEAST_EXPECT( - meta[jss::delivered_amount] == - STAmount{MPT(800)}.getJson(JsonOptions::none)); + BEAST_EXPECT(meta[sfDeliveredAmount.jsonName] == STAmount{MPT(800)}.getJson(JsonOptions::none)); + BEAST_EXPECT(meta[jss::delivered_amount] == STAmount{MPT(800)}.getJson(JsonOptions::none)); } else { BEAST_EXPECT(!meta.isMember(sfDeliveredAmount.jsonName)); - BEAST_EXPECT( - meta[jss::delivered_amount] = Json::Value("unavailable")); + BEAST_EXPECT(meta[jss::delivered_amount] = Json::Value("unavailable")); } - env(pay(bob, carol, MPT(1000)), - sendmax(MPT(1200)), - txflags(tfPartialPayment)); + env(pay(bob, carol, MPT(1000)), sendmax(MPT(1200)), txflags(tfPartialPayment)); env.close(); txHash = env.tx()->getJson(JsonOptions::none)[jss::hash].asString(); @@ -373,18 +347,13 @@ class DeliveredAmount_test : public beast::unit_test::suite if (features[fixMPTDeliveredAmount]) { - BEAST_EXPECT( - meta[sfDeliveredAmount.jsonName] == - STAmount{MPT(960)}.getJson(JsonOptions::none)); - BEAST_EXPECT( - meta[jss::delivered_amount] == - STAmount{MPT(960)}.getJson(JsonOptions::none)); + BEAST_EXPECT(meta[sfDeliveredAmount.jsonName] == STAmount{MPT(960)}.getJson(JsonOptions::none)); + BEAST_EXPECT(meta[jss::delivered_amount] == STAmount{MPT(960)}.getJson(JsonOptions::none)); } else { BEAST_EXPECT(!meta.isMember(sfDeliveredAmount.jsonName)); - BEAST_EXPECT( - meta[jss::delivered_amount] = Json::Value("unavailable")); + BEAST_EXPECT(meta[jss::delivered_amount] = Json::Value("unavailable")); } } diff --git a/src/test/rpc/DepositAuthorized_test.cpp b/src/test/rpc/DepositAuthorized_test.cpp index 3e082a70a1..e8abfd58b8 100644 --- a/src/test/rpc/DepositAuthorized_test.cpp +++ b/src/test/rpc/DepositAuthorized_test.cpp @@ -58,47 +58,27 @@ public: // becky is authorized to deposit to herself. validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(becky, becky, "validated").toStyledString()), - true); + env.rpc("json", "deposit_authorized", depositAuthArgs(becky, becky, "validated").toStyledString()), true); // alice should currently be authorized to deposit to becky. validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(alice, becky, "validated").toStyledString()), - true); + env.rpc("json", "deposit_authorized", depositAuthArgs(alice, becky, "validated").toStyledString()), true); // becky sets the DepositAuth flag in the current ledger. env(fset(becky, asfDepositAuth)); // alice is no longer authorized to deposit to becky in current ledger. validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(alice, becky).toStyledString()), - false); + env.rpc("json", "deposit_authorized", depositAuthArgs(alice, becky).toStyledString()), false); env.close(); // becky is still authorized to deposit to herself. validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(becky, becky, "validated").toStyledString()), - true); + env.rpc("json", "deposit_authorized", depositAuthArgs(becky, becky, "validated").toStyledString()), true); // It's not a reciprocal arrangement. becky can deposit to alice. validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(becky, alice, "current").toStyledString()), - true); + env.rpc("json", "deposit_authorized", depositAuthArgs(becky, alice, "current").toStyledString()), true); // becky creates a deposit authorization for alice. env(deposit::auth(becky, alice)); @@ -106,38 +86,22 @@ public: // alice is now authorized to deposit to becky. validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(alice, becky, "closed").toStyledString()), - true); + env.rpc("json", "deposit_authorized", depositAuthArgs(alice, becky, "closed").toStyledString()), true); // carol is still not authorized to deposit to becky. validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(carol, becky).toStyledString()), - false); + env.rpc("json", "deposit_authorized", depositAuthArgs(carol, becky).toStyledString()), false); // becky clears the DepositAuth flag so carol becomes authorized. env(fclear(becky, asfDepositAuth)); env.close(); validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(carol, becky).toStyledString()), - true); + env.rpc("json", "deposit_authorized", depositAuthArgs(carol, becky).toStyledString()), true); // alice is still authorized to deposit to becky. validateDepositAuthResult( - env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(alice, becky).toStyledString()), - true); + env.rpc("json", "deposit_authorized", depositAuthArgs(alice, becky).toStyledString()), true); } // Test malformed cases. @@ -150,10 +114,7 @@ public: Account const becky{"becky"}; // Lambda that checks the (error) result of deposit_authorized. - auto verifyErr = [this]( - Json::Value const& result, - char const* error, - char const* errorMsg) { + auto verifyErr = [this](Json::Value const& result, char const* error, char const* errorMsg) { BEAST_EXPECT(result[jss::result][jss::status] == jss::error); BEAST_EXPECT(result[jss::result][jss::error] == error); BEAST_EXPECT(result[jss::result][jss::error_message] == errorMsg); @@ -164,91 +125,67 @@ public: // Missing source_account field. Json::Value args{depositAuthArgs(alice, becky)}; args.removeMember(jss::source_account); - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; - verifyErr( - result, "invalidParams", "Missing field 'source_account'."); + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; + verifyErr(result, "invalidParams", "Missing field 'source_account'."); } { // Non-string source_account field. Json::Value args{depositAuthArgs(alice, becky)}; args[jss::source_account] = 7.3; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; - verifyErr( - result, - "invalidParams", - "Invalid field 'source_account', not a string."); + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; + verifyErr(result, "invalidParams", "Invalid field 'source_account', not a string."); } { // Corrupt source_account field. Json::Value args{depositAuthArgs(alice, becky)}; args[jss::source_account] = "rG1QQv2nh2gr7RCZ!P8YYcBUKCCN633jCn"; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; verifyErr(result, "actMalformed", "Account malformed."); } { // Missing destination_account field. Json::Value args{depositAuthArgs(alice, becky)}; args.removeMember(jss::destination_account); - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; - verifyErr( - result, - "invalidParams", - "Missing field 'destination_account'."); + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; + verifyErr(result, "invalidParams", "Missing field 'destination_account'."); } { // Non-string destination_account field. Json::Value args{depositAuthArgs(alice, becky)}; args[jss::destination_account] = 7.3; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; - verifyErr( - result, - "invalidParams", - "Invalid field 'destination_account', not a string."); + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; + verifyErr(result, "invalidParams", "Invalid field 'destination_account', not a string."); } { // Corrupt destination_account field. Json::Value args{depositAuthArgs(alice, becky)}; - args[jss::destination_account] = - "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas"; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; + args[jss::destination_account] = "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas"; + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; verifyErr(result, "actMalformed", "Account malformed."); } { // Request an invalid ledger. Json::Value args{depositAuthArgs(alice, becky, "-1")}; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; - verifyErr( - result, - "invalidParams", - "Invalid field 'ledger_index', not string or number."); + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; + verifyErr(result, "invalidParams", "Invalid field 'ledger_index', not string or number."); } { // Request a ledger that doesn't exist yet as a string. Json::Value args{depositAuthArgs(alice, becky, "17")}; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; verifyErr(result, "lgrNotFound", "ledgerNotFound"); } { // Request a ledger that doesn't exist yet. Json::Value args{depositAuthArgs(alice, becky)}; args[jss::ledger_index] = 17; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; verifyErr(result, "lgrNotFound", "ledgerNotFound"); } { // alice is not yet funded. Json::Value args{depositAuthArgs(alice, becky)}; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; verifyErr(result, "srcActNotFound", "Source account not found."); } env.fund(XRP(1000), alice); @@ -256,18 +193,15 @@ public: { // becky is not yet funded. Json::Value args{depositAuthArgs(alice, becky)}; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; - verifyErr( - result, "dstActNotFound", "Destination account not found."); + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; + verifyErr(result, "dstActNotFound", "Destination account not found."); } env.fund(XRP(1000), becky); env.close(); { // Once becky is funded try it again and see it succeed. Json::Value args{depositAuthArgs(alice, becky)}; - Json::Value const result{ - env.rpc("json", "deposit_authorized", args.toStyledString())}; + Json::Value const result{env.rpc("json", "deposit_authorized", args.toStyledString())}; validateDepositAuthResult(result, true); } } @@ -281,14 +215,11 @@ public: std::vector credentialIDs = {}, std::string_view error = "") { - BEAST_EXPECT( - result[jss::status] == authorized ? jss::success : jss::error); + BEAST_EXPECT(result[jss::status] == authorized ? jss::success : jss::error); if (result.isMember(jss::deposit_authorized)) BEAST_EXPECT(result[jss::deposit_authorized] == authorized); if (authorized) - BEAST_EXPECT( - result.isMember(jss::deposit_authorized) && - (result[jss::deposit_authorized] == true)); + BEAST_EXPECT(result.isMember(jss::deposit_authorized) && (result[jss::deposit_authorized] == true)); BEAST_EXPECT(result.isMember(jss::error) == !error.empty()); if (!error.empty()) @@ -350,16 +281,13 @@ public: env.close(); { - testcase( - "deposit_authorized with credentials failure: empty array."); + testcase("deposit_authorized with credentials failure: empty array."); auto args = depositAuthArgs(alice, becky, "validated"); args[jss::credentials] = Json::arrayValue; - auto const jv = - env.rpc("json", "deposit_authorized", args.toStyledString()); - checkCredentialsResponse( - jv[jss::result], alice, becky, false, {}, "invalidParams"); + auto const jv = env.rpc("json", "deposit_authorized", args.toStyledString()); + checkCredentialsResponse(jv[jss::result], alice, becky, false, {}, "invalidParams"); } { @@ -372,10 +300,8 @@ public: args[jss::credentials].append(1); args[jss::credentials].append(3); - auto const jv = - env.rpc("json", "deposit_authorized", args.toStyledString()); - checkCredentialsResponse( - jv[jss::result], alice, becky, false, {}, "invalidParams"); + auto const jv = env.rpc("json", "deposit_authorized", args.toStyledString()); + checkCredentialsResponse(jv[jss::result], alice, becky, false, {}, "invalidParams"); } { @@ -387,15 +313,8 @@ public: args[jss::credentials] = Json::arrayValue; args[jss::credentials].append("hello world"); - auto const jv = - env.rpc("json", "deposit_authorized", args.toStyledString()); - checkCredentialsResponse( - jv[jss::result], - alice, - becky, - false, - {"hello world"}, - "invalidParams"); + auto const jv = env.rpc("json", "deposit_authorized", args.toStyledString()); + checkCredentialsResponse(jv[jss::result], alice, becky, false, {"hello world"}, "invalidParams"); } { @@ -410,8 +329,7 @@ public: {"0127AB8B4B29CCDBB61AA51C0799A8A6BB80B86A9899807C11ED576AF8516" "473"}); - auto const jv = - env.rpc("json", "deposit_authorized", args.toStyledString()); + auto const jv = env.rpc("json", "deposit_authorized", args.toStyledString()); checkCredentialsResponse( jv[jss::result], alice, @@ -427,17 +345,8 @@ public: "deposit_authorized with credentials not authorized: " "credential not accepted"); auto const jv = env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(alice, becky, "validated", {credIdx}) - .toStyledString()); - checkCredentialsResponse( - jv[jss::result], - alice, - becky, - false, - {credIdx}, - "badCredentials"); + "json", "deposit_authorized", depositAuthArgs(alice, becky, "validated", {credIdx}).toStyledString()); + checkCredentialsResponse(jv[jss::result], alice, becky, false, {credIdx}, "badCredentials"); } // alice accept credentials @@ -449,15 +358,8 @@ public: auto const jv = env.rpc( "json", "deposit_authorized", - depositAuthArgs(alice, becky, "validated", {credIdx, credIdx}) - .toStyledString()); - checkCredentialsResponse( - jv[jss::result], - alice, - becky, - false, - {credIdx, credIdx}, - "badCredentials"); + depositAuthArgs(alice, becky, "validated", {credIdx, credIdx}).toStyledString()); + checkCredentialsResponse(jv[jss::result], alice, becky, false, {credIdx, credIdx}, "badCredentials"); } { @@ -484,23 +386,15 @@ public: testcase("deposit_authorized too long credentials"); auto const jv = env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(alice, becky, "validated", credIds) - .toStyledString()); - checkCredentialsResponse( - jv[jss::result], alice, becky, false, credIds, "invalidParams"); + "json", "deposit_authorized", depositAuthArgs(alice, becky, "validated", credIds).toStyledString()); + checkCredentialsResponse(jv[jss::result], alice, becky, false, credIds, "invalidParams"); } { testcase("deposit_authorized with credentials"); auto const jv = env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(alice, becky, "validated", {credIdx}) - .toStyledString()); - checkCredentialsResponse( - jv[jss::result], alice, becky, true, {credIdx}); + "json", "deposit_authorized", depositAuthArgs(alice, becky, "validated", {credIdx}).toStyledString()); + checkCredentialsResponse(jv[jss::result], alice, becky, true, {credIdx}); } { @@ -512,17 +406,12 @@ public: // retrieve the index of the credentials auto jv = credentials::ledgerEntry(env, becky, diana, credType); - std::string const credBecky = - jv[jss::result][jss::index].asString(); + std::string const credBecky = jv[jss::result][jss::index].asString(); testcase("deposit_authorized account without preauth"); jv = env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(becky, alice, "validated", {credBecky}) - .toStyledString()); - checkCredentialsResponse( - jv[jss::result], becky, alice, true, {credBecky}); + "json", "deposit_authorized", depositAuthArgs(becky, alice, "validated", {credBecky}).toStyledString()); + checkCredentialsResponse(jv[jss::result], becky, alice, true, {credBecky}); } { @@ -533,22 +422,12 @@ public: env.close(); // retrieve the index of the credentials auto jv = credentials::ledgerEntry(env, alice, carol, credType); - std::string const credDiana = - jv[jss::result][jss::index].asString(); + std::string const credDiana = jv[jss::result][jss::index].asString(); // alice try to use credential for different account jv = env.rpc( - "json", - "deposit_authorized", - depositAuthArgs(becky, alice, "validated", {credDiana}) - .toStyledString()); - checkCredentialsResponse( - jv[jss::result], - becky, - alice, - false, - {credDiana}, - "badCredentials"); + "json", "deposit_authorized", depositAuthArgs(becky, alice, "validated", {credDiana}).toStyledString()); + checkCredentialsResponse(jv[jss::result], becky, alice, false, {credDiana}, "badCredentials"); } { @@ -556,11 +435,7 @@ public: // check expired credentials char const credType2[] = "random"; - std::uint32_t const x = env.current() - ->header() - .parentCloseTime.time_since_epoch() - .count() + - 40; + std::uint32_t const x = env.current()->header().parentCloseTime.time_since_epoch().count() + 40; // create credentials with expire time 40s auto jv = credentials::create(alice, carol, credType2); @@ -585,10 +460,8 @@ public: jv = env.rpc( "json", "deposit_authorized", - depositAuthArgs(alice, becky, "validated", {credIdx2}) - .toStyledString()); - checkCredentialsResponse( - jv[jss::result], alice, becky, true, {credIdx2}); + depositAuthArgs(alice, becky, "validated", {credIdx2}).toStyledString()); + checkCredentialsResponse(jv[jss::result], alice, becky, true, {credIdx2}); } // increase timer by 20s @@ -599,16 +472,9 @@ public: jv = env.rpc( "json", "deposit_authorized", - depositAuthArgs(alice, becky, "validated", {credIdx2}) - .toStyledString()); + depositAuthArgs(alice, becky, "validated", {credIdx2}).toStyledString()); - checkCredentialsResponse( - jv[jss::result], - alice, - becky, - false, - {credIdx2}, - "badCredentials"); + checkCredentialsResponse(jv[jss::result], alice, becky, false, {credIdx2}, "badCredentials"); } } } diff --git a/src/test/rpc/Feature_test.cpp b/src/test/rpc/Feature_test.cpp index 6b66da072e..21596634e3 100644 --- a/src/test/rpc/Feature_test.cpp +++ b/src/test/rpc/Feature_test.cpp @@ -19,8 +19,7 @@ class Feature_test : public beast::unit_test::suite BEAST_EXPECT( supportedAmendments.size() == - xrpl::detail::numDownVotedAmendments() + - xrpl::detail::numUpVotedAmendments()); + xrpl::detail::numDownVotedAmendments() + xrpl::detail::numUpVotedAmendments()); { std::size_t up = 0, down = 0, obsolete = 0; for (auto const& [name, vote] : supportedAmendments) @@ -42,19 +41,14 @@ class Feature_test : public beast::unit_test::suite if (vote == VoteBehavior::Obsolete) { - BEAST_EXPECT( - allAmendments.contains(name) && - allAmendments.at(name) == AmendmentSupport::Retired); + BEAST_EXPECT(allAmendments.contains(name) && allAmendments.at(name) == AmendmentSupport::Retired); } else { - BEAST_EXPECT( - allAmendments.contains(name) && - allAmendments.at(name) == AmendmentSupport::Supported); + BEAST_EXPECT(allAmendments.contains(name) && allAmendments.at(name) == AmendmentSupport::Supported); } } - BEAST_EXPECT( - down + obsolete == xrpl::detail::numDownVotedAmendments()); + BEAST_EXPECT(down + obsolete == xrpl::detail::numDownVotedAmendments()); BEAST_EXPECT(up == xrpl::detail::numUpVotedAmendments()); } { @@ -79,9 +73,7 @@ class Feature_test : public beast::unit_test::suite } BEAST_EXPECT(supported + retired == supportedAmendments.size()); - BEAST_EXPECT( - allAmendments.size() - unsupported == - supportedAmendments.size()); + BEAST_EXPECT(allAmendments.size() - unsupported == supportedAmendments.size()); } } @@ -102,31 +94,24 @@ class Feature_test : public beast::unit_test::suite if (BEAST_EXPECT(registered)) { BEAST_EXPECT(featureToName(*registered) == feature); - BEAST_EXPECT( - bitsetIndexToFeature(featureToBitsetIndex(*registered)) == - *registered); + BEAST_EXPECT(bitsetIndexToFeature(featureToBitsetIndex(*registered)) == *registered); } } // Test an arbitrary unknown feature uint256 zero{0}; BEAST_EXPECT(featureToName(zero) == to_string(zero)); - BEAST_EXPECT( - featureToName(zero) == - "0000000000000000000000000000000000000000000000000000000000000000"); + BEAST_EXPECT(featureToName(zero) == "0000000000000000000000000000000000000000000000000000000000000000"); // Test looking up an unknown feature BEAST_EXPECT(!getRegisteredFeature("unknown")); // Test a random sampling of the variables. If any of these get retired // or removed, swap out for any other feature. - BEAST_EXPECT( - featureToName(fixRemoveNFTokenAutoTrustLine) == - "fixRemoveNFTokenAutoTrustLine"); + BEAST_EXPECT(featureToName(fixRemoveNFTokenAutoTrustLine) == "fixRemoveNFTokenAutoTrustLine"); BEAST_EXPECT(featureToName(featureBatch) == "Batch"); BEAST_EXPECT(featureToName(featureDID) == "DID"); - BEAST_EXPECT( - featureToName(fixIncludeKeyletFields) == "fixIncludeKeyletFields"); + BEAST_EXPECT(featureToName(fixIncludeKeyletFields) == "fixIncludeKeyletFields"); BEAST_EXPECT(featureToName(featureTokenEscrow) == "TokenEscrow"); } @@ -138,8 +123,7 @@ class Feature_test : public beast::unit_test::suite using namespace test::jtx; Env env{*this}; - std::map const& votes = - xrpl::detail::supportedAmendments(); + std::map const& votes = xrpl::detail::supportedAmendments(); auto jrr = env.rpc("feature")[jss::result]; if (!BEAST_EXPECT(jrr.isMember(jss::features))) @@ -150,27 +134,18 @@ class Feature_test : public beast::unit_test::suite return; // default config - so all should be disabled, and // supported. Some may be vetoed. - bool expectVeto = - (votes.at(feature[jss::name].asString()) == - VoteBehavior::DefaultNo); - bool expectObsolete = - (votes.at(feature[jss::name].asString()) == - VoteBehavior::Obsolete); + bool expectVeto = (votes.at(feature[jss::name].asString()) == VoteBehavior::DefaultNo); + bool expectObsolete = (votes.at(feature[jss::name].asString()) == VoteBehavior::Obsolete); BEAST_EXPECTS( - feature.isMember(jss::enabled) && - !feature[jss::enabled].asBool(), + feature.isMember(jss::enabled) && !feature[jss::enabled].asBool(), feature[jss::name].asString() + " enabled"); BEAST_EXPECTS( - feature.isMember(jss::vetoed) && - feature[jss::vetoed].isBool() == !expectObsolete && - (!feature[jss::vetoed].isBool() || - feature[jss::vetoed].asBool() == expectVeto) && - (feature[jss::vetoed].isBool() || - feature[jss::vetoed].asString() == "Obsolete"), + feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool() == !expectObsolete && + (!feature[jss::vetoed].isBool() || feature[jss::vetoed].asBool() == expectVeto) && + (feature[jss::vetoed].isBool() || feature[jss::vetoed].asString() == "Obsolete"), feature[jss::name].asString() + " vetoed"); BEAST_EXPECTS( - feature.isMember(jss::supported) && - feature[jss::supported].asBool(), + feature.isMember(jss::supported) && feature[jss::supported].asBool(), feature[jss::name].asString() + " supported"); } } @@ -194,9 +169,7 @@ class Feature_test : public beast::unit_test::suite BEAST_EXPECTS(feature[jss::name] == "fixAMMOverflowOffer", "name"); BEAST_EXPECTS(!feature[jss::enabled].asBool(), "enabled"); - BEAST_EXPECTS( - feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(), - "vetoed"); + BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(), "vetoed"); BEAST_EXPECTS(feature[jss::supported].asBool(), "supported"); // feature names are case-sensitive - expect error here @@ -216,8 +189,7 @@ class Feature_test : public beast::unit_test::suite auto testInvalidParam = [&](auto const& param) { Json::Value params; params[jss::feature] = param; - auto jrr = - env.rpc("json", "feature", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "feature", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::error_message] == "Invalid parameters."); }; @@ -232,8 +204,7 @@ class Feature_test : public beast::unit_test::suite { auto jrr = env.rpc("feature", "AllTheThings")[jss::result]; BEAST_EXPECT(jrr[jss::error] == "badFeature"); - BEAST_EXPECT( - jrr[jss::error_message] == "Feature unknown or invalid."); + BEAST_EXPECT(jrr[jss::error_message] == "Feature unknown or invalid."); } } @@ -256,25 +227,19 @@ class Feature_test : public beast::unit_test::suite // comparison to avoid maintenance as more amendments are added in // the future. BEAST_EXPECT(result[jss::features].size() >= 50); - for (auto it = result[jss::features].begin(); - it != result[jss::features].end(); - ++it) + for (auto it = result[jss::features].begin(); it != result[jss::features].end(); ++it) { uint256 id; (void)id.parseHex(it.key().asString().c_str()); if (!BEAST_EXPECT((*it).isMember(jss::name))) return; - bool expectEnabled = - env.app().getAmendmentTable().isEnabled(id); - bool expectSupported = - env.app().getAmendmentTable().isSupported(id); + bool expectEnabled = env.app().getAmendmentTable().isEnabled(id); + bool expectSupported = env.app().getAmendmentTable().isSupported(id); BEAST_EXPECTS( - (*it).isMember(jss::enabled) && - (*it)[jss::enabled].asBool() == expectEnabled, + (*it).isMember(jss::enabled) && (*it)[jss::enabled].asBool() == expectEnabled, (*it)[jss::name].asString() + " enabled"); BEAST_EXPECTS( - (*it).isMember(jss::supported) && - (*it)[jss::supported].asBool() == expectSupported, + (*it).isMember(jss::supported) && (*it)[jss::supported].asBool() == expectSupported, (*it)[jss::name].asString() + " supported"); BEAST_EXPECT(!(*it).isMember(jss::vetoed)); BEAST_EXPECT(!(*it).isMember(jss::majority)); @@ -290,12 +255,9 @@ class Feature_test : public beast::unit_test::suite params[jss::feature] = "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCD" "EF"; - auto const result = - env.rpc("json", "feature", to_string(params))[jss::result]; - BEAST_EXPECTS( - result[jss::error] == "badFeature", result.toStyledString()); - BEAST_EXPECT( - result[jss::error_message] == "Feature unknown or invalid."); + auto const result = env.rpc("json", "feature", to_string(params))[jss::result]; + BEAST_EXPECTS(result[jss::error] == "badFeature", result.toStyledString()); + BEAST_EXPECT(result[jss::error_message] == "Feature unknown or invalid."); } { @@ -305,14 +267,9 @@ class Feature_test : public beast::unit_test::suite "A7"; // invalid param params[jss::vetoed] = true; - auto const result = - env.rpc("json", "feature", to_string(params))[jss::result]; - BEAST_EXPECTS( - result[jss::error] == "noPermission", - result[jss::error].asString()); - BEAST_EXPECT( - result[jss::error_message] == - "You don't have permission for this command."); + auto const result = env.rpc("json", "feature", to_string(params))[jss::result]; + BEAST_EXPECTS(result[jss::error] == "noPermission", result[jss::error].asString()); + BEAST_EXPECT(result[jss::error_message] == "You don't have permission for this command."); } } @@ -324,49 +281,34 @@ class Feature_test : public beast::unit_test::suite using namespace test::jtx; Env env{*this, FeatureBitset{}}; - std::map const& votes = - xrpl::detail::supportedAmendments(); + std::map const& votes = xrpl::detail::supportedAmendments(); auto jrr = env.rpc("feature")[jss::result]; if (!BEAST_EXPECT(jrr.isMember(jss::features))) return; - for (auto it = jrr[jss::features].begin(); - it != jrr[jss::features].end(); - ++it) + for (auto it = jrr[jss::features].begin(); it != jrr[jss::features].end(); ++it) { uint256 id; (void)id.parseHex(it.key().asString().c_str()); if (!BEAST_EXPECT((*it).isMember(jss::name))) return; bool expectEnabled = env.app().getAmendmentTable().isEnabled(id); - bool expectSupported = - env.app().getAmendmentTable().isSupported(id); - bool expectVeto = - (votes.at((*it)[jss::name].asString()) == - VoteBehavior::DefaultNo); - bool expectObsolete = - (votes.at((*it)[jss::name].asString()) == - VoteBehavior::Obsolete); + bool expectSupported = env.app().getAmendmentTable().isSupported(id); + bool expectVeto = (votes.at((*it)[jss::name].asString()) == VoteBehavior::DefaultNo); + bool expectObsolete = (votes.at((*it)[jss::name].asString()) == VoteBehavior::Obsolete); BEAST_EXPECTS( - (*it).isMember(jss::enabled) && - (*it)[jss::enabled].asBool() == expectEnabled, + (*it).isMember(jss::enabled) && (*it)[jss::enabled].asBool() == expectEnabled, (*it)[jss::name].asString() + " enabled"); if (expectEnabled) - BEAST_EXPECTS( - !(*it).isMember(jss::vetoed), - (*it)[jss::name].asString() + " vetoed"); + BEAST_EXPECTS(!(*it).isMember(jss::vetoed), (*it)[jss::name].asString() + " vetoed"); else BEAST_EXPECTS( - (*it).isMember(jss::vetoed) && - (*it)[jss::vetoed].isBool() == !expectObsolete && - (!(*it)[jss::vetoed].isBool() || - (*it)[jss::vetoed].asBool() == expectVeto) && - ((*it)[jss::vetoed].isBool() || - (*it)[jss::vetoed].asString() == "Obsolete"), + (*it).isMember(jss::vetoed) && (*it)[jss::vetoed].isBool() == !expectObsolete && + (!(*it)[jss::vetoed].isBool() || (*it)[jss::vetoed].asBool() == expectVeto) && + ((*it)[jss::vetoed].isBool() || (*it)[jss::vetoed].asString() == "Obsolete"), (*it)[jss::name].asString() + " vetoed"); BEAST_EXPECTS( - (*it).isMember(jss::supported) && - (*it)[jss::supported].asBool() == expectSupported, + (*it).isMember(jss::supported) && (*it)[jss::supported].asBool() == expectSupported, (*it)[jss::name].asString() + " supported"); } } @@ -389,21 +331,11 @@ class Feature_test : public beast::unit_test::suite { if (!BEAST_EXPECT(feature.isMember(jss::name))) return; - BEAST_EXPECTS( - !feature.isMember(jss::majority), - feature[jss::name].asString() + " majority"); - BEAST_EXPECTS( - !feature.isMember(jss::count), - feature[jss::name].asString() + " count"); - BEAST_EXPECTS( - !feature.isMember(jss::threshold), - feature[jss::name].asString() + " threshold"); - BEAST_EXPECTS( - !feature.isMember(jss::validations), - feature[jss::name].asString() + " validations"); - BEAST_EXPECTS( - !feature.isMember(jss::vote), - feature[jss::name].asString() + " vote"); + BEAST_EXPECTS(!feature.isMember(jss::majority), feature[jss::name].asString() + " majority"); + BEAST_EXPECTS(!feature.isMember(jss::count), feature[jss::name].asString() + " count"); + BEAST_EXPECTS(!feature.isMember(jss::threshold), feature[jss::name].asString() + " threshold"); + BEAST_EXPECTS(!feature.isMember(jss::validations), feature[jss::name].asString() + " validations"); + BEAST_EXPECTS(!feature.isMember(jss::vote), feature[jss::name].asString() + " vote"); } auto majorities = getMajorityAmendments(*env.closed()); @@ -422,8 +354,7 @@ class Feature_test : public beast::unit_test::suite // There should be at least 2 amendments. Don't do exact comparison // to avoid maintenance as more amendments are added in the future. BEAST_EXPECT(majorities.size() >= 2); - std::map const& votes = - xrpl::detail::supportedAmendments(); + std::map const& votes = xrpl::detail::supportedAmendments(); jrr = env.rpc("feature")[jss::result]; if (!BEAST_EXPECT(jrr.isMember(jss::features))) @@ -432,36 +363,20 @@ class Feature_test : public beast::unit_test::suite { if (!BEAST_EXPECT(feature.isMember(jss::name))) return; - bool expectVeto = - (votes.at(feature[jss::name].asString()) == - VoteBehavior::DefaultNo); - bool expectObsolete = - (votes.at(feature[jss::name].asString()) == - VoteBehavior::Obsolete); + bool expectVeto = (votes.at(feature[jss::name].asString()) == VoteBehavior::DefaultNo); + bool expectObsolete = (votes.at(feature[jss::name].asString()) == VoteBehavior::Obsolete); BEAST_EXPECTS( - (expectVeto || expectObsolete) ^ - feature.isMember(jss::majority), + (expectVeto || expectObsolete) ^ feature.isMember(jss::majority), feature[jss::name].asString() + " majority"); BEAST_EXPECTS( - feature.isMember(jss::vetoed) && - feature[jss::vetoed].isBool() == !expectObsolete && - (!feature[jss::vetoed].isBool() || - feature[jss::vetoed].asBool() == expectVeto) && - (feature[jss::vetoed].isBool() || - feature[jss::vetoed].asString() == "Obsolete"), + feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool() == !expectObsolete && + (!feature[jss::vetoed].isBool() || feature[jss::vetoed].asBool() == expectVeto) && + (feature[jss::vetoed].isBool() || feature[jss::vetoed].asString() == "Obsolete"), feature[jss::name].asString() + " vetoed"); - BEAST_EXPECTS( - feature.isMember(jss::count), - feature[jss::name].asString() + " count"); - BEAST_EXPECTS( - feature.isMember(jss::threshold), - feature[jss::name].asString() + " threshold"); - BEAST_EXPECTS( - feature.isMember(jss::validations), - feature[jss::name].asString() + " validations"); - BEAST_EXPECT( - feature[jss::count] == - ((expectVeto || expectObsolete) ? 0 : 1)); + BEAST_EXPECTS(feature.isMember(jss::count), feature[jss::name].asString() + " count"); + BEAST_EXPECTS(feature.isMember(jss::threshold), feature[jss::name].asString() + " threshold"); + BEAST_EXPECTS(feature.isMember(jss::validations), feature[jss::name].asString() + " validations"); + BEAST_EXPECT(feature[jss::count] == ((expectVeto || expectObsolete) ? 0 : 1)); BEAST_EXPECT(feature[jss::threshold] == 1); BEAST_EXPECT(feature[jss::validations] == 1); BEAST_EXPECTS( @@ -487,9 +402,7 @@ class Feature_test : public beast::unit_test::suite return; auto feature = *(jrr.begin()); BEAST_EXPECTS(feature[jss::name] == featureName, "name"); - BEAST_EXPECTS( - feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(), - "vetoed"); + BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(), "vetoed"); jrr = env.rpc("feature", featureName, "reject")[jss::result]; if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status")) @@ -499,9 +412,7 @@ class Feature_test : public beast::unit_test::suite return; feature = *(jrr.begin()); BEAST_EXPECTS(feature[jss::name] == featureName, "name"); - BEAST_EXPECTS( - feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool(), - "vetoed"); + BEAST_EXPECTS(feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool(), "vetoed"); jrr = env.rpc("feature", featureName, "accept")[jss::result]; if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status")) @@ -511,9 +422,7 @@ class Feature_test : public beast::unit_test::suite return; feature = *(jrr.begin()); BEAST_EXPECTS(feature[jss::name] == featureName, "name"); - BEAST_EXPECTS( - feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(), - "vetoed"); + BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(), "vetoed"); // anything other than accept or reject is an error jrr = env.rpc("feature", featureName, "maybe"); @@ -530,10 +439,8 @@ class Feature_test : public beast::unit_test::suite Env env{*this}; auto const& supportedAmendments = detail::supportedAmendments(); - auto obsoleteFeature = std::find_if( - std::begin(supportedAmendments), - std::end(supportedAmendments), - [](auto const& pair) { + auto obsoleteFeature = + std::find_if(std::begin(supportedAmendments), std::end(supportedAmendments), [](auto const& pair) { return pair.second == VoteBehavior::Obsolete; }); @@ -553,10 +460,7 @@ class Feature_test : public beast::unit_test::suite return; auto feature = *(jrr.begin()); BEAST_EXPECTS(feature[jss::name] == featureName, "name"); - BEAST_EXPECTS( - feature[jss::vetoed].isString() && - feature[jss::vetoed].asString() == "Obsolete", - "vetoed"); + BEAST_EXPECTS(feature[jss::vetoed].isString() && feature[jss::vetoed].asString() == "Obsolete", "vetoed"); jrr = env.rpc("feature", featureName, "reject")[jss::result]; if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status")) @@ -566,10 +470,7 @@ class Feature_test : public beast::unit_test::suite return; feature = *(jrr.begin()); BEAST_EXPECTS(feature[jss::name] == featureName, "name"); - BEAST_EXPECTS( - feature[jss::vetoed].isString() && - feature[jss::vetoed].asString() == "Obsolete", - "vetoed"); + BEAST_EXPECTS(feature[jss::vetoed].isString() && feature[jss::vetoed].asString() == "Obsolete", "vetoed"); jrr = env.rpc("feature", featureName, "accept")[jss::result]; if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status")) @@ -579,10 +480,7 @@ class Feature_test : public beast::unit_test::suite return; feature = *(jrr.begin()); BEAST_EXPECTS(feature[jss::name] == featureName, "name"); - BEAST_EXPECTS( - feature[jss::vetoed].isString() && - feature[jss::vetoed].asString() == "Obsolete", - "vetoed"); + BEAST_EXPECTS(feature[jss::vetoed].isString() && feature[jss::vetoed].asString() == "Obsolete", "vetoed"); // anything other than accept or reject is an error jrr = env.rpc("feature", featureName, "maybe"); diff --git a/src/test/rpc/GRPCTestClientBase.h b/src/test/rpc/GRPCTestClientBase.h index 6cb806a562..5e547b1dfb 100644 --- a/src/test/rpc/GRPCTestClientBase.h +++ b/src/test/rpc/GRPCTestClientBase.h @@ -13,13 +13,9 @@ namespace test { struct GRPCTestClientBase { explicit GRPCTestClientBase(std::string const& port) - : stub_(org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub( - grpc::CreateChannel( - beast::IP::Endpoint( - boost::asio::ip::make_address(getEnvLocalhostAddr()), - std::stoi(port)) - .to_string(), - grpc::InsecureChannelCredentials()))) + : stub_(org::xrpl::rpc::v1::XRPLedgerAPIService::NewStub(grpc::CreateChannel( + beast::IP::Endpoint(boost::asio::ip::make_address(getEnvLocalhostAddr()), std::stoi(port)).to_string(), + grpc::InsecureChannelCredentials()))) { } diff --git a/src/test/rpc/GatewayBalances_test.cpp b/src/test/rpc/GatewayBalances_test.cpp index 40f56dfc81..6415f6a51f 100644 --- a/src/test/rpc/GatewayBalances_test.cpp +++ b/src/test/rpc/GatewayBalances_test.cpp @@ -77,8 +77,7 @@ public: if (wsc->version() == 2) { expect(jv.isMember(jss::jsonrpc) && jv[jss::jsonrpc] == "2.0"); - expect( - jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0"); + expect(jv.isMember(jss::ripplerpc) && jv[jss::ripplerpc] == "2.0"); expect(jv.isMember(jss::id) && jv[jss::id] == 5); } @@ -98,9 +97,7 @@ public: auto c2 = hwBalance[1u][jss::currency]; expect(c1 == "USD" || c2 == "USD"); expect(c1 == "JPY" || c2 == "JPY"); - expect( - hwBalance[0u][jss::value] == "5000" && - hwBalance[1u][jss::value] == "5000"); + expect(hwBalance[0u][jss::value] == "5000" && hwBalance[1u][jss::value] == "5000"); } { @@ -165,8 +162,7 @@ public: expect(jv[jss::status] == "error"); auto response = jv[jss::result]; - auto const error = - apiVersion < 2u ? "invalidHotWallet" : "invalidParams"; + auto const error = apiVersion < 2u ? "invalidHotWallet" : "invalidParams"; BEAST_EXPECT(response[jss::error] == error); }); } @@ -185,8 +181,7 @@ public: auto USD = alice["USD"]; // The largest valid STAmount of USD: - STAmount const maxUSD( - USD.issue(), STAmount::cMaxValue, STAmount::cMaxOffset); + STAmount const maxUSD(USD.issue(), STAmount::cMaxValue, STAmount::cMaxOffset); // Create a hotwallet Account const hw{"hw"}; diff --git a/src/test/rpc/GetAggregatePrice_test.cpp b/src/test/rpc/GetAggregatePrice_test.cpp index 0ffefc6cb6..e6cfb3a229 100644 --- a/src/test/rpc/GetAggregatePrice_test.cpp +++ b/src/test/rpc/GetAggregatePrice_test.cpp @@ -26,17 +26,12 @@ public: Env env(*this); auto const baseFee = env.current()->fees().base; // missing base_asset - auto ret = - Oracle::aggregatePrice(env, std::nullopt, "USD", oracles); - BEAST_EXPECT( - ret[jss::error_message].asString() == - "Missing field 'base_asset'."); + auto ret = Oracle::aggregatePrice(env, std::nullopt, "USD", oracles); + BEAST_EXPECT(ret[jss::error_message].asString() == "Missing field 'base_asset'."); // missing quote_asset ret = Oracle::aggregatePrice(env, "XRP", std::nullopt, oracles); - BEAST_EXPECT( - ret[jss::error_message].asString() == - "Missing field 'quote_asset'."); + BEAST_EXPECT(ret[jss::error_message].asString() == "Missing field 'quote_asset'."); // invalid base_asset, quote_asset std::vector invalidAsset = { @@ -66,9 +61,7 @@ public: // missing oracles array ret = Oracle::aggregatePrice(env, "XRP", "USD"); - BEAST_EXPECT( - ret[jss::error_message].asString() == - "Missing field 'oracles'."); + BEAST_EXPECT(ret[jss::error_message].asString() == "Missing field 'oracles'."); // empty oracles array ret = Oracle::aggregatePrice(env, "XRP", "USD", OraclesData{}); @@ -83,8 +76,7 @@ public: ret = Oracle::aggregatePrice(env, "XRP", "USD", {{{owner, 2}}}); BEAST_EXPECT(ret[jss::error].asString() == "objectNotFound"); // invalid values - std::vector invalidDocument = { - NoneTag, 1.2, -1, "", "none", "1.2"}; + std::vector invalidDocument = {NoneTag, 1.2, -1, "", "none", "1.2"}; for (auto const& v : invalidDocument) { ret = Oracle::aggregatePrice(env, "XRP", "USD", {{{owner, v}}}); @@ -93,51 +85,36 @@ public: BEAST_EXPECT(ret[jss::error].asString() == "invalidParams"); } // missing document id - ret = Oracle::aggregatePrice( - env, "XRP", "USD", {{{owner, std::nullopt}}}); + ret = Oracle::aggregatePrice(env, "XRP", "USD", {{{owner, std::nullopt}}}); BEAST_EXPECT(ret[jss::error].asString() == "oracleMalformed"); // invalid owner ret = Oracle::aggregatePrice(env, "XRP", "USD", {{{some, 1}}}); BEAST_EXPECT(ret[jss::error].asString() == "objectNotFound"); // missing account - ret = Oracle::aggregatePrice( - env, "XRP", "USD", {{{std::nullopt, 1}}}); + ret = Oracle::aggregatePrice(env, "XRP", "USD", {{{std::nullopt, 1}}}); BEAST_EXPECT(ret[jss::error].asString() == "oracleMalformed"); // oracles have wrong asset pair env.fund(XRP(1'000), owner); Oracle oracle( - env, - {.owner = owner, - .series = {{"XRP", "EUR", 740, 1}}, - .fee = static_cast(baseFee.drops())}); - ret = Oracle::aggregatePrice( - env, "XRP", "USD", {{{owner, oracle.documentID()}}}); + env, {.owner = owner, .series = {{"XRP", "EUR", 740, 1}}, .fee = static_cast(baseFee.drops())}); + ret = Oracle::aggregatePrice(env, "XRP", "USD", {{{owner, oracle.documentID()}}}); BEAST_EXPECT(ret[jss::error].asString() == "objectNotFound"); // invalid trim value - std::vector invalidTrim = { - NoneTag, 0, 26, -1, 1.2, "", "none", "1.2"}; + std::vector invalidTrim = {NoneTag, 0, 26, -1, 1.2, "", "none", "1.2"}; for (auto const& v : invalidTrim) { - ret = Oracle::aggregatePrice( - env, "XRP", "USD", {{{owner, oracle.documentID()}}}, v); + ret = Oracle::aggregatePrice(env, "XRP", "USD", {{{owner, oracle.documentID()}}}, v); BEAST_EXPECT(ret[jss::error].asString() == "invalidParams"); } // invalid time threshold value - std::vector invalidTime = { - NoneTag, -1, 1.2, "", "none", "1.2"}; + std::vector invalidTime = {NoneTag, -1, 1.2, "", "none", "1.2"}; for (auto const& v : invalidTime) { - ret = Oracle::aggregatePrice( - env, - "XRP", - "USD", - {{{owner, oracle.documentID()}}}, - std::nullopt, - v); + ret = Oracle::aggregatePrice(env, "XRP", "USD", {{{owner, oracle.documentID()}}}, std::nullopt, v); BEAST_EXPECT(ret[jss::error].asString() == "invalidParams"); } } @@ -145,16 +122,14 @@ public: // too many oracles { Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); OraclesData oracles; for (int i = 0; i < 201; ++i) { Account const owner(std::to_string(i)); env.fund(XRP(1'000), owner); - Oracle oracle( - env, {.owner = owner, .documentID = i, .fee = baseFee}); + Oracle oracle(env, {.owner = owner, .documentID = i, .fee = baseFee}); oracles.emplace_back(owner, oracle.documentID()); } auto const ret = Oracle::aggregatePrice(env, "XRP", "USD", oracles); @@ -172,8 +147,7 @@ public: oracles.reserve(10); for (int i = 0; i < 10; ++i) { - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); Account const owner{std::to_string(i)}; env.fund(XRP(1'000), owner); @@ -181,8 +155,7 @@ public: env, {.owner = owner, .documentID = rand(), - .series = - {{"XRP", "USD", 740 + i, 1}, {"XRP", "EUR", 740, 1}}, + .series = {{"XRP", "USD", 740 + i, 1}, {"XRP", "EUR", 740, 1}}, .fee = baseFee}); oracles.emplace_back(owner, oracle.documentID()); } @@ -192,11 +165,9 @@ public: // or time threshold { auto const all = testable_amendments(); - for (auto const& feats : - {all - featureSingleAssetVault - featureLendingProtocol, all}) + for (auto const& feats : {all - featureSingleAssetVault - featureLendingProtocol, all}) { - for (auto const mantissaSize : - {MantissaRange::small, MantissaRange::large}) + for (auto const mantissaSize : {MantissaRange::small, MantissaRange::large}) { // Regardless of the features enabled, RPC is controlled by // the global mantissa size. And since it's a thread-local, @@ -208,17 +179,13 @@ public: OraclesData oracles; prep(env, oracles); // entire and trimmed stats - auto ret = - Oracle::aggregatePrice(env, "XRP", "USD", oracles); + auto ret = Oracle::aggregatePrice(env, "XRP", "USD", oracles); BEAST_EXPECT(ret[jss::entire_set][jss::mean] == "74.45"); - BEAST_EXPECT( - ret[jss::entire_set][jss::size].asUInt() == 10); + BEAST_EXPECT(ret[jss::entire_set][jss::size].asUInt() == 10); // Short: 0.3027650354097492 BEAST_EXPECTS( - ret[jss::entire_set][jss::standard_deviation] == - "0.3027650354097491666", - ret[jss::entire_set][jss::standard_deviation] - .asString()); + ret[jss::entire_set][jss::standard_deviation] == "0.3027650354097491666", + ret[jss::entire_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::median] == "74.45"); BEAST_EXPECT(ret[jss::time] == 946694900); } @@ -231,22 +198,19 @@ public: OraclesData oracles; prep(env, oracles); // entire and trimmed stats - auto ret = - Oracle::aggregatePrice(env, "XRP", "USD", oracles, 20, 100); + auto ret = Oracle::aggregatePrice(env, "XRP", "USD", oracles, 20, 100); BEAST_EXPECT(ret[jss::entire_set][jss::mean] == "74.45"); BEAST_EXPECT(ret[jss::entire_set][jss::size].asUInt() == 10); // Short: "0.3027650354097492", BEAST_EXPECTS( - ret[jss::entire_set][jss::standard_deviation] == - "0.3027650354097491666", + ret[jss::entire_set][jss::standard_deviation] == "0.3027650354097491666", ret[jss::entire_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::median] == "74.45"); BEAST_EXPECT(ret[jss::trimmed_set][jss::mean] == "74.45"); BEAST_EXPECT(ret[jss::trimmed_set][jss::size].asUInt() == 6); // Short: "0.187082869338697", BEAST_EXPECTS( - ret[jss::trimmed_set][jss::standard_deviation] == - "0.1870828693386970693", + ret[jss::trimmed_set][jss::standard_deviation] == "0.1870828693386970693", ret[jss::trimmed_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::time] == 946694900); } @@ -255,61 +219,44 @@ public: // updated ledgers { Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); OraclesData oracles; prep(env, oracles); for (int i = 0; i < 3; ++i) { Oracle oracle( - env, - {.owner = oracles[i].first, - .documentID = asUInt(*oracles[i].second), - .fee = baseFee}, - false); + env, {.owner = oracles[i].first, .documentID = asUInt(*oracles[i].second), .fee = baseFee}, false); // push XRP/USD by more than three ledgers, so this price // oracle is not included in the dataset - oracle.set(UpdateArg{ - .series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); - oracle.set(UpdateArg{ - .series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); - oracle.set(UpdateArg{ - .series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); } for (int i = 3; i < 6; ++i) { Oracle oracle( - env, - {.owner = oracles[i].first, - .documentID = asUInt(*oracles[i].second), - .fee = baseFee}, - false); + env, {.owner = oracles[i].first, .documentID = asUInt(*oracles[i].second), .fee = baseFee}, false); // push XRP/USD by two ledgers, so this price // is included in the dataset - oracle.set(UpdateArg{ - .series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); - oracle.set(UpdateArg{ - .series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "EUR", 740, 1}}, .fee = baseFee}); } // entire and trimmed stats - auto ret = - Oracle::aggregatePrice(env, "XRP", "USD", oracles, 20, "200"); + auto ret = Oracle::aggregatePrice(env, "XRP", "USD", oracles, 20, "200"); BEAST_EXPECT(ret[jss::entire_set][jss::mean] == "74.6"); BEAST_EXPECT(ret[jss::entire_set][jss::size].asUInt() == 7); // Short: 0.2160246899469287 BEAST_EXPECTS( - ret[jss::entire_set][jss::standard_deviation] == - "0.2160246899469286744", + ret[jss::entire_set][jss::standard_deviation] == "0.2160246899469286744", ret[jss::entire_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::median] == "74.6"); BEAST_EXPECT(ret[jss::trimmed_set][jss::mean] == "74.6"); BEAST_EXPECT(ret[jss::trimmed_set][jss::size].asUInt() == 5); // Short: 0.158113883008419 BEAST_EXPECTS( - ret[jss::trimmed_set][jss::standard_deviation] == - "0.1581138830084189666", + ret[jss::trimmed_set][jss::standard_deviation] == "0.1581138830084189666", ret[jss::trimmed_set][jss::standard_deviation].asString()); BEAST_EXPECT(ret[jss::time] == 946694900); } @@ -317,28 +264,21 @@ public: // Reduced data set because of the time threshold { Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); OraclesData oracles; prep(env, oracles); for (int i = 0; i < oracles.size(); ++i) { Oracle oracle( - env, - {.owner = oracles[i].first, - .documentID = asUInt(*oracles[i].second), - .fee = baseFee}, - false); + env, {.owner = oracles[i].first, .documentID = asUInt(*oracles[i].second), .fee = baseFee}, false); // push XRP/USD by two ledgers, so this price // is included in the dataset - oracle.set(UpdateArg{ - .series = {{"XRP", "USD", 740, 1}}, .fee = baseFee}); + oracle.set(UpdateArg{.series = {{"XRP", "USD", 740, 1}}, .fee = baseFee}); } // entire stats only, limit lastUpdateTime to {200, 125} - auto ret = Oracle::aggregatePrice( - env, "XRP", "USD", oracles, std::nullopt, 75); + auto ret = Oracle::aggregatePrice(env, "XRP", "USD", oracles, std::nullopt, 75); BEAST_EXPECT(ret[jss::entire_set][jss::mean] == "74"); BEAST_EXPECT(ret[jss::entire_set][jss::size].asUInt() == 8); BEAST_EXPECT(ret[jss::entire_set][jss::standard_deviation] == "0"); diff --git a/src/test/rpc/GetCounts_test.cpp b/src/test/rpc/GetCounts_test.cpp index b9ad5ec254..07c29e3648 100644 --- a/src/test/rpc/GetCounts_test.cpp +++ b/src/test/rpc/GetCounts_test.cpp @@ -26,12 +26,8 @@ class GetCounts_test : public beast::unit_test::suite BEAST_EXPECT(!result.isMember("Transaction")); BEAST_EXPECT(!result.isMember("STObject")); BEAST_EXPECT(!result.isMember("HashRouterEntry")); - BEAST_EXPECT( - result.isMember(jss::uptime) && - !result[jss::uptime].asString().empty()); - BEAST_EXPECT( - result.isMember(jss::dbKBTotal) && - result[jss::dbKBTotal].asInt() > 0); + BEAST_EXPECT(result.isMember(jss::uptime) && !result[jss::uptime].asString().empty()); + BEAST_EXPECT(result.isMember(jss::dbKBTotal) && result[jss::dbKBTotal].asInt() > 0); } // create some transactions @@ -51,8 +47,7 @@ class GetCounts_test : public beast::unit_test::suite result = env.rpc("get_counts")[jss::result]; BEAST_EXPECT(result[jss::status] == "success"); // compare with values reported by CountedObjects - auto const& objectCounts = - CountedObjects::getInstance().getCounts(10); + auto const& objectCounts = CountedObjects::getInstance().getCounts(10); for (auto const& it : objectCounts) { BEAST_EXPECTS(result.isMember(it.first), it.first); @@ -68,8 +63,7 @@ class GetCounts_test : public beast::unit_test::suite BEAST_EXPECT(result[jss::status] == "success"); // compare with values reported by CountedObjects - auto const& objectCounts = - CountedObjects::getInstance().getCounts(100); + auto const& objectCounts = CountedObjects::getInstance().getCounts(100); for (auto const& it : objectCounts) { BEAST_EXPECTS(result.isMember(it.first), it.first); @@ -87,9 +81,7 @@ class GetCounts_test : public beast::unit_test::suite env(pay(alice, bob, alice["USD"](5))); result = env.rpc("get_counts")[jss::result]; // deliberately don't call close so we have open Tx - BEAST_EXPECT( - result.isMember(jss::local_txs) && - result[jss::local_txs].asInt() > 0); + BEAST_EXPECT(result.isMember(jss::local_txs) && result[jss::local_txs].asInt() > 0); } } diff --git a/src/test/rpc/Handler_test.cpp b/src/test/rpc/Handler_test.cpp index 9a6f1b3aa1..189949d92c 100644 --- a/src/test/rpc/Handler_test.cpp +++ b/src/test/rpc/Handler_test.cpp @@ -68,8 +68,7 @@ class Handler_test : public beast::unit_test::suite double const mean_squared = (sum * sum) / (j * j); return std::make_tuple( clock::duration{static_cast(sum / j)}, - clock::duration{ - static_cast(std::sqrt((sum_squared / j) - mean_squared))}, + clock::duration{static_cast(std::sqrt((sum_squared / j) - mean_squared))}, j); } @@ -81,8 +80,7 @@ class Handler_test : public beast::unit_test::suite std::random_device dev; std::ranlux48 prng(dev()); - std::vector names = - test::jtx::make_vector(xrpl::RPC::getHandlerNames()); + std::vector names = test::jtx::make_vector(xrpl::RPC::getHandlerNames()); std::uniform_int_distribution distr{0, names.size() - 1}; @@ -95,8 +93,7 @@ class Handler_test : public beast::unit_test::suite }, [&]() -> std::size_t { return distr(prng); }); - std::cout << "mean=" << mean << " stdev=" << stdev << " N=" << n - << '\n'; + std::cout << "mean=" << mean << " stdev=" << stdev << " N=" << n << '\n'; BEAST_EXPECT(dummy != 0); } diff --git a/src/test/rpc/JSONRPC_test.cpp b/src/test/rpc/JSONRPC_test.cpp index 6a9fae74a5..f0329748e1 100644 --- a/src/test/rpc/JSONRPC_test.cpp +++ b/src/test/rpc/JSONRPC_test.cpp @@ -63,10 +63,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'account'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'account'.", "Missing field 'tx_json.Sequence'."}}}, {"Pass in Fee with minimal payment, both Amount and DeliverMax.", __LINE__, @@ -83,10 +80,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"Pass in Sequence, no Amount only DeliverMax", __LINE__, @@ -102,10 +96,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Fee'.", - "Missing field 'tx_json.SigningPubKey'."}}}, + {{"", "", "Missing field 'tx_json.Fee'.", "Missing field 'tx_json.SigningPubKey'."}}}, {"Pass in Sequence and Fee with minimal payment, both Amount and " "DeliverMax.", @@ -145,10 +136,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Fee'.", - "Missing field 'tx_json.SigningPubKey'."}}}, + {{"", "", "Missing field 'tx_json.Fee'.", "Missing field 'tx_json.SigningPubKey'."}}}, {"Add 'fee_mult_max' and 'fee_div_max' field.", __LINE__, @@ -166,10 +154,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Fee'.", - "Missing field 'tx_json.SigningPubKey'."}}}, + {{"", "", "Missing field 'tx_json.Fee'.", "Missing field 'tx_json.SigningPubKey'."}}}, {"fee_mult_max is ignored if 'Fee' is present.", __LINE__, @@ -426,10 +411,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"Not valid to include both 'Paths' and 'build_path'.", __LINE__, @@ -478,10 +460,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"'Amount' may not be XRP for pathfinding, but 'SendMax' may be XRP.", __LINE__, @@ -502,10 +481,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"'secret' must be present.", __LINE__, @@ -556,10 +532,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"Malformed 'seed'.", __LINE__, @@ -646,10 +619,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": 0 } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"'Account' must be present.", __LINE__, @@ -700,10 +670,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"If 'offline' is true then a 'Sequence' field must be supplied.", __LINE__, @@ -803,10 +770,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"The 'Flags' field must be numeric.", __LINE__, @@ -841,10 +805,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"", - "", - "Missing field 'tx_json.Sequence'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'tx_json.Sequence'.", "Missing field 'tx_json.Sequence'."}}}, {"Single-sign a multisigned transaction.", __LINE__, @@ -871,10 +832,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType" : "Payment" } })", - {{"Already multisigned.", - "Already multisigned.", - "Secret does not match account.", - ""}}}, + {{"Already multisigned.", "Already multisigned.", "Secret does not match account.", ""}}}, {"Minimal sign_for.", __LINE__, @@ -892,10 +850,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"Secret does not match account.", - "Secret does not match account.", - "", - "Missing field 'tx_json.Signers'."}}}, + {{"Secret does not match account.", "Secret does not match account.", "", "Missing field 'tx_json.Signers'."}}}, {"Minimal offline sign_for.", __LINE__, @@ -954,10 +909,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"Disallowed seed.", - "Disallowed seed.", - "Disallowed seed.", - "Missing field 'tx_json.Signers'."}}}, + {{"Disallowed seed.", "Disallowed seed.", "Disallowed seed.", "Missing field 'tx_json.Signers'."}}}, {"Missing 'Account' in sign_for.", __LINE__, @@ -1203,10 +1155,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType" : "Payment" } })", - {{"Already multisigned.", - "Already multisigned.", - "Invalid signature.", - "Invalid signature."}}}, + {{"Already multisigned.", "Already multisigned.", "Invalid signature.", "Invalid signature."}}}, {"Non-empty 'SigningPubKey' in sign_for.", __LINE__, @@ -1362,10 +1311,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"Missing field 'secret'.", - "Missing field 'secret'.", - "Missing field 'account'.", - ""}}}, + {{"Missing field 'secret'.", "Missing field 'secret'.", "Missing field 'account'.", ""}}}, {"Minimal submit_multisigned with bad signature.", __LINE__, @@ -1390,10 +1336,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"Missing field 'secret'.", - "Missing field 'secret'.", - "Missing field 'account'.", - "Invalid signature."}}}, + {{"Missing field 'secret'.", "Missing field 'secret'.", "Missing field 'account'.", "Invalid signature."}}}, {"Missing tx_json in submit_multisigned.", __LINE__, @@ -1409,10 +1352,7 @@ static constexpr TxnTestData txnTestArray[] = { } ] })", - {{"Missing field 'secret'.", - "Missing field 'secret'.", - "Missing field 'account'.", - "Missing field 'tx_json'."}}}, + {{"Missing field 'secret'.", "Missing field 'secret'.", "Missing field 'account'.", "Missing field 'tx_json'."}}}, {"Missing sequence in submit_multisigned.", __LINE__, @@ -1601,10 +1541,7 @@ static constexpr TxnTestData txnTestArray[] = { "TransactionType": "Payment" } })", - {{"Missing field 'secret'.", - "Missing field 'secret'.", - "Missing field 'account'.", - "Source account not found."}}}, + {{"Missing field 'secret'.", "Missing field 'secret'.", "Missing field 'account'.", "Source account not found."}}}, {"Missing Fee in submit_multisigned.", __LINE__, @@ -2058,10 +1995,7 @@ static constexpr TxnTestData txnTestArray[] = { "Delegate": "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA" } })", - {{"", - "", - "Missing field 'account'.", - "Missing field 'tx_json.Sequence'."}}}, + {{"", "", "Missing field 'account'.", "Missing field 'tx_json.Sequence'."}}}, {"Delegate not well formed.", __LINE__, @@ -2127,12 +2061,10 @@ public: { testcase("bad RPC command"); test::jtx::Env env(*this); - Json::Value const result{ - env.rpc("bad_command", R"({"MakingThisUp": 0})")}; + Json::Value const result{env.rpc("bad_command", R"({"MakingThisUp": 0})")}; BEAST_EXPECT(result[jss::result][jss::error] == "unknownCmd"); - BEAST_EXPECT( - result[jss::result][jss::request][jss::command] == "bad_command"); + BEAST_EXPECT(result[jss::result][jss::request][jss::command] == "bad_command"); } void @@ -2169,19 +2101,12 @@ public: jt.jv.removeMember(jss::Fee); jt.jv.removeMember(jss::TxnSignature); req[jss::tx_json] = jt.jv; - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(result.size() == 0); BEAST_EXPECT( req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == - env.current()->fees().base.jsonClipped()); + req[jss::tx_json][jss::Fee] == env.current()->fees().base.jsonClipped()); } // test signers max size @@ -2240,19 +2165,12 @@ public: alice)); req[jss::tx_json] = jt.jv; - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(result.size() == 0); BEAST_EXPECT( req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == - env.current()->fees().base.jsonClipped()); + req[jss::tx_json][jss::Fee] == env.current()->fees().base.jsonClipped()); } } @@ -2261,28 +2179,18 @@ public: { testcase("autofill fees"); test::jtx::Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); auto ledger = env.current(); auto const& feeTrack = env.app().getFeeTrack(); { Json::Value req; - Json::Reader().parse( - "{ \"fee_mult_max\" : 1, \"tx_json\" : { } } ", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + Json::Reader().parse("{ \"fee_mult_max\" : 1, \"tx_json\" : { } } ", req); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == baseFee); + BEAST_EXPECT(req[jss::tx_json].isMember(jss::Fee) && req[jss::tx_json][jss::Fee] == baseFee); } { @@ -2291,33 +2199,18 @@ public: "{ \"fee_mult_max\" : 3, \"fee_div_max\" : 2, " "\"tx_json\" : { } } ", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == baseFee); + BEAST_EXPECT(req[jss::tx_json].isMember(jss::Fee) && req[jss::tx_json][jss::Fee] == baseFee); } { Json::Value req; - Json::Reader().parse( - "{ \"fee_mult_max\" : 0, \"tx_json\" : { } } ", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + Json::Reader().parse("{ \"fee_mult_max\" : 0, \"tx_json\" : { } } ", req); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee)); @@ -2331,14 +2224,8 @@ public: "{ \"fee_mult_max\" : 3, \"fee_div_max\" : 6, " "\"tx_json\" : { } } ", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee)); @@ -2350,14 +2237,8 @@ public: "{ \"fee_mult_max\" : 0, \"fee_div_max\" : 2, " "\"tx_json\" : { } } ", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee)); @@ -2369,14 +2250,8 @@ public: "{ \"fee_mult_max\" : 10, \"fee_div_max\" : 0, " "\"tx_json\" : { } } ", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee)); @@ -2386,22 +2261,14 @@ public: // transaction with a higher base fee Json::Value req; test::jtx::Account const alice("alice"); - req[jss::tx_json] = - test::jtx::acctdelete(env.master.human(), alice.human()); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrack, - env.app().getTxQ(), - env.app()); + req[jss::tx_json] = test::jtx::acctdelete(env.master.human(), alice.human()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrack, env.app().getTxQ(), env.app()); BEAST_EXPECT(result.size() == 0); BEAST_EXPECT( req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == - env.current()->fees().increment.jsonClipped()); + req[jss::tx_json][jss::Fee] == env.current()->fees().increment.jsonClipped()); } } @@ -2412,8 +2279,7 @@ public: using namespace test::jtx; Env env{*this, envconfig([](std::unique_ptr cfg) { cfg->loadFromString("[" SECTION_SIGNING_SUPPORT "]\ntrue"); - cfg->section("transaction_queue") - .set("minimum_txn_in_ledger_standalone", "3"); + cfg->section("transaction_queue").set("minimum_txn_in_ledger_standalone", "3"); return cfg; })}; LoadFeeTrack const& feeTrackOuter = env.app().getFeeTrack(); @@ -2427,19 +2293,11 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == 10); + BEAST_EXPECT(req[jss::tx_json].isMember(jss::Fee) && req[jss::tx_json][jss::Fee] == 10); } { @@ -2451,19 +2309,11 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == 10); + BEAST_EXPECT(req[jss::tx_json].isMember(jss::Fee) && req[jss::tx_json][jss::Fee] == 10); } // put 4 transactions into the open ledger @@ -2481,19 +2331,11 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == 8889); + BEAST_EXPECT(req[jss::tx_json].isMember(jss::Fee) && req[jss::tx_json][jss::Fee] == 8889); } { @@ -2505,14 +2347,8 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee)); @@ -2528,14 +2364,8 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); BEAST_EXPECT(!req[jss::tx_json].isMember(jss::Fee)); @@ -2551,19 +2381,11 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - req[jss::tx_json].isMember(jss::Fee) && - req[jss::tx_json][jss::Fee] == 8889); + BEAST_EXPECT(req[jss::tx_json].isMember(jss::Fee) && req[jss::tx_json][jss::Fee] == 8889); } { @@ -2575,14 +2397,8 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); } @@ -2596,14 +2412,8 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); } @@ -2618,14 +2428,8 @@ public: "tx_json" : { } })", req); - Json::Value result = checkFee( - req, - Role::ADMIN, - true, - env.app().config(), - feeTrackOuter, - env.app().getTxQ(), - env.app()); + Json::Value result = + checkFee(req, Role::ADMIN, true, env.app().config(), feeTrackOuter, env.app().getTxQ(), env.app()); BEAST_EXPECT(RPC::contains_error(result)); } @@ -2641,13 +2445,10 @@ public: auto result = rpcResult[jss::result]; BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - result[jss::tx_json].isMember(jss::Fee) && - result[jss::tx_json][jss::Fee] == "10"); + BEAST_EXPECT(result[jss::tx_json].isMember(jss::Fee) && result[jss::tx_json][jss::Fee] == "10"); BEAST_EXPECT( result[jss::tx_json].isMember(jss::Sequence) && - result[jss::tx_json][jss::Sequence].isConvertibleTo( - Json::ValueType::uintValue)); + result[jss::tx_json][jss::Sequence].isConvertibleTo(Json::ValueType::uintValue)); } { @@ -2669,13 +2470,10 @@ public: auto result = rpcResult[jss::result]; BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - result[jss::tx_json].isMember(jss::Fee) && - result[jss::tx_json][jss::Fee] == "7813"); + BEAST_EXPECT(result[jss::tx_json].isMember(jss::Fee) && result[jss::tx_json][jss::Fee] == "7813"); BEAST_EXPECT( result[jss::tx_json].isMember(jss::Sequence) && - result[jss::tx_json][jss::Sequence].isConvertibleTo( - Json::ValueType::uintValue)); + result[jss::tx_json][jss::Sequence].isConvertibleTo(Json::ValueType::uintValue)); env.close(); } @@ -2697,13 +2495,10 @@ public: auto result = rpcResult[jss::result]; BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - result[jss::tx_json].isMember(jss::Fee) && - result[jss::tx_json][jss::Fee] == "47"); + BEAST_EXPECT(result[jss::tx_json].isMember(jss::Fee) && result[jss::tx_json][jss::Fee] == "47"); BEAST_EXPECT( result[jss::tx_json].isMember(jss::Sequence) && - result[jss::tx_json][jss::Sequence].isConvertibleTo( - Json::ValueType::uintValue)); + result[jss::tx_json][jss::Sequence].isConvertibleTo(Json::ValueType::uintValue)); } { @@ -2730,13 +2525,10 @@ public: auto result = rpcResult[jss::result]; BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - result[jss::tx_json].isMember(jss::Fee) && - result[jss::tx_json][jss::Fee] == "6806"); + BEAST_EXPECT(result[jss::tx_json].isMember(jss::Fee) && result[jss::tx_json][jss::Fee] == "6806"); BEAST_EXPECT( result[jss::tx_json].isMember(jss::Sequence) && - result[jss::tx_json][jss::Sequence].isConvertibleTo( - Json::ValueType::uintValue)); + result[jss::tx_json][jss::Sequence].isConvertibleTo(Json::ValueType::uintValue)); } } @@ -2760,19 +2552,13 @@ public: auto result = rpcResult[jss::result]; BEAST_EXPECT(!RPC::contains_error(result)); - BEAST_EXPECT( - result[jss::tx_json].isMember(jss::NetworkID) && - result[jss::tx_json][jss::NetworkID] == 1025); + BEAST_EXPECT(result[jss::tx_json].isMember(jss::NetworkID) && result[jss::tx_json][jss::NetworkID] == 1025); } } // A function that can be called as though it would process a transaction. static void - fakeProcessTransaction( - std::shared_ptr&, - bool, - bool, - NetworkOPs::FailHard) + fakeProcessTransaction(std::shared_ptr&, bool, bool, NetworkOPs::FailHard) { ; } @@ -2828,18 +2614,13 @@ public: Application& app, ProcessTransactionFn const& processTransaction); - using TestStuff = - std::tuple; + using TestStuff = std::tuple; static TestStuff const testFuncs[] = { TestStuff{transactionSign, nullptr, "sign", 0}, TestStuff{nullptr, transactionSubmit, "submit", 1}, TestStuff{transactionSignFor, nullptr, "sign_for", 2}, - TestStuff{ - nullptr, - transactionSubmitMultiSigned, - "submit_multisigned", - 3}}; + TestStuff{nullptr, transactionSubmitMultiSigned, "submit_multisigned", 3}}; for (auto testFunc : testFuncs) { @@ -2849,11 +2630,9 @@ public: Json::Value req; Json::Reader().parse(txnTest.json, req); if (RPC::contains_error(req)) - Throw( - "Internal JSONRPC_test error. Bad test JSON."); + Throw("Internal JSONRPC_test error. Bad test JSON."); - static Role const testedRoles[] = { - Role::GUEST, Role::USER, Role::ADMIN, Role::FORBID}; + static Role const testedRoles[] = {Role::GUEST, Role::USER, Role::ADMIN, Role::FORBID}; for (Role testRole : testedRoles) { @@ -2862,26 +2641,13 @@ public: if (signFn != nullptr) { assert(get<1>(testFunc) == nullptr); - result = signFn( - req, - 1, - NetworkOPs::FailHard::yes, - testRole, - 1s, - env.app()); + result = signFn(req, 1, NetworkOPs::FailHard::yes, testRole, 1s, env.app()); } else { auto const submitFn = get<1>(testFunc); assert(submitFn != nullptr); - result = submitFn( - req, - 1, - NetworkOPs::FailHard::yes, - testRole, - 1s, - env.app(), - processTxn); + result = submitFn(req, 1, NetworkOPs::FailHard::yes, testRole, 1s, env.app(), processTxn); } std::string errStr; @@ -2895,9 +2661,8 @@ public: else { std::ostringstream description; - description << txnTest.description << " Called " - << get<2>(testFunc) << "(). Got \'" - << errStr << "\'"; + description << txnTest.description << " Called " << get<2>(testFunc) << "(). Got \'" << errStr + << "\'"; fail(description.str(), __FILE__, txnTest.line); } } diff --git a/src/test/rpc/KeyGeneration_test.cpp b/src/test/rpc/KeyGeneration_test.cpp index 23f2723d6a..987985070d 100644 --- a/src/test/rpc/KeyGeneration_test.cpp +++ b/src/test/rpc/KeyGeneration_test.cpp @@ -27,8 +27,7 @@ struct key_strings namespace common { static char const* passphrase = "REINDEER FLOTILLA"; -static char const* master_key = - "SCAT BERN ISLE FOR ROIL BUS SOAK AQUA FREE FOR DRAM BRIG"; +static char const* master_key = "SCAT BERN ISLE FOR ROIL BUS SOAK AQUA FREE FOR DRAM BRIG"; static char const* master_seed = "snMwVWs2hZzfDUF3p2tHZ3EgmyhFs"; static char const* master_seed_hex = "BE6A670A19B209E112146D0A7ED2AAD7"; } // namespace common @@ -94,10 +93,7 @@ public: BEAST_EXPECT(result.isMember(jss::public_key_hex)); BEAST_EXPECT(result.isMember(jss::key_type)); - expectEquals( - result[jss::key_type], - params.isMember(jss::key_type) ? params[jss::key_type] - : "secp256k1"); + expectEquals(result[jss::key_type], params.isMember(jss::key_type) ? params[jss::key_type] : "secp256k1"); BEAST_EXPECT(!result.isMember(jss::warning)); std::string seed = result[jss::master_seed].asString(); @@ -119,17 +115,12 @@ public: expectEquals(result[jss::master_seed_hex], s.master_seed_hex); expectEquals(result[jss::public_key], s.public_key); expectEquals(result[jss::public_key_hex], s.public_key_hex); - expectEquals( - result[jss::key_type], - params.isMember(jss::key_type) ? params[jss::key_type] - : "secp256k1"); + expectEquals(result[jss::key_type], params.isMember(jss::key_type) ? params[jss::key_type] : "secp256k1"); return result; } void - testSeed( - std::optional const& keyType, - key_strings const& strings) + testSeed(std::optional const& keyType, key_strings const& strings) { testcase("seed"); @@ -143,9 +134,7 @@ public: } void - testSeedHex( - std::optional const& keyType, - key_strings const& strings) + testSeedHex(std::optional const& keyType, key_strings const& strings) { testcase("seed_hex"); @@ -159,10 +148,7 @@ public: } void - testLegacyPassphrase( - char const* value, - std::optional const& keyType, - key_strings const& strings) + testLegacyPassphrase(char const* value, std::optional const& keyType, key_strings const& strings) { Json::Value params; if (keyType) @@ -177,9 +163,7 @@ public: } void - testLegacyPassphrase( - std::optional const& keyType, - key_strings const& strings) + testLegacyPassphrase(std::optional const& keyType, key_strings const& strings) { testcase("passphrase"); @@ -190,9 +174,7 @@ public: } void - testKeyType( - std::optional const& keyType, - key_strings const& strings) + testKeyType(std::optional const& keyType, key_strings const& strings) { testcase(keyType ? *keyType : "no key_type"); @@ -223,9 +205,7 @@ public: params[jss::passphrase] = 20160506; auto result = walletPropose(params); BEAST_EXPECT(contains_error(result)); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'passphrase', not string."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'passphrase', not string."); } { @@ -234,9 +214,7 @@ public: params[jss::seed] = Json::objectValue; auto result = walletPropose(params); BEAST_EXPECT(contains_error(result)); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'seed', not string."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'seed', not string."); } { @@ -245,9 +223,7 @@ public: params[jss::seed_hex] = Json::arrayValue; auto result = walletPropose(params); BEAST_EXPECT(contains_error(result)); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'seed_hex', not string."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'seed_hex', not string."); } // Specifying multiple items at once @@ -281,9 +257,7 @@ public: params[jss::seed_hex] = common::master_seed_hex; auto result = walletPropose(params); BEAST_EXPECT(contains_error(result)); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'key_type', not string."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'key_type', not string."); } { @@ -292,22 +266,16 @@ public: params[jss::seed] = common::master_seed; auto result = walletPropose(params); BEAST_EXPECT(contains_error(result)); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'key_type', not string."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'key_type', not string."); } } void - testKeypairForSignature( - std::optional keyType, - key_strings const& strings) + testKeypairForSignature(std::optional keyType, key_strings const& strings) { - testcase( - "keypairForSignature - " + (keyType ? *keyType : "no key_type")); + testcase("keypairForSignature - " + (keyType ? *keyType : "no key_type")); - auto const publicKey = parseBase58( - TokenType::AccountPublic, strings.public_key); + auto const publicKey = parseBase58(TokenType::AccountPublic, strings.public_key); BEAST_EXPECT(publicKey); if (!keyType) @@ -417,9 +385,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'secret', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'secret', not string."); } { @@ -431,9 +397,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'secret', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'secret', not string."); } { @@ -446,9 +410,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'secret', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'secret', not string."); } // Specify "secret" and "key_type" @@ -461,9 +423,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "The secret field is not allowed if key_type is used."); + BEAST_EXPECT(error[jss::error_message] == "The secret field is not allowed if key_type is used."); } // Specify unknown or bad "key_type" @@ -476,8 +436,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == "Invalid field 'key_type'."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'key_type'."); } { @@ -489,9 +448,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'key_type', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'key_type', not string."); } { @@ -503,9 +460,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'key_type', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'key_type', not string."); } // Specify non-string passphrase @@ -518,9 +473,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'passphrase', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'passphrase', not string."); } { // not a passphrase: object @@ -532,9 +485,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'passphrase', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'passphrase', not string."); } { // not a passphrase: array @@ -546,9 +497,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'passphrase', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'passphrase', not string."); } { // not a passphrase: empty string @@ -573,9 +522,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'seed', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'seed', not string."); } { // not a string: object @@ -587,9 +534,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'seed', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'seed', not string."); } { // not a string: array @@ -601,9 +546,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'seed', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'seed', not string."); } { // not a seed: empty @@ -652,9 +595,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'seed_hex', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'seed_hex', not string."); } { // not a string: object @@ -666,9 +607,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'seed_hex', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'seed_hex', not string."); } { // not a string: array @@ -680,9 +619,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); BEAST_EXPECT(!ret); - BEAST_EXPECT( - error[jss::error_message] == - "Invalid field 'seed_hex', not string."); + BEAST_EXPECT(error[jss::error_message] == "Invalid field 'seed_hex', not string."); } { // empty @@ -725,8 +662,7 @@ public: Json::Value params; Json::Value error; params[jss::key_type] = "secp256k1"; - params[jss::seed_hex] = - "BE6A670A19B209E112146D0A7ED2AAD72567D0FC913"; + params[jss::seed_hex] = "BE6A670A19B209E112146D0A7ED2AAD72567D0FC913"; auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); @@ -767,9 +703,7 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); - BEAST_EXPECT( - error[jss::error_message] == - "Specified seed is for an Ed25519 wallet."); + BEAST_EXPECT(error[jss::error_message] == "Specified seed is for an Ed25519 wallet."); } { @@ -799,60 +733,26 @@ public: auto ret = keypairForSignature(params, error); BEAST_EXPECT(contains_error(error)); - BEAST_EXPECT( - error[jss::error_message] == - "Specified seed is for an Ed25519 wallet."); + BEAST_EXPECT(error[jss::error_message] == "Specified seed is for an Ed25519 wallet."); } }; - test( - "sEdVWZmeUDgQdMEFKTK9kYVX71FKB7o", - "r34XnDB2zS11NZ1wKJzpU1mjWExGVugTaQ"); - test( - "sEd7zJoVnqg1FxB9EuaHC1AB5UPfHWz", - "rDw51qRrBEeMw7Na1Nh79LN7HYZDo7nZFE"); - test( - "sEdSxVntbihdLyabbfttMCqsaaucVR9", - "rwiyBDfAYegXZyaQcN2L1vAbKRYn2wNFMq"); - test( - "sEdSVwJjEXTYCztqDK4JD9WByH3otDX", - "rQJ4hZzNGkLQhLtKPCmu1ywEw1ai2vgUJN"); - test( - "sEdV3jXjKuUoQTSr1Rb4yw8Kyn9r46U", - "rERRw2Pxbau4tevE61V5vZUwD7Rus5Y6vW"); - test( - "sEdVeUZjuYT47Uy51FQCnzivsuWyiwB", - "rszewT5gRjUgWNEmnfMjvVYzJCkhvWY32i"); - test( - "sEd7MHTewdw4tFYeS7rk7XT4qHiA9jH", - "rBB2rvnf4ztwjgNhinFXQJ91nAZjkFgR3p"); - test( - "sEd7A5jFBSdWbNeKGriQvLr1thBScJh", - "rLAXz8Nz7aDivz7PwThsLFqaKrizepNCdA"); - test( - "sEdVPU9M2uyzVNT4Yb5Dn4tUtYjbFAw", - "rHbHRFPCxD5fnn98TBzsQHJ7SsRq7eHkRj"); - test( - "sEdVfF2zhAmS8gfMYzJ4yWBMeR4BZKc", - "r9PsneKHcAE7kUfiTixomM5Mnwi28tCc7h"); - test( - "sEdTjRtcsQkwthDXUSLi9DHNyJcR8GW", - "rM4soF4XS3wZrmLurvE6ZmudG16Lk5Dur5"); - test( - "sEdVNKeu1Lhpfh7Nf6tRDbxnmMyZ4Dv", - "r4ZwJxq6FDtWjapDtCGhjG6mtNm1nWdJcD"); - test( - "sEd7bK4gf5BHJ1WbaEWx8pKMA9MLHpC", - "rD6tnn51m4o1uXeEK9CFrZ3HR7DcFhiYnp"); - test( - "sEd7jCh3ppnQMsLdGcZ6TZayZaHhBLg", - "rTcBkiRQ1EfFQ4FCCwqXNHpn1yUTAACkj"); - test( - "sEdTFJezurQwSJAbkLygj2gQXBut2wh", - "rnXaMacNbRwcJddbbPbqdcpSUQcfzFmrR8"); - test( - "sEdSWajfQAAWFuDvVZF3AiGucReByLt", - "rBJtow6V3GTdsWMamrxetRDwWs6wwTxcKa"); + test("sEdVWZmeUDgQdMEFKTK9kYVX71FKB7o", "r34XnDB2zS11NZ1wKJzpU1mjWExGVugTaQ"); + test("sEd7zJoVnqg1FxB9EuaHC1AB5UPfHWz", "rDw51qRrBEeMw7Na1Nh79LN7HYZDo7nZFE"); + test("sEdSxVntbihdLyabbfttMCqsaaucVR9", "rwiyBDfAYegXZyaQcN2L1vAbKRYn2wNFMq"); + test("sEdSVwJjEXTYCztqDK4JD9WByH3otDX", "rQJ4hZzNGkLQhLtKPCmu1ywEw1ai2vgUJN"); + test("sEdV3jXjKuUoQTSr1Rb4yw8Kyn9r46U", "rERRw2Pxbau4tevE61V5vZUwD7Rus5Y6vW"); + test("sEdVeUZjuYT47Uy51FQCnzivsuWyiwB", "rszewT5gRjUgWNEmnfMjvVYzJCkhvWY32i"); + test("sEd7MHTewdw4tFYeS7rk7XT4qHiA9jH", "rBB2rvnf4ztwjgNhinFXQJ91nAZjkFgR3p"); + test("sEd7A5jFBSdWbNeKGriQvLr1thBScJh", "rLAXz8Nz7aDivz7PwThsLFqaKrizepNCdA"); + test("sEdVPU9M2uyzVNT4Yb5Dn4tUtYjbFAw", "rHbHRFPCxD5fnn98TBzsQHJ7SsRq7eHkRj"); + test("sEdVfF2zhAmS8gfMYzJ4yWBMeR4BZKc", "r9PsneKHcAE7kUfiTixomM5Mnwi28tCc7h"); + test("sEdTjRtcsQkwthDXUSLi9DHNyJcR8GW", "rM4soF4XS3wZrmLurvE6ZmudG16Lk5Dur5"); + test("sEdVNKeu1Lhpfh7Nf6tRDbxnmMyZ4Dv", "r4ZwJxq6FDtWjapDtCGhjG6mtNm1nWdJcD"); + test("sEd7bK4gf5BHJ1WbaEWx8pKMA9MLHpC", "rD6tnn51m4o1uXeEK9CFrZ3HR7DcFhiYnp"); + test("sEd7jCh3ppnQMsLdGcZ6TZayZaHhBLg", "rTcBkiRQ1EfFQ4FCCwqXNHpn1yUTAACkj"); + test("sEdTFJezurQwSJAbkLygj2gQXBut2wh", "rnXaMacNbRwcJddbbPbqdcpSUQcfzFmrR8"); + test("sEdSWajfQAAWFuDvVZF3AiGucReByLt", "rBJtow6V3GTdsWMamrxetRDwWs6wwTxcKa"); } void diff --git a/src/test/rpc/LedgerClosed_test.cpp b/src/test/rpc/LedgerClosed_test.cpp index 2bc5c2b0c9..d6b67ce406 100644 --- a/src/test/rpc/LedgerClosed_test.cpp +++ b/src/test/rpc/LedgerClosed_test.cpp @@ -21,9 +21,7 @@ public: env.fund(XRP(10000), alice); auto lc_result = env.rpc("ledger_closed")[jss::result]; - BEAST_EXPECT( - lc_result[jss::ledger_hash] == - "CCC3B3E88CCAC17F1BE6B4A648A55999411F19E3FE55EB721960EB0DF28EDDA5"); + BEAST_EXPECT(lc_result[jss::ledger_hash] == "CCC3B3E88CCAC17F1BE6B4A648A55999411F19E3FE55EB721960EB0DF28EDDA5"); BEAST_EXPECT(lc_result[jss::ledger_index] == 2); env.close(); @@ -36,9 +34,7 @@ public: BEAST_EXPECT((*ar_alice)[sfBalance] == XRP(10000)); lc_result = env.rpc("ledger_closed")[jss::result]; - BEAST_EXPECT( - lc_result[jss::ledger_hash] == - "0F1A9E0C109ADEF6DA2BDE19217C12BBEC57174CBDBD212B0EBDC1CEDB853185"); + BEAST_EXPECT(lc_result[jss::ledger_hash] == "0F1A9E0C109ADEF6DA2BDE19217C12BBEC57174CBDBD212B0EBDC1CEDB853185"); BEAST_EXPECT(lc_result[jss::ledger_index] == 3); } diff --git a/src/test/rpc/LedgerData_test.cpp b/src/test/rpc/LedgerData_test.cpp index 66be8486b4..0148185276 100644 --- a/src/test/rpc/LedgerData_test.cpp +++ b/src/test/rpc/LedgerData_test.cpp @@ -12,8 +12,7 @@ public: static bool checkMarker(Json::Value const& val) { - return val.isMember(jss::marker) && val[jss::marker].isString() && - val[jss::marker].asString().size() > 0; + return val.isMember(jss::marker) && val[jss::marker].isString() && val[jss::marker].asString().size() > 0; } void @@ -43,11 +42,8 @@ public: jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; { - auto const jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::ledger_current_index].isIntegral() && - jrr[jss::ledger_current_index].asInt() > 0); + auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].asInt() > 0); BEAST_EXPECT(checkMarker(jrr)); BEAST_EXPECT(checkArraySize(jrr[jss::state], max_limit)); } @@ -56,11 +52,8 @@ public: for (auto delta = -1; delta <= 1; delta++) { jvParams[jss::limit] = max_limit + delta; - auto const jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; - BEAST_EXPECT(checkArraySize( - jrr[jss::state], - (delta > 0 && !asAdmin) ? max_limit : max_limit + delta)); + auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; + BEAST_EXPECT(checkArraySize(jrr[jss::state], (delta > 0 && !asAdmin) ? max_limit : max_limit + delta)); } } @@ -86,11 +79,8 @@ public: Json::Value jvParams; jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = true; - auto const jrr = - env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::ledger_current_index].isIntegral() && - jrr[jss::ledger_current_index].asInt() > 0); + auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::ledger_current_index].isIntegral() && jrr[jss::ledger_current_index].asInt() > 0); BEAST_EXPECT(!jrr.isMember(jss::marker)); BEAST_EXPECT(checkArraySize(jrr[jss::state], num_accounts + 4)); } @@ -111,47 +101,37 @@ public: // bad limit Json::Value jvParams; jvParams[jss::limit] = "0"; // NOT an integer - auto const jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'limit', not integer."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'limit', not integer."); } { // invalid marker Json::Value jvParams; jvParams[jss::marker] = "NOT_A_MARKER"; - auto const jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'marker', not valid."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not valid."); } { // invalid marker - not a string Json::Value jvParams; jvParams[jss::marker] = 1; - auto const jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); BEAST_EXPECT(jrr[jss::status] == "error"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'marker', not valid."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'marker', not valid."); } { // ask for a bad ledger index Json::Value jvParams; jvParams[jss::ledger_index] = 10u; - auto const jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "lgrNotFound"); BEAST_EXPECT(jrr[jss::status] == "error"); BEAST_EXPECT(jrr[jss::error_message] == "ledgerNotFound"); @@ -180,8 +160,7 @@ public: Json::Value jvParams; jvParams[jss::ledger_index] = "current"; jvParams[jss::binary] = false; - auto jrr = - env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; + auto jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; auto const total_count = jrr[jss::state].size(); // now make request with a limit and loop until we get all @@ -192,8 +171,7 @@ public: while (jrr.isMember(jss::marker)) { jvParams[jss::marker] = jrr[jss::marker]; - jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; running_total += jrr[jss::state].size(); } BEAST_EXPECT(running_total == total_count); @@ -212,24 +190,19 @@ public: // Closed ledger with non binary form Json::Value jvParams; jvParams[jss::ledger_index] = "closed"; - auto jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + auto jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; if (BEAST_EXPECT(jrr.isMember(jss::ledger))) - BEAST_EXPECT( - jrr[jss::ledger][jss::ledger_hash] == - to_string(env.closed()->header().hash)); + BEAST_EXPECT(jrr[jss::ledger][jss::ledger_hash] == to_string(env.closed()->header().hash)); } { // Closed ledger with binary form Json::Value jvParams; jvParams[jss::ledger_index] = "closed"; jvParams[jss::binary] = true; - auto jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + auto jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; if (BEAST_EXPECT(jrr.isMember(jss::ledger))) { - auto data = - strUnHex(jrr[jss::ledger][jss::ledger_data].asString()); + auto data = strUnHex(jrr[jss::ledger][jss::ledger_data].asString()); if (BEAST_EXPECT(data)) { Serializer s(data->data(), data->size()); @@ -243,8 +216,7 @@ public: // Current ledger with binary form Json::Value jvParams; jvParams[jss::binary] = true; - auto jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + auto jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(!jrr[jss::ledger].isMember(jss::ledger_data)); } @@ -258,8 +230,7 @@ public: // Make sure fixInnerObjTemplate2 doesn't break amendments. for (FeatureBitset const& features : - {testable_amendments() - fixInnerObjTemplate2, - testable_amendments() | fixInnerObjTemplate2}) + {testable_amendments() - fixInnerObjTemplate2, testable_amendments() | fixInnerObjTemplate2}) { using namespace std::chrono; Env env{*this, envconfig(validator, ""), features}; @@ -272,8 +243,7 @@ public: Json::Value jvParams; jvParams[jss::ledger_index] = "current"; jvParams[jss::type] = type; - return env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + return env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; }; // Assert that state is an empty array. @@ -312,10 +282,7 @@ public: break; } - env(signers( - Account{"bob0"}, - 1, - {{Account{"bob1"}, 1}, {Account{"bob2"}, 1}})); + env(signers(Account{"bob0"}, 1, {{Account{"bob1"}, 1}, {Account{"bob2"}, 1}})); env(ticket::create(env.master, 1)); { @@ -324,10 +291,7 @@ public: jv[jss::Account] = Account{"bob5"}.human(); jv[jss::Destination] = Account{"bob6"}.human(); jv[jss::Amount] = XRP(50).value().getJson(JsonOptions::none); - jv[sfFinishAfter.fieldName] = - NetClock::time_point{env.now() + 10s} - .time_since_epoch() - .count(); + jv[sfFinishAfter.fieldName] = NetClock::time_point{env.now() + 10s}.time_since_epoch().count(); env(jv); } @@ -338,12 +302,8 @@ public: jv[jss::Destination] = Account{"bob7"}.human(); jv[jss::Amount] = XRP(100).value().getJson(JsonOptions::none); jv[jss::SettleDelay] = NetClock::duration{10s}.count(); - jv[sfPublicKey.fieldName] = - strHex(Account{"bob6"}.pk().slice()); - jv[sfCancelAfter.fieldName] = - NetClock::time_point{env.now() + 300s} - .time_since_epoch() - .count(); + jv[sfPublicKey.fieldName] = strHex(Account{"bob6"}.pk().slice()); + jv[sfCancelAfter.fieldName] = NetClock::time_point{env.now() + 300s}.time_since_epoch().count(); env(jv); } @@ -451,8 +411,7 @@ public: Json::Value jvParams; jvParams[jss::ledger_index] = "current"; jvParams[jss::type] = "misspelling"; - auto const jrr = env.rpc( - "json", "ledger_data", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger_data", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember("error")); BEAST_EXPECT(jrr["error"] == "invalidParams"); BEAST_EXPECT(jrr["error_message"] == "Invalid field 'type'."); diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index cc6d958a2d..a7ae547272 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -55,17 +55,14 @@ std::vector> mappings{ FieldType getFieldType(Json::StaticString fieldName) { - auto it = std::ranges::find_if(mappings, [&fieldName](auto const& pair) { - return pair.first == fieldName; - }); + auto it = std::ranges::find_if(mappings, [&fieldName](auto const& pair) { return pair.first == fieldName; }); if (it != mappings.end()) { return it->second; } else { - Throw( - "`mappings` is missing field " + std::string(fieldName.c_str())); + Throw("`mappings` is missing field " + std::string(fieldName.c_str())); } } @@ -96,8 +93,7 @@ getTypeName(FieldType typeID) case FieldType::UInt64Field: return "number"; default: - Throw( - "unknown type " + std::to_string(static_cast(typeID))); + Throw("unknown type " + std::to_string(static_cast(typeID))); } } @@ -111,32 +107,24 @@ class LedgerEntry_test : public beast::unit_test::suite std::source_location const location = std::source_location::current()) { if (BEAST_EXPECT(jv.isMember(jss::status))) - BEAST_EXPECTS( - jv[jss::status] == "error", std::to_string(location.line())); + BEAST_EXPECTS(jv[jss::status] == "error", std::to_string(location.line())); if (BEAST_EXPECT(jv.isMember(jss::error))) BEAST_EXPECTS( jv[jss::error] == err, - "Expected error " + err + ", received " + - jv[jss::error].asString() + ", at line " + - std::to_string(location.line()) + ", " + - jv.toStyledString()); + "Expected error " + err + ", received " + jv[jss::error].asString() + ", at line " + + std::to_string(location.line()) + ", " + jv.toStyledString()); if (msg.empty()) { BEAST_EXPECTS( - jv[jss::error_message] == Json::nullValue || - jv[jss::error_message] == "", - "Expected no error message, received \"" + - jv[jss::error_message].asString() + "\", at line " + - std::to_string(location.line()) + ", " + - jv.toStyledString()); + jv[jss::error_message] == Json::nullValue || jv[jss::error_message] == "", + "Expected no error message, received \"" + jv[jss::error_message].asString() + "\", at line " + + std::to_string(location.line()) + ", " + jv.toStyledString()); } else if (BEAST_EXPECT(jv.isMember(jss::error_message))) BEAST_EXPECTS( jv[jss::error_message] == msg, - "Expected error message \"" + msg + "\", received \"" + - jv[jss::error_message].asString() + "\", at line " + - std::to_string(location.line()) + ", " + - jv.toStyledString()); + "Expected error message \"" + msg + "\", received \"" + jv[jss::error_message].asString() + + "\", at line " + std::to_string(location.line()) + ", " + jv.toStyledString()); } std::vector @@ -179,10 +167,8 @@ class LedgerEntry_test : public beast::unit_test::suite injectArray // 20 }; - auto remove = - [&](std::vector indices) -> std::vector { - std::unordered_set indexSet( - indices.begin(), indices.end()); + auto remove = [&](std::vector indices) -> std::vector { + std::unordered_set indexSet(indices.begin(), indices.end()); std::vector values; values.reserve(allBadValues.size() - indexSet.size()); for (std::size_t i = 0; i < allBadValues.size(); ++i) @@ -230,9 +216,7 @@ class LedgerEntry_test : public beast::unit_test::suite case FieldType::UInt64Field: return badUInt64Values; default: - Throw( - "unknown type " + - std::to_string(static_cast(fieldType))); + Throw("unknown type " + std::to_string(static_cast(fieldType))); } } @@ -277,9 +261,7 @@ class LedgerEntry_test : public beast::unit_test::suite case FieldType::UInt64Field: return 1; default: - Throw( - "unknown type " + - std::to_string(static_cast(typeID))); + Throw("unknown type " + std::to_string(static_cast(typeID))); } } @@ -297,29 +279,18 @@ class LedgerEntry_test : public beast::unit_test::suite if (required) { correctRequest.removeMember(fieldName); - Json::Value const jrr = env.rpc( - apiVersion, - "json", - "ledger_entry", - to_string(correctRequest))[jss::result]; + Json::Value const jrr = + env.rpc(apiVersion, "json", "ledger_entry", to_string(correctRequest))[jss::result]; if (apiVersion < 2u) checkErrorValue(jrr, "unknownOption", "", location); else - checkErrorValue( - jrr, - "invalidParams", - "No ledger_entry params provided.", - location); + checkErrorValue(jrr, "invalidParams", "No ledger_entry params provided.", location); } auto tryField = [&](Json::Value fieldValue) -> void { correctRequest[fieldName] = fieldValue; - Json::Value const jrr = env.rpc( - apiVersion, - "json", - "ledger_entry", - to_string(correctRequest))[jss::result]; - auto const expectedErrMsg = - RPC::expected_field_message(fieldName, getTypeName(typeID)); + Json::Value const jrr = + env.rpc(apiVersion, "json", "ledger_entry", to_string(correctRequest))[jss::result]; + auto const expectedErrMsg = RPC::expected_field_message(fieldName, getTypeName(typeID)); checkErrorValue(jrr, expectedError, expectedErrMsg, location); }; @@ -350,42 +321,22 @@ class LedgerEntry_test : public beast::unit_test::suite if (required) { correctRequest[parentFieldName].removeMember(fieldName); - Json::Value const jrr = env.rpc( - apiVersion, - "json", - "ledger_entry", - to_string(correctRequest))[jss::result]; - checkErrorValue( - jrr, - "malformedRequest", - RPC::missing_field_message(fieldName.c_str()), - location); + Json::Value const jrr = + env.rpc(apiVersion, "json", "ledger_entry", to_string(correctRequest))[jss::result]; + checkErrorValue(jrr, "malformedRequest", RPC::missing_field_message(fieldName.c_str()), location); correctRequest[parentFieldName][fieldName] = Json::nullValue; - Json::Value const jrr2 = env.rpc( - apiVersion, - "json", - "ledger_entry", - to_string(correctRequest))[jss::result]; - checkErrorValue( - jrr2, - "malformedRequest", - RPC::missing_field_message(fieldName.c_str()), - location); + Json::Value const jrr2 = + env.rpc(apiVersion, "json", "ledger_entry", to_string(correctRequest))[jss::result]; + checkErrorValue(jrr2, "malformedRequest", RPC::missing_field_message(fieldName.c_str()), location); } auto tryField = [&](Json::Value fieldValue) -> void { correctRequest[parentFieldName][fieldName] = fieldValue; - Json::Value const jrr = env.rpc( - apiVersion, - "json", - "ledger_entry", - to_string(correctRequest))[jss::result]; + Json::Value const jrr = + env.rpc(apiVersion, "json", "ledger_entry", to_string(correctRequest))[jss::result]; checkErrorValue( - jrr, - expectedError, - RPC::expected_field_message(fieldName, getTypeName(typeID)), - location); + jrr, expectedError, RPC::expected_field_message(fieldName, getTypeName(typeID)), location); }; auto const& badValues = getBadValues(typeID); @@ -403,14 +354,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::StaticString const& parentField, std::source_location const location = std::source_location::current()) { - testMalformedField( - env, - Json::Value{}, - parentField, - FieldType::HashField, - "malformedRequest", - true, - location); + testMalformedField(env, Json::Value{}, parentField, FieldType::HashField, "malformedRequest", true, location); } struct Subfield @@ -428,20 +372,13 @@ class LedgerEntry_test : public beast::unit_test::suite std::source_location const location = std::source_location::current()) { testMalformedField( - env, - Json::Value{}, - parentField, - FieldType::HashOrObjectField, - "malformedRequest", - true, - location); + env, Json::Value{}, parentField, FieldType::HashOrObjectField, "malformedRequest", true, location); Json::Value correctOutput; correctOutput[parentField] = Json::objectValue; for (auto const& subfield : subfields) { - correctOutput[parentField][subfield.fieldName] = - getCorrectValue(subfield.fieldName); + correctOutput[parentField][subfield.fieldName] = getCorrectValue(subfield.fieldName); } for (auto const& subfield : subfields) @@ -475,8 +412,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::ledger_hash] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "AA"; - auto const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "lgrNotFound", "ledgerNotFound"); } { @@ -488,15 +424,9 @@ class LedgerEntry_test : public beast::unit_test::suite forAllApiVersions([&, this](unsigned apiVersion) { auto tryField = [&](Json::Value fieldValue) -> void { jvParams[jss::ledger_hash] = fieldValue; - Json::Value const jrr = env.rpc( - apiVersion, - "json", - "ledger_entry", - to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, - "invalidParams", - "Invalid field 'ledger_hash', not hex string."); + Json::Value const jrr = + env.rpc(apiVersion, "json", "ledger_entry", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "invalidParams", "Invalid field 'ledger_hash', not hex string."); }; auto const& badValues = getBadValues(typeId); @@ -514,8 +444,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::index] = "00000000000000000000000000000000000000000000000000000000000000" "00"; - auto const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } @@ -527,16 +456,12 @@ class LedgerEntry_test : public beast::unit_test::suite "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAA"; jvParams[jss::api_version] = apiVersion; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; if (apiVersion < 2u) checkErrorValue(jrr, "unknownOption", ""); else - checkErrorValue( - jrr, - "invalidParams", - "No ledger_entry params provided."); + checkErrorValue(jrr, "invalidParams", "No ledger_entry params provided."); } }); } @@ -569,8 +494,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::account_root] = alice.human(); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human()); BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] == "10000000000"); @@ -587,8 +511,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::account_root] = alice.human(); jvParams[jss::binary] = 1; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node_binary)); BEAST_EXPECT(jrr[jss::node_binary] == alicesAcctRootBinary); } @@ -596,8 +519,7 @@ class LedgerEntry_test : public beast::unit_test::suite // Request alice's account root using the index. Json::Value jvParams; jvParams[jss::index] = accountRootIndex; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(!jrr.isMember(jss::node_binary)); BEAST_EXPECT(jrr.isMember(jss::node)); BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human()); @@ -608,8 +530,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::index] = accountRootIndex; jvParams[jss::binary] = 0; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human()); BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] == "10000000000"); @@ -619,8 +540,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::account] = alice.human(); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human()); BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] == "10000000000"); @@ -629,20 +549,14 @@ class LedgerEntry_test : public beast::unit_test::suite { // Check malformed cases Json::Value jvParams; - testMalformedField( - env, - jvParams, - jss::account_root, - FieldType::AccountField, - "malformedAddress"); + testMalformedField(env, jvParams, jss::account_root, FieldType::AccountField, "malformedAddress"); } { // Request an account that is not in the ledger. Json::Value jvParams; jvParams[jss::account_root] = Account("bob").human(); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } } @@ -661,8 +575,7 @@ class LedgerEntry_test : public beast::unit_test::suite // easier to hack an object into the ledger than generate it // legitimately { - auto const amendments = [&](OpenView& view, - beast::Journal) -> bool { + auto const amendments = [&](OpenView& view, beast::Journal) -> bool { auto const sle = std::make_shared(keylet); // Create Amendments vector (enabled amendments) @@ -679,8 +592,7 @@ class LedgerEntry_test : public beast::unit_test::suite enabledAmendments.push_back( uint256::fromVoid("35291ADD2D79EB6991343BDA0912269C817D" "0F094B02226C1C14AD2858962ED4")); - sle->setFieldV256( - sfAmendments, STVector256(enabledAmendments)); + sle->setFieldV256(sfAmendments, STVector256(enabledAmendments)); // Create Majorities array STArray majorities; @@ -711,19 +623,12 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::amendments] = to_string(keylet.key); - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Amendments); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Amendments); } // negative tests - testMalformedField( - env, - Json::Value{}, - jss::amendments, - FieldType::FixedHashField, - "malformedRequest"); + testMalformedField(env, Json::Value{}, jss::amendments, FieldType::FixedHashField, "malformedRequest"); } void @@ -743,16 +648,12 @@ class LedgerEntry_test : public beast::unit_test::suite { Json::Value jvParams; jvParams[jss::amm] = to_string(amm.ammID()); - auto const result = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const result = env.rpc("json", "ledger_entry", to_string(jvParams)); BEAST_EXPECT( - result.isObject() && result.isMember(jss::result) && - !result[jss::result].isMember(jss::error) && + result.isObject() && result.isMember(jss::result) && !result[jss::result].isMember(jss::error) && result[jss::result].isMember(jss::node) && - result[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - result[jss::result][jss::node][sfLedgerEntryType.jsonName] == - jss::AMM); + result[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + result[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::AMM); } { @@ -770,16 +671,12 @@ class LedgerEntry_test : public beast::unit_test::suite ammParams[jss::asset2] = obj; } jvParams[jss::amm] = ammParams; - auto const result = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const result = env.rpc("json", "ledger_entry", to_string(jvParams)); BEAST_EXPECT( - result.isObject() && result.isMember(jss::result) && - !result[jss::result].isMember(jss::error) && + result.isObject() && result.isMember(jss::result) && !result[jss::result].isMember(jss::error) && result[jss::result].isMember(jss::node) && - result[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - result[jss::result][jss::node][sfLedgerEntryType.jsonName] == - jss::AMM); + result[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + result[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::AMM); } // negative tests @@ -813,10 +710,8 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::check] = to_string(checkId.key); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Check); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Check); BEAST_EXPECT(jrr[jss::node][sfSendMax.jsonName] == "100000000"); } { @@ -826,17 +721,14 @@ class LedgerEntry_test : public beast::unit_test::suite { Json::Value jvParams; jvParams[jss::account_root] = alice.human(); - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; accountRootIndex = jrr[jss::index].asString(); } Json::Value jvParams; jvParams[jss::check] = accountRootIndex; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, "unexpectedLedgerType", "Unexpected ledger type."); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "unexpectedLedgerType", "Unexpected ledger type."); } { // Check malformed cases @@ -868,25 +760,19 @@ class LedgerEntry_test : public beast::unit_test::suite // Succeed auto jv = credentials::ledgerEntry(env, alice, issuer, credType); BEAST_EXPECT( - jv.isObject() && jv.isMember(jss::result) && - !jv[jss::result].isMember(jss::error) && + jv.isObject() && jv.isMember(jss::result) && !jv[jss::result].isMember(jss::error) && jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == - jss::Credential); + jv[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::Credential); std::string const credIdx = jv[jss::result][jss::index].asString(); jv = credentials::ledgerEntry(env, credIdx); BEAST_EXPECT( - jv.isObject() && jv.isMember(jss::result) && - !jv[jss::result].isMember(jss::error) && + jv.isObject() && jv.isMember(jss::result) && !jv[jss::result].isMember(jss::error) && jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == - jss::Credential); + jv[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::Credential); } { @@ -895,8 +781,7 @@ class LedgerEntry_test : public beast::unit_test::suite env, "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B" "E4"); - checkErrorValue( - jv[jss::result], "entryNotFound", "Entry not found."); + checkErrorValue(jv[jss::result], "entryNotFound", "Entry not found."); } { @@ -934,10 +819,8 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::delegate][jss::account] = alice.human(); jvParams[jss::delegate][jss::authorize] = bob.human(); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Delegate); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Delegate); BEAST_EXPECT(jrr[jss::node][sfAccount.jsonName] == alice.human()); BEAST_EXPECT(jrr[jss::node][sfAuthorize.jsonName] == bob.human()); delegateIndex = jrr[jss::node][jss::index].asString(); @@ -947,10 +830,8 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::delegate] = delegateIndex; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Delegate); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Delegate); BEAST_EXPECT(jrr[jss::node][sfAccount.jsonName] == alice.human()); BEAST_EXPECT(jrr[jss::node][sfAuthorize.jsonName] == bob.human()); } @@ -992,12 +873,9 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::deposit_preauth][jss::owner] = alice.human(); jvParams[jss::deposit_preauth][jss::authorized] = becky.human(); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == - jss::DepositPreauth); + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::DepositPreauth); BEAST_EXPECT(jrr[jss::node][sfAccount.jsonName] == alice.human()); BEAST_EXPECT(jrr[jss::node][sfAuthorize.jsonName] == becky.human()); depositPreauthIndex = jrr[jss::node][jss::index].asString(); @@ -1007,12 +885,9 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::deposit_preauth] = depositPreauthIndex; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == - jss::DepositPreauth); + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::DepositPreauth); BEAST_EXPECT(jrr[jss::node][sfAccount.jsonName] == alice.human()); BEAST_EXPECT(jrr[jss::node][sfAuthorize.jsonName] == becky.human()); } @@ -1058,26 +933,20 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::deposit_preauth][jss::owner] = bob.human(); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - Json::arrayValue; - auto& arr( - jvParams[jss::deposit_preauth][jss::authorized_credentials]); + jvParams[jss::deposit_preauth][jss::authorized_credentials] = Json::arrayValue; + auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]); Json::Value jo; jo[jss::issuer] = issuer.human(); jo[jss::credential_type] = strHex(std::string_view(credType)); arr.append(std::move(jo)); - auto const jrr = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams)); BEAST_EXPECT( - jrr.isObject() && jrr.isMember(jss::result) && - !jrr[jss::result].isMember(jss::error) && + jrr.isObject() && jrr.isMember(jss::result) && !jrr[jss::result].isMember(jss::error) && jrr[jss::result].isMember(jss::node) && - jrr[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - jrr[jss::result][jss::node][sfLedgerEntryType.jsonName] == - jss::DepositPreauth); + jrr[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + jrr[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::DepositPreauth); } { @@ -1092,16 +961,12 @@ class LedgerEntry_test : public beast::unit_test::suite jo[jss::issuer] = fieldValue; jo[jss::credential_type] = strHex(std::string_view(credType)); arr.append(jo); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - arr; + jvParams[jss::deposit_preauth][jss::authorized_credentials] = arr; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - auto const expectedErrMsg = fieldValue.isNull() - ? RPC::missing_field_message(jss::issuer.c_str()) - : RPC::expected_field_message(jss::issuer, "AccountID"); - checkErrorValue( - jrr, "malformedAuthorizedCredentials", expectedErrMsg); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + auto const expectedErrMsg = fieldValue.isNull() ? RPC::missing_field_message(jss::issuer.c_str()) + : RPC::expected_field_message(jss::issuer, "AccountID"); + checkErrorValue(jrr, "malformedAuthorizedCredentials", expectedErrMsg); }; auto const& badValues = getBadValues(FieldType::AccountField); @@ -1118,23 +983,19 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::ledger_index] = jss::validated; jvParams[jss::deposit_preauth][jss::owner] = bob.human(); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - Json::arrayValue; - auto& arr( - jvParams[jss::deposit_preauth][jss::authorized_credentials]); + jvParams[jss::deposit_preauth][jss::authorized_credentials] = Json::arrayValue; + auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]); Json::Value jo; jo[jss::issuer] = issuer.human(); jo[jss::credential_type] = strHex(std::string_view(credType)); arr.append(jo); arr.append(std::move(jo)); - auto const jrr = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams)); checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", - RPC::expected_field_message( - jss::authorized_credentials, "array")); + RPC::expected_field_message(jss::authorized_credentials, "array")); } { @@ -1149,17 +1010,13 @@ class LedgerEntry_test : public beast::unit_test::suite jo[jss::issuer] = issuer.human(); jo[jss::credential_type] = fieldValue; arr.append(jo); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - arr; + jvParams[jss::deposit_preauth][jss::authorized_credentials] = arr; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; auto const expectedErrMsg = fieldValue.isNull() ? RPC::missing_field_message(jss::credential_type.c_str()) - : RPC::expected_field_message( - jss::credential_type, "hex string"); - checkErrorValue( - jrr, "malformedAuthorizedCredentials", expectedErrMsg); + : RPC::expected_field_message(jss::credential_type, "hex string"); + checkErrorValue(jrr, "malformedAuthorizedCredentials", expectedErrMsg); }; auto const& badValues = getBadValues(FieldType::BlobField); @@ -1177,18 +1034,15 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::deposit_preauth][jss::owner] = bob.human(); jvParams[jss::deposit_preauth][jss::authorized] = alice.human(); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - Json::arrayValue; - auto& arr( - jvParams[jss::deposit_preauth][jss::authorized_credentials]); + jvParams[jss::deposit_preauth][jss::authorized_credentials] = Json::arrayValue; + auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]); Json::Value jo; jo[jss::issuer] = issuer.human(); jo[jss::credential_type] = strHex(std::string_view(credType)); arr.append(std::move(jo)); - auto const jrr = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams)); checkErrorValue( jrr[jss::result], "malformedRequest", @@ -1216,14 +1070,11 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ledger_index] = jss::validated; jvParams[jss::deposit_preauth][jss::owner] = bob.human(); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - Json::arrayValue; - auto& arr( - jvParams[jss::deposit_preauth][jss::authorized_credentials]); + jvParams[jss::deposit_preauth][jss::authorized_credentials] = Json::arrayValue; + auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]); arr.append("foobar"); - auto const jrr = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams)); checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", @@ -1235,16 +1086,13 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ledger_index] = jss::validated; jvParams[jss::deposit_preauth][jss::owner] = bob.human(); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - Json::arrayValue; - auto& arr( - jvParams[jss::deposit_preauth][jss::authorized_credentials]); + jvParams[jss::deposit_preauth][jss::authorized_credentials] = Json::arrayValue; + auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]); Json::Value payload = Json::arrayValue; payload.append(42); arr.append(std::move(payload)); - auto const jrr = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams)); checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", @@ -1256,11 +1104,9 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ledger_index] = jss::validated; jvParams[jss::deposit_preauth][jss::owner] = bob.human(); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - Json::arrayValue; + jvParams[jss::deposit_preauth][jss::authorized_credentials] = Json::arrayValue; - auto const jrr = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams)); checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", @@ -1270,27 +1116,15 @@ class LedgerEntry_test : public beast::unit_test::suite { // Failed, authorized_credentials is too long static std::array const credTypes = { - "cred1", - "cred2", - "cred3", - "cred4", - "cred5", - "cred6", - "cred7", - "cred8", - "cred9"}; - static_assert( - sizeof(credTypes) / sizeof(credTypes[0]) > - maxCredentialsArraySize); + "cred1", "cred2", "cred3", "cred4", "cred5", "cred6", "cred7", "cred8", "cred9"}; + static_assert(sizeof(credTypes) / sizeof(credTypes[0]) > maxCredentialsArraySize); Json::Value jvParams; jvParams[jss::ledger_index] = jss::validated; jvParams[jss::deposit_preauth][jss::owner] = bob.human(); - jvParams[jss::deposit_preauth][jss::authorized_credentials] = - Json::arrayValue; + jvParams[jss::deposit_preauth][jss::authorized_credentials] = Json::arrayValue; - auto& arr( - jvParams[jss::deposit_preauth][jss::authorized_credentials]); + auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]); for (auto cred : credTypes) { @@ -1300,8 +1134,7 @@ class LedgerEntry_test : public beast::unit_test::suite arr.append(std::move(jo)); } - auto const jrr = - env.rpc("json", "ledger_entry", to_string(jvParams)); + auto const jrr = env.rpc("json", "ledger_entry", to_string(jvParams)); checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", @@ -1340,15 +1173,13 @@ class LedgerEntry_test : public beast::unit_test::suite BEAST_EXPECT(jrr[jss::ledger_index] == 5); } - std::string const dirRootIndex = - "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D"; + std::string const dirRootIndex = "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D"; { // Locate directory by index. Json::Value jvParams; jvParams[jss::directory] = dirRootIndex; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::node][sfIndexes.jsonName].size() == 32); } { @@ -1356,8 +1187,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::directory] = Json::objectValue; jvParams[jss::directory][jss::dir_root] = dirRootIndex; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::index] == dirRootIndex); } { @@ -1366,8 +1196,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::directory] = Json::objectValue; jvParams[jss::directory][jss::owner] = alice.human(); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::index] == dirRootIndex); } { @@ -1376,8 +1205,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::directory] = Json::objectValue; jvParams[jss::directory][jss::dir_root] = dirRootIndex; jvParams[jss::directory][jss::sub_index] = 1; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::index] != dirRootIndex); BEAST_EXPECT(jrr[jss::node][sfIndexes.jsonName].size() == 2); } @@ -1388,8 +1216,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::directory][jss::owner] = alice.human(); jvParams[jss::directory][jss::sub_index] = 1; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::index] != dirRootIndex); BEAST_EXPECT(jrr[jss::node][sfIndexes.jsonName].size() == 2); } @@ -1397,12 +1224,7 @@ class LedgerEntry_test : public beast::unit_test::suite // Bad directory argument. Json::Value jvParams; jvParams[jss::ledger_hash] = ledgerHash; - testMalformedField( - env, - jvParams, - jss::directory, - FieldType::HashOrObjectField, - "malformedRequest"); + testMalformedField(env, jvParams, jss::directory, FieldType::HashOrObjectField, "malformedRequest"); } { // Non-integer sub_index. @@ -1411,13 +1233,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::directory][jss::dir_root] = dirRootIndex; jvParams[jss::ledger_hash] = ledgerHash; testMalformedSubfield( - env, - jvParams, - jss::directory, - jss::sub_index, - FieldType::UInt64Field, - "malformedRequest", - false); + env, jvParams, jss::directory, jss::sub_index, FieldType::UInt64Field, "malformedRequest", false); } { // Malformed owner entry. @@ -1426,13 +1242,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::ledger_hash] = ledgerHash; testMalformedSubfield( - env, - jvParams, - jss::directory, - jss::owner, - FieldType::AccountField, - "malformedAddress", - false); + env, jvParams, jss::directory, jss::owner, FieldType::AccountField, "malformedAddress", false); } { // Malformed directory object. Specifies both dir_root and owner. @@ -1441,12 +1251,8 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::directory][jss::owner] = alice.human(); jvParams[jss::directory][jss::dir_root] = dirRootIndex; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, - "malformedRequest", - "Must have exactly one of `owner` and `dir_root` fields."); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "malformedRequest", "Must have exactly one of `owner` and `dir_root` fields."); } { // Incomplete directory object. Missing both dir_root and owner. @@ -1454,12 +1260,8 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::directory] = Json::objectValue; jvParams[jss::directory][jss::sub_index] = 1; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, - "malformedRequest", - "Must have exactly one of `owner` and `dir_root` fields."); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "malformedRequest", "Must have exactly one of `owner` and `dir_root` fields."); } } @@ -1483,8 +1285,7 @@ class LedgerEntry_test : public beast::unit_test::suite jv[jss::Account] = account.human(); jv[jss::Destination] = to.human(); jv[jss::Amount] = amount.getJson(JsonOptions::none); - jv[sfFinishAfter.jsonName] = - cancelAfter.time_since_epoch().count() + 2; + jv[sfFinishAfter.jsonName] = cancelAfter.time_since_epoch().count() + 2; return jv; }; @@ -1500,10 +1301,8 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::escrow] = Json::objectValue; jvParams[jss::escrow][jss::owner] = alice.human(); jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][jss::Amount] == XRP(333).value().getText()); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][jss::Amount] == XRP(333).value().getText()); escrowIndex = jrr[jss::index].asString(); } { @@ -1511,17 +1310,12 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::escrow] = escrowIndex; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][jss::Amount] == XRP(333).value().getText()); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][jss::Amount] == XRP(333).value().getText()); } { // Malformed escrow fields - runLedgerEntryTest( - env, - jss::escrow, - {{jss::owner, "malformedOwner"}, {jss::seq, "malformedSeq"}}); + runLedgerEntryTest(env, jss::escrow, {{jss::owner, "malformedOwner"}, {jss::seq, "malformedSeq"}}); } } @@ -1537,19 +1331,12 @@ class LedgerEntry_test : public beast::unit_test::suite Keylet const keylet = keylet::fees(); Json::Value jvParams; jvParams[jss::fee] = to_string(keylet.key); - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::FeeSettings); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::FeeSettings); } // negative tests - testMalformedField( - env, - Json::Value{}, - jss::fee, - FieldType::FixedHashField, - "malformedRequest"); + testMalformedField(env, Json::Value{}, jss::fee, FieldType::FixedHashField, "malformedRequest"); } void @@ -1564,20 +1351,12 @@ class LedgerEntry_test : public beast::unit_test::suite Keylet const keylet = keylet::skip(); Json::Value jvParams; jvParams[jss::hashes] = to_string(keylet.key); - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == - jss::LedgerHashes); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::LedgerHashes); } // negative tests - testMalformedField( - env, - Json::Value{}, - jss::hashes, - FieldType::FixedHashField, - "malformedRequest"); + testMalformedField(env, Json::Value{}, jss::hashes, FieldType::FixedHashField, "malformedRequest"); } void @@ -1592,26 +1371,19 @@ class LedgerEntry_test : public beast::unit_test::suite Account const buyer{"buyer"}; env.fund(XRP(1000), issuer, buyer); - uint256 const nftokenID0 = - token::getNextID(env, issuer, 0, tfTransferable); + uint256 const nftokenID0 = token::getNextID(env, issuer, 0, tfTransferable); env(token::mint(issuer, 0), txflags(tfTransferable)); env.close(); uint256 const offerID = keylet::nftoffer(issuer, env.seq(issuer)).key; - env(token::createOffer(issuer, nftokenID0, drops(1)), - token::destination(buyer), - txflags(tfSellNFToken)); + env(token::createOffer(issuer, nftokenID0, drops(1)), token::destination(buyer), txflags(tfSellNFToken)); { Json::Value jvParams; jvParams[jss::nft_offer] = to_string(offerID); - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == - jss::NFTokenOffer); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NFTokenOffer); BEAST_EXPECT(jrr[jss::node][sfOwner.jsonName] == issuer.human()); - BEAST_EXPECT( - jrr[jss::node][sfNFTokenID.jsonName] == to_string(nftokenID0)); + BEAST_EXPECT(jrr[jss::node][sfNFTokenID.jsonName] == to_string(nftokenID0)); BEAST_EXPECT(jrr[jss::node][sfAmount.jsonName] == "1"); } @@ -1639,10 +1411,8 @@ class LedgerEntry_test : public beast::unit_test::suite { Json::Value jvParams; jvParams[jss::nft_page] = to_string(nftpage.key); - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NFTokenPage); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NFTokenPage); } // negative tests @@ -1668,18 +1438,15 @@ class LedgerEntry_test : public beast::unit_test::suite // Create DisabledValidators array STArray disabledValidators; - auto disabledValidator = - STObject::makeInnerObject(sfDisabledValidator); + auto disabledValidator = STObject::makeInnerObject(sfDisabledValidator); auto pubKeyBlob = strUnHex( "ED58F6770DB5DD77E59D28CB650EC3816E2FC95021BB56E720C9A1" "2DA79C58A3AB"); disabledValidator.setFieldVL(sfPublicKey, *pubKeyBlob); - disabledValidator.setFieldU32( - sfFirstLedgerSequence, 91371264); + disabledValidator.setFieldU32(sfFirstLedgerSequence, 91371264); disabledValidators.push_back(std::move(disabledValidator)); - sle->setFieldArray( - sfDisabledValidators, disabledValidators); + sle->setFieldArray(sfDisabledValidators, disabledValidators); sle->setFieldH256( sfPreviousTxnID, uint256::fromVoid("8D47FFE664BE6C335108DF689537625855A6" @@ -1695,19 +1462,12 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::nunl] = to_string(keylet.key); - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NegativeUNL); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NegativeUNL); } // negative tests - testMalformedField( - env, - Json::Value{}, - jss::nunl, - FieldType::FixedHashField, - "malformedRequest"); + testMalformedField(env, Json::Value{}, jss::nunl, FieldType::FixedHashField, "malformedRequest"); } void @@ -1734,8 +1494,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::offer][jss::account] = alice.human(); jvParams[jss::offer][jss::seq] = env.seq(alice) - 1; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::node][jss::TakerGets] == "322000000"); offerIndex = jrr[jss::index].asString(); } @@ -1743,18 +1502,13 @@ class LedgerEntry_test : public beast::unit_test::suite // Request the offer using its index. Json::Value jvParams; jvParams[jss::offer] = offerIndex; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::node][jss::TakerGets] == "322000000"); } { // Malformed offer fields - runLedgerEntryTest( - env, - jss::offer, - {{jss::account, "malformedAddress"}, - {jss::seq, "malformedRequest"}}); + runLedgerEntryTest(env, jss::offer, {{jss::account, "malformedAddress"}, {jss::seq, "malformedRequest"}}); } } @@ -1791,15 +1545,13 @@ class LedgerEntry_test : public beast::unit_test::suite std::string const ledgerHash{to_string(env.closed()->header().hash)}; - uint256 const payChanIndex{ - keylet::payChan(alice, env.master, env.seq(alice) - 1).key}; + uint256 const payChanIndex{keylet::payChan(alice, env.master, env.seq(alice) - 1).key}; { // Request the payment channel using its index. Json::Value jvParams; jvParams[jss::payment_channel] = to_string(payChanIndex); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::node][sfAmount.jsonName] == "57000000"); BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] == "0"); BEAST_EXPECT(jrr[jss::node][sfSettleDelay.jsonName] == 18); @@ -1809,8 +1561,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::payment_channel] = ledgerHash; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } @@ -1841,8 +1592,7 @@ class LedgerEntry_test : public beast::unit_test::suite // check both aliases for (auto const& fieldName : {jss::ripple_state, jss::state}) { - std::string const ledgerHash{ - to_string(env.closed()->header().hash)}; + std::string const ledgerHash{to_string(env.closed()->header().hash)}; { // Request the trust line using the accounts and currency. Json::Value jvParams; @@ -1852,12 +1602,9 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[fieldName][jss::accounts][1u] = gw.human(); jvParams[fieldName][jss::currency] = "USD"; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfBalance.jsonName][jss::value] == "-97"); - BEAST_EXPECT( - jrr[jss::node][sfHighLimit.jsonName][jss::value] == "999"); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName][jss::value] == "-97"); + BEAST_EXPECT(jrr[jss::node][sfHighLimit.jsonName][jss::value] == "999"); } { // test basic malformed scenarios @@ -1877,8 +1624,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[fieldName][jss::accounts][0u] = alice.human(); jvParams[fieldName][jss::currency] = "USD"; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue( jrr, "malformedRequest", @@ -1895,8 +1641,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[fieldName][jss::accounts][2u] = alice.human(); jvParams[fieldName][jss::currency] = "USD"; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue( jrr, "malformedRequest", @@ -1915,15 +1660,9 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[fieldName][jss::accounts][1u] = gw.human(); jvParams[fieldName][jss::currency] = "USD"; - Json::Value const jrr = env.rpc( - "json", - "ledger_entry", - to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue( - jrr, - "malformedAddress", - RPC::expected_field_message( - jss::accounts, "array of Accounts")); + jrr, "malformedAddress", RPC::expected_field_message(jss::accounts, "array of Accounts")); } { @@ -1933,15 +1672,9 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[fieldName][jss::accounts][1u] = badAccount; jvParams[fieldName][jss::currency] = "USD"; - Json::Value const jrr = env.rpc( - "json", - "ledger_entry", - to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue( - jrr, - "malformedAddress", - RPC::expected_field_message( - jss::accounts, "array of Accounts")); + jrr, "malformedAddress", RPC::expected_field_message(jss::accounts, "array of Accounts")); } }; @@ -1961,12 +1694,8 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[fieldName][jss::accounts][1u] = alice.human(); jvParams[fieldName][jss::currency] = "USD"; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, - "malformedRequest", - "Cannot have a trustline to self."); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "malformedRequest", "Cannot have a trustline to self."); } } } @@ -2000,11 +1729,9 @@ class LedgerEntry_test : public beast::unit_test::suite { // Not a valid ticket requested by index. Json::Value jvParams; - jvParams[jss::ticket] = - to_string(getTicketIndex(env.master, tkt1 - 1)); + jvParams[jss::ticket] = to_string(getTicketIndex(env.master, tkt1 - 1)); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } { @@ -2012,10 +1739,8 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ticket] = to_string(getTicketIndex(env.master, tkt1)); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Ticket); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Ticket); BEAST_EXPECT(jrr[jss::node][sfTicketSequence.jsonName] == tkt1); } { @@ -2025,11 +1750,8 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::ticket][jss::account] = env.master.human(); jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 1; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][jss::index] == - to_string(getTicketIndex(env.master, tkt1 + 1))); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][jss::index] == to_string(getTicketIndex(env.master, tkt1 + 1))); } { // Not a valid ticket requested by account and sequence. @@ -2038,8 +1760,7 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::ticket][jss::account] = env.master.human(); jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 2; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } { @@ -2047,10 +1768,8 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ticket] = to_string(keylet::account(env.master).key); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, "unexpectedLedgerType", "Unexpected ledger type."); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "unexpectedLedgerType", "Unexpected ledger type."); } { @@ -2097,32 +1816,22 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::did] = alice.human(); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfDIDDocument.jsonName] == - strHex(std::string{"data"})); - BEAST_EXPECT( - jrr[jss::node][sfURI.jsonName] == strHex(std::string{"uri"})); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfDIDDocument.jsonName] == strHex(std::string{"data"})); + BEAST_EXPECT(jrr[jss::node][sfURI.jsonName] == strHex(std::string{"uri"})); } { // Request an index that is not a DID. Json::Value jvParams; jvParams[jss::did] = env.master.human(); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } { // Malformed DID index Json::Value jvParams; - testMalformedField( - env, - jvParams, - jss::did, - FieldType::AccountField, - "malformedAddress"); + testMalformedField(env, jvParams, jss::did, FieldType::AccountField, "malformedAddress"); } } @@ -2136,10 +1845,7 @@ class LedgerEntry_test : public beast::unit_test::suite Env env(*this); Account const owner("owner"); env.fund(XRP(1'000), owner); - Oracle oracle( - env, - {.owner = owner, - .fee = static_cast(env.current()->fees().base.drops())}); + Oracle oracle(env, {.owner = owner, .fee = static_cast(env.current()->fees().base.drops())}); { // test basic malformed scenarios @@ -2161,8 +1867,7 @@ class LedgerEntry_test : public beast::unit_test::suite using namespace xrpl::test::jtx::oracle; Env env(*this); - auto const baseFee = - static_cast(env.current()->fees().base.drops()); + auto const baseFee = static_cast(env.current()->fees().base.drops()); std::vector accounts; std::vector oracles; for (int i = 0; i < 10; ++i) @@ -2170,13 +1875,11 @@ class LedgerEntry_test : public beast::unit_test::suite Account const owner(std::string("owner") + std::to_string(i)); env.fund(XRP(1'000), owner); // different accounts can have the same asset pair - Oracle oracle( - env, {.owner = owner, .documentID = i, .fee = baseFee}); + Oracle oracle(env, {.owner = owner, .documentID = i, .fee = baseFee}); accounts.push_back(owner.id()); oracles.push_back(oracle.documentID()); // same account can have different asset pair - Oracle oracle1( - env, {.owner = owner, .documentID = i + 10, .fee = baseFee}); + Oracle oracle1(env, {.owner = owner, .documentID = i + 10, .fee = baseFee}); accounts.push_back(owner.id()); oracles.push_back(oracle1.documentID()); } @@ -2187,13 +1890,11 @@ class LedgerEntry_test : public beast::unit_test::suite if (i % 2) return Oracle::ledgerEntry(env, accounts[i], oracles[i]); // document id is string - return Oracle::ledgerEntry( - env, accounts[i], std::to_string(oracles[i])); + return Oracle::ledgerEntry(env, accounts[i], std::to_string(oracles[i])); }(); try { - BEAST_EXPECT( - jv[jss::node][jss::Owner] == to_string(accounts[i])); + BEAST_EXPECT(jv[jss::node][jss::Owner] == to_string(accounts[i])); } catch (...) { @@ -2217,35 +1918,28 @@ class LedgerEntry_test : public beast::unit_test::suite {.transferFee = 10, .metadata = "123", .ownerCount = 1, - .flags = tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | - tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback}); + .flags = tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | + tfMPTCanClawback}); mptAlice.authorize({.account = bob, .holderCount = 1}); std::string const ledgerHash{to_string(env.closed()->header().hash)}; - std::string const badMptID = - "00000193B9DDCAF401B5B3B26875986043F82CD0D13B4315"; + std::string const badMptID = "00000193B9DDCAF401B5B3B26875986043F82CD0D13B4315"; { // Request the MPTIssuance using its MPTIssuanceID. Json::Value jvParams; jvParams[jss::mpt_issuance] = strHex(mptAlice.issuanceID()); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfMPTokenMetadata.jsonName] == - strHex(std::string{"123"})); - BEAST_EXPECT( - jrr[jss::node][jss::mpt_issuance_id] == - strHex(mptAlice.issuanceID())); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfMPTokenMetadata.jsonName] == strHex(std::string{"123"})); + BEAST_EXPECT(jrr[jss::node][jss::mpt_issuance_id] == strHex(mptAlice.issuanceID())); } { // Request an index that is not a MPTIssuance. Json::Value jvParams; jvParams[jss::mpt_issuance] = badMptID; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } { @@ -2253,14 +1947,10 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::mptoken] = Json::objectValue; jvParams[jss::mptoken][jss::account] = bob.human(); - jvParams[jss::mptoken][jss::mpt_issuance_id] = - strHex(mptAlice.issuanceID()); + jvParams[jss::mptoken][jss::mpt_issuance_id] = strHex(mptAlice.issuanceID()); jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfMPTokenIssuanceID.jsonName] == - strHex(mptAlice.issuanceID())); + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfMPTokenIssuanceID.jsonName] == strHex(mptAlice.issuanceID())); } { // Request the MPToken using a bad mptIssuanceID. @@ -2269,19 +1959,13 @@ class LedgerEntry_test : public beast::unit_test::suite jvParams[jss::mptoken][jss::account] = bob.human(); jvParams[jss::mptoken][jss::mpt_issuance_id] = badMptID; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = env.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = env.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } { // Malformed MPTIssuance index Json::Value jvParams; - testMalformedField( - env, - jvParams, - jss::mptoken, - FieldType::HashOrObjectField, - "malformedRequest"); + testMalformedField(env, jvParams, jss::mptoken, FieldType::HashOrObjectField, "malformedRequest"); } } @@ -2315,30 +1999,23 @@ class LedgerEntry_test : public beast::unit_test::suite params[jss::permissioned_domain][jss::seq] = seq; auto jv = env.rpc("json", "ledger_entry", to_string(params)); BEAST_EXPECT( - jv.isObject() && jv.isMember(jss::result) && - !jv[jss::result].isMember(jss::error) && + jv.isObject() && jv.isMember(jss::result) && !jv[jss::result].isMember(jss::error) && jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == - jss::PermissionedDomain); + jv[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::PermissionedDomain); std::string const pdIdx = jv[jss::result][jss::index].asString(); - BEAST_EXPECT( - strHex(keylet::permissionedDomain(alice, seq).key) == pdIdx); + BEAST_EXPECT(strHex(keylet::permissionedDomain(alice, seq).key) == pdIdx); params.clear(); params[jss::ledger_index] = jss::validated; params[jss::permissioned_domain] = pdIdx; jv = env.rpc("json", "ledger_entry", to_string(params)); BEAST_EXPECT( - jv.isObject() && jv.isMember(jss::result) && - !jv[jss::result].isMember(jss::error) && + jv.isObject() && jv.isMember(jss::result) && !jv[jss::result].isMember(jss::error) && jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == - jss::PermissionedDomain); + jv[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::PermissionedDomain); } { @@ -2349,8 +2026,7 @@ class LedgerEntry_test : public beast::unit_test::suite "12F1F1F1F180D67377B2FAB292A31C922470326268D2B9B74CD1E582645B9A" "DE"; auto const jrr = env.rpc("json", "ledger_entry", to_string(params)); - checkErrorValue( - jrr[jss::result], "entryNotFound", "Entry not found."); + checkErrorValue(jrr[jss::result], "entryNotFound", "Entry not found."); } { // test basic malformed scenarios @@ -2390,34 +2066,28 @@ class LedgerEntry_test : public beast::unit_test::suite * @param expectedError: Optional. The expected error if not * good. Defaults to "entryNotFound". */ - auto checkResult = - [&](bool good, - Json::Value const& jv, - Json::StaticString const& expectedType, - std::optional const& expectedError = {}) { - if (good) - { - BEAST_EXPECTS( - jv.isObject() && jv.isMember(jss::result) && - !jv[jss::result].isMember(jss::error) && - jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - jv[jss::result][jss::node] - [sfLedgerEntryType.jsonName] == expectedType, - to_string(jv)); - } - else - { - BEAST_EXPECTS( - jv.isObject() && jv.isMember(jss::result) && - jv[jss::result].isMember(jss::error) && - !jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::error] == - expectedError.value_or("entryNotFound"), - to_string(jv)); - } - }; + auto checkResult = [&](bool good, + Json::Value const& jv, + Json::StaticString const& expectedType, + std::optional const& expectedError = {}) { + if (good) + { + BEAST_EXPECTS( + jv.isObject() && jv.isMember(jss::result) && !jv[jss::result].isMember(jss::error) && + jv[jss::result].isMember(jss::node) && + jv[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == expectedType, + to_string(jv)); + } + else + { + BEAST_EXPECTS( + jv.isObject() && jv.isMember(jss::result) && jv[jss::result].isMember(jss::error) && + !jv[jss::result].isMember(jss::node) && + jv[jss::result][jss::error] == expectedError.value_or("entryNotFound"), + to_string(jv)); + } + }; /** Runs a series of tests for a given fixed-position ledger * entry. @@ -2433,8 +2103,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::StaticString const& expectedType, Keylet const& expectedKey, bool good) { - testcase << expectedType.c_str() << (good ? "" : " not") - << " found"; + testcase << expectedType.c_str() << (good ? "" : " not") << " found"; auto const hexKey = strHex(expectedKey.key); @@ -2444,8 +2113,7 @@ class LedgerEntry_test : public beast::unit_test::suite Json::Value params; params[jss::ledger_index] = jss::validated; params[field] = Json::nullValue; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, expectedType, "malformedRequest"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2455,8 +2123,7 @@ class LedgerEntry_test : public beast::unit_test::suite // "field":"string" params[jss::ledger_index] = jss::validated; params[field] = "arbitrary string"; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, expectedType, "malformedRequest"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2466,8 +2133,7 @@ class LedgerEntry_test : public beast::unit_test::suite // "field":false params[jss::ledger_index] = jss::validated; params[field] = false; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, expectedType, "invalidParams"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2479,11 +2145,9 @@ class LedgerEntry_test : public beast::unit_test::suite auto const badKey = strHex(expectedKey.key + uint256{1}); params[jss::ledger_index] = jss::validated; params[field] = badKey; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, expectedType, "entryNotFound"); - BEAST_EXPECTS( - jv[jss::result][jss::index] == badKey, to_string(jv)); + BEAST_EXPECTS(jv[jss::result][jss::index] == badKey, to_string(jv)); } { @@ -2492,8 +2156,7 @@ class LedgerEntry_test : public beast::unit_test::suite params[jss::ledger_index] = jss::validated; params[jss::index] = field; params[jss::api_version] = 2; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, expectedType, "malformedRequest"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2505,11 +2168,9 @@ class LedgerEntry_test : public beast::unit_test::suite // Use the "field":true notation params[jss::ledger_index] = jss::validated; params[field] = true; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); // Index will always be returned for valid parameters. - std::string const pdIdx = - jv[jss::result][jss::index].asString(); + std::string const pdIdx = jv[jss::result][jss::index].asString(); BEAST_EXPECTS(hexKey == pdIdx, to_string(jv)); checkResult(good, jv, expectedType); @@ -2522,8 +2183,7 @@ class LedgerEntry_test : public beast::unit_test::suite // "field":"[index hash]" params[jss::ledger_index] = jss::validated; params[field] = hexKey; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(good, jv, expectedType); BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey); } @@ -2535,8 +2195,7 @@ class LedgerEntry_test : public beast::unit_test::suite params[jss::ledger_index] = jss::validated; params[jss::index] = field; params[jss::api_version] = 2; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, expectedType, "malformedRequest"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2547,8 +2206,7 @@ class LedgerEntry_test : public beast::unit_test::suite params[jss::ledger_index] = jss::validated; params[jss::index] = field; params[jss::api_version] = 3; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); // Index is correct either way BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey); checkResult(good, jv, expectedType); @@ -2559,8 +2217,7 @@ class LedgerEntry_test : public beast::unit_test::suite // Use the "index":"[index hash]" notation params[jss::ledger_index] = jss::validated; params[jss::index] = pdIdx; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); // Index is correct either way BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey); checkResult(good, jv, expectedType); @@ -2600,40 +2257,32 @@ class LedgerEntry_test : public beast::unit_test::suite * @param expectedError: Optional. The expected error if not * good. Defaults to "entryNotFound". */ - auto checkResult = - [&](bool good, - Json::Value const& jv, - int expectedCount, - std::optional const& expectedError = {}) { - if (good) - { - BEAST_EXPECTS( - jv.isObject() && jv.isMember(jss::result) && - !jv[jss::result].isMember(jss::error) && - jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::node].isMember( - sfLedgerEntryType.jsonName) && - jv[jss::result][jss::node] - [sfLedgerEntryType.jsonName] == jss::LedgerHashes, - to_string(jv)); - BEAST_EXPECTS( + auto checkResult = [&](bool good, + Json::Value const& jv, + int expectedCount, + std::optional const& expectedError = {}) { + if (good) + { + BEAST_EXPECTS( + jv.isObject() && jv.isMember(jss::result) && !jv[jss::result].isMember(jss::error) && jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::node].isMember("Hashes") && - jv[jss::result][jss::node]["Hashes"].size() == - expectedCount, - to_string(jv[jss::result][jss::node]["Hashes"].size())); - } - else - { - BEAST_EXPECTS( - jv.isObject() && jv.isMember(jss::result) && - jv[jss::result].isMember(jss::error) && - !jv[jss::result].isMember(jss::node) && - jv[jss::result][jss::error] == - expectedError.value_or("entryNotFound"), - to_string(jv)); - } - }; + jv[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) && + jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::LedgerHashes, + to_string(jv)); + BEAST_EXPECTS( + jv[jss::result].isMember(jss::node) && jv[jss::result][jss::node].isMember("Hashes") && + jv[jss::result][jss::node]["Hashes"].size() == expectedCount, + to_string(jv[jss::result][jss::node]["Hashes"].size())); + } + else + { + BEAST_EXPECTS( + jv.isObject() && jv.isMember(jss::result) && jv[jss::result].isMember(jss::error) && + !jv[jss::result].isMember(jss::node) && + jv[jss::result][jss::error] == expectedError.value_or("entryNotFound"), + to_string(jv)); + } + }; /** Runs a series of tests for a given ledger index. * @@ -2645,12 +2294,8 @@ class LedgerEntry_test : public beast::unit_test::suite * @param expectedCount: The number of Hashes expected in the * object if "good". */ - auto test = [&](Json::Value ledger, - Keylet const& expectedKey, - bool good, - int expectedCount = 0) { - testcase << "LedgerHashes: seq: " << env.current()->header().seq - << " \"hashes\":" << to_string(ledger) + auto test = [&](Json::Value ledger, Keylet const& expectedKey, bool good, int expectedCount = 0) { + testcase << "LedgerHashes: seq: " << env.current()->header().seq << " \"hashes\":" << to_string(ledger) << (good ? "" : " not") << " found"; auto const hexKey = strHex(expectedKey.key); @@ -2671,8 +2316,7 @@ class LedgerEntry_test : public beast::unit_test::suite // "hashes":"non-uint string" params[jss::ledger_index] = jss::validated; params[jss::hashes] = "arbitrary string"; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, 0, "malformedRequest"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2682,8 +2326,7 @@ class LedgerEntry_test : public beast::unit_test::suite // "hashes":"uint string" is invalid, too params[jss::ledger_index] = jss::validated; params[jss::hashes] = "10"; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, 0, "malformedRequest"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2693,8 +2336,7 @@ class LedgerEntry_test : public beast::unit_test::suite // "hashes":false params[jss::ledger_index] = jss::validated; params[jss::hashes] = false; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, 0, "invalidParams"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2704,8 +2346,7 @@ class LedgerEntry_test : public beast::unit_test::suite // "hashes":-1 params[jss::ledger_index] = jss::validated; params[jss::hashes] = -1; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, 0, "internal"); BEAST_EXPECT(!jv[jss::result].isMember(jss::index)); } @@ -2716,8 +2357,7 @@ class LedgerEntry_test : public beast::unit_test::suite auto const badKey = strHex(expectedKey.key + uint256{1}); params[jss::ledger_index] = jss::validated; params[jss::hashes] = badKey; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(false, jv, 0, "entryNotFound"); BEAST_EXPECT(jv[jss::result][jss::index] == badKey); } @@ -2728,12 +2368,10 @@ class LedgerEntry_test : public beast::unit_test::suite // Use the "hashes":ledger notation params[jss::ledger_index] = jss::validated; params[jss::hashes] = ledger; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(good, jv, expectedCount); // Index will always be returned for valid parameters. - std::string const pdIdx = - jv[jss::result][jss::index].asString(); + std::string const pdIdx = jv[jss::result][jss::index].asString(); BEAST_EXPECTS(hexKey == pdIdx, strHex(pdIdx)); } @@ -2742,13 +2380,11 @@ class LedgerEntry_test : public beast::unit_test::suite // "hashes":"[index hash]" params[jss::ledger_index] = jss::validated; params[jss::hashes] = hexKey; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(good, jv, expectedCount); // Index is correct either way BEAST_EXPECTS( - hexKey == jv[jss::result][jss::index].asString(), - strHex(jv[jss::result][jss::index].asString())); + hexKey == jv[jss::result][jss::index].asString(), strHex(jv[jss::result][jss::index].asString())); } { @@ -2756,13 +2392,11 @@ class LedgerEntry_test : public beast::unit_test::suite // Use the "index":"[index hash]" notation params[jss::ledger_index] = jss::validated; params[jss::index] = hexKey; - auto const jv = - env.rpc("json", "ledger_entry", to_string(params)); + auto const jv = env.rpc("json", "ledger_entry", to_string(params)); checkResult(good, jv, expectedCount); // Index is correct either way BEAST_EXPECTS( - hexKey == jv[jss::result][jss::index].asString(), - strHex(jv[jss::result][jss::index].asString())); + hexKey == jv[jss::result][jss::index].asString(), strHex(jv[jss::result][jss::index].asString())); } }; @@ -2815,10 +2449,8 @@ class LedgerEntry_test : public beast::unit_test::suite std::string const ledgerHash{to_string(env.closed()->header().hash)}; { // Request a check. - Json::Value const jrr = - env.rpc("ledger_entry", to_string(checkId.key))[jss::result]; - BEAST_EXPECT( - jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Check); + Json::Value const jrr = env.rpc("ledger_entry", to_string(checkId.key))[jss::result]; + BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Check); BEAST_EXPECT(jrr[jss::node][sfSendMax.jsonName] == "100000000"); } } @@ -2859,14 +2491,10 @@ public: } }; -class LedgerEntry_XChain_test : public beast::unit_test::suite, - public test::jtx::XChainBridgeObjects +class LedgerEntry_XChain_test : public beast::unit_test::suite, public test::jtx::XChainBridgeObjects { void - checkErrorValue( - Json::Value const& jv, - std::string const& err, - std::string const& msg) + checkErrorValue(Json::Value const& jv, std::string const& err, std::string const& msg) { if (BEAST_EXPECT(jv.isMember(jss::status))) BEAST_EXPECT(jv[jss::status] == "error"); @@ -2874,9 +2502,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, BEAST_EXPECT(jv[jss::error] == err); if (msg.empty()) { - BEAST_EXPECT( - jv[jss::error_message] == Json::nullValue || - jv[jss::error_message] == ""); + BEAST_EXPECT(jv[jss::error_message] == Json::nullValue || jv[jss::error_message] == ""); } else if (BEAST_EXPECT(jv.isMember(jss::error_message))) BEAST_EXPECT(jv[jss::error_message] == msg); @@ -2901,8 +2527,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, Json::Value jvParams; jvParams[jss::bridge_account] = mcDoor.human(); jvParams[jss::bridge] = jvb; - Json::Value const jrr = mcEnv.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = mcEnv.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); auto r = jrr[jss::node]; @@ -2931,8 +2556,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, // request the bridge via RPC by index Json::Value jvParams; jvParams[jss::index] = bridge_index; - Json::Value const jrr = mcEnv.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = mcEnv.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); BEAST_EXPECT(jrr[jss::node] == mcBridge); @@ -2944,8 +2568,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, jvParams[jss::bridge_account] = Account::master.human(); jvParams[jss::bridge] = jvb; jvParams[jss::ledger_hash] = ledgerHash; - Json::Value const jrr = mcEnv.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = mcEnv.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } @@ -2961,8 +2584,7 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, Json::Value jvParams; jvParams[jss::bridge_account] = mcDoor.human(); jvParams[jss::bridge] = jvb; - Json::Value const jrr = mcEnv.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + Json::Value const jrr = mcEnv.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); auto r = jrr[jss::node]; @@ -2994,18 +2616,15 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, // request the xchain_claim_id via RPC Json::Value jvParams; jvParams[jss::xchain_owned_claim_id] = jvXRPBridgeRPC; - jvParams[jss::xchain_owned_claim_id][jss::xchain_owned_claim_id] = - 1; - Json::Value const jrr = scEnv.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + jvParams[jss::xchain_owned_claim_id][jss::xchain_owned_claim_id] = 1; + Json::Value const jrr = scEnv.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); auto r = jrr[jss::node]; BEAST_EXPECT(r.isMember(jss::Account)); BEAST_EXPECT(r[jss::Account] == scAlice.human()); - BEAST_EXPECT( - r[sfLedgerEntryType.jsonName] == jss::XChainOwnedClaimID); + BEAST_EXPECT(r[sfLedgerEntryType.jsonName] == jss::XChainOwnedClaimID); BEAST_EXPECT(r[sfXChainClaimID.jsonName].asInt() == 1); BEAST_EXPECT(r[sfOwnerNode.jsonName].asInt() == 0); } @@ -3014,18 +2633,15 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, // request the xchain_claim_id via RPC Json::Value jvParams; jvParams[jss::xchain_owned_claim_id] = jvXRPBridgeRPC; - jvParams[jss::xchain_owned_claim_id][jss::xchain_owned_claim_id] = - 2; - Json::Value const jrr = scEnv.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + jvParams[jss::xchain_owned_claim_id][jss::xchain_owned_claim_id] = 2; + Json::Value const jrr = scEnv.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); auto r = jrr[jss::node]; BEAST_EXPECT(r.isMember(jss::Account)); BEAST_EXPECT(r[jss::Account] == scBob.human()); - BEAST_EXPECT( - r[sfLedgerEntryType.jsonName] == jss::XChainOwnedClaimID); + BEAST_EXPECT(r[sfLedgerEntryType.jsonName] == jss::XChainOwnedClaimID); BEAST_EXPECT(r[sfXChainClaimID.jsonName].asInt() == 2); BEAST_EXPECT(r[sfOwnerNode.jsonName].asInt() == 0); } @@ -3043,12 +2659,10 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, // note: signers.size() and quorum are both 5 in createBridgeObjects createBridgeObjects(mcEnv, scEnv); - auto scCarol = - Account("scCarol"); // Don't fund it - it will be created with the - // xchain transaction + auto scCarol = Account("scCarol"); // Don't fund it - it will be created with the + // xchain transaction auto const amt = XRP(1000); - mcEnv(sidechain_xchain_account_create( - mcAlice, jvb, scCarol, amt, reward)); + mcEnv(sidechain_xchain_account_create(mcAlice, jvb, scCarol, amt, reward)); mcEnv.close(); // send less than quorum of attestations (otherwise funds are @@ -3075,12 +2689,9 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, { // request the create account claim_id via RPC Json::Value jvParams; - jvParams[jss::xchain_owned_create_account_claim_id] = - jvXRPBridgeRPC; - jvParams[jss::xchain_owned_create_account_claim_id] - [jss::xchain_owned_create_account_claim_id] = 1; - Json::Value const jrr = scEnv.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + jvParams[jss::xchain_owned_create_account_claim_id] = jvXRPBridgeRPC; + jvParams[jss::xchain_owned_create_account_claim_id][jss::xchain_owned_create_account_claim_id] = 1; + Json::Value const jrr = scEnv.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::node)); auto r = jrr[jss::node]; @@ -3091,47 +2702,32 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, BEAST_EXPECT(r.isMember(sfXChainAccountCreateCount.jsonName)); BEAST_EXPECT(r[sfXChainAccountCreateCount.jsonName].asInt() == 1); - BEAST_EXPECT( - r.isMember(sfXChainCreateAccountAttestations.jsonName)); + BEAST_EXPECT(r.isMember(sfXChainCreateAccountAttestations.jsonName)); auto attest = r[sfXChainCreateAccountAttestations.jsonName]; BEAST_EXPECT(attest.isArray()); BEAST_EXPECT(attest.size() == 3); - BEAST_EXPECT(attest[Json::Value::UInt(0)].isMember( - sfXChainCreateAccountProofSig.jsonName)); + BEAST_EXPECT(attest[Json::Value::UInt(0)].isMember(sfXChainCreateAccountProofSig.jsonName)); Json::Value a[num_attest]; for (size_t i = 0; i < num_attest; ++i) { - a[i] = attest[Json::Value::UInt(0)] - [sfXChainCreateAccountProofSig.jsonName]; - BEAST_EXPECT( - a[i].isMember(jss::Amount) && - a[i][jss::Amount].asInt() == 1000 * drop_per_xrp); - BEAST_EXPECT( - a[i].isMember(jss::Destination) && - a[i][jss::Destination] == scCarol.human()); + a[i] = attest[Json::Value::UInt(0)][sfXChainCreateAccountProofSig.jsonName]; + BEAST_EXPECT(a[i].isMember(jss::Amount) && a[i][jss::Amount].asInt() == 1000 * drop_per_xrp); + BEAST_EXPECT(a[i].isMember(jss::Destination) && a[i][jss::Destination] == scCarol.human()); BEAST_EXPECT( a[i].isMember(sfAttestationSignerAccount.jsonName) && - std::any_of( - signers.begin(), signers.end(), [&](signer const& s) { - return a[i][sfAttestationSignerAccount.jsonName] == - s.account.human(); - })); + std::any_of(signers.begin(), signers.end(), [&](signer const& s) { + return a[i][sfAttestationSignerAccount.jsonName] == s.account.human(); + })); BEAST_EXPECT( a[i].isMember(sfAttestationRewardAccount.jsonName) && - std::any_of( - payee.begin(), - payee.end(), - [&](Account const& account) { - return a[i][sfAttestationRewardAccount.jsonName] == - account.human(); - })); + std::any_of(payee.begin(), payee.end(), [&](Account const& account) { + return a[i][sfAttestationRewardAccount.jsonName] == account.human(); + })); BEAST_EXPECT( - a[i].isMember(sfWasLockingChainSend.jsonName) && - a[i][sfWasLockingChainSend.jsonName] == 1); + a[i].isMember(sfWasLockingChainSend.jsonName) && a[i][sfWasLockingChainSend.jsonName] == 1); BEAST_EXPECT( a[i].isMember(sfSignatureReward.jsonName) && - a[i][sfSignatureReward.jsonName].asInt() == - 1 * drop_per_xrp); + a[i][sfSignatureReward.jsonName].asInt() == 1 * drop_per_xrp); } } @@ -3145,12 +2741,9 @@ class LedgerEntry_XChain_test : public beast::unit_test::suite, { // request the create account claim_id via RPC Json::Value jvParams; - jvParams[jss::xchain_owned_create_account_claim_id] = - jvXRPBridgeRPC; - jvParams[jss::xchain_owned_create_account_claim_id] - [jss::xchain_owned_create_account_claim_id] = 1; - Json::Value const jrr = scEnv.rpc( - "json", "ledger_entry", to_string(jvParams))[jss::result]; + jvParams[jss::xchain_owned_create_account_claim_id] = jvXRPBridgeRPC; + jvParams[jss::xchain_owned_create_account_claim_id][jss::xchain_owned_create_account_claim_id] = 1; + Json::Value const jrr = scEnv.rpc("json", "ledger_entry", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "entryNotFound", "Entry not found."); } } diff --git a/src/test/rpc/LedgerHeader_test.cpp b/src/test/rpc/LedgerHeader_test.cpp index 3af82d683e..8b460fe6a4 100644 --- a/src/test/rpc/LedgerHeader_test.cpp +++ b/src/test/rpc/LedgerHeader_test.cpp @@ -17,8 +17,7 @@ class LedgerHeader_test : public beast::unit_test::suite Json::Value params{Json::objectValue}; params[jss::api_version] = 1; params[jss::ledger_index] = "current"; - auto const result = - env.client().invoke("ledger_header", params)[jss::result]; + auto const result = env.client().invoke("ledger_header", params)[jss::result]; BEAST_EXPECT(result[jss::status] == "success"); BEAST_EXPECT(result.isMember("ledger")); BEAST_EXPECT(result[jss::ledger][jss::closed] == false); @@ -35,8 +34,7 @@ class LedgerHeader_test : public beast::unit_test::suite Json::Value params{Json::objectValue}; params[jss::api_version] = 1; params[jss::ledger_index] = "validated"; - auto const result = - env.client().invoke("ledger_header", params)[jss::result]; + auto const result = env.client().invoke("ledger_header", params)[jss::result]; BEAST_EXPECT(result[jss::status] == "success"); BEAST_EXPECT(result.isMember("ledger")); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); @@ -52,8 +50,7 @@ class LedgerHeader_test : public beast::unit_test::suite Json::Value params{Json::objectValue}; params[jss::api_version] = 2; - auto const result = - env.client().invoke("ledger_header", params)[jss::result]; + auto const result = env.client().invoke("ledger_header", params)[jss::result]; BEAST_EXPECT(result[jss::error] == "unknownCmd"); BEAST_EXPECT(result[jss::status] == "error"); } diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 583ff0a531..a656db558c 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -19,10 +19,7 @@ namespace test { class LedgerRPC_test : public beast::unit_test::suite { void - checkErrorValue( - Json::Value const& jv, - std::string const& err, - std::string const& msg) + checkErrorValue(Json::Value const& jv, std::string const& err, std::string const& msg) { if (BEAST_EXPECT(jv.isMember(jss::status))) BEAST_EXPECT(jv[jss::status] == "error"); @@ -30,15 +27,12 @@ class LedgerRPC_test : public beast::unit_test::suite BEAST_EXPECT(jv[jss::error] == err); if (msg.empty()) { - BEAST_EXPECT( - jv[jss::error_message] == Json::nullValue || - jv[jss::error_message] == ""); + BEAST_EXPECT(jv[jss::error_message] == Json::nullValue || jv[jss::error_message] == ""); } else if (BEAST_EXPECT(jv.isMember(jss::error_message))) BEAST_EXPECTS( jv[jss::error_message] == msg, - "Expected error message \"" + msg + "\", received \"" + - jv[jss::error_message].asString() + "\""); + "Expected error message \"" + msg + "\", received \"" + jv[jss::error_message].asString() + "\""); } // Corrupt a valid address by replacing the 10th character with '!'. @@ -66,8 +60,7 @@ class LedgerRPC_test : public beast::unit_test::suite Json::Value jvParams; // can be either numeric or quoted numeric jvParams[jss::ledger_index] = 1; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::ledger][jss::closed] == true); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "1"); } @@ -75,8 +68,7 @@ class LedgerRPC_test : public beast::unit_test::suite { Json::Value jvParams; jvParams[jss::ledger_index] = "1"; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::ledger][jss::closed] == true); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "1"); } @@ -85,11 +77,8 @@ class LedgerRPC_test : public beast::unit_test::suite // using current identifier auto const jrr = env.rpc("ledger", "current")[jss::result]; BEAST_EXPECT(jrr[jss::ledger][jss::closed] == false); - BEAST_EXPECT( - jrr[jss::ledger][jss::ledger_index] == - std::to_string(env.current()->header().seq)); - BEAST_EXPECT( - jrr[jss::ledger_current_index] == env.current()->header().seq); + BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == std::to_string(env.current()->header().seq)); + BEAST_EXPECT(jrr[jss::ledger_current_index] == env.current()->header().seq); } } @@ -112,32 +101,23 @@ class LedgerRPC_test : public beast::unit_test::suite // ask for an arbitrary string - index Json::Value jvParams; jvParams[jss::ledger_index] = "potato"; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, - "invalidParams", - "Invalid field 'ledger_index', not string or number."); + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "invalidParams", "Invalid field 'ledger_index', not string or number."); } { // ask for a negative index Json::Value jvParams; jvParams[jss::ledger_index] = -1; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, - "invalidParams", - "Invalid field 'ledger_index', not string or number."); + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "invalidParams", "Invalid field 'ledger_index', not string or number."); } { // ask for a bad ledger index Json::Value jvParams; jvParams[jss::ledger_index] = 10u; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "lgrNotFound", "ledgerNotFound"); } @@ -152,23 +132,20 @@ class LedgerRPC_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ledger_index] = "validated"; jvParams[jss::queue] = true; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; checkErrorValue(jrr, "invalidParams", "Invalid parameters."); } { // Request a ledger with a very large (double) sequence. - auto const ret = - env.rpc("json", "ledger", "{ \"ledger_index\" : 2e15 }"); + auto const ret = env.rpc("json", "ledger", "{ \"ledger_index\" : 2e15 }"); BEAST_EXPECT(RPC::contains_error(ret)); BEAST_EXPECT(ret[jss::error_message] == "Invalid parameters."); } { // Request a ledger with very large (integer) sequence. - auto const ret = env.rpc( - "json", "ledger", "{ \"ledger_index\" : 1000000000000000 }"); + auto const ret = env.rpc("json", "ledger", "{ \"ledger_index\" : 1000000000000000 }"); checkErrorValue(ret, "invalidParams", "Invalid parameters."); } } @@ -186,8 +163,7 @@ class LedgerRPC_test : public beast::unit_test::suite { auto const jrr = env.rpc("ledger_current")[jss::result]; - BEAST_EXPECT( - jrr[jss::ledger_current_index] == env.current()->header().seq); + BEAST_EXPECT(jrr[jss::ledger_current_index] == env.current()->header().seq); } } @@ -204,8 +180,7 @@ class LedgerRPC_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ledger_index] = 3u; jvParams[jss::full] = true; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState)); BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray()); BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u); @@ -224,10 +199,8 @@ class LedgerRPC_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ledger_index] = 1u; jvParams[jss::full] = true; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; - checkErrorValue( - jrr, "noPermission", "You don't have permission for this command."); + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + checkErrorValue(jrr, "noPermission", "You don't have permission for this command."); } void @@ -243,8 +216,7 @@ class LedgerRPC_test : public beast::unit_test::suite Json::Value jvParams; jvParams[jss::ledger_index] = 3u; jvParams[jss::accounts] = true; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState)); BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray()); BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u); @@ -262,9 +234,8 @@ class LedgerRPC_test : public beast::unit_test::suite auto cfg = envconfig(); cfg->FEES.reference_fee = 10; - Env env{ - *this, std::move(cfg), FeatureBitset{}}; // hashes requested below - // assume no amendments + Env env{*this, std::move(cfg), FeatureBitset{}}; // hashes requested below + // assume no amendments env.fund(XRP(10000), "alice"); env.close(); env.fund(XRP(10000), "bob"); @@ -277,8 +248,7 @@ class LedgerRPC_test : public beast::unit_test::suite // access via the legacy ledger field, keyword index values Json::Value jvParams; jvParams[jss::ledger] = "closed"; - auto jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5"); @@ -298,9 +268,7 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::ledger] = "invalid"; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'ledger', not string or number."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'ledger', not string or number."); // numeric index jvParams[jss::ledger] = 4; @@ -323,8 +291,7 @@ class LedgerRPC_test : public beast::unit_test::suite // access via the ledger_hash field Json::Value jvParams; jvParams[jss::ledger_hash] = hash3; - auto jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "3"); @@ -333,17 +300,13 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::ledger_hash] = "DEADBEEF" + hash3; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'ledger_hash', not hex string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'ledger_hash', not hex string."); // request with non-string ledger_hash jvParams[jss::ledger_hash] = 2; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'ledger_hash', not hex string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'ledger_hash', not hex string."); // malformed (non hex) hash jvParams[jss::ledger_hash] = @@ -351,9 +314,7 @@ class LedgerRPC_test : public beast::unit_test::suite "7F2775F2F7485BB37307984C3C0F2340"; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'ledger_hash', not hex string."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'ledger_hash', not hex string."); // properly formed, but just doesn't exist jvParams[jss::ledger_hash] = @@ -368,8 +329,7 @@ class LedgerRPC_test : public beast::unit_test::suite // access via the ledger_index field, keyword index values Json::Value jvParams; jvParams[jss::ledger_index] = "closed"; - auto jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::ledger)); BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == "5"); @@ -391,21 +351,17 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::ledger_index] = "invalid"; jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == - "Invalid field 'ledger_index', not string or number."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'ledger_index', not string or number."); // numeric index for (auto i : {1, 2, 3, 4, 5, 6}) { jvParams[jss::ledger_index] = i; - jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr.isMember(jss::ledger)); if (i < 6) BEAST_EXPECT(jrr.isMember(jss::ledger_hash)); - BEAST_EXPECT( - jrr[jss::ledger][jss::ledger_index] == std::to_string(i)); + BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] == std::to_string(i)); } // numeric index - out of range @@ -479,12 +435,8 @@ class LedgerRPC_test : public beast::unit_test::suite // Put some txs in the queue // Alice auto aliceSeq = env.seq(alice); - env(pay(alice, "george", XRP(1000)), - last_ledger_seq(7), - ter(terQUEUED)); - env(offer(alice, XRP(50000), alice["USD"](5000)), - seq(aliceSeq + 1), - ter(terQUEUED)); + env(pay(alice, "george", XRP(1000)), last_ledger_seq(7), ter(terQUEUED)); + env(offer(alice, XRP(50000), alice["USD"](5000)), seq(aliceSeq + 1), ter(terQUEUED)); env(noop(alice), seq(aliceSeq + 2), ter(terQUEUED)); // Bob auto batch = [&env](Account a) { @@ -671,18 +623,14 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::accounts] = true; jvParams[jss::expand] = true; jvParams[jss::type] = "hashes"; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState)); BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray()); - for (auto i = 0; i < jrr[jss::ledger][jss::accountState].size(); - i++) - if (jrr[jss::ledger][jss::accountState][i]["LedgerEntryType"] == - jss::LedgerHashes) + for (auto i = 0; i < jrr[jss::ledger][jss::accountState].size(); i++) + if (jrr[jss::ledger][jss::accountState][i]["LedgerEntryType"] == jss::LedgerHashes) { - index = jrr[jss::ledger][jss::accountState][i]["index"] - .asString(); + index = jrr[jss::ledger][jss::accountState][i]["index"].asString(); hashesLedgerEntryIndex = i; } @@ -692,10 +640,8 @@ class LedgerRPC_test : public beast::unit_test::suite // jss::type is a deprecated field BEAST_EXPECT( - jrr.isMember(jss::warnings) && jrr[jss::warnings].isArray() && - jrr[jss::warnings].size() == 1 && - jrr[jss::warnings][0u][jss::id].asInt() == - warnRPC_FIELDS_DEPRECATED); + jrr.isMember(jss::warnings) && jrr[jss::warnings].isArray() && jrr[jss::warnings].size() == 1 && + jrr[jss::warnings][0u][jss::id].asInt() == warnRPC_FIELDS_DEPRECATED); } { Json::Value jvParams; @@ -703,21 +649,16 @@ class LedgerRPC_test : public beast::unit_test::suite jvParams[jss::accounts] = true; jvParams[jss::expand] = false; jvParams[jss::type] = "hashes"; - auto const jrr = - env.rpc("json", "ledger", to_string(jvParams))[jss::result]; + auto const jrr = env.rpc("json", "ledger", to_string(jvParams))[jss::result]; BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState)); BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray()); BEAST_EXPECT( - hashesLedgerEntryIndex > 0 && - jrr[jss::ledger][jss::accountState][hashesLedgerEntryIndex] == - index); + hashesLedgerEntryIndex > 0 && jrr[jss::ledger][jss::accountState][hashesLedgerEntryIndex] == index); // jss::type is a deprecated field BEAST_EXPECT( - jrr.isMember(jss::warnings) && jrr[jss::warnings].isArray() && - jrr[jss::warnings].size() == 1 && - jrr[jss::warnings][0u][jss::id].asInt() == - warnRPC_FIELDS_DEPRECATED); + jrr.isMember(jss::warnings) && jrr[jss::warnings].isArray() && jrr[jss::warnings].size() == 1 && + jrr[jss::warnings][0u][jss::id].asInt() == warnRPC_FIELDS_DEPRECATED); } } diff --git a/src/test/rpc/LedgerRequest_test.cpp b/src/test/rpc/LedgerRequest_test.cpp index 153c6ad508..6a1bb2fb89 100644 --- a/src/test/rpc/LedgerRequest_test.cpp +++ b/src/test/rpc/LedgerRequest_test.cpp @@ -14,13 +14,10 @@ namespace RPC { class LedgerRequest_test : public beast::unit_test::suite { - static constexpr char const* hash1 = - "3020EB9E7BE24EF7D7A060CB051583EC117384636D1781AFB5B87F3E348DA489"; - static constexpr char const* accounthash1 = - "BD8A3D72CA73DDE887AD63666EC2BAD07875CBA997A102579B5B95ECDFFEAED8"; + static constexpr char const* hash1 = "3020EB9E7BE24EF7D7A060CB051583EC117384636D1781AFB5B87F3E348DA489"; + static constexpr char const* accounthash1 = "BD8A3D72CA73DDE887AD63666EC2BAD07875CBA997A102579B5B95ECDFFEAED8"; - static constexpr char const* zerohash = - "0000000000000000000000000000000000000000000000000000000000000000"; + static constexpr char const* zerohash = "0000000000000000000000000000000000000000000000000000000000000000"; public: void @@ -39,31 +36,27 @@ public: auto const result = env.rpc("ledger_request", "arbitrary_text"); BEAST_EXPECT( RPC::contains_error(result[jss::result]) && - result[jss::result][jss::error_message] == - "Ledger index too small"); + result[jss::result][jss::error_message] == "Ledger index too small"); } { auto const result = env.rpc("ledger_request", "-1"); BEAST_EXPECT( RPC::contains_error(result[jss::result]) && - result[jss::result][jss::error_message] == - "Ledger index too small"); + result[jss::result][jss::error_message] == "Ledger index too small"); } { auto const result = env.rpc("ledger_request", "0"); BEAST_EXPECT( RPC::contains_error(result[jss::result]) && - result[jss::result][jss::error_message] == - "Ledger index too small"); + result[jss::result][jss::error_message] == "Ledger index too small"); } { auto const result = env.rpc("ledger_request", "1"); BEAST_EXPECT( - !RPC::contains_error(result[jss::result]) && - result[jss::result][jss::ledger_index] == 1 && + !RPC::contains_error(result[jss::result]) && result[jss::result][jss::ledger_index] == 1 && result[jss::result].isMember(jss::ledger)); BEAST_EXPECT( result[jss::result][jss::ledger].isMember(jss::ledger_hash) && @@ -73,8 +66,7 @@ public: { auto const result = env.rpc("ledger_request", "2"); BEAST_EXPECT( - !RPC::contains_error(result[jss::result]) && - result[jss::result][jss::ledger_index] == 2 && + !RPC::contains_error(result[jss::result]) && result[jss::result][jss::ledger_index] == 2 && result[jss::result].isMember(jss::ledger)); BEAST_EXPECT( result[jss::result][jss::ledger].isMember(jss::ledger_hash) && @@ -84,26 +76,22 @@ public: { auto const result = env.rpc("ledger_request", "3"); BEAST_EXPECT( - !RPC::contains_error(result[jss::result]) && - result[jss::result][jss::ledger_index] == 3 && + !RPC::contains_error(result[jss::result]) && result[jss::result][jss::ledger_index] == 3 && result[jss::result].isMember(jss::ledger)); BEAST_EXPECT( result[jss::result][jss::ledger].isMember(jss::ledger_hash) && result[jss::result][jss::ledger][jss::ledger_hash].isString()); - auto const ledgerHash = - result[jss::result][jss::ledger][jss::ledger_hash].asString(); + auto const ledgerHash = result[jss::result][jss::ledger][jss::ledger_hash].asString(); { auto const r = env.rpc("ledger_request", ledgerHash); BEAST_EXPECT( - !RPC::contains_error(r[jss::result]) && - r[jss::result][jss::ledger_index] == 3 && + !RPC::contains_error(r[jss::result]) && r[jss::result][jss::ledger_index] == 3 && r[jss::result].isMember(jss::ledger)); BEAST_EXPECT( r[jss::result][jss::ledger].isMember(jss::ledger_hash) && - r[jss::result][jss::ledger][jss::ledger_hash] == - ledgerHash); + r[jss::result][jss::ledger][jss::ledger_hash] == ledgerHash); } } @@ -114,8 +102,7 @@ public: BEAST_EXPECT( RPC::contains_error(result[jss::result]) && - result[jss::result][jss::error_message] == - "Invalid field 'ledger_hash', not hex string."); + result[jss::result][jss::error_message] == "Invalid field 'ledger_hash', not hex string."); } { @@ -123,25 +110,21 @@ public: auto const result = env.rpc("ledger_request", ledgerHash); - BEAST_EXPECT( - !RPC::contains_error(result[jss::result]) && - result[jss::result][jss::have_header] == false); + BEAST_EXPECT(!RPC::contains_error(result[jss::result]) && result[jss::result][jss::have_header] == false); } { auto const result = env.rpc("ledger_request", "4"); BEAST_EXPECT( RPC::contains_error(result[jss::result]) && - result[jss::result][jss::error_message] == - "Ledger index too large"); + result[jss::result][jss::error_message] == "Ledger index too large"); } { auto const result = env.rpc("ledger_request", "5"); BEAST_EXPECT( RPC::contains_error(result[jss::result]) && - result[jss::result][jss::error_message] == - "Ledger index too large"); + result[jss::result][jss::error_message] == "Ledger index too large"); } } @@ -152,11 +135,8 @@ public: auto cfg = envconfig(); cfg->FEES.reference_fee = 10; - Env env{ - *this, - std::move(cfg), - FeatureBitset{}}; // the hashes being checked below - // assume no amendments + Env env{*this, std::move(cfg), FeatureBitset{}}; // the hashes being checked below + // assume no amendments Account const gw{"gateway"}; auto const USD = gw["USD"]; env.fund(XRP(100000), gw); @@ -176,8 +156,7 @@ public: auto result = env.rpc("ledger_request", "1")[jss::result]; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "1"); - BEAST_EXPECT( - result[jss::ledger][jss::total_coins] == "100000000000000000"); + BEAST_EXPECT(result[jss::ledger][jss::total_coins] == "100000000000000000"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash1); BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == zerohash); @@ -185,11 +164,9 @@ public: BEAST_EXPECT(result[jss::ledger][jss::transaction_hash] == zerohash); result = env.rpc("ledger_request", "2")[jss::result]; - constexpr char const* hash2 = - "CCC3B3E88CCAC17F1BE6B4A648A55999411F19E3FE55EB721960EB0DF28EDDA5"; + constexpr char const* hash2 = "CCC3B3E88CCAC17F1BE6B4A648A55999411F19E3FE55EB721960EB0DF28EDDA5"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "2"); - BEAST_EXPECT( - result[jss::ledger][jss::total_coins] == "100000000000000000"); + BEAST_EXPECT(result[jss::ledger][jss::total_coins] == "100000000000000000"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash2); BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash1); @@ -199,11 +176,9 @@ public: BEAST_EXPECT(result[jss::ledger][jss::transaction_hash] == zerohash); result = env.rpc("ledger_request", "3")[jss::result]; - constexpr char const* hash3 = - "9FFD8AE09190D5002FE4252A1B29EABCF40DABBCE3B42619C6BD0BE381D51103"; + constexpr char const* hash3 = "9FFD8AE09190D5002FE4252A1B29EABCF40DABBCE3B42619C6BD0BE381D51103"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "3"); - BEAST_EXPECT( - result[jss::ledger][jss::total_coins] == "99999999999999980"); + BEAST_EXPECT(result[jss::ledger][jss::total_coins] == "99999999999999980"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash3); BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash2); @@ -215,11 +190,9 @@ public: "CBD7F0948EBFA2241DE4EA627939A0FFEE6B80A90FE09C42C825DA546E9B73FF"); result = env.rpc("ledger_request", "4")[jss::result]; - constexpr char const* hash4 = - "7C9B614445517B8C6477E0AB10A35FFC1A23A34FEA41A91ECBDE884CC097C6E1"; + constexpr char const* hash4 = "7C9B614445517B8C6477E0AB10A35FFC1A23A34FEA41A91ECBDE884CC097C6E1"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "4"); - BEAST_EXPECT( - result[jss::ledger][jss::total_coins] == "99999999999999960"); + BEAST_EXPECT(result[jss::ledger][jss::total_coins] == "99999999999999960"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash4); BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash3); @@ -231,11 +204,9 @@ public: "9BBDDBF926100DFFF364E16268F544B19F5B9BC6ECCBBC104F98D13FA9F3BC35"); result = env.rpc("ledger_request", "5")[jss::result]; - constexpr char const* hash5 = - "98885D02145CCE4AD2605F1809F17188DB2053B14ED399CAC985DD8E03DCA8C0"; + constexpr char const* hash5 = "98885D02145CCE4AD2605F1809F17188DB2053B14ED399CAC985DD8E03DCA8C0"; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "5"); - BEAST_EXPECT( - result[jss::ledger][jss::total_coins] == "99999999999999940"); + BEAST_EXPECT(result[jss::ledger][jss::total_coins] == "99999999999999940"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash5); BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == hash4); @@ -268,10 +239,7 @@ public: "AB868A6CFEEC779C2FF845C0AF00A642259986AF40C01976A7F842B6918936" "C7"; jvParams[jss::ledger_index] = "1"; - auto const result = env.rpc( - "json", - "ledger_request", - jvParams.toStyledString())[jss::result]; + auto const result = env.rpc("json", "ledger_request", jvParams.toStyledString())[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::status] == "error"); BEAST_EXPECT( @@ -283,34 +251,26 @@ public: { Json::Value jvParams; jvParams[jss::ledger_index] = "index"; - auto const result = env.rpc( - "json", - "ledger_request", - jvParams.toStyledString())[jss::result]; + auto const result = env.rpc("json", "ledger_request", jvParams.toStyledString())[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::status] == "error"); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'ledger_index', not number."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'ledger_index', not number."); } // the purpose in this test is to force the ledger expiration/out of // date check to trigger env.timeKeeper().adjustCloseTime(weeks{3}); - auto const result = - env.rpc(apiVersion, "ledger_request", "1")[jss::result]; + auto const result = env.rpc(apiVersion, "ledger_request", "1")[jss::result]; BEAST_EXPECT(result[jss::status] == "error"); if (apiVersion == 1) { BEAST_EXPECT(result[jss::error] == "noCurrent"); - BEAST_EXPECT( - result[jss::error_message] == "Current ledger is unavailable."); + BEAST_EXPECT(result[jss::error_message] == "Current ledger is unavailable."); } else { BEAST_EXPECT(result[jss::error] == "notSynced"); - BEAST_EXPECT( - result[jss::error_message] == "Not synced to the network."); + BEAST_EXPECT(result[jss::error_message] == "Not synced to the network."); } } @@ -339,8 +299,7 @@ public: auto result = env.rpc("ledger_request", "1")[jss::result]; BEAST_EXPECT(result[jss::ledger][jss::ledger_index] == "1"); - BEAST_EXPECT( - result[jss::ledger][jss::total_coins] == "100000000000000000"); + BEAST_EXPECT(result[jss::ledger][jss::total_coins] == "100000000000000000"); BEAST_EXPECT(result[jss::ledger][jss::closed] == true); BEAST_EXPECT(result[jss::ledger][jss::ledger_hash] == hash1); BEAST_EXPECT(result[jss::ledger][jss::parent_hash] == zerohash); @@ -370,8 +329,7 @@ public: { testLedgerRequest(); testEvolution(); - forAllApiVersions( - std::bind_front(&LedgerRequest_test::testBadInput, this)); + forAllApiVersions(std::bind_front(&LedgerRequest_test::testBadInput, this)); testMoreThan256Closed(); testNonAdmin(); } diff --git a/src/test/rpc/ManifestRPC_test.cpp b/src/test/rpc/ManifestRPC_test.cpp index 96326e010f..f42fdd7164 100644 --- a/src/test/rpc/ManifestRPC_test.cpp +++ b/src/test/rpc/ManifestRPC_test.cpp @@ -25,9 +25,7 @@ public: { // manifest with no public key auto const info = env.rpc("json", "manifest", "{ }"); - BEAST_EXPECT( - info[jss::result][jss::error_message] == - "Missing field 'public_key'."); + BEAST_EXPECT(info[jss::result][jss::error_message] == "Missing field 'public_key'."); } { // manifest with malformed public key @@ -36,8 +34,7 @@ public: "manifest", "{ \"public_key\": " "\"abcdef12345\"}"); - BEAST_EXPECT( - info[jss::result][jss::error_message] == "Invalid parameters."); + BEAST_EXPECT(info[jss::result][jss::error_message] == "Invalid parameters."); } } @@ -47,8 +44,7 @@ public: testcase("Lookup"); using namespace jtx; - std::string const key = - "n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7"; + std::string const key = "n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7"; Env env{*this, envconfig([&key](std::unique_ptr cfg) { cfg->section(SECTION_VALIDATORS).append(key); return cfg; diff --git a/src/test/rpc/NoRippleCheck_test.cpp b/src/test/rpc/NoRippleCheck_test.cpp index 7ed2cd8fd1..0857561fda 100644 --- a/src/test/rpc/NoRippleCheck_test.cpp +++ b/src/test/rpc/NoRippleCheck_test.cpp @@ -29,18 +29,15 @@ class NoRippleCheck_test : public beast::unit_test::suite env.close(); { // missing account field - auto const result = - env.rpc("json", "noripple_check", "{}")[jss::result]; + auto const result = env.rpc("json", "noripple_check", "{}")[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT( - result[jss::error_message] == "Missing field 'account'."); + BEAST_EXPECT(result[jss::error_message] == "Missing field 'account'."); } { // missing role field Json::Value params; params[jss::account] = alice.human(); - auto const result = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto const result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::error_message] == "Missing field 'role'."); } @@ -51,11 +48,9 @@ class NoRippleCheck_test : public beast::unit_test::suite Json::Value params; params[jss::account] = param; params[jss::role] = "user"; - auto jrr = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto jrr = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jrr[jss::error_message] == "Invalid field 'account'."); + BEAST_EXPECT(jrr[jss::error_message] == "Invalid field 'account'."); }; testInvalidAccountParam(1); @@ -70,8 +65,7 @@ class NoRippleCheck_test : public beast::unit_test::suite Json::Value params; params[jss::account] = alice.human(); params[jss::role] = "not_a_role"; - auto const result = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto const result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::error_message] == "Invalid field 'role'."); } @@ -81,12 +75,9 @@ class NoRippleCheck_test : public beast::unit_test::suite params[jss::account] = alice.human(); params[jss::role] = "user"; params[jss::limit] = -1; - auto const result = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto const result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'limit', not unsigned integer."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'limit', not unsigned integer."); } { // invalid ledger (hash) @@ -94,12 +85,9 @@ class NoRippleCheck_test : public beast::unit_test::suite params[jss::account] = alice.human(); params[jss::role] = "user"; params[jss::ledger_hash] = 1; - auto const result = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto const result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'ledger_hash', not hex string."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'ledger_hash', not hex string."); } { // account not found @@ -107,8 +95,7 @@ class NoRippleCheck_test : public beast::unit_test::suite params[jss::account] = Account{"nobody"}.human(); params[jss::role] = "user"; params[jss::ledger] = "current"; - auto const result = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto const result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "actNotFound"); BEAST_EXPECT(result[jss::error_message] == "Account not found."); } @@ -119,8 +106,7 @@ class NoRippleCheck_test : public beast::unit_test::suite params[jss::account] = toBase58(TokenType::NodePrivate, alice.sk()); params[jss::role] = "user"; params[jss::ledger] = "current"; - auto const result = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto const result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "actMalformed"); BEAST_EXPECT(result[jss::error_message] == "Account malformed."); } @@ -132,8 +118,7 @@ class NoRippleCheck_test : public beast::unit_test::suite params[jss::role] = "user"; params[jss::ledger] = "current"; params[jss::ledger_hash] = "ABCDEF"; - auto const result = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto const result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT( result[jss::error_message] == @@ -147,20 +132,17 @@ class NoRippleCheck_test : public beast::unit_test::suite params[jss::account] = Account{"nobody"}.human(); params[jss::role] = "user"; params[jss::ledger] = Json::objectValue; - auto const result = env.rpc( - "json", "noripple_check", to_string(params))[jss::result]; + auto const result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT( - result[jss::error_message] == - "Invalid field 'ledger', not string or number."); + BEAST_EXPECT(result[jss::error_message] == "Invalid field 'ledger', not string or number."); } } void testBasic(bool user, bool problems) { - testcase << "Request noripple_check for " << (user ? "user" : "gateway") - << " role, expect" << (problems ? "" : " no") << " problems"; + testcase << "Request noripple_check for " << (user ? "user" : "gateway") << " role, expect" + << (problems ? "" : " no") << " problems"; using namespace test::jtx; Env env{*this}; @@ -185,8 +167,7 @@ class NoRippleCheck_test : public beast::unit_test::suite params[jss::account] = alice.human(); params[jss::role] = (user ? "user" : "gateway"); params[jss::ledger] = "current"; - auto result = - env.rpc("json", "noripple_check", to_string(params))[jss::result]; + auto result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; auto const pa = result["problems"]; if (!BEAST_EXPECT(pa.isArray())) @@ -199,17 +180,13 @@ class NoRippleCheck_test : public beast::unit_test::suite if (user) { - BEAST_EXPECT(boost::starts_with( - pa[0u].asString(), "You appear to have set")); - BEAST_EXPECT(boost::starts_with( - pa[1u].asString(), "You should probably set")); + BEAST_EXPECT(boost::starts_with(pa[0u].asString(), "You appear to have set")); + BEAST_EXPECT(boost::starts_with(pa[1u].asString(), "You should probably set")); } else { - BEAST_EXPECT(boost::starts_with( - pa[0u].asString(), "You should immediately set")); - BEAST_EXPECT( - boost::starts_with(pa[1u].asString(), "You should clear")); + BEAST_EXPECT(boost::starts_with(pa[0u].asString(), "You should immediately set")); + BEAST_EXPECT(boost::starts_with(pa[1u].asString(), "You should clear")); } } else @@ -220,8 +197,7 @@ class NoRippleCheck_test : public beast::unit_test::suite // now make a second request asking for the relevant transactions this // time. params[jss::transactions] = true; - result = - env.rpc("json", "noripple_check", to_string(params))[jss::result]; + result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; if (!BEAST_EXPECT(result[jss::transactions].isArray())) return; @@ -237,12 +213,8 @@ class NoRippleCheck_test : public beast::unit_test::suite BEAST_EXPECT(txs[0u][jss::TransactionType] == jss::AccountSet); } - BEAST_EXPECT( - result[jss::transactions][txs.size() - 1][jss::Account] == - alice.human()); - BEAST_EXPECT( - result[jss::transactions][txs.size() - 1] - [jss::TransactionType] == jss::TrustSet); + BEAST_EXPECT(result[jss::transactions][txs.size() - 1][jss::Account] == alice.human()); + BEAST_EXPECT(result[jss::transactions][txs.size() - 1][jss::TransactionType] == jss::TrustSet); BEAST_EXPECT( result[jss::transactions][txs.size() - 1][jss::LimitAmount] == gw["USD"](100).value().getJson(JsonOptions::none)); @@ -269,8 +241,7 @@ class NoRippleCheckLimits_test : public beast::unit_test::suite void testLimits(bool admin) { - testcase << "Check limits in returned data, " - << (admin ? "admin" : "non-admin"); + testcase << "Check limits in returned data, " << (admin ? "admin" : "non-admin"); using namespace test::jtx; @@ -292,15 +263,14 @@ class NoRippleCheckLimits_test : public beast::unit_test::suite using namespace xrpl::Resource; using namespace std::chrono; using namespace beast::IP; - auto c = env.app().getResourceManager().newInboundEndpoint( - Endpoint::from_string(test::getEnvLocalhostAddr())); + auto c = + env.app().getResourceManager().newInboundEndpoint(Endpoint::from_string(test::getEnvLocalhostAddr())); // if we go above the warning threshold, reset if (c.balance() > warningThreshold) { using ct = beast::abstract_clock; - c.entry().local_balance = - DecayingSample{steady_clock::now()}; + c.entry().local_balance = DecayingSample{steady_clock::now()}; } }; @@ -315,23 +285,14 @@ class NoRippleCheckLimits_test : public beast::unit_test::suite auto const baseFee = env.current()->fees().base; env(pay(env.master, gw, XRP(1000)), seq(autofill), - fee(toDrops( - txq.getMetrics(*env.current()).openLedgerFeeLevel, - baseFee) + - 1), + fee(toDrops(txq.getMetrics(*env.current()).openLedgerFeeLevel, baseFee) + 1), sig(autofill)); env(fset(gw, asfDefaultRipple), seq(autofill), - fee(toDrops( - txq.getMetrics(*env.current()).openLedgerFeeLevel, - baseFee) + - 1), + fee(toDrops(txq.getMetrics(*env.current()).openLedgerFeeLevel, baseFee) + 1), sig(autofill)); env(trust(alice, gw["USD"](10)), - fee(toDrops( - txq.getMetrics(*env.current()).openLedgerFeeLevel, - baseFee) + - 1)); + fee(toDrops(txq.getMetrics(*env.current()).openLedgerFeeLevel, baseFee) + 1)); env.close(); } @@ -340,33 +301,28 @@ class NoRippleCheckLimits_test : public beast::unit_test::suite params[jss::account] = alice.human(); params[jss::role] = "user"; params[jss::ledger] = "current"; - auto result = - env.rpc("json", "noripple_check", to_string(params))[jss::result]; + auto result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result["problems"].size() == 301); // one below minimum params[jss::limit] = 9; - result = - env.rpc("json", "noripple_check", to_string(params))[jss::result]; + result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result["problems"].size() == (admin ? 10 : 11)); // at minimum params[jss::limit] = 10; - result = - env.rpc("json", "noripple_check", to_string(params))[jss::result]; + result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result["problems"].size() == 11); // at max params[jss::limit] = 400; - result = - env.rpc("json", "noripple_check", to_string(params))[jss::result]; + result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result["problems"].size() == 401); // at max+1 params[jss::limit] = 401; - result = - env.rpc("json", "noripple_check", to_string(params))[jss::result]; + result = env.rpc("json", "noripple_check", to_string(params))[jss::result]; BEAST_EXPECT(result["problems"].size() == (admin ? 402 : 401)); } diff --git a/src/test/rpc/NoRipple_test.cpp b/src/test/rpc/NoRipple_test.cpp index 040ceaaa29..07b0c95e92 100644 --- a/src/test/rpc/NoRipple_test.cpp +++ b/src/test/rpc/NoRipple_test.cpp @@ -33,16 +33,11 @@ public: for (auto SetOrClear : {true, false}) { // Create a trust line with no-ripple flag setting - env(trust( - gw, - USD(100), - alice, - SetOrClear ? tfSetNoRipple : tfClearNoRipple)); + env(trust(gw, USD(100), alice, SetOrClear ? tfSetNoRipple : tfClearNoRipple)); env.close(); // Check no-ripple flag on sender 'gateway' - Json::Value lines{ - env.rpc("json", "account_lines", to_string(account_gw))}; + Json::Value lines{env.rpc("json", "account_lines", to_string(account_gw))}; auto const& gline0 = lines[jss::result][jss::lines][0u]; BEAST_EXPECT(gline0[jss::no_ripple].asBool() == SetOrClear); @@ -96,8 +91,7 @@ public: return dest_amt; }(); - auto const resp = - env.rpc("json", "ripple_path_find", to_string(params)); + auto const resp = env.rpc("json", "ripple_path_find", to_string(params)); BEAST_EXPECT(resp[jss::result][jss::alternatives].size() == 1); auto getAccountLines = [&env](Account const& acct) { @@ -167,8 +161,7 @@ public: return dest_amt; }(); - Json::Value const resp{ - env.rpc("json", "ripple_path_find", to_string(params))}; + Json::Value const resp{env.rpc("json", "ripple_path_find", to_string(params))}; BEAST_EXPECT(resp[jss::result][jss::alternatives].size() == 0); env(pay(alice, carol, bob["USD"](50)), ter(tecPATH_DRY)); @@ -239,13 +232,11 @@ public: params[jss::role] = "gateway"; params[jss::transactions] = "asdf"; - auto lines = - env.rpc("json", "noripple_check", to_string(params)); + auto lines = env.rpc("json", "noripple_check", to_string(params)); if (apiVersion < 2u) BEAST_EXPECT(lines[jss::result][jss::status] == "success"); else - BEAST_EXPECT( - lines[jss::result][jss::error] == "invalidParams"); + BEAST_EXPECT(lines[jss::result][jss::error] == "invalidParams"); } } } @@ -256,9 +247,7 @@ public: testSetAndClear(); auto withFeatsTests = [this](FeatureBitset features) { - forAllApiVersions([&, this](unsigned testVersion) { - testDefaultRipple(features, testVersion); - }); + forAllApiVersions([&, this](unsigned testVersion) { testDefaultRipple(features, testVersion); }); testNegativeBalance(features); testPairwise(features); }; diff --git a/src/test/rpc/OwnerInfo_test.cpp b/src/test/rpc/OwnerInfo_test.cpp index b47b529680..9e3fee04c2 100644 --- a/src/test/rpc/OwnerInfo_test.cpp +++ b/src/test/rpc/OwnerInfo_test.cpp @@ -22,32 +22,21 @@ class OwnerInfo_test : public beast::unit_test::suite env.close(); { // missing account field - auto const result = - env.rpc("json", "owner_info", "{}")[jss::result]; + auto const result = env.rpc("json", "owner_info", "{}")[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); - BEAST_EXPECT( - result[jss::error_message] == "Missing field 'account'."); + BEAST_EXPECT(result[jss::error_message] == "Missing field 'account'."); } { // ask for empty account Json::Value params; params[jss::account] = ""; - auto const result = - env.rpc("json", "owner_info", to_string(params))[jss::result]; - if (BEAST_EXPECT( - result.isMember(jss::accepted) && - result.isMember(jss::current))) + auto const result = env.rpc("json", "owner_info", to_string(params))[jss::result]; + if (BEAST_EXPECT(result.isMember(jss::accepted) && result.isMember(jss::current))) { - BEAST_EXPECT( - result[jss::accepted][jss::error] == "actMalformed"); - BEAST_EXPECT( - result[jss::accepted][jss::error_message] == - "Account malformed."); - BEAST_EXPECT( - result[jss::current][jss::error] == "actMalformed"); - BEAST_EXPECT( - result[jss::current][jss::error_message] == - "Account malformed."); + BEAST_EXPECT(result[jss::accepted][jss::error] == "actMalformed"); + BEAST_EXPECT(result[jss::accepted][jss::error_message] == "Account malformed."); + BEAST_EXPECT(result[jss::current][jss::error] == "actMalformed"); + BEAST_EXPECT(result[jss::current][jss::error_message] == "Account malformed."); } } @@ -56,8 +45,7 @@ class OwnerInfo_test : public beast::unit_test::suite // (deprecated) does not return an error, just empty fields. Json::Value params; params[jss::account] = Account{"bob"}.human(); - auto const result = - env.rpc("json", "owner_info", to_string(params))[jss::result]; + auto const result = env.rpc("json", "owner_info", to_string(params))[jss::result]; BEAST_EXPECT(result[jss::accepted] == Json::objectValue); BEAST_EXPECT(result[jss::current] == Json::objectValue); BEAST_EXPECT(result[jss::status] == "success"); @@ -89,11 +77,8 @@ class OwnerInfo_test : public beast::unit_test::suite Json::Value params; params[jss::account] = alice.human(); - auto const result = - env.rpc("json", "owner_info", to_string(params))[jss::result]; - if (!BEAST_EXPECT( - result.isMember(jss::accepted) && - result.isMember(jss::current))) + auto const result = env.rpc("json", "owner_info", to_string(params))[jss::result]; + if (!BEAST_EXPECT(result.isMember(jss::accepted) && result.isMember(jss::current))) { return; } @@ -107,27 +92,15 @@ class OwnerInfo_test : public beast::unit_test::suite BEAST_EXPECT( lines[0u][sfBalance.fieldName] == - (STAmount{Issue{to_currency("CNY"), noAccount()}, 0} - .value() - .getJson(JsonOptions::none))); - BEAST_EXPECT( - lines[0u][sfHighLimit.fieldName] == - alice["CNY"](1000).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - lines[0u][sfLowLimit.fieldName] == - gw["CNY"](0).value().getJson(JsonOptions::none)); + (STAmount{Issue{to_currency("CNY"), noAccount()}, 0}.value().getJson(JsonOptions::none))); + BEAST_EXPECT(lines[0u][sfHighLimit.fieldName] == alice["CNY"](1000).value().getJson(JsonOptions::none)); + BEAST_EXPECT(lines[0u][sfLowLimit.fieldName] == gw["CNY"](0).value().getJson(JsonOptions::none)); BEAST_EXPECT( lines[1u][sfBalance.fieldName] == - (STAmount{Issue{to_currency("USD"), noAccount()}, 0} - .value() - .getJson(JsonOptions::none))); - BEAST_EXPECT( - lines[1u][sfHighLimit.fieldName] == - alice["USD"](1000).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - lines[1u][sfLowLimit.fieldName] == - USD(0).value().getJson(JsonOptions::none)); + (STAmount{Issue{to_currency("USD"), noAccount()}, 0}.value().getJson(JsonOptions::none))); + BEAST_EXPECT(lines[1u][sfHighLimit.fieldName] == alice["USD"](1000).value().getJson(JsonOptions::none)); + BEAST_EXPECT(lines[1u][sfLowLimit.fieldName] == USD(0).value().getJson(JsonOptions::none)); if (!BEAST_EXPECT(result[jss::accepted].isMember(jss::offers))) return; @@ -136,12 +109,8 @@ class OwnerInfo_test : public beast::unit_test::suite return; BEAST_EXPECT(offers[0u][jss::Account] == alice.human()); - BEAST_EXPECT( - offers[0u][sfTakerGets.fieldName] == - XRP(1000).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - offers[0u][sfTakerPays.fieldName] == - USD(1).value().getJson(JsonOptions::none)); + BEAST_EXPECT(offers[0u][sfTakerGets.fieldName] == XRP(1000).value().getJson(JsonOptions::none)); + BEAST_EXPECT(offers[0u][sfTakerPays.fieldName] == USD(1).value().getJson(JsonOptions::none)); // current ledger entry if (!BEAST_EXPECT(result[jss::current].isMember(jss::ripple_lines))) @@ -152,27 +121,15 @@ class OwnerInfo_test : public beast::unit_test::suite BEAST_EXPECT( lines[0u][sfBalance.fieldName] == - (STAmount{Issue{to_currency("CNY"), noAccount()}, -50} - .value() - .getJson(JsonOptions::none))); - BEAST_EXPECT( - lines[0u][sfHighLimit.fieldName] == - alice["CNY"](1000).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - lines[0u][sfLowLimit.fieldName] == - gw["CNY"](0).value().getJson(JsonOptions::none)); + (STAmount{Issue{to_currency("CNY"), noAccount()}, -50}.value().getJson(JsonOptions::none))); + BEAST_EXPECT(lines[0u][sfHighLimit.fieldName] == alice["CNY"](1000).value().getJson(JsonOptions::none)); + BEAST_EXPECT(lines[0u][sfLowLimit.fieldName] == gw["CNY"](0).value().getJson(JsonOptions::none)); BEAST_EXPECT( lines[1u][sfBalance.fieldName] == - (STAmount{Issue{to_currency("USD"), noAccount()}, -50} - .value() - .getJson(JsonOptions::none))); - BEAST_EXPECT( - lines[1u][sfHighLimit.fieldName] == - alice["USD"](1000).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - lines[1u][sfLowLimit.fieldName] == - gw["USD"](0).value().getJson(JsonOptions::none)); + (STAmount{Issue{to_currency("USD"), noAccount()}, -50}.value().getJson(JsonOptions::none))); + BEAST_EXPECT(lines[1u][sfHighLimit.fieldName] == alice["USD"](1000).value().getJson(JsonOptions::none)); + BEAST_EXPECT(lines[1u][sfLowLimit.fieldName] == gw["USD"](0).value().getJson(JsonOptions::none)); if (!BEAST_EXPECT(result[jss::current].isMember(jss::offers))) return; @@ -183,12 +140,8 @@ class OwnerInfo_test : public beast::unit_test::suite BEAST_EXPECT(offers[1u] == result[jss::accepted][jss::offers][0u]); BEAST_EXPECT(offers[0u][jss::Account] == alice.human()); - BEAST_EXPECT( - offers[0u][sfTakerGets.fieldName] == - XRP(1000).value().getJson(JsonOptions::none)); - BEAST_EXPECT( - offers[0u][sfTakerPays.fieldName] == - CNY(2).value().getJson(JsonOptions::none)); + BEAST_EXPECT(offers[0u][sfTakerGets.fieldName] == XRP(1000).value().getJson(JsonOptions::none)); + BEAST_EXPECT(offers[0u][sfTakerPays.fieldName] == CNY(2).value().getJson(JsonOptions::none)); } public: diff --git a/src/test/rpc/Peers_test.cpp b/src/test/rpc/Peers_test.cpp index 639f5e98cb..8e4e560f3e 100644 --- a/src/test/rpc/Peers_test.cpp +++ b/src/test/rpc/Peers_test.cpp @@ -22,24 +22,20 @@ class Peers_test : public beast::unit_test::suite // without modification of the cluster, expect an empty set // from this request auto peers = env.rpc("peers")[jss::result]; - BEAST_EXPECT( - peers.isMember(jss::cluster) && peers[jss::cluster].size() == 0); + BEAST_EXPECT(peers.isMember(jss::cluster) && peers[jss::cluster].size() == 0); BEAST_EXPECT(peers.isMember(jss::peers) && peers[jss::peers].isNull()); // insert some nodes in to the cluster std::unordered_map nodes; for (auto i = 0; i < 3; ++i) { - auto kp = generateKeyPair( - KeyType::secp256k1, generateSeed("seed" + std::to_string(i))); + auto kp = generateKeyPair(KeyType::secp256k1, generateSeed("seed" + std::to_string(i))); std::string name = "Node " + std::to_string(i); using namespace std::chrono_literals; - env.app().cluster().update( - kp.first, name, 200, env.timeKeeper().now() - 10s); - nodes.insert(std::make_pair( - toBase58(TokenType::NodePublic, kp.first), name)); + env.app().cluster().update(kp.first, name, 200, env.timeKeeper().now() - 10s); + nodes.insert(std::make_pair(toBase58(TokenType::NodePublic, kp.first), name)); } // make request, verify nodes we created match @@ -49,9 +45,7 @@ class Peers_test : public beast::unit_test::suite return; if (!BEAST_EXPECT(peers[jss::cluster].size() == nodes.size())) return; - for (auto it = peers[jss::cluster].begin(); - it != peers[jss::cluster].end(); - ++it) + for (auto it = peers[jss::cluster].begin(); it != peers[jss::cluster].end(); ++it) { auto key = it.key().asString(); auto search = nodes.find(key); diff --git a/src/test/rpc/RPCCall_test.cpp b/src/test/rpc/RPCCall_test.cpp index 85402ff024..26f7ed0f18 100644 --- a/src/test/rpc/RPCCall_test.cpp +++ b/src/test/rpc/RPCCall_test.cpp @@ -37,11 +37,7 @@ struct RPCCallTestData std::initializer_list const& args_, Exception throwsWhat_, char const* exp_) - : description(description_) - , line(line_) - , args(args_) - , throwsWhat(throwsWhat_) - , exp(1, exp_) + : description(description_), line(line_), args(args_), throwsWhat(throwsWhat_), exp(1, exp_) { } @@ -51,11 +47,7 @@ struct RPCCallTestData std::initializer_list const& args_, Exception throwsWhat_, std::initializer_list exp_) - : description(description_) - , line(line_) - , args(args_) - , throwsWhat(throwsWhat_) - , exp(exp_) + : description(description_), line(line_), args(args_), throwsWhat(throwsWhat_), exp(exp_) { } @@ -86,9 +78,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_channels: account and ledger hash.", __LINE__, - {"account_channels", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "rD5MbavGfiSC5m7mkxy1FANuT7s3HxqpoF"}, + {"account_channels", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "rD5MbavGfiSC5m7mkxy1FANuT7s3HxqpoF"}, RPCCallTestData::no_exception, R"({ "method" : "account_channels", @@ -102,9 +92,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_channels: account and ledger index.", __LINE__, - {"account_channels", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "r9emE59aTWb85t64dAebKrxYMBTpzK5yR7"}, + {"account_channels", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "r9emE59aTWb85t64dAebKrxYMBTpzK5yR7"}, RPCCallTestData::no_exception, R"({ "method" : "account_channels", @@ -118,9 +106,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_channels: two accounts.", __LINE__, - {"account_channels", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA"}, + {"account_channels", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA"}, RPCCallTestData::no_exception, R"({ "method" : "account_channels", @@ -152,10 +138,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_channels: two accounts and ledger index.", __LINE__, - {"account_channels", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", - "90210"}, + {"account_channels", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "90210"}, RPCCallTestData::no_exception, R"({ "method" : "account_channels", @@ -308,11 +291,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_currencies: too many arguments.", __LINE__, - {"account_currencies", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "current", - "spare1", - "spare2"}, + {"account_currencies", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "current", "spare1", "spare2"}, RPCCallTestData::no_exception, R"({ "method" : "account_currencies", @@ -449,11 +428,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_info: too many arguments.", __LINE__, - {"account_info", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "current", - "extra1", - "extra2"}, + {"account_info", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "current", "extra1", "extra2"}, RPCCallTestData::no_exception, R"({ "method" : "account_info", @@ -502,9 +477,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_lines: peer.", __LINE__, - {"account_lines", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA"}, + {"account_lines", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA"}, RPCCallTestData::no_exception, R"({ "method" : "account_lines", @@ -518,10 +491,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_lines: peer and numeric ledger index.", __LINE__, - {"account_lines", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", - "888888888"}, + {"account_lines", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "888888888"}, RPCCallTestData::no_exception, R"({ "method" : "account_lines", @@ -536,10 +506,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_lines: peer and text ledger index.", __LINE__, - {"account_lines", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", - "closed"}, + {"account_lines", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "closed"}, RPCCallTestData::no_exception, R"({ "method" : "account_lines", @@ -688,10 +655,7 @@ static RPCCallTestData const rpcCallTestArray[] = { { "account_lines: invalid ledger selector.", __LINE__, - {"account_lines", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", - "not_a_ledger"}, + {"account_lines", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "not_a_ledger"}, RPCCallTestData::no_exception, R"({ "method" : "account_lines", @@ -1006,10 +970,7 @@ static RPCCallTestData const rpcCallTestArray[] = { {// Note: I believe this _ought_ to be detected as too many arguments. "account_offers: four arguments.", __LINE__, - {"account_offers", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "current", - "extra"}, + {"account_offers", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "current", "extra"}, RPCCallTestData::no_exception, R"({ "method" : "account_offers", @@ -1128,12 +1089,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_tx: ledger_index plus trailing params.", __LINE__, - {"account_tx", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "707", - "descending", - "binary", - "count"}, + {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "707", "descending", "binary", "count"}, RPCCallTestData::no_exception, R"({ "method" : "account_tx", @@ -1165,13 +1121,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_tx: ledger_index_min and _max plus trailing params.", __LINE__, - {"account_tx", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "-1", - "413", - "binary", - "count", - "descending"}, + {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "-1", "413", "binary", "count", "descending"}, RPCCallTestData::no_exception, R"({ "method" : "account_tx", @@ -1205,14 +1155,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_tx: ledger_index_min and _max, limit, trailing args.", __LINE__, - {"account_tx", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "247", - "-1", - "300", - "count", - "descending", - "binary"}, + {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "247", "-1", "300", "count", "descending", "binary"}, RPCCallTestData::no_exception, R"({ "method" : "account_tx", @@ -1231,12 +1174,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_tx: ledger_index_min and _max plus limit and offset.", __LINE__, - {"account_tx", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "589", - "590", - "67", - "45"}, + {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "589", "590", "67", "45"}, RPCCallTestData::no_exception, R"({ "method" : "account_tx", @@ -1253,14 +1191,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"account_tx: ledger_index_min and _max, limit, offset, trailing.", __LINE__, - {"account_tx", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "589", - "590", - "67", - "45", - "descending", - "count"}, + {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "589", "590", "67", "45", "descending", "count"}, RPCCallTestData::no_exception, R"({ "method" : "account_tx", @@ -1396,11 +1327,7 @@ static RPCCallTestData const rpcCallTestArray[] = { // Note: this really shouldn't throw, but does at the moment. "account_tx: non-integer offset.", __LINE__, - {"account_tx", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "-1", - "-1", - "decending"}, + {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "-1", "-1", "decending"}, RPCCallTestData::bad_cast, R"()", }, @@ -1408,26 +1335,14 @@ static RPCCallTestData const rpcCallTestArray[] = { // Note: this really shouldn't throw, but does at the moment. "account_tx: non-integer limit.", __LINE__, - {"account_tx", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "-1", - "-1", - "300", - "false"}, + {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "-1", "-1", "300", "false"}, RPCCallTestData::bad_cast, R"()", }, {// Note: this really shouldn't throw, but does at the moment. "account_tx: RIPD-1570.", __LINE__, - {"account_tx", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "-1", - "-1", - "2", - "false", - "false", - "false"}, + {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "-1", "-1", "2", "false", "false", "false"}, RPCCallTestData::bad_cast, R"()"}, @@ -1502,11 +1417,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"book_offers: add issuer and numeric ledger index.", __LINE__, - {"book_offers", - "USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "EUR", - "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", - "666"}, + {"book_offers", "USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "EUR", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "666"}, RPCCallTestData::no_exception, R"({ "method" : "book_offers", @@ -1527,11 +1438,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"book_offers: add issuer and text ledger index.", __LINE__, - {"book_offers", - "USD", - "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", - "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", - "current"}, + {"book_offers", "USD", "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "current"}, RPCCallTestData::no_exception, R"({ "method" : "book_offers", @@ -2425,10 +2332,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"deposit_authorized: with text ledger index.", __LINE__, - {"deposit_authorized", - "source_account_NotValidated", - "destination_account_NotValidated", - "validated"}, + {"deposit_authorized", "source_account_NotValidated", "destination_account_NotValidated", "validated"}, RPCCallTestData::no_exception, R"({ "method" : "deposit_authorized", @@ -2761,9 +2665,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"gateway_balances: 1 hotwallet.", __LINE__, - {"gateway_balances", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "hotwallet_is_not_validated"}, + {"gateway_balances", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "hotwallet_is_not_validated"}, RPCCallTestData::no_exception, R"({ "method" : "gateway_balances", @@ -2934,11 +2836,7 @@ static RPCCallTestData const rpcCallTestArray[] = { }, RPCCallTestData::bad_cast, R"()"}, - {"get_counts: count too large.", - __LINE__, - {"get_counts", "4294967296"}, - RPCCallTestData::bad_cast, - R"()"}, + {"get_counts: count too large.", __LINE__, {"get_counts", "4294967296"}, RPCCallTestData::bad_cast, R"()"}, // json // ------------------------------------------------------------------------ @@ -3165,9 +3063,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"json2: too many arguments.", __LINE__, - {"json2", - R"({"jsonrpc":"2.0","ripplerpc":"2.0","id":"A1","method":"call_this"})", - "extra"}, + {"json2", R"({"jsonrpc":"2.0","ripplerpc":"2.0","id":"A1","method":"call_this"})", "extra"}, RPCCallTestData::no_exception, R"({ "method" : "json2", @@ -3463,8 +3359,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"ledger: ledger hash.", __LINE__, - {"ledger", - "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789"}, + {"ledger", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789"}, RPCCallTestData::no_exception, R"({ "method" : "ledger", @@ -3645,8 +3540,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"ledger_header: ledger hash.", __LINE__, - {"ledger_header", - "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789"}, + {"ledger_header", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789"}, RPCCallTestData::no_exception, R"({ "method" : "ledger_header", @@ -3744,8 +3638,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"ledger_request: ledger hash.", __LINE__, - {"ledger_request", - "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789"}, + {"ledger_request", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789"}, RPCCallTestData::no_exception, R"({ "method" : "ledger_request", @@ -4253,10 +4146,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"peer_reservations_add: too many arguments.", __LINE__, - {"peer_reservations_add", - "public_key_string", - "public_key_description", - "spare"}, + {"peer_reservations_add", "public_key_string", "public_key_description", "spare"}, RPCCallTestData::no_exception, R"({ "method" : "peer_reservations_add", @@ -4300,10 +4190,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"peer_reservations_del: too many arguments.", __LINE__, - {"peer_reservations_del", - "public_key_string", - "public_key_description", - "spare"}, + {"peer_reservations_del", "public_key_string", "public_key_description", "spare"}, RPCCallTestData::no_exception, R"({ "method" : "peer_reservations_del", @@ -4650,12 +4537,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"sign: too many arguments.", __LINE__, - {"sign", - "my_secret", - R"({"json_argument":true})", - "offline", - "CounterpartySignature", - "extra"}, + {"sign", "my_secret", R"({"json_argument":true})", "offline", "CounterpartySignature", "extra"}, RPCCallTestData::no_exception, R"({ "method" : "sign", @@ -4730,11 +4612,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"sign_for: offline.", __LINE__, - {"sign_for", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "my_secret", - R"({"json_argument":true})", - "offline"}, + {"sign_for", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "my_secret", R"({"json_argument":true})", "offline"}, RPCCallTestData::no_exception, R"({ "method" : "sign_for", @@ -4770,12 +4648,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"sign_for: too many arguments.", __LINE__, - {"sign_for", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "my_secret", - R"({"json_argument":true})", - "offline", - "extra"}, + {"sign_for", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "my_secret", R"({"json_argument":true})", "offline", "extra"}, RPCCallTestData::no_exception, R"({ "method" : "sign_for", @@ -4808,11 +4681,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"sign_for: invalid final argument.", __LINE__, - {"sign_for", - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - "my_secret", - R"({"json_argument":true})", - "ofline"}, + {"sign_for", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "my_secret", R"({"json_argument":true})", "ofline"}, RPCCallTestData::no_exception, R"({ "method" : "sign_for", @@ -4915,12 +4784,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"submit: too many arguments.", __LINE__, - {"submit", - "my_secret", - R"({"json_argument":true})", - "offline", - "CounterpartySignature", - "extra"}, + {"submit", "my_secret", R"({"json_argument":true})", "offline", "CounterpartySignature", "extra"}, RPCCallTestData::no_exception, R"({ "method" : "submit", @@ -5185,9 +5049,7 @@ static RPCCallTestData const rpcCallTestArray[] = { // ----------------------------------------------------------- {"transaction_entry: ledger index.", __LINE__, - {"transaction_entry", - "0123456789ABCDEFGHIJKLMNOPQRSTUV0123456789ABCDEFGHIJKLMNOPQRSTUV", - "4294967295"}, + {"transaction_entry", "0123456789ABCDEFGHIJKLMNOPQRSTUV0123456789ABCDEFGHIJKLMNOPQRSTUV", "4294967295"}, RPCCallTestData::no_exception, R"({ "method" : "transaction_entry", @@ -5201,9 +5063,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"transaction_entry: text ledger index.", __LINE__, - {"transaction_entry", - "0123456789ABCDEFGHIJKLMNOPQRSTUV0123456789ABCDEFGHIJKLMNOPQRSTUV", - "current"}, + {"transaction_entry", "0123456789ABCDEFGHIJKLMNOPQRSTUV0123456789ABCDEFGHIJKLMNOPQRSTUV", "current"}, RPCCallTestData::no_exception, R"({ "method" : "transaction_entry", @@ -5250,10 +5110,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"transaction_entry: too many arguments.", __LINE__, - {"transaction_entry", - "0123456789ABCDEFGHIJKLMNOPQRSTUV0123456789ABCDEFGHIJKLMNOPQRSTUV", - "validated", - "extra"}, + {"transaction_entry", "0123456789ABCDEFGHIJKLMNOPQRSTUV0123456789ABCDEFGHIJKLMNOPQRSTUV", "validated", "extra"}, RPCCallTestData::no_exception, R"({ "method" : "transaction_entry", @@ -5716,13 +5573,7 @@ static RPCCallTestData const rpcCallTestArray[] = { })"}, {"internal: with parameters.", __LINE__, - {"internal", - "command_name", - "string_arg", - "1", - "-1", - "4294967296", - "3.14159"}, + {"internal", "command_name", "string_arg", "1", "-1", "4294967296", "3.14159"}, RPCCallTestData::no_exception, R"({ "method" : "internal", @@ -5908,13 +5759,10 @@ public: testRPCCall(unsigned apiVersion) { testcase << "RPCCall API version " << apiVersion; - if (!BEAST_EXPECT( - apiVersion >= RPC::apiMinimumSupportedVersion && - apiVersion <= RPC::apiMaximumValidVersion)) + if (!BEAST_EXPECT(apiVersion >= RPC::apiMinimumSupportedVersion && apiVersion <= RPC::apiMaximumValidVersion)) return; - test::jtx::Env env( - *this, makeNetworkConfig(11111)); // Used only for its Journal. + test::jtx::Env env(*this, makeNetworkConfig(11111)); // Used only for its Journal. // For each RPCCall test. for (RPCCallTestData const& rpcCallTest : rpcCallTestArray) @@ -5922,12 +5770,9 @@ public: if (!BEAST_EXPECT(!rpcCallTest.exp.empty())) break; - std::vector const args{ - rpcCallTest.args.begin(), rpcCallTest.args.end()}; + std::vector const args{rpcCallTest.args.begin(), rpcCallTest.args.end()}; - char const* const expVersioned = - (apiVersion - RPC::apiMinimumSupportedVersion) < - rpcCallTest.exp.size() + char const* const expVersioned = (apiVersion - RPC::apiMinimumSupportedVersion) < rpcCallTest.exp.size() ? rpcCallTest.exp[apiVersion - RPC::apiMinimumSupportedVersion] : rpcCallTest.exp.back(); @@ -5940,8 +5785,7 @@ public: } catch (std::bad_cast const&) { - if ((rpcCallTest.throwsWhat == RPCCallTestData::bad_cast) && - (std::strlen(expVersioned) == 0)) + if ((rpcCallTest.throwsWhat == RPCCallTestData::bad_cast) && (std::strlen(expVersioned) == 0)) { pass(); } @@ -5954,14 +5798,12 @@ public: } Json::Value exp; - Json::Reader{}.parse( - updateAPIVersionString(expVersioned, apiVersion), exp); + Json::Reader{}.parse(updateAPIVersionString(expVersioned, apiVersion), exp); // Lambda to remove the "params[0u]:error_code" field if present. // Error codes are not expected to be stable between releases. auto rmErrorCode = [](Json::Value& json) { - if (json.isMember(jss::params) && json[jss::params].isArray() && - json[jss::params].size() > 0 && + if (json.isMember(jss::params) && json[jss::params].isArray() && json[jss::params].size() > 0 && json[jss::params][0u].isObject()) { json[jss::params][0u].removeMember(jss::error_code); @@ -5971,8 +5813,7 @@ public: rmErrorCode(exp); // Pass if we didn't expect a throw and we got what we expected. - if ((rpcCallTest.throwsWhat == RPCCallTestData::no_exception) && - (got == exp)) + if ((rpcCallTest.throwsWhat == RPCCallTestData::no_exception) && (got == exp)) { pass(); } diff --git a/src/test/rpc/RPCOverload_test.cpp b/src/test/rpc/RPCOverload_test.cpp index d05dba4606..c8f02cd0a3 100644 --- a/src/test/rpc/RPCOverload_test.cpp +++ b/src/test/rpc/RPCOverload_test.cpp @@ -27,9 +27,8 @@ public: Account const bob{"bob"}; env.fund(XRP(10000), alice, bob); - std::unique_ptr client = useWS - ? makeWSClient(env.app().config()) - : makeJSONRPCClient(env.app().config()); + std::unique_ptr client = + useWS ? makeWSClient(env.app().config()) : makeJSONRPCClient(env.app().config()); Json::Value tx = Json::objectValue; tx[jss::tx_json] = pay(alice, bob, XRP(1)); @@ -47,8 +46,7 @@ public: // When booted, we just get a null json response if (jv.isNull()) booted = true; - else if (!(jv.isMember(jss::status) && - (jv[jss::status] == "success"))) + else if (!(jv.isMember(jss::status) && (jv[jss::status] == "success"))) { // Don't use BEAST_EXPECT above b/c it will be called a // non-deterministic number of times and the number of tests run diff --git a/src/test/rpc/RobustTransaction_test.cpp b/src/test/rpc/RobustTransaction_test.cpp index b0d0cdafd5..0934543fe0 100644 --- a/src/test/rpc/RobustTransaction_test.cpp +++ b/src/test/rpc/RobustTransaction_test.cpp @@ -30,10 +30,8 @@ public: BEAST_EXPECT(jv[jss::status] == "success"); 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::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); } } @@ -47,14 +45,11 @@ public: auto jv = wsc->invoke("submit", payment); 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::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::engine_result] == "tefMAX_LEDGER"); + BEAST_EXPECT(jv[jss::result][jss::engine_result] == "tefMAX_LEDGER"); // Submit past sequence transaction payment[jss::tx_json] = pay("alice", "bob", XRP(1)); @@ -62,10 +57,8 @@ public: jv = wsc->invoke("submit", payment); 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::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::engine_result] == "tefPAST_SEQ"); @@ -75,10 +68,8 @@ public: jv = wsc->invoke("submit", payment); 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::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::engine_result] == "terPRE_SEQ"); @@ -88,10 +79,8 @@ public: jv = wsc->invoke("submit", payment); 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::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::engine_result] == "tesSUCCESS"); @@ -103,10 +92,8 @@ public: jv = wsc->invoke("ledger_accept"); 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::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].isMember(jss::ledger_current_index)); @@ -115,17 +102,13 @@ public: { // Check balances BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - auto const& ff = jv[jss::meta]["AffectedNodes"][1u] - ["ModifiedNode"]["FinalFields"]; - return ff[jss::Account] == Account("bob").human() && - ff["Balance"] == "10001000000"; + auto const& ff = jv[jss::meta]["AffectedNodes"][1u]["ModifiedNode"]["FinalFields"]; + return ff[jss::Account] == Account("bob").human() && ff["Balance"] == "10001000000"; })); BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - auto const& ff = jv[jss::meta]["AffectedNodes"][1u] - ["ModifiedNode"]["FinalFields"]; - return ff[jss::Account] == Account("bob").human() && - ff["Balance"] == "10002000000"; + auto const& ff = jv[jss::meta]["AffectedNodes"][1u]["ModifiedNode"]["FinalFields"]; + return ff[jss::Account] == Account("bob").human() && ff["Balance"] == "10002000000"; })); } @@ -137,10 +120,8 @@ public: jv = wsc->invoke("unsubscribe", jv); 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::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"); @@ -175,10 +156,8 @@ public: jv = wsc->invoke("submit", jv); 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::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::engine_result] == "tesSUCCESS"); @@ -200,16 +179,14 @@ public: jv = wsc->invoke("account_tx", jv); 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::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); } // Check balance - auto ff = jv[jss::result][jss::transactions][0u][jss::meta] - ["AffectedNodes"][1u]["ModifiedNode"]["FinalFields"]; + auto ff = + jv[jss::result][jss::transactions][0u][jss::meta]["AffectedNodes"][1u]["ModifiedNode"]["FinalFields"]; BEAST_EXPECT(ff[jss::Account] == Account("bob").human()); BEAST_EXPECT(ff["Balance"] == "10001000000"); } @@ -233,10 +210,8 @@ public: jv = wsc->invoke("submit", jv); 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::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::engine_result] == "tesSUCCESS"); @@ -245,10 +220,8 @@ public: jv = wsc->invoke("ledger_accept"); 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::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].isMember(jss::ledger_current_index)); @@ -266,11 +239,8 @@ public: jv = wsc->invoke("subscribe", jv); 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::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"); @@ -282,22 +252,16 @@ public: auto jv = wsc->invoke("ledger_accept"); 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::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].isMember(jss::ledger_current_index)); + BEAST_EXPECT(jv[jss::result].isMember(jss::ledger_current_index)); // Wait for the jobqueue to process everything env.app().getJobQueue().rendezvous(); - BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jval) { - return jval[jss::type] == "ledgerClosed"; - })); + BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jval) { return jval[jss::type] == "ledgerClosed"; })); } { @@ -308,11 +272,8 @@ public: jv = wsc->invoke("unsubscribe", jv); 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::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"); @@ -330,11 +291,8 @@ public: jv = wsc->invoke("subscribe", jv); 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::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"); @@ -346,22 +304,16 @@ public: auto jv = wsc->invoke("ledger_accept"); 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::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].isMember(jss::ledger_current_index)); + BEAST_EXPECT(jv[jss::result].isMember(jss::ledger_current_index)); // Wait for the jobqueue to process everything env.app().getJobQueue().rendezvous(); - BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jval) { - return jval[jss::type] == "ledgerClosed"; - })); + BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jval) { return jval[jss::type] == "ledgerClosed"; })); } { @@ -372,11 +324,8 @@ public: jv = wsc->invoke("unsubscribe", jv); 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::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"); @@ -393,16 +342,14 @@ public: jv = wsc->invoke("account_tx", jv); 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::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); } // Check balance - auto ff = jv[jss::result][jss::transactions][0u][jss::meta] - ["AffectedNodes"][1u]["ModifiedNode"]["FinalFields"]; + auto ff = + jv[jss::result][jss::transactions][0u][jss::meta]["AffectedNodes"][1u]["ModifiedNode"]["FinalFields"]; BEAST_EXPECT(ff[jss::Account] == Account("bob").human()); BEAST_EXPECT(ff["Balance"] == "10001000000"); } @@ -426,10 +373,8 @@ public: jv = wsc->invoke("subscribe", jv); 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::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"); @@ -440,15 +385,12 @@ public: Json::Value jv; jv[jss::secret] = toBase58(generateSeed("alice")); jv[jss::tx_json] = fset("alice", 0); - jv[jss::tx_json][jss::Fee] = - static_cast(env.current()->fees().base.drops()); + jv[jss::tx_json][jss::Fee] = static_cast(env.current()->fees().base.drops()); jv = wsc->invoke("submit", jv); 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::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::engine_result] == "tesSUCCESS"); @@ -456,10 +398,8 @@ public: { // Check stream update - BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::transaction][jss::TransactionType] == - jss::AccountSet; - })); + BEAST_EXPECT(wsc->findMsg( + 5s, [&](auto const& jv) { return jv[jss::transaction][jss::TransactionType] == jss::AccountSet; })); } { @@ -470,10 +410,8 @@ public: jv = wsc->invoke("unsubscribe", jv); 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::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"); diff --git a/src/test/rpc/Roles_test.cpp b/src/test/rpc/Roles_test.cpp index 4fa99b432b..1750532a10 100644 --- a/src/test/rpc/Roles_test.cpp +++ b/src/test/rpc/Roles_test.cpp @@ -29,27 +29,21 @@ class Roles_test : public beast::unit_test::suite Env env(*this); BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "admin"); - BEAST_EXPECT(makeWSClient(env.app().config()) - ->invoke("ping")["result"]["unlimited"] - .asBool()); + BEAST_EXPECT(makeWSClient(env.app().config())->invoke("ping")["result"]["unlimited"].asBool()); } { Env env{*this, envconfig(no_admin)}; BEAST_EXPECT(!env.rpc("ping")["result"].isMember("role")); - auto wsRes = - makeWSClient(env.app().config())->invoke("ping")["result"]; - BEAST_EXPECT( - !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); + auto wsRes = makeWSClient(env.app().config())->invoke("ping")["result"]; + BEAST_EXPECT(!wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); } { Env env{*this, envconfig(secure_gateway)}; BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "proxied"); - auto wsRes = - makeWSClient(env.app().config())->invoke("ping")["result"]; - BEAST_EXPECT( - !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); + auto wsRes = makeWSClient(env.app().config())->invoke("ping")["result"]; + BEAST_EXPECT(!wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); std::unordered_map headers; Json::Value rpcRes; @@ -112,10 +106,8 @@ class Roles_test : public beast::unit_test::suite BEAST_EXPECT(rpcRes["ip"] == "99.88.77.66"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); - wsRes = makeWSClient(env.app().config(), true, 2, headers) - ->invoke("ping")["result"]; - BEAST_EXPECT( - !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); + wsRes = makeWSClient(env.app().config(), true, 2, headers)->invoke("ping")["result"]; + BEAST_EXPECT(!wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); std::string const name = "xrposhi"; headers["X-User"] = name; @@ -124,18 +116,15 @@ class Roles_test : public beast::unit_test::suite BEAST_EXPECT(rpcRes["username"] == name); BEAST_EXPECT(rpcRes["ip"] == "99.88.77.66"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); - wsRes = makeWSClient(env.app().config(), true, 2, headers) - ->invoke("ping")["result"]; + wsRes = makeWSClient(env.app().config(), true, 2, headers)->invoke("ping")["result"]; BEAST_EXPECT(wsRes["unlimited"].asBool()); // IPv6 tests. headers = {}; - headers["X-Forwarded-For"] = - "2001:db8:3333:4444:5555:6666:7777:8888"; + headers["X-Forwarded-For"] = "2001:db8:3333:4444:5555:6666:7777:8888"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); headers["X-Forwarded-For"] = @@ -143,16 +132,13 @@ class Roles_test : public beast::unit_test::suite "g:h:i:j:k:l"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); - headers["X-Forwarded-For"] = - "[2001:db8:3333:4444:5555:6666:7777:8888]"; + headers["X-Forwarded-For"] = "[2001:db8:3333:4444:5555:6666:7777:8888]"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); headers["X-Forwarded-For"] = @@ -160,21 +146,17 @@ class Roles_test : public beast::unit_test::suite "[g:h:i:j:k:l]"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); headers = {}; - headers["Forwarded"] = - "for=\"[2001:db8:3333:4444:5555:6666:7777:aaaa]\""; + headers["Forwarded"] = "for=\"[2001:db8:3333:4444:5555:6666:7777:aaaa]\""; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:aaaa"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:aaaa"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); - headers["Forwarded"] = - "For=\"[2001:db8:bb:cc:dd:ee:ff::]:2345\", for=99.00.11.22"; + headers["Forwarded"] = "For=\"[2001:db8:bb:cc:dd:ee:ff::]:2345\", for=99.00.11.22"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); BEAST_EXPECT(rpcRes["ip"] == "2001:db8:bb:cc:dd:ee:ff::"); @@ -193,8 +175,7 @@ class Roles_test : public beast::unit_test::suite headers["X-Forwarded-For"] = "2001:db8:3333:4444:5555:6666:1.2.3.4"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:1.2.3.4"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:1.2.3.4"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); headers["X-Forwarded-For"] = @@ -202,16 +183,13 @@ class Roles_test : public beast::unit_test::suite "g:h:i:j:k:l"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:5.6.7.8"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:5.6.7.8"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); - headers["X-Forwarded-For"] = - "[2001:db8:3333:4444:5555:6666:9.10.11.12]"; + headers["X-Forwarded-For"] = "[2001:db8:3333:4444:5555:6666:9.10.11.12]"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:9.10.11.12"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:9.10.11.12"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); headers["X-Forwarded-For"] = @@ -219,21 +197,17 @@ class Roles_test : public beast::unit_test::suite "[g:h:i:j:k:l]"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:13.14.15.16"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:13.14.15.16"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); headers = {}; - headers["Forwarded"] = - "for=\"[2001:db8:3333:4444:5555:6666:20.19.18.17]\""; + headers["Forwarded"] = "for=\"[2001:db8:3333:4444:5555:6666:20.19.18.17]\""; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); - BEAST_EXPECT( - rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:20.19.18.17"); + BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:20.19.18.17"); BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString())); - headers["Forwarded"] = - "For=\"[2001:db8:bb:cc::24.23.22.21]\", for=99.00.11.22"; + headers["Forwarded"] = "For=\"[2001:db8:bb:cc::24.23.22.21]\", for=99.00.11.22"; rpcRes = env.rpc(headers, "ping")["result"]; BEAST_EXPECT(rpcRes["role"] == "proxied"); BEAST_EXPECT(rpcRes["ip"] == "2001:db8:bb:cc::24.23.22.21"); @@ -251,18 +225,14 @@ class Roles_test : public beast::unit_test::suite { Env env{*this, envconfig(admin_localnet)}; BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "admin"); - BEAST_EXPECT(makeWSClient(env.app().config()) - ->invoke("ping")["result"]["unlimited"] - .asBool()); + BEAST_EXPECT(makeWSClient(env.app().config())->invoke("ping")["result"]["unlimited"].asBool()); } { Env env{*this, envconfig(secure_gateway_localnet)}; BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "proxied"); - auto wsRes = - makeWSClient(env.app().config())->invoke("ping")["result"]; - BEAST_EXPECT( - !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); + auto wsRes = makeWSClient(env.app().config())->invoke("ping")["result"]; + BEAST_EXPECT(!wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool()); std::unordered_map headers; headers["X-Forwarded-For"] = "12.34.56.78"; diff --git a/src/test/rpc/ServerDefinitions_test.cpp b/src/test/rpc/ServerDefinitions_test.cpp index ae2cccd908..20bd6ba363 100644 --- a/src/test/rpc/ServerDefinitions_test.cpp +++ b/src/test/rpc/ServerDefinitions_test.cpp @@ -24,8 +24,7 @@ public: BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(result[jss::result].isMember(jss::FIELDS)); BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES)); - BEAST_EXPECT( - result[jss::result].isMember(jss::TRANSACTION_RESULTS)); + BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_RESULTS)); BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_TYPES)); BEAST_EXPECT(result[jss::result].isMember(jss::TYPES)); BEAST_EXPECT(result[jss::result].isMember(jss::hash)); @@ -36,26 +35,17 @@ public: { auto const firstField = result[jss::result][jss::FIELDS][0u]; BEAST_EXPECT(firstField[0u].asString() == "Generic"); - BEAST_EXPECT( - firstField[1][jss::isSerialized].asBool() == false); - BEAST_EXPECT( - firstField[1][jss::isSigningField].asBool() == false); + BEAST_EXPECT(firstField[1][jss::isSerialized].asBool() == false); + BEAST_EXPECT(firstField[1][jss::isSigningField].asBool() == false); BEAST_EXPECT(firstField[1][jss::isVLEncoded].asBool() == false); BEAST_EXPECT(firstField[1][jss::nth].asUInt() == 0); BEAST_EXPECT(firstField[1][jss::type].asString() == "Unknown"); } - BEAST_EXPECT( - result[jss::result][jss::LEDGER_ENTRY_TYPES]["AccountRoot"] - .asUInt() == 97); - BEAST_EXPECT( - result[jss::result][jss::TRANSACTION_RESULTS]["tecDIR_FULL"] - .asUInt() == 121); - BEAST_EXPECT( - result[jss::result][jss::TRANSACTION_TYPES]["Payment"] - .asUInt() == 0); - BEAST_EXPECT( - result[jss::result][jss::TYPES]["AccountID"].asUInt() == 8); + BEAST_EXPECT(result[jss::result][jss::LEDGER_ENTRY_TYPES]["AccountRoot"].asUInt() == 97); + BEAST_EXPECT(result[jss::result][jss::TRANSACTION_RESULTS]["tecDIR_FULL"].asUInt() == 121); + BEAST_EXPECT(result[jss::result][jss::TRANSACTION_TYPES]["Payment"].asUInt() == 0); + BEAST_EXPECT(result[jss::result][jss::TYPES]["AccountID"].asUInt() == 8); // check exception SFields { @@ -96,18 +86,14 @@ public: Env env(*this); auto const firstResult = env.rpc("server_definitions"); auto const hash = firstResult[jss::result][jss::hash].asString(); - auto const hashParam = - std::string("{ ") + "\"hash\": \"" + hash + "\"}"; + auto const hashParam = std::string("{ ") + "\"hash\": \"" + hash + "\"}"; - auto const result = - env.rpc("json", "server_definitions", hashParam); + auto const result = env.rpc("json", "server_definitions", hashParam); BEAST_EXPECT(!result[jss::result].isMember(jss::error)); BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(!result[jss::result].isMember(jss::FIELDS)); - BEAST_EXPECT( - !result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES)); - BEAST_EXPECT( - !result[jss::result].isMember(jss::TRANSACTION_RESULTS)); + BEAST_EXPECT(!result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES)); + BEAST_EXPECT(!result[jss::result].isMember(jss::TRANSACTION_RESULTS)); BEAST_EXPECT(!result[jss::result].isMember(jss::TRANSACTION_TYPES)); BEAST_EXPECT(!result[jss::result].isMember(jss::TYPES)); BEAST_EXPECT(result[jss::result].isMember(jss::hash)); @@ -119,17 +105,14 @@ public: std::string const hash = "54296160385A27154BFA70A239DD8E8FD4CC2DB7BA32D970BA3A5B132CF749" "D1"; - auto const hashParam = - std::string("{ ") + "\"hash\": \"" + hash + "\"}"; + auto const hashParam = std::string("{ ") + "\"hash\": \"" + hash + "\"}"; - auto const result = - env.rpc("json", "server_definitions", hashParam); + auto const result = env.rpc("json", "server_definitions", hashParam); BEAST_EXPECT(!result[jss::result].isMember(jss::error)); BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(result[jss::result].isMember(jss::FIELDS)); BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES)); - BEAST_EXPECT( - result[jss::result].isMember(jss::TRANSACTION_RESULTS)); + BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_RESULTS)); BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_TYPES)); BEAST_EXPECT(result[jss::result].isMember(jss::TYPES)); BEAST_EXPECT(result[jss::result].isMember(jss::hash)); diff --git a/src/test/rpc/ServerInfo_test.cpp b/src/test/rpc/ServerInfo_test.cpp index 27b554e38b..054c3e563a 100644 --- a/src/test/rpc/ServerInfo_test.cpp +++ b/src/test/rpc/ServerInfo_test.cpp @@ -13,8 +13,7 @@ namespace xrpl { namespace test { namespace validator_data { -static auto const public_key = - "nHBt9fsb4849WmZiCds4r5TXyBeQjqnH5kzPtqgMAQMgi39YZRPa"; +static auto const public_key = "nHBt9fsb4849WmZiCds4r5TXyBeQjqnH5kzPtqgMAQMgi39YZRPa"; static auto const token = "eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3NDdiNT\n" @@ -52,8 +51,7 @@ protocol = wss2 admin = 127.0.0.1 )rippleConfig"); - p->loadFromString(boost::str( - toLoad % validator_data::token % validator_data::public_key)); + p->loadFromString(boost::str(toLoad % validator_data::token % validator_data::public_key)); setupConfigForUnitTests(*p); @@ -81,16 +79,12 @@ admin = 127.0.0.1 if (info.isMember(jss::git)) { auto const& git = info[jss::git]; + BEAST_EXPECT(git.isMember(jss::hash) || git.isMember(jss::branch)); BEAST_EXPECT( - git.isMember(jss::hash) || git.isMember(jss::branch)); - BEAST_EXPECT( - !git.isMember(jss::hash) || - (git[jss::hash].isString() && - git[jss::hash].asString().size() == 40)); + !git.isMember(jss::hash) || (git[jss::hash].isString() && git[jss::hash].asString().size() == 40)); BEAST_EXPECT( !git.isMember(jss::branch) || - (git[jss::branch].isString() && - git[jss::branch].asString().size() != 0)); + (git[jss::branch].isString() && git[jss::branch].asString().size() != 0)); } } @@ -98,8 +92,7 @@ admin = 127.0.0.1 Env env(*this); // Call NetworkOPs directly and set the admin flag to false. - auto const result = - env.app().getOPs().getServerInfo(true, false, 0); + auto const result = env.app().getOPs().getServerInfo(true, false, 0); // Expect that the admin ports are not included in the result. auto const& ports = result[jss::ports]; BEAST_EXPECT(ports.isArray() && ports.size() == 0); @@ -112,8 +105,7 @@ admin = 127.0.0.1 auto const& config = env.app().config(); auto const rpc_port = config["port_rpc"].get("port"); - auto const grpc_port = - config[SECTION_PORT_GRPC].get("port"); + auto const grpc_port = config[SECTION_PORT_GRPC].get("port"); auto const ws_port = config["port_ws"].get("port"); BEAST_EXPECT(grpc_port); BEAST_EXPECT(rpc_port); @@ -123,9 +115,7 @@ admin = 127.0.0.1 BEAST_EXPECT(!result[jss::result].isMember(jss::error)); BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(result[jss::result].isMember(jss::info)); - BEAST_EXPECT( - result[jss::result][jss::info][jss::pubkey_validator] == - validator_data::public_key); + BEAST_EXPECT(result[jss::result][jss::info][jss::pubkey_validator] == validator_data::public_key); auto const& ports = result[jss::result][jss::info][jss::ports]; BEAST_EXPECT(ports.isArray() && ports.size() == 3); diff --git a/src/test/rpc/Simulate_test.cpp b/src/test/rpc/Simulate_test.cpp index 7fe90fb9a1..194b0296ec 100644 --- a/src/test/rpc/Simulate_test.cpp +++ b/src/test/rpc/Simulate_test.cpp @@ -31,8 +31,7 @@ class Simulate_test : public beast::unit_test::suite BEAST_EXPECT(result.isMember(jss::engine_result)); BEAST_EXPECT(result.isMember(jss::engine_result_code)); BEAST_EXPECT(result.isMember(jss::engine_result_message)); - BEAST_EXPECT( - result.isMember(jss::tx_json) || result.isMember(jss::tx_blob)); + BEAST_EXPECT(result.isMember(jss::tx_json) || result.isMember(jss::tx_blob)); Json::Value tx_json; if (result.isMember(jss::tx_json)) @@ -43,18 +42,14 @@ class Simulate_test : public beast::unit_test::suite { auto const unHexed = strUnHex(result[jss::tx_blob].asString()); SerialIter sitTrans(makeSlice(*unHexed)); - tx_json = STObject(std::ref(sitTrans), sfGeneric) - .getJson(JsonOptions::none); + tx_json = STObject(std::ref(sitTrans), sfGeneric).getJson(JsonOptions::none); } BEAST_EXPECT(tx_json[jss::TransactionType] == tx[jss::TransactionType]); BEAST_EXPECT(tx_json[jss::Account] == tx[jss::Account]); - BEAST_EXPECT( - tx_json[jss::SigningPubKey] == tx.get(jss::SigningPubKey, "")); - BEAST_EXPECT( - tx_json[jss::TxnSignature] == tx.get(jss::TxnSignature, "")); + BEAST_EXPECT(tx_json[jss::SigningPubKey] == tx.get(jss::SigningPubKey, "")); + BEAST_EXPECT(tx_json[jss::TxnSignature] == tx.get(jss::TxnSignature, "")); BEAST_EXPECT(tx_json[jss::Fee] == tx.get(jss::Fee, expectedFee)); - BEAST_EXPECT( - tx_json[jss::Sequence] == tx.get(jss::Sequence, expectedSequence)); + BEAST_EXPECT(tx_json[jss::Sequence] == tx.get(jss::Sequence, expectedSequence)); } void @@ -64,16 +59,14 @@ class Simulate_test : public beast::unit_test::suite int const expectedSequence, XRPAmount const& expectedFee) { - return checkBasicReturnValidity( - result, tx, expectedSequence, expectedFee.jsonClipped().asString()); + return checkBasicReturnValidity(result, tx, expectedSequence, expectedFee.jsonClipped().asString()); } void testTx( jtx::Env& env, Json::Value const& tx, - std::function const& - validate, + std::function const& validate, bool testSerialized = true) { env.close(); @@ -93,8 +86,7 @@ class Simulate_test : public beast::unit_test::suite // It is technically not a valid STObject, so the following line // will crash STParsedJSONObject const parsed(std::string(jss::tx_json), tx); - auto const tx_blob = - strHex(parsed.object->getSerializer().peekData()); + auto const tx_blob = strHex(parsed.object->getSerializer().peekData()); if (BEAST_EXPECT(parsed.object.has_value())) { Json::Value params; @@ -107,20 +99,15 @@ class Simulate_test : public beast::unit_test::suite validate(env.rpc("simulate", tx_blob, "binary"), tx); } - BEAST_EXPECTS( - env.current()->txCount() == 0, - std::to_string(env.current()->txCount())); + BEAST_EXPECTS(env.current()->txCount() == 0, std::to_string(env.current()->txCount())); } void testTxJsonMetadataField( jtx::Env& env, Json::Value const& tx, - std::function const& validate, + std::function const& + validate, Json::Value const& expectedMetadataKey, Json::Value const& expectedMetadataValue) { @@ -128,20 +115,10 @@ class Simulate_test : public beast::unit_test::suite Json::Value params; params[jss::tx_json] = tx; - validate( - env.rpc("json", "simulate", to_string(params)), - tx, - expectedMetadataKey, - expectedMetadataValue); - validate( - env.rpc("simulate", to_string(tx)), - tx, - expectedMetadataKey, - expectedMetadataValue); + validate(env.rpc("json", "simulate", to_string(params)), tx, expectedMetadataKey, expectedMetadataValue); + validate(env.rpc("simulate", to_string(tx)), tx, expectedMetadataKey, expectedMetadataValue); - BEAST_EXPECTS( - env.current()->txCount() == 0, - std::to_string(env.current()->txCount())); + BEAST_EXPECTS(env.current()->txCount() == 0, std::to_string(env.current()->txCount())); } Json::Value @@ -151,8 +128,7 @@ class Simulate_test : public beast::unit_test::suite { auto unHexed = strUnHex(txResult[jss::meta_blob].asString()); SerialIter sitTrans(makeSlice(*unHexed)); - return STObject(std::ref(sitTrans), sfGeneric) - .getJson(JsonOptions::none); + return STObject(std::ref(sitTrans), sfGeneric).getJson(JsonOptions::none); } return txResult[jss::meta]; @@ -171,9 +147,7 @@ class Simulate_test : public beast::unit_test::suite // No params Json::Value const params = Json::objectValue; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Neither `tx_blob` nor `tx_json` included."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Neither `tx_blob` nor `tx_json` included."); } { // Providing both `tx_json` and `tx_blob` @@ -182,9 +156,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_blob] = "1200"; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Can only include one of `tx_blob` and `tx_json`."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Can only include one of `tx_blob` and `tx_json`."); } { // `binary` isn't a boolean @@ -192,9 +164,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_blob] = "1200"; params[jss::binary] = "100"; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'binary'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'binary'."); } { // Invalid `tx_blob` @@ -202,9 +172,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_blob] = "12"; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'tx_blob'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx_blob'."); } { // Empty `tx_json` @@ -212,9 +180,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = Json::objectValue; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Missing field 'tx.TransactionType'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Missing field 'tx.TransactionType'."); } { // No tx.Account @@ -224,9 +190,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Missing field 'tx.Account'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Missing field 'tx.Account'."); } { // Empty `tx_blob` @@ -234,9 +198,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_blob] = ""; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'tx_blob'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx_blob'."); } { // Non-string `tx_blob` @@ -244,9 +206,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_blob] = 1.1; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'tx_blob'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx_blob'."); } { // Non-object `tx_json` @@ -254,9 +214,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = ""; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'tx_json', not object."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx_json', not object."); } { // `seed` field included @@ -267,9 +225,7 @@ class Simulate_test : public beast::unit_test::suite tx_json[jss::Account] = env.master.human(); params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'seed'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'seed'."); } { // `secret` field included @@ -280,9 +236,7 @@ class Simulate_test : public beast::unit_test::suite tx_json[jss::Account] = env.master.human(); params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'secret'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'secret'."); } { // `seed_hex` field included @@ -293,9 +247,7 @@ class Simulate_test : public beast::unit_test::suite tx_json[jss::Account] = env.master.human(); params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'seed_hex'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'seed_hex'."); } { // `passphrase` field included @@ -306,9 +258,7 @@ class Simulate_test : public beast::unit_test::suite tx_json[jss::Account] = env.master.human(); params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'passphrase'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'passphrase'."); } { // Invalid transaction @@ -319,9 +269,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_exception] == - "Field 'Destination' is required but missing."); + BEAST_EXPECT(resp[jss::result][jss::error_exception] == "Field 'Destination' is required but missing."); } { // Bad account @@ -333,11 +281,8 @@ class Simulate_test : public beast::unit_test::suite auto const resp = env.rpc("json", "simulate", to_string(params)); BEAST_EXPECTS( - resp[jss::result][jss::error] == "srcActMalformed", - resp[jss::result][jss::error].toStyledString()); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'tx.Account'."); + resp[jss::result][jss::error] == "srcActMalformed", resp[jss::result][jss::error].toStyledString()); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx.Account'."); } { // Account doesn't exist for Sequence autofill @@ -348,9 +293,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Source account not found."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Source account not found."); } { // Invalid Signers field @@ -362,9 +305,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'tx.Signers'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx.Signers'."); } { // Invalid Signers field @@ -377,9 +318,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Invalid field 'tx.Signers[0]'."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Invalid field 'tx.Signers[0]'."); } { // Invalid transaction @@ -391,9 +330,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Field 'tx_json.foo' is unknown."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Field 'tx_json.foo' is unknown."); } { // non-`"binary"` second param for CLI @@ -413,9 +350,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Transaction should not be signed."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Transaction should not be signed."); } { // Signed multisig transaction @@ -436,9 +371,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = tx_json; auto const resp = env.rpc("json", "simulate", to_string(params)); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == - "Transaction should not be signed."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Transaction should not be signed."); } } @@ -450,8 +383,7 @@ class Simulate_test : public beast::unit_test::suite using namespace jtx; Env env(*this, envconfig([](std::unique_ptr cfg) { - cfg->section("transaction_queue") - .set("minimum_txn_in_ledger_standalone", "3"); + cfg->section("transaction_queue").set("minimum_txn_in_ledger_standalone", "3"); return cfg; })); @@ -504,8 +436,7 @@ class Simulate_test : public beast::unit_test::suite params[jss::tx_json] = jt.jv; auto const resp = env.rpc("json", "simulate", to_string(params)); BEAST_EXPECT(resp[jss::result][jss::error] == "notImpl"); - BEAST_EXPECT( - resp[jss::result][jss::error_message] == "Not implemented."); + BEAST_EXPECT(resp[jss::result][jss::error_message] == "Not implemented."); } void @@ -521,44 +452,33 @@ class Simulate_test : public beast::unit_test::suite static auto const newDomain = "123ABC"; { - auto validateOutput = [&](Json::Value const& resp, - Json::Value const& tx) { + auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) { auto result = resp[jss::result]; - checkBasicReturnValidity( - result, tx, 1, env.current()->fees().base); + checkBasicReturnValidity(result, tx, 1, env.current()->fees().base); BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS"); BEAST_EXPECT(result[jss::engine_result_code] == 0); BEAST_EXPECT( - result[jss::engine_result_message] == - "The simulated transaction would have been applied."); + result[jss::engine_result_message] == "The simulated transaction would have been applied."); - if (BEAST_EXPECT( - result.isMember(jss::meta) || - result.isMember(jss::meta_blob))) + if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob))) { Json::Value const metadata = getJsonMetadata(result); - if (BEAST_EXPECT( - metadata.isMember(sfAffectedNodes.jsonName))) + if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName))) { - BEAST_EXPECT( - metadata[sfAffectedNodes.jsonName].size() == 1); + BEAST_EXPECT(metadata[sfAffectedNodes.jsonName].size() == 1); auto node = metadata[sfAffectedNodes.jsonName][0u]; - if (BEAST_EXPECT( - node.isMember(sfModifiedNode.jsonName))) + if (BEAST_EXPECT(node.isMember(sfModifiedNode.jsonName))) { auto modifiedNode = node[sfModifiedNode]; - BEAST_EXPECT( - modifiedNode[sfLedgerEntryType] == - "AccountRoot"); + BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot"); auto finalFields = modifiedNode[sfFinalFields]; BEAST_EXPECT(finalFields[sfDomain] == newDomain); } } BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0); - BEAST_EXPECT( - metadata[sfTransactionResult.jsonName] == "tesSUCCESS"); + BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tesSUCCESS"); } }; @@ -591,22 +511,16 @@ class Simulate_test : public beast::unit_test::suite Account const alice("alice"); { - std::function const& - testSimulation = [&](Json::Value const& resp, - Json::Value const& tx) { + std::function const& testSimulation = + [&](Json::Value const& resp, Json::Value const& tx) { auto result = resp[jss::result]; - checkBasicReturnValidity( - result, tx, 1, env.current()->fees().base); + checkBasicReturnValidity(result, tx, 1, env.current()->fees().base); BEAST_EXPECT(result[jss::engine_result] == "temBAD_AMOUNT"); BEAST_EXPECT(result[jss::engine_result_code] == -298); - BEAST_EXPECT( - result[jss::engine_result_message] == - "Malformed: Bad amount."); + BEAST_EXPECT(result[jss::engine_result_message] == "Malformed: Bad amount."); - BEAST_EXPECT( - !result.isMember(jss::meta) && - !result.isMember(jss::meta_blob)); + BEAST_EXPECT(!result.isMember(jss::meta) && !result.isMember(jss::meta_blob)); }; Json::Value tx; @@ -639,15 +553,12 @@ class Simulate_test : public beast::unit_test::suite Account const alice("alice"); { - std::function const& - testSimulation = [&](Json::Value const& resp, - Json::Value const& tx) { + std::function const& testSimulation = + [&](Json::Value const& resp, Json::Value const& tx) { auto result = resp[jss::result]; - checkBasicReturnValidity( - result, tx, 1, env.current()->fees().base); + checkBasicReturnValidity(result, tx, 1, env.current()->fees().base); - BEAST_EXPECT( - result[jss::engine_result] == "tecNO_DST_INSUF_XRP"); + BEAST_EXPECT(result[jss::engine_result] == "tecNO_DST_INSUF_XRP"); BEAST_EXPECT(result[jss::engine_result_code] == 125); BEAST_EXPECT( result[jss::engine_result_message] == @@ -655,38 +566,26 @@ class Simulate_test : public beast::unit_test::suite "create " "it."); - if (BEAST_EXPECT( - result.isMember(jss::meta) || - result.isMember(jss::meta_blob))) + if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob))) { Json::Value const metadata = getJsonMetadata(result); - if (BEAST_EXPECT( - metadata.isMember(sfAffectedNodes.jsonName))) + if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName))) { - BEAST_EXPECT( - metadata[sfAffectedNodes.jsonName].size() == 1); + BEAST_EXPECT(metadata[sfAffectedNodes.jsonName].size() == 1); auto node = metadata[sfAffectedNodes.jsonName][0u]; - if (BEAST_EXPECT( - node.isMember(sfModifiedNode.jsonName))) + if (BEAST_EXPECT(node.isMember(sfModifiedNode.jsonName))) { auto modifiedNode = node[sfModifiedNode]; - BEAST_EXPECT( - modifiedNode[sfLedgerEntryType] == - "AccountRoot"); + BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot"); auto finalFields = modifiedNode[sfFinalFields]; BEAST_EXPECT( finalFields[sfBalance] == - std::to_string( - 100'000'000'000'000'000 - - env.current()->fees().base.drops())); + std::to_string(100'000'000'000'000'000 - env.current()->fees().base.drops())); } } - BEAST_EXPECT( - metadata[sfTransactionIndex.jsonName] == 0); - BEAST_EXPECT( - metadata[sfTransactionResult.jsonName] == - "tecNO_DST_INSUF_XRP"); + BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0); + BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tecNO_DST_INSUF_XRP"); } }; @@ -729,48 +628,37 @@ class Simulate_test : public beast::unit_test::suite env.close(); { - auto validateOutput = [&](Json::Value const& resp, - Json::Value const& tx) { + auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) { auto result = resp[jss::result]; checkBasicReturnValidity( result, tx, env.seq(alice), - tx.isMember(jss::Signers) ? env.current()->fees().base * 2 - : env.current()->fees().base); + tx.isMember(jss::Signers) ? env.current()->fees().base * 2 : env.current()->fees().base); BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS"); BEAST_EXPECT(result[jss::engine_result_code] == 0); BEAST_EXPECT( - result[jss::engine_result_message] == - "The simulated transaction would have been applied."); + result[jss::engine_result_message] == "The simulated transaction would have been applied."); - if (BEAST_EXPECT( - result.isMember(jss::meta) || - result.isMember(jss::meta_blob))) + if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob))) { Json::Value const metadata = getJsonMetadata(result); - if (BEAST_EXPECT( - metadata.isMember(sfAffectedNodes.jsonName))) + if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName))) { - BEAST_EXPECT( - metadata[sfAffectedNodes.jsonName].size() == 1); + BEAST_EXPECT(metadata[sfAffectedNodes.jsonName].size() == 1); auto node = metadata[sfAffectedNodes.jsonName][0u]; - if (BEAST_EXPECT( - node.isMember(sfModifiedNode.jsonName))) + if (BEAST_EXPECT(node.isMember(sfModifiedNode.jsonName))) { auto modifiedNode = node[sfModifiedNode]; - BEAST_EXPECT( - modifiedNode[sfLedgerEntryType] == - "AccountRoot"); + BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot"); auto finalFields = modifiedNode[sfFinalFields]; BEAST_EXPECT(finalFields[sfDomain] == newDomain); } } BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0); - BEAST_EXPECT( - metadata[sfTransactionResult.jsonName] == "tesSUCCESS"); + BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tesSUCCESS"); } }; @@ -799,8 +687,7 @@ class Simulate_test : public beast::unit_test::suite tx[sfTxnSignature] = ""; tx[sfSequence] = env.seq(alice); // transaction requires a non-base fee - tx[sfFee] = - (env.current()->fees().base * 2).jsonClipped().asString(); + tx[sfFee] = (env.current()->fees().base * 2).jsonClipped().asString(); tx[sfSigners][0u][sfSigner][jss::SigningPubKey] = ""; tx[sfSigners][0u][sfSigner][jss::TxnSignature] = ""; @@ -823,27 +710,17 @@ class Simulate_test : public beast::unit_test::suite env.close(); { - std::function const& - testSimulation = - [&](Json::Value const& resp, Json::Value const& tx) { - auto result = resp[jss::result]; - checkBasicReturnValidity( - result, - tx, - env.seq(env.master), - env.current()->fees().base); + std::function const& testSimulation = + [&](Json::Value const& resp, Json::Value const& tx) { + auto result = resp[jss::result]; + checkBasicReturnValidity(result, tx, env.seq(env.master), env.current()->fees().base); - BEAST_EXPECT( - result[jss::engine_result] == "tefMASTER_DISABLED"); - BEAST_EXPECT(result[jss::engine_result_code] == -188); - BEAST_EXPECT( - result[jss::engine_result_message] == - "Master key is disabled."); + BEAST_EXPECT(result[jss::engine_result] == "tefMASTER_DISABLED"); + BEAST_EXPECT(result[jss::engine_result_code] == -188); + BEAST_EXPECT(result[jss::engine_result_message] == "Master key is disabled."); - BEAST_EXPECT( - !result.isMember(jss::meta) && - !result.isMember(jss::meta_blob)); - }; + BEAST_EXPECT(!result.isMember(jss::meta) && !result.isMember(jss::meta_blob)); + }; Json::Value tx; @@ -886,25 +763,16 @@ class Simulate_test : public beast::unit_test::suite env.close(); { - std::function const& - testSimulation = [&](Json::Value const& resp, - Json::Value const& tx) { + std::function const& testSimulation = + [&](Json::Value const& resp, Json::Value const& tx) { auto result = resp[jss::result]; - checkBasicReturnValidity( - result, - tx, - env.seq(env.master), - env.current()->fees().base * 2); + checkBasicReturnValidity(result, tx, env.seq(env.master), env.current()->fees().base * 2); BEAST_EXPECT(result[jss::engine_result] == "temINVALID"); BEAST_EXPECT(result[jss::engine_result_code] == -277); - BEAST_EXPECT( - result[jss::engine_result_message] == - "The transaction is ill-formed."); + BEAST_EXPECT(result[jss::engine_result_message] == "The transaction is ill-formed."); - BEAST_EXPECT( - !result.isMember(jss::meta) && - !result.isMember(jss::meta_blob)); + BEAST_EXPECT(!result.isMember(jss::meta) && !result.isMember(jss::meta_blob)); }; Json::Value tx; @@ -929,8 +797,7 @@ class Simulate_test : public beast::unit_test::suite tx[sfTxnSignature] = ""; tx[sfSequence] = env.seq(env.master); tx[sfFee] = env.current()->fees().base.jsonClipped().asString(); - tx[sfSigners][0u][sfSigner][jss::SigningPubKey] = - strHex(becky.pk().slice()); + tx[sfSigners][0u][sfSigner][jss::SigningPubKey] = strHex(becky.pk().slice()); tx[sfSigners][0u][sfSigner][jss::TxnSignature] = ""; // test without autofill @@ -957,23 +824,16 @@ class Simulate_test : public beast::unit_test::suite env(signers(alice, 1, {{becky, 1}, {carol, 1}})); { - auto validateOutput = [&](Json::Value const& resp, - Json::Value const& tx) { + auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) { auto result = resp[jss::result]; - checkBasicReturnValidity( - result, tx, env.seq(alice), env.current()->fees().base * 2); + checkBasicReturnValidity(result, tx, env.seq(alice), env.current()->fees().base * 2); BEAST_EXPECTS( - result[jss::engine_result] == "tefBAD_SIGNATURE", - result[jss::engine_result].toStyledString()); + result[jss::engine_result] == "tefBAD_SIGNATURE", result[jss::engine_result].toStyledString()); BEAST_EXPECT(result[jss::engine_result_code] == -186); - BEAST_EXPECT( - result[jss::engine_result_message] == - "A signature is provided for a non-signer."); + BEAST_EXPECT(result[jss::engine_result_message] == "A signature is provided for a non-signer."); - BEAST_EXPECT( - !result.isMember(jss::meta) && - !result.isMember(jss::meta_blob)); + BEAST_EXPECT(!result.isMember(jss::meta) && !result.isMember(jss::meta_blob)); }; Json::Value tx; @@ -998,8 +858,7 @@ class Simulate_test : public beast::unit_test::suite tx[sfTxnSignature] = ""; tx[sfSequence] = env.seq(alice); // transaction requires a non-base fee - tx[sfFee] = - (env.current()->fees().base * 2).jsonClipped().asString(); + tx[sfFee] = (env.current()->fees().base * 2).jsonClipped().asString(); tx[sfSigners][0u][sfSigner][jss::TxnSignature] = ""; // test without autofill @@ -1026,57 +885,40 @@ class Simulate_test : public beast::unit_test::suite auto const credType = "123ABC"; auto jv = credentials::create(subject, issuer, credType); - uint32_t const t = - env.current()->header().parentCloseTime.time_since_epoch().count(); + uint32_t const t = env.current()->header().parentCloseTime.time_since_epoch().count(); jv[sfExpiration.jsonName] = t; env(jv); env.close(); { - auto validateOutput = [&](Json::Value const& resp, - Json::Value const& tx) { + auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) { auto result = resp[jss::result]; - checkBasicReturnValidity( - result, tx, env.seq(subject), env.current()->fees().base); + checkBasicReturnValidity(result, tx, env.seq(subject), env.current()->fees().base); BEAST_EXPECT(result[jss::engine_result] == "tecEXPIRED"); BEAST_EXPECT(result[jss::engine_result_code] == 148); - BEAST_EXPECT( - result[jss::engine_result_message] == - "Expiration time is passed."); + BEAST_EXPECT(result[jss::engine_result_message] == "Expiration time is passed."); - if (BEAST_EXPECT( - result.isMember(jss::meta) || - result.isMember(jss::meta_blob))) + if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob))) { Json::Value const metadata = getJsonMetadata(result); - if (BEAST_EXPECT( - metadata.isMember(sfAffectedNodes.jsonName))) + if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName))) { - BEAST_EXPECT( - metadata[sfAffectedNodes.jsonName].size() == 5); + BEAST_EXPECT(metadata[sfAffectedNodes.jsonName].size() == 5); try { bool found = false; - for (auto const& node : - metadata[sfAffectedNodes.jsonName]) + for (auto const& node : metadata[sfAffectedNodes.jsonName]) { if (node.isMember(sfDeletedNode.jsonName) && - node[sfDeletedNode.jsonName] - [sfLedgerEntryType.jsonName] - .asString() == "Credential") + node[sfDeletedNode.jsonName][sfLedgerEntryType.jsonName].asString() == "Credential") { - auto const deleted = - node[sfDeletedNode.jsonName] - [sfFinalFields.jsonName]; - found = deleted[jss::Issuer] == - issuer.human() && - deleted[jss::Subject] == - subject.human() && - deleted["CredentialType"] == - strHex(std::string_view(credType)); + auto const deleted = node[sfDeletedNode.jsonName][sfFinalFields.jsonName]; + found = deleted[jss::Issuer] == issuer.human() && + deleted[jss::Subject] == subject.human() && + deleted["CredentialType"] == strHex(std::string_view(credType)); break; } } @@ -1088,8 +930,7 @@ class Simulate_test : public beast::unit_test::suite } } BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0); - BEAST_EXPECT( - metadata[sfTransactionResult.jsonName] == "tecEXPIRED"); + BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tecEXPIRED"); } }; @@ -1108,18 +949,14 @@ class Simulate_test : public beast::unit_test::suite } // check that expired credentials weren't deleted - auto const jle = - credentials::ledgerEntry(env, subject, issuer, credType); + auto const jle = credentials::ledgerEntry(env, subject, issuer, credType); BEAST_EXPECT( - jle.isObject() && jle.isMember(jss::result) && - !jle[jss::result].isMember(jss::error) && - jle[jss::result].isMember(jss::node) && - jle[jss::result][jss::node].isMember("LedgerEntryType") && + jle.isObject() && jle.isMember(jss::result) && !jle[jss::result].isMember(jss::error) && + jle[jss::result].isMember(jss::node) && jle[jss::result][jss::node].isMember("LedgerEntryType") && jle[jss::result][jss::node]["LedgerEntryType"] == jss::Credential && jle[jss::result][jss::node][jss::Issuer] == issuer.human() && jle[jss::result][jss::node][jss::Subject] == subject.human() && - jle[jss::result][jss::node]["CredentialType"] == - strHex(std::string_view(credType))); + jle[jss::result][jss::node]["CredentialType"] == strHex(std::string_view(credType))); BEAST_EXPECT(ownerCount(env, issuer) == 1); BEAST_EXPECT(ownerCount(env, subject) == 0); @@ -1138,44 +975,33 @@ class Simulate_test : public beast::unit_test::suite static auto const newDomain = "123ABC"; { - auto validateOutput = [&](Json::Value const& resp, - Json::Value const& tx) { + auto validateOutput = [&](Json::Value const& resp, Json::Value const& tx) { auto result = resp[jss::result]; - checkBasicReturnValidity( - result, tx, 1, env.current()->fees().base); + checkBasicReturnValidity(result, tx, 1, env.current()->fees().base); BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS"); BEAST_EXPECT(result[jss::engine_result_code] == 0); BEAST_EXPECT( - result[jss::engine_result_message] == - "The simulated transaction would have been applied."); + result[jss::engine_result_message] == "The simulated transaction would have been applied."); - if (BEAST_EXPECT( - result.isMember(jss::meta) || - result.isMember(jss::meta_blob))) + if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob))) { Json::Value const metadata = getJsonMetadata(result); - if (BEAST_EXPECT( - metadata.isMember(sfAffectedNodes.jsonName))) + if (BEAST_EXPECT(metadata.isMember(sfAffectedNodes.jsonName))) { - BEAST_EXPECT( - metadata[sfAffectedNodes.jsonName].size() == 1); + BEAST_EXPECT(metadata[sfAffectedNodes.jsonName].size() == 1); auto node = metadata[sfAffectedNodes.jsonName][0u]; - if (BEAST_EXPECT( - node.isMember(sfModifiedNode.jsonName))) + if (BEAST_EXPECT(node.isMember(sfModifiedNode.jsonName))) { auto modifiedNode = node[sfModifiedNode]; - BEAST_EXPECT( - modifiedNode[sfLedgerEntryType] == - "AccountRoot"); + BEAST_EXPECT(modifiedNode[sfLedgerEntryType] == "AccountRoot"); auto finalFields = modifiedNode[sfFinalFields]; BEAST_EXPECT(finalFields[sfDomain] == newDomain); } } BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0); - BEAST_EXPECT( - metadata[sfTransactionResult.jsonName] == "tesSUCCESS"); + BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tesSUCCESS"); } }; @@ -1221,37 +1047,27 @@ class Simulate_test : public beast::unit_test::suite env.close(NetClock::time_point{446000000s}); { - auto validateOutput = - [&](Json::Value const& resp, - Json::Value const& tx, - Json::Value const& expectedMetadataKey, - Json::Value const& expectedMetadataValue) { - auto result = resp[jss::result]; + auto validateOutput = [&](Json::Value const& resp, + Json::Value const& tx, + Json::Value const& expectedMetadataKey, + Json::Value const& expectedMetadataValue) { + auto result = resp[jss::result]; - BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS"); - BEAST_EXPECT(result[jss::engine_result_code] == 0); - BEAST_EXPECT( - result[jss::engine_result_message] == - "The simulated transaction would have been applied."); + BEAST_EXPECT(result[jss::engine_result] == "tesSUCCESS"); + BEAST_EXPECT(result[jss::engine_result_code] == 0); + BEAST_EXPECT( + result[jss::engine_result_message] == "The simulated transaction would have been applied."); - if (BEAST_EXPECT( - result.isMember(jss::meta) || - result.isMember(jss::meta_blob))) - { - Json::Value const metadata = getJsonMetadata(result); + if (BEAST_EXPECT(result.isMember(jss::meta) || result.isMember(jss::meta_blob))) + { + Json::Value const metadata = getJsonMetadata(result); - BEAST_EXPECT( - metadata[sfTransactionIndex.jsonName] == 0); - BEAST_EXPECT( - metadata[sfTransactionResult.jsonName] == - "tesSUCCESS"); - BEAST_EXPECT( - metadata.isMember(expectedMetadataKey.asString())); - BEAST_EXPECT( - metadata[expectedMetadataKey.asString()] == - expectedMetadataValue); - } - }; + BEAST_EXPECT(metadata[sfTransactionIndex.jsonName] == 0); + BEAST_EXPECT(metadata[sfTransactionResult.jsonName] == "tesSUCCESS"); + BEAST_EXPECT(metadata.isMember(expectedMetadataKey.asString())); + BEAST_EXPECT(metadata[expectedMetadataKey.asString()] == expectedMetadataValue); + } + }; { Json::Value tx; @@ -1261,8 +1077,7 @@ class Simulate_test : public beast::unit_test::suite tx[sfAmount] = "100"; // test delivered amount - testTxJsonMetadataField( - env, tx, validateOutput, jss::delivered_amount, "100"); + testTxJsonMetadataField(env, tx, validateOutput, jss::delivered_amount, "100"); } { @@ -1271,11 +1086,9 @@ class Simulate_test : public beast::unit_test::suite tx[jss::TransactionType] = jss::NFTokenMint; tx[sfNFTokenTaxon] = 1; - Json::Value nftokenId = - to_string(token::getNextID(env, alice, 1)); + Json::Value nftokenId = to_string(token::getNextID(env, alice, 1)); // test nft synthetic - testTxJsonMetadataField( - env, tx, validateOutput, jss::nftoken_id, nftokenId); + testTxJsonMetadataField(env, tx, validateOutput, jss::nftoken_id, nftokenId); } { @@ -1283,15 +1096,9 @@ class Simulate_test : public beast::unit_test::suite tx[jss::Account] = alice.human(); tx[jss::TransactionType] = jss::MPTokenIssuanceCreate; - Json::Value mptIssuanceId = - to_string(makeMptID(env.seq(alice), alice)); + Json::Value mptIssuanceId = to_string(makeMptID(env.seq(alice), alice)); // test mpt issuance id - testTxJsonMetadataField( - env, - tx, - validateOutput, - jss::mpt_issuance_id, - mptIssuanceId); + testTxJsonMetadataField(env, tx, validateOutput, jss::mpt_issuance_id, mptIssuanceId); } } } diff --git a/src/test/rpc/Status_test.cpp b/src/test/rpc/Status_test.cpp index c2e9c836df..ac387196fe 100644 --- a/src/test/rpc/Status_test.cpp +++ b/src/test/rpc/Status_test.cpp @@ -112,11 +112,7 @@ private: template void - expectFill( - std::string const& label, - Type status, - Status::Strings messages, - std::string const& message) + expectFill(std::string const& label, Type status, Status::Strings messages, std::string const& message) { value_.clear(); fillJson(Status(status, messages)); @@ -128,20 +124,14 @@ private: expect(bool(error), prefix + "No error."); auto code = error[jss::code].asInt(); - expect( - status == code, - prefix + "Wrong status " + std::to_string(code) + - " != " + std::to_string(status)); + expect(status == code, prefix + "Wrong status " + std::to_string(code) + " != " + std::to_string(status)); auto m = error[jss::message].asString(); expect(m == message, m + " != " + message); auto d = error[jss::data]; size_t s1 = d.size(), s2 = messages.size(); - expect( - s1 == s2, - prefix + "Data sizes differ " + std::to_string(s1) + - " != " + std::to_string(s2)); + expect(s1 == s2, prefix + "Data sizes differ " + std::to_string(s1) + " != " + std::to_string(s2)); for (auto i = 0; i < std::min(s1, s2); ++i) { auto ds = d[i].asString(); @@ -153,17 +143,9 @@ private: test_error() { testcase("error"); - expectFill( - "temBAD_AMOUNT", - temBAD_AMOUNT, - {}, - "temBAD_AMOUNT: Malformed: Bad amount."); + expectFill("temBAD_AMOUNT", temBAD_AMOUNT, {}, "temBAD_AMOUNT: Malformed: Bad amount."); - expectFill( - "rpcBAD_SYNTAX", - rpcBAD_SYNTAX, - {"An error.", "Another error."}, - "badSyntax: Syntax error."); + expectFill("rpcBAD_SYNTAX", rpcBAD_SYNTAX, {"An error.", "Another error."}, "badSyntax: Syntax error."); expectFill("integer message", 23, {"Stuff."}, "23"); } diff --git a/src/test/rpc/Subscribe_test.cpp b/src/test/rpc/Subscribe_test.cpp index 5a58c27ea8..4f83f81da5 100644 --- a/src/test/rpc/Subscribe_test.cpp +++ b/src/test/rpc/Subscribe_test.cpp @@ -36,10 +36,8 @@ public: 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::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"); @@ -59,9 +57,7 @@ public: env.app().getOPs().reportFeeChange(); // Check stream update - BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::type] == "serverStatus"; - })); + BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { return jv[jss::type] == "serverStatus"; })); } { @@ -69,10 +65,8 @@ public: 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::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"); @@ -107,16 +101,12 @@ public: 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::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::ledger_index] == 2); - BEAST_EXPECT( - jv[jss::result][jss::network_id] == - env.app().config().NETWORK_ID); + BEAST_EXPECT(jv[jss::result][jss::network_id] == env.app().config().NETWORK_ID); } { @@ -125,8 +115,7 @@ public: // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::ledger_index] == 3 && - jv[jss::network_id] == env.app().config().NETWORK_ID; + return jv[jss::ledger_index] == 3 && jv[jss::network_id] == env.app().config().NETWORK_ID; })); } @@ -136,8 +125,7 @@ public: // Check stream update BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::ledger_index] == 4 && - jv[jss::network_id] == env.app().config().NETWORK_ID; + return jv[jss::ledger_index] == 4 && jv[jss::network_id] == env.app().config().NETWORK_ID; })); } @@ -145,10 +133,8 @@ public: 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::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"); @@ -171,10 +157,8 @@ public: 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::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"); @@ -186,8 +170,7 @@ public: // Check stream update for payment transaction BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::meta]["AffectedNodes"][1u]["CreatedNode"] - ["NewFields"][jss::Account] // + return jv[jss::meta]["AffectedNodes"][1u]["CreatedNode"]["NewFields"][jss::Account] // == Account("alice").human() && jv[jss::transaction][jss::TransactionType] // == jss::Payment && @@ -201,8 +184,7 @@ public: // Check stream update for accountset transaction BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::meta]["AffectedNodes"][0u]["ModifiedNode"] - ["FinalFields"][jss::Account] == + return jv[jss::meta]["AffectedNodes"][0u]["ModifiedNode"]["FinalFields"][jss::Account] == Account("alice").human(); })); @@ -211,8 +193,7 @@ public: // Check stream update for payment transaction BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::meta]["AffectedNodes"][1u]["CreatedNode"] - ["NewFields"][jss::Account] // + return jv[jss::meta]["AffectedNodes"][1u]["CreatedNode"]["NewFields"][jss::Account] // == Account("bob").human() && jv[jss::transaction][jss::TransactionType] // == jss::Payment && @@ -226,8 +207,7 @@ public: // Check stream update for accountset transaction BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::meta]["AffectedNodes"][0u]["ModifiedNode"] - ["FinalFields"][jss::Account] == + return jv[jss::meta]["AffectedNodes"][0u]["ModifiedNode"]["FinalFields"][jss::Account] == Account("bob").human(); })); } @@ -237,10 +217,8 @@ public: 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::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"); @@ -254,10 +232,8 @@ public: 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::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"); @@ -275,14 +251,12 @@ public: // Check stream updates BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::meta]["AffectedNodes"][1u]["ModifiedNode"] - ["FinalFields"][jss::Account] == + return jv[jss::meta]["AffectedNodes"][1u]["ModifiedNode"]["FinalFields"][jss::Account] == Account("alice").human(); })); BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::meta]["AffectedNodes"][1u]["CreatedNode"] - ["NewFields"]["LowLimit"][jss::issuer] == + return jv[jss::meta]["AffectedNodes"][1u]["CreatedNode"]["NewFields"]["LowLimit"][jss::issuer] == Account("alice").human(); })); } @@ -291,10 +265,8 @@ public: 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::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"); @@ -322,10 +294,8 @@ public: 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::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"); @@ -337,8 +307,7 @@ public: // Check stream update for payment transaction BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::meta]["AffectedNodes"][1u]["CreatedNode"] - ["NewFields"][jss::Account] // + return jv[jss::meta]["AffectedNodes"][1u]["CreatedNode"]["NewFields"][jss::Account] // == Account("alice").human() && jv[jss::close_time_iso] // == "2000-01-01T00:00:10Z" && @@ -361,8 +330,7 @@ public: // Check stream update for accountset transaction BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - return jv[jss::meta]["AffectedNodes"][0u]["ModifiedNode"] - ["FinalFields"][jss::Account] == + return jv[jss::meta]["AffectedNodes"][0u]["ModifiedNode"]["FinalFields"][jss::Account] == Account("alice").human(); })); } @@ -372,10 +340,8 @@ public: 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::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"); @@ -397,10 +363,8 @@ public: 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::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"); @@ -410,10 +374,8 @@ public: 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::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"); @@ -428,16 +390,13 @@ public: auto& cfg = env.app().config(); if (!BEAST_EXPECT(cfg.section(SECTION_VALIDATION_SEED).empty())) return; - auto const parsedseed = - parseBase58(cfg.section(SECTION_VALIDATION_SEED).values()[0]); + auto const parsedseed = parseBase58(cfg.section(SECTION_VALIDATION_SEED).values()[0]); if (!BEAST_EXPECT(parsedseed)) return; std::string const valPublicKey = toBase58( TokenType::NodePublic, - derivePublicKey( - KeyType::secp256k1, - generateSecretKey(KeyType::secp256k1, *parsedseed))); + derivePublicKey(KeyType::secp256k1, generateSecretKey(KeyType::secp256k1, *parsedseed))); auto wsc = makeWSClient(env.app().config()); Json::Value stream; @@ -449,10 +408,8 @@ public: 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::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"); @@ -460,20 +417,17 @@ public: { // Lambda to check ledger validations from the stream. - auto validValidationFields = [&env, &valPublicKey]( - Json::Value const& jv) { + auto validValidationFields = [&env, &valPublicKey](Json::Value const& jv) { if (jv[jss::type] != "validationReceived") return false; if (jv[jss::validation_public_key].asString() != valPublicKey) return false; - if (jv[jss::ledger_hash] != - to_string(env.closed()->header().hash)) + if (jv[jss::ledger_hash] != to_string(env.closed()->header().hash)) return false; - if (jv[jss::ledger_index] != - std::to_string(env.closed()->header().seq)) + if (jv[jss::ledger_index] != std::to_string(env.closed()->header().seq)) return false; if (jv[jss::flags] != (vfFullyCanonicalSig | vfFullValidation)) @@ -498,13 +452,11 @@ public: return false; uint32_t netID = env.app().config().NETWORK_ID; - if (!jv.isMember(jss::network_id) || - jv[jss::network_id] != netID) + if (!jv.isMember(jss::network_id) || jv[jss::network_id] != netID) return false; // Certain fields are only added on a flag ledger. - bool const isFlagLedger = - (env.closed()->header().seq + 1) % 256 == 0; + bool const isFlagLedger = (env.closed()->header().seq + 1) % 256 == 0; if (jv.isMember(jss::server_version) != isFlagLedger) return false; @@ -532,10 +484,8 @@ public: 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::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"); @@ -608,9 +558,7 @@ public: if (subscribe) { BEAST_EXPECT(jr[jss::error] == "invalidParams"); - BEAST_EXPECT( - jr[jss::error_message] == - "Only http and https is supported."); + BEAST_EXPECT(jr[jss::error_message] == "Only http and https is supported."); } } @@ -618,12 +566,9 @@ public: Env env_nonadmin{*this, no_admin(envconfig())}; Json::Value jv; jv[jss::url] = "no-url"; - auto jr = - env_nonadmin.rpc("json", method, to_string(jv))[jss::result]; + auto jr = env_nonadmin.rpc("json", method, to_string(jv))[jss::result]; BEAST_EXPECT(jr[jss::error] == "noPermission"); - BEAST_EXPECT( - jr[jss::error_message] == - "You don't have permission for this command."); + BEAST_EXPECT(jr[jss::error_message] == "You don't have permission for this command."); } std::initializer_list const nonArrays{ @@ -681,8 +626,7 @@ public: jv[jss::books][0u][jss::taker_pays] = Json::objectValue; auto jr = wsc->invoke(method, jv)[jss::result]; BEAST_EXPECT(jr[jss::error] == "srcCurMalformed"); - BEAST_EXPECT( - jr[jss::error_message] == "Source currency is malformed."); + BEAST_EXPECT(jr[jss::error_message] == "Source currency is malformed."); } { @@ -694,8 +638,7 @@ public: jv[jss::books][0u][jss::taker_pays][jss::currency] = "ZZZZ"; auto jr = wsc->invoke(method, jv)[jss::result]; BEAST_EXPECT(jr[jss::error] == "srcCurMalformed"); - BEAST_EXPECT( - jr[jss::error_message] == "Source currency is malformed."); + BEAST_EXPECT(jr[jss::error_message] == "Source currency is malformed."); } { @@ -708,8 +651,7 @@ public: jv[jss::books][0u][jss::taker_pays][jss::issuer] = 1; auto jr = wsc->invoke(method, jv)[jss::result]; BEAST_EXPECT(jr[jss::error] == "srcIsrMalformed"); - BEAST_EXPECT( - jr[jss::error_message] == "Source issuer is malformed."); + BEAST_EXPECT(jr[jss::error_message] == "Source issuer is malformed."); } { @@ -719,12 +661,10 @@ public: jv[jss::books][0u][jss::taker_gets] = Json::objectValue; jv[jss::books][0u][jss::taker_pays] = Json::objectValue; jv[jss::books][0u][jss::taker_pays][jss::currency] = "USD"; - jv[jss::books][0u][jss::taker_pays][jss::issuer] = - Account{"gateway"}.human() + "DEAD"; + jv[jss::books][0u][jss::taker_pays][jss::issuer] = Account{"gateway"}.human() + "DEAD"; auto jr = wsc->invoke(method, jv)[jss::result]; BEAST_EXPECT(jr[jss::error] == "srcIsrMalformed"); - BEAST_EXPECT( - jr[jss::error_message] == "Source issuer is malformed."); + BEAST_EXPECT(jr[jss::error_message] == "Source issuer is malformed."); } { @@ -732,16 +672,13 @@ public: jv[jss::books] = Json::arrayValue; jv[jss::books][0u] = Json::objectValue; jv[jss::books][0u][jss::taker_pays] = - Account{"gateway"}["USD"](1).value().getJson( - JsonOptions::include_date); + Account{"gateway"}["USD"](1).value().getJson(JsonOptions::include_date); jv[jss::books][0u][jss::taker_gets] = Json::objectValue; auto jr = wsc->invoke(method, jv)[jss::result]; // NOTE: this error is slightly incongruous with the // equivalent source currency error BEAST_EXPECT(jr[jss::error] == "dstAmtMalformed"); - BEAST_EXPECT( - jr[jss::error_message] == - "Destination amount/currency/issuer is malformed."); + BEAST_EXPECT(jr[jss::error_message] == "Destination amount/currency/issuer is malformed."); } { @@ -749,16 +686,13 @@ public: jv[jss::books] = Json::arrayValue; jv[jss::books][0u] = Json::objectValue; jv[jss::books][0u][jss::taker_pays] = - Account{"gateway"}["USD"](1).value().getJson( - JsonOptions::include_date); + Account{"gateway"}["USD"](1).value().getJson(JsonOptions::include_date); jv[jss::books][0u][jss::taker_gets][jss::currency] = "ZZZZ"; auto jr = wsc->invoke(method, jv)[jss::result]; // NOTE: this error is slightly incongruous with the // equivalent source currency error BEAST_EXPECT(jr[jss::error] == "dstAmtMalformed"); - BEAST_EXPECT( - jr[jss::error_message] == - "Destination amount/currency/issuer is malformed."); + BEAST_EXPECT(jr[jss::error_message] == "Destination amount/currency/issuer is malformed."); } { @@ -766,14 +700,12 @@ public: jv[jss::books] = Json::arrayValue; jv[jss::books][0u] = Json::objectValue; jv[jss::books][0u][jss::taker_pays] = - Account{"gateway"}["USD"](1).value().getJson( - JsonOptions::include_date); + Account{"gateway"}["USD"](1).value().getJson(JsonOptions::include_date); jv[jss::books][0u][jss::taker_gets][jss::currency] = "USD"; jv[jss::books][0u][jss::taker_gets][jss::issuer] = 1; auto jr = wsc->invoke(method, jv)[jss::result]; BEAST_EXPECT(jr[jss::error] == "dstIsrMalformed"); - BEAST_EXPECT( - jr[jss::error_message] == "Destination issuer is malformed."); + BEAST_EXPECT(jr[jss::error_message] == "Destination issuer is malformed."); } { @@ -781,15 +713,12 @@ public: jv[jss::books] = Json::arrayValue; jv[jss::books][0u] = Json::objectValue; jv[jss::books][0u][jss::taker_pays] = - Account{"gateway"}["USD"](1).value().getJson( - JsonOptions::include_date); + Account{"gateway"}["USD"](1).value().getJson(JsonOptions::include_date); jv[jss::books][0u][jss::taker_gets][jss::currency] = "USD"; - jv[jss::books][0u][jss::taker_gets][jss::issuer] = - Account{"gateway"}.human() + "DEAD"; + jv[jss::books][0u][jss::taker_gets][jss::issuer] = Account{"gateway"}.human() + "DEAD"; auto jr = wsc->invoke(method, jv)[jss::result]; BEAST_EXPECT(jr[jss::error] == "dstIsrMalformed"); - BEAST_EXPECT( - jr[jss::error_message] == "Destination issuer is malformed."); + BEAST_EXPECT(jr[jss::error_message] == "Destination issuer is malformed."); } { @@ -797,11 +726,9 @@ public: jv[jss::books] = Json::arrayValue; jv[jss::books][0u] = Json::objectValue; jv[jss::books][0u][jss::taker_pays] = - Account{"gateway"}["USD"](1).value().getJson( - JsonOptions::include_date); + Account{"gateway"}["USD"](1).value().getJson(JsonOptions::include_date); jv[jss::books][0u][jss::taker_gets] = - Account{"gateway"}["USD"](1).value().getJson( - JsonOptions::include_date); + Account{"gateway"}["USD"](1).value().getJson(JsonOptions::include_date); auto jr = wsc->invoke(method, jv)[jss::result]; BEAST_EXPECT(jr[jss::error] == "badMarket"); BEAST_EXPECT(jr[jss::error_message] == "No such market."); @@ -854,8 +781,7 @@ public: * return true if the subscribe or unsubscribe result is a success */ auto goodSubRPC = [](Json::Value const& subReply) -> bool { - return subReply.isMember(jss::result) && - subReply[jss::result].isMember(jss::status) && + return subReply.isMember(jss::result) && subReply[jss::result].isMember(jss::status) && subReply[jss::result][jss::status] == jss::success; }; @@ -864,9 +790,7 @@ public: * return {true, true} if received numReplies replies and also * received a tx with the account_history_tx_first == true */ - auto getTxHash = [](WSClient& wsc, - IdxHashVec& v, - int numReplies) -> std::pair { + auto getTxHash = [](WSClient& wsc, IdxHashVec& v, int numReplies) -> std::pair { bool first_flag = false; for (int i = 0; i < numReplies; ++i) @@ -882,12 +806,10 @@ public: first_flag = true; bool boundary = r.isMember(jss::account_history_boundary); int ledger_idx = r[jss::ledger_index].asInt(); - if (r.isMember(jss::transaction) && - r[jss::transaction].isMember(jss::hash)) + if (r.isMember(jss::transaction) && r[jss::transaction].isMember(jss::hash)) { auto t{r[jss::transaction]}; - v.emplace_back( - idx, t[jss::hash].asString(), boundary, ledger_idx); + v.emplace_back(idx, t[jss::hash].asString(), boundary, ledger_idx); continue; } } @@ -929,9 +851,7 @@ public: * and in the same order. * If sizeCompare is false, txHistoryVec is allowed to be larger. */ - auto hashCompare = [](IdxHashVec const& accountVec, - IdxHashVec const& txHistoryVec, - bool sizeCompare) -> bool { + auto hashCompare = [](IdxHashVec const& accountVec, IdxHashVec const& txHistoryVec, bool sizeCompare) -> bool { if (accountVec.empty() || txHistoryVec.empty()) return false; if (sizeCompare && accountVec.size() != (txHistoryVec.size())) @@ -957,8 +877,7 @@ public: return false; for (std::size_t i = 1; i < accountVec.size(); ++i) { - if (auto idx = getHistoryIndex(i); - !idx || *idx != *firstHistoryIndex + i) + if (auto idx = getHistoryIndex(i); !idx || *idx != *firstHistoryIndex + i) return false; } return true; @@ -999,8 +918,7 @@ public: for (size_t i = 0; i < num_tx; ++i) { auto [idx, hash, boundary, ledger] = vec[i]; - if ((i + 1 == num_tx || ledger != std::get<3>(vec[i + 1])) != - boundary) + if ((i + 1 == num_tx || ledger != std::get<3>(vec[i + 1])) != boundary) return false; } return true; @@ -1019,8 +937,7 @@ public: auto wscTxHistory = makeWSClient(env.app().config()); Json::Value request; request[jss::account_history_tx_stream] = Json::objectValue; - request[jss::account_history_tx_stream][jss::account] = - alice.human(); + request[jss::account_history_tx_stream][jss::account] = alice.human(); auto jv = wscTxHistory->invoke("subscribe", request); if (!BEAST_EXPECT(goodSubRPC(jv))) return; @@ -1031,8 +948,7 @@ public: /* * unsubscribe history only, future txns should still be streamed */ - request[jss::account_history_tx_stream][jss::stop_history_tx_only] = - true; + request[jss::account_history_tx_stream][jss::stop_history_tx_only] = true; jv = wscTxHistory->invoke("unsubscribe", request); if (!BEAST_EXPECT(goodSubRPC(jv))) return; @@ -1047,8 +963,7 @@ public: /* * unsubscribe, future txns should not be streamed */ - request[jss::account_history_tx_stream][jss::stop_history_tx_only] = - false; + request[jss::account_history_tx_stream][jss::stop_history_tx_only] = false; jv = wscTxHistory->invoke("unsubscribe", request); BEAST_EXPECT(goodSubRPC(jv)); @@ -1065,14 +980,12 @@ public: auto wscTxHistory = makeWSClient(env.app().config()); Json::Value request; request[jss::account_history_tx_stream] = Json::objectValue; - request[jss::account_history_tx_stream][jss::account] = - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; + request[jss::account_history_tx_stream][jss::account] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; auto jv = wscTxHistory->invoke("subscribe", request); if (!BEAST_EXPECT(goodSubRPC(jv))) return; IdxHashVec genesisFullHistoryVec; - if (!BEAST_EXPECT( - !getTxHash(*wscTxHistory, genesisFullHistoryVec, 1).first)) + if (!BEAST_EXPECT(!getTxHash(*wscTxHistory, genesisFullHistoryVec, 1).first)) return; /* @@ -1093,9 +1006,7 @@ public: r = getTxHash(*wscTxHistory, bobFullHistoryVec, 1); if (!BEAST_EXPECT(r.first && r.second)) return; - BEAST_EXPECT( - std::get<1>(bobFullHistoryVec.back()) == - std::get<1>(genesisFullHistoryVec.back())); + BEAST_EXPECT(std::get<1>(bobFullHistoryVec.back()) == std::get<1>(genesisFullHistoryVec.back())); /* * unsubscribe to prepare next test @@ -1103,8 +1014,7 @@ public: jv = wscTxHistory->invoke("unsubscribe", request); if (!BEAST_EXPECT(goodSubRPC(jv))) return; - request[jss::account_history_tx_stream][jss::account] = - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; + request[jss::account_history_tx_stream][jss::account] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; jv = wscTxHistory->invoke("unsubscribe", request); BEAST_EXPECT(goodSubRPC(jv)); @@ -1118,21 +1028,16 @@ public: jv = wscTxHistory->invoke("subscribe", request); bobFullHistoryVec.clear(); - BEAST_EXPECT( - getTxHash(*wscTxHistory, bobFullHistoryVec, 31).second); + BEAST_EXPECT(getTxHash(*wscTxHistory, bobFullHistoryVec, 31).second); jv = wscTxHistory->invoke("unsubscribe", request); - request[jss::account_history_tx_stream][jss::account] = - "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; + request[jss::account_history_tx_stream][jss::account] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; jv = wscTxHistory->invoke("subscribe", request); genesisFullHistoryVec.clear(); - BEAST_EXPECT( - getTxHash(*wscTxHistory, genesisFullHistoryVec, 31).second); + BEAST_EXPECT(getTxHash(*wscTxHistory, genesisFullHistoryVec, 31).second); jv = wscTxHistory->invoke("unsubscribe", request); - BEAST_EXPECT( - std::get<1>(bobFullHistoryVec.back()) == - std::get<1>(genesisFullHistoryVec.back())); + BEAST_EXPECT(std::get<1>(bobFullHistoryVec.back()) == std::get<1>(genesisFullHistoryVec.back())); } { @@ -1163,8 +1068,7 @@ public: // subscribe account tx history Json::Value request; request[jss::account_history_tx_stream] = Json::objectValue; - request[jss::account_history_tx_stream][jss::account] = - alice.human(); + request[jss::account_history_tx_stream][jss::account] = alice.human(); jv = wscTxHistory->invoke("subscribe", request); // compare historical txns @@ -1182,8 +1086,7 @@ public: { // take out all history txns from stream to prepare next test IdxHashVec initFundTxns; - if (!BEAST_EXPECT( - getTxHash(*wscTxHistory, initFundTxns, 10).second) || + if (!BEAST_EXPECT(getTxHash(*wscTxHistory, initFundTxns, 10).second) || !BEAST_EXPECT(checkBoundary(initFundTxns, false))) return; } @@ -1229,8 +1132,7 @@ public: // subscribe Json::Value request; request[jss::account_history_tx_stream] = Json::objectValue; - request[jss::account_history_tx_stream][jss::account] = - carol.human(); + request[jss::account_history_tx_stream][jss::account] = carol.human(); auto ws = makeWSClient(env.app().config()); auto jv = ws->invoke("subscribe", request); { @@ -1256,15 +1158,12 @@ public: env.close(); // many payments, and close lots of ledgers - auto oneRound = [&](int numPayments) { - return sendPayments(env, alice, carol, numPayments, 300); - }; + auto oneRound = [&](int numPayments) { return sendPayments(env, alice, carol, numPayments, 300); }; // subscribe Json::Value request; request[jss::account_history_tx_stream] = Json::objectValue; - request[jss::account_history_tx_stream][jss::account] = - carol.human(); + request[jss::account_history_tx_stream][jss::account] = carol.human(); auto wscLong = makeWSClient(env.app().config()); auto jv = wscLong->invoke("subscribe", request); { @@ -1301,8 +1200,7 @@ public: using namespace jtx; using namespace std::chrono_literals; FeatureBitset const all{ - jtx::testable_amendments() | featurePermissionedDomains | - featureCredentials | featurePermissionedDEX}; + jtx::testable_amendments() | featurePermissionedDomains | featureCredentials | featurePermissionedDEX}; Env env(*this, all); PermissionedDEX permDex(env); @@ -1322,15 +1220,10 @@ public: auto jv = wsc->invoke("subscribe", streams); if (!BEAST_EXPECT(jv[jss::status] == "success")) return; - env(offer(alice, XRP(10), USD(10)), - domain(domainID), - txflags(tfHybrid)); + env(offer(alice, XRP(10), USD(10)), domain(domainID), txflags(tfHybrid)); env.close(); - env(pay(bob, carol, USD(5)), - path(~USD), - sendmax(XRP(5)), - domain(domainID)); + env(pay(bob, carol, USD(5)), path(~USD), sendmax(XRP(5)), domain(domainID)); env.close(); BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { @@ -1338,12 +1231,9 @@ public: return false; auto const jrOffer = jv[jss::changes][0u]; - return (jv[jss::changes][0u][jss::domain]).asString() == - strHex(domainID) && - jrOffer[jss::currency_a].asString() == "XRP_drops" && - jrOffer[jss::volume_a].asString() == "5000000" && - jrOffer[jss::currency_b].asString() == - "rHUKYAZyUFn8PCZWbPfwHfbVQXTYrYKkHb/USD" && + return (jv[jss::changes][0u][jss::domain]).asString() == strHex(domainID) && + jrOffer[jss::currency_a].asString() == "XRP_drops" && jrOffer[jss::volume_a].asString() == "5000000" && + jrOffer[jss::currency_b].asString() == "rHUKYAZyUFn8PCZWbPfwHfbVQXTYrYKkHb/USD" && jrOffer[jss::volume_b].asString() == "5"; })); } @@ -1389,49 +1279,46 @@ public: auto verifyNFTokenID = [&](uint256 const& actualNftID) { BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { uint256 nftID; - BEAST_EXPECT( - nftID.parseHex(jv[jss::meta][jss::nftoken_id].asString())); + BEAST_EXPECT(nftID.parseHex(jv[jss::meta][jss::nftoken_id].asString())); return nftID == actualNftID; })); }; // Verify `nftoken_ids` value equals to the NFTokenIDs that were // changed in the most recent NFTokenCancelOffer transaction - auto verifyNFTokenIDsInCancelOffer = - [&](std::vector actualNftIDs) { - BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { - std::vector metaIDs; - std::transform( - jv[jss::meta][jss::nftoken_ids].begin(), - jv[jss::meta][jss::nftoken_ids].end(), - std::back_inserter(metaIDs), - [this](Json::Value id) { - uint256 nftID; - BEAST_EXPECT(nftID.parseHex(id.asString())); - return nftID; - }); - // Sort both array to prepare for comparison - std::sort(metaIDs.begin(), metaIDs.end()); - std::sort(actualNftIDs.begin(), actualNftIDs.end()); + auto verifyNFTokenIDsInCancelOffer = [&](std::vector actualNftIDs) { + BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { + std::vector metaIDs; + std::transform( + jv[jss::meta][jss::nftoken_ids].begin(), + jv[jss::meta][jss::nftoken_ids].end(), + std::back_inserter(metaIDs), + [this](Json::Value id) { + uint256 nftID; + BEAST_EXPECT(nftID.parseHex(id.asString())); + return nftID; + }); + // Sort both array to prepare for comparison + std::sort(metaIDs.begin(), metaIDs.end()); + std::sort(actualNftIDs.begin(), actualNftIDs.end()); - // Make sure the expect number of NFTs is correct - BEAST_EXPECT(metaIDs.size() == actualNftIDs.size()); + // Make sure the expect number of NFTs is correct + BEAST_EXPECT(metaIDs.size() == actualNftIDs.size()); - // Check the value of NFT ID in the meta with the - // actual values - for (size_t i = 0; i < metaIDs.size(); ++i) - BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]); - return true; - })); - }; + // Check the value of NFT ID in the meta with the + // actual values + for (size_t i = 0; i < metaIDs.size(); ++i) + BEAST_EXPECT(metaIDs[i] == actualNftIDs[i]); + return true; + })); + }; // Verify `offer_id` value equals to the offerID that was // changed in the most recent NFTokenCreateOffer tx auto verifyNFTokenOfferID = [&](uint256 const& offerID) { BEAST_EXPECT(wsc->findMsg(5s, [&](auto const& jv) { uint256 metaOfferID; - BEAST_EXPECT(metaOfferID.parseHex( - jv[jss::meta][jss::offer_id].asString())); + BEAST_EXPECT(metaOfferID.parseHex(jv[jss::meta][jss::offer_id].asString())); return metaOfferID == offerID; })); }; @@ -1440,14 +1327,12 @@ public: { // Alice mints 2 NFTs // Verify the NFTokenIDs are correct in the NFTokenMint tx meta - uint256 const nftId1{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId1{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); verifyNFTokenID(nftId1); - uint256 const nftId2{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId2{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); verifyNFTokenID(nftId2); @@ -1455,32 +1340,26 @@ public: // Alice creates one sell offer for each NFT // Verify the offer indexes are correct in the NFTokenCreateOffer tx // meta - uint256 const aliceOfferIndex1 = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId1, drops(1)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex1 = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId1, drops(1)), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(aliceOfferIndex1); - uint256 const aliceOfferIndex2 = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId2, drops(1)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex2 = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId2, drops(1)), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(aliceOfferIndex2); // Alice cancels two offers she created // Verify the NFTokenIDs are correct in the NFTokenCancelOffer tx // meta - env(token::cancelOffer( - alice, {aliceOfferIndex1, aliceOfferIndex2})); + env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2})); env.close(); verifyNFTokenIDsInCancelOffer({nftId1, nftId2}); // Bobs creates a buy offer for nftId1 // Verify the offer id is correct in the NFTokenCreateOffer tx meta - auto const bobBuyOfferIndex = - keylet::nftoffer(bob, env.seq(bob)).key; + auto const bobBuyOfferIndex = keylet::nftoffer(bob, env.seq(bob)).key; env(token::createOffer(bob, nftId1, drops(1)), token::owner(alice)); env.close(); verifyNFTokenOfferID(bobBuyOfferIndex); @@ -1495,31 +1374,25 @@ public: // Check `nftoken_ids` in brokered mode { // Alice mints a NFT - uint256 const nftId{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); verifyNFTokenID(nftId); // Alice creates sell offer and set broker as destination - uint256 const offerAliceToBroker = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId, drops(1)), - token::destination(broker), - txflags(tfSellNFToken)); + uint256 const offerAliceToBroker = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId, drops(1)), token::destination(broker), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(offerAliceToBroker); // Bob creates buy offer - uint256 const offerBobToBroker = - keylet::nftoffer(bob, env.seq(bob)).key; + uint256 const offerBobToBroker = keylet::nftoffer(bob, env.seq(bob)).key; env(token::createOffer(bob, nftId, drops(1)), token::owner(alice)); env.close(); verifyNFTokenOfferID(offerBobToBroker); // Check NFTokenID meta for NFTokenAcceptOffer in brokered mode - env(token::brokerOffers( - broker, offerBobToBroker, offerAliceToBroker)); + env(token::brokerOffers(broker, offerBobToBroker, offerAliceToBroker)); env.close(); verifyNFTokenID(nftId); } @@ -1528,39 +1401,32 @@ public: // multiple offers are cancelled for the same NFT { // Alice mints a NFT - uint256 const nftId{ - token::getNextID(env, alice, 0u, tfTransferable)}; + uint256 const nftId{token::getNextID(env, alice, 0u, tfTransferable)}; env(token::mint(alice, 0u), txflags(tfTransferable)); env.close(); verifyNFTokenID(nftId); // Alice creates 2 sell offers for the same NFT - uint256 const aliceOfferIndex1 = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId, drops(1)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex1 = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId, drops(1)), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(aliceOfferIndex1); - uint256 const aliceOfferIndex2 = - keylet::nftoffer(alice, env.seq(alice)).key; - env(token::createOffer(alice, nftId, drops(1)), - txflags(tfSellNFToken)); + uint256 const aliceOfferIndex2 = keylet::nftoffer(alice, env.seq(alice)).key; + env(token::createOffer(alice, nftId, drops(1)), txflags(tfSellNFToken)); env.close(); verifyNFTokenOfferID(aliceOfferIndex2); // Make sure the metadata only has 1 nft id, since both offers are // for the same nft - env(token::cancelOffer( - alice, {aliceOfferIndex1, aliceOfferIndex2})); + env(token::cancelOffer(alice, {aliceOfferIndex1, aliceOfferIndex2})); env.close(); verifyNFTokenIDsInCancelOffer({nftId}); } if (features[featureNFTokenMintOffer]) { - uint256 const aliceMintWithOfferIndex1 = - keylet::nftoffer(alice, env.seq(alice)).key; + uint256 const aliceMintWithOfferIndex1 = keylet::nftoffer(alice, env.seq(alice)).key; env(token::mint(alice), token::amount(XRP(0))); env.close(); verifyNFTokenOfferID(aliceMintWithOfferIndex1); diff --git a/src/test/rpc/TransactionEntry_test.cpp b/src/test/rpc/TransactionEntry_test.cpp index f81a04df6a..6302de4efa 100644 --- a/src/test/rpc/TransactionEntry_test.cpp +++ b/src/test/rpc/TransactionEntry_test.cpp @@ -23,8 +23,7 @@ class TransactionEntry_test : public beast::unit_test::suite { // no params - auto const result = - env.client().invoke("transaction_entry", {})[jss::result]; + auto const result = env.client().invoke("transaction_entry", {})[jss::result]; BEAST_EXPECT(result[jss::error] == "fieldNotFoundTransaction"); BEAST_EXPECT(result[jss::status] == "error"); } @@ -32,8 +31,7 @@ class TransactionEntry_test : public beast::unit_test::suite { Json::Value params{Json::objectValue}; params[jss::ledger] = 20; - auto const result = - env.client().invoke("transaction_entry", params)[jss::result]; + auto const result = env.client().invoke("transaction_entry", params)[jss::result]; BEAST_EXPECT(result[jss::error] == "lgrNotFound"); BEAST_EXPECT(result[jss::status] == "error"); } @@ -42,8 +40,7 @@ class TransactionEntry_test : public beast::unit_test::suite Json::Value params{Json::objectValue}; params[jss::ledger] = "current"; params[jss::tx_hash] = "DEADBEEF"; - auto const result = - env.client().invoke("transaction_entry", params)[jss::result]; + auto const result = env.client().invoke("transaction_entry", params)[jss::result]; BEAST_EXPECT(result[jss::error] == "notYetImplemented"); BEAST_EXPECT(result[jss::status] == "error"); } @@ -52,15 +49,13 @@ class TransactionEntry_test : public beast::unit_test::suite Json::Value params{Json::objectValue}; params[jss::ledger] = "closed"; params[jss::tx_hash] = "DEADBEEF"; - auto const result = - env.client().invoke("transaction_entry", params)[jss::result]; + auto const result = env.client().invoke("transaction_entry", params)[jss::result]; BEAST_EXPECT(!result[jss::ledger_hash].asString().empty()); BEAST_EXPECT(result[jss::error] == "malformedRequest"); BEAST_EXPECT(result[jss::status] == "error"); } - std::string const txHash{ - "E2FE8D4AF3FCC3944DDF6CD8CDDC5E3F0AD50863EF8919AFEF10CB6408CD4D05"}; + std::string const txHash{"E2FE8D4AF3FCC3944DDF6CD8CDDC5E3F0AD50863EF8919AFEF10CB6408CD4D05"}; // Command line format { @@ -80,24 +75,21 @@ class TransactionEntry_test : public beast::unit_test::suite { // First argument with too few characters - Json::Value const result{ - env.rpc("transaction_entry", txHash.substr(1), "closed")}; + Json::Value const result{env.rpc("transaction_entry", txHash.substr(1), "closed")}; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::status] == "error"); } { // First argument with too many characters - Json::Value const result{ - env.rpc("transaction_entry", txHash + "A", "closed")}; + Json::Value const result{env.rpc("transaction_entry", txHash + "A", "closed")}; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::status] == "error"); } { // Second argument not valid - Json::Value const result{ - env.rpc("transaction_entry", txHash, "closer")}; + Json::Value const result{env.rpc("transaction_entry", txHash, "closer")}; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::status] == "error"); } @@ -111,20 +103,16 @@ class TransactionEntry_test : public beast::unit_test::suite { // Three arguments - Json::Value const result{ - env.rpc("transaction_entry", txHash, "closed", "extra")}; + Json::Value const result{env.rpc("transaction_entry", txHash, "closed", "extra")}; BEAST_EXPECT(result[jss::error] == "badSyntax"); BEAST_EXPECT(result[jss::status] == "error"); } { // Valid structure, but transaction not found. - Json::Value const result{ - env.rpc("transaction_entry", txHash, "closed")}; - BEAST_EXPECT( - !result[jss::result][jss::ledger_hash].asString().empty()); - BEAST_EXPECT( - result[jss::result][jss::error] == "transactionNotFound"); + Json::Value const result{env.rpc("transaction_entry", txHash, "closed")}; + BEAST_EXPECT(!result[jss::result][jss::ledger_hash].asString().empty()); + BEAST_EXPECT(result[jss::result][jss::error] == "transactionNotFound"); BEAST_EXPECT(result[jss::result][jss::status] == "error"); } } @@ -151,8 +139,7 @@ class TransactionEntry_test : public beast::unit_test::suite params[jss::ledger_index] = index; params[jss::tx_hash] = txhash; params[jss::api_version] = apiVersion; - return env.client().invoke( - "transaction_entry", params)[jss::result]; + return env.client().invoke("transaction_entry", params)[jss::result]; }()}; if (!BEAST_EXPECT(resIndex.isMember(jss::tx_json))) @@ -168,8 +155,7 @@ class TransactionEntry_test : public beast::unit_test::suite BEAST_EXPECT(!resIndex[jss::tx_json].isMember(jss::Amount)); if (BEAST_EXPECT(!close_time_iso.empty())) - BEAST_EXPECT( - resIndex[jss::close_time_iso] == close_time_iso); + BEAST_EXPECT(resIndex[jss::close_time_iso] == close_time_iso); } else { @@ -183,12 +169,9 @@ class TransactionEntry_test : public beast::unit_test::suite Json::Value expected; Json::Reader().parse(expected_json, expected); if (RPC::contains_error(expected)) - Throw( - "Internal JSONRPC_test error. Bad test JSON."); + Throw("Internal JSONRPC_test error. Bad test JSON."); - for (auto memberIt = expected.begin(); - memberIt != expected.end(); - memberIt++) + for (auto memberIt = expected.begin(); memberIt != expected.end(); memberIt++) { auto const name = memberIt.memberName(); if (BEAST_EXPECT(resIndex[jss::tx_json].isMember(name))) @@ -211,25 +194,17 @@ class TransactionEntry_test : public beast::unit_test::suite params[jss::ledger_hash] = resIndex[jss::ledger_hash]; params[jss::tx_hash] = txhash; params[jss::api_version] = apiVersion; - Json::Value const resHash = env.client().invoke( - "transaction_entry", params)[jss::result]; + Json::Value const resHash = env.client().invoke("transaction_entry", params)[jss::result]; BEAST_EXPECT(resHash == resIndex); } // Use the command line form with the index. - Json::Value const clIndex{env.rpc( - apiVersion, - "transaction_entry", - txhash, - std::to_string(index))}; + Json::Value const clIndex{env.rpc(apiVersion, "transaction_entry", txhash, std::to_string(index))}; BEAST_EXPECT(clIndex["result"] == resIndex); // Use the command line form with the ledger_hash. - Json::Value const clHash{env.rpc( - apiVersion, - "transaction_entry", - txhash, - resIndex[jss::ledger_hash].asString())}; + Json::Value const clHash{ + env.rpc(apiVersion, "transaction_entry", txhash, resIndex[jss::ledger_hash].asString())}; BEAST_EXPECT(clHash["result"] == resIndex); }; @@ -238,15 +213,11 @@ class TransactionEntry_test : public beast::unit_test::suite env.fund(XRP(10000), A1); auto fund_1_tx = to_string(env.tx()->getTransactionID()); - BEAST_EXPECT( - fund_1_tx == - "F4E9DF90D829A9E8B423FF68C34413E240D8D8BB0EFD080DF08114ED398E2506"); + BEAST_EXPECT(fund_1_tx == "F4E9DF90D829A9E8B423FF68C34413E240D8D8BB0EFD080DF08114ED398E2506"); env.fund(XRP(10000), A2); auto fund_2_tx = to_string(env.tx()->getTransactionID()); - BEAST_EXPECT( - fund_2_tx == - "6853CD8226A05068C951CB1F54889FF4E40C5B440DC1C5BA38F114C4E0B1E705"); + BEAST_EXPECT(fund_2_tx == "6853CD8226A05068C951CB1F54889FF4E40C5B440DC1C5BA38F114C4E0B1E705"); env.close(); @@ -286,16 +257,12 @@ class TransactionEntry_test : public beast::unit_test::suite // refunds fees with a payment after TrustSet..so just ignore the type // in the check below auto trust_tx = to_string(env.tx()->getTransactionID()); - BEAST_EXPECT( - trust_tx == - "C992D97D88FF444A1AB0C06B27557EC54B7F7DA28254778E60238BEA88E0C101"); + BEAST_EXPECT(trust_tx == "C992D97D88FF444A1AB0C06B27557EC54B7F7DA28254778E60238BEA88E0C101"); env(pay(A2, A1, A2["USD"](5))); auto pay_tx = to_string(env.tx()->getTransactionID()); env.close(); - BEAST_EXPECT( - pay_tx == - "988046D484ACE9F5F6A8C792D89C6EA2DB307B5DDA9864AEBA88E6782ABD0865"); + BEAST_EXPECT(pay_tx == "988046D484ACE9F5F6A8C792D89C6EA2DB307B5DDA9864AEBA88E6782ABD0865"); check_tx( env.closed()->seq(), @@ -338,9 +305,7 @@ class TransactionEntry_test : public beast::unit_test::suite env(offer(A2, XRP(100), A2["USD"](1))); auto offer_tx = to_string(env.tx()->getTransactionID()); - BEAST_EXPECT( - offer_tx == - "5FCC1A27A7664F82A0CC4BE5766FBBB7C560D52B93AA7B550CD33B27AEC7EFFB"); + BEAST_EXPECT(offer_tx == "5FCC1A27A7664F82A0CC4BE5766FBBB7C560D52B93AA7B550CD33B27AEC7EFFB"); env.close(); check_tx( @@ -370,8 +335,7 @@ public: run() override { testBadInput(); - forAllApiVersions( - std::bind_front(&TransactionEntry_test::testRequest, this)); + forAllApiVersions(std::bind_front(&TransactionEntry_test::testRequest, this)); } }; diff --git a/src/test/rpc/TransactionHistory_test.cpp b/src/test/rpc/TransactionHistory_test.cpp index 1dec83584d..1d555ecd8c 100644 --- a/src/test/rpc/TransactionHistory_test.cpp +++ b/src/test/rpc/TransactionHistory_test.cpp @@ -21,8 +21,7 @@ class TransactionHistory_test : public beast::unit_test::suite { // no params - auto const result = - env.client().invoke("tx_history", {})[jss::result]; + auto const result = env.client().invoke("tx_history", {})[jss::result]; BEAST_EXPECT(result[jss::error] == "invalidParams"); BEAST_EXPECT(result[jss::status] == "error"); } @@ -31,8 +30,7 @@ class TransactionHistory_test : public beast::unit_test::suite // test at 1 greater than the allowed non-admin limit Json::Value params{Json::objectValue}; params[jss::start] = 10001; // limited to <= 10000 for non admin - auto const result = - env.client().invoke("tx_history", params)[jss::result]; + auto const result = env.client().invoke("tx_history", params)[jss::result]; BEAST_EXPECT(result[jss::error] == "noPermission"); BEAST_EXPECT(result[jss::status] == "error"); } @@ -47,8 +45,7 @@ class TransactionHistory_test : public beast::unit_test::suite Json::Value params{Json::objectValue}; params[jss::api_version] = 2; - auto const result = - env.client().invoke("tx_history", params)[jss::result]; + auto const result = env.client().invoke("tx_history", params)[jss::result]; BEAST_EXPECT(result[jss::error] == "unknownCmd"); BEAST_EXPECT(result[jss::status] == "error"); } @@ -83,10 +80,8 @@ class TransactionHistory_test : public beast::unit_test::suite // is available in tx_history. Json::Value params{Json::objectValue}; params[jss::start] = 0; - auto result = - env.client().invoke("tx_history", params)[jss::result]; - if (!BEAST_EXPECT( - result[jss::txs].isArray() && result[jss::txs].size() > 0)) + auto result = env.client().invoke("tx_history", params)[jss::result]; + if (!BEAST_EXPECT(result[jss::txs].isArray() && result[jss::txs].size() > 0)) return; // search for a tx in history matching the last offer @@ -112,10 +107,8 @@ class TransactionHistory_test : public beast::unit_test::suite { Json::Value params{Json::objectValue}; params[jss::start] = start; - auto result = - env.client().invoke("tx_history", params)[jss::result]; - if (!BEAST_EXPECT( - result[jss::txs].isArray() && result[jss::txs].size() > 0)) + auto result = env.client().invoke("tx_history", params)[jss::result]; + if (!BEAST_EXPECT(result[jss::txs].isArray() && result[jss::txs].size() > 0)) break; total += result[jss::txs].size(); start += 20; @@ -134,8 +127,7 @@ class TransactionHistory_test : public beast::unit_test::suite { Json::Value params{Json::objectValue}; params[jss::start] = 10000; // limited to <= 10000 for non admin - auto const result = - env.client().invoke("tx_history", params)[jss::result]; + auto const result = env.client().invoke("tx_history", params)[jss::result]; BEAST_EXPECT(result[jss::status] == "success"); BEAST_EXPECT(result[jss::index] == 10000); } diff --git a/src/test/rpc/Transaction_test.cpp b/src/test/rpc/Transaction_test.cpp index 6947fc91c2..0e212afb21 100644 --- a/src/test/rpc/Transaction_test.cpp +++ b/src/test/rpc/Transaction_test.cpp @@ -40,8 +40,7 @@ class Transaction_test : public beast::unit_test::suite char const* BINARY = jss::binary.c_str(); char const* NOT_FOUND = RPC::get_error_info(rpcTXN_NOT_FOUND).token; char const* INVALID = RPC::get_error_info(rpcINVALID_LGR_RANGE).token; - char const* EXCESSIVE = - RPC::get_error_info(rpcEXCESSIVE_LGR_RANGE).token; + char const* EXCESSIVE = RPC::get_error_info(rpcEXCESSIVE_LGR_RANGE).token; Env env{*this, features}; auto const alice = Account("alice"); @@ -56,8 +55,7 @@ class Transaction_test : public beast::unit_test::suite env(noop(alice)); txns.emplace_back(env.tx()); env.close(); - metas.emplace_back( - env.closed()->txRead(env.tx()->getTransactionID()).second); + metas.emplace_back(env.closed()->txRead(env.tx()->getTransactionID()).second); } auto const endLegSeq = env.closed()->header().seq; @@ -67,19 +65,11 @@ class Transaction_test : public beast::unit_test::suite auto const& tx = txns[i]; auto const& meta = metas[i]; auto const result = env.rpc( - COMMAND, - to_string(tx->getTransactionID()), - BINARY, - to_string(startLegSeq), - to_string(endLegSeq)); + COMMAND, to_string(tx->getTransactionID()), BINARY, to_string(startLegSeq), to_string(endLegSeq)); BEAST_EXPECT(result[jss::result][jss::status] == jss::success); - BEAST_EXPECT( - result[jss::result][jss::tx] == - strHex(tx->getSerializer().getData())); - BEAST_EXPECT( - result[jss::result][jss::meta] == - strHex(meta->getSerializer().getData())); + BEAST_EXPECT(result[jss::result][jss::tx] == strHex(tx->getSerializer().getData())); + BEAST_EXPECT(result[jss::result][jss::meta] == strHex(meta->getSerializer().getData())); } auto const tx = env.jt(noop(alice), seq(env.seq(alice))).stx; @@ -93,8 +83,7 @@ class Transaction_test : public beast::unit_test::suite to_string(endLegSeq + deltaEndSeq)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == NOT_FOUND); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == NOT_FOUND); if (deltaEndSeq) BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool()); @@ -133,23 +122,18 @@ class Transaction_test : public beast::unit_test::suite to_string(endLegSeq + deltaEndSeq)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == NOT_FOUND); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == NOT_FOUND); BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool()); } // Provide range without providing the `binary` // field. (Tests parameter parsing) { - auto const result = env.rpc( - COMMAND, - to_string(tx->getTransactionID()), - to_string(startLegSeq), - to_string(endLegSeq)); + auto const result = + env.rpc(COMMAND, to_string(tx->getTransactionID()), to_string(startLegSeq), to_string(endLegSeq)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == NOT_FOUND); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == NOT_FOUND); BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool()); } @@ -158,14 +142,10 @@ class Transaction_test : public beast::unit_test::suite // field. (Tests parameter parsing) { auto const result = env.rpc( - COMMAND, - to_string(tx->getTransactionID()), - to_string(startLegSeq), - to_string(deletedLedger - 1)); + COMMAND, to_string(tx->getTransactionID()), to_string(startLegSeq), to_string(deletedLedger - 1)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == NOT_FOUND); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == NOT_FOUND); BEAST_EXPECT(result[jss::result][jss::searched_all].asBool()); } @@ -174,10 +154,7 @@ class Transaction_test : public beast::unit_test::suite // field. (Tests parameter parsing) { auto const result = env.rpc( - COMMAND, - to_string(txns[0]->getTransactionID()), - to_string(startLegSeq), - to_string(deletedLedger - 1)); + COMMAND, to_string(txns[0]->getTransactionID()), to_string(startLegSeq), to_string(deletedLedger - 1)); BEAST_EXPECT(result[jss::result][jss::status] == jss::success); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); @@ -192,9 +169,7 @@ class Transaction_test : public beast::unit_test::suite to_string(deletedLedger - 1), to_string(startLegSeq)); - BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == INVALID); + BEAST_EXPECT(result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == INVALID); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } @@ -202,54 +177,35 @@ class Transaction_test : public beast::unit_test::suite // Provide an invalid range: (min < 0) { auto const result = env.rpc( - COMMAND, - to_string(tx->getTransactionID()), - BINARY, - to_string(-1), - to_string(deletedLedger - 1)); + COMMAND, to_string(tx->getTransactionID()), BINARY, to_string(-1), to_string(deletedLedger - 1)); - BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == INVALID); + BEAST_EXPECT(result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == INVALID); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } // Provide an invalid range: (min < 0, max < 0) { - auto const result = env.rpc( - COMMAND, - to_string(tx->getTransactionID()), - BINARY, - to_string(-20), - to_string(-10)); + auto const result = + env.rpc(COMMAND, to_string(tx->getTransactionID()), BINARY, to_string(-20), to_string(-10)); - BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == INVALID); + BEAST_EXPECT(result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == INVALID); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } // Provide an invalid range: (only one value) { - auto const result = env.rpc( - COMMAND, - to_string(tx->getTransactionID()), - BINARY, - to_string(20)); + auto const result = env.rpc(COMMAND, to_string(tx->getTransactionID()), BINARY, to_string(20)); - BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == INVALID); + BEAST_EXPECT(result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == INVALID); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } // Provide an invalid range: (only one value) { - auto const result = env.rpc( - COMMAND, to_string(tx->getTransactionID()), to_string(20)); + auto const result = env.rpc(COMMAND, to_string(tx->getTransactionID()), to_string(20)); // Since we only provided one value for the range, // the interface parses it as a false binary flag, @@ -271,8 +227,7 @@ class Transaction_test : public beast::unit_test::suite to_string(startLegSeq + 1001)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == EXCESSIVE); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == EXCESSIVE); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } @@ -290,8 +245,7 @@ class Transaction_test : public beast::unit_test::suite char const* BINARY = jss::binary.c_str(); char const* NOT_FOUND = RPC::get_error_info(rpcTXN_NOT_FOUND).token; char const* INVALID = RPC::get_error_info(rpcINVALID_LGR_RANGE).token; - char const* EXCESSIVE = - RPC::get_error_info(rpcEXCESSIVE_LGR_RANGE).token; + char const* EXCESSIVE = RPC::get_error_info(rpcEXCESSIVE_LGR_RANGE).token; Env env{*this, makeNetworkConfig(11111)}; uint32_t netID = env.app().config().NETWORK_ID; @@ -308,8 +262,7 @@ class Transaction_test : public beast::unit_test::suite env(noop(alice)); txns.emplace_back(env.tx()); env.close(); - metas.emplace_back( - env.closed()->txRead(env.tx()->getTransactionID()).second); + metas.emplace_back(env.closed()->txRead(env.tx()->getTransactionID()).second); } auto const endLegSeq = env.closed()->header().seq; @@ -327,28 +280,19 @@ class Transaction_test : public beast::unit_test::suite to_string(endLegSeq)); BEAST_EXPECT(result[jss::result][jss::status] == jss::success); - BEAST_EXPECT( - result[jss::result][jss::tx] == - strHex(tx->getSerializer().getData())); - BEAST_EXPECT( - result[jss::result][jss::meta] == - strHex(meta->getSerializer().getData())); + BEAST_EXPECT(result[jss::result][jss::tx] == strHex(tx->getSerializer().getData())); + BEAST_EXPECT(result[jss::result][jss::meta] == strHex(meta->getSerializer().getData())); } auto const tx = env.jt(noop(alice), seq(env.seq(alice))).stx; auto const ctid = *RPC::encodeCTID(endLegSeq, tx->getSeqValue(), netID); for (int deltaEndSeq = 0; deltaEndSeq < 2; ++deltaEndSeq) { - auto const result = env.rpc( - COMMAND, - ctid, - BINARY, - to_string(startLegSeq), - to_string(endLegSeq + deltaEndSeq)); + auto const result = + env.rpc(COMMAND, ctid, BINARY, to_string(startLegSeq), to_string(endLegSeq + deltaEndSeq)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == NOT_FOUND); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == NOT_FOUND); if (deltaEndSeq) BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool()); @@ -382,28 +326,21 @@ class Transaction_test : public beast::unit_test::suite for (int deltaEndSeq = 0; deltaEndSeq < 2; ++deltaEndSeq) { - auto const result = env.rpc( - COMMAND, - ctid, - BINARY, - to_string(startLegSeq), - to_string(endLegSeq + deltaEndSeq)); + auto const result = + env.rpc(COMMAND, ctid, BINARY, to_string(startLegSeq), to_string(endLegSeq + deltaEndSeq)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == NOT_FOUND); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == NOT_FOUND); BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool()); } // Provide range without providing the `binary` // field. (Tests parameter parsing) { - auto const result = env.rpc( - COMMAND, ctid, to_string(startLegSeq), to_string(endLegSeq)); + auto const result = env.rpc(COMMAND, ctid, to_string(startLegSeq), to_string(endLegSeq)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == NOT_FOUND); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == NOT_FOUND); BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool()); } @@ -411,15 +348,10 @@ class Transaction_test : public beast::unit_test::suite // Provide range without providing the `binary` // field. (Tests parameter parsing) { - auto const result = env.rpc( - COMMAND, - ctid, - to_string(startLegSeq), - to_string(deletedLedger - 1)); + auto const result = env.rpc(COMMAND, ctid, to_string(startLegSeq), to_string(deletedLedger - 1)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == NOT_FOUND); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == NOT_FOUND); BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool()); } @@ -441,44 +373,27 @@ class Transaction_test : public beast::unit_test::suite // Provide an invalid range: (min > max) { - auto const result = env.rpc( - COMMAND, - ctid, - BINARY, - to_string(deletedLedger - 1), - to_string(startLegSeq)); + auto const result = env.rpc(COMMAND, ctid, BINARY, to_string(deletedLedger - 1), to_string(startLegSeq)); - BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == INVALID); + BEAST_EXPECT(result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == INVALID); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } // Provide an invalid range: (min < 0) { - auto const result = env.rpc( - COMMAND, - ctid, - BINARY, - to_string(-1), - to_string(deletedLedger - 1)); + auto const result = env.rpc(COMMAND, ctid, BINARY, to_string(-1), to_string(deletedLedger - 1)); - BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == INVALID); + BEAST_EXPECT(result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == INVALID); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } // Provide an invalid range: (min < 0, max < 0) { - auto const result = - env.rpc(COMMAND, ctid, BINARY, to_string(-20), to_string(-10)); + auto const result = env.rpc(COMMAND, ctid, BINARY, to_string(-20), to_string(-10)); - BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == INVALID); + BEAST_EXPECT(result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == INVALID); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } @@ -487,9 +402,7 @@ class Transaction_test : public beast::unit_test::suite { auto const result = env.rpc(COMMAND, ctid, BINARY, to_string(20)); - BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == INVALID); + BEAST_EXPECT(result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == INVALID); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } @@ -510,16 +423,10 @@ class Transaction_test : public beast::unit_test::suite // Provide an invalid range: (max - min > 1000) { - auto const result = env.rpc( - COMMAND, - ctid, - BINARY, - to_string(startLegSeq), - to_string(startLegSeq + 1001)); + auto const result = env.rpc(COMMAND, ctid, BINARY, to_string(startLegSeq), to_string(startLegSeq + 1001)); BEAST_EXPECT( - result[jss::result][jss::status] == jss::error && - result[jss::result][jss::error] == EXCESSIVE); + result[jss::result][jss::status] == jss::error && result[jss::result][jss::error] == EXCESSIVE); BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all)); } @@ -537,8 +444,7 @@ class Transaction_test : public beast::unit_test::suite // Test case 1: Valid input values auto const expected11 = std::optional("CFFFFFFFFFFFFFFF"); - BEAST_EXPECT( - RPC::encodeCTID(0x0FFF'FFFFUL, 0xFFFFU, 0xFFFFU) == expected11); + BEAST_EXPECT(RPC::encodeCTID(0x0FFF'FFFFUL, 0xFFFFU, 0xFFFFU) == expected11); auto const expected12 = std::optional("C000000000000000"); BEAST_EXPECT(RPC::encodeCTID(0, 0, 0) == expected12); auto const expected13 = std::optional("C000000100020003"); @@ -556,17 +462,12 @@ class Transaction_test : public beast::unit_test::suite BEAST_EXPECT(!RPC::encodeCTID(0x0FFF'FFFFUL, 0xFFFFU, 0x1'0000U)); // Test case 5: Valid input values - auto const expected51 = - std::optional>( - std::make_tuple(0, 0, 0)); + auto const expected51 = std::optional>(std::make_tuple(0, 0, 0)); BEAST_EXPECT(RPC::decodeCTID("C000000000000000") == expected51); - auto const expected52 = - std::optional>( - std::make_tuple(1U, 2U, 3U)); + auto const expected52 = std::optional>(std::make_tuple(1U, 2U, 3U)); BEAST_EXPECT(RPC::decodeCTID("C000000100020003") == expected52); auto const expected53 = - std::optional>( - std::make_tuple(13249191UL, 12911U, 49221U)); + std::optional>(std::make_tuple(13249191UL, 12911U, 49221U)); BEAST_EXPECT(RPC::decodeCTID("C0CA2AA7326FC045") == expected53); // Test case 6: ctid not a string or big int @@ -587,20 +488,16 @@ class Transaction_test : public beast::unit_test::suite // Test case 11: Valid input values BEAST_EXPECT( (RPC::decodeCTID(0xCFFF'FFFF'FFFF'FFFFULL) == - std::optional>( - std::make_tuple(0x0FFF'FFFFUL, 0xFFFFU, 0xFFFFU)))); + std::optional>(std::make_tuple(0x0FFF'FFFFUL, 0xFFFFU, 0xFFFFU)))); BEAST_EXPECT( (RPC::decodeCTID(0xC000'0000'0000'0000ULL) == - std::optional>( - std::make_tuple(0, 0, 0)))); + std::optional>(std::make_tuple(0, 0, 0)))); BEAST_EXPECT( (RPC::decodeCTID(0xC000'0001'0002'0003ULL) == - std::optional>( - std::make_tuple(1U, 2U, 3U)))); + std::optional>(std::make_tuple(1U, 2U, 3U)))); BEAST_EXPECT( (RPC::decodeCTID(0xC0CA'2AA7'326F'C045ULL) == - std::optional>( - std::make_tuple(1324'9191UL, 12911U, 49221U)))); + std::optional>(std::make_tuple(1324'9191UL, 12911U, 49221U)))); // Test case 12: ctid not exactly 16 nibbles BEAST_EXPECT(!RPC::decodeCTID(0xC003'FFFF'FFFF'FFF)); @@ -647,8 +544,7 @@ class Transaction_test : public beast::unit_test::suite jsonTx[jss::binary] = false; jsonTx[jss::ctid] = *ctid; jsonTx[jss::id] = 1; - auto const jrr = - env.rpc("json", "tx", to_string(jsonTx))[jss::result]; + auto const jrr = env.rpc("json", "tx", to_string(jsonTx))[jss::result]; BEAST_EXPECT(jrr[jss::ctid] == ctid); BEAST_EXPECT(jrr.isMember(jss::hash)); } @@ -671,14 +567,12 @@ class Transaction_test : public beast::unit_test::suite // Verify that there are at least two upper case letters in ctid and // test a mixed case - if (BEAST_EXPECT( - std::count_if(ctid.begin(), ctid.end(), isUpper) > 1)) + if (BEAST_EXPECT(std::count_if(ctid.begin(), ctid.end(), isUpper) > 1)) { // Change the first upper case letter to lower case. std::string mixedCase = ctid; { - auto const iter = std::find_if( - mixedCase.begin(), mixedCase.end(), isUpper); + auto const iter = std::find_if(mixedCase.begin(), mixedCase.end(), isUpper); *iter = std::tolower(*iter); } BEAST_EXPECT(ctid != mixedCase); @@ -687,8 +581,7 @@ class Transaction_test : public beast::unit_test::suite jsonTx[jss::binary] = false; jsonTx[jss::ctid] = mixedCase; jsonTx[jss::id] = 1; - Json::Value const jrr = - env.rpc("json", "tx", to_string(jsonTx))[jss::result]; + Json::Value const jrr = env.rpc("json", "tx", to_string(jsonTx))[jss::result]; BEAST_EXPECT(jrr[jss::ctid] == ctid); BEAST_EXPECT(jrr[jss::hash]); } @@ -718,8 +611,7 @@ class Transaction_test : public beast::unit_test::suite params[jss::id] = 1; auto const hash = env.tx()->getJson(JsonOptions::none)[jss::hash]; params[jss::transaction] = hash; - auto const jrr = - env.rpc("json", "tx", to_string(params))[jss::result]; + auto const jrr = env.rpc("json", "tx", to_string(params))[jss::result]; BEAST_EXPECT(jrr[jss::hash] == hash); BEAST_EXPECT(jrr.isMember(jss::ctid) == (netID <= 0xFFFF)); @@ -748,8 +640,7 @@ class Transaction_test : public beast::unit_test::suite jsonTx[jss::binary] = false; jsonTx[jss::ctid] = ctid; jsonTx[jss::id] = 1; - auto const jrr = - env.rpc("json", "tx", to_string(jsonTx))[jss::result]; + auto const jrr = env.rpc("json", "tx", to_string(jsonTx))[jss::result]; BEAST_EXPECT(jrr[jss::error] == "wrongNetwork"); BEAST_EXPECT(jrr[jss::error_code] == rpcWRONG_NETWORK); BEAST_EXPECT( @@ -787,8 +678,7 @@ class Transaction_test : public beast::unit_test::suite std::shared_ptr txn = env.tx(); env.close(); - std::shared_ptr meta = - env.closed()->txRead(env.tx()->getTransactionID()).second; + std::shared_ptr meta = env.closed()->txRead(env.tx()->getTransactionID()).second; Json::Value expected = txn->getJson(JsonOptions::none); expected[jss::DeliverMax] = expected[jss::Amount]; @@ -809,12 +699,8 @@ class Transaction_test : public beast::unit_test::suite BEAST_EXPECT(result[jss::result][jss::status] == jss::success); if (apiVersion > 1) { - BEAST_EXPECT( - result[jss::result][jss::close_time_iso] == - "2000-01-01T00:00:20Z"); - BEAST_EXPECT( - result[jss::result][jss::hash] == - to_string(txn->getTransactionID())); + BEAST_EXPECT(result[jss::result][jss::close_time_iso] == "2000-01-01T00:00:20Z"); + BEAST_EXPECT(result[jss::result][jss::hash] == to_string(txn->getTransactionID())); BEAST_EXPECT(result[jss::result][jss::validated] == true); BEAST_EXPECT(result[jss::result][jss::ledger_index] == 4); BEAST_EXPECT( @@ -823,13 +709,10 @@ class Transaction_test : public beast::unit_test::suite "D2"); } - for (auto memberIt = expected.begin(); memberIt != expected.end(); - memberIt++) + for (auto memberIt = expected.begin(); memberIt != expected.end(); memberIt++) { std::string const name = memberIt.memberName(); - auto const& result_transaction = - (apiVersion > 1 ? result[jss::result][jss::tx_json] - : result[jss::result]); + auto const& result_transaction = (apiVersion > 1 ? result[jss::result][jss::tx_json] : result[jss::result]); if (BEAST_EXPECT(result_transaction.isMember(name))) { auto const received = result_transaction[name]; @@ -846,8 +729,7 @@ class Transaction_test : public beast::unit_test::suite void testBinaryRequest(unsigned apiVersion) { - testcase( - "Test binary request API version " + std::to_string(apiVersion)); + testcase("Test binary request API version " + std::to_string(apiVersion)); using namespace test::jtx; using std::to_string; @@ -863,11 +745,9 @@ class Transaction_test : public beast::unit_test::suite env.fund(XRP(1000000), alice, gw); std::shared_ptr const txn = env.tx(); BEAST_EXPECT( - to_string(txn->getTransactionID()) == - "3F8BDE5A5F82C4F4708E5E9255B713E303E6E1A371FD5C7A704AFD1387C23981"); + to_string(txn->getTransactionID()) == "3F8BDE5A5F82C4F4708E5E9255B713E303E6E1A371FD5C7A704AFD1387C23981"); env.close(); - std::shared_ptr meta = - env.closed()->txRead(txn->getTransactionID()).second; + std::shared_ptr meta = env.closed()->txRead(txn->getTransactionID()).second; std::string const expected_tx_blob = serializeHex(*txn); std::string const expected_meta_blob = serializeHex(*meta); @@ -884,31 +764,24 @@ class Transaction_test : public beast::unit_test::suite { BEAST_EXPECT(result[jss::result][jss::status] == "success"); BEAST_EXPECT(result[jss::result][jss::validated] == true); - BEAST_EXPECT( - result[jss::result][jss::hash] == - to_string(txn->getTransactionID())); + BEAST_EXPECT(result[jss::result][jss::hash] == to_string(txn->getTransactionID())); BEAST_EXPECT(result[jss::result][jss::ledger_index] == 3); BEAST_EXPECT(result[jss::result][jss::ctid] == "C000000300030000"); if (apiVersion > 1) { - BEAST_EXPECT( - result[jss::result][jss::tx_blob] == expected_tx_blob); - BEAST_EXPECT( - result[jss::result][jss::meta_blob] == expected_meta_blob); + BEAST_EXPECT(result[jss::result][jss::tx_blob] == expected_tx_blob); + BEAST_EXPECT(result[jss::result][jss::meta_blob] == expected_meta_blob); BEAST_EXPECT( result[jss::result][jss::ledger_hash] == "2D5150E5A5AA436736A732291E437ABF01BC9E206C2DF3C77C4F856915" "7905AA"); - BEAST_EXPECT( - result[jss::result][jss::close_time_iso] == - "2000-01-01T00:00:10Z"); + BEAST_EXPECT(result[jss::result][jss::close_time_iso] == "2000-01-01T00:00:10Z"); } else { BEAST_EXPECT(result[jss::result][jss::tx] == expected_tx_blob); - BEAST_EXPECT( - result[jss::result][jss::meta] == expected_meta_blob); + BEAST_EXPECT(result[jss::result][jss::meta] == expected_meta_blob); BEAST_EXPECT(result[jss::result][jss::date] == 10); } } @@ -919,8 +792,7 @@ public: run() override { using namespace test::jtx; - forAllApiVersions( - std::bind_front(&Transaction_test::testBinaryRequest, this)); + forAllApiVersions(std::bind_front(&Transaction_test::testBinaryRequest, this)); FeatureBitset const all{testable_amendments()}; testWithFeats(all); @@ -933,8 +805,7 @@ public: testRangeCTIDRequest(features); testCTIDValidation(features); testCTIDRPC(features); - forAllApiVersions( - std::bind_front(&Transaction_test::testRequest, this, features)); + forAllApiVersions(std::bind_front(&Transaction_test::testRequest, this, features)); } }; diff --git a/src/test/rpc/ValidatorInfo_test.cpp b/src/test/rpc/ValidatorInfo_test.cpp index a8fccc724b..41fa95940b 100644 --- a/src/test/rpc/ValidatorInfo_test.cpp +++ b/src/test/rpc/ValidatorInfo_test.cpp @@ -25,8 +25,7 @@ public: { Env env(*this); auto const info = env.rpc("validator_info"); - BEAST_EXPECT( - info[jss::result][jss::error_message] == "not a validator"); + BEAST_EXPECT(info[jss::result][jss::error_message] == "not a validator"); } } @@ -69,10 +68,8 @@ public: "VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0ifQ==" "\n"}; - std::string const master_key = - "nHBt9fsb4849WmZiCds4r5TXyBeQjqnH5kzPtqgMAQMgi39YZRPa"; - std::string const ephemeral_key = - "n9KsDYGKhABVc4wK5u3MnVhgPinyJimyKGpr9VJYuBaY8EnJXR2x"; + std::string const master_key = "nHBt9fsb4849WmZiCds4r5TXyBeQjqnH5kzPtqgMAQMgi39YZRPa"; + std::string const ephemeral_key = "n9KsDYGKhABVc4wK5u3MnVhgPinyJimyKGpr9VJYuBaY8EnJXR2x"; std::string const manifest = "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/" "vCxHXXLplc2GnMhAkE1agqXxBwDwDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQI" @@ -90,8 +87,7 @@ public: BEAST_EXPECT(info[jss::result][jss::seq] == 1); BEAST_EXPECT(info[jss::result][jss::master_key] == master_key); BEAST_EXPECT(info[jss::result][jss::manifest] == manifest); - BEAST_EXPECT( - info[jss::result][jss::ephemeral_key] == ephemeral_key); + BEAST_EXPECT(info[jss::result][jss::ephemeral_key] == ephemeral_key); } } diff --git a/src/test/rpc/ValidatorRPC_test.cpp b/src/test/rpc/ValidatorRPC_test.cpp index cf8741e507..a46d198b5a 100644 --- a/src/test/rpc/ValidatorRPC_test.cpp +++ b/src/test/rpc/ValidatorRPC_test.cpp @@ -51,17 +51,14 @@ public: Env env{*this, isAdmin ? envconfig() : envconfig(no_admin)}; auto const jrr = env.rpc("server_info")[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); - BEAST_EXPECT( - jrr[jss::info].isMember(jss::validator_list) == isAdmin); + BEAST_EXPECT(jrr[jss::info].isMember(jss::validator_list) == isAdmin); } { Env env{*this, isAdmin ? envconfig() : envconfig(no_admin)}; auto const jrr = env.rpc("server_state")[jss::result]; BEAST_EXPECT(jrr[jss::status] == "success"); - BEAST_EXPECT( - jrr[jss::state].isMember(jss::validator_list_expires) == - isAdmin); + BEAST_EXPECT(jrr[jss::state].isMember(jss::validator_list_expires) == isAdmin); } } } @@ -86,9 +83,7 @@ public: // Server info reports maximum expiration since not dynamic { auto const jrr = env.rpc("server_info")[jss::result]; - BEAST_EXPECT( - jrr[jss::info][jss::validator_list][jss::expiration] == - "never"); + BEAST_EXPECT(jrr[jss::info][jss::validator_list][jss::expiration] == "never"); } { auto const jrr = env.rpc("server_state")[jss::result]; @@ -101,8 +96,7 @@ public: auto const jrr = env.rpc("validators")[jss::result]; BEAST_EXPECT(jrr[jss::validator_list][jss::expiration] == "never"); BEAST_EXPECT(jrr[jss::validation_quorum].asUInt() == keys.size()); - BEAST_EXPECT( - jrr[jss::trusted_validator_keys].size() == keys.size()); + BEAST_EXPECT(jrr[jss::trusted_validator_keys].size() == keys.size()); BEAST_EXPECT(jrr[jss::publisher_lists].size() == 0); BEAST_EXPECT(jrr[jss::local_static_keys].size() == keys.size()); for (auto const& jKey : jrr[jss::local_static_keys]) @@ -136,12 +130,10 @@ public: BEAST_EXPECT(jrrnUnlSize == 2); for (std::uint32_t x = 0; x < jrrnUnlSize; ++x) { - auto parsedKey = parseBase58( - TokenType::NodePublic, jrrnUnl[x].asString()); + auto parsedKey = parseBase58(TokenType::NodePublic, jrrnUnl[x].asString()); BEAST_EXPECT(parsedKey); if (parsedKey) - BEAST_EXPECT( - disabledKeys.find(*parsedKey) != disabledKeys.end()); + BEAST_EXPECT(disabledKeys.find(*parsedKey) != disabledKeys.end()); } disabledKeys.clear(); @@ -156,14 +148,11 @@ public: { using namespace test::jtx; - auto toStr = [](PublicKey const& publicKey) { - return toBase58(TokenType::NodePublic, publicKey); - }; + auto toStr = [](PublicKey const& publicKey) { return toBase58(TokenType::NodePublic, publicKey); }; // Validator keys that will be in the published list std::vector validators = { - TrustedPublisherServer::randomValidator(), - TrustedPublisherServer::randomValidator()}; + TrustedPublisherServer::randomValidator(), TrustedPublisherServer::randomValidator()}; std::set expectedKeys; for (auto const& val : validators) expectedKeys.insert(toStr(val.masterPublic)); @@ -175,28 +164,20 @@ public: NetClock::time_point const validFrom2{validUntil - 60s}; NetClock::time_point const validUntil2{validFrom2 + 3600s}; auto server = make_TrustedPublisherServer( - worker.get_io_context(), - validators, - validUntil, - {{validFrom2, validUntil2}}, - false, - 1, - false); + worker.get_io_context(), validators, validUntil, {{validFrom2, validUntil2}}, false, 1, false); //---------------------------------------------------------------------- // Publisher list site unavailable v1 { // Publisher site information using namespace std::string_literals; - std::string siteURI = - "http://"s + getEnvLocalhostAddr() + ":1234/validators"; + std::string siteURI = "http://"s + getEnvLocalhostAddr() + ":1234/validators"; Env env{ *this, envconfig([&](std::unique_ptr cfg) { cfg->section(SECTION_VALIDATOR_LIST_SITES).append(siteURI); - cfg->section(SECTION_VALIDATOR_LIST_KEYS) - .append(strHex(server->publisherPublic())); + cfg->section(SECTION_VALIDATOR_LIST_KEYS).append(strHex(server->publisherPublic())); return cfg; }), }; @@ -206,24 +187,18 @@ public: { auto const jrr = env.rpc("server_info")[jss::result]; - BEAST_EXPECT( - jrr[jss::info][jss::validator_list][jss::expiration] == - "unknown"); + BEAST_EXPECT(jrr[jss::info][jss::validator_list][jss::expiration] == "unknown"); } { auto const jrr = env.rpc("server_state")[jss::result]; - BEAST_EXPECT( - jrr[jss::state][jss::validator_list_expires].asInt() == 0); + BEAST_EXPECT(jrr[jss::state][jss::validator_list_expires].asInt() == 0); } { auto const jrr = env.rpc("validators")[jss::result]; - BEAST_EXPECT( - jrr[jss::validation_quorum].asUInt() == - std::numeric_limits::max()); + BEAST_EXPECT(jrr[jss::validation_quorum].asUInt() == std::numeric_limits::max()); BEAST_EXPECT(jrr[jss::local_static_keys].size() == 0); BEAST_EXPECT(jrr[jss::trusted_validator_keys].size() == 0); - BEAST_EXPECT( - jrr[jss::validator_list][jss::expiration] == "unknown"); + BEAST_EXPECT(jrr[jss::validator_list][jss::expiration] == "unknown"); if (BEAST_EXPECT(jrr[jss::publisher_lists].size() == 1)) { @@ -233,9 +208,7 @@ public: BEAST_EXPECT(!jp.isMember(jss::seq)); BEAST_EXPECT(!jp.isMember(jss::expiration)); BEAST_EXPECT(!jp.isMember(jss::version)); - BEAST_EXPECT( - jp[jss::pubkey_publisher] == - strHex(server->publisherPublic())); + BEAST_EXPECT(jp[jss::pubkey_publisher] == strHex(server->publisherPublic())); } BEAST_EXPECT(jrr[jss::signing_keys].size() == 0); } @@ -255,15 +228,13 @@ public: { // Publisher site information using namespace std::string_literals; - std::string siteURI = - "http://"s + getEnvLocalhostAddr() + ":1234/validators2"; + std::string siteURI = "http://"s + getEnvLocalhostAddr() + ":1234/validators2"; Env env{ *this, envconfig([&](std::unique_ptr cfg) { cfg->section(SECTION_VALIDATOR_LIST_SITES).append(siteURI); - cfg->section(SECTION_VALIDATOR_LIST_KEYS) - .append(strHex(server->publisherPublic())); + cfg->section(SECTION_VALIDATOR_LIST_KEYS).append(strHex(server->publisherPublic())); return cfg; }), }; @@ -273,24 +244,18 @@ public: { auto const jrr = env.rpc("server_info")[jss::result]; - BEAST_EXPECT( - jrr[jss::info][jss::validator_list][jss::expiration] == - "unknown"); + BEAST_EXPECT(jrr[jss::info][jss::validator_list][jss::expiration] == "unknown"); } { auto const jrr = env.rpc("server_state")[jss::result]; - BEAST_EXPECT( - jrr[jss::state][jss::validator_list_expires].asInt() == 0); + BEAST_EXPECT(jrr[jss::state][jss::validator_list_expires].asInt() == 0); } { auto const jrr = env.rpc("validators")[jss::result]; - BEAST_EXPECT( - jrr[jss::validation_quorum].asUInt() == - std::numeric_limits::max()); + BEAST_EXPECT(jrr[jss::validation_quorum].asUInt() == std::numeric_limits::max()); BEAST_EXPECT(jrr[jss::local_static_keys].size() == 0); BEAST_EXPECT(jrr[jss::trusted_validator_keys].size() == 0); - BEAST_EXPECT( - jrr[jss::validator_list][jss::expiration] == "unknown"); + BEAST_EXPECT(jrr[jss::validator_list][jss::expiration] == "unknown"); if (BEAST_EXPECT(jrr[jss::publisher_lists].size() == 1)) { @@ -300,9 +265,7 @@ public: BEAST_EXPECT(!jp.isMember(jss::seq)); BEAST_EXPECT(!jp.isMember(jss::expiration)); BEAST_EXPECT(!jp.isMember(jss::version)); - BEAST_EXPECT( - jp[jss::pubkey_publisher] == - strHex(server->publisherPublic())); + BEAST_EXPECT(jp[jss::pubkey_publisher] == strHex(server->publisherPublic())); } BEAST_EXPECT(jrr[jss::signing_keys].size() == 0); } @@ -331,8 +294,7 @@ public: *this, envconfig([&](std::unique_ptr cfg) { cfg->section(SECTION_VALIDATOR_LIST_SITES).append(siteURI); - cfg->section(SECTION_VALIDATOR_LIST_KEYS) - .append(strHex(server->publisherPublic())); + cfg->section(SECTION_VALIDATOR_LIST_KEYS).append(strHex(server->publisherPublic())); return cfg; }), }; @@ -344,35 +306,24 @@ public: startKeys.insert(calcNodeID(val.masterPublic)); env.app().validators().updateTrusted( - startKeys, - env.timeKeeper().now(), - env.app().getOPs(), - env.app().overlay(), - env.app().getHashRouter()); + startKeys, env.timeKeeper().now(), env.app().getOPs(), env.app().overlay(), env.app().getHashRouter()); { auto const jrr = env.rpc("server_info")[jss::result]; - BEAST_EXPECT( - jrr[jss::info][jss::validator_list][jss::expiration] == - to_string(validUntil)); + BEAST_EXPECT(jrr[jss::info][jss::validator_list][jss::expiration] == to_string(validUntil)); } { auto const jrr = env.rpc("server_state")[jss::result]; BEAST_EXPECT( - jrr[jss::state][jss::validator_list_expires].asUInt() == - validUntil.time_since_epoch().count()); + jrr[jss::state][jss::validator_list_expires].asUInt() == validUntil.time_since_epoch().count()); } { auto const jrr = env.rpc("validators")[jss::result]; BEAST_EXPECT(jrr[jss::validation_quorum].asUInt() == 2); - BEAST_EXPECT( - jrr[jss::validator_list][jss::expiration] == - to_string(validUntil)); + BEAST_EXPECT(jrr[jss::validator_list][jss::expiration] == to_string(validUntil)); BEAST_EXPECT(jrr[jss::local_static_keys].size() == 0); - BEAST_EXPECT( - jrr[jss::trusted_validator_keys].size() == - expectedKeys.size()); + BEAST_EXPECT(jrr[jss::trusted_validator_keys].size() == expectedKeys.size()); for (auto const& jKey : jrr[jss::trusted_validator_keys]) { BEAST_EXPECT(expectedKeys.count(jKey.asString()) == 1); @@ -393,9 +344,7 @@ public: BEAST_EXPECT(foundKeys == expectedKeys); } BEAST_EXPECT(jp[jss::seq].asUInt() == 1); - BEAST_EXPECT( - jp[jss::pubkey_publisher] == - strHex(server->publisherPublic())); + BEAST_EXPECT(jp[jss::pubkey_publisher] == strHex(server->publisherPublic())); BEAST_EXPECT(jp[jss::expiration] == to_string(validUntil)); BEAST_EXPECT(jp[jss::version] == 1); } @@ -404,9 +353,7 @@ public: for (auto const& val : validators) { BEAST_EXPECT(jsk.isMember(toStr(val.masterPublic))); - BEAST_EXPECT( - jsk[toStr(val.masterPublic)] == - toStr(val.signingPublic)); + BEAST_EXPECT(jsk[toStr(val.masterPublic)] == toStr(val.signingPublic)); } } { @@ -433,8 +380,7 @@ public: *this, envconfig([&](std::unique_ptr cfg) { cfg->section(SECTION_VALIDATOR_LIST_SITES).append(siteURI); - cfg->section(SECTION_VALIDATOR_LIST_KEYS) - .append(strHex(server->publisherPublic())); + cfg->section(SECTION_VALIDATOR_LIST_KEYS).append(strHex(server->publisherPublic())); return cfg; }), }; @@ -446,35 +392,24 @@ public: startKeys.insert(calcNodeID(val.masterPublic)); env.app().validators().updateTrusted( - startKeys, - env.timeKeeper().now(), - env.app().getOPs(), - env.app().overlay(), - env.app().getHashRouter()); + startKeys, env.timeKeeper().now(), env.app().getOPs(), env.app().overlay(), env.app().getHashRouter()); { auto const jrr = env.rpc("server_info")[jss::result]; - BEAST_EXPECT( - jrr[jss::info][jss::validator_list][jss::expiration] == - to_string(validUntil2)); + BEAST_EXPECT(jrr[jss::info][jss::validator_list][jss::expiration] == to_string(validUntil2)); } { auto const jrr = env.rpc("server_state")[jss::result]; BEAST_EXPECT( - jrr[jss::state][jss::validator_list_expires].asUInt() == - validUntil2.time_since_epoch().count()); + jrr[jss::state][jss::validator_list_expires].asUInt() == validUntil2.time_since_epoch().count()); } { auto const jrr = env.rpc("validators")[jss::result]; BEAST_EXPECT(jrr[jss::validation_quorum].asUInt() == 2); - BEAST_EXPECT( - jrr[jss::validator_list][jss::expiration] == - to_string(validUntil2)); + BEAST_EXPECT(jrr[jss::validator_list][jss::expiration] == to_string(validUntil2)); BEAST_EXPECT(jrr[jss::local_static_keys].size() == 0); - BEAST_EXPECT( - jrr[jss::trusted_validator_keys].size() == - expectedKeys.size()); + BEAST_EXPECT(jrr[jss::trusted_validator_keys].size() == expectedKeys.size()); for (auto const& jKey : jrr[jss::trusted_validator_keys]) { BEAST_EXPECT(expectedKeys.count(jKey.asString()) == 1); @@ -495,13 +430,10 @@ public: BEAST_EXPECT(foundKeys == expectedKeys); } BEAST_EXPECT(jp[jss::seq].asUInt() == 1); - BEAST_EXPECT( - jp[jss::pubkey_publisher] == - strHex(server->publisherPublic())); + BEAST_EXPECT(jp[jss::pubkey_publisher] == strHex(server->publisherPublic())); BEAST_EXPECT(jp[jss::expiration] == to_string(validUntil)); BEAST_EXPECT(jp[jss::version] == 2); - if (BEAST_EXPECT(jp.isMember(jss::remaining)) && - BEAST_EXPECT(jp[jss::remaining].isArray()) && + if (BEAST_EXPECT(jp.isMember(jss::remaining)) && BEAST_EXPECT(jp[jss::remaining].isArray()) && BEAST_EXPECT(jp[jss::remaining].size() == 1)) { auto const& r = jp[jss::remaining][0u]; @@ -516,10 +448,8 @@ public: BEAST_EXPECT(foundKeys == expectedKeys); } BEAST_EXPECT(r[jss::seq].asUInt() == 2); - BEAST_EXPECT( - r[jss::effective] == to_string(validFrom2)); - BEAST_EXPECT( - r[jss::expiration] == to_string(validUntil2)); + BEAST_EXPECT(r[jss::effective] == to_string(validFrom2)); + BEAST_EXPECT(r[jss::expiration] == to_string(validUntil2)); } } auto jsk = jrr[jss::signing_keys]; @@ -527,9 +457,7 @@ public: for (auto const& val : validators) { BEAST_EXPECT(jsk.isMember(toStr(val.masterPublic))); - BEAST_EXPECT( - jsk[toStr(val.masterPublic)] == - toStr(val.signingPublic)); + BEAST_EXPECT(jsk[toStr(val.masterPublic)] == toStr(val.signingPublic)); } } { @@ -554,15 +482,9 @@ public: using namespace test::jtx; Env env{*this}; auto result = env.rpc("validation_create"); - BEAST_EXPECT( - result.isMember(jss::result) && - result[jss::result][jss::status] == "success"); - result = env.rpc( - "validation_create", - "BAWL MAN JADE MOON DOVE GEM SON NOW HAD ADEN GLOW TIRE"); - BEAST_EXPECT( - result.isMember(jss::result) && - result[jss::result][jss::status] == "success"); + BEAST_EXPECT(result.isMember(jss::result) && result[jss::result][jss::status] == "success"); + result = env.rpc("validation_create", "BAWL MAN JADE MOON DOVE GEM SON NOW HAD ADEN GLOW TIRE"); + BEAST_EXPECT(result.isMember(jss::result) && result[jss::result][jss::status] == "success"); } void diff --git a/src/test/rpc/Version_test.cpp b/src/test/rpc/Version_test.cpp index fd4bfdd565..1dec8627ed 100644 --- a/src/test/rpc/Version_test.cpp +++ b/src/test/rpc/Version_test.cpp @@ -24,9 +24,7 @@ class Version_test : public beast::unit_test::suite auto jrr = env.rpc( "json", "version", - "{\"api_version\": " + - std::to_string(RPC::apiMaximumSupportedVersion) + - "}")[jss::result]; + "{\"api_version\": " + std::to_string(RPC::apiMaximumSupportedVersion) + "}")[jss::result]; BEAST_EXPECT(isCorrectReply(jrr)); jrr = env.rpc("version")[jss::result]; @@ -45,17 +43,13 @@ class Version_test : public beast::unit_test::suite if (re.isMember("error_what")) if (re["error_what"].isString()) { - return re["error_what"].asString().find( - jss::invalid_API_version.c_str()) == 0; + return re["error_what"].asString().find(jss::invalid_API_version.c_str()) == 0; } return false; }; auto re = env.rpc( - "json", - "version", - "{\"api_version\": " + - std::to_string(RPC::apiMinimumSupportedVersion - 1) + "}"); + "json", "version", "{\"api_version\": " + std::to_string(RPC::apiMinimumSupportedVersion - 1) + "}"); BEAST_EXPECT(badVersion(re)); BEAST_EXPECT(env.app().config().BETA_RPC_API); @@ -63,12 +57,7 @@ class Version_test : public beast::unit_test::suite "json", "version", "{\"api_version\": " + - std::to_string( - std::max( - RPC::apiMaximumSupportedVersion.value, - RPC::apiBetaVersion.value) + - 1) + - "}"); + std::to_string(std::max(RPC::apiMaximumSupportedVersion.value, RPC::apiBetaVersion.value) + 1) + "}"); BEAST_EXPECT(badVersion(re)); re = env.rpc("json", "version", "{\"api_version\": \"a\"}"); @@ -80,57 +69,38 @@ class Version_test : public beast::unit_test::suite { testcase("test getAPIVersionNumber function"); - unsigned int versionIfUnspecified = - RPC::apiVersionIfUnspecified < RPC::apiMinimumSupportedVersion + unsigned int versionIfUnspecified = RPC::apiVersionIfUnspecified < RPC::apiMinimumSupportedVersion ? RPC::apiInvalidVersion : RPC::apiVersionIfUnspecified; Json::Value j_array = Json::Value(Json::arrayValue); Json::Value j_null = Json::Value(Json::nullValue); - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_array, false) == versionIfUnspecified); - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_null, false) == versionIfUnspecified); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_array, false) == versionIfUnspecified); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_null, false) == versionIfUnspecified); Json::Value j_object = Json::Value(Json::objectValue); - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, false) == versionIfUnspecified); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, false) == versionIfUnspecified); j_object[jss::api_version] = RPC::apiVersionIfUnspecified.value; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, false) == versionIfUnspecified); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, false) == versionIfUnspecified); j_object[jss::api_version] = RPC::apiMinimumSupportedVersion.value; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, false) == - RPC::apiMinimumSupportedVersion); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, false) == RPC::apiMinimumSupportedVersion); j_object[jss::api_version] = RPC::apiMaximumSupportedVersion.value; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, false) == - RPC::apiMaximumSupportedVersion); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, false) == RPC::apiMaximumSupportedVersion); j_object[jss::api_version] = RPC::apiMinimumSupportedVersion - 1; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, false) == - RPC::apiInvalidVersion); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); j_object[jss::api_version] = RPC::apiMaximumSupportedVersion + 1; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, false) == - RPC::apiInvalidVersion); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); j_object[jss::api_version] = RPC::apiBetaVersion.value; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, true) == RPC::apiBetaVersion); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, true) == RPC::apiBetaVersion); j_object[jss::api_version] = RPC::apiBetaVersion + 1; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, true) == RPC::apiInvalidVersion); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, true) == RPC::apiInvalidVersion); j_object[jss::api_version] = RPC::apiInvalidVersion.value; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, false) == - RPC::apiInvalidVersion); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); j_object[jss::api_version] = "a"; - BEAST_EXPECT( - RPC::getAPIVersionNumber(j_object, false) == - RPC::apiInvalidVersion); + BEAST_EXPECT(RPC::getAPIVersionNumber(j_object, false) == RPC::apiInvalidVersion); } void @@ -155,19 +125,14 @@ class Version_test : public beast::unit_test::suite "\"params\": { " "\"api_version\": " + std::to_string(RPC::apiMaximumSupportedVersion) + "}}"; - auto re = env.rpc( - "json2", '[' + without_api_verion + ", " + with_api_verion + ']'); + auto re = env.rpc("json2", '[' + without_api_verion + ", " + with_api_verion + ']'); if (!BEAST_EXPECT(re.isArray())) return; if (!BEAST_EXPECT(re.size() == 2)) return; - BEAST_EXPECT( - re[0u].isMember(jss::result) && - re[0u][jss::result].isMember(jss::version)); - BEAST_EXPECT( - re[1u].isMember(jss::result) && - re[1u][jss::result].isMember(jss::version)); + BEAST_EXPECT(re[0u].isMember(jss::result) && re[0u][jss::result].isMember(jss::version)); + BEAST_EXPECT(re[1u].isMember(jss::result) && re[1u][jss::result].isMember(jss::version)); } void @@ -192,22 +157,14 @@ class Version_test : public beast::unit_test::suite "\"method\": \"version\", " "\"params\": { " "\"api_version\": " + - std::to_string(std::max( - RPC::apiMaximumSupportedVersion.value, - RPC::apiBetaVersion.value) + - 1) + - "}}"; - auto re = env.rpc( - "json2", - '[' + without_api_verion + ", " + with_wrong_api_verion + ']'); + std::to_string(std::max(RPC::apiMaximumSupportedVersion.value, RPC::apiBetaVersion.value) + 1) + "}}"; + auto re = env.rpc("json2", '[' + without_api_verion + ", " + with_wrong_api_verion + ']'); if (!BEAST_EXPECT(re.isArray())) return; if (!BEAST_EXPECT(re.size() == 2)) return; - BEAST_EXPECT( - re[0u].isMember(jss::result) && - re[0u][jss::result].isMember(jss::version)); + BEAST_EXPECT(re[0u].isMember(jss::result) && re[0u][jss::result].isMember(jss::version)); BEAST_EXPECT(re[1u].isMember(jss::error)); } @@ -246,20 +203,14 @@ class Version_test : public beast::unit_test::suite if (!BEAST_EXPECT(env.app().config().BETA_RPC_API == true)) return; - auto jrr = env.rpc( - "json", - "version", - "{\"api_version\": " + std::to_string(RPC::apiBetaVersion) + - "}")[jss::result]; + auto jrr = + env.rpc("json", "version", "{\"api_version\": " + std::to_string(RPC::apiBetaVersion) + "}")[jss::result]; if (!BEAST_EXPECT(jrr.isMember(jss::version))) return; - if (!BEAST_EXPECT(jrr[jss::version].isMember(jss::first)) && - jrr[jss::version].isMember(jss::last)) + if (!BEAST_EXPECT(jrr[jss::version].isMember(jss::first)) && jrr[jss::version].isMember(jss::last)) return; - BEAST_EXPECT( - jrr[jss::version][jss::first] == - RPC::apiMinimumSupportedVersion.value); + BEAST_EXPECT(jrr[jss::version][jss::first] == RPC::apiMinimumSupportedVersion.value); BEAST_EXPECT(jrr[jss::version][jss::last] == RPC::apiBetaVersion.value); } diff --git a/src/test/server/ServerStatus_test.cpp b/src/test/server/ServerStatus_test.cpp index a2516126de..ccfdf2fd2b 100644 --- a/src/test/server/ServerStatus_test.cpp +++ b/src/test/server/ServerStatus_test.cpp @@ -27,21 +27,16 @@ namespace xrpl { namespace test { -class ServerStatus_test : public beast::unit_test::suite, - public beast::test::enable_yield_to +class ServerStatus_test : public beast::unit_test::suite, public beast::test::enable_yield_to { class myFields : public boost::beast::http::fields { }; auto - makeConfig( - std::string const& proto, - bool admin = true, - bool credentials = false) + makeConfig(std::string const& proto, bool admin = true, bool credentials = false) { - auto const section_name = - boost::starts_with(proto, "h") ? "port_rpc" : "port_ws"; + auto const section_name = boost::starts_with(proto, "h") ? "port_rpc" : "port_ws"; auto p = jtx::envconfig(); p->overwrite(section_name, "protocol", proto); @@ -95,8 +90,7 @@ class ServerStatus_test : public beast::unit_test::suite, std::array key; for (auto& v : key) v = d(e); - req.insert( - "Sec-WebSocket-Key", base64_encode(key.data(), key.size())); + req.insert("Sec-WebSocket-Key", base64_encode(key.data(), key.size())); }; req.insert("Sec-WebSocket-Version", "13"); req.insert(boost::beast::http::field::connection, "upgrade"); @@ -104,11 +98,7 @@ class ServerStatus_test : public beast::unit_test::suite, } auto - makeHTTPRequest( - std::string const& host, - uint16_t port, - std::string const& body, - myFields const& fields) + makeHTTPRequest(std::string const& host, uint16_t port, std::string const& body, myFields const& fields) { using namespace boost::asio; using namespace boost::beast::http; @@ -199,11 +189,9 @@ class ServerStatus_test : public beast::unit_test::suite, boost::beast::http::response& resp, boost::system::error_code& ec) { - auto const port = - env.app().config()["port_ws"].get("port"); + auto const port = env.app().config()["port_ws"].get("port"); auto ip = env.app().config()["port_ws"].get("ip"); - doRequest( - yield, makeWSUpgrade(*ip, *port), *ip, *port, secure, resp, ec); + doRequest(yield, makeWSUpgrade(*ip, *port), *ip, *port, secure, resp, ec); return; } @@ -217,17 +205,9 @@ class ServerStatus_test : public beast::unit_test::suite, std::string const& body = "", myFields const& fields = {}) { - auto const port = - env.app().config()["port_rpc"].get("port"); + auto const port = env.app().config()["port_rpc"].get("port"); auto const ip = env.app().config()["port_rpc"].get("ip"); - doRequest( - yield, - makeHTTPRequest(*ip, *port, body, fields), - *ip, - *port, - secure, - resp, - ec); + doRequest(yield, makeHTTPRequest(*ip, *port, body, fields), *ip, *port, secure, resp, ec); return; } @@ -279,9 +259,8 @@ class ServerStatus_test : public beast::unit_test::suite, void testAdminRequest(std::string const& proto, bool admin, bool credentials) { - testcase << "Admin request over " << proto << ", config " - << (admin ? "enabled" : "disabled") << ", credentials " - << (credentials ? "" : "not ") << "set"; + testcase << "Admin request over " << proto << ", config " << (admin ? "enabled" : "disabled") + << ", credentials " << (credentials ? "" : "not ") << "set"; using namespace jtx; Env env{*this, makeConfig(proto, admin, credentials)}; @@ -293,53 +272,34 @@ class ServerStatus_test : public beast::unit_test::suite, if (admin && credentials) { - auto const user = env.app() - .config()[proto_ws ? "port_ws" : "port_rpc"] - .get("admin_user"); + auto const user = env.app().config()[proto_ws ? "port_ws" : "port_rpc"].get("admin_user"); auto const password = - env.app() - .config()[proto_ws ? "port_ws" : "port_rpc"] - .get("admin_password"); + env.app().config()[proto_ws ? "port_ws" : "port_rpc"].get("admin_password"); // 1 - FAILS with wrong pass - jrr = makeAdminRequest( - env, proto, *user, *password + "_")[jss::result]; + jrr = makeAdminRequest(env, proto, *user, *password + "_")[jss::result]; + BEAST_EXPECT(jrr["error"] == proto_ws ? "forbidden" : "noPermission"); BEAST_EXPECT( - jrr["error"] == proto_ws ? "forbidden" : "noPermission"); - BEAST_EXPECT( - jrr["error_message"] == proto_ws - ? "Bad credentials." - : "You don't have permission for this command."); + jrr["error_message"] == proto_ws ? "Bad credentials." : "You don't have permission for this command."); // 2 - FAILS with password in an object - jrr = makeAdminRequest( - env, proto, *user, *password, true)[jss::result]; + jrr = makeAdminRequest(env, proto, *user, *password, true)[jss::result]; + BEAST_EXPECT(jrr["error"] == proto_ws ? "forbidden" : "noPermission"); BEAST_EXPECT( - jrr["error"] == proto_ws ? "forbidden" : "noPermission"); - BEAST_EXPECT( - jrr["error_message"] == proto_ws - ? "Bad credentials." - : "You don't have permission for this command."); + jrr["error_message"] == proto_ws ? "Bad credentials." : "You don't have permission for this command."); // 3 - FAILS with wrong user - jrr = makeAdminRequest( - env, proto, *user + "_", *password)[jss::result]; + jrr = makeAdminRequest(env, proto, *user + "_", *password)[jss::result]; + BEAST_EXPECT(jrr["error"] == proto_ws ? "forbidden" : "noPermission"); BEAST_EXPECT( - jrr["error"] == proto_ws ? "forbidden" : "noPermission"); - BEAST_EXPECT( - jrr["error_message"] == proto_ws - ? "Bad credentials." - : "You don't have permission for this command."); + jrr["error_message"] == proto_ws ? "Bad credentials." : "You don't have permission for this command."); // 4 - FAILS no credentials jrr = makeAdminRequest(env, proto, "", "")[jss::result]; + BEAST_EXPECT(jrr["error"] == proto_ws ? "forbidden" : "noPermission"); BEAST_EXPECT( - jrr["error"] == proto_ws ? "forbidden" : "noPermission"); - BEAST_EXPECT( - jrr["error_message"] == proto_ws - ? "Bad credentials." - : "You don't have permission for this command."); + jrr["error_message"] == proto_ws ? "Bad credentials." : "You don't have permission for this command."); // 5 - SUCCEEDS with proper credentials jrr = makeAdminRequest(env, proto, *user, *password)[jss::result]; @@ -359,12 +319,9 @@ class ServerStatus_test : public beast::unit_test::suite, { // 1 - FAILS - admin disabled jrr = makeAdminRequest(env, proto, "", "")[jss::result]; + BEAST_EXPECT(jrr["error"] == proto_ws ? "forbidden" : "noPermission"); BEAST_EXPECT( - jrr["error"] == proto_ws ? "forbidden" : "noPermission"); - BEAST_EXPECT( - jrr["error_message"] == proto_ws - ? "Bad credentials." - : "You don't have permission for this command."); + jrr["error_message"] == proto_ws ? "Bad credentials." : "You don't have permission for this command."); } } @@ -385,8 +342,7 @@ class ServerStatus_test : public beast::unit_test::suite, doWSRequest(env, yield, false, resp, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; - BEAST_EXPECT( - resp.result() == boost::beast::http::status::unauthorized); + BEAST_EXPECT(resp.result() == boost::beast::http::status::unauthorized); } // secure request @@ -396,8 +352,7 @@ class ServerStatus_test : public beast::unit_test::suite, doWSRequest(env, yield, true, resp, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; - BEAST_EXPECT( - resp.result() == boost::beast::http::status::unauthorized); + BEAST_EXPECT(resp.result() == boost::beast::http::status::unauthorized); } } @@ -445,8 +400,7 @@ class ServerStatus_test : public beast::unit_test::suite, return cfg; })}; - auto const port = - env.app().config()["port_ws"].get("port"); + auto const port = env.app().config()["port_ws"].get("port"); auto const ip = env.app().config()["port_ws"].get("ip"); boost::system::error_code ec; @@ -487,8 +441,7 @@ class ServerStatus_test : public beast::unit_test::suite, // The essence of this test is to have a client and server configured // out-of-phase with respect to ssl (secure client and insecure server // or vice-versa) - testcase << "Connect fails: " << client_protocol << " client to " - << server_protocol << " server"; + testcase << "Connect fails: " << client_protocol << " client to " << server_protocol << " server"; using namespace jtx; Env env{*this, makeConfig(server_protocol)}; @@ -501,12 +454,7 @@ class ServerStatus_test : public beast::unit_test::suite, } else { - doWSRequest( - env, - yield, - client_protocol == "wss" || client_protocol == "wss2", - resp, - ec); + doWSRequest(env, yield, client_protocol == "wss" || client_protocol == "wss2", resp, ec); BEAST_EXPECT(ec); } } @@ -514,15 +462,13 @@ class ServerStatus_test : public beast::unit_test::suite, void testAuth(bool secure, boost::asio::yield_context& yield) { - testcase << "Server with authorization, " - << (secure ? "secure" : "non-secure"); + testcase << "Server with authorization, " << (secure ? "secure" : "non-secure"); using namespace test::jtx; Env env{*this, envconfig([secure](std::unique_ptr cfg) { (*cfg)["port_rpc"].set("user", "me"); (*cfg)["port_rpc"].set("password", "secret"); - (*cfg)["port_rpc"].set( - "protocol", secure ? "https" : "http"); + (*cfg)["port_rpc"].set("protocol", secure ? "https" : "http"); if (secure) (*cfg)["port_ws"].set("protocol", "http,ws"); return cfg; @@ -548,16 +494,8 @@ class ServerStatus_test : public beast::unit_test::suite, doHTTPRequest(env, yield, secure, resp, ec, to_string(jr), auth); BEAST_EXPECT(resp.result() == boost::beast::http::status::forbidden); - auto const user = env.app() - .config() - .section("port_rpc") - .get("user") - .value(); - auto const pass = env.app() - .config() - .section("port_rpc") - .get("password") - .value(); + auto const user = env.app().config().section("port_rpc").get("user").value(); + auto const pass = env.app().config().section("port_rpc").get("password").value(); // try with the correct user/pass, but not encoded auth.set("Authorization", "Basic " + user + ":" + pass); @@ -584,10 +522,8 @@ class ServerStatus_test : public beast::unit_test::suite, return cfg; })}; - auto const port = - env.app().config()["port_rpc"].get("port").value(); - auto const ip = - env.app().config()["port_rpc"].get("ip").value(); + auto const port = env.app().config()["port_rpc"].get("port").value(); + auto const ip = env.app().config()["port_rpc"].get("ip").value(); boost::system::error_code ec; io_context& ios = get_io_context(); @@ -599,8 +535,7 @@ class ServerStatus_test : public beast::unit_test::suite, auto it = r.async_resolve(ip, std::to_string(port), yield[ec]); BEAST_EXPECT(!ec); - std::vector> - clients; + std::vector> clients; int connectionCount{1}; // starts at 1 because the Env already has one // for JSONRPCCLient @@ -612,8 +547,7 @@ class ServerStatus_test : public beast::unit_test::suite, int testTo = (limit == 0) ? 50 : limit + 1; while (connectionCount < testTo) { - clients.emplace_back(std::make_pair( - ip::tcp::socket{ios}, boost::beast::multi_buffer{})); + clients.emplace_back(std::make_pair(ip::tcp::socket{ios}, boost::beast::multi_buffer{})); async_connect(clients.back().first, it, yield[ec]); BEAST_EXPECT(!ec); auto req = makeHTTPRequest(ip, port, to_string(jr), {}); @@ -630,8 +564,7 @@ class ServerStatus_test : public beast::unit_test::suite, ++readCount; // expect the reads to fail for the clients that connected at or // above the limit. If limit is 0, all reads should succeed - BEAST_EXPECT( - (limit == 0 || readCount < limit - 1) ? (!ec) : bool(ec)); + BEAST_EXPECT((limit == 0 || readCount < limit - 1) ? (!ec) : bool(ec)); } } @@ -646,21 +579,14 @@ class ServerStatus_test : public beast::unit_test::suite, return cfg; })}; - auto const port = - env.app().config()["port_ws"].get("port").value(); - auto const ip = - env.app().config()["port_ws"].get("ip").value(); + auto const port = env.app().config()["port_ws"].get("port").value(); + auto const ip = env.app().config()["port_ws"].get("ip").value(); boost::beast::http::response resp; boost::system::error_code ec; doRequest(yield, makeWSUpgrade(ip, port), ip, port, true, resp, ec); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::switching_protocols); - BEAST_EXPECT( - resp.find("Upgrade") != resp.end() && - resp["Upgrade"] == "websocket"); - BEAST_EXPECT( - resp.find("Connection") != resp.end() && - boost::iequals(resp["Connection"], "upgrade")); + BEAST_EXPECT(resp.result() == boost::beast::http::status::switching_protocols); + BEAST_EXPECT(resp.find("Upgrade") != resp.end() && resp["Upgrade"] == "websocket"); + BEAST_EXPECT(resp.find("Connection") != resp.end() && boost::iequals(resp["Connection"], "upgrade")); } void @@ -671,22 +597,13 @@ class ServerStatus_test : public beast::unit_test::suite, using namespace test::jtx; Env env{*this}; - auto const port = - env.app().config()["port_ws"].get("port").value(); - auto const ip = - env.app().config()["port_ws"].get("ip").value(); + auto const port = env.app().config()["port_ws"].get("port").value(); + auto const ip = env.app().config()["port_ws"].get("ip").value(); boost::beast::http::response resp; boost::system::error_code ec; // body content is required here to avoid being // detected as a status request - doRequest( - yield, - makeHTTPRequest(ip, port, "foo", {}), - ip, - port, - false, - resp, - ec); + doRequest(yield, makeHTTPRequest(ip, port, "foo", {}), ip, port, false, resp, ec); BEAST_EXPECT(resp.result() == boost::beast::http::status::forbidden); BEAST_EXPECT(resp.body() == "Forbidden\r\n"); } @@ -701,10 +618,8 @@ class ServerStatus_test : public beast::unit_test::suite, using namespace boost::beast::http; Env env{*this}; - auto const port = - env.app().config()["port_ws"].get("port").value(); - auto const ip = - env.app().config()["port_ws"].get("ip").value(); + auto const port = env.app().config()["port_ws"].get("port").value(); + auto const ip = env.app().config()["port_ws"].get("ip").value(); boost::system::error_code ec; io_context& ios = get_io_context(); @@ -735,10 +650,8 @@ class ServerStatus_test : public beast::unit_test::suite, Json::Value resp; Json::Reader jr; - if (!BEAST_EXPECT(jr.parse( - boost::lexical_cast( - boost::beast::make_printable(sb.data())), - resp))) + if (!BEAST_EXPECT( + jr.parse(boost::lexical_cast(boost::beast::make_printable(sb.data())), resp))) return Json::objectValue; sb.consume(sb.size()); return resp; @@ -746,8 +659,7 @@ class ServerStatus_test : public beast::unit_test::suite, { // send invalid json auto resp = sendAndParse("NOT JSON"); - BEAST_EXPECT( - resp.isMember(jss::error) && resp[jss::error] == "jsonInvalid"); + BEAST_EXPECT(resp.isMember(jss::error) && resp[jss::error] == "jsonInvalid"); BEAST_EXPECT(!resp.isMember(jss::status)); } @@ -756,22 +668,17 @@ class ServerStatus_test : public beast::unit_test::suite, jv[jss::command] = "foo"; jv[jss::method] = "bar"; auto resp = sendAndParse(to_string(jv)); - BEAST_EXPECT( - resp.isMember(jss::error) && - resp[jss::error] == "missingCommand"); - BEAST_EXPECT( - resp.isMember(jss::status) && resp[jss::status] == "error"); + BEAST_EXPECT(resp.isMember(jss::error) && resp[jss::error] == "missingCommand"); + BEAST_EXPECT(resp.isMember(jss::status) && resp[jss::status] == "error"); } { // send a ping (not an error) Json::Value jv; jv[jss::command] = "ping"; auto resp = sendAndParse(to_string(jv)); + BEAST_EXPECT(resp.isMember(jss::status) && resp[jss::status] == "success"); BEAST_EXPECT( - resp.isMember(jss::status) && resp[jss::status] == "success"); - BEAST_EXPECT( - resp.isMember(jss::result) && - resp[jss::result].isMember(jss::role) && + resp.isMember(jss::result) && resp[jss::result].isMember(jss::role) && resp[jss::result][jss::role] == "admin"); } } @@ -779,8 +686,7 @@ class ServerStatus_test : public beast::unit_test::suite, void testAmendmentWarning(boost::asio::yield_context& yield) { - testcase( - "Status request over WS and RPC with/without Amendment Warning"); + testcase("Status request over WS and RPC with/without Amendment Warning"); using namespace jtx; using namespace boost::asio; using namespace boost::beast::http; @@ -805,8 +711,7 @@ class ServerStatus_test : public beast::unit_test::suite, auto si = env.rpc("server_info")[jss::result]; BEAST_EXPECT(si.isMember(jss::info)); BEAST_EXPECT(!si[jss::info].isMember(jss::amendment_blocked)); - BEAST_EXPECT( - env.app().getOPs().getConsensusInfo()["validating"] == true); + BEAST_EXPECT(env.app().getOPs().getConsensusInfo()["validating"] == true); BEAST_EXPECT(!si.isMember(jss::warnings)); // make an RPC server state request and look for @@ -814,39 +719,28 @@ class ServerStatus_test : public beast::unit_test::suite, si = env.rpc("server_state")[jss::result]; BEAST_EXPECT(si.isMember(jss::state)); BEAST_EXPECT(!si[jss::state].isMember(jss::amendment_blocked)); - BEAST_EXPECT( - env.app().getOPs().getConsensusInfo()["validating"] == true); + BEAST_EXPECT(env.app().getOPs().getConsensusInfo()["validating"] == true); BEAST_EXPECT(!si[jss::state].isMember(jss::warnings)); - auto const port_ws = - env.app().config()["port_ws"].get("port"); + auto const port_ws = env.app().config()["port_ws"].get("port"); auto const ip_ws = env.app().config()["port_ws"].get("ip"); boost::system::error_code ec; response resp; - doRequest( - yield, - makeHTTPRequest(*ip_ws, *port_ws, "", {}), - *ip_ws, - *port_ws, - false, - resp, - ec); + doRequest(yield, makeHTTPRequest(*ip_ws, *port_ws, "", {}), *ip_ws, *port_ws, false, resp, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; BEAST_EXPECT(resp.result() == boost::beast::http::status::ok); - BEAST_EXPECT( - resp.body().find("connectivity is working.") != std::string::npos); + BEAST_EXPECT(resp.body().find("connectivity is working.") != std::string::npos); // mark the Network as having an Amendment Warning, but won't fail env.app().getOPs().setAmendmentWarned(); env.app().getOPs().beginConsensus(env.closed()->header().hash, {}); // consensus doesn't change - BEAST_EXPECT( - env.app().getOPs().getConsensusInfo()["validating"] == true); + BEAST_EXPECT(env.app().getOPs().getConsensusInfo()["validating"] == true); // RPC request server_info again, now unsupported majority should be // returned @@ -854,11 +748,9 @@ class ServerStatus_test : public beast::unit_test::suite, BEAST_EXPECT(si.isMember(jss::info)); BEAST_EXPECT(!si[jss::info].isMember(jss::amendment_blocked)); BEAST_EXPECT( - si[jss::info].isMember(jss::warnings) && - si[jss::info][jss::warnings].isArray() && + si[jss::info].isMember(jss::warnings) && si[jss::info][jss::warnings].isArray() && si[jss::info][jss::warnings].size() == 1 && - si[jss::info][jss::warnings][0u][jss::id].asInt() == - warnRPC_UNSUPPORTED_MAJORITY); + si[jss::info][jss::warnings][0u][jss::id].asInt() == warnRPC_UNSUPPORTED_MAJORITY); // RPC request server_state again, now unsupported majority should be // returned @@ -866,45 +758,27 @@ class ServerStatus_test : public beast::unit_test::suite, BEAST_EXPECT(si.isMember(jss::state)); BEAST_EXPECT(!si[jss::state].isMember(jss::amendment_blocked)); BEAST_EXPECT( - si[jss::state].isMember(jss::warnings) && - si[jss::state][jss::warnings].isArray() && + si[jss::state].isMember(jss::warnings) && si[jss::state][jss::warnings].isArray() && si[jss::state][jss::warnings].size() == 1 && - si[jss::state][jss::warnings][0u][jss::id].asInt() == - warnRPC_UNSUPPORTED_MAJORITY); + si[jss::state][jss::warnings][0u][jss::id].asInt() == warnRPC_UNSUPPORTED_MAJORITY); // but status does not indicate a problem - doRequest( - yield, - makeHTTPRequest(*ip_ws, *port_ws, "", {}), - *ip_ws, - *port_ws, - false, - resp, - ec); + doRequest(yield, makeHTTPRequest(*ip_ws, *port_ws, "", {}), *ip_ws, *port_ws, false, resp, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; BEAST_EXPECT(resp.result() == boost::beast::http::status::ok); - BEAST_EXPECT( - resp.body().find("connectivity is working.") != std::string::npos); + BEAST_EXPECT(resp.body().find("connectivity is working.") != std::string::npos); // with ELB_SUPPORT, status still does not indicate a problem env.app().config().ELB_SUPPORT = true; - doRequest( - yield, - makeHTTPRequest(*ip_ws, *port_ws, "", {}), - *ip_ws, - *port_ws, - false, - resp, - ec); + doRequest(yield, makeHTTPRequest(*ip_ws, *port_ws, "", {}), *ip_ws, *port_ws, false, resp, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; BEAST_EXPECT(resp.result() == boost::beast::http::status::ok); - BEAST_EXPECT( - resp.body().find("connectivity is working.") != std::string::npos); + BEAST_EXPECT(resp.body().find("connectivity is working.") != std::string::npos); } void @@ -935,8 +809,7 @@ class ServerStatus_test : public beast::unit_test::suite, auto si = env.rpc("server_info")[jss::result]; BEAST_EXPECT(si.isMember(jss::info)); BEAST_EXPECT(!si[jss::info].isMember(jss::amendment_blocked)); - BEAST_EXPECT( - env.app().getOPs().getConsensusInfo()["validating"] == true); + BEAST_EXPECT(env.app().getOPs().getConsensusInfo()["validating"] == true); BEAST_EXPECT(!si.isMember(jss::warnings)); // make an RPC server state request and look for @@ -944,31 +817,21 @@ class ServerStatus_test : public beast::unit_test::suite, si = env.rpc("server_state")[jss::result]; BEAST_EXPECT(si.isMember(jss::state)); BEAST_EXPECT(!si[jss::state].isMember(jss::amendment_blocked)); - BEAST_EXPECT( - env.app().getOPs().getConsensusInfo()["validating"] == true); + BEAST_EXPECT(env.app().getOPs().getConsensusInfo()["validating"] == true); BEAST_EXPECT(!si[jss::state].isMember(jss::warnings)); - auto const port_ws = - env.app().config()["port_ws"].get("port"); + auto const port_ws = env.app().config()["port_ws"].get("port"); auto const ip_ws = env.app().config()["port_ws"].get("ip"); boost::system::error_code ec; response resp; - doRequest( - yield, - makeHTTPRequest(*ip_ws, *port_ws, "", {}), - *ip_ws, - *port_ws, - false, - resp, - ec); + doRequest(yield, makeHTTPRequest(*ip_ws, *port_ws, "", {}), *ip_ws, *port_ws, false, resp, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; BEAST_EXPECT(resp.result() == boost::beast::http::status::ok); - BEAST_EXPECT( - resp.body().find("connectivity is working.") != std::string::npos); + BEAST_EXPECT(resp.body().find("connectivity is working.") != std::string::npos); // mark the Network as Amendment Blocked, but still won't fail until // ELB is enabled (next step) @@ -976,70 +839,43 @@ class ServerStatus_test : public beast::unit_test::suite, env.app().getOPs().beginConsensus(env.closed()->header().hash, {}); // consensus now sees validation disabled - BEAST_EXPECT( - env.app().getOPs().getConsensusInfo()["validating"] == false); + BEAST_EXPECT(env.app().getOPs().getConsensusInfo()["validating"] == false); // RPC request server_info again, now AB should be returned si = env.rpc("server_info")[jss::result]; BEAST_EXPECT(si.isMember(jss::info)); + BEAST_EXPECT(si[jss::info].isMember(jss::amendment_blocked) && si[jss::info][jss::amendment_blocked] == true); BEAST_EXPECT( - si[jss::info].isMember(jss::amendment_blocked) && - si[jss::info][jss::amendment_blocked] == true); - BEAST_EXPECT( - si[jss::info].isMember(jss::warnings) && - si[jss::info][jss::warnings].isArray() && + si[jss::info].isMember(jss::warnings) && si[jss::info][jss::warnings].isArray() && si[jss::info][jss::warnings].size() == 1 && - si[jss::info][jss::warnings][0u][jss::id].asInt() == - warnRPC_AMENDMENT_BLOCKED); + si[jss::info][jss::warnings][0u][jss::id].asInt() == warnRPC_AMENDMENT_BLOCKED); // RPC request server_state again, now AB should be returned si = env.rpc("server_state")[jss::result]; + BEAST_EXPECT(si[jss::state].isMember(jss::amendment_blocked) && si[jss::state][jss::amendment_blocked] == true); BEAST_EXPECT( - si[jss::state].isMember(jss::amendment_blocked) && - si[jss::state][jss::amendment_blocked] == true); - BEAST_EXPECT( - si[jss::state].isMember(jss::warnings) && - si[jss::state][jss::warnings].isArray() && + si[jss::state].isMember(jss::warnings) && si[jss::state][jss::warnings].isArray() && si[jss::state][jss::warnings].size() == 1 && - si[jss::state][jss::warnings][0u][jss::id].asInt() == - warnRPC_AMENDMENT_BLOCKED); + si[jss::state][jss::warnings][0u][jss::id].asInt() == warnRPC_AMENDMENT_BLOCKED); // but status does not indicate because it still relies on ELB // being enabled - doRequest( - yield, - makeHTTPRequest(*ip_ws, *port_ws, "", {}), - *ip_ws, - *port_ws, - false, - resp, - ec); + doRequest(yield, makeHTTPRequest(*ip_ws, *port_ws, "", {}), *ip_ws, *port_ws, false, resp, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; BEAST_EXPECT(resp.result() == boost::beast::http::status::ok); - BEAST_EXPECT( - resp.body().find("connectivity is working.") != std::string::npos); + BEAST_EXPECT(resp.body().find("connectivity is working.") != std::string::npos); env.app().config().ELB_SUPPORT = true; - doRequest( - yield, - makeHTTPRequest(*ip_ws, *port_ws, "", {}), - *ip_ws, - *port_ws, - false, - resp, - ec); + doRequest(yield, makeHTTPRequest(*ip_ws, *port_ws, "", {}), *ip_ws, *port_ws, false, resp, ec); if (!BEAST_EXPECTS(!ec, ec.message())) return; - BEAST_EXPECT( - resp.result() == boost::beast::http::status::internal_server_error); - BEAST_EXPECT( - resp.body().find("cannot accept clients:") != std::string::npos); - BEAST_EXPECT( - resp.body().find("Server version too old") != std::string::npos); + BEAST_EXPECT(resp.result() == boost::beast::http::status::internal_server_error); + BEAST_EXPECT(resp.body().find("cannot accept clients:") != std::string::npos); + BEAST_EXPECT(resp.body().find("Server version too old") != std::string::npos); } void @@ -1054,8 +890,7 @@ class ServerStatus_test : public beast::unit_test::suite, { boost::beast::http::response resp; doHTTPRequest(env, yield, false, resp, ec, "{}"); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "Unable to parse request: \r\n"); } @@ -1064,8 +899,7 @@ class ServerStatus_test : public beast::unit_test::suite, Json::Value jv; jv["invalid"] = 1; doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "Null method\r\n"); } @@ -1074,8 +908,7 @@ class ServerStatus_test : public beast::unit_test::suite, Json::Value jv(Json::arrayValue); jv.append("invalid"); doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "Unable to parse request: \r\n"); } @@ -1086,8 +919,7 @@ class ServerStatus_test : public beast::unit_test::suite, j["invalid"] = 1; jv.append(j); doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "Unable to parse request: \r\n"); } @@ -1097,8 +929,7 @@ class ServerStatus_test : public beast::unit_test::suite, jv[jss::method] = "batch"; jv[jss::params] = 2; doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "Malformed batch request\r\n"); } @@ -1109,8 +940,7 @@ class ServerStatus_test : public beast::unit_test::suite, jv[jss::params] = Json::objectValue; jv[jss::params]["invalid"] = 3; doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "Malformed batch request\r\n"); } @@ -1119,8 +949,7 @@ class ServerStatus_test : public beast::unit_test::suite, boost::beast::http::response resp; jv[jss::method] = Json::nullValue; doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "Null method\r\n"); } @@ -1128,8 +957,7 @@ class ServerStatus_test : public beast::unit_test::suite, boost::beast::http::response resp; jv[jss::method] = 1; doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "method is not string\r\n"); } @@ -1137,8 +965,7 @@ class ServerStatus_test : public beast::unit_test::suite, boost::beast::http::response resp; jv[jss::method] = ""; doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "method is empty\r\n"); } @@ -1147,8 +974,7 @@ class ServerStatus_test : public beast::unit_test::suite, jv[jss::method] = "some_method"; jv[jss::params] = "params"; doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "params unparsable\r\n"); } @@ -1157,8 +983,7 @@ class ServerStatus_test : public beast::unit_test::suite, jv[jss::params] = Json::arrayValue; jv[jss::params][0u] = "not an object"; doHTTPRequest(env, yield, false, resp, ec, to_string(jv)); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::bad_request); + BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); BEAST_EXPECT(resp.body() == "params unparsable\r\n"); } } @@ -1180,8 +1005,7 @@ class ServerStatus_test : public beast::unit_test::suite, boost::beast::http::response resp; boost::system::error_code ec; doHTTPRequest(env, yield, false, resp, ec); - BEAST_EXPECT( - resp.result() == boost::beast::http::status::internal_server_error); + BEAST_EXPECT(resp.result() == boost::beast::http::status::internal_server_error); std::regex body{"Server cannot accept clients"}; BEAST_EXPECT(std::regex_search(resp.body(), body)); } diff --git a/src/test/server/Server_test.cpp b/src/test/server/Server_test.cpp index 2a4bb49d34..7347bf238c 100644 --- a/src/test/server/Server_test.cpp +++ b/src/test/server/Server_test.cpp @@ -35,9 +35,7 @@ public: { private: boost::asio::io_context io_context_; - std::optional> - work_; + std::optional> work_; std::thread thread_; public: @@ -67,14 +65,12 @@ public: beast::unit_test::suite& suite_; public: - explicit TestSink(beast::unit_test::suite& suite) - : Sink(beast::severities::kWarning, false), suite_(suite) + explicit TestSink(beast::unit_test::suite& suite) : Sink(beast::severities::kWarning, false), suite_(suite) { } void - write(beast::severities::Severity level, std::string const& text) - override + write(beast::severities::Severity level, std::string const& text) override { if (level < threshold()) return; @@ -83,8 +79,7 @@ public: } void - writeAlways(beast::severities::Severity level, std::string const& text) - override + writeAlways(beast::severities::Severity level, std::string const& text) override { suite_.log << text << std::endl; } @@ -111,10 +106,7 @@ public: } Handoff - onHandoff( - Session& session, - http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) + onHandoff(Session& session, http_request_type&& request, boost::asio::ip::tcp::endpoint remote_address) { return Handoff{}; } @@ -130,9 +122,7 @@ public: } void - onWSMessage( - std::shared_ptr session, - std::vector const&) + onWSMessage(std::shared_ptr session, std::vector const&) { } @@ -199,8 +189,7 @@ public: { std::string got; got.resize(n); - boost::asio::buffer_copy( - boost::asio::buffer(&got[0], n), b.data()); + boost::asio::buffer_copy(boost::asio::buffer(&got[0], n), b.data()); return BEAST_EXPECT(got == match); } } @@ -286,9 +275,7 @@ public: TestHandler handler; auto s = make_Server(handler, thread.get_io_context(), journal); std::vector serverPort(1); - serverPort.back().ip = - boost::asio::ip::make_address(getEnvLocalhostAddr()), - serverPort.back().port = 0; + serverPort.back().ip = boost::asio::ip::make_address(getEnvLocalhostAddr()), serverPort.back().port = 0; serverPort.back().protocol.insert("http"); auto eps = s->ports(serverPort); test_request(eps.begin()->second); @@ -321,10 +308,7 @@ public: } Handoff - onHandoff( - Session& session, - http_request_type&& request, - boost::asio::ip::tcp::endpoint remote_address) + onHandoff(Session& session, http_request_type&& request, boost::asio::ip::tcp::endpoint remote_address) { return Handoff{}; } @@ -335,9 +319,7 @@ public: } void - onWSMessage( - std::shared_ptr session, - std::vector const& buffers) + onWSMessage(std::shared_ptr session, std::vector const& buffers) { } @@ -361,9 +343,7 @@ public: TestThread thread; auto s = make_Server(h, thread.get_io_context(), journal); std::vector serverPort(1); - serverPort.back().ip = - boost::asio::ip::make_address(getEnvLocalhostAddr()), - serverPort.back().port = 0; + serverPort.back().ip = boost::asio::ip::make_address(getEnvLocalhostAddr()), serverPort.back().port = 0; serverPort.back().protocol.insert("http"); s->ports(serverPort); } @@ -387,8 +367,7 @@ public: }), std::make_unique(&messages)}; }); - BEAST_EXPECT( - messages.find("Missing 'ip' in [port_rpc]") != std::string::npos); + BEAST_EXPECT(messages.find("Missing 'ip' in [port_rpc]") != std::string::npos); except([&] { Env env{ @@ -400,8 +379,7 @@ public: }), std::make_unique(&messages)}; }); - BEAST_EXPECT( - messages.find("Missing 'port' in [port_rpc]") != std::string::npos); + BEAST_EXPECT(messages.find("Missing 'port' in [port_rpc]") != std::string::npos); except([&] { Env env{ @@ -414,9 +392,7 @@ public: }), std::make_unique(&messages)}; }); - BEAST_EXPECT( - messages.find("Invalid value '0' for key 'port' in [port_rpc]") == - std::string::npos); + BEAST_EXPECT(messages.find("Invalid value '0' for key 'port' in [port_rpc]") == std::string::npos); except([&] { Env env{ @@ -427,9 +403,7 @@ public: }), std::make_unique(&messages)}; }); - BEAST_EXPECT( - messages.find("Invalid value '0' for key 'port' in [server]") != - std::string::npos); + BEAST_EXPECT(messages.find("Invalid value '0' for key 'port' in [server]") != std::string::npos); except([&] { Env env{ @@ -443,44 +417,36 @@ public: }), std::make_unique(&messages)}; }); - BEAST_EXPECT( - messages.find("Missing 'protocol' in [port_rpc]") != - std::string::npos); + BEAST_EXPECT(messages.find("Missing 'protocol' in [port_rpc]") != std::string::npos); - except( - [&] // this creates a standard test config without the server - // section - { - Env env{ - *this, - envconfig([](std::unique_ptr cfg) { - cfg = std::make_unique(); - cfg->overwrite( - ConfigSection::nodeDatabase(), "type", "memory"); - cfg->overwrite( - ConfigSection::nodeDatabase(), "path", "main"); - cfg->deprecatedClearSection( - ConfigSection::importNodeDatabase()); - cfg->legacy("database_path", ""); - cfg->setupControl(true, true, true); - (*cfg)["port_peer"].set("ip", getEnvLocalhostAddr()); - (*cfg)["port_peer"].set("port", "8080"); - (*cfg)["port_peer"].set("protocol", "peer"); - (*cfg)["port_rpc"].set("ip", getEnvLocalhostAddr()); - (*cfg)["port_rpc"].set("port", "8081"); - (*cfg)["port_rpc"].set("protocol", "http,ws2"); - (*cfg)["port_rpc"].set("admin", getEnvLocalhostAddr()); - (*cfg)["port_ws"].set("ip", getEnvLocalhostAddr()); - (*cfg)["port_ws"].set("port", "8082"); - (*cfg)["port_ws"].set("protocol", "ws"); - (*cfg)["port_ws"].set("admin", getEnvLocalhostAddr()); - return cfg; - }), - std::make_unique(&messages)}; - }); - BEAST_EXPECT( - messages.find("Required section [server] is missing") != - std::string::npos); + except([&] // this creates a standard test config without the server + // section + { + Env env{ + *this, + envconfig([](std::unique_ptr cfg) { + cfg = std::make_unique(); + cfg->overwrite(ConfigSection::nodeDatabase(), "type", "memory"); + cfg->overwrite(ConfigSection::nodeDatabase(), "path", "main"); + cfg->deprecatedClearSection(ConfigSection::importNodeDatabase()); + cfg->legacy("database_path", ""); + cfg->setupControl(true, true, true); + (*cfg)["port_peer"].set("ip", getEnvLocalhostAddr()); + (*cfg)["port_peer"].set("port", "8080"); + (*cfg)["port_peer"].set("protocol", "peer"); + (*cfg)["port_rpc"].set("ip", getEnvLocalhostAddr()); + (*cfg)["port_rpc"].set("port", "8081"); + (*cfg)["port_rpc"].set("protocol", "http,ws2"); + (*cfg)["port_rpc"].set("admin", getEnvLocalhostAddr()); + (*cfg)["port_ws"].set("ip", getEnvLocalhostAddr()); + (*cfg)["port_ws"].set("port", "8082"); + (*cfg)["port_ws"].set("protocol", "ws"); + (*cfg)["port_ws"].set("admin", getEnvLocalhostAddr()); + return cfg; + }), + std::make_unique(&messages)}; + }); + BEAST_EXPECT(messages.find("Required section [server] is missing") != std::string::npos); except([&] // this creates a standard test config without some of the // port sections @@ -489,12 +455,9 @@ public: *this, envconfig([](std::unique_ptr cfg) { cfg = std::make_unique(); - cfg->overwrite( - ConfigSection::nodeDatabase(), "type", "memory"); - cfg->overwrite( - ConfigSection::nodeDatabase(), "path", "main"); - cfg->deprecatedClearSection( - ConfigSection::importNodeDatabase()); + cfg->overwrite(ConfigSection::nodeDatabase(), "type", "memory"); + cfg->overwrite(ConfigSection::nodeDatabase(), "path", "main"); + cfg->deprecatedClearSection(ConfigSection::importNodeDatabase()); cfg->legacy("database_path", ""); cfg->setupControl(true, true, true); (*cfg)["server"].append("port_peer"); @@ -504,8 +467,7 @@ public: }), std::make_unique(&messages)}; }); - BEAST_EXPECT( - messages.find("Missing section: [port_peer]") != std::string::npos); + BEAST_EXPECT(messages.find("Missing section: [port_peer]") != std::string::npos); } void diff --git a/src/test/shamap/FetchPack_test.cpp b/src/test/shamap/FetchPack_test.cpp index dc51616015..8919241996 100644 --- a/src/test/shamap/FetchPack_test.cpp +++ b/src/test/shamap/FetchPack_test.cpp @@ -36,8 +36,7 @@ public: struct TestFilter : SHAMapSyncFilter { - TestFilter(Map& map, beast::Journal journal) - : mMap(map), mJournal(journal) + TestFilter(Map& map, beast::Journal journal) : mMap(map), mJournal(journal) { } @@ -81,8 +80,7 @@ public: { while (n--) { - auto const result(t.addItem( - SHAMapNodeType::tnACCOUNT_STATE, make_random_item(r))); + auto const result(t.addItem(SHAMapNodeType::tnACCOUNT_STATE, make_random_item(r))); assert(result); (void)result; } diff --git a/src/test/shamap/SHAMapSync_test.cpp b/src/test/shamap/SHAMapSync_test.cpp index 912768e618..1add7a629e 100644 --- a/src/test/shamap/SHAMapSync_test.cpp +++ b/src/test/shamap/SHAMapSync_test.cpp @@ -57,8 +57,7 @@ public: if (beforeHash != map.getHash()) { - log << "Hashes do not match " << beforeHash << " " << map.getHash() - << std::endl; + log << "Hashes do not match " << beforeHash << " " << map.getHash() << std::endl; return false; } @@ -106,16 +105,11 @@ public: { std::vector> a; - BEAST_EXPECT(source.getNodeFat( - SHAMapNodeID(), a, rand_bool(eng_), rand_int(eng_, 2))); + BEAST_EXPECT(source.getNodeFat(SHAMapNodeID(), a, rand_bool(eng_), rand_int(eng_, 2))); unexpected(a.size() < 1, "NodeSize"); - BEAST_EXPECT( - destination - .addRootNode( - source.getHash(), makeSlice(a[0].second), nullptr) - .isGood()); + BEAST_EXPECT(destination.addRootNode(source.getHash(), makeSlice(a[0].second), nullptr).isGood()); } do @@ -136,8 +130,7 @@ public: // Don't use BEAST_EXPECT here b/c it will be called a // non-deterministic number of times and the number of tests run // should be deterministic - if (!source.getNodeFat( - it.first, b, rand_bool(eng_), rand_int(eng_, 2))) + if (!source.getNodeFat(it.first, b, rand_bool(eng_), rand_int(eng_, 2))) fail("", __FILE__, __LINE__); } @@ -152,10 +145,7 @@ public: // Don't use BEAST_EXPECT here b/c it will be called a // non-deterministic number of times and the number of tests run // should be deterministic - if (!destination - .addKnownNode( - b[i].first, makeSlice(b[i].second), nullptr) - .isUseful()) + if (!destination.addKnownNode(b[i].first, makeSlice(b[i].second), nullptr).isUseful()) fail("", __FILE__, __LINE__); } } while (true); diff --git a/src/test/shamap/SHAMap_test.cpp b/src/test/shamap/SHAMap_test.cpp index ade7a692f8..c91cc63749 100644 --- a/src/test/shamap/SHAMap_test.cpp +++ b/src/test/shamap/SHAMap_test.cpp @@ -117,16 +117,11 @@ public: tests::TestNodeFamily f(journal); // h3 and h4 differ only in the leaf, same terminal node (level 19) - constexpr uint256 h1( - "092891fe4ef6cee585fdc6fda0e09eb4d386363158ec3321b8123e5a772c6ca7"); - constexpr uint256 h2( - "436ccbac3347baa1f1e53baeef1f43334da88f1f6d70d963b833afd6dfa289fe"); - constexpr uint256 h3( - "b92891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8"); - constexpr uint256 h4( - "b92891fe4ef6cee585fdc6fda2e09eb4d386363158ec3321b8123e5a772c6ca8"); - constexpr uint256 h5( - "a92891fe4ef6cee585fdc6fda0e09eb4d386363158ec3321b8123e5a772c6ca7"); + constexpr uint256 h1("092891fe4ef6cee585fdc6fda0e09eb4d386363158ec3321b8123e5a772c6ca7"); + constexpr uint256 h2("436ccbac3347baa1f1e53baeef1f43334da88f1f6d70d963b833afd6dfa289fe"); + constexpr uint256 h3("b92891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8"); + constexpr uint256 h4("b92891fe4ef6cee585fdc6fda2e09eb4d386363158ec3321b8123e5a772c6ca8"); + constexpr uint256 h5("a92891fe4ef6cee585fdc6fda0e09eb4d386363158ec3321b8123e5a772c6ca7"); SHAMap sMap(SHAMapType::FREE, f); sMap.invariants(); @@ -139,15 +134,9 @@ public: auto i4 = make_shamapitem(h4, IntToVUC(4)); auto i5 = make_shamapitem(h5, IntToVUC(5)); - unexpected( - !sMap.addItem( - SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(*i2)), - "no add"); + unexpected(!sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(*i2)), "no add"); sMap.invariants(); - unexpected( - !sMap.addItem( - SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(*i1)), - "no add"); + unexpected(!sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(*i1)), "no add"); sMap.invariants(); auto i = sMap.begin(); @@ -249,9 +238,7 @@ public: BEAST_EXPECT(map.getHash() == beast::zero); for (int k = 0; k < keys.size(); ++k) { - BEAST_EXPECT(map.addItem( - SHAMapNodeType::tnTRANSACTION_NM, - make_shamapitem(keys[k], IntToVUC(k)))); + BEAST_EXPECT(map.addItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(keys[k], IntToVUC(k)))); BEAST_EXPECT(map.getHash().as_uint256() == hashes[k]); map.invariants(); } @@ -294,9 +281,7 @@ public: map.setUnbacked(); for (auto const& k : keys) { - map.addItem( - SHAMapNodeType::tnTRANSACTION_NM, - make_shamapitem(k, IntToVUC(0))); + map.addItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(k, IntToVUC(0))); map.invariants(); } @@ -328,9 +313,7 @@ class SHAMapPathProof_test : public beast::unit_test::suite for (unsigned char c = 1; c < 100; ++c) { uint256 k(c); - map.addItem( - SHAMapNodeType::tnACCOUNT_STATE, - make_shamapitem(k, Slice{k.data(), k.size()})); + map.addItem(SHAMapNodeType::tnACCOUNT_STATE, make_shamapitem(k, Slice{k.data(), k.size()})); map.invariants(); auto root = map.getHash().as_uint256(); diff --git a/src/test/shamap/common.h b/src/test/shamap/common.h index add2c79243..1779755619 100644 --- a/src/test/shamap/common.h +++ b/src/test/shamap/common.h @@ -24,23 +24,15 @@ private: public: TestNodeFamily(beast::Journal j) - : fbCache_(std::make_shared( - "App family full below cache", - clock_, - j)) - , tnCache_(std::make_shared( - "App family tree node cache", - 65536, - std::chrono::minutes{1}, - clock_, - j)) + : fbCache_(std::make_shared("App family full below cache", clock_, j)) + , tnCache_( + std::make_shared("App family tree node cache", 65536, std::chrono::minutes{1}, clock_, j)) , j_(j) { Section testSection; testSection.set("type", "memory"); testSection.set("path", "SHAMap_test"); - db_ = NodeStore::Manager::instance().make_Database( - megabytes(4), scheduler_, 1, testSection, j); + db_ = NodeStore::Manager::instance().make_Database(megabytes(4), scheduler_, 1, testSection, j); } NodeStore::Database& @@ -81,15 +73,13 @@ public: } void - missingNodeAcquireBySeq(std::uint32_t refNum, uint256 const& nodeHash) - override + missingNodeAcquireBySeq(std::uint32_t refNum, uint256 const& nodeHash) override { Throw("missing node"); } void - missingNodeAcquireByHash(uint256 const& refHash, std::uint32_t refNum) - override + missingNodeAcquireByHash(uint256 const& refHash, std::uint32_t refNum) override { Throw("missing node"); } diff --git a/src/test/unit_test/FileDirGuard.h b/src/test/unit_test/FileDirGuard.h index 94ca5948bd..90765f7029 100644 --- a/src/test/unit_test/FileDirGuard.h +++ b/src/test/unit_test/FileDirGuard.h @@ -33,8 +33,7 @@ protected: if (is_directory(toRm) && is_empty(toRm)) remove(toRm); else - test_.log << "Expected " << toRm.string() - << " to be an empty existing directory." << std::endl; + test_.log << "Expected " << toRm.string() << " to be an empty existing directory." << std::endl; } public: @@ -57,8 +56,7 @@ public: { // Cannot run the test. Someone created a file where we want to // put our directory - Throw( - "Cannot create directory: " + subDir_.string()); + Throw("Cannot create directory: " + subDir_.string()); } } @@ -102,8 +100,7 @@ public: std::string const& contents, bool useCounter = true, bool create = true) - : DirGuard(test, subDir, useCounter) - , file_(file.is_absolute() ? file : subdir() / file) + : DirGuard(test, subDir, useCounter), file_(file.is_absolute() ? file : subdir() / file) { if (!exists(file_)) { @@ -116,8 +113,7 @@ public: } else { - Throw( - "Refusing to overwrite existing file: " + file_.string()); + Throw("Refusing to overwrite existing file: " + file_.string()); } } @@ -133,8 +129,7 @@ public: else { if (created_) - test_.log << "Expected " << file_.string() - << " to be an existing file." << std::endl; + test_.log << "Expected " << file_.string() << " to be an existing file." << std::endl; } } catch (std::exception& e) diff --git a/src/test/unit_test/SuiteJournal.h b/src/test/unit_test/SuiteJournal.h index d64be9ea9b..0b87706056 100644 --- a/src/test/unit_test/SuiteJournal.h +++ b/src/test/unit_test/SuiteJournal.h @@ -33,14 +33,11 @@ public: write(beast::severities::Severity level, std::string const& text) override; void - writeAlways(beast::severities::Severity level, std::string const& text) - override; + writeAlways(beast::severities::Severity level, std::string const& text) override; }; inline void -SuiteJournalSink::write( - beast::severities::Severity level, - std::string const& text) +SuiteJournalSink::write(beast::severities::Severity level, std::string const& text) { // Only write the string if the level at least equals the threshold. if (level >= threshold()) @@ -48,9 +45,7 @@ SuiteJournalSink::write( } inline void -SuiteJournalSink::writeAlways( - beast::severities::Severity level, - std::string const& text) +SuiteJournalSink::writeAlways(beast::severities::Severity level, std::string const& text) { using namespace beast::severities; @@ -111,9 +106,7 @@ class StreamSink : public beast::Journal::Sink std::stringstream strm_; public: - StreamSink( - beast::severities::Severity threshold = beast::severities::kDebug) - : Sink(threshold, false) + StreamSink(beast::severities::Severity threshold = beast::severities::kDebug) : Sink(threshold, false) { } @@ -126,8 +119,7 @@ public: } inline void - writeAlways(beast::severities::Severity level, std::string const& text) - override + writeAlways(beast::severities::Severity level, std::string const& text) override { strm_ << text << std::endl; } diff --git a/src/test/unit_test/multi_runner.cpp b/src/test/unit_test/multi_runner.cpp index 4b1a82cd3f..eefd0c8250 100644 --- a/src/test/unit_test/multi_runner.cpp +++ b/src/test/unit_test/multi_runner.cpp @@ -49,10 +49,7 @@ results::add(suite_results const& r) if (elapsed >= std::chrono::seconds{1}) { auto const iter = std::lower_bound( - top.begin(), - top.end(), - elapsed, - [](run_time const& t1, typename clock_type::duration const& t2) { + top.begin(), top.end(), elapsed, [](run_time const& t1, typename clock_type::duration const& t2) { return t1.second > t2; }); @@ -61,25 +58,18 @@ results::add(suite_results const& r) if (top.size() == max_top && iter == top.end() - 1) { // avoid invalidating the iterator - *iter = run_time{ - static_string{static_string::string_view_type{r.name}}, - elapsed}; + *iter = run_time{static_string{static_string::string_view_type{r.name}}, elapsed}; } else { if (top.size() == max_top) top.resize(top.size() - 1); - top.emplace( - iter, - static_string{static_string::string_view_type{r.name}}, - elapsed); + top.emplace(iter, static_string{static_string::string_view_type{r.name}}, elapsed); } } else if (top.size() < max_top) { - top.emplace_back( - static_string{static_string::string_view_type{r.name}}, - elapsed); + top.emplace_back(static_string{static_string::string_view_type{r.name}}, elapsed); } } } @@ -101,9 +91,7 @@ results::merge(results const& r) r.top.begin(), r.top.end(), top_result.begin(), - [](run_time const& t1, run_time const& t2) { - return t1.second > t2.second; - }); + [](run_time const& t1, run_time const& t2) { return t1.second > t2.second; }); if (top_result.size() > max_top) top_result.resize(max_top); @@ -125,9 +113,8 @@ results::print(S& s) } auto const elapsed = clock_type::now() - start; - s << fmtdur(elapsed) << ", " << amount{suites, "suite"} << ", " - << amount{cases, "case"} << ", " << amount{total, "test"} << " total, " - << amount{failed, "failure"} << std::endl; + s << fmtdur(elapsed) << ", " << amount{suites, "suite"} << ", " << amount{cases, "case"} << ", " + << amount{total, "test"} << " total, " << amount{failed, "failure"} << std::endl; } //------------------------------------------------------------------------------ @@ -220,32 +207,26 @@ multi_runner_base::multi_runner_base() } shared_mem_ = boost::interprocess::shared_memory_object{ - std::conditional_t< - IsParent, - boost::interprocess::create_only_t, - boost::interprocess::open_only_t>{}, + std::conditional_t{}, shared_mem_name_, boost::interprocess::read_write}; if (IsParent) { shared_mem_.truncate(sizeof(inner)); - message_queue_ = - std::make_unique( - boost::interprocess::create_only, - message_queue_name_, - /*max messages*/ 16, - /*max message size*/ 1 << 20); + message_queue_ = std::make_unique( + boost::interprocess::create_only, + message_queue_name_, + /*max messages*/ 16, + /*max message size*/ 1 << 20); } else { - message_queue_ = - std::make_unique( - boost::interprocess::open_only, message_queue_name_); + message_queue_ = std::make_unique( + boost::interprocess::open_only, message_queue_name_); } - region_ = boost::interprocess::mapped_region{ - shared_mem_, boost::interprocess::read_write}; + region_ = boost::interprocess::mapped_region{shared_mem_, boost::interprocess::read_write}; if (IsParent) inner_ = new (region_.get_address()) inner{}; else @@ -332,9 +313,7 @@ multi_runner_base::print_results(S& s) template void -multi_runner_base::message_queue_send( - MessageType mt, - std::string const& s) +multi_runner_base::message_queue_send(MessageType mt, std::string const& s) { // must use a mutex since the two "sends" must happen in order std::lock_guard l{inner_->m_}; @@ -376,8 +355,7 @@ multi_runner_parent::multi_runner_parent() : os_(std::cout) { message_queue_thread_ = std::thread([this] { std::vector buf(1 << 20); - while (this->continue_message_queue_ || - this->message_queue_->get_num_msg()) + while (this->continue_message_queue_ || this->message_queue_->get_num_msg()) { // let children know the parent is still alive this->inc_keep_alive_count(); @@ -394,15 +372,13 @@ multi_runner_parent::multi_runner_parent() : os_(std::cout) { std::size_t recvd_size = 0; unsigned int priority = 0; - this->message_queue_->receive( - buf.data(), buf.size(), recvd_size, priority); + this->message_queue_->receive(buf.data(), buf.size(), recvd_size, priority); if (!recvd_size) continue; assert(recvd_size == 1); MessageType mt{*reinterpret_cast(buf.data())}; - this->message_queue_->receive( - buf.data(), buf.size(), recvd_size, priority); + this->message_queue_->receive(buf.data(), buf.size(), recvd_size, priority); if (recvd_size) { std::string s{buf.data(), recvd_size}; @@ -425,8 +401,7 @@ multi_runner_parent::multi_runner_parent() : os_(std::cout) } catch (std::exception const& e) { - std::cerr << "Error: " << e.what() - << " reading unit test message queue.\n"; + std::cerr << "Error: " << e.what() << " reading unit test message queue.\n"; return; } catch (...) @@ -451,8 +426,7 @@ multi_runner_parent::~multi_runner_parent() for (auto const& s : running_suites_) { - os_ << "\nSuite: " << s - << " failed to complete. The child process may have crashed.\n"; + os_ << "\nSuite: " << s << " failed to complete. The child process may have crashed.\n"; } } @@ -482,14 +456,8 @@ multi_runner_parent::add_failures(std::size_t failures) //------------------------------------------------------------------------------ -multi_runner_child::multi_runner_child( - std::size_t num_jobs, - bool quiet, - bool print_log) - : job_index_{checkout_job_index()} - , num_jobs_{num_jobs} - , quiet_{quiet} - , print_log_{!quiet || print_log} +multi_runner_child::multi_runner_child(std::size_t num_jobs, bool quiet, bool print_log) + : job_index_{checkout_job_index()}, num_jobs_{num_jobs}, quiet_{quiet}, print_log_{!quiet || print_log} { if (num_jobs_ > 1) { @@ -510,8 +478,7 @@ multi_runner_child::multi_runner_child( if (cur_count == last_count) { // assume parent process is no longer alive - std::cerr << "multi_runner_child " << job_index_ - << ": Assuming parent died, exiting.\n"; + std::cerr << "multi_runner_child " << job_index_ << ": Assuming parent died, exiting.\n"; std::exit(EXIT_FAILURE); } } @@ -566,8 +533,7 @@ multi_runner_child::on_suite_end() std::stringstream s; if (num_jobs_ > 1) s << job_index_ << "> "; - s << (suite_results_.failed > 0 ? "failed: " : "") - << suite_results_.name << " had " << suite_results_.failed + s << (suite_results_.failed > 0 ? "failed: " : "") << suite_results_.name << " had " << suite_results_.failed << " failures." << std::endl; message_queue_send(MessageType::log, s.str()); } @@ -586,8 +552,7 @@ multi_runner_child::on_case_begin(std::string const& name) std::stringstream s; if (num_jobs_ > 1) s << job_index_ << "> "; - s << suite_results_.name - << (case_results_.name.empty() ? "" : (" " + case_results_.name)) << '\n'; + s << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name)) << '\n'; message_queue_send(MessageType::log, s.str()); } @@ -611,8 +576,7 @@ multi_runner_child::on_fail(std::string const& reason) std::stringstream s; if (num_jobs_ > 1) s << job_index_ << "> "; - s << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") - << reason << '\n'; + s << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason << '\n'; message_queue_send(MessageType::log, s.str()); } diff --git a/src/test/unit_test/multi_runner.h b/src/test/unit_test/multi_runner.h index 813af61572..25649d917f 100644 --- a/src/test/unit_test/multi_runner.h +++ b/src/test/unit_test/multi_runner.h @@ -135,8 +135,7 @@ class multi_runner_base static constexpr char const* shared_mem_name_ = "RippledUnitTestSharedMem"; // name of the message queue a multi_runner_child will use to communicate // with multi_runner_parent - static constexpr char const* message_queue_name_ = - "RippledUnitTestMessageQueue"; + static constexpr char const* message_queue_name_ = "RippledUnitTestMessageQueue"; // `inner_` will be created in shared memory inner* inner_; @@ -233,8 +232,7 @@ public: /** A class to run a subset of unit tests */ -class multi_runner_child : public beast::unit_test::runner, - private detail::multi_runner_base +class multi_runner_child : public beast::unit_test::runner, private detail::multi_runner_base { private: std::size_t job_index_; diff --git a/src/tests/libxrpl/basics/Slice.cpp b/src/tests/libxrpl/basics/Slice.cpp index b36abe596d..4373f98168 100644 --- a/src/tests/libxrpl/basics/Slice.cpp +++ b/src/tests/libxrpl/basics/Slice.cpp @@ -7,10 +7,9 @@ using namespace xrpl; -static std::uint8_t const data[] = { - 0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23, 0x71, 0x6d, 0x2a, - 0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c, - 0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3}; +static std::uint8_t const data[] = {0xa8, 0xa1, 0x38, 0x45, 0x23, 0xec, 0xe4, 0x23, 0x71, 0x6d, 0x2a, + 0x18, 0xb4, 0x70, 0xcb, 0xf5, 0xac, 0x2d, 0x89, 0x4d, 0x19, 0x9c, + 0xf0, 0x2c, 0x15, 0xd1, 0xf9, 0x9b, 0x66, 0xd2, 0x30, 0xd3}; TEST(Slice, equality_and_inequality) { diff --git a/src/tests/libxrpl/basics/tagged_integer.cpp b/src/tests/libxrpl/basics/tagged_integer.cpp index 09f8b6787b..e24b299442 100644 --- a/src/tests/libxrpl/basics/tagged_integer.cpp +++ b/src/tests/libxrpl/basics/tagged_integer.cpp @@ -53,25 +53,15 @@ static_assert( !std::is_assignable::value, "TagUInt3 should not be assignable with a std::uint64_t"); -static_assert( - std::is_assignable::value, - "TagUInt1 should be assignable with a TagUInt1"); +static_assert(std::is_assignable::value, "TagUInt1 should be assignable with a TagUInt1"); -static_assert( - !std::is_assignable::value, - "TagUInt1 should not be assignable with a TagUInt2"); +static_assert(!std::is_assignable::value, "TagUInt1 should not be assignable with a TagUInt2"); -static_assert( - std::is_assignable::value, - "TagUInt3 should be assignable with a TagUInt1"); +static_assert(std::is_assignable::value, "TagUInt3 should be assignable with a TagUInt1"); -static_assert( - !std::is_assignable::value, - "TagUInt1 should not be assignable with a TagUInt3"); +static_assert(!std::is_assignable::value, "TagUInt1 should not be assignable with a TagUInt3"); -static_assert( - !std::is_assignable::value, - "TagUInt3 should not be assignable with a TagUInt1"); +static_assert(!std::is_assignable::value, "TagUInt3 should not be assignable with a TagUInt1"); // Check convertibility of tagged_integers static_assert( @@ -90,17 +80,11 @@ static_assert( !std::is_convertible::value, "std::uint64_t should not be convertible to a TagUInt2"); -static_assert( - !std::is_convertible::value, - "TagUInt1 should not be convertible to TagUInt2"); +static_assert(!std::is_convertible::value, "TagUInt1 should not be convertible to TagUInt2"); -static_assert( - !std::is_convertible::value, - "TagUInt1 should not be convertible to TagUInt3"); +static_assert(!std::is_convertible::value, "TagUInt1 should not be convertible to TagUInt3"); -static_assert( - !std::is_convertible::value, - "TagUInt2 should not be convertible to a TagUInt3"); +static_assert(!std::is_convertible::value, "TagUInt2 should not be convertible to a TagUInt3"); using TagInt = tagged_integer; diff --git a/src/tests/libxrpl/helpers/TestSink.cpp b/src/tests/libxrpl/helpers/TestSink.cpp index a71e9f7cc0..17cc110429 100644 --- a/src/tests/libxrpl/helpers/TestSink.cpp +++ b/src/tests/libxrpl/helpers/TestSink.cpp @@ -15,8 +15,7 @@ namespace xrpl { -TestSink::TestSink(beast::severities::Severity threshold) - : Sink(threshold, false) +TestSink::TestSink(beast::severities::Severity threshold) : Sink(threshold, false) { } @@ -29,9 +28,7 @@ TestSink::write(beast::severities::Severity level, std::string const& text) } void -TestSink::writeAlways( - beast::severities::Severity level, - std::string const& text) +TestSink::writeAlways(beast::severities::Severity level, std::string const& text) { auto supportsColor = [] { // 1. Check for "NO_COLOR" environment variable (Standard convention) diff --git a/src/tests/libxrpl/helpers/TestSink.h b/src/tests/libxrpl/helpers/TestSink.h index fc3223b04b..aa34e16838 100644 --- a/src/tests/libxrpl/helpers/TestSink.h +++ b/src/tests/libxrpl/helpers/TestSink.h @@ -20,8 +20,7 @@ public: write(beast::severities::Severity level, std::string const& text) override; void - writeAlways(beast::severities::Severity level, std::string const& text) - override; + writeAlways(beast::severities::Severity level, std::string const& text) override; }; } // namespace xrpl #endif // XRPL_DEBUGSINK_H diff --git a/src/tests/libxrpl/json/Value.cpp b/src/tests/libxrpl/json/Value.cpp index 4db1274a4d..1d1131b209 100644 --- a/src/tests/libxrpl/json/Value.cpp +++ b/src/tests/libxrpl/json/Value.cpp @@ -32,8 +32,7 @@ TEST(json_value, construct_and_compare_Json_StaticString) EXPECT_EQ(addrTest1, &sample[0]); EXPECT_EQ(test1.c_str(), &sample[0]); - static constexpr Json::StaticString test2{ - "Contents of a Json::StaticString"}; + static constexpr Json::StaticString test2{"Contents of a Json::StaticString"}; static constexpr Json::StaticString test3{"Another StaticString"}; EXPECT_EQ(test1, test2); @@ -202,11 +201,7 @@ TEST(json_value, different_types) TEST(json_value, compare_strings) { - auto doCompare = [&](Json::Value const& lhs, - Json::Value const& rhs, - bool lhsEqRhs, - bool lhsLtRhs, - int line) { + auto doCompare = [&](Json::Value const& lhs, Json::Value const& rhs, bool lhsEqRhs, bool lhsLtRhs, int line) { SCOPED_TRACE(line); EXPECT_EQ((lhs == rhs), lhsEqRhs); EXPECT_NE((lhs != rhs), lhsEqRhs); @@ -615,8 +610,7 @@ TEST(json_value, edge_cases) EXPECT_EQ(j1["max_int"].asInt(), max_int); EXPECT_EQ(j1["max_int"].asAbsUInt(), max_int); EXPECT_EQ(j1["min_int"].asInt(), min_int); - EXPECT_EQ( - j1["min_int"].asAbsUInt(), static_cast(min_int) * -1); + EXPECT_EQ(j1["min_int"].asAbsUInt(), static_cast(min_int) * -1); EXPECT_EQ(j1["a_uint"].asUInt(), a_uint); EXPECT_EQ(j1["a_uint"].asAbsUInt(), a_uint); EXPECT_GT(j1["a_uint"], a_large_int); @@ -626,9 +620,7 @@ TEST(json_value, edge_cases) EXPECT_EQ(j1["a_large_int"].asUInt(), a_large_int); EXPECT_LT(j1["a_large_int"], a_uint); EXPECT_EQ(j1["a_small_int"].asInt(), a_small_int); - EXPECT_EQ( - j1["a_small_int"].asAbsUInt(), - static_cast(a_small_int) * -1); + EXPECT_EQ(j1["a_small_int"].asAbsUInt(), static_cast(a_small_int) * -1); EXPECT_LT(j1["a_small_int"], a_uint); } @@ -839,9 +831,7 @@ TEST(json_value, compact) char const* s("{\"array\":[{\"12\":23},{},null,false,0.5]}"); auto countLines = [](std::string const& str) { - return 1 + std::count_if(str.begin(), str.end(), [](char c) { - return c == '\n'; - }); + return 1 + std::count_if(str.begin(), str.end(), [](char c) { return c == '\n'; }); }; EXPECT_TRUE(r.parse(s, j)); diff --git a/src/tests/libxrpl/json/Writer.cpp b/src/tests/libxrpl/json/Writer.cpp index 7016b4322d..54c3221858 100644 --- a/src/tests/libxrpl/json/Writer.cpp +++ b/src/tests/libxrpl/json/Writer.cpp @@ -156,8 +156,7 @@ TEST_F(WriterFixture, complex_object) writer->startSet(Writer::array, "subarray"); writer->append(23.5); writer->finishAll(); - checkOutputAndReset( - R"({"hello":"world","array":[true,12,[{"goodbye":"cruel world.","subarray":[23.5]}]]})"); + checkOutputAndReset(R"({"hello":"world","array":[true,12,[{"goodbye":"cruel world.","subarray":[23.5]}]]})"); } TEST_F(WriterFixture, json_value) diff --git a/src/tests/libxrpl/net/HTTPClient.cpp b/src/tests/libxrpl/net/HTTPClient.cpp index 5ff0bfc336..72a351f9b7 100644 --- a/src/tests/libxrpl/net/HTTPClient.cpp +++ b/src/tests/libxrpl/net/HTTPClient.cpp @@ -65,9 +65,7 @@ public: ~TestHTTPServer() { - XRPL_ASSERT( - finished(), - "xrpl::TestHTTPServer::~TestHTTPServer : accept future ready"); + XRPL_ASSERT(finished(), "xrpl::TestHTTPServer::~TestHTTPServer : accept future ready"); } boost::asio::io_context& @@ -121,8 +119,7 @@ private: { try { - auto socket = - co_await acceptor_.async_accept(boost::asio::use_awaitable); + auto socket = co_await acceptor_.async_accept(boost::asio::use_awaitable); if (!running_) break; @@ -150,8 +147,7 @@ private: boost::beast::http::request req; // Read the HTTP request asynchronously - co_await boost::beast::http::async_read( - socket, buffer, req, boost::asio::use_awaitable); + co_await boost::beast::http::async_read(socket, buffer, req, boost::asio::use_awaitable); // Create response boost::beast::http::response res; @@ -172,13 +168,11 @@ private: } // Send response asynchronously - co_await boost::beast::http::async_write( - socket, res, boost::asio::use_awaitable); + co_await boost::beast::http::async_write(socket, res, boost::asio::use_awaitable); // Shutdown socket gracefully boost::system::error_code shutdownEc; - socket.shutdown( - boost::asio::ip::tcp::socket::shutdown_send, shutdownEc); + socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, shutdownEc); } catch (std::exception const& e) { @@ -212,9 +206,7 @@ runHTTPTest( path, 1024, // max response size std::chrono::seconds(5), - [&](boost::system::error_code const& ec, - int status, - std::string const& data) -> bool { + [&](boost::system::error_code const& ec, int status, std::string const& data) -> bool { resultError = ec; resultStatus = status; resultData = data; @@ -227,9 +219,7 @@ runHTTPTest( auto start = std::chrono::steady_clock::now(); while (server.ioc().run_one() != 0) { - if (std::chrono::steady_clock::now() - start >= - std::chrono::seconds(10) || - server.finished()) + if (std::chrono::steady_clock::now() - start >= std::chrono::seconds(10) || server.finished()) { break; } @@ -268,8 +258,7 @@ TEST(HTTPClient, case_insensitive_content_length) std::string resultData; boost::system::error_code resultError; - bool testCompleted = runHTTPTest( - server, "/test", completed, resultStatus, resultData, resultError); + bool testCompleted = runHTTPTest(server, "/test", completed, resultStatus, resultData, resultError); // Verify results EXPECT_TRUE(testCompleted); @@ -291,8 +280,7 @@ TEST(HTTPClient, basic_http_request) std::string resultData; boost::system::error_code resultError; - bool testCompleted = runHTTPTest( - server, "/basic", completed, resultStatus, resultData, resultError); + bool testCompleted = runHTTPTest(server, "/basic", completed, resultStatus, resultData, resultError); EXPECT_TRUE(testCompleted); EXPECT_FALSE(resultError); @@ -311,8 +299,7 @@ TEST(HTTPClient, empty_response) std::string resultData; boost::system::error_code resultError; - bool testCompleted = runHTTPTest( - server, "/empty", completed, resultStatus, resultData, resultError); + bool testCompleted = runHTTPTest(server, "/empty", completed, resultStatus, resultData, resultError); EXPECT_TRUE(testCompleted); EXPECT_FALSE(resultError); @@ -335,13 +322,7 @@ TEST(HTTPClient, different_status_codes) std::string resultData; boost::system::error_code resultError; - bool testCompleted = runHTTPTest( - server, - "/status", - completed, - resultStatus, - resultData, - resultError); + bool testCompleted = runHTTPTest(server, "/status", completed, resultStatus, resultData, resultError); EXPECT_TRUE(testCompleted); EXPECT_FALSE(resultError); diff --git a/src/xrpld/app/consensus/RCLCensorshipDetector.h b/src/xrpld/app/consensus/RCLCensorshipDetector.h index 97d2743dc1..671337c118 100644 --- a/src/xrpld/app/consensus/RCLCensorshipDetector.h +++ b/src/xrpld/app/consensus/RCLCensorshipDetector.h @@ -19,8 +19,7 @@ public: TxID txid; Sequence seq; - TxIDSeq(TxID const& txid_, Sequence const& seq_) - : txid(txid_), seq(seq_) + TxIDSeq(TxID const& txid_, Sequence const& seq_) : txid(txid_), seq(seq_) { } }; diff --git a/src/xrpld/app/consensus/RCLConsensus.cpp b/src/xrpld/app/consensus/RCLConsensus.cpp index 654c2a8990..35f8eec1a3 100644 --- a/src/xrpld/app/consensus/RCLConsensus.cpp +++ b/src/xrpld/app/consensus/RCLConsensus.cpp @@ -41,14 +41,7 @@ RCLConsensus::RCLConsensus( Consensus::clock_type const& clock, ValidatorKeys const& validatorKeys, beast::Journal journal) - : adaptor_( - app, - std::move(feeVote), - ledgerMaster, - localTxs, - inboundTransactions, - validatorKeys, - journal) + : adaptor_(app, std::move(feeVote), ledgerMaster, localTxs, inboundTransactions, validatorKeys, journal) , consensus_(clock, adaptor_, journal) , j_(journal) { @@ -69,36 +62,25 @@ RCLConsensus::Adaptor::Adaptor( , inboundTransactions_{inboundTransactions} , j_(journal) , validatorKeys_(validatorKeys) - , valCookie_( - 1 + - rand_int( - crypto_prng(), - std::numeric_limits::max() - 1)) + , valCookie_(1 + rand_int(crypto_prng(), std::numeric_limits::max() - 1)) , nUnlVote_(validatorKeys_.nodeID, j_) { - XRPL_ASSERT( - valCookie_, "xrpl::RCLConsensus::Adaptor::Adaptor : nonzero cookie"); + XRPL_ASSERT(valCookie_, "xrpl::RCLConsensus::Adaptor::Adaptor : nonzero cookie"); - JLOG(j_.info()) << "Consensus engine started (cookie: " + - std::to_string(valCookie_) + ")"; + JLOG(j_.info()) << "Consensus engine started (cookie: " + std::to_string(valCookie_) + ")"; if (validatorKeys_.nodeID != beast::zero && validatorKeys_.keys) { std::stringstream ss; JLOG(j_.info()) << "Validator identity: " - << toBase58( - TokenType::NodePublic, - validatorKeys_.keys->masterPublicKey); + << toBase58(TokenType::NodePublic, validatorKeys_.keys->masterPublicKey); - if (validatorKeys_.keys->masterPublicKey != - validatorKeys_.keys->publicKey) + if (validatorKeys_.keys->masterPublicKey != validatorKeys_.keys->publicKey) { - JLOG(j_.debug()) - << "Validator ephemeral signing key: " - << toBase58( - TokenType::NodePublic, validatorKeys_.keys->publicKey) - << " (seq: " << std::to_string(validatorKeys_.sequence) << ")"; + JLOG(j_.debug()) << "Validator ephemeral signing key: " + << toBase58(TokenType::NodePublic, validatorKeys_.keys->publicKey) + << " (seq: " << std::to_string(validatorKeys_.sequence) << ")"; } } } @@ -118,23 +100,17 @@ RCLConsensus::Adaptor::acquireLedger(LedgerHash const& hash) // Tell the ledger acquire system that we need the consensus ledger acquiringLedger_ = hash; - app_.getJobQueue().addJob( - jtADVANCE, "GetConsL1", [id = hash, &app = app_, this]() { - JLOG(j_.debug()) - << "JOB advanceLedger getConsensusLedger1 started"; - app.getInboundLedgers().acquireAsync( - id, 0, InboundLedger::Reason::CONSENSUS); - }); + app_.getJobQueue().addJob(jtADVANCE, "GetConsL1", [id = hash, &app = app_, this]() { + JLOG(j_.debug()) << "JOB advanceLedger getConsensusLedger1 started"; + app.getInboundLedgers().acquireAsync(id, 0, InboundLedger::Reason::CONSENSUS); + }); } return std::nullopt; } XRPL_ASSERT( - !built->open() && built->isImmutable(), - "xrpl::RCLConsensus::Adaptor::acquireLedger : valid ledger state"); - XRPL_ASSERT( - built->header().hash == hash, - "xrpl::RCLConsensus::Adaptor::acquireLedger : ledger hash match"); + !built->open() && built->isImmutable(), "xrpl::RCLConsensus::Adaptor::acquireLedger : valid ledger state"); + XRPL_ASSERT(built->header().hash == hash, "xrpl::RCLConsensus::Adaptor::acquireLedger : ledger hash match"); // Notify inbound transactions of the new ledger sequence number inboundTransactions_.newRound(built->header().seq); @@ -152,10 +128,8 @@ RCLConsensus::Adaptor::share(RCLCxPeerPos const& peerPos) prop.set_proposeseq(proposal.proposeSeq()); prop.set_closetime(proposal.closeTime().time_since_epoch().count()); - prop.set_currenttxhash( - proposal.position().begin(), proposal.position().size()); - prop.set_previousledger( - proposal.prevLedger().begin(), proposal.position().size()); + prop.set_currenttxhash(proposal.position().begin(), proposal.position().size()); + prop.set_previousledger(proposal.prevLedger().begin(), proposal.position().size()); auto const pk = peerPos.publicKey().slice(); prop.set_nodepubkey(pk.data(), pk.size()); @@ -177,8 +151,7 @@ RCLConsensus::Adaptor::share(RCLCxTx const& tx) protocol::TMTransaction msg; msg.set_rawtransaction(slice.data(), slice.size()); msg.set_status(protocol::tsNEW); - msg.set_receivetimestamp( - app_.timeKeeper().now().time_since_epoch().count()); + msg.set_receivetimestamp(app_.timeKeeper().now().time_since_epoch().count()); static std::set skip{}; app_.overlay().relay(tx.id(), msg, skip); } @@ -191,15 +164,12 @@ void RCLConsensus::Adaptor::propose(RCLCxPeerPos::Proposal const& proposal) { JLOG(j_.trace()) << (proposal.isBowOut() ? "We bow out: " : "We propose: ") - << xrpl::to_string(proposal.prevLedger()) << " -> " - << xrpl::to_string(proposal.position()); + << xrpl::to_string(proposal.prevLedger()) << " -> " << xrpl::to_string(proposal.position()); protocol::TMProposeSet prop; - prop.set_currenttxhash( - proposal.position().begin(), proposal.position().size()); - prop.set_previousledger( - proposal.prevLedger().begin(), proposal.prevLedger().size()); + prop.set_currenttxhash(proposal.position().begin(), proposal.position().size()); + prop.set_previousledger(proposal.prevLedger().begin(), proposal.prevLedger().size()); prop.set_proposeseq(proposal.proposeSeq()); prop.set_closetime(proposal.closeTime().time_since_epoch().count()); @@ -214,18 +184,12 @@ RCLConsensus::Adaptor::propose(RCLCxPeerPos::Proposal const& proposal) prop.set_nodepubkey(keys.publicKey.data(), keys.publicKey.size()); - auto sig = - signDigest(keys.publicKey, keys.secretKey, proposal.signingHash()); + auto sig = signDigest(keys.publicKey, keys.secretKey, proposal.signingHash()); prop.set_signature(sig.data(), sig.size()); auto const suppression = proposalUniqueId( - proposal.position(), - proposal.prevLedger(), - proposal.proposeSeq(), - proposal.closeTime(), - keys.publicKey, - sig); + proposal.position(), proposal.prevLedger(), proposal.proposeSeq(), proposal.closeTime(), keys.publicKey, sig); app_.getHashRouter().addSuppression(suppression); @@ -261,25 +225,18 @@ RCLConsensus::Adaptor::proposersValidated(LedgerHash const& h) const } std::size_t -RCLConsensus::Adaptor::proposersFinished( - RCLCxLedger const& ledger, - LedgerHash const& h) const +RCLConsensus::Adaptor::proposersFinished(RCLCxLedger const& ledger, LedgerHash const& h) const { RCLValidations& vals = app_.getValidations(); - return vals.getNodesAfter( - RCLValidatedLedger(ledger.ledger_, vals.adaptor().journal()), h); + return vals.getNodesAfter(RCLValidatedLedger(ledger.ledger_, vals.adaptor().journal()), h); } uint256 -RCLConsensus::Adaptor::getPrevLedger( - uint256 ledgerID, - RCLCxLedger const& ledger, - ConsensusMode mode) +RCLConsensus::Adaptor::getPrevLedger(uint256 ledgerID, RCLCxLedger const& ledger, ConsensusMode mode) { RCLValidations& vals = app_.getValidations(); uint256 netLgr = vals.getPreferred( - RCLValidatedLedger{ledger.ledger_, vals.adaptor().journal()}, - ledgerMaster_.getValidLedgerIndex()); + RCLValidatedLedger{ledger.ledger_, vals.adaptor().journal()}, ledgerMaster_.getValidLedgerIndex()); if (netLgr != ledgerID) { @@ -293,10 +250,8 @@ RCLConsensus::Adaptor::getPrevLedger( } auto -RCLConsensus::Adaptor::onClose( - RCLCxLedger const& ledger, - NetClock::time_point const& closeTime, - ConsensusMode mode) -> Result +RCLConsensus::Adaptor::onClose(RCLCxLedger const& ledger, NetClock::time_point const& closeTime, ConsensusMode mode) + -> Result { bool const wrongLCL = mode == ConsensusMode::wrongLedger; bool const proposing = mode == ConsensusMode::proposing; @@ -311,20 +266,16 @@ RCLConsensus::Adaptor::onClose( auto initialLedger = app_.openLedger().current(); - auto initialSet = - std::make_shared(SHAMapType::TRANSACTION, app_.getNodeFamily()); + auto initialSet = std::make_shared(SHAMapType::TRANSACTION, app_.getNodeFamily()); initialSet->setUnbacked(); // Build SHAMap containing all transactions in our open ledger for (auto const& tx : initialLedger->txs) { - JLOG(j_.trace()) << "Adding open ledger TX " - << tx.first->getTransactionID(); + JLOG(j_.trace()) << "Adding open ledger TX " << tx.first->getTransactionID(); Serializer s(2048); tx.first->add(s); - initialSet->addItem( - SHAMapNodeType::tnTRANSACTION_NM, - make_shamapitem(tx.first->getTransactionID(), s.slice())); + initialSet->addItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(tx.first->getTransactionID(), s.slice())); } // Add pseudo-transactions to the set @@ -335,13 +286,11 @@ RCLConsensus::Adaptor::onClose( // previous ledger was flag ledger, add fee and amendment // pseudo-transactions auto validations = app_.validators().negativeUNLFilter( - app_.getValidations().getTrustedForLedger( - prevLedger->header().parentHash, prevLedger->seq() - 1)); + app_.getValidations().getTrustedForLedger(prevLedger->header().parentHash, prevLedger->seq() - 1)); if (validations.size() >= app_.validators().quorum()) { feeVote_->doVoting(prevLedger, validations, initialSet); - app_.getAmendmentTable().doVoting( - prevLedger, validations, initialSet, j_); + app_.getAmendmentTable().doVoting(prevLedger, validations, initialSet, j_); } } else if (prevLedger->isVotingLedger()) @@ -349,11 +298,7 @@ RCLConsensus::Adaptor::onClose( // previous ledger was a voting ledger, // so the current consensus session is for a flag ledger, // add negative UNL pseudo-transactions - nUnlVote_.doVoting( - prevLedger, - app_.validators().getTrustedMasterKeys(), - app_.getValidations(), - initialSet); + nUnlVote_.doVoting(prevLedger, app_.validators().getTrustedMasterKeys(), app_.getValidations(), initialSet); } } @@ -365,11 +310,9 @@ RCLConsensus::Adaptor::onClose( LedgerIndex const seq = prevLedger->header().seq + 1; RCLCensorshipDetector::TxIDSeqVec proposed; - initialSet->visitLeaves( - [&proposed, - seq](boost::intrusive_ptr const& item) { - proposed.emplace_back(item->key(), seq); - }); + initialSet->visitLeaves([&proposed, seq](boost::intrusive_ptr const& item) { + proposed.emplace_back(item->key(), seq); + }); censorshipDetector_.propose(std::move(proposed)); } @@ -397,13 +340,7 @@ RCLConsensus::Adaptor::onForceAccept( ConsensusMode const& mode, Json::Value&& consensusJson) { - doAccept( - result, - prevLedger, - closeResolution, - rawCloseTimes, - mode, - std::move(consensusJson)); + doAccept(result, prevLedger, closeResolution, rawCloseTimes, mode, std::move(consensusJson)); } void @@ -416,25 +353,16 @@ RCLConsensus::Adaptor::onAccept( Json::Value&& consensusJson, bool const validating) { - app_.getJobQueue().addJob( - jtACCEPT, - "AcceptLedger", - [=, this, cj = std::move(consensusJson)]() mutable { - // Note that no lock is held or acquired during this job. - // This is because generic Consensus guarantees that once a ledger - // is accepted, the consensus results and capture by reference state - // will not change until startRound is called (which happens via - // endConsensus). - RclConsensusLogger clog("onAccept", validating, j_); - this->doAccept( - result, - prevLedger, - closeResolution, - rawCloseTimes, - mode, - std::move(cj)); - this->app_.getOPs().endConsensus(clog.ss()); - }); + app_.getJobQueue().addJob(jtACCEPT, "AcceptLedger", [=, this, cj = std::move(consensusJson)]() mutable { + // Note that no lock is held or acquired during this job. + // This is because generic Consensus guarantees that once a ledger + // is accepted, the consensus results and capture by reference state + // will not change until startRound is called (which happens via + // endConsensus). + RclConsensusLogger clog("onAccept", validating, j_); + this->doAccept(result, prevLedger, closeResolution, rawCloseTimes, mode, std::move(cj)); + this->app_.getOPs().endConsensus(clog.ss()); + }); } void @@ -467,17 +395,13 @@ RCLConsensus::Adaptor::doAccept( else { // We agreed on a close time - consensusCloseTime = effCloseTime( - consensusCloseTime, closeResolution, prevLedger.closeTime()); + consensusCloseTime = effCloseTime(consensusCloseTime, closeResolution, prevLedger.closeTime()); closeTimeCorrect = true; } - JLOG(j_.debug()) << "Report: Prop=" << (proposing ? "yes" : "no") - << " val=" << (validating_ ? "yes" : "no") - << " corLCL=" << (haveCorrectLCL ? "yes" : "no") - << " fail=" << (consensusFail ? "yes" : "no"); - JLOG(j_.debug()) << "Report: Prev = " << prevLedger.id() << ":" - << prevLedger.seq(); + JLOG(j_.debug()) << "Report: Prop=" << (proposing ? "yes" : "no") << " val=" << (validating_ ? "yes" : "no") + << " corLCL=" << (haveCorrectLCL ? "yes" : "no") << " fail=" << (consensusFail ? "yes" : "no"); + JLOG(j_.debug()) << "Report: Prev = " << prevLedger.id() << ":" << prevLedger.seq(); //-------------------------------------------------------------------------- std::set failed; @@ -494,15 +418,13 @@ RCLConsensus::Adaptor::doAccept( { try { - retriableTxs.insert( - std::make_shared(SerialIter{item.slice()})); + retriableTxs.insert(std::make_shared(SerialIter{item.slice()})); JLOG(j_.debug()) << " Tx: " << item.key(); } catch (std::exception const& ex) { failed.insert(item.key()); - JLOG(j_.warn()) - << " Tx: " << item.key() << " throws: " << ex.what(); + JLOG(j_.warn()) << " Tx: " << item.key() << " throws: " << ex.what(); } } @@ -529,9 +451,7 @@ RCLConsensus::Adaptor::doAccept( std::vector accepted; result.txns.map_->visitLeaves( - [&accepted](boost::intrusive_ptr const& item) { - accepted.push_back(item->key()); - }); + [&accepted](boost::intrusive_ptr const& item) { accepted.push_back(item->key()); }); // Track all the transactions which failed or were marked as retriable for (auto const& r : retriableTxs) @@ -539,9 +459,7 @@ RCLConsensus::Adaptor::doAccept( censorshipDetector_.check( std::move(accepted), - [curr = built.seq(), - j = app_.journal("CensorshipDetector"), - &failed](uint256 const& id, LedgerIndex seq) { + [curr = built.seq(), j = app_.journal("CensorshipDetector"), &failed](uint256 const& id, LedgerIndex seq) { if (failed.count(id)) return true; @@ -550,8 +468,7 @@ RCLConsensus::Adaptor::doAccept( if (wait && (wait % censorshipWarnInternal == 0)) { std::ostringstream ss; - ss << "Potential Censorship: Eligible tx " << id - << ", which we are tracking since ledger " << seq + ss << "Potential Censorship: Eligible tx " << id << ", which we are tracking since ledger " << seq << " has not been included as of ledger " << curr << "."; JLOG(j.warn()) << ss.str(); @@ -562,11 +479,9 @@ RCLConsensus::Adaptor::doAccept( } if (validating_) - validating_ = ledgerMaster_.isCompatible( - *built.ledger_, j_.warn(), "Not validating"); + validating_ = ledgerMaster_.isCompatible(*built.ledger_, j_.warn(), "Not validating"); - if (validating_ && !consensusFail && - app_.getValidations().canValidateSeq(built.seq())) + if (validating_ && !consensusFail && app_.getValidations().canValidateSeq(built.seq())) { validate(built, result.txns, proposing); JLOG(j_.info()) << "CNF Val " << newLCLHash; @@ -575,8 +490,7 @@ RCLConsensus::Adaptor::doAccept( JLOG(j_.info()) << "CNF buildLCL " << newLCLHash; // See if we can accept a ledger as fully-validated - ledgerMaster_.consensusBuilt( - built.ledger_, result.txns.id(), std::move(consensusJson)); + ledgerMaster_.consensusBuilt(built.ledger_, result.txns.id(), std::move(consensusJson)); //------------------------------------------------------------------------- { @@ -600,9 +514,8 @@ RCLConsensus::Adaptor::doAccept( // we voted NO try { - JLOG(j_.debug()) - << "Test applying disputed transaction that did" - << " not get in " << dispute.tx().id(); + JLOG(j_.debug()) << "Test applying disputed transaction that did" + << " not get in " << dispute.tx().id(); SerialIter sit(dispute.tx().tx_->slice()); auto txn = std::make_shared(sit); @@ -672,26 +585,20 @@ RCLConsensus::Adaptor::doAccept( // we entered the round with the network, // see how close our close time is to other node's // close time reports, and update our clock. - if ((mode == ConsensusMode::proposing || - mode == ConsensusMode::observing) && - !consensusFail) + if ((mode == ConsensusMode::proposing || mode == ConsensusMode::observing) && !consensusFail) { auto closeTime = rawCloseTimes.self; - JLOG(j_.info()) << "We closed at " - << closeTime.time_since_epoch().count(); + JLOG(j_.info()) << "We closed at " << closeTime.time_since_epoch().count(); using usec64_t = std::chrono::duration; - usec64_t closeTotal = - std::chrono::duration_cast(closeTime.time_since_epoch()); + usec64_t closeTotal = std::chrono::duration_cast(closeTime.time_since_epoch()); int closeCount = 1; for (auto const& [t, v] : rawCloseTimes.peers) { - JLOG(j_.info()) << std::to_string(v) << " time votes for " - << std::to_string(t.time_since_epoch().count()); + JLOG(j_.info()) << std::to_string(v) << " time votes for " << std::to_string(t.time_since_epoch().count()); closeCount += v; - closeTotal += - std::chrono::duration_cast(t.time_since_epoch()) * v; + closeTotal += std::chrono::duration_cast(t.time_since_epoch()) * v; } closeTotal += usec64_t(closeCount / 2); // for round to nearest @@ -700,20 +607,15 @@ RCLConsensus::Adaptor::doAccept( // Use signed times since we are subtracting using duration = std::chrono::duration; using time_point = std::chrono::time_point; - auto offset = time_point{closeTotal} - - std::chrono::time_point_cast(closeTime); - JLOG(j_.info()) << "Our close offset is estimated at " << offset.count() - << " (" << closeCount << ")"; + auto offset = time_point{closeTotal} - std::chrono::time_point_cast(closeTime); + JLOG(j_.info()) << "Our close offset is estimated at " << offset.count() << " (" << closeCount << ")"; app_.timeKeeper().adjustCloseTime(offset); } } void -RCLConsensus::Adaptor::notify( - protocol::NodeEvent ne, - RCLCxLedger const& ledger, - bool haveCorrectLCL) +RCLConsensus::Adaptor::notify(protocol::NodeEvent ne, RCLCxLedger const& ledger, bool haveCorrectLCL) { protocol::TMStatusChange s; @@ -724,11 +626,8 @@ RCLConsensus::Adaptor::notify( s.set_ledgerseq(ledger.seq()); s.set_networktime(app_.timeKeeper().now().time_since_epoch().count()); - s.set_ledgerhashprevious( - ledger.parentID().begin(), - std::decay_t::bytes); - s.set_ledgerhash( - ledger.id().begin(), std::decay_t::bytes); + s.set_ledgerhashprevious(ledger.parentID().begin(), std::decay_t::bytes); + s.set_ledgerhash(ledger.id().begin(), std::decay_t::bytes); std::uint32_t uMin, uMax; if (!ledgerMaster_.getFullValidatedRange(uMin, uMax)) @@ -743,8 +642,7 @@ RCLConsensus::Adaptor::notify( } s.set_firstseq(uMin); s.set_lastseq(uMax); - app_.overlay().foreach( - send_always(std::make_shared(s, protocol::mtSTATUS_CHANGE))); + app_.overlay().foreach(send_always(std::make_shared(s, protocol::mtSTATUS_CHANGE))); JLOG(j_.trace()) << "send status change to peer"; } @@ -767,14 +665,7 @@ RCLConsensus::Adaptor::buildLCL( return buildLedger(*replayData, tapNONE, app_, j_); } return buildLedger( - previousLedger.ledger_, - closeTime, - closeTimeCorrect, - closeResolution, - app_, - retriableTxs, - failedTxs, - j_); + previousLedger.ledger_, closeTime, closeTimeCorrect, closeResolution, app_, retriableTxs, failedTxs, j_); }(); // Update fee computations based on accepted txs @@ -792,10 +683,7 @@ RCLConsensus::Adaptor::buildLCL( } void -RCLConsensus::Adaptor::validate( - RCLCxLedger const& ledger, - RCLTxSet const& txns, - bool proposing) +RCLConsensus::Adaptor::validate(RCLCxLedger const& ledger, RCLTxSet const& txns, bool proposing) { using namespace std::chrono_literals; @@ -814,11 +702,7 @@ RCLConsensus::Adaptor::validate( auto const& keys = *validatorKeys_.keys; auto v = std::make_shared( - lastValidationTime_, - keys.publicKey, - keys.secretKey, - validatorKeys_.nodeID, - [&](STValidation& v) { + lastValidationTime_, keys.publicKey, keys.secretKey, validatorKeys_.nodeID, [&](STValidation& v) { v.setFieldH256(sfLedgerHash, ledger.id()); v.setFieldH256(sfConsensusHash, txns.id()); @@ -852,18 +736,15 @@ RCLConsensus::Adaptor::validate( if (ledger.ledger_->isVotingLedger()) { // Fees: - feeVote_->doValidation( - ledger.ledger_->fees(), ledger.ledger_->rules(), v); + feeVote_->doValidation(ledger.ledger_->fees(), ledger.ledger_->rules(), v); // Amendments // FIXME: pass `v` and have the function insert the array // directly? - auto const amendments = app_.getAmendmentTable().doValidation( - getEnabledAmendments(*ledger.ledger_)); + auto const amendments = app_.getAmendmentTable().doValidation(getEnabledAmendments(*ledger.ledger_)); if (!amendments.empty()) - v.setFieldV256( - sfAmendments, STVector256(sfAmendments, amendments)); + v.setFieldV256(sfAmendments, STVector256(sfAmendments, amendments)); } }); @@ -886,14 +767,11 @@ RCLConsensus::Adaptor::validate( void RCLConsensus::Adaptor::onModeChange(ConsensusMode before, ConsensusMode after) { - JLOG(j_.info()) << "Consensus mode change before=" << to_string(before) - << ", after=" << to_string(after); + JLOG(j_.info()) << "Consensus mode change before=" << to_string(before) << ", after=" << to_string(after); // If we were proposing but aren't any longer, we need to reset the // censorship tracking to avoid bogus warnings. - if ((before == ConsensusMode::proposing || - before == ConsensusMode::observing) && - before != after) + if ((before == ConsensusMode::proposing || before == ConsensusMode::observing) && before != after) censorshipDetector_.reset(); mode_ = after; @@ -912,9 +790,7 @@ RCLConsensus::getJson(bool full) const } void -RCLConsensus::timerEntry( - NetClock::time_point const& now, - std::unique_ptr const& clog) +RCLConsensus::timerEntry(NetClock::time_point const& now, std::unique_ptr const& clog) { try { @@ -951,33 +827,25 @@ RCLConsensus::gotTxSet(NetClock::time_point const& now, RCLTxSet const& txSet) //! @see Consensus::simulate void -RCLConsensus::simulate( - NetClock::time_point const& now, - std::optional consensusDelay) +RCLConsensus::simulate(NetClock::time_point const& now, std::optional consensusDelay) { std::lock_guard _{mutex_}; consensus_.simulate(now, consensusDelay); } bool -RCLConsensus::peerProposal( - NetClock::time_point const& now, - RCLCxPeerPos const& newProposal) +RCLConsensus::peerProposal(NetClock::time_point const& now, RCLCxPeerPos const& newProposal) { std::lock_guard _{mutex_}; return consensus_.peerProposal(now, newProposal); } bool -RCLConsensus::Adaptor::preStartRound( - RCLCxLedger const& prevLgr, - hash_set const& nowTrusted) +RCLConsensus::Adaptor::preStartRound(RCLCxLedger const& prevLgr, hash_set const& nowTrusted) { // We have a key, we do not want out of sync validations after a restart // and are not amendment blocked. - validating_ = validatorKeys_.keys && - prevLgr.seq() >= app_.getMaxDisallowedLedger() && - !app_.getOPs().isBlocked(); + validating_ = validatorKeys_.keys && prevLgr.seq() >= app_.getMaxDisallowedLedger() && !app_.getOPs().isBlocked(); // If we are not running in standalone mode and there's a configured UNL, // check to make sure that it's not expired. @@ -997,14 +865,12 @@ RCLConsensus::Adaptor::preStartRound( if (validating_) { - JLOG(j_.info()) << "Entering consensus process, validating, synced=" - << (synced ? "yes" : "no"); + JLOG(j_.info()) << "Entering consensus process, validating, synced=" << (synced ? "yes" : "no"); } else { // Otherwise we just want to monitor the validation process. - JLOG(j_.info()) << "Entering consensus process, watching, synced=" - << (synced ? "yes" : "no"); + JLOG(j_.info()) << "Entering consensus process, watching, synced=" << (synced ? "yes" : "no"); } // Notify inbound ledgers that we are starting a new round @@ -1037,9 +903,7 @@ RCLConsensus::Adaptor::getQuorumKeys() const } std::size_t -RCLConsensus::Adaptor::laggards( - Ledger_t::Seq const seq, - hash_set& trustedKeys) const +RCLConsensus::Adaptor::laggards(Ledger_t::Seq const seq, hash_set& trustedKeys) const { return app_.getValidations().laggards(seq, trustedKeys); } @@ -1067,20 +931,10 @@ RCLConsensus::startRound( std::unique_ptr const& clog) { std::lock_guard _{mutex_}; - consensus_.startRound( - now, - prevLgrId, - prevLgr, - nowUntrusted, - adaptor_.preStartRound(prevLgr, nowTrusted), - clog); + consensus_.startRound(now, prevLgrId, prevLgr, nowUntrusted, adaptor_.preStartRound(prevLgr, nowTrusted), clog); } -RclConsensusLogger::RclConsensusLogger( - char const* label, - bool const validating, - beast::Journal j) - : j_(j) +RclConsensusLogger::RclConsensusLogger(char const* label, bool const validating, beast::Journal j) : j_(j) { if (!validating && !j.info()) return; @@ -1095,12 +949,11 @@ RclConsensusLogger::~RclConsensusLogger() { if (!ss_) return; - auto const duration = std::chrono::duration_cast( - std::chrono::steady_clock::now() - start_); + auto const duration = + std::chrono::duration_cast(std::chrono::steady_clock::now() - start_); std::stringstream outSs; - outSs << header_ << "duration " << (duration.count() / 1000) << '.' - << std::setw(3) << std::setfill('0') << (duration.count() % 1000) - << "s. " << ss_->str(); + outSs << header_ << "duration " << (duration.count() / 1000) << '.' << std::setw(3) << std::setfill('0') + << (duration.count() % 1000) << "s. " << ss_->str(); j_.sink().writeAlways(beast::severities::kInfo, outSs.str()); } diff --git a/src/xrpld/app/consensus/RCLConsensus.h b/src/xrpld/app/consensus/RCLConsensus.h index 2e33bbae14..476cb25715 100644 --- a/src/xrpld/app/consensus/RCLConsensus.h +++ b/src/xrpld/app/consensus/RCLConsensus.h @@ -63,8 +63,7 @@ class RCLConsensus // thread safety. std::atomic validating_{false}; std::atomic prevProposers_{0}; - std::atomic prevRoundTime_{ - std::chrono::milliseconds{0}}; + std::atomic prevRoundTime_{std::chrono::milliseconds{0}}; std::atomic mode_{ConsensusMode::observing}; RCLCensorshipDetector censorshipDetector_; @@ -119,9 +118,7 @@ class RCLConsensus @return Whether we enter the round proposing */ bool - preStartRound( - RCLCxLedger const& prevLedger, - hash_set const& nowTrusted); + preStartRound(RCLCxLedger const& prevLedger, hash_set const& nowTrusted); bool haveValidated() const; @@ -133,8 +130,7 @@ class RCLConsensus getQuorumKeys() const; std::size_t - laggards(Ledger_t::Seq const seq, hash_set& trustedKeys) - const; + laggards(Ledger_t::Seq const seq, hash_set& trustedKeys) const; /** Whether I am a validator. * @@ -262,10 +258,7 @@ class RCLConsensus the ledger matching ledgerID from the network */ uint256 - getPrevLedger( - uint256 ledgerID, - RCLCxLedger const& ledger, - ConsensusMode mode); + getPrevLedger(uint256 ledgerID, RCLCxLedger const& ledger, ConsensusMode mode); /** Notified of change in consensus mode @@ -283,10 +276,7 @@ class RCLConsensus @return Tentative consensus result */ Result - onClose( - RCLCxLedger const& ledger, - NetClock::time_point const& closeTime, - ConsensusMode mode); + onClose(RCLCxLedger const& ledger, NetClock::time_point const& closeTime, ConsensusMode mode); /** Process the accepted ledger. @@ -332,10 +322,7 @@ class RCLConsensus @param haveCorrectLCL Whether we believe we have the correct LCL. */ void - notify( - protocol::NodeEvent ne, - RCLCxLedger const& ledger, - bool haveCorrectLCL); + notify(protocol::NodeEvent ne, RCLCxLedger const& ledger, bool haveCorrectLCL); /** Accept a new ledger based on the given transactions. @@ -392,10 +379,7 @@ class RCLConsensus but are still around and trying to catch up. */ void - validate( - RCLCxLedger const& ledger, - RCLTxSet const& txns, - bool proposing); + validate(RCLCxLedger const& ledger, RCLTxSet const& txns, bool proposing); }; public: @@ -474,9 +458,7 @@ public: //! @see Consensus::timerEntry void - timerEntry( - NetClock::time_point const& now, - std::unique_ptr const& clog = {}); + timerEntry(NetClock::time_point const& now, std::unique_ptr const& clog = {}); //! @see Consensus::gotTxSet void @@ -492,15 +474,11 @@ public: //! @see Consensus::simulate void - simulate( - NetClock::time_point const& now, - std::optional consensusDelay); + simulate(NetClock::time_point const& now, std::optional consensusDelay); //! @see Consensus::proposal bool - peerProposal( - NetClock::time_point const& now, - RCLCxPeerPos const& newProposal); + peerProposal(NetClock::time_point const& now, RCLCxPeerPos const& newProposal); ConsensusParms const& parms() const @@ -536,10 +514,7 @@ class RclConsensusLogger std::chrono::steady_clock::time_point start_; public: - explicit RclConsensusLogger( - char const* label, - bool validating, - beast::Journal j); + explicit RclConsensusLogger(char const* label, bool validating, beast::Journal j); ~RclConsensusLogger(); std::unique_ptr const& diff --git a/src/xrpld/app/consensus/RCLCxPeerPos.cpp b/src/xrpld/app/consensus/RCLCxPeerPos.cpp index 5f227b00a9..4128d65c49 100644 --- a/src/xrpld/app/consensus/RCLCxPeerPos.cpp +++ b/src/xrpld/app/consensus/RCLCxPeerPos.cpp @@ -11,9 +11,7 @@ RCLCxPeerPos::RCLCxPeerPos( Slice const& signature, uint256 const& suppression, Proposal&& proposal) - : publicKey_(publicKey) - , suppression_(suppression) - , proposal_(std::move(proposal)) + : publicKey_(publicKey), suppression_(suppression), proposal_(std::move(proposal)) { // The maximum allowed size of a signature is 72 bytes; we verify // this elsewhere, but we want to be extra careful here: @@ -28,8 +26,7 @@ RCLCxPeerPos::RCLCxPeerPos( bool RCLCxPeerPos::checkSign() const { - return verifyDigest( - publicKey(), proposal_.signingHash(), signature(), false); + return verifyDigest(publicKey(), proposal_.signingHash(), signature(), false); } Json::Value diff --git a/src/xrpld/app/consensus/RCLCxPeerPos.h b/src/xrpld/app/consensus/RCLCxPeerPos.h index 08b93d4ba9..78a8bfde1e 100644 --- a/src/xrpld/app/consensus/RCLCxPeerPos.h +++ b/src/xrpld/app/consensus/RCLCxPeerPos.h @@ -37,11 +37,7 @@ public: @param proposal The consensus proposal */ - RCLCxPeerPos( - PublicKey const& publicKey, - Slice const& signature, - uint256 const& suppress, - Proposal&& proposal); + RCLCxPeerPos(PublicKey const& publicKey, Slice const& signature, uint256 const& suppress, Proposal&& proposal); //! Verify the signing hash of the proposal bool diff --git a/src/xrpld/app/consensus/RCLCxTx.h b/src/xrpld/app/consensus/RCLCxTx.h index 5e92aea8a6..a0cefcf199 100644 --- a/src/xrpld/app/consensus/RCLCxTx.h +++ b/src/xrpld/app/consensus/RCLCxTx.h @@ -89,8 +89,7 @@ public: */ RCLTxSet(std::shared_ptr m) : map_{std::move(m)} { - XRPL_ASSERT( - map_, "xrpl::RCLTxSet::MutableTxSet::RCLTxSet : non-null input"); + XRPL_ASSERT(map_, "xrpl::RCLTxSet::MutableTxSet::RCLTxSet : non-null input"); } /** Constructor from a previously created MutableTxSet @@ -157,8 +156,7 @@ public: for (auto const& [k, v] : delta) { XRPL_ASSERT( - (v.first && !v.second) || (v.second && !v.first), - "xrpl::RCLTxSet::compare : either side is set"); + (v.first && !v.second) || (v.second && !v.first), "xrpl::RCLTxSet::compare : either side is set"); ret[k] = static_cast(v.first); } diff --git a/src/xrpld/app/consensus/RCLValidations.cpp b/src/xrpld/app/consensus/RCLValidations.cpp index 6438334106..8c99ea9939 100644 --- a/src/xrpld/app/consensus/RCLValidations.cpp +++ b/src/xrpld/app/consensus/RCLValidations.cpp @@ -15,14 +15,11 @@ namespace xrpl { -RCLValidatedLedger::RCLValidatedLedger(MakeGenesis) - : ledgerID_{0}, ledgerSeq_{0}, j_{beast::Journal::getNullSink()} +RCLValidatedLedger::RCLValidatedLedger(MakeGenesis) : ledgerID_{0}, ledgerSeq_{0}, j_{beast::Journal::getNullSink()} { } -RCLValidatedLedger::RCLValidatedLedger( - std::shared_ptr const& ledger, - beast::Journal j) +RCLValidatedLedger::RCLValidatedLedger(std::shared_ptr const& ledger, beast::Journal j) : ledgerID_{ledger->header().hash}, ledgerSeq_{ledger->seq()}, j_{j} { auto const hashIndex = ledger->read(keylet::skip()); @@ -35,8 +32,7 @@ RCLValidatedLedger::RCLValidatedLedger( ancestors_ = hashIndex->getFieldV256(sfHashes).value(); } else - JLOG(j_.warn()) << "Ledger " << ledgerSeq_ << ":" << ledgerID_ - << " missing recent ancestor hashes"; + JLOG(j_.warn()) << "Ledger " << ledgerSeq_ << ":" << ledgerID_ << " missing recent ancestor hashes"; } auto @@ -67,10 +63,8 @@ RCLValidatedLedger::operator[](Seq const& s) const -> ID return ancestors_[ancestors_.size() - diff]; } - JLOG(j_.warn()) << "Unable to determine hash of ancestor seq=" << s - << " from ledger hash=" << ledgerID_ - << " seq=" << ledgerSeq_ << " (available: " << minSeq() - << "-" << seq() << ")"; + JLOG(j_.warn()) << "Unable to determine hash of ancestor seq=" << s << " from ledger hash=" << ledgerID_ + << " seq=" << ledgerSeq_ << " (available: " << minSeq() << "-" << seq() << ")"; // Default ID that is less than all others return ID{0}; } @@ -94,8 +88,7 @@ mismatch(RCLValidatedLedger const& a, RCLValidatedLedger const& b) return (curr < lower) ? Seq{1} : (curr + Seq{1}); } -RCLValidationsAdaptor::RCLValidationsAdaptor(Application& app, beast::Journal j) - : app_(app), j_(j) +RCLValidationsAdaptor::RCLValidationsAdaptor(Application& app, beast::Journal j) : app_(app), j_(j) { } @@ -110,32 +103,23 @@ RCLValidationsAdaptor::acquire(LedgerHash const& hash) { using namespace std::chrono_literals; auto ledger = perf::measureDurationAndLog( - [&]() { return app_.getLedgerMaster().getLedgerByHash(hash); }, - "getLedgerByHash", - 10ms, - j_); + [&]() { return app_.getLedgerMaster().getLedgerByHash(hash); }, "getLedgerByHash", 10ms, j_); if (!ledger) { - JLOG(j_.warn()) - << "Need validated ledger for preferred ledger analysis " << hash; + JLOG(j_.warn()) << "Need validated ledger for preferred ledger analysis " << hash; Application* pApp = &app_; app_.getJobQueue().addJob(jtADVANCE, "GetConsL2", [pApp, hash, this]() { JLOG(j_.debug()) << "JOB advanceLedger getConsensusLedger2 started"; - pApp->getInboundLedgers().acquireAsync( - hash, 0, InboundLedger::Reason::CONSENSUS); + pApp->getInboundLedgers().acquireAsync(hash, 0, InboundLedger::Reason::CONSENSUS); }); return std::nullopt; } - XRPL_ASSERT( - !ledger->open() && ledger->isImmutable(), - "xrpl::RCLValidationsAdaptor::acquire : valid ledger state"); - XRPL_ASSERT( - ledger->header().hash == hash, - "xrpl::RCLValidationsAdaptor::acquire : ledger hash match"); + XRPL_ASSERT(!ledger->open() && ledger->isImmutable(), "xrpl::RCLValidationsAdaptor::acquire : valid ledger state"); + XRPL_ASSERT(ledger->header().hash == hash, "xrpl::RCLValidationsAdaptor::acquire : ledger hash match"); return RCLValidatedLedger(std::move(ledger), j_); } @@ -165,8 +149,7 @@ handleNewValidation( auto& validations = app.getValidations(); // masterKey is seated only if validator is trusted or listed - auto const outcome = - validations.add(calcNodeID(masterKey.value_or(signingKey)), val); + auto const outcome = validations.add(calcNodeID(masterKey.value_or(signingKey)), val); if (outcome == ValStatus::current) { @@ -174,12 +157,10 @@ handleNewValidation( { if (bypassAccept == BypassAccept::yes) { - XRPL_ASSERT( - j, "xrpl::handleNewValidation : journal is available"); + XRPL_ASSERT(j, "xrpl::handleNewValidation : journal is available"); if (j.has_value()) { - JLOG(j->trace()) << "Bypassing checkAccept for validation " - << val->getLedgerHash(); + JLOG(j->trace()) << "Bypassing checkAccept for validation " << val->getLedgerHash(); } } else @@ -198,9 +179,8 @@ handleNewValidation( // counterintuitively, we *especially* want to forward such validations, // so that our peers will also observe them and take independent notice of // such validators, informing their operators. - if (auto const ls = val->isTrusted() - ? validations.adaptor().journal().error() - : validations.adaptor().journal().info(); + if (auto const ls = + val->isTrusted() ? validations.adaptor().journal().error() : validations.adaptor().journal().info(); ls.active()) { auto const id = [&masterKey, &signingKey]() { @@ -213,16 +193,12 @@ handleNewValidation( }(); if (outcome == ValStatus::conflicting) - ls << "Byzantine Behavior Detector: " - << (val->isTrusted() ? "trusted " : "untrusted ") << id - << ": Conflicting validation for " << seq << "!\n[" - << val->getSerializer().slice() << "]"; + ls << "Byzantine Behavior Detector: " << (val->isTrusted() ? "trusted " : "untrusted ") << id + << ": Conflicting validation for " << seq << "!\n[" << val->getSerializer().slice() << "]"; if (outcome == ValStatus::multiple) - ls << "Byzantine Behavior Detector: " - << (val->isTrusted() ? "trusted " : "untrusted ") << id - << ": Multiple validations for " << seq << "/" << hash << "!\n[" - << val->getSerializer().slice() << "]"; + ls << "Byzantine Behavior Detector: " << (val->isTrusted() ? "trusted " : "untrusted ") << id + << ": Multiple validations for " << seq << "/" << hash << "!\n[" << val->getSerializer().slice() << "]"; } } diff --git a/src/xrpld/app/consensus/RCLValidations.h b/src/xrpld/app/consensus/RCLValidations.h index 62dd52b1dd..97ccb727fe 100644 --- a/src/xrpld/app/consensus/RCLValidations.h +++ b/src/xrpld/app/consensus/RCLValidations.h @@ -148,9 +148,7 @@ public: RCLValidatedLedger(MakeGenesis); - RCLValidatedLedger( - std::shared_ptr const& ledger, - beast::Journal j); + RCLValidatedLedger(std::shared_ptr const& ledger, beast::Journal j); /// The sequence (index) of the ledger Seq diff --git a/src/xrpld/app/ledger/AcceptedLedger.cpp b/src/xrpld/app/ledger/AcceptedLedger.cpp index 76099ff864..89806c2337 100644 --- a/src/xrpld/app/ledger/AcceptedLedger.cpp +++ b/src/xrpld/app/ledger/AcceptedLedger.cpp @@ -4,28 +4,21 @@ namespace xrpl { -AcceptedLedger::AcceptedLedger( - std::shared_ptr const& ledger, - Application& app) - : mLedger(ledger) +AcceptedLedger::AcceptedLedger(std::shared_ptr const& ledger, Application& app) : mLedger(ledger) { transactions_.reserve(256); auto insertAll = [&](auto const& txns) { for (auto const& item : txns) - transactions_.emplace_back(std::make_unique( - ledger, item.first, item.second)); + transactions_.emplace_back(std::make_unique(ledger, item.first, item.second)); }; transactions_.reserve(256); insertAll(ledger->txs); - std::sort( - transactions_.begin(), - transactions_.end(), - [](auto const& a, auto const& b) { - return a->getTxnSeq() < b->getTxnSeq(); - }); + std::sort(transactions_.begin(), transactions_.end(), [](auto const& a, auto const& b) { + return a->getTxnSeq() < b->getTxnSeq(); + }); } } // namespace xrpl diff --git a/src/xrpld/app/ledger/AcceptedLedger.h b/src/xrpld/app/ledger/AcceptedLedger.h index 41177e7078..37e5d01a26 100644 --- a/src/xrpld/app/ledger/AcceptedLedger.h +++ b/src/xrpld/app/ledger/AcceptedLedger.h @@ -24,9 +24,7 @@ namespace xrpl { class AcceptedLedger : public CountedObject { public: - AcceptedLedger( - std::shared_ptr const& ledger, - Application& app); + AcceptedLedger(std::shared_ptr const& ledger, Application& app); std::shared_ptr const& getLedger() const diff --git a/src/xrpld/app/ledger/AcceptedLedgerTx.cpp b/src/xrpld/app/ledger/AcceptedLedgerTx.cpp index d57246444f..2ef05e511d 100644 --- a/src/xrpld/app/ledger/AcceptedLedgerTx.cpp +++ b/src/xrpld/app/ledger/AcceptedLedgerTx.cpp @@ -11,13 +11,9 @@ AcceptedLedgerTx::AcceptedLedgerTx( std::shared_ptr const& ledger, std::shared_ptr const& txn, std::shared_ptr const& met) - : mTxn(txn) - , mMeta(txn->getTransactionID(), ledger->seq(), *met) - , mAffected(mMeta.getAffectedAccounts()) + : mTxn(txn), mMeta(txn->getTransactionID(), ledger->seq(), *met), mAffected(mMeta.getAffectedAccounts()) { - XRPL_ASSERT( - !ledger->open(), - "xrpl::AcceptedLedgerTx::AcceptedLedgerTx : valid ledger state"); + XRPL_ASSERT(!ledger->open(), "xrpl::AcceptedLedgerTx::AcceptedLedgerTx : valid ledger state"); Serializer s; met->add(s); @@ -46,12 +42,8 @@ AcceptedLedgerTx::AcceptedLedgerTx( // If the offer create is not self funded then add the owner balance if (account != amount.issue().account) { - auto const ownerFunds = accountFunds( - *ledger, - account, - amount, - fhIGNORE_FREEZE, - beast::Journal{beast::Journal::getNullSink()}); + auto const ownerFunds = + accountFunds(*ledger, account, amount, fhIGNORE_FREEZE, beast::Journal{beast::Journal::getNullSink()}); mJson[jss::transaction][jss::owner_funds] = ownerFunds.getText(); } } @@ -60,9 +52,7 @@ AcceptedLedgerTx::AcceptedLedgerTx( std::string AcceptedLedgerTx::getEscMeta() const { - XRPL_ASSERT( - !mRawMeta.empty(), - "xrpl::AcceptedLedgerTx::getEscMeta : metadata is set"); + XRPL_ASSERT(!mRawMeta.empty(), "xrpl::AcceptedLedgerTx::getEscMeta : metadata is set"); return sqlBlobLiteral(mRawMeta); } diff --git a/src/xrpld/app/ledger/AccountStateSF.cpp b/src/xrpld/app/ledger/AccountStateSF.cpp index 44f18b5cd3..048a46e810 100644 --- a/src/xrpld/app/ledger/AccountStateSF.cpp +++ b/src/xrpld/app/ledger/AccountStateSF.cpp @@ -3,15 +3,10 @@ namespace xrpl { void -AccountStateSF::gotNode( - bool, - SHAMapHash const& nodeHash, - std::uint32_t ledgerSeq, - Blob&& nodeData, - SHAMapNodeType) const +AccountStateSF::gotNode(bool, SHAMapHash const& nodeHash, std::uint32_t ledgerSeq, Blob&& nodeData, SHAMapNodeType) + const { - db_.store( - hotACCOUNT_NODE, std::move(nodeData), nodeHash.as_uint256(), ledgerSeq); + db_.store(hotACCOUNT_NODE, std::move(nodeData), nodeHash.as_uint256(), ledgerSeq); } std::optional diff --git a/src/xrpld/app/ledger/AccountStateSF.h b/src/xrpld/app/ledger/AccountStateSF.h index 84738f6e1f..40f40ac8a1 100644 --- a/src/xrpld/app/ledger/AccountStateSF.h +++ b/src/xrpld/app/ledger/AccountStateSF.h @@ -13,18 +13,13 @@ namespace xrpl { class AccountStateSF : public SHAMapSyncFilter { public: - AccountStateSF(NodeStore::Database& db, AbstractFetchPackContainer& fp) - : db_(db), fp_(fp) + AccountStateSF(NodeStore::Database& db, AbstractFetchPackContainer& fp) : db_(db), fp_(fp) { } void - gotNode( - bool fromFilter, - SHAMapHash const& nodeHash, - std::uint32_t ledgerSeq, - Blob&& nodeData, - SHAMapNodeType type) const override; + gotNode(bool fromFilter, SHAMapHash const& nodeHash, std::uint32_t ledgerSeq, Blob&& nodeData, SHAMapNodeType type) + const override; std::optional getNode(SHAMapHash const& nodeHash) const override; diff --git a/src/xrpld/app/ledger/BookListeners.cpp b/src/xrpld/app/ledger/BookListeners.cpp index ebd59c3fcc..4d72c6f3b3 100644 --- a/src/xrpld/app/ledger/BookListeners.cpp +++ b/src/xrpld/app/ledger/BookListeners.cpp @@ -17,9 +17,7 @@ BookListeners::removeSubscriber(std::uint64_t seq) } void -BookListeners::publish( - MultiApiJson const& jvObj, - hash_set& havePublished) +BookListeners::publish(MultiApiJson const& jvObj, hash_set& havePublished) { std::lock_guard sl(mLock); auto it = mListeners.cbegin(); diff --git a/src/xrpld/app/ledger/BuildLedger.h b/src/xrpld/app/ledger/BuildLedger.h index ad6aba3288..24b9e988ff 100644 --- a/src/xrpld/app/ledger/BuildLedger.h +++ b/src/xrpld/app/ledger/BuildLedger.h @@ -51,11 +51,7 @@ buildLedger( @return The newly built ledger */ std::shared_ptr -buildLedger( - LedgerReplay const& replayData, - ApplyFlags applyFlags, - Application& app, - beast::Journal j); +buildLedger(LedgerReplay const& replayData, ApplyFlags applyFlags, Application& app, beast::Journal j); } // namespace xrpl #endif diff --git a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp index 6678ee6334..6a8dbd3d7d 100644 --- a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp +++ b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp @@ -32,8 +32,7 @@ ConsensusTransSetSF::gotNode( if ((type == SHAMapNodeType::tnTRANSACTION_NM) && (nodeData.size() > 16)) { // this is a transaction, and we didn't have it - JLOG(j_.debug()) - << "Node on our acquiring TX set is TXN we may not have"; + JLOG(j_.debug()) << "Node on our acquiring TX set is TXN we may not have"; try { @@ -46,15 +45,12 @@ ConsensusTransSetSF::gotNode( "xrpl::ConsensusTransSetSF::gotNode : transaction hash " "match"); auto const pap = &app_; - app_.getJobQueue().addJob(jtTRANSACTION, "TxsToTxn", [pap, stx]() { - pap->getOPs().submitTransaction(stx); - }); + app_.getJobQueue().addJob( + jtTRANSACTION, "TxsToTxn", [pap, stx]() { pap->getOPs().submitTransaction(stx); }); } catch (std::exception const& ex) { - JLOG(j_.warn()) - << "Fetched invalid transaction in proposed set. Exception: " - << ex.what(); + JLOG(j_.warn()) << "Fetched invalid transaction in proposed set. Exception: " << ex.what(); } } } @@ -66,8 +62,7 @@ ConsensusTransSetSF::getNode(SHAMapHash const& nodeHash) const if (m_nodeCache.retrieve(nodeHash, nodeData)) return nodeData; - auto txn = - app_.getMasterTransaction().fetch_from_cache(nodeHash.as_uint256()); + auto txn = app_.getMasterTransaction().fetch_from_cache(nodeHash.as_uint256()); if (txn) { diff --git a/src/xrpld/app/ledger/ConsensusTransSetSF.h b/src/xrpld/app/ledger/ConsensusTransSetSF.h index cdb1c47183..1e9acefc38 100644 --- a/src/xrpld/app/ledger/ConsensusTransSetSF.h +++ b/src/xrpld/app/ledger/ConsensusTransSetSF.h @@ -22,12 +22,8 @@ public: // Note that the nodeData is overwritten by this call void - gotNode( - bool fromFilter, - SHAMapHash const& nodeHash, - std::uint32_t ledgerSeq, - Blob&& nodeData, - SHAMapNodeType type) const override; + gotNode(bool fromFilter, SHAMapHash const& nodeHash, std::uint32_t ledgerSeq, Blob&& nodeData, SHAMapNodeType type) + const override; std::optional getNode(SHAMapHash const& nodeHash) const override; diff --git a/src/xrpld/app/ledger/InboundLedger.h b/src/xrpld/app/ledger/InboundLedger.h index 1b4353b260..c062b83143 100644 --- a/src/xrpld/app/ledger/InboundLedger.h +++ b/src/xrpld/app/ledger/InboundLedger.h @@ -75,12 +75,9 @@ public: init(ScopedLockType& collectionLock); bool - gotData( - std::weak_ptr, - std::shared_ptr const&); + gotData(std::weak_ptr, std::shared_ptr const&); - using neededHash_t = - std::pair; + using neededHash_t = std::pair; /** Return a Json::objectValue. */ Json::Value @@ -105,9 +102,7 @@ private: enum class TriggerReason { added, reply, timeout }; void - filterNodes( - std::vector>& nodes, - TriggerReason reason); + filterNodes(std::vector>& nodes, TriggerReason reason); void trigger(std::shared_ptr const&, TriggerReason); @@ -172,9 +167,7 @@ private: // Data we have received from peers std::mutex mReceivedDataLock; - std::vector< - std::pair, std::shared_ptr>> - mReceivedData; + std::vector, std::shared_ptr>> mReceivedData; bool mReceiveDispatched; std::unique_ptr mPeerSet; }; diff --git a/src/xrpld/app/ledger/InboundLedgers.h b/src/xrpld/app/ledger/InboundLedgers.h index 0e4d9996bb..6b4b1a6ef0 100644 --- a/src/xrpld/app/ledger/InboundLedgers.h +++ b/src/xrpld/app/ledger/InboundLedgers.h @@ -27,10 +27,7 @@ public: // Queue. TODO review whether all callers of acquire() can use this // instead. Inbound ledger acquisition is asynchronous anyway. virtual void - acquireAsync( - uint256 const& hash, - std::uint32_t seq, - InboundLedger::Reason reason) = 0; + acquireAsync(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason reason) = 0; virtual std::shared_ptr find(LedgerHash const& hash) = 0; @@ -38,10 +35,7 @@ public: // VFALCO TODO Remove the dependency on the Peer object. // virtual bool - gotLedgerData( - LedgerHash const& ledgerHash, - std::shared_ptr, - std::shared_ptr) = 0; + gotLedgerData(LedgerHash const& ledgerHash, std::shared_ptr, std::shared_ptr) = 0; virtual void gotStaleData(std::shared_ptr packet) = 0; diff --git a/src/xrpld/app/ledger/InboundTransactions.h b/src/xrpld/app/ledger/InboundTransactions.h index 6c0281e26f..e905fb1846 100644 --- a/src/xrpld/app/ledger/InboundTransactions.h +++ b/src/xrpld/app/ledger/InboundTransactions.h @@ -45,10 +45,7 @@ public: * @param message The LedgerData message. */ virtual void - gotData( - uint256 const& setHash, - std::shared_ptr peer, - std::shared_ptr message) = 0; + gotData(uint256 const& setHash, std::shared_ptr peer, std::shared_ptr message) = 0; /** Add a transaction set. * @@ -58,10 +55,7 @@ public: * or constructed by ourself during consensus. */ virtual void - giveSet( - uint256 const& setHash, - std::shared_ptr const& set, - bool acquired) = 0; + giveSet(uint256 const& setHash, std::shared_ptr const& set, bool acquired) = 0; /** Informs the container if a new consensus round */ diff --git a/src/xrpld/app/ledger/Ledger.cpp b/src/xrpld/app/ledger/Ledger.cpp index e21cbb6d54..9ad08f9894 100644 --- a/src/xrpld/app/ledger/Ledger.cpp +++ b/src/xrpld/app/ledger/Ledger.cpp @@ -109,8 +109,7 @@ public: txs_iter_impl(txs_iter_impl const&) = default; - txs_iter_impl(bool metadata, SHAMap::const_iterator iter) - : metadata_(metadata), iter_(std::move(iter)) + txs_iter_impl(bool metadata, SHAMap::const_iterator iter) : metadata_(metadata), iter_(std::move(iter)) { } @@ -146,11 +145,7 @@ public: //------------------------------------------------------------------------------ -Ledger::Ledger( - create_genesis_t, - Config const& config, - std::vector const& amendments, - Family& family) +Ledger::Ledger(create_genesis_t, Config const& config, std::vector const& amendments, Family& family) : mImmutable(false) , txMap_(SHAMapType::TRANSACTION, family) , stateMap_(SHAMapType::STATE, family) @@ -161,9 +156,7 @@ Ledger::Ledger( header_.drops = INITIAL_XRP; header_.closeTimeResolution = ledgerGenesisTimeResolution; - static auto const id = calcAccountID( - generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")) - .first); + static auto const id = calcAccountID(generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")).first); { auto const sle = std::make_shared(keylet::account(id)); sle->setFieldU32(sfSequence, 1); @@ -182,8 +175,7 @@ Ledger::Ledger( { auto sle = std::make_shared(keylet::fees()); // Whether featureXRPFees is supported will depend on startup options. - if (std::find(amendments.begin(), amendments.end(), featureXRPFees) != - amendments.end()) + if (std::find(amendments.begin(), amendments.end(), featureXRPFees) != amendments.end()) { sle->at(sfBaseFeeDrops) = config.FEES.reference_fee; sle->at(sfReserveBaseDrops) = config.FEES.account_reserve; @@ -191,14 +183,11 @@ Ledger::Ledger( } else { - if (auto const f = - config.FEES.reference_fee.dropsAs()) + if (auto const f = config.FEES.reference_fee.dropsAs()) sle->at(sfBaseFee) = *f; - if (auto const f = - config.FEES.account_reserve.dropsAs()) + if (auto const f = config.FEES.account_reserve.dropsAs()) sle->at(sfReserveBase) = *f; - if (auto const f = - config.FEES.owner_reserve.dropsAs()) + if (auto const f = config.FEES.owner_reserve.dropsAs()) sle->at(sfReserveIncrement) = *f; sle->at(sfReferenceFeeUnits) = Config::FEE_UNITS_DEPRECATED; } @@ -225,20 +214,16 @@ Ledger::Ledger( { loaded = true; - if (header_.txHash.isNonZero() && - !txMap_.fetchRoot(SHAMapHash{header_.txHash}, nullptr)) + if (header_.txHash.isNonZero() && !txMap_.fetchRoot(SHAMapHash{header_.txHash}, nullptr)) { loaded = false; - JLOG(j.warn()) << "Don't have transaction root for ledger" - << header_.seq; + JLOG(j.warn()) << "Don't have transaction root for ledger" << header_.seq; } - if (header_.accountHash.isNonZero() && - !stateMap_.fetchRoot(SHAMapHash{header_.accountHash}, nullptr)) + if (header_.accountHash.isNonZero() && !stateMap_.fetchRoot(SHAMapHash{header_.accountHash}, nullptr)) { loaded = false; - JLOG(j.warn()) << "Don't have state data root for ledger" - << header_.seq; + JLOG(j.warn()) << "Don't have state data root for ledger" << header_.seq; } txMap_.setImmutable(); @@ -272,19 +257,15 @@ Ledger::Ledger(Ledger const& prevLedger, NetClock::time_point closeTime) header_.closeTimeResolution = prevLedger.header_.closeTimeResolution; header_.parentHash = prevLedger.header().hash; header_.closeTimeResolution = getNextLedgerTimeResolution( - prevLedger.header_.closeTimeResolution, - getCloseAgree(prevLedger.header()), - header_.seq); + prevLedger.header_.closeTimeResolution, getCloseAgree(prevLedger.header()), header_.seq); if (prevLedger.header_.closeTime == NetClock::time_point{}) { - header_.closeTime = - roundCloseTime(closeTime, header_.closeTimeResolution); + header_.closeTime = roundCloseTime(closeTime, header_.closeTimeResolution); } else { - header_.closeTime = - prevLedger.header_.closeTime + header_.closeTimeResolution; + header_.closeTime = prevLedger.header_.closeTime + header_.closeTimeResolution; } } @@ -299,11 +280,7 @@ Ledger::Ledger(LedgerHeader const& info, Config const& config, Family& family) header_.hash = calculateLedgerHash(header_); } -Ledger::Ledger( - std::uint32_t ledgerSeq, - NetClock::time_point closeTime, - Config const& config, - Family& family) +Ledger::Ledger(std::uint32_t ledgerSeq, NetClock::time_point closeTime, Config const& config, Family& family) : mImmutable(false) , txMap_(SHAMapType::TRANSACTION, family) , stateMap_(SHAMapType::STATE, family) @@ -338,10 +315,7 @@ Ledger::setImmutable(bool rehash) } void -Ledger::setAccepted( - NetClock::time_point closeTime, - NetClock::duration closeResolution, - bool correctCloseTime) +Ledger::setAccepted(NetClock::time_point closeTime, NetClock::duration closeResolution, bool correctCloseTime) { // Used when we witnessed the consensus. XRPL_ASSERT(!open(), "xrpl::Ledger::setAccepted : valid ledger state"); @@ -356,8 +330,7 @@ bool Ledger::addSLE(SLE const& sle) { auto const s = sle.getSerializer(); - return stateMap_.addItem( - SHAMapNodeType::tnACCOUNT_STATE, make_shamapitem(sle.key(), s.slice())); + return stateMap_.addItem(SHAMapNodeType::tnACCOUNT_STATE, make_shamapitem(sle.key(), s.slice())); } //------------------------------------------------------------------------------ @@ -372,8 +345,7 @@ deserializeTx(SHAMapItem const& item) std::pair, std::shared_ptr> deserializeTxPlusMeta(SHAMapItem const& item) { - std::pair, std::shared_ptr> - result; + std::pair, std::shared_ptr> result; SerialIter sit(item.slice()); { SerialIter s(sit.getSlice(sit.getVLDataLength())); @@ -446,8 +418,7 @@ Ledger::slesEnd() const -> std::unique_ptr } auto -Ledger::slesUpperBound(uint256 const& key) const - -> std::unique_ptr +Ledger::slesUpperBound(uint256 const& key) const -> std::unique_ptr { return std::make_unique(stateMap_.upper_bound(key)); } @@ -516,9 +487,7 @@ Ledger::rawInsert(std::shared_ptr const& sle) { Serializer ss; sle->add(ss); - if (!stateMap_.addGiveItem( - SHAMapNodeType::tnACCOUNT_STATE, - make_shamapitem(sle->key(), ss.slice()))) + if (!stateMap_.addGiveItem(SHAMapNodeType::tnACCOUNT_STATE, make_shamapitem(sle->key(), ss.slice()))) LogicError("Ledger::rawInsert: key already exists"); } @@ -527,9 +496,7 @@ Ledger::rawReplace(std::shared_ptr const& sle) { Serializer ss; sle->add(ss); - if (!stateMap_.updateGiveItem( - SHAMapNodeType::tnACCOUNT_STATE, - make_shamapitem(sle->key(), ss.slice()))) + if (!stateMap_.updateGiveItem(SHAMapNodeType::tnACCOUNT_STATE, make_shamapitem(sle->key(), ss.slice()))) LogicError("Ledger::rawReplace: key not found"); } @@ -539,15 +506,13 @@ Ledger::rawTxInsert( std::shared_ptr const& txn, std::shared_ptr const& metaData) { - XRPL_ASSERT( - metaData, "xrpl::Ledger::rawTxInsert : non-null metadata input"); + XRPL_ASSERT(metaData, "xrpl::Ledger::rawTxInsert : non-null metadata input"); // low-level - just add to table Serializer s(txn->getDataLength() + metaData->getDataLength() + 16); s.addVL(txn->peekData()); s.addVL(metaData->peekData()); - if (!txMap_.addGiveItem( - SHAMapNodeType::tnTRANSACTION_MD, make_shamapitem(key, s.slice()))) + if (!txMap_.addGiveItem(SHAMapNodeType::tnTRANSACTION_MD, make_shamapitem(key, s.slice()))) LogicError("duplicate_tx: " + to_string(key)); } @@ -557,9 +522,7 @@ Ledger::rawTxInsertWithHash( std::shared_ptr const& txn, std::shared_ptr const& metaData) { - XRPL_ASSERT( - metaData, - "xrpl::Ledger::rawTxInsertWithHash : non-null metadata input"); + XRPL_ASSERT(metaData, "xrpl::Ledger::rawTxInsertWithHash : non-null metadata input"); // low-level - just add to table Serializer s(txn->getDataLength() + metaData->getDataLength() + 16); @@ -613,11 +576,8 @@ Ledger::setup() { auto const baseFeeXRP = sle->at(~sfBaseFeeDrops); auto const reserveBaseXRP = sle->at(~sfReserveBaseDrops); - auto const reserveIncrementXRP = - sle->at(~sfReserveIncrementDrops); - auto assign = [&ret]( - XRPAmount& dest, - std::optional const& src) { + auto const reserveIncrementXRP = sle->at(~sfReserveIncrementDrops); + auto assign = [&ret](XRPAmount& dest, std::optional const& src) { if (src) { if (src->native()) @@ -655,9 +615,7 @@ Ledger::setup() void Ledger::defaultFees(Config const& config) { - XRPL_ASSERT( - fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0, - "xrpl::Ledger::defaultFees : zero fees"); + XRPL_ASSERT(fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0, "xrpl::Ledger::defaultFees : zero fees"); if (fees_.base == 0) fees_.base = config.FEES.reference_fee; if (fees_.reserve == 0) @@ -682,8 +640,7 @@ hash_set Ledger::negativeUNL() const { hash_set negUnl; - if (auto sle = read(keylet::negativeUNL()); - sle && sle->isFieldPresent(sfDisabledValidators)) + if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfDisabledValidators)) { auto const& nUnlData = sle->getFieldArray(sfDisabledValidators); for (auto const& n : nUnlData) @@ -707,8 +664,7 @@ Ledger::negativeUNL() const std::optional Ledger::validatorToDisable() const { - if (auto sle = read(keylet::negativeUNL()); - sle && sle->isFieldPresent(sfValidatorToDisable)) + if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfValidatorToDisable)) { auto d = sle->getFieldVL(sfValidatorToDisable); auto s = makeSlice(d); @@ -722,8 +678,7 @@ Ledger::validatorToDisable() const std::optional Ledger::validatorToReEnable() const { - if (auto sle = read(keylet::negativeUNL()); - sle && sle->isFieldPresent(sfValidatorToReEnable)) + if (auto sle = read(keylet::negativeUNL()); sle && sle->isFieldPresent(sfValidatorToReEnable)) { auto d = sle->getFieldVL(sfValidatorToReEnable); auto s = makeSlice(d); @@ -754,8 +709,7 @@ Ledger::updateNegativeUNL() for (auto v : oldNUnl) { if (hasToReEnable && v.isFieldPresent(sfPublicKey) && - v.getFieldVL(sfPublicKey) == - sle->getFieldVL(sfValidatorToReEnable)) + v.getFieldVL(sfPublicKey) == sle->getFieldVL(sfValidatorToReEnable)) continue; newNUnl.push_back(v); } @@ -764,8 +718,7 @@ Ledger::updateNegativeUNL() if (hasToDisable) { newNUnl.push_back(STObject::makeInnerObject(sfDisabledValidator)); - newNUnl.back().setFieldVL( - sfPublicKey, sle->getFieldVL(sfValidatorToDisable)); + newNUnl.back().setFieldVL(sfPublicKey, sle->getFieldVL(sfValidatorToDisable)); newNUnl.back().setFieldU32(sfFirstLedgerSequence, seq()); } @@ -794,8 +747,7 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const if (stateMap_.getHash().isZero() && !header_.accountHash.isZero() && !stateMap_.fetchRoot(SHAMapHash{header_.accountHash}, nullptr)) { - missingNodes1.emplace_back( - SHAMapType::STATE, SHAMapHash{header_.accountHash}); + missingNodes1.emplace_back(SHAMapType::STATE, SHAMapHash{header_.accountHash}); } else { @@ -817,8 +769,7 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const if (txMap_.getHash().isZero() && header_.txHash.isNonZero() && !txMap_.fetchRoot(SHAMapHash{header_.txHash}, nullptr)) { - missingNodes2.emplace_back( - SHAMapType::TRANSACTION, SHAMapHash{header_.txHash}); + missingNodes2.emplace_back(SHAMapType::TRANSACTION, SHAMapHash{header_.txHash}); } else { @@ -840,8 +791,7 @@ bool Ledger::assertSensible(beast::Journal ledgerJ) const { if (header_.hash.isNonZero() && header_.accountHash.isNonZero() && - (header_.accountHash == stateMap_.getHash().as_uint256()) && - (header_.txHash == txMap_.getHash().as_uint256())) + (header_.accountHash == stateMap_.getHash().as_uint256()) && (header_.txHash == txMap_.getHash().as_uint256())) { return true; } @@ -889,9 +839,7 @@ Ledger::updateSkipList() created = false; } - XRPL_ASSERT( - hashes.size() <= 256, - "xrpl::Ledger::updateSkipList : first maximum hashes size"); + XRPL_ASSERT(hashes.size() <= 256, "xrpl::Ledger::updateSkipList : first maximum hashes size"); hashes.push_back(header_.parentHash); sle->setFieldV256(sfHashes, STVector256(hashes)); sle->setFieldU32(sfLastLedgerSequence, prevIndex); @@ -916,9 +864,7 @@ Ledger::updateSkipList() hashes = static_cast(sle->getFieldV256(sfHashes)); created = false; } - XRPL_ASSERT( - hashes.size() <= 256, - "xrpl::Ledger::updateSkipList : second maximum hashes size"); + XRPL_ASSERT(hashes.size() <= 256, "xrpl::Ledger::updateSkipList : second maximum hashes size"); if (hashes.size() == 256) hashes.erase(hashes.begin()); hashes.push_back(header_.parentHash); @@ -948,10 +894,7 @@ isFlagLedger(LedgerIndex seq) } static bool -saveValidatedLedger( - Application& app, - std::shared_ptr const& ledger, - bool current) +saveValidatedLedger(Application& app, std::shared_ptr const& ledger, bool current) { auto j = app.journal("Ledger"); auto seq = ledger->header().seq; @@ -978,14 +921,9 @@ saveValidatedLedger( Returns false on error */ bool -pendSaveValidated( - Application& app, - std::shared_ptr const& ledger, - bool isSynchronous, - bool isCurrent) +pendSaveValidated(Application& app, std::shared_ptr const& ledger, bool isSynchronous, bool isCurrent) { - if (!app.getHashRouter().setFlags( - ledger->header().hash, HashRouterFlags::SAVED)) + if (!app.getHashRouter().setFlags(ledger->header().hash, HashRouterFlags::SAVED)) { // We have tried to save this ledger recently auto stream = app.journal("Ledger").debug(); @@ -999,14 +937,12 @@ pendSaveValidated( } } - XRPL_ASSERT( - ledger->isImmutable(), "xrpl::pendSaveValidated : immutable ledger"); + XRPL_ASSERT(ledger->isImmutable(), "xrpl::pendSaveValidated : immutable ledger"); if (!app.pendingSaves().shouldWork(ledger->header().seq, isSynchronous)) { auto stream = app.journal("Ledger").debug(); - JLOG(stream) << "Pend save with seq in pending saves " - << ledger->header().seq; + JLOG(stream) << "Pend save with seq in pending saves " << ledger->header().seq; return true; } @@ -1014,9 +950,7 @@ pendSaveValidated( // See if we can use the JobQueue. if (!isSynchronous && app.getJobQueue().addJob( - isCurrent ? jtPUBLEDGER : jtPUBOLDLEDGER, - std::to_string(ledger->seq()), - [&app, ledger, isCurrent]() { + isCurrent ? jtPUBLEDGER : jtPUBOLDLEDGER, std::to_string(ledger->seq()), [&app, ledger, isCurrent]() { saveValidatedLedger(app, ledger, isCurrent); })) { @@ -1054,13 +988,8 @@ std::shared_ptr loadLedgerHelper(LedgerHeader const& info, Application& app, bool acquire) { bool loaded; - auto ledger = std::make_shared( - info, - loaded, - acquire, - app.config(), - app.getNodeFamily(), - app.journal("Ledger")); + auto ledger = + std::make_shared(info, loaded, acquire, app.config(), app.getNodeFamily(), app.journal("Ledger")); if (!loaded) ledger.reset(); @@ -1069,17 +998,13 @@ loadLedgerHelper(LedgerHeader const& info, Application& app, bool acquire) } static void -finishLoadByIndexOrHash( - std::shared_ptr const& ledger, - Config const& config, - beast::Journal j) +finishLoadByIndexOrHash(std::shared_ptr const& ledger, Config const& config, beast::Journal j) { if (!ledger) return; XRPL_ASSERT( - ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || - ledger->read(keylet::fees()), + ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()), "xrpl::finishLoadByIndexOrHash : valid ledger fees"); ledger->setImmutable(); @@ -1091,8 +1016,7 @@ finishLoadByIndexOrHash( std::tuple, std::uint32_t, uint256> getLatestLedger(Application& app) { - std::optional const info = - app.getRelationalDatabase().getNewestLedgerInfo(); + std::optional const info = app.getRelationalDatabase().getNewestLedgerInfo(); if (!info) return {std::shared_ptr(), {}, {}}; return {loadLedgerHelper(*info, app, true), info->seq, info->hash}; @@ -1101,8 +1025,7 @@ getLatestLedger(Application& app) std::shared_ptr loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire) { - if (std::optional info = - app.getRelationalDatabase().getLedgerInfoByIndex(ledgerIndex)) + if (std::optional info = app.getRelationalDatabase().getLedgerInfoByIndex(ledgerIndex)) { std::shared_ptr ledger = loadLedgerHelper(*info, app, acquire); finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger")); @@ -1114,14 +1037,11 @@ loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire) std::shared_ptr loadByHash(uint256 const& ledgerHash, Application& app, bool acquire) { - if (std::optional info = - app.getRelationalDatabase().getLedgerInfoByHash(ledgerHash)) + if (std::optional info = app.getRelationalDatabase().getLedgerInfoByHash(ledgerHash)) { std::shared_ptr ledger = loadLedgerHelper(*info, app, acquire); finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger")); - XRPL_ASSERT( - !ledger || ledger->header().hash == ledgerHash, - "xrpl::loadByHash : ledger hash match if loaded"); + XRPL_ASSERT(!ledger || ledger->header().hash == ledgerHash, "xrpl::loadByHash : ledger hash match if loaded"); return ledger; } return {}; diff --git a/src/xrpld/app/ledger/Ledger.h b/src/xrpld/app/ledger/Ledger.h index a17281f2c7..a8c9b91342 100644 --- a/src/xrpld/app/ledger/Ledger.h +++ b/src/xrpld/app/ledger/Ledger.h @@ -82,11 +82,7 @@ public: Amendments specified are enabled in the genesis ledger */ - Ledger( - create_genesis_t, - Config const& config, - std::vector const& amendments, - Family& family); + Ledger(create_genesis_t, Config const& config, std::vector const& amendments, Family& family); Ledger(LedgerHeader const& info, Config const& config, Family& family); @@ -111,11 +107,7 @@ public: Ledger(Ledger const& previous, NetClock::time_point closeTime); // used for database ledgers - Ledger( - std::uint32_t ledgerSeq, - NetClock::time_point closeTime, - Config const& config, - Family& family); + Ledger(std::uint32_t ledgerSeq, NetClock::time_point closeTime, Config const& config, Family& family); ~Ledger() = default; @@ -160,8 +152,7 @@ public: exists(uint256 const& key) const; std::optional - succ(uint256 const& key, std::optional const& last = std::nullopt) - const override; + succ(uint256 const& key, std::optional const& last = std::nullopt) const override; std::shared_ptr read(Keylet const& k) const override; @@ -248,10 +239,7 @@ public: } void - setAccepted( - NetClock::time_point closeTime, - NetClock::duration closeResolution, - bool correctCloseTime); + setAccepted(NetClock::time_point closeTime, NetClock::duration closeResolution, bool correctCloseTime); void setImmutable(bool rehash = true); @@ -416,11 +404,7 @@ isFlagLedger(LedgerIndex seq); //------------------------------------------------------------------------------ extern bool -pendSaveValidated( - Application& app, - std::shared_ptr const& ledger, - bool isSynchronous, - bool isCurrent); +pendSaveValidated(Application& app, std::shared_ptr const& ledger, bool isSynchronous, bool isCurrent); std::shared_ptr loadLedgerHelper(LedgerHeader const& sinfo, Application& app, bool acquire); diff --git a/src/xrpld/app/ledger/LedgerHistory.cpp b/src/xrpld/app/ledger/LedgerHistory.cpp index 2654e25d7b..50fe56fd90 100644 --- a/src/xrpld/app/ledger/LedgerHistory.cpp +++ b/src/xrpld/app/ledger/LedgerHistory.cpp @@ -10,9 +10,7 @@ namespace xrpl { // FIXME: Need to clean up ledgers by index at some point -LedgerHistory::LedgerHistory( - beast::insight::Collector::ptr const& collector, - Application& app) +LedgerHistory::LedgerHistory(beast::insight::Collector::ptr const& collector, Application& app) : app_(app) , collector_(collector) , mismatch_counter_(collector->make_counter("ledger.history", "mismatch")) @@ -22,32 +20,22 @@ LedgerHistory::LedgerHistory( std::chrono::seconds{app_.config().getValueFor(SizedItem::ledgerAge)}, stopwatch(), app_.journal("TaggedCache")) - , m_consensus_validated( - "ConsensusValidated", - 64, - std::chrono::minutes{5}, - stopwatch(), - app_.journal("TaggedCache")) + , m_consensus_validated("ConsensusValidated", 64, std::chrono::minutes{5}, stopwatch(), app_.journal("TaggedCache")) , j_(app.journal("LedgerHistory")) { } bool -LedgerHistory::insert( - std::shared_ptr const& ledger, - bool validated) +LedgerHistory::insert(std::shared_ptr const& ledger, bool validated) { if (!ledger->isImmutable()) LogicError("mutable Ledger in insert"); - XRPL_ASSERT( - ledger->stateMap().getHash().isNonZero(), - "xrpl::LedgerHistory::insert : nonzero hash"); + XRPL_ASSERT(ledger->stateMap().getHash().isNonZero(), "xrpl::LedgerHistory::insert : nonzero hash"); std::unique_lock sl(m_ledgers_by_hash.peekMutex()); - bool const alreadyHad = m_ledgers_by_hash.canonicalize_replace_cache( - ledger->header().hash, ledger); + bool const alreadyHad = m_ledgers_by_hash.canonicalize_replace_cache(ledger->header().hash, ledger); if (validated) mLedgersByIndex[ledger->header().seq] = ledger->header().hash; @@ -83,17 +71,13 @@ LedgerHistory::getLedgerBySeq(LedgerIndex index) if (!ret) return ret; - XRPL_ASSERT( - ret->header().seq == index, - "xrpl::LedgerHistory::getLedgerBySeq : result sequence match"); + XRPL_ASSERT(ret->header().seq == index, "xrpl::LedgerHistory::getLedgerBySeq : result sequence match"); { // Add this ledger to the local tracking by index std::unique_lock sl(m_ledgers_by_hash.peekMutex()); - XRPL_ASSERT( - ret->isImmutable(), - "xrpl::LedgerHistory::getLedgerBySeq : immutable result ledger"); + XRPL_ASSERT(ret->isImmutable(), "xrpl::LedgerHistory::getLedgerBySeq : immutable result ledger"); m_ledgers_by_hash.canonicalize_replace_client(ret->header().hash, ret); mLedgersByIndex[ret->header().seq] = ret->header().hash; return (ret->header().seq == index) ? ret : nullptr; @@ -123,48 +107,32 @@ LedgerHistory::getLedgerByHash(LedgerHash const& hash) if (!ret) return ret; - XRPL_ASSERT( - ret->isImmutable(), - "xrpl::LedgerHistory::getLedgerByHash : immutable loaded ledger"); - XRPL_ASSERT( - ret->header().hash == hash, - "xrpl::LedgerHistory::getLedgerByHash : loaded ledger hash match"); + XRPL_ASSERT(ret->isImmutable(), "xrpl::LedgerHistory::getLedgerByHash : immutable loaded ledger"); + XRPL_ASSERT(ret->header().hash == hash, "xrpl::LedgerHistory::getLedgerByHash : loaded ledger hash match"); m_ledgers_by_hash.canonicalize_replace_client(ret->header().hash, ret); - XRPL_ASSERT( - ret->header().hash == hash, - "xrpl::LedgerHistory::getLedgerByHash : result hash match"); + XRPL_ASSERT(ret->header().hash == hash, "xrpl::LedgerHistory::getLedgerByHash : result hash match"); return ret; } static void -log_one( - ReadView const& ledger, - uint256 const& tx, - char const* msg, - beast::Journal& j) +log_one(ReadView const& ledger, uint256 const& tx, char const* msg, beast::Journal& j) { auto metaData = ledger.txRead(tx).second; if (metaData != nullptr) { - JLOG(j.debug()) << "MISMATCH on TX " << tx << ": " << msg - << " is missing this transaction:\n" + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": " << msg << " is missing this transaction:\n" << metaData->getJson(JsonOptions::none); } else { - JLOG(j.debug()) << "MISMATCH on TX " << tx << ": " << msg - << " is missing this transaction."; + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": " << msg << " is missing this transaction."; } } static void -log_metadata_difference( - ReadView const& builtLedger, - ReadView const& validLedger, - uint256 const& tx, - beast::Journal j) +log_metadata_difference(ReadView const& builtLedger, ReadView const& validLedger, uint256 const& tx, beast::Journal j) { auto getMeta = [](ReadView const& ledger, uint256 const& txID) { std::optional ret; @@ -176,27 +144,22 @@ log_metadata_difference( auto validMetaData = getMeta(validLedger, tx); auto builtMetaData = getMeta(builtLedger, tx); - XRPL_ASSERT( - validMetaData || builtMetaData, - "xrpl::log_metadata_difference : some metadata present"); + XRPL_ASSERT(validMetaData || builtMetaData, "xrpl::log_metadata_difference : some metadata present"); if (validMetaData && builtMetaData) { auto const& validNodes = validMetaData->getNodes(); auto const& builtNodes = builtMetaData->getNodes(); - bool const result_diff = - validMetaData->getResultTER() != builtMetaData->getResultTER(); + bool const result_diff = validMetaData->getResultTER() != builtMetaData->getResultTER(); - bool const index_diff = - validMetaData->getIndex() != builtMetaData->getIndex(); + bool const index_diff = validMetaData->getIndex() != builtMetaData->getIndex(); bool const nodes_diff = validNodes != builtNodes; if (!result_diff && !index_diff && !nodes_diff) { - JLOG(j.error()) << "MISMATCH on TX " << tx - << ": No apparent mismatches detected!"; + JLOG(j.error()) << "MISMATCH on TX " << tx << ": No apparent mismatches detected!"; return; } @@ -204,19 +167,15 @@ log_metadata_difference( { if (result_diff && index_diff) { - JLOG(j.debug()) << "MISMATCH on TX " << tx - << ": Different result and index!"; + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": Different result and index!"; JLOG(j.debug()) << " Built:" - << " Result: " << builtMetaData->getResult() - << " Index: " << builtMetaData->getIndex(); + << " Result: " << builtMetaData->getResult() << " Index: " << builtMetaData->getIndex(); JLOG(j.debug()) << " Valid:" - << " Result: " << validMetaData->getResult() - << " Index: " << validMetaData->getIndex(); + << " Result: " << validMetaData->getResult() << " Index: " << validMetaData->getIndex(); } else if (result_diff) { - JLOG(j.debug()) - << "MISMATCH on TX " << tx << ": Different result!"; + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": Different result!"; JLOG(j.debug()) << " Built:" << " Result: " << builtMetaData->getResult(); JLOG(j.debug()) << " Valid:" @@ -224,8 +183,7 @@ log_metadata_difference( } else if (index_diff) { - JLOG(j.debug()) - << "MISMATCH on TX " << tx << ": Different index!"; + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": Different index!"; JLOG(j.debug()) << " Built:" << " Index: " << builtMetaData->getIndex(); JLOG(j.debug()) << " Valid:" @@ -236,43 +194,33 @@ log_metadata_difference( { if (result_diff && index_diff) { - JLOG(j.debug()) << "MISMATCH on TX " << tx - << ": Different result, index and nodes!"; - JLOG(j.debug()) << " Built:\n" - << builtMetaData->getJson(JsonOptions::none); - JLOG(j.debug()) << " Valid:\n" - << validMetaData->getJson(JsonOptions::none); + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": Different result, index and nodes!"; + JLOG(j.debug()) << " Built:\n" << builtMetaData->getJson(JsonOptions::none); + JLOG(j.debug()) << " Valid:\n" << validMetaData->getJson(JsonOptions::none); } else if (result_diff) { - JLOG(j.debug()) << "MISMATCH on TX " << tx - << ": Different result and nodes!"; - JLOG(j.debug()) - << " Built:" - << " Result: " << builtMetaData->getResult() << " Nodes:\n" - << builtNodes.getJson(JsonOptions::none); - JLOG(j.debug()) - << " Valid:" - << " Result: " << validMetaData->getResult() << " Nodes:\n" - << validNodes.getJson(JsonOptions::none); + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": Different result and nodes!"; + JLOG(j.debug()) << " Built:" + << " Result: " << builtMetaData->getResult() << " Nodes:\n" + << builtNodes.getJson(JsonOptions::none); + JLOG(j.debug()) << " Valid:" + << " Result: " << validMetaData->getResult() << " Nodes:\n" + << validNodes.getJson(JsonOptions::none); } else if (index_diff) { - JLOG(j.debug()) << "MISMATCH on TX " << tx - << ": Different index and nodes!"; - JLOG(j.debug()) - << " Built:" - << " Index: " << builtMetaData->getIndex() << " Nodes:\n" - << builtNodes.getJson(JsonOptions::none); - JLOG(j.debug()) - << " Valid:" - << " Index: " << validMetaData->getIndex() << " Nodes:\n" - << validNodes.getJson(JsonOptions::none); + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": Different index and nodes!"; + JLOG(j.debug()) << " Built:" + << " Index: " << builtMetaData->getIndex() << " Nodes:\n" + << builtNodes.getJson(JsonOptions::none); + JLOG(j.debug()) << " Valid:" + << " Index: " << validMetaData->getIndex() << " Nodes:\n" + << validNodes.getJson(JsonOptions::none); } else // nodes_diff { - JLOG(j.debug()) - << "MISMATCH on TX " << tx << ": Different nodes!"; + JLOG(j.debug()) << "MISMATCH on TX " << tx << ": Different nodes!"; JLOG(j.debug()) << " Built:" << " Nodes:\n" << builtNodes.getJson(JsonOptions::none); @@ -287,15 +235,13 @@ log_metadata_difference( if (validMetaData) { - JLOG(j.error()) << "MISMATCH on TX " << tx - << ": Metadata Difference. Valid=\n" + JLOG(j.error()) << "MISMATCH on TX " << tx << ": Metadata Difference. Valid=\n" << validMetaData->getJson(JsonOptions::none); } if (builtMetaData) { - JLOG(j.error()) << "MISMATCH on TX " << tx - << ": Metadata Difference. Built=\n" + JLOG(j.error()) << "MISMATCH on TX " << tx << ": Metadata Difference. Built=\n" << builtMetaData->getJson(JsonOptions::none); } } @@ -309,10 +255,7 @@ leaves(SHAMap const& sm) std::vector v; for (auto const& item : sm) v.push_back(&item); - std::sort( - v.begin(), v.end(), [](SHAMapItem const* lhs, SHAMapItem const* rhs) { - return lhs->key() < rhs->key(); - }); + std::sort(v.begin(), v.end(), [](SHAMapItem const* lhs, SHAMapItem const* rhs) { return lhs->key() < rhs->key(); }); return v; } @@ -324,8 +267,7 @@ LedgerHistory::handleMismatch( std::optional const& validatedConsensusHash, Json::Value const& consensus) { - XRPL_ASSERT( - built != valid, "xrpl::LedgerHistory::handleMismatch : unequal hashes"); + XRPL_ASSERT(built != valid, "xrpl::LedgerHistory::handleMismatch : unequal hashes"); ++mismatch_counter_; auto builtLedger = getLedgerByHash(built); @@ -334,15 +276,13 @@ LedgerHistory::handleMismatch( if (!builtLedger || !validLedger) { JLOG(j_.error()) << "MISMATCH cannot be analyzed:" - << " builtLedger: " << to_string(built) << " -> " - << builtLedger << " validLedger: " << to_string(valid) - << " -> " << validLedger; + << " builtLedger: " << to_string(built) << " -> " << builtLedger + << " validLedger: " << to_string(valid) << " -> " << validLedger; return; } XRPL_ASSERT( - builtLedger->header().seq == validLedger->header().seq, - "xrpl::LedgerHistory::handleMismatch : sequence match"); + builtLedger->header().seq == validLedger->header().seq, "xrpl::LedgerHistory::handleMismatch : sequence match"); if (auto stream = j_.debug()) { @@ -371,13 +311,11 @@ LedgerHistory::handleMismatch( if (builtConsensusHash && validatedConsensusHash) { if (builtConsensusHash != validatedConsensusHash) - JLOG(j_.error()) - << "MISMATCH on consensus transaction set " - << " built: " << to_string(*builtConsensusHash) - << " validated: " << to_string(*validatedConsensusHash); + JLOG(j_.error()) << "MISMATCH on consensus transaction set " + << " built: " << to_string(*builtConsensusHash) + << " validated: " << to_string(*validatedConsensusHash); else - JLOG(j_.error()) << "MISMATCH with same consensus transaction set: " - << to_string(*builtConsensusHash); + JLOG(j_.error()) << "MISMATCH with same consensus transaction set: " << to_string(*builtConsensusHash); } // Find differences between built and valid ledgers @@ -385,11 +323,10 @@ LedgerHistory::handleMismatch( auto const validTx = leaves(validLedger->txMap()); if (builtTx == validTx) - JLOG(j_.error()) << "MISMATCH with same " << builtTx.size() - << " transactions"; + JLOG(j_.error()) << "MISMATCH with same " << builtTx.size() << " transactions"; else - JLOG(j_.error()) << "MISMATCH with " << builtTx.size() << " built and " - << validTx.size() << " valid transactions."; + JLOG(j_.error()) << "MISMATCH with " << builtTx.size() << " built and " << validTx.size() + << " valid transactions."; JLOG(j_.error()) << "built\n" << getJson({*builtLedger, {}}); JLOG(j_.error()) << "valid\n" << getJson({*validLedger, {}}); @@ -414,8 +351,7 @@ LedgerHistory::handleMismatch( if ((*b)->slice() != (*v)->slice()) { // Same transaction with different metadata - log_metadata_difference( - *builtLedger, *validLedger, (*b)->key(), j_); + log_metadata_difference(*builtLedger, *validLedger, (*b)->key(), j_); } ++b; ++v; @@ -435,8 +371,7 @@ LedgerHistory::builtLedger( { LedgerIndex index = ledger->header().seq; LedgerHash hash = ledger->header().hash; - XRPL_ASSERT( - !hash.isZero(), "xrpl::LedgerHistory::builtLedger : nonzero hash"); + XRPL_ASSERT(!hash.isZero(), "xrpl::LedgerHistory::builtLedger : nonzero hash"); std::unique_lock sl(m_consensus_validated.peekMutex()); @@ -447,15 +382,9 @@ LedgerHistory::builtLedger( { if (entry->validated.value() != hash) { - JLOG(j_.error()) << "MISMATCH: seq=" << index - << " validated:" << entry->validated.value() + JLOG(j_.error()) << "MISMATCH: seq=" << index << " validated:" << entry->validated.value() << " then:" << hash; - handleMismatch( - hash, - entry->validated.value(), - consensusHash, - entry->validatedConsensusHash, - consensus); + handleMismatch(hash, entry->validated.value(), consensusHash, entry->validatedConsensusHash, consensus); } else { @@ -470,14 +399,11 @@ LedgerHistory::builtLedger( } void -LedgerHistory::validatedLedger( - std::shared_ptr const& ledger, - std::optional const& consensusHash) +LedgerHistory::validatedLedger(std::shared_ptr const& ledger, std::optional const& consensusHash) { LedgerIndex index = ledger->header().seq; LedgerHash hash = ledger->header().hash; - XRPL_ASSERT( - !hash.isZero(), "xrpl::LedgerHistory::validatedLedger : nonzero hash"); + XRPL_ASSERT(!hash.isZero(), "xrpl::LedgerHistory::validatedLedger : nonzero hash"); std::unique_lock sl(m_consensus_validated.peekMutex()); @@ -488,15 +414,9 @@ LedgerHistory::validatedLedger( { if (entry->built.value() != hash) { - JLOG(j_.error()) - << "MISMATCH: seq=" << index - << " built:" << entry->built.value() << " then:" << hash; + JLOG(j_.error()) << "MISMATCH: seq=" << index << " built:" << entry->built.value() << " then:" << hash; handleMismatch( - entry->built.value(), - hash, - entry->builtConsensusHash, - consensusHash, - entry->consensus.value()); + entry->built.value(), hash, entry->builtConsensusHash, consensusHash, entry->consensus.value()); } else { diff --git a/src/xrpld/app/ledger/LedgerHistory.h b/src/xrpld/app/ledger/LedgerHistory.h index 279d009429..68007546b6 100644 --- a/src/xrpld/app/ledger/LedgerHistory.h +++ b/src/xrpld/app/ledger/LedgerHistory.h @@ -17,9 +17,7 @@ namespace xrpl { class LedgerHistory { public: - LedgerHistory( - beast::insight::Collector::ptr const& collector, - Application& app); + LedgerHistory(beast::insight::Collector::ptr const& collector, Application& app); /** Track a ledger @return `true` if the ledger was already tracked @@ -62,16 +60,11 @@ public: /** Report that we have locally built a particular ledger */ void - builtLedger( - std::shared_ptr const&, - uint256 const& consensusHash, - Json::Value); + builtLedger(std::shared_ptr const&, uint256 const& consensusHash, Json::Value); /** Report that we have validated a particular ledger */ void - validatedLedger( - std::shared_ptr const&, - std::optional const& consensusHash); + validatedLedger(std::shared_ptr const&, std::optional const& consensusHash); /** Repair a hash to index mapping @param ledgerIndex The index whose mapping is to be repaired diff --git a/src/xrpld/app/ledger/LedgerMaster.h b/src/xrpld/app/ledger/LedgerMaster.h index 38dff835b7..5db8806534 100644 --- a/src/xrpld/app/ledger/LedgerMaster.h +++ b/src/xrpld/app/ledger/LedgerMaster.h @@ -89,10 +89,7 @@ public: storeLedger(std::shared_ptr ledger); void - setFullLedger( - std::shared_ptr const& ledger, - bool isSynchronous, - bool isCurrent); + setFullLedger(std::shared_ptr const& ledger, bool isSynchronous, bool isCurrent); /** Check the sequence number and parent close time of a ledger against our clock and last validated ledger to @@ -189,10 +186,7 @@ public: void checkAccept(uint256 const& hash, std::uint32_t seq); void - consensusBuilt( - std::shared_ptr const& ledger, - uint256 const& consensusHash, - Json::Value consensus); + consensusBuilt(std::shared_ptr const& ledger, uint256 const& consensusHash, Json::Value consensus); void setBuildingLedger(LedgerIndex index); @@ -338,8 +332,7 @@ private: int mPathFindThread{0}; // Pathfinder jobs dispatched bool mPathFindNewRequest{false}; - std::atomic_flag mGotFetchPackThread = - ATOMIC_FLAG_INIT; // GotFetchPack jobs dispatched + std::atomic_flag mGotFetchPackThread = ATOMIC_FLAG_INIT; // GotFetchPack jobs dispatched std::atomic mPubLedgerClose{0}; std::atomic mPubLedgerSeq{0}; @@ -373,14 +366,10 @@ private: struct Stats { template - Stats( - Handler const& handler, - beast::insight::Collector::ptr const& collector) + Stats(Handler const& handler, beast::insight::Collector::ptr const& collector) : hook(collector->make_hook(handler)) - , validatedLedgerAge( - collector->make_gauge("LedgerMaster", "Validated_Ledger_Age")) - , publishedLedgerAge( - collector->make_gauge("LedgerMaster", "Published_Ledger_Age")) + , validatedLedgerAge(collector->make_gauge("LedgerMaster", "Validated_Ledger_Age")) + , publishedLedgerAge(collector->make_gauge("LedgerMaster", "Published_Ledger_Age")) { } diff --git a/src/xrpld/app/ledger/LedgerReplay.h b/src/xrpld/app/ledger/LedgerReplay.h index 29e8a835fe..9051bb414c 100644 --- a/src/xrpld/app/ledger/LedgerReplay.h +++ b/src/xrpld/app/ledger/LedgerReplay.h @@ -18,9 +18,7 @@ class LedgerReplay : public CountedObject std::map> orderedTxns_; public: - LedgerReplay( - std::shared_ptr parent, - std::shared_ptr replay); + LedgerReplay(std::shared_ptr parent, std::shared_ptr replay); LedgerReplay( std::shared_ptr parent, diff --git a/src/xrpld/app/ledger/LedgerReplayTask.h b/src/xrpld/app/ledger/LedgerReplayTask.h index 623a193d93..40995430db 100644 --- a/src/xrpld/app/ledger/LedgerReplayTask.h +++ b/src/xrpld/app/ledger/LedgerReplayTask.h @@ -17,10 +17,9 @@ namespace test { class LedgerReplayClient; } // namespace test -class LedgerReplayTask final - : public TimeoutCounter, - public std::enable_shared_from_this, - public CountedObject +class LedgerReplayTask final : public TimeoutCounter, + public std::enable_shared_from_this, + public CountedObject { public: class TaskParameter @@ -44,10 +43,7 @@ public: * @param finishLedgerHash hash of the last ledger in the range * @param totalNumLedgers number of ledgers to download */ - TaskParameter( - InboundLedger::Reason r, - uint256 const& finishLedgerHash, - std::uint32_t totalNumLedgers); + TaskParameter(InboundLedger::Reason r, uint256 const& finishLedgerHash, std::uint32_t totalNumLedgers); /** * fill all the fields that was not filled during construction @@ -59,10 +55,7 @@ public: * true on success */ bool - update( - uint256 const& hash, - std::uint32_t seq, - std::vector const& sList); + update(uint256 const& hash, std::uint32_t seq, std::vector const& sList); /** check if this task can be merged into an existing task */ bool @@ -123,10 +116,7 @@ private: * @param sList skip list */ void - updateSkipList( - uint256 const& hash, - std::uint32_t seq, - std::vector const& sList); + updateSkipList(uint256 const& hash, std::uint32_t seq, std::vector const& sList); /** * Notify this task (by a LedgerDeltaAcquire subtask) that a delta is ready diff --git a/src/xrpld/app/ledger/LedgerReplayer.h b/src/xrpld/app/ledger/LedgerReplayer.h index b0e0692019..ff67a43e87 100644 --- a/src/xrpld/app/ledger/LedgerReplayer.h +++ b/src/xrpld/app/ledger/LedgerReplayer.h @@ -53,10 +53,7 @@ std::uint32_t constexpr MAX_QUEUED_TASKS = 100; class LedgerReplayer final { public: - LedgerReplayer( - Application& app, - InboundLedgers& inboundLedgers, - std::unique_ptr peerSetBuilder); + LedgerReplayer(Application& app, InboundLedgers& inboundLedgers, std::unique_ptr peerSetBuilder); ~LedgerReplayer(); @@ -68,10 +65,7 @@ public: * @note totalNumLedgers must > 0 && totalNumLedgers must <= 256 */ void - replay( - InboundLedger::Reason r, - uint256 const& finishLedgerHash, - std::uint32_t totalNumLedgers); + replay(InboundLedger::Reason r, uint256 const& finishLedgerHash, std::uint32_t totalNumLedgers); /** Create LedgerDeltaAcquire subtasks for the LedgerReplayTask task */ void @@ -84,9 +78,7 @@ public: * @note info and data must have been verified against the ledger hash */ void - gotSkipList( - LedgerHeader const& info, - boost::intrusive_ptr const& data); + gotSkipList(LedgerHeader const& info, boost::intrusive_ptr const& data); /** * Process a ledger delta (extracted from a TMReplayDeltaResponse message) @@ -95,9 +87,7 @@ public: * @note info and txns must have been verified against the ledger hash */ void - gotReplayDelta( - LedgerHeader const& info, - std::map>&& txns); + gotReplayDelta(LedgerHeader const& info, std::map>&& txns); /** Remove completed tasks */ void diff --git a/src/xrpld/app/ledger/LedgerToJson.h b/src/xrpld/app/ledger/LedgerToJson.h index 7b7e267d81..1d77c4dc39 100644 --- a/src/xrpld/app/ledger/LedgerToJson.h +++ b/src/xrpld/app/ledger/LedgerToJson.h @@ -13,26 +13,14 @@ namespace xrpl { struct LedgerFill { - LedgerFill( - ReadView const& l, - RPC::Context const* ctx, - int o = 0, - std::vector q = {}) + LedgerFill(ReadView const& l, RPC::Context const* ctx, int o = 0, std::vector q = {}) : ledger(l), options(o), txQueue(std::move(q)), context(ctx) { if (context) closeTime = context->ledgerMaster.getCloseTimeBySeq(ledger.seq()); } - enum Options { - dumpTxrp = 1, - dumpState = 2, - expand = 4, - full = 8, - binary = 16, - ownerFunds = 32, - dumpQueue = 64 - }; + enum Options { dumpTxrp = 1, dumpState = 2, expand = 4, full = 8, binary = 16, ownerFunds = 32, dumpQueue = 64 }; ReadView const& ledger; int options; diff --git a/src/xrpld/app/ledger/OpenLedger.h b/src/xrpld/app/ledger/OpenLedger.h index 45a3517168..498e140b4b 100644 --- a/src/xrpld/app/ledger/OpenLedger.h +++ b/src/xrpld/app/ledger/OpenLedger.h @@ -61,10 +61,7 @@ public: @param ledger A closed ledger */ - explicit OpenLedger( - std::shared_ptr const& ledger, - CachedSLEs& cache, - beast::Journal journal); + explicit OpenLedger(std::shared_ptr const& ledger, CachedSLEs& cache, beast::Journal journal); /** Returns `true` if there are no transactions. @@ -213,8 +210,7 @@ OpenLedger::apply( } catch (std::exception const& e) { - JLOG(j.error()) - << "OpenLedger::apply: Caught exception: " << e.what(); + JLOG(j.error()) << "OpenLedger::apply: Caught exception: " << e.what(); } } bool retry = true; @@ -246,8 +242,7 @@ OpenLedger::apply( // If there are any transactions left, we must have // tried them in at least one final pass - XRPL_ASSERT( - retries.empty() || !retry, "xrpl::OpenLedger::apply : valid retries"); + XRPL_ASSERT(retries.empty() || !retry, "xrpl::OpenLedger::apply : valid retries"); } //------------------------------------------------------------------------------ diff --git a/src/xrpld/app/ledger/OrderBookDB.cpp b/src/xrpld/app/ledger/OrderBookDB.cpp index 5963c00c5a..81a3bf5e4a 100644 --- a/src/xrpld/app/ledger/OrderBookDB.cpp +++ b/src/xrpld/app/ledger/OrderBookDB.cpp @@ -11,8 +11,7 @@ namespace xrpl { -OrderBookDB::OrderBookDB(Application& app) - : app_(app), seq_(0), j_(app.journal("OrderBookDB")) +OrderBookDB::OrderBookDB(Application& app) : app_(app), seq_(0), j_(app.journal("OrderBookDB")) { } @@ -39,18 +38,14 @@ OrderBookDB::setup(std::shared_ptr const& ledger) if (seq_.exchange(ledger->seq()) != seq) return; - JLOG(j_.debug()) << "Full order book update: " << seq << " to " - << ledger->seq(); + JLOG(j_.debug()) << "Full order book update: " << seq << " to " << ledger->seq(); if (app_.config().PATH_SEARCH_MAX != 0) { if (app_.config().standalone()) update(ledger); else - app_.getJobQueue().addJob( - jtUPDATE_PF, "OrderBookUpd", [this, ledger]() { - update(ledger); - }); + app_.getJobQueue().addJob(jtUPDATE_PF, "OrderBookUpd", [this, ledger]() { update(ledger); }); } } @@ -63,8 +58,7 @@ OrderBookDB::update(std::shared_ptr const& ledger) // A newer full update job is pending if (auto const seq = seq_.load(); seq > ledger->seq()) { - JLOG(j_.debug()) << "Eliding update for " << ledger->seq() - << " because of pending update to later " << seq; + JLOG(j_.debug()) << "Eliding update for " << ledger->seq() << " because of pending update to later " << seq; return; } @@ -87,14 +81,12 @@ OrderBookDB::update(std::shared_ptr const& ledger) { if (app_.isStopping()) { - JLOG(j_.info()) - << "Update halted because the process is stopping"; + JLOG(j_.info()) << "Update halted because the process is stopping"; seq_.store(0); return; } - if (sle->getType() == ltDIR_NODE && - sle->isFieldPresent(sfExchangeRate) && + if (sle->getType() == ltDIR_NODE && sle->isFieldPresent(sfExchangeRate) && sle->getFieldH256(sfRootIndex) == sle->key()) { Book book; @@ -136,14 +128,12 @@ OrderBookDB::update(std::shared_ptr const& ledger) } catch (SHAMapMissingNode const& mn) { - JLOG(j_.info()) << "Missing node in " << ledger->seq() - << " during update: " << mn.what(); + JLOG(j_.info()) << "Missing node in " << ledger->seq() << " during update: " << mn.what(); seq_.store(0); return; } - JLOG(j_.debug()) << "Update completed (" << ledger->seq() << "): " << cnt - << " books found"; + JLOG(j_.debug()) << "Update completed (" << ledger->seq() << "): " << cnt << " books found"; { std::lock_guard sl(mLock); @@ -176,9 +166,7 @@ OrderBookDB::addOrderBook(Book const& book) // return list of all orderbooks that want this issuerID and currencyID std::vector -OrderBookDB::getBooksByTakerPays( - Issue const& issue, - std::optional const& domain) +OrderBookDB::getBooksByTakerPays(Issue const& issue, std::optional const& domain) { std::vector ret; @@ -206,9 +194,7 @@ OrderBookDB::getBooksByTakerPays( } int -OrderBookDB::getBookSize( - Issue const& issue, - std::optional const& domain) +OrderBookDB::getBookSize(Issue const& issue, std::optional const& domain) { std::lock_guard sl(mLock); @@ -219,8 +205,7 @@ OrderBookDB::getBookSize( } else { - if (auto it = domainBooks_.find({issue, *domain}); - it != domainBooks_.end()) + if (auto it = domainBooks_.find({issue, *domain}); it != domainBooks_.end()) return static_cast(it->second.size()); } @@ -293,10 +278,8 @@ OrderBookDB::processTxn( if (node.getFieldU16(sfLedgerEntryType) == ltOFFER) { auto process = [&, this](SField const& field) { - if (auto data = dynamic_cast( - node.peekAtPField(field)); - data && data->isFieldPresent(sfTakerPays) && - data->isFieldPresent(sfTakerGets)) + if (auto data = dynamic_cast(node.peekAtPField(field)); + data && data->isFieldPresent(sfTakerPays) && data->isFieldPresent(sfTakerGets)) { auto listeners = getBookListeners( {data->getFieldAmount(sfTakerGets).issue(), @@ -319,8 +302,7 @@ OrderBookDB::processTxn( } catch (std::exception const& ex) { - JLOG(j_.info()) - << "processTxn: field not found (" << ex.what() << ")"; + JLOG(j_.info()) << "processTxn: field not found (" << ex.what() << ")"; } } } diff --git a/src/xrpld/app/ledger/OrderBookDB.h b/src/xrpld/app/ledger/OrderBookDB.h index 68bdf294a9..601b2d38e4 100644 --- a/src/xrpld/app/ledger/OrderBookDB.h +++ b/src/xrpld/app/ledger/OrderBookDB.h @@ -29,16 +29,12 @@ public: /** @return a list of all orderbooks that want this issuerID and currencyID. */ std::vector - getBooksByTakerPays( - Issue const&, - std::optional const& domain = std::nullopt); + getBooksByTakerPays(Issue const&, std::optional const& domain = std::nullopt); /** @return a count of all orderbooks that want this issuerID and currencyID. */ int - getBookSize( - Issue const&, - std::optional const& domain = std::nullopt); + getBookSize(Issue const&, std::optional const& domain = std::nullopt); bool isBookToXRP(Issue const&, std::optional domain = std::nullopt); @@ -50,10 +46,7 @@ public: // see if this txn effects any orderbook void - processTxn( - std::shared_ptr const& ledger, - AcceptedLedgerTx const& alTx, - MultiApiJson const& jvObj); + processTxn(std::shared_ptr const& ledger, AcceptedLedgerTx const& alTx, MultiApiJson const& jvObj); private: Application& app_; @@ -61,8 +54,7 @@ private: // Maps order books by "issue in" to "issue out": hardened_hash_map> allBooks_; - hardened_hash_map, hardened_hash_set> - domainBooks_; + hardened_hash_map, hardened_hash_set> domainBooks_; // does an order book to XRP exist hash_set xrpBooks_; diff --git a/src/xrpld/app/ledger/TransactionMaster.h b/src/xrpld/app/ledger/TransactionMaster.h index a9bf05065d..ceba55a85a 100644 --- a/src/xrpld/app/ledger/TransactionMaster.h +++ b/src/xrpld/app/ledger/TransactionMaster.h @@ -27,9 +27,7 @@ public: std::shared_ptr fetch_from_cache(uint256 const&); - std::variant< - std::pair, std::shared_ptr>, - TxSearched> + std::variant, std::shared_ptr>, TxSearched> fetch(uint256 const&, error_code_i& ec); /** @@ -41,27 +39,15 @@ public: * the all ledgers in the provided range were present in * the database while the search was conducted. */ - std::variant< - std::pair, std::shared_ptr>, - TxSearched> - fetch( - uint256 const&, - ClosedInterval const& range, - error_code_i& ec); + std::variant, std::shared_ptr>, TxSearched> + fetch(uint256 const&, ClosedInterval const& range, error_code_i& ec); std::shared_ptr - fetch( - boost::intrusive_ptr const& item, - SHAMapNodeType type, - std::uint32_t uCommitLedger); + fetch(boost::intrusive_ptr const& item, SHAMapNodeType type, std::uint32_t uCommitLedger); // return value: true = we had the transaction already bool - inLedger( - uint256 const& hash, - std::uint32_t ledger, - std::optional tseq, - std::optional netID); + inLedger(uint256 const& hash, std::uint32_t ledger, std::optional tseq, std::optional netID); void canonicalize(std::shared_ptr* pTransaction); diff --git a/src/xrpld/app/ledger/TransactionStateSF.cpp b/src/xrpld/app/ledger/TransactionStateSF.cpp index af7dd8640a..ee2febbd83 100644 --- a/src/xrpld/app/ledger/TransactionStateSF.cpp +++ b/src/xrpld/app/ledger/TransactionStateSF.cpp @@ -11,14 +11,8 @@ TransactionStateSF::gotNode( SHAMapNodeType type) const { - XRPL_ASSERT( - type != SHAMapNodeType::tnTRANSACTION_NM, - "xrpl::TransactionStateSF::gotNode : valid input"); - db_.store( - hotTRANSACTION_NODE, - std::move(nodeData), - nodeHash.as_uint256(), - ledgerSeq); + XRPL_ASSERT(type != SHAMapNodeType::tnTRANSACTION_NM, "xrpl::TransactionStateSF::gotNode : valid input"); + db_.store(hotTRANSACTION_NODE, std::move(nodeData), nodeHash.as_uint256(), ledgerSeq); } std::optional diff --git a/src/xrpld/app/ledger/TransactionStateSF.h b/src/xrpld/app/ledger/TransactionStateSF.h index 9950134e4b..0ea8d7fb2d 100644 --- a/src/xrpld/app/ledger/TransactionStateSF.h +++ b/src/xrpld/app/ledger/TransactionStateSF.h @@ -13,18 +13,13 @@ namespace xrpl { class TransactionStateSF : public SHAMapSyncFilter { public: - TransactionStateSF(NodeStore::Database& db, AbstractFetchPackContainer& fp) - : db_(db), fp_(fp) + TransactionStateSF(NodeStore::Database& db, AbstractFetchPackContainer& fp) : db_(db), fp_(fp) { } void - gotNode( - bool fromFilter, - SHAMapHash const& nodeHash, - std::uint32_t ledgerSeq, - Blob&& nodeData, - SHAMapNodeType type) const override; + gotNode(bool fromFilter, SHAMapHash const& nodeHash, std::uint32_t ledgerSeq, Blob&& nodeData, SHAMapNodeType type) + const override; std::optional getNode(SHAMapHash const& nodeHash) const override; diff --git a/src/xrpld/app/ledger/detail/BuildLedger.cpp b/src/xrpld/app/ledger/detail/BuildLedger.cpp index a716375f6b..1414441b35 100644 --- a/src/xrpld/app/ledger/detail/BuildLedger.cpp +++ b/src/xrpld/app/ledger/detail/BuildLedger.cpp @@ -38,8 +38,7 @@ buildLedgerImpl( { OpenView accum(&*built); - XRPL_ASSERT( - !accum.open(), "xrpl::buildLedgerImpl : valid ledger state"); + XRPL_ASSERT(!accum.open(), "xrpl::buildLedgerImpl : valid ledger state"); applyTxs(accum, built); accum.apply(*built); } @@ -51,15 +50,13 @@ buildLedgerImpl( int const asf = built->stateMap().flushDirty(hotACCOUNT_NODE); int const tmf = built->txMap().flushDirty(hotTRANSACTION_NODE); - JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf - << " transaction nodes"; + JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf << " transaction nodes"; } built->unshare(); // Accept ledger XRPL_ASSERT( - built->header().seq < XRP_LEDGER_EARLIEST_FEES || - built->read(keylet::fees()), + built->header().seq < XRP_LEDGER_EARLIEST_FEES || built->read(keylet::fees()), "xrpl::buildLedgerImpl : valid ledger fees"); built->setAccepted(closeTime, closeResolution, closeTimeCorrect); @@ -91,8 +88,8 @@ applyTransactions( // Attempt to apply all of the retriable transactions for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass) { - JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass - << " begins (" << txns.size() << " transactions)"; + JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass << " begins (" << txns.size() + << " transactions)"; int changes = 0; auto it = txns.begin(); @@ -109,8 +106,7 @@ applyTransactions( continue; } - switch (applyTransaction( - app, view, *it->second, certainRetry, tapNONE, j)) + switch (applyTransaction(app, view, *it->second, certainRetry, tapNONE, j)) { case ApplyTransactionResult::Success: it = txns.erase(it); @@ -128,15 +124,14 @@ applyTransactions( } catch (std::exception const& ex) { - JLOG(j.warn()) - << "Transaction " << txid << " throws: " << ex.what(); + JLOG(j.warn()) << "Transaction " << txid << " throws: " << ex.what(); failed.insert(txid); it = txns.erase(it); } } - JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass - << " completed (" << changes << " changes)"; + JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass << " completed (" << changes + << " changes)"; // Accumulate changes. count += changes; @@ -152,9 +147,7 @@ applyTransactions( // If there are any transactions left, we must have // tried them in at least one final pass - XRPL_ASSERT( - txns.empty() || !certainRetry, - "xrpl::applyTransactions : retry transactions"); + XRPL_ASSERT(txns.empty() || !certainRetry, "xrpl::applyTransactions : retry transactions"); return count; } @@ -170,8 +163,7 @@ buildLedger( std::set& failedTxns, beast::Journal j) { - JLOG(j.debug()) << "Report: Transaction Set = " << txns.key() << ", close " - << closeTime.time_since_epoch().count() + JLOG(j.debug()) << "Report: Transaction Set = " << txns.key() << ", close " << closeTime.time_since_epoch().count() << (closeTimeCorrect ? "" : " (incorrect)"); return buildLedgerImpl( @@ -182,34 +174,23 @@ buildLedger( app, j, [&](OpenView& accum, std::shared_ptr const& built) { - JLOG(j.debug()) - << "Attempting to apply " << txns.size() << " transactions"; + JLOG(j.debug()) << "Attempting to apply " << txns.size() << " transactions"; - auto const applied = - applyTransactions(app, built, txns, failedTxns, accum, j); + auto const applied = applyTransactions(app, built, txns, failedTxns, accum, j); if (!txns.empty() || !failedTxns.empty()) - JLOG(j.debug()) - << "Applied " << applied << " transactions; " - << failedTxns.size() << " failed and " << txns.size() - << " will be retried. " - << "Total transactions in ledger (including Inner Batch): " - << accum.txCount(); + JLOG(j.debug()) << "Applied " << applied << " transactions; " << failedTxns.size() << " failed and " + << txns.size() << " will be retried. " + << "Total transactions in ledger (including Inner Batch): " << accum.txCount(); else - JLOG(j.debug()) - << "Applied " << applied << " transactions. " - << "Total transactions in ledger (including Inner Batch): " - << accum.txCount(); + JLOG(j.debug()) << "Applied " << applied << " transactions. " + << "Total transactions in ledger (including Inner Batch): " << accum.txCount(); }); } // Build a ledger by replaying std::shared_ptr -buildLedger( - LedgerReplay const& replayData, - ApplyFlags applyFlags, - Application& app, - beast::Journal j) +buildLedger(LedgerReplay const& replayData, ApplyFlags applyFlags, Application& app, beast::Journal j) { auto const& replayLedger = replayData.replay(); diff --git a/src/xrpld/app/ledger/detail/InboundLedger.cpp b/src/xrpld/app/ledger/detail/InboundLedger.cpp index 710173cd17..3c8f61a915 100644 --- a/src/xrpld/app/ledger/detail/InboundLedger.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedger.cpp @@ -61,12 +61,7 @@ InboundLedger::InboundLedger( Reason reason, clock_type& clock, std::unique_ptr peerSet) - : TimeoutCounter( - app, - hash, - ledgerAcquireTimeout, - {jtLEDGER_DATA, "InboundLedger", 5}, - app.journal("InboundLedger")) + : TimeoutCounter(app, hash, ledgerAcquireTimeout, {jtLEDGER_DATA, "InboundLedger", 5}, app.journal("InboundLedger")) , m_clock(clock) , mHaveHeader(false) , mHaveState(false) @@ -102,8 +97,7 @@ InboundLedger::init(ScopedLockType& collectionLock) JLOG(journal_.debug()) << "Acquiring ledger we already have in " << " local store. " << hash_; XRPL_ASSERT( - mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || - mLedger->read(keylet::fees()), + mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), "xrpl::InboundLedger::init : valid ledger fees"); mLedger->setImmutable(); @@ -121,9 +115,8 @@ std::size_t InboundLedger::getPeerCount() const { auto const& peerIds = mPeerSet->getPeerIds(); - return std::count_if(peerIds.begin(), peerIds.end(), [this](auto id) { - return (app_.overlay().findPeerByShortID(id) != nullptr); - }); + return std::count_if( + peerIds.begin(), peerIds.end(), [this](auto id) { return (app_.overlay().findPeerByShortID(id) != nullptr); }); } void @@ -169,21 +162,15 @@ InboundLedger::~InboundLedger() } if (!isDone()) { - JLOG(journal_.debug()) - << "Acquire " << hash_ << " abort " - << ((timeouts_ == 0) ? std::string() - : (std::string("timeouts:") + - std::to_string(timeouts_) + " ")) - << mStats.get(); + JLOG(journal_.debug()) << "Acquire " << hash_ << " abort " + << ((timeouts_ == 0) ? std::string() + : (std::string("timeouts:") + std::to_string(timeouts_) + " ")) + << mStats.get(); } } static std::vector -neededHashes( - uint256 const& root, - SHAMap& map, - int max, - SHAMapSyncFilter* filter) +neededHashes(uint256 const& root, SHAMap& map, int max, SHAMapSyncFilter* filter) { std::vector ret; @@ -206,15 +193,13 @@ neededHashes( std::vector InboundLedger::neededTxHashes(int max, SHAMapSyncFilter* filter) const { - return neededHashes( - mLedger->header().txHash, mLedger->txMap(), max, filter); + return neededHashes(mLedger->header().txHash, mLedger->txMap(), max, filter); } std::vector InboundLedger::neededStateHashes(int max, SHAMapSyncFilter* filter) const { - return neededHashes( - mLedger->header().accountHash, mLedger->stateMap(), max, filter); + return neededHashes(mLedger->header().accountHash, mLedger->stateMap(), max, filter); } // See how much of the ledger data is stored locally @@ -227,16 +212,11 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) auto makeLedger = [&, this](Blob const& data) { JLOG(journal_.trace()) << "Ledger header found in fetch pack"; mLedger = std::make_shared( - deserializePrefixedHeader(makeSlice(data)), - app_.config(), - app_.getNodeFamily()); - if (mLedger->header().hash != hash_ || - (mSeq != 0 && mSeq != mLedger->header().seq)) + deserializePrefixedHeader(makeSlice(data)), app_.config(), app_.getNodeFamily()); + if (mLedger->header().hash != hash_ || (mSeq != 0 && mSeq != mLedger->header().seq)) { // We know for a fact the ledger can never be acquired - JLOG(journal_.warn()) - << "hash " << hash_ << " seq " << std::to_string(mSeq) - << " cannot be a ledger"; + JLOG(journal_.warn()) << "hash " << hash_ << " seq " << std::to_string(mSeq) << " cannot be a ledger"; mLedger.reset(); failed_ = true; } @@ -256,8 +236,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) if (std::addressof(dstDB) != std::addressof(srcDB)) { Blob blob{nodeObject->getData()}; - dstDB.store( - hotLEDGER, std::move(blob), hash_, mLedger->header().seq); + dstDB.store(hotLEDGER, std::move(blob), hash_, mLedger->header().seq); } } else @@ -274,8 +253,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) return; // Store the ledger header in the ledger's database - mLedger->stateMap().family().db().store( - hotLEDGER, std::move(*data), hash_, mLedger->header().seq); + mLedger->stateMap().family().db().store(hotLEDGER, std::move(*data), hash_, mLedger->header().seq); } if (mSeq == 0) @@ -294,10 +272,8 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) } else { - TransactionStateSF filter( - mLedger->txMap().family().db(), app_.getLedgerMaster()); - if (mLedger->txMap().fetchRoot( - SHAMapHash{mLedger->header().txHash}, &filter)) + TransactionStateSF filter(mLedger->txMap().family().db(), app_.getLedgerMaster()); + if (mLedger->txMap().fetchRoot(SHAMapHash{mLedger->header().txHash}, &filter)) { if (neededTxHashes(1, &filter).empty()) { @@ -312,15 +288,12 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) { if (mLedger->header().accountHash.isZero()) { - JLOG(journal_.fatal()) - << "We are acquiring a ledger with a zero account hash"; + JLOG(journal_.fatal()) << "We are acquiring a ledger with a zero account hash"; failed_ = true; return; } - AccountStateSF filter( - mLedger->stateMap().family().db(), app_.getLedgerMaster()); - if (mLedger->stateMap().fetchRoot( - SHAMapHash{mLedger->header().accountHash}, &filter)) + AccountStateSF filter(mLedger->stateMap().family().db(), app_.getLedgerMaster()); + if (mLedger->stateMap().fetchRoot(SHAMapHash{mLedger->header().accountHash}, &filter)) { if (neededStateHashes(1, &filter).empty()) { @@ -335,8 +308,7 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) JLOG(journal_.debug()) << "Had everything locally"; complete_ = true; XRPL_ASSERT( - mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || - mLedger->read(keylet::fees()), + mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), "xrpl::InboundLedger::tryDB : valid ledger fees"); mLedger->setImmutable(); } @@ -359,13 +331,11 @@ InboundLedger::onTimer(bool wasProgress, ScopedLockType&) { if (mSeq != 0) { - JLOG(journal_.warn()) - << timeouts_ << " timeouts for ledger " << mSeq; + JLOG(journal_.warn()) << timeouts_ << " timeouts for ledger " << mSeq; } else { - JLOG(journal_.warn()) - << timeouts_ << " timeouts for ledger " << hash_; + JLOG(journal_.warn()) << timeouts_ << " timeouts for ledger " << hash_; } failed_ = true; done(); @@ -379,8 +349,7 @@ InboundLedger::onTimer(bool wasProgress, ScopedLockType&) mByHash = true; std::size_t pc = getPeerCount(); - JLOG(journal_.debug()) - << "No progress(" << pc << ") for ledger " << hash_; + JLOG(journal_.debug()) << "No progress(" << pc << ") for ledger " << hash_; // addPeers triggers if the reason is not HISTORY // So if the reason IS HISTORY, need to trigger after we add @@ -425,20 +394,16 @@ InboundLedger::done() touch(); JLOG(journal_.debug()) << "Acquire " << hash_ << (failed_ ? " fail " : " ") - << ((timeouts_ == 0) - ? std::string() - : (std::string("timeouts:") + - std::to_string(timeouts_) + " ")) + << ((timeouts_ == 0) ? std::string() + : (std::string("timeouts:") + std::to_string(timeouts_) + " ")) << mStats.get(); - XRPL_ASSERT( - complete_ || failed_, "xrpl::InboundLedger::done : complete or failed"); + XRPL_ASSERT(complete_ || failed_, "xrpl::InboundLedger::done : complete or failed"); if (complete_ && !failed_ && mLedger) { XRPL_ASSERT( - mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || - mLedger->read(keylet::fees()), + mLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || mLedger->read(keylet::fees()), "xrpl::InboundLedger::done : valid ledger fees"); mLedger->setImmutable(); switch (mReason) @@ -453,17 +418,15 @@ InboundLedger::done() } // We hold the PeerSet lock, so must dispatch - app_.getJobQueue().addJob( - jtLEDGER_DATA, "AcqDone", [self = shared_from_this()]() { - if (self->complete_ && !self->failed_) - { - self->app_.getLedgerMaster().checkAccept(self->getLedger()); - self->app_.getLedgerMaster().tryAdvance(); - } - else - self->app_.getInboundLedgers().logFailure( - self->hash_, self->mSeq); - }); + app_.getJobQueue().addJob(jtLEDGER_DATA, "AcqDone", [self = shared_from_this()]() { + if (self->complete_ && !self->failed_) + { + self->app_.getLedgerMaster().checkAccept(self->getLedger()); + self->app_.getLedgerMaster().tryAdvance(); + } + else + self->app_.getInboundLedgers().logFailure(self->hash_, self->mSeq); + }); } /** Request more nodes, perhaps from a specific peer @@ -475,9 +438,8 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) if (isDone()) { - JLOG(journal_.debug()) - << "Trigger on ledger: " << hash_ << (complete_ ? " completed" : "") - << (failed_ ? " failed" : ""); + JLOG(journal_.debug()) << "Trigger on ledger: " << hash_ << (complete_ ? " completed" : "") + << (failed_ ? " failed" : ""); return; } @@ -491,8 +453,7 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) if (complete_ || failed_) ss << " complete=" << complete_ << " failed=" << failed_; else - ss << " header=" << mHaveHeader << " tx=" << mHaveTransactions - << " as=" << mHaveState; + ss << " header=" << mHaveHeader << " tx=" << mHaveTransactions << " as=" << mHaveState; stream << ss.str(); } @@ -514,8 +475,7 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) // Be more aggressive if we've timed out at least once tmGL.set_querytype(protocol::qtINDIRECT); - if (!progress_ && !failed_ && mByHash && - (timeouts_ > ledgerBecomeAggressiveThreshold)) + if (!progress_ && !failed_ && mByHash && (timeouts_ > ledgerBecomeAggressiveThreshold)) { auto need = getNeededHashes(); @@ -544,22 +504,19 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) } } - auto packet = - std::make_shared(tmBH, protocol::mtGET_OBJECTS); + auto packet = std::make_shared(tmBH, protocol::mtGET_OBJECTS); auto const& peerIds = mPeerSet->getPeerIds(); - std::for_each( - peerIds.begin(), peerIds.end(), [this, &packet](auto id) { - if (auto p = app_.overlay().findPeerByShortID(id)) - { - mByHash = false; - p->send(packet); - } - }); + std::for_each(peerIds.begin(), peerIds.end(), [this, &packet](auto id) { + if (auto p = app_.overlay().findPeerByShortID(id)) + { + mByHash = false; + p->send(packet); + } + }); } else { - JLOG(journal_.info()) - << "getNeededHashes says acquire is complete"; + JLOG(journal_.info()) << "getNeededHashes says acquire is complete"; mHaveHeader = true; mHaveTransactions = true; mHaveState = true; @@ -575,8 +532,7 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) tmGL.set_itype(protocol::liBASE); if (mSeq != 0) tmGL.set_ledgerseq(mSeq); - JLOG(journal_.trace()) << "Sending header request to " - << (peer ? "selected peer" : "all peers"); + JLOG(journal_.trace()) << "Sending header request to " << (peer ? "selected peer" : "all peers"); mPeerSet->sendRequest(tmGL, peer); return; } @@ -615,20 +571,17 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) // we need the root node tmGL.set_itype(protocol::liAS_NODE); *tmGL.add_nodeids() = SHAMapNodeID().getRawString(); - JLOG(journal_.trace()) << "Sending AS root request to " - << (peer ? "selected peer" : "all peers"); + JLOG(journal_.trace()) << "Sending AS root request to " << (peer ? "selected peer" : "all peers"); mPeerSet->sendRequest(tmGL, peer); return; } else { - AccountStateSF filter( - mLedger->stateMap().family().db(), app_.getLedgerMaster()); + AccountStateSF filter(mLedger->stateMap().family().db(), app_.getLedgerMaster()); // Release the lock while we process the large state map sl.unlock(); - auto nodes = - mLedger->stateMap().getMissingNodes(missingNodesFind, &filter); + auto nodes = mLedger->stateMap().getMissingNodes(missingNodesFind, &filter); sl.lock(); // Make sure nothing happened while we released the lock @@ -658,10 +611,8 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) *(tmGL.add_nodeids()) = id.first.getRawString(); } - JLOG(journal_.trace()) - << "Sending AS node request (" << nodes.size() - << ") to " - << (peer ? "selected peer" : "all peers"); + JLOG(journal_.trace()) << "Sending AS node request (" << nodes.size() << ") to " + << (peer ? "selected peer" : "all peers"); mPeerSet->sendRequest(tmGL, peer); return; } @@ -690,18 +641,15 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) // we need the root node tmGL.set_itype(protocol::liTX_NODE); *(tmGL.add_nodeids()) = SHAMapNodeID().getRawString(); - JLOG(journal_.trace()) << "Sending TX root request to " - << (peer ? "selected peer" : "all peers"); + JLOG(journal_.trace()) << "Sending TX root request to " << (peer ? "selected peer" : "all peers"); mPeerSet->sendRequest(tmGL, peer); return; } else { - TransactionStateSF filter( - mLedger->txMap().family().db(), app_.getLedgerMaster()); + TransactionStateSF filter(mLedger->txMap().family().db(), app_.getLedgerMaster()); - auto nodes = - mLedger->txMap().getMissingNodes(missingNodesFind, &filter); + auto nodes = mLedger->txMap().getMissingNodes(missingNodesFind, &filter); if (nodes.empty()) { @@ -726,9 +674,8 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) { *(tmGL.add_nodeids()) = n.first.getRawString(); } - JLOG(journal_.trace()) - << "Sending TX node request (" << nodes.size() - << ") to " << (peer ? "selected peer" : "all peers"); + JLOG(journal_.trace()) << "Sending TX node request (" << nodes.size() << ") to " + << (peer ? "selected peer" : "all peers"); mPeerSet->sendRequest(tmGL, peer); return; } @@ -742,25 +689,20 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) if (complete_ || failed_) { - JLOG(journal_.debug()) - << "Done:" << (complete_ ? " complete" : "") - << (failed_ ? " failed " : " ") << mLedger->header().seq; + JLOG(journal_.debug()) << "Done:" << (complete_ ? " complete" : "") << (failed_ ? " failed " : " ") + << mLedger->header().seq; sl.unlock(); done(); } } void -InboundLedger::filterNodes( - std::vector>& nodes, - TriggerReason reason) +InboundLedger::filterNodes(std::vector>& nodes, TriggerReason reason) { // Sort nodes so that the ones we haven't recently // requested come before the ones we have. auto dup = std::stable_partition( - nodes.begin(), nodes.end(), [this](auto const& item) { - return mRecentNodes.count(item.second) == 0; - }); + nodes.begin(), nodes.end(), [this](auto const& item) { return mRecentNodes.count(item.second) == 0; }); // If everything is a duplicate we don't want to send // any query at all except on a timeout where we need @@ -782,8 +724,7 @@ InboundLedger::filterNodes( nodes.erase(dup, nodes.end()); } - std::size_t const limit = - (reason == TriggerReason::reply) ? reqNodesReply : reqNodes; + std::size_t const limit = (reason == TriggerReason::reply) ? reqNodesReply : reqNodes; if (nodes.size() > limit) nodes.resize(limit); @@ -806,14 +747,10 @@ InboundLedger::takeHeader(std::string const& data) return true; auto* f = &app_.getNodeFamily(); - mLedger = std::make_shared( - deserializeHeader(makeSlice(data)), app_.config(), *f); - if (mLedger->header().hash != hash_ || - (mSeq != 0 && mSeq != mLedger->header().seq)) + mLedger = std::make_shared(deserializeHeader(makeSlice(data)), app_.config(), *f); + if (mLedger->header().hash != hash_ || (mSeq != 0 && mSeq != mLedger->header().seq)) { - JLOG(journal_.warn()) - << "Acquire hash mismatch: " << mLedger->header().hash - << "!=" << hash_; + JLOG(journal_.warn()) << "Acquire hash mismatch: " << mLedger->header().hash << "!=" << hash_; mLedger.reset(); return false; } @@ -866,19 +803,16 @@ InboundLedger::receiveNode(protocol::TMLedgerData& packet, SHAMapAddNode& san) return; } - auto [map, rootHash, filter] = [&]() - -> std::tuple> { + auto [map, rootHash, filter] = [&]() -> std::tuple> { if (packet.type() == protocol::liTX_NODE) return { mLedger->txMap(), SHAMapHash{mLedger->header().txHash}, - std::make_unique( - mLedger->txMap().family().db(), app_.getLedgerMaster())}; + std::make_unique(mLedger->txMap().family().db(), app_.getLedgerMaster())}; return { mLedger->stateMap(), SHAMapHash{mLedger->header().accountHash}, - std::make_unique( - mLedger->stateMap().family().db(), app_.getLedgerMaster())}; + std::make_unique(mLedger->stateMap().family().db(), app_.getLedgerMaster())}; }(); try @@ -950,10 +884,8 @@ InboundLedger::takeAsRootNode(Slice const& data, SHAMapAddNode& san) // LCOV_EXCL_STOP } - AccountStateSF filter( - mLedger->stateMap().family().db(), app_.getLedgerMaster()); - san += mLedger->stateMap().addRootNode( - SHAMapHash{mLedger->header().accountHash}, data, &filter); + AccountStateSF filter(mLedger->stateMap().family().db(), app_.getLedgerMaster()); + san += mLedger->stateMap().addRootNode(SHAMapHash{mLedger->header().accountHash}, data, &filter); return san.isGood(); } @@ -977,10 +909,8 @@ InboundLedger::takeTxRootNode(Slice const& data, SHAMapAddNode& san) // LCOV_EXCL_STOP } - TransactionStateSF filter( - mLedger->txMap().family().db(), app_.getLedgerMaster()); - san += mLedger->txMap().addRootNode( - SHAMapHash{mLedger->header().txHash}, data, &filter); + TransactionStateSF filter(mLedger->txMap().family().db(), app_.getLedgerMaster()); + san += mLedger->txMap().addRootNode(SHAMapHash{mLedger->header().txHash}, data, &filter); return san.isGood(); } @@ -991,30 +921,25 @@ InboundLedger::getNeededHashes() if (!mHaveHeader) { - ret.push_back( - std::make_pair(protocol::TMGetObjectByHash::otLEDGER, hash_)); + ret.push_back(std::make_pair(protocol::TMGetObjectByHash::otLEDGER, hash_)); return ret; } if (!mHaveState) { - AccountStateSF filter( - mLedger->stateMap().family().db(), app_.getLedgerMaster()); + AccountStateSF filter(mLedger->stateMap().family().db(), app_.getLedgerMaster()); for (auto const& h : neededStateHashes(4, &filter)) { - ret.push_back( - std::make_pair(protocol::TMGetObjectByHash::otSTATE_NODE, h)); + ret.push_back(std::make_pair(protocol::TMGetObjectByHash::otSTATE_NODE, h)); } } if (!mHaveTransactions) { - TransactionStateSF filter( - mLedger->txMap().family().db(), app_.getLedgerMaster()); + TransactionStateSF filter(mLedger->txMap().family().db(), app_.getLedgerMaster()); for (auto const& h : neededTxHashes(4, &filter)) { - ret.push_back(std::make_pair( - protocol::TMGetObjectByHash::otTRANSACTION_NODE, h)); + ret.push_back(std::make_pair(protocol::TMGetObjectByHash::otTRANSACTION_NODE, h)); } } @@ -1025,9 +950,7 @@ InboundLedger::getNeededHashes() Returns 'true' if we need to dispatch */ bool -InboundLedger::gotData( - std::weak_ptr peer, - std::shared_ptr const& data) +InboundLedger::gotData(std::weak_ptr peer, std::shared_ptr const& data) { std::lock_guard sl(mReceivedDataLock); @@ -1052,17 +975,14 @@ InboundLedger::gotData( // TODO Change peer to Consumer // int -InboundLedger::processData( - std::shared_ptr peer, - protocol::TMLedgerData& packet) +InboundLedger::processData(std::shared_ptr peer, protocol::TMLedgerData& packet) { if (packet.type() == protocol::liBASE) { if (packet.nodes().empty()) { JLOG(journal_.warn()) << peer->id() << ": empty header data"; - peer->charge( - Resource::feeMalformedRequest, "ledger_data empty header"); + peer->charge(Resource::feeMalformedRequest, "ledger_data empty header"); return -1; } @@ -1077,9 +997,7 @@ InboundLedger::processData( if (!takeHeader(packet.nodes(0).nodedata())) { JLOG(journal_.warn()) << "Got invalid header data"; - peer->charge( - Resource::feeMalformedRequest, - "ledger_data invalid header"); + peer->charge(Resource::feeMalformedRequest, "ledger_data invalid header"); return -1; } @@ -1100,8 +1018,7 @@ InboundLedger::processData( } catch (std::exception const& ex) { - JLOG(journal_.warn()) - << "Included AS/TX root invalid: " << ex.what(); + JLOG(journal_.warn()) << "Included AS/TX root invalid: " << ex.what(); using namespace std::string_literals; peer->charge(Resource::feeInvalidData, "ledger_data "s + ex.what()); return -1; @@ -1114,11 +1031,9 @@ InboundLedger::processData( return san.getGood(); } - if ((packet.type() == protocol::liTX_NODE) || - (packet.type() == protocol::liAS_NODE)) + if ((packet.type() == protocol::liTX_NODE) || (packet.type() == protocol::liAS_NODE)) { - std::string type = packet.type() == protocol::liTX_NODE ? "liTX_NODE: " - : "liAS_NODE: "; + std::string type = packet.type() == protocol::liTX_NODE ? "liTX_NODE: " : "liAS_NODE: "; if (packet.nodes().empty()) { @@ -1135,8 +1050,7 @@ InboundLedger::processData( if (!node.has_nodeid() || !node.has_nodedata()) { JLOG(journal_.warn()) << "Got bad node"; - peer->charge( - Resource::feeMalformedRequest, "ledger_data bad node"); + peer->charge(Resource::feeMalformedRequest, "ledger_data bad node"); return -1; } } @@ -1144,10 +1058,8 @@ InboundLedger::processData( SHAMapAddNode san; receiveNode(packet, san); - JLOG(journal_.debug()) - << "Ledger " - << ((packet.type() == protocol::liTX_NODE) ? "TX" : "AS") - << " node stats: " << san.get(); + JLOG(journal_.debug()) << "Ledger " << ((packet.type() == protocol::liTX_NODE) ? "TX" : "AS") + << " node stats: " << san.get(); if (san.isUseful()) progress_ = true; @@ -1215,19 +1127,13 @@ struct PeerDataCounts #if _MSC_VER std::vector, int>> s; s.reserve(n); - std::sample( - counts.begin(), counts.end(), std::back_inserter(s), n, rng); + std::sample(counts.begin(), counts.end(), std::back_inserter(s), n, rng); for (auto& v : s) { outFunc(v); } #else - std::sample( - counts.begin(), - counts.end(), - boost::make_function_output_iterator(outFunc), - n, - rng); + std::sample(counts.begin(), counts.end(), boost::make_function_output_iterator(outFunc), n, rng); #endif } }; @@ -1278,9 +1184,7 @@ InboundLedger::runData() // Select a random sample of the peers that gives us the most nodes that are // useful dataCounts.prune(); - dataCounts.sampleN(maxUsefulPeers, [&](std::shared_ptr const& peer) { - trigger(peer, TriggerReason::reply); - }); + dataCounts.sampleN(maxUsefulPeers, [&](std::shared_ptr const& peer) { trigger(peer, TriggerReason::reply); }); } Json::Value diff --git a/src/xrpld/app/ledger/detail/InboundLedgers.cpp b/src/xrpld/app/ledger/detail/InboundLedgers.cpp index fd2cde698e..626f58b686 100644 --- a/src/xrpld/app/ledger/detail/InboundLedgers.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedgers.cpp @@ -48,19 +48,13 @@ public: /** @callgraph */ std::shared_ptr - acquire( - uint256 const& hash, - std::uint32_t seq, - InboundLedger::Reason reason) override + acquire(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason reason) override { auto doAcquire = [&, seq, reason]() -> std::shared_ptr { - XRPL_ASSERT( - hash.isNonZero(), - "xrpl::InboundLedgersImp::acquire::doAcquire : nonzero hash"); + XRPL_ASSERT(hash.isNonZero(), "xrpl::InboundLedgersImp::acquire::doAcquire : nonzero hash"); // probably not the right rule - if (app_.getOPs().isNeedNetworkLedger() && - (reason != InboundLedger::Reason::GENERIC) && + if (app_.getOPs().isNeedNetworkLedger() && (reason != InboundLedger::Reason::GENERIC) && (reason != InboundLedger::Reason::CONSENSUS)) return {}; @@ -82,12 +76,7 @@ public: else { inbound = std::make_shared( - app_, - hash, - seq, - reason, - std::ref(m_clock), - mPeerSetBuilder->build()); + app_, hash, seq, reason, std::ref(m_clock), mPeerSetBuilder->build()); mLedgers.emplace(hash, inbound); inbound->init(sl); ++mCounter; @@ -106,17 +95,14 @@ public: return inbound->getLedger(); }; using namespace std::chrono_literals; - std::shared_ptr ledger = perf::measureDurationAndLog( - doAcquire, "InboundLedgersImp::acquire", 500ms, j_); + std::shared_ptr ledger = + perf::measureDurationAndLog(doAcquire, "InboundLedgersImp::acquire", 500ms, j_); return ledger; } void - acquireAsync( - uint256 const& hash, - std::uint32_t seq, - InboundLedger::Reason reason) override + acquireAsync(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason reason) override { std::unique_lock lock(acquiresMutex_); try @@ -129,15 +115,11 @@ public: } catch (std::exception const& e) { - JLOG(j_.warn()) - << "Exception thrown for acquiring new inbound ledger " << hash - << ": " << e.what(); + JLOG(j_.warn()) << "Exception thrown for acquiring new inbound ledger " << hash << ": " << e.what(); } catch (...) { - JLOG(j_.warn()) - << "Unknown exception thrown for acquiring new inbound ledger " - << hash; + JLOG(j_.warn()) << "Unknown exception thrown for acquiring new inbound ledger " << hash; } pendingAcquires_.erase(hash); } @@ -145,8 +127,7 @@ public: std::shared_ptr find(uint256 const& hash) override { - XRPL_ASSERT( - hash.isNonZero(), "xrpl::InboundLedgersImp::find : nonzero input"); + XRPL_ASSERT(hash.isNonZero(), "xrpl::InboundLedgersImp::find : nonzero input"); std::shared_ptr ret; @@ -178,38 +159,28 @@ public: /** We received a TMLedgerData from a peer. */ bool - gotLedgerData( - LedgerHash const& hash, - std::shared_ptr peer, - std::shared_ptr packet) override + gotLedgerData(LedgerHash const& hash, std::shared_ptr peer, std::shared_ptr packet) + override { if (auto ledger = find(hash)) { - JLOG(j_.trace()) << "Got data (" << packet->nodes().size() - << ") for acquiring ledger: " << hash; + JLOG(j_.trace()) << "Got data (" << packet->nodes().size() << ") for acquiring ledger: " << hash; // Stash the data for later processing and see if we need to // dispatch if (ledger->gotData(std::weak_ptr(peer), packet)) - app_.getJobQueue().addJob( - jtLEDGER_DATA, "ProcessLData", [ledger]() { - ledger->runData(); - }); + app_.getJobQueue().addJob(jtLEDGER_DATA, "ProcessLData", [ledger]() { ledger->runData(); }); return true; } - JLOG(j_.trace()) << "Got data for ledger " << hash - << " which we're no longer acquiring"; + JLOG(j_.trace()) << "Got data for ledger " << hash << " which we're no longer acquiring"; // If it's state node data, stash it because it still might be // useful. if (packet->type() == protocol::liAS_NODE) { - app_.getJobQueue().addJob( - jtLEDGER_DATA, "GotStaleData", [this, packet]() { - gotStaleData(packet); - }); + app_.getJobQueue().addJob(jtLEDGER_DATA, "GotStaleData", [this, packet]() { gotStaleData(packet); }); } return false; @@ -251,8 +222,7 @@ public: if (!node.has_nodeid() || !node.has_nodedata()) return; - auto newNode = - SHAMapTreeNode::makeFromWire(makeSlice(node.nodedata())); + auto newNode = SHAMapTreeNode::makeFromWire(makeSlice(node.nodedata())); if (!newNode) return; @@ -261,8 +231,7 @@ public: newNode->serializeWithPrefix(s); app_.getLedgerMaster().addFetchPack( - newNode->getHash().as_uint256(), - std::make_shared(s.begin(), s.end())); + newNode->getHash().as_uint256(), std::make_shared(s.begin(), s.end())); } } catch (std::exception const&) @@ -308,9 +277,7 @@ public: acqs.reserve(mLedgers.size()); for (auto const& it : mLedgers) { - XRPL_ASSERT( - it.second, - "xrpl::InboundLedgersImp::getInfo : non-null ledger"); + XRPL_ASSERT(it.second, "xrpl::InboundLedgersImp::getInfo : non-null ledger"); acqs.push_back(it); } for (auto const& it : mRecentFailures) @@ -400,13 +367,9 @@ public: beast::expire(mRecentFailures, kReacquireInterval); } - JLOG(j_.debug()) - << "Swept " << stuffToSweep.size() << " out of " << total - << " inbound ledgers. Duration: " - << std::chrono::duration_cast( - m_clock.now() - start) - .count() - << "ms"; + JLOG(j_.debug()) << "Swept " << stuffToSweep.size() << " out of " << total << " inbound ledgers. Duration: " + << std::chrono::duration_cast(m_clock.now() - start).count() + << "ms"; } void @@ -453,8 +416,7 @@ make_InboundLedgers( InboundLedgers::clock_type& clock, beast::insight::Collector::ptr const& collector) { - return std::make_unique( - app, clock, collector, make_PeerSetBuilder(app)); + return std::make_unique(app, clock, collector, make_PeerSetBuilder(app)); } } // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/InboundTransactions.cpp b/src/xrpld/app/ledger/detail/InboundTransactions.cpp index 80906c45e7..36ebb7bd9e 100644 --- a/src/xrpld/app/ledger/detail/InboundTransactions.cpp +++ b/src/xrpld/app/ledger/detail/InboundTransactions.cpp @@ -30,8 +30,7 @@ public: TransactionAcquire::pointer mAcquire; std::shared_ptr mSet; - InboundTransactionSet(std::uint32_t seq, std::shared_ptr const& set) - : mSeq(seq), mSet(set) + InboundTransactionSet(std::uint32_t seq, std::shared_ptr const& set) : mSeq(seq), mSet(set) { ; } @@ -56,8 +55,7 @@ public: , m_peerSetBuilder(std::move(peerSetBuilder)) , j_(app_.journal("InboundTransactions")) { - m_zeroSet.mSet = std::make_shared( - SHAMapType::TRANSACTION, uint256(), app_.getNodeFamily()); + m_zeroSet.mSet = std::make_shared(SHAMapType::TRANSACTION, uint256(), app_.getNodeFamily()); m_zeroSet.mSet->setUnbacked(); } @@ -99,8 +97,7 @@ public: if (!acquire || stopping_) return std::shared_ptr(); - ta = std::make_shared( - app_, hash, m_peerSetBuilder->build()); + ta = std::make_shared(app_, hash, m_peerSetBuilder->build()); auto& obj = m_map[hash]; obj.mAcquire = ta; @@ -115,15 +112,12 @@ public: /** We received a TMLedgerData from a peer. */ void - gotData( - LedgerHash const& hash, - std::shared_ptr peer, - std::shared_ptr packet_ptr) override + gotData(LedgerHash const& hash, std::shared_ptr peer, std::shared_ptr packet_ptr) + override { protocol::TMLedgerData& packet = *packet_ptr; - JLOG(j_.trace()) << "Got data (" << packet.nodes().size() - << ") for acquiring ledger: " << hash; + JLOG(j_.trace()) << "Got data (" << packet.nodes().size() << ") for acquiring ledger: " << hash; TransactionAcquire::pointer ta = getAcquire(hash); @@ -160,10 +154,7 @@ public: } void - giveSet( - uint256 const& hash, - std::shared_ptr const& set, - bool fromAcquire) override + giveSet(uint256 const& hash, std::shared_ptr const& set, bool fromAcquire) override { bool isNew = true; @@ -201,8 +192,7 @@ public: auto it = m_map.begin(); - std::uint32_t const minSeq = - (seq < setKeepRounds) ? 0 : (seq - setKeepRounds); + std::uint32_t const minSeq = (seq < setKeepRounds) ? 0 : (seq - setKeepRounds); std::uint32_t maxSeq = seq + setKeepRounds; while (it != m_map.end()) @@ -254,8 +244,7 @@ make_InboundTransactions( beast::insight::Collector::ptr const& collector, std::function const&, bool)> gotSet) { - return std::make_unique( - app, collector, std::move(gotSet), make_PeerSetBuilder(app)); + return std::make_unique(app, collector, std::move(gotSet), make_PeerSetBuilder(app)); } } // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp index 1eec2efc80..f54c79f9c0 100644 --- a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp +++ b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp @@ -53,8 +53,7 @@ class LedgerCleanerImp : public LedgerCleaner //-------------------------------------------------------------------------- public: - LedgerCleanerImp(Application& app, beast::Journal journal) - : app_(app), j_(journal) + LedgerCleanerImp(Application& app, beast::Journal journal) : app_(app), j_(journal) { } @@ -208,14 +207,10 @@ private: { std::unique_lock lock(mutex_); state_ = State::notCleaning; - wakeup_.wait(lock, [this]() { - return (shouldExit_ || state_ == State::cleaning); - }); + wakeup_.wait(lock, [this]() { return (shouldExit_ || state_ == State::cleaning); }); if (shouldExit_) break; - XRPL_ASSERT( - state_ == State::cleaning, - "xrpl::LedgerCleanerImp::run : is cleaning"); + XRPL_ASSERT(state_ == State::cleaning, "xrpl::LedgerCleanerImp::run : is cleaning"); } doLedgerCleaner(); } @@ -232,12 +227,9 @@ private: } catch (SHAMapMissingNode const& mn) { - JLOG(j_.warn()) - << "Ledger #" << ledger->header().seq << ": " << mn.what(); + JLOG(j_.warn()) << "Ledger #" << ledger->header().seq << ": " << mn.what(); app_.getInboundLedgers().acquire( - ledger->header().hash, - ledger->header().seq, - InboundLedger::Reason::GENERIC); + ledger->header().hash, ledger->header().seq, InboundLedger::Reason::GENERIC); } return hash ? *hash : beast::zero; // kludge } @@ -250,20 +242,14 @@ private: @return `true` if the ledger was cleaned. */ bool - doLedger( - LedgerIndex const& ledgerIndex, - LedgerHash const& ledgerHash, - bool doNodes, - bool doTxns) + doLedger(LedgerIndex const& ledgerIndex, LedgerHash const& ledgerHash, bool doNodes, bool doTxns) { - auto nodeLedger = app_.getInboundLedgers().acquire( - ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC); + auto nodeLedger = app_.getInboundLedgers().acquire(ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC); if (!nodeLedger) { JLOG(j_.debug()) << "Ledger " << ledgerIndex << " not available"; app_.getLedgerMaster().clearLedger(ledgerIndex); - app_.getInboundLedgers().acquire( - ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC); + app_.getInboundLedgers().acquire(ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC); return false; } @@ -272,15 +258,13 @@ private: (dbLedger->header().parentHash != nodeLedger->header().parentHash)) { // Ideally we'd also check for more than one ledger with that index - JLOG(j_.debug()) - << "Ledger " << ledgerIndex << " mismatches SQL DB"; + JLOG(j_.debug()) << "Ledger " << ledgerIndex << " mismatches SQL DB"; doTxns = true; } if (!app_.getLedgerMaster().fixIndex(ledgerIndex, ledgerHash)) { - JLOG(j_.debug()) - << "ledger " << ledgerIndex << " had wrong entry in history"; + JLOG(j_.debug()) << "ledger " << ledgerIndex << " had wrong entry in history"; doTxns = true; } @@ -288,8 +272,7 @@ private: { JLOG(j_.debug()) << "Ledger " << ledgerIndex << " is missing nodes"; app_.getLedgerMaster().clearLedger(ledgerIndex); - app_.getInboundLedgers().acquire( - ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC); + app_.getInboundLedgers().acquire(ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC); return false; } @@ -308,9 +291,7 @@ private: @return The hash of the ledger. This will be all-bits-zero if not found. */ LedgerHash - getHash( - LedgerIndex const& ledgerIndex, - std::shared_ptr& referenceLedger) + getHash(LedgerIndex const& ledgerIndex, std::shared_ptr& referenceLedger) { LedgerHash ledgerHash; @@ -337,17 +318,15 @@ private: LedgerHash refHash = getLedgerHash(referenceLedger, refIndex); bool const nonzero(refHash.isNonZero()); - XRPL_ASSERT( - nonzero, "xrpl::LedgerCleanerImp::getHash : nonzero hash"); + XRPL_ASSERT(nonzero, "xrpl::LedgerCleanerImp::getHash : nonzero hash"); if (nonzero) { // We found the hash and sequence of a better reference // ledger. - referenceLedger = app_.getInboundLedgers().acquire( - refHash, refIndex, InboundLedger::Reason::GENERIC); + referenceLedger = + app_.getInboundLedgers().acquire(refHash, refIndex, InboundLedger::Reason::GENERIC); if (referenceLedger) - ledgerHash = - getLedgerHash(referenceLedger, ledgerIndex); + ledgerHash = getLedgerHash(referenceLedger, ledgerIndex); } } } @@ -384,8 +363,7 @@ private: { std::lock_guard lock(mutex_); - if ((minRange_ > maxRange_) || (maxRange_ == 0) || - (minRange_ == 0)) + if ((minRange_ > maxRange_) || (maxRange_ == 0) || (minRange_ == 0)) { minRange_ = maxRange_ = 0; return; @@ -400,8 +378,7 @@ private: bool fail = false; if (ledgerHash.isZero()) { - JLOG(j_.info()) - << "Unable to get hash for ledger " << ledgerIndex; + JLOG(j_.info()) << "Unable to get hash for ledger " << ledgerIndex; fail = true; } else if (!doLedger(ledgerIndex, ledgerHash, doNodes, doTxns)) diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp index 6909c45328..f06beda768 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp @@ -20,9 +20,7 @@ LedgerDeltaAcquire::LedgerDeltaAcquire( app, ledgerHash, LedgerReplayParameters::SUB_TASK_TIMEOUT, - {jtREPLAY_TASK, - "LedReplDelta", - LedgerReplayParameters::MAX_QUEUED_TASKS}, + {jtREPLAY_TASK, "LedReplDelta", LedgerReplayParameters::MAX_QUEUED_TASKS}, app.journal("LedgerReplayDelta")) , inboundLedgers_(inboundLedgers) , ledgerSeq_(ledgerSeq) @@ -64,26 +62,22 @@ LedgerDeltaAcquire::trigger(std::size_t limit, ScopedLockType& sl) peerSet_->addPeers( limit, [this](auto peer) { - return peer->supportsFeature(ProtocolFeature::LedgerReplay) && - peer->hasLedger(hash_, ledgerSeq_); + return peer->supportsFeature(ProtocolFeature::LedgerReplay) && peer->hasLedger(hash_, ledgerSeq_); }, [this](auto peer) { if (peer->supportsFeature(ProtocolFeature::LedgerReplay)) { - JLOG(journal_.trace()) - << "Add a peer " << peer->id() << " for " << hash_; + JLOG(journal_.trace()) << "Add a peer " << peer->id() << " for " << hash_; protocol::TMReplayDeltaRequest request; request.set_ledgerhash(hash_.data(), hash_.size()); peerSet_->sendRequest(request, peer); } else { - if (++noFeaturePeerCount >= - LedgerReplayParameters::MAX_NO_FEATURE_PEER_COUNT) + if (++noFeaturePeerCount >= LedgerReplayParameters::MAX_NO_FEATURE_PEER_COUNT) { JLOG(journal_.debug()) << "Fall back for " << hash_; - timerInterval_ = - LedgerReplayParameters::SUB_TASK_FALLBACK_TIMEOUT; + timerInterval_ = LedgerReplayParameters::SUB_TASK_FALLBACK_TIMEOUT; fallBack_ = true; } } @@ -91,8 +85,7 @@ LedgerDeltaAcquire::trigger(std::size_t limit, ScopedLockType& sl) } if (fallBack_) - inboundLedgers_.acquire( - hash_, ledgerSeq_, InboundLedger::Reason::GENERIC); + inboundLedgers_.acquire(hash_, ledgerSeq_, InboundLedger::Reason::GENERIC); } void @@ -130,8 +123,7 @@ LedgerDeltaAcquire::processData( if (info.seq == ledgerSeq_) { // create a temporary ledger for building a LedgerReplay object later - replayTemp_ = - std::make_shared(info, app_.config(), app_.getNodeFamily()); + replayTemp_ = std::make_shared(info, app_.config(), app_.getNodeFamily()); if (replayTemp_) { complete_ = true; @@ -143,15 +135,12 @@ LedgerDeltaAcquire::processData( } failed_ = true; - JLOG(journal_.error()) - << "failed to create a (info only) ledger from verified data " << hash_; + JLOG(journal_.error()) << "failed to create a (info only) ledger from verified data " << hash_; notify(sl); } void -LedgerDeltaAcquire::addDataCallback( - InboundLedger::Reason reason, - OnDeltaDataCB&& cb) +LedgerDeltaAcquire::addDataCallback(InboundLedger::Reason reason, OnDeltaDataCB&& cb) { ScopedLockType sl(mtx_); dataReadyCallbacks_.emplace_back(std::move(cb)); @@ -164,8 +153,7 @@ LedgerDeltaAcquire::addDataCallback( if (isDone()) { - JLOG(journal_.debug()) - << "task added to a finished LedgerDeltaAcquire " << hash_; + JLOG(journal_.debug()) << "task added to a finished LedgerDeltaAcquire " << hash_; notify(sl); } } @@ -181,9 +169,7 @@ LedgerDeltaAcquire::tryBuild(std::shared_ptr const& parent) if (failed_ || !complete_ || !replayTemp_) return {}; - XRPL_ASSERT( - parent->seq() + 1 == replayTemp_->seq(), - "xrpl::LedgerDeltaAcquire::tryBuild : parent sequence match"); + XRPL_ASSERT(parent->seq() + 1 == replayTemp_->seq(), "xrpl::LedgerDeltaAcquire::tryBuild : parent sequence match"); XRPL_ASSERT( parent->header().hash == replayTemp_->header().parentHash, "xrpl::LedgerDeltaAcquire::tryBuild : parent hash match"); @@ -200,22 +186,17 @@ LedgerDeltaAcquire::tryBuild(std::shared_ptr const& parent) { failed_ = true; complete_ = false; - JLOG(journal_.error()) << "tryBuild failed " << hash_ << " with parent " - << parent->header().hash; + JLOG(journal_.error()) << "tryBuild failed " << hash_ << " with parent " << parent->header().hash; Throw("Cannot replay ledger"); } } void -LedgerDeltaAcquire::onLedgerBuilt( - ScopedLockType& sl, - std::optional reason) +LedgerDeltaAcquire::onLedgerBuilt(ScopedLockType& sl, std::optional reason) { - JLOG(journal_.debug()) << "onLedgerBuilt " << hash_ - << (reason ? " for a new reason" : ""); + JLOG(journal_.debug()) << "onLedgerBuilt " << hash_ << (reason ? " for a new reason" : ""); - std::vector reasons( - reasons_.begin(), reasons_.end()); + std::vector reasons(reasons_.begin(), reasons_.end()); bool firstTime = true; if (reason) // small chance { @@ -223,26 +204,23 @@ LedgerDeltaAcquire::onLedgerBuilt( reasons.push_back(*reason); firstTime = false; } - app_.getJobQueue().addJob( - jtREPLAY_TASK, - "OnLedBuilt", - [=, ledger = this->fullLedger_, &app = this->app_]() { - for (auto reason : reasons) + app_.getJobQueue().addJob(jtREPLAY_TASK, "OnLedBuilt", [=, ledger = this->fullLedger_, &app = this->app_]() { + for (auto reason : reasons) + { + switch (reason) { - switch (reason) - { - case InboundLedger::Reason::GENERIC: - app.getLedgerMaster().storeLedger(ledger); - break; - default: - // TODO for other use cases - break; - } + case InboundLedger::Reason::GENERIC: + app.getLedgerMaster().storeLedger(ledger); + break; + default: + // TODO for other use cases + break; } + } - if (firstTime) - app.getLedgerMaster().tryAdvance(); - }); + if (firstTime) + app.getLedgerMaster().tryAdvance(); + }); } void diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h index 779bbfa85e..7b4d478c13 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.h @@ -22,10 +22,9 @@ class LedgerReplayClient; * from the network. Before asking peers, always check if the local * node has the ledger. */ -class LedgerDeltaAcquire final - : public TimeoutCounter, - public std::enable_shared_from_this, - public CountedObject +class LedgerDeltaAcquire final : public TimeoutCounter, + public std::enable_shared_from_this, + public CountedObject { public: /** @@ -33,8 +32,7 @@ public: * @param successful if the ledger delta data was acquired successfully * @param hash hash of the ledger to build */ - using OnDeltaDataCB = - std::function; + using OnDeltaDataCB = std::function; /** * Constructor @@ -68,9 +66,7 @@ public: * @note info and Txns must have been verified against the ledger hash */ void - processData( - LedgerHeader const& info, - std::map>&& orderedTxns); + processData(LedgerHeader const& info, std::map>&& orderedTxns); /** * Try to build the ledger if not already @@ -116,9 +112,7 @@ private: * is added. */ void - onLedgerBuilt( - ScopedLockType& sl, - std::optional reason = {}); + onLedgerBuilt(ScopedLockType& sl, std::optional reason = {}); /** * Call the OnDeltaDataCB callbacks diff --git a/src/xrpld/app/ledger/detail/LedgerMaster.cpp b/src/xrpld/app/ledger/detail/LedgerMaster.cpp index 65421c9bd8..c4299c1b63 100644 --- a/src/xrpld/app/ledger/detail/LedgerMaster.cpp +++ b/src/xrpld/app/ledger/detail/LedgerMaster.cpp @@ -72,8 +72,7 @@ shouldAcquire( return minimumOnline.has_value() && candidateLedger >= *minimumOnline; }(); - JLOG(j.trace()) << "Missing ledger " << candidateLedger - << (ret ? " should" : " should NOT") << " be acquired"; + JLOG(j.trace()) << "Missing ledger " << candidateLedger << (ret ? " should" : " should NOT") << " be acquired"; return ret; } @@ -86,16 +85,10 @@ LedgerMaster::LedgerMaster( , m_journal(journal) , mLedgerHistory(collector, app) , standalone_(app_.config().standalone()) - , fetch_depth_( - app_.getSHAMapStore().clampFetchDepth(app_.config().FETCH_DEPTH)) + , fetch_depth_(app_.getSHAMapStore().clampFetchDepth(app_.config().FETCH_DEPTH)) , ledger_history_(app_.config().LEDGER_HISTORY) , ledger_fetch_size_(app_.config().getValueFor(SizedItem::ledgerFetch)) - , fetch_packs_( - "FetchPack", - 65536, - std::chrono::seconds{45}, - stopwatch, - app_.journal("TaggedCache")) + , fetch_packs_("FetchPack", 65536, std::chrono::seconds{45}, stopwatch, app_.journal("TaggedCache")) , m_stats(std::bind(&LedgerMaster::collect_metrics, this), collector) { } @@ -113,10 +106,7 @@ LedgerMaster::getValidLedgerIndex() } bool -LedgerMaster::isCompatible( - ReadView const& view, - beast::Journal::Stream s, - char const* reason) +LedgerMaster::isCompatible(ReadView const& view, beast::Journal::Stream s, char const* reason) { auto validLedger = getValidatedLedger(); @@ -129,12 +119,7 @@ LedgerMaster::isCompatible( std::lock_guard sl(m_mutex); if ((mLastValidLedger.second != 0) && - !areCompatible( - mLastValidLedger.first, - mLastValidLedger.second, - view, - s, - reason)) + !areCompatible(mLastValidLedger.first, mLastValidLedger.second, view, s, reason)) { return false; } @@ -226,8 +211,7 @@ LedgerMaster::setValidLedger(std::shared_ptr const& l) if (!standalone_) { auto validations = app_.validators().negativeUNLFilter( - app_.getValidations().getTrustedForLedger( - l->header().hash, l->header().seq)); + app_.getValidations().getTrustedForLedger(l->header().hash, l->header().seq)); times.reserve(validations.size()); for (auto const& val : validations) times.push_back(val->getSignTime()); @@ -255,8 +239,7 @@ LedgerMaster::setValidLedger(std::shared_ptr const& l) mValidLedgerSign = signTime.time_since_epoch().count(); XRPL_ASSERT( mValidLedgerSeq || !app_.getMaxDisallowedLedger() || - l->header().seq + max_ledger_difference_ > - app_.getMaxDisallowedLedger(), + l->header().seq + max_ledger_difference_ > app_.getMaxDisallowedLedger(), "xrpl::LedgerMaster::setValidLedger : valid ledger sequence"); (void)max_ledger_difference_; mValidLedgerSeq = l->header().seq; @@ -284,8 +267,7 @@ LedgerMaster::setValidLedger(std::shared_ptr const& l) // this message may be logged more than once per session, because // the node will otherwise function normally, and this gives // operators an opportunity to see and resolve the warning. - if (auto const first = - app_.getAmendmentTable().firstUnsupportedExpected()) + if (auto const first = app_.getAmendmentTable().firstUnsupportedExpected()) { JLOG(m_journal.error()) << "One or more unsupported amendments " "reached majority. Upgrade before " @@ -309,8 +291,7 @@ LedgerMaster::setPubLedger(std::shared_ptr const& l) } void -LedgerMaster::addHeldTransaction( - std::shared_ptr const& transaction) +LedgerMaster::addHeldTransaction(std::shared_ptr const& transaction) { std::lock_guard ml(m_mutex); mHeldTransactions.insert(transaction->getSTransaction()); @@ -330,9 +311,8 @@ LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) auto validLedger = getValidatedLedger(); if (validLedger && (ledger->header().seq < validLedger->header().seq)) { - JLOG(m_journal.trace()) - << "Candidate for current ledger has low seq " - << ledger->header().seq << " < " << validLedger->header().seq; + JLOG(m_journal.trace()) << "Candidate for current ledger has low seq " << ledger->header().seq << " < " + << validLedger->header().seq; return false; } @@ -346,13 +326,10 @@ LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) using namespace std::chrono_literals; if ((validLedger || (ledger->header().seq > 10)) && - ((std::max(closeTime, ledgerClose) - std::min(closeTime, ledgerClose)) > - 5min)) + ((std::max(closeTime, ledgerClose) - std::min(closeTime, ledgerClose)) > 5min)) { - JLOG(m_journal.warn()) - << "Candidate for current ledger has close time " - << to_string(ledgerClose) << " at network time " - << to_string(closeTime) << " seq " << ledger->header().seq; + JLOG(m_journal.warn()) << "Candidate for current ledger has close time " << to_string(ledgerClose) + << " at network time " << to_string(closeTime) << " seq " << ledger->header().seq; return false; } @@ -366,22 +343,20 @@ LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) LedgerIndex maxSeq = validLedger->header().seq + 10; if (closeTime > validLedger->header().parentCloseTime) - maxSeq += std::chrono::duration_cast( - closeTime - validLedger->header().parentCloseTime) - .count() / + maxSeq += + std::chrono::duration_cast(closeTime - validLedger->header().parentCloseTime) + .count() / 2; if (ledger->header().seq > maxSeq) { - JLOG(m_journal.warn()) - << "Candidate for current ledger has high seq " - << ledger->header().seq << " > " << maxSeq; + JLOG(m_journal.warn()) << "Candidate for current ledger has high seq " << ledger->header().seq << " > " + << maxSeq; return false; } - JLOG(m_journal.trace()) - << "Acceptable seq range: " << validLedger->header().seq - << " <= " << ledger->header().seq << " <= " << maxSeq; + JLOG(m_journal.trace()) << "Acceptable seq range: " << validLedger->header().seq + << " <= " << ledger->header().seq << " <= " << maxSeq; } return true; @@ -498,11 +473,8 @@ LedgerMaster::isValidated(ReadView const& ledger) // This ledger's hash is not the hash of the validated ledger if (hash) { - XRPL_ASSERT( - hash->isNonZero(), - "xrpl::LedgerMaster::isValidated : nonzero hash"); - uint256 valHash = - app_.getRelationalDatabase().getHashByIndex(seq); + XRPL_ASSERT(hash->isNonZero(), "xrpl::LedgerMaster::isValidated : nonzero hash"); + uint256 valHash = app_.getRelationalDatabase().getHashByIndex(seq); if (valHash == ledger.header().hash) { // SQL database doesn't match ledger chain @@ -525,9 +497,7 @@ LedgerMaster::isValidated(ReadView const& ledger) // returns Ledgers we have all the nodes for bool -LedgerMaster::getFullValidatedRange( - std::uint32_t& minVal, - std::uint32_t& maxVal) +LedgerMaster::getFullValidatedRange(std::uint32_t& minVal, std::uint32_t& maxVal) { // Validated ledger is likely not stored in the DB yet so we use the // published ledger which is. @@ -641,20 +611,16 @@ LedgerMaster::tryFill(std::shared_ptr ledger) mCompleteLedgers.insert(range(minHas, maxHas)); } maxHas = minHas; - ledgerHashes = app_.getRelationalDatabase().getHashesByIndex( - (seq < 500) ? 0 : (seq - 499), seq); + ledgerHashes = app_.getRelationalDatabase().getHashesByIndex((seq < 500) ? 0 : (seq - 499), seq); it = ledgerHashes.find(seq); if (it == ledgerHashes.end()) break; - if (!nodeStore.fetchNodeObject( - ledgerHashes.begin()->second.ledgerHash, - ledgerHashes.begin()->first)) + if (!nodeStore.fetchNodeObject(ledgerHashes.begin()->second.ledgerHash, ledgerHashes.begin()->first)) { // The ledger is not backed by the node store - JLOG(m_journal.warn()) << "SQL DB ledger sequence " << seq - << " mismatches node store"; + JLOG(m_journal.warn()) << "SQL DB ledger sequence " << seq << " mismatches node store"; break; } } @@ -686,8 +652,7 @@ LedgerMaster::getFetchPack(LedgerIndex missing, InboundLedger::Reason reason) auto const haveHash{getLedgerHashForHistory(ledgerIndex, reason)}; if (!haveHash || haveHash->isZero()) { - JLOG(m_journal.error()) - << "No hash for fetch pack. Missing Index " << missing; + JLOG(m_journal.error()) << "No hash for fetch pack. Missing Index " << missing; return; } @@ -742,9 +707,7 @@ LedgerMaster::fixMismatch(ReadView const& ledger) } catch (std::exception const& ex) { - JLOG(m_journal.warn()) - << "fixMismatch encounters partial ledger. Exception: " - << ex.what(); + JLOG(m_journal.warn()) << "fixMismatch encounters partial ledger. Exception: " << ex.what(); clearLedger(lSeq); return; } @@ -760,8 +723,7 @@ LedgerMaster::fixMismatch(ReadView const& ledger) if (invalidate != 0) { JLOG(m_journal.warn()) - << "Match at " << lSeq << ", " << invalidate - << " prior ledgers invalidated"; + << "Match at " << lSeq << ", " << invalidate << " prior ledgers invalidated"; } return; @@ -776,23 +738,17 @@ LedgerMaster::fixMismatch(ReadView const& ledger) // all prior ledgers invalidated if (invalidate != 0) { - JLOG(m_journal.warn()) - << "All " << invalidate << " prior ledgers invalidated"; + JLOG(m_journal.warn()) << "All " << invalidate << " prior ledgers invalidated"; } } void -LedgerMaster::setFullLedger( - std::shared_ptr const& ledger, - bool isSynchronous, - bool isCurrent) +LedgerMaster::setFullLedger(std::shared_ptr const& ledger, bool isSynchronous, bool isCurrent) { // A new ledger has been accepted as part of the trusted chain - JLOG(m_journal.debug()) << "Ledger " << ledger->header().seq - << " accepted :" << ledger->header().hash; + JLOG(m_journal.debug()) << "Ledger " << ledger->header().seq << " accepted :" << ledger->header().hash; XRPL_ASSERT( - ledger->stateMap().getHash().isNonZero(), - "xrpl::LedgerMaster::setFullLedger : nonzero ledger state hash"); + ledger->stateMap().getHash().isNonZero(), "xrpl::LedgerMaster::setFullLedger : nonzero ledger state hash"); ledger->setValidated(); ledger->setFull(); @@ -803,8 +759,7 @@ LedgerMaster::setFullLedger( { // Check the SQL database's entry for the sequence before this // ledger, if it's not this ledger's parent, invalidate it - uint256 prevHash = app_.getRelationalDatabase().getHashByIndex( - ledger->header().seq - 1); + uint256 prevHash = app_.getRelationalDatabase().getHashByIndex(ledger->header().seq - 1); if (prevHash.isNonZero() && prevHash != ledger->header().parentHash) clearLedger(ledger->header().seq - 1); } @@ -832,12 +787,10 @@ LedgerMaster::setFullLedger( // we think we have the previous ledger, double check auto prevLedger = getLedgerBySeq(ledger->header().seq - 1); - if (!prevLedger || - (prevLedger->header().hash != ledger->header().parentHash)) + if (!prevLedger || (prevLedger->header().hash != ledger->header().parentHash)) { - JLOG(m_journal.warn()) - << "Acquired ledger invalidates previous ledger: " - << (prevLedger ? "hashMismatch" : "missingLedger"); + JLOG(m_journal.warn()) << "Acquired ledger invalidates previous ledger: " + << (prevLedger ? "hashMismatch" : "missingLedger"); fixMismatch(*ledger); } } @@ -864,8 +817,7 @@ LedgerMaster::checkAccept(uint256 const& hash, std::uint32_t seq) if (seq < mValidLedgerSeq) return; - auto validations = app_.validators().negativeUNLFilter( - app_.getValidations().getTrustedForLedger(hash, seq)); + auto validations = app_.validators().negativeUNLFilter(app_.getValidations().getTrustedForLedger(hash, seq)); valCount = validations.size(); if (valCount >= app_.validators().quorum()) { @@ -895,8 +847,7 @@ LedgerMaster::checkAccept(uint256 const& hash, std::uint32_t seq) // FIXME: We may not want to fetch a ledger with just one // trusted validation - ledger = app_.getInboundLedgers().acquire( - hash, seq, InboundLedger::Reason::GENERIC); + ledger = app_.getInboundLedgers().acquire(hash, seq, InboundLedger::Reason::GENERIC); } if (ledger) @@ -931,18 +882,15 @@ LedgerMaster::checkAccept(std::shared_ptr const& ledger) auto const minVal = getNeededValidations(); auto validations = app_.validators().negativeUNLFilter( - app_.getValidations().getTrustedForLedger( - ledger->header().hash, ledger->header().seq)); + app_.getValidations().getTrustedForLedger(ledger->header().hash, ledger->header().seq)); auto const tvc = validations.size(); if (tvc < minVal) // nothing we can do { - JLOG(m_journal.trace()) - << "Only " << tvc << " validations for " << ledger->header().hash; + JLOG(m_journal.trace()) << "Only " << tvc << " validations for " << ledger->header().hash; return; } - JLOG(m_journal.info()) << "Advancing accepted ledger to " - << ledger->header().seq << " with >= " << minVal + JLOG(m_journal.info()) << "Advancing accepted ledger to " << ledger->header().seq << " with >= " << minVal << " validations"; ledger->setValidated(); @@ -958,8 +906,7 @@ LedgerMaster::checkAccept(std::shared_ptr const& ledger) std::uint32_t const base = app_.getFeeTrack().getLoadBase(); auto fees = app_.getValidations().fees(ledger->header().hash, base); { - auto fees2 = - app_.getValidations().fees(ledger->header().parentHash, base); + auto fees2 = app_.getValidations().fees(ledger->header().parentHash, base); fees.reserve(fees.size() + fees2.size()); std::copy(fees2.begin(), fees2.end(), std::back_inserter(fees)); } @@ -1006,8 +953,8 @@ LedgerMaster::checkAccept(std::shared_ptr const& ledger) if (upgradeWarningPrevTime_ == TimeKeeper::time_point()) { // Have not printed the warning before, check if need to print. - auto const vals = app_.getValidations().getTrustedForLedger( - ledger->header().parentHash, ledger->header().seq - 1); + auto const vals = + app_.getValidations().getTrustedForLedger(ledger->header().parentHash, ledger->header().seq - 1); std::size_t higherVersionCount = 0; std::size_t rippledCount = 0; for (auto const& v : vals) @@ -1015,10 +962,8 @@ LedgerMaster::checkAccept(std::shared_ptr const& ledger) if (v->isFieldPresent(sfServerVersion)) { auto version = v->getFieldU64(sfServerVersion); - higherVersionCount += - BuildInfo::isNewerVersion(version) ? 1 : 0; - rippledCount += - BuildInfo::isRippledVersion(version) ? 1 : 0; + higherVersionCount += BuildInfo::isNewerVersion(version) ? 1 : 0; + rippledCount += BuildInfo::isRippledVersion(version) ? 1 : 0; } } // We report only if (1) we have accumulated validation messages @@ -1029,13 +974,9 @@ LedgerMaster::checkAccept(std::shared_ptr const& ledger) { constexpr std::size_t reportingPercent = 90; constexpr std::size_t cutoffPercent = 60; - auto const unlSize{ - app_.validators().getQuorumKeys().second.size()}; - needPrint = unlSize > 0 && - calculatePercent(vals.size(), unlSize) >= - reportingPercent && - calculatePercent(higherVersionCount, rippledCount) >= - cutoffPercent; + auto const unlSize{app_.validators().getQuorumKeys().second.size()}; + needPrint = unlSize > 0 && calculatePercent(vals.size(), unlSize) >= reportingPercent && + calculatePercent(higherVersionCount, rippledCount) >= cutoffPercent; } } // To throttle the warning messages, instead of printing a warning @@ -1080,8 +1021,7 @@ LedgerMaster::consensusBuilt( if (ledger->header().seq <= mValidLedgerSeq) { auto stream = app_.journal("LedgerConsensus").info(); - JLOG(stream) << "Consensus built old ledger: " << ledger->header().seq - << " <= " << mValidLedgerSeq; + JLOG(stream) << "Consensus built old ledger: " << ledger->header().seq << " <= " << mValidLedgerSeq; return; } @@ -1098,8 +1038,7 @@ LedgerMaster::consensusBuilt( // This ledger cannot be the new fully-validated ledger, but // maybe we saved up validations for some other ledger that can be - auto validations = app_.validators().negativeUNLFilter( - app_.getValidations().currentTrusted()); + auto validations = app_.validators().negativeUNLFilter(app_.getValidations().currentTrusted()); // Track validation counts with sequence numbers class valSeq @@ -1164,9 +1103,7 @@ LedgerMaster::consensusBuilt( } std::optional -LedgerMaster::getLedgerHashForHistory( - LedgerIndex index, - InboundLedger::Reason reason) +LedgerMaster::getLedgerHashForHistory(LedgerIndex index, InboundLedger::Reason reason) { // Try to get the hash of a ledger we need to fetch for history std::optional ret; @@ -1186,8 +1123,7 @@ LedgerMaster::getLedgerHashForHistory( } std::vector> -LedgerMaster::findNewLedgersToPublish( - std::unique_lock& sl) +LedgerMaster::findNewLedgersToPublish(std::unique_lock& sl) { std::vector> ret; @@ -1202,15 +1138,13 @@ LedgerMaster::findNewLedgersToPublish( if (!mPubLedger) { - JLOG(m_journal.info()) - << "First published ledger will be " << mValidLedgerSeq; + JLOG(m_journal.info()) << "First published ledger will be " << mValidLedgerSeq; return {mValidLedger.get()}; } if (mValidLedgerSeq > (mPubLedgerSeq + MAX_LEDGER_GAP)) { - JLOG(m_journal.warn()) << "Gap in validated ledger stream " - << mPubLedgerSeq << " - " << mValidLedgerSeq - 1; + JLOG(m_journal.warn()) << "Gap in validated ledger stream " << mPubLedgerSeq << " - " << mValidLedgerSeq - 1; auto valLedger = mValidLedger.get(); ret.push_back(valLedger); @@ -1237,8 +1171,7 @@ LedgerMaster::findNewLedgersToPublish( { for (std::uint32_t seq = pubSeq; seq <= valSeq; ++seq) { - JLOG(m_journal.trace()) - << "Trying to fetch/publish valid ledger " << seq; + JLOG(m_journal.trace()) << "Trying to fetch/publish valid ledger " << seq; std::shared_ptr ledger; // This can throw @@ -1255,8 +1188,7 @@ LedgerMaster::findNewLedgersToPublish( else if (hash->isZero()) { // LCOV_EXCL_START - JLOG(m_journal.fatal()) << "Ledger: " << valSeq - << " does not have hash for " << seq; + JLOG(m_journal.fatal()) << "Ledger: " << valSeq << " does not have hash for " << seq; UNREACHABLE( "xrpl::LedgerMaster::findNewLedgersToPublish : ledger " "not found"); @@ -1271,8 +1203,7 @@ LedgerMaster::findNewLedgersToPublish( { // Can we try to acquire the ledger we need? if (!ledger && (++acqCount < ledger_fetch_size_)) - ledger = app_.getInboundLedgers().acquire( - *hash, seq, InboundLedger::Reason::GENERIC); + ledger = app_.getInboundLedgers().acquire(*hash, seq, InboundLedger::Reason::GENERIC); } // Did we acquire the next ledger we need to publish? @@ -1284,14 +1215,11 @@ LedgerMaster::findNewLedgersToPublish( } } - JLOG(m_journal.trace()) - << "ready to publish " << ret.size() << " ledgers."; + JLOG(m_journal.trace()) << "ready to publish " << ret.size() << " ledgers."; } catch (std::exception const& ex) { - JLOG(m_journal.error()) - << "Exception while trying to find ledgers to publish: " - << ex.what(); + JLOG(m_journal.error()) << "Exception while trying to find ledgers to publish: " << ex.what(); } if (app_.config().LEDGER_REPLAY) @@ -1306,26 +1234,19 @@ LedgerMaster::findNewLedgersToPublish( auto finishLedger = valLedger; while (startLedger->seq() + 1 < finishLedger->seq()) { - if (auto const parent = mLedgerHistory.getLedgerByHash( - finishLedger->header().parentHash); - parent) + if (auto const parent = mLedgerHistory.getLedgerByHash(finishLedger->header().parentHash); parent) { finishLedger = parent; } else { - auto numberLedgers = - finishLedger->seq() - startLedger->seq() + 1; - JLOG(m_journal.debug()) - << "Publish LedgerReplays " << numberLedgers - << " ledgers, from seq=" << startLedger->header().seq - << ", " << startLedger->header().hash - << " to seq=" << finishLedger->header().seq << ", " - << finishLedger->header().hash; + auto numberLedgers = finishLedger->seq() - startLedger->seq() + 1; + JLOG(m_journal.debug()) << "Publish LedgerReplays " << numberLedgers + << " ledgers, from seq=" << startLedger->header().seq << ", " + << startLedger->header().hash << " to seq=" << finishLedger->header().seq + << ", " << finishLedger->header().hash; app_.getLedgerReplayer().replay( - InboundLedger::Reason::GENERIC, - finishLedger->header().hash, - numberLedgers); + InboundLedger::Reason::GENERIC, finishLedger->header().hash, numberLedgers); break; } } @@ -1347,9 +1268,7 @@ LedgerMaster::tryAdvance() app_.getJobQueue().addJob(jtADVANCE, "AdvanceLedger", [this]() { std::unique_lock sl(m_mutex); - XRPL_ASSERT( - !mValidLedger.empty() && mAdvanceThread, - "xrpl::LedgerMaster::tryAdvance : has valid ledger"); + XRPL_ASSERT(!mValidLedger.empty() && mAdvanceThread, "xrpl::LedgerMaster::tryAdvance : has valid ledger"); JLOG(m_journal.trace()) << "advanceThread<"; @@ -1389,9 +1308,7 @@ LedgerMaster::updatePaths() { std::lock_guard ml(m_mutex); - if (!mValidLedger.empty() && - (!mPathLedger || - (mPathLedger->header().seq != mValidLedgerSeq))) + if (!mValidLedger.empty() && (!mPathLedger || (mPathLedger->header().seq != mValidLedgerSeq))) { // We have a new valid ledger since the last full pathfinding mPathLedger = mValidLedger.get(); lastLedger = mPathLedger; @@ -1412,12 +1329,10 @@ LedgerMaster::updatePaths() if (!standalone_) { // don't pathfind with a ledger that's more than 60 seconds old using namespace std::chrono; - auto age = time_point_cast(app_.timeKeeper().closeTime()) - - lastLedger->header().closeTime; + auto age = time_point_cast(app_.timeKeeper().closeTime()) - lastLedger->header().closeTime; if (age > 1min) { - JLOG(m_journal.debug()) - << "Published ledger too old for updating paths"; + JLOG(m_journal.debug()) << "Published ledger too old for updating paths"; std::lock_guard ml(m_mutex); --mPathFindThread; mPathLedger.reset(); @@ -1434,10 +1349,9 @@ LedgerMaster::updatePaths() { --mPathFindThread; mPathLedger.reset(); - JLOG(m_journal.debug()) - << "No path requests found. Nothing to do for updating " - "paths. " - << mPathFindThread << " jobs remaining"; + JLOG(m_journal.debug()) << "No path requests found. Nothing to do for updating " + "paths. " + << mPathFindThread << " jobs remaining"; return; } } @@ -1447,9 +1361,8 @@ LedgerMaster::updatePaths() std::lock_guard ml(m_mutex); if (!pathRequests.requestsPending()) { - JLOG(m_journal.debug()) - << "No path requests left. No need for further updating " - "paths"; + JLOG(m_journal.debug()) << "No path requests left. No need for further updating " + "paths"; --mPathFindThread; mPathLedger.reset(); return; @@ -1462,17 +1375,13 @@ LedgerMaster::updatePaths() { // our parent is the problem app_.getInboundLedgers().acquire( - lastLedger->header().parentHash, - lastLedger->header().seq - 1, - InboundLedger::Reason::GENERIC); + lastLedger->header().parentHash, lastLedger->header().seq - 1, InboundLedger::Reason::GENERIC); } else { // this ledger is the problem app_.getInboundLedgers().acquire( - lastLedger->header().hash, - lastLedger->header().seq, - InboundLedger::Reason::GENERIC); + lastLedger->header().hash, lastLedger->header().seq, InboundLedger::Reason::GENERIC); } } } @@ -1509,18 +1418,12 @@ LedgerMaster::newOrderBookDB() /** A thread needs to be dispatched to handle pathfinding work of some kind. */ bool -LedgerMaster::newPFWork( - char const* name, - std::unique_lock&) +LedgerMaster::newPFWork(char const* name, std::unique_lock&) { - if (!app_.isStopping() && mPathFindThread < 2 && - app_.getPathRequests().requestsPending()) + if (!app_.isStopping() && mPathFindThread < 2 && app_.getPathRequests().requestsPending()) { - JLOG(m_journal.debug()) - << "newPFWork: Creating job. path find threads: " - << mPathFindThread; - if (app_.getJobQueue().addJob( - jtUPDATE_PF, name, [this]() { updatePaths(); })) + JLOG(m_journal.debug()) << "newPFWork: Creating job. path find threads: " << mPathFindThread; + if (app_.getJobQueue().addJob(jtUPDATE_PF, name, [this]() { updatePaths(); })) { ++mPathFindThread; } @@ -1582,20 +1485,16 @@ std::optional LedgerMaster::getCloseTimeBySeq(LedgerIndex ledgerIndex) { uint256 hash = getHashBySeq(ledgerIndex); - return hash.isNonZero() ? getCloseTimeByHash(hash, ledgerIndex) - : std::nullopt; + return hash.isNonZero() ? getCloseTimeByHash(hash, ledgerIndex) : std::nullopt; } std::optional -LedgerMaster::getCloseTimeByHash( - LedgerHash const& ledgerHash, - std::uint32_t index) +LedgerMaster::getCloseTimeByHash(LedgerHash const& ledgerHash, std::uint32_t index) { auto nodeObject = app_.getNodeStore().fetchNodeObject(ledgerHash, index); if (nodeObject && (nodeObject->getData().size() >= 120)) { - SerialIter it( - nodeObject->getData().data(), nodeObject->getData().size()); + SerialIter it(nodeObject->getData().data(), nodeObject->getData().size()); if (safe_cast(it.get32()) == HashPrefix::ledgerMaster) { it.skip( @@ -1672,8 +1571,7 @@ LedgerMaster::walkHashBySeq( // Try to acquire the complete ledger if (!ledger) { - if (auto const l = app_.getInboundLedgers().acquire( - *refHash, refIndex, reason)) + if (auto const l = app_.getInboundLedgers().acquire(*refHash, refIndex, reason)) { ledgerHash = hashOfSeq(*l, index, m_journal); XRPL_ASSERT( @@ -1791,38 +1689,29 @@ LedgerMaster::fetchForHistory( scope_unlock sul{sl}; if (auto hash = getLedgerHashForHistory(missing, reason)) { - XRPL_ASSERT( - hash->isNonZero(), - "xrpl::LedgerMaster::fetchForHistory : found ledger"); + XRPL_ASSERT(hash->isNonZero(), "xrpl::LedgerMaster::fetchForHistory : found ledger"); auto ledger = getLedgerByHash(*hash); if (!ledger) { if (!app_.getInboundLedgers().isFailure(*hash)) { - ledger = - app_.getInboundLedgers().acquire(*hash, missing, reason); - if (!ledger && missing != fetch_seq_ && - missing > app_.getNodeStore().earliestLedgerSeq()) + ledger = app_.getInboundLedgers().acquire(*hash, missing, reason); + if (!ledger && missing != fetch_seq_ && missing > app_.getNodeStore().earliestLedgerSeq()) { - JLOG(m_journal.trace()) - << "fetchForHistory want fetch pack " << missing; + JLOG(m_journal.trace()) << "fetchForHistory want fetch pack " << missing; fetch_seq_ = missing; getFetchPack(missing, reason); } else - JLOG(m_journal.trace()) - << "fetchForHistory no fetch pack for " << missing; + JLOG(m_journal.trace()) << "fetchForHistory no fetch pack for " << missing; } else - JLOG(m_journal.debug()) - << "fetchForHistory found failed acquire"; + JLOG(m_journal.debug()) << "fetchForHistory found failed acquire"; } if (ledger) { auto seq = ledger->header().seq; - XRPL_ASSERT( - seq == missing, - "xrpl::LedgerMaster::fetchForHistory : sequence match"); + XRPL_ASSERT(seq == missing, "xrpl::LedgerMaster::fetchForHistory : sequence match"); JLOG(m_journal.trace()) << "fetchForHistory acquired " << seq; setFullLedger(ledger, false, false); int fillInProgress; @@ -1832,18 +1721,14 @@ LedgerMaster::fetchForHistory( fillInProgress = mFillInProgress; } if (fillInProgress == 0 && - app_.getRelationalDatabase().getHashByIndex(seq - 1) == - ledger->header().parentHash) + app_.getRelationalDatabase().getHashByIndex(seq - 1) == ledger->header().parentHash) { { // Previous ledger is in DB std::lock_guard lock(m_mutex); mFillInProgress = seq; } - app_.getJobQueue().addJob( - jtADVANCE, "TryFill", [this, ledger]() { - tryFill(ledger); - }); + app_.getJobQueue().addJob(jtADVANCE, "TryFill", [this, ledger]() { tryFill(ledger); }); } progress = true; } @@ -1853,9 +1738,7 @@ LedgerMaster::fetchForHistory( // Do not fetch ledger sequences lower // than the earliest ledger sequence fetchSz = app_.getNodeStore().earliestLedgerSeq(); - fetchSz = missing >= fetchSz - ? std::min(ledger_fetch_size_, (missing - fetchSz) + 1) - : 0; + fetchSz = missing >= fetchSz ? std::min(ledger_fetch_size_, (missing - fetchSz) + 1) : 0; try { for (std::uint32_t i = 0; i < fetchSz; ++i) @@ -1873,23 +1756,17 @@ LedgerMaster::fetchForHistory( } catch (std::exception const& ex) { - JLOG(m_journal.warn()) - << "Threw while prefetching: " << ex.what(); + JLOG(m_journal.warn()) << "Threw while prefetching: " << ex.what(); } } } else { - JLOG(m_journal.fatal()) - << "Can't find ledger following prevMissing " << missing; - JLOG(m_journal.fatal()) - << "Pub:" << mPubLedgerSeq << " Val:" << mValidLedgerSeq; - JLOG(m_journal.fatal()) - << "Ledgers: " << app_.getLedgerMaster().getCompleteLedgers(); - JLOG(m_journal.fatal()) - << "Acquire reason: " - << (reason == InboundLedger::Reason::HISTORY ? "HISTORY" - : "NOT HISTORY"); + JLOG(m_journal.fatal()) << "Can't find ledger following prevMissing " << missing; + JLOG(m_journal.fatal()) << "Pub:" << mPubLedgerSeq << " Val:" << mValidLedgerSeq; + JLOG(m_journal.fatal()) << "Ledgers: " << app_.getLedgerMaster().getCompleteLedgers(); + JLOG(m_journal.fatal()) << "Acquire reason: " + << (reason == InboundLedger::Reason::HISTORY ? "HISTORY" : "NOT HISTORY"); clearLedger(missing + 1); progress = true; } @@ -1908,8 +1785,7 @@ LedgerMaster::doAdvance(std::unique_lock& sl) if (pubLedgers.empty()) { if (!standalone_ && !app_.getFeeTrack().isLoadedLocal() && - (app_.getJobQueue().getJobCount(jtPUBOLDLEDGER) < 10) && - (mValidLedgerSeq == mPubLedgerSeq) && + (app_.getJobQueue().getJobCount(jtPUBOLDLEDGER) < 10) && (mValidLedgerSeq == mPubLedgerSeq) && (getValidatedLedgerAge() < MAX_LEDGER_AGE_ACQUIRE) && (app_.getNodeStore().getWriteLoad() < MAX_WRITE_LOAD_ACQUIRE)) { @@ -1919,14 +1795,11 @@ LedgerMaster::doAdvance(std::unique_lock& sl) { std::lock_guard sll(mCompleteLock); missing = prevMissing( - mCompleteLedgers, - mPubLedger->header().seq, - app_.getNodeStore().earliestLedgerSeq()); + mCompleteLedgers, mPubLedger->header().seq, app_.getNodeStore().earliestLedgerSeq()); } if (missing) { - JLOG(m_journal.trace()) - << "tryAdvance discovered missing " << *missing; + JLOG(m_journal.trace()) << "tryAdvance discovered missing " << *missing; if ((mFillInProgress == 0 || *missing > mFillInProgress) && shouldAcquire( mValidLedgerSeq, @@ -1935,8 +1808,7 @@ LedgerMaster::doAdvance(std::unique_lock& sl) *missing, m_journal)) { - JLOG(m_journal.trace()) - << "advanceThread should acquire"; + JLOG(m_journal.trace()) << "advanceThread should acquire"; } else missing = std::nullopt; @@ -1946,8 +1818,7 @@ LedgerMaster::doAdvance(std::unique_lock& sl) fetchForHistory(*missing, progress, reason, sl); if (mValidLedgerSeq != mPubLedgerSeq) { - JLOG(m_journal.debug()) - << "tryAdvance found last valid changed"; + JLOG(m_journal.debug()) << "tryAdvance found last valid changed"; progress = true; } } @@ -1960,14 +1831,12 @@ LedgerMaster::doAdvance(std::unique_lock& sl) } else { - JLOG(m_journal.trace()) << "tryAdvance found " << pubLedgers.size() - << " ledgers to publish"; + JLOG(m_journal.trace()) << "tryAdvance found " << pubLedgers.size() << " ledgers to publish"; for (auto const& ledger : pubLedgers) { { scope_unlock sul{sl}; - JLOG(m_journal.debug()) - << "tryAdvance publishing seq " << ledger->header().seq; + JLOG(m_journal.debug()) << "tryAdvance publishing seq " << ledger->header().seq; setFullLedger(ledger, true, true); } @@ -2056,24 +1925,22 @@ populateFetchPack( Serializer s(1024); - want.visitDifferences( - have, - [&s, withLeaves, &cnt, into, seq](SHAMapTreeNode const& n) -> bool { - if (!withLeaves && n.isLeaf()) - return true; + want.visitDifferences(have, [&s, withLeaves, &cnt, into, seq](SHAMapTreeNode const& n) -> bool { + if (!withLeaves && n.isLeaf()) + return true; - s.erase(); - n.serializeWithPrefix(s); + s.erase(); + n.serializeWithPrefix(s); - auto const& hash = n.getHash().as_uint256(); + auto const& hash = n.getHash().as_uint256(); - protocol::TMIndexedObject* obj = into->add_objects(); - obj->set_ledgerseq(seq); - obj->set_hash(hash.data(), hash.size()); - obj->set_data(s.getDataPtr(), s.getLength()); + protocol::TMIndexedObject* obj = into->add_objects(); + obj->set_ledgerseq(seq); + obj->set_hash(hash.data(), hash.size()); + obj->set_data(s.getDataPtr(), s.getLength()); - return --cnt != 0; - }); + return --cnt != 0; + }); } void @@ -2105,16 +1972,14 @@ LedgerMaster::makeFetchPack( if (!have) { - JLOG(m_journal.info()) - << "Peer requests fetch pack for ledger we don't have: " << have; + JLOG(m_journal.info()) << "Peer requests fetch pack for ledger we don't have: " << have; peer->charge(Resource::feeRequestNoReply, "get_object ledger"); return; } if (have->open()) { - JLOG(m_journal.warn()) - << "Peer requests fetch pack from open ledger: " << have; + JLOG(m_journal.warn()) << "Peer requests fetch pack from open ledger: " << have; peer->charge(Resource::feeMalformedRequest, "get_object ledger open"); return; } @@ -2130,11 +1995,9 @@ LedgerMaster::makeFetchPack( if (!want) { - JLOG(m_journal.info()) - << "Peer requests fetch pack for ledger whose predecessor we " - << "don't have: " << have; - peer->charge( - Resource::feeRequestNoReply, "get_object ledger no parent"); + JLOG(m_journal.info()) << "Peer requests fetch pack for ledger whose predecessor we " + << "don't have: " << have; + peer->charge(Resource::feeRequestNoReply, "get_object ledger no parent"); return; } @@ -2172,14 +2035,12 @@ LedgerMaster::makeFetchPack( // Add the data protocol::TMIndexedObject* obj = reply.add_objects(); - obj->set_hash( - want->header().hash.data(), want->header().hash.size()); + obj->set_hash(want->header().hash.data(), want->header().hash.size()); obj->set_data(hdr.getDataPtr(), hdr.getLength()); obj->set_ledgerseq(lSeq); } - populateFetchPack( - want->stateMap(), &have->stateMap(), 16384, &reply, lSeq); + populateFetchPack(want->stateMap(), &have->stateMap(), 16384, &reply, lSeq); // We use nullptr here because transaction maps are per ledger // and so the requestor is unlikely to already have it. @@ -2195,16 +2056,14 @@ LedgerMaster::makeFetchPack( auto msg = std::make_shared(reply, protocol::mtGET_OBJECTS); - JLOG(m_journal.info()) - << "Built fetch pack with " << reply.objects().size() << " nodes (" - << msg->getBufferSize() << " bytes)"; + JLOG(m_journal.info()) << "Built fetch pack with " << reply.objects().size() << " nodes (" + << msg->getBufferSize() << " bytes)"; peer->send(msg); } catch (std::exception const& ex) { - JLOG(m_journal.warn()) - << "Exception building fetch pack. Exception: " << ex.what(); + JLOG(m_journal.warn()) << "Exception building fetch pack. Exception: " << ex.what(); } } @@ -2234,8 +2093,7 @@ LedgerMaster::txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex) return {}; for (auto it = lgr->txs.begin(); it != lgr->txs.end(); ++it) - if (it->first && it->second && - it->second->isFieldPresent(sfTransactionIndex) && + if (it->first && it->second && it->second->isFieldPresent(sfTransactionIndex) && it->second->getFieldU32(sfTransactionIndex) == txnIndex) return it->first->getTransactionID(); diff --git a/src/xrpld/app/ledger/detail/LedgerReplay.cpp b/src/xrpld/app/ledger/detail/LedgerReplay.cpp index 5d7ce0e69f..e77adc9700 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplay.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplay.cpp @@ -3,9 +3,7 @@ namespace xrpl { -LedgerReplay::LedgerReplay( - std::shared_ptr parent, - std::shared_ptr replay) +LedgerReplay::LedgerReplay(std::shared_ptr parent, std::shared_ptr replay) : parent_{std::move(parent)}, replay_{std::move(replay)} { for (auto const& item : replay_->txMap()) @@ -20,9 +18,7 @@ LedgerReplay::LedgerReplay( std::shared_ptr parent, std::shared_ptr replay, std::map>&& orderedTxns) - : parent_{std::move(parent)} - , replay_{std::move(replay)} - , orderedTxns_{std::move(orderedTxns)} + : parent_{std::move(parent)}, replay_{std::move(replay)}, orderedTxns_{std::move(orderedTxns)} { } diff --git a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp index 9356f17af0..4fcb924c27 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.cpp @@ -8,25 +8,19 @@ #include namespace xrpl { -LedgerReplayMsgHandler::LedgerReplayMsgHandler( - Application& app, - LedgerReplayer& replayer) - : app_(app) - , replayer_(replayer) - , journal_(app.journal("LedgerReplayMsgHandler")) +LedgerReplayMsgHandler::LedgerReplayMsgHandler(Application& app, LedgerReplayer& replayer) + : app_(app), replayer_(replayer), journal_(app.journal("LedgerReplayMsgHandler")) { } protocol::TMProofPathResponse -LedgerReplayMsgHandler::processProofPathRequest( - std::shared_ptr const& msg) +LedgerReplayMsgHandler::processProofPathRequest(std::shared_ptr const& msg) { protocol::TMProofPathRequest& packet = *msg; protocol::TMProofPathResponse reply; if (!packet.has_key() || !packet.has_ledgerhash() || !packet.has_type() || - packet.ledgerhash().size() != uint256::size() || - packet.key().size() != uint256::size() || + packet.ledgerhash().size() != uint256::size() || packet.key().size() != uint256::size() || !protocol::TMLedgerMapType_IsValid(packet.type())) { JLOG(journal_.debug()) << "getProofPath: Invalid request"; @@ -42,8 +36,7 @@ LedgerReplayMsgHandler::processProofPathRequest( auto ledger = app_.getLedgerMaster().getLedgerByHash(ledgerHash); if (!ledger) { - JLOG(journal_.debug()) - << "getProofPath: Don't have ledger " << ledgerHash; + JLOG(journal_.debug()) << "getProofPath: Don't have ledger " << ledgerHash; reply.set_error(protocol::TMReplyError::reNO_LEDGER); return reply; } @@ -64,8 +57,7 @@ LedgerReplayMsgHandler::processProofPathRequest( if (!path) { - JLOG(journal_.debug()) << "getProofPath: Don't have the node " << key - << " of ledger " << ledgerHash; + JLOG(journal_.debug()) << "getProofPath: Don't have the node " << key << " of ledger " << ledgerHash; reply.set_error(protocol::TMReplyError::reNO_NODE); return reply; } @@ -78,20 +70,17 @@ LedgerReplayMsgHandler::processProofPathRequest( for (auto const& b : *path) reply.add_path(b.data(), b.size()); - JLOG(journal_.debug()) << "getProofPath for the node " << key - << " of ledger " << ledgerHash << " path length " + JLOG(journal_.debug()) << "getProofPath for the node " << key << " of ledger " << ledgerHash << " path length " << path->size(); return reply; } bool -LedgerReplayMsgHandler::processProofPathResponse( - std::shared_ptr const& msg) +LedgerReplayMsgHandler::processProofPathResponse(std::shared_ptr const& msg) { protocol::TMProofPathResponse& reply = *msg; - if (reply.has_error() || !reply.has_key() || !reply.has_ledgerhash() || - !reply.has_type() || !reply.has_ledgerheader() || - reply.path_size() == 0) + if (reply.has_error() || !reply.has_key() || !reply.has_ledgerhash() || !reply.has_type() || + !reply.has_ledgerheader() || reply.path_size() == 0) { JLOG(journal_.debug()) << "Bad message: Error reply"; return false; @@ -99,14 +88,12 @@ LedgerReplayMsgHandler::processProofPathResponse( if (reply.type() != protocol::lmACCOUNT_STATE) { - JLOG(journal_.debug()) - << "Bad message: we only support the state ShaMap for now"; + JLOG(journal_.debug()) << "Bad message: we only support the state ShaMap for now"; return false; } // deserialize the header - auto info = deserializeHeader( - {reply.ledgerheader().data(), reply.ledgerheader().size()}); + auto info = deserializeHeader({reply.ledgerheader().data(), reply.ledgerheader().size()}); uint256 replyHash(reply.ledgerhash()); if (calculateLedgerHash(info) != replyHash) { @@ -118,10 +105,9 @@ LedgerReplayMsgHandler::processProofPathResponse( uint256 key(reply.key()); if (key != keylet::skip().key) { - JLOG(journal_.debug()) - << "Bad message: we only support the short skip list for now. " - "Key in reply " - << key; + JLOG(journal_.debug()) << "Bad message: we only support the short skip list for now. " + "Key in reply " + << key; return false; } @@ -158,14 +144,12 @@ LedgerReplayMsgHandler::processProofPathResponse( } protocol::TMReplayDeltaResponse -LedgerReplayMsgHandler::processReplayDeltaRequest( - std::shared_ptr const& msg) +LedgerReplayMsgHandler::processReplayDeltaRequest(std::shared_ptr const& msg) { protocol::TMReplayDeltaRequest& packet = *msg; protocol::TMReplayDeltaResponse reply; - if (!packet.has_ledgerhash() || - packet.ledgerhash().size() != uint256::size()) + if (!packet.has_ledgerhash() || packet.ledgerhash().size() != uint256::size()) { JLOG(journal_.debug()) << "getReplayDelta: Invalid request"; reply.set_error(protocol::TMReplyError::reBAD_REQUEST); @@ -177,8 +161,7 @@ LedgerReplayMsgHandler::processReplayDeltaRequest( auto ledger = app_.getLedgerMaster().getLedgerByHash(ledgerHash); if (!ledger || !ledger->isImmutable()) { - JLOG(journal_.debug()) - << "getReplayDelta: Don't have ledger " << ledgerHash; + JLOG(journal_.debug()) << "getReplayDelta: Don't have ledger " << ledgerHash; reply.set_error(protocol::TMReplyError::reNO_LEDGER); return reply; } @@ -189,19 +172,17 @@ LedgerReplayMsgHandler::processReplayDeltaRequest( reply.set_ledgerheader(nData.getDataPtr(), nData.getLength()); // pack transactions auto const& txMap = ledger->txMap(); - txMap.visitLeaves( - [&](boost::intrusive_ptr const& txNode) { - reply.add_transaction(txNode->data(), txNode->size()); - }); + txMap.visitLeaves([&](boost::intrusive_ptr const& txNode) { + reply.add_transaction(txNode->data(), txNode->size()); + }); - JLOG(journal_.debug()) << "getReplayDelta for ledger " << ledgerHash - << " txMap hash " << txMap.getHash().as_uint256(); + JLOG(journal_.debug()) << "getReplayDelta for ledger " << ledgerHash << " txMap hash " + << txMap.getHash().as_uint256(); return reply; } bool -LedgerReplayMsgHandler::processReplayDeltaResponse( - std::shared_ptr const& msg) +LedgerReplayMsgHandler::processReplayDeltaResponse(std::shared_ptr const& msg) { protocol::TMReplayDeltaResponse& reply = *msg; if (reply.has_error() || !reply.has_ledgerheader()) @@ -210,8 +191,7 @@ LedgerReplayMsgHandler::processReplayDeltaResponse( return false; } - auto info = deserializeHeader( - {reply.ledgerheader().data(), reply.ledgerheader().size()}); + auto info = deserializeHeader({reply.ledgerheader().data(), reply.ledgerheader().size()}); uint256 replyHash(reply.ledgerhash()); if (calculateLedgerHash(info) != replyHash) { @@ -231,8 +211,7 @@ LedgerReplayMsgHandler::processReplayDeltaResponse( // -- TxShaMapItem for building a ShaMap for verification // -- Tx // -- TxMetaData for Tx ordering - Serializer shaMapItemData( - reply.transaction(i).data(), reply.transaction(i).size()); + Serializer shaMapItemData(reply.transaction(i).data(), reply.transaction(i).size()); SerialIter txMetaSit(makeSlice(reply.transaction(i))); SerialIter txSit(txMetaSit.getSlice(txMetaSit.getVLDataLength())); @@ -248,9 +227,7 @@ LedgerReplayMsgHandler::processReplayDeltaResponse( STObject meta(metaSit, sfMetadata); orderedTxns.emplace(meta[sfTransactionIndex], std::move(tx)); - if (!txMap.addGiveItem( - SHAMapNodeType::tnTRANSACTION_MD, - make_shamapitem(tid, shaMapItemData.slice()))) + if (!txMap.addGiveItem(SHAMapNodeType::tnTRANSACTION_MD, make_shamapitem(tid, shaMapItemData.slice()))) { JLOG(journal_.debug()) << "Bad message: Cannot deserialize"; return false; diff --git a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.h b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.h index fff3e75460..7cd231e59a 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.h +++ b/src/xrpld/app/ledger/detail/LedgerReplayMsgHandler.h @@ -19,8 +19,7 @@ public: * @note check has_error() and error() of the response for error */ protocol::TMProofPathResponse - processProofPathRequest( - std::shared_ptr const& msg); + processProofPathRequest(std::shared_ptr const& msg); /** * Process TMProofPathResponse @@ -28,16 +27,14 @@ public: * true otherwise */ bool - processProofPathResponse( - std::shared_ptr const& msg); + processProofPathResponse(std::shared_ptr const& msg); /** * Process TMReplayDeltaRequest and return TMReplayDeltaResponse * @note check has_error() and error() of the response for error */ protocol::TMReplayDeltaResponse - processReplayDeltaRequest( - std::shared_ptr const& msg); + processReplayDeltaRequest(std::shared_ptr const& msg); /** * Process TMReplayDeltaResponse @@ -45,8 +42,7 @@ public: * true otherwise */ bool - processReplayDeltaResponse( - std::shared_ptr const& msg); + processReplayDeltaResponse(std::shared_ptr const& msg); private: Application& app_; diff --git a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp index c31aba6c43..b7d788e15a 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp @@ -19,10 +19,7 @@ LedgerReplayTask::TaskParameter::TaskParameter( } bool -LedgerReplayTask::TaskParameter::update( - uint256 const& hash, - std::uint32_t seq, - std::vector const& sList) +LedgerReplayTask::TaskParameter::update(uint256 const& hash, std::uint32_t seq, std::vector const& sList) { if (finishHash_ != hash || sList.size() + 1 < totalLedgers_ || full_) return false; @@ -31,22 +28,18 @@ LedgerReplayTask::TaskParameter::update( skipList_ = sList; skipList_.emplace_back(finishHash_); startHash_ = skipList_[skipList_.size() - totalLedgers_]; - XRPL_ASSERT( - startHash_.isNonZero(), - "xrpl::LedgerReplayTask::TaskParameter::update : nonzero start hash"); + XRPL_ASSERT(startHash_.isNonZero(), "xrpl::LedgerReplayTask::TaskParameter::update : nonzero start hash"); startSeq_ = finishSeq_ - totalLedgers_ + 1; full_ = true; return true; } bool -LedgerReplayTask::TaskParameter::canMergeInto( - TaskParameter const& existingTask) const +LedgerReplayTask::TaskParameter::canMergeInto(TaskParameter const& existingTask) const { if (reason_ == existingTask.reason_) { - if (finishHash_ == existingTask.finishHash_ && - totalLedgers_ <= existingTask.totalLedgers_) + if (finishHash_ == existingTask.finishHash_ && totalLedgers_ <= existingTask.totalLedgers_) { return true; } @@ -54,11 +47,9 @@ LedgerReplayTask::TaskParameter::canMergeInto( if (existingTask.full_) { auto const& exList = existingTask.skipList_; - if (auto i = std::find(exList.begin(), exList.end(), finishHash_); - i != exList.end()) + if (auto i = std::find(exList.begin(), exList.end(), finishHash_); i != exList.end()) { - return existingTask.totalLedgers_ >= - totalLedgers_ + (exList.end() - i) - 1; + return existingTask.totalLedgers_ >= totalLedgers_ + (exList.end() - i) - 1; } } } @@ -76,17 +67,14 @@ LedgerReplayTask::LedgerReplayTask( app, parameter.finishHash_, LedgerReplayParameters::TASK_TIMEOUT, - {jtREPLAY_TASK, - "LedReplTask", - LedgerReplayParameters::MAX_QUEUED_TASKS}, + {jtREPLAY_TASK, "LedReplTask", LedgerReplayParameters::MAX_QUEUED_TASKS}, app.journal("LedgerReplayTask")) , inboundLedgers_(inboundLedgers) , replayer_(replayer) , parameter_(parameter) , maxTimeouts_(std::max( LedgerReplayParameters::TASK_MAX_TIMEOUTS_MINIMUM, - parameter.totalLedgers_ * - LedgerReplayParameters::TASK_MAX_TIMEOUTS_MULTIPLIER)) + parameter.totalLedgers_ * LedgerReplayParameters::TASK_MAX_TIMEOUTS_MULTIPLIER)) , skipListAcquirer_(skipListAcquirer) { JLOG(journal_.trace()) << "Create " << hash_; @@ -113,8 +101,7 @@ LedgerReplayTask::init() else { auto const skipListData = sptr->skipListAcquirer_->getData(); - sptr->updateSkipList( - hash, skipListData->ledgerSeq, skipListData->skipList); + sptr->updateSkipList(hash, skipListData->ledgerSeq, skipListData->skipList); } } }); @@ -139,16 +126,12 @@ LedgerReplayTask::trigger(ScopedLockType& sl) parent_ = app_.getLedgerMaster().getLedgerByHash(parameter_.startHash_); if (!parent_) { - parent_ = inboundLedgers_.acquire( - parameter_.startHash_, - parameter_.startSeq_, - InboundLedger::Reason::GENERIC); + parent_ = + inboundLedgers_.acquire(parameter_.startHash_, parameter_.startSeq_, InboundLedger::Reason::GENERIC); } if (parent_) { - JLOG(journal_.trace()) - << "Got start ledger " << parameter_.startHash_ << " for task " - << hash_; + JLOG(journal_.trace()) << "Got start ledger " << parameter_.startHash_ << " for task " << hash_; } } @@ -158,8 +141,7 @@ LedgerReplayTask::trigger(ScopedLockType& sl) void LedgerReplayTask::deltaReady(uint256 const& deltaHash) { - JLOG(journal_.trace()) << "Delta " << deltaHash << " ready for task " - << hash_; + JLOG(journal_.trace()) << "Delta " << deltaHash << " ready for task " << hash_; ScopedLockType sl(mtx_); if (!isDone()) tryAdvance(sl); @@ -169,14 +151,11 @@ void LedgerReplayTask::tryAdvance(ScopedLockType& sl) { JLOG(journal_.trace()) << "tryAdvance task " << hash_ - << (parameter_.full_ ? ", full parameter" - : ", waiting to fill parameter") - << ", deltaIndex=" << deltaToBuild_ - << ", totalDeltas=" << deltas_.size() << ", parent " + << (parameter_.full_ ? ", full parameter" : ", waiting to fill parameter") + << ", deltaIndex=" << deltaToBuild_ << ", totalDeltas=" << deltas_.size() << ", parent " << (parent_ ? parent_->header().hash : uint256()); - bool shouldTry = parent_ && parameter_.full_ && - parameter_.totalLedgers_ - 1 == deltas_.size(); + bool shouldTry = parent_ && parameter_.full_ && parameter_.totalLedgers_ - 1 == deltas_.size(); if (!shouldTry) return; @@ -186,14 +165,11 @@ LedgerReplayTask::tryAdvance(ScopedLockType& sl) { auto& delta = deltas_[deltaToBuild_]; XRPL_ASSERT( - parent_->seq() + 1 == delta->ledgerSeq_, - "xrpl::LedgerReplayTask::tryAdvance : consecutive sequence"); + parent_->seq() + 1 == delta->ledgerSeq_, "xrpl::LedgerReplayTask::tryAdvance : consecutive sequence"); if (auto l = delta->tryBuild(parent_); l) { - JLOG(journal_.debug()) - << "Task " << hash_ << " got ledger " << l->header().hash - << " deltaIndex=" << deltaToBuild_ - << " totalDeltas=" << deltas_.size(); + JLOG(journal_.debug()) << "Task " << hash_ << " got ledger " << l->header().hash + << " deltaIndex=" << deltaToBuild_ << " totalDeltas=" << deltas_.size(); parent_ = l; } else @@ -210,10 +186,7 @@ LedgerReplayTask::tryAdvance(ScopedLockType& sl) } void -LedgerReplayTask::updateSkipList( - uint256 const& hash, - std::uint32_t seq, - std::vector const& sList) +LedgerReplayTask::updateSkipList(uint256 const& hash, std::uint32_t seq, std::vector const& sList) { { ScopedLockType sl(mtx_); @@ -240,8 +213,7 @@ LedgerReplayTask::onTimer(bool progress, ScopedLockType& sl) if (timeouts_ > maxTimeouts_) { failed_ = true; - JLOG(journal_.debug()) - << "LedgerReplayTask Failed, too many timeouts " << hash_; + JLOG(journal_.debug()) << "LedgerReplayTask Failed, too many timeouts " << hash_; } else { @@ -259,26 +231,23 @@ void LedgerReplayTask::addDelta(std::shared_ptr const& delta) { std::weak_ptr wptr = shared_from_this(); - delta->addDataCallback( - parameter_.reason_, [wptr](bool good, uint256 const& hash) { - if (auto sptr = wptr.lock(); sptr) - { - if (!good) - sptr->cancel(); - else - sptr->deltaReady(hash); - } - }); + delta->addDataCallback(parameter_.reason_, [wptr](bool good, uint256 const& hash) { + if (auto sptr = wptr.lock(); sptr) + { + if (!good) + sptr->cancel(); + else + sptr->deltaReady(hash); + } + }); ScopedLockType sl(mtx_); if (!isDone()) { - JLOG(journal_.trace()) - << "addDelta task " << hash_ << " deltaIndex=" << deltaToBuild_ - << " totalDeltas=" << deltas_.size(); + JLOG(journal_.trace()) << "addDelta task " << hash_ << " deltaIndex=" << deltaToBuild_ + << " totalDeltas=" << deltas_.size(); XRPL_ASSERT( - deltas_.empty() || - deltas_.back()->ledgerSeq_ + 1 == delta->ledgerSeq_, + deltas_.empty() || deltas_.back()->ledgerSeq_ + 1 == delta->ledgerSeq_, "xrpl::LedgerReplayTask::addDelta : no deltas or consecutive " "sequence"); deltas_.push_back(delta); diff --git a/src/xrpld/app/ledger/detail/LedgerReplayer.cpp b/src/xrpld/app/ledger/detail/LedgerReplayer.cpp index 1d1cdf3ec2..b52abc5624 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayer.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayer.cpp @@ -22,18 +22,13 @@ LedgerReplayer::~LedgerReplayer() } void -LedgerReplayer::replay( - InboundLedger::Reason r, - uint256 const& finishLedgerHash, - std::uint32_t totalNumLedgers) +LedgerReplayer::replay(InboundLedger::Reason r, uint256 const& finishLedgerHash, std::uint32_t totalNumLedgers) { XRPL_ASSERT( - finishLedgerHash.isNonZero() && totalNumLedgers > 0 && - totalNumLedgers <= LedgerReplayParameters::MAX_TASK_SIZE, + finishLedgerHash.isNonZero() && totalNumLedgers > 0 && totalNumLedgers <= LedgerReplayParameters::MAX_TASK_SIZE, "xrpl::LedgerReplayer::replay : valid inputs"); - LedgerReplayTask::TaskParameter parameter( - r, finishLedgerHash, totalNumLedgers); + LedgerReplayTask::TaskParameter parameter(r, finishLedgerHash, totalNumLedgers); std::shared_ptr task; std::shared_ptr skipList; @@ -44,8 +39,7 @@ LedgerReplayer::replay( return; if (tasks_.size() >= LedgerReplayParameters::MAX_TASKS) { - JLOG(j_.info()) << "Too many replay tasks, dropping new task " - << parameter.finishHash_; + JLOG(j_.info()) << "Too many replay tasks, dropping new task " << parameter.finishHash_; return; } @@ -53,15 +47,12 @@ LedgerReplayer::replay( { if (parameter.canMergeInto(t->getTaskParameter())) { - JLOG(j_.info()) << "Task " << parameter.finishHash_ << " with " - << totalNumLedgers + JLOG(j_.info()) << "Task " << parameter.finishHash_ << " with " << totalNumLedgers << " ledgers merged into an existing task."; return; } } - JLOG(j_.info()) << "Replay " << totalNumLedgers - << " ledgers. Finish ledger hash " - << parameter.finishHash_; + JLOG(j_.info()) << "Replay " << totalNumLedgers << " ledgers. Finish ledger hash " << parameter.finishHash_; auto i = skipLists_.find(parameter.finishHash_); if (i != skipLists_.end()) @@ -70,16 +61,12 @@ LedgerReplayer::replay( if (!skipList) // cannot find, or found but cannot lock { skipList = std::make_shared( - app_, - inboundLedgers_, - parameter.finishHash_, - peerSetBuilder_->build()); + app_, inboundLedgers_, parameter.finishHash_, peerSetBuilder_->build()); skipLists_[parameter.finishHash_] = skipList; newSkipList = true; } - task = std::make_shared( - app_, inboundLedgers_, *this, skipList, std::move(parameter)); + task = std::make_shared(app_, inboundLedgers_, *this, skipList, std::move(parameter)); tasks_.push_back(task); } @@ -103,21 +90,15 @@ LedgerReplayer::createDeltas(std::shared_ptr task) JLOG(j_.trace()) << "Creating " << parameter.totalLedgers_ - 1 << " deltas"; if (parameter.totalLedgers_ > 1) { - auto skipListItem = std::find( - parameter.skipList_.begin(), - parameter.skipList_.end(), - parameter.startHash_); - if (skipListItem == parameter.skipList_.end() || - ++skipListItem == parameter.skipList_.end()) + auto skipListItem = std::find(parameter.skipList_.begin(), parameter.skipList_.end(), parameter.startHash_); + if (skipListItem == parameter.skipList_.end() || ++skipListItem == parameter.skipList_.end()) { - JLOG(j_.error()) << "Task parameter error when creating deltas " - << parameter.finishHash_; + JLOG(j_.error()) << "Task parameter error when creating deltas " << parameter.finishHash_; return; } for (std::uint32_t seq = parameter.startSeq_ + 1; - seq <= parameter.finishSeq_ && - skipListItem != parameter.skipList_.end(); + seq <= parameter.finishSeq_ && skipListItem != parameter.skipList_.end(); ++seq, ++skipListItem) { std::shared_ptr delta; @@ -133,11 +114,7 @@ LedgerReplayer::createDeltas(std::shared_ptr task) if (!delta) // cannot find, or found but cannot lock { delta = std::make_shared( - app_, - inboundLedgers_, - *skipListItem, - seq, - peerSetBuilder_->build()); + app_, inboundLedgers_, *skipListItem, seq, peerSetBuilder_->build()); deltas_[*skipListItem] = delta; newDelta = true; } @@ -151,9 +128,7 @@ LedgerReplayer::createDeltas(std::shared_ptr task) } void -LedgerReplayer::gotSkipList( - LedgerHeader const& info, - boost::intrusive_ptr const& item) +LedgerReplayer::gotSkipList(LedgerHeader const& info, boost::intrusive_ptr const& item) { std::shared_ptr skipList = {}; { @@ -174,9 +149,7 @@ LedgerReplayer::gotSkipList( } void -LedgerReplayer::gotReplayDelta( - LedgerHeader const& info, - std::map>&& txns) +LedgerReplayer::gotReplayDelta(LedgerHeader const& info, std::map>&& txns) { std::shared_ptr delta = {}; { @@ -202,8 +175,7 @@ LedgerReplayer::sweep() auto const start = std::chrono::steady_clock::now(); { std::lock_guard lock(mtx_); - JLOG(j_.debug()) << "Sweeping, LedgerReplayer has " << tasks_.size() - << " tasks, " << skipLists_.size() + JLOG(j_.debug()) << "Sweeping, LedgerReplayer has " << tasks_.size() << " tasks, " << skipLists_.size() << " skipLists, and " << deltas_.size() << " deltas."; tasks_.erase( @@ -213,8 +185,7 @@ LedgerReplayer::sweep() [this](auto const& t) -> bool { if (t->finished()) { - JLOG(j_.debug()) << "Sweep task " - << t->getTaskParameter().finishHash_; + JLOG(j_.debug()) << "Sweep task " << t->getTaskParameter().finishHash_; return true; } return false; @@ -235,11 +206,10 @@ LedgerReplayer::sweep() removeCannotLocked(skipLists_); removeCannotLocked(deltas_); } - JLOG(j_.debug()) << " LedgerReplayer sweep lock duration " - << std::chrono::duration_cast( - std::chrono::steady_clock::now() - start) - .count() - << "ms"; + JLOG(j_.debug()) + << " LedgerReplayer sweep lock duration " + << std::chrono::duration_cast(std::chrono::steady_clock::now() - start).count() + << "ms"; } void @@ -248,8 +218,7 @@ LedgerReplayer::stop() JLOG(j_.info()) << "Stopping..."; { std::lock_guard lock(mtx_); - std::for_each( - tasks_.begin(), tasks_.end(), [](auto& i) { i->cancel(); }); + std::for_each(tasks_.begin(), tasks_.end(), [](auto& i) { i->cancel(); }); tasks_.clear(); auto lockAndCancel = [](auto& i) { if (auto sptr = i.second.lock(); sptr) diff --git a/src/xrpld/app/ledger/detail/LedgerToJson.cpp b/src/xrpld/app/ledger/detail/LedgerToJson.cpp index b1f6d6b297..a675550537 100644 --- a/src/xrpld/app/ledger/detail/LedgerToJson.cpp +++ b/src/xrpld/app/ledger/detail/LedgerToJson.cpp @@ -33,17 +33,10 @@ isBinary(LedgerFill const& fill) } void -fillJson( - Json::Value& json, - bool closed, - LedgerHeader const& info, - bool bFull, - unsigned apiVersion) +fillJson(Json::Value& json, bool closed, LedgerHeader const& info, bool bFull, unsigned apiVersion) { json[jss::parent_hash] = to_string(info.parentHash); - json[jss::ledger_index] = (apiVersion > 1) - ? Json::Value(info.seq) - : Json::Value(std::to_string(info.seq)); + json[jss::ledger_index] = (apiVersion > 1) ? Json::Value(info.seq) : Json::Value(std::to_string(info.seq)); if (closed) { @@ -63,8 +56,7 @@ fillJson( json[jss::close_flags] = info.closeFlags; // Always show fields that contribute to the ledger hash - json[jss::parent_close_time] = - info.parentCloseTime.time_since_epoch().count(); + json[jss::parent_close_time] = info.parentCloseTime.time_since_epoch().count(); json[jss::close_time] = info.closeTime.time_since_epoch().count(); json[jss::close_time_resolution] = info.closeTimeResolution.count(); @@ -111,19 +103,15 @@ fillJsonTx( if (fill.context->apiVersion > 1) txJson[jss::hash] = to_string(txn->getTransactionID()); - auto const json_meta = - (fill.context->apiVersion > 1 ? jss::meta_blob : jss::meta); + auto const json_meta = (fill.context->apiVersion > 1 ? jss::meta_blob : jss::meta); if (stMeta) txJson[json_meta] = serializeHex(*stMeta); } else if (fill.context->apiVersion > 1) { - copyFrom( - txJson[jss::tx_json], - txn->getJson(JsonOptions::disable_API_prior_V2, false)); + copyFrom(txJson[jss::tx_json], txn->getJson(JsonOptions::disable_API_prior_V2, false)); txJson[jss::hash] = to_string(txn->getTransactionID()); - RPC::insertDeliverMax( - txJson[jss::tx_json], txnType, fill.context->apiVersion); + RPC::insertDeliverMax(txJson[jss::tx_json], txnType, fill.context->apiVersion); if (stMeta) { @@ -132,23 +120,16 @@ fillJsonTx( // If applicable, insert delivered amount if (txnType == ttPAYMENT || txnType == ttCHECK_CASH) RPC::insertDeliveredAmount( - txJson[jss::meta], - fill.ledger, - txn, - {txn->getTransactionID(), fill.ledger.seq(), *stMeta}); + txJson[jss::meta], fill.ledger, txn, {txn->getTransactionID(), fill.ledger.seq(), *stMeta}); // If applicable, insert mpt issuance id - RPC::insertMPTokenIssuanceID( - txJson[jss::meta], - txn, - {txn->getTransactionID(), fill.ledger.seq(), *stMeta}); + RPC::insertMPTokenIssuanceID(txJson[jss::meta], txn, {txn->getTransactionID(), fill.ledger.seq(), *stMeta}); } if (!fill.ledger.open()) txJson[jss::ledger_hash] = to_string(fill.ledger.header().hash); - bool const validated = - fill.context->ledgerMaster.isValidated(fill.ledger); + bool const validated = fill.context->ledgerMaster.isValidated(fill.ledger); txJson[jss::validated] = validated; if (validated) { @@ -169,21 +150,15 @@ fillJsonTx( // If applicable, insert delivered amount if (txnType == ttPAYMENT || txnType == ttCHECK_CASH) RPC::insertDeliveredAmount( - txJson[jss::metaData], - fill.ledger, - txn, - {txn->getTransactionID(), fill.ledger.seq(), *stMeta}); + txJson[jss::metaData], fill.ledger, txn, {txn->getTransactionID(), fill.ledger.seq(), *stMeta}); // If applicable, insert mpt issuance id RPC::insertMPTokenIssuanceID( - txJson[jss::metaData], - txn, - {txn->getTransactionID(), fill.ledger.seq(), *stMeta}); + txJson[jss::metaData], txn, {txn->getTransactionID(), fill.ledger.seq(), *stMeta}); } } - if ((fill.options & LedgerFill::ownerFunds) && - txn->getTxnType() == ttOFFER_CREATE) + if ((fill.options & LedgerFill::ownerFunds) && txn->getTxnType() == ttOFFER_CREATE) { auto const account = txn->getAccountID(sfAccount); auto const amount = txn->getFieldAmount(sfTakerGets); @@ -193,11 +168,7 @@ fillJsonTx( if (account != amount.getIssuer()) { auto const ownerFunds = accountFunds( - fill.ledger, - account, - amount, - fhIGNORE_FREEZE, - beast::Journal{beast::Journal::getNullSink()}); + fill.ledger, account, amount, fhIGNORE_FREEZE, beast::Journal{beast::Journal::getNullSink()}); txJson[jss::owner_funds] = ownerFunds.getText(); } } @@ -217,8 +188,7 @@ fillJsonTx(Json::Value& json, LedgerFill const& fill) auto appendAll = [&](auto const& txs) { for (auto& i : txs) { - txns.append( - fillJsonTx(fill, bBinary, bExpanded, i.first, i.second)); + txns.append(fillJsonTx(fill, bBinary, bExpanded, i.first, i.second)); } }; @@ -229,8 +199,7 @@ fillJsonTx(Json::Value& json, LedgerFill const& fill) // Nothing the user can do about this. if (fill.context) { - JLOG(fill.context->j.error()) - << "Exception in " << __func__ << ": " << ex.what(); + JLOG(fill.context->j.error()) << "Exception in " << __func__ << ": " << ex.what(); } } } @@ -273,8 +242,7 @@ fillJsonQueue(Json::Value& json, LedgerFill const& fill) txJson[jss::LastLedgerSequence] = *tx.lastValid; txJson[jss::fee] = to_string(tx.consequences.fee()); - auto const spend = - tx.consequences.potentialSpend() + tx.consequences.fee(); + auto const spend = tx.consequences.potentialSpend() + tx.consequences.fee(); txJson[jss::max_spend_drops] = to_string(spend); txJson[jss::auth_change] = tx.consequences.isBlocker(); @@ -306,8 +274,7 @@ fillJson(Json::Value& json, LedgerFill const& fill) !fill.ledger.open(), fill.ledger.header(), bFull, - (fill.context ? fill.context->apiVersion - : RPC::apiMaximumSupportedVersion)); + (fill.context ? fill.context->apiVersion : RPC::apiMaximumSupportedVersion)); if (bFull || fill.options & LedgerFill::dumpTxrp) fillJsonTx(json, fill); diff --git a/src/xrpld/app/ledger/detail/LocalTxs.cpp b/src/xrpld/app/ledger/detail/LocalTxs.cpp index 1e9cfe0b9b..48bd80fbf2 100644 --- a/src/xrpld/app/ledger/detail/LocalTxs.cpp +++ b/src/xrpld/app/ledger/detail/LocalTxs.cpp @@ -42,8 +42,7 @@ public: , m_seqProxy(txn->getSeqProxy()) { if (txn->isFieldPresent(sfLastLedgerSequence)) - m_expire = - std::min(m_expire, txn->getFieldU32(sfLastLedgerSequence) + 1); + m_expire = std::min(m_expire, txn->getFieldU32(sfLastLedgerSequence) + 1); } uint256 const& @@ -93,8 +92,7 @@ public: // Add a new transaction to the set of local transactions void - push_back(LedgerIndex index, std::shared_ptr const& txn) - override + push_back(LedgerIndex index, std::shared_ptr const& txn) override { std::lock_guard lock(m_lock); @@ -137,8 +135,7 @@ public: if (!sleAcct) return false; - SeqProxy const acctSeq = - SeqProxy::sequence(sleAcct->getFieldU32(sfSequence)); + SeqProxy const acctSeq = SeqProxy::sequence(sleAcct->getFieldU32(sfSequence)); SeqProxy const seqProx = txn.getSeqProxy(); if (seqProx.isSeq()) diff --git a/src/xrpld/app/ledger/detail/OpenLedger.cpp b/src/xrpld/app/ledger/detail/OpenLedger.cpp index 35f4b75157..698862d4da 100644 --- a/src/xrpld/app/ledger/detail/OpenLedger.cpp +++ b/src/xrpld/app/ledger/detail/OpenLedger.cpp @@ -13,10 +13,7 @@ namespace xrpl { -OpenLedger::OpenLedger( - std::shared_ptr const& ledger, - CachedSLEs& cache, - beast::Journal journal) +OpenLedger::OpenLedger(std::shared_ptr const& ledger, CachedSLEs& cache, beast::Journal journal) : j_(journal), cache_(cache), current_(create(ledger->rules(), ledger)) { } @@ -82,9 +79,7 @@ OpenLedger::accept( *ledger, boost::adaptors::transform( current_->txs, - [](std::pair< - std::shared_ptr, - std::shared_ptr> const& p) { + [](std::pair, std::shared_ptr> const& p) { return p.first; }), retries, @@ -127,8 +122,7 @@ OpenLedger::accept( tx->add(s); msg.set_rawtransaction(s.data(), s.size()); msg.set_status(protocol::tsNEW); - msg.set_receivetimestamp( - app.timeKeeper().now().time_since_epoch().count()); + msg.set_receivetimestamp(app.timeKeeper().now().time_since_epoch().count()); app.overlay().relay(txId, msg, *toSkip); } } @@ -141,14 +135,9 @@ OpenLedger::accept( //------------------------------------------------------------------------------ std::shared_ptr -OpenLedger::create( - Rules const& rules, - std::shared_ptr const& ledger) +OpenLedger::create(Rules const& rules, std::shared_ptr const& ledger) { - return std::make_shared( - open_ledger, - rules, - std::make_shared(ledger, cache_)); + return std::make_shared(open_ledger, rules, std::make_shared(ledger, cache_)); } auto @@ -166,8 +155,7 @@ OpenLedger::apply_one( auto const result = xrpl::apply(app, view, *tx, flags, j); if (result.applied || result.ter == terQUEUED) return Result::success; - if (isTefFailure(result.ter) || isTemMalformed(result.ter) || - isTelLocal(result.ter)) + if (isTefFailure(result.ter) || isTemMalformed(result.ter) || isTelLocal(result.ter)) return Result::failure; return Result::retry; } diff --git a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp index 09d0ba1ea6..353b4fdbc8 100644 --- a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp +++ b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp @@ -15,9 +15,7 @@ SkipListAcquire::SkipListAcquire( app, ledgerHash, LedgerReplayParameters::SUB_TASK_TIMEOUT, - {jtREPLAY_TASK, - "SkipListAcq", - LedgerReplayParameters::MAX_QUEUED_TASKS}, + {jtREPLAY_TASK, "SkipListAcq", LedgerReplayParameters::MAX_QUEUED_TASKS}, app.journal("LedgerReplaySkipList")) , inboundLedgers_(inboundLedgers) , peerSet_(std::move(peerSet)) @@ -56,32 +54,25 @@ SkipListAcquire::trigger(std::size_t limit, ScopedLockType& sl) peerSet_->addPeers( limit, [this](auto peer) { - return peer->supportsFeature(ProtocolFeature::LedgerReplay) && - peer->hasLedger(hash_, 0); + return peer->supportsFeature(ProtocolFeature::LedgerReplay) && peer->hasLedger(hash_, 0); }, [this](auto peer) { if (peer->supportsFeature(ProtocolFeature::LedgerReplay)) { - JLOG(journal_.trace()) - << "Add a peer " << peer->id() << " for " << hash_; + JLOG(journal_.trace()) << "Add a peer " << peer->id() << " for " << hash_; protocol::TMProofPathRequest request; request.set_ledgerhash(hash_.data(), hash_.size()); - request.set_key( - keylet::skip().key.data(), keylet::skip().key.size()); - request.set_type( - protocol::TMLedgerMapType::lmACCOUNT_STATE); + request.set_key(keylet::skip().key.data(), keylet::skip().key.size()); + request.set_type(protocol::TMLedgerMapType::lmACCOUNT_STATE); peerSet_->sendRequest(request, peer); } else { - JLOG(journal_.trace()) << "Add a no feature peer " - << peer->id() << " for " << hash_; - if (++noFeaturePeerCount_ >= - LedgerReplayParameters::MAX_NO_FEATURE_PEER_COUNT) + JLOG(journal_.trace()) << "Add a no feature peer " << peer->id() << " for " << hash_; + if (++noFeaturePeerCount_ >= LedgerReplayParameters::MAX_NO_FEATURE_PEER_COUNT) { JLOG(journal_.debug()) << "Fall back for " << hash_; - timerInterval_ = - LedgerReplayParameters::SUB_TASK_FALLBACK_TIMEOUT; + timerInterval_ = LedgerReplayParameters::SUB_TASK_FALLBACK_TIMEOUT; fallBack_ = true; } } @@ -115,13 +106,9 @@ SkipListAcquire::pmDowncast() } void -SkipListAcquire::processData( - std::uint32_t ledgerSeq, - boost::intrusive_ptr const& item) +SkipListAcquire::processData(std::uint32_t ledgerSeq, boost::intrusive_ptr const& item) { - XRPL_ASSERT( - ledgerSeq != 0 && item, - "xrpl::SkipListAcquire::processData : valid inputs"); + XRPL_ASSERT(ledgerSeq != 0 && item, "xrpl::SkipListAcquire::processData : valid inputs"); ScopedLockType sl(mtx_); if (isDone()) return; @@ -129,12 +116,9 @@ SkipListAcquire::processData( JLOG(journal_.trace()) << "got data for " << hash_; try { - if (auto sle = - std::make_shared(SerialIter{item->slice()}, item->key()); - sle) + if (auto sle = std::make_shared(SerialIter{item->slice()}, item->key()); sle) { - if (auto const& skipList = sle->getFieldV256(sfHashes).value(); - !skipList.empty()) + if (auto const& skipList = sle->getFieldV256(sfHashes).value(); !skipList.empty()) onSkipListAcquired(skipList, ledgerSeq, sl); return; } @@ -144,8 +128,7 @@ SkipListAcquire::processData( } failed_ = true; - JLOG(journal_.error()) << "failed to retrieve Skip list from verified data " - << hash_; + JLOG(journal_.error()) << "failed to retrieve Skip list from verified data " << hash_; notify(sl); } @@ -156,8 +139,7 @@ SkipListAcquire::addDataCallback(OnSkipListDataCB&& cb) dataReadyCallbacks_.emplace_back(std::move(cb)); if (isDone()) { - JLOG(journal_.debug()) - << "task added to a finished SkipListAcquire " << hash_; + JLOG(journal_.debug()) << "task added to a finished SkipListAcquire " << hash_; notify(sl); } } @@ -170,12 +152,9 @@ SkipListAcquire::getData() const } void -SkipListAcquire::retrieveSkipList( - std::shared_ptr const& ledger, - ScopedLockType& sl) +SkipListAcquire::retrieveSkipList(std::shared_ptr const& ledger, ScopedLockType& sl) { - if (auto const hashIndex = ledger->read(keylet::skip()); - hashIndex && hashIndex->isFieldPresent(sfHashes)) + if (auto const hashIndex = ledger->read(keylet::skip()); hashIndex && hashIndex->isFieldPresent(sfHashes)) { auto const& slist = hashIndex->getFieldV256(sfHashes).value(); if (!slist.empty()) @@ -186,16 +165,12 @@ SkipListAcquire::retrieveSkipList( } failed_ = true; - JLOG(journal_.error()) << "failed to retrieve Skip list from a ledger " - << hash_; + JLOG(journal_.error()) << "failed to retrieve Skip list from a ledger " << hash_; notify(sl); } void -SkipListAcquire::onSkipListAcquired( - std::vector const& skipList, - std::uint32_t ledgerSeq, - ScopedLockType& sl) +SkipListAcquire::onSkipListAcquired(std::vector const& skipList, std::uint32_t ledgerSeq, ScopedLockType& sl) { complete_ = true; data_ = std::make_shared(ledgerSeq, skipList); diff --git a/src/xrpld/app/ledger/detail/SkipListAcquire.h b/src/xrpld/app/ledger/detail/SkipListAcquire.h index 15c420a5cd..587f6c19fd 100644 --- a/src/xrpld/app/ledger/detail/SkipListAcquire.h +++ b/src/xrpld/app/ledger/detail/SkipListAcquire.h @@ -19,10 +19,9 @@ class LedgerReplayClient; * Manage the retrieval of a skip list in a ledger from the network. * Before asking peers, always check if the local node has the ledger. */ -class SkipListAcquire final - : public TimeoutCounter, - public std::enable_shared_from_this, - public CountedObject +class SkipListAcquire final : public TimeoutCounter, + public std::enable_shared_from_this, + public CountedObject { public: /** @@ -30,17 +29,14 @@ public: * @param successful if the skipList data was acquired successfully * @param hash hash of the ledger that has the skipList */ - using OnSkipListDataCB = - std::function; + using OnSkipListDataCB = std::function; struct SkipListData { std::uint32_t const ledgerSeq; std::vector const skipList; - SkipListData( - std::uint32_t const ledgerSeq, - std::vector const& skipList) + SkipListData(std::uint32_t const ledgerSeq, std::vector const& skipList) : ledgerSeq(ledgerSeq), skipList(skipList) { } @@ -75,9 +71,7 @@ public: * @note ledgerSeq and item must have been verified against the ledger hash */ void - processData( - std::uint32_t ledgerSeq, - boost::intrusive_ptr const& item); + processData(std::uint32_t ledgerSeq, boost::intrusive_ptr const& item); /** * Add a callback that will be called when the skipList is ready or failed. @@ -111,9 +105,7 @@ private: * @param sl lock. this function must be called with the lock */ void - retrieveSkipList( - std::shared_ptr const& ledger, - ScopedLockType& sl); + retrieveSkipList(std::shared_ptr const& ledger, ScopedLockType& sl); /** * Process the skip list @@ -122,10 +114,7 @@ private: * @param sl lock. this function must be called with the lock */ void - onSkipListAcquired( - std::vector const& skipList, - std::uint32_t ledgerSeq, - ScopedLockType& sl); + onSkipListAcquired(std::vector const& skipList, std::uint32_t ledgerSeq, ScopedLockType& sl); /** * Call the OnSkipListDataCB callbacks diff --git a/src/xrpld/app/ledger/detail/TimeoutCounter.cpp b/src/xrpld/app/ledger/detail/TimeoutCounter.cpp index 3482725148..0ce6de0d34 100644 --- a/src/xrpld/app/ledger/detail/TimeoutCounter.cpp +++ b/src/xrpld/app/ledger/detail/TimeoutCounter.cpp @@ -34,17 +34,16 @@ TimeoutCounter::setTimer(ScopedLockType& sl) if (isDone()) return; timer_.expires_after(timerInterval_); - timer_.async_wait( - [wptr = pmDowncast()](boost::system::error_code const& ec) { - if (ec == boost::asio::error::operation_aborted) - return; + timer_.async_wait([wptr = pmDowncast()](boost::system::error_code const& ec) { + if (ec == boost::asio::error::operation_aborted) + return; - if (auto ptr = wptr.lock()) - { - ScopedLockType sl(ptr->mtx_); - ptr->queueJob(sl); - } - }); + if (auto ptr = wptr.lock()) + { + ScopedLockType sl(ptr->mtx_); + ptr->queueJob(sl); + } + }); } void @@ -53,22 +52,17 @@ TimeoutCounter::queueJob(ScopedLockType& sl) if (isDone()) return; if (queueJobParameter_.jobLimit && - app_.getJobQueue().getJobCountTotal(queueJobParameter_.jobType) >= - queueJobParameter_.jobLimit) + app_.getJobQueue().getJobCountTotal(queueJobParameter_.jobType) >= queueJobParameter_.jobLimit) { - JLOG(journal_.debug()) << "Deferring " << queueJobParameter_.jobName - << " timer due to load"; + JLOG(journal_.debug()) << "Deferring " << queueJobParameter_.jobName << " timer due to load"; setTimer(sl); return; } - app_.getJobQueue().addJob( - queueJobParameter_.jobType, - queueJobParameter_.jobName, - [wptr = pmDowncast()]() { - if (auto sptr = wptr.lock(); sptr) - sptr->invokeOnTimer(); - }); + app_.getJobQueue().addJob(queueJobParameter_.jobType, queueJobParameter_.jobName, [wptr = pmDowncast()]() { + if (auto sptr = wptr.lock(); sptr) + sptr->invokeOnTimer(); + }); } void diff --git a/src/xrpld/app/ledger/detail/TransactionAcquire.cpp b/src/xrpld/app/ledger/detail/TransactionAcquire.cpp index 6b22c6ca8b..f838a912eb 100644 --- a/src/xrpld/app/ledger/detail/TransactionAcquire.cpp +++ b/src/xrpld/app/ledger/detail/TransactionAcquire.cpp @@ -19,21 +19,12 @@ enum { MAX_TIMEOUTS = 20, }; -TransactionAcquire::TransactionAcquire( - Application& app, - uint256 const& hash, - std::unique_ptr peerSet) - : TimeoutCounter( - app, - hash, - TX_ACQUIRE_TIMEOUT, - {jtTXN_DATA, "TxAcq", {}}, - app.journal("TransactionAcquire")) +TransactionAcquire::TransactionAcquire(Application& app, uint256 const& hash, std::unique_ptr peerSet) + : TimeoutCounter(app, hash, TX_ACQUIRE_TIMEOUT, {jtTXN_DATA, "TxAcq", {}}, app.journal("TransactionAcquire")) , mHaveRoot(false) , mPeerSet(std::move(peerSet)) { - mMap = std::make_shared( - SHAMapType::TRANSACTION, hash, app_.getNodeFamily()); + mMap = std::make_shared(SHAMapType::TRANSACTION, hash, app_.getNodeFamily()); mMap->setUnbacked(); } @@ -60,9 +51,7 @@ TransactionAcquire::done() // just updates the consensus and related structures when we acquire // a transaction set. No need to update them if we're shutting down. app_.getJobQueue().addJob( - jtTXN_DATA, "ComplAcquire", [pap, hash, map]() { - pap->getInboundTransactions().giveSet(hash, map, true); - }); + jtTXN_DATA, "ComplAcquire", [pap, hash, map]() { pap->getInboundTransactions().giveSet(hash, map, true); }); } } @@ -104,8 +93,7 @@ TransactionAcquire::trigger(std::shared_ptr const& peer) if (!mHaveRoot) { - JLOG(journal_.trace()) << "TransactionAcquire::trigger " - << (peer ? "havePeer" : "noPeer") << " no root"; + JLOG(journal_.trace()) << "TransactionAcquire::trigger " << (peer ? "havePeer" : "noPeer") << " no root"; protocol::TMGetLedger tmGL; tmGL.set_ledgerhash(hash_.begin(), hash_.size()); tmGL.set_itype(protocol::liTS_CANDIDATE); @@ -184,11 +172,8 @@ TransactionAcquire::takeNodes( if (d.first.isRoot()) { if (mHaveRoot) - JLOG(journal_.debug()) - << "Got root TXS node, already have it"; - else if (!mMap->addRootNode( - SHAMapHash{hash_}, d.second, nullptr) - .isGood()) + JLOG(journal_.debug()) << "Got root TXS node, already have it"; + else if (!mMap->addRootNode(SHAMapHash{hash_}, d.second, nullptr).isGood()) { JLOG(journal_.warn()) << "TX acquire got bad root node"; } @@ -208,9 +193,7 @@ TransactionAcquire::takeNodes( } catch (std::exception const& ex) { - JLOG(journal_.error()) - << "Peer " << peer->id() - << " sent us junky transaction node data: " << ex.what(); + JLOG(journal_.error()) << "Peer " << peer->id() << " sent us junky transaction node data: " << ex.what(); return SHAMapAddNode::invalid(); } } @@ -219,9 +202,7 @@ void TransactionAcquire::addPeers(std::size_t limit) { mPeerSet->addPeers( - limit, - [this](auto peer) { return peer->hasTxSet(hash_); }, - [this](auto peer) { trigger(peer); }); + limit, [this](auto peer) { return peer->hasTxSet(hash_); }, [this](auto peer) { trigger(peer); }); } void diff --git a/src/xrpld/app/ledger/detail/TransactionAcquire.h b/src/xrpld/app/ledger/detail/TransactionAcquire.h index 83f9b62f83..dd12e8afb0 100644 --- a/src/xrpld/app/ledger/detail/TransactionAcquire.h +++ b/src/xrpld/app/ledger/detail/TransactionAcquire.h @@ -9,24 +9,18 @@ namespace xrpl { // VFALCO TODO rename to PeerTxRequest // A transaction set we are trying to acquire -class TransactionAcquire final - : public TimeoutCounter, - public std::enable_shared_from_this, - public CountedObject +class TransactionAcquire final : public TimeoutCounter, + public std::enable_shared_from_this, + public CountedObject { public: using pointer = std::shared_ptr; - TransactionAcquire( - Application& app, - uint256 const& hash, - std::unique_ptr peerSet); + TransactionAcquire(Application& app, uint256 const& hash, std::unique_ptr peerSet); ~TransactionAcquire() = default; SHAMapAddNode - takeNodes( - std::vector> const& data, - std::shared_ptr const&); + takeNodes(std::vector> const& data, std::shared_ptr const&); void init(int startPeers); diff --git a/src/xrpld/app/ledger/detail/TransactionMaster.cpp b/src/xrpld/app/ledger/detail/TransactionMaster.cpp index e8580bcfc6..834234dd4e 100644 --- a/src/xrpld/app/ledger/detail/TransactionMaster.cpp +++ b/src/xrpld/app/ledger/detail/TransactionMaster.cpp @@ -9,13 +9,7 @@ namespace xrpl { TransactionMaster::TransactionMaster(Application& app) - : mApp(app) - , mCache( - "TransactionCache", - 65536, - std::chrono::minutes{30}, - stopwatch(), - mApp.journal("TaggedCache")) + : mApp(app), mCache("TransactionCache", 65536, std::chrono::minutes{30}, stopwatch(), mApp.journal("TaggedCache")) { } @@ -41,13 +35,10 @@ TransactionMaster::fetch_from_cache(uint256 const& txnID) return mCache.fetch(txnID); } -std::variant< - std::pair, std::shared_ptr>, - TxSearched> +std::variant, std::shared_ptr>, TxSearched> TransactionMaster::fetch(uint256 const& txnID, error_code_i& ec) { - using TxPair = - std::pair, std::shared_ptr>; + using TxPair = std::pair, std::shared_ptr>; if (auto txn = fetch_from_cache(txnID); txn && !txn->isValidated()) return std::pair{std::move(txn), nullptr}; @@ -65,16 +56,10 @@ TransactionMaster::fetch(uint256 const& txnID, error_code_i& ec) return std::pair{std::move(txn), std::move(txnMeta)}; } -std::variant< - std::pair, std::shared_ptr>, - TxSearched> -TransactionMaster::fetch( - uint256 const& txnID, - ClosedInterval const& range, - error_code_i& ec) +std::variant, std::shared_ptr>, TxSearched> +TransactionMaster::fetch(uint256 const& txnID, ClosedInterval const& range, error_code_i& ec) { - using TxPair = - std::pair, std::shared_ptr>; + using TxPair = std::pair, std::shared_ptr>; if (auto txn = fetch_from_cache(txnID); txn && !txn->isValidated()) return std::pair{std::move(txn), nullptr}; @@ -93,10 +78,7 @@ TransactionMaster::fetch( } std::shared_ptr -TransactionMaster::fetch( - boost::intrusive_ptr const& item, - SHAMapNodeType type, - std::uint32_t uCommitLedger) +TransactionMaster::fetch(boost::intrusive_ptr const& item, SHAMapNodeType type, std::uint32_t uCommitLedger) { std::shared_ptr txn; auto iTx = fetch_from_cache(item->key()); @@ -111,8 +93,7 @@ TransactionMaster::fetch( else if (type == SHAMapNodeType::tnTRANSACTION_MD) { auto blob = SerialIter{item->slice()}.getVL(); - txn = std::make_shared( - SerialIter{blob.data(), blob.size()}); + txn = std::make_shared(SerialIter{blob.data(), blob.size()}); } } else diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index 785b02dbb8..3045097e4a 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -89,10 +89,7 @@ private: beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_context& ios) - : m_event(ev) - , m_journal(journal) - , m_probe(interval, ios) - , lastSample_{} + : m_event(ev), m_journal(journal), m_probe(interval, ios), lastSample_{} { } @@ -115,8 +112,7 @@ private: m_event.notify(lastSample); if (lastSample >= 500ms) { - JLOG(m_journal.warn()) - << "io_context latency = " << lastSample.count(); + JLOG(m_journal.warn()) << "io_context latency = " << lastSample.count(); } } @@ -239,35 +235,24 @@ public: //-------------------------------------------------------------------------- - ApplicationImp( - std::unique_ptr config, - std::unique_ptr logs, - std::unique_ptr timeKeeper) + ApplicationImp(std::unique_ptr config, std::unique_ptr logs, std::unique_ptr timeKeeper) : BasicApp(numberOfThreads(*config)) , config_(std::move(config)) , logs_(std::move(logs)) , timeKeeper_(std::move(timeKeeper)) - , instanceCookie_( - 1 + - rand_int( - crypto_prng(), - std::numeric_limits::max() - 1)) + , instanceCookie_(1 + rand_int(crypto_prng(), std::numeric_limits::max() - 1)) , m_journal(logs_->journal("Application")) // PerfLog must be started before any other threads are launched. , perfLog_(perf::make_PerfLog( - perf::setup_PerfLog( - config_->section("perf"), - config_->CONFIG_DIR), + perf::setup_PerfLog(config_->section("perf"), config_->CONFIG_DIR), *this, logs_->journal("PerfLog"), [this] { signalStop("PerfLog"); })) , m_txMaster(*this) - , m_collectorManager(make_CollectorManager( - config_->section(SECTION_INSIGHT), - logs_->journal("Collector"))) + , m_collectorManager(make_CollectorManager(config_->section(SECTION_INSIGHT), logs_->journal("Collector"))) , m_jobQueue(std::make_unique( [](std::unique_ptr const& config) { @@ -277,8 +262,7 @@ public: if (config->WORKERS) return config->WORKERS; - auto count = - static_cast(std::thread::hardware_concurrency()); + auto count = static_cast(std::thread::hardware_concurrency()); // Be more aggressive about the number of threads to use // for the job queue if the server is configured as @@ -299,42 +283,24 @@ public: , m_nodeStoreScheduler(*m_jobQueue) - , m_shaMapStore(make_SHAMapStore( - *this, - m_nodeStoreScheduler, - logs_->journal("SHAMapStore"))) + , m_shaMapStore(make_SHAMapStore(*this, m_nodeStoreScheduler, logs_->journal("SHAMapStore"))) - , m_tempNodeCache( - "NodeCache", - 16384, - std::chrono::seconds{90}, - stopwatch(), - logs_->journal("TaggedCache")) + , m_tempNodeCache("NodeCache", 16384, std::chrono::seconds{90}, stopwatch(), logs_->journal("TaggedCache")) - , cachedSLEs_( - "Cached SLEs", - 0, - std::chrono::minutes(1), - stopwatch(), - logs_->journal("CachedSLEs")) + , cachedSLEs_("Cached SLEs", 0, std::chrono::minutes(1), stopwatch(), logs_->journal("CachedSLEs")) , validatorKeys_(*config_, m_journal) - , m_resourceManager(Resource::make_Manager( - m_collectorManager->collector(), - logs_->journal("Resource"))) + , m_resourceManager(Resource::make_Manager(m_collectorManager->collector(), logs_->journal("Resource"))) - , m_nodeStore(m_shaMapStore->makeNodeStore( - config_->PREFETCH_WORKERS > 0 ? config_->PREFETCH_WORKERS : 4)) + , m_nodeStore(m_shaMapStore->makeNodeStore(config_->PREFETCH_WORKERS > 0 ? config_->PREFETCH_WORKERS : 4)) , nodeFamily_(*this, *m_collectorManager) , m_orderBookDB(*this) - , m_pathRequests(std::make_unique( - *this, - logs_->journal("PathRequest"), - m_collectorManager->collector())) + , m_pathRequests( + std::make_unique(*this, logs_->journal("PathRequest"), m_collectorManager->collector())) , m_ledgerMaster(std::make_unique( *this, @@ -342,28 +308,19 @@ public: m_collectorManager->collector(), logs_->journal("LedgerMaster"))) - , ledgerCleaner_( - make_LedgerCleaner(*this, logs_->journal("LedgerCleaner"))) + , ledgerCleaner_(make_LedgerCleaner(*this, logs_->journal("LedgerCleaner"))) // VFALCO NOTE must come before NetworkOPs to prevent a crash due // to dependencies in the destructor. // - , m_inboundLedgers(make_InboundLedgers( - *this, - stopwatch(), - m_collectorManager->collector())) + , m_inboundLedgers(make_InboundLedgers(*this, stopwatch(), m_collectorManager->collector())) , m_inboundTransactions(make_InboundTransactions( *this, m_collectorManager->collector(), - [this](std::shared_ptr const& set, bool fromAcquire) { - gotTXSet(set, fromAcquire); - })) + [this](std::shared_ptr const& set, bool fromAcquire) { gotTXSet(set, fromAcquire); })) - , m_ledgerReplayer(std::make_unique( - *this, - *m_inboundLedgers, - make_PeerSetBuilder(*this))) + , m_ledgerReplayer(std::make_unique(*this, *m_inboundLedgers, make_PeerSetBuilder(*this))) , m_acceptedLedgerCache( "AcceptedLedger", @@ -387,14 +344,11 @@ public: , cluster_(std::make_unique(logs_->journal("Overlay"))) - , peerReservations_(std::make_unique( - logs_->journal("PeerReservationTable"))) + , peerReservations_(std::make_unique(logs_->journal("PeerReservationTable"))) - , validatorManifests_( - std::make_unique(logs_->journal("ManifestCache"))) + , validatorManifests_(std::make_unique(logs_->journal("ManifestCache"))) - , publisherManifests_( - std::make_unique(logs_->journal("ManifestCache"))) + , publisherManifests_(std::make_unique(logs_->journal("ManifestCache"))) , validators_(std::make_unique( *validatorManifests_, @@ -414,23 +368,15 @@ public: *m_resourceManager, *m_collectorManager)) - , mFeeTrack( - std::make_unique(logs_->journal("LoadManager"))) + , mFeeTrack(std::make_unique(logs_->journal("LoadManager"))) - , hashRouter_(std::make_unique( - setup_HashRouter(*config_), - stopwatch())) + , hashRouter_(std::make_unique(setup_HashRouter(*config_), stopwatch())) - , mValidations( - ValidationParms(), - stopwatch(), - *this, - logs_->journal("Validations")) + , mValidations(ValidationParms(), stopwatch(), *this, logs_->journal("Validations")) , m_loadManager(make_LoadManager(*this, logs_->journal("LoadManager"))) - , txQ_( - std::make_unique(setup_TxQ(*config_), logs_->journal("TxQ"))) + , txQ_(std::make_unique(setup_TxQ(*config_), logs_->journal("TxQ"))) , sweepTimer_(get_io_context()) @@ -440,8 +386,7 @@ public: , checkSigs_(true) - , m_resolver( - ResolverAsio::New(get_io_context(), logs_->journal("Resolver"))) + , m_resolver(ResolverAsio::New(get_io_context(), logs_->journal("Resolver"))) , m_io_latency_sampler( m_collectorManager->collector()->make_event("ios_latency"), @@ -541,8 +486,7 @@ public: if (nodeIdentity_) return *nodeIdentity_; - LogicError( - "Accessing Application::nodeIdentity() before it is initialized."); + LogicError("Accessing Application::nodeIdentity() before it is initialized."); } std::optional @@ -772,16 +716,14 @@ public: Overlay& overlay() override { - XRPL_ASSERT( - overlay_, "xrpl::ApplicationImp::overlay : non-null overlay"); + XRPL_ASSERT(overlay_, "xrpl::ApplicationImp::overlay : non-null overlay"); return *overlay_; } TxQ& getTxQ() override { - XRPL_ASSERT( - txQ_, "xrpl::ApplicationImp::getTxQ : non-null transaction queue"); + XRPL_ASSERT(txQ_, "xrpl::ApplicationImp::getTxQ : non-null transaction queue"); return *txQ_; } @@ -798,9 +740,7 @@ public: DatabaseCon& getWalletDB() override { - XRPL_ASSERT( - mWalletDB, - "xrpl::ApplicationImp::getWalletDB : non-null wallet database"); + XRPL_ASSERT(mWalletDB, "xrpl::ApplicationImp::getWalletDB : non-null wallet database"); return *mWalletDB; } @@ -822,8 +762,7 @@ public: try { - mRelationalDatabase = - RelationalDatabase::init(*this, *config_, *m_jobQueue); + mRelationalDatabase = RelationalDatabase::init(*this, *config_, *m_jobQueue); // wallet database auto setup = setup_DatabaseCon(*config_, m_journal); @@ -833,8 +772,7 @@ public: } catch (std::exception const& e) { - JLOG(m_journal.fatal()) - << "Failed to initialize SQL databases: " << e.what(); + JLOG(m_journal.fatal()) << "Failed to initialize SQL databases: " << e.what(); return false; } @@ -848,27 +786,23 @@ public: { auto j = logs_->journal("NodeObject"); NodeStore::DummyScheduler dummyScheduler; - std::unique_ptr source = - NodeStore::Manager::instance().make_Database( - megabytes(config_->getValueFor( - SizedItem::burstSize, std::nullopt)), - dummyScheduler, - 0, - config_->section(ConfigSection::importNodeDatabase()), - j); + std::unique_ptr source = NodeStore::Manager::instance().make_Database( + megabytes(config_->getValueFor(SizedItem::burstSize, std::nullopt)), + dummyScheduler, + 0, + config_->section(ConfigSection::importNodeDatabase()), + j); - JLOG(j.warn()) << "Starting node import from '" << source->getName() - << "' to '" << m_nodeStore->getName() << "'."; + JLOG(j.warn()) << "Starting node import from '" << source->getName() << "' to '" << m_nodeStore->getName() + << "'."; using namespace std::chrono; auto const start = steady_clock::now(); m_nodeStore->importDatabase(*source); - auto const elapsed = - duration_cast(steady_clock::now() - start); - JLOG(j.warn()) << "Node import from '" << source->getName() - << "' took " << elapsed.count() << " seconds."; + auto const elapsed = duration_cast(steady_clock::now() - start); + JLOG(j.warn()) << "Node import from '" << source->getName() << "' took " << elapsed.count() << " seconds."; } return true; @@ -890,28 +824,23 @@ public: setSweepTimer() { // Only start the timer if waitHandlerCounter_ is not yet joined. - if (auto optionalCountedHandler = waitHandlerCounter_.wrap( - [this](boost::system::error_code const& e) { - if (e.value() == boost::system::errc::success) - { - m_jobQueue->addJob( - jtSWEEP, "sweep", [this]() { doSweep(); }); - } - // Recover as best we can if an unexpected error occurs. - if (e.value() != boost::system::errc::success && - e.value() != boost::asio::error::operation_aborted) - { - // Try again later and hope for the best. - JLOG(m_journal.error()) - << "Sweep timer got error '" << e.message() - << "'. Restarting timer."; - setSweepTimer(); - } - })) + if (auto optionalCountedHandler = waitHandlerCounter_.wrap([this](boost::system::error_code const& e) { + if (e.value() == boost::system::errc::success) + { + m_jobQueue->addJob(jtSWEEP, "sweep", [this]() { doSweep(); }); + } + // Recover as best we can if an unexpected error occurs. + if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted) + { + // Try again later and hope for the best. + JLOG(m_journal.error()) << "Sweep timer got error '" << e.message() << "'. Restarting timer."; + setSweepTimer(); + } + })) { using namespace std::chrono; - sweepTimer_.expires_after(seconds{config_->SWEEP_INTERVAL.value_or( - config_->getValueFor(SizedItem::sweepInterval))}); + sweepTimer_.expires_after( + seconds{config_->SWEEP_INTERVAL.value_or(config_->getValueFor(SizedItem::sweepInterval))}); sweepTimer_.async_wait(std::move(*optionalCountedHandler)); } } @@ -920,24 +849,20 @@ public: setEntropyTimer() { // Only start the timer if waitHandlerCounter_ is not yet joined. - if (auto optionalCountedHandler = waitHandlerCounter_.wrap( - [this](boost::system::error_code const& e) { - if (e.value() == boost::system::errc::success) - { - crypto_prng().mix_entropy(); - setEntropyTimer(); - } - // Recover as best we can if an unexpected error occurs. - if (e.value() != boost::system::errc::success && - e.value() != boost::asio::error::operation_aborted) - { - // Try again later and hope for the best. - JLOG(m_journal.error()) - << "Entropy timer got error '" << e.message() - << "'. Restarting timer."; - setEntropyTimer(); - } - })) + if (auto optionalCountedHandler = waitHandlerCounter_.wrap([this](boost::system::error_code const& e) { + if (e.value() == boost::system::errc::success) + { + crypto_prng().mix_entropy(); + setEntropyTimer(); + } + // Recover as best we can if an unexpected error occurs. + if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted) + { + // Try again later and hope for the best. + JLOG(m_journal.error()) << "Entropy timer got error '" << e.message() << "'. Restarting timer."; + setEntropyTimer(); + } + })) { using namespace std::chrono_literals; entropyTimer_.expires_after(5min); @@ -948,8 +873,7 @@ public: void doSweep() { - if (!config_->standalone() && - !getRelationalDatabase().transactionDbHasSpace(*config_)) + if (!config_->standalone() && !getRelationalDatabase().transactionDbHasSpace(*config_)) { signalStop("Out of transaction DB space"); } @@ -959,52 +883,42 @@ public: // have listeners register for "onSweep ()" notification. { - std::shared_ptr const fullBelowCache = - nodeFamily_.getFullBelowCache(); + std::shared_ptr const fullBelowCache = nodeFamily_.getFullBelowCache(); - std::shared_ptr const treeNodeCache = - nodeFamily_.getTreeNodeCache(); + std::shared_ptr const treeNodeCache = nodeFamily_.getTreeNodeCache(); std::size_t const oldFullBelowSize = fullBelowCache->size(); std::size_t const oldTreeNodeSize = treeNodeCache->size(); nodeFamily_.sweep(); - JLOG(m_journal.debug()) - << "NodeFamily::FullBelowCache sweep. Size before: " - << oldFullBelowSize - << "; size after: " << fullBelowCache->size(); + JLOG(m_journal.debug()) << "NodeFamily::FullBelowCache sweep. Size before: " << oldFullBelowSize + << "; size after: " << fullBelowCache->size(); - JLOG(m_journal.debug()) - << "NodeFamily::TreeNodeCache sweep. Size before: " - << oldTreeNodeSize << "; size after: " << treeNodeCache->size(); + JLOG(m_journal.debug()) << "NodeFamily::TreeNodeCache sweep. Size before: " << oldTreeNodeSize + << "; size after: " << treeNodeCache->size(); } { - TaggedCache const& masterTxCache = - getMasterTransaction().getCache(); + TaggedCache const& masterTxCache = getMasterTransaction().getCache(); std::size_t const oldMasterTxSize = masterTxCache.size(); getMasterTransaction().sweep(); - JLOG(m_journal.debug()) - << "MasterTransaction sweep. Size before: " << oldMasterTxSize - << "; size after: " << masterTxCache.size(); + JLOG(m_journal.debug()) << "MasterTransaction sweep. Size before: " << oldMasterTxSize + << "; size after: " << masterTxCache.size(); } { // Does not appear to have an associated cache. getNodeStore().sweep(); } { - std::size_t const oldLedgerMasterCacheSize = - getLedgerMaster().getFetchPackCacheSize(); + std::size_t const oldLedgerMasterCacheSize = getLedgerMaster().getFetchPackCacheSize(); getLedgerMaster().sweep(); - JLOG(m_journal.debug()) - << "LedgerMaster sweep. Size before: " - << oldLedgerMasterCacheSize << "; size after: " - << getLedgerMaster().getFetchPackCacheSize(); + JLOG(m_journal.debug()) << "LedgerMaster sweep. Size before: " << oldLedgerMasterCacheSize + << "; size after: " << getLedgerMaster().getFetchPackCacheSize(); } { // NodeCache == TaggedCache @@ -1012,52 +926,36 @@ public: getTempNodeCache().sweep(); - JLOG(m_journal.debug()) - << "TempNodeCache sweep. Size before: " << oldTempNodeCacheSize - << "; size after: " << getTempNodeCache().size(); + JLOG(m_journal.debug()) << "TempNodeCache sweep. Size before: " << oldTempNodeCacheSize + << "; size after: " << getTempNodeCache().size(); } { - std::size_t const oldCurrentCacheSize = - getValidations().sizeOfCurrentCache(); - std::size_t const oldSizeSeqEnforcesSize = - getValidations().sizeOfSeqEnforcersCache(); - std::size_t const oldByLedgerSize = - getValidations().sizeOfByLedgerCache(); - std::size_t const oldBySequenceSize = - getValidations().sizeOfBySequenceCache(); + std::size_t const oldCurrentCacheSize = getValidations().sizeOfCurrentCache(); + std::size_t const oldSizeSeqEnforcesSize = getValidations().sizeOfSeqEnforcersCache(); + std::size_t const oldByLedgerSize = getValidations().sizeOfByLedgerCache(); + std::size_t const oldBySequenceSize = getValidations().sizeOfBySequenceCache(); getValidations().expire(m_journal); - JLOG(m_journal.debug()) - << "Validations Current expire. Size before: " - << oldCurrentCacheSize - << "; size after: " << getValidations().sizeOfCurrentCache(); + JLOG(m_journal.debug()) << "Validations Current expire. Size before: " << oldCurrentCacheSize + << "; size after: " << getValidations().sizeOfCurrentCache(); - JLOG(m_journal.debug()) - << "Validations SeqEnforcer expire. Size before: " - << oldSizeSeqEnforcesSize << "; size after: " - << getValidations().sizeOfSeqEnforcersCache(); + JLOG(m_journal.debug()) << "Validations SeqEnforcer expire. Size before: " << oldSizeSeqEnforcesSize + << "; size after: " << getValidations().sizeOfSeqEnforcersCache(); - JLOG(m_journal.debug()) - << "Validations ByLedger expire. Size before: " - << oldByLedgerSize - << "; size after: " << getValidations().sizeOfByLedgerCache(); + JLOG(m_journal.debug()) << "Validations ByLedger expire. Size before: " << oldByLedgerSize + << "; size after: " << getValidations().sizeOfByLedgerCache(); - JLOG(m_journal.debug()) - << "Validations BySequence expire. Size before: " - << oldBySequenceSize - << "; size after: " << getValidations().sizeOfBySequenceCache(); + JLOG(m_journal.debug()) << "Validations BySequence expire. Size before: " << oldBySequenceSize + << "; size after: " << getValidations().sizeOfBySequenceCache(); } { - std::size_t const oldInboundLedgersSize = - getInboundLedgers().cacheSize(); + std::size_t const oldInboundLedgersSize = getInboundLedgers().cacheSize(); getInboundLedgers().sweep(); - JLOG(m_journal.debug()) - << "InboundLedgers sweep. Size before: " - << oldInboundLedgersSize - << "; size after: " << getInboundLedgers().cacheSize(); + JLOG(m_journal.debug()) << "InboundLedgers sweep. Size before: " << oldInboundLedgersSize + << "; size after: " << getInboundLedgers().cacheSize(); } { size_t const oldTasksSize = getLedgerReplayer().tasksSize(); @@ -1066,39 +964,30 @@ public: getLedgerReplayer().sweep(); - JLOG(m_journal.debug()) - << "LedgerReplayer tasks sweep. Size before: " << oldTasksSize - << "; size after: " << getLedgerReplayer().tasksSize(); + JLOG(m_journal.debug()) << "LedgerReplayer tasks sweep. Size before: " << oldTasksSize + << "; size after: " << getLedgerReplayer().tasksSize(); - JLOG(m_journal.debug()) - << "LedgerReplayer deltas sweep. Size before: " - << oldDeltasSize - << "; size after: " << getLedgerReplayer().deltasSize(); + JLOG(m_journal.debug()) << "LedgerReplayer deltas sweep. Size before: " << oldDeltasSize + << "; size after: " << getLedgerReplayer().deltasSize(); - JLOG(m_journal.debug()) - << "LedgerReplayer skipLists sweep. Size before: " - << oldSkipListsSize - << "; size after: " << getLedgerReplayer().skipListsSize(); + JLOG(m_journal.debug()) << "LedgerReplayer skipLists sweep. Size before: " << oldSkipListsSize + << "; size after: " << getLedgerReplayer().skipListsSize(); } { - std::size_t const oldAcceptedLedgerSize = - m_acceptedLedgerCache.size(); + std::size_t const oldAcceptedLedgerSize = m_acceptedLedgerCache.size(); m_acceptedLedgerCache.sweep(); - JLOG(m_journal.debug()) - << "AcceptedLedgerCache sweep. Size before: " - << oldAcceptedLedgerSize - << "; size after: " << m_acceptedLedgerCache.size(); + JLOG(m_journal.debug()) << "AcceptedLedgerCache sweep. Size before: " << oldAcceptedLedgerSize + << "; size after: " << m_acceptedLedgerCache.size(); } { std::size_t const oldCachedSLEsSize = cachedSLEs_.size(); cachedSLEs_.sweep(); - JLOG(m_journal.debug()) - << "CachedSLEs sweep. Size before: " << oldCachedSLEsSize - << "; size after: " << cachedSLEs_.size(); + JLOG(m_journal.debug()) << "CachedSLEs sweep. Size before: " << oldCachedSLEsSize + << "; size after: " << cachedSLEs_.size(); } // Set timer to do another sweep later. @@ -1132,11 +1021,7 @@ private: loadLedgerFromFile(std::string const& ledgerID); bool - loadOldLedger( - std::string const& ledgerID, - bool replay, - bool isFilename, - std::optional trapTxID); + loadOldLedger(std::string const& ledgerID, bool replay, bool isFilename, std::optional trapTxID); void setMaxDisallowedLedger(); @@ -1158,17 +1043,16 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) // to async_wait). m_signals.add(SIGINT); m_signals.add(SIGTERM); - m_signals.async_wait( - [this](boost::system::error_code const& ec, int signum) { - // Indicates the signal handler has been aborted; do nothing - if (ec == boost::asio::error::operation_aborted) - return; + m_signals.async_wait([this](boost::system::error_code const& ec, int signum) { + // Indicates the signal handler has been aborted; do nothing + if (ec == boost::asio::error::operation_aborted) + return; - JLOG(m_journal.info()) << "Received signal " << signum; + JLOG(m_journal.info()) << "Received signal " << signum; - if (signum == SIGTERM || signum == SIGINT) - signalStop("Signal: " + to_string(signum)); - }); + if (signum == SIGTERM || signum == SIGINT) + signalStop("Signal: " + to_string(signum)); + }); auto debug_log = config_->getDebugLogFile(); @@ -1185,8 +1069,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) logs_->threshold(kDebug); } - JLOG(m_journal.info()) << "Process starting: " - << BuildInfo::getFullVersionString() + JLOG(m_journal.info()) << "Process starting: " << BuildInfo::getFullVersionString() << ", Instance Cookie: " << instanceCookie_; if (numberOfThreads(*config_) < 2) @@ -1219,8 +1102,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) for (auto const& [a, vote] : amendments) { auto const f = xrpl::getRegisteredFeature(a); - XRPL_ASSERT( - f, "xrpl::ApplicationImp::setup : registered feature"); + XRPL_ASSERT(f, "xrpl::ApplicationImp::setup : registered feature"); if (f) supported.emplace_back(a, *f, vote); } @@ -1231,12 +1113,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) Section const& upVoted = config_->section(SECTION_AMENDMENTS); m_amendmentTable = make_AmendmentTable( - *this, - config().AMENDMENT_MAJORITY_TIME, - supported, - upVoted, - downVoted, - logs_->journal("Amendments")); + *this, config().AMENDMENT_MAJORITY_TIME, supported, upVoted, downVoted, logs_->journal("Amendments")); } Pathfinder::initPathTable(); @@ -1249,20 +1126,14 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) startGenesisLedger(); } - else if ( - startUp == Config::LOAD || startUp == Config::LOAD_FILE || - startUp == Config::REPLAY) + else if (startUp == Config::LOAD || startUp == Config::LOAD_FILE || startUp == Config::REPLAY) { JLOG(m_journal.info()) << "Loading specified Ledger"; if (!loadOldLedger( - config_->START_LEDGER, - startUp == Config::REPLAY, - startUp == Config::LOAD_FILE, - config_->TRAP_TX_HASH)) + config_->START_LEDGER, startUp == Config::REPLAY, startUp == Config::LOAD_FILE, config_->TRAP_TX_HASH)) { - JLOG(m_journal.error()) - << "The specified ledger could not be loaded."; + JLOG(m_journal.error()) << "The specified ledger could not be loaded."; if (config_->FAST_LOAD) { // Fall back to syncing from the network, such as @@ -1291,8 +1162,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) if (auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT) { - m_ledgerMaster->setLedgerRangePresent( - forcedRange->first, forcedRange->second); + m_ledgerMaster->setLedgerRangePresent(forcedRange->first, forcedRange->second); } m_orderBookDB.setup(getLedgerMaster().getCurrentLedger()); @@ -1338,17 +1208,14 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) config().section(SECTION_VALIDATOR_LIST_KEYS).values(), config().VALIDATOR_LIST_THRESHOLD)) { - JLOG(m_journal.fatal()) - << "Invalid entry in validator configuration."; + JLOG(m_journal.fatal()) << "Invalid entry in validator configuration."; return false; } } - if (!validatorSites_->load( - config().section(SECTION_VALIDATOR_LIST_SITES).values())) + if (!validatorSites_->load(config().section(SECTION_VALIDATOR_LIST_SITES).values())) { - JLOG(m_journal.fatal()) - << "Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES << "]"; + JLOG(m_journal.fatal()) << "Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES << "]"; return false; } @@ -1378,8 +1245,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) add(*overlay_); // add to PropertyStream // start first consensus round - if (!m_networkOPs->beginConsensus( - m_ledgerMaster->getClosedLedger()->header().hash, {})) + if (!m_networkOPs->beginConsensus(m_ledgerMaster->getClosedLedger()->header().hash, {})) { JLOG(m_journal.fatal()) << "Unable to start consensus"; return false; @@ -1388,8 +1254,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) { try { - auto setup = setup_ServerHandler( - *config_, beast::logstream{m_journal.error()}); + auto setup = setup_ServerHandler(*config_, beast::logstream{m_journal.error()}); setup.makeContexts(); serverHandler_->setup(setup, m_journal); fixConfigPorts(*config_, serverHandler_->endpoints()); @@ -1413,8 +1278,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) // of message, if displayed, should be displayed from PeerFinder. if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty()) { - JLOG(m_journal.warn()) - << "No outbound peer connections will be made"; + JLOG(m_journal.warn()) << "No outbound peer connections will be made"; } // VFALCO NOTE the state timer resets the deadlock detector. @@ -1439,12 +1303,10 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) JLOG(m_journal.warn()) << "*** rippled."; JLOG(m_journal.warn()) << "*** If you do not use them to sign " "transactions please edit your"; - JLOG(m_journal.warn()) - << "*** configuration file and remove the [enable_signing] stanza."; + JLOG(m_journal.warn()) << "*** configuration file and remove the [enable_signing] stanza."; JLOG(m_journal.warn()) << "*** If you do use them to sign transactions " "please migrate to a"; - JLOG(m_journal.warn()) - << "*** standalone signing solution as soon as possible."; + JLOG(m_journal.warn()) << "*** standalone signing solution as soon as possible."; } // @@ -1457,14 +1319,12 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) if (!jrReader.parse(cmd, jvCommand)) { - JLOG(m_journal.fatal()) << "Couldn't parse entry in [" - << SECTION_RPC_STARTUP << "]: '" << cmd; + JLOG(m_journal.fatal()) << "Couldn't parse entry in [" << SECTION_RPC_STARTUP << "]: '" << cmd; } if (!config_->quiet()) { - JLOG(m_journal.fatal()) - << "Startup RPC: " << jvCommand << std::endl; + JLOG(m_journal.fatal()) << "Startup RPC: " << jvCommand << std::endl; } Resource::Charge loadType = Resource::feeReferenceRPC; @@ -1499,8 +1359,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) void ApplicationImp::start(bool withTimers) { - JLOG(m_journal.info()) << "Application starting. Version is " - << BuildInfo::getVersionString(); + JLOG(m_journal.info()) << "Application starting. Version is " << BuildInfo::getVersionString(); if (withTimers) { @@ -1516,8 +1375,7 @@ ApplicationImp::start(bool withTimers) overlay_->start(); if (grpcServer_->start()) - fixConfigPorts( - *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}}); + fixConfigPorts(*config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}}); ledgerCleaner_->start(); perfLog_->start(); @@ -1563,8 +1421,7 @@ ApplicationImp::run() } catch (boost::system::system_error const& e) { - JLOG(m_journal.error()) - << "Application: sweepTimer cancel error: " << e.what(); + JLOG(m_journal.error()) << "Application: sweepTimer cancel error: " << e.what(); } try @@ -1573,8 +1430,7 @@ ApplicationImp::run() } catch (boost::system::system_error const& e) { - JLOG(m_journal.error()) - << "Application: entropyTimer cancel error: " << e.what(); + JLOG(m_journal.error()) << "Application: entropyTimer cancel error: " << e.what(); } } @@ -1590,14 +1446,11 @@ ApplicationImp::run() // TODO Store manifests in manifests.sqlite instead of wallet.db validatorManifests_->save( - getWalletDB(), "ValidatorManifests", [this](PublicKey const& pubKey) { - return validators().listed(pubKey); - }); + getWalletDB(), "ValidatorManifests", [this](PublicKey const& pubKey) { return validators().listed(pubKey); }); - publisherManifests_->save( - getWalletDB(), "PublisherManifests", [this](PublicKey const& pubKey) { - return validators().trustedPublisher(pubKey); - }); + publisherManifests_->save(getWalletDB(), "PublisherManifests", [this](PublicKey const& pubKey) { + return validators().trustedPublisher(pubKey); + }); // The order of these stop calls is delicate. // Re-ordering them risks undefined behavior. @@ -1680,19 +1533,16 @@ void ApplicationImp::startGenesisLedger() { std::vector const initialAmendments = - (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired() - : std::vector{}; + (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired() : std::vector{}; - std::shared_ptr const genesis = std::make_shared( - create_genesis, *config_, initialAmendments, nodeFamily_); + std::shared_ptr const genesis = + std::make_shared(create_genesis, *config_, initialAmendments, nodeFamily_); m_ledgerMaster->storeLedger(genesis); - auto const next = - std::make_shared(*genesis, timeKeeper().closeTime()); + auto const next = std::make_shared(*genesis, timeKeeper().closeTime()); next->updateSkipList(); XRPL_ASSERT( - next->header().seq < XRP_LEDGER_EARLIEST_FEES || - next->read(keylet::fees()), + next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()), "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees"); next->setImmutable(); openLedger_.emplace(next, cachedSLEs_, logs_->journal("OpenLedger")); @@ -1713,8 +1563,7 @@ ApplicationImp::getLastFullLedger() return ledger; XRPL_ASSERT( - ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || - ledger->read(keylet::fees()), + ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()), "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees"); ledger->setImmutable(); @@ -1798,18 +1647,15 @@ ApplicationImp::loadLedgerFromFile(std::string const& name) if (ledger.get().isMember("close_time_resolution")) { using namespace std::chrono; - closeTimeResolution = - seconds{ledger.get()["close_time_resolution"].asUInt()}; + closeTimeResolution = seconds{ledger.get()["close_time_resolution"].asUInt()}; } if (ledger.get().isMember("close_time_estimated")) { - closeTimeEstimated = - ledger.get()["close_time_estimated"].asBool(); + closeTimeEstimated = ledger.get()["close_time_estimated"].asBool(); } if (ledger.get().isMember("total_coins")) { - totalDrops = beast::lexicalCastThrow( - ledger.get()["total_coins"].asString()); + totalDrops = beast::lexicalCastThrow(ledger.get()["total_coins"].asString()); } ledger = ledger.get()["accountState"]; @@ -1821,8 +1667,7 @@ ApplicationImp::loadLedgerFromFile(std::string const& name) return nullptr; } - auto loadLedger = - std::make_shared(seq, closeTime, *config_, nodeFamily_); + auto loadLedger = std::make_shared(seq, closeTime, *config_, nodeFamily_); loadLedger->setTotalDrops(totalDrops); for (Json::UInt index = 0; index < ledger.get().size(); ++index) @@ -1859,8 +1704,7 @@ ApplicationImp::loadLedgerFromFile(std::string const& name) if (!loadLedger->addSLE(sle)) { - JLOG(m_journal.fatal()) - << "Couldn't add serialized ledger: " << uIndex; + JLOG(m_journal.fatal()) << "Couldn't add serialized ledger: " << uIndex; return nullptr; } } @@ -1868,11 +1712,9 @@ ApplicationImp::loadLedgerFromFile(std::string const& name) loadLedger->stateMap().flushDirty(hotACCOUNT_NODE); XRPL_ASSERT( - loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || - loadLedger->read(keylet::fees()), + loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()), "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees"); - loadLedger->setAccepted( - closeTime, closeTimeResolution, !closeTimeEstimated); + loadLedger->setAccepted(closeTime, closeTimeResolution, !closeTimeEstimated); return loadLedger; } @@ -1911,12 +1753,7 @@ ApplicationImp::loadOldLedger( { // Try to build the ledger from the back end auto il = std::make_shared( - *this, - hash, - 0, - InboundLedger::Reason::GENERIC, - stopwatch(), - make_DummyPeerSet(*this)); + *this, hash, 0, InboundLedger::Reason::GENERIC, stopwatch(), make_DummyPeerSet(*this)); if (il->checkLocal()) loadLedger = il->getLedger(); } @@ -1950,8 +1787,7 @@ ApplicationImp::loadOldLedger( loadLedger = loadByHash(replayLedger->header().parentHash, *this); if (!loadLedger) { - JLOG(m_journal.info()) - << "Loading parent ledger from node store"; + JLOG(m_journal.info()) << "Loading parent ledger from node store"; // Try to build the ledger from the back end auto il = std::make_shared( @@ -1983,27 +1819,24 @@ ApplicationImp::loadOldLedger( sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}}; if (loadLedger->header().closeTime < ledgerWarnTimePoint) { - JLOG(m_journal.fatal()) - << "\n\n*** WARNING ***\n" - "You are replaying a ledger from before " - << to_string(ledgerWarnTimePoint) - << " UTC.\n" - "This replay will not handle your ledger as it was " - "originally " - "handled.\nConsider running an earlier version of rippled " - "to " - "get the older rules.\n*** CONTINUING ***\n"; + JLOG(m_journal.fatal()) << "\n\n*** WARNING ***\n" + "You are replaying a ledger from before " + << to_string(ledgerWarnTimePoint) + << " UTC.\n" + "This replay will not handle your ledger as it was " + "originally " + "handled.\nConsider running an earlier version of rippled " + "to " + "get the older rules.\n*** CONTINUING ***\n"; } - JLOG(m_journal.info()) << "Loading ledger " << loadLedger->header().hash - << " seq:" << loadLedger->header().seq; + JLOG(m_journal.info()) << "Loading ledger " << loadLedger->header().hash << " seq:" << loadLedger->header().seq; if (loadLedger->header().accountHash.isZero()) { // LCOV_EXCL_START JLOG(m_journal.fatal()) << "Ledger is empty."; - UNREACHABLE( - "xrpl::ApplicationImp::loadOldLedger : ledger is empty"); + UNREACHABLE("xrpl::ApplicationImp::loadOldLedger : ledger is empty"); return false; // LCOV_EXCL_STOP } @@ -2030,21 +1863,18 @@ ApplicationImp::loadOldLedger( // LCOV_EXCL_STOP } - m_ledgerMaster->setLedgerRangePresent( - loadLedger->header().seq, loadLedger->header().seq); + m_ledgerMaster->setLedgerRangePresent(loadLedger->header().seq, loadLedger->header().seq); m_ledgerMaster->switchLCL(loadLedger); loadLedger->setValidated(); m_ledgerMaster->setFullLedger(loadLedger, true, false); - openLedger_.emplace( - loadLedger, cachedSLEs_, logs_->journal("OpenLedger")); + openLedger_.emplace(loadLedger, cachedSLEs_, logs_->journal("OpenLedger")); if (replay) { // inject transaction(s) from the replayLedger into our open ledger // and build replay structure - auto replayData = - std::make_unique(loadLedger, replayLedger); + auto replayData = std::make_unique(loadLedger, replayLedger); for (auto const& [_, tx] : replayData->orderedTxns()) { @@ -2061,34 +1891,30 @@ ApplicationImp::loadOldLedger( forceValidity(getHashRouter(), txID, Validity::SigGoodOnly); - openLedger_->modify( - [&txID, &s](OpenView& view, beast::Journal j) { - view.rawTxInsert(txID, std::move(s), nullptr); - return true; - }); + openLedger_->modify([&txID, &s](OpenView& view, beast::Journal j) { + view.rawTxInsert(txID, std::move(s), nullptr); + return true; + }); } m_ledgerMaster->takeReplay(std::move(replayData)); if (trapTxID && !trapTxID_) { - JLOG(m_journal.fatal()) - << "Ledger " << replayLedger->header().seq - << " does not contain the transaction hash " << *trapTxID; + JLOG(m_journal.fatal()) << "Ledger " << replayLedger->header().seq + << " does not contain the transaction hash " << *trapTxID; return false; } } } catch (SHAMapMissingNode const& mn) { - JLOG(m_journal.fatal()) - << "While loading specified ledger: " << mn.what(); + JLOG(m_journal.fatal()) << "While loading specified ledger: " << mn.what(); return false; } catch (boost::bad_lexical_cast&) { - JLOG(m_journal.fatal()) - << "Ledger specified '" << ledgerID << "' is not valid"; + JLOG(m_journal.fatal()) << "Ledger specified '" << ledgerID << "' is not valid"; return false; } @@ -2156,8 +1982,7 @@ ApplicationImp::setMaxDisallowedLedger() if (seq) maxDisallowedLedger_ = *seq; - JLOG(m_journal.trace()) - << "Max persisted ledger is " << maxDisallowedLedger_; + JLOG(m_journal.trace()) << "Max persisted ledger is " << maxDisallowedLedger_; } //------------------------------------------------------------------------------ @@ -2169,13 +1994,9 @@ Application::Application() : beast::PropertyStream::Source("app") //------------------------------------------------------------------------------ std::unique_ptr -make_Application( - std::unique_ptr config, - std::unique_ptr logs, - std::unique_ptr timeKeeper) +make_Application(std::unique_ptr config, std::unique_ptr logs, std::unique_ptr timeKeeper) { - return std::make_unique( - std::move(config), std::move(logs), std::move(timeKeeper)); + return std::make_unique(std::move(config), std::move(logs), std::move(timeKeeper)); } void @@ -2190,8 +2011,7 @@ fixConfigPorts(Config& config, Endpoints const& endpoints) auto const optPort = section.get("port"); if (optPort) { - std::uint16_t const port = - beast::lexicalCast(*optPort); + std::uint16_t const port = beast::lexicalCast(*optPort); if (!port) section.set("port", std::to_string(ep.port())); } diff --git a/src/xrpld/app/main/Application.h b/src/xrpld/app/main/Application.h index ffb3cd9983..07edd5f558 100644 --- a/src/xrpld/app/main/Application.h +++ b/src/xrpld/app/main/Application.h @@ -259,10 +259,7 @@ public: }; std::unique_ptr -make_Application( - std::unique_ptr config, - std::unique_ptr logs, - std::unique_ptr timeKeeper); +make_Application(std::unique_ptr config, std::unique_ptr logs, std::unique_ptr timeKeeper); } // namespace xrpl diff --git a/src/xrpld/app/main/BasicApp.cpp b/src/xrpld/app/main/BasicApp.cpp index 95cdf890cc..be0c158b85 100644 --- a/src/xrpld/app/main/BasicApp.cpp +++ b/src/xrpld/app/main/BasicApp.cpp @@ -12,8 +12,7 @@ BasicApp::BasicApp(std::size_t numberOfThreads) while (numberOfThreads--) { threads_.emplace_back([this, numberOfThreads]() { - beast::setCurrentThreadName( - "io svc #" + std::to_string(numberOfThreads)); + beast::setCurrentThreadName("io svc #" + std::to_string(numberOfThreads)); this->io_context_.run(); }); } diff --git a/src/xrpld/app/main/BasicApp.h b/src/xrpld/app/main/BasicApp.h index 75c4c1890c..0d38260e43 100644 --- a/src/xrpld/app/main/BasicApp.h +++ b/src/xrpld/app/main/BasicApp.h @@ -11,9 +11,7 @@ class BasicApp { private: - std::optional> - work_; + std::optional> work_; std::vector threads_; boost::asio::io_context io_context_; diff --git a/src/xrpld/app/main/CollectorManager.cpp b/src/xrpld/app/main/CollectorManager.cpp index 110ea564d8..7a3306b60b 100644 --- a/src/xrpld/app/main/CollectorManager.cpp +++ b/src/xrpld/app/main/CollectorManager.cpp @@ -11,19 +11,16 @@ public: beast::insight::Collector::ptr m_collector; std::unique_ptr m_groups; - CollectorManagerImp(Section const& params, beast::Journal journal) - : m_journal(journal) + CollectorManagerImp(Section const& params, beast::Journal journal) : m_journal(journal) { std::string const& server = get(params, "server"); if (server == "statsd") { - beast::IP::Endpoint const address( - beast::IP::Endpoint::from_string(get(params, "address"))); + beast::IP::Endpoint const address(beast::IP::Endpoint::from_string(get(params, "address"))); std::string const& prefix(get(params, "prefix")); - m_collector = - beast::insight::StatsDCollector::New(address, prefix, journal); + m_collector = beast::insight::StatsDCollector::New(address, prefix, journal); } else { diff --git a/src/xrpld/app/main/GRPCServer.cpp b/src/xrpld/app/main/GRPCServer.cpp index 6ed902ec1e..9b07728eb8 100644 --- a/src/xrpld/app/main/GRPCServer.cpp +++ b/src/xrpld/app/main/GRPCServer.cpp @@ -24,8 +24,7 @@ getEndpoint(std::string const& peer) peerClean = peer.substr(first + 1); } - std::optional endpoint = - beast::IP::Endpoint::from_string_checked(peerClean); + std::optional endpoint = beast::IP::Endpoint::from_string_checked(peerClean); if (endpoint) return beast::IP::to_asio_endpoint(endpoint.value()); } @@ -70,15 +69,7 @@ std::shared_ptr GRPCServerImpl::CallData::clone() { return std::make_shared>( - service_, - cq_, - app_, - bindListener_, - handler_, - forward_, - requiredCondition_, - loadType_, - secureGatewayIPs_); + service_, cq_, app_, bindListener_, handler_, forward_, requiredCondition_, loadType_, secureGatewayIPs_); } template @@ -88,8 +79,7 @@ GRPCServerImpl::CallData::process() // sanity check BOOST_ASSERT(!finished_); - std::shared_ptr> thisShared = - this->shared_from_this(); + std::shared_ptr> thisShared = this->shared_from_this(); // Need to set finished to true before processing the response, // because as soon as the response is posted to the completion @@ -100,26 +90,22 @@ GRPCServerImpl::CallData::process() // ensures that finished is always true when this CallData object // is returned as a tag in handleRpcs(), after sending the response finished_ = true; - auto coro = app_.getJobQueue().postCoro( - JobType::jtRPC, - "gRPC-Client", - [thisShared](std::shared_ptr coro) { + auto coro = + app_.getJobQueue().postCoro(JobType::jtRPC, "gRPC-Client", [thisShared](std::shared_ptr coro) { thisShared->process(coro); }); // If coro is null, then the JobQueue has already been shutdown if (!coro) { - grpc::Status status{ - grpc::StatusCode::INTERNAL, "Job Queue is already stopped"}; + grpc::Status status{grpc::StatusCode::INTERNAL, "Job Queue is already stopped"}; responder_.FinishWithError(status, this); } } template void -GRPCServerImpl::CallData::process( - std::shared_ptr coro) +GRPCServerImpl::CallData::process(std::shared_ptr coro) { try { @@ -127,9 +113,7 @@ GRPCServerImpl::CallData::process( bool isUnlimited = clientIsUnlimited(); if (!isUnlimited && usage.disconnect(app_.journal("gRPCServer"))) { - grpc::Status status{ - grpc::StatusCode::RESOURCE_EXHAUSTED, - "usage balance exceeds threshold"}; + grpc::Status status{grpc::StatusCode::RESOURCE_EXHAUSTED, "usage balance exceeds threshold"}; responder_.FinishWithError(status, this); } else @@ -151,8 +135,7 @@ GRPCServerImpl::CallData::process( toLog << user.value(); toLog << " isUnlimited = " << isUnlimited; - JLOG(app_.journal("GRPCServer::Calldata").debug()) - << toLog.str(); + JLOG(app_.journal("GRPCServer::Calldata").debug()) << toLog.str(); } RPC::GRPCContext context{ @@ -169,15 +152,12 @@ GRPCServerImpl::CallData::process( request_}; // Make sure we can currently handle the rpc - error_code_i conditionMetRes = - RPC::conditionMet(requiredCondition_, context); + error_code_i conditionMetRes = RPC::conditionMet(requiredCondition_, context); if (conditionMetRes != rpcSUCCESS) { RPC::ErrorInfo errorInfo = RPC::get_error_info(conditionMetRes); - grpc::Status status{ - grpc::StatusCode::FAILED_PRECONDITION, - errorInfo.message.c_str()}; + grpc::Status status{grpc::StatusCode::FAILED_PRECONDITION, errorInfo.message.c_str()}; responder_.FinishWithError(status, this); } else @@ -225,8 +205,7 @@ GRPCServerImpl::CallData::getUser() { if (auto descriptor = Request::GetDescriptor()->FindFieldByName("user")) { - std::string user = - Request::GetReflection()->GetString(request_, descriptor); + std::string user = Request::GetReflection()->GetString(request_, descriptor); if (!user.empty()) { return user; @@ -272,14 +251,11 @@ GRPCServerImpl::CallData::clientIsUnlimited() template void -GRPCServerImpl::CallData::setIsUnlimited( - Response& response, - bool isUnlimited) +GRPCServerImpl::CallData::setIsUnlimited(Response& response, bool isUnlimited) { if (isUnlimited) { - if (auto descriptor = - Response::GetDescriptor()->FindFieldByName("is_unlimited")) + if (auto descriptor = Response::GetDescriptor()->FindFieldByName("is_unlimited")) { Response::GetReflection()->SetBool(&response, descriptor, true); } @@ -292,13 +268,11 @@ GRPCServerImpl::CallData::getUsage() { auto endpoint = getClientEndpoint(); if (endpoint) - return app_.getResourceManager().newInboundEndpoint( - beast::IP::from_asio(endpoint.value())); + return app_.getResourceManager().newInboundEndpoint(beast::IP::from_asio(endpoint.value())); Throw("Failed to get client endpoint"); } -GRPCServerImpl::GRPCServerImpl(Application& app) - : app_(app), journal_(app_.journal("gRPC Server")) +GRPCServerImpl::GRPCServerImpl(Application& app) : app_(app), journal_(app_.journal("gRPC Server")) { // if present, get endpoint from config if (app_.config().exists(SECTION_PORT_GRPC)) @@ -314,8 +288,7 @@ GRPCServerImpl::GRPCServerImpl(Application& app) return; try { - boost::asio::ip::tcp::endpoint endpoint( - boost::asio::ip::make_address(*optIp), std::stoi(*optPort)); + boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::make_address(*optIp), std::stoi(*optPort)); std::stringstream ss; ss << endpoint; @@ -341,11 +314,9 @@ GRPCServerImpl::GRPCServerImpl(Application& app) if (addr.is_unspecified()) { - JLOG(journal_.error()) - << "Can't pass unspecified IP in " - << "secure_gateway section of port_grpc"; - Throw( - "Unspecified IP in secure_gateway section"); + JLOG(journal_.error()) << "Can't pass unspecified IP in " + << "secure_gateway section of port_grpc"; + Throw("Unspecified IP in secure_gateway section"); } secureGatewayIPs_.emplace_back(addr); @@ -353,10 +324,8 @@ GRPCServerImpl::GRPCServerImpl(Application& app) } catch (std::exception const&) { - JLOG(journal_.error()) - << "Error parsing secure gateway IPs for grpc server"; - Throw( - "Error parsing secure_gateway section"); + JLOG(journal_.error()) << "Error parsing secure gateway IPs for grpc server"; + Throw("Error parsing secure_gateway section"); } } } @@ -394,11 +363,7 @@ GRPCServerImpl::handleRpcs() auto erase = [&requests](Processor* ptr) { auto it = std::find_if( - requests.begin(), - requests.end(), - [ptr](std::shared_ptr& sPtr) { - return sPtr.get() == ptr; - }); + requests.begin(), requests.end(), [ptr](std::shared_ptr& sPtr) { return sPtr.get() == ptr; }); BOOST_ASSERT(it != requests.end()); it->swap(requests.back()); requests.pop_back(); @@ -460,21 +425,16 @@ GRPCServerImpl::setupListeners() { std::vector> requests; - auto addToRequests = [&requests](auto callData) { - requests.push_back(std::move(callData)); - }; + auto addToRequests = [&requests](auto callData) { requests.push_back(std::move(callData)); }; { - using cd = CallData< - org::xrpl::rpc::v1::GetLedgerRequest, - org::xrpl::rpc::v1::GetLedgerResponse>; + using cd = CallData; addToRequests(std::make_shared( service_, *cq_, app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestGetLedger, + &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetLedger, doLedgerGrpc, &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedger, RPC::NO_CONDITION, @@ -482,16 +442,13 @@ GRPCServerImpl::setupListeners() secureGatewayIPs_)); } { - using cd = CallData< - org::xrpl::rpc::v1::GetLedgerDataRequest, - org::xrpl::rpc::v1::GetLedgerDataResponse>; + using cd = CallData; addToRequests(std::make_shared( service_, *cq_, app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestGetLedgerData, + &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetLedgerData, doLedgerDataGrpc, &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerData, RPC::NO_CONDITION, @@ -499,16 +456,13 @@ GRPCServerImpl::setupListeners() secureGatewayIPs_)); } { - using cd = CallData< - org::xrpl::rpc::v1::GetLedgerDiffRequest, - org::xrpl::rpc::v1::GetLedgerDiffResponse>; + using cd = CallData; addToRequests(std::make_shared( service_, *cq_, app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestGetLedgerDiff, + &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetLedgerDiff, doLedgerDiffGrpc, &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerDiff, RPC::NO_CONDITION, @@ -516,16 +470,13 @@ GRPCServerImpl::setupListeners() secureGatewayIPs_)); } { - using cd = CallData< - org::xrpl::rpc::v1::GetLedgerEntryRequest, - org::xrpl::rpc::v1::GetLedgerEntryResponse>; + using cd = CallData; addToRequests(std::make_shared( service_, *cq_, app_, - &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService:: - RequestGetLedgerEntry, + &org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetLedgerEntry, doLedgerEntryGrpc, &org::xrpl::rpc::v1::XRPLedgerAPIService::Stub::GetLedgerEntry, RPC::NO_CONDITION, @@ -549,8 +500,7 @@ GRPCServerImpl::start() // Listen on the given address without any authentication mechanism. // Actually binded port will be returned into "port" variable. int port = 0; - builder.AddListeningPort( - serverAddress_, grpc::InsecureServerCredentials(), &port); + builder.AddListeningPort(serverAddress_, grpc::InsecureServerCredentials(), &port); // Register "service_" as the instance through which we'll communicate with // clients. In this case it corresponds to an *asynchronous* service. builder.RegisterService(&service_); @@ -567,10 +517,8 @@ GRPCServerImpl::start() boost::asio::ip::tcp::endpoint GRPCServerImpl::getEndpoint() const { - std::string const addr = - serverAddress_.substr(0, serverAddress_.find_last_of(':')); - return boost::asio::ip::tcp::endpoint( - boost::asio::ip::make_address(addr), serverPort_); + std::string const addr = serverAddress_.substr(0, serverAddress_.find_last_of(':')); + return boost::asio::ip::tcp::endpoint(boost::asio::ip::make_address(addr), serverPort_); } bool diff --git a/src/xrpld/app/main/GRPCServer.h b/src/xrpld/app/main/GRPCServer.h index c2697e26c6..67748c359d 100644 --- a/src/xrpld/app/main/GRPCServer.h +++ b/src/xrpld/app/main/GRPCServer.h @@ -85,17 +85,13 @@ private: // typedef for actual handler (that populates a response) // handlers are defined in rpc/GRPCHandlers.h template - using Handler = std::function( - RPC::GRPCContext&)>; + using Handler = std::function(RPC::GRPCContext&)>; // This implementation is currently limited to v1 of the API static unsigned constexpr apiVersion = 1; template - using Forward = std::function; + using Forward = std::function< + grpc::Status(org::xrpl::rpc::v1::XRPLedgerAPIService::Stub*, grpc::ClientContext*, Request, Response*)>; public: explicit GRPCServerImpl(Application& app); @@ -128,9 +124,7 @@ public: private: // Class encompassing the state and logic needed to serve a request. template - class CallData - : public Processor, - public std::enable_shared_from_this> + class CallData : public Processor, public std::enable_shared_from_this> { private: // The means of communication with the gRPC runtime for an asynchronous diff --git a/src/xrpld/app/main/LoadManager.cpp b/src/xrpld/app/main/LoadManager.cpp index 91afb67eb7..d1336b20d9 100644 --- a/src/xrpld/app/main/LoadManager.cpp +++ b/src/xrpld/app/main/LoadManager.cpp @@ -26,8 +26,7 @@ LoadManager::~LoadManager() catch (std::exception const& ex) { // Swallow the exception in a destructor. - JLOG(journal_.warn()) - << "std::exception in ~LoadManager. " << ex.what(); + JLOG(journal_.warn()) << "std::exception in ~LoadManager. " << ex.what(); } } @@ -55,8 +54,7 @@ void LoadManager::start() { JLOG(journal_.debug()) << "Starting"; - XRPL_ASSERT( - !thread_.joinable(), "xrpl::LoadManager::start : thread not joinable"); + XRPL_ASSERT(!thread_.joinable(), "xrpl::LoadManager::start : thread not joinable"); thread_ = std::thread{&LoadManager::run, this}; } @@ -104,8 +102,7 @@ LoadManager::run() // Measure the amount of time we have been stalled, in seconds. using namespace std::chrono; - auto const timeSpentStalled = - duration_cast(steady_clock::now() - lastHeartbeat); + auto const timeSpentStalled = duration_cast(steady_clock::now() - lastHeartbeat); constexpr auto reportingIntervalSeconds = 10s; constexpr auto stallFatalLogMessageTimeLimit = 90s; @@ -118,23 +115,17 @@ LoadManager::run() { if (timeSpentStalled < stallFatalLogMessageTimeLimit) { - JLOG(journal_.warn()) - << "Server stalled for " << timeSpentStalled.count() - << " seconds."; + JLOG(journal_.warn()) << "Server stalled for " << timeSpentStalled.count() << " seconds."; if (app_.getJobQueue().isOverloaded()) { - JLOG(journal_.warn()) - << "JobQueue: " << app_.getJobQueue().getJson(0); + JLOG(journal_.warn()) << "JobQueue: " << app_.getJobQueue().getJson(0); } } else { - JLOG(journal_.fatal()) - << "Server stalled for " << timeSpentStalled.count() - << " seconds."; - JLOG(journal_.fatal()) - << "JobQueue: " << app_.getJobQueue().getJson(0); + JLOG(journal_.fatal()) << "Server stalled for " << timeSpentStalled.count() << " seconds."; + JLOG(journal_.fatal()) << "JobQueue: " << app_.getJobQueue().getJson(0); } } @@ -143,11 +134,9 @@ LoadManager::run() // as a LogicError if (timeSpentStalled >= stallLogicErrorTimeLimit) { - JLOG(journal_.fatal()) - << "LogicError: Fatal server stall detected. Stalled time: " - << timeSpentStalled.count() << "s"; - JLOG(journal_.fatal()) - << "JobQueue: " << app_.getJobQueue().getJson(0); + JLOG(journal_.fatal()) << "LogicError: Fatal server stall detected. Stalled time: " + << timeSpentStalled.count() << "s"; + JLOG(journal_.fatal()) << "JobQueue: " << app_.getJobQueue().getJson(0); LogicError("Fatal server stall detected"); } } @@ -156,8 +145,7 @@ LoadManager::run() bool change = false; if (app_.getJobQueue().isOverloaded()) { - JLOG(journal_.info()) << "Raising local fee (JQ overload): " - << app_.getJobQueue().getJson(0); + JLOG(journal_.info()) << "Raising local fee (JQ overload): " << app_.getJobQueue().getJson(0); change = app_.getFeeTrack().raiseLocalFee(); } else diff --git a/src/xrpld/app/main/Main.cpp b/src/xrpld/app/main/Main.cpp index d8bc601744..031daeb5e9 100644 --- a/src/xrpld/app/main/Main.cpp +++ b/src/xrpld/app/main/Main.cpp @@ -86,11 +86,10 @@ adjustDescriptorLimit(int needed, beast::Journal j) if (needed > available) { - j.fatal() << "Insufficient number of file descriptors: " << needed - << " are needed, but only " << available << " are available."; + j.fatal() << "Insufficient number of file descriptors: " << needed << " are needed, but only " << available + << " are available."; - std::cerr << "Insufficient number of file descriptors: " << needed - << " are needed, but only " << available + std::cerr << "Insufficient number of file descriptors: " << needed << " are needed, but only " << available << " are available.\n"; return false; @@ -103,69 +102,68 @@ adjustDescriptorLimit(int needed, beast::Journal j) void printHelp(po::options_description const& desc) { - std::cerr - << systemName() << "d [options] \n" - << desc << std::endl - << "Commands: \n" - " account_currencies []\n" - " account_info | []\n" - " account_lines |\"\" []\n" - " account_channels |\"\" []\n" - " account_objects []\n" - " account_offers | []\n" - " account_tx accountID [ledger_index_min [ledger_index_max " - "[limit " - "]]] [binary]\n" - " book_changes []\n" - " book_offers [ " - "[ [ []]]]]\n" - " can_delete [||now|always|never]\n" - " channel_authorize \n" - " channel_verify \n" - " connect []\n" - " consensus_info\n" - " deposit_authorized " - "[ [, ...]]\n" - " feature [ [accept|reject]]\n" - " fetch_info [clear]\n" - " gateway_balances [] [ [ " - " ]]\n" - " get_counts\n" - " json \n" - " ledger [|current|closed|validated] [full]\n" - " ledger_accept\n" - " ledger_cleaner\n" - " ledger_closed\n" - " ledger_current\n" - " ledger_request \n" - " log_level [[] ]\n" - " logrotate\n" - " manifest \n" - " peers\n" - " ping\n" - " random\n" - " peer_reservations_add []\n" - " peer_reservations_del \n" - " peer_reservations_list\n" - " ripple ...\n" - " ripple_path_find []\n" - " server_definitions []\n" - " server_info [counters]\n" - " server_state [counters]\n" - " sign [offline]\n" - " sign_for " - "[offline] []\n" - " stop\n" - " simulate [|] []\n" - " submit |[ ]\n" - " submit_multisigned \n" - " tx \n" - " validation_create [||]\n" - " validator_info\n" - " validators\n" - " validator_list_sites\n" - " version\n" - " wallet_propose []\n"; + std::cerr << systemName() << "d [options] \n" + << desc << std::endl + << "Commands: \n" + " account_currencies []\n" + " account_info | []\n" + " account_lines |\"\" []\n" + " account_channels |\"\" []\n" + " account_objects []\n" + " account_offers | []\n" + " account_tx accountID [ledger_index_min [ledger_index_max " + "[limit " + "]]] [binary]\n" + " book_changes []\n" + " book_offers [ " + "[ [ []]]]]\n" + " can_delete [||now|always|never]\n" + " channel_authorize \n" + " channel_verify \n" + " connect []\n" + " consensus_info\n" + " deposit_authorized " + "[ [, ...]]\n" + " feature [ [accept|reject]]\n" + " fetch_info [clear]\n" + " gateway_balances [] [ [ " + " ]]\n" + " get_counts\n" + " json \n" + " ledger [|current|closed|validated] [full]\n" + " ledger_accept\n" + " ledger_cleaner\n" + " ledger_closed\n" + " ledger_current\n" + " ledger_request \n" + " log_level [[] ]\n" + " logrotate\n" + " manifest \n" + " peers\n" + " ping\n" + " random\n" + " peer_reservations_add []\n" + " peer_reservations_del \n" + " peer_reservations_list\n" + " ripple ...\n" + " ripple_path_find []\n" + " server_definitions []\n" + " server_info [counters]\n" + " server_state [counters]\n" + " sign [offline]\n" + " sign_for " + "[offline] []\n" + " stop\n" + " simulate [|] []\n" + " submit |[ ]\n" + " submit_multisigned \n" + " tx \n" + " validation_create [||]\n" + " validator_info\n" + " validators\n" + " validator_list_sites\n" + " version\n" + " wallet_propose []\n"; } //------------------------------------------------------------------------------ @@ -188,8 +186,7 @@ public: std::for_each(v.begin(), v.end(), [this](std::string s) { boost::trim(s); if (selectors_.empty() || !s.empty()) - selectors_.emplace_back( - beast::unit_test::selector::automatch, s); + selectors_.emplace_back(beast::unit_test::selector::automatch, s); }); } @@ -227,9 +224,7 @@ anyMissing(Runner& runner, multi_selector const& pred) { auto const missing = pred.size() - runner.suites(); runner.add_failures(missing); - std::cout << "Failed: " << missing - << " filters did not match any existing test suites" - << std::endl; + std::cout << "Failed: " << missing << " filters did not match any existing test suites" << std::endl; return true; } return false; @@ -259,8 +254,7 @@ runUnitTests( multi_runner_child child_runner{num_jobs, quiet, log}; child_runner.arg(argument); multi_selector pred(pattern); - auto const any_failed = - child_runner.run_multi(pred) || anyMissing(child_runner, pred); + auto const any_failed = child_runner.run_multi(pred) || anyMissing(child_runner, pred); if (any_failed) return EXIT_FAILURE; @@ -281,9 +275,7 @@ runUnitTests( } for (std::size_t i = 0; i < num_jobs; ++i) - children.emplace_back( - boost::process::v1::exe = exe_name, - boost::process::v1::args = args); + children.emplace_back(boost::process::v1::exe = exe_name, boost::process::v1::args = args); int bad_child_exits = 0; int terminated_child_exits = 0; @@ -348,42 +340,27 @@ run(int argc, char** argv) // Set up option parsing. // po::options_description gen("General Options"); - gen.add_options()( - "conf", po::value(), "Specify the configuration file.")( - "debug", "Enable normally suppressed debug logging")( - "help,h", "Display this message.")( + gen.add_options()("conf", po::value(), "Specify the configuration file.")( + "debug", "Enable normally suppressed debug logging")("help,h", "Display this message.")( "newnodeid", "Generate a new node identity for this server.")( - "nodeid", - po::value(), - "Specify the node identity for this server.")( - "quorum", - po::value(), - "Override the minimum validation quorum.")( - "silent", "No output to the console after startup.")( - "standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.") + "nodeid", po::value(), "Specify the node identity for this server.")( + "quorum", po::value(), "Override the minimum validation quorum.")( + "silent", "No output to the console after startup.")("standalone,a", "Run with no peers.")( + "verbose,v", "Verbose logging.") ("force_ledger_present_range", po::value(), "Specify the range of present ledgers for testing purposes. Min and " - "max values are comma separated.")( - "version", "Display the build version."); + "max values are comma separated.")("version", "Display the build version."); po::options_description data("Ledger/Data Options"); data.add_options()("import", importText.c_str())( - "ledger", - po::value(), - "Load the specified ledger and start from the value given.")( - "ledgerfile", - po::value(), - "Load the specified ledger file.")( - "load", "Load the current ledger from the local DB.")( - "net", "Get the initial ledger from the network.")( + "ledger", po::value(), "Load the specified ledger and start from the value given.")( + "ledgerfile", po::value(), "Load the specified ledger file.")( + "load", "Load the current ledger from the local DB.")("net", "Get the initial ledger from the network.")( "replay", "Replay a ledger close.")( - "trap_tx_hash", - po::value(), - "Trap a specific transaction during replay.")( - "start", "Start from a fresh Ledger.")( - "vacuum", "VACUUM the transaction db.")( + "trap_tx_hash", po::value(), "Trap a specific transaction during replay.")( + "start", "Start from a fresh Ledger.")("vacuum", "VACUUM the transaction db.")( "valid", "Consider the initial ledger a valid network ledger."); po::options_description rpc("RPC Client Options"); @@ -418,16 +395,12 @@ run(int argc, char** argv) "is made available to each suite that runs. Interpretation of the " "argument is handled individually by any suite that accesses it -- " "as such, it typically only make sense to provide this when running " - "a single suite.")( - "unittest-ipv6", - "Use IPv6 localhost when running unittests (default is IPv4).")( + "a single suite.")("unittest-ipv6", "Use IPv6 localhost when running unittests (default is IPv4).")( "unittest-log", "Force unit test log message output. Only useful in combination with " "--quiet, in which case log messages will print but suite/case names " "will not.")( - "unittest-jobs", - po::value(), - "Number of unittest jobs to run in parallel (child processes)."); + "unittest-jobs", po::value(), "Number of unittest jobs to run in parallel (child processes)."); #endif // ENABLE_TESTS // These are hidden options, not intended to be shown in the usage/help @@ -441,11 +414,9 @@ run(int argc, char** argv) "purpose, " "so this option is not needed for users") #ifdef ENABLE_TESTS - ("unittest-child", - "For internal use only when spawning child unit test processes.") + ("unittest-child", "For internal use only when spawning child unit test processes.") #else - ("unittest", "Disabled in this build.")( - "unittest-child", "Disabled in this build.") + ("unittest", "Disabled in this build.")("unittest-child", "Disabled in this build.") #endif // ENABLE_TESTS ("fg", "Deprecated: server always in foreground mode."); @@ -497,8 +468,7 @@ run(int argc, char** argv) if (vm.count("version")) { - std::cout << "rippled version " << BuildInfo::getVersionString() - << std::endl; + std::cout << "rippled version " << BuildInfo::getVersionString() << std::endl; #ifdef GIT_COMMIT_HASH std::cout << "Git commit hash: " << GIT_COMMIT_HASH << std::endl; #endif @@ -560,15 +530,10 @@ run(int argc, char** argv) auto config = std::make_unique(); - auto configFile = - vm.count("conf") ? vm["conf"].as() : std::string(); + auto configFile = vm.count("conf") ? vm["conf"].as() : std::string(); // config file, quiet flag. - config->setup( - configFile, - bool(vm.count("quiet")), - bool(vm.count("silent")), - bool(vm.count("standalone"))); + config->setup(configFile, bool(vm.count("quiet")), bool(vm.count("silent")), bool(vm.count("standalone"))); if (vm.count("vacuum")) { @@ -586,8 +551,7 @@ run(int argc, char** argv) } catch (std::exception const& e) { - std::cerr << "exception " << e.what() << " in function " << __func__ - << std::endl; + std::cerr << "exception " << e.what() << " in function " << __func__ << std::endl; return -1; } @@ -601,9 +565,7 @@ run(int argc, char** argv) auto const r = [&vm]() -> std::vector { std::vector strVec; boost::split( - strVec, - vm["force_ledger_present_range"].as(), - boost::algorithm::is_any_of(",")); + strVec, vm["force_ledger_present_range"].as(), boost::algorithm::is_any_of(",")); std::vector result; for (auto& s : strVec) { @@ -618,15 +580,13 @@ run(int argc, char** argv) { if (r[0] > r[1]) { - throw std::runtime_error( - "Invalid force_ledger_present_range parameter"); + throw std::runtime_error("Invalid force_ledger_present_range parameter"); } config->FORCED_LEDGER_RANGE_PRESENT.emplace(r[0], r[1]); } else { - throw std::runtime_error( - "Invalid force_ledger_present_range parameter"); + throw std::runtime_error("Invalid force_ledger_present_range parameter"); } } catch (std::exception const& e) @@ -685,18 +645,15 @@ run(int argc, char** argv) if (vm.count("trap_tx_hash") && vm.count("replay") == 0) { - std::cerr << "Cannot use trap option without replay option" - << std::endl; + std::cerr << "Cannot use trap option without replay option" << std::endl; return -1; } if (vm.count("net") && !config->FAST_LOAD) { - if ((config->START_UP == Config::LOAD) || - (config->START_UP == Config::REPLAY)) + if ((config->START_UP == Config::LOAD) || (config->START_UP == Config::REPLAY)) { - std::cerr << "Net and load/replay options are incompatible" - << std::endl; + std::cerr << "Net and load/replay options are incompatible" << std::endl; return -1; } @@ -712,12 +669,10 @@ run(int argc, char** argv) // happen after the config file is loaded. if (vm.count("rpc_ip")) { - auto endpoint = beast::IP::Endpoint::from_string_checked( - vm["rpc_ip"].as()); + auto endpoint = beast::IP::Endpoint::from_string_checked(vm["rpc_ip"].as()); if (!endpoint) { - std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as() - << "\n"; + std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as() << "\n"; return -1; } @@ -729,8 +684,7 @@ run(int argc, char** argv) std::cerr << "WARNING: using deprecated rpc_port param.\n"; try { - endpoint = - endpoint->at_port(vm["rpc_port"].as()); + endpoint = endpoint->at_port(vm["rpc_port"].as()); if (endpoint->port() == 0) throw std::domain_error("0"); } @@ -759,8 +713,7 @@ run(int argc, char** argv) } catch (std::exception const& e) { - std::cerr << "Invalid value specified for --quorum (" << e.what() - << ")\n"; + std::cerr << "Invalid value specified for --quorum (" << e.what() << ")\n"; return -1; } } @@ -783,13 +736,12 @@ run(int argc, char** argv) // say 1.7 or higher if (config->had_trailing_comments()) { - JLOG(logs->journal("Application").warn()) - << "Trailing comments were seen in your config file. " - << "The treatment of inline/trailing comments has changed " - "recently. " - << "Any `#` characters NOT intended to delimit comments should " - "be " - << "preceded by a \\"; + JLOG(logs->journal("Application").warn()) << "Trailing comments were seen in your config file. " + << "The treatment of inline/trailing comments has changed " + "recently. " + << "Any `#` characters NOT intended to delimit comments should " + "be " + << "preceded by a \\"; } // We want at least 1024 file descriptors. We'll @@ -800,16 +752,14 @@ run(int argc, char** argv) if (vm.count("debug")) setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace)); - auto app = make_Application( - std::move(config), std::move(logs), std::make_unique()); + auto app = make_Application(std::move(config), std::move(logs), std::make_unique()); if (!app->setup(vm)) return -1; // With our configuration parsed, ensure we have // enough file descriptors available: - if (!adjustDescriptorLimit( - app->fdRequired(), app->logs().journal("Application"))) + if (!adjustDescriptorLimit(app->fdRequired(), app->logs().journal("Application"))) return -1; // Start the server @@ -823,8 +773,7 @@ run(int argc, char** argv) // We have an RPC command to process: beast::setCurrentThreadName("rippled: rpc"); - return RPCCall::fromCommandLine( - *config, vm["parameters"].as>(), *logs); + return RPCCall::fromCommandLine(*config, vm["parameters"].as>(), *logs); // LCOV_EXCL_STOP } diff --git a/src/xrpld/app/main/NodeIdentity.cpp b/src/xrpld/app/main/NodeIdentity.cpp index 73ef3f0152..b585b80b5b 100644 --- a/src/xrpld/app/main/NodeIdentity.cpp +++ b/src/xrpld/app/main/NodeIdentity.cpp @@ -7,9 +7,7 @@ namespace xrpl { std::pair -getNodeIdentity( - Application& app, - boost::program_options::variables_map const& cmdline) +getNodeIdentity(Application& app, boost::program_options::variables_map const& cmdline) { std::optional seed; @@ -22,12 +20,10 @@ getNodeIdentity( } else if (app.config().exists(SECTION_NODE_SEED)) { - seed = parseBase58( - app.config().section(SECTION_NODE_SEED).lines().front()); + seed = parseBase58(app.config().section(SECTION_NODE_SEED).lines().front()); if (!seed) - Throw("Invalid [" SECTION_NODE_SEED - "] in configuration file"); + Throw("Invalid [" SECTION_NODE_SEED "] in configuration file"); } if (seed) diff --git a/src/xrpld/app/main/NodeIdentity.h b/src/xrpld/app/main/NodeIdentity.h index 7fdb748033..ca47ae72ae 100644 --- a/src/xrpld/app/main/NodeIdentity.h +++ b/src/xrpld/app/main/NodeIdentity.h @@ -16,9 +16,7 @@ namespace xrpl { @param cmdline The command line parameters passed into the application. */ std::pair -getNodeIdentity( - Application& app, - boost::program_options::variables_map const& cmdline); +getNodeIdentity(Application& app, boost::program_options::variables_map const& cmdline); } // namespace xrpl diff --git a/src/xrpld/app/main/NodeStoreScheduler.cpp b/src/xrpld/app/main/NodeStoreScheduler.cpp index 0e02a092f8..1b3ff4ab03 100644 --- a/src/xrpld/app/main/NodeStoreScheduler.cpp +++ b/src/xrpld/app/main/NodeStoreScheduler.cpp @@ -12,8 +12,7 @@ NodeStoreScheduler::scheduleTask(NodeStore::Task& task) if (jobQueue_.isStopped()) return; - if (!jobQueue_.addJob( - jtWRITE, "NObjStore", [&task]() { task.performScheduledTask(); })) + if (!jobQueue_.addJob(jtWRITE, "NObjStore", [&task]() { task.performScheduledTask(); })) { // Job not added, presumably because we're shutting down. // Recover by executing the task synchronously. @@ -28,10 +27,7 @@ NodeStoreScheduler::onFetch(NodeStore::FetchReport const& report) return; jobQueue_.addLoadEvents( - report.fetchType == NodeStore::FetchType::async ? jtNS_ASYNC_READ - : jtNS_SYNC_READ, - 1, - report.elapsed); + report.fetchType == NodeStore::FetchType::async ? jtNS_ASYNC_READ : jtNS_SYNC_READ, 1, report.elapsed); } void diff --git a/src/xrpld/app/misc/AMMHelpers.h b/src/xrpld/app/misc/AMMHelpers.h index 3a33f49ee4..e54eea2f01 100644 --- a/src/xrpld/app/misc/AMMHelpers.h +++ b/src/xrpld/app/misc/AMMHelpers.h @@ -37,10 +37,7 @@ enum class IsDeposit : bool { No = false, Yes = true }; * @return LP Tokens as IOU */ STAmount -ammLPTokens( - STAmount const& asset1, - STAmount const& asset2, - Issue const& lptIssue); +ammLPTokens(STAmount const& asset1, STAmount const& asset2, Issue const& lptIssue); /** Calculate LP Tokens given asset's deposit amount. * @param asset1Balance current AMM asset1 balance @@ -64,11 +61,7 @@ lpTokensOut( * @return */ STAmount -ammAssetIn( - STAmount const& asset1Balance, - STAmount const& lptAMMBalance, - STAmount const& lpTokens, - std::uint16_t tfee); +ammAssetIn(STAmount const& asset1Balance, STAmount const& lptAMMBalance, STAmount const& lpTokens, std::uint16_t tfee); /** Calculate LP Tokens given asset's withdraw amount. Return 0 * if can't calculate. @@ -93,11 +86,7 @@ lpTokensIn( * @return calculated asset amount */ STAmount -ammAssetOut( - STAmount const& assetBalance, - STAmount const& lptAMMBalance, - STAmount const& lpTokens, - std::uint16_t tfee); +ammAssetOut(STAmount const& assetBalance, STAmount const& lptAMMBalance, STAmount const& lpTokens, std::uint16_t tfee); /** Check if the relative distance between the qualities * is within the requested distance. @@ -107,10 +96,7 @@ ammAssetOut( * @return true if within dist, false otherwise */ inline bool -withinRelativeDistance( - Quality const& calcQuality, - Quality const& reqQuality, - Number const& dist) +withinRelativeDistance(Quality const& calcQuality, Quality const& reqQuality, Number const& dist) { if (calcQuality == reqQuality) return true; @@ -174,10 +160,7 @@ solveQuadraticEqSmallest(Number const& a, Number const& b, Number const& c); */ template std::optional> -getAMMOfferStartWithTakerGets( - TAmounts const& pool, - Quality const& targetQuality, - std::uint16_t const& tfee) +getAMMOfferStartWithTakerGets(TAmounts const& pool, Quality const& targetQuality, std::uint16_t const& tfee) { if (targetQuality.rate() == beast::zero) return std::nullopt; @@ -186,15 +169,13 @@ getAMMOfferStartWithTakerGets( auto const f = feeMult(tfee); auto const a = 1; auto const b = pool.in * (1 - 1 / f) / targetQuality.rate() - 2 * pool.out; - auto const c = - pool.out * pool.out - (pool.in * pool.out) / targetQuality.rate(); + auto const c = pool.out * pool.out - (pool.in * pool.out) / targetQuality.rate(); auto nTakerGets = solveQuadraticEqSmallest(a, b, c); if (!nTakerGets || *nTakerGets <= 0) return std::nullopt; // LCOV_EXCL_LINE - auto const nTakerGetsConstraint = - pool.out - pool.in / (targetQuality.rate() * f); + auto const nTakerGetsConstraint = pool.out - pool.in / (targetQuality.rate() * f); if (nTakerGetsConstraint <= 0) return std::nullopt; @@ -205,16 +186,13 @@ getAMMOfferStartWithTakerGets( auto getAmounts = [&pool, &tfee](Number const& nTakerGetsProposed) { // Round downward to minimize the offer and to maximize the quality. // This has the most impact when takerGets is XRP. - auto const takerGets = toAmount( - getIssue(pool.out), nTakerGetsProposed, Number::downward); - return TAmounts{ - swapAssetOut(pool, takerGets, tfee), takerGets}; + auto const takerGets = toAmount(getIssue(pool.out), nTakerGetsProposed, Number::downward); + return TAmounts{swapAssetOut(pool, takerGets, tfee), takerGets}; }; // Try to reduce the offer size to improve the quality. // The quality might still not match the targetQuality for a tiny offer. - if (auto const amounts = getAmounts(*nTakerGets); - Quality{amounts} < targetQuality) + if (auto const amounts = getAmounts(*nTakerGets); Quality{amounts} < targetQuality) return getAmounts(detail::reduceOffer(amounts.out)); else return amounts; @@ -245,10 +223,7 @@ getAMMOfferStartWithTakerGets( */ template std::optional> -getAMMOfferStartWithTakerPays( - TAmounts const& pool, - Quality const& targetQuality, - std::uint16_t tfee) +getAMMOfferStartWithTakerPays(TAmounts const& pool, Quality const& targetQuality, std::uint16_t tfee) { if (targetQuality.rate() == beast::zero) return std::nullopt; @@ -257,15 +232,13 @@ getAMMOfferStartWithTakerPays( auto const f = feeMult(tfee); auto const& a = f; auto const b = pool.in * (1 + f); - auto const c = - pool.in * pool.in - pool.in * pool.out * targetQuality.rate(); + auto const c = pool.in * pool.in - pool.in * pool.out * targetQuality.rate(); auto nTakerPays = solveQuadraticEqSmallest(a, b, c); if (!nTakerPays || nTakerPays <= 0) return std::nullopt; // LCOV_EXCL_LINE - auto const nTakerPaysConstraint = - pool.out * targetQuality.rate() - pool.in / f; + auto const nTakerPaysConstraint = pool.out * targetQuality.rate() - pool.in / f; if (nTakerPaysConstraint <= 0) return std::nullopt; @@ -276,16 +249,13 @@ getAMMOfferStartWithTakerPays( auto getAmounts = [&pool, &tfee](Number const& nTakerPaysProposed) { // Round downward to minimize the offer and to maximize the quality. // This has the most impact when takerPays is XRP. - auto const takerPays = toAmount( - getIssue(pool.in), nTakerPaysProposed, Number::downward); - return TAmounts{ - takerPays, swapAssetIn(pool, takerPays, tfee)}; + auto const takerPays = toAmount(getIssue(pool.in), nTakerPaysProposed, Number::downward); + return TAmounts{takerPays, swapAssetIn(pool, takerPays, tfee)}; }; // Try to reduce the offer size to improve the quality. // The quality might still not match the targetQuality for a tiny offer. - if (auto const amounts = getAmounts(*nTakerPays); - Quality{amounts} < targetQuality) + if (auto const amounts = getAmounts(*nTakerPays); Quality{amounts} < targetQuality) return getAmounts(detail::reduceOffer(amounts.in)); else return amounts; @@ -327,61 +297,48 @@ changeSpotPriceQuality( auto const f = feeMult(tfee); // 1 - fee auto const& a = f; auto const b = pool.in * (1 + f); - Number const c = - pool.in * pool.in - pool.in * pool.out * quality.rate(); + Number const c = pool.in * pool.in - pool.in * pool.out * quality.rate(); if (auto const res = b * b - 4 * a * c; res < 0) return std::nullopt; // LCOV_EXCL_LINE - else if (auto const nTakerPaysPropose = (-b + root2(res)) / (2 * a); - nTakerPaysPropose > 0) + else if (auto const nTakerPaysPropose = (-b + root2(res)) / (2 * a); nTakerPaysPropose > 0) { auto const nTakerPays = [&]() { // The fee might make the AMM offer quality less than CLOB // quality. Therefore, AMM offer has to satisfy this constraint: // o / i >= q. Substituting o with swapAssetIn() gives: i <= O / // q - I / (1 - fee). - auto const nTakerPaysConstraint = - pool.out * quality.rate() - pool.in / f; + auto const nTakerPaysConstraint = pool.out * quality.rate() - pool.in / f; if (nTakerPaysPropose > nTakerPaysConstraint) return nTakerPaysConstraint; return nTakerPaysPropose; }(); if (nTakerPays <= 0) { - JLOG(j.trace()) - << "changeSpotPriceQuality calc failed: " - << to_string(pool.in) << " " << to_string(pool.out) << " " - << quality << " " << tfee; + JLOG(j.trace()) << "changeSpotPriceQuality calc failed: " << to_string(pool.in) << " " + << to_string(pool.out) << " " << quality << " " << tfee; return std::nullopt; } - auto const takerPays = - toAmount(getIssue(pool.in), nTakerPays, Number::upward); + auto const takerPays = toAmount(getIssue(pool.in), nTakerPays, Number::upward); // should not fail - if (auto const amounts = - TAmounts{ - takerPays, swapAssetIn(pool, takerPays, tfee)}; - Quality{amounts} < quality && - !withinRelativeDistance( - Quality{amounts}, quality, Number(1, -7))) + if (auto const amounts = TAmounts{takerPays, swapAssetIn(pool, takerPays, tfee)}; + Quality{amounts} < quality && !withinRelativeDistance(Quality{amounts}, quality, Number(1, -7))) { - JLOG(j.error()) - << "changeSpotPriceQuality failed: " << to_string(pool.in) - << " " << to_string(pool.out) << " " - << " " << quality << " " << tfee << " " - << to_string(amounts.in) << " " << to_string(amounts.out); + JLOG(j.error()) << "changeSpotPriceQuality failed: " << to_string(pool.in) << " " << to_string(pool.out) + << " " + << " " << quality << " " << tfee << " " << to_string(amounts.in) << " " + << to_string(amounts.out); Throw("changeSpotPriceQuality failed"); } else { - JLOG(j.trace()) - << "changeSpotPriceQuality succeeded: " - << to_string(pool.in) << " " << to_string(pool.out) << " " - << " " << quality << " " << tfee << " " - << to_string(amounts.in) << " " << to_string(amounts.out); + JLOG(j.trace()) << "changeSpotPriceQuality succeeded: " << to_string(pool.in) << " " + << to_string(pool.out) << " " + << " " << quality << " " << tfee << " " << to_string(amounts.in) << " " + << to_string(amounts.out); return amounts; } } - JLOG(j.trace()) << "changeSpotPriceQuality calc failed: " - << to_string(pool.in) << " " << to_string(pool.out) + JLOG(j.trace()) << "changeSpotPriceQuality calc failed: " << to_string(pool.in) << " " << to_string(pool.out) << " " << quality << " " << tfee; return std::nullopt; } @@ -395,26 +352,20 @@ changeSpotPriceQuality( }(); if (!amounts) { - JLOG(j.trace()) << "changeSpotPrice calc failed: " << to_string(pool.in) - << " " << to_string(pool.out) << " " << quality << " " - << tfee << std::endl; + JLOG(j.trace()) << "changeSpotPrice calc failed: " << to_string(pool.in) << " " << to_string(pool.out) << " " + << quality << " " << tfee << std::endl; return std::nullopt; } if (Quality{*amounts} < quality) { - JLOG(j.error()) << "changeSpotPriceQuality failed: " - << to_string(pool.in) << " " << to_string(pool.out) - << " " << quality << " " << tfee << " " - << to_string(amounts->in) << " " - << to_string(amounts->out); + JLOG(j.error()) << "changeSpotPriceQuality failed: " << to_string(pool.in) << " " << to_string(pool.out) << " " + << quality << " " << tfee << " " << to_string(amounts->in) << " " << to_string(amounts->out); return std::nullopt; } - JLOG(j.trace()) << "changeSpotPriceQuality succeeded: " - << to_string(pool.in) << " " << to_string(pool.out) << " " - << " " << quality << " " << tfee << " " - << to_string(amounts->in) << " " << to_string(amounts->out); + JLOG(j.trace()) << "changeSpotPriceQuality succeeded: " << to_string(pool.in) << " " << to_string(pool.out) << " " + << " " << quality << " " << tfee << " " << to_string(amounts->in) << " " << to_string(amounts->out); return amounts; } @@ -442,13 +393,9 @@ changeSpotPriceQuality( */ template TOut -swapAssetIn( - TAmounts const& pool, - TIn const& assetIn, - std::uint16_t tfee) +swapAssetIn(TAmounts const& pool, TIn const& assetIn, std::uint16_t tfee) { - if (auto const& rules = getCurrentTransactionRules(); - rules && rules->enabled(fixAMMv1_1)) + if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixAMMv1_1)) { // set rounding to always favor the amm. Clip to zero. // calculate: @@ -498,8 +445,7 @@ swapAssetIn( { return toAmount( getIssue(pool.out), - pool.out - - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)), + pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)), Number::downward); } } @@ -515,13 +461,9 @@ swapAssetIn( */ template TIn -swapAssetOut( - TAmounts const& pool, - TOut const& assetOut, - std::uint16_t tfee) +swapAssetOut(TAmounts const& pool, TOut const& assetOut, std::uint16_t tfee) { - if (auto const& rules = getCurrentTransactionRules(); - rules && rules->enabled(fixAMMv1_1)) + if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixAMMv1_1)) { // set rounding to always favor the amm. Clip to zero. // calculate: @@ -571,8 +513,7 @@ swapAssetOut( { return toAmount( getIssue(pool.in), - ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / - feeMult(tfee), + ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee), Number::upward); } } @@ -594,10 +535,7 @@ square(Number const& n); * @param isDeposit Yes if deposit, No if withdraw */ STAmount -adjustLPTokens( - STAmount const& lptAMMBalance, - STAmount const& lpTokens, - IsDeposit isDeposit); +adjustLPTokens(STAmount const& lptAMMBalance, STAmount const& lpTokens, IsDeposit isDeposit); /** Calls adjustLPTokens() and adjusts deposit or withdraw amounts if * the adjusted LP tokens are less than the provided LP tokens. @@ -656,11 +594,7 @@ getAssetRounding(IsDeposit isDeposit) */ template STAmount -getRoundedAsset( - Rules const& rules, - STAmount const& balance, - A const& frac, - IsDeposit isDeposit) +getRoundedAsset(Rules const& rules, STAmount const& balance, A const& frac, IsDeposit isDeposit) { if (!rules.enabled(fixAMMv1_3)) { @@ -698,11 +632,7 @@ getRoundedAsset( * digits) when adding the lptokens to the balance. */ STAmount -getRoundedLPTokens( - Rules const& rules, - STAmount const& balance, - Number const& frac, - IsDeposit isDeposit); +getRoundedLPTokens(Rules const& rules, STAmount const& balance, Number const& frac, IsDeposit isDeposit); /** Round AMM single deposit/withdrawal LPToken amount. * The lambda's are used to delay evaluation until the function is executed @@ -755,11 +685,7 @@ adjustAssetOutByTokens( * is used to adjust equal deposit/withdraw amount. */ Number -adjustFracByTokens( - Rules const& rules, - STAmount const& lptAMMBalance, - STAmount const& tokens, - Number const& frac); +adjustFracByTokens(Rules const& rules, STAmount const& lptAMMBalance, STAmount const& tokens, Number const& frac); } // namespace xrpl diff --git a/src/xrpld/app/misc/AMMUtils.h b/src/xrpld/app/misc/AMMUtils.h index 266f50bb87..5ed03d51f7 100644 --- a/src/xrpld/app/misc/AMMUtils.h +++ b/src/xrpld/app/misc/AMMUtils.h @@ -51,39 +51,25 @@ ammLPHolds( beast::Journal const j); STAmount -ammLPHolds( - ReadView const& view, - SLE const& ammSle, - AccountID const& lpAccount, - beast::Journal const j); +ammLPHolds(ReadView const& view, SLE const& ammSle, AccountID const& lpAccount, beast::Journal const j); /** Get AMM trading fee for the given account. The fee is discounted * if the account is the auction slot owner or one of the slot's authorized * accounts. */ std::uint16_t -getTradingFee( - ReadView const& view, - SLE const& ammSle, - AccountID const& account); +getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account); /** Returns total amount held by AMM for the given token. */ STAmount -ammAccountHolds( - ReadView const& view, - AccountID const& ammAccountID, - Issue const& issue); +ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Issue const& issue); /** Delete trustlines to AMM. If all trustlines are deleted then * AMM object and account are deleted. Otherwise tecIMPCOMPLETE is returned. */ TER -deleteAMMAccount( - Sandbox& view, - Issue const& asset, - Issue const& asset2, - beast::Journal j); +deleteAMMAccount(Sandbox& view, Issue const& asset, Issue const& asset2, beast::Journal j); /** Initialize Auction and Voting slots and set the trading/discounted fee. */ @@ -100,10 +86,7 @@ initializeFeeAuctionVote( * for instance Liquidity Provider has more than one LPToken trustline. */ Expected -isOnlyLiquidityProvider( - ReadView const& view, - Issue const& ammIssue, - AccountID const& lpAccount); +isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID const& lpAccount); /** Due to rounding, the LPTokenBalance of the last LP might * not match the LP's trustline balance. If it's within the tolerance, diff --git a/src/xrpld/app/misc/AmendmentTable.h b/src/xrpld/app/misc/AmendmentTable.h index 0265e0127f..d6cb3d7bce 100644 --- a/src/xrpld/app/misc/AmendmentTable.h +++ b/src/xrpld/app/misc/AmendmentTable.h @@ -22,8 +22,7 @@ public: struct FeatureInfo { FeatureInfo() = delete; - FeatureInfo(std::string const& n, uint256 const& f, VoteBehavior v) - : name(n), feature(f), vote(v) + FeatureInfo(std::string const& n, uint256 const& f, VoteBehavior v) : name(n), feature(f), vote(v) { } @@ -71,8 +70,7 @@ public: /** Called when a new fully-validated ledger is accepted. */ void - doValidatedLedger( - std::shared_ptr const& lastValidatedLedger) + doValidatedLedger(std::shared_ptr const& lastValidatedLedger) { if (needValidatedLedger(lastValidatedLedger->seq())) doValidatedLedger( @@ -143,27 +141,23 @@ public: // Inject appropriate pseudo-transactions for (auto const& it : actions) { - STTx amendTx( - ttAMENDMENT, - [&it, seq = lastClosedLedger->seq() + 1](auto& obj) { - obj.setAccountID(sfAccount, AccountID()); - obj.setFieldH256(sfAmendment, it.first); - obj.setFieldU32(sfLedgerSequence, seq); + STTx amendTx(ttAMENDMENT, [&it, seq = lastClosedLedger->seq() + 1](auto& obj) { + obj.setAccountID(sfAccount, AccountID()); + obj.setFieldH256(sfAmendment, it.first); + obj.setFieldU32(sfLedgerSequence, seq); - if (it.second != 0) - obj.setFieldU32(sfFlags, it.second); - }); + if (it.second != 0) + obj.setFieldU32(sfFlags, it.second); + }); Serializer s; amendTx.add(s); - JLOG(j.debug()) << "Amendments: Adding pseudo-transaction: " - << amendTx.getTransactionID() << ": " + JLOG(j.debug()) << "Amendments: Adding pseudo-transaction: " << amendTx.getTransactionID() << ": " << strHex(s.slice()) << ": " << amendTx; initialPosition->addGiveItem( - SHAMapNodeType::tnTRANSACTION_NM, - make_shamapitem(amendTx.getTransactionID(), s.slice())); + SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(amendTx.getTransactionID(), s.slice())); } } }; diff --git a/src/xrpld/app/misc/CanonicalTXSet.cpp b/src/xrpld/app/misc/CanonicalTXSet.cpp index ac1b86e62f..6e6102afe7 100644 --- a/src/xrpld/app/misc/CanonicalTXSet.cpp +++ b/src/xrpld/app/misc/CanonicalTXSet.cpp @@ -33,10 +33,7 @@ void CanonicalTXSet::insert(std::shared_ptr const& txn) { map_.insert(std::make_pair( - Key(accountKey(txn->getAccountID(sfAccount)), - txn->getSeqProxy(), - txn->getTransactionID()), - txn)); + Key(accountKey(txn->getAccountID(sfAccount)), txn->getSeqProxy(), txn->getTransactionID()), txn)); } std::shared_ptr @@ -59,10 +56,8 @@ CanonicalTXSet::popAcctTransaction(std::shared_ptr const& tx) auto const seqProxy = tx->getSeqProxy(); Key const after(effectiveAccount, seqProxy, beast::zero); auto const itrNext{map_.lower_bound(after)}; - if (itrNext != map_.end() && - itrNext->first.getAccount() == effectiveAccount && - (!itrNext->second->getSeqProxy().isSeq() || - itrNext->second->getSeqProxy().value() == seqProxy.value() + 1)) + if (itrNext != map_.end() && itrNext->first.getAccount() == effectiveAccount && + (!itrNext->second->getSeqProxy().isSeq() || itrNext->second->getSeqProxy().value() == seqProxy.value() + 1)) { result = std::move(itrNext->second); map_.erase(itrNext); diff --git a/src/xrpld/app/misc/CanonicalTXSet.h b/src/xrpld/app/misc/CanonicalTXSet.h index 8d0461a845..15fb656403 100644 --- a/src/xrpld/app/misc/CanonicalTXSet.h +++ b/src/xrpld/app/misc/CanonicalTXSet.h @@ -86,8 +86,7 @@ private: accountKey(AccountID const& account); public: - using const_iterator = - std::map>::const_iterator; + using const_iterator = std::map>::const_iterator; public: explicit CanonicalTXSet(LedgerHash const& saltHash) : salt_(saltHash) diff --git a/src/xrpld/app/misc/FeeVote.h b/src/xrpld/app/misc/FeeVote.h index aed64be2c2..4b7f7f8409 100644 --- a/src/xrpld/app/misc/FeeVote.h +++ b/src/xrpld/app/misc/FeeVote.h @@ -19,10 +19,7 @@ public: @param baseValidation */ virtual void - doValidation( - Fees const& lastFees, - Rules const& rules, - STValidation& val) = 0; + doValidation(Fees const& lastFees, Rules const& rules, STValidation& val) = 0; /** Cast our local vote on the fee. diff --git a/src/xrpld/app/misc/FeeVoteImpl.cpp b/src/xrpld/app/misc/FeeVoteImpl.cpp index 08a9abf2db..4c38b561f6 100644 --- a/src/xrpld/app/misc/FeeVoteImpl.cpp +++ b/src/xrpld/app/misc/FeeVoteImpl.cpp @@ -18,8 +18,7 @@ private: std::map voteMap_; public: - VotableValue(value_type current, value_type target) - : current_(current), target_(target) + VotableValue(value_type current, value_type target) : current_(current), target_(target) { // Add our vote ++voteMap_[target_]; @@ -55,8 +54,7 @@ VotableValue::getVotes() const -> std::pair for (auto const& [key, val] : voteMap_) { // Take most voted value between current and target, inclusive - if ((key <= std::max(target_, current_)) && - (key >= std::min(target_, current_)) && (val > weight)) + if ((key <= std::max(target_, current_)) && (key >= std::min(target_, current_)) && (val > weight)) { ourVote = key; weight = val; @@ -80,8 +78,7 @@ public: FeeVoteImpl(FeeSetup const& setup, beast::Journal journal); void - doValidation(Fees const& lastFees, Rules const& rules, STValidation& val) - override; + doValidation(Fees const& lastFees, Rules const& rules, STValidation& val) override; void doVoting( @@ -92,55 +89,34 @@ public: //-------------------------------------------------------------------------- -FeeVoteImpl::FeeVoteImpl(FeeSetup const& setup, beast::Journal journal) - : target_(setup), journal_(journal) +FeeVoteImpl::FeeVoteImpl(FeeSetup const& setup, beast::Journal journal) : target_(setup), journal_(journal) { } void -FeeVoteImpl::doValidation( - Fees const& lastFees, - Rules const& rules, - STValidation& v) +FeeVoteImpl::doValidation(Fees const& lastFees, Rules const& rules, STValidation& v) { // Values should always be in a valid range (because the voting process // will ignore out-of-range values) but if we detect such a case, we do // not send a value. if (rules.enabled(featureXRPFees)) { - auto vote = [&v, this]( - auto const current, - XRPAmount target, - char const* name, - auto const& sfield) { + auto vote = [&v, this](auto const current, XRPAmount target, char const* name, auto const& sfield) { if (current != target) { - JLOG(journal_.info()) - << "Voting for " << name << " of " << target; + JLOG(journal_.info()) << "Voting for " << name << " of " << target; v[sfield] = target; } }; vote(lastFees.base, target_.reference_fee, "base fee", sfBaseFeeDrops); - vote( - lastFees.reserve, - target_.account_reserve, - "base reserve", - sfReserveBaseDrops); - vote( - lastFees.increment, - target_.owner_reserve, - "reserve increment", - sfReserveIncrementDrops); + vote(lastFees.reserve, target_.account_reserve, "base reserve", sfReserveBaseDrops); + vote(lastFees.increment, target_.owner_reserve, "reserve increment", sfReserveIncrementDrops); } else { - auto to32 = [](XRPAmount target) { - return target.dropsAs(); - }; - auto to64 = [](XRPAmount target) { - return target.dropsAs(); - }; + auto to32 = [](XRPAmount target) { return target.dropsAs(); }; + auto to64 = [](XRPAmount target) { return target.dropsAs(); }; auto vote = [&v, this]( auto const current, XRPAmount target, @@ -149,8 +125,7 @@ FeeVoteImpl::doValidation( auto const& sfield) { if (current != target) { - JLOG(journal_.info()) - << "Voting for " << name << " of " << target; + JLOG(journal_.info()) << "Voting for " << name << " of " << target; if (auto const f = convertCallback(target)) v[sfield] = *f; @@ -158,18 +133,8 @@ FeeVoteImpl::doValidation( }; vote(lastFees.base, target_.reference_fee, to64, "base fee", sfBaseFee); - vote( - lastFees.reserve, - target_.account_reserve, - to32, - "base reserve", - sfReserveBase); - vote( - lastFees.increment, - target_.owner_reserve, - to32, - "reserve increment", - sfReserveIncrement); + vote(lastFees.reserve, target_.account_reserve, to32, "base reserve", sfReserveBase); + vote(lastFees.increment, target_.owner_reserve, to32, "reserve increment", sfReserveIncrement); } } @@ -181,38 +146,32 @@ FeeVoteImpl::doVoting( { // LCL must be flag ledger XRPL_ASSERT( - lastClosedLedger && isFlagLedger(lastClosedLedger->seq()), - "xrpl::FeeVoteImpl::doVoting : has a flag ledger"); + lastClosedLedger && isFlagLedger(lastClosedLedger->seq()), "xrpl::FeeVoteImpl::doVoting : has a flag ledger"); - detail::VotableValue baseFeeVote( - lastClosedLedger->fees().base, target_.reference_fee); + detail::VotableValue baseFeeVote(lastClosedLedger->fees().base, target_.reference_fee); - detail::VotableValue baseReserveVote( - lastClosedLedger->fees().reserve, target_.account_reserve); + detail::VotableValue baseReserveVote(lastClosedLedger->fees().reserve, target_.account_reserve); - detail::VotableValue incReserveVote( - lastClosedLedger->fees().increment, target_.owner_reserve); + detail::VotableValue incReserveVote(lastClosedLedger->fees().increment, target_.owner_reserve); auto const& rules = lastClosedLedger->rules(); if (rules.enabled(featureXRPFees)) { - auto doVote = [](std::shared_ptr const& val, - detail::VotableValue& value, - SF_AMOUNT const& xrpField) { - if (auto const field = ~val->at(~xrpField); - field && field->native()) - { - auto const vote = field->xrp(); - if (isLegalAmountSigned(vote)) - value.addVote(vote); + auto doVote = + [](std::shared_ptr const& val, detail::VotableValue& value, SF_AMOUNT const& xrpField) { + if (auto const field = ~val->at(~xrpField); field && field->native()) + { + auto const vote = field->xrp(); + if (isLegalAmountSigned(vote)) + value.addVote(vote); + else + value.noVote(); + } else + { value.noVote(); - } - else - { - value.noVote(); - } - }; + } + }; for (auto const& val : set) { @@ -225,27 +184,26 @@ FeeVoteImpl::doVoting( } else { - auto doVote = [](std::shared_ptr const& val, - detail::VotableValue& value, - auto const& valueField) { - if (auto const field = val->at(~valueField)) - { - using XRPType = XRPAmount::value_type; - auto const vote = *field; - if (vote <= std::numeric_limits::max() && - isLegalAmountSigned(XRPAmount{unsafe_cast(vote)})) - value.addVote(XRPAmount{unsafe_cast(vote)}); + auto doVote = + [](std::shared_ptr const& val, detail::VotableValue& value, auto const& valueField) { + if (auto const field = val->at(~valueField)) + { + using XRPType = XRPAmount::value_type; + auto const vote = *field; + if (vote <= std::numeric_limits::max() && + isLegalAmountSigned(XRPAmount{unsafe_cast(vote)})) + value.addVote(XRPAmount{unsafe_cast(vote)}); + else + // Invalid amounts will be treated as if they're + // not provided. Don't throw because this value is + // provided by an external entity. + value.noVote(); + } else - // Invalid amounts will be treated as if they're - // not provided. Don't throw because this value is - // provided by an external entity. + { value.noVote(); - } - else - { - value.noVote(); - } - }; + } + }; for (auto const& val : set) { @@ -270,9 +228,8 @@ FeeVoteImpl::doVoting( // add transactions to our position if (baseFee.second || baseReserve.second || incReserve.second) { - JLOG(journal_.warn()) - << "We are voting for a fee change: " << baseFee.first << "/" - << baseReserve.first << "/" << incReserve.first; + JLOG(journal_.warn()) << "We are voting for a fee change: " << baseFee.first << "/" << baseReserve.first << "/" + << incReserve.first; STTx feeTx(ttFEE, [=, &rules](auto& obj) { obj[sfAccount] = AccountID(); @@ -287,13 +244,9 @@ FeeVoteImpl::doVoting( { // Without the featureXRPFees amendment, these fields are // required. - obj[sfBaseFee] = - baseFee.first.dropsAs(baseFeeVote.current()); - obj[sfReserveBase] = baseReserve.first.dropsAs( - baseReserveVote.current()); - obj[sfReserveIncrement] = - incReserve.first.dropsAs( - incReserveVote.current()); + obj[sfBaseFee] = baseFee.first.dropsAs(baseFeeVote.current()); + obj[sfReserveBase] = baseReserve.first.dropsAs(baseReserveVote.current()); + obj[sfReserveIncrement] = incReserve.first.dropsAs(incReserveVote.current()); obj[sfReferenceFeeUnits] = Config::FEE_UNITS_DEPRECATED; } }); @@ -305,9 +258,7 @@ FeeVoteImpl::doVoting( Serializer s; feeTx.add(s); - if (!initialPosition->addGiveItem( - SHAMapNodeType::tnTRANSACTION_NM, - make_shamapitem(txID, s.slice()))) + if (!initialPosition->addGiveItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(txID, s.slice()))) { JLOG(journal_.warn()) << "Ledger already had fee change"; } diff --git a/src/xrpld/app/misc/HashRouter.cpp b/src/xrpld/app/misc/HashRouter.cpp index a2ba41b361..eca46c9872 100644 --- a/src/xrpld/app/misc/HashRouter.cpp +++ b/src/xrpld/app/misc/HashRouter.cpp @@ -17,8 +17,7 @@ HashRouter::emplace(uint256 const& key) -> std::pair // See if any suppressions need to be expired expire(suppressionMap_, setup_.holdTime); - return std::make_pair( - std::ref(suppressionMap_.emplace(key, Entry()).first->second), true); + return std::make_pair(std::ref(suppressionMap_.emplace(key, Entry()).first->second), true); } void @@ -46,10 +45,7 @@ HashRouter::addSuppressionPeerWithStatus(uint256 const& key, PeerShortID peer) } bool -HashRouter::addSuppressionPeer( - uint256 const& key, - PeerShortID peer, - HashRouterFlags& flags) +HashRouter::addSuppressionPeer(uint256 const& key, PeerShortID peer, HashRouterFlags& flags) { std::lock_guard lock(mutex_); @@ -86,8 +82,7 @@ HashRouter::getFlags(uint256 const& key) bool HashRouter::setFlags(uint256 const& key, HashRouterFlags flags) { - XRPL_ASSERT( - static_cast(flags), "xrpl::HashRouter::setFlags : valid input"); + XRPL_ASSERT(static_cast(flags), "xrpl::HashRouter::setFlags : valid input"); std::lock_guard lock(mutex_); @@ -101,8 +96,7 @@ HashRouter::setFlags(uint256 const& key, HashRouterFlags flags) } auto -HashRouter::shouldRelay(uint256 const& key) - -> std::optional> +HashRouter::shouldRelay(uint256 const& key) -> std::optional> { std::lock_guard lock(mutex_); @@ -142,8 +136,7 @@ setup_HashRouter(Config const& config) } if (setup.relayTime > setup.holdTime) { - Throw( - "HashRouter relay time must be less than or equal to hold time"); + Throw("HashRouter relay time must be less than or equal to hold time"); } return setup; diff --git a/src/xrpld/app/misc/HashRouter.h b/src/xrpld/app/misc/HashRouter.h index 449097a387..d4ff8629f3 100644 --- a/src/xrpld/app/misc/HashRouter.h +++ b/src/xrpld/app/misc/HashRouter.h @@ -154,9 +154,7 @@ private: last relay timestamp and return true. */ bool - shouldRelay( - Stopwatch::time_point const& now, - std::chrono::seconds relayTime) + shouldRelay(Stopwatch::time_point const& now, std::chrono::seconds relayTime) { if (relayed_ && *relayed_ + relayTime > now) return false; @@ -183,8 +181,7 @@ private: }; public: - HashRouter(Setup const& setup, Stopwatch& clock) - : setup_(setup), suppressionMap_(clock) + HashRouter(Setup const& setup, Stopwatch& clock) : setup_(setup), suppressionMap_(clock) { } @@ -210,18 +207,11 @@ public: addSuppressionPeerWithStatus(uint256 const& key, PeerShortID peer); bool - addSuppressionPeer( - uint256 const& key, - PeerShortID peer, - HashRouterFlags& flags); + addSuppressionPeer(uint256 const& key, PeerShortID peer, HashRouterFlags& flags); // Add a peer suppression and return whether the entry should be processed bool - shouldProcess( - uint256 const& key, - PeerShortID peer, - HashRouterFlags& flags, - std::chrono::seconds tx_interval); + shouldProcess(uint256 const& key, PeerShortID peer, HashRouterFlags& flags, std::chrono::seconds tx_interval); /** Set the flags on a hash. @@ -259,12 +249,7 @@ private: Setup const setup_; // Stores all suppressed hashes and their expiration time - beast::aged_unordered_map< - uint256, - Entry, - Stopwatch::clock_type, - hardened_hash> - suppressionMap_; + beast::aged_unordered_map> suppressionMap_; }; HashRouter::Setup diff --git a/src/xrpld/app/misc/LendingHelpers.h b/src/xrpld/app/misc/LendingHelpers.h index 79fc617569..0e04f0f793 100644 --- a/src/xrpld/app/misc/LendingHelpers.h +++ b/src/xrpld/app/misc/LendingHelpers.h @@ -19,10 +19,7 @@ loanPeriodicRate(TenthBips32 interestRate, std::uint32_t paymentInterval); /// Ensure the periodic payment is always rounded consistently inline Number -roundPeriodicPayment( - Asset const& asset, - Number const& periodicPayment, - std::int32_t scale) +roundPeriodicPayment(Asset const& asset, Number const& periodicPayment, std::int32_t scale) { return roundToAsset(asset, periodicPayment, scale, Number::upward); } @@ -113,8 +110,7 @@ struct LoanState interestOutstanding() const { XRPL_ASSERT_PARTS( - interestDue + managementFeeDue == - valueOutstanding - principalOutstanding, + interestDue + managementFeeDue == valueOutstanding - principalOutstanding, "xrpl::LoanState::interestOutstanding", "other values add up correctly"); return interestDue + managementFeeDue; @@ -159,11 +155,7 @@ struct LoanProperties // accumulated rounding errors and leftover dust amounts. template void -adjustImpreciseNumber( - NumberProxy value, - Number const& adjustment, - Asset const& asset, - int vaultScale) +adjustImpreciseNumber(NumberProxy value, Number const& adjustment, Asset const& asset, int vaultScale) { value = roundToAsset(asset, value + adjustment, vaultScale); @@ -176,8 +168,7 @@ getAssetsTotalScale(SLE::const_ref vaultSle) { if (!vaultSle) return Number::minExponent - 1; // LCOV_EXCL_LINE - return STAmount{vaultSle->at(sfAsset), vaultSle->at(sfAssetsTotal)} - .exponent(); + return STAmount{vaultSle->at(sfAsset), vaultSle->at(sfAssetsTotal)}.exponent(); } TER @@ -209,11 +200,7 @@ LoanState constructRoundedLoanState(SLE::const_ref loan); Number -computeManagementFee( - Asset const& asset, - Number const& interest, - TenthBips32 managementFeeRate, - std::int32_t scale); +computeManagementFee(Asset const& asset, Number const& interest, TenthBips32 managementFeeRate, std::int32_t scale); Number computeFullPaymentInterest( @@ -317,15 +304,11 @@ struct ExtendedPaymentComponents : public PaymentComponents // borrower is sufficient to cover all components of the payment. Number totalDue; - ExtendedPaymentComponents( - PaymentComponents const& p, - Number fee, - Number interest = numZero) + ExtendedPaymentComponents(PaymentComponents const& p, Number fee, Number interest = numZero) : PaymentComponents(p) , untrackedManagementFee(fee) , untrackedInterest(interest) - , totalDue( - trackedValueDelta + untrackedInterest + untrackedManagementFee) + , totalDue(trackedValueDelta + untrackedInterest + untrackedManagementFee) { } }; @@ -378,9 +361,7 @@ Number computeRaisedRate(Number const& periodicRate, std::uint32_t paymentsRemaining); Number -computePaymentFactor( - Number const& periodicRate, - std::uint32_t paymentsRemaining); +computePaymentFactor(Number const& periodicRate, std::uint32_t paymentsRemaining); std::pair computeInterestAndFeeParts( @@ -390,10 +371,7 @@ computeInterestAndFeeParts( std::int32_t loanScale); Number -loanPeriodicPayment( - Number const& principalOutstanding, - Number const& periodicRate, - std::uint32_t paymentsRemaining); +loanPeriodicPayment(Number const& principalOutstanding, Number const& periodicRate, std::uint32_t paymentsRemaining); Number loanPrincipalFromPeriodicPayment( diff --git a/src/xrpld/app/misc/LoadFeeTrack.h b/src/xrpld/app/misc/LoadFeeTrack.h index 181fb0536e..3c6932fa41 100644 --- a/src/xrpld/app/misc/LoadFeeTrack.h +++ b/src/xrpld/app/misc/LoadFeeTrack.h @@ -25,8 +25,7 @@ struct Fees; class LoadFeeTrack final { public: - explicit LoadFeeTrack( - beast::Journal journal = beast::Journal(beast::Journal::getNullSink())) + explicit LoadFeeTrack(beast::Journal journal = beast::Journal(beast::Journal::getNullSink())) : j_(journal) , localTxnLoadFee_(lftNormalFee) , remoteTxnLoadFee_(lftNormalFee) @@ -76,8 +75,7 @@ public: getLoadFactor() const { std::lock_guard sl(lock_); - return std::max( - {clusterTxnLoadFee_, localTxnLoadFee_, remoteTxnLoadFee_}); + return std::max({clusterTxnLoadFee_, localTxnLoadFee_, remoteTxnLoadFee_}); } std::pair @@ -86,8 +84,7 @@ public: std::lock_guard sl(lock_); return std::make_pair( - std::max(localTxnLoadFee_, remoteTxnLoadFee_), - std::max(remoteTxnLoadFee_, clusterTxnLoadFee_)); + std::max(localTxnLoadFee_, remoteTxnLoadFee_), std::max(remoteTxnLoadFee_, clusterTxnLoadFee_)); } void @@ -114,26 +111,21 @@ public: isLoadedCluster() const { std::lock_guard sl(lock_); - return (raiseCount_ != 0) || (localTxnLoadFee_ != lftNormalFee) || - (clusterTxnLoadFee_ != lftNormalFee); + return (raiseCount_ != 0) || (localTxnLoadFee_ != lftNormalFee) || (clusterTxnLoadFee_ != lftNormalFee); } private: - static std::uint32_t constexpr lftNormalFee = - 256; // 256 is the minimum/normal load factor - static std::uint32_t constexpr lftFeeIncFraction = - 4; // increase fee by 1/4 - static std::uint32_t constexpr lftFeeDecFraction = - 4; // decrease fee by 1/4 + static std::uint32_t constexpr lftNormalFee = 256; // 256 is the minimum/normal load factor + static std::uint32_t constexpr lftFeeIncFraction = 4; // increase fee by 1/4 + static std::uint32_t constexpr lftFeeDecFraction = 4; // decrease fee by 1/4 static std::uint32_t constexpr lftFeeMax = lftNormalFee * 1000000; beast::Journal const j_; std::mutex mutable lock_; - std::uint32_t localTxnLoadFee_; // Scale factor, lftNormalFee = normal fee - std::uint32_t remoteTxnLoadFee_; // Scale factor, lftNormalFee = normal fee - std::uint32_t - clusterTxnLoadFee_; // Scale factor, lftNormalFee = normal fee + std::uint32_t localTxnLoadFee_; // Scale factor, lftNormalFee = normal fee + std::uint32_t remoteTxnLoadFee_; // Scale factor, lftNormalFee = normal fee + std::uint32_t clusterTxnLoadFee_; // Scale factor, lftNormalFee = normal fee std::uint32_t raiseCount_; }; @@ -141,11 +133,7 @@ private: // Scale using load as well as base rate XRPAmount -scaleFeeLoad( - XRPAmount fee, - LoadFeeTrack const& feeTrack, - Fees const& fees, - bool bUnlimited); +scaleFeeLoad(XRPAmount fee, LoadFeeTrack const& feeTrack, Fees const& fees, bool bUnlimited); } // namespace xrpl diff --git a/src/xrpld/app/misc/Manifest.h b/src/xrpld/app/misc/Manifest.h index c1a77be63b..a41e16dbf9 100644 --- a/src/xrpld/app/misc/Manifest.h +++ b/src/xrpld/app/misc/Manifest.h @@ -86,11 +86,7 @@ struct Manifest std::optional const& signingKey_, std::uint32_t seq, std::string const& domain_) - : serialized(serialized_) - , masterKey(masterKey_) - , signingKey(signingKey_) - , sequence(seq) - , domain(domain_) + : serialized(serialized_), masterKey(masterKey_), signingKey(signingKey_), sequence(seq), domain(domain_) { } @@ -146,21 +142,14 @@ std::optional deserializeManifest(Slice s, beast::Journal journal); inline std::optional -deserializeManifest( - std::string const& s, - beast::Journal journal = beast::Journal(beast::Journal::getNullSink())) +deserializeManifest(std::string const& s, beast::Journal journal = beast::Journal(beast::Journal::getNullSink())) { return deserializeManifest(makeSlice(s), journal); } -template < - class T, - class = std::enable_if_t< - std::is_same::value || std::is_same::value>> +template ::value || std::is_same::value>> std::optional -deserializeManifest( - std::vector const& v, - beast::Journal journal = beast::Journal(beast::Journal::getNullSink())) +deserializeManifest(std::vector const& v, beast::Journal journal = beast::Journal(beast::Journal::getNullSink())) { return deserializeManifest(makeSlice(v), journal); } @@ -171,9 +160,8 @@ operator==(Manifest const& lhs, Manifest const& rhs) { // In theory, comparing the two serialized strings should be // sufficient. - return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey && - lhs.signingKey == rhs.signingKey && lhs.domain == rhs.domain && - lhs.serialized == rhs.serialized; + return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey && lhs.signingKey == rhs.signingKey && + lhs.domain == rhs.domain && lhs.serialized == rhs.serialized; } inline bool @@ -248,9 +236,7 @@ private: std::atomic seq_{0}; public: - explicit ManifestCache( - beast::Journal j = beast::Journal(beast::Journal::getNullSink())) - : j_(j) + explicit ManifestCache(beast::Journal j = beast::Journal(beast::Journal::getNullSink())) : j_(j) { } @@ -383,10 +369,7 @@ public: May be called concurrently */ void - save( - DatabaseCon& dbCon, - std::string const& dbTable, - std::function const& isTrusted); + save(DatabaseCon& dbCon, std::string const& dbTable, std::function const& isTrusted); /** Invokes the callback once for every populated manifest. diff --git a/src/xrpld/app/misc/NegativeUNLVote.cpp b/src/xrpld/app/misc/NegativeUNLVote.cpp index 12467697fa..d4a64a34dd 100644 --- a/src/xrpld/app/misc/NegativeUNLVote.cpp +++ b/src/xrpld/app/misc/NegativeUNLVote.cpp @@ -6,8 +6,7 @@ namespace xrpl { -NegativeUNLVote::NegativeUNLVote(NodeID const& myId, beast::Journal j) - : myId_(myId), j_(j) +NegativeUNLVote::NegativeUNLVote(NodeID const& myId, beast::Journal j) : myId_(myId), j_(j) { } @@ -63,27 +62,20 @@ NegativeUNLVote::doVoting( purgeNewValidators(seq); // Process the table and find all candidates to disable or to re-enable - auto const candidates = - findAllCandidates(unlNodeIDs, negUnlNodeIDs, *scoreTable); + auto const candidates = findAllCandidates(unlNodeIDs, negUnlNodeIDs, *scoreTable); // Pick one to disable and one to re-enable if any, add ttUNL_MODIFY Tx if (!candidates.toDisableCandidates.empty()) { - auto n = choose( - prevLedger->header().hash, candidates.toDisableCandidates); - XRPL_ASSERT( - nidToKeyMap.contains(n), - "xrpl::NegativeUNLVote::doVoting : found node to disable"); + auto n = choose(prevLedger->header().hash, candidates.toDisableCandidates); + XRPL_ASSERT(nidToKeyMap.contains(n), "xrpl::NegativeUNLVote::doVoting : found node to disable"); addTx(seq, nidToKeyMap.at(n), ToDisable, initialSet); } if (!candidates.toReEnableCandidates.empty()) { - auto n = choose( - prevLedger->header().hash, candidates.toReEnableCandidates); - XRPL_ASSERT( - nidToKeyMap.contains(n), - "xrpl::NegativeUNLVote::doVoting : found node to enable"); + auto n = choose(prevLedger->header().hash, candidates.toReEnableCandidates); + XRPL_ASSERT(nidToKeyMap.contains(n), "xrpl::NegativeUNLVote::doVoting : found node to enable"); addTx(seq, nidToKeyMap.at(n), ToReEnable, initialSet); } } @@ -105,29 +97,22 @@ NegativeUNLVote::addTx( Serializer s; negUnlTx.add(s); if (!initialSet->addGiveItem( - SHAMapNodeType::tnTRANSACTION_NM, - make_shamapitem(negUnlTx.getTransactionID(), s.slice()))) + SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(negUnlTx.getTransactionID(), s.slice()))) { - JLOG(j_.warn()) << "N-UNL: ledger seq=" << seq - << ", add ttUNL_MODIFY tx failed"; + JLOG(j_.warn()) << "N-UNL: ledger seq=" << seq << ", add ttUNL_MODIFY tx failed"; } else { JLOG(j_.debug()) << "N-UNL: ledger seq=" << seq - << ", add a ttUNL_MODIFY Tx with txID: " - << negUnlTx.getTransactionID() << ", the validator to " - << (modify == ToDisable ? "disable: " : "re-enable: ") - << vp; + << ", add a ttUNL_MODIFY Tx with txID: " << negUnlTx.getTransactionID() + << ", the validator to " << (modify == ToDisable ? "disable: " : "re-enable: ") << vp; } } NodeID -NegativeUNLVote::choose( - uint256 const& randomPadData, - std::vector const& candidates) +NegativeUNLVote::choose(uint256 const& randomPadData, std::vector const& candidates) { - XRPL_ASSERT( - !candidates.empty(), "xrpl::NegativeUNLVote::choose : non-empty input"); + XRPL_ASSERT(!candidates.empty(), "xrpl::NegativeUNLVote::choose : non-empty input"); static_assert(NodeID::bytes <= uint256::bytes); NodeID randomPad = NodeID::fromVoid(randomPadData.data()); NodeID txNodeID = candidates[0]; @@ -167,9 +152,8 @@ NegativeUNLVote::buildScoreTable( auto const numAncestors = ledgerAncestors.size(); if (numAncestors < FLAG_LEDGER_INTERVAL) { - JLOG(j_.debug()) << "N-UNL: ledger " << seq - << " not enough history. Can trace back only " - << numAncestors << " ledgers."; + JLOG(j_.debug()) << "N-UNL: ledger " << seq << " not enough history. Can trace back only " << numAncestors + << " ledgers."; return {}; } @@ -184,8 +168,7 @@ NegativeUNLVote::buildScoreTable( // the score table. for (int i = 0; i < FLAG_LEDGER_INTERVAL; ++i) { - for (auto const& v : validations.getTrustedForLedger( - ledgerAncestors[numAncestors - 1 - i], seq - 2 - i)) + for (auto const& v : validations.getTrustedForLedger(ledgerAncestors[numAncestors - 1 - i], seq - 2 - i)) { if (scoreTable.count(v->getNodeID())) ++scoreTable[v->getNodeID()]; @@ -201,16 +184,12 @@ NegativeUNLVote::buildScoreTable( }(); if (myValidationCount < negativeUNLMinLocalValsToVote) { - JLOG(j_.debug()) << "N-UNL: ledger " << seq - << ". Local node only issued " << myValidationCount - << " validations in last " << FLAG_LEDGER_INTERVAL - << " ledgers." + JLOG(j_.debug()) << "N-UNL: ledger " << seq << ". Local node only issued " << myValidationCount + << " validations in last " << FLAG_LEDGER_INTERVAL << " ledgers." << " The reliability measurement could be wrong."; return {}; } - else if ( - myValidationCount > negativeUNLMinLocalValsToVote && - myValidationCount <= FLAG_LEDGER_INTERVAL) + else if (myValidationCount > negativeUNLMinLocalValsToVote && myValidationCount <= FLAG_LEDGER_INTERVAL) { return scoreTable; } @@ -218,9 +197,8 @@ NegativeUNLVote::buildScoreTable( { // cannot happen because validations.getTrustedForLedger does not // return multiple validations of the same ledger from a validator. - JLOG(j_.error()) << "N-UNL: ledger " << seq << ". Local node issued " - << myValidationCount << " validations in last " - << FLAG_LEDGER_INTERVAL << " ledgers. Too many!"; + JLOG(j_.error()) << "N-UNL: ledger " << seq << ". Local node issued " << myValidationCount + << " validations in last " << FLAG_LEDGER_INTERVAL << " ledgers. Too many!"; return {}; } } @@ -233,8 +211,7 @@ NegativeUNLVote::findAllCandidates( { // Compute if need to find more validators to disable auto const canAdd = [&]() -> bool { - auto const maxNegativeListed = static_cast( - std::ceil(unl.size() * negativeUNLMaxListed)); + auto const maxNegativeListed = static_cast(std::ceil(unl.size() * negativeUNLMaxListed)); std::size_t negativeListed = 0; for (auto const& n : unl) { @@ -242,11 +219,9 @@ NegativeUNLVote::findAllCandidates( ++negativeListed; } bool const result = negativeListed < maxNegativeListed; - JLOG(j_.trace()) << "N-UNL: nodeId " << myId_ << " lowWaterMark " - << negativeUNLLowWaterMark << " highWaterMark " - << negativeUNLHighWaterMark << " canAdd " << result - << " negativeListed " << negativeListed - << " maxNegativeListed " << maxNegativeListed; + JLOG(j_.trace()) << "N-UNL: nodeId " << myId_ << " lowWaterMark " << negativeUNLLowWaterMark + << " highWaterMark " << negativeUNLHighWaterMark << " canAdd " << result << " negativeListed " + << negativeListed << " maxNegativeListed " << maxNegativeListed; return result; }(); @@ -260,8 +235,7 @@ NegativeUNLVote::findAllCandidates( // (2) has less than negativeUNLLowWaterMark validations, // (3) is not in negUnl, and // (4) is not a new validator. - if (canAdd && score < negativeUNLLowWaterMark && - !negUnl.count(nodeId) && !newValidators_.count(nodeId)) + if (canAdd && score < negativeUNLLowWaterMark && !negUnl.count(nodeId) && !newValidators_.count(nodeId)) { JLOG(j_.trace()) << "N-UNL: toDisable candidate " << nodeId; candidates.toDisableCandidates.push_back(nodeId); @@ -301,17 +275,14 @@ NegativeUNLVote::findAllCandidates( } void -NegativeUNLVote::newValidators( - LedgerIndex seq, - hash_set const& nowTrusted) +NegativeUNLVote::newValidators(LedgerIndex seq, hash_set const& nowTrusted) { std::lock_guard lock(mutex_); for (auto const& n : nowTrusted) { if (newValidators_.find(n) == newValidators_.end()) { - JLOG(j_.trace()) << "N-UNL: add a new validator " << n - << " at ledger seq=" << seq; + JLOG(j_.trace()) << "N-UNL: add a new validator " << n << " at ledger seq=" << seq; newValidators_[n] = seq; } } diff --git a/src/xrpld/app/misc/NegativeUNLVote.h b/src/xrpld/app/misc/NegativeUNLVote.h index 3146294923..68daa0e57b 100644 --- a/src/xrpld/app/misc/NegativeUNLVote.h +++ b/src/xrpld/app/misc/NegativeUNLVote.h @@ -34,20 +34,17 @@ public: * An unreliable validator is a candidate to be disabled by the NegativeUNL * protocol. */ - static constexpr size_t negativeUNLLowWaterMark = - FLAG_LEDGER_INTERVAL * 50 / 100; + static constexpr size_t negativeUNLLowWaterMark = FLAG_LEDGER_INTERVAL * 50 / 100; /** * An unreliable validator must have more than negativeUNLHighWaterMark * validations in the last flag ledger period to be re-enabled. */ - static constexpr size_t negativeUNLHighWaterMark = - FLAG_LEDGER_INTERVAL * 80 / 100; + static constexpr size_t negativeUNLHighWaterMark = FLAG_LEDGER_INTERVAL * 80 / 100; /** * The minimum number of validations of the local node for it to * participate in the voting. */ - static constexpr size_t negativeUNLMinLocalValsToVote = - FLAG_LEDGER_INTERVAL * 90 / 100; + static constexpr size_t negativeUNLMinLocalValsToVote = FLAG_LEDGER_INTERVAL * 90 / 100; /** * We don't want to disable new validators immediately after adding them. * So we skip voting for disabling them for 2 flag ledgers. @@ -129,11 +126,7 @@ private: * @param initialSet the transaction set */ void - addTx( - LedgerIndex seq, - PublicKey const& vp, - NegativeUNLModify modify, - std::shared_ptr const& initialSet); + addTx(LedgerIndex seq, PublicKey const& vp, NegativeUNLModify modify, std::shared_ptr const& initialSet); /** * Pick one candidate from a vector of candidates. diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index 696512b5f4..7da26ada40 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -82,11 +82,7 @@ class NetworkOPsImp final : public NetworkOPs bool applied = false; TER result; - TransactionStatus( - std::shared_ptr t, - bool a, - bool l, - FailHard f) + TransactionStatus(std::shared_ptr t, bool a, bool l, FailHard f) : transaction(t), admin(a), local(l), failType(f) { XRPL_ASSERT( @@ -134,8 +130,7 @@ class NetworkOPsImp final : public NetworkOPs OperatingMode mode_ = OperatingMode::DISCONNECTED; std::array counters_; mutable std::mutex mutex_; - std::chrono::steady_clock::time_point start_ = - std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point start_ = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point const processStart_ = start_; std::uint64_t initialSyncUs_{0}; static std::array const states_; @@ -143,8 +138,7 @@ class NetworkOPsImp final : public NetworkOPs public: explicit StateAccounting() { - counters_[static_cast(OperatingMode::DISCONNECTED)] - .transitions = 1; + counters_[static_cast(OperatingMode::DISCONNECTED)].transitions = 1; } /** @@ -185,10 +179,7 @@ class NetworkOPsImp final : public NetworkOPs { ServerFeeSummary() = default; - ServerFeeSummary( - XRPAmount fee, - TxQ::Metrics&& escalationMetrics, - LoadFeeTrack const& loadFeeTrack); + ServerFeeSummary(XRPAmount fee, TxQ::Metrics&& escalationMetrics, LoadFeeTrack const& loadFeeTrack); bool operator!=(ServerFeeSummary const& b) const; @@ -226,21 +217,15 @@ public: , accountHistoryTxTimer_(io_svc) , mConsensus( app, - make_FeeVote( - setup_FeeVote(app_.config().section("voting")), - app_.logs().journal("FeeVote")), + make_FeeVote(setup_FeeVote(app_.config().section("voting")), app_.logs().journal("FeeVote")), ledgerMaster, *m_localTX, app.getInboundTransactions(), beast::get_abstract_clock(), validatorKeys, app_.logs().journal("LedgerConsensus")) - , validatorPK_( - validatorKeys.keys ? validatorKeys.keys->publicKey - : decltype(validatorPK_){}) - , validatorMasterPK_( - validatorKeys.keys ? validatorKeys.keys->masterPublicKey - : decltype(validatorMasterPK_){}) + , validatorPK_(validatorKeys.keys ? validatorKeys.keys->publicKey : decltype(validatorPK_){}) + , validatorMasterPK_(validatorKeys.keys ? validatorKeys.keys->masterPublicKey : decltype(validatorMasterPK_){}) , m_ledgerMaster(ledgerMaster) , m_job_queue(job_queue) , m_standalone(standalone) @@ -276,11 +261,8 @@ public: submitTransaction(std::shared_ptr const&) override; void - processTransaction( - std::shared_ptr& transaction, - bool bUnlimited, - bool bLocal, - FailHard failType) override; + processTransaction(std::shared_ptr& transaction, bool bUnlimited, bool bLocal, FailHard failType) + override; void processTransactionSet(CanonicalTXSet const& set) override; @@ -294,10 +276,7 @@ public: * @param failType fail_hard setting from transaction submission. */ void - doTransactionSync( - std::shared_ptr transaction, - bool bUnlimited, - FailHard failType); + doTransactionSync(std::shared_ptr transaction, bool bUnlimited, FailHard failType); /** * For transactions not submitted by a locally connected client, fire and @@ -309,10 +288,7 @@ public: * @param failType fail_hard setting from transaction submission. */ void - doTransactionAsync( - std::shared_ptr transaction, - bool bUnlimited, - FailHard failtype); + doTransactionAsync(std::shared_ptr transaction, bool bUnlimited, FailHard failtype); private: bool @@ -343,9 +319,7 @@ public: // Json::Value - getOwnerInfo( - std::shared_ptr lpLedger, - AccountID const& account) override; + getOwnerInfo(std::shared_ptr lpLedger, AccountID const& account) override; // // Book functions. @@ -366,9 +340,7 @@ public: processTrustedProposal(RCLCxPeerPos proposal) override; bool - recvValidation( - std::shared_ptr const& val, - std::string const& source) override; + recvValidation(std::shared_ptr const& val, std::string const& source) override; void mapComplete(std::shared_ptr const& map, bool fromAcquire) override; @@ -384,9 +356,7 @@ private: public: bool - beginConsensus( - uint256 const& networkClosed, - std::unique_ptr const& clog) override; + beginConsensus(uint256 const& networkClosed, std::unique_ptr const& clog) override; void endConsensus(std::unique_ptr const& clog) override; void @@ -440,8 +410,7 @@ public: Json::Value getLedgerFetchInfo() override; std::uint32_t - acceptLedger( - std::optional consensusDelay) override; + acceptLedger(std::optional consensusDelay) override; void reportFeeChange() override; void @@ -470,38 +439,22 @@ public: // InfoSub::Source. // void - subAccount( - InfoSub::ref ispListener, - hash_set const& vnaAccountIDs, - bool rt) override; + subAccount(InfoSub::ref ispListener, hash_set const& vnaAccountIDs, bool rt) override; void - unsubAccount( - InfoSub::ref ispListener, - hash_set const& vnaAccountIDs, - bool rt) override; + unsubAccount(InfoSub::ref ispListener, hash_set const& vnaAccountIDs, bool rt) override; // Just remove the subscription from the tracking // not from the InfoSub. Needed for InfoSub destruction void - unsubAccountInternal( - std::uint64_t seq, - hash_set const& vnaAccountIDs, - bool rt) override; + unsubAccountInternal(std::uint64_t seq, hash_set const& vnaAccountIDs, bool rt) override; error_code_i - subAccountHistory(InfoSub::ref ispListener, AccountID const& account) - override; + subAccountHistory(InfoSub::ref ispListener, AccountID const& account) override; void - unsubAccountHistory( - InfoSub::ref ispListener, - AccountID const& account, - bool historyOnly) override; + unsubAccountHistory(InfoSub::ref ispListener, AccountID const& account, bool historyOnly) override; void - unsubAccountHistoryInternal( - std::uint64_t seq, - AccountID const& account, - bool historyOnly) override; + unsubAccountHistoryInternal(std::uint64_t seq, AccountID const& account, bool historyOnly) override; bool subLedger(InfoSub::ref ispListener, Json::Value& jvResult) override; @@ -514,8 +467,7 @@ public: unsubBookChanges(std::uint64_t uListener) override; bool - subServer(InfoSub::ref ispListener, Json::Value& jvResult, bool admin) - override; + subServer(InfoSub::ref ispListener, Json::Value& jvResult, bool admin) override; bool unsubServer(std::uint64_t uListener) override; @@ -575,8 +527,7 @@ public: } catch (boost::system::system_error const& e) { - JLOG(m_journal.error()) - << "NetworkOPs: heartbeatTimer cancel error: " << e.what(); + JLOG(m_journal.error()) << "NetworkOPs: heartbeatTimer cancel error: " << e.what(); } try @@ -585,8 +536,7 @@ public: } catch (boost::system::system_error const& e) { - JLOG(m_journal.error()) - << "NetworkOPs: clusterTimer cancel error: " << e.what(); + JLOG(m_journal.error()) << "NetworkOPs: clusterTimer cancel error: " << e.what(); } try @@ -595,9 +545,7 @@ public: } catch (boost::system::system_error const& e) { - JLOG(m_journal.error()) - << "NetworkOPs: accountHistoryTxTimer cancel error: " - << e.what(); + JLOG(m_journal.error()) << "NetworkOPs: accountHistoryTxTimer cancel error: " << e.what(); } } // Make sure that any waitHandlers pending in our timers are done. @@ -705,16 +653,13 @@ private: InfoSub::wptr sinkWptr_; std::shared_ptr index_; }; - using SubAccountHistoryMapType = - hash_map>; + using SubAccountHistoryMapType = hash_map>; /** * @note called while holding mSubLock */ void - subAccountHistoryStart( - std::shared_ptr const& ledger, - SubAccountHistoryInfoWeak& subInfo); + subAccountHistoryStart(std::shared_ptr const& ledger, SubAccountHistoryInfoWeak& subInfo); void addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo); void @@ -795,37 +740,18 @@ private: struct Stats { template - Stats( - Handler const& handler, - beast::insight::Collector::ptr const& collector) + Stats(Handler const& handler, beast::insight::Collector::ptr const& collector) : hook(collector->make_hook(handler)) - , disconnected_duration(collector->make_gauge( - "State_Accounting", - "Disconnected_duration")) - , connected_duration(collector->make_gauge( - "State_Accounting", - "Connected_duration")) - , syncing_duration( - collector->make_gauge("State_Accounting", "Syncing_duration")) - , tracking_duration(collector->make_gauge( - "State_Accounting", - "Tracking_duration")) - , full_duration( - collector->make_gauge("State_Accounting", "Full_duration")) - , disconnected_transitions(collector->make_gauge( - "State_Accounting", - "Disconnected_transitions")) - , connected_transitions(collector->make_gauge( - "State_Accounting", - "Connected_transitions")) - , syncing_transitions(collector->make_gauge( - "State_Accounting", - "Syncing_transitions")) - , tracking_transitions(collector->make_gauge( - "State_Accounting", - "Tracking_transitions")) - , full_transitions( - collector->make_gauge("State_Accounting", "Full_transitions")) + , disconnected_duration(collector->make_gauge("State_Accounting", "Disconnected_duration")) + , connected_duration(collector->make_gauge("State_Accounting", "Connected_duration")) + , syncing_duration(collector->make_gauge("State_Accounting", "Syncing_duration")) + , tracking_duration(collector->make_gauge("State_Accounting", "Tracking_duration")) + , full_duration(collector->make_gauge("State_Accounting", "Full_duration")) + , disconnected_transitions(collector->make_gauge("State_Accounting", "Disconnected_transitions")) + , connected_transitions(collector->make_gauge("State_Accounting", "Connected_transitions")) + , syncing_transitions(collector->make_gauge("State_Accounting", "Syncing_transitions")) + , tracking_transitions(collector->make_gauge("State_Accounting", "Tracking_transitions")) + , full_transitions(collector->make_gauge("State_Accounting", "Full_transitions")) { } @@ -853,22 +779,19 @@ private: //------------------------------------------------------------------------------ -static std::array const stateNames{ - {"disconnected", "connected", "syncing", "tracking", "full"}}; +static std::array const stateNames{{"disconnected", "connected", "syncing", "tracking", "full"}}; std::array const NetworkOPsImp::states_ = stateNames; -std::array const - NetworkOPsImp::StateAccounting::states_ = { - {Json::StaticString(stateNames[0]), - Json::StaticString(stateNames[1]), - Json::StaticString(stateNames[2]), - Json::StaticString(stateNames[3]), - Json::StaticString(stateNames[4])}}; +std::array const NetworkOPsImp::StateAccounting::states_ = { + {Json::StaticString(stateNames[0]), + Json::StaticString(stateNames[1]), + Json::StaticString(stateNames[2]), + Json::StaticString(stateNames[3]), + Json::StaticString(stateNames[4])}}; -static auto const genesisAccountId = calcAccountID( - generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")) - .first); +static auto const genesisAccountId = + calcAccountID(generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase")).first); //------------------------------------------------------------------------------ inline OperatingMode @@ -950,21 +873,17 @@ NetworkOPsImp::setTimer( std::function onError) { // Only start the timer if waitHandlerCounter_ is not yet joined. - if (auto optionalCountedHandler = waitHandlerCounter_.wrap( - [this, onExpire, onError](boost::system::error_code const& e) { - if ((e.value() == boost::system::errc::success) && - (!m_job_queue.isStopped())) + if (auto optionalCountedHandler = + waitHandlerCounter_.wrap([this, onExpire, onError](boost::system::error_code const& e) { + if ((e.value() == boost::system::errc::success) && (!m_job_queue.isStopped())) { onExpire(); } // Recover as best we can if an unexpected error occurs. - if (e.value() != boost::system::errc::success && - e.value() != boost::asio::error::operation_aborted) + if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted) { // Try again later and hope for the best. - JLOG(m_journal.error()) - << "Timer got error '" << e.message() - << "'. Restarting timer."; + JLOG(m_journal.error()) << "Timer got error '" << e.message() << "'. Restarting timer."; onError(); } })) @@ -980,11 +899,7 @@ NetworkOPsImp::setHeartbeatTimer() setTimer( heartbeatTimer_, mConsensus.parms().ledgerGRANULARITY, - [this]() { - m_job_queue.addJob(jtNETOP_TIMER, "NetHeart", [this]() { - processHeartbeatTimer(); - }); - }, + [this]() { m_job_queue.addJob(jtNETOP_TIMER, "NetHeart", [this]() { processHeartbeatTimer(); }); }, [this]() { setHeartbeatTimer(); }); } @@ -996,19 +911,14 @@ NetworkOPsImp::setClusterTimer() setTimer( clusterTimer_, 10s, - [this]() { - m_job_queue.addJob(jtNETOP_CLUSTER, "NetCluster", [this]() { - processClusterTimer(); - }); - }, + [this]() { m_job_queue.addJob(jtNETOP_CLUSTER, "NetCluster", [this]() { processClusterTimer(); }); }, [this]() { setClusterTimer(); }); } void NetworkOPsImp::setAccountHistoryJobTimer(SubAccountHistoryInfoWeak subInfo) { - JLOG(m_journal.debug()) << "Scheduling AccountHistory job for account " - << toBase58(subInfo.index_->accountId_); + JLOG(m_journal.debug()) << "Scheduling AccountHistory job for account " << toBase58(subInfo.index_->accountId_); using namespace std::chrono_literals; setTimer( accountHistoryTxTimer_, @@ -1020,8 +930,7 @@ NetworkOPsImp::setAccountHistoryJobTimer(SubAccountHistoryInfoWeak subInfo) void NetworkOPsImp::processHeartbeatTimer() { - RclConsensusLogger clog( - "Heartbeat Timer", mConsensus.validating(), m_journal); + RclConsensusLogger clog("Heartbeat Timer", mConsensus.validating(), m_journal); { std::unique_lock lock{app_.getMasterMutex()}; @@ -1045,9 +954,8 @@ NetworkOPsImp::processHeartbeatTimer() } else { - CLOG(clog.ss()) - << "already DISCONNECTED. too few peers (" << numPeers - << "), need at least " << minPeerCount_; + CLOG(clog.ss()) << "already DISCONNECTED. too few peers (" << numPeers << "), need at least " + << minPeerCount_; } // MasterMutex lock need not be held to call setHeartbeatTimer() @@ -1062,10 +970,8 @@ NetworkOPsImp::processHeartbeatTimer() if (mMode == OperatingMode::DISCONNECTED) { setMode(OperatingMode::CONNECTED); - JLOG(m_journal.info()) - << "Node count (" << numPeers << ") is sufficient."; - CLOG(clog.ss()) << "setting mode to CONNECTED based on " << numPeers - << " peers. "; + JLOG(m_journal.info()) << "Node count (" << numPeers << ") is sufficient."; + CLOG(clog.ss()) << "setting mode to CONNECTED based on " << numPeers << " peers. "; } // Check if the last validated ledger forces a change between these @@ -1079,8 +985,7 @@ NetworkOPsImp::processHeartbeatTimer() auto newMode = mMode.load(); if (origMode != newMode) { - CLOG(clog.ss()) - << ", changing to " << strOperatingMode(newMode, true); + CLOG(clog.ss()) << ", changing to " << strOperatingMode(newMode, true); } CLOG(clog.ss()) << ". "; } @@ -1111,9 +1016,7 @@ NetworkOPsImp::processClusterTimer() bool const update = app_.cluster().update( app_.nodeIdentity().first, "", - (m_ledgerMaster.getValidatedLedgerAge() <= 4min) - ? app_.getFeeTrack().getLocalFee() - : 0, + (m_ledgerMaster.getValidatedLedgerAge() <= 4min) ? app_.getFeeTrack().getLocalFee() : 0, app_.timeKeeper().now()); if (!update) @@ -1140,17 +1043,14 @@ NetworkOPsImp::processClusterTimer() node.set_name(to_string(item.address)); node.set_cost(item.balance); } - app_.overlay().foreach(send_if( - std::make_shared(cluster, protocol::mtCLUSTER), - peer_in_cluster())); + app_.overlay().foreach(send_if(std::make_shared(cluster, protocol::mtCLUSTER), peer_in_cluster())); setClusterTimer(); } //------------------------------------------------------------------------------ std::string -NetworkOPsImp::strOperatingMode(OperatingMode const mode, bool const admin) - const +NetworkOPsImp::strOperatingMode(OperatingMode const mode, bool const admin) const { if (mode == OperatingMode::FULL && admin) { @@ -1178,11 +1078,9 @@ NetworkOPsImp::submitTransaction(std::shared_ptr const& iTrans) } // Enforce Network bar for batch txn - if (iTrans->isFlag(tfInnerBatchTxn) && - m_ledgerMaster.getValidatedRules().enabled(featureBatch)) + if (iTrans->isFlag(tfInnerBatchTxn) && m_ledgerMaster.getValidatedRules().enabled(featureBatch)) { - JLOG(m_journal.error()) - << "Submitted transaction invalid: tfInnerBatchTxn flag present."; + JLOG(m_journal.error()) << "Submitted transaction invalid: tfInnerBatchTxn flag present."; return; } @@ -1200,23 +1098,18 @@ NetworkOPsImp::submitTransaction(std::shared_ptr const& iTrans) try { - auto const [validity, reason] = checkValidity( - app_.getHashRouter(), - *trans, - m_ledgerMaster.getValidatedRules(), - app_.config()); + auto const [validity, reason] = + checkValidity(app_.getHashRouter(), *trans, m_ledgerMaster.getValidatedRules(), app_.config()); if (validity != Validity::Valid) { - JLOG(m_journal.warn()) - << "Submitted transaction invalid: " << reason; + JLOG(m_journal.warn()) << "Submitted transaction invalid: " << reason; return; } } catch (std::exception const& ex) { - JLOG(m_journal.warn()) - << "Exception checking transaction " << txid << ": " << ex.what(); + JLOG(m_journal.warn()) << "Exception checking transaction " << txid << ": " << ex.what(); return; } @@ -1255,19 +1148,15 @@ NetworkOPsImp::preProcessTransaction(std::shared_ptr& transaction) { transaction->setStatus(INVALID); transaction->setResult(temINVALID_FLAG); - app_.getHashRouter().setFlags( - transaction->getID(), HashRouterFlags::BAD); + app_.getHashRouter().setFlags(transaction->getID(), HashRouterFlags::BAD); return false; } // NOTE ximinez - I think this check is redundant, // but I'm not 100% sure yet. // If so, only cost is looking up HashRouter flags. - auto const [validity, reason] = - checkValidity(app_.getHashRouter(), sttx, view->rules(), app_.config()); - XRPL_ASSERT( - validity == Validity::Valid, - "xrpl::NetworkOPsImp::processTransaction : valid validity"); + auto const [validity, reason] = checkValidity(app_.getHashRouter(), sttx, view->rules(), app_.config()); + XRPL_ASSERT(validity == Validity::Valid, "xrpl::NetworkOPsImp::processTransaction : valid validity"); // Not concerned with local checks at this point. if (validity == Validity::SigBad) @@ -1275,8 +1164,7 @@ NetworkOPsImp::preProcessTransaction(std::shared_ptr& transaction) JLOG(m_journal.info()) << "Transaction has bad signature: " << reason; transaction->setStatus(INVALID); transaction->setResult(temBAD_SIGNATURE); - app_.getHashRouter().setFlags( - transaction->getID(), HashRouterFlags::BAD); + app_.getHashRouter().setFlags(transaction->getID(), HashRouterFlags::BAD); return false; } @@ -1306,24 +1194,19 @@ NetworkOPsImp::processTransaction( } void -NetworkOPsImp::doTransactionAsync( - std::shared_ptr transaction, - bool bUnlimited, - FailHard failType) +NetworkOPsImp::doTransactionAsync(std::shared_ptr transaction, bool bUnlimited, FailHard failType) { std::lock_guard lock(mMutex); if (transaction->getApplying()) return; - mTransactions.push_back( - TransactionStatus(transaction, bUnlimited, false, failType)); + mTransactions.push_back(TransactionStatus(transaction, bUnlimited, false, failType)); transaction->setApplying(); if (mDispatchState == DispatchState::none) { - if (m_job_queue.addJob( - jtBATCH, "TxBatchAsync", [this]() { transactionBatch(); })) + if (m_job_queue.addJob(jtBATCH, "TxBatchAsync", [this]() { transactionBatch(); })) { mDispatchState = DispatchState::scheduled; } @@ -1331,24 +1214,18 @@ NetworkOPsImp::doTransactionAsync( } void -NetworkOPsImp::doTransactionSync( - std::shared_ptr transaction, - bool bUnlimited, - FailHard failType) +NetworkOPsImp::doTransactionSync(std::shared_ptr transaction, bool bUnlimited, FailHard failType) { std::unique_lock lock(mMutex); if (!transaction->getApplying()) { - mTransactions.push_back( - TransactionStatus(transaction, bUnlimited, true, failType)); + mTransactions.push_back(TransactionStatus(transaction, bUnlimited, true, failType)); transaction->setApplying(); } doTransactionSyncBatch( - lock, [&transaction](std::unique_lock const&) { - return transaction->getApplying(); - }); + lock, [&transaction](std::unique_lock const&) { return transaction->getApplying(); }); } void @@ -1370,9 +1247,7 @@ NetworkOPsImp::doTransactionSyncBatch( if (mTransactions.size()) { // More transactions need to be applied, but by another job. - if (m_job_queue.addJob(jtBATCH, "TxBatchSync", [this]() { - transactionBatch(); - })) + if (m_job_queue.addJob(jtBATCH, "TxBatchSync", [this]() { transactionBatch(); })) { mDispatchState = DispatchState::scheduled; } @@ -1396,11 +1271,9 @@ NetworkOPsImp::processTransactionSet(CanonicalTXSet const& set) { if (!reason.empty()) { - JLOG(m_journal.trace()) - << "Exception checking transaction: " << reason; + JLOG(m_journal.trace()) << "Exception checking transaction: " << reason; } - app_.getHashRouter().setFlags( - tx->getTransactionID(), HashRouterFlags::BAD); + app_.getHashRouter().setFlags(tx->getTransactionID(), HashRouterFlags::BAD); continue; } @@ -1440,13 +1313,9 @@ NetworkOPsImp::processTransactionSet(CanonicalTXSet const& set) } doTransactionSyncBatch(lock, [&](std::unique_lock const&) { - XRPL_ASSERT( - lock.owns_lock(), - "xrpl::NetworkOPsImp::processTransactionSet has lock"); + XRPL_ASSERT(lock.owns_lock(), "xrpl::NetworkOPsImp::processTransactionSet has lock"); return std::any_of( - mTransactions.begin(), mTransactions.end(), [](auto const& t) { - return t.transaction->getApplying(); - }); + mTransactions.begin(), mTransactions.end(), [](auto const& t) { return t.transaction->getApplying(); }); }); } @@ -1470,12 +1339,8 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) std::vector submit_held; std::vector transactions; mTransactions.swap(transactions); - XRPL_ASSERT( - !transactions.empty(), - "xrpl::NetworkOPsImp::apply : non-empty transactions"); - XRPL_ASSERT( - mDispatchState != DispatchState::running, - "xrpl::NetworkOPsImp::apply : is not running"); + XRPL_ASSERT(!transactions.empty(), "xrpl::NetworkOPsImp::apply : non-empty transactions"); + XRPL_ASSERT(mDispatchState != DispatchState::running, "xrpl::NetworkOPsImp::apply : is not running"); mDispatchState = DispatchState::running; @@ -1485,8 +1350,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) std::unique_lock masterLock{app_.getMasterMutex(), std::defer_lock}; bool changed = false; { - std::unique_lock ledgerLock{ - m_ledgerMaster.peekMutex(), std::defer_lock}; + std::unique_lock ledgerLock{m_ledgerMaster.peekMutex(), std::defer_lock}; std::lock(masterLock, ledgerLock); app_.openLedger().modify([&](OpenView& view, beast::Journal j) { @@ -1500,8 +1364,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) if (e.failType == FailHard::yes) flags |= tapFAIL_HARD; - auto const result = app_.getTxQ().apply( - app_, view, e.transaction->getSTransaction(), flags, j); + auto const result = app_.getTxQ().apply(app_, view, e.transaction->getSTransaction(), flags, j); e.result = result.ter; e.applied = result.applied; changed = changed || result.applied; @@ -1523,16 +1386,14 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) if (e.applied) { - pubProposedTransaction( - newOL, e.transaction->getSTransaction(), e.result); + pubProposedTransaction(newOL, e.transaction->getSTransaction(), e.result); e.transaction->setApplied(); } e.transaction->setResult(e.result); if (isTemMalformed(e.result)) - app_.getHashRouter().setFlags( - e.transaction->getID(), HashRouterFlags::BAD); + app_.getHashRouter().setFlags(e.transaction->getID(), HashRouterFlags::BAD); #ifdef DEBUG if (e.result != tesSUCCESS) @@ -1541,8 +1402,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) if (transResultInfo(e.result, token, human)) { - JLOG(m_journal.info()) - << "TransactionResult: " << token << ": " << human; + JLOG(m_journal.info()) << "TransactionResult: " << token << ": " << human; } } #endif @@ -1551,8 +1411,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) if (e.result == tesSUCCESS) { - JLOG(m_journal.debug()) - << "Transaction is now included in open ledger"; + JLOG(m_journal.debug()) << "Transaction is now included in open ledger"; e.transaction->setStatus(INCLUDED); // Pop as many "reasonable" transactions for this account as @@ -1561,8 +1420,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) auto const& txCur = e.transaction->getSTransaction(); std::size_t count = 0; - for (auto txNext = m_ledgerMaster.popAcctTransaction(txCur); - txNext && count < maxPoppedTransactions; + for (auto txNext = m_ledgerMaster.popAcctTransaction(txCur); txNext && count < maxPoppedTransactions; txNext = m_ledgerMaster.popAcctTransaction(txCur), ++count) { if (!batchLock.owns_lock()) @@ -1586,9 +1444,8 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) } else if (e.result == terQUEUED) { - JLOG(m_journal.debug()) - << "Transaction is likely to claim a" - << " fee, but is queued until fee drops"; + JLOG(m_journal.debug()) << "Transaction is likely to claim a" + << " fee, but is queued until fee drops"; e.transaction->setStatus(HELD); // Add to held transactions, because it could get @@ -1598,19 +1455,13 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) e.transaction->setQueued(); e.transaction->setKept(); } - else if ( - isTerRetry(e.result) || isTelLocal(e.result) || - isTefFailure(e.result)) + else if (isTerRetry(e.result) || isTelLocal(e.result) || isTefFailure(e.result)) { if (e.failType != FailHard::yes) { - auto const lastLedgerSeq = - e.transaction->getSTransaction()->at( - ~sfLastLedgerSequence); - auto const ledgersLeft = lastLedgerSeq - ? *lastLedgerSeq - - m_ledgerMaster.getCurrentLedgerIndex() - : std::optional{}; + auto const lastLedgerSeq = e.transaction->getSTransaction()->at(~sfLastLedgerSequence); + auto const ledgersLeft = lastLedgerSeq ? *lastLedgerSeq - m_ledgerMaster.getCurrentLedgerIndex() + : std::optional{}; // If any of these conditions are met, the transaction can // be held: // 1. It was submitted locally. (Note that this flag is only @@ -1627,56 +1478,43 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) // the other conditions, so don't hold it again. Time's // up!) // - if (e.local || - (ledgersLeft && ledgersLeft <= LocalTxs::holdLedgers) || - app_.getHashRouter().setFlags( - e.transaction->getID(), HashRouterFlags::HELD)) + if (e.local || (ledgersLeft && ledgersLeft <= LocalTxs::holdLedgers) || + app_.getHashRouter().setFlags(e.transaction->getID(), HashRouterFlags::HELD)) { // transaction should be held - JLOG(m_journal.debug()) - << "Transaction should be held: " << e.result; + JLOG(m_journal.debug()) << "Transaction should be held: " << e.result; e.transaction->setStatus(HELD); m_ledgerMaster.addHeldTransaction(e.transaction); e.transaction->setKept(); } else JLOG(m_journal.debug()) - << "Not holding transaction " - << e.transaction->getID() << ": " + << "Not holding transaction " << e.transaction->getID() << ": " << (e.local ? "local" : "network") << ", " - << "result: " << e.result << " ledgers left: " - << (ledgersLeft ? to_string(*ledgersLeft) - : "unspecified"); + << "result: " << e.result + << " ledgers left: " << (ledgersLeft ? to_string(*ledgersLeft) : "unspecified"); } } else { - JLOG(m_journal.debug()) - << "Status other than success " << e.result; + JLOG(m_journal.debug()) << "Status other than success " << e.result; e.transaction->setStatus(INVALID); } - auto const enforceFailHard = - e.failType == FailHard::yes && !isTesSuccess(e.result); + auto const enforceFailHard = e.failType == FailHard::yes && !isTesSuccess(e.result); if (addLocal && !enforceFailHard) { - m_localTX->push_back( - m_ledgerMaster.getCurrentLedgerIndex(), - e.transaction->getSTransaction()); + m_localTX->push_back(m_ledgerMaster.getCurrentLedgerIndex(), e.transaction->getSTransaction()); e.transaction->setKept(); } - if ((e.applied || - ((mMode != OperatingMode::FULL) && - (e.failType != FailHard::yes) && e.local) || + if ((e.applied || ((mMode != OperatingMode::FULL) && (e.failType != FailHard::yes) && e.local) || (e.result == terQUEUED)) && !enforceFailHard) { - auto const toSkip = - app_.getHashRouter().shouldRelay(e.transaction->getID()); - if (auto const sttx = *(e.transaction->getSTransaction()); - toSkip && + auto const toSkip = app_.getHashRouter().shouldRelay(e.transaction->getID()); + if (auto const sttx = *(e.transaction->getSTransaction()); toSkip && // Skip relaying if it's an inner batch txn. The flag should // only be set if the Batch feature is enabled. If Batch is // not enabled, the flag is always invalid, so don't relay @@ -1689,8 +1527,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) sttx.add(s); tx.set_rawtransaction(s.data(), s.size()); tx.set_status(protocol::tsCURRENT); - tx.set_receivetimestamp( - app_.timeKeeper().now().time_since_epoch().count()); + tx.set_receivetimestamp(app_.timeKeeper().now().time_since_epoch().count()); tx.set_deferred(e.result == terQUEUED); // FIXME: This should be when we received it app_.overlay().relay(e.transaction->getID(), tx, *toSkip); @@ -1701,10 +1538,8 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) if (validatedLedgerIndex) { auto [fee, accountSeq, availableSeq] = - app_.getTxQ().getTxRequiredFeeAndSeq( - *newOL, e.transaction->getSTransaction()); - e.transaction->setCurrentLedgerState( - *validatedLedgerIndex, fee, accountSeq, availableSeq); + app_.getTxQ().getTxRequiredFeeAndSeq(*newOL, e.transaction->getSTransaction()); + e.transaction->setCurrentLedgerState(*validatedLedgerIndex, fee, accountSeq, availableSeq); } } } @@ -1736,9 +1571,7 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) // Json::Value -NetworkOPsImp::getOwnerInfo( - std::shared_ptr lpLedger, - AccountID const& account) +NetworkOPsImp::getOwnerInfo(std::shared_ptr lpLedger, AccountID const& account) { Json::Value jvObjects(Json::objectValue); auto root = keylet::ownerDir(account); @@ -1752,30 +1585,24 @@ NetworkOPsImp::getOwnerInfo( for (auto const& uDirEntry : sleNode->getFieldV256(sfIndexes)) { auto sleCur = lpLedger->read(keylet::child(uDirEntry)); - XRPL_ASSERT( - sleCur, - "xrpl::NetworkOPsImp::getOwnerInfo : non-null child SLE"); + XRPL_ASSERT(sleCur, "xrpl::NetworkOPsImp::getOwnerInfo : non-null child SLE"); switch (sleCur->getType()) { case ltOFFER: if (!jvObjects.isMember(jss::offers)) - jvObjects[jss::offers] = - Json::Value(Json::arrayValue); + jvObjects[jss::offers] = Json::Value(Json::arrayValue); - jvObjects[jss::offers].append( - sleCur->getJson(JsonOptions::none)); + jvObjects[jss::offers].append(sleCur->getJson(JsonOptions::none)); break; case ltRIPPLE_STATE: if (!jvObjects.isMember(jss::ripple_lines)) { - jvObjects[jss::ripple_lines] = - Json::Value(Json::arrayValue); + jvObjects[jss::ripple_lines] = Json::Value(Json::arrayValue); } - jvObjects[jss::ripple_lines].append( - sleCur->getJson(JsonOptions::none)); + jvObjects[jss::ripple_lines].append(sleCur->getJson(JsonOptions::none)); break; case ltACCOUNT_ROOT: @@ -1795,9 +1622,7 @@ NetworkOPsImp::getOwnerInfo( if (uNodeDir) { sleNode = lpLedger->read(keylet::page(root, uNodeDir)); - XRPL_ASSERT( - sleNode, - "xrpl::NetworkOPsImp::getOwnerInfo : read next page"); + XRPL_ASSERT(sleNode, "xrpl::NetworkOPsImp::getOwnerInfo : read next page"); } } while (uNodeDir); } @@ -1866,9 +1691,7 @@ NetworkOPsImp::clearUNLBlocked() } bool -NetworkOPsImp::checkLastClosedLedger( - Overlay::PeerSequence const& peerList, - uint256& networkClosed) +NetworkOPsImp::checkLastClosedLedger(Overlay::PeerSequence const& peerList, uint256& networkClosed) { // Returns true if there's an *abnormal* ledger issue, normal changing in // TRACKING mode should return false. Do we have sufficient validations for @@ -1891,8 +1714,7 @@ NetworkOPsImp::checkLastClosedLedger( // Determine preferred last closed ledger auto& validations = app_.getValidations(); - JLOG(m_journal.debug()) - << "ValidationTrie " << Json::Compact(validations.getJsonTrie()); + JLOG(m_journal.debug()) << "ValidationTrie " << Json::Compact(validations.getJsonTrie()); // Will rely on peer LCL if no trusted validations exist hash_map peerCounts; @@ -1936,13 +1758,11 @@ NetworkOPsImp::checkLastClosedLedger( auto consensus = m_ledgerMaster.getLedgerByHash(closedLedger); if (!consensus) - consensus = app_.getInboundLedgers().acquire( - closedLedger, 0, InboundLedger::Reason::CONSENSUS); + consensus = app_.getInboundLedgers().acquire(closedLedger, 0, InboundLedger::Reason::CONSENSUS); if (consensus && (!m_ledgerMaster.canBeCurrent(consensus) || - !m_ledgerMaster.isCompatible( - *consensus, m_journal.debug(), "Not switching"))) + !m_ledgerMaster.isCompatible(*consensus, m_journal.debug(), "Not switching"))) { // Don't switch to a ledger not on the validated chain // or with an invalid close time or sequence @@ -1951,8 +1771,7 @@ NetworkOPsImp::checkLastClosedLedger( } JLOG(m_journal.warn()) << "We are not running on the consensus ledger"; - JLOG(m_journal.info()) << "Our LCL: " << ourClosed->header().hash - << getJson({*ourClosed, {}}); + JLOG(m_journal.info()) << "Our LCL: " << ourClosed->header().hash << getJson({*ourClosed, {}}); JLOG(m_journal.info()) << "Net LCL " << closedLedger; if ((mMode == OperatingMode::TRACKING) || (mMode == OperatingMode::FULL)) @@ -1972,12 +1791,10 @@ NetworkOPsImp::checkLastClosedLedger( } void -NetworkOPsImp::switchLastClosedLedger( - std::shared_ptr const& newLCL) +NetworkOPsImp::switchLastClosedLedger(std::shared_ptr const& newLCL) { // set the newLCL as our last closed ledger -- this is abnormal code - JLOG(m_journal.error()) - << "JUMP last closed ledger to " << newLCL->header().hash; + JLOG(m_journal.error()) << "JUMP last closed ledger to " << newLCL->header().hash; clearNeedNetworkLedger(); @@ -2017,29 +1834,20 @@ NetworkOPsImp::switchLastClosedLedger( s.set_newevent(protocol::neSWITCHED_LEDGER); s.set_ledgerseq(newLCL->header().seq); s.set_networktime(app_.timeKeeper().now().time_since_epoch().count()); - s.set_ledgerhashprevious( - newLCL->header().parentHash.begin(), - newLCL->header().parentHash.size()); - s.set_ledgerhash( - newLCL->header().hash.begin(), newLCL->header().hash.size()); + s.set_ledgerhashprevious(newLCL->header().parentHash.begin(), newLCL->header().parentHash.size()); + s.set_ledgerhash(newLCL->header().hash.begin(), newLCL->header().hash.size()); - app_.overlay().foreach( - send_always(std::make_shared(s, protocol::mtSTATUS_CHANGE))); + app_.overlay().foreach(send_always(std::make_shared(s, protocol::mtSTATUS_CHANGE))); } bool -NetworkOPsImp::beginConsensus( - uint256 const& networkClosed, - std::unique_ptr const& clog) +NetworkOPsImp::beginConsensus(uint256 const& networkClosed, std::unique_ptr const& clog) { - XRPL_ASSERT( - networkClosed.isNonZero(), - "xrpl::NetworkOPsImp::beginConsensus : nonzero input"); + XRPL_ASSERT(networkClosed.isNonZero(), "xrpl::NetworkOPsImp::beginConsensus : nonzero input"); auto closingInfo = m_ledgerMaster.getCurrentLedger()->header(); - JLOG(m_journal.info()) << "Consensus time for #" << closingInfo.seq - << " with LCL " << closingInfo.parentHash; + JLOG(m_journal.info()) << "Consensus time for #" << closingInfo.seq << " with LCL " << closingInfo.parentHash; auto prevLedger = m_ledgerMaster.getLedgerByHash(closingInfo.parentHash); @@ -2062,8 +1870,7 @@ NetworkOPsImp::beginConsensus( "xrpl::NetworkOPsImp::beginConsensus : prevLedger hash matches " "parent"); XRPL_ASSERT( - closingInfo.parentHash == - m_ledgerMaster.getClosedLedger()->header().hash, + closingInfo.parentHash == m_ledgerMaster.getClosedLedger()->header().hash, "xrpl::NetworkOPsImp::beginConsensus : closedLedger parent matches " "hash"); @@ -2079,17 +1886,11 @@ NetworkOPsImp::beginConsensus( { app_.getValidations().trustChanged(changes.added, changes.removed); // Update the AmendmentTable so it tracks the current validators. - app_.getAmendmentTable().trustChanged( - app_.validators().getQuorumKeys().second); + app_.getAmendmentTable().trustChanged(app_.validators().getQuorumKeys().second); } mConsensus.startRound( - app_.timeKeeper().closeTime(), - networkClosed, - prevLedger, - changes.removed, - changes.added, - clog); + app_.timeKeeper().closeTime(), networkClosed, prevLedger, changes.removed, changes.added, clog); ConsensusPhase const currPhase = mConsensus.phase(); if (mLastConsensusPhase != currPhase) @@ -2117,11 +1918,10 @@ NetworkOPsImp::processTrustedProposal(RCLCxPeerPos peerPos) // // Another, innocuous explanation is unusual message routing and delays, // causing this node to receive its own messages back. - JLOG(m_journal.error()) - << "Received a proposal signed by MY KEY from a peer. This may " - "indicate a misconfiguration where another node has the same " - "validator key, or may be caused by unusual message routing and " - "delays."; + JLOG(m_journal.error()) << "Received a proposal signed by MY KEY from a peer. This may " + "indicate a misconfiguration where another node has the same " + "validator key, or may be caused by unusual message routing and " + "delays."; return false; } @@ -2139,8 +1939,7 @@ NetworkOPsImp::mapComplete(std::shared_ptr const& map, bool fromAcquire) protocol::TMHaveTransactionSet msg; msg.set_hash(map->getHash().as_uint256().begin(), 256 / 8); msg.set_status(protocol::tsHAVE); - app_.overlay().foreach( - send_always(std::make_shared(msg, protocol::mtHAVE_SET))); + app_.overlay().foreach(send_always(std::make_shared(msg, protocol::mtHAVE_SET))); // We acquired it because consensus asked us to if (fromAcquire) @@ -2162,8 +1961,7 @@ NetworkOPsImp::endConsensus(std::unique_ptr const& clog) } uint256 networkClosed; - bool ledgerChange = - checkLastClosedLedger(app_.overlay().getActivePeers(), networkClosed); + bool ledgerChange = checkLastClosedLedger(app_.overlay().getActivePeers(), networkClosed); if (networkClosed.isZero()) { @@ -2177,9 +1975,7 @@ NetworkOPsImp::endConsensus(std::unique_ptr const& clog) // timing to make sure there shouldn't be a newer LCL. We need this // information to do the next three tests. - if (((mMode == OperatingMode::CONNECTED) || - (mMode == OperatingMode::SYNCING)) && - !ledgerChange) + if (((mMode == OperatingMode::CONNECTED) || (mMode == OperatingMode::SYNCING)) && !ledgerChange) { // Count number of peers that agree with us and UNL nodes whose // validations we have for LCL. If the ledger is good enough, go to @@ -2188,17 +1984,13 @@ NetworkOPsImp::endConsensus(std::unique_ptr const& clog) setMode(OperatingMode::TRACKING); } - if (((mMode == OperatingMode::CONNECTED) || - (mMode == OperatingMode::TRACKING)) && - !ledgerChange) + if (((mMode == OperatingMode::CONNECTED) || (mMode == OperatingMode::TRACKING)) && !ledgerChange) { // check if the ledger is good enough to go to FULL // Note: Do not go to FULL if we don't have the previous ledger // check if the ledger is bad enough to go to CONNECTED -- TODO auto current = m_ledgerMaster.getCurrentLedger(); - if (app_.timeKeeper().now() < - (current->header().parentCloseTime + - 2 * current->header().closeTimeResolution)) + if (app_.timeKeeper().now() < (current->header().parentCloseTime + 2 * current->header().closeTimeResolution)) { setMode(OperatingMode::FULL); } @@ -2229,8 +2021,7 @@ NetworkOPsImp::pubManifest(Manifest const& mo) jvObj[jss::type] = "manifestReceived"; jvObj[jss::master_key] = toBase58(TokenType::NodePublic, mo.masterKey); if (mo.signingKey) - jvObj[jss::signing_key] = - toBase58(TokenType::NodePublic, *mo.signingKey); + jvObj[jss::signing_key] = toBase58(TokenType::NodePublic, *mo.signingKey); jvObj[jss::seq] = Json::UInt(mo.sequence); if (auto sig = mo.getSignature()) jvObj[jss::signature] = strHex(*sig); @@ -2239,8 +2030,7 @@ NetworkOPsImp::pubManifest(Manifest const& mo) jvObj[jss::domain] = mo.domain; jvObj[jss::manifest] = strHex(mo.serialized); - for (auto i = mStreamMaps[sManifests].begin(); - i != mStreamMaps[sManifests].end();) + for (auto i = mStreamMaps[sManifests].begin(); i != mStreamMaps[sManifests].end();) { if (auto p = i->second.lock()) { @@ -2267,11 +2057,9 @@ NetworkOPsImp::ServerFeeSummary::ServerFeeSummary( } bool -NetworkOPsImp::ServerFeeSummary::operator!=( - NetworkOPsImp::ServerFeeSummary const& b) const +NetworkOPsImp::ServerFeeSummary::operator!=(NetworkOPsImp::ServerFeeSummary const& b) const { - if (loadFactorServer != b.loadFactorServer || - loadBaseServer != b.loadBaseServer || baseFee != b.baseFee || + if (loadFactorServer != b.loadFactorServer || loadBaseServer != b.loadBaseServer || baseFee != b.baseFee || em.has_value() != b.em.has_value()) return true; @@ -2279,8 +2067,7 @@ NetworkOPsImp::ServerFeeSummary::operator!=( { return ( em->minProcessingFeeLevel != b.em->minProcessingFeeLevel || - em->openLedgerFeeLevel != b.em->openLedgerFeeLevel || - em->referenceFeeLevel != b.em->referenceFeeLevel); + em->openLedgerFeeLevel != b.em->openLedgerFeeLevel || em->referenceFeeLevel != b.em->referenceFeeLevel); } return false; @@ -2323,27 +2110,19 @@ NetworkOPsImp::pubServer() { auto const loadFactor = std::max( safe_cast(f.loadFactorServer), - mulDiv( - f.em->openLedgerFeeLevel, - f.loadBaseServer, - f.em->referenceFeeLevel) - .value_or(xrpl::muldiv_max)); + mulDiv(f.em->openLedgerFeeLevel, f.loadBaseServer, f.em->referenceFeeLevel).value_or(xrpl::muldiv_max)); jvObj[jss::load_factor] = trunc32(loadFactor); - jvObj[jss::load_factor_fee_escalation] = - f.em->openLedgerFeeLevel.jsonClipped(); - jvObj[jss::load_factor_fee_queue] = - f.em->minProcessingFeeLevel.jsonClipped(); - jvObj[jss::load_factor_fee_reference] = - f.em->referenceFeeLevel.jsonClipped(); + jvObj[jss::load_factor_fee_escalation] = f.em->openLedgerFeeLevel.jsonClipped(); + jvObj[jss::load_factor_fee_queue] = f.em->minProcessingFeeLevel.jsonClipped(); + jvObj[jss::load_factor_fee_reference] = f.em->referenceFeeLevel.jsonClipped(); } else jvObj[jss::load_factor] = f.loadFactorServer; mLastFeeSummary = f; - for (auto i = mStreamMaps[sServer].begin(); - i != mStreamMaps[sServer].end();) + for (auto i = mStreamMaps[sServer].begin(); i != mStreamMaps[sServer].end();) { InfoSub::pointer p = i->second.lock(); @@ -2403,8 +2182,7 @@ NetworkOPsImp::pubValidation(std::shared_ptr const& val) auto const signerPublic = val->getSignerPublic(); jvObj[jss::type] = "validationReceived"; - jvObj[jss::validation_public_key] = - toBase58(TokenType::NodePublic, signerPublic); + jvObj[jss::validation_public_key] = toBase58(TokenType::NodePublic, signerPublic); jvObj[jss::ledger_hash] = to_string(val->getLedgerHash()); jvObj[jss::signature] = strHex(val->getSignature()); jvObj[jss::full] = val->isFull(); @@ -2422,8 +2200,7 @@ NetworkOPsImp::pubValidation(std::shared_ptr const& val) if (auto hash = (*val)[~sfValidatedHash]) jvObj[jss::validated_hash] = strHex(*hash); - auto const masterKey = - app_.validatorManifests().getMasterKey(signerPublic); + auto const masterKey = app_.validatorManifests().getMasterKey(signerPublic); if (masterKey != signerPublic) jvObj[jss::master_key] = toBase58(TokenType::NodePublic, masterKey); @@ -2457,16 +2234,13 @@ NetworkOPsImp::pubValidation(std::shared_ptr const& val) // (The ~ operator converts the Proxy to a std::optional, which // simplifies later operations) - if (auto const baseFeeXRP = ~val->at(~sfBaseFeeDrops); - baseFeeXRP && baseFeeXRP->native()) + if (auto const baseFeeXRP = ~val->at(~sfBaseFeeDrops); baseFeeXRP && baseFeeXRP->native()) jvObj[jss::base_fee] = baseFeeXRP->xrp().jsonClipped(); - if (auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops); - reserveBaseXRP && reserveBaseXRP->native()) + if (auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops); reserveBaseXRP && reserveBaseXRP->native()) jvObj[jss::reserve_base] = reserveBaseXRP->xrp().jsonClipped(); - if (auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops); - reserveIncXRP && reserveIncXRP->native()) + if (auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops); reserveIncXRP && reserveIncXRP->native()) jvObj[jss::reserve_inc] = reserveIncXRP->xrp().jsonClipped(); // NOTE Use MultiApiJson to publish two slightly different JSON objects @@ -2478,13 +2252,11 @@ NetworkOPsImp::pubValidation(std::shared_ptr const& val) // Type conversion for older API versions to string if (jvTx.isMember(jss::ledger_index)) { - jvTx[jss::ledger_index] = - std::to_string(jvTx[jss::ledger_index].asUInt()); + jvTx[jss::ledger_index] = std::to_string(jvTx[jss::ledger_index].asUInt()); } }); - for (auto i = mStreamMaps[sValidations].begin(); - i != mStreamMaps[sValidations].end();) + for (auto i = mStreamMaps[sValidations].begin(); i != mStreamMaps[sValidations].end();) { if (auto p = i->second.lock()) { @@ -2512,8 +2284,7 @@ NetworkOPsImp::pubPeerStatus(std::function const& func) jvObj[jss::type] = "peerStatusChange"; - for (auto i = mStreamMaps[sPeerStatus].begin(); - i != mStreamMaps[sPeerStatus].end();) + for (auto i = mStreamMaps[sPeerStatus].begin(); i != mStreamMaps[sPeerStatus].end();) { InfoSub::pointer p = i->second.lock(); @@ -2560,12 +2331,9 @@ NetworkOPsImp::setMode(OperatingMode om) } bool -NetworkOPsImp::recvValidation( - std::shared_ptr const& val, - std::string const& source) +NetworkOPsImp::recvValidation(std::shared_ptr const& val, std::string const& source) { - JLOG(m_journal.trace()) - << "recvValidation " << val->getLedgerHash() << " from " << source; + JLOG(m_journal.trace()) << "recvValidation " << val->getLedgerHash() << " from " << source; std::unique_lock lock(validationsMutex_); BypassAccept bypassAccept = BypassAccept::no; @@ -2580,15 +2348,12 @@ NetworkOPsImp::recvValidation( } catch (std::exception const& e) { - JLOG(m_journal.warn()) - << "Exception thrown for handling new validation " - << val->getLedgerHash() << ": " << e.what(); + JLOG(m_journal.warn()) << "Exception thrown for handling new validation " << val->getLedgerHash() << ": " + << e.what(); } catch (...) { - JLOG(m_journal.warn()) - << "Unknown exception thrown for handling new validation " - << val->getLedgerHash(); + JLOG(m_journal.warn()) << "Unknown exception thrown for handling new validation " << val->getLedgerHash(); } if (bypassAccept == BypassAccept::no) { @@ -2657,8 +2422,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) "One or more unsupported amendments have reached majority. " "Upgrade to the latest version before they are activated " "to avoid being amendment blocked."; - if (auto const expected = - app_.getAmendmentTable().firstUnsupportedExpected()) + if (auto const expected = app_.getAmendmentTable().firstUnsupportedExpected()) { auto& d = w[jss::details] = Json::objectValue; d[jss::expected_date] = expected->time_since_epoch().count(); @@ -2682,14 +2446,12 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) info[jss::server_state] = strOperatingMode(admin); - info[jss::time] = to_string(std::chrono::floor( - std::chrono::system_clock::now())); + info[jss::time] = to_string(std::chrono::floor(std::chrono::system_clock::now())); if (needNetworkLedger_) info[jss::network_ledger] = "waiting"; - info[jss::validation_quorum] = - static_cast(app_.validators().quorum()); + info[jss::validation_quorum] = static_cast(app_.validators().quorum()); if (admin) { @@ -2717,8 +2479,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) if (!human) { if (when) - info[jss::validator_list_expires] = - safe_cast(when->time_since_epoch().count()); + info[jss::validator_list_expires] = safe_cast(when->time_since_epoch().count()); else info[jss::validator_list_expires] = 0; } @@ -2764,16 +2525,13 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) } #endif } - info[jss::io_latency_ms] = - static_cast(app_.getIOLatency().count()); + info[jss::io_latency_ms] = static_cast(app_.getIOLatency().count()); if (admin) { - if (auto const localPubKey = app_.validators().localPublicKey(); - localPubKey && app_.getValidationPublicKey()) + if (auto const localPubKey = app_.validators().localPublicKey(); localPubKey && app_.getValidationPublicKey()) { - info[jss::pubkey_validator] = - toBase58(TokenType::NodePublic, localPubKey.value()); + info[jss::pubkey_validator] = toBase58(TokenType::NodePublic, localPubKey.value()); } else { @@ -2791,8 +2549,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) info[jss::current_activities] = app_.getPerfLog().currentJson(); } - info[jss::pubkey_node] = - toBase58(TokenType::NodePublic, app_.nodeIdentity().first); + info[jss::pubkey_node] = toBase58(TokenType::NodePublic, app_.nodeIdentity().first); info[jss::complete_ledgers] = app_.getLedgerMaster().getCompleteLedgers(); @@ -2811,13 +2568,11 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) if (human) { - lastClose[jss::converge_time_s] = - std::chrono::duration{mConsensus.prevRoundTime()}.count(); + lastClose[jss::converge_time_s] = std::chrono::duration{mConsensus.prevRoundTime()}.count(); } else { - lastClose[jss::converge_time] = - Json::Int(mConsensus.prevRoundTime().count()); + lastClose[jss::converge_time] = Json::Int(mConsensus.prevRoundTime().count()); } info[jss::last_close] = lastClose; @@ -2830,8 +2585,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) if (auto const netid = app_.overlay().networkID()) info[jss::network_id] = static_cast(*netid); - auto const escalationMetrics = - app_.getTxQ().getMetrics(*app_.openLedger().current()); + auto const escalationMetrics = app_.getTxQ().getMetrics(*app_.openLedger().current()); auto const loadFactorServer = app_.getFeeTrack().getLoadFactor(); auto const loadBaseServer = app_.getFeeTrack().getLoadBase(); @@ -2839,14 +2593,10 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) In practice, this just strips the units, but it will continue to work correctly if either base value ever changes. */ auto const loadFactorFeeEscalation = - mulDiv( - escalationMetrics.openLedgerFeeLevel, - loadBaseServer, - escalationMetrics.referenceFeeLevel) + mulDiv(escalationMetrics.openLedgerFeeLevel, loadBaseServer, escalationMetrics.referenceFeeLevel) .value_or(xrpl::muldiv_max); - auto const loadFactor = std::max( - safe_cast(loadFactorServer), loadFactorFeeEscalation); + auto const loadFactor = std::max(safe_cast(loadFactorServer), loadFactorFeeEscalation); if (!human) { @@ -2859,48 +2609,36 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) probably isn't enough extant XRP to drive the factor that high. */ - info[jss::load_factor_fee_escalation] = - escalationMetrics.openLedgerFeeLevel.jsonClipped(); - info[jss::load_factor_fee_queue] = - escalationMetrics.minProcessingFeeLevel.jsonClipped(); - info[jss::load_factor_fee_reference] = - escalationMetrics.referenceFeeLevel.jsonClipped(); + info[jss::load_factor_fee_escalation] = escalationMetrics.openLedgerFeeLevel.jsonClipped(); + info[jss::load_factor_fee_queue] = escalationMetrics.minProcessingFeeLevel.jsonClipped(); + info[jss::load_factor_fee_reference] = escalationMetrics.referenceFeeLevel.jsonClipped(); } else { - info[jss::load_factor] = - static_cast(loadFactor) / loadBaseServer; + info[jss::load_factor] = static_cast(loadFactor) / loadBaseServer; if (loadFactorServer != loadFactor) - info[jss::load_factor_server] = - static_cast(loadFactorServer) / loadBaseServer; + info[jss::load_factor_server] = static_cast(loadFactorServer) / loadBaseServer; if (admin) { std::uint32_t fee = app_.getFeeTrack().getLocalFee(); if (fee != loadBaseServer) - info[jss::load_factor_local] = - static_cast(fee) / loadBaseServer; + info[jss::load_factor_local] = static_cast(fee) / loadBaseServer; fee = app_.getFeeTrack().getRemoteFee(); if (fee != loadBaseServer) - info[jss::load_factor_net] = - static_cast(fee) / loadBaseServer; + info[jss::load_factor_net] = static_cast(fee) / loadBaseServer; fee = app_.getFeeTrack().getClusterFee(); if (fee != loadBaseServer) - info[jss::load_factor_cluster] = - static_cast(fee) / loadBaseServer; + info[jss::load_factor_cluster] = static_cast(fee) / loadBaseServer; } - if (escalationMetrics.openLedgerFeeLevel != - escalationMetrics.referenceFeeLevel && + if (escalationMetrics.openLedgerFeeLevel != escalationMetrics.referenceFeeLevel && (admin || loadFactorFeeEscalation != loadFactor)) info[jss::load_factor_fee_escalation] = - escalationMetrics.openLedgerFeeLevel.decimalFromReference( - escalationMetrics.referenceFeeLevel); - if (escalationMetrics.minProcessingFeeLevel != - escalationMetrics.referenceFeeLevel) + escalationMetrics.openLedgerFeeLevel.decimalFromReference(escalationMetrics.referenceFeeLevel); + if (escalationMetrics.minProcessingFeeLevel != escalationMetrics.referenceFeeLevel) info[jss::load_factor_fee_queue] = - escalationMetrics.minProcessingFeeLevel.decimalFromReference( - escalationMetrics.referenceFeeLevel); + escalationMetrics.minProcessingFeeLevel.decimalFromReference(escalationMetrics.referenceFeeLevel); } bool valid = false; @@ -2923,8 +2661,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) l[jss::base_fee] = baseFee.jsonClipped(); l[jss::reserve_base] = lpClosed->fees().reserve.jsonClipped(); l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped(); - l[jss::close_time] = Json::Value::UInt( - lpClosed->header().closeTime.time_since_epoch().count()); + l[jss::close_time] = Json::Value::UInt(lpClosed->header().closeTime.time_since_epoch().count()); } else { @@ -2932,17 +2669,14 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) l[jss::reserve_base_xrp] = lpClosed->fees().reserve.decimalXRP(); l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP(); - if (auto const closeOffset = app_.timeKeeper().closeOffset(); - std::abs(closeOffset.count()) >= 60) - l[jss::close_time_offset] = - static_cast(closeOffset.count()); + if (auto const closeOffset = app_.timeKeeper().closeOffset(); std::abs(closeOffset.count()) >= 60) + l[jss::close_time_offset] = static_cast(closeOffset.count()); constexpr std::chrono::seconds highAgeThreshold{1000000}; if (m_ledgerMaster.haveValidated()) { auto const age = m_ledgerMaster.getValidatedLedgerAge(); - l[jss::age] = - Json::UInt(age < highAgeThreshold ? age.count() : 0); + l[jss::age] = Json::UInt(age < highAgeThreshold ? age.count() : 0); } else { @@ -2952,8 +2686,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) { using namespace std::chrono_literals; auto age = closeTime - lCloseTime; - l[jss::age] = - Json::UInt(age < highAgeThreshold ? age.count() : 0); + l[jss::age] = Json::UInt(age < highAgeThreshold ? age.count() : 0); } } } @@ -2972,16 +2705,12 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) accounting_.json(info); info[jss::uptime] = UptimeClock::now().time_since_epoch().count(); - info[jss::jq_trans_overflow] = - std::to_string(app_.overlay().getJqTransOverflow()); - info[jss::peer_disconnects] = - std::to_string(app_.overlay().getPeerDisconnect()); - info[jss::peer_disconnects_resources] = - std::to_string(app_.overlay().getPeerDisconnectCharges()); + info[jss::jq_trans_overflow] = std::to_string(app_.overlay().getJqTransOverflow()); + info[jss::peer_disconnects] = std::to_string(app_.overlay().getPeerDisconnect()); + info[jss::peer_disconnects_resources] = std::to_string(app_.overlay().getPeerDisconnectCharges()); // This array must be sorted in increasing order. - static constexpr std::array protocols{ - "http", "https", "peer", "ws", "ws2", "wss", "wss2"}; + static constexpr std::array protocols{"http", "https", "peer", "ws", "ws2", "wss", "wss2"}; static_assert(std::is_sorted(std::begin(protocols), std::end(protocols))); { Json::Value ports{Json::arrayValue}; @@ -2989,8 +2718,8 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) { // Don't publish admin ports for non-admin users if (!admin && - !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() && - port.admin_user.empty() && port.admin_password.empty())) + !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() && port.admin_user.empty() && + port.admin_password.empty())) continue; std::vector proto; std::set_intersection( @@ -3052,8 +2781,7 @@ NetworkOPsImp::pubProposedTransaction( if (transaction->isFlag(tfInnerBatchTxn)) return; - MultiApiJson jvObj = - transJson(transaction, result, false, ledger, std::nullopt); + MultiApiJson jvObj = transJson(transaction, result, false, ledger, std::nullopt); { std::lock_guard sl(mSubLock); @@ -3086,23 +2814,17 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) // Ledgers are published only when they acquire sufficient validations // Holes are filled across connection loss or other catastrophe - std::shared_ptr alpAccepted = - app_.getAcceptedLedgerCache().fetch(lpAccepted->header().hash); + std::shared_ptr alpAccepted = app_.getAcceptedLedgerCache().fetch(lpAccepted->header().hash); if (!alpAccepted) { alpAccepted = std::make_shared(lpAccepted, app_); - app_.getAcceptedLedgerCache().canonicalize_replace_client( - lpAccepted->header().hash, alpAccepted); + app_.getAcceptedLedgerCache().canonicalize_replace_client(lpAccepted->header().hash, alpAccepted); } - XRPL_ASSERT( - alpAccepted->getLedger().get() == lpAccepted.get(), - "xrpl::NetworkOPsImp::pubLedger : accepted input"); + XRPL_ASSERT(alpAccepted->getLedger().get() == lpAccepted.get(), "xrpl::NetworkOPsImp::pubLedger : accepted input"); { - JLOG(m_journal.debug()) - << "Publishing ledger " << lpAccepted->header().seq << " " - << lpAccepted->header().hash; + JLOG(m_journal.debug()) << "Publishing ledger " << lpAccepted->header().seq << " " << lpAccepted->header().hash; std::lock_guard sl(mSubLock); @@ -3113,8 +2835,7 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) jvObj[jss::type] = "ledgerClosed"; jvObj[jss::ledger_index] = lpAccepted->header().seq; jvObj[jss::ledger_hash] = to_string(lpAccepted->header().hash); - jvObj[jss::ledger_time] = Json::Value::UInt( - lpAccepted->header().closeTime.time_since_epoch().count()); + jvObj[jss::ledger_time] = Json::Value::UInt(lpAccepted->header().closeTime.time_since_epoch().count()); jvObj[jss::network_id] = app_.config().NETWORK_ID; @@ -3122,15 +2843,13 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) jvObj[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED; jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped(); jvObj[jss::reserve_base] = lpAccepted->fees().reserve.jsonClipped(); - jvObj[jss::reserve_inc] = - lpAccepted->fees().increment.jsonClipped(); + jvObj[jss::reserve_inc] = lpAccepted->fees().increment.jsonClipped(); jvObj[jss::txn_count] = Json::UInt(alpAccepted->size()); if (mMode >= OperatingMode::SYNCING) { - jvObj[jss::validated_ledgers] = - app_.getLedgerMaster().getCompleteLedgers(); + jvObj[jss::validated_ledgers] = app_.getLedgerMaster().getCompleteLedgers(); } auto it = mStreamMaps[sLedger].begin(); @@ -3178,8 +2897,7 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) auto& subInfo = inner.second; if (subInfo.index_->separationLedgerSeq_ == 0) { - subAccountHistoryStart( - alpAccepted->getLedger(), subInfo); + subAccountHistoryStart(alpAccepted->getLedger(), subInfo); } } } @@ -3191,8 +2909,7 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) for (auto const& accTx : *alpAccepted) { JLOG(m_journal.trace()) << "pubAccepted: " << accTx->getJson(); - pubValidatedTransaction( - lpAccepted, *accTx, accTx == *(--alpAccepted->end())); + pubValidatedTransaction(lpAccepted, *accTx, accTx == *(--alpAccepted->end())); } } @@ -3207,17 +2924,14 @@ NetworkOPsImp::reportFeeChange() // only schedule the job if something has changed if (f != mLastFeeSummary) { - m_job_queue.addJob( - jtCLIENT_FEE_CHANGE, "PubFee", [this]() { pubServer(); }); + m_job_queue.addJob(jtCLIENT_FEE_CHANGE, "PubFee", [this]() { pubServer(); }); } } void NetworkOPsImp::reportConsensusStateChange(ConsensusPhase phase) { - m_job_queue.addJob(jtCLIENT_CONSENSUS, "PubCons", [this, phase]() { - pubConsensus(phase); - }); + m_job_queue.addJob(jtCLIENT_CONSENSUS, "PubCons", [this, phase]() { pubConsensus(phase); }); } inline void @@ -3251,17 +2965,14 @@ NetworkOPsImp::transJson( // NOTE jvObj is not a finished object for either API version. After // it's populated, we need to finish it for a specific API version. This is // done in a loop, near the end of this function. - jvObj[jss::transaction] = - transaction->getJson(JsonOptions::disable_API_prior_V2, false); + jvObj[jss::transaction] = transaction->getJson(JsonOptions::disable_API_prior_V2, false); if (meta) { jvObj[jss::meta] = meta->get().getJson(JsonOptions::none); - RPC::insertDeliveredAmount( - jvObj[jss::meta], *ledger, transaction, meta->get()); + RPC::insertDeliveredAmount(jvObj[jss::meta], *ledger, transaction, meta->get()); RPC::insertNFTSyntheticInJson(jvObj, transaction, meta->get()); - RPC::insertMPTokenIssuanceID( - jvObj[jss::meta], transaction, meta->get()); + RPC::insertMPTokenIssuanceID(jvObj[jss::meta], transaction, meta->get()); } // add CTID where the needed data for it exists @@ -3273,9 +2984,7 @@ NetworkOPsImp::transJson( if (transaction->isFieldPresent(sfNetworkID)) netID = transaction->getFieldU32(sfNetworkID); - if (std::optional ctid = - RPC::encodeCTID(ledger->header().seq, txnSeq, netID); - ctid) + if (std::optional ctid = RPC::encodeCTID(ledger->header().seq, txnSeq, netID); ctid) jvObj[jss::ctid] = *ctid; } if (!ledger->open()) @@ -3284,8 +2993,7 @@ NetworkOPsImp::transJson( if (validated) { jvObj[jss::ledger_index] = ledger->header().seq; - jvObj[jss::transaction][jss::date] = - ledger->header().closeTime.time_since_epoch().count(); + jvObj[jss::transaction][jss::date] = ledger->header().closeTime.time_since_epoch().count(); jvObj[jss::validated] = true; jvObj[jss::close_time_iso] = to_string_iso(ledger->header().closeTime); @@ -3310,12 +3018,7 @@ NetworkOPsImp::transJson( // If the offer create is not self funded then add the owner balance if (account != amount.issue().account) { - auto const ownerFunds = accountFunds( - *ledger, - account, - amount, - fhIGNORE_FREEZE, - app_.journal("View")); + auto const ownerFunds = accountFunds(*ledger, account, amount, fhIGNORE_FREEZE, app_.journal("View")); jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText(); } } @@ -3324,10 +3027,8 @@ NetworkOPsImp::transJson( MultiApiJson multiObj{jvObj}; forAllApiVersions( multiObj.visit(), // - [&]( - Json::Value& jvTx, std::integral_constant) { - RPC::insertDeliverMax( - jvTx[jss::transaction], transaction->getTxnType(), Version); + [&](Json::Value& jvTx, std::integral_constant) { + RPC::insertDeliverMax(jvTx[jss::transaction], transaction->getTxnType(), Version); if constexpr (Version > 1) { @@ -3414,13 +3115,11 @@ NetworkOPsImp::pubAccountTransaction( { std::lock_guard sl(mSubLock); - if (!mSubAccount.empty() || !mSubRTAccount.empty() || - !mSubAccountHistory.empty()) + if (!mSubAccount.empty() || !mSubRTAccount.empty() || !mSubAccountHistory.empty()) { for (auto const& affectedAccount : transaction.getAffected()) { - if (auto simiIt = mSubRTAccount.find(affectedAccount); - simiIt != mSubRTAccount.end()) + if (auto simiIt = mSubRTAccount.find(affectedAccount); simiIt != mSubRTAccount.end()) { auto it = simiIt->second.begin(); @@ -3439,8 +3138,7 @@ NetworkOPsImp::pubAccountTransaction( } } - if (auto simiIt = mSubAccount.find(affectedAccount); - simiIt != mSubAccount.end()) + if (auto simiIt = mSubAccount.find(affectedAccount); simiIt != mSubAccount.end()) { auto it = simiIt->second.begin(); while (it != simiIt->second.end()) @@ -3458,8 +3156,7 @@ NetworkOPsImp::pubAccountTransaction( } } - if (auto historyIt = mSubAccountHistory.find(affectedAccount); - historyIt != mSubAccountHistory.end()) + if (auto historyIt = mSubAccountHistory.find(affectedAccount); historyIt != mSubAccountHistory.end()) { auto& subs = historyIt->second; auto it = subs.begin(); @@ -3474,8 +3171,7 @@ NetworkOPsImp::pubAccountTransaction( if (auto isSptr = info.sinkWptr_.lock(); isSptr) { - accountHistoryNotify.emplace_back( - SubAccountHistoryInfo{isSptr, info.index_}); + accountHistoryNotify.emplace_back(SubAccountHistoryInfo{isSptr, info.index_}); ++it; } else @@ -3490,9 +3186,8 @@ NetworkOPsImp::pubAccountTransaction( } } - JLOG(m_journal.trace()) - << "pubAccountTransaction: " - << "proposed=" << iProposed << ", accepted=" << iAccepted; + JLOG(m_journal.trace()) << "pubAccountTransaction: " + << "proposed=" << iProposed << ", accepted=" << iAccepted; if (!notify.empty() || !accountHistoryNotify.empty()) { @@ -3514,8 +3209,7 @@ NetworkOPsImp::pubAccountTransaction( jvObj.set(jss::account_history_boundary, true); XRPL_ASSERT( - jvObj.isMember(jss::account_history_tx_stream) == - MultiApiJson::none, + jvObj.isMember(jss::account_history_tx_stream) == MultiApiJson::none, "xrpl::NetworkOPsImp::pubAccountTransaction : " "account_history_tx_stream not set"); for (auto& info : accountHistoryNotify) @@ -3550,13 +3244,11 @@ NetworkOPsImp::pubProposedAccountTransaction( if (mSubRTAccount.empty()) return; - if (!mSubAccount.empty() || !mSubRTAccount.empty() || - !mSubAccountHistory.empty()) + if (!mSubAccount.empty() || !mSubRTAccount.empty() || !mSubAccountHistory.empty()) { for (auto const& affectedAccount : tx->getMentionedAccounts()) { - if (auto simiIt = mSubRTAccount.find(affectedAccount); - simiIt != mSubRTAccount.end()) + if (auto simiIt = mSubRTAccount.find(affectedAccount); simiIt != mSubRTAccount.end()) { auto it = simiIt->second.begin(); @@ -3591,8 +3283,7 @@ NetworkOPsImp::pubProposedAccountTransaction( [&](Json::Value const& jv) { isrListener->send(jv, true); }); XRPL_ASSERT( - jvObj.isMember(jss::account_history_tx_stream) == - MultiApiJson::none, + jvObj.isMember(jss::account_history_tx_stream) == MultiApiJson::none, "xrpl::NetworkOPs::pubProposedAccountTransaction : " "account_history_tx_stream not set"); for (auto& info : accountHistoryNotify) @@ -3613,17 +3304,13 @@ NetworkOPsImp::pubProposedAccountTransaction( // void -NetworkOPsImp::subAccount( - InfoSub::ref isrListener, - hash_set const& vnaAccountIDs, - bool rt) +NetworkOPsImp::subAccount(InfoSub::ref isrListener, hash_set const& vnaAccountIDs, bool rt) { SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount; for (auto const& naAccountID : vnaAccountIDs) { - JLOG(m_journal.trace()) - << "subAccount: account: " << toBase58(naAccountID); + JLOG(m_journal.trace()) << "subAccount: account: " << toBase58(naAccountID); isrListener->insertSubAccountInfo(naAccountID, rt); } @@ -3650,10 +3337,7 @@ NetworkOPsImp::subAccount( } void -NetworkOPsImp::unsubAccount( - InfoSub::ref isrListener, - hash_set const& vnaAccountIDs, - bool rt) +NetworkOPsImp::unsubAccount(InfoSub::ref isrListener, hash_set const& vnaAccountIDs, bool rt) { for (auto const& naAccountID : vnaAccountIDs) { @@ -3666,10 +3350,7 @@ NetworkOPsImp::unsubAccount( } void -NetworkOPsImp::unsubAccountInternal( - std::uint64_t uSeq, - hash_set const& vnaAccountIDs, - bool rt) +NetworkOPsImp::unsubAccountInternal(std::uint64_t uSeq, hash_set const& vnaAccountIDs, bool rt) { std::lock_guard sl(mSubLock); @@ -3711,9 +3392,8 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) { // LCOV_EXCL_START UNREACHABLE("xrpl::NetworkOPsImp::addAccountHistoryJob : no database"); - JLOG(m_journal.error()) - << "AccountHistory job for account " - << toBase58(subInfo.index_->accountId_) << " no database"; + JLOG(m_journal.error()) << "AccountHistory job for account " << toBase58(subInfo.index_->accountId_) + << " no database"; if (auto sptr = subInfo.sinkWptr_.lock(); sptr) { sptr->send(rpcError(rpcINTERNAL), true); @@ -3723,299 +3403,252 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) // LCOV_EXCL_STOP } - app_.getJobQueue().addJob( - jtCLIENT_ACCT_HIST, - "HistTxStream", - [this, dbType = databaseType, subInfo]() { - auto const& accountId = subInfo.index_->accountId_; - auto& lastLedgerSeq = subInfo.index_->historyLastLedgerSeq_; - auto& txHistoryIndex = subInfo.index_->historyTxIndex_; + app_.getJobQueue().addJob(jtCLIENT_ACCT_HIST, "HistTxStream", [this, dbType = databaseType, subInfo]() { + auto const& accountId = subInfo.index_->accountId_; + auto& lastLedgerSeq = subInfo.index_->historyLastLedgerSeq_; + auto& txHistoryIndex = subInfo.index_->historyTxIndex_; - JLOG(m_journal.trace()) - << "AccountHistory job for account " << toBase58(accountId) - << " started. lastLedgerSeq=" << lastLedgerSeq; + JLOG(m_journal.trace()) << "AccountHistory job for account " << toBase58(accountId) + << " started. lastLedgerSeq=" << lastLedgerSeq; - auto isFirstTx = [&](std::shared_ptr const& tx, - std::shared_ptr const& meta) -> bool { - /* - * genesis account: first tx is the one with seq 1 - * other account: first tx is the one created the account - */ - if (accountId == genesisAccountId) + auto isFirstTx = [&](std::shared_ptr const& tx, std::shared_ptr const& meta) -> bool { + /* + * genesis account: first tx is the one with seq 1 + * other account: first tx is the one created the account + */ + if (accountId == genesisAccountId) + { + auto stx = tx->getSTransaction(); + if (stx->getAccountID(sfAccount) == accountId && stx->getSeqValue() == 1) + return true; + } + + for (auto& node : meta->getNodes()) + { + if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT) + continue; + + if (node.isFieldPresent(sfNewFields)) { - auto stx = tx->getSTransaction(); - if (stx->getAccountID(sfAccount) == accountId && - stx->getSeqValue() == 1) - return true; - } - - for (auto& node : meta->getNodes()) - { - if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT) - continue; - - if (node.isFieldPresent(sfNewFields)) + if (auto inner = dynamic_cast(node.peekAtPField(sfNewFields)); inner) { - if (auto inner = dynamic_cast( - node.peekAtPField(sfNewFields)); - inner) + if (inner->isFieldPresent(sfAccount) && inner->getAccountID(sfAccount) == accountId) { - if (inner->isFieldPresent(sfAccount) && - inner->getAccountID(sfAccount) == accountId) - { - return true; - } + return true; } } } + } - return false; - }; + return false; + }; - auto send = [&](Json::Value const& jvObj, - bool unsubscribe) -> bool { - if (auto sptr = subInfo.sinkWptr_.lock()) - { - sptr->send(jvObj, true); - if (unsubscribe) - unsubAccountHistory(sptr, accountId, false); - return true; - } - - return false; - }; - - auto sendMultiApiJson = [&](MultiApiJson const& jvObj, - bool unsubscribe) -> bool { - if (auto sptr = subInfo.sinkWptr_.lock()) - { - jvObj.visit( - sptr->getApiVersion(), // - [&](Json::Value const& jv) { sptr->send(jv, true); }); - - if (unsubscribe) - unsubAccountHistory(sptr, accountId, false); - return true; - } - - return false; - }; - - auto getMoreTxns = - [&](std::uint32_t minLedger, - std::uint32_t maxLedger, - std::optional marker) - -> std::optional>> { - switch (dbType) - { - case Sqlite: { - auto db = static_cast( - &app_.getRelationalDatabase()); - RelationalDatabase::AccountTxPageOptions options{ - accountId, minLedger, maxLedger, marker, 0, true}; - return db->newestAccountTxPage(options); - } - // LCOV_EXCL_START - default: { - UNREACHABLE( - "xrpl::NetworkOPsImp::addAccountHistoryJob : " - "getMoreTxns : invalid database type"); - return {}; - } - // LCOV_EXCL_STOP - } - }; - - /* - * search backward until the genesis ledger or asked to stop - */ - while (lastLedgerSeq >= 2 && !subInfo.index_->stopHistorical_) + auto send = [&](Json::Value const& jvObj, bool unsubscribe) -> bool { + if (auto sptr = subInfo.sinkWptr_.lock()) { - int feeChargeCount = 0; - if (auto sptr = subInfo.sinkWptr_.lock(); sptr) - { - sptr->getConsumer().charge(Resource::feeMediumBurdenRPC); - ++feeChargeCount; + sptr->send(jvObj, true); + if (unsubscribe) + unsubAccountHistory(sptr, accountId, false); + return true; + } + + return false; + }; + + auto sendMultiApiJson = [&](MultiApiJson const& jvObj, bool unsubscribe) -> bool { + if (auto sptr = subInfo.sinkWptr_.lock()) + { + jvObj.visit( + sptr->getApiVersion(), // + [&](Json::Value const& jv) { sptr->send(jv, true); }); + + if (unsubscribe) + unsubAccountHistory(sptr, accountId, false); + return true; + } + + return false; + }; + + auto getMoreTxns = [&](std::uint32_t minLedger, + std::uint32_t maxLedger, + std::optional marker) + -> std::optional< + std::pair>> { + switch (dbType) + { + case Sqlite: { + auto db = static_cast(&app_.getRelationalDatabase()); + RelationalDatabase::AccountTxPageOptions options{accountId, minLedger, maxLedger, marker, 0, true}; + return db->newestAccountTxPage(options); } - else - { - JLOG(m_journal.trace()) - << "AccountHistory job for account " - << toBase58(accountId) << " no InfoSub. Fee charged " - << feeChargeCount << " times."; - return; + // LCOV_EXCL_START + default: { + UNREACHABLE( + "xrpl::NetworkOPsImp::addAccountHistoryJob : " + "getMoreTxns : invalid database type"); + return {}; } + // LCOV_EXCL_STOP + } + }; - // try to search in 1024 ledgers till reaching genesis ledgers - auto startLedgerSeq = - (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2); - JLOG(m_journal.trace()) - << "AccountHistory job for account " << toBase58(accountId) - << ", working on ledger range [" << startLedgerSeq << "," - << lastLedgerSeq << "]"; + /* + * search backward until the genesis ledger or asked to stop + */ + while (lastLedgerSeq >= 2 && !subInfo.index_->stopHistorical_) + { + int feeChargeCount = 0; + if (auto sptr = subInfo.sinkWptr_.lock(); sptr) + { + sptr->getConsumer().charge(Resource::feeMediumBurdenRPC); + ++feeChargeCount; + } + else + { + JLOG(m_journal.trace()) << "AccountHistory job for account " << toBase58(accountId) + << " no InfoSub. Fee charged " << feeChargeCount << " times."; + return; + } - auto haveRange = [&]() -> bool { - std::uint32_t validatedMin = UINT_MAX; - std::uint32_t validatedMax = 0; - auto haveSomeValidatedLedgers = - app_.getLedgerMaster().getValidatedRange( - validatedMin, validatedMax); + // try to search in 1024 ledgers till reaching genesis ledgers + auto startLedgerSeq = (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2); + JLOG(m_journal.trace()) << "AccountHistory job for account " << toBase58(accountId) + << ", working on ledger range [" << startLedgerSeq << "," << lastLedgerSeq << "]"; - return haveSomeValidatedLedgers && - validatedMin <= startLedgerSeq && - lastLedgerSeq <= validatedMax; - }(); + auto haveRange = [&]() -> bool { + std::uint32_t validatedMin = UINT_MAX; + std::uint32_t validatedMax = 0; + auto haveSomeValidatedLedgers = app_.getLedgerMaster().getValidatedRange(validatedMin, validatedMax); - if (!haveRange) + return haveSomeValidatedLedgers && validatedMin <= startLedgerSeq && lastLedgerSeq <= validatedMax; + }(); + + if (!haveRange) + { + JLOG(m_journal.debug()) << "AccountHistory reschedule job for account " << toBase58(accountId) + << ", incomplete ledger range [" << startLedgerSeq << "," << lastLedgerSeq + << "]"; + setAccountHistoryJobTimer(subInfo); + return; + } + + std::optional marker{}; + while (!subInfo.index_->stopHistorical_) + { + auto dbResult = getMoreTxns(startLedgerSeq, lastLedgerSeq, marker); + if (!dbResult) { + // LCOV_EXCL_START + UNREACHABLE( + "xrpl::NetworkOPsImp::addAccountHistoryJob : " + "getMoreTxns failed"); JLOG(m_journal.debug()) - << "AccountHistory reschedule job for account " - << toBase58(accountId) << ", incomplete ledger range [" - << startLedgerSeq << "," << lastLedgerSeq << "]"; - setAccountHistoryJobTimer(subInfo); + << "AccountHistory job for account " << toBase58(accountId) << " getMoreTxns failed."; + send(rpcError(rpcINTERNAL), true); return; + // LCOV_EXCL_STOP } - std::optional marker{}; - while (!subInfo.index_->stopHistorical_) + auto const& txns = dbResult->first; + marker = dbResult->second; + size_t num_txns = txns.size(); + for (size_t i = 0; i < num_txns; ++i) { - auto dbResult = - getMoreTxns(startLedgerSeq, lastLedgerSeq, marker); - if (!dbResult) + auto const& [tx, meta] = txns[i]; + + if (!tx || !meta) + { + JLOG(m_journal.debug()) + << "AccountHistory job for account " << toBase58(accountId) << " empty tx or meta."; + send(rpcError(rpcINTERNAL), true); + return; + } + auto curTxLedger = app_.getLedgerMaster().getLedgerBySeq(tx->getLedger()); + if (!curTxLedger) { // LCOV_EXCL_START UNREACHABLE( "xrpl::NetworkOPsImp::addAccountHistoryJob : " - "getMoreTxns failed"); + "getLedgerBySeq failed"); JLOG(m_journal.debug()) - << "AccountHistory job for account " - << toBase58(accountId) << " getMoreTxns failed."; + << "AccountHistory job for account " << toBase58(accountId) << " no ledger."; + send(rpcError(rpcINTERNAL), true); + return; + // LCOV_EXCL_STOP + } + std::shared_ptr stTxn = tx->getSTransaction(); + if (!stTxn) + { + // LCOV_EXCL_START + UNREACHABLE( + "NetworkOPsImp::addAccountHistoryJob : " + "getSTransaction failed"); + JLOG(m_journal.debug()) + << "AccountHistory job for account " << toBase58(accountId) << " getSTransaction failed."; send(rpcError(rpcINTERNAL), true); return; // LCOV_EXCL_STOP } - auto const& txns = dbResult->first; - marker = dbResult->second; - size_t num_txns = txns.size(); - for (size_t i = 0; i < num_txns; ++i) + auto const mRef = std::ref(*meta); + auto const trR = meta->getResultTER(); + MultiApiJson jvTx = transJson(stTxn, trR, true, curTxLedger, mRef); + + jvTx.set(jss::account_history_tx_index, txHistoryIndex--); + if (i + 1 == num_txns || txns[i + 1].first->getLedger() != tx->getLedger()) + jvTx.set(jss::account_history_boundary, true); + + if (isFirstTx(tx, meta)) { - auto const& [tx, meta] = txns[i]; + jvTx.set(jss::account_history_tx_first, true); + sendMultiApiJson(jvTx, false); - if (!tx || !meta) - { - JLOG(m_journal.debug()) - << "AccountHistory job for account " - << toBase58(accountId) << " empty tx or meta."; - send(rpcError(rpcINTERNAL), true); - return; - } - auto curTxLedger = - app_.getLedgerMaster().getLedgerBySeq( - tx->getLedger()); - if (!curTxLedger) - { - // LCOV_EXCL_START - UNREACHABLE( - "xrpl::NetworkOPsImp::addAccountHistoryJob : " - "getLedgerBySeq failed"); - JLOG(m_journal.debug()) - << "AccountHistory job for account " - << toBase58(accountId) << " no ledger."; - send(rpcError(rpcINTERNAL), true); - return; - // LCOV_EXCL_STOP - } - std::shared_ptr stTxn = - tx->getSTransaction(); - if (!stTxn) - { - // LCOV_EXCL_START - UNREACHABLE( - "NetworkOPsImp::addAccountHistoryJob : " - "getSTransaction failed"); - JLOG(m_journal.debug()) - << "AccountHistory job for account " - << toBase58(accountId) - << " getSTransaction failed."; - send(rpcError(rpcINTERNAL), true); - return; - // LCOV_EXCL_STOP - } - - auto const mRef = std::ref(*meta); - auto const trR = meta->getResultTER(); - MultiApiJson jvTx = - transJson(stTxn, trR, true, curTxLedger, mRef); - - jvTx.set( - jss::account_history_tx_index, txHistoryIndex--); - if (i + 1 == num_txns || - txns[i + 1].first->getLedger() != tx->getLedger()) - jvTx.set(jss::account_history_boundary, true); - - if (isFirstTx(tx, meta)) - { - jvTx.set(jss::account_history_tx_first, true); - sendMultiApiJson(jvTx, false); - - JLOG(m_journal.trace()) - << "AccountHistory job for account " - << toBase58(accountId) - << " done, found last tx."; - return; - } - else - { - sendMultiApiJson(jvTx, false); - } - } - - if (marker) - { JLOG(m_journal.trace()) - << "AccountHistory job for account " - << toBase58(accountId) - << " paging, marker=" << marker->ledgerSeq << ":" - << marker->txnSeq; + << "AccountHistory job for account " << toBase58(accountId) << " done, found last tx."; + return; } else { - break; + sendMultiApiJson(jvTx, false); } } - if (!subInfo.index_->stopHistorical_) + if (marker) { - lastLedgerSeq = startLedgerSeq - 1; - if (lastLedgerSeq <= 1) - { - JLOG(m_journal.trace()) - << "AccountHistory job for account " - << toBase58(accountId) - << " done, reached genesis ledger."; - return; - } + JLOG(m_journal.trace()) << "AccountHistory job for account " << toBase58(accountId) + << " paging, marker=" << marker->ledgerSeq << ":" << marker->txnSeq; + } + else + { + break; } } - }); + + if (!subInfo.index_->stopHistorical_) + { + lastLedgerSeq = startLedgerSeq - 1; + if (lastLedgerSeq <= 1) + { + JLOG(m_journal.trace()) + << "AccountHistory job for account " << toBase58(accountId) << " done, reached genesis ledger."; + return; + } + } + } + }); } void -NetworkOPsImp::subAccountHistoryStart( - std::shared_ptr const& ledger, - SubAccountHistoryInfoWeak& subInfo) +NetworkOPsImp::subAccountHistoryStart(std::shared_ptr const& ledger, SubAccountHistoryInfoWeak& subInfo) { subInfo.index_->separationLedgerSeq_ = ledger->seq(); auto const& accountId = subInfo.index_->accountId_; auto const accountKeylet = keylet::account(accountId); if (!ledger->exists(accountKeylet)) { - JLOG(m_journal.debug()) - << "subAccountHistoryStart, no account " << toBase58(accountId) - << ", no need to add AccountHistory job."; + JLOG(m_journal.debug()) << "subAccountHistoryStart, no account " << toBase58(accountId) + << ", no need to add AccountHistory job."; return; } if (accountId == genesisAccountId) @@ -4024,10 +3657,8 @@ NetworkOPsImp::subAccountHistoryStart( { if (sleAcct->getFieldU32(sfSequence) == 1) { - JLOG(m_journal.debug()) - << "subAccountHistoryStart, genesis account " - << toBase58(accountId) - << " does not have tx, no need to add AccountHistory job."; + JLOG(m_journal.debug()) << "subAccountHistoryStart, genesis account " << toBase58(accountId) + << " does not have tx, no need to add AccountHistory job."; return; } } @@ -4044,36 +3675,29 @@ NetworkOPsImp::subAccountHistoryStart( subInfo.index_->historyLastLedgerSeq_ = ledger->seq(); subInfo.index_->haveHistorical_ = true; - JLOG(m_journal.debug()) - << "subAccountHistoryStart, add AccountHistory job: accountId=" - << toBase58(accountId) << ", currentLedgerSeq=" << ledger->seq(); + JLOG(m_journal.debug()) << "subAccountHistoryStart, add AccountHistory job: accountId=" << toBase58(accountId) + << ", currentLedgerSeq=" << ledger->seq(); addAccountHistoryJob(subInfo); } error_code_i -NetworkOPsImp::subAccountHistory( - InfoSub::ref isrListener, - AccountID const& accountId) +NetworkOPsImp::subAccountHistory(InfoSub::ref isrListener, AccountID const& accountId) { if (!isrListener->insertSubAccountHistory(accountId)) { - JLOG(m_journal.debug()) - << "subAccountHistory, already subscribed to account " - << toBase58(accountId); + JLOG(m_journal.debug()) << "subAccountHistory, already subscribed to account " << toBase58(accountId); return rpcINVALID_PARAMS; } std::lock_guard sl(mSubLock); - SubAccountHistoryInfoWeak ahi{ - isrListener, std::make_shared(accountId)}; + SubAccountHistoryInfoWeak ahi{isrListener, std::make_shared(accountId)}; auto simIterator = mSubAccountHistory.find(accountId); if (simIterator == mSubAccountHistory.end()) { hash_map inner; inner.emplace(isrListener->getSeq(), ahi); - mSubAccountHistory.insert( - simIterator, std::make_pair(accountId, inner)); + mSubAccountHistory.insert(simIterator, std::make_pair(accountId, inner)); } else { @@ -4090,18 +3714,14 @@ NetworkOPsImp::subAccountHistory( // The node does not have validated ledgers, so wait for // one before start streaming. // In this case, the subscription is also considered successful. - JLOG(m_journal.debug()) - << "subAccountHistory, no validated ledger yet, delay start"; + JLOG(m_journal.debug()) << "subAccountHistory, no validated ledger yet, delay start"; } return rpcSUCCESS; } void -NetworkOPsImp::unsubAccountHistory( - InfoSub::ref isrListener, - AccountID const& account, - bool historyOnly) +NetworkOPsImp::unsubAccountHistory(InfoSub::ref isrListener, AccountID const& account, bool historyOnly) { if (!historyOnly) isrListener->deleteSubAccountHistory(account); @@ -4109,10 +3729,7 @@ NetworkOPsImp::unsubAccountHistory( } void -NetworkOPsImp::unsubAccountHistoryInternal( - std::uint64_t seq, - AccountID const& account, - bool historyOnly) +NetworkOPsImp::unsubAccountHistoryInternal(std::uint64_t seq, AccountID const& account, bool historyOnly) { std::lock_guard sl(mSubLock); auto simIterator = mSubAccountHistory.find(account); @@ -4133,9 +3750,8 @@ NetworkOPsImp::unsubAccountHistoryInternal( mSubAccountHistory.erase(simIterator); } } - JLOG(m_journal.debug()) - << "unsubAccountHistory, account " << toBase58(account) - << ", historyOnly = " << (historyOnly ? "true" : "false"); + JLOG(m_journal.debug()) << "unsubAccountHistory, account " << toBase58(account) + << ", historyOnly = " << (historyOnly ? "true" : "false"); } } @@ -4163,17 +3779,14 @@ NetworkOPsImp::unsubBook(std::uint64_t uSeq, Book const& book) } std::uint32_t -NetworkOPsImp::acceptLedger( - std::optional consensusDelay) +NetworkOPsImp::acceptLedger(std::optional consensusDelay) { // This code-path is exclusively used when the server is in standalone // mode via `ledger_accept` - XRPL_ASSERT( - m_standalone, "xrpl::NetworkOPsImp::acceptLedger : is standalone"); + XRPL_ASSERT(m_standalone, "xrpl::NetworkOPsImp::acceptLedger : is standalone"); if (!m_standalone) - Throw( - "Operation only possible in STANDALONE mode."); + Throw("Operation only possible in STANDALONE mode."); // FIXME Could we improve on this and remove the need for a specialized // API in Consensus? @@ -4190,8 +3803,7 @@ NetworkOPsImp::subLedger(InfoSub::ref isrListener, Json::Value& jvResult) { jvResult[jss::ledger_index] = lpClosed->header().seq; jvResult[jss::ledger_hash] = to_string(lpClosed->header().hash); - jvResult[jss::ledger_time] = Json::Value::UInt( - lpClosed->header().closeTime.time_since_epoch().count()); + jvResult[jss::ledger_time] = Json::Value::UInt(lpClosed->header().closeTime.time_since_epoch().count()); if (!lpClosed->rules().enabled(featureXRPFees)) jvResult[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED; jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped(); @@ -4202,14 +3814,11 @@ NetworkOPsImp::subLedger(InfoSub::ref isrListener, Json::Value& jvResult) if ((mMode >= OperatingMode::SYNCING) && !isNeedNetworkLedger()) { - jvResult[jss::validated_ledgers] = - app_.getLedgerMaster().getCompleteLedgers(); + jvResult[jss::validated_ledgers] = app_.getLedgerMaster().getCompleteLedgers(); } std::lock_guard sl(mSubLock); - return mStreamMaps[sLedger] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sLedger].emplace(isrListener->getSeq(), isrListener).second; } // <-- bool: true=added, false=already there @@ -4217,9 +3826,7 @@ bool NetworkOPsImp::subBookChanges(InfoSub::ref isrListener) { std::lock_guard sl(mSubLock); - return mStreamMaps[sBookChanges] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sBookChanges].emplace(isrListener->getSeq(), isrListener).second; } // <-- bool: true=erased, false=was not there @@ -4243,9 +3850,7 @@ bool NetworkOPsImp::subManifests(InfoSub::ref isrListener) { std::lock_guard sl(mSubLock); - return mStreamMaps[sManifests] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sManifests].emplace(isrListener->getSeq(), isrListener).second; } // <-- bool: true=erased, false=was not there @@ -4258,10 +3863,7 @@ NetworkOPsImp::unsubManifests(std::uint64_t uSeq) // <-- bool: true=added, false=already there bool -NetworkOPsImp::subServer( - InfoSub::ref isrListener, - Json::Value& jvResult, - bool admin) +NetworkOPsImp::subServer(InfoSub::ref isrListener, Json::Value& jvResult, bool admin) { uint256 uRandom; @@ -4277,13 +3879,10 @@ NetworkOPsImp::subServer( jvResult[jss::load_base] = feeTrack.getLoadBase(); jvResult[jss::load_factor] = feeTrack.getLoadFactor(); jvResult[jss::hostid] = getHostId(admin); - jvResult[jss::pubkey_node] = - toBase58(TokenType::NodePublic, app_.nodeIdentity().first); + jvResult[jss::pubkey_node] = toBase58(TokenType::NodePublic, app_.nodeIdentity().first); std::lock_guard sl(mSubLock); - return mStreamMaps[sServer] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sServer].emplace(isrListener->getSeq(), isrListener).second; } // <-- bool: true=erased, false=was not there @@ -4299,9 +3898,7 @@ bool NetworkOPsImp::subTransactions(InfoSub::ref isrListener) { std::lock_guard sl(mSubLock); - return mStreamMaps[sTransactions] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sTransactions].emplace(isrListener->getSeq(), isrListener).second; } // <-- bool: true=erased, false=was not there @@ -4317,9 +3914,7 @@ bool NetworkOPsImp::subRTTransactions(InfoSub::ref isrListener) { std::lock_guard sl(mSubLock); - return mStreamMaps[sRTTransactions] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sRTTransactions].emplace(isrListener->getSeq(), isrListener).second; } // <-- bool: true=erased, false=was not there @@ -4335,9 +3930,7 @@ bool NetworkOPsImp::subValidations(InfoSub::ref isrListener) { std::lock_guard sl(mSubLock); - return mStreamMaps[sValidations] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sValidations].emplace(isrListener->getSeq(), isrListener).second; } void @@ -4359,9 +3952,7 @@ bool NetworkOPsImp::subPeerStatus(InfoSub::ref isrListener) { std::lock_guard sl(mSubLock); - return mStreamMaps[sPeerStatus] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sPeerStatus].emplace(isrListener->getSeq(), isrListener).second; } // <-- bool: true=erased, false=was not there @@ -4377,9 +3968,7 @@ bool NetworkOPsImp::subConsensus(InfoSub::ref isrListener) { std::lock_guard sl(mSubLock); - return mStreamMaps[sConsensusPhase] - .emplace(isrListener->getSeq(), isrListener) - .second; + return mStreamMaps[sConsensusPhase].emplace(isrListener->getSeq(), isrListener).second; } // <-- bool: true=erased, false=was not there @@ -4448,8 +4037,7 @@ NetworkOPsImp::getBookPage( Json::Value const& jvMarker, Json::Value& jvResult) { // CAUTION: This is the old get book page logic - Json::Value& jvOffers = - (jvResult[jss::offers] = Json::Value(Json::arrayValue)); + Json::Value& jvOffers = (jvResult[jss::offers] = Json::Value(Json::arrayValue)); std::unordered_map umBalance; uint256 const uBookBase = getBookBase(book); @@ -4466,8 +4054,7 @@ NetworkOPsImp::getBookPage( ReadView const& view = *lpLedger; - bool const bGlobalFreeze = isGlobalFrozen(view, book.out.account) || - isGlobalFrozen(view, book.in.account); + bool const bGlobalFreeze = isGlobalFrozen(view, book.out.account) || isGlobalFrozen(view, book.in.account); bool bDone = false; bool bDirectAdvance = true; @@ -4506,10 +4093,8 @@ NetworkOPsImp::getBookPage( cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex); - JLOG(m_journal.trace()) - << "getBookPage: uTipIndex=" << uTipIndex; - JLOG(m_journal.trace()) - << "getBookPage: offerIndex=" << offerIndex; + JLOG(m_journal.trace()) << "getBookPage: uTipIndex=" << uTipIndex; + JLOG(m_journal.trace()) << "getBookPage: offerIndex=" << offerIndex; } } @@ -4552,12 +4137,7 @@ NetworkOPsImp::getBookPage( // Did not find balance in table. saOwnerFunds = accountHolds( - view, - uOfferOwnerID, - book.out.currency, - book.out.account, - fhZERO_IF_FROZEN, - viewJ); + view, uOfferOwnerID, book.out.currency, book.out.account, fhZERO_IF_FROZEN, viewJ); if (saOwnerFunds < beast::zero) { @@ -4598,17 +4178,13 @@ NetworkOPsImp::getBookPage( saTakerGetsFunded = saOwnerFundsLimit; saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]); - std::min( - saTakerPays, - multiply( - saTakerGetsFunded, saDirRate, saTakerPays.issue())) + std::min(saTakerPays, multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue())) .setJson(jvOffer[jss::taker_pays_funded]); } STAmount saOwnerPays = (parityRate == offerRate) ? saTakerGetsFunded - : std::min( - saOwnerFunds, multiply(saTakerGetsFunded, offerRate)); + : std::min(saOwnerFunds, multiply(saTakerGetsFunded, offerRate)); umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays; @@ -4630,8 +4206,7 @@ NetworkOPsImp::getBookPage( } else { - JLOG(m_journal.trace()) - << "getBookPage: offerIndex=" << offerIndex; + JLOG(m_journal.trace()) << "getBookPage: offerIndex=" << offerIndex; } } } @@ -4664,8 +4239,7 @@ NetworkOPsImp::getBookPage( auto const rate = transferRate(lesActive, book.out.account); - bool const bGlobalFreeze = lesActive.isGlobalFrozen(book.out.account) || - lesActive.isGlobalFrozen(book.in.account); + bool const bGlobalFreeze = lesActive.isGlobalFrozen(book.out.account) || lesActive.isGlobalFrozen(book.in.account); while (iLimit-- > 0 && obIterator.nextOffer()) { @@ -4703,11 +4277,8 @@ NetworkOPsImp::getBookPage( { // Did not find balance in table. - saOwnerFunds = lesActive.accountHolds( - uOfferOwnerID, - book.out.currency, - book.out.account, - fhZERO_IF_FROZEN); + saOwnerFunds = + lesActive.accountHolds(uOfferOwnerID, book.out.currency, book.out.account, fhZERO_IF_FROZEN); if (saOwnerFunds.isNegative()) { @@ -4750,16 +4321,13 @@ NetworkOPsImp::getBookPage( // TODO(tom): The result of this expression is not used - what's // going on here? - std::min( - saTakerPays, - multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue())) + std::min(saTakerPays, multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue())) .setJson(jvOffer[jss::taker_pays_funded]); } STAmount saOwnerPays = (parityRate == offerRate) ? saTakerGetsFunded - : std::min( - saOwnerFunds, multiply(saTakerGetsFunded, offerRate)); + : std::min(saOwnerFunds, multiply(saTakerGetsFunded, offerRate)); umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays; @@ -4782,38 +4350,22 @@ inline void NetworkOPsImp::collect_metrics() { auto [counters, mode, start, initialSync] = accounting_.getCounterData(); - auto const current = std::chrono::duration_cast( - std::chrono::steady_clock::now() - start); + auto const current = + std::chrono::duration_cast(std::chrono::steady_clock::now() - start); counters[static_cast(mode)].dur += current; std::lock_guard lock(m_statsMutex); - m_stats.disconnected_duration.set( - counters[static_cast(OperatingMode::DISCONNECTED)] - .dur.count()); - m_stats.connected_duration.set( - counters[static_cast(OperatingMode::CONNECTED)] - .dur.count()); - m_stats.syncing_duration.set( - counters[static_cast(OperatingMode::SYNCING)].dur.count()); - m_stats.tracking_duration.set( - counters[static_cast(OperatingMode::TRACKING)] - .dur.count()); - m_stats.full_duration.set( - counters[static_cast(OperatingMode::FULL)].dur.count()); + m_stats.disconnected_duration.set(counters[static_cast(OperatingMode::DISCONNECTED)].dur.count()); + m_stats.connected_duration.set(counters[static_cast(OperatingMode::CONNECTED)].dur.count()); + m_stats.syncing_duration.set(counters[static_cast(OperatingMode::SYNCING)].dur.count()); + m_stats.tracking_duration.set(counters[static_cast(OperatingMode::TRACKING)].dur.count()); + m_stats.full_duration.set(counters[static_cast(OperatingMode::FULL)].dur.count()); - m_stats.disconnected_transitions.set( - counters[static_cast(OperatingMode::DISCONNECTED)] - .transitions); - m_stats.connected_transitions.set( - counters[static_cast(OperatingMode::CONNECTED)] - .transitions); - m_stats.syncing_transitions.set( - counters[static_cast(OperatingMode::SYNCING)].transitions); - m_stats.tracking_transitions.set( - counters[static_cast(OperatingMode::TRACKING)] - .transitions); - m_stats.full_transitions.set( - counters[static_cast(OperatingMode::FULL)].transitions); + m_stats.disconnected_transitions.set(counters[static_cast(OperatingMode::DISCONNECTED)].transitions); + m_stats.connected_transitions.set(counters[static_cast(OperatingMode::CONNECTED)].transitions); + m_stats.syncing_transitions.set(counters[static_cast(OperatingMode::SYNCING)].transitions); + m_stats.tracking_transitions.set(counters[static_cast(OperatingMode::TRACKING)].transitions); + m_stats.full_transitions.set(counters[static_cast(OperatingMode::FULL)].transitions); } void @@ -4823,12 +4375,9 @@ NetworkOPsImp::StateAccounting::mode(OperatingMode om) std::lock_guard lock(mutex_); ++counters_[static_cast(om)].transitions; - if (om == OperatingMode::FULL && - counters_[static_cast(om)].transitions == 1) + if (om == OperatingMode::FULL && counters_[static_cast(om)].transitions == 1) { - initialSyncUs_ = std::chrono::duration_cast( - now - processStart_) - .count(); + initialSyncUs_ = std::chrono::duration_cast(now - processStart_).count(); } counters_[static_cast(mode_)].dur += std::chrono::duration_cast(now - start_); @@ -4841,8 +4390,8 @@ void NetworkOPsImp::StateAccounting::json(Json::Value& obj) const { auto [counters, mode, start, initialSync] = getCounterData(); - auto const current = std::chrono::duration_cast( - std::chrono::steady_clock::now() - start); + auto const current = + std::chrono::duration_cast(std::chrono::steady_clock::now() - start); counters[static_cast(mode)].dur += current; obj[jss::state_accounting] = Json::objectValue; diff --git a/src/xrpld/app/misc/NetworkOPs.h b/src/xrpld/app/misc/NetworkOPs.h index 5b92e4574b..7e230510a8 100644 --- a/src/xrpld/app/misc/NetworkOPs.h +++ b/src/xrpld/app/misc/NetworkOPs.h @@ -92,8 +92,7 @@ public: virtual OperatingMode getOperatingMode() const = 0; virtual std::string - strOperatingMode(OperatingMode const mode, bool const admin = false) - const = 0; + strOperatingMode(OperatingMode const mode, bool const admin = false) const = 0; virtual std::string strOperatingMode(bool const admin = false) const = 0; @@ -116,11 +115,7 @@ public: * @param failType fail_hard setting from transaction submission. */ virtual void - processTransaction( - std::shared_ptr& transaction, - bool bUnlimited, - bool bLocal, - FailHard failType) = 0; + processTransaction(std::shared_ptr& transaction, bool bUnlimited, bool bLocal, FailHard failType) = 0; /** * Process a set of transactions synchronously, and ensuring that they are @@ -137,9 +132,7 @@ public: // virtual Json::Value - getOwnerInfo( - std::shared_ptr lpLedger, - AccountID const& account) = 0; + getOwnerInfo(std::shared_ptr lpLedger, AccountID const& account) = 0; //-------------------------------------------------------------------------- // @@ -163,18 +156,14 @@ public: processTrustedProposal(RCLCxPeerPos peerPos) = 0; virtual bool - recvValidation( - std::shared_ptr const& val, - std::string const& source) = 0; + recvValidation(std::shared_ptr const& val, std::string const& source) = 0; virtual void mapComplete(std::shared_ptr const& map, bool fromAcquire) = 0; // network state machine virtual bool - beginConsensus( - uint256 const& netLCL, - std::unique_ptr const& clog) = 0; + beginConsensus(uint256 const& netLCL, std::unique_ptr const& clog) = 0; virtual void endConsensus(std::unique_ptr const& clog) = 0; virtual void @@ -229,9 +218,7 @@ public: proposing being accepted. */ virtual std::uint32_t - acceptLedger( - std::optional consensusDelay = - std::nullopt) = 0; + acceptLedger(std::optional consensusDelay = std::nullopt) = 0; virtual void reportFeeChange() = 0; diff --git a/src/xrpld/app/misc/PermissionedDEXHelpers.cpp b/src/xrpld/app/misc/PermissionedDEXHelpers.cpp index 0cf41ac6f0..f88c2ab9d4 100644 --- a/src/xrpld/app/misc/PermissionedDEXHelpers.cpp +++ b/src/xrpld/app/misc/PermissionedDEXHelpers.cpp @@ -6,10 +6,7 @@ namespace xrpl { namespace permissioned_dex { bool -accountInDomain( - ReadView const& view, - AccountID const& account, - Domain const& domainID) +accountInDomain(ReadView const& view, AccountID const& account, Domain const& domainID) { auto const sleDomain = view.read(keylet::permissionedDomain(domainID)); if (!sleDomain) @@ -21,26 +18,19 @@ accountInDomain( auto const& credentials = sleDomain->getFieldArray(sfAcceptedCredentials); - bool const inDomain = std::any_of( - credentials.begin(), credentials.end(), [&](auto const& credential) { - auto const sleCred = view.read(keylet::credential( - account, credential[sfIssuer], credential[sfCredentialType])); - if (!sleCred || !sleCred->isFlag(lsfAccepted)) - return false; + bool const inDomain = std::any_of(credentials.begin(), credentials.end(), [&](auto const& credential) { + auto const sleCred = view.read(keylet::credential(account, credential[sfIssuer], credential[sfCredentialType])); + if (!sleCred || !sleCred->isFlag(lsfAccepted)) + return false; - return !credentials::checkExpired( - sleCred, view.header().parentCloseTime); - }); + return !credentials::checkExpired(sleCred, view.header().parentCloseTime); + }); return inDomain; } bool -offerInDomain( - ReadView const& view, - uint256 const& offerID, - Domain const& domainID, - beast::Journal j) +offerInDomain(ReadView const& view, uint256 const& offerID, Domain const& domainID, beast::Journal j) { auto const sleOffer = view.read(keylet::offer(offerID)); @@ -54,11 +44,9 @@ offerInDomain( if (sleOffer->getFieldH256(sfDomainID) != domainID) return false; // LCOV_EXCL_LINE - if (sleOffer->isFlag(lsfHybrid) && - !sleOffer->isFieldPresent(sfAdditionalBooks)) + if (sleOffer->isFlag(lsfHybrid) && !sleOffer->isFieldPresent(sfAdditionalBooks)) { - JLOG(j.error()) << "Hybrid offer " << offerID - << " missing AdditionalBooks field"; + JLOG(j.error()) << "Hybrid offer " << offerID << " missing AdditionalBooks field"; return false; // LCOV_EXCL_LINE } diff --git a/src/xrpld/app/misc/PermissionedDEXHelpers.h b/src/xrpld/app/misc/PermissionedDEXHelpers.h index 9b6d23d09d..832129db2f 100644 --- a/src/xrpld/app/misc/PermissionedDEXHelpers.h +++ b/src/xrpld/app/misc/PermissionedDEXHelpers.h @@ -6,18 +6,11 @@ namespace permissioned_dex { // Check if an account is in a permissioned domain [[nodiscard]] bool -accountInDomain( - ReadView const& view, - AccountID const& account, - Domain const& domainID); +accountInDomain(ReadView const& view, AccountID const& account, Domain const& domainID); // Check if an offer is in the permissioned domain [[nodiscard]] bool -offerInDomain( - ReadView const& view, - uint256 const& offerID, - Domain const& domainID, - beast::Journal j); +offerInDomain(ReadView const& view, uint256 const& offerID, Domain const& domainID, beast::Journal j); } // namespace permissioned_dex diff --git a/src/xrpld/app/misc/SHAMapStore.h b/src/xrpld/app/misc/SHAMapStore.h index 26d6120f32..30253d92a5 100644 --- a/src/xrpld/app/misc/SHAMapStore.h +++ b/src/xrpld/app/misc/SHAMapStore.h @@ -84,10 +84,7 @@ public: //------------------------------------------------------------------------------ std::unique_ptr -make_SHAMapStore( - Application& app, - NodeStore::Scheduler& scheduler, - beast::Journal journal); +make_SHAMapStore(Application& app, NodeStore::Scheduler& scheduler, beast::Journal journal); } // namespace xrpl #endif diff --git a/src/xrpld/app/misc/SHAMapStoreImp.cpp b/src/xrpld/app/misc/SHAMapStoreImp.cpp index 98be038554..0ed3b8a3fc 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.cpp +++ b/src/xrpld/app/misc/SHAMapStoreImp.cpp @@ -14,9 +14,7 @@ namespace xrpl { void -SHAMapStoreImp::SavedStateDB::init( - BasicConfig const& config, - std::string const& dbName) +SHAMapStoreImp::SavedStateDB::init(BasicConfig const& config, std::string const& dbName) { std::lock_guard lock(mutex_); initStateDB(sqlDb_, config, dbName); @@ -62,10 +60,7 @@ SHAMapStoreImp::SavedStateDB::setLastRotated(LedgerIndex seq) //------------------------------------------------------------------------------ -SHAMapStoreImp::SHAMapStoreImp( - Application& app, - NodeStore::Scheduler& scheduler, - beast::Journal journal) +SHAMapStoreImp::SHAMapStoreImp(Application& app, NodeStore::Scheduler& scheduler, beast::Journal journal) : app_(app) , scheduler_(scheduler) , journal_(journal) @@ -77,9 +72,7 @@ SHAMapStoreImp::SHAMapStoreImp( Section& section{config.section(ConfigSection::nodeDatabase())}; if (section.empty()) { - Throw( - "Missing [" + ConfigSection::nodeDatabase() + - "] entry in configuration file"); + Throw("Missing [" + ConfigSection::nodeDatabase() + "] entry in configuration file"); } // RocksDB only. Use sensible defaults if no values specified. @@ -87,9 +80,7 @@ SHAMapStoreImp::SHAMapStoreImp( { if (!section.exists("cache_mb")) { - section.set( - "cache_mb", - std::to_string(config.getValueFor(SizedItem::hashNodeDBCache))); + section.set("cache_mb", std::to_string(config.getValueFor(SizedItem::hashNodeDBCache))); } if (!section.exists("filter_bits") && (config.NODE_SIZE >= 2)) @@ -116,14 +107,10 @@ SHAMapStoreImp::SHAMapStoreImp( get_if_exists(section, "advisory_delete", advisoryDelete_); - auto const minInterval = config.standalone() - ? minimumDeletionIntervalSA_ - : minimumDeletionInterval_; + auto const minInterval = config.standalone() ? minimumDeletionIntervalSA_ : minimumDeletionInterval_; if (deleteInterval_ < minInterval) { - Throw( - "online_delete must be at least " + - std::to_string(minInterval)); + Throw("online_delete must be at least " + std::to_string(minInterval)); } if (config.LEDGER_HISTORY > deleteInterval_) @@ -146,16 +133,10 @@ SHAMapStoreImp::makeNodeStore(int readThreads) // Provide default values: if (!nscfg.exists("cache_size")) - nscfg.set( - "cache_size", - std::to_string(app_.config().getValueFor( - SizedItem::treeCacheSize, std::nullopt))); + nscfg.set("cache_size", std::to_string(app_.config().getValueFor(SizedItem::treeCacheSize, std::nullopt))); if (!nscfg.exists("cache_age")) - nscfg.set( - "cache_age", - std::to_string(app_.config().getValueFor( - SizedItem::treeCacheAge, std::nullopt))); + nscfg.set("cache_age", std::to_string(app_.config().getValueFor(SizedItem::treeCacheAge, std::nullopt))); std::unique_ptr db; @@ -187,8 +168,7 @@ SHAMapStoreImp::makeNodeStore(int readThreads) else { db = NodeStore::Manager::instance().make_Database( - megabytes( - app_.config().getValueFor(SizedItem::burstSize, std::nullopt)), + megabytes(app_.config().getValueFor(SizedItem::burstSize, std::nullopt)), scheduler_, readThreads, nscfg, @@ -229,11 +209,7 @@ bool SHAMapStoreImp::copyNode(std::uint64_t& nodeCount, SHAMapTreeNode const& node) { // Copy a single record from node to dbRotating_ - dbRotating_->fetchNodeObject( - node.getHash().as_uint256(), - 0, - NodeStore::FetchType::synchronous, - true); + dbRotating_->fetchNodeObject(node.getHash().as_uint256(), 0, NodeStore::FetchType::synchronous, true); if (!(++nodeCount % checkHealthInterval_)) { if (healthWait() == stopping) @@ -286,18 +262,15 @@ SHAMapStoreImp::run() } bool const readyToRotate = - validatedSeq >= lastRotated + deleteInterval_ && - canDelete_ >= lastRotated - 1 && healthWait() == keepGoing; + validatedSeq >= lastRotated + deleteInterval_ && canDelete_ >= lastRotated - 1 && healthWait() == keepGoing; // will delete up to (not including) lastRotated if (readyToRotate) { - JLOG(journal_.warn()) - << "rotating validatedSeq " << validatedSeq << " lastRotated " - << lastRotated << " deleteInterval " << deleteInterval_ - << " canDelete_ " << canDelete_ << " state " - << app_.getOPs().strOperatingMode(false) << " age " - << ledgerMaster_->getValidatedLedgerAge().count() << 's'; + JLOG(journal_.warn()) << "rotating validatedSeq " << validatedSeq << " lastRotated " << lastRotated + << " deleteInterval " << deleteInterval_ << " canDelete_ " << canDelete_ << " state " + << app_.getOPs().strOperatingMode(false) << " age " + << ledgerMaster_->getValidatedLedgerAge().count() << 's'; clearPrior(lastRotated); if (healthWait() == stopping) @@ -309,25 +282,18 @@ SHAMapStoreImp::run() try { validatedLedger->stateMap().snapShot(false)->visitNodes( - std::bind( - &SHAMapStoreImp::copyNode, - this, - std::ref(nodeCount), - std::placeholders::_1)); + std::bind(&SHAMapStoreImp::copyNode, this, std::ref(nodeCount), std::placeholders::_1)); } catch (SHAMapMissingNode const& e) { - JLOG(journal_.error()) - << "Missing node while copying ledger before rotate: " - << e.what(); + JLOG(journal_.error()) << "Missing node while copying ledger before rotate: " << e.what(); continue; } if (healthWait() == stopping) return; // Only log if we completed without a "health" abort - JLOG(journal_.debug()) << "copied ledger " << validatedSeq - << " nodecount " << nodeCount; + JLOG(journal_.debug()) << "copied ledger " << validatedSeq << " nodecount " << nodeCount; JLOG(journal_.debug()) << "freshening caches"; freshenCaches(); @@ -338,8 +304,7 @@ SHAMapStoreImp::run() JLOG(journal_.trace()) << "Making a new backend"; auto newBackend = makeBackendRotating(); - JLOG(journal_.debug()) - << validatedSeq << " new backend " << newBackend->getName(); + JLOG(journal_.debug()) << validatedSeq << " new backend " << newBackend->getName(); clearCaches(validatedSeq); if (healthWait() == stopping) @@ -348,9 +313,7 @@ SHAMapStoreImp::run() lastRotated = validatedSeq; dbRotating_->rotate( - std::move(newBackend), - [&](std::string const& writableName, - std::string const& archiveName) { + std::move(newBackend), [&](std::string const& writableName, std::string const& archiveName) { SavedState savedState; savedState.writableDb = writableName; savedState.archiveDb = archiveName; @@ -375,8 +338,7 @@ SHAMapStoreImp::dbPaths() { if (!boost::filesystem::is_directory(dbPath)) { - journal_.error() - << "node db path must be a directory. " << dbPath.string(); + journal_.error() << "node db path must be a directory. " << dbPath.string(); Throw("node db path must be a directory."); } } @@ -413,9 +375,7 @@ SHAMapStoreImp::dbPaths() bool archiveDbExists = false; std::vector pathsToDelete; - for (boost::filesystem::directory_iterator it(dbPath); - it != boost::filesystem::directory_iterator(); - ++it) + for (boost::filesystem::directory_iterator it(dbPath); it != boost::filesystem::directory_iterator(); ++it) { if (!state.writableDb.compare(it->path().string())) writableDbExists = true; @@ -425,30 +385,23 @@ SHAMapStoreImp::dbPaths() pathsToDelete.push_back(it->path()); } - if ((!writableDbExists && state.writableDb.size()) || - (!archiveDbExists && state.archiveDb.size()) || - (writableDbExists != archiveDbExists) || - state.writableDb.empty() != state.archiveDb.empty()) + if ((!writableDbExists && state.writableDb.size()) || (!archiveDbExists && state.archiveDb.size()) || + (writableDbExists != archiveDbExists) || state.writableDb.empty() != state.archiveDb.empty()) { - boost::filesystem::path stateDbPathName = - app_.config().legacy("database_path"); + boost::filesystem::path stateDbPathName = app_.config().legacy("database_path"); stateDbPathName /= dbName_; stateDbPathName += "*"; - journal_.error() - << "state db error:\n" - << " writableDbExists " << writableDbExists << " archiveDbExists " - << archiveDbExists << '\n' - << " writableDb '" << state.writableDb << "' archiveDb '" - << state.archiveDb << "\n\n" - << "The existing data is in a corrupted state.\n" - << "To resume operation, remove the files matching " - << stateDbPathName.string() << " and contents of the directory " - << get(section, "path") << '\n' - << "Optionally, you can move those files to another\n" - << "location if you wish to analyze or back up the data.\n" - << "However, there is no guarantee that the data in its\n" - << "existing form is usable."; + journal_.error() << "state db error:\n" + << " writableDbExists " << writableDbExists << " archiveDbExists " << archiveDbExists << '\n' + << " writableDb '" << state.writableDb << "' archiveDb '" << state.archiveDb << "\n\n" + << "The existing data is in a corrupted state.\n" + << "To resume operation, remove the files matching " << stateDbPathName.string() + << " and contents of the directory " << get(section, "path") << '\n' + << "Optionally, you can move those files to another\n" + << "location if you wish to analyze or back up the data.\n" + << "However, there is no guarantee that the data in its\n" + << "existing form is usable."; Throw("state db error"); } @@ -479,8 +432,7 @@ SHAMapStoreImp::makeBackendRotating(std::string path) auto backend{NodeStore::Manager::instance().make_Backend( section, - megabytes( - app_.config().getValueFor(SizedItem::burstSize, std::nullopt)), + megabytes(app_.config().getValueFor(SizedItem::burstSize, std::nullopt)), scheduler_, app_.logs().journal(nodeStoreName_))}; backend->open(); @@ -494,14 +446,11 @@ SHAMapStoreImp::clearSql( std::function()> const& getMinSeq, std::function const& deleteBeforeSeq) { - XRPL_ASSERT( - deleteInterval_, - "xrpl::SHAMapStoreImp::clearSql : nonzero delete interval"); + XRPL_ASSERT(deleteInterval_, "xrpl::SHAMapStoreImp::clearSql : nonzero delete interval"); LedgerIndex min = std::numeric_limits::max(); { - JLOG(journal_.trace()) - << "Begin: Look up lowest value of: " << TableName; + JLOG(journal_.trace()) << "Begin: Look up lowest value of: " << TableName; auto m = getMinSeq(); JLOG(journal_.trace()) << "End: Look up lowest value of: " << TableName; if (!m) @@ -518,18 +467,15 @@ SHAMapStoreImp::clearSql( return; } - JLOG(journal_.debug()) << "start deleting in: " << TableName << " from " - << min << " to " << lastRotated; + JLOG(journal_.debug()) << "start deleting in: " << TableName << " from " << min << " to " << lastRotated; while (min < lastRotated) { min = std::min(lastRotated, min + deleteBatch_); - JLOG(journal_.trace()) - << "Begin: Delete up to " << deleteBatch_ - << " rows with LedgerSeq < " << min << " from: " << TableName; + JLOG(journal_.trace()) << "Begin: Delete up to " << deleteBatch_ << " rows with LedgerSeq < " << min + << " from: " << TableName; deleteBeforeSeq(min); - JLOG(journal_.trace()) - << "End: Delete up to " << deleteBatch_ << " rows with LedgerSeq < " - << min << " from: " << TableName; + JLOG(journal_.trace()) << "End: Delete up to " << deleteBatch_ << " rows with LedgerSeq < " << min + << " from: " << TableName; if (healthWait() == stopping) return; if (min < lastRotated) @@ -562,16 +508,13 @@ SHAMapStoreImp::clearPrior(LedgerIndex lastRotated) // Do not allow ledgers to be acquired from the network // that are about to be deleted. minimumOnline_ = lastRotated + 1; - JLOG(journal_.trace()) << "Begin: Clear internal ledgers up to " - << lastRotated; + JLOG(journal_.trace()) << "Begin: Clear internal ledgers up to " << lastRotated; ledgerMaster_->clearPriorLedgers(lastRotated); - JLOG(journal_.trace()) << "End: Clear internal ledgers up to " - << lastRotated; + JLOG(journal_.trace()) << "End: Clear internal ledgers up to " << lastRotated; if (healthWait() == stopping) return; - SQLiteDatabase* const db = - dynamic_cast(&app_.getRelationalDatabase()); + SQLiteDatabase* const db = dynamic_cast(&app_.getRelationalDatabase()); if (!db) Throw("Failed to get relational database"); @@ -590,24 +533,16 @@ SHAMapStoreImp::clearPrior(LedgerIndex lastRotated) clearSql( lastRotated, "Transactions", - [&db]() -> std::optional { - return db->getTransactionsMinLedgerSeq(); - }, - [&db](LedgerIndex min) -> void { - db->deleteTransactionsBeforeLedgerSeq(min); - }); + [&db]() -> std::optional { return db->getTransactionsMinLedgerSeq(); }, + [&db](LedgerIndex min) -> void { db->deleteTransactionsBeforeLedgerSeq(min); }); if (healthWait() == stopping) return; clearSql( lastRotated, "AccountTransactions", - [&db]() -> std::optional { - return db->getAccountTransactionsMinLedgerSeq(); - }, - [&db](LedgerIndex min) -> void { - db->deleteAccountTransactionsBeforeLedgerSeq(min); - }); + [&db]() -> std::optional { return db->getAccountTransactionsMinLedgerSeq(); }, + [&db](LedgerIndex min) -> void { db->deleteAccountTransactionsBeforeLedgerSeq(min); }); if (healthWait() == stopping) return; } @@ -622,8 +557,7 @@ SHAMapStoreImp::healthWait() { lock.unlock(); JLOG(journal_.warn()) << "Waiting " << recoveryWaitTime_.count() - << "s for node to stabilize. state: " - << app_.getOPs().strOperatingMode(mode, false) + << "s for node to stabilize. state: " << app_.getOPs().strOperatingMode(mode, false) << ". age " << age.count() << 's'; std::this_thread::sleep_for(recoveryWaitTime_); age = ledgerMaster_->getValidatedLedgerAge(); @@ -661,10 +595,7 @@ SHAMapStoreImp::minimumOnline() const //------------------------------------------------------------------------------ std::unique_ptr -make_SHAMapStore( - Application& app, - NodeStore::Scheduler& scheduler, - beast::Journal journal) +make_SHAMapStore(Application& app, NodeStore::Scheduler& scheduler, beast::Journal journal) { return std::make_unique(app, scheduler, journal); } diff --git a/src/xrpld/app/misc/SHAMapStoreImp.h b/src/xrpld/app/misc/SHAMapStoreImp.h index 38997c2997..05faae5bd4 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.h +++ b/src/xrpld/app/misc/SHAMapStoreImp.h @@ -100,16 +100,12 @@ private: static constexpr auto nodeStoreName_ = "NodeStore"; public: - SHAMapStoreImp( - Application& app, - NodeStore::Scheduler& scheduler, - beast::Journal journal); + SHAMapStoreImp(Application& app, NodeStore::Scheduler& scheduler, beast::Journal journal); std::uint32_t clampFetchDepth(std::uint32_t fetch_depth) const override { - return deleteInterval_ ? std::min(fetch_depth, deleteInterval_) - : fetch_depth; + return deleteInterval_ ? std::min(fetch_depth, deleteInterval_) : fetch_depth; } std::unique_ptr @@ -176,8 +172,7 @@ private: for (auto const& key : cache.getKeys()) { - dbRotating_->fetchNodeObject( - key, 0, NodeStore::FetchType::synchronous, true); + dbRotating_->fetchNodeObject(key, 0, NodeStore::FetchType::synchronous, true); if (!(++check % checkHealthInterval_) && healthWait() == stopping) return true; } diff --git a/src/xrpld/app/misc/Transaction.h b/src/xrpld/app/misc/Transaction.h index 9f75387744..c902d4a4f3 100644 --- a/src/xrpld/app/misc/Transaction.h +++ b/src/xrpld/app/misc/Transaction.h @@ -40,17 +40,13 @@ enum class TxSearched { all, some, unknown }; // This class is for constructing and examining transactions. // Transactions are static so manipulation functions are unnecessary. -class Transaction : public std::enable_shared_from_this, - public CountedObject +class Transaction : public std::enable_shared_from_this, public CountedObject { public: using pointer = std::shared_ptr; using ref = pointer const&; - Transaction( - std::shared_ptr const&, - std::string&, - Application&) noexcept; + Transaction(std::shared_ptr const&, std::string&, Application&) noexcept; // The two boost::optional parameters are because SOCI requires // boost::optional (not std::optional) parameters. @@ -251,15 +247,8 @@ public: { CurrentLedgerState() = delete; - CurrentLedgerState( - LedgerIndex li, - XRPAmount fee, - std::uint32_t accSeqNext, - std::uint32_t accSeqAvail) - : validatedLedger{li} - , minFeeRequired{fee} - , accountSeqNext{accSeqNext} - , accountSeqAvail{accSeqAvail} + CurrentLedgerState(LedgerIndex li, XRPAmount fee, std::uint32_t accSeqNext, std::uint32_t accSeqAvail) + : validatedLedger{li}, minFeeRequired{fee}, accountSeqNext{accSeqNext}, accountSeqAvail{accSeqAvail} { } @@ -293,8 +282,7 @@ public: std::uint32_t accountSeq, std::uint32_t availableSeq) { - currentLedgerState_.emplace( - validatedLedger, fee, accountSeq, availableSeq); + currentLedgerState_.emplace(validatedLedger, fee, accountSeq, availableSeq); } Json::Value @@ -306,8 +294,7 @@ public: // at the time of search. struct Locator { - std::variant, ClosedInterval> - locator; + std::variant, ClosedInterval> locator; // @return true if transaction was found, false otherwise // @@ -317,8 +304,7 @@ public: bool isFound() { - return std::holds_alternative>( - locator); + return std::holds_alternative>(locator); } // @return key used to find transaction in nodestore @@ -352,29 +338,15 @@ public: static Locator locate(uint256 const& id, Application& app); - static std::variant< - std::pair, std::shared_ptr>, - TxSearched> + static std::variant, std::shared_ptr>, TxSearched> load(uint256 const& id, Application& app, error_code_i& ec); - static std::variant< - std::pair, std::shared_ptr>, - TxSearched> - load( - uint256 const& id, - Application& app, - ClosedInterval const& range, - error_code_i& ec); + static std::variant, std::shared_ptr>, TxSearched> + load(uint256 const& id, Application& app, ClosedInterval const& range, error_code_i& ec); private: - static std::variant< - std::pair, std::shared_ptr>, - TxSearched> - load( - uint256 const& id, - Application& app, - std::optional> const& range, - error_code_i& ec); + static std::variant, std::shared_ptr>, TxSearched> + load(uint256 const& id, Application& app, std::optional> const& range, error_code_i& ec); uint256 mTransactionID; diff --git a/src/xrpld/app/misc/TxQ.h b/src/xrpld/app/misc/TxQ.h index 10ed4adeea..004cd085fc 100644 --- a/src/xrpld/app/misc/TxQ.h +++ b/src/xrpld/app/misc/TxQ.h @@ -252,12 +252,7 @@ public: will return `{ terQUEUED, false }`. */ ApplyResult - apply( - Application& app, - OpenView& view, - std::shared_ptr const& tx, - ApplyFlags flags, - beast::Journal j); + apply(Application& app, OpenView& view, std::shared_ptr const& tx, ApplyFlags flags, beast::Journal j); /** Fill the new open ledger with transactions from the queue. @@ -314,9 +309,7 @@ public: * and first available sequence */ FeeAndSeq - getTxRequiredFeeAndSeq( - OpenView const& view, - std::shared_ptr const& tx) const; + getTxRequiredFeeAndSeq(OpenView const& view, std::shared_ptr const& tx) const; /** Returns information about the transactions currently in the queue for the account. @@ -346,9 +339,7 @@ public: private: // Implementation for nextQueuableSeq(). The passed lock must be held. SeqProxy - nextQueuableSeqImpl( - std::shared_ptr const& sleAccount, - std::lock_guard const&) const; + nextQueuableSeqImpl(std::shared_ptr const& sleAccount, std::lock_guard const&) const; /** Track and use the fee escalation metrics of the @@ -381,18 +372,11 @@ private: public: /// Constructor FeeMetrics(Setup const& setup, beast::Journal j) - : minimumTxnCount_( - setup.standAlone ? setup.minimumTxnInLedgerSA - : setup.minimumTxnInLedger) - , targetTxnCount_( - setup.targetTxnInLedger < minimumTxnCount_ - ? minimumTxnCount_ - : setup.targetTxnInLedger) + : minimumTxnCount_(setup.standAlone ? setup.minimumTxnInLedgerSA : setup.minimumTxnInLedger) + , targetTxnCount_(setup.targetTxnInLedger < minimumTxnCount_ ? minimumTxnCount_ : setup.targetTxnInLedger) , maximumTxnCount_( setup.maximumTxnInLedger - ? *setup.maximumTxnInLedger < targetTxnCount_ - ? targetTxnCount_ - : *setup.maximumTxnInLedger + ? *setup.maximumTxnInLedger < targetTxnCount_ ? targetTxnCount_ : *setup.maximumTxnInLedger : std::optional(std::nullopt)) , txnsExpected_(minimumTxnCount_) , recentTxnCounts_(setup.ledgersInQueue) @@ -412,11 +396,7 @@ private: @param setup Customization params. */ std::size_t - update( - Application& app, - ReadView const& view, - bool timeLeap, - TxQ::Setup const& setup); + update(Application& app, ReadView const& view, bool timeLeap, TxQ::Setup const& setup); /// Snapshot of the externally relevant FeeMetrics /// fields at any given time. @@ -634,8 +614,7 @@ private: operator()(MaybeTx const& lhs, MaybeTx const& rhs) const { if (lhs.feeLevel == rhs.feeLevel) - return (lhs.txID ^ MaybeTx::parentHashComp) < - (rhs.txID ^ MaybeTx::parentHashComp); + return (lhs.txID ^ MaybeTx::parentHashComp) < (rhs.txID ^ MaybeTx::parentHashComp); return lhs.feeLevel > rhs.feeLevel; } }; @@ -728,13 +707,10 @@ private: std::optional const& replacedTxIter, std::shared_ptr const& tx); - using FeeHook = boost::intrusive::member_hook< - MaybeTx, - boost::intrusive::set_member_hook<>, - &MaybeTx::byFeeListHook>; + using FeeHook = + boost::intrusive::member_hook, &MaybeTx::byFeeListHook>; - using FeeMultiSet = boost::intrusive:: - multiset>; + using FeeMultiSet = boost::intrusive::multiset>; using AccountMap = std::map; @@ -804,14 +780,10 @@ private: is higher), or next entry in byFee_ (lower fee level). Used to get the next "applicable" MaybeTx for accept(). */ - FeeMultiSet::iterator_type eraseAndAdvance( - FeeMultiSet::const_iterator_type); + FeeMultiSet::iterator_type eraseAndAdvance(FeeMultiSet::const_iterator_type); /// Erase a range of items, based on TxQAccount::TxMap iterators TxQAccount::TxMap::iterator - erase( - TxQAccount& txQAccount, - TxQAccount::TxMap::const_iterator begin, - TxQAccount::TxMap::const_iterator end); + erase(TxQAccount& txQAccount, TxQAccount::TxMap::const_iterator begin, TxQAccount::TxMap::const_iterator end); /** All-or-nothing attempt to try to apply the queued txs for @@ -843,15 +815,13 @@ template XRPAmount toDrops(FeeLevel const& level, XRPAmount baseFee) { - return mulDiv(level, baseFee, TxQ::baseLevel) - .value_or(XRPAmount(STAmount::cMaxNativeN)); + return mulDiv(level, baseFee, TxQ::baseLevel).value_or(XRPAmount(STAmount::cMaxNativeN)); } inline FeeLevel64 toFeeLevel(XRPAmount const& drops, XRPAmount const& baseFee) { - return mulDiv(drops, TxQ::baseLevel, baseFee) - .value_or(FeeLevel64(std::numeric_limits::max())); + return mulDiv(drops, TxQ::baseLevel, baseFee).value_or(FeeLevel64(std::numeric_limits::max())); } } // namespace xrpl diff --git a/src/xrpld/app/misc/ValidatorKeys.h b/src/xrpld/app/misc/ValidatorKeys.h index a1511c134a..3a9aaf6d2c 100644 --- a/src/xrpld/app/misc/ValidatorKeys.h +++ b/src/xrpld/app/misc/ValidatorKeys.h @@ -26,13 +26,8 @@ public: SecretKey secretKey; Keys() = delete; - Keys( - PublicKey const& masterPublic_, - PublicKey const& public_, - SecretKey const& secret_) - : masterPublicKey(masterPublic_) - , publicKey(public_) - , secretKey(secret_) + Keys(PublicKey const& masterPublic_, PublicKey const& public_, SecretKey const& secret_) + : masterPublicKey(masterPublic_), publicKey(public_), secretKey(secret_) { } }; diff --git a/src/xrpld/app/misc/ValidatorList.h b/src/xrpld/app/misc/ValidatorList.h index 45b24e8609..3b15af00dc 100644 --- a/src/xrpld/app/misc/ValidatorList.h +++ b/src/xrpld/app/misc/ValidatorList.h @@ -273,11 +273,7 @@ public: { explicit PublisherListStats() = default; explicit PublisherListStats(ListDisposition d); - PublisherListStats( - ListDisposition d, - PublicKey key, - PublisherStatus stat, - std::size_t seq); + PublisherListStats(ListDisposition d, PublicKey key, PublisherStatus stat, std::size_t seq); ListDisposition bestDisposition() const; @@ -297,10 +293,7 @@ public: struct MessageWithHash { explicit MessageWithHash() = default; - explicit MessageWithHash( - std::shared_ptr const& message_, - uint256 hash_, - std::size_t num_); + explicit MessageWithHash(std::shared_ptr const& message_, uint256 hash_, std::size_t num_); std::shared_ptr message; uint256 hash; std::size_t numVLs = 0; @@ -604,22 +597,19 @@ public: May be called concurrently */ void - for_each_available( - std::function const& blobInfos, - PublicKey const& pubKey, - std::size_t maxSequence, - uint256 const& hash)> func) const; + for_each_available(std::function const& blobInfos, + PublicKey const& pubKey, + std::size_t maxSequence, + uint256 const& hash)> func) const; /** Returns the current valid list for the given publisher key, if available, as a Json object. */ std::optional - getAvailable( - std::string_view pubKey, - std::optional forceVersion = {}); + getAvailable(std::string_view pubKey, std::optional forceVersion = {}); /** Return the number of configured validator list sites. */ std::size_t @@ -692,8 +682,7 @@ public: * @return a filtered copy of the validations */ std::vector> - negativeUNLFilter( - std::vector>&& validations) const; + negativeUNLFilter(std::vector>&& validations) const; private: /** Return the number of configured validator list sites. */ @@ -779,9 +768,7 @@ private: lock_guard const&); static void - buildBlobInfos( - std::map& blobInfos, - PublisherListCollection const& lists); + buildBlobInfos(std::map& blobInfos, PublisherListCollection const& lists); static std::map buildBlobInfos(PublisherListCollection const& lists); @@ -818,10 +805,7 @@ private: writing to a cache file, or serving to a /vl/ query */ static Json::Value - buildFileData( - std::string const& pubKey, - PublisherListCollection const& pubCollection, - beast::Journal j); + buildFileData(std::string const& pubKey, PublisherListCollection const& pubCollection, beast::Journal j); /** Build a Json representation of the collection, suitable for writing to a cache file, or serving to a /vl/ query @@ -873,10 +857,7 @@ private: Calling public member function is expected to lock mutex */ bool - removePublisherList( - lock_guard const&, - PublicKey const& publisherKey, - PublisherStatus reason); + removePublisherList(lock_guard const&, PublicKey const& publisherKey, PublisherStatus reason); /** Return quorum for trusted validator set @@ -889,10 +870,7 @@ private: recently received validations */ std::size_t - calculateQuorum( - std::size_t unlSize, - std::size_t effectiveUnlSize, - std::size_t seenSize); + calculateQuorum(std::size_t unlSize, std::size_t effectiveUnlSize, std::size_t seenSize); }; // hashing helpers @@ -944,8 +922,7 @@ void hash_append(Hasher& h, TMValidatorListCollection const& msg) { using beast::hash_append; - hash_append( - h, msg.manifest(), xrpl::ValidatorList::parseBlobs(msg), msg.version()); + hash_append(h, msg.manifest(), xrpl::ValidatorList::parseBlobs(msg), msg.version()); } } // namespace protocol diff --git a/src/xrpld/app/misc/ValidatorSite.h b/src/xrpld/app/misc/ValidatorSite.h index 64b22f065d..075722bca6 100644 --- a/src/xrpld/app/misc/ValidatorSite.h +++ b/src/xrpld/app/misc/ValidatorSite.h @@ -178,16 +178,12 @@ public: private: /// Load configured site URIs. bool - load( - std::vector const& siteURIs, - std::lock_guard const&); + load(std::vector const& siteURIs, std::lock_guard const&); /// Queue next site to be fetched /// lock over site_mutex_ and state_mutex_ required void - setTimer( - std::lock_guard const&, - std::lock_guard const&); + setTimer(std::lock_guard const&, std::lock_guard const&); /// request took too long void @@ -207,34 +203,22 @@ private: /// Store latest list fetched from anywhere void - onTextFetch( - boost::system::error_code const& ec, - std::string const& res, - std::size_t siteIdx); + onTextFetch(boost::system::error_code const& ec, std::string const& res, std::size_t siteIdx); /// Initiate request to given resource. /// lock over sites_mutex_ required void - makeRequest( - std::shared_ptr resource, - std::size_t siteIdx, - std::lock_guard const&); + makeRequest(std::shared_ptr resource, std::size_t siteIdx, std::lock_guard const&); /// Parse json response from validator list site. /// lock over sites_mutex_ required void - parseJsonResponse( - std::string const& res, - std::size_t siteIdx, - std::lock_guard const&); + parseJsonResponse(std::string const& res, std::size_t siteIdx, std::lock_guard const&); /// Interpret a redirect response. /// lock over sites_mutex_ required std::shared_ptr - processRedirect( - detail::response_type& res, - std::size_t siteIdx, - std::lock_guard const&); + processRedirect(detail::response_type& res, std::size_t siteIdx, std::lock_guard const&); /// If no sites are provided, or a site fails to load, /// get a list of local cache files from the ValidatorList. diff --git a/src/xrpld/app/misc/detail/AMMHelpers.cpp b/src/xrpld/app/misc/detail/AMMHelpers.cpp index 0b741c8d36..ff3474f33d 100644 --- a/src/xrpld/app/misc/detail/AMMHelpers.cpp +++ b/src/xrpld/app/misc/detail/AMMHelpers.cpp @@ -3,14 +3,10 @@ namespace xrpl { STAmount -ammLPTokens( - STAmount const& asset1, - STAmount const& asset2, - Issue const& lptIssue) +ammLPTokens(STAmount const& asset1, STAmount const& asset2, Issue const& lptIssue) { // AMM invariant: sqrt(asset1 * asset2) >= LPTokensBalance - auto const rounding = - isFeatureEnabled(fixAMMv1_3) ? Number::downward : Number::getround(); + auto const rounding = isFeatureEnabled(fixAMMv1_3) ? Number::downward : Number::getround(); NumberRoundModeGuard g(rounding); auto const tokens = root2(asset1 * asset2); return toSTAmount(lptIssue, tokens); @@ -58,11 +54,7 @@ lpTokensOut( * (R/t2)**2 + R*(2*d/t2 - 1/f1) + d**2 - f2**2 = 0 */ STAmount -ammAssetIn( - STAmount const& asset1Balance, - STAmount const& lptAMMBalance, - STAmount const& lpTokens, - std::uint16_t tfee) +ammAssetIn(STAmount const& asset1Balance, STAmount const& lptAMMBalance, STAmount const& lpTokens, std::uint16_t tfee) { auto const f1 = feeMult(tfee); auto const f2 = feeMultHalf(tfee) / f1; @@ -74,8 +66,7 @@ ammAssetIn( auto const c = d * d - f2 * f2; if (!isFeatureEnabled(fixAMMv1_3)) { - return toSTAmount( - asset1Balance.issue(), asset1Balance * solveQuadraticEq(a, b, c)); + return toSTAmount(asset1Balance.issue(), asset1Balance * solveQuadraticEq(a, b, c)); } else { @@ -123,11 +114,7 @@ lpTokensIn( * R = (t1**2 + t1*(f - 2)) / (t1*f - 1) */ STAmount -ammAssetOut( - STAmount const& assetBalance, - STAmount const& lptAMMBalance, - STAmount const& lpTokens, - std::uint16_t tfee) +ammAssetOut(STAmount const& assetBalance, STAmount const& lptAMMBalance, STAmount const& lpTokens, std::uint16_t tfee) { auto const f = getFee(tfee); Number const t1 = lpTokens / lptAMMBalance; @@ -151,10 +138,7 @@ square(Number const& n) } STAmount -adjustLPTokens( - STAmount const& lptAMMBalance, - STAmount const& lpTokens, - IsDeposit isDeposit) +adjustLPTokens(STAmount const& lptAMMBalance, STAmount const& lpTokens, IsDeposit isDeposit) { // Force rounding downward to ensure adjusted tokens are less or equal // to requested tokens. @@ -178,21 +162,18 @@ adjustAmountsByLPTokens( if (isFeatureEnabled(fixAMMv1_3)) return std::make_tuple(amount, amount2, lpTokens); - auto const lpTokensActual = - adjustLPTokens(lptAMMBalance, lpTokens, isDeposit); + auto const lpTokensActual = adjustLPTokens(lptAMMBalance, lpTokens, isDeposit); if (lpTokensActual == beast::zero) { - auto const amount2Opt = - amount2 ? std::make_optional(STAmount{}) : std::nullopt; + auto const amount2Opt = amount2 ? std::make_optional(STAmount{}) : std::nullopt; return std::make_tuple(STAmount{}, amount2Opt, lpTokensActual); } if (lpTokensActual < lpTokens) { bool const ammRoundingEnabled = [&]() { - if (auto const& rules = getCurrentTransactionRules(); - rules && rules->enabled(fixAMMv1_1)) + if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixAMMv1_1)) return true; return false; }(); @@ -202,41 +183,33 @@ adjustAmountsByLPTokens( { Number const fr = lpTokensActual / lpTokens; auto const amountActual = toSTAmount(amount.issue(), fr * amount); - auto const amount2Actual = - toSTAmount(amount2->issue(), fr * *amount2); + auto const amount2Actual = toSTAmount(amount2->issue(), fr * *amount2); if (!ammRoundingEnabled) return std::make_tuple( amountActual < amount ? amountActual : amount, amount2Actual < amount2 ? amount2Actual : amount2, lpTokensActual); else - return std::make_tuple( - amountActual, amount2Actual, lpTokensActual); + return std::make_tuple(amountActual, amount2Actual, lpTokensActual); } // Single trade auto const amountActual = [&]() { if (isDeposit == IsDeposit::Yes) - return ammAssetIn( - amountBalance, lptAMMBalance, lpTokensActual, tfee); + return ammAssetIn(amountBalance, lptAMMBalance, lpTokensActual, tfee); else if (!ammRoundingEnabled) - return ammAssetOut( - amountBalance, lptAMMBalance, lpTokens, tfee); + return ammAssetOut(amountBalance, lptAMMBalance, lpTokens, tfee); else - return ammAssetOut( - amountBalance, lptAMMBalance, lpTokensActual, tfee); + return ammAssetOut(amountBalance, lptAMMBalance, lpTokensActual, tfee); }(); if (!ammRoundingEnabled) - return amountActual < amount - ? std::make_tuple(amountActual, std::nullopt, lpTokensActual) - : std::make_tuple(amount, std::nullopt, lpTokensActual); + return amountActual < amount ? std::make_tuple(amountActual, std::nullopt, lpTokensActual) + : std::make_tuple(amount, std::nullopt, lpTokensActual); else return std::make_tuple(amountActual, std::nullopt, lpTokensActual); } - XRPL_ASSERT( - lpTokensActual == lpTokens, - "xrpl::adjustAmountsByLPTokens : LP tokens match actual"); + XRPL_ASSERT(lpTokensActual == lpTokens, "xrpl::adjustAmountsByLPTokens : LP tokens match actual"); return {amount, amount2, lpTokensActual}; } @@ -289,11 +262,7 @@ getRoundedAsset( } STAmount -getRoundedLPTokens( - Rules const& rules, - STAmount const& balance, - Number const& frac, - IsDeposit isDeposit) +getRoundedLPTokens(Rules const& rules, STAmount const& balance, Number const& frac, IsDeposit isDeposit) { if (!rules.enabled(fixAMMv1_3)) return toSTAmount(balance.issue(), balance * frac); @@ -379,11 +348,7 @@ adjustAssetOutByTokens( } Number -adjustFracByTokens( - Rules const& rules, - STAmount const& lptAMMBalance, - STAmount const& tokens, - Number const& frac) +adjustFracByTokens(Rules const& rules, STAmount const& lptAMMBalance, STAmount const& tokens, Number const& frac) { if (!rules.enabled(fixAMMv1_3)) return frac; diff --git a/src/xrpld/app/misc/detail/AMMUtils.cpp b/src/xrpld/app/misc/detail/AMMUtils.cpp index c0cda2bd73..36a40f1709 100644 --- a/src/xrpld/app/misc/detail/AMMUtils.cpp +++ b/src/xrpld/app/misc/detail/AMMUtils.cpp @@ -17,10 +17,8 @@ ammPoolHolds( FreezeHandling freezeHandling, beast::Journal const j) { - auto const assetInBalance = - accountHolds(view, ammAccountID, issue1, freezeHandling, j); - auto const assetOutBalance = - accountHolds(view, ammAccountID, issue2, freezeHandling, j); + auto const assetInBalance = accountHolds(view, ammAccountID, issue1, freezeHandling, j); + auto const assetOutBalance = accountHolds(view, ammAccountID, issue2, freezeHandling, j); return std::make_pair(assetInBalance, assetOutBalance); } @@ -38,32 +36,25 @@ ammHolds( auto const issue2 = ammSle[sfAsset2].get(); if (optIssue1 && optIssue2) { - if (invalidAMMAssetPair( - *optIssue1, - *optIssue2, - std::make_optional(std::make_pair(issue1, issue2)))) + if (invalidAMMAssetPair(*optIssue1, *optIssue2, std::make_optional(std::make_pair(issue1, issue2)))) { // This error can only be hit if the AMM is corrupted // LCOV_EXCL_START - JLOG(j.debug()) << "ammHolds: Invalid optIssue1 or optIssue2 " - << *optIssue1 << " " << *optIssue2; + JLOG(j.debug()) << "ammHolds: Invalid optIssue1 or optIssue2 " << *optIssue1 << " " << *optIssue2; return std::nullopt; // LCOV_EXCL_STOP } return std::make_optional(std::make_pair(*optIssue1, *optIssue2)); } - auto const singleIssue = - [&issue1, &issue2, &j]( - Issue checkIssue, - char const* label) -> std::optional> { + auto const singleIssue = [&issue1, &issue2, &j]( + Issue checkIssue, char const* label) -> std::optional> { if (checkIssue == issue1) return std::make_optional(std::make_pair(issue1, issue2)); else if (checkIssue == issue2) return std::make_optional(std::make_pair(issue2, issue1)); // Unreachable unless AMM corrupted. // LCOV_EXCL_START - JLOG(j.debug()) - << "ammHolds: Invalid " << label << " " << checkIssue; + JLOG(j.debug()) << "ammHolds: Invalid " << label << " " << checkIssue; return std::nullopt; // LCOV_EXCL_STOP }; @@ -80,13 +71,8 @@ ammHolds( }(); if (!issues) return Unexpected(tecAMM_INVALID_TOKENS); - auto const [asset1, asset2] = ammPoolHolds( - view, - ammSle.getAccountID(sfAccount), - issues->first, - issues->second, - freezeHandling, - j); + auto const [asset1, asset2] = + ammPoolHolds(view, ammSle.getAccountID(sfAccount), issues->first, issues->second, freezeHandling, j); return std::make_tuple(asset1, asset2, ammSle[sfLPTokenBalance]); } @@ -112,15 +98,13 @@ ammLPHolds( { amount.clear(Issue{currency, ammAccount}); JLOG(j.trace()) << "ammLPHolds: no SLE " - << " lpAccount=" << to_string(lpAccount) - << " amount=" << amount.getFullText(); + << " lpAccount=" << to_string(lpAccount) << " amount=" << amount.getFullText(); } else if (isFrozen(view, lpAccount, currency, ammAccount)) { amount.clear(Issue{currency, ammAccount}); JLOG(j.trace()) << "ammLPHolds: frozen currency " - << " lpAccount=" << to_string(lpAccount) - << " amount=" << amount.getFullText(); + << " lpAccount=" << to_string(lpAccount) << " amount=" << amount.getFullText(); } else { @@ -133,19 +117,14 @@ ammLPHolds( amount.setIssuer(ammAccount); JLOG(j.trace()) << "ammLPHolds:" - << " lpAccount=" << to_string(lpAccount) - << " amount=" << amount.getFullText(); + << " lpAccount=" << to_string(lpAccount) << " amount=" << amount.getFullText(); } return view.balanceHook(lpAccount, ammAccount, amount); } STAmount -ammLPHolds( - ReadView const& view, - SLE const& ammSle, - AccountID const& lpAccount, - beast::Journal const j) +ammLPHolds(ReadView const& view, SLE const& ammSle, AccountID const& lpAccount, beast::Journal const j) { return ammLPHolds( view, @@ -161,25 +140,20 @@ getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account) { using namespace std::chrono; XRPL_ASSERT( - !view.rules().enabled(fixInnerObjTemplate) || - ammSle.isFieldPresent(sfAuctionSlot), + !view.rules().enabled(fixInnerObjTemplate) || ammSle.isFieldPresent(sfAuctionSlot), "xrpl::getTradingFee : auction present"); if (ammSle.isFieldPresent(sfAuctionSlot)) { - auto const& auctionSlot = - static_cast(ammSle.peekAtField(sfAuctionSlot)); + auto const& auctionSlot = static_cast(ammSle.peekAtField(sfAuctionSlot)); // Not expired if (auto const expiration = auctionSlot[~sfExpiration]; - duration_cast( - view.header().parentCloseTime.time_since_epoch()) - .count() < expiration) + duration_cast(view.header().parentCloseTime.time_since_epoch()).count() < expiration) { if (auctionSlot[~sfAccount] == account) return auctionSlot[sfDiscountedFee]; if (auctionSlot.isFieldPresent(sfAuthAccounts)) { - for (auto const& acct : - auctionSlot.getFieldArray(sfAuthAccounts)) + for (auto const& acct : auctionSlot.getFieldArray(sfAuthAccounts)) if (acct[~sfAccount] == account) return auctionSlot[sfDiscountedFee]; } @@ -189,20 +163,15 @@ getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account) } STAmount -ammAccountHolds( - ReadView const& view, - AccountID const& ammAccountID, - Issue const& issue) +ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Issue const& issue) { if (isXRP(issue)) { if (auto const sle = view.read(keylet::account(ammAccountID))) return (*sle)[sfBalance]; } - else if (auto const sle = view.read( - keylet::line(ammAccountID, issue.account, issue.currency)); - sle && - !isFrozen(view, ammAccountID, issue.currency, issue.account)) + else if (auto const sle = view.read(keylet::line(ammAccountID, issue.account, issue.currency)); + sle && !isFrozen(view, ammAccountID, issue.currency, issue.account)) { auto amount = (*sle)[sfBalance]; if (ammAccountID > issue.account) @@ -215,18 +184,12 @@ ammAccountHolds( } static TER -deleteAMMTrustLines( - Sandbox& sb, - AccountID const& ammAccountID, - std::uint16_t maxTrustlinesToDelete, - beast::Journal j) +deleteAMMTrustLines(Sandbox& sb, AccountID const& ammAccountID, std::uint16_t maxTrustlinesToDelete, beast::Journal j) { return cleanupOnAccountDelete( sb, keylet::ownerDir(ammAccountID), - [&](LedgerEntryType nodeType, - uint256 const&, - std::shared_ptr& sleItem) -> std::pair { + [&](LedgerEntryType nodeType, uint256 const&, std::shared_ptr& sleItem) -> std::pair { // Skip AMM if (nodeType == LedgerEntryType::ltAMM) return {tesSUCCESS, SkipEntry::Yes}; @@ -234,9 +197,7 @@ deleteAMMTrustLines( if (nodeType != LedgerEntryType::ltRIPPLE_STATE) { // LCOV_EXCL_START - JLOG(j.error()) - << "deleteAMMTrustLines: deleting non-trustline " - << nodeType; + JLOG(j.error()) << "deleteAMMTrustLines: deleting non-trustline " << nodeType; return {tecINTERNAL, SkipEntry::No}; // LCOV_EXCL_STOP } @@ -245,34 +206,26 @@ deleteAMMTrustLines( if (sleItem->getFieldAmount(sfBalance) != beast::zero) { // LCOV_EXCL_START - JLOG(j.error()) - << "deleteAMMTrustLines: deleting trustline with " - "non-zero balance."; + JLOG(j.error()) << "deleteAMMTrustLines: deleting trustline with " + "non-zero balance."; return {tecINTERNAL, SkipEntry::No}; // LCOV_EXCL_STOP } - return { - deleteAMMTrustLine(sb, sleItem, ammAccountID, j), - SkipEntry::No}; + return {deleteAMMTrustLine(sb, sleItem, ammAccountID, j), SkipEntry::No}; }, j, maxTrustlinesToDelete); } TER -deleteAMMAccount( - Sandbox& sb, - Issue const& asset, - Issue const& asset2, - beast::Journal j) +deleteAMMAccount(Sandbox& sb, Issue const& asset, Issue const& asset2, beast::Journal j) { auto ammSle = sb.peek(keylet::amm(asset, asset2)); if (!ammSle) { // LCOV_EXCL_START - JLOG(j.error()) << "deleteAMMAccount: AMM object does not exist " - << asset << " " << asset2; + JLOG(j.error()) << "deleteAMMAccount: AMM object does not exist " << asset << " " << asset2; return tecINTERNAL; // LCOV_EXCL_STOP } @@ -282,20 +235,16 @@ deleteAMMAccount( if (!sleAMMRoot) { // LCOV_EXCL_START - JLOG(j.error()) << "deleteAMMAccount: AMM account does not exist " - << to_string(ammAccountID); + JLOG(j.error()) << "deleteAMMAccount: AMM account does not exist " << to_string(ammAccountID); return tecINTERNAL; // LCOV_EXCL_STOP } - if (auto const ter = - deleteAMMTrustLines(sb, ammAccountID, maxDeletableAMMTrustLines, j); - ter != tesSUCCESS) + if (auto const ter = deleteAMMTrustLines(sb, ammAccountID, maxDeletableAMMTrustLines, j); ter != tesSUCCESS) return ter; auto const ownerDirKeylet = keylet::ownerDir(ammAccountID); - if (!sb.dirRemove( - ownerDirKeylet, (*ammSle)[sfOwnerNode], ammSle->key(), false)) + if (!sb.dirRemove(ownerDirKeylet, (*ammSle)[sfOwnerNode], ammSle->key(), false)) { // LCOV_EXCL_START JLOG(j.error()) << "deleteAMMAccount: failed to remove dir link"; @@ -305,8 +254,7 @@ deleteAMMAccount( if (sb.exists(ownerDirKeylet) && !sb.emptyDirDelete(ownerDirKeylet)) { // LCOV_EXCL_START - JLOG(j.error()) << "deleteAMMAccount: cannot delete root dir node of " - << toBase58(ammAccountID); + JLOG(j.error()) << "deleteAMMAccount: cannot delete root dir node of " << toBase58(ammAccountID); return tecINTERNAL; // LCOV_EXCL_STOP } @@ -338,8 +286,7 @@ initializeFeeAuctionVote( // AMM creator gets the auction slot for free. // AuctionSlot is created on AMMCreate and updated on AMMDeposit // when AMM is in an empty state - if (rules.enabled(fixInnerObjTemplate) && - !ammSle->isFieldPresent(sfAuctionSlot)) + if (rules.enabled(fixInnerObjTemplate) && !ammSle->isFieldPresent(sfAuctionSlot)) { STObject auctionSlot = STObject::makeInnerObject(sfAuctionSlot); ammSle->set(std::move(auctionSlot)); @@ -348,9 +295,7 @@ initializeFeeAuctionVote( auctionSlot.setAccountID(sfAccount, account); // current + sec in 24h auto const expiration = - std::chrono::duration_cast( - view.header().parentCloseTime.time_since_epoch()) - .count() + + std::chrono::duration_cast(view.header().parentCloseTime.time_since_epoch()).count() + TOTAL_TIME_SLOT_SECS; auctionSlot.setFieldU32(sfExpiration, expiration); auctionSlot.setFieldAmount(sfPrice, STAmount{lptIssue, 0}); @@ -366,10 +311,7 @@ initializeFeeAuctionVote( } Expected -isOnlyLiquidityProvider( - ReadView const& view, - Issue const& ammIssue, - AccountID const& lpAccount) +isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID const& lpAccount) { // Liquidity Provider (LP) must have one LPToken trustline std::uint8_t nLPTokenTrustLines = 0; @@ -411,10 +353,8 @@ isOnlyLiquidityProvider( return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE auto const lowLimit = sle->getFieldAmount(sfLowLimit); auto const highLimit = sle->getFieldAmount(sfHighLimit); - auto const isLPTrustline = lowLimit.getIssuer() == lpAccount || - highLimit.getIssuer() == lpAccount; - auto const isLPTokenTrustline = - lowLimit.issue() == ammIssue || highLimit.issue() == ammIssue; + auto const isLPTrustline = lowLimit.getIssuer() == lpAccount || highLimit.getIssuer() == lpAccount; + auto const isLPTokenTrustline = lowLimit.issue() == ammIssue || highLimit.issue() == ammIssue; // Liquidity Provider trustline if (isLPTrustline) @@ -437,8 +377,7 @@ isOnlyLiquidityProvider( auto const uNodeNext = ownerDir->getFieldU64(sfIndexNext); if (uNodeNext == 0) { - if (nLPTokenTrustLines != 1 || nIOUTrustLines == 0 || - nIOUTrustLines > 2) + if (nLPTokenTrustLines != 1 || nIOUTrustLines == 0 || nIOUTrustLines > 2) return Unexpected(tecINTERNAL); // LCOV_EXCL_LINE return true; } @@ -454,15 +393,11 @@ verifyAndAdjustLPTokenBalance( std::shared_ptr& ammSle, AccountID const& account) { - if (auto const res = isOnlyLiquidityProvider(sb, lpTokens.issue(), account); - !res) + if (auto const res = isOnlyLiquidityProvider(sb, lpTokens.issue(), account); !res) return Unexpected(res.error()); else if (res.value()) { - if (withinRelativeDistance( - lpTokens, - ammSle->getFieldAmount(sfLPTokenBalance), - Number{1, -3})) + if (withinRelativeDistance(lpTokens, ammSle->getFieldAmount(sfLPTokenBalance), Number{1, -3})) { ammSle->setFieldAmount(sfLPTokenBalance, lpTokens); sb.update(ammSle); diff --git a/src/xrpld/app/misc/detail/AmendmentTable.cpp b/src/xrpld/app/misc/detail/AmendmentTable.cpp index 8ed9bc12c5..2942c8bde6 100644 --- a/src/xrpld/app/misc/detail/AmendmentTable.cpp +++ b/src/xrpld/app/misc/detail/AmendmentTable.cpp @@ -37,15 +37,12 @@ parseSection(Section const& section) boost::smatch match; if (!boost::regex_match(line, match, re1)) - Throw( - "Invalid entry '" + line + "' in [" + section.name() + "]"); + Throw("Invalid entry '" + line + "' in [" + section.name() + "]"); uint256 id; if (!id.parseHex(match[1])) - Throw( - "Invalid amendment ID '" + match[1] + "' in [" + - section.name() + "]"); + Throw("Invalid amendment ID '" + match[1] + "' in [" + section.name() + "]"); names.push_back(std::make_pair(id, match[2])); } @@ -98,9 +95,7 @@ public: // // Call with AmendmentTable::mutex_ locked. void - trustChanged( - hash_set const& allTrusted, - std::lock_guard const& lock) + trustChanged(hash_set const& allTrusted, std::lock_guard const& lock) { decltype(recordedVotes_) newRecordedVotes; newRecordedVotes.reserve(allTrusted.size()); @@ -158,25 +153,20 @@ public: // validators with these newest votes. for (auto const& val : valSet) { - auto const pkHuman = - toBase58(TokenType::NodePublic, val->getSignerPublic()); + auto const pkHuman = toBase58(TokenType::NodePublic, val->getSignerPublic()); // If this validation comes from one of our trusted validators... - if (auto const iter = recordedVotes_.find(val->getSignerPublic()); - iter != recordedVotes_.end()) + if (auto const iter = recordedVotes_.find(val->getSignerPublic()); iter != recordedVotes_.end()) { iter->second.timeout = newTimeout; if (val->isFieldPresent(sfAmendments)) { auto const& choices = val->getFieldV256(sfAmendments); iter->second.upVotes.assign(choices.begin(), choices.end()); - JLOG(j.debug()) - << "recordVotes: Validation from trusted " << pkHuman - << " has " << choices.size() << " amendment votes: " - << boost::algorithm::join( - iter->second.upVotes | - boost::adaptors::transformed( - to_string<256, void>), - ", "); + JLOG(j.debug()) << "recordVotes: Validation from trusted " << pkHuman << " has " << choices.size() + << " amendment votes: " + << boost::algorithm::join( + iter->second.upVotes | boost::adaptors::transformed(to_string<256, void>), + ", "); // TODO: Maybe transform using to_short_string once #5126 is // merged // @@ -187,15 +177,12 @@ public: { // This validator does not upVote any amendments right now. iter->second.upVotes.clear(); - JLOG(j.debug()) << "recordVotes: Validation from trusted " - << pkHuman << " has no amendment votes."; + JLOG(j.debug()) << "recordVotes: Validation from trusted " << pkHuman << " has no amendment votes."; } } else { - JLOG(j.debug()) - << "recordVotes: Ignoring validation from untrusted " - << pkHuman; + JLOG(j.debug()) << "recordVotes: Ignoring validation from untrusted " << pkHuman; } } @@ -203,26 +190,21 @@ public: std::for_each( recordedVotes_.begin(), recordedVotes_.end(), - [&closeTime, newTimeout, &j]( - decltype(recordedVotes_)::value_type& votes) { - auto const pkHuman = - toBase58(TokenType::NodePublic, votes.first); + [&closeTime, newTimeout, &j](decltype(recordedVotes_)::value_type& votes) { + auto const pkHuman = toBase58(TokenType::NodePublic, votes.first); if (!votes.second.timeout) { XRPL_ASSERT( votes.second.upVotes.empty(), "xrpl::TrustedVotes::recordVotes : received no " "upvotes"); - JLOG(j.debug()) - << "recordVotes: Have not received any " - "amendment votes from " - << pkHuman << " since last timeout or startup"; + JLOG(j.debug()) << "recordVotes: Have not received any " + "amendment votes from " + << pkHuman << " since last timeout or startup"; } else if (closeTime > votes.second.timeout) { - JLOG(j.debug()) - << "recordVotes: Timeout: Clearing votes from " - << pkHuman; + JLOG(j.debug()) << "recordVotes: Timeout: Clearing votes from " << pkHuman; votes.second.timeout.reset(); votes.second.upVotes.clear(); } @@ -233,10 +215,8 @@ public: "xrpl::TrustedVotes::recordVotes : votes not " "expired"); using namespace std::chrono; - auto const age = duration_cast( - newTimeout - *votes.second.timeout); - JLOG(j.debug()) << "recordVotes: Using " << age.count() - << "min old cached votes from " << pkHuman; + auto const age = duration_cast(newTimeout - *votes.second.timeout); + JLOG(j.debug()) << "recordVotes: Using " << age.count() << "min old cached votes from " << pkHuman; } }); } @@ -252,8 +232,7 @@ public: for (auto& validatorVotes : recordedVotes_) { XRPL_ASSERT( - validatorVotes.second.timeout || - validatorVotes.second.upVotes.empty(), + validatorVotes.second.timeout || validatorVotes.second.upVotes.empty(), "xrpl::TrustedVotes::getVotes : valid votes"); if (validatorVotes.second.timeout) ++available; @@ -303,10 +282,7 @@ private: int threshold_ = 0; public: - AmendmentSet( - Rules const& rules, - TrustedVotes const& trustedVotes, - std::lock_guard const& lock) + AmendmentSet(Rules const& rules, TrustedVotes const& trustedVotes, std::lock_guard const& lock) { // process validations for ledger before flag ledger. auto [trustedCount, newVotes] = trustedVotes.getVotes(rules, lock); @@ -317,8 +293,7 @@ public: threshold_ = std::max( 1L, static_cast( - (trustedValidations_ * amendmentMajorityCalcThreshold.num) / - amendmentMajorityCalcThreshold.den)); + (trustedValidations_ * amendmentMajorityCalcThreshold.num) / amendmentMajorityCalcThreshold.den)); } bool @@ -409,8 +384,7 @@ private: get(uint256 const& amendment, std::lock_guard const& lock); AmendmentState const* - get(uint256 const& amendment, - std::lock_guard const& lock) const; + get(uint256 const& amendment, std::lock_guard const& lock) const; // Injects amendment json into v. Must be called with mutex_ locked. void @@ -422,10 +396,7 @@ private: std::lock_guard const& lock) const; void - persistVote( - uint256 const& amendment, - std::string const& name, - AmendmentVote vote) const; + persistVote(uint256 const& amendment, std::string const& name, AmendmentVote vote) const; public: AmendmentTableImpl( @@ -467,10 +438,7 @@ public: needValidatedLedger(LedgerIndex seq) const override; void - doValidatedLedger( - LedgerIndex seq, - std::set const& enabled, - majorityAmendments_t const& majority) override; + doValidatedLedger(LedgerIndex seq, std::set const& enabled, majorityAmendments_t const& majority) override; void trustChanged(hash_set const& allTrusted) override; @@ -499,11 +467,7 @@ AmendmentTableImpl::AmendmentTableImpl( Section const& enabled, Section const& vetoed, beast::Journal journal) - : lastUpdateSeq_(0) - , majorityTime_(majorityTime) - , unsupportedEnabled_(false) - , j_(journal) - , db_(app.getWalletDB()) + : lastUpdateSeq_(0), majorityTime_(majorityTime), unsupportedEnabled_(false), j_(journal), db_(app.getWalletDB()) { std::lock_guard lock(mutex_); @@ -535,8 +499,7 @@ AmendmentTableImpl::AmendmentTableImpl( break; } - JLOG(j_.debug()) << "Amendment " << amendment << " (" << s.name - << ") is supported and will be " + JLOG(j_.debug()) << "Amendment " << amendment << " (" << s.name << ") is supported and will be " << (s.vote == AmendmentVote::up ? "up" : "down") << " voted by default if not enabled on the ledger."; } @@ -563,9 +526,8 @@ AmendmentTableImpl::AmendmentTableImpl( { if (featureVotesExist) { // If the table existed, warn about duplicate config info - JLOG(j_.warn()) - << "[veto_amendments] section in config file ignored" - " in favor of data in db/wallet.db."; + JLOG(j_.warn()) << "[veto_amendments] section in config file ignored" + " in favor of data in db/wallet.db."; break; } else @@ -576,10 +538,8 @@ AmendmentTableImpl::AmendmentTableImpl( } else { - JLOG(j_.warn()) - << "[veto_amendments] section in config has amendment " - << '(' << a.first << ", " << a.second - << ") both [veto_amendments] and [amendments]."; + JLOG(j_.warn()) << "[veto_amendments] section in config has amendment " << '(' << a.first << ", " + << a.second << ") both [veto_amendments] and [amendments]."; } } } @@ -595,22 +555,18 @@ AmendmentTableImpl::AmendmentTableImpl( if (!amendment_hash || !amendment_name || !vote) { // These fields should never have nulls, but check - Throw( - "Invalid FeatureVotes row in wallet.db"); + Throw("Invalid FeatureVotes row in wallet.db"); } if (!amend_hash.parseHex(*amendment_hash)) { - Throw( - "Invalid amendment ID '" + *amendment_hash + - " in wallet.db"); + Throw("Invalid amendment ID '" + *amendment_hash + " in wallet.db"); } if (*vote == AmendmentVote::down) { // Unknown amendments are effectively vetoed already if (auto s = get(amend_hash, lock)) { - JLOG(j_.info()) << "Amendment {" << *amendment_name << ", " - << amend_hash << "} is downvoted."; + JLOG(j_.info()) << "Amendment {" << *amendment_name << ", " << amend_hash << "} is downvoted."; if (!amendment_name->empty()) s->name = *amendment_name; // An obsolete amendment's vote can never be changed @@ -622,8 +578,7 @@ AmendmentTableImpl::AmendmentTableImpl( { AmendmentState& s = add(amend_hash, lock); - JLOG(j_.debug()) << "Amendment {" << *amendment_name << ", " - << amend_hash << "} is upvoted."; + JLOG(j_.debug()) << "Amendment {" << *amendment_name << ", " << amend_hash << "} is upvoted."; if (!amendment_name->empty()) s.name = *amendment_name; // An obsolete amendment's vote can never be changed @@ -634,28 +589,21 @@ AmendmentTableImpl::AmendmentTableImpl( } AmendmentState& -AmendmentTableImpl::add( - uint256 const& amendmentHash, - std::lock_guard const&) +AmendmentTableImpl::add(uint256 const& amendmentHash, std::lock_guard const&) { // call with the mutex held return amendmentMap_[amendmentHash]; } AmendmentState* -AmendmentTableImpl::get( - uint256 const& amendmentHash, - std::lock_guard const& lock) +AmendmentTableImpl::get(uint256 const& amendmentHash, std::lock_guard const& lock) { // Forward to the const version of get. - return const_cast( - std::as_const(*this).get(amendmentHash, lock)); + return const_cast(std::as_const(*this).get(amendmentHash, lock)); } AmendmentState const* -AmendmentTableImpl::get( - uint256 const& amendmentHash, - std::lock_guard const&) const +AmendmentTableImpl::get(uint256 const& amendmentHash, std::lock_guard const&) const { // call with the mutex held auto ret = amendmentMap_.find(amendmentHash); @@ -681,14 +629,9 @@ AmendmentTableImpl::find(std::string const& name) const } void -AmendmentTableImpl::persistVote( - uint256 const& amendment, - std::string const& name, - AmendmentVote vote) const +AmendmentTableImpl::persistVote(uint256 const& amendment, std::string const& name, AmendmentVote vote) const { - XRPL_ASSERT( - vote != AmendmentVote::obsolete, - "xrpl::AmendmentTableImpl::persistVote : valid vote input"); + XRPL_ASSERT(vote != AmendmentVote::obsolete, "xrpl::AmendmentTableImpl::persistVote : valid vote input"); auto db = db_.checkoutDb(); voteAmendment(*db, amendment, name, vote); } @@ -732,8 +675,7 @@ AmendmentTableImpl::enable(uint256 const& amendment) if (!s.supported) { - JLOG(j_.error()) << "Unsupported amendment " << amendment - << " activated."; + JLOG(j_.error()) << "Unsupported amendment " << amendment << " activated."; unsupportedEnabled_ = true; } @@ -782,8 +724,7 @@ AmendmentTableImpl::doValidation(std::set const& enabled) const amendments.reserve(amendmentMap_.size()); for (auto const& e : amendmentMap_) { - if (e.second.supported && e.second.vote == AmendmentVote::up && - (enabled.count(e.first) == 0)) + if (e.second.supported && e.second.vote == AmendmentVote::up && (enabled.count(e.first) == 0)) { amendments.push_back(e.first); JLOG(j_.info()) << "Voting for amendment " << e.second.name; @@ -812,8 +753,7 @@ AmendmentTableImpl::doVoting( majorityAmendments_t const& majorityAmendments, std::vector> const& valSet) { - JLOG(j_.trace()) << "voting at " << closeTime.time_since_epoch().count() - << ": " << enabledAmendments.size() << ", " + JLOG(j_.trace()) << "voting at " << closeTime.time_since_epoch().count() << ": " << enabledAmendments.size() << ", " << majorityAmendments.size() << ", " << valSet.size(); std::lock_guard lock(mutex_); @@ -822,11 +762,9 @@ AmendmentTableImpl::doVoting( previousTrustedVotes_.recordVotes(rules, valSet, closeTime, j_, lock); // Tally the most recent votes. - auto vote = - std::make_unique(rules, previousTrustedVotes_, lock); + auto vote = std::make_unique(rules, previousTrustedVotes_, lock); JLOG(j_.debug()) << "Counted votes from " << vote->trustedValidations() - << " valid trusted validations, threshold is: " - << vote->threshold(); + << " valid trusted validations, threshold is: " << vote->threshold(); // Map of amendments to the action to be taken for each one. The action is // the value of the flags in the pseudo-transaction @@ -855,13 +793,11 @@ AmendmentTableImpl::doVoting( auto const logStr = [&entry, &vote]() { std::stringstream ss; - ss << entry.first << " (" << entry.second.name << ") has " - << vote->votes(entry.first) << " votes"; + ss << entry.first << " (" << entry.second.name << ") has " << vote->votes(entry.first) << " votes"; return ss.str(); }(); - if (hasValMajority && !hasLedgerMajority && - entry.second.vote == AmendmentVote::up) + if (hasValMajority && !hasLedgerMajority && entry.second.vote == AmendmentVote::up) { // Ledger says no majority, validators say yes, and voting yes // locally @@ -875,8 +811,7 @@ AmendmentTableImpl::doVoting( actions[entry.first] = tfLostMajority; } else if ( - hasLedgerMajority && - ((*majorityTime + majorityTime_) <= closeTime) && + hasLedgerMajority && ((*majorityTime + majorityTime_) <= closeTime) && entry.second.vote == AmendmentVote::up) { // Ledger says majority held @@ -886,9 +821,7 @@ AmendmentTableImpl::doVoting( // Logging only below this point else if (hasValMajority && hasLedgerMajority) { - JLOG(j_.debug()) - << logStr - << ": amendment holding majority, waiting to be enabled"; + JLOG(j_.debug()) << logStr << ": amendment holding majority, waiting to be enabled"; } else if (!hasValMajority) { @@ -939,8 +872,7 @@ AmendmentTableImpl::doValidatedLedger( if (!s.supported) { - JLOG(j_.info()) << "Unsupported amendment " << hash - << " reached majority at " << to_string(time); + JLOG(j_.info()) << "Unsupported amendment " << hash << " reached majority at " << to_string(time); if (!firstUnsupportedExpected_ || firstUnsupportedExpected_ > time) firstUnsupportedExpected_ = time; } @@ -999,12 +931,7 @@ AmendmentTableImpl::getJson(bool isAdmin) const std::lock_guard lock(mutex_); for (auto const& e : amendmentMap_) { - injectJson( - ret[to_string(e.first)] = Json::objectValue, - e.first, - e.second, - isAdmin, - lock); + injectJson(ret[to_string(e.first)] = Json::objectValue, e.first, e.second, isAdmin, lock); } } return ret; @@ -1020,8 +947,7 @@ AmendmentTableImpl::getJson(uint256 const& amendmentID, bool isAdmin) const AmendmentState const* a = get(amendmentID, lock); if (a) { - Json::Value& jAmendment = - (ret[to_string(amendmentID)] = Json::objectValue); + Json::Value& jAmendment = (ret[to_string(amendmentID)] = Json::objectValue); injectJson(jAmendment, amendmentID, *a, isAdmin, lock); } } @@ -1038,8 +964,7 @@ make_AmendmentTable( Section const& vetoed, beast::Journal journal) { - return std::make_unique( - app, majorityTime, supported, enabled, vetoed, journal); + return std::make_unique(app, majorityTime, supported, enabled, vetoed, journal); } } // namespace xrpl diff --git a/src/xrpld/app/misc/detail/DelegateUtils.cpp b/src/xrpld/app/misc/detail/DelegateUtils.cpp index 027f2f1cc6..74ec55cdee 100644 --- a/src/xrpld/app/misc/detail/DelegateUtils.cpp +++ b/src/xrpld/app/misc/detail/DelegateUtils.cpp @@ -35,10 +35,8 @@ loadGranularPermission( for (auto const& permission : permissionArray) { auto const permissionValue = permission[sfPermissionValue]; - auto const granularValue = - static_cast(permissionValue); - auto const& type = - Permission::getInstance().getGranularTxType(granularValue); + auto const granularValue = static_cast(permissionValue); + auto const& type = Permission::getInstance().getGranularTxType(granularValue); if (type && *type == txType) granularPermissions.insert(granularValue); } diff --git a/src/xrpld/app/misc/detail/LendingHelpers.cpp b/src/xrpld/app/misc/detail/LendingHelpers.cpp index a8354ff049..106eeb9301 100644 --- a/src/xrpld/app/misc/detail/LendingHelpers.cpp +++ b/src/xrpld/app/misc/detail/LendingHelpers.cpp @@ -7,8 +7,7 @@ namespace xrpl { bool checkLendingProtocolDependencies(PreflightContext const& ctx) { - return ctx.rules.enabled(featureSingleAssetVault) && - VaultCreate::checkExtraFeatures(ctx); + return ctx.rules.enabled(featureSingleAssetVault) && VaultCreate::checkExtraFeatures(ctx); } LoanPaymentParts& @@ -38,8 +37,7 @@ LoanPaymentParts::operator+=(LoanPaymentParts const& other) bool LoanPaymentParts::operator==(LoanPaymentParts const& other) const { - return principalPaid == other.principalPaid && - interestPaid == other.interestPaid && + return principalPaid == other.principalPaid && interestPaid == other.interestPaid && valueChange == other.valueChange && feePaid == other.feePaid; } @@ -52,8 +50,7 @@ Number loanPeriodicRate(TenthBips32 interestRate, std::uint32_t paymentInterval) { // Need floating point math, since we're dividing by a large number - return tenthBipsOfValue(Number(paymentInterval), interestRate) / - secondsInYear; + return tenthBipsOfValue(Number(paymentInterval), interestRate) / secondsInYear; } /* Checks if a value is already rounded to the specified scale. @@ -63,8 +60,7 @@ loanPeriodicRate(TenthBips32 interestRate, std::uint32_t paymentInterval) bool isRounded(Asset const& asset, Number const& value, std::int32_t scale) { - return roundToAsset(asset, value, scale, Number::downward) == - roundToAsset(asset, value, scale, Number::upward); + return roundToAsset(asset, value, scale, Number::downward) == roundToAsset(asset, value, scale, Number::upward); } namespace detail { @@ -96,9 +92,7 @@ computeRaisedRate(Number const& periodicRate, std::uint32_t paymentsRemaining) * Equation (6) from XLS-66 spec, Section A-2 Equation Glossary */ Number -computePaymentFactor( - Number const& periodicRate, - std::uint32_t paymentsRemaining) +computePaymentFactor(Number const& periodicRate, std::uint32_t paymentsRemaining) { if (paymentsRemaining == 0) return numZero; @@ -107,8 +101,7 @@ computePaymentFactor( if (periodicRate == beast::zero) return Number{1} / paymentsRemaining; - Number const raisedRate = - computeRaisedRate(periodicRate, paymentsRemaining); + Number const raisedRate = computeRaisedRate(periodicRate, paymentsRemaining); return (periodicRate * raisedRate) / (raisedRate - 1); } @@ -119,10 +112,7 @@ computePaymentFactor( * Equation (7) from XLS-66 spec, Section A-2 Equation Glossary */ Number -loanPeriodicPayment( - Number const& principalOutstanding, - Number const& periodicRate, - std::uint32_t paymentsRemaining) +loanPeriodicPayment(Number const& principalOutstanding, Number const& periodicRate, std::uint32_t paymentsRemaining) { if (principalOutstanding == 0 || paymentsRemaining == 0) return 0; @@ -131,8 +121,7 @@ loanPeriodicPayment( if (periodicRate == beast::zero) return principalOutstanding / paymentsRemaining; - return principalOutstanding * - computePaymentFactor(periodicRate, paymentsRemaining); + return principalOutstanding * computePaymentFactor(periodicRate, paymentsRemaining); } /* Reverse-calculates principal from periodic payment amount. @@ -152,8 +141,7 @@ loanPrincipalFromPeriodicPayment( if (periodicRate == 0) return periodicPayment * paymentsRemaining; - return periodicPayment / - computePaymentFactor(periodicRate, paymentsRemaining); + return periodicPayment / computePaymentFactor(periodicRate, paymentsRemaining); } /* @@ -168,8 +156,7 @@ computeInterestAndFeeParts( TenthBips16 managementFeeRate, std::int32_t loanScale) { - auto const fee = - computeManagementFee(asset, interest, managementFeeRate, loanScale); + auto const fee = computeManagementFee(asset, interest, managementFeeRate, loanScale); return std::make_pair(interest - fee, fee); } @@ -241,8 +228,7 @@ loanAccruedInterest( // Division is more likely to introduce rounding errors, which will then get // amplified by multiplication. Therefore, we first multiply, and only then // divide. - return principalOutstanding * periodicRate * secondsSinceLastPayment / - paymentInterval; + return principalOutstanding * periodicRate * secondsSinceLastPayment / paymentInterval; } /* Applies a payment to the loan state and returns the breakdown of amounts @@ -266,8 +252,7 @@ doPayment( UInt32OptionalProxy& nextDueDateProxy, std::uint32_t paymentInterval) { - XRPL_ASSERT_PARTS( - nextDueDateProxy, "xrpl::detail::doPayment", "Next due date proxy set"); + XRPL_ASSERT_PARTS(nextDueDateProxy, "xrpl::detail::doPayment", "Next due date proxy set"); if (payment.specialCase == PaymentSpecialCase::final) { @@ -276,9 +261,7 @@ doPayment( "xrpl::detail::doPayment", "Full principal payment"); XRPL_ASSERT_PARTS( - totalValueOutstandingProxy == payment.trackedValueDelta, - "xrpl::detail::doPayment", - "Full value payment"); + totalValueOutstandingProxy == payment.trackedValueDelta, "xrpl::detail::doPayment", "Full value payment"); XRPL_ASSERT_PARTS( managementFeeOutstandingProxy == payment.trackedManagementFeeDelta, "xrpl::detail::doPayment", @@ -316,9 +299,7 @@ doPayment( "xrpl::detail::doPayment", "Partial principal payment"); XRPL_ASSERT_PARTS( - totalValueOutstandingProxy > payment.trackedValueDelta, - "xrpl::detail::doPayment", - "Partial value payment"); + totalValueOutstandingProxy > payment.trackedValueDelta, "xrpl::detail::doPayment", "Partial value payment"); // Management fees are expected to be relatively small, and could get to // zero before the loan is paid off XRPL_ASSERT_PARTS( @@ -336,8 +317,7 @@ doPayment( XRPL_ASSERT_PARTS( // Use an explicit cast because the template parameter can be // ValueProxy or Number - static_cast(principalOutstandingProxy) <= - static_cast(totalValueOutstandingProxy), + static_cast(principalOutstandingProxy) <= static_cast(totalValueOutstandingProxy), "xrpl::detail::doPayment", "principal does not exceed total"); @@ -348,26 +328,23 @@ doPayment( "xrpl::detail::doPayment", "fee outstanding stays valid"); - return LoanPaymentParts{ - // Principal paid is straightforward - it's the tracked delta - .principalPaid = payment.trackedPrincipalDelta, + return LoanPaymentParts{// Principal paid is straightforward - it's the tracked delta + .principalPaid = payment.trackedPrincipalDelta, - // Interest paid combines: - // 1. Tracked interest from the amortization schedule - // (derived from the tracked deltas) - // 2. Untracked interest (e.g., late payment penalties) - .interestPaid = - payment.trackedInterestPart() + payment.untrackedInterest, + // Interest paid combines: + // 1. Tracked interest from the amortization schedule + // (derived from the tracked deltas) + // 2. Untracked interest (e.g., late payment penalties) + .interestPaid = payment.trackedInterestPart() + payment.untrackedInterest, - // Value change represents how the loan's total value changed beyond - // normal amortization. - .valueChange = payment.untrackedInterest, + // Value change represents how the loan's total value changed beyond + // normal amortization. + .valueChange = payment.untrackedInterest, - // Fee paid combines: - // 1. Tracked management fees from the amortization schedule - // 2. Untracked fees (e.g., late payment fees, service fees) - .feePaid = - payment.trackedManagementFeeDelta + payment.untrackedManagementFee}; + // Fee paid combines: + // 1. Tracked management fees from the amortization schedule + // 2. Untracked fees (e.g., late payment fees, service fees) + .feePaid = payment.trackedManagementFeeDelta + payment.untrackedManagementFee}; } /* Simulates an overpayment to validate it won't break the loan's amortization. @@ -393,8 +370,8 @@ tryOverpayment( beast::Journal j) { // Calculate what the loan state SHOULD be theoretically (at full precision) - auto const theoreticalState = computeTheoreticalLoanState( - periodicPayment, periodicRate, paymentRemaining, managementFeeRate); + auto const theoreticalState = + computeTheoreticalLoanState(periodicPayment, periodicRate, paymentRemaining, managementFeeRate); // Calculate the accumulated rounding errors. These need to be preserved // across the re-amortization to maintain consistency with the loan's @@ -404,61 +381,40 @@ tryOverpayment( // Compute the new principal by applying the overpayment to the theoretical // principal. Use max with 0 to ensure we never go negative. - auto const newTheoreticalPrincipal = std::max( - theoreticalState.principalOutstanding - - overpaymentComponents.trackedPrincipalDelta, - Number{0}); + auto const newTheoreticalPrincipal = + std::max(theoreticalState.principalOutstanding - overpaymentComponents.trackedPrincipalDelta, Number{0}); // Compute new loan properties based on the reduced principal. This // recalculates the periodic payment, total value, and management fees // for the remaining payment schedule. auto newLoanProperties = computeLoanProperties( - asset, - newTheoreticalPrincipal, - periodicRate, - paymentRemaining, - managementFeeRate, - loanScale); + asset, newTheoreticalPrincipal, periodicRate, paymentRemaining, managementFeeRate, loanScale); - JLOG(j.debug()) << "new periodic payment: " - << newLoanProperties.periodicPayment - << ", new total value: " - << newLoanProperties.loanState.valueOutstanding - << ", first payment principal: " - << newLoanProperties.firstPaymentPrincipal; + JLOG(j.debug()) << "new periodic payment: " << newLoanProperties.periodicPayment + << ", new total value: " << newLoanProperties.loanState.valueOutstanding + << ", first payment principal: " << newLoanProperties.firstPaymentPrincipal; // Calculate what the new loan state should be with the new periodic payment // including rounding errors - auto const newTheoreticalState = computeTheoreticalLoanState( - newLoanProperties.periodicPayment, - periodicRate, - paymentRemaining, - managementFeeRate) + + auto const newTheoreticalState = + computeTheoreticalLoanState( + newLoanProperties.periodicPayment, periodicRate, paymentRemaining, managementFeeRate) + errors; - JLOG(j.debug()) << "new theoretical value: " - << newTheoreticalState.valueOutstanding << ", principal: " - << newTheoreticalState.principalOutstanding - << ", interest gross: " - << newTheoreticalState.interestOutstanding(); + JLOG(j.debug()) << "new theoretical value: " << newTheoreticalState.valueOutstanding + << ", principal: " << newTheoreticalState.principalOutstanding + << ", interest gross: " << newTheoreticalState.interestOutstanding(); // Update the loan state variables with the new values that include the // preserved rounding errors. This ensures the loan's tracked state remains // consistent with its payment history. auto const principalOutstanding = std::clamp( - roundToAsset( - asset, - newTheoreticalState.principalOutstanding, - loanScale, - Number::upward), + roundToAsset(asset, newTheoreticalState.principalOutstanding, loanScale, Number::upward), numZero, roundedOldState.principalOutstanding); auto const totalValueOutstanding = std::clamp( roundToAsset( - asset, - principalOutstanding + newTheoreticalState.interestOutstanding(), - loanScale, - Number::upward), + asset, principalOutstanding + newTheoreticalState.interestOutstanding(), loanScale, Number::upward), numZero, roundedOldState.valueOutstanding); auto const managementFeeOutstanding = std::clamp( @@ -466,8 +422,8 @@ tryOverpayment( numZero, roundedOldState.managementFeeDue); - auto const roundedNewState = constructLoanState( - totalValueOutstanding, principalOutstanding, managementFeeOutstanding); + auto const roundedNewState = + constructLoanState(totalValueOutstanding, principalOutstanding, managementFeeOutstanding); // Update newLoanProperties so that checkLoanGuards can make an accurate // evaluation. @@ -475,8 +431,7 @@ tryOverpayment( JLOG(j.debug()) << "new rounded value: " << roundedNewState.valueOutstanding << ", principal: " << roundedNewState.principalOutstanding - << ", interest gross: " - << roundedNewState.interestOutstanding(); + << ", interest gross: " << roundedNewState.interestOutstanding(); // check that the loan is still valid if (auto const ter = checkLoanGuards( @@ -499,8 +454,7 @@ tryOverpayment( // Validate that all computed properties are reasonable. These checks should // never fail under normal circumstances, but we validate defensively. - if (newLoanProperties.periodicPayment <= 0 || - newLoanProperties.loanState.valueOutstanding <= 0 || + if (newLoanProperties.periodicPayment <= 0 || newLoanProperties.loanState.valueOutstanding <= 0 || newLoanProperties.loanState.managementFeeDue < 0) { // LCOV_EXCL_START @@ -508,10 +462,8 @@ tryOverpayment( "properties are invalid. Does " "not compute. TotalValueOutstanding: " << newLoanProperties.loanState.valueOutstanding - << ", PeriodicPayment : " - << newLoanProperties.periodicPayment - << ", ManagementFeeOwedToBroker: " - << newLoanProperties.loanState.managementFeeDue; + << ", PeriodicPayment : " << newLoanProperties.periodicPayment + << ", ManagementFeeOwedToBroker: " << newLoanProperties.loanState.managementFeeDue; return Unexpected(tesSUCCESS); // LCOV_EXCL_STOP } @@ -521,8 +473,7 @@ tryOverpayment( // The change in loan management fee is equal to the change between the old // and the new outstanding management fees XRPL_ASSERT_PARTS( - deltas.managementFee == - roundedOldState.managementFeeDue - managementFeeOutstanding, + deltas.managementFee == roundedOldState.managementFeeDue - managementFeeOutstanding, "xrpl::detail::tryOverpayment", "no fee change"); @@ -550,12 +501,10 @@ tryOverpayment( // Value change includes both the reduction from paying down // principal (negative) and any untracked interest penalties // (positive, e.g., if the overpayment itself incurs a fee) - .valueChange = - valueChange + overpaymentComponents.untrackedInterest, + .valueChange = valueChange + overpaymentComponents.untrackedInterest, // Fee paid includes both the reduction in tracked management fees // and any untracked fees on the overpayment itself - .feePaid = overpaymentComponents.untrackedManagementFee + - overpaymentComponents.trackedManagementFeeDelta, + .feePaid = overpaymentComponents.untrackedManagementFee + overpaymentComponents.trackedManagementFeeDelta, }, newLoanProperties); } @@ -586,22 +535,17 @@ doOverpayment( TenthBips16 const managementFeeRate, beast::Journal j) { - auto const loanState = constructLoanState( - totalValueOutstandingProxy, - principalOutstandingProxy, - managementFeeOutstandingProxy); + auto const loanState = + constructLoanState(totalValueOutstandingProxy, principalOutstandingProxy, managementFeeOutstandingProxy); auto const periodicPayment = periodicPaymentProxy; - JLOG(j.debug()) - << "overpayment components:" - << ", totalValue before: " << *totalValueOutstandingProxy - << ", valueDelta: " << overpaymentComponents.trackedValueDelta - << ", principalDelta: " << overpaymentComponents.trackedPrincipalDelta - << ", managementFeeDelta: " - << overpaymentComponents.trackedManagementFeeDelta - << ", interestPart: " << overpaymentComponents.trackedInterestPart() - << ", untrackedInterest: " << overpaymentComponents.untrackedInterest - << ", totalDue: " << overpaymentComponents.totalDue - << ", payments remaining :" << paymentRemaining; + JLOG(j.debug()) << "overpayment components:" + << ", totalValue before: " << *totalValueOutstandingProxy + << ", valueDelta: " << overpaymentComponents.trackedValueDelta + << ", principalDelta: " << overpaymentComponents.trackedPrincipalDelta + << ", managementFeeDelta: " << overpaymentComponents.trackedManagementFeeDelta + << ", interestPart: " << overpaymentComponents.trackedInterestPart() + << ", untrackedInterest: " << overpaymentComponents.untrackedInterest + << ", totalDue: " << overpaymentComponents.totalDue << ", payments remaining :" << paymentRemaining; // Attempt to re-amortize the loan with the overpayment applied. // This modifies the temporary copies, leaving the proxies unchanged. @@ -628,9 +572,8 @@ doOverpayment( { // LCOV_EXCL_START JLOG(j.warn()) << "Overpayment not allowed: principal " - << "outstanding did not decrease. Before: " - << *principalOutstandingProxy << ". After: " - << newRoundedLoanState.principalOutstanding; + << "outstanding did not decrease. Before: " << *principalOutstandingProxy + << ". After: " << newRoundedLoanState.principalOutstanding; return Unexpected(tesSUCCESS); // LCOV_EXCL_STOP } @@ -641,38 +584,32 @@ doOverpayment( XRPL_ASSERT_PARTS( overpaymentComponents.trackedPrincipalDelta == - principalOutstandingProxy - - newRoundedLoanState.principalOutstanding, + principalOutstandingProxy - newRoundedLoanState.principalOutstanding, "xrpl::detail::doOverpayment", "principal change agrees"); // I'm not 100% sure the following asserts are correct. If in doubt, and // everything else works, remove any that cause trouble. - JLOG(j.debug()) - << "valueChange: " << loanPaymentParts.valueChange - << ", totalValue before: " << *totalValueOutstandingProxy - << ", totalValue after: " << newRoundedLoanState.valueOutstanding - << ", totalValue delta: " - << (totalValueOutstandingProxy - newRoundedLoanState.valueOutstanding) - << ", principalDelta: " << overpaymentComponents.trackedPrincipalDelta - << ", principalPaid: " << loanPaymentParts.principalPaid - << ", Computed difference: " - << overpaymentComponents.trackedPrincipalDelta - + JLOG(j.debug()) << "valueChange: " << loanPaymentParts.valueChange + << ", totalValue before: " << *totalValueOutstandingProxy + << ", totalValue after: " << newRoundedLoanState.valueOutstanding + << ", totalValue delta: " << (totalValueOutstandingProxy - newRoundedLoanState.valueOutstanding) + << ", principalDelta: " << overpaymentComponents.trackedPrincipalDelta + << ", principalPaid: " << loanPaymentParts.principalPaid << ", Computed difference: " + << overpaymentComponents.trackedPrincipalDelta - (totalValueOutstandingProxy - newRoundedLoanState.valueOutstanding); XRPL_ASSERT_PARTS( loanPaymentParts.valueChange == newRoundedLoanState.valueOutstanding - - (totalValueOutstandingProxy - - overpaymentComponents.trackedPrincipalDelta) + + (totalValueOutstandingProxy - overpaymentComponents.trackedPrincipalDelta) + overpaymentComponents.trackedInterestPart(), "xrpl::detail::doOverpayment", "interest paid agrees"); XRPL_ASSERT_PARTS( - overpaymentComponents.trackedPrincipalDelta == - loanPaymentParts.principalPaid, + overpaymentComponents.trackedPrincipalDelta == loanPaymentParts.principalPaid, "xrpl::detail::doOverpayment", "principal payment matches"); @@ -719,25 +656,18 @@ computeLatePayment( return Unexpected(tecTOO_SOON); // Calculate the penalty interest based on how long the payment is overdue. - auto const latePaymentInterest = loanLatePaymentInterest( - principalOutstanding, - lateInterestRate, - view.parentCloseTime(), - nextDueDate); + auto const latePaymentInterest = + loanLatePaymentInterest(principalOutstanding, lateInterestRate, view.parentCloseTime(), nextDueDate); // Round the late interest and split it between the vault (net interest) // and the broker (management fee portion). This lambda ensures we // round before splitting to maintain precision. auto const [roundedLateInterest, roundedLateManagementFee] = [&]() { - auto const interest = - roundToAsset(asset, latePaymentInterest, loanScale); - return computeInterestAndFeeParts( - asset, interest, managementFeeRate, loanScale); + auto const interest = roundToAsset(asset, latePaymentInterest, loanScale); + return computeInterestAndFeeParts(asset, interest, managementFeeRate, loanScale); }(); - XRPL_ASSERT( - roundedLateInterest >= 0, - "xrpl::detail::computeLatePayment : valid late interest"); + XRPL_ASSERT(roundedLateInterest >= 0, "xrpl::detail::computeLatePayment : valid late interest"); XRPL_ASSERT_PARTS( periodic.specialCase != PaymentSpecialCase::extra, "xrpl::detail::computeLatePayment", @@ -754,8 +684,7 @@ computeLatePayment( // 1. Regular service fee (from periodic.untrackedManagementFee) // 2. Late payment fee (fixed penalty) // 3. Management fee portion of late interest - periodic.untrackedManagementFee + latePaymentFee + - roundedLateManagementFee, + periodic.untrackedManagementFee + latePaymentFee + roundedLateManagementFee, // Untracked interest includes: // 1. Any untracked interest from the regular payment (usually 0) @@ -765,17 +694,14 @@ computeLatePayment( periodic.untrackedInterest + roundedLateInterest}; XRPL_ASSERT_PARTS( - isRounded(asset, late.totalDue, loanScale), - "xrpl::detail::computeLatePayment", - "total due is rounded"); + isRounded(asset, late.totalDue, loanScale), "xrpl::detail::computeLatePayment", "total due is rounded"); // Check that the borrower provided enough funds to cover the late payment. // The late payment is more expensive than a regular payment due to the // penalties. if (amount < late.totalDue) { - JLOG(j.warn()) << "Late loan payment amount is insufficient. Due: " - << late.totalDue << ", paid: " << amount; + JLOG(j.warn()) << "Late loan payment amount is insufficient. Due: " << late.totalDue << ", paid: " << amount; return Unexpected(tecINSUFFICIENT_PAYMENT); } @@ -833,8 +759,7 @@ computeFullPayment( // This theoretical (unrounded) value is used to compute interest and // penalties accurately. Number const theoreticalPrincipalOutstanding = - loanPrincipalFromPeriodicPayment( - periodicPayment, periodicRate, paymentRemaining); + loanPrincipalFromPeriodicPayment(periodicPayment, periodicRate, paymentRemaining); // Full payment interest includes both accrued interest (time since last // payment) and prepayment penalty (for closing early). @@ -850,10 +775,8 @@ computeFullPayment( // Split the full payment interest into net interest (to vault) and // management fee (to broker), applying proper rounding. auto const [roundedFullInterest, roundedFullManagementFee] = [&]() { - auto const interest = roundToAsset( - asset, fullPaymentInterest, loanScale, Number::downward); - return computeInterestAndFeeParts( - asset, interest, managementFeeRate, loanScale); + auto const interest = roundToAsset(asset, fullPaymentInterest, loanScale, Number::downward); + return computeInterestAndFeeParts(asset, interest, managementFeeRate, loanScale); }(); ExtendedPaymentComponents const full{ @@ -861,8 +784,7 @@ computeFullPayment( // Pay off all tracked outstanding balances: principal, interest, // and fees. // This marks the loan as complete (final payment). - .trackedValueDelta = principalOutstanding + - totalInterestOutstanding + managementFeeOutstanding, + .trackedValueDelta = principalOutstanding + totalInterestOutstanding + managementFeeOutstanding, .trackedPrincipalDelta = principalOutstanding, // All outstanding management fees are paid. This zeroes out the @@ -891,19 +813,14 @@ computeFullPayment( }; XRPL_ASSERT_PARTS( - isRounded(asset, full.totalDue, loanScale), - "xrpl::detail::computeFullPayment", - "total due is rounded"); + isRounded(asset, full.totalDue, loanScale), "xrpl::detail::computeFullPayment", "total due is rounded"); - JLOG(j.trace()) << "computeFullPayment result: periodicPayment: " - << periodicPayment << ", periodicRate: " << periodicRate - << ", paymentRemaining: " << paymentRemaining - << ", theoreticalPrincipalOutstanding: " - << theoreticalPrincipalOutstanding + JLOG(j.trace()) << "computeFullPayment result: periodicPayment: " << periodicPayment + << ", periodicRate: " << periodicRate << ", paymentRemaining: " << paymentRemaining + << ", theoreticalPrincipalOutstanding: " << theoreticalPrincipalOutstanding << ", fullPaymentInterest: " << fullPaymentInterest << ", roundedFullInterest: " << roundedFullInterest - << ", roundedFullManagementFee: " - << roundedFullManagementFee + << ", roundedFullManagementFee: " << roundedFullManagementFee << ", untrackedInterest: " << full.untrackedInterest; if (amount < full.totalDue) @@ -917,8 +834,7 @@ computeFullPayment( Number PaymentComponents::trackedInterestPart() const { - return trackedValueDelta - - (trackedPrincipalDelta + trackedManagementFeeDelta); + return trackedValueDelta - (trackedPrincipalDelta + trackedManagementFeeDelta); } /* Computes the breakdown of a regular periodic payment into principal, @@ -952,23 +868,17 @@ computePaymentComponents( TenthBips16 managementFeeRate) { XRPL_ASSERT_PARTS( - isRounded(asset, totalValueOutstanding, scale) && - isRounded(asset, principalOutstanding, scale) && + isRounded(asset, totalValueOutstanding, scale) && isRounded(asset, principalOutstanding, scale) && isRounded(asset, managementFeeOutstanding, scale), "xrpl::detail::computePaymentComponents", "Outstanding values are rounded"); - XRPL_ASSERT_PARTS( - paymentRemaining > 0, - "xrpl::detail::computePaymentComponents", - "some payments remaining"); + XRPL_ASSERT_PARTS(paymentRemaining > 0, "xrpl::detail::computePaymentComponents", "some payments remaining"); - auto const roundedPeriodicPayment = - roundPeriodicPayment(asset, periodicPayment, scale); + auto const roundedPeriodicPayment = roundPeriodicPayment(asset, periodicPayment, scale); // Final payment: pay off everything remaining, ignoring the normal // periodic payment amount. This ensures the loan completes cleanly. - if (paymentRemaining == 1 || - totalValueOutstanding <= roundedPeriodicPayment) + if (paymentRemaining == 1 || totalValueOutstanding <= roundedPeriodicPayment) { // If there's only one payment left, we need to pay off each of the loan // parts. @@ -981,23 +891,20 @@ computePaymentComponents( // Calculate what the loan state SHOULD be after this payment (the target). // This is computed at full precision using the theoretical amortization. - LoanState const trueTarget = computeTheoreticalLoanState( - periodicPayment, periodicRate, paymentRemaining - 1, managementFeeRate); + LoanState const trueTarget = + computeTheoreticalLoanState(periodicPayment, periodicRate, paymentRemaining - 1, managementFeeRate); // Round the target to the loan's scale to match how actual loan values // are stored. LoanState const roundedTarget = LoanState{ - .valueOutstanding = - roundToAsset(asset, trueTarget.valueOutstanding, scale), - .principalOutstanding = - roundToAsset(asset, trueTarget.principalOutstanding, scale), + .valueOutstanding = roundToAsset(asset, trueTarget.valueOutstanding, scale), + .principalOutstanding = roundToAsset(asset, trueTarget.principalOutstanding, scale), .interestDue = roundToAsset(asset, trueTarget.interestDue, scale), - .managementFeeDue = - roundToAsset(asset, trueTarget.managementFeeDue, scale)}; + .managementFeeDue = roundToAsset(asset, trueTarget.managementFeeDue, scale)}; // Get the current actual loan state from the ledger values - LoanState const currentLedgerState = constructLoanState( - totalValueOutstanding, principalOutstanding, managementFeeOutstanding); + LoanState const currentLedgerState = + constructLoanState(totalValueOutstanding, principalOutstanding, managementFeeOutstanding); // The difference between current and target states gives us the payment // components. Any discrepancies from accumulated rounding are captured @@ -1014,8 +921,7 @@ computePaymentComponents( "principal delta not greater than outstanding"); // Cap each component to never exceed what's actually outstanding - deltas.principal = - std::min(deltas.principal, currentLedgerState.principalOutstanding); + deltas.principal = std::min(deltas.principal, currentLedgerState.principalOutstanding); XRPL_ASSERT_PARTS( deltas.interest <= currentLedgerState.interestDue, @@ -1052,10 +958,7 @@ computePaymentComponents( component -= part; excess -= part; } - XRPL_ASSERT_PARTS( - excess >= beast::zero, - "xrpl::detail::computePaymentComponents", - "excess non-negative"); + XRPL_ASSERT_PARTS(excess >= beast::zero, "xrpl::detail::computePaymentComponents", "excess non-negative"); }; // Helper to reduce deltas when they collectively exceed a limit. // Order matters: we prefer to reduce interest first (most flexible), @@ -1069,8 +972,7 @@ computePaymentComponents( // Check if deltas exceed the total outstanding value. This should never // happen due to earlier caps, but handle it defensively. - Number totalOverpayment = - deltas.total() - currentLedgerState.valueOutstanding; + Number totalOverpayment = deltas.total() - currentLedgerState.valueOutstanding; if (totalOverpayment > beast::zero) { @@ -1086,9 +988,7 @@ computePaymentComponents( Number shortage = roundedPeriodicPayment - deltas.total(); XRPL_ASSERT_PARTS( - isRounded(asset, shortage, scale), - "xrpl::detail::computePaymentComponents", - "shortage is rounded"); + isRounded(asset, shortage, scale), "xrpl::detail::computePaymentComponents", "shortage is rounded"); if (shortage < beast::zero) { @@ -1101,31 +1001,24 @@ computePaymentComponents( // At this point, shortage >= 0 means we're paying less than the full // periodic payment (due to rounding or component caps). // shortage < 0 would mean we're trying to pay more than allowed (bug). - XRPL_ASSERT_PARTS( - shortage >= beast::zero, - "xrpl::detail::computePaymentComponents", - "no shortage or excess"); + XRPL_ASSERT_PARTS(shortage >= beast::zero, "xrpl::detail::computePaymentComponents", "no shortage or excess"); // Final validation that all components are valid XRPL_ASSERT_PARTS( - deltas.total() == - deltas.principal + deltas.interest + deltas.managementFee, + deltas.total() == deltas.principal + deltas.interest + deltas.managementFee, "xrpl::detail::computePaymentComponents", "total value adds up"); XRPL_ASSERT_PARTS( - deltas.principal >= beast::zero && - deltas.principal <= currentLedgerState.principalOutstanding, + deltas.principal >= beast::zero && deltas.principal <= currentLedgerState.principalOutstanding, "xrpl::detail::computePaymentComponents", "valid principal result"); XRPL_ASSERT_PARTS( - deltas.interest >= beast::zero && - deltas.interest <= currentLedgerState.interestDue, + deltas.interest >= beast::zero && deltas.interest <= currentLedgerState.interestDue, "xrpl::detail::computePaymentComponents", "valid interest result"); XRPL_ASSERT_PARTS( - deltas.managementFee >= beast::zero && - deltas.managementFee <= currentLedgerState.managementFeeDue, + deltas.managementFee >= beast::zero && deltas.managementFee <= currentLedgerState.managementFeeDue, "xrpl::detail::computePaymentComponents", "valid fee result"); @@ -1136,12 +1029,9 @@ computePaymentComponents( // Final safety clamp to ensure no value exceeds its outstanding balance return PaymentComponents{ - .trackedValueDelta = std::clamp( - deltas.total(), numZero, currentLedgerState.valueOutstanding), - .trackedPrincipalDelta = std::clamp( - deltas.principal, numZero, currentLedgerState.principalOutstanding), - .trackedManagementFeeDelta = std::clamp( - deltas.managementFee, numZero, currentLedgerState.managementFeeDue), + .trackedValueDelta = std::clamp(deltas.total(), numZero, currentLedgerState.valueOutstanding), + .trackedPrincipalDelta = std::clamp(deltas.principal, numZero, currentLedgerState.principalOutstanding), + .trackedManagementFeeDelta = std::clamp(deltas.managementFee, numZero, currentLedgerState.managementFeeDue), }; } @@ -1180,22 +1070,16 @@ computeOverpaymentComponents( // First, deduct the fixed overpayment fee from the total amount. // This reduces the effective payment that will be applied to the loan. // Equation (22) from XLS-66 spec, Section A-2 Equation Glossary - Number const overpaymentFee = roundToAsset( - asset, tenthBipsOfValue(overpayment, overpaymentFeeRate), loanScale); + Number const overpaymentFee = roundToAsset(asset, tenthBipsOfValue(overpayment, overpaymentFeeRate), loanScale); // Calculate the penalty interest on the effective payment amount. // This interest doesn't follow the normal amortization schedule - it's // a one-time charge for paying early. // Equation (20) and (21) from XLS-66 spec, Section A-2 Equation Glossary - auto const [roundedOverpaymentInterest, roundedOverpaymentManagementFee] = - [&]() { - auto const interest = roundToAsset( - asset, - tenthBipsOfValue(overpayment, overpaymentInterestRate), - loanScale); - return detail::computeInterestAndFeeParts( - asset, interest, managementFeeRate, loanScale); - }(); + auto const [roundedOverpaymentInterest, roundedOverpaymentManagementFee] = [&]() { + auto const interest = roundToAsset(asset, tenthBipsOfValue(overpayment, overpaymentInterestRate), loanScale); + return detail::computeInterestAndFeeParts(asset, interest, managementFeeRate, loanScale); + }(); auto const result = detail::ExtendedPaymentComponents{ // Build the payment components, after fees and penalty @@ -1203,8 +1087,8 @@ computeOverpaymentComponents( // reduction. detail::PaymentComponents{ .trackedValueDelta = overpayment - overpaymentFee, - .trackedPrincipalDelta = overpayment - roundedOverpaymentInterest - - roundedOverpaymentManagementFee - overpaymentFee, + .trackedPrincipalDelta = + overpayment - roundedOverpaymentInterest - roundedOverpaymentManagementFee - overpaymentFee, .trackedManagementFeeDelta = roundedOverpaymentManagementFee, .specialCase = detail::PaymentSpecialCase::extra}, // Untracked management fee is the fixed overpayment fee @@ -1271,8 +1155,7 @@ checkLoanGuards( LoanProperties const& properties, beast::Journal j) { - auto const totalInterestOutstanding = - properties.loanState.valueOutstanding - principalRequested; + auto const totalInterestOutstanding = properties.loanState.valueOutstanding - principalRequested; // Guard 1: if there is no computed total interest over the life of the // loan for a non-zero interest rate, we cannot properly amortize the // loan @@ -1280,8 +1163,7 @@ checkLoanGuards( { // Unless this is a zero-interest loan, there must be some interest // due on the loan, even if it's (measurable) dust - JLOG(j.warn()) << "Loan for " << principalRequested - << " with interest has no interest due"; + JLOG(j.warn()) << "Loan for " << principalRequested << " with interest has no interest due"; return tecPRECISION_LOSS; } // Guard 1a: If there is any interest computed over the life of the @@ -1289,8 +1171,7 @@ checkLoanGuards( if (!expectInterest && totalInterestOutstanding > 0) { // LCOV_EXCL_START - JLOG(j.warn()) << "Loan for " << principalRequested - << " with no interest has interest due"; + JLOG(j.warn()) << "Loan for " << principalRequested << " with no interest has interest due"; return tecINTERNAL; // LCOV_EXCL_STOP } @@ -1311,12 +1192,10 @@ checkLoanGuards( // Guard 3: If the periodic payment is so small that it can't even be // rounded to a representable value, then the loan can't be paid. Also, // avoids dividing by 0. - auto const roundedPayment = roundPeriodicPayment( - vaultAsset, properties.periodicPayment, properties.loanScale); + auto const roundedPayment = roundPeriodicPayment(vaultAsset, properties.periodicPayment, properties.loanScale); if (roundedPayment == beast::zero) { - JLOG(j.warn()) << "Loan Periodic payment (" - << properties.periodicPayment << ") rounds to 0. "; + JLOG(j.warn()) << "Loan Periodic payment (" << properties.periodicPayment << ") rounds to 0. "; return tecPRECISION_LOSS; } @@ -1326,14 +1205,11 @@ checkLoanGuards( { NumberRoundModeGuard mg(Number::upward); - if (std::int64_t const computedPayments{ - properties.loanState.valueOutstanding / roundedPayment}; + if (std::int64_t const computedPayments{properties.loanState.valueOutstanding / roundedPayment}; computedPayments != paymentTotal) { - JLOG(j.warn()) << "Loan Periodic payment (" - << properties.periodicPayment << ") rounding (" - << roundedPayment << ") on a total value of " - << properties.loanState.valueOutstanding + JLOG(j.warn()) << "Loan Periodic payment (" << properties.periodicPayment << ") rounding (" + << roundedPayment << ") on a total value of " << properties.loanState.valueOutstanding << " can not complete the loan in the specified " "number of payments (" << computedPayments << " != " << paymentTotal << ")"; @@ -1360,12 +1236,7 @@ computeFullPaymentInterest( TenthBips32 closeInterestRate) { auto const accruedInterest = detail::loanAccruedInterest( - theoreticalPrincipalOutstanding, - periodicRate, - parentCloseTime, - startDate, - prevPaymentDate, - paymentInterval); + theoreticalPrincipalOutstanding, periodicRate, parentCloseTime, startDate, prevPaymentDate, paymentInterval); XRPL_ASSERT( accruedInterest >= 0, "xrpl::detail::computeFullPaymentInterest : valid accrued " @@ -1416,31 +1287,23 @@ computeTheoreticalLoanState( { if (paymentRemaining == 0) { - return LoanState{ - .valueOutstanding = 0, - .principalOutstanding = 0, - .interestDue = 0, - .managementFeeDue = 0}; + return LoanState{.valueOutstanding = 0, .principalOutstanding = 0, .interestDue = 0, .managementFeeDue = 0}; } // Equation (30) from XLS-66 spec, Section A-2 Equation Glossary Number const totalValueOutstanding = periodicPayment * paymentRemaining; Number const principalOutstanding = - detail::loanPrincipalFromPeriodicPayment( - periodicPayment, periodicRate, paymentRemaining); + detail::loanPrincipalFromPeriodicPayment(periodicPayment, periodicRate, paymentRemaining); // Equation (31) from XLS-66 spec, Section A-2 Equation Glossary - Number const interestOutstandingGross = - totalValueOutstanding - principalOutstanding; + Number const interestOutstandingGross = totalValueOutstanding - principalOutstanding; // Equation (32) from XLS-66 spec, Section A-2 Equation Glossary - Number const managementFeeOutstanding = - tenthBipsOfValue(interestOutstandingGross, managementFeeRate); + Number const managementFeeOutstanding = tenthBipsOfValue(interestOutstandingGross, managementFeeRate); // Equation (33) from XLS-66 spec, Section A-2 Equation Glossary - Number const interestOutstandingNet = - interestOutstandingGross - managementFeeOutstanding; + Number const interestOutstandingNet = interestOutstandingGross - managementFeeOutstanding; return LoanState{ .valueOutstanding = totalValueOutstanding, @@ -1481,8 +1344,7 @@ constructLoanState( return LoanState{ .valueOutstanding = totalValueOutstanding, .principalOutstanding = principalOutstanding, - .interestDue = totalValueOutstanding - principalOutstanding - - managementFeeOutstanding, + .interestDue = totalValueOutstanding - principalOutstanding - managementFeeOutstanding, .managementFeeDue = managementFeeOutstanding}; } @@ -1490,9 +1352,7 @@ LoanState constructRoundedLoanState(SLE::const_ref loan) { return constructLoanState( - loan->at(sfTotalValueOutstanding), - loan->at(sfPrincipalOutstanding), - loan->at(sfManagementFeeOutstanding)); + loan->at(sfTotalValueOutstanding), loan->at(sfPrincipalOutstanding), loan->at(sfManagementFeeOutstanding)); } /* @@ -1502,17 +1362,9 @@ constructRoundedLoanState(SLE::const_ref loan) * Equation (32) from XLS-66 spec, Section A-2 Equation Glossary */ Number -computeManagementFee( - Asset const& asset, - Number const& value, - TenthBips32 managementFeeRate, - std::int32_t scale) +computeManagementFee(Asset const& asset, Number const& value, TenthBips32 managementFeeRate, std::int32_t scale) { - return roundToAsset( - asset, - tenthBipsOfValue(value, managementFeeRate), - scale, - Number::downward); + return roundToAsset(asset, tenthBipsOfValue(value, managementFeeRate), scale, Number::downward); } /* @@ -1534,16 +1386,9 @@ computeLoanProperties( std::int32_t minimumScale) { auto const periodicRate = loanPeriodicRate(interestRate, paymentInterval); - XRPL_ASSERT( - interestRate == 0 || periodicRate > 0, - "xrpl::computeLoanProperties : valid rate"); + XRPL_ASSERT(interestRate == 0 || periodicRate > 0, "xrpl::computeLoanProperties : valid rate"); return computeLoanProperties( - asset, - principalOutstanding, - periodicRate, - paymentsRemaining, - managementFeeRate, - minimumScale); + asset, principalOutstanding, periodicRate, paymentsRemaining, managementFeeRate, minimumScale); } /* @@ -1563,13 +1408,11 @@ computeLoanProperties( TenthBips32 managementFeeRate, std::int32_t minimumScale) { - auto const periodicPayment = detail::loanPeriodicPayment( - principalOutstanding, periodicRate, paymentsRemaining); + auto const periodicPayment = detail::loanPeriodicPayment(principalOutstanding, periodicRate, paymentsRemaining); auto const [totalValueOutstanding, loanScale] = [&]() { // only round up if there should be interest - NumberRoundModeGuard mg( - periodicRate == 0 ? Number::to_nearest : Number::upward); + NumberRoundModeGuard mg(periodicRate == 0 ? Number::to_nearest : Number::upward); // Use STAmount's internal rounding instead of roundToAsset, because // we're going to use this result to determine the scale for all the // other rounding. @@ -1583,8 +1426,7 @@ computeLoanProperties( auto const loanScale = std::max(minimumScale, amount.exponent()); XRPL_ASSERT_PARTS( (amount.integral() && loanScale == 0) || - (!amount.integral() && - loanScale >= static_cast(amount).exponent()), + (!amount.integral() && loanScale >= static_cast(amount).exponent()), "xrpl::computeLoanProperties", "loanScale value fits expectations"); @@ -1598,14 +1440,11 @@ computeLoanProperties( // Since we just figured out the loan scale, we haven't been able to // validate that the principal fits in it, so to allow this function to // succeed, round it here, and let the caller do the validation. - auto const roundedPrincipalOutstanding = roundToAsset( - asset, principalOutstanding, loanScale, Number::to_nearest); + auto const roundedPrincipalOutstanding = roundToAsset(asset, principalOutstanding, loanScale, Number::to_nearest); // Equation (31) from XLS-66 spec, Section A-2 Equation Glossary - auto const totalInterestOutstanding = - totalValueOutstanding - roundedPrincipalOutstanding; - auto const feeOwedToBroker = computeManagementFee( - asset, totalInterestOutstanding, managementFeeRate, loanScale); + auto const totalInterestOutstanding = totalValueOutstanding - roundedPrincipalOutstanding; + auto const feeOwedToBroker = computeManagementFee(asset, totalInterestOutstanding, managementFeeRate, loanScale); // Compute the principal part of the first payment. This is needed // because the principal part may be rounded down to zero, which @@ -1613,30 +1452,20 @@ computeLoanProperties( auto const firstPaymentPrincipal = [&]() { // Compute the parts for the first payment. Ensure that the // principal payment will actually change the principal. - auto const startingState = computeTheoreticalLoanState( - periodicPayment, - periodicRate, - paymentsRemaining, - managementFeeRate); + auto const startingState = + computeTheoreticalLoanState(periodicPayment, periodicRate, paymentsRemaining, managementFeeRate); - auto const firstPaymentState = computeTheoreticalLoanState( - periodicPayment, - periodicRate, - paymentsRemaining - 1, - managementFeeRate); + auto const firstPaymentState = + computeTheoreticalLoanState(periodicPayment, periodicRate, paymentsRemaining - 1, managementFeeRate); // The unrounded principal part needs to be large enough to affect // the principal. What to do if not is left to the caller - return startingState.principalOutstanding - - firstPaymentState.principalOutstanding; + return startingState.principalOutstanding - firstPaymentState.principalOutstanding; }(); return LoanProperties{ .periodicPayment = periodicPayment, - .loanState = constructLoanState( - totalValueOutstanding, - roundedPrincipalOutstanding, - feeOwedToBroker), + .loanState = constructLoanState(totalValueOutstanding, roundedPrincipalOutstanding, feeOwedToBroker), .loanScale = loanScale, .firstPaymentPrincipal = firstPaymentPrincipal, }; @@ -1700,29 +1529,23 @@ loanMakePayment( // Compute the periodic rate that will be used for calculations // throughout Number const periodicRate = loanPeriodicRate(interestRate, paymentInterval); - XRPL_ASSERT( - interestRate == 0 || periodicRate > 0, - "xrpl::loanMakePayment : valid rate"); + XRPL_ASSERT(interestRate == 0 || periodicRate > 0, "xrpl::loanMakePayment : valid rate"); - XRPL_ASSERT( - *totalValueOutstandingProxy > 0, - "xrpl::loanMakePayment : valid total value"); + XRPL_ASSERT(*totalValueOutstandingProxy > 0, "xrpl::loanMakePayment : valid total value"); view.update(loan); // ------------------------------------------------------------- // A late payment not flagged as late overrides all other options. - if (paymentType != LoanPaymentType::late && - hasExpired(view, nextDueDateProxy)) + if (paymentType != LoanPaymentType::late && hasExpired(view, nextDueDateProxy)) { // If the payment is late, and the late flag was not set, it's not // valid JLOG(j.warn()) << "Loan payment is overdue. Use the tfLoanLatePayment " "transaction " "flag to make a late payment. Loan was created on " - << startDate << ", prev payment due date is " - << prevPaymentDateProxy << ", next payment due date is " - << nextDueDateProxy << ", ledger time is " + << startDate << ", prev payment due date is " << prevPaymentDateProxy + << ", next payment due date is " << nextDueDateProxy << ", ledger time is " << view.parentCloseTime().time_since_epoch().count(); return Unexpected(tecEXPIRED); } @@ -1732,13 +1555,10 @@ loanMakePayment( if (paymentType == LoanPaymentType::full) { TenthBips32 const closeInterestRate{loan->at(sfCloseInterestRate)}; - Number const closePaymentFee = - roundToAsset(asset, loan->at(sfClosePaymentFee), loanScale); + Number const closePaymentFee = roundToAsset(asset, loan->at(sfClosePaymentFee), loanScale); - LoanState const roundedLoanState = constructLoanState( - totalValueOutstandingProxy, - principalOutstandingProxy, - managementFeeOutstandingProxy); + LoanState const roundedLoanState = + constructLoanState(totalValueOutstandingProxy, principalOutstandingProxy, managementFeeOutstandingProxy); if (auto const fullPaymentComponents = detail::computeFullPayment( asset, @@ -1797,10 +1617,7 @@ loanMakePayment( paymentRemainingProxy, managementFeeRate), serviceFee}; - XRPL_ASSERT_PARTS( - periodic.trackedPrincipalDelta >= 0, - "xrpl::loanMakePayment", - "regular payment valid principal"); + XRPL_ASSERT_PARTS(periodic.trackedPrincipalDelta >= 0, "xrpl::loanMakePayment", "regular payment valid principal"); // ------------------------------------------------------------- // late payment handling @@ -1850,8 +1667,7 @@ loanMakePayment( // regular periodic payment handling XRPL_ASSERT_PARTS( - paymentType == LoanPaymentType::regular || - paymentType == LoanPaymentType::overpayment, + paymentType == LoanPaymentType::regular || paymentType == LoanPaymentType::overpayment, "xrpl::loanMakePayment", "regular payment type"); @@ -1860,15 +1676,12 @@ loanMakePayment( Number totalPaid; std::size_t numPayments = 0; - while ((amount >= (totalPaid + periodic.totalDue)) && - paymentRemainingProxy > 0 && + while ((amount >= (totalPaid + periodic.totalDue)) && paymentRemainingProxy > 0 && numPayments < loanMaximumPaymentsPerTransaction) { // Try to make more payments XRPL_ASSERT_PARTS( - periodic.trackedPrincipalDelta >= 0, - "xrpl::loanMakePayment", - "payment pays non-negative principal"); + periodic.trackedPrincipalDelta >= 0, "xrpl::loanMakePayment", "payment pays non-negative principal"); totalPaid += periodic.totalDue; totalParts += detail::doPayment( @@ -1883,8 +1696,7 @@ loanMakePayment( ++numPayments; XRPL_ASSERT_PARTS( - (periodic.specialCase == detail::PaymentSpecialCase::final) == - (paymentRemainingProxy == 0), + (periodic.specialCase == detail::PaymentSpecialCase::final) == (paymentRemainingProxy == 0), "xrpl::loanMakePayment", "final payment is the final payment"); @@ -1908,46 +1720,32 @@ loanMakePayment( if (numPayments == 0) { - JLOG(j.warn()) << "Regular loan payment amount is insufficient. Due: " - << periodic.totalDue << ", paid: " << amount; + JLOG(j.warn()) << "Regular loan payment amount is insufficient. Due: " << periodic.totalDue + << ", paid: " << amount; return Unexpected(tecINSUFFICIENT_PAYMENT); } XRPL_ASSERT_PARTS( - totalParts.principalPaid + totalParts.interestPaid + - totalParts.feePaid == - totalPaid, + totalParts.principalPaid + totalParts.interestPaid + totalParts.feePaid == totalPaid, "xrpl::loanMakePayment", "payment parts add up"); - XRPL_ASSERT_PARTS( - totalParts.valueChange == 0, - "xrpl::loanMakePayment", - "no value change"); + XRPL_ASSERT_PARTS(totalParts.valueChange == 0, "xrpl::loanMakePayment", "no value change"); // ------------------------------------------------------------- // overpayment handling - if (paymentType == LoanPaymentType::overpayment && - loan->isFlag(lsfLoanOverpayment) && paymentRemainingProxy > 0 && + if (paymentType == LoanPaymentType::overpayment && loan->isFlag(lsfLoanOverpayment) && paymentRemainingProxy > 0 && totalPaid < amount && numPayments < loanMaximumPaymentsPerTransaction) { - TenthBips32 const overpaymentInterestRate{ - loan->at(sfOverpaymentInterestRate)}; + TenthBips32 const overpaymentInterestRate{loan->at(sfOverpaymentInterestRate)}; TenthBips32 const overpaymentFeeRate{loan->at(sfOverpaymentFee)}; // It shouldn't be possible for the overpayment to be greater than // totalValueOutstanding, because that would have been processed as // another normal payment. But cap it just in case. - Number const overpayment = - std::min(amount - totalPaid, *totalValueOutstandingProxy); + Number const overpayment = std::min(amount - totalPaid, *totalValueOutstandingProxy); - detail::ExtendedPaymentComponents const overpaymentComponents = - detail::computeOverpaymentComponents( - asset, - loanScale, - overpayment, - overpaymentInterestRate, - overpaymentFeeRate, - managementFeeRate); + detail::ExtendedPaymentComponents const overpaymentComponents = detail::computeOverpaymentComponents( + asset, loanScale, overpayment, overpaymentInterestRate, overpaymentFeeRate, managementFeeRate); // Don't process an overpayment if the whole amount (or more!) // gets eaten by fees and interest. @@ -1985,19 +1783,15 @@ loanMakePayment( // Check the final results are rounded, to double-check that the // intermediate steps were rounded. XRPL_ASSERT( - isRounded(asset, totalParts.principalPaid, loanScale) && - totalParts.principalPaid >= beast::zero, + isRounded(asset, totalParts.principalPaid, loanScale) && totalParts.principalPaid >= beast::zero, "xrpl::loanMakePayment : total principal paid is valid"); XRPL_ASSERT( - isRounded(asset, totalParts.interestPaid, loanScale) && - totalParts.interestPaid >= beast::zero, + isRounded(asset, totalParts.interestPaid, loanScale) && totalParts.interestPaid >= beast::zero, "xrpl::loanMakePayment : total interest paid is valid"); XRPL_ASSERT( - isRounded(asset, totalParts.valueChange, loanScale), - "xrpl::loanMakePayment : loan value change is valid"); + isRounded(asset, totalParts.valueChange, loanScale), "xrpl::loanMakePayment : loan value change is valid"); XRPL_ASSERT( - isRounded(asset, totalParts.feePaid, loanScale) && - totalParts.feePaid >= beast::zero, + isRounded(asset, totalParts.feePaid, loanScale) && totalParts.feePaid >= beast::zero, "xrpl::loanMakePayment : fee paid is valid"); return totalParts; } diff --git a/src/xrpld/app/misc/detail/LoadFeeTrack.cpp b/src/xrpld/app/misc/detail/LoadFeeTrack.cpp index 6166656aee..91a40c6a9d 100644 --- a/src/xrpld/app/misc/detail/LoadFeeTrack.cpp +++ b/src/xrpld/app/misc/detail/LoadFeeTrack.cpp @@ -32,8 +32,7 @@ LoadFeeTrack::raiseLocalFee() if (origFee == localTxnLoadFee_) return false; - JLOG(j_.debug()) << "Local load fee raised from " << origFee << " to " - << localTxnLoadFee_; + JLOG(j_.debug()) << "Local load fee raised from " << origFee << " to " << localTxnLoadFee_; return true; } @@ -53,8 +52,7 @@ LoadFeeTrack::lowerLocalFee() if (origFee == localTxnLoadFee_) return false; - JLOG(j_.debug()) << "Local load fee lowered from " << origFee << " to " - << localTxnLoadFee_; + JLOG(j_.debug()) << "Local load fee lowered from " << origFee << " to " << localTxnLoadFee_; return true; } @@ -62,11 +60,7 @@ LoadFeeTrack::lowerLocalFee() // Scale using load as well as base rate XRPAmount -scaleFeeLoad( - XRPAmount fee, - LoadFeeTrack const& feeTrack, - Fees const& fees, - bool bUnlimited) +scaleFeeLoad(XRPAmount fee, LoadFeeTrack const& feeTrack, Fees const& fees, bool bUnlimited) { if (fee == 0) return fee; @@ -83,8 +77,7 @@ scaleFeeLoad( // fee = fee * feeFactor / (lftNormalFee); // without overflow, and as accurately as possible - auto const result = mulDiv( - fee, feeFactor, safe_cast(feeTrack.getLoadBase())); + auto const result = mulDiv(fee, feeFactor, safe_cast(feeTrack.getLoadBase())); if (!result) Throw("scaleFeeLoad"); return *result; diff --git a/src/xrpld/app/misc/detail/Manifest.cpp b/src/xrpld/app/misc/detail/Manifest.cpp index 59a1325e32..c226407231 100644 --- a/src/xrpld/app/misc/detail/Manifest.cpp +++ b/src/xrpld/app/misc/detail/Manifest.cpp @@ -130,45 +130,31 @@ deserializeManifest(Slice s, beast::Journal journal) return std::nullopt; } - std::string const serialized( - reinterpret_cast(s.data()), s.size()); + std::string const serialized(reinterpret_cast(s.data()), s.size()); // If the manifest is revoked, then the signingKey will be unseated return Manifest(serialized, masterKey, signingKey, seq, domain); } catch (std::exception const& ex) { - JLOG(journal.error()) - << "Exception in " << __func__ << ": " << ex.what(); + JLOG(journal.error()) << "Exception in " << __func__ << ": " << ex.what(); return std::nullopt; } } template Stream& -logMftAct( - Stream& s, - std::string const& action, - PublicKey const& pk, - std::uint32_t seq) +logMftAct(Stream& s, std::string const& action, PublicKey const& pk, std::uint32_t seq) { - s << "Manifest: " << action - << ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq - << ";"; + s << "Manifest: " << action << ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq << ";"; return s; } template Stream& -logMftAct( - Stream& s, - std::string const& action, - PublicKey const& pk, - std::uint32_t seq, - std::uint32_t oldSeq) +logMftAct(Stream& s, std::string const& action, PublicKey const& pk, std::uint32_t seq, std::uint32_t oldSeq) { - s << "Manifest: " << action - << ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq + s << "Manifest: " << action << ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq << ";OldSeq: " << oldSeq << ";"; return s; } @@ -247,11 +233,8 @@ loadValidatorToken(std::vector const& blob, beast::Journal journal) { std::string tokenStr; - tokenStr.reserve(std::accumulate( - blob.cbegin(), - blob.cend(), - std::size_t(0), - [](std::size_t init, std::string const& s) { + tokenStr.reserve( + std::accumulate(blob.cbegin(), blob.cend(), std::size_t(0), [](std::size_t init, std::string const& s) { return init + s.size(); })); @@ -281,8 +264,7 @@ loadValidatorToken(std::vector const& blob, beast::Journal journal) } catch (std::exception const& ex) { - JLOG(journal.error()) - << "Exception in " << __func__ << ": " << ex.what(); + JLOG(journal.error()) << "Exception in " << __func__ << ": " << ex.what(); return std::nullopt; } } @@ -304,8 +286,7 @@ ManifestCache::getMasterKey(PublicKey const& pk) const { std::shared_lock lock{mutex_}; - if (auto const iter = signingToMasterKeys_.find(pk); - iter != signingToMasterKeys_.end()) + if (auto const iter = signingToMasterKeys_.find(pk); iter != signingToMasterKeys_.end()) return iter->second; return pk; @@ -369,11 +350,8 @@ ManifestCache::applyManifest(Manifest m) // comment below), `checkSignature` only needs to be set to true on the // first run. auto prewriteCheck = - [this, &m](auto const& iter, bool checkSignature, auto const& lock) - -> std::optional { - XRPL_ASSERT( - lock.owns_lock(), - "xrpl::ManifestCache::applyManifest::prewriteCheck : locked"); + [this, &m](auto const& iter, bool checkSignature, auto const& lock) -> std::optional { + XRPL_ASSERT(lock.owns_lock(), "xrpl::ManifestCache::applyManifest::prewriteCheck : locked"); (void)lock; // not used. parameter is present to ensure the mutex is // locked when the lambda is called. if (iter != map_.end() && m.sequence <= iter->second.sequence) @@ -383,12 +361,7 @@ ManifestCache::applyManifest(Manifest m) // several cases including when we receive manifests from a peer who // doesn't have the latest data. if (auto stream = j_.debug()) - logMftAct( - stream, - "Stale", - m.masterKey, - m.sequence, - iter->second.sequence); + logMftAct(stream, "Stale", m.masterKey, m.sequence, iter->second.sequence); return ManifestDisposition::stale; } @@ -413,11 +386,9 @@ ManifestCache::applyManifest(Manifest m) // Sanity check: the master key of this manifest should not be used as // the ephemeral key of another manifest: - if (auto const x = signingToMasterKeys_.find(m.masterKey); - x != signingToMasterKeys_.end()) + if (auto const x = signingToMasterKeys_.find(m.masterKey); x != signingToMasterKeys_.end()) { - JLOG(j_.warn()) << to_string(m) - << ": Master key already used as ephemeral key for " + JLOG(j_.warn()) << to_string(m) << ": Master key already used as ephemeral key for " << toBase58(TokenType::NodePublic, x->second); return ManifestDisposition::badMasterKey; @@ -436,22 +407,17 @@ ManifestCache::applyManifest(Manifest m) // Sanity check: the ephemeral key of this manifest should not be // used as the master or ephemeral key of another manifest: - if (auto const x = signingToMasterKeys_.find(*m.signingKey); - x != signingToMasterKeys_.end()) + if (auto const x = signingToMasterKeys_.find(*m.signingKey); x != signingToMasterKeys_.end()) { - JLOG(j_.warn()) - << to_string(m) - << ": Ephemeral key already used as ephemeral key for " - << toBase58(TokenType::NodePublic, x->second); + JLOG(j_.warn()) << to_string(m) << ": Ephemeral key already used as ephemeral key for " + << toBase58(TokenType::NodePublic, x->second); return ManifestDisposition::badEphemeralKey; } if (auto const x = map_.find(*m.signingKey); x != map_.end()) { - JLOG(j_.warn()) - << to_string(m) << ": Ephemeral key used as master key for " - << to_string(x->second); + JLOG(j_.warn()) << to_string(m) << ": Ephemeral key used as master key for " << to_string(x->second); return ManifestDisposition::badEphemeralKey; } @@ -462,8 +428,7 @@ ManifestCache::applyManifest(Manifest m) { std::shared_lock sl{mutex_}; - if (auto d = - prewriteCheck(map_.find(m.masterKey), /*checkSig*/ true, sl)) + if (auto d = prewriteCheck(map_.find(m.masterKey), /*checkSig*/ true, sl)) return *d; } @@ -500,12 +465,7 @@ ManifestCache::applyManifest(Manifest m) // An ephemeral key was revoked and superseded by a new key. This is // expected, but should happen infrequently. if (auto stream = j_.info()) - logMftAct( - stream, - "AcceptedUpdate", - m.masterKey, - m.sequence, - iter->second.sequence); + logMftAct(stream, "AcceptedUpdate", m.masterKey, m.sequence, iter->second.sequence); signingToMasterKeys_.erase(*iter->second.signingKey); @@ -564,17 +524,14 @@ ManifestCache::load( configRevocation.cbegin(), configRevocation.cend(), std::size_t(0), - [](std::size_t init, std::string const& s) { - return init + s.size(); - })); + [](std::size_t init, std::string const& s) { return init + s.size(); })); for (auto const& line : configRevocation) revocationStr += boost::algorithm::trim_copy(line); auto mo = deserializeManifest(base64_decode(revocationStr)); - if (!mo || !mo->revoked() || - applyManifest(std::move(*mo)) == ManifestDisposition::invalid) + if (!mo || !mo->revoked() || applyManifest(std::move(*mo)) == ManifestDisposition::invalid) { JLOG(j_.error()) << "Invalid validator key revocation in config"; return false; diff --git a/src/xrpld/app/misc/detail/Transaction.cpp b/src/xrpld/app/misc/detail/Transaction.cpp index 77a8897d9c..61a2a36695 100644 --- a/src/xrpld/app/misc/detail/Transaction.cpp +++ b/src/xrpld/app/misc/detail/Transaction.cpp @@ -12,10 +12,7 @@ namespace xrpl { -Transaction::Transaction( - std::shared_ptr const& stx, - std::string& reason, - Application& app) noexcept +Transaction::Transaction(std::shared_ptr const& stx, std::string& reason, Application& app) noexcept : mTransaction(stx), mApp(app), j_(app.journal("Ledger")) { try @@ -83,8 +80,7 @@ Transaction::transactionFromSQL( Blob const& rawTxn, Application& app) { - std::uint32_t const inLedger = - rangeCheckedCast(ledgerSeq.value_or(0)); + std::uint32_t const inLedger = rangeCheckedCast(ledgerSeq.value_or(0)); SerialIter it(makeSlice(rawTxn)); auto txn = std::make_shared(it); @@ -96,31 +92,21 @@ Transaction::transactionFromSQL( return tr; } -std::variant< - std::pair, std::shared_ptr>, - TxSearched> +std::variant, std::shared_ptr>, TxSearched> Transaction::load(uint256 const& id, Application& app, error_code_i& ec) { return load(id, app, std::nullopt, ec); } -std::variant< - std::pair, std::shared_ptr>, - TxSearched> -Transaction::load( - uint256 const& id, - Application& app, - ClosedInterval const& range, - error_code_i& ec) +std::variant, std::shared_ptr>, TxSearched> +Transaction::load(uint256 const& id, Application& app, ClosedInterval const& range, error_code_i& ec) { using op = std::optional>; return load(id, app, op{range}, ec); } -std::variant< - std::pair, std::shared_ptr>, - TxSearched> +std::variant, std::shared_ptr>, TxSearched> Transaction::load( uint256 const& id, Application& app, @@ -142,8 +128,7 @@ Json::Value Transaction::getJson(JsonOptions options, bool binary) const { // Note, we explicitly suppress `include_date` option here - Json::Value ret( - mTransaction->getJson(options & ~JsonOptions::include_date, binary)); + Json::Value ret(mTransaction->getJson(options & ~JsonOptions::include_date, binary)); // NOTE Binary STTx::getJson output might not be a JSON object if (ret.isObject() && mLedgerIndex) @@ -173,8 +158,7 @@ Transaction::getJson(JsonOptions options, bool binary) const if (mTxnSeq && netID) { - std::optional const ctid = - RPC::encodeCTID(mLedgerIndex, *mTxnSeq, *netID); + std::optional const ctid = RPC::encodeCTID(mLedgerIndex, *mTxnSeq, *netID); if (ctid) ret[jss::ctid] = *ctid; } diff --git a/src/xrpld/app/misc/detail/TxQ.cpp b/src/xrpld/app/misc/detail/TxQ.cpp index 01abcc9c7d..61741b73f0 100644 --- a/src/xrpld/app/misc/detail/TxQ.cpp +++ b/src/xrpld/app/misc/detail/TxQ.cpp @@ -55,38 +55,27 @@ getLastLedgerSequence(STTx const& tx) static FeeLevel64 increase(FeeLevel64 level, std::uint32_t increasePercent) { - return mulDiv(level, 100 + increasePercent, 100) - .value_or(static_cast(xrpl::muldiv_max)); + return mulDiv(level, 100 + increasePercent, 100).value_or(static_cast(xrpl::muldiv_max)); } ////////////////////////////////////////////////////////////////////////// std::size_t -TxQ::FeeMetrics::update( - Application& app, - ReadView const& view, - bool timeLeap, - TxQ::Setup const& setup) +TxQ::FeeMetrics::update(Application& app, ReadView const& view, bool timeLeap, TxQ::Setup const& setup) { std::vector feeLevels; auto const txBegin = view.txs.begin(); auto const txEnd = view.txs.end(); auto const size = std::distance(txBegin, txEnd); feeLevels.reserve(size); - std::for_each(txBegin, txEnd, [&](auto const& tx) { - feeLevels.push_back(getFeeLevelPaid(view, *tx.first)); - }); + std::for_each(txBegin, txEnd, [&](auto const& tx) { feeLevels.push_back(getFeeLevelPaid(view, *tx.first)); }); std::sort(feeLevels.begin(), feeLevels.end()); - XRPL_ASSERT( - size == feeLevels.size(), - "xrpl::TxQ::FeeMetrics::update : fee levels size"); + XRPL_ASSERT(size == feeLevels.size(), "xrpl::TxQ::FeeMetrics::update : fee levels size"); JLOG((timeLeap ? j_.warn() : j_.debug())) - << "Ledger " << view.header().seq << " has " << size - << " transactions. " - << "Ledgers are processing " << (timeLeap ? "slowly" : "as expected") - << ". Expected transactions is currently " << txnsExpected_ - << " and multiplier is " << escalationMultiplier_; + << "Ledger " << view.header().seq << " has " << size << " transactions. " + << "Ledgers are processing " << (timeLeap ? "slowly" : "as expected") << ". Expected transactions is currently " + << txnsExpected_ << " and multiplier is " << escalationMultiplier_; if (timeLeap) { @@ -95,22 +84,17 @@ TxQ::FeeMetrics::update( auto const cutPct = 100 - setup.slowConsensusDecreasePercent; // upperLimit must be >= minimumTxnCount_ or std::clamp can give // unexpected results - auto const upperLimit = std::max( - mulDiv(txnsExpected_, cutPct, 100).value_or(xrpl::muldiv_max), - minimumTxnCount_); + auto const upperLimit = + std::max(mulDiv(txnsExpected_, cutPct, 100).value_or(xrpl::muldiv_max), minimumTxnCount_); txnsExpected_ = std::clamp( - mulDiv(size, cutPct, 100).value_or(xrpl::muldiv_max), - minimumTxnCount_, - upperLimit); + mulDiv(size, cutPct, 100).value_or(xrpl::muldiv_max), minimumTxnCount_, upperLimit); recentTxnCounts_.clear(); } else if (size > txnsExpected_ || size > targetTxnCount_) { recentTxnCounts_.push_back( - mulDiv(size, 100 + setup.normalConsensusIncreasePercent, 100) - .value_or(xrpl::muldiv_max)); - auto const iter = - std::max_element(recentTxnCounts_.begin(), recentTxnCounts_.end()); + mulDiv(size, 100 + setup.normalConsensusIncreasePercent, 100).value_or(xrpl::muldiv_max)); + auto const iter = std::max_element(recentTxnCounts_.begin(), recentTxnCounts_.end()); BOOST_ASSERT(iter != recentTxnCounts_.end()); auto const next = [&] { // Grow quickly: If the max_element is >= the @@ -139,14 +123,11 @@ TxQ::FeeMetrics::update( // evaluates to the middle element; for an even // number of elements, it will add the two elements // on either side of the "middle" and average them. - escalationMultiplier_ = - (feeLevels[size / 2] + feeLevels[(size - 1) / 2] + FeeLevel64{1}) / - 2; - escalationMultiplier_ = - std::max(escalationMultiplier_, setup.minimumEscalationMultiplier); + escalationMultiplier_ = (feeLevels[size / 2] + feeLevels[(size - 1) / 2] + FeeLevel64{1}) / 2; + escalationMultiplier_ = std::max(escalationMultiplier_, setup.minimumEscalationMultiplier); } - JLOG(j_.debug()) << "Expected transactions updated to " << txnsExpected_ - << " and multiplier updated to " << escalationMultiplier_; + JLOG(j_.debug()) << "Expected transactions updated to " << txnsExpected_ << " and multiplier updated to " + << escalationMultiplier_; return size; } @@ -205,10 +186,7 @@ static_assert(sumOfFirstSquares(0x1FFFFF).first == true, ""); static_assert(sumOfFirstSquares(0x1FFFFF).second == 0x2AAAA8AAAAB00000ul, ""); static_assert(sumOfFirstSquares(0x200000).first == false, ""); -static_assert( - sumOfFirstSquares(0x200000).second == - std::numeric_limits::max(), - ""); +static_assert(sumOfFirstSquares(0x200000).second == std::numeric_limits::max(), ""); } // namespace detail @@ -250,8 +228,7 @@ TxQ::FeeMetrics::escalatedSeriesFeeLevel( // are nearly nil. if (!sumNlast.first) return {sumNlast.first, FeeLevel64{sumNlast.second}}; - auto const totalFeeLevel = mulDiv( - multiplier, sumNlast.second - sumNcurrent.second, target * target); + auto const totalFeeLevel = mulDiv(multiplier, sumNlast.second - sumNcurrent.second, target * target); return {totalFeeLevel.has_value(), *totalFeeLevel}; } @@ -280,18 +257,15 @@ ApplyResult TxQ::MaybeTx::apply(Application& app, OpenView& view, beast::Journal j) { // If the rules or flags change, preflight again - XRPL_ASSERT( - pfResult, "xrpl::TxQ::MaybeTx::apply : preflight result is set"); + XRPL_ASSERT(pfResult, "xrpl::TxQ::MaybeTx::apply : preflight result is set"); NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)}; if (pfResult->rules != view.rules() || pfResult->flags != flags) { - JLOG(j.debug()) << "Queued transaction " << txID - << " rules or flags have changed. Flags from " + JLOG(j.debug()) << "Queued transaction " << txID << " rules or flags have changed. Flags from " << pfResult->flags << " to " << flags; - pfResult.emplace( - preflight(app, view.rules(), pfResult->tx, flags, pfResult->j)); + pfResult.emplace(preflight(app, view.rules(), pfResult->tx, flags, pfResult->j)); } auto pcresult = preclaim(*pfResult, app, view); @@ -299,8 +273,7 @@ TxQ::MaybeTx::apply(Application& app, OpenView& view, beast::Journal j) return doApply(pcresult, app, view); } -TxQ::TxQAccount::TxQAccount(std::shared_ptr const& txn) - : TxQAccount(txn->getAccountID(sfAccount)) +TxQ::TxQAccount::TxQAccount(std::shared_ptr const& txn) : TxQAccount(txn->getAccountID(sfAccount)) { } @@ -325,11 +298,8 @@ TxQ::TxQAccount::add(MaybeTx&& txn) auto const seqProx = txn.seqProxy; auto result = transactions.emplace(seqProx, std::move(txn)); - XRPL_ASSERT( - result.second, "xrpl::TxQ::TxQAccount::add : emplace succeeded"); - XRPL_ASSERT( - &result.first->second != &txn, - "xrpl::TxQ::TxQAccount::add : transaction moved"); + XRPL_ASSERT(result.second, "xrpl::TxQ::TxQAccount::add : emplace succeeded"); + XRPL_ASSERT(&result.first->second != &txn, "xrpl::TxQ::TxQAccount::add : transaction moved"); return result.first->second; } @@ -342,8 +312,7 @@ TxQ::TxQAccount::remove(SeqProxy seqProx) ////////////////////////////////////////////////////////////////////////// -TxQ::TxQ(Setup const& setup, beast::Journal j) - : setup_(setup), j_(j), feeMetrics_(setup, j), maxSize_(std::nullopt) +TxQ::TxQ(Setup const& setup, beast::Journal j) : setup_(setup), j_(j), feeMetrics_(setup, j), maxSize_(std::nullopt) { } @@ -356,8 +325,7 @@ template bool TxQ::isFull() const { - static_assert( - fillPercentage > 0 && fillPercentage <= 100, "Invalid fill percentage"); + static_assert(fillPercentage > 0 && fillPercentage <= 100, "Invalid fill percentage"); return maxSize_ && byFee_.size() >= (*maxSize_ * fillPercentage / 100); } @@ -375,8 +343,7 @@ TxQ::canBeHeld( // AccountTxnID is not supported by the transaction // queue yet, but should be added in the future. // tapFAIL_HARD transactions are never held - if (tx.isFieldPresent(sfPreviousTxnID) || - tx.isFieldPresent(sfAccountTxnID) || (flags & tapFAIL_HARD)) + if (tx.isFieldPresent(sfPreviousTxnID) || tx.isFieldPresent(sfAccountTxnID) || (flags & tapFAIL_HARD)) return telCAN_NOT_QUEUE; { @@ -384,8 +351,7 @@ TxQ::canBeHeld( // promise to stick around for long enough that it has // a realistic chance of getting into a ledger. auto const lastValid = getLastLedgerSequence(tx); - if (lastValid && - *lastValid < view.header().seq + setup_.minimumLastLedgerBuffer) + if (lastValid && *lastValid < view.header().seq + setup_.minimumLastLedgerBuffer) return telCAN_NOT_QUEUE; } @@ -428,8 +394,7 @@ TxQ::canBeHeld( } auto -TxQ::erase(TxQ::FeeMultiSet::const_iterator_type candidateIter) - -> FeeMultiSet::iterator_type +TxQ::erase(TxQ::FeeMultiSet::const_iterator_type candidateIter) -> FeeMultiSet::iterator_type { auto& txQAccount = byAccount_.at(candidateIter->account); auto const seqProx = candidateIter->seqProxy; @@ -444,42 +409,33 @@ TxQ::erase(TxQ::FeeMultiSet::const_iterator_type candidateIter) } auto -TxQ::eraseAndAdvance(TxQ::FeeMultiSet::const_iterator_type candidateIter) - -> FeeMultiSet::iterator_type +TxQ::eraseAndAdvance(TxQ::FeeMultiSet::const_iterator_type candidateIter) -> FeeMultiSet::iterator_type { auto& txQAccount = byAccount_.at(candidateIter->account); - auto const accountIter = - txQAccount.transactions.find(candidateIter->seqProxy); - XRPL_ASSERT( - accountIter != txQAccount.transactions.end(), - "xrpl::TxQ::eraseAndAdvance : account found"); + auto const accountIter = txQAccount.transactions.find(candidateIter->seqProxy); + XRPL_ASSERT(accountIter != txQAccount.transactions.end(), "xrpl::TxQ::eraseAndAdvance : account found"); // Note that sequence-based transactions must be applied in sequence order // from smallest to largest. But ticket-based transactions can be // applied in any order. XRPL_ASSERT( - candidateIter->seqProxy.isTicket() || - accountIter == txQAccount.transactions.begin(), + candidateIter->seqProxy.isTicket() || accountIter == txQAccount.transactions.begin(), "xrpl::TxQ::eraseAndAdvance : ticket or sequence"); XRPL_ASSERT( - byFee_.iterator_to(accountIter->second) == candidateIter, - "xrpl::TxQ::eraseAndAdvance : found in byFee"); + byFee_.iterator_to(accountIter->second) == candidateIter, "xrpl::TxQ::eraseAndAdvance : found in byFee"); auto const accountNextIter = std::next(accountIter); // Check if the next transaction for this account is earlier in the queue, // which means we skipped it earlier, and need to try it again. auto const feeNextIter = std::next(candidateIter); - bool const useAccountNext = - accountNextIter != txQAccount.transactions.end() && + bool const useAccountNext = accountNextIter != txQAccount.transactions.end() && accountNextIter->first > candidateIter->seqProxy && - (feeNextIter == byFee_.end() || - byFee_.value_comp()(accountNextIter->second, *feeNextIter)); + (feeNextIter == byFee_.end() || byFee_.value_comp()(accountNextIter->second, *feeNextIter)); auto const candidateNextIter = byFee_.erase(candidateIter); txQAccount.transactions.erase(accountIter); - return useAccountNext ? byFee_.iterator_to(accountNextIter->second) - : candidateNextIter; + return useAccountNext ? byFee_.iterator_to(accountNextIter->second) : candidateNextIter; } auto @@ -519,19 +475,16 @@ TxQ::tryClearAccountQueueUpThruTx( auto endTxIter = accountIter->second.transactions.lower_bound(tSeqProx); auto const dist = std::distance(beginTxIter, endTxIter); - auto const requiredTotalFeeLevel = FeeMetrics::escalatedSeriesFeeLevel( - metricsSnapshot, view, txExtraCount, dist + 1); + auto const requiredTotalFeeLevel = + FeeMetrics::escalatedSeriesFeeLevel(metricsSnapshot, view, txExtraCount, dist + 1); // If the computation for the total manages to overflow (however extremely // unlikely), then there's no way we can confidently verify if the queue // can be cleared. if (!requiredTotalFeeLevel.first) return {telINSUF_FEE_P, false}; - auto const totalFeeLevelPaid = std::accumulate( - beginTxIter, - endTxIter, - feeLevelPaid, - [](auto const& total, auto const& txn) { + auto const totalFeeLevelPaid = + std::accumulate(beginTxIter, endTxIter, feeLevelPaid, [](auto const& total, auto const& txn) { return total + txn.second.feeLevel; }); @@ -586,8 +539,7 @@ TxQ::tryClearAccountQueueUpThruTx( // queue. endTxIter = erase(accountIter->second, beginTxIter, endTxIter); // If `tx` is replacing a queued tx, delete that one, too. - if (endTxIter != accountIter->second.transactions.end() && - endTxIter->first == tSeqProx) + if (endTxIter != accountIter->second.transactions.end() && endTxIter->first == tSeqProx) erase(accountIter->second, endTxIter, std::next(endTxIter)); } @@ -708,12 +660,7 @@ TxQ::tryClearAccountQueueUpThruTx( // beyond that limit are rejected. // ApplyResult -TxQ::apply( - Application& app, - OpenView& view, - std::shared_ptr const& tx, - ApplyFlags flags, - beast::Journal j) +TxQ::apply(Application& app, OpenView& view, std::shared_ptr const& tx, ApplyFlags flags, beast::Journal j) { NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)}; @@ -746,8 +693,7 @@ TxQ::apply( // If the transaction needs a Ticket is that Ticket in the ledger? SeqProxy const acctSeqProx = SeqProxy::sequence((*sleAccount)[sfSequence]); SeqProxy const txSeqProx = tx->getSeqProxy(); - if (txSeqProx.isTicket() && - !view.exists(keylet::ticket(account, txSeqProx))) + if (txSeqProx.isTicket() && !view.exists(keylet::ticket(account, txSeqProx))) { if (txSeqProx.value() < acctSeqProx.value()) // The ticket number is low enough that it should already be @@ -775,10 +721,7 @@ TxQ::apply( // to individually check each queued ticket against the ledger. struct TxIter { - TxIter( - TxQAccount::TxMap::iterator first_, - TxQAccount::TxMap::iterator end_) - : first(first_), end(end_) + TxIter(TxQAccount::TxMap::iterator first_, TxQAccount::TxMap::iterator end_) : first(first_), end(end_) { } @@ -786,17 +729,13 @@ TxQ::apply( TxQAccount::TxMap::iterator end; }; - std::optional const txIter = - [accountIter, - accountIsInQueue, - acctSeqProx]() -> std::optional { + std::optional const txIter = [accountIter, accountIsInQueue, acctSeqProx]() -> std::optional { if (!accountIsInQueue) return {}; // Find the first transaction in the queue that we might apply. TxQAccount::TxMap& acctTxs = accountIter->second.transactions; - TxQAccount::TxMap::iterator const firstIter = - acctTxs.lower_bound(acctSeqProx); + TxQAccount::TxMap::iterator const firstIter = acctTxs.lower_bound(acctSeqProx); if (firstIter == acctTxs.end()) // Even though there may be transactions in the queue, there are @@ -806,8 +745,7 @@ TxQ::apply( return {TxIter{firstIter, acctTxs.end()}}; }(); - auto const acctTxCount{ - !txIter ? 0 : std::distance(txIter->first, txIter->end)}; + auto const acctTxCount{!txIter ? 0 : std::distance(txIter->first, txIter->end)}; // Is tx a blocker? If so there are very limited conditions when it // is allowed in the TxQ: @@ -820,25 +758,22 @@ TxQ::apply( { // A blocker may not be co-resident with other transactions in // the account's queue. - JLOG(j_.trace()) - << "Rejecting blocker transaction " << transactionID - << ". Account has other queued transactions."; + JLOG(j_.trace()) << "Rejecting blocker transaction " << transactionID + << ". Account has other queued transactions."; return {telCAN_NOT_QUEUE_BLOCKS, false}; } if (acctTxCount == 1 && (txSeqProx != txIter->first->first)) { // The blocker is not replacing the lone queued transaction. - JLOG(j_.trace()) - << "Rejecting blocker transaction " << transactionID - << ". Blocker does not replace lone queued transaction."; + JLOG(j_.trace()) << "Rejecting blocker transaction " << transactionID + << ". Blocker does not replace lone queued transaction."; return {telCAN_NOT_QUEUE_BLOCKS, false}; } } // If the transaction is intending to replace a transaction in the queue // identify the one that might be replaced. - auto replacedTxIter = [accountIsInQueue, &accountIter, txSeqProx]() - -> std::optional { + auto replacedTxIter = [accountIsInQueue, &accountIter, txSeqProx]() -> std::optional { if (accountIsInQueue) { TxQAccount& txQAcct = accountIter->second; @@ -853,8 +788,7 @@ TxQ::apply( // replacement, so just pull it up now. auto const metricsSnapshot = feeMetrics_.getSnapshot(); auto const feeLevelPaid = getFeeLevelPaid(view, *tx); - auto const requiredFeeLevel = - getRequiredFeeLevel(view, flags, metricsSnapshot, lock); + auto const requiredFeeLevel = getRequiredFeeLevel(view, flags, metricsSnapshot, lock); // Is there a blocker already in the account's queue? If so, don't // allow additional transactions in the queue. @@ -865,9 +799,7 @@ TxQ::apply( // // We only need to check if txIter->first is a blocker because we // require that a blocker be alone in the account's queue. - if (acctTxCount == 1 && - txIter->first->second.consequences().isBlocker() && - (txIter->first->first != txSeqProx)) + if (acctTxCount == 1 && txIter->first->second.consequences().isBlocker() && (txIter->first->first != txSeqProx)) { return {telCAN_NOT_QUEUE_BLOCKED, false}; } @@ -882,29 +814,23 @@ TxQ::apply( // Is the current transaction's fee higher than // the queued transaction's fee + a percentage TxQAccount::TxMap::iterator const& existingIter = *replacedTxIter; - auto requiredRetryLevel = increase( - existingIter->second.feeLevel, setup_.retrySequencePercent); - JLOG(j_.trace()) - << "Found transaction in queue for account " << account - << " with " << txSeqProx << " new txn fee level is " - << feeLevelPaid << ", old txn fee level is " - << existingIter->second.feeLevel - << ", new txn needs fee level of " << requiredRetryLevel; + auto requiredRetryLevel = increase(existingIter->second.feeLevel, setup_.retrySequencePercent); + JLOG(j_.trace()) << "Found transaction in queue for account " << account << " with " << txSeqProx + << " new txn fee level is " << feeLevelPaid << ", old txn fee level is " + << existingIter->second.feeLevel << ", new txn needs fee level of " << requiredRetryLevel; if (feeLevelPaid > requiredRetryLevel) { // Continue, leaving the queued transaction marked for removal. // DO NOT REMOVE if the new tx fails, because there may // be other txs dependent on it in the queue. - JLOG(j_.trace()) << "Removing transaction from queue " - << existingIter->second.txID << " in favor of " + JLOG(j_.trace()) << "Removing transaction from queue " << existingIter->second.txID << " in favor of " << transactionID; } else { // Drop the current transaction - JLOG(j_.trace()) - << "Ignoring transaction " << transactionID - << " in favor of queued " << existingIter->second.txID; + JLOG(j_.trace()) << "Ignoring transaction " << transactionID << " in favor of queued " + << existingIter->second.txID; return {telCAN_NOT_QUEUE_FEE, false}; } } @@ -915,8 +841,7 @@ TxQ::apply( ApplyViewImpl applyView; OpenView openView; - MultiTxn(OpenView& view, ApplyFlags flags) - : applyView(&view, flags), openView(&applyView) + MultiTxn(OpenView& view, ApplyFlags flags) : applyView(&view, flags), openView(&applyView) { } }; @@ -957,14 +882,7 @@ TxQ::apply( { // If the transaction is queueable, create the multiTxn // object to hold the info we need to adjust for prior txns. - TER const ter{canBeHeld( - *tx, - flags, - view, - sleAccount, - accountIter, - replacedTxIter, - lock)}; + TER const ter{canBeHeld(*tx, flags, view, sleAccount, accountIter, replacedTxIter, lock)}; if (!isTesSuccess(ter)) return {ter, false}; @@ -985,8 +903,7 @@ TxQ::apply( // Find the entry in the queue that precedes the new // transaction, if one does. - TxQAccount::TxMap::const_iterator const prevIter = - txQAcct.getPrevTx(txSeqProx); + TxQAccount::TxMap::const_iterator const prevIter = txQAcct.getPrevTx(txSeqProx); // Does the new transaction go to the front of the queue? // This can happen if: @@ -1014,8 +931,7 @@ TxQ::apply( // front of this one in the queue. Make sure the current // transaction fits in proper sequence order with the // previous transaction or is a ticket. - if (txSeqProx.isSeq() && - nextQueuableSeqImpl(sleAccount, lock) != txSeqProx) + if (txSeqProx.isSeq() && nextQueuableSeqImpl(sleAccount, lock) != txSeqProx) return {telCAN_NOT_QUEUE, false}; } @@ -1032,8 +948,7 @@ TxQ::apply( if (iter->first != txSeqProx) { totalFee += iter->second.consequences().fee(); - potentialSpend += - iter->second.consequences().potentialSpend(); + potentialSpend += iter->second.consequences().potentialSpend(); } else if (std::next(iter) != txIter->end) { @@ -1094,12 +1009,10 @@ TxQ::apply( */ auto const reserve = view.fees().reserve; auto const base = view.fees().base; - if (totalFee >= balance || - (reserve > 10 * base && totalFee >= reserve)) + if (totalFee >= balance || (reserve > 10 * base && totalFee >= reserve)) { // Drop the current transaction - JLOG(j_.trace()) << "Ignoring transaction " << transactionID - << ". Total fees in flight too high."; + JLOG(j_.trace()) << "Ignoring transaction " << transactionID << ". Total fees in flight too high."; return {telCAN_NOT_QUEUE_BALANCE, false}; } @@ -1113,12 +1026,10 @@ TxQ::apply( // Subtract the fees and XRP spend from all of the other // transactions in the queue. That prevents a transaction // inserted in the middle from fouling up later transactions. - auto const potentialTotalSpend = totalFee + - std::min(balance - std::min(balance, reserve), potentialSpend); + auto const potentialTotalSpend = totalFee + std::min(balance - std::min(balance, reserve), potentialSpend); XRPL_ASSERT( potentialTotalSpend > XRPAmount{0} || - (potentialTotalSpend == XRPAmount{0} && - multiTxn->applyView.fees().base == 0), + (potentialTotalSpend == XRPAmount{0} && multiTxn->applyView.fees().base == 0), "xrpl::TxQ::apply : total spend check"); sleBump->setFieldAmount(sfBalance, balance - potentialTotalSpend); // The transaction's sequence/ticket will be valid when the other @@ -1126,9 +1037,8 @@ TxQ::apply( // sequence, set the account to match it. If it has a ticket, use // the next queueable sequence, which is the closest approximation // to the most successful case. - sleBump->at(sfSequence) = txSeqProx.isSeq() - ? txSeqProx.value() - : nextQueuableSeqImpl(sleAccount, lock).value(); + sleBump->at(sfSequence) = + txSeqProx.isSeq() ? txSeqProx.value() : nextQueuableSeqImpl(sleAccount, lock).value(); } } @@ -1143,19 +1053,16 @@ TxQ::apply( // Note that earlier code has already verified that the sequence/ticket // is valid. So we use a special entry point that runs all of the // preclaim checks with the exception of the sequence check. - auto const pcresult = - preclaim(pfResult, app, multiTxn ? multiTxn->openView : view); + auto const pcresult = preclaim(pfResult, app, multiTxn ? multiTxn->openView : view); if (!pcresult.likelyToClaimFee) return {pcresult.ter, false}; // Too low of a fee should get caught by preclaim XRPL_ASSERT(feeLevelPaid >= baseLevel, "xrpl::TxQ::apply : minimum fee"); - JLOG(j_.trace()) << "Transaction " << transactionID << " from account " - << account << " has fee level of " << feeLevelPaid - << " needs at least " << requiredFeeLevel - << " to get in the open ledger, which has " - << view.txCount() << " entries."; + JLOG(j_.trace()) << "Transaction " << transactionID << " from account " << account << " has fee level of " + << feeLevelPaid << " needs at least " << requiredFeeLevel + << " to get in the open ledger, which has " << view.txCount() << " entries."; /* Quick heuristic check to see if it's worth checking that this tx has a high enough fee to clear all the txs in front of it in the queue. @@ -1175,8 +1082,8 @@ TxQ::apply( conditions change, but don't waste the effort to clear). */ if (txSeqProx.isSeq() && txIter && multiTxn.has_value() && - txIter->first->second.retriesRemaining == MaybeTx::retriesAllowed && - feeLevelPaid > requiredFeeLevel && requiredFeeLevel > baseLevel) + txIter->first->second.retriesRemaining == MaybeTx::retriesAllowed && feeLevelPaid > requiredFeeLevel && + requiredFeeLevel > baseLevel) { OpenView sandbox(open_ledger, &view, view.rules()); @@ -1205,13 +1112,11 @@ TxQ::apply( // If `multiTxn` has a value, then `canBeHeld` has already been verified if (!multiTxn) { - TER const ter{canBeHeld( - *tx, flags, view, sleAccount, accountIter, replacedTxIter, lock)}; + TER const ter{canBeHeld(*tx, flags, view, sleAccount, accountIter, replacedTxIter, lock)}; if (!isTesSuccess(ter)) { // Bail, transaction cannot be held - JLOG(j_.trace()) - << "Transaction " << transactionID << " cannot be held"; + JLOG(j_.trace()) << "Transaction " << transactionID << " cannot be held"; return {ter, false}; } } @@ -1234,10 +1139,8 @@ TxQ::apply( // is 2000, and an account can only have 10 transactions // queued. However, it can occur if settings are changed, // and there is unit test coverage. - JLOG(j_.info()) - << "Queue is full, and transaction " << transactionID - << " would kick a transaction from the same account (" - << account << ") out of the queue."; + JLOG(j_.info()) << "Queue is full, and transaction " << transactionID + << " would kick a transaction from the same account (" << account << ") out of the queue."; return {telCAN_NOT_QUEUE_FULL, false}; } auto const& endAccount = byAccount_.at(lastRIter->account); @@ -1245,8 +1148,7 @@ TxQ::apply( // Compute the average of all the txs for the endAccount, // but only if the last tx in the queue has a lower fee // level than this candidate tx. - if (lastRIter->feeLevel > feeLevelPaid || - endAccount.transactions.size() == 1) + if (lastRIter->feeLevel > feeLevelPaid || endAccount.transactions.size() == 1) return lastRIter->feeLevel; constexpr FeeLevel64 max{std::numeric_limits::max()}; @@ -1254,20 +1156,16 @@ TxQ::apply( endAccount.transactions.begin(), endAccount.transactions.end(), std::pair(0, 0), - [&](auto const& total, - auto const& txn) -> std::pair { + [&](auto const& total, auto const& txn) -> std::pair { // Check for overflow. - auto next = - txn.second.feeLevel / endAccount.transactions.size(); - auto mod = - txn.second.feeLevel % endAccount.transactions.size(); + auto next = txn.second.feeLevel / endAccount.transactions.size(); + auto mod = txn.second.feeLevel % endAccount.transactions.size(); if (total.first >= max - next || total.second >= max - mod) return {max, FeeLevel64{0}}; return {total.first + next, total.second + mod}; }); - return endTotal.first + - endTotal.second / endAccount.transactions.size(); + return endTotal.first + endTotal.second / endAccount.transactions.size(); }(); if (feeLevelPaid > endEffectiveFeeLevel) { @@ -1275,20 +1173,16 @@ TxQ::apply( // valuable, so kick out the cheapest transaction. auto dropRIter = endAccount.transactions.rbegin(); XRPL_ASSERT( - dropRIter->second.account == lastRIter->account, - "xrpl::TxQ::apply : cheapest transaction found"); - JLOG(j_.info()) - << "Removing last item of account " << lastRIter->account - << " from queue with average fee of " << endEffectiveFeeLevel - << " in favor of " << transactionID << " with fee of " - << feeLevelPaid; + dropRIter->second.account == lastRIter->account, "xrpl::TxQ::apply : cheapest transaction found"); + JLOG(j_.info()) << "Removing last item of account " << lastRIter->account + << " from queue with average fee of " << endEffectiveFeeLevel << " in favor of " + << transactionID << " with fee of " << feeLevelPaid; erase(byFee_.iterator_to(dropRIter->second)); } else { - JLOG(j_.info()) - << "Queue is full, and transaction " << transactionID - << " fee is lower than end item's account average fee"; + JLOG(j_.info()) << "Queue is full, and transaction " << transactionID + << " fee is lower than end item's account average fee"; return {telCAN_NOT_QUEUE_FULL, false}; } } @@ -1303,8 +1197,7 @@ TxQ::apply( { // Create a new TxQAccount object and add the byAccount lookup. [[maybe_unused]] bool created = false; - std::tie(accountIter, created) = - byAccount_.emplace(account, TxQAccount(tx)); + std::tie(accountIter, created) = byAccount_.emplace(account, TxQAccount(tx)); XRPL_ASSERT(created, "xrpl::TxQ::apply : account created"); } // Modify the flags for use when coming out of the queue. @@ -1315,15 +1208,13 @@ TxQ::apply( // Don't allow soft failures, which can lead to retries flags &= ~tapRETRY; - auto& candidate = accountIter->second.add( - {tx, transactionID, feeLevelPaid, flags, pfResult}); + auto& candidate = accountIter->second.add({tx, transactionID, feeLevelPaid, flags, pfResult}); // Then index it into the byFee lookup. byFee_.insert(candidate); - JLOG(j_.debug()) << "Added transaction " << candidate.txID - << " with result " << transToken(pfResult.ter) << " from " - << (accountIsInQueue ? "existing" : "new") << " account " - << candidate.account << " to queue." + JLOG(j_.debug()) << "Added transaction " << candidate.txID << " with result " << transToken(pfResult.ter) + << " from " << (accountIsInQueue ? "existing" : "new") << " account " << candidate.account + << " to queue." << " Flags: " << flags; return {terQUEUED, false}; @@ -1352,8 +1243,7 @@ TxQ::processClosedLedger(Application& app, ReadView const& view, bool timeLeap) auto ledgerSeq = view.header().seq; if (!timeLeap) - maxSize_ = std::max( - snapshot.txnsExpected * setup_.ledgersInQueue, setup_.queueSizeMin); + maxSize_ = std::max(snapshot.txnsExpected * setup_.ledgersInQueue, setup_.queueSizeMin); // Remove any queued candidates whose LastLedgerSequence has gone by. for (auto candidateIter = byFee_.begin(); candidateIter != byFee_.end();) @@ -1371,8 +1261,7 @@ TxQ::processClosedLedger(Application& app, ReadView const& view, bool timeLeap) // Remove any TxQAccounts that don't have candidates // under them - for (auto txQAccountIter = byAccount_.begin(); - txQAccountIter != byAccount_.end();) + for (auto txQAccountIter = byAccount_.begin(); txQAccountIter != byAccount_.end();) { if (txQAccountIter->second.empty()) txQAccountIter = byAccount_.erase(txQAccountIter); @@ -1429,72 +1318,56 @@ TxQ::accept(Application& app, OpenView& view) { auto& account = byAccount_.at(candidateIter->account); auto const beginIter = account.transactions.begin(); - if (candidateIter->seqProxy.isSeq() && - candidateIter->seqProxy > beginIter->first) + if (candidateIter->seqProxy.isSeq() && candidateIter->seqProxy > beginIter->first) { // There is a sequence transaction at the front of the queue and // candidate has a later sequence, so skip this candidate. We // need to process sequence-based transactions in sequence order. - JLOG(j_.trace()) - << "Skipping queued transaction " << candidateIter->txID - << " from account " << candidateIter->account - << " as it is not the first."; + JLOG(j_.trace()) << "Skipping queued transaction " << candidateIter->txID << " from account " + << candidateIter->account << " as it is not the first."; candidateIter++; continue; } - auto const requiredFeeLevel = - getRequiredFeeLevel(view, tapNONE, metricsSnapshot, lock); + auto const requiredFeeLevel = getRequiredFeeLevel(view, tapNONE, metricsSnapshot, lock); auto const feeLevelPaid = candidateIter->feeLevel; - JLOG(j_.trace()) << "Queued transaction " << candidateIter->txID - << " from account " << candidateIter->account - << " has fee level of " << feeLevelPaid - << " needs at least " << requiredFeeLevel; + JLOG(j_.trace()) << "Queued transaction " << candidateIter->txID << " from account " << candidateIter->account + << " has fee level of " << feeLevelPaid << " needs at least " << requiredFeeLevel; if (feeLevelPaid >= requiredFeeLevel) { - JLOG(j_.trace()) << "Applying queued transaction " - << candidateIter->txID << " to open ledger."; + JLOG(j_.trace()) << "Applying queued transaction " << candidateIter->txID << " to open ledger."; - auto const [txnResult, didApply, _metadata] = - candidateIter->apply(app, view, j_); + auto const [txnResult, didApply, _metadata] = candidateIter->apply(app, view, j_); if (didApply) { // Remove the candidate from the queue - JLOG(j_.debug()) - << "Queued transaction " << candidateIter->txID - << " applied successfully with " << transToken(txnResult) - << ". Remove from queue."; + JLOG(j_.debug()) << "Queued transaction " << candidateIter->txID << " applied successfully with " + << transToken(txnResult) << ". Remove from queue."; candidateIter = eraseAndAdvance(candidateIter); ledgerChanged = true; } - else if ( - isTefFailure(txnResult) || isTemMalformed(txnResult) || - candidateIter->retriesRemaining <= 0) + else if (isTefFailure(txnResult) || isTemMalformed(txnResult) || candidateIter->retriesRemaining <= 0) { if (candidateIter->retriesRemaining <= 0) account.retryPenalty = true; else account.dropPenalty = true; - JLOG(j_.debug()) << "Queued transaction " << candidateIter->txID - << " failed with " << transToken(txnResult) - << ". Remove from queue."; + JLOG(j_.debug()) << "Queued transaction " << candidateIter->txID << " failed with " + << transToken(txnResult) << ". Remove from queue."; candidateIter = eraseAndAdvance(candidateIter); } else { - JLOG(j_.debug()) << "Queued transaction " << candidateIter->txID - << " failed with " << transToken(txnResult) - << ". Leave in queue." - << " Applied: " << didApply - << ". Flags: " << candidateIter->flags; + JLOG(j_.debug()) << "Queued transaction " << candidateIter->txID << " failed with " + << transToken(txnResult) << ". Leave in queue." + << " Applied: " << didApply << ". Flags: " << candidateIter->flags; if (account.retryPenalty && candidateIter->retriesRemaining > 2) candidateIter->retriesRemaining = 1; else --candidateIter->retriesRemaining; candidateIter->lastResult = txnResult; - if (account.dropPenalty && account.transactions.size() > 1 && - isFull<95>()) + if (account.dropPenalty && account.transactions.size() > 1 && isFull<95>()) { // The queue is close to full, this account has multiple // txs queued, and this account has had a transaction @@ -1503,12 +1376,9 @@ TxQ::accept(Application& app, OpenView& view) { // Since the failed transaction has a ticket, order // doesn't matter. Drop this one. - JLOG(j_.info()) - << "Queue is nearly full, and transaction " - << candidateIter->txID << " failed with " - << transToken(txnResult) - << ". Removing ticketed tx from account " - << account.account; + JLOG(j_.info()) << "Queue is nearly full, and transaction " << candidateIter->txID + << " failed with " << transToken(txnResult) + << ". Removing ticketed tx from account " << account.account; candidateIter = eraseAndAdvance(candidateIter); } else @@ -1519,15 +1389,11 @@ TxQ::accept(Application& app, OpenView& view) // this account. auto dropRIter = account.transactions.rbegin(); XRPL_ASSERT( - dropRIter->second.account == candidateIter->account, - "xrpl::TxQ::accept : account check"); + dropRIter->second.account == candidateIter->account, "xrpl::TxQ::accept : account check"); - JLOG(j_.info()) - << "Queue is nearly full, and transaction " - << candidateIter->txID << " failed with " - << transToken(txnResult) - << ". Removing last item from account " - << account.account; + JLOG(j_.info()) << "Queue is nearly full, and transaction " << candidateIter->txID + << " failed with " << transToken(txnResult) + << ". Removing last item from account " << account.account; auto endIter = byFee_.iterator_to(dropRIter->second); if (endIter != candidateIter) erase(endIter); @@ -1574,8 +1440,7 @@ TxQ::accept(Application& app, OpenView& view) byFee_.insert(candidate); } } - XRPL_ASSERT( - byFee_.size() == startingSize, "xrpl::TxQ::accept : byFee size match"); + XRPL_ASSERT(byFee_.size() == startingSize, "xrpl::TxQ::accept : byFee size match"); return ledgerChanged; } @@ -1597,9 +1462,7 @@ TxQ::nextQueuableSeq(std::shared_ptr const& sleAccount) const // sequence number, that is not used by a transaction in the queue, must // be found and returned. SeqProxy -TxQ::nextQueuableSeqImpl( - std::shared_ptr const& sleAccount, - std::lock_guard const&) const +TxQ::nextQueuableSeqImpl(std::shared_ptr const& sleAccount, std::lock_guard const&) const { // If the account is not in the ledger or a non-account was passed // then return zero. We have no idea. @@ -1610,8 +1473,7 @@ TxQ::nextQueuableSeqImpl( // If the account is not in the queue then acctSeqProx is good enough. auto const accountIter = byAccount_.find((*sleAccount)[sfAccount]); - if (accountIter == byAccount_.end() || - accountIter->second.transactions.empty()) + if (accountIter == byAccount_.end() || accountIter->second.transactions.empty()) return acctSeqProx; TxQAccount::TxMap const& acctTxs = accountIter->second.transactions; @@ -1621,8 +1483,7 @@ TxQ::nextQueuableSeqImpl( // wild, but it's uncommon. TxQAccount::TxMap::const_iterator txIter = acctTxs.lower_bound(acctSeqProx); - if (txIter == acctTxs.end() || !txIter->first.isSeq() || - txIter->first != acctSeqProx) + if (txIter == acctTxs.end() || !txIter->first.isSeq() || txIter->first != acctSeqProx) // Either... // o There are no queued sequence-based transactions equal to or // following acctSeqProx or @@ -1678,8 +1539,7 @@ TxQ::tryDirectApply( FeeLevel64 const requiredFeeLevel = [this, &view, flags]() { std::lock_guard lock(mutex_); - return getRequiredFeeLevel( - view, flags, feeMetrics_.getSnapshot(), lock); + return getRequiredFeeLevel(view, flags, feeMetrics_.getSnapshot(), lock); }(); // If the transaction's fee is high enough we may be able to put the @@ -1690,16 +1550,12 @@ TxQ::tryDirectApply( { // Attempt to apply the transaction directly. auto const transactionID = tx->getTransactionID(); - JLOG(j_.trace()) << "Applying transaction " << transactionID - << " to open ledger."; + JLOG(j_.trace()) << "Applying transaction " << transactionID << " to open ledger."; - auto const [txnResult, didApply, metadata] = - xrpl::apply(app, view, *tx, flags, j); + auto const [txnResult, didApply, metadata] = xrpl::apply(app, view, *tx, flags, j); JLOG(j_.trace()) << "New transaction " << transactionID - << (didApply ? " applied successfully with " - : " failed with ") - << transToken(txnResult); + << (didApply ? " applied successfully with " : " failed with ") << transToken(txnResult); if (didApply) { @@ -1711,8 +1567,7 @@ TxQ::tryDirectApply( if (accountIter != byAccount_.end()) { TxQAccount& txQAcct = accountIter->second; - if (auto const existingIter = - txQAcct.transactions.find(txSeqProx); + if (auto const existingIter = txQAcct.transactions.find(txSeqProx); existingIter != txQAcct.transactions.end()) { removeFromByFee(existingIter, tx); @@ -1734,18 +1589,10 @@ TxQ::removeFromByFee( // If the transaction we're holding replaces a transaction in the // queue, remove the transaction that is being replaced. auto deleteIter = byFee_.iterator_to((*replacedTxIter)->second); - XRPL_ASSERT( - deleteIter != byFee_.end(), - "xrpl::TxQ::removeFromByFee : found in byFee"); - XRPL_ASSERT( - &(*replacedTxIter)->second == &*deleteIter, - "xrpl::TxQ::removeFromByFee : matching transaction"); - XRPL_ASSERT( - deleteIter->seqProxy == tx->getSeqProxy(), - "xrpl::TxQ::removeFromByFee : matching sequence"); - XRPL_ASSERT( - deleteIter->account == (*tx)[sfAccount], - "xrpl::TxQ::removeFromByFee : matching account"); + XRPL_ASSERT(deleteIter != byFee_.end(), "xrpl::TxQ::removeFromByFee : found in byFee"); + XRPL_ASSERT(&(*replacedTxIter)->second == &*deleteIter, "xrpl::TxQ::removeFromByFee : matching transaction"); + XRPL_ASSERT(deleteIter->seqProxy == tx->getSeqProxy(), "xrpl::TxQ::removeFromByFee : matching sequence"); + XRPL_ASSERT(deleteIter->account == (*tx)[sfAccount], "xrpl::TxQ::removeFromByFee : matching account"); erase(deleteIter); } @@ -1766,8 +1613,7 @@ TxQ::getMetrics(OpenView const& view) const result.txInLedger = view.txCount(); result.txPerLedger = snapshot.txnsExpected; result.referenceFeeLevel = baseLevel; - result.minProcessingFeeLevel = - isFull() ? byFee_.rbegin()->feeLevel + FeeLevel64{1} : baseLevel; + result.minProcessingFeeLevel = isFull() ? byFee_.rbegin()->feeLevel + FeeLevel64{1} : baseLevel; result.medFeeLevel = snapshot.escalationMultiplier; result.openLedgerFeeLevel = FeeMetrics::scaleFeeLevel(snapshot, view); @@ -1775,9 +1621,7 @@ TxQ::getMetrics(OpenView const& view) const } TxQ::FeeAndSeq -TxQ::getTxRequiredFeeAndSeq( - OpenView const& view, - std::shared_ptr const& tx) const +TxQ::getTxRequiredFeeAndSeq(OpenView const& view, std::shared_ptr const& tx) const { auto const account = (*tx)[sfAccount]; @@ -1792,8 +1636,7 @@ TxQ::getTxRequiredFeeAndSeq( std::uint32_t const accountSeq = sle ? (*sle)[sfSequence] : 0; std::uint32_t const availableSeq = nextQueuableSeqImpl(sle, lock).value(); return { - mulDiv(fee, baseFee, baseLevel) - .value_or(XRPAmount(std::numeric_limits::max())), + mulDiv(fee, baseFee, baseLevel).value_or(XRPAmount(std::numeric_limits::max())), accountSeq, availableSeq}; } @@ -1807,8 +1650,7 @@ TxQ::getAccountTxs(AccountID const& account) const AccountMap::const_iterator const accountIter{byAccount_.find(account)}; - if (accountIter == byAccount_.end() || - accountIter->second.transactions.empty()) + if (accountIter == byAccount_.end() || accountIter->second.transactions.empty()) return result; result.reserve(accountIter->second.transactions.size()); @@ -1875,12 +1717,10 @@ TxQ::doRPC(Application& app) const drops[jss::base_fee] = to_string(baseFee); drops[jss::median_fee] = to_string(toDrops(metrics.medFeeLevel, baseFee)); - drops[jss::minimum_fee] = to_string(toDrops( - metrics.minProcessingFeeLevel, - metrics.txCount >= metrics.txQMaxSize ? effectiveBaseFee : baseFee)); + drops[jss::minimum_fee] = to_string( + toDrops(metrics.minProcessingFeeLevel, metrics.txCount >= metrics.txQMaxSize ? effectiveBaseFee : baseFee)); auto openFee = toDrops(metrics.openLedgerFeeLevel, effectiveBaseFee); - if (effectiveBaseFee && - toFeeLevel(openFee, effectiveBaseFee) < metrics.openLedgerFeeLevel) + if (effectiveBaseFee && toFeeLevel(openFee, effectiveBaseFee) < metrics.openLedgerFeeLevel) openFee += 1; drops[jss::open_ledger_fee] = to_string(openFee); @@ -1897,13 +1737,9 @@ setup_TxQ(Config const& config) set(setup.ledgersInQueue, "ledgers_in_queue", section); set(setup.queueSizeMin, "minimum_queue_size", section); set(setup.retrySequencePercent, "retry_sequence_percent", section); - set(setup.minimumEscalationMultiplier, - "minimum_escalation_multiplier", - section); + set(setup.minimumEscalationMultiplier, "minimum_escalation_multiplier", section); set(setup.minimumTxnInLedger, "minimum_txn_in_ledger", section); - set(setup.minimumTxnInLedgerSA, - "minimum_txn_in_ledger_standalone", - section); + set(setup.minimumTxnInLedgerSA, "minimum_txn_in_ledger_standalone", section); set(setup.targetTxnInLedger, "target_txn_in_ledger", section); std::uint32_t max; if (set(max, "maximum_txn_in_ledger", section)) @@ -1934,21 +1770,15 @@ setup_TxQ(Config const& config) moot. (There are other ways to do that, including minimum_txn_in_ledger.) */ - set(setup.normalConsensusIncreasePercent, - "normal_consensus_increase_percent", - section); - setup.normalConsensusIncreasePercent = - std::clamp(setup.normalConsensusIncreasePercent, 0u, 1000u); + set(setup.normalConsensusIncreasePercent, "normal_consensus_increase_percent", section); + setup.normalConsensusIncreasePercent = std::clamp(setup.normalConsensusIncreasePercent, 0u, 1000u); /* If this percentage is outside of the 0-100 range, the results are nonsensical (uint overflows happen, so the limit grows instead of shrinking). 0 is not recommended. */ - set(setup.slowConsensusDecreasePercent, - "slow_consensus_decrease_percent", - section); - setup.slowConsensusDecreasePercent = - std::clamp(setup.slowConsensusDecreasePercent, 0u, 100u); + set(setup.slowConsensusDecreasePercent, "slow_consensus_decrease_percent", section); + setup.slowConsensusDecreasePercent = std::clamp(setup.slowConsensusDecreasePercent, 0u, 100u); set(setup.maximumTxnPerAccount, "maximum_txn_per_account", section); set(setup.minimumLastLedgerBuffer, "minimum_last_ledger_buffer", section); diff --git a/src/xrpld/app/misc/detail/ValidatorKeys.cpp b/src/xrpld/app/misc/detail/ValidatorKeys.cpp index 757a18aa47..675ce4ac6f 100644 --- a/src/xrpld/app/misc/detail/ValidatorKeys.cpp +++ b/src/xrpld/app/misc/detail/ValidatorKeys.cpp @@ -9,31 +9,25 @@ namespace xrpl { ValidatorKeys::ValidatorKeys(Config const& config, beast::Journal j) { - if (config.exists(SECTION_VALIDATOR_TOKEN) && - config.exists(SECTION_VALIDATION_SEED)) + if (config.exists(SECTION_VALIDATOR_TOKEN) && config.exists(SECTION_VALIDATION_SEED)) { configInvalid_ = true; - JLOG(j.fatal()) << "Cannot specify both [" SECTION_VALIDATION_SEED - "] and [" SECTION_VALIDATOR_TOKEN "]"; + JLOG(j.fatal()) << "Cannot specify both [" SECTION_VALIDATION_SEED "] and [" SECTION_VALIDATOR_TOKEN "]"; return; } if (config.exists(SECTION_VALIDATOR_TOKEN)) { // token is non-const so it can be moved from - if (auto token = loadValidatorToken( - config.section(SECTION_VALIDATOR_TOKEN).lines())) + if (auto token = loadValidatorToken(config.section(SECTION_VALIDATOR_TOKEN).lines())) { - auto const pk = - derivePublicKey(KeyType::secp256k1, token->validationSecret); + auto const pk = derivePublicKey(KeyType::secp256k1, token->validationSecret); auto const m = deserializeManifest(base64_decode(token->manifest)); if (!m || pk != m->signingKey) { configInvalid_ = true; - JLOG(j.fatal()) - << "Invalid token specified in [" SECTION_VALIDATOR_TOKEN - "]"; + JLOG(j.fatal()) << "Invalid token specified in [" SECTION_VALIDATOR_TOKEN "]"; } else { @@ -46,19 +40,16 @@ ValidatorKeys::ValidatorKeys(Config const& config, beast::Journal j) else { configInvalid_ = true; - JLOG(j.fatal()) - << "Invalid token specified in [" SECTION_VALIDATOR_TOKEN "]"; + JLOG(j.fatal()) << "Invalid token specified in [" SECTION_VALIDATOR_TOKEN "]"; } } else if (config.exists(SECTION_VALIDATION_SEED)) { - auto const seed = parseBase58( - config.section(SECTION_VALIDATION_SEED).lines().front()); + auto const seed = parseBase58(config.section(SECTION_VALIDATION_SEED).lines().front()); if (!seed) { configInvalid_ = true; - JLOG(j.fatal()) - << "Invalid seed specified in [" SECTION_VALIDATION_SEED "]"; + JLOG(j.fatal()) << "Invalid seed specified in [" SECTION_VALIDATION_SEED "]"; } else { diff --git a/src/xrpld/app/misc/detail/ValidatorList.cpp b/src/xrpld/app/misc/detail/ValidatorList.cpp index 5c1c5e80a1..0edd0de9be 100644 --- a/src/xrpld/app/misc/detail/ValidatorList.cpp +++ b/src/xrpld/app/misc/detail/ValidatorList.cpp @@ -67,20 +67,17 @@ ValidatorList::PublisherListStats::PublisherListStats( ListDisposition ValidatorList::PublisherListStats::bestDisposition() const { - return dispositions.empty() ? ListDisposition::invalid - : dispositions.begin()->first; + return dispositions.empty() ? ListDisposition::invalid : dispositions.begin()->first; } ListDisposition ValidatorList::PublisherListStats::worstDisposition() const { - return dispositions.empty() ? ListDisposition::invalid - : dispositions.rbegin()->first; + return dispositions.empty() ? ListDisposition::invalid : dispositions.rbegin()->first; } void -ValidatorList::PublisherListStats::mergeDispositions( - PublisherListStats const& src) +ValidatorList::PublisherListStats::mergeDispositions(PublisherListStats const& src) { for (auto const& [disp, count] : src.dispositions) { @@ -137,8 +134,7 @@ ValidatorList::load( std::lock_guard lock{mutex_}; - JLOG(j_.debug()) - << "Loading configured trusted validator list publisher keys"; + JLOG(j_.debug()) << "Loading configured trusted validator list publisher keys"; std::size_t count = 0; for (auto key : publisherKeys) @@ -158,16 +154,13 @@ ValidatorList::load( if (publisherManifests_.revoked(id)) { - JLOG(j_.warn()) - << "Configured validator list publisher key is revoked: " - << key; + JLOG(j_.warn()) << "Configured validator list publisher key is revoked: " << key; status = PublisherStatus::revoked; } if (publisherLists_.count(id)) { - JLOG(j_.warn()) - << "Duplicate validator list publisher key: " << key; + JLOG(j_.warn()) << "Duplicate validator list publisher key: " << key; continue; } @@ -182,17 +175,14 @@ ValidatorList::load( XRPL_ASSERT( listThreshold_ > 0 && listThreshold_ <= publisherLists_.size(), "xrpl::ValidatorList::load : list threshold inside range"); - JLOG(j_.debug()) << "Validator list threshold set in configuration to " - << listThreshold_; + JLOG(j_.debug()) << "Validator list threshold set in configuration to " << listThreshold_; } else { // Want truncated result when dividing an odd integer - listThreshold_ = (publisherLists_.size() < 3) - ? 1 // - : publisherLists_.size() / 2 + 1; - JLOG(j_.debug()) << "Validator list threshold computed as " - << listThreshold_; + listThreshold_ = (publisherLists_.size() < 3) ? 1 // + : publisherLists_.size() / 2 + 1; + JLOG(j_.debug()) << "Validator list threshold computed as " << listThreshold_; } JLOG(j_.debug()) << "Loaded " << count << " keys"; @@ -205,12 +195,10 @@ ValidatorList::load( { // The local validator must meet listThreshold_ so the validator does // not ignore itself. - auto const [_, inserted] = - keyListings_.insert({*localPubKey_, listThreshold_}); + auto const [_, inserted] = keyListings_.insert({*localPubKey_, listThreshold_}); if (inserted) { - JLOG(j_.debug()) << "Added own master key " - << toBase58(TokenType::NodePublic, *localPubKey_); + JLOG(j_.debug()) << "Added own master key " << toBase58(TokenType::NodePublic, *localPubKey_); } } @@ -229,8 +217,7 @@ ValidatorList::load( return false; } - auto const id = - parseBase58(TokenType::NodePublic, match[1].str()); + auto const id = parseBase58(TokenType::NodePublic, match[1].str()); if (!id) { @@ -264,9 +251,7 @@ ValidatorList::load( } boost::filesystem::path -ValidatorList::getCacheFileName( - ValidatorList::lock_guard const&, - PublicKey const& pubKey) const +ValidatorList::getCacheFileName(ValidatorList::lock_guard const&, PublicKey const& pubKey) const { return dataPath_ / (filePrefix_ + strHex(pubKey)); } @@ -294,8 +279,7 @@ ValidatorList::buildFileData( XRPL_ASSERT( pubCollection.rawVersion == 2 || pubCollection.remaining.empty(), "xrpl::ValidatorList::buildFileData : valid publisher list input"); - auto const effectiveVersion = - forceVersion ? *forceVersion : pubCollection.rawVersion; + auto const effectiveVersion = forceVersion ? *forceVersion : pubCollection.rawVersion; value[jss::manifest] = pubCollection.rawManifest; value[jss::version] = effectiveVersion; @@ -309,21 +293,18 @@ ValidatorList::buildFileData( value[jss::signature] = current.rawSignature; // This is only possible if "downgrading" a v2 UNL to v1, for // example for the /vl/ endpoint. - if (current.rawManifest && - *current.rawManifest != pubCollection.rawManifest) + if (current.rawManifest && *current.rawManifest != pubCollection.rawManifest) value[jss::manifest] = *current.rawManifest; break; } case 2: { Json::Value blobs(Json::arrayValue); - auto add = [&blobs, &outerManifest = pubCollection.rawManifest]( - PublisherList const& pubList) { + auto add = [&blobs, &outerManifest = pubCollection.rawManifest](PublisherList const& pubList) { auto& blob = blobs.append(Json::objectValue); blob[jss::blob] = pubList.rawBlob; blob[jss::signature] = pubList.rawSignature; - if (pubList.rawManifest && - *pubList.rawManifest != outerManifest) + if (pubList.rawManifest && *pubList.rawManifest != outerManifest) blob[jss::manifest] = *pubList.rawManifest; }; @@ -338,8 +319,7 @@ ValidatorList::buildFileData( break; } default: - JLOG(j.trace()) - << "Invalid VL version provided: " << effectiveVersion; + JLOG(j.trace()) << "Invalid VL version provided: " << effectiveVersion; value = Json::nullValue; } @@ -347,9 +327,7 @@ ValidatorList::buildFileData( } void -ValidatorList::cacheValidatorFile( - ValidatorList::lock_guard const& lock, - PublicKey const& pubKey) const +ValidatorList::cacheValidatorFile(ValidatorList::lock_guard const& lock, PublicKey const& pubKey) const { if (dataPath_.empty()) return; @@ -358,8 +336,7 @@ ValidatorList::cacheValidatorFile( boost::system::error_code ec; - Json::Value value = - buildFileData(strHex(pubKey), publisherLists_.at(pubKey), j_); + Json::Value value = buildFileData(strHex(pubKey), publisherLists_.at(pubKey), j_); // rippled should be the only process writing to this file, so // if it ever needs to be read, it is not expected to change externally, so // delay the refresh as long as possible: 24 hours. (See also @@ -371,8 +348,7 @@ ValidatorList::cacheValidatorFile( if (ec) { // Log and ignore any file I/O exceptions - JLOG(j_.error()) << "Problem writing " << filename << " " << ec.value() - << ": " << ec.message(); + JLOG(j_.error()) << "Problem writing " << filename << " " << ec.value() << ": " << ec.message(); } } @@ -384,8 +360,7 @@ ValidatorList::parseBlobs(std::uint32_t version, Json::Value const& body) switch (version) { case 1: { - if (!body.isMember(jss::blob) || !body[jss::blob].isString() || - !body.isMember(jss::signature) || + if (!body.isMember(jss::blob) || !body[jss::blob].isString() || !body.isMember(jss::signature) || !body[jss::signature].isString() || // If the v2 field is present, the VL is malformed body.isMember(jss::blobs_v2)) @@ -393,9 +368,7 @@ ValidatorList::parseBlobs(std::uint32_t version, Json::Value const& body) ValidatorBlobInfo& info = result.emplace_back(); info.blob = body[jss::blob].asString(); info.signature = body[jss::signature].asString(); - XRPL_ASSERT( - result.size() == 1, - "xrpl::ValidatorList::parseBlobs : single element result"); + XRPL_ASSERT(result.size() == 1, "xrpl::ValidatorList::parseBlobs : single element result"); return result; } // Treat unknown versions as if they're the latest version. This @@ -404,8 +377,7 @@ ValidatorList::parseBlobs(std::uint32_t version, Json::Value const& body) // validated elsewhere. case 2: default: { - if (!body.isMember(jss::blobs_v2) || - !body[jss::blobs_v2].isArray() || + if (!body.isMember(jss::blobs_v2) || !body[jss::blobs_v2].isArray() || body[jss::blobs_v2].size() > maxSupportedBlobs || // If any of the v1 fields are present, the VL is malformed body.isMember(jss::blob) || body.isMember(jss::signature)) @@ -414,10 +386,8 @@ ValidatorList::parseBlobs(std::uint32_t version, Json::Value const& body) result.reserve(blobs.size()); for (auto const& blobInfo : blobs) { - if (!blobInfo.isObject() || - !blobInfo.isMember(jss::signature) || - !blobInfo[jss::signature].isString() || - !blobInfo.isMember(jss::blob) || + if (!blobInfo.isObject() || !blobInfo.isMember(jss::signature) || + !blobInfo[jss::signature].isString() || !blobInfo.isMember(jss::blob) || !blobInfo[jss::blob].isString()) return {}; ValidatorBlobInfo& info = result.emplace_back(); @@ -524,13 +494,9 @@ splitMessageParts( smallMsg.set_manifest(blob.manifest()); XRPL_ASSERT( - Message::totalSize(smallMsg) <= maximumMessageSize, - "xrpl::splitMessageParts : maximum message size"); + Message::totalSize(smallMsg) <= maximumMessageSize, "xrpl::splitMessageParts : maximum message size"); - messages.emplace_back( - std::make_shared(smallMsg, protocol::mtVALIDATOR_LIST), - sha512Half(smallMsg), - 1); + messages.emplace_back(std::make_shared(smallMsg, protocol::mtVALIDATOR_LIST), sha512Half(smallMsg), 1); return messages.back().numVLs; } else @@ -554,8 +520,7 @@ splitMessageParts( else { messages.emplace_back( - std::make_shared( - *smallMsg, protocol::mtVALIDATOR_LIST_COLLECTION), + std::make_shared(*smallMsg, protocol::mtVALIDATOR_LIST_COLLECTION), sha512Half(*smallMsg), smallMsg->blobs_size()); return messages.back().numVLs; @@ -578,8 +543,7 @@ buildValidatorListMessage( "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : empty messages " "input"); protocol::TMValidatorList msg; - auto const manifest = - currentBlob.manifest ? *currentBlob.manifest : rawManifest; + auto const manifest = currentBlob.manifest ? *currentBlob.manifest : rawManifest; auto const version = 1; msg.set_manifest(manifest); msg.set_blob(currentBlob.blob); @@ -591,10 +555,7 @@ buildValidatorListMessage( Message::totalSize(msg) <= maximumMessageSize, "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : maximum " "message size"); - messages.emplace_back( - std::make_shared(msg, protocol::mtVALIDATOR_LIST), - sha512Half(msg), - 1); + messages.emplace_back(std::make_shared(msg, protocol::mtVALIDATOR_LIST), sha512Half(msg), 1); return 1; } @@ -640,10 +601,7 @@ buildValidatorListMessage( else { messages.emplace_back( - std::make_shared( - msg, protocol::mtVALIDATOR_LIST_COLLECTION), - sha512Half(msg), - msg.blobs_size()); + std::make_shared(msg, protocol::mtVALIDATOR_LIST_COLLECTION), sha512Half(msg), msg.blobs_size()); return messages.back().numVLs; } } @@ -666,25 +624,15 @@ ValidatorList::buildValidatorListMessages( "xrpl::ValidatorList::buildValidatorListMessages : empty messages " "input"); auto const& [currentSeq, currentBlob] = *blobInfos.begin(); - auto numVLs = std::accumulate( - messages.begin(), - messages.end(), - 0, - [](std::size_t total, MessageWithHash const& m) { - return total + m.numVLs; - }); + auto numVLs = std::accumulate(messages.begin(), messages.end(), 0, [](std::size_t total, MessageWithHash const& m) { + return total + m.numVLs; + }); if (messageVersion == 2 && peerSequence < maxSequence) { // Version 2 if (messages.empty()) { - numVLs = buildValidatorListMessage( - messages, - peerSequence, - rawVersion, - rawManifest, - blobInfos, - maxSize); + numVLs = buildValidatorListMessage(messages, peerSequence, rawVersion, rawManifest, blobInfos, maxSize); if (messages.empty()) // No message was generated. Create an empty placeholder so we // dont' repeat the work later. @@ -700,11 +648,7 @@ ValidatorList::buildValidatorListMessages( if (messages.empty()) { numVLs = buildValidatorListMessage( - messages, - rawVersion, - currentBlob.manifest ? *currentBlob.manifest : rawManifest, - currentBlob, - maxSize); + messages, rawVersion, currentBlob.manifest ? *currentBlob.manifest : rawManifest, currentBlob, maxSize); if (messages.empty()) // No message was generated. Create an empty placeholder so we // dont' repeat the work later. @@ -731,20 +675,13 @@ ValidatorList::sendValidatorList( HashRouter& hashRouter, beast::Journal j) { - std::size_t const messageVersion = - peer.supportsFeature(ProtocolFeature::ValidatorList2Propagation) ? 2 - : peer.supportsFeature(ProtocolFeature::ValidatorListPropagation) ? 1 - : 0; + std::size_t const messageVersion = peer.supportsFeature(ProtocolFeature::ValidatorList2Propagation) ? 2 + : peer.supportsFeature(ProtocolFeature::ValidatorListPropagation) ? 1 + : 0; if (!messageVersion) return; auto const [newPeerSequence, numVLs] = buildValidatorListMessages( - messageVersion, - peerSequence, - maxSequence, - rawVersion, - rawManifest, - blobInfos, - messages); + messageVersion, peerSequence, maxSequence, rawVersion, rawManifest, blobInfos, messages); if (newPeerSequence) { XRPL_ASSERT( @@ -766,28 +703,21 @@ ValidatorList::sendValidatorList( } // The only way sent wil be false is if the messages was too big, and // thus there will only be one entry without a message - XRPL_ASSERT( - sent || messages.size() == 1, - "xrpl::ValidatorList::sendValidatorList : sent or one message"); + XRPL_ASSERT(sent || messages.size() == 1, "xrpl::ValidatorList::sendValidatorList : sent or one message"); if (sent) { if (messageVersion > 1) - JLOG(j.debug()) - << "Sent " << messages.size() - << " validator list collection(s) containing " << numVLs - << " validator list(s) for " << strHex(publisherKey) - << " with sequence range " << peerSequence << ", " - << newPeerSequence << " to " << peer.fingerprint(); + JLOG(j.debug()) << "Sent " << messages.size() << " validator list collection(s) containing " << numVLs + << " validator list(s) for " << strHex(publisherKey) << " with sequence range " + << peerSequence << ", " << newPeerSequence << " to " << peer.fingerprint(); else { XRPL_ASSERT( numVLs == 1, "xrpl::ValidatorList::sendValidatorList : one validator " "list"); - JLOG(j.debug()) - << "Sent validator list for " << strHex(publisherKey) - << " with sequence " << newPeerSequence << " to " - << peer.fingerprint(); + JLOG(j.debug()) << "Sent validator list for " << strHex(publisherKey) << " with sequence " + << newPeerSequence << " to " << peer.fingerprint(); } } } @@ -808,16 +738,7 @@ ValidatorList::sendValidatorList( { std::vector messages; sendValidatorList( - peer, - peerSequence, - publisherKey, - maxSequence, - rawVersion, - rawManifest, - blobInfos, - messages, - hashRouter, - j); + peer, peerSequence, publisherKey, maxSequence, rawVersion, rawManifest, blobInfos, messages, hashRouter, j); } // static @@ -828,8 +749,7 @@ ValidatorList::buildBlobInfos( { auto const& current = lists.current; auto const& remaining = lists.remaining; - blobInfos[current.sequence] = { - current.rawBlob, current.rawSignature, current.rawManifest}; + blobInfos[current.sequence] = {current.rawBlob, current.rawSignature, current.rawManifest}; for (auto const& [sequence, vl] : remaining) { blobInfos[sequence] = {vl.rawBlob, vl.rawSignature, vl.rawManifest}; @@ -838,8 +758,7 @@ ValidatorList::buildBlobInfos( // static std::map -ValidatorList::buildBlobInfos( - ValidatorList::PublisherListCollection const& lists) +ValidatorList::buildBlobInfos(ValidatorList::PublisherListCollection const& lists) { std::map result; buildBlobInfos(result, lists); @@ -871,15 +790,13 @@ ValidatorList::broadcastBlobs( // This will hold v2 messages indexed by the peer's // `publisherListSequence`. For each `publisherListSequence`, we'll // only send the VLs with higher sequences. - std::map> - messages2; + std::map> messages2; // If any peers are found that are worth considering, this list will // be built to hold info for all of the valid VLs. std::map blobInfos; XRPL_ASSERT( - lists.current.sequence == maxSequence || - lists.remaining.count(maxSequence) == 1, + lists.current.sequence == maxSequence || lists.remaining.count(maxSequence) == 1, "xrpl::ValidatorList::broadcastBlobs : valid sequence"); // Can't use overlay.foreach here because we need to modify // the peer, and foreach provides a const& @@ -887,14 +804,12 @@ ValidatorList::broadcastBlobs( { if (toSkip->count(peer->id()) == 0) { - auto const peerSequence = - peer->publisherListSequence(publisherKey).value_or(0); + auto const peerSequence = peer->publisherListSequence(publisherKey).value_or(0); if (peerSequence < maxSequence) { if (blobInfos.empty()) buildBlobInfos(blobInfos, lists); - auto const v2 = peer->supportsFeature( - ProtocolFeature::ValidatorList2Propagation); + auto const v2 = peer->supportsFeature(ProtocolFeature::ValidatorList2Propagation); sendValidatorList( *peer, peerSequence, @@ -926,8 +841,7 @@ ValidatorList::applyListsAndBroadcast( HashRouter& hashRouter, NetworkOPs& networkOPs) { - auto const result = - applyLists(manifest, version, blobs, std::move(siteUri), hash); + auto const result = applyLists(manifest, version, blobs, std::move(siteUri), hash); auto const disposition = result.bestDisposition(); if (disposition == ListDisposition::accepted) @@ -954,20 +868,12 @@ ValidatorList::applyListsAndBroadcast( // this function is only called for PublicKeys which are not specified // in the config file (Note: Keys specified in the local config file are // stored in ValidatorList::localPublisherList data member). - if (broadcast && result.status <= PublisherStatus::expired && - result.publisherKey && + if (broadcast && result.status <= PublisherStatus::expired && result.publisherKey && publisherLists_[*result.publisherKey].maxSequence) { auto const& pubCollection = publisherLists_[*result.publisherKey]; - broadcastBlobs( - *result.publisherKey, - pubCollection, - *pubCollection.maxSequence, - hash, - overlay, - hashRouter, - j_); + broadcastBlobs(*result.publisherKey, pubCollection, *pubCollection.maxSequence, hash, overlay, hashRouter, j_); } return result; @@ -981,10 +887,7 @@ ValidatorList::applyLists( std::string siteUri, std::optional const& hash /* = {} */) { - if (std::count( - std::begin(supportedListVersions), - std::end(supportedListVersions), - version) != 1) + if (std::count(std::begin(supportedListVersions), std::end(supportedListVersions), version) != 1) return PublisherListStats{ListDisposition::unsupported_version}; std::lock_guard lock{mutex_}; @@ -992,19 +895,11 @@ ValidatorList::applyLists( PublisherListStats result; for (auto const& blobInfo : blobs) { - auto stats = applyList( - manifest, - blobInfo.manifest, - blobInfo.blob, - blobInfo.signature, - version, - siteUri, - hash, - lock); + auto stats = + applyList(manifest, blobInfo.manifest, blobInfo.blob, blobInfo.signature, version, siteUri, hash, lock); if (stats.bestDisposition() < result.bestDisposition() || - (stats.bestDisposition() == result.bestDisposition() && - stats.sequence > result.sequence)) + (stats.bestDisposition() == result.bestDisposition() && stats.sequence > result.sequence)) { stats.mergeDispositions(result); result = std::move(stats); @@ -1028,8 +923,7 @@ ValidatorList::applyLists( next == remaining.end() || next->first > iter->first, "xrpl::ValidatorList::applyLists : next is valid"); if (iter->first <= current.sequence || - (next != remaining.end() && - next->second.validFrom <= iter->second.validFrom)) + (next != remaining.end() && next->second.validFrom <= iter->second.validFrom)) { iter = remaining.erase(iter); } @@ -1063,16 +957,13 @@ ValidatorList::updatePublisherList( auto iOld = oldList.begin(); while (iNew != publisherList.end() || iOld != oldList.end()) { - if (iOld == oldList.end() || - (iNew != publisherList.end() && *iNew < *iOld)) + if (iOld == oldList.end() || (iNew != publisherList.end() && *iNew < *iOld)) { // Increment list count for added keys ++keyListings_[*iNew]; ++iNew; } - else if ( - iNew == publisherList.end() || - (iOld != oldList.end() && *iOld < *iNew)) + else if (iNew == publisherList.end() || (iOld != oldList.end() && *iOld < *iNew)) { // Decrement list count for removed keys if (keyListings_[*iOld] <= 1) @@ -1099,16 +990,13 @@ ValidatorList::updatePublisherList( if (!m || !keyListings_.count(m->masterKey)) { - JLOG(j_.warn()) << "List for " << strHex(pubKey) - << " contained untrusted validator manifest"; + JLOG(j_.warn()) << "List for " << strHex(pubKey) << " contained untrusted validator manifest"; continue; } - if (auto const r = validatorManifests_.applyManifest(std::move(*m)); - r == ManifestDisposition::invalid) + if (auto const r = validatorManifests_.applyManifest(std::move(*m)); r == ManifestDisposition::invalid) { - JLOG(j_.warn()) << "List for " << strHex(pubKey) - << " contained invalid validator manifest"; + JLOG(j_.warn()) << "List for " << strHex(pubKey) << " contained invalid validator manifest"; } } } @@ -1135,13 +1023,11 @@ ValidatorList::applyList( return PublisherListStats{ListDisposition::invalid}; } - auto [result, pubKeyOpt] = - verify(lock, list, std::move(*m), blob, signature); + auto [result, pubKeyOpt] = verify(lock, list, std::move(*m), blob, signature); if (!pubKeyOpt) { - JLOG(j_.warn()) - << "UNL manifest is signed with an unrecognized master public key"; + JLOG(j_.warn()) << "UNL manifest is signed with an unrecognized master public key"; return PublisherListStats{result}; } @@ -1164,16 +1050,11 @@ ValidatorList::applyList( { auto const& pubCollection = publisherLists_[pubKey]; if (pubCollection.maxSequence && - (result == ListDisposition::same_sequence || - result == ListDisposition::known_sequence)) + (result == ListDisposition::same_sequence || result == ListDisposition::known_sequence)) { // We've seen something valid list for this publisher // already, so return what we know about it. - return PublisherListStats{ - result, - pubKey, - pubCollection.status, - *pubCollection.maxSequence}; + return PublisherListStats{result, pubKey, pubCollection.status, *pubCollection.maxSequence}; } } return PublisherListStats{result}; @@ -1182,14 +1063,11 @@ ValidatorList::applyList( // Update publisher's list auto& pubCollection = publisherLists_[pubKey]; auto const sequence = list[jss::sequence].asUInt(); - auto const accepted = - (result == ListDisposition::accepted || - result == ListDisposition::expired); + auto const accepted = (result == ListDisposition::accepted || result == ListDisposition::expired); if (accepted) - pubCollection.status = result == ListDisposition::accepted - ? PublisherStatus::available - : PublisherStatus::expired; + pubCollection.status = + result == ListDisposition::accepted ? PublisherStatus::available : PublisherStatus::expired; pubCollection.rawManifest = globalManifest; if (!pubCollection.maxSequence || sequence > *pubCollection.maxSequence) pubCollection.maxSequence = sequence; @@ -1211,19 +1089,15 @@ ValidatorList::applyList( // Remove the entry in "remaining" pubCollection.remaining.erase(sequence); // Done - XRPL_ASSERT( - publisher.sequence == sequence, - "xrpl::ValidatorList::applyList : publisher sequence match"); + XRPL_ASSERT(publisher.sequence == sequence, "xrpl::ValidatorList::applyList : publisher sequence match"); } else { - auto& publisher = accepted ? pubCollection.current - : pubCollection.remaining[sequence]; + auto& publisher = accepted ? pubCollection.current : pubCollection.remaining[sequence]; publisher.sequence = sequence; - publisher.validFrom = TimeKeeper::time_point{TimeKeeper::duration{ - list.isMember(jss::effective) ? list[jss::effective].asUInt() : 0}}; - publisher.validUntil = TimeKeeper::time_point{ - TimeKeeper::duration{list[jss::expiration].asUInt()}}; + publisher.validFrom = TimeKeeper::time_point{ + TimeKeeper::duration{list.isMember(jss::effective) ? list[jss::effective].asUInt() : 0}}; + publisher.validUntil = TimeKeeper::time_point{TimeKeeper::duration{list[jss::expiration].asUInt()}}; publisher.siteUri = std::move(siteUri); publisher.rawBlob = blob; publisher.rawSignature = signature; @@ -1244,23 +1118,18 @@ ValidatorList::applyList( if (val.isObject() && val.isMember(jss::validation_public_key) && val[jss::validation_public_key].isString()) { - std::optional const ret = - strUnHex(val[jss::validation_public_key].asString()); + std::optional const ret = strUnHex(val[jss::validation_public_key].asString()); if (!ret || !publicKeyType(makeSlice(*ret))) { - JLOG(j_.error()) - << "Invalid node identity: " - << val[jss::validation_public_key].asString(); + JLOG(j_.error()) << "Invalid node identity: " << val[jss::validation_public_key].asString(); } else { - publisherList.push_back( - PublicKey(Slice{ret->data(), ret->size()})); + publisherList.push_back(PublicKey(Slice{ret->data(), ret->size()})); } - if (val.isMember(jss::manifest) && - val[jss::manifest].isString()) + if (val.isMember(jss::manifest) && val[jss::manifest].isString()) manifests.push_back(val[jss::manifest].asString()); } } @@ -1278,8 +1147,7 @@ ValidatorList::applyList( pubCollection.rawVersion = std::max(pubCollection.rawVersion, 2u); } - PublisherListStats const applyResult{ - result, pubKey, pubCollection.status, *pubCollection.maxSequence}; + PublisherListStats const applyResult{result, pubKey, pubCollection.status, *pubCollection.maxSequence}; if (accepted) { @@ -1381,16 +1249,14 @@ ValidatorList::verify( if (!r.parse(data, list)) return {ListDisposition::invalid, masterPubKey}; - if (list.isMember(jss::sequence) && list[jss::sequence].isInt() && - list.isMember(jss::expiration) && list[jss::expiration].isInt() && - (!list.isMember(jss::effective) || list[jss::effective].isInt()) && + if (list.isMember(jss::sequence) && list[jss::sequence].isInt() && list.isMember(jss::expiration) && + list[jss::expiration].isInt() && (!list.isMember(jss::effective) || list[jss::effective].isInt()) && list.isMember(jss::validators) && list[jss::validators].isArray()) { auto const sequence = list[jss::sequence].asUInt(); - auto const validFrom = TimeKeeper::time_point{TimeKeeper::duration{ - list.isMember(jss::effective) ? list[jss::effective].asUInt() : 0}}; - auto const validUntil = TimeKeeper::time_point{ - TimeKeeper::duration{list[jss::expiration].asUInt()}}; + auto const validFrom = TimeKeeper::time_point{ + TimeKeeper::duration{list.isMember(jss::effective) ? list[jss::effective].asUInt() : 0}}; + auto const validUntil = TimeKeeper::time_point{TimeKeeper::duration{list[jss::expiration].asUInt()}}; auto const now = timeKeeper_.now(); auto const& listCollection = publisherLists_[masterPubKey]; if (validUntil <= validFrom) @@ -1412,12 +1278,9 @@ ValidatorList::verify( // order. This may result in some duplicated processing, but // prevents the risk of missing valid data. Else return // known_sequence - return !listCollection.maxSequence || - sequence > *listCollection.maxSequence || + return !listCollection.maxSequence || sequence > *listCollection.maxSequence || (listCollection.remaining.count(sequence) == 0 && - validFrom < listCollection.remaining - .at(*listCollection.maxSequence) - .validFrom) + validFrom < listCollection.remaining.at(*listCollection.maxSequence).validFrom) ? std::make_pair(ListDisposition::pending, masterPubKey) : std::make_pair(ListDisposition::known_sequence, masterPubKey); } @@ -1439,9 +1302,7 @@ ValidatorList::listed(PublicKey const& identity) const } bool -ValidatorList::trusted( - ValidatorList::shared_lock const&, - PublicKey const& identity) const +ValidatorList::trusted(ValidatorList::shared_lock const&, PublicKey const& identity) const { auto const pubKey = validatorManifests_.getMasterKey(identity); return trustedMasterKeys_.find(pubKey) != trustedMasterKeys_.end(); @@ -1466,9 +1327,7 @@ ValidatorList::getListedKey(PublicKey const& identity) const } std::optional -ValidatorList::getTrustedKey( - ValidatorList::shared_lock const&, - PublicKey const& identity) const +ValidatorList::getTrustedKey(ValidatorList::shared_lock const&, PublicKey const& identity) const { auto const pubKey = validatorManifests_.getMasterKey(identity); if (trustedMasterKeys_.find(pubKey) != trustedMasterKeys_.end()) @@ -1506,15 +1365,13 @@ ValidatorList::removePublisherList( PublisherStatus reason) { XRPL_ASSERT( - reason != PublisherStatus::available && - reason != PublisherStatus::unavailable, + reason != PublisherStatus::available && reason != PublisherStatus::unavailable, "xrpl::ValidatorList::removePublisherList : valid reason input"); auto const iList = publisherLists_.find(publisherKey); if (iList == publisherLists_.end()) return false; - JLOG(j_.debug()) << "Removing validator list for publisher " - << strHex(publisherKey); + JLOG(j_.debug()) << "Removing validator list for publisher " << strHex(publisherKey); for (auto const& val : iList->second.current.list) { @@ -1644,29 +1501,24 @@ ValidatorList::getJson() const } // Validator keys listed in the local config file - Json::Value& jLocalStaticKeys = - (res[jss::local_static_keys] = Json::arrayValue); + Json::Value& jLocalStaticKeys = (res[jss::local_static_keys] = Json::arrayValue); for (auto const& key : localPublisherList.list) jLocalStaticKeys.append(toBase58(TokenType::NodePublic, key)); // Publisher lists - Json::Value& jPublisherLists = - (res[jss::publisher_lists] = Json::arrayValue); + Json::Value& jPublisherLists = (res[jss::publisher_lists] = Json::arrayValue); for (auto const& [publicKey, pubCollection] : publisherLists_) { Json::Value& curr = jPublisherLists.append(Json::objectValue); curr[jss::pubkey_publisher] = strHex(publicKey); - curr[jss::available] = - pubCollection.status == PublisherStatus::available; + curr[jss::available] = pubCollection.status == PublisherStatus::available; - auto appendList = [](PublisherList const& publisherList, - Json::Value& target) { + auto appendList = [](PublisherList const& publisherList, Json::Value& target) { target[jss::uri] = publisherList.siteUri; if (publisherList.validUntil != TimeKeeper::time_point{}) { - target[jss::seq] = - static_cast(publisherList.sequence); + target[jss::seq] = static_cast(publisherList.sequence); target[jss::expiration] = to_string(publisherList.validUntil); } if (publisherList.validFrom != TimeKeeper::time_point{}) @@ -1696,16 +1548,14 @@ ValidatorList::getJson() const appendList(future, r); // Race conditions can happen, so make this check "fuzzy" XRPL_ASSERT( - future.validFrom > timeKeeper_.now() + 600s, - "xrpl::ValidatorList::getJson : minimum valid from"); + future.validFrom > timeKeeper_.now() + 600s, "xrpl::ValidatorList::getJson : minimum valid from"); } if (remaining.size()) curr[jss::remaining] = std::move(remaining); } // Trusted validator keys - Json::Value& jValidatorKeys = - (res[jss::trusted_validator_keys] = Json::arrayValue); + Json::Value& jValidatorKeys = (res[jss::trusted_validator_keys] = Json::arrayValue); for (auto const& k : trustedMasterKeys_) { jValidatorKeys.append(toBase58(TokenType::NodePublic, k)); @@ -1713,8 +1563,7 @@ ValidatorList::getJson() const // signing keys Json::Value& jSigningKeys = (res[jss::signing_keys] = Json::objectValue); - validatorManifests_.for_each_manifest([&jSigningKeys, - this](Manifest const& manifest) { + validatorManifests_.for_each_manifest([&jSigningKeys, this](Manifest const& manifest) { auto it = keyListings_.find(manifest.masterKey); if (it != keyListings_.end() && manifest.signingKey) { @@ -1737,8 +1586,7 @@ ValidatorList::getJson() const } void -ValidatorList::for_each_listed( - std::function func) const +ValidatorList::for_each_listed(std::function func) const { std::shared_lock read_lock{mutex_}; @@ -1747,14 +1595,13 @@ ValidatorList::for_each_listed( } void -ValidatorList::for_each_available( - std::function const& blobInfos, - PublicKey const& pubKey, - std::size_t maxSequence, - uint256 const& hash)> func) const +ValidatorList::for_each_available(std::function const& blobInfos, + PublicKey const& pubKey, + std::size_t maxSequence, + uint256 const& hash)> func) const { std::shared_lock read_lock{mutex_}; @@ -1762,9 +1609,7 @@ ValidatorList::for_each_available( { if (plCollection.status != PublisherStatus::available) continue; - XRPL_ASSERT( - plCollection.maxSequence != 0, - "xrpl::ValidatorList::for_each_available : nonzero maxSequence"); + XRPL_ASSERT(plCollection.maxSequence != 0, "xrpl::ValidatorList::for_each_available : nonzero maxSequence"); func( plCollection.rawManifest, plCollection.rawVersion, @@ -1776,9 +1621,7 @@ ValidatorList::for_each_available( } std::optional -ValidatorList::getAvailable( - std::string_view pubKey, - std::optional forceVersion /* = {} */) +ValidatorList::getAvailable(std::string_view pubKey, std::optional forceVersion /* = {} */) { std::shared_lock read_lock{mutex_}; @@ -1786,8 +1629,7 @@ ValidatorList::getAvailable( if (!keyBlob || !publicKeyType(makeSlice(*keyBlob))) { - JLOG(j_.warn()) << "Invalid requested validator list publisher key: " - << pubKey; + JLOG(j_.warn()) << "Invalid requested validator list publisher key: " << pubKey; return {}; } @@ -1795,27 +1637,21 @@ ValidatorList::getAvailable( auto const iter = publisherLists_.find(id); - if (iter == publisherLists_.end() || - iter->second.status != PublisherStatus::available) + if (iter == publisherLists_.end() || iter->second.status != PublisherStatus::available) return {}; - Json::Value value = - buildFileData(std::string{pubKey}, iter->second, forceVersion, j_); + Json::Value value = buildFileData(std::string{pubKey}, iter->second, forceVersion, j_); return value; } std::size_t -ValidatorList::calculateQuorum( - std::size_t unlSize, - std::size_t effectiveUnlSize, - std::size_t seenSize) +ValidatorList::calculateQuorum(std::size_t unlSize, std::size_t effectiveUnlSize, std::size_t seenSize) { // Use quorum if specified via command line. if (minimumQuorum_ > 0) { - JLOG(j_.warn()) << "Using potentially unsafe quorum of " - << *minimumQuorum_ + JLOG(j_.warn()) << "Using potentially unsafe quorum of " << *minimumQuorum_ << " as specified on the command line"; return *minimumQuorum_; } @@ -1852,9 +1688,7 @@ ValidatorList::calculateQuorum( auto const errorThreshold = std::min( listThreshold_, // publisherLists_.size() - listThreshold_ + 1); - XRPL_ASSERT( - errorThreshold > 0, - "xrpl::ValidatorList::calculateQuorum : nonzero error threshold"); + XRPL_ASSERT(errorThreshold > 0, "xrpl::ValidatorList::calculateQuorum : nonzero error threshold"); if (unavailable >= errorThreshold) return std::numeric_limits::max(); } @@ -1893,8 +1727,7 @@ ValidatorList::calculateQuorum( // Note that the negative UNL protocol introduced the // AbsoluteMinimumQuorum which is 60% of the original UNL size. The // effective quorum should not be lower than it. - return static_cast(std::max( - std::ceil(effectiveUnlSize * 0.8f), std::ceil(unlSize * 0.6f))); + return static_cast(std::max(std::ceil(effectiveUnlSize * 0.8f), std::ceil(unlSize * 0.6f))); } TrustChanges @@ -1925,8 +1758,7 @@ ValidatorList::updateTrusted( if (iter != remaining.end() && iter->second.validFrom <= closeTime) { // Find the LAST candidate that is ready to go live. - for (auto next = std::next(iter); next != remaining.end() && - next->second.validFrom <= closeTime; + for (auto next = std::next(iter); next != remaining.end() && next->second.validFrom <= closeTime; ++iter, ++next) { XRPL_ASSERT( @@ -1943,17 +1775,13 @@ ValidatorList::updateTrusted( auto sequence = iter->first; auto& candidate = iter->second; auto& current = collection.current; - XRPL_ASSERT( - candidate.validFrom <= closeTime, - "xrpl::ValidatorList::updateTrusted : maximum time"); + XRPL_ASSERT(candidate.validFrom <= closeTime, "xrpl::ValidatorList::updateTrusted : maximum time"); auto const oldList = current.list; current = std::move(candidate); if (collection.status != PublisherStatus::available) collection.status = PublisherStatus::available; - XRPL_ASSERT( - current.sequence == sequence, - "xrpl::ValidatorList::updateTrusted : sequence match"); + XRPL_ASSERT(current.sequence == sequence, "xrpl::ValidatorList::updateTrusted : sequence match"); // If the list is expired, remove the validators so they don't // get processed in. The expiration check below will do the rest // of the work @@ -1967,14 +1795,7 @@ ValidatorList::updateTrusted( // unknown (unlikely). Those that do understand v2 should // already have this list and are in the process of // switching themselves. - broadcastBlobs( - pubKey, - collection, - sequence, - current.hash, - overlay, - hashRouter, - j_); + broadcastBlobs(pubKey, collection, sequence, current.hash, overlay, hashRouter, j_); // Erase any candidates that we skipped over, plus this one remaining.erase(firstIter, std::next(iter)); @@ -1983,8 +1804,7 @@ ValidatorList::updateTrusted( // Remove if expired // ValidatorLists specified in the local config file never expire. // Hence, the below steps are not relevant for localPublisherList - if (collection.status == PublisherStatus::available && - collection.current.validUntil <= closeTime) + if (collection.status == PublisherStatus::available && collection.current.validUntil <= closeTime) { removePublisherList(lock, pubKey, PublisherStatus::expired); ops.setUNLBlocked(); @@ -2010,17 +1830,14 @@ ValidatorList::updateTrusted( } else { - XRPL_ASSERT( - kit->second >= listThreshold_, - "xrpl::ValidatorList::updateTrusted : count meets threshold"); + XRPL_ASSERT(kit->second >= listThreshold_, "xrpl::ValidatorList::updateTrusted : count meets threshold"); ++it; } } for (auto const& val : keyListings_) { - if (val.second >= listThreshold_ && - !validatorManifests_.revoked(val.first) && + if (val.second >= listThreshold_ && !validatorManifests_.revoked(val.first) && trustedMasterKeys_.emplace(val.first).second) trustChanges.added.insert(calcNodeID(val.first)); } @@ -2035,18 +1852,14 @@ ValidatorList::updateTrusted( // manifests must contain a valid signingKey for (auto const& k : trustedMasterKeys_) { - std::optional const signingKey = - validatorManifests_.getSigningKey(k); - XRPL_ASSERT( - signingKey, - "xrpl::ValidatorList::updateTrusted : found signing key"); + std::optional const signingKey = validatorManifests_.getSigningKey(k); + XRPL_ASSERT(signingKey, "xrpl::ValidatorList::updateTrusted : found signing key"); trustedSigningKeys_.insert(*signingKey); } } - JLOG(j_.debug()) - << trustedMasterKeys_.size() << " of " << keyListings_.size() - << " listed validators eligible for inclusion in the trusted set"; + JLOG(j_.debug()) << trustedMasterKeys_.size() << " of " << keyListings_.size() + << " listed validators eligible for inclusion in the trusted set"; auto const unlSize = trustedMasterKeys_.size(); auto effectiveUnlSize = unlSize; @@ -2071,20 +1884,16 @@ ValidatorList::updateTrusted( } quorum_ = calculateQuorum(unlSize, effectiveUnlSize, seenSize); - JLOG(j_.debug()) << "Using quorum of " << quorum_ << " for new set of " - << unlSize << " trusted validators (" - << trustChanges.added.size() << " added, " - << trustChanges.removed.size() << " removed)"; + JLOG(j_.debug()) << "Using quorum of " << quorum_ << " for new set of " << unlSize << " trusted validators (" + << trustChanges.added.size() << " added, " << trustChanges.removed.size() << " removed)"; if (unlSize < quorum_) { - JLOG(j_.warn()) << "New quorum of " << quorum_ - << " exceeds the number of trusted validators (" - << unlSize << ")"; + JLOG(j_.warn()) << "New quorum of " << quorum_ << " exceeds the number of trusted validators (" << unlSize + << ")"; } - if ((publisherLists_.size() || localPublisherList.list.size()) && - unlSize == 0) + if ((publisherLists_.size() || localPublisherList.list.size()) && unlSize == 0) { // No validators. Lock down. ops.setUNLBlocked(); @@ -2122,8 +1931,7 @@ ValidatorList::setNegativeUNL(hash_set const& negUnl) } std::vector> -ValidatorList::negativeUNLFilter( - std::vector>&& validations) const +ValidatorList::negativeUNLFilter(std::vector>&& validations) const { // Remove validations that are from validators on the negative UNL. auto ret = std::move(validations); @@ -2136,9 +1944,7 @@ ValidatorList::negativeUNLFilter( ret.begin(), ret.end(), [&](auto const& v) -> bool { - if (auto const masterKey = - getTrustedKey(read_lock, v->getSignerPublic()); - masterKey) + if (auto const masterKey = getTrustedKey(read_lock, v->getSignerPublic()); masterKey) { return negativeUNL_.count(*masterKey); } diff --git a/src/xrpld/app/misc/detail/ValidatorSite.cpp b/src/xrpld/app/misc/detail/ValidatorSite.cpp index a76980ac02..7d440028cf 100644 --- a/src/xrpld/app/misc/detail/ValidatorSite.cpp +++ b/src/xrpld/app/misc/detail/ValidatorSite.cpp @@ -66,10 +66,7 @@ ValidatorSite::Site::Site(std::string uri) { } -ValidatorSite::ValidatorSite( - Application& app, - std::optional j, - std::chrono::seconds timeout) +ValidatorSite::ValidatorSite(Application& app, std::optional j, std::chrono::seconds timeout) : app_{app} , j_{j ? *j : app_.logs().journal("ValidatorSite")} , timer_{app_.getIOContext()} @@ -115,9 +112,7 @@ ValidatorSite::load(std::vector const& siteURIs) } bool -ValidatorSite::load( - std::vector const& siteURIs, - std::lock_guard const& lock_sites) +ValidatorSite::load(std::vector const& siteURIs, std::lock_guard const& lock_sites) { // If no sites are provided, act as if a site failed to load. if (siteURIs.empty()) @@ -133,8 +128,7 @@ ValidatorSite::load( } catch (std::exception const& e) { - JLOG(j_.error()) - << "Invalid validator site uri: " << uri << ": " << e.what(); + JLOG(j_.error()) << "Invalid validator site uri: " << uri << ": " << e.what(); return false; } } @@ -187,14 +181,10 @@ ValidatorSite::stop() } void -ValidatorSite::setTimer( - std::lock_guard const& site_lock, - std::lock_guard const& state_lock) +ValidatorSite::setTimer(std::lock_guard const& site_lock, std::lock_guard const& state_lock) { auto next = std::min_element( - sites_.begin(), sites_.end(), [](Site const& a, Site const& b) { - return a.nextRefresh < b.nextRefresh; - }); + sites_.begin(), sites_.end(), [](Site const& a, Site const& b) { return a.nextRefresh < b.nextRefresh; }); if (next != sites_.end()) { @@ -202,9 +192,7 @@ ValidatorSite::setTimer( cv_.notify_all(); timer_.expires_at(next->nextRefresh); auto idx = std::distance(sites_.begin(), next); - timer_.async_wait([this, idx](boost::system::error_code const& ec) { - this->onTimer(idx, ec); - }); + timer_.async_wait([this, idx](boost::system::error_code const& ec) { this->onTimer(idx, ec); }); } } @@ -230,15 +218,12 @@ ValidatorSite::makeRequest( } }; auto onFetch = [this, siteIdx, timeoutCancel]( - error_code const& err, - endpoint_type const& endpoint, - detail::response_type&& resp) { + error_code const& err, endpoint_type const& endpoint, detail::response_type&& resp) { timeoutCancel(); onSiteFetch(err, endpoint, std::move(resp), siteIdx); }; - auto onFetchFile = [this, siteIdx, timeoutCancel]( - error_code const& err, std::string const& resp) { + auto onFetchFile = [this, siteIdx, timeoutCancel](error_code const& err, std::string const& resp) { timeoutCancel(); onTextFetch(err, resp, siteIdx); }; @@ -273,8 +258,7 @@ ValidatorSite::makeRequest( else { BOOST_ASSERT(resource->pUrl.scheme == "file"); - sp = std::make_shared( - resource->pUrl.path, app_.getIOContext(), onFetchFile); + sp = std::make_shared(resource->pUrl.path, app_.getIOContext(), onFetchFile); } sites_[siteIdx].lastRequestSuccessful = false; @@ -284,9 +268,7 @@ ValidatorSite::makeRequest( // than requestTimeout_ to complete std::lock_guard lock_state{state_mutex_}; timer_.expires_after(requestTimeout_); - timer_.async_wait([this, siteIdx](boost::system::error_code const& ec) { - this->onRequestTimeout(siteIdx, ec); - }); + timer_.async_wait([this, siteIdx](boost::system::error_code const& ec) { this->onRequestTimeout(siteIdx, ec); }); } void @@ -305,8 +287,7 @@ ValidatorSite::onRequestTimeout(std::size_t siteIdx, error_code const& ec) // first, which will leave activeResource empty. auto const& site = sites_[siteIdx]; if (site.activeResource) - JLOG(j_.warn()) << "Request for " << site.activeResource->uri - << " took too long"; + JLOG(j_.warn()) << "Request for " << site.activeResource->uri << " took too long"; else JLOG(j_.error()) << "Request took too long, but a response has " "already been processed"; @@ -332,8 +313,7 @@ ValidatorSite::onTimer(std::size_t siteIdx, error_code const& ec) try { std::lock_guard lock{sites_mutex_}; - sites_[siteIdx].nextRefresh = - clock_type::now() + sites_[siteIdx].refreshInterval; + sites_[siteIdx].nextRefresh = clock_type::now() + sites_[siteIdx].refreshInterval; sites_[siteIdx].redirCount = 0; // the WorkSSL client ctor can throw if SSL init fails makeRequest(sites_[siteIdx].startingResource, siteIdx, lock); @@ -342,10 +322,7 @@ ValidatorSite::onTimer(std::size_t siteIdx, error_code const& ec) { JLOG(j_.error()) << "Exception in " << __func__ << ": " << ex.what(); onSiteFetch( - boost::system::error_code{-1, boost::system::generic_category()}, - {}, - detail::response_type{}, - siteIdx); + boost::system::error_code{-1, boost::system::generic_category()}, {}, detail::response_type{}, siteIdx); } } @@ -360,8 +337,7 @@ ValidatorSite::parseJsonResponse( Json::Value body; if (!r.parse(res.data(), body)) { - JLOG(j_.warn()) << "Unable to parse JSON response from " - << sites_[siteIdx].activeResource->uri; + JLOG(j_.warn()) << "Unable to parse JSON response from " << sites_[siteIdx].activeResource->uri; throw std::runtime_error{"bad json"}; } return body; @@ -369,9 +345,8 @@ ValidatorSite::parseJsonResponse( auto const [valid, version, blobs] = [&body]() { // Check the easy fields first - bool valid = body.isObject() && body.isMember(jss::manifest) && - body[jss::manifest].isString() && body.isMember(jss::version) && - body[jss::version].isInt(); + bool valid = body.isObject() && body.isMember(jss::manifest) && body[jss::manifest].isString() && + body.isMember(jss::version) && body[jss::version].isInt(); // Check the version-specific blob & signature fields std::uint32_t version; std::vector blobs; @@ -386,90 +361,62 @@ ValidatorSite::parseJsonResponse( if (!valid) { - JLOG(j_.warn()) << "Missing fields in JSON response from " - << sites_[siteIdx].activeResource->uri; + JLOG(j_.warn()) << "Missing fields in JSON response from " << sites_[siteIdx].activeResource->uri; throw std::runtime_error{"missing fields"}; } auto const manifest = body[jss::manifest].asString(); - XRPL_ASSERT( - version == body[jss::version].asUInt(), - "xrpl::ValidatorSite::parseJsonResponse : version match"); + XRPL_ASSERT(version == body[jss::version].asUInt(), "xrpl::ValidatorSite::parseJsonResponse : version match"); auto const& uri = sites_[siteIdx].activeResource->uri; auto const hash = sha512Half(manifest, blobs, version); auto const applyResult = app_.validators().applyListsAndBroadcast( - manifest, - version, - blobs, - uri, - hash, - app_.overlay(), - app_.getHashRouter(), - app_.getOPs()); + manifest, version, blobs, uri, hash, app_.overlay(), app_.getHashRouter(), app_.getOPs()); - sites_[siteIdx].lastRefreshStatus.emplace( - Site::Status{clock_type::now(), applyResult.bestDisposition(), ""}); + sites_[siteIdx].lastRefreshStatus.emplace(Site::Status{clock_type::now(), applyResult.bestDisposition(), ""}); for (auto const& [disp, count] : applyResult.dispositions) { switch (disp) { case ListDisposition::accepted: - JLOG(j_.debug()) << "Applied " << count - << " new validator list(s) from " << uri; + JLOG(j_.debug()) << "Applied " << count << " new validator list(s) from " << uri; break; case ListDisposition::expired: - JLOG(j_.debug()) << "Applied " << count - << " expired validator list(s) from " << uri; + JLOG(j_.debug()) << "Applied " << count << " expired validator list(s) from " << uri; break; case ListDisposition::same_sequence: - JLOG(j_.debug()) - << "Ignored " << count - << " validator list(s) with current sequence from " << uri; + JLOG(j_.debug()) << "Ignored " << count << " validator list(s) with current sequence from " << uri; break; case ListDisposition::pending: - JLOG(j_.debug()) << "Processed " << count - << " future validator list(s) from " << uri; + JLOG(j_.debug()) << "Processed " << count << " future validator list(s) from " << uri; break; case ListDisposition::known_sequence: - JLOG(j_.debug()) - << "Ignored " << count - << " validator list(s) with future known sequence from " - << uri; + JLOG(j_.debug()) << "Ignored " << count << " validator list(s) with future known sequence from " << uri; break; case ListDisposition::stale: - JLOG(j_.warn()) << "Ignored " << count - << "stale validator list(s) from " << uri; + JLOG(j_.warn()) << "Ignored " << count << "stale validator list(s) from " << uri; break; case ListDisposition::untrusted: - JLOG(j_.warn()) << "Ignored " << count - << " untrusted validator list(s) from " << uri; + JLOG(j_.warn()) << "Ignored " << count << " untrusted validator list(s) from " << uri; break; case ListDisposition::invalid: - JLOG(j_.warn()) << "Ignored " << count - << " invalid validator list(s) from " << uri; + JLOG(j_.warn()) << "Ignored " << count << " invalid validator list(s) from " << uri; break; case ListDisposition::unsupported_version: - JLOG(j_.warn()) - << "Ignored " << count - << " unsupported version validator list(s) from " << uri; + JLOG(j_.warn()) << "Ignored " << count << " unsupported version validator list(s) from " << uri; break; default: BOOST_ASSERT(false); } } - if (body.isMember(jss::refresh_interval) && - body[jss::refresh_interval].isNumeric()) + if (body.isMember(jss::refresh_interval) && body[jss::refresh_interval].isNumeric()) { using namespace std::chrono_literals; - std::chrono::minutes const refresh = std::clamp( - std::chrono::minutes{body[jss::refresh_interval].asUInt()}, - 1min, - std::chrono::minutes{24h}); + std::chrono::minutes const refresh = + std::clamp(std::chrono::minutes{body[jss::refresh_interval].asUInt()}, 1min, std::chrono::minutes{24h}); sites_[siteIdx].refreshInterval = refresh; - sites_[siteIdx].nextRefresh = - clock_type::now() + sites_[siteIdx].refreshInterval; + sites_[siteIdx].nextRefresh = clock_type::now() + sites_[siteIdx].refreshInterval; } } @@ -483,37 +430,30 @@ ValidatorSite::processRedirect( std::shared_ptr newLocation; if (res.find(field::location) == res.end() || res[field::location].empty()) { - JLOG(j_.warn()) << "Request for validator list at " - << sites_[siteIdx].activeResource->uri + JLOG(j_.warn()) << "Request for validator list at " << sites_[siteIdx].activeResource->uri << " returned a redirect with no Location."; throw std::runtime_error{"missing location"}; } if (sites_[siteIdx].redirCount == max_redirects) { - JLOG(j_.warn()) << "Exceeded max redirects for validator list at " - << sites_[siteIdx].loadedResource->uri; + JLOG(j_.warn()) << "Exceeded max redirects for validator list at " << sites_[siteIdx].loadedResource->uri; throw std::runtime_error{"max redirects"}; } - JLOG(j_.debug()) << "Got redirect for validator list from " - << sites_[siteIdx].activeResource->uri + JLOG(j_.debug()) << "Got redirect for validator list from " << sites_[siteIdx].activeResource->uri << " to new location " << res[field::location]; try { - newLocation = - std::make_shared(std::string(res[field::location])); + newLocation = std::make_shared(std::string(res[field::location])); ++sites_[siteIdx].redirCount; - if (newLocation->pUrl.scheme != "http" && - newLocation->pUrl.scheme != "https") - throw std::runtime_error( - "invalid scheme in redirect " + newLocation->pUrl.scheme); + if (newLocation->pUrl.scheme != "http" && newLocation->pUrl.scheme != "https") + throw std::runtime_error("invalid scheme in redirect " + newLocation->pUrl.scheme); } catch (std::exception const& ex) { - JLOG(j_.error()) << "Invalid redirect location: " - << res[field::location]; + JLOG(j_.error()) << "Invalid redirect location: " << res[field::location]; throw; } return newLocation; @@ -530,15 +470,12 @@ ValidatorSite::onSiteFetch( { if (endpoint != endpoint_type{}) sites_[siteIdx].lastRequestEndpoint = endpoint; - JLOG(j_.debug()) << "Got completion for " - << sites_[siteIdx].activeResource->uri << " " - << endpoint; + JLOG(j_.debug()) << "Got completion for " << sites_[siteIdx].activeResource->uri << " " << endpoint; auto onError = [&](std::string const& errMsg, bool retry) { - sites_[siteIdx].lastRefreshStatus.emplace(Site::Status{ - clock_type::now(), ListDisposition::invalid, errMsg}); + sites_[siteIdx].lastRefreshStatus.emplace( + Site::Status{clock_type::now(), ListDisposition::invalid, errMsg}); if (retry) - sites_[siteIdx].nextRefresh = - clock_type::now() + error_retry_interval; + sites_[siteIdx].nextRefresh = clock_type::now() + error_retry_interval; // See if there's a copy saved locally from last time we // saw the list. @@ -546,10 +483,8 @@ ValidatorSite::onSiteFetch( }; if (ec) { - JLOG(j_.warn()) - << "Problem retrieving from " - << sites_[siteIdx].activeResource->uri << " " << endpoint << " " - << ec.value() << ":" << ec.message(); + JLOG(j_.warn()) << "Problem retrieving from " << sites_[siteIdx].activeResource->uri << " " << endpoint + << " " << ec.value() << ":" << ec.message(); onError("fetch error", true); } else @@ -567,15 +502,13 @@ ValidatorSite::onSiteFetch( case status::permanent_redirect: case status::found: case status::temporary_redirect: { - auto newLocation = - processRedirect(res, siteIdx, lock_sites); + auto newLocation = processRedirect(res, siteIdx, lock_sites); XRPL_ASSERT( newLocation, "xrpl::ValidatorSite::onSiteFetch : non-null " "validator"); // for perm redirects, also update our starting URI - if (res.result() == status::moved_permanently || - res.result() == status::permanent_redirect) + if (res.result() == status::moved_permanently || res.result() == status::permanent_redirect) { sites_[siteIdx].startingResource = newLocation; } @@ -584,19 +517,15 @@ ValidatorSite::onSiteFetch( // state update/notify below } default: { - JLOG(j_.warn()) - << "Request for validator list at " - << sites_[siteIdx].activeResource->uri << " " - << endpoint - << " returned bad status: " << res.result_int(); + JLOG(j_.warn()) << "Request for validator list at " << sites_[siteIdx].activeResource->uri + << " " << endpoint << " returned bad status: " << res.result_int(); onError("bad result code", true); } } } catch (std::exception const& ex) { - JLOG(j_.error()) - << "Exception in " << __func__ << ": " << ex.what(); + JLOG(j_.error()) << "Exception in " << __func__ << ": " << ex.what(); onError(ex.what(), false); } } @@ -611,10 +540,7 @@ ValidatorSite::onSiteFetch( } void -ValidatorSite::onTextFetch( - boost::system::error_code const& ec, - std::string const& res, - std::size_t siteIdx) +ValidatorSite::onTextFetch(boost::system::error_code const& ec, std::string const& res, std::size_t siteIdx) { std::lock_guard lock_sites{sites_mutex_}; { @@ -622,8 +548,7 @@ ValidatorSite::onTextFetch( { if (ec) { - JLOG(j_.warn()) << "Problem retrieving from " - << sites_[siteIdx].activeResource->uri << " " + JLOG(j_.warn()) << "Problem retrieving from " << sites_[siteIdx].activeResource->uri << " " << ec.value() << ": " << ec.message(); throw std::runtime_error{"fetch error"}; } @@ -634,10 +559,9 @@ ValidatorSite::onTextFetch( } catch (std::exception const& ex) { - JLOG(j_.error()) - << "Exception in " << __func__ << ": " << ex.what(); - sites_[siteIdx].lastRefreshStatus.emplace(Site::Status{ - clock_type::now(), ListDisposition::invalid, ex.what()}); + JLOG(j_.error()) << "Exception in " << __func__ << ": " << ex.what(); + sites_[siteIdx].lastRefreshStatus.emplace( + Site::Status{clock_type::now(), ListDisposition::invalid, ex.what()}); } sites_[siteIdx].activeResource.reset(); } @@ -670,16 +594,12 @@ ValidatorSite::getJson() const v[jss::next_refresh_time] = to_string(site.nextRefresh); if (site.lastRefreshStatus) { - v[jss::last_refresh_time] = - to_string(site.lastRefreshStatus->refreshed); - v[jss::last_refresh_status] = - to_string(site.lastRefreshStatus->disposition); + v[jss::last_refresh_time] = to_string(site.lastRefreshStatus->refreshed); + v[jss::last_refresh_status] = to_string(site.lastRefreshStatus->disposition); if (!site.lastRefreshStatus->message.empty()) - v[jss::last_refresh_message] = - site.lastRefreshStatus->message; + v[jss::last_refresh_message] = site.lastRefreshStatus->message; } - v[jss::refresh_interval_min] = - static_cast(site.refreshInterval.count()); + v[jss::refresh_interval_min] = static_cast(site.refreshInterval.count()); } } return jrr; diff --git a/src/xrpld/app/misc/detail/Work.h b/src/xrpld/app/misc/detail/Work.h index 4d1547c4fb..90e81b7bbf 100644 --- a/src/xrpld/app/misc/detail/Work.h +++ b/src/xrpld/app/misc/detail/Work.h @@ -8,8 +8,7 @@ namespace xrpl { namespace detail { -using response_type = - boost::beast::http::response; +using response_type = boost::beast::http::response; class Work { diff --git a/src/xrpld/app/misc/detail/WorkBase.h b/src/xrpld/app/misc/detail/WorkBase.h index 6c46749f6d..1e519c7b2f 100644 --- a/src/xrpld/app/misc/detail/WorkBase.h +++ b/src/xrpld/app/misc/detail/WorkBase.h @@ -25,15 +25,13 @@ protected: using endpoint_type = boost::asio::ip::tcp::endpoint; public: - using callback_type = std::function< - void(error_code const&, endpoint_type const&, response_type&&)>; + using callback_type = std::function; protected: using socket_type = boost::asio::ip::tcp::socket; using resolver_type = boost::asio::ip::tcp::resolver; using results_type = boost::asio::ip::tcp::resolver::results_type; - using request_type = - boost::beast::http::request; + using request_type = boost::beast::http::request; std::string host_; std::string path_; @@ -123,9 +121,7 @@ template WorkBase::~WorkBase() { if (cb_) - cb_(make_error_code(boost::system::errc::not_a_socket), - lastEndpoint_, - std::move(res_)); + cb_(make_error_code(boost::system::errc::not_a_socket), lastEndpoint_, std::move(res_)); close(); } @@ -135,20 +131,14 @@ WorkBase::run() { if (!strand_.running_in_this_thread()) return boost::asio::post( - ios_, - boost::asio::bind_executor( - strand_, std::bind(&WorkBase::run, impl().shared_from_this()))); + ios_, boost::asio::bind_executor(strand_, std::bind(&WorkBase::run, impl().shared_from_this()))); resolver_.async_resolve( host_, port_, boost::asio::bind_executor( strand_, - std::bind( - &WorkBase::onResolve, - impl().shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + std::bind(&WorkBase::onResolve, impl().shared_from_this(), std::placeholders::_1, std::placeholders::_2))); } template @@ -160,9 +150,7 @@ WorkBase::cancel() return boost::asio::post( ios_, - boost::asio::bind_executor( - strand_, - std::bind(&WorkBase::cancel, impl().shared_from_this()))); + boost::asio::bind_executor(strand_, std::bind(&WorkBase::cancel, impl().shared_from_this()))); } error_code ec; @@ -193,11 +181,7 @@ WorkBase::onResolve(error_code const& ec, results_type results) results, boost::asio::bind_executor( strand_, - std::bind( - &WorkBase::onConnect, - impl().shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + std::bind(&WorkBase::onConnect, impl().shared_from_this(), std::placeholders::_1, std::placeholders::_2))); } template @@ -226,11 +210,7 @@ WorkBase::onStart() impl().stream(), req_, boost::asio::bind_executor( - strand_, - std::bind( - &WorkBase::onRequest, - impl().shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&WorkBase::onRequest, impl().shared_from_this(), std::placeholders::_1))); } template @@ -245,11 +225,7 @@ WorkBase::onRequest(error_code const& ec) readBuf_, res_, boost::asio::bind_executor( - strand_, - std::bind( - &WorkBase::onResponse, - impl().shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&WorkBase::onResponse, impl().shared_from_this(), std::placeholders::_1))); } template diff --git a/src/xrpld/app/misc/detail/WorkFile.h b/src/xrpld/app/misc/detail/WorkFile.h index ac926ede1f..cce7fd410e 100644 --- a/src/xrpld/app/misc/detail/WorkFile.h +++ b/src/xrpld/app/misc/detail/WorkFile.h @@ -24,14 +24,10 @@ protected: using response_type = std::string; public: - using callback_type = - std::function; + using callback_type = std::function; public: - WorkFile( - std::string const& path, - boost::asio::io_context& ios, - callback_type cb); + WorkFile(std::string const& path, boost::asio::io_context& ios, callback_type cb); ~WorkFile(); void @@ -49,14 +45,8 @@ private: //------------------------------------------------------------------------------ -WorkFile::WorkFile( - std::string const& path, - boost::asio::io_context& ios, - callback_type cb) - : path_(path) - , cb_(std::move(cb)) - , ios_(ios) - , strand_(boost::asio::make_strand(ios)) +WorkFile::WorkFile(std::string const& path, boost::asio::io_context& ios, callback_type cb) + : path_(path), cb_(std::move(cb)), ios_(ios), strand_(boost::asio::make_strand(ios)) { } @@ -71,9 +61,7 @@ WorkFile::run() { if (!strand_.running_in_this_thread()) return boost::asio::post( - ios_, - boost::asio::bind_executor( - strand_, std::bind(&WorkFile::run, shared_from_this()))); + ios_, boost::asio::bind_executor(strand_, std::bind(&WorkFile::run, shared_from_this()))); error_code ec; auto const fileContents = getFileContents(ec, path_, megabytes(1)); diff --git a/src/xrpld/app/misc/detail/WorkPlain.h b/src/xrpld/app/misc/detail/WorkPlain.h index 23bae20006..cac6d76a62 100644 --- a/src/xrpld/app/misc/detail/WorkPlain.h +++ b/src/xrpld/app/misc/detail/WorkPlain.h @@ -8,8 +8,7 @@ namespace xrpl { namespace detail { // Work over TCP/IP -class WorkPlain : public WorkBase, - public std::enable_shared_from_this +class WorkPlain : public WorkBase, public std::enable_shared_from_this { friend class WorkBase; diff --git a/src/xrpld/app/misc/detail/WorkSSL.cpp b/src/xrpld/app/misc/detail/WorkSSL.cpp index 6ccc83f595..47902e900a 100644 --- a/src/xrpld/app/misc/detail/WorkSSL.cpp +++ b/src/xrpld/app/misc/detail/WorkSSL.cpp @@ -24,8 +24,7 @@ WorkSSL::WorkSSL( { auto ec = context_.preConnectVerify(stream_, host_); if (ec) - Throw( - boost::str(boost::format("preConnectVerify: %s") % ec.message())); + Throw(boost::str(boost::format("preConnectVerify: %s") % ec.message())); } void @@ -38,11 +37,7 @@ WorkSSL::onConnect(error_code const& ec) stream_.async_handshake( boost::asio::ssl::stream_base::client, boost::asio::bind_executor( - strand_, - std::bind( - &WorkSSL::onHandshake, - shared_from_this(), - std::placeholders::_1))); + strand_, std::bind(&WorkSSL::onHandshake, shared_from_this(), std::placeholders::_1))); } void diff --git a/src/xrpld/app/misc/detail/WorkSSL.h b/src/xrpld/app/misc/detail/WorkSSL.h index 7dd1a94c9e..bed963d8ec 100644 --- a/src/xrpld/app/misc/detail/WorkSSL.h +++ b/src/xrpld/app/misc/detail/WorkSSL.h @@ -17,8 +17,7 @@ namespace xrpl { namespace detail { // Work over SSL -class WorkSSL : public WorkBase, - public std::enable_shared_from_this +class WorkSSL : public WorkBase, public std::enable_shared_from_this { friend class WorkBase; diff --git a/src/xrpld/app/paths/AMMContext.h b/src/xrpld/app/paths/AMMContext.h index a272ba291e..9e82a7394a 100644 --- a/src/xrpld/app/paths/AMMContext.h +++ b/src/xrpld/app/paths/AMMContext.h @@ -32,8 +32,7 @@ private: std::uint16_t ammIters_{0}; public: - AMMContext(AccountID const& account, bool multiPath) - : account_(account), multiPath_(multiPath) + AMMContext(AccountID const& account, bool multiPath) : account_(account), multiPath_(multiPath) { } ~AMMContext() = default; diff --git a/src/xrpld/app/paths/AMMLiquidity.h b/src/xrpld/app/paths/AMMLiquidity.h index b5b865d80e..c22901b28e 100644 --- a/src/xrpld/app/paths/AMMLiquidity.h +++ b/src/xrpld/app/paths/AMMLiquidity.h @@ -63,8 +63,7 @@ public: * quality. */ std::optional> - getOffer(ReadView const& view, std::optional const& clobQuality) - const; + getOffer(ReadView const& view, std::optional const& clobQuality) const; AccountID const& ammAccount() const diff --git a/src/xrpld/app/paths/AMMOffer.h b/src/xrpld/app/paths/AMMOffer.h index 7a81e53176..893938f0f2 100644 --- a/src/xrpld/app/paths/AMMOffer.h +++ b/src/xrpld/app/paths/AMMOffer.h @@ -81,20 +81,14 @@ public: * current quality. */ TAmounts - limitOut( - TAmounts const& offerAmount, - TOut const& limit, - bool roundUp) const; + limitOut(TAmounts const& offerAmount, TOut const& limit, bool roundUp) const; /** Limit in of the provided offer. If one-path then swapIn * using current balances. If multi-path then ceil_in using * current quality. */ TAmounts - limitIn( - TAmounts const& offerAmount, - TIn const& limit, - bool roundUp) const; + limitIn(TAmounts const& offerAmount, TIn const& limit, bool roundUp) const; QualityFunction getQualityFunc() const; diff --git a/src/xrpld/app/paths/AccountCurrencies.cpp b/src/xrpld/app/paths/AccountCurrencies.cpp index fbb9c63cd8..8e51999018 100644 --- a/src/xrpld/app/paths/AccountCurrencies.cpp +++ b/src/xrpld/app/paths/AccountCurrencies.cpp @@ -3,10 +3,7 @@ namespace xrpl { hash_set -accountSourceCurrencies( - AccountID const& account, - std::shared_ptr const& lrCache, - bool includeXRP) +accountSourceCurrencies(AccountID const& account, std::shared_ptr const& lrCache, bool includeXRP) { hash_set currencies; @@ -14,8 +11,7 @@ accountSourceCurrencies( if (includeXRP) currencies.insert(xrpCurrency()); - if (auto const lines = - lrCache->getRippleLines(account, LineDirection::outgoing)) + if (auto const lines = lrCache->getRippleLines(account, LineDirection::outgoing)) { for (auto const& rspEntry : *lines) { @@ -24,10 +20,9 @@ accountSourceCurrencies( // Filter out non if (saBalance > beast::zero // Have IOUs to send. - || - (rspEntry.getLimitPeer() - // Peer extends credit. - && ((-saBalance) < rspEntry.getLimitPeer()))) // Credit left. + || (rspEntry.getLimitPeer() + // Peer extends credit. + && ((-saBalance) < rspEntry.getLimitPeer()))) // Credit left. { currencies.insert(saBalance.getCurrency()); } @@ -39,10 +34,7 @@ accountSourceCurrencies( } hash_set -accountDestCurrencies( - AccountID const& account, - std::shared_ptr const& lrCache, - bool includeXRP) +accountDestCurrencies(AccountID const& account, std::shared_ptr const& lrCache, bool includeXRP) { hash_set currencies; @@ -50,8 +42,7 @@ accountDestCurrencies( currencies.insert(xrpCurrency()); // Even if account doesn't exist - if (auto const lines = - lrCache->getRippleLines(account, LineDirection::outgoing)) + if (auto const lines = lrCache->getRippleLines(account, LineDirection::outgoing)) { for (auto const& rspEntry : *lines) { diff --git a/src/xrpld/app/paths/AccountCurrencies.h b/src/xrpld/app/paths/AccountCurrencies.h index de46a13808..f0fa1bc504 100644 --- a/src/xrpld/app/paths/AccountCurrencies.h +++ b/src/xrpld/app/paths/AccountCurrencies.h @@ -8,16 +8,10 @@ namespace xrpl { hash_set -accountDestCurrencies( - AccountID const& account, - std::shared_ptr const& cache, - bool includeXRP); +accountDestCurrencies(AccountID const& account, std::shared_ptr const& cache, bool includeXRP); hash_set -accountSourceCurrencies( - AccountID const& account, - std::shared_ptr const& lrLedger, - bool includeXRP); +accountSourceCurrencies(AccountID const& account, std::shared_ptr const& lrLedger, bool includeXRP); } // namespace xrpl diff --git a/src/xrpld/app/paths/Flow.cpp b/src/xrpld/app/paths/Flow.cpp index b5088d15b3..1f6d29bfb9 100644 --- a/src/xrpld/app/paths/Flow.cpp +++ b/src/xrpld/app/paths/Flow.cpp @@ -13,11 +13,7 @@ namespace xrpl { template static auto -finishFlow( - PaymentSandbox& sb, - Issue const& srcIssue, - Issue const& dstIssue, - FlowResult&& f) +finishFlow(PaymentSandbox& sb, Issue const& srcIssue, Issue const& dstIssue, FlowResult&& f) { path::RippleCalc::Output result; if (f.ter == tesSUCCESS) @@ -94,8 +90,7 @@ flow( if (j.trace()) { - j.trace() << "\nsrc: " << src << "\ndst: " << dst - << "\nsrcIssue: " << srcIssue << "\ndstIssue: " << dstIssue; + j.trace() << "\nsrc: " << src << "\ndst: " << dst << "\nsrcIssue: " << srcIssue << "\ndstIssue: " << dstIssue; j.trace() << "\nNumStrands: " << strands.size(); for (auto const& curStrand : strands) { diff --git a/src/xrpld/app/paths/PathRequest.cpp b/src/xrpld/app/paths/PathRequest.cpp index 41bae4b178..e2a3e14485 100644 --- a/src/xrpld/app/paths/PathRequest.cpp +++ b/src/xrpld/app/paths/PathRequest.cpp @@ -76,21 +76,17 @@ PathRequest::~PathRequest() if (quick_reply_ != steady_clock::time_point{}) { fast = " fast:"; - fast += std::to_string( - duration_cast(quick_reply_ - created_).count()); + fast += std::to_string(duration_cast(quick_reply_ - created_).count()); fast += "ms"; } if (full_reply_ != steady_clock::time_point{}) { full = " full:"; - full += std::to_string( - duration_cast(full_reply_ - created_).count()); + full += std::to_string(duration_cast(full_reply_ - created_).count()); full += "ms"; } - stream - << iIdentifier << " complete:" << fast << full << " total:" - << duration_cast(steady_clock::now() - created_).count() - << "ms"; + stream << iIdentifier << " complete:" << fast << full + << " total:" << duration_cast(steady_clock::now() - created_).count() << "ms"; } bool @@ -173,8 +169,7 @@ PathRequest::isValid(std::shared_ptr const& crCache) auto const sleDest = lrLedger->read(keylet::account(*raDstAccount)); - Json::Value& jvDestCur = - (jvStatus[jss::destination_currencies] = Json::arrayValue); + Json::Value& jvDestCur = (jvStatus[jss::destination_currencies] = Json::arrayValue); if (!sleDest) { @@ -197,13 +192,11 @@ PathRequest::isValid(std::shared_ptr const& crCache) { bool const disallowXRP(sleDest->getFlags() & lsfDisallowXRP); - auto usDestCurrID = - accountDestCurrencies(*raDstAccount, crCache, !disallowXRP); + auto usDestCurrID = accountDestCurrencies(*raDstAccount, crCache, !disallowXRP); for (auto const& currency : usDestCurrID) jvDestCur.append(to_string(currency)); - jvStatus[jss::destination_tag] = - (sleDest->getFlags() & lsfRequireDestTag); + jvStatus[jss::destination_tag] = (sleDest->getFlags() & lsfRequireDestTag); } jvStatus[jss::ledger_hash] = to_string(lrLedger->header().hash); @@ -221,9 +214,7 @@ PathRequest::isValid(std::shared_ptr const& crCache) in all cases. */ std::pair -PathRequest::doCreate( - std::shared_ptr const& cache, - Json::Value const& value) +PathRequest::doCreate(std::shared_ptr const& cache, Json::Value const& value) { bool valid = false; @@ -271,16 +262,14 @@ PathRequest::parseJson(Json::Value const& jvParams) return PFR_PJ_INVALID; } - raSrcAccount = - parseBase58(jvParams[jss::source_account].asString()); + raSrcAccount = parseBase58(jvParams[jss::source_account].asString()); if (!raSrcAccount) { jvStatus = rpcError(rpcSRC_ACT_MALFORMED); return PFR_PJ_INVALID; } - raDstAccount = - parseBase58(jvParams[jss::destination_account].asString()); + raDstAccount = parseBase58(jvParams[jss::destination_account].asString()); if (!raDstAccount) { jvStatus = rpcError(rpcDST_ACT_MALFORMED); @@ -295,10 +284,8 @@ PathRequest::parseJson(Json::Value const& jvParams) convert_all_ = saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true); - if ((saDstAmount.getCurrency().isZero() && - saDstAmount.getIssuer().isNonZero()) || - (saDstAmount.getCurrency() == badCurrency()) || - (!convert_all_ && saDstAmount <= beast::zero)) + if ((saDstAmount.getCurrency().isZero() && saDstAmount.getIssuer().isNonZero()) || + (saDstAmount.getCurrency() == badCurrency()) || (!convert_all_ && saDstAmount <= beast::zero)) { jvStatus = rpcError(rpcDST_AMT_MALFORMED); return PFR_PJ_INVALID; @@ -315,11 +302,9 @@ PathRequest::parseJson(Json::Value const& jvParams) saSendMax.emplace(); if (!amountFromJsonNoThrow(*saSendMax, jvParams[jss::send_max]) || - (saSendMax->getCurrency().isZero() && - saSendMax->getIssuer().isNonZero()) || + (saSendMax->getCurrency().isZero() && saSendMax->getIssuer().isNonZero()) || (saSendMax->getCurrency() == badCurrency()) || - (*saSendMax <= beast::zero && - *saSendMax != STAmount(saSendMax->issue(), 1u, 0, true))) + (*saSendMax <= beast::zero && *saSendMax != STAmount(saSendMax->issue(), 1u, 0, true))) { jvStatus = rpcError(rpcSENDMAX_MALFORMED); return PFR_PJ_INVALID; @@ -342,8 +327,7 @@ PathRequest::parseJson(Json::Value const& jvParams) { // Mandatory currency Currency srcCurrencyID; - if (!c.isObject() || !c.isMember(jss::currency) || - !c[jss::currency].isString() || + if (!c.isObject() || !c.isMember(jss::currency) || !c[jss::currency].isString() || !to_currency(srcCurrencyID, c[jss::currency].asString())) { jvStatus = rpcError(rpcSRC_CUR_MALFORMED); @@ -353,8 +337,7 @@ PathRequest::parseJson(Json::Value const& jvParams) // Optional issuer AccountID srcIssuerID; if (c.isMember(jss::issuer) && - (!c[jss::issuer].isString() || - !to_issuer(srcIssuerID, c[jss::issuer].asString()))) + (!c[jss::issuer].isString() || !to_issuer(srcIssuerID, c[jss::issuer].asString()))) { jvStatus = rpcError(rpcSRC_ISR_MALFORMED); return PFR_PJ_INVALID; @@ -380,8 +363,7 @@ PathRequest::parseJson(Json::Value const& jvParams) { // If neither is the source and they are not equal, then the // source issuer is illegal. - if (srcIssuerID != *raSrcAccount && - saSendMax->getIssuer() != *raSrcAccount && + if (srcIssuerID != *raSrcAccount && saSendMax->getIssuer() != *raSrcAccount && srcIssuerID != saSendMax->getIssuer()) { jvStatus = rpcError(rpcSRC_ISR_MALFORMED); @@ -392,18 +374,15 @@ PathRequest::parseJson(Json::Value const& jvParams) // Otherwise, use the one that's not the source. if (srcIssuerID != *raSrcAccount) { - sciSourceCurrencies.insert( - {srcCurrencyID, srcIssuerID}); + sciSourceCurrencies.insert({srcCurrencyID, srcIssuerID}); } else if (saSendMax->getIssuer() != *raSrcAccount) { - sciSourceCurrencies.insert( - {srcCurrencyID, saSendMax->getIssuer()}); + sciSourceCurrencies.insert({srcCurrencyID, saSendMax->getIssuer()}); } else { - sciSourceCurrencies.insert( - {srcCurrencyID, *raSrcAccount}); + sciSourceCurrencies.insert({srcCurrencyID, *raSrcAccount}); } } } @@ -420,8 +399,7 @@ PathRequest::parseJson(Json::Value const& jvParams) if (jvParams.isMember(jss::domain)) { uint256 num; - if (!jvParams[jss::domain].isString() || - !num.parseHex(jvParams[jss::domain].asString())) + if (!jvParams[jss::domain].isString() || !num.parseHex(jvParams[jss::domain].asString())) { jvStatus = rpcError(rpcDOMAIN_MALFORMED); return PFR_PJ_INVALID; @@ -471,15 +449,7 @@ PathRequest::getPathFinder( if (i != currency_map.end()) return i->second; auto pathfinder = std::make_unique( - cache, - *raSrcAccount, - *raDstAccount, - currency, - std::nullopt, - dst_amount, - saSendMax, - domain, - app_); + cache, *raSrcAccount, *raDstAccount, currency, std::nullopt, dst_amount, saSendMax, domain, app_); if (pathfinder->findPaths(level, continueCallback)) pathfinder->computePathRanks(max_paths_, continueCallback); else @@ -509,8 +479,7 @@ PathRequest::findPaths( { if (sourceCurrencies.size() >= RPC::Tuning::max_auto_src_cur) return false; - sourceCurrencies.insert( - {c, c.isZero() ? xrpAccount() : *raSrcAccount}); + sourceCurrencies.insert({c, c.isZero() ? xrpAccount() : *raSrcAccount}); } } } @@ -521,17 +490,9 @@ PathRequest::findPaths( { if (continueCallback && !continueCallback()) break; - JLOG(m_journal.debug()) - << iIdentifier - << " Trying to find paths: " << STAmount(issue, 1).getFullText(); + JLOG(m_journal.debug()) << iIdentifier << " Trying to find paths: " << STAmount(issue, 1).getFullText(); - auto& pathfinder = getPathFinder( - cache, - currency_map, - issue.currency, - dst_amount, - level, - continueCallback); + auto& pathfinder = getPathFinder(cache, currency_map, issue.currency, dst_amount, level, continueCallback); if (!pathfinder) { JLOG(m_journal.debug()) << iIdentifier << " No paths found"; @@ -539,12 +500,8 @@ PathRequest::findPaths( } STPath fullLiquidityPath; - auto ps = pathfinder->getBestPaths( - max_paths_, - fullLiquidityPath, - mContext[issue], - issue.account, - continueCallback); + auto ps = + pathfinder->getBestPaths(max_paths_, fullLiquidityPath, mContext[issue], issue.account, continueCallback); mContext[issue] = ps; auto const& sourceAccount = [&] { @@ -557,17 +514,14 @@ PathRequest::findPaths( return *raSrcAccount; }(); - STAmount saMaxAmount = saSendMax.value_or( - STAmount(Issue{issue.currency, sourceAccount}, 1u, 0, true)); + STAmount saMaxAmount = saSendMax.value_or(STAmount(Issue{issue.currency, sourceAccount}, 1u, 0, true)); - JLOG(m_journal.debug()) - << iIdentifier << " Paths found, calling rippleCalc"; + JLOG(m_journal.debug()) << iIdentifier << " Paths found, calling rippleCalc"; path::RippleCalc::Input rcInput; if (convert_all_) rcInput.partialPaymentAllowed = true; - auto sandbox = - std::make_unique(&*cache->getLedger(), tapNONE); + auto sandbox = std::make_unique(&*cache->getLedger(), tapNONE); auto rc = path::RippleCalc::rippleCalculate( *sandbox, saMaxAmount, // --> Amount to send is unlimited @@ -583,12 +537,10 @@ PathRequest::findPaths( if (!convert_all_ && !fullLiquidityPath.empty() && (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL)) { - JLOG(m_journal.debug()) - << iIdentifier << " Trying with an extra path element"; + JLOG(m_journal.debug()) << iIdentifier << " Trying with an extra path element"; ps.push_back(fullLiquidityPath); - sandbox = - std::make_unique(&*cache->getLedger(), tapNONE); + sandbox = std::make_unique(&*cache->getLedger(), tapNONE); rc = path::RippleCalc::rippleCalculate( *sandbox, saMaxAmount, // --> Amount to send is unlimited @@ -602,15 +554,11 @@ PathRequest::findPaths( if (rc.result() != tesSUCCESS) { - JLOG(m_journal.warn()) - << iIdentifier << " Failed with covering path " - << transHuman(rc.result()); + JLOG(m_journal.warn()) << iIdentifier << " Failed with covering path " << transHuman(rc.result()); } else { - JLOG(m_journal.debug()) - << iIdentifier << " Extra path element gives " - << transHuman(rc.result()); + JLOG(m_journal.debug()) << iIdentifier << " Extra path element gives " << transHuman(rc.result()); } } @@ -618,13 +566,11 @@ PathRequest::findPaths( { Json::Value jvEntry(Json::objectValue); rc.actualAmountIn.setIssuer(sourceAccount); - jvEntry[jss::source_amount] = - rc.actualAmountIn.getJson(JsonOptions::none); + jvEntry[jss::source_amount] = rc.actualAmountIn.getJson(JsonOptions::none); jvEntry[jss::paths_computed] = ps.getJson(JsonOptions::none); if (convert_all_) - jvEntry[jss::destination_amount] = - rc.actualAmountOut.getJson(JsonOptions::none); + jvEntry[jss::destination_amount] = rc.actualAmountOut.getJson(JsonOptions::none); if (hasCompletion()) { @@ -636,8 +582,7 @@ PathRequest::findPaths( } else { - JLOG(m_journal.debug()) << iIdentifier << " rippleCalc returns " - << transHuman(rc.result()); + JLOG(m_journal.debug()) << iIdentifier << " rippleCalc returns " << transHuman(rc.result()); } } @@ -657,8 +602,7 @@ PathRequest::doUpdate( std::function const& continueCallback) { using namespace std::chrono; - JLOG(m_journal.debug()) - << iIdentifier << " update " << (fast ? "fast" : "normal"); + JLOG(m_journal.debug()) << iIdentifier << " update " << (fast ? "fast" : "normal"); { std::lock_guard sl(mLock); @@ -672,8 +616,7 @@ PathRequest::doUpdate( if (hasCompletion()) { // Old ripple_path_find API gives destination_currencies - auto& destCurrencies = - (newStatus[jss::destination_currencies] = Json::arrayValue); + auto& destCurrencies = (newStatus[jss::destination_currencies] = Json::arrayValue); auto usCurrencies = accountDestCurrencies(*raDstAccount, cache, true); for (auto const& c : usCurrencies) destCurrencies.append(to_string(c)); @@ -707,8 +650,7 @@ PathRequest::doUpdate( else if (bLastSuccess) { // decrement, if possible - if (iLevel > app_.config().PATH_SEARCH || - (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))) + if (iLevel > app_.config().PATH_SEARCH || (loaded && (iLevel > app_.config().PATH_SEARCH_FAST))) --iLevel; } else @@ -750,8 +692,7 @@ PathRequest::doUpdate( jvStatus = newStatus; } - JLOG(m_journal.debug()) - << iIdentifier << " update finished " << (fast ? "fast" : "normal"); + JLOG(m_journal.debug()) << iIdentifier << " update finished " << (fast ? "fast" : "normal"); return newStatus; } diff --git a/src/xrpld/app/paths/PathRequest.h b/src/xrpld/app/paths/PathRequest.h index 8f63cfa9a9..edeab4dc88 100644 --- a/src/xrpld/app/paths/PathRequest.h +++ b/src/xrpld/app/paths/PathRequest.h @@ -106,11 +106,7 @@ private: Returns false if the source currencies are invalid. */ bool - findPaths( - std::shared_ptr const&, - int const, - Json::Value&, - std::function const&); + findPaths(std::shared_ptr const&, int const, Json::Value&, std::function const&); int parseJson(Json::Value const&); diff --git a/src/xrpld/app/paths/PathRequests.cpp b/src/xrpld/app/paths/PathRequests.cpp index cfe6080eac..2c1ef8cbad 100644 --- a/src/xrpld/app/paths/PathRequests.cpp +++ b/src/xrpld/app/paths/PathRequests.cpp @@ -16,9 +16,7 @@ namespace xrpl { Get the correct ledger to use. */ std::shared_ptr -PathRequests::getLineCache( - std::shared_ptr const& ledger, - bool authoritative) +PathRequests::getLineCache(std::shared_ptr const& ledger, bool authoritative) { std::lock_guard sl(mLock); @@ -26,22 +24,18 @@ PathRequests::getLineCache( std::uint32_t const lineSeq = lineCache ? lineCache->getLedger()->seq() : 0; std::uint32_t const lgrSeq = ledger->seq(); - JLOG(mJournal.debug()) << "getLineCache has cache for " << lineSeq - << ", considering " << lgrSeq; + JLOG(mJournal.debug()) << "getLineCache has cache for " << lineSeq << ", considering " << lgrSeq; - if ((lineSeq == 0) || // no ledger - (authoritative && (lgrSeq > lineSeq)) || // newer authoritative ledger - (authoritative && - ((lgrSeq + 8) < lineSeq)) || // we jumped way back for some reason - (lgrSeq > (lineSeq + 8))) // we jumped way forward for some reason + if ((lineSeq == 0) || // no ledger + (authoritative && (lgrSeq > lineSeq)) || // newer authoritative ledger + (authoritative && ((lgrSeq + 8) < lineSeq)) || // we jumped way back for some reason + (lgrSeq > (lineSeq + 8))) // we jumped way forward for some reason { - JLOG(mJournal.debug()) - << "getLineCache creating new cache for " << lgrSeq; + JLOG(mJournal.debug()) << "getLineCache creating new cache for " << lgrSeq; // Assign to the local before the member, because the member is a // weak_ptr, and will immediately discard it if there are no other // references. - lineCache_ = lineCache = std::make_shared( - ledger, app_.journal("RippleLineCache")); + lineCache_ = lineCache = std::make_shared(ledger, app_.journal("RippleLineCache")); } return lineCache; } @@ -49,8 +43,7 @@ PathRequests::getLineCache( void PathRequests::updateAll(std::shared_ptr const& inLedger) { - auto event = - app_.getJobQueue().makeLoadEvent(jtPATH_FIND, "PathRequest::updateAll"); + auto event = app_.getJobQueue().makeLoadEvent(jtPATH_FIND, "PathRequest::updateAll"); std::vector requests; std::shared_ptr cache; @@ -65,15 +58,12 @@ PathRequests::updateAll(std::shared_ptr const& inLedger) bool newRequests = app_.getLedgerMaster().isNewPathRequest(); bool mustBreak = false; - JLOG(mJournal.trace()) << "updateAll seq=" << cache->getLedger()->seq() - << ", " << requests.size() << " requests"; + JLOG(mJournal.trace()) << "updateAll seq=" << cache->getLedger()->seq() << ", " << requests.size() << " requests"; int processed = 0, removed = 0; - auto getSubscriber = - [](PathRequest::pointer const& request) -> InfoSub::pointer { - if (auto ipSub = request->getSubscriber(); - ipSub && ipSub->getRequest() == request) + auto getSubscriber = [](PathRequest::pointer const& request) -> InfoSub::pointer { + if (auto ipSub = request->getSubscriber(); ipSub && ipSub->getRequest() == request) { return ipSub; } @@ -91,8 +81,7 @@ PathRequests::updateAll(std::shared_ptr const& inLedger) auto request = wr.lock(); bool remove = true; - JLOG(mJournal.trace()) - << "updateAll request " << (request ? "" : "not ") << "found"; + JLOG(mJournal.trace()) << "updateAll request " << (request ? "" : "not ") << "found"; if (request) { @@ -102,8 +91,7 @@ PathRequests::updateAll(std::shared_ptr const& inLedger) // indicates that this request is no longer relevant. return (bool)getSubscriber(request); }; - if (!request->needsUpdate( - newRequests, cache->getLedger()->seq())) + if (!request->needsUpdate(newRequests, cache->getLedger()->seq())) remove = false; else { @@ -115,8 +103,7 @@ PathRequests::updateAll(std::shared_ptr const& inLedger) // it can be freed if the client disconnects, and // thus fail to lock later. ipSub.reset(); - Json::Value update = request->doUpdate( - cache, false, continueCallback); + Json::Value update = request->doUpdate(cache, false, continueCallback); request->updateComplete(); update[jss::type] = "path_find"; if ((ipSub = getSubscriber(request))) @@ -143,23 +130,19 @@ PathRequests::updateAll(std::shared_ptr const& inLedger) // Remove any dangling weak pointers or weak // pointers that refer to this path request. - auto ret = std::remove_if( - requests_.begin(), - requests_.end(), - [&removed, &request](auto const& wl) { - auto r = wl.lock(); + auto ret = std::remove_if(requests_.begin(), requests_.end(), [&removed, &request](auto const& wl) { + auto r = wl.lock(); - if (r && r != request) - return false; - ++removed; - return true; - }); + if (r && r != request) + return false; + ++removed; + return true; + }); requests_.erase(ret, requests_.end()); } - mustBreak = - !newRequests && app_.getLedgerMaster().isNewPathRequest(); + mustBreak = !newRequests && app_.getLedgerMaster().isNewPathRequest(); // We weren't handling new requests and then // there was a new request @@ -197,8 +180,7 @@ PathRequests::updateAll(std::shared_ptr const& inLedger) } } while (!app_.getJobQueue().isStopping()); - JLOG(mJournal.debug()) << "updateAll complete: " << processed - << " processed and " << removed << " removed"; + JLOG(mJournal.debug()) << "updateAll complete: " << processed << " processed and " << removed << " removed"; } bool @@ -215,13 +197,12 @@ PathRequests::insertPathRequest(PathRequest::pointer const& req) // Insert after any older unserviced requests but before // any serviced requests - auto ret = - std::find_if(requests_.begin(), requests_.end(), [](auto const& wl) { - auto r = wl.lock(); + auto ret = std::find_if(requests_.begin(), requests_.end(), [](auto const& wl) { + auto r = wl.lock(); - // We come before handled requests - return r && !r->isNew(); - }); + // We come before handled requests + return r && !r->isNew(); + }); requests_.emplace(ret, req); } @@ -233,11 +214,9 @@ PathRequests::makePathRequest( std::shared_ptr const& inLedger, Json::Value const& requestJson) { - auto req = std::make_shared( - app_, subscriber, ++mLastIdentifier, *this, mJournal); + auto req = std::make_shared(app_, subscriber, ++mLastIdentifier, *this, mJournal); - auto [valid, jvRes] = - req->doCreate(getLineCache(inLedger, false), requestJson); + auto [valid, jvRes] = req->doCreate(getLineCache(inLedger, false), requestJson); if (valid) { @@ -259,8 +238,7 @@ PathRequests::makeLegacyPathRequest( { // This assignment must take place before the // completion function is called - req = std::make_shared( - app_, completion, consumer, ++mLastIdentifier, *this, mJournal); + req = std::make_shared(app_, completion, consumer, ++mLastIdentifier, *this, mJournal); auto [valid, jvRes] = req->doCreate(getLineCache(inLedger, false), request); @@ -288,11 +266,9 @@ PathRequests::doLegacyPathRequest( std::shared_ptr const& inLedger, Json::Value const& request) { - auto cache = std::make_shared( - inLedger, app_.journal("RippleLineCache")); + auto cache = std::make_shared(inLedger, app_.journal("RippleLineCache")); - auto req = std::make_shared( - app_, [] {}, consumer, ++mLastIdentifier, *this, mJournal); + auto req = std::make_shared(app_, [] {}, consumer, ++mLastIdentifier, *this, mJournal); auto [valid, jvRes] = req->doCreate(cache, request); if (valid) diff --git a/src/xrpld/app/paths/PathRequests.h b/src/xrpld/app/paths/PathRequests.h index 5c97bafa8a..33b817f8c0 100644 --- a/src/xrpld/app/paths/PathRequests.h +++ b/src/xrpld/app/paths/PathRequests.h @@ -15,10 +15,7 @@ class PathRequests { public: /** A collection of all PathRequest instances. */ - PathRequests( - Application& app, - beast::Journal journal, - beast::insight::Collector::ptr const& collector) + PathRequests(Application& app, beast::Journal journal, beast::insight::Collector::ptr const& collector) : app_(app), mJournal(journal), mLastIdentifier(0) { mFast = collector->make_event("pathfind_fast"); @@ -36,9 +33,7 @@ public: requestsPending() const; std::shared_ptr - getLineCache( - std::shared_ptr const& ledger, - bool authoritative); + getLineCache(std::shared_ptr const& ledger, bool authoritative); // Create a new-style path request that pushes // updates to a subscriber diff --git a/src/xrpld/app/paths/Pathfinder.cpp b/src/xrpld/app/paths/Pathfinder.cpp index c99467dade..b64ce0cc20 100644 --- a/src/xrpld/app/paths/Pathfinder.cpp +++ b/src/xrpld/app/paths/Pathfinder.cpp @@ -62,10 +62,7 @@ struct AccountCandidate }; bool -compareAccountCandidate( - std::uint32_t seq, - AccountCandidate const& first, - AccountCandidate const& second) +compareAccountCandidate(std::uint32_t seq, AccountCandidate const& first, AccountCandidate const& second) { if (first.priority < second.priority) return false; @@ -151,17 +148,12 @@ Pathfinder::Pathfinder( Application& app) : mSrcAccount(uSrcAccount) , mDstAccount(uDstAccount) - , mEffectiveDst( - isXRP(saDstAmount.getIssuer()) ? uDstAccount - : saDstAmount.getIssuer()) + , mEffectiveDst(isXRP(saDstAmount.getIssuer()) ? uDstAccount : saDstAmount.getIssuer()) , mDstAmount(saDstAmount) , mSrcCurrency(uSrcCurrency) , mSrcIssuer(uSrcIssuer) , mSrcAmount(srcAmount.value_or(STAmount( - Issue{ - uSrcCurrency, - uSrcIssuer.value_or( - isXRP(uSrcCurrency) ? xrpAccount() : uSrcAccount)}, + Issue{uSrcCurrency, uSrcIssuer.value_or(isXRP(uSrcCurrency) ? xrpAccount() : uSrcAccount)}, 1u, 0, true))) @@ -173,14 +165,11 @@ Pathfinder::Pathfinder( , j_(app.journal("Pathfinder")) { XRPL_ASSERT( - !uSrcIssuer || isXRP(uSrcCurrency) == isXRP(uSrcIssuer.value()), - "xrpl::Pathfinder::Pathfinder : valid inputs"); + !uSrcIssuer || isXRP(uSrcCurrency) == isXRP(uSrcIssuer.value()), "xrpl::Pathfinder::Pathfinder : valid inputs"); } bool -Pathfinder::findPaths( - int searchLevel, - std::function const& continueCallback) +Pathfinder::findPaths(int searchLevel, std::function const& continueCallback) { JLOG(j_.trace()) << "findPaths start"; if (mDstAmount == beast::zero) @@ -194,8 +183,7 @@ Pathfinder::findPaths( // below - why don't we do it each time we return false? } - if (mSrcAccount == mDstAccount && mDstAccount == mEffectiveDst && - mSrcCurrency == mDstAmount.getCurrency()) + if (mSrcAccount == mDstAccount && mDstAccount == mEffectiveDst && mSrcCurrency == mDstAmount.getCurrency()) { // No need to send to same account with same currency. JLOG(j_.debug()) << "Tried to send to same issuer"; @@ -203,8 +191,7 @@ Pathfinder::findPaths( return false; } - if (mSrcAccount == mEffectiveDst && - mSrcCurrency == mDstAmount.getCurrency()) + if (mSrcAccount == mEffectiveDst && mSrcCurrency == mDstAmount.getCurrency()) { // Default path might work, but any path would loop return true; @@ -217,13 +204,10 @@ Pathfinder::findPaths( auto& account = useIssuerAccount ? *mSrcIssuer : mSrcAccount; auto issuer = currencyIsXRP ? AccountID() : account; mSource = STPathElement(account, mSrcCurrency, issuer); - auto issuerString = - mSrcIssuer ? to_string(*mSrcIssuer) : std::string("none"); + auto issuerString = mSrcIssuer ? to_string(*mSrcIssuer) : std::string("none"); JLOG(j_.trace()) << "findPaths>" - << " mSrcAccount=" << mSrcAccount - << " mDstAccount=" << mDstAccount - << " mDstAmount=" << mDstAmount.getFullText() - << " mSrcCurrency=" << mSrcCurrency + << " mSrcAccount=" << mSrcAccount << " mDstAccount=" << mDstAccount + << " mDstAmount=" << mDstAmount.getFullText() << " mSrcCurrency=" << mSrcCurrency << " mSrcIssuer=" << issuerString; if (!mLedger) @@ -242,8 +226,7 @@ Pathfinder::findPaths( return false; } - if ((mEffectiveDst != mDstAccount) && - !mLedger->exists(keylet::account(mEffectiveDst))) + if ((mEffectiveDst != mDstAccount) && !mLedger->exists(keylet::account(mEffectiveDst))) { JLOG(j_.debug()) << "Non-existent gateway"; return false; @@ -262,9 +245,7 @@ Pathfinder::findPaths( auto const reserve = STAmount(mLedger->fees().reserve); if (mDstAmount < reserve) { - JLOG(j_.debug()) - << "New account not getting enough funding: " << mDstAmount - << " < " << reserve; + JLOG(j_.debug()) << "New account not getting enough funding: " << mDstAmount << " < " << reserve; return false; } } @@ -349,15 +330,7 @@ Pathfinder::getPathLiquidity( rcInput.partialPaymentAllowed = true; auto rc = path::RippleCalc::rippleCalculate( - sandbox, - mSrcAmount, - minDstAmount, - mDstAccount, - mSrcAccount, - pathSet, - mDomain, - app_.logs(), - &rcInput); + sandbox, mSrcAmount, minDstAmount, mDstAccount, mSrcAccount, pathSet, mDomain, app_.logs(), &rcInput); // If we can't get even the minimum liquidity requested, we're done. if (rc.result() != tesSUCCESS) return rc.result(); @@ -389,16 +362,13 @@ Pathfinder::getPathLiquidity( } catch (std::exception const& e) { - JLOG(j_.info()) << "checkpath: exception (" << e.what() << ") " - << path.getJson(JsonOptions::none); + JLOG(j_.info()) << "checkpath: exception (" << e.what() << ") " << path.getJson(JsonOptions::none); return tefEXCEPTION; } } void -Pathfinder::computePathRanks( - int maxPaths, - std::function const& continueCallback) +Pathfinder::computePathRanks(int maxPaths, std::function const& continueCallback) { mRemainingAmount = convertAmount(mDstAmount, convert_all_); @@ -422,14 +392,12 @@ Pathfinder::computePathRanks( if (rc.result() == tesSUCCESS) { - JLOG(j_.debug()) - << "Default path contributes: " << rc.actualAmountIn; + JLOG(j_.debug()) << "Default path contributes: " << rc.actualAmountIn; mRemainingAmount -= rc.actualAmountOut; } else { - JLOG(j_.debug()) - << "Default path fails: " << transToken(rc.result()); + JLOG(j_.debug()) << "Default path fails: " << transToken(rc.result()); } } catch (std::exception const&) @@ -481,8 +449,7 @@ Pathfinder::rankPaths( std::vector& rankedPaths, std::function const& continueCallback) { - JLOG(j_.trace()) << "rankPaths with " << paths.size() << " candidates, and " - << maxPaths << " maximum"; + JLOG(j_.trace()) << "rankPaths with " << paths.size() << " candidates, and " << maxPaths << " maximum"; rankedPaths.clear(); rankedPaths.reserve(paths.size()); @@ -507,21 +474,18 @@ Pathfinder::rankPaths( { STAmount liquidity; uint64_t uQuality; - auto const resultCode = getPathLiquidity( - currentPath, saMinDstAmount, liquidity, uQuality); + auto const resultCode = getPathLiquidity(currentPath, saMinDstAmount, liquidity, uQuality); if (resultCode != tesSUCCESS) { - JLOG(j_.debug()) - << "findPaths: dropping : " << transToken(resultCode) - << ": " << currentPath.getJson(JsonOptions::none); + JLOG(j_.debug()) << "findPaths: dropping : " << transToken(resultCode) << ": " + << currentPath.getJson(JsonOptions::none); } else { JLOG(j_.debug()) << "findPaths: quality: " << uQuality << ": " << currentPath.getJson(JsonOptions::none); - rankedPaths.push_back( - {uQuality, currentPath.size(), liquidity, i}); + rankedPaths.push_back({uQuality, currentPath.size(), liquidity, i}); } } } @@ -532,9 +496,7 @@ Pathfinder::rankPaths( // length of path // A better PathRank is lower, best are sorted to the beginning. std::sort( - rankedPaths.begin(), - rankedPaths.end(), - [&](Pathfinder::PathRank const& a, Pathfinder::PathRank const& b) { + rankedPaths.begin(), rankedPaths.end(), [&](Pathfinder::PathRank const& a, Pathfinder::PathRank const& b) { // 1) Higher quality (lower cost) is better if (!convert_all_ && a.quality != b.quality) return a.quality < b.quality; @@ -560,17 +522,13 @@ Pathfinder::getBestPaths( AccountID const& srcIssuer, std::function const& continueCallback) { - JLOG(j_.debug()) << "findPaths: " << mCompletePaths.size() << " paths and " - << extraPaths.size() << " extras"; + JLOG(j_.debug()) << "findPaths: " << mCompletePaths.size() << " paths and " << extraPaths.size() << " extras"; if (mCompletePaths.empty() && extraPaths.empty()) return mCompletePaths; - XRPL_ASSERT( - fullLiquidityPath.empty(), - "xrpl::Pathfinder::getBestPaths : first empty path result"); - bool const issuerIsSender = - isXRP(mSrcCurrency) || (srcIssuer == mSrcAccount); + XRPL_ASSERT(fullLiquidityPath.empty(), "xrpl::Pathfinder::getBestPaths : first empty path result"); + bool const issuerIsSender = isXRP(mSrcCurrency) || (srcIssuer == mSrcAccount); std::vector extraPathRanks; rankPaths(maxPaths, extraPaths, extraPathRanks, continueCallback); @@ -585,8 +543,7 @@ Pathfinder::getBestPaths( auto pathsIterator = mPathRanks.begin(); auto extraPathsIterator = extraPathRanks.begin(); - while (pathsIterator != mPathRanks.end() || - extraPathsIterator != extraPathRanks.end()) + while (pathsIterator != mPathRanks.end() || extraPathsIterator != extraPathRanks.end()) { if (continueCallback && !continueCallback()) break; @@ -614,8 +571,7 @@ Pathfinder::getBestPaths( auto& pathRank = usePath ? *pathsIterator : *extraPathsIterator; - auto const& path = usePath ? mCompletePaths[pathRank.index] - : extraPaths[pathRank.index]; + auto const& path = usePath ? mCompletePaths[pathRank.index] : extraPaths[pathRank.index]; if (useExtraPath) ++extraPathsIterator; @@ -648,42 +604,33 @@ Pathfinder::getBestPaths( startsWithIssuer = true; } - if (iPathsLeft > 1 || - (iPathsLeft > 0 && pathRank.liquidity >= remaining)) + if (iPathsLeft > 1 || (iPathsLeft > 0 && pathRank.liquidity >= remaining)) // last path must fill { --iPathsLeft; remaining -= pathRank.liquidity; bestPaths.push_back(startsWithIssuer ? removeIssuer(path) : path); } - else if ( - iPathsLeft == 0 && pathRank.liquidity >= mDstAmount && - fullLiquidityPath.empty()) + else if (iPathsLeft == 0 && pathRank.liquidity >= mDstAmount && fullLiquidityPath.empty()) { // We found an extra path that can move the whole amount. fullLiquidityPath = (startsWithIssuer ? removeIssuer(path) : path); - JLOG(j_.debug()) << "Found extra full path: " - << fullLiquidityPath.getJson(JsonOptions::none); + JLOG(j_.debug()) << "Found extra full path: " << fullLiquidityPath.getJson(JsonOptions::none); } else { - JLOG(j_.debug()) << "Skipping a non-filling path: " - << path.getJson(JsonOptions::none); + JLOG(j_.debug()) << "Skipping a non-filling path: " << path.getJson(JsonOptions::none); } } if (remaining > beast::zero) { - XRPL_ASSERT( - fullLiquidityPath.empty(), - "xrpl::Pathfinder::getBestPaths : second empty path result"); - JLOG(j_.info()) << "Paths could not send " << remaining << " of " - << mDstAmount; + XRPL_ASSERT(fullLiquidityPath.empty(), "xrpl::Pathfinder::getBestPaths : second empty path result"); + JLOG(j_.info()) << "Paths could not send " << remaining << " of " << mDstAmount; } else { - JLOG(j_.debug()) << "findPaths: RESULTS: " - << bestPaths.getJson(JsonOptions::none); + JLOG(j_.debug()) << "findPaths: RESULTS: " << bestPaths.getJson(JsonOptions::none); } return bestPaths; } @@ -692,9 +639,8 @@ bool Pathfinder::issueMatchesOrigin(Issue const& issue) { bool matchingCurrency = (issue.currency == mSrcCurrency); - bool matchingAccount = isXRP(issue.currency) || - (mSrcIssuer && issue.account == mSrcIssuer) || - issue.account == mSrcAccount; + bool matchingAccount = + isXRP(issue.currency) || (mSrcIssuer && issue.account == mSrcIssuer) || issue.account == mSrcAccount; return matchingCurrency && matchingAccount; } @@ -740,13 +686,11 @@ Pathfinder::getPathsOut( } else if ( rspEntry.getBalance() <= beast::zero && - (!rspEntry.getLimitPeer() || - -rspEntry.getBalance() >= rspEntry.getLimitPeer() || + (!rspEntry.getLimitPeer() || -rspEntry.getBalance() >= rspEntry.getLimitPeer() || (bAuthRequired && !rspEntry.getAuth()))) { } - else if ( - isDstCurrency && dstAccount == rspEntry.getAccountIDPeer()) + else if (isDstCurrency && dstAccount == rspEntry.getAccountIDPeer()) { count += 10000; // count a path to the destination extra } @@ -776,8 +720,7 @@ Pathfinder::addLinks( int addFlags, std::function const& continueCallback) { - JLOG(j_.debug()) << "addLink< on " << currentPaths.size() - << " source(s), flags=" << addFlags; + JLOG(j_.debug()) << "addLink< on " << currentPaths.size() << " source(s), flags=" << addFlags; for (auto const& path : currentPaths) { if (continueCallback && !continueCallback()) @@ -787,12 +730,9 @@ Pathfinder::addLinks( } STPathSet& -Pathfinder::addPathsForType( - PathType const& pathType, - std::function const& continueCallback) +Pathfinder::addPathsForType(PathType const& pathType, std::function const& continueCallback) { - JLOG(j_.debug()) << "addPathsForType " - << CollectionAndDelimiter(pathType, ", "); + JLOG(j_.debug()) << "addPathsForType " << CollectionAndDelimiter(pathType, ", "); // See if the set of paths for this type already exists. auto it = mPaths.find(pathType); if (it != mPaths.end()) @@ -809,12 +749,10 @@ Pathfinder::addPathsForType( PathType parentPathType = pathType; parentPathType.pop_back(); - STPathSet const& parentPaths = - addPathsForType(parentPathType, continueCallback); + STPathSet const& parentPaths = addPathsForType(parentPathType, continueCallback); STPathSet& pathsOut = mPaths[pathType]; - JLOG(j_.debug()) << "getPaths< adding onto '" - << pathTypeToString(parentPathType) << "' to get '" + JLOG(j_.debug()) << "getPaths< adding onto '" << pathTypeToString(parentPathType) << "' to get '" << pathTypeToString(pathType) << "'"; int initialSize = mCompletePaths.size(); @@ -825,9 +763,7 @@ Pathfinder::addPathsForType( { case nt_SOURCE: // Source must always be at the start, so pathsOut has to be empty. - XRPL_ASSERT( - pathsOut.empty(), - "xrpl::Pathfinder::addPathsForType : empty paths"); + XRPL_ASSERT(pathsOut.empty(), "xrpl::Pathfinder::addPathsForType : empty paths"); pathsOut.push_back(STPath()); break; @@ -840,55 +776,36 @@ Pathfinder::addPathsForType( break; case nt_XRP_BOOK: - addLinks( - parentPaths, - pathsOut, - afADD_BOOKS | afOB_XRP, - continueCallback); + addLinks(parentPaths, pathsOut, afADD_BOOKS | afOB_XRP, continueCallback); break; case nt_DEST_BOOK: - addLinks( - parentPaths, - pathsOut, - afADD_BOOKS | afOB_LAST, - continueCallback); + addLinks(parentPaths, pathsOut, afADD_BOOKS | afOB_LAST, continueCallback); break; case nt_DESTINATION: // FIXME: What if a different issuer was specified on the // destination amount? // TODO(tom): what does this even mean? Should it be a JIRA? - addLinks( - parentPaths, - pathsOut, - afADD_ACCOUNTS | afAC_LAST, - continueCallback); + addLinks(parentPaths, pathsOut, afADD_ACCOUNTS | afAC_LAST, continueCallback); break; } if (mCompletePaths.size() != initialSize) { - JLOG(j_.debug()) << (mCompletePaths.size() - initialSize) - << " complete paths added"; + JLOG(j_.debug()) << (mCompletePaths.size() - initialSize) << " complete paths added"; } - JLOG(j_.debug()) << "getPaths> " << pathsOut.size() - << " partial paths found"; + JLOG(j_.debug()) << "getPaths> " << pathsOut.size() << " partial paths found"; return pathsOut; } bool -Pathfinder::isNoRipple( - AccountID const& fromAccount, - AccountID const& toAccount, - Currency const& currency) +Pathfinder::isNoRipple(AccountID const& fromAccount, AccountID const& toAccount, Currency const& currency) { - auto sleRipple = - mLedger->read(keylet::line(toAccount, fromAccount, currency)); + auto sleRipple = mLedger->read(keylet::line(toAccount, fromAccount, currency)); - auto const flag( - (toAccount > fromAccount) ? lsfHighNoRipple : lsfLowNoRipple); + auto const flag((toAccount > fromAccount) ? lsfHighNoRipple : lsfLowNoRipple); return sleRipple && (sleRipple->getFieldU32(sfFlags) & flag); } @@ -910,9 +827,7 @@ Pathfinder::isNoRippleOut(STPath const& currentPath) // If there's only one item in the path, return true if that item specifies // no ripple on the output. A path with no ripple on its output can't be // followed by a link with no ripple on its input. - auto const& fromAccount = (currentPath.size() == 1) - ? mSrcAccount - : (currentPath.end() - 2)->getAccountID(); + auto const& fromAccount = (currentPath.size() == 1) ? mSrcAccount : (currentPath.end() - 2)->getAccountID(); auto const& toAccount = endElement.getAccountID(); return isNoRipple(fromAccount, toAccount, endElement.getCurrency()); } @@ -959,8 +874,7 @@ Pathfinder::addLink( { if (mDstAmount.native() && !currentPath.empty()) { // non-default path to XRP destination - JLOG(j_.trace()) << "complete path found ax: " - << currentPath.getJson(JsonOptions::none); + JLOG(j_.trace()) << "complete path found ax: " << currentPath.getJson(JsonOptions::none); addUniquePath(mCompletePaths, currentPath); } } @@ -971,17 +885,13 @@ Pathfinder::addLink( if (sleEnd) { - bool const bRequireAuth( - sleEnd->getFieldU32(sfFlags) & lsfRequireAuth); - bool const bIsEndCurrency( - uEndCurrency == mDstAmount.getCurrency()); + bool const bRequireAuth(sleEnd->getFieldU32(sfFlags) & lsfRequireAuth); + bool const bIsEndCurrency(uEndCurrency == mDstAmount.getCurrency()); bool const bIsNoRippleOut(isNoRippleOut(currentPath)); bool const bDestOnly(addFlags & afAC_LAST); if (auto const lines = mRLCache->getRippleLines( - uEndAccount, - bIsNoRippleOut ? LineDirection::incoming - : LineDirection::outgoing)) + uEndAccount, bIsNoRippleOut ? LineDirection::incoming : LineDirection::outgoing)) { auto& rippleLines = *lines; @@ -1014,8 +924,7 @@ Pathfinder::addLink( // path is for correct currency and has not been // seen if (rs.getBalance() <= beast::zero && - (!rs.getLimitPeer() || - -rs.getBalance() >= rs.getLimitPeer() || + (!rs.getLimitPeer() || -rs.getBalance() >= rs.getLimitPeer() || (bRequireAuth && !rs.getAuth()))) { // path has no credit @@ -1033,18 +942,14 @@ Pathfinder::addLink( if (!currentPath.empty()) { JLOG(j_.trace()) - << "complete path found ae: " - << currentPath.getJson( - JsonOptions::none); - addUniquePath( - mCompletePaths, currentPath); + << "complete path found ae: " << currentPath.getJson(JsonOptions::none); + addUniquePath(mCompletePaths, currentPath); } } else if (!bDestOnly) { // this is a high-priority candidate - candidates.push_back( - {AccountCandidate::highPriority, acct}); + candidates.push_back({AccountCandidate::highPriority, acct}); } } else if (acct == mSrcAccount) @@ -1055,12 +960,7 @@ Pathfinder::addLink( { // save this candidate int out = getPathsOut( - uEndCurrency, - acct, - direction, - bIsEndCurrency, - mEffectiveDst, - continueCallback); + uEndCurrency, acct, direction, bIsEndCurrency, mEffectiveDst, continueCallback); if (out) candidates.push_back({out, acct}); } @@ -1073,10 +973,7 @@ Pathfinder::addLink( candidates.begin(), candidates.end(), std::bind( - compareAccountCandidate, - mLedger->seq(), - std::placeholders::_1, - std::placeholders::_2)); + compareAccountCandidate, mLedger->seq(), std::placeholders::_1, std::placeholders::_2)); int count = candidates.size(); // allow more paths from source @@ -1092,12 +989,8 @@ Pathfinder::addLink( return; // Add accounts to incompletePaths STPathElement pathElement( - STPathElement::typeAccount, - it->account, - uEndCurrency, - it->account); - incompletePaths.assembleAdd( - currentPath, pathElement); + STPathElement::typeAccount, it->account, uEndCurrency, it->account); + incompletePaths.assembleAdd(currentPath, pathElement); ++it; } } @@ -1115,35 +1008,24 @@ Pathfinder::addLink( if (addFlags & afOB_XRP) { // to XRP only - if (!bOnXRP && - app_.getOrderBookDB().isBookToXRP( - {uEndCurrency, uEndIssuer}, mDomain)) + if (!bOnXRP && app_.getOrderBookDB().isBookToXRP({uEndCurrency, uEndIssuer}, mDomain)) { - STPathElement pathElement( - STPathElement::typeCurrency, - xrpAccount(), - xrpCurrency(), - xrpAccount()); + STPathElement pathElement(STPathElement::typeCurrency, xrpAccount(), xrpCurrency(), xrpAccount()); incompletePaths.assembleAdd(currentPath, pathElement); } } else { bool bDestOnly = (addFlags & afOB_LAST) != 0; - auto books = app_.getOrderBookDB().getBooksByTakerPays( - {uEndCurrency, uEndIssuer}, mDomain); - JLOG(j_.trace()) - << books.size() << " books found from this currency/issuer"; + auto books = app_.getOrderBookDB().getBooksByTakerPays({uEndCurrency, uEndIssuer}, mDomain); + JLOG(j_.trace()) << books.size() << " books found from this currency/issuer"; for (auto const& book : books) { if (continueCallback && !continueCallback()) return; - if (!currentPath.hasSeen( - xrpAccount(), book.out.currency, book.out.account) && - !issueMatchesOrigin(book.out) && - (!bDestOnly || - (book.out.currency == mDstAmount.getCurrency()))) + if (!currentPath.hasSeen(xrpAccount(), book.out.currency, book.out.account) && + !issueMatchesOrigin(book.out) && (!bDestOnly || (book.out.currency == mDstAmount.getCurrency()))) { STPath newPath(currentPath); @@ -1151,39 +1033,28 @@ Pathfinder::addLink( { // to XRP // add the order book itself - newPath.emplace_back( - STPathElement::typeCurrency, - xrpAccount(), - xrpCurrency(), - xrpAccount()); + newPath.emplace_back(STPathElement::typeCurrency, xrpAccount(), xrpCurrency(), xrpAccount()); if (mDstAmount.getCurrency().isZero()) { // destination is XRP, add account and path is // complete - JLOG(j_.trace()) - << "complete path found bx: " - << currentPath.getJson(JsonOptions::none); + JLOG(j_.trace()) << "complete path found bx: " << currentPath.getJson(JsonOptions::none); addUniquePath(mCompletePaths, newPath); } else incompletePaths.push_back(newPath); } - else if (!currentPath.hasSeen( - book.out.account, - book.out.currency, - book.out.account)) + else if (!currentPath.hasSeen(book.out.account, book.out.currency, book.out.account)) { // Don't want the book if we've already seen the issuer // book -> account -> book - if ((newPath.size() >= 2) && - (newPath.back().isAccount()) && + if ((newPath.size() >= 2) && (newPath.back().isAccount()) && (newPath[newPath.size() - 2].isOffer())) { // replace the redundant account with the order book newPath[newPath.size() - 1] = STPathElement( - STPathElement::typeCurrency | - STPathElement::typeIssuer, + STPathElement::typeCurrency | STPathElement::typeIssuer, xrpAccount(), book.out.currency, book.out.account); @@ -1192,27 +1063,21 @@ Pathfinder::addLink( { // add the order book newPath.emplace_back( - STPathElement::typeCurrency | - STPathElement::typeIssuer, + STPathElement::typeCurrency | STPathElement::typeIssuer, xrpAccount(), book.out.currency, book.out.account); } - if (hasEffectiveDestination && - book.out.account == mDstAccount && + if (hasEffectiveDestination && book.out.account == mDstAccount && book.out.currency == mDstAmount.getCurrency()) { // We skipped a required issuer } - else if ( - book.out.account == mEffectiveDst && - book.out.currency == mDstAmount.getCurrency()) + else if (book.out.account == mEffectiveDst && book.out.currency == mDstAmount.getCurrency()) { // with the destination account, this path is // complete - JLOG(j_.trace()) - << "complete path found ba: " - << currentPath.getJson(JsonOptions::none); + JLOG(j_.trace()) << "complete path found ba: " << currentPath.getJson(JsonOptions::none); addUniquePath(mCompletePaths, newPath); } else @@ -1221,10 +1086,7 @@ Pathfinder::addLink( incompletePaths.assembleAdd( newPath, STPathElement( - STPathElement::typeAccount, - book.out.account, - book.out.currency, - book.out.account)); + STPathElement::typeAccount, book.out.account, book.out.currency, book.out.account)); } } } diff --git a/src/xrpld/app/paths/Pathfinder.h b/src/xrpld/app/paths/Pathfinder.h index b269cc868b..131e9420c1 100644 --- a/src/xrpld/app/paths/Pathfinder.h +++ b/src/xrpld/app/paths/Pathfinder.h @@ -40,15 +40,11 @@ public: initPathTable(); bool - findPaths( - int searchLevel, - std::function const& continueCallback = {}); + findPaths(int searchLevel, std::function const& continueCallback = {}); /** Compute the rankings of the paths. */ void - computePathRanks( - int maxPaths, - std::function const& continueCallback = {}); + computePathRanks(int maxPaths, std::function const& continueCallback = {}); /* Get the best paths, up to maxPaths in number, from mCompletePaths. @@ -64,11 +60,11 @@ public: std::function const& continueCallback = {}); enum NodeType { - nt_SOURCE, // The source account: with an issuer account, if needed. - nt_ACCOUNTS, // Accounts that connect from this source/currency. - nt_BOOKS, // Order books that connect to this currency. - nt_XRP_BOOK, // The order book from this currency to XRP. - nt_DEST_BOOK, // The order book to the destination currency/issuer. + nt_SOURCE, // The source account: with an issuer account, if needed. + nt_ACCOUNTS, // Accounts that connect from this source/currency. + nt_BOOKS, // Order books that connect to this currency. + nt_XRP_BOOK, // The order book from this currency to XRP. + nt_DEST_BOOK, // The order book to the destination currency/issuer. nt_DESTINATION // The destination account only. }; @@ -116,9 +112,7 @@ private: // Add all paths of one type to mCompletePaths. STPathSet& - addPathsForType( - PathType const& type, - std::function const& continueCallback); + addPathsForType(PathType const& type, std::function const& continueCallback); bool issueMatchesOrigin(Issue const&); @@ -164,10 +158,7 @@ private: // Is the "no ripple" flag set from one account to another? bool - isNoRipple( - AccountID const& fromAccount, - AccountID const& toAccount, - Currency const& currency); + isNoRipple(AccountID const& fromAccount, AccountID const& toAccount, Currency const& currency); void rankPaths( diff --git a/src/xrpld/app/paths/RippleCalc.cpp b/src/xrpld/app/paths/RippleCalc.cpp index 2b48a6ba5c..0667e1971c 100644 --- a/src/xrpld/app/paths/RippleCalc.cpp +++ b/src/xrpld/app/paths/RippleCalc.cpp @@ -44,22 +44,18 @@ RippleCalc::rippleCalculate( auto j = l.journal("Flow"); { - bool const defaultPaths = - !pInputs ? true : pInputs->defaultPathsAllowed; + bool const defaultPaths = !pInputs ? true : pInputs->defaultPathsAllowed; - bool const partialPayment = - !pInputs ? false : pInputs->partialPaymentAllowed; + bool const partialPayment = !pInputs ? false : pInputs->partialPaymentAllowed; auto const limitQuality = [&]() -> std::optional { - if (pInputs && pInputs->limitQuality && - saMaxAmountReq > beast::zero) + if (pInputs && pInputs->limitQuality && saMaxAmountReq > beast::zero) return Quality{Amounts(saMaxAmountReq, saDstAmountReq)}; return std::nullopt; }(); auto const sendMax = [&]() -> std::optional { - if (saMaxAmountReq >= beast::zero || - saMaxAmountReq.getCurrency() != saDstAmountReq.getCurrency() || + if (saMaxAmountReq >= beast::zero || saMaxAmountReq.getCurrency() != saDstAmountReq.getCurrency() || saMaxAmountReq.getIssuer() != uSrcAccountID) { return saMaxAmountReq; @@ -97,10 +93,8 @@ RippleCalc::rippleCalculate( } j.debug() << "RippleCalc Result> " - << " actualIn: " << flowOut.actualAmountIn - << ", actualOut: " << flowOut.actualAmountOut - << ", result: " << flowOut.result() - << ", dstAmtReq: " << saDstAmountReq + << " actualIn: " << flowOut.actualAmountIn << ", actualOut: " << flowOut.actualAmountOut + << ", result: " << flowOut.result() << ", dstAmtReq: " << saDstAmountReq << ", sendMax: " << saMaxAmountReq; flowSB.apply(view); diff --git a/src/xrpld/app/paths/RippleLineCache.cpp b/src/xrpld/app/paths/RippleLineCache.cpp index ece4c4149a..aaef368cff 100644 --- a/src/xrpld/app/paths/RippleLineCache.cpp +++ b/src/xrpld/app/paths/RippleLineCache.cpp @@ -3,9 +3,7 @@ namespace xrpl { -RippleLineCache::RippleLineCache( - std::shared_ptr const& ledger, - beast::Journal j) +RippleLineCache::RippleLineCache(std::shared_ptr const& ledger, beast::Journal j) : ledger_(ledger), journal_(j) { JLOG(journal_.debug()) << "created for ledger " << ledger_->header().seq; @@ -13,23 +11,17 @@ RippleLineCache::RippleLineCache( RippleLineCache::~RippleLineCache() { - JLOG(journal_.debug()) << "destroyed for ledger " << ledger_->header().seq - << " with " << lines_.size() << " accounts and " - << totalLineCount_ << " distinct trust lines."; + JLOG(journal_.debug()) << "destroyed for ledger " << ledger_->header().seq << " with " << lines_.size() + << " accounts and " << totalLineCount_ << " distinct trust lines."; } std::shared_ptr> -RippleLineCache::getRippleLines( - AccountID const& accountID, - LineDirection direction) +RippleLineCache::getRippleLines(AccountID const& accountID, LineDirection direction) { auto const hash = hasher_(accountID); AccountKey key(accountID, direction, hash); AccountKey otherkey( - accountID, - direction == LineDirection::outgoing ? LineDirection::incoming - : LineDirection::outgoing, - hash); + accountID, direction == LineDirection::outgoing ? LineDirection::incoming : LineDirection::outgoing, hash); std::lock_guard sl(mLock); @@ -40,18 +32,13 @@ RippleLineCache::getRippleLines( // number of trust line objects held in memory. Ensure that there is // only a single set of trustlines in the cache per account. auto const size = otheriter->second ? otheriter->second->size() : 0; - JLOG(journal_.info()) - << "Request for " - << (direction == LineDirection::outgoing ? "outgoing" - : "incoming") - << " trust lines for account " << accountID << " found " << size - << (direction == LineDirection::outgoing ? " incoming" - : " outgoing") - << " trust lines. " - << (direction == LineDirection::outgoing - ? "Deleting the subset of incoming" - : "Returning the superset of outgoing") - << " trust lines. "; + JLOG(journal_.info()) << "Request for " << (direction == LineDirection::outgoing ? "outgoing" : "incoming") + << " trust lines for account " << accountID << " found " << size + << (direction == LineDirection::outgoing ? " incoming" : " outgoing") + << " trust lines. " + << (direction == LineDirection::outgoing ? "Deleting the subset of incoming" + : "Returning the superset of outgoing") + << " trust lines. "; if (direction == LineDirection::outgoing) { // This request is for the outgoing set, but there is already a @@ -59,9 +46,7 @@ RippleLineCache::getRippleLines( // to be replaced by the full set. The full set will be built // below, and will be returned, if needed, on subsequent calls // for either value of outgoing. - XRPL_ASSERT( - size <= totalLineCount_, - "xrpl::RippleLineCache::getRippleLines : maximum lines"); + XRPL_ASSERT(size <= totalLineCount_, "xrpl::RippleLineCache::getRippleLines : maximum lines"); totalLineCount_ -= size; lines_.erase(otheriter); } @@ -81,32 +66,22 @@ RippleLineCache::getRippleLines( if (inserted) { - XRPL_ASSERT( - it->second == nullptr, - "xrpl::RippleLineCache::getRippleLines : null lines"); - auto lines = - PathFindTrustLine::getItems(accountID, *ledger_, direction); + XRPL_ASSERT(it->second == nullptr, "xrpl::RippleLineCache::getRippleLines : null lines"); + auto lines = PathFindTrustLine::getItems(accountID, *ledger_, direction); if (lines.size()) { - it->second = std::make_shared>( - std::move(lines)); + it->second = std::make_shared>(std::move(lines)); totalLineCount_ += it->second->size(); } } XRPL_ASSERT( - !it->second || (it->second->size() > 0), - "xrpl::RippleLineCache::getRippleLines : null or nonempty lines"); + !it->second || (it->second->size() > 0), "xrpl::RippleLineCache::getRippleLines : null or nonempty lines"); auto const size = it->second ? it->second->size() : 0; - JLOG(journal_.trace()) << "getRippleLines for ledger " - << ledger_->header().seq << " found " << size - << (key.direction_ == LineDirection::outgoing - ? " outgoing" - : " incoming") - << " lines for " << (inserted ? "new " : "existing ") - << accountID << " out of a total of " - << lines_.size() << " accounts and " - << totalLineCount_ << " trust lines"; + JLOG(journal_.trace()) << "getRippleLines for ledger " << ledger_->header().seq << " found " << size + << (key.direction_ == LineDirection::outgoing ? " outgoing" : " incoming") << " lines for " + << (inserted ? "new " : "existing ") << accountID << " out of a total of " << lines_.size() + << " accounts and " << totalLineCount_ << " trust lines"; return it->second; } diff --git a/src/xrpld/app/paths/RippleLineCache.h b/src/xrpld/app/paths/RippleLineCache.h index c2763ca2b4..8307fb8b4b 100644 --- a/src/xrpld/app/paths/RippleLineCache.h +++ b/src/xrpld/app/paths/RippleLineCache.h @@ -17,9 +17,7 @@ namespace xrpl { class RippleLineCache final : public CountedObject { public: - explicit RippleLineCache( - std::shared_ptr const& l, - beast::Journal j); + explicit RippleLineCache(std::shared_ptr const& l, beast::Journal j); ~RippleLineCache(); std::shared_ptr const& @@ -57,10 +55,7 @@ private: LineDirection direction_; std::size_t hash_value_; - AccountKey( - AccountID const& account, - LineDirection direction, - std::size_t hash) + AccountKey(AccountID const& account, LineDirection direction, std::size_t hash) : account_(account), direction_(direction), hash_value_(hash) { } @@ -73,8 +68,7 @@ private: bool operator==(AccountKey const& lhs) const { - return hash_value_ == lhs.hash_value_ && account_ == lhs.account_ && - direction_ == lhs.direction_; + return hash_value_ == lhs.hash_value_ && account_ == lhs.account_ && direction_ == lhs.direction_; } std::size_t @@ -100,11 +94,7 @@ private: // most accounts are not going to have any entries (estimated over 90%), so // vectors will not need to be created for them. This should lead to far // less memory usage overall. - hash_map< - AccountKey, - std::shared_ptr>, - AccountKey::Hash> - lines_; + hash_map>, AccountKey::Hash> lines_; std::size_t totalLineCount_ = 0; }; diff --git a/src/xrpld/app/paths/TrustLine.cpp b/src/xrpld/app/paths/TrustLine.cpp index b6ce9d74b0..f34dcbdf81 100644 --- a/src/xrpld/app/paths/TrustLine.cpp +++ b/src/xrpld/app/paths/TrustLine.cpp @@ -6,9 +6,7 @@ namespace xrpl { -TrustLineBase::TrustLineBase( - std::shared_ptr const& sle, - AccountID const& viewAccount) +TrustLineBase::TrustLineBase(std::shared_ptr const& sle, AccountID const& viewAccount) : key_(sle->key()) , mLowLimit(sle->getFieldAmount(sfLowLimit)) , mHighLimit(sle->getFieldAmount(sfHighLimit)) @@ -30,9 +28,7 @@ TrustLineBase::getJson(int) } std::optional -PathFindTrustLine::makeItem( - AccountID const& accountID, - std::shared_ptr const& sle) +PathFindTrustLine::makeItem(AccountID const& accountID, std::shared_ptr const& sle) { if (!sle || sle->getType() != ltRIPPLE_STATE) return {}; @@ -42,22 +38,14 @@ PathFindTrustLine::makeItem( namespace detail { template std::vector -getTrustLineItems( - AccountID const& accountID, - ReadView const& view, - LineDirection direction = LineDirection::outgoing) +getTrustLineItems(AccountID const& accountID, ReadView const& view, LineDirection direction = LineDirection::outgoing) { std::vector items; - forEachItem( - view, - accountID, - [&items, &accountID, &direction]( - std::shared_ptr const& sleCur) { - auto ret = T::makeItem(accountID, sleCur); - if (ret && - (direction == LineDirection::outgoing || !ret->getNoRipple())) - items.push_back(std::move(*ret)); - }); + forEachItem(view, accountID, [&items, &accountID, &direction](std::shared_ptr const& sleCur) { + auto ret = T::makeItem(accountID, sleCur); + if (ret && (direction == LineDirection::outgoing || !ret->getNoRipple())) + items.push_back(std::move(*ret)); + }); // This list may be around for a while, so free up any unneeded // capacity items.shrink_to_fit(); @@ -67,18 +55,12 @@ getTrustLineItems( } // namespace detail std::vector -PathFindTrustLine::getItems( - AccountID const& accountID, - ReadView const& view, - LineDirection direction) +PathFindTrustLine::getItems(AccountID const& accountID, ReadView const& view, LineDirection direction) { - return detail::getTrustLineItems( - accountID, view, direction); + return detail::getTrustLineItems(accountID, view, direction); } -RPCTrustLine::RPCTrustLine( - std::shared_ptr const& sle, - AccountID const& viewAccount) +RPCTrustLine::RPCTrustLine(std::shared_ptr const& sle, AccountID const& viewAccount) : TrustLineBase(sle, viewAccount) , lowQualityIn_(sle->getFieldU32(sfLowQualityIn)) , lowQualityOut_(sle->getFieldU32(sfLowQualityOut)) @@ -88,9 +70,7 @@ RPCTrustLine::RPCTrustLine( } std::optional -RPCTrustLine::makeItem( - AccountID const& accountID, - std::shared_ptr const& sle) +RPCTrustLine::makeItem(AccountID const& accountID, std::shared_ptr const& sle) { if (!sle || sle->getType() != ltRIPPLE_STATE) return {}; diff --git a/src/xrpld/app/paths/TrustLine.h b/src/xrpld/app/paths/TrustLine.h index a0a58c2bde..45cc797cb4 100644 --- a/src/xrpld/app/paths/TrustLine.h +++ b/src/xrpld/app/paths/TrustLine.h @@ -36,9 +36,7 @@ class TrustLineBase protected: // This class should not be instantiated directly. Use one of the derived // classes. - TrustLineBase( - std::shared_ptr const& sle, - AccountID const& viewAccount); + TrustLineBase(std::shared_ptr const& sle, AccountID const& viewAccount); ~TrustLineBase() = default; TrustLineBase(TrustLineBase const&) = default; @@ -96,15 +94,13 @@ public: LineDirection getDirection() const { - return getNoRipple() ? LineDirection::incoming - : LineDirection::outgoing; + return getNoRipple() ? LineDirection::incoming : LineDirection::outgoing; } LineDirection getDirectionPeer() const { - return getNoRipplePeer() ? LineDirection::incoming - : LineDirection::outgoing; + return getNoRipplePeer() ? LineDirection::incoming : LineDirection::outgoing; } /** Have we set the freeze flag on our peer */ @@ -170,8 +166,7 @@ protected: }; // This wrapper is used for the path finder -class PathFindTrustLine final : public TrustLineBase, - public CountedObject +class PathFindTrustLine final : public TrustLineBase, public CountedObject { using TrustLineBase::TrustLineBase; @@ -182,25 +177,19 @@ public: makeItem(AccountID const& accountID, std::shared_ptr const& sle); static std::vector - getItems( - AccountID const& accountID, - ReadView const& view, - LineDirection direction); + getItems(AccountID const& accountID, ReadView const& view, LineDirection direction); }; // This wrapper is used for the `AccountLines` command and includes the quality // in and quality out values. -class RPCTrustLine final : public TrustLineBase, - public CountedObject +class RPCTrustLine final : public TrustLineBase, public CountedObject { using TrustLineBase::TrustLineBase; public: RPCTrustLine() = delete; - RPCTrustLine( - std::shared_ptr const& sle, - AccountID const& viewAccount); + RPCTrustLine(std::shared_ptr const& sle, AccountID const& viewAccount); Rate const& getQualityIn() const diff --git a/src/xrpld/app/paths/detail/AMMLiquidity.cpp b/src/xrpld/app/paths/detail/AMMLiquidity.cpp index 2042467923..ebbb51ce25 100644 --- a/src/xrpld/app/paths/detail/AMMLiquidity.cpp +++ b/src/xrpld/app/paths/detail/AMMLiquidity.cpp @@ -37,15 +37,12 @@ AMMLiquidity::fetchBalances(ReadView const& view) const template TAmounts -AMMLiquidity::generateFibSeqOffer( - TAmounts const& balances) const +AMMLiquidity::generateFibSeqOffer(TAmounts const& balances) const { TAmounts cur{}; - cur.in = toAmount( - getIssue(balances.in), - InitialFibSeqPct * initialBalances_.in, - Number::rounding_mode::upward); + cur.in = + toAmount(getIssue(balances.in), InitialFibSeqPct * initialBalances_.in, Number::rounding_mode::upward); cur.out = swapAssetIn(initialBalances_, cur.in, tradingFee_); if (ammContext_.curIters() == 0) @@ -58,18 +55,13 @@ AMMLiquidity::generateFibSeqOffer( 196418, 317811, 514229, 832040, 1346269}; // clang-format on - XRPL_ASSERT( - !ammContext_.maxItersReached(), - "xrpl::AMMLiquidity::generateFibSeqOffer : maximum iterations"); + XRPL_ASSERT(!ammContext_.maxItersReached(), "xrpl::AMMLiquidity::generateFibSeqOffer : maximum iterations"); cur.out = toAmount( - getIssue(balances.out), - cur.out * fib[ammContext_.curIters() - 1], - Number::rounding_mode::downward); + getIssue(balances.out), cur.out * fib[ammContext_.curIters() - 1], Number::rounding_mode::downward); // swapAssetOut() returns negative in this case if (cur.out >= balances.out) - Throw( - "AMMLiquidity: generateFibSeqOffer exceeds the balance"); + Throw("AMMLiquidity: generateFibSeqOffer exceeds the balance"); cur.in = swapAssetOut(balances, cur.out, tradingFee_); @@ -100,16 +92,13 @@ maxOut(T const& out, Issue const& iss) template std::optional> -AMMLiquidity::maxOffer( - TAmounts const& balances, - Rules const& rules) const +AMMLiquidity::maxOffer(TAmounts const& balances, Rules const& rules) const { if (!rules.enabled(fixAMMOverflowOffer)) { return AMMOffer( *this, - {maxAmount(), - swapAssetIn(balances, maxAmount(), tradingFee_)}, + {maxAmount(), swapAssetIn(balances, maxAmount(), tradingFee_)}, balances, Quality{balances}); } @@ -118,19 +107,13 @@ AMMLiquidity::maxOffer( auto const out = maxOut(balances.out, issueOut()); if (out <= TOut{0} || out >= balances.out) return std::nullopt; - return AMMOffer( - *this, - {swapAssetOut(balances, out, tradingFee_), out}, - balances, - Quality{balances}); + return AMMOffer(*this, {swapAssetOut(balances, out, tradingFee_), out}, balances, Quality{balances}); } } template std::optional> -AMMLiquidity::getOffer( - ReadView const& view, - std::optional const& clobQuality) const +AMMLiquidity::getOffer(ReadView const& view, std::optional const& clobQuality) const { // Can't generate more offers if multi-path. if (ammContext_.maxItersReached()) @@ -145,10 +128,8 @@ AMMLiquidity::getOffer( return std::nullopt; } - JLOG(j_.trace()) << "AMMLiquidity::getOffer balances " - << to_string(initialBalances_.in) << " " - << to_string(initialBalances_.out) << " new balances " - << to_string(balances.in) << " " + JLOG(j_.trace()) << "AMMLiquidity::getOffer balances " << to_string(initialBalances_.in) << " " + << to_string(initialBalances_.out) << " new balances " << to_string(balances.in) << " " << to_string(balances.out); // Can't generate AMM with a better quality than CLOB's @@ -159,9 +140,8 @@ AMMLiquidity::getOffer( // to the requested clobQuality but not exactly and potentially SPQ may keep // on approaching clobQuality for many iterations. Checking for the quality // threshold prevents this scenario. - if (auto const spotPriceQ = Quality{balances}; clobQuality && - (spotPriceQ <= clobQuality || - withinRelativeDistance(spotPriceQ, *clobQuality, Number(1, -7)))) + if (auto const spotPriceQ = Quality{balances}; + clobQuality && (spotPriceQ <= clobQuality || withinRelativeDistance(spotPriceQ, *clobQuality, Number(1, -7)))) { JLOG(j_.trace()) << "AMMLiquidity::getOffer, higher clob quality"; return std::nullopt; @@ -175,8 +155,7 @@ AMMLiquidity::getOffer( auto const amounts = generateFibSeqOffer(balances); if (clobQuality && Quality{amounts} < clobQuality) return std::nullopt; - return AMMOffer( - *this, amounts, balances, Quality{amounts}); + return AMMOffer(*this, amounts, balances, Quality{amounts}); } else if (!clobQuality) { @@ -187,18 +166,14 @@ AMMLiquidity::getOffer( // nullopt if the pool is small. return maxOffer(balances, view.rules()); } - else if ( - auto const amounts = changeSpotPriceQuality( - balances, *clobQuality, tradingFee_, view.rules(), j_)) + else if (auto const amounts = changeSpotPriceQuality(balances, *clobQuality, tradingFee_, view.rules(), j_)) { - return AMMOffer( - *this, *amounts, balances, Quality{*amounts}); + return AMMOffer(*this, *amounts, balances, Quality{*amounts}); } else if (view.rules().enabled(fixAMMv1_2)) { if (auto const maxAMMOffer = maxOffer(balances, view.rules()); - maxAMMOffer && - Quality{maxAMMOffer->amount()} > *clobQuality) + maxAMMOffer && Quality{maxAMMOffer->amount()} > *clobQuality) return maxAMMOffer; } } @@ -219,22 +194,16 @@ AMMLiquidity::getOffer( if (offer) { - if (offer->amount().in > beast::zero && - offer->amount().out > beast::zero) + if (offer->amount().in > beast::zero && offer->amount().out > beast::zero) { - JLOG(j_.trace()) - << "AMMLiquidity::getOffer, created " - << to_string(offer->amount().in) << "/" << issueIn_ << " " - << to_string(offer->amount().out) << "/" << issueOut_; + JLOG(j_.trace()) << "AMMLiquidity::getOffer, created " << to_string(offer->amount().in) << "/" << issueIn_ + << " " << to_string(offer->amount().out) << "/" << issueOut_; return offer; } - JLOG(j_.debug()) << "AMMLiquidity::getOffer, no valid offer " - << ammContext_.multiPath() << " " - << ammContext_.curIters() << " " - << (clobQuality ? clobQuality->rate() : STAmount{}) - << " " << to_string(balances.in) << " " - << to_string(balances.out); + JLOG(j_.debug()) << "AMMLiquidity::getOffer, no valid offer " << ammContext_.multiPath() << " " + << ammContext_.curIters() << " " << (clobQuality ? clobQuality->rate() : STAmount{}) << " " + << to_string(balances.in) << " " << to_string(balances.out); } return std::nullopt; diff --git a/src/xrpld/app/paths/detail/AMMOffer.cpp b/src/xrpld/app/paths/detail/AMMOffer.cpp index 1152b673da..dd6b021689 100644 --- a/src/xrpld/app/paths/detail/AMMOffer.cpp +++ b/src/xrpld/app/paths/detail/AMMOffer.cpp @@ -11,11 +11,7 @@ AMMOffer::AMMOffer( TAmounts const& amounts, TAmounts const& balances, Quality const& quality) - : ammLiquidity_(ammLiquidity) - , amounts_(amounts) - , balances_(balances) - , quality_(quality) - , consumed_(false) + : ammLiquidity_(ammLiquidity), amounts_(amounts), balances_(balances), quality_(quality), consumed_(false) { } @@ -42,9 +38,7 @@ AMMOffer::amount() const template void -AMMOffer::consume( - ApplyView& view, - TAmounts const& consumed) +AMMOffer::consume(ApplyView& view, TAmounts const& consumed) { // Consumed offer must be less or equal to the original if (consumed.in > amounts_.in || consumed.out > amounts_.out) @@ -60,10 +54,7 @@ AMMOffer::consume( template TAmounts -AMMOffer::limitOut( - TAmounts const& offerAmount, - TOut const& limit, - bool roundUp) const +AMMOffer::limitOut(TAmounts const& offerAmount, TOut const& limit, bool roundUp) const { // Change the offer size proportionally to the original offer quality // to keep the strands quality order unchanged. The taker pays slightly @@ -85,16 +76,12 @@ AMMOffer::limitOut( template TAmounts -AMMOffer::limitIn( - TAmounts const& offerAmount, - TIn const& limit, - bool roundUp) const +AMMOffer::limitIn(TAmounts const& offerAmount, TIn const& limit, bool roundUp) const { // See the comments above in limitOut(). if (ammLiquidity_.multiPath()) { - if (auto const& rules = getCurrentTransactionRules(); - rules && rules->enabled(fixReducedOffersV2)) + if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixReducedOffersV2)) return quality().ceil_in_strict(offerAmount, limit, roundUp); return quality().ceil_in(offerAmount, limit); @@ -108,45 +95,33 @@ AMMOffer::getQualityFunc() const { if (ammLiquidity_.multiPath()) return QualityFunction{quality(), QualityFunction::CLOBLikeTag{}}; - return QualityFunction{ - balances_, ammLiquidity_.tradingFee(), QualityFunction::AMMTag{}}; + return QualityFunction{balances_, ammLiquidity_.tradingFee(), QualityFunction::AMMTag{}}; } template bool -AMMOffer::checkInvariant( - TAmounts const& consumed, - beast::Journal j) const +AMMOffer::checkInvariant(TAmounts const& consumed, beast::Journal j) const { if (consumed.in > amounts_.in || consumed.out > amounts_.out) { - JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed " - << to_string(consumed.in) << " " - << to_string(consumed.out) << " amounts " - << to_string(amounts_.in) << " " + JLOG(j.error()) << "AMMOffer::checkInvariant failed: consumed " << to_string(consumed.in) << " " + << to_string(consumed.out) << " amounts " << to_string(amounts_.in) << " " << to_string(amounts_.out); return false; } Number const product = balances_.in * balances_.out; - auto const newBalances = TAmounts{ - balances_.in + consumed.in, balances_.out - consumed.out}; + auto const newBalances = TAmounts{balances_.in + consumed.in, balances_.out - consumed.out}; Number const newProduct = newBalances.in * newBalances.out; - if (newProduct >= product || - withinRelativeDistance(product, newProduct, Number{1, -7})) + if (newProduct >= product || withinRelativeDistance(product, newProduct, Number{1, -7})) return true; - JLOG(j.error()) << "AMMOffer::checkInvariant failed: balances " - << to_string(balances_.in) << " " - << to_string(balances_.out) << " new balances " - << to_string(newBalances.in) << " " - << to_string(newBalances.out) << " product/newProduct " - << product << " " << newProduct << " diff " - << (product != Number{0} - ? to_string((product - newProduct) / product) - : "undefined"); + JLOG(j.error()) << "AMMOffer::checkInvariant failed: balances " << to_string(balances_.in) << " " + << to_string(balances_.out) << " new balances " << to_string(newBalances.in) << " " + << to_string(newBalances.out) << " product/newProduct " << product << " " << newProduct << " diff " + << (product != Number{0} ? to_string((product - newProduct) / product) : "undefined"); return false; } diff --git a/src/xrpld/app/paths/detail/AmountSpec.h b/src/xrpld/app/paths/detail/AmountSpec.h index 5249bd30e0..3ebe5fde91 100644 --- a/src/xrpld/app/paths/detail/AmountSpec.h +++ b/src/xrpld/app/paths/detail/AmountSpec.h @@ -106,8 +106,7 @@ template <> inline IOUAmount& get(EitherAmount& amt) { - XRPL_ASSERT( - !amt.native, "xrpl::get(EitherAmount&) : is not XRP"); + XRPL_ASSERT(!amt.native, "xrpl::get(EitherAmount&) : is not XRP"); return amt.iou; } @@ -131,8 +130,7 @@ template <> inline IOUAmount const& get(EitherAmount const& amt) { - XRPL_ASSERT( - !amt.native, "xrpl::get(EitherAmount const&) : is not XRP"); + XRPL_ASSERT(!amt.native, "xrpl::get(EitherAmount const&) : is not XRP"); return amt.iou; } @@ -140,8 +138,7 @@ template <> inline XRPAmount const& get(EitherAmount const& amt) { - XRPL_ASSERT( - amt.native, "xrpl::get(EitherAmount const&) : is XRP"); + XRPL_ASSERT(amt.native, "xrpl::get(EitherAmount const&) : is XRP"); return amt.xrp; } @@ -152,8 +149,7 @@ toAmountSpec(STAmount const& amt) amt.mantissa() < std::numeric_limits::max(), "xrpl::toAmountSpec(STAmount const&) : maximum mantissa"); bool const isNeg = amt.negative(); - std::int64_t const sMant = - isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); + std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); AmountSpec result; result.native = isXRP(amt); diff --git a/src/xrpld/app/paths/detail/BookStep.cpp b/src/xrpld/app/paths/detail/BookStep.cpp index baef42a492..b9c8aa4e67 100644 --- a/src/xrpld/app/paths/detail/BookStep.cpp +++ b/src/xrpld/app/paths/detail/BookStep.cpp @@ -109,8 +109,7 @@ public: DebtDirection debtDirection(ReadView const& sb, StrandDirection dir) const override { - return ownerPaysTransferFee_ ? DebtDirection::issues - : DebtDirection::redeems; + return ownerPaysTransferFee_ ? DebtDirection::issues : DebtDirection::redeems; } std::optional @@ -120,8 +119,7 @@ public: } std::pair, DebtDirection> - qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) - const override; + qualityUpperBound(ReadView const& v, DebtDirection prevStepDir) const override; std::pair, DebtDirection> getQualityFunc(ReadView const& v, DebtDirection prevStepDir) const override; @@ -130,22 +128,13 @@ public: offersUsed() const override; std::pair - revImp( - PaymentSandbox& sb, - ApplyView& afView, - boost::container::flat_set& ofrsToRm, - TOut const& out); + revImp(PaymentSandbox& sb, ApplyView& afView, boost::container::flat_set& ofrsToRm, TOut const& out); std::pair - fwdImp( - PaymentSandbox& sb, - ApplyView& afView, - boost::container::flat_set& ofrsToRm, - TIn const& in); + fwdImp(PaymentSandbox& sb, ApplyView& afView, boost::container::flat_set& ofrsToRm, TIn const& in); std::pair - validFwd(PaymentSandbox& sb, ApplyView& afView, EitherAmount const& in) - override; + validFwd(PaymentSandbox& sb, ApplyView& afView, EitherAmount const& in) override; // Check for errors frozen constraints. TER @@ -163,9 +152,7 @@ protected: { std::ostringstream ostr; ostr << name << ": " - << "\ninIss: " << book_.in.account - << "\noutIss: " << book_.out.account - << "\ninCur: " << book_.in.currency + << "\ninIss: " << book_.in.account << "\noutIss: " << book_.out.account << "\ninCur: " << book_.in.currency << "\noutCur: " << book_.out.currency; return ostr.str(); } @@ -193,11 +180,7 @@ private: // Return the unfunded and bad offers and the number of offers consumed. template std::pair, std::uint32_t> - forEachOffer( - PaymentSandbox& sb, - ApplyView& afView, - DebtDirection prevStepDebtDir, - Callback& callback) const; + forEachOffer(PaymentSandbox& sb, ApplyView& afView, DebtDirection prevStepDebtDir, Callback& callback) const; // Offer is either TOffer or AMMOffer template